Merge from Chromium at DEPS revision 260458

This commit was generated by merge_to_master.py.

Change-Id: I140fa91b7f09c8efba4424e99ccb87b94a11d022
diff --git a/.DEPS.git b/.DEPS.git
index 41f2f99..9ea2237 100644
--- a/.DEPS.git
+++ b/.DEPS.git
@@ -11,9 +11,9 @@
     'git_url':
          'https://chromium.googlesource.com',
     'webkit_rev':
-         '@48c52b58cc2c891749ba24007d0c21b073df0264',
+         '@5e620ca2839c6485de31d0df09785ded8976e586',
     'angle_revision':
-         '28b4790916c70dff3cee85ba351ab46299a1af97'
+         '740a2f8daa9cc45c53ecf7333c3ae5aa64c821f8'
 }
 
 deps = {
@@ -32,7 +32,7 @@
     'src/media/cdm/ppapi/api':
         Var('git_url') + '/chromium/cdm.git@01f5723f05af12535ef5fa052a26fc90848d16be',
     'src/native_client':
-        Var('git_url') + '/native_client/src/native_client.git@e09b4868c94ea626d2ee5b534c7a667558a7e504',
+        Var('git_url') + '/native_client/src/native_client.git@8d8fb11b56552cc0811f4cd568c98dbc23008f09',
     'src/sdch/open-vcdiff':
         Var('git_url') + '/external/open-vcdiff.git@438f2a5be6d809bc21611a94cd37bfc8c28ceb33',
     'src/testing/gmock':
@@ -50,7 +50,7 @@
     'src/third_party/bidichecker':
         Var('git_url') + '/external/bidichecker/lib.git@97f2aa645b74c28c57eca56992235c79850fa9e0',
     'src/third_party/brotli/src':
-        Var('git_url') + '/external/font-compression-reference.git@7f848593bd2ec83f4537b6d494a5bf55b9bd4456',
+        Var('git_url') + '/external/font-compression-reference.git@0829e37293abc2523a1d2b0f4d68ff7b5fcd8e01',
     'src/third_party/cacheinvalidation/src':
         Var('git_url') + '/external/google-cache-invalidation-api/src.git@6cd2fc3c3f3b3c95870be4696e642d4c3f051b59',
     'src/third_party/clang_format/script':
@@ -66,7 +66,7 @@
     'src/third_party/hunspell_dictionaries':
         Var('git_url') + '/chromium/deps/hunspell_dictionaries.git@4560bdd463a3500e2334e85c8a0e9e5d5d6774e7',
     'src/third_party/icu':
-        Var('git_url') + '/chromium/deps/icu46.git@7a1ec88f69e25b3efcf76196d07f7815255db025',
+        Var('git_url') + '/chromium/deps/icu46.git@bd5531d35256739a1321c2f4cab18a667640f3c8',
     'src/third_party/jsoncpp/source/include':
         Var('git_url') + '/external/jsoncpp/jsoncpp/include.git@b0dd48e02b6e6248328db78a65b5c601f150c349',
     'src/third_party/jsoncpp/source/src/lib_json':
@@ -82,9 +82,9 @@
     'src/third_party/libexif/sources':
         Var('git_url') + '/chromium/deps/libexif/sources.git@d815c325bab0d1871d4c7e70600ecdfdab07db9e',
     'src/third_party/libjingle/source/talk':
-        Var('git_url') + '/external/webrtc/trunk/talk.git@2613d7316fc4cf9a10e113a3352a0d993387a554',
+        Var('git_url') + '/external/webrtc/trunk/talk.git@fc1e785be93c8b9bcce13c29d35af2a1ca91e6af',
     'src/third_party/libjpeg_turbo':
-        Var('git_url') + '/chromium/deps/libjpeg_turbo.git@966a02fd0c4047a6badca966cd77f1496b690447',
+        Var('git_url') + '/chromium/deps/libjpeg_turbo.git@f7e5ddf60109893580bf01e8ff7587c23260b0bd',
     'src/third_party/libphonenumber/src/phonenumbers':
         Var('git_url') + '/external/libphonenumber/cpp/src/phonenumbers.git@8d8b5b3b2035197795d27573d4cf566b5d9ad689',
     'src/third_party/libphonenumber/src/resources':
@@ -94,11 +94,11 @@
     'src/third_party/libsrtp':
         Var('git_url') + '/chromium/deps/libsrtp.git@84122798bb16927b1e676bd4f938a6e48e5bf2fe',
     'src/third_party/libvpx':
-        Var('git_url') + '/chromium/deps/libvpx.git@adc66e2f7c95a249c86f2f54ce8306b8b3f2c14c',
+        Var('git_url') + '/chromium/deps/libvpx.git@2cb6e5586451498e72e2b58eac385f3fc1da3251',
     'src/third_party/libwebm/source':
         Var('git_url') + '/webm/libwebm.git@0f7815b036651e242ec8c2fcfb59fe54f69be1a8',
     'src/third_party/libyuv':
-        Var('git_url') + '/external/libyuv.git@efc5d9b930223c2b1fd71c7958bfa39d23dccf15',
+        Var('git_url') + '/external/libyuv.git@91dc3eddebc189c8bb19b4af1fadccda2b869729',
     'src/third_party/mesa/src':
         Var('git_url') + '/chromium/deps/mesa.git@3f79f50967bbf4fdaba7507a8d1526aa24eefd91',
     'src/third_party/openmax_dl':
@@ -106,13 +106,13 @@
     'src/third_party/openssl':
         Var('git_url') + '/chromium/deps/openssl.git@7cdf2c0cb89b1f90e0f332b6594e3ea155c48b5c',
     'src/third_party/opus/src':
-        Var('git_url') + '/chromium/deps/opus.git@dd52457296df1ef41bae8e28dc321d6798509172',
+        Var('git_url') + '/chromium/deps/opus.git@36fa2621472ebf5b859fd16bbdb749019c68cc69',
     'src/third_party/ots':
-        Var('git_url') + '/external/ots.git@eea48361b1ffcc1bded0ba25c8f747e634cd8e51',
+        Var('git_url') + '/external/ots.git@011a74db66c39c0d8cb6cb2fb6a62c38dd0e1fe0',
     'src/third_party/pyftpdlib/src':
         Var('git_url') + '/external/pyftpdlib.git@2be6d65e31c7ee6320d059f581f05ae8d89d7e45',
     'src/third_party/pywebsocket/src':
-        Var('git_url') + '/external/pywebsocket/src.git@e8de2ba77f55c48e291f70f389f647fafd12ec87',
+        Var('git_url') + '/external/pywebsocket/src.git@cb349e87ddb30ff8d1fa1a89be39cec901f4a29c',
     'src/third_party/safe_browsing/testing':
         Var('git_url') + '/external/google-safe-browsing/testing.git@9d7e8064f3ca2e45891470c9b5b1dce54af6a9d6',
     'src/third_party/scons-2.0.1':
@@ -120,11 +120,11 @@
     'src/third_party/sfntly/cpp/src':
         Var('git_url') + '/external/sfntly/cpp/src.git@8f090032dd4f8f8908f338cc73bb840b788377f2',
     'src/third_party/skia/gyp':
-        Var('git_url') + '/external/skia/gyp.git@b4627d588c9694f702259ff2b2fb28c76622b529',
+        Var('git_url') + '/external/skia/gyp.git@6401119e16e65c3d79295bb9bc0974cff493cec0',
     'src/third_party/skia/include':
-        Var('git_url') + '/external/skia/include.git@1a457fc9b3ed678499fbb2f84b49b982dd52f3d7',
+        Var('git_url') + '/external/skia/include.git@9037c629a3dedeea696dc5f1b0d84af3042bf058',
     'src/third_party/skia/src':
-        Var('git_url') + '/external/skia/src.git@4b918979684999218060ad465093cb4f274c99ef',
+        Var('git_url') + '/external/skia/src.git@cc58d293368028a1daefc1dda642dbcb83e81aba',
     'src/third_party/smhasher/src':
         Var('git_url') + '/external/smhasher.git@b52816cce35fbfdda7d56c533cf53d15201513e3',
     'src/third_party/snappy/src':
@@ -134,7 +134,7 @@
     'src/third_party/swig/Lib':
         Var('git_url') + '/chromium/deps/swig/Lib.git@f2a695d52e61e6a8d967731434f165ed400f0d69',
     'src/third_party/trace-viewer':
-        Var('git_url') + '/external/trace-viewer.git@add63d3e224be3fd9b467b03729ebbc9e62ebbef',
+        Var('git_url') + '/external/trace-viewer.git@9e9e8d0832f8428801af57a57723d176f5549385',
     'src/third_party/usrsctp/usrsctplib':
         Var('git_url') + '/external/usrsctplib.git@6b0af72aa691378aac94d6acda1ce759ed75ff00',
     'src/third_party/webdriver/pylib':
@@ -144,28 +144,28 @@
     'src/third_party/webpagereplay':
         Var('git_url') + '/external/web-page-replay.git@1cf80576c1c4beb6185af0ac70eb7379c5e8262b',
     'src/third_party/webrtc':
-        Var('git_url') + '/external/webrtc/trunk/webrtc.git@76cd2f7dec281c9842ebc5417eeea376fa54746c',
+        Var('git_url') + '/external/webrtc/trunk/webrtc.git@4910a7fdac98f28f0f37ad5b9d03ebd85ae55e14',
     'src/third_party/yasm/source/patched-yasm':
         Var('git_url') + '/chromium/deps/yasm/patched-yasm.git@c960eb11ccda80b10ed50be39df4f0663b371d1d',
     'src/tools/deps2git':
         Var('git_url') + '/chromium/tools/deps2git.git@5d3006d5bf9a3982b8549f8a7bd25ac40e038be0',
     'src/tools/grit':
-        Var('git_url') + '/external/grit-i18n.git@6138ad6c701588481ebf147546df9e96a311553e',
+        Var('git_url') + '/external/grit-i18n.git@94856f5fbe5d71b14a4d39e494b5882e930d8c21',
     'src/tools/gyp':
-        Var('git_url') + '/external/gyp.git@4f54696fd3e5945c6320da7312484b0cb192e4e1',
+        Var('git_url') + '/external/gyp.git@dde28829b59815fc4fbbb76ff1a7054e2c3db85f',
     'src/tools/page_cycler/acid3':
         Var('git_url') + '/chromium/deps/acid3.git@6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
     'src/tools/swarming_client':
         Var('git_url') + '/external/swarming.client.git@8472efa59518a6e28db6da249685d65f49ce8244',
     'src/v8':
-        Var('git_url') + '/external/v8.git@69f64b1a8bfa6f5418b7c1f71d4e0833f76e93ed',
+        Var('git_url') + '/external/v8.git@895f00d1d8c5a7a7209c36d690688e3552de3df4',
 }
 
 deps_os = {
     'android':
     {
         'src/third_party/android_tools':
-            Var('git_url') + '/android_tools.git@0582bdc17b4829beb522975441546a4eb99b11b5',
+            Var('git_url') + '/android_tools.git@ca35676f4f652fa97964c488313720f55efd4405',
         'src/third_party/aosp':
             Var('git_url') + '/chromium/deps/aosp.git@bbafe5155dff86bbba1e92b42a073ffcfcfbf28c',
         'src/third_party/apache-mime4j':
@@ -254,7 +254,7 @@
         'src/third_party/mesa/src':
             None,
         'src/third_party/nss':
-            Var('git_url') + '/chromium/deps/nss.git@ff99706f30463342ff042be4915365065d8024ff',
+            Var('git_url') + '/chromium/deps/nss.git@494b6787f175f59018d1018ad7fb51f94a549f95',
         'src/third_party/openmax_dl':
             None,
         'src/third_party/opus/src':
@@ -303,7 +303,7 @@
         'src/third_party/lighttpd':
             Var('git_url') + '/chromium/deps/lighttpd.git@9dfa55d15937a688a92cbf2b7a8621b0927d06eb',
         'src/third_party/nss':
-            Var('git_url') + '/chromium/deps/nss.git@ff99706f30463342ff042be4915365065d8024ff',
+            Var('git_url') + '/chromium/deps/nss.git@494b6787f175f59018d1018ad7fb51f94a549f95',
         'src/third_party/pdfsqueeze':
             Var('git_url') + '/external/pdfsqueeze.git@5936b871e6a087b7e50d4cbcb122378d8a07499f',
         'src/third_party/swig/mac':
@@ -316,9 +316,9 @@
         'src/third_party/chromite':
             Var('git_url') + '/chromiumos/chromite.git@473f7ab6baf1781618f379a7680b56048b5e0ec1',
         'src/third_party/cros_dbus_cplusplus/source':
-            Var('git_url') + '/chromiumos/third_party/dbus-cplusplus.git@e4120532bbf3ca9f743b0be1f539381a54d16867',
+            Var('git_url') + '/chromiumos/third_party/dbus-cplusplus.git@f78453e0ba9f3d1584e8873aa3c7437cec861ce0',
         'src/third_party/cros_system_api':
-            Var('git_url') + '/chromiumos/platform/system_api.git@26a32fcb2afed4a3ec12070388d752dd795dac8e',
+            Var('git_url') + '/chromiumos/platform/system_api.git@844a42e5f5c7a106807b09b6c2ac6b00b166c1cc',
         'src/third_party/fontconfig/src':
             Var('git_url') + '/external/fontconfig.git@f16c3118e25546c1b749f9823c51827a60aeb5c1',
         'src/third_party/freetype2/src':
@@ -361,7 +361,7 @@
         'src/third_party/nacl_sdk_binaries':
             Var('git_url') + '/chromium/deps/nacl_sdk_binaries.git@759dfca03bdc774da7ecbf974f6e2b84f43699a5',
         'src/third_party/nss':
-            Var('git_url') + '/chromium/deps/nss.git@ff99706f30463342ff042be4915365065d8024ff',
+            Var('git_url') + '/chromium/deps/nss.git@494b6787f175f59018d1018ad7fb51f94a549f95',
         'src/third_party/pefile':
             Var('git_url') + '/external/pefile.git@d0ca75794f69f1d09fd6d31d40ba2f1e9b3b7fb4',
         'src/third_party/perl':
@@ -460,7 +460,7 @@
          [
     'python',
     'src/tools/clang/scripts/update.py',
-    '--mac-only'
+    '--if-needed'
 ],
     'pattern':
          '.',
@@ -508,7 +508,7 @@
     'src/tools/gn/bin/win/gn.exe.sha1'
 ],
     'pattern':
-         'src/tools/gn/bin/win/gn.exe.sha1',
+         '.',
     'name':
          'gn_win'
 },
@@ -525,7 +525,7 @@
     'src/tools/gn/bin/mac/gn.sha1'
 ],
     'pattern':
-         'src/tools/gn/bin/mac/gn.sha1',
+         '.',
     'name':
          'gn_mac'
 },
@@ -542,7 +542,7 @@
     'src/tools/gn/bin/linux/gn.sha1'
 ],
     'pattern':
-         'src/tools/gn/bin/linux/gn.sha1',
+         '.',
     'name':
          'gn_linux'
 },
@@ -559,7 +559,7 @@
     'src/tools/gn/bin/linux/gn32.sha1'
 ],
     'pattern':
-         'src/tools/gn/bin/linux/gn32.sha1',
+         '.',
     'name':
          'gn_linux32'
 },
@@ -576,7 +576,7 @@
     'src/third_party/clang_format/bin/win/clang-format.exe.sha1'
 ],
     'pattern':
-         'src/third_party/clang_format/bin/win/clang-format.exe.sha1',
+         '.',
     'name':
          'clang_format_win'
 },
@@ -593,7 +593,7 @@
     'src/third_party/clang_format/bin/mac/clang-format.sha1'
 ],
     'pattern':
-         'src/third_party/clang_format/bin/mac/clang-format.sha1',
+         '.',
     'name':
          'clang_format_mac'
 },
@@ -610,7 +610,7 @@
     'src/third_party/clang_format/bin/linux/clang-format.sha1'
 ],
     'pattern':
-         'src/third_party/clang_format/bin/linux/clang-format.sha1',
+         '.',
     'name':
          'clang_format_linux'
 },
@@ -627,7 +627,7 @@
     'src/build/linux/bin/eu-strip.sha1'
 ],
     'pattern':
-         'src/build/linux/bin/eu-strip.sha1',
+         '.',
     'name':
          'eu-strip'
 },
diff --git a/AUTHORS b/AUTHORS
index 349f73a..a1e27b3 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -33,6 +33,7 @@
 Andrei Parvu <parvu@adobe.com>
 Andrew Brampton <me@bramp.net>
 Andrew Tulloch <andrew@tullo.ch>
+Anish Patankar <anish.p@samsung.com>
 Antonio Gomes <a1.gomes@sisa.samsung.com>
 Arthur Lussos <developer0420@gmail.com>
 Arun Mankuzhi <arun.m@samsung.com>
@@ -85,6 +86,7 @@
 Dongwoo Joshua Im <dw.im@samsung.com>
 Douglas F. Turner <doug.turner@gmail.com>
 Edward Crossman <tedoc2000@gmail.com>
+Eero Häkkinen <e.hakkinen@partner.samsung.com>
 Ehsan Akhgari <ehsan.akhgari@gmail.com>
 Elan Ruusamäe <elan.ruusamae@gmail.com>
 Eric Rescorla <ekr@rtfm.com>
@@ -313,6 +315,7 @@
 Soren Dreijer <dreijerbit@gmail.com>
 Stephen Searles <stephen.searles@gmail.com>
 Steven Pennington <spenn@engr.uvic.ca>
+Subrahmanya Praveen Munukutla <sataya.m@samsung.com>
 Suchit Agrawal <a.suchit@samsung.com>
 Sudarsana Babu Nagineni <sudarsana.nagineni@intel.com>
 Sudarshan Parthasarathy <sudarshan.p@samsung.com>
diff --git a/DEPS b/DEPS
index b8194d5..abd77c9 100644
--- a/DEPS
+++ b/DEPS
@@ -23,19 +23,19 @@
   "libcxxabi_revision": "197063",
   "webkit_trunk": "http://src.chromium.org/blink/trunk",
   "nacl_trunk": "http://src.chromium.org/native_client/trunk",
-  "webkit_revision": "169622",
+  "webkit_revision": "170423",
   "chromium_git": "https://chromium.googlesource.com",
   "chromiumos_git": "https://chromium.googlesource.com/chromiumos",
   "skia_git": "https://skia.googlesource.com",
   "swig_revision": "230490",
-  "nacl_revision": "12892",
+  "nacl_revision": "12952",
   # After changing nacl_revision, run 'glient sync' and check native_client/DEPS
   # to update other nacl_*_revision's.
   "nacl_tools_revision": "12760",  # native_client/DEPS: tools_rev
   "google_toolbox_for_mac_revision": "662",
   "libaddressinput_revision": "176",
   "libphonenumber_revision": "621",
-  "libvpx_revision": "257501",
+  "libvpx_revision": "259953",
   "lss_revision": "24",
 
   # These two FFmpeg variables must be updated together.  One is used for SVN
@@ -45,19 +45,19 @@
 
   "sfntly_revision": "228",
   "lighttpd_revision": "33737",
-  "skia_revision": "13854",
-  "skia_hash": "36048534886f9dd626e0e2bc112c8716c7be2ad8",
+  "skia_revision": "13966",
+  "skia_hash": "c94a028ff836f8f0af41ec33ceb1f4bc140841bf",
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and V8 without interference from each other.
   "v8_branch": "trunk",
-  "v8_revision": "20094",
+  "v8_revision": "20290",
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling WebRTC
   # and V8 without interference from each other.
-  "webrtc_revision": "5721",
+  "webrtc_revision": "5807",
   "jsoncpp_revision": "248",
-  "nss_revision": "257452",
+  "nss_revision": "259440",
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -69,7 +69,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  "angle_revision": "28b4790916c70dff3cee85ba351ab46299a1af97",
+  "angle_revision": "740a2f8daa9cc45c53ecf7333c3ae5aa64c821f8",
 }
 
 deps = {
@@ -89,7 +89,7 @@
     Var("chromium_git") + "/angle/angle.git@" + Var("angle_revision"),
 
   "src/third_party/trace-viewer":
-    (Var("googlecode_url") % "trace-viewer") + "/trunk@1203",
+    (Var("googlecode_url") % "trace-viewer") + "/trunk@1221",
 
   "src/third_party/WebKit":
     Var("webkit_trunk") + "@" + Var("webkit_revision"),
@@ -103,7 +103,7 @@
     "/external/w3c/csswg-test.git@8c415e3215a203fa3a22dbdd1799279fdf44c81e",
 
   "src/third_party/icu":
-    "/trunk/deps/third_party/icu46@258359",
+    "/trunk/deps/third_party/icu46@259309",
 
   "src/third_party/libexif/sources":
     "/trunk/deps/third_party/libexif/sources@146817",
@@ -134,10 +134,10 @@
     (Var("googlecode_url") % "snappy") + "/trunk@80",
 
   "src/tools/grit":
-    (Var("googlecode_url") % "grit-i18n") + "/trunk@156",
+    (Var("googlecode_url") % "grit-i18n") + "/trunk@157",
 
   "src/tools/gyp":
-    (Var("googlecode_url") % "gyp") + "/trunk@1879",
+    (Var("googlecode_url") % "gyp") + "/trunk@1880",
 
   "src/tools/swarming_client":
     Var("chromium_git") + "/external/swarming.client.git@" +
@@ -168,11 +168,11 @@
     (Var("googlecode_url") % "skia") + "/trunk/include@" + Var("skia_revision"),
 
   "src/third_party/ots":
-    (Var("googlecode_url") % "ots") + "/trunk@110",
+    (Var("googlecode_url") % "ots") + "/trunk@112",
 
   "src/third_party/brotli/src":
     Var("chromium_git") +
-    "/external/font-compression-reference.git@7f848593bd2ec83f4537b6d494a5bf55b9bd4456",
+    "/external/font-compression-reference.git@0829e37293abc2523a1d2b0f4d68ff7b5fcd8e01",
 
   "src/tools/page_cycler/acid3":
     "/trunk/deps/page_cycler/acid3@171600",
@@ -226,7 +226,7 @@
     "/trunk/deps/third_party/yasm/patched-yasm@167605",
 
   "src/third_party/libjpeg_turbo":
-    "/trunk/deps/third_party/libjpeg_turbo@251747",
+    "/trunk/deps/third_party/libjpeg_turbo@259851",
 
   "src/third_party/flac":
     "/trunk/deps/third_party/flac@222897",
@@ -253,7 +253,7 @@
         "/trunk/jsoncpp/src/lib_json@" + Var("jsoncpp_revision"),
 
   "src/third_party/libyuv":
-    (Var("googlecode_url") % "libyuv") + "/trunk@985",
+    (Var("googlecode_url") % "libyuv") + "/trunk@986",
 
   "src/third_party/smhasher/src":
     (Var("googlecode_url") % "smhasher") + "/trunk@151",
@@ -285,10 +285,10 @@
     (Var("googlecode_url") % "web-page-replay") + "/trunk@544",
 
   "src/third_party/pywebsocket/src":
-    (Var("googlecode_url") % "pywebsocket") + "/trunk/src@662",
+    (Var("googlecode_url") % "pywebsocket") + "/trunk/src@790",
 
   "src/third_party/opus/src":
-    "/trunk/deps/third_party/opus@237544",
+    "/trunk/deps/third_party/opus@256783",
 
   "src/media/cdm/ppapi/api":
     "/trunk/deps/cdm@249141",
@@ -480,12 +480,12 @@
     # Used on Linux only. CrOS already has a copy.
     "src/third_party/cros_dbus_cplusplus/source":
       Var("chromiumos_git") + "/third_party/dbus-cplusplus.git" +
-      "@e4120532bbf3ca9f743b0be1f539381a54d16867",
+      "@f78453e0ba9f3d1584e8873aa3c7437cec861ce0",
 
     # For Linux and Chromium OS.
     "src/third_party/cros_system_api":
       Var("chromiumos_git") + "/platform/system_api.git" +
-      "@26a32fcb2afed4a3ec12070388d752dd795dac8e",
+      "@844a42e5f5c7a106807b09b6c2ac6b00b166c1cc",
 
     # Note that this is different from Android's freetype repo.
     "src/third_party/freetype2/src":
@@ -517,7 +517,7 @@
   "android": {
     "src/third_party/android_tools":
       Var("chromium_git") + "/android_tools.git" +
-      "@0582bdc17b4829beb522975441546a4eb99b11b5",
+      "@ca35676f4f652fa97964c488313720f55efd4405",
 
     "src/third_party/aosp":
       "/trunk/deps/third_party/aosp@148330",
@@ -642,12 +642,10 @@
         "--arch=i386"],
   },
   {
-    # Pull clang on mac. If nothing changed, or on non-mac platforms, this takes
-    # zero seconds to run. If something changed, it downloads a prebuilt clang,
-    # which takes ~20s, but clang speeds up builds by more than 20s.
+    # Pull clang if on Mac or clang is requested via GYP_DEFINES.
     "name": "clang",
     "pattern": ".",
-    "action": ["python", "src/tools/clang/scripts/update.py", "--mac-only"],
+    "action": ["python", "src/tools/clang/scripts/update.py", "--if-needed"],
   },
   {
     # Update LASTCHANGE. This is also run by export_tarball.py in
@@ -669,7 +667,7 @@
   # Pull GN binaries. This needs to be before running GYP below.
   {
     "name": "gn_win",
-    "pattern": "src/tools/gn/bin/win/gn.exe.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=win32",
@@ -680,7 +678,7 @@
   },
   {
     "name": "gn_mac",
-    "pattern": "src/tools/gn/bin/mac/gn.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=darwin",
@@ -691,7 +689,7 @@
   },
   {
     "name": "gn_linux",
-    "pattern": "src/tools/gn/bin/linux/gn.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=linux*",
@@ -702,7 +700,7 @@
   },
   {
     "name": "gn_linux32",
-    "pattern": "src/tools/gn/bin/linux/gn32.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=linux*",
@@ -714,7 +712,7 @@
   # Pull clang-format binaries using checked-in hashes.
   {
     "name": "clang_format_win",
-    "pattern": "src/third_party/clang_format/bin/win/clang-format.exe.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=win32",
@@ -725,7 +723,7 @@
   },
   {
     "name": "clang_format_mac",
-    "pattern": "src/third_party/clang_format/bin/mac/clang-format.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=darwin",
@@ -736,7 +734,7 @@
   },
   {
     "name": "clang_format_linux",
-    "pattern": "src/third_party/clang_format/bin/linux/clang-format.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=linux*",
@@ -748,7 +746,7 @@
   # Pull eu-strip binaries using checked-in hashes.
   {
     "name": "eu-strip",
-    "pattern": "src/build/linux/bin/eu-strip.sha1",
+    "pattern": ".",
     "action": [ "download_from_google_storage",
                 "--no_resume",
                 "--platform=linux*",
diff --git a/GypAndroid.darwin-arm.mk b/GypAndroid.darwin-arm.mk
index 5f4b2a0..2568ed8 100644
--- a/GypAndroid.darwin-arm.mk
+++ b/GypAndroid.darwin-arm.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/webkit_version.target.darwin-arm.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.darwin-arm.mk
 include $(LOCAL_PATH)/crypto/crypto.target.darwin-arm.mk
 include $(LOCAL_PATH)/gin/gin.target.darwin-arm.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.darwin-arm.mk
@@ -208,6 +209,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.darwin-arm.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.darwin-arm.mk
diff --git a/GypAndroid.darwin-arm64.mk b/GypAndroid.darwin-arm64.mk
index 5f4b2a0..2568ed8 100644
--- a/GypAndroid.darwin-arm64.mk
+++ b/GypAndroid.darwin-arm64.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.darwin-arm.mk
 include $(LOCAL_PATH)/content/webkit_version.target.darwin-arm.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.darwin-arm.mk
 include $(LOCAL_PATH)/crypto/crypto.target.darwin-arm.mk
 include $(LOCAL_PATH)/gin/gin.target.darwin-arm.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.darwin-arm.mk
@@ -208,6 +209,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.darwin-arm.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.darwin-arm.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.darwin-arm.mk
diff --git a/GypAndroid.darwin-mips.mk b/GypAndroid.darwin-mips.mk
index 99ecdd7..4e8314c 100644
--- a/GypAndroid.darwin-mips.mk
+++ b/GypAndroid.darwin-mips.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.darwin-mips.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.darwin-mips.mk
 include $(LOCAL_PATH)/content/webkit_version.target.darwin-mips.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.darwin-mips.mk
 include $(LOCAL_PATH)/crypto/crypto.target.darwin-mips.mk
 include $(LOCAL_PATH)/gin/gin.target.darwin-mips.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.darwin-mips.mk
@@ -203,6 +204,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.darwin-mips.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.darwin-mips.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.darwin-mips.mk
diff --git a/GypAndroid.darwin-x86.mk b/GypAndroid.darwin-x86.mk
index 3b8d35e..e2e7dc9 100644
--- a/GypAndroid.darwin-x86.mk
+++ b/GypAndroid.darwin-x86.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.darwin-x86.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.darwin-x86.mk
 include $(LOCAL_PATH)/content/webkit_version.target.darwin-x86.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.darwin-x86.mk
 include $(LOCAL_PATH)/crypto/crypto.target.darwin-x86.mk
 include $(LOCAL_PATH)/gin/gin.target.darwin-x86.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.darwin-x86.mk
@@ -212,6 +213,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.darwin-x86.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.darwin-x86.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.darwin-x86.mk
diff --git a/GypAndroid.darwin-x86_64.mk b/GypAndroid.darwin-x86_64.mk
new file mode 100644
index 0000000..4a979f7
--- /dev/null
+++ b/GypAndroid.darwin-x86_64.mk
@@ -0,0 +1,290 @@
+# This file is generated by gyp; do not edit.
+
+
+LOCAL_PATH := $(call my-dir)
+GYP_CONFIGURATION ?= Debug
+
+include $(LOCAL_PATH)/android_webview/All.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/android_webview/android_webview_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/android_webview/android_webview_pak.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/android_webview/libwebviewchromium.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/android_webview_native_jni.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/webview_native.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/allocator/allocator_extension_thunks.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/base.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/base_i18n.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/base_java_application_state.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/base_java_memory_pressure_level_list.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/base_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/base_prefs.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/base_static.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/cc/cc.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/auto_login_parser.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_browser.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_renderer.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_risk_proto.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_core_browser.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_core_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_regexes.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/components_resources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/components_strings.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/navigation_interception.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/navigation_interception_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/os_crypt.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/tracing.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/user_prefs.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/visitedlink_browser.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/visitedlink_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/visitedlink_renderer.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/web_contents_delegate_android.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/web_contents_delegate_android_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/components/webdata_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/browser/devtools/devtools_resources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/browser/speech/proto/speech_proto.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/common_aidl.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_app_both.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_browser.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_child.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_gpu.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_renderer.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_resources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/content_utility.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/gesture_event_type_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/java_set_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/motionevent_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/page_transition_types_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/popup_item_type_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/result_codes_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/screen_orientation_values_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/speech_recognition_error_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/content/webkit_version.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/crypto/crypto.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gin/gin.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/google_apis/google_apis.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer/gles2_utils.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer_client.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer_service.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/disk_cache_proto.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/gles2_c_lib.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/gles2_cmd_helper.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/gles2_implementation.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/gpu.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/gpu_config.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/gpu_ipc.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ipc/ipc.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/jingle/jingle_glue.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/media.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/media_android_imageformat_list.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/media_android_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/media_asm.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/media_mmx.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/media_sse.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/media_sse2.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/player_android.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/shared_memory_support.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/shared_memory_support_sse.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/media/video_capture_android_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/cert_verify_status_android_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/certificate_mime_types_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/http_server.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/net.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/net_errors_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/net_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/net_resources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/net/private_key_types_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/printing/printing.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/printing/printing_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/sandbox/sandbox.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/sandbox/sandbox_services.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/sandbox/seccomp_bpf.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/sdch/sdch.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/skia/skia.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_chrome.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_chrome_opts.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_library.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_opts.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_opts_ssse3.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/sql/sql.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/testing/gtest_prod.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/aggregate_generated_bindings.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/cached_jinja_templates.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/cached_yacc_tables.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/event_interfaces.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/generated_bindings.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/global_constructors_idls.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/individual_generated_bindings.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/interfaces_info.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/config.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/debugger_script_source.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/generate_inspector_protocol_version.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/generated_testing_idls.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/injected_canvas_script_source.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/injected_script_source.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/inspector_instrumentation_sources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/inspector_overlay_page.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/inspector_protocol_sources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/make_core_generated.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_dom.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_generated.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_html.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_prerequisites.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_remaining.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_rendering.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_svg.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_audits_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_codemirror_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_console_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_css.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_elements_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_extensions_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_layers_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_network_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_profiles_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_resources_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_scripts_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_timeline_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_heap_snapshot_worker_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_script_formatter_worker_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_temp_storage_shared_worker_js.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/devtools_extension_api.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/devtools_html.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/frontend_protocol_sources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/generate_devtools_grd.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/supported_css_properties.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/heap/blink_heap.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/heap/blink_heap_asm_stubs.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/modules/modules.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/blink_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/blink_platform.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/blink_prerequisites.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/make_platform_generated.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/web/blink_web.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_generate_devtools_grd.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/angle/src/commit_id.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/angle/src/preprocessor.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/angle/src/translator.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/ashmem/ashmem.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/brotli/brotli.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/expat/expat.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/freetype/ft2.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/iccjpeg/iccjpeg.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icudata.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icui18n.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icui18n.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icuuc.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icuuc.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/system_icu.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/khronos/khronos_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/leveldatabase/leveldatabase.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libevent/libevent.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libjingle/libjingle.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libjpeg/libjpeg.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libphonenumber/libphonenumber.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libpng/libpng.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_dec.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_demux.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_dsp.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_dsp_neon.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_enc.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libxml/libxml.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/npapi/npapi.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/openssl/openssl.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/opus/opus.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/ots/ots.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/protobuf/protobuf_lite.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/protobuf/protoc.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/qcms/qcms.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/re2/re2.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/sfntly/sfntly.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/smhasher/cityhash.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/sqlite/sqlite.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/widevine/cdm/widevine_cdm_version_h.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/config_sources.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/generate_files.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genmacro.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genmodule.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genperf.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genperf_libs.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genstring.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genversion.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/re2c.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/yasm.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/zlib/google/zip.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/zlib/minizip.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/third_party/zlib/zlib.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/tools/json_schema_compiler/api_gen_util.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/accessibility/accessibility.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/accessibility/ax_gen.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/android/bitmap_format_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/android/window_open_disposition_java.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/base/strings/ui_strings.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/base/ui_base.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/base/ui_base_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/events/dom4_keycode_converter.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/events/events.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/events/events_base.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/events/gesture_detection.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/gfx/gfx.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/gfx/gfx_geometry.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/gfx/gfx_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/gl/gl.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/gl/gl_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/gl/surface_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/native_theme/native_theme.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/resources/ui_resources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/shell_dialogs/shell_dialogs.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/snapshot/snapshot.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/ui/surface/surface.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/url/url_lib.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/generate_trig_table.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/js2c.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/mksnapshot.x64.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_base.x64.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_base.x64.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_nosnapshot.x64.host.darwin-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_snapshot.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/child/overscroller_jni_headers.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/child/webkit_child.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/common/gpu/webkit_gpu.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/common/webkit_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_resources.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_storage_common.target.darwin-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_strings.target.darwin-x86_64.mk
+
+# "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from
+# all the included sub-makefiles. This is just here to clarify.
+gyp_all_modules:
diff --git a/GypAndroid.linux-arm.mk b/GypAndroid.linux-arm.mk
index 60fb9ff..b79df89 100644
--- a/GypAndroid.linux-arm.mk
+++ b/GypAndroid.linux-arm.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.linux-arm.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.linux-arm.mk
 include $(LOCAL_PATH)/content/webkit_version.target.linux-arm.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.linux-arm.mk
 include $(LOCAL_PATH)/crypto/crypto.target.linux-arm.mk
 include $(LOCAL_PATH)/gin/gin.target.linux-arm.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.linux-arm.mk
@@ -208,6 +209,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.linux-arm.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.linux-arm.mk
diff --git a/GypAndroid.linux-arm64.mk b/GypAndroid.linux-arm64.mk
index 60fb9ff..b79df89 100644
--- a/GypAndroid.linux-arm64.mk
+++ b/GypAndroid.linux-arm64.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.linux-arm.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.linux-arm.mk
 include $(LOCAL_PATH)/content/webkit_version.target.linux-arm.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.linux-arm.mk
 include $(LOCAL_PATH)/crypto/crypto.target.linux-arm.mk
 include $(LOCAL_PATH)/gin/gin.target.linux-arm.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.linux-arm.mk
@@ -208,6 +209,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.linux-arm.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.linux-arm.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.linux-arm.mk
diff --git a/GypAndroid.linux-mips.mk b/GypAndroid.linux-mips.mk
index e5c11c1..f15bc5b 100644
--- a/GypAndroid.linux-mips.mk
+++ b/GypAndroid.linux-mips.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.linux-mips.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.linux-mips.mk
 include $(LOCAL_PATH)/content/webkit_version.target.linux-mips.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.linux-mips.mk
 include $(LOCAL_PATH)/crypto/crypto.target.linux-mips.mk
 include $(LOCAL_PATH)/gin/gin.target.linux-mips.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.linux-mips.mk
@@ -203,6 +204,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.linux-mips.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.linux-mips.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.linux-mips.mk
diff --git a/GypAndroid.linux-x86.mk b/GypAndroid.linux-x86.mk
index 11c0c79..759a62c 100644
--- a/GypAndroid.linux-x86.mk
+++ b/GypAndroid.linux-x86.mk
@@ -65,6 +65,7 @@
 include $(LOCAL_PATH)/content/screen_orientation_values_java.target.linux-x86.mk
 include $(LOCAL_PATH)/content/speech_recognition_error_java.target.linux-x86.mk
 include $(LOCAL_PATH)/content/webkit_version.target.linux-x86.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.linux-x86.mk
 include $(LOCAL_PATH)/crypto/crypto.target.linux-x86.mk
 include $(LOCAL_PATH)/gin/gin.target.linux-x86.mk
 include $(LOCAL_PATH)/google_apis/google_apis.target.linux-x86.mk
@@ -212,6 +213,7 @@
 include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/libxml/libxml.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.linux-x86.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.linux-x86.mk
 include $(LOCAL_PATH)/third_party/npapi/npapi.target.linux-x86.mk
diff --git a/GypAndroid.linux-x86_64.mk b/GypAndroid.linux-x86_64.mk
new file mode 100644
index 0000000..83b4ab4
--- /dev/null
+++ b/GypAndroid.linux-x86_64.mk
@@ -0,0 +1,290 @@
+# This file is generated by gyp; do not edit.
+
+
+LOCAL_PATH := $(call my-dir)
+GYP_CONFIGURATION ?= Debug
+
+include $(LOCAL_PATH)/android_webview/All.target.linux-x86_64.mk
+include $(LOCAL_PATH)/android_webview/android_webview_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/android_webview/android_webview_pak.target.linux-x86_64.mk
+include $(LOCAL_PATH)/android_webview/libwebviewchromium.target.linux-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/android_webview_native_jni.target.linux-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/android_webview/native/webview_native.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/allocator/allocator_extension_thunks.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/base.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/base_i18n.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/base_java_application_state.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/base_java_memory_pressure_level_list.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/base_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/base_prefs.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/base_static.target.linux-x86_64.mk
+include $(LOCAL_PATH)/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86_64.mk
+include $(LOCAL_PATH)/cc/cc.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/auto_login_parser.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_browser.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_renderer.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_content_risk_proto.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_core_browser.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_core_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/autofill_regexes.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/components_resources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/components_strings.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/navigation_interception.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/navigation_interception_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/os_crypt.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/tracing.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/user_prefs.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/visitedlink_browser.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/visitedlink_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/visitedlink_renderer.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/web_contents_delegate_android.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/web_contents_delegate_android_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/components/webdata_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/browser/devtools/devtools_resources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/browser/speech/proto/speech_proto.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/common_aidl.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_app_both.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_browser.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_child.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_gpu.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_renderer.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_resources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/content_utility.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/gesture_event_type_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/java_set_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/motionevent_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/page_transition_types_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/popup_item_type_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/result_codes_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/screen_orientation_values_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/speech_recognition_error_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/content/webkit_version.target.linux-x86_64.mk
+include $(LOCAL_PATH)/courgette/courgette_lib.target.linux-x86_64.mk
+include $(LOCAL_PATH)/crypto/crypto.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gin/gin.target.linux-x86_64.mk
+include $(LOCAL_PATH)/google_apis/google_apis.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer/gles2_utils.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer_client.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/command_buffer_service.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/disk_cache_proto.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/gles2_c_lib.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/gles2_cmd_helper.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/gles2_implementation.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/gpu.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/gpu_config.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/gpu_ipc.target.linux-x86_64.mk
+include $(LOCAL_PATH)/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ipc/ipc.target.linux-x86_64.mk
+include $(LOCAL_PATH)/jingle/jingle_glue.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/media.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/media_android_imageformat_list.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/media_android_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/media_asm.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/media_mmx.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/media_sse.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/media_sse2.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/player_android.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/shared_memory_support.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/shared_memory_support_sse.target.linux-x86_64.mk
+include $(LOCAL_PATH)/media/video_capture_android_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/cert_verify_status_android_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/certificate_mime_types_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/http_server.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/net.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/net_errors_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/net_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/net_resources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/net/private_key_types_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/printing/printing.target.linux-x86_64.mk
+include $(LOCAL_PATH)/printing/printing_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/sandbox/sandbox.target.linux-x86_64.mk
+include $(LOCAL_PATH)/sandbox/sandbox_services.target.linux-x86_64.mk
+include $(LOCAL_PATH)/sandbox/sandbox_services_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/sandbox/seccomp_bpf.target.linux-x86_64.mk
+include $(LOCAL_PATH)/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/sdch/sdch.target.linux-x86_64.mk
+include $(LOCAL_PATH)/skia/skia.target.linux-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_chrome.target.linux-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_chrome_opts.target.linux-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_library.target.linux-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_opts.target.linux-x86_64.mk
+include $(LOCAL_PATH)/skia/skia_opts_ssse3.target.linux-x86_64.mk
+include $(LOCAL_PATH)/sql/sql.target.linux-x86_64.mk
+include $(LOCAL_PATH)/testing/gtest_prod.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/aggregate_generated_bindings.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/cached_jinja_templates.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/cached_yacc_tables.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/event_interfaces.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/generated_bindings.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/global_constructors_idls.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/individual_generated_bindings.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/bindings/interfaces_info.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/config.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/debugger_script_source.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/generate_inspector_protocol_version.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/generated_testing_idls.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/injected_canvas_script_source.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/injected_script_source.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/inspector_instrumentation_sources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/inspector_overlay_page.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/inspector_protocol_sources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/make_core_generated.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_dom.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_generated.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_html.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_prerequisites.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_remaining.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_rendering.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/core/webcore_svg.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_audits_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_codemirror_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_console_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_css.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_elements_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_extensions_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_layers_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_network_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_profiles_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_resources_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_scripts_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_devtools_timeline_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_heap_snapshot_worker_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_script_formatter_worker_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/concatenated_temp_storage_shared_worker_js.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/devtools_extension_api.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/devtools_html.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/frontend_protocol_sources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/generate_devtools_grd.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/devtools/supported_css_properties.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/heap/blink_heap.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/heap/blink_heap_asm_stubs.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/modules/modules.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/blink_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/blink_platform.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/blink_prerequisites.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/platform/make_platform_generated.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/web/blink_web.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/Source/wtf/wtf_config.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_generate_devtools_grd.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_minimal.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/WebKit/public/blink_skia_config.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/angle/src/commit_id.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/angle/src/preprocessor.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/angle/src/translator.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/ashmem/ashmem.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/brotli/brotli.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/expat/expat.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/freetype/ft2.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/iccjpeg/iccjpeg.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icudata.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icui18n.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icui18n.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icuuc.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/icuuc.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/icu/system_icu.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/khronos/khronos_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/leveldatabase/leveldatabase.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libevent/libevent.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libjingle/libjingle.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libjingle/libjingle_p2p_constants.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libjpeg/libjpeg.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libphonenumber/libphonenumber.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libpng/libpng.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_dec.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_demux.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_dsp.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_dsp_neon.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_enc.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libwebp/libwebp_utils.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libxml/libxml.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/libxslt/libxslt.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/lzma_sdk/lzma_sdk.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/mesa/mesa_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/modp_b64/modp_b64.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/npapi/npapi.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/openssl/openssl.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/opus/opus.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/ots/ots.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/protobuf/protobuf_lite.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/protobuf/protoc.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/qcms/qcms.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/re2/re2.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/sfntly/sfntly.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/smhasher/cityhash.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/sqlite/sqlite.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/widevine/cdm/widevine_cdm_version_h.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/config_sources.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/generate_files.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genmacro.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genmodule.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genperf.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genperf_libs.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genstring.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/genversion.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/re2c.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/yasm/yasm.host.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/zlib/google/zip.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/zlib/minizip.target.linux-x86_64.mk
+include $(LOCAL_PATH)/third_party/zlib/zlib.target.linux-x86_64.mk
+include $(LOCAL_PATH)/tools/json_schema_compiler/api_gen_util.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/accessibility/accessibility.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/accessibility/ax_gen.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/android/bitmap_format_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/android/window_open_disposition_java.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/base/strings/ui_strings.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/base/ui_base.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/base/ui_base_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/events/dom4_keycode_converter.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/events/events.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/events/events_base.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/events/gesture_detection.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/gfx/gfx.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/gfx/gfx_geometry.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/gfx/gfx_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/gl/gl.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/gl/gl_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/gl/surface_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/native_theme/native_theme.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/resources/ui_resources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/shell_dialogs/shell_dialogs.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/snapshot/snapshot.target.linux-x86_64.mk
+include $(LOCAL_PATH)/ui/surface/surface.target.linux-x86_64.mk
+include $(LOCAL_PATH)/url/url_lib.target.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/generate_trig_table.host.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/js2c.host.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/mksnapshot.x64.host.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8.target.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_base.x64.host.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_base.x64.target.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_nosnapshot.x64.host.linux-x86_64.mk
+include $(LOCAL_PATH)/v8/tools/gyp/v8_snapshot.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/child/overscroller_jni_headers.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/child/webkit_child.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/common/gpu/webkit_gpu.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/common/webkit_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_resources.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_storage_browser.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_storage_common.target.linux-x86_64.mk
+include $(LOCAL_PATH)/webkit/webkit_strings.target.linux-x86_64.mk
+
+# "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from
+# all the included sub-makefiles. This is just here to clarify.
+gyp_all_modules:
diff --git a/NOTICE b/NOTICE
index 79977d3..ed275f5 100644
--- a/NOTICE
+++ b/NOTICE
@@ -3923,6 +3923,33 @@
           may use your version of this file under either the NPL or the
           [___] License."
 
+Copyright (c) 2010-2014, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 		    GNU GENERAL PUBLIC LICENSE
 		       Version 2, June 1991
 
diff --git a/OWNERS b/OWNERS
index 695d6ca..95b6345 100644
--- a/OWNERS
+++ b/OWNERS
@@ -9,4 +9,4 @@
 per-file Android.mk=benm@chromium.org
 per-file Android.mk=torne@chromium.org
 per-file PRESUBMIT*.py=maruel@chromium.org
-per-file PRESUBMIT*.py=joi@chromium.org
+
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 326178c..8c27266 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -61,8 +61,7 @@
     'You might be calling functions intended only for testing from\n'
     'production code.  It is OK to ignore this warning if you know what\n'
     'you are doing, as the heuristics used to detect the situation are\n'
-    'not perfect.  The commit queue will not block on this warning.\n'
-    'Email joi@chromium.org if you have questions.')
+    'not perfect.  The commit queue will not block on this warning.')
 
 
 _INCLUDE_ORDER_WARNING = (
@@ -170,6 +169,7 @@
         r"^components[\\\/]breakpad[\\\/]app[\\\/]breakpad_mac\.mm$",
         r"^content[\\\/]shell[\\\/]browser[\\\/]shell_browser_main\.cc$",
         r"^content[\\\/]shell[\\\/]browser[\\\/]shell_message_filter\.cc$",
+        r"^mojo[\\\/]system[\\\/]raw_shared_buffer_posix\.cc$",
         r"^net[\\\/]disk_cache[\\\/]cache_util\.cc$",
       ),
     ),
@@ -759,7 +759,7 @@
   if problems:
     return [output_api.PresubmitPromptOrNotify(
         'Most layers below src/chrome/ should not hardcode service URLs.\n'
-        'Are you sure this is correct? (Contact: joi@chromium.org)',
+        'Are you sure this is correct?',
         ['  %s:%d:  %s' % (
             problem[0], problem[1], problem[2]) for problem in problems])]
   else:
@@ -905,6 +905,7 @@
                      r"logging_native_handler\.cc$",
                  r"^content[\\\/]common[\\\/]gpu[\\\/]client[\\\/]"
                      r"gl_helper_benchmark\.cc$",
+                 r"^native_client_sdk[\\\/]",
                  r"^remoting[\\\/]base[\\\/]logging\.h$",
                  r"^remoting[\\\/]host[\\\/].*",
                  r"^sandbox[\\\/]linux[\\\/].*",
diff --git a/WATCHLISTS b/WATCHLISTS
index 2ce79f8..0f06006 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -671,8 +671,7 @@
     'android_infra': ['bulach+watch@chromium.org',
                       'yfriedman+watch@chromium.org',
                       'ilevy-cc@chromium.org',
-                      'klundberg+watch@chromium.org',
-                      'craigdh+watch@chromium.org'],
+                      'klundberg+watch@chromium.org'],
     'android_tab': ['dtrainor@chromium.org'],
     'android_webview': ['android-webview-reviews@chromium.org'],
     'app_list': ['tfarina@chromium.org', 'chrome-apps-syd-reviews@chromium.org'],
@@ -734,7 +733,7 @@
                      'eugenis+clang@chromium.org',
                      'glider+clang@chromium.org'],
     'clipboard': ['dcheng@chromium.org'],
-    'content': ['jam@chromium.org', 'joi+watch-content@chromium.org',
+    'content': ['jam@chromium.org',
                 'darin-cc@chromium.org'],
     'content_shell': ['jochen+watch@chromium.org'],
     'cookie_monster': ['erikwright@chromium.org'],
diff --git a/android_webview/All.target.darwin-x86_64.mk b/android_webview/All.target.darwin-x86_64.mk
new file mode 100644
index 0000000..9e2bec8
--- /dev/null
+++ b/android_webview/All.target.darwin-x86_64.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_All_gyp
+LOCAL_MODULE_STEM := All
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(TARGET_OUT_INTERMEDIATE_LIBRARIES)/libwebviewchromium.so \
+	$(call intermediates-dir-for,GYP,base_base_java_application_state_gyp)/base_java_application_state.stamp \
+	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_list_gyp)/base_java_memory_pressure_level_list.stamp \
+	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp)/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_page_transition_types_java_gyp)/page_transition_types_java.stamp \
+	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp)/popup_item_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp)/result_codes_java.stamp \
+	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp)/screen_orientation_values_java.stamp \
+	$(call intermediates-dir-for,GYP,content_speech_recognition_error_java_gyp)/speech_recognition_error_java.stamp \
+	$(call intermediates-dir-for,GYP,media_media_android_imageformat_list_gyp)/media_android_imageformat_list.stamp \
+	$(call intermediates-dir-for,GYP,net_certificate_mime_types_java_gyp)/certificate_mime_types_java.stamp \
+	$(call intermediates-dir-for,GYP,net_cert_verify_status_android_java_gyp)/cert_verify_status_android_java.stamp \
+	$(call intermediates-dir-for,GYP,net_net_errors_java_gyp)/net_errors_java.stamp \
+	$(call intermediates-dir-for,GYP,net_private_key_types_java_gyp)/private_key_types_java.stamp \
+	$(call intermediates-dir-for,GYP,ui_android_window_open_disposition_java_gyp)/window_open_disposition_java.stamp \
+	$(call intermediates-dir-for,GYP,ui_android_bitmap_format_java_gyp)/bitmap_format_java.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_All_gyp
+
+# Alias gyp target name.
+.PHONY: All
+All: android_webview_All_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/All.target.linux-x86_64.mk b/android_webview/All.target.linux-x86_64.mk
new file mode 100644
index 0000000..9e2bec8
--- /dev/null
+++ b/android_webview/All.target.linux-x86_64.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_All_gyp
+LOCAL_MODULE_STEM := All
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(TARGET_OUT_INTERMEDIATE_LIBRARIES)/libwebviewchromium.so \
+	$(call intermediates-dir-for,GYP,base_base_java_application_state_gyp)/base_java_application_state.stamp \
+	$(call intermediates-dir-for,GYP,base_base_java_memory_pressure_level_list_gyp)/base_java_memory_pressure_level_list.stamp \
+	$(call intermediates-dir-for,GYP,content_gesture_event_type_java_gyp)/gesture_event_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_page_transition_types_java_gyp)/page_transition_types_java.stamp \
+	$(call intermediates-dir-for,GYP,content_popup_item_type_java_gyp)/popup_item_type_java.stamp \
+	$(call intermediates-dir-for,GYP,content_result_codes_java_gyp)/result_codes_java.stamp \
+	$(call intermediates-dir-for,GYP,content_screen_orientation_values_java_gyp)/screen_orientation_values_java.stamp \
+	$(call intermediates-dir-for,GYP,content_speech_recognition_error_java_gyp)/speech_recognition_error_java.stamp \
+	$(call intermediates-dir-for,GYP,media_media_android_imageformat_list_gyp)/media_android_imageformat_list.stamp \
+	$(call intermediates-dir-for,GYP,net_certificate_mime_types_java_gyp)/certificate_mime_types_java.stamp \
+	$(call intermediates-dir-for,GYP,net_cert_verify_status_android_java_gyp)/cert_verify_status_android_java.stamp \
+	$(call intermediates-dir-for,GYP,net_net_errors_java_gyp)/net_errors_java.stamp \
+	$(call intermediates-dir-for,GYP,net_private_key_types_java_gyp)/private_key_types_java.stamp \
+	$(call intermediates-dir-for,GYP,ui_android_window_open_disposition_java_gyp)/window_open_disposition_java.stamp \
+	$(call intermediates-dir-for,GYP,ui_android_bitmap_format_java_gyp)/bitmap_format_java.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_All_gyp
+
+# Alias gyp target name.
+.PHONY: All
+All: android_webview_All_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/OWNERS b/android_webview/OWNERS
index b0d9e88..e1c7ba2 100644
--- a/android_webview/OWNERS
+++ b/android_webview/OWNERS
@@ -1,6 +1,3 @@
-# Please include joi@ or erikwright@ on the review for any changes
-# to DEPS files under android_webview/ 
-
 benm@chromium.org
 boliu@chromium.org
 michaelbai@chromium.org
diff --git a/android_webview/android_webview.gyp b/android_webview/android_webview.gyp
index 478eb92..ef872cc 100644
--- a/android_webview/android_webview.gyp
+++ b/android_webview/android_webview.gyp
@@ -26,13 +26,6 @@
         [ 'android_webview_build==0', {
           'product_prefix': 'libstandalone',
         }],
-        # The general approach is to allow the executable target to choose
-        # the allocator, but as in the WebView case we are building a library
-        # only, put the dependency on the allocator here
-        [ 'android_webview_build==1 and android_use_tcmalloc==1', {
-          'dependencies': [
-            '../base/allocator/allocator.gyp:allocator', ],
-        }],
         [ 'android_webview_build==1 and use_system_skia==0', {
           # When not using the system skia there are linker warnings about
           # overriden hidden symbols which there's no easy way to eliminate;
@@ -58,9 +51,6 @@
         '<(DEPTH)/ui/resources/ui_resources.gyp:ui_resources',
         '<(DEPTH)/webkit/webkit_resources.gyp:webkit_resources',
       ],
-      'variables': {
-        'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
-      },
       'actions': [
         {
           'action_name': 'repack_android_webview_pack',
@@ -72,16 +62,9 @@
               '<(SHARED_INTERMEDIATE_DIR)/webkit/blink_resources.pak',
               '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources_100_percent.pak',
             ],
+            'pak_output': '<(PRODUCT_DIR)/android_webview_apk/assets/webviewchromium.pak',
           },
-          'inputs': [
-            '<(repack_path)',
-            '<@(pak_inputs)',
-          ],
-          'outputs': [
-            '<(PRODUCT_DIR)/android_webview_apk/assets/webviewchromium.pak',
-          ],
-          'action': ['python', '<(repack_path)', '<@(_outputs)',
-                     '<@(pak_inputs)'],
+         'includes': [ '../build/repack_action.gypi' ],
         }
       ],
     },
@@ -197,8 +180,6 @@
         'common/aw_hit_test_data.cc',
         'common/aw_hit_test_data.h',
         'common/aw_resource.h',
-        'common/aw_switches.cc',
-        'common/aw_switches.h',
         'common/devtools_instrumentation.h',
         'common/print_messages.cc',
         'common/print_messages.h',
diff --git a/android_webview/android_webview_common.target.darwin-arm.mk b/android_webview/android_webview_common.target.darwin-arm.mk
index e34c1c9..269ebc4 100644
--- a/android_webview/android_webview_common.target.darwin-arm.mk
+++ b/android_webview/android_webview_common.target.darwin-arm.mk
@@ -66,7 +66,6 @@
 	android_webview/common/android_webview_message_generator.cc \
 	android_webview/common/aw_content_client.cc \
 	android_webview/common/aw_hit_test_data.cc \
-	android_webview/common/aw_switches.cc \
 	android_webview/common/print_messages.cc \
 	android_webview/common/render_view_messages.cc \
 	android_webview/common/url_constants.cc \
@@ -142,9 +141,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -158,6 +155,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -284,9 +282,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -300,6 +296,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/android_webview_common.target.darwin-mips.mk b/android_webview/android_webview_common.target.darwin-mips.mk
index d4e2591..dcf30ac 100644
--- a/android_webview/android_webview_common.target.darwin-mips.mk
+++ b/android_webview/android_webview_common.target.darwin-mips.mk
@@ -66,7 +66,6 @@
 	android_webview/common/android_webview_message_generator.cc \
 	android_webview/common/aw_content_client.cc \
 	android_webview/common/aw_hit_test_data.cc \
-	android_webview/common/aw_switches.cc \
 	android_webview/common/print_messages.cc \
 	android_webview/common/render_view_messages.cc \
 	android_webview/common/url_constants.cc \
@@ -141,9 +140,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -157,6 +154,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -282,9 +280,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -298,6 +294,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/android_webview_common.target.darwin-x86.mk b/android_webview/android_webview_common.target.darwin-x86.mk
index 36edcdc..a94ba9d 100644
--- a/android_webview/android_webview_common.target.darwin-x86.mk
+++ b/android_webview/android_webview_common.target.darwin-x86.mk
@@ -66,7 +66,6 @@
 	android_webview/common/android_webview_message_generator.cc \
 	android_webview/common/aw_content_client.cc \
 	android_webview/common/aw_hit_test_data.cc \
-	android_webview/common/aw_switches.cc \
 	android_webview/common/print_messages.cc \
 	android_webview/common/render_view_messages.cc \
 	android_webview/common/url_constants.cc \
@@ -143,9 +142,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -159,6 +156,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -285,9 +283,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -301,6 +297,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/android_webview_common.target.darwin-x86_64.mk b/android_webview/android_webview_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..3eb967c
--- /dev/null
+++ b/android_webview/android_webview_common.target.darwin-x86_64.mk
@@ -0,0 +1,428 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := android_webview_android_webview_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,android_webview_android_webview_pak_gyp)/android_webview_pak.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	android_webview/browser/aw_browser_context.cc \
+	android_webview/browser/aw_browser_main_parts.cc \
+	android_webview/browser/aw_contents_client_bridge_base.cc \
+	android_webview/browser/aw_content_browser_client.cc \
+	android_webview/browser/aw_cookie_access_policy.cc \
+	android_webview/browser/aw_download_manager_delegate.cc \
+	android_webview/browser/aw_form_database_service.cc \
+	android_webview/browser/aw_gl_surface.cc \
+	android_webview/browser/aw_http_auth_handler_base.cc \
+	android_webview/browser/aw_javascript_dialog_manager.cc \
+	android_webview/browser/aw_login_delegate.cc \
+	android_webview/browser/aw_pref_store.cc \
+	android_webview/browser/aw_quota_manager_bridge.cc \
+	android_webview/browser/aw_quota_permission_context.cc \
+	android_webview/browser/aw_request_interceptor.cc \
+	android_webview/browser/aw_resource_context.cc \
+	android_webview/browser/aw_web_preferences_populater.cc \
+	android_webview/browser/browser_view_renderer.cc \
+	android_webview/browser/find_helper.cc \
+	android_webview/browser/gpu_memory_buffer_factory_impl.cc \
+	android_webview/browser/hardware_renderer.cc \
+	android_webview/browser/icon_helper.cc \
+	android_webview/browser/intercepted_request_data.cc \
+	android_webview/browser/gl_view_renderer_manager.cc \
+	android_webview/browser/net/android_stream_reader_url_request_job.cc \
+	android_webview/browser/net/aw_network_delegate.cc \
+	android_webview/browser/net/aw_url_request_context_getter.cc \
+	android_webview/browser/net/aw_url_request_job_factory.cc \
+	android_webview/browser/net_disk_cache_remover.cc \
+	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
+	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
+	android_webview/browser/renderer_host/print_manager.cc \
+	android_webview/browser/scoped_app_gl_state_restore.cc \
+	android_webview/browser/shared_renderer_state.cc \
+	android_webview/common/android_webview_message_generator.cc \
+	android_webview/common/aw_content_client.cc \
+	android_webview/common/aw_hit_test_data.cc \
+	android_webview/common/print_messages.cc \
+	android_webview/common/render_view_messages.cc \
+	android_webview/common/url_constants.cc \
+	android_webview/lib/aw_browser_dependency_factory_impl.cc \
+	android_webview/lib/main/aw_main_delegate.cc \
+	android_webview/renderer/aw_content_renderer_client.cc \
+	android_webview/renderer/aw_key_systems.cc \
+	android_webview/renderer/aw_permission_client.cc \
+	android_webview/renderer/aw_render_frame_observer.cc \
+	android_webview/renderer/aw_render_process_observer.cc \
+	android_webview/renderer/aw_render_view_ext.cc \
+	android_webview/renderer/print_web_view_helper.cc \
+	android_webview/renderer/print_web_view_helper_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_android_webview_common_gyp
+
+# Alias gyp target name.
+.PHONY: android_webview_common
+android_webview_common: android_webview_android_webview_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/android_webview/android_webview_common.target.linux-arm.mk b/android_webview/android_webview_common.target.linux-arm.mk
index e34c1c9..269ebc4 100644
--- a/android_webview/android_webview_common.target.linux-arm.mk
+++ b/android_webview/android_webview_common.target.linux-arm.mk
@@ -66,7 +66,6 @@
 	android_webview/common/android_webview_message_generator.cc \
 	android_webview/common/aw_content_client.cc \
 	android_webview/common/aw_hit_test_data.cc \
-	android_webview/common/aw_switches.cc \
 	android_webview/common/print_messages.cc \
 	android_webview/common/render_view_messages.cc \
 	android_webview/common/url_constants.cc \
@@ -142,9 +141,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -158,6 +155,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -284,9 +282,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -300,6 +296,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/android_webview_common.target.linux-mips.mk b/android_webview/android_webview_common.target.linux-mips.mk
index d4e2591..dcf30ac 100644
--- a/android_webview/android_webview_common.target.linux-mips.mk
+++ b/android_webview/android_webview_common.target.linux-mips.mk
@@ -66,7 +66,6 @@
 	android_webview/common/android_webview_message_generator.cc \
 	android_webview/common/aw_content_client.cc \
 	android_webview/common/aw_hit_test_data.cc \
-	android_webview/common/aw_switches.cc \
 	android_webview/common/print_messages.cc \
 	android_webview/common/render_view_messages.cc \
 	android_webview/common/url_constants.cc \
@@ -141,9 +140,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -157,6 +154,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -282,9 +280,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -298,6 +294,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/android_webview_common.target.linux-x86.mk b/android_webview/android_webview_common.target.linux-x86.mk
index 36edcdc..a94ba9d 100644
--- a/android_webview/android_webview_common.target.linux-x86.mk
+++ b/android_webview/android_webview_common.target.linux-x86.mk
@@ -66,7 +66,6 @@
 	android_webview/common/android_webview_message_generator.cc \
 	android_webview/common/aw_content_client.cc \
 	android_webview/common/aw_hit_test_data.cc \
-	android_webview/common/aw_switches.cc \
 	android_webview/common/print_messages.cc \
 	android_webview/common/render_view_messages.cc \
 	android_webview/common/url_constants.cc \
@@ -143,9 +142,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -159,6 +156,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -285,9 +283,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -301,6 +297,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/android_webview_common.target.linux-x86_64.mk b/android_webview/android_webview_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..3eb967c
--- /dev/null
+++ b/android_webview/android_webview_common.target.linux-x86_64.mk
@@ -0,0 +1,428 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := android_webview_android_webview_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,android_webview_android_webview_pak_gyp)/android_webview_pak.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	android_webview/browser/aw_browser_context.cc \
+	android_webview/browser/aw_browser_main_parts.cc \
+	android_webview/browser/aw_contents_client_bridge_base.cc \
+	android_webview/browser/aw_content_browser_client.cc \
+	android_webview/browser/aw_cookie_access_policy.cc \
+	android_webview/browser/aw_download_manager_delegate.cc \
+	android_webview/browser/aw_form_database_service.cc \
+	android_webview/browser/aw_gl_surface.cc \
+	android_webview/browser/aw_http_auth_handler_base.cc \
+	android_webview/browser/aw_javascript_dialog_manager.cc \
+	android_webview/browser/aw_login_delegate.cc \
+	android_webview/browser/aw_pref_store.cc \
+	android_webview/browser/aw_quota_manager_bridge.cc \
+	android_webview/browser/aw_quota_permission_context.cc \
+	android_webview/browser/aw_request_interceptor.cc \
+	android_webview/browser/aw_resource_context.cc \
+	android_webview/browser/aw_web_preferences_populater.cc \
+	android_webview/browser/browser_view_renderer.cc \
+	android_webview/browser/find_helper.cc \
+	android_webview/browser/gpu_memory_buffer_factory_impl.cc \
+	android_webview/browser/hardware_renderer.cc \
+	android_webview/browser/icon_helper.cc \
+	android_webview/browser/intercepted_request_data.cc \
+	android_webview/browser/gl_view_renderer_manager.cc \
+	android_webview/browser/net/android_stream_reader_url_request_job.cc \
+	android_webview/browser/net/aw_network_delegate.cc \
+	android_webview/browser/net/aw_url_request_context_getter.cc \
+	android_webview/browser/net/aw_url_request_job_factory.cc \
+	android_webview/browser/net_disk_cache_remover.cc \
+	android_webview/browser/net/input_stream_reader.cc \
+	android_webview/browser/renderer_host/aw_render_view_host_ext.cc \
+	android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.cc \
+	android_webview/browser/renderer_host/print_manager.cc \
+	android_webview/browser/scoped_app_gl_state_restore.cc \
+	android_webview/browser/shared_renderer_state.cc \
+	android_webview/common/android_webview_message_generator.cc \
+	android_webview/common/aw_content_client.cc \
+	android_webview/common/aw_hit_test_data.cc \
+	android_webview/common/print_messages.cc \
+	android_webview/common/render_view_messages.cc \
+	android_webview/common/url_constants.cc \
+	android_webview/lib/aw_browser_dependency_factory_impl.cc \
+	android_webview/lib/main/aw_main_delegate.cc \
+	android_webview/renderer/aw_content_renderer_client.cc \
+	android_webview/renderer/aw_key_systems.cc \
+	android_webview/renderer/aw_permission_client.cc \
+	android_webview/renderer/aw_render_frame_observer.cc \
+	android_webview/renderer/aw_render_process_observer.cc \
+	android_webview/renderer/aw_render_view_ext.cc \
+	android_webview/renderer/print_web_view_helper.cc \
+	android_webview/renderer/print_web_view_helper_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_android_webview_common_gyp
+
+# Alias gyp target name.
+.PHONY: android_webview_common
+android_webview_common: android_webview_android_webview_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/android_webview/android_webview_pak.target.darwin-x86_64.mk b/android_webview/android_webview_pak.target.darwin-x86_64.mk
new file mode 100644
index 0000000..441e6f5
--- /dev/null
+++ b/android_webview/android_webview_pak.target.darwin-x86_64.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_android_webview_pak_gyp
+LOCAL_MODULE_STEM := android_webview_pak
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,net_net_resources_gyp)/net_resources.stamp \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp
+
+### Rules for action "repack_android_webview_pack":
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(gyp_shared_intermediate_dir)/content/content_resources.pak $(gyp_shared_intermediate_dir)/net/net_resources.pak $(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak $(gyp_shared_intermediate_dir)/webkit/blink_resources.pak $(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: android_webview_android_webview_gyp_android_webview_pak_target_repack_android_webview_pack ($@)"
+	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_apk/assets; python ../tools/grit/grit/format/repack.py "$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak" "$(gyp_shared_intermediate_dir)/content/content_resources.pak" "$(gyp_shared_intermediate_dir)/net/net_resources.pak" "$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak" "$(gyp_shared_intermediate_dir)/webkit/blink_resources.pak" "$(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak"
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_android_webview_pak_gyp
+
+# Alias gyp target name.
+.PHONY: android_webview_pak
+android_webview_pak: android_webview_android_webview_pak_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/android_webview_pak.target.linux-x86_64.mk b/android_webview/android_webview_pak.target.linux-x86_64.mk
new file mode 100644
index 0000000..441e6f5
--- /dev/null
+++ b/android_webview/android_webview_pak.target.linux-x86_64.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_android_webview_pak_gyp
+LOCAL_MODULE_STEM := android_webview_pak
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,net_net_resources_gyp)/net_resources.stamp \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp
+
+### Rules for action "repack_android_webview_pack":
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak: $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(gyp_shared_intermediate_dir)/content/content_resources.pak $(gyp_shared_intermediate_dir)/net/net_resources.pak $(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak $(gyp_shared_intermediate_dir)/webkit/blink_resources.pak $(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: android_webview_android_webview_gyp_android_webview_pak_target_repack_android_webview_pack ($@)"
+	$(hide)cd $(gyp_local_path)/android_webview; mkdir -p $(gyp_shared_intermediate_dir)/android_webview_apk/assets; python ../tools/grit/grit/format/repack.py "$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak" "$(gyp_shared_intermediate_dir)/content/content_resources.pak" "$(gyp_shared_intermediate_dir)/net/net_resources.pak" "$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak" "$(gyp_shared_intermediate_dir)/webkit/blink_resources.pak" "$(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak"
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview_apk/assets/webviewchromium.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_android_webview_pak_gyp
+
+# Alias gyp target name.
+.PHONY: android_webview_pak
+android_webview_pak: android_webview_android_webview_pak_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index 8c1e0ec..9ef21e5 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -171,6 +171,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) {
   // TODO(toyoshim): Android WebView is not supported yet.
   // See http://crbug.com/339767.
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index 0aa47c3..d4d3734 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -93,6 +93,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) OVERRIDE;
   virtual void CancelMidiSysExPermissionRequest(
         int render_process_id,
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc
index 32cb906..5bbc1ab 100644
--- a/android_webview/browser/browser_view_renderer.cc
+++ b/android_webview/browser/browser_view_renderer.cc
@@ -13,7 +13,6 @@
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
 #include "content/public/browser/android/synchronous_compositor.h"
-#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
@@ -23,7 +22,6 @@
 using base::android::AttachCurrentThread;
 using base::android::JavaRef;
 using base::android::ScopedJavaLocalRef;
-using content::BrowserThread;
 
 namespace android_webview {
 
@@ -31,15 +29,44 @@
 
 const int64 kFallbackTickTimeoutInMilliseconds = 20;
 
+class AutoResetWithLock {
+ public:
+  AutoResetWithLock(gfx::Vector2dF* scoped_variable,
+                    gfx::Vector2dF new_value,
+                    base::Lock& lock)
+      : scoped_variable_(scoped_variable),
+        original_value_(*scoped_variable),
+        lock_(lock) {
+    base::AutoLock auto_lock(lock_);
+    *scoped_variable_ = new_value;
+  }
+
+  ~AutoResetWithLock() {
+    base::AutoLock auto_lock(lock_);
+    *scoped_variable_ = original_value_;
+  }
+
+ private:
+  gfx::Vector2dF* scoped_variable_;
+  gfx::Vector2dF original_value_;
+  base::Lock& lock_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoResetWithLock);
+};
+
 }  // namespace
 
 BrowserViewRenderer::BrowserViewRenderer(
     BrowserViewRendererClient* client,
     SharedRendererState* shared_renderer_state,
-    content::WebContents* web_contents)
+    content::WebContents* web_contents,
+    const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
     : client_(client),
       shared_renderer_state_(shared_renderer_state),
       web_contents_(web_contents),
+      weak_factory_on_ui_thread_(this),
+      ui_thread_weak_ptr_(weak_factory_on_ui_thread_.GetWeakPtr()),
+      ui_task_runner_(ui_task_runner),
       has_compositor_(false),
       is_paused_(false),
       view_visible_(false),
@@ -124,8 +151,8 @@
 
   // Reset scroll back to the origin, will go back to the old
   // value when scroll_reset is out of scope.
-  base::AutoReset<gfx::Vector2dF> scroll_reset(&scroll_offset_dip_,
-                                               gfx::Vector2d());
+  AutoResetWithLock scroll_reset(
+      &scroll_offset_dip_, gfx::Vector2dF(), scroll_offset_dip_lock_);
 
   SkCanvas* rec_canvas = picture->beginRecording(width, height, 0);
   if (has_compositor_)
@@ -227,6 +254,7 @@
                "BrowserViewRenderer::DidInitializeCompositor");
   DCHECK(compositor);
   DCHECK(!has_compositor_);
+  DCHECK(ui_task_runner_->BelongsToCurrentThread());
   has_compositor_ = true;
   shared_renderer_state_->SetCompositorOnUiThread(compositor);
 }
@@ -235,11 +263,20 @@
     content::SynchronousCompositor* compositor) {
   TRACE_EVENT0("android_webview", "BrowserViewRenderer::DidDestroyCompositor");
   DCHECK(has_compositor_);
+  DCHECK(ui_task_runner_->BelongsToCurrentThread());
   has_compositor_ = false;
   shared_renderer_state_->SetCompositorOnUiThread(NULL);
 }
 
 void BrowserViewRenderer::SetContinuousInvalidate(bool invalidate) {
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BrowserViewRenderer::SetContinuousInvalidate,
+                   ui_thread_weak_ptr_,
+                   invalidate));
+    return;
+  }
   if (compositor_needs_continuous_invalidate_ == invalidate)
     return;
 
@@ -284,16 +321,25 @@
   DCHECK_LE(scroll_offset_dip.x(), max_scroll_offset_dip_.x());
   DCHECK_LE(scroll_offset_dip.y(), max_scroll_offset_dip_.y());
 
-  if (scroll_offset_dip_ == scroll_offset_dip)
-    return;
+  {
+    base::AutoLock lock(scroll_offset_dip_lock_);
+    if (scroll_offset_dip_ == scroll_offset_dip)
+      return;
 
-  scroll_offset_dip_ = scroll_offset_dip;
+    scroll_offset_dip_ = scroll_offset_dip;
+  }
 
   if (has_compositor_)
     shared_renderer_state_->CompositorDidChangeRootLayerScrollOffset();
 }
 
 void BrowserViewRenderer::DidUpdateContent() {
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    ui_task_runner_->PostTask(FROM_HERE,
+                              base::Bind(&BrowserViewRenderer::DidUpdateContent,
+                                         ui_thread_weak_ptr_));
+    return;
+  }
   TRACE_EVENT_INSTANT0("android_webview",
                        "BrowserViewRenderer::DidUpdateContent",
                        TRACE_EVENT_SCOPE_THREAD);
@@ -304,6 +350,14 @@
 
 void BrowserViewRenderer::SetMaxRootLayerScrollOffset(
     gfx::Vector2dF new_value_dip) {
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BrowserViewRenderer::SetMaxRootLayerScrollOffset,
+                   ui_thread_weak_ptr_,
+                   new_value_dip));
+    return;
+  }
   DCHECK_GT(dip_scale_, 0);
 
   max_scroll_offset_dip_ = new_value_dip;
@@ -315,12 +369,24 @@
 
 void BrowserViewRenderer::SetTotalRootLayerScrollOffset(
     gfx::Vector2dF scroll_offset_dip) {
-  // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
-  // DrawGl when http://crbug.com/249972 is fixed.
-  if (scroll_offset_dip_ == scroll_offset_dip)
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BrowserViewRenderer::SetTotalRootLayerScrollOffset,
+                   ui_thread_weak_ptr_,
+                   scroll_offset_dip));
     return;
+  }
 
-  scroll_offset_dip_ = scroll_offset_dip;
+  {
+    base::AutoLock lock(scroll_offset_dip_lock_);
+    // TOOD(mkosiba): Add a DCHECK to say that this does _not_ get called during
+    // DrawGl when http://crbug.com/249972 is fixed.
+    if (scroll_offset_dip_ == scroll_offset_dip)
+      return;
+
+    scroll_offset_dip_ = scroll_offset_dip;
+  }
 
   gfx::Vector2d max_offset = max_scroll_offset();
   gfx::Vector2d scroll_offset;
@@ -347,10 +413,16 @@
 }
 
 gfx::Vector2dF BrowserViewRenderer::GetTotalRootLayerScrollOffset() {
+  base::AutoLock lock(scroll_offset_dip_lock_);
   return scroll_offset_dip_;
 }
 
 bool BrowserViewRenderer::IsExternalFlingActive() const {
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    // TODO(boliu): This is short term hack since we cannot call into
+    // view system on non-UI thread.
+    return false;
+  }
   return client_->IsFlingActive();
 }
 
@@ -358,20 +430,49 @@
     float page_scale_factor,
     float min_page_scale_factor,
     float max_page_scale_factor) {
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BrowserViewRenderer::SetRootLayerPageScaleFactorAndLimits,
+                   ui_thread_weak_ptr_,
+                   page_scale_factor,
+                   min_page_scale_factor,
+                   max_page_scale_factor));
+    return;
+  }
   page_scale_factor_ = page_scale_factor;
   DCHECK_GT(page_scale_factor_, 0);
   client_->SetPageScaleFactorAndLimits(
       page_scale_factor, min_page_scale_factor, max_page_scale_factor);
+  client_->SetMaxContainerViewScrollOffset(max_scroll_offset());
 }
 
 void BrowserViewRenderer::SetRootLayerScrollableSize(
     gfx::SizeF scrollable_size) {
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BrowserViewRenderer::SetRootLayerScrollableSize,
+                   ui_thread_weak_ptr_,
+                   scrollable_size));
+    return;
+  }
   client_->SetContentsSize(scrollable_size);
 }
 
 void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll,
                                         gfx::Vector2dF latest_overscroll_delta,
                                         gfx::Vector2dF current_fling_velocity) {
+  if (!ui_task_runner_->BelongsToCurrentThread()) {
+    ui_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&BrowserViewRenderer::DidOverscroll,
+                   ui_thread_weak_ptr_,
+                   accumulated_overscroll,
+                   latest_overscroll_delta,
+                   current_fling_velocity));
+    return;
+  }
   const float physical_pixel_scale = dip_scale_ * page_scale_factor_;
   if (accumulated_overscroll == latest_overscroll_delta)
     overscroll_rounding_error_ = gfx::Vector2dF();
@@ -417,8 +518,7 @@
   // ticked. This can happen if this is reached because force_invalidate is
   // true.
   if (compositor_needs_continuous_invalidate_) {
-    BrowserThread::PostDelayedTask(
-        BrowserThread::UI,
+    ui_task_runner_->PostDelayedTask(
         FROM_HERE,
         fallback_tick_.callback(),
         base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h
index 5ae1d9b..da82fce 100644
--- a/android_webview/browser/browser_view_renderer.h
+++ b/android_webview/browser/browser_view_renderer.h
@@ -54,9 +54,11 @@
 // Provides software and hardware rendering and the Capture Picture API.
 class BrowserViewRenderer : public content::SynchronousCompositorClient {
  public:
-  BrowserViewRenderer(BrowserViewRendererClient* client,
-                      SharedRendererState* shared_renderer_state,
-                      content::WebContents* web_contents);
+  BrowserViewRenderer(
+      BrowserViewRendererClient* client,
+      SharedRendererState* shared_renderer_state,
+      content::WebContents* web_contents,
+      const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner);
 
   virtual ~BrowserViewRenderer();
 
@@ -147,6 +149,14 @@
   BrowserViewRendererClient* client_;
   SharedRendererState* shared_renderer_state_;
   content::WebContents* web_contents_;
+  // TODO(boliu): This class should only be used on the UI thread. However in
+  // short term to supporting HardwareRenderer, some callbacks on
+  // SynchronousCompositorClient may be called on non-UI thread. These are
+  // used to detect this and post them back to UI thread.
+  base::WeakPtrFactory<BrowserViewRenderer> weak_factory_on_ui_thread_;
+  base::WeakPtr<BrowserViewRenderer> ui_thread_weak_ptr_;
+  scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+
   bool has_compositor_;
 
   bool is_paused_;
@@ -175,6 +185,9 @@
 
   DrawGLInput draw_gl_input_;
 
+  // TODO(boliu): This is a short term solution to support
+  // SynchronousCompositorClient methods called on non-UI thread.
+  base::Lock scroll_offset_dip_lock_;
   // Current scroll offset in CSS pixels.
   gfx::Vector2dF scroll_offset_dip_;
 
diff --git a/android_webview/browser/gpu_memory_buffer_factory_impl.cc b/android_webview/browser/gpu_memory_buffer_factory_impl.cc
index c4a6cac..4e2f5d7 100644
--- a/android_webview/browser/gpu_memory_buffer_factory_impl.cc
+++ b/android_webview/browser/gpu_memory_buffer_factory_impl.cc
@@ -19,7 +19,7 @@
 
 class GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
  public:
-  GpuMemoryBufferImpl(int buffer_id, gfx::Size size)
+  GpuMemoryBufferImpl(long buffer_id, gfx::Size size)
       : buffer_id_(buffer_id),
         size_(size),
         mapped_(false) {
@@ -62,13 +62,13 @@
   }
   virtual gfx::GpuMemoryBufferHandle GetHandle() const OVERRIDE {
     gfx::GpuMemoryBufferHandle handle;
-    handle.type = gfx::EGL_CLIENT_BUFFER;
+    handle.type = gfx::ANDROID_NATIVE_BUFFER;
     handle.native_buffer = g_gl_draw_functions->get_native_buffer(buffer_id_);
     return handle;
   }
 
  private:
-  int buffer_id_;
+  long buffer_id_;
   gfx::Size size_;
   bool mapped_;
 
@@ -91,7 +91,7 @@
   // GL_RGBA8_OES.
   CHECK_EQ(static_cast<GLenum>(GL_RGBA8_OES), internalformat);
   CHECK(g_gl_draw_functions);
-  int buffer_id = g_gl_draw_functions->create_graphic_buffer(width, height);
+  long buffer_id = g_gl_draw_functions->create_graphic_buffer(width, height);
   if (!buffer_id)
     return NULL;
 
diff --git a/android_webview/browser/hardware_renderer.cc b/android_webview/browser/hardware_renderer.cc
index 083ace7..1352825 100644
--- a/android_webview/browser/hardware_renderer.cc
+++ b/android_webview/browser/hardware_renderer.cc
@@ -8,7 +8,6 @@
 #include "android_webview/browser/browser_view_renderer_client.h"
 #include "android_webview/browser/gl_view_renderer_manager.h"
 #include "android_webview/browser/scoped_app_gl_state_restore.h"
-#include "android_webview/common/aw_switches.h"
 #include "android_webview/public/browser/draw_gl.h"
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
diff --git a/android_webview/browser/net/aw_network_delegate.cc b/android_webview/browser/net/aw_network_delegate.cc
index c5aef1f..a18226c 100644
--- a/android_webview/browser/net/aw_network_delegate.cc
+++ b/android_webview/browser/net/aw_network_delegate.cc
@@ -45,7 +45,8 @@
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     const net::HttpResponseHeaders* original_response_headers,
-    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   return net::OK;
 }
 
diff --git a/android_webview/browser/net/aw_network_delegate.h b/android_webview/browser/net/aw_network_delegate.h
index 6d34469..7b78dda 100644
--- a/android_webview/browser/net/aw_network_delegate.h
+++ b/android_webview/browser/net/aw_network_delegate.h
@@ -30,8 +30,8 @@
       net::URLRequest* request,
       const net::CompletionCallback& callback,
       const net::HttpResponseHeaders* original_response_headers,
-      scoped_refptr<net::HttpResponseHeaders>* override_response_headers)
-      OVERRIDE;
+      scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE;
   virtual void OnBeforeRedirect(net::URLRequest* request,
                                 const GURL& new_location) OVERRIDE;
   virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc
index 38c70a2..a6bd025 100644
--- a/android_webview/browser/net/aw_url_request_context_getter.cc
+++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -12,7 +12,6 @@
 #include "android_webview/browser/net/aw_url_request_job_factory.h"
 #include "android_webview/browser/net/init_native_callback.h"
 #include "android_webview/common/aw_content_client.h"
-#include "android_webview/common/aw_switches.h"
 #include "base/command_line.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
index 8efdf04..ccd511f 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
@@ -6,7 +6,6 @@
 
 #include "android_webview/browser/aw_browser_context.h"
 #include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h"
-#include "android_webview/common/aw_switches.h"
 #include "android_webview/common/render_view_messages.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/callback.h"
diff --git a/android_webview/buildbot/aosp_manifest.xml b/android_webview/buildbot/aosp_manifest.xml
index b791f02..565a9d5 100644
--- a/android_webview/buildbot/aosp_manifest.xml
+++ b/android_webview/buildbot/aosp_manifest.xml
@@ -244,7 +244,7 @@
   <project path="frameworks/testing" name="platform/frameworks/testing" />
   <project path="frameworks/uiautomator" name="platform/frameworks/uiautomator" />
   <project path="frameworks/volley" name="platform/frameworks/volley" />
-  <project path="frameworks/webview" name="platform/frameworks/webview" revision="f246f9015ed47f7a7d03764d0271918318c82e93" remote="aosp" />
+  <project path="frameworks/webview" name="platform/frameworks/webview" revision="91c257e83bf32e3394686cafd27a83c6ccd6b912" remote="aosp" />
   <project path="frameworks/wilhelm" name="platform/frameworks/wilhelm" />
   <project path="hardware/akm" name="platform/hardware/akm" />
   <project path="hardware/broadcom/libbt" name="platform/hardware/broadcom/libbt" groups="pdk" />
diff --git a/android_webview/common/aw_switches.cc b/android_webview/common/aw_switches.cc
deleted file mode 100644
index 6b9b2fd..0000000
--- a/android_webview/common/aw_switches.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "android_webview/common/aw_switches.h"
-
-namespace switches {
-
-const char kEnableAccelerated2dCanvas[] = "enable-accelerated-2d-canvas";
-
-}  // namespace switches
diff --git a/android_webview/common/aw_switches.h b/android_webview/common/aw_switches.h
deleted file mode 100644
index 5111a08..0000000
--- a/android_webview/common/aw_switches.h
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef ANDROID_WEBVIEW_COMMON_AW_SWITCHES_H_
-#define ANDROID_WEBVIEW_COMMON_AW_SWITCHES_H_
-
-namespace switches {
-
-// Explicitly enable accelerated 2d canvas.
-// TODO(boliu): Remove this switch once on by default.
-extern const char kEnableAccelerated2dCanvas[];
-
-}  // namespace switches
-
-#endif  // ANDROID_WEBVIEW_COMMON_AW_SWITCHES_H_
diff --git a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
index b3aa4f8..589ca62 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java
@@ -33,7 +33,7 @@
     public static void loadLibrary() {
         PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX);
         try {
-            LibraryLoader.loadNow();
+            LibraryLoader.loadNow(null);
             initTraceEvent();
         } catch (ProcessInitException e) {
             throw new RuntimeException("Cannot load WebView", e);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java
index 02453f4..c8796ac 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContents.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java
@@ -543,7 +543,7 @@
     }
 
     private static ContentViewCore createAndInitializeContentViewCore(ViewGroup containerView,
-            InternalAccessDelegate internalDispatcher, int nativeWebContents,
+            InternalAccessDelegate internalDispatcher, long nativeWebContents,
             GestureStateListener gestureStateListener,
             ContentViewClient contentViewClient,
             ContentViewCore.ZoomControlsDelegate zoomControlsDelegate) {
@@ -583,7 +583,7 @@
         // bind all the native->java relationships.
         mCleanupReference = new CleanupReference(this, new DestroyRunnable(mNativeAwContents));
 
-        int nativeWebContents = nativeGetWebContents(mNativeAwContents);
+        long nativeWebContents = nativeGetWebContents(mNativeAwContents);
         mContentViewCore = createAndInitializeContentViewCore(
                 mContainerView, mInternalAccessAdapter, nativeWebContents,
                 new AwGestureStateListener(), mContentViewClient, mZoomControls);
@@ -602,7 +602,7 @@
      * provide the AwContents to host the pop up content.
      */
     public void supplyContentsForPopup(AwContents newContents) {
-        int popupNativeAwContents = nativeReleasePopupAwContents(mNativeAwContents);
+        long popupNativeAwContents = nativeReleasePopupAwContents(mNativeAwContents);
         if (popupNativeAwContents == 0) {
             Log.w(TAG, "Popup WebView bind failed: no pending content.");
             if (newContents != null) newContents.destroy();
@@ -618,7 +618,7 @@
 
     // Recap: supplyContentsForPopup() is called on the parent window's content, this method is
     // called on the popup window's content.
-    private void receivePopupContents(int popupNativeAwContents) {
+    private void receivePopupContents(long popupNativeAwContents) {
         mDeferredShouldOverrideUrlLoadingIsPendingForPopup = true;
         // Save existing view state.
         final boolean wasAttached = mIsAttachedToWindow;
@@ -705,15 +705,15 @@
         return mAwPdfExporter;
     }
 
-    public static void setAwDrawSWFunctionTable(int functionTablePointer) {
+    public static void setAwDrawSWFunctionTable(long functionTablePointer) {
         nativeSetAwDrawSWFunctionTable(functionTablePointer);
     }
 
-    public static void setAwDrawGLFunctionTable(int functionTablePointer) {
+    public static void setAwDrawGLFunctionTable(long functionTablePointer) {
         nativeSetAwDrawGLFunctionTable(functionTablePointer);
     }
 
-    public static int getAwDrawGLFunction() {
+    public static long getAwDrawGLFunction() {
         return nativeGetAwDrawGLFunction();
     }
 
@@ -740,7 +740,7 @@
         return nativeGetNativeInstanceCount();
     }
 
-    public int getAwDrawGLViewContext() {
+    public long getAwDrawGLViewContext() {
         // Only called during early construction, so client should not have had a chance to
         // call destroy yet.
         assert mNativeAwContents != 0;
@@ -1977,6 +1977,9 @@
         if (mPageScaleFactor != pageScaleFactor) {
           float oldPageScaleFactor = mPageScaleFactor;
           mPageScaleFactor = pageScaleFactor;
+          // NOTE: if this ever needs to become synchronous then we need to make sure the scroll
+          // bounds are correctly updated before calling the method, otherwise embedder code that
+          // attempts to scroll on scale change might cause weird results.
           mContentsClient.getCallbackHelper().postOnScaleChangedScaled(
                   (float)(oldPageScaleFactor * mDIPScale),
                   (float)(mPageScaleFactor * mDIPScale));
@@ -2067,9 +2070,9 @@
 
     private static native long nativeInit(AwBrowserContext browserContext);
     private static native void nativeDestroy(long nativeAwContents);
-    private static native void nativeSetAwDrawSWFunctionTable(int functionTablePointer);
-    private static native void nativeSetAwDrawGLFunctionTable(int functionTablePointer);
-    private static native int nativeGetAwDrawGLFunction();
+    private static native void nativeSetAwDrawSWFunctionTable(long functionTablePointer);
+    private static native void nativeSetAwDrawGLFunctionTable(long functionTablePointer);
+    private static native long nativeGetAwDrawGLFunction();
     private static native int nativeGetNativeInstanceCount();
     private static native void nativeSetShouldDownloadFavicons();
     private native void nativeSetJavaPeers(long nativeAwContents, AwContents awContents,
@@ -2077,7 +2080,7 @@
             AwContentsClientBridge contentsClientBridge,
             AwContentsIoThreadClient ioThreadClient,
             InterceptNavigationDelegate navigationInterceptionDelegate);
-    private native int nativeGetWebContents(long nativeAwContents);
+    private native long nativeGetWebContents(long nativeAwContents);
 
     private native void nativeDocumentHasImages(long nativeAwContents, Message message);
     private native void nativeGenerateMHTML(
@@ -2116,11 +2119,11 @@
     // Returns false if restore state fails.
     private native boolean nativeRestoreFromOpaqueState(long nativeAwContents, byte[] state);
 
-    private native int nativeReleasePopupAwContents(long nativeAwContents);
+    private native long nativeReleasePopupAwContents(long nativeAwContents);
     private native void nativeFocusFirstNode(long nativeAwContents);
     private native void nativeSetBackgroundColor(long nativeAwContents, int color);
 
-    private native int nativeGetAwDrawGLViewContext(long nativeAwContents);
+    private native long nativeGetAwDrawGLViewContext(long nativeAwContents);
     private native long nativeCapturePicture(long nativeAwContents, int width, int height);
     private native void nativeEnableOnNewPicture(long nativeAwContents, boolean enabled);
     private native void nativeClearView(long nativeAwContents);
diff --git a/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java b/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java
index 915f2c6..f4e683b 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java
@@ -12,7 +12,7 @@
 @JNINamespace("android_webview")
 public class AwDevToolsServer {
 
-    private int mNativeDevToolsServer = 0;
+    private long mNativeDevToolsServer = 0;
 
     public AwDevToolsServer() {
         mNativeDevToolsServer = nativeInitRemoteDebugging();
@@ -27,7 +27,7 @@
         nativeSetRemoteDebuggingEnabled(mNativeDevToolsServer, enabled);
     }
 
-    private native int nativeInitRemoteDebugging();
-    private native void nativeDestroyRemoteDebugging(int devToolsServer);
-    private native void nativeSetRemoteDebuggingEnabled(int devToolsServer, boolean enabled);
+    private native long nativeInitRemoteDebugging();
+    private native void nativeDestroyRemoteDebugging(long devToolsServer);
+    private native void nativeSetRemoteDebuggingEnabled(long devToolsServer, boolean enabled);
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/AwPdfExporter.java b/android_webview/java/src/org/chromium/android_webview/AwPdfExporter.java
index a29ee4d..d8b8e37 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwPdfExporter.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwPdfExporter.java
@@ -69,7 +69,7 @@
     }
 
     @CalledByNative
-    private void setNativeAwPdfExporter(int nativePdfExporter) {
+    private void setNativeAwPdfExporter(long nativePdfExporter) {
         mNativeAwPdfExporter = nativePdfExporter;
         // Handle the cornercase that Webview.Destroy is called before the native side
         // has a chance to complete the pdf exporting.
diff --git a/android_webview/java/src/org/chromium/android_webview/AwSettings.java b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
index 9c8f3b4..a00235b 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwSettings.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwSettings.java
@@ -256,7 +256,7 @@
         }
     }
 
-    void setWebContents(int nativeWebContents) {
+    void setWebContents(long nativeWebContents) {
         synchronized (mAwSettingsLock) {
             if (mNativeAwSettings != 0) {
                 nativeDestroy(mNativeAwSettings);
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
index 5b73156..3ada155 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java
@@ -13,7 +13,6 @@
 import org.chromium.android_webview.AwContentsClient;
 import org.chromium.android_webview.AwLayoutSizer;
 import org.chromium.android_webview.test.util.CommonResources;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.content.browser.test.util.CallbackHelper;
 import org.chromium.ui.gfx.DeviceDisplayInfo;
@@ -357,9 +356,8 @@
         assertEquals(expectedHeightCss, mOnContentSizeChangedHelper.getHeight());
     }
 
-    //@SmallTest
-    //@Feature({"AndroidWebView"})
-    @DisabledTest
+    @SmallTest
+    @Feature({"AndroidWebView"})
     public void testReceivingSizeAfterLoadUpdatesLayout() throws Throwable {
         final TestAwContentsClient contentsClient = new TestAwContentsClient();
         final AwTestContainerView testContainerView = createDetachedTestContainerViewOnMainSync(
@@ -369,22 +367,26 @@
         final double deviceDIPScale =
             DeviceDisplayInfo.create(testContainerView.getContext()).getDIPScale();
         final int physicalWidth = 600;
+        final int spanWidth = 42;
         final int expectedWidthCss =
             (int) Math.ceil(physicalWidth / deviceDIPScale);
 
-        StringBuilder htmlBuilder = new StringBuilder(" <html><body><span>");
-        for (int i = 0; i < 10; ++i)
-            htmlBuilder.append("test test test");
-        htmlBuilder.append("</span></body></html>");
+        StringBuilder htmlBuilder = new StringBuilder("<html><body style='margin:0px;'>");
+        final String spanBlock =
+            "<span style='width: " + spanWidth + "px; display: inline-block;'>a</span>";
+        for (int i = 0; i < 10; ++i) {
+            htmlBuilder.append(spanBlock);
+        }
+        htmlBuilder.append("</body></html>");
 
         int contentSizeChangeCallCount = mOnContentSizeChangedHelper.getCallCount();
         loadDataAsync(awContents, htmlBuilder.toString(), "text/html", false);
-        mOnContentSizeChangedHelper.waitForCallback(contentSizeChangeCallCount);
-
         // Because we're loading the contents into a detached WebView its layout size is 0x0 and as
         // a result of that the paragraph will be formated such that each word is on a separate
         // line.
-        assertTrue(mOnContentSizeChangedHelper.getWidth() < expectedWidthCss);
+        waitForContentSizeToChangeTo(mOnContentSizeChangedHelper, contentSizeChangeCallCount,
+                spanWidth, -1);
+
         final int narrowLayoutHeight = mOnContentSizeChangedHelper.getHeight();
 
         contentSizeChangeCallCount = mOnContentSizeChangedHelper.getCallCount();
@@ -399,7 +401,7 @@
         // As a result of calling the onSizeChanged method the layout size should be updated to
         // match the width of the webview and the text we previously loaded should reflow making the
         // contents width match the WebView width.
-        assertEquals(mOnContentSizeChangedHelper.getWidth(), expectedWidthCss);
+        assertEquals(expectedWidthCss, mOnContentSizeChangedHelper.getWidth());
         assertTrue(mOnContentSizeChangedHelper.getHeight() < narrowLayoutHeight);
         assertTrue(mOnContentSizeChangedHelper.getHeight() > 0);
     }
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
index fed6524..0b5e19f 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java
@@ -57,15 +57,17 @@
      */
     abstract class AwSettingsTestHelper<T> {
         protected final AwContents mAwContents;
+        protected final Context mContext;
         protected final TestAwContentsClient mContentViewClient;
         protected final AwSettings mAwSettings;
 
-        AwSettingsTestHelper(AwContents awContents,
+        AwSettingsTestHelper(AwTestContainerView containerView,
                              TestAwContentsClient contentViewClient,
                              boolean requiresJsEnabled) throws Throwable {
-            mAwContents = awContents;
+            mAwContents = containerView.getAwContents();
+            mContext = containerView.getContext();
             mContentViewClient = contentViewClient;
-            mAwSettings = AwSettingsTest.this.getAwSettingsOnUiThread(awContents);
+            mAwSettings = AwSettingsTest.this.getAwSettingsOnUiThread(mAwContents);
             if (requiresJsEnabled) {
                 mAwSettings.setJavaScriptEnabled(true);
             }
@@ -140,9 +142,9 @@
         private static final String JS_ENABLED_STRING = "JS Enabled";
         private static final String JS_DISABLED_STRING = "JS Disabled";
 
-        AwSettingsJavaScriptTestHelper(AwContents awContents,
+        AwSettingsJavaScriptTestHelper(AwTestContainerView containerView,
                                        TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, false);
+            super(containerView, contentViewClient, false);
         }
 
         @Override
@@ -184,9 +186,9 @@
     // JavaScript state.
     class AwSettingsJavaScriptDynamicTestHelper extends AwSettingsJavaScriptTestHelper {
         AwSettingsJavaScriptDynamicTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient);
+            super(containerView, contentViewClient);
             // Load the page.
             super.doEnsureSettingHasValue(getInitialValue());
         }
@@ -208,9 +210,9 @@
         private static final String PLUGINS_ENABLED_STRING = "Embed";
         private static final String PLUGINS_DISABLED_STRING = "NoEmbed";
 
-        AwSettingsPluginsTestHelper(AwContents awContents,
+        AwSettingsPluginsTestHelper(AwTestContainerView containerView,
                                     TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
         }
 
         @Override
@@ -249,9 +251,9 @@
 
     class AwSettingsStandardFontFamilyTestHelper extends AwSettingsTestHelper<String> {
         AwSettingsStandardFontFamilyTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
         }
 
         @Override
@@ -289,9 +291,9 @@
 
     class AwSettingsDefaultFontSizeTestHelper extends AwSettingsTestHelper<Integer> {
         AwSettingsDefaultFontSizeTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
         }
 
         @Override
@@ -331,10 +333,10 @@
         private ImagePageGenerator mGenerator;
 
         AwSettingsLoadImagesAutomaticallyTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient,
                 ImagePageGenerator generator) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mGenerator = generator;
         }
 
@@ -372,11 +374,11 @@
     class AwSettingsImagesEnabledHelper extends AwSettingsTestHelper<Boolean> {
 
         AwSettingsImagesEnabledHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient,
                 TestWebServer webServer,
                 ImagePageGenerator generator) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mWebServer = webServer;
             mGenerator = generator;
         }
@@ -420,9 +422,9 @@
 
     class AwSettingsDefaultTextEncodingTestHelper extends AwSettingsTestHelper<String> {
         AwSettingsDefaultTextEncodingTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
         }
 
         @Override
@@ -462,9 +464,9 @@
         private static final String CUSTOM_UA = "ChromeViewTest";
 
         AwSettingsUserAgentStringTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mDefaultUa = mAwSettings.getUserAgentString();
         }
 
@@ -513,9 +515,9 @@
         private static final String HAS_LOCAL_STORAGE = "Has localStorage";
 
         AwSettingsDomStorageEnabledTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
         }
 
@@ -556,9 +558,9 @@
         private static final String HAS_DATABASE = "Has database";
 
         AwSettingsDatabaseTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
         }
 
@@ -600,9 +602,9 @@
         private static final String ACCESS_DENIED_TITLE = "Exception";
 
         AwSettingsUniversalAccessFromFilesTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_CONTAINER_FILE));
             AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
             mIframeContainerUrl = UrlUtils.getTestFileUrl(TEST_CONTAINER_FILE);
@@ -653,9 +655,9 @@
         private static final String ACCESS_DENIED_TITLE = "Exception";
 
         AwSettingsFileAccessFromFilesIframeTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_CONTAINER_FILE));
             AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
             mIframeContainerUrl = UrlUtils.getTestFileUrl(TEST_CONTAINER_FILE);
@@ -703,9 +705,9 @@
         private static final String ACCESS_DENIED_TITLE = "Exception";
 
         AwSettingsFileAccessFromFilesXhrTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
             mXhrContainerUrl = UrlUtils.getTestFileUrl(TEST_FILE);
             mAwSettings.setAllowUniversalAccessFromFileURLs(false);
@@ -749,10 +751,10 @@
         private static final String ACCESS_GRANTED_TITLE = "Hello, World!";
 
         AwSettingsFileUrlAccessTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient,
                 int startIndex) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mIndex = startIndex;
             AwSettingsTest.assertFileIsReadable(UrlUtils.getTestFilePath(TEST_FILE));
         }
@@ -796,10 +798,10 @@
     class AwSettingsContentUrlAccessTestHelper extends AwSettingsTestHelper<Boolean> {
 
         AwSettingsContentUrlAccessTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient,
                 int index) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mTarget = "content_access_" + index;
         }
 
@@ -841,10 +843,10 @@
         private static final String TARGET = "content_from_file";
 
         AwSettingsContentUrlAccessFromFileTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient,
                 int index) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mIndex = index;
             mTempDir = getInstrumentation().getTargetContext().getCacheDir().getPath();
         }
@@ -903,9 +905,9 @@
         protected static final float PARAGRAPH_FONT_SIZE = 14.0f;
 
         AwSettingsTextAutosizingTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mNeedToWaitForFontSizeChange = false;
             loadDataSync(getData());
         }
@@ -938,9 +940,17 @@
         }
 
         protected String getData() {
+            DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(mContext);
+            int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
+            int layoutWidth = (int) (displayWidth * 2.5f); // Use 2.5 as autosizing layout tests do.
             StringBuilder sb = new StringBuilder();
             sb.append("<html>" +
-                    "<head><script>" +
+                    "<head>" +
+                    "<meta name=\"viewport\" content=\"width=" + layoutWidth + "\">" +
+                    "<style>" +
+                    "body { width: " + layoutWidth + "px; margin: 0; overflow-y: hidden; }" +
+                    "</style>" +
+                    "<script>" +
                     "function setTitleToActualFontSize() {" +
                     // parseFloat is used to trim out the "px" suffix.
                     "  document.title = parseFloat(getComputedStyle(" +
@@ -951,7 +961,7 @@
             sb.append(PARAGRAPH_FONT_SIZE);
             sb.append("px;\">");
             // Make the paragraph wide enough for being processed by the font autosizer.
-            for (int i = 0; i < 100; i++) {
+            for (int i = 0; i < 500; i++) {
                 sb.append("Hello, World! ");
             }
             sb.append("</p></body></html>");
@@ -966,9 +976,9 @@
                                               AwSettingsTextAutosizingTestHelper<LayoutAlgorithm> {
 
         AwSettingsLayoutAlgorithmTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient);
+            super(containerView, contentViewClient);
             // Font autosizing doesn't step in for narrow layout widths.
             mAwSettings.setUseWideViewPort(true);
         }
@@ -1012,9 +1022,9 @@
         private final float mInitialActualFontSize;
 
         AwSettingsTextZoomTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient);
+            super(containerView, contentViewClient);
             mInitialActualFontSize = getActualFontSize();
         }
 
@@ -1060,9 +1070,9 @@
         private final float mInitialActualFontSize;
 
         AwSettingsTextZoomAutosizingTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient);
+            super(containerView, contentViewClient);
             mAwSettings.setLayoutAlgorithm(LayoutAlgorithm.TEXT_AUTOSIZING);
             // The initial font size can be adjusted by font autosizer depending on the page's
             // viewport width.
@@ -1110,9 +1120,9 @@
         private static final String POPUP_BLOCKED = "Popup blocked";
 
         AwSettingsJavaScriptPopupsTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
         }
 
         @Override
@@ -1167,11 +1177,11 @@
     class AwSettingsCacheModeTestHelper extends AwSettingsTestHelper<Integer> {
 
         AwSettingsCacheModeTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient,
                 int index,
                 TestWebServer webServer) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mIndex = index;
             mWebServer = webServer;
         }
@@ -1225,9 +1235,9 @@
         private static final String VIEWPORT_TAG_LAYOUT_WIDTH = "3000";
 
         AwSettingsUseWideViewportTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
         }
 
         @Override
@@ -1273,10 +1283,10 @@
         private static final float DEFAULT_PAGE_SCALE = 1.0f;
 
         AwSettingsLoadWithOverviewModeTestHelper(
-                AwContents awContents,
+                AwTestContainerView containerView,
                 TestAwContentsClient contentViewClient,
                 boolean withViewPortTag) throws Throwable {
-            super(awContents, contentViewClient, true);
+            super(containerView, contentViewClient, true);
             mWithViewPortTag = withViewPortTag;
             mAwSettings.setUseWideViewPort(true);
         }
@@ -1368,8 +1378,8 @@
     public void testJavaScriptEnabledWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsJavaScriptTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsJavaScriptTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsJavaScriptTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsJavaScriptTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -1377,8 +1387,8 @@
     public void testJavaScriptEnabledDynamicWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsJavaScriptDynamicTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsJavaScriptDynamicTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsJavaScriptDynamicTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsJavaScriptDynamicTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -1386,8 +1396,8 @@
     public void testPluginsEnabledWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsPluginsTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsPluginsTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsPluginsTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsPluginsTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -1395,8 +1405,8 @@
     public void testStandardFontFamilyWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsStandardFontFamilyTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsStandardFontFamilyTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsStandardFontFamilyTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsStandardFontFamilyTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -1404,8 +1414,8 @@
     public void testDefaultFontSizeWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsDefaultFontSizeTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsDefaultFontSizeTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsDefaultFontSizeTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsDefaultFontSizeTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     // The test verifies that after changing the LoadsImagesAutomatically
@@ -1446,9 +1456,9 @@
         ViewPair views = createViews();
         runPerViewSettingsTest(
             new AwSettingsLoadImagesAutomaticallyTestHelper(
-                views.getContents0(), views.getClient0(), new ImagePageGenerator(0, true)),
+                views.getContainer0(), views.getClient0(), new ImagePageGenerator(0, true)),
             new AwSettingsLoadImagesAutomaticallyTestHelper(
-                views.getContents1(), views.getClient1(), new ImagePageGenerator(1, true)));
+                views.getContainer1(), views.getClient1(), new ImagePageGenerator(1, true)));
     }
 
     @SmallTest
@@ -1456,8 +1466,8 @@
     public void testDefaultTextEncodingWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsDefaultTextEncodingTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsDefaultTextEncodingTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsDefaultTextEncodingTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsDefaultTextEncodingTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     // The test verifies that the default user agent string follows the format
@@ -1572,8 +1582,8 @@
     public void testUserAgentStringWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsUserAgentStringTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsUserAgentStringTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsUserAgentStringTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsUserAgentStringTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -1616,8 +1626,8 @@
     public void testDomStorageEnabledWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsDomStorageEnabledTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsDomStorageEnabledTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsDomStorageEnabledTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsDomStorageEnabledTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     // Ideally, these three tests below should be combined into one, or tested using
@@ -1629,8 +1639,8 @@
         TestAwContentsClient client = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
                 createAwTestContainerViewOnMainSync(client);
-        final AwContents awContents = testContainerView.getAwContents();
-        AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client);
+        AwSettingsDatabaseTestHelper helper =
+                new AwSettingsDatabaseTestHelper(testContainerView, client);
         helper.ensureSettingHasInitialValue();
     }
 
@@ -1640,8 +1650,8 @@
         TestAwContentsClient client = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
                 createAwTestContainerViewOnMainSync(client);
-        final AwContents awContents = testContainerView.getAwContents();
-        AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client);
+        AwSettingsDatabaseTestHelper helper =
+                new AwSettingsDatabaseTestHelper(testContainerView, client);
         helper.setAlteredSettingValue();
         helper.ensureSettingHasAlteredValue();
     }
@@ -1652,8 +1662,8 @@
         TestAwContentsClient client = new TestAwContentsClient();
         final AwTestContainerView testContainerView =
                 createAwTestContainerViewOnMainSync(client);
-        final AwContents awContents = testContainerView.getAwContents();
-        AwSettingsDatabaseTestHelper helper = new AwSettingsDatabaseTestHelper(awContents, client);
+        AwSettingsDatabaseTestHelper helper =
+                new AwSettingsDatabaseTestHelper(testContainerView, client);
         helper.setInitialSettingValue();
         helper.ensureSettingHasInitialValue();
     }
@@ -1663,9 +1673,9 @@
     public void testUniversalAccessFromFilesWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsUniversalAccessFromFilesTestHelper(views.getContents0(),
+            new AwSettingsUniversalAccessFromFilesTestHelper(views.getContainer0(),
                 views.getClient0()),
-            new AwSettingsUniversalAccessFromFilesTestHelper(views.getContents1(),
+            new AwSettingsUniversalAccessFromFilesTestHelper(views.getContainer1(),
                 views.getClient1()));
     }
 
@@ -1696,9 +1706,9 @@
         ViewPair views = createViews();
         runPerViewSettingsTest(
             new AwSettingsFileAccessFromFilesIframeTestHelper(
-                views.getContents0(), views.getClient0()),
+                views.getContainer0(), views.getClient0()),
             new AwSettingsFileAccessFromFilesIframeTestHelper(
-                views.getContents1(), views.getClient1()));
+                views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -1706,9 +1716,9 @@
     public void testFileAccessFromFilesXhrWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContents0(),
+            new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContainer0(),
                 views.getClient0()),
-            new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContents1(),
+            new AwSettingsFileAccessFromFilesXhrTestHelper(views.getContainer1(),
                 views.getClient1()));
     }
 
@@ -1717,8 +1727,8 @@
     public void testFileUrlAccessWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsFileUrlAccessTestHelper(views.getContents0(), views.getClient0(), 0),
-            new AwSettingsFileUrlAccessTestHelper(views.getContents1(), views.getClient1(), 1));
+            new AwSettingsFileUrlAccessTestHelper(views.getContainer0(), views.getClient0(), 0),
+            new AwSettingsFileUrlAccessTestHelper(views.getContainer1(), views.getClient1(), 1));
     }
 
     @SmallTest
@@ -1726,8 +1736,8 @@
     public void testContentUrlAccessWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsContentUrlAccessTestHelper(views.getContents0(), views.getClient0(), 0),
-            new AwSettingsContentUrlAccessTestHelper(views.getContents1(), views.getClient1(), 1));
+            new AwSettingsContentUrlAccessTestHelper(views.getContainer0(), views.getClient0(), 0),
+            new AwSettingsContentUrlAccessTestHelper(views.getContainer1(), views.getClient1(), 1));
     }
 
     @SmallTest
@@ -1758,9 +1768,9 @@
         ViewPair views = createViews();
         runPerViewSettingsTest(
             new AwSettingsContentUrlAccessFromFileTestHelper(
-                    views.getContents0(), views.getClient0(), 0),
+                    views.getContainer0(), views.getClient0(), 0),
             new AwSettingsContentUrlAccessFromFileTestHelper(
-                    views.getContents1(), views.getClient1(), 1));
+                    views.getContainer1(), views.getClient1(), 1));
     }
 
     @SmallTest
@@ -1826,12 +1836,12 @@
             webServer = new TestWebServer(false);
             runPerViewSettingsTest(
                     new AwSettingsImagesEnabledHelper(
-                            views.getContents0(),
+                            views.getContainer0(),
                             views.getClient0(),
                             webServer,
                             new ImagePageGenerator(0, true)),
                     new AwSettingsImagesEnabledHelper(
-                            views.getContents1(),
+                            views.getContainer1(),
                             views.getClient1(),
                             webServer,
                             new ImagePageGenerator(1, true)));
@@ -2035,8 +2045,8 @@
     public void testLayoutAlgorithmWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsLayoutAlgorithmTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsLayoutAlgorithmTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsLayoutAlgorithmTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsLayoutAlgorithmTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -2044,8 +2054,8 @@
     public void testTextZoomWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsTextZoomTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsTextZoomTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsTextZoomTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsTextZoomTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -2053,8 +2063,8 @@
     public void testTextZoomAutosizingWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsTextZoomAutosizingTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsTextZoomAutosizingTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsTextZoomAutosizingTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsTextZoomAutosizingTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -2062,8 +2072,8 @@
     public void testJavaScriptPopupsWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsJavaScriptPopupsTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsJavaScriptPopupsTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsJavaScriptPopupsTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsJavaScriptPopupsTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -2172,9 +2182,9 @@
             webServer = new TestWebServer(false);
             runPerViewSettingsTest(
                     new AwSettingsCacheModeTestHelper(
-                            views.getContents0(), views.getClient0(), 0, webServer),
+                            views.getContainer0(), views.getClient0(), 0, webServer),
                     new AwSettingsCacheModeTestHelper(
-                            views.getContents1(), views.getClient1(), 1, webServer));
+                            views.getContainer1(), views.getClient1(), 1, webServer));
         } finally {
             if (webServer != null) webServer.shutdown();
         }
@@ -2331,8 +2341,8 @@
     public void testUseWideViewportWithTwoViews() throws Throwable {
         ViewPair views = createViews();
         runPerViewSettingsTest(
-            new AwSettingsUseWideViewportTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsUseWideViewportTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     @SmallTest
@@ -2340,12 +2350,14 @@
     public void testUseWideViewportWithTwoViewsNoQuirks() throws Throwable {
         ViewPair views = createViews(false);
         runPerViewSettingsTest(
-            new AwSettingsUseWideViewportTestHelper(views.getContents0(), views.getClient0()),
-            new AwSettingsUseWideViewportTestHelper(views.getContents1(), views.getClient1()));
+            new AwSettingsUseWideViewportTestHelper(views.getContainer0(), views.getClient0()),
+            new AwSettingsUseWideViewportTestHelper(views.getContainer1(), views.getClient1()));
     }
 
     private void useWideViewportLayoutWidthTest(
-            final AwContents awContents, CallbackHelper onPageFinishedHelper) throws Throwable {
+            AwTestContainerView testContainer, CallbackHelper onPageFinishedHelper)
+            throws Throwable {
+        final AwContents awContents = testContainer.getAwContents();
         AwSettings settings = getAwSettingsOnUiThread(awContents);
 
         final String pageTemplate = "<html><head>%s</head>" +
@@ -2359,8 +2371,7 @@
                 pageTemplate,
                 "<meta name='viewport' content='width=" + viewportTagSpecifiedWidth + "' />");
 
-        DeviceDisplayInfo deviceInfo =
-                DeviceDisplayInfo.create(getInstrumentation().getTargetContext());
+        DeviceDisplayInfo deviceInfo = DeviceDisplayInfo.create(testContainer.getContext());
         int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
 
         settings.setJavaScriptEnabled(true);
@@ -2405,8 +2416,7 @@
         TestAwContentsClient contentClient = new TestAwContentsClient();
         AwTestContainerView testContainerView =
                 createAwTestContainerViewOnMainSync(contentClient);
-        useWideViewportLayoutWidthTest(testContainerView.getAwContents(),
-                contentClient.getOnPageFinishedHelper());
+        useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper());
     }
 
     @SmallTest
@@ -2415,8 +2425,7 @@
         TestAwContentsClient contentClient = new TestAwContentsClient();
         AwTestContainerView testContainerView =
                 createAwTestContainerViewOnMainSync(contentClient, false);
-        useWideViewportLayoutWidthTest(testContainerView.getAwContents(),
-                contentClient.getOnPageFinishedHelper());
+        useWideViewportLayoutWidthTest(testContainerView, contentClient.getOnPageFinishedHelper());
     }
 
     @MediumTest
@@ -2430,8 +2439,18 @@
         AwSettings settings = getAwSettingsOnUiThread(awContents);
         settings.setBuiltInZoomControls(true);
 
-        final String page = "<html><body>Page Text</body></html>";
+        DeviceDisplayInfo deviceInfo =
+                DeviceDisplayInfo.create(testContainerView.getContext());
+        int displayWidth = (int) (deviceInfo.getDisplayWidth() / deviceInfo.getDIPScale());
+        int layoutWidth = displayWidth * 2;
+        final String page = "<html>" +
+                "<head><meta name='viewport' content='width=" + layoutWidth + "'>" +
+                "<style> body { width: " + layoutWidth + "px; }</style></head>" +
+                "<body>Page Text</body></html>";
+
         assertFalse(settings.getUseWideViewPort());
+        // Without wide viewport the <meta viewport> tag will be ignored by WebView,
+        // but it doesn't really matter as we don't expect double tap to change the scale.
         loadDataSync(awContents, onPageFinishedHelper, page, "text/html", false);
         final float initialScale = getScaleOnUiThread(awContents);
         simulateDoubleTapCenterOfWebViewOnUiThread(testContainerView);
@@ -2454,9 +2473,9 @@
         ViewPair views = createViews();
         runPerViewSettingsTest(
                 new AwSettingsLoadWithOverviewModeTestHelper(
-                        views.getContents0(), views.getClient0(), false),
+                        views.getContainer0(), views.getClient0(), false),
                 new AwSettingsLoadWithOverviewModeTestHelper(
-                        views.getContents1(), views.getClient1(), false));
+                        views.getContainer1(), views.getClient1(), false));
     }
 
     @SmallTest
@@ -2465,9 +2484,9 @@
         ViewPair views = createViews();
         runPerViewSettingsTest(
                 new AwSettingsLoadWithOverviewModeTestHelper(
-                        views.getContents0(), views.getClient0(), true),
+                        views.getContainer0(), views.getClient0(), true),
                 new AwSettingsLoadWithOverviewModeTestHelper(
-                        views.getContents1(), views.getClient1(), true));
+                        views.getContainer1(), views.getClient1(), true));
     }
 
     @SmallTest
@@ -2615,33 +2634,41 @@
     }
 
     static class ViewPair {
-        private final AwContents contents0;
-        private final TestAwContentsClient client0;
-        private final AwContents contents1;
-        private final TestAwContentsClient client1;
+        private final AwTestContainerView mContainer0;
+        private final TestAwContentsClient mClient0;
+        private final AwTestContainerView mContainer1;
+        private final TestAwContentsClient mClient1;
 
-        ViewPair(AwContents contents0, TestAwContentsClient client0,
-                 AwContents contents1, TestAwContentsClient client1) {
-            this.contents0 = contents0;
-            this.client0 = client0;
-            this.contents1 = contents1;
-            this.client1 = client1;
+        ViewPair(AwTestContainerView container0, TestAwContentsClient client0,
+                 AwTestContainerView container1, TestAwContentsClient client1) {
+            this.mContainer0 = container0;
+            this.mClient0 = client0;
+            this.mContainer1 = container1;
+            this.mClient1 = client1;
+        }
+
+        AwTestContainerView getContainer0() {
+            return mContainer0;
         }
 
         AwContents getContents0() {
-            return contents0;
+            return mContainer0.getAwContents();
         }
 
         TestAwContentsClient getClient0() {
-            return client0;
+            return mClient0;
+        }
+
+        AwTestContainerView getContainer1() {
+            return mContainer1;
         }
 
         AwContents getContents1() {
-            return contents1;
+            return mContainer1.getAwContents();
         }
 
         TestAwContentsClient getClient1() {
-            return client1;
+            return mClient1;
         }
     }
 
@@ -2702,9 +2729,9 @@
         TestAwContentsClient client0 = new TestAwContentsClient();
         TestAwContentsClient client1 = new TestAwContentsClient();
         return new ViewPair(
-            createAwTestContainerViewOnMainSync(client0, supportsLegacyQuirks).getAwContents(),
+            createAwTestContainerViewOnMainSync(client0, supportsLegacyQuirks),
             client0,
-            createAwTestContainerViewOnMainSync(client1, supportsLegacyQuirks).getAwContents(),
+            createAwTestContainerViewOnMainSync(client1, supportsLegacyQuirks),
             client1);
     }
 
diff --git a/android_webview/lib/main/aw_main_delegate.cc b/android_webview/lib/main/aw_main_delegate.cc
index a9573a1..967fea3 100644
--- a/android_webview/lib/main/aw_main_delegate.cc
+++ b/android_webview/lib/main/aw_main_delegate.cc
@@ -8,7 +8,6 @@
 #include "android_webview/browser/gpu_memory_buffer_factory_impl.h"
 #include "android_webview/browser/hardware_renderer.h"
 #include "android_webview/browser/scoped_allow_wait_for_legacy_web_view_api.h"
-#include "android_webview/common/aw_switches.h"
 #include "android_webview/lib/aw_browser_dependency_factory_impl.h"
 #include "android_webview/native/aw_geolocation_permission_context.h"
 #include "android_webview/native/aw_quota_manager_bridge_impl.h"
diff --git a/android_webview/libwebviewchromium.target.darwin-arm.mk b/android_webview/libwebviewchromium.target.darwin-arm.mk
index 1abeafe..59ef5db 100644
--- a/android_webview/libwebviewchromium.target.darwin-arm.mk
+++ b/android_webview/libwebviewchromium.target.darwin-arm.mk
@@ -185,6 +185,8 @@
 	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -317,6 +319,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -407,6 +410,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -607,6 +611,8 @@
 	ui_native_theme_native_theme_gyp \
 	content_content_gpu_gyp \
 	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
 	net_http_server_gyp \
 	ui_surface_surface_gyp \
 	printing_printing_gyp \
diff --git a/android_webview/libwebviewchromium.target.darwin-mips.mk b/android_webview/libwebviewchromium.target.darwin-mips.mk
index 773e7a3..0b0a54b 100644
--- a/android_webview/libwebviewchromium.target.darwin-mips.mk
+++ b/android_webview/libwebviewchromium.target.darwin-mips.mk
@@ -183,6 +183,8 @@
 	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -311,6 +313,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -400,6 +403,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -593,6 +597,8 @@
 	ui_native_theme_native_theme_gyp \
 	content_content_gpu_gyp \
 	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
 	net_http_server_gyp \
 	ui_surface_surface_gyp \
 	printing_printing_gyp \
diff --git a/android_webview/libwebviewchromium.target.darwin-x86.mk b/android_webview/libwebviewchromium.target.darwin-x86.mk
index 3c04e23..ab4dbe5 100644
--- a/android_webview/libwebviewchromium.target.darwin-x86.mk
+++ b/android_webview/libwebviewchromium.target.darwin-x86.mk
@@ -189,6 +189,8 @@
 	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -322,6 +324,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -412,6 +415,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -610,6 +614,8 @@
 	ui_native_theme_native_theme_gyp \
 	content_content_gpu_gyp \
 	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
 	net_http_server_gyp \
 	ui_surface_surface_gyp \
 	printing_printing_gyp \
diff --git a/android_webview/libwebviewchromium.target.darwin-x86_64.mk b/android_webview/libwebviewchromium.target.darwin-x86_64.mk
new file mode 100644
index 0000000..499a7ed
--- /dev/null
+++ b/android_webview/libwebviewchromium.target.darwin-x86_64.mk
@@ -0,0 +1,666 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE := libwebviewchromium
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,android_webview_android_webview_common_gyp)/android_webview_android_webview_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,android_webview_native_webview_native_gyp)/android_webview_native_webview_native_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_static_gyp)/base_base_static_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_third_party_dynamic_annotations_dynamic_annotations_gyp)/base_third_party_dynamic_annotations_dynamic_annotations_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,cc_cc_gyp)/cc_cc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_gyp)/base_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_allocator_allocator_extension_thunks_gyp)/base_allocator_allocator_extension_thunks_gyp.a \
+	$(call intermediates-dir-for,GYP,testing_gtest_prod_gyp)/gtest_prod.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_modp_b64_modp_b64_gyp)/third_party_modp_b64_modp_b64_gyp.a \
+	$(call intermediates-dir-for,GYP,base_base_jni_headers_gyp)/base_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_ashmem_ashmem_gyp)/ashmem.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libevent_libevent_gyp)/third_party_libevent_libevent_gyp.a \
+	$(call intermediates-dir-for,GYP,gpu_gpu_gyp)/gpu.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_client_gyp)/gpu_command_buffer_client_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_gles2_utils_gyp)/gpu_command_buffer_gles2_utils_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_disk_cache_proto_gyp)/gpu_disk_cache_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_protobuf_protobuf_lite_gyp)/third_party_protobuf_protobuf_lite_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,crypto_crypto_gyp)/crypto_crypto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_openssl_openssl_gyp)/third_party_openssl_openssl_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_re2_re2_gyp)/third_party_re2_re2_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_smhasher_cityhash_gyp)/third_party_smhasher_cityhash_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gfx_gfx_gyp)/ui_gfx_gfx_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_i18n_gyp)/base_base_i18n_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_system_icu_gyp)/system_icu.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_ssse3_gyp)/skia_skia_opts_ssse3_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_sfntly_sfntly_gyp)/third_party_sfntly_sfntly_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libpng_libpng_gyp)/third_party_libpng_libpng_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_opts_gyp)/skia_skia_chrome_opts_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gfx_gfx_geometry_gyp)/ui_gfx_gfx_geometry_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_libjpeg_libjpeg_gyp)/libjpeg.stamp \
+	$(call intermediates-dir-for,GYP,ui_gfx_gfx_jni_headers_gyp)/gfx_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_mesa_mesa_headers_gyp)/mesa_headers.stamp \
+	$(call intermediates-dir-for,GYP,ui_gl_gl_jni_headers_gyp)/gl_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,ui_gl_surface_jni_headers_gyp)/surface_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_angle_src_translator_gyp)/third_party_angle_src_translator_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_angle_src_preprocessor_gyp)/third_party_angle_src_preprocessor_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ipc_ipc_gyp)/ipc_ipc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_gyp)/media_media_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_opus_opus_gyp)/third_party_opus_opus_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_events_base_gyp)/ui_events_events_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_dom4_keycode_converter_gyp)/ui_events_dom4_keycode_converter_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,url_url_lib_gyp)/url_url_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_shared_memory_support_gyp)/media_shared_memory_support_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_shared_memory_support_sse_gyp)/media_shared_memory_support_sse_gyp.a \
+	$(call intermediates-dir-for,GYP,media_media_android_jni_headers_gyp)/media_android_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_player_android_gyp)/media_player_android_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_widevine_cdm_widevine_cdm_version_h_gyp)/widevine_cdm_version_h.stamp \
+	$(call intermediates-dir-for,GYP,media_video_capture_android_jni_headers_gyp)/video_capture_android_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_asm_gyp)/media_media_asm_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_mmx_gyp)/media_media_mmx_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_sse_gyp)/media_media_sse_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_sse2_gyp)/media_media_sse2_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_browser_gyp)/components_autofill_content_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_prefs_gyp)/base_base_prefs_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_browser_gyp)/content_content_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_common_gyp)/content_content_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_tracing_gyp)/components_tracing_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,net_net_gyp)/net_net_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sdch_sdch_gyp)/sdch_sdch_gyp.a \
+	$(call intermediates-dir-for,GYP,net_net_resources_gyp)/net_resources.stamp \
+	$(call intermediates-dir-for,GYP,net_net_jni_headers_gyp)/net_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libjingle_libjingle_gyp)/third_party_libjingle_libjingle_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libjingle_libjingle_p2p_constants_gyp)/third_party_libjingle_libjingle_p2p_constants_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,tools_json_schema_compiler_api_gen_util_gyp)/tools_json_schema_compiler_api_gen_util_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,ui_base_strings_ui_strings_gyp)/ui_strings.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_events_gyp)/ui_events_events_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_base_ui_base_jni_headers_gyp)/ui_base_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_shell_dialogs_shell_dialogs_gyp)/ui_shell_dialogs_shell_dialogs_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_c_lib_gyp)/gpu_gles2_c_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_implementation_gyp)/gpu_gles2_implementation_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_skia_bindings_gpu_skia_bindings_gyp)/gpu_skia_bindings_gpu_skia_bindings_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_platform_blink_platform_gyp)/third_party_WebKit_Source_platform_blink_platform_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_config_gyp)/config.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_wtf_wtf_gyp)/third_party_WebKit_Source_wtf_wtf_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_wtf_wtf_config_gyp)/wtf_config.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_platform_blink_common_gyp)/third_party_WebKit_Source_platform_blink_common_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_platform_blink_prerequisites_gyp)/blink_prerequisites.stamp \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_gyp)/webp.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dec_gyp)/third_party_libwebp_libwebp_dec_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dsp_gyp)/third_party_libwebp_libwebp_dsp_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_dsp_neon_gyp)/libwebp_dsp_neon.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_utils_gyp)/third_party_libwebp_libwebp_utils_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_demux_gyp)/third_party_libwebp_libwebp_demux_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_enc_gyp)/third_party_libwebp_libwebp_enc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_ots_ots_gyp)/third_party_ots_ots_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_brotli_brotli_gyp)/third_party_brotli_brotli_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_qcms_qcms_gyp)/third_party_qcms_qcms_gyp.a \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,v8_tools_gyp_v8_base_x64_gyp)/v8_tools_gyp_v8_base_x64_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,v8_tools_gyp_v8_snapshot_gyp)/v8_tools_gyp_v8_snapshot_gyp.a \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_js2c_host_gyp,true)/js2c.stamp \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_generate_trig_table_host_gyp,true)/generate_trig_table.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_platform_make_platform_generated_gyp)/make_platform_generated.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_iccjpeg_iccjpeg_gyp)/third_party_iccjpeg_iccjpeg_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_harfbuzz_ng_harfbuzz_ng_gyp)/third_party_harfbuzz_ng_harfbuzz_ng_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_web_blink_web_gyp)/third_party_WebKit_Source_web_blink_web_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_webcore_gyp)/webcore.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_dom_gyp)/third_party_WebKit_Source_core_webcore_dom_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_webcore_prerequisites_gyp)/webcore_prerequisites.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_debugger_script_source_gyp)/debugger_script_source.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_injected_canvas_script_source_gyp)/injected_canvas_script_source.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_injected_script_source_gyp)/injected_script_source.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_inspector_overlay_page_gyp)/inspector_overlay_page.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_inspector_protocol_sources_gyp)/inspector_protocol_sources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_generate_inspector_protocol_version_gyp)/generate_inspector_protocol_version.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_inspector_instrumentation_sources_gyp)/inspector_instrumentation_sources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_generated_bindings_gyp)/generated_bindings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_aggregate_generated_bindings_gyp)/aggregate_generated_bindings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_event_interfaces_gyp)/event_interfaces.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_interfaces_info_gyp)/interfaces_info.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_global_constructors_idls_gyp)/global_constructors_idls.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_generated_testing_idls_gyp)/generated_testing_idls.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_individual_generated_bindings_gyp)/individual_generated_bindings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_cached_yacc_tables_gyp)/cached_yacc_tables.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_cached_jinja_templates_gyp)/cached_jinja_templates.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_make_core_generated_gyp)/make_core_generated.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_heap_blink_heap_gyp)/third_party_WebKit_Source_heap_blink_heap_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_heap_blink_heap_asm_stubs_gyp)/third_party_WebKit_Source_heap_blink_heap_asm_stubs_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libxml_libxml_gyp)/third_party_libxml_libxml_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libxslt_libxslt_gyp)/third_party_libxslt_libxslt_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_sqlite_sqlite_gyp)/third_party_sqlite_sqlite_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_html_gyp)/third_party_WebKit_Source_core_webcore_html_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_remaining_gyp)/third_party_WebKit_Source_core_webcore_remaining_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_rendering_gyp)/third_party_WebKit_Source_core_webcore_rendering_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_svg_gyp)/third_party_WebKit_Source_core_webcore_svg_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_generated_gyp)/third_party_WebKit_Source_core_webcore_generated_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gin_gin_gyp)/gin_gin_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_minimal_gyp)/blink_minimal.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_webkit_common_gyp)/webkit_common_webkit_common_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_webkit_storage_browser_gyp)/webkit_webkit_storage_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sql_sql_gyp)/sql_sql_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_leveldatabase_leveldatabase_gyp)/third_party_leveldatabase_leveldatabase_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_webkit_storage_common_gyp)/webkit_webkit_storage_common_gyp.a \
+	$(call intermediates-dir-for,GYP,content_webkit_version_gyp)/webkit_version.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_motionevent_jni_headers_gyp)/motionevent_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,google_apis_google_apis_gyp)/google_apis_google_apis_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_google_zip_gyp)/third_party_zlib_google_zip_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_minizip_gyp)/third_party_zlib_minizip_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_gesture_detection_gyp)/ui_events_gesture_detection_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_child_webkit_child_gyp)/webkit_child_webkit_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
+	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_devtools_html_gyp)/devtools_html.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_devtools_extension_api_gyp)/devtools_extension_api.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_js_gyp)/concatenated_devtools_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_supported_css_properties_gyp)/supported_css_properties.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_frontend_protocol_sources_gyp)/frontend_protocol_sources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_console_js_gyp)/concatenated_devtools_console_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_elements_js_gyp)/concatenated_devtools_elements_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_resources_js_gyp)/concatenated_devtools_resources_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_network_js_gyp)/concatenated_devtools_network_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_extensions_js_gyp)/concatenated_devtools_extensions_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_scripts_js_gyp)/concatenated_devtools_scripts_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_timeline_js_gyp)/concatenated_devtools_timeline_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_profiles_js_gyp)/concatenated_devtools_profiles_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_audits_js_gyp)/concatenated_devtools_audits_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_codemirror_js_gyp)/concatenated_devtools_codemirror_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_layers_js_gyp)/concatenated_devtools_layers_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_heap_snapshot_worker_js_gyp)/concatenated_heap_snapshot_worker_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_temp_storage_shared_worker_js_gyp)/concatenated_temp_storage_shared_worker_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_angle_src_commit_id_gyp)/commit_id.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
+	$(call intermediates-dir-for,GYP,printing_printing_jni_headers_gyp)/printing_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_services_headers_gyp)/sandbox_services_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_helpers_gyp)/sandbox_seccomp_bpf_helpers_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_gyp)/third_party_libphonenumber_libphonenumber_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_common_gyp)/components_autofill_content_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_core_common_gyp)/components_autofill_core_common_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_jni_headers_gyp)/autofill_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_risk_proto_gyp)/components_autofill_content_risk_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_core_browser_gyp)/components_autofill_core_browser_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_regexes_gyp)/autofill_regexes.stamp \
+	$(call intermediates-dir-for,GYP,components_components_resources_gyp)/components_resources.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_os_crypt_gyp)/components_os_crypt_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_user_prefs_gyp)/components_user_prefs_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_webdata_common_gyp)/components_webdata_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_web_contents_delegate_android_gyp)/components_web_contents_delegate_android_gyp.a \
+	$(call intermediates-dir-for,GYP,components_web_contents_delegate_android_jni_headers_gyp)/web_contents_delegate_android_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_android_webview_native_jni_gyp)/android_webview_native_jni.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_input_stream_android_jar_jni_headers_gyp)/input_stream_android_jar_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_cancellation_signal_android_jar_jni_headers_gyp)/cancellation_signal_android_jar_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_auto_login_parser_gyp)/components_auto_login_parser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_renderer_gyp)/components_autofill_content_renderer_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_renderer_gyp)/content_content_renderer_gyp.a \
+	$(call intermediates-dir-for,GYP,jingle_jingle_glue_gyp)/jingle_glue.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_navigation_interception_gyp)/components_navigation_interception_gyp.a \
+	$(call intermediates-dir-for,GYP,components_navigation_interception_jni_headers_gyp)/navigation_interception_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_visitedlink_browser_gyp)/components_visitedlink_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_visitedlink_common_gyp)/components_visitedlink_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_visitedlink_renderer_gyp)/components_visitedlink_renderer_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_app_both_gyp)/content_content_app_both_gyp.a \
+	$(call intermediates-dir-for,GYP,android_webview_android_webview_pak_gyp)/android_webview_pak.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	android_webview/lib/main/webview_entry_point.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,--no-fatal-warnings \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-shared,-Bsymbolic \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,--no-fatal-warnings \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-shared,-Bsymbolic \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	android_webview_android_webview_common_gyp \
+	android_webview_native_webview_native_gyp \
+	base_base_static_gyp \
+	base_third_party_dynamic_annotations_dynamic_annotations_gyp \
+	cc_cc_gyp \
+	base_base_gyp \
+	base_allocator_allocator_extension_thunks_gyp \
+	third_party_modp_b64_modp_b64_gyp \
+	third_party_libevent_libevent_gyp \
+	gpu_command_buffer_client_gyp \
+	gpu_command_buffer_common_gyp \
+	gpu_command_buffer_gles2_utils_gyp \
+	gpu_command_buffer_service_gyp \
+	gpu_disk_cache_proto_gyp \
+	third_party_protobuf_protobuf_lite_gyp \
+	crypto_crypto_gyp \
+	third_party_openssl_openssl_gyp \
+	third_party_re2_re2_gyp \
+	third_party_smhasher_cityhash_gyp \
+	ui_gfx_gfx_gyp \
+	base_base_i18n_gyp \
+	skia_skia_library_gyp \
+	skia_skia_opts_gyp \
+	skia_skia_opts_ssse3_gyp \
+	third_party_zlib_zlib_gyp \
+	third_party_sfntly_sfntly_gyp \
+	third_party_freetype_ft2_gyp \
+	third_party_libpng_libpng_gyp \
+	skia_skia_chrome_gyp \
+	skia_skia_chrome_opts_gyp \
+	ui_gfx_gfx_geometry_gyp \
+	ui_gl_gl_gyp \
+	third_party_angle_src_translator_gyp \
+	third_party_angle_src_preprocessor_gyp \
+	gpu_gles2_cmd_helper_gyp \
+	gpu_gpu_config_gyp \
+	gpu_gpu_ipc_gyp \
+	ipc_ipc_gyp \
+	media_media_gyp \
+	third_party_opus_opus_gyp \
+	ui_events_events_base_gyp \
+	ui_events_dom4_keycode_converter_gyp \
+	url_url_lib_gyp \
+	media_shared_memory_support_gyp \
+	media_shared_memory_support_sse_gyp \
+	media_player_android_gyp \
+	media_media_asm_gyp \
+	media_media_mmx_gyp \
+	media_media_sse_gyp \
+	media_media_sse2_gyp \
+	components_autofill_content_browser_gyp \
+	base_base_prefs_gyp \
+	content_content_browser_gyp \
+	content_content_common_gyp \
+	components_tracing_gyp \
+	net_net_gyp \
+	sdch_sdch_gyp \
+	third_party_libjingle_libjingle_gyp \
+	third_party_libjingle_libjingle_p2p_constants_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	tools_json_schema_compiler_api_gen_util_gyp \
+	ui_base_ui_base_gyp \
+	ui_events_events_gyp \
+	ui_shell_dialogs_shell_dialogs_gyp \
+	gpu_gles2_c_lib_gyp \
+	gpu_gles2_implementation_gyp \
+	gpu_skia_bindings_gpu_skia_bindings_gyp \
+	third_party_WebKit_Source_platform_blink_platform_gyp \
+	third_party_WebKit_Source_wtf_wtf_gyp \
+	third_party_WebKit_Source_platform_blink_common_gyp \
+	third_party_libwebp_libwebp_dec_gyp \
+	third_party_libwebp_libwebp_dsp_gyp \
+	third_party_libwebp_libwebp_utils_gyp \
+	third_party_libwebp_libwebp_demux_gyp \
+	third_party_libwebp_libwebp_enc_gyp \
+	third_party_ots_ots_gyp \
+	third_party_brotli_brotli_gyp \
+	third_party_qcms_qcms_gyp \
+	v8_tools_gyp_v8_base_x64_gyp \
+	v8_tools_gyp_v8_snapshot_gyp \
+	third_party_iccjpeg_iccjpeg_gyp \
+	third_party_harfbuzz_ng_harfbuzz_ng_gyp \
+	third_party_WebKit_Source_web_blink_web_gyp \
+	third_party_WebKit_Source_core_webcore_dom_gyp \
+	third_party_WebKit_Source_heap_blink_heap_gyp \
+	third_party_WebKit_Source_heap_blink_heap_asm_stubs_gyp \
+	third_party_libxml_libxml_gyp \
+	third_party_libxslt_libxslt_gyp \
+	third_party_sqlite_sqlite_gyp \
+	third_party_WebKit_Source_core_webcore_html_gyp \
+	third_party_WebKit_Source_core_webcore_remaining_gyp \
+	third_party_WebKit_Source_core_webcore_rendering_gyp \
+	third_party_WebKit_Source_core_webcore_svg_gyp \
+	third_party_WebKit_Source_core_webcore_generated_gyp \
+	gin_gin_gyp \
+	third_party_WebKit_Source_modules_modules_gyp \
+	webkit_common_gpu_webkit_gpu_gyp \
+	webkit_common_webkit_common_gyp \
+	webkit_webkit_storage_browser_gyp \
+	sql_sql_gyp \
+	third_party_leveldatabase_leveldatabase_gyp \
+	webkit_webkit_storage_common_gyp \
+	google_apis_google_apis_gyp \
+	third_party_zlib_google_zip_gyp \
+	third_party_zlib_minizip_gyp \
+	ui_events_gesture_detection_gyp \
+	ui_snapshot_snapshot_gyp \
+	content_browser_speech_proto_speech_proto_gyp \
+	content_content_child_gyp \
+	webkit_child_webkit_child_gyp \
+	ui_native_theme_native_theme_gyp \
+	content_content_gpu_gyp \
+	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
+	net_http_server_gyp \
+	ui_surface_surface_gyp \
+	printing_printing_gyp \
+	sandbox_sandbox_services_gyp \
+	sandbox_seccomp_bpf_gyp \
+	sandbox_seccomp_bpf_helpers_gyp \
+	third_party_libphonenumber_libphonenumber_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp \
+	components_autofill_content_common_gyp \
+	components_autofill_core_common_gyp \
+	components_autofill_content_risk_proto_gyp \
+	components_autofill_core_browser_gyp \
+	components_os_crypt_gyp \
+	components_user_prefs_gyp \
+	components_webdata_common_gyp \
+	components_web_contents_delegate_android_gyp \
+	components_auto_login_parser_gyp \
+	components_autofill_content_renderer_gyp \
+	content_content_renderer_gyp \
+	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
+	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
+	components_navigation_interception_gyp \
+	components_visitedlink_browser_gyp \
+	components_visitedlink_common_gyp \
+	components_visitedlink_renderer_gyp \
+	content_content_app_both_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	liblog \
+	libcutils \
+	libandroid \
+	libjnigraphics \
+	libicui18n \
+	libicuuc \
+	libexpat \
+	libjpeg \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: libwebviewchromium
+
+LOCAL_PRELINK_MODULE := false
+include $(BUILD_SHARED_LIBRARY)
diff --git a/android_webview/libwebviewchromium.target.linux-arm.mk b/android_webview/libwebviewchromium.target.linux-arm.mk
index 1abeafe..59ef5db 100644
--- a/android_webview/libwebviewchromium.target.linux-arm.mk
+++ b/android_webview/libwebviewchromium.target.linux-arm.mk
@@ -185,6 +185,8 @@
 	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -317,6 +319,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -407,6 +410,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -607,6 +611,8 @@
 	ui_native_theme_native_theme_gyp \
 	content_content_gpu_gyp \
 	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
 	net_http_server_gyp \
 	ui_surface_surface_gyp \
 	printing_printing_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-mips.mk b/android_webview/libwebviewchromium.target.linux-mips.mk
index 773e7a3..0b0a54b 100644
--- a/android_webview/libwebviewchromium.target.linux-mips.mk
+++ b/android_webview/libwebviewchromium.target.linux-mips.mk
@@ -183,6 +183,8 @@
 	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -311,6 +313,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -400,6 +403,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -593,6 +597,8 @@
 	ui_native_theme_native_theme_gyp \
 	content_content_gpu_gyp \
 	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
 	net_http_server_gyp \
 	ui_surface_surface_gyp \
 	printing_printing_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-x86.mk b/android_webview/libwebviewchromium.target.linux-x86.mk
index 3c04e23..ab4dbe5 100644
--- a/android_webview/libwebviewchromium.target.linux-x86.mk
+++ b/android_webview/libwebviewchromium.target.linux-x86.mk
@@ -189,6 +189,8 @@
 	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
 	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
 	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
 	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
@@ -322,6 +324,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -412,6 +415,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -610,6 +614,8 @@
 	ui_native_theme_native_theme_gyp \
 	content_content_gpu_gyp \
 	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
 	net_http_server_gyp \
 	ui_surface_surface_gyp \
 	printing_printing_gyp \
diff --git a/android_webview/libwebviewchromium.target.linux-x86_64.mk b/android_webview/libwebviewchromium.target.linux-x86_64.mk
new file mode 100644
index 0000000..499a7ed
--- /dev/null
+++ b/android_webview/libwebviewchromium.target.linux-x86_64.mk
@@ -0,0 +1,666 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MODULE := libwebviewchromium
+LOCAL_MODULE_SUFFIX := .so
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,android_webview_android_webview_common_gyp)/android_webview_android_webview_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,android_webview_native_webview_native_gyp)/android_webview_native_webview_native_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_static_gyp)/base_base_static_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_third_party_dynamic_annotations_dynamic_annotations_gyp)/base_third_party_dynamic_annotations_dynamic_annotations_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,cc_cc_gyp)/cc_cc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_gyp)/base_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_allocator_allocator_extension_thunks_gyp)/base_allocator_allocator_extension_thunks_gyp.a \
+	$(call intermediates-dir-for,GYP,testing_gtest_prod_gyp)/gtest_prod.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_modp_b64_modp_b64_gyp)/third_party_modp_b64_modp_b64_gyp.a \
+	$(call intermediates-dir-for,GYP,base_base_jni_headers_gyp)/base_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_ashmem_ashmem_gyp)/ashmem.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libevent_libevent_gyp)/third_party_libevent_libevent_gyp.a \
+	$(call intermediates-dir-for,GYP,gpu_gpu_gyp)/gpu.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_client_gyp)/gpu_command_buffer_client_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_gles2_utils_gyp)/gpu_command_buffer_gles2_utils_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_disk_cache_proto_gyp)/gpu_disk_cache_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_protobuf_protobuf_lite_gyp)/third_party_protobuf_protobuf_lite_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,crypto_crypto_gyp)/crypto_crypto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_openssl_openssl_gyp)/third_party_openssl_openssl_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_re2_re2_gyp)/third_party_re2_re2_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_smhasher_cityhash_gyp)/third_party_smhasher_cityhash_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gfx_gfx_gyp)/ui_gfx_gfx_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_i18n_gyp)/base_base_i18n_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_system_icu_gyp)/system_icu.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_gyp)/skia_skia_opts_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_opts_ssse3_gyp)/skia_skia_opts_ssse3_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_zlib_gyp)/third_party_zlib_zlib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_sfntly_sfntly_gyp)/third_party_sfntly_sfntly_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_freetype_ft2_gyp)/third_party_freetype_ft2_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libpng_libpng_gyp)/third_party_libpng_libpng_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_opts_gyp)/skia_skia_chrome_opts_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gfx_gfx_geometry_gyp)/ui_gfx_gfx_geometry_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_libjpeg_libjpeg_gyp)/libjpeg.stamp \
+	$(call intermediates-dir-for,GYP,ui_gfx_gfx_jni_headers_gyp)/gfx_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_mesa_mesa_headers_gyp)/mesa_headers.stamp \
+	$(call intermediates-dir-for,GYP,ui_gl_gl_jni_headers_gyp)/gl_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,ui_gl_surface_jni_headers_gyp)/surface_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_angle_src_translator_gyp)/third_party_angle_src_translator_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_angle_src_preprocessor_gyp)/third_party_angle_src_preprocessor_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ipc_ipc_gyp)/ipc_ipc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_gyp)/media_media_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_opus_opus_gyp)/third_party_opus_opus_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_events_base_gyp)/ui_events_events_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_dom4_keycode_converter_gyp)/ui_events_dom4_keycode_converter_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,url_url_lib_gyp)/url_url_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_shared_memory_support_gyp)/media_shared_memory_support_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_shared_memory_support_sse_gyp)/media_shared_memory_support_sse_gyp.a \
+	$(call intermediates-dir-for,GYP,media_media_android_jni_headers_gyp)/media_android_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_player_android_gyp)/media_player_android_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_widevine_cdm_widevine_cdm_version_h_gyp)/widevine_cdm_version_h.stamp \
+	$(call intermediates-dir-for,GYP,media_video_capture_android_jni_headers_gyp)/video_capture_android_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_asm_gyp)/media_media_asm_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_mmx_gyp)/media_media_mmx_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_sse_gyp)/media_media_sse_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,media_media_sse2_gyp)/media_media_sse2_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_browser_gyp)/components_autofill_content_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,base_base_prefs_gyp)/base_base_prefs_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_browser_gyp)/content_content_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_common_gyp)/content_content_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_tracing_gyp)/components_tracing_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,net_net_gyp)/net_net_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sdch_sdch_gyp)/sdch_sdch_gyp.a \
+	$(call intermediates-dir-for,GYP,net_net_resources_gyp)/net_resources.stamp \
+	$(call intermediates-dir-for,GYP,net_net_jni_headers_gyp)/net_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libjingle_libjingle_gyp)/third_party_libjingle_libjingle_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libjingle_libjingle_p2p_constants_gyp)/third_party_libjingle_libjingle_p2p_constants_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,tools_json_schema_compiler_api_gen_util_gyp)/tools_json_schema_compiler_api_gen_util_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,ui_base_strings_ui_strings_gyp)/ui_strings.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_events_gyp)/ui_events_events_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_base_ui_base_jni_headers_gyp)/ui_base_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_shell_dialogs_shell_dialogs_gyp)/ui_shell_dialogs_shell_dialogs_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_c_lib_gyp)/gpu_gles2_c_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_implementation_gyp)/gpu_gles2_implementation_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_skia_bindings_gpu_skia_bindings_gyp)/gpu_skia_bindings_gpu_skia_bindings_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_platform_blink_platform_gyp)/third_party_WebKit_Source_platform_blink_platform_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_config_gyp)/config.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_wtf_wtf_gyp)/third_party_WebKit_Source_wtf_wtf_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_wtf_wtf_config_gyp)/wtf_config.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_platform_blink_common_gyp)/third_party_WebKit_Source_platform_blink_common_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_platform_blink_prerequisites_gyp)/blink_prerequisites.stamp \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_gyp)/webp.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dec_gyp)/third_party_libwebp_libwebp_dec_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dsp_gyp)/third_party_libwebp_libwebp_dsp_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_dsp_neon_gyp)/libwebp_dsp_neon.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_utils_gyp)/third_party_libwebp_libwebp_utils_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_demux_gyp)/third_party_libwebp_libwebp_demux_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_enc_gyp)/third_party_libwebp_libwebp_enc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_ots_ots_gyp)/third_party_ots_ots_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_brotli_brotli_gyp)/third_party_brotli_brotli_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_qcms_qcms_gyp)/third_party_qcms_qcms_gyp.a \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,v8_tools_gyp_v8_base_x64_gyp)/v8_tools_gyp_v8_base_x64_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,v8_tools_gyp_v8_snapshot_gyp)/v8_tools_gyp_v8_snapshot_gyp.a \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_js2c_host_gyp,true)/js2c.stamp \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_generate_trig_table_host_gyp,true)/generate_trig_table.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_platform_make_platform_generated_gyp)/make_platform_generated.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_iccjpeg_iccjpeg_gyp)/third_party_iccjpeg_iccjpeg_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_harfbuzz_ng_harfbuzz_ng_gyp)/third_party_harfbuzz_ng_harfbuzz_ng_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_web_blink_web_gyp)/third_party_WebKit_Source_web_blink_web_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_webcore_gyp)/webcore.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_dom_gyp)/third_party_WebKit_Source_core_webcore_dom_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_webcore_prerequisites_gyp)/webcore_prerequisites.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_debugger_script_source_gyp)/debugger_script_source.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_injected_canvas_script_source_gyp)/injected_canvas_script_source.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_injected_script_source_gyp)/injected_script_source.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_inspector_overlay_page_gyp)/inspector_overlay_page.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_inspector_protocol_sources_gyp)/inspector_protocol_sources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_generate_inspector_protocol_version_gyp)/generate_inspector_protocol_version.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_inspector_instrumentation_sources_gyp)/inspector_instrumentation_sources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_generated_bindings_gyp)/generated_bindings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_aggregate_generated_bindings_gyp)/aggregate_generated_bindings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_event_interfaces_gyp)/event_interfaces.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_interfaces_info_gyp)/interfaces_info.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_global_constructors_idls_gyp)/global_constructors_idls.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_generated_testing_idls_gyp)/generated_testing_idls.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_individual_generated_bindings_gyp)/individual_generated_bindings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_cached_yacc_tables_gyp)/cached_yacc_tables.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_bindings_cached_jinja_templates_gyp)/cached_jinja_templates.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_core_make_core_generated_gyp)/make_core_generated.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_heap_blink_heap_gyp)/third_party_WebKit_Source_heap_blink_heap_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_heap_blink_heap_asm_stubs_gyp)/third_party_WebKit_Source_heap_blink_heap_asm_stubs_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libxml_libxml_gyp)/third_party_libxml_libxml_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libxslt_libxslt_gyp)/third_party_libxslt_libxslt_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_sqlite_sqlite_gyp)/third_party_sqlite_sqlite_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_html_gyp)/third_party_WebKit_Source_core_webcore_html_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_remaining_gyp)/third_party_WebKit_Source_core_webcore_remaining_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_rendering_gyp)/third_party_WebKit_Source_core_webcore_rendering_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_svg_gyp)/third_party_WebKit_Source_core_webcore_svg_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_core_webcore_generated_gyp)/third_party_WebKit_Source_core_webcore_generated_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gin_gin_gyp)/gin_gin_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_WebKit_Source_modules_modules_gyp)/third_party_WebKit_Source_modules_modules_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_minimal_gyp)/blink_minimal.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_gpu_webkit_gpu_gyp)/webkit_common_gpu_webkit_gpu_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_common_webkit_common_gyp)/webkit_common_webkit_common_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_webkit_storage_browser_gyp)/webkit_webkit_storage_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sql_sql_gyp)/sql_sql_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_leveldatabase_leveldatabase_gyp)/third_party_leveldatabase_leveldatabase_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_webkit_storage_common_gyp)/webkit_webkit_storage_common_gyp.a \
+	$(call intermediates-dir-for,GYP,content_webkit_version_gyp)/webkit_version.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_motionevent_jni_headers_gyp)/motionevent_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,google_apis_google_apis_gyp)/google_apis_google_apis_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_google_zip_gyp)/third_party_zlib_google_zip_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_zlib_minizip_gyp)/third_party_zlib_minizip_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_events_gesture_detection_gyp)/ui_events_gesture_detection_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_snapshot_snapshot_gyp)/ui_snapshot_snapshot_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_child_gyp)/content_content_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_child_webkit_child_gyp)/webkit_child_webkit_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_native_theme_native_theme_gyp)/ui_native_theme_native_theme_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_gpu_gyp)/content_content_gpu_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_utility_gyp)/content_content_utility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,courgette_courgette_lib_gyp)/courgette_courgette_lib_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_lzma_sdk_lzma_sdk_gyp)/third_party_lzma_sdk_lzma_sdk_gyp.a \
+	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_generate_devtools_grd_gyp)/generate_devtools_grd.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_devtools_html_gyp)/devtools_html.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_devtools_extension_api_gyp)/devtools_extension_api.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_js_gyp)/concatenated_devtools_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_supported_css_properties_gyp)/supported_css_properties.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_frontend_protocol_sources_gyp)/frontend_protocol_sources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_console_js_gyp)/concatenated_devtools_console_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_elements_js_gyp)/concatenated_devtools_elements_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_resources_js_gyp)/concatenated_devtools_resources_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_network_js_gyp)/concatenated_devtools_network_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_extensions_js_gyp)/concatenated_devtools_extensions_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_scripts_js_gyp)/concatenated_devtools_scripts_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_timeline_js_gyp)/concatenated_devtools_timeline_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_profiles_js_gyp)/concatenated_devtools_profiles_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_audits_js_gyp)/concatenated_devtools_audits_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_codemirror_js_gyp)/concatenated_devtools_codemirror_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_layers_js_gyp)/concatenated_devtools_layers_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_heap_snapshot_worker_js_gyp)/concatenated_heap_snapshot_worker_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_script_formatter_worker_js_gyp)/concatenated_script_formatter_worker_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_temp_storage_shared_worker_js_gyp)/concatenated_temp_storage_shared_worker_js.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_Source_devtools_concatenated_devtools_css_gyp)/concatenated_devtools_css.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,net_http_server_gyp)/net_http_server_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_surface_surface_gyp)/ui_surface_surface_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_angle_src_commit_id_gyp)/commit_id.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,printing_printing_gyp)/printing_printing_gyp.a \
+	$(call intermediates-dir-for,GYP,printing_printing_jni_headers_gyp)/printing_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_services_headers_gyp)/sandbox_services_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_helpers_gyp)/sandbox_seccomp_bpf_helpers_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_gyp)/third_party_libphonenumber_libphonenumber_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_common_gyp)/components_autofill_content_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_core_common_gyp)/components_autofill_core_common_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_jni_headers_gyp)/autofill_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_risk_proto_gyp)/components_autofill_content_risk_proto_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_core_browser_gyp)/components_autofill_core_browser_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_regexes_gyp)/autofill_regexes.stamp \
+	$(call intermediates-dir-for,GYP,components_components_resources_gyp)/components_resources.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_os_crypt_gyp)/components_os_crypt_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_user_prefs_gyp)/components_user_prefs_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_webdata_common_gyp)/components_webdata_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_web_contents_delegate_android_gyp)/components_web_contents_delegate_android_gyp.a \
+	$(call intermediates-dir-for,GYP,components_web_contents_delegate_android_jni_headers_gyp)/web_contents_delegate_android_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_android_webview_native_jni_gyp)/android_webview_native_jni.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_input_stream_android_jar_jni_headers_gyp)/input_stream_android_jar_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_cancellation_signal_android_jar_jni_headers_gyp)/cancellation_signal_android_jar_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_auto_login_parser_gyp)/components_auto_login_parser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_renderer_gyp)/components_autofill_content_renderer_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_renderer_gyp)/content_content_renderer_gyp.a \
+	$(call intermediates-dir-for,GYP,jingle_jingle_glue_gyp)/jingle_glue.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_renderer_compositor_bindings_webkit_compositor_support_gyp)/webkit_renderer_compositor_bindings_webkit_compositor_support_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_navigation_interception_gyp)/components_navigation_interception_gyp.a \
+	$(call intermediates-dir-for,GYP,components_navigation_interception_jni_headers_gyp)/navigation_interception_jni_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_visitedlink_browser_gyp)/components_visitedlink_browser_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_visitedlink_common_gyp)/components_visitedlink_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_visitedlink_renderer_gyp)/components_visitedlink_renderer_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_content_app_both_gyp)/content_content_app_both_gyp.a \
+	$(call intermediates-dir-for,GYP,android_webview_android_webview_pak_gyp)/android_webview_pak.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	android_webview/lib/main/webview_entry_point.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,--no-fatal-warnings \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-shared,-Bsymbolic \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,--no-fatal-warnings \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-shared,-Bsymbolic \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	android_webview_android_webview_common_gyp \
+	android_webview_native_webview_native_gyp \
+	base_base_static_gyp \
+	base_third_party_dynamic_annotations_dynamic_annotations_gyp \
+	cc_cc_gyp \
+	base_base_gyp \
+	base_allocator_allocator_extension_thunks_gyp \
+	third_party_modp_b64_modp_b64_gyp \
+	third_party_libevent_libevent_gyp \
+	gpu_command_buffer_client_gyp \
+	gpu_command_buffer_common_gyp \
+	gpu_command_buffer_gles2_utils_gyp \
+	gpu_command_buffer_service_gyp \
+	gpu_disk_cache_proto_gyp \
+	third_party_protobuf_protobuf_lite_gyp \
+	crypto_crypto_gyp \
+	third_party_openssl_openssl_gyp \
+	third_party_re2_re2_gyp \
+	third_party_smhasher_cityhash_gyp \
+	ui_gfx_gfx_gyp \
+	base_base_i18n_gyp \
+	skia_skia_library_gyp \
+	skia_skia_opts_gyp \
+	skia_skia_opts_ssse3_gyp \
+	third_party_zlib_zlib_gyp \
+	third_party_sfntly_sfntly_gyp \
+	third_party_freetype_ft2_gyp \
+	third_party_libpng_libpng_gyp \
+	skia_skia_chrome_gyp \
+	skia_skia_chrome_opts_gyp \
+	ui_gfx_gfx_geometry_gyp \
+	ui_gl_gl_gyp \
+	third_party_angle_src_translator_gyp \
+	third_party_angle_src_preprocessor_gyp \
+	gpu_gles2_cmd_helper_gyp \
+	gpu_gpu_config_gyp \
+	gpu_gpu_ipc_gyp \
+	ipc_ipc_gyp \
+	media_media_gyp \
+	third_party_opus_opus_gyp \
+	ui_events_events_base_gyp \
+	ui_events_dom4_keycode_converter_gyp \
+	url_url_lib_gyp \
+	media_shared_memory_support_gyp \
+	media_shared_memory_support_sse_gyp \
+	media_player_android_gyp \
+	media_media_asm_gyp \
+	media_media_mmx_gyp \
+	media_media_sse_gyp \
+	media_media_sse2_gyp \
+	components_autofill_content_browser_gyp \
+	base_base_prefs_gyp \
+	content_content_browser_gyp \
+	content_content_common_gyp \
+	components_tracing_gyp \
+	net_net_gyp \
+	sdch_sdch_gyp \
+	third_party_libjingle_libjingle_gyp \
+	third_party_libjingle_libjingle_p2p_constants_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	tools_json_schema_compiler_api_gen_util_gyp \
+	ui_base_ui_base_gyp \
+	ui_events_events_gyp \
+	ui_shell_dialogs_shell_dialogs_gyp \
+	gpu_gles2_c_lib_gyp \
+	gpu_gles2_implementation_gyp \
+	gpu_skia_bindings_gpu_skia_bindings_gyp \
+	third_party_WebKit_Source_platform_blink_platform_gyp \
+	third_party_WebKit_Source_wtf_wtf_gyp \
+	third_party_WebKit_Source_platform_blink_common_gyp \
+	third_party_libwebp_libwebp_dec_gyp \
+	third_party_libwebp_libwebp_dsp_gyp \
+	third_party_libwebp_libwebp_utils_gyp \
+	third_party_libwebp_libwebp_demux_gyp \
+	third_party_libwebp_libwebp_enc_gyp \
+	third_party_ots_ots_gyp \
+	third_party_brotli_brotli_gyp \
+	third_party_qcms_qcms_gyp \
+	v8_tools_gyp_v8_base_x64_gyp \
+	v8_tools_gyp_v8_snapshot_gyp \
+	third_party_iccjpeg_iccjpeg_gyp \
+	third_party_harfbuzz_ng_harfbuzz_ng_gyp \
+	third_party_WebKit_Source_web_blink_web_gyp \
+	third_party_WebKit_Source_core_webcore_dom_gyp \
+	third_party_WebKit_Source_heap_blink_heap_gyp \
+	third_party_WebKit_Source_heap_blink_heap_asm_stubs_gyp \
+	third_party_libxml_libxml_gyp \
+	third_party_libxslt_libxslt_gyp \
+	third_party_sqlite_sqlite_gyp \
+	third_party_WebKit_Source_core_webcore_html_gyp \
+	third_party_WebKit_Source_core_webcore_remaining_gyp \
+	third_party_WebKit_Source_core_webcore_rendering_gyp \
+	third_party_WebKit_Source_core_webcore_svg_gyp \
+	third_party_WebKit_Source_core_webcore_generated_gyp \
+	gin_gin_gyp \
+	third_party_WebKit_Source_modules_modules_gyp \
+	webkit_common_gpu_webkit_gpu_gyp \
+	webkit_common_webkit_common_gyp \
+	webkit_webkit_storage_browser_gyp \
+	sql_sql_gyp \
+	third_party_leveldatabase_leveldatabase_gyp \
+	webkit_webkit_storage_common_gyp \
+	google_apis_google_apis_gyp \
+	third_party_zlib_google_zip_gyp \
+	third_party_zlib_minizip_gyp \
+	ui_events_gesture_detection_gyp \
+	ui_snapshot_snapshot_gyp \
+	content_browser_speech_proto_speech_proto_gyp \
+	content_content_child_gyp \
+	webkit_child_webkit_child_gyp \
+	ui_native_theme_native_theme_gyp \
+	content_content_gpu_gyp \
+	content_content_utility_gyp \
+	courgette_courgette_lib_gyp \
+	third_party_lzma_sdk_lzma_sdk_gyp \
+	net_http_server_gyp \
+	ui_surface_surface_gyp \
+	printing_printing_gyp \
+	sandbox_sandbox_services_gyp \
+	sandbox_seccomp_bpf_gyp \
+	sandbox_seccomp_bpf_helpers_gyp \
+	third_party_libphonenumber_libphonenumber_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp \
+	components_autofill_content_common_gyp \
+	components_autofill_core_common_gyp \
+	components_autofill_content_risk_proto_gyp \
+	components_autofill_core_browser_gyp \
+	components_os_crypt_gyp \
+	components_user_prefs_gyp \
+	components_webdata_common_gyp \
+	components_web_contents_delegate_android_gyp \
+	components_auto_login_parser_gyp \
+	components_autofill_content_renderer_gyp \
+	content_content_renderer_gyp \
+	webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp \
+	webkit_renderer_compositor_bindings_webkit_compositor_support_gyp \
+	components_navigation_interception_gyp \
+	components_visitedlink_browser_gyp \
+	components_visitedlink_common_gyp \
+	components_visitedlink_renderer_gyp \
+	content_content_app_both_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	liblog \
+	libcutils \
+	libandroid \
+	libjnigraphics \
+	libicui18n \
+	libicuuc \
+	libexpat \
+	libjpeg \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: libwebviewchromium
+
+LOCAL_PRELINK_MODULE := false
+include $(BUILD_SHARED_LIBRARY)
diff --git a/android_webview/native/android_webview_native_jni.target.darwin-arm.mk b/android_webview/native/android_webview_native_jni.target.darwin-arm.mk
index d3b4c45..945a59f 100644
--- a/android_webview/native/android_webview_native_jni.target.darwin-arm.mk
+++ b/android_webview/native/android_webview_native_jni.target.darwin-arm.mk
@@ -301,6 +301,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -383,6 +384,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/android_webview_native_jni.target.darwin-mips.mk b/android_webview/native/android_webview_native_jni.target.darwin-mips.mk
index 3a7acea..a40056f 100644
--- a/android_webview/native/android_webview_native_jni.target.darwin-mips.mk
+++ b/android_webview/native/android_webview_native_jni.target.darwin-mips.mk
@@ -300,6 +300,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -381,6 +382,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/android_webview_native_jni.target.darwin-x86.mk b/android_webview/native/android_webview_native_jni.target.darwin-x86.mk
index 6d536d5..b0c6827 100644
--- a/android_webview/native/android_webview_native_jni.target.darwin-x86.mk
+++ b/android_webview/native/android_webview_native_jni.target.darwin-x86.mk
@@ -302,6 +302,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -384,6 +385,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/android_webview_native_jni.target.darwin-x86_64.mk b/android_webview/native/android_webview_native_jni.target.darwin-x86_64.mk
new file mode 100644
index 0000000..24e4019
--- /dev/null
+++ b/android_webview/native/android_webview_native_jni.target.darwin-x86_64.mk
@@ -0,0 +1,440 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_native_android_webview_native_jni_gyp
+LOCAL_MODULE_STEM := android_webview_native_jni
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,android_webview_native_input_stream_android_jar_jni_headers_gyp)/input_stream_android_jar_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_cancellation_signal_android_jar_jni_headers_gyp)/cancellation_signal_android_jar_jni_headers.stamp
+
+
+### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwDevToolsServer.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPdfExporter.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AndroidProtocolHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AndroidProtocolHandler.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwContents.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwContents.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwContentsClientBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwContentsClientBridge.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwCookieManager.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwCookieManager.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwDevToolsServer.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwFormDatabase.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwFormDatabase.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwHttpAuthHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwHttpAuthHandler.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPdfExporter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPdfExporter.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwQuotaManagerBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwResource.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwResource.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwSettings.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwSettings.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwWebContentsDelegate.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/InterceptedRequestData.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/InterceptedRequestData.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h \
+	android_webview_native_android_webview_native_jni_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_android_webview_native_jni_gyp
+
+# Alias gyp target name.
+.PHONY: android_webview_native_jni
+android_webview_native_jni: android_webview_native_android_webview_native_jni_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/native/android_webview_native_jni.target.linux-arm.mk b/android_webview/native/android_webview_native_jni.target.linux-arm.mk
index d3b4c45..945a59f 100644
--- a/android_webview/native/android_webview_native_jni.target.linux-arm.mk
+++ b/android_webview/native/android_webview_native_jni.target.linux-arm.mk
@@ -301,6 +301,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -383,6 +384,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/android_webview_native_jni.target.linux-mips.mk b/android_webview/native/android_webview_native_jni.target.linux-mips.mk
index 3a7acea..a40056f 100644
--- a/android_webview/native/android_webview_native_jni.target.linux-mips.mk
+++ b/android_webview/native/android_webview_native_jni.target.linux-mips.mk
@@ -300,6 +300,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -381,6 +382,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/android_webview_native_jni.target.linux-x86.mk b/android_webview/native/android_webview_native_jni.target.linux-x86.mk
index 6d536d5..b0c6827 100644
--- a/android_webview/native/android_webview_native_jni.target.linux-x86.mk
+++ b/android_webview/native/android_webview_native_jni.target.linux-x86.mk
@@ -302,6 +302,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -384,6 +385,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/android_webview_native_jni.target.linux-x86_64.mk b/android_webview/native/android_webview_native_jni.target.linux-x86_64.mk
new file mode 100644
index 0000000..24e4019
--- /dev/null
+++ b/android_webview/native/android_webview_native_jni.target.linux-x86_64.mk
@@ -0,0 +1,440 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_native_android_webview_native_jni_gyp
+LOCAL_MODULE_STEM := android_webview_native_jni
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,android_webview_native_input_stream_android_jar_jni_headers_gyp)/input_stream_android_jar_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,android_webview_native_cancellation_signal_android_jar_jni_headers_gyp)/cancellation_signal_android_jar_jni_headers.stamp
+
+
+### Generated for rule "android_webview_native_webview_native_gyp_android_webview_native_jni_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/android_webview/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../java/src/org/chromium/android_webview/AndroidProtocolHandler.java', '../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java', '../java/src/org/chromium/android_webview/AwContents.java', '../java/src/org/chromium/android_webview/AwContentsClientBridge.java', '../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java', '../java/src/org/chromium/android_webview/AwCookieManager.java', '../java/src/org/chromium/android_webview/AwDevToolsServer.java', '../java/src/org/chromium/android_webview/AwFormDatabase.java', '../java/src/org/chromium/android_webview/AwHttpAuthHandler.java', '../java/src/org/chromium/android_webview/AwPdfExporter.java', '../java/src/org/chromium/android_webview/AwPicture.java', '../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java', '../java/src/org/chromium/android_webview/AwResource.java', '../java/src/org/chromium/android_webview/AwSettings.java', '../java/src/org/chromium/android_webview/AwWebContentsDelegate.java', '../java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java', '../java/src/org/chromium/android_webview/InterceptedRequestData.java', '../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/android_webview/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AndroidProtocolHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AndroidProtocolHandler.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwAutofillManagerDelegate.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwContents.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwContents.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwContentsClientBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwContentsClientBridge.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwContentsIoThreadClient.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwCookieManager.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwCookieManager.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwDevToolsServer.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwDevToolsServer.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwFormDatabase.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwFormDatabase.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwHttpAuthHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwHttpAuthHandler.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPdfExporter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPdfExporter.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwPicture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwPicture.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwQuotaManagerBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwQuotaManagerBridge.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwResource.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwResource.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwSettings.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwSettings.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegate.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/AwWebContentsDelegate.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/ExternalVideoSurfaceContainer.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/InterceptedRequestData.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/InterceptedRequestData.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h
+
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h: $(LOCAL_PATH)/android_webview/java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; cd $(gyp_local_path)/android_webview/native; ../../base/android/jni_generator/jni_generator.py --input_file ../java/src/org/chromium/android_webview/JavaBrowserViewRendererHelper.java --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: android_webview_native_android_webview_native_jni_gyp_rule_trigger
+android_webview_native_android_webview_native_jni_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AndroidProtocolHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwAutofillManagerDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContents_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsClientBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwContentsIoThreadClient_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwCookieManager_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwDevToolsServer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwFormDatabase_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwHttpAuthHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPdfExporter_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwPicture_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwQuotaManagerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwResource_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/AwWebContentsDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/ExternalVideoSurfaceContainer_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InterceptedRequestData_jni.h \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/JavaBrowserViewRendererHelper_jni.h \
+	android_webview_native_android_webview_native_jni_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_android_webview_native_jni_gyp
+
+# Alias gyp target name.
+.PHONY: android_webview_native_jni
+android_webview_native_jni: android_webview_native_android_webview_native_jni_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/native/aw_contents.cc b/android_webview/native/aw_contents.cc
index 7eceea1..bde37b6 100644
--- a/android_webview/native/aw_contents.cc
+++ b/android_webview/native/aw_contents.cc
@@ -82,7 +82,7 @@
 
 extern "C" {
 static AwDrawGLFunction DrawGLFunction;
-static void DrawGLFunction(int view_context,
+static void DrawGLFunction(long view_context,
                            AwDrawGLInfo* draw_info,
                            void* spare) {
   // |view_context| is the value that was returned from the java
@@ -191,9 +191,11 @@
       shared_renderer_state_(
           BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI),
           this),
-      browser_view_renderer_(this,
-                             &shared_renderer_state_,
-                             web_contents_.get()) {
+      browser_view_renderer_(
+          this,
+          &shared_renderer_state_,
+          web_contents_.get(),
+          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)) {
   base::subtle::NoBarrier_AtomicIncrement(&g_instance_count, 1);
   icon_helper_.reset(new IconHelper(web_contents_.get()));
   icon_helper_->SetListener(this);
@@ -321,10 +323,10 @@
   }
 }
 
-jint AwContents::GetWebContents(JNIEnv* env, jobject obj) {
+jlong AwContents::GetWebContents(JNIEnv* env, jobject obj) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(web_contents_);
-  return reinterpret_cast<jint>(web_contents_.get());
+  return reinterpret_cast<intptr_t>(web_contents_.get());
 }
 
 void AwContents::Destroy(JNIEnv* env, jobject obj) {
@@ -345,18 +347,20 @@
   return reinterpret_cast<intptr_t>(new AwContents(web_contents.Pass()));
 }
 
-static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass, jint function_table) {
+static void SetAwDrawSWFunctionTable(JNIEnv* env, jclass,
+                                     jlong function_table) {
   JavaBrowserViewRendererHelper::SetAwDrawSWFunctionTable(
       reinterpret_cast<AwDrawSWFunctionTable*>(function_table));
 }
 
-static void SetAwDrawGLFunctionTable(JNIEnv* env, jclass, jint function_table) {
+static void SetAwDrawGLFunctionTable(JNIEnv* env, jclass,
+                                     jlong function_table) {
   GpuMemoryBufferFactoryImpl::SetAwDrawGLFunctionTable(
       reinterpret_cast<AwDrawGLFunctionTable*>(function_table));
 }
 
-static jint GetAwDrawGLFunction(JNIEnv* env, jclass) {
-  return reinterpret_cast<jint>(&DrawGLFunction);
+static jlong GetAwDrawGLFunction(JNIEnv* env, jclass) {
+  return reinterpret_cast<intptr_t>(&DrawGLFunction);
 }
 
 // static
@@ -364,9 +368,9 @@
   return base::subtle::NoBarrier_Load(&g_instance_count);
 }
 
-jint AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) {
+jlong AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  return reinterpret_cast<jint>(this);
+  return reinterpret_cast<intptr_t>(this);
 }
 
 void AwContents::DrawGL(AwDrawGLInfo* draw_info) {
@@ -874,9 +878,9 @@
   render_view_host_ext_->SetBackgroundColor(color);
 }
 
-jint AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) {
+jlong AwContents::ReleasePopupAwContents(JNIEnv* env, jobject obj) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  return reinterpret_cast<jint>(pending_contents_.release());
+  return reinterpret_cast<intptr_t>(pending_contents_.release());
 }
 
 gfx::Point AwContents::GetLocationOnScreen() {
diff --git a/android_webview/native/aw_contents.h b/android_webview/native/aw_contents.h
index 93c2f2f..acae893 100644
--- a/android_webview/native/aw_contents.h
+++ b/android_webview/native/aw_contents.h
@@ -83,7 +83,7 @@
                     jobject contents_client_bridge,
                     jobject io_thread_client,
                     jobject intercept_navigation_delegate);
-  jint GetWebContents(JNIEnv* env, jobject obj);
+  jlong GetWebContents(JNIEnv* env, jobject obj);
 
   void Destroy(JNIEnv* env, jobject obj);
   void DocumentHasImages(JNIEnv* env, jobject obj, jobject message);
@@ -120,7 +120,7 @@
               jint clip_top,
               jint clip_right,
               jint clip_bottom);
-  jint GetAwDrawGLViewContext(JNIEnv* env, jobject obj);
+  jlong GetAwDrawGLViewContext(JNIEnv* env, jobject obj);
   jlong CapturePicture(JNIEnv* env, jobject obj, int width, int height);
   void EnableOnNewPicture(JNIEnv* env, jobject obj, jboolean enabled);
   void ClearView(JNIEnv* env, jobject obj);
@@ -180,7 +180,7 @@
 
   void ClearCache(JNIEnv* env, jobject obj, jboolean include_disk_files);
   void SetPendingWebContentsForPopup(scoped_ptr<content::WebContents> pending);
-  jint ReleasePopupAwContents(JNIEnv* env, jobject obj);
+  jlong ReleasePopupAwContents(JNIEnv* env, jobject obj);
 
   void ScrollTo(JNIEnv* env, jobject obj, jint x, jint y);
   void SetDipScale(JNIEnv* env, jobject obj, jfloat dip_scale);
diff --git a/android_webview/native/aw_dev_tools_server.cc b/android_webview/native/aw_dev_tools_server.cc
index 6129a35..fe3bffe 100644
--- a/android_webview/native/aw_dev_tools_server.cc
+++ b/android_webview/native/aw_dev_tools_server.cc
@@ -199,19 +199,19 @@
   return RegisterNativesImpl(env);
 }
 
-static jint InitRemoteDebugging(JNIEnv* env,
+static jlong InitRemoteDebugging(JNIEnv* env,
                                 jobject obj) {
   AwDevToolsServer* server = new AwDevToolsServer();
-  return reinterpret_cast<jint>(server);
+  return reinterpret_cast<intptr_t>(server);
 }
 
-static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jint server) {
+static void DestroyRemoteDebugging(JNIEnv* env, jobject obj, jlong server) {
   delete reinterpret_cast<AwDevToolsServer*>(server);
 }
 
 static void SetRemoteDebuggingEnabled(JNIEnv* env,
                                       jobject obj,
-                                      jint server,
+                                      jlong server,
                                       jboolean enabled) {
   AwDevToolsServer* devtools_server =
       reinterpret_cast<AwDevToolsServer*>(server);
diff --git a/android_webview/native/aw_pdf_exporter.cc b/android_webview/native/aw_pdf_exporter.cc
index b72a7a2..7a13fd7 100644
--- a/android_webview/native/aw_pdf_exporter.cc
+++ b/android_webview/native/aw_pdf_exporter.cc
@@ -30,7 +30,7 @@
       web_contents_(web_contents) {
   DCHECK(obj);
   Java_AwPdfExporter_setNativeAwPdfExporter(
-      env, obj, reinterpret_cast<jint>(this));
+      env, obj, reinterpret_cast<intptr_t>(this));
 }
 
 AwPdfExporter::~AwPdfExporter() {
diff --git a/android_webview/native/aw_settings.cc b/android_webview/native/aw_settings.cc
index e2379ed..cf66d4e 100644
--- a/android_webview/native/aw_settings.cc
+++ b/android_webview/native/aw_settings.cc
@@ -326,10 +326,16 @@
   web_prefs->spatial_navigation_enabled =
       Java_AwSettings_getSpatialNavigationLocked(env, obj);
 
-  web_prefs->accelerated_2d_canvas_enabled =
-      !accelerated_2d_canvas_disabled_by_switch_ &&
-      Java_AwSettings_getEnableSupportedHardwareAcceleratedFeaturesLocked(
-          env, obj);
+  web_prefs->accelerated_2d_canvas_enabled = true;
+  if (accelerated_2d_canvas_disabled_by_switch_ ||
+      !Java_AwSettings_getEnableSupportedHardwareAcceleratedFeaturesLocked(
+          env, obj)) {
+    // Any canvas smaller than this will fallback to software. Abusing this
+    // slightly to turn canvas off without changing
+    // accelerated_2d_canvas_enabled, which also affects compositing mode.
+    // Using 100M instead of max int to avoid overflows.
+    web_prefs->minimum_accelerated_2d_canvas_size = 100 * 1000 * 1000;
+  }
 }
 
 static jlong Init(JNIEnv* env,
diff --git a/android_webview/native/aw_web_contents_delegate.cc b/android_webview/native/aw_web_contents_delegate.cc
index 75db194..3c5c40e 100644
--- a/android_webview/native/aw_web_contents_delegate.cc
+++ b/android_webview/native/aw_web_contents_delegate.cc
@@ -163,7 +163,7 @@
 // typically happens when popups are created.
 void AwWebContentsDelegate::WebContentsCreated(
     WebContents* source_contents,
-    int64 source_frame_id,
+    int opener_render_frame_id,
     const base::string16& frame_name,
     const GURL& target_url,
     content::WebContents* new_contents) {
diff --git a/android_webview/native/aw_web_contents_delegate.h b/android_webview/native/aw_web_contents_delegate.h
index ca42459..6f444a7 100644
--- a/android_webview/native/aw_web_contents_delegate.h
+++ b/android_webview/native/aw_web_contents_delegate.h
@@ -42,7 +42,7 @@
                               bool* was_blocked) OVERRIDE;
 
   virtual void WebContentsCreated(content::WebContents* source_contents,
-                                  int64 source_frame_id,
+                                  int opener_render_frame_id,
                                   const base::string16& frame_name,
                                   const GURL& target_url,
                                   content::WebContents* new_contents) OVERRIDE;
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-arm.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-arm.mk
index 7ce208d..3af3d8d 100644
--- a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-arm.mk
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-mips.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-mips.mk
index 4057e0b..fc10979 100644
--- a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-mips.mk
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86.mk
index a619327..21c839b 100644
--- a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86.mk
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86_64.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..339318e
--- /dev/null
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_native_cancellation_signal_android_jar_jni_headers_gyp
+LOCAL_MODULE_STEM := cancellation_signal_android_jar_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/os/CancellationSignal.class ($@)"
+	$(hide)cd $(gyp_local_path)/android_webview/native; mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/os/CancellationSignal.class --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_cancellation_signal_android_jar_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: cancellation_signal_android_jar_jni_headers
+cancellation_signal_android_jar_jni_headers: android_webview_native_cancellation_signal_android_jar_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-arm.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-arm.mk
index 7ce208d..3af3d8d 100644
--- a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-arm.mk
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-mips.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-mips.mk
index 4057e0b..fc10979 100644
--- a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-mips.mk
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86.mk
index a619327..21c839b 100644
--- a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86.mk
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86_64.mk b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..339318e
--- /dev/null
+++ b/android_webview/native/cancellation_signal_android_jar_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_native_cancellation_signal_android_jar_jni_headers_gyp
+LOCAL_MODULE_STEM := cancellation_signal_android_jar_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/os/CancellationSignal.class ($@)"
+	$(hide)cd $(gyp_local_path)/android_webview/native; mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/os/CancellationSignal.class --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/CancellationSignal_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_cancellation_signal_android_jar_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: cancellation_signal_android_jar_jni_headers
+cancellation_signal_android_jar_jni_headers: android_webview_native_cancellation_signal_android_jar_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-arm.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-arm.mk
index 2b0bf5b..21e9ad6 100644
--- a/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-arm.mk
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-mips.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-mips.mk
index 7dc6bb8..b21c0b6 100644
--- a/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-mips.mk
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86.mk
index 158f403..d2bb078 100644
--- a/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86.mk
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86_64.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..b16ca48
--- /dev/null
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_native_input_stream_android_jar_jni_headers_gyp
+LOCAL_MODULE_STEM := input_stream_android_jar_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/java/io/InputStream.class ($@)"
+	$(hide)cd $(gyp_local_path)/android_webview/native; mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file java/io/InputStream.class --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_input_stream_android_jar_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: input_stream_android_jar_jni_headers
+input_stream_android_jar_jni_headers: android_webview_native_input_stream_android_jar_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.linux-arm.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-arm.mk
index 2b0bf5b..21e9ad6 100644
--- a/android_webview/native/input_stream_android_jar_jni_headers.target.linux-arm.mk
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.linux-mips.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-mips.mk
index 7dc6bb8..b21c0b6 100644
--- a/android_webview/native/input_stream_android_jar_jni_headers.target.linux-mips.mk
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86.mk
index 158f403..d2bb078 100644
--- a/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86.mk
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86_64.mk b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..b16ca48
--- /dev/null
+++ b/android_webview/native/input_stream_android_jar_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := android_webview_native_input_stream_android_jar_jni_headers_gyp
+LOCAL_MODULE_STEM := input_stream_android_jar_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/java/io/InputStream.class ($@)"
+	$(hide)cd $(gyp_local_path)/android_webview/native; mkdir -p $(gyp_shared_intermediate_dir)/android_webview/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file java/io/InputStream.class --output_dir "$(gyp_shared_intermediate_dir)/android_webview/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/android_webview/jni/InputStream_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_input_stream_android_jar_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: input_stream_android_jar_jni_headers
+input_stream_android_jar_jni_headers: android_webview_native_input_stream_android_jar_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/android_webview/native/webview_native.target.darwin-arm.mk b/android_webview/native/webview_native.target.darwin-arm.mk
index 772c331..b77b2de 100644
--- a/android_webview/native/webview_native.target.darwin-arm.mk
+++ b/android_webview/native/webview_native.target.darwin-arm.mk
@@ -114,9 +114,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -126,6 +124,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -239,9 +238,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +248,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/webview_native.target.darwin-mips.mk b/android_webview/native/webview_native.target.darwin-mips.mk
index a24d4ea..6435f1b 100644
--- a/android_webview/native/webview_native.target.darwin-mips.mk
+++ b/android_webview/native/webview_native.target.darwin-mips.mk
@@ -113,9 +113,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -125,6 +123,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -237,9 +236,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +246,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/webview_native.target.darwin-x86.mk b/android_webview/native/webview_native.target.darwin-x86.mk
index 6c81ce2..a18ec96 100644
--- a/android_webview/native/webview_native.target.darwin-x86.mk
+++ b/android_webview/native/webview_native.target.darwin-x86.mk
@@ -114,9 +114,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -126,6 +124,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -238,9 +237,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -250,6 +247,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/webview_native.target.darwin-x86_64.mk b/android_webview/native/webview_native.target.darwin-x86_64.mk
new file mode 100644
index 0000000..20ee0ff
--- /dev/null
+++ b/android_webview/native/webview_native.target.darwin-x86_64.mk
@@ -0,0 +1,367 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := android_webview_native_webview_native_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,android_webview_native_android_webview_native_jni_gyp)/android_webview_native_jni.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	android_webview/native/android_protocol_handler.cc \
+	android_webview/native/android_webview_jni_registrar.cc \
+	android_webview/native/aw_autofill_manager_delegate.cc \
+	android_webview/native/aw_browser_dependency_factory.cc \
+	android_webview/native/aw_contents.cc \
+	android_webview/native/aw_contents_client_bridge.cc \
+	android_webview/native/aw_contents_io_thread_client_impl.cc \
+	android_webview/native/aw_dev_tools_server.cc \
+	android_webview/native/aw_form_database.cc \
+	android_webview/native/aw_geolocation_permission_context.cc \
+	android_webview/native/aw_http_auth_handler.cc \
+	android_webview/native/aw_pdf_exporter.cc \
+	android_webview/native/aw_picture.cc \
+	android_webview/native/aw_quota_manager_bridge_impl.cc \
+	android_webview/native/aw_resource.cc \
+	android_webview/native/aw_settings.cc \
+	android_webview/native/aw_web_contents_delegate.cc \
+	android_webview/native/aw_web_contents_view_delegate.cc \
+	android_webview/native/aw_web_preferences_populater_impl.cc \
+	android_webview/native/cookie_manager.cc \
+	android_webview/native/input_stream_impl.cc \
+	android_webview/native/intercepted_request_data_impl.cc \
+	android_webview/native/java_browser_view_renderer_helper.cc \
+	android_webview/native/net_init_native_callback.cc \
+	android_webview/native/state_serializer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/android_webview \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/android_webview \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_webview_native_gyp
+
+# Alias gyp target name.
+.PHONY: webview_native
+webview_native: android_webview_native_webview_native_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/android_webview/native/webview_native.target.linux-arm.mk b/android_webview/native/webview_native.target.linux-arm.mk
index 772c331..b77b2de 100644
--- a/android_webview/native/webview_native.target.linux-arm.mk
+++ b/android_webview/native/webview_native.target.linux-arm.mk
@@ -114,9 +114,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -126,6 +124,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -239,9 +238,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +248,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/webview_native.target.linux-mips.mk b/android_webview/native/webview_native.target.linux-mips.mk
index a24d4ea..6435f1b 100644
--- a/android_webview/native/webview_native.target.linux-mips.mk
+++ b/android_webview/native/webview_native.target.linux-mips.mk
@@ -113,9 +113,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -125,6 +123,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -237,9 +236,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +246,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/webview_native.target.linux-x86.mk b/android_webview/native/webview_native.target.linux-x86.mk
index 6c81ce2..a18ec96 100644
--- a/android_webview/native/webview_native.target.linux-x86.mk
+++ b/android_webview/native/webview_native.target.linux-x86.mk
@@ -114,9 +114,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -126,6 +124,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -238,9 +237,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -250,6 +247,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/android_webview/native/webview_native.target.linux-x86_64.mk b/android_webview/native/webview_native.target.linux-x86_64.mk
new file mode 100644
index 0000000..20ee0ff
--- /dev/null
+++ b/android_webview/native/webview_native.target.linux-x86_64.mk
@@ -0,0 +1,367 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := android_webview_native_webview_native_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,android_webview_native_android_webview_native_jni_gyp)/android_webview_native_jni.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	android_webview/native/android_protocol_handler.cc \
+	android_webview/native/android_webview_jni_registrar.cc \
+	android_webview/native/aw_autofill_manager_delegate.cc \
+	android_webview/native/aw_browser_dependency_factory.cc \
+	android_webview/native/aw_contents.cc \
+	android_webview/native/aw_contents_client_bridge.cc \
+	android_webview/native/aw_contents_io_thread_client_impl.cc \
+	android_webview/native/aw_dev_tools_server.cc \
+	android_webview/native/aw_form_database.cc \
+	android_webview/native/aw_geolocation_permission_context.cc \
+	android_webview/native/aw_http_auth_handler.cc \
+	android_webview/native/aw_pdf_exporter.cc \
+	android_webview/native/aw_picture.cc \
+	android_webview/native/aw_quota_manager_bridge_impl.cc \
+	android_webview/native/aw_resource.cc \
+	android_webview/native/aw_settings.cc \
+	android_webview/native/aw_web_contents_delegate.cc \
+	android_webview/native/aw_web_contents_view_delegate.cc \
+	android_webview/native/aw_web_preferences_populater_impl.cc \
+	android_webview/native/cookie_manager.cc \
+	android_webview/native/input_stream_impl.cc \
+	android_webview/native/intercepted_request_data_impl.cc \
+	android_webview/native/java_browser_view_renderer_helper.cc \
+	android_webview/native/net_init_native_callback.cc \
+	android_webview/native/state_serializer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/android_webview \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/android_webview \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: android_webview_native_webview_native_gyp
+
+# Alias gyp target name.
+.PHONY: webview_native
+webview_native: android_webview_native_webview_native_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/android_webview/public/browser/draw_gl.h b/android_webview/public/browser/draw_gl.h
index f898025..56e3064 100644
--- a/android_webview/public/browser/draw_gl.h
+++ b/android_webview/public/browser/draw_gl.h
@@ -58,7 +58,7 @@
 // call to AwContents.getAwDrawGLViewContext().
 // |draw_info| carries the in and out parameters for this draw.
 // |spare| ignored; pass NULL.
-typedef void (AwDrawGLFunction)(int view_context,
+typedef void (AwDrawGLFunction)(long view_context,
                                 AwDrawGLInfo* draw_info,
                                 void* spare);
 enum AwMapMode {
@@ -68,17 +68,17 @@
 };
 
 // Called to create a GraphicBuffer
-typedef int AwCreateGraphicBufferFunction(int w, int h);
+typedef long AwCreateGraphicBufferFunction(int w, int h);
 // Called to release a GraphicBuffer
-typedef void AwReleaseGraphicBufferFunction(int buffer_id);
+typedef void AwReleaseGraphicBufferFunction(long buffer_id);
 // Called to map a GraphicBuffer in |mode|.
-typedef int AwMapFunction(int buffer_id, AwMapMode mode, void** vaddr);
+typedef int AwMapFunction(long buffer_id, AwMapMode mode, void** vaddr);
 // Called to unmap a GraphicBuffer
-typedef int AwUnmapFunction(int buffer_id);
+typedef int AwUnmapFunction(long buffer_id);
 // Called to get a native buffer pointer
-typedef void* AwGetNativeBufferFunction(int buffer_id);
+typedef void* AwGetNativeBufferFunction(long buffer_id);
 // Called to get the stride of the buffer
-typedef unsigned int AwGetStrideFunction(int buffer_id);
+typedef unsigned int AwGetStrideFunction(long buffer_id);
 
 // Set of functions used in rendering in hardware mode
 struct AwDrawGLFunctionTable {
diff --git a/android_webview/renderer/print_web_view_helper.cc b/android_webview/renderer/print_web_view_helper.cc
index 829a6e9..fe1ac8d 100644
--- a/android_webview/renderer/print_web_view_helper.cc
+++ b/android_webview/renderer/print_web_view_helper.cc
@@ -379,7 +379,7 @@
 
 }  // namespace
 
-FrameReference::FrameReference(const blink::WebFrame* frame) {
+FrameReference::FrameReference(blink::WebFrame* frame) {
   Reset(frame);
 }
 
@@ -390,18 +390,25 @@
 FrameReference::~FrameReference() {
 }
 
-void FrameReference::Reset(const blink::WebFrame* frame) {
+void FrameReference::Reset(blink::WebFrame* frame) {
   if (frame) {
     view_ = frame->view();
-    frame_name_ = frame->uniqueName();
+    frame_ = frame;
   } else {
     view_ = NULL;
-    frame_name_.reset();
+    frame_ = NULL;
   }
 }
 
 blink::WebFrame* FrameReference::GetFrame() {
-  return view_ ? view_->findFrameByName(frame_name_) : NULL;
+  if (view_ == NULL || frame_ == NULL)
+    return NULL;
+  for (blink::WebFrame* frame = view_->mainFrame(); frame != NULL;
+           frame = frame->traverseNext(false)) {
+    if (frame == frame_)
+      return frame;
+  }
+  return NULL;
 }
 
 blink::WebView* FrameReference::view() {
diff --git a/android_webview/renderer/print_web_view_helper.h b/android_webview/renderer/print_web_view_helper.h
index 1835584..18ef9ea 100644
--- a/android_webview/renderer/print_web_view_helper.h
+++ b/android_webview/renderer/print_web_view_helper.h
@@ -42,20 +42,21 @@
 
 // Stores reference to frame using WebVew and unique name.
 // Workaround to modal dialog issue on Linux. crbug.com/236147.
+// If WebFrame someday supports WeakPtr, we should use it here.
 class FrameReference {
  public:
-  explicit FrameReference(const blink::WebFrame* frame);
+  explicit FrameReference(blink::WebFrame* frame);
   FrameReference();
   ~FrameReference();
 
-  void Reset(const blink::WebFrame* frame);
+  void Reset(blink::WebFrame* frame);
 
   blink::WebFrame* GetFrame();
   blink::WebView* view();
 
  private:
   blink::WebView* view_;
-  blink::WebString frame_name_;
+  blink::WebFrame* frame_;
 };
 
 // PrintWebViewHelper handles most of the printing grunt work for RenderView.
diff --git a/android_webview/tools/gyp_webview b/android_webview/tools/gyp_webview
index ff39f60..3b7f8aa 100755
--- a/android_webview/tools/gyp_webview
+++ b/android_webview/tools/gyp_webview
@@ -68,6 +68,9 @@
   if [ "$PLATFORM" == "${host_platform}-x86" -o "$PLATFORM" == "all" ]; then
     ${GYP} --suffix .${host_platform}-x86 ${EFLAGS} -Dtarget_arch=ia32
   fi
+  if [ "$PLATFORM" == "${host_platform}-x86_64" -o "$PLATFORM" == "all" ]; then
+    ${GYP} --suffix .${host_platform}-x86_64 ${EFLAGS} -Dtarget_arch=x64
+  fi
   if [ "$PLATFORM" == "${host_platform}-mips" -o "$PLATFORM" == "all" ]; then
     ${GYP} --suffix .${host_platform}-mips ${EFLAGS} -Dtarget_arch=mipsel
   fi
diff --git a/android_webview/tools/third_party_files_whitelist.txt b/android_webview/tools/third_party_files_whitelist.txt
index 956ac72..a5a4139 100644
--- a/android_webview/tools/third_party_files_whitelist.txt
+++ b/android_webview/tools/third_party_files_whitelist.txt
@@ -45,6 +45,8 @@
 # String 'copyright' used in code.
 chrome/browser/resources/file_manager/foreground/js/media/video_player_scripts.js
 # String 'copyright' used in code.
+chrome/browser/resources/video_player/js/video_player_scripts.js
+# String 'copyright' used in code.
 chrome/common/importer/firefox_importer_utils.cc
 # Copyright Netscape Communications Corporation; MPL, GPL v2 or LGPL v2
 # license. Not used on Android.
diff --git a/apps/DEPS b/apps/DEPS
index e9d3eeb..703a749 100644
--- a/apps/DEPS
+++ b/apps/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
   "+base",
+  "+content/public/app",
   "+content/public/browser",
   "+content/public/common",
   "+content/public/test",
diff --git a/apps/app_window_browsertest.cc b/apps/app_window_browsertest.cc
index cc41155..4c417c7 100644
--- a/apps/app_window_browsertest.cc
+++ b/apps/app_window_browsertest.cc
@@ -13,7 +13,10 @@
 
 typedef extensions::PlatformAppBrowserTest AppWindowBrowserTest;
 
-#if defined(TOOLKIT_GTK)
+// This test is disabled on Linux because of the unpredictable nature of native
+// windows. We cannot assume that the window manager will insert any title bar
+// at all, so the test may fail on certain window managers.
+#if defined(TOOLKIT_GTK) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
 #define MAYBE_FrameInsetsForDefaultFrame DISABLED_FrameInsetsForDefaultFrame
 #else
 #define MAYBE_FrameInsetsForDefaultFrame FrameInsetsForDefaultFrame
@@ -33,7 +36,10 @@
   CloseAppWindow(app_window);
 }
 
-#if defined(TOOLKIT_GTK)
+// This test is also disabled on Linux because frame: color is ignored on stable
+// and beta channels (so it can fail the same as the previous test).
+// TODO(benwells): Re-enable on Linux after frame: color is on stable.
+#if defined(TOOLKIT_GTK) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
 #define MAYBE_FrameInsetsForColoredFrame DISABLED_FrameInsetsForColoredFrame
 #else
 #define MAYBE_FrameInsetsForColoredFrame FrameInsetsForColoredFrame
diff --git a/apps/apps.gypi b/apps/apps.gypi
index 65d1e0d..9a295bf 100644
--- a/apps/apps.gypi
+++ b/apps/apps.gypi
@@ -117,9 +117,6 @@
             '../ui/base/strings/ui_strings.gyp:ui_strings',
             '../ui/resources/ui_resources.gyp:ui_resources',
           ],
-          'variables': {
-            'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
-          },
           'actions': [
             {
               'action_name': 'repack_app_shell_pack',
@@ -139,22 +136,15 @@
                   '<(SHARED_INTERMEDIATE_DIR)/ui/ui_strings/ui_strings_en-US.pak',
                   '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak',
                 ],
+                'pak_output': '<(PRODUCT_DIR)/app_shell.pak',
               },
-              'inputs': [
-                '<(repack_path)',
-                '<@(pak_inputs)',
-              ],
-              'outputs': [
-                '<(PRODUCT_DIR)/app_shell.pak',
-              ],
-              'action': ['python', '<(repack_path)', '<@(_outputs)',
-                         '<@(pak_inputs)'],
+             'includes': [ '../build/repack_action.gypi' ],
             },
           ],
         },
         {
-          'target_name': 'app_shell',
-          'type': 'executable',
+          'target_name': 'app_shell_lib',
+          'type': 'static_library',
           'defines!': ['CONTENT_IMPLEMENTATION'],
           'variables': {
             'chromium_code': 1,
@@ -162,11 +152,13 @@
           'dependencies': [
             'app_shell_pak',
             'apps',
+            'common/extensions/api/api.gyp:chrome_api',
             'test_support_common',
             '../base/base.gyp:base',
             '../base/base.gyp:base_prefs_test_support',
             '../content/content.gyp:content',
             '../content/content_shell_and_tests.gyp:content_shell_lib',
+            '../extensions/common/api/api.gyp:extensions_api',
             '../skia/skia.gyp:skia',
             '../ui/views/views.gyp:views',
             '../ui/wm/wm.gyp:wm_test_support',
@@ -177,7 +169,6 @@
           'sources': [
             'shell/app/shell_main_delegate.cc',
             'shell/app/shell_main_delegate.h',
-            'shell/app/shell_main.cc',
             'shell/browser/shell_app_sorting.cc',
             'shell/browser/shell_app_sorting.h',
             'shell/browser/shell_app_window_delegate.cc',
@@ -190,6 +181,8 @@
             'shell/browser/shell_browser_main_parts.h',
             'shell/browser/shell_content_browser_client.cc',
             'shell/browser/shell_content_browser_client.h',
+            'shell/browser/shell_desktop_controller.cc',
+            'shell/browser/shell_desktop_controller.h',
             'shell/browser/shell_extension_system.cc',
             'shell/browser/shell_extension_system.h',
             'shell/browser/shell_extension_system_factory.cc',
@@ -198,8 +191,6 @@
             'shell/browser/shell_extension_web_contents_observer.h',
             'shell/browser/shell_extensions_browser_client.cc',
             'shell/browser/shell_extensions_browser_client.h',
-            'shell/browser/web_view_window.cc',
-            'shell/browser/web_view_window.cc',
             'shell/common/shell_content_client.cc',
             'shell/common/shell_content_client.h',
             'shell/common/shell_extensions_client.cc',
@@ -207,6 +198,24 @@
             'shell/renderer/shell_content_renderer_client.cc',
             'shell/renderer/shell_content_renderer_client.h',
           ],
+        },
+        {
+          'target_name': 'app_shell',
+          'type': 'executable',
+          'defines!': ['CONTENT_IMPLEMENTATION'],
+          'variables': {
+            'chromium_code': 1,
+          },
+          'dependencies': [
+            'app_shell_lib',
+            'app_shell_pak',
+          ],
+          'include_dirs': [
+            '..',
+          ],
+          'sources': [
+            'shell/app/shell_main.cc',
+          ],
           'conditions': [
             ['OS=="win"', {
               'msvs_settings': {
@@ -221,7 +230,34 @@
             }],
           ],
         },
+        {
+          'target_name': 'apps_browsertests',
+          'type': '<(gtest_target_type)',
+          'variables': {
+            'chromium_code': 1,
+          },
+          'dependencies': [
+            'app_shell_lib',
+            # TODO(yoz): find the right deps
+            '../base/base.gyp:test_support_base',
+            '../content/content.gyp:content_app_both',
+            '../content/content_shell_and_tests.gyp:content_browser_test_support',
+            '../content/content_shell_and_tests.gyp:test_support_content',
+            '../testing/gtest.gyp:gtest',
+          ],
+          'defines': [
+            'HAS_OUT_OF_PROC_TEST_RUNNER',
+          ],
+          'sources': [
+            # TODO(yoz): Refactor once we have a second test target.
+            'test/app_shell_test.h',
+            'test/app_shell_test.cc',
+            'test/apps_test_launcher_delegate.cc',
+            'test/apps_test_launcher_delegate.h',
+            'test/apps_tests_main.cc',
+          ],
+        },
       ],  # targets
-    }],  # chromeos==1
+    }],  # chromeos==1 or linux aura or win aura
   ],  # conditions
 }
diff --git a/apps/common/api/dummy.idl b/apps/common/api/dummy.idl
new file mode 100644
index 0000000..ac622b5
--- /dev/null
+++ b/apps/common/api/dummy.idl
@@ -0,0 +1,10 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// TODO(jamescook): Remove this once actual APIs live here.
+// This is a placeholder IDL so the docserver doesn't choke on an empty
+// apps API path.
+namespace dummy {
+}
+
diff --git a/apps/launcher.cc b/apps/launcher.cc
index 5842225..b19d9a2 100644
--- a/apps/launcher.cc
+++ b/apps/launcher.cc
@@ -54,6 +54,7 @@
 using extensions::app_file_handler_util::CreateFileEntry;
 using extensions::app_file_handler_util::GrantedFileEntry;
 using extensions::app_file_handler_util::HasFileSystemWritePermission;
+using extensions::EventRouter;
 using extensions::Extension;
 using extensions::ExtensionHost;
 using extensions::ExtensionSystem;
@@ -377,8 +378,7 @@
   if (win8::IsSingleWindowMetroMode())
     return;
 #endif
-  extensions::EventRouter* event_router =
-      ExtensionSystem::Get(profile)->event_router();
+  EventRouter* event_router = EventRouter::Get(profile);
   bool listening_to_restart = event_router->
       ExtensionHasEventListener(extension->id(),
                                 app_runtime::OnRestarted::kEventName);
diff --git a/apps/shell/browser/shell_browser_main_parts.cc b/apps/shell/browser/shell_browser_main_parts.cc
index ab9aac2..2700cb4 100644
--- a/apps/shell/browser/shell_browser_main_parts.cc
+++ b/apps/shell/browser/shell_browser_main_parts.cc
@@ -7,10 +7,10 @@
 #include "apps/browser_context_keyed_service_factories.h"
 #include "apps/shell/browser/shell_apps_client.h"
 #include "apps/shell/browser/shell_browser_context.h"
+#include "apps/shell/browser/shell_desktop_controller.h"
 #include "apps/shell/browser/shell_extension_system.h"
 #include "apps/shell/browser/shell_extension_system_factory.h"
 #include "apps/shell/browser/shell_extensions_browser_client.h"
-#include "apps/shell/browser/web_view_window.h"
 #include "apps/shell/common/shell_extensions_client.h"
 #include "base/command_line.h"
 #include "base/file_util.h"
@@ -22,17 +22,9 @@
 #include "content/shell/browser/shell_net_log.h"
 #include "extensions/browser/browser_context_keyed_service_factories.h"
 #include "extensions/browser/extension_system.h"
-#include "ui/aura/env.h"
-#include "ui/aura/test/test_screen.h"
-#include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/base/ime/input_method_initializer.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/screen.h"
-#include "ui/views/test/test_views_delegate.h"
-#include "ui/views/views_delegate.h"
 #include "ui/views/widget/widget.h"
-#include "ui/wm/test/wm_test_helper.h"
 
 using content::BrowserContext;
 using extensions::Extension;
@@ -49,35 +41,13 @@
   extensions::ShellExtensionSystemFactory::GetInstance();
 }
 
-// A ViewsDelegate to attach new unparented windows to app_shell's root window.
-class ShellViewsDelegate : public views::TestViewsDelegate {
- public:
-  explicit ShellViewsDelegate(aura::Window* root_window)
-      : root_window_(root_window) {}
-  virtual ~ShellViewsDelegate() {}
-
-  // views::ViewsDelegate implementation.
-  virtual void OnBeforeWidgetInit(
-      views::Widget::InitParams* params,
-      views::internal::NativeWidgetDelegate* delegate) OVERRIDE {
-    if (!params->parent)
-      params->parent = root_window_;
-  }
-
- private:
-  aura::Window* root_window_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegate);
-};
-
 }  // namespace
 
 namespace apps {
 
 ShellBrowserMainParts::ShellBrowserMainParts(
     const content::MainFunctionParams& parameters)
-    : extension_system_(NULL) {
-}
+    : extension_system_(NULL), parameters_(parameters) {}
 
 ShellBrowserMainParts::~ShellBrowserMainParts() {
 }
@@ -100,10 +70,11 @@
 }
 
 void ShellBrowserMainParts::PreMainMessageLoopRun() {
+  desktop_controller_.reset(new ShellDesktopController);
+  desktop_controller_->GetWindowTreeHost()->AddObserver(this);
+
   // NOTE: Much of this is culled from chrome/test/base/chrome_test_suite.cc
-
   // TODO(jamescook): Initialize chromeos::UserManager.
-
   net_log_.reset(new content::ShellNetLog("app_shell"));
 
   // Initialize our "profile" equivalent.
@@ -131,8 +102,14 @@
   devtools_delegate_.reset(
       new content::ShellDevToolsDelegate(browser_context_.get()));
 
-  CreateRootWindow();
-  CreateViewsDelegate();
+  // For running browser tests.
+  // TODO(yoz): This is set up to exit prematurely because we don't have
+  // any tests yet.
+  if (parameters_.ui_task) {
+    parameters_.ui_task->Run();
+    delete parameters_.ui_task;
+    return;
+  }
 
   const std::string kAppSwitch = "app";
   CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -141,11 +118,7 @@
     base::FilePath app_absolute_dir = base::MakeAbsoluteFilePath(app_dir);
     extension_system_->LoadAndLaunchApp(app_absolute_dir);
   } else {
-    // TODO(jamescook): For demo purposes create a window with a WebView just
-    // to ensure that the content module is properly initialized.
-    webview_window_.reset(CreateWebViewWindow(browser_context_.get(),
-        wm_test_helper_->host()->window()));
-    webview_window_->Show();
+    LOG(ERROR) << "--" << kAppSwitch << " unset; boredom is in your future";
   }
 }
 
@@ -157,15 +130,15 @@
 }
 
 void ShellBrowserMainParts::PostMainMessageLoopRun() {
-  DestroyViewsDelegate();
-  DestroyRootWindow();
   BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
       browser_context_.get());
   extension_system_ = NULL;
   extensions::ExtensionsBrowserClient::Set(NULL);
   extensions_browser_client_.reset();
   browser_context_.reset();
-  aura::Env::DeleteInstance();
+
+  desktop_controller_->GetWindowTreeHost()->RemoveObserver(this);
+  desktop_controller_.reset();
 }
 
 void ShellBrowserMainParts::OnHostCloseRequested(
@@ -175,40 +148,6 @@
                                          base::MessageLoop::QuitClosure());
 }
 
-void ShellBrowserMainParts::CreateRootWindow() {
-  test_screen_.reset(aura::TestScreen::Create());
-  // TODO(jamescook): Replace this with a real Screen implementation.
-  gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
-  // TODO(jamescook): Initialize a real input method.
-  ui::InitializeInputMethodForTesting();
-  // Set up basic pieces of views::corewm.
-  wm_test_helper_.reset(new wm::WMTestHelper(gfx::Size(800, 600)));
-  // Ensure the X window gets mapped.
-  wm_test_helper_->host()->Show();
-  // Watch for the user clicking the close box.
-  wm_test_helper_->host()->AddObserver(this);
-}
-
-void ShellBrowserMainParts::DestroyRootWindow() {
-  // We should close widget before destroying root window.
-  webview_window_.reset();
-  devtools_delegate_->Stop();
-  wm_test_helper_->host()->RemoveObserver(this);
-  wm_test_helper_.reset();
-  ui::ShutdownInputMethodForTesting();
-}
-
-void ShellBrowserMainParts::CreateViewsDelegate() {
-  DCHECK(!views::ViewsDelegate::views_delegate);
-  views::ViewsDelegate::views_delegate =
-      new ShellViewsDelegate(wm_test_helper_->host()->window());
-}
-
-void ShellBrowserMainParts::DestroyViewsDelegate() {
-  delete views::ViewsDelegate::views_delegate;
-  views::ViewsDelegate::views_delegate = NULL;
-}
-
 void ShellBrowserMainParts::CreateExtensionSystem() {
   DCHECK(browser_context_);
   extension_system_ = static_cast<ShellExtensionSystem*>(
diff --git a/apps/shell/browser/shell_browser_main_parts.h b/apps/shell/browser/shell_browser_main_parts.h
index 653e90d..e29140d 100644
--- a/apps/shell/browser/shell_browser_main_parts.h
+++ b/apps/shell/browser/shell_browser_main_parts.h
@@ -9,12 +9,9 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "content/public/browser/browser_main_parts.h"
+#include "content/public/common/main_function_params.h"
 #include "ui/aura/window_tree_host_observer.h"
 
-namespace aura {
-class TestScreen;
-}
-
 namespace content {
 class ShellBrowserContext;
 class ShellDevToolsDelegate;
@@ -34,14 +31,11 @@
 class NetLog;
 }
 
-namespace wm {
-class WMTestHelper;
-}
-
 namespace apps {
 
 class ShellAppsClient;
 class ShellBrowserContext;
+class ShellDesktopController;
 class ShellExtensionsClient;
 
 // Handles initialization of AppShell.
@@ -73,19 +67,10 @@
   virtual void OnHostCloseRequested(const aura::WindowTreeHost* host) OVERRIDE;
 
  private:
-  // Creates the window that hosts the apps.
-  void CreateRootWindow();
-
-  // Closes and destroys the root window hosting the app.
-  void DestroyRootWindow();
-
-  // Window placement is controlled by a ViewsDelegate.
-  void CreateViewsDelegate();
-  void DestroyViewsDelegate();
-
   // Creates and initializes the ExtensionSystem.
   void CreateExtensionSystem();
 
+  scoped_ptr<ShellDesktopController> desktop_controller_;
   scoped_ptr<ShellBrowserContext> browser_context_;
   scoped_ptr<ShellExtensionsClient> extensions_client_;
   scoped_ptr<extensions::ShellExtensionsBrowserClient>
@@ -93,18 +78,14 @@
   scoped_ptr<ShellAppsClient> apps_client_;
   scoped_ptr<net::NetLog> net_log_;
 
-  // Enable a minimal set of views::corewm to be initialized.
-  scoped_ptr<wm::WMTestHelper> wm_test_helper_;
-
-  scoped_ptr<aura::TestScreen> test_screen_;
-
-  scoped_ptr<views::Widget> webview_window_;
-
   scoped_ptr<content::ShellDevToolsDelegate> devtools_delegate_;
 
   // Owned by the KeyedService system.
   extensions::ShellExtensionSystem* extension_system_;
 
+  // For running app browsertests.
+  const content::MainFunctionParams parameters_;
+
   DISALLOW_COPY_AND_ASSIGN(ShellBrowserMainParts);
 };
 
diff --git a/apps/shell/browser/shell_desktop_controller.cc b/apps/shell/browser/shell_desktop_controller.cc
new file mode 100644
index 0000000..9725c51
--- /dev/null
+++ b/apps/shell/browser/shell_desktop_controller.cc
@@ -0,0 +1,121 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "apps/shell/browser/shell_desktop_controller.h"
+
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/aura/env.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/ime/input_method_initializer.h"
+#include "ui/gfx/screen.h"
+#include "ui/views/test/test_views_delegate.h"
+#include "ui/views/views_delegate.h"
+#include "ui/views/widget/widget.h"
+#include "ui/wm/test/wm_test_helper.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/display/chromeos/display_mode.h"
+#include "ui/display/chromeos/display_snapshot.h"
+#endif
+
+namespace apps {
+namespace {
+
+const SkColor kBackgroundColor = SK_ColorBLACK;
+
+// A ViewsDelegate to attach new unparented windows to app_shell's root window.
+class ShellViewsDelegate : public views::TestViewsDelegate {
+ public:
+  explicit ShellViewsDelegate(aura::Window* root_window)
+      : root_window_(root_window) {}
+  virtual ~ShellViewsDelegate() {}
+
+  // views::ViewsDelegate implementation.
+  virtual void OnBeforeWidgetInit(
+      views::Widget::InitParams* params,
+      views::internal::NativeWidgetDelegate* delegate) OVERRIDE {
+    if (!params->parent)
+      params->parent = root_window_;
+  }
+
+ private:
+  aura::Window* root_window_;  // Not owned.
+
+  DISALLOW_COPY_AND_ASSIGN(ShellViewsDelegate);
+};
+
+}  // namespace
+
+ShellDesktopController::ShellDesktopController() {
+#if defined(OS_CHROMEOS)
+  output_configurator_.reset(new ui::OutputConfigurator);
+  output_configurator_->Init(false);
+  output_configurator_->ForceInitialConfigure(0);
+  output_configurator_->AddObserver(this);
+#endif
+  CreateRootWindow();
+
+  DCHECK(!views::ViewsDelegate::views_delegate);
+  views::ViewsDelegate::views_delegate =
+      new ShellViewsDelegate(wm_test_helper_->host()->window());
+}
+
+ShellDesktopController::~ShellDesktopController() {
+  delete views::ViewsDelegate::views_delegate;
+  views::ViewsDelegate::views_delegate = NULL;
+  DestroyRootWindow();
+  aura::Env::DeleteInstance();
+}
+
+aura::WindowTreeHost* ShellDesktopController::GetWindowTreeHost() {
+  return wm_test_helper_->host();
+}
+
+#if defined(OS_CHROMEOS)
+void ShellDesktopController::OnDisplayModeChanged(
+    const std::vector<ui::OutputConfigurator::DisplayState>& outputs) {
+  gfx::Size size = GetPrimaryDisplaySize();
+  if (!size.IsEmpty())
+    wm_test_helper_->host()->UpdateRootWindowSize(size);
+}
+#endif
+
+void ShellDesktopController::CreateRootWindow() {
+  test_screen_.reset(aura::TestScreen::Create());
+  // TODO(jamescook): Replace this with a real Screen implementation.
+  gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen_.get());
+  // TODO(jamescook): Initialize a real input method.
+  ui::InitializeInputMethodForTesting();
+
+  // Set up basic pieces of views::corewm.
+  gfx::Size size = GetPrimaryDisplaySize();
+  if (size.IsEmpty())
+    size = gfx::Size(800, 600);
+  wm_test_helper_.reset(new wm::WMTestHelper(size));
+  wm_test_helper_->host()->compositor()->SetBackgroundColor(kBackgroundColor);
+
+  // Ensure the X window gets mapped.
+  wm_test_helper_->host()->Show();
+}
+
+void ShellDesktopController::DestroyRootWindow() {
+  wm_test_helper_.reset();
+  ui::ShutdownInputMethodForTesting();
+}
+
+gfx::Size ShellDesktopController::GetPrimaryDisplaySize() {
+#if defined(OS_CHROMEOS)
+  const std::vector<ui::OutputConfigurator::DisplayState>& states =
+      output_configurator_->cached_outputs();
+  if (states.empty())
+    return gfx::Size();
+  const ui::DisplayMode* mode = states[0].display->current_mode();
+  return mode ? mode->size() : gfx::Size();
+#else
+  return gfx::Size();
+#endif
+}
+
+}  // namespace apps
diff --git a/apps/shell/browser/shell_desktop_controller.h b/apps/shell/browser/shell_desktop_controller.h
new file mode 100644
index 0000000..3420790
--- /dev/null
+++ b/apps/shell/browser/shell_desktop_controller.h
@@ -0,0 +1,74 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef APPS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_H_
+#define APPS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/aura/window_tree_host_observer.h"
+#include "ui/gfx/geometry/size.h"
+
+#if defined(OS_CHROMEOS)
+#include "ui/display/chromeos/output_configurator.h"
+#endif
+
+namespace aura {
+class TestScreen;
+class WindowTreeHost;
+}
+
+namespace wm {
+class WMTestHelper;
+}
+
+namespace apps {
+
+// Handles desktop-related tasks for app_shell.
+class ShellDesktopController
+#if defined(OS_CHROMEOS)
+    : public ui::OutputConfigurator::Observer
+#endif
+      {
+ public:
+  ShellDesktopController();
+  virtual ~ShellDesktopController();
+
+  // Returns the host for the Aura window tree.
+  aura::WindowTreeHost* GetWindowTreeHost();
+
+#if defined(OS_CHROMEOS)
+  // ui::OutputConfigurator::Observer overrides.
+  virtual void OnDisplayModeChanged(
+      const std::vector<ui::OutputConfigurator::DisplayState>& outputs)
+      OVERRIDE;
+#endif
+
+ private:
+  // Creates the window that hosts the app.
+  void CreateRootWindow();
+
+  // Closes and destroys the root window hosting the app.
+  void DestroyRootWindow();
+
+  // Returns the dimensions (in pixels) of the primary display, or an empty size
+  // if the dimensions can't be determined or no display is connected.
+  gfx::Size GetPrimaryDisplaySize();
+
+#if defined(OS_CHROMEOS)
+  scoped_ptr<ui::OutputConfigurator> output_configurator_;
+#endif
+
+  // Enable a minimal set of views::corewm to be initialized.
+  scoped_ptr<wm::WMTestHelper> wm_test_helper_;
+
+  scoped_ptr<aura::TestScreen> test_screen_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShellDesktopController);
+};
+
+}  // namespace apps
+
+#endif  // APPS_SHELL_BROWSER_SHELL_DESKTOP_CONTROLLER_H_
diff --git a/apps/shell/browser/web_view_window.cc b/apps/shell/browser/web_view_window.cc
deleted file mode 100644
index 88b24ce..0000000
--- a/apps/shell/browser/web_view_window.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "apps/shell/browser/web_view_window.h"
-
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
-#include "ui/aura/window.h"
-#include "ui/views/controls/webview/webview.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_delegate.h"
-
-namespace {
-
-// A simple window containing a single web view.
-class WebViewWindowContents : public views::WidgetDelegateView {
- public:
-  explicit WebViewWindowContents(content::BrowserContext* browser_context)
-      : browser_context_(browser_context) {}
-  virtual ~WebViewWindowContents() {}
-
-  // views::WidgetDelegateView overrides:
-  virtual views::View* GetContentsView() OVERRIDE;
-  virtual void WindowClosing() OVERRIDE;
-
-  // views::View overrides:
-  virtual void ViewHierarchyChanged(
-      const ViewHierarchyChangedDetails& details) OVERRIDE;
-
- private:
-  // Initialize this view's children.
-  void InitChildViews();
-
-  content::BrowserContext* browser_context_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebViewWindowContents);
-};
-
-views::View* WebViewWindowContents::GetContentsView() {
-  return this;
-}
-
-void WebViewWindowContents::WindowClosing() {
-  // Close the app when the window is closed.
-  if (base::MessageLoopForUI::current()->is_running())
-    base::MessageLoopForUI::current()->Quit();
-}
-
-void WebViewWindowContents::ViewHierarchyChanged(
-    const ViewHierarchyChangedDetails& details) {
-  // Initialize child views when this view is attached.
-  if (details.is_add && details.child == this)
-    InitChildViews();
-}
-
-void WebViewWindowContents::InitChildViews() {
-  // Create a WebView that fills the window.
-  SetLayoutManager(new views::FillLayout);
-  views::WebView* web_view = new views::WebView(browser_context_);
-  AddChildView(web_view);
-
-  web_view->LoadInitialURL(GURL("http://www.google.com/"));
-  web_view->web_contents()->GetView()->Focus();
-}
-
-}  // namespace
-
-namespace apps {
-
-views::Widget* CreateWebViewWindow(content::BrowserContext* browser_context,
-                                 aura::Window* window_context) {
-  views::Widget* widget = new views::Widget;
-  views::Widget::InitParams params;
-  params.delegate = new WebViewWindowContents(browser_context);
-  params.context = window_context;
-  // Make widget owns the native_widget, so that the pointer of widget is still
-  // valid after user click the close button of the widget inside root window.
-  // app_shell client controls the widget lifetime.
-  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
-  params.bounds = window_context->bounds();
-  params.top_level = true;
-  widget->Init(params);
-  return widget;
-}
-
-}  // namespace apps
diff --git a/apps/shell/browser/web_view_window.h b/apps/shell/browser/web_view_window.h
deleted file mode 100644
index e3d53f7..0000000
--- a/apps/shell/browser/web_view_window.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef APPS_SHELL_BROWSER_WEB_VIEW_WINDOW_H_
-#define APPS_SHELL_BROWSER_WEB_VIEW_WINDOW_H_
-
-namespace aura {
-class Window;
-}
-
-namespace content {
-class BrowserContext;
-}
-
-namespace views {
-class Widget;
-}
-
-namespace apps {
-
-// Create an example window containing a WebView.
-views::Widget* CreateWebViewWindow(content::BrowserContext* browser_context,
-                                   aura::Window* window_context);
-
-}  // namespace apps
-
-#endif  // APPS_SHELL_BROWSER_WEB_VIEW_WINDOW_H_
diff --git a/apps/test/app_shell_test.cc b/apps/test/app_shell_test.cc
new file mode 100644
index 0000000..9baf997
--- /dev/null
+++ b/apps/test/app_shell_test.cc
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "apps/test/app_shell_test.h"
+
+#include "apps/apps_client.h"
+#include "apps/shell/browser/shell_browser_context.h"
+#include "apps/shell/browser/shell_extension_system.h"
+#include "apps/shell/browser/shell_extension_system_factory.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/common/extension_paths.h"
+
+namespace apps {
+
+AppShellTest::AppShellTest() {}
+
+AppShellTest::~AppShellTest() {}
+
+void AppShellTest::SetUpOnMainThread() {
+  std::vector<content::BrowserContext*> contexts =
+      AppsClient::Get()->GetLoadedBrowserContexts();
+  CHECK_EQ(1U, contexts.size());
+  browser_context_ = contexts[0];
+
+  extension_system_ = static_cast<extensions::ShellExtensionSystem*>(
+      extensions::ExtensionSystem::Get(browser_context_));
+}
+
+void AppShellTest::RunTestOnMainThreadLoop() {
+  // Pump startup related events.
+  base::MessageLoopForUI::current()->RunUntilIdle();
+
+  SetUpOnMainThread();
+
+  RunTestOnMainThread();
+
+  TearDownOnMainThread();
+
+  // TODO(yoz): Make windows close. This doesn't seem to close the root window.
+  extension_system_->CloseApp();
+}
+
+bool AppShellTest::LoadAndLaunchApp(const base::FilePath& app_dir) {
+  return extension_system_->LoadAndLaunchApp(app_dir);
+}
+
+}  // namespace apps
diff --git a/apps/test/app_shell_test.h b/apps/test/app_shell_test.h
new file mode 100644
index 0000000..e6be460
--- /dev/null
+++ b/apps/test/app_shell_test.h
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef APPS_TEST_APP_SHELL_TEST_H_
+#define APPS_TEST_APP_SHELL_TEST_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_base.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace extensions {
+class ShellExtensionSystem;
+}
+
+namespace apps {
+
+// Base class for app shell browser tests.
+class AppShellTest : public content::BrowserTestBase {
+ public:
+  AppShellTest();
+  virtual ~AppShellTest();
+
+  virtual void SetUpOnMainThread() OVERRIDE;
+  virtual void RunTestOnMainThreadLoop() OVERRIDE;
+
+  // Loads an unpacked application from a directory using |extension_system_|
+  // and attempts to launch it. Returns true on success.
+  bool LoadAndLaunchApp(const base::FilePath& app_dir);
+
+  content::BrowserContext* browser_context() { return browser_context_; }
+
+ private:
+  content::BrowserContext* browser_context_;
+  extensions::ShellExtensionSystem* extension_system_;
+};
+
+}  // namespace apps
+
+#endif  // APPS_TEST_APP_SHELL_TEST_H_
diff --git a/apps/test/apps_test_launcher_delegate.cc b/apps/test/apps_test_launcher_delegate.cc
new file mode 100644
index 0000000..dec4a18
--- /dev/null
+++ b/apps/test/apps_test_launcher_delegate.cc
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "apps/test/apps_test_launcher_delegate.h"
+
+#include "apps/shell/app/shell_main_delegate.h"
+#include "base/test/test_suite.h"
+
+namespace apps {
+
+int AppsTestLauncherDelegate::RunTestSuite(int argc, char** argv) {
+  return base::TestSuite(argc, argv).Run();
+}
+
+bool AppsTestLauncherDelegate::AdjustChildProcessCommandLine(
+    base::CommandLine* command_line,
+    const base::FilePath& temp_data_dir) {
+  return true;
+}
+
+content::ContentMainDelegate*
+AppsTestLauncherDelegate::CreateContentMainDelegate() {
+  return new ShellMainDelegate();
+}
+
+}  // namespace apps
diff --git a/apps/test/apps_test_launcher_delegate.h b/apps/test/apps_test_launcher_delegate.h
new file mode 100644
index 0000000..60dc175
--- /dev/null
+++ b/apps/test/apps_test_launcher_delegate.h
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef APPS_TEST_APPS_TEST_LAUNCHER_DELEGATE_H_
+#define APPS_TEST_APPS_TEST_LAUNCHER_DELEGATE_H_
+
+#include "content/public/test/test_launcher.h"
+
+namespace apps {
+
+class AppsTestLauncherDelegate : public content::TestLauncherDelegate {
+ public:
+  virtual int RunTestSuite(int argc, char** argv) OVERRIDE;
+  virtual bool AdjustChildProcessCommandLine(
+      base::CommandLine* command_line,
+      const base::FilePath& temp_data_dir) OVERRIDE;
+  virtual content::ContentMainDelegate* CreateContentMainDelegate() OVERRIDE;
+};
+
+}  // namespace apps
+
+#endif  // APPS_TEST_APPS_TEST_LAUNCHER_DELEGATE_H_
diff --git a/apps/test/apps_tests_main.cc b/apps/test/apps_tests_main.cc
new file mode 100644
index 0000000..080841e
--- /dev/null
+++ b/apps/test/apps_tests_main.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <algorithm>
+
+#include "apps/test/apps_test_launcher_delegate.h"
+#include "base/sys_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+int main(int argc, char** argv) {
+  int default_jobs = std::max(1, base::SysInfo::NumberOfProcessors() / 2);
+  apps::AppsTestLauncherDelegate launcher_delegate;
+  return content::LaunchTests(&launcher_delegate, default_jobs, argc, argv);
+}
diff --git a/apps/ui/views/app_window_frame_view.cc b/apps/ui/views/app_window_frame_view.cc
index e1c399f..5f7842c 100644
--- a/apps/ui/views/app_window_frame_view.cc
+++ b/apps/ui/views/app_window_frame_view.cc
@@ -4,12 +4,12 @@
 
 #include "apps/ui/views/app_window_frame_view.h"
 
-#include "apps/ui/native_app_window.h"
 #include "base/strings/utf_string_conversions.h"
 #include "extensions/common/draggable_region.h"
 #include "grit/theme_resources.h"
 #include "grit/ui_strings.h"  // Accessibility names
 #include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkRegion.h"
 #include "ui/base/hit_test.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -37,9 +37,9 @@
 const char AppWindowFrameView::kViewClassName[] =
     "browser/ui/views/extensions/AppWindowFrameView";
 
-AppWindowFrameView::AppWindowFrameView(NativeAppWindow* window)
-    : window_(window),
-      widget_(NULL),
+AppWindowFrameView::AppWindowFrameView()
+    : widget_(NULL),
+      draggable_region_(NULL),
       close_button_(NULL),
       maximize_button_(NULL),
       restore_button_(NULL),
@@ -51,18 +51,22 @@
 AppWindowFrameView::~AppWindowFrameView() {}
 
 void AppWindowFrameView::Init(views::Widget* widget,
+                              bool draw_frame,
                               const SkColor& frame_color,
+                              const SkRegion* draggable_region,
                               int resize_inside_bounds_size,
                               int resize_outside_bounds_size,
                               int resize_outside_scale_for_touch,
                               int resize_area_corner_size) {
   widget_ = widget;
+  draw_frame_ = draw_frame;
   frame_color_ = frame_color;
+  draggable_region_ = draggable_region;
   resize_inside_bounds_size_ = resize_inside_bounds_size;
   resize_outside_bounds_size_ = resize_outside_bounds_size;
   resize_area_corner_size_ = resize_area_corner_size;
 
-  if (!window_->IsFrameless()) {
+  if (draw_frame) {
     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
     close_button_ = new views::ImageButton(this);
     close_button_->SetImage(
@@ -125,7 +129,7 @@
 // views::NonClientFrameView implementation.
 
 gfx::Rect AppWindowFrameView::GetBoundsForClientView() const {
-  if (window_->IsFrameless() || widget_->IsFullscreen())
+  if (!draw_frame_ || widget_->IsFullscreen())
     return bounds();
   return gfx::Rect(
       0, kCaptionHeight, width(), std::max(0, height() - kCaptionHeight));
@@ -133,8 +137,16 @@
 
 gfx::Rect AppWindowFrameView::GetWindowBoundsForClientBounds(
     const gfx::Rect& client_bounds) const {
-  if (window_->IsFrameless()) {
-    gfx::Rect window_bounds = client_bounds;
+  gfx::Rect window_bounds = client_bounds;
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  // Get the difference between the widget's client area bounds and window
+  // bounds, and grow |window_bounds| by that amount.
+  gfx::Insets native_frame_insets =
+      widget_->GetClientAreaBoundsInScreen().InsetsFrom(
+          widget_->GetWindowBoundsInScreen());
+  window_bounds.Inset(native_frame_insets);
+#endif
+  if (!draw_frame_) {
     // Enforce minimum size (1, 1) in case that client_bounds is passed with
     // empty size. This could occur when the frameless window is being
     // initialized.
@@ -147,10 +159,10 @@
 
   int closeButtonOffsetX = (kCaptionHeight - close_button_->height()) / 2;
   int header_width = close_button_->width() + closeButtonOffsetX * 2;
-  return gfx::Rect(client_bounds.x(),
-                   client_bounds.y() - kCaptionHeight,
-                   std::max(header_width, client_bounds.width()),
-                   client_bounds.height() + kCaptionHeight);
+  return gfx::Rect(window_bounds.x(),
+                   window_bounds.y() - kCaptionHeight,
+                   std::max(header_width, window_bounds.width()),
+                   window_bounds.height() + kCaptionHeight);
 }
 
 int AppWindowFrameView::NonClientHitTest(const gfx::Point& point) {
@@ -189,11 +201,8 @@
 
   // Check for possible draggable region in the client area for the frameless
   // window.
-  if (window_->IsFrameless()) {
-    SkRegion* draggable_region = window_->GetDraggableRegion();
-    if (draggable_region && draggable_region->contains(point.x(), point.y()))
-      return HTCAPTION;
-  }
+  if (draggable_region_ && draggable_region_->contains(point.x(), point.y()))
+    return HTCAPTION;
 
   int client_component = widget_->client_view()->NonClientHitTest(point);
   if (client_component != HTNOWHERE)
@@ -235,7 +244,7 @@
 }
 
 void AppWindowFrameView::Layout() {
-  if (window_->IsFrameless())
+  if (!draw_frame_)
     return;
   gfx::Size close_size = close_button_->GetPreferredSize();
   const int kButtonOffsetY = 0;
@@ -282,7 +291,7 @@
 }
 
 void AppWindowFrameView::OnPaint(gfx::Canvas* canvas) {
-  if (window_->IsFrameless())
+  if (!draw_frame_)
     return;
 
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
@@ -314,7 +323,7 @@
 
 gfx::Size AppWindowFrameView::GetMinimumSize() {
   gfx::Size min_size = widget_->client_view()->GetMinimumSize();
-  if (window_->IsFrameless())
+  if (!draw_frame_)
     return min_size;
 
   // Ensure we can display the top of the caption area.
@@ -346,7 +355,7 @@
 
 void AppWindowFrameView::ButtonPressed(views::Button* sender,
                                        const ui::Event& event) {
-  DCHECK(!window_->IsFrameless());
+  DCHECK(draw_frame_);
   if (sender == close_button_)
     widget_->Close();
   else if (sender == maximize_button_)
diff --git a/apps/ui/views/app_window_frame_view.h b/apps/ui/views/app_window_frame_view.h
index 69e84e9..64379f8 100644
--- a/apps/ui/views/app_window_frame_view.h
+++ b/apps/ui/views/app_window_frame_view.h
@@ -7,12 +7,15 @@
 
 #include <string>
 
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/gfx/path.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/size.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/window/non_client_view.h"
 
+class SkRegion;
+
 namespace gfx {
 class Canvas;
 class Point;
@@ -29,22 +32,24 @@
 
 namespace apps {
 
-class NativeAppWindow;
-
 // A frameless or non-Ash, non-panel NonClientFrameView for app windows.
 class AppWindowFrameView : public views::NonClientFrameView,
                            public views::ButtonListener {
  public:
   static const char kViewClassName[];
 
-  explicit AppWindowFrameView(NativeAppWindow* window);
+  explicit AppWindowFrameView();
   virtual ~AppWindowFrameView();
 
   // Initializes this for |widget|. Sets the number of pixels for which a click
   // is interpreted as a resize for the inner and outer border of the window
-  // and the lower-right corner resize handle.
+  // and the lower-right corner resize handle. If |draw_frame|, the view draws
+  // its own window title area and controls, using |frame_color| (otherwise
+  // |frame_color| is ignored). |draggable_region| may be NULL.
   void Init(views::Widget* widget,
+            bool draw_frame,
             const SkColor& frame_color,
+            const SkRegion* draggable_region,
             int resize_inside_bounds_size,
             int resize_outside_bounds_size,
             int resize_outside_scale_for_touch,
@@ -74,9 +79,10 @@
   virtual void ButtonPressed(views::Button* sender,
                              const ui::Event& event) OVERRIDE;
 
-  NativeAppWindow* window_;
   views::Widget* widget_;
+  bool draw_frame_;
   SkColor frame_color_;
+  const SkRegion* draggable_region_;
   views::ImageButton* close_button_;
   views::ImageButton* maximize_button_;
   views::ImageButton* restore_button_;
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index 7195004..9f1d226 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -1140,13 +1140,7 @@
 
 void AcceleratorController::SetBrightnessControlDelegate(
     scoped_ptr<BrightnessControlDelegate> brightness_control_delegate) {
-  // Install brightness control delegate only when internal
-  // display exists.
-  if (Shell::GetInstance()->display_manager()->HasInternalDisplay() ||
-      CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAshEnableBrightnessControl)) {
-    brightness_control_delegate_ = brightness_control_delegate.Pass();
-  }
+  brightness_control_delegate_ = brightness_control_delegate.Pass();
 }
 
 void AcceleratorController::SetImeControlDelegate(
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index 80a2345..5be401a 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -754,18 +754,6 @@
   const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
   const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
   {
-    EXPECT_FALSE(ProcessWithContext(brightness_down));
-    EXPECT_FALSE(ProcessWithContext(brightness_up));
-    DummyBrightnessControlDelegate* delegate =
-        new DummyBrightnessControlDelegate(true);
-    GetController()->SetBrightnessControlDelegate(
-        scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
-    EXPECT_FALSE(ProcessWithContext(brightness_down));
-    EXPECT_FALSE(ProcessWithContext(brightness_up));
-  }
-  // Enable internal display.
-  EnableInternalDisplay();
-  {
     DummyBrightnessControlDelegate* delegate =
         new DummyBrightnessControlDelegate(false);
     GetController()->SetBrightnessControlDelegate(
@@ -1167,19 +1155,6 @@
   const ui::Accelerator brightness_down(ui::VKEY_BRIGHTNESS_DOWN, ui::EF_NONE);
   const ui::Accelerator brightness_up(ui::VKEY_BRIGHTNESS_UP, ui::EF_NONE);
   {
-    EXPECT_FALSE(ProcessWithContext(brightness_down));
-    EXPECT_FALSE(ProcessWithContext(brightness_up));
-    DummyBrightnessControlDelegate* delegate =
-        new DummyBrightnessControlDelegate(true);
-    GetController()->SetBrightnessControlDelegate(
-        scoped_ptr<BrightnessControlDelegate>(delegate).Pass());
-    EXPECT_FALSE(ProcessWithContext(brightness_down));
-    EXPECT_FALSE(ProcessWithContext(brightness_up));
-  }
-  EnableInternalDisplay();
-  {
-    EXPECT_FALSE(ProcessWithContext(brightness_down));
-    EXPECT_FALSE(ProcessWithContext(brightness_up));
     DummyBrightnessControlDelegate* delegate =
         new DummyBrightnessControlDelegate(false);
     GetController()->SetBrightnessControlDelegate(
diff --git a/ash/accelerators/nested_dispatcher_controller.h b/ash/accelerators/nested_dispatcher_controller.h
index 74dcd90..b3db4e9 100644
--- a/ash/accelerators/nested_dispatcher_controller.h
+++ b/ash/accelerators/nested_dispatcher_controller.h
@@ -8,7 +8,7 @@
 #include "ash/ash_export.h"
 #include "base/callback.h"
 #include "base/message_loop/message_loop.h"
-#include "ui/aura/client/dispatcher_client.h"
+#include "ui/wm/public/dispatcher_client.h"
 
 namespace ash {
 
diff --git a/ash/accelerators/nested_dispatcher_controller_unittest.cc b/ash/accelerators/nested_dispatcher_controller_unittest.cc
index b40903e..cc0a352 100644
--- a/ash/accelerators/nested_dispatcher_controller_unittest.cc
+++ b/ash/accelerators/nested_dispatcher_controller_unittest.cc
@@ -10,13 +10,13 @@
 #include "base/bind.h"
 #include "base/event_types.h"
 #include "base/message_loop/message_loop.h"
-#include "ui/aura/client/dispatcher_client.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/event_utils.h"
+#include "ui/wm/public/dispatcher_client.h"
 
 #if defined(USE_X11)
 #include <X11/Xlib.h>
diff --git a/ash/accessibility_delegate.h b/ash/accessibility_delegate.h
index 037a40f..7a1b400 100644
--- a/ash/accessibility_delegate.h
+++ b/ash/accessibility_delegate.h
@@ -21,7 +21,7 @@
   A11Y_ALERT_WINDOW_NEEDED
 };
 
-// A deletate class to control accessibility features.
+// A delegate class to control and query accessibility features.
 class ASH_EXPORT AccessibilityDelegate {
  public:
   virtual ~AccessibilityDelegate() {}
@@ -45,7 +45,7 @@
   // Invoked to change the type of the screen magnifier.
   virtual void SetMagnifierType(MagnifierType type) = 0;
 
-  // Returns true if the screen magnifier is enabled or not.
+  // Returns true if the screen magnifier is enabled.
   virtual bool IsMagnifierEnabled() const = 0;
 
   // Returns the current screen magnifier mode.
@@ -54,7 +54,7 @@
   // Invoked to enable Large Cursor.
   virtual void SetLargeCursorEnabled(bool enabled) = 0;
 
-  // Returns ture if Large Cursor is enabled or not.
+  // Returns ture if Large Cursor is enabled.
   virtual bool IsLargeCursorEnabled() const = 0;
 
   // Invoked to enable autoclick.
@@ -72,6 +72,9 @@
   // Returns true when the accessibility menu should be shown.
   virtual bool ShouldShowAccessibilityMenu() const = 0;
 
+  // Returns true if a braille display is connected to the system.
+  virtual bool IsBrailleDisplayConnected() const = 0;
+
   // Cancel all current and queued speech immediately.
   virtual void SilenceSpokenFeedback() const = 0;
 
diff --git a/ash/ash.gyp b/ash/ash.gyp
index c65d6ed..ebb6e60 100644
--- a/ash/ash.gyp
+++ b/ash/ash.gyp
@@ -25,12 +25,14 @@
         '../skia/skia.gyp:skia',
         '../third_party/icu/icu.gyp:icui18n',
         '../third_party/icu/icu.gyp:icuuc',
+        '../ui/accessibility/accessibility.gyp:accessibility',
         '../ui/app_list/app_list.gyp:app_list',
         '../ui/aura/aura.gyp:aura',
         '../ui/base/strings/ui_strings.gyp:ui_strings',
         '../ui/base/ui_base.gyp:ui_base',
         '../ui/compositor/compositor.gyp:compositor',
         '../ui/events/events.gyp:events',
+        '../ui/events/events.gyp:events_base',
         '../ui/gfx/gfx.gyp:gfx',
         '../ui/gfx/gfx.gyp:gfx_geometry',
         '../ui/keyboard/keyboard.gyp:keyboard',
@@ -550,7 +552,7 @@
         'wm/maximize_mode/maximize_mode_window_manager.cc',
         'wm/maximize_mode/maximize_mode_window_manager.h',
         'wm/maximize_mode/maximize_mode_window_state.cc',
-        'wm/maximize_mode/maximize_mode_window_state.h',        
+        'wm/maximize_mode/maximize_mode_window_state.h',
         'wm/maximize_mode/workspace_backdrop_delegate.cc',
         'wm/maximize_mode/workspace_backdrop_delegate.h',
         'wm/mru_window_tracker.cc',
@@ -675,10 +677,6 @@
             ['exclude', 'accelerators/magnifier_key_scroller.h'],
             ['exclude', 'accelerators/spoken_feedback_toggler.cc'],
             ['exclude', 'accelerators/spoken_feedback_toggler.h'],
-            ['exclude', 'display/display_change_observer_chromeos.cc'],
-            ['exclude', 'display/display_change_observer_chromeos.h'],
-            ['exclude', 'display/display_error_observer_chromeos.cc'],
-            ['exclude', 'display/display_error_observer_chromeos.h'],
           ],
         }],
         ['chromeos==1', {
@@ -847,10 +845,10 @@
         '../ui/message_center/message_center.gyp:message_center_test_support',
         '../ui/resources/ui_resources.gyp:ui_resources',
         '../ui/ui_unittests.gyp:ui_test_support',
+        '../ui/views/controls/webview/webview_tests.gyp:webview_test_support',
+        '../ui/views/examples/examples.gyp:views_examples_with_content_lib',
         '../ui/views/views.gyp:views',
-        '../ui/views/views.gyp:views_examples_with_content_lib',
         '../ui/views/views.gyp:views_test_support',
-        '../ui/views/views.gyp:views_with_content_test_support',
         '../ui/web_dialogs/web_dialogs.gyp:web_dialogs_test_support',
         '../ui/wm/wm.gyp:wm_core',
         '../url/url.gyp:url_lib',
@@ -1029,8 +1027,6 @@
           'sources/': [
             ['exclude', 'accelerators/magnifier_key_scroller_unittest.cc'],
             ['exclude', 'accelerators/spoken_feedback_toggler_unittest.cc'],
-            ['exclude', 'display/display_change_observer_chromeos_unittest.cc'],
-            ['exclude', 'display/display_error_observer_chromeos_unittest.cc'],
           ],
         }],
         ['chromeos==1', {
@@ -1082,9 +1078,9 @@
         '../ui/keyboard/keyboard.gyp:keyboard',
         '../ui/message_center/message_center.gyp:message_center',
         '../ui/resources/ui_resources.gyp:ui_resources',
+        '../ui/views/examples/examples.gyp:views_examples_lib',
+        '../ui/views/examples/examples.gyp:views_examples_with_content_lib',
         '../ui/views/views.gyp:views',
-        '../ui/views/views.gyp:views_examples_lib',
-        '../ui/views/views.gyp:views_examples_with_content_lib',
         '../ui/views/views.gyp:views_test_support',
         'ash',
         'ash_resources',
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index e0531e4..1e5ed6f 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -208,6 +208,9 @@
       <message name="IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME" desc="The accessible name of the status tray.">
         Status tray
       </message>
+      <message name="IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED_BUBBLE" desc="The message shown on a bubble when a braille display is connected">
+Braille display connected.
+      </message>
       <message name="IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE" desc="The message shown on a bubble when spoken feedback is enabled">
 ChromeVox (spoken feedback) is enabled.
 Press Ctrl+Alt+Z to disable.
diff --git a/ash/ash_switches.cc b/ash/ash_switches.cc
index a96fafd..7c3146f 100644
--- a/ash/ash_switches.cc
+++ b/ash/ash_switches.cc
@@ -57,10 +57,6 @@
 const char kAshEnableAlternateFrameCaptionButtonStyle[] =
     "ash-enable-alternate-caption-button";
 
-// Always enable brightness control. Used by machines that don't report their
-// main monitor as internal.
-const char kAshEnableBrightnessControl[] = "ash-enable-brightness-control";
-
 #if defined(OS_CHROMEOS)
 // Enables key bindings to scroll magnified screen.
 const char kAshEnableMagnifierKeyScroller[] =
diff --git a/ash/ash_switches.h b/ash/ash_switches.h
index 80ab2db..829ee96 100644
--- a/ash/ash_switches.h
+++ b/ash/ash_switches.h
@@ -28,7 +28,6 @@
 ASH_EXPORT extern const char kAshDisableAlternateShelfLayout[];
 ASH_EXPORT extern const char kAshDisableDockedWindows[];
 ASH_EXPORT extern const char kAshEnableAlternateFrameCaptionButtonStyle[];
-ASH_EXPORT extern const char kAshEnableBrightnessControl[];
 #if defined(OS_CHROMEOS)
 ASH_EXPORT extern const char kAshEnableMagnifierKeyScroller[];
 ASH_EXPORT extern const char kAshEnableMultiUserTray[];
diff --git a/ash/default_accessibility_delegate.cc b/ash/default_accessibility_delegate.cc
index 975c3b6..169b4f7 100644
--- a/ash/default_accessibility_delegate.cc
+++ b/ash/default_accessibility_delegate.cc
@@ -83,6 +83,10 @@
          virtual_keyboard_enabled_;
 }
 
+bool DefaultAccessibilityDelegate::IsBrailleDisplayConnected() const {
+  return false;
+}
+
 void DefaultAccessibilityDelegate::SilenceSpokenFeedback() const {
 }
 
diff --git a/ash/default_accessibility_delegate.h b/ash/default_accessibility_delegate.h
index 6254218..4804bbd 100644
--- a/ash/default_accessibility_delegate.h
+++ b/ash/default_accessibility_delegate.h
@@ -32,6 +32,7 @@
   virtual void SetVirtualKeyboardEnabled(bool enabled) OVERRIDE;
   virtual bool IsVirtualKeyboardEnabled() const OVERRIDE;
   virtual bool ShouldShowAccessibilityMenu() const OVERRIDE;
+  virtual bool IsBrailleDisplayConnected() const OVERRIDE;
   virtual void SilenceSpokenFeedback() const OVERRIDE;
   virtual void ToggleSpokenFeedback(
       AccessibilityNotificationVisibility notify) OVERRIDE;
diff --git a/ash/desktop_background/desktop_background_view.cc b/ash/desktop_background/desktop_background_view.cc
index 0f14604..b0e3149 100644
--- a/ash/desktop_background/desktop_background_view.cc
+++ b/ash/desktop_background/desktop_background_view.cc
@@ -188,6 +188,7 @@
     params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
   params.parent = root_window->GetChildById(container_id);
   desktop_widget->Init(params);
+  desktop_widget->GetNativeWindow()->layer()->SetMasksToBounds(true);
   desktop_widget->SetContentsView(
       new LayerControlView(new DesktopBackgroundView()));
   int animation_type = wallpaper_delegate->GetAnimationType();
diff --git a/ash/dip_unittest.cc b/ash/dip_unittest.cc
index 6c23910..748c78f 100644
--- a/ash/dip_unittest.cc
+++ b/ash/dip_unittest.cc
@@ -15,7 +15,6 @@
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/compositor/layer.h"
@@ -26,6 +25,7 @@
 #include "ui/wm/core/shadow.h"
 #include "ui/wm/core/shadow_controller.h"
 #include "ui/wm/core/shadow_types.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 
diff --git a/ash/display/cursor_window_controller.cc b/ash/display/cursor_window_controller.cc
index 6fb1a08..abc5175 100644
--- a/ash/display/cursor_window_controller.cc
+++ b/ash/display/cursor_window_controller.cc
@@ -58,8 +58,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
   virtual bool HasHitTestMask() const OVERRIDE { return false; }
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE {}
 
   // Sets cursor compositing mode on/off.
   void SetCursorCompositingEnabled(bool enabled) {
diff --git a/ash/display/display_change_observer_chromeos.cc b/ash/display/display_change_observer_chromeos.cc
index 6aca864..97c9d26 100644
--- a/ash/display/display_change_observer_chromeos.cc
+++ b/ash/display/display_change_observer_chromeos.cc
@@ -158,13 +158,17 @@
     ids.insert(id);
 
     displays.push_back(DisplayInfo(id, name, has_overscan));
-    displays.back().set_device_scale_factor(device_scale_factor);
-    displays.back().SetBounds(display_bounds);
-    displays.back().set_native(true);
-    displays.back().set_display_modes(display_modes);
-    displays.back().set_touch_support(
+    DisplayInfo& new_info = displays.back();
+    new_info.set_device_scale_factor(device_scale_factor);
+    new_info.SetBounds(display_bounds);
+    new_info.set_native(true);
+    new_info.set_display_modes(display_modes);
+    new_info.set_touch_support(
         output.touch_device_id == 0 ? gfx::Display::TOUCH_SUPPORT_UNAVAILABLE :
                                       gfx::Display::TOUCH_SUPPORT_AVAILABLE);
+    new_info.set_available_color_profiles(
+        Shell::GetInstance()->output_configurator()->
+        GetAvailableColorCalibrationProfiles(id));
   }
 
   // DisplayManager can be null during the boot.
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index 03dda59..496eb1e 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -24,7 +24,6 @@
 #include "ash/wm/coordinate_conversion.h"
 #include "base/command_line.h"
 #include "base/strings/stringprintf.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/screen_position_client.h"
@@ -37,12 +36,13 @@
 #include "ui/compositor/compositor_vsync_manager.h"
 #include "ui/gfx/display.h"
 #include "ui/gfx/screen.h"
+#include "ui/wm/public/activation_client.h"
 
 #if defined(OS_CHROMEOS)
+#include "ash/display/output_configurator_animation.h"
 #include "base/sys_info.h"
 #include "base/time/time.h"
 #if defined(USE_X11)
-#include "ash/display/output_configurator_animation.h"
 #include "ui/base/x/x11_util.h"
 #include "ui/gfx/x/x11_types.h"
 
@@ -227,9 +227,7 @@
     : primary_root_window_for_replace_(NULL),
       focus_activation_store_(new internal::FocusActivationStore()),
       cursor_window_controller_(new internal::CursorWindowController()),
-      mirror_window_controller_(new internal::MirrorWindowController()),
-      virtual_keyboard_window_controller_(
-          new internal::VirtualKeyboardWindowController) {
+      mirror_window_controller_(new internal::MirrorWindowController()) {
 #if defined(OS_CHROMEOS)
   if (base::SysInfo::IsRunningOnChromeOS())
     limiter_.reset(new DisplayChangeLimiter);
@@ -243,6 +241,10 @@
 }
 
 void DisplayController::Start() {
+  // Created here so that Shell has finished being created. Adds itself
+  // as a ShellObserver.
+  virtual_keyboard_window_controller_.reset(
+      new internal::VirtualKeyboardWindowController);
   Shell::GetScreen()->AddObserver(this);
   Shell::GetInstance()->display_manager()->set_delegate(this);
 
@@ -371,7 +373,7 @@
       return;
     limiter_->SetThrottleTimeout(kCycleDisplayThrottleTimeoutMs);
   }
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   Shell* shell = Shell::GetInstance();
   internal::OutputConfiguratorAnimation* animation =
       shell->output_configurator_animation();
@@ -390,7 +392,7 @@
   }
 
   if (Shell::GetScreen()->GetNumDisplays() > 1) {
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
     internal::OutputConfiguratorAnimation* animation =
         Shell::GetInstance()->output_configurator_animation();
     if (animation) {
@@ -720,7 +722,7 @@
 }
 
 void DisplayController::OnFadeOutForSwapDisplayFinished() {
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   SetPrimaryDisplay(ScreenUtil::GetSecondaryDisplay());
   Shell::GetInstance()->output_configurator_animation()->StartFadeInAnimation();
 #endif
diff --git a/ash/display/display_controller_unittest.cc b/ash/display/display_controller_unittest.cc
index 6a49e2a..8c64560 100644
--- a/ash/display/display_controller_unittest.cc
+++ b/ash/display/display_controller_unittest.cc
@@ -20,8 +20,6 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
 #include "base/command_line.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/env.h"
@@ -32,6 +30,8 @@
 #include "ui/gfx/display.h"
 #include "ui/gfx/screen.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_client.h"
 
 #if defined(USE_X11)
 #include <X11/Xlib.h>
diff --git a/ash/display/display_info.cc b/ash/display/display_info.cc
index 17a1bc1..e3a4b63 100644
--- a/ash/display/display_info.cc
+++ b/ash/display/display_info.cc
@@ -173,7 +173,8 @@
       device_scale_factor_(1.0f),
       overscan_insets_in_dip_(0, 0, 0, 0),
       configured_ui_scale_(1.0f),
-      native_(false) {
+      native_(false),
+      color_profile_(ui::COLOR_PROFILE_STANDARD) {
 }
 
 DisplayInfo::DisplayInfo(int64 id,
@@ -187,7 +188,8 @@
       device_scale_factor_(1.0f),
       overscan_insets_in_dip_(0, 0, 0, 0),
       configured_ui_scale_(1.0f),
-      native_(false) {
+      native_(false),
+      color_profile_(ui::COLOR_PROFILE_STANDARD) {
 }
 
 DisplayInfo::~DisplayInfo() {
@@ -212,13 +214,17 @@
   if (!native_info.overscan_insets_in_dip_.empty())
     overscan_insets_in_dip_ = native_info.overscan_insets_in_dip_;
 
-  // Rotation_ and ui_scale_ are given by preference, or unit
-  // tests. Don't copy if this native_info came from
+  // Rotation_ and ui_scale_ color_profile_ are given by preference,
+  // or unit tests. Don't copy if this native_info came from
   // DisplayChangeObserver.
   if (!native_info.native()) {
     rotation_ = native_info.rotation_;
     configured_ui_scale_ = native_info.configured_ui_scale_;
+    color_profile_ = native_info.color_profile();
   }
+
+  available_color_profiles_ = native_info.available_color_profiles();
+
   // Don't copy insets as it may be given by preference.  |rotation_|
   // is treated as a native so that it can be specified in
   // |CreateFromSpec|.
@@ -298,5 +304,17 @@
   return ToString() + ", display_modes==" + display_modes_str;
 }
 
+void DisplayInfo::SetColorProfile(ui::ColorCalibrationProfile profile) {
+  if (IsColorProfileAvailable(profile))
+    color_profile_ = profile;
+}
+
+bool DisplayInfo::IsColorProfileAvailable(
+    ui::ColorCalibrationProfile profile) const {
+  return std::find(available_color_profiles_.begin(),
+                   available_color_profiles_.end(),
+                   profile) != available_color_profiles_.end();
+}
+
 }  // namespace internal
 }  // namespace ash
diff --git a/ash/display/display_info.h b/ash/display/display_info.h
index ccb989a..14af285 100644
--- a/ash/display/display_info.h
+++ b/ash/display/display_info.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "ash/ash_export.h"
+#include "ui/display/display_constants.h"
 #include "ui/gfx/display.h"
 #include "ui/gfx/insets.h"
 #include "ui/gfx/rect.h"
@@ -154,6 +155,27 @@
     display_modes_.swap(display_modes);
   }
 
+  ui::ColorCalibrationProfile color_profile() const {
+    return color_profile_;
+  }
+
+  // Sets the color profile. It will ignore if the specified |profile| is not in
+  // |available_color_profiles_|.
+  void SetColorProfile(ui::ColorCalibrationProfile profile);
+
+  // Returns true if |profile| is in |available_color_profiles_|.
+  bool IsColorProfileAvailable(ui::ColorCalibrationProfile profile) const;
+
+  const std::vector<ui::ColorCalibrationProfile>&
+      available_color_profiles() const {
+    return available_color_profiles_;
+  }
+
+  void set_available_color_profiles(
+      const std::vector<ui::ColorCalibrationProfile>& profiles) {
+    available_color_profiles_ = profiles;
+  }
+
   // Returns a string representation of the DisplayInfo, excluding display
   // modes.
   std::string ToString() const;
@@ -195,6 +217,12 @@
 
   // The list of modes supported by this display.
   std::vector<DisplayMode> display_modes_;
+
+  // The current profile of the color calibration.
+  ui::ColorCalibrationProfile color_profile_;
+
+  // The list of available variations for the color calibration.
+  std::vector<ui::ColorCalibrationProfile> available_color_profiles_;
 };
 
 }  // namespace internal
diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc
index ac3da91..fb4bd6e 100644
--- a/ash/display/display_manager.cc
+++ b/ash/display/display_manager.cc
@@ -17,6 +17,7 @@
 #include "base/auto_reset.h"
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
@@ -453,7 +454,7 @@
     return;
   }
   display_modes_[display_id] = *iter;
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   if (base::SysInfo::IsRunningOnChromeOS())
     Shell::GetInstance()->output_configurator()->OnConfigurationChanged();
 #endif
@@ -464,11 +465,13 @@
     gfx::Display::Rotation rotation,
     float ui_scale,
     const gfx::Insets* overscan_insets,
-    const gfx::Size& resolution_in_pixels) {
+    const gfx::Size& resolution_in_pixels,
+    ui::ColorCalibrationProfile color_profile) {
   if (display_info_.find(display_id) == display_info_.end())
     display_info_[display_id] = DisplayInfo(display_id, std::string(), false);
 
   display_info_[display_id].set_rotation(rotation);
+  display_info_[display_id].SetColorProfile(color_profile);
   // Just in case the preference file was corrupted.
   if (0.5f <= ui_scale && ui_scale <= 2.0f)
     display_info_[display_id].set_configured_ui_scale(ui_scale);
@@ -502,6 +505,26 @@
       it->second.overscan_insets_in_dip() : gfx::Insets();
 }
 
+void DisplayManager::SetColorCalibrationProfile(
+    int64 display_id,
+    ui::ColorCalibrationProfile profile) {
+#if defined(OS_CHROMEOS)
+  if (!display_info_[display_id].IsColorProfileAvailable(profile))
+    return;
+
+  if (delegate_)
+    delegate_->PreDisplayConfigurationChange(false);
+  if (Shell::GetInstance()->output_configurator()->SetColorCalibrationProfile(
+          display_id, profile)) {
+    display_info_[display_id].SetColorProfile(profile);
+    UMA_HISTOGRAM_ENUMERATION(
+        "ChromeOS.Display.ColorProfile", profile, ui::NUM_COLOR_PROFILES);
+  }
+  if (delegate_)
+    delegate_->PostDisplayConfigurationChange();
+#endif
+}
+
 void DisplayManager::OnNativeDisplaysChanged(
     const std::vector<DisplayInfo>& updated_displays) {
   if (updated_displays.empty()) {
@@ -972,6 +995,18 @@
     display_info_[new_info.id()].set_native(false);
   }
   display_info_[new_info.id()].UpdateDisplaySize();
+
+  OnDisplayInfoUpdated(display_info_[new_info.id()]);
+}
+
+void DisplayManager::OnDisplayInfoUpdated(const DisplayInfo& display_info) {
+#if defined(OS_CHROMEOS)
+  ui::ColorCalibrationProfile color_profile = display_info.color_profile();
+  if (color_profile != ui::COLOR_PROFILE_STANDARD) {
+    Shell::GetInstance()->output_configurator()->SetColorCalibrationProfile(
+        display_info.id(), color_profile);
+  }
+#endif
 }
 
 gfx::Display DisplayManager::CreateDisplayFromDisplayInfoById(int64 id) {
diff --git a/ash/display/display_manager.h b/ash/display/display_manager.h
index c17f73f..c672524 100644
--- a/ash/display/display_manager.h
+++ b/ash/display/display_manager.h
@@ -174,7 +174,8 @@
                                gfx::Display::Rotation rotation,
                                float ui_scale,
                                const gfx::Insets* overscan_insets,
-                               const gfx::Size& resolution_in_pixels);
+                               const gfx::Size& resolution_in_pixels,
+                               ui::ColorCalibrationProfile color_profile);
 
   // Returns the display's selected mode.
   bool GetSelectedModeForDisplayId(int64 display_id,
@@ -188,6 +189,10 @@
   // the display.
   gfx::Insets GetOverscanInsets(int64 display_id) const;
 
+  // Sets the color calibration of the display to |profile|.
+  void SetColorCalibrationProfile(int64 display_id,
+                                  ui::ColorCalibrationProfile profile);
+
   // Called when display configuration has changed. The new display
   // configurations is passed as a vector of Display object, which
   // contains each display's new infomration.
@@ -304,6 +309,9 @@
   // a display.
   void InsertAndUpdateDisplayInfo(const DisplayInfo& new_info);
 
+  // Called when the display info is updated through InsertAndUpdateDisplayInfo.
+  void OnDisplayInfoUpdated(const DisplayInfo& display_info);
+
   // Creates a display object from the DisplayInfo for |display_id|.
   gfx::Display CreateDisplayFromDisplayInfoById(int64 display_id);
 
diff --git a/ash/display/screen_position_controller.cc b/ash/display/screen_position_controller.cc
index c0079c8..6572ac1 100644
--- a/ash/display/screen_position_controller.cc
+++ b/ash/display/screen_position_controller.cc
@@ -12,7 +12,6 @@
 #include "ash/wm/system_modal_container_layout_manager.h"
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -21,6 +20,7 @@
 #include "ui/gfx/display.h"
 #include "ui/gfx/screen.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace {
diff --git a/ash/display/virtual_keyboard_window_controller.cc b/ash/display/virtual_keyboard_window_controller.cc
index bef3b45..531aa9b 100644
--- a/ash/display/virtual_keyboard_window_controller.cc
+++ b/ash/display/virtual_keyboard_window_controller.cc
@@ -19,14 +19,17 @@
 #include "ui/aura/root_window_transformer.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/keyboard/keyboard_controller.h"
+#include "ui/keyboard/keyboard_util.h"
 
 namespace ash {
 namespace internal {
 
 VirtualKeyboardWindowController::VirtualKeyboardWindowController() {
+  Shell::GetInstance()->AddShellObserver(this);
 }
 
 VirtualKeyboardWindowController::~VirtualKeyboardWindowController() {
+  Shell::GetInstance()->RemoveShellObserver(this);
   // Make sure the root window gets deleted before cursor_window_delegate.
   Close();
 }
@@ -92,5 +95,16 @@
   host->SetRootWindowTransformer(transformer.Pass());
 }
 
+void VirtualKeyboardWindowController::OnMaximizeModeStarted() {
+  keyboard::SetTouchKeyboardEnabled(true);
+  Shell::GetInstance()->CreateKeyboard();
+}
+
+void VirtualKeyboardWindowController::OnMaximizeModeEnded() {
+  keyboard::SetTouchKeyboardEnabled(false);
+  if (!keyboard::IsKeyboardEnabled())
+    Shell::GetInstance()->DeactivateKeyboard();
+}
+
 }  // namespace internal
 }  // namespace ash
diff --git a/ash/display/virtual_keyboard_window_controller.h b/ash/display/virtual_keyboard_window_controller.h
index 6a46659..1686539 100644
--- a/ash/display/virtual_keyboard_window_controller.h
+++ b/ash/display/virtual_keyboard_window_controller.h
@@ -6,6 +6,7 @@
 #define ASH_DISPLAY_VIRTUAL_KEYBOARD_WINDOW_CONTROLLER_H_
 
 #include "ash/ash_export.h"
+#include "ash/shell_observer.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "ui/gfx/display.h"
@@ -26,7 +27,7 @@
 
 // This class maintains the RootWindowController dedicated for
 // virtual keyboard.
-class ASH_EXPORT VirtualKeyboardWindowController {
+class ASH_EXPORT VirtualKeyboardWindowController : public ShellObserver {
  public:
   VirtualKeyboardWindowController();
   virtual ~VirtualKeyboardWindowController();
@@ -40,6 +41,10 @@
   // Close the mirror window.
   void Close();
 
+  // ShellObserver:
+  virtual void OnMaximizeModeStarted() OVERRIDE;
+  virtual void OnMaximizeModeEnded() OVERRIDE;
+
  private:
   friend class test::VirtualKeyboardWindowControllerTest;
 
diff --git a/ash/display/virtual_keyboard_window_controller_unittest.cc b/ash/display/virtual_keyboard_window_controller_unittest.cc
index 720690e..915be43 100644
--- a/ash/display/virtual_keyboard_window_controller_unittest.cc
+++ b/ash/display/virtual_keyboard_window_controller_unittest.cc
@@ -12,6 +12,7 @@
 #include "ash/test/ash_test_base.h"
 #include "base/command_line.h"
 #include "ui/keyboard/keyboard_switches.h"
+#include "ui/keyboard/keyboard_util.h"
 
 namespace ash {
 namespace test {
@@ -22,16 +23,6 @@
       : virtual_keyboard_window_controller_(NULL) {}
   virtual ~VirtualKeyboardWindowControllerTest() {}
 
-  virtual void SetUp() OVERRIDE {
-    if (SupportsMultipleDisplays()) {
-      CommandLine::ForCurrentProcess()->AppendSwitchASCII(
-          switches::kAshHostWindowBounds, "1+1-300x300,1+301-300x300");
-      CommandLine::ForCurrentProcess()->AppendSwitch(
-          keyboard::switches::kKeyboardUsabilityExperiment);
-    }
-    test::AshTestBase::SetUp();
-  }
-
   void set_virtual_keyboard_window_controller(
       internal::VirtualKeyboardWindowController* controller) {
     virtual_keyboard_window_controller_ = controller;
@@ -48,8 +39,28 @@
   DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardWindowControllerTest);
 };
 
+class VirtualKeyboardUsabilityExperimentTest
+    : public VirtualKeyboardWindowControllerTest {
+ public:
+  VirtualKeyboardUsabilityExperimentTest()
+    : VirtualKeyboardWindowControllerTest() {}
+  virtual ~VirtualKeyboardUsabilityExperimentTest() {}
 
-TEST_F(VirtualKeyboardWindowControllerTest, VirtualKeyboardWindowTest) {
+  virtual void SetUp() OVERRIDE {
+    if (SupportsMultipleDisplays()) {
+      CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+          switches::kAshHostWindowBounds, "1+1-300x300,1+301-300x300");
+      CommandLine::ForCurrentProcess()->AppendSwitch(
+          keyboard::switches::kKeyboardUsabilityExperiment);
+    }
+    test::AshTestBase::SetUp();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(VirtualKeyboardUsabilityExperimentTest);
+};
+
+TEST_F(VirtualKeyboardUsabilityExperimentTest, VirtualKeyboardWindowTest) {
   if (!SupportsMultipleDisplays())
     return;
   RunAllPendingInMessageLoop();
@@ -62,5 +73,19 @@
       internal::kShellWindowId_VirtualKeyboardContainer));
 }
 
+// Tests that the onscreen keyboard becomes enabled when maximize mode is
+// enabled.
+TEST_F(VirtualKeyboardWindowControllerTest, EnabledDuringMaximizeMode) {
+  set_virtual_keyboard_window_controller(
+      Shell::GetInstance()->display_controller()->
+          virtual_keyboard_window_controller());
+
+  ASSERT_FALSE(keyboard::IsKeyboardEnabled());
+  Shell::GetInstance()->EnableMaximizeModeWindowManager(true);
+  EXPECT_TRUE(keyboard::IsKeyboardEnabled());
+  Shell::GetInstance()->EnableMaximizeModeWindowManager(false);
+  EXPECT_FALSE(keyboard::IsKeyboardEnabled());
+}
+
 }  // namespace test
 }  // namespace ash
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc
index 472172b..cc8d96b 100644
--- a/ash/drag_drop/drag_drop_controller.cc
+++ b/ash/drag_drop/drag_drop_controller.cc
@@ -12,7 +12,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "ui/aura/client/capture_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -29,6 +28,7 @@
 #include "ui/gfx/rect_conversions.h"
 #include "ui/views/views_delegate.h"
 #include "ui/views/widget/native_widget_aura.h"
+#include "ui/wm/public/drag_drop_delegate.h"
 
 namespace ash {
 namespace internal {
@@ -123,8 +123,6 @@
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {
     DCHECK(mask->isEmpty());
   }
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE {}
 
  private:
   DragDropController* drag_drop_controller_;
diff --git a/ash/drag_drop/drag_drop_controller.h b/ash/drag_drop/drag_drop_controller.h
index a9220db..5d05ec9 100644
--- a/ash/drag_drop/drag_drop_controller.h
+++ b/ash/drag_drop/drag_drop_controller.h
@@ -8,13 +8,13 @@
 #include "ash/ash_export.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/event_handler.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/rect.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 namespace gfx {
 class LinearAnimation;
diff --git a/ash/drag_drop/drag_drop_tracker.cc b/ash/drag_drop/drag_drop_tracker.cc
index 48badf3..55cb7b9 100644
--- a/ash/drag_drop/drag_drop_tracker.cc
+++ b/ash/drag_drop/drag_drop_tracker.cc
@@ -7,12 +7,12 @@
 #include "ash/shell.h"
 #include "ash/shell_window_ids.h"
 #include "ash/wm/coordinate_conversion.h"
-#include "ui/aura/client/activation_delegate.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/events/event.h"
 #include "ui/gfx/screen.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace ash {
 namespace internal {
diff --git a/ash/extended_desktop_unittest.cc b/ash/extended_desktop_unittest.cc
index 0554398..0bc1ed4 100644
--- a/ash/extended_desktop_unittest.cc
+++ b/ash/extended_desktop_unittest.cc
@@ -15,7 +15,6 @@
 #include "ash/wm/window_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/test/event_generator.h"
@@ -30,6 +29,7 @@
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace {
diff --git a/ash/focus_cycler.cc b/ash/focus_cycler.cc
index efd958c..0fa83aa 100644
--- a/ash/focus_cycler.cc
+++ b/ash/focus_cycler.cc
@@ -8,11 +8,11 @@
 #include "ash/wm/mru_window_tracker.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/focus/focus_search.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 
diff --git a/ash/frame/custom_frame_view_ash.cc b/ash/frame/custom_frame_view_ash.cc
index 96bcafb..196f901 100644
--- a/ash/frame/custom_frame_view_ash.cc
+++ b/ash/frame/custom_frame_view_ash.cc
@@ -10,7 +10,10 @@
 #include "ash/frame/caption_buttons/frame_maximize_button_observer.h"
 #include "ash/frame/default_header_painter.h"
 #include "ash/frame/frame_border_hit_test_controller.h"
+#include "ash/frame/frame_util.h"
 #include "ash/frame/header_painter.h"
+#include "ash/session_state_delegate.h"
+#include "ash/shell.h"
 #include "ash/wm/immersive_fullscreen_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_state_delegate.h"
@@ -20,9 +23,11 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/image/image.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/size.h"
+#include "ui/views/controls/image_view.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
@@ -45,6 +50,9 @@
       ash::wm::WindowState* window_state,
       ash::CustomFrameViewAsh* custom_frame_view)
       : window_state_(NULL) {
+#if defined(OS_CHROMEOS)
+    // TODO(pkotwicz): Investigate if immersive fullscreen can be enabled for
+    // Windows Ash.
     immersive_fullscreen_controller_.reset(
         new ash::ImmersiveFullscreenController);
     custom_frame_view->InitImmersiveFullscreenControllerForView(
@@ -58,6 +66,7 @@
     window_state_ = window_state;
     window_state_->AddObserver(this);
     window_state_->window()->AddObserver(this);
+#endif
   }
   virtual ~CustomFrameViewAshWindowStateDelegate() {
     if (window_state_) {
@@ -142,6 +151,8 @@
   // Returns the view's minimum width.
   int GetMinimumWidth() const;
 
+  void UpdateAvatarIcon();
+
   // views::View overrides:
   virtual void Layout() OVERRIDE;
   virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
@@ -150,6 +161,10 @@
     return caption_button_container_;
   }
 
+  views::View* avatar_icon() const {
+    return avatar_icon_;
+  }
+
  private:
   // ImmersiveFullscreenController::Delegate overrides:
   virtual void OnImmersiveRevealStarted() OVERRIDE;
@@ -167,6 +182,8 @@
   // Helper for painting the header.
   scoped_ptr<DefaultHeaderPainter> header_painter_;
 
+  views::ImageView* avatar_icon_;
+
   // View which contains the window caption buttons.
   FrameCaptionButtonContainerView* caption_button_container_;
 
@@ -187,6 +204,7 @@
 CustomFrameViewAsh::HeaderView::HeaderView(views::Widget* frame)
     : frame_(frame),
       header_painter_(new ash::DefaultHeaderPainter),
+      avatar_icon_(NULL),
       caption_button_container_(NULL),
       maximize_bubble_(NULL),
       fullscreen_visible_fraction_(0) {
@@ -205,6 +223,7 @@
     frame_maximize_button->AddObserver(this);
 
   header_painter_->Init(frame_, this, NULL, caption_button_container_);
+  UpdateAvatarIcon();
 }
 
 CustomFrameViewAsh::HeaderView::~HeaderView() {
@@ -238,6 +257,33 @@
   return header_painter_->GetMinimumHeaderWidth();
 }
 
+void CustomFrameViewAsh::HeaderView::UpdateAvatarIcon() {
+  SessionStateDelegate* delegate =
+      Shell::GetInstance()->session_state_delegate();
+  aura::Window* window = frame_->GetNativeView();
+  bool show = delegate->ShouldShowAvatar(window);
+  int icon_size = 0;
+  if (!show) {
+    if (!avatar_icon_)
+      return;
+    delete avatar_icon_;
+    avatar_icon_ = NULL;
+  } else {
+    gfx::ImageSkia image = GetAvatarImageForContext(
+        delegate->GetBrowserContextForWindow(window)).AsImageSkia();
+    DCHECK(!image.isNull());
+    DCHECK_EQ(image.width(), image.height());
+    if (!avatar_icon_) {
+      avatar_icon_ = new views::ImageView();
+      AddChildView(avatar_icon_);
+    }
+    avatar_icon_->SetImage(image);
+    icon_size = image.width();
+  }
+  header_painter_->UpdateWindowIcon(avatar_icon_, icon_size);
+  Layout();
+}
+
 void CustomFrameViewAsh::HeaderView::Layout() {
   header_painter_->LayoutHeader();
 }
@@ -475,10 +521,20 @@
   return false;
 }
 
+void CustomFrameViewAsh::VisibilityChanged(views::View* starting_from,
+                                           bool is_visible) {
+  if (is_visible)
+    header_view_->UpdateAvatarIcon();
+}
+
 views::View* CustomFrameViewAsh::GetHeaderView() {
   return header_view_;
 }
 
+const views::View* CustomFrameViewAsh::GetAvatarIconViewForTest() const {
+  return header_view_->avatar_icon();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // CustomFrameViewAsh, private:
 
diff --git a/ash/frame/custom_frame_view_ash.h b/ash/frame/custom_frame_view_ash.h
index 6fd9bdf..bfa6729 100644
--- a/ash/frame/custom_frame_view_ash.h
+++ b/ash/frame/custom_frame_view_ash.h
@@ -58,10 +58,14 @@
   virtual gfx::Size GetMaximumSize() OVERRIDE;
   virtual void SchedulePaintInRect(const gfx::Rect& r) OVERRIDE;
   virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE;
+  virtual void VisibilityChanged(views::View* starting_from,
+                                 bool is_visible) OVERRIDE;
 
   // Get the view of the header.
   views::View* GetHeaderView();
 
+  const views::View* GetAvatarIconViewForTest() const;
+
  private:
   class OverlayView;
   friend class TestWidgetConstraintsDelegate;
diff --git a/ash/frame/custom_frame_view_ash_unittest.cc b/ash/frame/custom_frame_view_ash_unittest.cc
index eb0a543..68a85a8 100644
--- a/ash/frame/custom_frame_view_ash_unittest.cc
+++ b/ash/frame/custom_frame_view_ash_unittest.cc
@@ -4,7 +4,9 @@
 
 #include "ash/frame/custom_frame_view_ash.h"
 
+#include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/test/test_session_state_delegate.h"
 #include "base/memory/scoped_ptr.h"
 #include "grit/ash_resources.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -97,6 +99,11 @@
     return widget.Pass();
   }
 
+  test::TestSessionStateDelegate* GetTestSessionStateDelegate() {
+    return static_cast<ash::test::TestSessionStateDelegate*>(
+        Shell::GetInstance()->session_state_delegate());
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(CustomFrameViewAshTest);
 };
@@ -158,4 +165,30 @@
             max_frame_size.height());
 }
 
+// Verify that CustomFrameViewAsh updates the avatar icon based on the
+// state of the SessionStateDelegate after visibility change.
+TEST_F(CustomFrameViewAshTest, AvatarIcon) {
+  TestWidgetConstraintsDelegate* delegate = new TestWidgetConstraintsDelegate;
+  scoped_ptr<views::Widget> widget(CreateWidget(delegate));
+
+  CustomFrameViewAsh* custom_frame_view = delegate->custom_frame_view();
+  EXPECT_FALSE(custom_frame_view->GetAvatarIconViewForTest());
+
+  // Avatar image becomes available.
+  const gfx::ImageSkia user_image =
+      *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+          IDR_AURA_UBER_TRAY_GUEST_ICON);
+  GetTestSessionStateDelegate()->SetUserImage(user_image);
+  widget->Hide();
+  widget->Show();
+  EXPECT_TRUE(custom_frame_view->GetAvatarIconViewForTest());
+
+  // Avatar image is gone; the ImageView for the avatar icon should be
+  // removed.
+  GetTestSessionStateDelegate()->SetUserImage(gfx::ImageSkia());
+  widget->Hide();
+  widget->Show();
+  EXPECT_FALSE(custom_frame_view->GetAvatarIconViewForTest());
+}
+
 }  // namespace ash
diff --git a/ash/frame/default_header_painter.cc b/ash/frame/default_header_painter.cc
index 80e2f53..fd31d77 100644
--- a/ash/frame/default_header_painter.cc
+++ b/ash/frame/default_header_painter.cc
@@ -31,10 +31,10 @@
 // Color for the window title text.
 const SkColor kTitleTextColor = SkColorSetRGB(40, 40, 40);
 // Color of the active window header/content separator line.
-const SkColor kHeaderContentSeparatorColor = SkColorSetRGB(180, 180, 182);
+const SkColor kHeaderContentSeparatorColor = SkColorSetRGB(150, 150, 152);
 // Color of the inactive window header/content separator line.
 const SkColor kHeaderContentSeparatorInactiveColor =
-    SkColorSetRGB(150, 150, 152);
+    SkColorSetRGB(180, 180, 182);
 // Duration of crossfade animation for activating and deactivating frame.
 const int kActivationCrossfadeDurationMs = 200;
 
@@ -75,6 +75,7 @@
     : frame_(NULL),
       view_(NULL),
       window_icon_(NULL),
+      window_icon_size_(HeaderPainterUtil::GetDefaultIconSize()),
       caption_button_container_(NULL),
       height_(0),
       mode_(MODE_INACTIVE),
@@ -168,23 +169,20 @@
   int active_alpha = activation_animation_->CurrentValueBetween(0, 255);
   int inactive_alpha = 255 - active_alpha;
 
-  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   SkPaint paint;
   if (inactive_alpha > 0) {
     if (active_alpha > 0)
       paint.setXfermodeMode(SkXfermode::kPlus_Mode);
 
     paint.setAlpha(inactive_alpha);
-    gfx::ImageSkia inactive_frame =
-        *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_BASE_INACTIVE);
+    gfx::ImageSkia inactive_frame = *GetInactiveFrameImage();
     TileRoundRect(canvas, inactive_frame, paint, GetLocalBounds(),
         corner_radius);
   }
 
   if (active_alpha > 0) {
     paint.setAlpha(active_alpha);
-    gfx::ImageSkia active_frame =
-        *rb.GetImageSkiaNamed(IDR_AURA_WINDOW_HEADER_BASE_ACTIVE);
+    gfx::ImageSkia active_frame = *GetActiveFrameImage();
     TileRoundRect(canvas, active_frame, paint, GetLocalBounds(),
         corner_radius);
   }
@@ -215,11 +213,11 @@
   if (window_icon_) {
     // Vertically center the window icon with respect to the caption button
     // container.
-    int icon_size = HeaderPainterUtil::GetIconSize();
     // Floor when computing the center of |caption_button_container_|.
-    int icon_offset_y = caption_button_container_->height() / 2 - icon_size / 2;
+    int icon_offset_y =
+        caption_button_container_->height() / 2 - window_icon_size_ / 2;
     window_icon_->SetBounds(HeaderPainterUtil::GetIconXOffset(), icon_offset_y,
-        icon_size, icon_size);
+                            window_icon_size_, window_icon_size_);
   }
 
   // The header/content separator line overlays the caption buttons.
@@ -238,6 +236,12 @@
   view_->SchedulePaintInRect(GetTitleBounds());
 }
 
+void DefaultHeaderPainter::UpdateWindowIcon(views::View* window_icon,
+                                            int window_icon_size) {
+  window_icon_ = window_icon;
+  window_icon_size_ = window_icon_size;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // gfx::AnimationDelegate overrides:
 
@@ -318,4 +322,17 @@
       window_icon_, caption_button_container_, GetTitleFontList());
 }
 
+gfx::ImageSkia* DefaultHeaderPainter::GetActiveFrameImage() const {
+  return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+      IDR_AURA_WINDOW_HEADER_BASE);
+}
+
+gfx::ImageSkia* DefaultHeaderPainter::GetInactiveFrameImage() const {
+  int frame_image_id = (frame_->IsMaximized() || frame_->IsFullscreen()) ?
+      IDR_AURA_WINDOW_HEADER_BASE :
+      IDR_AURA_WINDOW_HEADER_BASE_RESTORED_INACTIVE;
+  return ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+      frame_image_id);
+}
+
 }  // namespace ash
diff --git a/ash/frame/default_header_painter.h b/ash/frame/default_header_painter.h
index 80990c1..e06c312 100644
--- a/ash/frame/default_header_painter.h
+++ b/ash/frame/default_header_painter.h
@@ -14,6 +14,7 @@
 #include "ui/gfx/animation/animation_delegate.h"
 
 namespace gfx {
+class ImageSkia;
 class Rect;
 class SlideAnimation;
 }
@@ -46,6 +47,9 @@
   virtual void SetHeaderHeightForPainting(int height) OVERRIDE;
   virtual void SchedulePaintForTitle() OVERRIDE;
 
+  // Sets the window icon for the header. Passing NULL removes the window icon.
+  void UpdateWindowIcon(views::View* window_icon, int icon_size);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(DefaultHeaderPainterTest, TitleIconAlignment);
 
@@ -70,9 +74,16 @@
   // Returns the bounds for the title.
   gfx::Rect GetTitleBounds() const;
 
+  // Returns the frame image to use when |frame_| is active.
+  gfx::ImageSkia* GetActiveFrameImage() const;
+
+  // Returns the frame image to use when |frame_| is inactive.
+  gfx::ImageSkia* GetInactiveFrameImage() const;
+
   views::Widget* frame_;
   views::View* view_;
   views::View* window_icon_;  // May be NULL.
+  int window_icon_size_;
   FrameCaptionButtonContainerView* caption_button_container_;
 
   // The height of the header including the header/content separator.
diff --git a/ash/frame/header_painter_util.cc b/ash/frame/header_painter_util.cc
index ca83824..1054291 100644
--- a/ash/frame/header_painter_util.cc
+++ b/ash/frame/header_painter_util.cc
@@ -22,8 +22,8 @@
 // Distance between left edge of the window and the header icon.
 const int kIconXOffset = 9;
 
-// Height and width of header icon.
-const int kIconSize = 16;
+// Default height and width of header icon.
+const int kDefaultIconSize = 16;
 
 // Space between the title text and the caption buttons.
 const int kTitleCaptionButtonSpacing = 5;
@@ -57,8 +57,8 @@
 }
 
 // static
-int HeaderPainterUtil::GetIconSize() {
-  return kIconSize;
+int HeaderPainterUtil::GetDefaultIconSize() {
+  return kDefaultIconSize;
 }
 
 // static
diff --git a/ash/frame/header_painter_util.h b/ash/frame/header_painter_util.h
index 468184a..5e4bde4 100644
--- a/ash/frame/header_painter_util.h
+++ b/ash/frame/header_painter_util.h
@@ -31,7 +31,7 @@
   static int GetIconXOffset();
 
   // Returns the size of the header icon.
-  static int GetIconSize();
+  static int GetDefaultIconSize();
 
   // Returns the amount that the frame background is inset from the left edge of
   // the window.
diff --git a/ash/ime/OWNERS b/ash/ime/OWNERS
index 7224e3b..cb42d0b 100644
--- a/ash/ime/OWNERS
+++ b/ash/ime/OWNERS
@@ -1,3 +1,7 @@
-komatsu@chromium.org
+# primary reviewer
 mukai@chromium.org
+
+# backup reviewers
+komatsu@chromium.org
 nona@chromium.org
+yukishiino@chromium.org
diff --git a/ash/resources/ash_resources.grd b/ash/resources/ash_resources.grd
index 1a051da..75c3a69 100644
--- a/ash/resources/ash_resources.grd
+++ b/ash/resources/ash_resources.grd
@@ -253,8 +253,8 @@
       <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_CONTROL_ICON_SIZE" file="common/window_control_icon_size.png" />
       <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_CONTROL_ICON_SIZE_I" file="common/window_control_icon_size_inactive.png" />
 
-      <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_BASE_ACTIVE" file="common/window_header_base_active.png" />
-      <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_BASE_INACTIVE" file="common/window_header_base_inactive.png" />
+      <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_BASE" file="common/window_header_base_active.png" />
+      <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_BASE_RESTORED_INACTIVE" file="common/window_header_base_inactive.png" />
       <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_BOTTOM" file="common/window_header_shade_bottom_inactive.png" />
       <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_LEFT" file="common/window_header_shade_left_inactive.png" />
       <structure type="chrome_scaled_image" name="IDR_AURA_WINDOW_HEADER_SHADE_INACTIVE_RIGHT" file="common/window_header_shade_right_inactive.png" />
diff --git a/ash/resources/default_100_percent/common/browser_window_control_icon_restored_close.png b/ash/resources/default_100_percent/common/browser_window_control_icon_restored_close.png
index 506c3fe..edd1e96 100644
--- a/ash/resources/default_100_percent/common/browser_window_control_icon_restored_close.png
+++ b/ash/resources/default_100_percent/common/browser_window_control_icon_restored_close.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/browser_window_control_icon_restored_size.png b/ash/resources/default_100_percent/common/browser_window_control_icon_restored_size.png
index 619995f..e63715e 100644
--- a/ash/resources/default_100_percent/common/browser_window_control_icon_restored_size.png
+++ b/ash/resources/default_100_percent/common/browser_window_control_icon_restored_size.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_bottom.png b/ash/resources/default_100_percent/common/phantom_window_bottom.png
index d6e9295..6873a1e 100644
--- a/ash/resources/default_100_percent/common/phantom_window_bottom.png
+++ b/ash/resources/default_100_percent/common/phantom_window_bottom.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_bottom_left.png b/ash/resources/default_100_percent/common/phantom_window_bottom_left.png
index d74a7ef..0158807 100644
--- a/ash/resources/default_100_percent/common/phantom_window_bottom_left.png
+++ b/ash/resources/default_100_percent/common/phantom_window_bottom_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_bottom_right.png b/ash/resources/default_100_percent/common/phantom_window_bottom_right.png
index 52623b5..a423777 100644
--- a/ash/resources/default_100_percent/common/phantom_window_bottom_right.png
+++ b/ash/resources/default_100_percent/common/phantom_window_bottom_right.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_left.png b/ash/resources/default_100_percent/common/phantom_window_left.png
index f49c69f..17efe04 100644
--- a/ash/resources/default_100_percent/common/phantom_window_left.png
+++ b/ash/resources/default_100_percent/common/phantom_window_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_right.png b/ash/resources/default_100_percent/common/phantom_window_right.png
index 35c83a2..b4f1d9c 100644
--- a/ash/resources/default_100_percent/common/phantom_window_right.png
+++ b/ash/resources/default_100_percent/common/phantom_window_right.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_top.png b/ash/resources/default_100_percent/common/phantom_window_top.png
index c13c63f..0189e53 100644
--- a/ash/resources/default_100_percent/common/phantom_window_top.png
+++ b/ash/resources/default_100_percent/common/phantom_window_top.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_top_left.png b/ash/resources/default_100_percent/common/phantom_window_top_left.png
index 608bc0d..fdd2740 100644
--- a/ash/resources/default_100_percent/common/phantom_window_top_left.png
+++ b/ash/resources/default_100_percent/common/phantom_window_top_left.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/phantom_window_top_right.png b/ash/resources/default_100_percent/common/phantom_window_top_right.png
index 8550c44..d49a6aa 100644
--- a/ash/resources/default_100_percent/common/phantom_window_top_right.png
+++ b/ash/resources/default_100_percent/common/phantom_window_top_right.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_overview_close_hover.png b/ash/resources/default_100_percent/common/window_overview_close_hover.png
index 243cf1b..2a57bf0 100644
--- a/ash/resources/default_100_percent/common/window_overview_close_hover.png
+++ b/ash/resources/default_100_percent/common/window_overview_close_hover.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_overview_close_normal.png b/ash/resources/default_100_percent/common/window_overview_close_normal.png
index 954ceb3..2a80812 100644
--- a/ash/resources/default_100_percent/common/window_overview_close_normal.png
+++ b/ash/resources/default_100_percent/common/window_overview_close_normal.png
Binary files differ
diff --git a/ash/resources/default_100_percent/common/window_overview_close_pressed.png b/ash/resources/default_100_percent/common/window_overview_close_pressed.png
index 6fb5bdf..80fdce7 100644
--- a/ash/resources/default_100_percent/common/window_overview_close_pressed.png
+++ b/ash/resources/default_100_percent/common/window_overview_close_pressed.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/avatar_holder.png b/ash/resources/default_100_percent/cros/avatar_holder.png
index fe79fd7..276d3c2 100644
--- a/ash/resources/default_100_percent/cros/avatar_holder.png
+++ b/ash/resources/default_100_percent/cros/avatar_holder.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/avatar_holder_mask.png b/ash/resources/default_100_percent/cros/avatar_holder_mask.png
index 387ffaf..e66457b 100644
--- a/ash/resources/default_100_percent/cros/avatar_holder_mask.png
+++ b/ash/resources/default_100_percent/cros/avatar_holder_mask.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_dark.png b/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_dark.png
index bcd8193..b201c39 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_dark.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_light.png b/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_light.png
index 24d0b07..0079811 100644
--- a/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_light.png
+++ b/ash/resources/default_100_percent/cros/network/statusbar_network_active_portal_light.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/notification/display_notification_icon.png b/ash/resources/default_100_percent/cros/notification/display_notification_icon.png
index 7ded7aa..e49d82a 100644
--- a/ash/resources/default_100_percent/cros/notification/display_notification_icon.png
+++ b/ash/resources/default_100_percent/cros/notification/display_notification_icon.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_auto_rotate.png b/ash/resources/default_100_percent/cros/status/status_auto_rotate.png
new file mode 100644
index 0000000..646efca
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/status/status_auto_rotate.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_auto_rotate_dark.png b/ash/resources/default_100_percent/cros/status/status_auto_rotate_dark.png
new file mode 100644
index 0000000..4e9569c
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/status/status_auto_rotate_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_auto_rotate_locked.png b/ash/resources/default_100_percent/cros/status/status_auto_rotate_locked.png
new file mode 100644
index 0000000..640c3f3
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/status/status_auto_rotate_locked.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_auto_rotate_locked_dark.png b/ash/resources/default_100_percent/cros/status/status_auto_rotate_locked_dark.png
new file mode 100644
index 0000000..7a4a150
--- /dev/null
+++ b/ash/resources/default_100_percent/cros/status/status_auto_rotate_locked_dark.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_overview_mode.png b/ash/resources/default_100_percent/cros/status/status_overview_mode.png
index 67a8aef..d145a94 100644
--- a/ash/resources/default_100_percent/cros/status/status_overview_mode.png
+++ b/ash/resources/default_100_percent/cros/status/status_overview_mode.png
Binary files differ
diff --git a/ash/resources/default_100_percent/cros/status/status_virtual_keyboard.png b/ash/resources/default_100_percent/cros/status/status_virtual_keyboard.png
index c36c944..52813bf 100644
--- a/ash/resources/default_100_percent/cros/status/status_virtual_keyboard.png
+++ b/ash/resources/default_100_percent/cros/status/status_virtual_keyboard.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_bottom.png b/ash/resources/default_200_percent/common/phantom_window_bottom.png
index cc4e32e..ecc8ac3 100644
--- a/ash/resources/default_200_percent/common/phantom_window_bottom.png
+++ b/ash/resources/default_200_percent/common/phantom_window_bottom.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_bottom_left.png b/ash/resources/default_200_percent/common/phantom_window_bottom_left.png
index 7999cc5..15d21ea 100644
--- a/ash/resources/default_200_percent/common/phantom_window_bottom_left.png
+++ b/ash/resources/default_200_percent/common/phantom_window_bottom_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_bottom_right.png b/ash/resources/default_200_percent/common/phantom_window_bottom_right.png
index 0b6bf34..7e1e9b6 100644
--- a/ash/resources/default_200_percent/common/phantom_window_bottom_right.png
+++ b/ash/resources/default_200_percent/common/phantom_window_bottom_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_center.png b/ash/resources/default_200_percent/common/phantom_window_center.png
index 7619d39..05b4d6e 100644
--- a/ash/resources/default_200_percent/common/phantom_window_center.png
+++ b/ash/resources/default_200_percent/common/phantom_window_center.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_left.png b/ash/resources/default_200_percent/common/phantom_window_left.png
index dd0e81a..a9709f8 100644
--- a/ash/resources/default_200_percent/common/phantom_window_left.png
+++ b/ash/resources/default_200_percent/common/phantom_window_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_right.png b/ash/resources/default_200_percent/common/phantom_window_right.png
index 0c27eed..468f108 100644
--- a/ash/resources/default_200_percent/common/phantom_window_right.png
+++ b/ash/resources/default_200_percent/common/phantom_window_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_top.png b/ash/resources/default_200_percent/common/phantom_window_top.png
index 5ca087b..930a8d6 100644
--- a/ash/resources/default_200_percent/common/phantom_window_top.png
+++ b/ash/resources/default_200_percent/common/phantom_window_top.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_top_left.png b/ash/resources/default_200_percent/common/phantom_window_top_left.png
index 699e049..8ec1e8a 100644
--- a/ash/resources/default_200_percent/common/phantom_window_top_left.png
+++ b/ash/resources/default_200_percent/common/phantom_window_top_left.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/phantom_window_top_right.png b/ash/resources/default_200_percent/common/phantom_window_top_right.png
index 1f14869..f11c024 100644
--- a/ash/resources/default_200_percent/common/phantom_window_top_right.png
+++ b/ash/resources/default_200_percent/common/phantom_window_top_right.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_overview_close_hover.png b/ash/resources/default_200_percent/common/window_overview_close_hover.png
index e135dc1..7835d49 100644
--- a/ash/resources/default_200_percent/common/window_overview_close_hover.png
+++ b/ash/resources/default_200_percent/common/window_overview_close_hover.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_overview_close_normal.png b/ash/resources/default_200_percent/common/window_overview_close_normal.png
index 3b3ed84..54c9910 100644
--- a/ash/resources/default_200_percent/common/window_overview_close_normal.png
+++ b/ash/resources/default_200_percent/common/window_overview_close_normal.png
Binary files differ
diff --git a/ash/resources/default_200_percent/common/window_overview_close_pressed.png b/ash/resources/default_200_percent/common/window_overview_close_pressed.png
index fb77bfa..ea10e07 100644
--- a/ash/resources/default_200_percent/common/window_overview_close_pressed.png
+++ b/ash/resources/default_200_percent/common/window_overview_close_pressed.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/avatar_holder.png b/ash/resources/default_200_percent/cros/avatar_holder.png
index ce1aeb8..fefe883 100644
--- a/ash/resources/default_200_percent/cros/avatar_holder.png
+++ b/ash/resources/default_200_percent/cros/avatar_holder.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/avatar_holder_mask.png b/ash/resources/default_200_percent/cros/avatar_holder_mask.png
index 267b336..3b8c042 100644
--- a/ash/resources/default_200_percent/cros/avatar_holder_mask.png
+++ b/ash/resources/default_200_percent/cros/avatar_holder_mask.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_dark.png b/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_dark.png
index c43eb29..b10d869 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_dark.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_light.png b/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_light.png
index e531c2f..49930ee 100644
--- a/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_light.png
+++ b/ash/resources/default_200_percent/cros/network/statusbar_network_active_portal_light.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/notification/display_notification_icon.png b/ash/resources/default_200_percent/cros/notification/display_notification_icon.png
index ca326e2..832e974 100644
--- a/ash/resources/default_200_percent/cros/notification/display_notification_icon.png
+++ b/ash/resources/default_200_percent/cros/notification/display_notification_icon.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_accessibility_mode.png b/ash/resources/default_200_percent/cros/status/status_accessibility_mode.png
index cf900eb..3ea908b 100644
--- a/ash/resources/default_200_percent/cros/status/status_accessibility_mode.png
+++ b/ash/resources/default_200_percent/cros/status/status_accessibility_mode.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_auto_rotate.png b/ash/resources/default_200_percent/cros/status/status_auto_rotate.png
new file mode 100644
index 0000000..9bc087f
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/status/status_auto_rotate.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_auto_rotate_dark.png b/ash/resources/default_200_percent/cros/status/status_auto_rotate_dark.png
new file mode 100644
index 0000000..1f9b5ce
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/status/status_auto_rotate_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_auto_rotate_locked.png b/ash/resources/default_200_percent/cros/status/status_auto_rotate_locked.png
new file mode 100644
index 0000000..c0f228b
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/status/status_auto_rotate_locked.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_auto_rotate_locked_dark.png b/ash/resources/default_200_percent/cros/status/status_auto_rotate_locked_dark.png
new file mode 100644
index 0000000..68477fc
--- /dev/null
+++ b/ash/resources/default_200_percent/cros/status/status_auto_rotate_locked_dark.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_overview_mode.png b/ash/resources/default_200_percent/cros/status/status_overview_mode.png
index 1986cd9..f684c7e 100644
--- a/ash/resources/default_200_percent/cros/status/status_overview_mode.png
+++ b/ash/resources/default_200_percent/cros/status/status_overview_mode.png
Binary files differ
diff --git a/ash/resources/default_200_percent/cros/status/status_virtual_keyboard.png b/ash/resources/default_200_percent/cros/status/status_virtual_keyboard.png
index f9decd0..a882f85 100644
--- a/ash/resources/default_200_percent/cros/status/status_virtual_keyboard.png
+++ b/ash/resources/default_200_percent/cros/status/status_virtual_keyboard.png
Binary files differ
diff --git a/ash/root_window_controller.cc b/ash/root_window_controller.cc
index ba8eb3f..429c9c5 100644
--- a/ash/root_window_controller.cc
+++ b/ash/root_window_controller.cc
@@ -48,9 +48,7 @@
 #include "base/command_line.h"
 #include "base/time/time.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/tooltip_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -69,6 +67,8 @@
 #include "ui/wm/core/easy_resize_window_targeter.h"
 #include "ui/wm/core/visibility_controller.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/tooltip_client.h"
 #include "ui/wm/public/window_types.h"
 
 #if defined(OS_CHROMEOS)
@@ -253,8 +253,6 @@
     return false;
   }
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(EmptyWindowDelegate);
diff --git a/ash/session_state_delegate.h b/ash/session_state_delegate.h
index 4df1617..f0e7f22 100644
--- a/ash/session_state_delegate.h
+++ b/ash/session_state_delegate.h
@@ -51,6 +51,10 @@
   virtual content::BrowserContext* GetBrowserContextByIndex(
       MultiProfileIndex index) = 0;
 
+  // Returns the browser context associated with the window.
+  virtual content::BrowserContext* GetBrowserContextForWindow(
+      aura::Window* window) = 0;
+
   // Returns the maximum possible number of logged in users.
   virtual int GetMaximumNumberOfLoggedInUsers() const = 0;
 
diff --git a/ash/session_state_delegate_stub.cc b/ash/session_state_delegate_stub.cc
index 7fc01da..dcbd346 100644
--- a/ash/session_state_delegate_stub.cc
+++ b/ash/session_state_delegate_stub.cc
@@ -6,6 +6,7 @@
 
 #include "ash/shell.h"
 #include "ash/shell/example_factory.h"
+#include "ash/shell_delegate.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 
@@ -20,7 +21,13 @@
 content::BrowserContext*
 SessionStateDelegateStub::GetBrowserContextByIndex(
     MultiProfileIndex index) {
-  return NULL;
+  return Shell::GetInstance()->delegate()->GetActiveBrowserContext();
+}
+
+content::BrowserContext*
+SessionStateDelegateStub::GetBrowserContextForWindow(
+    aura::Window* window) {
+  return Shell::GetInstance()->delegate()->GetActiveBrowserContext();
 }
 
 int SessionStateDelegateStub::GetMaximumNumberOfLoggedInUsers() const {
@@ -79,11 +86,11 @@
 
 const gfx::ImageSkia& SessionStateDelegateStub::GetUserImage(
     content::BrowserContext* context) const {
-  return null_image_;
+  return user_image_;
 }
 
 bool SessionStateDelegateStub::ShouldShowAvatar(aura::Window* window) {
-  return false;
+  return !user_image_.isNull();
 }
 
 void SessionStateDelegateStub::SwitchActiveUser(const std::string& user_id) {
diff --git a/ash/session_state_delegate_stub.h b/ash/session_state_delegate_stub.h
index 8c27e9a..5693fa7 100644
--- a/ash/session_state_delegate_stub.h
+++ b/ash/session_state_delegate_stub.h
@@ -21,6 +21,8 @@
   // SessionStateDelegate:
   virtual content::BrowserContext* GetBrowserContextByIndex(
       MultiProfileIndex index) OVERRIDE;
+  virtual content::BrowserContext* GetBrowserContextForWindow(
+      aura::Window* window) OVERRIDE;
   virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE;
   virtual int NumberOfLoggedInUsers() const OVERRIDE;
   virtual bool IsActiveUserSessionStarted() const OVERRIDE;
@@ -50,7 +52,7 @@
   bool screen_locked_;
 
   // A pseudo user image.
-  gfx::ImageSkia null_image_;
+  gfx::ImageSkia user_image_;
 
   DISALLOW_COPY_AND_ASSIGN(SessionStateDelegateStub);
 };
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc
index 4f433ce..c973157 100644
--- a/ash/shelf/shelf.cc
+++ b/ash/shelf/shelf.cc
@@ -24,7 +24,6 @@
 #include "ash/shell_window_ids.h"
 #include "ash/wm/window_properties.h"
 #include "grit/ash_resources.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_observer.h"
@@ -37,6 +36,7 @@
 #include "ui/views/accessible_pane_view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index 9cc67d6..8db87f4 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -36,7 +36,6 @@
 #include "base/i18n/rtl.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/ui_base_switches.h"
@@ -48,6 +47,7 @@
 #include "ui/events/event_handler.h"
 #include "ui/gfx/screen.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace internal {
@@ -198,6 +198,8 @@
 ShelfLayoutManager::ShelfLayoutManager(ShelfWidget* shelf)
     : root_window_(shelf->GetNativeView()->GetRootWindow()),
       updating_bounds_(false),
+      force_shelf_always_visibile_(
+          Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled()),
       auto_hide_behavior_(SHELF_AUTO_HIDE_BEHAVIOR_NEVER),
       alignment_(SHELF_ALIGNMENT_BOTTOM),
       shelf_(shelf),
@@ -318,7 +320,8 @@
   if (!workspace_controller_)
     return;
 
-  if (Shell::GetInstance()->session_state_delegate()->IsScreenLocked()) {
+  if (Shell::GetInstance()->session_state_delegate()->IsScreenLocked() ||
+      force_shelf_always_visibile_) {
     SetState(SHELF_VISIBLE);
   } else {
     // TODO(zelidrag): Verify shelf drag animation still shows on the device
@@ -393,6 +396,9 @@
 // ShelfLayoutManager, Gesture functions:
 
 void ShelfLayoutManager::OnGestureEdgeSwipe(const ui::GestureEvent& gesture) {
+  if (force_shelf_always_visibile_)
+    return;
+
   if (visibility_state() == SHELF_AUTO_HIDE) {
     gesture_drag_auto_hide_state_ = SHELF_AUTO_HIDE_SHOWN;
     gesture_drag_status_ = GESTURE_DRAG_COMPLETE_IN_PROGRESS;
@@ -402,6 +408,8 @@
 }
 
 void ShelfLayoutManager::StartGestureDrag(const ui::GestureEvent& gesture) {
+  if (force_shelf_always_visibile_)
+    return;
   gesture_drag_status_ = GESTURE_DRAG_IN_PROGRESS;
   gesture_drag_amount_ = 0.f;
   gesture_drag_auto_hide_state_ = visibility_state() == SHELF_AUTO_HIDE ?
@@ -411,6 +419,8 @@
 
 ShelfLayoutManager::DragState ShelfLayoutManager::UpdateGestureDrag(
     const ui::GestureEvent& gesture) {
+  if (force_shelf_always_visibile_)
+    return DRAG_SHELF;
   bool horizontal = IsHorizontalAlignment();
   gesture_drag_amount_ += horizontal ? gesture.details().scroll_y() :
                                        gesture.details().scroll_x();
@@ -435,6 +445,8 @@
 }
 
 void ShelfLayoutManager::CompleteGestureDrag(const ui::GestureEvent& gesture) {
+  if (force_shelf_always_visibile_)
+    return;
   bool horizontal = IsHorizontalAlignment();
   bool should_change = false;
   if (gesture.type() == ui::ET_GESTURE_SCROLL_END) {
@@ -555,6 +567,21 @@
   LayoutShelf();
 }
 
+void ShelfLayoutManager::OnMaximizeModeStarted() {
+  DCHECK(!force_shelf_always_visibile_);
+  force_shelf_always_visibile_ = true;
+  UpdateVisibilityState();
+}
+
+void ShelfLayoutManager::OnMaximizeModeEnded() {
+  DCHECK(force_shelf_always_visibile_);
+  // Note: At this time Ash::Shell::IsMaximizeModeWindowManagerEnabled() will
+  // report true, even though it is in progress of shut down. To address this
+  // |force_shelf_always_visibile_| will be read.
+  force_shelf_always_visibile_ = false;
+  UpdateVisibilityState();
+}
+
 void ShelfLayoutManager::OnWindowActivated(aura::Window* gained_active,
                                            aura::Window* lost_active) {
   UpdateAutoHideStateNow();
@@ -1003,6 +1030,9 @@
 
 ShelfAutoHideState ShelfLayoutManager::CalculateAutoHideState(
     ShelfVisibilityState visibility_state) const {
+  if (force_shelf_always_visibile_)
+    return SHELF_AUTO_HIDE_SHOWN;
+
   if (visibility_state != SHELF_AUTO_HIDE || !shelf_)
     return SHELF_AUTO_HIDE_HIDDEN;
 
diff --git a/ash/shelf/shelf_layout_manager.h b/ash/shelf/shelf_layout_manager.h
index 861b25b..4e03c7a 100644
--- a/ash/shelf/shelf_layout_manager.h
+++ b/ash/shelf/shelf_layout_manager.h
@@ -21,12 +21,12 @@
 #include "base/logging.h"
 #include "base/observer_list.h"
 #include "base/timer/timer.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/layout_manager.h"
 #include "ui/gfx/insets.h"
 #include "ui/gfx/rect.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_controller_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class RootWindow;
@@ -184,6 +184,8 @@
 
   // Overridden from ash::ShellObserver:
   virtual void OnLockStateChanged(bool locked) OVERRIDE;
+  virtual void OnMaximizeModeStarted() OVERRIDE;
+  virtual void OnMaximizeModeEnded() OVERRIDE;
 
   // Overriden from aura::client::ActivationChangeObserver:
   virtual void OnWindowActivated(aura::Window* gained_active,
@@ -346,6 +348,10 @@
   // UpdateBoundsAndOpacity() again from SetChildBounds().
   bool updating_bounds_;
 
+  // If true, the shelf gets forced (e.g. by the maximize mode) to be always
+  // visible.
+  bool force_shelf_always_visibile_;
+
   // See description above setter.
   ShelfAutoHideBehavior auto_hide_behavior_;
 
diff --git a/ash/shelf/shelf_layout_manager_unittest.cc b/ash/shelf/shelf_layout_manager_unittest.cc
index 7b3b5d8..9217b2a 100644
--- a/ash/shelf/shelf_layout_manager_unittest.cc
+++ b/ash/shelf/shelf_layout_manager_unittest.cc
@@ -861,6 +861,38 @@
   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
 }
 
+// Check that swipes and mouse interactions do have no impact in Maximize mode.
+TEST_F(ShelfLayoutManagerTest, MaximizeModePreventsMouseHide) {
+  aura::Window* root = Shell::GetPrimaryRootWindow();
+  aura::test::EventGenerator generator(root, root);
+  generator.MoveMouseTo(0, 0);
+
+  ShelfLayoutManager* shelf = GetShelfLayoutManager();
+  shelf->SetAutoHideBehavior(ash::SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+  views::Widget* widget = new views::Widget;
+  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+  params.bounds = gfx::Rect(0, 0, 200, 200);
+  params.context = CurrentContext();
+  // Widget is now owned by the parent window.
+  widget->Init(params);
+  widget->Maximize();
+  widget->Show();
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+  shelf->OnMaximizeModeStarted();
+  // LayoutShelf() forces the animation to completion.
+  shelf->LayoutShelf();
+
+  // Drag mouse to bottom of screen. In contrast to normal operation the shelf
+  // should remain visible.
+  generator.MoveMouseTo(0, 0);
+  generator.PressLeftButton();
+  generator.MoveMouseTo(0, root->bounds().bottom() - 1);
+  UpdateAutoHideStateNow();
+  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+}
+
 // Test the behavior of the shelf when it is auto hidden and it is on the
 // boundary between the primary and the secondary display.
 TEST_F(ShelfLayoutManagerTest, AutoHideShelfOnScreenBoundary) {
@@ -1493,7 +1525,8 @@
             display.work_area().y() - display.bounds().y());
 }
 
-TEST_F(ShelfLayoutManagerTest, GestureEdgeSwipe) {
+//  https://code.google.com/p/chromium/issues/detail?id=356419
+TEST_F(ShelfLayoutManagerTest, DISABLED_GestureEdgeSwipe) {
   ShelfLayoutManager* shelf = GetShelfLayoutManager();
   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
   views::Widget* widget = new views::Widget;
@@ -1504,41 +1537,63 @@
   widget->Show();
   widget->Maximize();
 
-  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
-
   aura::Window* window = widget->GetNativeWindow();
   shelf->LayoutShelf();
 
   gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
   gfx::Rect bounds_shelf = window->bounds();
-
-  // Edge swipe when SHELF_VISIBLE should not change visibility state.
-  EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
-  generator.GestureEdgeSwipe();
   EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
 
-  // Edge swipe when AUTO_HIDE_HIDDEN should change to AUTO_HIDE_SHOWN.
   shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
   shelf->LayoutShelf();
-  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
   generator.GestureEdgeSwipe();
-  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
-  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+  EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
 
   widget->SetFullscreen(true);
   wm::GetWindowState(window)->set_hide_shelf_when_fullscreen(false);
   shelf->UpdateVisibilityState();
 
-  // Edge swipe in fullscreen + AUTO_HIDE_HIDDEN should show the shelf and
-  // remain fullscreen.
+  gfx::Rect bounds_fullscreen = window->bounds();
   EXPECT_TRUE(widget->IsFullscreen());
-  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
   generator.GestureEdgeSwipe();
-  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_BEHAVIOR_NEVER, shelf->auto_hide_behavior());
+  EXPECT_FALSE(widget->IsFullscreen());
+}
+
+// Check that in maximize mode gesture swipes on the shelf have no effect.
+TEST_F(ShelfLayoutManagerTest, MaximizeModeGestureEdgeSwipe) {
+  ShelfLayoutManager* shelf = GetShelfLayoutManager();
+  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER);
+  views::Widget* widget = new views::Widget;
+  views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
+  params.bounds = gfx::Rect(0, 0, 200, 200);
+  params.context = CurrentContext();
+  widget->Init(params);
+  widget->Show();
+  widget->Maximize();
+
+  shelf->LayoutShelf();
+
+  shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+  shelf->LayoutShelf();
+  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+  shelf->OnMaximizeModeStarted();
+  shelf->LayoutShelf();
   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
-  EXPECT_TRUE(widget->IsFullscreen());
+
+  aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow());
+  generator.GestureEdgeSwipe();
+
+  EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
 }
 
 #if defined(OS_WIN)
@@ -1933,6 +1988,34 @@
   EXPECT_EQ(SHELF_BACKGROUND_OVERLAP, GetShelfWidget()->GetBackgroundType());
 }
 
+// Verify that setting the shelf's auto hide mode in maximize mode does not
+// hide.
+TEST_F(ShelfLayoutManagerTest, DoesNotHideInMaximizeMode) {
+  EXPECT_EQ(SHELF_BACKGROUND_DEFAULT, GetShelfWidget()->GetBackgroundType());
+
+  GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+  scoped_ptr<aura::Window> w1(CreateTestWindow());
+  w1->Show();
+  ShelfLayoutManager* shelf = GetShelfLayoutManager();
+
+  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+
+  GetShelfLayoutManager()->OnMaximizeModeStarted();
+  EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+  // Setting the state again should have no impact.
+  GetShelfLayoutManager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
+  EXPECT_EQ(SHELF_VISIBLE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->auto_hide_state());
+
+  GetShelfLayoutManager()->OnMaximizeModeEnded();
+  EXPECT_EQ(SHELF_AUTO_HIDE, shelf->visibility_state());
+  EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->auto_hide_state());
+}
+
 #if defined(OS_CHROMEOS)
 #define MAYBE_StatusAreaHitBoxCoversEdge StatusAreaHitBoxCoversEdge
 #else
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index 47c6d07..f3f1f29 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -22,7 +22,6 @@
 #include "ash/wm/window_properties.h"
 #include "ash/wm/workspace_controller.h"
 #include "grit/ash_resources.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_observer.h"
@@ -38,6 +37,7 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/wm/core/easy_resize_window_targeter.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace {
 // Size of black border at bottom (or side) of shelf.
diff --git a/ash/shelf/shelf_window_watcher.cc b/ash/shelf/shelf_window_watcher.cc
index 59cb38b..9488d10 100644
--- a/ash/shelf/shelf_window_watcher.cc
+++ b/ash/shelf/shelf_window_watcher.cc
@@ -16,11 +16,11 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/screen.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace {
 
diff --git a/ash/shelf/shelf_window_watcher.h b/ash/shelf/shelf_window_watcher.h
index 57b4ed2..ba42756 100644
--- a/ash/shelf/shelf_window_watcher.h
+++ b/ash/shelf/shelf_window_watcher.h
@@ -10,9 +10,9 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/scoped_observer.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/display_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 
diff --git a/ash/shell.cc b/ash/shell.cc
index 8f47b57..34c386d 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -113,16 +113,13 @@
 #if defined(USE_X11)
 #include "ash/accelerators/magnifier_key_scroller.h"
 #include "ash/accelerators/spoken_feedback_toggler.h"
+#include "base/message_loop/message_pump_x11.h"
+#endif  // defined(USE_X11)
 #include "ash/ash_constants.h"
 #include "ash/display/display_change_observer_chromeos.h"
 #include "ash/display/display_error_observer_chromeos.h"
 #include "ash/display/output_configurator_animation.h"
 #include "ash/display/projecting_observer_chromeos.h"
-#include "ash/system/chromeos/session/last_window_closed_logout_reminder.h"
-#include "base/message_loop/message_pump_x11.h"
-#include "base/sys_info.h"
-#include "ui/display/chromeos/output_configurator.h"
-#endif  // defined(USE_X11)
 #include "ash/display/resolution_notification_controller.h"
 #include "ash/sticky_keys/sticky_keys_controller.h"
 #include "ash/system/chromeos/bluetooth/bluetooth_notification_controller.h"
@@ -131,8 +128,11 @@
 #include "ash/system/chromeos/power/power_status.h"
 #include "ash/system/chromeos/power/user_activity_notifier.h"
 #include "ash/system/chromeos/power/video_activity_notifier.h"
+#include "ash/system/chromeos/session/last_window_closed_logout_reminder.h"
 #include "ash/system/chromeos/session/logout_confirmation_controller.h"
 #include "base/bind_helpers.h"
+#include "base/sys_info.h"
+#include "ui/display/chromeos/output_configurator.h"
 #endif  // defined(OS_CHROMEOS)
 
 namespace ash {
@@ -606,12 +606,12 @@
       delegate_(delegate),
       window_positioner_(new WindowPositioner),
       activation_client_(NULL),
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
       output_configurator_(new ui::OutputConfigurator()),
-#endif  // defined(OS_CHROMEOS) && defined(USE_X11)
+#endif  // defined(OS_CHROMEOS)
       native_cursor_manager_(new AshNativeCursorManager),
-      cursor_manager_(scoped_ptr< ::wm::NativeCursorManager>(
-          native_cursor_manager_)),
+      cursor_manager_(
+          scoped_ptr< ::wm::NativeCursorManager>(native_cursor_manager_)),
       simulate_modal_window_open_for_testing_(false),
       is_touch_hud_projection_enabled_(false) {
   DCHECK(delegate_.get());
@@ -630,6 +630,8 @@
 Shell::~Shell() {
   TRACE_EVENT0("shutdown", "ash::Shell::Destructor");
 
+  delegate_->PreShutdown();
+
   views::FocusManagerFactory::Install(NULL);
 
   // Remove the focus from any window. This will prevent overhead and side
@@ -760,7 +762,7 @@
   new_window_delegate_.reset();
   media_delegate_.reset();
 
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   if (display_change_observer_)
     output_configurator_->RemoveObserver(display_change_observer_.get());
   if (output_configurator_animation_)
@@ -787,7 +789,7 @@
         internal::DisplayManager::VIRTUAL_KEYBOARD);
   }
   bool display_initialized = display_manager_->InitFromCommandLine();
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   output_configurator_->Init(!gpu_support_->IsPanelFittingDisabled());
   output_configurator_animation_.reset(
       new internal::OutputConfiguratorAnimation());
@@ -809,7 +811,7 @@
         delegate_->IsFirstRunAfterBoot() ? kChromeOsBootColor : 0);
     display_initialized = true;
   }
-#endif  // defined(OS_CHROMEOS) && defined(USE_X11)
+#endif  // defined(OS_CHROMEOS)
   if (!display_initialized)
     display_manager_->InitDefaultDisplay();
 
@@ -910,7 +912,7 @@
   lock_state_controller_.reset(new LockStateController);
   power_button_controller_.reset(new PowerButtonController(
       lock_state_controller_.get()));
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   // Pass the initial display state to PowerButtonController.
   power_button_controller_->OnDisplayModeChanged(
       output_configurator_->cached_outputs());
diff --git a/ash/shell.h b/ash/shell.h
index ddb59b6..1f511db 100644
--- a/ash/shell.h
+++ b/ash/shell.h
@@ -19,7 +19,6 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/events/event_target.h"
@@ -27,6 +26,7 @@
 #include "ui/gfx/screen.h"
 #include "ui/gfx/size.h"
 #include "ui/wm/core/cursor_manager.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace app_list {
 class AppListView;
@@ -501,7 +501,6 @@
   void DoInitialWorkspaceAnimation();
 
 #if defined(OS_CHROMEOS)
-#if defined(USE_X11)
   // TODO(oshima): Move these objects to DisplayController.
   ui::OutputConfigurator* output_configurator() {
     return output_configurator_.get();
@@ -512,7 +511,6 @@
   internal::DisplayErrorObserver* display_error_observer() {
     return display_error_observer_.get();
   }
-#endif  // defined(USE_X11)
 
   internal::ResolutionNotificationController*
       resolution_notification_controller() {
@@ -712,7 +710,6 @@
       logout_confirmation_controller_;
   scoped_ptr<internal::LastWindowClosedLogoutReminder>
       last_window_closed_logout_reminder_;
-#if defined(USE_X11)
   // Controls video output device state.
   scoped_ptr<ui::OutputConfigurator> output_configurator_;
   scoped_ptr<internal::OutputConfiguratorAnimation>
@@ -723,6 +720,7 @@
   // Listens for output changes and updates the display manager.
   scoped_ptr<internal::DisplayChangeObserver> display_change_observer_;
 
+#if defined(USE_X11)
   scoped_ptr<ui::EventHandler> magnifier_key_scroll_handler_;
   scoped_ptr<ui::EventHandler> speech_feedback_handler_;
 #endif  // defined(USE_X11)
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc
index d21f7ac..4efd104 100644
--- a/ash/shell/shell_delegate_impl.cc
+++ b/ash/shell/shell_delegate_impl.cc
@@ -101,7 +101,7 @@
 void ShellDelegateImpl::PreInit() {
 }
 
-void ShellDelegateImpl::Shutdown() {
+void ShellDelegateImpl::PreShutdown() {
 }
 
 void ShellDelegateImpl::Exit() {
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h
index 2b5aa12..705ef21 100644
--- a/ash/shell/shell_delegate_impl.h
+++ b/ash/shell/shell_delegate_impl.h
@@ -39,7 +39,7 @@
   virtual bool IsMultiProfilesEnabled() const OVERRIDE;
   virtual bool IsRunningInForcedAppMode() const OVERRIDE;
   virtual void PreInit() OVERRIDE;
-  virtual void Shutdown() OVERRIDE;
+  virtual void PreShutdown() OVERRIDE;
   virtual void Exit() OVERRIDE;
   virtual keyboard::KeyboardControllerProxy*
       CreateKeyboardControllerProxy() OVERRIDE;
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h
index ba28e0c..9a4ac77 100644
--- a/ash/shell_delegate.h
+++ b/ash/shell_delegate.h
@@ -76,8 +76,9 @@
   // can perform tasks necessary before the shell is initialized.
   virtual void PreInit() = 0;
 
-  // Shuts down the environment.
-  virtual void Shutdown() = 0;
+  // Called at the beginninig of Shell destructor so that
+  // delegate can use Shell instance to perform cleanup tasks.
+  virtual void PreShutdown() = 0;
 
   // Invoked when the user uses Ctrl-Shift-Q to close chrome.
   virtual void Exit() = 0;
diff --git a/ash/sticky_keys/sticky_keys_controller.cc b/ash/sticky_keys/sticky_keys_controller.cc
index 812e46e..e5bb0af 100644
--- a/ash/sticky_keys/sticky_keys_controller.cc
+++ b/ash/sticky_keys/sticky_keys_controller.cc
@@ -97,7 +97,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 //  StickyKeys
 StickyKeysController::StickyKeysController()
-    : enabled_(false) {
+    : enabled_(false),
+      mod3_enabled_(false),
+      altgr_enabled_(false) {
 }
 
 StickyKeysController::~StickyKeysController() {
@@ -124,12 +126,21 @@
                                 new StickyKeysHandlerDelegateImpl()));
 
       overlay_.reset(new StickyKeysOverlay());
-    } else if (overlay_.get()) {
+      overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_);
+    } else if (overlay_) {
       overlay_->Show(false);
     }
   }
 }
 
+void StickyKeysController::SetModifiersEnabled(bool mod3_enabled,
+                                               bool altgr_enabled) {
+  mod3_enabled_ = mod3_enabled;
+  altgr_enabled_ = altgr_enabled;
+  if (overlay_)
+    overlay_->SetModifierVisible(ui::EF_ALTGR_DOWN, altgr_enabled_);
+}
+
 bool StickyKeysController::HandleKeyEvent(ui::KeyEvent* event) {
   return shift_sticky_key_->HandleKeyEvent(event) ||
       alt_sticky_key_->HandleKeyEvent(event) ||
diff --git a/ash/sticky_keys/sticky_keys_controller.h b/ash/sticky_keys/sticky_keys_controller.h
index 018d4f5..792f2c5 100644
--- a/ash/sticky_keys/sticky_keys_controller.h
+++ b/ash/sticky_keys/sticky_keys_controller.h
@@ -67,6 +67,8 @@
   // Activate sticky keys to intercept and modify incoming events.
   void Enable(bool enabled);
 
+  void SetModifiersEnabled(bool mod3_enabled, bool altgr_enabled);
+
   // Overridden from ui::EventHandler:
   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE;
@@ -92,6 +94,12 @@
   // Whether sticky keys is activated and modifying events.
   bool enabled_;
 
+  // Whether the current layout has a mod3 key.
+  bool mod3_enabled_;
+
+  // Whether the current layout has an altgr key.
+  bool altgr_enabled_;
+
   // Sticky key handlers.
   scoped_ptr<StickyKeysHandler> shift_sticky_key_;
   scoped_ptr<StickyKeysHandler> alt_sticky_key_;
diff --git a/ash/sticky_keys/sticky_keys_overlay.cc b/ash/sticky_keys/sticky_keys_overlay.cc
index 4d32f03..e91caf4 100644
--- a/ash/sticky_keys/sticky_keys_overlay.cc
+++ b/ash/sticky_keys/sticky_keys_overlay.cc
@@ -130,6 +130,8 @@
 
   StickyKeyState GetKeyState(ui::EventFlags modifier);
 
+  void SetModifierVisible(ui::EventFlags modifier, bool visible);
+
  private:
   void AddKeyLabel(ui::EventFlags modifier, const std::string& key_label);
 
@@ -191,6 +193,13 @@
   return it->second->state();
 }
 
+void StickyKeysOverlayView::SetModifierVisible(ui::EventFlags modifier,
+                                               bool visible) {
+  ModifierLabelMap::iterator it = modifier_label_map_.find(modifier);
+  DCHECK(it != modifier_label_map_.end());
+  it->second->SetVisible(visible);
+}
+
 void StickyKeysOverlayView::AddKeyLabel(ui::EventFlags modifier,
                                         const std::string& key_label) {
   StickyKeyOverlayLabel* label = new StickyKeyOverlayLabel(key_label);
@@ -257,6 +266,12 @@
   overlay_widget_->GetLayer()->SetTransform(gfx::Transform());
 }
 
+void StickyKeysOverlay::SetModifierVisible(ui::EventFlags modifier,
+                                           bool visible) {
+  overlay_view_->SetModifierVisible(modifier, visible);
+  widget_size_ = overlay_view_->GetPreferredSize();
+}
+
 void StickyKeysOverlay::SetModifierKeyState(ui::EventFlags modifier,
                                             StickyKeyState state) {
   overlay_view_->SetKeyState(modifier, state);
diff --git a/ash/sticky_keys/sticky_keys_overlay.h b/ash/sticky_keys/sticky_keys_overlay.h
index 88d195a..74d082a 100644
--- a/ash/sticky_keys/sticky_keys_overlay.h
+++ b/ash/sticky_keys/sticky_keys_overlay.h
@@ -36,6 +36,8 @@
   // Shows or hides the overlay.
   void Show(bool visible);
 
+  void SetModifierVisible(ui::EventFlags modifier, bool visible);
+
   // Updates the overlay with the current state of a sticky key modifier.
   void SetModifierKeyState(ui::EventFlags modifier,
                            StickyKeyState state);
diff --git a/ash/strings/ash_strings_am.xtb b/ash/strings/ash_strings_am.xtb
index dd99043..99cec7e 100644
--- a/ash/strings/ash_strings_am.xtb
+++ b/ash/strings/ash_strings_am.xtb
@@ -203,7 +203,7 @@
 <translation id="7593891976182323525">Search ወይም Shift</translation>
 <translation id="7649070708921625228">እገዛ</translation>
 <translation id="3050422059534974565">CAPS LOCK በርቷል።
-ለመሰረዝ Search ወይም Shift ይጫኑ።</translation>
+ይቅር ለማለት Search ወይም Shift ይጫኑ።</translation>
 <translation id="397105322502079400">በማስላት ላይ...</translation>
 <translation id="158849752021629804">የቤት አውታረ መረብ ያስፈልጋል</translation>
 <translation id="6857811139397017780"><ph name="NETWORKSERVICE"/>ን አግብር</translation>
@@ -221,7 +221,7 @@
 ለማሰናከል Ctrl+Alt+Z ይጫኑ።</translation>
 <translation id="5045002648206642691">የGoogle Drive ቅንብሮች...</translation>
 <translation id="7209101170223508707">CAPS LOCK በርቷል።
-ለመሰረዝ Alt+Search ወይም Shift ይጫኑ።</translation>
+ይቅር ለማለት Alt+Search ወይም Shift ይጫኑ።</translation>
 <translation id="8940956008527784070">ባትሪ ዝቅተኛ ነው (<ph name="PERCENTAGE"/>%)</translation>
 <translation id="4918086044614829423">ይቀበሉ</translation>
 <translation id="5102001756192215136"><ph name="HOUR"/>:<ph name="MINUTE"/> ቀርቷል</translation>
diff --git a/ash/system/chromeos/network/network_connect.cc b/ash/system/chromeos/network/network_connect.cc
index d83357d..e239ff9 100644
--- a/ash/system/chromeos/network/network_connect.cc
+++ b/ash/system/chromeos/network/network_connect.cc
@@ -109,6 +109,32 @@
   NOTREACHED();
 }
 
+// If |shared| is true, sets |profile_path| to the shared profile path.
+// Otherwise sets |profile_path| to the user profile path if authenticated and
+// available. Returns 'false' if unable to set |profile_path|.
+bool GetNetworkProfilePath(bool shared, std::string* profile_path) {
+  if (shared) {
+    *profile_path = NetworkProfileHandler::GetSharedProfilePath();
+    return true;
+  }
+
+  if (!chromeos::LoginState::Get()->IsUserAuthenticated()) {
+    NET_LOG_ERROR("User profile specified before login", "");
+    return false;
+  }
+
+  const NetworkProfile* profile  =
+      NetworkHandler::Get()->network_profile_handler()->
+      GetDefaultUserProfile();
+  if (!profile) {
+    NET_LOG_ERROR("No user profile for unshared network configuration", "");
+    return false;
+  }
+
+  *profile_path = profile->path;
+  return true;
+}
+
 void OnConnectFailed(const std::string& service_path,
                      gfx::NativeWindow parent_window,
                      const std::string& error_name,
@@ -213,14 +239,33 @@
   ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, "");
 }
 
-void OnConfigureSucceeded(const std::string& service_path) {
+void OnConfigureSucceeded(bool connect_on_configure,
+                          const std::string& service_path) {
   NET_LOG_USER("Configure Succeeded", service_path);
+  if (!connect_on_configure)
+    return;
   // After configuring a network, ignore any (possibly stale) error state.
   const bool check_error_state = false;
   const gfx::NativeWindow parent_window = NULL;
   CallConnectToNetwork(service_path, check_error_state, parent_window);
 }
 
+void CallCreateConfiguration(base::DictionaryValue* properties,
+                             bool shared,
+                             bool connect_on_configure) {
+  std::string profile_path;
+  if (!GetNetworkProfilePath(shared, &profile_path)) {
+    ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, "");
+    return;
+  }
+  properties->SetStringWithoutPathExpansion(
+      shill::kProfileProperty, profile_path);
+  NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
+      *properties,
+      base::Bind(&OnConfigureSucceeded, connect_on_configure),
+      base::Bind(&OnConfigureFailed));
+}
+
 void SetPropertiesFailed(const std::string& desc,
                          const std::string& service_path,
                          const std::string& config_error_name,
@@ -262,31 +307,6 @@
       base::Bind(&SetPropertiesFailed, "ClearProperties", service_path));
 }
 
-// Returns false if !shared and no valid profile is available, which will
-// trigger an error and abort.
-bool GetNetworkProfilePath(bool shared, std::string* profile_path) {
-  if (shared) {
-    *profile_path = NetworkProfileHandler::GetSharedProfilePath();
-    return true;
-  }
-
-  if (!chromeos::LoginState::Get()->IsUserAuthenticated()) {
-    NET_LOG_ERROR("User profile specified before login", "");
-    return false;
-  }
-
-  const NetworkProfile* profile  =
-      NetworkHandler::Get()->network_profile_handler()->
-      GetDefaultUserProfile();
-  if (!profile) {
-    NET_LOG_ERROR("No user profile for unshared network configuration", "");
-    return false;
-  }
-
-  *profile_path = profile->path;
-  return true;
-}
-
 void ConfigureSetProfileSucceeded(
     const std::string& service_path,
     scoped_ptr<base::DictionaryValue> properties_to_set) {
@@ -321,8 +341,8 @@
                       gfx::NativeWindow parent_window) {
   NET_LOG_USER("ConnectToNetwork", service_path);
   const NetworkState* network = GetNetworkState(service_path);
-  if (network && !network->last_error().empty()) {
-    NET_LOG_USER("Configure: " + network->last_error(), service_path);
+  if (network && !network->error().empty() && !network->security().empty()) {
+    NET_LOG_USER("Configure: " + network->error(), service_path);
     // If the network is in an error state, show the configuration UI directly
     // to avoid a spurious notification.
     HandleUnconfiguredNetwork(service_path, parent_window);
@@ -466,17 +486,12 @@
 void CreateConfigurationAndConnect(base::DictionaryValue* properties,
                                    bool shared) {
   NET_LOG_USER("CreateConfigurationAndConnect", "");
-  std::string profile_path;
-  if (!GetNetworkProfilePath(shared, &profile_path)) {
-    ShowErrorNotification(NetworkConnectionHandler::kErrorConfigureFailed, "");
-    return;
-  }
-  properties->SetStringWithoutPathExpansion(
-      shill::kProfileProperty, profile_path);
-  NetworkHandler::Get()->network_configuration_handler()->CreateConfiguration(
-      *properties,
-      base::Bind(&OnConfigureSucceeded),
-      base::Bind(&OnConfigureFailed));
+  CallCreateConfiguration(properties, shared, true /* connect_on_configure */);
+}
+
+void CreateConfiguration(base::DictionaryValue* properties, bool shared) {
+  NET_LOG_USER("CreateConfiguration", "");
+  CallCreateConfiguration(properties, shared, false /* connect_on_configure */);
 }
 
 base::string16 ErrorString(const std::string& error,
diff --git a/ash/system/chromeos/network/network_connect.h b/ash/system/chromeos/network/network_connect.h
index adf939d..2d72938 100644
--- a/ash/system/chromeos/network/network_connect.h
+++ b/ash/system/chromeos/network/network_connect.h
@@ -55,10 +55,16 @@
     bool shared);
 
 // Requests a new network configuration to be created from a dictionary of
-// Shill properties. The profile used is determined by |shared|.
+// Shill properties and sends a connect request if the configuration succeeds.
+// The profile used is determined by |shared|.
 ASH_EXPORT void CreateConfigurationAndConnect(base::DictionaryValue* properties,
                                               bool shared);
 
+// Requests a new network configuration to be created from a dictionary of
+// Shill properties. The profile used is determined by |shared|.
+ASH_EXPORT void CreateConfiguration(base::DictionaryValue* properties,
+                                    bool shared);
+
 // Returns the localized string for shill error string |error|.
 ASH_EXPORT base::string16 ErrorString(const std::string& error,
                                       const std::string& service_path);
diff --git a/ash/system/chromeos/network/network_state_notifier.cc b/ash/system/chromeos/network/network_state_notifier.cc
index b81476d..027b284 100644
--- a/ash/system/chromeos/network/network_state_notifier.cc
+++ b/ash/system/chromeos/network/network_state_notifier.cc
@@ -252,35 +252,41 @@
     std::string shill_error;
     shill_properties.GetStringWithoutPathExpansion(shill::kErrorProperty,
                                                    &shill_error);
-    if (shill_error.empty()) {
-      NET_LOG_DEBUG("Service.Error is empty, trying PreviousError",
-                    service_path);
+    if (!chromeos::NetworkState::ErrorIsValid(shill_error)) {
       shill_properties.GetStringWithoutPathExpansion(
           shill::kPreviousErrorProperty, &shill_error);
+      NET_LOG_DEBUG("Notify Service.PreviousError: " + shill_error,
+                    service_path);
+      if (!chromeos::NetworkState::ErrorIsValid(shill_error))
+        shill_error.clear();
+    } else {
+      NET_LOG_DEBUG("Notify Service.Error: " + shill_error, service_path);
     }
-    std::string last_error;
+
     const NetworkState* network =
         NetworkHandler::Get()->network_state_handler()->GetNetworkState(
             service_path);
-    if (network)
-      last_error = network->last_error();
-    if (!last_error.empty() && last_error != shill_error) {
-      NET_LOG_DEBUG(
-          "last_error:" + last_error + " != Service.Error: " + shill_error,
-          service_path);
-      // Use Shill Error unless empty, since it is more recent.
+    if (network) {
+      // Always log last_error, but only use it if shill_error is empty.
+      // TODO(stevenjb): This shouldn't ever be necessary, but is kept here as a
+      // failsafe since more information is better than less when debugging and
+      // we have encountered some strange edge cases before.
+      NET_LOG_DEBUG("Notify Network.last_error: " + network->last_error(),
+                    service_path);
       if (shill_error.empty())
-        shill_error = last_error;
+        shill_error = network->last_error();
     }
+
     if (ShillErrorIsIgnored(shill_error)) {
-      NET_LOG_DEBUG("Ignoring error: " + error_name, service_path);
+      NET_LOG_DEBUG("Notify Ignoring error: " + error_name, service_path);
       return;
     }
+
     error = network_connect::ErrorString(shill_error, service_path);
     if (error.empty())
       error = l10n_util::GetStringUTF16(IDS_CHROMEOS_NETWORK_ERROR_UNKNOWN);
   }
-  NET_LOG_ERROR("Connect error notification: " + base::UTF16ToUTF8(error),
+  NET_LOG_ERROR("Notify connect error: " + base::UTF16ToUTF8(error),
                 service_path);
 
   std::string network_name =
diff --git a/ash/system/system_notifier.cc b/ash/system/system_notifier.cc
index 16e024a..7669186 100644
--- a/ash/system/system_notifier.cc
+++ b/ash/system/system_notifier.cc
@@ -22,7 +22,6 @@
 };
 
 const char* kAshSystemNotifiers[] = {
-  kNotifierAuthError,
   kNotifierDisplay,
   kNotifierDisplayResolutionChange,
   kNotifierDisplayError,
@@ -55,7 +54,6 @@
 
 }  // namespace
 
-const char kNotifierAuthError[] = "ash.auth.error";
 const char kNotifierBluetooth[] = "ash.bluetooth";
 const char kNotifierDisplay[] = "ash.display";
 const char kNotifierDisplayResolutionChange[] = "ash.display.resolution-change";
diff --git a/ash/system/system_notifier.h b/ash/system/system_notifier.h
index 00ec2df..0d4b6c7 100644
--- a/ash/system/system_notifier.h
+++ b/ash/system/system_notifier.h
@@ -14,7 +14,6 @@
 namespace system_notifier {
 
 // The list of ash system notifier IDs. Alphabetical order.
-ASH_EXPORT extern const char kNotifierAuthError[];
 ASH_EXPORT extern const char kNotifierBluetooth[];
 ASH_EXPORT extern const char kNotifierDisplay[];
 ASH_EXPORT extern const char kNotifierDisplayResolutionChange[];
diff --git a/ash/system/tray/hover_highlight_view.cc b/ash/system/tray/hover_highlight_view.cc
index bc8f017..e78944c 100644
--- a/ash/system/tray/hover_highlight_view.cc
+++ b/ash/system/tray/hover_highlight_view.cc
@@ -142,7 +142,8 @@
 
   if (checkable_) {
     state->role = ui::AX_ROLE_CHECK_BOX;
-    state->state = checked_ ? ui::AX_STATE_CHECKED : 0;
+    if (checked_)
+      state->AddStateFlag(ui::AX_STATE_CHECKED);
   }
 }
 
diff --git a/ash/system/tray_accessibility.cc b/ash/system/tray_accessibility.cc
index 4e94408..073b898 100644
--- a/ash/system/tray_accessibility.cc
+++ b/ash/system/tray_accessibility.cc
@@ -14,8 +14,8 @@
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/tray/tray_details_view.h"
 #include "ash/system/tray/tray_item_more.h"
-#include "ash/system/tray/tray_notification_view.h"
 #include "ash/system/tray/tray_popup_label_button.h"
+#include "base/strings/utf_string_conversions.h"
 #include "grit/ash_resources.h"
 #include "grit/ash_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -32,13 +32,14 @@
 namespace {
 
 enum AccessibilityState {
-  A11Y_NONE             = 0,
-  A11Y_SPOKEN_FEEDBACK  = 1 << 0,
-  A11Y_HIGH_CONTRAST    = 1 << 1,
+  A11Y_NONE = 0,
+  A11Y_SPOKEN_FEEDBACK = 1 << 0,
+  A11Y_HIGH_CONTRAST = 1 << 1,
   A11Y_SCREEN_MAGNIFIER = 1 << 2,
-  A11Y_LARGE_CURSOR     = 1 << 3,
-  A11Y_AUTOCLICK        = 1 << 4,
+  A11Y_LARGE_CURSOR = 1 << 3,
+  A11Y_AUTOCLICK = 1 << 4,
   A11Y_VIRTUAL_KEYBOARD = 1 << 5,
+  A11Y_BRAILLE_DISPLAY_CONNECTED = 1 << 6,
 };
 
 uint32 GetAccessibilityState() {
@@ -57,6 +58,8 @@
     state |= A11Y_AUTOCLICK;
   if (delegate->IsVirtualKeyboardEnabled())
     state |= A11Y_VIRTUAL_KEYBOARD;
+  if (delegate->IsBrailleDisplayConnected())
+    state |= A11Y_BRAILLE_DISPLAY_CONNECTED;
   return state;
 }
 
@@ -88,25 +91,35 @@
   DISALLOW_COPY_AND_ASSIGN(DefaultAccessibilityView);
 };
 
-class AccessibilityPopupView : public TrayNotificationView {
- public:
-  AccessibilityPopupView(SystemTrayItem* owner)
-      : TrayNotificationView(owner, IDR_AURA_UBER_TRAY_ACCESSIBILITY_DARK) {
-    InitView(GetLabel());
-  }
+////////////////////////////////////////////////////////////////////////////////
+// ash::internal::tray::AccessibilityPopupView
 
- private:
-  views::Label* GetLabel() {
-    views::Label* label = new views::Label(
-        l10n_util::GetStringUTF16(
-            IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE));
-    label->SetMultiLine(true);
-    label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    return label;
-  }
+AccessibilityPopupView::AccessibilityPopupView(SystemTrayItem* owner,
+                                               uint32 enabled_state_bits)
+    : TrayNotificationView(owner, IDR_AURA_UBER_TRAY_ACCESSIBILITY_DARK),
+      label_(CreateLabel(enabled_state_bits)) {
+  InitView(label_);
+}
 
-  DISALLOW_COPY_AND_ASSIGN(AccessibilityPopupView);
-};
+views::Label* AccessibilityPopupView::CreateLabel(uint32 enabled_state_bits) {
+  DCHECK((enabled_state_bits &
+          (A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED)) != 0);
+  base::string16 text;
+  if (enabled_state_bits & A11Y_BRAILLE_DISPLAY_CONNECTED) {
+    text.append(l10n_util::GetStringUTF16(
+        IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED_BUBBLE));
+  }
+  if (enabled_state_bits & A11Y_SPOKEN_FEEDBACK) {
+    if (!text.empty())
+      text.append(base::ASCIIToUTF16(" "));
+    text.append(l10n_util::GetStringUTF16(
+        IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE));
+  }
+  views::Label* label = new views::Label(text);
+  label->SetMultiLine(true);
+  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  return label;
+}
 
 ////////////////////////////////////////////////////////////////////////////////
 // ash::internal::tray::AccessibilityDetailedView
@@ -302,7 +315,7 @@
       default_(NULL),
       detailed_popup_(NULL),
       detailed_menu_(NULL),
-      request_popup_view_(false),
+      request_popup_view_state_(A11Y_NONE),
       tray_icon_visible_(false),
       login_(GetCurrentLoginStatus()),
       previous_accessibility_state_(GetAccessibilityState()),
@@ -359,9 +372,10 @@
   CHECK(detailed_popup_ == NULL);
   CHECK(detailed_menu_ == NULL);
 
-  if (request_popup_view_) {
-    detailed_popup_ = new tray::AccessibilityPopupView(this);
-    request_popup_view_ = false;
+  if (request_popup_view_state_) {
+    detailed_popup_ =
+        new tray::AccessibilityPopupView(this, request_popup_view_state_);
+    request_popup_view_state_ = A11Y_NONE;
     return detailed_popup_;
   } else {
     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
@@ -394,11 +408,21 @@
   SetTrayIconVisible(GetInitialVisibility());
 
   uint32 accessibility_state = GetAccessibilityState();
-  if ((notify == ash::A11Y_NOTIFICATION_SHOW) &&
-      !(previous_accessibility_state_ & A11Y_SPOKEN_FEEDBACK) &&
-      (accessibility_state & A11Y_SPOKEN_FEEDBACK)) {
+  // We'll get an extra notification if a braille display is connected when
+  // spoken feedback wasn't already enabled.  This is because the braille
+  // connection state is already updated when spoken feedback is enabled so
+  // that the notifications can be consolidated into one.  Therefore, we
+  // return early if there's no change in the state that we keep track of.
+  if (accessibility_state == previous_accessibility_state_)
+    return;
+  // Contains bits for spoken feedback and braille display connected currently
+  // being enabled.
+  uint32 being_enabled =
+      (accessibility_state & ~previous_accessibility_state_) &
+      (A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED);
+  if ((notify == ash::A11Y_NOTIFICATION_SHOW) && being_enabled != A11Y_NONE) {
     // Shows popup if |notify| is true and the spoken feedback is being enabled.
-    request_popup_view_ = true;
+    request_popup_view_state_ = being_enabled;
     PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
   } else {
     if (detailed_popup_)
diff --git a/ash/system/tray_accessibility.h b/ash/system/tray_accessibility.h
index 1d6e9f8..df0a186 100644
--- a/ash/system/tray_accessibility.h
+++ b/ash/system/tray_accessibility.h
@@ -9,6 +9,7 @@
 #include "ash/shell_observer.h"
 #include "ash/system/tray/tray_details_view.h"
 #include "ash/system/tray/tray_image_item.h"
+#include "ash/system/tray/tray_notification_view.h"
 #include "ash/system/tray/view_click_listener.h"
 #include "base/gtest_prod_util.h"
 #include "ui/gfx/font.h"
@@ -21,6 +22,7 @@
 namespace views {
 class Button;
 class ImageView;
+class Label;
 class View;
 }
 
@@ -43,7 +45,19 @@
 
 namespace tray {
 
-class AccessibilityPopupView;
+class AccessibilityPopupView : public TrayNotificationView {
+ public:
+  AccessibilityPopupView(SystemTrayItem* owner, uint32 enabled_state_bits);
+
+  const views::Label* label_for_test() const { return label_; }
+
+ private:
+  views::Label* CreateLabel(uint32 enabled_state_bits);
+
+  views::Label* label_;
+
+  DISALLOW_COPY_AND_ASSIGN(AccessibilityPopupView);
+};
 
 class AccessibilityDetailedView : public TrayDetailsView,
                                   public ViewClickListener,
@@ -119,7 +133,10 @@
   tray::AccessibilityPopupView* detailed_popup_;
   tray::AccessibilityDetailedView* detailed_menu_;
 
-  bool request_popup_view_;
+  // Bitmap of fvalues from AccessibilityState.  Can contain any or
+  // both of A11Y_SPOKEN_FEEDBACK A11Y_BRAILLE_DISPLAY_CONNECTED.
+  uint32 request_popup_view_state_;
+
   bool tray_icon_visible_;
   user::LoginStatus login_;
 
diff --git a/ash/test/test_activation_delegate.h b/ash/test/test_activation_delegate.h
index 02aeb45..b60354e 100644
--- a/ash/test/test_activation_delegate.h
+++ b/ash/test/test_activation_delegate.h
@@ -7,9 +7,9 @@
 
 #include "base/compiler_specific.h"
 #include "base/logging.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
 #include "ui/events/event_handler.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace aura {
 class Window;
diff --git a/ash/test/test_session_state_delegate.cc b/ash/test/test_session_state_delegate.cc
index 722981f..491408e 100644
--- a/ash/test/test_session_state_delegate.cc
+++ b/ash/test/test_session_state_delegate.cc
@@ -46,6 +46,12 @@
   return NULL;
 }
 
+content::BrowserContext*
+TestSessionStateDelegate::GetBrowserContextForWindow(
+    aura::Window* window) {
+  return NULL;
+}
+
 int TestSessionStateDelegate::GetMaximumNumberOfLoggedInUsers() const {
   return 3;
 }
@@ -118,6 +124,11 @@
   user_adding_screen_running_ = user_adding_screen_running;
 }
 
+void TestSessionStateDelegate::SetUserImage(
+    const gfx::ImageSkia& user_image) {
+  user_image_ = user_image;
+}
+
 const base::string16 TestSessionStateDelegate::GetUserDisplayName(
     MultiProfileIndex index) const {
   return base::UTF8ToUTF16("Über tray Über tray Über tray Über tray");
@@ -140,11 +151,11 @@
 
 const gfx::ImageSkia& TestSessionStateDelegate::GetUserImage(
     content::BrowserContext* context) const {
-  return null_image_;
+  return user_image_;
 }
 
 bool TestSessionStateDelegate::ShouldShowAvatar(aura::Window* window) {
-  return false;
+  return !user_image_.isNull();
 }
 
 void TestSessionStateDelegate::SwitchActiveUser(const std::string& user_id) {
diff --git a/ash/test/test_session_state_delegate.h b/ash/test/test_session_state_delegate.h
index 21c34f6..2cc95e5 100644
--- a/ash/test/test_session_state_delegate.h
+++ b/ash/test/test_session_state_delegate.h
@@ -24,6 +24,8 @@
   // SessionStateDelegate:
   virtual content::BrowserContext* GetBrowserContextByIndex(
       MultiProfileIndex index) OVERRIDE;
+  virtual content::BrowserContext* GetBrowserContextForWindow(
+      aura::Window* window) OVERRIDE;
   virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE;
   virtual int NumberOfLoggedInUsers() const OVERRIDE;
   virtual bool IsActiveUserSessionStarted() const OVERRIDE;
@@ -75,6 +77,9 @@
   // running now.
   void SetUserAddingScreenRunning(bool user_adding_screen_running);
 
+  // Setting non NULL image enables avatar icon.
+  void SetUserImage(const gfx::ImageSkia& user_image);
+
  private:
   // Whether a session is in progress and there is an active user.
   bool has_active_user_;
@@ -104,7 +109,7 @@
   std::string activated_user_;
 
   // A test user image.
-  gfx::ImageSkia null_image_;
+  gfx::ImageSkia user_image_;
 
   DISALLOW_COPY_AND_ASSIGN(TestSessionStateDelegate);
 };
diff --git a/ash/test/test_shell_delegate.cc b/ash/test/test_shell_delegate.cc
index 57c76cc..fe981d7 100644
--- a/ash/test/test_shell_delegate.cc
+++ b/ash/test/test_shell_delegate.cc
@@ -80,7 +80,7 @@
 void TestShellDelegate::PreInit() {
 }
 
-void TestShellDelegate::Shutdown() {
+void TestShellDelegate::PreShutdown() {
 }
 
 void TestShellDelegate::Exit() {
diff --git a/ash/test/test_shell_delegate.h b/ash/test/test_shell_delegate.h
index a41d1bb..9e610b6 100644
--- a/ash/test/test_shell_delegate.h
+++ b/ash/test/test_shell_delegate.h
@@ -35,7 +35,7 @@
   virtual bool IsMultiProfilesEnabled() const OVERRIDE;
   virtual bool IsRunningInForcedAppMode() const OVERRIDE;
   virtual void PreInit() OVERRIDE;
-  virtual void Shutdown() OVERRIDE;
+  virtual void PreShutdown() OVERRIDE;
   virtual void Exit() OVERRIDE;
   virtual keyboard::KeyboardControllerProxy*
       CreateKeyboardControllerProxy() OVERRIDE;
diff --git a/ash/tooltips/tooltip_controller_unittest.cc b/ash/tooltips/tooltip_controller_unittest.cc
index 64e69dd..b41a99c 100644
--- a/ash/tooltips/tooltip_controller_unittest.cc
+++ b/ash/tooltips/tooltip_controller_unittest.cc
@@ -5,7 +5,6 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "base/strings/utf_string_conversions.h"
-#include "ui/aura/client/tooltip_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/window.h"
@@ -17,6 +16,7 @@
 #include "ui/views/corewm/tooltip_controller_test_helper.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/tooltip_client.h"
 
 using views::corewm::TooltipController;
 using views::corewm::test::TooltipTestView;
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc
index 4911483..354e99e 100644
--- a/ash/wm/default_state.cc
+++ b/ash/wm/default_state.cc
@@ -31,7 +31,7 @@
 
 bool IsPanel(aura::Window* window) {
   return window->parent() &&
-      window->parent()->id() == internal::kShellWindowId_DockedContainer;
+      window->parent()->id() == internal::kShellWindowId_PanelContainer;
 }
 
 void MoveToDisplayForRestore(WindowState* window_state) {
@@ -128,87 +128,30 @@
     return;
   }
 
-  if (current != next_state_type) {
-    state_type_ = next_state_type;
-    window_state->UpdateWindowShowStateFromStateType();
-    window_state->NotifyPreStateTypeChange(current);
-    // TODO(oshima): Make docked window a state.
-    if (window_state->IsSnapped() ||
-        (!window_state->IsDocked() && !IsPanel(window_state->window()))) {
-      UpdateBounds(window_state, current);
-    }
-    window_state->NotifyPostStateTypeChange(current);
-  }
+  EnterToNextState(window_state, next_state_type);
 }
 
 WindowStateType DefaultState::GetType() const {
   return state_type_;
 }
 
-void DefaultState::AttachState(WindowState* window_state,
-                               WindowState::State* previous_state) {
+void DefaultState::AttachState(
+    WindowState* window_state,
+    WindowState::State* state_in_previous_mode) {
   DCHECK_EQ(stored_window_state_, window_state);
-  WindowStateType old_state_type = state_type_;
-  state_type_ = previous_state->GetType();
 
-  // Forget our restore sizes when the workspace size has changed.
-  bool workspace_unchanged = stored_workspace_size_ ==
-      window_state->window()->parent()->bounds().size();
+  ReenterToCurrentState(window_state, state_in_previous_mode);
 
-  // Set the restore bounds to be the previous bounds - this might be required
-  // for some state transitions like restore, so that the animations are sound.
-  if (!stored_bounds_.IsEmpty() && workspace_unchanged)
-    window_state->SetRestoreBoundsInParent(stored_bounds_);
-  else
-    window_state->ClearRestoreBounds();
-
-  if (old_state_type != state_type_) {
-    wm::WMEventType type = wm::WM_EVENT_NORMAL;
-    switch (old_state_type) {
-      case wm::WINDOW_STATE_TYPE_DEFAULT:
-      case wm::WINDOW_STATE_TYPE_AUTO_POSITIONED:
-      case wm::WINDOW_STATE_TYPE_NORMAL:
-      case wm::WINDOW_STATE_TYPE_DETACHED:
-      case wm::WINDOW_STATE_TYPE_END:
-        break;
-      case wm::WINDOW_STATE_TYPE_MINIMIZED:
-        type = wm::WM_EVENT_MINIMIZE;
-        break;
-      case wm::WINDOW_STATE_TYPE_MAXIMIZED:
-        type = wm::WM_EVENT_MAXIMIZE;
-        break;
-      case wm::WINDOW_STATE_TYPE_INACTIVE:
-        type = wm::WM_EVENT_SHOW_INACTIVE;
-        break;
-      case wm::WINDOW_STATE_TYPE_FULLSCREEN:
-        type = wm::WM_EVENT_TOGGLE_FULLSCREEN;
-        break;
-      case wm::WINDOW_STATE_TYPE_LEFT_SNAPPED:
-        type = wm::WM_EVENT_SNAP_LEFT;
-        break;
-      case wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED:
-        type = wm::WM_EVENT_SNAP_RIGHT;
-        break;
-    }
-    wm::WMEvent event(type);
+  // If the display has changed while in the another mode,
+  // we need to let windows know the change.
+  gfx::Display current_display = Shell::GetScreen()->
+      GetDisplayNearestWindow(window_state->window());
+  if (stored_display_state_.bounds() != current_display.bounds()) {
+    const WMEvent event(wm::WM_EVENT_DISPLAY_BOUNDS_CHANGED);
     window_state->OnWMEvent(&event);
-  }
-
-  if (workspace_unchanged) {
-    // If the bounds are not yet set and valid we restore them.
-    if (!stored_bounds_.IsEmpty() &&
-        stored_bounds_ != window_state->window()->bounds()) {
-      if (state_type_ == wm::WINDOW_STATE_TYPE_MINIMIZED)
-        window_state->SetBoundsDirect(stored_bounds_);
-      else
-        window_state->SetBoundsDirectAnimated(stored_bounds_);
-    }
-
-    // Then restore the restore bounds to their previous value.
-    if (!stored_restore_bounds_.IsEmpty())
-      window_state->SetRestoreBoundsInParent(stored_restore_bounds_);
-    else
-      window_state->ClearRestoreBounds();
+  } else if (stored_display_state_.work_area() != current_display.work_area()) {
+    const WMEvent event(wm::WM_EVENT_WORKAREA_BOUNDS_CHANGED);
+    window_state->OnWMEvent(&event);
   }
 }
 
@@ -218,10 +161,12 @@
   stored_bounds_ = window->bounds();
   stored_restore_bounds_ = window_state->HasRestoreBounds() ?
       window_state->GetRestoreBoundsInParent() : gfx::Rect();
-  // If the container size for this window has changed we need to restore the
-  // proper location of the window within the container. Note that this might
-  // not be the same as the screen resolution.
-  stored_workspace_size_ = window_state->window()->parent()->bounds().size();
+  // Remember the display state so that in case of the display change
+  // while in the other mode, we can perform necessary action to
+  // restore the window state to the proper state for the current
+  // display.
+  stored_display_state_ = Shell::GetScreen()->
+      GetDisplayNearestWindow(window_state->window());
 }
 
 // static
@@ -439,44 +384,125 @@
 }
 
 // static
-void DefaultState::UpdateBounds(WindowState* window_state,
-                                WindowStateType old_state_type) {
-  aura::Window* window = window_state->window();
-  // Do nothing If this is not yet added to the container.
-  if (!window->parent())
+bool DefaultState::SetMaximizedOrFullscreenBounds(WindowState* window_state) {
+  DCHECK(!window_state->is_dragged());
+  if (window_state->IsMaximized()) {
+    window_state->SetBoundsDirect(
+        ScreenUtil::GetMaximizedWindowBoundsInParent(window_state->window()));
+    return true;
+  }
+  if (window_state->IsFullscreen()) {
+    window_state->SetBoundsDirect(
+        ScreenUtil::GetDisplayBoundsInParent(window_state->window()));
+    return true;
+  }
+  return false;
+}
+
+// static
+void DefaultState::SetBounds(WindowState* window_state,
+                             const SetBoundsEvent* event) {
+  if (window_state->is_dragged()) {
+    window_state->SetBoundsDirect(event->requested_bounds());
+  } else if (window_state->IsSnapped()) {
+    gfx::Rect work_area_in_parent =
+        ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_state->window());
+    gfx::Rect child_bounds(event->requested_bounds());
+    AdjustBoundsSmallerThan(work_area_in_parent.size(), &child_bounds);
+    window_state->AdjustSnappedBounds(&child_bounds);
+    window_state->SetBoundsDirect(child_bounds);
+  } else if (!SetMaximizedOrFullscreenBounds(window_state)) {
+    window_state->SetBoundsConstrained(event->requested_bounds());
+  }
+}
+
+void DefaultState::EnterToNextState(WindowState* window_state,
+                                    WindowStateType next_state_type) {
+  // Do nothing if  we're already in the same state.
+  if (state_type_ == next_state_type)
     return;
 
-  if (!window_state->HasRestoreBounds() &&
-      (old_state_type == WINDOW_STATE_TYPE_DEFAULT ||
-       old_state_type == WINDOW_STATE_TYPE_NORMAL) &&
-      !window_state->IsMinimized() &&
-      !window_state->IsNormalStateType()) {
-    window_state->SaveCurrentBoundsForRestore();
+  WindowStateType previous_state_type = state_type_;
+  state_type_ = next_state_type;
+
+  window_state->UpdateWindowShowStateFromStateType();
+  window_state->NotifyPreStateTypeChange(previous_state_type);
+
+  // This Docked/Snapped hack is due to the issue that IsDocked returns
+  // true for dragging window.  TODO(oshima): Make docked window a state
+  // and remove this hack.
+  if (window_state->window()->parent() &&
+      (window_state->IsSnapped() ||
+       (!window_state->IsDocked() && !IsPanel(window_state->window())))) {
+    if (!window_state->HasRestoreBounds() &&
+        (previous_state_type == WINDOW_STATE_TYPE_DEFAULT ||
+         previous_state_type == WINDOW_STATE_TYPE_NORMAL) &&
+        !window_state->IsMinimized() &&
+        !window_state->IsNormalStateType()) {
+      window_state->SaveCurrentBoundsForRestore();
+    }
+
+    // When restoring from a minimized state, we want to restore to the previous
+    // bounds. However, we want to maintain the restore bounds. (The restore
+    // bounds are set if a user maximized the window in one axis by double
+    // clicking the window border for example).
+    gfx::Rect restore_bounds_in_screen;
+    if (previous_state_type == WINDOW_STATE_TYPE_MINIMIZED &&
+        window_state->IsNormalStateType() &&
+        window_state->HasRestoreBounds() &&
+        !window_state->unminimize_to_restore_bounds()) {
+      restore_bounds_in_screen = window_state->GetRestoreBoundsInScreen();
+      window_state->SaveCurrentBoundsForRestore();
+    }
+
+    if (window_state->IsMaximizedOrFullscreen())
+      MoveToDisplayForRestore(window_state);
+
+    UpdateBoundsFromState(window_state, previous_state_type);
+
+    // Normal state should have no restore bounds unless it's
+    // unminimzied.
+    if (!restore_bounds_in_screen.IsEmpty())
+      window_state->SetRestoreBoundsInScreen(restore_bounds_in_screen);
+    else if (window_state->IsNormalStateType())
+      window_state->ClearRestoreBounds();
+  }
+  window_state->NotifyPostStateTypeChange(previous_state_type);
+}
+
+void DefaultState::ReenterToCurrentState(
+    WindowState* window_state,
+    WindowState::State* state_in_previous_mode) {
+  WindowStateType previous_state_type = state_in_previous_mode->GetType();
+  window_state->UpdateWindowShowStateFromStateType();
+  window_state->NotifyPreStateTypeChange(previous_state_type);
+
+  if (state_type_ == wm::WINDOW_STATE_TYPE_NORMAL ||
+      state_type_ == wm::WINDOW_STATE_TYPE_DEFAULT) {
+    // Use the restore mechanism to set the bounds for
+    // the window in normal state. This also covers unminimize case.
+    window_state->SetRestoreBoundsInParent(stored_bounds_);
   }
 
-  // When restoring from a minimized state, we want to restore to the previous
-  // bounds. However, we want to maintain the restore bounds. (The restore
-  // bounds are set if a user maximized the window in one axis by double
-  // clicking the window border for example).
-  gfx::Rect restore_bounds_in_screen;
-  if (old_state_type == WINDOW_STATE_TYPE_MINIMIZED &&
-      window_state->IsNormalStateType() &&
-      window_state->HasRestoreBounds() &&
-      !window_state->unminimize_to_restore_bounds()) {
-    restore_bounds_in_screen = window_state->GetRestoreBoundsInScreen();
-    window_state->SaveCurrentBoundsForRestore();
-  }
+  UpdateBoundsFromState(window_state, state_in_previous_mode->GetType());
 
-  if (window_state->IsMaximizedOrFullscreen())
-    MoveToDisplayForRestore(window_state);
+  // Then restore the restore bounds to their previous value.
+  if (!stored_restore_bounds_.IsEmpty())
+    window_state->SetRestoreBoundsInParent(stored_restore_bounds_);
+  else
+    window_state->ClearRestoreBounds();
 
-  WindowStateType state_type = window_state->GetStateType();
+  window_state->NotifyPostStateTypeChange(previous_state_type);
+}
+
+void DefaultState::UpdateBoundsFromState(WindowState* window_state,
+                                         WindowStateType previous_state_type) {
+  aura::Window* window = window_state->window();
   gfx::Rect bounds_in_parent;
-
-  switch (state_type) {
+  switch (state_type_) {
     case WINDOW_STATE_TYPE_LEFT_SNAPPED:
     case WINDOW_STATE_TYPE_RIGHT_SNAPPED:
-      bounds_in_parent = state_type == WINDOW_STATE_TYPE_LEFT_SNAPPED ?
+      bounds_in_parent = state_type_ == WINDOW_STATE_TYPE_LEFT_SNAPPED ?
           GetDefaultLeftSnappedWindowBoundsInParent(window_state->window()) :
           GetDefaultRightSnappedWindowBoundsInParent(window_state->window());
       break;
@@ -510,12 +536,12 @@
       return;
   }
 
-  if (state_type != WINDOW_STATE_TYPE_MINIMIZED) {
-    if (old_state_type == WINDOW_STATE_TYPE_MINIMIZED ||
+  if (state_type_ != WINDOW_STATE_TYPE_MINIMIZED) {
+    if (previous_state_type == WINDOW_STATE_TYPE_MINIMIZED ||
         window_state->IsFullscreen()) {
       window_state->SetBoundsDirect(bounds_in_parent);
     } else if (window_state->IsMaximized() ||
-               IsMaximizedOrFullscreenWindowStateType(old_state_type)) {
+               IsMaximizedOrFullscreenWindowStateType(previous_state_type)) {
       window_state->SetBoundsDirectCrossFade(bounds_in_parent);
     } else if (window_state->is_dragged()) {
       // SetBoundsDirectAnimated does not work when the window gets reparented.
@@ -529,7 +555,7 @@
   if (window_state->IsMinimized()) {
     // Save the previous show state so that we can correctly restore it.
     window_state->window()->SetProperty(aura::client::kRestoreShowStateKey,
-                                        ToWindowShowState(old_state_type));
+                                        ToWindowShowState(previous_state_type));
     ::wm::SetWindowVisibilityAnimationType(
         window_state->window(), WINDOW_VISIBILITY_ANIMATION_TYPE_MINIMIZE);
 
@@ -539,57 +565,16 @@
     if (window_state->IsActive())
       window_state->Deactivate();
   } else if ((window_state->window()->TargetVisibility() ||
-              old_state_type == WINDOW_STATE_TYPE_MINIMIZED) &&
+              previous_state_type == WINDOW_STATE_TYPE_MINIMIZED) &&
              !window_state->window()->layer()->visible()) {
     // The layer may be hidden if the window was previously minimized. Make
     // sure it's visible.
     window_state->window()->Show();
-    if (old_state_type == WINDOW_STATE_TYPE_MINIMIZED &&
+    if (previous_state_type == WINDOW_STATE_TYPE_MINIMIZED &&
         !window_state->IsMaximizedOrFullscreen()) {
       window_state->set_unminimize_to_restore_bounds(false);
     }
   }
-
-  if (window_state->IsNormalStateType())
-    window_state->ClearRestoreBounds();
-
-  // Set the restore rectangle to the previously set restore rectangle.
-  if (!restore_bounds_in_screen.IsEmpty())
-    window_state->SetRestoreBoundsInScreen(restore_bounds_in_screen);
-}
-
-// static
-bool DefaultState::SetMaximizedOrFullscreenBounds(WindowState* window_state) {
-  DCHECK(!window_state->is_dragged());
-  if (window_state->IsMaximized()) {
-    window_state->SetBoundsDirect(
-        ScreenUtil::GetMaximizedWindowBoundsInParent(window_state->window()));
-    return true;
-  }
-  if (window_state->IsFullscreen()) {
-    window_state->SetBoundsDirect(
-        ScreenUtil::GetDisplayBoundsInParent(window_state->window()));
-    return true;
-  }
-  return false;
-}
-
-// static
-void DefaultState::SetBounds(WindowState* window_state,
-                             const SetBoundsEvent* event) {
-
-  if (window_state->is_dragged()) {
-    window_state->SetBoundsDirect(event->requested_bounds());
-  } else if (window_state->IsSnapped()) {
-    gfx::Rect work_area_in_parent =
-        ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_state->window());
-    gfx::Rect child_bounds(event->requested_bounds());
-    AdjustBoundsSmallerThan(work_area_in_parent.size(), &child_bounds);
-    window_state->AdjustSnappedBounds(&child_bounds);
-    window_state->SetBoundsDirect(child_bounds);
-  } else if (!SetMaximizedOrFullscreenBounds(window_state)) {
-    window_state->SetBoundsConstrained(event->requested_bounds());
-  }
 }
 
 // static
@@ -612,6 +597,8 @@
     center_in_parent.ClampToCenteredSize(window->bounds().size());
     window_state->SetBoundsDirectAnimated(center_in_parent);
   }
+  // Centering window is treated as if a user moved and resized the window.
+  window_state->set_bounds_changed_by_user(true);
 }
 
 }  // namespace wm
diff --git a/ash/wm/default_state.h b/ash/wm/default_state.h
index cfab381..ccee0f8 100644
--- a/ash/wm/default_state.h
+++ b/ash/wm/default_state.h
@@ -6,6 +6,7 @@
 #define ASH_WM_DEFAULT_STATE_H_
 
 #include "ash/wm/window_state.h"
+#include "ui/gfx/display.h"
 
 namespace ash {
 namespace wm {
@@ -35,10 +36,6 @@
   static bool ProcessWorkspaceEvents(WindowState* window_state,
                                      const WMEvent* event);
 
-  // Animates to new window bounds based on the current and previous state type.
-  static void UpdateBounds(wm::WindowState* window_state,
-                           wm::WindowStateType old_state_type);
-
   // Set the fullscreen/maximized bounds without animation.
   static bool SetMaximizedOrFullscreenBounds(wm::WindowState* window_state);
 
@@ -47,6 +44,21 @@
 
   static void CenterWindow(WindowState* window_state);
 
+  // Enters next state. This is used when the state moves from one to another
+  // within the same desktop mode.
+  void EnterToNextState(wm::WindowState* window_state,
+                        wm::WindowStateType next_state_type);
+
+  // Reenters the current state. This is called when migrating from
+  // previous desktop mode, and the window's state needs to re-construct the
+  // state/bounds for this state.
+  void ReenterToCurrentState(wm::WindowState* window_state,
+                             wm::WindowState::State* state_in_previous_mode);
+
+  // Animates to new window bounds based on the current and previous state type.
+  void UpdateBoundsFromState(wm::WindowState* window_state,
+                             wm::WindowStateType old_state_type);
+
   // The current type of the window.
   WindowStateType state_type_;
 
@@ -54,9 +66,8 @@
   gfx::Rect stored_bounds_;
   gfx::Rect stored_restore_bounds_;
 
-  // The size of the workspace when the mode got started. If it differs from
-  // the current values the bounds will get ignored.
-  gfx::Size stored_workspace_size_;
+  // The display state in which the mode got started.
+  gfx::Display stored_display_state_;
 
   // The window state only gets remembered for DCHECK reasons.
   WindowState* stored_window_state_;
diff --git a/ash/wm/dock/docked_window_layout_manager.cc b/ash/wm/dock/docked_window_layout_manager.cc
index 63ad210..04273e1 100644
--- a/ash/wm/dock/docked_window_layout_manager.cc
+++ b/ash/wm/dock/docked_window_layout_manager.cc
@@ -26,7 +26,6 @@
 #include "grit/ash_resources.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkPaint.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/window.h"
@@ -39,6 +38,7 @@
 #include "ui/gfx/rect.h"
 #include "ui/views/background.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace internal {
diff --git a/ash/wm/dock/docked_window_layout_manager.h b/ash/wm/dock/docked_window_layout_manager.h
index 974be11..18569d8 100644
--- a/ash/wm/dock/docked_window_layout_manager.h
+++ b/ash/wm/dock/docked_window_layout_manager.h
@@ -18,12 +18,12 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "base/time/time.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/layout_manager.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/rect.h"
 #include "ui/keyboard/keyboard_controller_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class Window;
diff --git a/ash/wm/drag_details.h b/ash/wm/drag_details.h
index 2d3bed4..d8f7d6e 100644
--- a/ash/wm/drag_details.h
+++ b/ash/wm/drag_details.h
@@ -9,8 +9,8 @@
 #include "ash/wm/wm_types.h"
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/window_move_client.h"
 #include "ui/gfx/rect.h"
+#include "ui/wm/public/window_move_client.h"
 
 namespace aura {
 class Window;
diff --git a/ash/wm/immersive_fullscreen_controller.cc b/ash/wm/immersive_fullscreen_controller.cc
index 976eaae..b8c721c 100644
--- a/ash/wm/immersive_fullscreen_controller.cc
+++ b/ash/wm/immersive_fullscreen_controller.cc
@@ -11,7 +11,6 @@
 #include "ash/wm/resize_handle_window_targeter.h"
 #include "ash/wm/window_state.h"
 #include "base/metrics/histogram.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/cursor_client.h"
@@ -29,6 +28,7 @@
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/transient_window_manager.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 using views::View;
 
@@ -62,6 +62,13 @@
 // See ShouldIgnoreMouseEventAtLocation() for more details.
 const int kHeightOfDeadRegionAboveTopContainer = 10;
 
+// The height in pixels of the region below the top edge of the display in which
+// the mouse can trigger revealing the top-of-window views. The height must be
+// greater than 1px because the top pixel is used to trigger moving the cursor
+// between displays if the user has a vertical display layout (primary display
+// above/below secondary display).
+const int kMouseRevealBoundsHeight = 3;
+
 // Returns the BubbleDelegateView corresponding to |maybe_bubble| if
 // |maybe_bubble| is a bubble.
 views::BubbleDelegateView* AsBubbleDelegate(aura::Window* maybe_bubble) {
@@ -104,20 +111,6 @@
 
 }  // namespace
 
-// The height in pixels of the region below the top edge of the display in which
-// the mouse can trigger revealing the top-of-window views.
-#if defined(OS_WIN)
-// Windows 8 reserves some pixels at the top of the screen for the hand icon
-// that allows you to drag a metro app off the screen, so a few additional
-// pixels of space must be reserved for the mouse reveal.
-const int ImmersiveFullscreenController::kMouseRevealBoundsHeight = 9;
-#else
-// The height must be greater than 1px because the top pixel is used to trigger
-// moving the cursor between displays if the user has a vertical display layout
-// (primary display above/below secondary display).
-const int ImmersiveFullscreenController::kMouseRevealBoundsHeight = 3;
-#endif
-
 ////////////////////////////////////////////////////////////////////////////////
 
 // Class which keeps the top-of-window views revealed as long as one of the
@@ -404,12 +397,6 @@
     return;
 
   switch (event->type()) {
-#if defined(OS_WIN)
-    case ui::ET_GESTURE_WIN8_EDGE_SWIPE:
-      UpdateRevealedLocksForSwipe(GetSwipeType(event));
-      event->SetHandled();
-      break;
-#endif
     case ui::ET_GESTURE_SCROLL_BEGIN:
       if (ShouldHandleGestureEvent(GetEventLocationInScreen(*event))) {
         gesture_begun_ = true;
@@ -863,10 +850,6 @@
 
 ImmersiveFullscreenController::SwipeType
 ImmersiveFullscreenController::GetSwipeType(ui::GestureEvent* event) const {
-#if defined(OS_WIN)
-  if (event->type() == ui::ET_GESTURE_WIN8_EDGE_SWIPE)
-    return SWIPE_OPEN;
-#endif
   if (event->type() != ui::ET_GESTURE_SCROLL_UPDATE)
     return SWIPE_NONE;
   // Make sure that it is a clear vertical gesture.
diff --git a/ash/wm/immersive_fullscreen_controller.h b/ash/wm/immersive_fullscreen_controller.h
index 4f0b20b..b98b32f 100644
--- a/ash/wm/immersive_fullscreen_controller.h
+++ b/ash/wm/immersive_fullscreen_controller.h
@@ -46,8 +46,6 @@
       public views::WidgetObserver,
       public ImmersiveRevealedLock::Delegate {
  public:
-  static const int kMouseRevealBoundsHeight;
-
   // The enum is used for an enumerated histogram. New items should be only
   // added to the end.
   enum WindowType {
diff --git a/ash/wm/immersive_fullscreen_controller_unittest.cc b/ash/wm/immersive_fullscreen_controller_unittest.cc
index ca21e23..4693ef5 100644
--- a/ash/wm/immersive_fullscreen_controller_unittest.cc
+++ b/ash/wm/immersive_fullscreen_controller_unittest.cc
@@ -25,6 +25,9 @@
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 
+// For now, immersive fullscreen is Chrome OS only.
+#if defined(OS_CHROMEOS)
+
 namespace ash {
 
 namespace {
@@ -343,6 +346,12 @@
 // Test mouse event processing for top-of-screen reveal triggering.
 TEST_F(ImmersiveFullscreenControllerTest, OnMouseEvent) {
   // Set up initial state.
+  UpdateDisplay("800x600,800x600");
+  ash::DisplayLayout display_layout(ash::DisplayLayout::RIGHT, 0);
+  ash::Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
+      display_layout);
+
+  // Set up initial state.
   SetEnabled(true);
   ASSERT_TRUE(controller()->IsEnabled());
   ASSERT_FALSE(controller()->IsRevealed());
@@ -369,8 +378,7 @@
 
   // Moving |ImmersiveFullscreenControllerTest::kMouseRevealBoundsHeight| down
   // from the top edge stops it.
-  event_generator.MoveMouseBy(0,
-      ImmersiveFullscreenController::kMouseRevealBoundsHeight);
+  event_generator.MoveMouseBy(0, 3);
   EXPECT_FALSE(top_edge_hover_timer_running());
 
   // Moving back to the top starts the timer again.
@@ -671,16 +679,7 @@
 }
 
 // Test when the SWIPE_CLOSE edge gesture closes the top-of-window views.
-#if defined(OS_WIN)
-// On Windows, touch events do not result in mouse events being disabled.  As
-// a result, the last part of this test which ends the reveal via a gesture will
-// not work correctly.  See crbug.com/332430, and the function
-// ShouldHideCursorOnTouch() in compound_event_filter.cc.
-#define MAYBE_EndRevealViaGesture DISABLED_EndRevealViaGesture
-#else
-#define MAYBE_EndRevealViaGesture EndRevealViaGesture
-#endif
-TEST_F(ImmersiveFullscreenControllerTest, MAYBE_EndRevealViaGesture) {
+TEST_F(ImmersiveFullscreenControllerTest, EndRevealViaGesture) {
   SetEnabled(true);
   EXPECT_TRUE(controller()->IsEnabled());
   EXPECT_FALSE(controller()->IsRevealed());
@@ -1055,3 +1054,5 @@
 }
 
 }  // namespase ash
+
+#endif  // defined(OS_CHROMEOS)
diff --git a/ash/wm/lock_state_controller_unittest.cc b/ash/wm/lock_state_controller_unittest.cc
index fd49ef1..b950fe1 100644
--- a/ash/wm/lock_state_controller_unittest.cc
+++ b/ash/wm/lock_state_controller_unittest.cc
@@ -25,7 +25,7 @@
 #include "ui/gfx/rect.h"
 #include "ui/gfx/size.h"
 
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
 #include "ui/display/chromeos/output_configurator.h"
 #include "ui/display/chromeos/test/test_display_snapshot.h"
 #include "ui/display/display_constants.h"
diff --git a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc
index f2ee161..82b07d7 100644
--- a/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc
+++ b/ash/wm/maximize_mode/maximize_mode_window_manager_unittest.cc
@@ -65,11 +65,10 @@
 
   // Resize our desktop.
   void ResizeDesktop(int width_delta) {
-    aura::Window* container = Shell::GetContainer(
-        Shell::GetPrimaryRootWindow(), kSwitchableWindowContainerIds[0]);
-    gfx::Rect bounds = container->bounds();
-    bounds.set_width(bounds.width() - width_delta);
-    container->SetBounds(bounds);
+    gfx::Size size = Shell::GetScreen()->GetDisplayNearestWindow(
+        Shell::GetPrimaryRootWindow()).size();
+    size.Enlarge(0, width_delta);
+    UpdateDisplay(size.ToString());
   }
 
  private:
@@ -356,31 +355,39 @@
 // Check that resizing the desktop does reposition unmaximizable & managed
 // windows.
 TEST_F(MaximizeModeWindowManagerTest, DesktopSizeChangeMovesUnmaximizable) {
-  gfx::Rect rect(20, 140, 100, 100);
-  scoped_ptr<aura::Window> window(
+  UpdateDisplay("400x400");
+  // This window will move because it does not fit the new bounds.
+  gfx::Rect rect(20, 300, 100, 100);
+  scoped_ptr<aura::Window> window1(
       CreateNonMaximizableWindow(ui::wm::WINDOW_TYPE_NORMAL, rect));
-  EXPECT_EQ(rect.ToString(), window->bounds().ToString());
+  EXPECT_EQ(rect.ToString(), window1->bounds().ToString());
+
+  // This window will not move because it does fit the new bounds.
+  gfx::Rect rect2(20, 140, 100, 100);
+  scoped_ptr<aura::Window> window2(
+      CreateNonMaximizableWindow(ui::wm::WINDOW_TYPE_NORMAL, rect2));
 
   // Turning on the manager will reposition (but not resize) the window.
   ash::internal::MaximizeModeWindowManager* manager =
       CreateMaximizeModeWindowManager();
   ASSERT_TRUE(manager);
-  EXPECT_EQ(1, manager->GetNumberOfManagedWindows());
-  gfx::Rect moved_bounds(window->bounds());
+  EXPECT_EQ(2, manager->GetNumberOfManagedWindows());
+  gfx::Rect moved_bounds(window1->bounds());
   EXPECT_NE(rect.origin().ToString(), moved_bounds.origin().ToString());
   EXPECT_EQ(rect.size().ToString(), moved_bounds.size().ToString());
 
   // Simulating a desktop resize should move the window again.
-  ResizeDesktop(-10);
-  gfx::Rect new_moved_bounds(window->bounds());
+  UpdateDisplay("300x300");
+  gfx::Rect new_moved_bounds(window1->bounds());
   EXPECT_NE(rect.origin().ToString(), new_moved_bounds.origin().ToString());
   EXPECT_EQ(rect.size().ToString(), new_moved_bounds.size().ToString());
   EXPECT_NE(moved_bounds.origin().ToString(), new_moved_bounds.ToString());
 
   // Turning off the mode should not restore to the initial coordinates since
-  // the new resolution is different.
+  // the new resolution is smaller and the window was on the edge.
   DestroyMaximizeModeWindowManager();
-  EXPECT_NE(rect.ToString(), window->bounds().ToString());
+  EXPECT_NE(rect.ToString(), window1->bounds().ToString());
+  EXPECT_EQ(rect2.ToString(), window2->bounds().ToString());
 }
 
 // Check that windows return to original location if desktop size changes to
diff --git a/ash/wm/mru_window_tracker.cc b/ash/wm/mru_window_tracker.cc
index 8e211b3..419fed5 100644
--- a/ash/wm/mru_window_tracker.cc
+++ b/ash/wm/mru_window_tracker.cc
@@ -13,10 +13,10 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace_controller.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 
diff --git a/ash/wm/mru_window_tracker.h b/ash/wm/mru_window_tracker.h
index 2c2a5ea..78a42c3 100644
--- a/ash/wm/mru_window_tracker.h
+++ b/ash/wm/mru_window_tracker.h
@@ -11,8 +11,8 @@
 #include "ash/ash_export.h"
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class RootWindow;
diff --git a/ash/wm/overview/window_selector.cc b/ash/wm/overview/window_selector.cc
index c36be04..15bdf3f 100644
--- a/ash/wm/overview/window_selector.cc
+++ b/ash/wm/overview/window_selector.cc
@@ -19,7 +19,6 @@
 #include "base/command_line.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -27,6 +26,7 @@
 #include "ui/events/event.h"
 #include "ui/events/event_handler.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 
diff --git a/ash/wm/overview/window_selector.h b/ash/wm/overview/window_selector.h
index d54e7ee..d34c901 100644
--- a/ash/wm/overview/window_selector.h
+++ b/ash/wm/overview/window_selector.h
@@ -13,8 +13,8 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/time/time.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class RootWindow;
diff --git a/ash/wm/overview/window_selector_unittest.cc b/ash/wm/overview/window_selector_unittest.cc
index d3edb7a..f78bcbf 100644
--- a/ash/wm/overview/window_selector_unittest.cc
+++ b/ash/wm/overview/window_selector_unittest.cc
@@ -24,7 +24,6 @@
 #include "base/memory/scoped_vector.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
-#include "ui/aura/client/activation_delegate.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/focus_client.h"
@@ -37,6 +36,7 @@
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/transform.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace ash {
 namespace internal {
diff --git a/ash/wm/panels/panel_layout_manager.cc b/ash/wm/panels/panel_layout_manager.cc
index 64b04c0..95db257 100644
--- a/ash/wm/panels/panel_layout_manager.cc
+++ b/ash/wm/panels/panel_layout_manager.cc
@@ -23,7 +23,6 @@
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/window.h"
@@ -35,6 +34,7 @@
 #include "ui/gfx/vector2d.h"
 #include "ui/views/background.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace internal {
@@ -371,7 +371,6 @@
     panel_info.slide_in = true;
   }
   panel_windows_.push_back(panel_info);
-  child->AddObserver(this);
   wm::GetWindowState(child)->AddObserver(this);
   Relayout();
 }
@@ -388,7 +387,6 @@
     delete found->callout_widget;
     panel_windows_.erase(found);
   }
-  child->RemoveObserver(this);
   wm::GetWindowState(child)->RemoveObserver(this);
 
   if (dragged_panel_ == child)
@@ -402,6 +400,8 @@
 
 void PanelLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
                                                         bool visible) {
+  if (visible)
+    wm::GetWindowState(child)->Restore();
   Relayout();
 }
 
@@ -481,12 +481,6 @@
     RestorePanel(window_state->window());
 }
 
-void PanelLayoutManager::OnWindowVisibilityChanged(
-    aura::Window* window, bool visible) {
-  if (visible)
-    wm::GetWindowState(window)->Restore();
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // PanelLayoutManager, aura::client::ActivationChangeObserver implementation:
 
diff --git a/ash/wm/panels/panel_layout_manager.h b/ash/wm/panels/panel_layout_manager.h
index aff6d58..2d17b2d 100644
--- a/ash/wm/panels/panel_layout_manager.h
+++ b/ash/wm/panels/panel_layout_manager.h
@@ -17,11 +17,10 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/layout_manager.h"
-#include "ui/aura/window_observer.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_controller_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class Window;
@@ -56,7 +55,6 @@
     : public aura::LayoutManager,
       public ShelfIconObserver,
       public ShellObserver,
-      public aura::WindowObserver,
       public aura::client::ActivationChangeObserver,
       public keyboard::KeyboardControllerObserver,
       public DisplayController::Observer,
@@ -101,10 +99,6 @@
       wm::WindowState* window_state,
       wm::WindowStateType old_type) OVERRIDE;
 
-  // Overridden from aura::WindowObserver
-  virtual void OnWindowVisibilityChanged(aura::Window* window,
-                                         bool visible) OVERRIDE;
-
   // Overridden from aura::client::ActivationChangeObserver
   virtual void OnWindowActivated(aura::Window* gained_active,
                                  aura::Window* lost_active) OVERRIDE;
diff --git a/ash/wm/power_button_controller.cc b/ash/wm/power_button_controller.cc
index c2d63f9..a380392 100644
--- a/ash/wm/power_button_controller.cc
+++ b/ash/wm/power_button_controller.cc
@@ -27,13 +27,13 @@
           CommandLine::ForCurrentProcess()->HasSwitch(
               switches::kAuraLegacyPowerButton)),
       controller_(controller) {
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   Shell::GetInstance()->output_configurator()->AddObserver(this);
 #endif
 }
 
 PowerButtonController::~PowerButtonController() {
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   Shell::GetInstance()->output_configurator()->RemoveObserver(this);
 #endif
 }
@@ -116,7 +116,7 @@
     controller_->CancelLockAnimation();
 }
 
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
 void PowerButtonController::OnDisplayModeChanged(
     const ui::OutputConfigurator::DisplayStateList& outputs) {
   bool internal_display_off = false;
diff --git a/ash/wm/power_button_controller.h b/ash/wm/power_button_controller.h
index f2ab809..d32b3ab 100644
--- a/ash/wm/power_button_controller.h
+++ b/ash/wm/power_button_controller.h
@@ -9,7 +9,7 @@
 #include "ash/wm/session_state_animator.h"
 #include "base/basictypes.h"
 
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
 #include "ui/display/chromeos/output_configurator.h"
 #endif
 
@@ -35,7 +35,7 @@
 class ASH_EXPORT PowerButtonController
 // TODO(derat): Remove these ifdefs after OutputConfigurator becomes
 // cross-platform.
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
     : public ui::OutputConfigurator::Observer
 #endif
       {
@@ -54,7 +54,7 @@
   void OnPowerButtonEvent(bool down, const base::TimeTicks& timestamp);
   void OnLockButtonEvent(bool down, const base::TimeTicks& timestamp);
 
-#if defined(OS_CHROMEOS) && defined(USE_X11)
+#if defined(OS_CHROMEOS)
   // Overriden from ui::OutputConfigurator::Observer:
   virtual void OnDisplayModeChanged(
       const ui::OutputConfigurator::DisplayStateList& outputs) OVERRIDE;
diff --git a/ash/wm/system_gesture_event_filter.cc b/ash/wm/system_gesture_event_filter.cc
index 2499726..1c31832 100644
--- a/ash/wm/system_gesture_event_filter.cc
+++ b/ash/wm/system_gesture_event_filter.cc
@@ -65,9 +65,7 @@
 
   if (event->type() == ui::ET_GESTURE_WIN8_EDGE_SWIPE &&
       shelf_gesture_handler_->ProcessGestureEvent(*event)) {
-    // Do not stop propagation, since the immersive fullscreen controller may
-    // need to handle this event.
-    return;
+    event->StopPropagation();
   }
 }
 
diff --git a/ash/wm/toplevel_window_event_handler.h b/ash/wm/toplevel_window_event_handler.h
index 4998f4b..5d9caf8 100644
--- a/ash/wm/toplevel_window_event_handler.h
+++ b/ash/wm/toplevel_window_event_handler.h
@@ -13,10 +13,10 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/window_move_client.h"
 #include "ui/events/event_handler.h"
 #include "ui/gfx/point.h"
 #include "ui/gfx/rect.h"
+#include "ui/wm/public/window_move_client.h"
 
 namespace aura {
 class Window;
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc
index 437a519..a387067 100644
--- a/ash/wm/toplevel_window_event_handler_unittest.cc
+++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -18,7 +18,6 @@
 #include "base/compiler_specific.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/window_move_client.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/test/test_window_delegate.h"
@@ -27,6 +26,7 @@
 #include "ui/events/event.h"
 #include "ui/gfx/screen.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/window_move_client.h"
 
 #if defined(OS_WIN)
 // Windows headers define macros for these function names which screw with us.
diff --git a/ash/wm/window_animations.cc b/ash/wm/window_animations.cc
index e69b94b..109aa1b 100644
--- a/ash/wm/window_animations.cc
+++ b/ash/wm/window_animations.cc
@@ -304,7 +304,8 @@
     // Triggers OnImplicitAnimationsCompleted() to be called and deletes us.
     layer_owner_->root()->GetAnimator()->StopAnimating();
   }
-  virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
+  virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
+                                              aura::Window* new_root) OVERRIDE {
     layer_owner_->root()->GetAnimator()->StopAnimating();
   }
 
diff --git a/ash/wm/window_manager_unittest.cc b/ash/wm/window_manager_unittest.cc
index b940474..92d2fdf 100644
--- a/ash/wm/window_manager_unittest.cc
+++ b/ash/wm/window_manager_unittest.cc
@@ -8,8 +8,6 @@
 #include "ash/test/shell_test_api.h"
 #include "ash/test/test_activation_delegate.h"
 #include "ash/wm/window_util.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/activation_delegate.h"
 #include "ui/aura/client/cursor_client_observer.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/env.h"
@@ -26,6 +24,8 @@
 #include "ui/gfx/screen.h"
 #include "ui/wm/core/compound_event_filter.h"
 #include "ui/wm/core/input_method_event_filter.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace {
 
diff --git a/ash/wm/window_resizer.h b/ash/wm/window_resizer.h
index 278d199..21cfd52 100644
--- a/ash/wm/window_resizer.h
+++ b/ash/wm/window_resizer.h
@@ -10,8 +10,8 @@
 #include "ash/wm/window_state.h"
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/window_move_client.h"
 #include "ui/gfx/rect.h"
+#include "ui/wm/public/window_move_client.h"
 
 namespace aura {
 class Window;
diff --git a/ash/wm/window_util.cc b/ash/wm/window_util.cc
index e3263a0..906c885 100644
--- a/ash/wm/window_util.cc
+++ b/ash/wm/window_util.cc
@@ -12,7 +12,6 @@
 #include "ash/wm/window_properties.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -24,6 +23,7 @@
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace wm {
diff --git a/ash/wm/window_util_unittest.cc b/ash/wm/window_util_unittest.cc
index 5445793..9c10cf1 100644
--- a/ash/wm/window_util_unittest.cc
+++ b/ash/wm/window_util_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "ash/screen_util.h"
 #include "ash/test/ash_test_base.h"
+#include "ash/wm/window_state.h"
 #include "ui/aura/window.h"
 
 namespace ash {
@@ -29,7 +30,13 @@
   UpdateDisplay("500x400, 600x400");
   scoped_ptr<aura::Window> window(
       CreateTestWindowInShellWithBounds(gfx::Rect(12, 20, 100, 100)));
+
+  wm::WindowState* window_state = wm::GetWindowState(window.get());
+  EXPECT_FALSE(window_state->bounds_changed_by_user());
+
   wm::CenterWindow(window.get());
+  // Centring window is considered as a user's action.
+  EXPECT_TRUE(window_state->bounds_changed_by_user());
   EXPECT_EQ("200,126 100x100", window->bounds().ToString());
   EXPECT_EQ("200,126 100x100", window->GetBoundsInScreen().ToString());
   window->SetBoundsInScreen(gfx::Rect(600, 0, 100, 100),
diff --git a/ash/wm/workspace/workspace_event_handler_unittest.cc b/ash/wm/workspace/workspace_event_handler_unittest.cc
index de17d09..f02830a 100644
--- a/ash/wm/workspace/workspace_event_handler_unittest.cc
+++ b/ash/wm/workspace/workspace_event_handler_unittest.cc
@@ -13,7 +13,6 @@
 #include "ash/wm/workspace_controller.h"
 #include "ash/wm/workspace_controller_test_helper.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/window_move_client.h"
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
@@ -22,6 +21,7 @@
 #include "ui/events/event_processor.h"
 #include "ui/gfx/screen.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/window_move_client.h"
 
 #if defined(OS_WIN)
 #include "base/win/windows_version.h"
diff --git a/ash/wm/workspace/workspace_layout_manager.cc b/ash/wm/workspace/workspace_layout_manager.cc
index d812be6..1b4b4af 100644
--- a/ash/wm/workspace/workspace_layout_manager.cc
+++ b/ash/wm/workspace/workspace_layout_manager.cc
@@ -18,7 +18,6 @@
 #include "ash/wm/window_util.h"
 #include "ash/wm/wm_event.h"
 #include "ash/wm/workspace/workspace_layout_manager_delegate.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
@@ -27,6 +26,7 @@
 #include "ui/events/event.h"
 #include "ui/gfx/screen.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 using aura::Window;
 
diff --git a/ash/wm/workspace/workspace_layout_manager.h b/ash/wm/workspace/workspace_layout_manager.h
index ff15728..970f5e4 100644
--- a/ash/wm/workspace/workspace_layout_manager.h
+++ b/ash/wm/workspace/workspace_layout_manager.h
@@ -14,10 +14,10 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/layout_manager.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/rect.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class RootWindow;
diff --git a/ash/wm/workspace_controller.cc b/ash/wm/workspace_controller.cc
index d7cb7aa..96735be 100644
--- a/ash/wm/workspace_controller.cc
+++ b/ash/wm/workspace_controller.cc
@@ -14,7 +14,6 @@
 #include "ash/wm/workspace/workspace_event_handler.h"
 #include "ash/wm/workspace/workspace_layout_manager.h"
 #include "ash/wm/workspace/workspace_layout_manager_delegate.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -22,6 +21,7 @@
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/wm/core/visibility_controller.h"
 #include "ui/wm/core/window_animations.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace internal {
diff --git a/base/BUILD.gn b/base/BUILD.gn
index d07e10b..7aa8659 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/config/ui.gni")
 
 component("base") {
-  external = true
   sources = [
     "../build/build_config.h",
     "third_party/dmg_fp/dmg_fp.h",
@@ -272,15 +271,14 @@
     "memory/discardable_memory_allocator_android.cc",
     "memory/discardable_memory_allocator_android.h",
     "memory/discardable_memory_android.cc",
-    "memory/discardable_memory_android.h",
     "memory/discardable_memory_emulated.cc",
     "memory/discardable_memory_emulated.h",
     "memory/discardable_memory_linux.cc",
     "memory/discardable_memory_mac.cc",
     "memory/discardable_memory_malloc.cc",
     "memory/discardable_memory_malloc.h",
-    "memory/discardable_memory_provider.cc",
-    "memory/discardable_memory_provider.h",
+    "memory/discardable_memory_manager.cc",
+    "memory/discardable_memory_manager.h",
     "memory/discardable_memory_win.cc",
     "memory/linked_ptr.h",
     "memory/manual_constructor.h",
@@ -843,7 +841,6 @@
 # library. Note that this library cannot depend on base because base depends on
 # base_static.
 static_library("base_static") {
-  external = true
   sources = [
     "base_switches.cc",
     "base_switches.h",
@@ -853,7 +850,6 @@
 }
 
 component("base_i18n") {
-  external = true
   sources = [
     "i18n/base_i18n_export.h",
     "i18n/bidi_line_iterator.cc",
diff --git a/base/allocator/BUILD.gn b/base/allocator/BUILD.gn
index 64d052d..6766911 100644
--- a/base/allocator/BUILD.gn
+++ b/base/allocator/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 static_library("allocator_extension_thunks") {
-  external = true
   sources = [
     "allocator_extension_thunks.cc",
     "allocator_extension_thunks.h",
diff --git a/base/allocator/allocator.gyp b/base/allocator/allocator.gyp
index 4d95906..632e072 100644
--- a/base/allocator/allocator.gyp
+++ b/base/allocator/allocator.gyp
@@ -408,11 +408,6 @@
               '-Wl,-u_ZN15HeapLeakChecker12IgnoreObjectEPKv,-u_ZN15HeapLeakChecker14UnIgnoreObjectEPKv',
           ]},
         }],
-        # Need to distinguish a non-SDK build for Android WebView
-        # due to differences in C include files.
-        ['OS=="android" and android_webview_build==1', {
-          'defines': ['ANDROID_NON_SDK_BUILD'],
-        }],
         [ 'use_vtable_verify==1', {
           'cflags': [
             '-fvtable-verify=preinit',
diff --git a/base/allocator/allocator_extension_thunks.target.darwin-arm.mk b/base/allocator/allocator_extension_thunks.target.darwin-arm.mk
index 8025ab0..e8ee3eb 100644
--- a/base/allocator/allocator_extension_thunks.target.darwin-arm.mk
+++ b/base/allocator/allocator_extension_thunks.target.darwin-arm.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/allocator/allocator_extension_thunks.target.darwin-mips.mk b/base/allocator/allocator_extension_thunks.target.darwin-mips.mk
index dcb22ca..84b5ec2 100644
--- a/base/allocator/allocator_extension_thunks.target.darwin-mips.mk
+++ b/base/allocator/allocator_extension_thunks.target.darwin-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/allocator/allocator_extension_thunks.target.darwin-x86.mk b/base/allocator/allocator_extension_thunks.target.darwin-x86.mk
index 1a60871..8c3402b 100644
--- a/base/allocator/allocator_extension_thunks.target.darwin-x86.mk
+++ b/base/allocator/allocator_extension_thunks.target.darwin-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/allocator/allocator_extension_thunks.target.darwin-x86_64.mk b/base/allocator/allocator_extension_thunks.target.darwin-x86_64.mk
new file mode 100644
index 0000000..e582e9f
--- /dev/null
+++ b/base/allocator/allocator_extension_thunks.target.darwin-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_allocator_allocator_extension_thunks_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/allocator/allocator_extension_thunks.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_allocator_allocator_extension_thunks_gyp
+
+# Alias gyp target name.
+.PHONY: allocator_extension_thunks
+allocator_extension_thunks: base_allocator_allocator_extension_thunks_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/allocator/allocator_extension_thunks.target.linux-arm.mk b/base/allocator/allocator_extension_thunks.target.linux-arm.mk
index 8025ab0..e8ee3eb 100644
--- a/base/allocator/allocator_extension_thunks.target.linux-arm.mk
+++ b/base/allocator/allocator_extension_thunks.target.linux-arm.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/allocator/allocator_extension_thunks.target.linux-mips.mk b/base/allocator/allocator_extension_thunks.target.linux-mips.mk
index dcb22ca..84b5ec2 100644
--- a/base/allocator/allocator_extension_thunks.target.linux-mips.mk
+++ b/base/allocator/allocator_extension_thunks.target.linux-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/allocator/allocator_extension_thunks.target.linux-x86.mk b/base/allocator/allocator_extension_thunks.target.linux-x86.mk
index 1a60871..8c3402b 100644
--- a/base/allocator/allocator_extension_thunks.target.linux-x86.mk
+++ b/base/allocator/allocator_extension_thunks.target.linux-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/allocator/allocator_extension_thunks.target.linux-x86_64.mk b/base/allocator/allocator_extension_thunks.target.linux-x86_64.mk
new file mode 100644
index 0000000..e582e9f
--- /dev/null
+++ b/base/allocator/allocator_extension_thunks.target.linux-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_allocator_allocator_extension_thunks_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/allocator/allocator_extension_thunks.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_allocator_allocator_extension_thunks_gyp
+
+# Alias gyp target name.
+.PHONY: allocator_extension_thunks
+allocator_extension_thunks: base_allocator_allocator_extension_thunks_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/allocator/allocator_shim.cc b/base/allocator/allocator_shim.cc
index d2dd5a4..c0de36e 100644
--- a/base/allocator/allocator_shim.cc
+++ b/base/allocator/allocator_shim.cc
@@ -41,8 +41,8 @@
 // See SetupSubprocessAllocator() to specify a default secondary (subprocess)
 // allocator.
 // TODO(jar): Switch to using TCMALLOC for the renderer as well.
-#if (defined(ADDRESS_SANITIZER) && defined(OS_WIN))
-// The Windows implementation of Asan requires the use of "WINHEAP".
+#if defined(SYZYASAN)
+// SyzyASan requires the use of "WINHEAP".
 static Allocator allocator = WINHEAP;
 #else
 static Allocator allocator = TCMALLOC;
@@ -228,9 +228,9 @@
 
 // The CRT heap initialization stub.
 extern "C" int _heap_init() {
-// Don't use the environment variable if ADDRESS_SANITIZER is defined on
-// Windows, as the implementation requires Winheap to be the allocator.
-#if !(defined(ADDRESS_SANITIZER) && defined(OS_WIN))
+// Don't use the environment variable if SYZYASAN is defined, as the
+// implementation requires Winheap to be the allocator.
+#if !defined(SYZYASAN)
   const char* environment_value = GetenvBeforeMain(primary_name);
   if (environment_value) {
     if (!stricmp(environment_value, "winheap"))
@@ -356,9 +356,9 @@
   buffer[sizeof(buffer) - 1] = '\0';
 
   if (secondary_length || !primary_length) {
-    // Don't use the environment variable if ADDRESS_SANITIZER is defined on
-    // Windows, as the implementation require Winheap to be the allocator.
-#if !(defined(ADDRESS_SANITIZER) && defined(OS_WIN))
+// Don't use the environment variable if SYZYASAN is defined, as the
+// implementation require Winheap to be the allocator.
+#if !defined(SYZYASAN)
     const char* secondary_value = secondary_length ? buffer : "TCMALLOC";
     // Force renderer (or other subprocesses) to use secondary_value.
 #else
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 4e15955..c3b3b35 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -4,6 +4,7 @@
 
 package org.chromium.base.library_loader;
 
+import android.content.Context;
 import android.os.SystemClock;
 import android.util.Log;
 
@@ -41,16 +42,42 @@
     // library_loader_hooks.cc).
     private static boolean sInitialized = false;
 
+    // One-way switch becomes true if the system library loading failed,
+    // and the right native library was found and loaded by the hack.
+    // The flag is used to report UMA stats later.
+    private static boolean sNativeLibraryHackWasUsed = false;
+
+
     /**
-     *  This method blocks until the library is fully loaded and initialized.
+     * TODO: http://crbug.com/354655
+     * remove this method once WebViewChromiumFactoryProvider.java
+     * changes the call to ensureInitialized(null).
      */
     public static void ensureInitialized() throws ProcessInitException {
+        ensureInitialized(null);
+    }
+
+    /**
+     *  This method blocks until the library is fully loaded and initialized.
+     *
+     *  @param context The context in which the method is called, the caller
+     *    may pass in a null context if it doesn't know in which context it
+     *    is running, or it doesn't need to work around the issue
+     *    http://b/13216167.
+     *
+     *    When the context is not null and native library was not extracted
+     *    by Android package manager, the LibraryLoader class
+     *    will extract the native libraries from APK. This is a hack used to
+     *    work around some Sony devices with the following platform bug:
+     *    http://b/13216167.
+     */
+    public static void ensureInitialized(Context context) throws ProcessInitException {
         synchronized (sLock) {
             if (sInitialized) {
                 // Already initialized, nothing to do.
                 return;
             }
-            loadAlreadyLocked();
+            loadAlreadyLocked(context);
             initializeAlreadyLocked(CommandLine.getJavaSwitchesOrNull());
         }
     }
@@ -73,9 +100,9 @@
      *
      * @throws ProcessInitException if the native library failed to load.
      */
-    public static void loadNow() throws ProcessInitException {
+    public static void loadNow(Context context) throws ProcessInitException {
         synchronized (sLock) {
-            loadAlreadyLocked();
+            loadAlreadyLocked(context);
         }
     }
 
@@ -93,7 +120,7 @@
     }
 
     // Invoke System.loadLibrary(...), triggering JNI_OnLoad in native code
-    private static void loadAlreadyLocked() throws ProcessInitException {
+    private static void loadAlreadyLocked(Context context) throws ProcessInitException {
         try {
             if (!sLoaded) {
                 assert !sInitialized;
@@ -108,7 +135,21 @@
                     if (useChromiumLinker) {
                         Linker.loadLibrary(library);
                     } else {
-                        System.loadLibrary(library);
+                        try {
+                            System.loadLibrary(library);
+                            if (context != null) {
+                                LibraryLoaderHelper.deleteWorkaroundLibrariesAsynchronously(
+                                    context);
+                            }
+                        } catch (UnsatisfiedLinkError e) {
+                            if (context != null
+                                && LibraryLoaderHelper.tryLoadLibraryUsingWorkaround(context,
+                                                                                     library)) {
+                                sNativeLibraryHackWasUsed = true;
+                            } else {
+                                throw e;
+                            }
+                        }
                     }
                 }
                 if (useChromiumLinker) Linker.finishLibraryLoad();
@@ -154,6 +195,8 @@
             nativeRecordChromiumAndroidLinkerHistogram(Linker.loadAtFixedAddressFailed(),
                     SysUtils.isLowEndDevice());
         }
+
+        nativeRecordNativeLibraryHack(sNativeLibraryHackWasUsed);
     }
 
     // Only methods needed before or during normal JNI registration are during System.OnLoad.
@@ -174,4 +217,6 @@
     // Get the version of the native library. This is needed so that we can check we
     // have the right version before initializing the (rest of the) JNI.
     private static native String nativeGetVersionNumber();
+
+    private static native void nativeRecordNativeLibraryHack(boolean usedHack);
 }
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java
new file mode 100644
index 0000000..7eeb2c8
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoaderHelper.java
@@ -0,0 +1,259 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+package org.chromium.base.library_loader;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.os.Build;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+/**
+ * The class provides helper functions to extract native libraries from APK,
+ * and load libraries from there.
+ *
+ * The class should be package-visible only, but made public for testing
+ * purpose.
+ */
+public class LibraryLoaderHelper {
+    private static final String TAG = "LibraryLoaderHelper";
+
+    private static final String LIB_DIR = "lib";
+
+    /**
+     * One-way switch becomes true if native libraries were unpacked
+     * from APK.
+     */
+    private static boolean sLibrariesWereUnpacked = false;
+
+    /**
+     * Loads native libraries using workaround only, skip the library in system
+     * lib path. The method exists only for testing purpose.
+     * Caller must ensure thread safety of this method.
+     * @param context
+     */
+    public static boolean loadNativeLibrariesUsingWorkaroundForTesting(Context context) {
+        // Although tryLoadLibraryUsingWorkaround might be called multiple times,
+        // libraries should only be unpacked once, this is guaranteed by
+        // sLibrariesWereUnpacked.
+        for (String library : NativeLibraries.LIBRARIES) {
+            if (!tryLoadLibraryUsingWorkaround(context, library)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Try to load a native library using a workaround of
+     *   http://b/13216167.
+     *
+     * Workaround for b/13216167 was adapted from code in
+     * https://googleplex-android-review.git.corp.google.com/#/c/433061
+     *
+     * More details about http://b/13216167:
+     *   PackageManager may fail to update shared library.
+     *
+     * Native library directory in an updated package is a symbolic link
+     * to a directory in /data/app-lib/<package name>, for example:
+     * /data/data/com.android.chrome/lib -> /data/app-lib/com.android.chrome[-1].
+     * When updating the application, the PackageManager create a new directory,
+     * e.g., /data/app-lib/com.android.chrome-2, and remove the old symlink and
+     * recreate one to the new directory. However, on some devices (e.g. Sony Xperia),
+     * the symlink was updated, but fails to extract new native libraries from
+     * the new apk.
+
+     * We make the following changes to alleviate the issue:
+     *  1) name the native library with apk version code, e.g.,
+     *     libchrome.1750.136.so, 1750.136 is Chrome version number;
+     *  2) first try to load the library using System.loadLibrary,
+     *     if that failed due to the library file was not found,
+     *     search the named library in a /data/data/com.android.chrome/app_lib
+     *     directory. Because of change 1), each version has a different native
+     *     library name, so avoid mistakenly using the old native library.
+     *
+     *  If named library is not in /data/data/com.android.chrome/app_lib directory,
+     *  extract native libraries from apk and cache in the directory.
+     *
+     * This function doesn't throw UnsatisfiedLinkError, the caller needs to
+     * check the return value.
+     */
+    static boolean tryLoadLibraryUsingWorkaround(Context context, String library) {
+        assert context != null;
+        File libFile = getWorkaroundLibFile(context, library);
+        if (!libFile.exists() && !unpackLibrariesOnce(context)) {
+            return false;
+        }
+        try {
+            System.load(libFile.getAbsolutePath());
+            return true;
+        } catch (UnsatisfiedLinkError e) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the directory for holding extracted native libraries.
+     * It may create the directory if it doesn't exist.
+     *
+     * @param context
+     * @return the directory file object
+     */
+    public static File getWorkaroundLibDir(Context context) {
+        return context.getDir(LIB_DIR, Context.MODE_PRIVATE);
+    }
+
+    private static File getWorkaroundLibFile(Context context, String library) {
+        String libName = System.mapLibraryName(library);
+        return new File(getWorkaroundLibDir(context), libName);
+    }
+
+    /**
+     * Unpack native libraries from the APK file. The method is supposed to
+     * be called only once. It deletes existing files in unpacked directory
+     * before unpacking.
+     *
+     * @param context
+     * @return true when unpacking was successful, false when failed or called
+     *         more than once.
+     */
+    private static boolean unpackLibrariesOnce(Context context) {
+        if (sLibrariesWereUnpacked) {
+            return false;
+        }
+        sLibrariesWereUnpacked = true;
+
+        File libDir = getWorkaroundLibDir(context);
+        if (libDir.exists()) {
+            assert libDir.isDirectory();
+            deleteDirectorySync(libDir);
+        }
+
+        try {
+            ApplicationInfo appInfo = context.getApplicationInfo();
+            ZipFile file = new ZipFile(new File(appInfo.sourceDir), ZipFile.OPEN_READ);
+            for (String libName : NativeLibraries.LIBRARIES) {
+                String jniNameInApk = "lib/" + Build.CPU_ABI + "/" +
+                    System.mapLibraryName(libName);
+
+                final ZipEntry entry = file.getEntry(jniNameInApk);
+                if (entry == null) {
+                    Log.e(TAG, appInfo.sourceDir + " doesn't have file " + jniNameInApk);
+                    file.close();
+                    deleteDirectorySync(libDir);
+                    return false;
+                }
+
+                File outputFile = getWorkaroundLibFile(context, libName);
+
+                Log.i(TAG, "Extracting native libraries into " + outputFile.getAbsolutePath());
+
+                assert !outputFile.exists();
+
+                try {
+                    if (!outputFile.createNewFile()) {
+                        throw new IOException();
+                    }
+
+                    InputStream is = null;
+                    FileOutputStream os = null;
+                    try {
+                        is = file.getInputStream(entry);
+                        os = new FileOutputStream(outputFile);
+                        int count = 0;
+                        byte[] buffer = new byte[16 * 1024];
+                        while ((count = is.read(buffer)) > 0) {
+                            os.write(buffer, 0, count);
+                        }
+                    } finally {
+                        try {
+                            if (is != null) is.close();
+                        } finally {
+                            if (os != null) os.close();
+                        }
+                    }
+                    // Change permission to rwxr-xr-x
+                    outputFile.setReadable(true, false);
+                    outputFile.setExecutable(true, false);
+                    outputFile.setWritable(true);
+                } catch (IOException e) {
+                    if (outputFile.exists()) {
+                        if (!outputFile.delete()) {
+                            Log.e(TAG, "Failed to delete " + outputFile.getAbsolutePath());
+                        }
+                    }
+                    file.close();
+                    throw e;
+                }
+            }
+            file.close();
+            return true;
+        } catch (IOException e) {
+            Log.e(TAG, "Failed to unpack native libraries", e);
+            deleteDirectorySync(libDir);
+            return false;
+        }
+    }
+
+    /**
+     * Delete old library files in the backup directory.
+     *  The actual deletion is done in a background thread.
+     *
+     * @param context
+     */
+    static void deleteWorkaroundLibrariesAsynchronously(Context context) {
+        // Child process should not reach here.
+        final File libDir = getWorkaroundLibDir(context);
+        if (libDir.exists()) {
+            assert libDir.isDirectory();
+            // Async deletion
+            new Thread() {
+                @Override
+                public void run() {
+                    deleteDirectorySync(libDir);
+                }
+            }.start();
+        }
+    }
+
+    /**
+     * Delete the workaround libraries and directory synchronously.
+     * For testing purpose only.
+     * @param context
+     */
+    public static void deleteWorkaroundLibrariesSynchronously(Context context) {
+        File libDir = getWorkaroundLibDir(context);
+        if (libDir.exists()) {
+            deleteDirectorySync(libDir);
+        }
+    }
+
+    private static void deleteDirectorySync(File dir) {
+        try {
+            File[] files = dir.listFiles();
+            if (files != null) {
+                for (File file : files) {
+                    String fileName = file.getName();
+                    if (!file.delete()) {
+                      Log.e(TAG, "Failed to remove " + file.getAbsolutePath());
+                    }
+                }
+            }
+            if (!dir.delete()) {
+                Log.w(TAG, "Failed to remove " + dir.getAbsolutePath());
+            }
+            return;
+        } catch (Exception e) {
+            Log.e(TAG, "Failed to remove old libs, ", e);
+        }
+    }
+}
diff --git a/base/android/javatests/src/org/chromium/base/LibraryLoaderHelperTest.java b/base/android/javatests/src/org/chromium/base/LibraryLoaderHelperTest.java
new file mode 100644
index 0000000..85f4c77
--- /dev/null
+++ b/base/android/javatests/src/org/chromium/base/LibraryLoaderHelperTest.java
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.content.Context;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.MediumTest;
+
+import org.chromium.base.library_loader.LibraryLoaderHelper;
+
+import java.io.File;
+
+/**
+ * Test class for the native library hack.
+ */
+public class LibraryLoaderHelperTest extends InstrumentationTestCase {
+    private static final String TAG = "LibraryLoaderHelperTest";
+
+    @Override
+    public void setUp() throws Exception {
+        Context context = getInstrumentation().getTargetContext();
+        LibraryLoaderHelper.deleteWorkaroundLibrariesSynchronously(context);
+    }
+
+    @MediumTest
+    public void testLoadNativeLibraries() {
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                Context context = getInstrumentation().getTargetContext();
+                File libDir = LibraryLoaderHelper.getWorkaroundLibDir(context);
+                assertTrue(libDir.exists());
+                assertTrue(libDir.isDirectory());
+                assertEquals(libDir.list().length, 0);
+
+                assertTrue(
+                    LibraryLoaderHelper.loadNativeLibrariesUsingWorkaroundForTesting(
+                        context));
+
+                assertTrue(libDir.list().length > 0);
+            }
+        });
+    }
+
+    @Override
+    public void tearDown() throws Exception {
+        Context context = getInstrumentation().getTargetContext();
+        LibraryLoaderHelper.deleteWorkaroundLibrariesSynchronously(context);
+        super.tearDown();
+    }
+}
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py
index f5aab86..2733583 100755
--- a/base/android/jni_generator/jni_generator.py
+++ b/base/android/jni_generator/jni_generator.py
@@ -206,6 +206,7 @@
     if '/' in param:
       # Coming from javap, use the fully qualified param directly.
       return prefix + 'L' + JniParams.RemapClassName(param) + ';'
+
     for qualified_name in (object_param_list +
                            [JniParams._fully_qualified_class] +
                            JniParams._inner_classes):
@@ -238,6 +239,12 @@
         if qualified_name.endswith('/' + outer):
           return (prefix + JniParams.RemapClassName(qualified_name) +
                   '$' + inner + ';')
+      raise SyntaxError('Inner class (%s) can not be '
+                        'used directly by JNI. Please import the outer '
+                        'class, probably:\n'
+                        'import %s.%s;' %
+                        (param, JniParams._package.replace('/', '.'),
+                         outer.replace('/', '.')))
 
     # Type not found, falling back to same package as this class.
     return (prefix + 'L' +
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py
index 32fb4c6..61d76c8 100755
--- a/base/android/jni_generator/jni_generator_tests.py
+++ b/base/android/jni_generator/jni_generator_tests.py
@@ -994,5 +994,22 @@
         test_data, 'org/chromium/example/jni_generator/Test', options)
     self.assertGoldenTextEquals(jni_from_java.GetContent())
 
+  def testOuterInnerRaises(self):
+    test_data = """
+    package org.chromium.media;
+
+    @CalledByNative
+    static int getCaptureFormatWidth(VideoCapture.CaptureFormat format) {
+        return format.getWidth();
+    }
+    """
+    def willRaise():
+      jni_generator.JNIFromJavaSource(
+          test_data,
+          'org/chromium/media/VideoCaptureFactory',
+          TestOptions())
+    self.assertRaises(SyntaxError, willRaise)
+
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/base/android/library_loader/library_loader_hooks.cc b/base/android/library_loader/library_loader_hooks.cc
index 8fa16df..0145eab 100644
--- a/base/android/library_loader/library_loader_hooks.cc
+++ b/base/android/library_loader/library_loader_hooks.cc
@@ -64,5 +64,9 @@
   return env->NewStringUTF(g_library_version_number);
 }
 
+static void RecordNativeLibraryHack(JNIEnv*, jclass, jboolean usedHack) {
+  UMA_HISTOGRAM_BOOLEAN("LibraryLoader.NativeLibraryHack", usedHack);
+}
+
 }  // namespace android
 }  // namespace base
diff --git a/base/atomicops.h b/base/atomicops.h
index 3d15e03..d950581 100644
--- a/base/atomicops.h
+++ b/base/atomicops.h
@@ -146,8 +146,10 @@
 #include "base/atomicops_internals_mac.h"
 #elif defined(OS_NACL)
 #include "base/atomicops_internals_gcc.h"
-#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)
+#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARMEL)
 #include "base/atomicops_internals_arm_gcc.h"
+#elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM64)
+#include "base/atomicops_internals_arm64_gcc.h"
 #elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
 #include "base/atomicops_internals_x86_gcc.h"
 #elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS_FAMILY)
diff --git a/base/atomicops_internals_arm64_gcc.h b/base/atomicops_internals_arm64_gcc.h
new file mode 100644
index 0000000..a2b0abc
--- /dev/null
+++ b/base/atomicops_internals_arm64_gcc.h
@@ -0,0 +1,360 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file is an internal atomic implementation, use base/atomicops.h instead.
+
+// TODO(rmcilroy): Investigate whether we can use __sync__ intrinsics instead of
+//                 the hand coded assembly without introducing perf regressions.
+// TODO(rmcilroy): Investigate whether we can use acquire / release versions of
+//                 exclusive load / store assembly instructions and do away with
+//                 the barriers.
+
+#ifndef BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+#define BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+
+#if defined(OS_QNX)
+#include <sys/cpuinline.h>
+#endif
+
+namespace base {
+namespace subtle {
+
+inline void MemoryBarrier() {
+  __asm__ __volatile__ (  // NOLINT
+    "dmb ish                                  \n\t"  // Data memory barrier.
+    ::: "memory"
+  );  // NOLINT
+}
+
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "1:                                    \n\t"
+    "clrex                                 \n\t"  // In case we didn't swap.
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[result], %[ptr]               \n\t"  // Load the previous value.
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                       \n\t"
+    "ldxr %w[result], %[ptr]                  \n\t"  // Load the previous value.
+    "add %w[result], %w[result], %w[increment]\n\t"
+    "stxr %w[temp], %w[result], %[ptr]        \n\t"  // Try to store the result.
+    "cbnz %w[temp], 0b                        \n\t"  // Retry on failure.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"r" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  MemoryBarrier();
+  Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+
+  return result;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "dmb ish                               \n\t"  // Data memory barrier.
+    "1:                                    \n\t"
+    // If the compare failed the 'dmb' is unnecessary, but we still need a
+    // 'clrex'.
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  MemoryBarrier();
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "1:                                    \n\t"
+    // If the compare failed the we still need a 'clrex'.
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+// 64-bit versions of the operations.
+// See the 32-bit versions for comments.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "1:                                    \n\t"
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[result], %[ptr]                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                     \n\t"
+    "ldxr %[result], %[ptr]                 \n\t"
+    "add %[result], %[result], %[increment] \n\t"
+    "stxr %w[temp], %[result], %[ptr]       \n\t"
+    "cbnz %w[temp], 0b                      \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"r" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  MemoryBarrier();
+  Atomic64 result = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+
+  return result;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "dmb ish                               \n\t"
+    "1:                                    \n\t"
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  MemoryBarrier();
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "1:                                    \n\t"
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace base::subtle
+}  // namespace base
+
+#endif  // BASE_ATOMICOPS_INTERNALS_ARM64_GCC_H_
diff --git a/base/base.gyp b/base/base.gyp
index 963cd51..1e9ae28 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -221,9 +221,6 @@
         }],
       ],
       'sources': [
-        'third_party/nspr/prcpucfg.h',
-        'third_party/nspr/prcpucfg_win.h',
-        'third_party/nspr/prtypes.h',
         'third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
         'third_party/xdg_user_dirs/xdg_user_dir_lookup.h',
         'async_socket_io_handler.h',
@@ -512,8 +509,8 @@
         'md5_unittest.cc',
         'memory/aligned_memory_unittest.cc',
         'memory/discardable_memory_allocator_android_unittest.cc',
+        'memory/discardable_memory_manager_unittest.cc',
         'memory/discardable_memory_unittest.cc',
-        'memory/discardable_memory_provider_unittest.cc',
         'memory/linked_ptr_unittest.cc',
         'memory/ref_counted_memory_unittest.cc',
         'memory/ref_counted_unittest.cc',
@@ -788,11 +785,6 @@
             '../third_party/libevent/libevent.gyp:libevent'
           ],
         }],
-        ['use_aura==1 and use_x11==1',  {
-          'sources': [
-            'x11/edid_parser_x11_unittest.cc',
-          ],
-        }],
       ],  # conditions
       'target_conditions': [
         ['OS == "ios" and _toolset != "host"', {
@@ -1091,9 +1083,6 @@
             4267,
           ],
           'sources': [
-            'third_party/nspr/prcpucfg.h',
-            'third_party/nspr/prcpucfg_win.h',
-            'third_party/nspr/prtypes.h',
             'third_party/xdg_user_dirs/xdg_user_dir_lookup.cc',
             'third_party/xdg_user_dirs/xdg_user_dir_lookup.h',
             'async_socket_io_handler.h',
diff --git a/base/base.gypi b/base/base.gypi
index d0ed5bb..1d15b0a 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -18,17 +18,8 @@
           'third_party/dmg_fp/dtoa_wrapper.cc',
           'third_party/icu/icu_utf.cc',
           'third_party/icu/icu_utf.h',
-          'third_party/nspr/prcpucfg.h',
-          'third_party/nspr/prcpucfg_freebsd.h',
-          'third_party/nspr/prcpucfg_linux.h',
-          'third_party/nspr/prcpucfg_mac.h',
-          'third_party/nspr/prcpucfg_nacl.h',
-          'third_party/nspr/prcpucfg_openbsd.h',
-          'third_party/nspr/prcpucfg_solaris.h',
-          'third_party/nspr/prcpucfg_win.h',
           'third_party/nspr/prtime.cc',
           'third_party/nspr/prtime.h',
-          'third_party/nspr/prtypes.h',
           'third_party/superfasthash/superfasthash.c',
           'third_party/xdg_mime/xdgmime.h',
           'allocator/allocator_extension.cc',
@@ -323,8 +314,8 @@
           'memory/discardable_memory_mac.cc',
           'memory/discardable_memory_malloc.cc',
           'memory/discardable_memory_malloc.h',
-          'memory/discardable_memory_provider.cc',
-          'memory/discardable_memory_provider.h',
+          'memory/discardable_memory_manager.cc',
+          'memory/discardable_memory_manager.h',
           'memory/discardable_memory_win.cc',
           'memory/linked_ptr.h',
           'memory/manual_constructor.h',
@@ -454,6 +445,7 @@
           'process/launch_posix.cc',
           'process/launch_win.cc',
           'process/memory.h',
+          'process/memory.cc',
           'process/memory_linux.cc',
           'process/memory_mac.mm',
           'process/memory_win.cc',
@@ -720,14 +712,6 @@
           'win/wrapped_window_proc.cc',
           'win/wrapped_window_proc.h',
         ],
-        'conditions': [
-          ['use_aura==1 and use_x11==1', {
-            'sources': [
-              'x11/edid_parser_x11.cc',
-              'x11/edid_parser_x11.h',
-            ],
-          }],
-        ],
         'defines': [
           'BASE_IMPLEMENTATION',
         ],
diff --git a/base/base.target.darwin-arm.mk b/base/base.target.darwin-arm.mk
index 965f904..3334a30 100644
--- a/base/base.target.darwin-arm.mk
+++ b/base/base.target.darwin-arm.mk
@@ -130,7 +130,7 @@
 	base/memory/discardable_memory_android.cc \
 	base/memory/discardable_memory_emulated.cc \
 	base/memory/discardable_memory_malloc.cc \
-	base/memory/discardable_memory_provider.cc \
+	base/memory/discardable_memory_manager.cc \
 	base/memory/memory_pressure_listener.cc \
 	base/memory/ref_counted.cc \
 	base/memory/ref_counted_memory.cc \
@@ -175,6 +175,7 @@
 	base/process/kill_posix.cc \
 	base/process/launch.cc \
 	base/process/launch_posix.cc \
+	base/process/memory.cc \
 	base/process/memory_linux.cc \
 	base/process/process_handle_linux.cc \
 	base/process/process_handle_posix.cc \
@@ -311,6 +312,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
@@ -398,6 +400,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
diff --git a/base/base.target.darwin-mips.mk b/base/base.target.darwin-mips.mk
index 16c8518..93d926c 100644
--- a/base/base.target.darwin-mips.mk
+++ b/base/base.target.darwin-mips.mk
@@ -130,7 +130,7 @@
 	base/memory/discardable_memory_android.cc \
 	base/memory/discardable_memory_emulated.cc \
 	base/memory/discardable_memory_malloc.cc \
-	base/memory/discardable_memory_provider.cc \
+	base/memory/discardable_memory_manager.cc \
 	base/memory/memory_pressure_listener.cc \
 	base/memory/ref_counted.cc \
 	base/memory/ref_counted_memory.cc \
@@ -175,6 +175,7 @@
 	base/process/kill_posix.cc \
 	base/process/launch.cc \
 	base/process/launch_posix.cc \
+	base/process/memory.cc \
 	base/process/memory_linux.cc \
 	base/process/process_handle_linux.cc \
 	base/process/process_handle_posix.cc \
@@ -310,6 +311,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
@@ -396,6 +398,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
diff --git a/base/base.target.darwin-x86.mk b/base/base.target.darwin-x86.mk
index e514855..dc6890c 100644
--- a/base/base.target.darwin-x86.mk
+++ b/base/base.target.darwin-x86.mk
@@ -131,7 +131,7 @@
 	base/memory/discardable_memory_android.cc \
 	base/memory/discardable_memory_emulated.cc \
 	base/memory/discardable_memory_malloc.cc \
-	base/memory/discardable_memory_provider.cc \
+	base/memory/discardable_memory_manager.cc \
 	base/memory/memory_pressure_listener.cc \
 	base/memory/ref_counted.cc \
 	base/memory/ref_counted_memory.cc \
@@ -176,6 +176,7 @@
 	base/process/kill_posix.cc \
 	base/process/launch.cc \
 	base/process/launch_posix.cc \
+	base/process/memory.cc \
 	base/process/memory_linux.cc \
 	base/process/process_handle_linux.cc \
 	base/process/process_handle_posix.cc \
@@ -313,6 +314,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
@@ -400,6 +402,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
diff --git a/base/base.target.darwin-x86_64.mk b/base/base.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7709e10
--- /dev/null
+++ b/base/base.target.darwin-x86_64.mk
@@ -0,0 +1,501 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,testing_gtest_prod_gyp)/gtest_prod.stamp \
+	$(call intermediates-dir-for,GYP,base_base_jni_headers_gyp)/base_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_ashmem_ashmem_gyp)/ashmem.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/async_socket_io_handler_posix.cc \
+	base/event_recorder_stubs.cc \
+	base/linux_util.cc \
+	base/message_loop/message_pump_android.cc \
+	base/message_loop/message_pump_libevent.cc \
+	base/metrics/field_trial.cc \
+	base/posix/file_descriptor_shuffle.cc \
+	base/sync_socket_posix.cc \
+	base/third_party/dmg_fp/g_fmt.cc \
+	base/third_party/dmg_fp/dtoa_wrapper.cc \
+	base/third_party/icu/icu_utf.cc \
+	base/third_party/nspr/prtime.cc \
+	base/third_party/superfasthash/superfasthash.c \
+	base/allocator/allocator_extension.cc \
+	base/allocator/type_profiler_control.cc \
+	base/android/application_status_listener.cc \
+	base/android/base_jni_registrar.cc \
+	base/android/build_info.cc \
+	base/android/command_line_android.cc \
+	base/android/content_uri_utils.cc \
+	base/android/cpu_features.cc \
+	base/android/fifo_utils.cc \
+	base/android/important_file_writer_android.cc \
+	base/android/scoped_java_ref.cc \
+	base/android/jni_android.cc \
+	base/android/jni_array.cc \
+	base/android/jni_helper.cc \
+	base/android/jni_registrar.cc \
+	base/android/jni_string.cc \
+	base/android/library_loader/library_loader_hooks.cc \
+	base/android/memory_pressure_listener_android.cc \
+	base/android/java_handler_thread.cc \
+	base/android/path_service_android.cc \
+	base/android/path_utils.cc \
+	base/android/sys_utils.cc \
+	base/android/trace_event_binding.cc \
+	base/at_exit.cc \
+	base/atomicops_internals_x86_gcc.cc \
+	base/barrier_closure.cc \
+	base/base64.cc \
+	base/base_paths.cc \
+	base/base_paths_android.cc \
+	base/big_endian.cc \
+	base/bind_helpers.cc \
+	base/build_time.cc \
+	base/callback_helpers.cc \
+	base/callback_internal.cc \
+	base/command_line.cc \
+	base/cpu.cc \
+	base/debug/alias.cc \
+	base/debug/crash_logging.cc \
+	base/debug/debugger.cc \
+	base/debug/debugger_posix.cc \
+	base/debug/dump_without_crashing.cc \
+	base/debug/proc_maps_linux.cc \
+	base/debug/profiler.cc \
+	base/debug/stack_trace.cc \
+	base/debug/stack_trace_android.cc \
+	base/debug/trace_event_android.cc \
+	base/debug/trace_event_impl.cc \
+	base/debug/trace_event_impl_constants.cc \
+	base/debug/trace_event_synthetic_delay.cc \
+	base/debug/trace_event_system_stats_monitor.cc \
+	base/debug/trace_event_memory.cc \
+	base/deferred_sequenced_task_runner.cc \
+	base/environment.cc \
+	base/file_util.cc \
+	base/file_util_android.cc \
+	base/file_util_posix.cc \
+	base/files/file.cc \
+	base/files/file_enumerator.cc \
+	base/files/file_enumerator_posix.cc \
+	base/files/file_path.cc \
+	base/files/file_path_constants.cc \
+	base/files/file_path_watcher.cc \
+	base/files/file_path_watcher_linux.cc \
+	base/files/file_posix.cc \
+	base/files/file_proxy.cc \
+	base/files/file_util_proxy.cc \
+	base/files/important_file_writer.cc \
+	base/files/memory_mapped_file.cc \
+	base/files/memory_mapped_file_posix.cc \
+	base/files/scoped_file.cc \
+	base/files/scoped_platform_file_closer.cc \
+	base/files/scoped_temp_dir.cc \
+	base/guid.cc \
+	base/guid_posix.cc \
+	base/hash.cc \
+	base/ini_parser.cc \
+	base/json/json_file_value_serializer.cc \
+	base/json/json_parser.cc \
+	base/json/json_reader.cc \
+	base/json/json_string_value_serializer.cc \
+	base/json/json_writer.cc \
+	base/json/string_escape.cc \
+	base/lazy_instance.cc \
+	base/location.cc \
+	base/logging.cc \
+	base/md5.cc \
+	base/memory/aligned_memory.cc \
+	base/memory/discardable_memory.cc \
+	base/memory/discardable_memory_allocator_android.cc \
+	base/memory/discardable_memory_android.cc \
+	base/memory/discardable_memory_emulated.cc \
+	base/memory/discardable_memory_malloc.cc \
+	base/memory/discardable_memory_manager.cc \
+	base/memory/memory_pressure_listener.cc \
+	base/memory/ref_counted.cc \
+	base/memory/ref_counted_memory.cc \
+	base/memory/shared_memory_android.cc \
+	base/memory/shared_memory_posix.cc \
+	base/memory/singleton.cc \
+	base/memory/weak_ptr.cc \
+	base/message_loop/incoming_task_queue.cc \
+	base/message_loop/message_loop.cc \
+	base/message_loop/message_loop_proxy.cc \
+	base/message_loop/message_loop_proxy_impl.cc \
+	base/message_loop/message_pump.cc \
+	base/message_loop/message_pump_default.cc \
+	base/metrics/sample_map.cc \
+	base/metrics/sample_vector.cc \
+	base/metrics/bucket_ranges.cc \
+	base/metrics/histogram.cc \
+	base/metrics/histogram_base.cc \
+	base/metrics/histogram_delta_serialization.cc \
+	base/metrics/histogram_samples.cc \
+	base/metrics/histogram_snapshot_manager.cc \
+	base/metrics/sparse_histogram.cc \
+	base/metrics/statistics_recorder.cc \
+	base/metrics/stats_counters.cc \
+	base/metrics/stats_table.cc \
+	base/metrics/user_metrics.cc \
+	base/native_library_posix.cc \
+	base/os_compat_android.cc \
+	base/path_service.cc \
+	base/pending_task.cc \
+	base/pickle.cc \
+	base/platform_file.cc \
+	base/platform_file_posix.cc \
+	base/posix/global_descriptors.cc \
+	base/posix/unix_domain_socket_linux.cc \
+	base/power_monitor/power_monitor.cc \
+	base/power_monitor/power_monitor_device_source_android.cc \
+	base/power_monitor/power_monitor_device_source.cc \
+	base/power_monitor/power_monitor_source.cc \
+	base/process/internal_linux.cc \
+	base/process/kill.cc \
+	base/process/kill_posix.cc \
+	base/process/launch.cc \
+	base/process/launch_posix.cc \
+	base/process/memory.cc \
+	base/process/memory_linux.cc \
+	base/process/process_handle_linux.cc \
+	base/process/process_handle_posix.cc \
+	base/process/process_iterator.cc \
+	base/process/process_iterator_linux.cc \
+	base/process/process_metrics.cc \
+	base/process/process_metrics_linux.cc \
+	base/process/process_metrics_posix.cc \
+	base/process/process_posix.cc \
+	base/profiler/scoped_profile.cc \
+	base/profiler/alternate_timer.cc \
+	base/profiler/tracked_time.cc \
+	base/rand_util.cc \
+	base/rand_util_posix.cc \
+	base/run_loop.cc \
+	base/safe_strerror_posix.cc \
+	base/scoped_native_library.cc \
+	base/sequence_checker_impl.cc \
+	base/sequenced_task_runner.cc \
+	base/sha1_portable.cc \
+	base/strings/latin1_string_conversions.cc \
+	base/strings/nullable_string16.cc \
+	base/strings/safe_sprintf.cc \
+	base/strings/string16.cc \
+	base/strings/string_number_conversions.cc \
+	base/strings/string_split.cc \
+	base/strings/string_piece.cc \
+	base/strings/string_util.cc \
+	base/strings/string_util_constants.cc \
+	base/strings/stringprintf.cc \
+	base/strings/sys_string_conversions_posix.cc \
+	base/strings/utf_offset_string_conversions.cc \
+	base/strings/utf_string_conversion_utils.cc \
+	base/strings/utf_string_conversions.cc \
+	base/supports_user_data.cc \
+	base/synchronization/cancellation_flag.cc \
+	base/synchronization/condition_variable_posix.cc \
+	base/synchronization/lock.cc \
+	base/synchronization/lock_impl_posix.cc \
+	base/synchronization/waitable_event_posix.cc \
+	base/synchronization/waitable_event_watcher_posix.cc \
+	base/system_monitor/system_monitor.cc \
+	base/sys_info.cc \
+	base/sys_info_android.cc \
+	base/sys_info_linux.cc \
+	base/sys_info_posix.cc \
+	base/task/cancelable_task_tracker.cc \
+	base/task_runner.cc \
+	base/thread_task_runner_handle.cc \
+	base/threading/non_thread_safe_impl.cc \
+	base/threading/platform_thread_android.cc \
+	base/threading/platform_thread_posix.cc \
+	base/threading/post_task_and_reply_impl.cc \
+	base/threading/sequenced_worker_pool.cc \
+	base/threading/simple_thread.cc \
+	base/threading/thread.cc \
+	base/threading/thread_checker_impl.cc \
+	base/threading/thread_collision_warner.cc \
+	base/threading/thread_id_name_manager.cc \
+	base/threading/thread_local_posix.cc \
+	base/threading/thread_local_storage.cc \
+	base/threading/thread_local_storage_posix.cc \
+	base/threading/thread_restrictions.cc \
+	base/threading/watchdog.cc \
+	base/threading/worker_pool.cc \
+	base/threading/worker_pool_posix.cc \
+	base/time/clock.cc \
+	base/time/default_clock.cc \
+	base/time/default_tick_clock.cc \
+	base/time/tick_clock.cc \
+	base/time/time.cc \
+	base/time/time_posix.cc \
+	base/timer/elapsed_timer.cc \
+	base/timer/hi_res_timer_manager_posix.cc \
+	base/timer/mock_timer.cc \
+	base/timer/timer.cc \
+	base/tracked_objects.cc \
+	base/tracking_info.cc \
+	base/values.cc \
+	base/value_conversions.cc \
+	base/version.cc \
+	base/vlog.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_IMPLEMENTATION' \
+	'-DANDROID_SINCOS_PROVIDED' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/base \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_IMPLEMENTATION' \
+	'-DANDROID_SINCOS_PROVIDED' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/base \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_gyp
+
+# Alias gyp target name.
+.PHONY: base
+base: base_base_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/base.target.linux-arm.mk b/base/base.target.linux-arm.mk
index 965f904..3334a30 100644
--- a/base/base.target.linux-arm.mk
+++ b/base/base.target.linux-arm.mk
@@ -130,7 +130,7 @@
 	base/memory/discardable_memory_android.cc \
 	base/memory/discardable_memory_emulated.cc \
 	base/memory/discardable_memory_malloc.cc \
-	base/memory/discardable_memory_provider.cc \
+	base/memory/discardable_memory_manager.cc \
 	base/memory/memory_pressure_listener.cc \
 	base/memory/ref_counted.cc \
 	base/memory/ref_counted_memory.cc \
@@ -175,6 +175,7 @@
 	base/process/kill_posix.cc \
 	base/process/launch.cc \
 	base/process/launch_posix.cc \
+	base/process/memory.cc \
 	base/process/memory_linux.cc \
 	base/process/process_handle_linux.cc \
 	base/process/process_handle_posix.cc \
@@ -311,6 +312,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
@@ -398,6 +400,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
diff --git a/base/base.target.linux-mips.mk b/base/base.target.linux-mips.mk
index 16c8518..93d926c 100644
--- a/base/base.target.linux-mips.mk
+++ b/base/base.target.linux-mips.mk
@@ -130,7 +130,7 @@
 	base/memory/discardable_memory_android.cc \
 	base/memory/discardable_memory_emulated.cc \
 	base/memory/discardable_memory_malloc.cc \
-	base/memory/discardable_memory_provider.cc \
+	base/memory/discardable_memory_manager.cc \
 	base/memory/memory_pressure_listener.cc \
 	base/memory/ref_counted.cc \
 	base/memory/ref_counted_memory.cc \
@@ -175,6 +175,7 @@
 	base/process/kill_posix.cc \
 	base/process/launch.cc \
 	base/process/launch_posix.cc \
+	base/process/memory.cc \
 	base/process/memory_linux.cc \
 	base/process/process_handle_linux.cc \
 	base/process/process_handle_posix.cc \
@@ -310,6 +311,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
@@ -396,6 +398,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
diff --git a/base/base.target.linux-x86.mk b/base/base.target.linux-x86.mk
index e514855..dc6890c 100644
--- a/base/base.target.linux-x86.mk
+++ b/base/base.target.linux-x86.mk
@@ -131,7 +131,7 @@
 	base/memory/discardable_memory_android.cc \
 	base/memory/discardable_memory_emulated.cc \
 	base/memory/discardable_memory_malloc.cc \
-	base/memory/discardable_memory_provider.cc \
+	base/memory/discardable_memory_manager.cc \
 	base/memory/memory_pressure_listener.cc \
 	base/memory/ref_counted.cc \
 	base/memory/ref_counted_memory.cc \
@@ -176,6 +176,7 @@
 	base/process/kill_posix.cc \
 	base/process/launch.cc \
 	base/process/launch_posix.cc \
+	base/process/memory.cc \
 	base/process/memory_linux.cc \
 	base/process/process_handle_linux.cc \
 	base/process/process_handle_posix.cc \
@@ -313,6 +314,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
@@ -400,6 +402,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_IMPLEMENTATION' \
diff --git a/base/base.target.linux-x86_64.mk b/base/base.target.linux-x86_64.mk
new file mode 100644
index 0000000..7709e10
--- /dev/null
+++ b/base/base.target.linux-x86_64.mk
@@ -0,0 +1,501 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,testing_gtest_prod_gyp)/gtest_prod.stamp \
+	$(call intermediates-dir-for,GYP,base_base_jni_headers_gyp)/base_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_ashmem_ashmem_gyp)/ashmem.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/async_socket_io_handler_posix.cc \
+	base/event_recorder_stubs.cc \
+	base/linux_util.cc \
+	base/message_loop/message_pump_android.cc \
+	base/message_loop/message_pump_libevent.cc \
+	base/metrics/field_trial.cc \
+	base/posix/file_descriptor_shuffle.cc \
+	base/sync_socket_posix.cc \
+	base/third_party/dmg_fp/g_fmt.cc \
+	base/third_party/dmg_fp/dtoa_wrapper.cc \
+	base/third_party/icu/icu_utf.cc \
+	base/third_party/nspr/prtime.cc \
+	base/third_party/superfasthash/superfasthash.c \
+	base/allocator/allocator_extension.cc \
+	base/allocator/type_profiler_control.cc \
+	base/android/application_status_listener.cc \
+	base/android/base_jni_registrar.cc \
+	base/android/build_info.cc \
+	base/android/command_line_android.cc \
+	base/android/content_uri_utils.cc \
+	base/android/cpu_features.cc \
+	base/android/fifo_utils.cc \
+	base/android/important_file_writer_android.cc \
+	base/android/scoped_java_ref.cc \
+	base/android/jni_android.cc \
+	base/android/jni_array.cc \
+	base/android/jni_helper.cc \
+	base/android/jni_registrar.cc \
+	base/android/jni_string.cc \
+	base/android/library_loader/library_loader_hooks.cc \
+	base/android/memory_pressure_listener_android.cc \
+	base/android/java_handler_thread.cc \
+	base/android/path_service_android.cc \
+	base/android/path_utils.cc \
+	base/android/sys_utils.cc \
+	base/android/trace_event_binding.cc \
+	base/at_exit.cc \
+	base/atomicops_internals_x86_gcc.cc \
+	base/barrier_closure.cc \
+	base/base64.cc \
+	base/base_paths.cc \
+	base/base_paths_android.cc \
+	base/big_endian.cc \
+	base/bind_helpers.cc \
+	base/build_time.cc \
+	base/callback_helpers.cc \
+	base/callback_internal.cc \
+	base/command_line.cc \
+	base/cpu.cc \
+	base/debug/alias.cc \
+	base/debug/crash_logging.cc \
+	base/debug/debugger.cc \
+	base/debug/debugger_posix.cc \
+	base/debug/dump_without_crashing.cc \
+	base/debug/proc_maps_linux.cc \
+	base/debug/profiler.cc \
+	base/debug/stack_trace.cc \
+	base/debug/stack_trace_android.cc \
+	base/debug/trace_event_android.cc \
+	base/debug/trace_event_impl.cc \
+	base/debug/trace_event_impl_constants.cc \
+	base/debug/trace_event_synthetic_delay.cc \
+	base/debug/trace_event_system_stats_monitor.cc \
+	base/debug/trace_event_memory.cc \
+	base/deferred_sequenced_task_runner.cc \
+	base/environment.cc \
+	base/file_util.cc \
+	base/file_util_android.cc \
+	base/file_util_posix.cc \
+	base/files/file.cc \
+	base/files/file_enumerator.cc \
+	base/files/file_enumerator_posix.cc \
+	base/files/file_path.cc \
+	base/files/file_path_constants.cc \
+	base/files/file_path_watcher.cc \
+	base/files/file_path_watcher_linux.cc \
+	base/files/file_posix.cc \
+	base/files/file_proxy.cc \
+	base/files/file_util_proxy.cc \
+	base/files/important_file_writer.cc \
+	base/files/memory_mapped_file.cc \
+	base/files/memory_mapped_file_posix.cc \
+	base/files/scoped_file.cc \
+	base/files/scoped_platform_file_closer.cc \
+	base/files/scoped_temp_dir.cc \
+	base/guid.cc \
+	base/guid_posix.cc \
+	base/hash.cc \
+	base/ini_parser.cc \
+	base/json/json_file_value_serializer.cc \
+	base/json/json_parser.cc \
+	base/json/json_reader.cc \
+	base/json/json_string_value_serializer.cc \
+	base/json/json_writer.cc \
+	base/json/string_escape.cc \
+	base/lazy_instance.cc \
+	base/location.cc \
+	base/logging.cc \
+	base/md5.cc \
+	base/memory/aligned_memory.cc \
+	base/memory/discardable_memory.cc \
+	base/memory/discardable_memory_allocator_android.cc \
+	base/memory/discardable_memory_android.cc \
+	base/memory/discardable_memory_emulated.cc \
+	base/memory/discardable_memory_malloc.cc \
+	base/memory/discardable_memory_manager.cc \
+	base/memory/memory_pressure_listener.cc \
+	base/memory/ref_counted.cc \
+	base/memory/ref_counted_memory.cc \
+	base/memory/shared_memory_android.cc \
+	base/memory/shared_memory_posix.cc \
+	base/memory/singleton.cc \
+	base/memory/weak_ptr.cc \
+	base/message_loop/incoming_task_queue.cc \
+	base/message_loop/message_loop.cc \
+	base/message_loop/message_loop_proxy.cc \
+	base/message_loop/message_loop_proxy_impl.cc \
+	base/message_loop/message_pump.cc \
+	base/message_loop/message_pump_default.cc \
+	base/metrics/sample_map.cc \
+	base/metrics/sample_vector.cc \
+	base/metrics/bucket_ranges.cc \
+	base/metrics/histogram.cc \
+	base/metrics/histogram_base.cc \
+	base/metrics/histogram_delta_serialization.cc \
+	base/metrics/histogram_samples.cc \
+	base/metrics/histogram_snapshot_manager.cc \
+	base/metrics/sparse_histogram.cc \
+	base/metrics/statistics_recorder.cc \
+	base/metrics/stats_counters.cc \
+	base/metrics/stats_table.cc \
+	base/metrics/user_metrics.cc \
+	base/native_library_posix.cc \
+	base/os_compat_android.cc \
+	base/path_service.cc \
+	base/pending_task.cc \
+	base/pickle.cc \
+	base/platform_file.cc \
+	base/platform_file_posix.cc \
+	base/posix/global_descriptors.cc \
+	base/posix/unix_domain_socket_linux.cc \
+	base/power_monitor/power_monitor.cc \
+	base/power_monitor/power_monitor_device_source_android.cc \
+	base/power_monitor/power_monitor_device_source.cc \
+	base/power_monitor/power_monitor_source.cc \
+	base/process/internal_linux.cc \
+	base/process/kill.cc \
+	base/process/kill_posix.cc \
+	base/process/launch.cc \
+	base/process/launch_posix.cc \
+	base/process/memory.cc \
+	base/process/memory_linux.cc \
+	base/process/process_handle_linux.cc \
+	base/process/process_handle_posix.cc \
+	base/process/process_iterator.cc \
+	base/process/process_iterator_linux.cc \
+	base/process/process_metrics.cc \
+	base/process/process_metrics_linux.cc \
+	base/process/process_metrics_posix.cc \
+	base/process/process_posix.cc \
+	base/profiler/scoped_profile.cc \
+	base/profiler/alternate_timer.cc \
+	base/profiler/tracked_time.cc \
+	base/rand_util.cc \
+	base/rand_util_posix.cc \
+	base/run_loop.cc \
+	base/safe_strerror_posix.cc \
+	base/scoped_native_library.cc \
+	base/sequence_checker_impl.cc \
+	base/sequenced_task_runner.cc \
+	base/sha1_portable.cc \
+	base/strings/latin1_string_conversions.cc \
+	base/strings/nullable_string16.cc \
+	base/strings/safe_sprintf.cc \
+	base/strings/string16.cc \
+	base/strings/string_number_conversions.cc \
+	base/strings/string_split.cc \
+	base/strings/string_piece.cc \
+	base/strings/string_util.cc \
+	base/strings/string_util_constants.cc \
+	base/strings/stringprintf.cc \
+	base/strings/sys_string_conversions_posix.cc \
+	base/strings/utf_offset_string_conversions.cc \
+	base/strings/utf_string_conversion_utils.cc \
+	base/strings/utf_string_conversions.cc \
+	base/supports_user_data.cc \
+	base/synchronization/cancellation_flag.cc \
+	base/synchronization/condition_variable_posix.cc \
+	base/synchronization/lock.cc \
+	base/synchronization/lock_impl_posix.cc \
+	base/synchronization/waitable_event_posix.cc \
+	base/synchronization/waitable_event_watcher_posix.cc \
+	base/system_monitor/system_monitor.cc \
+	base/sys_info.cc \
+	base/sys_info_android.cc \
+	base/sys_info_linux.cc \
+	base/sys_info_posix.cc \
+	base/task/cancelable_task_tracker.cc \
+	base/task_runner.cc \
+	base/thread_task_runner_handle.cc \
+	base/threading/non_thread_safe_impl.cc \
+	base/threading/platform_thread_android.cc \
+	base/threading/platform_thread_posix.cc \
+	base/threading/post_task_and_reply_impl.cc \
+	base/threading/sequenced_worker_pool.cc \
+	base/threading/simple_thread.cc \
+	base/threading/thread.cc \
+	base/threading/thread_checker_impl.cc \
+	base/threading/thread_collision_warner.cc \
+	base/threading/thread_id_name_manager.cc \
+	base/threading/thread_local_posix.cc \
+	base/threading/thread_local_storage.cc \
+	base/threading/thread_local_storage_posix.cc \
+	base/threading/thread_restrictions.cc \
+	base/threading/watchdog.cc \
+	base/threading/worker_pool.cc \
+	base/threading/worker_pool_posix.cc \
+	base/time/clock.cc \
+	base/time/default_clock.cc \
+	base/time/default_tick_clock.cc \
+	base/time/tick_clock.cc \
+	base/time/time.cc \
+	base/time/time_posix.cc \
+	base/timer/elapsed_timer.cc \
+	base/timer/hi_res_timer_manager_posix.cc \
+	base/timer/mock_timer.cc \
+	base/timer/timer.cc \
+	base/tracked_objects.cc \
+	base/tracking_info.cc \
+	base/values.cc \
+	base/value_conversions.cc \
+	base/version.cc \
+	base/vlog.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_IMPLEMENTATION' \
+	'-DANDROID_SINCOS_PROVIDED' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/base \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_IMPLEMENTATION' \
+	'-DANDROID_SINCOS_PROVIDED' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/base \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_gyp
+
+# Alias gyp target name.
+.PHONY: base
+base: base_base_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/base_i18n.target.darwin-arm.mk b/base/base_i18n.target.darwin-arm.mk
index 308e9cd..4af0a7a 100644
--- a/base/base_i18n.target.darwin-arm.mk
+++ b/base/base_i18n.target.darwin-arm.mk
@@ -98,6 +98,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
@@ -189,6 +190,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
diff --git a/base/base_i18n.target.darwin-mips.mk b/base/base_i18n.target.darwin-mips.mk
index 3bbe5f4..4ba95f2 100644
--- a/base/base_i18n.target.darwin-mips.mk
+++ b/base/base_i18n.target.darwin-mips.mk
@@ -97,6 +97,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
@@ -187,6 +188,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
diff --git a/base/base_i18n.target.darwin-x86.mk b/base/base_i18n.target.darwin-x86.mk
index 7692b3e..fbf8b1b 100644
--- a/base/base_i18n.target.darwin-x86.mk
+++ b/base/base_i18n.target.darwin-x86.mk
@@ -99,6 +99,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
@@ -190,6 +191,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
diff --git a/base/base_i18n.target.darwin-x86_64.mk b/base/base_i18n.target.darwin-x86_64.mk
new file mode 100644
index 0000000..e6373ba
--- /dev/null
+++ b/base/base_i18n.target.darwin-x86_64.mk
@@ -0,0 +1,291 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_i18n_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/i18n/bidi_line_iterator.cc \
+	base/i18n/break_iterator.cc \
+	base/i18n/case_conversion.cc \
+	base/i18n/char_iterator.cc \
+	base/i18n/file_util_icu.cc \
+	base/i18n/i18n_constants.cc \
+	base/i18n/icu_encoding_detection.cc \
+	base/i18n/icu_string_conversions.cc \
+	base/i18n/icu_util.cc \
+	base/i18n/number_formatting.cc \
+	base/i18n/rtl.cc \
+	base/i18n/streaming_utf8_validator.cc \
+	base/i18n/string_compare.cc \
+	base/i18n/string_search.cc \
+	base/i18n/time_formatting.cc \
+	base/i18n/timezone.cc \
+	base/i18n/utf8_validator_tables.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_I18N_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_I18N_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_i18n_gyp
+
+# Alias gyp target name.
+.PHONY: base_i18n
+base_i18n: base_base_i18n_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/base_i18n.target.linux-arm.mk b/base/base_i18n.target.linux-arm.mk
index 308e9cd..4af0a7a 100644
--- a/base/base_i18n.target.linux-arm.mk
+++ b/base/base_i18n.target.linux-arm.mk
@@ -98,6 +98,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
@@ -189,6 +190,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
diff --git a/base/base_i18n.target.linux-mips.mk b/base/base_i18n.target.linux-mips.mk
index 3bbe5f4..4ba95f2 100644
--- a/base/base_i18n.target.linux-mips.mk
+++ b/base/base_i18n.target.linux-mips.mk
@@ -97,6 +97,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
@@ -187,6 +188,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
diff --git a/base/base_i18n.target.linux-x86.mk b/base/base_i18n.target.linux-x86.mk
index 7692b3e..fbf8b1b 100644
--- a/base/base_i18n.target.linux-x86.mk
+++ b/base/base_i18n.target.linux-x86.mk
@@ -99,6 +99,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
@@ -190,6 +191,7 @@
 	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DBASE_I18N_IMPLEMENTATION' \
diff --git a/base/base_i18n.target.linux-x86_64.mk b/base/base_i18n.target.linux-x86_64.mk
new file mode 100644
index 0000000..e6373ba
--- /dev/null
+++ b/base/base_i18n.target.linux-x86_64.mk
@@ -0,0 +1,291 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_i18n_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/i18n/bidi_line_iterator.cc \
+	base/i18n/break_iterator.cc \
+	base/i18n/case_conversion.cc \
+	base/i18n/char_iterator.cc \
+	base/i18n/file_util_icu.cc \
+	base/i18n/i18n_constants.cc \
+	base/i18n/icu_encoding_detection.cc \
+	base/i18n/icu_string_conversions.cc \
+	base/i18n/icu_util.cc \
+	base/i18n/number_formatting.cc \
+	base/i18n/rtl.cc \
+	base/i18n/streaming_utf8_validator.cc \
+	base/i18n/string_compare.cc \
+	base/i18n/string_search.cc \
+	base/i18n/time_formatting.cc \
+	base/i18n/timezone.cc \
+	base/i18n/utf8_validator_tables.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_I18N_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DBASE_I18N_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_i18n_gyp
+
+# Alias gyp target name.
+.PHONY: base_i18n
+base_i18n: base_base_i18n_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/base_java_application_state.target.darwin-arm.mk b/base/base_java_application_state.target.darwin-arm.mk
index 28953f7..ed3ce47 100644
--- a/base/base_java_application_state.target.darwin-arm.mk
+++ b/base/base_java_application_state.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_application_state.target.darwin-mips.mk b/base/base_java_application_state.target.darwin-mips.mk
index 16f15ef..230ad2e 100644
--- a/base/base_java_application_state.target.darwin-mips.mk
+++ b/base/base_java_application_state.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_application_state.target.darwin-x86.mk b/base/base_java_application_state.target.darwin-x86.mk
index 12cbc8f..cd1f59f 100644
--- a/base/base_java_application_state.target.darwin-x86.mk
+++ b/base/base_java_application_state.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_application_state.target.darwin-x86_64.mk b/base/base_java_application_state.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a0fed1c
--- /dev/null
+++ b/base/base_java_application_state.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := base_base_java_application_state_gyp
+LOCAL_MODULE_STEM := base_java_application_state
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "base_base_gyp_base_java_application_state_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'android/application_state_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/src/org/chromium/base/ApplicationState.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ApplicationState.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/base/android/application_state_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/base; cd $(gyp_local_path)/base; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java" "--template=android/java/src/org/chromium/base/ApplicationState.template"
+
+.PHONY: base_base_java_application_state_gyp_rule_trigger
+base_base_java_application_state_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	base_base_java_application_state_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_java_application_state_gyp
+
+# Alias gyp target name.
+.PHONY: base_java_application_state
+base_java_application_state: base_base_java_application_state_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/base/base_java_application_state.target.linux-arm.mk b/base/base_java_application_state.target.linux-arm.mk
index 28953f7..ed3ce47 100644
--- a/base/base_java_application_state.target.linux-arm.mk
+++ b/base/base_java_application_state.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_application_state.target.linux-mips.mk b/base/base_java_application_state.target.linux-mips.mk
index 16f15ef..230ad2e 100644
--- a/base/base_java_application_state.target.linux-mips.mk
+++ b/base/base_java_application_state.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_application_state.target.linux-x86.mk b/base/base_java_application_state.target.linux-x86.mk
index 12cbc8f..cd1f59f 100644
--- a/base/base_java_application_state.target.linux-x86.mk
+++ b/base/base_java_application_state.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_application_state.target.linux-x86_64.mk b/base/base_java_application_state.target.linux-x86_64.mk
new file mode 100644
index 0000000..a0fed1c
--- /dev/null
+++ b/base/base_java_application_state.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := base_base_java_application_state_gyp
+LOCAL_MODULE_STEM := base_java_application_state
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "base_base_gyp_base_java_application_state_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'android/application_state_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/src/org/chromium/base/ApplicationState.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ApplicationState.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/base/android/application_state_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/base; cd $(gyp_local_path)/base; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java" "--template=android/java/src/org/chromium/base/ApplicationState.template"
+
+.PHONY: base_base_java_application_state_gyp_rule_trigger
+base_base_java_application_state_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/base/ApplicationState.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	base_base_java_application_state_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_java_application_state_gyp
+
+# Alias gyp target name.
+.PHONY: base_java_application_state
+base_java_application_state: base_base_java_application_state_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/base/base_java_memory_pressure_level_list.target.darwin-arm.mk b/base/base_java_memory_pressure_level_list.target.darwin-arm.mk
index ecf6444..a3d4c70 100644
--- a/base/base_java_memory_pressure_level_list.target.darwin-arm.mk
+++ b/base/base_java_memory_pressure_level_list.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_memory_pressure_level_list.target.darwin-mips.mk b/base/base_java_memory_pressure_level_list.target.darwin-mips.mk
index c829249..2ab63ca 100644
--- a/base/base_java_memory_pressure_level_list.target.darwin-mips.mk
+++ b/base/base_java_memory_pressure_level_list.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_memory_pressure_level_list.target.darwin-x86.mk b/base/base_java_memory_pressure_level_list.target.darwin-x86.mk
index 93daeee..cf46c27 100644
--- a/base/base_java_memory_pressure_level_list.target.darwin-x86.mk
+++ b/base/base_java_memory_pressure_level_list.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_memory_pressure_level_list.target.darwin-x86_64.mk b/base/base_java_memory_pressure_level_list.target.darwin-x86_64.mk
new file mode 100644
index 0000000..6a922c7
--- /dev/null
+++ b/base/base_java_memory_pressure_level_list.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := base_base_java_memory_pressure_level_list_gyp
+LOCAL_MODULE_STEM := base_java_memory_pressure_level_list
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "base_base_gyp_base_java_memory_pressure_level_list_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'memory/memory_pressure_level_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/src/org/chromium/base/MemoryPressureLevelList.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/MemoryPressureLevelList.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/base/memory/memory_pressure_level_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/base; cd $(gyp_local_path)/base; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java" "--template=android/java/src/org/chromium/base/MemoryPressureLevelList.template"
+
+.PHONY: base_base_java_memory_pressure_level_list_gyp_rule_trigger
+base_base_java_memory_pressure_level_list_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	base_base_java_memory_pressure_level_list_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_java_memory_pressure_level_list_gyp
+
+# Alias gyp target name.
+.PHONY: base_java_memory_pressure_level_list
+base_java_memory_pressure_level_list: base_base_java_memory_pressure_level_list_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/base/base_java_memory_pressure_level_list.target.linux-arm.mk b/base/base_java_memory_pressure_level_list.target.linux-arm.mk
index ecf6444..a3d4c70 100644
--- a/base/base_java_memory_pressure_level_list.target.linux-arm.mk
+++ b/base/base_java_memory_pressure_level_list.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_memory_pressure_level_list.target.linux-mips.mk b/base/base_java_memory_pressure_level_list.target.linux-mips.mk
index c829249..2ab63ca 100644
--- a/base/base_java_memory_pressure_level_list.target.linux-mips.mk
+++ b/base/base_java_memory_pressure_level_list.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_memory_pressure_level_list.target.linux-x86.mk b/base/base_java_memory_pressure_level_list.target.linux-x86.mk
index 93daeee..cf46c27 100644
--- a/base/base_java_memory_pressure_level_list.target.linux-x86.mk
+++ b/base/base_java_memory_pressure_level_list.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_java_memory_pressure_level_list.target.linux-x86_64.mk b/base/base_java_memory_pressure_level_list.target.linux-x86_64.mk
new file mode 100644
index 0000000..6a922c7
--- /dev/null
+++ b/base/base_java_memory_pressure_level_list.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := base_base_java_memory_pressure_level_list_gyp
+LOCAL_MODULE_STEM := base_java_memory_pressure_level_list
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "base_base_gyp_base_java_memory_pressure_level_list_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'memory/memory_pressure_level_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/src/org/chromium/base/MemoryPressureLevelList.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/MemoryPressureLevelList.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/base/memory/memory_pressure_level_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/base; cd $(gyp_local_path)/base; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java" "--template=android/java/src/org/chromium/base/MemoryPressureLevelList.template"
+
+.PHONY: base_base_java_memory_pressure_level_list_gyp_rule_trigger
+base_base_java_memory_pressure_level_list_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/base/MemoryPressureLevelList.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	base_base_java_memory_pressure_level_list_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_java_memory_pressure_level_list_gyp
+
+# Alias gyp target name.
+.PHONY: base_java_memory_pressure_level_list
+base_java_memory_pressure_level_list: base_base_java_memory_pressure_level_list_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/base/base_jni_headers.target.darwin-arm.mk b/base/base_jni_headers.target.darwin-arm.mk
index 7786e83..90e4334 100644
--- a/base/base_jni_headers.target.darwin-arm.mk
+++ b/base/base_jni_headers.target.darwin-arm.mk
@@ -275,6 +275,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -357,6 +358,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_jni_headers.target.darwin-mips.mk b/base/base_jni_headers.target.darwin-mips.mk
index dce720c..789a160 100644
--- a/base/base_jni_headers.target.darwin-mips.mk
+++ b/base/base_jni_headers.target.darwin-mips.mk
@@ -274,6 +274,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -355,6 +356,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_jni_headers.target.darwin-x86.mk b/base/base_jni_headers.target.darwin-x86.mk
index 33abfbc..6ca134f 100644
--- a/base/base_jni_headers.target.darwin-x86.mk
+++ b/base/base_jni_headers.target.darwin-x86.mk
@@ -276,6 +276,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -358,6 +359,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_jni_headers.target.darwin-x86_64.mk b/base/base_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d41370d
--- /dev/null
+++ b/base/base_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,414 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := base_base_jni_headers_gyp
+LOCAL_MODULE_STEM := base_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "base_base_gyp_base_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/base/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['android/java/src/org/chromium/base/ApplicationStatus.java', 'android/java/src/org/chromium/base/BuildInfo.java', 'android/java/src/org/chromium/base/CommandLine.java', 'android/java/src/org/chromium/base/ContentUriUtils.java', 'android/java/src/org/chromium/base/CpuFeatures.java', 'android/java/src/org/chromium/base/ImportantFileWriterAndroid.java', 'android/java/src/org/chromium/base/library_loader/LibraryLoader.java', 'android/java/src/org/chromium/base/MemoryPressureListener.java', 'android/java/src/org/chromium/base/JavaHandlerThread.java', 'android/java/src/org/chromium/base/PathService.java', 'android/java/src/org/chromium/base/PathUtils.java', 'android/java/src/org/chromium/base/PowerMonitor.java', 'android/java/src/org/chromium/base/SystemMessageHandler.java', 'android/java/src/org/chromium/base/SysUtils.java', 'android/java/src/org/chromium/base/ThreadUtils.java', 'android/java/src/org/chromium/base/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/base/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ApplicationStatus.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ApplicationStatus.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/BuildInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/BuildInfo.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/CommandLine.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/CommandLine.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ContentUriUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ContentUriUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/CpuFeatures.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/CpuFeatures.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ImportantFileWriterAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/library_loader/LibraryLoader.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/MemoryPressureListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/MemoryPressureListener.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/JavaHandlerThread.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/JavaHandlerThread.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/PathService.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/PathService.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/PathUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/PathUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/PowerMonitor.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/PowerMonitor.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/SystemMessageHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/SystemMessageHandler.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/SysUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/SysUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ThreadUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ThreadUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/TraceEvent.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/TraceEvent.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h \
+	base_base_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: base_jni_headers
+base_jni_headers: base_base_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/base/base_jni_headers.target.linux-arm.mk b/base/base_jni_headers.target.linux-arm.mk
index 7786e83..90e4334 100644
--- a/base/base_jni_headers.target.linux-arm.mk
+++ b/base/base_jni_headers.target.linux-arm.mk
@@ -275,6 +275,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -357,6 +358,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_jni_headers.target.linux-mips.mk b/base/base_jni_headers.target.linux-mips.mk
index dce720c..789a160 100644
--- a/base/base_jni_headers.target.linux-mips.mk
+++ b/base/base_jni_headers.target.linux-mips.mk
@@ -274,6 +274,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -355,6 +356,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_jni_headers.target.linux-x86.mk b/base/base_jni_headers.target.linux-x86.mk
index 33abfbc..6ca134f 100644
--- a/base/base_jni_headers.target.linux-x86.mk
+++ b/base/base_jni_headers.target.linux-x86.mk
@@ -276,6 +276,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -358,6 +359,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_jni_headers.target.linux-x86_64.mk b/base/base_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..d41370d
--- /dev/null
+++ b/base/base_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,414 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := base_base_jni_headers_gyp
+LOCAL_MODULE_STEM := base_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "base_base_gyp_base_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/base/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['android/java/src/org/chromium/base/ApplicationStatus.java', 'android/java/src/org/chromium/base/BuildInfo.java', 'android/java/src/org/chromium/base/CommandLine.java', 'android/java/src/org/chromium/base/ContentUriUtils.java', 'android/java/src/org/chromium/base/CpuFeatures.java', 'android/java/src/org/chromium/base/ImportantFileWriterAndroid.java', 'android/java/src/org/chromium/base/library_loader/LibraryLoader.java', 'android/java/src/org/chromium/base/MemoryPressureListener.java', 'android/java/src/org/chromium/base/JavaHandlerThread.java', 'android/java/src/org/chromium/base/PathService.java', 'android/java/src/org/chromium/base/PathUtils.java', 'android/java/src/org/chromium/base/PowerMonitor.java', 'android/java/src/org/chromium/base/SystemMessageHandler.java', 'android/java/src/org/chromium/base/SysUtils.java', 'android/java/src/org/chromium/base/ThreadUtils.java', 'android/java/src/org/chromium/base/TraceEvent.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/base/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ApplicationStatus.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ApplicationStatus.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/BuildInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/BuildInfo.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/CommandLine.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/CommandLine.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ContentUriUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ContentUriUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/CpuFeatures.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/CpuFeatures.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ImportantFileWriterAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ImportantFileWriterAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/library_loader/LibraryLoader.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/MemoryPressureListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/MemoryPressureListener.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/JavaHandlerThread.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/JavaHandlerThread.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/PathService.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/PathService.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/PathUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/PathUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/PowerMonitor.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/PowerMonitor.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/SystemMessageHandler.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/SystemMessageHandler.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/SysUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/SysUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/ThreadUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/ThreadUtils.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h: $(LOCAL_PATH)/base/android/java/src/org/chromium/base/TraceEvent.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/base/jni; cd $(gyp_local_path)/base; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/base/TraceEvent.java --output_dir "$(gyp_shared_intermediate_dir)/base/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: base_base_jni_headers_gyp_rule_trigger
+base_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/base/jni/ApplicationStatus_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/BuildInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CommandLine_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ContentUriUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/CpuFeatures_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ImportantFileWriterAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/LibraryLoader_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/MemoryPressureListener_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/JavaHandlerThread_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathService_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PathUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/PowerMonitor_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SystemMessageHandler_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/SysUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/ThreadUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/base/jni/TraceEvent_jni.h \
+	base_base_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: base_jni_headers
+base_jni_headers: base_base_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/base/base_paths_win.cc b/base/base_paths_win.cc
index d4e11ae..509d5fd 100644
--- a/base/base_paths_win.cc
+++ b/base/base_paths_win.cc
@@ -191,6 +191,13 @@
       cur = cur.AppendASCII("User Pinned");
       cur = cur.AppendASCII("TaskBar");
       break;
+    case base::DIR_WINDOWS_FONTS:
+      if (FAILED(SHGetFolderPath(
+              NULL, CSIDL_FONTS, NULL, SHGFP_TYPE_CURRENT, system_buffer))) {
+        return false;
+      }
+      cur = FilePath(system_buffer);
+      break;
     default:
       return false;
   }
diff --git a/base/base_paths_win.h b/base/base_paths_win.h
index 1c44578..b042d08 100644
--- a/base/base_paths_win.h
+++ b/base/base_paths_win.h
@@ -41,6 +41,7 @@
                                   // of the Default user.
   DIR_TASKBAR_PINS,       // Directory for the shortcuts pinned to taskbar via
                           // base::win::TaskbarPinShortcutLink().
+  DIR_WINDOWS_FONTS,      // Usually C:\Windows\Fonts.
 
   PATH_WIN_END
 };
diff --git a/base/base_prefs.target.darwin-arm.mk b/base/base_prefs.target.darwin-arm.mk
index e4cf7d6..1c069d4 100644
--- a/base/base_prefs.target.darwin-arm.mk
+++ b/base/base_prefs.target.darwin-arm.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_prefs.target.darwin-mips.mk b/base/base_prefs.target.darwin-mips.mk
index 132c87e..c8ccbf7 100644
--- a/base/base_prefs.target.darwin-mips.mk
+++ b/base/base_prefs.target.darwin-mips.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_prefs.target.darwin-x86.mk b/base/base_prefs.target.darwin-x86.mk
index cdb1bda..181ce24 100644
--- a/base/base_prefs.target.darwin-x86.mk
+++ b/base/base_prefs.target.darwin-x86.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_prefs.target.darwin-x86_64.mk b/base/base_prefs.target.darwin-x86_64.mk
new file mode 100644
index 0000000..ffab75e
--- /dev/null
+++ b/base/base_prefs.target.darwin-x86_64.mk
@@ -0,0 +1,275 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_prefs_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/prefs/default_pref_store.cc \
+	base/prefs/json_pref_store.cc \
+	base/prefs/overlay_user_pref_store.cc \
+	base/prefs/pref_change_registrar.cc \
+	base/prefs/pref_member.cc \
+	base/prefs/pref_notifier_impl.cc \
+	base/prefs/pref_registry.cc \
+	base/prefs/pref_registry_simple.cc \
+	base/prefs/pref_service.cc \
+	base/prefs/pref_service_factory.cc \
+	base/prefs/pref_store.cc \
+	base/prefs/pref_value_map.cc \
+	base/prefs/pref_value_store.cc \
+	base/prefs/scoped_user_pref_update.cc \
+	base/prefs/value_map_pref_store.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DBASE_PREFS_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DBASE_PREFS_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_prefs_gyp
+
+# Alias gyp target name.
+.PHONY: base_prefs
+base_prefs: base_base_prefs_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/base_prefs.target.linux-arm.mk b/base/base_prefs.target.linux-arm.mk
index e4cf7d6..1c069d4 100644
--- a/base/base_prefs.target.linux-arm.mk
+++ b/base/base_prefs.target.linux-arm.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_prefs.target.linux-mips.mk b/base/base_prefs.target.linux-mips.mk
index 132c87e..c8ccbf7 100644
--- a/base/base_prefs.target.linux-mips.mk
+++ b/base/base_prefs.target.linux-mips.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_prefs.target.linux-x86.mk b/base/base_prefs.target.linux-x86.mk
index cdb1bda..181ce24 100644
--- a/base/base_prefs.target.linux-x86.mk
+++ b/base/base_prefs.target.linux-x86.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DBASE_PREFS_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_prefs.target.linux-x86_64.mk b/base/base_prefs.target.linux-x86_64.mk
new file mode 100644
index 0000000..ffab75e
--- /dev/null
+++ b/base/base_prefs.target.linux-x86_64.mk
@@ -0,0 +1,275 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_prefs_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/prefs/default_pref_store.cc \
+	base/prefs/json_pref_store.cc \
+	base/prefs/overlay_user_pref_store.cc \
+	base/prefs/pref_change_registrar.cc \
+	base/prefs/pref_member.cc \
+	base/prefs/pref_notifier_impl.cc \
+	base/prefs/pref_registry.cc \
+	base/prefs/pref_registry_simple.cc \
+	base/prefs/pref_service.cc \
+	base/prefs/pref_service_factory.cc \
+	base/prefs/pref_store.cc \
+	base/prefs/pref_value_map.cc \
+	base/prefs/pref_value_store.cc \
+	base/prefs/scoped_user_pref_update.cc \
+	base/prefs/value_map_pref_store.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DBASE_PREFS_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DBASE_PREFS_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_prefs_gyp
+
+# Alias gyp target name.
+.PHONY: base_prefs
+base_prefs: base_base_prefs_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/base_static.target.darwin-arm.mk b/base/base_static.target.darwin-arm.mk
index b14c9db..e7f0b83 100644
--- a/base/base_static.target.darwin-arm.mk
+++ b/base/base_static.target.darwin-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_static.target.darwin-mips.mk b/base/base_static.target.darwin-mips.mk
index 9e9223c..7c88d07 100644
--- a/base/base_static.target.darwin-mips.mk
+++ b/base/base_static.target.darwin-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -159,6 +160,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_static.target.darwin-x86.mk b/base/base_static.target.darwin-x86.mk
index 6d9790a..5645d20 100644
--- a/base/base_static.target.darwin-x86.mk
+++ b/base/base_static.target.darwin-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_static.target.darwin-x86_64.mk b/base/base_static.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a303d71
--- /dev/null
+++ b/base/base_static.target.darwin-x86_64.mk
@@ -0,0 +1,257 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_static_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/base_switches.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_static_gyp
+
+# Alias gyp target name.
+.PHONY: base_static
+base_static: base_base_static_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/base_static.target.linux-arm.mk b/base/base_static.target.linux-arm.mk
index b14c9db..e7f0b83 100644
--- a/base/base_static.target.linux-arm.mk
+++ b/base/base_static.target.linux-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_static.target.linux-mips.mk b/base/base_static.target.linux-mips.mk
index 9e9223c..7c88d07 100644
--- a/base/base_static.target.linux-mips.mk
+++ b/base/base_static.target.linux-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -159,6 +160,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_static.target.linux-x86.mk b/base/base_static.target.linux-x86.mk
index 6d9790a..5645d20 100644
--- a/base/base_static.target.linux-x86.mk
+++ b/base/base_static.target.linux-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/base/base_static.target.linux-x86_64.mk b/base/base_static.target.linux-x86_64.mk
new file mode 100644
index 0000000..a303d71
--- /dev/null
+++ b/base/base_static.target.linux-x86_64.mk
@@ -0,0 +1,257 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_base_static_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/base_switches.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_base_static_gyp
+
+# Alias gyp target name.
+.PHONY: base_static
+base_static: base_base_static_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index 2c93d53..e1f15cb 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -127,10 +127,6 @@
     return *copies_;
   }
 
-  int assigns() const {
-    return *assigns_;
-  }
-
  private:
   int* copies_;
   int* assigns_;
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index c83b6b5..16837df 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -196,19 +196,6 @@
 // If available, it would look like:
 //   __attribute__((format(wprintf, format_param, dots_param)))
 
-#if defined(__OBJC__)
-// Tell the compiler a function is using a +[NSString stringWithFormat:]
-// style format string. |format_param| is the one-based index of the format
-// string parameter; |dots_param| is the one-based index of the "..."
-// parameter. This should only be used when building Objective-C code.
-#if defined(COMPILER_GCC)
-#define NSSTRING_FORMAT(format_param, dots_param) \
-    __attribute__((format(__NSString__, format_param, dots_param)))
-#else
-#define NSSTRING_FORMAT(format_param, dots_param)
-#endif  // defined(COMPILER_GCC)
-#endif  // defined(__OBJC__)
-
 // MemorySanitizer annotations.
 #if defined(MEMORY_SANITIZER) && !defined(OS_NACL)
 #include <sanitizer/msan_interface.h>
@@ -230,15 +217,6 @@
 #endif  // defined(OS_WIN)
 #endif  // !defined(CDECL)
 
-// Macro for hinting that an expression is likely to be true.
-#if !defined(LIKELY)
-#if defined(COMPILER_GCC)
-#define LIKELY(x) __builtin_expect(!!(x), 1)
-#else
-#define LIKELY(x) (x)
-#endif  // defined(COMPILER_GCC)
-#endif  // !defined(LIKELY)
-
 // Macro for hinting that an expression is likely to be false.
 #if !defined(UNLIKELY)
 #if defined(COMPILER_GCC)
diff --git a/base/debug/proc_maps_linux.cc b/base/debug/proc_maps_linux.cc
index d9ff8c5..1e0209e 100644
--- a/base/debug/proc_maps_linux.cc
+++ b/base/debug/proc_maps_linux.cc
@@ -91,6 +91,7 @@
 
 bool ParseProcMaps(const std::string& input,
                    std::vector<MappedMemoryRegion>* regions_out) {
+  CHECK(regions_out);
   std::vector<MappedMemoryRegion> regions;
 
   // This isn't async safe nor terribly efficient, but it doesn't need to be at
@@ -101,8 +102,10 @@
   for (size_t i = 0; i < lines.size(); ++i) {
     // Due to splitting on '\n' the last line should be empty.
     if (i == lines.size() - 1) {
-      if (!lines[i].empty())
+      if (!lines[i].empty()) {
+        DLOG(WARNING) << "Last line not empty";
         return false;
+      }
       break;
     }
 
@@ -125,6 +128,7 @@
     if (sscanf(line, "%" SCNxPTR "-%" SCNxPTR " %4c %llx %hhx:%hhx %ld %n",
                &region.start, &region.end, permissions, &region.offset,
                &dev_major, &dev_minor, &inode, &path_index) < 7) {
+      DPLOG(WARNING) << "sscanf failed for line: " << line;
       return false;
     }
 
diff --git a/base/debug/proc_maps_linux_unittest.cc b/base/debug/proc_maps_linux_unittest.cc
index 7c2929f..fc8ced6 100644
--- a/base/debug/proc_maps_linux_unittest.cc
+++ b/base/debug/proc_maps_linux_unittest.cc
@@ -277,5 +277,37 @@
   }
 }
 
+TEST(ProcMapsTest, ParseProcMapsEmptyString) {
+  std::vector<MappedMemoryRegion> regions;
+  EXPECT_TRUE(ParseProcMaps("", &regions));
+  EXPECT_EQ(0ULL, regions.size());
+}
+
+// Testing a couple of remotely possible weird things in the input:
+// - Line ending with \r\n or \n\r.
+// - File name contains quotes.
+// - File name has whitespaces.
+TEST(ProcMapsTest, ParseProcMapsWeirdCorrectInput) {
+  std::vector<MappedMemoryRegion> regions;
+  const std::string kContents =
+    "00400000-0040b000 r-xp 00000000 fc:00 2106562 "
+      "               /bin/cat\r\n"
+    "7f53b7dad000-7f53b7f62000 r-xp 00000000 fc:00 263011 "
+      "       /lib/x86_64-linux-gnu/libc-2.15.so\n\r"
+    "7f53b816d000-7f53b818f000 r-xp 00000000 fc:00 264284 "
+      "        /lib/x86_64-linux-gnu/ld-2.15.so\n"
+    "7fff9c7ff000-7fff9c800000 r-xp 00000000 00:00 0 "
+      "               \"vd so\"\n"
+    "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 "
+      "               [vsys call]\n";
+  EXPECT_TRUE(ParseProcMaps(kContents, &regions));
+  EXPECT_EQ(5ULL, regions.size());
+  EXPECT_EQ("/bin/cat", regions[0].path);
+  EXPECT_EQ("/lib/x86_64-linux-gnu/libc-2.15.so", regions[1].path);
+  EXPECT_EQ("/lib/x86_64-linux-gnu/ld-2.15.so", regions[2].path);
+  EXPECT_EQ("\"vd so\"", regions[3].path);
+  EXPECT_EQ("[vsys call]", regions[4].path);
+}
+
 }  // namespace debug
 }  // namespace base
diff --git a/base/debug/stack_trace.h b/base/debug/stack_trace.h
index b0883c1..78f886a 100644
--- a/base/debug/stack_trace.h
+++ b/base/debug/stack_trace.h
@@ -27,6 +27,15 @@
 // unit_tests only! This is not thread-safe: only call from main thread.
 BASE_EXPORT bool EnableInProcessStackDumping();
 
+// A different version of EnableInProcessStackDumping that also works for
+// sandboxed processes.  For more details take a look at the description
+// of EnableInProcessStackDumping.
+// Calling this function on Linux opens /proc/self/maps and caches its
+// contents. In DEBUG builds, this function also opens the object files that
+// are loaded in memory and caches their file descriptors (this cannot be
+// done in official builds because it has security implications).
+BASE_EXPORT bool EnableInProcessStackDumpingForSandbox();
+
 // A stacktrace can be helpful in debugging. For example, you can include a
 // stacktrace member in a object (probably around #ifndef NDEBUG) so that you
 // can later see where the given object was created from.
diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc
index 3f0e95f..2d63a24 100644
--- a/base/debug/stack_trace_posix.cc
+++ b/base/debug/stack_trace_posix.cc
@@ -15,7 +15,10 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <map>
 #include <ostream>
+#include <string>
+#include <vector>
 
 #if defined(__GLIBCXX__)
 #include <cxxabi.h>
@@ -27,11 +30,14 @@
 
 #include "base/basictypes.h"
 #include "base/debug/debugger.h"
+#include "base/debug/proc_maps_linux.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
 
 #if defined(USE_SYMBOLIZE)
 #include "base/third_party/symbolize/symbolize.h"
@@ -115,14 +121,27 @@
 };
 
 void OutputPointer(void* pointer, BacktraceOutputHandler* handler) {
-  char buf[1024] = { '\0' };
-  handler->HandleOutput(" [0x");
+  // This should be more than enough to store a 64-bit number in hex:
+  // 16 hex digits + 1 for null-terminator.
+  char buf[17] = { '\0' };
+  handler->HandleOutput("0x");
   internal::itoa_r(reinterpret_cast<intptr_t>(pointer),
                    buf, sizeof(buf), 16, 12);
   handler->HandleOutput(buf);
-  handler->HandleOutput("]");
 }
 
+#if defined(USE_SYMBOLIZE)
+void OutputFrameId(intptr_t frame_id, BacktraceOutputHandler* handler) {
+  // Max unsigned 64-bit number in decimal has 20 digits (18446744073709551615).
+  // Hence, 30 digits should be more than enough to represent it in decimal
+  // (including the null-terminator).
+  char buf[30] = { '\0' };
+  handler->HandleOutput("#");
+  internal::itoa_r(frame_id, buf, sizeof(buf), 10, 1);
+  handler->HandleOutput(buf);
+}
+#endif  // defined(USE_SYMBOLIZE)
+
 void ProcessBacktrace(void *const *trace,
                       size_t size,
                       BacktraceOutputHandler* handler) {
@@ -131,6 +150,8 @@
 
 #if defined(USE_SYMBOLIZE)
   for (size_t i = 0; i < size; ++i) {
+    OutputFrameId(i, handler);
+    handler->HandleOutput(" ");
     OutputPointer(trace[i], handler);
     handler->HandleOutput(" ");
 
@@ -168,8 +189,9 @@
 
   if (!printed) {
     for (size_t i = 0; i < size; ++i) {
+      handler->HandleOutput(" [");
       OutputPointer(trace[i], handler);
-      handler->HandleOutput("\n");
+      handler->HandleOutput("]\n");
     }
   }
 #endif  // defined(USE_SYMBOLIZE)
@@ -438,6 +460,248 @@
 
 }  // namespace
 
+#if defined(USE_SYMBOLIZE)
+
+// class SandboxSymbolizeHelper.
+//
+// The purpose of this class is to prepare and install a "file open" callback
+// needed by the stack trace symbolization code
+// (base/third_party/symbolize/symbolize.h) so that it can function properly
+// in a sandboxed process.  The caveat is that this class must be instantiated
+// before the sandboxing is enabled so that it can get the chance to open all
+// the object files that are loaded in the virtual address space of the current
+// process.
+class SandboxSymbolizeHelper {
+ public:
+  // Returns the singleton instance.
+  static SandboxSymbolizeHelper* GetInstance() {
+    return Singleton<SandboxSymbolizeHelper>::get();
+  }
+
+ private:
+  friend struct DefaultSingletonTraits<SandboxSymbolizeHelper>;
+
+  SandboxSymbolizeHelper()
+      : is_initialized_(false) {
+    Init();
+  }
+
+  ~SandboxSymbolizeHelper() {
+    UnregisterCallback();
+    CloseObjectFiles();
+  }
+
+  // Returns a O_RDONLY file descriptor for |file_path| if it was opened
+  // sucessfully during the initialization.  The file is repositioned at
+  // offset 0.
+  // IMPORTANT: This function must be async-signal-safe because it can be
+  // called from a signal handler (symbolizing stack frames for a crash).
+  int GetFileDescriptor(const char* file_path) {
+    int fd = -1;
+
+#if !defined(NDEBUG)
+    if (file_path) {
+      // The assumption here is that iterating over std::map<std::string, int>
+      // using a const_iterator does not allocate dynamic memory, hense it is
+      // async-signal-safe.
+      std::map<std::string, int>::const_iterator it;
+      for (it = modules_.begin(); it != modules_.end(); ++it) {
+        if (strcmp((it->first).c_str(), file_path) == 0) {
+          // POSIX.1-2004 requires an implementation to guarantee that dup()
+          // is async-signal-safe.
+          fd = dup(it->second);
+          break;
+        }
+      }
+      // POSIX.1-2004 requires an implementation to guarantee that lseek()
+      // is async-signal-safe.
+      if (fd >= 0 && lseek(fd, 0, SEEK_SET) < 0) {
+        // Failed to seek.
+        fd = -1;
+      }
+    }
+#endif  // !defined(NDEBUG)
+
+    return fd;
+  }
+
+  // Searches for the object file (from /proc/self/maps) that contains
+  // the specified pc.  If found, sets |start_address| to the start address
+  // of where this object file is mapped in memory, sets the module base
+  // address into |base_address|, copies the object file name into
+  // |out_file_name|, and attempts to open the object file.  If the object
+  // file is opened successfully, returns the file descriptor.  Otherwise,
+  // returns -1.  |out_file_name_size| is the size of the file name buffer
+  // (including the null terminator).
+  // IMPORTANT: This function must be async-signal-safe because it can be
+  // called from a signal handler (symbolizing stack frames for a crash).
+  static int OpenObjectFileContainingPc(uint64_t pc, uint64_t& start_address,
+                                        uint64_t& base_address, char* file_path,
+                                        int file_path_size) {
+    // This method can only be called after the singleton is instantiated.
+    // This is ensured by the following facts:
+    // * This is the only static method in this class, it is private, and
+    //   the class has no friends (except for the DefaultSingletonTraits).
+    //   The compiler guarantees that it can only be called after the
+    //   singleton is instantiated.
+    // * This method is used as a callback for the stack tracing code and
+    //   the callback registration is done in the constructor, so logically
+    //   it cannot be called before the singleton is created.
+    SandboxSymbolizeHelper* instance = GetInstance();
+
+    // The assumption here is that iterating over
+    // std::vector<MappedMemoryRegion> using a const_iterator does not allocate
+    // dynamic memory, hence it is async-signal-safe.
+    std::vector<MappedMemoryRegion>::const_iterator it;
+    bool is_first = true;
+    for (it = instance->regions_.begin(); it != instance->regions_.end();
+         ++it, is_first = false) {
+      const MappedMemoryRegion& region = *it;
+      if (region.start <= pc && pc < region.end) {
+        start_address = region.start;
+        // Don't subtract 'start_address' from the first entry:
+        // * If a binary is compiled w/o -pie, then the first entry in
+        //   process maps is likely the binary itself (all dynamic libs
+        //   are mapped higher in address space). For such a binary,
+        //   instruction offset in binary coincides with the actual
+        //   instruction address in virtual memory (as code section
+        //   is mapped to a fixed memory range).
+        // * If a binary is compiled with -pie, all the modules are
+        //   mapped high at address space (in particular, higher than
+        //   shadow memory of the tool), so the module can't be the
+        //   first entry.
+        base_address = (is_first ? 0U : start_address) - region.offset;
+        if (file_path && file_path_size > 0) {
+          strncpy(file_path, region.path.c_str(), file_path_size);
+          // Ensure null termination.
+          file_path[file_path_size - 1] = '\0';
+        }
+        return instance->GetFileDescriptor(region.path.c_str());
+      }
+    }
+    return -1;
+  }
+
+  // Parses /proc/self/maps in order to compile a list of all object file names
+  // for the modules that are loaded in the current process.
+  // Returns true on success.
+  bool CacheMemoryRegions() {
+    // Reads /proc/self/maps.
+    std::string contents;
+    if (!ReadProcMaps(&contents)) {
+      LOG(ERROR) << "Failed to read /proc/self/maps";
+      return false;
+    }
+
+    // Parses /proc/self/maps.
+    if (!ParseProcMaps(contents, &regions_)) {
+      LOG(ERROR) << "Failed to parse the contents of /proc/self/maps";
+      return false;
+    }
+
+    is_initialized_ = true;
+    return true;
+  }
+
+  // Opens all object files and caches their file descriptors.
+  void OpenSymbolFiles() {
+    // Pre-opening and caching the file descriptors of all loaded modules is
+    // not considered safe for retail builds.  Hence it is only done in debug
+    // builds.  For more details, take a look at: http://crbug.com/341966
+    // Enabling this to release mode would require approval from the security
+    // team.
+#if !defined(NDEBUG)
+    // Open the object files for all read-only executable regions and cache
+    // their file descriptors.
+    std::vector<MappedMemoryRegion>::const_iterator it;
+    for (it = regions_.begin(); it != regions_.end(); ++it) {
+      const MappedMemoryRegion& region = *it;
+      // Only interesed in read-only executable regions.
+      if ((region.permissions & MappedMemoryRegion::READ) ==
+              MappedMemoryRegion::READ &&
+          (region.permissions & MappedMemoryRegion::WRITE) == 0 &&
+          (region.permissions & MappedMemoryRegion::EXECUTE) ==
+              MappedMemoryRegion::EXECUTE) {
+        if (region.path.empty()) {
+          // Skip regions with empty file names.
+          continue;
+        }
+        if (region.path[0] == '[') {
+          // Skip pseudo-paths, like [stack], [vdso], [heap], etc ...
+          continue;
+        }
+        // Avoid duplicates.
+        if (modules_.find(region.path) == modules_.end()) {
+          int fd = open(region.path.c_str(), O_RDONLY | O_CLOEXEC);
+          if (fd >= 0) {
+            modules_.insert(std::make_pair(region.path, fd));
+          } else {
+            LOG(WARNING) << "Failed to open file: " << region.path
+                         << "\n  Error: " << strerror(errno);
+          }
+        }
+      }
+    }
+#endif  // !defined(NDEBUG)
+  }
+
+  // Initializes and installs the symbolization callback.
+  void Init() {
+    if (CacheMemoryRegions()) {
+      OpenSymbolFiles();
+      google::InstallSymbolizeOpenObjectFileCallback(
+          &OpenObjectFileContainingPc);
+    }
+  }
+
+  // Unregister symbolization callback.
+  void UnregisterCallback() {
+    if (is_initialized_) {
+      google::InstallSymbolizeOpenObjectFileCallback(NULL);
+      is_initialized_ = false;
+    }
+  }
+
+  // Closes all file descriptors owned by this instance.
+  void CloseObjectFiles() {
+#if !defined(NDEBUG)
+    std::map<std::string, int>::iterator it;
+    for (it = modules_.begin(); it != modules_.end(); ++it) {
+      int ret = IGNORE_EINTR(close(it->second));
+      DCHECK(!ret);
+      it->second = -1;
+    }
+    modules_.clear();
+#endif  // !defined(NDEBUG)
+  }
+
+  // Set to true upon successful initialization.
+  bool is_initialized_;
+
+#if !defined(NDEBUG)
+  // Mapping from file name to file descriptor.  Includes file descriptors
+  // for all successfully opened object files and the file descriptor for
+  // /proc/self/maps.  This code is not safe for release builds so
+  // this is only done for DEBUG builds.
+  std::map<std::string, int> modules_;
+#endif  // !defined(NDEBUG)
+
+  // Cache for the process memory regions.  Produced by parsing the contents
+  // of /proc/self/maps cache.
+  std::vector<MappedMemoryRegion> regions_;
+
+  DISALLOW_COPY_AND_ASSIGN(SandboxSymbolizeHelper);
+};
+#endif  // USE_SYMBOLIZE
+
+bool EnableInProcessStackDumpingForSandbox() {
+#if defined(USE_SYMBOLIZE)
+  SandboxSymbolizeHelper::GetInstance();
+#endif  // USE_SYMBOLIZE
+
+  return EnableInProcessStackDumping();
+}
+
 bool EnableInProcessStackDumping() {
   // When running in an application, our code typically expects SIGPIPE
   // to be ignored.  Therefore, when testing that same code, it should run
@@ -462,7 +726,10 @@
   success &= (sigaction(SIGFPE, &action, NULL) == 0);
   success &= (sigaction(SIGBUS, &action, NULL) == 0);
   success &= (sigaction(SIGSEGV, &action, NULL) == 0);
+// On Linux, SIGSYS is reserved by the kernel for seccomp-bpf sandboxing.
+#if !defined(OS_LINUX)
   success &= (sigaction(SIGSYS, &action, NULL) == 0);
+#endif  // !defined(OS_LINUX)
 
   return success;
 }
diff --git a/base/files/file.cc b/base/files/file.cc
index cd167b1..2a2f843 100644
--- a/base/files/file.cc
+++ b/base/files/file.cc
@@ -20,7 +20,7 @@
 
 File::File()
     : file_(kInvalidPlatformFileValue),
-      error_details_(FILE_OK),
+      error_details_(FILE_ERROR_FAILED),
       created_(false),
       async_(false) {
 }
@@ -45,6 +45,13 @@
 #endif
 }
 
+File::File(Error error_details)
+    : file_(kInvalidPlatformFileValue),
+      error_details_(error_details),
+      created_(false),
+      async_(false) {
+}
+
 File::File(RValue other)
     : file_(other.object->TakePlatformFile()),
       error_details_(other.object->error_details()),
diff --git a/base/files/file.h b/base/files/file.h
index dc7616b..a4aea07 100644
--- a/base/files/file.h
+++ b/base/files/file.h
@@ -149,6 +149,9 @@
   // Takes ownership of |platform_file|.
   explicit File(PlatformFile platform_file);
 
+  // Creates an object with a specific error_details code.
+  explicit File(Error error_details);
+
   // Move constructor for C++03 move emulation of this type.
   File(RValue other);
 
diff --git a/base/files/file_unittest.cc b/base/files/file_unittest.cc
index 59cba31..468b2a8 100644
--- a/base/files/file_unittest.cc
+++ b/base/files/file_unittest.cc
@@ -17,6 +17,17 @@
   FilePath file_path = temp_dir.path().AppendASCII("create_file_1");
 
   {
+    // Don't create a File at all.
+    File file;
+    EXPECT_FALSE(file.IsValid());
+    EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details());
+
+    File file2(base::File::FILE_ERROR_TOO_MANY_OPENED);
+    EXPECT_FALSE(file2.IsValid());
+    EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
+  }
+
+  {
     // Open a file that doesn't exist.
     File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
     EXPECT_FALSE(file.IsValid());
diff --git a/base/memory/discardable_memory_allocator_android.cc b/base/memory/discardable_memory_allocator_android.cc
index 1588317..077a441 100644
--- a/base/memory/discardable_memory_allocator_android.cc
+++ b/base/memory/discardable_memory_allocator_android.cc
@@ -102,22 +102,16 @@
   return close(fd) == 0;
 }
 
-DiscardableMemoryLockStatus LockAshmemRegion(int fd,
-                                             size_t off,
-                                             size_t size,
-                                             const void* address) {
+DiscardableMemoryLockStatus LockAshmemRegion(int fd, size_t off, size_t size) {
   const int result = ashmem_pin_region(fd, off, size);
-  DCHECK_EQ(0, mprotect(address, size, PROT_READ | PROT_WRITE));
   return result == ASHMEM_WAS_PURGED ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
                                      : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
 }
 
-bool UnlockAshmemRegion(int fd, size_t off, size_t size, const void* address) {
+bool UnlockAshmemRegion(int fd, size_t off, size_t size) {
   const int failed = ashmem_unpin_region(fd, off, size);
   if (failed)
     DLOG(ERROR) << "Failed to unpin memory.";
-  // This allows us to catch accesses to unlocked memory.
-  DCHECK_EQ(0, mprotect(address, size, PROT_NONE));
   return !failed;
 }
 
@@ -150,13 +144,13 @@
   virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
     DCHECK(!locked_);
     locked_ = true;
-    return LockAshmemRegion(fd_, offset_, size_, address_);
+    return LockAshmemRegion(fd_, offset_, size_);
   }
 
   virtual void Unlock() OVERRIDE {
     DCHECK(locked_);
     locked_ = false;
-    UnlockAshmemRegion(fd_, offset_, size_, address_);
+    UnlockAshmemRegion(fd_, offset_, size_);
   }
 
   virtual void* Memory() const OVERRIDE {
@@ -335,7 +329,7 @@
 
     const size_t offset =
         static_cast<char*>(reused_chunk.start) - static_cast<char*>(base_);
-    LockAshmemRegion(fd_, offset, reused_chunk_size, reused_chunk.start);
+    LockAshmemRegion(fd_, offset, reused_chunk_size);
     scoped_ptr<DiscardableMemory> memory(
         new DiscardableAshmemChunk(this, fd_, reused_chunk.start, offset,
                                    reused_chunk_size));
@@ -481,7 +475,7 @@
 
 DiscardableMemoryAllocator::DiscardableAshmemChunk::~DiscardableAshmemChunk() {
   if (locked_)
-    UnlockAshmemRegion(fd_, offset_, size_, address_);
+    UnlockAshmemRegion(fd_, offset_, size_);
   ashmem_region_->OnChunkDeletion(address_, size_);
 }
 
diff --git a/base/memory/discardable_memory_emulated.cc b/base/memory/discardable_memory_emulated.cc
index be756d6..82f887f 100644
--- a/base/memory/discardable_memory_emulated.cc
+++ b/base/memory/discardable_memory_emulated.cc
@@ -5,13 +5,13 @@
 #include "base/memory/discardable_memory_emulated.h"
 
 #include "base/lazy_instance.h"
-#include "base/memory/discardable_memory_provider.h"
+#include "base/memory/discardable_memory_manager.h"
 
 namespace base {
 
 namespace {
 
-base::LazyInstance<internal::DiscardableMemoryProvider>::Leaky g_provider =
+base::LazyInstance<internal::DiscardableMemoryManager>::Leaky g_manager =
     LAZY_INSTANCE_INITIALIZER;
 
 }  // namespace
@@ -20,28 +20,28 @@
 
 DiscardableMemoryEmulated::DiscardableMemoryEmulated(size_t size)
     : is_locked_(false) {
-  g_provider.Pointer()->Register(this, size);
+  g_manager.Pointer()->Register(this, size);
 }
 
 DiscardableMemoryEmulated::~DiscardableMemoryEmulated() {
   if (is_locked_)
     Unlock();
-  g_provider.Pointer()->Unregister(this);
+  g_manager.Pointer()->Unregister(this);
 }
 
 // static
 void DiscardableMemoryEmulated::RegisterMemoryPressureListeners() {
-  g_provider.Pointer()->RegisterMemoryPressureListener();
+  g_manager.Pointer()->RegisterMemoryPressureListener();
 }
 
 // static
 void DiscardableMemoryEmulated::UnregisterMemoryPressureListeners() {
-  g_provider.Pointer()->UnregisterMemoryPressureListener();
+  g_manager.Pointer()->UnregisterMemoryPressureListener();
 }
 
 // static
 void DiscardableMemoryEmulated::PurgeForTesting() {
-  g_provider.Pointer()->PurgeAll();
+  g_manager.Pointer()->PurgeAll();
 }
 
 bool DiscardableMemoryEmulated::Initialize() {
@@ -52,7 +52,7 @@
   DCHECK(!is_locked_);
 
   bool purged = false;
-  memory_ = g_provider.Pointer()->Acquire(this, &purged);
+  memory_ = g_manager.Pointer()->Acquire(this, &purged);
   if (!memory_)
     return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
 
@@ -63,7 +63,7 @@
 
 void DiscardableMemoryEmulated::Unlock() {
   DCHECK(is_locked_);
-  g_provider.Pointer()->Release(this, memory_.Pass());
+  g_manager.Pointer()->Release(this, memory_.Pass());
   is_locked_ = false;
 }
 
diff --git a/base/memory/discardable_memory_manager.cc b/base/memory/discardable_memory_manager.cc
new file mode 100644
index 0000000..c1b9f36
--- /dev/null
+++ b/base/memory/discardable_memory_manager.cc
@@ -0,0 +1,227 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/discardable_memory_manager.h"
+
+#include "base/bind.h"
+#include "base/containers/hash_tables.h"
+#include "base/containers/mru_cache.h"
+#include "base/debug/trace_event.h"
+#include "base/synchronization/lock.h"
+#include "base/sys_info.h"
+
+namespace base {
+namespace internal {
+
+namespace {
+
+// This is admittedly pretty magical. It's approximately enough memory for four
+// 2560x1600 images.
+static const size_t kDefaultDiscardableMemoryLimit = 64 * 1024 * 1024;
+static const size_t kDefaultBytesToKeepUnderModeratePressure =
+    kDefaultDiscardableMemoryLimit / 4;
+
+}  // namespace
+
+DiscardableMemoryManager::DiscardableMemoryManager()
+    : allocations_(AllocationMap::NO_AUTO_EVICT),
+      bytes_allocated_(0),
+      discardable_memory_limit_(kDefaultDiscardableMemoryLimit),
+      bytes_to_keep_under_moderate_pressure_(
+          kDefaultBytesToKeepUnderModeratePressure) {
+}
+
+DiscardableMemoryManager::~DiscardableMemoryManager() {
+  DCHECK(allocations_.empty());
+  DCHECK_EQ(0u, bytes_allocated_);
+}
+
+void DiscardableMemoryManager::RegisterMemoryPressureListener() {
+  AutoLock lock(lock_);
+  DCHECK(base::MessageLoop::current());
+  DCHECK(!memory_pressure_listener_);
+  memory_pressure_listener_.reset(
+      new MemoryPressureListener(
+          base::Bind(&DiscardableMemoryManager::OnMemoryPressure,
+                     Unretained(this))));
+}
+
+void DiscardableMemoryManager::UnregisterMemoryPressureListener() {
+  AutoLock lock(lock_);
+  DCHECK(memory_pressure_listener_);
+  memory_pressure_listener_.reset();
+}
+
+void DiscardableMemoryManager::SetDiscardableMemoryLimit(size_t bytes) {
+  AutoLock lock(lock_);
+  discardable_memory_limit_ = bytes;
+  EnforcePolicyWithLockAcquired();
+}
+
+void DiscardableMemoryManager::SetBytesToKeepUnderModeratePressure(
+    size_t bytes) {
+  AutoLock lock(lock_);
+  bytes_to_keep_under_moderate_pressure_ = bytes;
+}
+
+void DiscardableMemoryManager::Register(
+    const DiscardableMemory* discardable, size_t bytes) {
+  AutoLock lock(lock_);
+  // A registered memory listener is currently required. This DCHECK can be
+  // moved or removed if we decide that it's useful to relax this condition.
+  // TODO(reveman): Enable this DCHECK when skia and blink are able to
+  // register memory pressure listeners. crbug.com/333907
+  // DCHECK(memory_pressure_listener_);
+  DCHECK(allocations_.Peek(discardable) == allocations_.end());
+  allocations_.Put(discardable, Allocation(bytes));
+}
+
+void DiscardableMemoryManager::Unregister(
+    const DiscardableMemory* discardable) {
+  AutoLock lock(lock_);
+  AllocationMap::iterator it = allocations_.Peek(discardable);
+  if (it == allocations_.end())
+    return;
+
+  if (it->second.memory) {
+    size_t bytes = it->second.bytes;
+    DCHECK_LE(bytes, bytes_allocated_);
+    bytes_allocated_ -= bytes;
+    free(it->second.memory);
+  }
+  allocations_.Erase(it);
+}
+
+scoped_ptr<uint8, FreeDeleter> DiscardableMemoryManager::Acquire(
+    const DiscardableMemory* discardable,
+    bool* purged) {
+  AutoLock lock(lock_);
+  // NB: |allocations_| is an MRU cache, and use of |Get| here updates that
+  // cache.
+  AllocationMap::iterator it = allocations_.Get(discardable);
+  CHECK(it != allocations_.end());
+
+  if (it->second.memory) {
+    scoped_ptr<uint8, FreeDeleter> memory(it->second.memory);
+    it->second.memory = NULL;
+    *purged = false;
+    return memory.Pass();
+  }
+
+  size_t bytes = it->second.bytes;
+  if (!bytes)
+    return scoped_ptr<uint8, FreeDeleter>();
+
+  if (discardable_memory_limit_) {
+    size_t limit = 0;
+    if (bytes < discardable_memory_limit_)
+      limit = discardable_memory_limit_ - bytes;
+
+    PurgeLRUWithLockAcquiredUntilUsageIsWithin(limit);
+  }
+
+  // Check for overflow.
+  if (std::numeric_limits<size_t>::max() - bytes < bytes_allocated_)
+    return scoped_ptr<uint8, FreeDeleter>();
+
+  scoped_ptr<uint8, FreeDeleter> memory(static_cast<uint8*>(malloc(bytes)));
+  if (!memory)
+    return scoped_ptr<uint8, FreeDeleter>();
+
+  bytes_allocated_ += bytes;
+  *purged = true;
+  return memory.Pass();
+}
+
+void DiscardableMemoryManager::Release(
+    const DiscardableMemory* discardable,
+    scoped_ptr<uint8, FreeDeleter> memory) {
+  AutoLock lock(lock_);
+  // NB: |allocations_| is an MRU cache, and use of |Get| here updates that
+  // cache.
+  AllocationMap::iterator it = allocations_.Get(discardable);
+  CHECK(it != allocations_.end());
+
+  DCHECK(!it->second.memory);
+  it->second.memory = memory.release();
+
+  EnforcePolicyWithLockAcquired();
+}
+
+void DiscardableMemoryManager::PurgeAll() {
+  AutoLock lock(lock_);
+  PurgeLRUWithLockAcquiredUntilUsageIsWithin(0);
+}
+
+bool DiscardableMemoryManager::IsRegisteredForTest(
+    const DiscardableMemory* discardable) const {
+  AutoLock lock(lock_);
+  AllocationMap::const_iterator it = allocations_.Peek(discardable);
+  return it != allocations_.end();
+}
+
+bool DiscardableMemoryManager::CanBePurgedForTest(
+    const DiscardableMemory* discardable) const {
+  AutoLock lock(lock_);
+  AllocationMap::const_iterator it = allocations_.Peek(discardable);
+  return it != allocations_.end() && it->second.memory;
+}
+
+size_t DiscardableMemoryManager::GetBytesAllocatedForTest() const {
+  AutoLock lock(lock_);
+  return bytes_allocated_;
+}
+
+void DiscardableMemoryManager::OnMemoryPressure(
+    MemoryPressureListener::MemoryPressureLevel pressure_level) {
+  switch (pressure_level) {
+    case MemoryPressureListener::MEMORY_PRESSURE_MODERATE:
+      Purge();
+      return;
+    case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL:
+      PurgeAll();
+      return;
+  }
+
+  NOTREACHED();
+}
+
+void DiscardableMemoryManager::Purge() {
+  AutoLock lock(lock_);
+
+  PurgeLRUWithLockAcquiredUntilUsageIsWithin(
+      bytes_to_keep_under_moderate_pressure_);
+}
+
+void DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
+    size_t limit) {
+  TRACE_EVENT1(
+      "base",
+      "DiscardableMemoryManager::PurgeLRUWithLockAcquiredUntilUsageIsWithin",
+      "limit", limit);
+
+  lock_.AssertAcquired();
+
+  for (AllocationMap::reverse_iterator it = allocations_.rbegin();
+       it != allocations_.rend();
+       ++it) {
+    if (bytes_allocated_ <= limit)
+      break;
+    if (!it->second.memory)
+      continue;
+
+    size_t bytes = it->second.bytes;
+    DCHECK_LE(bytes, bytes_allocated_);
+    bytes_allocated_ -= bytes;
+    free(it->second.memory);
+    it->second.memory = NULL;
+  }
+}
+
+void DiscardableMemoryManager::EnforcePolicyWithLockAcquired() {
+  PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_);
+}
+
+}  // namespace internal
+}  // namespace base
diff --git a/base/memory/discardable_memory_manager.h b/base/memory/discardable_memory_manager.h
new file mode 100644
index 0000000..2b72c51
--- /dev/null
+++ b/base/memory/discardable_memory_manager.h
@@ -0,0 +1,150 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_
+#define BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_
+
+#include "base/base_export.h"
+#include "base/containers/hash_tables.h"
+#include "base/containers/mru_cache.h"
+#include "base/memory/memory_pressure_listener.h"
+#include "base/synchronization/lock.h"
+
+namespace base {
+class DiscardableMemory;
+}  // namespace base
+
+#if defined(COMPILER_GCC)
+namespace BASE_HASH_NAMESPACE {
+template <>
+struct hash<const base::DiscardableMemory*> {
+  size_t operator()(const base::DiscardableMemory* ptr) const {
+    return hash<size_t>()(reinterpret_cast<size_t>(ptr));
+  }
+};
+}  // namespace BASE_HASH_NAMESPACE
+#endif  // COMPILER
+
+namespace base {
+namespace internal {
+
+// The DiscardableMemoryManager manages a collection of emulated
+// DiscardableMemory instances. It is used on platforms that do not support
+// discardable memory natively. It keeps track of all DiscardableMemory
+// instances (in case they need to be purged), and the total amount of
+// allocated memory (in case this forces a purge).
+//
+// When notified of memory pressure, the manager either purges the LRU
+// memory -- if the pressure is moderate -- or all discardable memory
+// if the pressure is critical.
+//
+// NB - this class is an implementation detail. It has been exposed for testing
+// purposes. You should not need to use this class directly.
+class BASE_EXPORT_PRIVATE DiscardableMemoryManager {
+ public:
+  DiscardableMemoryManager();
+  ~DiscardableMemoryManager();
+
+  // Call this to register memory pressure listener. Must be called on a
+  // thread with a MessageLoop current.
+  void RegisterMemoryPressureListener();
+
+  // Call this to unregister memory pressure listener.
+  void UnregisterMemoryPressureListener();
+
+  // The maximum number of bytes of discardable memory that may be allocated
+  // before we force a purge. If this amount is zero, it is interpreted as
+  // having no limit at all.
+  void SetDiscardableMemoryLimit(size_t bytes);
+
+  // Sets the amount of memory to keep when we're under moderate pressure.
+  void SetBytesToKeepUnderModeratePressure(size_t bytes);
+
+  // Adds the given discardable memory to the manager's collection.
+  void Register(const DiscardableMemory* discardable, size_t bytes);
+
+  // Removes the given discardable memory from the manager's collection.
+  void Unregister(const DiscardableMemory* discardable);
+
+  // Returns NULL if an error occurred. Otherwise, returns the backing buffer
+  // and sets |purged| to indicate whether or not the backing buffer has been
+  // purged since last use.
+  scoped_ptr<uint8, FreeDeleter> Acquire(
+      const DiscardableMemory* discardable, bool* purged);
+
+  // Release a previously acquired backing buffer. This gives the buffer back
+  // to the manager where it can be purged if necessary.
+  void Release(const DiscardableMemory* discardable,
+               scoped_ptr<uint8, FreeDeleter> memory);
+
+  // Purges all discardable memory.
+  void PurgeAll();
+
+  // Returns true if discardable memory has been added to the manager's
+  // collection. This should only be used by tests.
+  bool IsRegisteredForTest(const DiscardableMemory* discardable) const;
+
+  // Returns true if discardable memory can be purged. This should only
+  // be used by tests.
+  bool CanBePurgedForTest(const DiscardableMemory* discardable) const;
+
+  // Returns total amount of allocated discardable memory. This should only
+  // be used by tests.
+  size_t GetBytesAllocatedForTest() const;
+
+ private:
+  struct Allocation {
+   explicit Allocation(size_t bytes)
+       : bytes(bytes),
+         memory(NULL) {
+   }
+
+    size_t bytes;
+    uint8* memory;
+  };
+  typedef HashingMRUCache<const DiscardableMemory*, Allocation> AllocationMap;
+
+  // This can be called as a hint that the system is under memory pressure.
+  void OnMemoryPressure(
+      MemoryPressureListener::MemoryPressureLevel pressure_level);
+
+  // Purges until discardable memory usage is within
+  // |bytes_to_keep_under_moderate_pressure_|.
+  void Purge();
+
+  // Purges least recently used memory until usage is less or equal to |limit|.
+  // Caller must acquire |lock_| prior to calling this function.
+  void PurgeLRUWithLockAcquiredUntilUsageIsWithin(size_t limit);
+
+  // Ensures that we don't allocate beyond our memory limit.
+  // Caller must acquire |lock_| prior to calling this function.
+  void EnforcePolicyWithLockAcquired();
+
+  // Needs to be held when accessing members.
+  mutable Lock lock_;
+
+  // A MRU cache of all allocated bits of discardable memory. Used for purging.
+  AllocationMap allocations_;
+
+  // The total amount of allocated discardable memory.
+  size_t bytes_allocated_;
+
+  // The maximum number of bytes of discardable memory that may be allocated.
+  size_t discardable_memory_limit_;
+
+  // Under moderate memory pressure, we will purge until usage is within this
+  // limit.
+  size_t bytes_to_keep_under_moderate_pressure_;
+
+  // Allows us to be respond when the system reports that it is under memory
+  // pressure.
+  scoped_ptr<MemoryPressureListener> memory_pressure_listener_;
+
+  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryManager);
+};
+
+}  // namespace internal
+}  // namespace base
+
+#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_MANAGER_H_
diff --git a/base/memory/discardable_memory_manager_unittest.cc b/base/memory/discardable_memory_manager_unittest.cc
new file mode 100644
index 0000000..95e7c13
--- /dev/null
+++ b/base/memory/discardable_memory_manager_unittest.cc
@@ -0,0 +1,410 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/discardable_memory_manager.h"
+
+#include "base/bind.h"
+#include "base/memory/discardable_memory.h"
+#include "base/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+
+class DiscardableMemoryManagerTestBase {
+ public:
+  class TestDiscardableMemory : public DiscardableMemory {
+   public:
+    TestDiscardableMemory(
+        internal::DiscardableMemoryManager* manager, size_t size)
+        : manager_(manager),
+          is_locked_(false) {
+      manager_->Register(this, size);
+    }
+
+    virtual ~TestDiscardableMemory() {
+      if (is_locked_)
+        Unlock();
+      manager_->Unregister(this);
+    }
+
+    // Overridden from DiscardableMemory:
+    virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
+      DCHECK(!is_locked_);
+
+      bool purged = false;
+      memory_ = manager_->Acquire(this, &purged);
+      if (!memory_)
+        return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
+
+      is_locked_ = true;
+      return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
+                    : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
+    }
+    virtual void Unlock() OVERRIDE {
+      DCHECK(is_locked_);
+      manager_->Release(this, memory_.Pass());
+      is_locked_ = false;
+    }
+    virtual void* Memory() const OVERRIDE {
+      DCHECK(memory_);
+      return memory_.get();
+    }
+
+   private:
+    internal::DiscardableMemoryManager* manager_;
+    scoped_ptr<uint8, FreeDeleter> memory_;
+    bool is_locked_;
+
+    DISALLOW_COPY_AND_ASSIGN(TestDiscardableMemory);
+  };
+
+  DiscardableMemoryManagerTestBase()
+      : manager_(new internal::DiscardableMemoryManager) {
+    manager_->RegisterMemoryPressureListener();
+  }
+
+ protected:
+  bool IsRegistered(const DiscardableMemory* discardable) {
+    return manager_->IsRegisteredForTest(discardable);
+  }
+
+  bool CanBePurged(const DiscardableMemory* discardable) {
+    return manager_->CanBePurgedForTest(discardable);
+  }
+
+  size_t BytesAllocated() const {
+    return manager_->GetBytesAllocatedForTest();
+  }
+
+  void* Memory(const DiscardableMemory* discardable) const {
+    return discardable->Memory();
+  }
+
+  void SetDiscardableMemoryLimit(size_t bytes) {
+    manager_->SetDiscardableMemoryLimit(bytes);
+  }
+
+  void SetBytesToKeepUnderModeratePressure(size_t bytes) {
+    manager_->SetBytesToKeepUnderModeratePressure(bytes);
+  }
+
+  scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size) {
+    scoped_ptr<TestDiscardableMemory> memory(
+        new TestDiscardableMemory(manager_.get(), size));
+    if (memory->Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_PURGED)
+      return scoped_ptr<DiscardableMemory>();
+    return memory.PassAs<DiscardableMemory>();
+  }
+
+ private:
+  MessageLoopForIO message_loop_;
+  scoped_ptr<internal::DiscardableMemoryManager> manager_;
+};
+
+class DiscardableMemoryManagerTest
+    : public DiscardableMemoryManagerTestBase,
+      public testing::Test {
+ public:
+  DiscardableMemoryManagerTest() {}
+};
+
+TEST_F(DiscardableMemoryManagerTest, CreateLockedMemory) {
+  size_t size = 1024;
+  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+  EXPECT_TRUE(IsRegistered(discardable.get()));
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+  EXPECT_EQ(1024u, BytesAllocated());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+}
+
+TEST_F(DiscardableMemoryManagerTest, CreateLockedMemoryZeroSize) {
+  size_t size = 0;
+  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+  EXPECT_FALSE(discardable);
+  EXPECT_FALSE(IsRegistered(discardable.get()));
+  EXPECT_EQ(0u, BytesAllocated());
+}
+
+TEST_F(DiscardableMemoryManagerTest, LockAfterUnlock) {
+  size_t size = 1024;
+  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+  EXPECT_TRUE(IsRegistered(discardable.get()));
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+  EXPECT_EQ(1024u, BytesAllocated());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+
+  // Now unlock so we can lock later.
+  discardable->Unlock();
+  EXPECT_TRUE(CanBePurged(discardable.get()));
+
+  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable->Lock());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+}
+
+TEST_F(DiscardableMemoryManagerTest, LockAfterPurge) {
+  size_t size = 1024;
+  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+  EXPECT_TRUE(IsRegistered(discardable.get()));
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+  EXPECT_EQ(1024u, BytesAllocated());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+
+  // Now unlock so we can lock later.
+  discardable->Unlock();
+  EXPECT_TRUE(CanBePurged(discardable.get()));
+
+  // Force the system to purge.
+  MemoryPressureListener::NotifyMemoryPressure(
+      MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
+
+  // Required because ObserverListThreadSafe notifies via PostTask.
+  RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable->Lock());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+}
+
+TEST_F(DiscardableMemoryManagerTest, LockAfterPurgeAndCannotReallocate) {
+  size_t size = 1024;
+  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+  EXPECT_TRUE(IsRegistered(discardable.get()));
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+  EXPECT_EQ(1024u, BytesAllocated());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+
+  // Now unlock so we can lock later.
+  discardable->Unlock();
+  EXPECT_TRUE(CanBePurged(discardable.get()));
+
+  // Set max allowed allocation to 1 byte. This will make cause the memory
+  // to be purged.
+  SetDiscardableMemoryLimit(1);
+
+  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable->Lock());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+}
+
+TEST_F(DiscardableMemoryManagerTest, Overflow) {
+  {
+    size_t size = 1024;
+    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+    EXPECT_TRUE(IsRegistered(discardable.get()));
+    EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+    EXPECT_EQ(1024u, BytesAllocated());
+
+    size_t massive_size = std::numeric_limits<size_t>::max();
+    const scoped_ptr<DiscardableMemory> massive_discardable(
+        CreateLockedMemory(massive_size));
+    EXPECT_FALSE(massive_discardable);
+    EXPECT_EQ(1024u, BytesAllocated());
+  }
+  EXPECT_EQ(0u, BytesAllocated());
+}
+
+class PermutationTestData {
+ public:
+  PermutationTestData(unsigned d0, unsigned d1, unsigned d2) {
+    ordering_[0] = d0;
+    ordering_[1] = d1;
+    ordering_[2] = d2;
+  }
+
+  const unsigned* ordering() const { return ordering_; }
+
+ private:
+  unsigned ordering_[3];
+};
+
+class DiscardableMemoryManagerPermutationTest
+    : public DiscardableMemoryManagerTestBase,
+      public testing::TestWithParam<PermutationTestData> {
+ public:
+  DiscardableMemoryManagerPermutationTest() {}
+
+ protected:
+  // Use discardable memory in order specified by ordering parameter.
+  void CreateAndUseDiscardableMemory() {
+    for (int i = 0; i < 3; ++i) {
+      discardables_[i] = CreateLockedMemory(1024);
+      EXPECT_TRUE(discardables_[i]);
+      EXPECT_NE(static_cast<void*>(NULL), Memory(discardables_[i].get()));
+      discardables_[i]->Unlock();
+    }
+    for (int i = 0; i < 3; ++i) {
+      int index = GetParam().ordering()[i];
+      EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED,
+                discardables_[index]->Lock());
+      // Leave i == 0 locked.
+      if (i > 0)
+        discardables_[index]->Unlock();
+    }
+  }
+
+  DiscardableMemory* discardable(unsigned position) {
+    return discardables_[GetParam().ordering()[position]].get();
+  }
+
+ private:
+  scoped_ptr<DiscardableMemory> discardables_[3];
+};
+
+// Verify that memory was discarded in the correct order after applying
+// memory pressure.
+TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedModeratePressure) {
+  CreateAndUseDiscardableMemory();
+
+  SetBytesToKeepUnderModeratePressure(1024);
+  SetDiscardableMemoryLimit(2048);
+
+  MemoryPressureListener::NotifyMemoryPressure(
+      MemoryPressureListener::MEMORY_PRESSURE_MODERATE);
+  RunLoop().RunUntilIdle();
+
+  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, discardable(2)->Lock());
+  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(1)->Lock());
+  // 0 should still be locked.
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0)));
+}
+
+// Verify that memory was discarded in the correct order after changing
+// memory limit.
+TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedExceedLimit) {
+  CreateAndUseDiscardableMemory();
+
+  SetBytesToKeepUnderModeratePressure(1024);
+  SetDiscardableMemoryLimit(2048);
+
+  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, discardable(2)->Lock());
+  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(1)->Lock());
+  // 0 should still be locked.
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0)));
+}
+
+// Verify that no more memory than necessary was discarded after changing
+// memory limit.
+TEST_P(DiscardableMemoryManagerPermutationTest, LRUDiscardedAmount) {
+  SetBytesToKeepUnderModeratePressure(2048);
+  SetDiscardableMemoryLimit(4096);
+
+  CreateAndUseDiscardableMemory();
+
+  SetDiscardableMemoryLimit(2048);
+
+  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(2)->Lock());
+  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable(1)->Lock());
+  // 0 should still be locked.
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0)));
+}
+
+TEST_P(DiscardableMemoryManagerPermutationTest,
+       CriticalPressureFreesAllUnlocked) {
+  CreateAndUseDiscardableMemory();
+
+  MemoryPressureListener::NotifyMemoryPressure(
+      MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
+  RunLoop().RunUntilIdle();
+
+  for (int i = 0; i < 3; ++i) {
+    if (i == 0)
+      EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(i)));
+    else
+      EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable(i)->Lock());
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(DiscardableMemoryManagerPermutationTests,
+                        DiscardableMemoryManagerPermutationTest,
+                        ::testing::Values(PermutationTestData(0, 1, 2),
+                                          PermutationTestData(0, 2, 1),
+                                          PermutationTestData(1, 0, 2),
+                                          PermutationTestData(1, 2, 0),
+                                          PermutationTestData(2, 0, 1),
+                                          PermutationTestData(2, 1, 0)));
+
+TEST_F(DiscardableMemoryManagerTest, NormalDestruction) {
+  {
+    size_t size = 1024;
+    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+    EXPECT_TRUE(IsRegistered(discardable.get()));
+    EXPECT_EQ(1024u, BytesAllocated());
+  }
+  EXPECT_EQ(0u, BytesAllocated());
+}
+
+TEST_F(DiscardableMemoryManagerTest, DestructionWhileLocked) {
+  {
+    size_t size = 1024;
+    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+    EXPECT_TRUE(IsRegistered(discardable.get()));
+    EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+    EXPECT_EQ(1024u, BytesAllocated());
+    EXPECT_FALSE(CanBePurged(discardable.get()));
+  }
+  // Should have ignored the "locked" status and freed the discardable memory.
+  EXPECT_EQ(0u, BytesAllocated());
+}
+
+#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
+// Death tests are not supported with Android APKs.
+TEST_F(DiscardableMemoryManagerTest, UnlockedMemoryAccessCrashesInDebugMode) {
+  size_t size = 1024;
+  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+  EXPECT_TRUE(IsRegistered(discardable.get()));
+  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+  EXPECT_EQ(1024u, BytesAllocated());
+  EXPECT_FALSE(CanBePurged(discardable.get()));
+  discardable->Unlock();
+  EXPECT_TRUE(CanBePurged(discardable.get()));
+  // We *must* die if we are asked to vend a pointer to unlocked memory.
+  EXPECT_DEATH(discardable->Memory(), ".*Check failed.*");
+}
+#endif
+
+class ThreadedDiscardableMemoryManagerTest
+    : public DiscardableMemoryManagerTest {
+ public:
+  ThreadedDiscardableMemoryManagerTest()
+      : memory_usage_thread_("memory_usage_thread"),
+        thread_sync_(true, false) {
+  }
+
+  virtual void SetUp() OVERRIDE {
+    memory_usage_thread_.Start();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    memory_usage_thread_.Stop();
+  }
+
+  void UseMemoryHelper() {
+    size_t size = 1024;
+    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
+    EXPECT_TRUE(IsRegistered(discardable.get()));
+    EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
+    discardable->Unlock();
+  }
+
+  void SignalHelper() {
+    thread_sync_.Signal();
+  }
+
+  Thread memory_usage_thread_;
+  WaitableEvent thread_sync_;
+};
+
+TEST_F(ThreadedDiscardableMemoryManagerTest, UseMemoryOnThread) {
+  memory_usage_thread_.message_loop()->PostTask(
+      FROM_HERE,
+      Bind(&ThreadedDiscardableMemoryManagerTest::UseMemoryHelper,
+           Unretained(this)));
+  memory_usage_thread_.message_loop()->PostTask(
+      FROM_HERE,
+      Bind(&ThreadedDiscardableMemoryManagerTest::SignalHelper,
+           Unretained(this)));
+  thread_sync_.Wait();
+}
+
+}  // namespace base
diff --git a/base/memory/discardable_memory_provider.cc b/base/memory/discardable_memory_provider.cc
deleted file mode 100644
index 5d43b44..0000000
--- a/base/memory/discardable_memory_provider.cc
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_provider.h"
-
-#include "base/bind.h"
-#include "base/containers/hash_tables.h"
-#include "base/containers/mru_cache.h"
-#include "base/debug/trace_event.h"
-#include "base/synchronization/lock.h"
-#include "base/sys_info.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-// This is admittedly pretty magical. It's approximately enough memory for four
-// 2560x1600 images.
-static const size_t kDefaultDiscardableMemoryLimit = 64 * 1024 * 1024;
-static const size_t kDefaultBytesToKeepUnderModeratePressure =
-    kDefaultDiscardableMemoryLimit / 4;
-
-}  // namespace
-
-DiscardableMemoryProvider::DiscardableMemoryProvider()
-    : allocations_(AllocationMap::NO_AUTO_EVICT),
-      bytes_allocated_(0),
-      discardable_memory_limit_(kDefaultDiscardableMemoryLimit),
-      bytes_to_keep_under_moderate_pressure_(
-          kDefaultBytesToKeepUnderModeratePressure) {
-}
-
-DiscardableMemoryProvider::~DiscardableMemoryProvider() {
-  DCHECK(allocations_.empty());
-  DCHECK_EQ(0u, bytes_allocated_);
-}
-
-void DiscardableMemoryProvider::RegisterMemoryPressureListener() {
-  AutoLock lock(lock_);
-  DCHECK(base::MessageLoop::current());
-  DCHECK(!memory_pressure_listener_);
-  memory_pressure_listener_.reset(
-      new MemoryPressureListener(
-          base::Bind(&DiscardableMemoryProvider::OnMemoryPressure,
-                     Unretained(this))));
-}
-
-void DiscardableMemoryProvider::UnregisterMemoryPressureListener() {
-  AutoLock lock(lock_);
-  DCHECK(memory_pressure_listener_);
-  memory_pressure_listener_.reset();
-}
-
-void DiscardableMemoryProvider::SetDiscardableMemoryLimit(size_t bytes) {
-  AutoLock lock(lock_);
-  discardable_memory_limit_ = bytes;
-  EnforcePolicyWithLockAcquired();
-}
-
-void DiscardableMemoryProvider::SetBytesToKeepUnderModeratePressure(
-    size_t bytes) {
-  AutoLock lock(lock_);
-  bytes_to_keep_under_moderate_pressure_ = bytes;
-}
-
-void DiscardableMemoryProvider::Register(
-    const DiscardableMemory* discardable, size_t bytes) {
-  AutoLock lock(lock_);
-  // A registered memory listener is currently required. This DCHECK can be
-  // moved or removed if we decide that it's useful to relax this condition.
-  // TODO(reveman): Enable this DCHECK when skia and blink are able to
-  // register memory pressure listeners. crbug.com/333907
-  // DCHECK(memory_pressure_listener_);
-  DCHECK(allocations_.Peek(discardable) == allocations_.end());
-  allocations_.Put(discardable, Allocation(bytes));
-}
-
-void DiscardableMemoryProvider::Unregister(
-    const DiscardableMemory* discardable) {
-  AutoLock lock(lock_);
-  AllocationMap::iterator it = allocations_.Peek(discardable);
-  if (it == allocations_.end())
-    return;
-
-  if (it->second.memory) {
-    size_t bytes = it->second.bytes;
-    DCHECK_LE(bytes, bytes_allocated_);
-    bytes_allocated_ -= bytes;
-    free(it->second.memory);
-  }
-  allocations_.Erase(it);
-}
-
-scoped_ptr<uint8, FreeDeleter> DiscardableMemoryProvider::Acquire(
-    const DiscardableMemory* discardable,
-    bool* purged) {
-  AutoLock lock(lock_);
-  // NB: |allocations_| is an MRU cache, and use of |Get| here updates that
-  // cache.
-  AllocationMap::iterator it = allocations_.Get(discardable);
-  CHECK(it != allocations_.end());
-
-  if (it->second.memory) {
-    scoped_ptr<uint8, FreeDeleter> memory(it->second.memory);
-    it->second.memory = NULL;
-    *purged = false;
-    return memory.Pass();
-  }
-
-  size_t bytes = it->second.bytes;
-  if (!bytes)
-    return scoped_ptr<uint8, FreeDeleter>();
-
-  if (discardable_memory_limit_) {
-    size_t limit = 0;
-    if (bytes < discardable_memory_limit_)
-      limit = discardable_memory_limit_ - bytes;
-
-    PurgeLRUWithLockAcquiredUntilUsageIsWithin(limit);
-  }
-
-  // Check for overflow.
-  if (std::numeric_limits<size_t>::max() - bytes < bytes_allocated_)
-    return scoped_ptr<uint8, FreeDeleter>();
-
-  scoped_ptr<uint8, FreeDeleter> memory(static_cast<uint8*>(malloc(bytes)));
-  if (!memory)
-    return scoped_ptr<uint8, FreeDeleter>();
-
-  bytes_allocated_ += bytes;
-  *purged = true;
-  return memory.Pass();
-}
-
-void DiscardableMemoryProvider::Release(
-    const DiscardableMemory* discardable,
-    scoped_ptr<uint8, FreeDeleter> memory) {
-  AutoLock lock(lock_);
-  // NB: |allocations_| is an MRU cache, and use of |Get| here updates that
-  // cache.
-  AllocationMap::iterator it = allocations_.Get(discardable);
-  CHECK(it != allocations_.end());
-
-  DCHECK(!it->second.memory);
-  it->second.memory = memory.release();
-
-  EnforcePolicyWithLockAcquired();
-}
-
-void DiscardableMemoryProvider::PurgeAll() {
-  AutoLock lock(lock_);
-  PurgeLRUWithLockAcquiredUntilUsageIsWithin(0);
-}
-
-bool DiscardableMemoryProvider::IsRegisteredForTest(
-    const DiscardableMemory* discardable) const {
-  AutoLock lock(lock_);
-  AllocationMap::const_iterator it = allocations_.Peek(discardable);
-  return it != allocations_.end();
-}
-
-bool DiscardableMemoryProvider::CanBePurgedForTest(
-    const DiscardableMemory* discardable) const {
-  AutoLock lock(lock_);
-  AllocationMap::const_iterator it = allocations_.Peek(discardable);
-  return it != allocations_.end() && it->second.memory;
-}
-
-size_t DiscardableMemoryProvider::GetBytesAllocatedForTest() const {
-  AutoLock lock(lock_);
-  return bytes_allocated_;
-}
-
-void DiscardableMemoryProvider::OnMemoryPressure(
-    MemoryPressureListener::MemoryPressureLevel pressure_level) {
-  switch (pressure_level) {
-    case MemoryPressureListener::MEMORY_PRESSURE_MODERATE:
-      Purge();
-      return;
-    case MemoryPressureListener::MEMORY_PRESSURE_CRITICAL:
-      PurgeAll();
-      return;
-  }
-
-  NOTREACHED();
-}
-
-void DiscardableMemoryProvider::Purge() {
-  AutoLock lock(lock_);
-
-  PurgeLRUWithLockAcquiredUntilUsageIsWithin(
-      bytes_to_keep_under_moderate_pressure_);
-}
-
-void DiscardableMemoryProvider::PurgeLRUWithLockAcquiredUntilUsageIsWithin(
-    size_t limit) {
-  TRACE_EVENT1(
-      "base",
-      "DiscardableMemoryProvider::PurgeLRUWithLockAcquiredUntilUsageIsWithin",
-      "limit", limit);
-
-  lock_.AssertAcquired();
-
-  for (AllocationMap::reverse_iterator it = allocations_.rbegin();
-       it != allocations_.rend();
-       ++it) {
-    if (bytes_allocated_ <= limit)
-      break;
-    if (!it->second.memory)
-      continue;
-
-    size_t bytes = it->second.bytes;
-    DCHECK_LE(bytes, bytes_allocated_);
-    bytes_allocated_ -= bytes;
-    free(it->second.memory);
-    it->second.memory = NULL;
-  }
-}
-
-void DiscardableMemoryProvider::EnforcePolicyWithLockAcquired() {
-  PurgeLRUWithLockAcquiredUntilUsageIsWithin(discardable_memory_limit_);
-}
-
-}  // namespace internal
-}  // namespace base
diff --git a/base/memory/discardable_memory_provider.h b/base/memory/discardable_memory_provider.h
deleted file mode 100644
index 8ecc971..0000000
--- a/base/memory/discardable_memory_provider.h
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_MEMORY_DISCARDABLE_MEMORY_PROVIDER_H_
-#define BASE_MEMORY_DISCARDABLE_MEMORY_PROVIDER_H_
-
-#include "base/base_export.h"
-#include "base/containers/hash_tables.h"
-#include "base/containers/mru_cache.h"
-#include "base/memory/memory_pressure_listener.h"
-#include "base/synchronization/lock.h"
-
-namespace base {
-class DiscardableMemory;
-}  // namespace base
-
-#if defined(COMPILER_GCC)
-namespace BASE_HASH_NAMESPACE {
-template <>
-struct hash<const base::DiscardableMemory*> {
-  size_t operator()(const base::DiscardableMemory* ptr) const {
-    return hash<size_t>()(reinterpret_cast<size_t>(ptr));
-  }
-};
-}  // namespace BASE_HASH_NAMESPACE
-#endif  // COMPILER
-
-namespace base {
-namespace internal {
-
-// The DiscardableMemoryProvider manages a collection of emulated
-// DiscardableMemory instances. It is used on platforms that do not support
-// discardable memory natively. It keeps track of all DiscardableMemory
-// instances (in case they need to be purged), and the total amount of
-// allocated memory (in case this forces a purge).
-//
-// When notified of memory pressure, the provider either purges the LRU
-// memory -- if the pressure is moderate -- or all discardable memory
-// if the pressure is critical.
-//
-// NB - this class is an implementation detail. It has been exposed for testing
-// purposes. You should not need to use this class directly.
-class BASE_EXPORT_PRIVATE DiscardableMemoryProvider {
- public:
-  DiscardableMemoryProvider();
-  ~DiscardableMemoryProvider();
-
-  // Call this to register memory pressure listener. Must be called on a
-  // thread with a MessageLoop current.
-  void RegisterMemoryPressureListener();
-
-  // Call this to unregister memory pressure listener.
-  void UnregisterMemoryPressureListener();
-
-  // The maximum number of bytes of discardable memory that may be allocated
-  // before we force a purge. If this amount is zero, it is interpreted as
-  // having no limit at all.
-  void SetDiscardableMemoryLimit(size_t bytes);
-
-  // Sets the amount of memory to keep when we're under moderate pressure.
-  void SetBytesToKeepUnderModeratePressure(size_t bytes);
-
-  // Adds the given discardable memory to the provider's collection.
-  void Register(const DiscardableMemory* discardable, size_t bytes);
-
-  // Removes the given discardable memory from the provider's collection.
-  void Unregister(const DiscardableMemory* discardable);
-
-  // Returns NULL if an error occurred. Otherwise, returns the backing buffer
-  // and sets |purged| to indicate whether or not the backing buffer has been
-  // purged since last use.
-  scoped_ptr<uint8, FreeDeleter> Acquire(
-      const DiscardableMemory* discardable, bool* purged);
-
-  // Release a previously acquired backing buffer. This gives the buffer back
-  // to the provider where it can be purged if necessary.
-  void Release(const DiscardableMemory* discardable,
-               scoped_ptr<uint8, FreeDeleter> memory);
-
-  // Purges all discardable memory.
-  void PurgeAll();
-
-  // Returns true if discardable memory has been added to the provider's
-  // collection. This should only be used by tests.
-  bool IsRegisteredForTest(const DiscardableMemory* discardable) const;
-
-  // Returns true if discardable memory can be purged. This should only
-  // be used by tests.
-  bool CanBePurgedForTest(const DiscardableMemory* discardable) const;
-
-  // Returns total amount of allocated discardable memory. This should only
-  // be used by tests.
-  size_t GetBytesAllocatedForTest() const;
-
- private:
-  struct Allocation {
-   explicit Allocation(size_t bytes)
-       : bytes(bytes),
-         memory(NULL) {
-   }
-
-    size_t bytes;
-    uint8* memory;
-  };
-  typedef HashingMRUCache<const DiscardableMemory*, Allocation> AllocationMap;
-
-  // This can be called as a hint that the system is under memory pressure.
-  void OnMemoryPressure(
-      MemoryPressureListener::MemoryPressureLevel pressure_level);
-
-  // Purges until discardable memory usage is within
-  // |bytes_to_keep_under_moderate_pressure_|.
-  void Purge();
-
-  // Purges least recently used memory until usage is less or equal to |limit|.
-  // Caller must acquire |lock_| prior to calling this function.
-  void PurgeLRUWithLockAcquiredUntilUsageIsWithin(size_t limit);
-
-  // Ensures that we don't allocate beyond our memory limit.
-  // Caller must acquire |lock_| prior to calling this function.
-  void EnforcePolicyWithLockAcquired();
-
-  // Needs to be held when accessing members.
-  mutable Lock lock_;
-
-  // A MRU cache of all allocated bits of discardable memory. Used for purging.
-  AllocationMap allocations_;
-
-  // The total amount of allocated discardable memory.
-  size_t bytes_allocated_;
-
-  // The maximum number of bytes of discardable memory that may be allocated.
-  size_t discardable_memory_limit_;
-
-  // Under moderate memory pressure, we will purge until usage is within this
-  // limit.
-  size_t bytes_to_keep_under_moderate_pressure_;
-
-  // Allows us to be respond when the system reports that it is under memory
-  // pressure.
-  scoped_ptr<MemoryPressureListener> memory_pressure_listener_;
-
-  DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryProvider);
-};
-
-}  // namespace internal
-}  // namespace base
-
-#endif  // BASE_MEMORY_DISCARDABLE_MEMORY_PROVIDER_H_
diff --git a/base/memory/discardable_memory_provider_unittest.cc b/base/memory/discardable_memory_provider_unittest.cc
deleted file mode 100644
index 352f524..0000000
--- a/base/memory/discardable_memory_provider_unittest.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/memory/discardable_memory_provider.h"
-
-#include "base/bind.h"
-#include "base/memory/discardable_memory.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class DiscardableMemoryProviderTestBase {
- public:
-  class TestDiscardableMemory : public DiscardableMemory {
-   public:
-    TestDiscardableMemory(
-        internal::DiscardableMemoryProvider* provider, size_t size)
-        : provider_(provider),
-          is_locked_(false) {
-      provider_->Register(this, size);
-    }
-
-    virtual ~TestDiscardableMemory() {
-      if (is_locked_)
-        Unlock();
-      provider_->Unregister(this);
-    }
-
-    // Overridden from DiscardableMemory:
-    virtual DiscardableMemoryLockStatus Lock() OVERRIDE {
-      DCHECK(!is_locked_);
-
-      bool purged = false;
-      memory_ = provider_->Acquire(this, &purged);
-      if (!memory_)
-        return DISCARDABLE_MEMORY_LOCK_STATUS_FAILED;
-
-      is_locked_ = true;
-      return purged ? DISCARDABLE_MEMORY_LOCK_STATUS_PURGED
-                    : DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS;
-    }
-    virtual void Unlock() OVERRIDE {
-      DCHECK(is_locked_);
-      provider_->Release(this, memory_.Pass());
-      is_locked_ = false;
-    }
-    virtual void* Memory() const OVERRIDE {
-      DCHECK(memory_);
-      return memory_.get();
-    }
-
-   private:
-    internal::DiscardableMemoryProvider* provider_;
-    scoped_ptr<uint8, FreeDeleter> memory_;
-    bool is_locked_;
-
-    DISALLOW_COPY_AND_ASSIGN(TestDiscardableMemory);
-  };
-
-  DiscardableMemoryProviderTestBase()
-      : provider_(new internal::DiscardableMemoryProvider) {
-    provider_->RegisterMemoryPressureListener();
-  }
-
- protected:
-  bool IsRegistered(const DiscardableMemory* discardable) {
-    return provider_->IsRegisteredForTest(discardable);
-  }
-
-  bool CanBePurged(const DiscardableMemory* discardable) {
-    return provider_->CanBePurgedForTest(discardable);
-  }
-
-  size_t BytesAllocated() const {
-    return provider_->GetBytesAllocatedForTest();
-  }
-
-  void* Memory(const DiscardableMemory* discardable) const {
-    return discardable->Memory();
-  }
-
-  void SetDiscardableMemoryLimit(size_t bytes) {
-    provider_->SetDiscardableMemoryLimit(bytes);
-  }
-
-  void SetBytesToKeepUnderModeratePressure(size_t bytes) {
-    provider_->SetBytesToKeepUnderModeratePressure(bytes);
-  }
-
-  scoped_ptr<DiscardableMemory> CreateLockedMemory(size_t size) {
-    scoped_ptr<TestDiscardableMemory> memory(
-        new TestDiscardableMemory(provider_.get(), size));
-    if (memory->Lock() != DISCARDABLE_MEMORY_LOCK_STATUS_PURGED)
-      return scoped_ptr<DiscardableMemory>();
-    return memory.PassAs<DiscardableMemory>();
-  }
-
- private:
-  MessageLoopForIO message_loop_;
-  scoped_ptr<internal::DiscardableMemoryProvider> provider_;
-};
-
-class DiscardableMemoryProviderTest
-    : public DiscardableMemoryProviderTestBase,
-      public testing::Test {
- public:
-  DiscardableMemoryProviderTest() {}
-};
-
-TEST_F(DiscardableMemoryProviderTest, CreateLockedMemory) {
-  size_t size = 1024;
-  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-  EXPECT_TRUE(IsRegistered(discardable.get()));
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-}
-
-TEST_F(DiscardableMemoryProviderTest, CreateLockedMemoryZeroSize) {
-  size_t size = 0;
-  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-  EXPECT_FALSE(discardable);
-  EXPECT_FALSE(IsRegistered(discardable.get()));
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-TEST_F(DiscardableMemoryProviderTest, LockAfterUnlock) {
-  size_t size = 1024;
-  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-  EXPECT_TRUE(IsRegistered(discardable.get()));
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-
-  // Now unlock so we can lock later.
-  discardable->Unlock();
-  EXPECT_TRUE(CanBePurged(discardable.get()));
-
-  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable->Lock());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-}
-
-TEST_F(DiscardableMemoryProviderTest, LockAfterPurge) {
-  size_t size = 1024;
-  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-  EXPECT_TRUE(IsRegistered(discardable.get()));
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-
-  // Now unlock so we can lock later.
-  discardable->Unlock();
-  EXPECT_TRUE(CanBePurged(discardable.get()));
-
-  // Force the system to purge.
-  MemoryPressureListener::NotifyMemoryPressure(
-      MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
-
-  // Required because ObserverListThreadSafe notifies via PostTask.
-  RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable->Lock());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-}
-
-TEST_F(DiscardableMemoryProviderTest, LockAfterPurgeAndCannotReallocate) {
-  size_t size = 1024;
-  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-  EXPECT_TRUE(IsRegistered(discardable.get()));
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-
-  // Now unlock so we can lock later.
-  discardable->Unlock();
-  EXPECT_TRUE(CanBePurged(discardable.get()));
-
-  // Set max allowed allocation to 1 byte. This will make cause the memory
-  // to be purged.
-  SetDiscardableMemoryLimit(1);
-
-  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable->Lock());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-}
-
-TEST_F(DiscardableMemoryProviderTest, Overflow) {
-  {
-    size_t size = 1024;
-    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-    EXPECT_TRUE(IsRegistered(discardable.get()));
-    EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-    EXPECT_EQ(1024u, BytesAllocated());
-
-    size_t massive_size = std::numeric_limits<size_t>::max();
-    const scoped_ptr<DiscardableMemory> massive_discardable(
-        CreateLockedMemory(massive_size));
-    EXPECT_FALSE(massive_discardable);
-    EXPECT_EQ(1024u, BytesAllocated());
-  }
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-class PermutationTestData {
- public:
-  PermutationTestData(unsigned d0, unsigned d1, unsigned d2) {
-    ordering_[0] = d0;
-    ordering_[1] = d1;
-    ordering_[2] = d2;
-  }
-
-  const unsigned* ordering() const { return ordering_; }
-
- private:
-  unsigned ordering_[3];
-};
-
-class DiscardableMemoryProviderPermutationTest
-    : public DiscardableMemoryProviderTestBase,
-      public testing::TestWithParam<PermutationTestData> {
- public:
-  DiscardableMemoryProviderPermutationTest() {}
-
- protected:
-  // Use discardable memory in order specified by ordering parameter.
-  void CreateAndUseDiscardableMemory() {
-    for (int i = 0; i < 3; ++i) {
-      discardables_[i] = CreateLockedMemory(1024);
-      EXPECT_TRUE(discardables_[i]);
-      EXPECT_NE(static_cast<void*>(NULL), Memory(discardables_[i].get()));
-      discardables_[i]->Unlock();
-    }
-    for (int i = 0; i < 3; ++i) {
-      int index = GetParam().ordering()[i];
-      EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED,
-                discardables_[index]->Lock());
-      // Leave i == 0 locked.
-      if (i > 0)
-        discardables_[index]->Unlock();
-    }
-  }
-
-  DiscardableMemory* discardable(unsigned position) {
-    return discardables_[GetParam().ordering()[position]].get();
-  }
-
- private:
-  scoped_ptr<DiscardableMemory> discardables_[3];
-};
-
-// Verify that memory was discarded in the correct order after applying
-// memory pressure.
-TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedModeratePressure) {
-  CreateAndUseDiscardableMemory();
-
-  SetBytesToKeepUnderModeratePressure(1024);
-  SetDiscardableMemoryLimit(2048);
-
-  MemoryPressureListener::NotifyMemoryPressure(
-      MemoryPressureListener::MEMORY_PRESSURE_MODERATE);
-  RunLoop().RunUntilIdle();
-
-  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, discardable(2)->Lock());
-  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(1)->Lock());
-  // 0 should still be locked.
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0)));
-}
-
-// Verify that memory was discarded in the correct order after changing
-// memory limit.
-TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedExceedLimit) {
-  CreateAndUseDiscardableMemory();
-
-  SetBytesToKeepUnderModeratePressure(1024);
-  SetDiscardableMemoryLimit(2048);
-
-  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_FAILED, discardable(2)->Lock());
-  EXPECT_NE(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(1)->Lock());
-  // 0 should still be locked.
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0)));
-}
-
-// Verify that no more memory than necessary was discarded after changing
-// memory limit.
-TEST_P(DiscardableMemoryProviderPermutationTest, LRUDiscardedAmount) {
-  SetBytesToKeepUnderModeratePressure(2048);
-  SetDiscardableMemoryLimit(4096);
-
-  CreateAndUseDiscardableMemory();
-
-  SetDiscardableMemoryLimit(2048);
-
-  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_SUCCESS, discardable(2)->Lock());
-  EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable(1)->Lock());
-  // 0 should still be locked.
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(0)));
-}
-
-TEST_P(DiscardableMemoryProviderPermutationTest,
-       CriticalPressureFreesAllUnlocked) {
-  CreateAndUseDiscardableMemory();
-
-  MemoryPressureListener::NotifyMemoryPressure(
-      MemoryPressureListener::MEMORY_PRESSURE_CRITICAL);
-  RunLoop().RunUntilIdle();
-
-  for (int i = 0; i < 3; ++i) {
-    if (i == 0)
-      EXPECT_NE(static_cast<void*>(NULL), Memory(discardable(i)));
-    else
-      EXPECT_EQ(DISCARDABLE_MEMORY_LOCK_STATUS_PURGED, discardable(i)->Lock());
-  }
-}
-
-INSTANTIATE_TEST_CASE_P(DiscardableMemoryProviderPermutationTests,
-                        DiscardableMemoryProviderPermutationTest,
-                        ::testing::Values(PermutationTestData(0, 1, 2),
-                                          PermutationTestData(0, 2, 1),
-                                          PermutationTestData(1, 0, 2),
-                                          PermutationTestData(1, 2, 0),
-                                          PermutationTestData(2, 0, 1),
-                                          PermutationTestData(2, 1, 0)));
-
-TEST_F(DiscardableMemoryProviderTest, NormalDestruction) {
-  {
-    size_t size = 1024;
-    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-    EXPECT_TRUE(IsRegistered(discardable.get()));
-    EXPECT_EQ(1024u, BytesAllocated());
-  }
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-TEST_F(DiscardableMemoryProviderTest, DestructionWhileLocked) {
-  {
-    size_t size = 1024;
-    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-    EXPECT_TRUE(IsRegistered(discardable.get()));
-    EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-    EXPECT_EQ(1024u, BytesAllocated());
-    EXPECT_FALSE(CanBePurged(discardable.get()));
-  }
-  // Should have ignored the "locked" status and freed the discardable memory.
-  EXPECT_EQ(0u, BytesAllocated());
-}
-
-#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS)
-// Death tests are not supported with Android APKs.
-TEST_F(DiscardableMemoryProviderTest, UnlockedMemoryAccessCrashesInDebugMode) {
-  size_t size = 1024;
-  const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-  EXPECT_TRUE(IsRegistered(discardable.get()));
-  EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-  EXPECT_EQ(1024u, BytesAllocated());
-  EXPECT_FALSE(CanBePurged(discardable.get()));
-  discardable->Unlock();
-  EXPECT_TRUE(CanBePurged(discardable.get()));
-  // We *must* die if we are asked to vend a pointer to unlocked memory.
-  EXPECT_DEATH(discardable->Memory(), ".*Check failed.*");
-}
-#endif
-
-class ThreadedDiscardableMemoryProviderTest
-    : public DiscardableMemoryProviderTest {
- public:
-  ThreadedDiscardableMemoryProviderTest()
-      : memory_usage_thread_("memory_usage_thread"),
-        thread_sync_(true, false) {
-  }
-
-  virtual void SetUp() OVERRIDE {
-    memory_usage_thread_.Start();
-  }
-
-  virtual void TearDown() OVERRIDE {
-    memory_usage_thread_.Stop();
-  }
-
-  void UseMemoryHelper() {
-    size_t size = 1024;
-    const scoped_ptr<DiscardableMemory> discardable(CreateLockedMemory(size));
-    EXPECT_TRUE(IsRegistered(discardable.get()));
-    EXPECT_NE(static_cast<void*>(NULL), Memory(discardable.get()));
-    discardable->Unlock();
-  }
-
-  void SignalHelper() {
-    thread_sync_.Signal();
-  }
-
-  Thread memory_usage_thread_;
-  WaitableEvent thread_sync_;
-};
-
-TEST_F(ThreadedDiscardableMemoryProviderTest, UseMemoryOnThread) {
-  memory_usage_thread_.message_loop()->PostTask(
-      FROM_HERE,
-      Bind(&ThreadedDiscardableMemoryProviderTest::UseMemoryHelper,
-           Unretained(this)));
-  memory_usage_thread_.message_loop()->PostTask(
-      FROM_HERE,
-      Bind(&ThreadedDiscardableMemoryProviderTest::SignalHelper,
-           Unretained(this)));
-  thread_sync_.Wait();
-}
-
-}  // namespace base
diff --git a/base/memory/shared_memory.h b/base/memory/shared_memory.h
index f2ba702..87b923e 100644
--- a/base/memory/shared_memory.h
+++ b/base/memory/shared_memory.h
@@ -261,10 +261,12 @@
 
  private:
 #if defined(OS_POSIX) && !defined(OS_NACL)
+#if !defined(OS_ANDROID)
   bool PrepareMapFile(ScopedFILE fp, ScopedFD readonly);
   bool FilePathForMemoryName(const std::string& mem_name, FilePath* path);
-  void LockOrUnlockCommon(int function);
 #endif
+  void LockOrUnlockCommon(int function);
+#endif  // defined(OS_POSIX) && !defined(OS_NACL)
   enum ShareMode {
     SHARE_READONLY,
     SHARE_CURRENT_MODE,
diff --git a/base/memory/shared_memory_posix.cc b/base/memory/shared_memory_posix.cc
index 5fcbbfe..2afe450 100644
--- a/base/memory/shared_memory_posix.cc
+++ b/base/memory/shared_memory_posix.cc
@@ -270,7 +270,6 @@
   }
   return PrepareMapFile(fp.Pass(), readonly_fd.Pass());
 }
-
 #endif  // !defined(OS_ANDROID)
 
 bool SharedMemory::MapAt(off_t offset, size_t bytes) {
@@ -385,7 +384,6 @@
 
   return true;
 }
-#endif
 
 // For the given shmem named |mem_name|, return a filename to mmap()
 // (and possibly create).  Modifies |filename|.  Return false on
@@ -413,6 +411,7 @@
   *path = temp_dir.AppendASCII(name_base + ".shmem." + mem_name);
   return true;
 }
+#endif  // !defined(OS_ANDROID)
 
 void SharedMemory::LockOrUnlockCommon(int function) {
   DCHECK_GE(mapped_file_, 0);
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
index 4637165..7ccee73 100644
--- a/base/message_loop/message_loop_unittest.cc
+++ b/base/message_loop/message_loop_unittest.cc
@@ -53,36 +53,11 @@
   Foo() : test_count_(0) {
   }
 
-  void Test0() {
-    ++test_count_;
-  }
-
   void Test1ConstRef(const std::string& a) {
     ++test_count_;
     result_.append(a);
   }
 
-  void Test1Ptr(std::string* a) {
-    ++test_count_;
-    result_.append(*a);
-  }
-
-  void Test1Int(int a) {
-    test_count_ += a;
-  }
-
-  void Test2Ptr(std::string* a, std::string* b) {
-    ++test_count_;
-    result_.append(*a);
-    result_.append(*b);
-  }
-
-  void Test2Mixed(const std::string& a, std::string* b) {
-    ++test_count_;
-    result_.append(a);
-    result_.append(*b);
-  }
-
   int test_count() const { return test_count_; }
   const std::string& result() const { return result_; }
 
diff --git a/base/metrics/user_metrics.h b/base/metrics/user_metrics.h
index 10e7d3c..57356c3 100644
--- a/base/metrics/user_metrics.h
+++ b/base/metrics/user_metrics.h
@@ -30,9 +30,10 @@
 // name from the hash later on.
 //
 // Once a new recorded action is added, run
-// tools/metrics/actions/extract_actions.py --hash
-// to generate a new mapping of [action hashes -> metric names] and send it
-// out for review to be updated.
+//   tools/metrics/actions/extract_actions.py
+// to add the metric to actions.xml, then update the <owner>s and <description>
+// sections. Make sure to include the actions.xml file when you upload your code
+// for review!
 //
 // For more complicated situations (like when there are many different
 // possible actions), see RecordComputedAction.
diff --git a/base/native_library.h b/base/native_library.h
index d7513d0..1e764da 100644
--- a/base/native_library.h
+++ b/base/native_library.h
@@ -8,8 +8,11 @@
 // This file defines a cross-platform "NativeLibrary" type which represents
 // a loadable module.
 
+#include <string>
+
 #include "base/base_export.h"
 #include "base/compiler_specific.h"
+#include "base/strings/string16.h"
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
@@ -18,8 +21,6 @@
 #import <CoreFoundation/CoreFoundation.h>
 #endif  // OS_*
 
-#include "base/strings/string16.h"
-
 namespace base {
 
 class FilePath;
@@ -50,11 +51,26 @@
 typedef void* NativeLibrary;
 #endif  // OS_*
 
+struct BASE_EXPORT NativeLibraryLoadError {
+#if defined(OS_WIN)
+  NativeLibraryLoadError() : code(0) {}
+#endif  // OS_WIN
+
+  // Returns a string representation of the load error.
+  std::string ToString() const;
+
+#if defined(OS_WIN)
+  DWORD code;
+#else
+  std::string message;
+#endif  // OS_WIN
+};
+
 // Loads a native library from disk.  Release it with UnloadNativeLibrary when
 // you're done.  Returns NULL on failure.
-// If |error| is not NULL, it may be filled in with an error message on error.
+// If |error| is not NULL, it may be filled in on load error.
 BASE_EXPORT NativeLibrary LoadNativeLibrary(const FilePath& library_path,
-                                            std::string* error);
+                                            NativeLibraryLoadError* error);
 
 #if defined(OS_WIN)
 // Loads a native library from disk.  Release it with UnloadNativeLibrary when
diff --git a/base/native_library_mac.mm b/base/native_library_mac.mm
index 6544fca..6696454 100644
--- a/base/native_library_mac.mm
+++ b/base/native_library_mac.mm
@@ -41,9 +41,14 @@
   return section == NULL ? OBJC_NOT_PRESENT : OBJC_PRESENT;
 }
 
+std::string NativeLibraryLoadError::ToString() const {
+  return message;
+}
+
 // static
+// TODO(xhwang): Fill |error|. See http://crbug.com/353771
 NativeLibrary LoadNativeLibrary(const base::FilePath& library_path,
-                                std::string* error) {
+                                NativeLibraryLoadError* /* error */) {
   // dlopen() etc. open the file off disk.
   if (library_path.Extension() == "dylib" || !DirectoryExists(library_path)) {
     void* dylib = dlopen(library_path.value().c_str(), RTLD_LAZY);
diff --git a/base/native_library_posix.cc b/base/native_library_posix.cc
index dfa20fc..3179a93 100644
--- a/base/native_library_posix.cc
+++ b/base/native_library_posix.cc
@@ -13,9 +13,13 @@
 
 namespace base {
 
+std::string NativeLibraryLoadError::ToString() const {
+  return message;
+}
+
 // static
 NativeLibrary LoadNativeLibrary(const FilePath& library_path,
-                                std::string* error) {
+                                NativeLibraryLoadError* error) {
   // dlopen() opens the file off disk.
   base::ThreadRestrictions::AssertIOAllowed();
 
@@ -25,7 +29,7 @@
   // and http://crbug.com/40794.
   void* dl = dlopen(library_path.value().c_str(), RTLD_LAZY);
   if (!dl && error)
-    *error = dlerror();
+    error->message = dlerror();
 
   return dl;
 }
diff --git a/base/native_library_win.cc b/base/native_library_win.cc
index bcea485..43528b9 100644
--- a/base/native_library_win.cc
+++ b/base/native_library_win.cc
@@ -15,9 +15,11 @@
 
 typedef HMODULE (WINAPI* LoadLibraryFunction)(const wchar_t* file_name);
 
+namespace {
+
 NativeLibrary LoadNativeLibraryHelper(const FilePath& library_path,
                                       LoadLibraryFunction load_library_api,
-                                      std::string* error) {
+                                      NativeLibraryLoadError* error) {
   // LoadLibrary() opens the file off disk.
   ThreadRestrictions::AssertIOAllowed();
 
@@ -36,8 +38,7 @@
   HMODULE module = (*load_library_api)(library_path.value().c_str());
   if (!module && error) {
     // GetLastError() needs to be called immediately after |load_library_api|.
-    DWORD last_error = GetLastError();
-    *error = StringPrintf("%u", last_error);
+    error->code = GetLastError();
   }
 
   if (restore_directory)
@@ -46,9 +47,15 @@
   return module;
 }
 
+}  // namespace
+
+std::string NativeLibraryLoadError::ToString() const {
+  return StringPrintf("%u", code);
+}
+
 // static
 NativeLibrary LoadNativeLibrary(const FilePath& library_path,
-                                std::string* error) {
+                                NativeLibraryLoadError* error) {
   return LoadNativeLibraryHelper(library_path, LoadLibraryW, error);
 }
 
diff --git a/base/prefs/overlay_user_pref_store_unittest.cc b/base/prefs/overlay_user_pref_store_unittest.cc
index c4e980b..18e9a5c 100644
--- a/base/prefs/overlay_user_pref_store_unittest.cc
+++ b/base/prefs/overlay_user_pref_store_unittest.cc
@@ -48,47 +48,39 @@
   overlay_->AddObserver(&obs);
 
   // Check that underlay first value is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(1);
   underlay_->SetValue(overlay_key, new FundamentalValue(42));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(overlay_key);
 
   // Check that underlay overwriting is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(1);
   underlay_->SetValue(overlay_key, new FundamentalValue(43));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(overlay_key);
 
   // Check that overwriting change in overlay is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(1);
   overlay_->SetValue(overlay_key, new FundamentalValue(44));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(overlay_key);
 
   // Check that hidden underlay change is not reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(0);
   underlay_->SetValue(overlay_key, new FundamentalValue(45));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 
   // Check that overlay remove is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(1);
   overlay_->RemoveValue(overlay_key);
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(overlay_key);
 
   // Check that underlay remove is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(1);
   underlay_->RemoveValue(overlay_key);
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(overlay_key);
 
   // Check respecting of silence.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(0);
   overlay_->SetValueSilently(overlay_key, new FundamentalValue(46));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 
   overlay_->RemoveObserver(&obs);
 
   // Check successful unsubscription.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(overlay_key))).Times(0);
   underlay_->SetValue(overlay_key, new FundamentalValue(47));
   overlay_->SetValue(overlay_key, new FundamentalValue(48));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 }
 
 TEST_F(OverlayUserPrefStoreTest, GetAndSet) {
@@ -154,23 +146,20 @@
   const Value* value = NULL;
 
   // Check that underlay first value is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(regular_key))).Times(1);
   underlay_->SetValue(regular_key, new FundamentalValue(42));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(regular_key);
 
   // Check that underlay overwriting is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(regular_key))).Times(1);
   underlay_->SetValue(regular_key, new FundamentalValue(43));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(regular_key);
 
   // Check that we get this value from the overlay
   EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
   EXPECT_TRUE(base::FundamentalValue(43).Equals(value));
 
   // Check that overwriting change in overlay is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(regular_key))).Times(1);
   overlay_->SetValue(regular_key, new FundamentalValue(44));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(regular_key);
 
   // Check that we get this value from the overlay and the underlay.
   EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
@@ -179,26 +168,23 @@
   EXPECT_TRUE(base::FundamentalValue(44).Equals(value));
 
   // Check that overlay remove is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(regular_key))).Times(1);
   overlay_->RemoveValue(regular_key);
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(regular_key);
 
   // Check that value was removed from overlay and underlay
   EXPECT_FALSE(overlay_->GetValue(regular_key, &value));
   EXPECT_FALSE(underlay_->GetValue(regular_key, &value));
 
   // Check respecting of silence.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(regular_key))).Times(0);
   overlay_->SetValueSilently(regular_key, new FundamentalValue(46));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 
   overlay_->RemoveObserver(&obs);
 
   // Check successful unsubscription.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(regular_key))).Times(0);
   underlay_->SetValue(regular_key, new FundamentalValue(47));
   overlay_->SetValue(regular_key, new FundamentalValue(48));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 }
 
 // Check that names mapping works correctly.
@@ -210,14 +196,12 @@
 
   // Check that if there is no override in the overlay, changing underlay value
   // is reported as changing an overlay value.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(1);
   underlay_->SetValue(mapped_underlay_key, new FundamentalValue(42));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(mapped_overlay_key);
 
   // Check that underlay overwriting is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(1);
   underlay_->SetValue(mapped_underlay_key, new FundamentalValue(43));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(mapped_overlay_key);
 
   // Check that we get this value from the overlay with both keys
   EXPECT_TRUE(overlay_->GetValue(mapped_overlay_key, &value));
@@ -227,9 +211,8 @@
   EXPECT_TRUE(base::FundamentalValue(43).Equals(value));
 
   // Check that overwriting change in overlay is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(1);
   overlay_->SetValue(mapped_overlay_key, new FundamentalValue(44));
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(mapped_overlay_key);
 
   // Check that we get an overriden value from overlay, while reading the
   // value from underlay still holds an old value.
@@ -241,38 +224,31 @@
   EXPECT_TRUE(base::FundamentalValue(43).Equals(value));
 
   // Check that hidden underlay change is not reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(0);
   underlay_->SetValue(mapped_underlay_key, new FundamentalValue(45));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 
   // Check that overlay remove is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(1);
   overlay_->RemoveValue(mapped_overlay_key);
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(mapped_overlay_key);
 
   // Check that underlay remove is reported.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(1);
   underlay_->RemoveValue(mapped_underlay_key);
-  Mock::VerifyAndClearExpectations(&obs);
+  obs.VerifyAndResetChangedKey(mapped_overlay_key);
 
   // Check that value was removed.
   EXPECT_FALSE(overlay_->GetValue(mapped_overlay_key, &value));
   EXPECT_FALSE(overlay_->GetValue(mapped_underlay_key, &value));
 
   // Check respecting of silence.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(0);
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_underlay_key))).Times(0);
   overlay_->SetValueSilently(mapped_overlay_key, new FundamentalValue(46));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 
   overlay_->RemoveObserver(&obs);
 
   // Check successful unsubscription.
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_overlay_key))).Times(0);
-  EXPECT_CALL(obs, OnPrefValueChanged(StrEq(mapped_underlay_key))).Times(0);
   underlay_->SetValue(mapped_underlay_key, new FundamentalValue(47));
   overlay_->SetValue(mapped_overlay_key, new FundamentalValue(48));
-  Mock::VerifyAndClearExpectations(&obs);
+  EXPECT_TRUE(obs.changed_keys.empty());
 }
 
 }  // namespace base
diff --git a/base/prefs/pref_notifier_impl_unittest.cc b/base/prefs/pref_notifier_impl_unittest.cc
index 29ea322..8482c02 100644
--- a/base/prefs/pref_notifier_impl_unittest.cc
+++ b/base/prefs/pref_notifier_impl_unittest.cc
@@ -80,13 +80,6 @@
   virtual ~PrefObserverMock() {}
 
   MOCK_METHOD2(OnPreferenceChanged, void(PrefService*, const std::string&));
-
-  void Expect(PrefService* prefs,
-              const std::string& pref_name,
-              const base::Value* value) {
-    EXPECT_CALL(*this, OnPreferenceChanged(prefs, pref_name))
-        .With(PrefValueMatches(prefs, pref_name, value));
-  }
 };
 
 // Test fixture class.
diff --git a/base/prefs/pref_service.cc b/base/prefs/pref_service.cc
index 8a2c742..a8e56d0 100644
--- a/base/prefs/pref_service.cc
+++ b/base/prefs/pref_service.cc
@@ -67,7 +67,9 @@
 }
 
 void PrefService::InitFromStorage(bool async) {
-  if (!async) {
+  if (user_pref_store_->IsInitializationComplete()) {
+    read_error_callback_.Run(user_pref_store_->GetReadError());
+  } else if (!async) {
     read_error_callback_.Run(user_pref_store_->ReadPrefs());
   } else {
     // Guarantee that initialization happens after this function returned.
diff --git a/base/prefs/pref_store_observer_mock.cc b/base/prefs/pref_store_observer_mock.cc
index 0970e63..f1a31bb 100644
--- a/base/prefs/pref_store_observer_mock.cc
+++ b/base/prefs/pref_store_observer_mock.cc
@@ -4,6 +4,26 @@
 
 #include "base/prefs/pref_store_observer_mock.h"
 
-PrefStoreObserverMock::PrefStoreObserverMock() {}
+#include "testing/gtest/include/gtest/gtest.h"
+
+PrefStoreObserverMock::PrefStoreObserverMock()
+    : initialized(false), initialization_success(false) {}
 
 PrefStoreObserverMock::~PrefStoreObserverMock() {}
+
+void PrefStoreObserverMock::VerifyAndResetChangedKey(
+    const std::string& expected) {
+  EXPECT_EQ(1u, changed_keys.size());
+  if (changed_keys.size() >= 1)
+    EXPECT_EQ(expected, changed_keys.front());
+  changed_keys.clear();
+}
+
+void PrefStoreObserverMock::OnPrefValueChanged(const std::string& key) {
+  changed_keys.push_back(key);
+}
+
+void PrefStoreObserverMock::OnInitializationCompleted(bool success) {
+  initialized = true;
+  initialization_success = success;
+}
diff --git a/base/prefs/pref_store_observer_mock.h b/base/prefs/pref_store_observer_mock.h
index 8252c3b..594807f 100644
--- a/base/prefs/pref_store_observer_mock.h
+++ b/base/prefs/pref_store_observer_mock.h
@@ -5,18 +5,28 @@
 #ifndef BASE_PREFS_PREF_STORE_OBSERVER_MOCK_H_
 #define BASE_PREFS_PREF_STORE_OBSERVER_MOCK_H_
 
-#include "base/basictypes.h"
-#include "base/prefs/pref_store.h"
-#include "testing/gmock/include/gmock/gmock.h"
+#include <string>
+#include <vector>
 
-// A gmock-ified implementation of PrefStore::Observer.
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/prefs/pref_store.h"
+
+// A mock implementation of PrefStore::Observer.
 class PrefStoreObserverMock : public PrefStore::Observer {
  public:
   PrefStoreObserverMock();
   virtual ~PrefStoreObserverMock();
 
-  MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
-  MOCK_METHOD1(OnInitializationCompleted, void(bool));
+  void VerifyAndResetChangedKey(const std::string& expected);
+
+  // PrefStore::Observer implementation
+  virtual void OnPrefValueChanged(const std::string& key) OVERRIDE;
+  virtual void OnInitializationCompleted(bool success) OVERRIDE;
+
+  std::vector<std::string> changed_keys;
+  bool initialized;
+  bool initialization_success;  // Only valid if |initialized|.
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PrefStoreObserverMock);
diff --git a/base/prefs/testing_pref_store.cc b/base/prefs/testing_pref_store.cc
index 2f429c9..f20824e 100644
--- a/base/prefs/testing_pref_store.cc
+++ b/base/prefs/testing_pref_store.cc
@@ -9,8 +9,12 @@
 
 TestingPrefStore::TestingPrefStore()
     : read_only_(true),
-      init_complete_(false) {
-}
+      read_success_(true),
+      read_error_(PersistentPrefStore::PREF_READ_ERROR_NONE),
+      block_async_read_(false),
+      pending_async_read_(false),
+      init_complete_(false),
+      committed_(true) {}
 
 bool TestingPrefStore::GetValue(const std::string& key,
                                 const base::Value** value) const {
@@ -39,18 +43,23 @@
 }
 
 void TestingPrefStore::SetValue(const std::string& key, base::Value* value) {
-  if (prefs_.SetValue(key, value))
+  if (prefs_.SetValue(key, value)) {
+    committed_ = false;
     NotifyPrefValueChanged(key);
+  }
 }
 
 void TestingPrefStore::SetValueSilently(const std::string& key,
                                         base::Value* value) {
-  prefs_.SetValue(key, value);
+  if (prefs_.SetValue(key, value))
+    committed_ = false;
 }
 
 void TestingPrefStore::RemoveValue(const std::string& key) {
-  if (prefs_.RemoveValue(key))
+  if (prefs_.RemoveValue(key)) {
+    committed_ = false;
     NotifyPrefValueChanged(key);
+  }
 }
 
 bool TestingPrefStore::ReadOnly() const {
@@ -58,21 +67,26 @@
 }
 
 PersistentPrefStore::PrefReadError TestingPrefStore::GetReadError() const {
-  return PersistentPrefStore::PREF_READ_ERROR_NONE;
+  return read_error_;
 }
 
 PersistentPrefStore::PrefReadError TestingPrefStore::ReadPrefs() {
   NotifyInitializationCompleted();
-  return PersistentPrefStore::PREF_READ_ERROR_NONE;
+  return read_error_;
 }
 
-void TestingPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate_raw) {
-  scoped_ptr<ReadErrorDelegate> error_delegate(error_delegate_raw);
-  NotifyInitializationCompleted();
+void TestingPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
+  DCHECK(!pending_async_read_);
+  error_delegate_.reset(error_delegate);
+  if (block_async_read_)
+    pending_async_read_ = true;
+  else
+    NotifyInitializationCompleted();
 }
 
+void TestingPrefStore::CommitPendingWrite() { committed_ = true; }
+
 void TestingPrefStore::SetInitializationCompleted() {
-  init_complete_ = true;
   NotifyInitializationCompleted();
 }
 
@@ -81,7 +95,12 @@
 }
 
 void TestingPrefStore::NotifyInitializationCompleted() {
-  FOR_EACH_OBSERVER(Observer, observers_, OnInitializationCompleted(true));
+  DCHECK(!init_complete_);
+  init_complete_ = true;
+  if (read_success_ && read_error_ != PREF_READ_ERROR_NONE && error_delegate_)
+    error_delegate_->OnError(read_error_);
+  FOR_EACH_OBSERVER(
+      Observer, observers_, OnInitializationCompleted(read_success_));
 }
 
 void TestingPrefStore::ReportValueChanged(const std::string& key) {
@@ -126,8 +145,26 @@
   return stored_value->GetAsBoolean(value);
 }
 
+void TestingPrefStore::SetBlockAsyncRead(bool block_async_read) {
+  DCHECK(!init_complete_);
+  block_async_read_ = block_async_read;
+  if (pending_async_read_ && !block_async_read_)
+    NotifyInitializationCompleted();
+}
+
 void TestingPrefStore::set_read_only(bool read_only) {
   read_only_ = read_only;
 }
 
+void TestingPrefStore::set_read_success(bool read_success) {
+  DCHECK(!init_complete_);
+  read_success_ = read_success;
+}
+
+void TestingPrefStore::set_read_error(
+    PersistentPrefStore::PrefReadError read_error) {
+  DCHECK(!init_complete_);
+  read_error_ = read_error;
+}
+
 TestingPrefStore::~TestingPrefStore() {}
diff --git a/base/prefs/testing_pref_store.h b/base/prefs/testing_pref_store.h
index c6a2b83..785f935 100644
--- a/base/prefs/testing_pref_store.h
+++ b/base/prefs/testing_pref_store.h
@@ -40,7 +40,7 @@
   virtual PrefReadError GetReadError() const OVERRIDE;
   virtual PersistentPrefStore::PrefReadError ReadPrefs() OVERRIDE;
   virtual void ReadPrefsAsync(ReadErrorDelegate* error_delegate) OVERRIDE;
-  virtual void CommitPendingWrite() OVERRIDE {}
+  virtual void CommitPendingWrite() OVERRIDE;
 
   // Marks the store as having completed initialization.
   void SetInitializationCompleted();
@@ -58,9 +58,18 @@
   bool GetInteger(const std::string& key, int* value) const;
   bool GetBoolean(const std::string& key, bool* value) const;
 
+  // Determines whether ReadPrefsAsync completes immediately. Defaults to false
+  // (non-blocking). To block, invoke this with true (blocking) before the call
+  // to ReadPrefsAsync. To unblock, invoke again with false (non-blocking) after
+  // the call to ReadPrefsAsync.
+  void SetBlockAsyncRead(bool block_async_read);
+
   // Getter and Setter methods for setting and getting the state of the
   // |TestingPrefStore|.
   virtual void set_read_only(bool read_only);
+  void set_read_success(bool read_success);
+  void set_read_error(PersistentPrefStore::PrefReadError read_error);
+  bool committed() { return committed_; }
 
  protected:
   virtual ~TestingPrefStore();
@@ -72,9 +81,26 @@
   // Flag that indicates if the PrefStore is read-only
   bool read_only_;
 
+  // The result to pass to PrefStore::Observer::OnInitializationCompleted
+  bool read_success_;
+
+  // The result to return from ReadPrefs or ReadPrefsAsync.
+  PersistentPrefStore::PrefReadError read_error_;
+
+  // Whether a call to ReadPrefsAsync should block.
+  bool block_async_read_;
+
+  // Whether there is a pending call to ReadPrefsAsync.
+  bool pending_async_read_;
+
   // Whether initialization has been completed.
   bool init_complete_;
 
+  // Whether the store contents have been committed to disk since the last
+  // mutation.
+  bool committed_;
+
+  scoped_ptr<ReadErrorDelegate> error_delegate_;
   ObserverList<PrefStore::Observer, true> observers_;
 
   DISALLOW_COPY_AND_ASSIGN(TestingPrefStore);
diff --git a/base/process/memory.cc b/base/process/memory.cc
new file mode 100644
index 0000000..1dbc363
--- /dev/null
+++ b/base/process/memory.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/process/memory.h"
+
+namespace base {
+
+// Defined in memory_mac.mm for Mac.
+#if !defined(OS_MACOSX)
+
+bool UncheckedCalloc(size_t num_items, size_t size, void** result) {
+  const size_t alloc_size = num_items * size;
+
+  // Overflow check
+  if (size && ((alloc_size / size) != num_items)) {
+    *result = NULL;
+    return false;
+  }
+
+  if (!UncheckedMalloc(alloc_size, result))
+    return false;
+
+  memset(*result, 0, alloc_size);
+  return true;
+}
+
+#endif
+
+}
diff --git a/base/process/memory.h b/base/process/memory.h
index 8187032..a73fbe1 100644
--- a/base/process/memory.h
+++ b/base/process/memory.h
@@ -61,17 +61,27 @@
 BASE_EXPORT bool AdjustOOMScore(ProcessId process, int score);
 #endif
 
+// Special allocator functions for callers that want to check for OOM.
+// These will not abort if the allocation fails even if
+// EnableTerminationOnOutOfMemory has been called.
+// This can be useful for huge and/or unpredictable size memory allocations.
+// Please only use this if you really handle the case when the allocation
+// fails. Doing otherwise would risk security.
+// These functions may still crash on OOM when running under memory tools,
+// specifically ASan and other sanitizers.
+// Return value tells whether the allocation succeeded. If it fails |result| is
+// set to NULL, otherwise it holds the memory address.
+BASE_EXPORT WARN_UNUSED_RESULT bool UncheckedMalloc(size_t size,
+                                                    void** result);
+BASE_EXPORT WARN_UNUSED_RESULT bool UncheckedCalloc(size_t num_items,
+                                                    size_t size,
+                                                    void** result);
+
+// TODO(b.kelemen): make Skia use the new interface and remove these.
 #if defined(OS_MACOSX)
-// Very large images or svg canvases can cause huge mallocs.  Skia
-// does tricks on tcmalloc-based systems to allow malloc to fail with
-// a NULL rather than hit the oom crasher.  This replicates that for
-// OSX.
-//
-// IF YOU USE THIS WITHOUT CONSULTING YOUR FRIENDLY OSX DEVELOPER,
-// YOUR CODE IS LIKELY TO BE REVERTED.  THANK YOU.
 BASE_EXPORT void* UncheckedMalloc(size_t size);
 BASE_EXPORT void* UncheckedCalloc(size_t num_items, size_t size);
-#endif  // defined(OS_MACOSX)
+#endif
 
 }  // namespace base
 
diff --git a/base/process/memory_linux.cc b/base/process/memory_linux.cc
index a40c270..befd832 100644
--- a/base/process/memory_linux.cc
+++ b/base/process/memory_linux.cc
@@ -12,6 +12,22 @@
 #include "base/process/internal_linux.h"
 #include "base/strings/string_number_conversions.h"
 
+#if defined(USE_TCMALLOC)
+// Used by UncheckedMalloc. If tcmalloc is linked to the executable
+// this will be replaced by a strong symbol that actually implement
+// the semantics and don't call new handler in case the allocation fails.
+extern "C" {
+
+__attribute__((weak, visibility("default")))
+void* tc_malloc_skip_new_handler_weak(size_t size);
+
+void* tc_malloc_skip_new_handler_weak(size_t size) {
+  return malloc(size);
+}
+
+}
+#endif
+
 namespace base {
 
 size_t g_oom_size = 0U;
@@ -182,4 +198,16 @@
   return false;
 }
 
+bool UncheckedMalloc(size_t size, void** result) {
+#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) || \
+    (!defined(LIBC_GLIBC) && !defined(USE_TCMALLOC))
+  *result = malloc(size);
+#elif defined(LIBC_GLIBC) && !defined(USE_TCMALLOC)
+  *result = __libc_malloc(size);
+#elif defined(USE_TCMALLOC)
+  *result = tc_malloc_skip_new_handler_weak(size);
+#endif
+  return *result != NULL;
+}
+
 }  // namespace base
diff --git a/base/process/memory_mac.mm b/base/process/memory_mac.mm
index 3e281cd..6cf1297 100644
--- a/base/process/memory_mac.mm
+++ b/base/process/memory_mac.mm
@@ -502,26 +502,42 @@
 
 }  // namespace
 
-void* UncheckedMalloc(size_t size) {
+bool UncheckedMalloc(size_t size, void** result) {
   if (g_old_malloc) {
 #if ARCH_CPU_32_BITS
     ScopedClearErrno clear_errno;
     ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true);
 #endif  // ARCH_CPU_32_BITS
-    return g_old_malloc(malloc_default_zone(), size);
+    *result = g_old_malloc(malloc_default_zone(), size);
+  } else {
+    *result = malloc(size);
   }
-  return malloc(size);
+
+  return *result != NULL;
 }
 
-void* UncheckedCalloc(size_t num_items, size_t size) {
+bool UncheckedCalloc(size_t num_items, size_t size, void** result) {
   if (g_old_calloc) {
 #if ARCH_CPU_32_BITS
     ScopedClearErrno clear_errno;
     ThreadLocalBooleanAutoReset flag(g_unchecked_alloc.Pointer(), true);
 #endif  // ARCH_CPU_32_BITS
-    return g_old_calloc(malloc_default_zone(), num_items, size);
+    *result = g_old_calloc(malloc_default_zone(), num_items, size);
+  } else {
+    *result = calloc(num_items, size);
   }
-  return calloc(num_items, size);
+
+  return *result != NULL;
+}
+
+void* UncheckedMalloc(size_t size) {
+  void* address;
+  return UncheckedMalloc(size, &address) ? address : NULL;
+}
+
+void* UncheckedCalloc(size_t num_items, size_t size) {
+  void* address;
+  return UncheckedCalloc(num_items, size, &address) ? address : NULL;
 }
 
 void EnableTerminationOnOutOfMemory() {
diff --git a/base/process/memory_unittest.cc b/base/process/memory_unittest.cc
index 5a1bcdf..048c09d 100644
--- a/base/process/memory_unittest.cc
+++ b/base/process/memory_unittest.cc
@@ -152,13 +152,9 @@
 // Android doesn't implement set_new_handler, so we can't use the
 // OutOfMemoryTest cases.
 // OpenBSD does not support these tests either.
-// AddressSanitizer and ThreadSanitizer define the malloc()/free()/etc.
-// functions so that they don't crash if the program is out of memory, so the
-// OOM tests aren't supposed to work.
 // TODO(vandebo) make this work on Windows too.
 #if !defined(OS_ANDROID) && !defined(OS_OPENBSD) && \
-    !defined(OS_WIN) && \
-    !defined(ADDRESS_SANITIZER) && !defined(THREAD_SANITIZER)
+    !defined(OS_WIN)
 
 #if defined(USE_TCMALLOC)
 extern "C" {
@@ -166,14 +162,14 @@
 }
 #endif  // defined(USE_TCMALLOC)
 
-class OutOfMemoryDeathTest : public testing::Test {
+class OutOfMemoryTest : public testing::Test {
  public:
-  OutOfMemoryDeathTest()
-      : value_(NULL),
-        // Make test size as large as possible minus a few pages so
-        // that alignment or other rounding doesn't make it wrap.
-        test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024),
-        signed_test_size_(std::numeric_limits<ssize_t>::max()) {
+  OutOfMemoryTest()
+    : value_(NULL),
+    // Make test size as large as possible minus a few pages so
+    // that alignment or other rounding doesn't make it wrap.
+    test_size_(std::numeric_limits<std::size_t>::max() - 12 * 1024),
+    signed_test_size_(std::numeric_limits<ssize_t>::max()) {
   }
 
 #if defined(USE_TCMALLOC)
@@ -186,6 +182,14 @@
   }
 #endif  // defined(USE_TCMALLOC)
 
+ protected:
+  void* value_;
+  size_t test_size_;
+  ssize_t signed_test_size_;
+};
+
+class OutOfMemoryDeathTest : public OutOfMemoryTest {
+ public:
   void SetUpInDeathAssert() {
     // Must call EnableTerminationOnOutOfMemory() because that is called from
     // chrome's main function and therefore hasn't been called yet.
@@ -194,10 +198,6 @@
     // should be done inside of the ASSERT_DEATH.
     base::EnableTerminationOnOutOfMemory();
   }
-
-  void* value_;
-  size_t test_size_;
-  ssize_t signed_test_size_;
 };
 
 TEST_F(OutOfMemoryDeathTest, New) {
@@ -375,5 +375,54 @@
 #endif  // !ARCH_CPU_64_BITS
 #endif  // OS_MACOSX
 
-#endif  // !defined(OS_ANDROID) && !defined(OS_OPENBSD) &&
-        // !defined(OS_WIN) && !defined(ADDRESS_SANITIZER)
+class OutOfMemoryHandledTest : public OutOfMemoryTest {
+ public:
+  static const size_t kSafeMallocSize = 512;
+  static const size_t kSafeCallocSize = 128;
+  static const size_t kSafeCallocItems = 4;
+
+  virtual void SetUp() {
+    OutOfMemoryTest::SetUp();
+
+    // We enable termination on OOM - just as Chrome does at early
+    // initialization - and test that UncheckedMalloc and  UncheckedCalloc
+    // properly by-pass this in order to allow the caller to handle OOM.
+    base::EnableTerminationOnOutOfMemory();
+  }
+};
+
+// TODO(b.kelemen): make UncheckedMalloc and UncheckedCalloc work
+// on Windows as well.
+// UncheckedMalloc() and UncheckedCalloc() work as regular malloc()/calloc()
+// under sanitizer tools.
+#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+TEST_F(OutOfMemoryHandledTest, UncheckedMalloc) {
+  EXPECT_TRUE(base::UncheckedMalloc(kSafeMallocSize, &value_));
+  EXPECT_TRUE(value_ != NULL);
+  free(value_);
+
+  EXPECT_FALSE(base::UncheckedMalloc(test_size_, &value_));
+  EXPECT_TRUE(value_ == NULL);
+}
+
+TEST_F(OutOfMemoryHandledTest, UncheckedCalloc) {
+  EXPECT_TRUE(base::UncheckedCalloc(1, kSafeMallocSize, &value_));
+  EXPECT_TRUE(value_ != NULL);
+  const char* bytes = static_cast<const char*>(value_);
+  for (size_t i = 0; i < kSafeMallocSize; ++i)
+    EXPECT_EQ(0, bytes[i]);
+  free(value_);
+
+  EXPECT_TRUE(
+      base::UncheckedCalloc(kSafeCallocItems, kSafeCallocSize, &value_));
+  EXPECT_TRUE(value_ != NULL);
+  bytes = static_cast<const char*>(value_);
+  for (size_t i = 0; i < (kSafeCallocItems * kSafeCallocSize); ++i)
+    EXPECT_EQ(0, bytes[i]);
+  free(value_);
+
+  EXPECT_FALSE(base::UncheckedCalloc(1, test_size_, &value_));
+  EXPECT_TRUE(value_ == NULL);
+}
+#endif  // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
+#endif  // !defined(OS_ANDROID) && !defined(OS_OPENBSD) && !defined(OS_WIN)
diff --git a/base/process/memory_win.cc b/base/process/memory_win.cc
index c53a1be..668214c 100644
--- a/base/process/memory_win.cc
+++ b/base/process/memory_win.cc
@@ -82,4 +82,15 @@
   return instance;
 }
 
+// TODO(b.kelemen): implement it with the required semantics. On Linux this is
+// implemented with a weak symbol that is overridden by tcmalloc. This is
+// neccessary because base cannot have a direct dependency on tcmalloc. Since
+// weak symbols are not supported on Windows this will involve some build time
+// magic, much like what is done for libcrt in order to override the allocation
+// functions.
+bool UncheckedMalloc(size_t size, void** result) {
+  *result = malloc(size);
+  return *result != NULL;
+}
+
 }  // namespace base
diff --git a/base/process/process_util_unittest.cc b/base/process/process_util_unittest.cc
index 41a8dd6..250b06a 100644
--- a/base/process/process_util_unittest.cc
+++ b/base/process/process_util_unittest.cc
@@ -235,7 +235,8 @@
 // This test intentionally crashes, so we don't need to run it under
 // AddressSanitizer.
 // TODO(jschuh): crbug.com/175753 Fix this in Win64 bots.
-#if defined(ADDRESS_SANITIZER) || (defined(OS_WIN) && defined(ARCH_CPU_X86_64))
+#if defined(ADDRESS_SANITIZER) || \
+    (defined(OS_WIN) && defined(ARCH_CPU_X86_64)) || defined(SYZYASAN)
 #define MAYBE_GetTerminationStatusCrash DISABLED_GetTerminationStatusCrash
 #else
 #define MAYBE_GetTerminationStatusCrash GetTerminationStatusCrash
diff --git a/base/security_unittest.cc b/base/security_unittest.cc
index d613f34..6735f6a 100644
--- a/base/security_unittest.cc
+++ b/base/security_unittest.cc
@@ -43,11 +43,11 @@
 }
 
 // - NO_TCMALLOC (should be defined if compiled with use_allocator!="tcmalloc")
-// - ADDRESS_SANITIZER because it has its own memory allocator
+// - ADDRESS_SANITIZER and SYZYASAN because they have their own memory allocator
 // - IOS does not use tcmalloc
 // - OS_MACOSX does not use tcmalloc
 #if !defined(NO_TCMALLOC) && !defined(ADDRESS_SANITIZER) && \
-    !defined(OS_IOS) && !defined(OS_MACOSX)
+    !defined(OS_IOS) && !defined(OS_MACOSX) && !defined(SYZYASAN)
   #define TCMALLOC_TEST(function) function
 #else
   #define TCMALLOC_TEST(function) DISABLED_##function
diff --git a/base/synchronization/condition_variable_unittest.cc b/base/synchronization/condition_variable_unittest.cc
index ee554ff..5f947a9 100644
--- a/base/synchronization/condition_variable_unittest.cc
+++ b/base/synchronization/condition_variable_unittest.cc
@@ -101,7 +101,6 @@
   int GetNumThreadsTakingAssignments() const;
   int GetNumThreadsCompletingTasks() const;
   int GetNumberOfCompletedTasks() const;
-  TimeDelta GetWorkTime() const;
 
   void SetWorkTime(TimeDelta delay);
   void SetTaskCount(int count);
@@ -651,10 +650,6 @@
   return total;
 }
 
-TimeDelta WorkQueue::GetWorkTime() const {
-  return worker_delay_;
-}
-
 void WorkQueue::SetWorkTime(TimeDelta delay) {
   worker_delay_ = delay;
 }
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index ae15fd5..ed100eb 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/config/ui.gni")
 
 static_library("test_support_base") {
-  external = true
   sources = [
     "expectations/expectation.cc",
     "expectations/expectation.h",
@@ -125,7 +124,6 @@
 }
 
 static_library("test_support_perf") {
-  external = true
   sources = [
     "run_all_perftests.cc",
   ]
@@ -142,7 +140,6 @@
 }
 
 static_library("run_all_unittests") {
-  external = true
   sources = [
     "run_all_unittests.cc",
   ]
diff --git a/base/test/test_timeouts.cc b/base/test/test_timeouts.cc
index 467c0fe..5302626 100644
--- a/base/test/test_timeouts.cc
+++ b/base/test/test_timeouts.cc
@@ -16,7 +16,7 @@
 
 // ASan and TSan instrument each memory access. This may slow the execution
 // down significantly.
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER)
+#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) || defined(SYZYASAN)
 static const int kTimeoutMultiplier = 2;
 #else
 static const int kTimeoutMultiplier = 1;
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-arm.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-arm.mk
index 5b965b2..a422f18 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-arm.mk
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-mips.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-mips.mk
index cd1c67c..b58872b 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-mips.mk
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86.mk
index 51a276b..8c8b315 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86.mk
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86_64.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86_64.mk
new file mode 100644
index 0000000..03074a5
--- /dev/null
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.darwin-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_third_party_dynamic_annotations_dynamic_annotations_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/third_party/dynamic_annotations/dynamic_annotations.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_third_party_dynamic_annotations_dynamic_annotations_gyp
+
+# Alias gyp target name.
+.PHONY: dynamic_annotations
+dynamic_annotations: base_third_party_dynamic_annotations_dynamic_annotations_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-arm.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-arm.mk
index 5b965b2..a422f18 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-arm.mk
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-mips.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-mips.mk
index cd1c67c..b58872b 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-mips.mk
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86.mk
index 51a276b..8c8b315 100644
--- a/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86.mk
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86_64.mk b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86_64.mk
new file mode 100644
index 0000000..03074a5
--- /dev/null
+++ b/base/third_party/dynamic_annotations/dynamic_annotations.target.linux-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := base_third_party_dynamic_annotations_dynamic_annotations_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	base/third_party/dynamic_annotations/dynamic_annotations.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: base_third_party_dynamic_annotations_dynamic_annotations_gyp
+
+# Alias gyp target name.
+.PHONY: dynamic_annotations
+dynamic_annotations: base_third_party_dynamic_annotations_dynamic_annotations_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/base/third_party/nspr/BUILD.gn b/base/third_party/nspr/BUILD.gn
index 9852f5d..c67874a 100644
--- a/base/third_party/nspr/BUILD.gn
+++ b/base/third_party/nspr/BUILD.gn
@@ -3,19 +3,9 @@
 # found in the LICENSE file.
 
 static_library("nspr") {
-  external = true
   sources = [
-    "prcpucfg.h",
-    "prcpucfg_freebsd.h",
-    "prcpucfg_linux.h",
-    "prcpucfg_mac.h",
-    "prcpucfg_nacl.h",
-    "prcpucfg_openbsd.h",
-    "prcpucfg_solaris.h",
-    "prcpucfg_win.h",
     "prtime.cc",
     "prtime.h",
-    "prtypes.h",
   ]
 
   # In GYP this project is part of base, so it uses the base implementation
diff --git a/base/third_party/nspr/prcpucfg.h b/base/third_party/nspr/prcpucfg.h
deleted file mode 100644
index d6ebb47..0000000
--- a/base/third_party/nspr/prcpucfg.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2008, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-#ifndef BASE_THIRD_PARTY_NSPR_PRCPUCFG_H__
-#define BASE_THIRD_PARTY_NSPR_PRCPUCFG_H__
-
-#if defined(WIN32)
-#include "base/third_party/nspr/prcpucfg_win.h"
-#elif defined(__APPLE__)
-#include "base/third_party/nspr/prcpucfg_mac.h"
-#elif defined(__native_client__)
-#include "base/third_party/nspr/prcpucfg_nacl.h"
-#elif defined(__linux__) || defined(ANDROID)
-#include "base/third_party/nspr/prcpucfg_linux.h"
-#elif defined(__FreeBSD__)
-#include "base/third_party/nspr/prcpucfg_freebsd.h"
-#elif defined(__OpenBSD__)
-#include "base/third_party/nspr/prcpucfg_openbsd.h"
-#elif defined(__sun)
-#include "base/third_party/nspr/prcpucfg_solaris.h"
-#else
-#error Provide a prcpucfg.h appropriate for your platform
-#endif
-
-#endif  // BASE_THIRD_PARTY_NSPR_PRCPUCFG_H__
diff --git a/base/third_party/nspr/prcpucfg_freebsd.h b/base/third_party/nspr/prcpucfg_freebsd.h
deleted file mode 100644
index 76d3542..0000000
--- a/base/third_party/nspr/prcpucfg_freebsd.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nspr_cpucfg___
-#define nspr_cpucfg___
-
-#ifndef XP_UNIX
-#define XP_UNIX
-#endif
-
-#ifndef FREEBSD
-#define FREEBSD
-#endif
-
-#define PR_AF_INET6 28  /* same as AF_INET6 */
-
-#ifndef HAVE_LONG_LONG
-#define HAVE_LONG_LONG
-#endif
-
-#if defined(__i386__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#undef	HAVE_ALIGNED_DOUBLES
-#undef	HAVE_ALIGNED_LONGLONGS
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-
-#elif defined(__alpha__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-
-#elif defined(__sparc__)
-
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN 1
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-
-#elif defined(__ia64__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#elif defined(__amd64__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#else
-
-#error "Unknown CPU architecture"
-
-#endif
-
-#ifndef NO_NSPR_10_SUPPORT
-
-#define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
-#define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
-#define BYTES_PER_INT 		PR_BYTES_PER_INT
-#define BYTES_PER_INT64		PR_BYTES_PER_INT64
-#define BYTES_PER_LONG		PR_BYTES_PER_LONG
-#define BYTES_PER_FLOAT		PR_BYTES_PER_FLOAT
-#define BYTES_PER_DOUBLE	PR_BYTES_PER_DOUBLE
-#define BYTES_PER_WORD		PR_BYTES_PER_WORD
-#define BYTES_PER_DWORD		PR_BYTES_PER_DWORD
-
-#define BITS_PER_BYTE		PR_BITS_PER_BYTE
-#define BITS_PER_SHORT		PR_BITS_PER_SHORT
-#define BITS_PER_INT		PR_BITS_PER_INT
-#define BITS_PER_INT64		PR_BITS_PER_INT64
-#define BITS_PER_LONG		PR_BITS_PER_LONG
-#define BITS_PER_FLOAT		PR_BITS_PER_FLOAT
-#define BITS_PER_DOUBLE		PR_BITS_PER_DOUBLE
-#define BITS_PER_WORD		PR_BITS_PER_WORD
-
-#define BITS_PER_BYTE_LOG2	PR_BITS_PER_BYTE_LOG2
-#define BITS_PER_SHORT_LOG2	PR_BITS_PER_SHORT_LOG2
-#define BITS_PER_INT_LOG2	PR_BITS_PER_INT_LOG2
-#define BITS_PER_INT64_LOG2	PR_BITS_PER_INT64_LOG2
-#define BITS_PER_LONG_LOG2	PR_BITS_PER_LONG_LOG2
-#define BITS_PER_FLOAT_LOG2	PR_BITS_PER_FLOAT_LOG2
-#define BITS_PER_DOUBLE_LOG2 	PR_BITS_PER_DOUBLE_LOG2
-#define BITS_PER_WORD_LOG2	PR_BITS_PER_WORD_LOG2
-
-#define ALIGN_OF_SHORT		PR_ALIGN_OF_SHORT
-#define ALIGN_OF_INT		PR_ALIGN_OF_INT
-#define ALIGN_OF_LONG		PR_ALIGN_OF_LONG
-#define ALIGN_OF_INT64		PR_ALIGN_OF_INT64
-#define ALIGN_OF_FLOAT		PR_ALIGN_OF_FLOAT
-#define ALIGN_OF_DOUBLE		PR_ALIGN_OF_DOUBLE
-#define ALIGN_OF_POINTER	PR_ALIGN_OF_POINTER
-#define ALIGN_OF_WORD		PR_ALIGN_OF_WORD
-
-#define BYTES_PER_WORD_LOG2	PR_BYTES_PER_WORD_LOG2
-#define BYTES_PER_DWORD_LOG2	PR_BYTES_PER_DWORD_LOG2
-#define WORDS_PER_DWORD_LOG2	PR_WORDS_PER_DWORD_LOG2
-
-#endif /* NO_NSPR_10_SUPPORT */
-
-#endif /* nspr_cpucfg___ */
diff --git a/base/third_party/nspr/prcpucfg_linux.h b/base/third_party/nspr/prcpucfg_linux.h
deleted file mode 100644
index 45d6bf9..0000000
--- a/base/third_party/nspr/prcpucfg_linux.h
+++ /dev/null
@@ -1,809 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nspr_cpucfg___
-#define nspr_cpucfg___
-
-#ifndef XP_UNIX
-#define XP_UNIX
-#endif
-
-#ifndef LINUX
-#define LINUX
-#endif
-
-#define PR_AF_INET6 10  /* same as AF_INET6 */
-
-#ifdef __powerpc64__
-
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN    1
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__powerpc__)
-
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN    1
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__alpha)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#define PR_BYTES_PER_WORD_LOG2  3
-#define PR_BYTES_PER_DWORD_LOG2 3
-
-#elif defined(__ia64__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#define PR_BYTES_PER_WORD_LOG2  3
-#define PR_BYTES_PER_DWORD_LOG2 3
-
-#elif defined(__x86_64__)
-
-#ifdef __ILP32__
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#else
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#define PR_BYTES_PER_WORD_LOG2  3
-#define PR_BYTES_PER_DWORD_LOG2 3
-
-#endif
-
-#elif defined(__mc68000__)
-
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN 1
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     2
-#define PR_ALIGN_OF_LONG    2
-#define PR_ALIGN_OF_INT64   2
-#define PR_ALIGN_OF_FLOAT   2
-#define PR_ALIGN_OF_DOUBLE  2
-#define PR_ALIGN_OF_POINTER 2
-#define PR_ALIGN_OF_WORD    2
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__sparc__)
-
-#undef	IS_LITTLE_ENDIAN
-#define	IS_BIG_ENDIAN 1
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__i386__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__mips__)
-
-#ifdef __MIPSEB__
-#define IS_BIG_ENDIAN 1
-#undef  IS_LITTLE_ENDIAN
-#elif defined(__MIPSEL__)
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#else
-#error "Unknown MIPS endianness."
-#endif
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__arm__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__aarch64__)
-
-#ifdef __AARCH64EB__
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN 1
-#elif defined(__AARCH64EL__)
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#else
-#error "Unknown Aarch64 endianness."
-#endif
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#define PR_BYTES_PER_WORD_LOG2  3
-#define PR_BYTES_PER_DWORD_LOG2 3
-
-#elif defined(__hppa__)
-
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN    1
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__s390x__)
-
-#define IS_BIG_ENDIAN 1
-#undef  IS_LITTLE_ENDIAN
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__s390__)
-
-#define IS_BIG_ENDIAN 1
-#undef  IS_LITTLE_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#else
-
-#error "Unknown CPU architecture"
-
-#endif
-
-#define	HAVE_LONG_LONG
-#if PR_ALIGN_OF_DOUBLE == 8
-#define HAVE_ALIGNED_DOUBLES
-#endif
-#if PR_ALIGN_OF_INT64 == 8
-#define HAVE_ALIGNED_LONGLONGS
-#endif
-
-#ifndef NO_NSPR_10_SUPPORT
-
-#define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
-#define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
-#define BYTES_PER_INT 		PR_BYTES_PER_INT
-#define BYTES_PER_INT64		PR_BYTES_PER_INT64
-#define BYTES_PER_LONG		PR_BYTES_PER_LONG
-#define BYTES_PER_FLOAT		PR_BYTES_PER_FLOAT
-#define BYTES_PER_DOUBLE	PR_BYTES_PER_DOUBLE
-#define BYTES_PER_WORD		PR_BYTES_PER_WORD
-#define BYTES_PER_DWORD		PR_BYTES_PER_DWORD
-
-#define BITS_PER_BYTE		PR_BITS_PER_BYTE
-#define BITS_PER_SHORT		PR_BITS_PER_SHORT
-#define BITS_PER_INT		PR_BITS_PER_INT
-#define BITS_PER_INT64		PR_BITS_PER_INT64
-#define BITS_PER_LONG		PR_BITS_PER_LONG
-#define BITS_PER_FLOAT		PR_BITS_PER_FLOAT
-#define BITS_PER_DOUBLE		PR_BITS_PER_DOUBLE
-#define BITS_PER_WORD		PR_BITS_PER_WORD
-
-#define BITS_PER_BYTE_LOG2	PR_BITS_PER_BYTE_LOG2
-#define BITS_PER_SHORT_LOG2	PR_BITS_PER_SHORT_LOG2
-#define BITS_PER_INT_LOG2	PR_BITS_PER_INT_LOG2
-#define BITS_PER_INT64_LOG2	PR_BITS_PER_INT64_LOG2
-#define BITS_PER_LONG_LOG2	PR_BITS_PER_LONG_LOG2
-#define BITS_PER_FLOAT_LOG2	PR_BITS_PER_FLOAT_LOG2
-#define BITS_PER_DOUBLE_LOG2 	PR_BITS_PER_DOUBLE_LOG2
-#define BITS_PER_WORD_LOG2	PR_BITS_PER_WORD_LOG2
-
-#define ALIGN_OF_SHORT		PR_ALIGN_OF_SHORT
-#define ALIGN_OF_INT		PR_ALIGN_OF_INT
-#define ALIGN_OF_LONG		PR_ALIGN_OF_LONG
-#define ALIGN_OF_INT64		PR_ALIGN_OF_INT64
-#define ALIGN_OF_FLOAT		PR_ALIGN_OF_FLOAT
-#define ALIGN_OF_DOUBLE		PR_ALIGN_OF_DOUBLE
-#define ALIGN_OF_POINTER	PR_ALIGN_OF_POINTER
-#define ALIGN_OF_WORD		PR_ALIGN_OF_WORD
-
-#define BYTES_PER_WORD_LOG2	PR_BYTES_PER_WORD_LOG2
-#define BYTES_PER_DWORD_LOG2	PR_BYTES_PER_DWORD_LOG2
-#define WORDS_PER_DWORD_LOG2	PR_WORDS_PER_DWORD_LOG2
-
-#endif /* NO_NSPR_10_SUPPORT */
-
-#endif /* nspr_cpucfg___ */
diff --git a/base/third_party/nspr/prcpucfg_mac.h b/base/third_party/nspr/prcpucfg_mac.h
deleted file mode 100644
index 60bea8e..0000000
--- a/base/third_party/nspr/prcpucfg_mac.h
+++ /dev/null
@@ -1,197 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nspr_cpucfg___
-#define nspr_cpucfg___
-
-#ifndef XP_UNIX
-#define XP_UNIX
-#endif
-
-#define PR_AF_INET6 30  /* same as AF_INET6 */
-
-#ifdef __LITTLE_ENDIAN__
-#undef IS_BIG_ENDIAN
-#define  IS_LITTLE_ENDIAN 1
-#else
-#undef IS_LITTLE_ENDIAN
-#define  IS_BIG_ENDIAN 1
-#endif
-
-#ifdef __x86_64__
-#define IS_64
-#endif
-
-#ifndef HAVE_LONG_LONG
-#define	HAVE_LONG_LONG
-#endif
-#undef	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS 1
-
-#ifdef IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-#define PR_BITS_PER_DWORD   64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-#define PR_BITS_PER_DWORD_LOG2  6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-#define PR_ALIGN_OF_DWORD   8
-
-#else /* IS_64 */
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-#define PR_BITS_PER_DWORD   64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#endif /* IS_64 */
-
-#ifndef NO_NSPR_10_SUPPORT
-
-#define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
-#define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
-#define BYTES_PER_INT 		PR_BYTES_PER_INT
-#define BYTES_PER_INT64		PR_BYTES_PER_INT64
-#define BYTES_PER_LONG		PR_BYTES_PER_LONG
-#define BYTES_PER_FLOAT		PR_BYTES_PER_FLOAT
-#define BYTES_PER_DOUBLE	PR_BYTES_PER_DOUBLE
-#define BYTES_PER_WORD		PR_BYTES_PER_WORD
-#define BYTES_PER_DWORD		PR_BYTES_PER_DWORD
-
-#define BITS_PER_BYTE		PR_BITS_PER_BYTE
-#define BITS_PER_SHORT		PR_BITS_PER_SHORT
-#define BITS_PER_INT		PR_BITS_PER_INT
-#define BITS_PER_INT64		PR_BITS_PER_INT64
-#define BITS_PER_LONG		PR_BITS_PER_LONG
-#define BITS_PER_FLOAT		PR_BITS_PER_FLOAT
-#define BITS_PER_DOUBLE		PR_BITS_PER_DOUBLE
-#define BITS_PER_WORD		PR_BITS_PER_WORD
-
-#define BITS_PER_BYTE_LOG2	PR_BITS_PER_BYTE_LOG2
-#define BITS_PER_SHORT_LOG2	PR_BITS_PER_SHORT_LOG2
-#define BITS_PER_INT_LOG2	PR_BITS_PER_INT_LOG2
-#define BITS_PER_INT64_LOG2	PR_BITS_PER_INT64_LOG2
-#define BITS_PER_LONG_LOG2	PR_BITS_PER_LONG_LOG2
-#define BITS_PER_FLOAT_LOG2	PR_BITS_PER_FLOAT_LOG2
-#define BITS_PER_DOUBLE_LOG2 	PR_BITS_PER_DOUBLE_LOG2
-#define BITS_PER_WORD_LOG2	PR_BITS_PER_WORD_LOG2
-
-#define ALIGN_OF_SHORT		PR_ALIGN_OF_SHORT
-#define ALIGN_OF_INT		PR_ALIGN_OF_INT
-#define ALIGN_OF_LONG		PR_ALIGN_OF_LONG
-#define ALIGN_OF_INT64		PR_ALIGN_OF_INT64
-#define ALIGN_OF_FLOAT		PR_ALIGN_OF_FLOAT
-#define ALIGN_OF_DOUBLE		PR_ALIGN_OF_DOUBLE
-#define ALIGN_OF_POINTER	PR_ALIGN_OF_POINTER
-#define ALIGN_OF_WORD		PR_ALIGN_OF_WORD
-
-#define BYTES_PER_WORD_LOG2	PR_BYTES_PER_WORD_LOG2
-#define BYTES_PER_DWORD_LOG2	PR_BYTES_PER_DWORD_LOG2
-#define WORDS_PER_DWORD_LOG2	PR_WORDS_PER_DWORD_LOG2
-
-#endif /* NO_NSPR_10_SUPPORT */
-
-#endif /* nspr_cpucfg___ */
-
diff --git a/base/third_party/nspr/prcpucfg_nacl.h b/base/third_party/nspr/prcpucfg_nacl.h
deleted file mode 100644
index ba92726..0000000
--- a/base/third_party/nspr/prcpucfg_nacl.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nspr_cpucfg___
-#define nspr_cpucfg___
-
-#ifndef XP_UNIX
-#define XP_UNIX
-#endif
-
-#ifndef LINUX
-#define LINUX
-#endif
-
-#define PR_AF_INET6 10  /* same as AF_INET6 */
-
-#if defined(__x86_64__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#define PR_BYTES_PER_WORD_LOG2  3
-#define PR_BYTES_PER_DWORD_LOG2 3
-
-#elif defined(__i386__) || defined(__pnacl__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__arm__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#elif defined(__mips__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 4
-#define PR_ALIGN_OF_WORD    4
-
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#else
-
-#error "Unknown CPU architecture"
-
-#endif
-
-#define	HAVE_LONG_LONG
-#if PR_ALIGN_OF_DOUBLE == 8
-#define HAVE_ALIGNED_DOUBLES
-#endif
-#if PR_ALIGN_OF_INT64 == 8
-#define HAVE_ALIGNED_LONGLONGS
-#endif
-
-#ifndef NO_NSPR_10_SUPPORT
-
-#define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
-#define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
-#define BYTES_PER_INT 		PR_BYTES_PER_INT
-#define BYTES_PER_INT64		PR_BYTES_PER_INT64
-#define BYTES_PER_LONG		PR_BYTES_PER_LONG
-#define BYTES_PER_FLOAT		PR_BYTES_PER_FLOAT
-#define BYTES_PER_DOUBLE	PR_BYTES_PER_DOUBLE
-#define BYTES_PER_WORD		PR_BYTES_PER_WORD
-#define BYTES_PER_DWORD		PR_BYTES_PER_DWORD
-
-#define BITS_PER_BYTE		PR_BITS_PER_BYTE
-#define BITS_PER_SHORT		PR_BITS_PER_SHORT
-#define BITS_PER_INT		PR_BITS_PER_INT
-#define BITS_PER_INT64		PR_BITS_PER_INT64
-#define BITS_PER_LONG		PR_BITS_PER_LONG
-#define BITS_PER_FLOAT		PR_BITS_PER_FLOAT
-#define BITS_PER_DOUBLE		PR_BITS_PER_DOUBLE
-#define BITS_PER_WORD		PR_BITS_PER_WORD
-
-#define BITS_PER_BYTE_LOG2	PR_BITS_PER_BYTE_LOG2
-#define BITS_PER_SHORT_LOG2	PR_BITS_PER_SHORT_LOG2
-#define BITS_PER_INT_LOG2	PR_BITS_PER_INT_LOG2
-#define BITS_PER_INT64_LOG2	PR_BITS_PER_INT64_LOG2
-#define BITS_PER_LONG_LOG2	PR_BITS_PER_LONG_LOG2
-#define BITS_PER_FLOAT_LOG2	PR_BITS_PER_FLOAT_LOG2
-#define BITS_PER_DOUBLE_LOG2 	PR_BITS_PER_DOUBLE_LOG2
-#define BITS_PER_WORD_LOG2	PR_BITS_PER_WORD_LOG2
-
-#define ALIGN_OF_SHORT		PR_ALIGN_OF_SHORT
-#define ALIGN_OF_INT		PR_ALIGN_OF_INT
-#define ALIGN_OF_LONG		PR_ALIGN_OF_LONG
-#define ALIGN_OF_INT64		PR_ALIGN_OF_INT64
-#define ALIGN_OF_FLOAT		PR_ALIGN_OF_FLOAT
-#define ALIGN_OF_DOUBLE		PR_ALIGN_OF_DOUBLE
-#define ALIGN_OF_POINTER	PR_ALIGN_OF_POINTER
-#define ALIGN_OF_WORD		PR_ALIGN_OF_WORD
-
-#define BYTES_PER_WORD_LOG2	PR_BYTES_PER_WORD_LOG2
-#define BYTES_PER_DWORD_LOG2	PR_BYTES_PER_DWORD_LOG2
-#define WORDS_PER_DWORD_LOG2	PR_WORDS_PER_DWORD_LOG2
-
-#endif /* NO_NSPR_10_SUPPORT */
-
-#endif /* nspr_cpucfg___ */
diff --git a/base/third_party/nspr/prcpucfg_openbsd.h b/base/third_party/nspr/prcpucfg_openbsd.h
deleted file mode 100644
index 93c5b32..0000000
--- a/base/third_party/nspr/prcpucfg_openbsd.h
+++ /dev/null
@@ -1,337 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nspr_cpucfg___
-#define nspr_cpucfg___
-
-#ifndef XP_UNIX
-#define XP_UNIX
-#endif
-
-#ifndef OPENBSD
-#define OPENBSD
-#endif
-
-#define PR_AF_INET6 28  /* same as AF_INET6 */
-
-#ifndef HAVE_LONG_LONG
-#define HAVE_LONG_LONG
-#endif
-
-#if defined(__i386__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#undef	HAVE_ALIGNED_DOUBLES
-#undef	HAVE_ALIGNED_LONGLONGS
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-
-#elif defined(__alpha__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-
-#elif defined(__sparc__)
-
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN 1
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-
-#elif defined(__ia64__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#elif defined(__amd64__)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-#define PR_ALIGN_OF_WORD    8
-
-#else
-
-#error "Unknown CPU architecture"
-
-#endif
-
-#ifndef NO_NSPR_10_SUPPORT
-
-#define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
-#define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
-#define BYTES_PER_INT 		PR_BYTES_PER_INT
-#define BYTES_PER_INT64		PR_BYTES_PER_INT64
-#define BYTES_PER_LONG		PR_BYTES_PER_LONG
-#define BYTES_PER_FLOAT		PR_BYTES_PER_FLOAT
-#define BYTES_PER_DOUBLE	PR_BYTES_PER_DOUBLE
-#define BYTES_PER_WORD		PR_BYTES_PER_WORD
-#define BYTES_PER_DWORD		PR_BYTES_PER_DWORD
-
-#define BITS_PER_BYTE		PR_BITS_PER_BYTE
-#define BITS_PER_SHORT		PR_BITS_PER_SHORT
-#define BITS_PER_INT		PR_BITS_PER_INT
-#define BITS_PER_INT64		PR_BITS_PER_INT64
-#define BITS_PER_LONG		PR_BITS_PER_LONG
-#define BITS_PER_FLOAT		PR_BITS_PER_FLOAT
-#define BITS_PER_DOUBLE		PR_BITS_PER_DOUBLE
-#define BITS_PER_WORD		PR_BITS_PER_WORD
-
-#define BITS_PER_BYTE_LOG2	PR_BITS_PER_BYTE_LOG2
-#define BITS_PER_SHORT_LOG2	PR_BITS_PER_SHORT_LOG2
-#define BITS_PER_INT_LOG2	PR_BITS_PER_INT_LOG2
-#define BITS_PER_INT64_LOG2	PR_BITS_PER_INT64_LOG2
-#define BITS_PER_LONG_LOG2	PR_BITS_PER_LONG_LOG2
-#define BITS_PER_FLOAT_LOG2	PR_BITS_PER_FLOAT_LOG2
-#define BITS_PER_DOUBLE_LOG2 	PR_BITS_PER_DOUBLE_LOG2
-#define BITS_PER_WORD_LOG2	PR_BITS_PER_WORD_LOG2
-
-#define ALIGN_OF_SHORT		PR_ALIGN_OF_SHORT
-#define ALIGN_OF_INT		PR_ALIGN_OF_INT
-#define ALIGN_OF_LONG		PR_ALIGN_OF_LONG
-#define ALIGN_OF_INT64		PR_ALIGN_OF_INT64
-#define ALIGN_OF_FLOAT		PR_ALIGN_OF_FLOAT
-#define ALIGN_OF_DOUBLE		PR_ALIGN_OF_DOUBLE
-#define ALIGN_OF_POINTER	PR_ALIGN_OF_POINTER
-#define ALIGN_OF_WORD		PR_ALIGN_OF_WORD
-
-#define BYTES_PER_WORD_LOG2	PR_BYTES_PER_WORD_LOG2
-#define BYTES_PER_DWORD_LOG2	PR_BYTES_PER_DWORD_LOG2
-#define WORDS_PER_DWORD_LOG2	PR_WORDS_PER_DWORD_LOG2
-
-#endif /* NO_NSPR_10_SUPPORT */
-
-#endif /* nspr_cpucfg___ */
diff --git a/base/third_party/nspr/prcpucfg_solaris.h b/base/third_party/nspr/prcpucfg_solaris.h
deleted file mode 100644
index 81313e5..0000000
--- a/base/third_party/nspr/prcpucfg_solaris.h
+++ /dev/null
@@ -1,203 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nspr_cpucfg___
-#define nspr_cpucfg___
-
-#ifndef XP_UNIX
-#define XP_UNIX
-#endif
-
-#ifndef SOLARIS
-#define SOLARIS
-#endif
-
-#define PR_AF_INET6 26  /* same as AF_INET6 */
-
-#if defined(sparc) || defined(__sparc)
-#undef  IS_LITTLE_ENDIAN
-#define IS_BIG_ENDIAN 1
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_DOUBLE  8
-#if defined(__sparcv9)
-#define IS_64
-#endif
-#elif defined(__x86_64)
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_DOUBLE  8
-#define IS_64
-#elif defined(i386) || defined(__i386)
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define PR_ALIGN_OF_INT64   4
-#define PR_ALIGN_OF_DOUBLE  4
-#else
-#error unknown processor
-#endif
-
-#ifdef IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   8
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   8
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   3
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    64
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   6
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_POINTER 8
-
-#else /* IS_64 */
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_DOUBLE 8
-#define PR_BYTES_PER_WORD   4
-#define PR_BYTES_PER_DWORD  8
-#define PR_BYTES_PER_WORD_LOG2   2
-#define PR_BYTES_PER_DWORD_LOG2  3
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_DOUBLE  64
-#define PR_BITS_PER_WORD    32
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_DOUBLE_LOG2 6
-#define PR_BITS_PER_WORD_LOG2   5
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_POINTER 4
-
-#endif /* IS_64 */
-
-#ifndef HAVE_LONG_LONG
-#define	HAVE_LONG_LONG
-#endif
-#define	HAVE_ALIGNED_DOUBLES
-#define	HAVE_ALIGNED_LONGLONGS
-
-#ifndef NO_NSPR_10_SUPPORT
-
-#define BYTES_PER_BYTE		PR_BYTES_PER_BYTE
-#define BYTES_PER_SHORT 	PR_BYTES_PER_SHORT
-#define BYTES_PER_INT 		PR_BYTES_PER_INT
-#define BYTES_PER_INT64		PR_BYTES_PER_INT64
-#define BYTES_PER_LONG		PR_BYTES_PER_LONG
-#define BYTES_PER_FLOAT		PR_BYTES_PER_FLOAT
-#define BYTES_PER_DOUBLE	PR_BYTES_PER_DOUBLE
-#define BYTES_PER_WORD		PR_BYTES_PER_WORD
-#define BYTES_PER_DWORD		PR_BYTES_PER_DWORD
-
-#define BITS_PER_BYTE		PR_BITS_PER_BYTE
-#define BITS_PER_SHORT		PR_BITS_PER_SHORT
-#define BITS_PER_INT		PR_BITS_PER_INT
-#define BITS_PER_INT64		PR_BITS_PER_INT64
-#define BITS_PER_LONG		PR_BITS_PER_LONG
-#define BITS_PER_FLOAT		PR_BITS_PER_FLOAT
-#define BITS_PER_DOUBLE		PR_BITS_PER_DOUBLE
-#define BITS_PER_WORD		PR_BITS_PER_WORD
-
-#define BITS_PER_BYTE_LOG2	PR_BITS_PER_BYTE_LOG2
-#define BITS_PER_SHORT_LOG2	PR_BITS_PER_SHORT_LOG2
-#define BITS_PER_INT_LOG2	PR_BITS_PER_INT_LOG2
-#define BITS_PER_INT64_LOG2	PR_BITS_PER_INT64_LOG2
-#define BITS_PER_LONG_LOG2	PR_BITS_PER_LONG_LOG2
-#define BITS_PER_FLOAT_LOG2	PR_BITS_PER_FLOAT_LOG2
-#define BITS_PER_DOUBLE_LOG2 	PR_BITS_PER_DOUBLE_LOG2
-#define BITS_PER_WORD_LOG2	PR_BITS_PER_WORD_LOG2
-
-#define ALIGN_OF_SHORT		PR_ALIGN_OF_SHORT
-#define ALIGN_OF_INT		PR_ALIGN_OF_INT
-#define ALIGN_OF_LONG		PR_ALIGN_OF_LONG
-#define ALIGN_OF_INT64		PR_ALIGN_OF_INT64
-#define ALIGN_OF_FLOAT		PR_ALIGN_OF_FLOAT
-#define ALIGN_OF_DOUBLE		PR_ALIGN_OF_DOUBLE
-#define ALIGN_OF_POINTER	PR_ALIGN_OF_POINTER
-#define ALIGN_OF_WORD		PR_ALIGN_OF_WORD
-
-#define BYTES_PER_WORD_LOG2	PR_BYTES_PER_WORD_LOG2
-#define BYTES_PER_DWORD_LOG2	PR_BYTES_PER_DWORD_LOG2
-#define WORDS_PER_DWORD_LOG2	PR_WORDS_PER_DWORD_LOG2
-
-#endif /* NO_NSPR_10_SUPPORT */
-
-#endif /* ifndef nspr_cpucfg___ */
diff --git a/base/third_party/nspr/prcpucfg_win.h b/base/third_party/nspr/prcpucfg_win.h
deleted file mode 100644
index 4ad5345..0000000
--- a/base/third_party/nspr/prcpucfg_win.h
+++ /dev/null
@@ -1,256 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef nspr_cpucfg___
-#define nspr_cpucfg___
-
-#ifndef XP_PC
-#define XP_PC
-#endif
-
-#ifndef WIN32
-#define WIN32
-#endif
-
-#ifndef WIN95
-#define WIN95
-#endif
-
-#define PR_AF_INET6 23  /* same as AF_INET6 */
-
-#if defined(_M_IX86) || defined(_X86_)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_WORD	4
-#define PR_BYTES_PER_DWORD	8
-#define PR_BYTES_PER_DOUBLE 8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_WORD	32
-#define PR_BITS_PER_DWORD	64
-#define PR_BITS_PER_DOUBLE  64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_WORD_LOG2	5
-#define PR_BITS_PER_DWORD_LOG2	6
-#define PR_BITS_PER_DOUBLE_LOG2 6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_WORD	4
-#define PR_ALIGN_OF_DWORD	8
-#define PR_ALIGN_OF_DOUBLE  4
-#define PR_ALIGN_OF_POINTER 4
-
-#define PR_BYTES_PER_WORD_LOG2	2
-#define PR_BYTES_PER_DWORD_LOG2	2
-
-#elif defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_WORD	8
-#define PR_BYTES_PER_DWORD	8
-#define PR_BYTES_PER_DOUBLE 8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_WORD	64
-#define PR_BITS_PER_DWORD	64
-#define PR_BITS_PER_DOUBLE  64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_WORD_LOG2	6
-#define PR_BITS_PER_DWORD_LOG2	6
-#define PR_BITS_PER_DOUBLE_LOG2 6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_WORD	8
-#define PR_ALIGN_OF_DWORD	8
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-
-#define PR_BYTES_PER_WORD_LOG2	3
-#define PR_BYTES_PER_DWORD_LOG2	3
-
-#elif defined(_M_IA64) || defined(_IA64_)
-
-#define IS_LITTLE_ENDIAN 1
-#undef  IS_BIG_ENDIAN
-#define IS_64
-
-#define PR_BYTES_PER_BYTE   1
-#define PR_BYTES_PER_SHORT  2
-#define PR_BYTES_PER_INT    4
-#define PR_BYTES_PER_INT64  8
-#define PR_BYTES_PER_LONG   4
-#define PR_BYTES_PER_FLOAT  4
-#define PR_BYTES_PER_WORD	8
-#define PR_BYTES_PER_DWORD	8
-#define PR_BYTES_PER_DOUBLE 8
-
-#define PR_BITS_PER_BYTE    8
-#define PR_BITS_PER_SHORT   16
-#define PR_BITS_PER_INT     32
-#define PR_BITS_PER_INT64   64
-#define PR_BITS_PER_LONG    32
-#define PR_BITS_PER_FLOAT   32
-#define PR_BITS_PER_WORD	64
-#define PR_BITS_PER_DWORD	64
-#define PR_BITS_PER_DOUBLE  64
-
-#define PR_BITS_PER_BYTE_LOG2   3
-#define PR_BITS_PER_SHORT_LOG2  4
-#define PR_BITS_PER_INT_LOG2    5
-#define PR_BITS_PER_INT64_LOG2  6
-#define PR_BITS_PER_LONG_LOG2   5
-#define PR_BITS_PER_FLOAT_LOG2  5
-#define PR_BITS_PER_WORD_LOG2	6
-#define PR_BITS_PER_DWORD_LOG2	6
-#define PR_BITS_PER_DOUBLE_LOG2 6
-
-#define PR_ALIGN_OF_SHORT   2
-#define PR_ALIGN_OF_INT     4
-#define PR_ALIGN_OF_LONG    4
-#define PR_ALIGN_OF_INT64   8
-#define PR_ALIGN_OF_FLOAT   4
-#define PR_ALIGN_OF_WORD	8
-#define PR_ALIGN_OF_DWORD	8
-#define PR_ALIGN_OF_DOUBLE  8
-#define PR_ALIGN_OF_POINTER 8
-
-#define PR_BYTES_PER_WORD_LOG2	3
-#define PR_BYTES_PER_DWORD_LOG2	3
-
-#else /* defined(_M_IX86) || defined(_X86_) */
-
-#error unknown processor architecture
-
-#endif /* defined(_M_IX86) || defined(_X86_) */
-
-#ifndef HAVE_LONG_LONG
-#define HAVE_LONG_LONG
-#endif
-
-#ifndef NO_NSPR_10_SUPPORT
-
-#define BYTES_PER_BYTE      PR_BYTES_PER_BYTE
-#define BYTES_PER_SHORT     PR_BYTES_PER_SHORT
-#define BYTES_PER_INT       PR_BYTES_PER_INT
-#define BYTES_PER_INT64     PR_BYTES_PER_INT64
-#define BYTES_PER_LONG      PR_BYTES_PER_LONG
-#define BYTES_PER_FLOAT     PR_BYTES_PER_FLOAT
-#define BYTES_PER_DOUBLE    PR_BYTES_PER_DOUBLE
-#define BYTES_PER_WORD      PR_BYTES_PER_WORD
-#define BYTES_PER_DWORD     PR_BYTES_PER_DWORD
-
-#define BITS_PER_BYTE       PR_BITS_PER_BYTE
-#define BITS_PER_SHORT      PR_BITS_PER_SHORT
-#define BITS_PER_INT        PR_BITS_PER_INT
-#define BITS_PER_INT64      PR_BITS_PER_INT64
-#define BITS_PER_LONG       PR_BITS_PER_LONG
-#define BITS_PER_FLOAT      PR_BITS_PER_FLOAT
-#define BITS_PER_DOUBLE     PR_BITS_PER_DOUBLE
-#define BITS_PER_WORD       PR_BITS_PER_WORD
-
-#define BITS_PER_BYTE_LOG2  PR_BITS_PER_BYTE_LOG2
-#define BITS_PER_SHORT_LOG2 PR_BITS_PER_SHORT_LOG2
-#define BITS_PER_INT_LOG2   PR_BITS_PER_INT_LOG2
-#define BITS_PER_INT64_LOG2 PR_BITS_PER_INT64_LOG2
-#define BITS_PER_LONG_LOG2  PR_BITS_PER_LONG_LOG2
-#define BITS_PER_FLOAT_LOG2 PR_BITS_PER_FLOAT_LOG2
-#define BITS_PER_DOUBLE_LOG2    PR_BITS_PER_DOUBLE_LOG2
-#define BITS_PER_WORD_LOG2  PR_BITS_PER_WORD_LOG2
-
-#define ALIGN_OF_SHORT      PR_ALIGN_OF_SHORT
-#define ALIGN_OF_INT        PR_ALIGN_OF_INT
-#define ALIGN_OF_LONG       PR_ALIGN_OF_LONG
-#define ALIGN_OF_INT64      PR_ALIGN_OF_INT64
-#define ALIGN_OF_FLOAT      PR_ALIGN_OF_FLOAT
-#define ALIGN_OF_DOUBLE     PR_ALIGN_OF_DOUBLE
-#define ALIGN_OF_POINTER    PR_ALIGN_OF_POINTER
-#define ALIGN_OF_WORD       PR_ALIGN_OF_WORD
-
-#define BYTES_PER_WORD_LOG2		PR_BYTES_PER_WORD_LOG2
-#define BYTES_PER_DWORD_LOG2    PR_BYTES_PER_DWORD_LOG2
-#define WORDS_PER_DWORD_LOG2    PR_WORDS_PER_DWORD_LOG2
-
-#endif /* NO_NSPR_10_SUPPORT */
-
-#endif /* nspr_cpucfg___ */
diff --git a/base/third_party/nspr/prtime.cc b/base/third_party/nspr/prtime.cc
index 5fc89c5..0c97bc1 100644
--- a/base/third_party/nspr/prtime.cc
+++ b/base/third_party/nspr/prtime.cc
@@ -443,10 +443,6 @@
 PRTimeParameters
 PR_GMTParameters(const PRExplodedTime *gmt)
 {
-#if defined(XP_MAC)
-#pragma unused (gmt)
-#endif
-
     PRTimeParameters retVal = { 0, 0 };
     return retVal;
 }
diff --git a/base/third_party/nspr/prtime.h b/base/third_party/nspr/prtime.h
index ffbedec..01c009e 100644
--- a/base/third_party/nspr/prtime.h
+++ b/base/third_party/nspr/prtime.h
@@ -52,10 +52,26 @@
 #ifndef BASE_PRTIME_H__
 #define BASE_PRTIME_H__
 
+#include <stdint.h>
+
 #include "base/base_export.h"
-#include "base/third_party/nspr/prtypes.h"
+
+typedef int8_t PRInt8;
+typedef int16_t PRInt16;
+typedef int32_t PRInt32;
+typedef int64_t PRInt64;
+typedef int PRIntn;
+
+typedef PRIntn PRBool;
+#define PR_TRUE 1
+#define PR_FALSE 0
+
+typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
 
 #define PR_ASSERT DCHECK
+#define PR_CALLBACK
+#define PR_INT16_MAX 32767
+#define NSPR_API(__type) extern __type
 
 #define LL_I2L(l, i)    ((l) = (PRInt64)(i))
 #define LL_MUL(r, a, b) ((r) = (a) * (b))
diff --git a/base/third_party/nspr/prtypes.h b/base/third_party/nspr/prtypes.h
deleted file mode 100644
index 630df81..0000000
--- a/base/third_party/nspr/prtypes.h
+++ /dev/null
@@ -1,558 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape Portable Runtime (NSPR).
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-/*
-** File:                prtypes.h
-** Description: Definitions of NSPR's basic types
-**
-** Prototypes and macros used to make up for deficiencies that we have found
-** in ANSI environments.
-**
-** Since we do not wrap <stdlib.h> and all the other standard headers, authors
-** of portable code will not know in general that they need these definitions.
-** Instead of requiring these authors to find the dependent uses in their code
-** and take the following steps only in those C files, we take steps once here
-** for all C files.
-**/
-
-#ifndef prtypes_h___
-#define prtypes_h___
-
-#ifdef MDCPUCFG
-#include MDCPUCFG
-#else
-#include "base/third_party/nspr/prcpucfg.h"
-#endif
-
-#include <stddef.h>
-
-/***********************************************************************
-** MACROS:      PR_EXTERN
-**              PR_IMPLEMENT
-** DESCRIPTION:
-**      These are only for externally visible routines and globals.  For
-**      internal routines, just use "extern" for type checking and that
-**      will not export internal cross-file or forward-declared symbols.
-**      Define a macro for declaring procedures return types. We use this to
-**      deal with windoze specific type hackery for DLL definitions. Use
-**      PR_EXTERN when the prototype for the method is declared. Use
-**      PR_IMPLEMENT for the implementation of the method.
-**
-** Example:
-**   in dowhim.h
-**     PR_EXTERN( void ) DoWhatIMean( void );
-**   in dowhim.c
-**     PR_IMPLEMENT( void ) DoWhatIMean( void ) { return; }
-**
-**
-***********************************************************************/
-#if 1
-
-/*
-** Local change: the portions of NSPR used by the base module are
-** implementation details.  NSPR symbols do not need to be exported beyond
-** the base module.  For all platforms, avoid decorating functions with
-** specific visibility and access keywords.
-*/
-
-#define PR_EXPORT(__type) extern __type
-#define PR_EXPORT_DATA(__type) extern __type
-#define PR_IMPORT(__type) extern __type
-#define PR_IMPORT_DATA(__type) extern __type
-
-#define PR_EXTERN(__type) extern __type
-#define PR_IMPLEMENT(__type) __type
-#define PR_EXTERN_DATA(__type) extern __type
-#define PR_IMPLEMENT_DATA(__type) __type
-
-#define PR_CALLBACK
-#define PR_CALLBACK_DECL
-#define PR_STATIC_CALLBACK(__x) static __x
-
-#elif defined(WIN32)
-
-#define PR_EXPORT(__type) extern __declspec(dllexport) __type
-#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
-#define PR_IMPORT(__type) __declspec(dllimport) __type
-#define PR_IMPORT_DATA(__type) __declspec(dllimport) __type
-
-#define PR_EXTERN(__type) extern __declspec(dllexport) __type
-#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
-#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
-#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
-
-#define PR_CALLBACK
-#define PR_CALLBACK_DECL
-#define PR_STATIC_CALLBACK(__x) static __x
-
-#elif defined(XP_BEOS)
-
-#define PR_EXPORT(__type) extern __declspec(dllexport) __type
-#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
-#define PR_IMPORT(__type) extern __declspec(dllexport) __type
-#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type
-
-#define PR_EXTERN(__type) extern __declspec(dllexport) __type
-#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
-#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
-#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
-
-#define PR_CALLBACK
-#define PR_CALLBACK_DECL
-#define PR_STATIC_CALLBACK(__x) static __x
-
-#elif defined(XP_OS2) && defined(__declspec)
-
-#define PR_EXPORT(__type) extern __declspec(dllexport) __type
-#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
-#define PR_IMPORT(__type) extern  __declspec(dllimport) __type
-#define PR_IMPORT_DATA(__type) extern __declspec(dllimport) __type
-
-#define PR_EXTERN(__type) extern __declspec(dllexport) __type
-#define PR_IMPLEMENT(__type) __declspec(dllexport) __type
-#define PR_EXTERN_DATA(__type) extern __declspec(dllexport) __type
-#define PR_IMPLEMENT_DATA(__type) __declspec(dllexport) __type
-
-#define PR_CALLBACK
-#define PR_CALLBACK_DECL
-#define PR_STATIC_CALLBACK(__x) static __x
-
-#elif defined(SYMBIAN)
-
-#define PR_EXPORT(__type) extern __declspec(dllexport) __type
-#define PR_EXPORT_DATA(__type) extern __declspec(dllexport) __type
-#ifdef __WINS__
-#define PR_IMPORT(__type) extern __declspec(dllexport) __type
-#define PR_IMPORT_DATA(__type) extern __declspec(dllexport) __type
-#else
-#define PR_IMPORT(__type) extern __declspec(dllimport) __type
-#define PR_IMPORT_DATA(__type) extern __declspec(dllimport) __type
-#endif
-
-#define PR_EXTERN(__type) extern __type
-#define PR_IMPLEMENT(__type) __type
-#define PR_EXTERN_DATA(__type) extern __type
-#define PR_IMPLEMENT_DATA(__type) __type
-
-#define PR_CALLBACK
-#define PR_CALLBACK_DECL
-#define PR_STATIC_CALLBACK(__x) static __x
-
-#else /* Unix */
-
-/* GCC 3.3 and later support the visibility attribute. */
-#if (__GNUC__ >= 4) || \
-    (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
-#define PR_VISIBILITY_DEFAULT __attribute__((visibility("default")))
-#else
-#define PR_VISIBILITY_DEFAULT
-#endif
-
-#define PR_EXPORT(__type) extern PR_VISIBILITY_DEFAULT __type
-#define PR_EXPORT_DATA(__type) extern PR_VISIBILITY_DEFAULT __type
-#define PR_IMPORT(__type) extern PR_VISIBILITY_DEFAULT __type
-#define PR_IMPORT_DATA(__type) extern PR_VISIBILITY_DEFAULT __type
-
-#define PR_EXTERN(__type) extern PR_VISIBILITY_DEFAULT __type
-#define PR_IMPLEMENT(__type) PR_VISIBILITY_DEFAULT __type
-#define PR_EXTERN_DATA(__type) extern PR_VISIBILITY_DEFAULT __type
-#define PR_IMPLEMENT_DATA(__type) PR_VISIBILITY_DEFAULT __type
-#define PR_CALLBACK
-#define PR_CALLBACK_DECL
-#define PR_STATIC_CALLBACK(__x) static __x
-
-#endif
-
-#if defined(_NSPR_BUILD_)
-#define NSPR_API(__type) PR_EXPORT(__type)
-#define NSPR_DATA_API(__type) PR_EXPORT_DATA(__type)
-#else
-#define NSPR_API(__type) PR_IMPORT(__type)
-#define NSPR_DATA_API(__type) PR_IMPORT_DATA(__type)
-#endif
-
-/***********************************************************************
-** MACROS:      PR_BEGIN_MACRO
-**              PR_END_MACRO
-** DESCRIPTION:
-**      Macro body brackets so that macros with compound statement definitions
-**      behave syntactically more like functions when called.
-***********************************************************************/
-#define PR_BEGIN_MACRO  do {
-#define PR_END_MACRO    } while (0)
-
-/***********************************************************************
-** MACROS:      PR_BEGIN_EXTERN_C
-**              PR_END_EXTERN_C
-** DESCRIPTION:
-**      Macro shorthands for conditional C++ extern block delimiters.
-***********************************************************************/
-#ifdef __cplusplus
-#define PR_BEGIN_EXTERN_C       extern "C" {
-#define PR_END_EXTERN_C         }
-#else
-#define PR_BEGIN_EXTERN_C
-#define PR_END_EXTERN_C
-#endif
-
-/***********************************************************************
-** MACROS:      PR_BIT
-**              PR_BITMASK
-** DESCRIPTION:
-** Bit masking macros.  XXX n must be <= 31 to be portable
-***********************************************************************/
-#define PR_BIT(n)       ((PRUint32)1 << (n))
-#define PR_BITMASK(n)   (PR_BIT(n) - 1)
-
-/***********************************************************************
-** MACROS:      PR_ROUNDUP
-**              PR_MIN
-**              PR_MAX
-**              PR_ABS
-** DESCRIPTION:
-**      Commonly used macros for operations on compatible types.
-***********************************************************************/
-#define PR_ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y))
-#define PR_MIN(x,y)     ((x)<(y)?(x):(y))
-#define PR_MAX(x,y)     ((x)>(y)?(x):(y))
-#define PR_ABS(x)       ((x)<0?-(x):(x))
-
-PR_BEGIN_EXTERN_C
-
-/************************************************************************
-** TYPES:       PRUint8
-**              PRInt8
-** DESCRIPTION:
-**  The int8 types are known to be 8 bits each. There is no type that
-**      is equivalent to a plain "char". 
-************************************************************************/
-#if PR_BYTES_PER_BYTE == 1
-typedef unsigned char PRUint8;
-/*
-** Some cfront-based C++ compilers do not like 'signed char' and
-** issue the warning message:
-**     warning: "signed" not implemented (ignored)
-** For these compilers, we have to define PRInt8 as plain 'char'.
-** Make sure that plain 'char' is indeed signed under these compilers.
-*/
-#if (defined(HPUX) && defined(__cplusplus) \
-        && !defined(__GNUC__) && __cplusplus < 199707L) \
-    || (defined(SCO) && defined(__cplusplus) \
-        && !defined(__GNUC__) && __cplusplus == 1L)
-typedef char PRInt8;
-#else
-typedef signed char PRInt8;
-#endif
-#else
-#error No suitable type for PRInt8/PRUint8
-#endif
-
-/************************************************************************
- * MACROS:      PR_INT8_MAX
- *              PR_INT8_MIN
- *              PR_UINT8_MAX
- * DESCRIPTION:
- *  The maximum and minimum values of a PRInt8 or PRUint8.
-************************************************************************/
-
-#define PR_INT8_MAX 127
-#define PR_INT8_MIN (-128)
-#define PR_UINT8_MAX 255U
-
-/************************************************************************
-** TYPES:       PRUint16
-**              PRInt16
-** DESCRIPTION:
-**  The int16 types are known to be 16 bits each. 
-************************************************************************/
-#if PR_BYTES_PER_SHORT == 2
-typedef unsigned short PRUint16;
-typedef short PRInt16;
-#else
-#error No suitable type for PRInt16/PRUint16
-#endif
-
-/************************************************************************
- * MACROS:      PR_INT16_MAX
- *              PR_INT16_MIN
- *              PR_UINT16_MAX
- * DESCRIPTION:
- *  The maximum and minimum values of a PRInt16 or PRUint16.
-************************************************************************/
-
-#define PR_INT16_MAX 32767
-#define PR_INT16_MIN (-32768)
-#define PR_UINT16_MAX 65535U
-
-/************************************************************************
-** TYPES:       PRUint32
-**              PRInt32
-** DESCRIPTION:
-**  The int32 types are known to be 32 bits each. 
-************************************************************************/
-#if PR_BYTES_PER_INT == 4
-typedef unsigned int PRUint32;
-typedef int PRInt32;
-#define PR_INT32(x)  x
-#define PR_UINT32(x) x ## U
-#elif PR_BYTES_PER_LONG == 4
-typedef unsigned long PRUint32;
-typedef long PRInt32;
-#define PR_INT32(x)  x ## L
-#define PR_UINT32(x) x ## UL
-#else
-#error No suitable type for PRInt32/PRUint32
-#endif
-
-/************************************************************************
- * MACROS:      PR_INT32_MAX
- *              PR_INT32_MIN
- *              PR_UINT32_MAX
- * DESCRIPTION:
- *  The maximum and minimum values of a PRInt32 or PRUint32.
-************************************************************************/
-
-#define PR_INT32_MAX PR_INT32(2147483647)
-#define PR_INT32_MIN (-PR_INT32_MAX - 1)
-#define PR_UINT32_MAX PR_UINT32(4294967295)
-
-/************************************************************************
-** TYPES:       PRUint64
-**              PRInt64
-** DESCRIPTION:
-**  The int64 types are known to be 64 bits each. Care must be used when
-**      declaring variables of type PRUint64 or PRInt64. Different hardware
-**      architectures and even different compilers have varying support for
-**      64 bit values. The only guaranteed portability requires the use of
-**      the LL_ macros (see prlong.h).
-************************************************************************/
-#ifdef HAVE_LONG_LONG
-/* Keep this in sync with prlong.h. */
-/*
- * On 64-bit Mac OS X, uint64 needs to be defined as unsigned long long to
- * match uint64_t, otherwise our uint64 typedef conflicts with the uint64
- * typedef in cssmconfig.h, which CoreServices.h includes indirectly.
- */
-#if PR_BYTES_PER_LONG == 8 && !defined(__APPLE__)
-typedef long PRInt64;
-typedef unsigned long PRUint64;
-#elif defined(WIN32) && !defined(__GNUC__)
-typedef __int64  PRInt64;
-typedef unsigned __int64 PRUint64;
-#else
-typedef long long PRInt64;
-typedef unsigned long long PRUint64;
-#endif /* PR_BYTES_PER_LONG == 8 */
-#else  /* !HAVE_LONG_LONG */
-typedef struct {
-#ifdef IS_LITTLE_ENDIAN
-    PRUint32 lo, hi;
-#else
-    PRUint32 hi, lo;
-#endif
-} PRInt64;
-typedef PRInt64 PRUint64;
-#endif /* !HAVE_LONG_LONG */
-
-/************************************************************************
-** TYPES:       PRUintn
-**              PRIntn
-** DESCRIPTION:
-**  The PRIntn types are most appropriate for automatic variables. They are
-**      guaranteed to be at least 16 bits, though various architectures may
-**      define them to be wider (e.g., 32 or even 64 bits). These types are
-**      never valid for fields of a structure. 
-************************************************************************/
-#if PR_BYTES_PER_INT >= 2
-typedef int PRIntn;
-typedef unsigned int PRUintn;
-#else
-#error 'sizeof(int)' not sufficient for platform use
-#endif
-
-/************************************************************************
-** TYPES:       PRFloat64
-** DESCRIPTION:
-**  NSPR's floating point type is always 64 bits. 
-************************************************************************/
-typedef double          PRFloat64;
-
-/************************************************************************
-** TYPES:       PRSize
-** DESCRIPTION:
-**  A type for representing the size of objects. 
-************************************************************************/
-typedef size_t PRSize;
-
-
-/************************************************************************
-** TYPES:       PROffset32, PROffset64
-** DESCRIPTION:
-**  A type for representing byte offsets from some location. 
-************************************************************************/
-typedef PRInt32 PROffset32;
-typedef PRInt64 PROffset64;
-
-/************************************************************************
-** TYPES:       PRPtrDiff
-** DESCRIPTION:
-**  A type for pointer difference. Variables of this type are suitable
-**      for storing a pointer or pointer subtraction. 
-************************************************************************/
-typedef ptrdiff_t PRPtrdiff;
-
-/************************************************************************
-** TYPES:       PRUptrdiff
-** DESCRIPTION:
-**  A type for pointer difference. Variables of this type are suitable
-**      for storing a pointer or pointer sutraction. 
-************************************************************************/
-#ifdef _WIN64
-typedef PRUint64 PRUptrdiff;
-#else
-typedef unsigned long PRUptrdiff;
-#endif
-
-/************************************************************************
-** TYPES:       PRBool
-** DESCRIPTION:
-**  Use PRBool for variables and parameter types. Use PR_FALSE and PR_TRUE
-**      for clarity of target type in assignments and actual arguments. Use
-**      'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans
-**      just as you would C int-valued conditions. 
-************************************************************************/
-typedef PRIntn PRBool;
-#define PR_TRUE 1
-#define PR_FALSE 0
-
-/************************************************************************
-** TYPES:       PRPackedBool
-** DESCRIPTION:
-**  Use PRPackedBool within structs where bitfields are not desirable
-**      but minimum and consistant overhead matters.
-************************************************************************/
-typedef PRUint8 PRPackedBool;
-
-/*
-** Status code used by some routines that have a single point of failure or 
-** special status return.
-*/
-typedef enum { PR_FAILURE = -1, PR_SUCCESS = 0 } PRStatus;
-
-#ifndef __PRUNICHAR__
-#define __PRUNICHAR__
-#ifdef WIN32
-typedef wchar_t PRUnichar;
-#else
-typedef PRUint16 PRUnichar;
-#endif
-#endif
-
-/*
-** WARNING: The undocumented data types PRWord and PRUword are
-** only used in the garbage collection and arena code.  Do not
-** use PRWord and PRUword in new code.
-**
-** A PRWord is an integer that is the same size as a void*.
-** It implements the notion of a "word" in the Java Virtual
-** Machine.  (See Sec. 3.4 "Words", The Java Virtual Machine
-** Specification, Addison-Wesley, September 1996.
-** http://java.sun.com/docs/books/vmspec/index.html.)
-*/
-#ifdef _WIN64
-typedef PRInt64 PRWord;
-typedef PRUint64 PRUword;
-#else
-typedef long PRWord;
-typedef unsigned long PRUword;
-#endif
-
-#if defined(NO_NSPR_10_SUPPORT)
-#else
-/********* ???????????????? FIX ME       ??????????????????????????? *****/
-/********************** Some old definitions until pr=>ds transition is done ***/
-/********************** Also, we are still using NSPR 1.0. GC ******************/
-/*
-** Fundamental NSPR macros, used nearly everywhere.
-*/
-
-#define PR_PUBLIC_API		PR_IMPLEMENT
-
-/*
-** Macro body brackets so that macros with compound statement definitions
-** behave syntactically more like functions when called.
-*/
-#define NSPR_BEGIN_MACRO        do {
-#define NSPR_END_MACRO          } while (0)
-
-/*
-** Macro shorthands for conditional C++ extern block delimiters.
-*/
-#ifdef NSPR_BEGIN_EXTERN_C
-#undef NSPR_BEGIN_EXTERN_C
-#endif
-#ifdef NSPR_END_EXTERN_C
-#undef NSPR_END_EXTERN_C
-#endif
-
-#ifdef __cplusplus
-#define NSPR_BEGIN_EXTERN_C     extern "C" {
-#define NSPR_END_EXTERN_C       }
-#else
-#define NSPR_BEGIN_EXTERN_C
-#define NSPR_END_EXTERN_C
-#endif
-
-/********* ????????????? End Fix me ?????????????????????????????? *****/
-#endif /* NO_NSPR_10_SUPPORT */
-
-/*
-** Compile-time assert. "condition" must be a constant expression.
-** The macro can be used only in places where an "extern" declaration is
-** allowed.
-*/
-#define PR_STATIC_ASSERT(condition) \
-    extern void pr_static_assert(int arg[(condition) ? 1 : -1])
-
-PR_END_EXTERN_C
-
-#if !defined(NO_NSPR_10_SUPPORT)
-#include "base/basictypes.h"
-#endif
-
-#endif /* prtypes_h___ */
-
diff --git a/base/third_party/symbolize/BUILD.gn b/base/third_party/symbolize/BUILD.gn
index cb2d1ce..79bc133 100644
--- a/base/third_party/symbolize/BUILD.gn
+++ b/base/third_party/symbolize/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 static_library("symbolize") {
-  external = true
   sources = [
     "config.h",
     "demangle.cc",
diff --git a/base/third_party/xdg_user_dirs/BUILD.gn b/base/third_party/xdg_user_dirs/BUILD.gn
index eda4e02..f2145b7 100644
--- a/base/third_party/xdg_user_dirs/BUILD.gn
+++ b/base/third_party/xdg_user_dirs/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 static_library("xdg_user_dirs") {
-  external = true
   sources = [
     "xdg_user_dir_lookup.cc",
     "xdg_user_dir_lookup.h",
diff --git a/base/threading/platform_thread_mac.mm b/base/threading/platform_thread_mac.mm
index d81a286..486181f 100644
--- a/base/threading/platform_thread_mac.mm
+++ b/base/threading/platform_thread_mac.mm
@@ -5,13 +5,13 @@
 #include "base/threading/platform_thread.h"
 
 #import <Foundation/Foundation.h>
-#include <algorithm>
-#include <dlfcn.h>
 #include <mach/mach.h>
 #include <mach/mach_time.h>
 #include <mach/thread_policy.h>
 #include <sys/resource.h>
 
+#include <algorithm>
+
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/threading/thread_id_name_manager.h"
@@ -45,21 +45,13 @@
   ThreadIdNameManager::GetInstance()->SetName(CurrentId(), name);
   tracked_objects::ThreadData::InitializeThreadContext(name);
 
-  // pthread_setname_np is only available in 10.6 or later, so test
-  // for it at runtime.
-  int (*dynamic_pthread_setname_np)(const char*);
-  *reinterpret_cast<void**>(&dynamic_pthread_setname_np) =
-      dlsym(RTLD_DEFAULT, "pthread_setname_np");
-  if (!dynamic_pthread_setname_np)
-    return;
-
   // Mac OS X does not expose the length limit of the name, so
   // hardcode it.
   const int kMaxNameLength = 63;
   std::string shortened_name = std::string(name).substr(0, kMaxNameLength);
   // pthread_setname() fails (harmlessly) in the sandbox, ignore when it does.
   // See http://crbug.com/47058
-  dynamic_pthread_setname_np(shortened_name.c_str());
+  pthread_setname_np(shortened_name.c_str());
 }
 
 namespace {
diff --git a/base/time/time.cc b/base/time/time.cc
index 2c63886..f731356 100644
--- a/base/time/time.cc
+++ b/base/time/time.cc
@@ -11,7 +11,6 @@
 #include "base/lazy_instance.h"
 #include "base/logging.h"
 #include "base/third_party/nspr/prtime.h"
-#include "base/third_party/nspr/prtypes.h"
 
 namespace base {
 
diff --git a/base/tools_sanity_unittest.cc b/base/tools_sanity_unittest.cc
index c763a32..b1da3e1 100644
--- a/base/tools_sanity_unittest.cc
+++ b/base/tools_sanity_unittest.cc
@@ -20,7 +20,7 @@
 
 // Helper for memory accesses that can potentially corrupt memory or cause a
 // crash during a native run.
-#if defined(ADDRESS_SANITIZER)
+#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
 #if defined(OS_IOS)
 // EXPECT_DEATH is not supported on IOS.
 #define HARMFUL_ACCESS(action,error_regexp) do { action; } while (0)
@@ -94,10 +94,10 @@
   leak[4] = 1;  // Make sure the allocated memory is used.
 }
 
-#if defined(ADDRESS_SANITIZER) && (defined(OS_IOS) || defined(OS_WIN))
+#if (defined(ADDRESS_SANITIZER) && defined(OS_IOS)) || defined(SYZYASAN)
 // Because iOS doesn't support death tests, each of the following tests will
-// crash the whole program under Asan. On Windows Asan is based on SyzyAsan, the
-// error report mecanism is different than with Asan so those test will fail.
+// crash the whole program under Asan. On Windows Asan is based on SyzyAsan; the
+// error report mechanism is different than with Asan so these tests will fail.
 #define MAYBE_AccessesToNewMemory DISABLED_AccessesToNewMemory
 #define MAYBE_AccessesToMallocMemory DISABLED_AccessesToMallocMemory
 #else
@@ -113,7 +113,7 @@
 // tests should be put back under the (defined(OS_IOS) || defined(OS_WIN))
 // clause above.
 // See also http://crbug.com/172614.
-#if defined(ADDRESS_SANITIZER)
+#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
 #define MAYBE_SingleElementDeletedWithBraces \
     DISABLED_SingleElementDeletedWithBraces
 #define MAYBE_ArrayDeletedWithoutBraces DISABLED_ArrayDeletedWithoutBraces
@@ -135,7 +135,7 @@
 }
 
 TEST(ToolsSanityTest, MAYBE_ArrayDeletedWithoutBraces) {
-#if !defined(ADDRESS_SANITIZER)
+#if !defined(ADDRESS_SANITIZER) && !defined(SYZYASAN)
   // This test may corrupt memory if not run under Valgrind or compiled with
   // AddressSanitizer.
   if (!RunningOnValgrind())
@@ -161,7 +161,7 @@
   delete [] foo;
 }
 
-#if defined(ADDRESS_SANITIZER)
+#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
 TEST(ToolsSanityTest, DISABLED_AddressSanitizerNullDerefCrashTest) {
   // Intentionally crash to make sure AddressSanitizer is running.
   // This test should not be ran on bots.
diff --git a/base/win/iat_patch_function.cc b/base/win/iat_patch_function.cc
index 923dc04..21c3995 100644
--- a/base/win/iat_patch_function.cc
+++ b/base/win/iat_patch_function.cc
@@ -285,5 +285,10 @@
   return error;
 }
 
+void* IATPatchFunction::original_function() const {
+  DCHECK(is_patched());
+  return original_function_;
+}
+
 }  // namespace win
 }  // namespace base
diff --git a/base/win/iat_patch_function.h b/base/win/iat_patch_function.h
index 3ae1f3c..5026e0e 100644
--- a/base/win/iat_patch_function.h
+++ b/base/win/iat_patch_function.h
@@ -57,6 +57,8 @@
     return (NULL != intercept_function_);
   }
 
+  void* original_function() const;
+
  private:
   HMODULE module_handle_;
   void* intercept_function_;
diff --git a/base/x11/edid_parser_x11.cc b/base/x11/edid_parser_x11.cc
deleted file mode 100644
index 74b14b6..0000000
--- a/base/x11/edid_parser_x11.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/x11/edid_parser_x11.h"
-
-#include <X11/extensions/Xrandr.h>
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-
-#include "base/hash.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_util.h"
-#include "base/sys_byteorder.h"
-
-namespace {
-
-// Returns 64-bit persistent ID for the specified manufacturer's ID and
-// product_code_hash, and the index of the output it is connected to.
-// |output_index| is used to distinguish the displays of the same type. For
-// example, swapping two identical display between two outputs will not be
-// treated as swap. The 'serial number' field in EDID isn't used here because
-// it is not guaranteed to have unique number and it may have the same fixed
-// value (like 0).
-int64 GetID(uint16 manufacturer_id,
-            uint32 product_code_hash,
-            uint8 output_index) {
-  return ((static_cast<int64>(manufacturer_id) << 40) |
-          (static_cast<int64>(product_code_hash) << 8) | output_index);
-}
-
-bool IsRandRAvailable() {
-  int randr_version_major = 0;
-  int randr_version_minor = 0;
-  static bool is_randr_available = XRRQueryVersion(
-      base::MessagePumpX11::GetDefaultXDisplay(),
-      &randr_version_major, &randr_version_minor);
-  return is_randr_available;
-}
-
-}  // namespace
-
-namespace base {
-
-bool GetEDIDProperty(XID output, unsigned long* nitems, unsigned char** prop) {
-  if (!IsRandRAvailable())
-    return false;
-
-  Display* display = base::MessagePumpX11::GetDefaultXDisplay();
-
-  static Atom edid_property = XInternAtom(
-      base::MessagePumpX11::GetDefaultXDisplay(),
-      RR_PROPERTY_RANDR_EDID, false);
-
-  bool has_edid_property = false;
-  int num_properties = 0;
-  Atom* properties = XRRListOutputProperties(display, output, &num_properties);
-  for (int i = 0; i < num_properties; ++i) {
-    if (properties[i] == edid_property) {
-      has_edid_property = true;
-      break;
-    }
-  }
-  XFree(properties);
-  if (!has_edid_property)
-    return false;
-
-  Atom actual_type;
-  int actual_format;
-  unsigned long bytes_after;
-  XRRGetOutputProperty(display,
-                       output,
-                       edid_property,
-                       0,                // offset
-                       128,              // length
-                       false,            // _delete
-                       false,            // pending
-                       AnyPropertyType,  // req_type
-                       &actual_type,
-                       &actual_format,
-                       nitems,
-                       &bytes_after,
-                       prop);
-  DCHECK_EQ(XA_INTEGER, actual_type);
-  DCHECK_EQ(8, actual_format);
-  return true;
-}
-
-bool GetDisplayId(XID output_id, size_t output_index, int64* display_id_out) {
-  unsigned long nitems = 0;
-  unsigned char* prop = NULL;
-  if (!GetEDIDProperty(output_id, &nitems, &prop))
-    return false;
-
-  bool result =
-      GetDisplayIdFromEDID(prop, nitems, output_index, display_id_out);
-  XFree(prop);
-  return result;
-}
-
-bool GetDisplayIdFromEDID(const unsigned char* prop,
-                          unsigned long nitems,
-                          size_t output_index,
-                          int64* display_id_out) {
-  uint16 manufacturer_id = 0;
-  std::string product_name;
-
-  // ParseOutputDeviceData fails if it doesn't have product_name.
-  ParseOutputDeviceData(prop, nitems, &manufacturer_id, &product_name);
-
-  // Generates product specific value from product_name instead of product code.
-  // See crbug.com/240341
-  uint32 product_code_hash = product_name.empty() ?
-      0 : base::Hash(product_name);
-  if (manufacturer_id != 0) {
-    // An ID based on display's index will be assigned later if this call
-    // fails.
-    *display_id_out = GetID(
-        manufacturer_id, product_code_hash, output_index);
-    return true;
-  }
-  return false;
-}
-
-bool ParseOutputDeviceData(const unsigned char* prop,
-                           unsigned long nitems,
-                           uint16* manufacturer_id,
-                           std::string* human_readable_name) {
-  // See http://en.wikipedia.org/wiki/Extended_display_identification_data
-  // for the details of EDID data format.  We use the following data:
-  //   bytes 8-9: manufacturer EISA ID, in big-endian
-  //   bytes 54-125: four descriptors (18-bytes each) which may contain
-  //     the display name.
-  const unsigned int kManufacturerOffset = 8;
-  const unsigned int kManufacturerLength = 2;
-  const unsigned int kDescriptorOffset = 54;
-  const unsigned int kNumDescriptors = 4;
-  const unsigned int kDescriptorLength = 18;
-  // The specifier types.
-  const unsigned char kMonitorNameDescriptor = 0xfc;
-
-  if (manufacturer_id) {
-    if (nitems < kManufacturerOffset + kManufacturerLength) {
-      LOG(ERROR) << "too short EDID data: manifacturer id";
-      return false;
-    }
-
-    *manufacturer_id =
-        *reinterpret_cast<const uint16*>(prop + kManufacturerOffset);
-#if defined(ARCH_CPU_LITTLE_ENDIAN)
-    *manufacturer_id = base::ByteSwap(*manufacturer_id);
-#endif
-  }
-
-  if (!human_readable_name)
-    return true;
-
-  human_readable_name->clear();
-  for (unsigned int i = 0; i < kNumDescriptors; ++i) {
-    if (nitems < kDescriptorOffset + (i + 1) * kDescriptorLength)
-      break;
-
-    const unsigned char* desc_buf =
-        prop + kDescriptorOffset + i * kDescriptorLength;
-    // If the descriptor contains the display name, it has the following
-    // structure:
-    //   bytes 0-2, 4: \0
-    //   byte 3: descriptor type, defined above.
-    //   bytes 5-17: text data, ending with \r, padding with spaces
-    // we should check bytes 0-2 and 4, since it may have other values in
-    // case that the descriptor contains other type of data.
-    if (desc_buf[0] == 0 && desc_buf[1] == 0 && desc_buf[2] == 0 &&
-        desc_buf[4] == 0) {
-      if (desc_buf[3] == kMonitorNameDescriptor) {
-        std::string found_name(
-            reinterpret_cast<const char*>(desc_buf + 5), kDescriptorLength - 5);
-        TrimWhitespaceASCII(found_name, TRIM_TRAILING, human_readable_name);
-        break;
-      }
-    }
-  }
-
-  // Verify if the |human_readable_name| consists of printable characters only.
-  for (size_t i = 0; i < human_readable_name->size(); ++i) {
-    char c = (*human_readable_name)[i];
-    if (!isascii(c) || !isprint(c)) {
-      human_readable_name->clear();
-      LOG(ERROR) << "invalid EDID: human unreadable char in name";
-      return false;
-    }
-  }
-
-  return true;
-}
-
-}  // namespace base
diff --git a/base/x11/edid_parser_x11.h b/base/x11/edid_parser_x11.h
deleted file mode 100644
index 0fba0b5..0000000
--- a/base/x11/edid_parser_x11.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef BASE_X11_EDID_PARSER_X11_H_
-#define BASE_X11_EDID_PARSER_X11_H_
-
-#include <string>
-
-#include "base/base_export.h"
-#include "base/basictypes.h"
-
-typedef unsigned long XID;
-
-// EDID (Extended Display Identification Data) is a format for monitor
-// metadata. This provides a parser for the data and an interface to get it
-// from XRandR.
-
-namespace base {
-
-// Get the EDID data from the |output| and stores to |prop|. |nitem| will store
-// the number of characters |prop| will have. It doesn't take the ownership of
-// |prop|, so caller must release it by XFree().
-// Returns true if EDID property is successfully obtained. Otherwise returns
-// false and does not touch |prop| and |nitems|.
-BASE_EXPORT bool GetEDIDProperty(XID output,
-                                 unsigned long* nitems,
-                                 unsigned char** prop);
-
-// Gets the EDID data from |output| and generates the display id through
-// |GetDisplayIdFromEDID|.
-BASE_EXPORT bool GetDisplayId(XID output, size_t index,
-                              int64* display_id_out);
-
-// Generates the display id for the pair of |prop| with |nitems| length and
-// |index|, and store in |display_id_out|. Returns true if the display id is
-// successfully generated, or false otherwise.
-BASE_EXPORT bool GetDisplayIdFromEDID(const unsigned char* prop,
-                                      unsigned long nitems,
-                                      size_t index,
-                                      int64* display_id_out);
-
-// Parses |prop| as EDID data and stores extracted data into |manufacturer_id|
-// and |human_readable_name| and returns true. NULL can be passed for unwanted
-// output parameters. Some devices (especially internal displays) may not have
-// the field for |human_readable_name|, and it will return true in that case.
-BASE_EXPORT bool ParseOutputDeviceData(const unsigned char* prop,
-                                       unsigned long nitems,
-                                       uint16* manufacturer_id,
-                                       std::string* human_readable_name);
-
-}  // namespace base
-
-#endif  // BASE_X11_EDID_PARSER_X11_H_
diff --git a/base/x11/edid_parser_x11_unittest.cc b/base/x11/edid_parser_x11_unittest.cc
deleted file mode 100644
index 97e3ce1..0000000
--- a/base/x11/edid_parser_x11_unittest.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/x11/edid_parser_x11.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include <X11/extensions/Xrandr.h>
-
-namespace base {
-
-namespace {
-
-// Returns the number of characters in the string literal but doesn't count its
-// terminator NULL byte.
-#define charsize(str) (arraysize(str) - 1)
-
-// Sample EDID data extracted from real devices.
-const unsigned char kNormalDisplay[] =
-    "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01"
-    "\x02\x16\x01\x04\xb5\x40\x28\x78\xe2\x8d\x85\xad\x4f\x35\xb1\x25"
-    "\x0e\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
-    "\x01\x01\x01\x01\x01\x01\xe2\x68\x00\xa0\xa0\x40\x2e\x60\x30\x20"
-    "\x36\x00\x81\x90\x21\x00\x00\x1a\xbc\x1b\x00\xa0\x50\x20\x17\x30"
-    "\x30\x20\x36\x00\x81\x90\x21\x00\x00\x1a\x00\x00\x00\xfc\x00\x48"
-    "\x50\x20\x5a\x52\x33\x30\x77\x0a\x20\x20\x20\x20\x00\x00\x00\xff"
-    "\x00\x43\x4e\x34\x32\x30\x32\x31\x33\x37\x51\x0a\x20\x20\x00\x71";
-
-const unsigned char kInternalDisplay[] =
-    "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00"
-    "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27"
-    "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
-    "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30"
-    "\x13\x00\x05\xa3\x10\x00\x00\x19\x00\x00\x00\x0f\x00\x00\x00\x00"
-    "\x00\x00\x00\x00\x00\x23\x87\x02\x64\x00\x00\x00\x00\xfe\x00\x53"
-    "\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x00\x00\x00\xfe"
-    "\x00\x31\x32\x31\x41\x54\x31\x31\x2d\x38\x30\x31\x0a\x20\x00\x45";
-
-const unsigned char kOverscanDisplay[] =
-    "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00"
-    "\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26"
-    "\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00"
-    "\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
-    "\x45\x00\xa0\x5a\x00\x00\x00\x1e\x66\x21\x56\xaa\x51\x00\x1e\x30"
-    "\x46\x8f\x33\x00\xa0\x5a\x00\x00\x00\x1e\x00\x00\x00\xfd\x00\x18"
-    "\x4b\x0f\x51\x17\x00\x0a\x20\x20\x20\x20\x20\x20\x00\x00\x00\xfc"
-    "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d"
-    "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07"
-    "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01"
-    "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00"
-    "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00"
-    "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0"
-    "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6";
-
-const unsigned char kLP2565A[] =
-    "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x76\x26\x01\x01\x01\x01"
-    "\x02\x12\x01\x03\x80\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26"
-    "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x81\x80\x81\x99\x71\x00\xA9\x00"
-    "\xA9\x40\xB3\x00\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20"
-    "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E"
-    "\x5E\x11\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48"
-    "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF"
-    "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\xA4";
-
-const unsigned char kLP2565B[] =
-    "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x75\x26\x01\x01\x01\x01"
-    "\x02\x12\x01\x03\x6E\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26"
-    "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x71\x00\xA9\x00\xA9\x40\xA9\x4F"
-    "\xB3\x00\xD1\xC0\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20"
-    "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E"
-    "\x5E\x15\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48"
-    "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF"
-    "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\x45";
-
-}  // namespace
-
-TEST(EdidParserX11Test, ParseEDID) {
-  uint16 manufacturer_id = 0;
-  std::string human_readable_name;
-  EXPECT_TRUE(ParseOutputDeviceData(
-      kNormalDisplay, charsize(kNormalDisplay),
-      &manufacturer_id, &human_readable_name));
-  EXPECT_EQ(0x22f0u, manufacturer_id);
-  EXPECT_EQ("HP ZR30w", human_readable_name);
-
-  manufacturer_id = 0;
-  human_readable_name.clear();
-  EXPECT_TRUE(ParseOutputDeviceData(
-      kInternalDisplay, charsize(kInternalDisplay),
-      &manufacturer_id, NULL));
-  EXPECT_EQ(0x4ca3u, manufacturer_id);
-  EXPECT_EQ("", human_readable_name);
-
-  // Internal display doesn't have name.
-  EXPECT_TRUE(ParseOutputDeviceData(
-      kInternalDisplay, charsize(kInternalDisplay),
-      NULL, &human_readable_name));
-  EXPECT_TRUE(human_readable_name.empty());
-
-  manufacturer_id = 0;
-  human_readable_name.clear();
-  EXPECT_TRUE(ParseOutputDeviceData(
-      kOverscanDisplay, charsize(kOverscanDisplay),
-      &manufacturer_id, &human_readable_name));
-  EXPECT_EQ(0x4c2du, manufacturer_id);
-  EXPECT_EQ("SAMSUNG", human_readable_name);
-}
-
-TEST(EdidParserX11Test, ParseBrokenEDID) {
-  uint16 manufacturer_id = 0;
-  std::string human_readable_name;
-
-  // length == 0
-  EXPECT_FALSE(ParseOutputDeviceData(
-      kNormalDisplay, 0,
-      &manufacturer_id, &human_readable_name));
-
-  // name is broken. Copying kNormalDisplay and substitute its name data by
-  // some control code.
-  std::string display_data(
-      reinterpret_cast<const char*>(kNormalDisplay), charsize(kNormalDisplay));
-
-  // display's name data is embedded in byte 95-107 in this specific example.
-  // Fix here too when the contents of kNormalDisplay is altered.
-  display_data[97] = '\x1b';
-  EXPECT_FALSE(ParseOutputDeviceData(
-      reinterpret_cast<const unsigned char*>(display_data.data()),
-      display_data.size(),
-      &manufacturer_id, &human_readable_name));
-
-  // If |human_readable_name| isn't specified, it skips parsing the name.
-  manufacturer_id = 0;
-  EXPECT_TRUE(ParseOutputDeviceData(
-      reinterpret_cast<const unsigned char*>(display_data.data()),
-      display_data.size(),
-      &manufacturer_id, NULL));
-  EXPECT_EQ(0x22f0u, manufacturer_id);
-}
-
-TEST(EdidParserX11Test, GetDisplayId) {
-  // EDID of kLP2565A and B are slightly different but actually the same device.
-  int64 id1 = -1;
-  int64 id2 = -1;
-  EXPECT_TRUE(GetDisplayIdFromEDID(kLP2565A, charsize(kLP2565A), 0, &id1));
-  EXPECT_TRUE(GetDisplayIdFromEDID(kLP2565B, charsize(kLP2565B), 0, &id2));
-  EXPECT_EQ(id1, id2);
-  EXPECT_NE(-1, id1);
-}
-
-TEST(EdidParserX11Test, GetDisplayIdFromInternal) {
-  int64 id = -1;
-  EXPECT_TRUE(GetDisplayIdFromEDID(
-      kInternalDisplay, charsize(kInternalDisplay), 0, &id));
-  EXPECT_NE(-1, id);
-}
-
-TEST(EdidParserX11Test, GetDisplayIdFailure) {
-  int64 id = -1;
-  EXPECT_FALSE(GetDisplayIdFromEDID(NULL, 0, 0, &id));
-  EXPECT_EQ(-1, id);
-}
-
-}   // namespace base
diff --git a/build/all.gyp b/build/all.gyp
index 142c4f5..ee57a18 100644
--- a/build/all.gyp
+++ b/build/all.gyp
@@ -362,7 +362,7 @@
             'chromium_swarm_tests',
           ],
         }],
-        ['OS!="android" and OS!="ios"', {
+        ['OS!="android"', {
           'dependencies': [
             '../google_apis/gcm/gcm.gyp:gcm_unit_tests',
           ],
@@ -446,15 +446,6 @@
             }],
           ],
         }, # target_name: blink_tests
-        {
-          # TODO(jochen): Eventually remove this target after everybody and
-          # the bots started to use blink_tests only.
-          'target_name': 'all_webkit',
-          'type': 'none',
-          'dependencies': [
-            'blink_tests',
-          ],
-        }, # target_name: all_webkit
       ],
     }], # OS!=ios
     ['OS!="ios" and OS!="android"', {
@@ -1176,8 +1167,8 @@
             '../ui/message_center/message_center.gyp:*',
             '../ui/snapshot/snapshot.gyp:snapshot_unittests',
             '../ui/ui_unittests.gyp:ui_unittests',
+            '../ui/views/examples/examples.gyp:views_examples_with_content_exe',
             '../ui/views/views.gyp:views',
-            '../ui/views/views.gyp:views_examples_with_content_exe',
             '../ui/views/views.gyp:views_unittests',
             '../webkit/renderer/compositor_bindings/compositor_bindings_tests.gyp:webkit_compositor_bindings_unittests',
             'blink_tests',
diff --git a/build/android/PRESUBMIT.py b/build/android/PRESUBMIT.py
index 569482f..5431cdc 100644
--- a/build/android/PRESUBMIT.py
+++ b/build/android/PRESUBMIT.py
@@ -38,8 +38,7 @@
   output.extend(input_api.canned_checks.RunPylint(
       input_api,
       output_api,
-      white_list=[r'PRESUBMIT\.py$', r'buildbot/.*\.py$', r'pylib/.*\.py$'],
-      black_list=[r'pylib/symbols/.*\.py$'],
+      black_list=[r'pylib/symbols/.*\.py$', r'gyp/.*\.py$'],
       extra_paths_list=[
           J(), J('..', '..', 'third_party', 'android_testrunner'),
           J('buildbot')]))
diff --git a/build/android/adb_logcat_monitor.py b/build/android/adb_logcat_monitor.py
index 35ef790..a2acfd1 100755
--- a/build/android/adb_logcat_monitor.py
+++ b/build/android/adb_logcat_monitor.py
@@ -108,12 +108,12 @@
 
   # Set up the alarm for calling 'adb devices'. This is to ensure
   # our script doesn't get stuck waiting for a process response
-  def TimeoutHandler(_, unused_frame):
+  def TimeoutHandler(_signum, _unused_frame):
     raise TimeoutException()
   signal.signal(signal.SIGALRM, TimeoutHandler)
 
   # Handle SIGTERMs to ensure clean shutdown
-  def SigtermHandler(_, unused_frame):
+  def SigtermHandler(_signum, _unused_frame):
     raise SigtermError()
   signal.signal(signal.SIGTERM, SigtermHandler)
 
diff --git a/build/android/adb_logcat_printer.py b/build/android/adb_logcat_printer.py
index 8e69a2c..f79a9e4 100755
--- a/build/android/adb_logcat_printer.py
+++ b/build/android/adb_logcat_printer.py
@@ -17,6 +17,7 @@
 will attempt to terminate the contained PID by sending a SIGINT and
 monitoring for the deletion of the aforementioned file.
 """
+# pylint: disable=W0702
 
 import cStringIO
 import logging
diff --git a/build/android/adb_profile_chrome.py b/build/android/adb_profile_chrome.py
index 107e4b3..a219bfe 100755
--- a/build/android/adb_profile_chrome.py
+++ b/build/android/adb_profile_chrome.py
@@ -4,7 +4,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import base64
 import gzip
 import logging
 import optparse
@@ -27,13 +26,13 @@
 _TRACE_VIEWER_ROOT = os.path.join(constants.DIR_SOURCE_ROOT,
                                   'third_party', 'trace-viewer')
 sys.path.append(_TRACE_VIEWER_ROOT)
-from trace_viewer.build import trace2html
+from trace_viewer.build import trace2html # pylint: disable=F0401
 
 _DEFAULT_CHROME_CATEGORIES = '_DEFAULT_CHROME_CATEGORIES'
 
 
 def _GetTraceTimestamp():
- return time.strftime('%Y-%m-%d-%H%M%S', time.localtime())
+  return time.strftime('%Y-%m-%d-%H%M%S', time.localtime())
 
 
 class ChromeTracingController(object):
@@ -117,7 +116,7 @@
   def GetCategories(adb):
     return adb.RunShellCommand('atrace --list_categories')
 
-  def StartTracing(self, interval):
+  def StartTracing(self, _):
     self._thread = threading.Thread(target=self._CollectData)
     self._thread.start()
 
@@ -363,7 +362,7 @@
                     action='store_true')
   parser.add_option('-z', '--compress', help='Compress the resulting trace '
                     'with gzip. ', action='store_true')
-  options, args = parser.parse_args()
+  options, _args = parser.parse_args()
   if options.trace_cc:
     parser.parse_error("""--trace-cc is deprecated.
 
diff --git a/build/android/ant/apk-package.xml b/build/android/ant/apk-package.xml
index 69f5501..7cb6a96 100644
--- a/build/android/ant/apk-package.xml
+++ b/build/android/ant/apk-package.xml
@@ -56,9 +56,6 @@
   <property name="dex.file.name" value="classes.dex" />
   <property name="intermediate.dex.file" location="${out.absolute.dir}/${dex.file.name}" />
 
-  <property name="source.dir" value="${SOURCE_DIR}" />
-  <property name="source.absolute.dir" location="${source.dir}" />
-
   <!-- Macro that enables passing a variable list of external jar files
        to ApkBuilder. -->
   <macrodef name="package-helper">
@@ -75,7 +72,6 @@
           previousBuildType="/"
           buildType="${build.is.packaging.debug}/${build.is.signing.debug}">
         <dex path="${intermediate.dex.file}"/>
-        <sourcefolder path="${source.absolute.dir}"/>
         <nativefolder path="${native.libs.absolute.dir}" />
         <extra-jars/>
       </apkbuilder>
diff --git a/build/android/asan_symbolize.py b/build/android/asan_symbolize.py
index 0504aa2..10087a6 100755
--- a/build/android/asan_symbolize.py
+++ b/build/android/asan_symbolize.py
@@ -53,18 +53,17 @@
   return symbol.TranslateLibPath(library)
 
 
-def _Symbolize(input):
+def _Symbolize(asan_input):
   asan_libs = _FindASanLibraries()
   libraries = collections.defaultdict(list)
   asan_lines = []
-  for asan_log_line in [a.rstrip() for a in input]:
+  for asan_log_line in [a.rstrip() for a in asan_input]:
     m = _ParseAsanLogLine(asan_log_line)
     if m:
       libraries[m['library']].append(m)
     asan_lines.append({'raw_log': asan_log_line, 'parsed': m})
 
   all_symbols = collections.defaultdict(dict)
-  original_symbols_dir = symbol.SYMBOLS_DIR
   for library, items in libraries.iteritems():
     libname = _TranslateLibPath(library, asan_libs)
     lib_relative_addrs = set([i['rel_address'] for i in items])
@@ -82,7 +81,7 @@
     if (m['library'] in all_symbols and
         m['rel_address'] in all_symbols[m['library']]['symbols']):
       s = all_symbols[m['library']]['symbols'][m['rel_address']][0]
-      print '%s%s %s %s' %(m['prefix'], m['pos'], s[0], s[1])
+      print '%s%s %s %s' % (m['prefix'], m['pos'], s[0], s[1])
     else:
       print asan_log_line['raw_log']
 
@@ -92,12 +91,12 @@
   parser.add_option('-l', '--logcat',
                     help='File containing adb logcat output with ASan stacks. '
                          'Use stdin if not specified.')
-  options, args = parser.parse_args()
+  options, _ = parser.parse_args()
   if options.logcat:
-    input = file(options.logcat, 'r')
+    asan_input = file(options.logcat, 'r')
   else:
-    input = sys.stdin
-  _Symbolize(input.readlines())
+    asan_input = sys.stdin
+  _Symbolize(asan_input.readlines())
 
 
 if __name__ == "__main__":
diff --git a/build/android/bb_run_sharded_steps.py b/build/android/bb_run_sharded_steps.py
index 6124819..6aeba5b 100755
--- a/build/android/bb_run_sharded_steps.py
+++ b/build/android/bb_run_sharded_steps.py
@@ -10,7 +10,6 @@
 """
 
 import optparse
-import os
 import sys
 
 from pylib import cmd_helper
@@ -27,7 +26,7 @@
   parser.add_option('-p', '--print_results',
                     help='Only prints the results for the previously '
                          'executed step, do not run it again.')
-  options, urls = parser.parse_args(argv)
+  options, _ = parser.parse_args(argv)
   if options.print_results:
     return cmd_helper.RunCmd(['build/android/test_runner.py', 'perf',
                               '--print-step', options.print_results])
diff --git a/build/android/buildbot/bb_device_status_check.py b/build/android/buildbot/bb_device_status_check.py
index f057962..e7d8c54 100755
--- a/build/android/buildbot/bb_device_status_check.py
+++ b/build/android/buildbot/bb_device_status_check.py
@@ -64,17 +64,6 @@
       return lambda_function(found[0])
     return 'Unknown'
 
-  if options.device_status_dashboard:
-    # Dashboard does not track install speed. Do not unnecessarily install.
-    install_speed = 'Unknown'
-  else:
-    install_output = GetCmdOutput(
-      ['%s/build/android/adb_install_apk.py' % constants.DIR_SOURCE_ROOT,
-       '--apk',
-       '%s/build/android/CheckInstallApk-debug.apk' % constants.DIR_SOURCE_ROOT
-      ])
-    install_speed = _GetData('(\d+) KB/s', install_output)
-
   ac_power = _GetData('AC powered: (\w+)', battery)
   battery_level = _GetData('level: (\d+)', battery)
   battery_temp = _GetData('temperature: (\d+)', battery,
@@ -89,7 +78,6 @@
             '  Battery temp: %s' % battery_temp,
             '  IMEI slice: %s' % imei_slice,
             '  Wifi IP: %s' % device_adb.GetWifiIP(),
-            '  Install Speed: %s KB/s' % install_speed,
             '']
 
   errors = []
@@ -101,14 +89,8 @@
       errors += ['Setup wizard not disabled. Was it provisioned correctly?']
   if device_product_name == 'mantaray' and ac_power != 'true':
     errors += ['Mantaray device not connected to AC power.']
-  # TODO(navabi): Insert warning once we have a better handle of what install
-  # speeds to expect. The following lines were causing too many alerts.
-  # if install_speed < 500:
-  #   errors += ['Device install speed too low. Do not use for testing.']
 
-  # Causing the device status check step fail for slow install speed or low
-  # battery currently is too disruptive to the bots (especially try bots).
-  # Turn off devices with low battery and the step does not fail.
+  # Turn off devices with low battery.
   if battery_level < 15:
     device_adb.EnableAdbRoot()
     device_adb.Shutdown()
@@ -365,8 +347,8 @@
 
   if False in fail_step_lst:
     # TODO(navabi): Build fails on device status check step if there exists any
-    # devices with critically low battery or install speed. Remove those devices
-    # from testing, allowing build to continue with good devices.
+    # devices with critically low battery. Remove those devices from testing,
+    # allowing build to continue with good devices.
     return 1
 
   if not devices:
diff --git a/build/android/finalize_apk_action.gypi b/build/android/finalize_apk_action.gypi
index 52aaa93..afe9f1b 100644
--- a/build/android/finalize_apk_action.gypi
+++ b/build/android/finalize_apk_action.gypi
@@ -20,6 +20,8 @@
   'message': 'Signing/aligning <(_target_name) APK: <(input_apk_path)',
   'variables': {
     'keystore_path%': '<(DEPTH)/build/android/ant/chromium-debug.keystore',
+    'keystore_name%': 'chromiumdebugkey',
+    'keystore_password%': 'chromium',
   },
   'inputs': [
     '<(DEPTH)/build/android/gyp/util/build_utils.py',
@@ -35,6 +37,8 @@
     '--android-sdk-root=<(android_sdk_root)',
     '--unsigned-apk-path=<(input_apk_path)',
     '--final-apk-path=<(output_apk_path)',
-    '--keystore-path=<(keystore_path)',
+    '--key-path=<(keystore_path)',
+    '--key-name=<(keystore_name)',
+    '--key-passwd=<(keystore_password)',
   ],
 }
diff --git a/build/android/findbugs_diff.py b/build/android/findbugs_diff.py
index eb117da..28224f1 100755
--- a/build/android/findbugs_diff.py
+++ b/build/android/findbugs_diff.py
@@ -24,7 +24,6 @@
 
 """
 
-import optparse
 import os
 import sys
 
@@ -32,7 +31,7 @@
 from pylib.utils import findbugs
 
 
-def main(argv):
+def main():
   parser = findbugs.GetCommonParser()
 
   options, _ = parser.parse_args()
@@ -47,4 +46,4 @@
 
 
 if __name__ == '__main__':
-  sys.exit(main(sys.argv))
+  sys.exit(main())
diff --git a/build/android/generate_emma_html.py b/build/android/generate_emma_html.py
index 463a836..93b0b0e 100755
--- a/build/android/generate_emma_html.py
+++ b/build/android/generate_emma_html.py
@@ -11,7 +11,6 @@
 import optparse
 import os
 import sys
-import traceback
 
 from pylib import cmd_helper
 from pylib import constants
@@ -36,7 +35,7 @@
   return files
 
 
-def main(argv):
+def main():
   option_parser = optparse.OptionParser()
   option_parser.add_option('--output', help='HTML output filename.')
   option_parser.add_option('--coverage-dir', default=None,
@@ -48,7 +47,7 @@
   option_parser.add_option('--cleanup', action='store_true',
                            help=('If set, removes coverage files generated at '
                                  'runtime.'))
-  options, args = option_parser.parse_args()
+  options, _ = option_parser.parse_args()
 
   if not (options.coverage_dir and options.metadata_dir and options.output):
     option_parser.error('One or more mandatory options are missing.')
@@ -88,4 +87,4 @@
 
 
 if __name__ == '__main__':
-  sys.exit(main(sys.argv))
+  sys.exit(main())
diff --git a/build/android/gyp/delete_files.py b/build/android/gyp/delete_files.py
new file mode 100755
index 0000000..802824d
--- /dev/null
+++ b/build/android/gyp/delete_files.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Delete files in directories matching a pattern.
+"""
+
+import glob
+import optparse
+import os
+import sys
+
+def main():
+  parser = optparse.OptionParser()
+  parser.add_option(
+      '--pattern',
+      help='Pattern for matching Files to delete.')
+  parser.add_option(
+      '--keep',
+      help='Files to keep even if they matches the pattern.')
+
+  options, args = parser.parse_args()
+
+  if not options.pattern or not args:
+    print 'No --pattern or target directories given'
+    return
+
+  for target_dir in args:
+    target_pattern = os.path.join(target_dir, options.pattern)
+    matching_files = glob.glob(target_pattern)
+
+    keep_pattern = os.path.join(target_dir, options.keep)
+    files_to_keep = glob.glob(keep_pattern)
+
+    for target_file in matching_files:
+      if target_file in files_to_keep:
+        continue
+
+      if os.path.isfile(target_file):
+        os.remove(target_file)
+
+if __name__ == '__main__':
+  sys.exit(main())
+
diff --git a/build/android/gyp/finalize_apk.py b/build/android/gyp/finalize_apk.py
index 5fe2bd1..9759097 100755
--- a/build/android/gyp/finalize_apk.py
+++ b/build/android/gyp/finalize_apk.py
@@ -15,16 +15,16 @@
 
 from util import build_utils
 
-def SignApk(keystore_path, unsigned_path, signed_path):
+def SignApk(key_path, key_name, key_passwd, unsigned_path, signed_path):
   shutil.copy(unsigned_path, signed_path)
   sign_cmd = [
       'jarsigner',
       '-sigalg', 'MD5withRSA',
       '-digestalg', 'SHA1',
-      '-keystore', keystore_path,
-      '-storepass', 'chromium',
+      '-keystore', key_path,
+      '-storepass', key_passwd,
       signed_path,
-      'chromiumdebugkey',
+      key_name,
     ]
   build_utils.CheckOutput(sign_cmd)
 
@@ -46,14 +46,17 @@
   parser.add_option('--unsigned-apk-path', help='Path to input unsigned APK.')
   parser.add_option('--final-apk-path',
       help='Path to output signed and aligned APK.')
-  parser.add_option('--keystore-path', help='Path to keystore for signing.')
+  parser.add_option('--key-path', help='Path to keystore for signing.')
+  parser.add_option('--key-passwd', help='Keystore password')
+  parser.add_option('--key-name', help='Keystore name')
   parser.add_option('--stamp', help='Path to touch on success.')
 
   options, _ = parser.parse_args()
 
   with tempfile.NamedTemporaryFile() as intermediate_file:
     signed_apk_path = intermediate_file.name
-    SignApk(options.keystore_path, options.unsigned_apk_path, signed_apk_path)
+    SignApk(options.key_path, options.key_name, options.key_passwd,
+            options.unsigned_apk_path, signed_apk_path)
     AlignApk(options.android_sdk_root, signed_apk_path, options.final_apk_path)
 
   if options.stamp:
diff --git a/build/android/gyp/gcc_preprocess.py b/build/android/gyp/gcc_preprocess.py
index b6b7e82..d816741 100755
--- a/build/android/gyp/gcc_preprocess.py
+++ b/build/android/gyp/gcc_preprocess.py
@@ -37,9 +37,6 @@
   parser.add_option('--stamp', help='Path to touch on success.')
   parser.add_option('--defines', help='Pre-defines macros', action='append')
 
-  # TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja.
-  parser.add_option('--ignore', help='Ignored.')
-
   options, _ = parser.parse_args()
 
   DoGcc(options)
diff --git a/build/android/gyp/javac.py b/build/android/gyp/javac.py
index d36427b..f51f76c 100755
--- a/build/android/gyp/javac.py
+++ b/build/android/gyp/javac.py
@@ -88,9 +88,6 @@
                     'compiled should be built with stricter warnings for '
                     'chromium code.')
 
-  # TODO(newt): remove this once http://crbug.com/177552 is fixed in ninja.
-  parser.add_option('--ignore', help='Ignored.')
-
   options, args = parser.parse_args()
 
   DoJavac(options, args)
diff --git a/build/android/host_heartbeat.py b/build/android/host_heartbeat.py
index 8321a77..6e011e2 100755
--- a/build/android/host_heartbeat.py
+++ b/build/android/host_heartbeat.py
@@ -7,8 +7,8 @@
 """Sends a heart beat pulse to the currently online Android devices.
 This heart beat lets the devices know that they are connected to a host.
 """
+# pylint: disable=W0702
 
-import os
 import sys
 import time
 
diff --git a/build/android/install_emulator_deps.py b/build/android/install_emulator_deps.py
index fcb0954..341b8dc 100755
--- a/build/android/install_emulator_deps.py
+++ b/build/android/install_emulator_deps.py
@@ -30,6 +30,7 @@
 SDK_BASE_URL = 'http://dl.google.com/android/adt'
 SDK_ZIP = 'adt-bundle-linux-x86_64-20131030.zip'
 
+# pylint: disable=C0301
 # Android x86 system image from the Intel website:
 # http://software.intel.com/en-us/articles/intel-eula-x86-android-4-2-jelly-bean-bin
 # These don't exist prior to Android-15.
@@ -40,6 +41,7 @@
   17: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-17_r01.zip',
   18: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-18_r01.zip',
   19: 'http://download-software.intel.com/sites/landingpage/android/sysimg_x86-19_r01.zip'}
+#pylint: enable=C0301
 
 def CheckSDK():
   """Check if SDK is already installed.
diff --git a/build/android/lighttpd_server.py b/build/android/lighttpd_server.py
index 11ae794..a5195ac 100755
--- a/build/android/lighttpd_server.py
+++ b/build/android/lighttpd_server.py
@@ -64,7 +64,8 @@
   def _Mktmp(self, name):
     return os.path.join(self.temp_dir, name)
 
-  def _GetRandomPort(self):
+  @staticmethod
+  def _GetRandomPort():
     # The ports of test server is arranged in constants.py.
     return random.randint(constants.LIGHTTPD_RANDOM_PORT_FIRST,
                           constants.LIGHTTPD_RANDOM_PORT_LAST)
@@ -145,7 +146,8 @@
         break
     return (client_error or 'Timeout', server_msg)
 
-  def _KillProcessListeningOnPort(self, port):
+  @staticmethod
+  def _KillProcessListeningOnPort(port):
     """Checks if there is a process listening on port number |port| and
     terminates it if found.
 
@@ -158,7 +160,8 @@
       assert subprocess.call(['fuser', '-v', '%d/tcp' % port]) != 0, \
           'Unable to kill process listening on port %d.' % port
 
-  def _GetDefaultBaseConfig(self):
+  @staticmethod
+  def _GetDefaultBaseConfig():
     return """server.tag                  = "%(server_tag)s"
 server.modules              = ( "mod_access",
                                 "mod_accesslog",
diff --git a/build/android/lint/suppress.py b/build/android/lint/suppress.py
index 9664ffd..52d7579 100755
--- a/build/android/lint/suppress.py
+++ b/build/android/lint/suppress.py
@@ -101,7 +101,7 @@
   _WriteConfigFile(config_path, issues_dict)
 
 
-def main(argv):
+def main():
   parser = optparse.OptionParser(usage='%prog RESULT-FILE')
   _, args = parser.parse_args()
 
@@ -112,4 +112,4 @@
 
 
 if __name__ == '__main__':
-  main(sys.argv)
+  main()
diff --git a/build/android/provision_devices.py b/build/android/provision_devices.py
index 5cf1cc5..53eb373 100755
--- a/build/android/provision_devices.py
+++ b/build/android/provision_devices.py
@@ -21,6 +21,7 @@
 from pylib import android_commands
 from pylib import constants
 from pylib import device_settings
+from pylib.cmd_helper import GetCmdOutput
 
 
 def KillHostHeartbeat():
@@ -83,6 +84,33 @@
                             android_commands.LOCAL_PROPERTIES_PATH)
 
 
+def WipeDeviceData(device):
+  """Wipes data from device, keeping only the adb_keys for authorization.
+
+  After wiping data on a device that has been authorized, adb can still
+  communicate with the device, but after reboot the device will need to be
+  re-authorized because the adb keys file is stored in /data/misc/adb/.
+  Thus, before reboot the adb_keys file is rewritten so the device does not need
+  to be re-authorized.
+
+  Arguments:
+    device: the device to wipe
+  """
+  android_cmd = android_commands.AndroidCommands(device)
+  device_authorized = android_cmd.FileExistsOnDevice(constants.ADB_KEYS_FILE)
+  if device_authorized:
+    adb_keys = android_cmd.RunShellCommandWithSU(
+      'cat %s' % constants.ADB_KEYS_FILE)[0]
+  android_cmd.RunShellCommandWithSU('wipe data')
+  if device_authorized:
+    path_list = constants.ADB_KEYS_FILE.split('/')
+    dir_path = '/'.join(path_list[:len(path_list)-1])
+    android_cmd.RunShellCommandWithSU('mkdir -p %s' % dir_path)
+    adb_keys = android_cmd.RunShellCommand(
+      'echo %s > %s' % (adb_keys, constants.ADB_KEYS_FILE))
+  android_cmd.Reboot()
+
+
 def ProvisionDevices(options):
   if options.device is not None:
     devices = [options.device]
@@ -90,6 +118,14 @@
     devices = android_commands.GetAttachedDevices()
   for device in devices:
     android_cmd = android_commands.AndroidCommands(device)
+    install_output = GetCmdOutput(
+      ['%s/build/android/adb_install_apk.py' % constants.DIR_SOURCE_ROOT,
+       '--apk',
+       '%s/build/android/CheckInstallApk-debug.apk' % constants.DIR_SOURCE_ROOT
+       ])
+    failure_string = 'Failure [INSTALL_FAILED_INSUFFICIENT_STORAGE]'
+    if failure_string in install_output:
+      WipeDeviceData(device)
     _ConfigureLocalProperties(android_cmd)
     device_settings.ConfigureContentSettingsDict(
         android_cmd, device_settings.DETERMINISTIC_DEVICE_SETTINGS)
diff --git a/build/android/pylib/android_commands.py b/build/android/pylib/android_commands.py
index 4cf996f..d56a138 100644
--- a/build/android/pylib/android_commands.py
+++ b/build/android/pylib/android_commands.py
@@ -26,6 +26,7 @@
 import constants
 import screenshot
 import system_properties
+from utils import host_utils
 
 try:
   from pylib import pexpect
@@ -1001,10 +1002,7 @@
         if host_path_mtime == os.stat(host_path).st_mtime:
           return
 
-    def GetHostSize(path):
-      return int(cmd_helper.GetCmdOutput(['du', '-sb', path]).split()[0])
-
-    size = GetHostSize(host_path)
+    size = host_utils.GetRecursiveDiskUsage(host_path)
     self._pushed_files.append(device_path)
     self._potential_push_size += size
 
@@ -1039,7 +1037,8 @@
 
     diff_size = 0
     if len(changed_files) <= MAX_INDIVIDUAL_PUSHES:
-      diff_size = sum(GetHostSize(f[0]) for f in changed_files)
+      diff_size = sum(host_utils.GetRecursiveDiskUsage(f[0])
+                      for f in changed_files)
 
     # TODO(craigdh): Replace this educated guess with a heuristic that
     # approximates the push time for each method.
diff --git a/build/android/pylib/constants.py b/build/android/pylib/constants.py
index 3d72150..3316332 100644
--- a/build/android/pylib/constants.py
+++ b/build/android/pylib/constants.py
@@ -124,6 +124,8 @@
 SDK_BUILD_TEST_JAVALIB_DIR = 'test.lib.java'
 SDK_BUILD_APKS_DIR = 'apks'
 
+ADB_KEYS_FILE = '/data/misc/adb/adb_keys'
+
 PERF_OUTPUT_DIR = os.path.join(DIR_SOURCE_ROOT, 'out', 'step_results')
 # The directory on the device where perf test output gets saved to.
 DEVICE_PERF_OUTPUT_DIR = (
diff --git a/build/android/pylib/utils/host_utils.py b/build/android/pylib/utils/host_utils.py
new file mode 100644
index 0000000..580721f
--- /dev/null
+++ b/build/android/pylib/utils/host_utils.py
@@ -0,0 +1,16 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+
+
+def GetRecursiveDiskUsage(path):
+  """Returns the disk usage in bytes of |path|. Similar to `du -sb |path|`."""
+  running_size = os.path.getsize(path)
+  if os.path.isdir(path):
+    for root, dirs, files in os.walk(path):
+      running_size += sum([os.path.getsize(os.path.join(root, f))
+                           for f in files + dirs])
+  return running_size
+
diff --git a/build/android/surface_stats.py b/build/android/surface_stats.py
index 4b90216..1fe121e 100755
--- a/build/android/surface_stats.py
+++ b/build/android/surface_stats.py
@@ -95,7 +95,7 @@
                     type='float',
                     help='Time in seconds to sleep between updates.')
 
-  options, args = parser.parse_args(argv)
+  options, _ = parser.parse_args(argv)
   run_tests_helper.SetLogLevel(options.verbose_count)
 
   adb = android_commands.AndroidCommands(options.device)
diff --git a/build/android/symbolize_test.py b/build/android/symbolize_test.py
index d9caea8..826d852 100755
--- a/build/android/symbolize_test.py
+++ b/build/android/symbolize_test.py
@@ -15,7 +15,6 @@
   nm -gC *.so
 """
 
-import sys
 import StringIO
 import unittest
 
diff --git a/build/android/test_runner.py b/build/android/test_runner.py
index 335f166..45df772 100755
--- a/build/android/test_runner.py
+++ b/build/android/test_runner.py
@@ -14,7 +14,6 @@
 import signal
 import sys
 import threading
-import traceback
 
 from pylib import android_commands
 from pylib import constants
@@ -187,7 +186,7 @@
                                  'chromium build directory.'))
 
 
-def ProcessJavaTestOptions(options, error_func):
+def ProcessJavaTestOptions(options):
   """Processes options/arguments and populates |options| with defaults."""
 
   if options.annotation_str:
@@ -246,7 +245,7 @@
     instrumentation tests.
   """
 
-  ProcessJavaTestOptions(options, error_func)
+  ProcessJavaTestOptions(options)
 
   if options.java_only and options.python_only:
     error_func('Options java_only (-j) and python_only (-p) '
@@ -324,7 +323,7 @@
     uiautomator tests.
   """
 
-  ProcessJavaTestOptions(options, error_func)
+  ProcessJavaTestOptions(options)
 
   if not options.package:
     error_func('--package is required.')
@@ -490,7 +489,7 @@
       single_step)
 
 
-def _RunGTests(options, error_func, devices):
+def _RunGTests(options, devices):
   """Subcommand of RunTestsCommands which runs gtests."""
   ProcessGTestOptions(options)
 
@@ -528,7 +527,7 @@
   return exit_code
 
 
-def _RunLinkerTests(options, error_func, devices):
+def _RunLinkerTests(options, devices):
   """Subcommand of RunTestsCommands which runs linker tests."""
   runner_factory, tests = linker_setup.Setup(options, devices)
 
@@ -716,9 +715,9 @@
     raise Exception('Failed to reset test server port.')
 
   if command == 'gtest':
-    return _RunGTests(options, option_parser.error, devices)
+    return _RunGTests(options, devices)
   elif command == 'linker':
-    return _RunLinkerTests(options, option_parser.error, devices)
+    return _RunLinkerTests(options, devices)
   elif command == 'instrumentation':
     return _RunInstrumentationTests(options, option_parser.error, devices)
   elif command == 'uiautomator':
@@ -731,13 +730,13 @@
     raise Exception('Unknown test type.')
 
 
-def HelpCommand(command, options, args, option_parser):
+def HelpCommand(command, _options, args, option_parser):
   """Display help for a certain command, or overall help.
 
   Args:
     command: String indicating the command that was received to trigger
         this function.
-    options: optparse options dictionary.
+    options: optparse options dictionary. unused.
     args: List of extra args from optparse.
     option_parser: optparse.OptionParser object.
 
@@ -793,12 +792,12 @@
     }
 
 
-def DumpThreadStacks(signal, frame):
+def DumpThreadStacks(_signal, _frame):
   for thread in threading.enumerate():
     reraiser_thread.LogThreadStack(thread)
 
 
-def main(argv):
+def main():
   signal.signal(signal.SIGUSR1, DumpThreadStacks)
   option_parser = command_option_parser.CommandOptionParser(
       commands_dict=VALID_COMMANDS)
@@ -806,4 +805,4 @@
 
 
 if __name__ == '__main__':
-  sys.exit(main(sys.argv))
+  sys.exit(main())
diff --git a/build/android/tombstones.py b/build/android/tombstones.py
index 5cbca85..e1192d7 100755
--- a/build/android/tombstones.py
+++ b/build/android/tombstones.py
@@ -10,7 +10,6 @@
 # Assumes tombstone file was created with current symbols.
 
 import datetime
-import logging
 import multiprocessing
 import os
 import subprocess
@@ -177,7 +176,7 @@
                     default=4,
                     help='Number of jobs to use when processing multiple '
                          'crash stacks.')
-  options, args = parser.parse_args()
+  options, _ = parser.parse_args()
 
   if options.device:
     devices = [options.device]
diff --git a/build/check_return_value.py b/build/check_return_value.py
new file mode 100755
index 0000000..6f0daec
--- /dev/null
+++ b/build/check_return_value.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""This program wraps an arbitrary command and prints "1" if the command ran
+successfully."""
+
+import subprocess
+import sys
+
+if not subprocess.call(sys.argv[1:]):
+  print 1
+else:
+  print 0
diff --git a/build/common.gypi b/build/common.gypi
index 6ff8c50..8c94b1f 100644
--- a/build/common.gypi
+++ b/build/common.gypi
@@ -35,6 +35,15 @@
 
             # Configure the build for small devices. See crbug.com/318413
             'embedded%': 0,
+
+            'conditions': [
+              # Compute the architecture that we're building on.
+              ['OS=="win" or OS=="mac" or OS=="ios"', {
+                'host_arch%': 'ia32',
+              }, {
+                'host_arch%': '<!(python <(DEPTH)/build/linux/detect_host_arch.py)',
+              }],
+            ],
           },
           # Copy conditionally-set variables out one scope.
           'chromeos%': '<(chromeos)',
@@ -43,13 +52,20 @@
           'use_cras%': '<(use_cras)',
           'use_ozone%': '<(use_ozone)',
           'embedded%': '<(embedded)',
+          'host_arch%': '<(host_arch)',
 
           # Whether we are using Views Toolkit
           'toolkit_views%': 0,
 
-          # Use OpenSSL instead of NSS. Under development: see http://crbug.com/62803
+          # Use OpenSSL instead of NSS as the underlying SSL and crypto
+          # implementation. Certificate verification will in most cases be
+          # handled by the OS. If OpenSSL's struct X509 is used to represent
+          # certificates, use_openssl_certs must be set.
           'use_openssl%': 0,
 
+          # Typedef X509Certificate::OSCertHandle to OpenSSL's struct X509*.
+          'use_openssl_certs%': 0,
+
           # Disable viewport meta tag by default.
           'enable_viewport%': 0,
 
@@ -96,13 +112,6 @@
               'desktop_linux%': 0,
             }],
 
-            # Compute the architecture that we're building on.
-            ['OS=="win" or OS=="mac" or OS=="ios"', {
-              'host_arch%': 'ia32',
-            }, {
-              'host_arch%': '<!(python <(DEPTH)/build/linux/detect_host_arch.py)',
-            }],
-
             # Embedded implies ozone.
             ['embedded==1', {
               'use_ozone%': 1,
@@ -113,6 +122,14 @@
             }, {
               'use_system_fontconfig%': 1,
             }],
+
+            ['OS=="android"', {
+              'target_arch%': 'arm',
+            }, {
+              # Default architecture we're building for is the architecture we're
+              # building on, and possibly sub-architecture (for iOS builds).
+              'target_arch%': '<(host_arch)',
+            }],
           ],
         },
         # Copy conditionally-set variables out one scope.
@@ -124,12 +141,14 @@
         'use_ozone%': '<(use_ozone)',
         'embedded%': '<(embedded)',
         'use_openssl%': '<(use_openssl)',
+        'use_openssl_certs%': '<(use_openssl_certs)',
         'use_system_fontconfig%': '<(use_system_fontconfig)',
         'enable_viewport%': '<(enable_viewport)',
         'enable_hidpi%': '<(enable_hidpi)',
         'buildtype%': '<(buildtype)',
         'branding%': '<(branding)',
         'host_arch%': '<(host_arch)',
+        'target_arch%': '<(target_arch)',
 
         'target_subarch%': '',
 
@@ -151,6 +170,10 @@
         'use_goma%': 0,
         'gomadir%': '',
 
+        # The system root for cross-compiles. Default: none.
+        'sysroot%': '',
+        'chroot_cmd%': '',
+
         'conditions': [
           # Ash needs Aura.
           ['use_aura==0', {
@@ -221,13 +244,6 @@
           ['OS=="ios"', {
             'target_subarch%': 'arm32',
           }],
-          ['OS=="android"', {
-            'target_arch%': 'arm',
-          }, {
-            # Default architecture we're building for is the architecture we're
-            # building on, and possibly sub-architecture (for iOS builds).
-            'target_arch%': '<(host_arch)',
-          }],
         ],
       },
 
@@ -247,6 +263,7 @@
       'use_clipboard_aurax11%': '<(use_clipboard_aurax11)',
       'embedded%': '<(embedded)',
       'use_openssl%': '<(use_openssl)',
+      'use_openssl_certs%': '<(use_openssl_certs)',
       'use_system_fontconfig%': '<(use_system_fontconfig)',
       'enable_viewport%': '<(enable_viewport)',
       'enable_hidpi%': '<(enable_hidpi)',
@@ -258,6 +275,8 @@
       'buildtype%': '<(buildtype)',
       'branding%': '<(branding)',
       'arm_version%': '<(arm_version)',
+      'sysroot%': '<(sysroot)',
+      'chroot_cmd%': '<(chroot_cmd)',
 
       # Whether content/chrome is using mojo: see http://crbug.com/353602
       'use_mojo%': 0,
@@ -286,10 +305,6 @@
       # Detect NEON support at run-time.
       'arm_neon_optional%': 0,
 
-      # The system root for cross-compiles. Default: none.
-      'sysroot%': '',
-      'chroot_cmd%': '',
-
       # The system libdir used for this ABI.
       'system_libdir%': 'lib',
 
@@ -425,13 +440,20 @@
       'cld_version%': 2,
 
       # For CLD2, the size of the tables that should be included in the build
-      # Only evaluated if cld_version == 2.
+      # Only evaluated if cld_version == 2 or if building the CLD2 dynamic data
+      # tool explicitly.
       # See third_party/cld_2/cld_2.gyp for more information.
       #   0: Small tables, lower accuracy
       #   1: Medium tables, medium accuracy
       #   2: Large tables, high accuracy
       'cld2_table_size%': 2,
 
+      # Set the way CLD is compiled. Only evaluated if cld_version == 2.
+      #   0: static, language scoring tables compiled into the binary
+      #   1: dynamic, language scoring tables live in a data file that must
+      #      be loaded at runtime.
+      'cld2_dynamic%': 0,
+
       # Enable spell checker.
       'enable_spellcheck%': 1,
 
@@ -554,6 +576,14 @@
           'use_nss%': 0,
         }],
 
+        # When OpenSSL is used for SSL and crypto on Unix-like systems, use
+        # OpenSSL's certificate definition.
+        ['(OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris") and use_openssl==1', {
+          'use_openssl_certs%': 1,
+        }, {
+          'use_openssl_certs%': 0,
+        }],
+
         # libudev usage.  This currently only affects the content layer.
         ['OS=="linux" and embedded==0', {
           'use_udev%': 1,
@@ -629,6 +659,7 @@
           'enable_extensions%': 0,
           'enable_google_now%': 0,
           'cld_version%': 1,
+          'cld2_dynamic%': 0,
           'enable_spellcheck%': 0,
           'enable_themes%': 0,
           'remoting%': 0,
@@ -679,6 +710,7 @@
           'enable_extensions%': 0,
           'enable_google_now%': 0,
           'cld_version%': 1,
+          'cld2_dynamic%': 0,
           'enable_printing%': 0,
           'enable_session_service%': 0,
           'enable_themes%': 0,
@@ -916,6 +948,7 @@
     'use_cras%': '<(use_cras)',
     'use_mojo%': '<(use_mojo)',
     'use_openssl%': '<(use_openssl)',
+    'use_openssl_certs%': '<(use_openssl_certs)',
     'use_nss%': '<(use_nss)',
     'use_udev%': '<(use_udev)',
     'os_bsd%': '<(os_bsd)',
@@ -995,6 +1028,7 @@
     'enable_google_now%': '<(enable_google_now)',
     'cld_version%': '<(cld_version)',
     'cld2_table_size%': '<(cld2_table_size)',
+    'cld2_dynamic%': '<(cld2_dynamic)',
     'enable_captive_portal_detection%': '<(enable_captive_portal_detection)',
     'disable_ftp_support%': '<(disable_ftp_support)',
     'enable_task_manager%': '<(enable_task_manager)',
@@ -1170,11 +1204,12 @@
     'release_unwind_tables%': 1,
 
     # Enable TCMalloc.
-    # TODO(dmikurube): Change the default of use_allocator to "tcmalloc".
-    # TODO(dmikurube): Kill linux_use_tcmalloc. http://crbug.com/345554
+    # TODO(dmikurube): Change Linux default of use_allocator to "tcmalloc".
+    # TODO(dmikurube): Change Android default of use_allocator to "none".
+    # TODO(dmikurube): Kill {linux|android}_use_tcmalloc. http://crbug.com/345554
     # {linux|android}_use_tcmalloc are to be replaced with use_allocator.
     # They are now used only if use_allocator=="see_use_tcmalloc" (default).
-    # TODO(dmikurube): Assert when linux_use_tcmalloc is explicitly specified.
+    # TODO(dmikurube): Assert when {linux|android}_use_tcmalloc is explicitly specified.
     'linux_use_tcmalloc%': 1,
     'android_use_tcmalloc%': 0,
     'use_allocator%': 'see_use_tcmalloc',
@@ -1488,7 +1523,7 @@
               'android_toolchain%': '<(android_ndk_root)/toolchains/arm-linux-androideabi-4.6/prebuilt/<(host_os)-<(android_host_arch)/bin',
             }],
             ['target_arch == "arm64"', {
-              'android_app_abi%': 'arm64',
+              'android_app_abi%': 'arm64-v8a',
               'android_gdbserver_executable%': 'gdbserver64',
               'android_gdbserver%': '<(android_ndk_root)/prebuilt/android-arm64/gdbserver64/gdbserver64',
               'android_ndk_sysroot%': '<(android_ndk_root)/platforms/android-19/arch-arm64',
@@ -1508,7 +1543,7 @@
         'android_gdbserver_executable': '<(android_gdbserver_executable)',
         'android_gdbserver%': '<(android_gdbserver)',
         'android_ndk_root%': '<(android_ndk_root)',
-        'android_ndk_sysroot': '<(android_ndk_sysroot)',
+        'android_ndk_sysroot%': '<(android_ndk_sysroot)',
         'android_sdk_root%': '<(android_sdk_root)',
         'android_sdk_version%': '<(android_sdk_version)',
         'android_toolchain%': '<(android_toolchain)',
@@ -1538,6 +1573,7 @@
 
         # Always uses openssl.
         'use_openssl%': 1,
+        'use_openssl_certs%': 1,
 
         'proprietary_codecs%': '<(proprietary_codecs)',
         'safe_browsing%': 2,
@@ -1762,6 +1798,9 @@
       ['toolkit_views==1', {
         'grit_defines': ['-D', 'toolkit_views'],
       }],
+      ['use_mojo==1', {
+        'grit_defines': ['-D', 'use_mojo'],
+      }],
       ['toolkit_uses_gtk==1', {
         'grit_defines': ['-D', 'toolkit_uses_gtk'],
       }],
@@ -1786,11 +1825,6 @@
       ['use_titlecase_in_grd_files==1', {
         'grit_defines': ['-D', 'use_titlecase'],
       }],
-      ['OS=="android" and (target_arch=="ia32" or target_arch=="x64")', {
-        # WebAudio on Android/x86 is disabled by default, unlike
-        # everywhere else, so use appropriate message.
-        'grit_defines': ['-D', 'use_webaudio_enable_message'],
-      }],
       ['use_third_party_translations==1', {
         'grit_defines': ['-D', 'use_third_party_translations'],
         'locales': [
@@ -2092,6 +2126,8 @@
       # processing.
       'chromium_code%': '<(chromium_code)',
 
+      'component%': '<(component)',
+
       # See http://msdn.microsoft.com/en-us/library/aa652360(VS.71).aspx
       'win_release_Optimization%': '2', # 2 = /Os
       'win_debug_Optimization%': '0',   # 0 = /Od
@@ -2424,7 +2460,7 @@
           },
         },
         'defines': [
-            'ADDRESS_SANITIZER',
+            'SYZYASAN',
             'MEMORY_TOOL_REPLACES_ALLOCATOR',
         ],
       }],
@@ -2500,6 +2536,9 @@
       ['cld_version!=0', {
         'defines': ['CLD_VERSION=<(cld_version)'],
       }],
+      ['cld2_dynamic!=0', {
+        'defines': ['CLD2_DYNAMIC_MODE=1'],
+      }],
       ['enable_printing==1', {
         'defines': ['ENABLE_FULL_PRINTING=1', 'ENABLE_PRINTING=1'],
       }],
@@ -2562,9 +2601,18 @@
       }],
     ],  # conditions for 'target_defaults'
     'target_conditions': [
-      ['<(use_openssl)==1 or >(nacl_untrusted_build)==1', {
+      ['<(use_openssl)==1', {
         'defines': ['USE_OPENSSL=1'],
       }],
+      ['<(use_openssl_certs)==1', {
+        'defines': ['USE_OPENSSL_CERTS=1'],
+      }],
+      ['>(nacl_untrusted_build)==1', {
+        'defines': [
+          'USE_OPENSSL=1',
+          'USE_OPENSSL_CERTS=1',
+        ],
+      }],
       ['<(use_nss)==1 and >(nacl_untrusted_build)==0', {
         'defines': ['USE_NSS=1'],
       }],
@@ -3025,8 +3073,8 @@
     },
   },
   'conditions': [
-    # TODO(jochen): Enable this on chromeos. http://crbug.com/353127
-    ['os_posix==1 and chromeos==0', {
+    # TODO(jochen): Enable this on chromeos on arm. http://crbug.com/356580
+    ['os_posix==1 and (chromeos==0 or target_arch!="arm")', {
       'target_defaults': {
         'ldflags': [
           '-Wl,--fatal-warnings',
@@ -3520,6 +3568,9 @@
               # code generated by flex (used in angle) contains that keyword.
               # http://crbug.com/255186
               '-Wno-deprecated-register',
+
+              # TODO(thakis): Remove, http://crbug.com/341352
+              '-Wno-absolute-value',
             ],
             'cflags!': [
               # Clang doesn't seem to know know this flag.
@@ -3608,6 +3659,13 @@
                 ],
               }],
             ],
+            'conditions': [
+              ['OS=="mac"', {
+                'cflags': [
+                  '-mllvm -asan-globals=0',  # http://crbug.com/352073
+                ],
+              }],
+            ],
           }],
           ['asan_coverage!=0', {
             'target_conditions': [
@@ -3617,13 +3675,6 @@
                 ],
               }],
             ],
-            'conditions': [
-              ['OS=="mac"', {
-                'cflags': [
-                  '-mllvm -asan-globals=0',  # http://crbug.com/352073
-                ],
-              }],
-            ],
           }],
           ['lsan==1', {
             'target_conditions': [
@@ -3771,8 +3822,8 @@
               }],
             ],
           }],
-          # TODO(dmikurube): Kill linux_use_tcmalloc. http://crbug.com/345554
-          ['(use_allocator!="tcmalloc" and (use_allocator!="see_use_tcmalloc" or linux_use_tcmalloc==0)) and android_use_tcmalloc==0', {
+          # TODO(dmikurube): Kill {linux|android}_use_tcmalloc. http://crbug.com/345554
+          ['use_allocator!="tcmalloc" and (use_allocator!="see_use_tcmalloc" or ((OS=="linux" and linux_use_tcmalloc==0) or (OS=="android" and android_use_tcmalloc==0)))', {
             'defines': ['NO_TCMALLOC'],
           }],
           ['linux_use_gold_flags==1', {
@@ -3972,7 +4023,6 @@
                   ['target_arch=="arm"', {
                     'cflags': [
                       '-target arm-linux-androideabi',
-                      '-mllvm -arm-enable-ehabi',
                     ],
                     'ldflags': [
                       '-target arm-linux-androideabi',
@@ -4261,6 +4311,9 @@
                 # e.g. code generated by flex (used in angle) contains that
                 # keyword. http://crbug.com/255186
                 '-Wno-deprecated-register',
+
+                # TODO(thakis): Remove, http://crbug.com/341352
+                '-Wno-absolute-value',
               ],
 
               'conditions': [
@@ -4900,6 +4953,7 @@
                   '-Wno-missing-braces',
                   '-Wno-missing-declarations',
                   '-Wno-msvc-include',
+                  '-Wno-absolute-value',
                   '-Wno-null-dereference',
                   '-Wno-overloaded-virtual',
                   '-Wno-parentheses',
diff --git a/build/compiler_version.py b/build/compiler_version.py
index b06712d..fd23d89 100755
--- a/build/compiler_version.py
+++ b/build/compiler_version.py
@@ -60,6 +60,10 @@
 
 
 def main(args):
+  # Force the locale to C otherwise the version string could be localized
+  # making regex matching fail.
+  os.environ["LC_ALL"] = "C"
+
   tool = "compiler"
   if len(args) == 1:
     tool = args[0]
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index cdc7f6b..89498b0 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -238,7 +238,6 @@
       if (cpu_arch == "arm") {
         cflags += [
           "-target arm-linux-androideabi",
-          "-mllvm -arm-enable-ehabi",
         ]
         ldflags += [ "-target arm-linux-androideabi" ]
       } else if (cpu_arch == "x86") {
diff --git a/build/config/linux/pkg_config.gni b/build/config/linux/pkg_config.gni
index fdd31ba..04487cc 100644
--- a/build/config/linux/pkg_config.gni
+++ b/build/config/linux/pkg_config.gni
@@ -19,14 +19,14 @@
 #   }
 
 template("pkg_config") {
-  assert(defined(packages),
+  assert(defined(invoker.packages),
         "Variable |packages| must be defined to be a list in pkg_config.")
   config(target_name) {
     if (sysroot != "") {
       # Pass the sysroot if we're using one (it requires the CPU arch also).
-      args = ["-s", sysroot, "-a", cpu_arch] + packages
+      args = ["-s", sysroot, "-a", cpu_arch] + invoker.packages
     } else {
-      args = packages
+      args = invoker.packages
     }
     pkgresult = exec_script("//build/config/linux/pkg-config.py",
                             args, "value")
@@ -35,5 +35,9 @@
     libs = pkgresult[2]
     lib_dirs = pkgresult[3]
     ldflags = pkgresult[4]
+
+    if (defined(invoker.defines)) {
+      defines = invoker.defines
+    }
   }
 }
diff --git a/build/git-hooks/pre-commit b/build/git-hooks/pre-commit
index a39be22..790e14e 100755
--- a/build/git-hooks/pre-commit
+++ b/build/git-hooks/pre-commit
@@ -1,6 +1,28 @@
 #!/bin/sh
 
-submods=$(git diff-index --cached --ignore-submodules=dirty HEAD | grep -e '^:160000' -e '^:...... 160000' | xargs)
+submodule_diff() {
+  if test -n "$2"; then
+    git diff-tree -r --ignore-submodules=dirty "$1" "$2" | grep -e '^:160000' -e '^:...... 160000' | xargs
+  else
+    git diff-index --cached --ignore-submodules=dirty "$1" | grep -e '^:160000' -e '^:...... 160000' | xargs
+  fi
+}
+
+if git rev-parse --verify --quiet --no-revs MERGE_HEAD; then
+  merge_base=$(git merge-base HEAD MERGE_HEAD)
+  if test -z "$(submodule_diff $merge_base HEAD)"; then
+    # Most up-to-date submodules are in MERGE_HEAD.
+    head_ref=MERGE_HEAD
+  else
+    # Most up-to-date submodules are in HEAD.
+    head_ref=HEAD
+  fi
+else
+  # No merge in progress. Submodules must match HEAD.
+  head_ref=HEAD
+fi
+
+submods=$(submodule_diff $head_ref)
 if test "$submods"; then
   echo "You are trying to commit changes to the following submodules:" 1>&2
   echo 1>&2
@@ -23,8 +45,11 @@
   exit 1
 fi
 
-if [ -n "$(git ls-files .gitmodules)" ] &&
-   [ -n "$(git diff-index --cached HEAD .gitmodules)" ]; then
+gitmodules_diff() {
+  git diff-index --cached "$1" .gitmodules
+}
+
+if test "$(git ls-files .gitmodules)" -a "$(gitmodules_diff $head_ref)"; then
   cat <<EOF 1>&2
 You are trying to commit a change to .gitmodules.  That is not allowed.
 To make changes to submodule names/paths, edit DEPS.
diff --git a/build/gyp_chromium b/build/gyp_chromium
index 072836d..210df12 100755
--- a/build/gyp_chromium
+++ b/build/gyp_chromium
@@ -64,41 +64,24 @@
   return glob.glob(os.path.join(chrome_src, '*', 'supplement.gypi'))
 
 
-def FormatKeyForGN(key):
-  """Returns the given GYP key reformatted for GN.
-
-  GYP dictionary keys can be almost anything, but in GN they are identifiers
-  and must follow the same rules. This reformats such keys to be valid GN
-  identifiers."""
-  return ''.join([c if c in string.ascii_letters else '_' for c in key])
-
-
-def EscapeStringForGN(s):
-  """Converts a string to a GN string literal."""
-  for old, new in [('\\', '\\\\'), ('$', '\\$'), ('"', '\\"')]:
-    s = s.replace(old, new)
-  return '"' + s + '"'
-
-
 def ProcessGypDefinesItems(items):
   """Converts a list of strings to a list of key-value pairs."""
   result = []
   for item in items:
     tokens = item.split('=', 1)
     # Some GYP variables have hyphens, which we don't support.
-    key = FormatKeyForGN(tokens[0])
     if len(tokens) == 2:
-      result += [(key, tokens[1])]
+      result += [(tokens[0], tokens[1])]
     else:
       # No value supplied, treat it as a boolean and set it. Note that we
       # use the string '1' here so we have a consistent definition whether
       # you do 'foo=1' or 'foo'.
-      result += [(key, '1')]
+      result += [(tokens[0], '1')]
   return result
 
 
-def GetGypVarsForGN(supplemental_files):
-  """Returns a dictionary of all GYP vars that we will be passing to GN."""
+def GetGypVars(supplemental_files):
+  """Returns a dictionary of all GYP vars."""
   # Find the .gyp directory in the user's home directory.
   home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None)
   if home_dot_gyp:
@@ -132,7 +115,7 @@
         raise
       variables = file_data.get('variables', [])
       for v in variables:
-        supp_items += [(FormatKeyForGN(v), str(variables[v]))]
+        supp_items += [(v, str(variables[v]))]
 
   # GYP defines from the environment.
   env_items = ProcessGypDefinesItems(
@@ -150,10 +133,6 @@
   cmdline_items = ProcessGypDefinesItems(cmdline_input_items)
 
   vars_dict = dict(supp_items + env_items + cmdline_items)
-  # It's not possible to set a default value for cpu_arch in GN, so do it here
-  # for now (http://crbug.com/344767).
-  if vars_dict.get('OS') == 'android' and not 'target_arch' in vars_dict:
-    vars_dict['target_arch'] = 'arm'
   return vars_dict
 
 
@@ -176,103 +155,6 @@
   return "out"
 
 
-def GetArgsStringForGN(vars_dict):
-  """Returns the args to pass to GN.
-  Based on a subset of the GYP variables that have been rewritten a bit."""
-  gn_args = ''
-
-  # Note: These are the additional flags passed to various builds by builders
-  # on the main waterfall. We'll probably need to add these at some point:
-  #   mac_strip_release=1         http://crbug.com/330301
-  #   linux_dump_symbols=0        http://crbug.com/330300
-  #   host_os=linux  Probably can skip, GN knows the host OS.
-  #   order_text_section=<path>   http://crbug.com/330299
-  #   chromium_win_pch=0          http://crbug.com/297678
-  #   chromium_ios_signing=0      http://crbug.com/330302
-  #   use_allocator=tcmalloc      http://crbug.com/330303, 345554
-  #   release_extra_flags=...     http://crbug.com/330305
-
-  # These tuples of (key, value, gn_arg_string) use the gn_arg_string for
-  # gn when the key is set to the given value in the GYP arguments.
-  remap_cases = [
-      ('android_webview_build', '1', 'is_android_webview_build=true'),
-      ('branding', 'Chrome', 'is_chrome_branded=true'),
-      ('build_for_tool', 'drmemory', 'disable_iterator_debugging=true'),
-      ('build_for_tool', 'tsan', 'disable_iterator_debugging=true'),
-      ('buildtype', 'Official', 'is_official_build=true'),
-      ('component', 'shared_library', 'is_component_build=true'),
-      ('clang', '1', 'is_clang=true'),
-      ('clang_use_chrome_plugins', '0', 'clang_use_chrome_plugins=false'),
-      ('disable_glibcxx_debug', '1', 'disable_iterator_debugging=true'),
-      ('enable_mdns', '0', 'enable_mdns=false'),
-      ('enable_mdns', '1', 'enable_mdns=true'),
-      ('enable_plugins', '0', 'enable_plugins=false'),
-      ('enable_plugins', '1', 'enable_plugins=true'),
-      ('target_arch', 'ia32', 'cpu_arch="x86"'),
-      ('target_arch', 'x64', 'cpu_arch="x64" force_win64=true'),
-      ('target_arch', 'arm', 'cpu_arch="arm"'),
-      ('target_arch', 'mipsel', 'cpu_arch="mipsel"'),
-      ('fastbuild', '0', 'symbol_level=2'),
-      ('fastbuild', '1', 'symbol_level=1'),
-      ('fastbuild', '2', 'symbol_level=0'),
-      ('OS', 'ios', 'os="ios"'),
-      ('OS', 'android', 'os="android"'),
-      ('chromeos', '1', 'os="chromeos"'),
-      ('use_aura', '1', 'use_aura=true'),
-      ('use_goma', '1', 'use_goma=true'),
-      ('use_openssl', '0', 'use_openssl=false'),
-      ('use_openssl', '1', 'use_openssl=true'),
-      ('asan', '1', 'is_asan=true'),
-      ('lsan', '1', 'is_lsan=true'),
-      ('msan', '1', 'is_msan=true'),
-      ('tsan', '1', 'is_tsan=true'),
-  ]
-  for i in remap_cases:
-    if i[0] in vars_dict and vars_dict[i[0]] == i[1]:
-      gn_args += ' ' + i[2]
-
-  # These string arguments get passed directly as GN strings.
-  for v in ['android_src', 'arm_float_abi', 'ios_deployment_target',
-            'ios_sdk_path', 'windows_sdk_path']:
-    if v in vars_dict:
-      gn_args += ' ' + v + '=' + EscapeStringForGN(vars_dict[v])
-
-  # gomadir is renamed goma_dir in the GN build.
-  if 'gomadir' in vars_dict:
-    gn_args += ' goma_dir=%s' % EscapeStringForGN(vars_dict['gomadir'])
-
-  # Set the "use_ios_simulator" flag if the ios_sdk_path is set.
-  if 'ios_sdk_path' in vars_dict:
-    if os.path.basename(vars_dict['ios_sdk_path']).lower().startswith(
-        'iphonesimulator'):
-      gn_args += ' use_ios_simulator=true'
-    else:
-      gn_args += ' use_ios_simulator=false'
-
-  # These arguments get passed directly as integers (avoiding the quoting and
-  # escaping of the string ones above).
-  for v in ['arm_version']:
-    if v in vars_dict:
-      gn_args += ' %s=%s' % (v, vars_dict[v])
-
-  # Some other flags come from GYP environment variables.
-  gyp_msvs_version = os.environ.get('GYP_MSVS_VERSION', '')
-  if gyp_msvs_version:
-    gn_args += ' visual_studio_version=' + EscapeStringForGN(gyp_msvs_version)
-  gyp_msvs_override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH', '')
-  if gyp_msvs_override_path:
-    gn_args += ' visual_studio_path=' + \
-        EscapeStringForGN(gyp_msvs_override_path)
-
-  # Set the GYP flag so BUILD files know they're being invoked in GYP mode.
-  gn_args += ' is_gyp=true'
-
-  gyp_outdir = GetOutputDirectory()
-  gn_args += ' gyp_output_dir=\"%s\"' % gyp_outdir
-
-  return gn_args.strip()
-
-
 def additional_include_files(supplemental_files, args=[]):
   """
   Returns a list of additional (.gypi) files to include, without duplicating
@@ -303,38 +185,6 @@
   return result
 
 
-def RunGN(vars_dict):
-  """Runs GN, returning True if it succeeded, printing an error and returning
-  false if not."""
-
-  # The binaries in platform-specific subdirectories in src/tools/gn/bin.
-  gnpath = SRC_DIR + '/tools/gn/bin/'
-  if sys.platform in ('cygwin', 'win32'):
-    gnpath += 'win/gn.exe'
-  elif sys.platform.startswith('linux'):
-    # On Linux we have 32-bit and 64-bit versions.
-    if subprocess.check_output(["getconf", "LONG_BIT"]).find("64") >= 0:
-      gnpath += 'linux/gn'
-    else:
-      gnpath += 'linux/gn32'
-  elif sys.platform == 'darwin':
-    gnpath += 'mac/gn'
-  else:
-    print 'Unknown platform for GN: ', sys.platform
-    return False
-
-  print 'Generating gyp files from GN...'
-
-  # Need to pass both the source root (the bots don't run this command from
-  # within the source tree) as well as set the is_gyp value so the BUILD files
-  # to know they're being run under GYP.
-  args = [gnpath, 'gyp', '-q',
-          '--root=' + chrome_src,
-          '--args=' + GetArgsStringForGN(vars_dict),
-          '--output=//' + GetOutputDirectory() + '/gn_build/']
-  return subprocess.call(args) == 0
-
-
 if __name__ == '__main__':
   args = sys.argv[1:]
 
@@ -424,19 +274,16 @@
     args.append('--check')
 
   supplemental_includes = GetSupplementalFiles()
-  gn_vars_dict = GetGypVarsForGN(supplemental_includes)
+  gyp_vars_dict = GetGypVars(supplemental_includes)
 
   # Automatically turn on crosscompile support for platforms that need it.
   # (The Chrome OS build sets CC_host / CC_target which implicitly enables
   # this mode.)
   if all(('ninja' in os.environ.get('GYP_GENERATORS', ''),
-          gn_vars_dict.get('OS') in ['android', 'ios'],
+          gyp_vars_dict.get('OS') in ['android', 'ios'],
           'GYP_CROSSCOMPILE' not in os.environ)):
     os.environ['GYP_CROSSCOMPILE'] = '1'
 
-  # TODO(brettw) bug 350974 either turn back on GN or delete all of this code.
-  #if not RunGN(gn_vars_dict):
-  #  sys.exit(1)
   args.extend(
       ['-I' + i for i in additional_include_files(supplemental_includes, args)])
 
diff --git a/build/ios/grit_whitelist.txt b/build/ios/grit_whitelist.txt
index 6583829..666af97 100644
--- a/build/ios/grit_whitelist.txt
+++ b/build/ios/grit_whitelist.txt
@@ -700,6 +700,7 @@
 IDS_POLICY_DM_STATUS_SERVICE_DEPROVISIONED
 IDS_POLICY_DM_STATUS_SERVICE_DEVICE_ID_CONFLICT
 IDS_POLICY_DM_STATUS_SERVICE_DEVICE_NOT_FOUND
+IDS_POLICY_DM_STATUS_SERVICE_DOMAIN_MISMATCH
 IDS_POLICY_DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER
 IDS_POLICY_DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED
 IDS_POLICY_DM_STATUS_SERVICE_MANAGEMENT_TOKEN_INVALID
diff --git a/build/java_apk.gypi b/build/java_apk.gypi
index ed4f714..ccfd9af 100644
--- a/build/java_apk.gypi
+++ b/build/java_apk.gypi
@@ -108,7 +108,6 @@
     'unsigned_apk_path': '<(intermediate_dir)/<(apk_name)-unsigned.apk',
     'final_apk_path%': '<(PRODUCT_DIR)/apks/<(apk_name).apk',
     'incomplete_apk_path': '<(intermediate_dir)/<(apk_name)-incomplete.apk',
-    'source_dir': '<(java_in_dir)/src',
     'apk_install_record': '<(intermediate_dir)/apk_install.record.stamp',
     'device_intermediate_dir': '/data/local/tmp/chromium/<(_target_name)/<(CONFIGURATION_NAME)',
     'symlink_script_host_path': '<(intermediate_dir)/create_symlinks.sh',
@@ -757,7 +756,6 @@
         '-DCONFIGURATION_NAME=<(CONFIGURATION_NAME)',
         '-DNATIVE_LIBS_DIR=<(apk_package_native_libs_dir)',
         '-DOUT_DIR=<(intermediate_dir)',
-        '-DSOURCE_DIR=<(source_dir)',
         '-DUNSIGNED_APK_PATH=<(unsigned_apk_path)',
         '-DEMMA_INSTRUMENT=<(emma_instrument)',
         '-DEMMA_DEVICE_JAR=<(emma_device_jar)',
diff --git a/build/linux/system.gyp b/build/linux/system.gyp
index 92db5ff..569ab63 100644
--- a/build/linux/system.gyp
+++ b/build/linux/system.gyp
@@ -7,7 +7,9 @@
     'conditions': [
       ['sysroot!=""', {
         'pkg-config': '<(chroot_cmd) ./pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
-        'libgcrypt-config': '<(chroot_cmd) ./libgcrypt-config-wrapper "<(sysroot)"',
+        # libgcrypt-config-wrapper invokes libgcrypt-config directly from the 
+        # sysroot, so there's no need to prefix it with <(chroot_cmd).
+        'libgcrypt-config': './libgcrypt-config-wrapper "<(sysroot)"',
       }, {
         'pkg-config': 'pkg-config',
         'libgcrypt-config': 'libgcrypt-config',
@@ -743,7 +745,10 @@
           },
           'link_settings': {
             'libraries': [
-              '<!@(<(libgcrypt-config) --libs)',
+              # libgcrypt-config does not support --libs-only-l options,
+              # and the result contains -L options, which shouldn't be in
+              # the entries of 'libraries'. So filter them out.
+              '<!@(<(libgcrypt-config) --libs | sed -e \'s/-L[^ ]*//g\')',
             ],
           },
         }],
diff --git a/build/repack_action.gypi b/build/repack_action.gypi
new file mode 100644
index 0000000..e4bbf68
--- /dev/null
+++ b/build/repack_action.gypi
@@ -0,0 +1,23 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is meant to be included into an action to invoke grit repack in a
+# consistent manner. To use this the following variables need to be
+# defined:
+#   pak_inputs: list: paths of pak files that need to be combined.
+#   pak_output: string: the output pak file path. 
+
+{
+  'variables': {
+    'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
+  },
+  'inputs': [
+    '<(repack_path)',
+    '<@(pak_inputs)',
+  ],
+  'outputs': [
+    '<(pak_output)'
+  ],
+  'action': ['python', '<(repack_path)', '<(pak_output)', '<@(pak_inputs)'],
+}
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index e1f8a89..7e66c16 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -16,6 +16,23 @@
 #                   toolchain.)
 template("gcc_toolchain") {
   toolchain(target_name) {
+    assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value")
+    assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value")
+    assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ar\" value")
+    assert(defined(invoker.ar), "gcc_toolchain() must specify a \"ld\" value")
+    assert(defined(invoker.toolchain_cpu_arch),
+                   "gcc_toolchain() must specify a \"toolchain_cpu_arch\"")
+    assert(defined(invoker.toolchain_os),
+                   "gcc_toolchain() must specify a \"toolchain_os\"")
+
+    # We can't do string interpolation ($ in strings) on things with dots in
+    # them. To allow us to use $cc below, for example, we create copies of
+    # these values in our scope.
+    cc = invoker.cc
+    cxx = invoker.cxx
+    ar = invoker.ar
+    ld = invoker.ld
+
     # Make these apply to all tools below.
     lib_prefix = "-l"
     lib_dir_prefix="-L"
@@ -61,8 +78,8 @@
     # When invoking this toolchain not as the default one, these args will be
     # passed to the build. They are ignored when this is the default toolchain.
     toolchain_args() {
-      cpu_arch = toolchain_cpu_arch
-      os = toolchain_os
+      cpu_arch = invoker.toolchain_cpu_arch
+      os = invoker.toolchain_os
     }
   }
 }
diff --git a/build/util/BUILD.gn b/build/util/BUILD.gn
index 9275585..a564fd4 100644
--- a/build/util/BUILD.gn
+++ b/build/util/BUILD.gn
@@ -10,9 +10,9 @@
 # The version is a string rather than an integer for extra flexibility (for

 # example, we may require git hashes in the future).

 #

-# All you nede to do is depend on this target, and then from your source code:

+# All you need to do is depend on this target, and then from your source code:

 #  #include "build/util/last_change.h"

-custom("last_change") {

+action("last_change") {

   script = "//build/util/lastchange.py"

 

   # This script must be run before targets depending on us.

diff --git a/build/util/LASTCHANGE b/build/util/LASTCHANGE
index 205e060..a3316fe 100644
--- a/build/util/LASTCHANGE
+++ b/build/util/LASTCHANGE
@@ -1 +1 @@
-LASTCHANGE=258528
+LASTCHANGE=260458
diff --git a/build/util/LASTCHANGE.blink b/build/util/LASTCHANGE.blink
index fc727a2..9cfba81 100644
--- a/build/util/LASTCHANGE.blink
+++ b/build/util/LASTCHANGE.blink
@@ -1 +1 @@
-LASTCHANGE=169622
+LASTCHANGE=170423
diff --git a/build/util/version.gypi b/build/util/version.gypi
index 424871d..9d295b5 100644
--- a/build/util/version.gypi
+++ b/build/util/version.gypi
@@ -12,6 +12,8 @@
     'version_path': '<(version_path)',
     'version_full':
         '<!(python <(version_py_path) -f <(version_path) -t "@MAJOR@.@MINOR@.@BUILD@.@PATCH@")',
+    'version_libchrome_short':
+        '<!(python <(version_py_path) -f <(version_path) -t "@BUILD@.@PATCH@")',
     'version_mac_dylib':
         '<!(python <(version_py_path) -f <(version_path) -t "@BUILD@.@PATCH_HI@.@PATCH_LO@" -e "PATCH_HI=int(PATCH)/256" -e "PATCH_LO=int(PATCH)%256")',
   },  # variables
diff --git a/build/whitespace_file.txt b/build/whitespace_file.txt
index 86668eb..2cda113 100644
--- a/build/whitespace_file.txt
+++ b/build/whitespace_file.txt
@@ -81,3 +81,5 @@
 I'm really tempted to change something above the line.
 Reeccciiiipppppeeeeeesssssss!!!!!!!!!
 PEOPLE SAY "FAILURE IS NOT AN OPTION", BUT FAILURE IS ALWAYS AN OPTION.
+
+I can feel the heat closing in, feel them out there making their moves...
diff --git a/cc/cc.target.darwin-arm.mk b/cc/cc.target.darwin-arm.mk
index 6ed4ee5..8b6d8d5 100644
--- a/cc/cc.target.darwin-arm.mk
+++ b/cc/cc.target.darwin-arm.mk
@@ -287,9 +287,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -299,6 +297,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -413,9 +412,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -425,6 +422,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/cc/cc.target.darwin-mips.mk b/cc/cc.target.darwin-mips.mk
index e007a8a..14312c0 100644
--- a/cc/cc.target.darwin-mips.mk
+++ b/cc/cc.target.darwin-mips.mk
@@ -286,9 +286,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -298,6 +296,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -411,9 +410,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -423,6 +420,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/cc/cc.target.darwin-x86.mk b/cc/cc.target.darwin-x86.mk
index 30e5641..799b2d2 100644
--- a/cc/cc.target.darwin-x86.mk
+++ b/cc/cc.target.darwin-x86.mk
@@ -288,9 +288,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -300,6 +298,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -414,9 +413,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -426,6 +423,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/cc/cc.target.darwin-x86_64.mk b/cc/cc.target.darwin-x86_64.mk
new file mode 100644
index 0000000..b964f75
--- /dev/null
+++ b/cc/cc.target.darwin-x86_64.mk
@@ -0,0 +1,540 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := cc_cc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,gpu_gpu_gyp)/gpu.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	cc/animation/animation.cc \
+	cc/animation/animation_curve.cc \
+	cc/animation/animation_events.cc \
+	cc/animation/animation_id_provider.cc \
+	cc/animation/animation_registrar.cc \
+	cc/animation/keyframed_animation_curve.cc \
+	cc/animation/layer_animation_controller.cc \
+	cc/animation/scroll_offset_animation_curve.cc \
+	cc/animation/scrollbar_animation_controller_linear_fade.cc \
+	cc/animation/scrollbar_animation_controller_thinning.cc \
+	cc/animation/timing_function.cc \
+	cc/animation/transform_operation.cc \
+	cc/animation/transform_operations.cc \
+	cc/base/invalidation_region.cc \
+	cc/base/latency_info_swap_promise.cc \
+	cc/base/latency_info_swap_promise_monitor.cc \
+	cc/base/math_util.cc \
+	cc/base/region.cc \
+	cc/base/rolling_time_delta_history.cc \
+	cc/base/swap_promise_monitor.cc \
+	cc/base/switches.cc \
+	cc/base/tiling_data.cc \
+	cc/debug/benchmark_instrumentation.cc \
+	cc/debug/debug_colors.cc \
+	cc/debug/debug_rect_history.cc \
+	cc/debug/frame_rate_counter.cc \
+	cc/debug/layer_tree_debug_state.cc \
+	cc/debug/micro_benchmark.cc \
+	cc/debug/micro_benchmark_impl.cc \
+	cc/debug/micro_benchmark_controller.cc \
+	cc/debug/micro_benchmark_controller_impl.cc \
+	cc/debug/paint_time_counter.cc \
+	cc/debug/picture_record_benchmark.cc \
+	cc/debug/rasterize_and_record_benchmark.cc \
+	cc/debug/rasterize_and_record_benchmark_impl.cc \
+	cc/debug/rendering_stats.cc \
+	cc/debug/rendering_stats_instrumentation.cc \
+	cc/debug/traced_picture.cc \
+	cc/debug/traced_value.cc \
+	cc/debug/unittest_only_benchmark.cc \
+	cc/debug/unittest_only_benchmark_impl.cc \
+	cc/input/page_scale_animation.cc \
+	cc/input/top_controls_manager.cc \
+	cc/layers/content_layer.cc \
+	cc/layers/contents_scaling_layer.cc \
+	cc/layers/delegated_frame_provider.cc \
+	cc/layers/delegated_frame_resource_collection.cc \
+	cc/layers/delegated_renderer_layer.cc \
+	cc/layers/delegated_renderer_layer_impl.cc \
+	cc/layers/heads_up_display_layer.cc \
+	cc/layers/heads_up_display_layer_impl.cc \
+	cc/layers/image_layer.cc \
+	cc/layers/io_surface_layer.cc \
+	cc/layers/io_surface_layer_impl.cc \
+	cc/layers/layer.cc \
+	cc/layers/layer_impl.cc \
+	cc/layers/layer_lists.cc \
+	cc/layers/layer_position_constraint.cc \
+	cc/layers/layer_utils.cc \
+	cc/layers/nine_patch_layer.cc \
+	cc/layers/nine_patch_layer_impl.cc \
+	cc/layers/painted_scrollbar_layer.cc \
+	cc/layers/painted_scrollbar_layer_impl.cc \
+	cc/layers/picture_image_layer.cc \
+	cc/layers/picture_image_layer_impl.cc \
+	cc/layers/picture_layer.cc \
+	cc/layers/picture_layer_impl.cc \
+	cc/layers/render_surface.cc \
+	cc/layers/render_surface_impl.cc \
+	cc/layers/scrollbar_layer_impl_base.cc \
+	cc/layers/solid_color_layer.cc \
+	cc/layers/solid_color_layer_impl.cc \
+	cc/layers/solid_color_scrollbar_layer.cc \
+	cc/layers/solid_color_scrollbar_layer_impl.cc \
+	cc/layers/surface_layer.cc \
+	cc/layers/surface_layer_impl.cc \
+	cc/layers/texture_layer.cc \
+	cc/layers/texture_layer_impl.cc \
+	cc/layers/tiled_layer.cc \
+	cc/layers/tiled_layer_impl.cc \
+	cc/layers/ui_resource_layer.cc \
+	cc/layers/ui_resource_layer_impl.cc \
+	cc/layers/video_frame_provider_client_impl.cc \
+	cc/layers/video_layer.cc \
+	cc/layers/video_layer_impl.cc \
+	cc/output/begin_frame_args.cc \
+	cc/output/compositor_frame.cc \
+	cc/output/compositor_frame_ack.cc \
+	cc/output/compositor_frame_metadata.cc \
+	cc/output/context_provider.cc \
+	cc/output/copy_output_request.cc \
+	cc/output/copy_output_result.cc \
+	cc/output/delegated_frame_data.cc \
+	cc/output/delegating_renderer.cc \
+	cc/output/direct_renderer.cc \
+	cc/output/filter_operation.cc \
+	cc/output/filter_operations.cc \
+	cc/output/geometry_binding.cc \
+	cc/output/gl_frame_data.cc \
+	cc/output/gl_renderer.cc \
+	cc/output/gl_renderer_draw_cache.cc \
+	cc/output/managed_memory_policy.cc \
+	cc/output/output_surface.cc \
+	cc/output/overlay_candidate.cc \
+	cc/output/overlay_processor.cc \
+	cc/output/overlay_strategy_single_on_top.cc \
+	cc/output/program_binding.cc \
+	cc/output/render_surface_filters.cc \
+	cc/output/renderer.cc \
+	cc/output/shader.cc \
+	cc/output/software_frame_data.cc \
+	cc/output/software_output_device.cc \
+	cc/output/software_renderer.cc \
+	cc/quads/checkerboard_draw_quad.cc \
+	cc/quads/content_draw_quad_base.cc \
+	cc/quads/debug_border_draw_quad.cc \
+	cc/quads/draw_quad.cc \
+	cc/quads/io_surface_draw_quad.cc \
+	cc/quads/picture_draw_quad.cc \
+	cc/quads/render_pass.cc \
+	cc/quads/render_pass_draw_quad.cc \
+	cc/quads/shared_quad_state.cc \
+	cc/quads/solid_color_draw_quad.cc \
+	cc/quads/stream_video_draw_quad.cc \
+	cc/quads/surface_draw_quad.cc \
+	cc/quads/texture_draw_quad.cc \
+	cc/quads/tile_draw_quad.cc \
+	cc/quads/yuv_video_draw_quad.cc \
+	cc/resources/bitmap_content_layer_updater.cc \
+	cc/resources/bitmap_skpicture_content_layer_updater.cc \
+	cc/resources/content_layer_updater.cc \
+	cc/resources/direct_raster_worker_pool.cc \
+	cc/resources/image_layer_updater.cc \
+	cc/resources/image_raster_worker_pool.cc \
+	cc/resources/layer_quad.cc \
+	cc/resources/layer_tiling_data.cc \
+	cc/resources/layer_updater.cc \
+	cc/resources/managed_tile_state.cc \
+	cc/resources/memory_history.cc \
+	cc/resources/picture.cc \
+	cc/resources/picture_layer_tiling.cc \
+	cc/resources/picture_layer_tiling_set.cc \
+	cc/resources/picture_pile.cc \
+	cc/resources/picture_pile_base.cc \
+	cc/resources/picture_pile_impl.cc \
+	cc/resources/pixel_buffer_raster_worker_pool.cc \
+	cc/resources/prioritized_resource.cc \
+	cc/resources/prioritized_resource_manager.cc \
+	cc/resources/prioritized_tile_set.cc \
+	cc/resources/priority_calculator.cc \
+	cc/resources/raster_mode.cc \
+	cc/resources/raster_worker_pool.cc \
+	cc/resources/raster_worker_pool_delegate.cc \
+	cc/resources/resource.cc \
+	cc/resources/resource_format.cc \
+	cc/resources/resource_pool.cc \
+	cc/resources/resource_provider.cc \
+	cc/resources/resource_update.cc \
+	cc/resources/resource_update_controller.cc \
+	cc/resources/resource_update_queue.cc \
+	cc/resources/scoped_resource.cc \
+	cc/resources/scoped_ui_resource.cc \
+	cc/resources/shared_bitmap.cc \
+	cc/resources/single_release_callback.cc \
+	cc/resources/skpicture_content_layer_updater.cc \
+	cc/resources/task_graph_runner.cc \
+	cc/resources/texture_mailbox.cc \
+	cc/resources/texture_mailbox_deleter.cc \
+	cc/resources/texture_uploader.cc \
+	cc/resources/tile.cc \
+	cc/resources/tile_manager.cc \
+	cc/resources/tile_priority.cc \
+	cc/resources/transferable_resource.cc \
+	cc/resources/ui_resource_bitmap.cc \
+	cc/resources/ui_resource_request.cc \
+	cc/resources/video_resource_updater.cc \
+	cc/scheduler/delay_based_time_source.cc \
+	cc/scheduler/frame_rate_controller.cc \
+	cc/scheduler/scheduler.cc \
+	cc/scheduler/scheduler_settings.cc \
+	cc/scheduler/scheduler_state_machine.cc \
+	cc/trees/blocking_task_runner.cc \
+	cc/trees/damage_tracker.cc \
+	cc/trees/layer_sorter.cc \
+	cc/trees/layer_tree_host.cc \
+	cc/trees/layer_tree_host_common.cc \
+	cc/trees/layer_tree_host_impl.cc \
+	cc/trees/layer_tree_impl.cc \
+	cc/trees/layer_tree_settings.cc \
+	cc/trees/occlusion_tracker.cc \
+	cc/trees/proxy.cc \
+	cc/trees/proxy_timing_history.cc \
+	cc/trees/quad_culler.cc \
+	cc/trees/single_thread_proxy.cc \
+	cc/trees/thread_proxy.cc \
+	cc/trees/tree_synchronizer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCC_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCC_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: cc_cc_gyp
+
+# Alias gyp target name.
+.PHONY: cc
+cc: cc_cc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/cc/cc.target.linux-arm.mk b/cc/cc.target.linux-arm.mk
index 6ed4ee5..8b6d8d5 100644
--- a/cc/cc.target.linux-arm.mk
+++ b/cc/cc.target.linux-arm.mk
@@ -287,9 +287,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -299,6 +297,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -413,9 +412,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -425,6 +422,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/cc/cc.target.linux-mips.mk b/cc/cc.target.linux-mips.mk
index e007a8a..14312c0 100644
--- a/cc/cc.target.linux-mips.mk
+++ b/cc/cc.target.linux-mips.mk
@@ -286,9 +286,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -298,6 +296,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -411,9 +410,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -423,6 +420,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/cc/cc.target.linux-x86.mk b/cc/cc.target.linux-x86.mk
index 30e5641..799b2d2 100644
--- a/cc/cc.target.linux-x86.mk
+++ b/cc/cc.target.linux-x86.mk
@@ -288,9 +288,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -300,6 +298,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -414,9 +413,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -426,6 +423,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/cc/cc.target.linux-x86_64.mk b/cc/cc.target.linux-x86_64.mk
new file mode 100644
index 0000000..b964f75
--- /dev/null
+++ b/cc/cc.target.linux-x86_64.mk
@@ -0,0 +1,540 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := cc_cc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,gpu_gpu_gyp)/gpu.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	cc/animation/animation.cc \
+	cc/animation/animation_curve.cc \
+	cc/animation/animation_events.cc \
+	cc/animation/animation_id_provider.cc \
+	cc/animation/animation_registrar.cc \
+	cc/animation/keyframed_animation_curve.cc \
+	cc/animation/layer_animation_controller.cc \
+	cc/animation/scroll_offset_animation_curve.cc \
+	cc/animation/scrollbar_animation_controller_linear_fade.cc \
+	cc/animation/scrollbar_animation_controller_thinning.cc \
+	cc/animation/timing_function.cc \
+	cc/animation/transform_operation.cc \
+	cc/animation/transform_operations.cc \
+	cc/base/invalidation_region.cc \
+	cc/base/latency_info_swap_promise.cc \
+	cc/base/latency_info_swap_promise_monitor.cc \
+	cc/base/math_util.cc \
+	cc/base/region.cc \
+	cc/base/rolling_time_delta_history.cc \
+	cc/base/swap_promise_monitor.cc \
+	cc/base/switches.cc \
+	cc/base/tiling_data.cc \
+	cc/debug/benchmark_instrumentation.cc \
+	cc/debug/debug_colors.cc \
+	cc/debug/debug_rect_history.cc \
+	cc/debug/frame_rate_counter.cc \
+	cc/debug/layer_tree_debug_state.cc \
+	cc/debug/micro_benchmark.cc \
+	cc/debug/micro_benchmark_impl.cc \
+	cc/debug/micro_benchmark_controller.cc \
+	cc/debug/micro_benchmark_controller_impl.cc \
+	cc/debug/paint_time_counter.cc \
+	cc/debug/picture_record_benchmark.cc \
+	cc/debug/rasterize_and_record_benchmark.cc \
+	cc/debug/rasterize_and_record_benchmark_impl.cc \
+	cc/debug/rendering_stats.cc \
+	cc/debug/rendering_stats_instrumentation.cc \
+	cc/debug/traced_picture.cc \
+	cc/debug/traced_value.cc \
+	cc/debug/unittest_only_benchmark.cc \
+	cc/debug/unittest_only_benchmark_impl.cc \
+	cc/input/page_scale_animation.cc \
+	cc/input/top_controls_manager.cc \
+	cc/layers/content_layer.cc \
+	cc/layers/contents_scaling_layer.cc \
+	cc/layers/delegated_frame_provider.cc \
+	cc/layers/delegated_frame_resource_collection.cc \
+	cc/layers/delegated_renderer_layer.cc \
+	cc/layers/delegated_renderer_layer_impl.cc \
+	cc/layers/heads_up_display_layer.cc \
+	cc/layers/heads_up_display_layer_impl.cc \
+	cc/layers/image_layer.cc \
+	cc/layers/io_surface_layer.cc \
+	cc/layers/io_surface_layer_impl.cc \
+	cc/layers/layer.cc \
+	cc/layers/layer_impl.cc \
+	cc/layers/layer_lists.cc \
+	cc/layers/layer_position_constraint.cc \
+	cc/layers/layer_utils.cc \
+	cc/layers/nine_patch_layer.cc \
+	cc/layers/nine_patch_layer_impl.cc \
+	cc/layers/painted_scrollbar_layer.cc \
+	cc/layers/painted_scrollbar_layer_impl.cc \
+	cc/layers/picture_image_layer.cc \
+	cc/layers/picture_image_layer_impl.cc \
+	cc/layers/picture_layer.cc \
+	cc/layers/picture_layer_impl.cc \
+	cc/layers/render_surface.cc \
+	cc/layers/render_surface_impl.cc \
+	cc/layers/scrollbar_layer_impl_base.cc \
+	cc/layers/solid_color_layer.cc \
+	cc/layers/solid_color_layer_impl.cc \
+	cc/layers/solid_color_scrollbar_layer.cc \
+	cc/layers/solid_color_scrollbar_layer_impl.cc \
+	cc/layers/surface_layer.cc \
+	cc/layers/surface_layer_impl.cc \
+	cc/layers/texture_layer.cc \
+	cc/layers/texture_layer_impl.cc \
+	cc/layers/tiled_layer.cc \
+	cc/layers/tiled_layer_impl.cc \
+	cc/layers/ui_resource_layer.cc \
+	cc/layers/ui_resource_layer_impl.cc \
+	cc/layers/video_frame_provider_client_impl.cc \
+	cc/layers/video_layer.cc \
+	cc/layers/video_layer_impl.cc \
+	cc/output/begin_frame_args.cc \
+	cc/output/compositor_frame.cc \
+	cc/output/compositor_frame_ack.cc \
+	cc/output/compositor_frame_metadata.cc \
+	cc/output/context_provider.cc \
+	cc/output/copy_output_request.cc \
+	cc/output/copy_output_result.cc \
+	cc/output/delegated_frame_data.cc \
+	cc/output/delegating_renderer.cc \
+	cc/output/direct_renderer.cc \
+	cc/output/filter_operation.cc \
+	cc/output/filter_operations.cc \
+	cc/output/geometry_binding.cc \
+	cc/output/gl_frame_data.cc \
+	cc/output/gl_renderer.cc \
+	cc/output/gl_renderer_draw_cache.cc \
+	cc/output/managed_memory_policy.cc \
+	cc/output/output_surface.cc \
+	cc/output/overlay_candidate.cc \
+	cc/output/overlay_processor.cc \
+	cc/output/overlay_strategy_single_on_top.cc \
+	cc/output/program_binding.cc \
+	cc/output/render_surface_filters.cc \
+	cc/output/renderer.cc \
+	cc/output/shader.cc \
+	cc/output/software_frame_data.cc \
+	cc/output/software_output_device.cc \
+	cc/output/software_renderer.cc \
+	cc/quads/checkerboard_draw_quad.cc \
+	cc/quads/content_draw_quad_base.cc \
+	cc/quads/debug_border_draw_quad.cc \
+	cc/quads/draw_quad.cc \
+	cc/quads/io_surface_draw_quad.cc \
+	cc/quads/picture_draw_quad.cc \
+	cc/quads/render_pass.cc \
+	cc/quads/render_pass_draw_quad.cc \
+	cc/quads/shared_quad_state.cc \
+	cc/quads/solid_color_draw_quad.cc \
+	cc/quads/stream_video_draw_quad.cc \
+	cc/quads/surface_draw_quad.cc \
+	cc/quads/texture_draw_quad.cc \
+	cc/quads/tile_draw_quad.cc \
+	cc/quads/yuv_video_draw_quad.cc \
+	cc/resources/bitmap_content_layer_updater.cc \
+	cc/resources/bitmap_skpicture_content_layer_updater.cc \
+	cc/resources/content_layer_updater.cc \
+	cc/resources/direct_raster_worker_pool.cc \
+	cc/resources/image_layer_updater.cc \
+	cc/resources/image_raster_worker_pool.cc \
+	cc/resources/layer_quad.cc \
+	cc/resources/layer_tiling_data.cc \
+	cc/resources/layer_updater.cc \
+	cc/resources/managed_tile_state.cc \
+	cc/resources/memory_history.cc \
+	cc/resources/picture.cc \
+	cc/resources/picture_layer_tiling.cc \
+	cc/resources/picture_layer_tiling_set.cc \
+	cc/resources/picture_pile.cc \
+	cc/resources/picture_pile_base.cc \
+	cc/resources/picture_pile_impl.cc \
+	cc/resources/pixel_buffer_raster_worker_pool.cc \
+	cc/resources/prioritized_resource.cc \
+	cc/resources/prioritized_resource_manager.cc \
+	cc/resources/prioritized_tile_set.cc \
+	cc/resources/priority_calculator.cc \
+	cc/resources/raster_mode.cc \
+	cc/resources/raster_worker_pool.cc \
+	cc/resources/raster_worker_pool_delegate.cc \
+	cc/resources/resource.cc \
+	cc/resources/resource_format.cc \
+	cc/resources/resource_pool.cc \
+	cc/resources/resource_provider.cc \
+	cc/resources/resource_update.cc \
+	cc/resources/resource_update_controller.cc \
+	cc/resources/resource_update_queue.cc \
+	cc/resources/scoped_resource.cc \
+	cc/resources/scoped_ui_resource.cc \
+	cc/resources/shared_bitmap.cc \
+	cc/resources/single_release_callback.cc \
+	cc/resources/skpicture_content_layer_updater.cc \
+	cc/resources/task_graph_runner.cc \
+	cc/resources/texture_mailbox.cc \
+	cc/resources/texture_mailbox_deleter.cc \
+	cc/resources/texture_uploader.cc \
+	cc/resources/tile.cc \
+	cc/resources/tile_manager.cc \
+	cc/resources/tile_priority.cc \
+	cc/resources/transferable_resource.cc \
+	cc/resources/ui_resource_bitmap.cc \
+	cc/resources/ui_resource_request.cc \
+	cc/resources/video_resource_updater.cc \
+	cc/scheduler/delay_based_time_source.cc \
+	cc/scheduler/frame_rate_controller.cc \
+	cc/scheduler/scheduler.cc \
+	cc/scheduler/scheduler_settings.cc \
+	cc/scheduler/scheduler_state_machine.cc \
+	cc/trees/blocking_task_runner.cc \
+	cc/trees/damage_tracker.cc \
+	cc/trees/layer_sorter.cc \
+	cc/trees/layer_tree_host.cc \
+	cc/trees/layer_tree_host_common.cc \
+	cc/trees/layer_tree_host_impl.cc \
+	cc/trees/layer_tree_impl.cc \
+	cc/trees/layer_tree_settings.cc \
+	cc/trees/occlusion_tracker.cc \
+	cc/trees/proxy.cc \
+	cc/trees/proxy_timing_history.cc \
+	cc/trees/quad_culler.cc \
+	cc/trees/single_thread_proxy.cc \
+	cc/trees/thread_proxy.cc \
+	cc/trees/tree_synchronizer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCC_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCC_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: cc_cc_gyp
+
+# Alias gyp target name.
+.PHONY: cc
+cc: cc_cc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 0c7bb62..39528df 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -41,6 +41,7 @@
       'layers/picture_layer_impl_unittest.cc',
       'layers/picture_layer_unittest.cc',
       'layers/render_surface_unittest.cc',
+      'layers/render_surface_impl_unittest.cc',
       'layers/scrollbar_layer_unittest.cc',
       'layers/solid_color_layer_impl_unittest.cc',
       'layers/solid_color_scrollbar_layer_impl_unittest.cc',
@@ -102,7 +103,6 @@
       'trees/layer_tree_host_unittest_delegated.cc',
       'trees/layer_tree_host_unittest_occlusion.cc',
       'trees/layer_tree_host_unittest_picture.cc',
-      'trees/layer_tree_host_unittest_pinch_zoom.cc',
       'trees/layer_tree_host_unittest_scroll.cc',
       'trees/layer_tree_host_unittest_video.cc',
       'trees/occlusion_tracker_unittest.cc',
diff --git a/cc/layers/content_layer.cc b/cc/layers/content_layer.cc
index edca5ed..178211f 100644
--- a/cc/layers/content_layer.cc
+++ b/cc/layers/content_layer.cc
@@ -126,6 +126,8 @@
         id());
   }
   updater_->SetOpaque(contents_opaque());
+  if (client_)
+    updater_->SetFillsBoundsCompletely(client_->FillsBoundsCompletely());
 
   SetTextureFormat(
       layer_tree_host()->GetRendererCapabilities().best_texture_format);
diff --git a/cc/layers/content_layer_client.h b/cc/layers/content_layer_client.h
index eac1a87..6a77dab 100644
--- a/cc/layers/content_layer_client.h
+++ b/cc/layers/content_layer_client.h
@@ -26,6 +26,10 @@
   // If the client paints LCD text, it may want to invalidate the layer.
   virtual void DidChangeLayerCanUseLCDText() = 0;
 
+  // If true the layer may skip clearing the background before rasterizing,
+  // because it will cover any uncleared data with content.
+  virtual bool FillsBoundsCompletely() const = 0;
+
  protected:
   virtual ~ContentLayerClient() {}
 };
diff --git a/cc/layers/content_layer_unittest.cc b/cc/layers/content_layer_unittest.cc
index 17cf11b..8770303 100644
--- a/cc/layers/content_layer_unittest.cc
+++ b/cc/layers/content_layer_unittest.cc
@@ -26,6 +26,7 @@
     *opaque = gfx::RectF(opaque_layer_rect_);
   }
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
+  virtual bool FillsBoundsCompletely() const OVERRIDE { return false; }
 
  private:
   gfx::Rect opaque_layer_rect_;
diff --git a/cc/layers/delegated_renderer_layer_impl.cc b/cc/layers/delegated_renderer_layer_impl.cc
index dbc67dc..4556db6 100644
--- a/cc/layers/delegated_renderer_layer_impl.cc
+++ b/cc/layers/delegated_renderer_layer_impl.cc
@@ -366,7 +366,7 @@
       scoped_ptr<SolidColorDrawQuad> top_quad = SolidColorDrawQuad::Create();
       top_quad->SetNew(
           shared_quad_state, top, top, colors[i % kNumColors], false);
-      quad_sink->MaybeAppend(top_quad.PassAs<DrawQuad>());
+      quad_sink->Append(top_quad.PassAs<DrawQuad>());
 
       scoped_ptr<SolidColorDrawQuad> bottom_quad = SolidColorDrawQuad::Create();
       bottom_quad->SetNew(shared_quad_state,
@@ -374,7 +374,7 @@
                           bottom,
                           colors[kNumColors - 1 - (i % kNumColors)],
                           false);
-      quad_sink->MaybeAppend(bottom_quad.PassAs<DrawQuad>());
+      quad_sink->Append(bottom_quad.PassAs<DrawQuad>());
     }
     if (!left.IsEmpty()) {
       scoped_ptr<SolidColorDrawQuad> left_quad = SolidColorDrawQuad::Create();
@@ -383,12 +383,12 @@
                         left,
                         colors[kNumColors - 1 - (i % kNumColors)],
                         false);
-      quad_sink->MaybeAppend(left_quad.PassAs<DrawQuad>());
+      quad_sink->Append(left_quad.PassAs<DrawQuad>());
 
       scoped_ptr<SolidColorDrawQuad> right_quad = SolidColorDrawQuad::Create();
       right_quad->SetNew(
           shared_quad_state, right, right, colors[i % kNumColors], false);
-      quad_sink->MaybeAppend(right_quad.PassAs<DrawQuad>());
+      quad_sink->Append(right_quad.PassAs<DrawQuad>());
     }
   }
 }
@@ -446,9 +446,16 @@
     }
     DCHECK(output_shared_quad_state);
 
+    gfx::Rect quad_visible_rect = quad_sink->UnoccludedContentRect(
+        delegated_quad->visible_rect,
+        output_shared_quad_state->content_to_target_transform);
+    if (quad_visible_rect.IsEmpty())
+      continue;
+
     scoped_ptr<DrawQuad> output_quad;
     if (delegated_quad->material != DrawQuad::RENDER_PASS) {
       output_quad = delegated_quad->Copy(output_shared_quad_state);
+      output_quad->visible_rect = quad_visible_rect;
     } else {
       RenderPass::Id delegated_contributing_render_pass_id =
           RenderPassDrawQuad::MaterialCast(delegated_quad)->render_pass_id;
@@ -467,11 +474,12 @@
         output_quad = RenderPassDrawQuad::MaterialCast(delegated_quad)->Copy(
             output_shared_quad_state,
             output_contributing_render_pass_id).PassAs<DrawQuad>();
+        output_quad->visible_rect = quad_visible_rect;
       }
     }
 
     if (output_quad)
-      quad_sink->MaybeAppend(output_quad.Pass());
+      quad_sink->Append(output_quad.Pass());
   }
 }
 
diff --git a/cc/layers/delegated_renderer_layer_impl_unittest.cc b/cc/layers/delegated_renderer_layer_impl_unittest.cc
index fea1531..7578e22 100644
--- a/cc/layers/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/layers/delegated_renderer_layer_impl_unittest.cc
@@ -16,6 +16,7 @@
 #include "cc/test/fake_proxy.h"
 #include "cc/test/fake_rendering_stats_instrumentation.h"
 #include "cc/test/geometry_test_utils.h"
+#include "cc/test/layer_test_common.h"
 #include "cc/test/mock_quad_culler.h"
 #include "cc/test/render_pass_test_common.h"
 #include "cc/test/render_pass_test_utils.h"
@@ -1405,5 +1406,139 @@
   host_impl_->DidDrawAllLayers(frame);
 }
 
+TEST_F(DelegatedRendererLayerImplTest, Occlusion) {
+  gfx::Size layer_size(1000, 1000);
+  gfx::Size viewport_size(1000, 1000);
+  gfx::Rect quad_rect(200, 300, 400, 500);
+
+  gfx::Transform transform;
+  transform.Translate(11.0, 0.0);
+
+  LayerTestCommon::LayerImplTest impl;
+
+  FakeDelegatedRendererLayerImpl* delegated_renderer_layer_impl =
+      impl.AddChildToRoot<FakeDelegatedRendererLayerImpl>();
+  delegated_renderer_layer_impl->SetAnchorPoint(gfx::PointF());
+  delegated_renderer_layer_impl->SetBounds(layer_size);
+  delegated_renderer_layer_impl->SetContentBounds(layer_size);
+  delegated_renderer_layer_impl->SetDrawsContent(true);
+
+  ScopedPtrVector<RenderPass> delegated_render_passes;
+  // pass2 is just the size of the quad. It contributes to |pass1| with a
+  // translation of (11,0).
+  RenderPass::Id pass2_id =
+      delegated_renderer_layer_impl->FirstContributingRenderPassId();
+  TestRenderPass* pass2 =
+      AddRenderPass(&delegated_render_passes, pass2_id, quad_rect, transform);
+  AddQuad(pass2, gfx::Rect(quad_rect.size()), SK_ColorRED);
+  // |pass1| covers the whole layer.
+  RenderPass::Id pass1_id = RenderPass::Id(impl.root_layer()->id(), 0);
+  TestRenderPass* pass1 = AddRenderPass(&delegated_render_passes,
+                                        pass1_id,
+                                        gfx::Rect(layer_size),
+                                        gfx::Transform());
+  AddRenderPassQuad(pass1, pass2, 0, FilterOperations(), transform);
+  delegated_renderer_layer_impl->SetFrameDataForRenderPasses(
+      &delegated_render_passes);
+
+  impl.CalcDrawProps(viewport_size);
+
+  // The |quad_rect| translated by the |transform|.
+  gfx::Rect quad_screen_rect = quad_rect + gfx::Vector2d(11, 0);
+
+  {
+    SCOPED_TRACE("No occlusion");
+    gfx::Rect occluded;
+
+    {
+      SCOPED_TRACE("Root render pass");
+      impl.AppendQuadsForPassWithOcclusion(
+          delegated_renderer_layer_impl, pass1_id, occluded);
+      LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
+                                                   quad_screen_rect);
+      ASSERT_EQ(1u, impl.quad_list().size());
+      EXPECT_EQ(DrawQuad::RENDER_PASS, impl.quad_list()[0]->material);
+    }
+    {
+      SCOPED_TRACE("Contributing render pass");
+      impl.AppendQuadsForPassWithOcclusion(
+          delegated_renderer_layer_impl, pass2_id, occluded);
+      LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
+                                                   gfx::Rect(quad_rect.size()));
+      ASSERT_EQ(1u, impl.quad_list().size());
+      EXPECT_EQ(DrawQuad::SOLID_COLOR, impl.quad_list()[0]->material);
+    }
+  }
+
+  {
+    SCOPED_TRACE("Full occlusion");
+    {
+      gfx::Rect occluded(delegated_renderer_layer_impl->visible_content_rect());
+
+      SCOPED_TRACE("Root render pass");
+      impl.AppendQuadsForPassWithOcclusion(
+          delegated_renderer_layer_impl, pass1_id, occluded);
+      LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
+                                                   gfx::Rect());
+      EXPECT_EQ(impl.quad_list().size(), 0u);
+    }
+    {
+      gfx::Rect occluded(delegated_renderer_layer_impl->visible_content_rect());
+      // Move the occlusion to where it is in the contributing surface.
+      occluded -= quad_rect.OffsetFromOrigin();
+
+      SCOPED_TRACE("Contributing render pass");
+      impl.AppendQuadsForPassWithOcclusion(
+          delegated_renderer_layer_impl, pass2_id, occluded);
+      LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
+                                                   gfx::Rect());
+      EXPECT_EQ(impl.quad_list().size(), 0u);
+    }
+  }
+
+  {
+    SCOPED_TRACE("Partial occlusion");
+    {
+      gfx::Rect occluded(0, 0, 500, 1000);
+
+      SCOPED_TRACE("Root render pass");
+      impl.AppendQuadsForPassWithOcclusion(
+          delegated_renderer_layer_impl, pass1_id, occluded);
+      size_t partially_occluded_count = 0;
+      LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
+          impl.quad_list(),
+          quad_screen_rect,
+          occluded,
+          &partially_occluded_count);
+      // The layer outputs one quad, which is partially occluded.
+      EXPECT_EQ(1u, impl.quad_list().size());
+      EXPECT_EQ(1u, partially_occluded_count);
+    }
+    {
+      gfx::Rect occluded(0, 0, 500, 1000);
+      // Move the occlusion to where it is in the contributing surface.
+      occluded -= quad_rect.OffsetFromOrigin() + gfx::Vector2d(11, 0);
+
+      SCOPED_TRACE("Contributing render pass");
+      impl.AppendQuadsForPassWithOcclusion(
+          delegated_renderer_layer_impl, pass2_id, occluded);
+      size_t partially_occluded_count = 0;
+      LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
+          impl.quad_list(),
+          gfx::Rect(quad_rect.size()),
+          occluded,
+          &partially_occluded_count);
+      // The layer outputs one quad, which is partially occluded.
+      EXPECT_EQ(1u, impl.quad_list().size());
+      EXPECT_EQ(1u, partially_occluded_count);
+      // The quad in the contributing surface is at (211,300) in the root.
+      // The occlusion extends to 500 in the x-axis, pushing the left of the
+      // visible part of the quad to 500 - 211 = 300 - 11 inside the quad.
+      EXPECT_EQ(gfx::Rect(300 - 11, 0, 100 + 11, 500).ToString(),
+                impl.quad_list()[0]->visible_rect.ToString());
+    }
+  }
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index c6ed5fc..888913c 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -170,13 +170,14 @@
   }
 
   TRACE_EVENT0("cc", "UploadHudTexture");
-  const SkBitmap* bitmap = &hud_canvas_->getDevice()->accessBitmap(false);
-  SkAutoLockPixels locker(*bitmap);
-
+  SkImageInfo info;
+  size_t row_bytes = 0;
+  const void* pixels = hud_canvas_->peekPixels(&info, &row_bytes);
+  DCHECK(pixels);
   gfx::Rect content_rect(content_bounds());
-  DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config);
+  DCHECK(info.colorType() == kPMColor_SkColorType);
   resource_provider->SetPixels(hud_resource_->id(),
-                               static_cast<const uint8_t*>(bitmap->getPixels()),
+                               static_cast<const uint8_t*>(pixels),
                                content_rect,
                                content_rect,
                                gfx::Vector2d());
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc
index d016571..44c71e5 100644
--- a/cc/layers/layer.cc
+++ b/cc/layers/layer.cc
@@ -674,11 +674,6 @@
 void Layer::SetScrollOffset(gfx::Vector2d scroll_offset) {
   DCHECK(IsPropertyChangeAllowed());
 
-  if (layer_tree_host()) {
-    scroll_offset = layer_tree_host()->DistributeScrollOffsetToViewports(
-        scroll_offset, this);
-  }
-
   if (scroll_offset_ == scroll_offset)
     return;
   scroll_offset_ = scroll_offset;
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 363bffb..06981ea 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -310,7 +310,7 @@
       DebugBorderDrawQuad::Create();
   debug_border_quad->SetNew(
       shared_quad_state, quad_rect, visible_quad_rect, color, width);
-  quad_sink->MaybeAppend(debug_border_quad.PassAs<DrawQuad>());
+  quad_sink->Append(debug_border_quad.PassAs<DrawQuad>());
 }
 
 bool LayerImpl::HasDelegatedContent() const {
@@ -1156,7 +1156,7 @@
   DCHECK(this != layer_tree_impl()->InnerViewportScrollLayer() ||
          IsContainerForFixedPositionLayers());
 
-  gfx::Size scaled_scroll_bounds(bounds());
+  gfx::SizeF scaled_scroll_bounds(bounds());
 
   float scale_factor = 1.f;
   for (LayerImpl const* current_layer = this;
@@ -1285,7 +1285,7 @@
   // viewport).
   if (scrollbar_animation_controller_) {
     bool should_animate = scrollbar_animation_controller_->DidScrollUpdate(
-        layer_tree_impl_->CurrentPhysicalTimeTicks());
+        layer_tree_impl_->CurrentFrameTimeTicks());
     if (should_animate)
       layer_tree_impl_->StartScrollbarAnimation();
   }
diff --git a/cc/layers/nine_patch_layer_impl_unittest.cc b/cc/layers/nine_patch_layer_impl_unittest.cc
index 614f5ed..2a7cf9c 100644
--- a/cc/layers/nine_patch_layer_impl_unittest.cc
+++ b/cc/layers/nine_patch_layer_impl_unittest.cc
@@ -55,12 +55,8 @@
   layer->draw_properties().render_target = layer.get();
 
   UIResourceId uid = 1;
-  SkBitmap skbitmap;
-  skbitmap.setConfig(
-      SkBitmap::kARGB_8888_Config, bitmap_size.width(), bitmap_size.height());
-  skbitmap.allocPixels();
-  skbitmap.setImmutable();
-  UIResourceBitmap bitmap(skbitmap);
+  bool is_opaque = false;
+  UIResourceBitmap bitmap(bitmap_size, is_opaque);
 
   host_impl.CreateUIResource(uid, bitmap);
   layer->SetUIResourceId(uid);
diff --git a/cc/layers/nine_patch_layer_unittest.cc b/cc/layers/nine_patch_layer_unittest.cc
index cdb2af3..4166d8e 100644
--- a/cc/layers/nine_patch_layer_unittest.cc
+++ b/cc/layers/nine_patch_layer_unittest.cc
@@ -64,13 +64,9 @@
 
   EXPECT_FALSE(test_layer->DrawsContent());
 
-  SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
-  bitmap.allocPixels();
-  bitmap.setImmutable();
-
+  bool is_opaque = false;
   scoped_ptr<ScopedUIResource> resource = ScopedUIResource::Create(
-      layer_tree_host_.get(), UIResourceBitmap(bitmap));
+      layer_tree_host_.get(), UIResourceBitmap(gfx::Size(10, 10), is_opaque));
   gfx::Rect aperture(5, 5, 1, 1);
   bool fill_center = true;
   test_layer->SetAperture(aperture);
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc
index 320ea30..f88951b 100644
--- a/cc/layers/painted_scrollbar_layer.cc
+++ b/cc/layers/painted_scrollbar_layer.cc
@@ -247,11 +247,7 @@
   DCHECK(!layer_rect.size().IsEmpty());
 
   SkBitmap skbitmap;
-  skbitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                     content_rect.width(),
-                     content_rect.height());
-  skbitmap.allocPixels();
-
+  skbitmap.allocN32Pixels(content_rect.width(), content_rect.height());
   SkCanvas skcanvas(skbitmap);
 
   float scale_x =
diff --git a/cc/layers/picture_image_layer.cc b/cc/layers/picture_image_layer.cc
index 127560d..caf8c0b 100644
--- a/cc/layers/picture_image_layer.cc
+++ b/cc/layers/picture_image_layer.cc
@@ -52,7 +52,17 @@
       SkFloatToScalar(static_cast<float>(bounds().height()) / bitmap_.height());
   canvas->scale(content_to_layer_scale_x, content_to_layer_scale_y);
 
-  canvas->drawBitmap(bitmap_, 0, 0);
+  // Because PictureImageLayer always FillsBoundsCompletely it will not clear
+  // before painting on playback. As a result we must configure the paint to
+  // copy over the uncleared destination, rather than blending with it.
+  SkPaint paint;
+  paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+  canvas->drawBitmap(bitmap_, 0, 0, &paint);
+}
+
+bool PictureImageLayer::FillsBoundsCompletely() const {
+  // PictureImageLayer will always paint to the entire layer bounds.
+  return true;
 }
 
 }  // namespace cc
diff --git a/cc/layers/picture_image_layer.h b/cc/layers/picture_image_layer.h
index 8066428..1457a9f 100644
--- a/cc/layers/picture_image_layer.h
+++ b/cc/layers/picture_image_layer.h
@@ -30,6 +30,7 @@
       const gfx::Rect& clip,
       gfx::RectF* opaque) OVERRIDE;
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
+  virtual bool FillsBoundsCompletely() const OVERRIDE;
 
  private:
   PictureImageLayer();
diff --git a/cc/layers/picture_layer.cc b/cc/layers/picture_layer.cc
index 3a474d3..dee9a78 100644
--- a/cc/layers/picture_layer.cc
+++ b/cc/layers/picture_layer.cc
@@ -111,9 +111,11 @@
     // the full page content must always be provided in the picture layer.
     visible_layer_rect = gfx::Rect(bounds());
   }
+  DCHECK(client_);
   updated |= pile_->Update(client_,
                            SafeOpaqueBackgroundColor(),
                            contents_opaque(),
+                           client_->FillsBoundsCompletely(),
                            pile_invalidation_,
                            visible_layer_rect,
                            update_source_frame_number_,
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index c85e0c5..9dbcb49 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -482,8 +482,6 @@
 void PictureLayerImpl::SetHasGpuRasterizationHint(bool has_hint) {
   bool old_should_use_gpu_rasterization = ShouldUseGpuRasterization();
   has_gpu_rasterization_hint_ = has_hint;
-  if (has_gpu_rasterization_hint_)
-    should_use_low_res_tiling_ = false;
   if (ShouldUseGpuRasterization() != old_should_use_gpu_rasterization)
     RemoveAllTilings();
 }
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index 4b997fa..9ce3e41 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -123,7 +123,9 @@
   void RemoveAllTilings();
   void SyncFromActiveLayer(const PictureLayerImpl* other);
   void ManageTilings(bool animating_transform_to_screen);
-  bool ShouldHaveLowResTiling() const { return should_use_low_res_tiling_; }
+  bool ShouldHaveLowResTiling() const {
+    return should_use_low_res_tiling_ && !ShouldUseGpuRasterization();
+  }
   virtual bool ShouldAdjustRasterScale(
       bool animating_transform_to_screen) const;
   virtual void RecalculateRasterScales(
diff --git a/cc/layers/picture_layer_unittest.cc b/cc/layers/picture_layer_unittest.cc
index 25bfd99..3ff1de5 100644
--- a/cc/layers/picture_layer_unittest.cc
+++ b/cc/layers/picture_layer_unittest.cc
@@ -24,6 +24,9 @@
                              const gfx::Rect& clip,
                              gfx::RectF* opaque) OVERRIDE {}
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
+  virtual bool FillsBoundsCompletely() const OVERRIDE {
+    return false;
+  };
 };
 
 TEST(PictureLayerTest, NoTilesIfEmptyBounds) {
diff --git a/cc/layers/quad_sink.h b/cc/layers/quad_sink.h
index 1b82470..add4e99 100644
--- a/cc/layers/quad_sink.h
+++ b/cc/layers/quad_sink.h
@@ -16,6 +16,7 @@
 namespace cc {
 
 class DrawQuad;
+class LayerImpl;
 class SharedQuadState;
 
 class CC_EXPORT QuadSink {
@@ -32,6 +33,10 @@
       const gfx::Rect& content_rect,
       const gfx::Transform& draw_transform) = 0;
 
+  virtual gfx::Rect UnoccludedContributingSurfaceContentRect(
+      const gfx::Rect& content_rect,
+      const gfx::Transform& draw_transform) = 0;
+
   // Returns true if the quad is added to the list, and false if the quad is
   // entirely culled.
   virtual bool MaybeAppend(scoped_ptr<DrawQuad> draw_quad) = 0;
diff --git a/cc/layers/render_surface_impl.cc b/cc/layers/render_surface_impl.cc
index 9a1edbf..ddb7158 100644
--- a/cc/layers/render_surface_impl.cc
+++ b/cc/layers/render_surface_impl.cc
@@ -143,6 +143,12 @@
 
   const gfx::Transform& draw_transform =
       for_replica ? replica_draw_transform_ : draw_transform_;
+  gfx::Rect visible_content_rect =
+      quad_sink->UnoccludedContributingSurfaceContentRect(content_rect_,
+                                                          draw_transform);
+  if (visible_content_rect.IsEmpty())
+    return;
+
   SharedQuadState* shared_quad_state =
       quad_sink->UseSharedQuadState(SharedQuadState::Create());
   shared_quad_state->SetAll(draw_transform,
@@ -154,8 +160,6 @@
                             owning_layer_->blend_mode());
 
   if (owning_layer_->ShowDebugBorders()) {
-    gfx::Rect quad_rect = content_rect_;
-    gfx::Rect visible_quad_rect = quad_rect;
     SkColor color = for_replica ?
                     DebugColors::SurfaceReplicaBorderColor() :
                     DebugColors::SurfaceBorderColor();
@@ -167,8 +171,8 @@
     scoped_ptr<DebugBorderDrawQuad> debug_border_quad =
         DebugBorderDrawQuad::Create();
     debug_border_quad->SetNew(
-        shared_quad_state, quad_rect, visible_quad_rect, color, width);
-    quad_sink->MaybeAppend(debug_border_quad.PassAs<DrawQuad>());
+        shared_quad_state, content_rect_, visible_content_rect, color, width);
+    quad_sink->Append(debug_border_quad.PassAs<DrawQuad>());
   }
 
   // TODO(shawnsingh): By using the same RenderSurfaceImpl for both the content
@@ -212,7 +216,6 @@
         uv_scale_y);
   }
 
-  gfx::Rect visible_content_rect(content_rect_);
   ResourceProvider::ResourceId mask_resource_id =
       mask_layer ? mask_layer->ContentsResourceId() : 0;
   gfx::Rect contents_changed_since_last_frame =
@@ -229,7 +232,7 @@
                mask_uv_rect,
                owning_layer_->filters(),
                owning_layer_->background_filters());
-  quad_sink->MaybeAppend(quad.PassAs<DrawQuad>());
+  quad_sink->Append(quad.PassAs<DrawQuad>());
 }
 
 }  // namespace cc
diff --git a/cc/layers/render_surface_impl_unittest.cc b/cc/layers/render_surface_impl_unittest.cc
new file mode 100644
index 0000000..20c2afb
--- /dev/null
+++ b/cc/layers/render_surface_impl_unittest.cc
@@ -0,0 +1,68 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/layers/render_surface_impl.h"
+
+#include "cc/test/layer_test_common.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cc {
+namespace {
+
+TEST(RenderSurfaceLayerImplTest, Occlusion) {
+  gfx::Size layer_size(1000, 1000);
+  gfx::Size viewport_size(1000, 1000);
+
+  LayerTestCommon::LayerImplTest impl;
+
+  LayerImpl* owning_layer_impl = impl.AddChildToRoot<LayerImpl>();
+  owning_layer_impl->SetAnchorPoint(gfx::PointF());
+  owning_layer_impl->SetBounds(layer_size);
+  owning_layer_impl->SetContentBounds(layer_size);
+  owning_layer_impl->SetDrawsContent(true);
+  owning_layer_impl->SetForceRenderSurface(true);
+
+  impl.CalcDrawProps(viewport_size);
+
+  RenderSurfaceImpl* render_surface_impl = owning_layer_impl->render_surface();
+  ASSERT_TRUE(render_surface_impl);
+
+  {
+    SCOPED_TRACE("No occlusion");
+    gfx::Rect occluded;
+    impl.AppendSurfaceQuadsWithOcclusion(render_surface_impl, occluded);
+
+    LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(),
+                                                 gfx::Rect(layer_size));
+    EXPECT_EQ(1u, impl.quad_list().size());
+  }
+
+  {
+    SCOPED_TRACE("Full occlusion");
+    gfx::Rect occluded(owning_layer_impl->visible_content_rect());
+    impl.AppendSurfaceQuadsWithOcclusion(render_surface_impl, occluded);
+
+    LayerTestCommon::VerifyQuadsExactlyCoverRect(impl.quad_list(), gfx::Rect());
+    EXPECT_EQ(impl.quad_list().size(), 0u);
+  }
+
+  {
+    SCOPED_TRACE("Partial occlusion");
+    gfx::Rect occluded(200, 0, 800, 1000);
+    impl.AppendSurfaceQuadsWithOcclusion(render_surface_impl, occluded);
+
+    size_t partially_occluded_count = 0;
+    LayerTestCommon::VerifyQuadsCoverRectWithOcclusion(
+        impl.quad_list(),
+        gfx::Rect(layer_size),
+        occluded,
+        &partially_occluded_count);
+    // The layer outputs one quad, which is partially occluded.
+    EXPECT_EQ(1u, impl.quad_list().size());
+    EXPECT_EQ(1u, partially_occluded_count);
+  }
+}
+
+}  // namespace
+}  // namespace cc
diff --git a/cc/layers/ui_resource_layer_impl_unittest.cc b/cc/layers/ui_resource_layer_impl_unittest.cc
index c5933b6..e5eacc5 100644
--- a/cc/layers/ui_resource_layer_impl_unittest.cc
+++ b/cc/layers/ui_resource_layer_impl_unittest.cc
@@ -35,15 +35,7 @@
   layer->CreateRenderSurface();
   layer->draw_properties().render_target = layer.get();
 
-  SkBitmap skbitmap;
-  skbitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                     bitmap_size.width(),
-                     bitmap_size.height(),
-                     0,
-                     opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-  skbitmap.allocPixels();
-  skbitmap.setImmutable();
-  UIResourceBitmap bitmap(skbitmap);
+  UIResourceBitmap bitmap(bitmap_size, opaque);
 
   host_impl->CreateUIResource(uid, bitmap);
   layer->SetUIResourceId(uid);
diff --git a/cc/layers/ui_resource_layer_unittest.cc b/cc/layers/ui_resource_layer_unittest.cc
index 1e0e1de..25cc2c7 100644
--- a/cc/layers/ui_resource_layer_unittest.cc
+++ b/cc/layers/ui_resource_layer_unittest.cc
@@ -65,8 +65,7 @@
   EXPECT_FALSE(test_layer->DrawsContent());
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
-  bitmap.allocPixels();
+  bitmap.allocN32Pixels(10, 10);
   bitmap.setImmutable();
 
   test_layer->SetBitmap(bitmap);
@@ -93,13 +92,9 @@
 
   EXPECT_FALSE(test_layer->DrawsContent());
 
-  SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
-  bitmap.allocPixels();
-  bitmap.setImmutable();
-
+  bool is_opaque = false;
   scoped_ptr<ScopedUIResource> resource = ScopedUIResource::Create(
-      layer_tree_host_.get(), UIResourceBitmap(bitmap));
+      layer_tree_host_.get(), UIResourceBitmap(gfx::Size(10, 10), is_opaque));
   test_layer->SetUIResourceId(resource->id());
   test_layer->Update(&queue, &occlusion_tracker);
 
diff --git a/cc/layers/video_frame_provider_client_impl.cc b/cc/layers/video_frame_provider_client_impl.cc
index 732bbbb..9071fdc 100644
--- a/cc/layers/video_frame_provider_client_impl.cc
+++ b/cc/layers/video_frame_provider_client_impl.cc
@@ -22,7 +22,7 @@
 
 VideoFrameProviderClientImpl::VideoFrameProviderClientImpl(
     VideoFrameProvider* provider)
-    : provider_(provider) {
+    : active_video_layer_(NULL), provider_(provider) {
   // This only happens during a commit on the compositor thread while the main
   // thread is blocked. That makes this a thread-safe call to set the video
   // frame provider client that does not require a lock. The same is true of
diff --git a/cc/layers/video_frame_provider_client_impl.h b/cc/layers/video_frame_provider_client_impl.h
index 2bcb446..e676d0b 100644
--- a/cc/layers/video_frame_provider_client_impl.h
+++ b/cc/layers/video_frame_provider_client_impl.h
@@ -22,6 +22,7 @@
   static scoped_refptr<VideoFrameProviderClientImpl> Create(
       VideoFrameProvider* provider);
 
+  VideoLayerImpl* active_video_layer() { return active_video_layer_; }
   void set_active_video_layer(VideoLayerImpl* video_layer) {
     active_video_layer_ = video_layer;
   }
diff --git a/cc/layers/video_layer_impl.cc b/cc/layers/video_layer_impl.cc
index 101965a..e6e54a1 100644
--- a/cc/layers/video_layer_impl.cc
+++ b/cc/layers/video_layer_impl.cc
@@ -143,10 +143,14 @@
     return;
 
   // Pixels for macroblocked formats.
-  float tex_width_scale =
+  const float tex_width_scale =
       static_cast<float>(visible_rect.width()) / coded_size.width();
-  float tex_height_scale =
+  const float tex_height_scale =
       static_cast<float>(visible_rect.height()) / coded_size.height();
+  const float tex_x_offset =
+      static_cast<float>(visible_rect.x()) / coded_size.width();
+  const float tex_y_offset =
+      static_cast<float>(visible_rect.y()) / coded_size.height();
 
   switch (frame_resource_type_) {
     // TODO(danakj): Remove this, hide it in the hardware path.
@@ -179,14 +183,15 @@
       DCHECK_GE(frame_resources_.size(), 3u);
       if (frame_resources_.size() < 3u)
         break;
-      gfx::SizeF tex_scale(tex_width_scale, tex_height_scale);
+      gfx::RectF tex_coord_rect(
+          tex_x_offset, tex_y_offset, tex_width_scale, tex_height_scale);
       scoped_ptr<YUVVideoDrawQuad> yuv_video_quad = YUVVideoDrawQuad::Create();
       yuv_video_quad->SetNew(
           shared_quad_state,
           quad_rect,
           opaque_rect,
           visible_quad_rect,
-          tex_scale,
+          tex_coord_rect,
           frame_resources_[0],
           frame_resources_[1],
           frame_resources_[2],
@@ -240,14 +245,13 @@
       DCHECK_EQ(frame_resources_.size(), 1u);
       if (frame_resources_.size() < 1u)
         break;
-      gfx::Size visible_size(visible_rect.width(), visible_rect.height());
       scoped_ptr<IOSurfaceDrawQuad> io_surface_quad =
           IOSurfaceDrawQuad::Create();
       io_surface_quad->SetNew(shared_quad_state,
                               quad_rect,
                               opaque_rect,
                               visible_quad_rect,
-                              visible_size,
+                              visible_rect.size(),
                               frame_resources_[0],
                               IOSurfaceDrawQuad::UNFLIPPED);
       quad_sink->Append(io_surface_quad.PassAs<DrawQuad>());
@@ -275,8 +279,7 @@
                                     false,
                                     SK_ColorTRANSPARENT,
                                     true);
-      quad_sink->Append(solid_color_draw_quad.PassAs<DrawQuad>(),
-                        append_quads_data);
+      quad_sink->Append(solid_color_draw_quad.PassAs<DrawQuad>());
       break;
     }
 #endif  // defined(VIDEO_HOLE)
diff --git a/cc/layers/video_layer_impl_unittest.cc b/cc/layers/video_layer_impl_unittest.cc
index dc9c6fb..68a2b2e 100644
--- a/cc/layers/video_layer_impl_unittest.cc
+++ b/cc/layers/video_layer_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "cc/layers/video_layer_impl.h"
 
+#include "cc/layers/video_frame_provider_client_impl.h"
 #include "cc/output/context_provider.h"
 #include "cc/output/output_surface.h"
 #include "cc/test/fake_video_frame_provider.h"
@@ -76,5 +77,22 @@
   }
 }
 
+TEST(VideoLayerImplTest, DidBecomeActiveShouldSetActiveVideoLayer) {
+  LayerTestCommon::LayerImplTest impl;
+  DebugScopedSetImplThreadAndMainThreadBlocked thread(impl.proxy());
+
+  FakeVideoFrameProvider provider;
+  VideoLayerImpl* video_layer_impl =
+      impl.AddChildToRoot<VideoLayerImpl>(&provider);
+
+  VideoFrameProviderClientImpl* client =
+      static_cast<VideoFrameProviderClientImpl*>(provider.client());
+  ASSERT_TRUE(client);
+  EXPECT_FALSE(client->active_video_layer());
+
+  video_layer_impl->DidBecomeActive();
+  EXPECT_EQ(video_layer_impl, client->active_video_layer());
+}
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/output/delegating_renderer.cc b/cc/output/delegating_renderer.cc
index b189386..e2d3145 100644
--- a/cc/output/delegating_renderer.cc
+++ b/cc/output/delegating_renderer.cc
@@ -171,8 +171,8 @@
                                                 size_t bytes_allocated) {
   ContextProvider* context_provider = output_surface_->context_provider();
   if (!context_provider) {
-    // TODO(piman): software path.
-    NOTIMPLEMENTED();
+    // In the software path each child process manages its memory separately,
+    // so memory stats don't have to be sent anywhere.
     return;
   }
   gpu::ManagedMemoryStats stats;
diff --git a/cc/output/direct_renderer.cc b/cc/output/direct_renderer.cc
index 1eb0fbc..0eb2dcb 100644
--- a/cc/output/direct_renderer.cc
+++ b/cc/output/direct_renderer.cc
@@ -133,7 +133,11 @@
                                ResourceProvider* resource_provider)
     : Renderer(client, settings),
       output_surface_(output_surface),
-      resource_provider_(resource_provider) {}
+      resource_provider_(resource_provider),
+      overlay_processor_(
+          new OverlayProcessor(output_surface, resource_provider)) {
+  overlay_processor_->Initialize();
+}
 
 DirectRenderer::~DirectRenderer() {}
 
@@ -218,6 +222,9 @@
   frame.disable_picture_quad_image_filtering =
       disable_picture_quad_image_filtering;
 
+  overlay_processor_->ProcessForOverlays(render_passes_in_draw_order,
+                                         &frame.overlay_list);
+
   EnsureBackbuffer();
 
   // Only reshape when we know we are going to draw. Otherwise, the reshape
diff --git a/cc/output/direct_renderer.h b/cc/output/direct_renderer.h
index a08feef..fce36db 100644
--- a/cc/output/direct_renderer.h
+++ b/cc/output/direct_renderer.h
@@ -9,6 +9,7 @@
 #include "base/callback.h"
 #include "base/containers/scoped_ptr_hash_map.h"
 #include "cc/base/cc_export.h"
+#include "cc/output/overlay_processor.h"
 #include "cc/output/renderer.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/scoped_resource.h"
@@ -57,6 +58,8 @@
     ContextProvider* offscreen_context_provider;
 
     bool disable_picture_quad_image_filtering;
+
+    OverlayCandidateList overlay_list;
   };
 
   void SetEnlargePassTextureAmountForTesting(const gfx::Vector2d& amount);
@@ -123,6 +126,7 @@
   base::ScopedPtrHashMap<RenderPass::Id, ScopedResource> render_pass_textures_;
   OutputSurface* output_surface_;
   ResourceProvider* resource_provider_;
+  scoped_ptr<OverlayProcessor> overlay_processor_;
 
   // For use in coordinate conversion, this stores the output rect, viewport
   // rect (= unflipped version of glViewport rect), and the size of target
diff --git a/cc/output/gl_renderer.cc b/cc/output/gl_renderer.cc
index 89b1e00..1e16121 100644
--- a/cc/output/gl_renderer.cc
+++ b/cc/output/gl_renderer.cc
@@ -258,6 +258,8 @@
     pending_async_read_pixels_.pop_back();
   }
 
+  in_use_overlay_resources_.clear();
+
   CleanupSharedObjects();
 }
 
@@ -1631,8 +1633,9 @@
     DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), a_plane_lock->target());
   }
 
-  int tex_scale_location = -1;
   int matrix_location = -1;
+  int tex_scale_location = -1;
+  int tex_offset_location = -1;
   int y_texture_location = -1;
   int u_texture_location = -1;
   int v_texture_location = -1;
@@ -1644,8 +1647,9 @@
     const VideoYUVAProgram* program = GetVideoYUVAProgram(tex_coord_precision);
     DCHECK(program && (program->initialized() || IsContextLost()));
     SetUseProgram(program->program());
-    tex_scale_location = program->vertex_shader().tex_scale_location();
     matrix_location = program->vertex_shader().matrix_location();
+    tex_scale_location = program->vertex_shader().tex_scale_location();
+    tex_offset_location = program->vertex_shader().tex_offset_location();
     y_texture_location = program->fragment_shader().y_texture_location();
     u_texture_location = program->fragment_shader().u_texture_location();
     v_texture_location = program->fragment_shader().v_texture_location();
@@ -1657,8 +1661,9 @@
     const VideoYUVProgram* program = GetVideoYUVProgram(tex_coord_precision);
     DCHECK(program && (program->initialized() || IsContextLost()));
     SetUseProgram(program->program());
-    tex_scale_location = program->vertex_shader().tex_scale_location();
     matrix_location = program->vertex_shader().matrix_location();
+    tex_scale_location = program->vertex_shader().tex_scale_location();
+    tex_offset_location = program->vertex_shader().tex_offset_location();
     y_texture_location = program->fragment_shader().y_texture_location();
     u_texture_location = program->fragment_shader().u_texture_location();
     v_texture_location = program->fragment_shader().v_texture_location();
@@ -1669,8 +1674,12 @@
 
   GLC(gl_,
       gl_->Uniform2f(tex_scale_location,
-                     quad->tex_scale.width(),
-                     quad->tex_scale.height()));
+                     quad->tex_coord_rect.width(),
+                     quad->tex_coord_rect.height()));
+  GLC(gl_,
+      gl_->Uniform2f(tex_offset_location,
+                     quad->tex_coord_rect.x(),
+                     quad->tex_coord_rect.y()));
   GLC(gl_, gl_->Uniform1i(y_texture_location, 1));
   GLC(gl_, gl_->Uniform1i(u_texture_location, 2));
   GLC(gl_, gl_->Uniform1i(v_texture_location, 3));
@@ -1739,10 +1748,8 @@
                                  const PictureDrawQuad* quad) {
   if (on_demand_tile_raster_bitmap_.width() != quad->texture_size.width() ||
       on_demand_tile_raster_bitmap_.height() != quad->texture_size.height()) {
-    on_demand_tile_raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
-                                            quad->texture_size.width(),
-                                            quad->texture_size.height());
-    on_demand_tile_raster_bitmap_.allocPixels();
+    on_demand_tile_raster_bitmap_.allocN32Pixels(quad->texture_size.width(),
+                                                 quad->texture_size.height());
 
     if (on_demand_tile_raster_resource_id_)
       resource_provider_->DeleteResource(on_demand_tile_raster_resource_id_);
@@ -2000,6 +2007,8 @@
 
   GLC(gl_, gl_->Disable(GL_BLEND));
   blend_shadow_ = false;
+
+  ScheduleOverlays(frame);
 }
 
 void GLRenderer::FinishDrawingQuadList() { FlushTextureQuadCache(); }
@@ -2171,6 +2180,11 @@
   }
   output_surface_->SwapBuffers(&compositor_frame);
 
+  // Release previously used overlay resources and hold onto the pending ones
+  // until the next swap buffers.
+  in_use_overlay_resources_.clear();
+  in_use_overlay_resources_.swap(pending_overlay_resources_);
+
   swap_buffer_rect_ = gfx::Rect();
 
   // We don't have real fences, so we mark read fences as passed
@@ -2298,9 +2312,7 @@
   DCHECK(request->force_bitmap_result());
 
   scoped_ptr<SkBitmap> bitmap(new SkBitmap);
-  bitmap->setConfig(
-      SkBitmap::kARGB_8888_Config, window_rect.width(), window_rect.height());
-  bitmap->allocPixels();
+  bitmap->allocN32Pixels(window_rect.width(), window_rect.height());
 
   scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap));
 
@@ -3047,4 +3059,30 @@
   return output_surface_->context_provider()->IsContextLost();
 }
 
+void GLRenderer::ScheduleOverlays(DrawingFrame* frame) {
+  if (!frame->overlay_list.size())
+    return;
+
+  ResourceProvider::ResourceIdArray resources;
+  OverlayCandidateList& overlays = frame->overlay_list;
+  OverlayCandidateList::iterator it;
+  for (it = overlays.begin(); it != overlays.end(); ++it) {
+    const OverlayCandidate& overlay = *it;
+    // Skip primary plane.
+    if (overlay.plane_z_order == 0)
+      continue;
+
+    pending_overlay_resources_.push_back(
+        make_scoped_ptr(new ResourceProvider::ScopedReadLockGL(
+            resource_provider(), overlay.resource_id)));
+
+    context_support_->ScheduleOverlayPlane(
+        overlay.plane_z_order,
+        overlay.transform,
+        pending_overlay_resources_.back()->texture_id(),
+        overlay.display_rect,
+        overlay.uv_rect);
+  }
+}
+
 }  // namespace cc
diff --git a/cc/output/gl_renderer.h b/cc/output/gl_renderer.h
index 82befc7..13a9060 100644
--- a/cc/output/gl_renderer.h
+++ b/cc/output/gl_renderer.h
@@ -220,6 +220,13 @@
   virtual void EnsureBackbuffer() OVERRIDE;
   void EnforceMemoryPolicy();
 
+  void ScheduleOverlays(DrawingFrame* frame);
+
+  typedef ScopedPtrVector<ResourceProvider::ScopedReadLockGL>
+      OverlayResourceLockList;
+  OverlayResourceLockList pending_overlay_resources_;
+  OverlayResourceLockList in_use_overlay_resources_;
+
   RendererCapabilitiesImpl capabilities_;
 
   unsigned offscreen_framebuffer_id_;
@@ -286,10 +293,10 @@
   // Video shaders.
   typedef ProgramBinding<VertexShaderVideoTransform, FragmentShaderRGBATex>
       VideoStreamTextureProgram;
-  typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVVideo>
-      VideoYUVProgram;
-  typedef ProgramBinding<VertexShaderPosTexYUVStretch, FragmentShaderYUVAVideo>
-      VideoYUVAProgram;
+  typedef ProgramBinding<VertexShaderPosTexYUVStretchOffset,
+                         FragmentShaderYUVVideo> VideoYUVProgram;
+  typedef ProgramBinding<VertexShaderPosTexYUVStretchOffset,
+                         FragmentShaderYUVAVideo> VideoYUVAProgram;
 
   // Special purpose / effects shaders.
   typedef ProgramBinding<VertexShaderPos, FragmentShaderColor>
diff --git a/cc/output/overlay_candidate.cc b/cc/output/overlay_candidate.cc
index dd3ebc2..05a510b 100644
--- a/cc/output/overlay_candidate.cc
+++ b/cc/output/overlay_candidate.cc
@@ -2,7 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "cc/output/overlay_candidate_validator.h"
+#include "cc/output/overlay_candidate.h"
+
+#include "ui/gfx/rect_conversions.h"
 
 namespace cc {
 
@@ -10,8 +12,30 @@
     : transform(NONE),
       format(RGBA_8888),
       uv_rect(0.f, 0.f, 1.f, 1.f),
+      resource_id(0),
+      plane_z_order(0),
       overlay_handled(false) {}
 
 OverlayCandidate::~OverlayCandidate() {}
 
+// static
+OverlayCandidate::OverlayTransform OverlayCandidate::GetOverlayTransform(
+    const gfx::Transform& quad_transform,
+    bool flipped) {
+  if (!quad_transform.IsIdentityOrTranslation())
+    return INVALID;
+
+  return flipped ? FLIP_VERTICAL : NONE;
+}
+
+// static
+gfx::Rect OverlayCandidate::GetOverlayRect(const gfx::Transform& quad_transform,
+                                           const gfx::Rect& rect) {
+  DCHECK(quad_transform.IsIdentityOrTranslation());
+
+  gfx::RectF float_rect(rect);
+  quad_transform.TransformRect(&float_rect);
+  return gfx::ToNearestRect(float_rect);
+}
+
 }  // namespace cc
diff --git a/cc/output/overlay_candidate.h b/cc/output/overlay_candidate.h
index c530136..e6883cc 100644
--- a/cc/output/overlay_candidate.h
+++ b/cc/output/overlay_candidate.h
@@ -11,11 +11,14 @@
 #include "cc/base/cc_export.h"
 #include "cc/resources/resource_format.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
 
 namespace cc {
 
-struct CC_EXPORT OverlayCandidate {
+class CC_EXPORT OverlayCandidate {
+ public:
   enum OverlayTransform {
+    INVALID,
     NONE,
     FLIP_HORIZONTAL,
     FLIP_VERTICAL,
@@ -24,6 +27,12 @@
     ROTATE_270,
   };
 
+  static OverlayTransform GetOverlayTransform(
+      const gfx::Transform& quad_transform,
+      bool flipped);
+  static gfx::Rect GetOverlayRect(const gfx::Transform& quad_transform,
+                                  const gfx::Rect& rect);
+
   OverlayCandidate();
   ~OverlayCandidate();
 
@@ -35,12 +44,19 @@
   gfx::Rect display_rect;
   // Crop within the buffer to be placed inside |display_rect|.
   gfx::RectF uv_rect;
+  // Texture resource to present in an overlay.
+  unsigned resource_id;
+  // Stacking order of the overlay plane relative to the main surface,
+  // which is 0. Signed to allow for "underlays".
+  int plane_z_order;
 
   // To be modified by the implementer if this candidate can go into
   // an overlay.
   bool overlay_handled;
 };
 
+typedef std::vector<OverlayCandidate> OverlayCandidateList;
+
 }  // namespace cc
 
 #endif  // CC_OUTPUT_OVERLAY_CANDIDATE_H_
diff --git a/cc/output/overlay_candidate_validator.h b/cc/output/overlay_candidate_validator.h
index 026f4f3..fb528da 100644
--- a/cc/output/overlay_candidate_validator.h
+++ b/cc/output/overlay_candidate_validator.h
@@ -19,8 +19,6 @@
 // configurations for a particular output device.
 class CC_EXPORT OverlayCandidateValidator {
  public:
-  typedef std::vector<OverlayCandidate> OverlayCandidateList;
-
   // A list of possible overlay candidates is presented to this function.
   // The expected result is that those candidates that can be in a separate
   // plane are marked with |overlay_handled| set to true, otherwise they are
diff --git a/cc/output/overlay_processor.cc b/cc/output/overlay_processor.cc
index afdb966..c13a6cf 100644
--- a/cc/output/overlay_processor.cc
+++ b/cc/output/overlay_processor.cc
@@ -19,7 +19,9 @@
 
 void OverlayProcessor::Initialize() {
   DCHECK(surface_);
-  DCHECK(resource_provider_);
+  if (!resource_provider_)
+    return;
+
   OverlayCandidateValidator* candidates =
       surface_->overlay_candidate_validator();
   if (candidates) {
@@ -31,10 +33,11 @@
 OverlayProcessor::~OverlayProcessor() {}
 
 void OverlayProcessor::ProcessForOverlays(
-    RenderPassList* render_passes_in_draw_order) {
+    RenderPassList* render_passes_in_draw_order,
+    OverlayCandidateList* candidate_list) {
   for (StrategyList::iterator it = strategies_.begin(); it != strategies_.end();
        ++it) {
-    if ((*it)->Attempt(render_passes_in_draw_order))
+    if ((*it)->Attempt(render_passes_in_draw_order, candidate_list))
       return;
   }
 }
diff --git a/cc/output/overlay_processor.h b/cc/output/overlay_processor.h
index 41a1f4d..e50972e 100644
--- a/cc/output/overlay_processor.h
+++ b/cc/output/overlay_processor.h
@@ -8,6 +8,7 @@
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "cc/base/cc_export.h"
+#include "cc/output/overlay_candidate.h"
 #include "cc/quads/render_pass.h"
 
 namespace cc {
@@ -23,7 +24,8 @@
     // current set of render passes. Returns true if the strategy was successful
     // and adds any additional passes necessary to represent overlays to
     // |render_passes_in_draw_order|.
-    virtual bool Attempt(RenderPassList* render_passes_in_draw_order) = 0;
+    virtual bool Attempt(RenderPassList* render_passes_in_draw_order,
+                         OverlayCandidateList* candidates) = 0;
   };
   typedef ScopedPtrVector<Strategy> StrategyList;
 
@@ -32,7 +34,8 @@
   // Virtual to allow testing different strategies.
   virtual void Initialize();
 
-  void ProcessForOverlays(RenderPassList* render_passes_in_draw_order);
+  void ProcessForOverlays(RenderPassList* render_passes_in_draw_order,
+                          OverlayCandidateList* candidate_list);
 
  protected:
   StrategyList strategies_;
diff --git a/cc/output/overlay_strategy_single_on_top.cc b/cc/output/overlay_strategy_single_on_top.cc
index 4c20641..d9ac36c 100644
--- a/cc/output/overlay_strategy_single_on_top.cc
+++ b/cc/output/overlay_strategy_single_on_top.cc
@@ -19,7 +19,8 @@
       resource_provider_(resource_provider) {}
 
 bool OverlayStrategySingleOnTop::Attempt(
-    RenderPassList* render_passes_in_draw_order) {
+    RenderPassList* render_passes_in_draw_order,
+    OverlayCandidateList* candidate_list) {
   // Only attempt to handle very simple case for now.
   if (!capability_checker_)
     return false;
@@ -37,14 +38,17 @@
     return false;
 
   // Simple quads only.
-  if (!quad.quadTransform().IsIdentityOrTranslation() || quad.needs_blending ||
+  OverlayCandidate::OverlayTransform overlay_transform =
+      OverlayCandidate::GetOverlayTransform(quad.quadTransform(), quad.flipped);
+  if (overlay_transform == OverlayCandidate::INVALID ||
+      !quad.quadTransform().IsIdentityOrTranslation() || quad.needs_blending ||
       quad.shared_quad_state->opacity != 1.f ||
       quad.shared_quad_state->blend_mode != SkXfermode::kSrcOver_Mode ||
       quad.premultiplied_alpha || quad.background_color != SK_ColorTRANSPARENT)
     return false;
 
   // Add our primary surface.
-  OverlayCandidateValidator::OverlayCandidateList candidates;
+  OverlayCandidateList candidates;
   OverlayCandidate main_image;
   main_image.display_rect = root_render_pass->output_rect;
   main_image.format = RGBA_8888;
@@ -52,13 +56,13 @@
 
   // Add the overlay.
   OverlayCandidate candidate;
-  gfx::RectF float_rect(quad.rect);
-  quad.quadTransform().TransformRect(&float_rect);
-  candidate.transform =
-      quad.flipped ? OverlayCandidate::FLIP_VERTICAL : OverlayCandidate::NONE;
-  candidate.display_rect = gfx::ToNearestRect(float_rect);
+  candidate.transform = overlay_transform;
+  candidate.display_rect =
+      OverlayCandidate::GetOverlayRect(quad.quadTransform(), quad.rect);
   candidate.uv_rect = BoundingRect(quad.uv_top_left, quad.uv_bottom_right);
   candidate.format = RGBA_8888;
+  candidate.resource_id = quad.resource_id;
+  candidate.plane_z_order = 1;
   candidates.push_back(candidate);
 
   // Check for support.
@@ -66,16 +70,12 @@
 
   // If the candidate can be handled by an overlay, create a pass for it.
   if (candidates[1].overlay_handled) {
-    scoped_ptr<RenderPass> overlay_pass = RenderPass::Create();
-    overlay_pass->overlay_state = RenderPass::SIMPLE_OVERLAY;
-
     scoped_ptr<DrawQuad> overlay_quad = quad_list.take(quad_list.begin());
     quad_list.erase(quad_list.begin());
-    overlay_pass->quad_list.push_back(overlay_quad.Pass());
-    render_passes_in_draw_order->insert(render_passes_in_draw_order->begin(),
-                                        overlay_pass.Pass());
+    candidate_list->swap(candidates);
+    return true;
   }
-  return candidates[1].overlay_handled;
+  return false;
 }
 
 }  // namespace cc
diff --git a/cc/output/overlay_strategy_single_on_top.h b/cc/output/overlay_strategy_single_on_top.h
index 99005fd..d984d3d 100644
--- a/cc/output/overlay_strategy_single_on_top.h
+++ b/cc/output/overlay_strategy_single_on_top.h
@@ -8,6 +8,7 @@
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
 #include "cc/base/cc_export.h"
+#include "cc/output/overlay_candidate.h"
 #include "cc/output/overlay_processor.h"
 #include "cc/quads/render_pass.h"
 
@@ -18,7 +19,8 @@
  public:
   OverlayStrategySingleOnTop(OverlayCandidateValidator* capability_checker,
                              ResourceProvider* resource_provider);
-  virtual bool Attempt(RenderPassList* render_passes_in_draw_order) OVERRIDE;
+  virtual bool Attempt(RenderPassList* render_passes_in_draw_order,
+                       OverlayCandidateList* candidate_list) OVERRIDE;
 
  private:
   OverlayCandidateValidator* capability_checker_;
diff --git a/cc/output/overlay_unittest.cc b/cc/output/overlay_unittest.cc
index ab22cb4..c8f069c 100644
--- a/cc/output/overlay_unittest.cc
+++ b/cc/output/overlay_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "cc/base/scoped_ptr_vector.h"
+#include "cc/output/gl_renderer.h"
 #include "cc/output/output_surface.h"
 #include "cc/output/output_surface_client.h"
 #include "cc/output/overlay_candidate_validator.h"
@@ -16,8 +17,12 @@
 #include "cc/test/fake_output_surface_client.h"
 #include "cc/test/geometry_test_utils.h"
 #include "cc/test/test_context_provider.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using testing::_;
+using testing::Mock;
+
 namespace cc {
 namespace {
 
@@ -103,8 +108,7 @@
                output_rect,
                output_rect,
                gfx::Transform(),
-               has_transparent_background,
-               RenderPass::NO_OVERLAY);
+               has_transparent_background);
 
   scoped_ptr<SharedQuadState> shared_state = SharedQuadState::Create();
   shared_state->opacity = 1.f;
@@ -112,9 +116,8 @@
   return pass.Pass();
 }
 
-scoped_ptr<TextureDrawQuad> CreateCandidateQuad(
-    ResourceProvider* resource_provider,
-    const SharedQuadState* shared_quad_state) {
+ResourceProvider::ResourceId CreateResource(
+    ResourceProvider* resource_provider) {
   unsigned sync_point = 0;
   TextureMailbox mailbox =
       TextureMailbox(gpu::Mailbox::Generate(), GL_TEXTURE_2D, sync_point);
@@ -122,9 +125,14 @@
   scoped_ptr<SingleReleaseCallback> release_callback =
       SingleReleaseCallback::Create(base::Bind(&MailboxReleased));
 
-  ResourceProvider::ResourceId resource_id =
-      resource_provider->CreateResourceFromTextureMailbox(
-          mailbox, release_callback.Pass());
+  return resource_provider->CreateResourceFromTextureMailbox(
+      mailbox, release_callback.Pass());
+}
+
+scoped_ptr<TextureDrawQuad> CreateCandidateQuad(
+    ResourceProvider* resource_provider,
+    const SharedQuadState* shared_quad_state) {
+  ResourceProvider::ResourceId resource_id = CreateResource(resource_provider);
   bool premultiplied_alpha = false;
   bool flipped = false;
   float vertex_opacity[4] = {1.0f, 1.0f, 1.0f, 1.0f};
@@ -169,7 +177,6 @@
     EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect);
     EXPECT_EQ(expected->has_transparent_background,
               actual->has_transparent_background);
-    EXPECT_EQ(expected->overlay_state, actual->overlay_state);
 
     EXPECT_EQ(expected->shared_quad_state_list.size(),
               actual->shared_quad_state_list.size());
@@ -252,22 +259,24 @@
   pass_list.push_back(pass.Pass());
 
   // Check for potential candidates.
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
 
-  // This should have one more pass with an overlay.
-  ASSERT_EQ(2U, pass_list.size());
+  ASSERT_EQ(1U, pass_list.size());
+  ASSERT_EQ(2U, candidate_list.size());
 
-  RenderPass* overlay_pass = pass_list.front();
-  EXPECT_EQ(RenderPass::SIMPLE_OVERLAY, overlay_pass->overlay_state);
   RenderPass* main_pass = pass_list.back();
-  EXPECT_EQ(RenderPass::NO_OVERLAY, main_pass->overlay_state);
+  // Check that the quad is gone.
+  EXPECT_EQ(2U, main_pass->quad_list.size());
+  const QuadList& quad_list = main_pass->quad_list;
+  for (QuadList::ConstBackToFrontIterator it = quad_list.BackToFrontBegin();
+       it != quad_list.BackToFrontEnd();
+       ++it) {
+    EXPECT_NE(DrawQuad::TEXTURE_CONTENT, (*it)->material);
+  }
 
-  // Check that the quad is what we expect it to be.
-  EXPECT_EQ(1U, overlay_pass->quad_list.size());
-  const DrawQuad* overlay_quad = overlay_pass->quad_list.front();
-  EXPECT_EQ(DrawQuad::TEXTURE_CONTENT, overlay_quad->material);
-  EXPECT_EQ(original_quad->resource_id,
-            TextureDrawQuad::MaterialCast(overlay_quad)->resource_id);
+  // Check that the right resource id got extracted.
+  EXPECT_EQ(original_quad->resource_id, candidate_list.back().resource_id);
 }
 
 TEST_F(SingleOverlayOnTopTest, NoCandidates) {
@@ -283,7 +292,9 @@
   RenderPassList original_pass_list;
   RenderPass::CopyAll(pass_list, &original_pass_list);
 
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  EXPECT_EQ(0U, candidate_list.size());
   // There should be nothing new here.
   CompareRenderPassLists(pass_list, original_pass_list);
 }
@@ -306,7 +317,9 @@
   RenderPassList original_pass_list;
   RenderPass::CopyAll(pass_list, &original_pass_list);
 
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  EXPECT_EQ(0U, candidate_list.size());
   // There should be nothing new here.
   CompareRenderPassLists(pass_list, original_pass_list);
 }
@@ -330,11 +343,16 @@
 
   pass_list.push_back(pass.Pass());
 
-  // Check for potential candidates.
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  RenderPassList original_pass_list;
+  RenderPass::CopyAll(pass_list, &original_pass_list);
 
-  // This should have one more pass with an overlay.
-  ASSERT_EQ(3U, pass_list.size());
+  // Check for potential candidates.
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  EXPECT_EQ(2U, candidate_list.size());
+
+  // This should be the same.
+  ASSERT_EQ(2U, pass_list.size());
 }
 
 TEST_F(SingleOverlayOnTopTest, RejectPremultipliedAlpha) {
@@ -346,9 +364,10 @@
   pass->quad_list.push_back(quad.PassAs<DrawQuad>());
   RenderPassList pass_list;
   pass_list.push_back(pass.Pass());
-  overlay_processor_->ProcessForOverlays(&pass_list);
-  ASSERT_EQ(1U, pass_list.size());
-  EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
+  EXPECT_EQ(1U, pass_list.size());
+  EXPECT_EQ(0U, candidate_list.size());
 }
 
 TEST_F(SingleOverlayOnTopTest, RejectBlending) {
@@ -360,9 +379,10 @@
   pass->quad_list.push_back(quad.PassAs<DrawQuad>());
   RenderPassList pass_list;
   pass_list.push_back(pass.Pass());
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
   ASSERT_EQ(1U, pass_list.size());
-  EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+  EXPECT_EQ(0U, candidate_list.size());
 }
 
 TEST_F(SingleOverlayOnTopTest, RejectBackgroundColor) {
@@ -374,9 +394,10 @@
   pass->quad_list.push_back(quad.PassAs<DrawQuad>());
   RenderPassList pass_list;
   pass_list.push_back(pass.Pass());
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
   ASSERT_EQ(1U, pass_list.size());
-  EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+  EXPECT_EQ(0U, candidate_list.size());
 }
 
 TEST_F(SingleOverlayOnTopTest, RejectBlendMode) {
@@ -388,9 +409,10 @@
   pass->quad_list.push_back(quad.PassAs<DrawQuad>());
   RenderPassList pass_list;
   pass_list.push_back(pass.Pass());
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
   ASSERT_EQ(1U, pass_list.size());
-  EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+  EXPECT_EQ(0U, candidate_list.size());
 }
 
 TEST_F(SingleOverlayOnTopTest, RejectOpacity) {
@@ -402,9 +424,10 @@
   pass->quad_list.push_back(quad.PassAs<DrawQuad>());
   RenderPassList pass_list;
   pass_list.push_back(pass.Pass());
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
   ASSERT_EQ(1U, pass_list.size());
-  EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+  EXPECT_EQ(0U, candidate_list.size());
 }
 
 TEST_F(SingleOverlayOnTopTest, RejectTransform) {
@@ -417,9 +440,283 @@
   pass->quad_list.push_back(quad.PassAs<DrawQuad>());
   RenderPassList pass_list;
   pass_list.push_back(pass.Pass());
-  overlay_processor_->ProcessForOverlays(&pass_list);
+  OverlayCandidateList candidate_list;
+  overlay_processor_->ProcessForOverlays(&pass_list, &candidate_list);
   ASSERT_EQ(1U, pass_list.size());
-  EXPECT_EQ(RenderPass::NO_OVERLAY, pass_list.back()->overlay_state);
+  EXPECT_EQ(0U, candidate_list.size());
+}
+
+class OverlayInfoRendererGL : public GLRenderer {
+ public:
+  OverlayInfoRendererGL(RendererClient* client,
+                        const LayerTreeSettings* settings,
+                        OutputSurface* output_surface,
+                        ResourceProvider* resource_provider)
+      : GLRenderer(client,
+                   settings,
+                   output_surface,
+                   resource_provider,
+                   NULL,
+                   0),
+        expect_overlays_(false) {}
+
+  MOCK_METHOD2(DoDrawQuad, void(DrawingFrame* frame, const DrawQuad* quad));
+
+  virtual void FinishDrawingFrame(DrawingFrame* frame) OVERRIDE {
+    GLRenderer::FinishDrawingFrame(frame);
+
+    if (!expect_overlays_) {
+      EXPECT_EQ(0U, frame->overlay_list.size());
+      return;
+    }
+
+    ASSERT_EQ(2U, frame->overlay_list.size());
+    EXPECT_NE(0U, frame->overlay_list.back().resource_id);
+  }
+
+  void set_expect_overlays(bool expect_overlays) {
+    expect_overlays_ = expect_overlays;
+  }
+
+ private:
+  bool expect_overlays_;
+};
+
+class FakeRendererClient : public RendererClient {
+ public:
+  // RendererClient methods.
+  virtual void SetFullRootLayerDamage() OVERRIDE {}
+};
+
+class MockOverlayScheduler {
+ public:
+  MOCK_METHOD5(Schedule,
+               void(int plane_z_order,
+                    unsigned plane_transform,
+                    unsigned overlay_texture_id,
+                    const gfx::Rect& display_bounds,
+                    const gfx::RectF& uv_rect));
+};
+
+class GLRendererWithOverlaysTest : public testing::Test {
+ protected:
+  GLRendererWithOverlaysTest() {
+    provider_ = TestContextProvider::Create();
+    output_surface_.reset(new OverlayOutputSurface(provider_));
+    CHECK(output_surface_->BindToClient(&output_surface_client_));
+    resource_provider_ =
+        ResourceProvider::Create(output_surface_.get(), NULL, 0, false, 1);
+
+    provider_->support()->SetScheduleOverlayPlaneCallback(base::Bind(
+        &MockOverlayScheduler::Schedule, base::Unretained(&scheduler_)));
+  }
+
+  void Init(bool use_validator) {
+    if (use_validator)
+      output_surface_->InitWithSingleOverlayValidator();
+
+    renderer_ =
+        make_scoped_ptr(new OverlayInfoRendererGL(&renderer_client_,
+                                                  &settings_,
+                                                  output_surface_.get(),
+                                                  resource_provider_.get()));
+  }
+
+  void SwapBuffers() { renderer_->SwapBuffers(CompositorFrameMetadata()); }
+
+  LayerTreeSettings settings_;
+  FakeOutputSurfaceClient output_surface_client_;
+  scoped_ptr<OverlayOutputSurface> output_surface_;
+  FakeRendererClient renderer_client_;
+  scoped_ptr<ResourceProvider> resource_provider_;
+  scoped_ptr<OverlayInfoRendererGL> renderer_;
+  scoped_refptr<TestContextProvider> provider_;
+  MockOverlayScheduler scheduler_;
+};
+
+TEST_F(GLRendererWithOverlaysTest, OverlayQuadNotDrawn) {
+  bool use_validator = true;
+  Init(use_validator);
+  renderer_->set_expect_overlays(true);
+  gfx::Rect viewport_rect(16, 16);
+
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+  pass->quad_list.push_back(
+      CreateCandidateQuad(resource_provider_.get(),
+                          pass->shared_quad_state_list.back())
+          .PassAs<DrawQuad>());
+
+  pass->quad_list.push_back(CreateCheckeredQuad(
+      resource_provider_.get(), pass->shared_quad_state_list.back()));
+  pass->quad_list.push_back(CreateCheckeredQuad(
+      resource_provider_.get(), pass->shared_quad_state_list.back()));
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // Candidate pass was taken out and extra skipped pass added,
+  // so only draw 2 quads.
+  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(2);
+  EXPECT_CALL(scheduler_,
+              Schedule(1,
+                       OverlayCandidate::NONE,
+                       _,
+                       kOverlayRect,
+                       BoundingRect(kUVTopLeft, kUVBottomRight))).Times(1);
+  renderer_->DrawFrame(
+      &pass_list, NULL, 1.f, viewport_rect, viewport_rect, false);
+
+  SwapBuffers();
+
+  Mock::VerifyAndClearExpectations(renderer_.get());
+  Mock::VerifyAndClearExpectations(&scheduler_);
+}
+
+TEST_F(GLRendererWithOverlaysTest, OccludedQuadDrawn) {
+  bool use_validator = true;
+  Init(use_validator);
+  renderer_->set_expect_overlays(false);
+  gfx::Rect viewport_rect(16, 16);
+
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+  pass->quad_list.push_back(CreateCheckeredQuad(
+      resource_provider_.get(), pass->shared_quad_state_list.back()));
+  pass->quad_list.push_back(CreateCheckeredQuad(
+      resource_provider_.get(), pass->shared_quad_state_list.back()));
+
+  pass->quad_list.push_back(
+      CreateCandidateQuad(resource_provider_.get(),
+                          pass->shared_quad_state_list.back())
+          .PassAs<DrawQuad>());
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // 3 quads in the pass, all should draw.
+  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+  renderer_->DrawFrame(
+      &pass_list, NULL, 1.f, viewport_rect, viewport_rect, false);
+
+  SwapBuffers();
+
+  Mock::VerifyAndClearExpectations(renderer_.get());
+  Mock::VerifyAndClearExpectations(&scheduler_);
+}
+
+TEST_F(GLRendererWithOverlaysTest, NoValidatorNoOverlay) {
+  bool use_validator = false;
+  Init(use_validator);
+  renderer_->set_expect_overlays(false);
+  gfx::Rect viewport_rect(16, 16);
+
+  scoped_ptr<RenderPass> pass = CreateRenderPass();
+
+  pass->quad_list.push_back(
+      CreateCandidateQuad(resource_provider_.get(),
+                          pass->shared_quad_state_list.back())
+          .PassAs<DrawQuad>());
+
+  pass->quad_list.push_back(CreateCheckeredQuad(
+      resource_provider_.get(), pass->shared_quad_state_list.back()));
+  pass->quad_list.push_back(CreateCheckeredQuad(
+      resource_provider_.get(), pass->shared_quad_state_list.back()));
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  // Should see no overlays.
+  EXPECT_CALL(*renderer_, DoDrawQuad(_, _)).Times(3);
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+  renderer_->DrawFrame(
+      &pass_list, NULL, 1.f, viewport_rect, viewport_rect, false);
+
+  SwapBuffers();
+
+  Mock::VerifyAndClearExpectations(renderer_.get());
+  Mock::VerifyAndClearExpectations(&scheduler_);
+}
+
+TEST_F(GLRendererWithOverlaysTest, ResourcesExportedAndReturned) {
+  bool use_validator = true;
+  Init(use_validator);
+  renderer_->set_expect_overlays(true);
+
+  ResourceProvider::ResourceId resource1 =
+      CreateResource(resource_provider_.get());
+  ResourceProvider::ResourceId resource2 =
+      CreateResource(resource_provider_.get());
+
+  DirectRenderer::DrawingFrame frame1;
+  frame1.overlay_list.resize(2);
+  OverlayCandidate& overlay1 = frame1.overlay_list.back();
+  overlay1.resource_id = resource1;
+  overlay1.plane_z_order = 1;
+
+  DirectRenderer::DrawingFrame frame2;
+  frame2.overlay_list.resize(2);
+  OverlayCandidate& overlay2 = frame2.overlay_list.back();
+  overlay2.resource_id = resource2;
+  overlay2.plane_z_order = 1;
+
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+  renderer_->FinishDrawingFrame(&frame1);
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+  SwapBuffers();
+  Mock::VerifyAndClearExpectations(&scheduler_);
+
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+  renderer_->FinishDrawingFrame(&frame2);
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+  SwapBuffers();
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+  Mock::VerifyAndClearExpectations(&scheduler_);
+
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+  renderer_->FinishDrawingFrame(&frame1);
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource2));
+  SwapBuffers();
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+  Mock::VerifyAndClearExpectations(&scheduler_);
+
+  // No overlays, release the resource.
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+  DirectRenderer::DrawingFrame frame3;
+  renderer_->set_expect_overlays(false);
+  renderer_->FinishDrawingFrame(&frame3);
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource2));
+  SwapBuffers();
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+  Mock::VerifyAndClearExpectations(&scheduler_);
+
+  // Use the same buffer twice.
+  renderer_->set_expect_overlays(true);
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+  renderer_->FinishDrawingFrame(&frame1);
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  SwapBuffers();
+  Mock::VerifyAndClearExpectations(&scheduler_);
+
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(1);
+  renderer_->FinishDrawingFrame(&frame1);
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  SwapBuffers();
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  Mock::VerifyAndClearExpectations(&scheduler_);
+
+  EXPECT_CALL(scheduler_, Schedule(_, _, _, _, _)).Times(0);
+  renderer_->set_expect_overlays(false);
+  renderer_->FinishDrawingFrame(&frame3);
+  EXPECT_TRUE(resource_provider_->InUseByConsumer(resource1));
+  SwapBuffers();
+  EXPECT_FALSE(resource_provider_->InUseByConsumer(resource1));
+  Mock::VerifyAndClearExpectations(&scheduler_);
 }
 
 }  // namespace
diff --git a/cc/output/renderer_pixeltest.cc b/cc/output/renderer_pixeltest.cc
index 1165f9a..585a94c 100644
--- a/cc/output/renderer_pixeltest.cc
+++ b/cc/output/renderer_pixeltest.cc
@@ -403,28 +403,30 @@
 class VideoGLRendererPixelTest : public GLRendererPixelTest {
  protected:
   scoped_ptr<YUVVideoDrawQuad> CreateTestYUVVideoDrawQuad(
-      SharedQuadState* shared_state, bool with_alpha, bool is_transparent) {
-    gfx::Rect rect(this->device_viewport_size_);
-    gfx::Rect opaque_rect(0, 0, 0, 0);
+      SharedQuadState* shared_state,
+      bool with_alpha,
+      bool is_transparent,
+      const gfx::RectF& tex_coord_rect) {
+    const gfx::Rect rect(this->device_viewport_size_);
+    const gfx::Rect uv_rect(
+        0, 0, (rect.width() + 1) / 2, (rect.height() + 1) / 2);
+    const gfx::Rect opaque_rect(0, 0, 0, 0);
 
     ResourceProvider::ResourceId y_resource =
-        resource_provider_->CreateResource(
-            this->device_viewport_size_,
-            GL_CLAMP_TO_EDGE,
-            ResourceProvider::TextureUsageAny,
-            LUMINANCE_8);
+        resource_provider_->CreateResource(rect.size(),
+                                           GL_CLAMP_TO_EDGE,
+                                           ResourceProvider::TextureUsageAny,
+                                           LUMINANCE_8);
     ResourceProvider::ResourceId u_resource =
-        resource_provider_->CreateResource(
-            this->device_viewport_size_,
-            GL_CLAMP_TO_EDGE,
-            ResourceProvider::TextureUsageAny,
-            LUMINANCE_8);
+        resource_provider_->CreateResource(uv_rect.size(),
+                                           GL_CLAMP_TO_EDGE,
+                                           ResourceProvider::TextureUsageAny,
+                                           LUMINANCE_8);
     ResourceProvider::ResourceId v_resource =
-        resource_provider_->CreateResource(
-            this->device_viewport_size_,
-            GL_CLAMP_TO_EDGE,
-            ResourceProvider::TextureUsageAny,
-            LUMINANCE_8);
+        resource_provider_->CreateResource(uv_rect.size(),
+                                           GL_CLAMP_TO_EDGE,
+                                           ResourceProvider::TextureUsageAny,
+                                           LUMINANCE_8);
     ResourceProvider::ResourceId a_resource = 0;
     if (with_alpha) {
       a_resource = resource_provider_->CreateResource(
@@ -434,10 +436,7 @@
                        LUMINANCE_8);
     }
 
-    int w = this->device_viewport_size_.width();
-    int h = this->device_viewport_size_.height();
-    const int y_plane_size = w * h;
-    gfx::Rect uv_rect((w + 1) / 2, (h + 1) / 2);
+    const int y_plane_size = rect.size().GetArea();
     const int uv_plane_size = uv_rect.size().GetArea();
     scoped_ptr<uint8_t[]> y_plane(new uint8_t[y_plane_size]);
     scoped_ptr<uint8_t[]> u_plane(new uint8_t[uv_plane_size]);
@@ -445,19 +444,26 @@
     scoped_ptr<uint8_t[]> a_plane;
     if (with_alpha)
       a_plane.reset(new uint8_t[y_plane_size]);
-    // YUV values representing Green.
-    memset(y_plane.get(), 149, y_plane_size);
-    memset(u_plane.get(), 43, uv_plane_size);
-    memset(v_plane.get(), 21, uv_plane_size);
+    // YUV values representing a striped pattern, for validating texture
+    // coordinates for sampling.
+    uint8_t y_value = 0;
+    uint8_t u_value = 0;
+    uint8_t v_value = 0;
+    for (int i = 0; i < y_plane_size; ++i)
+      y_plane.get()[i] = (y_value += 1);
+    for (int i = 0; i < uv_plane_size; ++i) {
+      u_plane.get()[i] = (u_value += 3);
+      v_plane.get()[i] = (v_value += 5);
+    }
     if (with_alpha)
       memset(a_plane.get(), is_transparent ? 0 : 128, y_plane_size);
 
-    resource_provider_->SetPixels(y_resource, y_plane.get(), rect, rect,
-                                  gfx::Vector2d());
-    resource_provider_->SetPixels(u_resource, u_plane.get(), uv_rect, uv_rect,
-                                  gfx::Vector2d());
-    resource_provider_->SetPixels(v_resource, v_plane.get(), uv_rect, uv_rect,
-                                  gfx::Vector2d());
+    resource_provider_->SetPixels(
+        y_resource, y_plane.get(), rect, rect, gfx::Vector2d());
+    resource_provider_->SetPixels(
+        u_resource, u_plane.get(), uv_rect, uv_rect, gfx::Vector2d());
+    resource_provider_->SetPixels(
+        v_resource, v_plane.get(), uv_rect, uv_rect, gfx::Vector2d());
     if (with_alpha) {
       resource_provider_->SetPixels(a_resource, a_plane.get(), rect, rect,
                                     gfx::Vector2d());
@@ -468,7 +474,7 @@
                      rect,
                      opaque_rect,
                      rect,
-                     gfx::Size(),
+                     tex_coord_rect,
                      y_resource,
                      u_resource,
                      v_resource,
@@ -486,8 +492,32 @@
   scoped_ptr<SharedQuadState> shared_state =
       CreateTestSharedQuadState(gfx::Transform(), rect);
 
-  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
-      CreateTestYUVVideoDrawQuad(shared_state.get(), false, false);
+  scoped_ptr<YUVVideoDrawQuad> yuv_quad = CreateTestYUVVideoDrawQuad(
+      shared_state.get(), false, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f));
+
+  pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
+
+  RenderPassList pass_list;
+  pass_list.push_back(pass.Pass());
+
+  EXPECT_TRUE(
+      this->RunPixelTest(&pass_list,
+                         PixelTest::NoOffscreenContext,
+                         base::FilePath(FILE_PATH_LITERAL("yuv_stripes.png")),
+                         FuzzyPixelOffByOneComparator(true)));
+}
+
+TEST_F(VideoGLRendererPixelTest, OffsetYUVRect) {
+  gfx::Rect rect(this->device_viewport_size_);
+
+  RenderPass::Id id(1, 1);
+  scoped_ptr<RenderPass> pass = CreateTestRootRenderPass(id, rect);
+
+  scoped_ptr<SharedQuadState> shared_state =
+      CreateTestSharedQuadState(gfx::Transform(), rect);
+
+  scoped_ptr<YUVVideoDrawQuad> yuv_quad = CreateTestYUVVideoDrawQuad(
+      shared_state.get(), false, false, gfx::RectF(0.125f, 0.25f, 0.75f, 0.5f));
 
   pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
 
@@ -497,8 +527,8 @@
   EXPECT_TRUE(this->RunPixelTest(
       &pass_list,
       PixelTest::NoOffscreenContext,
-      base::FilePath(FILE_PATH_LITERAL("green.png")),
-      ExactPixelComparator(true)));
+      base::FilePath(FILE_PATH_LITERAL("yuv_stripes_offset.png")),
+      FuzzyPixelOffByOneComparator(true)));
 }
 
 TEST_F(VideoGLRendererPixelTest, SimpleYUVARect) {
@@ -510,8 +540,8 @@
   scoped_ptr<SharedQuadState> shared_state =
       CreateTestSharedQuadState(gfx::Transform(), rect);
 
-  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
-      CreateTestYUVVideoDrawQuad(shared_state.get(), true, false);
+  scoped_ptr<YUVVideoDrawQuad> yuv_quad = CreateTestYUVVideoDrawQuad(
+      shared_state.get(), true, false, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f));
 
   pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
 
@@ -526,8 +556,8 @@
   EXPECT_TRUE(this->RunPixelTest(
       &pass_list,
       PixelTest::NoOffscreenContext,
-      base::FilePath(FILE_PATH_LITERAL("green_alpha.png")),
-      ExactPixelComparator(true)));
+      base::FilePath(FILE_PATH_LITERAL("yuv_stripes_alpha.png")),
+      FuzzyPixelOffByOneComparator(true)));
 }
 
 TEST_F(VideoGLRendererPixelTest, FullyTransparentYUVARect) {
@@ -539,8 +569,8 @@
   scoped_ptr<SharedQuadState> shared_state =
       CreateTestSharedQuadState(gfx::Transform(), rect);
 
-  scoped_ptr<YUVVideoDrawQuad> yuv_quad =
-      CreateTestYUVVideoDrawQuad(shared_state.get(), true, true);
+  scoped_ptr<YUVVideoDrawQuad> yuv_quad = CreateTestYUVVideoDrawQuad(
+      shared_state.get(), true, true, gfx::RectF(0.0f, 0.0f, 1.0f, 1.0f));
 
   pass->quad_list.push_back(yuv_quad.PassAs<DrawQuad>());
 
@@ -1805,8 +1835,7 @@
       CreateTestRenderPass(id, viewport, transform_to_root);
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
-  bitmap.allocPixels();
+  bitmap.allocN32Pixels(2, 2);
   {
     SkAutoLockPixels lock(bitmap);
     SkCanvas canvas(bitmap);
diff --git a/cc/output/shader.cc b/cc/output/shader.cc
index 7f1bac7..96b745c 100644
--- a/cc/output/shader.cc
+++ b/cc/output/shader.cc
@@ -185,16 +185,16 @@
   );  // NOLINT(whitespace/parens)
 }
 
-VertexShaderPosTexYUVStretch::VertexShaderPosTexYUVStretch()
-    : matrix_location_(-1),
-      tex_scale_location_(-1) {}
+VertexShaderPosTexYUVStretchOffset::VertexShaderPosTexYUVStretchOffset()
+    : matrix_location_(-1), tex_scale_location_(-1), tex_offset_location_(-1) {}
 
-void VertexShaderPosTexYUVStretch::Init(GLES2Interface* context,
-                                        unsigned program,
-                                        int* base_uniform_index) {
+void VertexShaderPosTexYUVStretchOffset::Init(GLES2Interface* context,
+                                              unsigned program,
+                                              int* base_uniform_index) {
   static const char* uniforms[] = {
     "matrix",
     "texScale",
+    "texOffset",
   };
   int locations[arraysize(uniforms)];
 
@@ -206,9 +206,10 @@
                              base_uniform_index);
   matrix_location_ = locations[0];
   tex_scale_location_ = locations[1];
+  tex_offset_location_ = locations[2];
 }
 
-std::string VertexShaderPosTexYUVStretch::GetShaderString() const {
+std::string VertexShaderPosTexYUVStretchOffset::GetShaderString() const {
   return VERTEX_SHADER(
     precision mediump float;
     attribute vec4 a_position;
@@ -216,9 +217,10 @@
     uniform mat4 matrix;
     varying TexCoordPrecision vec2 v_texCoord;
     uniform TexCoordPrecision vec2 texScale;
+    uniform TexCoordPrecision vec2 texOffset;
     void main() {
         gl_Position = matrix * a_position;
-        v_texCoord = a_texCoord * texScale;
+        v_texCoord = a_texCoord * texScale + texOffset;
     }
   );  // NOLINT(whitespace/parens)
 }
diff --git a/cc/output/shader.h b/cc/output/shader.h
index 36430cc..83c41ee 100644
--- a/cc/output/shader.h
+++ b/cc/output/shader.h
@@ -72,9 +72,9 @@
   DISALLOW_COPY_AND_ASSIGN(VertexShaderPosTex);
 };
 
-class VertexShaderPosTexYUVStretch {
+class VertexShaderPosTexYUVStretchOffset {
  public:
-  VertexShaderPosTexYUVStretch();
+  VertexShaderPosTexYUVStretchOffset();
 
   void Init(gpu::gles2::GLES2Interface* context,
             unsigned program,
@@ -83,12 +83,14 @@
 
   int matrix_location() const { return matrix_location_; }
   int tex_scale_location() const { return tex_scale_location_; }
+  int tex_offset_location() const { return tex_offset_location_; }
 
  private:
   int matrix_location_;
   int tex_scale_location_;
+  int tex_offset_location_;
 
-  DISALLOW_COPY_AND_ASSIGN(VertexShaderPosTexYUVStretch);
+  DISALLOW_COPY_AND_ASSIGN(VertexShaderPosTexYUVStretchOffset);
 };
 
 class VertexShaderPos {
diff --git a/cc/output/software_output_device.cc b/cc/output/software_output_device.cc
index d066f4c..428ba9b 100644
--- a/cc/output/software_output_device.cc
+++ b/cc/output/software_output_device.cc
@@ -6,7 +6,6 @@
 
 #include "base/logging.h"
 #include "cc/output/software_frame_data.h"
-#include "third_party/skia/include/core/SkBitmapDevice.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/vsync_provider.h"
@@ -21,14 +20,14 @@
   if (viewport_size_ == viewport_size)
     return;
 
+  SkImageInfo info = SkImageInfo::MakeN32(
+      viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType);
   viewport_size_ = viewport_size;
-  device_ = skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
-      viewport_size.width(), viewport_size.height(), true));
-  canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
+  canvas_ = skia::AdoptRef(SkCanvas::NewRaster(info));
 }
 
 SkCanvas* SoftwareOutputDevice::BeginPaint(const gfx::Rect& damage_rect) {
-  DCHECK(device_);
+  DCHECK(canvas_);
   damage_rect_ = damage_rect;
   return canvas_.get();
 }
@@ -41,11 +40,10 @@
   frame_data->handle = base::SharedMemory::NULLHandle();
 }
 
-void SoftwareOutputDevice::CopyToBitmap(
-    const gfx::Rect& rect, SkBitmap* output) {
-  DCHECK(device_);
-  const SkBitmap& bitmap = device_->accessBitmap(false);
-  bitmap.extractSubset(output, gfx::RectToSkIRect(rect));
+void SoftwareOutputDevice::CopyToPixels(const gfx::Rect& rect, void* pixels) {
+  DCHECK(canvas_);
+  SkImageInfo info = SkImageInfo::MakeN32Premul(rect.width(), rect.height());
+  canvas_->readPixels(info, pixels, info.minRowBytes(), rect.x(), rect.y());
 }
 
 void SoftwareOutputDevice::Scroll(const gfx::Vector2d& delta,
diff --git a/cc/output/software_output_device.h b/cc/output/software_output_device.h
index f03e964..e371654 100644
--- a/cc/output/software_output_device.h
+++ b/cc/output/software_output_device.h
@@ -50,8 +50,8 @@
   virtual void EndPaint(SoftwareFrameData* frame_data);
 
   // Copies pixels inside |rect| from the current software framebuffer to
-  // |output|. Fails if there is no current softwareframebuffer.
-  virtual void CopyToBitmap(const gfx::Rect& rect, SkBitmap* output);
+  // |pixels|. Fails if there is no current softwareframebuffer.
+  virtual void CopyToPixels(const gfx::Rect& rect, void* pixels);
 
   // Blit the pixel content of the SoftwareOutputDevice by |delta| with the
   // write clipped to |clip_rect|.
@@ -76,7 +76,6 @@
  protected:
   gfx::Size viewport_size_;
   gfx::Rect damage_rect_;
-  skia::RefPtr<SkBaseDevice> device_;
   skia::RefPtr<SkCanvas> canvas_;
   scoped_ptr<gfx::VSyncProvider> vsync_provider_;
 
diff --git a/cc/output/software_renderer.cc b/cc/output/software_renderer.cc
index 778755f..4f132a1 100644
--- a/cc/output/software_renderer.cc
+++ b/cc/output/software_renderer.cc
@@ -648,13 +648,9 @@
 void SoftwareRenderer::GetFramebufferPixels(void* pixels,
                                             const gfx::Rect& rect) {
   TRACE_EVENT0("cc", "SoftwareRenderer::GetFramebufferPixels");
-  SkBitmap subset_bitmap;
   gfx::Rect frame_rect(rect);
   frame_rect += current_viewport_rect_.OffsetFromOrigin();
-  output_device_->CopyToBitmap(frame_rect, &subset_bitmap);
-  subset_bitmap.copyPixelsTo(pixels,
-                             4 * frame_rect.width() * frame_rect.height(),
-                             4 * frame_rect.width());
+  output_device_->CopyToPixels(frame_rect, pixels);
 }
 
 void SoftwareRenderer::SetVisible(bool visible) {
diff --git a/cc/quads/draw_quad_unittest.cc b/cc/quads/draw_quad_unittest.cc
index 1918a51..2b491f4 100644
--- a/cc/quads/draw_quad_unittest.cc
+++ b/cc/quads/draw_quad_unittest.cc
@@ -589,7 +589,7 @@
 TEST(DrawQuadTest, CopyYUVVideoDrawQuad) {
   gfx::Rect opaque_rect(33, 47, 10, 12);
   gfx::Rect visible_rect(40, 50, 30, 20);
-  gfx::SizeF tex_scale(0.75f, 0.5f);
+  gfx::RectF tex_coord_rect(0.0f, 0.0f, 0.75f, 0.5f);
   ResourceProvider::ResourceId y_plane_resource_id = 45;
   ResourceProvider::ResourceId u_plane_resource_id = 532;
   ResourceProvider::ResourceId v_plane_resource_id = 4;
@@ -599,7 +599,7 @@
   CREATE_QUAD_7_NEW(YUVVideoDrawQuad,
                     opaque_rect,
                     visible_rect,
-                    tex_scale,
+                    tex_coord_rect,
                     y_plane_resource_id,
                     u_plane_resource_id,
                     v_plane_resource_id,
@@ -607,20 +607,20 @@
   EXPECT_EQ(DrawQuad::YUV_VIDEO_CONTENT, copy_quad->material);
   EXPECT_RECT_EQ(opaque_rect, copy_quad->opaque_rect);
   EXPECT_RECT_EQ(visible_rect, copy_quad->visible_rect);
-  EXPECT_EQ(tex_scale, copy_quad->tex_scale);
+  EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
   EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id);
   EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id);
   EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id);
   EXPECT_EQ(a_plane_resource_id, copy_quad->a_plane_resource_id);
 
   CREATE_QUAD_5_ALL(YUVVideoDrawQuad,
-                    tex_scale,
+                    tex_coord_rect,
                     y_plane_resource_id,
                     u_plane_resource_id,
                     v_plane_resource_id,
                     a_plane_resource_id);
   EXPECT_EQ(DrawQuad::YUV_VIDEO_CONTENT, copy_quad->material);
-  EXPECT_EQ(tex_scale, copy_quad->tex_scale);
+  EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
   EXPECT_EQ(y_plane_resource_id, copy_quad->y_plane_resource_id);
   EXPECT_EQ(u_plane_resource_id, copy_quad->u_plane_resource_id);
   EXPECT_EQ(v_plane_resource_id, copy_quad->v_plane_resource_id);
@@ -848,7 +848,7 @@
 TEST_F(DrawQuadIteratorTest, YUVVideoDrawQuad) {
   gfx::Rect opaque_rect(33, 47, 10, 12);
   gfx::Rect visible_rect(40, 50, 30, 20);
-  gfx::SizeF tex_scale(0.75f, 0.5f);
+  gfx::RectF tex_coord_rect(0.0f, 0.0f, 0.75f, 0.5f);
   ResourceProvider::ResourceId y_plane_resource_id = 45;
   ResourceProvider::ResourceId u_plane_resource_id = 532;
   ResourceProvider::ResourceId v_plane_resource_id = 4;
@@ -858,7 +858,7 @@
   CREATE_QUAD_7_NEW(YUVVideoDrawQuad,
                     opaque_rect,
                     visible_rect,
-                    tex_scale,
+                    tex_coord_rect,
                     y_plane_resource_id,
                     u_plane_resource_id,
                     v_plane_resource_id,
diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc
index 1eeefe4..82deccd 100644
--- a/cc/quads/render_pass.cc
+++ b/cc/quads/render_pass.cc
@@ -33,18 +33,13 @@
   return make_scoped_ptr(new RenderPass(num_layers));
 }
 
-RenderPass::RenderPass()
-    : id(Id(-1, -1)),
-      has_transparent_background(true),
-      overlay_state(NO_OVERLAY) {
+RenderPass::RenderPass() : id(Id(-1, -1)), has_transparent_background(true) {
   shared_quad_state_list.reserve(kDefaultNumSharedQuadStatesToReserve);
   quad_list.reserve(kDefaultNumQuadsToReserve);
 }
 
 RenderPass::RenderPass(size_t num_layers)
-    : id(Id(-1, -1)),
-      has_transparent_background(true),
-      overlay_state(NO_OVERLAY) {
+    : id(Id(-1, -1)), has_transparent_background(true) {
   // Each layer usually produces one shared quad state, so the number of layers
   // is a good hint for what to reserve here.
   shared_quad_state_list.reserve(num_layers);
@@ -63,8 +58,7 @@
                     output_rect,
                     damage_rect,
                     transform_to_root_target,
-                    has_transparent_background,
-                    overlay_state);
+                    has_transparent_background);
   return copy_pass.Pass();
 }
 
@@ -83,8 +77,7 @@
                       source->output_rect,
                       source->damage_rect,
                       source->transform_to_root_target,
-                      source->has_transparent_background,
-                      source->overlay_state);
+                      source->has_transparent_background);
     for (size_t i = 0; i < source->shared_quad_state_list.size(); ++i) {
       copy_pass->shared_quad_state_list.push_back(
           source->shared_quad_state_list[i]->Copy());
@@ -135,8 +128,7 @@
                         const gfx::Rect& output_rect,
                         const gfx::RectF& damage_rect,
                         const gfx::Transform& transform_to_root_target,
-                        bool has_transparent_background,
-                        OverlayState overlay_state) {
+                        bool has_transparent_background) {
   DCHECK_GT(id.layer_id, 0);
   DCHECK_GE(id.index, 0);
 
@@ -145,7 +137,6 @@
   this->damage_rect = damage_rect;
   this->transform_to_root_target = transform_to_root_target;
   this->has_transparent_background = has_transparent_background;
-  this->overlay_state = overlay_state;
 
   DCHECK(quad_list.empty());
   DCHECK(shared_quad_state_list.empty());
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 5cada2a..4285e53 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -62,11 +62,6 @@
     }
   };
 
-  // Specifies whether the pass is going into an overlay, needs to be rendered
-  // into a buffer before it can be presented to overlay hardware or a quad
-  // inside it is presented as is.
-  enum OverlayState { NO_OVERLAY, RENDER_AND_OVERLAY, SIMPLE_OVERLAY, };
-
   ~RenderPass();
 
   static scoped_ptr<RenderPass> Create();
@@ -89,8 +84,7 @@
               const gfx::Rect& output_rect,
               const gfx::RectF& damage_rect,
               const gfx::Transform& transform_to_root_target,
-              bool has_transparent_background,
-              OverlayState overlay_state);
+              bool has_transparent_background);
 
   scoped_ptr<base::Value> AsValue() const;
 
@@ -117,8 +111,6 @@
   QuadList quad_list;
   SharedQuadStateList shared_quad_state_list;
 
-  OverlayState overlay_state;
-
  protected:
   explicit RenderPass(size_t num_layers);
   RenderPass();
diff --git a/cc/quads/render_pass_unittest.cc b/cc/quads/render_pass_unittest.cc
index 1305741..fd58523 100644
--- a/cc/quads/render_pass_unittest.cc
+++ b/cc/quads/render_pass_unittest.cc
@@ -31,7 +31,6 @@
   gfx::RectF damage_rect;
   bool has_transparent_background;
   ScopedPtrVector<CopyOutputRequest> copy_callbacks;
-  RenderPass::OverlayState overlay_state;
 };
 
 static void CompareRenderPassLists(const RenderPassList& expected_list,
@@ -48,7 +47,6 @@
     EXPECT_RECT_EQ(expected->damage_rect, actual->damage_rect);
     EXPECT_EQ(expected->has_transparent_background,
               actual->has_transparent_background);
-    EXPECT_EQ(expected->overlay_state, actual->overlay_state);
 
     EXPECT_EQ(expected->shared_quad_state_list.size(),
               actual->shared_quad_state_list.size());
@@ -71,15 +69,13 @@
       gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
   gfx::Rect damage_rect(56, 123, 19, 43);
   bool has_transparent_background = true;
-  RenderPass::OverlayState overlay_state = RenderPass::SIMPLE_OVERLAY;
 
   scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
   pass->SetAll(id,
                output_rect,
                damage_rect,
                transform_to_root,
-               has_transparent_background,
-               overlay_state);
+               has_transparent_background);
   pass->copy_requests.push_back(CopyOutputRequest::CreateEmptyRequest());
 
   // Stick a quad in the pass, this should not get copied.
@@ -107,7 +103,6 @@
   EXPECT_EQ(pass->transform_to_root_target, copy->transform_to_root_target);
   EXPECT_RECT_EQ(pass->damage_rect, copy->damage_rect);
   EXPECT_EQ(pass->has_transparent_background, copy->has_transparent_background);
-  EXPECT_EQ(pass->overlay_state, copy->overlay_state);
   EXPECT_EQ(0u, copy->quad_list.size());
 
   // The copy request should not be copied/duplicated.
@@ -126,15 +121,13 @@
       gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
   gfx::Rect damage_rect(56, 123, 19, 43);
   bool has_transparent_background = true;
-  RenderPass::OverlayState overlay_state = RenderPass::SIMPLE_OVERLAY;
 
   scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
   pass->SetAll(id,
                output_rect,
                damage_rect,
                transform_to_root,
-               has_transparent_background,
-               overlay_state);
+               has_transparent_background);
 
   // Two quads using one shared state.
   scoped_ptr<SharedQuadState> shared_state1 = SharedQuadState::Create();
@@ -197,15 +190,13 @@
       gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
   gfx::Rect contrib_damage_rect(11, 16, 10, 15);
   bool contrib_has_transparent_background = true;
-  RenderPass::OverlayState contrib_overlay_state = RenderPass::SIMPLE_OVERLAY;
 
   scoped_ptr<TestRenderPass> contrib = TestRenderPass::Create();
   contrib->SetAll(contrib_id,
                   contrib_output_rect,
                   contrib_damage_rect,
                   contrib_transform_to_root,
-                  contrib_has_transparent_background,
-                  contrib_overlay_state);
+                  contrib_has_transparent_background);
 
   scoped_ptr<SharedQuadState> contrib_shared_state = SharedQuadState::Create();
   contrib_shared_state->SetAll(gfx::Transform(),
@@ -258,15 +249,13 @@
       gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
   gfx::Rect damage_rect(56, 123, 19, 43);
   bool has_transparent_background = true;
-  RenderPass::OverlayState overlay_state = RenderPass::SIMPLE_OVERLAY;
 
   scoped_ptr<TestRenderPass> pass = TestRenderPass::Create();
   pass->SetAll(id,
                output_rect,
                damage_rect,
                transform_to_root,
-               has_transparent_background,
-               overlay_state);
+               has_transparent_background);
 
   // A shared state with a quad.
   scoped_ptr<SharedQuadState> shared_state1 = SharedQuadState::Create();
diff --git a/cc/quads/yuv_video_draw_quad.cc b/cc/quads/yuv_video_draw_quad.cc
index e410757..ea56677 100644
--- a/cc/quads/yuv_video_draw_quad.cc
+++ b/cc/quads/yuv_video_draw_quad.cc
@@ -25,7 +25,7 @@
                               const gfx::Rect& rect,
                               const gfx::Rect& opaque_rect,
                               const gfx::Rect& visible_rect,
-                              const gfx::SizeF& tex_scale,
+                              const gfx::RectF& tex_coord_rect,
                               unsigned y_plane_resource_id,
                               unsigned u_plane_resource_id,
                               unsigned v_plane_resource_id,
@@ -33,7 +33,7 @@
   bool needs_blending = false;
   DrawQuad::SetAll(shared_quad_state, DrawQuad::YUV_VIDEO_CONTENT, rect,
                    opaque_rect, visible_rect, needs_blending);
-  this->tex_scale = tex_scale;
+  this->tex_coord_rect = tex_coord_rect;
   this->y_plane_resource_id = y_plane_resource_id;
   this->u_plane_resource_id = u_plane_resource_id;
   this->v_plane_resource_id = v_plane_resource_id;
@@ -45,14 +45,14 @@
                               const gfx::Rect& opaque_rect,
                               const gfx::Rect& visible_rect,
                               bool needs_blending,
-                              const gfx::SizeF& tex_scale,
+                              const gfx::RectF& tex_coord_rect,
                               unsigned y_plane_resource_id,
                               unsigned u_plane_resource_id,
                               unsigned v_plane_resource_id,
                               unsigned a_plane_resource_id) {
   DrawQuad::SetAll(shared_quad_state, DrawQuad::YUV_VIDEO_CONTENT, rect,
                    opaque_rect, visible_rect, needs_blending);
-  this->tex_scale = tex_scale;
+  this->tex_coord_rect = tex_coord_rect;
   this->y_plane_resource_id = y_plane_resource_id;
   this->u_plane_resource_id = u_plane_resource_id;
   this->v_plane_resource_id = v_plane_resource_id;
@@ -75,7 +75,7 @@
 }
 
 void YUVVideoDrawQuad::ExtendValue(base::DictionaryValue* value) const {
-  value->Set("tex_scale", MathUtil::AsValue(tex_scale).release());
+  value->Set("tex_coord_rect", MathUtil::AsValue(tex_coord_rect).release());
   value->SetInteger("y_plane_resource_id", y_plane_resource_id);
   value->SetInteger("u_plane_resource_id", u_plane_resource_id);
   value->SetInteger("v_plane_resource_id", v_plane_resource_id);
diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
index 3ac2336..65b35e0 100644
--- a/cc/quads/yuv_video_draw_quad.h
+++ b/cc/quads/yuv_video_draw_quad.h
@@ -23,7 +23,7 @@
               const gfx::Rect& rect,
               const gfx::Rect& opaque_rect,
               const gfx::Rect& visible_rect,
-              const gfx::SizeF& tex_scale,
+              const gfx::RectF& tex_coord_rect,
               unsigned y_plane_resource_id,
               unsigned u_plane_resource_id,
               unsigned v_plane_resource_id,
@@ -34,13 +34,13 @@
               const gfx::Rect& opaque_rect,
               const gfx::Rect& visible_rect,
               bool needs_blending,
-              const gfx::SizeF& tex_scale,
+              const gfx::RectF& tex_coord_rect,
               unsigned y_plane_resource_id,
               unsigned u_plane_resource_id,
               unsigned v_plane_resource_id,
               unsigned a_plane_resource_id);
 
-  gfx::SizeF tex_scale;
+  gfx::RectF tex_coord_rect;
   unsigned y_plane_resource_id;
   unsigned u_plane_resource_id;
   unsigned v_plane_resource_id;
diff --git a/cc/resources/bitmap_content_layer_updater.cc b/cc/resources/bitmap_content_layer_updater.cc
index 6f2332b..6f7cd01 100644
--- a/cc/resources/bitmap_content_layer_updater.cc
+++ b/cc/resources/bitmap_content_layer_updater.cc
@@ -64,11 +64,8 @@
     devtools_instrumentation::ScopedLayerTask paint_setup(
         devtools_instrumentation::kPaintSetup, layer_id_);
     canvas_size_ = content_rect.size();
-    bitmap_backing_.setConfig(
-        SkBitmap::kARGB_8888_Config,
-        canvas_size_.width(), canvas_size_.height(),
-        0, layer_is_opaque_ ? kOpaque_SkAlphaType : kPremul_SkAlphaType);
-    bitmap_backing_.allocPixels();
+    bitmap_backing_.allocN32Pixels(
+        canvas_size_.width(), canvas_size_.height(), layer_is_opaque_);
     canvas_ = skia::AdoptRef(new SkCanvas(bitmap_backing_));
   }
 
diff --git a/cc/resources/content_layer_updater.cc b/cc/resources/content_layer_updater.cc
index a176ac4..f0711df 100644
--- a/cc/resources/content_layer_updater.cc
+++ b/cc/resources/content_layer_updater.cc
@@ -24,6 +24,7 @@
     : rendering_stats_instrumentation_(stats_instrumentation),
       layer_id_(layer_id),
       layer_is_opaque_(false),
+      layer_fills_bounds_completely_(false),
       painter_(painter.Pass()) {}
 
 ContentLayerUpdater::~ContentLayerUpdater() {}
@@ -61,9 +62,9 @@
 
   canvas->clipRect(layer_sk_rect);
 
-  // If the layer has opaque contents then there is no need to
-  // clear the canvas before painting.
-  if (!layer_is_opaque_) {
+  // If the layer has opaque contents or will fill the bounds completely there
+  // is no need to clear the canvas before painting.
+  if (!layer_is_opaque_ && !layer_fills_bounds_completely_) {
     TRACE_EVENT0("cc", "Clear");
     canvas->drawColor(SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode);
   }
@@ -83,4 +84,8 @@
   layer_is_opaque_ = opaque;
 }
 
+void ContentLayerUpdater::SetFillsBoundsCompletely(bool fills_bounds) {
+  layer_fills_bounds_completely_ = fills_bounds;
+}
+
 }  // namespace cc
diff --git a/cc/resources/content_layer_updater.h b/cc/resources/content_layer_updater.h
index 6af2195..7ab2429 100644
--- a/cc/resources/content_layer_updater.h
+++ b/cc/resources/content_layer_updater.h
@@ -23,6 +23,7 @@
  public:
   void set_rendering_stats_instrumentation(RenderingStatsInstrumentation* rsi);
   virtual void SetOpaque(bool opaque) OVERRIDE;
+  virtual void SetFillsBoundsCompletely(bool fills_bounds) OVERRIDE;
 
  protected:
   ContentLayerUpdater(scoped_ptr<LayerPainter> painter,
@@ -38,12 +39,17 @@
   gfx::Rect content_rect() const { return content_rect_; }
 
   bool layer_is_opaque() const { return layer_is_opaque_; }
+  bool layer_fills_bounds_completely() const {
+    return layer_fills_bounds_completely_;
+  }
 
   RenderingStatsInstrumentation* rendering_stats_instrumentation_;
   int layer_id_;
 
   // True when it is known that all output pixels will be opaque.
   bool layer_is_opaque_;
+  // True when it is known that all output pixels will be filled.
+  bool layer_fills_bounds_completely_;
 
  private:
   gfx::Rect content_rect_;
diff --git a/cc/resources/direct_raster_worker_pool.cc b/cc/resources/direct_raster_worker_pool.cc
index fb0eab5..6b27846 100644
--- a/cc/resources/direct_raster_worker_pool.cc
+++ b/cc/resources/direct_raster_worker_pool.cc
@@ -4,6 +4,7 @@
 
 #include "cc/resources/direct_raster_worker_pool.h"
 
+#include "base/debug/trace_event.h"
 #include "cc/output/context_provider.h"
 #include "cc/resources/resource.h"
 #include "cc/resources/resource_provider.h"
diff --git a/cc/resources/image_raster_worker_pool.cc b/cc/resources/image_raster_worker_pool.cc
index bffebf2..bbaa2c5 100644
--- a/cc/resources/image_raster_worker_pool.cc
+++ b/cc/resources/image_raster_worker_pool.cc
@@ -5,7 +5,6 @@
 #include "cc/resources/image_raster_worker_pool.h"
 
 #include "base/debug/trace_event.h"
-#include "base/values.h"
 #include "cc/debug/traced_value.h"
 #include "cc/resources/resource.h"
 
diff --git a/cc/resources/image_raster_worker_pool.h b/cc/resources/image_raster_worker_pool.h
index 4f28929..279ff46 100644
--- a/cc/resources/image_raster_worker_pool.h
+++ b/cc/resources/image_raster_worker_pool.h
@@ -7,6 +7,8 @@
 
 #include "cc/resources/raster_worker_pool.h"
 
+#include "base/values.h"
+
 namespace cc {
 
 class CC_EXPORT ImageRasterWorkerPool : public RasterWorkerPool {
diff --git a/cc/resources/layer_updater.h b/cc/resources/layer_updater.h
index 44c6765..47f4410 100644
--- a/cc/resources/layer_updater.h
+++ b/cc/resources/layer_updater.h
@@ -59,6 +59,9 @@
   // Set true by the layer when it is known that the entire output is going to
   // be opaque.
   virtual void SetOpaque(bool opaque) {}
+  // Set true by the layer when it is known that the entire output bounds will
+  // be rasterized.
+  virtual void SetFillsBoundsCompletely(bool fills_bounds) {}
 
  protected:
   virtual ~LayerUpdater() {}
diff --git a/cc/resources/managed_tile_state.h b/cc/resources/managed_tile_state.h
index e457983..3423737 100644
--- a/cc/resources/managed_tile_state.h
+++ b/cc/resources/managed_tile_state.h
@@ -7,10 +7,12 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "cc/resources/platform_color.h"
+#include "cc/resources/raster_mode.h"
 #include "cc/resources/raster_worker_pool.h"
 #include "cc/resources/resource_pool.h"
 #include "cc/resources/resource_provider.h"
 #include "cc/resources/scoped_resource.h"
+#include "cc/resources/tile_priority.h"
 
 namespace cc {
 
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index 02d7650..3b90ac4 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -505,8 +505,7 @@
     Picture::AsTraceableRecordData() const {
   scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
   record_data->Set("picture_id", TracedValue::CreateIDRef(this).release());
-  record_data->SetInteger("width", layer_rect_.width());
-  record_data->SetInteger("height", layer_rect_.height());
+  record_data->Set("layer_rect", MathUtil::AsValue(layer_rect_).release());
   return TracedValue::FromValue(record_data.release());
 }
 
diff --git a/cc/resources/picture_pile.cc b/cc/resources/picture_pile.cc
index e82a23e..1af8b4c 100644
--- a/cc/resources/picture_pile.cc
+++ b/cc/resources/picture_pile.cc
@@ -147,16 +147,17 @@
 PicturePile::~PicturePile() {
 }
 
-bool PicturePile::Update(
-    ContentLayerClient* painter,
-    SkColor background_color,
-    bool contents_opaque,
-    const Region& invalidation,
-    const gfx::Rect& visible_layer_rect,
-    int frame_number,
-    RenderingStatsInstrumentation* stats_instrumentation) {
+bool PicturePile::Update(ContentLayerClient* painter,
+                         SkColor background_color,
+                         bool contents_opaque,
+                         bool contents_fill_bounds_completely,
+                         const Region& invalidation,
+                         const gfx::Rect& visible_layer_rect,
+                         int frame_number,
+                         RenderingStatsInstrumentation* stats_instrumentation) {
   background_color_ = background_color;
   contents_opaque_ = contents_opaque;
+  contents_fill_bounds_completely_ = contents_fill_bounds_completely;
 
   gfx::Rect interest_rect = visible_layer_rect;
   interest_rect.Inset(
diff --git a/cc/resources/picture_pile.h b/cc/resources/picture_pile.h
index d83adde..804a679 100644
--- a/cc/resources/picture_pile.h
+++ b/cc/resources/picture_pile.h
@@ -20,14 +20,14 @@
   // Re-record parts of the picture that are invalid.
   // Invalidations are in layer space.
   // Return true iff the pile was modified.
-  bool Update(
-      ContentLayerClient* painter,
-      SkColor background_color,
-      bool contents_opaque,
-      const Region& invalidation,
-      const gfx::Rect& visible_layer_rect,
-      int frame_number,
-      RenderingStatsInstrumentation* stats_instrumentation);
+  bool Update(ContentLayerClient* painter,
+              SkColor background_color,
+              bool contents_opaque,
+              bool contents_fill_bounds_completely,
+              const Region& invalidation,
+              const gfx::Rect& visible_layer_rect,
+              int frame_number,
+              RenderingStatsInstrumentation* stats_instrumentation);
 
   void set_slow_down_raster_scale_factor(int factor) {
     slow_down_raster_scale_factor_for_debug_ = factor;
diff --git a/cc/resources/picture_pile_base.cc b/cc/resources/picture_pile_base.cc
index ee2f519..2fb6ef5 100644
--- a/cc/resources/picture_pile_base.cc
+++ b/cc/resources/picture_pile_base.cc
@@ -43,6 +43,7 @@
       background_color_(SkColorSetARGBInline(0, 0, 0, 0)),
       slow_down_raster_scale_factor_for_debug_(0),
       contents_opaque_(false),
+      contents_fill_bounds_completely_(false),
       show_debug_picture_borders_(false),
       clear_canvas_with_debug_color_(kDefaultClearCanvasSetting),
       has_any_recordings_(false) {
@@ -62,6 +63,7 @@
       slow_down_raster_scale_factor_for_debug_(
           other->slow_down_raster_scale_factor_for_debug_),
       contents_opaque_(other->contents_opaque_),
+      contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
       show_debug_picture_borders_(other->show_debug_picture_borders_),
       clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
       has_any_recordings_(other->has_any_recordings_) {}
@@ -76,6 +78,7 @@
       slow_down_raster_scale_factor_for_debug_(
           other->slow_down_raster_scale_factor_for_debug_),
       contents_opaque_(other->contents_opaque_),
+      contents_fill_bounds_completely_(other->contents_fill_bounds_completely_),
       show_debug_picture_borders_(other->show_debug_picture_borders_),
       clear_canvas_with_debug_color_(other->clear_canvas_with_debug_color_),
       has_any_recordings_(other->has_any_recordings_) {
diff --git a/cc/resources/picture_pile_base.h b/cc/resources/picture_pile_base.h
index afdf1d9..be9955e 100644
--- a/cc/resources/picture_pile_base.h
+++ b/cc/resources/picture_pile_base.h
@@ -105,6 +105,7 @@
   SkColor background_color_;
   int slow_down_raster_scale_factor_for_debug_;
   bool contents_opaque_;
+  bool contents_fill_bounds_completely_;
   bool show_debug_picture_borders_;
   bool clear_canvas_with_debug_color_;
   // A hint about whether there are any recordings. This may be a false
diff --git a/cc/resources/picture_pile_impl.cc b/cc/resources/picture_pile_impl.cc
index 415f9a7..2e771fa 100644
--- a/cc/resources/picture_pile_impl.cc
+++ b/cc/resources/picture_pile_impl.cc
@@ -105,17 +105,13 @@
   // If this picture has opaque contents, it is guaranteeing that it will
   // draw an opaque rect the size of the layer.  If it is not, then we must
   // clear this canvas ourselves.
-  if (!contents_opaque_) {
-    // Clearing is about ~4x faster than drawing a rect even if the content
-    // isn't covering a majority of the canvas.
-    canvas->clear(SK_ColorTRANSPARENT);
-  } else {
+  if (contents_opaque_) {
     // Even if it is opaque, on any rasterizations that touch the edge of the
     // layer, we also need to raster the background color underneath the last
     // texel (since the recording won't cover it) and outside the last texel
     // (due to linear filtering when using this texture).
-    gfx::SizeF total_content_size = gfx::ScaleSize(tiling_.total_size(),
-                                                   contents_scale);
+    gfx::SizeF total_content_size =
+        gfx::ScaleSize(tiling_.total_size(), contents_scale);
     gfx::Rect content_rect(gfx::ToCeiledSize(total_content_size));
 
     // The final texel of content may only be partially covered by a
@@ -137,6 +133,11 @@
       canvas->drawColor(background_color_, SkXfermode::kSrc_Mode);
       canvas->restore();
     }
+  } else if (!contents_fill_bounds_completely_) {
+    TRACE_EVENT_INSTANT0("cc", "SkCanvas::clear", TRACE_EVENT_SCOPE_THREAD);
+    // Clearing is about ~4x faster than drawing a rect even if the content
+    // isn't covering a majority of the canvas.
+    canvas->clear(SK_ColorTRANSPARENT);
   }
 
   RasterCommon(canvas,
diff --git a/cc/resources/picture_pile_impl_unittest.cc b/cc/resources/picture_pile_impl_unittest.cc
index f6414db..c60bce3 100644
--- a/cc/resources/picture_pile_impl_unittest.cc
+++ b/cc/resources/picture_pile_impl_unittest.cc
@@ -674,10 +674,7 @@
       canvas_rect.Inset(0, 0, -1, -1);
 
       SkBitmap bitmap;
-      bitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                       canvas_rect.width(),
-                       canvas_rect.height());
-      bitmap.allocPixels();
+      bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height());
       SkCanvas canvas(bitmap);
       canvas.clear(SK_ColorTRANSPARENT);
 
@@ -726,10 +723,7 @@
   canvas_rect.Inset(0, 0, -1, -1);
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                   canvas_rect.width(),
-                   canvas_rect.height());
-  bitmap.allocPixels();
+  bitmap.allocN32Pixels(canvas_rect.width(), canvas_rect.height());
   SkCanvas canvas(bitmap);
 
   FakeRenderingStatsInstrumentation rendering_stats_instrumentation;
diff --git a/cc/resources/picture_pile_unittest.cc b/cc/resources/picture_pile_unittest.cc
index 5c1a57a..c64d420 100644
--- a/cc/resources/picture_pile_unittest.cc
+++ b/cc/resources/picture_pile_unittest.cc
@@ -56,6 +56,7 @@
     return pile_->Update(&client_,
                          background_color_,
                          contents_opaque_,
+                         false,
                          invalidation,
                          visible_layer_rect,
                          frame_number_,
diff --git a/cc/resources/pixel_buffer_raster_worker_pool.cc b/cc/resources/pixel_buffer_raster_worker_pool.cc
index 3e84dbc..80ddcd9 100644
--- a/cc/resources/pixel_buffer_raster_worker_pool.cc
+++ b/cc/resources/pixel_buffer_raster_worker_pool.cc
@@ -8,7 +8,6 @@
 
 #include "base/containers/stack_container.h"
 #include "base/debug/trace_event.h"
-#include "base/values.h"
 #include "cc/debug/traced_value.h"
 #include "cc/resources/resource.h"
 
diff --git a/cc/resources/pixel_buffer_raster_worker_pool.h b/cc/resources/pixel_buffer_raster_worker_pool.h
index 9971503..884213c 100644
--- a/cc/resources/pixel_buffer_raster_worker_pool.h
+++ b/cc/resources/pixel_buffer_raster_worker_pool.h
@@ -7,6 +7,7 @@
 
 #include <vector>
 
+#include "base/values.h"
 #include "cc/resources/raster_worker_pool.h"
 
 namespace cc {
diff --git a/cc/resources/raster_worker_pool.cc b/cc/resources/raster_worker_pool.cc
index ea776d0..6a807e6 100644
--- a/cc/resources/raster_worker_pool.cc
+++ b/cc/resources/raster_worker_pool.cc
@@ -8,45 +8,15 @@
 
 #include "base/atomic_sequence_num.h"
 #include "base/debug/trace_event_synthetic_delay.h"
-#include "base/json/json_writer.h"
 #include "base/lazy_instance.h"
-#include "base/metrics/histogram.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/simple_thread.h"
 #include "base/threading/thread_local.h"
-#include "base/values.h"
 #include "cc/base/scoped_ptr_deque.h"
-#include "cc/debug/devtools_instrumentation.h"
-#include "cc/debug/traced_value.h"
-#include "cc/resources/picture_pile_impl.h"
-#include "cc/resources/resource.h"
-#include "cc/resources/resource_provider.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
-#include "skia/ext/paint_simplifier.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
 
 namespace cc {
 namespace {
 
-// Subclass of Allocator that takes a suitably allocated pointer and uses
-// it as the pixel memory for the bitmap.
-class IdentityAllocator : public SkBitmap::Allocator {
- public:
-  explicit IdentityAllocator(void* buffer) : buffer_(buffer) {}
-  virtual bool allocPixelRef(SkBitmap* dst, SkColorTable*) OVERRIDE {
-    dst->setPixels(buffer_);
-    return true;
-  }
-
- private:
-  void* buffer_;
-};
-
-// Flag to indicate whether we should try and detect that
-// a tile is of solid color.
-const bool kUseColorEstimator = true;
-
 // Synthetic delay for raster tasks that are required for activation. Global to
 // avoid static initializer on critical path.
 struct RasterRequiredForActivationSyntheticDelayInitializer {
@@ -96,6 +66,8 @@
   virtual void Run() OVERRIDE {
     // Use picture clone index 0..num_threads.
     int picture_clone_index = picture_clone_index_sequence_.GetNext();
+    DCHECK_LE(0, picture_clone_index);
+    DCHECK_GT(RasterWorkerPool::GetNumRasterThreads(), picture_clone_index);
     current_tls_.Set(new ThreadLocalState(picture_clone_index));
 
     internal::TaskGraphRunner::Run();
@@ -113,247 +85,6 @@
 
 int g_num_raster_threads = 0;
 
-class DisableLCDTextFilter : public SkDrawFilter {
- public:
-  // SkDrawFilter interface.
-  virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE {
-    if (type != SkDrawFilter::kText_Type)
-      return true;
-
-    paint->setLCDRenderText(false);
-    return true;
-  }
-};
-
-class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
- public:
-  RasterWorkerPoolTaskImpl(
-      const Resource* resource,
-      PicturePileImpl* picture_pile,
-      const gfx::Rect& content_rect,
-      float contents_scale,
-      RasterMode raster_mode,
-      TileResolution tile_resolution,
-      int layer_id,
-      const void* tile_id,
-      int source_frame_number,
-      bool analyze_picture,
-      RenderingStatsInstrumentation* rendering_stats,
-      const base::Callback<void(const PicturePileImpl::Analysis&, bool)>& reply,
-      internal::WorkerPoolTask::Vector* dependencies)
-      : internal::RasterWorkerPoolTask(resource, dependencies),
-        picture_pile_(picture_pile),
-        content_rect_(content_rect),
-        contents_scale_(contents_scale),
-        raster_mode_(raster_mode),
-        tile_resolution_(tile_resolution),
-        layer_id_(layer_id),
-        tile_id_(tile_id),
-        source_frame_number_(source_frame_number),
-        analyze_picture_(analyze_picture),
-        rendering_stats_(rendering_stats),
-        reply_(reply),
-        canvas_(NULL) {}
-
-  // Overridden from internal::Task:
-  virtual void RunOnWorkerThread() OVERRIDE {
-    TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::RunOnWorkerThread");
-
-    DCHECK(picture_pile_);
-    if (canvas_) {
-      AnalyzeAndRaster(picture_pile_->GetCloneForDrawingOnThread(
-          g_task_graph_runner.Pointer()
-              ->GetPictureCloneIndexForCurrentThread()));
-    }
-  }
-
-  // Overridden from internal::WorkerPoolTask:
-  virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
-      OVERRIDE {
-    DCHECK(!canvas_);
-    canvas_ = client->AcquireCanvasForRaster(this, resource());
-  }
-  virtual void RunOnOriginThread() OVERRIDE {
-    TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::RunOnOriginThread");
-    if (canvas_)
-      AnalyzeAndRaster(picture_pile_);
-  }
-  virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
-      OVERRIDE {
-    canvas_ = NULL;
-    client->ReleaseCanvasForRaster(this, resource());
-  }
-  virtual void RunReplyOnOriginThread() OVERRIDE {
-    DCHECK(!canvas_);
-    reply_.Run(analysis_, !HasFinishedRunning());
-  }
-
- protected:
-  virtual ~RasterWorkerPoolTaskImpl() { DCHECK(!canvas_); }
-
- private:
-  scoped_ptr<base::Value> DataAsValue() const {
-    scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
-    res->Set("tile_id", TracedValue::CreateIDRef(tile_id_).release());
-    res->Set("resolution", TileResolutionAsValue(tile_resolution_).release());
-    res->SetInteger("source_frame_number", source_frame_number_);
-    res->SetInteger("layer_id", layer_id_);
-    return res.PassAs<base::Value>();
-  }
-
-  void AnalyzeAndRaster(PicturePileImpl* picture_pile) {
-    DCHECK(picture_pile);
-    DCHECK(canvas_);
-
-    if (analyze_picture_) {
-      Analyze(picture_pile);
-      if (analysis_.is_solid_color)
-        return;
-    }
-
-    Raster(picture_pile);
-  }
-
-  void Analyze(PicturePileImpl* picture_pile) {
-    TRACE_EVENT1("cc",
-                 "RasterWorkerPoolTaskImpl::Analyze",
-                 "data",
-                 TracedValue::FromValue(DataAsValue().release()));
-
-    DCHECK(picture_pile);
-
-    picture_pile->AnalyzeInRect(
-        content_rect_, contents_scale_, &analysis_, rendering_stats_);
-
-    // Record the solid color prediction.
-    UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
-                          analysis_.is_solid_color);
-
-    // Clear the flag if we're not using the estimator.
-    analysis_.is_solid_color &= kUseColorEstimator;
-  }
-
-  void Raster(PicturePileImpl* picture_pile) {
-    TRACE_EVENT2(
-        "cc",
-        "RasterWorkerPoolTaskImpl::Raster",
-        "data",
-        TracedValue::FromValue(DataAsValue().release()),
-        "raster_mode",
-        TracedValue::FromValue(RasterModeAsValue(raster_mode_).release()));
-
-    devtools_instrumentation::ScopedLayerTask raster_task(
-        devtools_instrumentation::kRasterTask, layer_id_);
-
-    skia::RefPtr<SkDrawFilter> draw_filter;
-    switch (raster_mode_) {
-      case LOW_QUALITY_RASTER_MODE:
-        draw_filter = skia::AdoptRef(new skia::PaintSimplifier);
-        break;
-      case HIGH_QUALITY_NO_LCD_RASTER_MODE:
-        draw_filter = skia::AdoptRef(new DisableLCDTextFilter);
-        break;
-      case HIGH_QUALITY_RASTER_MODE:
-        break;
-      case NUM_RASTER_MODES:
-      default:
-        NOTREACHED();
-    }
-    canvas_->setDrawFilter(draw_filter.get());
-
-    base::TimeDelta prev_rasterize_time =
-        rendering_stats_->impl_thread_rendering_stats().rasterize_time;
-
-    // Only record rasterization time for highres tiles, because
-    // lowres tiles are not required for activation and therefore
-    // introduce noise in the measurement (sometimes they get rasterized
-    // before we draw and sometimes they aren't)
-    RenderingStatsInstrumentation* stats =
-        tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL;
-    DCHECK(picture_pile);
-    picture_pile->RasterToBitmap(
-        canvas_, content_rect_, contents_scale_, stats);
-
-    if (rendering_stats_->record_rendering_stats()) {
-      base::TimeDelta current_rasterize_time =
-          rendering_stats_->impl_thread_rendering_stats().rasterize_time;
-      HISTOGRAM_CUSTOM_COUNTS(
-          "Renderer4.PictureRasterTimeUS",
-          (current_rasterize_time - prev_rasterize_time).InMicroseconds(),
-          0,
-          100000,
-          100);
-    }
-  }
-
-  PicturePileImpl::Analysis analysis_;
-  scoped_refptr<PicturePileImpl> picture_pile_;
-  gfx::Rect content_rect_;
-  float contents_scale_;
-  RasterMode raster_mode_;
-  TileResolution tile_resolution_;
-  int layer_id_;
-  const void* tile_id_;
-  int source_frame_number_;
-  bool analyze_picture_;
-  RenderingStatsInstrumentation* rendering_stats_;
-  const base::Callback<void(const PicturePileImpl::Analysis&, bool)> reply_;
-  SkCanvas* canvas_;
-
-  DISALLOW_COPY_AND_ASSIGN(RasterWorkerPoolTaskImpl);
-};
-
-class ImageDecodeWorkerPoolTaskImpl : public internal::WorkerPoolTask {
- public:
-  ImageDecodeWorkerPoolTaskImpl(
-      SkPixelRef* pixel_ref,
-      int layer_id,
-      RenderingStatsInstrumentation* rendering_stats,
-      const base::Callback<void(bool was_canceled)>& reply)
-      : pixel_ref_(skia::SharePtr(pixel_ref)),
-        layer_id_(layer_id),
-        rendering_stats_(rendering_stats),
-        reply_(reply) {}
-
-  // Overridden from internal::Task:
-  virtual void RunOnWorkerThread() OVERRIDE {
-    TRACE_EVENT0("cc", "ImageDecodeWorkerPoolTaskImpl::RunOnWorkerThread");
-    Decode();
-  }
-
-  // Overridden from internal::WorkerPoolTask:
-  virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
-      OVERRIDE {}
-  virtual void RunOnOriginThread() OVERRIDE {
-    TRACE_EVENT0("cc", "ImageDecodeWorkerPoolTaskImpl::RunOnOriginThread");
-    Decode();
-  }
-  virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
-      OVERRIDE {}
-  virtual void RunReplyOnOriginThread() OVERRIDE {
-    reply_.Run(!HasFinishedRunning());
-  }
-
- protected:
-  virtual ~ImageDecodeWorkerPoolTaskImpl() {}
-
- private:
-  void Decode() {
-    devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
-        pixel_ref_.get());
-    // This will cause the image referred to by pixel ref to be decoded.
-    pixel_ref_->lockPixels();
-    pixel_ref_->unlockPixels();
-  }
-
-  skia::RefPtr<SkPixelRef> pixel_ref_;
-  int layer_id_;
-  RenderingStatsInstrumentation* rendering_stats_;
-  const base::Callback<void(bool was_canceled)> reply_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageDecodeWorkerPoolTaskImpl);
-};
-
 class RasterFinishedWorkerPoolTaskImpl : public internal::WorkerPoolTask {
  public:
   typedef base::Callback<void(const internal::WorkerPoolTask* source)> Callback;
@@ -570,47 +301,6 @@
   return g_task_graph_runner.Pointer()->GetPictureCloneIndexForCurrentThread();
 }
 
-// static
-scoped_refptr<internal::RasterWorkerPoolTask>
-RasterWorkerPool::CreateRasterTask(
-    const Resource* resource,
-    PicturePileImpl* picture_pile,
-    const gfx::Rect& content_rect,
-    float contents_scale,
-    RasterMode raster_mode,
-    TileResolution tile_resolution,
-    int layer_id,
-    const void* tile_id,
-    int source_frame_number,
-    bool analyze_picture,
-    RenderingStatsInstrumentation* rendering_stats,
-    const base::Callback<void(const PicturePileImpl::Analysis&, bool)>& reply,
-    internal::WorkerPoolTask::Vector* dependencies) {
-  return make_scoped_refptr(new RasterWorkerPoolTaskImpl(resource,
-                                                         picture_pile,
-                                                         content_rect,
-                                                         contents_scale,
-                                                         raster_mode,
-                                                         tile_resolution,
-                                                         layer_id,
-                                                         tile_id,
-                                                         source_frame_number,
-                                                         analyze_picture,
-                                                         rendering_stats,
-                                                         reply,
-                                                         dependencies));
-}
-
-// static
-scoped_refptr<internal::WorkerPoolTask> RasterWorkerPool::CreateImageDecodeTask(
-    SkPixelRef* pixel_ref,
-    int layer_id,
-    RenderingStatsInstrumentation* rendering_stats,
-    const base::Callback<void(bool was_canceled)>& reply) {
-  return make_scoped_refptr(new ImageDecodeWorkerPoolTaskImpl(
-      pixel_ref, layer_id, rendering_stats, reply));
-}
-
 void RasterWorkerPool::SetClient(RasterWorkerPoolClient* client) {
   client_ = client;
 }
diff --git a/cc/resources/raster_worker_pool.h b/cc/resources/raster_worker_pool.h
index 13cdd55..e257e07 100644
--- a/cc/resources/raster_worker_pool.h
+++ b/cc/resources/raster_worker_pool.h
@@ -8,22 +8,21 @@
 #include <deque>
 #include <vector>
 
-#include "cc/debug/rendering_stats_instrumentation.h"
-#include "cc/resources/picture_pile_impl.h"
-#include "cc/resources/raster_mode.h"
+#include "base/memory/weak_ptr.h"
 #include "cc/resources/resource_format.h"
 #include "cc/resources/task_graph_runner.h"
-#include "cc/resources/tile_priority.h"
 
-class SkPixelRef;
+class SkCanvas;
+
+namespace base {
+class SequencedTaskRunner;
+}
 
 namespace cc {
-
 class Resource;
 class ResourceProvider;
 
 namespace internal {
-
 class WorkerPoolTask;
 
 class CC_EXPORT WorkerPoolTaskClient {
@@ -145,28 +144,6 @@
   static unsigned kRasterRequiredForActivationFinishedTaskPriority;
   static unsigned kRasterTaskPriorityBase;
 
-  // TODO(vmpstr): Figure out an elegant way to not pass this many parameters.
-  static scoped_refptr<internal::RasterWorkerPoolTask> CreateRasterTask(
-      const Resource* resource,
-      PicturePileImpl* picture_pile,
-      const gfx::Rect& content_rect,
-      float contents_scale,
-      RasterMode raster_mode,
-      TileResolution tile_resolution,
-      int layer_id,
-      const void* tile_id,
-      int source_frame_number,
-      bool analyze_picture,
-      RenderingStatsInstrumentation* rendering_stats,
-      const base::Callback<void(const PicturePileImpl::Analysis&, bool)>& reply,
-      internal::WorkerPoolTask::Vector* dependencies);
-
-  static scoped_refptr<internal::WorkerPoolTask> CreateImageDecodeTask(
-      SkPixelRef* pixel_ref,
-      int layer_id,
-      RenderingStatsInstrumentation* rendering_stats,
-      const base::Callback<void(bool was_canceled)>& reply);
-
   void SetClient(RasterWorkerPoolClient* client);
 
   // Tells the worker pool to shutdown after canceling all previously
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index 55dafbd..1e7c9d7 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -210,29 +210,29 @@
       lock_for_read_count(0),
       imported_count(0),
       exported_count(0),
+      dirty_image(false),
       locked_for_write(false),
-      origin(Internal),
+      lost(false),
       marked_for_deletion(false),
       pending_set_pixels(false),
       set_pixels_completion_forced(false),
       allocated(false),
       enable_read_lock_fences(false),
+      has_shared_bitmap_id(false),
+      allow_overlay(false),
       read_lock_fence(NULL),
       size(),
+      origin(Internal),
       target(0),
       original_filter(0),
       filter(0),
       image_id(0),
       bound_image_id(0),
-      dirty_image(false),
       texture_pool(0),
       wrap_mode(0),
-      lost(false),
       hint(TextureUsageAny),
       type(InvalidType),
       format(RGBA_8888),
-      has_shared_bitmap_id(false),
-      allow_overlay(false),
       shared_bitmap(NULL) {}
 
 ResourceProvider::Resource::~Resource() {}
@@ -255,28 +255,29 @@
       lock_for_read_count(0),
       imported_count(0),
       exported_count(0),
+      dirty_image(false),
       locked_for_write(false),
-      origin(origin),
+      lost(false),
       marked_for_deletion(false),
       pending_set_pixels(false),
       set_pixels_completion_forced(false),
       allocated(false),
       enable_read_lock_fences(false),
+      has_shared_bitmap_id(false),
+      allow_overlay(false),
       read_lock_fence(NULL),
       size(size),
+      origin(origin),
       target(target),
       original_filter(filter),
       filter(filter),
       image_id(0),
       bound_image_id(0),
-      dirty_image(false),
       texture_pool(texture_pool),
       wrap_mode(wrap_mode),
-      lost(false),
       hint(hint),
       type(GLTexture),
       format(format),
-      has_shared_bitmap_id(false),
       shared_bitmap(NULL) {
   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
   DCHECK_EQ(origin == Internal, !!texture_pool);
@@ -297,28 +298,29 @@
       lock_for_read_count(0),
       imported_count(0),
       exported_count(0),
+      dirty_image(false),
       locked_for_write(false),
-      origin(origin),
+      lost(false),
       marked_for_deletion(false),
       pending_set_pixels(false),
       set_pixels_completion_forced(false),
       allocated(false),
       enable_read_lock_fences(false),
+      has_shared_bitmap_id(!!bitmap),
+      allow_overlay(false),
       read_lock_fence(NULL),
       size(size),
+      origin(origin),
       target(0),
       original_filter(filter),
       filter(filter),
       image_id(0),
       bound_image_id(0),
-      dirty_image(false),
       texture_pool(0),
       wrap_mode(wrap_mode),
-      lost(false),
       hint(TextureUsageAny),
       type(Bitmap),
       format(RGBA_8888),
-      has_shared_bitmap_id(!!bitmap),
       shared_bitmap(bitmap) {
   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
   DCHECK(origin == Delegated || pixels);
@@ -340,28 +342,29 @@
       lock_for_read_count(0),
       imported_count(0),
       exported_count(0),
+      dirty_image(false),
       locked_for_write(false),
-      origin(origin),
+      lost(false),
       marked_for_deletion(false),
       pending_set_pixels(false),
       set_pixels_completion_forced(false),
       allocated(false),
       enable_read_lock_fences(false),
+      has_shared_bitmap_id(true),
+      allow_overlay(false),
       read_lock_fence(NULL),
       size(size),
+      origin(origin),
       target(0),
       original_filter(filter),
       filter(filter),
       image_id(0),
       bound_image_id(0),
-      dirty_image(false),
       texture_pool(0),
       wrap_mode(wrap_mode),
-      lost(false),
       hint(TextureUsageAny),
       type(Bitmap),
       format(RGBA_8888),
-      has_shared_bitmap_id(true),
       shared_bitmap_id(bitmap_id),
       shared_bitmap(NULL) {
   DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
@@ -449,10 +452,8 @@
       DCHECK_EQ(RGBA_8888, resource()->format);
       SkImageInfo image_info = SkImageInfo::MakeN32Premul(
           resource()->size.width(), resource()->size.height());
-      size_t row_bytes = SkBitmap::ComputeRowBytes(SkBitmap::kARGB_8888_Config,
-                                                   resource()->size.width());
       surface = skia::AdoptRef(SkSurface::NewRasterDirect(
-          image_info, resource()->pixels, row_bytes));
+          image_info, resource()->pixels, image_info.minRowBytes()));
       break;
     }
     default:
@@ -483,19 +484,18 @@
     case RGBA_4444:
       // Use the default stride if we will eventually convert this
       // bitmap to 4444.
-      raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
-                               resource()->size.width(),
-                               resource()->size.height());
-      raster_bitmap_.allocPixels();
+      raster_bitmap_.allocN32Pixels(resource()->size.width(),
+                                    resource()->size.height());
       break;
     case RGBA_8888:
-    case BGRA_8888:
-      raster_bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
-                               resource()->size.width(),
-                               resource()->size.height(),
-                               stride);
-      raster_bitmap_.setPixels(mapped_buffer_);
+    case BGRA_8888: {
+      SkImageInfo info = SkImageInfo::MakeN32Premul(resource()->size.width(),
+                                                    resource()->size.height());
+      if (0 == stride)
+        stride = info.minRowBytes();
+      raster_bitmap_.installPixels(info, mapped_buffer_, stride);
       break;
+    }
     case LUMINANCE_8:
     case RGB_565:
     case ETC1:
@@ -799,12 +799,11 @@
   ResourceMap::iterator it = resources_.find(id);
   CHECK(it != resources_.end());
   Resource* resource = &it->second;
-  DCHECK(!resource->lock_for_read_count);
   DCHECK(!resource->marked_for_deletion);
   DCHECK_EQ(resource->imported_count, 0);
   DCHECK(resource->pending_set_pixels || !resource->locked_for_write);
 
-  if (resource->exported_count > 0) {
+  if (resource->exported_count > 0 || resource->lock_for_read_count > 0) {
     resource->marked_for_deletion = true;
     return;
   } else {
@@ -933,21 +932,20 @@
     DCHECK_EQ(Bitmap, resource->type);
     DCHECK(resource->allocated);
     DCHECK_EQ(RGBA_8888, resource->format);
-    SkBitmap src_full;
-    src_full.setConfig(
-        SkBitmap::kARGB_8888_Config, image_rect.width(), image_rect.height());
-    src_full.setPixels(const_cast<uint8_t*>(image));
-    SkBitmap src_subset;
-    SkIRect sk_source_rect = SkIRect::MakeXYWH(source_rect.x(),
-                                               source_rect.y(),
-                                               source_rect.width(),
-                                               source_rect.height());
-    sk_source_rect.offset(-image_rect.x(), -image_rect.y());
-    src_full.extractSubset(&src_subset, sk_source_rect);
+    DCHECK(source_rect.x() >= image_rect.x());
+    DCHECK(source_rect.y() >= image_rect.y());
+    DCHECK(source_rect.right() <= image_rect.right());
+    DCHECK(source_rect.bottom() <= image_rect.bottom());
+    SkImageInfo source_info =
+        SkImageInfo::MakeN32Premul(source_rect.width(), source_rect.height());
+    size_t image_row_bytes = image_rect.width() * 4;
+    gfx::Vector2d source_offset = source_rect.origin() - image_rect.origin();
+    image += source_offset.y() * image_row_bytes + source_offset.x() * 4;
 
     ScopedWriteLockSoftware lock(this, id);
     SkCanvas* dest = lock.sk_canvas();
-    dest->writePixels(src_subset, dest_offset.x(), dest_offset.y());
+    dest->writePixels(
+        source_info, image, image_row_bytes, dest_offset.x(), dest_offset.y());
   }
 }
 
@@ -1088,10 +1086,25 @@
 }
 
 void ResourceProvider::UnlockForRead(ResourceId id) {
-  Resource* resource = GetResource(id);
+  DCHECK(thread_checker_.CalledOnValidThread());
+  ResourceMap::iterator it = resources_.find(id);
+  CHECK(it != resources_.end());
+
+  Resource* resource = &it->second;
   DCHECK_GT(resource->lock_for_read_count, 0);
   DCHECK_EQ(resource->exported_count, 0);
   resource->lock_for_read_count--;
+  if (resource->marked_for_deletion && !resource->lock_for_read_count) {
+    if (!resource->child_id) {
+      // The resource belongs to this ResourceProvider, so it can be destroyed.
+      DeleteResourceInternal(it, Normal);
+    } else {
+      ChildMap::iterator child_it = children_.find(resource->child_id);
+      ResourceIdArray unused;
+      unused.push_back(id);
+      DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused);
+    }
+  }
 }
 
 const ResourceProvider::Resource* ResourceProvider::LockForWrite(
@@ -1175,10 +1188,9 @@
 void ResourceProvider::PopulateSkBitmapWithResource(
     SkBitmap* sk_bitmap, const Resource* resource) {
   DCHECK_EQ(RGBA_8888, resource->format);
-  sk_bitmap->setConfig(SkBitmap::kARGB_8888_Config,
-                       resource->size.width(),
-                       resource->size.height());
-  sk_bitmap->setPixels(resource->pixels);
+  SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(),
+                                                resource->size.height());
+  sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes());
 }
 
 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware(
@@ -1649,7 +1661,6 @@
     Resource& resource = it->second;
 
     DCHECK(!resource.locked_for_write);
-    DCHECK(!resource.lock_for_read_count);
     DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
     DCHECK(child_info->parent_to_child_map.count(local_id));
 
@@ -1658,9 +1669,10 @@
 
     bool is_lost =
         resource.lost || (resource.type == GLTexture && lost_output_surface_);
-    if (resource.exported_count > 0) {
+    if (resource.exported_count > 0 || resource.lock_for_read_count > 0) {
       if (style != ForShutdown) {
-        // Defer this until we receive the resource back from the parent.
+        // Defer this until we receive the resource back from the parent or
+        // the read lock is released.
         resource.marked_for_deletion = true;
         continue;
       }
diff --git a/cc/resources/resource_provider.h b/cc/resources/resource_provider.h
index 056ce2f..c7c0f5f 100644
--- a/cc/resources/resource_provider.h
+++ b/cc/resources/resource_provider.h
@@ -416,30 +416,30 @@
     int lock_for_read_count;
     int imported_count;
     int exported_count;
-    bool locked_for_write;
-    Origin origin;
-    bool marked_for_deletion;
-    bool pending_set_pixels;
-    bool set_pixels_completion_forced;
-    bool allocated;
-    bool enable_read_lock_fences;
+    bool dirty_image : 1;
+    bool locked_for_write : 1;
+    bool lost : 1;
+    bool marked_for_deletion : 1;
+    bool pending_set_pixels : 1;
+    bool set_pixels_completion_forced : 1;
+    bool allocated : 1;
+    bool enable_read_lock_fences : 1;
+    bool has_shared_bitmap_id : 1;
+    bool allow_overlay : 1;
     scoped_refptr<Fence> read_lock_fence;
     gfx::Size size;
+    Origin origin;
     GLenum target;
     // TODO(skyostil): Use a separate sampler object for filter state.
     GLenum original_filter;
     GLenum filter;
     unsigned image_id;
     unsigned bound_image_id;
-    bool dirty_image;
     GLenum texture_pool;
     GLint wrap_mode;
-    bool lost;
     TextureUsageHint hint;
     ResourceType type;
     ResourceFormat format;
-    bool has_shared_bitmap_id;
-    bool allow_overlay;
     SharedBitmapId shared_bitmap_id;
     SharedBitmap* shared_bitmap;
     linked_ptr<DirectRasterBuffer> direct_raster_buffer;
diff --git a/cc/resources/resource_provider_unittest.cc b/cc/resources/resource_provider_unittest.cc
index cca0c5b..21feb89 100644
--- a/cc/resources/resource_provider_unittest.cc
+++ b/cc/resources/resource_provider_unittest.cc
@@ -825,6 +825,56 @@
   EXPECT_FALSE(returned_to_child[3].lost);
 }
 
+TEST_P(ResourceProviderTest, ReadLockCountStopsReturnToChildOrDelete) {
+  if (GetParam() != ResourceProvider::GLTexture)
+    return;
+  gfx::Size size(1, 1);
+  ResourceFormat format = RGBA_8888;
+
+  ResourceProvider::ResourceId id1 = child_resource_provider_->CreateResource(
+      size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
+  uint8_t data1[4] = {1, 2, 3, 4};
+  gfx::Rect rect(size);
+  child_resource_provider_->SetPixels(id1, data1, rect, rect, gfx::Vector2d());
+
+  ReturnedResourceArray returned_to_child;
+  int child_id =
+      resource_provider_->CreateChild(GetReturnCallback(&returned_to_child));
+  {
+    // Transfer some resources to the parent.
+    ResourceProvider::ResourceIdArray resource_ids_to_transfer;
+    resource_ids_to_transfer.push_back(id1);
+    TransferableResourceArray list;
+    child_resource_provider_->PrepareSendToParent(resource_ids_to_transfer,
+                                                  &list);
+    ASSERT_EQ(1u, list.size());
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+
+    resource_provider_->ReceiveFromChild(child_id, list);
+
+    ResourceProvider::ScopedReadLockGL lock(resource_provider_.get(),
+                                            list[0].id);
+
+    resource_provider_->DeclareUsedResourcesFromChild(
+        child_id, ResourceProvider::ResourceIdArray());
+    EXPECT_EQ(0u, returned_to_child.size());
+  }
+
+  EXPECT_EQ(1u, returned_to_child.size());
+  child_resource_provider_->ReceiveReturnsFromParent(returned_to_child);
+
+  {
+    ResourceProvider::ScopedReadLockGL lock(child_resource_provider_.get(),
+                                            id1);
+    child_resource_provider_->DeleteResource(id1);
+    EXPECT_EQ(1u, child_resource_provider_->num_resources());
+    EXPECT_TRUE(child_resource_provider_->InUseByConsumer(id1));
+  }
+
+  EXPECT_EQ(0u, child_resource_provider_->num_resources());
+  resource_provider_->DestroyChild(child_id);
+}
+
 TEST_P(ResourceProviderTest, TransferSoftwareResources) {
   if (GetParam() != ResourceProvider::Bitmap)
     return;
@@ -848,11 +898,9 @@
   ResourceProvider::ResourceId id3 = child_resource_provider_->CreateResource(
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
   uint8_t data3[4] = { 6, 7, 8, 9 };
-  SkBitmap bitmap3;
-  bitmap3.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
-  bitmap3.setPixels(data3);
+  SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
   SkCanvas* raster_canvas = child_resource_provider_->MapImageRasterBuffer(id3);
-  raster_canvas->writePixels(bitmap3, 0, 0);
+  raster_canvas->writePixels(info, data3, info.minRowBytes(), 0, 0);
   child_resource_provider_->UnmapImageRasterBuffer(id3);
 
   scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
@@ -962,7 +1010,7 @@
     expected_ids.insert(id3);
     expected_ids.insert(id4);
     std::set<ResourceProvider::ResourceId> returned_ids;
-    for(unsigned i = 0; i < 4; i++)
+    for (unsigned i = 0; i < 4; i++)
       returned_ids.insert(returned_to_child[i].id);
     EXPECT_EQ(expected_ids, returned_ids);
     EXPECT_FALSE(returned_to_child[0].lost);
@@ -1042,7 +1090,7 @@
   expected_ids.insert(id3);
   expected_ids.insert(id4);
   std::set<ResourceProvider::ResourceId> returned_ids;
-  for(unsigned i = 0; i < 4; i++)
+  for (unsigned i = 0; i < 4; i++)
     returned_ids.insert(returned_to_child[i].id);
   EXPECT_EQ(expected_ids, returned_ids);
   EXPECT_FALSE(returned_to_child[0].lost);
@@ -2844,8 +2892,7 @@
   resource_provider->AcquirePixelRasterBuffer(id);
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
-  bitmap.allocPixels();
+  bitmap.allocN32Pixels(size.width(), size.height());
   *(bitmap.getAddr32(0, 0)) = kBadBeef;
   SkCanvas* canvas = resource_provider->MapPixelRasterBuffer(id);
   canvas->writePixels(bitmap, 0, 0);
@@ -3064,8 +3111,7 @@
       size, GL_CLAMP_TO_EDGE, ResourceProvider::TextureUsageAny, format);
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, size.width(), size.height());
-  bitmap.allocPixels();
+  bitmap.allocN32Pixels(size.width(), size.height());
   *(bitmap.getAddr32(0, 0)) = kBadBeef;
   SkCanvas* canvas = resource_provider->MapImageRasterBuffer(id);
   ASSERT_TRUE(!!canvas);
diff --git a/cc/resources/resource_update_controller_unittest.cc b/cc/resources/resource_update_controller_unittest.cc
index 80e8a76..44e65a5 100644
--- a/cc/resources/resource_update_controller_unittest.cc
+++ b/cc/resources/resource_update_controller_unittest.cc
@@ -108,8 +108,7 @@
 
  protected:
   virtual void SetUp() {
-    bitmap_.setConfig(SkBitmap::kARGB_8888_Config, 300, 150);
-    bitmap_.allocPixels();
+    bitmap_.allocN32Pixels(300, 150);
 
     for (int i = 0; i < 4; i++) {
       textures_[i] = PrioritizedResource::Create(resource_manager_.get(),
diff --git a/cc/resources/task_graph_runner.h b/cc/resources/task_graph_runner.h
index 3e34a3e..fe605d1 100644
--- a/cc/resources/task_graph_runner.h
+++ b/cc/resources/task_graph_runner.h
@@ -124,7 +124,7 @@
   void CollectCompletedTasks(NamespaceToken token,
                              Task::Vector* completed_tasks);
 
-  // Run tasks on until Shutdown() is called.
+  // Run tasks until Shutdown() is called.
   void Run();
 
   // Process all pending tasks, but don't wait/sleep. Return as soon as all
diff --git a/cc/resources/tile.h b/cc/resources/tile.h
index 138cad5..7df43e0 100644
--- a/cc/resources/tile.h
+++ b/cc/resources/tile.h
@@ -10,6 +10,7 @@
 #include "base/memory/scoped_vector.h"
 #include "cc/base/ref_counted_managed.h"
 #include "cc/resources/managed_tile_state.h"
+#include "cc/resources/picture_pile_impl.h"
 #include "cc/resources/raster_mode.h"
 #include "cc/resources/tile_priority.h"
 #include "ui/gfx/rect.h"
@@ -17,8 +18,6 @@
 
 namespace cc {
 
-class PicturePileImpl;
-
 class CC_EXPORT Tile : public RefCountedManaged<Tile> {
  public:
   enum TileRasterFlags {
diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc
index 39db650..8dc9c29 100644
--- a/cc/resources/tile_manager.cc
+++ b/cc/resources/tile_manager.cc
@@ -12,6 +12,7 @@
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
+#include "cc/debug/devtools_instrumentation.h"
 #include "cc/debug/traced_value.h"
 #include "cc/layers/picture_layer_impl.h"
 #include "cc/resources/direct_raster_worker_pool.h"
@@ -19,11 +20,258 @@
 #include "cc/resources/pixel_buffer_raster_worker_pool.h"
 #include "cc/resources/raster_worker_pool_delegate.h"
 #include "cc/resources/tile.h"
+#include "skia/ext/paint_simplifier.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
 #include "ui/gfx/rect_conversions.h"
 
 namespace cc {
 namespace {
 
+// Flag to indicate whether we should try and detect that
+// a tile is of solid color.
+const bool kUseColorEstimator = true;
+
+class DisableLCDTextFilter : public SkDrawFilter {
+ public:
+  // SkDrawFilter interface.
+  virtual bool filter(SkPaint* paint, SkDrawFilter::Type type) OVERRIDE {
+    if (type != SkDrawFilter::kText_Type)
+      return true;
+
+    paint->setLCDRenderText(false);
+    return true;
+  }
+};
+
+class RasterWorkerPoolTaskImpl : public internal::RasterWorkerPoolTask {
+ public:
+  RasterWorkerPoolTaskImpl(
+      const Resource* resource,
+      PicturePileImpl* picture_pile,
+      const gfx::Rect& content_rect,
+      float contents_scale,
+      RasterMode raster_mode,
+      TileResolution tile_resolution,
+      int layer_id,
+      const void* tile_id,
+      int source_frame_number,
+      bool analyze_picture,
+      RenderingStatsInstrumentation* rendering_stats,
+      const base::Callback<void(const PicturePileImpl::Analysis&, bool)>& reply,
+      internal::WorkerPoolTask::Vector* dependencies)
+      : internal::RasterWorkerPoolTask(resource, dependencies),
+        picture_pile_(picture_pile),
+        content_rect_(content_rect),
+        contents_scale_(contents_scale),
+        raster_mode_(raster_mode),
+        tile_resolution_(tile_resolution),
+        layer_id_(layer_id),
+        tile_id_(tile_id),
+        source_frame_number_(source_frame_number),
+        analyze_picture_(analyze_picture),
+        rendering_stats_(rendering_stats),
+        reply_(reply),
+        canvas_(NULL) {}
+
+  // Overridden from internal::Task:
+  virtual void RunOnWorkerThread() OVERRIDE {
+    TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::RunOnWorkerThread");
+
+    DCHECK(picture_pile_);
+    if (canvas_) {
+      AnalyzeAndRaster(picture_pile_->GetCloneForDrawingOnThread(
+          RasterWorkerPool::GetPictureCloneIndexForCurrentThread()));
+    }
+  }
+
+  // Overridden from internal::WorkerPoolTask:
+  virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
+      OVERRIDE {
+    DCHECK(!canvas_);
+    canvas_ = client->AcquireCanvasForRaster(this, resource());
+  }
+  virtual void RunOnOriginThread() OVERRIDE {
+    TRACE_EVENT0("cc", "RasterWorkerPoolTaskImpl::RunOnOriginThread");
+    if (canvas_)
+      AnalyzeAndRaster(picture_pile_);
+  }
+  virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
+      OVERRIDE {
+    canvas_ = NULL;
+    client->ReleaseCanvasForRaster(this, resource());
+  }
+  virtual void RunReplyOnOriginThread() OVERRIDE {
+    DCHECK(!canvas_);
+    reply_.Run(analysis_, !HasFinishedRunning());
+  }
+
+ protected:
+  virtual ~RasterWorkerPoolTaskImpl() { DCHECK(!canvas_); }
+
+ private:
+  scoped_ptr<base::Value> DataAsValue() const {
+    scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
+    res->Set("tile_id", TracedValue::CreateIDRef(tile_id_).release());
+    res->Set("resolution", TileResolutionAsValue(tile_resolution_).release());
+    res->SetInteger("source_frame_number", source_frame_number_);
+    res->SetInteger("layer_id", layer_id_);
+    return res.PassAs<base::Value>();
+  }
+
+  void AnalyzeAndRaster(PicturePileImpl* picture_pile) {
+    DCHECK(picture_pile);
+    DCHECK(canvas_);
+
+    if (analyze_picture_) {
+      Analyze(picture_pile);
+      if (analysis_.is_solid_color)
+        return;
+    }
+
+    Raster(picture_pile);
+  }
+
+  void Analyze(PicturePileImpl* picture_pile) {
+    TRACE_EVENT1("cc",
+                 "RasterWorkerPoolTaskImpl::Analyze",
+                 "data",
+                 TracedValue::FromValue(DataAsValue().release()));
+
+    DCHECK(picture_pile);
+
+    picture_pile->AnalyzeInRect(
+        content_rect_, contents_scale_, &analysis_, rendering_stats_);
+
+    // Record the solid color prediction.
+    UMA_HISTOGRAM_BOOLEAN("Renderer4.SolidColorTilesAnalyzed",
+                          analysis_.is_solid_color);
+
+    // Clear the flag if we're not using the estimator.
+    analysis_.is_solid_color &= kUseColorEstimator;
+  }
+
+  void Raster(PicturePileImpl* picture_pile) {
+    TRACE_EVENT2(
+        "cc",
+        "RasterWorkerPoolTaskImpl::Raster",
+        "data",
+        TracedValue::FromValue(DataAsValue().release()),
+        "raster_mode",
+        TracedValue::FromValue(RasterModeAsValue(raster_mode_).release()));
+
+    devtools_instrumentation::ScopedLayerTask raster_task(
+        devtools_instrumentation::kRasterTask, layer_id_);
+
+    skia::RefPtr<SkDrawFilter> draw_filter;
+    switch (raster_mode_) {
+      case LOW_QUALITY_RASTER_MODE:
+        draw_filter = skia::AdoptRef(new skia::PaintSimplifier);
+        break;
+      case HIGH_QUALITY_NO_LCD_RASTER_MODE:
+        draw_filter = skia::AdoptRef(new DisableLCDTextFilter);
+        break;
+      case HIGH_QUALITY_RASTER_MODE:
+        break;
+      case NUM_RASTER_MODES:
+      default:
+        NOTREACHED();
+    }
+    canvas_->setDrawFilter(draw_filter.get());
+
+    base::TimeDelta prev_rasterize_time =
+        rendering_stats_->impl_thread_rendering_stats().rasterize_time;
+
+    // Only record rasterization time for highres tiles, because
+    // lowres tiles are not required for activation and therefore
+    // introduce noise in the measurement (sometimes they get rasterized
+    // before we draw and sometimes they aren't)
+    RenderingStatsInstrumentation* stats =
+        tile_resolution_ == HIGH_RESOLUTION ? rendering_stats_ : NULL;
+    DCHECK(picture_pile);
+    picture_pile->RasterToBitmap(
+        canvas_, content_rect_, contents_scale_, stats);
+
+    if (rendering_stats_->record_rendering_stats()) {
+      base::TimeDelta current_rasterize_time =
+          rendering_stats_->impl_thread_rendering_stats().rasterize_time;
+      HISTOGRAM_CUSTOM_COUNTS(
+          "Renderer4.PictureRasterTimeUS",
+          (current_rasterize_time - prev_rasterize_time).InMicroseconds(),
+          0,
+          100000,
+          100);
+    }
+  }
+
+  PicturePileImpl::Analysis analysis_;
+  scoped_refptr<PicturePileImpl> picture_pile_;
+  gfx::Rect content_rect_;
+  float contents_scale_;
+  RasterMode raster_mode_;
+  TileResolution tile_resolution_;
+  int layer_id_;
+  const void* tile_id_;
+  int source_frame_number_;
+  bool analyze_picture_;
+  RenderingStatsInstrumentation* rendering_stats_;
+  const base::Callback<void(const PicturePileImpl::Analysis&, bool)> reply_;
+  SkCanvas* canvas_;
+
+  DISALLOW_COPY_AND_ASSIGN(RasterWorkerPoolTaskImpl);
+};
+
+class ImageDecodeWorkerPoolTaskImpl : public internal::WorkerPoolTask {
+ public:
+  ImageDecodeWorkerPoolTaskImpl(
+      SkPixelRef* pixel_ref,
+      int layer_id,
+      RenderingStatsInstrumentation* rendering_stats,
+      const base::Callback<void(bool was_canceled)>& reply)
+      : pixel_ref_(skia::SharePtr(pixel_ref)),
+        layer_id_(layer_id),
+        rendering_stats_(rendering_stats),
+        reply_(reply) {}
+
+  // Overridden from internal::Task:
+  virtual void RunOnWorkerThread() OVERRIDE {
+    TRACE_EVENT0("cc", "ImageDecodeWorkerPoolTaskImpl::RunOnWorkerThread");
+    Decode();
+  }
+
+  // Overridden from internal::WorkerPoolTask:
+  virtual void ScheduleOnOriginThread(internal::WorkerPoolTaskClient* client)
+      OVERRIDE {}
+  virtual void RunOnOriginThread() OVERRIDE {
+    TRACE_EVENT0("cc", "ImageDecodeWorkerPoolTaskImpl::RunOnOriginThread");
+    Decode();
+  }
+  virtual void CompleteOnOriginThread(internal::WorkerPoolTaskClient* client)
+      OVERRIDE {}
+  virtual void RunReplyOnOriginThread() OVERRIDE {
+    reply_.Run(!HasFinishedRunning());
+  }
+
+ protected:
+  virtual ~ImageDecodeWorkerPoolTaskImpl() {}
+
+ private:
+  void Decode() {
+    devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
+        pixel_ref_.get());
+    // This will cause the image referred to by pixel ref to be decoded.
+    pixel_ref_->lockPixels();
+    pixel_ref_->unlockPixels();
+  }
+
+  skia::RefPtr<SkPixelRef> pixel_ref_;
+  int layer_id_;
+  RenderingStatsInstrumentation* rendering_stats_;
+  const base::Callback<void(bool was_canceled)> reply_;
+
+  DISALLOW_COPY_AND_ASSIGN(ImageDecodeWorkerPoolTaskImpl);
+};
+
 const size_t kScheduledRasterTasksLimit = 32u;
 
 // Memory limit policy works by mapping some bin states to the NEVER bin.
@@ -868,14 +1116,14 @@
 scoped_refptr<internal::WorkerPoolTask> TileManager::CreateImageDecodeTask(
     Tile* tile,
     SkPixelRef* pixel_ref) {
-  return RasterWorkerPool::CreateImageDecodeTask(
+  return make_scoped_refptr(new ImageDecodeWorkerPoolTaskImpl(
       pixel_ref,
       tile->layer_id(),
       rendering_stats_instrumentation_,
       base::Bind(&TileManager::OnImageDecodeTaskCompleted,
                  base::Unretained(this),
                  tile->layer_id(),
-                 base::Unretained(pixel_ref)));
+                 base::Unretained(pixel_ref))));
 }
 
 scoped_refptr<internal::RasterWorkerPoolTask> TileManager::CreateRasterTask(
@@ -917,7 +1165,7 @@
   // gpu rasterization where there is no upload.
   bool analyze_picture = !tile->use_gpu_rasterization();
 
-  return RasterWorkerPool::CreateRasterTask(
+  return make_scoped_refptr(new RasterWorkerPoolTaskImpl(
       const_resource,
       tile->picture_pile(),
       tile->content_rect(),
@@ -934,7 +1182,7 @@
                  tile->id(),
                  base::Passed(&resource),
                  mts.raster_mode),
-      &decode_tasks);
+      &decode_tasks));
 }
 
 void TileManager::OnImageDecodeTaskCompleted(int layer_id,
diff --git a/cc/resources/ui_resource_bitmap.cc b/cc/resources/ui_resource_bitmap.cc
index 562e13a..58df9d9 100644
--- a/cc/resources/ui_resource_bitmap.cc
+++ b/cc/resources/ui_resource_bitmap.cc
@@ -13,7 +13,7 @@
 namespace cc {
 
 void UIResourceBitmap::Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
-                              gfx::Size size,
+                              const gfx::Size& size,
                               UIResourceFormat format) {
   DCHECK(size.width());
   DCHECK(size.height());
@@ -29,7 +29,7 @@
 }
 
 UIResourceBitmap::UIResourceBitmap(const SkBitmap& skbitmap) {
-  DCHECK_EQ(skbitmap.config(), SkBitmap::kARGB_8888_Config);
+  DCHECK_EQ(skbitmap.colorType(), kPMColor_SkColorType);
   DCHECK_EQ(skbitmap.width(), skbitmap.rowBytesAsPixels());
   DCHECK(skbitmap.isImmutable());
 
@@ -41,8 +41,19 @@
   SetOpaque(skbitmap.isOpaque());
 }
 
+UIResourceBitmap::UIResourceBitmap(const gfx::Size& size, bool is_opaque) {
+  SkAlphaType alphaType = is_opaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType;
+  SkImageInfo info =
+      SkImageInfo::MakeN32(size.width(), size.height(), alphaType);
+  skia::RefPtr<SkPixelRef> pixel_ref = skia::AdoptRef(
+      SkMallocPixelRef::NewAllocate(info, info.minRowBytes(), NULL));
+  pixel_ref->setImmutable();
+  Create(pixel_ref, size, UIResourceBitmap::RGBA8);
+  SetOpaque(is_opaque);
+}
+
 UIResourceBitmap::UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref,
-                                   gfx::Size size) {
+                                   const gfx::Size& size) {
   Create(pixel_ref, size, UIResourceBitmap::ETC1);
 }
 
diff --git a/cc/resources/ui_resource_bitmap.h b/cc/resources/ui_resource_bitmap.h
index 2cce0b3..b8863d8 100644
--- a/cc/resources/ui_resource_bitmap.h
+++ b/cc/resources/ui_resource_bitmap.h
@@ -44,14 +44,16 @@
   // User must ensure that |skbitmap| is immutable.  The SkBitmap Format should
   // be 32-bit RGBA.
   explicit UIResourceBitmap(const SkBitmap& skbitmap);
-  UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref, gfx::Size size);
+  UIResourceBitmap(const gfx::Size& size, bool is_opaque);
+  UIResourceBitmap(const skia::RefPtr<SkPixelRef>& pixel_ref,
+                   const gfx::Size& size);
   ~UIResourceBitmap();
 
  private:
   friend class AutoLockUIResourceBitmap;
 
   void Create(const skia::RefPtr<SkPixelRef>& pixel_ref,
-              gfx::Size size,
+              const gfx::Size& size,
               UIResourceFormat format);
 
   skia::RefPtr<SkPixelRef> pixel_ref_;
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
index dee285a..df42874 100644
--- a/cc/resources/video_resource_updater.cc
+++ b/cc/resources/video_resource_updater.cc
@@ -58,12 +58,6 @@
 
 bool VideoResourceUpdater::VerifyFrame(
     const scoped_refptr<media::VideoFrame>& video_frame) {
-  // If these fail, we'll have to add logic that handles offset bitmap/texture
-  // UVs. For now, just expect (0, 0) offset, since all our decoders so far
-  // don't offset.
-  DCHECK_EQ(video_frame->visible_rect().x(), 0);
-  DCHECK_EQ(video_frame->visible_rect().y(), 0);
-
   switch (video_frame->format()) {
     // Acceptable inputs.
     case media::VideoFrame::YV12:
@@ -87,35 +81,16 @@
 // For frames that we receive in software format, determine the dimensions of
 // each plane in the frame.
 static gfx::Size SoftwarePlaneDimension(
-    media::VideoFrame::Format input_frame_format,
-    const gfx::Size& coded_size,
+    const scoped_refptr<media::VideoFrame>& input_frame,
     ResourceFormat output_resource_format,
-    int plane_index) {
+    size_t plane_index) {
   if (output_resource_format == kYUVResourceFormat) {
-    if (plane_index == media::VideoFrame::kYPlane ||
-        plane_index == media::VideoFrame::kAPlane)
-      return coded_size;
-
-    switch (input_frame_format) {
-      case media::VideoFrame::YV12:
-      case media::VideoFrame::YV12A:
-      case media::VideoFrame::YV12J:
-        return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 0.5f));
-      case media::VideoFrame::YV16:
-        return gfx::ToFlooredSize(gfx::ScaleSize(coded_size, 0.5f, 1.f));
-
-      case media::VideoFrame::UNKNOWN:
-      case media::VideoFrame::I420:
-      case media::VideoFrame::NATIVE_TEXTURE:
-#if defined(VIDEO_HOLE)
-      case media::VideoFrame::HOLE:
-#endif  // defined(VIDEO_HOLE)
-        NOTREACHED();
-    }
+    return media::VideoFrame::PlaneSize(
+        input_frame->format(), plane_index, input_frame->coded_size());
   }
 
   DCHECK_EQ(output_resource_format, kRGBResourceFormat);
-  return coded_size;
+  return input_frame->coded_size();
 }
 
 VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
@@ -144,8 +119,7 @@
   bool software_compositor = context_provider_ == NULL;
 
   ResourceFormat output_resource_format = kYUVResourceFormat;
-  size_t output_plane_count =
-      (input_frame_format == media::VideoFrame::YV12A) ? 4 : 3;
+  size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format);
 
   // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB
   // conversion here. That involves an extra copy of each frame to a bitmap.
@@ -157,17 +131,12 @@
   }
 
   int max_resource_size = resource_provider_->max_texture_size();
-  gfx::Size coded_frame_size = video_frame->coded_size();
-
   std::vector<PlaneResource> plane_resources;
   bool allocation_success = true;
 
   for (size_t i = 0; i < output_plane_count; ++i) {
     gfx::Size output_plane_resource_size =
-        SoftwarePlaneDimension(input_frame_format,
-                               coded_frame_size,
-                               output_resource_format,
-                               i);
+        SoftwarePlaneDimension(video_frame, output_resource_format, i);
     if (output_plane_resource_size.IsEmpty() ||
         output_plane_resource_size.width() > max_resource_size ||
         output_plane_resource_size.height() > max_resource_size) {
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index 4d06101..5b108bb 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -97,8 +97,7 @@
                       source.output_rect,
                       source.damage_rect,
                       source.transform_to_root_target,
-                      source.has_transparent_background,
-                      source.overlay_state);
+                      source.has_transparent_background);
 
     // Contributing passes aggregated in to the pass list need to take the
     // transform of the surface quad into account to update their transform to
@@ -204,8 +203,7 @@
                       source.output_rect,
                       source.damage_rect,
                       source.transform_to_root_target,
-                      source.has_transparent_background,
-                      source.overlay_state);
+                      source.has_transparent_background);
 
     CopyQuadsToPass(source.quad_list,
                     source.shared_quad_state_list,
diff --git a/cc/test/data/yuv_stripes.png b/cc/test/data/yuv_stripes.png
new file mode 100644
index 0000000..aaa6ec4
--- /dev/null
+++ b/cc/test/data/yuv_stripes.png
Binary files differ
diff --git a/cc/test/data/yuv_stripes_alpha.png b/cc/test/data/yuv_stripes_alpha.png
new file mode 100644
index 0000000..7c90de4
--- /dev/null
+++ b/cc/test/data/yuv_stripes_alpha.png
Binary files differ
diff --git a/cc/test/data/yuv_stripes_offset.png b/cc/test/data/yuv_stripes_offset.png
new file mode 100644
index 0000000..d6b344b
--- /dev/null
+++ b/cc/test/data/yuv_stripes_offset.png
Binary files differ
diff --git a/cc/test/fake_content_layer_client.cc b/cc/test/fake_content_layer_client.cc
index 563e945..2d1c304 100644
--- a/cc/test/fake_content_layer_client.cc
+++ b/cc/test/fake_content_layer_client.cc
@@ -39,4 +39,6 @@
   }
 }
 
+bool FakeContentLayerClient::FillsBoundsCompletely() const { return false; }
+
 }  // namespace cc
diff --git a/cc/test/fake_content_layer_client.h b/cc/test/fake_content_layer_client.h
index 1f8a1c6..8410f3e 100644
--- a/cc/test/fake_content_layer_client.h
+++ b/cc/test/fake_content_layer_client.h
@@ -31,6 +31,7 @@
                              const gfx::Rect& rect,
                              gfx::RectF* opaque_rect) OVERRIDE;
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
+  virtual bool FillsBoundsCompletely() const OVERRIDE;
 
   void set_paint_all_opaque(bool opaque) { paint_all_opaque_ = opaque; }
 
diff --git a/cc/test/fake_scoped_ui_resource.cc b/cc/test/fake_scoped_ui_resource.cc
index bf86f54..0631cd8 100644
--- a/cc/test/fake_scoped_ui_resource.cc
+++ b/cc/test/fake_scoped_ui_resource.cc
@@ -11,11 +11,8 @@
 namespace {
 
 UIResourceBitmap CreateMockUIResourceBitmap() {
-  SkBitmap skbitmap;
-  skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
-  skbitmap.allocPixels();
-  skbitmap.setImmutable();
-  return UIResourceBitmap(skbitmap);
+  bool is_opaque = false;
+  return UIResourceBitmap(gfx::Size(1, 1), is_opaque);
 }
 
 }  // anonymous namespace
diff --git a/cc/test/fake_video_frame_provider.h b/cc/test/fake_video_frame_provider.h
index 972d8f8..fc462e4 100644
--- a/cc/test/fake_video_frame_provider.h
+++ b/cc/test/fake_video_frame_provider.h
@@ -21,6 +21,8 @@
   virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>&)
       OVERRIDE {}
 
+  Client* client() { return client_; }
+
   void set_frame(const scoped_refptr<media::VideoFrame>& frame) {
     frame_ = frame;
   }
diff --git a/cc/test/layer_test_common.cc b/cc/test/layer_test_common.cc
index 31a16e1..a3ab907 100644
--- a/cc/test/layer_test_common.cc
+++ b/cc/test/layer_test_common.cc
@@ -72,12 +72,18 @@
   // Quads that are fully occluded on one axis only should be shrunken.
   for (size_t i = 0; i < quads.size(); ++i) {
     DrawQuad* quad = quads[i];
-    bool fully_occluded_horizontal = quad->rect.x() >= occluded.x() &&
-                                     quad->rect.right() <= occluded.right();
-    bool fully_occluded_vertical = quad->rect.y() >= occluded.y() &&
-                                   quad->rect.bottom() <= occluded.bottom();
+    DCHECK(quad->quadTransform().IsIdentityOrIntegerTranslation());
+    gfx::Rect target_rect =
+        MathUtil::MapEnclosingClippedRect(quad->quadTransform(), quad->rect);
+    gfx::Rect target_visible_rect = MathUtil::MapEnclosingClippedRect(
+        quad->quadTransform(), quad->visible_rect);
+
+    bool fully_occluded_horizontal = target_rect.x() >= occluded.x() &&
+                                     target_rect.right() <= occluded.right();
+    bool fully_occluded_vertical = target_rect.y() >= occluded.y() &&
+                                   target_rect.bottom() <= occluded.bottom();
     bool should_be_occluded =
-        quad->rect.Intersects(occluded) &&
+        target_rect.Intersects(occluded) &&
         (fully_occluded_vertical || fully_occluded_horizontal);
     if (!should_be_occluded) {
       EXPECT_EQ(quad->rect.ToString(), quad->visible_rect.ToString());
@@ -114,10 +120,35 @@
   AppendQuadsData data;
 
   quad_culler_.clear_lists();
-  quad_culler_.set_occluded_content_rect(occluded);
+  quad_culler_.set_occluded_target_rect(occluded);
   layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider());
   layer_impl->AppendQuads(&quad_culler_, &data);
   layer_impl->DidDraw(resource_provider());
 }
 
+void LayerTestCommon::LayerImplTest::AppendQuadsForPassWithOcclusion(
+    LayerImpl* layer_impl,
+    const RenderPass::Id& id,
+    const gfx::Rect& occluded) {
+  AppendQuadsData data(id);
+
+  quad_culler_.clear_lists();
+  quad_culler_.set_occluded_target_rect(occluded);
+  layer_impl->WillDraw(DRAW_MODE_HARDWARE, resource_provider());
+  layer_impl->AppendQuads(&quad_culler_, &data);
+  layer_impl->DidDraw(resource_provider());
+}
+
+void LayerTestCommon::LayerImplTest::AppendSurfaceQuadsWithOcclusion(
+    RenderSurfaceImpl* surface_impl,
+    const gfx::Rect& occluded) {
+  AppendQuadsData data;
+
+  quad_culler_.clear_lists();
+  quad_culler_.set_occluded_target_rect_for_contributing_surface(occluded);
+  bool for_replica = false;
+  RenderPass::Id id(1, 1);
+  surface_impl->AppendQuads(&quad_culler_, &data, for_replica, id);
+}
+
 }  // namespace cc
diff --git a/cc/test/layer_test_common.h b/cc/test/layer_test_common.h
index cb56417..2cbd563 100644
--- a/cc/test/layer_test_common.h
+++ b/cc/test/layer_test_common.h
@@ -28,8 +28,10 @@
 namespace gfx { class Rect; }
 
 namespace cc {
+class LayerImpl;
 class OutputSurface;
 class QuadList;
+class RenderSurfaceImpl;
 class ResourceProvider;
 
 class LayerTestCommon {
@@ -78,6 +80,11 @@
     void CalcDrawProps(const gfx::Size& viewport_size);
     void AppendQuadsWithOcclusion(LayerImpl* layer_impl,
                                   const gfx::Rect& occluded);
+    void AppendQuadsForPassWithOcclusion(LayerImpl* layer_impl,
+                                         const RenderPass::Id& id,
+                                         const gfx::Rect& occluded);
+    void AppendSurfaceQuadsWithOcclusion(RenderSurfaceImpl* surface_impl,
+                                         const gfx::Rect& occluded);
 
     OutputSurface* output_surface() const {
       return host_->host_impl()->output_surface();
@@ -85,6 +92,7 @@
     ResourceProvider* resource_provider() const {
       return host_->host_impl()->resource_provider();
     }
+    LayerImpl* root_layer() const { return root_layer_impl_.get(); }
     FakeLayerTreeHostImpl* host_impl() const { return host_->host_impl(); }
     Proxy* proxy() const { return host_->host_impl()->proxy(); }
     const QuadList& quad_list() const { return quad_culler_.quad_list(); }
diff --git a/cc/test/layer_tree_json_parser.cc b/cc/test/layer_tree_json_parser.cc
index e543f1d..1634868 100644
--- a/cc/test/layer_tree_json_parser.cc
+++ b/cc/test/layer_tree_json_parser.cc
@@ -69,8 +69,7 @@
     scoped_refptr<NinePatchLayer> nine_patch_layer = NinePatchLayer::Create();
 
     SkBitmap bitmap;
-    bitmap.setConfig(SkBitmap::kARGB_8888_Config, image_width, image_height);
-    bitmap.allocPixels(NULL, NULL);
+    bitmap.allocN32Pixels(image_width, image_height);
     bitmap.setImmutable();
     nine_patch_layer->SetBitmap(bitmap);
     nine_patch_layer->SetAperture(
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc
index 7ae11c3..a282cc4 100644
--- a/cc/test/layer_tree_pixel_test.cc
+++ b/cc/test/layer_tree_pixel_test.cc
@@ -268,12 +268,8 @@
   gl->DeleteTextures(1, &texture_id);
 
   scoped_ptr<SkBitmap> bitmap(new SkBitmap);
-  bitmap->setConfig(SkBitmap::kARGB_8888_Config,
-                    size.width(),
-                    size.height());
-  bitmap->allocPixels();
+  bitmap->allocN32Pixels(size.width(), size.height());
 
-  scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap));
   uint8* out_pixels = static_cast<uint8*>(bitmap->getPixels());
 
   size_t row_bytes = size.width() * 4;
@@ -324,7 +320,7 @@
   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
-  DCHECK_EQ(SkBitmap::kARGB_8888_Config, bitmap.getConfig());
+  DCHECK_EQ(kPMColor_SkColorType, bitmap.colorType());
 
   {
     SkAutoLockPixels lock(bitmap);
diff --git a/cc/test/mock_quad_culler.cc b/cc/test/mock_quad_culler.cc
index d15f126..781647d 100644
--- a/cc/test/mock_quad_culler.cc
+++ b/cc/test/mock_quad_culler.cc
@@ -4,6 +4,7 @@
 
 #include "cc/test/mock_quad_culler.h"
 
+#include "cc/base/math_util.h"
 #include "cc/quads/draw_quad.h"
 
 namespace cc {
@@ -30,8 +31,32 @@
 gfx::Rect MockQuadCuller::UnoccludedContentRect(
     const gfx::Rect& content_rect,
     const gfx::Transform& draw_transform) {
-  gfx::Rect result = content_rect;
-  result.Subtract(occluded_content_rect_);
+  DCHECK(draw_transform.IsIdentityOrIntegerTranslation() ||
+         occluded_target_rect_.IsEmpty());
+  gfx::Rect target_rect =
+      MathUtil::MapEnclosingClippedRect(draw_transform, content_rect);
+  target_rect.Subtract(occluded_target_rect_);
+  gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
+  if (!draw_transform.GetInverse(&inverse_draw_transform))
+    NOTREACHED();
+  gfx::Rect result = MathUtil::ProjectEnclosingClippedRect(
+      inverse_draw_transform, target_rect);
+  return result;
+}
+
+gfx::Rect MockQuadCuller::UnoccludedContributingSurfaceContentRect(
+    const gfx::Rect& content_rect,
+    const gfx::Transform& draw_transform) {
+  DCHECK(draw_transform.IsIdentityOrIntegerTranslation() ||
+         occluded_target_rect_for_contributing_surface_.IsEmpty());
+  gfx::Rect target_rect =
+      MathUtil::MapEnclosingClippedRect(draw_transform, content_rect);
+  target_rect.Subtract(occluded_target_rect_for_contributing_surface_);
+  gfx::Transform inverse_draw_transform(gfx::Transform::kSkipInitialization);
+  if (!draw_transform.GetInverse(&inverse_draw_transform))
+    NOTREACHED();
+  gfx::Rect result = MathUtil::ProjectEnclosingClippedRect(
+      inverse_draw_transform, target_rect);
   return result;
 }
 
diff --git a/cc/test/mock_quad_culler.h b/cc/test/mock_quad_culler.h
index 543b8ec..541f66b 100644
--- a/cc/test/mock_quad_culler.h
+++ b/cc/test/mock_quad_culler.h
@@ -26,6 +26,9 @@
   virtual gfx::Rect UnoccludedContentRect(const gfx::Rect& content_rect,
                                           const gfx::Transform& draw_transform)
       OVERRIDE;
+  virtual gfx::Rect UnoccludedContributingSurfaceContentRect(
+      const gfx::Rect& content_rect,
+      const gfx::Transform& draw_transform) OVERRIDE;
   virtual bool MaybeAppend(scoped_ptr<DrawQuad> draw_quad) OVERRIDE;
   virtual void Append(scoped_ptr<DrawQuad> draw_quad) OVERRIDE;
 
@@ -34,8 +37,13 @@
     return *active_shared_quad_state_list_;
   }
 
-  void set_occluded_content_rect(const gfx::Rect& occluded) {
-    occluded_content_rect_ = occluded;
+  void set_occluded_target_rect(const gfx::Rect& occluded) {
+    occluded_target_rect_ = occluded;
+  }
+
+  void set_occluded_target_rect_for_contributing_surface(
+      const gfx::Rect& occluded) {
+    occluded_target_rect_for_contributing_surface_ = occluded;
   }
 
   void clear_lists() {
@@ -48,7 +56,8 @@
   QuadList quad_list_storage_;
   SharedQuadStateList* active_shared_quad_state_list_;
   SharedQuadStateList shared_quad_state_storage_;
-  gfx::Rect occluded_content_rect_;
+  gfx::Rect occluded_target_rect_;
+  gfx::Rect occluded_target_rect_for_contributing_surface_;
 };
 
 }  // namespace cc
diff --git a/cc/test/render_pass_test_common.cc b/cc/test/render_pass_test_common.cc
index 70df149..56e2b07 100644
--- a/cc/test/render_pass_test_common.cc
+++ b/cc/test/render_pass_test_common.cc
@@ -230,7 +230,7 @@
                    rect,
                    opaque_rect,
                    visible_rect,
-                   gfx::Size(100, 100),
+                   gfx::RectF(0, 0, 100, 100),
                    plane_resources[0],
                    plane_resources[1],
                    plane_resources[2],
diff --git a/cc/test/skia_common.cc b/cc/test/skia_common.cc
index 277a124..7d1c3b8 100644
--- a/cc/test/skia_common.cc
+++ b/cc/test/skia_common.cc
@@ -15,26 +15,19 @@
 void DrawPicture(unsigned char* buffer,
                  const gfx::Rect& layer_rect,
                  scoped_refptr<Picture> picture) {
+  SkImageInfo info =
+      SkImageInfo::MakeN32Premul(layer_rect.width(), layer_rect.height());
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config,
-                   layer_rect.width(),
-                   layer_rect.height());
-  bitmap.setPixels(buffer);
+  bitmap.installPixels(info, buffer, info.minRowBytes());
   SkCanvas canvas(bitmap);
   canvas.clipRect(gfx::RectToSkRect(layer_rect));
   picture->Raster(&canvas, NULL, layer_rect, 1.0f);
 }
 
 void CreateBitmap(const gfx::Size& size, const char* uri, SkBitmap* bitmap) {
-  SkImageInfo info = {
-    size.width(),
-    size.height(),
-    kPMColor_SkColorType,
-    kPremul_SkAlphaType
-  };
+  SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
 
-  bitmap->setConfig(info);
-  bitmap->allocPixels();
+  bitmap->allocPixels(info);
   bitmap->pixelRef()->setImmutable();
   bitmap->pixelRef()->setURI(uri);
 }
diff --git a/cc/test/solid_color_content_layer_client.cc b/cc/test/solid_color_content_layer_client.cc
index 2f0d1df..5e9d37e 100644
--- a/cc/test/solid_color_content_layer_client.cc
+++ b/cc/test/solid_color_content_layer_client.cc
@@ -26,4 +26,8 @@
     *opaque_rect = rect;
 }
 
+bool SolidColorContentLayerClient::FillsBoundsCompletely() const {
+  return false;
+}
+
 }  // namespace cc
diff --git a/cc/test/solid_color_content_layer_client.h b/cc/test/solid_color_content_layer_client.h
index eaca9e7..d854004 100644
--- a/cc/test/solid_color_content_layer_client.h
+++ b/cc/test/solid_color_content_layer_client.h
@@ -20,6 +20,7 @@
   virtual void PaintContents(SkCanvas* canvas,
                              const gfx::Rect& rect,
                              gfx::RectF* opaque_rect) OVERRIDE;
+  virtual bool FillsBoundsCompletely() const OVERRIDE;
 
  private:
   SkColor color_;
diff --git a/cc/test/test_context_support.cc b/cc/test/test_context_support.cc
index 3c2e31a..0e668aa 100644
--- a/cc/test/test_context_support.cc
+++ b/cc/test/test_context_support.cc
@@ -56,6 +56,11 @@
   set_visible_callback_ = set_visible_callback;
 }
 
+void TestContextSupport::SetScheduleOverlayPlaneCallback(
+    const ScheduleOverlayPlaneCallback& schedule_overlay_plane_callback) {
+  schedule_overlay_plane_callback_ = schedule_overlay_plane_callback;
+}
+
 void TestContextSupport::Swap() {
   last_swap_type_ = SWAP;
   base::MessageLoop::current()->PostTask(
@@ -71,6 +76,20 @@
                             weak_ptr_factory_.GetWeakPtr()));
 }
 
+void TestContextSupport::ScheduleOverlayPlane(int plane_z_order,
+                                              unsigned plane_transform,
+                                              unsigned overlay_texture_id,
+                                              const gfx::Rect& display_bounds,
+                                              const gfx::RectF& uv_rect) {
+  if (!schedule_overlay_plane_callback_.is_null()) {
+    schedule_overlay_plane_callback_.Run(plane_z_order,
+                                         plane_transform,
+                                         overlay_texture_id,
+                                         display_bounds,
+                                         uv_rect);
+  }
+}
+
 void TestContextSupport::SetSwapBuffersCompleteCallback(
     const base::Closure& callback) {
   swap_buffers_complete_callback_ = callback;
diff --git a/cc/test/test_context_support.h b/cc/test/test_context_support.h
index 7ae657c..9fd5d1d 100644
--- a/cc/test/test_context_support.h
+++ b/cc/test/test_context_support.h
@@ -29,6 +29,11 @@
   virtual void PartialSwapBuffers(const gfx::Rect& sub_buffer) OVERRIDE;
   virtual void SetSwapBuffersCompleteCallback(
       const base::Closure& callback) OVERRIDE;
+  virtual void ScheduleOverlayPlane(int plane_z_order,
+                                    unsigned plane_transform,
+                                    unsigned overlay_texture_id,
+                                    const gfx::Rect& display_bounds,
+                                    const gfx::RectF& uv_rect) OVERRIDE;
 
   void CallAllSyncPointCallbacks();
 
@@ -36,6 +41,15 @@
   void SetSurfaceVisibleCallback(
       const SurfaceVisibleCallback& set_visible_callback);
 
+  typedef base::Callback<void(int plane_z_order,
+                              unsigned plane_transform,
+                              unsigned overlay_texture_id,
+                              const gfx::Rect& display_bounds,
+                              const gfx::RectF& crop_rect)>
+      ScheduleOverlayPlaneCallback;
+  void SetScheduleOverlayPlaneCallback(
+      const ScheduleOverlayPlaneCallback& schedule_overlay_plane_callback);
+
   enum SwapType {
     NO_SWAP,
     SWAP,
@@ -52,6 +66,7 @@
 
   std::vector<base::Closure> sync_point_callbacks_;
   SurfaceVisibleCallback set_visible_callback_;
+  ScheduleOverlayPlaneCallback schedule_overlay_plane_callback_;
 
   base::Closure swap_buffers_complete_callback_;
 
diff --git a/cc/test/tiled_layer_test_common.cc b/cc/test/tiled_layer_test_common.cc
index a0dbfc7..430eddf 100644
--- a/cc/test/tiled_layer_test_common.cc
+++ b/cc/test/tiled_layer_test_common.cc
@@ -9,8 +9,7 @@
 FakeLayerUpdater::Resource::Resource(FakeLayerUpdater* layer,
                                      scoped_ptr<PrioritizedResource> texture)
     : LayerUpdater::Resource(texture.Pass()), layer_(layer) {
-  bitmap_.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
-  bitmap_.allocPixels();
+  bitmap_.allocN32Pixels(10, 10);
 }
 
 FakeLayerUpdater::Resource::~Resource() {}
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index f4bfada..2177280 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -1059,50 +1059,6 @@
   }
 }
 
-gfx::Vector2d LayerTreeHost::DistributeScrollOffsetToViewports(
-    const gfx::Vector2d offset,
-    Layer* layer) {
-  DCHECK(layer);
-  if (layer != outer_viewport_scroll_layer_.get())
-    return offset;
-
-  gfx::Vector2d inner_viewport_offset =
-      inner_viewport_scroll_layer_->scroll_offset();
-  gfx::Vector2d outer_viewport_offset =
-      outer_viewport_scroll_layer_->scroll_offset();
-
-  if (offset == inner_viewport_offset + outer_viewport_offset) {
-    // In this case, nothing should change, so we just return to the outer
-    // viewport the offset is already has.
-    return outer_viewport_offset;
-  }
-
-  // In the spirit of document-scrolls-first, we always want any change to
-  // go to the outer viewport first.
-  gfx::Vector2d max_outer_viewport_scroll_offset =
-      outer_viewport_scroll_layer_->MaxScrollOffset();
-  gfx::Vector2d max_inner_viewport_scroll_offset =
-      inner_viewport_scroll_layer_->MaxScrollOffset();
-
-  // TODO(bokan): This trips on zoom-out due to how Blink orders scale-scroll.
-  //              Disabled until that's sorted out: crbug.com/336574
-  // gfx::Vector2d total_max_scroll_offset =
-  //    max_outer_viewport_scroll_offset + max_inner_viewport_scroll_offset;
-  // DCHECK(total_max_scroll_offset.x() >= offset.x() &&
-  //       total_max_scroll_offset.y() >= offset.y());
-
-  outer_viewport_offset = offset - inner_viewport_offset;
-  outer_viewport_offset.SetToMin(max_outer_viewport_scroll_offset);
-  outer_viewport_offset.SetToMax(gfx::Vector2d());
-
-  inner_viewport_offset = offset - outer_viewport_offset;
-  inner_viewport_offset.SetToMin(max_inner_viewport_scroll_offset);
-  inner_viewport_offset.SetToMax(gfx::Vector2d());
-  inner_viewport_scroll_layer_->SetScrollOffset(inner_viewport_offset);
-
-  return outer_viewport_offset;
-}
-
 void LayerTreeHost::StartRateLimiter() {
   if (animating_)
     return;
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index 4564584..98ac83d 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -239,9 +239,6 @@
                                base::TimeDelta duration);
 
   void ApplyScrollAndScale(const ScrollAndScaleSet& info);
-  gfx::Vector2d DistributeScrollOffsetToViewports(const gfx::Vector2d offset,
-                                                  Layer* layer);
-
   void SetImplTransform(const gfx::Transform& transform);
 
   // Virtual for tests.
diff --git a/cc/trees/layer_tree_host_common_unittest.cc b/cc/trees/layer_tree_host_common_unittest.cc
index d6c7cf7..377dc86 100644
--- a/cc/trees/layer_tree_host_common_unittest.cc
+++ b/cc/trees/layer_tree_host_common_unittest.cc
@@ -199,6 +199,7 @@
                              const gfx::Rect& clip,
                              gfx::RectF* opaque) OVERRIDE {}
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
+  virtual bool FillsBoundsCompletely() const OVERRIDE { return false; }
 };
 
 scoped_refptr<ContentLayer> CreateDrawableContentLayer(
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 958419e..072e8e7 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -109,14 +109,10 @@
   if (!context_provider)
     return GL_TEXTURE_2D;
 
-  // TODO(reveman): Determine if GL_TEXTURE_EXTERNAL_OES works well on
-  // Android before we enable this. crbug.com/322780
-#if !defined(OS_ANDROID)
   if (context_provider->ContextCapabilities().gpu.egl_image_external)
     return GL_TEXTURE_EXTERNAL_OES;
   if (context_provider->ContextCapabilities().gpu.texture_rectangle)
     return GL_TEXTURE_RECTANGLE_ARB;
-#endif
 
   return GL_TEXTURE_2D;
 }
@@ -942,8 +938,7 @@
   if (should_background_tick)
     DCHECK(active_tree_->root_layer());
 
-  bool enabled = should_background_tick &&
-                 !animation_registrar_->active_animation_controllers().empty();
+  bool enabled = should_background_tick && needs_animate_layers();
 
   // Lazily create the time_source adapter so that we can vary the interval for
   // testing.
@@ -2272,8 +2267,14 @@
         break;
     }
 
-    if (layer_impl == InnerViewportScrollLayer())
+    if (layer_impl == InnerViewportScrollLayer()) {
       unused_root_delta.Subtract(applied_delta);
+      const float kOverscrollEpsilon = 0.01f;
+      if (std::abs(unused_root_delta.x()) < kOverscrollEpsilon)
+        unused_root_delta.set_x(0.0f);
+      if (std::abs(unused_root_delta.y()) < kOverscrollEpsilon)
+        unused_root_delta.set_y(0.0f);
+    }
 
     did_lock_scrolling_layer_ = true;
     if (!should_bubble_scrolls_) {
@@ -2314,7 +2315,7 @@
     accumulated_root_overscroll_.set_y(0);
 
   accumulated_root_overscroll_ += unused_root_delta;
-  bool did_overscroll = !gfx::ToRoundedVector2d(unused_root_delta).IsZero();
+  bool did_overscroll = !unused_root_delta.IsZero();
   if (did_overscroll && input_handler_client_) {
     DidOverscrollParams params;
     params.accumulated_overscroll = accumulated_root_overscroll_;
@@ -2460,8 +2461,7 @@
         scroll_layer_impl ? scroll_layer_impl->scrollbar_animation_controller()
                           : NULL;
     if (animation_controller) {
-      animation_controller->DidMouseMoveOffScrollbar(
-          CurrentPhysicalTimeTicks());
+      animation_controller->DidMouseMoveOffScrollbar(CurrentFrameTimeTicks());
       StartScrollbarAnimation();
     }
     scroll_layer_id_when_mouse_over_scrollbar_ = 0;
@@ -2490,7 +2490,7 @@
                  DeviceSpaceDistanceToLayer(device_viewport_point, *it));
 
   bool should_animate = animation_controller->DidMouseMoveNear(
-      CurrentPhysicalTimeTicks(), distance_to_scrollbar / device_scale_factor_);
+      CurrentFrameTimeTicks(), distance_to_scrollbar / device_scale_factor_);
   if (should_animate)
     StartScrollbarAnimation();
 }
@@ -2504,7 +2504,7 @@
       scroll_layer_id_when_mouse_over_scrollbar_ = scroll_layer_id;
       bool should_animate =
           layer_impl->scrollbar_animation_controller()->DidMouseMoveNear(
-              CurrentPhysicalTimeTicks(), 0);
+              CurrentFrameTimeTicks(), 0);
       if (should_animate)
         StartScrollbarAnimation();
     } else {
@@ -2682,7 +2682,7 @@
 
 void LayerTreeHostImpl::AnimateLayers(base::TimeTicks monotonic_time) {
   if (!settings_.accelerated_animation_enabled ||
-      animation_registrar_->active_animation_controllers().empty() ||
+      !needs_animate_layers() ||
       !active_tree_->root_layer())
     return;
 
@@ -2704,7 +2704,7 @@
 
 void LayerTreeHostImpl::UpdateAnimationState(bool start_ready_animations) {
   if (!settings_.accelerated_animation_enabled ||
-      animation_registrar_->active_animation_controllers().empty() ||
+      !needs_animate_layers() ||
       !active_tree_->root_layer())
     return;
 
@@ -2820,7 +2820,7 @@
 
 void LayerTreeHostImpl::StartScrollbarAnimation() {
   TRACE_EVENT0("cc", "LayerTreeHostImpl::StartScrollbarAnimation");
-  StartScrollbarAnimationRecursive(RootLayer(), CurrentPhysicalTimeTicks());
+  StartScrollbarAnimationRecursive(RootLayer(), CurrentFrameTimeTicks());
 }
 
 void LayerTreeHostImpl::StartScrollbarAnimationRecursive(LayerImpl* layer,
@@ -2852,22 +2852,21 @@
   DidModifyTilePriorities();
 }
 
+void LayerTreeHostImpl::UpdateCurrentFrameTime() {
+  DCHECK(current_frame_timeticks_.is_null());
+  current_frame_timeticks_ = gfx::FrameTime::Now();
+}
+
 void LayerTreeHostImpl::ResetCurrentFrameTimeForNextFrame() {
   current_frame_timeticks_ = base::TimeTicks();
 }
 
-void LayerTreeHostImpl::UpdateCurrentFrameTime(base::TimeTicks* ticks) const {
-  if (ticks->is_null()) {
-    *ticks = CurrentPhysicalTimeTicks();
-  }
-}
-
 base::TimeTicks LayerTreeHostImpl::CurrentFrameTimeTicks() {
-  UpdateCurrentFrameTime(&current_frame_timeticks_);
-  return current_frame_timeticks_;
-}
-
-base::TimeTicks LayerTreeHostImpl::CurrentPhysicalTimeTicks() const {
+  // Try to use the current frame time to keep animations non-jittery.  But if
+  // we're not in a frame (because this is during an input event or a delayed
+  // task), fall back to physical time.  This should still be monotonic.
+  if (!current_frame_timeticks_.is_null())
+    return current_frame_timeticks_;
   return gfx::FrameTime::Now();
 }
 
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 52c2c98..10477dc 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -388,11 +388,10 @@
 
   void SetTreePriority(TreePriority priority);
 
+  void UpdateCurrentFrameTime();
   void ResetCurrentFrameTimeForNextFrame();
   virtual base::TimeTicks CurrentFrameTimeTicks();
 
-  virtual base::TimeTicks CurrentPhysicalTimeTicks() const;
-
   scoped_ptr<base::Value> AsValue() const { return AsValueWithFrame(NULL); }
   scoped_ptr<base::Value> AsValueWithFrame(FrameData* frame) const;
   scoped_ptr<base::Value> ActivationStateAsValue() const;
@@ -505,8 +504,6 @@
   void AnimateScrollbarsRecursive(LayerImpl* layer,
                                   base::TimeTicks time);
 
-  void UpdateCurrentFrameTime(base::TimeTicks* ticks) const;
-
   LayerImpl* FindScrollLayerForDeviceViewportPoint(
       const gfx::PointF& device_viewport_point,
       InputHandler::ScrollInputType type,
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index bcbc6c3..351ec35 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1178,7 +1178,7 @@
                           manager,
                           0) {}
 
-  virtual base::TimeTicks CurrentPhysicalTimeTicks() const OVERRIDE {
+  virtual base::TimeTicks CurrentFrameTimeTicks() OVERRIDE {
     return fake_current_physical_time_;
   }
 
@@ -3162,6 +3162,42 @@
   EXPECT_EQ(gfx::Vector2dF(), host_impl_->current_fling_velocity());
 }
 
+TEST_F(LayerTreeHostImplTest, UnnecessaryGlowEffectCallsWhileScrollingUp) {
+  // Edge glow effect should be applicable only upon reaching Edges
+  // of the content. unnecessary glow effect calls shouldn't be
+  // called while scrolling up without reaching the edge of the content.
+  gfx::Size surface_size(100, 100);
+  gfx::Size content_size(200, 200);
+  scoped_ptr<LayerImpl> root_clip =
+      LayerImpl::Create(host_impl_->active_tree(), 3);
+  scoped_ptr<LayerImpl> root =
+      CreateScrollableLayer(1, content_size, root_clip.get());
+  root->SetIsContainerForFixedPositionLayers(true);
+  scoped_ptr<LayerImpl> child =
+      CreateScrollableLayer(2, content_size, root_clip.get());
+
+  child->SetScrollClipLayer(Layer::INVALID_ID);
+  root->AddChild(child.Pass());
+  root_clip->AddChild(root.Pass());
+
+  host_impl_->SetViewportSize(surface_size);
+  host_impl_->active_tree()->SetRootLayer(root_clip.Pass());
+  host_impl_->active_tree()->SetViewportLayersFromIds(3, 1, Layer::INVALID_ID);
+  host_impl_->active_tree()->DidBecomeActive();
+  DrawFrame();
+  {
+    EXPECT_EQ(InputHandler::ScrollStarted,
+              host_impl_->ScrollBegin(gfx::Point(0, 0), InputHandler::Wheel));
+    host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, 100));
+    EXPECT_EQ(gfx::Vector2dF().ToString(),
+              host_impl_->accumulated_root_overscroll().ToString());
+    host_impl_->ScrollBy(gfx::Point(), gfx::Vector2dF(0, -2.30f));
+    EXPECT_EQ(gfx::Vector2dF().ToString(),
+              host_impl_->accumulated_root_overscroll().ToString());
+    host_impl_->ScrollEnd();
+  }
+}
+
 class BlendStateCheckLayer : public LayerImpl {
  public:
   static scoped_ptr<LayerImpl> Create(LayerTreeImpl* tree_impl,
@@ -3696,13 +3732,9 @@
   host_impl_->SetViewportSize(DipSizeToPixelSize(viewport_size_));
   SetupActiveTreeLayers();
 
-  SkBitmap skbitmap;
-  skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
-  skbitmap.allocPixels();
-  skbitmap.setImmutable();
-
   // Specify an overhang bitmap to use.
-  UIResourceBitmap ui_resource_bitmap(skbitmap);
+  bool is_opaque = false;
+  UIResourceBitmap ui_resource_bitmap(gfx::Size(2, 2), is_opaque);
   ui_resource_bitmap.SetWrapMode(UIResourceBitmap::REPEAT);
   UIResourceId ui_resource_id = 12345;
   host_impl_->CreateUIResource(ui_resource_id, ui_resource_bitmap);
@@ -5632,13 +5664,9 @@
 
   EXPECT_EQ(0u, context3d->NumTextures());
 
-  SkBitmap skbitmap;
-  skbitmap.setConfig(SkBitmap::kARGB_8888_Config, 1, 1);
-  skbitmap.allocPixels();
-  skbitmap.setImmutable();
-
   UIResourceId ui_resource_id = 1;
-  UIResourceBitmap bitmap(skbitmap);
+  bool is_opaque = false;
+  UIResourceBitmap bitmap(gfx::Size(1, 1), is_opaque);
   host_impl_->CreateUIResource(ui_resource_id, bitmap);
   EXPECT_EQ(1u, context3d->NumTextures());
   ResourceProvider::ResourceId id1 =
diff --git a/cc/trees/layer_tree_host_pixeltest_masks.cc b/cc/trees/layer_tree_host_pixeltest_masks.cc
index 4e07199..913d63f 100644
--- a/cc/trees/layer_tree_host_pixeltest_masks.cc
+++ b/cc/trees/layer_tree_host_pixeltest_masks.cc
@@ -24,6 +24,8 @@
 
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
 
+  virtual bool FillsBoundsCompletely() const OVERRIDE { return false; }
+
   virtual void PaintContents(SkCanvas* canvas,
                              const gfx::Rect& rect,
                              gfx::RectF* opaque_rect) OVERRIDE {
@@ -76,8 +78,7 @@
   mask->SetBounds(gfx::Size(100, 100));
 
   SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 400, 400);
-  bitmap.allocPixels();
+  bitmap.allocN32Pixels(400, 400);
   SkCanvas canvas(bitmap);
   canvas.scale(SkIntToScalar(4), SkIntToScalar(4));
   MaskContentLayerClient client;
diff --git a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
index 5164027..8f6242d 100644
--- a/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
+++ b/cc/trees/layer_tree_host_pixeltest_on_demand_raster.cc
@@ -63,6 +63,8 @@
 
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE { }
 
+  virtual bool FillsBoundsCompletely() const OVERRIDE { return false; }
+
   virtual void PaintContents(SkCanvas* canvas,
                              const gfx::Rect& clip,
                              gfx::RectF* opaque) OVERRIDE {
diff --git a/cc/trees/layer_tree_host_pixeltest_readback.cc b/cc/trees/layer_tree_host_pixeltest_readback.cc
index e784535..e8ad466 100644
--- a/cc/trees/layer_tree_host_pixeltest_readback.cc
+++ b/cc/trees/layer_tree_host_pixeltest_readback.cc
@@ -1109,15 +1109,10 @@
       device_viewport_copy_rect.Intersect(device_viewport_copy_subrect_);
 
     scoped_ptr<SkBitmap> bitmap(new SkBitmap);
-    bitmap->setConfig(SkBitmap::kARGB_8888_Config,
-                      device_viewport_copy_rect.width(),
-                      device_viewport_copy_rect.height());
-    bitmap->allocPixels();
-    {
-      scoped_ptr<SkAutoLockPixels> lock(new SkAutoLockPixels(*bitmap));
-      layer_tree_host()->CompositeAndReadback(bitmap->getPixels(),
-                                              device_viewport_copy_rect);
-    }
+    bitmap->allocN32Pixels(device_viewport_copy_rect.width(),
+                           device_viewport_copy_rect.height());
+    layer_tree_host()->CompositeAndReadback(bitmap->getPixels(),
+                                            device_viewport_copy_rect);
 
     result_bitmap_ = bitmap.Pass();
     EndTest();
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index c3734df..785f7d1 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -1313,6 +1313,7 @@
       test_layer_->SetOpacity(0.f);
   }
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
+  virtual bool FillsBoundsCompletely() const OVERRIDE { return false; }
 
  private:
   Layer* test_layer_;
@@ -2042,8 +2043,7 @@
     texture_ = PrioritizedResource::Create(
         layer_tree_host()->contents_texture_manager());
     texture_->SetDimensions(gfx::Size(10, 10), RGBA_8888);
-    bitmap_.setConfig(SkBitmap::kARGB_8888_Config, 10, 10);
-    bitmap_.allocPixels();
+    bitmap_.allocN32Pixels(10, 10);
   }
 
   scoped_ptr<PrioritizedResource> texture_;
@@ -2595,6 +2595,7 @@
       ++lcd_notification_count_;
       layer_->SetNeedsDisplay();
     }
+    virtual bool FillsBoundsCompletely() const OVERRIDE { return false; }
 
    private:
     Layer* layer_;
@@ -2834,6 +2835,8 @@
 
     virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
 
+    virtual bool FillsBoundsCompletely() const OVERRIDE { return false; }
+
    private:
     Layer* layer_;
   };
@@ -3061,11 +3064,12 @@
   int frame_;
 };
 
-TEST_F(LayerTreeHostTestNumFramesPending, DelegatingRenderer) {
+// Flaky on all platforms: http://crbug.com/327498
+TEST_F(LayerTreeHostTestNumFramesPending, DISABLED_DelegatingRenderer) {
   RunTest(true, true, true);
 }
 
-TEST_F(LayerTreeHostTestNumFramesPending, GLRenderer) {
+TEST_F(LayerTreeHostTestNumFramesPending, DISABLED_GLRenderer) {
   RunTest(true, false, true);
 }
 
diff --git a/cc/trees/layer_tree_host_unittest_pinch_zoom.cc b/cc/trees/layer_tree_host_unittest_pinch_zoom.cc
deleted file mode 100644
index a77cbdc..0000000
--- a/cc/trees/layer_tree_host_unittest_pinch_zoom.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "cc/trees/layer_tree_host.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "cc/layers/layer.h"
-#include "cc/test/geometry_test_utils.h"
-#include "cc/test/layer_tree_test.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using gfx::Vector2d;
-
-namespace cc {
-namespace {
-
-class LayerTreeHostPinchZoomTest : public LayerTreeTest {};
-
-// Ensure that the DistributeScrollOffsetToViewports() method of LayerTreeHost
-// does not set values outside the scroll offset max.
-class LayerTreeHostPinchZoomTestDistributeScrollOffsetToViewports
-    : public LayerTreeHostPinchZoomTest {
- public:
-  // Sets up a 2X scale resulting in the following viewport configuration:
-  //    +------------------------------------------------+
-  //    |              |              |                  |
-  //    |              |              |                  |
-  //    |              |              |                  |
-  //    |  InnerClip   |5px           |                  |
-  //    |              |              |                  |
-  //    |              |              |10px              |
-  //    |--------------+              |                  |
-  //    |      5px                    |                  |
-  //    |                             |                  | 20px
-  //    | Inner Scroll/Outer Clip     |                  |
-  //    |                             |                  |
-  //    |-----------------------------+                  |
-  //    |             10px                               |
-  //    |                                                |
-  //    |                                                |
-  //    |                 Outer Scroll Layer             |
-  //    |                                                |
-  //    |                                                |
-  //    +------------------------------------------------+
-  //                         20px
-  //
-  virtual void SetupTree() OVERRIDE {
-    scoped_refptr<Layer> inner_viewport_clip_layer = Layer::Create();
-    scoped_refptr<Layer> page_scale_layer = Layer::Create();
-    scoped_refptr<Layer> inner_viewport_scroll_layer = Layer::Create();
-    scoped_refptr<Layer> outer_viewport_clip_layer = Layer::Create();
-    scoped_refptr<Layer> outer_viewport_scroll_layer = Layer::Create();
-
-    inner_viewport_scroll_layer->SetScrollClipLayerId(
-        inner_viewport_clip_layer->id());
-    inner_viewport_scroll_layer->SetUserScrollable(true, true);
-
-    inner_viewport_clip_layer->AddChild(page_scale_layer);
-    page_scale_layer->AddChild(inner_viewport_scroll_layer);
-
-    inner_viewport_scroll_layer->AddChild(outer_viewport_clip_layer);
-    outer_viewport_clip_layer->AddChild(outer_viewport_scroll_layer);
-
-    outer_viewport_scroll_layer->SetScrollClipLayerId(
-        outer_viewport_clip_layer->id());
-    outer_viewport_scroll_layer->SetUserScrollable(true, true);
-
-    layer_tree_host()->RegisterViewportLayers(page_scale_layer,
-        inner_viewport_scroll_layer,
-        outer_viewport_scroll_layer);
-
-    inner_viewport_clip_layer->SetBounds(gfx::Size(10, 10));
-    outer_viewport_clip_layer->SetAnchorPoint(gfx::PointF());
-    outer_viewport_clip_layer->SetBounds(gfx::Size(10, 10));
-
-    layer_tree_host()->SetRootLayer(inner_viewport_clip_layer);
-
-    inner_viewport_scroll_layer->SetBounds(gfx::Size(10, 10));
-    outer_viewport_scroll_layer->SetBounds(gfx::Size(20, 20));
-    layer_tree_host()->SetPageScaleFactorAndLimits(2.0f, 1.0f, 5.0f);
-
-    // Sanity check
-    EXPECT_VECTOR_EQ(Vector2d(5, 5),
-        inner_viewport_scroll_layer->MaxScrollOffset());
-    EXPECT_VECTOR_EQ(Vector2d(10, 10),
-        outer_viewport_scroll_layer->MaxScrollOffset());
-    EXPECT_VECTOR_EQ(Vector2d(0, 0),
-        inner_viewport_scroll_layer->scroll_offset());
-    EXPECT_VECTOR_EQ(Vector2d(0, 0),
-        outer_viewport_scroll_layer->scroll_offset());
-  }
-
-  virtual void BeginTest() OVERRIDE {
-    Layer *inner = layer_tree_host()->inner_viewport_scroll_layer();
-    Layer *outer = layer_tree_host()->outer_viewport_scroll_layer();
-
-    // Try to scroll beyond offset minium
-    gfx::Vector2d offset(-20, -20);
-    outer->SetScrollOffset(offset);
-    EXPECT_VECTOR_EQ(Vector2d(0, 0), inner->scroll_offset());
-    EXPECT_VECTOR_EQ(Vector2d(0, 0), outer->scroll_offset());
-
-    // Try to scroll beyond offset maximum
-    offset = gfx::Vector2d(20, 20);
-    outer->SetScrollOffset(offset);
-    EXPECT_VECTOR_EQ(Vector2d(5, 5), inner->scroll_offset());
-    EXPECT_VECTOR_EQ(Vector2d(10, 10), outer->scroll_offset());
-
-    EndTest();
-  }
-
-  virtual void AfterTest() OVERRIDE {}
-};
-
-TEST_F(LayerTreeHostPinchZoomTestDistributeScrollOffsetToViewports, Test) {
-    RunTest(true, false, false);
-}
-
-}  // namespace
-}  // namespace cc
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index ae3a421..c1fb010 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -255,8 +255,8 @@
 
   if (currently_scrolling_layer_ &&
       currently_scrolling_layer_->scrollbar_animation_controller())
-    currently_scrolling_layer_->scrollbar_animation_controller()->
-        DidScrollGestureEnd(CurrentPhysicalTimeTicks());
+    currently_scrolling_layer_->scrollbar_animation_controller()
+        ->DidScrollGestureEnd(CurrentFrameTimeTicks());
   currently_scrolling_layer_ = layer;
   if (layer && layer->scrollbar_animation_controller())
     layer->scrollbar_animation_controller()->DidScrollGestureBegin();
@@ -682,10 +682,6 @@
   return layer_tree_host_impl_->CurrentFrameTimeTicks();
 }
 
-base::TimeTicks LayerTreeImpl::CurrentPhysicalTimeTicks() const {
-  return layer_tree_host_impl_->CurrentPhysicalTimeTicks();
-}
-
 void LayerTreeImpl::SetNeedsCommit() {
   layer_tree_host_impl_->SetNeedsCommit();
 }
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 7dc9269..6ab1df1 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -80,7 +80,6 @@
   int MaxTextureSize() const;
   bool PinchGestureActive() const;
   base::TimeTicks CurrentFrameTimeTicks() const;
-  base::TimeTicks CurrentPhysicalTimeTicks() const;
   void SetNeedsCommit();
   gfx::Size DrawViewportSize() const;
   void StartScrollbarAnimation();
diff --git a/cc/trees/quad_culler.cc b/cc/trees/quad_culler.cc
index f161f64..68ef157 100644
--- a/cc/trees/quad_culler.cc
+++ b/cc/trees/quad_culler.cc
@@ -44,6 +44,13 @@
       layer_->render_target(), content_rect, draw_transform);
 }
 
+gfx::Rect QuadCuller::UnoccludedContributingSurfaceContentRect(
+    const gfx::Rect& content_rect,
+    const gfx::Transform& draw_transform) {
+  return occlusion_tracker_.UnoccludedContributingSurfaceContentRect(
+      layer_, content_rect, draw_transform);
+}
+
 static inline bool AppendQuadInternal(
     scoped_ptr<DrawQuad> draw_quad,
     const gfx::Rect& culled_rect,
diff --git a/cc/trees/quad_culler.h b/cc/trees/quad_culler.h
index 74aae6d..de2aa3e 100644
--- a/cc/trees/quad_culler.h
+++ b/cc/trees/quad_culler.h
@@ -30,6 +30,9 @@
   virtual gfx::Rect UnoccludedContentRect(const gfx::Rect& content_rect,
                                           const gfx::Transform& draw_transform)
       OVERRIDE;
+  virtual gfx::Rect UnoccludedContributingSurfaceContentRect(
+      const gfx::Rect& content_rect,
+      const gfx::Transform& draw_transform) OVERRIDE;
   virtual bool MaybeAppend(scoped_ptr<DrawQuad> draw_quad) OVERRIDE;
   virtual void Append(scoped_ptr<DrawQuad> draw_quad) OVERRIDE;
 
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 0008f0e..8a1547c 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -456,7 +456,7 @@
 
   // Sample the frame time now. This time will be used for updating animations
   // when we draw.
-  impl().layer_tree_host_impl->CurrentFrameTimeTicks();
+  impl().layer_tree_host_impl->UpdateCurrentFrameTime();
 
   impl().scheduler->BeginImplFrame(args);
 }
@@ -771,7 +771,7 @@
   scoped_ptr<BeginMainFrameAndCommitState> begin_main_frame_state(
       new BeginMainFrameAndCommitState);
   begin_main_frame_state->monotonic_frame_begin_time =
-      impl().layer_tree_host_impl->CurrentPhysicalTimeTicks();
+      impl().layer_tree_host_impl->CurrentFrameTimeTicks();
   begin_main_frame_state->scroll_info =
       impl().layer_tree_host_impl->ProcessScrollDeltas();
 
@@ -1629,7 +1629,7 @@
       impl().layer_tree_host_impl->IsCurrentlyScrolling() ||
       impl().layer_tree_host_impl->page_scale_animation_active();
 
-  base::TimeTicks now = impl().layer_tree_host_impl->CurrentPhysicalTimeTicks();
+  base::TimeTicks now = impl().layer_tree_host_impl->CurrentFrameTimeTicks();
 
   // Update expiration time if smoothness currently takes priority.
   if (smoothness_takes_priority) {
diff --git a/chrome/VERSION b/chrome/VERSION
index 54e232e..2389149 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
-MAJOR=35
+MAJOR=36
 MINOR=0
-BUILD=1903
+BUILD=1917
 PATCH=0
diff --git a/chrome/android/java/res/drawable-hdpi/dismiss.png b/chrome/android/java/res/drawable-hdpi/dismiss.png
new file mode 100644
index 0000000..4e86d73
--- /dev/null
+++ b/chrome/android/java/res/drawable-hdpi/dismiss.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-hdpi/infobar_incomplete.png b/chrome/android/java/res/drawable-hdpi/infobar_incomplete.png
deleted file mode 100644
index ecca086..0000000
--- a/chrome/android/java/res/drawable-hdpi/infobar_incomplete.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/dismiss.png b/chrome/android/java/res/drawable-xhdpi/dismiss.png
new file mode 100644
index 0000000..155de3f
--- /dev/null
+++ b/chrome/android/java/res/drawable-xhdpi/dismiss.png
Binary files differ
diff --git a/chrome/android/java/res/drawable-xhdpi/infobar_incomplete.png b/chrome/android/java/res/drawable-xhdpi/infobar_incomplete.png
deleted file mode 100644
index 8fad9ed..0000000
--- a/chrome/android/java/res/drawable-xhdpi/infobar_incomplete.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/drawable/app_banner_button_close.xml b/chrome/android/java/res/drawable/app_banner_button_close.xml
new file mode 100644
index 0000000..8111617
--- /dev/null
+++ b/chrome/android/java/res/drawable/app_banner_button_close.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright 2014 The Chromium Authors. All rights reserved.
+
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true" android:drawable="@color/app_banner_card_highlight" />
+    <item android:drawable="@android:color/transparent" />
+</selector>
diff --git a/chrome/android/java/res/drawable/dismiss.png b/chrome/android/java/res/drawable/dismiss.png
new file mode 100644
index 0000000..f77c4e5
--- /dev/null
+++ b/chrome/android/java/res/drawable/dismiss.png
Binary files differ
diff --git a/chrome/android/java/res/drawable/infobar_incomplete.png b/chrome/android/java/res/drawable/infobar_incomplete.png
deleted file mode 100644
index ed8fca1..0000000
--- a/chrome/android/java/res/drawable/infobar_incomplete.png
+++ /dev/null
Binary files differ
diff --git a/chrome/android/java/res/layout/app_banner_view.xml b/chrome/android/java/res/layout/app_banner_view.xml
index 0959be9..95928de 100644
--- a/chrome/android/java/res/layout/app_banner_view.xml
+++ b/chrome/android/java/res/layout/app_banner_view.xml
@@ -63,6 +63,16 @@
             android:layout_width="wrap_content"
             android:layout_height="@dimen/app_banner_star_height" />
 
+    <!-- Button that closes the banner. -->
+    <ImageButton
+            android:id="@+id/close_button"
+            android:adjustViewBounds="true"
+            android:src="@drawable/dismiss"
+            android:background="@drawable/app_banner_button_close"
+            android:padding="@dimen/app_banner_close_button_padding"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"/>
+
     <!-- View covering the entire banner.  Used to indicate the banner is highlighted. -->
     <View
             android:id="@+id/banner_highlight"
diff --git a/chrome/android/java/res/layout/share_dialog_item.xml b/chrome/android/java/res/layout/share_dialog_item.xml
new file mode 100644
index 0000000..64776d3
--- /dev/null
+++ b/chrome/android/java/res/layout/share_dialog_item.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2014 The Chromium Authors. All rights reserved.
+
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:background="?android:attr/selectableItemBackground"
+    android:orientation="horizontal" >
+    <ImageView android:id="@+id/icon"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:layout_marginStart="12dp"
+        android:padding="4dp"
+        android:scaleType="fitCenter" />
+    <TextView android:id="@+id/text"
+        android:layout_width="wrap_content"
+        android:layout_height="48dp"
+        android:gravity="start|center_vertical"
+        android:layout_marginStart="12dp"
+        android:maxLines="2"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+</LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/layout/three_button_menu_item.xml b/chrome/android/java/res/layout/three_button_menu_item.xml
index 8e104f1..ebc7353 100644
--- a/chrome/android/java/res/layout/three_button_menu_item.xml
+++ b/chrome/android/java/res/layout/three_button_menu_item.xml
@@ -19,9 +19,8 @@
         android:scaleType="center" />
 
     <View
-        android:layout_width="@dimen/menu_item_divider_width"
+        android:layout_width="1dp"
         android:layout_height="?android:attr/listPreferredItemHeightSmall"
-        android:layout_marginBottom="@dimen/menu_item_divider_width"
         android:background="?android:attr/listDivider" />
 
     <ImageButton
@@ -33,9 +32,8 @@
         android:scaleType="center" />
 
     <View
-        android:layout_width="@dimen/menu_item_divider_width"
+        android:layout_width="1dp"
         android:layout_height="?android:attr/listPreferredItemHeightSmall"
-        android:layout_marginBottom="@dimen/menu_item_divider_width"
         android:background="?android:attr/listDivider" />
 
     <ImageButton
diff --git a/chrome/android/java/res/layout/title_button_menu_item.xml b/chrome/android/java/res/layout/title_button_menu_item.xml
index 3305198..94c0850 100644
--- a/chrome/android/java/res/layout/title_button_menu_item.xml
+++ b/chrome/android/java/res/layout/title_button_menu_item.xml
@@ -23,18 +23,17 @@
         android:textAppearance="?android:attr/textAppearanceLargePopupMenu" />
 
     <View
-        android:layout_width="@dimen/menu_item_divider_width"
+        android:id="@+id/divider"
+        android:layout_width="1dp"
         android:layout_height="match_parent"
-        android:layout_marginBottom="@dimen/menu_item_divider_width"
         android:background="?android:attr/listDivider" />
 
     <ImageButton
         android:id="@+id/button"
-        android:layout_width="wrap_content"
-        android:layout_height="match_parent"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
         android:background="?android:attr/selectableItemBackground"
-        android:paddingEnd="10dp"
-        android:paddingStart="10dp"
-        android:scaleType="center" />
+        android:padding="10dp"
+        android:scaleType="fitCenter" />
 
 </LinearLayout>
\ No newline at end of file
diff --git a/chrome/android/java/res/values-hdpi/dimens.xml b/chrome/android/java/res/values-hdpi/dimens.xml
deleted file mode 100644
index 18e1a69..0000000
--- a/chrome/android/java/res/values-hdpi/dimens.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2013 The Chromium Authors. All rights reserved.
-
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file.
--->
-
-<resources>
-    <!-- Custom Menu dimensions -->
-    <dimen name="menu_item_divider_width">1px</dimen>
-</resources>
diff --git a/chrome/android/java/res/values-xhdpi/dimens.xml b/chrome/android/java/res/values-xhdpi/dimens.xml
deleted file mode 100644
index 6906d3b..0000000
--- a/chrome/android/java/res/values-xhdpi/dimens.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2013 The Chromium Authors. All rights reserved.
-
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file.
--->
-
-<resources>
-    <!-- Custom Menu dimensions -->
-    <dimen name="menu_item_divider_width">2px</dimen>
-</resources>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 887b081..326e43a 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -9,9 +9,8 @@
     <dimen name="certificate_viewer_padding">20dp</dimen>
 
     <!-- Custom Menu dimensions -->
-    <dimen name="menu_item_divider_width">1px</dimen>
     <dimen name="menu_width">257dp</dimen>
-    <dimen name="menu_vertical_offset">0px</dimen>
+    <dimen name="menu_vertical_offset">0dp</dimen>
     <!-- The amount to fade the edges of the menu to indicate more content is available
          via scrolling. -->
     <dimen name="menu_vertical_fade_distance">15dp</dimen>
@@ -52,6 +51,8 @@
     <dimen name="app_banner_button_padding_sides">12dp</dimen>
     <dimen name="app_banner_button_padding_above_below">0dp</dimen>
 
+    <dimen name="app_banner_close_button_padding">12dp</dimen>
+
     <dimen name="app_banner_icon_size">80dp</dimen>
     <dimen name="app_banner_icon_margin_end">8dp</dimen>
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java
index ec94472..e745eaa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWebContentsDelegateAndroid.java
@@ -33,8 +33,8 @@
     }
 
     @CalledByNative
-    public void webContentsCreated(long sourceWebContents, long sourceFrameId, String frameName,
-            String targetUrl, long newWebContents) {
+    public void webContentsCreated(long sourceWebContents, long opener_render_frame_id,
+            String frameName, String targetUrl, long newWebContents) {
     }
 
     // Helper functions used to create types that are part of the public interface
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/EmptyTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/EmptyTabObserver.java
index ec4ab95..da56c37 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/EmptyTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/EmptyTabObserver.java
@@ -53,4 +53,9 @@
     @Override
     public void onDidFailLoad(Tab tab, boolean isProvisionalLoad, boolean isMainFrame,
             int errorCode, String description, String failingUrl) { }
+
+    @Override
+    public void onDidStartProvisionalLoadForFrame(Tab tab, long frameId, long parentFrameId,
+            boolean isMainFrame, String validatedUrl, boolean isErrorPage,
+            boolean isIframeSrcdoc) { }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/RecentlyClosedBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/RecentlyClosedBridge.java
index ce6bdb0..d3a33e6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/RecentlyClosedBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/RecentlyClosedBridge.java
@@ -6,6 +6,7 @@
 
 import org.chromium.base.CalledByNative;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.ui.WindowOpenDisposition;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -94,6 +95,7 @@
         return received ? tabs : null;
     }
 
+    // TODO(newt): delete this once all callers are using the new method below.
     /**
      * Opens a recently closed tab in the current tab.
      *
@@ -102,7 +104,23 @@
      * @return Whether the tab was successfully opened.
      */
     public boolean openRecentlyClosedTab(Tab tab, RecentlyClosedTab recentTab) {
-        return nativeOpenRecentlyClosedTab(mNativeRecentlyClosedTabsBridge, tab, recentTab.id);
+        return openRecentlyClosedTab(tab, recentTab, WindowOpenDisposition.CURRENT_TAB);
+    }
+
+    /**
+     * Opens a recently closed tab in the current tab or a new tab. If opened in the current tab,
+     * the current tab's entire history is replaced.
+     *
+     * @param tab The current Tab.
+     * @param recentTab The RecentlyClosedTab to open.
+     * @param windowOpenDisposition The WindowOpenDisposition value specifying whether to open in
+     *         the current tab or a new tab.
+     * @return Whether the tab was successfully opened.
+     */
+    public boolean openRecentlyClosedTab(Tab tab, RecentlyClosedTab recentTab,
+            int windowOpenDisposition) {
+        return nativeOpenRecentlyClosedTab(mNativeRecentlyClosedTabsBridge, tab, recentTab.id,
+                windowOpenDisposition);
     }
 
     /**
@@ -118,7 +136,7 @@
             long nativeRecentlyClosedTabsBridge, RecentlyClosedCallback callback);
     private native boolean nativeGetRecentlyClosedTabs(
             long nativeRecentlyClosedTabsBridge, List<RecentlyClosedTab> tabs, int maxTabCount);
-    private native boolean nativeOpenRecentlyClosedTab(
-            long nativeRecentlyClosedTabsBridge, Tab tab, int recentTabId);
+    private native boolean nativeOpenRecentlyClosedTab(long nativeRecentlyClosedTabsBridge,
+            Tab tab, int recentTabId, int windowOpenDisposition);
     private native void nativeClearRecentlyClosedTabs(long nativeRecentlyClosedTabsBridge);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
index 3c934f2..0793671 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
@@ -270,6 +270,16 @@
                         description, failingUrl);
             }
         }
+
+        @Override
+        public void didStartProvisionalLoadForFrame(long frameId, long parentFrameId,
+                boolean isMainFrame, String validatedUrl, boolean isErrorPage,
+                boolean isIframeSrcdoc) {
+            for (TabObserver observer : mObservers) {
+                observer.onDidStartProvisionalLoadForFrame(Tab.this, frameId, parentFrameId,
+                        isMainFrame, validatedUrl, isErrorPage, isIframeSrcdoc);
+            }
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/TabObserver.java
index f8df8e6..b154c30 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/TabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/TabObserver.java
@@ -122,4 +122,19 @@
             Tab tab, boolean isProvisionalLoad, boolean isMainFrame, int errorCode,
             String description, String failingUrl);
 
+    /**
+     * Called when load is started for a given frame.
+     * @param tab            The notifying {@link Tab}.
+     * @param frameId        A positive, non-zero integer identifying the navigating frame.
+     * @param parentFrameId  The frame identifier of the frame containing the navigating frame,
+     *                       or -1 if the frame is not contained in another frame.
+     * @param isMainFrame    Whether the load is happening for the main frame.
+     * @param validatedUrl   The validated URL that is being navigated to.
+     * @param isErrorPage    Whether this is navigating to an error page.
+     * @param isIframeSrcdoc Whether this is navigating to about:srcdoc.
+     */
+    public void onDidStartProvisionalLoadForFrame(
+            Tab tab, long frameId, long parentFrameId, boolean isMainFrame, String validatedUrl,
+            boolean isErrorPage, boolean isIframeSrcdoc);
+
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
index ec9fe27..cc59342 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuAdapter.java
@@ -148,6 +148,7 @@
                     holder = new TitleButtonMenuItemViewHolder();
                     convertView = mInflater.inflate(R.layout.title_button_menu_item, null);
                     holder.title = (Button) convertView.findViewById(R.id.title);
+                    holder.divider = convertView.findViewById(R.id.divider);
                     holder.button = (ImageButton) convertView.findViewById(R.id.button);
                     convertView.setTag(holder);
                 } else {
@@ -163,7 +164,14 @@
                         mAppMenu.onItemClick(titleItem);
                     }
                 });
-                setupImageButton(holder.button, item.getSubMenu().getItem(1));
+                if (item.getSubMenu().getItem(1).getIcon() != null) {
+                    holder.button.setVisibility(View.VISIBLE);
+                    holder.divider.setVisibility(View.VISIBLE);
+                    setupImageButton(holder.button, item.getSubMenu().getItem(1));
+                } else {
+                    holder.button.setVisibility(View.GONE);
+                    holder.divider.setVisibility(View.GONE);
+                }
                 convertView.setFocusable(false);
                 convertView.setEnabled(false);
                 break;
@@ -200,6 +208,7 @@
 
     static class TitleButtonMenuItemViewHolder {
         public Button title;
+        public View divider;
         public ImageButton button;
     }
 }
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
index 064ebdc..bf49ed9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerManager.java
@@ -4,40 +4,33 @@
 
 package org.chromium.chrome.browser.banners;
 
-import android.app.Activity;
-import android.content.ActivityNotFoundException;
-import android.content.ContentResolver;
-import android.content.Intent;
-import android.content.IntentSender;
-import android.content.pm.PackageManager;
+import android.app.PendingIntent;
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.text.TextUtils;
-import android.util.Log;
 
 import org.chromium.base.CalledByNative;
+import org.chromium.base.JNINamespace;
 import org.chromium.chrome.browser.EmptyTabObserver;
 import org.chromium.chrome.browser.Tab;
 import org.chromium.chrome.browser.TabObserver;
 import org.chromium.content.browser.ContentView;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.R;
-import org.chromium.ui.base.WindowAndroid;
-import org.chromium.ui.base.WindowAndroid.IntentCallback;
 
 /**
  * Manages an AppBannerView for a Tab and its ContentView.
  *
  * The AppBannerManager manages a single AppBannerView, dismissing it when the user navigates to a
- * new page or creating a new one when it detects that the current webpage is requesting a banner
- * to be built.  The actual observation of the WebContents (which triggers the automatic creation
- * and removal of banners, among other things) is done by the native-side AppBannerManager.
+ * new page or creating a new one when it detects that the current webpage is requesting a banner to
+ * be built. The actual observation of the WebContents (which triggers the automatic creation and
+ * removal of banners, among other things) is done by the native-side AppBannerManager.
  *
  * This Java-side class owns its native-side counterpart, which is basically used to grab resources
  * from the network.
  */
-public class AppBannerManager implements AppBannerView.Observer, InstallerDelegate.Observer,
-        AppDetailsDelegate.Observer, IntentCallback {
+@JNINamespace("banners")
+public class AppBannerManager implements AppBannerView.Observer, AppDetailsDelegate.Observer {
     private static final String TAG = "AppBannerManager";
 
     /** Retrieves information about a given package. */
@@ -129,7 +122,7 @@
     @CalledByNative
     private void prepareBanner(String url, String packageName) {
         // Get rid of whatever banner is there currently.
-        if (mBannerView != null) dismissCurrentBanner();
+        if (mBannerView != null) dismissCurrentBanner(AppBannerMetricsIds.DISMISS_ERROR);
 
         if (sAppDetailsDelegate == null || !isBannerForCurrentPage(url)) return;
 
@@ -155,129 +148,74 @@
      * Called when all the data required to show a banner has finally been retrieved.
      * Creates the banner and shows it, as long as the banner is still meant for the current page.
      * @param imageUrl URL of the icon.
-     * @param appIcon  Bitmap containing the icon itself.
+     * @param appIcon Bitmap containing the icon itself.
+     * @return Whether or not the banner was created.
      */
     @CalledByNative
-    private void createBanner(String imageUrl, Bitmap appIcon) {
-        if (mAppData == null || !isBannerForCurrentPage(mAppData.siteUrl())) return;
+    private boolean createBanner(String imageUrl, Bitmap appIcon) {
+        if (mAppData == null || !isBannerForCurrentPage(mAppData.siteUrl())) return false;
 
         if (!TextUtils.equals(mAppData.imageUrl(), imageUrl)) {
             resetState();
-            return;
+            return false;
         }
 
         mAppData.setIcon(new BitmapDrawable(mContentView.getContext().getResources(), appIcon));
         mBannerView = AppBannerView.create(mContentView, this, mAppData);
+        return true;
     }
 
     /**
-     * Dismisses whatever banner is currently being displayed.
-     * This is treated as an automatic dismissal and not one that blocks the banner from appearing
-     * in the future.
+     * Dismisses whatever banner is currently being displayed. This is treated as an automatic
+     * dismissal and not one that blocks the banner from appearing in the future.
+     * @param dismissalType What triggered the dismissal.
      */
     @CalledByNative
-    private void dismissCurrentBanner() {
-        if (mBannerView != null) mBannerView.dismiss();
+    private void dismissCurrentBanner(int dismissalType) {
+        if (mBannerView != null) mBannerView.dismiss(dismissalType);
         resetState();
     }
 
     @Override
-    public void onButtonClicked(AppBannerView banner) {
+    public void onBannerRemoved(AppBannerView banner) {
         if (mBannerView != banner) return;
-
-        if (mAppData.installState() == AppData.INSTALL_STATE_NOT_INSTALLED) {
-            // The user initiated an install.
-            WindowAndroid window = mTab.getWindowAndroid();
-            if (window.showIntent(mAppData.installIntent(), this, R.string.low_memory_error)) {
-                // Temporarily hide the banner.
-                mBannerView.createVerticalSnapAnimation(false);
-            } else {
-                Log.e(TAG, "Failed to fire install intent.");
-                dismissCurrentBanner();
-            }
-        } else if (mAppData.installState() == AppData.INSTALL_STATE_INSTALLED) {
-            // The app is installed.  Open it.
-            String packageName = mAppData.packageName();
-            PackageManager packageManager = mContentView.getContext().getPackageManager();
-            Intent appIntent = packageManager.getLaunchIntentForPackage(packageName);
-            try {
-                mContentView.getContext().startActivity(appIntent);
-            } catch (ActivityNotFoundException e) {
-                Log.e(TAG, "Failed to find app package: " + packageName);
-            }
-            dismissCurrentBanner();
-        }
-    }
-
-    @Override
-    public void onBannerClicked(AppBannerView banner) {
-        if (mContentView == null || mBannerView == null || mBannerView != banner) {
-            return;
-        }
-
-        try {
-            // Send the user to the app's Play store page.
-            IntentSender sender = banner.getAppData().detailsIntent().getIntentSender();
-            mContentView.getContext().startIntentSender(sender, new Intent(), 0, 0, 0);
-        } catch (IntentSender.SendIntentException e) {
-            Log.e(TAG, "Failed to launch details intent.");
-        }
-
-        dismissCurrentBanner();
-    }
-
-    @Override
-    public void onIntentCompleted(WindowAndroid window, int resultCode,
-            ContentResolver contentResolver, Intent data) {
-        if (mContentView == null || mBannerView == null || mBannerView.getAppData() != mAppData) {
-            return;
-        }
-
-        mBannerView.createVerticalSnapAnimation(true);
-        if (resultCode == Activity.RESULT_OK) {
-            // The user chose to install the app.  Watch the PackageManager to see when it finishes
-            // installing it.
-            mAppData.beginTrackingInstallation(mContentView.getContext(), this);
-            mBannerView.updateButtonState();
-        }
-    }
-
-    @Override
-    public void onInstallFinished(InstallerDelegate monitor, boolean success) {
-        if (mBannerView == null || mAppData == null || mAppData.installTask() != monitor) return;
-
-        if (success) {
-            // Let the user open the app from here.
-            mAppData.setInstallState(AppData.INSTALL_STATE_INSTALLED);
-            mBannerView.updateButtonState();
-        } else {
-            dismissCurrentBanner();
-        }
-    }
-
-    @Override
-    public void onBannerDismissed(AppBannerView banner) {
-        if (mBannerView != banner) return;
-
-        // If the user swiped the banner off of the screen, block it from being shown again.
-        boolean swipedAway = Math.abs(banner.getTranslationX()) >= banner.getWidth();
-        if (swipedAway) {
-            nativeBlockBanner(mNativePointer, mAppData.siteUrl(), mAppData.packageName());
-        }
-
         resetState();
     }
 
+    @Override
+    public void onBannerBlocked(AppBannerView banner, String url, String packageName) {
+        if (mBannerView != banner) return;
+        nativeBlockBanner(mNativePointer, url, packageName);
+    }
+
+    @Override
+    public void onBannerDismissEvent(AppBannerView banner, int eventType) {
+        if (mBannerView != banner) return;
+        nativeRecordDismissEvent(eventType);
+    }
+
+    @Override
+    public void onBannerInstallEvent(AppBannerView banner, int eventType) {
+        if (mBannerView != banner) return;
+        nativeRecordInstallEvent(eventType);
+    }
+
+    @Override
+    public boolean onFireIntent(AppBannerView banner, PendingIntent intent) {
+        if (mBannerView != banner) return false;
+        return mTab.getWindowAndroid().showIntent(intent, banner, R.string.low_memory_error);
+    }
+
     /**
      * Resets all of the state, killing off any running tasks.
      */
     private void resetState() {
-        if (mAppData != null) {
-            mAppData.destroy();
-            mAppData = null;
+        if (mBannerView != null) {
+            mBannerView.destroy();
+            mBannerView = null;
         }
 
-        mBannerView = null;
+        mAppData = null;
     }
 
     /**
@@ -292,9 +230,13 @@
     private static native boolean nativeIsEnabled();
     private native long nativeInit();
     private native void nativeDestroy(long nativeAppBannerManager);
-    private native void nativeReplaceWebContents(
-            long nativeAppBannerManager, WebContents webContents);
+    private native void nativeReplaceWebContents(long nativeAppBannerManager,
+            WebContents webContents);
     private native void nativeBlockBanner(
             long nativeAppBannerManager, String url, String packageName);
     private native boolean nativeFetchIcon(long nativeAppBannerManager, String imageUrl);
+
+    // UMA tracking.
+    private static native void nativeRecordDismissEvent(int metric);
+    private static native void nativeRecordInstallEvent(int metric);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerView.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerView.java
index a3b1e55..9345693 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppBannerView.java
@@ -5,16 +5,27 @@
 package org.chromium.chrome.browser.banners;
 
 import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.ActivityNotFoundException;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Rect;
+import android.os.Looper;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.widget.Button;
+import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.TextView;
 
@@ -22,6 +33,8 @@
 import org.chromium.chrome.R;
 import org.chromium.content.browser.ContentView;
 import org.chromium.ui.base.LocalizationUtils;
+import org.chromium.ui.base.WindowAndroid;
+import org.chromium.ui.base.WindowAndroid.IntentCallback;
 
 /**
  * Lays out a banner for showing info about an app on the Play Store.
@@ -49,52 +62,73 @@
  * to account for less screen real estate.  This means that all of the View's widgets and cached
  * dimensions must be rebuilt from scratch.
  */
-public class AppBannerView extends SwipableOverlayView implements View.OnClickListener {
+public class AppBannerView extends SwipableOverlayView
+        implements View.OnClickListener, InstallerDelegate.Observer, IntentCallback {
+    private static final String TAG = "AppBannerView";
+
     /**
      * Class that is alerted about things happening to the BannerView.
      */
     public static interface Observer {
         /**
-         * Called when the banner is dismissed.
+         * Called when the banner is removed from the hierarchy.
          * @param banner Banner being dismissed.
          */
-        public void onBannerDismissed(AppBannerView banner);
+        public void onBannerRemoved(AppBannerView banner);
 
         /**
-         * Called when the install button has been clicked.
-         * @param banner Banner firing the event.
+         * Called when the user manually closes a banner.
+         * @param banner      Banner being blocked.
+         * @param url         URL of the page that requested the banner.
+         * @param packageName Name of the app's package.
          */
-        public void onButtonClicked(AppBannerView banner);
+        public void onBannerBlocked(AppBannerView banner, String url, String packageName);
 
         /**
-         * Called when something other than the button is clicked.
-         * @param banner Banner firing the event.
+         * Called when the banner begins to be dismissed.
+         * @param banner      Banner being closed.
+         * @param dismissType Type of dismissal performed.
          */
-        public void onBannerClicked(AppBannerView banner);
+        public void onBannerDismissEvent(AppBannerView banner, int dismissType);
+
+        /**
+         * Called when an install event has occurred.
+         */
+        public void onBannerInstallEvent(AppBannerView banner, int eventType);
+
+        /**
+         * Called when the banner needs to have an Activity started for a result.
+         * @param banner Banner firing the event.
+         * @param intent Intent to fire.
+         */
+        public boolean onFireIntent(AppBannerView banner, PendingIntent intent);
     }
 
+    // Installation states.
+    private static final int INSTALL_STATE_NOT_INSTALLED = 0;
+    private static final int INSTALL_STATE_INSTALLING = 1;
+    private static final int INSTALL_STATE_INSTALLED = 2;
+
     // XML layout for the BannerView.
     private static final int BANNER_LAYOUT = R.layout.app_banner_view;
 
-    // Maximum distance the finger can travel before dismissing the highlight.
-    private static final float HIGHLIGHT_DISTANCE = 20;
-
     // True if the layout is in left-to-right layout mode (regular mode).
     private final boolean mIsLayoutLTR;
 
     // Class to alert about BannerView events.
     private AppBannerView.Observer mObserver;
 
+    // Information about the package.  Shouldn't ever be null after calling {@link #initialize()}.
+    private AppData mAppData;
+
     // Views comprising the app banner.
     private ImageView mIconView;
     private TextView mTitleView;
-    private Button mButtonView;
+    private Button mInstallButtonView;
     private RatingView mRatingView;
     private View mLogoView;
     private View mBannerHighlightView;
-
-    // Information about the package.
-    private AppData mAppData;
+    private ImageButton mCloseButtonView;
 
     // Dimension values.
     private int mDefinedMaxWidth;
@@ -103,6 +137,7 @@
     private int mMarginLeft;
     private int mMarginRight;
     private int mMarginBottom;
+    private int mTouchSlop;
 
     // Highlight variables.
     private boolean mIsBannerPressed;
@@ -111,6 +146,11 @@
     // Initial padding values.
     private final Rect mBackgroundDrawablePadding;
 
+    // Install tracking.
+    private boolean mWasInstallDialogShown;
+    private InstallerDelegate mInstallTask;
+    private int mInstallState;
+
     /**
      * Creates a BannerView and adds it to the given ContentView.
      * @param contentView ContentView to display the AppBannerView for.
@@ -142,6 +182,8 @@
         mBackgroundDrawablePadding.right = ApiCompatibilityUtils.getPaddingEnd(this);
         mBackgroundDrawablePadding.top = getPaddingTop();
         mBackgroundDrawablePadding.bottom = getPaddingBottom();
+
+        mInstallState = INSTALL_STATE_NOT_INSTALLED;
     }
 
     /**
@@ -178,38 +220,106 @@
         // Pull out all of the controls we are expecting.
         mIconView = (ImageView) findViewById(R.id.app_icon);
         mTitleView = (TextView) findViewById(R.id.app_title);
-        mButtonView = (Button) findViewById(R.id.app_install_button);
+        mInstallButtonView = (Button) findViewById(R.id.app_install_button);
         mRatingView = (RatingView) findViewById(R.id.app_rating);
         mLogoView = findViewById(R.id.store_logo);
         mBannerHighlightView = findViewById(R.id.banner_highlight);
+        mCloseButtonView = (ImageButton) findViewById(R.id.close_button);
 
         assert mIconView != null;
         assert mTitleView != null;
-        assert mButtonView != null;
+        assert mInstallButtonView != null;
         assert mLogoView != null;
         assert mRatingView != null;
         assert mBannerHighlightView != null;
+        assert mCloseButtonView != null;
 
-        // Set up the button to fire an event.
-        mButtonView.setOnClickListener(this);
+        // Set up the buttons to fire an event.
+        mInstallButtonView.setOnClickListener(this);
+        mCloseButtonView.setOnClickListener(this);
 
         // Configure the controls with the package information.
         mTitleView.setText(mAppData.title());
         mIconView.setImageDrawable(mAppData.icon());
         mRatingView.initialize(mAppData.rating());
 
-        // Update the button state.
-        updateButtonState();
+        // Determine how much the user can drag sideways before their touch is considered a scroll.
+        mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
+
+        // Set up the install button.
+        updateButtonAppearance();
     }
 
     @Override
     public void onClick(View view) {
-        if (mObserver != null && view == mButtonView) mObserver.onButtonClicked(this);
+        if (mObserver == null) return;
+
+        // Only allow the button to be clicked when the banner's in a neutral position.
+        if (Math.abs(getTranslationX()) > ZERO_THRESHOLD
+                || Math.abs(getTranslationY()) > ZERO_THRESHOLD) {
+            return;
+        }
+
+        if (view == mInstallButtonView) {
+            // Ignore button clicks when the app is installing.
+            if (mInstallState == INSTALL_STATE_INSTALLING) return;
+
+            mInstallButtonView.setEnabled(false);
+
+            if (mInstallState == INSTALL_STATE_NOT_INSTALLED) {
+                // The user initiated an install. Track it happening only once.
+                if (!mWasInstallDialogShown) {
+                    mObserver.onBannerInstallEvent(this, AppBannerMetricsIds.INSTALL_TRIGGERED);
+                    mWasInstallDialogShown = true;
+                }
+
+                if (mObserver.onFireIntent(this, mAppData.installIntent())) {
+                    // Temporarily hide the banner.
+                    createVerticalSnapAnimation(false);
+                } else {
+                    Log.e(TAG, "Failed to fire install intent.");
+                    dismiss(AppBannerMetricsIds.DISMISS_ERROR);
+                }
+            } else if (mInstallState == INSTALL_STATE_INSTALLED) {
+                // The app is installed. Open it.
+                String packageName = mAppData.packageName();
+                PackageManager packageManager = getContext().getPackageManager();
+                Intent appIntent = packageManager.getLaunchIntentForPackage(packageName);
+                try {
+                    getContext().startActivity(appIntent);
+                } catch (ActivityNotFoundException e) {
+                    Log.e(TAG, "Failed to find app package: " + packageName);
+                }
+
+                dismiss(AppBannerMetricsIds.DISMISS_APP_OPEN);
+            }
+        } else if (view == mCloseButtonView) {
+            if (mObserver != null) {
+                mObserver.onBannerBlocked(this, mAppData.siteUrl(), mAppData.packageName());
+            }
+
+            dismiss(AppBannerMetricsIds.DISMISS_CLOSE_BUTTON);
+        }
+    }
+
+    @Override
+    protected void onViewSwipedAway() {
+        if (mObserver == null) return;
+        mObserver.onBannerDismissEvent(this, AppBannerMetricsIds.DISMISS_BANNER_SWIPE);
+        mObserver.onBannerBlocked(this, mAppData.siteUrl(), mAppData.packageName());
     }
 
     @Override
     protected void onViewClicked() {
-        if (mObserver != null) mObserver.onBannerClicked(this);
+        // Send the user to the app's Play store page.
+        try {
+            IntentSender sender = mAppData.detailsIntent().getIntentSender();
+            getContext().startIntentSender(sender, new Intent(), 0, 0, 0);
+        } catch (IntentSender.SendIntentException e) {
+            Log.e(TAG, "Failed to launch details intent.");
+        }
+
+        dismiss(AppBannerMetricsIds.DISMISS_BANNER_CLICK);
     }
 
     @Override
@@ -221,6 +331,41 @@
     }
 
     @Override
+    public void onIntentCompleted(WindowAndroid window, int resultCode,
+            ContentResolver contentResolver, Intent data) {
+        if (isDismissed()) return;
+
+        createVerticalSnapAnimation(true);
+        if (resultCode == Activity.RESULT_OK) {
+            // The user chose to install the app. Watch the PackageManager to see when it finishes
+            // installing it.
+            mObserver.onBannerInstallEvent(this, AppBannerMetricsIds.INSTALL_STARTED);
+
+            PackageManager pm = getContext().getPackageManager();
+            mInstallTask =
+                    new InstallerDelegate(Looper.getMainLooper(), pm, this, mAppData.packageName());
+            mInstallTask.start();
+            mInstallState = INSTALL_STATE_INSTALLING;
+        }
+        updateButtonAppearance();
+    }
+
+
+    @Override
+    public void onInstallFinished(InstallerDelegate monitor, boolean success) {
+        if (isDismissed() || mInstallTask != monitor) return;
+
+        if (success) {
+            // Let the user open the app from here.
+            mObserver.onBannerInstallEvent(this, AppBannerMetricsIds.INSTALL_COMPLETED);
+            mInstallState = INSTALL_STATE_INSTALLED;
+            updateButtonAppearance();
+        } else {
+            dismiss(AppBannerMetricsIds.DISMISS_INSTALL_TIMEOUT);
+        }
+    }
+
+    @Override
     protected ViewGroup.MarginLayoutParams createLayoutParams() {
         // Define the margin around the entire banner that accounts for the drop shadow.
         ViewGroup.MarginLayoutParams params = super.createLayoutParams();
@@ -234,46 +379,66 @@
      */
     @Override
     boolean removeFromParent() {
-        boolean removed = super.removeFromParent();
-        if (removed) mObserver.onBannerDismissed(this);
-        return removed;
+        if (super.removeFromParent()) {
+            mObserver.onBannerRemoved(this);
+            destroy();
+            return true;
+        }
+
+        return false;
     }
 
     /**
-     * Returns data for the app the banner is being shown for.
-     * @return The AppData being used by the banner.
+     * Dismisses the banner.
+     * @param eventType Event that triggered the dismissal.  See {@link AppBannerMetricsIds}.
      */
-    AppData getAppData() {
-        return mAppData;
+    public void dismiss(int eventType) {
+        if (isDismissed() || mObserver == null) return;
+
+        dismiss(eventType == AppBannerMetricsIds.DISMISS_CLOSE_BUTTON);
+        mObserver.onBannerDismissEvent(this, eventType);
+    }
+
+    /**
+     * Destroys the Banner.
+     */
+    public void destroy() {
+        if (!isDismissed()) dismiss(AppBannerMetricsIds.DISMISS_ERROR);
+
+        if (mInstallTask != null) {
+            mInstallTask.cancel();
+            mInstallTask = null;
+        }
     }
 
     /**
      * Updates the text and color of the button displayed on the button.
      */
-    void updateButtonState() {
-        if (mButtonView == null) return;
+    void updateButtonAppearance() {
+        if (mInstallButtonView == null) return;
 
         Resources res = getResources();
         int fgColor;
         String text;
-        if (mAppData.installState() == AppData.INSTALL_STATE_INSTALLED) {
-            ApiCompatibilityUtils.setBackgroundForView(mButtonView,
+        if (mInstallState == INSTALL_STATE_INSTALLED) {
+            ApiCompatibilityUtils.setBackgroundForView(mInstallButtonView,
                     res.getDrawable(R.drawable.app_banner_button_open));
             fgColor = res.getColor(R.color.app_banner_open_button_fg);
             text = res.getString(R.string.app_banner_open);
         } else {
-            ApiCompatibilityUtils.setBackgroundForView(mButtonView,
+            ApiCompatibilityUtils.setBackgroundForView(mInstallButtonView,
                     res.getDrawable(R.drawable.app_banner_button_install));
             fgColor = res.getColor(R.color.app_banner_install_button_fg);
-            if (mAppData.installState() == AppData.INSTALL_STATE_NOT_INSTALLED) {
+            if (mInstallState == INSTALL_STATE_NOT_INSTALLED) {
                 text = mAppData.installButtonText();
             } else {
                 text = res.getString(R.string.app_banner_installing);
             }
         }
 
-        mButtonView.setTextColor(fgColor);
-        mButtonView.setText(text);
+        mInstallButtonView.setTextColor(fgColor);
+        mInstallButtonView.setText(text);
+        mInstallButtonView.setEnabled(mInstallState != INSTALL_STATE_INSTALLING);
     }
 
     /**
@@ -296,7 +461,7 @@
             // scrolls a bit to the side.
             float xDifference = Math.abs(event.getRawX() - mInitialXForHighlight);
             if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
-                    || (action == MotionEvent.ACTION_MOVE && xDifference > HIGHLIGHT_DISTANCE)) {
+                    || (action == MotionEvent.ACTION_MOVE && xDifference > mTouchSlop)) {
                 mIsBannerPressed = false;
                 mBannerHighlightView.setVisibility(View.INVISIBLE);
             }
@@ -304,6 +469,7 @@
 
         return super.onTouchEvent(event);
     }
+
     /**
      * Fade the banner back into view.
      */
@@ -321,6 +487,7 @@
     @Override
     protected void onDetachedFromWindow() {
         super.onDetachedFromWindow();
+        setAlpha(0.0f);
         setVisibility(INVISIBLE);
     }
 
@@ -333,6 +500,8 @@
     protected void onConfigurationChanged(Configuration config) {
         super.onConfigurationChanged(config);
 
+        if (isDismissed()) return;
+
         // If the card's maximum width hasn't changed, the individual views can't have, either.
         int newDefinedWidth = getResources().getDimensionPixelSize(R.dimen.app_banner_max_width);
         if (mDefinedMaxWidth == newDefinedWidth) return;
@@ -342,7 +511,7 @@
         while (getChildCount() > 0) removeViewAt(0);
         mIconView = null;
         mTitleView = null;
-        mButtonView = null;
+        mInstallButtonView = null;
         mRatingView = null;
         mLogoView = null;
         mBannerHighlightView = null;
@@ -364,7 +533,7 @@
      * DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
      * DPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPD
      * DP......                               cPD
-     * DP...... TITLE-------------------------cPD
+     * DP...... TITLE----------------------- XcPD
      * DP.ICON. *****                         cPD
      * DP...... LOGO                    BUTTONcPD
      * DP...... cccccccccccccccccccccccccccccccPD
@@ -384,7 +553,8 @@
      * 3) The install button occupies the bottom-right of the banner.
      * 4) The Google Play logo occupies the space to the left of the button.
      * 5) The rating is assigned space above the logo and below the title.
-     * 6) The title is assigned whatever space is left and sits on top of the tallest stack of
+     * 6) The close button (if visible) sits in the top right of the banner.
+     * 7) The title is assigned whatever space is left and sits on top of the tallest stack of
      *    controls.
      *
      * See {@link #android.view.View.onMeasure(int, int)} for the parameters.
@@ -434,11 +604,12 @@
         // 2) The app title + control padding + star rating + store logo.
         // 3) The app title + control padding + install button.
         // The control padding is extra padding that applies only to the non-icon widgets.
+        // The close button does not get counted as part of a stack.
         int iconStackHeight = getHeightWithMargins(mIconView);
         int logoStackHeight = getHeightWithMargins(mTitleView) + mPaddingControls
                 + getHeightWithMargins(mRatingView) + getHeightWithMargins(mLogoView);
         int buttonStackHeight = getHeightWithMargins(mTitleView) + mPaddingControls
-                + getHeightWithMargins(mButtonView);
+                + getHeightWithMargins(mInstallButtonView);
         int biggestStackHeight =
                 Math.max(iconStackHeight, Math.max(logoStackHeight, buttonStackHeight));
 
@@ -451,7 +622,7 @@
         final int contentWidth =
                 maxControlWidth - getWidthWithMargins(mIconView) - mPaddingControls;
         final int contentHeight = biggestStackHeight - mPaddingControls;
-        measureChildForSpace(mButtonView, contentWidth, contentHeight);
+        measureChildForSpace(mInstallButtonView, contentWidth, contentHeight);
         measureChildForSpace(mLogoView, contentWidth, contentHeight);
 
         // Measure the star rating, which sits below the title and above the logo.
@@ -459,10 +630,18 @@
         final int ratingHeight = contentHeight - getHeightWithMargins(mLogoView);
         measureChildForSpace(mRatingView, ratingWidth, ratingHeight);
 
-        // The app title spans the top of the banner and sits on top of the other controls.
-        int biggerStack = Math.max(getHeightWithMargins(mButtonView),
+        // The close button sits to the right of the title and above the install button.
+        final int closeWidth = contentWidth;
+        final int closeHeight = contentHeight - getHeightWithMargins(mInstallButtonView);
+        measureChildForSpace(mCloseButtonView, closeWidth, closeHeight);
+
+        // The app title spans the top of the banner and sits on top of the other controls, and to
+        // the left of the close button. The computation for the width available to the title is
+        // complicated by how the button sits in the corner and absorbs the padding that would
+        // normally be there.
+        int biggerStack = Math.max(getHeightWithMargins(mInstallButtonView),
                 getHeightWithMargins(mLogoView) + getHeightWithMargins(mRatingView));
-        final int titleWidth = contentWidth;
+        final int titleWidth = contentWidth - getWidthWithMargins(mCloseButtonView) + mPaddingCard;
         final int titleHeight = contentHeight - biggerStack;
         measureChildForSpace(mTitleView, titleWidth, titleHeight);
 
@@ -495,6 +674,18 @@
         // The highlight overlay covers the entire banner (minus drop shadow padding).
         mBannerHighlightView.layout(start, top, end, bottom);
 
+        // Lay out the close button in the top-right corner.  Padding that would normally go to the
+        // card is applied to the close button so that it has a bigger touch target.
+        if (mCloseButtonView.getVisibility() == VISIBLE) {
+            int closeWidth = mCloseButtonView.getMeasuredWidth();
+            int closeTop =
+                    top + ((MarginLayoutParams) mCloseButtonView.getLayoutParams()).topMargin;
+            int closeBottom = closeTop + mCloseButtonView.getMeasuredHeight();
+            int closeRight = mIsLayoutLTR ? end : (getMeasuredWidth() - end + closeWidth);
+            int closeLeft = closeRight - closeWidth;
+            mCloseButtonView.layout(closeLeft, closeTop, closeRight, closeBottom);
+        }
+
         // Apply the padding for the rest of the widgets.
         top += mPaddingCard;
         bottom -= mPaddingCard;
@@ -538,11 +729,11 @@
         mLogoView.layout(logoLeft, logoTop, logoLeft + logoWidth, logoBottom);
 
         // Lay out the install button in the bottom-right corner.
-        int buttonHeight = mButtonView.getMeasuredHeight();
-        int buttonWidth = mButtonView.getMeasuredWidth();
+        int buttonHeight = mInstallButtonView.getMeasuredHeight();
+        int buttonWidth = mInstallButtonView.getMeasuredWidth();
         int buttonRight = mIsLayoutLTR ? end : (getMeasuredWidth() - end + buttonWidth);
         int buttonLeft = buttonRight - buttonWidth;
-        mButtonView.layout(buttonLeft, bottom - buttonHeight, buttonRight, bottom);
+        mInstallButtonView.layout(buttonLeft, bottom - buttonHeight, buttonRight, bottom);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppData.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppData.java
index 28c94dd..2da22f5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/AppData.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/AppData.java
@@ -5,20 +5,12 @@
 package org.chromium.chrome.browser.banners;
 
 import android.app.PendingIntent;
-import android.content.Context;
-import android.content.pm.PackageManager;
 import android.graphics.drawable.Drawable;
-import android.os.Looper;
 
 /**
  * Stores information about a particular app.
  */
 public class AppData {
-    // Installation states.
-    static final int INSTALL_STATE_NOT_INSTALLED = 0;
-    static final int INSTALL_STATE_INSTALLING = 1;
-    static final int INSTALL_STATE_INSTALLED = 2;
-
     // Immutable data about this app.
     private final String mSiteUrl;
     private final String mPackageName;
@@ -33,10 +25,6 @@
 
     // Data that can be updated asynchronously.
     private Drawable mIcon;
-    private int mInstallState;
-
-    // Task that watches the package manager for installation progress.
-    private InstallerDelegate mInstallTask;
 
     /**
      * Creates a new AppData for the given page and package.
@@ -46,7 +34,6 @@
     public AppData(String siteUrl, String packageName) {
         mSiteUrl = siteUrl;
         mPackageName = packageName;
-        mInstallState = INSTALL_STATE_NOT_INSTALLED;
     }
 
     /**
@@ -124,22 +111,6 @@
     }
 
     /**
-     * Returns the state of the install.
-     * @return INSTALL_STATE_* representing the current phase of the installation.
-     */
-    int installState() {
-        return mInstallState;
-    }
-
-    /**
-     * Returns the task tracking the installation.
-     * @return The InstallerDelegate that is tracking the app's installation.
-     */
-    InstallerDelegate installTask() {
-        return mInstallTask;
-    }
-
-    /**
      * Stores all of the data about the given app after it's been retrieved.
      * @param title             App title.
      * @param imageUrl          URL where the icon is located.
@@ -165,34 +136,4 @@
     void setIcon(Drawable icon) {
         mIcon = icon;
     }
-
-    /**
-     * Sets the install state.
-     * @param installState Current state of the installation.
-     */
-    void setInstallState(int installState) {
-        mInstallState = installState;
-    }
-
-    /**
-     * Begins tracking the installation of the package.
-     * @param context  Context to grab the PackageManager from.
-     * @param observer Observer to notify when the app has finished installing.
-     */
-    void beginTrackingInstallation(Context context, InstallerDelegate.Observer observer) {
-        PackageManager pm = context.getPackageManager();
-        mInstallTask = new InstallerDelegate(Looper.getMainLooper(), pm, observer, mPackageName);
-        mInstallTask.start();
-        mInstallState = AppData.INSTALL_STATE_INSTALLING;
-    }
-
-    /**
-     * Clean up any pending operations.
-     */
-    void destroy() {
-        if (mInstallTask != null) {
-            mInstallTask.cancel();
-            mInstallTask = null;
-        }
-    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java
index c38de8b..2428ce5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/InstallerDelegate.java
@@ -79,7 +79,7 @@
     public void start() {
         mTimestampStarted = SystemClock.elapsedRealtime();
         mIsRunning = true;
-        run();
+        mHandler.postDelayed(this, mMsBetweenRuns);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java
index ce3afbe..9ecd0ed 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/banners/SwipableOverlayView.java
@@ -85,6 +85,7 @@
 
     protected static final long MS_ANIMATION_DURATION = 250;
     private static final long MS_DISMISS_FLING_THRESHOLD = MS_ANIMATION_DURATION * 2;
+    private static final long MS_SLOW_DISMISS = MS_ANIMATION_DURATION * 3;
 
     // Detects when the user is dragging the View.
     private final GestureDetector mGestureDetector;
@@ -104,9 +105,6 @@
     // Animation currently being used to translate the View.
     private AnimatorSet mCurrentAnimation;
 
-    // Whether or not the current animation is adding or removing the View.
-    private boolean mIsAnimationAddingOrRemovingView;
-
     // Direction the user is horizontally dragging.
     private int mDragDirection;
 
@@ -128,6 +126,12 @@
     // How tall the View is, including its margins.
     private int mTotalHeight;
 
+    // Whether or not the View ever been fully displayed.
+    private boolean mIsBeingDisplayedForFirstTime;
+
+    // Whether or not the View has been, or is being, dismissed.
+    private boolean mIsDismissed;
+
     /**
      * Creates a SwipableOverlayView.
      * @param context Context for acquiring resources.
@@ -215,7 +219,7 @@
 
         int action = event.getActionMasked();
         if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
-            createHorizontalAnimation();
+            onFinishHorizontalGesture();
             return true;
         }
         return false;
@@ -262,7 +266,7 @@
                 // Check if the velocity from the user's drag is higher; if so, use that one
                 // instead since that often feels more correct.
                 mDragXPerMs = mDragDirection * Math.max(androidXPerMs, dragXPerMs);
-                createHorizontalAnimation();
+                onFinishHorizontalGesture();
                 return true;
             }
 
@@ -280,6 +284,22 @@
     }
 
     /**
+     * Called at the end of a user gesture on the banner to either return the banner to a neutral
+     * position in the center of the screen or dismiss it entirely.
+     */
+    private void onFinishHorizontalGesture() {
+        mDragDirection = determineFinalHorizontalLocation();
+        if (mDragDirection == DRAGGED_CANCEL) {
+            // Move the View back to the center of the screen.
+            createHorizontalSnapAnimation(true);
+        } else {
+            // User swiped the View away.  Dismiss it.
+            onViewSwipedAway();
+            dismiss(true);
+        }
+    }
+
+    /**
      * Creates a listener than monitors the ContentViewCore for scrolls and flings.
      * The listener updates the location of this View to account for the user's gestures.
      * @return GestureStateListener to send to the ContentViewCore.
@@ -299,6 +319,8 @@
                 mGestureState = GESTURE_NONE;
 
                 int finalOffsetY = computeScrollDifference(scrollOffsetY, scrollExtentY);
+                updateTranslation(scrollOffsetY, scrollExtentY);
+
                 boolean isScrollingDownward = finalOffsetY > 0;
 
                 boolean isVisibleInitially = mInitialTranslationY < mTotalHeight;
@@ -333,6 +355,8 @@
                 mGestureState = GESTURE_NONE;
 
                 int finalOffsetY = computeScrollDifference(scrollOffsetY, scrollExtentY);
+                updateTranslation(scrollOffsetY, scrollExtentY);
+
                 boolean isNearTopOfPage = finalOffsetY < (mTotalHeight * FULL_THRESHOLD);
                 boolean isVisibleEnough = getTranslationY() < mTotalHeight * FULL_THRESHOLD;
                 createVerticalSnapAnimation(isNearTopOfPage || isVisibleEnough);
@@ -342,7 +366,10 @@
             public void onScrollOffsetOrExtentChanged(int scrollOffsetY, int scrollExtentY) {
                 // This function is called for both fling and scrolls.
                 if (mGestureState == GESTURE_NONE || !cancelCurrentAnimation()) return;
+                updateTranslation(scrollOffsetY, scrollExtentY);
+            }
 
+            private void updateTranslation(int scrollOffsetY, int scrollExtentY) {
                 float translation = mInitialTranslationY
                         + computeScrollDifference(scrollOffsetY, scrollExtentY);
                 translation = Math.max(0.0f, Math.min(mTotalHeight, translation));
@@ -364,7 +391,7 @@
 
                 // Animate the View coming in from the bottom of the screen.
                 setTranslationY(mTotalHeight);
-                mIsAnimationAddingOrRemovingView = true;
+                mIsBeingDisplayedForFirstTime = true;
                 createVerticalSnapAnimation(true);
                 mCurrentAnimation.start();
             }
@@ -381,19 +408,65 @@
         float translationY = visible ? 0.0f : mTotalHeight;
         float yDifference = Math.abs(translationY - getTranslationY()) / mTotalHeight;
         long duration = (long) (MS_ANIMATION_DURATION * yDifference);
-        createAnimation(1.0f, 0, translationY, duration, false);
+        createAnimation(1.0f, 0, translationY, duration);
     }
 
     /**
-     * Dismisses the View, animating it moving vertically off of the screen if needed.
+     * Create an animation that snaps the View into position horizontally.
+     * @param visible If true, snaps the View to the bottom-center of the screen.  If false,
+     *                translates the View to the side of the screen.
      */
-    protected void dismiss() {
-        if (getParent() == null) return;
+    private void createHorizontalSnapAnimation(boolean visible) {
+        if (visible) {
+            // Move back to the center of the screen.
+            createAnimation(1.0f, 0.0f, getTranslationY(), MS_ANIMATION_DURATION);
+        } else {
+            if (mDragDirection == DRAGGED_CANCEL) {
+                // No direction was selected
+                mDragDirection = DRAGGED_LEFT;
+            }
 
-        float translationY = mTotalHeight;
-        float yDifference = Math.abs(translationY - getTranslationY()) / mTotalHeight;
-        long duration = (long) (MS_ANIMATION_DURATION * yDifference);
-        createAnimation(1.0f, 0, translationY, duration, true);
+            float finalX = mDragDirection * getWidth();
+
+            // Determine how long it will take for the banner to leave the screen.
+            long duration = MS_ANIMATION_DURATION;
+            switch (mGestureState) {
+                case GESTURE_FLINGING:
+                    duration = (long) calculateMsRequiredToFlingOffScreen();
+                    break;
+                case GESTURE_NONE:
+                    // Explicitly use a slow animation to help educate the user about swiping.
+                    duration = MS_SLOW_DISMISS;
+                    break;
+                default:
+                    break;
+            }
+
+            createAnimation(0.0f, finalX, getTranslationY(), duration);
+        }
+    }
+
+    /**
+     * Dismisses the View, animating it moving off of the screen if needed.
+     * @param horizontally True if the View is being dismissed to the side of the screen.
+     */
+    protected boolean dismiss(boolean horizontally) {
+        if (getParent() == null || mIsDismissed) return false;
+
+        mIsDismissed = true;
+        if (horizontally) {
+            createHorizontalSnapAnimation(false);
+        } else {
+            createVerticalSnapAnimation(false);
+        }
+        return true;
+    }
+
+    /**
+     * @return Whether or not the View has been dismissed.
+     */
+    protected boolean isDismissed() {
+        return mIsDismissed;
     }
 
     /**
@@ -416,43 +489,37 @@
     }
 
     /**
-     * Horizontally slide the View either to the center of the screen or off of it for dismissal.
-     * If the animation translates the View off the screen, the View is removed from the hierarchy
-     * and marked as a manual removal.
+     * Determine where the View needs to move.  If the user hasn't tried hard enough to dismiss
+     * the View, move it back to the center.
+     * @return DRAGGED_CANCEL if the View should return to a neutral center position.
+     *         DRAGGED_LEFT if the View should be dismissed to the left.
+     *         DRAGGED_RIGHT if the View should be dismissed to the right.
      */
-    private void createHorizontalAnimation() {
-        long duration = MS_ANIMATION_DURATION;
-
-        // Determine where the View needs to move. Because of the unreliability of the fling
-        // velocity, we ignore it and instead rely on the direction the user was last dragging the
-        // View.  Moreover, we lower the translation threshold for dismissal.
-        boolean isFlinging = mGestureState == GESTURE_FLINGING;
-
-        // If the user hasn't tried hard enough to dismiss the View, move it back to the center.
-        if (isFlinging) {
-            // Assuming a linear velocity, allow flinging the View away if it would fly off the
-            // screen in a reasonable time frame.
-            float remainingDifference = mDragDirection * getWidth() - getTranslationX();
-            float msRequired = Math.abs(remainingDifference / mDragXPerMs);
-
-            if (msRequired < MS_DISMISS_FLING_THRESHOLD) {
-                duration = (long) msRequired;
-            } else {
-                mDragDirection = DRAGGED_CANCEL;
-            }
-        } else {
+    private int determineFinalHorizontalLocation() {
+        if (mGestureState == GESTURE_FLINGING) {
+            // Because of the unreliability of the fling velocity, we ignore it and instead rely on
+            // the direction the user was last dragging the View.  Moreover, we lower the
+            // translation threshold for dismissal, requiring the View to translate off screen
+            // within a reasonable time frame.
+            float msRequired = calculateMsRequiredToFlingOffScreen();
+            if (msRequired > MS_DISMISS_FLING_THRESHOLD) return DRAGGED_CANCEL;
+        } else if (mGestureState == GESTURE_SCROLLING) {
             // Check if the user has dragged the View far enough to be dismissed.
             float dismissPercentage = DISMISS_SWIPE_THRESHOLD;
             float dismissThreshold = getWidth() * dismissPercentage;
-            if (Math.abs(getTranslationX()) < dismissThreshold) mDragDirection = DRAGGED_CANCEL;
+            if (Math.abs(getTranslationX()) < dismissThreshold) return DRAGGED_CANCEL;
         }
 
-        // Set up the animation parameters.
-        float finalAlpha = mDragDirection == DRAGGED_CANCEL ? 1.0f : 0.0f;
-        float finalX = mDragDirection * getWidth();
-        boolean isSwipedAway = mDragDirection != DRAGGED_CANCEL;
+        return mDragDirection;
+    }
 
-        createAnimation(finalAlpha, finalX, getTranslationY(), duration, isSwipedAway);
+    /**
+     * Assuming a linear velocity, determine how long it would take for the View to translate off
+     * of the screen.
+     */
+    private float calculateMsRequiredToFlingOffScreen() {
+        float remainingDifference = mDragDirection * getWidth() - getTranslationX();
+        return Math.abs(remainingDifference / mDragXPerMs);
     }
 
     /**
@@ -461,9 +528,8 @@
      * @param x X-coordinate of the final translation.
      * @param y Y-coordinate of the final translation.
      * @param duration How long the animation should run for.
-     * @param remove If true, remove the View from its parent ViewGroup.
      */
-    private void createAnimation(float alpha, float x, float y, long duration, boolean remove) {
+    private void createAnimation(float alpha, float x, float y, long duration) {
         Animator alphaAnimator =
                 ObjectAnimator.ofPropertyValuesHolder(this,
                         PropertyValuesHolder.ofFloat("alpha", getAlpha(), alpha));
@@ -474,7 +540,6 @@
                 ObjectAnimator.ofPropertyValuesHolder(this,
                         PropertyValuesHolder.ofFloat("translationY", getTranslationY(), y));
 
-        mIsAnimationAddingOrRemovingView = remove;
         mCurrentAnimation = new AnimatorSet();
         mCurrentAnimation.setDuration(duration);
         mCurrentAnimation.playTogether(alphaAnimator, translationXAnimator, translationYAnimator);
@@ -491,11 +556,11 @@
         return new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
+                if (mIsDismissed) removeFromParent();
+
                 mGestureState = GESTURE_NONE;
                 mCurrentAnimation = null;
-
-                if (mIsAnimationAddingOrRemovingView) removeFromParent();
-                mIsAnimationAddingOrRemovingView = false;
+                mIsBeingDisplayedForFirstTime = false;
             }
         };
     }
@@ -515,12 +580,26 @@
      * @return True if the animation was canceled or wasn't running, false otherwise.
      */
     private boolean cancelCurrentAnimation() {
-        if (mIsAnimationAddingOrRemovingView) return false;
+        if (!mayCancelCurrentAnimation()) return false;
         if (mCurrentAnimation != null) mCurrentAnimation.cancel();
         return true;
     }
 
     /**
+     * Determines whether or not the animation can be interrupted.  Animations may not be canceled
+     * when the View is being dismissed or when it's coming onto screen for the first time.
+     * @return Whether or not the animation may be interrupted.
+     */
+    private boolean mayCancelCurrentAnimation() {
+        return !mIsBeingDisplayedForFirstTime && !mIsDismissed;
+    }
+
+    /**
+     * Called when the View has been swiped away by the user.
+     */
+    protected abstract void onViewSwipedAway();
+
+    /**
      * Called when the View has been clicked.
      */
     protected abstract void onViewClicked();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java
index abfb78e..8661274 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReporter.java
@@ -79,7 +79,7 @@
      */
     @CalledByNative
     private void dismissOverlay() {
-        if (mFeedbackReportingView != null) mFeedbackReportingView.dismiss();
+        if (mFeedbackReportingView != null) mFeedbackReportingView.dismiss(true);
         mOverlayUrl = null;
         mFeedbackReportingView = null;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReportingView.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReportingView.java
index 59e178c..fddf984 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReportingView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/FeedbackReportingView.java
@@ -128,8 +128,8 @@
      * {@link org.chromium.chrome.browser.dom_distiller.FeedbackReporter}.
      */
     @Override
-    protected void dismiss() {
-        super.dismiss();
+    protected boolean dismiss(boolean horizontally) {
+        return super.dismiss(horizontally);
     }
 
     @Override
@@ -139,4 +139,8 @@
     @Override
     protected void onViewPressed(MotionEvent event) {
     }
+
+    @Override
+    protected void onViewSwipedAway() {
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutoLoginDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutoLoginDelegate.java
index bead036..6bcd00a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutoLoginDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/AutoLoginDelegate.java
@@ -10,7 +10,7 @@
 import org.chromium.base.CalledByNative;
 
 /**
- * Java equivalent of the C++ AutoLoginDelegate.
+ * Java equivalent of the C++ AutoLoginDelegateAndroid.
  *
  * Offers functionality to log in using the account in the system and keeps track
  * of all the native autologin infobars and their respective accounts.
@@ -95,8 +95,8 @@
         }
     }
 
-    private native void nativeLoginSuccess(long nativeAutoLoginInfoBarDelegate,
+    private native void nativeLoginSuccess(long nativeAutoLoginInfoBarDelegateAndroid,
             String result);
-    private native void nativeLoginFailed(long nativeAutoLoginInfoBarDelegate);
-    private native void nativeLoginDismiss(long nativeAutoLoginInfoBarDelegate);
+    private native void nativeLoginFailed(long nativeAutoLoginInfoBarDelegateAndroid);
+    private native void nativeLoginDismiss(long nativeAutoLoginInfoBarDelegateAndroid);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java
index 5c79543..8443ae4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/InfoBarLayout.java
@@ -144,7 +144,7 @@
 
         // Set up the close button.
         mCloseButton.setId(R.id.infobar_close_button);
-        mCloseButton.setImageResource(R.drawable.infobar_dismiss);
+        mCloseButton.setImageResource(R.drawable.dismiss);
         mCloseButton.setBackgroundResource(R.drawable.infobar_close_bg);
         mCloseButton.setOnClickListener(this);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/profiles/ProfileDownloader.java b/chrome/android/java/src/org/chromium/chrome/browser/profiles/ProfileDownloader.java
index 0f61ddd..25d320c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/profiles/ProfileDownloader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/profiles/ProfileDownloader.java
@@ -67,7 +67,25 @@
         }
     }
 
+    /**
+     * @param profile Profile
+     * @return The profile name if cached, or null.
+     */
+    public static String getCachedName(Profile profile) {
+        return nativeGetCachedNameForPrimaryAccount(profile);
+    }
+
+    /**
+     * @param profile Profile
+     * @return The profile avatar if cached, or null.
+     */
+    public static Bitmap getCachedAvatar(Profile profile) {
+        return nativeGetCachedAvatarForPrimaryAccount(profile);
+    }
+
     // Native methods.
     private static native void nativeStartFetchingAccountInfoFor(
             Profile profile, String accountId, int imageSidePixels);
+    private static native String nativeGetCachedNameForPrimaryAccount(Profile profile);
+    private static native Bitmap nativeGetCachedAvatarForPrimaryAccount(Profile profile);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/share/OWNERS
new file mode 100644
index 0000000..c203f93
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/OWNERS
@@ -0,0 +1,2 @@
+aurimas@chromium.org
+dtrainor@chromium.org
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDialogAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDialogAdapter.java
new file mode 100644
index 0000000..fce5d01
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDialogAdapter.java
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.share;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.graphics.drawable.Drawable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.chromium.chrome.R;
+
+import java.util.List;
+
+/**
+ * Adapter that provides the list of activities via which a web page can be shared.
+ */
+class ShareDialogAdapter extends ArrayAdapter<ResolveInfo> {
+    private final LayoutInflater mInflater;
+    private final PackageManager mManager;
+
+    /**
+     * @param context Context used to for layout inflation.
+     * @param manager PackageManager used to query for activity information.
+     * @param objects The list of possible share intents.
+     */
+    public ShareDialogAdapter(Context context, PackageManager manager, List<ResolveInfo> objects) {
+        super(context, R.layout.share_dialog_item, objects);
+        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        mManager = manager;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        View view;
+        if (convertView == null) {
+            view = mInflater.inflate(R.layout.share_dialog_item, parent, false);
+        } else {
+            view = convertView;
+        }
+        TextView text = (TextView) view.findViewById(R.id.text);
+        ImageView icon = (ImageView) view.findViewById(R.id.icon);
+
+        text.setText(getItem(position).loadLabel(mManager));
+        icon.setImageDrawable(loadIconForResolveInfo(getItem(position)));
+        return view;
+    }
+
+    private Drawable loadIconForResolveInfo(ResolveInfo info) {
+        try {
+            final int iconRes = info.getIconResource();
+            if (iconRes != 0) {
+                Resources res = mManager.getResourcesForApplication(info.activityInfo.packageName);
+                Drawable icon = res.getDrawable(iconRes);
+                return icon;
+            }
+        } catch (NameNotFoundException e) {
+            // Could not find the icon. loadIcon call below will return the default app icon.
+        }
+        return info.loadIcon(mManager);
+    }
+
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
new file mode 100644
index 0000000..e9e6e61
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -0,0 +1,184 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.share;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.preference.PreferenceManager;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+
+import org.chromium.chrome.R;
+
+import java.util.List;
+
+/**
+ * A helper class that helps to start an intent to share titles and URLs.
+ */
+public class ShareHelper {
+
+    private static final String PACKAGE_NAME_KEY = "last_shared_package_name";
+    private static final String CLASS_NAME_KEY = "last_shared_class_name";
+
+    /**
+     * Intent extra for sharing screenshots via the Share intent.
+     *
+     * Copied from {@link android.provider.Browser} as it is marked as {@literal @hide}.
+     */
+    private static final String EXTRA_SHARE_SCREENSHOT = "share_screenshot";
+
+    private ShareHelper() {}
+
+    /**
+     * Creates and shows a share intent picker dialog or starts a share intent directly with the
+     * activity that was most recently used to share based on shareDirectly value.
+     *
+     * @param shareDirectly Whether it should share directly with the activity that was most
+     *                      recently used to share.
+     * @param activity Activity that is used to access package manager.
+     * @param title Title of the page to be shared.
+     * @param url URL of the page to be shared.
+     * @param screenshot Screenshot of the page to be shared.
+     */
+    public static void share(boolean shareDirectly, Activity activity, String title, String url,
+            Bitmap screenshot) {
+        if (shareDirectly) {
+            shareWithLastUsed(activity, title, url, screenshot);
+        } else {
+            showShareDialog(activity, title, url, screenshot);
+        }
+    }
+
+    /**
+     * Creates and shows a share intent picker dialog.
+     *
+     * @param activity Activity that is used to access package manager.
+     * @param title Title of the page to be shared.
+     * @param url URL of the page to be shared.
+     * @param screenshot Screenshot of the page to be shared.
+     */
+    private static void showShareDialog(final Activity activity, final String title,
+            final String url, final Bitmap screenshot) {
+        Intent intent = getShareIntent(title, url, screenshot);
+        PackageManager manager = activity.getPackageManager();
+        List<ResolveInfo> resolveInfoList = manager.queryIntentActivities(intent, 0);
+        assert resolveInfoList.size() > 0;
+        if (resolveInfoList.size() == 0) return;
+
+        final ShareDialogAdapter adapter =
+                new ShareDialogAdapter(activity, manager, resolveInfoList);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setTitle(activity.getString(R.string.share_link_chooser_title));
+        builder.setAdapter(adapter, null);
+
+        final AlertDialog dialog = builder.create();
+        dialog.show();
+        dialog.getListView().setOnItemClickListener(new OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                ResolveInfo info = adapter.getItem(position);
+                ActivityInfo ai = info.activityInfo;
+                ComponentName component =
+                        new ComponentName(ai.applicationInfo.packageName, ai.name);
+                setLastShareComponentName(activity, component);
+                Intent intent = getDirectShareIntentForComponent(title, url, screenshot, component);
+                activity.startActivity(intent);
+                dialog.dismiss();
+            }
+        });
+    }
+
+    /**
+     * Starts a share intent with the activity that was most recently used to share.
+     * If there is no most recently used activity, it does nothing.
+     * @param activity Activity that is used to start the share intent.
+     * @param title Title of the page to be shared.
+     * @param url URL of the page to be shared.
+     * @param screenshot Screenshot of the page to be shared.
+     */
+    private static void shareWithLastUsed(
+            Activity activity, String title, String url, Bitmap screenshot) {
+        ComponentName component = getLastShareComponentName(activity);
+        if (component == null) return;
+        Intent intent = getDirectShareIntentForComponent(title, url, screenshot, component);
+        activity.startActivity(intent);
+    }
+
+    /**
+     * Set the icon and the title for the menu item used for direct share.
+     *
+     * @param activity Activity that is used to access the package manager.
+     * @param item The menu item that is used for direct share
+     */
+    public static void configureDirectShareMenuItem(Activity activity, MenuItem item) {
+        Drawable directShareIcon = null;
+        CharSequence directShareTitle = null;
+
+        ComponentName component = getLastShareComponentName(activity);
+        if (component != null) {
+            try {
+                directShareIcon = activity.getPackageManager().getActivityIcon(component);
+                ApplicationInfo ai = activity.getPackageManager().getApplicationInfo(
+                        component.getPackageName(), 0);
+                directShareTitle = activity.getPackageManager().getApplicationLabel(ai);
+            } catch (NameNotFoundException exception) {
+                // Use the default null values.
+            }
+        }
+
+        item.setIcon(directShareIcon);
+        if (directShareTitle != null) {
+            item.setTitle(activity.getString(R.string.accessibility_menu_share_via,
+                    directShareTitle));
+        }
+    }
+
+    private static Intent getShareIntent(String title, String url, Bitmap screenshot) {
+        Intent intent = new Intent(Intent.ACTION_SEND);
+        intent.setType("text/plain");
+        intent.putExtra(Intent.EXTRA_SUBJECT, title);
+        intent.putExtra(Intent.EXTRA_TEXT, url);
+        if (screenshot != null) intent.putExtra(EXTRA_SHARE_SCREENSHOT, screenshot);
+        return intent;
+    }
+
+    private static Intent getDirectShareIntentForComponent(String title, String url,
+            Bitmap screenshot, ComponentName component) {
+        Intent intent = getShareIntent(title, url, screenshot);
+        intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
+                | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+        intent.setComponent(component);
+        return intent;
+    }
+
+    private static ComponentName getLastShareComponentName(Context context) {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+        String packageName = preferences.getString(PACKAGE_NAME_KEY, null);
+        String className = preferences.getString(CLASS_NAME_KEY, null);
+        if (packageName == null || className == null) return null;
+        return new ComponentName(packageName, className);
+    }
+
+    private static void setLastShareComponentName(Context context, ComponentName component) {
+        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
+        SharedPreferences.Editor editor = preferences.edit();
+        editor.putString(PACKAGE_NAME_KEY, component.getPackageName());
+        editor.putString(CLASS_NAME_KEY, component.getClassName());
+        editor.apply();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
index dfca176..c7f513c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninManager.java
@@ -377,6 +377,13 @@
         }
     }
 
+    /**
+     * @return True if the new profile management is enabled.
+     */
+    public static boolean isNewProfileManagementEnabled() {
+        return nativeIsNewProfileManagementEnabled();
+    }
+
     // Native methods.
     private native long nativeInit();
     private native boolean nativeShouldLoadPolicyForUser(String username);
@@ -388,4 +395,5 @@
     private native String nativeGetManagementDomain(long nativeSigninManagerAndroid);
     private native void nativeWipeProfileData(long nativeSigninManagerAndroid);
     private native void nativeLogInSignedInUser(long nativeSigninManagerAndroid);
+    private static native boolean nativeIsNewProfileManagementEnabled();
 }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index 1026390..a7bfb6d 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -215,6 +215,15 @@
       <message name="IDS_MENU_PRINT" desc="Menu item for printing the current page. [CHAR-LIMIT=27]">
         Print…
       </message>
+      <message name="IDS_MENU_SHARE_PAGE" desc="Menu item for sharing the current page. [CHAR-LIMIT=27]">
+        Share…
+      </message>
+      <message name="IDS_SHARE_LINK_CHOOSER_TITLE" desc="title for the share dialog when sharing the current address [CHAR-LIMIT=27]">
+        Share via
+      </message>
+      <message name="IDS_ACCESSIBILITY_MENU_SHARE_VIA" desc="Content description share current page via the most recently used application menu item">
+        Share via <ph name="APPLICATION">%s<ex>Gmail</ex></ph>
+      </message>
       <message name="IDS_ERROR_PRINTING_FAILED" desc="Generic error message shown when Chrome fails to print the current page for some reason.">
         There was a problem printing the page. Please try again.
       </message>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_am.xtb b/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
index b088275..077ed45 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_am.xtb
@@ -7,7 +7,7 @@
 <translation id="7644305409888602715">ገጹን ወደ <ph name="SOURCE_LANGUAGE"/> በመተርጎም ላይ...</translation>
 <translation id="1491151370853475546">ይህን ገጽ ዳግም ይጫኑ</translation>
 <translation id="641643625718530986">አትም…</translation>
-<translation id="7658239707568436148">ሰርዝ</translation>
+<translation id="7658239707568436148">ይቅር</translation>
 <translation id="6458785801851713928">ማመሳሰል ለእርስዎ ጎራ አይገኝም።</translation>
 <translation id="2731700343119398978">እባክዎ ይጠብቁ...</translation>
 <translation id="7378627244592794276">አይ</translation>
diff --git a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
index 25d4500..e3f8c47 100644
--- a/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
+++ b/chrome/android/java/strings/translations/android_chrome_strings_de.xtb
@@ -51,7 +51,7 @@
 <translation id="5164482624172255778">Soll Google Chrome ab dem nächsten Aufruf eine Übersetzung von Seiten dieser Website anbieten, die auf <ph name="LANGUAGE"/> sind?</translation>
 <translation id="8528538445849828817">Sprache der Seite: <ph name="SOURCE_LANGUAGE"/></translation>
 <translation id="6512448926095770873">Diese Seite verlassen</translation>
-<translation id="7947953824732555851">Annehmen und anmelden</translation>
+<translation id="7947953824732555851">Akzeptieren und anmelden</translation>
 <translation id="6040143037577758943">Schließen</translation>
 <translation id="969096075394517431">Sprachen ändern</translation>
 <translation id="5032574515228824816">Eingabeaufforderung</translation>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
index 0a70e14..0eab086 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/AppMenuTest.java
@@ -209,8 +209,15 @@
         assertTrue(mAppMenu.isShowing());
     }
 
-    private void pressKey(int keycode) {
-        getInstrumentation().sendKeyDownUpSync(keycode);
+    private void pressKey(final int keycode) {
+        final View view = mAppMenu.getPopup().getListView();
+        ThreadUtils.runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, keycode));
+                view.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, keycode));
+            }
+        });
         getInstrumentation().waitForIdleSync();
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/OWNERS b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/OWNERS
new file mode 100644
index 0000000..6b0cb44
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/appmenu/OWNERS
@@ -0,0 +1,2 @@
+aurimas@chromium.org
+kkimlabs@chromium.org
\ No newline at end of file
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
index 8bad5f9..8b908e0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/AutofillPopupTest.java
@@ -23,6 +23,8 @@
 import org.chromium.content.browser.test.util.TouchCommon;
 import org.chromium.ui.autofill.AutofillPopup;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
 
@@ -44,7 +46,7 @@
     private static final String EMAIL = "john@acme.inc";
     private static final String ORIGIN = "https://www.example.com";
 
-    private static final String PAGE_DATA = UrlUtils.encodeHtmlDataUri(
+    private static final String BASIC_PAGE_DATA = UrlUtils.encodeHtmlDataUri(
             "<html><head><meta name=\"viewport\"" +
             "content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\" /></head>" +
             "<body><form method=\"POST\">" +
@@ -56,28 +58,81 @@
             "<input type=\"text\" id=\"zc\" autocomplete=\"postal-code\"><br>" +
             "<input type=\"text\" id=\"em\" autocomplete=\"email\"><br>" +
             "<input type=\"text\" id=\"ph\" autocomplete=\"tel\"><br>" +
+            "<input type=\"text\" id=\"fx\" autocomplete=\"fax\"><br>" +
+            "<select id=\"co\" autocomplete=\"country\"><br>" +
+            "<option value=\"BR\">Brazil</option>" +
+            "<option value=\"US\">United States</option>" +
+            "</select>" +
+            "<input type=\"submit\" />" +
+            "</form></body></html>");
+
+    private static final String INITIATING_ELEMENT_FILLED = UrlUtils.encodeHtmlDataUri(
+            "<html><head><meta name=\"viewport\"" +
+            "content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\" /></head>" +
+            "<body><form method=\"POST\">" +
+            "<input type=\"text\" id=\"fn\" autocomplete=\"given-name\" value=\"J\"><br>" +
+            "<input type=\"text\" id=\"ln\" autocomplete=\"family-name\"><br>" +
+            "<input type=\"text\" id=\"em\" autocomplete=\"email\"><br>" +
+            "<select id=\"co\" autocomplete=\"country\"><br>" +
+            "<option value=\"US\">United States</option>" +
+            "<option value=\"BR\">Brazil</option>" +
+            "</select>" +
+            "<input type=\"submit\" />" +
+            "</form></body></html>");
+
+    private static final String ANOTHER_ELEMENT_FILLED = UrlUtils.encodeHtmlDataUri(
+            "<html><head><meta name=\"viewport\"" +
+            "content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\" /></head>" +
+            "<body><form method=\"POST\">" +
+            "<input type=\"text\" id=\"fn\" autocomplete=\"given-name\"><br>" +
+            "<input type=\"text\" id=\"ln\" autocomplete=\"family-name\"><br>" +
+            "<input type=\"text\" id=\"em\" autocomplete=\"email\" value=\"foo@example.com\"><br>" +
+            "<select id=\"co\" autocomplete=\"country\"><br>" +
+            "<option></option>" +
+            "<option value=\"BR\">Brazil</option>" +
+            "<option value=\"US\">United States</option>" +
+            "</select>" +
+            "<input type=\"submit\" />" +
+            "</form></body></html>");
+
+    private static final String INVALID_OPTION = UrlUtils.encodeHtmlDataUri(
+            "<html><head><meta name=\"viewport\"" +
+            "content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0\" /></head>" +
+            "<body><form method=\"POST\">" +
+            "<input type=\"text\" id=\"fn\" autocomplete=\"given-name\" value=\"J\"><br>" +
+            "<input type=\"text\" id=\"ln\" autocomplete=\"family-name\"><br>" +
+            "<input type=\"text\" id=\"em\" autocomplete=\"email\"><br>" +
+            "<select id=\"co\" autocomplete=\"country\"><br>" +
+            "<option value=\"GB\">Great Britain</option>" +
+            "<option value=\"BR\">Brazil</option>" +
+            "</select>" +
             "<input type=\"submit\" />" +
             "</form></body></html>");
 
     private AutofillTestHelper mHelper;
+    private List<AutofillLogger.LogEntry> mAutofillLoggedEntries;
 
     @Override
     public void setUp() throws Exception {
         super.setUp();
         clearAppData();
-        launchChromeShellWithUrl(PAGE_DATA);
-        assertTrue(waitForActiveShellToBeDoneLoading());
-        mHelper = new AutofillTestHelper();
+        mAutofillLoggedEntries = new ArrayList<AutofillLogger.LogEntry>();
+        AutofillLogger.setLogger(
+            new AutofillLogger.Logger() {
+                @Override
+                public void didFillField(AutofillLogger.LogEntry logEntry) {
+                    mAutofillLoggedEntries.add(logEntry);
+                }}
+        );
     }
 
-    /**
-     * Tests that bringing up an Autofill and clicking on the first entry fills out the expected
-     * Autofill information.
-     */
-    @MediumTest
-    @Feature({"autofill"})
-    public void testClickAutofillPopupSuggestion()
+    private TestCallbackHelperContainer loadAndFillForm(
+            final String formDataUrl, final String inputText)
             throws InterruptedException, ExecutionException, TimeoutException {
+        launchChromeShellWithUrl(formDataUrl);
+        assertTrue(waitForActiveShellToBeDoneLoading());
+        mHelper = new AutofillTestHelper();
+
         // The TestInputMethodManagerWrapper intercepts showSoftInput so that a keyboard is never
         // brought up.
         final ContentView view = getActivity().getActiveContentView();
@@ -102,7 +157,8 @@
         ThreadUtils.runOnUiThreadBlocking(new Runnable() {
             @Override
             public void run() {
-                view.getContentViewCore().getInputConnectionForTest().setComposingText("J", 1);
+                view.getContentViewCore().getInputConnectionForTest().setComposingText(
+                        inputText, 1);
             }
         });
 
@@ -119,6 +175,20 @@
 
         waitForInputFieldFill(view, viewClient);
 
+        return viewClient;
+    }
+
+    /**
+     * Tests that bringing up an Autofill and clicking on the first entry fills out the expected
+     * Autofill information.
+     */
+    @MediumTest
+    @Feature({"autofill"})
+    public void testClickAutofillPopupSuggestion()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        TestCallbackHelperContainer viewClient = loadAndFillForm(BASIC_PAGE_DATA, "J");
+        final ContentView view = getActivity().getActiveContentView();
+
         assertEquals("First name did not match",
                 FIRST_NAME, DOMUtils.getNodeValue(view, viewClient, "fn"));
         assertEquals("Last name did not match",
@@ -129,12 +199,84 @@
                 ADDRESS_LINE2, DOMUtils.getNodeValue(view, viewClient, "a2"));
         assertEquals("City did not match",
                 CITY, DOMUtils.getNodeValue(view, viewClient, "ct"));
-        assertEquals("Zip code des not match",
+        assertEquals("Zip code did not match",
                 ZIP_CODE, DOMUtils.getNodeValue(view, viewClient, "zc"));
-        assertEquals("Email does not match",
+        assertEquals("Country did not match",
+                COUNTRY, DOMUtils.getNodeValue(view, viewClient, "co"));
+        assertEquals("Email did not match",
                 EMAIL, DOMUtils.getNodeValue(view, viewClient, "em"));
-        assertEquals("Phone number does not match",
+        assertEquals("Phone number did not match",
                 PHONE_NUMBER, DOMUtils.getNodeValue(view, viewClient, "ph"));
+
+        final String profileFullName = FIRST_NAME + " " + LAST_NAME;
+        final int loggedEntries = 9;
+        assertEquals("Mismatched number of logged entries",
+                loggedEntries, mAutofillLoggedEntries.size());
+        assertLogged(FIRST_NAME, profileFullName);
+        assertLogged(LAST_NAME, profileFullName);
+        assertLogged(ADDRESS_LINE1, profileFullName);
+        assertLogged(ADDRESS_LINE2, profileFullName);
+        assertLogged(CITY, profileFullName);
+        assertLogged(ZIP_CODE, profileFullName);
+        assertLogged(COUNTRY, profileFullName);
+        assertLogged(EMAIL, profileFullName);
+        assertLogged(PHONE_NUMBER, profileFullName);
+    }
+
+    /**
+     * Tests that bringing up an Autofill and clicking on the partially filled first
+     * element will still fill the entire form (including the initiating element itself).
+     */
+    @MediumTest
+    @Feature({"autofill"})
+    public void testLoggingInitiatedElementFilled()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        loadAndFillForm(INITIATING_ELEMENT_FILLED, "o");
+        final String profileFullName = FIRST_NAME + " " + LAST_NAME;
+        final int loggedEntries = 4;
+        assertEquals("Mismatched number of logged entries",
+                loggedEntries, mAutofillLoggedEntries.size());
+        assertLogged(FIRST_NAME, profileFullName);
+        assertLogged(LAST_NAME, profileFullName);
+        assertLogged(EMAIL, profileFullName);
+        assertLogged(COUNTRY, profileFullName);
+    }
+
+    /**
+     * Tests that bringing up an Autofill and clicking on the empty first element
+     * will fill the all other elements except the previously filled email.
+     */
+    @MediumTest
+    @Feature({"autofill"})
+    public void testLoggingAnotherElementFilled()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        loadAndFillForm(ANOTHER_ELEMENT_FILLED, "J");
+        final String profileFullName = FIRST_NAME + " " + LAST_NAME;
+        final int loggedEntries = 3;
+        assertEquals("Mismatched number of logged entries",
+                loggedEntries, mAutofillLoggedEntries.size());
+        assertLogged(FIRST_NAME, profileFullName);
+        assertLogged(LAST_NAME, profileFullName);
+        assertLogged(COUNTRY, profileFullName);
+        // Email will not be logged since it already had some data.
+    }
+
+    /**
+     * Tests that selecting a value not present in <option> will not be filled.
+     */
+    @MediumTest
+    @Feature({"autofill"})
+    public void testNotLoggingInvalidOption()
+            throws InterruptedException, ExecutionException, TimeoutException {
+        loadAndFillForm(INVALID_OPTION, "o");
+        final String profileFullName = FIRST_NAME + " " + LAST_NAME;
+        final int loggedEntries = 3;
+        assertEquals("Mismatched number of logged entries",
+                loggedEntries, mAutofillLoggedEntries.size());
+        assertLogged(FIRST_NAME, profileFullName);
+        assertLogged(LAST_NAME, profileFullName);
+        assertLogged(EMAIL, profileFullName);
+        // Country will not be logged since "US" is not a valid <option>.
     }
 
     // Wait and assert helper methods -------------------------------------------------------------
@@ -188,4 +330,14 @@
                     }
                 }));
     }
+
+    private void assertLogged(String autofilledValue, String profileFullName) {
+        for (AutofillLogger.LogEntry entry : mAutofillLoggedEntries) {
+            if (entry.getAutofilledValue().equals(autofilledValue) &&
+                entry.getProfileFullName().equals(profileFullName)) {
+                return;
+            }
+        }
+        fail("Logged entry not found [" + autofilledValue + "," + profileFullName + "]");
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java
index e8ff481..7a0035e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/banners/InstallerDelegateTest.java
@@ -51,12 +51,14 @@
     private boolean mResultFinished;
     private InstallerDelegate mResultDelegate;
     private boolean mResultSuccess;
+    private boolean mInstallStarted;
 
     @Override
     public void onInstallFinished(InstallerDelegate delegate, boolean success) {
         mResultDelegate = delegate;
         mResultSuccess = success;
         mResultFinished = true;
+        assertTrue(mInstallStarted);
     }
 
     @Override
@@ -86,6 +88,7 @@
 
     private void startMonitoring() throws InterruptedException {
         mTestDelegate.start();
+        mInstallStarted = true;
 
         // Wait until we know that the Thread is running the InstallerDelegate task.
         assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
@@ -147,4 +150,14 @@
         startMonitoring();
         checkResults(false);
     }
+
+    /**
+     * Makes sure that the runnable isn't called until returning from start().
+     */
+    public void testRunnableRaceCondition() throws InterruptedException {
+        mPackageManager.isInstalled = true;
+        mTestDelegate.setTimingForTests(1, 5000);
+        startMonitoring();
+        checkResults(true);
+    }
 }
diff --git a/chrome/android/shell/java/AndroidManifest.xml b/chrome/android/shell/java/AndroidManifest.xml
index 6c7945d..b3e17ef 100644
--- a/chrome/android/shell/java/AndroidManifest.xml
+++ b/chrome/android/shell/java/AndroidManifest.xml
@@ -14,6 +14,7 @@
             android:protectionLevel="signature" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.CAMERA" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS"/>
     <uses-permission android:name="android.permission.INTERNET"/>
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java
index 700c509..8b61726 100644
--- a/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java
+++ b/chrome/android/shell/java/src/org/chromium/chrome/shell/ChromeShellActivity.java
@@ -12,6 +12,7 @@
 import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.View;
 import android.widget.Toast;
 
 import com.google.common.annotations.VisibleForTesting;
@@ -26,12 +27,14 @@
 import org.chromium.chrome.browser.appmenu.AppMenuPropertiesDelegate;
 import org.chromium.chrome.browser.printing.PrintingControllerFactory;
 import org.chromium.chrome.browser.printing.TabPrinter;
+import org.chromium.chrome.browser.share.ShareHelper;
 import org.chromium.chrome.shell.sync.SyncController;
 import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
 import org.chromium.content.browser.ActivityContentVideoViewClient;
 import org.chromium.content.browser.BrowserStartupController;
 import org.chromium.content.browser.ContentView;
 import org.chromium.content.browser.DeviceUtils;
+import org.chromium.content.common.ContentSwitches;
 import org.chromium.printing.PrintManagerDelegateImpl;
 import org.chromium.printing.PrintingController;
 import org.chromium.sync.signin.ChromeSigninController;
@@ -129,7 +132,25 @@
 
         mWindow = sWindowAndroidFactory.getActivityWindowAndroid(this);
         mWindow.restoreInstanceState(savedInstanceState);
-        mTabManager.initialize(mWindow, new ActivityContentVideoViewClient(this));
+        mTabManager.initialize(mWindow, new ActivityContentVideoViewClient(this) {
+            @Override
+            public void onShowCustomView(View view) {
+                super.onShowCustomView(view);
+                if (!CommandLine.getInstance().hasSwitch(
+                        ContentSwitches.DISABLE_OVERLAY_FULLSCREEN_VIDEO_SUBTITLE)) {
+                    mTabManager.setOverlayVideoMode(true);
+                }
+            }
+
+            @Override
+            public void onDestroyContentVideoView() {
+                super.onDestroyContentVideoView();
+                if (!CommandLine.getInstance().hasSwitch(
+                        ContentSwitches.DISABLE_OVERLAY_FULLSCREEN_VIDEO_SUBTITLE)) {
+                    mTabManager.setOverlayVideoMode(false);
+                }
+            }
+        });
 
         String startupUrl = getUrlFromIntent(getIntent());
         if (!TextUtils.isEmpty(startupUrl)) {
@@ -291,6 +312,11 @@
                     activeTab.goForward();
                 }
                 return true;
+            case R.id.share_menu_id:
+            case R.id.direct_share_menu_id:
+                ShareHelper.share(item.getItemId() == R.id.direct_share_menu_id, this,
+                        activeTab.getTitle(), activeTab.getUrl(), null);
+                return true;
             default:
                 return super.onOptionsItemSelected(item);
         }
@@ -315,13 +341,16 @@
 
     @Override
     public void prepareMenu(Menu menu) {
+        menu.setGroupVisible(R.id.MAIN_MENU, true);
+        ChromeShellTab activeTab = getActiveTab();
+
         // Disable the "Back" menu item if there is no page to go to.
         MenuItem backMenuItem = menu.findItem(R.id.back_menu_id);
-        backMenuItem.setEnabled(getActiveTab().canGoBack());
+        backMenuItem.setEnabled(activeTab != null ? activeTab.canGoBack() : false);
 
         // Disable the "Forward" menu item if there is no page to go to.
         MenuItem forwardMenuItem = menu.findItem(R.id.forward_menu_id);
-        forwardMenuItem.setEnabled(getActiveTab().canGoForward());
+        forwardMenuItem.setEnabled(activeTab != null ? activeTab.canGoForward() : false);
 
         // ChromeShell does not know about bookmarks yet
         menu.findItem(R.id.bookmark_this_page_id).setEnabled(true);
@@ -335,10 +364,16 @@
 
         menu.findItem(R.id.print).setVisible(ApiCompatibilityUtils.isPrintingSupported());
 
-        menu.findItem(R.id.distill_page).setVisible(
-                CommandLine.getInstance().hasSwitch(ChromeShellSwitches.ENABLE_DOM_DISTILLER));
-
-        menu.setGroupVisible(R.id.MAIN_MENU, true);
+        MenuItem distillPageItem = menu.findItem(R.id.distill_page);
+        if (CommandLine.getInstance().hasSwitch(ChromeShellSwitches.ENABLE_DOM_DISTILLER)) {
+            String url = activeTab != null ? activeTab.getUrl() : null;
+            distillPageItem.setEnabled(!TextUtils.isEmpty(url) &&
+                    !url.startsWith(CHROME_DISTILLER_SCHEME));
+            distillPageItem.setVisible(true);
+        } else {
+            distillPageItem.setVisible(false);
+        }
+        ShareHelper.configureDirectShareMenuItem(this, menu.findItem(R.id.direct_share_menu_id));
     }
 
     @VisibleForTesting
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/MenuHandler.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/MenuHandler.java
deleted file mode 100644
index 6db23ec..0000000
--- a/chrome/android/shell/java/src/org/chromium/chrome/shell/MenuHandler.java
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.shell;
-
-/**
- * By implementing this interface the class declares that it has functionality available to open a
- * popup menu visible to the user.
- */
-public interface MenuHandler {
-    public void showPopupMenu();
-}
\ No newline at end of file
diff --git a/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java b/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java
index 3a2d294..025b1f2 100644
--- a/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java
+++ b/chrome/android/shell/java/src/org/chromium/chrome/shell/TabManager.java
@@ -79,6 +79,15 @@
     }
 
     /**
+     * Enter or leave overlay video mode.
+     * @param enabled Whether overlay mode is enabled.
+     */
+    public void setOverlayVideoMode(boolean enabled) {
+        if (mContentViewRenderView == null) return;
+        mContentViewRenderView.setOverlayVideoMode(enabled);
+    }
+
+    /**
      * @return The currently visible {@link ChromeShellTab}.
      */
     public ChromeShellTab getCurrentTab() {
diff --git a/chrome/android/shell/res/menu/main_menu.xml b/chrome/android/shell/res/menu/main_menu.xml
index e15ca02..a4b59db 100644
--- a/chrome/android/shell/res/menu/main_menu.xml
+++ b/chrome/android/shell/res/menu/main_menu.xml
@@ -4,29 +4,46 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file.
 -->
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
 
-<menu xmlns:android="http://schemas.android.com/apk/res/android">
-    <group android:id="@+id/MAIN_MENU"
-           android:visible="false">
+    <group
+        android:id="@+id/MAIN_MENU"
+        android:visible="false" >
         <item>
             <menu>
-              <item android:id="@+id/back_menu_id"
-                android:title="@string/accessibility_menu_back"
-                android:icon="@drawable/back_button_selector"/>
-              <item android:id="@+id/forward_menu_id"
-                android:title="@string/accessibility_menu_forward"
-                android:icon="@drawable/forward_button_selector"/>
-              <item android:id="@+id/bookmark_this_page_id"
-                android:title="@string/accessibility_menu_bookmark"
-                android:icon="@drawable/star"/>
+                <item
+                    android:id="@+id/back_menu_id"
+                    android:icon="@drawable/back_button_selector"
+                    android:title="@string/accessibility_menu_back"/>
+                <item
+                    android:id="@+id/forward_menu_id"
+                    android:icon="@drawable/forward_button_selector"
+                    android:title="@string/accessibility_menu_forward"/>
+                <item
+                    android:id="@+id/bookmark_this_page_id"
+                    android:icon="@drawable/star"
+                    android:title="@string/accessibility_menu_bookmark"/>
             </menu>
         </item>
-        <item android:id="@+id/signin"
-              android:title="@string/signin_sign_in" />
-        <item android:id="@+id/print"
-              android:title="@string/print_menu" />
-        <item android:id="@+id/distill_page"
-              android:title="@string/distill_page_menu" />
+        <item
+            android:id="@+id/signin"
+            android:title="@string/signin_sign_in"/>
+        <item
+            android:id="@+id/print"
+            android:title="@string/print_menu"/>
+        <item
+            android:id="@+id/distill_page"
+            android:title="@string/distill_page_menu"/>
+        <item>
+            <menu>
+                <item
+                    android:id="@+id/share_menu_id"
+                    android:title="@string/menu_share_page"/>
+                <item
+                    android:id="@+id/direct_share_menu_id"
+                    android:title="@null"/>
+            </menu>
+        </item>
     </group>
-</menu>
 
+</menu>
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 50070e0..e2cca2c 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -1151,9 +1151,15 @@
   <message name="IDS_WELCOME_SCREEN_TITLE" desc="Title of the OOBE welcome screen">
     Connect
   </message>
+  <message name="IDS_NETWORK_SCREEN_ACCESSIBLE_TITLE" desc="Text to be spoken on opening the OOBE network screen">
+    Welcome! Set your language and network
+  </message>
   <message name="IDS_EULA_SCREEN_TITLE" desc="Title of the OOBE EULA screen">
     The small print
   </message>
+  <message name="IDS_EULA_SCREEN_ACCESSIBLE_TITLE" desc="Title to be spoken on opening the OOBE EULA screen">
+    <ph name="PRODUCT_OS_NAME">$1<ex>Chrome OS</ex></ph> terms
+  </message>
   <message name="IDS_AUTOSTART_WARNING_TITLE" desc="Title of the kiosk autostart screen">
     Auto-launch permission requested
   </message>
@@ -1184,6 +1190,9 @@
   <message name="IDS_UPDATE_SCREEN_TITLE" desc="Title of the OOBE update screen">
     Update
   </message>
+  <message name="IDS_UPDATE_SCREEN_ACCESSIBLE_TITLE" desc="Title to be spoken on opening the OOBE update screen">
+    Chrome updates automatically so you always have the freshest version
+  </message>
   <message name="IDS_SIGNIN_SCREEN_TITLE" desc="Title of OOBE/Add User sign-in screen">
     Sign in
   </message>
@@ -1341,7 +1350,7 @@
   <message name="IDS_LOGIN_PREVIOUS_PASSWORD" desc="Password field text on the password changed dialog">
     Previous password
   </message>
-  <message name="IDS_LOGIN_SAML_NOTICE" desc="Text message displayed above SAML portal to learly indicate that the user is being redirected to another sign-in provider.">
+  <message name="IDS_LOGIN_SAML_NOTICE" desc="Text message displayed above SAML portal to early indicate that the user is being redirected to another sign-in provider.">
     The sign-in service below is hosted by <ph name="SAML_DOMAIN">$1<ex>saml.com</ex></ph>. Sign in to continue.
   </message>
   <message name="IDS_LOGIN_CONFIRM_PASSWORD_TITLE" desc="Title for the confirm password dialog.">
@@ -1444,12 +1453,18 @@
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_MANAGER_PASSWORD_HINT" desc="Supervised user dialog, manager selection page, text shown as a hint in the user password field.">
     Enter password
   </message>
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_SETUP_ACCESSIBLE_TITLE" desc="Text to be spoken on opening supervised user creation username and password set-up dialog.">
+    Set up new supervised user
+  </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_TITLE" desc="Supervised user dialog, new user page, title for name of new user">
     Create a name -
   </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_EXPLANATION" desc="Supervised user dialog, new user page, explanation for name of new user">
     This supervised user will be managed by <ph name="MANAGER_EMAIL">$1<ex>john.doe@example.com</ex></ph>.
   </message>
+  <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_HINT" desc="Text shown as a hint in the new user name field in supervised user creation dialog.">
+    Enter new name
+  </message>
   <message name="IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_TITLE" desc="Supervised user dialog, new user page, title for password for new user.">
     Create a password -
   </message>
@@ -1788,6 +1803,9 @@
   <message name="IDS_OPTIONS_SETTINGS_BLUETOOTH_SCANNING">
     Searching for devices...
   </message>
+  <message name="IDS_OPTIONS_SETTINGS_BLUETOOTH_SCAN_STOPPED">
+    Device scan stopped.
+  </message>
   <message name="IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES">
     No devices
   </message>
@@ -1959,6 +1977,9 @@
   <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OVERSCAN" desc="The section title for TV alignment (calibration of display overscan) option for a selected display.">
     TV alignment:
   </message>
+  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE" desc="The section title for color calibration profile selection.">
+    Color profile:
+  </message>
   <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_MIRRORING" desc="Button label to start display mirroring.">
     Start mirroring
   </message>
@@ -1980,6 +2001,18 @@
   <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN" desc="Button label to start calibrating the overscan preference.">
     Adjust...
   </message>
+  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_STANDARD" desc="The color profile name for 'standard'.">
+    Standard
+  </message>
+  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_DYNAMIC" desc="The color profile name for 'dynamic'.">
+    Dynamic
+  </message>
+  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_MOVIE" desc="The color profile name for 'movie'.">
+    Movie
+  </message>
+  <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_READING" desc="The color profile name for 'reading'.">
+    Reading
+  </message>
   <message name="IDS_OPTIONS_SETTINGS_DISPLAY_OVERSCAN_TAB_TITLE" desc="Title for the display overscan calibration tab.">
     TV alignment
   </message>
@@ -2031,9 +2064,12 @@
   <message name="IDS_OPTIONS_SETTINGS_OTHER_CELLULAR_NETWORKS" desc="In the settings tab, the text on the button to display other cellular networks.">
     Other mobile network...
   </message>
-  <message name="IDS_OPTIONS_SETTINGS_JOIN_WIFI_NETWORKS" desc="The title for the dialog to join a wifi network.">
+  <message name="IDS_OPTIONS_SETTINGS_JOIN_WIFI_NETWORKS" desc="The title for the dialog to configure and connect to a wifi network.">
     Join Wi-Fi network
   </message>
+  <message name="IDS_OPTIONS_SETTINGS_CONFIGURE_ETHERNET" desc="The title for the dialog to configure an ethernet network.">
+    Configure Ethernet network
+  </message>
   <message name="IDS_OPTIONS_SETTINGS_JOIN_WIMAX_NETWORKS" desc="The title for the dialog to join a wimax network.">
     Join WiMAX network
   </message>
@@ -2134,10 +2170,10 @@
     Discard photo
   </message>
   <message name="IDS_OPTIONS_PHOTO_CAPTURE_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce that a photo was captured.">
-    Captured photo
+    Photo was captured
   </message>
   <message name="IDS_OPTIONS_PHOTO_DISCARD_ACCESSIBLE_TEXT" desc="The accessible message to speak to announce that a photo was discarded.">
-    Discarded photo
+    Photo was discarded
   </message>
   <message name="IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO" desc="The text on the button to flip the camera image horizontally.">
     Flip camera image horizontally
@@ -2675,15 +2711,36 @@
   </message>
 
   <message name="IDS_RESET_SCREEN_WARNING_MSG" desc="Warning text shown on reset screen above the exclamation icon.">
+    Reset this <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device
+  </message>
+  <message name="IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_MSG" desc="Warning text shown on confirmation-form of reset screen above the exclamation icon.">
     Powerwash your <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device
   </message>
+  <message name="IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_AND_ROLLBACK_MSG" desc="Warning text shown on confirmation-form of reset screen above the exclamation icon.">
+    Powerwash your <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device and revert to a previous update
+  </message>
   <message name="IDS_RESET_SCREEN_WARNING_DETAILS" desc="Warning text shown on reset screen below the exclamation icon.">
-    A Powerwash resets your <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device to be just like new. All files and media stored locally on your computer will be erased.
+    Powerwash to reset your <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device to be just like new.
   </message>
-  <message name="IDS_RESET_SCREEN_WARNING_DETAILS_RESTART" desc="Warning text shown on reset screen below the exclamation icon if device needs extra restart before powerwash.">
-    A restart is required before your device can be reset with Powerwash. A Powerwash resets your <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device to be just like new.
+  <message name="IDS_RESET_SCREEN_CONFIRMATION_WARNING_DETAILS" desc="Warning text shown on confirmation-form of reset screen below the exclamation icon.">
+    A Powerwash resets your <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device to be just like new.
   </message>
-  <message name="IDS_RESET_SCREEN_RESET" desc="Reset button text">
+  <message name="IDS_RESET_SCREEN_CONFIRMATION_WARNING_ROLLBACK_DETAILS" desc="Warning text shown on confirmation-form of reset screen below the exclamation icon.">
+    A Powerwash resets your <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device to be just like new. Additionally, your device will revert to a previous update of <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph>.
+  </message>
+  <message name="IDS_RESET_SCREEN_WARNING_DETAILS_DATA" desc="Additional warning text shown on reset screen below the main warning.">
+    All user accounts and local data will be removed.
+  </message>
+  <message name="IDS_RESET_SCREEN_RESTART_MSG" desc="Text shown on reset screen below warning messages if device needs extra restart before powerwash.">
+    A restart is required before your device can be reset.
+  </message>
+  <message name="IDS_RESET_SCREEN_ROLLBACK_OPTION" desc="Checkbox label for rollback option of powerwash process. Is shown on reset screen.">
+    Also revert to a previous <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> update.
+  </message>
+  <message name="IDS_RESET_SCREEN_POWERWASH" desc="Powerwash button text">
+    Powerwash
+  </message>
+  <message name="IDS_RESET_SCREEN_RESET" desc="Reset button text. Button launches powerwash.">
     Reset
   </message>
 
@@ -4699,6 +4756,12 @@
   <message name="IDS_KIOSK_OFFLINE_MESSAGE" desc="An offline message that shows up when a kiosk app can't launch without network connectivity.">
     Please connect to the Internet to launch your app in kiosk mode.
   </message>
+  <message name="IDS_LOGIN_NETWORK_RESTORED_TITLE" desc="An message title shown when network connectivity is restored during kiosk app launch.">
+    Network connectivity restored
+  </message>
+  <message name="IDS_KIOSK_ONLINE_MESSAGE" desc="An message that shows up when a kiosk app is ready to launch after established network connectivity.">
+    Your network connectivity is restored. Please select a different network or press 'Continue' button below to launch your kiosk app.
+  </message>
   <message name="IDS_UPDATE_OFFLINE_MESSAGE" desc="An offline message that shows up in the OOBE update screen.">
     Please connect to the Internet to update your Chromebook.
   </message>
@@ -4741,6 +4804,9 @@
   <message name="IDS_LOGIN_CONFIRM_KIOSK_DIAGNOSTIC_FORMAT" desc="Text to be shown on a dialog to confirm launching kiosk app in diagnostic mode.">
     Are you sure you want to launch "<ph name="APP_NAME">$1<ex>Kiosk App</ex></ph>" in diagnostic mode?
   </message>
+  <message name="IDS_LOGIN_GUEST_SIGNIN_FIX_NETWORK">
+    You may also try to <ph name="GUEST_SIGNIN_LINK_START">$1<ex>&gt;a&lt;</ex></ph>browse as guest<ph name="GUEST_SIGNIN_LINK_END">$2<ex>&gt;/a&lt;</ex></ph> to fix this network error.
+  </message>
   <message name="IDS_LOGIN_CONNECTING_INDICATOR_TEXT" desc="A message to show telling the user that the device is attempting to re-connect to the network.">
     Connecting and verifying<ph name="ANIMATED_ELLIPSIS">$1<ex>...</ex></ph>
   </message>
@@ -4827,10 +4893,10 @@
     Howdy.
   </message>
   <message name="IDS_FIRST_RUN_GREETING_STEP_TEXT_1" desc="First part of message shown on the first dialog of firsr-run tutorial.">
-    Welcome to the Chromebook family. This is no ordinary computer.
+    Welcome to the <ph name="SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> family. This is no ordinary computer.
   </message>
   <message name="IDS_FIRST_RUN_GREETING_STEP_TEXT_2" desc="Second part of message shown on the first dialog of firsr-run tutorial.">
-    This Chromebook was designed to deliver the best experience of the web to you.
+    This <ph name="SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device was designed to deliver the best experience of the web to you.
   </message>
   <message name="IDS_FIRST_RUN_GREETING_STEP_BUTTON" desc="Text on the button located on the first dialog of first-run tutorial.">
     Take a tour
@@ -4854,7 +4920,7 @@
     Have fun! We're here for you.
   </message>
   <message name="IDS_FIRST_RUN_HELP_STEP_TEXT_1" desc="First part of text shown on the first-run tutorial bubble pointing to help button in system tray.">
-    Enjoy your Chromebook. Questions? You can always get help by clicking the "?" in the status tray.
+    Enjoy your <ph name="SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> device. Questions? You can always get help by clicking the "?" in the status tray.
   </message>
   <message name="IDS_FIRST_RUN_HELP_STEP_TEXT_2" desc="Second part of text shown on the first-run tutorial bubble pointing to help button in system tray.">
     Want to discover more awesome features?
@@ -5178,9 +5244,18 @@
   <message name="IDS_ENTERPRISE_ENROLLMENT_DEPROVISIONED_ERROR" desc="Error message to show when enrollment fails because the administrator has deprovisioned the device on the server side.">
     This device has been placed into a deprovisioned state by the administrator. To enable it for enrollment, please have your administrator place the device into a pending state.
   </message>
+  <message name="IDS_ENTERPRISE_ENROLLMENT_DOMAIN_MISMATCH_ERROR" desc="Error message shown when the device doesn't belong to the domain the user tried to enroll it to.">
+    This device cannot be enrolled to the domain your account belongs to because the device is marked for management by a different domain.
+  </message>
   <message name="IDS_ENTERPRISE_ENROLLMENT_SCREEN_TITLE" desc="The title on the enterprise enrollment dialog.">
     Enterprise enrollment
   </message>
+  <message name="IDS_ENTERPRISE_ENROLLMENT_DESCRIPTION" desc="Short description of enterprise enrollment.">
+    Sign in with the username given to you by your organization to enroll your device for enterprise management.
+  </message>
+  <message name="IDS_ENTERPRISE_ENROLLMENT_RE_ENROLLMENT_TEXT" desc="Paragraph explaining previous association of the device with a domain.">
+    This device has been marked for enterprise management by <ph name="MANAGEMENT_DOMAIN">$1<ex>example.com</ex></ph>.
+  </message>
   <message name="IDS_ENTERPRISE_ENROLLMENT_RETRY" desc="Label for the retry button on the error step in the enterprise enrollment dialog.">
     Try again
   </message>
diff --git a/chrome/app/chromium_strings.grd b/chrome/app/chromium_strings.grd
index 5f2bd23..a7d3891 100644
--- a/chrome/app/chromium_strings.grd
+++ b/chrome/app/chromium_strings.grd
@@ -863,6 +863,14 @@
 • Manage your Google Accounts
       </message>
 
+      <!-- Account removal view in the avatar menu bubble -->
+      <message name="IDS_PROFILES_ACCOUNT_REMOVAL_TEXT" desc="Main text of the account removal view when removing a secondary account.">
+        To remove your account, Chromium needs to restart. Make sure you've saved any open work before continuing.
+      </message>
+      <message name="IDS_PROFILES_PRIMARY_ACCOUNT_REMOVAL_TEXT" desc="Main text of the account removal view when removing a primary account.">
+        You're using <ph name="PROFILE_EMAIL">$1<ex>jessica@gmail.com</ex></ph> to sync your Chromium stuff. To update your sync preference or to use Chromium without a Google account, visit settings.
+      </message>
+
       <!-- Sync Promo New Tab Page bubble strings -->
       <message name="IDS_SYNC_PROMO_NTP_BUBBLE_MESSAGE_NEW" desc="The body of the sync promo NTP bubble.">
         Now that you're signed in, you can get your tabs, bookmarks and other Chromium stuff across your laptop, phone and tablet. You will also receive more relevant suggestions and features on Google services.
@@ -942,7 +950,7 @@
         </message>
       </if>
       <if expr="chromeos">
-        <message name="IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error bubble view when the user needs to update their sync passphrase.">
+        <message name="IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error notification when the user needs to update their sync passphrase.">
           Chromium OS could not sync your data. Please update your Sync passphrase.
         </message>
         <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error notification when the user's sign-in credentials are out of date.">
@@ -960,6 +968,9 @@
         On Mac, passwords are saved to your Keychain and may be accessed or synced by other Chromium users sharing this OS X account.
       </message>
 
+      <message name="IDS_AUTOFILL_ADDRESS_BOOK_PROMPT_DESCRIPTION" desc="Text to show in dialog requesting permission to access the user's Address Book contents.">
+        Details from your contacts can help you fill out forms more quickly in Chromium.
+      </message>
       <message name="IDS_AUTOFILL_CC_INFOBAR_TEXT" desc="Text to show in the Autofill credit card request infobar.">
         Do you want Chromium to save this credit card information for completing web forms?
       </message>
@@ -1160,6 +1171,44 @@
         </message>
       </if>
 
+      <!-- Settings API bubble -->
+      <message name="IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_START_PAGES" desc="Text displayed in the Settings API bubble as first line when an extension has changed the start pages.">
+        An extension has changed what page is shown when you start Chromium.
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was just the start pages. The triple single quotes are needed to preserve the space before and after the sentence which is needed when the language (Chrome is being translated to) uses space as word separator. Please preserve them, unless the language being translated to does not use space as word separator.">
+        ''' It also controls what page is shown when you start Chromium. '''
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_HOME" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was both the start page and the home page. See IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES for reason for triple quotes.">
+        ''' It also controls what page is shown when you start Chromium or click the Home button. '''
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_SEARCH" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was both the start page and the search engine. See IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES for reason for triple quotes.">
+        ''' It also controls what page is shown when you start Chromium or search from the Omnibox. '''
+      </message>
+      
+      <!-- Update bubble -->
+      <message name="IDS_REINSTALL_APP" desc="Text for the button the user clicks to reinstall the app.">
+        Reinstall Chromium
+      </message>
+      <if expr="use_titlecase">
+        <message name="IDS_UPGRADE_BUBBLE_MENU_ITEM" desc="In Title Case: Text for the Chrome menu option replacing Update required.">
+          Chromium is Out of Date
+        </message>
+      </if>
+      <if expr="not use_titlecase">
+        <message name="IDS_UPGRADE_BUBBLE_MENU_ITEM" desc="Text for the Chrome menu option replacing Update required.">
+          Chromium is out of date
+        </message>
+      </if>
+      <message name="IDS_UPGRADE_BUBBLE_TITLE" desc="Text for the title of the upgrade bubble view.">
+        Chromium is out of date
+      </message>
+      <message name="IDS_UPGRADE_BUBBLE_TEXT" desc="Text for the upgrade bubble view full description.">
+        Chromium could not update itself to the latest version, so you are missing out on awesome new features and security fixes. You need to manually reinstall Chromium.
+      </message>
+      <message name="IDS_UPGRADE_BUBBLE_REENABLE_TEXT" desc="Text for the upgrade bubble view full description.">
+        Chromium could not update itself to the latest version, so you are missing out on awesome new features and security fixes. You need to update Chromium.
+      </message>
+
       <!-- chrome://ntp -->
       <if expr="not is_android">
         <message name="IDS_NEW_TAB_OTR_EXTENSIONS_MESSAGE"
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 426dd93..42f6bc4 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3546,10 +3546,6 @@
       </message>
       <!-- User Image Selection Dialog -->
       <message name="IDS_USER_IMAGE_SCREEN_TITLE" desc="String to be displayed in the title bar of the user image selection dialog">
-        Smile! Take a picture of yourself and set it as your account picture.
-      </message>
-      <!-- OOBE progress bar labels -->
-      <message name="IDS_OOBE_PICTURE" desc="The label of OOBE progress bar step, must be short">
         Choose your account picture
       </message>
 
@@ -4571,6 +4567,12 @@
       <message name="IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE" desc="Permission string for network list access.">
         Access list of network connections
       </message>
+      <message name="IDS_EXTENSION_PROMPT_WARNING_ACCESSIBILITY_FEATURES_MODIFY" desc="Permission string for modifying acccessibility settings via extension API shown when an extension utilizing the API is installed.">
+        Modify your accessibility settings
+      </message>
+      <message name="IDS_EXTENSION_PROMPT_WARNING_ACCESSIBILITY_FEATURES_READ" desc="Permission string for modifying acccessibility settings via extension API shown when a extension utilizing the API is installed.">
+        Read your accessibility settings
+      </message>
       <message name="IDS_EXTENSION_PROMPT_WARNING_SEARCH_SETTINGS_OVERRIDE" desc="Permission string for search settings override.">
         Change your search settings to: <ph name="SEARCH_HOST">$1<ex>url.search.com</ex></ph>
       </message>
@@ -5399,6 +5401,69 @@
         Extensions running in developer mode can harm your computer. If you're not a developer, you should disable these extensions running in developer mode to stay safe.
       </message>
 
+      <!-- Settings API bubble -->
+      <message name="IDS_EXTENSIONS_DISABLE_EXTENSIONS" desc="Text for the Disable Extensions (note: plural) button">
+        Disable Extensions
+      </message>
+      <if expr="use_titlecase">
+        <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_HOME_PAGE_BUBBLE" desc="In Title Case: Title of a bubble warning users that an extension has overridden their home page setting">
+         Is This the Home Page You Were Expecting?
+        </message>
+      </if>
+      <if expr="not use_titlecase">
+        <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_HOME_PAGE_BUBBLE" desc="Title of a bubble warning users that an extension has overridden their home page setting">
+          Is this the home page you were expecting?
+        </message>
+      </if>
+      <if expr="use_titlecase">
+        <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_STARTUP_PAGES_BUBBLE" desc="In Title Case: Title of a bubble warning users that an extension has overridden their startup pages setting">
+          Is This the Startup Page You Were Expecting?
+        </message>
+      </if>
+      <if expr="not use_titlecase">
+        <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_STARTUP_PAGES_BUBBLE" desc="Title of a bubble warning users that an extension has overridden their startup pages setting">
+          Is this the startup page you were expecting?
+        </message>
+      </if>
+      <if expr="use_titlecase">
+        <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_SEARCH_ENGINE_BUBBLE" desc="In Title Case: Title of a bubble warning users that an extension has overridden their default search engine setting">
+          Is This the Search Page You Were Expecting?
+        </message>
+      </if>
+      <if expr="not use_titlecase">
+        <message name="IDS_EXTENSIONS_SETTINGS_API_TITLE_SEARCH_ENGINE_BUBBLE" desc="Title of a bubble warning users that an extension has overridden their default search engine setting">
+          Is this the search page you were expecting?
+        </message>
+      </if>
+
+      <message name="IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_SEARCH_ENGINE" desc="Text displayed in the Settings API bubble as first line when an extension has changed the search engine.">
+        An extension has changed what page is shown when you search from the Omnibox.
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_HOME_PAGE" desc="Text displayed in the Settings API bubble as first line when an extension has changed the home page.">
+        An extension has changed what page is shown when you click the Home button.
+      </message>
+
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was just the search engine. The triple single quotes are needed to preserve the space before and after the sentence which is needed when the language (Chrome is being translated to) uses space as word separator. Please preserve them, unless the language being translated to does not use space as word separator.">
+        ''' It also controls what page is shown when you search from the Omnibox.'''
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_PAGE" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was the just home page. See IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE for reason for triple quotes.">
+        ''' It also controls what page is shown when you click the Home button. '''
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_AND_SEARCH" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was both the home page and the search engine. See IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE for reason for triple quotes.">
+        ''' It also controls what page is shown when you click the Home button or search from the Omnibox. '''
+      </message>
+
+      <message name="IDS_EXTENSIONS_SETTINGS_API_THIRD_LINE_CONFIRMATION" desc="Third line in the Settings API bubble, always appended after the first (and optional second) line to make one paragraph. See IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE for reason for triple quotes.">
+        ''' If you didn't want these changes, you can restore your previous settings.'''
+      </message>
+
+      <message name="IDS_EXTENSIONS_SETTINGS_API_RESTORE_SETTINGS" desc="The button in the Settings API bubble that reverts the settings changes made by the extension and restores what the user had before.">
+        Restore settings
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_KEEP_CHANGES" desc="The button in the Settings API bubble that cancels the bubble without action.">
+        Keep changes
+      </message>
+
       <!-- chrome://settings-frame/options_settings_app.html for the App Launcher Settings App -->
       <if expr="enable_settings_app">
         <message name="IDS_SETTINGS_APP_LAUNCHER_PRODUCT_NAME" desc="Product name to use when referring to applications running in the App Launcher inside the non-browser Settings App">
@@ -6272,12 +6337,6 @@
       <message name="IDS_FLAGS_ASH_ENABLE_TOUCH_VIEW_TESTING_DESCRIPTION" desc="Description for the flag to enable the TouchView testing mode.">
         Enable Ctrl+Alt+Shift+D to toggle the TouchView maximizing mode.
       </message>
-      <message name="IDS_FLAGS_ASH_ENABLE_BRIGHTNESS_CONTROL_NAME" desc="Title for the flag which can be used to enable brightness control of external displays.">
-        Enable brightness control of external displays
-      </message>
-      <message name="IDS_FLAGS_ASH_ENABLE_BRIGHTNESS_CONTROL_DESCRIPTION" desc="Description for the flag to enable brightness control of external displays.">
-        Make the brightness keys adjust external displays' brightness levels on devices that don't have internal displays.
-      </message>
       <message name="IDS_FLAGS_ENABLE_FULL_MULTI_PROFILE_MODE" desc="Title for the full multi profile mode flag.">
         Enable side-by-side multi profile mode
       </message>
@@ -6741,12 +6800,6 @@
         <message name="IDS_FLAGS_ENABLE_APP_LIST_DESCRIPTION" desc="Description of the flag to enable app launcher.">
           Enable the App Launcher. Upon enabling, creates operating system shortcuts to the App Launcher.
         </message>
-        <message name="IDS_FLAGS_ENABLE_APP_LIST_START_PAGE_NAME" desc="Name of the flag to enable the start page of app launcher.">
-          Enable the App Launcher start page.
-        </message>
-        <message name="IDS_FLAGS_ENABLE_APP_LIST_START_PAGE_DESCRIPTION" desc="Description of the flag to enable the start page of app launcher.">
-          Enable the App Launcher start page. If enabled, App Launcher will show a start page in addition to the apps grid.
-        </message>
         <message name="IDS_FLAGS_DISABLE_APP_LIST_FOLDER" desc="Name of the flag to disable app list folder.">
           Disable App Launcher folders.
         </message>
@@ -6948,9 +7001,9 @@
         sync-touchmove
       </message>
       <message name="IDS_FLAGS_BLEEDING_RENDERER_NAME" desc="Name of the 'Stacked Tabs' lab.">
-        Bleeding Edge Renderer Paths
+        Bleeding Edge Renderer Paths - LIKELY TO CRASH YOUR BROWSER
       </message>
-      <message name="IDS_FLAGS_BLEEDING_RENDERER_DESCRIPTION" desc="Description of the 'Stacked Tabs' lab.">
+      <message name="IDS_FLAGS_BLEEDING_RENDERER_DESCRIPTION" desc="Description of the 'Bleeding edge' lab.">
         Use bleeding-edge code to make Chrome draw content faster. The changes
         behind this path are very likely to break lots of content.
       </message>
@@ -6980,22 +7033,37 @@
 
       <!-- WebRTC logs -->
       <message name="IDS_WEBRTC_LOGS_TITLE" desc="Title for the chrome://webrtc-logs page.">
-        Uploaded WebRTC logs
+        WebRTC logs
       </message>
       <message name="IDS_WEBRTC_LOGS_LOG_COUNT_BANNER_FORMAT" desc="Format for WebRTC log count banner on chrome://webrtc-logs">
-        Uploaded WebRTC logs (<ph name="WEBRTC_LOG_COUNT">$1<ex>3</ex></ph>)
+        WebRTC logs (<ph name="WEBRTC_LOG_COUNT">$1<ex>3</ex></ph>)
       </message>
       <message name="IDS_WEBRTC_LOGS_LOG_HEADER_FORMAT" desc="Format for uploaded log entry headings on chrome://webrtc-logs">
-        WebRTC log ID <ph name="WEBRTC_LOG_ID">$1<ex>8fa95dbb6f2ec862</ex></ph>
+        WebRTC log captured <ph name="WEBRTC_LOG_CAPTURE_TIME">$1<ex>Tuesday, January 25, 2011 2:58:02 PM</ex></ph>
       </message>
-      <message name="IDS_WEBRTC_LOGS_LOG_TIME_FORMAT" desc="Format for uploaded log entry upload time on chrome://webrtc-logs">
-        Uploaded <ph name="WEBRTC_LOG_TIME">$1<ex>Tuesday, January 25, 2011 2:58:02 PM</ex></ph>
+      <message name="IDS_WEBRTC_LOGS_LOG_LOCAL_FILE_LABEL_FORMAT" desc="Format for local log entry label on chrome://webrtc-logs">
+        Local file:
+      </message>
+      <message name="IDS_WEBRTC_LOGS_LOG_LOCAL_FILE_FORMAT" desc="Format for file in local log entry on chrome://webrtc-logs">
+        <ph name="WEBRTC_LOG_LOCAL_FILE">$1<ex>/path/to/file</ex></ph>
+      </message>
+      <message name="IDS_WEBRTC_LOGS_NO_LOCAL_LOG_FILE_MESSAGE" desc="The explanatory message for chrome://webrtc-logs when there is no local log file">
+        No local log file.
+      </message>
+      <message name="IDS_WEBRTC_LOGS_LOG_UPLOAD_TIME_FORMAT" desc="Format for uploaded log entry upload time on chrome://webrtc-logs">
+        Uploaded <ph name="WEBRTC_LOG_UPLOAD_TIME">$1<ex>Tuesday, January 25, 2011 2:58:02 PM</ex></ph>
+      </message>
+      <message name="IDS_WEBRTC_LOGS_LOG_REPORT_ID_FORMAT" desc="Format for uploaded log entry report ID on chrome://webrtc-logs">
+        Report ID <ph name="WEBRTC_LOG_REPORT_ID">$1<ex>8fa95dbb6f2ec862</ex></ph>
       </message>
       <message name="IDS_WEBRTC_LOGS_BUG_LINK_LABEL" desc="Link text for filing a bug on chrome://webrtc-logs">
         File bug
       </message>
-      <message name="IDS_WEBRTC_LOGS_NO_LOGS_MESSAGE" desc="The explanatory message for chrome://webrtc-logs when there are no uploaded logs">
-        You have no recently uploaded WebRTC logs.
+      <message name="IDS_WEBRTC_LOGS_LOG_NOT_UPLOADED_MESSAGE" desc="The explanatory message for chrome://webrtc-logs when the log has not been uploaded">
+        Log not uploaded.
+      </message>
+      <message name="IDS_WEBRTC_LOGS_NO_LOGS_MESSAGE" desc="The explanatory message for chrome://webrtc-logs when there are no captured logs">
+        You have no recently captured WebRTC logs.
       </message>
 
       <!-- Custom dictionary page -->
@@ -7021,10 +7089,13 @@
         Enable "Ok Google" to start a voice search
       </message>
       <message name="IDS_HOTWORD_SEARCH_PREF_DESCRIPTION" desc="Description of the hotword  search preference">
-        Important: When you say "Ok Google," Chrome will send the sound of the next thing you say to Google.
+        When you say "Ok Google," Chrome will search for what you say next.
+      </message>
+      <message name="IDS_HOTWORD_CONFIRM_BUBBLE_TITLE" desc="The title text for the bubble to enable the hotword voice search trigger.">
+        Ok Google
       </message>
       <message name="IDS_HOTWORD_CONFIRM_BUBBLE_ENABLE" desc="The button text that allows the hotword voice search trigger.">
-        Enable "Ok Google"
+        OK
       </message>
       <message name="IDS_HOTWORD_CONFIRM_BUBBLE_DISABLE" desc="The button text that disallows the hotword voice search trigger.">
         Cancel
@@ -7035,6 +7106,9 @@
       <message name="IDS_HOTWORD_RETRY_DOWNLOAD_BUTTON" desc="The button text that retries a failed hotword setup in the settings page.">
         Retry
       </message>
+      <message name="IDS_HOTWORD_AUDIO_LOGGING_ENABLE" desc="A checkbox in the hotword confirm dialog that allows for sending audio of 'Ok, Google' plus a few seconds before back to Google to improve voice search.">
+        Improve voice search by sending the sound of "Ok Google," and a few seconds before, to Google.
+      </message>
 
       <!-- Conflicts page -->
       <message name="IDS_CONFLICTS_CHECK_PAGE_TABLE_TITLE_SUFFIX_ONE" desc="What gets appended after the page title if no conflicts were found.">
@@ -8379,28 +8453,12 @@
       </message>
 
       <!-- Upgrade bubble messages -->
-      <message name="IDS_REINSTALL_APP" desc="Text for the button the user clicks to reinstall the app.">
-        Reinstall <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph>
+      <message name="IDS_REENABLE_UPDATES" desc="Text for the button the user clicks to re-enable automatic updates.">
+        Enable autoupdate
       </message>
       <message name="IDS_LATER" desc="Text for the button the user clicks to be reminded of reinstalling the app later.">
         Later
       </message>
-      <if expr="use_titlecase">
-        <message name="IDS_UPGRADE_BUBBLE_MENU_ITEM" desc="In Title Case: Text for the Chrome menu option replacing Update required.">
-          <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> is Out of Date
-        </message>
-      </if>
-      <if expr="not use_titlecase">
-        <message name="IDS_UPGRADE_BUBBLE_MENU_ITEM" desc="Text for the Chrome menu option replacing Update required.">
-          <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> is out of date
-        </message>
-      </if>
-      <message name="IDS_UPGRADE_BUBBLE_TITLE" desc="Text for the title of the upgrade bubble view.">
-        <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> is out of date
-      </message>
-      <message name="IDS_UPGRADE_BUBBLE_TEXT" desc="Text for the upgrade bubble view full description.">
-        <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph> could not update itself to the latest version, so you are missing out on awesome new features and security fixes. You need to manually reinstall <ph name="IDS_SHORT_PRODUCT_NAME">$1<ex>Chrome</ex></ph>.
-      </message>
 
       <!-- Print -->
       <message name="IDS_DEFAULT_PRINT_DOCUMENT_TITLE" desc="Default title for a print document">
@@ -11552,50 +11610,41 @@
       <message name="IDS_PROFILES_EDIT_PROFILE_LINK" desc="Link in the avatar menu bubble to edit a profile.">
         edit
       </message>
+      <message name="IDS_PROFILES_GAIA_SIGNIN_TITLE" desc="Title of the account removal view in the avatar menu bubble.">
+        Sign in
+      </message>
+      <message name="IDS_PROFILES_GAIA_ADD_ACCOUNT_TITLE" desc="Title of the account removal view in the avatar menu bubble.">
+        Add account
+      </message>
+      <message name="IDS_PROFILES_ACCOUNT_REMOVAL_TITLE" desc="Title of the account removal view in the avatar menu bubble.">
+        Remove account
+      </message>
+      <message name="IDS_PROFILES_ACCOUNT_REMOVAL_BUTTON" desc="Text of the ok button on the account removal view in the avatar menu bubble.">
+        Remove account and relaunch
+      </message>
       <message name="IDS_PROFILES_SIGNIN_TUTORIAL_TITLE" desc="Title of the tutorial card in the avatar menu bubble view for a signed-in user.">
         Hey, <ph name="PROFILE_DISPLAY_NAME">$1<ex>Jessica</ex></ph>!
       </message>
       <message name="IDS_PROFILES_SIGNIN_TUTORIAL_OK_BUTTON" desc="Text of the ok button on the tutorial card in the avatar menu bubble view">
         Ok, Got it!
       </message>
+      <message name="IDS_PROFILES_NOT_YOU_BUTTON" desc="Button in the avatar menu bubble view for launching the user manager.">
+        Not <ph name="PROFILE_DISPLAY_NAME">$1<ex>Jessica</ex></ph>?
+      </message>
       <if expr="not use_titlecase">
-        <message name="IDS_PROFILES_ADD_PERSON_BUTTON" desc="Button in the avatar menu bubble view for creating a new user.">
-          Add person
-        </message>
-        <message name="IDS_PROFILES_GUEST_BUTTON" desc="Button in the avatar menu bubble view for guest browsing.">
-          Browse as guest
-        </message>
-        <message name="IDS_PROFILES_EXIT_GUEST_BUTTON" desc="Button in the avatar menu bubble view to end guest browsing.">
-          End guest session
-        </message>
-        <message name="IDS_PROFILES_ALL_PEOPLE_BUTTON" desc="Button in the avatar menu bubble view for launching the user manager.">
-          View all people
-        </message>
         <message name="IDS_PROFILES_PROFILE_ADD_ACCOUNT_BUTTON" desc="Button in the avatar menu bubble view used to add an account to a profile.">
           Add account for <ph name="PROFILE_NAME">$1<ex>John</ex></ph>
         </message>
         <message name="IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON" desc="Button in the avatar menu bubble view used to manage accounts for a profile.">
-          Manage accounts
+          Your accounts
         </message>
       </if>
       <if expr="use_titlecase">
-        <message name="IDS_PROFILES_ADD_PERSON_BUTTON" desc="Button in the avatar menu bubble view for creating a new user.">
-          Add Person
-        </message>
-        <message name="IDS_PROFILES_GUEST_BUTTON" desc="Button in the avatar menu bubble view for guest browsing.">
-          Browse as Guest
-        </message>
-        <message name="IDS_PROFILES_EXIT_GUEST_BUTTON" desc="Button in the avatar menu bubble view to end guest browsing.">
-          End Guest Session
-        </message>
-        <message name="IDS_PROFILES_ALL_PEOPLE_BUTTON" desc="Button in the avatar menu bubble view for launching the user manager.">
-          View All People
-        </message>
         <message name="IDS_PROFILES_PROFILE_ADD_ACCOUNT_BUTTON" desc="Button in the avatar menu bubble view used to add an account to a profile.">
           Add Account for <ph name="PROFILE_NAME">$1<ex>John</ex></ph>
         </message>
         <message name="IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON" desc="Button in the avatar menu bubble view used to manage accounts for a profile.">
-          Manage Accounts
+          Your Accounts
         </message>
       </if>
       <message name="IDS_PROFILES_PROFILE_CHANGE_PHOTO_BUTTON" desc="Button in the avatar menu bubble view used to change the photo for a profile.">
@@ -12257,11 +12306,11 @@
       <message name="IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE" desc="Title in the sign-in error bubble view/notification.">
         Sign-in Error
       </message>
-      <message name="IDS_SYNC_ERROR_BUBBLE_VIEW_TITLE" desc="Title in the sync error bubble view.">
+      <message name="IDS_SYNC_ERROR_BUBBLE_VIEW_TITLE" desc="Title in the sync error bubble view/notification.">
         Sync Error
       </message>
-      <message name="IDS_SIGNIN_ERROR_NOTIFICATION_TITLE_MULTIPROFILE" desc="Title in the sign-in error notification when multiple users are logged in.">
-        Sign-in Error: <ph name="USER_NAME">$1<ex>foo@example.com</ex></ph>
+      <message name="IDS_SYNC_NOTIFICATION_ACCEPT" desc="A button label shown in the sync error notification when the passphrase needs to be updated.">
+        Update sync passphrase
       </message>
 
       <if expr="not use_titlecase">
@@ -12275,7 +12324,7 @@
           Sync Error: Update Sync passphrase...
         </message>
         <if expr="chromeos">
-          <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT" desc="The accept button in the sync error bubble view when the user needs to sign out and sign in again to Chrome OS.">
+          <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_ACCEPT" desc="The accept button in the sync error bubble view/notification when the user needs to sign out and sign in again to Chrome OS.">
             Sign out then sign in again...
           </message>
           <message name="IDS_SYNC_SIGN_IN_ERROR_WRENCH_MENU_ITEM" desc="The sync error wrench menu item when the user needs to sign out and sign in again to Chrome OS.">
@@ -14144,6 +14193,12 @@
     <message name="IDS_FLAGS_ENABLE_NEW_PROFILE_MANAGEMENT_DESCRIPTION" desc="Description for the flag to enable the new profile management">
       Enables the new profile management system, including profile sign-out and the new avatar menu UI.
     </message>
+    <message name="IDS_FLAGS_ENABLE_FAST_USER_SWITCHING_NAME" desc="Title for the flag to enable fast user switching.">
+      Enable fast user switching in the avatar menu
+    </message>
+    <message name="IDS_FLAGS_ENABLE_FAST_USER_SWITCHING_DESCRIPTION" desc="Description for the flag to enable fast user switching">
+      Enables fast switching between users in the avatar menu.
+    </message>
     <message name="IDS_FLAGS_ENABLE_WEB_BASED_SIGNIN_NAME" desc="Title for the flag to enable web-based sign-in flows.">
       Enable pure web-based sign-in flows
     </message>
@@ -14189,6 +14244,13 @@
       Enable Swipe Selection support for the virtual keyboard. Unless the virtual keyboard is also enabled, this will do nothing.
     </message>
 
+    <message name="IDS_FLAGS_ENABLE_INPUT_VIEW_NAME" desc="Name of about::flags option to enable IME extensions to override the virtual keyboard view">
+      Enable input views.
+    </message>
+    <message name="IDS_FLAGS_ENABLE_INPUT_VIEW_DESCRIPTION" desc="Description of about::flags option to enable IME extensions to override the virtual keyboard view">
+      Enable IME extensions to supply custom views for user input such as  virtual keyboards.
+    </message>
+
     <!-- Simple Cache Backend experiment. -->
     <message name="IDS_FLAGS_ENABLE_SIMPLE_CACHE_BACKEND_NAME" desc="Name of about:flags option to turn on the Simple Cache Backend">
       Simple Cache for HTTP.
@@ -14777,6 +14839,22 @@
     <message name="IDS_FLAGS_PREFETCH_SEARCH_RESULTS_DESCRIPTION" desc="Describes an about:flags experiment for prefetching search results">
       If enabled, prefetch search results for the typed omnibox query and reuse prerendered search base page to commit any search query (not just prefetch query).
     </message>
+
+    <!-- Settings window flags -->
+    <message name="IDS_FLAGS_ENABLE_SETTINGS_WINDOW_NAME" desc="An about::flags experiment title to show settings in a separate window">
+      Show settings in a window
+    </message>
+    <message name="IDS_FLAGS_ENABLE_SETTINGS_WINDOW_DESCRIPTION" desc="Describes an about:flags experiment to show settings in a separate window">
+      If enabled, Settings will be shown in a dedicated window instead of as a browser tab.
+    </message>
+
+    <!-- Instant search clicks experiment flags -->
+    <message name="IDS_FLAGS_ENABLE_INSTANT_SEARCH_CLICKS_NAME" desc="Title for the flag to enable instant search clicks">
+      Prefetch search results
+    </message>
+    <message name="IDS_FLAGS_ENABLE_INSTANT_SEARCH_CLICKS_DESCRIPTION" desc="Description to enable instant search clicks">
+      If enabled, prefetch previews for search results and swap them with original page when is downloaded and rendered.
+    </message>
   </messages>
   </release>
 </grit>
diff --git a/chrome/app/google_chrome_strings.grd b/chrome/app/google_chrome_strings.grd
index 4fd7e3d..0561e02 100644
--- a/chrome/app/google_chrome_strings.grd
+++ b/chrome/app/google_chrome_strings.grd
@@ -787,6 +787,14 @@
 • Manage your Google Accounts
       </message>
 
+      <!-- Account removal view in the avatar menu bubble -->
+      <message name="IDS_PROFILES_ACCOUNT_REMOVAL_TEXT" desc="Main text of the account removal view when removing a secondary account.">
+        To remove your account, Chrome needs to restart. Make sure you've saved any open work before continuing.
+      </message>
+      <message name="IDS_PROFILES_PRIMARY_ACCOUNT_REMOVAL_TEXT" desc="Main text of the account removal view when removing a primary account.">
+        You're using <ph name="PROFILE_EMAIL">$1<ex>jessica@gmail.com</ex></ph> to sync your Chrome stuff. To update your sync preference or to use Chrome without a Google account, visit settings.
+      </message>
+
       <!-- Sync Promo New Tab Page bubble strings -->
       <message name="IDS_SYNC_PROMO_NTP_BUBBLE_MESSAGE_NEW" desc="The body of the sync promo NTP bubble.">
         Now that you're signed in, you can get your tabs, bookmarks and other Chrome stuff across your laptop, phone and tablet. You will also receive more relevant suggestions and features on Google services.
@@ -855,13 +863,13 @@
         <message name="IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error bubble view when the user needs to update their sync passphrase.">
           Google Chrome could not sync your data. Please update your Sync passphrase.
         </message>
-        <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error bubble view when the user's sign-in credentials are out of date.">
+        <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when the user's sign-in credentials are out of date.">
           Google Chrome could not sync your data because your account sign-in details are out of date.
         </message>
-        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error bubble view when sync is not available for their domain.">
+        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when sync is not available for their domain.">
           Google Chrome could not sync your data because Sync is not available for your domain.
         </message>
-        <message name="IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error bubble view when there's an error signing in.">
+        <message name="IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error bubble view when there's an error signing in.">
           Google Chrome could not sync your data due to an error signing in.
         </message>
       </if>
@@ -869,13 +877,13 @@
         <message name="IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error bubble view when the user needs to update their sync passphrase.">
           Chrome OS could not sync your data. Please update your Sync passphrase.
         </message>
-        <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error notification when the user's sign-in credentials are out of date.">
+        <message name="IDS_SYNC_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error notification when the user's sign-in credentials are out of date.">
           Chrome OS could not sync your data because your account sign-in details are out of date.
         </message>
-        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error notification when sync is not available for their domain.">
+        <message name="IDS_SYNC_UNAVAILABLE_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error notification when sync is not available for their domain.">
           Chrome OS could not sync your data because Sync is not available for your domain.
         </message>
-        <message name="IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sync error notification when there's an error signing in.">
+        <message name="IDS_SYNC_OTHER_SIGN_IN_ERROR_BUBBLE_VIEW_MESSAGE" desc="Message in the sign-in error notification when there's an error signing in.">
           Chrome OS could not sync your data due to an error signing in.
         </message>
       </if>
@@ -884,6 +892,9 @@
         On Mac, passwords are saved to your Keychain and may be accessed or synced by other Chrome users sharing this OS X account.
       </message>
 
+      <message name="IDS_AUTOFILL_ADDRESS_BOOK_PROMPT_DESCRIPTION" desc="Text to show in dialog requesting permission to access the user's Address Book contents.">
+        Details from your contacts can help you fill out forms more quickly in Chrome.
+      </message>
       <message name="IDS_AUTOFILL_CC_INFOBAR_TEXT" desc="Text to show in the Autofill credit card request infobar.">
         Do you want Chrome to save this credit card information for completing web forms?
       </message>
@@ -1084,6 +1095,44 @@
         </message>
       </if>
 
+      <!-- Settings API bubble -->
+      <message name="IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_START_PAGES" desc="Text displayed in the Settings API bubble as first line when an extension has changed the start pages.">
+        An extension has changed what page is shown when you start Chrome.
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was just the start pages. The triple single quotes are needed to preserve the space before and after the sentence which is needed when the language (Chrome is being translated to) uses space as word separator. Please preserve them, unless the language being translated to does not use space as word separator.">
+        ''' It also controls what page is shown when you start Chrome. '''
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_HOME" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was both the start page and the home page. See IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES for reason for triple quotes.">
+        ''' It also controls what page is shown when you start Chrome or click the Home button. '''
+      </message>
+      <message name="IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_SEARCH" desc="Second line in the Settings API bubble. Only shown if the secondary change by the extension was both the start page and the search engine. See IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES for reason for triple quotes.">
+        ''' It also controls what page is shown when you start Chrome or search from the Omnibox. '''
+      </message>
+
+      <!-- Update bubble -->
+      <message name="IDS_REINSTALL_APP" desc="Text for the button the user clicks to reinstall the app.">
+        Reinstall Chrome
+      </message>
+      <if expr="use_titlecase">
+        <message name="IDS_UPGRADE_BUBBLE_MENU_ITEM" desc="In Title Case: Text for the Chrome menu option replacing Update required.">
+          Chrome is Out of Date
+        </message>
+      </if>
+      <if expr="not use_titlecase">
+        <message name="IDS_UPGRADE_BUBBLE_MENU_ITEM" desc="Text for the Chrome menu option replacing Update required.">
+          Chrome is out of date
+        </message>
+      </if>
+      <message name="IDS_UPGRADE_BUBBLE_TITLE" desc="Text for the title of the upgrade bubble view.">
+        Chrome is out of date
+      </message>
+      <message name="IDS_UPGRADE_BUBBLE_TEXT" desc="Text for the upgrade bubble view full description.">
+        Chrome could not update itself to the latest version, so you are missing out on awesome new features and security fixes. You need to manually reinstall Chrome.
+      </message>
+      <message name="IDS_UPGRADE_BUBBLE_REENABLE_TEXT" desc="Text for the upgrade bubble view full description.">
+        Chrome could not update itself to the latest version, so you are missing out on awesome new features and security fixes. You need to update Chrome.
+      </message>
+
       <!-- chrome://ntp -->
       <if expr="not is_android">
         <message name="IDS_NEW_TAB_OTR_EXTENSIONS_MESSAGE"
diff --git a/chrome/app/resources/chromium_strings_am.xtb b/chrome/app/resources/chromium_strings_am.xtb
index bd04587..49dd113 100644
--- a/chrome/app/resources/chromium_strings_am.xtb
+++ b/chrome/app/resources/chromium_strings_am.xtb
@@ -195,13 +195,13 @@
 <translation id="2119636228670142020">&amp;ስለChromium ስርዓተ ክወና</translation>
 <translation id="1708666629004767631">አዲስና ደህንነቱ ይበልጥ የተጠበቀ የChromium ስሪት አለ።</translation>
 <translation id="378917192836375108">Chromium ድር ላይ ያለ ስልክ ቁጥር ጠቅ እንዲያደርጉትና በSkype እንዲደውሉበት ያስችልዎታል!</translation>
-<translation id="8724049448828509830">አንድ ውርድ አሁን በሂደት ላይ ነው። ከChromium ወጥተው ውርዱን መሰረዝ ይፈልጋሉ?</translation>
+<translation id="8724049448828509830">አንድ ውርድ አሁን በሂደት ላይ ነው። ከChromium ወጥተው ውርዱን ይቅር ማለት ይፈልጋሉ?</translation>
 <translation id="608189560609172163">በመለያ ሲገባ በነበረ ስህተት ምክንያት Chromium ውሂብዎን ማመሳሰል አልቻለም።</translation>
 <translation id="3360567213983886831">Chromium ሁለትዮሾች</translation>
 <translation id="8985587603644336029">የሆነ ሰው ከዚህ ቀደም በዚህ ኮምፒውተር ላይ እንደ <ph name="ACCOUNT_EMAIL_LAST"/> ሆኖ ወደ Chromium ገብቶ ነበር። ያ መለያዎ ካልሆነ መረጃዎን ለይተው ለማስቀመጥ አዲስ የChromium ተጠቃሚ ይፍጠሩ።
 
 ዝም ብሎ መግባት እንደ ዕልባቶች፣ ታሪክ እና ሌሎች ቅንብሮች ያሉ የChromium መረጃዎችን ከ<ph name="ACCOUNT_EMAIL_NEW"/> ጋር ያዋህዳቸዋል።</translation>
-<translation id="2739631515503418643">ውርዶች በአሁኑ ጊዜ በሂደት ላይ ናቸው። ከChromium መውጣትና ውርዶቹን መሰረዝ ይፈልጋሉ?</translation>
+<translation id="2739631515503418643">ውርዶች በአሁኑ ጊዜ በሂደት ላይ ናቸው። ከChromium መውጣትና ውርዶቹን ይቅር ማለት ይፈልጋሉ?</translation>
 <translation id="9013262824292842194">Chromium Windows Vista ወይም Windows XP ከSP2 ወይም ከዚያ በላይ ይፈልጋል።</translation>
 <translation id="1967743265616885482">ተመሳሳይ ስም ያለው ሞዱል ከChromium ጋር የሚጋጭ መሆኑ ይታወቃል።</translation>
 <translation id="4224199872375172890">Chromium የተዘመነ ነው።</translation>
diff --git a/chrome/app/resources/generated_resources_am.xtb b/chrome/app/resources/generated_resources_am.xtb
index b3b5ca9..dd727c1 100644
--- a/chrome/app/resources/generated_resources_am.xtb
+++ b/chrome/app/resources/generated_resources_am.xtb
@@ -311,6 +311,7 @@
           የሚከተሉትን ደረጃዎች በመከተል ችግሩን ለመመርመር መሞከር ይችላሉ፦
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">ከQTKit ይልቅ የMac OS X AVFoundation ኤፒአይዎችን መጠቀምን አንቃ።</translation>
 <translation id="6317369057005134371">የመተግበሪያ መስኮትን በመጠበቅ ላይ...</translation>
 <translation id="6391832066170725637">ፋይሉ ወይም ማውጫው ሊገኘም አልቻለም።</translation>
 <translation id="7393381084163773901">የጎዳና አድራሻ</translation>
@@ -421,7 +422,7 @@
 <translation id="5516565854418269276">&amp;ሁልጊዜ የዕልባቶች አሞሌን አሳይ</translation>
 <translation id="6426222199977479699">SSL ስህተት</translation>
 <translation id="2688196195245426394">መሣሪያውን በዚህ አገልጋይ ላይ በመመዝገብ ላይ ሳለ ስህተት፦ <ph name="CLIENT_ERROR"/>።</translation>
-<translation id="667115622929458276">ማንነትን የማያሳውቁ ውርዶች በአሁኑ ጊዜ በሂደት ላይ ናቸው። ማንነትን ከማያሳውቅ ሁነታ ወጥተው ውርዶቹን መሰረዝ ይፈልጋሉ?</translation>
+<translation id="667115622929458276">ማንነትን የማያሳውቁ ውርዶች በአሁኑ ጊዜ በሂደት ላይ ናቸው። ማንነትን ከማያሳውቅ ሁነታ ወጥተው ውርዶቹን ይቅር ማለት ይፈልጋሉ?</translation>
 <translation id="1528372117901087631">የበይነመረብ ግንኙነት</translation>
 <translation id="1788636309517085411">ነባሪን ይጠቀሙ</translation>
 <translation id="4159435316791146348">ከCPSC እና ከሌሎች ተቆጣጣሪ ኤጀንሲዎች በተሰጠ መመሪያ እና ማረጋገጫ መሰረት፣ Google እና HP የHP Chromebook 11 ኦሪጂናል ኃይል መሙያ መልሰው እየጠሩ ነው።</translation>
@@ -762,7 +763,7 @@
 <translation id="3280237271814976245">አስቀምጥ &amp;እንደ…</translation>
 <translation id="7221155467930685510">$1 ጊባ</translation>
 <translation id="2624142942574147739">ይህ ገጽ ካሜራዎን እና ማይክሮፎንዎን እየደረሰባቸው ነው።</translation>
-<translation id="7658239707568436148">ሰርዝ</translation>
+<translation id="7658239707568436148">ይቅር</translation>
 <translation id="557722062034137776">የእርስዎን መሣሪያ ዳግም ማስጀመር በእርስዎ Google መለያዎች ወይም ከእነዚህ መለያዎች ጋር በተመሳሰሉ ማንኛውም ውሂብ ላይ ምንም ተጽዕኖ አይኖረውም። ይሁንና በመሣሪያዎ ላይ የተቀመጡ ፋይሎች ሁሉ ይሰረዛሉ።</translation>
 <translation id="2223809180207557256">የይለፍ ቃላትን ዓረፋ ያንቁ</translation>
 <translation id="8695825812785969222">&amp;ቦታ ክፈት…</translation>
@@ -1073,7 +1074,7 @@
 <translation id="7787129790495067395">በአሁኑ ጊዜ የይለፍ ሐረግ እየተጠቀሙ ነዎት።  የይለፍ ሐረግዎን ከረሱት Google ዳሽቦርድን ተጠቅመው ውሂብዎን ከGoogle አገልጋዮች ለማጽዳት ማመሳሰልን ዳግም ሊያስጀምሩ ይችላሉ።</translation>
 <translation id="2098305189700762159">አልተገኘም</translation>
 <translation id="2521119273159503752">የምዝግብ ማስታወሻ መታወቂያ</translation>
-<translation id="1273135602584709125">የድርጅት ምዝገባ ይሰርዙ</translation>
+<translation id="1273135602584709125">የድርጅት ምዝገባ ይቅር</translation>
 <translation id="2686759344028411998">ማንኛውም የተጫኑ ሞዱሎችን ማግኘት አልተቻለም።</translation>
 <translation id="1286637972568390913">የWebRTC ሃርድዌር ቪዲዮ ኮድ መፍታት አሰናክል።</translation>
 <translation id="572525680133754531">የንብብር ጥንክር ለማረም እና ለማጥናት እንዲያግዝ የተጠናከሩ ዝግጁ ንብርብሮች ዙሪያ ላይ ድንበር ያዘጋጃል።</translation>
@@ -1316,6 +1317,7 @@
 <translation id="8442065444327205563">ሰነድዎ ለመታየት ዝግጁ ነው።</translation>
 <translation id="236141728043665931">ሁልጊዜ የማይክሮፎን መዳረሻ አግድ</translation>
 <translation id="2307462900900812319">አውታረ መረብ አዋቅር</translation>
+<translation id="1704385717926547822">የሙከራ የChromecast ድጋፍን አንቃ</translation>
 <translation id="5911798608827489036">በአካባቢያዊው አውታረ መረብ ወይም በይነመረቡ ላይ ካለ ማንኛውም ኮምፒውተር ጋር ውሂብ ይለዋወጡ</translation>
 <translation id="220858061631308971">እባክዎ ይህን የፒን ኮድ በ«<ph name="DEVICE_NAME"/>» ላይ ያስገቡት፦</translation>
 <translation id="6263082573641595914">Microsoft CA ቅጂ</translation>
@@ -1975,7 +1977,7 @@
 <translation id="2969972665754920929">መተግበሪያዎች እና ቅጥያዎች ክትትል በሚደረግባቸው ተጠቃሚዎች ሊቀየሩ አይችሉም። የመተግበሪያዎች ገንቢ መሣሪያዎች ይዘጋሉ።</translation>
 <translation id="149347756975725155">የቅጥያ አዶ «<ph name="ICON"/>»ን መጫን አልተቻለም።</translation>
 <translation id="3011362742078013760">&amp;ሁሉንም እልባቶች በስውር መስኮት ውስጥ ክፈት</translation>
-<translation id="3009300415590184725">እርግጠኛ ነዎት የተንቀሳቃሽ ስልክ ውሂብ አገልግሎት የማዋቀር ሂደቱን መሰረዝ ይፈልጋሉ?</translation>
+<translation id="3009300415590184725">እርግጠኛ ነዎት የተንቀሳቃሽ ስልክ ውሂብ አገልግሎት የማዋቀር ሂደቱን ይቅር ማለት ይፈልጋሉ?</translation>
 <translation id="7851457902707056880">በመለያ መግባት ለመለያው ባለቤት ብቻ ተገድቧል። እባክዎ ዳግም ያስነሱና በባለቤቱ መለያ ይግቡ። ማሽኑ በ30 ሰከንዶች ውስጥ ዳግም ይነሳል።</translation>
 <translation id="2148756636027685713">ቅርጸት መስራት ተጠናቅቋል</translation>
 <translation id="5451285724299252438">የገጽ ክልል ጽሑፍ ሳጥን</translation>
@@ -2306,7 +2308,7 @@
 <translation id="9111102763498581341">ክፈት</translation>
 <translation id="5975792506968920132">የባትሪ መሞላት መቶኛ ደረጃ</translation>
 <translation id="289695669188700754">ቁልፍ መታወቂያ፦ <ph name="KEY_ID"/></translation>
-<translation id="8183644773978894558">ማንነትን የማያሳውቅ ውርድ አሁን በሂደት ላይ ነው። ከማንነትን የማያሳውቅ ሁነታ ወጥተው ውርዱን መሰረዝ ይፈልጋሉ?</translation>
+<translation id="8183644773978894558">ማንነትን የማያሳውቅ ውርድ አሁን በሂደት ላይ ነው። ከማንነትን የማያሳውቅ ሁነታ ወጥተው ውርዱን ይቅር ማለት ይፈልጋሉ?</translation>
 <translation id="8767072502252310690">ተጠቃሚዎች</translation>
 <translation id="683526731807555621">አዲስ የፍለጋ ፕሮግራም አክል</translation>
 <translation id="6871644448911473373">OCSP ምላሽ ሰጪ፦ <ph name="LOCATION"/></translation>
@@ -2542,7 +2544,7 @@
 <translation id="6800914069727136216">በይዘት ጥቅል ውስጥ</translation>
 <translation id="8661104342181683507">ዘላቂ የሆነ የ<ph name="NUMBER_OF_FILES"/> ፋይል መዳረሻ አለው።</translation>
 <translation id="860043288473659153">የካርድ ያዢ ስም</translation>
-<translation id="3866249974567520381">ገለጻ</translation>
+<translation id="3866249974567520381">ማብራሪያ</translation>
 <translation id="2900139581179749587">ንግግር አልታወቀም።</translation>
 <translation id="2294358108254308676"><ph name="PRODUCT_NAME"/>ን መጫን ይፈልጋሉ?</translation>
 <translation id="6549689063733911810">የቅርብ ጊዜ</translation>
@@ -2940,6 +2942,7 @@
 <translation id="8670869118777164560">ይህ ቅጥያ አንድ የአውታረ መረብ ጥያቄ ወደ <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> ማዞር አልተሳካለትም ምክንያቱም ሌላ ቅጥያ (<ph name="EXTENSION_NAME"/>) ወደ <ph name="ACTUAL_REDIRECT_DESTINATION"/> አዙሮታል።</translation>
 <translation id="3654092442379740616">የማመሳሰል ስህተት፦  <ph name="PRODUCT_NAME"/> ጊዜው ያለፈበትና መዘመን የሚያስፈልገው ነው።</translation>
 <translation id="790040513076446191">ከግላዊነት ጋር የተገናኙ ቅንብሮችን ይቆጣጠሩ</translation>
+<translation id="7260002739296185724">በOS X &gt;= 10.7 ላይ ቪዲዮን ለመቅረጽ እና የቪዲዮ መሣሪያ መከታተልን ለማንቃት የAVFoundation መጠቀምን ያንቁ። አለበለዚያ QTKit ስራ ላይ ይውላል።</translation>
 <translation id="3116361045094675131">የዩናይትድ ኪንግደም ቁልፍ ሰሌዳ</translation>
 <translation id="1463985642028688653">አግድ</translation>
 <translation id="1715941336038158809">የተሳሳተ የተጠቃሚ ስም ወይም የይለፍ ቃል።</translation>
@@ -3055,7 +3058,7 @@
 <translation id="7248671827512403053">መተግበሪያ</translation>
 <translation id="450070808725753129">አውታረ መረቡ እንዲደርስ የተፈቀደ መሣሪያ ነው ተብሎ አስቀድሞ ከተዘረዘረ ከዝርዝሩ
         አስወግደው እንደገና ማከል ይሞክሩ።</translation>
-<translation id="778627899913883287">እነዚህ ልዩ ፈቃዶች ቅጥያው ማድረግ አለበት ብለው ለሚያስቡት ነገር ትርጉም የሚሰጡ መሆናቸውን እርግጠኛ ይሁኑ። ትርጉም የማይሰጡ ከሆነ ተወው የሚለውን ጠቅ ያድርጉ።</translation>
+<translation id="778627899913883287">እነዚህ ልዩ ፈቃዶች ቅጥያው ማድረግ አለበት ብለው ለሚያስቡት ነገር ትርጉም የሚሰጡ መሆናቸውን እርግጠኛ ይሁኑ። ትርጉም የማይሰጡ ከሆነ ይቅር የሚለውን ጠቅ ያድርጉ።</translation>
 <translation id="4742746985488890273">መደርደሪያ ላይ ሰካ</translation>
 <translation id="1113869188872983271">&amp;እንደገና ደርድርን ቀልብስ</translation>
 <translation id="16620462294541761">ይቅርታ፣ የይለፍ ቃልዎ ሊረጋገጥ አልቻለም። እባክዎ እንደገና ይሞክሩ።</translation>
@@ -3613,7 +3616,7 @@
 
         ለተጨማሪ መረጃ የስርዓት አስተዳዳሪዎን ያነጋግሩ።
 
-        ይህ መሣሪያ የድርጅትዎ ካልሆነ እና የግል መሣሪያዎ ከሆነ የመሣሪያው ምዝገባ ሂደትን ለመሰረዝና ወደ በመለያ መግቢያ ማያ ገጹ ለመግባት Ctrl+Alt+E መጫን ይችላሉ።</translation>
+        ይህ መሣሪያ የድርጅትዎ ካልሆነ እና የግል መሣሪያዎ ከሆነ የመሣሪያው ምዝገባ ሂደትን ይቅር ለማለት እና ወደ በመለያ መግቢያ ማያ ገጹ ለመግባት Ctrl+Alt+E መጫን ይችላሉ።</translation>
 <translation id="479536056609751218">ድረ-ገጽ፣ ኤች ቲ ኤም ኤል ብቻ</translation>
 <translation id="8822808012507380471">ከ<ph name="SHORT_PRODUCT_NAME"/> ጋር የሚዛመዱ የሁሉም ሂደቶች የግል ማህደረ ትውስታ አጠቃላይ አጠቃቀም</translation>
 <translation id="534916491091036097">ግራ ቅንፍ</translation>
@@ -3800,6 +3803,7 @@
 <translation id="6658571109205370715">የምስክር ወረቀት ግልጽነት</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">ዕልባት ሰርዝ</translation>
+<translation id="7166627725100067582">የድር ቪዲዮዎችን በChromecast መሣሪያዎች ላይ እንዲያጫውቱ እና እንዲቆጣጠሩ የሚያስችል የሙከራ Chromecast ድጋፍን ያንቁ።</translation>
 <translation id="3031557471081358569">ከውጪ ለማስመጣት ንጥሎችን ምረጥ፦</translation>
 <translation id="1368832886055348810">ከግራ ወደ ቀኝ</translation>
 <translation id="834106456999819211">ትእዛዝዎ እየተሰስተናገደ ነው</translation>
@@ -4115,7 +4119,7 @@
 <translation id="1479356886123917758">ከኮምፒውተርዎ ላይ ፎቶዎች፣ ሙዚቃ እና ሌላ ማህደረ መረጃ ይድረሱና ይለውጡ።</translation>
 <translation id="5295309862264981122">ዳሰሳን አረጋግጥ</translation>
 <translation id="718827667662449283">ዩናይትድ ኪንግደም</translation>
-<translation id="2908999529399859069">አይ፣ ተወው</translation>
+<translation id="2908999529399859069">አይ፣ ይቅር</translation>
 <translation id="5804241973901381774">ፍቃዶች</translation>
 <translation id="901834265349196618">ኢሜይል</translation>
 <translation id="8382207127145268451">የውሂብ ጨመቃ ተኪን አንቃ</translation>
diff --git a/chrome/app/resources/generated_resources_ar.xtb b/chrome/app/resources/generated_resources_ar.xtb
index cd8c1a8..8790bd2 100644
--- a/chrome/app/resources/generated_resources_ar.xtb
+++ b/chrome/app/resources/generated_resources_ar.xtb
@@ -305,6 +305,7 @@
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> يمكنك محاولة تشخيص المشكلة باتباع الخطوات التالية:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">‏تمكين استخدام Mac OS X AVFoundation APIs، بدلاً من QTKit.</translation>
 <translation id="6317369057005134371">جارٍ انتظار نافذة التطبيق...</translation>
 <translation id="6391832066170725637">تعذّر العثور على الملفّ أو الدليل.</translation>
 <translation id="7393381084163773901">عنوان الشارع</translation>
@@ -1289,6 +1290,7 @@
 <translation id="8442065444327205563">المستند جاهز للعرض.</translation>
 <translation id="236141728043665931">حظر الدخول إلى الميكروفون دومًا</translation>
 <translation id="2307462900900812319">تهيئة الشبكة</translation>
+<translation id="1704385717926547822">‏تمكين دعم Chromecast التجريبي</translation>
 <translation id="5911798608827489036">تبادل البيانات مع أي جهاز كمبيوتر متصل بالشبكة المحلية أو الإنترنت</translation>
 <translation id="220858061631308971">الرجاء إدخال رمز رقم التعريف الشخصي هذا على &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">‏إصدار المرجع المصدق (CA) لـ Microsoft</translation>
@@ -2886,6 +2888,7 @@
 <translation id="8670869118777164560">أخفقت الإضافة في إعادة توجيه طلب الشبكة إلى <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> نظرًا لإعادة توجيهها بواسطة إضافة أخرى (<ph name="EXTENSION_NAME"/>) إلى <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">خطأ في المزامنة: <ph name="PRODUCT_NAME"/> قديم ويجب تحديثه.</translation>
 <translation id="790040513076446191">معالجة الإعدادات المتعلقة بالخصوصية</translation>
+<translation id="7260002739296185724">‏يمكنك تمكين استخدام AVFoundation لالتقاط الفيديو ومراقبة جهاز الفيديو على نظام التشغيل OS X &gt;= 10.7. سيتم استخدام QTKit بخلاف ذلك.</translation>
 <translation id="3116361045094675131">لوحة المفاتيح البريطانية</translation>
 <translation id="1463985642028688653">حظر</translation>
 <translation id="1715941336038158809">اسم المستخدم أو كلمة المرور غير صالحة.</translation>
@@ -3745,6 +3748,7 @@
 <translation id="6658571109205370715">شفافية الشهادة</translation>
 <translation id="8050038245906040378">‏التوقيع بالرمز التجاري لـ Microsoft</translation>
 <translation id="7299721129597238157">حذف الإشارة المرجعية</translation>
+<translation id="7166627725100067582">‏يمكنك تمكين دعم Chromecast التجريبي للسماح بتشغيل مقاطع الفيديو والتحكم فيها من الويب على أجهزة Chromecast.</translation>
 <translation id="3031557471081358569">اختيار العناصر المراد استيرادها:</translation>
 <translation id="1368832886055348810">من اليسار لليمين</translation>
 <translation id="834106456999819211">طلبك قيد المعالجة</translation>
diff --git a/chrome/app/resources/generated_resources_bg.xtb b/chrome/app/resources/generated_resources_bg.xtb
index 294c2cd..5a22d8a 100644
--- a/chrome/app/resources/generated_resources_bg.xtb
+++ b/chrome/app/resources/generated_resources_bg.xtb
@@ -303,6 +303,7 @@
 <translation id="7607274158153386860">Заявка за сайта за таблети</translation>
 <translation id="8028060951694135607">Възстановяване на ключ от Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Можете да опитате да диагностицирате проблема, като предприемете следните стъпки: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Активиране на употребата на приложните програмни интерфейси (API) на AVFoundation под Mac OS X вместо на QTKit.</translation>
 <translation id="6317369057005134371">Прозорецът на приложението се изчаква...</translation>
 <translation id="6391832066170725637">Файлът или директорията не можаха да бъдат намерени.</translation>
 <translation id="7393381084163773901">Пощенски адрес</translation>
@@ -1292,6 +1293,7 @@
 <translation id="8442065444327205563">Документът е готов за преглед.</translation>
 <translation id="236141728043665931">Достъпът до микрофона да се блокира винаги</translation>
 <translation id="2307462900900812319">Конфигуриране на мрежата</translation>
+<translation id="1704385717926547822">Активиране на експерименталната поддръжка на Chromecast</translation>
 <translation id="5911798608827489036">Обмен на данни с всеки компютър в локалната мрежа или интернет</translation>
 <translation id="220858061631308971">Моля, въведете този ПИН код на „<ph name="DEVICE_NAME"/>“:</translation>
 <translation id="6263082573641595914">Версия на сертифициращ орган от Microsoft</translation>
@@ -2889,6 +2891,7 @@
 <translation id="8670869118777164560">Това разширение не успя да пренасочи заявка от мрежата към <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, защото друго разширение (<ph name="EXTENSION_NAME"/>) я пренасочи към <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Грешка при синхронизирането:  <ph name="PRODUCT_NAME"/> е стара версия и трябва да се актуализира.</translation>
 <translation id="790040513076446191">Манипулиране на свързаните с поверителността настройки</translation>
+<translation id="7260002739296185724">Активирайте употребата на AVFoundation за запис на видео и наблюдение на видеоустройства под OS X &gt;= 10.7. В противен случай ще се ползва QTKit.</translation>
 <translation id="3116361045094675131">Британска клавиатура</translation>
 <translation id="1463985642028688653">блокиране</translation>
 <translation id="1715941336038158809">Невалидно потребителско име или парола.</translation>
@@ -3737,6 +3740,7 @@
 <translation id="6658571109205370715">Прозрачност на сертификатите</translation>
 <translation id="8050038245906040378">Подписване от Microsoft на код за търговски цели</translation>
 <translation id="7299721129597238157">Изтриване на отметката</translation>
+<translation id="7166627725100067582">Активирайте експерименталната поддръжка, позволяваща използване на устройства Chromecast за възпроизвеждане и контролиране на видеоклипове от мрежата.</translation>
 <translation id="3031557471081358569">Изберете елементи за импортиране:</translation>
 <translation id="1368832886055348810">Отляво надясно</translation>
 <translation id="834106456999819211">Поръчката ви се обработва</translation>
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb
index 64c3690..bacd5a0 100644
--- a/chrome/app/resources/generated_resources_bn.xtb
+++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -309,6 +309,7 @@
       নিম্নলিখিত পদক্ষেপ গ্রহণের দ্বারা আপনি সমস্যা নির্ণয় করতে পারেন:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit এর পরিবর্তে Mac OS X AVFoundation APIs এর ব্যবহার সক্ষম করুন।</translation>
 <translation id="6317369057005134371">অ্যাপ্লিকেশন উইন্ডোর জন্য অপেক্ষা করা হচ্ছে...</translation>
 <translation id="6391832066170725637">ফাইল অথবা ডাইরেক্টরি খুঁজে পাওয়া যাবে না৷</translation>
 <translation id="7393381084163773901">রাস্তার ঠিকানা</translation>
@@ -1304,6 +1305,7 @@
 <translation id="8442065444327205563">আপনার দস্তাবেজটি দেখার জন্য প্রস্তুত৷</translation>
 <translation id="236141728043665931">মাইক্রোফোনের অ্যাক্সেস সর্বদা অবরুদ্ধ রাখুন</translation>
 <translation id="2307462900900812319">নেটওয়ার্ক কনফিগার করুন</translation>
+<translation id="1704385717926547822">পরীক্ষামূলক Chromecast সহায়তা সক্ষম করুন</translation>
 <translation id="5911798608827489036">স্থানীয় নেটওয়ার্ক বা ইন্টারনেটে যেকোনো কম্পিউটারের সাথে ডেটা বিনিময় করুন</translation>
 <translation id="220858061631308971">দয়া করে  <ph name="DEVICE_NAME"/> &quot;-এ পিন কোড লিখুন: </translation>
 <translation id="6263082573641595914">Microsoft CA সংস্করণ</translation>
@@ -2916,6 +2918,7 @@
 <translation id="8670869118777164560">এই এক্সটেনশনটি <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>এ একটি নেটওয়ার্কের পুনঃনির্দেশ অনুরোধ করতে ব্যর্থ হয়েছে কারণ অন্য এক্সটেনশন (<ph name="EXTENSION_NAME"/>) এটিকে <ph name="ACTUAL_REDIRECT_DESTINATION"/> এ পুনঃনির্দেশ করেছে৷</translation>
 <translation id="3654092442379740616">সিঙ্ক ত্রুটি: <ph name="PRODUCT_NAME"/> তারিখ সীমার বাইরে এবং আপডেট করা প্রয়োজন৷</translation>
 <translation id="790040513076446191">গোপনীয়তা-সংক্রান্ত সেটিংস নিপূণভাবে ব্যবহার করুন</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7 এ ভিডিও ক্যাপচার ও ভিডিও ডিভাইস নিয়ন্ত্রণের জন্য AVFoundation'র ব্যবহার সক্ষম করুন৷ অন্যথায়, QTKit ব্যবহার করা হবে৷</translation>
 <translation id="3116361045094675131">ইউকে কীবোর্ড</translation>
 <translation id="1463985642028688653">অবরুদ্ধ করুন</translation>
 <translation id="1715941336038158809">অবৈধ ব্যবহারকারী নাম বা পাসওয়ার্ড৷</translation>
@@ -3769,6 +3772,7 @@
 <translation id="6658571109205370715">শংসাপত্রের স্বচ্ছতা</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">বুকমার্ক মুছুন</translation>
+<translation id="7166627725100067582">Chromecast ডিভাইসগুলিতে ওয়েব থেকে ভিডিওগুলিকে চালানো ও নিয়ন্ত্রণ করার বিষয়ে Chromecast এর পরীক্ষামূলক সমর্থন সক্ষম করুন৷</translation>
 <translation id="3031557471081358569">আমদানির জন্য আইটেম নির্বাচন করুন:</translation>
 <translation id="1368832886055348810">বাম থেকে ডান</translation>
 <translation id="834106456999819211">আপনার অর্ডারটি প্রক্রিয়া করা হয়েছে</translation>
diff --git a/chrome/app/resources/generated_resources_ca.xtb b/chrome/app/resources/generated_resources_ca.xtb
index 5f8c737..2c27699 100644
--- a/chrome/app/resources/generated_resources_ca.xtb
+++ b/chrome/app/resources/generated_resources_ca.xtb
@@ -307,6 +307,7 @@
           Per provar de diagnosticar el problema, seguiu aquests passos:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Activa l'ús de les API de Mac OS X AVFoundation, en lloc de QTKit.</translation>
 <translation id="6317369057005134371">S'està esperant la finestra de l'aplicació...</translation>
 <translation id="6391832066170725637">No s'ha trobat el fitxer ni el directori.</translation>
 <translation id="7393381084163773901">Adreça postal</translation>
@@ -1291,6 +1292,7 @@
 <translation id="8442065444327205563">Ja podeu visualitzar el docum.</translation>
 <translation id="236141728043665931">Bloqueja sempre l'accés al micròfon</translation>
 <translation id="2307462900900812319">Configura la xarxa</translation>
+<translation id="1704385717926547822">Activa la compatibilitat de Chromecast experimental</translation>
 <translation id="5911798608827489036">Intercanvia dades amb un altre ordinador de la xarxa local o d'Internet</translation>
 <translation id="220858061631308971">Introduïu aquest codi PIN a &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Versió de CA de Microsoft</translation>
@@ -2894,6 +2896,7 @@
 <translation id="8670869118777164560">Aquesta extensió no ha pogut redirigir una sol·licitud de xarxa a <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> perquè una altra extensió (<ph name="EXTENSION_NAME"/>) l'ha redirigida a <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Error de sincronització: <ph name="PRODUCT_NAME"/> no està actualitzat i necessita una actualització.</translation>
 <translation id="790040513076446191">Manipular la configuració relacionada amb la privadesa</translation>
+<translation id="7260002739296185724">Activa l'ús d'AV Foundation per capturar vídeo i controlar dispositius de vídeo a OS X 10.7 (o posteriors); si no s'activa, s'utilitzarà QTKit.</translation>
 <translation id="3116361045094675131">Teclat anglès</translation>
 <translation id="1463985642028688653">bloqueja</translation>
 <translation id="1715941336038158809">El nom d'usuari o la contrasenya no són vàlids.</translation>
@@ -3755,6 +3758,7 @@
 <translation id="6658571109205370715">Transparència del certificat</translation>
 <translation id="8050038245906040378">Signatura de codi comercial de Microsoft</translation>
 <translation id="7299721129597238157">Suprimeix l'adreça d'interès</translation>
+<translation id="7166627725100067582">Activa la compatibilitat de Chromecast experimental per reproduir i controlar vídeos d'Internet en dispositius Chromecast.</translation>
 <translation id="3031557471081358569">Selecciona elements per importar:</translation>
 <translation id="1368832886055348810">D'esquerra a dreta</translation>
 <translation id="834106456999819211">La vostra comanda s'està processant</translation>
@@ -4646,7 +4650,7 @@
 <translation id="7664620655576155379">Dispositiu Bluetooth no compatible: &quot;<ph name="DEVICE_NAME"/>&quot;.</translation>
 <translation id="2990212470195050777">Desactiva l'API font multimèdia sense prefix</translation>
 <translation id="2225024820658613551">No hauríeu de continuar, &lt;strong&gt;sobretot&lt;/strong&gt; si és la primera vegada que veieu aquesta advertència en aquest lloc.</translation>
-<translation id="2049639323467105390"><ph name="DOMAIN"/> gestiona aquest dispositiu.</translation>
+<translation id="2049639323467105390">Aquest dispositiu està gestionat per <ph name="DOMAIN"/></translation>
 <translation id="1932098463447129402">No abans</translation>
 <translation id="5409029099497331039">Sorprèn-me</translation>
 <translation id="7845920762538502375"><ph name="PRODUCT_NAME"/> no pot sincronitzar les dades perquè no s'ha pogut connectar al servidor de sincronització. S'està tornant a provar...</translation>
diff --git a/chrome/app/resources/generated_resources_cs.xtb b/chrome/app/resources/generated_resources_cs.xtb
index 1bf8b53..df391a2 100644
--- a/chrome/app/resources/generated_resources_cs.xtb
+++ b/chrome/app/resources/generated_resources_cs.xtb
@@ -304,6 +304,7 @@
           Problém můžete zkusit diagnostikovat pomocí následujících kroků:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Povolit použití rozhraní Mac OS X AVFoundation API namísto rozhraní QTKit</translation>
 <translation id="6317369057005134371">Čekání na okno aplikace...</translation>
 <translation id="6391832066170725637">Soubor nebo adresář se nepodařilo nalézt.</translation>
 <translation id="7393381084163773901">Ulice a číslo popisné</translation>
@@ -1291,6 +1292,7 @@
 <translation id="8442065444327205563">Dokument připraven k zobrazení</translation>
 <translation id="236141728043665931">Vždy blokovat přístup k mikrofonu</translation>
 <translation id="2307462900900812319">Konfigurovat síť</translation>
+<translation id="1704385717926547822">Povolit experimentální podporu Chromecastu</translation>
 <translation id="5911798608827489036">Výměna dat s libovolným počítačem v lokální síti nebo internetu</translation>
 <translation id="220858061631308971">Zadejte prosím v zařízení <ph name="DEVICE_NAME"/> tento kód PIN:</translation>
 <translation id="6263082573641595914">Verze CA Microsoft</translation>
@@ -2898,6 +2900,7 @@
 <translation id="8670869118777164560">Tomuto rozšíření se nepodařilo přesměrovat požadavek sítě do umístění <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, protože jej jiné rozšíření (<ph name="EXTENSION_NAME"/>) přesměrovalo do umístění <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Chyba synchronizace: Prohlížeč <ph name="PRODUCT_NAME"/> je zastaralý a potřebuje aktualizovat.</translation>
 <translation id="790040513076446191">Manipulovat s nastavením týkajícím se ochrany soukromí</translation>
+<translation id="7260002739296185724">Povolí v systému OS X 10.7 a novějších verzích použití rozhraní AV Foundation pro záznam videa a sledování videozařízení. V jiných případech bude použito rozhraní QTKit.</translation>
 <translation id="3116361045094675131">Britská klávesnice</translation>
 <translation id="1463985642028688653">blokovat</translation>
 <translation id="1715941336038158809">Neplatné uživatelské jméno nebo heslo.</translation>
@@ -3759,6 +3762,7 @@
 <translation id="6658571109205370715">Transparentnost certifikátu</translation>
 <translation id="8050038245906040378">Komerční podepisování kódu Microsoft</translation>
 <translation id="7299721129597238157">Smazat záložku</translation>
+<translation id="7166627725100067582">Povolí experimentální podporu Chromecastu, která umožňuje přehrávat a ovládat videa z webu v zařízeních Chromecast.</translation>
 <translation id="3031557471081358569">Vyberte položky k importu:</translation>
 <translation id="1368832886055348810">Zleva doprava</translation>
 <translation id="834106456999819211">Vaše objednávka se zpracovává</translation>
diff --git a/chrome/app/resources/generated_resources_da.xtb b/chrome/app/resources/generated_resources_da.xtb
index 419dcd3..ef441c9 100644
--- a/chrome/app/resources/generated_resources_da.xtb
+++ b/chrome/app/resources/generated_resources_da.xtb
@@ -83,7 +83,7 @@
 <translation id="2105006017282194539">Ikke indlæst endnu</translation>
 <translation id="7821009361098626711">Serveren <ph name="DOMAIN"/> kræver et brugernavn og en adgangskode. Serveren siger: <ph name="REALM"/>.</translation>
 <translation id="8546541260734613940">[*.]eksempel.dk</translation>
-<translation id="524759338601046922">Angiv den nye PIN-kode igen:</translation>
+<translation id="524759338601046922">Angiv den nye pinkode igen:</translation>
 <translation id="2580889980133367162">Tillad altid, at <ph name="HOST"/> downloader flere forskellige filer</translation>
 <translation id="8972513834460200407">Kontakt din netværksadministrator for at sikre, at firewallen ikke blokerer downloads fra Google-servere.</translation>
 <translation id="1444628761356461360">Denne indstilling administreres af enhedsejeren <ph name="OWNER_EMAIL"/>.</translation>
@@ -294,7 +294,7 @@
 <translation id="6015796118275082299">År</translation>
 <translation id="8106242143503688092">Indlæs ikke (anbefales)</translation>
 <translation id="2647434099613338025">Tilføj sprog</translation>
-<translation id="5078796286268621944">Forkert PIN-kode</translation>
+<translation id="5078796286268621944">Forkert pinkode</translation>
 <translation id="3480411814272635771">Forekomster, hvor en fane ikke svarede</translation>
 <translation id="8487678622945914333">Zoom ind</translation>
 <translation id="3846593650622216128">Disse indstillinger håndhæves af en udvidelse.</translation>
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Anmod om tabletwebsite</translation>
 <translation id="8028060951694135607">Microsoft-nøglegenoprettelse</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Du kan forsøge at diagnosticere problemet ved hjælp af følgende trin: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Aktivér brug af Mac OS X AVFoundation-API'er i stedet for QTKit.</translation>
 <translation id="6317369057005134371">Venter på applikationsvindue...</translation>
 <translation id="6391832066170725637">Filen eller mappen blev ikke fundet.</translation>
 <translation id="7393381084163773901">Adresse</translation>
@@ -882,7 +883,7 @@
 <translation id="6677037229676347494">Det forventede id er &quot;<ph name="EXPECTED_ID"/>&quot;, men id'et var &quot;<ph name="NEW_ID"/>&quot;.</translation>
 <translation id="7400418766976504921">Webadresse</translation>
 <translation id="7456847797759667638">Åbn placering...</translation>
-<translation id="3754634516926225076">Forkert PIN-kode. Prøv igen.</translation>
+<translation id="3754634516926225076">Forkert pinkode. Prøv igen.</translation>
 <translation id="5622017037336776003">Åbn PDF-fil i Læser</translation>
 <translation id="7378627244592794276">Nej</translation>
 <translation id="6949306908218145636">Tilføjer åbne sider som bogmærke...</translation>
@@ -964,7 +965,7 @@
 <translation id="4692690030323697737">Mellemnavn(e)</translation>
 <translation id="1779766957982586368">Luk vindue</translation>
 <translation id="4850886885716139402">Vis</translation>
-<translation id="89217462949994770">Du har angivet en forkert PIN-kode for mange gange. Kontakt <ph name="CARRIER_ID"/> for at få en ny 8-cifret nøgle til oplåsning af PIN-kode.</translation>
+<translation id="89217462949994770">Du har angivet en forkert pinkode for mange gange. Kontakt <ph name="CARRIER_ID"/> for at få en ny 8-cifret nøgle til oplåsning af pinkode.</translation>
 <translation id="2776441542064982094">Det ser ud til, at der ikke kan registreres nogen tilgængelige enheder på netværket. Hvis din enhed er tændt og har forbindelse til internettet, kan du prøve at registrere den ved hjælp af vejledningen i instruktionsmanualen.</translation>
 <translation id="8659716501582523573">IP-adresse:</translation>
 <translation id="5920618722884262402">Bloker krænkende ord</translation>
@@ -1148,7 +1149,7 @@
 <translation id="2359345697448000899">Administrer dine udvidelser ved at klikke på Udvidelser i værktøjsmenuen.</translation>
 <translation id="6725970970008349185">Antal kandidater, der skal vises pr. side</translation>
 <translation id="6513615899227776181">Plugin: <ph name="PLUGIN_NAME"/></translation>
-<translation id="6198252989419008588">Skift PIN-kode</translation>
+<translation id="6198252989419008588">Skift pinkode</translation>
 <translation id="5749483996735055937">Der opstod et problem under kopieringen af genoprettelsesbilledet til enheden.</translation>
 <translation id="4341364588986930687"><ph name="DOMAIN"/> kræver, at din enheds identitet bekræftes af Google, for at fastslå muligheden for forbedret afspilning af beskyttede medier. <ph name="LEARN_MORE"/>.</translation>
 <translation id="7643817847124207232">Forbindelsen til internettet er tabt.</translation>
@@ -1298,6 +1299,7 @@
 <translation id="8442065444327205563">Dit dokument er klar til visning.</translation>
 <translation id="236141728043665931">Bloker altid mikrofonadgang</translation>
 <translation id="2307462900900812319">Konfigurer netværk</translation>
+<translation id="1704385717926547822">Aktivér eksperimentel understøttelse af Chromecast</translation>
 <translation id="5911798608827489036">Udveksl data med en computer på det lokale netværk eller internettet</translation>
 <translation id="220858061631308971">Indtast denne pinkode på &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Version af Microsoft-nøglecenter</translation>
@@ -1630,7 +1632,7 @@
 Når der oprettes en administreret bruger, oprettes der ikke automatisk en Google-konto, og brugerens bogmærker, browserhistorik og øvrige indstillinger vil ikke blive synkroniseret til andre enheder med Chrome-synkronisering.
 
 Når du har oprettet en ny administreret bruger, kan du til enhver tid administrere vedkommendes indstillinger på en hvilken som helst enhed på www.chrome.com/manage. <ph name="BEGIN_LINK"/>Få flere oplysninger om administrerede brugere<ph name="END_LINK"/></translation>
-<translation id="6562758426028728553">Angiv den gamle og nye PIN-kode.</translation>
+<translation id="6562758426028728553">Angiv den gamle og nye pinkode.</translation>
 <translation id="614161640521680948">Sprog:</translation>
 <translation id="6404511346730675251">Rediger bogmærke</translation>
 <translation id="6718273304615422081">Komprimerer...</translation>
@@ -1691,7 +1693,7 @@
 <translation id="7767646430896201896">Indstillinger:</translation>
 <translation id="3562567103352435966">Websitet på <ph name="HOST_NAME"/> indeholder elementer fra websites, der ser ud til at hoste malware, dvs. software, som kan skade din enhed eller på anden måde foretage handlinger, som du ikke har givet tilladelse til. Hvis du besøger et website, der indeholder malware, kan det risikere at inficere din enhed. Websitet hoster også indhold fra websites, der er blevet rapporteret som &quot;phishingwebsites&quot;. Phishingwebsites narrer brugere til at opgive personlige eller økonomiske oplysninger. Websites gør ofte dette ved at udgive sig for at repræsentere troværdige institutioner, f.eks. banker.</translation>
 <translation id="7124398136655728606">Esc rydder hele præredigeringsbuffer</translation>
-<translation id="3344786168130157628">Navn på adgangspunkt:</translation>
+<translation id="3344786168130157628">Adgangspunkt:</translation>
 <translation id="8293206222192510085">Tilføj bogmærke</translation>
 <translation id="2592884116796016067">En del af denne side (HTML WebWorker) er gået ned og fungerer derfor muligvis ikke korrekt.</translation>
 <translation id="4310934920174255895"><ph name="BEGIN_BOLD"/>Du er i inkognitotilstand.<ph name="END_BOLD"/>
@@ -2102,7 +2104,7 @@
 <translation id="8457625695411745683">god</translation>
 <translation id="8335587457941836791">Frigør fra hylden</translation>
 <translation id="2222641695352322289">Den eneste måde at fortryde dette på er ved at geninstallere <ph name="IDS_SHORT_PRODUCT_OS_NAME"/>.</translation>
-<translation id="5605716740717446121">Dit SIM-kort deaktiveres permanent, hvis du ikke kan angive den korrekte nøgle til oplåsning af PIN-kode. Forsøg tilbage: <ph name="TRIES_COUNT"/></translation>
+<translation id="5605716740717446121">Dit SIM-kort deaktiveres permanent, hvis du ikke kan angive den korrekte nøgle til oplåsning af pinkode. Forsøg tilbage: <ph name="TRIES_COUNT"/></translation>
 <translation id="7863819943399969413">Opret en app på dette website...</translation>
 <translation id="5502500733115278303">Importeret fra Firefox</translation>
 <translation id="569109051430110155">Find automatisk</translation>
@@ -2203,7 +2205,7 @@
 <translation id="5495466433285976480">Dette vil fjerne alle lokale brugere, filer, data og andre indstillinger, når du genstarter næste gang. Alle brugere skal logge ind igen.</translation>
 <translation id="7842346819602959665">Den nyeste version af udvidelsen &quot;<ph name="EXTENSION_NAME"/>&quot; kræver flere tilladelser, så den er deaktiveret.</translation>
 <translation id="3776667127601582921">I dette tilfælde er servercertifikatet eller et mellem-CA-certifikat, der  præsenteres for din browser, ugyldige. Dette kan betyde, at certifikatet er i et forkert format, indeholder ugyldige felter, eller ikke understøttes.</translation>
-<translation id="2412835451908901523">Angiv den 8-cifrede nøgle til oplåsning af PIN-kode, som du har fået fra <ph name="CARRIER_ID"/></translation>
+<translation id="2412835451908901523">Angiv den 8-cifrede nøgle til oplåsning af pinkode, som du har fået fra <ph name="CARRIER_ID"/></translation>
 <translation id="25770266525034120">Udvidelseswebadresse</translation>
 <translation id="7548916768233393626">Gennemtving høj DPI-tilstand</translation>
 <translation id="33562952999632466">DevTools anmoder om fuld adgang til <ph name="FOLDER_PATH"/>. Sørg for, at du ikke afslører nogen følsomme oplysninger.</translation>
@@ -2308,7 +2310,7 @@
 <translation id="409579654357498729">Føj til Cloudprinter</translation>
 <translation id="2120316813730635488">Forekomster, hvor en udvidelse blev installeret</translation>
 <translation id="8398877366907290961">Fortsæt alligevel</translation>
-<translation id="5063180925553000800">Ny PIN-kode:</translation>
+<translation id="5063180925553000800">Ny pinkode:</translation>
 <translation id="4883178195103750615">Eksporter bogmærker til HTML-fil...</translation>
 <translation id="2496540304887968742">Denne enhed skal have en kapacitet på 4 GB eller mere.</translation>
 <translation id="6974053822202609517">Højre til venstre</translation>
@@ -2585,7 +2587,7 @@
 <translation id="350945665292790777">Bruger GPU-accelereret sammensætning på alle sider, ikke kun dem, der omfatter GPU-accelererede lag.</translation>
 <translation id="5273628206174272911">Eksperimentel funktion, der muliggør vandret rulning i historikken.</translation>
 <translation id="4360991150548211679">Downloads er i gang</translation>
-<translation id="8278091814884719774">Er du sikker på, at du vil konfigurere denne enhed som en Chromebox til møder?</translation>
+<translation id="8278091814884719774">Er du sikker på, at du vil konfigurere denne enhed som en Chromebox til videokonference?</translation>
 <translation id="180035236176489073">Du skal være online for at få adgang til disse filer.</translation>
 <translation id="4522570452068850558">Detaljer</translation>
 <translation id="1091767800771861448">Tryk på ESC for at springe over (kun uofficielle builds).</translation>
@@ -2702,7 +2704,7 @@
 <translation id="1774833706453699074">Tilføj åbne sider som bogmærker...</translation>
 <translation id="5031870354684148875">Om Google Oversæt</translation>
 <translation id="5702389759209837579">Få adgang til dine åbne faner på alle dine enheder.</translation>
-<translation id="8381055888183086563">Aktiverer fejlretning af indstillinger for kontekstmenu som f.eks. Inspect Element for pakkede applikationer.</translation>
+<translation id="8381055888183086563">Aktiverer fejlretning af indstillinger for genvejsmenu, f.eks. Inspect Element for pakkede applikationer.</translation>
 <translation id="1675020493753693718">Aktivér interaktiv autofuldførelse</translation>
 <translation id="1189418886587279221">Aktivér hjælpefunktioner for at gøre din enhed nemmere at bruge.</translation>
 <translation id="8263744495942430914"><ph name="FULLSCREEN_ORIGIN"/> har deaktiveret din musemarkør.</translation>
@@ -2748,7 +2750,7 @@
 <translation id="8477384620836102176">&amp;Generelt</translation>
 <translation id="7785791760347294399">Appoplysninger...</translation>
 <translation id="8059417245945632445">&amp;Inspicer enheder</translation>
-<translation id="3391392691301057522">Gammel PIN-kode:</translation>
+<translation id="3391392691301057522">Gammel pinkode:</translation>
 <translation id="96421021576709873">Wi-Fi-netværk</translation>
 <translation id="1344519653668879001">Deaktiver revision af hyperlink</translation>
 <translation id="6463795194797719782">&amp;Rediger</translation>
@@ -2902,6 +2904,7 @@
 <translation id="8670869118777164560">Denne udvidelse kunne ikke omdirigere en netværksanmodning til <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, fordi en anden udvidelse (<ph name="EXTENSION_NAME"/>) omdirigerede den til <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Synkroniseringsfejl: <ph name="PRODUCT_NAME"/> er forældet og skal opdateres.</translation>
 <translation id="790040513076446191">Manipuler indstillinger til beskyttelse af personlige oplysninger</translation>
+<translation id="7260002739296185724">Aktivér brug af AVFoundation til optagelse af video og overvågning af videoenheder i OS X &gt;= 10.7. Hvis AVFoundation ikke aktiveres, bruges QTKit i stedet.</translation>
 <translation id="3116361045094675131">Britisk tastatur</translation>
 <translation id="1463985642028688653">bloker</translation>
 <translation id="1715941336038158809">Ugyldigt brugernavn eller ugyldig adgangskode.</translation>
@@ -3761,6 +3764,7 @@
 <translation id="6658571109205370715">Gennemsigtighed for certifikater</translation>
 <translation id="8050038245906040378">Microsoft-signering af kommerciel kode</translation>
 <translation id="7299721129597238157">Slet bogmærke</translation>
+<translation id="7166627725100067582">Aktivér eksperimentel understøttelse af Chromecast. Dette gør det muligt at afspille og styre videoer fra nettet på Chromecast-enheder.</translation>
 <translation id="3031557471081358569">Vælg at importere følgende:</translation>
 <translation id="1368832886055348810">Venstre til højre</translation>
 <translation id="834106456999819211">Din ordre behandles</translation>
@@ -4229,7 +4233,7 @@
 <translation id="129553762522093515">Senest lukkede</translation>
 <translation id="1588870296199743671">Åbn link med...</translation>
 <translation id="4761104368405085019">Brug din mikrofon</translation>
-<translation id="4287167099933143704">Angiv nøgle til oplåsning af PIN-kode</translation>
+<translation id="4287167099933143704">Angiv nøgle til oplåsning af pinkode</translation>
 <translation id="3936418843437416078">Installationer</translation>
 <translation id="3129140854689651517">Find tekst</translation>
 <translation id="2473195200299095979">Oversæt denne side</translation>
@@ -4508,7 +4512,7 @@
 <translation id="4450974146388585462">Diagnosticer</translation>
 <translation id="7339763383339757376">PKCS #7, enkeltcertifikat</translation>
 <translation id="7587108133605326224">Baltisk</translation>
-<translation id="3991936620356087075">Du har angivet den forkert nøgle til oplåsning af PIN-kode for mange gange. Dit SIM-kort deaktiveres permanent.</translation>
+<translation id="3991936620356087075">Du har angivet den forkert nøgle til oplåsning af pinkode for mange gange. Dit SIM-kort deaktiveres permanent.</translation>
 <translation id="5367091008316207019">Læser fil...</translation>
 <translation id="936801553271523408">Data til systemdiagnosticering</translation>
 <translation id="3634258439821604538">Deaktiver tilføjelser til scripts for tilgængelighed.</translation>
@@ -4720,7 +4724,7 @@
 <translation id="6921812972154549137">Cookies og andre website- og plugindata</translation>
 <translation id="8137559199583651773">Administrer udvidelser</translation>
 <translation id="6886871292305414135">Åbn link i ny &amp;fane</translation>
-<translation id="1639192739400715787">Angiv PIN-kode til SIM-kort for at få adgang til sikkerhedsindstillingerne</translation>
+<translation id="1639192739400715787">Angiv pinkode til SIM-kort for at få adgang til sikkerhedsindstillingerne</translation>
 <translation id="4499634737431431434">Uger</translation>
 <translation id="7961015016161918242">Aldrig</translation>
 <translation id="3950924596163729246">Der kunne ikke opnås adgang til netværket.</translation>
@@ -4851,7 +4855,7 @@
 <translation id="988159990683914416">Udviklerversion</translation>
 <translation id="1097658378307015415">Før du logger ind, skal du logge ind som gæst for at aktivere netværket <ph name="NETWORK_ID"/></translation>
 <translation id="5170477580121653719">Ledig plads på Google Drev: <ph name="SPACE_AVAILABLE"/>.</translation>
-<translation id="4114470632216071239">Lås SIM-kort (kræv PIN-kode for at bruge mobildata)</translation>
+<translation id="4114470632216071239">Lås SIM-kort (kræv pinkode for at bruge mobildata)</translation>
 <translation id="6581162200855843583">Link til Google Drev</translation>
 <translation id="5783221160790377646">En administreret bruger kunne ikke oprettes på grund af en fejl. Prøv igen senere.</translation>
 <translation id="340771324714262530">Stop spejling</translation>
@@ -4946,7 +4950,7 @@
 <translation id="3046910703532196514">Webside, komplet</translation>
 <translation id="5062930723426326933">Login mislykkedes. Opret forbindelse til internettet, og prøv igen.</translation>
 <translation id="5316716239522500219">Spejlvend skærmene</translation>
-<translation id="9112614144067920641">Vælg en ny PIN-kode.</translation>
+<translation id="9112614144067920641">Vælg en ny pinkode.</translation>
 <translation id="1338950911836659113">Sletter...</translation>
 <translation id="7109926893210135223">Downloaden er i gang</translation>
 <translation id="2061855250933714566"><ph name="ENCODING_CATEGORY"/> (<ph name="ENCODING_NAME"/>)</translation>
@@ -5114,7 +5118,7 @@
 <translation id="1038842779957582377">ukendt navn</translation>
 <translation id="5327248766486351172">Navn</translation>
 <translation id="2150661552845026580">Vil du tilføje &quot;<ph name="EXTENSION_NAME"/>&quot;?</translation>
-<translation id="5553784454066145694">Vælg ny PIN-kode</translation>
+<translation id="5553784454066145694">Vælg ny pinkode</translation>
 <translation id="6101226222197207147">Ny app er tilføjet (<ph name="EXTENSION_NAME"/>)</translation>
 <translation id="8989148748219918422"><ph name="ORGANIZATION"/> [<ph name="COUNTRY"/>]</translation>
 <translation id="8248821880964244299">Vil du virkelig gerne slette denne app?</translation>
@@ -5168,7 +5172,7 @@
 <translation id="4393744079468921084">Ja, afslut inkognitotilstand</translation>
 <translation id="6920989436227028121">Åbn som almindelig fane</translation>
 <translation id="4057041477816018958"><ph name="SPEED"/> - <ph name="RECEIVED_AMOUNT"/></translation>
-<translation id="2050339315714019657">Portræt</translation>
+<translation id="2050339315714019657">Stående</translation>
 <translation id="8273027367978594412">Når den er aktiveret, vil en gæstebruger være tilgængelig i skrivebordsversionen af Chrome.</translation>
 <translation id="6991128190741664836">Senere</translation>
 <translation id="8261490674758214762">De kan:</translation>
@@ -5316,7 +5320,7 @@
 <translation id="5233736638227740678">&amp;Indsæt</translation>
 <translation id="8308427013383895095">Oversættelsen mislykkedes på grund af problemer med netværksforbindelsen.</translation>
 <translation id="1828901632669367785">Dialogboks til Udskriv via system...</translation>
-<translation id="1801298019027379214">Forkert PIN-kode. Prøv igen. Forsøg tilbage: <ph name="TRIES_COUNT"/></translation>
+<translation id="1801298019027379214">Forkert pinkode. Prøv igen. Forsøg tilbage: <ph name="TRIES_COUNT"/></translation>
 <translation id="534749176369872155"><ph name="SITE"/> gav Chrome en liste over forhåndsgodkendte loginoplysninger for certifikater. Chrome modtog ikke nogen forhåndsgodkendte loginoplysninger under dette forsøg på at oprette forbindelse, hvilket indikerer, at en person foregiver at repræsentere <ph name="SITE"/>.</translation>
 <translation id="992543612453727859">Tilføj udtryk foran</translation>
 <translation id="4728558894243024398">Platform</translation>
diff --git a/chrome/app/resources/generated_resources_de.xtb b/chrome/app/resources/generated_resources_de.xtb
index b48279b..d59a6e1 100644
--- a/chrome/app/resources/generated_resources_de.xtb
+++ b/chrome/app/resources/generated_resources_de.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Tablet-Website anfordern</translation>
 <translation id="8028060951694135607">Microsoft-Schlüsselwiederherstellung</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/><ph name="LINE_BREAK"/> Sie können versuchen, das Problem folgendermaßen zu diagnostizieren:<ph name="LINE_BREAK"/><ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">AVFoundation APIs für Mac OS X aktivieren (statt Verwendung von QTKit)</translation>
 <translation id="6317369057005134371">Warten auf Anwendungsfenster...</translation>
 <translation id="6391832066170725637">Die Datei oder das Verzeichnis konnte nicht gefunden werden.</translation>
 <translation id="7393381084163773901">Postadresse</translation>
@@ -1293,6 +1294,7 @@
 <translation id="8442065444327205563">Ihr Dokument ist bereit.</translation>
 <translation id="236141728043665931">Zugriff auf das Mikrofon immer blockieren</translation>
 <translation id="2307462900900812319">Netzwerk konfigurieren</translation>
+<translation id="1704385717926547822">Experimentelle Chromecast-Unterstützung aktivieren</translation>
 <translation id="5911798608827489036">Daten mit einem beliebigen Computer im lokalen Netz oder Internet austauschen</translation>
 <translation id="220858061631308971">Geben Sie diesen PIN-Code bitte auf &quot;<ph name="DEVICE_NAME"/> &quot; ein:</translation>
 <translation id="6263082573641595914">Microsoft - Version der Zertifizierungsstelle</translation>
@@ -1813,7 +1815,7 @@
 <translation id="39964277676607559">JavaScript-Datei &quot;<ph name="RELATIVE_PATH"/>&quot; konnte nicht für das Content-Skript geladen werden.</translation>
 <translation id="979598830323579437">Vergrößerungsfaktor der Lupe erhöhen</translation>
 <translation id="4284105660453474798">Möchten Sie &quot;$1&quot; wirklich löschen?</translation>
-<translation id="1600857548979126453">Auf das Backend für Seiten-Debugger zugreifen</translation>
+<translation id="1600857548979126453">Auf das Back-End für Seiten-Debugger zugreifen</translation>
 <translation id="3516765099410062445">Der Verlauf für alle Geräte, auf denen Sie angemeldet sind, wird angezeigt. <ph name="BEGIN_LINK"/>Weitere Informationen<ph name="END_LINK"/></translation>
 <translation id="4378551569595875038">Verbindung...</translation>
 <translation id="7029809446516969842">Passwörter</translation>
@@ -1868,7 +1870,7 @@
 <translation id="3081104028562135154">Erhöhen</translation>
 <translation id="3734816294831429815"><ph name="PRODUCT_NAME"/> wird in <ph name="SECONDS"/> Sekunden neu gestartet.</translation>
 <translation id="2728624657977418581">Vornamen hinzufügen</translation>
-<translation id="8732030010853991079">Klicken Sie auf dieses Symbol, um diese Erweiterung zu verwenden.</translation>
+<translation id="8732030010853991079">Klicken Sie auf dieses Symbol, um die Erweiterung zu verwenden.</translation>
 <translation id="32330993344203779">Ihr Gerät wurde erfolgreich für die Verwaltung für Unternehmen angemeldet.</translation>
 <translation id="158917669717260118">Die Webseite konnte nicht geladen werden, da sich Ihr Computer im Ruhemodus befindet. Dabei werden alle Netzwerkverbindungen unterbrochen und neue Netzwerkanfragen schlagen fehl. Das Problem lässt sich normalerweise beheben, indem die Seite neu geladen wird.</translation>
 <translation id="6316671927443834085">Die Verbindung mit &quot;<ph name="DEVICE_NAME"/>&quot; konnte nicht getrennt werden.</translation>
@@ -2661,7 +2663,7 @@
 <translation id="3714633008798122362">Web-Kalender</translation>
 <translation id="3251759466064201842">&lt;Gehört nicht zum Zertifikat&gt;</translation>
 <translation id="6186096729871643580">Antialiasing für LCD-Text</translation>
-<translation id="7303492016543161086">Optionen für Bedienungshilfen im Taskleistenmenü anzeigen</translation>
+<translation id="7303492016543161086">Optionen für Bedienungshilfen im Systemmenü anzeigen</translation>
 <translation id="6410257289063177456">Bilddateien</translation>
 <translation id="6419902127459849040">Mitteleuropäisch</translation>
 <translation id="6707389671160270963">SSL-Client-Zertifikat</translation>
@@ -2682,7 +2684,7 @@
 <translation id="5702389759209837579">Greifen Sie auf Ihre offenen Tabs auf all Ihren Geräten zu.</translation>
 <translation id="8381055888183086563">Aktiviert Kontextmenü-Optionen für das Debugging, wie z. B. &quot;Element prüfen&quot; für gepackte Apps</translation>
 <translation id="1675020493753693718">Interaktive Autovervollständigung aktivieren</translation>
-<translation id="1189418886587279221">Aktivieren Sie Zugänglichkeitsfunktionen, damit Ihr Gerät noch leichter zu verwenden ist.</translation>
+<translation id="1189418886587279221">Aktivieren Sie die Bedienungshilfe-Funktionen, damit Ihr Gerät leichter zu verwenden ist.</translation>
 <translation id="8263744495942430914"><ph name="FULLSCREEN_ORIGIN"/> hat Ihren Mauszeiger deaktiviert.</translation>
 <translation id="6404451368029478467"><ph name="PRODUCT_NAME"/> wird automatisch aktualisiert, sodass Sie immer über die neueste Version verfügen. Nach Abschluss des Downloads wird <ph name="PRODUCT_NAME"/> neu gestartet und Sie können fortfahren.</translation>
 <translation id="3367237600478196733">Seitenladevorgänge</translation>
@@ -2880,6 +2882,7 @@
 <translation id="8670869118777164560">Die Erweiterung konnte die Netzwerkanfrage nicht an <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> weiterleiten, da eine andere Erweiterung (<ph name="EXTENSION_NAME"/>) sie an <ph name="ACTUAL_REDIRECT_DESTINATION"/> weitergeleitet hat.</translation>
 <translation id="3654092442379740616">Synchronisierungsfehler: <ph name="PRODUCT_NAME"/> ist veraltet und muss aktualisiert werden.</translation>
 <translation id="790040513076446191">Datenschutzeinstellungen bearbeiten</translation>
+<translation id="7260002739296185724">Aktiviert AVFoundation für Videoaufnahmen und Videoüberwachung auf Geräten mit OS X 10.7 oder höher. Andernfalls wird QTKit verwendet.</translation>
 <translation id="3116361045094675131">UK-Englische Tastatur </translation>
 <translation id="1463985642028688653">blockieren</translation>
 <translation id="1715941336038158809">Ungültiger Nutzername oder ungültiges Passwort</translation>
@@ -3731,6 +3734,7 @@
 <translation id="6658571109205370715">Zertifikatstransparenz</translation>
 <translation id="8050038245906040378">Kommerzielle Microsoft-Codesignatur</translation>
 <translation id="7299721129597238157">Lesezeichen löschen</translation>
+<translation id="7166627725100067582">Aktiviert die experimentelle Chromecast-Unterstützung, die das Abspielen und Steuern von Webvideos auf Chromecast-Geräten ermöglicht.</translation>
 <translation id="3031557471081358569">Zu importierende Daten wählen:</translation>
 <translation id="1368832886055348810">Rechtsläufig</translation>
 <translation id="834106456999819211">Ihre Bestellung wird bearbeitet.</translation>
@@ -4983,7 +4987,7 @@
 <translation id="4258348331913189841">Dateisysteme</translation>
 <translation id="3817519158465675771">Netzwerkoptionen...</translation>
 <translation id="4618990963915449444">Alle Dateien auf <ph name="DEVICE_NAME"/> werden gelöscht.</translation>
-<translation id="5011739343823725107">Fehler beim Starten des Synchronisierungs-Backends</translation>
+<translation id="5011739343823725107">Fehler beim Starten des Synchronisierungs-Back-Ends</translation>
 <translation id="8726206820263995930">Fehler beim Übertragen von Richtlinieneinstellungen vom Server: <ph name="CLIENT_ERROR"/>.</translation>
 <translation id="614998064310228828">Gerätemodell:</translation>
 <translation id="8708671767545720562">&amp;Weitere Informationen</translation>
diff --git a/chrome/app/resources/generated_resources_el.xtb b/chrome/app/resources/generated_resources_el.xtb
index 75ed2c7..57708c3 100644
--- a/chrome/app/resources/generated_resources_el.xtb
+++ b/chrome/app/resources/generated_resources_el.xtb
@@ -308,6 +308,7 @@
           Μπορείτε να προσπαθήσετε να κάνετε διάγνωση του προβλήματος, ακολουθώντας τα παρακάτω βήματα::
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Ενεργοποίηση των API OS X AVFoundation, αντί του QTKit.</translation>
 <translation id="6317369057005134371">Αναμονή για το παράθυρο της εφαρμογής…</translation>
 <translation id="6391832066170725637">Δεν ήταν δυνατή η εύρεση του αρχείου ή του καταλόγου.</translation>
 <translation id="7393381084163773901">Οδός</translation>
@@ -849,10 +850,10 @@
     <ph name="BEGIN_BOLD"/>επιτρέπετε ή να απαγορεύετε την πρόσβαση<ph name="END_BOLD"/> σε συγκεκριμένους ιστότοπους, να
     <ph name="BEGIN_BOLD"/>ελέγχετε<ph name="END_BOLD"/> τους ιστότοπους που επισκέφτηκε ένας εποπτευόμενος χρήστης και να
     <ph name="BEGIN_BOLD"/>διαχειρίζεστε<ph name="END_BOLD"/> άλλες ρυθμίσεις.</translation>
-<translation id="1513184107918394878">Ενεργοποίηση παράλληλης λειτουργίας πολλών προφίλ, κατά την οποία όλα τα παράθυρα προγραμμάτων περιήγησης και εφαρμογών μοιράζονται το ίδιο χώρο εργασίας.</translation>
+<translation id="1513184107918394878">Ενεργοποίηση παράλληλης λειτουργίας πολλών προφίλ, κατά την οποία όλα τα παράθυρα προγραμμάτων περιήγησης και εφαρμογών μοιράζονται τον ίδιο χώρο εργασίας.</translation>
 <translation id="733982989083769113">Λήξη περιόδου σύνδεσης επισκέπτη</translation>
 <translation id="6828153365543658583">Περιορισμός σύνδεσης στους ακόλουθους χρήστες:</translation>
-<translation id="8106045200081704138">Σε κοινή χρήση με εμένα</translation>
+<translation id="8106045200081704138">Κοινόχρηστο με εμένα</translation>
 <translation id="1652965563555864525">&amp;Σίγαση</translation>
 <translation id="4200983522494130825">Νέα &amp;καρτέλα</translation>
 <translation id="7979036127916589816">Σφάλμα Συγχρονισμού</translation>
@@ -1301,6 +1302,7 @@
 <translation id="8442065444327205563">Το έγγραφό σας είναι έτοιμο.</translation>
 <translation id="236141728043665931">Να μην επιτρέπται ποτέ η πρόσβαση στο μικρόφωνο</translation>
 <translation id="2307462900900812319">Διαμόρφωση δικτύου</translation>
+<translation id="1704385717926547822">Ενεργοποίηση πειραματικής υποστήριξης Chromecast</translation>
 <translation id="5911798608827489036">Ανταλλαγή δεδομένων με οποιονδήποτε υπολογιστή στο τοπικό δίκτυο ή το Διαδίκτυο</translation>
 <translation id="220858061631308971">Εισαγάγετε αυτόν τον κωδικό PIN στη συσκευή &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Microsoft CA Version</translation>
@@ -2911,6 +2913,7 @@
 <translation id="8670869118777164560">Αυτή η επέκταση απέτυχε να ανακατευθύνει κάποιο αίτημα δικτύου στο <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> επειδή κάποια άλλη επέκταση (<ph name="EXTENSION_NAME"/>) το ανακατεύθυνε στο <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Σφάλμα συγχρονισμού: Το <ph name="PRODUCT_NAME"/> πρέπει να ενημερωθεί.</translation>
 <translation id="790040513076446191">Διαχείριση ρυθμίσεων σχετικά με το απόρρητο</translation>
+<translation id="7260002739296185724">Ενεργοποίηση χρήσης AVFoundation για λήψη βίντεο και παρακολούθηση συσκευής βίντεο σε OS X &gt;= 10.7. Σε διαφορετική περίπτωση θα χρησιμοποιηθεί το QTKit.</translation>
 <translation id="3116361045094675131">Πληκτρολόγιο με αγγλικούς χαρακτήρες (ΗΒ)</translation>
 <translation id="1463985642028688653">αποκλεισμός</translation>
 <translation id="1715941336038158809">Μη έγκυρο όνομα χρήση ή κωδικός πρόσβασης.</translation>
@@ -3477,7 +3480,7 @@
 <translation id="8978526688207379569">Αυτός ο ιστότοπος κατέβασε αυτόματα πολλά αρχεία.</translation>
 <translation id="5959471481388474538">Το δίκτυο δεν είναι διαθέσιμο</translation>
 <translation id="4871308555310586478">Όχι από το Chrome Web Store.</translation>
-<translation id="3578594933904494462">Γίνεται κοινή χρήση του περιεχομένου αυτής της ετικέτας.</translation>
+<translation id="3578594933904494462">Το περιεχόμενο αυτής της ετικέτας είναι κοινόχρηστο.</translation>
 <translation id="295942452804818007">Εμφάνιση μενού κατάστασης</translation>
 <translation id="8051961636969466900">Μπορείτε να βοηθήσετε να γίνει το Chrome πιο ασφαλές και εύχρηστο αποστέλλοντας ύποπτα αρχεία λήψης στη Google.</translation>
 <translation id="3831099738707437457">&amp;Απόκρυψη Πλαισίου Ορθογραφικού Ελέγχου</translation>
@@ -3771,6 +3774,7 @@
 <translation id="6658571109205370715">Πιστοποιητικό διαφάνειας</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">Διαγραφή σελιδοδείκτη</translation>
+<translation id="7166627725100067582">Ενεργοποίηση πειραματικής υποστήριξης Chromecast που επιτρέπει την αναπαραγωγή και τον έλεγχο βίντεο από τον ιστό σε συσκευές Chromecast.</translation>
 <translation id="3031557471081358569">Επιλογή στοιχείων για εισαγωγή:</translation>
 <translation id="1368832886055348810">Από αριστερά προς τα δεξιά</translation>
 <translation id="834106456999819211">Η παραγγελία σας υποβάλλεται σε επεξεργασία</translation>
@@ -4159,7 +4163,7 @@
 <translation id="6361850914223837199">Λεπτομέρειες σφάλματος:</translation>
 <translation id="7187948801578913257">H συμπιεσμένη εφαρμογή και το ιδιωτικό κλειδί θα εγγραφούν στο γονικό κατάλογο του καταλόγου ρίζας της επέκτασης που θα συμπιεστεί. Για να ενημερώσετε μια εφαρμογή, επιλέξτε το αρχείο ιδιωτικού κλειδιού, για να το χρησιμοποιήσετε ξανά.</translation>
 <translation id="8948393169621400698">Να επιτρέπονται πάντα οι προσθήκες στο <ph name="HOST"/></translation>
-<translation id="6527303717912515753">Κοινή χρήση</translation>
+<translation id="6527303717912515753">Κοινοποίηση</translation>
 <translation id="8731948433915954843">Μετακινεί τη διεύθυνση URL εκτός του κύριου πλαισίου και εμφανίζει το όνομα κεντρικού υπολογιστή στο πλαίσιο πληροφοριών προέλευσης στη γραμμή εργαλείων.</translation>
 <translation id="8211154138148153396">Ειδοποιήσεις για τον εντοπισμό συσκευής στο τοπικό δίκτυο.</translation>
 <translation id="5039512255859636053">$1 TB</translation>
diff --git a/chrome/app/resources/generated_resources_en-GB.xtb b/chrome/app/resources/generated_resources_en-GB.xtb
index c6b8ebe..9e69c47 100644
--- a/chrome/app/resources/generated_resources_en-GB.xtb
+++ b/chrome/app/resources/generated_resources_en-GB.xtb
@@ -308,6 +308,7 @@
           You can try to diagnose the problem by taking the following steps:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Enable use of Mac OS X AVFoundation APIs, instead of QTKit.</translation>
 <translation id="6317369057005134371">Waiting for application window...</translation>
 <translation id="6391832066170725637">The file or directory could not be found.</translation>
 <translation id="7393381084163773901">Street address</translation>
@@ -1305,6 +1306,7 @@
 <translation id="8442065444327205563">Your document is ready to view.</translation>
 <translation id="236141728043665931">Always block microphone access</translation>
 <translation id="2307462900900812319">Configure network</translation>
+<translation id="1704385717926547822">Enable experimental Chromecast support</translation>
 <translation id="5911798608827489036">Exchange data with any computer on the local network or internet</translation>
 <translation id="220858061631308971">Please enter this PIN code on &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Microsoft CA Version</translation>
@@ -2913,6 +2915,7 @@
 <translation id="8670869118777164560">This extension failed to redirect a network request to <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> because another extension (<ph name="EXTENSION_NAME"/>) redirected it to <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Sync Error:  <ph name="PRODUCT_NAME"/> is out of date and needs to be updated.</translation>
 <translation id="790040513076446191">Manipulate privacy-related settings</translation>
+<translation id="7260002739296185724">Enable AVFoundation use for video capture and video device monitoring on OS X &gt;= 10.7. QTKit will be used otherwise.</translation>
 <translation id="3116361045094675131">UK keyboard</translation>
 <translation id="1463985642028688653">block</translation>
 <translation id="1715941336038158809">Invalid user name or password.</translation>
@@ -3774,6 +3777,7 @@
 <translation id="6658571109205370715">Certificate transparency</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">Delete bookmark</translation>
+<translation id="7166627725100067582">Enable experimental Chromecast support allowing for play and control of videos from the Web on Chromecast devices.</translation>
 <translation id="3031557471081358569">Select items to be imported:</translation>
 <translation id="1368832886055348810">Left to Right</translation>
 <translation id="834106456999819211">Your order is being processed</translation>
diff --git a/chrome/app/resources/generated_resources_es-419.xtb b/chrome/app/resources/generated_resources_es-419.xtb
index 17d4564..33d19a8 100644
--- a/chrome/app/resources/generated_resources_es-419.xtb
+++ b/chrome/app/resources/generated_resources_es-419.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Solicitar sitio para tablet</translation>
 <translation id="8028060951694135607">Recuperación de claves de Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Puedes tratar de diagnosticar el problema siguiendo estos pasos: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Habilitar el uso de las API de AVFoundation para Mac OS X en lugar de QTKit</translation>
 <translation id="6317369057005134371">Esperando ventana de la aplicación…</translation>
 <translation id="6391832066170725637">No se ha podido encontrar el archivo o el directorio.</translation>
 <translation id="7393381084163773901">Dirección</translation>
@@ -1291,6 +1292,7 @@
 <translation id="8442065444327205563">Documento listo para ver</translation>
 <translation id="236141728043665931">Bloquear siempre el acceso al micrófono</translation>
 <translation id="2307462900900812319">Configurar red</translation>
+<translation id="1704385717926547822">Habilitar compatibilidad de Chromecast experimental</translation>
 <translation id="5911798608827489036">Intercambiar datos con cualquier computadora en la red local o en internet</translation>
 <translation id="220858061631308971">Ingresa este código PIN en &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Versión de entidad de certificación de Microsoft</translation>
@@ -2895,6 +2897,7 @@
 <translation id="8670869118777164560">Esta extensión no pudo redireccionar una solicitud de red a <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> porque otra extensión (<ph name="EXTENSION_NAME"/>) la redireccionó a <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Error de sincronización: <ph name="PRODUCT_NAME"/> caducó y necesita que lo actualices.</translation>
 <translation id="790040513076446191">Manipular la configuración relacionada con la privacidad</translation>
+<translation id="7260002739296185724">Permite habilitar el uso de AVFoundation para capturar videos y supervisar dispositivos de video en OS X &gt;= 10.7. De lo contrario, se utilizará QTKit.</translation>
 <translation id="3116361045094675131">Teclado en inglés del Reino Unido</translation>
 <translation id="1463985642028688653">bloquear</translation>
 <translation id="1715941336038158809">Nombre de usuario o contraseña no válidos</translation>
@@ -3750,6 +3753,7 @@
 <translation id="6658571109205370715">Transparencia en certificados</translation>
 <translation id="8050038245906040378">Firma de código comercial de Microsoft</translation>
 <translation id="7299721129597238157">Eliminar marcador</translation>
+<translation id="7166627725100067582">Permite habilitar la compatibilidad de Chromecast experimental para reproducir y controlar videos de la Web en dispositivos Chromecast.</translation>
 <translation id="3031557471081358569">Selecciona elementos para importar:</translation>
 <translation id="1368832886055348810">De izquierda a derecha</translation>
 <translation id="834106456999819211">Procesando el pedido</translation>
diff --git a/chrome/app/resources/generated_resources_es.xtb b/chrome/app/resources/generated_resources_es.xtb
index f5f2418..704116d 100644
--- a/chrome/app/resources/generated_resources_es.xtb
+++ b/chrome/app/resources/generated_resources_es.xtb
@@ -310,6 +310,7 @@
           Puedes intentar realizar un diagnóstico del problema siguiendo estos pasos:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Habilitar el uso de las API de AV Foundation de Mac OS X en lugar de utilizar QTKit.</translation>
 <translation id="6317369057005134371">Esperando ventana de la aplicación...</translation>
 <translation id="6391832066170725637">No se ha podido encontrar el archivo o el directorio.</translation>
 <translation id="7393381084163773901">Dirección postal</translation>
@@ -1301,6 +1302,7 @@
 <translation id="8442065444327205563">Ya puedes ver el documento.</translation>
 <translation id="236141728043665931">Bloquear siempre el acceso al micrófono</translation>
 <translation id="2307462900900812319">Configurar red</translation>
+<translation id="1704385717926547822">Habilitar compatibilidad con Chromecast experimental</translation>
 <translation id="5911798608827489036">Intercambiar datos con otro ordenador de la red local o de Internet</translation>
 <translation id="220858061631308971">Introduce este código PIN en &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Versión de entidad emisora de certificados de Microsoft</translation>
@@ -2906,6 +2908,7 @@
 <translation id="8670869118777164560">Esta extensión no ha podido redireccionar una solicitud de red a <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> porque otra extensión (<ph name="EXTENSION_NAME"/>) la ha redireccionado a <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Error de sincronización: <ph name="PRODUCT_NAME"/> está obsoleto y debe actualizarse.</translation>
 <translation id="790040513076446191">Modificar la configuración relacionada con la privacidad</translation>
+<translation id="7260002739296185724">Habilita el uso de AV Foundation para capturar ví­deos y controlar dispositivos de vídeo en OS X 10.7 y versiones posteriores. De lo contrario, se utiliza QTKit.</translation>
 <translation id="3116361045094675131">Teclado del Reino Unido</translation>
 <translation id="1463985642028688653">bloquear</translation>
 <translation id="1715941336038158809">El nombre de usuario o la contraseña no son válidos.</translation>
@@ -3765,6 +3768,7 @@
 <translation id="6658571109205370715">Transparencia de certificados</translation>
 <translation id="8050038245906040378">Firma de código comercial de Microsoft</translation>
 <translation id="7299721129597238157">Eliminar marcador</translation>
+<translation id="7166627725100067582">Habilita la compatibilidad con Chromecast experimental para poder reproducir y controlar vídeos de la Web en dispositivos Chromecast.</translation>
 <translation id="3031557471081358569">Selecciona elementos para importar:</translation>
 <translation id="1368832886055348810">De izquierda a derecha</translation>
 <translation id="834106456999819211">El pedido se está procesando</translation>
@@ -5328,7 +5332,7 @@
 <translation id="534749176369872155"><ph name="SITE"/> ha proporcionado a Chrome una lista de credenciales de certificados con aprobación previa, pero Chrome no ha recibido ninguna de esas credenciales durante este intento de conexión, lo que indica que un atacante está intentando suplantar la identidad de <ph name="SITE"/>.</translation>
 <translation id="992543612453727859">Añadir frases al principio</translation>
 <translation id="4728558894243024398">Plataforma</translation>
-<translation id="7127980134843952133">Descargar historial</translation>
+<translation id="7127980134843952133">Historial de descargas</translation>
 <translation id="4998873842614926205">Confirmar cambios</translation>
 <translation id="6596325263575161958">Opciones de encriptación</translation>
 <translation id="5037888205580811046">Permite habilitar una interfaz de usuario interactiva de la opción Autocompletar que se puede invocar ejecutando la función HTMLFormElement#requestAutocomplete.</translation>
diff --git a/chrome/app/resources/generated_resources_et.xtb b/chrome/app/resources/generated_resources_et.xtb
index 8835629..1a17414 100644
--- a/chrome/app/resources/generated_resources_et.xtb
+++ b/chrome/app/resources/generated_resources_et.xtb
@@ -305,6 +305,7 @@
 <translation id="8028060951694135607">Microsofti võtme taastamine</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Võite proovida probleemi diagnoosida järgmiste sammude abil:
 <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Luba QTKiti asemel kasutada Mac OS X AVFoundationi API-sid.</translation>
 <translation id="6317369057005134371">Rakenduse akna ootamine ...</translation>
 <translation id="6391832066170725637">Faili või kataloogi ei leitud.</translation>
 <translation id="7393381084163773901">Aadress</translation>
@@ -1304,6 +1305,7 @@
 <translation id="8442065444327205563">Dokument on kuvamiseks valmis.</translation>
 <translation id="236141728043665931">Blokeeri alati juurdepääs mikrofonile</translation>
 <translation id="2307462900900812319">Seadista võrk</translation>
+<translation id="1704385717926547822">Luba katseline Chromecasti tugi</translation>
 <translation id="5911798608827489036">Vaheta andmeid mis tahes arvutiga kohalikus võrgus või Internetis</translation>
 <translation id="220858061631308971">Sisestage seadmes „<ph name="DEVICE_NAME"/>” see PIN-kood:</translation>
 <translation id="6263082573641595914">Microsofti CA versioon</translation>
@@ -2907,6 +2909,7 @@
 <translation id="8670869118777164560">Laiendusel ei õnnestunud võrgutaotlust ümber suunata asukohta <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, kuna teine laiendus (<ph name="EXTENSION_NAME"/>) suunas selle asukohta <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Sünkroonimisviga: <ph name="PRODUCT_NAME"/> on aegunud ja vajab värskendamist.</translation>
 <translation id="790040513076446191">Privaatsusega seotud seadete muutmine</translation>
+<translation id="7260002739296185724">Lubab AVFoundationi kasutamise videohõiveks ja videoseadme jälgimiseks operatsioonisüsteemi OS X versiooni 10.7 või vanemate versioonide puhul. Muidu kasutatakse QTKit-i.</translation>
 <translation id="3116361045094675131">Ühendkuningriigi klaviatuur</translation>
 <translation id="1463985642028688653">blokeeri</translation>
 <translation id="1715941336038158809">Kehtetu kasutaja nimi või parool.</translation>
@@ -3767,6 +3770,7 @@
 <translation id="6658571109205370715">Sertifikaadi läbipaistvus</translation>
 <translation id="8050038245906040378">Microsofti äriline koodsigneerimine</translation>
 <translation id="7299721129597238157">Kustuta järjehoidja</translation>
+<translation id="7166627725100067582">Lubab katselise Chromecasti toe, mis lubab esitada ja juhtida veebivideoid Chromecasti seadmetes.</translation>
 <translation id="3031557471081358569">Vali importimiseks üksused:</translation>
 <translation id="1368832886055348810">Left to Right (Vasakult paremale)</translation>
 <translation id="834106456999819211">Teie tellimust töödeldakse</translation>
diff --git a/chrome/app/resources/generated_resources_fa.xtb b/chrome/app/resources/generated_resources_fa.xtb
index a0ff8e8..8fba876 100644
--- a/chrome/app/resources/generated_resources_fa.xtb
+++ b/chrome/app/resources/generated_resources_fa.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">درخواست سایت رایانه لوحی</translation>
 <translation id="8028060951694135607">‏بازیابی کلید Microsot</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> با انجام مراحل زیر می‌توانید سعی کنید مشکل را تشخیص دهید: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">‏استفاده از APIهای Mac OS X AVFoundation را به جای QTKit فعال کنید.</translation>
 <translation id="6317369057005134371">در انتظار پنجره برنامه ...</translation>
 <translation id="6391832066170725637">فایل یا دایرکتوری یافت نشد.</translation>
 <translation id="7393381084163773901">آدرس خیابان</translation>
@@ -1290,6 +1291,7 @@
 <translation id="8442065444327205563">سند شما آماده مشاهده است.</translation>
 <translation id="236141728043665931">دسترسی به میکروفون همیشه مسدود شود</translation>
 <translation id="2307462900900812319">پیکربندی شبکه</translation>
+<translation id="1704385717926547822">‏فعال کردن پشتیبانی آزمایشی Chromecast</translation>
 <translation id="5911798608827489036">تبادل اطلاعات با هر رایانه‌ای بر روی شبکه محلی یا اینترنت</translation>
 <translation id="220858061631308971">لطفاً این کد پین را در &quot;<ph name="DEVICE_NAME"/>&quot; وارد کنید:</translation>
 <translation id="6263082573641595914">‏نسخه CA Microsoft</translation>
@@ -2895,6 +2897,7 @@
 <translation id="8670869118777164560">این فایل افزودنی نتوانست درخواست شبکه را به <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> مجدداً هدایت کند چون فایل افزودنی دیگری (<ph name="EXTENSION_NAME"/>) آن را به <ph name="ACTUAL_REDIRECT_DESTINATION"/> مجدداً هدایت کرد.</translation>
 <translation id="3654092442379740616">خطای همگام‌سازی: <ph name="PRODUCT_NAME"/> به‌روز نیست و باید به‌روز شود.</translation>
 <translation id="790040513076446191">دستکاری تنظیمات مربوط به حریم خصوصی</translation>
+<translation id="7260002739296185724">‏استفاده از AVFoundation را برای ضبط ویدیو فعال کنید تا کنترل دستگاه ویدیو در OS X &gt;= 10.7. در غیر این صورت QTKit استفاده شود.</translation>
 <translation id="3116361045094675131">صفحه‌کلید انگلیسی</translation>
 <translation id="1463985642028688653">مسدود کردن</translation>
 <translation id="1715941336038158809">نام کاربری یا رمز ورود نامعتبر است.</translation>
@@ -3750,6 +3753,7 @@
 <translation id="6658571109205370715">شفافیت گواهینامه</translation>
 <translation id="8050038245906040378">‏امضای کد تجاری Microsoft</translation>
 <translation id="7299721129597238157">حذف نشانک</translation>
+<translation id="7166627725100067582">‏پشتیبانی آزمایشی Chromecast را فعال کنید که امکان پخش و کنترل ویدیوهای وب را در دستگاه‌های Chromecast فراهم می‌کند.</translation>
 <translation id="3031557471081358569">آیتم هایی را برای وارد کردن انتخاب کنید:</translation>
 <translation id="1368832886055348810">چپ به راست</translation>
 <translation id="834106456999819211">سفارش شما درحال پردازش است</translation>
diff --git a/chrome/app/resources/generated_resources_fi.xtb b/chrome/app/resources/generated_resources_fi.xtb
index 3b3cdd8..96b96a7 100644
--- a/chrome/app/resources/generated_resources_fi.xtb
+++ b/chrome/app/resources/generated_resources_fi.xtb
@@ -303,6 +303,7 @@
 <translation id="7607274158153386860">Pyydä tablet-laitteelle sopiva sivusto</translation>
 <translation id="8028060951694135607">Microsoftin avaimen palautus</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Voit yrittää diagnosoida ongelman toimimalla seuraavasti: <ph name="LINE_BREAK"/><ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Käytä Mac OS X:n AVFoundation-sovellusliittymiä QTKitin sijaan.</translation>
 <translation id="6317369057005134371">Odotetaan sovellusikkunaa…</translation>
 <translation id="6391832066170725637">Tiedostoa tai hakemistoa ei löytynyt.</translation>
 <translation id="7393381084163773901">Katuosoite</translation>
@@ -1290,6 +1291,7 @@
 <translation id="8442065444327205563">Asiakirja on valmis tarkast.</translation>
 <translation id="236141728043665931">Estä aina mikrofonin käyttö</translation>
 <translation id="2307462900900812319">Määritä verkko</translation>
+<translation id="1704385717926547822">Ota kokeellinen Chromecast-tuki käyttöön</translation>
 <translation id="5911798608827489036">Vaihda tietoja minkä tahansa paikallisverkossa tai internetissä olevan tietokoneen kanssa</translation>
 <translation id="220858061631308971">Syötä tämä PIN-koodi laitteella <ph name="DEVICE_NAME"/>:</translation>
 <translation id="6263082573641595914">Microsoftin varmenteen myöntäjän versio</translation>
@@ -2875,6 +2877,7 @@
 <translation id="8670869118777164560">Tämä laajennus ei uudelleenohjannut verkkopyyntöä kohteeseen <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, koska toinen laajennus (<ph name="EXTENSION_NAME"/>) uudelleenohjasi sen kohteeseen <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Synkronointivirhe: <ph name="PRODUCT_NAME"/> on vanhentunut ja tulee päivittää.</translation>
 <translation id="790040513076446191">Muokata tietosuojaan liittyviä asetuksia</translation>
+<translation id="7260002739296185724">Käytä AVFoundationia videon kaappaukseen ja videolaitteiden hallintaan OS X -versiota 10.7 uudemmissa käyttöjärjestelmissä. QTKit-sovelluskehystä käytetään muissa tapauksissa.</translation>
 <translation id="3116361045094675131">Näppäimistö: UK</translation>
 <translation id="1463985642028688653">estä</translation>
 <translation id="1715941336038158809">Virheellinen käyttäjänimi tai salasana.</translation>
@@ -3731,6 +3734,7 @@
 <translation id="6658571109205370715">Varmenteen avoimuus</translation>
 <translation id="8050038245906040378">Microsoftin kaupallinen koodin allekirjoitus</translation>
 <translation id="7299721129597238157">Poista kirjanmerkki</translation>
+<translation id="7166627725100067582">Ota käyttöön kokeellinen Chromecast-tuki, joka mahdollistaa verkkovideoiden toistamisen ja hallinnan Chromecast-laitteilla.</translation>
 <translation id="3031557471081358569">Valitse tuotavat kohteet:</translation>
 <translation id="1368832886055348810">Vasemmalta oikealle</translation>
 <translation id="834106456999819211">Tilaustasi käsitellään</translation>
diff --git a/chrome/app/resources/generated_resources_fil.xtb b/chrome/app/resources/generated_resources_fil.xtb
index fc01387..43060d8 100644
--- a/chrome/app/resources/generated_resources_fil.xtb
+++ b/chrome/app/resources/generated_resources_fil.xtb
@@ -308,6 +308,7 @@
           Maaari mong subukang i-diagnose ang problema sa pamamagitan ng pagsasagawa ng sumusunod na mga hakbang:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">I-enable ang paggamit ng mga Mac OS X AVFoundation API, sa halip ng QTKit.</translation>
 <translation id="6317369057005134371">Hinihintay ang application window...</translation>
 <translation id="6391832066170725637">Ang file o direktoryo ay hindi mahanap.</translation>
 <translation id="7393381084163773901">Address ng kalye</translation>
@@ -1305,6 +1306,7 @@
 <translation id="8442065444327205563">Handa tingnan dokumento mo.</translation>
 <translation id="236141728043665931">Palaging i-block ang pag-access sa mikropono</translation>
 <translation id="2307462900900812319">I-configure ang network</translation>
+<translation id="1704385717926547822">I-enable ang pang-eksperimentong suporta sa Chromecast</translation>
 <translation id="5911798608827489036">Makipagpalitan ng data sa anumang computer sa lokal na network o internet</translation>
 <translation id="220858061631308971">Pakilagay ang PIN code na ito sa &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Microsoft CA Version</translation>
@@ -2921,6 +2923,7 @@
 <translation id="8670869118777164560">Nabigo ang extension na ito na mag-redirect ng kahilingan sa network sa <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> dahil may isa pang extension (<ph name="EXTENSION_NAME"/>) na nag-redirect nito sa <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Error sa Pag-sync:  Ang <ph name="PRODUCT_NAME"/> ay hindi na napapanahon at kinakailangang ma-update.</translation>
 <translation id="790040513076446191">Manipulahin ang mga setting kaugnay ng privacy</translation>
+<translation id="7260002739296185724">I-enable ang paggamit ng AV Foundation para sa pag-capture ng video at pagsubaybay sa video device sa OS X &gt;= 10.7. Sa halip ay gagamitin ang QTKit.</translation>
 <translation id="3116361045094675131">UK keyboard</translation>
 <translation id="1463985642028688653">i-block</translation>
 <translation id="1715941336038158809">Hindi wastong user name o password.</translation>
@@ -3782,6 +3785,7 @@
 <translation id="6658571109205370715">Certificate ng transparency</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">Tanggalin ang bookmark</translation>
+<translation id="7166627725100067582">I-enable ang pang-eksperimentong suporta sa Chromecast na pumapayag na i-play at kontrolin ang mga video mula sa Web sa mga Chromecast device.</translation>
 <translation id="3031557471081358569">Pumili ng mga item upang ma-import:</translation>
 <translation id="1368832886055348810">Kaliwa papuntang Kanan</translation>
 <translation id="834106456999819211">Pinoproseso ang iyong order</translation>
diff --git a/chrome/app/resources/generated_resources_fr.xtb b/chrome/app/resources/generated_resources_fr.xtb
index 99f8edb..14ac269 100644
--- a/chrome/app/resources/generated_resources_fr.xtb
+++ b/chrome/app/resources/generated_resources_fr.xtb
@@ -308,6 +308,7 @@
           Pour tenter de diagnostiquer le problème, procédez de la manière suivante :
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Activer l'utilisation des API Mac OS X AVFoundation, au lieu du framework QTKit</translation>
 <translation id="6317369057005134371">Création de la fenêtre de l'application en cours…</translation>
 <translation id="6391832066170725637">Fichier ou répertoire introuvable</translation>
 <translation id="7393381084163773901">Adresse postale</translation>
@@ -1302,6 +1303,7 @@
 <translation id="8442065444327205563">Votre document est disponible.</translation>
 <translation id="236141728043665931">Toujours bloquer l'accès au micro</translation>
 <translation id="2307462900900812319">Configurer le réseau</translation>
+<translation id="1704385717926547822">Activer la compatibilité expérimentale de Chromecast</translation>
 <translation id="5911798608827489036">Échanger des données avec tout ordinateur sur le réseau local ou sur Internet</translation>
 <translation id="220858061631308971">Veuillez saisir le code d'accès de &quot;<ph name="DEVICE_NAME"/>&quot; :</translation>
 <translation id="6263082573641595914">Version de l'autorité de certification Microsoft</translation>
@@ -2921,6 +2923,7 @@
 <translation id="8670869118777164560">Une requête réseau n'a pas pu être redirigée vers <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> par cette extension, car elle a été redirigée vers <ph name="ACTUAL_REDIRECT_DESTINATION"/> par une autre extension (<ph name="EXTENSION_NAME"/>).</translation>
 <translation id="3654092442379740616">Erreur de synchronisation. <ph name="PRODUCT_NAME"/> est obsolète et doit être mis à jour.</translation>
 <translation id="790040513076446191">Modifier les paramètres de confidentialité</translation>
+<translation id="7260002739296185724">Activez l'utilisation d'AVFoundation pour la capture vidéo et le contrôle d'appareil vidéo sur OS X 10.7 ou version ultérieure. Dans les autres cas, le framework QTKit sera utilisé.</translation>
 <translation id="3116361045094675131">Clavier britannique</translation>
 <translation id="1463985642028688653">bloquer</translation>
 <translation id="1715941336038158809">Nom d'utilisateur ou mot de passe incorrect</translation>
@@ -3781,6 +3784,7 @@
 <translation id="6658571109205370715">Transparence du certificat</translation>
 <translation id="8050038245906040378">Signature du code commercial Microsoft</translation>
 <translation id="7299721129597238157">Supprimer le favori</translation>
+<translation id="7166627725100067582">Activez la compatibilité expérimentale de Chromecast permettant de lire et de contrôler des vidéos du Web sur des appareils Chromecast.</translation>
 <translation id="3031557471081358569">Sélectionnez les éléments à importer :</translation>
 <translation id="1368832886055348810">De gauche à droite</translation>
 <translation id="834106456999819211">Commande en cours de traitement</translation>
diff --git a/chrome/app/resources/generated_resources_gu.xtb b/chrome/app/resources/generated_resources_gu.xtb
index 0ad98a6..2c8140e 100644
--- a/chrome/app/resources/generated_resources_gu.xtb
+++ b/chrome/app/resources/generated_resources_gu.xtb
@@ -312,6 +312,7 @@
           તમે નીચેનાં પગલાંઓ લઇને સમસ્યાનું નિદાન કરવાનો પ્રયત્ન કરી શકો છો:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit ને બદલે Mac OS X AVFoundation API ના ઉપયોગને સક્ષમ કરો.</translation>
 <translation id="6317369057005134371">એપ્લિકેશન વિન્ડો માટે રાહ જોઇ રહ્યાં છે...</translation>
 <translation id="6391832066170725637">ફાઇલ અથવા ડાયરેક્ટરી શોધી શકાઈ નથી.</translation>
 <translation id="7393381084163773901">શેરીનું સરનામું</translation>
@@ -1312,6 +1313,7 @@
 <translation id="8442065444327205563">આપનો દસ્તાવેજ જોવા માટે તૈયાર છે.</translation>
 <translation id="236141728043665931">માઇક્રોફોનની ઍક્સેસને હંમેશા અવરોધિત કરો</translation>
 <translation id="2307462900900812319">નેટવર્ક ગોઠવો</translation>
+<translation id="1704385717926547822">પ્રાયોગિક Chromecast સમર્થનને સક્ષમ કરો</translation>
 <translation id="5911798608827489036">સ્થાનિક નેટવર્ક અથવા ઇન્ટરનેટ પર કોઈપણ કમ્પ્યુટર સાથે ડેટા વિનિમય કરો</translation>
 <translation id="220858061631308971">કૃપા કરીને &quot;<ph name="DEVICE_NAME"/>&quot; પર આ પિન કોડ દાખલ કરો:</translation>
 <translation id="6263082573641595914">Microsoft CA સંસ્કરણ</translation>
@@ -2925,6 +2927,7 @@
 <translation id="8670869118777164560">આ એક્સટેન્શન એક નેટવર્ક વિનંતીને <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> પર રીડાયરેક્ટ કરવામાં નિષ્ફળ થયું કારણ કે અન્ય એક્સટેન્શન (<ph name="EXTENSION_NAME"/>) એ તેને <ph name="ACTUAL_REDIRECT_DESTINATION"/> પર રીડાયરેક્ટ કર્યું છે.</translation>
 <translation id="3654092442379740616">સમન્વયન ભૂલ: <ph name="PRODUCT_NAME"/> જૂનું છે અને તેને અપડેટ કરવાની જરૂર છે.</translation>
 <translation id="790040513076446191">ગોપનીયતા સંબંધિત સેટિંગ્સનો કૂશળતાપૂર્વક ઉપયોગ કરે છે.</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7 પર વિડિઓ કેપ્ચર અને વિડિઓ ઉપકરણ નિરીક્ષણ માટે AVFoundation ઉપયોગને સક્ષમ કરો. અન્યથા QTKit નો ઉપયોગ કરવામાં આવશે.</translation>
 <translation id="3116361045094675131">યુકે કીબોર્ડ</translation>
 <translation id="1463985642028688653">અવરોધિત કરો</translation>
 <translation id="1715941336038158809">અમાન્ય લૉગિન નામ અથવા પાસવર્ડ.</translation>
@@ -3779,6 +3782,7 @@
 <translation id="6658571109205370715">પ્રમાણપત્ર પારદર્શિતા</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">બુકમાર્ક કાઢી નાખો</translation>
+<translation id="7166627725100067582">Chromecast ઉપકરણો પર વેબથી વિડિઓઝને ચલાવવા અને નિયંત્રિત કરવા માટે મંજૂરી આપવાના પ્રાયોગિક Chromecast સમર્થનને સક્ષમ કરો.</translation>
 <translation id="3031557471081358569">આયાત કરવા માટે આઇટમ્સ પસંદ કરો:</translation>
 <translation id="1368832886055348810">ડાબેથી જમણે</translation>
 <translation id="834106456999819211">તમારા ઓર્ડર પર પ્રક્રિયા કરવામાં આવી રહી છે</translation>
diff --git a/chrome/app/resources/generated_resources_hi.xtb b/chrome/app/resources/generated_resources_hi.xtb
index bf81e42..2cbbecb 100644
--- a/chrome/app/resources/generated_resources_hi.xtb
+++ b/chrome/app/resources/generated_resources_hi.xtb
@@ -311,6 +311,7 @@
           आप निम्न चरणों का पालन करके समस्‍या का निदान करने का प्रयास कर सकते हैं:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit के बजाय Mac OS X AVFoundation API के उपयोग को सक्षम करें.</translation>
 <translation id="6317369057005134371">एप्लिकेशन विंडो की प्रतीक्षा की जा रही है...</translation>
 <translation id="6391832066170725637">फ़ाइल या निर्देशिका मिली.</translation>
 <translation id="7393381084163773901">सड़क का पता</translation>
@@ -1306,6 +1307,7 @@
 <translation id="8442065444327205563">आपका दस्तावेज़ देखे जाने के लिए तैयार है.</translation>
 <translation id="236141728043665931">माइक्रोफ़ोन एक्सेस हमेशा अवरुद्ध करें</translation>
 <translation id="2307462900900812319">नेटवर्क कॉन्फ़िगर करें</translation>
+<translation id="1704385717926547822">प्रयोगात्मक Chromecast समर्थन को सक्षम करें</translation>
 <translation id="5911798608827489036">स्थानीय नेटवर्क या इंटरनेट पर किसी कंप्यूटर से डेटा का आदान-प्रदान करें</translation>
 <translation id="220858061631308971">कृपया इस पिन कोड को &quot;<ph name="DEVICE_NAME"/>&quot; पर दर्ज करें:</translation>
 <translation id="6263082573641595914">Microsoft CA Version</translation>
@@ -2932,6 +2934,7 @@
 <translation id="8670869118777164560">यह एक्सटेंशन <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> तक नेटवर्क अनुरोध को रीडायरेक्ट करने में विफल रहा क्योंकि एक अन्य एक्सटेंशन (<ph name="EXTENSION_NAME"/>) ने इसे <ph name="ACTUAL_REDIRECT_DESTINATION"/> को रीडायरेक्ट कर दिया था.</translation>
 <translation id="3654092442379740616">समन्‍वयन त्रुटि:  <ph name="PRODUCT_NAME"/> पुराना है और इसे अपडेट करने की आवश्‍यकता है.</translation>
 <translation id="790040513076446191">गोपनीयता-संबंधी सेटिंग में हेरफेर करें</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7 पर वीडियो कैप्चर करने और वीडियो उपकरण को मॉनिटर करने के लिए AVFoundation के उपयोग को सक्षम करें. अन्यथा QTKit का उपयोग किया जाएगा.</translation>
 <translation id="3116361045094675131">यूके कीबोर्ड</translation>
 <translation id="1463985642028688653">अवरोधित करें</translation>
 <translation id="1715941336038158809">अमान्य उपयोगकर्ता नाम या पासवर्ड.</translation>
@@ -3793,6 +3796,7 @@
 <translation id="6658571109205370715">प्रमाणपत्र पारदर्शिता</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">बुकमार्क हटाएं</translation>
+<translation id="7166627725100067582">Chromecast उपकरणों पर वेब से वीडियो चलाने और नियंत्रित करने देने के लिए प्रयोगात्मक Chromecast सहायता सक्षम करें.</translation>
 <translation id="3031557471081358569">आयात करने के लिए आइटम को चुनें:</translation>
 <translation id="1368832886055348810">बाएं से दाएं</translation>
 <translation id="834106456999819211">आपका आदेश प्रोसेस किया जा रहा है</translation>
diff --git a/chrome/app/resources/generated_resources_hr.xtb b/chrome/app/resources/generated_resources_hr.xtb
index 8b2019c..4b1def6 100644
--- a/chrome/app/resources/generated_resources_hr.xtb
+++ b/chrome/app/resources/generated_resources_hr.xtb
@@ -303,6 +303,7 @@
 <translation id="7607274158153386860">Zahtjev za web-lokaciju tabletnog računala</translation>
 <translation id="8028060951694135607">Oporavak Microsoftovog ključa</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Možete pokušati dijagnosticirati problem na sljedeći način: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Omogući upotrebu Mac OS X AVFoundation API-ja umjesto QTKita.</translation>
 <translation id="6317369057005134371">Čeka se prozor aplikacije...</translation>
 <translation id="6391832066170725637">Datoteku ili direktorij nije bilo moguće naći.</translation>
 <translation id="7393381084163773901">Ulica i kućni broj</translation>
@@ -1285,6 +1286,7 @@
 <translation id="8442065444327205563">Dokument je spreman za prikaz.</translation>
 <translation id="236141728043665931">Uvijek blokiraj pristup mikrofonu</translation>
 <translation id="2307462900900812319">Konfiguriraj mrežu</translation>
+<translation id="1704385717926547822">Omogući eksperimentalnu podršku za Chromecast</translation>
 <translation id="5911798608827489036">Razmjena podataka s bilo kojim računalom na lokalnoj mreži ili internetu</translation>
 <translation id="220858061631308971">Unesite ovaj PIN kôd na uređaj &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Microsoft CA verzija</translation>
@@ -2884,6 +2886,7 @@
 <translation id="8670869118777164560">Ovo proširenje nije uspjelo preusmjeriti mrežni zahtjev na odredište <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> jer ga je drugo proširenje (<ph name="EXTENSION_NAME"/>) preusmjerilo na odredište <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Pogreška u sinkronizaciji: proizvod <ph name="PRODUCT_NAME"/> zastario je i treba ga ažurirati.</translation>
 <translation id="790040513076446191">rukovati postavkama koje se odnose na privatnost</translation>
+<translation id="7260002739296185724">Omogući upotrebu AVFoundationa za snimanje videozapisa i nadzor videouređaja na OS-u X 10.7 i novijim verzijama. U suprotnom će se upotrebljavati QTKit.</translation>
 <translation id="3116361045094675131">UK tipkovnica</translation>
 <translation id="1463985642028688653">blokiraj</translation>
 <translation id="1715941336038158809">Nevažeće korisničko ime ili zaporka.</translation>
@@ -3740,6 +3743,7 @@
 <translation id="6658571109205370715">Transparentnost certifikata</translation>
 <translation id="8050038245906040378">Microsoftovo komercijalno kodno potpisivanje</translation>
 <translation id="7299721129597238157">Izbriši oznaku</translation>
+<translation id="7166627725100067582">Omogući eksperimentalnu podršku za Chromecast koja omogućuje reprodukciju i kontrolu videozapisa s weba na uređajima Chromecast.</translation>
 <translation id="3031557471081358569">Odaberi stavke za uvoz:</translation>
 <translation id="1368832886055348810">Slijeva udesno</translation>
 <translation id="834106456999819211">Vaša se narudžba obrađuje</translation>
diff --git a/chrome/app/resources/generated_resources_hu.xtb b/chrome/app/resources/generated_resources_hu.xtb
index 3634f5b..6f561d4 100644
--- a/chrome/app/resources/generated_resources_hu.xtb
+++ b/chrome/app/resources/generated_resources_hu.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Táblagépre optimalizált webhely kérése</translation>
 <translation id="8028060951694135607">Microsoft kulcshelyreállító</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/><ph name="LINE_BREAK"/> Megpróbálhatja diagnosztizálni a problémát a következő lépések követésével: <ph name="LINE_BREAK"/><ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">A Mac OS X AVFoundation API-k használatának engedélyezése a QTKit helyett.</translation>
 <translation id="6317369057005134371">Várakozás az alkalmazás ablakára...</translation>
 <translation id="6391832066170725637">A fájlt vagy könyvtárat nem sikerült megtalálni.</translation>
 <translation id="7393381084163773901">Cím</translation>
@@ -1290,6 +1291,7 @@
 <translation id="8442065444327205563">A dokumentum készen áll a megtekintésre.</translation>
 <translation id="236141728043665931">Mikrofon elérésének állandó tiltása</translation>
 <translation id="2307462900900812319">Hálózat beállítása</translation>
+<translation id="1704385717926547822">Kísérleti Chromecast-támogatás engedélyezése</translation>
 <translation id="5911798608827489036">Adatok cseréje bármilyen számítógéppel a helyi hálózaton vagy az interneten</translation>
 <translation id="220858061631308971">Kérjük, adja meg a PIN kódot a(z) &quot;<ph name="DEVICE_NAME"/>&quot; eszközhöz:</translation>
 <translation id="6263082573641595914">Microsoft CA verzió</translation>
@@ -2890,6 +2892,7 @@
 <translation id="8670869118777164560">A bővítmény nem tudta átirányítani a hálózati kérést <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> felé, mivel egy másik bővítmény (<ph name="EXTENSION_NAME"/>) átirányította azt a következőre: <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Szinkronizálási hiba: A <ph name="PRODUCT_NAME"/> elavult, így frissítése szükséges.</translation>
 <translation id="790040513076446191">Adatvédelemmel kapcsolatos beállítások módosítása</translation>
+<translation id="7260002739296185724">Az AVFoundation használatának engedélyezése a videorögzítéshez és a videoeszköz felügyeletéhez a legalább 10.7-es verziószámú OS X esetében. Egyéb esetben a rendszer a QTKitet használja.</translation>
 <translation id="3116361045094675131">Brit billentyűzet</translation>
 <translation id="1463985642028688653">letiltás</translation>
 <translation id="1715941336038158809">Érvénytelen felhasználónév vagy jelszó.</translation>
@@ -3745,6 +3748,7 @@
 <translation id="6658571109205370715">Tanúsítvány átláthatósága</translation>
 <translation id="8050038245906040378">Microsoft kereskedelmi kódaláírás</translation>
 <translation id="7299721129597238157">Könyvjelző törlése</translation>
+<translation id="7166627725100067582">Az internetes videók Chromecast-eszközökön való lejátszását és lejátszásának szabályozását lehetővé tevő kísérleti Chromecast-támogatás engedélyezése.</translation>
 <translation id="3031557471081358569">Válassza ki az importálandó elemeket:</translation>
 <translation id="1368832886055348810">Balról jobbra</translation>
 <translation id="834106456999819211">Megrendelésének feldolgozása folyamatban van</translation>
diff --git a/chrome/app/resources/generated_resources_id.xtb b/chrome/app/resources/generated_resources_id.xtb
index f38b53e..391264f 100644
--- a/chrome/app/resources/generated_resources_id.xtb
+++ b/chrome/app/resources/generated_resources_id.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Minta situs tablet</translation>
 <translation id="8028060951694135607">Microsoft Key Recovery</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Anda dapat mencoba  mendiagnosis masalah dengan mengambil langkah-langkah berikut: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Aktifkan penggunaan API AVFoundation Mac OS X, sebagai ganti QTKit.</translation>
 <translation id="6317369057005134371">Menunggu jendela aplikasi...</translation>
 <translation id="6391832066170725637">File atau direktori tak ditemukan.</translation>
 <translation id="7393381084163773901">Alamat</translation>
@@ -1292,6 +1293,7 @@
 <translation id="8442065444327205563">Dokumen Anda siap dilihat.</translation>
 <translation id="236141728043665931">Selalu blokir akses mikrofon</translation>
 <translation id="2307462900900812319">Konfigurasi jaringan</translation>
+<translation id="1704385717926547822">Aktifkan dukungan Chromecast eksperimental</translation>
 <translation id="5911798608827489036">Tukar data dengan komputer mana saja di jaringan lokal atau internet</translation>
 <translation id="220858061631308971">Masukkan kode PIN ini ke &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Microsoft CA Version</translation>
@@ -2810,7 +2812,7 @@
 <translation id="8266502311388875829">Hapus dari folder</translation>
 <translation id="427243282273028705">Debug hanya jika URL manifes mengakhiri dengan debug.nmf</translation>
 <translation id="2471964272749426546">Metode masukan Tamil (Tamil99)</translation>
-<translation id="9088917181875854783">Konfirmasi bahwa kode sandi ini ditampilkan di &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
+<translation id="9088917181875854783">Konfirmasikan bahwa kunci sandi ini ditampilkan di &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="8814190375133053267">Wi-Fi</translation>
 <translation id="5236831943526452400">Hapus cookie dan data situs lain saat Anda menutup browser</translation>
 <translation id="1558834950088298812">Kekerapan saat ekstensi diperbarui</translation>
@@ -2895,6 +2897,7 @@
 <translation id="8670869118777164560">Ekstensi ini gagal mengalihkan permintaan jaringan ke <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> karena ekstensi lain (<ph name="EXTENSION_NAME"/>) mengalihkannya ke <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Kesalahan Sinkronisasi: <ph name="PRODUCT_NAME"/> sudah usang dan perlu diperbarui.</translation>
 <translation id="790040513076446191">Memanipulasi setelan yang terkait privasi</translation>
+<translation id="7260002739296185724">Aktifkan penggunaan AVFoundation untuk perekaman video dan pemantauan perangkat video di OS X &gt;= 10.7. QTKit akan digunakan sebagai gantinya.</translation>
 <translation id="3116361045094675131">Keyboard Inggris</translation>
 <translation id="1463985642028688653">cekal</translation>
 <translation id="1715941336038158809">Nama pengguna atau sandi tidak valid.</translation>
@@ -3754,6 +3757,7 @@
 <translation id="6658571109205370715">Transparansi sertifikat</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">Hapus bookmark</translation>
+<translation id="7166627725100067582">Aktifkan dukungan Chromecast eksperimental yang memungkinkan pemutaran dan pengontrolan video dari Web di perangkat Chromecast.</translation>
 <translation id="3031557471081358569">Pilih item yang akan diimpor:</translation>
 <translation id="1368832886055348810">Kiri ke Kanan</translation>
 <translation id="834106456999819211">Pesanan Anda sedang diproses</translation>
@@ -4536,7 +4540,7 @@
 <translation id="6929555043669117778">Lanjutkan mencekal munculan</translation>
 <translation id="3508920295779105875">Pilih Folder Lain...</translation>
 <translation id="2159915644201199628">Tidak dapat mendekode gambar: '<ph name="IMAGE_NAME"/>'</translation>
-<translation id="904451693890288097">Masukkan kode sandi untuk &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
+<translation id="904451693890288097">Masukkan kunci sandi untuk &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="2604467856256242911">Aktifkan dukungan untuk profil pengguna yang dikelola oleh pengguna lain dan dapat memiliki batasan yang diterapkan.</translation>
 <translation id="2987775926667433828">Cina Tradisional</translation>
 <translation id="5210496856287228091">Nonaktifkan animasi boot.</translation>
@@ -4672,7 +4676,7 @@
 <translation id="5925147183566400388">Pengarah Pernyataan Praktik Sertifikasi</translation>
 <translation id="8119381715954636144">Identitas tidak terverifikasi</translation>
 <translation id="1497270430858433901">Anda menerima gratis <ph name="DATA_AMOUNT"/> pada <ph name="DATE"/></translation>
-<translation id="1779652936965200207">Masukkan kode sandi ini di &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
+<translation id="1779652936965200207">Masukkan kunci sandi ini di &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="8307376264102990850">Mengisi - Menghitung waktu sampai penuh</translation>
 <translation id="636850387210749493">Pendaftaran perusahaan</translation>
 <translation id="4602466770786743961">Selelu izinkan <ph name="HOST"/> mengakses kamera dan mikrofon Anda</translation>
diff --git a/chrome/app/resources/generated_resources_it.xtb b/chrome/app/resources/generated_resources_it.xtb
index e928171..6a5a33d 100644
--- a/chrome/app/resources/generated_resources_it.xtb
+++ b/chrome/app/resources/generated_resources_it.xtb
@@ -307,6 +307,7 @@
           Puoi provare a diagnosticare il problema procedendo nel seguente modo:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Attiva l'utilizzo delle API Mac OS X AVFoundation anziché di QTKit.</translation>
 <translation id="6317369057005134371">In attesa della finestra dell'applicazione...</translation>
 <translation id="6391832066170725637">Impossibile trovare il file o la directory.</translation>
 <translation id="7393381084163773901">Indirizzo</translation>
@@ -1284,6 +1285,7 @@
 <translation id="8442065444327205563">Il documento può essere visualizzato.</translation>
 <translation id="236141728043665931">Impedisci sempre l'accesso al microfono</translation>
 <translation id="2307462900900812319">Configura rete</translation>
+<translation id="1704385717926547822">Attiva supporto sperimentale Chromecast</translation>
 <translation id="5911798608827489036">Scambio di dati con qualsiasi computer sulla rete locale o su Internet</translation>
 <translation id="220858061631308971">Inserisci questo codice PIN su &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Versione CA Microsoft</translation>
@@ -2876,6 +2878,7 @@
 <translation id="8670869118777164560">Questa estensione non è riuscita a reindirizzare una richiesta di rete a <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> perché un'altra estensione (<ph name="EXTENSION_NAME"/>) l'ha reindirizzata a <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Errore di sincronizzazione. <ph name="PRODUCT_NAME"/> è obsoleto e deve essere aggiornato.</translation>
 <translation id="790040513076446191">Modifica delle impostazioni relative alla privacy</translation>
+<translation id="7260002739296185724">Consente di attivare l'utilizzo di AVFoundation per l'acquisizione di video e il monitoraggio di dispositivi video su OS X &gt;= 10.7. In caso contrario verrà utilizzato QTKit.</translation>
 <translation id="3116361045094675131">Tastiera britannica</translation>
 <translation id="1463985642028688653">blocca</translation>
 <translation id="1715941336038158809">Password o nome utente non valido.</translation>
@@ -3727,6 +3730,7 @@
 <translation id="6658571109205370715">Certificate transparency</translation>
 <translation id="8050038245906040378">Firma codice commerciale Microsoft</translation>
 <translation id="7299721129597238157">Elimina preferito</translation>
+<translation id="7166627725100067582">Consente di attivare il supporto sperimentale Chromecast che consente la riproduzione e il controllo dei video dal Web sui dispositivi Chromecast.</translation>
 <translation id="3031557471081358569">Seleziona elementi da importare:</translation>
 <translation id="1368832886055348810">Da sinistra a destra</translation>
 <translation id="834106456999819211">Il tuo ordine è in fase di evasione</translation>
diff --git a/chrome/app/resources/generated_resources_iw.xtb b/chrome/app/resources/generated_resources_iw.xtb
index dff9ca3..052b73b 100644
--- a/chrome/app/resources/generated_resources_iw.xtb
+++ b/chrome/app/resources/generated_resources_iw.xtb
@@ -299,6 +299,7 @@
 <translation id="7607274158153386860">בקש אתר טאבלט</translation>
 <translation id="8028060951694135607">‏שחזור מפתח של Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/><ph name="LINE_BREAK"/> תוכל לנסות לאבחן את הבעיה באמצעות השלבים הבאים:<ph name="LINE_BREAK"/><ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">‏הפעל את השימוש בממשקי API של Mac OS X AVFoundation, במקום ב-QTKit.</translation>
 <translation id="6317369057005134371">ממתין לחלון היישום...</translation>
 <translation id="6391832066170725637">הקובץ או הספרייה לא נמצאו.</translation>
 <translation id="7393381084163773901">כתובת</translation>
@@ -1294,6 +1295,7 @@
 <translation id="8442065444327205563">המסמך מוכן להצגה.</translation>
 <translation id="236141728043665931">חסום תמיד גישה למיקרופון</translation>
 <translation id="2307462900900812319">הגדר את הרשת</translation>
+<translation id="1704385717926547822">‏הפעל תמיכה ניסיונית ב-Chromecast</translation>
 <translation id="5911798608827489036">החלפת נתונים עם כל מחשב ברשת המקומית או באינטרנט</translation>
 <translation id="220858061631308971">‏הזן את קוד PIN זה ב-&quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">‏גרסת רשות אישורים של Microsoft</translation>
@@ -2886,6 +2888,7 @@
 <translation id="8670869118777164560">תוסף זה נכשל בניתוב בקשת רשת אל <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> מכיוון שתוסף אחר (<ph name="EXTENSION_NAME"/>) ניתב אותו אל <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">שגיאת סנכרון:  <ph name="PRODUCT_NAME"/> אינו מעודכן ויש לעדכן אותו.</translation>
 <translation id="790040513076446191">לשנות הגדרות הקשורות לפרטיות</translation>
+<translation id="7260002739296185724">‏הפעל שימוש ב-AVFoundation לצילום וידאו ולמעקב אחר מכשירי וידאו בגרסת OS X‏ 10.7 ואילך. אחרת, ייעשה שימוש ב-QTKit.</translation>
 <translation id="3116361045094675131">מקלדת אנגלית (בריטניה)</translation>
 <translation id="1463985642028688653">חסום</translation>
 <translation id="1715941336038158809">שם משתמש או סיסמה לא חוקיים.</translation>
@@ -3738,6 +3741,7 @@
 <translation id="6658571109205370715">שקיפות אישור</translation>
 <translation id="8050038245906040378">‏חתימת קוד מסחרי של Microsoft</translation>
 <translation id="7299721129597238157">מחק סימניה</translation>
+<translation id="7166627725100067582">‏הפעל תמיכה ניסיונית ב-Chromecast כדי לאפשר הפעלה של סרטונים ושליטה בהם מהאינטרנט במכשירי Chromecast.</translation>
 <translation id="3031557471081358569">בחר פריטים לייבוא:</translation>
 <translation id="1368832886055348810">משמאל לימין</translation>
 <translation id="834106456999819211">ההזמנה שלך בטיפול</translation>
diff --git a/chrome/app/resources/generated_resources_ja.xtb b/chrome/app/resources/generated_resources_ja.xtb
index 41f0f39..06891c6 100644
--- a/chrome/app/resources/generated_resources_ja.xtb
+++ b/chrome/app/resources/generated_resources_ja.xtb
@@ -309,6 +309,7 @@
           問題を診断するには次の手順に従ってください:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Mac OS X AVFoundation API を使用できるようにする(QTKit の代わりに使用)</translation>
 <translation id="6317369057005134371">アプリケーション ウィンドウを待機しています...</translation>
 <translation id="6391832066170725637">指定したファイルまたはディレクトリは見つかりませんでした。</translation>
 <translation id="7393381084163773901">町村、番地</translation>
@@ -1297,6 +1298,7 @@
 <translation id="8442065444327205563">ドキュメントを表示できます。</translation>
 <translation id="236141728043665931">マイクのアクセスを常にブロックする</translation>
 <translation id="2307462900900812319">ネットワークを設定</translation>
+<translation id="1704385717926547822">試験運用版の Chromecast サポートを有効にする</translation>
 <translation id="5911798608827489036">ローカル ネットワークまたはインターネット上のパソコンとのデータ交換</translation>
 <translation id="220858061631308971">「<ph name="DEVICE_NAME"/>」の PIN コードを入力してください:</translation>
 <translation id="6263082573641595914">Microsoft CA バージョン</translation>
@@ -2911,6 +2913,7 @@
 <translation id="8670869118777164560">別の拡張機能(<ph name="EXTENSION_NAME"/>)がネットワーク リクエストを <ph name="ACTUAL_REDIRECT_DESTINATION"/> にリダイレクトしたため、この拡張機能はリクエストを <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> にリダイレクトできませんでした。</translation>
 <translation id="3654092442379740616">同期エラー: <ph name="PRODUCT_NAME"/> が最新ではないため、更新する必要があります。</translation>
 <translation id="790040513076446191">プライバシー関連設定を操作する</translation>
+<translation id="7260002739296185724">OS X 10.7 以上で、動画キャプチャと動画デバイスの監視に AVFoundation を使用できるようにします。AVFoundation を使用しない場合、QTKit が代わりに使用されます。</translation>
 <translation id="3116361045094675131">英語(英国)のキーボード</translation>
 <translation id="1463985642028688653">ブロック</translation>
 <translation id="1715941336038158809">ユーザー名またはパスワードが無効です。</translation>
@@ -3772,6 +3775,7 @@
 <translation id="6658571109205370715">証明書の透明性</translation>
 <translation id="8050038245906040378">Microsoft 商用コード署名</translation>
 <translation id="7299721129597238157">ブックマークを削除</translation>
+<translation id="7166627725100067582">Chromecast デバイス上でウェブ動画の再生と操作を行うための、試験運用版の Chromecast サポートを有効にします。</translation>
 <translation id="3031557471081358569">インポートするデータを選択:</translation>
 <translation id="1368832886055348810">左から右</translation>
 <translation id="834106456999819211">お申し込みを処理しています</translation>
diff --git a/chrome/app/resources/generated_resources_kn.xtb b/chrome/app/resources/generated_resources_kn.xtb
index e241a3c..464820c 100644
--- a/chrome/app/resources/generated_resources_kn.xtb
+++ b/chrome/app/resources/generated_resources_kn.xtb
@@ -308,6 +308,7 @@
           ಈ ಮಂದಿನ ಹಂತಗಳನ್ನು ಅನುಸರಿಸುವ  ಮೂಲಕ ನೀವು ಸಮಸ್ಯೆಯನ್ನು ಪರಿಹರಿಸಲು ಪ್ರಯತ್ನಿಸಬಹುದು:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit ಬದಲಾಗಿ, Mac OS X AVFoundation API ಗಳ ಬಳಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ.</translation>
 <translation id="6317369057005134371">ಅಪ್ಲಿಕೇಶನ್ ವಿಂಡೋಗಾಗಿ ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ...</translation>
 <translation id="6391832066170725637">ಫೈಲ್ ಅಥವಾ ಡೈರೆಕ್ಟರಿ ಪತ್ತೆಯಾಗಿಲ್ಲ.</translation>
 <translation id="7393381084163773901">ಗಲ್ಲಿಯ ವಿಳಾಸ</translation>
@@ -1302,6 +1303,7 @@
 <translation id="8442065444327205563">ನಿಮ್ಮ ಡಾಕ್ಯುಮೆಂಟ್ ವೀಕ್ಷಿಸಲು ಸಿದ್ಧವಿದೆ.</translation>
 <translation id="236141728043665931">ಯಾವಾಗಲೂ ಮೈಕ್ರೋಫೋನ್ ಪ್ರವೇಶವನ್ನು ನಿರ್ಬಂಧಿಸಿ</translation>
 <translation id="2307462900900812319">ನೆಟ್‌ವರ್ಕ್ ಕಾನ್ಫಿಗರ್ ಮಾಡು</translation>
+<translation id="1704385717926547822">ಪ್ರಯೋಗಾತ್ಮಕ Chromecast ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ</translation>
 <translation id="5911798608827489036">ಸ್ಥಳೀಯ ನೆಟ್‌ವರ್ಕ್ ಅಥವಾ ಇಂಟರ್ನೆಟ್‌ನಲ್ಲಿ ಯಾವುದೇ ಕಂಪ್ಯೂಟರ್‌ನೊಂದಿಗೆ ಡೇಟಾ ವಿನಿಮಯ ಮಾಡಿ</translation>
 <translation id="220858061631308971">ದಯವಿಟ್ಟು &quot;<ph name="DEVICE_NAME"/>&quot; ಇದರಲ್ಲಿ ಈ ಪಿನ್ ಕೋಡ್ ಅನ್ನು ನಮೂದಿಸಿ :</translation>
 <translation id="6263082573641595914">Microsoft CA ಆವೃತ್ತಿ</translation>
@@ -2902,6 +2904,7 @@
 <translation id="8670869118777164560">ಬೇರೊಂದು ವಿಸ್ತರಣೆಯು (<ph name="EXTENSION_NAME"/>) ಇದನ್ನು <ph name="ACTUAL_REDIRECT_DESTINATION"/> ಗೆ ಮರುನಿರ್ದೇಶಿಸಿರುವ ಕಾರಣ ಈ ವಿಸ್ತರಣೆಯು ನೆಟ್‌ವರ್ಕ್ ವಿನಂತಿಯನ್ನು <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> ಗೆ ಮರುನಿರ್ದೇಶಿಸಲು ವಿಫಲವಾಗಿದೆ.</translation>
 <translation id="3654092442379740616">ಸಿಂಕ್ ದೋಷ: <ph name="PRODUCT_NAME"/> ಅವಧಿ ಮುಕ್ತಾಯಗೊಂಡಿದೆ ಮತ್ತು ನವೀಕರಿಸುವ ಅಗತ್ಯವಿದೆ.</translation>
 <translation id="790040513076446191">ಗೌಪ್ಯತೆಗೆ- ಸಂಬಂಧಿಸಿದ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಸ್ವಾಧೀನಪಡಿಸಿಕೊಳ್ಳಿ</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7 ನಲ್ಲಿ ವೀಡಿಯೊ ಸೆರೆಹಿಡಿಯಲು ಮತ್ತು ವೀಡಿಯೊ ಸಾಧನದ ಪರಿವೀಕ್ಷಣೆಯ ಬಳಕೆಗಾಗಿ AVFoundation ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ. ಇಲ್ಲವಾದಲ್ಲಿ QTKit ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ.</translation>
 <translation id="3116361045094675131">ಯುಕೆ ಕೀಬೋರ್ಡ್</translation>
 <translation id="1463985642028688653">ಮುಚ್ಚು</translation>
 <translation id="1715941336038158809">ಅಮಾನ್ಯ ಬಳಕೆದಾರ ಹೆಸರು ಅಥವಾ ಪಾಸ್‌ವರ್ಡ್.</translation>
@@ -3759,6 +3762,7 @@
 <translation id="6658571109205370715">ಪಾರದರ್ಶಕತೆ ಪ್ರಮಾಣಪತ್ರ</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">ಬುಕ್‌ಮಾರ್ಕ್ ಅಳಿಸು</translation>
+<translation id="7166627725100067582">ಪ್ರಾಯೋಗಿಕ Chromecast ಬೆಂಬಲವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ ಈ ಮೂಲಕ Chromecast ಸಾಧನಗಳಲ್ಲಿನ ವೆಬ್‍‍ನಿಂದ ವೀಡಿಯೊಗಳನ್ನು ಪ್ಲೇ ಮಾಡಲು ಮತ್ತು ನಿಯಂತ್ರಿಸಲು ಅನುಮತಿಸಿ.</translation>
 <translation id="3031557471081358569">ಆಮದು ಮಾಡಲು ಐಟಂಗಳನ್ನು ಆಯ್ಕೆ ಮಾಡಿ:</translation>
 <translation id="1368832886055348810">ಎಡದಿಂದ ಬಲಕ್ಕೆ</translation>
 <translation id="834106456999819211">ನಿಮ್ಮ ಆದೇಶವನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗುತ್ತಿದೆ</translation>
diff --git a/chrome/app/resources/generated_resources_ko.xtb b/chrome/app/resources/generated_resources_ko.xtb
index 8089c11..1dd52a5 100644
--- a/chrome/app/resources/generated_resources_ko.xtb
+++ b/chrome/app/resources/generated_resources_ko.xtb
@@ -308,6 +308,7 @@
           다음 단계에 따라 문제를 진단할 수 있습니다.
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Mac OS X AVFoundation API 사용 설정(QTKit 대신)</translation>
 <translation id="6317369057005134371">애플리케이션 창을 기다리는 중...</translation>
 <translation id="6391832066170725637">파일이나 디렉토리를 찾지 못했습니다.</translation>
 <translation id="7393381084163773901">상세 주소</translation>
@@ -1308,6 +1309,7 @@
 <translation id="8442065444327205563">문서를 볼 준비가 되었습니다.</translation>
 <translation id="236141728043665931">마이크 액세스 항상 차단</translation>
 <translation id="2307462900900812319">네트워크 설정</translation>
+<translation id="1704385717926547822">실험용 Chromecast 지원 사용 설정</translation>
 <translation id="5911798608827489036">로컬 네트워크 또는 인터넷의 모든 컴퓨터와 데이터 교환</translation>
 <translation id="220858061631308971">'<ph name="DEVICE_NAME"/>'의 PIN 코드를 입력하세요:</translation>
 <translation id="6263082573641595914">Microsoft CA Version</translation>
@@ -2918,6 +2920,7 @@
 <translation id="8670869118777164560">이 확장 프로그램에서 네트워크 요청을 <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>(으)로 리디렉션하는 데 실패했습니다. 다른 확장 프로그램(<ph name="EXTENSION_NAME"/>)이 해당 요청을 <ph name="ACTUAL_REDIRECT_DESTINATION"/>(으)로 리디렉션했습니다.</translation>
 <translation id="3654092442379740616">동기화 오류: <ph name="PRODUCT_NAME"/>이(가) 오래되어 업데이트해야 합니다.</translation>
 <translation id="790040513076446191">개인정보 보호 관련 설정 조정</translation>
+<translation id="7260002739296185724">OS X 10.7 이상에서 동영상 캡처 및 동영상 기기 모니터링에 AVFoundation을 사용하도록 설정합니다. 설정하지 않을 경우 QTKit이 사용됩니다.</translation>
 <translation id="3116361045094675131">영어(영국식) 키보드</translation>
 <translation id="1463985642028688653">차단</translation>
 <translation id="1715941336038158809">사용자 이름 또는 비밀번호가 잘못되었습니다.</translation>
@@ -3777,6 +3780,7 @@
 <translation id="6658571109205370715">인증서 확인</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">북마크 삭제</translation>
+<translation id="7166627725100067582">Chromecast 기기에서 웹의 동영상을 재생하고 제어할 수 있는 실험용 Chromecast 지원을 사용하도록 설정합니다.</translation>
 <translation id="3031557471081358569">가져올 항목 선택:</translation>
 <translation id="1368832886055348810">왼쪽에서 오른쪽으로</translation>
 <translation id="834106456999819211">신청 내용을 처리하는 중입니다.</translation>
@@ -4549,7 +4553,7 @@
 <translation id="6947969589393588905"><ph name="IDS_SHORT_PRODUCT_NAME"/>이(가) 이전 버전입니다.</translation>
 <translation id="4784330909746505604">PowerPoint 프레젠테이션</translation>
 <translation id="4345587454538109430">설정...</translation>
-<translation id="3255228561559750854">검색하거나 'Ok, Google'이라고 말하세요.</translation>
+<translation id="3255228561559750854">검색하거나 'OK Google'이라고 말하세요.</translation>
 <translation id="8148264977957212129">병음 입력 방법</translation>
 <translation id="2288278176040912387">레코드 플레이어</translation>
 <translation id="7772032839648071052">암호 확인</translation>
diff --git a/chrome/app/resources/generated_resources_lt.xtb b/chrome/app/resources/generated_resources_lt.xtb
index 5a687ec..b6c9fe8 100644
--- a/chrome/app/resources/generated_resources_lt.xtb
+++ b/chrome/app/resources/generated_resources_lt.xtb
@@ -307,6 +307,7 @@
           Galite pabandyti nustatyti problemą atlikę šiuos veiksmus:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Įgalinti „Mac OS X AVFoundation“ API naudojimą vietoje „QTKit“.</translation>
 <translation id="6317369057005134371">Laukiama programos lango...</translation>
 <translation id="6391832066170725637">Nepavyko rasti failo ar aplanko.</translation>
 <translation id="7393381084163773901">Adresas</translation>
@@ -1305,6 +1306,7 @@
 <translation id="8442065444327205563">Dokumentas parengtas peržiūr.</translation>
 <translation id="236141728043665931">Visada blokuoti prieigą prie mikrofono</translation>
 <translation id="2307462900900812319">Konfigūruoti tinklą</translation>
+<translation id="1704385717926547822">Įgalinti eksperimentinį „Chromecast“ palaikymą</translation>
 <translation id="5911798608827489036">Keistis duomenimis su bet kuriuo kompiuteriu vietiniame tinkle ar internete</translation>
 <translation id="220858061631308971">Įveskite šį PIN kodą „<ph name="DEVICE_NAME"/>“:</translation>
 <translation id="6263082573641595914">„Microsoft“ CA versija</translation>
@@ -2927,6 +2929,7 @@
 <translation id="8670869118777164560">Šiam plėtiniui peradresuojant tinklo užklausą <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> įvyko klaida, nes kitas plėtinys („<ph name="EXTENSION_NAME"/>“) peradresavo ją <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Sinchronizavimo klaida: „<ph name="PRODUCT_NAME"/>“ yra pasenusi ir turi būti atnaujinta.</translation>
 <translation id="790040513076446191">Keisti privatumo nustatymus</translation>
+<translation id="7260002739296185724">Įgalinti „AVFoundation“ naudojimą vaizdo įrašams fiksuoti ir vaizdo įrenginiui stebėti naudojant 10.7 ar naujesnės versijos „OS X“. Kitu atveju bus naudojama „QTKit“.</translation>
 <translation id="3116361045094675131">JK klaviatūra</translation>
 <translation id="1463985642028688653">blokuoti</translation>
 <translation id="1715941336038158809">Neteisingas naudotojo vardas ar slaptažodis.</translation>
@@ -3497,7 +3500,7 @@
 <translation id="3578594933904494462">Šio skirtuko lapo turinys bendrinamas.</translation>
 <translation id="295942452804818007">Rodyti būsenos meniu</translation>
 <translation id="8051961636969466900">Galite padėti užtikrinti „Chrome“ saugą ir lengvesnį naudojimą siųsdami įtartinus atsisiųstus failus „Google“.</translation>
-<translation id="3831099738707437457">&amp;Slėpti rašybos tikrinimo skydą</translation>
+<translation id="3831099738707437457">&amp;Slėpti rašybos tikrinimo skydelį</translation>
 <translation id="4243835228168841140"><ph name="FULLSCREEN_ORIGIN"/> norima neleisti pelės žymeklio.</translation>
 <translation id="8662911384982557515">Pakeisti pagrindinį puslapį į: <ph name="HOME_PAGE"/></translation>
 <translation id="1040471547130882189">Papildinys neatsako</translation>
@@ -3789,6 +3792,7 @@
 <translation id="6658571109205370715">Sertifikato skaidrumas</translation>
 <translation id="8050038245906040378">„Microsoft“ komercinio kodo pasirašymas</translation>
 <translation id="7299721129597238157">Ištrinti žymę</translation>
+<translation id="7166627725100067582">Įgalinti eksperimentinį „Chromecast“ palaikymą, kurį naudojant galima paleisti ir valdyti vaizdo įrašus prisijungus prie žiniatinklio „Chromecast“ įrenginiais.</translation>
 <translation id="3031557471081358569">Pasirinkite elementus importavimui:</translation>
 <translation id="1368832886055348810">Iš kairės į dešinę</translation>
 <translation id="834106456999819211">Užsakymas apdorojamas</translation>
@@ -4896,7 +4900,7 @@
 <translation id="8091486941471012404">Įgalinti Programų paleidimo priemonės aplankus.</translation>
 <translation id="8675377193764357545">Sinchronizuota kaip <ph name="USER_EMAIL_ADDRESS"/></translation>
 <translation id="466816546394172504">Neleisti atidėtų 2D matomųjų tinklalapių sričių</translation>
-<translation id="5398353896536222911">&amp;Rodyti rašybos tikrinimo skydą</translation>
+<translation id="5398353896536222911">&amp;Rodyti rašybos tikrinimo skydelį</translation>
 <translation id="8018604194395563792">„<ph name="PRODUCT_NAME"/>“ užblokavo prieigą prie šio puslapio <ph name="HOST_NAME"/>.</translation>
 <translation id="3494769164076977169">Paklausti, kai svetainė bando atsisiųsti failus automatiškai po pirmo failo (rekomenduojama)</translation>
 <translation id="7549053541268690807">Ieškoti žodyne</translation>
diff --git a/chrome/app/resources/generated_resources_lv.xtb b/chrome/app/resources/generated_resources_lv.xtb
index e4e14e9..c7a4f27 100644
--- a/chrome/app/resources/generated_resources_lv.xtb
+++ b/chrome/app/resources/generated_resources_lv.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Pieprasīt planšetdatoram paredzētu vietnes versiju</translation>
 <translation id="8028060951694135607">Microsoft atslēgas atkopšana</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/><ph name="LINE_BREAK"/> Varat mēģināt noteikt problēmu, izpildot šādas darbības: <ph name="LINE_BREAK"/><ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Iespējot Mac OS X AV Foundation API izmantošanu (QTKit vietā)</translation>
 <translation id="6317369057005134371">Notiek lietojumprogrammas loga gaidīšana...</translation>
 <translation id="6391832066170725637">Failu vai direktoriju nevar atrast.</translation>
 <translation id="7393381084163773901">Adrese</translation>
@@ -1300,6 +1301,7 @@
 <translation id="8442065444327205563">Varat skatīt savu dokumentu.</translation>
 <translation id="236141728043665931">Vienmēr bloķēt piekļuvi mikrofonam</translation>
 <translation id="2307462900900812319">Konfigurēt tīklu</translation>
+<translation id="1704385717926547822">Iespējot eksperimentālo Chromecast atbalstu</translation>
 <translation id="5911798608827489036">Apmainīties datiem ar jebkuru datoru lokālajā tīklā vai internetā</translation>
 <translation id="220858061631308971">Ievadiet šo PIN kodu ierīcē <ph name="DEVICE_NAME"/>:</translation>
 <translation id="6263082573641595914">Microsoft CA versija</translation>
@@ -2907,6 +2909,7 @@
 <translation id="8670869118777164560">Šis paplašinājums nevarēja novirzīt tīkla pieprasījumu uz galamērķi <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, jo cits paplašinājums (<ph name="EXTENSION_NAME"/>) to novirzīja uz šādu galamērķi: <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Sinhronizācijas kļūda: <ph name="PRODUCT_NAME"/> ir novecojis un ir jāatjaunina.</translation>
 <translation id="790040513076446191">Manipulēt ar konfidencialitāti saistītus iestatījumus</translation>
+<translation id="7260002739296185724">Iespējojiet platformas AV Foundation izmantošanu video tveršanai un video ierīces pārraudzībai operētājsistēmā OS X 10.7 vai jaunākā versijā. Pretējā gadījumā tiks izmantots QTKit.</translation>
 <translation id="3116361045094675131">AK tastatūra</translation>
 <translation id="1463985642028688653">bloķēt</translation>
 <translation id="1715941336038158809">Nederīgs lietotājvārds vai parole.</translation>
@@ -3766,6 +3769,7 @@
 <translation id="6658571109205370715">Sertifikātu pārskatāmība</translation>
 <translation id="8050038245906040378">Microsoft tirdzniecības koda parakstīšana</translation>
 <translation id="7299721129597238157">Dzēst grāmatzīmi</translation>
+<translation id="7166627725100067582">Iespējojiet eksperimentālo Chromecast atbalstu, lai atļautu atskaņot un pārvaldīt videoklipus tīmeklī, izmantojot Chromecast ierīces.</translation>
 <translation id="3031557471081358569">Izvēlēties vienumu, ko importēt:</translation>
 <translation id="1368832886055348810">No kreisās uz labo pusi</translation>
 <translation id="834106456999819211">Jūsu pasūtījums tiek apstrādāts</translation>
diff --git a/chrome/app/resources/generated_resources_ml.xtb b/chrome/app/resources/generated_resources_ml.xtb
index 6b87d77..41b7d06 100644
--- a/chrome/app/resources/generated_resources_ml.xtb
+++ b/chrome/app/resources/generated_resources_ml.xtb
@@ -308,6 +308,7 @@
           ഇനിപ്പറയുന്ന ഘട്ടങ്ങൾ പാലിച്ച് നിങ്ങൾക്ക് പ്രശ്‌നം പരിഹരിക്കാൻ ശ്രമിക്കാവുന്നതാണ്:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit-ന് പകരം Mac OS X AVFoundation API-കളുടെ ഉപയോഗം പ്രവർത്തനക്ഷമമാക്കുക.</translation>
 <translation id="6317369057005134371">അപ്ലിക്കേഷൻ വിൻഡോയ്‌ക്കായി കാത്തിരിക്കുന്നു...</translation>
 <translation id="6391832066170725637">ഫയല്‍ അല്ലെങ്കില്‍ ഡയറക്ടറി കണ്ടെത്താന്‍ കഴിഞ്ഞില്ല.</translation>
 <translation id="7393381084163773901">സ്‌ട്രീറ്റ് വിലാസം</translation>
@@ -1316,6 +1317,7 @@
 <translation id="8442065444327205563">നിങ്ങളുടെ പ്രമാണം കാണുന്നതിന് തയ്യാറാണ്.</translation>
 <translation id="236141728043665931">എല്ലായ്‌പ്പോഴും മൈക്രോഫോൺ ആക്‌സസ്സ് തടയുക</translation>
 <translation id="2307462900900812319">നെറ്റ്‌വർക്ക് കോൺഫിഗർ ചെയ്യുക</translation>
+<translation id="1704385717926547822">പരീക്ഷണാത്മക Chromecast പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുക</translation>
 <translation id="5911798608827489036">ഏതു കമ്പ്യൂട്ടർ ഉപയോഗിച്ചും പ്രാദേശിക നെറ്റ്‌വർക്കിലോ ഇന്റർനെറ്റിലോ ഡാറ്റ എക്‌സ്‌ചേഞ്ച് ചെയ്യുക</translation>
 <translation id="220858061631308971">&quot;<ph name="DEVICE_NAME"/>&quot; എന്നതിൽ PIN കോഡ് നൽകുക:</translation>
 <translation id="6263082573641595914">Microsoft CA പതിപ്പ്</translation>
@@ -2925,6 +2927,7 @@
 <translation id="8670869118777164560">മറ്റൊരു വിപുലീകരണം (<ph name="EXTENSION_NAME"/>), <ph name="ACTUAL_REDIRECT_DESTINATION"/>-ലേക്ക് ഒരു നെറ്റ്‌വർക്ക് അഭ്യർത്ഥനയെ റീഡയറക്റ്റുചെയ്‌തതിനാൽ അതിനെ <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>-ലേക്ക് റീഡയറക്റ്റുചെയ്യുന്നതിന് ഈ വിപുലീകരണം പരാജയപ്പെട്ടു.</translation>
 <translation id="3654092442379740616">സമന്വയിപ്പിക്കൽ പിശക്:  <ph name="PRODUCT_NAME"/> എന്നത് കാലഹരണപ്പെട്ടതിനാൽ അപ്‌ഡേറ്റ് ചെയ്യേണ്ടത് ആവശ്യമാണ്.</translation>
 <translation id="790040513076446191">സ്വകാര്യത സംബന്ധിയായ ക്രമീകരണങ്ങൾ കൈകാര്യം ചെയ്യുക</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7-ൽ വീഡിയോ എടുക്കുന്നതിനും വീഡിയോ ഉപകരണം നിരീക്ഷിക്കുന്നതിനുമായി AVFoundation ഉപയോഗം പ്രവർത്തനക്ഷമമാക്കുക. അല്ലെങ്കിൽ QTKit ഉപയോഗിക്കും.</translation>
 <translation id="3116361045094675131">യുകെ കീബോര്‍ഡ്</translation>
 <translation id="1463985642028688653">തടയുക</translation>
 <translation id="1715941336038158809">ഉപയോക്തൃ നാമം അല്ലെങ്കില്‍ പാസ്‌വേഡ് അസാധുവാണ്.</translation>
@@ -3783,6 +3786,7 @@
 <translation id="6658571109205370715">സർട്ടിഫിക്കറ്റ് സുതാര്യത</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">ബുക്ക്‌മാര്‍‌ക്ക് ഇല്ലാതാക്കുക</translation>
+<translation id="7166627725100067582">Chromecast ഉപകരണങ്ങളിലെ വെബിൽ നിന്ന് വീഡിയോകൾ പ്ലേ ചെയ്യാനും നിയന്ത്രിക്കാനും അനുവദിക്കുന്ന പരീക്ഷണാത്മക Chromecast പിന്തുണ പ്രവർത്തനക്ഷമമാക്കുക.</translation>
 <translation id="3031557471081358569">ഇറക്കുമതി ചെയ്യുന്നതിനായി ഇനങ്ങള്‍ തിരഞ്ഞെടുക്കുക:</translation>
 <translation id="1368832886055348810">ഇടതുനിന്ന് വലത്തേക്ക്</translation>
 <translation id="834106456999819211">നിങ്ങളുടെ ഓർഡർ പ്രോസസ്സുചെയ്യുന്നു</translation>
diff --git a/chrome/app/resources/generated_resources_mr.xtb b/chrome/app/resources/generated_resources_mr.xtb
index 9ba6aa8..628058a 100644
--- a/chrome/app/resources/generated_resources_mr.xtb
+++ b/chrome/app/resources/generated_resources_mr.xtb
@@ -309,6 +309,7 @@
 <translation id="7607274158153386860">टॅब्लेट साइटची विनंती करा</translation>
 <translation id="8028060951694135607">Microsoft Key Recovery</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/><ph name="LINE_BREAK"/> आपण समस्‍येचे निदान करण्‍याचा प्रयत्‍न खालील चरणांचे अनुसरण करून करू शकता: <ph name="LINE_BREAK"/><ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit च्याऐवजी Mac OS X AVFoundation APIs चा वापर सक्षम करा.</translation>
 <translation id="6317369057005134371">अनुप्रयोग विंडोसाठी प्रतीक्षा करत आहे...</translation>
 <translation id="6391832066170725637">फाइल किंवा निर्देशिका आढळणे शक्य नाही.</translation>
 <translation id="7393381084163773901">मार्ग पत्ता</translation>
@@ -1306,6 +1307,7 @@
 <translation id="8442065444327205563">पहाण्यासाठी आपला दस्तऐवज तयार आहे.</translation>
 <translation id="236141728043665931">मायक्रोफोन प्रवेश नेहमी अवरोधित करा</translation>
 <translation id="2307462900900812319">नेटवर्क कॉन्फिगर करा</translation>
+<translation id="1704385717926547822">प्रायोगिक Chromecast समर्थन सक्षम करा</translation>
 <translation id="5911798608827489036">स्थानिक नेटवर्क किंवा इंटरनेटवरील कोणत्याही संगणकासह डेटा अदलाबदल करा</translation>
 <translation id="220858061631308971">कृपया यावर हा पिन कोड प्रविष्‍ट करा &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Microsoft CA आवृत्ती</translation>
@@ -2923,6 +2925,7 @@
 <translation id="8670869118777164560">हा विस्तार <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> वर एक नेटवर्क विनंती पुनर्निर्देशित करण्यात अयशस्वी झाला कारण दुसर्‍या (<ph name="EXTENSION_NAME"/>) विस्ताराने तो <ph name="ACTUAL_REDIRECT_DESTINATION"/> वर पुनर्निर्देशित केला.</translation>
 <translation id="3654092442379740616">समक्रमण त्रुटी: <ph name="PRODUCT_NAME"/> कालबाह्य नाही आणि अद्यतनित केले जाणे आवश्यक आहे.</translation>
 <translation id="790040513076446191">गोपनीयतेशी-संबद्ध सेटिंग्ज कुशलतेने हाताळा</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7 वर व्हिडिओ कॅप्चर आणि व्हिडिओ डिव्हाइस परीक्षणासाठी AVFoundation वापर सक्षम करा. अन्यथा QTKit वापरले जाईल.</translation>
 <translation id="3116361045094675131">यूके कीबोर्ड</translation>
 <translation id="1463985642028688653">अवरोधित करा</translation>
 <translation id="1715941336038158809">अवैध वापरकर्ता नाव किंवा संकेतशब्द.</translation>
@@ -3781,6 +3784,7 @@
 <translation id="6658571109205370715">प्रमाणपत्र पारदर्शकता</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">बुकमार्क हटवा</translation>
+<translation id="7166627725100067582">Chromecast डिव्हाइसेसवर वेबवरील व्हिडिओ प्ले करण्यास आणि नियंत्रित करण्यास अनुमती देणारे प्रायोगिक Chromecast समर्थन सक्षम करा.</translation>
 <translation id="3031557471081358569">आयात करण्यासाठी आयटम निवडा:</translation>
 <translation id="1368832886055348810">डावीकडून उजवीकडे</translation>
 <translation id="834106456999819211">आपल्‍या ऑर्डरवर प्रक्रिया केली जात आहे</translation>
diff --git a/chrome/app/resources/generated_resources_ms.xtb b/chrome/app/resources/generated_resources_ms.xtb
index 440a41b..92926fa 100644
--- a/chrome/app/resources/generated_resources_ms.xtb
+++ b/chrome/app/resources/generated_resources_ms.xtb
@@ -308,6 +308,7 @@
           Anda boleh cuba untuk mendiagnosis masalah dengan mengambil langkah berikut:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Membolehkan penggunaan Mac OS X AVFoundation API, bukannya QTKit.</translation>
 <translation id="6317369057005134371">Menunggu tetingkap aplikasi...</translation>
 <translation id="6391832066170725637">Fail atau direktori tidak dapat dijumpai.</translation>
 <translation id="7393381084163773901">Alamat jalan</translation>
@@ -1306,6 +1307,7 @@
 <translation id="8442065444327205563">Dokumen anda telah sedia untuk dilihat.</translation>
 <translation id="236141728043665931">Sentiasa sekat akses mikrofon</translation>
 <translation id="2307462900900812319">Konfigurasikan rangkaian</translation>
+<translation id="1704385717926547822">Dayakan sokongan Chromecast percubaan</translation>
 <translation id="5911798608827489036">Bertukar data dengan mana-mana komputer pada rangkaian tempatan atau internet</translation>
 <translation id="220858061631308971">Sila masukkan kod PIN ini pada &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Versi Microsoft CA</translation>
@@ -2933,6 +2935,7 @@
 <translation id="8670869118777164560">Pelanjutan ini gagal mengubah hala permintaan rangkaian ke <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> kerana pelanjutan lain (<ph name="EXTENSION_NAME"/>) mengubah halanya ke <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Ralat Segerak:  <ph name="PRODUCT_NAME"/> sudah lapuk dan perlu dikemas kini.</translation>
 <translation id="790040513076446191">Manipulasi tetapan yang berkaitan privasi</translation>
+<translation id="7260002739296185724">Membolehkan penggunaan AVFoundation untuk merakam video dan pemantauan peranti video pada OS X &gt;= 10.7. QTKit akan digunakan sebaliknya.</translation>
 <translation id="3116361045094675131">Papan kekunci UK</translation>
 <translation id="1463985642028688653">sekat</translation>
 <translation id="1715941336038158809">Nama pengguna atau kata laluan tidak sah.</translation>
@@ -3794,6 +3797,7 @@
 <translation id="6658571109205370715">Ketelusan sijil</translation>
 <translation id="8050038245906040378">Menandatangani Kod Komersial Microsoft</translation>
 <translation id="7299721129597238157">Padamkan penanda halaman</translation>
+<translation id="7166627725100067582">Dayakan sokongan Chromecast percubaan yang membolehkan video dimainkan dan dikawal dari Web pada peranti Chromecast.</translation>
 <translation id="3031557471081358569">Pilih item untuk mengimport:</translation>
 <translation id="1368832886055348810">Kiri ke Kanan</translation>
 <translation id="834106456999819211">Pesanan anda sedang diproses</translation>
diff --git a/chrome/app/resources/generated_resources_nl.xtb b/chrome/app/resources/generated_resources_nl.xtb
index 7fc943e..81b1e27 100644
--- a/chrome/app/resources/generated_resources_nl.xtb
+++ b/chrome/app/resources/generated_resources_nl.xtb
@@ -312,6 +312,7 @@
           Je kunt als volgt proberen vast te stellen wat het probleem is:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Gebruik van Mac OS X AVFoundation API's in plaats van QTKit inschakelen.</translation>
 <translation id="6317369057005134371">Wachten op appvenster...</translation>
 <translation id="6391832066170725637">Kan bestand of directory niet vinden.</translation>
 <translation id="7393381084163773901">Adres</translation>
@@ -1311,6 +1312,7 @@
 <translation id="8442065444327205563">Document gereed voor weergave.</translation>
 <translation id="236141728043665931">Microfoontoegang altijd blokkeren</translation>
 <translation id="2307462900900812319">Netwerk configureren</translation>
+<translation id="1704385717926547822">Experimentele Chromecast-ondersteuning inschakelen</translation>
 <translation id="5911798608827489036">Gegevens uitwisselen met elke computer op het lokale netwerk of internet</translation>
 <translation id="220858061631308971">Voer deze pincode in op '<ph name="DEVICE_NAME"/>':</translation>
 <translation id="6263082573641595914">CA-versie van Microsoft</translation>
@@ -2928,6 +2930,7 @@
 <translation id="8670869118777164560">Deze extensie heeft een netwerkverzoek niet kunnen omleiden naar <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> omdat een andere extensie (<ph name="EXTENSION_NAME"/>) het verzoek heeft omgeleid naar <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Synchronisatiefout: <ph name="PRODUCT_NAME"/> is verouderd en moet worden bijgewerkt.</translation>
 <translation id="790040513076446191">Privacygerelateerde instellingen manipuleren</translation>
+<translation id="7260002739296185724">Het gebruik van AVFoundation voor video-opname en videoapparaatcontrole inschakelen voor OS X &gt;= 10.7. Anders wordt QTKit gebruikt.</translation>
 <translation id="3116361045094675131">Brits toetsenbord</translation>
 <translation id="1463985642028688653">blokkeren</translation>
 <translation id="1715941336038158809">De gebruikersnaam of het wachtwoord is ongeldig.</translation>
@@ -3787,6 +3790,7 @@
 <translation id="6658571109205370715">Certificaattransparantie</translation>
 <translation id="8050038245906040378">Commerciële handtekening bij programmacode van Microsoft</translation>
 <translation id="7299721129597238157">Bladwijzer verwijderen</translation>
+<translation id="7166627725100067582">Experimentele Chromecast-ondersteuning inschakelen waardoor video's op internet kunnen worden afgespeeld en bediend op Chromecast-apparaten.</translation>
 <translation id="3031557471081358569">Selecteer items die je wilt importeren:</translation>
 <translation id="1368832886055348810">Links naar rechts</translation>
 <translation id="834106456999819211">Je bestelling wordt verwerkt</translation>
diff --git a/chrome/app/resources/generated_resources_no.xtb b/chrome/app/resources/generated_resources_no.xtb
index 04e0d74..6436246 100644
--- a/chrome/app/resources/generated_resources_no.xtb
+++ b/chrome/app/resources/generated_resources_no.xtb
@@ -303,6 +303,7 @@
           Du kan prøve å feilsøke problemet ved hjelp av følgende fremgangsmåte:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Aktiver bruk av Mac OS X AVFoundation API-er i stedet for QTKit.</translation>
 <translation id="6317369057005134371">Venter på appvinduet …</translation>
 <translation id="6391832066170725637">Filen eller katalogen ble ikke funnet.</translation>
 <translation id="7393381084163773901">Gateadresse</translation>
@@ -1295,6 +1296,7 @@
 <translation id="8442065444327205563">Dokumentet ditt er klart for visning.</translation>
 <translation id="236141728043665931">Blokkér alltid bruk av mikrofonen</translation>
 <translation id="2307462900900812319">Konfigurer nettverket</translation>
+<translation id="1704385717926547822">Aktiver eksperimentell Chromecast-støtte</translation>
 <translation id="5911798608827489036">utveksle data med en hvilken som helst datamaskin på det lokale nettverket eller Internett</translation>
 <translation id="220858061631308971">Skriv inn denne PIN-koden på «<ph name="DEVICE_NAME"/>»:</translation>
 <translation id="6263082573641595914">Microsoft sertifiseringsinstansversjon</translation>
@@ -2902,6 +2904,7 @@
 <translation id="8670869118777164560">Denne utvidelsen kunne ikke viderekoble en nettverksforespørsel til <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> fordi en annen utvidelse (<ph name="EXTENSION_NAME"/>) viderekoblet den til <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Synkroniseringsfeil: <ph name="PRODUCT_NAME"/> er foreldet og må oppdateres.</translation>
 <translation id="790040513076446191">manipulere personvernrelaterte innstillinger</translation>
+<translation id="7260002739296185724">Aktiver AV Foundation-bruk for videoopptak og videoenhetsovervåking på OS X &gt;= 10.7. QTKit brukes i andre tilfeller.</translation>
 <translation id="3116361045094675131">Britisk tastatur</translation>
 <translation id="1463985642028688653">blokkér</translation>
 <translation id="1715941336038158809">Ugyldig brukernavn og passord.</translation>
@@ -3758,6 +3761,7 @@
 <translation id="6658571109205370715">Sertifikatåpenhet</translation>
 <translation id="8050038245906040378">Microsoft-signering med kommersiell kode</translation>
 <translation id="7299721129597238157">Slett bokmerket</translation>
+<translation id="7166627725100067582">Aktiver eksperimentell Chromecast-støtte som gir mulighet for avspilling og kontroll av videoer fra nettet på Chromecast-enheter.</translation>
 <translation id="3031557471081358569">Velg elementer som skal importeres:</translation>
 <translation id="1368832886055348810">Venstre til høyre</translation>
 <translation id="834106456999819211">Bestillingen din behandles</translation>
diff --git a/chrome/app/resources/generated_resources_pl.xtb b/chrome/app/resources/generated_resources_pl.xtb
index 94b2114..0984492 100644
--- a/chrome/app/resources/generated_resources_pl.xtb
+++ b/chrome/app/resources/generated_resources_pl.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Żądaj strony w wersji dla tabletów</translation>
 <translation id="8028060951694135607">Odzyskiwanie kluczy firmy Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Możesz spróbować zdiagnozować problem, wykonując następujące czynności: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Włącz użycie interfejsów API AVFoundation zamiast QTKit w systemie Mac OS X.</translation>
 <translation id="6317369057005134371">Czekam na okno aplikacji...</translation>
 <translation id="6391832066170725637">Nie można znaleźć pliku lub katalogu.</translation>
 <translation id="7393381084163773901">Adres</translation>
@@ -1292,6 +1293,7 @@
 <translation id="8442065444327205563">Dokument gotowy do pokazania.</translation>
 <translation id="236141728043665931">Zawsze blokuj dostęp do mikrofonu</translation>
 <translation id="2307462900900812319">Skonfiguruj sieć</translation>
+<translation id="1704385717926547822">Włącz eksperymentalną obsługę Chromecasta</translation>
 <translation id="5911798608827489036">Wymiana danych z dowolnym komputerem w sieci lokalnej lub internecie</translation>
 <translation id="220858061631308971">Wpisz ten kod PIN na urządzeniu „<ph name="DEVICE_NAME"/>”:</translation>
 <translation id="6263082573641595914">Wersja urzędu certyfikacji firmy Microsoft</translation>
@@ -2889,6 +2891,7 @@
 <translation id="8670869118777164560">Rozszerzenie nie przekierowało żądania sieciowego do <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, bo inne rozszerzenie (<ph name="EXTENSION_NAME"/>) przekierowało je do <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Błąd synchronizacji: aplikacja <ph name="PRODUCT_NAME"/> jest nieaktualna i musi zostać zaktualizowana.</translation>
 <translation id="790040513076446191">Manipulować ustawieniami ochrony prywatności</translation>
+<translation id="7260002739296185724">Włącz użycie AVFoundation do przechwytywania obrazu wideo i monitorowania urządzeń wideo w systemie Mac OS X 10.7 lub nowszym. W przeciwnym razie zostanie użyty moduł QTKit.</translation>
 <translation id="3116361045094675131">Klawiatura brytyjska</translation>
 <translation id="1463985642028688653">blokuj</translation>
 <translation id="1715941336038158809">Nieprawidłowa nazwa użytkownika lub hasło.</translation>
@@ -3747,6 +3750,7 @@
 <translation id="6658571109205370715">Przejrzystość certyfikatu</translation>
 <translation id="8050038245906040378">Podpisywanie kodu handlowego firmy Microsoft</translation>
 <translation id="7299721129597238157">Usuń zakładkę</translation>
+<translation id="7166627725100067582">Włącz eksperymentalną obsługę Chromecasta, która pozwala na odtwarzanie filmów z internetu i sterowanie nimi na urządzeniach Chromecast.</translation>
 <translation id="3031557471081358569">Wybierz elementy do zaimportowania:</translation>
 <translation id="1368832886055348810">Od lewej do prawej</translation>
 <translation id="834106456999819211">Właśnie realizujemy Twoje zamówienie</translation>
diff --git a/chrome/app/resources/generated_resources_pt-BR.xtb b/chrome/app/resources/generated_resources_pt-BR.xtb
index b2923ff..5198e51 100644
--- a/chrome/app/resources/generated_resources_pt-BR.xtb
+++ b/chrome/app/resources/generated_resources_pt-BR.xtb
@@ -304,6 +304,7 @@
 <translation id="7607274158153386860">Solicitar site para tablet</translation>
 <translation id="8028060951694135607">Recuperação de chave da Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Você pode tentar diagnosticar o problema realizando as seguintes etapas: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Ativar o uso das APIs do Mac OS X AVFoundations em vez do QTKit.</translation>
 <translation id="6317369057005134371">Aguardando janela do aplicativo...</translation>
 <translation id="6391832066170725637">Não foi possível encontrar o arquivo ou diretório.</translation>
 <translation id="7393381084163773901">Endereço de correspondência</translation>
@@ -1291,6 +1292,7 @@
 <translation id="8442065444327205563">O documento está pronto para visualização.</translation>
 <translation id="236141728043665931">Sempre bloquear o acesso ao microfone</translation>
 <translation id="2307462900900812319">Configurar rede</translation>
+<translation id="1704385717926547822">Ativar suporte experimental para Chromecast</translation>
 <translation id="5911798608827489036">Trocar dados com qualquer computador da rede local ou Internet</translation>
 <translation id="220858061631308971">Digite este código PIN em &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Versão da autoridade de certificação da Microsoft</translation>
@@ -2895,6 +2897,7 @@
 <translation id="8670869118777164560">Esta extensão falhou ao redirecionar uma solicitação da rede para <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> porque outra extensão (<ph name="EXTENSION_NAME"/>) redirecionou a solicitação para <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Erro de sincronização: <ph name="PRODUCT_NAME"/> está desatualizado e precisa ser atualizado.</translation>
 <translation id="790040513076446191">Manipular as configurações relacionadas à privacidade</translation>
+<translation id="7260002739296185724">Ativar o uso do AVFoundation para captura de vídeo e monitoramento de dispositivos de vídeo no OS X&gt;= 10.7. Se esse uso não for ativado, será usado o QTKit.</translation>
 <translation id="3116361045094675131">Teclado do Reino Unido</translation>
 <translation id="1463985642028688653">bloquear</translation>
 <translation id="1715941336038158809">Nome de usuário ou senha inválida.</translation>
@@ -3756,6 +3759,7 @@
 <translation id="6658571109205370715">Transparência do certificado</translation>
 <translation id="8050038245906040378">Assinatura do código comercial da Microsoft</translation>
 <translation id="7299721129597238157">Excluir favorito</translation>
+<translation id="7166627725100067582">Ativar o suporte experimental do Chromecast, que permite reproduzir e controlar vídeos da Web em dispositivos Chromecast.</translation>
 <translation id="3031557471081358569">Selecione os itens que serão importados:</translation>
 <translation id="1368832886055348810">Da esquerda para a direita</translation>
 <translation id="834106456999819211">Seu pedido está sendo processado</translation>
diff --git a/chrome/app/resources/generated_resources_pt-PT.xtb b/chrome/app/resources/generated_resources_pt-PT.xtb
index 74f2a59..0a46c9e 100644
--- a/chrome/app/resources/generated_resources_pt-PT.xtb
+++ b/chrome/app/resources/generated_resources_pt-PT.xtb
@@ -307,6 +307,7 @@
           Siga estes passos para tentar diagnosticar o problema:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Ativar a utilização de APIs do AVFoundation do Mac OS X como alternativa ao QTKit.</translation>
 <translation id="6317369057005134371">A aguardar janela da aplicação...</translation>
 <translation id="6391832066170725637">Não foi possível localizar o ficheiro ou directório.</translation>
 <translation id="7393381084163773901">Morada</translation>
@@ -1301,6 +1302,7 @@
 <translation id="8442065444327205563">O seu documento está pronto para visualização.</translation>
 <translation id="236141728043665931">Bloquear sempre o acesso ao microfone</translation>
 <translation id="2307462900900812319">Configurar rede</translation>
+<translation id="1704385717926547822">Ativar a compatibilidade experimental do Chromecast</translation>
 <translation id="5911798608827489036">Trocar dados com qualquer computador na rede local ou na Internet</translation>
 <translation id="220858061631308971">Introduza este código PIN no &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Versão de AC Microsoft</translation>
@@ -2905,6 +2907,7 @@
 <translation id="8670869118777164560">Falha desta extensão ao redirecionar um pedido de rede para <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, porque outra extensão (<ph name="EXTENSION_NAME"/>) o redirecionou para <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Erro de Sincronização: o <ph name="PRODUCT_NAME"/> está desatualizado e tem de ser atualizado.</translation>
 <translation id="790040513076446191">Manipular as definições relacionadas com privacidade</translation>
+<translation id="7260002739296185724">Ativar a utilização do AVFoundation para captura de vídeo e monitorização de dispositivos de vídeo no OS X &gt;= 10.7. Em alternativa, será utilizado o QTKit.</translation>
 <translation id="3116361045094675131">Teclado inglês</translation>
 <translation id="1463985642028688653">bloquear</translation>
 <translation id="1715941336038158809">Nome de utilizador ou palavra-passe inválidos.</translation>
@@ -3763,6 +3766,7 @@
 <translation id="6658571109205370715">Transparência do certificado</translation>
 <translation id="8050038245906040378">Assinatura de código comercial Microsoft</translation>
 <translation id="7299721129597238157">Eliminar marcador</translation>
+<translation id="7166627725100067582">Ativar a compatibilidade experimental do Chromecast permitindo reproduzir e controlar vídeos da Web em dispositivos Chromecast.</translation>
 <translation id="3031557471081358569">Seleccione os itens a importar:</translation>
 <translation id="1368832886055348810">Da esquerda para a direita</translation>
 <translation id="834106456999819211">A sua encomenda está a ser processada</translation>
diff --git a/chrome/app/resources/generated_resources_ro.xtb b/chrome/app/resources/generated_resources_ro.xtb
index 9000f6c..a4f5d46 100644
--- a/chrome/app/resources/generated_resources_ro.xtb
+++ b/chrome/app/resources/generated_resources_ro.xtb
@@ -307,6 +307,7 @@
           Puteți încerca să diagnosticați problema efectuând următorii pași:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Activați folosirea API-urilor AV Foundation în Mac OS X, în locul platformei QTKit.</translation>
 <translation id="6317369057005134371">Se așteaptă fereastra aplicației...</translation>
 <translation id="6391832066170725637">Fișierul sau directorul nu a putut fi găsit.</translation>
 <translation id="7393381084163773901">Adresă fizică</translation>
@@ -1303,6 +1304,7 @@
 <translation id="8442065444327205563">Documentul este gata de afișare.</translation>
 <translation id="236141728043665931">Blocați întotdeauna accesul la microfon</translation>
 <translation id="2307462900900812319">Configurați rețeaua</translation>
+<translation id="1704385717926547822">Activați compatibilitatea experimentală pentru Chromecast</translation>
 <translation id="5911798608827489036">Faceți schimb de date cu orice computer din rețeaua locală sau de pe internet</translation>
 <translation id="220858061631308971">Introduceți acest cod PIN pe „<ph name="DEVICE_NAME"/>”:</translation>
 <translation id="6263082573641595914">Versiune CA Microsoft</translation>
@@ -2920,6 +2922,7 @@
 <translation id="8670869118777164560">Această extensie nu a putut redirecționa o solicitare din rețea către <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, deoarece o altă extensie (<ph name="EXTENSION_NAME"/>) a redirecționat-o către <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Eroare de sincronizare: <ph name="PRODUCT_NAME"/> este învechit și trebuie să fie actualizat.</translation>
 <translation id="790040513076446191">Manipulează setările privind confidențialitatea</translation>
+<translation id="7260002739296185724">Activează folosirea platformei AV Foundation pentru înregistrarea video și monitorizarea dispozitivului video în OS X 10.7 și versiunile ulterioare. În celelalte cazuri, se va folosi QTKit.</translation>
 <translation id="3116361045094675131">Tastatură UK</translation>
 <translation id="1463985642028688653">blocați</translation>
 <translation id="1715941336038158809">Nume de utilizator sau parolă nevalidă.</translation>
@@ -3779,6 +3782,7 @@
 <translation id="6658571109205370715">Certificate Transparency</translation>
 <translation id="8050038245906040378">Semnare comercială a codului Microsoft</translation>
 <translation id="7299721129597238157">Ștergeți marcajul</translation>
+<translation id="7166627725100067582">Activează compatibilitatea experimentală pentru Chromecast și vă permite să redați și să controlați videoclipurile de pe web pe dispozitivele Chromecast.</translation>
 <translation id="3031557471081358569">Selectați elementele de importat:</translation>
 <translation id="1368832886055348810">De la stânga la dreapta</translation>
 <translation id="834106456999819211">Comanda se procesează</translation>
diff --git a/chrome/app/resources/generated_resources_ru.xtb b/chrome/app/resources/generated_resources_ru.xtb
index dd9915f..e294439 100644
--- a/chrome/app/resources/generated_resources_ru.xtb
+++ b/chrome/app/resources/generated_resources_ru.xtb
@@ -303,6 +303,7 @@
 <translation id="7607274158153386860">Запросить версию сайта для планшетных ПК</translation>
 <translation id="8028060951694135607">Восстановление ключей Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/>Вы можете попытаться определить причины проблемы, воспользовавшись приведенными ниже инструкциями.<ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Использовать AV Foundation API в среде Mac OS X вместо QTKit</translation>
 <translation id="6317369057005134371">Запуск приложения…</translation>
 <translation id="6391832066170725637">Не удалось найти файл или каталог.</translation>
 <translation id="7393381084163773901">Почтовый адрес</translation>
@@ -1292,6 +1293,7 @@
 <translation id="8442065444327205563">Документ готов к просмотру.</translation>
 <translation id="236141728043665931">Всегда блокировать доступ к микрофону</translation>
 <translation id="2307462900900812319">Настройка сети</translation>
+<translation id="1704385717926547822">Включить экспериментальную поддержку Chromecast</translation>
 <translation id="5911798608827489036">Обмен данными с любыми компьютерами в локальной сети или в Интернете</translation>
 <translation id="220858061631308971">Введите PIN-код для устройства &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Версия ЦС Microsoft</translation>
@@ -2893,6 +2895,7 @@
 <translation id="8670869118777164560">Расширение не может перенаправить сетевой запрос на <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, поскольку другое расширение (<ph name="EXTENSION_NAME"/>) перенаправило его на <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Ошибка синхронизации. Программа <ph name="PRODUCT_NAME"/> устарела, обновите ее.</translation>
 <translation id="790040513076446191">Управление настройками конфиденциальности</translation>
+<translation id="7260002739296185724">Использовать AV Foundation для видеосъемки и мониторинга видеоустройств в Mac OS X 10.7 и более поздних версий (в противном случае будет использоваться QTKit)</translation>
 <translation id="3116361045094675131">Английская раскладка</translation>
 <translation id="1463985642028688653">блокировать</translation>
 <translation id="1715941336038158809">Недействительное имя пользователя или пароль.</translation>
@@ -3750,6 +3753,7 @@
 <translation id="6658571109205370715">Временные метки сертификатов</translation>
 <translation id="8050038245906040378">Подписывание коммерческого кода Microsoft</translation>
 <translation id="7299721129597238157">Удалить закладку</translation>
+<translation id="7166627725100067582">Включить экспериментальную поддержку Chromecast, которая позволяет передавать видео из Интернета на устройства Chromecast</translation>
 <translation id="3031557471081358569">Выберите элементы для импорта:</translation>
 <translation id="1368832886055348810">Слева направо</translation>
 <translation id="834106456999819211">Ваш запрос обрабатывается</translation>
diff --git a/chrome/app/resources/generated_resources_sk.xtb b/chrome/app/resources/generated_resources_sk.xtb
index 396e8b3..a4d33d9 100644
--- a/chrome/app/resources/generated_resources_sk.xtb
+++ b/chrome/app/resources/generated_resources_sk.xtb
@@ -307,6 +307,7 @@
           Problém môžete skúsiť diagnostikovať pomocou nasledujúcich krokov:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Povolenie použitia rozhraní AV Foundation API systému Mac OS X (namiesto rozhrania QTKit).</translation>
 <translation id="6317369057005134371">Čaká sa na okno aplikácie...</translation>
 <translation id="6391832066170725637">Súbor alebo adresár sa nenašiel.</translation>
 <translation id="7393381084163773901">Adresa</translation>
@@ -1302,6 +1303,7 @@
 <translation id="8442065444327205563">Dokument je pripr. na zobraz.</translation>
 <translation id="236141728043665931">Vždy blokovať prístup k mikrofónu</translation>
 <translation id="2307462900900812319">Konfigurovať sieť</translation>
+<translation id="1704385717926547822">Povolenie experimentálnej podpory zariadenia Chromecast</translation>
 <translation id="5911798608827489036">Výmena údajov s ktorýmkoľvek počítačom v miestnej sieti alebo na internete</translation>
 <translation id="220858061631308971">Zadajte tento kód PIN v zariadení „<ph name="DEVICE_NAME"/>“:</translation>
 <translation id="6263082573641595914">Certifikačná autorita spoločnosti Microsoft – verzia</translation>
@@ -2909,6 +2911,7 @@
 <translation id="8670869118777164560">Tomuto rozšíreniu sa nepodarilo presmerovať žiadosť o siete na stránky <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, pretože ju iné rozšírenie (<ph name="EXTENSION_NAME"/>) presmerovalo na stránky <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Chyba synchronizácie: Prehliadač <ph name="PRODUCT_NAME"/> je zastaraný a treba ho aktualizovať.</translation>
 <translation id="790040513076446191">Manipulovať s nastaveniami týkajúcimi sa ochrany osobných údajov</translation>
+<translation id="7260002739296185724">Povoľte použitie rozhraní AV Foundation na zaznamenávanie videa a sledovanie zariadenia prehrávajúceho video v systéme OS X verzie 10.7 alebo novšej. Inak sa použije rozhranie QTKit.</translation>
 <translation id="3116361045094675131">britská klávesnica</translation>
 <translation id="1463985642028688653">blokovať</translation>
 <translation id="1715941336038158809">Neplatné meno používateľa alebo heslo.</translation>
@@ -3770,6 +3773,7 @@
 <translation id="6658571109205370715">Transparentnosť certifikátu</translation>
 <translation id="8050038245906040378">Komerčné podpisovanie kódu Microsoft</translation>
 <translation id="7299721129597238157">Odstrániť záložku</translation>
+<translation id="7166627725100067582">Povolí experimentálnu podporu zariadenia Chromecast, ktorá umožňuje prehrávať a ovládať videá z webu na zariadeniach Chromecast.</translation>
 <translation id="3031557471081358569">Vyberte položky na import:</translation>
 <translation id="1368832886055348810">Zľava doprava</translation>
 <translation id="834106456999819211">Vaša objednávka sa spracováva</translation>
@@ -4541,7 +4545,7 @@
 <translation id="6947969589393588905">Aplikácia <ph name="IDS_SHORT_PRODUCT_NAME"/> je zastaraná</translation>
 <translation id="4784330909746505604">Prezentácia aplikácie PowerPoint</translation>
 <translation id="4345587454538109430">Konfigurovať...</translation>
-<translation id="3255228561559750854">Vyhľadávajte alebo vyslovte kľúčové slovo Ok, Google</translation>
+<translation id="3255228561559750854">Vyhľadávajte alebo vyslovte „Ok, Google“</translation>
 <translation id="8148264977957212129">Metóda vstupu Pinyin</translation>
 <translation id="2288278176040912387">Gramofón</translation>
 <translation id="7772032839648071052">Potvrďte prístupovú frázu</translation>
diff --git a/chrome/app/resources/generated_resources_sl.xtb b/chrome/app/resources/generated_resources_sl.xtb
index 177467f..d797e58 100644
--- a/chrome/app/resources/generated_resources_sl.xtb
+++ b/chrome/app/resources/generated_resources_sl.xtb
@@ -308,6 +308,7 @@
           Težavo lahko poskusite diagnosticirati s tem postopkom:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Omogoči uporabo API-jev za ogrodje AVFoundation v sistemu Mac OS X namesto ogrodja QTKit.</translation>
 <translation id="6317369057005134371">Čakanje na okno aplikacije …</translation>
 <translation id="6391832066170725637">Strežnika ali imenika ni bilo mogoče najti.</translation>
 <translation id="7393381084163773901">Ulični naslov</translation>
@@ -1303,6 +1304,7 @@
 <translation id="8442065444327205563">Dokument je pripravljen za ogled.</translation>
 <translation id="236141728043665931">Vedno prepreči dostop do mikrofona</translation>
 <translation id="2307462900900812319">Konfiguriranje omrežja</translation>
+<translation id="1704385717926547822">Omogoči preskusno podporo za Chromecast</translation>
 <translation id="5911798608827489036">Izmenjava podatkov s katerim koli računalnikom v lokalnem omrežju ali internetu</translation>
 <translation id="220858061631308971">Vnesite PIN za napravo »<ph name="DEVICE_NAME"/>«:</translation>
 <translation id="6263082573641595914">Microsoftova različica overitelja potrdil</translation>
@@ -2919,6 +2921,7 @@
 <translation id="8670869118777164560">Razširitvi ni uspelo preusmeriti omrežne zahteve <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, ker jo je druga razširitev (<ph name="EXTENSION_NAME"/>) preusmerila na cilj <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Napaka pri sinhronizaciji: <ph name="PRODUCT_NAME"/> je zastarel in ga je treba posodobiti.</translation>
 <translation id="790040513076446191">Upravljajte nastavitve zasebnosti</translation>
+<translation id="7260002739296185724">Omogoči uporabo ogrodja AVFoundation za zajemanje videa in nadzor videonaprav v sistemu OS X 10.7 in novejših. Namesto tega bo uporabljeno ogrodje QTKit.</translation>
 <translation id="3116361045094675131">Angleška tipkovnica (Velika Britanija)</translation>
 <translation id="1463985642028688653">blokiraj</translation>
 <translation id="1715941336038158809">Neveljavno uporabniško ime ali geslo.</translation>
@@ -3779,6 +3782,7 @@
 <translation id="6658571109205370715">Preglednost potrdil</translation>
 <translation id="8050038245906040378">Microsoftovo komercialno podpisovanje kode</translation>
 <translation id="7299721129597238157">Izbriši zaznamek</translation>
+<translation id="7166627725100067582">Onemogoči poskusno podporo za Chromecast, ki v napravah Chromecast omogoča predvajanje in nadziranje videoposnetkov iz spleta.</translation>
 <translation id="3031557471081358569">Izberite elemente, ki jih želite uvoziti:</translation>
 <translation id="1368832886055348810">Od leve proti desni</translation>
 <translation id="834106456999819211">Vaše naročilo je v obdelavi</translation>
diff --git a/chrome/app/resources/generated_resources_sr.xtb b/chrome/app/resources/generated_resources_sr.xtb
index 4f1e577..b87106e 100644
--- a/chrome/app/resources/generated_resources_sr.xtb
+++ b/chrome/app/resources/generated_resources_sr.xtb
@@ -308,6 +308,7 @@
           Можете да покушате да утврдите проблем ако пратите следеће кораке:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Омогући коришћење Mac OS X AVFoundation API-ја, уместо QTKit-а.</translation>
 <translation id="6317369057005134371">Чека се прозор апликације...</translation>
 <translation id="6391832066170725637">Није могуће пронаћи датотеку или директоријум.</translation>
 <translation id="7393381084163773901">Адреса</translation>
@@ -1304,6 +1305,7 @@
 <translation id="8442065444327205563">Документ је спреман за приказ.</translation>
 <translation id="236141728043665931">Увек блокирај приступ микрофону</translation>
 <translation id="2307462900900812319">Конфигуриши мрежу</translation>
+<translation id="1704385717926547822">Омогући експерименталну подршку за Chromecast</translation>
 <translation id="5911798608827489036">Размена података са било којим рачунаром на локалној мрежи или интернету</translation>
 <translation id="220858061631308971">Унесите овај PIN кôд на уређају „<ph name="DEVICE_NAME"/>“:</translation>
 <translation id="6263082573641595914">Верзија Microsoft CA</translation>
@@ -2918,6 +2920,7 @@
 <translation id="8670869118777164560">Овај додатак није успео да преусмери захтев мреже на <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> пошто га је други додатак (<ph name="EXTENSION_NAME"/>) преусмерио на <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Грешка при синхронизацији: Производ <ph name="PRODUCT_NAME"/> је застарео и потребно је да га ажурирате.</translation>
 <translation id="790040513076446191">Управљање подешавањима у вези са приватношћу</translation>
+<translation id="7260002739296185724">Омогућите коришћење AVFoundation-а за снимање видео снимака и надгледање видео уређаја на OS X &gt;= 10.7. У супротном користиће се QTKit.</translation>
 <translation id="3116361045094675131">Језик тастатуре: енглески (УК)</translation>
 <translation id="1463985642028688653">блокирај</translation>
 <translation id="1715941336038158809">Неважеће корисничко име или лозинка.</translation>
@@ -3776,6 +3779,7 @@
 <translation id="6658571109205370715">Транспарентност сертификата</translation>
 <translation id="8050038245906040378">Microsoft потписивање комерцијалних кодова</translation>
 <translation id="7299721129597238157">Брисање обележивача</translation>
+<translation id="7166627725100067582">Омогућите експерименталну подршку за Chromecast која омогућава пуштање и контролу видео снимака са веба на Chromecast уређајима.</translation>
 <translation id="3031557471081358569">Изаберите ставке за увоз:</translation>
 <translation id="1368832886055348810">Слева надесно</translation>
 <translation id="834106456999819211">Обрађујемо поруџбину</translation>
diff --git a/chrome/app/resources/generated_resources_sv.xtb b/chrome/app/resources/generated_resources_sv.xtb
index 0cc66c6..fb957ef 100644
--- a/chrome/app/resources/generated_resources_sv.xtb
+++ b/chrome/app/resources/generated_resources_sv.xtb
@@ -312,6 +312,7 @@
           Du kan försöka diagnostisera problemet så här:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Aktivera användning av AV Foundation-API:er för Mac OS X i stället för QTKit.</translation>
 <translation id="6317369057005134371">Väntar på appfönstret ...</translation>
 <translation id="6391832066170725637">Det gick inte att hitta filen eller katalogen.</translation>
 <translation id="7393381084163773901">Gatuadress</translation>
@@ -1308,6 +1309,7 @@
 <translation id="8442065444327205563">Dokumentet är klart att visas.</translation>
 <translation id="236141728043665931">Blockera alltid mikrofonåtkomsten</translation>
 <translation id="2307462900900812319">Konfigurera nätverk</translation>
+<translation id="1704385717926547822">Aktivera experimentellt stöd för Chromecast</translation>
 <translation id="5911798608827489036">Utväxla data med en dator i det lokala nätverket eller via internet</translation>
 <translation id="220858061631308971">Ange den här PIN-koden på <ph name="DEVICE_NAME"/>:</translation>
 <translation id="6263082573641595914">Microsofts version av certifikatutfärdare</translation>
@@ -2916,6 +2918,7 @@
 <translation id="8670869118777164560">Det gick inte att omdirigera nätverksbegäran till <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> eftersom ett annat tillägg (<ph name="EXTENSION_NAME"/>) omdirigerade det till <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Synkroniseringsfel. <ph name="PRODUCT_NAME"/> är inaktuellt och behöver uppdateras.</translation>
 <translation id="790040513076446191">Ändra sekretessrelaterade inställningar</translation>
+<translation id="7260002739296185724">Aktivera användning av AV Foundation för videofilmning och övervakning av videoenhet på OS X &gt;= 10.7. QTKit används annars.</translation>
 <translation id="3116361045094675131">Brittiskt tangentbord</translation>
 <translation id="1463985642028688653">blockera</translation>
 <translation id="1715941336038158809">Ogiltigt användarnamn eller lösenord.</translation>
@@ -3777,6 +3780,7 @@
 <translation id="6658571109205370715">Certifikattransparens</translation>
 <translation id="8050038245906040378">Microsofts kommersiella kodsignering</translation>
 <translation id="7299721129597238157">Ta bort bokmärke</translation>
+<translation id="7166627725100067582">Aktivera experimentellt stöd för Chromecast så att du kan spela upp och styra videor från webben på Chromecast-enheter.</translation>
 <translation id="3031557471081358569">Välj objekt att importera:</translation>
 <translation id="1368832886055348810">Vänster till höger</translation>
 <translation id="834106456999819211">Din beställning bearbetas</translation>
diff --git a/chrome/app/resources/generated_resources_sw.xtb b/chrome/app/resources/generated_resources_sw.xtb
index fba4541..2bb153a 100644
--- a/chrome/app/resources/generated_resources_sw.xtb
+++ b/chrome/app/resources/generated_resources_sw.xtb
@@ -310,6 +310,7 @@
           Unaweza kujaribu kuchunguza tatizo kwa kuchukua hatua zifuatazo:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Washa matumizi ya API za Mac OS X AV Foundation, badala ya QTKit.</translation>
 <translation id="6317369057005134371">Inasubiri dirisha la kutuma maombi...</translation>
 <translation id="6391832066170725637">Faili au saraka haikupatikana.</translation>
 <translation id="7393381084163773901">Anwani ya mtaa</translation>
@@ -1300,6 +1301,7 @@
 <translation id="8442065444327205563">Sasa unaweza kuitazama hati yako.</translation>
 <translation id="236141728043665931">Zuia ufikiaji wa maikrofoni kila wakati</translation>
 <translation id="2307462900900812319">Sanidi mtandao</translation>
+<translation id="1704385717926547822">Washa uwezo wa majaribio wa kutumia Chromecast</translation>
 <translation id="5911798608827489036">Badilisha data kwa kompyuta yoyote kwenye mtandao au intaneti ya karibu</translation>
 <translation id="220858061631308971">Tafadhali ingiza msimbo huu wa PIN kwenye &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Toleo la Mamlaka ya Cheti la Microsoft</translation>
@@ -2912,6 +2914,7 @@
 <translation id="8670869118777164560">Kiendelezi kimeshindwa kuelekeza upya ombi la mtandao kwenye <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> kwa sababu kiendelezi kingine (<ph name="EXTENSION_NAME"/>) kimeelekeza upya kwenye <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Hitilafu ya Kusawazisha: Muda wa <ph name="PRODUCT_NAME"/> umeisha na inahitaji kusasishwa.</translation>
 <translation id="790040513076446191">Weka utakavyo mipangilio husika ya faragha</translation>
+<translation id="7260002739296185724">Washa matumizi ya AVFoundation kwa ajili ya kuchukua picha za video na ufuatiliaji wa kifaa cha video kwenye OS X&gt; = 10.7. QTKit itatumika badala yake.</translation>
 <translation id="3116361045094675131">Kibodi ya Uingereza</translation>
 <translation id="1463985642028688653">zuia</translation>
 <translation id="1715941336038158809">Jina la mtumiaji au nenosiri ni batili.</translation>
@@ -3766,6 +3769,7 @@
 <translation id="6658571109205370715">Uwazi wa cheti</translation>
 <translation id="8050038245906040378">Uwekaji Sahihi kwa Misimbo kwa Biashara kutoka Microsoft</translation>
 <translation id="7299721129597238157">Futa alamisho</translation>
+<translation id="7166627725100067582">Washa uwezo wa majaribio wa kutumia Chromecast unaoruhusu kucheza na kudhibiti video kutoka Wavuti kwenye vifaa vya Chromecast.</translation>
 <translation id="3031557471081358569">Chagua vitu vya kuingiza:</translation>
 <translation id="1368832886055348810">Kushoto hadi Kulia</translation>
 <translation id="834106456999819211">Agizo lako linashughulikiwa</translation>
diff --git a/chrome/app/resources/generated_resources_ta.xtb b/chrome/app/resources/generated_resources_ta.xtb
index 6370309..dd0d825 100644
--- a/chrome/app/resources/generated_resources_ta.xtb
+++ b/chrome/app/resources/generated_resources_ta.xtb
@@ -308,6 +308,7 @@
 <translation id="7607274158153386860">டேப்லெட் தளத்தைக் கோரு</translation>
 <translation id="8028060951694135607">Microsoft Key Recovery</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> நீங்கள் பின்வரும் செயல்பாடுகளைச் செய்வதன் மூலம், சிக்கலைக் கண்டறிய முயலலாம்: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit க்குப் பதிலாக, Mac OS X AVFoundation APIகள் பயன்பாட்டை இயக்கு.</translation>
 <translation id="6317369057005134371">பயன்பாட்டு சாளரத்திற்காகக் காத்திருக்கிறது...</translation>
 <translation id="6391832066170725637">கோப்பு அல்லது கோப்பகத்தைக் கண்டறிய முடியவில்லை.</translation>
 <translation id="7393381084163773901">வீதியின் முகவரி</translation>
@@ -1304,6 +1305,7 @@
 <translation id="8442065444327205563">உங்கள் ஆவணம் பார்ப்பதற்குத் தயாராக உள்ளது.</translation>
 <translation id="236141728043665931">மைக்ரோஃபோன் அணுகலை எப்போதும் தடு</translation>
 <translation id="2307462900900812319">பிணையத்தை உள்ளமை</translation>
+<translation id="1704385717926547822">சோதனை Chromecast ஆதரவை இயக்கு</translation>
 <translation id="5911798608827489036">அகப் பிணையம் அல்லது இணையத்தில் உள்ள எந்த கணினியுடனும் தரவைப் பரிமாறவும்</translation>
 <translation id="220858061631308971">&quot;<ph name="DEVICE_NAME"/>&quot; இல் இந்த PIN குறியீட்டை உள்ளிடுக:</translation>
 <translation id="6263082573641595914">Microsoft CA பதிப்பு</translation>
@@ -2899,6 +2901,7 @@
 <translation id="8670869118777164560">(<ph name="EXTENSION_NAME"/>) என்ற வேறொரு நீட்டிப்பு <ph name="ACTUAL_REDIRECT_DESTINATION"/> க்குத் திசைத்திருப்பப்பட்டதால் பிணைய கோரிக்கையை <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> க்கு திசைத்திருப்புவதில் இந்த நீட்டிப்பு தோல்வியடைந்தது.</translation>
 <translation id="3654092442379740616">ஒத்திசைவுப் பிழை:  <ph name="PRODUCT_NAME"/> காலாவதியானதால், அதைப் புதுப்பிக்க வேண்டும்.</translation>
 <translation id="790040513076446191">தனியுரிமைத் தொடர்பான அமைப்புகளை கையாளலாம்</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7 இல் வீடியோ எடுக்க, வீடியோ சாதனத்தைக் கண்காணிப்பதற்கான AV Foundation பயன்பாட்டை இயக்கவும். மற்ற நிலைகளில், QTKit பயன்படுத்தப்படும்.</translation>
 <translation id="3116361045094675131">யுகே விசைப்பலகை</translation>
 <translation id="1463985642028688653">தடு</translation>
 <translation id="1715941336038158809">செல்லாத பயனர் பெயர் அல்லது கடவுச்சொல்.</translation>
@@ -3750,6 +3753,7 @@
 <translation id="6658571109205370715">சான்றிதழ் வெளிப்படைத்தன்மை</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">புக்மார்க்கை நீக்கு</translation>
+<translation id="7166627725100067582">Chromecast சாதனங்களில் இணையத்திலிருந்து பெறப்படும் வீடியோக்களை இயக்க, கட்டுப்படுத்த அனுமதிக்கும் சோதனை Chromecast ஆதரவை இயக்கவும்.</translation>
 <translation id="3031557471081358569">இறக்குமதிக்கு உருப்படிகளைத் தேர்ந்தெடு</translation>
 <translation id="1368832886055348810">இடமிருந்து வலம்</translation>
 <translation id="834106456999819211">உங்கள் ஆர்டர் செயல்படுத்தப்படுகிறது</translation>
diff --git a/chrome/app/resources/generated_resources_te.xtb b/chrome/app/resources/generated_resources_te.xtb
index 5a61983..e4be3f3 100644
--- a/chrome/app/resources/generated_resources_te.xtb
+++ b/chrome/app/resources/generated_resources_te.xtb
@@ -307,6 +307,7 @@
 <translation id="7607274158153386860">టాబ్లెట్ సైట్‌ను అభ్యర్థించు</translation>
 <translation id="8028060951694135607">Microsoft Key Recovery</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> మీరు క్రింద ఉన్న దశలను పాటించడం ద్వారా సమస్యను కనుగొనడానికి ప్రయత్నించవచ్చు: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKitకి బదులుగా, Mac OS X AVఫౌండేషన్ APIల వినియోగాన్ని ప్రారంభించండి.</translation>
 <translation id="6317369057005134371">అనువర్తన విండో కోసం వేచి ఉంది...</translation>
 <translation id="6391832066170725637">ఫైల్ లేదా డైరెక్టరీ కనుగొనబడలేదు.</translation>
 <translation id="7393381084163773901">వీధి చిరునామా</translation>
@@ -1302,6 +1303,7 @@
 <translation id="8442065444327205563">మీ పత్రం వీక్షించడానికి సిద్ధంగా ఉంది.</translation>
 <translation id="236141728043665931">ఎల్లప్పుడూ మైక్రోఫోన్ ప్రాప్యతను బ్లాక్ చేయి</translation>
 <translation id="2307462900900812319">నెట్‌వర్క్‌ని కాన్ఫిగర్ చేయి</translation>
+<translation id="1704385717926547822">ప్రయోగాత్మక Chromecast మద్దతుని ప్రారంభించండి</translation>
 <translation id="5911798608827489036">స్థానిక నెట్‌వర్క్ లేదా ఇంటర్నెట్‌లో ఏదైనా కంప్యూటర్‌తో డేటాను పరస్పరం మార్చుకోండి</translation>
 <translation id="220858061631308971">దయచేసి ఈ PIN కోడ్‌ని &quot;<ph name="DEVICE_NAME"/>&quot;లో నమోదు చేయండి:</translation>
 <translation id="6263082573641595914">Microsoft CA సంస్కరణ</translation>
@@ -2912,6 +2914,7 @@
 <translation id="8670869118777164560">వేరొక పొడిగింపు (<ph name="EXTENSION_NAME"/>) నెట్‌వర్క్ అభ్యర్థనను <ph name="ACTUAL_REDIRECT_DESTINATION"/>కు దారి మళ్లించినందున ఈ పొడిగింపు దీన్ని <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>కు దారి మళ్లించడంలో విఫలమైంది.</translation>
 <translation id="3654092442379740616">సమకాలీకరణ లోపం:  <ph name="PRODUCT_NAME"/> గడువు ముగిసింది మరియు నవీకరించాల్సి ఉంది.</translation>
 <translation id="790040513076446191">గోప్యత సంబంధ సెట్టింగ్‌లను మ్యానిపులేట్ చేయండి</translation>
+<translation id="7260002739296185724">OS X &gt;= 10.7లో వీడియో క్యాప్చర్ మరియు వీడియో పరికర పర్యవేక్షణ కోసం AVఫౌండేషన్ వినియోగాన్ని ప్రారంభించండి. లేకపోతే QTKit ఉపయోగించబడుతుంది.</translation>
 <translation id="3116361045094675131">UK కీబోర్డ్</translation>
 <translation id="1463985642028688653">బ్లాక్ చేయి</translation>
 <translation id="1715941336038158809">చెల్లని వినియోగదారు పేరు లేదా పాస్‌వర్డ్.</translation>
@@ -3769,6 +3772,7 @@
 <translation id="6658571109205370715">ప్రమాణపత్ర పారదర్శకత</translation>
 <translation id="8050038245906040378">Microsoft Commercial Code Signing</translation>
 <translation id="7299721129597238157">బుక్‌మార్క్‌ను తొలగించు</translation>
+<translation id="7166627725100067582">Chromecast పరికరాల్లో వెబ్ నుండి వీడియోలను ప్లే చేయడానికి మరియు నియంత్రించడానికి అనుమతించే ప్రయోగాత్మక Chromecast మద్దతుని ప్రారంభించండి.</translation>
 <translation id="3031557471081358569">దిగుమతి చెయ్యడానికి ఐటమ్‌లను ఎంచుకోండి:</translation>
 <translation id="1368832886055348810">ఎడమ నుండి కుడికి</translation>
 <translation id="834106456999819211">మీ ఆర్డర్ ప్రాసెస్ చేయబడుతోంది</translation>
diff --git a/chrome/app/resources/generated_resources_th.xtb b/chrome/app/resources/generated_resources_th.xtb
index 03f4bb6..62d9e09 100644
--- a/chrome/app/resources/generated_resources_th.xtb
+++ b/chrome/app/resources/generated_resources_th.xtb
@@ -301,6 +301,7 @@
 <translation id="7607274158153386860">ขอไซต์แท็บเล็ต</translation>
 <translation id="8028060951694135607">การกู้คืนคีย์ของ Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/><ph name="LINE_BREAK"/> คุณอาจพยายามวิเคราะห์ปัญหาได้โดยปฏิบัติตามขั้นตอนต่อไปนี้: <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">เปิดการใช้ API ของ Mac OS X AVFoundation แทน QTKit</translation>
 <translation id="6317369057005134371">กำลังรอหน้าต่างแอปพลิเคชัน...</translation>
 <translation id="6391832066170725637">ไม่พบไฟล์หรือไดเรกทอรี</translation>
 <translation id="7393381084163773901">ที่อยู่</translation>
@@ -1283,6 +1284,7 @@
 <translation id="8442065444327205563">เอกสารของคุณพร้อมดูแล้ว</translation>
 <translation id="236141728043665931">บล็อกการเข้าถึงไมโครโฟนเสมอ</translation>
 <translation id="2307462900900812319">กำหนดค่าเครือข่าย</translation>
+<translation id="1704385717926547822">เปิดใช้การสนับสนุน Chromecast รุ่นทดลอง</translation>
 <translation id="5911798608827489036">แลกเปลี่ยนข้อมูลกับคอมพิวเตอร์ใดๆ ที่อยู่ในเครือข่ายในท้องถิ่นหรืออินเทอร์เน็ต</translation>
 <translation id="220858061631308971">โปรดป้อนรหัส PIN นี้บน &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">รุ่นของผู้มีสิทธิ์ออกใบรับรองของ Microsoft</translation>
@@ -2871,6 +2873,7 @@
 <translation id="8670869118777164560">ส่วนขยายนี้ไม่สามารถเปลี่ยนเส้นทางคำขอเครือข่ายไปยัง <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> เนื่องจากส่วนขยายอื่น (<ph name="EXTENSION_NAME"/>) ได้เปลี่ยนเส้นทางคำขอไปยัง <ph name="ACTUAL_REDIRECT_DESTINATION"/></translation>
 <translation id="3654092442379740616">การซิงค์มีข้อผิดพลาด: <ph name="PRODUCT_NAME"/> เก่าเกินไปและต้องมีการอัปเดต</translation>
 <translation id="790040513076446191">จัดการการตั้งค่าที่เกี่ยวข้องกับความเป็นส่วนตัว</translation>
+<translation id="7260002739296185724">เปิดการใช้ AVFoundation สำหรับการจับภาพวิดีโอและการตรวจสอบอุปกรณ์วิดีโอใน OS X เวอร์ชัน 10.7 หรือสูงกว่า หรือใช้ QTKit แทน</translation>
 <translation id="3116361045094675131">แป้นพิมพ์ภาษาอังกฤษสหราชอาณาจักร</translation>
 <translation id="1463985642028688653">บล็อก</translation>
 <translation id="1715941336038158809">ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง</translation>
@@ -3730,6 +3733,7 @@
 <translation id="6658571109205370715">ความโปร่งใสของใบรับรอง</translation>
 <translation id="8050038245906040378">การรับรองรหัสเชิงพาณิชย์ของ Microsoft</translation>
 <translation id="7299721129597238157">ลบบุ๊กมาร์ก</translation>
+<translation id="7166627725100067582">เปิดใช้การสนับสนุน Chromecast รุ่นทดลองที่อนุญาตให้เล่นและควบคุมวิดีโอจากเว็บบนอุปกรณ์ของ Chromecast</translation>
 <translation id="3031557471081358569">เลือกรายการที่จะนำเข้าต่อไปนี้:</translation>
 <translation id="1368832886055348810">ซ้ายไปขวา</translation>
 <translation id="834106456999819211">การสั่งซื้อของคุณอยู่ระหว่างดำเนินการ</translation>
@@ -5064,7 +5068,7 @@
 <translation id="475088594373173692">ผู้ใช้แรก</translation>
 <translation id="1731911755844941020">กำลังส่งคำขอ...</translation>
 <translation id="7885283703487484916">สั้นมาก</translation>
-<translation id="8371695176452482769">พูดเดี๋ยวนี้</translation>
+<translation id="8371695176452482769">เชิญพูดเลย</translation>
 <translation id="7622116780510618781">แท็บที่เรียงซ้อน</translation>
 <translation id="4361745360460842907">เปิดเป็นแท็บ</translation>
 <translation id="5238278114306905396">แอปพลิเคชัน &quot;<ph name="EXTENSION_NAME"/>&quot; ถูกนำออกโดยอัตโนมัติ</translation>
diff --git a/chrome/app/resources/generated_resources_tr.xtb b/chrome/app/resources/generated_resources_tr.xtb
index 804a968..2b567d4 100644
--- a/chrome/app/resources/generated_resources_tr.xtb
+++ b/chrome/app/resources/generated_resources_tr.xtb
@@ -311,6 +311,7 @@
           Aşağıdaki adımları uygulayarak sorunu teşhis etmeyi deneyebilirsiniz:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">QTKit yerine Mac OS X AVFoundation API'larını kullanmayı etkinleştir</translation>
 <translation id="6317369057005134371">Uygulama penceresi bekleniyor...</translation>
 <translation id="6391832066170725637">Dosya veya dizin bulunamadı.</translation>
 <translation id="7393381084163773901">Adres</translation>
@@ -1306,6 +1307,7 @@
 <translation id="8442065444327205563">Dokümanınız görüntülenmeye hazır.</translation>
 <translation id="236141728043665931">Mikrofon erişimini her zaman engelle</translation>
 <translation id="2307462900900812319">Ağı yapılandır</translation>
+<translation id="1704385717926547822">Deneysel Chromecast desteğini etkinleştir</translation>
 <translation id="5911798608827489036">Yerel ağ veya İnternet üzerindeki herhangi bir bilgisayarla veri değişimi</translation>
 <translation id="220858061631308971">Lütfen &quot;<ph name="DEVICE_NAME"/>&quot; cihazında bu PIN kodunu girin:</translation>
 <translation id="6263082573641595914">Microsoft CA Sürümü</translation>
@@ -2917,6 +2919,7 @@
 <translation id="8670869118777164560">Bu uzantı bir ağ isteğini <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> hedefine yönlendiremedi, çünkü başka bir uzantı (<ph name="EXTENSION_NAME"/>) o isteği <ph name="ACTUAL_REDIRECT_DESTINATION"/> hedefine yönlendirmişti.</translation>
 <translation id="3654092442379740616">Senkronizasyon Hatası: <ph name="PRODUCT_NAME"/> eski ve güncellenmesi gerekiyor.</translation>
 <translation id="790040513076446191">Gizlilikle ilgili ayarları değiştirme</translation>
+<translation id="7260002739296185724">OS X 10.7 veya sonraki sürüm cihazlarda video yakalama ve video cihazı izleme için AVFoundation kullanımını etkinleştirir. Aksi takdirde QTKit kullanılacaktır.</translation>
 <translation id="3116361045094675131">İngilizce klavye</translation>
 <translation id="1463985642028688653">engelle</translation>
 <translation id="1715941336038158809">Geçersiz kullanıcı adı veya şifre.</translation>
@@ -3778,6 +3781,7 @@
 <translation id="6658571109205370715">Sertifika şeffaflığı</translation>
 <translation id="8050038245906040378">Microsoft Ticari Kod İmzalama</translation>
 <translation id="7299721129597238157">Yer işaretini sil</translation>
+<translation id="7166627725100067582">Chromecast cihazlarda web üzerinden video oynatma ve kontrol etme olanağı sağlayan deneysel Chromecast desteğini etkinleştirir.</translation>
 <translation id="3031557471081358569">Alınacak öğeleri seçin:</translation>
 <translation id="1368832886055348810">Soldan Sağa</translation>
 <translation id="834106456999819211">Siparişiniz işleniyor</translation>
diff --git a/chrome/app/resources/generated_resources_uk.xtb b/chrome/app/resources/generated_resources_uk.xtb
index 361d589..a20435a 100644
--- a/chrome/app/resources/generated_resources_uk.xtb
+++ b/chrome/app/resources/generated_resources_uk.xtb
@@ -303,6 +303,7 @@
 <translation id="7607274158153386860">Запитувати сайт планшетного ПК</translation>
 <translation id="8028060951694135607">Відновлення ключів Microsoft</translation>
 <translation id="323962671734198379"><ph name="ERROR_DESCRIPTION_TEXT"/> <ph name="LINE_BREAK"/> Спробуйте діагностувати проблему, виконавши вказані нижче дії. <ph name="LINE_BREAK"/> <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Увімкнути використання API ОС Mac X AVFoundation замість QTKit.</translation>
 <translation id="6317369057005134371">Очікування вікна програми…</translation>
 <translation id="6391832066170725637">Не вдалося знайти файл або каталог.</translation>
 <translation id="7393381084163773901">Адреса</translation>
@@ -1284,6 +1285,7 @@
 <translation id="8442065444327205563">Документ готовий для перегляду</translation>
 <translation id="236141728043665931">Завжди блокувати доступ до мікрофона</translation>
 <translation id="2307462900900812319">Установити параметри мережі</translation>
+<translation id="1704385717926547822">Увімкнути експериментальну підтримку Chromecast</translation>
 <translation id="5911798608827489036">Обмінюватися даними з будь-яким комп’ютером у локальній мережі чи Інтернеті</translation>
 <translation id="220858061631308971">Введіть цей PIN-код на пристрої &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Версія ЦС Microsoft</translation>
@@ -2868,6 +2870,7 @@
 <translation id="8670869118777164560">Це розширення не переспрямувало запит мережі на сторінку <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>, оскільки інше розширення (<ph name="EXTENSION_NAME"/>) переспрямувало його на сторінку <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Помилка синхронізації. Версія <ph name="PRODUCT_NAME"/> застаріла та потребує оновлення.</translation>
 <translation id="790040513076446191">Керувати налаштуваннями, пов’язаними з конфіденційністю</translation>
+<translation id="7260002739296185724">Увімкнути використання AVFoundation для запису відео та відстеження відеопристрою в OС X &gt;= 10.7. В інших випадках використовувати QTKit.</translation>
 <translation id="3116361045094675131">Британська розкладка</translation>
 <translation id="1463985642028688653">заблокувати</translation>
 <translation id="1715941336038158809">Недійсне ім'я користувача чи пароль.</translation>
@@ -3720,6 +3723,7 @@
 <translation id="6658571109205370715">Прозорість сертифіката</translation>
 <translation id="8050038245906040378">Підписування комерційного коду Microsoft</translation>
 <translation id="7299721129597238157">Видалити закладку</translation>
+<translation id="7166627725100067582">Увімкнути експериментальну підтримку Chromecast, яка дає змогу переглядати відео з Інтернету та керувати ними на пристроях Chromecast.</translation>
 <translation id="3031557471081358569">Виберіть елементи для імпорту:</translation>
 <translation id="1368832886055348810">Зліва направо</translation>
 <translation id="834106456999819211">Ваше замовлення обробляється.</translation>
diff --git a/chrome/app/resources/generated_resources_vi.xtb b/chrome/app/resources/generated_resources_vi.xtb
index 992fdc3..c722de1 100644
--- a/chrome/app/resources/generated_resources_vi.xtb
+++ b/chrome/app/resources/generated_resources_vi.xtb
@@ -308,6 +308,7 @@
           Bạn có thể cố gắng chẩn đoán sự cố bằng cách thực hiện theo các bước sau:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">Cho phép sử dụng Mac OS X API AVFoundation, thay vì QTKit.</translation>
 <translation id="6317369057005134371">Đang đợi cửa sổ ứng dụng...</translation>
 <translation id="6391832066170725637">Không thể tìm thấy tệp hay thư mục.</translation>
 <translation id="7393381084163773901">Địa chỉ đường phố</translation>
@@ -1308,6 +1309,7 @@
 <translation id="8442065444327205563">Tài liệu đã sẵn sàng để xem.</translation>
 <translation id="236141728043665931">Luôn chặn quyền truy cập micrô</translation>
 <translation id="2307462900900812319">Định cấu hình mạng</translation>
+<translation id="1704385717926547822">Bật hỗ trợ Chromecast thử nghiệm</translation>
 <translation id="5911798608827489036">Trao đổi dữ liệu với bất kỳ máy tính nào trên mạng cục bộ hoặc internet</translation>
 <translation id="220858061631308971">Vui lòng nhập mã PIN này trên &quot;<ph name="DEVICE_NAME"/>&quot;:</translation>
 <translation id="6263082573641595914">Phiên bản CA của Microsoft</translation>
@@ -2924,6 +2926,7 @@
 <translation id="8670869118777164560">Tiện ích mở rộng này không thể chuyển hướng yêu cầu mạng đến <ph name="ATTEMPTED_REDIRECT_DESTINATION"/> do tiện ích mở rộng khác (<ph name="EXTENSION_NAME"/>) đã chuyển hướng yêu cầu mạng này đến <ph name="ACTUAL_REDIRECT_DESTINATION"/>.</translation>
 <translation id="3654092442379740616">Lỗi đồng bộ hóa:  <ph name="PRODUCT_NAME"/> đã cũ và cần được cập nhật.</translation>
 <translation id="790040513076446191">Thực hiện cài đặt liên quan đến bảo mật</translation>
+<translation id="7260002739296185724">Bật sử dụng AV Foundation để quay video và giám sát thiết bị video trên OS X &gt;= 10.7. Thay vào đó, QTKit sẽ được sử dụng.</translation>
 <translation id="3116361045094675131">Bàn phím Vương quốc Anh</translation>
 <translation id="1463985642028688653">chặn</translation>
 <translation id="1715941336038158809">Tên người dùng hoặc mật khẩu không hợp lệ.</translation>
@@ -3785,6 +3788,7 @@
 <translation id="6658571109205370715">Tính rõ ràng của chứng chỉ</translation>
 <translation id="8050038245906040378">Ký Mã Thương mại của Microsoft</translation>
 <translation id="7299721129597238157">Xóa dấu trang</translation>
+<translation id="7166627725100067582">Bật hỗ trợ Chromecast thử nghiệm cho phép phát và điều khiển video từ Web trên thiết bị Chromecast.</translation>
 <translation id="3031557471081358569">Chọn các mục cần nhập:</translation>
 <translation id="1368832886055348810">Trái sang Phải</translation>
 <translation id="834106456999819211">Đơn đặt hàng của bạn đang được xử lý</translation>
diff --git a/chrome/app/resources/generated_resources_zh-CN.xtb b/chrome/app/resources/generated_resources_zh-CN.xtb
index 8e2cc99..204b86e 100644
--- a/chrome/app/resources/generated_resources_zh-CN.xtb
+++ b/chrome/app/resources/generated_resources_zh-CN.xtb
@@ -303,6 +303,7 @@
           您可以尝试按以下步骤诊断该问题:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">启用Mac OS X AVFoundation API(而不是QTKit)。</translation>
 <translation id="6317369057005134371">等待应用窗口…</translation>
 <translation id="6391832066170725637">无法找到该文件或目录。</translation>
 <translation id="7393381084163773901">街道地址</translation>
@@ -414,7 +415,7 @@
 <translation id="8589311641140863898">实验性扩展程序 API</translation>
 <translation id="8945311516363276943">启用概览模式。</translation>
 <translation id="6990295747880223380">内嵌 HistoryQuickProvider 建议</translation>
-<translation id="631155299877799862">一旦启用,则只要按F4键进入全屏模式,所有非浏览器窗口(例如:应用和任务管理器)均使用扩窗全屏模式。</translation>
+<translation id="631155299877799862">一旦启用,则只要按F4键进入全屏模式,所有非浏览器窗口(例如:应用和任务管理器)均使用沉浸全屏模式。</translation>
 <translation id="869891660844655955">截止日期</translation>
 <translation id="8336153091935557858">昨天<ph name="YESTERDAY_DAYTIME"/></translation>
 <translation id="8642171459927087831">访问令牌</translation>
@@ -778,7 +779,7 @@
 <translation id="3298461240075561421">即使您之前从该网站下载过文件,但该网站可能当时已遭到黑客入侵。您可以日后再尝试下载,而不是恢复此文件。</translation>
 <translation id="9208886416788010685">Adobe Reader 已过期</translation>
 <translation id="1274997165432133392">Cookie及其他网站数据</translation>
-<translation id="5967061606189338140">为非浏览器窗口启用扩窗全屏模式。</translation>
+<translation id="5967061606189338140">为非浏览器窗口启用沉浸全屏模式。</translation>
 <translation id="2945028952025978099">停用 2D 画布渲染的延迟,从而立即完成绘图操作,然后再运行下一个 JavaScript 命令。</translation>
 <translation id="375841316537350618">正在下载代理脚本...</translation>
 <translation id="45400070127195133">启用此选项后,网络应用即可访问仍处于草稿阶段的 WebGL 扩展程序。</translation>
@@ -1280,6 +1281,7 @@
 <translation id="8442065444327205563">您可以查看文档了。</translation>
 <translation id="236141728043665931">始终禁止使用麦克风</translation>
 <translation id="2307462900900812319">配置网络</translation>
+<translation id="1704385717926547822">启用实验性Chromecast支持功能</translation>
 <translation id="5911798608827489036">与本地网络或互联网上的任何计算机交换数据</translation>
 <translation id="220858061631308971">请在“<ph name="DEVICE_NAME"/>”上输入此 PIN 码:</translation>
 <translation id="6263082573641595914">Microsoft CA 版本</translation>
@@ -2878,6 +2880,7 @@
 <translation id="8670869118777164560">此扩展程序无法将该网络请求重新定向到 <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>,因为其他扩展程序(<ph name="EXTENSION_NAME"/>)已将其重新定向到 <ph name="ACTUAL_REDIRECT_DESTINATION"/>。</translation>
 <translation id="3654092442379740616">发生同步错误:<ph name="PRODUCT_NAME"/>已过期,需要更新。</translation>
 <translation id="790040513076446191">管理隐私相关设置</translation>
+<translation id="7260002739296185724">启用后,将使用AVFoundation在OS X 10.7及更高版本的系统上进行视频捕获和视频设备监控,否则将使用QTKit。</translation>
 <translation id="3116361045094675131">英语(英国)键盘</translation>
 <translation id="1463985642028688653">阻止</translation>
 <translation id="1715941336038158809">用户名或密码无效。</translation>
@@ -3732,6 +3735,7 @@
 <translation id="6658571109205370715">证书透明度</translation>
 <translation id="8050038245906040378">Microsoft 商业代码签名</translation>
 <translation id="7299721129597238157">删除书签</translation>
+<translation id="7166627725100067582">启用实验性Chromecast支持功能。此功能可用来在Chromecast设备上播放和控制网络视频。</translation>
 <translation id="3031557471081358569">选择要导入的内容:</translation>
 <translation id="1368832886055348810">从左向右</translation>
 <translation id="834106456999819211">系统正在处理您的订单</translation>
@@ -5178,7 +5182,7 @@
 <translation id="4034042927394659004">降低键盘亮度</translation>
 <translation id="5898154795085152510">该服务器返回了一个无效的客户端证书。错误编号:<ph name="ERROR_NUMBER"/> (<ph name="ERROR_NAME"/>)。</translation>
 <translation id="2704184184447774363">Microsoft 文档签名</translation>
-<translation id="5677928146339483299">已拦截</translation>
+<translation id="5677928146339483299">已屏蔽</translation>
 <translation id="4645676300727003670">保留(&amp;K)</translation>
 <translation id="1646136617204068573">匈牙利语键盘</translation>
 <translation id="3225579507836276307">某个第三方扩展程序已阻止对此网页的访问。</translation>
diff --git a/chrome/app/resources/generated_resources_zh-TW.xtb b/chrome/app/resources/generated_resources_zh-TW.xtb
index df3d9f4..1bdeff9 100644
--- a/chrome/app/resources/generated_resources_zh-TW.xtb
+++ b/chrome/app/resources/generated_resources_zh-TW.xtb
@@ -35,7 +35,7 @@
 <translation id="4121993058175073134">如要傳送淨匯出資料,請在「設定」應用程式中設定您的電子郵件帳戶。</translation>
 <translation id="8099771777867258638">將焦點移至啟動器</translation>
 <translation id="6865313869410766144">自動填入表單資料</translation>
-<translation id="3581034179710640788">此網站的安全性憑證已過期!</translation>
+<translation id="3581034179710640788">這個網站的安全性憑證已過期!</translation>
 <translation id="2825758591930162672">主體的公開金鑰</translation>
 <translation id="8275038454117074363">匯入</translation>
 <translation id="8418445294933751433">顯示為分頁(&amp;S)</translation>
@@ -304,6 +304,7 @@
           您可以執行下列步驟,嘗試診斷問題:
           <ph name="LINE_BREAK"/>
           <ph name="PLATFORM_TEXT"/></translation>
+<translation id="4119224432853805992">使用 Mac OS X AVFoundation API 取代 QTKit。</translation>
 <translation id="6317369057005134371">正在等待應用程式視窗...</translation>
 <translation id="6391832066170725637">找不到檔案或目錄。</translation>
 <translation id="7393381084163773901">街道地址</translation>
@@ -425,7 +426,7 @@
 <translation id="6464076120278668805">停止忽略 autocomplete='off'</translation>
 <translation id="4449935293120761385">關於自動填入</translation>
 <translation id="4624372983866754392">啟用近期的專屬圖示集同步功能。</translation>
-<translation id="4194570336751258953">啟用輕觸點選功能</translation>
+<translation id="4194570336751258953">啟用點按功能</translation>
 <translation id="8489339890656090972">全域加速溢位捲動</translation>
 <translation id="6066742401428748382">存取網頁遭到拒絕</translation>
 <translation id="5111692334209731439">書籤管理員(&amp;B)</translation>
@@ -505,7 +506,7 @@
 <translation id="5453029940327926427">關閉分頁</translation>
 <translation id="949088605431823851">您在哪裡購買這部 HP Chromebook 11?</translation>
 <translation id="9087353528325876418">Web Proxy Auto Discovery 網址</translation>
-<translation id="4801956050125744859">同時保留兩個版本</translation>
+<translation id="4801956050125744859">兩個版本都保留</translation>
 <translation id="3878840326289104869">正在建立受監管的使用者</translation>
 <translation id="406070391919917862">背景應用程式</translation>
 <translation id="7000777920654628318">啟用這項功能時,光柵執行緒會直接寫入 GPU 記憶體。</translation>
@@ -1285,6 +1286,7 @@
 <translation id="8442065444327205563">現在可以瀏覽您的文件了。</translation>
 <translation id="236141728043665931">一律封鎖存取麥克風</translation>
 <translation id="2307462900900812319">設定網路</translation>
+<translation id="1704385717926547822">啟用實驗性 Chromecast 支援</translation>
 <translation id="5911798608827489036">與區域網路或網際網路中的任何電腦交換資料</translation>
 <translation id="220858061631308971">請在「<ph name="DEVICE_NAME"/>」上輸入以下 PIN 碼:</translation>
 <translation id="6263082573641595914">Microsoft CA 版本</translation>
@@ -1602,7 +1604,7 @@
 <translation id="3009779501245596802">索引資料庫</translation>
 <translation id="1404301347395550388">啟用 Encrypted Media Extensions。</translation>
 <translation id="3041612393474885105">憑證資訊</translation>
-<translation id="5023943178135355362">澳洲式捲動方式 - <ph name="BEGIN_LINK"/>瞭解詳情<ph name="END_LINK"/></translation>
+<translation id="5023943178135355362">澳洲式捲動 - <ph name="BEGIN_LINK"/>瞭解詳情<ph name="END_LINK"/></translation>
 <translation id="7378810950367401542">/</translation>
 <translation id="6426039856985689743">停用行動數據</translation>
 <translation id="539643935609409426">如要隱藏這個程式的存取權,您必須使用 [控制台] 中的 [<ph name="CONTROL_PANEL_APPLET_NAME"/>] 以解除安裝此程式。是否要開啟 [<ph name="CONTROL_PANEL_APPLET_NAME"/>]?</translation>
@@ -1979,7 +1981,7 @@
 <translation id="1084538181352409184">檢查您的 Proxy 設定,或是與您的網路管理員聯絡
           確認您的 Proxy 伺服器運作正常。
           <ph name="PLATFORM_TEXT"/></translation>
-<translation id="374530189620960299">網站的安全性憑證不可靠!</translation>
+<translation id="374530189620960299">這個網站的安全性憑證不可靠!</translation>
 <translation id="2560069378501715434">啟用 WebAudio</translation>
 <translation id="4924638091161556692">已修正</translation>
 <translation id="8893928184421379330">很抱歉,系統無法識別 <ph name="DEVICE_LABEL"/> 裝置。</translation>
@@ -2731,7 +2733,7 @@
 <translation id="1361655923249334273">未使用</translation>
 <translation id="4326192123064055915">咖啡</translation>
 <translation id="5434065355175441495">PKCS #1 RSA 加密</translation>
-<translation id="7073704676847768330">這可能不是您在找的網站!</translation>
+<translation id="7073704676847768330">這可能不是您要找的網站!</translation>
 <translation id="8477384620836102176">一般(&amp;G)</translation>
 <translation id="7785791760347294399">應用程式資訊...</translation>
 <translation id="8059417245945632445">檢查裝置 (&amp;I)</translation>
@@ -2889,6 +2891,7 @@
 <translation id="8670869118777164560">這個擴充功能無法將網路要求重新導向至 <ph name="ATTEMPTED_REDIRECT_DESTINATION"/>,因為其他擴充功能 (<ph name="EXTENSION_NAME"/>) 已將要求重新導向至 <ph name="ACTUAL_REDIRECT_DESTINATION"/>。</translation>
 <translation id="3654092442379740616">同步功能發生錯誤:<ph name="PRODUCT_NAME"/> 版本過舊,必須更新。</translation>
 <translation id="790040513076446191">操控隱私權相關設定</translation>
+<translation id="7260002739296185724">在 OS X 10.7 以上版本的作業系統中,使用 AVFoundation 執行視訊擷取和視訊裝置監控;如果不使用 AVFoundation,系統將採用 QTKit 執行這些作業。</translation>
 <translation id="3116361045094675131">英式鍵盤</translation>
 <translation id="1463985642028688653">封鎖</translation>
 <translation id="1715941336038158809">使用者名稱或密碼無效。</translation>
@@ -3748,6 +3751,7 @@
 <translation id="6658571109205370715">Certificate Transparency</translation>
 <translation id="8050038245906040378">Microsoft 商用程式碼簽署</translation>
 <translation id="7299721129597238157">刪除書籤</translation>
+<translation id="7166627725100067582">啟用實驗性 Chromecast 支援,讓您透過 Chromecast 裝置播放及控制線上影片。</translation>
 <translation id="3031557471081358569">選取要匯入的項目:</translation>
 <translation id="1368832886055348810">由左至右</translation>
 <translation id="834106456999819211">系統正在處理您的訂單</translation>
@@ -3857,7 +3861,7 @@
 <translation id="5951823343679007761">未安裝電池</translation>
 <translation id="479555359673800162">停用密碼管理員重新驗證功能</translation>
 <translation id="8569682776816196752">找不到目的地</translation>
-<translation id="1618661679583408047">此伺服器的安全性憑證尚未生效!</translation>
+<translation id="1618661679583408047">這個伺服器的安全憑證尚未生效!</translation>
 <translation id="7039912931802252762">Microsoft 智慧卡登入</translation>
 <translation id="3915280005470252504">語音搜尋</translation>
 <translation id="3752582316358263300">確定...</translation>
diff --git a/chrome/app/resources/google_chrome_strings_am.xtb b/chrome/app/resources/google_chrome_strings_am.xtb
index ffb4069..18025a0 100644
--- a/chrome/app/resources/google_chrome_strings_am.xtb
+++ b/chrome/app/resources/google_chrome_strings_am.xtb
@@ -129,7 +129,7 @@
 <translation id="6145223986912084844">Chrome</translation>
 <translation id="6757767188268205357">አታርመኝ</translation>
 <translation id="2290095356545025170">እርግጠኛ ነዎት Google Chromeን ማራገፍ ይፈልጋሉ?</translation>
-<translation id="7062966102157262887">አንድ ውርድ አሁን በሂደት ላይ ነው። ውርዱን ሰርዘው ከGoogle Chrome መውጣት ይፈልጋሉ?</translation>
+<translation id="7062966102157262887">አንድ ውርድ አሁን በሂደት ላይ ነው። የውርዱን ማስቀረት ከGoogle Chrome መውጣት ይፈልጋሉ?</translation>
 <translation id="4273752058983339720">ኮምፒውተርዎን ሲያስነሱ Google Chrome በራስ-ሰር እንዲጀምር ተዋቅሯል።</translation>
 <translation id="1104959162601287462">ስለ &amp;Chrome ስርዓተ ክወና</translation>
 <translation id="5328989068199000832">Google Chrome Binaries</translation>
@@ -185,7 +185,7 @@
 <translation id="9102715433345326100">ይህ ፋይል ተንኮል-አዘል ነው፣ እና Chrome አግዶታል።</translation>
 <translation id="3170677364322086041">ይህ ጣቢያ ከእንግዲህ የደህንነት እና የመረጋጋት ዝማኔዎችን መቀበል የማይችለውን አገልግሎቱ ያበቃውን Chrome ክፈፍ ተሰኪ እየተጠቀመ ነው። እባክዎ ያራግፉትና ወደ ዘመናዊ አሳሽ ያሻሽሉት።</translation>
 <translation id="8205111949707227942">ከተፈለገ፦ የአጠቃቀም ስታትስቲክስ እና የብልሽት ሪፖርቶች ለGoogle በመላክ Chrome ስርዓተ ክወና የተሻለ እንዲሆን ያግዙ።</translation>
-<translation id="7253415505590551024">ውርዶች አሁን በሂደት ላይ ናቸው። ውርዱን ሰርዘው ከGoogle Chrome መውጣት ይፈልጋሉ?</translation>
+<translation id="7253415505590551024">ውርዶች አሁን በሂደት ላይ ናቸው። የውርዱን ማስቀረት ከGoogle Chrome መውጣት ይፈልጋሉ?</translation>
 <translation id="7196020411877309443">ለምን ይህን አያለሁ?</translation>
 <translation id="2769762047821873045">Google Chrome መነሻ ማሰሻዎ አይደለም።</translation>
 <translation id="4567424176335768812">እንደ <ph name="USER_EMAIL_ADDRESS"/> ሆነው ገብተዋል። አሁን የእርስዎን ዕልባቶች፣ ታሪክ እና ሌሎች ቅንብሮች በመለያ በገቡ ሁሉም መሣሪያዎችዎ ላይ መድረስ ይችላሉ።</translation>
diff --git a/chrome/app/resources/locale_settings_chromiumos.grd b/chrome/app/resources/locale_settings_chromiumos.grd
index a82a6f47..8273021 100644
--- a/chrome/app/resources/locale_settings_chromiumos.grd
+++ b/chrome/app/resources/locale_settings_chromiumos.grd
@@ -184,25 +184,25 @@
 
       <!-- The default value for |WebPreference::pictograph_font_family| -->
       <message name="IDS_PICTOGRAPH_FONT_FAMILY" use_name_for_id="true">
-        Droid Emoji
+        Noto Sans Emoji
       </message>
 
       <!-- The default value for |WebPreference::standard_font_family_map| for
            Arabic script. -->
       <message name="IDS_STANDARD_FONT_FAMILY_ARABIC" use_name_for_id="true">
-        Droid Arabic Naskh
+        Noto Naskh Arabic UI
       </message>
 
       <!-- The default value for |WebPreference::serif_font_family_map| for
            Arabic script. -->
       <message name="IDS_SERIF_FONT_FAMILY_ARABIC" use_name_for_id="true">
-        Droid Arabic Kufi
+        Noto Kufi Arabic
       </message>
 
       <!-- The default value for |WebPreference::sans_serif_font_family_map| for
            Arabic script.  -->
       <message name="IDS_SANS_SERIF_FONT_FAMILY_ARABIC" use_name_for_id="true">
-        Droid Arabic Naskh
+        Noto Naskh Arabic UI
       </message>
 
       <!-- The default value for |WebPreference::standard_font_family_map| for
diff --git a/chrome/app/resources/locale_settings_google_chromeos.grd b/chrome/app/resources/locale_settings_google_chromeos.grd
index 7fa9684..2901289 100644
--- a/chrome/app/resources/locale_settings_google_chromeos.grd
+++ b/chrome/app/resources/locale_settings_google_chromeos.grd
@@ -184,25 +184,25 @@
 
       <!-- The default value for |WebPreference::pictograph_font_family| -->
       <message name="IDS_PICTOGRAPH_FONT_FAMILY" use_name_for_id="true">
-        Droid Emoji
+        Noto Sans Emoji
       </message>
 
       <!-- The default value for |WebPreference::standard_font_family_map| for
            Arabic script. -->
       <message name="IDS_STANDARD_FONT_FAMILY_ARABIC" use_name_for_id="true">
-        Droid Arabic Naskh
+        Noto Naskh Arabic UI
       </message>
 
       <!-- The default value for |WebPreference::serif_font_family_map| for
            Arabic script. -->
       <message name="IDS_SERIF_FONT_FAMILY_ARABIC" use_name_for_id="true">
-        Droid Arabic Kufi
+        Noto Kufi Arabic
       </message>
 
       <!-- The default value for |WebPreference::sans_serif_font_family_map| for
            Arabic script.  -->
       <message name="IDS_SANS_SERIF_FONT_FAMILY_ARABIC" use_name_for_id="true">
-        Droid Arabic Naskh
+        Noto Naskh Arabic UI
       </message>
 
       <!-- The default value for |WebPreference::standard_font_family_map| for
diff --git a/chrome/app/theme/chromium/linux/app_list_256.png b/chrome/app/theme/chromium/linux/app_list_256.png
index eba48b7..a78a3a6 100644
--- a/chrome/app/theme/chromium/linux/app_list_256.png
+++ b/chrome/app/theme/chromium/linux/app_list_256.png
Binary files differ
diff --git a/chrome/app/theme/chromium/linux/app_list_32.png b/chrome/app/theme/chromium/linux/app_list_32.png
index 2470706..d5b26cd 100644
--- a/chrome/app/theme/chromium/linux/app_list_32.png
+++ b/chrome/app/theme/chromium/linux/app_list_32.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/browser_action_highlight.png b/chrome/app/theme/default_100_percent/browser_action_highlight.png
deleted file mode 100644
index 44b74ab..0000000
--- a/chrome/app/theme/default_100_percent/browser_action_highlight.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/app_list_mic_hotword_off.png b/chrome/app/theme/default_100_percent/common/app_list_mic_hotword_off.png
index 658aa61..db78128 100644
--- a/chrome/app/theme/default_100_percent/common/app_list_mic_hotword_off.png
+++ b/chrome/app/theme/default_100_percent/common/app_list_mic_hotword_off.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/avatar_menu_lock.png b/chrome/app/theme/default_100_percent/common/avatar_menu_lock.png
index 207611a..54e6b15 100644
--- a/chrome/app/theme/default_100_percent/common/avatar_menu_lock.png
+++ b/chrome/app/theme/default_100_percent/common/avatar_menu_lock.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/avatar_menu_profile.png b/chrome/app/theme/default_100_percent/common/avatar_menu_profile.png
index a78a6c0..da9c2d2 100644
--- a/chrome/app/theme/default_100_percent/common/avatar_menu_profile.png
+++ b/chrome/app/theme/default_100_percent/common/avatar_menu_profile.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/block_notifier.png b/chrome/app/theme/default_100_percent/common/block_notifier.png
index f8c66fa..d6f1f65 100644
--- a/chrome/app/theme/default_100_percent/common/block_notifier.png
+++ b/chrome/app/theme/default_100_percent/common/block_notifier.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/browser_action_highlight.png b/chrome/app/theme/default_100_percent/common/browser_action_highlight.png
deleted file mode 100644
index 08aea8c..0000000
--- a/chrome/app/theme/default_100_percent/common/browser_action_highlight.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom.png
index f3c1dca..9c6ed43 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_left.png
index 91d471a..f126b23 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_right.png
index 1787e47..a3e954a 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_center.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_center.png
index 2922da4..b1dfd27 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_left.png
index 6b1e602..4f67b18 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_right.png
index 1081740..fecc9da 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top.png
index 84e16e2..ed5954f 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_left.png
index 0cdab7c..ad698e9 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_right.png
index 5a94878..24f7467 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom.png
index a9b1b8f..ecd902d 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_left.png
index 9e8295d..f10ecff 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_right.png
index 39a6cd9..d9b523d 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_center.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_center.png
index dc415bb..a257a26 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_left.png
index 46e739d..2781532 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_right.png
index 19f4f41..e633198 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top.png
index 6d72e05..addccc8 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_left.png
index b00e119..db01e58 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_right.png
index b6db1a5..046411c 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom.png
index 5a19d30..1eec434 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_left.png
index a08ae48..948f48a 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_right.png
index 5b1524c..e644475 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_center.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_center.png
index 9c254b9..7014175 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_left.png
index da2cd48..a53121a 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_right.png
index 9033ae3..cf45d5c 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top.png
index dc1b3fc..5049fb3 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_left.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_left.png
index a3e2c17..3101fac 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_right.png b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_right.png
index 904c980..4621028 100644
--- a/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_brokenssl_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom.png
index 33778bd..824186e 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_left.png
index 2a6d995..446ae65 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_right.png
index 53cc07b..8003f0d 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_center.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_center.png
index b65890d..e78c5a6 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_left.png
index 0243e75..68d6b8f 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_right.png
index 09825c8..b3800e9 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top.png
index aae1102..831cb0e 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_left.png
index e304ebc9..acc5f7d 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_right.png
index 41e7e40..4054a22 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom.png
index 15e4370..9ee492a 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_left.png
index 118994c..6eb4ec4 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_right.png
index 65e0692..ec8435f 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_center.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_center.png
index 298b9d0..ab1082f 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_left.png
index 676a30c..37e4472 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_right.png
index 1407d3d..0744377 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top.png
index 69e3f41..4ad4bbb 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_left.png
index ffe1372..bd7b40c 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_right.png
index 698d28e..d04ab9c 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom.png
index a43bb2f..af5bf2e 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_left.png
index c08bb86..f81496a 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_right.png
index 68f568a..e49052c 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_center.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_center.png
index d191cd8..d5e7688 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_left.png
index 3aa4431..1d909b9 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_right.png
index 0081a95..09d5d52 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top.png
index fe51436..c83ede6 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_left.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_left.png
index 634c00b..ca54fd3 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_right.png b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_right.png
index a84177f..83070e3 100644
--- a/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_extended_validation_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_bottom.png b/chrome/app/theme/default_100_percent/common/chip_hover_bottom.png
index 71a3c24..4441a02 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_hover_bottom_left.png
index 81698ca..3815a83 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_hover_bottom_right.png
index da06861..522299b 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_center.png b/chrome/app/theme/default_100_percent/common/chip_hover_center.png
index a5392a9..2c801b9 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_left.png b/chrome/app/theme/default_100_percent/common/chip_hover_left.png
index a554a86..b8c08ff 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_right.png b/chrome/app/theme/default_100_percent/common/chip_hover_right.png
index db93500..f615715 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_top.png b/chrome/app/theme/default_100_percent/common/chip_hover_top.png
index 273ef48..6e741d0 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_top_left.png b/chrome/app/theme/default_100_percent/common/chip_hover_top_left.png
index 6d8d673..bd7199e 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_hover_top_right.png b/chrome/app/theme/default_100_percent/common/chip_hover_top_right.png
index bef4a5a..073379f 100644
--- a/chrome/app/theme/default_100_percent/common/chip_hover_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom.png
index 3740acf..fbc2d31 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_left.png
index cb07f88..50a1eaf 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_right.png
index 8910c9a..ab2f162 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_center.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_center.png
index b01b105..5333581 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_left.png
index d7872b0..b3466f8 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_right.png
index dced9a0..70513e2 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_top.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_top.png
index 4ac7c3c..76a1f43 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_left.png
index b27c148..fe43486 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_right.png
index 7aebb63..125ba1b 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom.png
index b43b130..980bca4 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_left.png
index b647867..3aaa2ef 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_right.png
index 573b5f6..278fc33 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_center.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_center.png
index bf9bf3c..8bf6cae 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_left.png
index fea641e..3af2ed5 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_right.png
index f89f83d..7b8f697 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_top.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_top.png
index 13993cb..86f772c 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_left.png
index 75d297a..70c16e3 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_right.png
index b86b050..eaf0932 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom.png
index cf1f5e8..16a5ffc 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_left.png
index 940ddf2..89e9a56 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_right.png
index 00a9e53..4f71ea2 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_center.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_center.png
index 5e1cb4e..271f5db 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_left.png
index dcc86d3..0e180b1 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_right.png
index 196a8e5..bffe6ef 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top.png
index 93daa32..8d94209 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_left.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_left.png
index fc12883..44d23f5 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_right.png b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_right.png
index 5539bfd..12e73ae 100644
--- a/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_malware_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_bottom.png b/chrome/app/theme/default_100_percent/common/chip_normal_bottom.png
index 05803b2..babb3f9 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_normal_bottom_left.png
index 2ee7128..4012684 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_normal_bottom_right.png
index bb60813..f435c37 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_center.png b/chrome/app/theme/default_100_percent/common/chip_normal_center.png
index 733ecd2c..138a024 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_left.png b/chrome/app/theme/default_100_percent/common/chip_normal_left.png
index 0346bec..bf497d1 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_right.png b/chrome/app/theme/default_100_percent/common/chip_normal_right.png
index b2dab26..c1d2435 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_top.png b/chrome/app/theme/default_100_percent/common/chip_normal_top.png
index ef3fe5a..d4b261d 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_top_left.png b/chrome/app/theme/default_100_percent/common/chip_normal_top_left.png
index 1379c56..2d74595 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_normal_top_right.png b/chrome/app/theme/default_100_percent/common/chip_normal_top_right.png
index e425fc5..7185e80 100644
--- a/chrome/app/theme/default_100_percent/common/chip_normal_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_bottom.png b/chrome/app/theme/default_100_percent/common/chip_pressed_bottom.png
index 1900a81..c6d08f9 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_bottom.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_left.png b/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_left.png
index 78e1b0f..e24f191 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_right.png b/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_right.png
index 6bd1f65..3fe7267 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_center.png b/chrome/app/theme/default_100_percent/common/chip_pressed_center.png
index 012c1be..0b84bea 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_center.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_left.png b/chrome/app/theme/default_100_percent/common/chip_pressed_left.png
index 507efec..326131b 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_right.png b/chrome/app/theme/default_100_percent/common/chip_pressed_right.png
index 9c3cc8d..caa6db9 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_top.png b/chrome/app/theme/default_100_percent/common/chip_pressed_top.png
index 8f87cdb..fcf3ca5 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_top.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_top_left.png b/chrome/app/theme/default_100_percent/common/chip_pressed_top_left.png
index bef4d3f..21572cf 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_top_left.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/chip_pressed_top_right.png b/chrome/app/theme/default_100_percent/common/chip_pressed_top_right.png
index aa6457d..f8be8b5 100644
--- a/chrome/app/theme/default_100_percent/common/chip_pressed_top_right.png
+++ b/chrome/app/theme/default_100_percent/common/chip_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/controlled_setting_owner.png b/chrome/app/theme/default_100_percent/common/controlled_setting_owner.png
index 21f38d6..bf01075 100644
--- a/chrome/app/theme/default_100_percent/common/controlled_setting_owner.png
+++ b/chrome/app/theme/default_100_percent/common/controlled_setting_owner.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom.png
new file mode 100644
index 0000000..db8f87c
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom_left.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom_left.png
new file mode 100644
index 0000000..1236ae7
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom_right.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom_right.png
new file mode 100644
index 0000000..4e3bdc6
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_center.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_center.png
new file mode 100644
index 0000000..4e9811d
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_left.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_left.png
new file mode 100644
index 0000000..c4f07b9
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_right.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_right.png
new file mode 100644
index 0000000..d38c8b6
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top.png
new file mode 100644
index 0000000..78bb7ac
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top_left.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top_left.png
new file mode 100644
index 0000000..c8b85f8
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top_right.png b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top_right.png
new file mode 100644
index 0000000..3f1fa00
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/developer_mode_highlight_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/edit_button.png b/chrome/app/theme/default_100_percent/common/edit_button.png
index e1842fc..07366e4 100644
--- a/chrome/app/theme/default_100_percent/common/edit_button.png
+++ b/chrome/app/theme/default_100_percent/common/edit_button.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/edit_button_hover.png b/chrome/app/theme/default_100_percent/common/edit_button_hover.png
index 87c24a9..78f279a 100644
--- a/chrome/app/theme/default_100_percent/common/edit_button_hover.png
+++ b/chrome/app/theme/default_100_percent/common/edit_button_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/edit_button_pressed.png b/chrome/app/theme/default_100_percent/common/edit_button_pressed.png
index 9bf08ed..84c8686 100644
--- a/chrome/app/theme/default_100_percent/common/edit_button_pressed.png
+++ b/chrome/app/theme/default_100_percent/common/edit_button_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_3d_blocked.png b/chrome/app/theme/default_100_percent/common/infobar_3d_blocked.png
new file mode 100644
index 0000000..d7f4ea2
--- /dev/null
+++ b/chrome/app/theme/default_100_percent/common/infobar_3d_blocked.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_didyoumean.png b/chrome/app/theme/default_100_percent/common/infobar_alt_nav_url.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/infobar_didyoumean.png
rename to chrome/app/theme/default_100_percent/common/infobar_alt_nav_url.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_incomplete.png b/chrome/app/theme/default_100_percent/common/infobar_incomplete.png
deleted file mode 100644
index ddcdb4a..0000000
--- a/chrome/app/theme/default_100_percent/common/infobar_incomplete.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_lock.png b/chrome/app/theme/default_100_percent/common/infobar_lock.png
deleted file mode 100644
index d749996..0000000
--- a/chrome/app/theme/default_100_percent/common/infobar_lock.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_camera.png b/chrome/app/theme/default_100_percent/common/infobar_media_stream_camera.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/infobar_camera.png
rename to chrome/app/theme/default_100_percent/common/infobar_media_stream_camera.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_microphone.png b/chrome/app/theme/default_100_percent/common/infobar_media_stream_mic.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/infobar_microphone.png
rename to chrome/app/theme/default_100_percent/common/infobar_media_stream_mic.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_plugin.png b/chrome/app/theme/default_100_percent/common/infobar_plugin_install.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/infobar_plugin.png
rename to chrome/app/theme/default_100_percent/common/infobar_plugin_install.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_protected_media_identifier.png b/chrome/app/theme/default_100_percent/common/infobar_protected_media_identifier.png
deleted file mode 100644
index d612379..0000000
--- a/chrome/app/theme/default_100_percent/common/infobar_protected_media_identifier.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_restore.png b/chrome/app/theme/default_100_percent/common/infobar_restore_session.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/infobar_restore.png
rename to chrome/app/theme/default_100_percent/common/infobar_restore_session.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/infobar_savepassword.png b/chrome/app/theme/default_100_percent/common/infobar_save_password.png
similarity index 100%
rename from chrome/app/theme/default_100_percent/common/infobar_savepassword.png
rename to chrome/app/theme/default_100_percent/common/infobar_save_password.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/complete.png b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/complete.png
index 04583f6..8a148dc 100644
--- a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/complete.png
+++ b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/complete.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/family_and_friends.png b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/family_and_friends.png
index d75a56e..75a4601 100644
--- a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/family_and_friends.png
+++ b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/family_and_friends.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/guests.png b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/guests.png
index e1f6a25..9416ead 100644
--- a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/guests.png
+++ b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/guests.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/welcome.png b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/welcome.png
index 3bb2741..48de523 100644
--- a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/welcome.png
+++ b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/welcome.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/your_chrome.png b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/your_chrome.png
index 2ac3709..7be3580 100644
--- a/chrome/app/theme/default_100_percent/common/user_manager_tutorial/your_chrome.png
+++ b/chrome/app/theme/default_100_percent/common/user_manager_tutorial/your_chrome.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/captive_portal_icon.png b/chrome/app/theme/default_100_percent/cros/captive_portal_icon.png
index c0c7b23..5735670 100644
--- a/chrome/app/theme/default_100_percent/cros/captive_portal_icon.png
+++ b/chrome/app/theme/default_100_percent/cros/captive_portal_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/controlled_setting_shared.png b/chrome/app/theme/default_100_percent/cros/controlled_setting_shared.png
index 11b199e..a4976ba 100644
--- a/chrome/app/theme/default_100_percent/cros/controlled_setting_shared.png
+++ b/chrome/app/theme/default_100_percent/cros/controlled_setting_shared.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/globe_icon.png b/chrome/app/theme/default_100_percent/cros/globe_icon.png
index ff4a748..9870e0c 100644
--- a/chrome/app/theme/default_100_percent/cros/globe_icon.png
+++ b/chrome/app/theme/default_100_percent/cros/globe_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/kiosk_app_user_pod_icon.png b/chrome/app/theme/default_100_percent/cros/kiosk_app_user_pod_icon.png
index 96d064f..810db09 100644
--- a/chrome/app/theme/default_100_percent/cros/kiosk_app_user_pod_icon.png
+++ b/chrome/app/theme/default_100_percent/cros/kiosk_app_user_pod_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/notification_drive.png b/chrome/app/theme/default_100_percent/cros/notification_drive.png
index cd1f1a5..ce88f06 100644
--- a/chrome/app/theme/default_100_percent/cros/notification_drive.png
+++ b/chrome/app/theme/default_100_percent/cros/notification_drive.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/cros/secondary_user_settings.png b/chrome/app/theme/default_100_percent/cros/secondary_user_settings.png
index b207eac..686cd1a 100644
--- a/chrome/app/theme/default_100_percent/cros/secondary_user_settings.png
+++ b/chrome/app/theme/default_100_percent/cros/secondary_user_settings.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_autofill.png b/chrome/app/theme/default_100_percent/infobar_autofill.png
deleted file mode 100644
index 60a96ba..0000000
--- a/chrome/app/theme/default_100_percent/infobar_autofill.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_autologin.png b/chrome/app/theme/default_100_percent/infobar_autologin.png
deleted file mode 100644
index 1b1340e..0000000
--- a/chrome/app/theme/default_100_percent/infobar_autologin.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_cookie.png b/chrome/app/theme/default_100_percent/infobar_cookie.png
deleted file mode 100644
index 485b361..0000000
--- a/chrome/app/theme/default_100_percent/infobar_cookie.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_desktop_notifications.png b/chrome/app/theme/default_100_percent/infobar_desktop_notifications.png
deleted file mode 100644
index f836166..0000000
--- a/chrome/app/theme/default_100_percent/infobar_desktop_notifications.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_didyoumean.png b/chrome/app/theme/default_100_percent/infobar_didyoumean.png
deleted file mode 100644
index 0e14574..0000000
--- a/chrome/app/theme/default_100_percent/infobar_didyoumean.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_geolocation.png b/chrome/app/theme/default_100_percent/infobar_geolocation.png
deleted file mode 100644
index 4fd43ea..0000000
--- a/chrome/app/theme/default_100_percent/infobar_geolocation.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_incomplete.png b/chrome/app/theme/default_100_percent/infobar_incomplete.png
deleted file mode 100644
index ddcdb4a..0000000
--- a/chrome/app/theme/default_100_percent/infobar_incomplete.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_lock.png b/chrome/app/theme/default_100_percent/infobar_lock.png
deleted file mode 100644
index d749996..0000000
--- a/chrome/app/theme/default_100_percent/infobar_lock.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_multiple_downloads.png b/chrome/app/theme/default_100_percent/infobar_multiple_downloads.png
deleted file mode 100644
index 3236742..0000000
--- a/chrome/app/theme/default_100_percent/infobar_multiple_downloads.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_plugin.png b/chrome/app/theme/default_100_percent/infobar_plugin.png
deleted file mode 100644
index 2308d97..0000000
--- a/chrome/app/theme/default_100_percent/infobar_plugin.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_plugin_crashed.png b/chrome/app/theme/default_100_percent/infobar_plugin_crashed.png
deleted file mode 100644
index 229c487..0000000
--- a/chrome/app/theme/default_100_percent/infobar_plugin_crashed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_protected_media_identifier.png b/chrome/app/theme/default_100_percent/infobar_protected_media_identifier.png
deleted file mode 100644
index d612379..0000000
--- a/chrome/app/theme/default_100_percent/infobar_protected_media_identifier.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_restore.png b/chrome/app/theme/default_100_percent/infobar_restore.png
deleted file mode 100644
index 4c3ff90..0000000
--- a/chrome/app/theme/default_100_percent/infobar_restore.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_savepassword.png b/chrome/app/theme/default_100_percent/infobar_savepassword.png
deleted file mode 100644
index 1b1340e..0000000
--- a/chrome/app/theme/default_100_percent/infobar_savepassword.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_theme.png b/chrome/app/theme/default_100_percent/infobar_theme.png
deleted file mode 100644
index 3711787..0000000
--- a/chrome/app/theme/default_100_percent/infobar_theme.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobar_translate.png b/chrome/app/theme/default_100_percent/infobar_translate.png
deleted file mode 100644
index 8f7f893..0000000
--- a/chrome/app/theme/default_100_percent/infobar_translate.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_hover.png
deleted file mode 100644
index 3c91507..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_hover.png
deleted file mode 100644
index 9f03813..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_normal.png
deleted file mode 100644
index 8dbac53..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_pressed.png
deleted file mode 100644
index 59d875f..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_left_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_normal.png
deleted file mode 100644
index cee34ab..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_pressed.png
deleted file mode 100644
index 99fa8d1..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_hover.png
deleted file mode 100644
index 695bb90..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_normal.png
deleted file mode 100644
index 3861491..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_pressed.png
deleted file mode 100644
index 824432b..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_bottom_right_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_center_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_center_hover.png
deleted file mode 100644
index 021b925..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_center_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_center_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_center_normal.png
deleted file mode 100644
index 021b925..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_center_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_center_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_center_pressed.png
deleted file mode 100644
index 2be6423..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_center_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_left_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_left_hover.png
deleted file mode 100644
index a1ed196..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_left_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_left_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_left_normal.png
deleted file mode 100644
index b0ed44d..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_left_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_left_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_left_pressed.png
deleted file mode 100644
index f487916..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_left_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_menu_droparrow.png b/chrome/app/theme/default_100_percent/infobarbutton_menu_droparrow.png
deleted file mode 100644
index 40e041c..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_menu_droparrow.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_right_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_right_hover.png
deleted file mode 100644
index 846d7b0..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_right_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_right_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_right_normal.png
deleted file mode 100644
index e073e1c..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_right_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_right_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_right_pressed.png
deleted file mode 100644
index 64873c0..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_right_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_top_hover.png
deleted file mode 100644
index dc06a81..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_left_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_top_left_hover.png
deleted file mode 100644
index 80599fb..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_left_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_left_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_top_left_normal.png
deleted file mode 100644
index 48a8b66..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_left_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_left_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_top_left_pressed.png
deleted file mode 100644
index 617922d..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_left_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_top_normal.png
deleted file mode 100644
index adc52e1..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_top_pressed.png
deleted file mode 100644
index 1fdace6..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_right_hover.png b/chrome/app/theme/default_100_percent/infobarbutton_top_right_hover.png
deleted file mode 100644
index 480eb64..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_right_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_right_normal.png b/chrome/app/theme/default_100_percent/infobarbutton_top_right_normal.png
deleted file mode 100644
index 6352afb..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_right_normal.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/infobarbutton_top_right_pressed.png b/chrome/app/theme/default_100_percent/infobarbutton_top_right_pressed.png
deleted file mode 100644
index 5b23bad..0000000
--- a/chrome/app/theme/default_100_percent/infobarbutton_top_right_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow.png
index 840315f..bd21bcc 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_hover.png
index accea4d..de93ace 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_pressed.png
index accea4d..de93ace 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_arrow_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom.png
index 1dfc861..81e02d6 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_hover.png
index b7bd130..6ebb6fb 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left.png
index 53b6695..60ca697 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png
index 269bdd7..37287cd 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png
index ad610e8..955b904 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_pressed.png
index fa5a489..c1309df 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right.png
index af248bc..72b2418 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png
index 58086e7..83d7a22 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png
index 4851524..bf01c9d 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center.png
index cac2123..224c3d5 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_hover.png
index 2aecf2f..66d75a2 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_pressed.png
index 7e739b0..72fe624 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_center_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left.png
index 04c5b8e..fa39e14 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_hover.png
index 956893a..55e32fa 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_pressed.png
index ba39108..02080a0 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_left_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right.png
index e33ccb5..81d7862 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_hover.png
index 1fa0a46..54327ce 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_pressed.png
index 754ed4d..cfd4a9d 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_right_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom.png
index de4eb2b..7f1e57b 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png
index 0220e83..02827fe 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png
index 5e4fe22..78bc49c 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_center.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_center.png
index ab955e5..d41af86 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_center.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_left.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_left.png
index db82709..4b28927 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_left.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_right.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_right.png
index 462dbf3..6ccee50 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_right.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top.png
index 87c7c59..7a44c7e 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_left.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_left.png
index 02665c3..dc8d416 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_left.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_right.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_right.png
index 920e531..b1fbf95 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_right.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_themed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top.png
index 49c4ae9..117201e 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_hover.png
index cc7ef7e..8fb3ed2 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left.png
index 609184b..f440bf2 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_hover.png
index 96466d0..f797512 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_pressed.png
index 37173a1..7dff89b 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_left_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_pressed.png
index 8214f35..5c2fef1 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right.png
index 9b8e6a2..ea67c95 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_hover.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_hover.png
index 40f3fa9..f690835 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_hover.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_pressed.png b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_pressed.png
index 6b31f25..73d77ba 100644
--- a/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_pressed.png
+++ b/chrome/app/theme/default_100_percent/mac/avatar_button/sign_in_button_top_right_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/app_list_mic_hotword_off.png b/chrome/app/theme/default_200_percent/common/app_list_mic_hotword_off.png
index c07a10f..3282e40 100644
--- a/chrome/app/theme/default_200_percent/common/app_list_mic_hotword_off.png
+++ b/chrome/app/theme/default_200_percent/common/app_list_mic_hotword_off.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/avatar_menu_lock.png b/chrome/app/theme/default_200_percent/common/avatar_menu_lock.png
index d3deef8..ac57c89 100644
--- a/chrome/app/theme/default_200_percent/common/avatar_menu_lock.png
+++ b/chrome/app/theme/default_200_percent/common/avatar_menu_lock.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/avatar_menu_profile.png b/chrome/app/theme/default_200_percent/common/avatar_menu_profile.png
index 2fe0d65..0e9ce60 100644
--- a/chrome/app/theme/default_200_percent/common/avatar_menu_profile.png
+++ b/chrome/app/theme/default_200_percent/common/avatar_menu_profile.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/block_notifier.png b/chrome/app/theme/default_200_percent/common/block_notifier.png
index 2813f1b..6c7b057 100644
--- a/chrome/app/theme/default_200_percent/common/block_notifier.png
+++ b/chrome/app/theme/default_200_percent/common/block_notifier.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/browser_action_highlight.png b/chrome/app/theme/default_200_percent/common/browser_action_highlight.png
deleted file mode 100644
index 9681205..0000000
--- a/chrome/app/theme/default_200_percent/common/browser_action_highlight.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom.png
index 53022ff..5a60cef 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_left.png
index 810bcf5..6dbe235 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_right.png
index 0f0fe64..062d091 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_center.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_center.png
index 4f9307c..79159ed 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_left.png
index 9e7433d..c123993 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_right.png
index 85efef9..5fd13dc 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top.png
index 85c7867..dff4b6d 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_left.png
index c058490..71e6430 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_right.png
index 7ebce59..acdd3bb 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom.png
index 6e51656..cb3e846 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_left.png
index 8293a97..8f83a6e 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_right.png
index 34cb8159..544f711 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_center.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_center.png
index 8df20c3..51895c1 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_left.png
index a8cbf5a..4d0313b 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_right.png
index 3f8b9b0..0fa66ca 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top.png
index 3ba4151..e59b5b9 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_left.png
index 0e740c3..9994e31 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_right.png
index 723ec75..8be6981 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom.png
index 636a78a..6b2439d 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_left.png
index 6dab414..cdbb170 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_right.png
index 8f313fa..af09312 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_center.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_center.png
index faa775d..96f1bdc 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_left.png
index bec798f..a7bbdc3 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_right.png
index 8f60b2d..4c2f655 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top.png
index 0edac0d..74bebb2 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_left.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_left.png
index 794e451..38017c6 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_right.png b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_right.png
index 5c0bad6..a302d3e 100644
--- a/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_brokenssl_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom.png
index 0d14eae..d4180f9 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_left.png
index 7488caf..ec9a176 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_right.png
index be103c9..d99bb8a 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_center.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_center.png
index 27fbb27..4bec84a 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_left.png
index e485d54..28012a8 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_right.png
index fd75437..946decb 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top.png
index bfe3d5b..5906e26 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_left.png
index c80b801..cc5d9ba 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_right.png
index e3d3a59c..3ba4554 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom.png
index 7cba1ae..46eb82f 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_left.png
index 55fe8e4..579a9af 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_right.png
index 5b8698d..7ebba25 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_center.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_center.png
index 2121af9..87511cd 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_left.png
index 20e0557..63788b1 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_right.png
index 7e152d3..90efa6b 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top.png
index c423568..7722f62 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_left.png
index 410713f..559b2f8 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_right.png
index 70dba60..a64ce6f 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom.png
index 469e27b..13fb474 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_left.png
index cee98ab..3da0c7b 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_right.png
index e446993..4b027bc 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_center.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_center.png
index f373ed6..db4ddce 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_left.png
index 2b472fd..2d0494f 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_right.png
index 52eac3c..8183528 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top.png
index 461e371..28e4494 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_left.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_left.png
index 0aefbfb..9876ab1 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_right.png b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_right.png
index 311f1de..bad486c 100644
--- a/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_extended_validation_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_bottom.png b/chrome/app/theme/default_200_percent/common/chip_hover_bottom.png
index 2e4dc0b..a7ed6d3 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_hover_bottom_left.png
index 45db92f..4199099 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_hover_bottom_right.png
index 4b437f0..bff20ad 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_center.png b/chrome/app/theme/default_200_percent/common/chip_hover_center.png
index 31c884f..c473159 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_left.png b/chrome/app/theme/default_200_percent/common/chip_hover_left.png
index 79b0202..c453e2a 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_right.png b/chrome/app/theme/default_200_percent/common/chip_hover_right.png
index e87f710..ce81745 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_top.png b/chrome/app/theme/default_200_percent/common/chip_hover_top.png
index 4f530bd..f397492 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_top_left.png b/chrome/app/theme/default_200_percent/common/chip_hover_top_left.png
index b599218..f400233 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_hover_top_right.png b/chrome/app/theme/default_200_percent/common/chip_hover_top_right.png
index 17a631e..dbc627f 100644
--- a/chrome/app/theme/default_200_percent/common/chip_hover_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom.png
index 9900656..be8717a 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_left.png
index 4c477c3..fef3d5e 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_right.png
index 9a5367b..653a52c 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_center.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_center.png
index de20470..af31be9 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_left.png
index 8258c8f..ba5a648 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_right.png
index 8c46add..d7a7a3f 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_top.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_top.png
index 54bdd61..dda199c 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_left.png
index 419fbf6..026aa28 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_right.png
index 76d395c..f0c70e1 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_hover_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom.png
index 766cc23..6a57725 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_left.png
index 47904a8..94e0daf 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_right.png
index 5bcb3fa..7ecaeba 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_center.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_center.png
index 02ec55b..8a0ec09 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_left.png
index bdf86b8..9e9694d 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_right.png
index 763e1e2..942b472 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_top.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_top.png
index 786b139..4fd3cd8 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_left.png
index 47fd024..3160255 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_right.png
index 3e9ee4b..9e0331e 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom.png
index c73dd70..6d01ab6 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_left.png
index 3f05d13..4e2d045 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_right.png
index 0e95752..adc748e 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_center.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_center.png
index 25a6c4a..d616762 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_left.png
index 6daa18c..e1c1a51 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_right.png
index a45d36b..a50fa87 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top.png
index 2ae6207..90f97f2 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_left.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_left.png
index 8643274..35cbd2b 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_right.png b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_right.png
index aedce39..4c5d69a 100644
--- a/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_malware_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_bottom.png b/chrome/app/theme/default_200_percent/common/chip_normal_bottom.png
index 34c7c7e..3cbb341 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_normal_bottom_left.png
index 4a5f163..7031991 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_normal_bottom_right.png
index 1f96b92..9d6a411 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_center.png b/chrome/app/theme/default_200_percent/common/chip_normal_center.png
index 64f0438..7de9ee8 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_left.png b/chrome/app/theme/default_200_percent/common/chip_normal_left.png
index 7f4823c..df5a0ab 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_right.png b/chrome/app/theme/default_200_percent/common/chip_normal_right.png
index 6847870..b62d3be 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_top.png b/chrome/app/theme/default_200_percent/common/chip_normal_top.png
index b6a20c5..1f40b0b 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_top_left.png b/chrome/app/theme/default_200_percent/common/chip_normal_top_left.png
index 78d5264..eae835e 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_normal_top_right.png b/chrome/app/theme/default_200_percent/common/chip_normal_top_right.png
index a430c95..dc991a8 100644
--- a/chrome/app/theme/default_200_percent/common/chip_normal_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_normal_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_bottom.png b/chrome/app/theme/default_200_percent/common/chip_pressed_bottom.png
index a9a4384..369c991 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_bottom.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_left.png b/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_left.png
index 37c6c9a..73de368 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_right.png b/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_right.png
index 23671cf..e2ef01d 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_center.png b/chrome/app/theme/default_200_percent/common/chip_pressed_center.png
index 880d983..31f62ef 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_center.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_left.png b/chrome/app/theme/default_200_percent/common/chip_pressed_left.png
index 71f1c63..8ae29cb 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_right.png b/chrome/app/theme/default_200_percent/common/chip_pressed_right.png
index 7219fca..cf36d07 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_top.png b/chrome/app/theme/default_200_percent/common/chip_pressed_top.png
index ac49ee9..d5e1230 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_top.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_top_left.png b/chrome/app/theme/default_200_percent/common/chip_pressed_top_left.png
index 19100e2..0bcdd81 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/chip_pressed_top_right.png b/chrome/app/theme/default_200_percent/common/chip_pressed_top_right.png
index c058f88..ee68fd0 100644
--- a/chrome/app/theme/default_200_percent/common/chip_pressed_top_right.png
+++ b/chrome/app/theme/default_200_percent/common/chip_pressed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/controlled_setting_owner.png b/chrome/app/theme/default_200_percent/common/controlled_setting_owner.png
index dfac7d0..7340185 100644
--- a/chrome/app/theme/default_200_percent/common/controlled_setting_owner.png
+++ b/chrome/app/theme/default_200_percent/common/controlled_setting_owner.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom.png
new file mode 100644
index 0000000..5251abc
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom_left.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom_left.png
new file mode 100644
index 0000000..93eec6c
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom_right.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom_right.png
new file mode 100644
index 0000000..2dc3eb7
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_center.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_center.png
new file mode 100644
index 0000000..e35457e
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_left.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_left.png
new file mode 100644
index 0000000..e683c1e
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_right.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_right.png
new file mode 100644
index 0000000..52f8c69
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top.png
new file mode 100644
index 0000000..acf06d1
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top_left.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top_left.png
new file mode 100644
index 0000000..20a0723
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top_right.png b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top_right.png
new file mode 100644
index 0000000..0832d28
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/developer_mode_highlight_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/edit_button.png b/chrome/app/theme/default_200_percent/common/edit_button.png
index 9b8845c..c403a2f 100644
--- a/chrome/app/theme/default_200_percent/common/edit_button.png
+++ b/chrome/app/theme/default_200_percent/common/edit_button.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/edit_button_hover.png b/chrome/app/theme/default_200_percent/common/edit_button_hover.png
index 1771fd5..1b6da86 100644
--- a/chrome/app/theme/default_200_percent/common/edit_button_hover.png
+++ b/chrome/app/theme/default_200_percent/common/edit_button_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/edit_button_pressed.png b/chrome/app/theme/default_200_percent/common/edit_button_pressed.png
index a5e63f6..2169b56 100644
--- a/chrome/app/theme/default_200_percent/common/edit_button_pressed.png
+++ b/chrome/app/theme/default_200_percent/common/edit_button_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/folder.png b/chrome/app/theme/default_200_percent/common/folder.png
index b4daabf..8eed360 100644
--- a/chrome/app/theme/default_200_percent/common/folder.png
+++ b/chrome/app/theme/default_200_percent/common/folder.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_3d_blocked.png b/chrome/app/theme/default_200_percent/common/infobar_3d_blocked.png
new file mode 100644
index 0000000..f74a6b8
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/infobar_3d_blocked.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_alt_nav_url.png b/chrome/app/theme/default_200_percent/common/infobar_alt_nav_url.png
new file mode 100644
index 0000000..547e3a3
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/infobar_alt_nav_url.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_didyoumean.png b/chrome/app/theme/default_200_percent/common/infobar_didyoumean.png
deleted file mode 100644
index 7f0f70d..0000000
--- a/chrome/app/theme/default_200_percent/common/infobar_didyoumean.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_incomplete.png b/chrome/app/theme/default_200_percent/common/infobar_incomplete.png
deleted file mode 100644
index a2f69d1..0000000
--- a/chrome/app/theme/default_200_percent/common/infobar_incomplete.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_lock.png b/chrome/app/theme/default_200_percent/common/infobar_lock.png
deleted file mode 100644
index bf3ef4a..0000000
--- a/chrome/app/theme/default_200_percent/common/infobar_lock.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_camera.png b/chrome/app/theme/default_200_percent/common/infobar_media_stream_camera.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/common/infobar_camera.png
rename to chrome/app/theme/default_200_percent/common/infobar_media_stream_camera.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_microphone.png b/chrome/app/theme/default_200_percent/common/infobar_media_stream_mic.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/common/infobar_microphone.png
rename to chrome/app/theme/default_200_percent/common/infobar_media_stream_mic.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_plugin.png b/chrome/app/theme/default_200_percent/common/infobar_plugin_install.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/common/infobar_plugin.png
rename to chrome/app/theme/default_200_percent/common/infobar_plugin_install.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_protected_media_identifier.png b/chrome/app/theme/default_200_percent/common/infobar_protected_media_identifier.png
deleted file mode 100644
index 4a5ccff..0000000
--- a/chrome/app/theme/default_200_percent/common/infobar_protected_media_identifier.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_restore.png b/chrome/app/theme/default_200_percent/common/infobar_restore_session.png
similarity index 100%
rename from chrome/app/theme/default_200_percent/common/infobar_restore.png
rename to chrome/app/theme/default_200_percent/common/infobar_restore_session.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_save_password.png b/chrome/app/theme/default_200_percent/common/infobar_save_password.png
new file mode 100644
index 0000000..ede1f4f
--- /dev/null
+++ b/chrome/app/theme/default_200_percent/common/infobar_save_password.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/infobar_savepassword.png b/chrome/app/theme/default_200_percent/common/infobar_savepassword.png
deleted file mode 100644
index f578c6c..0000000
--- a/chrome/app/theme/default_200_percent/common/infobar_savepassword.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/omnibox_popup_border_and_shadow_top_left.png b/chrome/app/theme/default_200_percent/common/omnibox_popup_border_and_shadow_top_left.png
index 7aca65c..54ccb7a 100644
--- a/chrome/app/theme/default_200_percent/common/omnibox_popup_border_and_shadow_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/omnibox_popup_border_and_shadow_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/textfield_top_left.png b/chrome/app/theme/default_200_percent/common/textfield_top_left.png
index 434b6dd..4707fbf 100644
--- a/chrome/app/theme/default_200_percent/common/textfield_top_left.png
+++ b/chrome/app/theme/default_200_percent/common/textfield_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/complete.png b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/complete.png
index f528487..3055f86 100644
--- a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/complete.png
+++ b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/complete.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/family_and_friends.png b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/family_and_friends.png
index 7c02196..cb3f225 100644
--- a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/family_and_friends.png
+++ b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/family_and_friends.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/guests.png b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/guests.png
index bb7414d..6f39d7b 100644
--- a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/guests.png
+++ b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/guests.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/welcome.png b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/welcome.png
index 61dbc74..4f072d0 100644
--- a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/welcome.png
+++ b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/welcome.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/your_chrome.png b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/your_chrome.png
index 40c1245..c366f21 100644
--- a/chrome/app/theme/default_200_percent/common/user_manager_tutorial/your_chrome.png
+++ b/chrome/app/theme/default_200_percent/common/user_manager_tutorial/your_chrome.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/captive_portal_icon.png b/chrome/app/theme/default_200_percent/cros/captive_portal_icon.png
index 3506c7c..7537a59 100644
--- a/chrome/app/theme/default_200_percent/cros/captive_portal_icon.png
+++ b/chrome/app/theme/default_200_percent/cros/captive_portal_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/controlled_setting_shared.png b/chrome/app/theme/default_200_percent/cros/controlled_setting_shared.png
index 1d45ae8..afcd55d 100644
--- a/chrome/app/theme/default_200_percent/cros/controlled_setting_shared.png
+++ b/chrome/app/theme/default_200_percent/cros/controlled_setting_shared.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/globe_icon.png b/chrome/app/theme/default_200_percent/cros/globe_icon.png
index dc0307a..2ec845c 100644
--- a/chrome/app/theme/default_200_percent/cros/globe_icon.png
+++ b/chrome/app/theme/default_200_percent/cros/globe_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/kiosk_app_user_pod_icon.png b/chrome/app/theme/default_200_percent/cros/kiosk_app_user_pod_icon.png
index 453634d..ada93a0 100644
--- a/chrome/app/theme/default_200_percent/cros/kiosk_app_user_pod_icon.png
+++ b/chrome/app/theme/default_200_percent/cros/kiosk_app_user_pod_icon.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/notification_drive.png b/chrome/app/theme/default_200_percent/cros/notification_drive.png
index 52183c0..2c1cba4 100644
--- a/chrome/app/theme/default_200_percent/cros/notification_drive.png
+++ b/chrome/app/theme/default_200_percent/cros/notification_drive.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/cros/secondary_user_settings.png b/chrome/app/theme/default_200_percent/cros/secondary_user_settings.png
index 5f3ba6f..8a0e72a 100644
--- a/chrome/app/theme/default_200_percent/cros/secondary_user_settings.png
+++ b/chrome/app/theme/default_200_percent/cros/secondary_user_settings.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_autofill.png b/chrome/app/theme/default_200_percent/infobar_autofill.png
deleted file mode 100644
index e4114c7..0000000
--- a/chrome/app/theme/default_200_percent/infobar_autofill.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_autologin.png b/chrome/app/theme/default_200_percent/infobar_autologin.png
deleted file mode 100644
index 7a957e9..0000000
--- a/chrome/app/theme/default_200_percent/infobar_autologin.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_cookie.png b/chrome/app/theme/default_200_percent/infobar_cookie.png
deleted file mode 100644
index ce7136f..0000000
--- a/chrome/app/theme/default_200_percent/infobar_cookie.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_desktop_notifications.png b/chrome/app/theme/default_200_percent/infobar_desktop_notifications.png
deleted file mode 100644
index ed0faad..0000000
--- a/chrome/app/theme/default_200_percent/infobar_desktop_notifications.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_didyoumean.png b/chrome/app/theme/default_200_percent/infobar_didyoumean.png
deleted file mode 100644
index 7f0f70d..0000000
--- a/chrome/app/theme/default_200_percent/infobar_didyoumean.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_geolocation.png b/chrome/app/theme/default_200_percent/infobar_geolocation.png
deleted file mode 100644
index 5ecf7a1..0000000
--- a/chrome/app/theme/default_200_percent/infobar_geolocation.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_incomplete.png b/chrome/app/theme/default_200_percent/infobar_incomplete.png
deleted file mode 100644
index a2f69d1..0000000
--- a/chrome/app/theme/default_200_percent/infobar_incomplete.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_lock.png b/chrome/app/theme/default_200_percent/infobar_lock.png
deleted file mode 100644
index bf3ef4a..0000000
--- a/chrome/app/theme/default_200_percent/infobar_lock.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_multiple_downloads.png b/chrome/app/theme/default_200_percent/infobar_multiple_downloads.png
deleted file mode 100644
index 0edd17e..0000000
--- a/chrome/app/theme/default_200_percent/infobar_multiple_downloads.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_plugin.png b/chrome/app/theme/default_200_percent/infobar_plugin.png
deleted file mode 100644
index 82c425b..0000000
--- a/chrome/app/theme/default_200_percent/infobar_plugin.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_plugin_crashed.png b/chrome/app/theme/default_200_percent/infobar_plugin_crashed.png
deleted file mode 100644
index e14818b..0000000
--- a/chrome/app/theme/default_200_percent/infobar_plugin_crashed.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_protected_media_identifier.png b/chrome/app/theme/default_200_percent/infobar_protected_media_identifier.png
deleted file mode 100644
index 4a5ccff..0000000
--- a/chrome/app/theme/default_200_percent/infobar_protected_media_identifier.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_restore.png b/chrome/app/theme/default_200_percent/infobar_restore.png
deleted file mode 100644
index f0e8e22..0000000
--- a/chrome/app/theme/default_200_percent/infobar_restore.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_savepassword.png b/chrome/app/theme/default_200_percent/infobar_savepassword.png
deleted file mode 100644
index f578c6c..0000000
--- a/chrome/app/theme/default_200_percent/infobar_savepassword.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_theme.png b/chrome/app/theme/default_200_percent/infobar_theme.png
deleted file mode 100644
index 8889ab7..0000000
--- a/chrome/app/theme/default_200_percent/infobar_theme.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/infobar_translate.png b/chrome/app/theme/default_200_percent/infobar_translate.png
deleted file mode 100644
index f7284c3..0000000
--- a/chrome/app/theme/default_200_percent/infobar_translate.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow.png
index 04c85de..85f53eb 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_hover.png
index e2e0343..faa4410 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_pressed.png
index 0a60d07..b080c3a 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_arrow_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom.png
index 507cbe7..9cb9bac 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_hover.png
index 75a49aa..6729ec7 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left.png
index 8ce5355..09650ad 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png
index 35152c7..78256bd 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png
index 6035e31..32f64e9 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_left_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_pressed.png
index ca1f6ed..e40fd52 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right.png
index ba5784c..a68cc41 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png
index da24c99..ffb79a9 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png
index 870ded2..90bbbe8 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_bottom_right_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center.png
index 8e18d43..c4f38f8 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_hover.png
index 82c3cb2..7b2e615 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_pressed.png
index 5178bbf..6b71353 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_center_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left.png
index e124348..7801232 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_hover.png
index e7183c2..4d215c2 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_pressed.png
index 323c4f2..63ac9d7 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_left_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right.png
index d661ffb..242fbc1 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_hover.png
index db2c054..051da5d 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_pressed.png
index db8fbc5..c9f3107 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_right_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom.png
index d8f5dd0..f162111 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png
index 523d43e..16010f8 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png
index 59961a8..0f568b5 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_bottom_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_center.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_center.png
index 245940c..3941e05 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_center.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_center.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_left.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_left.png
index 37f0331..7e824d6 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_left.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_right.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_right.png
index 206d90e..968514a 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_right.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top.png
index 4432c1b..79f2f44 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_left.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_left.png
index 0e1eab8..a1b464a 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_left.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_right.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_right.png
index 525c34a..7f366b5 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_right.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_themed_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top.png
index bdb310a..810148c 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_hover.png
index 4774bf8..c62034a 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left.png
index fc8893e..6e7e023 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_hover.png
index 53e4535..19a0f7d 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_pressed.png
index 0d66d87..41d206b 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_left_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_pressed.png
index 2212149..a18c867 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_pressed.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right.png
index a85c671..d32023e 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_hover.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_hover.png
index 44f6411..2c05d61 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_hover.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_hover.png
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_pressed.png b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_pressed.png
index 9718783..9fe3050 100644
--- a/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_pressed.png
+++ b/chrome/app/theme/default_200_percent/mac/avatar_button/sign_in_button_top_right_pressed.png
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index 8b73458..e817da9 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -122,13 +122,11 @@
         <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION" file="browser_action.png" />
         <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION_H" file="browser_action_hover.png" />
         <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION_P" file="browser_action_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION_HIGHLIGHT" file="browser_action_highlight.png" />
       </if>
       <if expr="toolkit_views or is_macosx or is_ios">
         <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION" file="common/browser_action_normal.png" />
         <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION_H" file="common/browser_action_hover.png" />
         <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION_P" file="common/browser_action_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTION_HIGHLIGHT" file="common/browser_action_highlight.png" />
       </if>
       <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTIONS_OVERFLOW" file="common/browser_actions_overflow_normal.png" />
       <structure type="chrome_scaled_image" name="IDR_BROWSER_ACTIONS_OVERFLOW_H" file="common/browser_actions_overflow_hover.png" />
@@ -165,6 +163,15 @@
       <if expr="chromeos">
         <structure type="chrome_scaled_image" name="IDR_CROS_DEFAULT_THROBBER" file="cros/default_throbber.png" />
       </if>
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_BOTTOM_LEFT" file="common/developer_mode_highlight_bottom_left.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_BOTTOM" file="common/developer_mode_highlight_bottom.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_BOTTOM_RIGHT" file="common/developer_mode_highlight_bottom_right.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_CENTER" file="common/developer_mode_highlight_center.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_LEFT" file="common/developer_mode_highlight_left.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_RIGHT" file="common/developer_mode_highlight_right.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_TOP_LEFT" file="common/developer_mode_highlight_top_left.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_TOP" file="common/developer_mode_highlight_top.png" />
+      <structure type="chrome_scaled_image" name="IDR_DEVELOPER_MODE_HIGHLIGHT_TOP_RIGHT" file="common/developer_mode_highlight_top_right.png" />
       <structure type="chrome_scaled_image" name="IDR_DOCK_HIGH" file="dock_tab_high.png" />
       <structure type="chrome_scaled_image" name="IDR_DOCK_MAX" file="dock_tab_max.png" />
       <structure type="chrome_scaled_image" name="IDR_DOCK_WIDE" file="dock_tab_wide.png" />
@@ -214,9 +221,6 @@
       <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_BACKGROUND_32" file="download_progress_background32.png" />
       <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_16" file="download_progress_foreground16.png" />
       <structure type="chrome_scaled_image" name="IDR_DOWNLOAD_PROGRESS_FOREGROUND_32" file="download_progress_foreground32.png" />
-      <if expr="is_android">
-        <structure type="chrome_scaled_image" name="IDR_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_ICON" file="infobar_protected_media_identifier.png" />
-      </if>
       <if expr="chromeos">
         <structure type="chrome_scaled_image" name="IDR_ENROLL_FAILURE" file="enroll_failure.png" />
         <structure type="chrome_scaled_image" name="IDR_ENROLL_SUCCESS" file="enroll_success.png" />
@@ -309,7 +313,6 @@
       </if>
       <structure type="chrome_scaled_image" name="IDR_FROZEN_TAB_ICON" file="frozen_tab.png" />
       <structure type="chrome_scaled_image" name="IDR_FULLSCREEN_MENU_BUTTON" file="fullscreen_menu_button.png" />
-      <structure type="chrome_scaled_image" name="IDR_GEOLOCATION_INFOBAR_ICON" file="infobar_geolocation.png" />
       <structure type="chrome_scaled_image" name="IDR_HELP_MENU" file="common/help_16.png" />
       <structure type="chrome_scaled_image" name="IDR_HISTORY_FAVICON" file="common/favicon_history.png" />
       <if expr="not toolkit_views and not is_macosx and not is_ios">
@@ -328,10 +331,10 @@
       </if>
       <if expr="not is_android and not is_ios">
         <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_ADD_USER" file="common/icon_add_user.png" />
-        <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_ADD_USER_WHITE" file="common/icon_add_user_white.png" />
         <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_BROWSE_GUEST" file="common/icon_browse_as_guest.png" />
-        <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_BROWSE_GUEST_WHITE" file="common/icon_browse_as_guest_white.png" />
         <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_LOCKED" file="common/icon_locked.png" />
+        <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_MENU_LOCK" file="common/avatar_menu_lock.png" />
+        <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_MENU_AVATAR" file="common/avatar_menu_profile.png" />
         <structure type="chrome_scaled_image"
         name="IDR_ICON_PROFILES_EDIT_HOVER" file="common/edit_button_hover.png" />
         <structure type="chrome_scaled_image" name="IDR_ICON_PROFILES_EDIT_PRESSED" file="common/edit_button_pressed.png" />
@@ -359,51 +362,59 @@
       </if>
       <structure type="chrome_scaled_image" name="IDR_INFO" file="info_small.png" />
       <if expr="toolkit_views">
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_BOTTOM" file="infobarbutton_bottom_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_BOTTOM_LEFT" file="infobarbutton_bottom_left_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_BOTTOM_RIGHT" file="infobarbutton_bottom_right_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_CENTER" file="infobarbutton_center_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_LEFT" file="infobarbutton_left_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_RIGHT" file="infobarbutton_right_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_TOP" file="infobarbutton_top_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_TOP_LEFT" file="infobarbutton_top_left_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_TOP_RIGHT" file="infobarbutton_top_right_hover.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_MENU_DROPARROW" file="infobarbutton_menu_droparrow.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_BOTTOM" file="infobarbutton_bottom_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_BOTTOM_LEFT" file="infobarbutton_bottom_left_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_BOTTOM_RIGHT" file="infobarbutton_bottom_right_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_CENTER" file="infobarbutton_center_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_LEFT" file="infobarbutton_left_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_RIGHT" file="infobarbutton_right_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_TOP" file="infobarbutton_top_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_TOP_LEFT" file="infobarbutton_top_left_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_TOP_RIGHT" file="infobarbutton_top_right_normal.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_BOTTOM" file="infobarbutton_bottom_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_BOTTOM_LEFT" file="infobarbutton_bottom_left_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_BOTTOM_RIGHT" file="infobarbutton_bottom_right_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_CENTER" file="infobarbutton_center_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_LEFT" file="infobarbutton_left_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_RIGHT" file="infobarbutton_right_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_TOP" file="infobarbutton_top_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_TOP_LEFT" file="infobarbutton_top_left_pressed.png" />
-        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_TOP_RIGHT" file="infobarbutton_top_right_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_BOTTOM" file="common/infobarbutton_bottom_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_BOTTOM_LEFT" file="common/infobarbutton_bottom_left_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_BOTTOM_RIGHT" file="common/infobarbutton_bottom_right_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_CENTER" file="common/infobarbutton_center_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_LEFT" file="common/infobarbutton_left_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_RIGHT" file="common/infobarbutton_right_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_TOP" file="common/infobarbutton_top_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_TOP_LEFT" file="common/infobarbutton_top_left_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_HOVER_TOP_RIGHT" file="common/infobarbutton_top_right_hover.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_MENU_DROPARROW" file="common/infobarbutton_menu_droparrow.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_BOTTOM" file="common/infobarbutton_bottom_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_BOTTOM_LEFT" file="common/infobarbutton_bottom_left_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_BOTTOM_RIGHT" file="common/infobarbutton_bottom_right_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_CENTER" file="common/infobarbutton_center_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_LEFT" file="common/infobarbutton_left_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_RIGHT" file="common/infobarbutton_right_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_TOP" file="common/infobarbutton_top_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_TOP_LEFT" file="common/infobarbutton_top_left_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_NORMAL_TOP_RIGHT" file="common/infobarbutton_top_right_normal.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_BOTTOM" file="common/infobarbutton_bottom_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_BOTTOM_LEFT" file="common/infobarbutton_bottom_left_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_BOTTOM_RIGHT" file="common/infobarbutton_bottom_right_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_CENTER" file="common/infobarbutton_center_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_LEFT" file="common/infobarbutton_left_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_RIGHT" file="common/infobarbutton_right_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_TOP" file="common/infobarbutton_top_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_TOP_LEFT" file="common/infobarbutton_top_left_pressed.png" />
+        <structure type="chrome_scaled_image" name="IDR_INFOBARBUTTON_PRESSED_TOP_RIGHT" file="common/infobarbutton_top_right_pressed.png" />
       </if>
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_ALT_NAV_URL" file="infobar_didyoumean.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_AUTOFILL" file="infobar_autofill.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_AUTOLOGIN" file="infobar_autologin.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_COOKIE" file="infobar_cookie.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_DESKTOP_NOTIFICATIONS" file="infobar_desktop_notifications.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_INCOMPLETE" file="infobar_incomplete.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MEDIA_STREAM_CAMERA" file="common/infobar_camera.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MIDI_SYSEX" file="common/infobar_midi.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MEDIA_STREAM_MIC" file="common/infobar_microphone.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MULTIPLE_DOWNLOADS" file="infobar_multiple_downloads.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_PLUGIN_CRASHED" file="infobar_plugin_crashed.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_PLUGIN_INSTALL" file="infobar_plugin.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_RESTORE_SESSION" file="infobar_restore.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_SAVE_PASSWORD" file="infobar_savepassword.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_THEME" file="infobar_theme.png" />
-      <structure type="chrome_scaled_image" name="IDR_INFOBAR_TRANSLATE" file="infobar_translate.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_3D_BLOCKED" file="common/infobar_3d_blocked.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_ALT_NAV_URL" file="common/infobar_alt_nav_url.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_AUTOFILL" file="common/infobar_autofill.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_AUTOLOGIN" file="common/infobar_autologin.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_COOKIE" file="common/infobar_cookie.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_DESKTOP_NOTIFICATIONS" file="common/infobar_desktop_notifications.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_GEOLOCATION" file="common/infobar_geolocation.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MEDIA_STREAM_CAMERA" file="common/infobar_media_stream_camera.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MEDIA_STREAM_MIC" file="common/infobar_media_stream_mic.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MIDI" file="common/infobar_midi.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_MULTIPLE_DOWNLOADS" file="common/infobar_multiple_downloads.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_PLUGIN_CRASHED" file="common/infobar_plugin_crashed.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_PLUGIN_INSTALL" file="common/infobar_plugin_install.png" />
+      <if expr="is_android">
+        <!-- The actual image here is not used; this line only exists to
+             reserve a valid ID, so the Android code can map it to the
+             appropriate Android resource.  So we just refer to a random
+             image. -->
+        <structure type="chrome_scaled_image" name="IDR_INFOBAR_PROTECTED_MEDIA_IDENTIFIER" file="common/app_default_icon.png" />
+      </if>
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_RESTORE_SESSION" file="common/infobar_restore_session.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_SAVE_PASSWORD" file="common/infobar_save_password.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_THEME" file="common/infobar_theme.png" />
+      <structure type="chrome_scaled_image" name="IDR_INFOBAR_TRANSLATE" file="common/infobar_translate.png" />
       <structure type="chrome_scaled_image" name="IDR_INFOBAR_WARNING" file="common/infobar_warning.png" />
       <structure type="chrome_scaled_image" name="IDR_INPUT_ALERT" file="common/input_alert.png" />
       <structure type="chrome_scaled_image" name="IDR_INPUT_ALERT_MENU" file="common/input_alert_menu.png" />
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 1286def..39be0d7 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -40,6 +40,7 @@
   "+components/webdata/common",
   "+content/public/browser",
   "+content/test/net",
+  "+courgette",
   "+device/bluetooth",
   "+device/media_transfer_protocol",
   "+extensions/browser",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b3abe89..5a1f67a 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -407,9 +407,11 @@
 // comment to the end of the feature name, like so:
 //   "my-special-feature",  // FLAGS:RECORD_UMA
 //
-// After doing that, run //tools/metrics/actions/extract_actions.py (see
-// instructions at the top of that file for details) to update the
-// chromeactions.txt file, which will enable UMA to record your feature flag.
+// After doing that, run
+//   tools/metrics/actions/extract_actions.py
+// to add the metric to actions.xml (which will enable UMA to record your
+// feature flag), then update the <owner>s and <description> sections. Make sure
+// to include the actions.xml file when you upload your code for review!
 //
 // After your feature has shipped under a flag, you can locate the metrics under
 // the action name AboutFlags_internal-action-name. Actions are recorded once
@@ -568,15 +570,6 @@
   },
 #endif
 #if defined(OS_ANDROID)
-#if defined(ARCH_CPU_X86)
-  {
-      "enable-webaudio",
-      IDS_FLAGS_ENABLE_WEBAUDIO_NAME,
-      IDS_FLAGS_ENABLE_WEBAUDIO_DESCRIPTION,
-      kOsAndroid,
-      SINGLE_VALUE_TYPE(switches::kEnableWebAudio)
-  },
-#else
   {
     "disable-webaudio",
     IDS_FLAGS_DISABLE_WEBAUDIO_NAME,
@@ -585,7 +578,6 @@
     SINGLE_VALUE_TYPE(switches::kDisableWebAudio)
   },
 #endif
-#endif
   {
     "fixed-position-creates-stacking-context",
     IDS_FLAGS_FIXED_POSITION_CREATES_STACKING_CONTEXT_NAME,
@@ -762,6 +754,13 @@
     SINGLE_VALUE_TYPE(switches::kSavePageAsMHTML)
   },
   {
+    "enable-autologin",
+    IDS_FLAGS_ENABLE_AUTOLOGIN_NAME,
+    IDS_FLAGS_ENABLE_AUTOLOGIN_DESCRIPTION,
+    kOsMac | kOsWin | kOsLinux,
+    SINGLE_VALUE_TYPE(switches::kEnableAutologin)
+  },
+  {
     "enable-quic",
     IDS_FLAGS_ENABLE_QUIC_NAME,
     IDS_FLAGS_ENABLE_QUIC_DESCRIPTION,
@@ -1096,13 +1095,6 @@
     kOsCrOS,
     SINGLE_VALUE_TYPE(ash::switches::kAshEnableTouchViewTesting),
   },
-  {
-    "ash-enable-brightness-control",
-    IDS_FLAGS_ASH_ENABLE_BRIGHTNESS_CONTROL_NAME,
-    IDS_FLAGS_ASH_ENABLE_BRIGHTNESS_CONTROL_DESCRIPTION,
-    kOsCrOS,
-    SINGLE_VALUE_TYPE(ash::switches::kAshEnableBrightnessControl)
-  },
 #endif
 #if defined(OS_CHROMEOS)
   {
@@ -1342,12 +1334,20 @@
     kOsCrOS,
     SINGLE_VALUE_TYPE(keyboard::switches::kEnableSwipeSelection)
   },
+  {
+    "enable-input-view",
+    IDS_FLAGS_ENABLE_INPUT_VIEW_NAME,
+    IDS_FLAGS_ENABLE_INPUT_VIEW_DESCRIPTION,
+    kOsCrOS,
+    ENABLE_DISABLE_VALUE_TYPE(keyboard::switches::kEnableInputView,
+                              keyboard::switches::kDisableInputView)
+  },
 #endif
   {
     "enable-simple-cache-backend",
     IDS_FLAGS_ENABLE_SIMPLE_CACHE_BACKEND_NAME,
     IDS_FLAGS_ENABLE_SIMPLE_CACHE_BACKEND_DESCRIPTION,
-    kOsAll,
+    kOsWin | kOsMac | kOsLinux | kOsCrOS,
     MULTI_VALUE_TYPE(kSimpleCacheBackendChoices)
   },
   {
@@ -1482,6 +1482,13 @@
     SINGLE_VALUE_TYPE(switches::kNewProfileManagement)
   },
   {
+    "enable-fast-user-switching",
+    IDS_FLAGS_ENABLE_FAST_USER_SWITCHING_NAME,
+    IDS_FLAGS_ENABLE_FAST_USER_SWITCHING_DESCRIPTION,
+    kOsMac | kOsWin | kOsLinux,
+    SINGLE_VALUE_TYPE(switches::kFastUserSwitching)
+  },
+  {
     "enable-web-based-signin",
     IDS_FLAGS_ENABLE_WEB_BASED_SIGNIN_NAME,
     IDS_FLAGS_ENABLE_WEB_BASED_SIGNIN_DESCRIPTION,
@@ -1503,13 +1510,6 @@
     SINGLE_VALUE_TYPE(switches::kResetAppListInstallState)
   },
 #if defined(ENABLE_APP_LIST)
-  {
-    "enable-app-launcher-start-page",
-    IDS_FLAGS_ENABLE_APP_LIST_START_PAGE_NAME,
-    IDS_FLAGS_ENABLE_APP_LIST_START_PAGE_DESCRIPTION,
-    kOsWin | kOsCrOS,
-    SINGLE_VALUE_TYPE(switches::kShowAppListStartPage)
-  },
 #if defined(OS_LINUX)
   {
     // This is compiled out on non-Linux platforms because otherwise it would be
@@ -1773,7 +1773,8 @@
     IDS_FLAGS_ENABLE_FAST_TEXT_AUTOSIZING_NAME,
     IDS_FLAGS_ENABLE_FAST_TEXT_AUTOSIZING_DESCRIPTION,
     kOsAndroid,
-    SINGLE_VALUE_TYPE(switches::kEnableFastTextAutosizing)
+    ENABLE_DISABLE_VALUE_TYPE(switches::kEnableFastTextAutosizing,
+                              switches::kDisableFastTextAutosizing)
   },
   {
     "disable-cast",
@@ -1817,9 +1818,25 @@
     "bleeding-edge-renderer-mode",
     IDS_FLAGS_BLEEDING_RENDERER_NAME,
     IDS_FLAGS_BLEEDING_RENDERER_DESCRIPTION,
-    kOsAll,
+    kOsAndroid,
     SINGLE_VALUE_TYPE(switches::kEnableBleedingEdgeRenderingFastPaths)
   },
+  {
+    "enable-settings-window",
+    IDS_FLAGS_ENABLE_SETTINGS_WINDOW_NAME,
+    IDS_FLAGS_ENABLE_SETTINGS_WINDOW_DESCRIPTION,
+    kOsDesktop,
+    SINGLE_VALUE_TYPE(switches::kEnableSettingsWindow)
+  },
+#if defined(OS_ANDROID)
+  {
+    "enable-instant-search-clicks",
+    IDS_FLAGS_ENABLE_INSTANT_SEARCH_CLICKS_NAME,
+    IDS_FLAGS_ENABLE_INSTANT_SEARCH_CLICKS_DESCRIPTION,
+    kOsAndroid,
+    SINGLE_VALUE_TYPE(switches::kEnableInstantSearchClicks)
+  },
+#endif
 };
 
 const Experiment* experiments = kExperiments;
diff --git a/chrome/browser/accessibility/accessibility_extension_apitest.cc b/chrome/browser/accessibility/accessibility_extension_apitest.cc
index 00a1013..10b55c2 100644
--- a/chrome/browser/accessibility/accessibility_extension_apitest.cc
+++ b/chrome/browser/accessibility/accessibility_extension_apitest.cc
@@ -12,8 +12,8 @@
 #include "chrome/test/base/test_switches.h"
 #include "extensions/common/switches.h"
 
-// Times out on win asan, http://crbug.com/166026
-#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
+// Times out on win syzyasan, http://crbug.com/166026
+#if defined(SYZYASAN)
 #define MAYBE_GetAlertsForTab DISABLED_GetAlertsForTab
 #else
 #define MAYBE_GetAlertsForTab GetAlertsForTab
diff --git a/chrome/browser/android/banners/app_banner_manager.cc b/chrome/browser/android/banners/app_banner_manager.cc
index aafc174..0348807 100644
--- a/chrome/browser/android/banners/app_banner_manager.cc
+++ b/chrome/browser/android/banners/app_banner_manager.cc
@@ -7,7 +7,10 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/command_line.h"
+#include "base/metrics/histogram.h"
+#include "chrome/browser/android/banners/app_banner_metrics_ids.h"
 #include "chrome/browser/android/banners/app_banner_settings_helper.h"
+#include "chrome/browser/android/banners/app_banner_utilities.h"
 #include "chrome/browser/bitmap_fetcher.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
@@ -25,6 +28,8 @@
 const char kBannerTag[] = "google-play-id";
 }
 
+namespace banners {
+
 AppBannerManager::AppBannerManager(JNIEnv* env, jobject obj)
     : MetaTagObserver(kBannerTag),
       weak_java_banner_view_manager_(env, obj) {}
@@ -64,7 +69,7 @@
   ScopedJavaLocalRef<jobject> jobj = weak_java_banner_view_manager_.get(env);
   if (jobj.is_null())
     return;
-  Java_AppBannerManager_dismissCurrentBanner(env, jobj.obj());
+  Java_AppBannerManager_dismissCurrentBanner(env, jobj.obj(), DISMISS_NAVIGATE);
 }
 
 void AppBannerManager::OnFetchComplete(const GURL url, const SkBitmap* bitmap) {
@@ -78,10 +83,12 @@
     ScopedJavaLocalRef<jstring> jimage_url(
         ConvertUTF8ToJavaString(env, url.spec()));
     ScopedJavaLocalRef<jobject> jimage = gfx::ConvertToJavaBitmap(bitmap);
-    Java_AppBannerManager_createBanner(env,
-                                       jobj.obj(),
-                                       jimage_url.obj(),
-                                       jimage.obj());
+    bool displayed = Java_AppBannerManager_createBanner(env,
+                                                        jobj.obj(),
+                                                        jimage_url.obj(),
+                                                        jimage.obj());
+    if (displayed)
+      banners::TrackDisplayEvent(DISPLAY_CREATED);
   } else {
     DVLOG(1) << "Failed to retrieve image: " << url;
   }
@@ -92,6 +99,7 @@
 void AppBannerManager::HandleMetaTagContent(const std::string& tag_content,
                                             const GURL& expected_url) {
   DCHECK(web_contents());
+  banners::TrackDisplayEvent(DISPLAY_BANNER_REQUESTED);
 
   if (!AppBannerSettingsHelper::IsAllowed(web_contents(),
                                           expected_url,
@@ -130,6 +138,14 @@
   return true;
 }
 
+void RecordDismissEvent(JNIEnv* env, jclass clazz, jint metric) {
+  banners::TrackDismissEvent(metric);
+}
+
+void RecordInstallEvent(JNIEnv* env, jclass clazz, jint metric) {
+  banners::TrackInstallEvent(metric);
+}
+
 jlong Init(JNIEnv* env, jobject obj) {
   AppBannerManager* manager = new AppBannerManager(env, obj);
   return reinterpret_cast<intptr_t>(manager);
@@ -144,3 +160,5 @@
 bool RegisterAppBannerManager(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
+
+}  // namespace banners
diff --git a/chrome/browser/android/banners/app_banner_manager.h b/chrome/browser/android/banners/app_banner_manager.h
index 2ff64e8..226f119 100644
--- a/chrome/browser/android/banners/app_banner_manager.h
+++ b/chrome/browser/android/banners/app_banner_manager.h
@@ -53,6 +53,9 @@
  * Java side manages what happens in these situations, which will usually result
  * in dropping the old banner request on the floor.
  */
+
+namespace banners {
+
 class AppBannerManager : public chrome::BitmapFetcherDelegate,
                          public MetaTagObserver {
  public:
@@ -102,4 +105,6 @@
 // Register native methods
 bool RegisterAppBannerManager(JNIEnv* env);
 
+}  // namespace banners
+
 #endif  // CHROME_BROWSER_ANDROID_BANNERS_APP_BANNER_MANAGER_H_
diff --git a/chrome/browser/android/bookmarks/bookmarks_bridge.cc b/chrome/browser/android/bookmarks/bookmarks_bridge.cc
index 504781f..166eb3f 100644
--- a/chrome/browser/android/bookmarks/bookmarks_bridge.cc
+++ b/chrome/browser/android/bookmarks/bookmarks_bridge.cc
@@ -278,7 +278,7 @@
   if (!IsEditBookmarksEnabled())
     return false;
   if (partner_bookmarks_shim_->IsPartnerBookmark(node))
-    return true;
+    return partner_bookmarks_shim_->IsEditable(node);
   return !managed_bookmarks_shim_->IsManagedBookmark(node);
 }
 
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc b/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc
index 208027a..78f8072 100644
--- a/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc
+++ b/chrome/browser/android/bookmarks/partner_bookmarks_shim.cc
@@ -42,6 +42,8 @@
 static const char kMappingProviderTitle[] = "provider_title";
 static const char kMappingTitle[] = "mapped_title";
 
+static bool g_disable_partner_bookmarks_editing = false;
+
 }  // namespace
 
 // static
@@ -70,6 +72,11 @@
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 }
 
+// static
+void PartnerBookmarksShim::DisablePartnerBookmarksEditing() {
+  g_disable_partner_bookmarks_editing = true;
+}
+
 bool PartnerBookmarksShim::IsLoaded() const {
   return g_partner_model_keeper.Get().loaded;
 }
@@ -83,21 +90,34 @@
   DCHECK(IsPartnerBookmark(node));
   if (!HasPartnerBookmarks())
     return false;
-  for (const BookmarkNode* i = node; i != NULL; i = i->parent()) {
-    const NodeRenamingMapKey key(i->url(), i->GetTitle());
-    NodeRenamingMap::const_iterator remap = node_rename_remove_map_.find(key);
-    if (remap != node_rename_remove_map_.end() && remap->second.empty())
-      return false;
+  if (!g_disable_partner_bookmarks_editing) {
+    for (const BookmarkNode* i = node; i != NULL; i = i->parent()) {
+      const NodeRenamingMapKey key(i->url(), i->GetTitle());
+      NodeRenamingMap::const_iterator remap = node_rename_remove_map_.find(key);
+      if (remap != node_rename_remove_map_.end() && remap->second.empty())
+        return false;
+    }
   }
   return true;
 }
 
+bool PartnerBookmarksShim::IsEditable(const BookmarkNode* node) const {
+  DCHECK(IsPartnerBookmark(node));
+  if (!HasPartnerBookmarks())
+    return false;
+  if (g_disable_partner_bookmarks_editing)
+    return false;
+  return true;
+}
+
 void PartnerBookmarksShim::RemoveBookmark(const BookmarkNode* node) {
+  DCHECK(IsEditable(node));
   RenameBookmark(node, base::string16());
 }
 
 void PartnerBookmarksShim::RenameBookmark(const BookmarkNode* node,
                                           const base::string16& title) {
+  DCHECK(IsEditable(node));
   const NodeRenamingMapKey key(node->url(), node->GetTitle());
   node_rename_remove_map_[key] = title;
   SaveNodeMapping();
@@ -126,10 +146,12 @@
   DCHECK(node);
   DCHECK(IsPartnerBookmark(node));
 
-  const NodeRenamingMapKey key(node->url(), node->GetTitle());
-  NodeRenamingMap::const_iterator i = node_rename_remove_map_.find(key);
-  if (i != node_rename_remove_map_.end())
-    return i->second;
+  if (!g_disable_partner_bookmarks_editing) {
+    const NodeRenamingMapKey key(node->url(), node->GetTitle());
+    NodeRenamingMap::const_iterator i = node_rename_remove_map_.find(key);
+    if (i != node_rename_remove_map_.end())
+      return i->second;
+  }
 
   return node->GetTitle();
 }
@@ -184,6 +206,11 @@
   g_partner_model_keeper.Get().partner_bookmarks_root.reset(0);
 }
 
+// static
+void PartnerBookmarksShim::EnablePartnerBookmarksEditing() {
+  g_disable_partner_bookmarks_editing = false;
+}
+
 PartnerBookmarksShim::PartnerBookmarksShim(PrefService* prefs)
     : prefs_(prefs),
       observers_(
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_shim.h b/chrome/browser/android/bookmarks/partner_bookmarks_shim.h
index acb542e..9d6fa46 100644
--- a/chrome/browser/android/bookmarks/partner_bookmarks_shim.h
+++ b/chrome/browser/android/bookmarks/partner_bookmarks_shim.h
@@ -36,6 +36,14 @@
   // Registers preferences.
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
+  // Disables the editing and stops any edits from being applied.
+  // The user will start to see the original (unedited) partner bookmarks.
+  // Edits are stored in the user profile, so once the editing is enabled
+  // ("not disabled") the user would see the edited partner bookmarks.
+  // This method should be called as early as possible: it does NOT send any
+  // notifications to already existing shims.
+  static void DisablePartnerBookmarksEditing();
+
   // Returns true if everything got loaded.
   bool IsLoaded() const;
 
@@ -46,6 +54,9 @@
   // nor any of its parents were "removed").
   bool IsReachable(const BookmarkNode* node) const;
 
+  // Returns true if a given node is editable and if editing is allowed.
+  bool IsEditable(const BookmarkNode* node) const;
+
   // Removes a given bookmark.
   // Makes the |node| (and, consequently, all its children) unreachable.
   void RemoveBookmark(const BookmarkNode* node);
@@ -104,6 +115,9 @@
   // For testing: clears partner bookmark model data.
   static void ClearPartnerModelForTesting();
 
+  // For testing: re-enables partner bookmarks editing.
+  static void EnablePartnerBookmarksEditing();
+
  private:
   explicit PartnerBookmarksShim(PrefService* prefs);
   virtual ~PartnerBookmarksShim();
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_shim_unittest.cc b/chrome/browser/android/bookmarks/partner_bookmarks_shim_unittest.cc
index dbbf1ce..0449087 100644
--- a/chrome/browser/android/bookmarks/partner_bookmarks_shim_unittest.cc
+++ b/chrome/browser/android/bookmarks/partner_bookmarks_shim_unittest.cc
@@ -70,6 +70,7 @@
   virtual void TearDown() OVERRIDE {
     PartnerBookmarksShim::ClearInBrowserContextForTesting(profile_.get());
     PartnerBookmarksShim::ClearPartnerModelForTesting();
+    PartnerBookmarksShim::EnablePartnerBookmarksEditing();
     profile_.reset(NULL);
   }
 
@@ -371,3 +372,41 @@
     EXPECT_FALSE(shim->IsReachable(partner_bookmark2));
   }
 }
+
+TEST_F(PartnerBookmarksShimTest, DisableEditing) {
+  PartnerBookmarksShim* shim = partner_bookmarks_shim();
+  shim->AddObserver(&observer_);
+
+  EXPECT_CALL(observer_, PartnerShimLoaded(shim)).Times(0);
+  EXPECT_CALL(observer_, PartnerShimChanged(shim)).Times(0);
+
+  BookmarkNode* root_partner_node = new BookmarkPermanentNode(0);
+  root_partner_node->SetTitle(base::ASCIIToUTF16("Partner bookmarks"));
+
+  BookmarkNode* partner_bookmark1 = new BookmarkNode(3, GURL("http://a"));
+  partner_bookmark1->set_type(BookmarkNode::URL);
+  partner_bookmark1->SetTitle(base::ASCIIToUTF16("a"));
+  root_partner_node->Add(partner_bookmark1, root_partner_node->child_count());
+
+  BookmarkNode* partner_bookmark2 = new BookmarkNode(3, GURL("http://b"));
+  partner_bookmark2->set_type(BookmarkNode::URL);
+  partner_bookmark2->SetTitle(base::ASCIIToUTF16("b"));
+  root_partner_node->Add(partner_bookmark2, root_partner_node->child_count());
+
+  ASSERT_FALSE(shim->IsLoaded());
+  EXPECT_CALL(observer_, PartnerShimLoaded(shim)).Times(1);
+  shim->SetPartnerBookmarksRoot(root_partner_node);
+  ASSERT_TRUE(shim->IsLoaded());
+
+  // Check that edits work by default.
+  EXPECT_CALL(observer_, PartnerShimChanged(shim)).Times(2);
+  shim->RenameBookmark(partner_bookmark1, base::ASCIIToUTF16("a2.com"));
+  shim->RemoveBookmark(partner_bookmark2);
+  EXPECT_EQ(base::ASCIIToUTF16("a2.com"), shim->GetTitle(partner_bookmark1));
+  EXPECT_FALSE(shim->IsReachable(partner_bookmark2));
+
+  // Disable edits and check that edits are not applied anymore.
+  PartnerBookmarksShim::DisablePartnerBookmarksEditing();
+  EXPECT_EQ(base::ASCIIToUTF16("a"), shim->GetTitle(partner_bookmark1));
+  EXPECT_TRUE(shim->IsReachable(partner_bookmark2));
+}
diff --git a/chrome/browser/android/chrome_jni_registrar.cc b/chrome/browser/android/chrome_jni_registrar.cc
index 08c9e12..ed0c523 100644
--- a/chrome/browser/android/chrome_jni_registrar.cc
+++ b/chrome/browser/android/chrome_jni_registrar.cc
@@ -52,7 +52,7 @@
 #include "chrome/browser/ui/android/autofill/autofill_popup_view_android.h"
 #include "chrome/browser/ui/android/chrome_http_auth_handler.h"
 #include "chrome/browser/ui/android/context_menu_helper.h"
-#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate.h"
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
 #include "chrome/browser/ui/android/infobars/confirm_infobar.h"
 #include "chrome/browser/ui/android/infobars/infobar_android.h"
 #include "chrome/browser/ui/android/infobars/infobar_container_android.h"
@@ -90,7 +90,7 @@
   { "AccountManagementScreenHelper", AccountManagementScreenHelper::Register },
   { "AndroidProfileOAuth2TokenService",
     AndroidProfileOAuth2TokenService::Register },
-  { "AppBannerManager", RegisterAppBannerManager },
+  { "AppBannerManager", banners::RegisterAppBannerManager },
   { "ApplicationLifetime", RegisterApplicationLifetimeAndroid },
   { "AutofillDialogControllerAndroid",
     autofill::AutofillDialogControllerAndroid::
@@ -101,7 +101,7 @@
     autofill::AutofillLoggerAndroid::Register },
   { "AutofillPopup",
     autofill::AutofillPopupViewAndroid::RegisterAutofillPopupViewAndroid },
-  { "AutoLoginDelegate", AutoLoginInfoBarDelegate::Register },
+  { "AutoLoginDelegate", AutoLoginInfoBarDelegateAndroid::Register },
   { "BookmarksBridge", BookmarksBridge::RegisterBookmarksBridge },
   { "CertificateViewer", RegisterCertificateViewer },
   { "ChromeBrowserProvider",
diff --git a/chrome/browser/android/chrome_startup_flags.cc b/chrome/browser/android/chrome_startup_flags.cc
index 88c2e23..8d1c18e 100644
--- a/chrome/browser/android/chrome_startup_flags.cc
+++ b/chrome/browser/android/chrome_startup_flags.cc
@@ -35,6 +35,9 @@
 }  // namespace
 
 void SetChromeSpecificCommandLineFlags() {
+  // Turn on autologin.
+  SetCommandLineSwitch(switches::kEnableAutologin);
+
   // Enable prerender for the omnibox.
   SetCommandLineSwitchASCII(switches::kPrerenderMode,
                             switches::kPrerenderModeSwitchValueEnabled);
@@ -52,4 +55,11 @@
       channel == chrome::VersionInfo::CHANNEL_DEV) {
     SetCommandLineSwitch(switches::kEnableDomDistiller);
   }
+
+  // Enable the Fast Text Autosizer on local builds, canary and dev-channel.
+  if (channel == chrome::VersionInfo::CHANNEL_UNKNOWN ||
+      channel == chrome::VersionInfo::CHANNEL_CANARY ||
+      channel == chrome::VersionInfo::CHANNEL_DEV) {
+    SetCommandLineSwitch(switches::kEnableFastTextAutosizing);
+  }
 }
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.cc b/chrome/browser/android/chrome_web_contents_delegate_android.cc
index e125026..a5c2e8c 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.cc
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.cc
@@ -88,9 +88,10 @@
 }
 
 void ChromeWebContentsDelegateAndroid::LoadingStateChanged(
-    WebContents* source) {
+    WebContents* source, bool to_different_document) {
   bool has_stopped = source == NULL || !source->IsLoading();
-  WebContentsDelegateAndroid::LoadingStateChanged(source);
+  WebContentsDelegateAndroid::LoadingStateChanged(
+      source, to_different_document);
   LoadProgressChanged(source, has_stopped ? 1 : 0);
 }
 
@@ -327,7 +328,7 @@
 }
 
 void ChromeWebContentsDelegateAndroid::WebContentsCreated(
-    content::WebContents* source_contents, int64 source_frame_id,
+    content::WebContents* source_contents, int opener_render_frame_id,
     const base::string16& frame_name, const GURL& target_url,
     content::WebContents* new_contents) {
   JNIEnv* env = AttachCurrentThread();
@@ -335,7 +336,7 @@
   if (obj.is_null())
     return;
   Java_ChromeWebContentsDelegateAndroid_webContentsCreated(env, obj.obj(),
-      reinterpret_cast<intptr_t>(source_contents), source_frame_id,
+      reinterpret_cast<intptr_t>(source_contents), opener_render_frame_id,
       base::android::ConvertUTF16ToJavaString(env, frame_name).Release(),
       base::android::ConvertUTF8ToJavaString(env, target_url.spec()).Release(),
       reinterpret_cast<intptr_t>(new_contents));
diff --git a/chrome/browser/android/chrome_web_contents_delegate_android.h b/chrome/browser/android/chrome_web_contents_delegate_android.h
index 78ecf5c..2b2bef1 100644
--- a/chrome/browser/android/chrome_web_contents_delegate_android.h
+++ b/chrome/browser/android/chrome_web_contents_delegate_android.h
@@ -37,7 +37,8 @@
   ChromeWebContentsDelegateAndroid(JNIEnv* env, jobject obj);
   virtual ~ChromeWebContentsDelegateAndroid();
 
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
   virtual void RunFileChooser(content::WebContents* web_contents,
                               const content::FileChooserParams& params)
                               OVERRIDE;
@@ -73,7 +74,7 @@
                               bool user_gesture,
                               bool* was_blocked) OVERRIDE;
   virtual void WebContentsCreated(content::WebContents* source_contents,
-                                  int64 source_frame_id,
+                                  int opener_render_frame_id,
                                   const base::string16& frame_name,
                                   const GURL& target_url,
                                   content::WebContents* new_contents) OVERRIDE;
diff --git a/chrome/browser/android/new_tab_page_url_handler.cc b/chrome/browser/android/new_tab_page_url_handler.cc
new file mode 100644
index 0000000..7ea7593
--- /dev/null
+++ b/chrome/browser/android/new_tab_page_url_handler.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/new_tab_page_url_handler.h"
+
+#include <string>
+
+#include "base/strings/string_util.h"
+#include "chrome/common/url_constants.h"
+#include "content/public/common/url_constants.h"
+#include "url/gurl.h"
+
+namespace {
+const char kLegacyBookmarksFragment[] = "bookmarks";
+const char kLegacyOpenTabsFragment[] = "open_tabs";
+const char kLegacyRecentTabsHost[] = "recent_tabs";
+}
+
+namespace chrome {
+namespace android {
+
+bool HandleAndroidNewTabURL(GURL* url,
+                            content::BrowserContext* browser_context) {
+  if (url->SchemeIs(content::kChromeUIScheme) &&
+      url->host() == chrome::kChromeUINewTabHost) {
+    std::string ref = url->ref();
+    if (StartsWithASCII(ref, kLegacyBookmarksFragment, true)) {
+      *url = GURL(chrome::kChromeUINativeBookmarksURL);
+    } else if (ref == kLegacyOpenTabsFragment) {
+      *url = GURL(chrome::kChromeUINativeRecentTabsURL);
+    } else {
+      *url = GURL(chrome::kChromeUINativeNewTabURL);
+    }
+    return true;
+  }
+
+  if (url->SchemeIs(chrome::kChromeNativeScheme) &&
+      url->host() == kLegacyRecentTabsHost) {
+    *url = GURL(chrome::kChromeUINativeRecentTabsURL);
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace android
+}  // namespace chrome
diff --git a/chrome/browser/android/new_tab_page_url_handler.h b/chrome/browser/android/new_tab_page_url_handler.h
new file mode 100644
index 0000000..90c968a
--- /dev/null
+++ b/chrome/browser/android/new_tab_page_url_handler.h
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_NEW_TAB_PAGE_URL_HANDLER_H_
+#define CHROME_BROWSER_ANDROID_NEW_TAB_PAGE_URL_HANDLER_H_
+
+class GURL;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace chrome {
+namespace android {
+
+// Rewrites old-style Android NTP URLs to new-style NTP URLs:
+//  - chrome://newtab              -> chrome-native://newtab
+//  - chrome://newtab#most_visited -> chrome-native://newtab
+//  - chrome://newtab#incognito    -> chrome-native://newtab
+//  - chrome://newtab#bookmarks    -> chrome-native://bookmarks
+//  - chrome://newtab#bookmarks:99 -> chrome-native://bookmarks
+//  - chrome://newtab#open_tabs    -> chrome-native://recent-tabs
+//  - chrome-native://recent_tabs  -> chrome-native://recent-tabs
+//
+// TODO(newt): Once most users have upgraded past M34, simplify this down to a
+// single rule: chrome://newtab -> chrome-native://newtab
+bool HandleAndroidNewTabURL(GURL* url,
+                            content::BrowserContext* browser_context);
+
+}  // namespace android
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_ANDROID_NEW_TAB_PAGE_URL_HANDLER_H_
diff --git a/chrome/browser/android/profiles/profile_downloader_android.cc b/chrome/browser/android/profiles/profile_downloader_android.cc
index c9e8699..773facb 100644
--- a/chrome/browser/android/profiles/profile_downloader_android.cc
+++ b/chrome/browser/android/profiles/profile_downloader_android.cc
@@ -6,6 +6,7 @@
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_android.h"
 #include "chrome/browser/profiles/profile_downloader.h"
 #include "chrome/browser/profiles/profile_downloader_delegate.h"
@@ -105,6 +106,44 @@
 }
 
 // static
+jstring GetCachedNameForPrimaryAccount(JNIEnv* env,
+                                       jclass clazz,
+                                       jobject jprofile) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  ProfileInfoInterface& info =
+      g_browser_process->profile_manager()->GetProfileInfoCache();
+  const size_t index = info.GetIndexOfProfileWithPath(profile->GetPath());
+
+  base::string16 name;
+  if (index != std::string::npos) {
+    name = info.GetGAIANameOfProfileAtIndex(index);
+    if (name.empty())
+      name = info.GetNameOfProfileAtIndex(index);
+  }
+
+  return base::android::ConvertUTF16ToJavaString(env, name).Release();
+}
+
+// static
+jobject GetCachedAvatarForPrimaryAccount(JNIEnv* env,
+                                         jclass clazz,
+                                         jobject jprofile) {
+  Profile* profile = ProfileAndroid::FromProfileAndroid(jprofile);
+  ProfileInfoInterface& info =
+      g_browser_process->profile_manager()->GetProfileInfoCache();
+  const size_t index = info.GetIndexOfProfileWithPath(profile->GetPath());
+
+  ScopedJavaLocalRef<jobject> jbitmap;
+  if (index != std::string::npos) {
+    const gfx::Image& img = info.GetAvatarIconOfProfileAtIndex(index);
+    if (!img.IsEmpty() && img.AsImageSkia().bitmap())
+      jbitmap = gfx::ConvertToJavaBitmap(img.AsImageSkia().bitmap());
+  }
+
+  return jbitmap.Release();
+}
+
+// static
 void StartFetchingAccountInfoFor(
     JNIEnv* env,
     jclass clazz,
diff --git a/chrome/browser/android/recently_closed_tabs_bridge.cc b/chrome/browser/android/recently_closed_tabs_bridge.cc
index aa12f0f..681ea14 100644
--- a/chrome/browser/android/recently_closed_tabs_bridge.cc
+++ b/chrome/browser/android/recently_closed_tabs_bridge.cc
@@ -89,7 +89,8 @@
 jboolean RecentlyClosedTabsBridge::OpenRecentlyClosedTab(JNIEnv* env,
                                                          jobject obj,
                                                          jobject jtab,
-                                                         jint recent_tab_id) {
+                                                         jint recent_tab_id,
+                                                         jint j_disposition) {
   if (!tab_restore_service_)
     return false;
 
@@ -112,9 +113,11 @@
   session_tab.current_navigation_index = tab_entry->current_navigation_index;
   session_tab.navigations = tab_entry->navigations;
 
+  WindowOpenDisposition disposition =
+      static_cast<WindowOpenDisposition>(j_disposition);
   SessionRestore::RestoreForeignSessionTab(web_contents,
                                            session_tab,
-                                           CURRENT_TAB);
+                                           disposition);
   return true;
 }
 
diff --git a/chrome/browser/android/recently_closed_tabs_bridge.h b/chrome/browser/android/recently_closed_tabs_bridge.h
index a67d875..8bb04e8 100644
--- a/chrome/browser/android/recently_closed_tabs_bridge.h
+++ b/chrome/browser/android/recently_closed_tabs_bridge.h
@@ -28,7 +28,8 @@
   jboolean OpenRecentlyClosedTab(JNIEnv* env,
                                  jobject obj,
                                  jobject jtab,
-                                 jint tab_id);
+                                 jint tab_id,
+                                 jint j_disposition);
   void ClearRecentlyClosedTabs(JNIEnv* env, jobject obj);
 
   // Observer callback for TabRestoreServiceObserver. Notifies the registered
diff --git a/chrome/browser/android/resource_id.h b/chrome/browser/android/resource_id.h
index 9ead2e8..a8939bf 100644
--- a/chrome/browser/android/resource_id.h
+++ b/chrome/browser/android/resource_id.h
@@ -14,16 +14,13 @@
 DEFINE_RESOURCE_ID(0, 0)
 
 // InfoBar resources.
-DEFINE_RESOURCE_ID(IDR_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_ICON,
-                   R.drawable.infobar_protected_media_identifier)
-DEFINE_RESOURCE_ID(IDR_GEOLOCATION_INFOBAR_ICON, R.drawable.infobar_geolocation)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_ALT_NAV_URL, R.drawable.infobar_didyoumean)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_AUTOFILL, R.drawable.infobar_autofill)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_AUTOLOGIN, R.drawable.infobar_autologin)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_COOKIE, R.drawable.infobar_cookie)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_DESKTOP_NOTIFICATIONS,\
                    R.drawable.infobar_desktop_notifications)
-DEFINE_RESOURCE_ID(IDR_INFOBAR_INCOMPLETE, R.drawable.infobar_incomplete)
+DEFINE_RESOURCE_ID(IDR_INFOBAR_GEOLOCATION, R.drawable.infobar_geolocation)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_MEDIA_STREAM_CAMERA, R.drawable.infobar_camera)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_MEDIA_STREAM_MIC, R.drawable.infobar_microphone)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_MULTIPLE_DOWNLOADS,\
@@ -31,6 +28,8 @@
 DEFINE_RESOURCE_ID(IDR_INFOBAR_PLUGIN_CRASHED,\
                    R.drawable.infobar_plugin_crashed)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_PLUGIN_INSTALL, R.drawable.infobar_plugin)
+DEFINE_RESOURCE_ID(IDR_INFOBAR_PROTECTED_MEDIA_IDENTIFIER,
+                   R.drawable.infobar_protected_media_identifier)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_RESTORE_SESSION, R.drawable.infobar_restore)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_SAVE_PASSWORD, R.drawable.infobar_savepassword)
 DEFINE_RESOURCE_ID(IDR_INFOBAR_WARNING, R.drawable.infobar_warning)
diff --git a/chrome/browser/android/signin/signin_manager_android.cc b/chrome/browser/android/signin/signin_manager_android.cc
index f96de01..0aaf59d 100644
--- a/chrome/browser/android/signin/signin_manager_android.cc
+++ b/chrome/browser/android/signin/signin_manager_android.cc
@@ -23,7 +23,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/profile_management_switches.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "jni/SigninManager_jni.h"
 
 #if defined(ENABLE_CONFIGURATION_POLICY)
@@ -260,6 +260,10 @@
 #endif
 }
 
+static jboolean IsNewProfileManagementEnabled(JNIEnv* env, jclass clazz) {
+  return switches::IsNewProfileManagement();
+}
+
 // static
 bool SigninManagerAndroid::Register(JNIEnv* env) {
   return RegisterNativesImpl(env);
diff --git a/chrome/browser/apps/ephemeral_app_browsertest.cc b/chrome/browser/apps/ephemeral_app_browsertest.cc
index 6f68ba7..67c52e5 100644
--- a/chrome/browser/apps/ephemeral_app_browsertest.cc
+++ b/chrome/browser/apps/ephemeral_app_browsertest.cc
@@ -6,15 +6,18 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/stl_util.h"
 #include "chrome/browser/apps/app_browsertest_util.h"
+#include "chrome/browser/apps/ephemeral_app_service.h"
 #include "chrome/browser/extensions/api/file_system/file_system_api.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_test_message_listener.h"
+#include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/common/extensions/api/alarms.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/common/switches.h"
@@ -24,27 +27,22 @@
 using extensions::Event;
 using extensions::EventRouter;
 using extensions::Extension;
+using extensions::ExtensionInfo;
+using extensions::ExtensionPrefs;
 using extensions::ExtensionSystem;
+using extensions::Manifest;
 using extensions::PlatformAppBrowserTest;
 
 namespace {
 
 namespace alarms = extensions::api::alarms;
 
-const char kDispatchEventTestApp[] =
-    "platform_apps/ephemeral_apps/dispatch_event";
-
-const char kMessagingReceiverApp[] =
-    "platform_apps/ephemeral_apps/messaging_receiver";
-
-const char kMessagingReceiverAppV2[] =
-    "platform_apps/ephemeral_apps/messaging_receiver2";
-
-const char kNotificationsTestApp[] =
-    "platform_apps/ephemeral_apps/notification_settings";
-
-const char kFileSystemTestApp[] =
-    "platform_apps/ephemeral_apps/filesystem_retain_entries";
+const char kDispatchEventTestApp[] = "ephemeral_apps/dispatch_event";
+const char kMessagingReceiverApp[] = "ephemeral_apps/messaging_receiver";
+const char kMessagingReceiverAppV2[] = "ephemeral_apps/messaging_receiver2";
+const char kNotificationsTestApp[] = "ephemeral_apps/notification_settings";
+const char kFileSystemTestApp[] = "ephemeral_apps/filesystem_retain_entries";
+const char kRetainDataApp[] = "ephemeral_apps/retain_data";
 
 typedef std::vector<message_center::Notifier*> NotifierList;
 
@@ -60,6 +58,19 @@
   return false;
 }
 
+bool IsAppInExtensionsInfo(const ExtensionPrefs::ExtensionsInfo& ext_info,
+                           const std::string& extension_id) {
+  for (size_t i = 0; i < ext_info.size(); ++i) {
+    ExtensionInfo* info = ext_info.at(i).get();
+    if (info->extension_id == extension_id)
+      return true;
+  }
+
+  return false;
+}
+
+}  // namespace
+
 class EphemeralAppBrowserTest : public PlatformAppBrowserTest {
  protected:
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -74,17 +85,25 @@
         extensions::switches::kEventPageSuspendingTime, "10");
   }
 
-  const Extension* InstallEphemeralApp(const char* test_path) {
-    base::FilePath path = test_data_dir_.AppendASCII(test_path);
+  base::FilePath GetTestPath(const char* test_path) {
+    return test_data_dir_.AppendASCII("platform_apps").AppendASCII(test_path);
+  }
+
+  const Extension* InstallEphemeralApp(const char* test_path,
+                                       Manifest::Location manifest_location) {
     const Extension* extension =
         InstallExtensionWithSourceAndFlags(
-            path,
+            GetTestPath(test_path),
             1,
-            extensions::Manifest::UNPACKED,
+            manifest_location,
             Extension::IS_EPHEMERAL);
     return extension;
   }
 
+  const Extension* InstallEphemeralApp(const char* test_path) {
+    return InstallEphemeralApp(test_path, Manifest::INTERNAL);
+  }
+
   const Extension* InstallAndLaunchEphemeralApp(const char* test_path) {
     ExtensionTestMessageListener launched_listener("launched", false);
     const Extension* extension = InstallEphemeralApp(test_path);
@@ -134,6 +153,21 @@
     event_page_destroyed_signal.Wait();
   }
 
+  void EvictApp(const std::string& app_id) {
+    // Uninstall the app, which is what happens when ephemeral apps get evicted
+    // from the cache.
+    content::WindowedNotificationObserver uninstalled_signal(
+        chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
+        content::Source<Profile>(browser()->profile()));
+
+    ExtensionService* service =
+        ExtensionSystem::Get(browser()->profile())->extension_service();
+    ASSERT_TRUE(service);
+    service->UninstallExtension(app_id, false, NULL);
+
+    uninstalled_signal.Wait();
+  }
+
   void VerifyAppNotLoaded(const std::string& app_id) {
     EXPECT_FALSE(ExtensionSystem::Get(browser()->profile())->
         process_manager()->GetBackgroundHostForExtension(app_id));
@@ -151,9 +185,14 @@
 
     event_router->DispatchEventToExtension(app_id, event.Pass());
   }
-};
 
-}  // namespace
+  void GarbageCollectData() {
+    EphemeralAppService* service =
+        EphemeralAppService::Get(browser()->profile());
+    ASSERT_TRUE(service);
+    service->GarbageCollectData();
+  }
+};
 
 // Verify that ephemeral apps can be launched and receive system events when
 // they are running. Once they are inactive they should not receive system
@@ -225,9 +264,9 @@
   }
 
   base::FilePath app_v2_path = PackExtensionWithOptions(
-      test_data_dir_.AppendASCII(kMessagingReceiverAppV2),
+      GetTestPath(kMessagingReceiverAppV2),
       crx_path,
-      test_data_dir_.AppendASCII(kMessagingReceiverApp).ReplaceExtension(
+      GetTestPath(kMessagingReceiverApp).ReplaceExtension(
           FILE_PATH_LITERAL(".pem")),
       base::FilePath());
   ASSERT_FALSE(app_v2_path.empty());
@@ -266,18 +305,8 @@
   notification_service->SetNotifierEnabled(notifier_id, false);
   EXPECT_FALSE(notification_service->IsNotifierEnabled(notifier_id));
 
-  // Uninstall the app, which is what happens when ephemeral apps get evicted
-  // from the cache.
-  content::WindowedNotificationObserver uninstalled_signal(
-      chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
-      content::Source<Profile>(browser()->profile()));
-
-  ExtensionService* service =
-      ExtensionSystem::Get(browser()->profile())->extension_service();
-  ASSERT_TRUE(service);
-  service->UninstallExtension(app->id(), false, NULL);
-
-  uninstalled_signal.Wait();
+  // Remove the app.
+  EvictApp(app->id());
 
   // Reinstall the ephemeral app and verify that notifications remain disabled.
   app = InstallEphemeralApp(kNotificationsTestApp);
@@ -342,7 +371,8 @@
       "temp", temp_dir.path());
 
   // The first test opens the file and writes the file handle to local storage.
-  const Extension* app = InstallEphemeralApp(kFileSystemTestApp);
+  const Extension* app = InstallEphemeralApp(kFileSystemTestApp,
+                                             Manifest::UNPACKED);
   ASSERT_TRUE(LaunchAppAndRunTest(app, "OpenAndRetainFile")) << message_;
 
   // Verify that after the app has been closed, all retained entries are
@@ -350,7 +380,133 @@
   std::vector<apps::SavedFileEntry> file_entries =
       apps::SavedFilesService::Get(browser()->profile())
           ->GetAllFileEntries(app->id());
+  EXPECT_TRUE(file_entries.empty());
 
   // The second test verifies that the file cannot be reopened.
   ASSERT_TRUE(LaunchAppAndRunTest(app, "RestoreRetainedFile")) << message_;
 }
+
+// Verify that once evicted from the cache, the data of ephemeral apps will not
+// be deleted.
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RetainData) {
+  // Phase 1 - Install the ephemeral app and write data to various storage.
+  const Extension* app = InstallEphemeralApp(kRetainDataApp);
+  ASSERT_TRUE(app);
+  ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_;
+
+  // Sanity check to ensure that the ReadData tests should pass before the app
+  // is removed.
+  ASSERT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_;
+
+  // Remove the app.
+  const std::string app_id = app->id();
+  EvictApp(app->id());
+  app = NULL;
+
+  // The app should be in the list of evicted apps.
+  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
+  ASSERT_TRUE(prefs);
+  scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
+      prefs->GetEvictedEphemeralAppsInfo());
+  EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id));
+
+  // The app should not be in the list of installed extensions.
+  extensions_info = prefs->GetInstalledExtensionsInfo();
+  EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id));
+
+  // Ensure the evicted app is considered to have isolated storage. This will
+  // prevent its data from getting garbage collected by
+  // ExtensionService::GarbageCollectIsolatedStorage().
+  GURL site_url = extensions::util::GetSiteForExtensionId(
+      app_id, browser()->profile());
+  EXPECT_TRUE(extensions::util::SiteHasIsolatedStorage(
+                  site_url, browser()->profile()));
+
+  // Phase 2 - Reinstall the ephemeral app and verify that data still exists
+  // in the storage.
+  app = InstallEphemeralApp(kRetainDataApp);
+  ASSERT_TRUE(app);
+  EXPECT_TRUE(LaunchAppAndRunTest(app, "ReadData")) << message_;
+
+  // The app should now be in the list of installed extensions, but not in the
+  // list of evicted apps.
+  extensions_info = prefs->GetInstalledExtensionsInfo();
+  EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, app_id));
+  extensions_info = prefs->GetEvictedEphemeralAppsInfo();
+  EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id));
+}
+
+// Verify that the data of regular installed apps are deleted on uninstall.
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, RemoveInstalledData) {
+  // Install the ephemeral app and write data to various storage.
+  const Extension* app = InstallPlatformApp(kRetainDataApp);
+  ASSERT_TRUE(app);
+  ASSERT_TRUE(LaunchAppAndRunTest(app, "WriteData")) << message_;
+
+  // Remove the app.
+  const std::string app_id = app->id();
+  EvictApp(app->id());
+  app = NULL;
+
+  // The app should not be in the preferences.
+  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
+  ASSERT_TRUE(prefs);
+  scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
+      prefs->GetEvictedEphemeralAppsInfo());
+  EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id));
+  extensions_info = prefs->GetInstalledExtensionsInfo();
+  EXPECT_FALSE(IsAppInExtensionsInfo(*extensions_info, app_id));
+
+  // Reinstall the app and verify that all data has been reset.
+  app = InstallPlatformApp(kRetainDataApp);
+  ASSERT_TRUE(LaunchAppAndRunTest(app, "DataReset")) << message_;
+}
+
+// Verify that once evicted from the cache, ephemeral apps will remain in
+// extension prefs, but marked as evicted. After garbage collection of data,
+// both their data and preferences should be removed.
+IN_PROC_BROWSER_TEST_F(EphemeralAppBrowserTest, GarbageCollectData) {
+  // Create two apps. Both will be evicted from the cache, but the data of
+  // one will be garbage collected.
+  const Extension* evict_app = InstallEphemeralApp(kRetainDataApp);
+  ASSERT_TRUE(evict_app);
+  ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "WriteData")) << message_;
+  std::string evict_app_id = evict_app->id();
+  EvictApp(evict_app_id);
+  evict_app = NULL;
+
+  const Extension* retain_app = InstallEphemeralApp(kDispatchEventTestApp);
+  ASSERT_TRUE(retain_app);
+  std::string retain_app_id = retain_app->id();
+  EvictApp(retain_app_id);
+  retain_app = NULL;
+
+  ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
+  ASSERT_TRUE(prefs);
+
+  // Both apps should be in the list of evicted apps.
+  scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
+      prefs->GetEvictedEphemeralAppsInfo());
+  EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id));
+  EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, evict_app_id));
+
+  // Set a fake last launch time so that the ephemeral app's data will be
+  // garbage collected.
+  base::Time launch_time =
+      base::Time::Now() - base::TimeDelta::FromDays(
+                              EphemeralAppService::kDataInactiveThreshold + 1);
+  prefs->SetLastLaunchTime(evict_app_id, launch_time);
+  prefs->SetLastLaunchTime(retain_app_id, base::Time::Now());
+
+  // Garbage collect data.
+  GarbageCollectData();
+
+  // The garbage collected app should no longer be in the preferences.
+  extensions_info = prefs->GetEvictedEphemeralAppsInfo();
+  EXPECT_TRUE(IsAppInExtensionsInfo(*extensions_info, retain_app_id));
+  ASSERT_FALSE(IsAppInExtensionsInfo(*extensions_info, evict_app_id));
+
+  // Reinstall the app and verify that all data has been reset.
+  evict_app = InstallEphemeralApp(kRetainDataApp);
+  ASSERT_TRUE(LaunchAppAndRunTest(evict_app, "DataReset")) << message_;
+}
diff --git a/chrome/browser/apps/ephemeral_app_service.cc b/chrome/browser/apps/ephemeral_app_service.cc
index 86ea100..0832e14 100644
--- a/chrome/browser/apps/ephemeral_app_service.cc
+++ b/chrome/browser/apps/ephemeral_app_service.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "chrome/browser/apps/ephemeral_app_service_factory.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/data_deleter.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/profiles/profile.h"
@@ -21,6 +22,7 @@
 #include "extensions/common/extension_set.h"
 
 using extensions::Extension;
+using extensions::ExtensionInfo;
 using extensions::ExtensionPrefs;
 using extensions::ExtensionSet;
 using extensions::ExtensionSystem;
@@ -30,28 +32,27 @@
 
 // The number of seconds after startup before performing garbage collection
 // of ephemeral apps.
-const int kGarbageCollectStartupDelay = 60;
+const int kGarbageCollectAppsStartupDelay = 60;
 
 // The number of seconds after an ephemeral app has been installed before
 // performing garbage collection.
-const int kGarbageCollectInstallDelay = 15;
+const int kGarbageCollectAppsInstallDelay = 15;
 
 // When the number of ephemeral apps reaches this count, trigger garbage
 // collection to trim off the least-recently used apps in excess of
 // kMaxEphemeralAppsCount.
-const int kGarbageCollectTriggerCount = 35;
+const int kGarbageCollectAppsTriggerCount = 35;
+
+// The number of seconds after startup before performing garbage collection
+// of the data of evicted ephemeral apps.
+const int kGarbageCollectDataStartupDelay = 120;
 
 }  // namespace
 
-// The number of days of inactivity before an ephemeral app will be removed.
 const int EphemeralAppService::kAppInactiveThreshold = 10;
-
-// If the ephemeral app has been launched within this number of days, it will
-// definitely not be garbage collected.
 const int EphemeralAppService::kAppKeepThreshold = 1;
-
-// The maximum number of ephemeral apps to keep cached. Excess may be removed.
 const int EphemeralAppService::kMaxEphemeralAppsCount = 30;
+const int EphemeralAppService::kDataInactiveThreshold = 90;
 
 // static
 EphemeralAppService* EphemeralAppService::Get(Profile* profile) {
@@ -93,9 +94,9 @@
       DCHECK(extension);
       if (extension->is_ephemeral()) {
         ++ephemeral_app_count_;
-        if (ephemeral_app_count_ >= kGarbageCollectTriggerCount)
+        if (ephemeral_app_count_ >= kGarbageCollectAppsTriggerCount)
           TriggerGarbageCollect(
-              base::TimeDelta::FromSeconds(kGarbageCollectInstallDelay));
+              base::TimeDelta::FromSeconds(kGarbageCollectAppsInstallDelay));
       }
       break;
     }
@@ -109,7 +110,7 @@
     }
     case chrome::NOTIFICATION_PROFILE_DESTROYED: {
       // Ideally we need to know when the extension system is shutting down.
-      garbage_collect_timer_.Stop();
+      garbage_collect_apps_timer_.Stop();
       break;
     }
     default:
@@ -120,7 +121,13 @@
 void EphemeralAppService::Init() {
   InitEphemeralAppCount();
   TriggerGarbageCollect(
-      base::TimeDelta::FromSeconds(kGarbageCollectStartupDelay));
+      base::TimeDelta::FromSeconds(kGarbageCollectAppsStartupDelay));
+
+  garbage_collect_data_timer_.Start(
+      FROM_HERE,
+      base::TimeDelta::FromSeconds(kGarbageCollectDataStartupDelay),
+      this,
+      &EphemeralAppService::GarbageCollectData);
 }
 
 void EphemeralAppService::InitEphemeralAppCount() {
@@ -138,12 +145,13 @@
 }
 
 void EphemeralAppService::TriggerGarbageCollect(const base::TimeDelta& delay) {
-  if (!garbage_collect_timer_.IsRunning())
-    garbage_collect_timer_.Start(
-      FROM_HERE,
-      delay,
-      this,
-      &EphemeralAppService::GarbageCollectApps);
+  if (!garbage_collect_apps_timer_.IsRunning()) {
+    garbage_collect_apps_timer_.Start(
+        FROM_HERE,
+        delay,
+        this,
+        &EphemeralAppService::GarbageCollectApps);
+  }
 }
 
 void EphemeralAppService::GarbageCollectApps() {
@@ -225,3 +233,52 @@
     }
   }
 }
+
+void EphemeralAppService::GarbageCollectData() {
+  ExtensionService* service =
+      ExtensionSystem::Get(profile_)->extension_service();
+  DCHECK(service);
+  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
+  DCHECK(prefs);
+  scoped_ptr<ExtensionPrefs::ExtensionsInfo> evicted_apps_info(
+      prefs->GetEvictedEphemeralAppsInfo());
+
+  base::Time time_now = base::Time::Now();
+  const base::Time inactive_threshold =
+      time_now - base::TimeDelta::FromDays(kDataInactiveThreshold);
+
+  for (size_t i = 0; i < evicted_apps_info->size(); ++i) {
+    ExtensionInfo* info = evicted_apps_info->at(i).get();
+    base::Time last_launch_time = prefs->GetLastLaunchTime(info->extension_id);
+    if (last_launch_time > inactive_threshold)
+      continue;
+
+    // Sanity check to ensure the app is not currently installed.
+    if (service->GetInstalledExtension(info->extension_id)) {
+      NOTREACHED();
+      continue;
+    }
+
+    // Ensure the app is not waiting to be installed.
+    scoped_ptr<ExtensionInfo> delayed_install(
+        prefs->GetDelayedInstallInfo(info->extension_id));
+    if (delayed_install.get())
+      continue;
+
+    if (info->extension_manifest.get()) {
+      std::string error;
+      scoped_refptr<const Extension> extension(Extension::Create(
+          info->extension_path,
+          info->extension_location,
+          *info->extension_manifest,
+          prefs->GetCreationFlags(info->extension_id),
+          info->extension_id,
+          &error));
+
+      if (extension.get())
+        extensions::DataDeleter::StartDeleting(profile_, extension.get());
+    }
+
+    prefs->RemoveEvictedEphemeralApp(info->extension_id);
+  }
+}
diff --git a/chrome/browser/apps/ephemeral_app_service.h b/chrome/browser/apps/ephemeral_app_service.h
index ac8dea3..a1d4fbb 100644
--- a/chrome/browser/apps/ephemeral_app_service.h
+++ b/chrome/browser/apps/ephemeral_app_service.h
@@ -30,10 +30,18 @@
   explicit EphemeralAppService(Profile* profile);
   virtual ~EphemeralAppService();
 
-  // Constants exposed for testing purposes.
+  // Constants exposed for testing purposes:
+
+  // The number of days of inactivity before an ephemeral app will be removed.
   static const int kAppInactiveThreshold;
+  // If the ephemeral app has been launched within this number of days, it will
+  // definitely not be garbage collected.
   static const int kAppKeepThreshold;
+  // The maximum number of ephemeral apps to keep cached. Excess may be removed.
   static const int kMaxEphemeralAppsCount;
+  // The number of days of inactivity before the data of an already evicted
+  // ephemeral app will be removed.
+  static const int kDataInactiveThreshold;
 
  private:
   // A map used to order the ephemeral apps by their last launch time.
@@ -54,15 +62,21 @@
                               const LaunchTimeAppMap& app_launch_times,
                               std::set<std::string>* remove_app_ids);
 
+  // Garbage collect the data of ephemeral apps that have been evicted and
+  // inactive for a long period of time.
+  void GarbageCollectData();
+
   Profile* profile_;
 
   content::NotificationRegistrar registrar_;
 
-  base::OneShotTimer<EphemeralAppService> garbage_collect_timer_;
+  base::OneShotTimer<EphemeralAppService> garbage_collect_apps_timer_;
+  base::OneShotTimer<EphemeralAppService> garbage_collect_data_timer_;
 
   // The count of cached ephemeral apps.
   int ephemeral_app_count_;
 
+  friend class EphemeralAppBrowserTest;
   friend class EphemeralAppServiceTest;
   friend class EphemeralAppServiceBrowserTest;
 
diff --git a/chrome/browser/apps/ephemeral_app_service_browsertest.cc b/chrome/browser/apps/ephemeral_app_service_browsertest.cc
index ccf0bbf..e59eec2 100644
--- a/chrome/browser/apps/ephemeral_app_service_browsertest.cc
+++ b/chrome/browser/apps/ephemeral_app_service_browsertest.cc
@@ -37,7 +37,7 @@
           InstallExtensionWithSourceAndFlags(
               path,
               1,
-              extensions::Manifest::UNPACKED,
+              extensions::Manifest::INTERNAL,
               Extension::IS_EPHEMERAL);
       app_ids_.push_back(extension->id());
     }
diff --git a/chrome/browser/apps/shortcut_manager.cc b/chrome/browser/apps/shortcut_manager.cc
index 07b489b..c135d6e 100644
--- a/chrome/browser/apps/shortcut_manager.cc
+++ b/chrome/browser/apps/shortcut_manager.cc
@@ -132,7 +132,7 @@
         create_or_update = base::Bind(&CreateShortcutsInApplicationsMenu);
       }
       if (!create_or_update.is_null()) {
-        web_app::UpdateShortcutInfoAndIconForApp(*extension, profile_,
+        web_app::UpdateShortcutInfoAndIconForApp(extension, profile_,
                                                  create_or_update);
       }
       break;
@@ -189,7 +189,7 @@
        it != apps->end(); ++it) {
     if (ShouldCreateShortcutFor(it->get()))
       web_app::UpdateShortcutInfoAndIconForApp(
-          *it->get(), profile_, base::Bind(&CreateShortcutsInApplicationsMenu));
+          it->get(), profile_, base::Bind(&CreateShortcutsInApplicationsMenu));
   }
 }
 
diff --git a/chrome/browser/apps/web_view_browsertest.cc b/chrome/browser/apps/web_view_browsertest.cc
index 98877a2..e3afc1f 100644
--- a/chrome/browser/apps/web_view_browsertest.cc
+++ b/chrome/browser/apps/web_view_browsertest.cc
@@ -564,7 +564,7 @@
     }
 
     ExtensionTestMessageListener done_listener("TEST_PASSED", false);
-    done_listener.AlsoListenForFailureMessage("TEST_FAILED");
+    done_listener.set_failure_message("TEST_FAILED");
     if (!content::ExecuteScript(
             embedder_web_contents,
             base::StringPrintf("runTest('%s')", test_name.c_str()))) {
@@ -618,7 +618,7 @@
     ASSERT_TRUE(embedder_web_contents);
 
     ExtensionTestMessageListener test_run_listener("PASSED", false);
-    test_run_listener.AlsoListenForFailureMessage("FAILED");
+    test_run_listener.set_failure_message("FAILED");
     EXPECT_TRUE(
         content::ExecuteScript(
             embedder_web_contents,
@@ -1577,11 +1577,11 @@
 
   content::WebContents* embedder_web_contents = GetFirstAppWindowWebContents();
   ASSERT_TRUE(embedder_web_contents);
-  MockWebContentsDelegate* mock = new MockWebContentsDelegate;
-  embedder_web_contents->SetDelegate(mock);
+  scoped_ptr<MockWebContentsDelegate> mock(new MockWebContentsDelegate());
+  embedder_web_contents->SetDelegate(mock.get());
 
   ExtensionTestMessageListener done_listener("TEST_PASSED", false);
-  done_listener.AlsoListenForFailureMessage("TEST_FAILED");
+  done_listener.set_failure_message("TEST_FAILED");
   EXPECT_TRUE(
       content::ExecuteScript(
           embedder_web_contents,
@@ -1598,7 +1598,7 @@
       SetBrowserClientForTesting(&new_client);
 
   ExtensionTestMessageListener launched_listener("Launched", false);
-  launched_listener.AlsoListenForFailureMessage("TEST_FAILED");
+  launched_listener.set_failure_message("TEST_FAILED");
   LoadAndLaunchPlatformApp("web_view/context_menus/basic");
   ASSERT_TRUE(launched_listener.WaitUntilSatisfied());
 
@@ -1839,9 +1839,9 @@
   // Replace WebContentsDelegate with mock version so we can intercept download
   // requests.
   content::WebContentsDelegate* delegate = guest_web_contents->GetDelegate();
-  MockDownloadWebContentsDelegate* mock_delegate =
-      new MockDownloadWebContentsDelegate(delegate);
-  guest_web_contents->SetDelegate(mock_delegate);
+  scoped_ptr<MockDownloadWebContentsDelegate>
+      mock_delegate(new MockDownloadWebContentsDelegate(delegate));
+  guest_web_contents->SetDelegate(mock_delegate.get());
 
   // Start test.
   // 1. Guest requests a download that its embedder denies.
diff --git a/chrome/browser/apps/web_view_interactive_browsertest.cc b/chrome/browser/apps/web_view_interactive_browsertest.cc
index 5e332c2..3b633fa 100644
--- a/chrome/browser/apps/web_view_interactive_browsertest.cc
+++ b/chrome/browser/apps/web_view_interactive_browsertest.cc
@@ -172,7 +172,7 @@
 
     scoped_ptr<ExtensionTestMessageListener> done_listener(
         new ExtensionTestMessageListener("TEST_PASSED", false));
-    done_listener->AlsoListenForFailureMessage("TEST_FAILED");
+    done_listener->set_failure_message("TEST_FAILED");
     if (!content::ExecuteScript(
             *embedder_web_contents,
             base::StringPrintf("runTest('%s')", test_name.c_str()))) {
@@ -473,7 +473,7 @@
   // div. We then move the mouse over that div to ensure the mouse was properly
   // unlocked and that the div receieves the message.
   ExtensionTestMessageListener move_captured_listener("move-captured", false);
-  move_captured_listener.AlsoListenForFailureMessage("timeout");
+  move_captured_listener.set_failure_message("timeout");
 
   // Mouse should already be over lock button (since we just unlocked), so send
   // click to re-lock the mouse.
@@ -744,7 +744,7 @@
 
   ExtensionTestMessageListener done_listener(
       "TEST_PASSED", false);
-  done_listener.AlsoListenForFailureMessage("TEST_FAILED");
+  done_listener.set_failure_message("TEST_FAILED");
   ExtensionTestMessageListener ready_back_key_listener(
       "ReadyForBackKey", false);
   ExtensionTestMessageListener ready_forward_key_listener(
diff --git a/chrome/browser/autocomplete/autocomplete_controller.cc b/chrome/browser/autocomplete/autocomplete_controller.cc
index 1af794f..08d70ac 100644
--- a/chrome/browser/autocomplete/autocomplete_controller.cc
+++ b/chrome/browser/autocomplete/autocomplete_controller.cc
@@ -238,7 +238,14 @@
     // TODO(mpearson): Remove timing code once bugs 178705 / 237703 / 168933
     // are resolved.
     base::TimeTicks provider_start_time = base::TimeTicks::Now();
-    (*i)->Start(input_, minimal_changes);
+
+    // Call Start() on ZeroSuggestProvider with an INVALID AutocompleteInput
+    // to clear out zero-suggest |matches_|.
+    if (*i == zero_suggest_provider_)
+      (*i)->Start(AutocompleteInput(), minimal_changes);
+    else
+      (*i)->Start(input_, minimal_changes);
+
     if (input.matches_requested() != AutocompleteInput::ALL_MATCHES)
       DCHECK((*i)->done());
     base::TimeTicks provider_end_time = base::TimeTicks::Now();
@@ -297,28 +304,20 @@
   }
 }
 
-void AutocompleteController::StartZeroSuggest(
-    const GURL& url,
-    AutocompleteInput::PageClassification page_classification,
-    const base::string16& permanent_text) {
+void AutocompleteController::StartZeroSuggest(const AutocompleteInput& input) {
   if (zero_suggest_provider_ != NULL) {
     DCHECK(!in_start_);  // We should not be already running a query.
 
-    // Call Start() on all providers with INVALID input to clear out cached
-    // |matches_| to ensure they aren't used with zero suggest.
+    // Call Start() on all prefix-based providers with an INVALID
+    // AutocompleteInput to clear out cached |matches_|, which ensures that
+    // they aren't used with zero suggest.
     for (ACProviders::iterator i(providers_.begin()); i != providers_.end();
-        ++i)
-      (*i)->Start(AutocompleteInput(), false);
-
-    zero_suggest_provider_->StartZeroSuggest(
-        url, page_classification, permanent_text);
-  }
-}
-
-void AutocompleteController::StopZeroSuggest() {
-  if (zero_suggest_provider_ != NULL) {
-    DCHECK(!in_start_);  // We should not be already running a query.
-    zero_suggest_provider_->Stop(false);
+        ++i) {
+      if (*i == zero_suggest_provider_)
+        (*i)->Start(input, false);
+      else
+        (*i)->Start(AutocompleteInput(), false);
+    }
   }
 }
 
@@ -512,10 +511,7 @@
   base::string16 last_keyword;
   for (AutocompleteResult::iterator i(result->begin()); i != result->end();
        ++i) {
-    if ((i->provider->type() == AutocompleteProvider::TYPE_KEYWORD &&
-         !i->keyword.empty()) ||
-        (i->provider->type() == AutocompleteProvider::TYPE_SEARCH &&
-         AutocompleteMatch::IsSearchType(i->type))) {
+    if (AutocompleteMatch::IsSearchType(i->type)) {
       if (AutocompleteMatchHasCustomDescription(*i))
         continue;
       i->description.clear();
diff --git a/chrome/browser/autocomplete/autocomplete_controller.h b/chrome/browser/autocomplete/autocomplete_controller.h
index 8931b96..1f2a09c 100644
--- a/chrome/browser/autocomplete/autocomplete_controller.h
+++ b/chrome/browser/autocomplete/autocomplete_controller.h
@@ -74,16 +74,10 @@
   // If |clear_result| is true, the controller will also erase the result set.
   void Stop(bool clear_result);
 
-  // Begin asynchronously fetching zero-suggest suggestions for |url| of
-  // classification |page_classification|. |permanent_text| is the omnibox
-  // text for the current page.
-  void StartZeroSuggest(
-      const GURL& url,
-      AutocompleteInput::PageClassification page_classification,
-      const base::string16& permanent_text);
-
-  // Cancels any pending zero-suggest fetch.
-  void StopZeroSuggest();
+  // Begin asynchronous fetch of zero-suggest suggestions. The |input| should
+  // contain current omnibox input, the URL of the page we are on, and
+  // that page's classification.
+  void StartZeroSuggest(const AutocompleteInput& input);
 
   // Asks the relevant provider to delete |match|, and ensures observers are
   // notified of resulting changes immediately.  This should only be called when
diff --git a/chrome/browser/autocomplete/autocomplete_match.cc b/chrome/browser/autocomplete/autocomplete_match.cc
index 4d04019..9784dd6 100644
--- a/chrome/browser/autocomplete/autocomplete_match.cc
+++ b/chrome/browser/autocomplete/autocomplete_match.cc
@@ -338,11 +338,16 @@
   return type == AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED ||
          type == AutocompleteMatchType::SEARCH_HISTORY ||
          type == AutocompleteMatchType::SEARCH_SUGGEST ||
-         type == AutocompleteMatchType::SEARCH_SUGGEST_ENTITY ||
+         type == AutocompleteMatchType::SEARCH_OTHER_ENGINE ||
+         IsSpecializedSearchType(type);
+}
+
+// static
+bool AutocompleteMatch::IsSpecializedSearchType(Type type) {
+  return type == AutocompleteMatchType::SEARCH_SUGGEST_ENTITY ||
          type == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE ||
          type == AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED ||
-         type == AutocompleteMatchType::SEARCH_SUGGEST_PROFILE ||
-         type == AutocompleteMatchType::SEARCH_OTHER_ENGINE;
+         type == AutocompleteMatchType::SEARCH_SUGGEST_PROFILE;
 }
 
 void AutocompleteMatch::ComputeStrippedDestinationURL(Profile* profile) {
diff --git a/chrome/browser/autocomplete/autocomplete_match.h b/chrome/browser/autocomplete/autocomplete_match.h
index 07a7387..57c0efe 100644
--- a/chrome/browser/autocomplete/autocomplete_match.h
+++ b/chrome/browser/autocomplete/autocomplete_match.h
@@ -23,6 +23,10 @@
 class Time;
 }  // namespace base
 
+const char kACMatchPropertyInputText[] = "input text";
+const char kACMatchPropertyContentsPrefix[] = "match contents prefix";
+const char kACMatchPropertyContentsStartIndex[] = "match contents start index";
+
 // AutocompleteMatch ----------------------------------------------------------
 
 // A single result line with classified spans.  The autocomplete popup displays
@@ -162,6 +166,10 @@
   // an extension).
   static bool IsSearchType(Type type);
 
+  // Convenience function to check if |type| is a special search suggest type -
+  // like entity, personalized, profile or postfix.
+  static bool IsSpecializedSearchType(Type type);
+
   // Copies the destination_url with "www." stripped off to
   // |stripped_destination_url| and also converts https protocol to
   // http.  These two conversions are merely to allow comparisons to
diff --git a/chrome/browser/autocomplete/autocomplete_result.cc b/chrome/browser/autocomplete/autocomplete_result.cc
index 1eeed77..0391cfe 100644
--- a/chrome/browser/autocomplete/autocomplete_result.cc
+++ b/chrome/browser/autocomplete/autocomplete_result.cc
@@ -287,8 +287,17 @@
 }
 
 bool AutocompleteResult::TopMatchIsStandaloneVerbatimMatch() const {
-  return !empty() && match_at(0).IsVerbatimType() &&
-      ((size() == 1) || !match_at(1).IsVerbatimType());
+  if (empty() || !match_at(0).IsVerbatimType())
+    return false;
+
+  // Skip any copied matches, under the assumption that they'll be expired and
+  // disappear.  We don't want this disappearance to cause the visibility of the
+  // top match to change.
+  for (const_iterator i(begin() + 1); i != end(); ++i) {
+    if (!i->from_previous)
+      return !i->IsVerbatimType();
+  }
+  return true;
 }
 
 void AutocompleteResult::Reset() {
diff --git a/chrome/browser/autocomplete/autocomplete_result_unittest.cc b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
index 025c176..41d12c1 100644
--- a/chrome/browser/autocomplete/autocomplete_result_unittest.cc
+++ b/chrome/browser/autocomplete/autocomplete_result_unittest.cc
@@ -591,6 +591,35 @@
   EXPECT_FALSE(result.ShouldHideTopMatch());
 }
 
+TEST_F(AutocompleteResultTest, ShouldHideTopMatchAfterCopy) {
+  base::FieldTrialList::CreateFieldTrial("InstantExtended",
+                                         "Group1 hide_verbatim:1");
+  ACMatches matches;
+
+  // Case 1: Top match is a verbatim match followed by only copied matches.
+  PopulateAutocompleteMatchesFromTestData(kVerbatimMatches,
+                                          arraysize(kVerbatimMatches),
+                                          &matches);
+  for (size_t i = 1; i < arraysize(kVerbatimMatches); ++i)
+    matches[i].from_previous = true;
+  AutocompleteResult result;
+  result.AppendMatches(matches);
+  EXPECT_TRUE(result.ShouldHideTopMatch());
+  result.Reset();
+
+  // Case 2: The copied matches are then followed by a non-verbatim match.
+  PopulateAutocompleteMatchesFromTestData(kNonVerbatimMatches, 1, &matches);
+  result.AppendMatches(matches);
+  EXPECT_TRUE(result.ShouldHideTopMatch());
+  result.Reset();
+
+  // Case 3: The copied matches are instead followed by a verbatim match.
+  matches.back().from_previous = true;
+  PopulateAutocompleteMatchesFromTestData(kVerbatimMatches, 1, &matches);
+  result.AppendMatches(matches);
+  EXPECT_FALSE(result.ShouldHideTopMatch());
+}
+
 TEST_F(AutocompleteResultTest, DoNotHideTopMatch_FieldTrialFlagDisabled) {
   // This test config is identical to ShouldHideTopMatch test ("Case 1") except
   // that the "hide_verbatim" flag is disabled in the field trials.
diff --git a/chrome/browser/autocomplete/base_search_provider.cc b/chrome/browser/autocomplete/base_search_provider.cc
index 06e3cf3..82de99b 100644
--- a/chrome/browser/autocomplete/base_search_provider.cc
+++ b/chrome/browser/autocomplete/base_search_provider.cc
@@ -124,6 +124,20 @@
   return match.GetAdditionalInfo(kShouldPrefetchKey) == kTrue;
 }
 
+// static
+AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
+    const base::string16& suggestion,
+    AutocompleteMatchType::Type type,
+    bool from_keyword_provider,
+    const TemplateURL* template_url) {
+  return CreateSearchSuggestion(
+      NULL, AutocompleteInput(), BaseSearchProvider::SuggestResult(
+          suggestion, type, suggestion, base::string16(), base::string16(),
+          std::string(), std::string(), from_keyword_provider, 0, false, false,
+          base::string16()),
+      template_url, 0, 0, false);
+}
+
 void BaseSearchProvider::Stop(bool clear_cached_results) {
   StopSuggest();
   done_ = true;
@@ -435,12 +449,13 @@
   match.contents = suggestion.match_contents();
   match.contents_class = suggestion.match_contents_class();
   if (suggestion.type() == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE) {
-    match.RecordAdditionalInfo("input text", base::UTF16ToUTF8(input.text()));
     match.RecordAdditionalInfo(
-        "match contents prefix",
+        kACMatchPropertyInputText, base::UTF16ToUTF8(input.text()));
+    match.RecordAdditionalInfo(
+        kACMatchPropertyContentsPrefix,
         base::UTF16ToUTF8(suggestion.match_contents_prefix()));
     match.RecordAdditionalInfo(
-        "match contents start index",
+        kACMatchPropertyContentsStartIndex,
         static_cast<int>(
             suggestion.suggestion().length() - match.contents.length()));
   }
@@ -448,8 +463,10 @@
   if (!suggestion.annotation().empty())
     match.description = suggestion.annotation();
 
+  // suggestion.match_contents() should have already been collapsed.
   match.allowed_to_be_default_match =
-      (input.text() == suggestion.match_contents());
+      (base::CollapseWhitespace(input.text(), false) ==
+       suggestion.match_contents());
 
   // When the user forced a query, we need to make sure all the fill_into_edit
   // values preserve that property.  Otherwise, if the user starts editing a
@@ -795,6 +812,8 @@
   const bool allow_navsuggest = input.type() != AutocompleteInput::FORCED_QUERY;
   const std::string languages(
       profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
+  const base::string16& trimmed_input =
+      base::CollapseWhitespace(input.text(), false);
   for (size_t index = 0; results_list->GetString(index, &suggestion); ++index) {
     // Google search may return empty suggestions for weird input characters,
     // they make no sense at all and can cause problems in our code.
@@ -843,9 +862,11 @@
 
       // TODO(kochi): Improve calculator suggestion presentation.
       results->suggest_results.push_back(SuggestResult(
-          suggestion, match_type, match_contents, match_contents_prefix,
-          annotation, suggest_query_params, deletion_url, is_keyword_result,
-          relevance, relevances != NULL, should_prefetch, input.text()));
+          base::CollapseWhitespace(suggestion, false), match_type,
+          base::CollapseWhitespace(match_contents, false),
+          match_contents_prefix, annotation, suggest_query_params,
+          deletion_url, is_keyword_result, relevance, relevances != NULL,
+          should_prefetch, trimmed_input));
     }
   }
   SortResults(is_keyword_result, relevances, results);
diff --git a/chrome/browser/autocomplete/base_search_provider.h b/chrome/browser/autocomplete/base_search_provider.h
index bc77f13..86eab74 100644
--- a/chrome/browser/autocomplete/base_search_provider.h
+++ b/chrome/browser/autocomplete/base_search_provider.h
@@ -54,6 +54,16 @@
   // Returns whether |match| is flagged as a query that should be prefetched.
   static bool ShouldPrefetch(const AutocompleteMatch& match);
 
+  // Returns a simpler AutocompleteMatch suitable for persistence like in
+  // ShortcutsDatabase.
+  // NOTE: Use with care. Most likely you want the other CreateSearchSuggestion
+  // with protected access.
+  static AutocompleteMatch CreateSearchSuggestion(
+      const base::string16& suggestion,
+      AutocompleteMatchType::Type type,
+      bool from_keyword_provider,
+      const TemplateURL* template_url);
+
   // AutocompleteProvider:
   virtual void Stop(bool clear_cached_results) OVERRIDE;
   virtual void DeleteMatch(const AutocompleteMatch& match) OVERRIDE;
@@ -196,6 +206,7 @@
     // The contents to be displayed as prefix of match contents.
     // Used for postfix suggestions to display a leading ellipsis (or some
     // equivalent character) to indicate omitted text.
+    // Only used to pass this information to about:omnibox's "Additional Info".
     base::string16 match_contents_prefix_;
 
     // Optional annotation for the |match_contents_| for disambiguation.
diff --git a/chrome/browser/autocomplete/keyword_provider.cc b/chrome/browser/autocomplete/keyword_provider.cc
index 2878ed7..13c9920 100644
--- a/chrome/browser/autocomplete/keyword_provider.cc
+++ b/chrome/browser/autocomplete/keyword_provider.cc
@@ -592,8 +592,6 @@
         match->contents.assign(base::UTF8ToUTF16(suggestion.description));
         match->contents_class =
             extensions::StyleTypesToACMatchClassifications(suggestion);
-        match->description.clear();
-        match->description_class.clear();
       }
 
       done_ = true;
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc
index 1b77f34..70044e0 100644
--- a/chrome/browser/autocomplete/search_provider.cc
+++ b/chrome/browser/autocomplete/search_provider.cc
@@ -822,11 +822,13 @@
       TemplateURLRef::NO_SUGGESTIONS_AVAILABLE :
       TemplateURLRef::NO_SUGGESTION_CHOSEN;
   if (verbatim_relevance > 0) {
+    const base::string16& trimmed_verbatim =
+        base::CollapseWhitespace(input_.text(), false);
     SuggestResult verbatim(
-        input_.text(), AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
-        input_.text(), base::string16(), base::string16(), std::string(),
+        trimmed_verbatim, AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
+        trimmed_verbatim, base::string16(), base::string16(), std::string(),
         std::string(), false, verbatim_relevance, relevance_from_server, false,
-        input_.text());
+        trimmed_verbatim);
     AddMatchToMap(verbatim, std::string(), did_not_accept_default_suggestion,
                   false, &map);
   }
@@ -844,11 +846,13 @@
       const int keyword_verbatim_relevance =
           GetKeywordVerbatimRelevance(&keyword_relevance_from_server);
       if (keyword_verbatim_relevance > 0) {
+        const base::string16& trimmed_verbatim =
+            base::CollapseWhitespace(keyword_input_.text(), false);
         SuggestResult verbatim(
-            keyword_input_.text(), AutocompleteMatchType::SEARCH_OTHER_ENGINE,
-            keyword_input_.text(), base::string16(), base::string16(),
+            trimmed_verbatim, AutocompleteMatchType::SEARCH_OTHER_ENGINE,
+            trimmed_verbatim, base::string16(), base::string16(),
             std::string(), std::string(), true, keyword_verbatim_relevance,
-            keyword_relevance_from_server, false, keyword_input_.text());
+            keyword_relevance_from_server, false, trimmed_verbatim);
         AddMatchToMap(verbatim, std::string(),
                       did_not_accept_keyword_suggestion, false, &map);
       }
@@ -1061,12 +1065,18 @@
   const bool prevent_search_history_inlining =
       OmniboxFieldTrial::SearchHistoryPreventInlining(
           input_.current_page_classification());
+  const base::string16& trimmed_input =
+      base::CollapseWhitespace(input_text, false);
   for (HistoryResults::const_iterator i(results.begin()); i != results.end();
        ++i) {
+    const base::string16& trimmed_suggestion =
+        base::CollapseWhitespace(i->term, false);
+
     // Don't autocomplete multi-word queries that have only been seen once
     // unless the user has typed more than one word.
     bool prevent_inline_autocomplete = base_prevent_inline_autocomplete ||
-        (!input_multiple_words && (i->visits < 2) && HasMultipleWords(i->term));
+        (!input_multiple_words && (i->visits < 2) &&
+         HasMultipleWords(trimmed_suggestion));
 
     // Don't autocomplete search terms that would normally be treated as URLs
     // when typed. For example, if the user searched for "google.com" and types
@@ -1081,9 +1091,10 @@
     //  * When the user has typed the whole term, the "what you typed" history
     //    match will outrank us for URL-like inputs anyway, so we need not do
     //    anything special.
-    if (!prevent_inline_autocomplete && classifier && (i->term != input_text)) {
+    if (!prevent_inline_autocomplete && classifier &&
+        (trimmed_suggestion != trimmed_input)) {
       AutocompleteMatch match;
-      classifier->Classify(i->term, false, false,
+      classifier->Classify(trimmed_suggestion, false, false,
                            input_.current_page_classification(), &match, NULL);
       prevent_inline_autocomplete =
           !AutocompleteMatch::IsSearchType(match.type);
@@ -1093,9 +1104,9 @@
         i->time, is_keyword, !prevent_inline_autocomplete,
         prevent_search_history_inlining);
     scored_results.push_back(SuggestResult(
-        i->term, AutocompleteMatchType::SEARCH_HISTORY, i->term,
-        base::string16(), base::string16(), std::string(), std::string(),
-        is_keyword, relevance, false, false, input_text));
+        trimmed_suggestion, AutocompleteMatchType::SEARCH_HISTORY,
+        trimmed_suggestion, base::string16(), base::string16(), std::string(),
+        std::string(), is_keyword, relevance, false, false, trimmed_input));
   }
 
   // History returns results sorted for us.  However, we may have docked some
diff --git a/chrome/browser/autocomplete/search_provider_unittest.cc b/chrome/browser/autocomplete/search_provider_unittest.cc
index ae57ff8..968f531 100644
--- a/chrome/browser/autocomplete/search_provider_unittest.cc
+++ b/chrome/browser/autocomplete/search_provider_unittest.cc
@@ -364,7 +364,8 @@
   ASSERT_GE(provider_->matches().size(), 1u);
   EXPECT_TRUE(FindMatchWithDestination(GURL(
       default_t_url_->url_ref().ReplaceSearchTerms(
-          TemplateURLRef::SearchTermsArgs(text))),
+          TemplateURLRef::SearchTermsArgs(base::CollapseWhitespace(
+              text, false)))),
       wyt_match));
 }
 
@@ -741,10 +742,12 @@
   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
 }
 
-// Autocompletion should work at a word boundary after a space.
+// Autocompletion should work at a word boundary after a space, and should
+// offer a suggestion for the trimmed search query.
 TEST_F(SearchProviderTest, AutocompleteAfterSpace) {
-  GURL term_url(AddSearchToHistory(default_t_url_, ASCIIToUTF16("two searches"),
-                                   2));
+  AddSearchToHistory(default_t_url_, ASCIIToUTF16("two  searches "), 2);
+  GURL suggested_url(default_t_url_->url_ref().ReplaceSearchTerms(
+      TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("two searches"))));
   profile_.BlockUntilHistoryProcessesPendingRequests();
 
   AutocompleteMatch wyt_match;
@@ -752,9 +755,11 @@
                                                       &wyt_match));
   ASSERT_EQ(2u, provider_->matches().size());
   AutocompleteMatch term_match;
-  EXPECT_TRUE(FindMatchWithDestination(term_url, &term_match));
+  EXPECT_TRUE(FindMatchWithDestination(suggested_url, &term_match));
   EXPECT_GT(term_match.relevance, wyt_match.relevance);
   EXPECT_TRUE(term_match.allowed_to_be_default_match);
+  EXPECT_EQ(ASCIIToUTF16("searches"), term_match.inline_autocompletion);
+  EXPECT_EQ(ASCIIToUTF16("two searches"), term_match.fill_into_edit);
   EXPECT_TRUE(wyt_match.allowed_to_be_default_match);
 }
 
@@ -914,33 +919,41 @@
                    ASCIIToUTF16("k foo") ) } },
 
     // Make sure extra whitespace after the keyword doesn't change the
-    // keyword verbatim query.
+    // keyword verbatim query.  Also verify that interior consecutive
+    // whitespace gets trimmed.
     { ASCIIToUTF16("k   foo"), 2,
       { ResultInfo(GURL("http://keyword/foo"),
                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
                    true,
                    ASCIIToUTF16("k foo")),
-        ResultInfo(GURL("http://defaultturl/k%20%20%20foo"),
+        ResultInfo(GURL("http://defaultturl/k%20foo"),
                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
                    false,
-                   ASCIIToUTF16("k   foo")) } },
+                   ASCIIToUTF16("k foo")) } },
     // Leading whitespace should be stripped before SearchProvider gets the
     // input; hence there are no tests here about how it handles those inputs.
 
-    // But whitespace elsewhere in the query string should matter to both
-    // matches.
+    // Verify that interior consecutive whitespace gets trimmed in either case.
     { ASCIIToUTF16("k  foo  bar"), 2,
-      { ResultInfo(GURL("http://keyword/foo%20%20bar"),
+      { ResultInfo(GURL("http://keyword/foo%20bar"),
                    AutocompleteMatchType::SEARCH_OTHER_ENGINE,
                    true,
-                   ASCIIToUTF16("k foo  bar")),
-        ResultInfo(GURL("http://defaultturl/k%20%20foo%20%20bar"),
+                   ASCIIToUTF16("k foo bar")),
+        ResultInfo(GURL("http://defaultturl/k%20foo%20bar"),
                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
                    false,
-                   ASCIIToUTF16("k  foo  bar")) } },
-    // Note in the above test case we don't test trailing whitespace because
-    // SearchProvider still doesn't handle this well.  See related bugs:
-    // 102690, 99239, 164635.
+                   ASCIIToUTF16("k foo bar")) } },
+
+    // Verify that trailing whitespace gets trimmed.
+    { ASCIIToUTF16("k foo bar  "), 2,
+      { ResultInfo(GURL("http://keyword/foo%20bar"),
+                   AutocompleteMatchType::SEARCH_OTHER_ENGINE,
+                   true,
+                   ASCIIToUTF16("k foo bar")),
+        ResultInfo(GURL("http://defaultturl/k%20foo%20bar"),
+                   AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
+                   false,
+                   ASCIIToUTF16("k foo bar")) } },
 
     // Keywords can be prefixed by certain things that should get ignored
     // when constructing the keyword match.
@@ -979,11 +992,12 @@
                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
                    true,
                    ASCIIToUTF16("k")) } },
+    // Ditto.  Trailing whitespace shouldn't make a difference.
     { ASCIIToUTF16("k "), 1,
-      { ResultInfo(GURL("http://defaultturl/k%20"),
+      { ResultInfo(GURL("http://defaultturl/k"),
                    AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
                    true,
-                   ASCIIToUTF16("k ")) } }
+                   ASCIIToUTF16("k")) } }
 
     // The fact that verbatim queries to keyword are handled by KeywordProvider
     // not SearchProvider is tested in
diff --git a/chrome/browser/autocomplete/shortcuts_backend.cc b/chrome/browser/autocomplete/shortcuts_backend.cc
index b7d5d78..ea5c9e7 100644
--- a/chrome/browser/autocomplete/shortcuts_backend.cc
+++ b/chrome/browser/autocomplete/shortcuts_backend.cc
@@ -13,14 +13,17 @@
 #include "base/guid.h"
 #include "base/i18n/case_conversion.h"
 #include "base/strings/string_util.h"
+#include "chrome/browser/autocomplete/autocomplete_input.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 #include "chrome/browser/autocomplete/autocomplete_result.h"
+#include "chrome/browser/autocomplete/base_search_provider.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/history/history_notifications.h"
 #include "chrome/browser/history/history_service.h"
 #include "chrome/browser/history/shortcuts_database.h"
 #include "chrome/browser/omnibox/omnibox_log.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/autocomplete_match_type.h"
 #include "chrome/common/chrome_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
@@ -52,16 +55,12 @@
     case AutocompleteMatchType::NAVSUGGEST:
       return AutocompleteMatchType::HISTORY_URL;
 
-    case AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED:
-    case AutocompleteMatchType::SEARCH_SUGGEST:
-    case AutocompleteMatchType::SEARCH_SUGGEST_ENTITY:
-    case AutocompleteMatchType::SEARCH_SUGGEST_INFINITE:
-    case AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED:
-    case AutocompleteMatchType::SEARCH_SUGGEST_PROFILE:
-      return AutocompleteMatchType::SEARCH_HISTORY;
+    case AutocompleteMatchType::SEARCH_OTHER_ENGINE:
+      return type;
 
     default:
-      return type;
+      return AutocompleteMatch::IsSearchType(type) ?
+          AutocompleteMatchType::SEARCH_HISTORY : type;
   }
 }
 
@@ -71,7 +70,8 @@
 // ShortcutsBackend -----------------------------------------------------------
 
 ShortcutsBackend::ShortcutsBackend(Profile* profile, bool suppress_db)
-    : current_state_(NOT_INITIALIZED),
+    : profile_(profile),
+      current_state_(NOT_INITIALIZED),
       no_db_access_(suppress_db) {
   if (!suppress_db) {
     db_ = new history::ShortcutsDatabase(
@@ -124,13 +124,13 @@
            StartsWith(it->first, text_lowercase, true); ++it) {
     if (match.destination_url == it->second.match_core.destination_url) {
       UpdateShortcut(history::ShortcutsDatabase::Shortcut(
-          it->second.id, text, MatchToMatchCore(match), now,
+          it->second.id, text, MatchToMatchCore(match, profile_), now,
           it->second.number_of_hits + 1));
       return;
     }
   }
   AddShortcut(history::ShortcutsDatabase::Shortcut(
-      base::GenerateGUID(), text, MatchToMatchCore(match), now, 1));
+      base::GenerateGUID(), text, MatchToMatchCore(match, profile_), now, 1));
 }
 
 ShortcutsBackend::~ShortcutsBackend() {
@@ -138,12 +138,23 @@
 
 // static
 history::ShortcutsDatabase::Shortcut::MatchCore
-    ShortcutsBackend::MatchToMatchCore(const AutocompleteMatch& match) {
+    ShortcutsBackend::MatchToMatchCore(const AutocompleteMatch& match,
+                                       Profile* profile) {
+  const AutocompleteMatch::Type match_type = GetTypeForShortcut(match.type);
+  const AutocompleteMatch& normalized_match =
+      AutocompleteMatch::IsSpecializedSearchType(match.type) ?
+          BaseSearchProvider::CreateSearchSuggestion(
+              match.search_terms_args->search_terms, match_type,
+              (match.transition == content::PAGE_TRANSITION_KEYWORD),
+              match.GetTemplateURL(profile, false)) :
+          match;
   return history::ShortcutsDatabase::Shortcut::MatchCore(
-      match.fill_into_edit, match.destination_url, match.contents,
-      StripMatchMarkers(match.contents_class), match.description,
-      StripMatchMarkers(match.description_class), match.transition,
-      GetTypeForShortcut(match.type), match.keyword);
+      normalized_match.fill_into_edit, normalized_match.destination_url,
+      normalized_match.contents,
+      StripMatchMarkers(normalized_match.contents_class),
+      normalized_match.description,
+      StripMatchMarkers(normalized_match.description_class),
+      normalized_match.transition, match_type, normalized_match.keyword);
 }
 
 void ShortcutsBackend::ShutdownOnUIThread() {
diff --git a/chrome/browser/autocomplete/shortcuts_backend.h b/chrome/browser/autocomplete/shortcuts_backend.h
index 0e89d9a..64f3bcc 100644
--- a/chrome/browser/autocomplete/shortcuts_backend.h
+++ b/chrome/browser/autocomplete/shortcuts_backend.h
@@ -80,6 +80,7 @@
   friend class base::RefCountedThreadSafe<ShortcutsBackend>;
   friend class ShortcutsProviderTest;
   friend class ShortcutsBackendTest;
+  FRIEND_TEST_ALL_PREFIXES(ShortcutsBackendTest, EntitySuggestionTest);
 
   enum CurrentState {
     NOT_INITIALIZED,  // Backend created but not initialized.
@@ -93,7 +94,7 @@
   virtual ~ShortcutsBackend();
 
   static history::ShortcutsDatabase::Shortcut::MatchCore MatchToMatchCore(
-      const AutocompleteMatch& match);
+      const AutocompleteMatch& match, Profile* profile);
 
   // RefcountedBrowserContextKeyedService:
   virtual void ShutdownOnUIThread() OVERRIDE;
@@ -127,6 +128,7 @@
   // Deletes all of the shortcuts.
   bool DeleteAllShortcuts();
 
+  Profile* profile_;
   CurrentState current_state_;
   ObserverList<ShortcutsBackendObserver> observer_list_;
   scoped_refptr<history::ShortcutsDatabase> db_;
diff --git a/chrome/browser/autocomplete/shortcuts_backend_unittest.cc b/chrome/browser/autocomplete/shortcuts_backend_unittest.cc
index 7e4455a3..fa055af 100644
--- a/chrome/browser/autocomplete/shortcuts_backend_unittest.cc
+++ b/chrome/browser/autocomplete/shortcuts_backend_unittest.cc
@@ -11,7 +11,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
 #include "chrome/browser/history/shortcuts_database.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/test_browser_thread.h"
 #include "sql/statement.h"
 
@@ -30,6 +33,7 @@
     const std::string& contents_class = std::string(),
     const std::string& description_class = std::string(),
     AutocompleteMatch::Type type = AutocompleteMatchType::URL_WHAT_YOU_TYPED);
+  void SetSearchProvider();
 
   virtual void SetUp();
   virtual void TearDown();
@@ -52,9 +56,10 @@
   bool DeleteShortcutsWithIDs(
       const history::ShortcutsDatabase::ShortcutIDs& deleted_ids);
 
+ protected:
+  TestingProfile profile_;
 
  private:
-  TestingProfile profile_;
   scoped_refptr<ShortcutsBackend> backend_;
   base::MessageLoopForUI ui_message_loop_;
   content::TestBrowserThread ui_thread_;
@@ -86,7 +91,22 @@
       AutocompleteMatch::ClassificationsFromString(contents_class);
   match.description_class =
       AutocompleteMatch::ClassificationsFromString(description_class);
-  return ShortcutsBackend::MatchToMatchCore(match);
+  match.search_terms_args.reset(
+      new TemplateURLRef::SearchTermsArgs(match.contents));
+  return ShortcutsBackend::MatchToMatchCore(match, &profile_);
+}
+
+void ShortcutsBackendTest::SetSearchProvider() {
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(&profile_);
+  TemplateURLData data;
+  data.SetURL("http://foo.com/search?bar={searchTerms}");
+  data.SetKeyword(base::UTF8ToUTF16("foo"));
+
+  TemplateURL* template_url = new TemplateURL(&profile_, data);
+  // Takes ownership of |template_url|.
+  template_url_service->Add(template_url);
+  template_url_service->SetDefaultSearchProvider(template_url);
 }
 
 void ShortcutsBackendTest::SetUp() {
@@ -96,6 +116,12 @@
   backend_ = ShortcutsBackendFactory::GetForProfile(&profile_);
   ASSERT_TRUE(backend_.get());
   backend_->AddObserver(this);
+
+  TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+      &profile_, &TemplateURLServiceFactory::BuildInstanceFor);
+  TemplateURLService* template_url_service =
+      TemplateURLServiceFactory::GetForProfile(&profile_);
+  ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service);
 }
 
 void ShortcutsBackendTest::TearDown() {
@@ -156,14 +182,23 @@
     std::string output_description_class;
     AutocompleteMatch::Type output_type;
   } cases[] = {
-    { "0,1,4,0", "0,3,4,1",       AutocompleteMatchType::URL_WHAT_YOU_TYPED,
-      "0,1,4,0", "0,1",           AutocompleteMatchType::HISTORY_URL },
-    { "0,3,5,1", "0,2,5,0",       AutocompleteMatchType::NAVSUGGEST,
-      "0,1",     "0,0",           AutocompleteMatchType::HISTORY_URL },
-    { "0,1",     "0,0,11,2,15,0", AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
-      "0,1",     "0,0",           AutocompleteMatchType::SEARCH_HISTORY },
-    { "0,1",     "0,0",           AutocompleteMatchType::SEARCH_SUGGEST,
-      "0,1",     "0,0",           AutocompleteMatchType::SEARCH_HISTORY },
+    { "0,1,4,0", "0,3,4,1",  AutocompleteMatchType::URL_WHAT_YOU_TYPED,
+      "0,1,4,0", "0,1",      AutocompleteMatchType::HISTORY_URL },
+    { "0,3,5,1", "0,2,5,0",  AutocompleteMatchType::NAVSUGGEST,
+      "0,1",     "0,0",      AutocompleteMatchType::HISTORY_URL },
+    { "0,1",     "0,0,11,2,15,0",
+                             AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED,
+      "0,1",     "0,0",      AutocompleteMatchType::SEARCH_HISTORY },
+    { "0,1",     "0,0",      AutocompleteMatchType::SEARCH_SUGGEST,
+      "0,1",     "0,0",      AutocompleteMatchType::SEARCH_HISTORY },
+    { "0,1",     "0,0",      AutocompleteMatchType::SEARCH_SUGGEST_ENTITY,
+      "",        "",         AutocompleteMatchType::SEARCH_HISTORY },
+    { "0,1",     "0,0",      AutocompleteMatchType::SEARCH_SUGGEST_INFINITE,
+      "",        "",         AutocompleteMatchType::SEARCH_HISTORY },
+    { "0,1",     "0,0",      AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED,
+      "",        "",         AutocompleteMatchType::SEARCH_HISTORY },
+    { "0,1",     "0,0",      AutocompleteMatchType::SEARCH_SUGGEST_PROFILE,
+      "",        "",         AutocompleteMatchType::SEARCH_HISTORY },
   };
 
   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
@@ -171,12 +206,42 @@
         MatchCoreForTesting(std::string(), cases[i].input_contents_class,
                             cases[i].input_description_class,
                             cases[i].input_type));
-    EXPECT_EQ(cases[i].output_contents_class, match_core.contents_class);
-    EXPECT_EQ(cases[i].output_description_class, match_core.description_class);
-    EXPECT_EQ(cases[i].output_type, match_core.type);
+    EXPECT_EQ(cases[i].output_contents_class, match_core.contents_class)
+        << ":i:" << i << ":type:" << cases[i].input_type;
+    EXPECT_EQ(cases[i].output_description_class, match_core.description_class)
+        << ":i:" << i << ":type:" << cases[i].input_type;
+    EXPECT_EQ(cases[i].output_type, match_core.type)
+        << ":i:" << i << ":type:" << cases[i].input_type;
   }
 }
 
+TEST_F(ShortcutsBackendTest, EntitySuggestionTest) {
+  SetSearchProvider();
+  AutocompleteMatch match;
+  match.fill_into_edit = base::UTF8ToUTF16("franklin d roosevelt");
+  match.type = AutocompleteMatchType::SEARCH_SUGGEST_ENTITY;
+  match.contents = base::UTF8ToUTF16("roosevelt");
+  match.contents_class =
+      AutocompleteMatch::ClassificationsFromString("0,0,5,2");
+  match.description = base::UTF8ToUTF16("Franklin D. Roosevelt");
+  match.description_class = AutocompleteMatch::ClassificationsFromString("0,4");
+  match.destination_url = GURL(
+      "http://www.foo.com/search?bar=franklin+d+roosevelt&gs_ssp=1234");
+  match.keyword = base::UTF8ToUTF16("foo");
+  match.search_terms_args.reset(
+      new TemplateURLRef::SearchTermsArgs(match.fill_into_edit));
+
+  history::ShortcutsDatabase::Shortcut::MatchCore match_core =
+      ShortcutsBackend::MatchToMatchCore(match, &profile_);
+
+  EXPECT_EQ("http://foo.com/search?bar=franklin+d+roosevelt",
+            match_core.destination_url.spec());
+  EXPECT_EQ(match.fill_into_edit, match_core.contents);
+  EXPECT_EQ("0,0", match_core.contents_class);
+  EXPECT_EQ(base::string16(), match_core.description);
+  EXPECT_TRUE(match_core.description_class.empty());
+}
+
 TEST_F(ShortcutsBackendTest, AddAndUpdateShortcut) {
   InitBackend();
   EXPECT_FALSE(changed_notified());
diff --git a/chrome/browser/autocomplete/zero_suggest_provider.cc b/chrome/browser/autocomplete/zero_suggest_provider.cc
index 52b1cd1..6fe499f 100644
--- a/chrome/browser/autocomplete/zero_suggest_provider.cc
+++ b/chrome/browser/autocomplete/zero_suggest_provider.cc
@@ -81,32 +81,17 @@
 }
 
 void ZeroSuggestProvider::Start(const AutocompleteInput& input,
-                                bool /*minimal_changes*/) {
-}
+                                bool minimal_changes) {
+  matches_.clear();
+  if (input.type() == AutocompleteInput::INVALID)
+    return;
 
-void ZeroSuggestProvider::ResetSession() {
-  // The user has started editing in the omnibox, so leave
-  // |field_trial_triggered_in_session_| unchanged and set
-  // |field_trial_triggered_| to false since zero suggest is inactive now.
-  field_trial_triggered_ = false;
-
-  // This call clears out |matches_| so that they don't pollute prefix-based
-  // queries.
-  // TODO(mariakhomenko): Change the model to clear |matches_| on Start() like
-  // all the other providers.
-  Stop(true);
-}
-
-void ZeroSuggestProvider::StartZeroSuggest(
-    const GURL& current_page_url,
-    AutocompleteInput::PageClassification page_classification,
-    const base::string16& permanent_text) {
   Stop(true);
   field_trial_triggered_ = false;
   field_trial_triggered_in_session_ = false;
-  permanent_text_ = permanent_text;
-  current_query_ = current_page_url.spec();
-  current_page_classification_ = page_classification;
+  permanent_text_ = input.text();
+  current_query_ = input.current_url().spec();
+  current_page_classification_ = input.current_page_classification();
   current_url_match_ = MatchForCurrentURL();
 
   const TemplateURL* default_provider =
@@ -122,7 +107,7 @@
     return;
 
   // No need to send the current page URL in personalized suggest field trial.
-  if (CanSendURL(current_page_url, suggest_url, default_provider,
+  if (CanSendURL(input.current_url(), suggest_url, default_provider,
                  current_page_classification_, profile_) &&
       !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) {
     // Update suggest_url to include the current_page_url.
@@ -130,7 +115,7 @@
     suggest_url = GURL(default_provider->suggestions_url_ref().
                        ReplaceSearchTerms(search_term_args));
   } else if (!CanShowZeroSuggestWithoutSendingURL(suggest_url,
-                                                  current_page_url)) {
+                                                  input.current_url())) {
     return;
   }
 
@@ -141,6 +126,13 @@
   Run(suggest_url);
 }
 
+void ZeroSuggestProvider::ResetSession() {
+  // The user has started editing in the omnibox, so leave
+  // |field_trial_triggered_in_session_| unchanged and set
+  // |field_trial_triggered_| to false since zero suggest is inactive now.
+  field_trial_triggered_ = false;
+}
+
 ZeroSuggestProvider::ZeroSuggestProvider(
   AutocompleteProviderListener* listener,
   Profile* profile)
@@ -193,7 +185,6 @@
   results_.suggest_results.clear();
   results_.navigation_results.clear();
   current_query_.clear();
-  matches_.clear();
 }
 
 int ZeroSuggestProvider::GetDefaultResultRelevance() const {
@@ -356,10 +347,6 @@
 }
 
 AutocompleteMatch ZeroSuggestProvider::MatchForCurrentURL() {
-  AutocompleteInput input(permanent_text_, base::string16::npos, base::string16(),
-                          GURL(current_query_), current_page_classification_,
-                          false, false, true, AutocompleteInput::ALL_MATCHES);
-
   AutocompleteMatch match;
   AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(
       permanent_text_, false, true, current_page_classification_, &match, NULL);
diff --git a/chrome/browser/autocomplete/zero_suggest_provider.h b/chrome/browser/autocomplete/zero_suggest_provider.h
index 59282e7..68acf23 100644
--- a/chrome/browser/autocomplete/zero_suggest_provider.h
+++ b/chrome/browser/autocomplete/zero_suggest_provider.h
@@ -49,19 +49,11 @@
 
   // AutocompleteProvider:
   virtual void Start(const AutocompleteInput& input,
-                     bool /*minimal_changes*/) OVERRIDE;
+                     bool minimal_changes) OVERRIDE;
 
   // Sets |field_trial_triggered_| to false.
   virtual void ResetSession() OVERRIDE;
 
-  // Initiates a new fetch for the given |url| of classification
-  // |page_classification|. |permanent_text| is the omnibox text
-  // for the current page.
-  void StartZeroSuggest(
-      const GURL& curent_page_url,
-      AutocompleteInput::PageClassification page_classification,
-      const base::string16& permanent_text);
-
  private:
   ZeroSuggestProvider(AutocompleteProviderListener* listener,
                       Profile* profile);
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc
index 6707986..f1e2b62 100644
--- a/chrome/browser/autofill/autofill_interactive_uitest.cc
+++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -490,7 +490,9 @@
 }
 
 // Test that a JavaScript onchange event is fired after auto-filling a form.
-IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, OnChangeAfterAutofill) {
+// Temporarily disabled for crbug.com/353691.
+IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest,
+                       DISABLED_OnChangeAfterAutofill) {
   CreateTestProfile();
 
   const char* kOnChangeScript =
diff --git a/chrome/browser/autofill/risk/fingerprint_browsertest.cc b/chrome/browser/autofill/risk/fingerprint_browsertest.cc
index 7b7bea4..03e5c7f 100644
--- a/chrome/browser/autofill/risk/fingerprint_browsertest.cc
+++ b/chrome/browser/autofill/risk/fingerprint_browsertest.cc
@@ -95,11 +95,15 @@
     EXPECT_TRUE(machine.cpu().has_vendor_name());
     EXPECT_TRUE(machine.cpu().has_brand());
     EXPECT_TRUE(machine.has_ram());
-    ASSERT_TRUE(machine.has_graphics_card());
-    EXPECT_TRUE(machine.graphics_card().has_vendor_id());
-    EXPECT_TRUE(machine.graphics_card().has_device_id());
     EXPECT_TRUE(machine.has_browser_build());
     EXPECT_TRUE(machine.has_browser_feature());
+    if (content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL)) {
+      ASSERT_TRUE(machine.has_graphics_card());
+      EXPECT_TRUE(machine.graphics_card().has_vendor_id());
+      EXPECT_TRUE(machine.graphics_card().has_device_id());
+    } else {
+      EXPECT_FALSE(machine.has_graphics_card());
+    }
 
     ASSERT_TRUE(fingerprint->has_transient_state());
     const Fingerprint::TransientState& transient_state =
@@ -173,11 +177,6 @@
 
 // Test that getting a fingerprint works on some basic level.
 IN_PROC_BROWSER_TEST_F(AutofillRiskFingerprintTest, GetFingerprint) {
-  // This test hangs when there is no GPU process.
-  // http://crbug.com/327272
-  if (!content::GpuDataManager::GetInstance()->GpuAccessAllowed(NULL))
-    return;
-
   content::Geoposition position;
   position.latitude = kLatitude;
   position.longitude = kLongitude;
diff --git a/chrome/browser/automation/automation_provider_observers.cc b/chrome/browser/automation/automation_provider_observers.cc
index 2048e27..8dae793 100644
--- a/chrome/browser/automation/automation_provider_observers.cc
+++ b/chrome/browser/automation/automation_provider_observers.cc
@@ -1751,8 +1751,8 @@
   base::ListValue* default_sites_list = new base::ListValue;
   history::MostVisitedURLList urls = top_sites_->GetPrepopulatePages();
   for (size_t i = 0; i < urls.size(); ++i) {
-    default_sites_list->Append(base::Value::CreateStringValue(
-        urls[i].url.possibly_invalid_spec()));
+    default_sites_list->Append(
+        new base::StringValue(urls[i].url.possibly_invalid_spec()));
   }
   ntp_info_->Set("default_sites", default_sites_list);
 
@@ -2110,8 +2110,7 @@
       base::ListValue* titles = new base::ListValue();
       for (size_t title_index = 0; title_index < iterator->titles.size();
            ++title_index) {
-        titles->Append(
-            base::Value::CreateStringValue(iterator->titles[title_index]));
+        titles->Append(new base::StringValue(iterator->titles[title_index]));
       }
       proc_data->Set("titles", titles);
 
diff --git a/chrome/browser/automation/testing_automation_provider.cc b/chrome/browser/automation/testing_automation_provider.cc
index e461641..12fc4d3 100644
--- a/chrome/browser/automation/testing_automation_provider.cc
+++ b/chrome/browser/automation/testing_automation_provider.cc
@@ -915,7 +915,7 @@
     }
 
     drop_data.filenames.push_back(
-        content::DropData::FileInfo(path, base::string16()));
+        ui::FileInfo(base::FilePath::FromUTF16Unsafe(path), base::FilePath()));
   }
 
   const gfx::Point client(x, y);
diff --git a/chrome/browser/background/background_contents_service.cc b/chrome/browser/background/background_contents_service.cc
index 46918a1..c05cec3 100644
--- a/chrome/browser/background/background_contents_service.cc
+++ b/chrome/browser/background/background_contents_service.cc
@@ -40,6 +40,7 @@
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/browser/extension_host.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
@@ -221,12 +222,18 @@
       !g_browser_process->profile_manager()->IsValidProfile(profile)) {
       return;
   }
+
   extensions::ExtensionSystem* extension_system =
       extensions::ExtensionSystem::Get(profile);
-  if (!extension_system || !extension_system->extension_service())
+  extensions::ExtensionRegistry* extension_registry =
+      extensions::ExtensionRegistry::Get(profile);
+  if (!extension_system || !extension_system->extension_service() ||
+      !extension_registry) {
     return;
-  if (!extension_system->extension_service()->
-          GetTerminatedExtension(extension_id)) {
+  }
+
+  if (!extension_registry->GetExtensionById(
+          extension_id, extensions::ExtensionRegistry::TERMINATED)) {
     // Either the app/extension was uninstalled by policy or it has since
     // been restarted successfully by someone else (the user).
     return;
diff --git a/chrome/browser/bookmarks/bookmark_html_writer.cc b/chrome/browser/bookmarks/bookmark_html_writer.cc
index c0cbd9c..5e075af 100644
--- a/chrome/browser/bookmarks/bookmark_html_writer.cc
+++ b/chrome/browser/bookmarks/bookmark_html_writer.cc
@@ -8,6 +8,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
+#include "base/files/file.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/platform_file.h"
@@ -25,8 +26,6 @@
 #include "content/public/browser/notification_source.h"
 #include "grit/generated_resources.h"
 #include "net/base/escape.h"
-#include "net/base/file_stream.h"
-#include "net/base/net_errors.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/favicon_size.h"
 
@@ -145,8 +144,8 @@
 
     Write(kFolderChildrenEnd);
     Write(kNewline);
-    // File stream close is forced so that unit test could read it.
-    file_stream_.reset();
+    // File close is forced so that unit test could read it.
+    file_.reset();
 
     NotifyOnFinish();
   }
@@ -169,9 +168,9 @@
 
   // Opens the file, returning true on success.
   bool OpenFile() {
-    file_stream_.reset(new net::FileStream(NULL));
-    int flags = base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
-    return (file_stream_->OpenSync(path_, flags) == net::OK);
+    int flags = base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE;
+    file_.reset(new base::File(path_, flags));
+    return file_->IsValid();
   }
 
   // Increments the indent.
@@ -195,10 +194,9 @@
   // Writes raw text out returning true on success. This does not escape
   // the text in anyway.
   bool Write(const std::string& text) {
-    // net::FileStream does not allow 0-byte writes.
     if (!text.length())
       return true;
-    size_t wrote = file_stream_->WriteSync(text.c_str(), text.length());
+    size_t wrote = file_->WriteAtCurrentPos(text.c_str(), text.length());
     bool result = (wrote == text.length());
     DCHECK(result);
     return result;
@@ -373,7 +371,7 @@
   BookmarksExportObserver* observer_;
 
   // File we're writing to.
-  scoped_ptr<net::FileStream> file_stream_;
+  scoped_ptr<base::File> file_;
 
   // How much we indent when writing a bookmark/folder. This is modified
   // via IncrementIndent and DecrementIndent.
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index e87427b..a67eb35 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -286,7 +286,9 @@
   platform_part()->StartTearDown();
 
 #if defined(ENABLE_WEBRTC)
-  webrtc_log_uploader_.reset();
+  // Cancel any uploads to release the system url request context references.
+  if (webrtc_log_uploader_)
+    webrtc_log_uploader_->StartShutdown();
 #endif
 
   if (local_state())
@@ -297,6 +299,11 @@
   // With the file_thread_ flushed, we can release any icon resources.
   icon_manager_.reset();
 
+#if defined(ENABLE_WEBRTC)
+  // Must outlive the file thread.
+  webrtc_log_uploader_.reset();
+#endif
+
   // Reset associated state right after actual thread is stopped,
   // as io_thread_.global_ cleanup happens in CleanUp on the IO
   // thread, i.e. as the thread exits its message loop.
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index f5413f8..9109e40 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -337,6 +337,7 @@
       </if>
       <if expr="chromeos">
         <include name="IDR_FILEMANAGER_MANIFEST" file="resources\file_manager\manifest.json" type="BINDATA" />
+        <include name="IDR_VIDEOPLAYER_MANIFEST" file="resources\video_player\manifest.json" type="BINDATA" />
       </if>
       <if expr="image_loader_extension">
         <include name="IDR_IMAGE_LOADER_MANIFEST" file="resources\image_loader\manifest.json" type="BINDATA" />
@@ -397,6 +398,7 @@
       </if>
       <if expr="chromeos">
         <include name="IDR_SOUND_STARTUP_WAV" file="resources\chromeos\sounds\startup.wav" type="BINDATA" />
+        <include name="IDR_SOUND_STARTUP2_WAV" file="resources\chromeos\sounds\startup2.wav" type="BINDATA" />
         <include name="IDR_SOUND_LOCK_WAV" file="resources\chromeos\sounds\lock.wav" type="BINDATA" />
         <include name="IDR_SOUND_UNLOCK_WAV" file="resources\chromeos\sounds\unlock.wav" type="BINDATA" />
         <include name="IDR_SOUND_SHUTDOWN_WAV" file="resources\chromeos\sounds\shutdown.wav" type="BINDATA" />
diff --git a/chrome/browser/browser_shutdown.cc b/chrome/browser/browser_shutdown.cc
index 7ebee0d..37b1ba3 100644
--- a/chrome/browser/browser_shutdown.cc
+++ b/chrome/browser/browser_shutdown.cc
@@ -18,9 +18,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
-#include "build/build_config.h"
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/first_run/upgrade_util.h"
@@ -36,8 +34,6 @@
 #include "chrome/common/switch_utils.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/browser_util_win.h"
@@ -62,9 +58,6 @@
 // Whether the browser is trying to quit (e.g., Quit chosen from menu).
 bool g_trying_to_quit = false;
 
-// Whether the browser should quit without closing browsers.
-bool g_shutting_down_without_closing_browsers = false;
-
 #if defined(OS_WIN)
 upgrade_util::RelaunchMode g_relaunch_mode =
     upgrade_util::RELAUNCH_MODE_DEFAULT;
@@ -346,12 +339,4 @@
   return g_trying_to_quit;
 }
 
-bool ShuttingDownWithoutClosingBrowsers() {
-  return g_shutting_down_without_closing_browsers;
-}
-
-void SetShuttingDownWithoutClosingBrowsers(bool without_close) {
-  g_shutting_down_without_closing_browsers = without_close;
-}
-
 }  // namespace browser_shutdown
diff --git a/chrome/browser/browser_shutdown.h b/chrome/browser/browser_shutdown.h
index 208bb1d..f53de37 100644
--- a/chrome/browser/browser_shutdown.h
+++ b/chrome/browser/browser_shutdown.h
@@ -66,15 +66,6 @@
 // General accessor.
 bool IsTryingToQuit();
 
-// This is true on X during an END_SESSION initiated by X IO Error, when we
-// can no longer depend on the X server to be running. As a result we don't
-// explicitly close the browser windows, which can lead to conditions which
-// would fail checks.
-bool ShuttingDownWithoutClosingBrowsers();
-
-// Sets the ShuttingDownWithoutClosingBrowsers flag.
-void SetShuttingDownWithoutClosingBrowsers(bool without_close);
-
 }  // namespace browser_shutdown
 
 #endif  // CHROME_BROWSER_BROWSER_SHUTDOWN_H__
diff --git a/chrome/browser/browsing_data/browsing_data_remover.cc b/chrome/browser/browsing_data/browsing_data_remover.cc
index aeee8d5..2c070d1 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover.cc
@@ -31,6 +31,10 @@
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/media/media_device_id_salt.h"
+#if defined(ENABLE_WEBRTC)
+#include "chrome/browser/media/webrtc_log_list.h"
+#include "chrome/browser/media/webrtc_log_util.h"
+#endif
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
@@ -195,6 +199,9 @@
       waiting_for_clear_pnacl_cache_(false),
       waiting_for_clear_server_bound_certs_(false),
       waiting_for_clear_storage_partition_data_(false),
+#if defined(ENABLE_WEBRTC)
+      waiting_for_clear_webrtc_logs_(false),
+#endif
       remove_mask_(0),
       remove_origin_(GURL()),
       origin_set_mask_(0),
@@ -375,6 +382,18 @@
         data_manager->Refresh();
     }
 
+#if defined(ENABLE_WEBRTC)
+    waiting_for_clear_webrtc_logs_ = true;
+    BrowserThread::PostTaskAndReply(
+        BrowserThread::FILE,
+        FROM_HERE,
+        base::Bind(
+            &WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles,
+            WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath()),
+            delete_begin_),
+        base::Bind(&BrowsingDataRemover::OnClearedWebRtcLogs,
+                   base::Unretained(this)));
+#endif
   }
 
   if ((remove_mask & REMOVE_DOWNLOADS) && may_delete_history) {
@@ -707,6 +726,9 @@
          !waiting_for_clear_hostname_resolution_cache_ &&
          !waiting_for_clear_network_predictor_ &&
          !waiting_for_clear_platform_keys_ &&
+#if defined(ENABLE_WEBRTC)
+         !waiting_for_clear_webrtc_logs_ &&
+#endif
          !waiting_for_clear_storage_partition_data_;
 }
 
@@ -1077,3 +1099,11 @@
   waiting_for_clear_storage_partition_data_ = false;
   NotifyAndDeleteIfDone();
 }
+
+#if defined(ENABLE_WEBRTC)
+void BrowsingDataRemover::OnClearedWebRtcLogs() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  waiting_for_clear_webrtc_logs_ = false;
+  NotifyAndDeleteIfDone();
+}
+#endif
diff --git a/chrome/browser/browsing_data/browsing_data_remover.h b/chrome/browser/browsing_data/browsing_data_remover.h
index df9bd61..4b4603d 100644
--- a/chrome/browser/browsing_data/browsing_data_remover.h
+++ b/chrome/browser/browsing_data/browsing_data_remover.h
@@ -341,10 +341,14 @@
   // been deleted.
   void OnClearedAutofillOriginURLs();
 
-
   // Callback on UI thread when the storage partition related data are cleared.
   void OnClearedStoragePartitionData();
 
+#if defined(ENABLE_WEBRTC)
+  // Callback on UI thread when the WebRTC logs have been deleted.
+  void OnClearedWebRtcLogs();
+#endif
+
   // Returns true if we're all done.
   bool AllDone();
 
@@ -400,6 +404,9 @@
   bool waiting_for_clear_pnacl_cache_;
   bool waiting_for_clear_server_bound_certs_;
   bool waiting_for_clear_storage_partition_data_;
+#if defined(ENABLE_WEBRTC)
+  bool waiting_for_clear_webrtc_logs_;
+#endif
 
   // The removal mask for the current removal operation.
   int remove_mask_;
diff --git a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
index 3387324..cbf7087 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_unittest.cc
@@ -187,8 +187,7 @@
   virtual content::IndexedDBContext* GetIndexedDBContext() OVERRIDE {
     return NULL;
   }
-  virtual content::ServiceWorkerContextWrapper*
-  GetServiceWorkerContext() OVERRIDE {
+  virtual content::ServiceWorkerContext* GetServiceWorkerContext() OVERRIDE {
     return NULL;
   }
 
diff --git a/chrome/browser/captive_portal/captive_portal_detector.cc b/chrome/browser/captive_portal/captive_portal_detector.cc
index 26f1a20..846566b 100644
--- a/chrome/browser/captive_portal/captive_portal_detector.cc
+++ b/chrome/browser/captive_portal/captive_portal_detector.cc
@@ -103,6 +103,7 @@
   results->result = RESULT_NO_RESPONSE;
   results->response_code = url_fetcher->GetResponseCode();
   results->retry_after_delta = base::TimeDelta();
+  results->landing_url = url_fetcher->GetURL();
 
   // If there's a network error of some sort when fetching a file via HTTP,
   // there may be a networking problem, rather than a captive portal.
diff --git a/chrome/browser/captive_portal/captive_portal_detector.h b/chrome/browser/captive_portal/captive_portal_detector.h
index 162ae6e..aa72294 100644
--- a/chrome/browser/captive_portal/captive_portal_detector.h
+++ b/chrome/browser/captive_portal/captive_portal_detector.h
@@ -44,6 +44,7 @@
     Result result;
     int response_code;
     base::TimeDelta retry_after_delta;
+    GURL landing_url;
   };
 
   typedef base::Callback<void(const Results& results)> DetectionCallback;
diff --git a/chrome/browser/captive_portal/captive_portal_service.cc b/chrome/browser/captive_portal/captive_portal_service.cc
index dc40d2a..41c4cea 100644
--- a/chrome/browser/captive_portal/captive_portal_service.cc
+++ b/chrome/browser/captive_portal/captive_portal_service.cc
@@ -27,6 +27,22 @@
 
 namespace {
 
+// Make sure this enum is in sync with CaptivePortalDetectionResult enum
+// in histograms.xml. This enum is append-only, don't modify existing values.
+enum CaptivePortalDetectionResult {
+  // There's a confirmed connection to the Internet.
+  DETECTION_RESULT_INTERNET_CONNECTED,
+  // Received a network or HTTP error, or a non-HTTP response.
+  DETECTION_RESULT_NO_RESPONSE,
+  // Encountered a captive portal with a non-HTTPS landing URL.
+  DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL,
+  // Received a network or HTTP error with an HTTPS landing URL.
+  DETECTION_RESULT_NO_RESPONSE_HTTPS_LANDING_URL,
+  // Encountered a captive portal with an HTTPS landing URL.
+  DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL_HTTPS_LANDING_URL,
+  DETECTION_RESULT_COUNT
+};
+
 // Records histograms relating to how often captive portal detection attempts
 // ended with |result| in a row, and for how long |result| was the last result
 // of a detection attempt.  Recorded both on quit and on a new Result.
@@ -69,6 +85,26 @@
   result_duration_histogram->AddTime(result_duration);
 }
 
+int GetHistogramEntryForDetectionResult(
+    const CaptivePortalDetector::Results& results) {
+  bool is_https = results.landing_url.SchemeIs("https");
+  switch (results.result) {
+    case RESULT_INTERNET_CONNECTED:
+      return DETECTION_RESULT_INTERNET_CONNECTED;
+    case RESULT_NO_RESPONSE:
+      return is_https ?
+          DETECTION_RESULT_NO_RESPONSE_HTTPS_LANDING_URL :
+          DETECTION_RESULT_NO_RESPONSE;
+    case RESULT_BEHIND_CAPTIVE_PORTAL:
+      return is_https ?
+          DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL_HTTPS_LANDING_URL :
+          DETECTION_RESULT_BEHIND_CAPTIVE_PORTAL;
+    default:
+      NOTREACHED();
+      return -1;
+  }
+}
+
 bool ShouldDeferToNativeCaptivePortalDetection() {
   // On Windows 8, defer to the native captive portal detection.  OSX Lion and
   // later also have captive portal detection, but experimentally, this code
@@ -210,8 +246,8 @@
 
   // Record histograms.
   UMA_HISTOGRAM_ENUMERATION("CaptivePortal.DetectResult",
-                            result,
-                            RESULT_COUNT);
+                            GetHistogramEntryForDetectionResult(results),
+                            DETECTION_RESULT_COUNT);
 
   // If this isn't the first captive portal result, record stats.
   if (!last_check_time_.is_null()) {
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index c03b8a8..b71cd51 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -173,7 +173,6 @@
 #include "chrome/installer/util/install_util.h"
 #include "chrome/installer/util/shell_util.h"
 #include "net/base/net_util.h"
-#include "printing/printed_document.h"
 #include "ui/base/l10n/l10n_util_win.h"
 #include "ui/gfx/win/dpi.h"
 #endif  // defined(OS_WIN)
@@ -185,10 +184,18 @@
 #include "chrome/browser/mac/keystone_glue.h"
 #endif
 
+#if defined(ENABLE_FULL_PRINTING) && !defined(OFFICIAL_BUILD)
+#include "printing/printed_document.h"
+#endif
+
 #if defined(ENABLE_RLZ)
 #include "chrome/browser/rlz/rlz.h"
 #endif
 
+#if defined(ENABLE_WEBRTC)
+#include "chrome/browser/media/webrtc_log_util.h"
+#endif
+
 #if defined(USE_AURA)
 #include "ui/aura/env.h"
 #endif
@@ -645,6 +652,8 @@
     return;
   }
 
+  metrics->CheckForClonedInstall();
+
   if (IsMetricsReportingEnabled())
     metrics->Start();
 }
@@ -763,13 +772,13 @@
 int ChromeBrowserMainParts::PreCreateThreads() {
   TRACE_EVENT0("startup", "ChromeBrowserMainParts::PreCreateThreads");
   result_code_ = PreCreateThreadsImpl();
-  // These members must be initialized before returning from this function.
-#if !defined(OS_ANDROID)
-  DCHECK(master_prefs_.get());
-  DCHECK(browser_creator_.get());
-#endif
 
-  if (result_code_ == 0) {
+  if (result_code_ == content::RESULT_CODE_NORMAL_EXIT) {
+#if !defined(OS_ANDROID)
+    // These members must be initialized before exiting this function normally.
+    DCHECK(master_prefs_.get());
+    DCHECK(browser_creator_.get());
+#endif
     for (size_t i = 0; i < chrome_extra_parts_.size(); ++i)
       chrome_extra_parts_[i]->PreCreateThreads();
   }
@@ -1085,6 +1094,15 @@
   // Allow ProcessSingleton to process messages.
   process_singleton_->Unlock();
 #endif
+#if defined(ENABLE_WEBRTC)
+  // Set up a task to delete old WebRTC log files for all profiles. Use a delay
+  // to reduce the impact on startup time.
+  BrowserThread::PostDelayedTask(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles),
+      base::TimeDelta::FromMinutes(1));
+#endif
 }
 
 int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1397,7 +1415,7 @@
   if (parsed_command_line().HasSwitch(switches::kEnableWatchdog))
     InstallJankometer(parsed_command_line());
 
-#if defined(OS_WIN) && !defined(GOOGLE_CHROME_BUILD)
+#if defined(ENABLE_FULL_PRINTING) && !defined(OFFICIAL_BUILD)
   if (parsed_command_line().HasSwitch(switches::kDebugPrint)) {
     base::FilePath path =
         parsed_command_line().GetSwitchValuePath(switches::kDebugPrint);
diff --git a/chrome/browser/chrome_browser_main_extra_parts_x11.cc b/chrome/browser/chrome_browser_main_extra_parts_x11.cc
index bcbf506..4afcda8 100644
--- a/chrome/browser/chrome_browser_main_extra_parts_x11.cc
+++ b/chrome/browser/chrome_browser_main_extra_parts_x11.cc
@@ -7,7 +7,6 @@
 #include "base/bind.h"
 #include "base/debug/debugger.h"
 #include "base/message_loop/message_loop.h"
-#include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/common/chrome_result_codes.h"
 #include "content/public/browser/browser_thread.h"
@@ -55,7 +54,6 @@
   if (!g_in_x11_io_error_handler) {
     g_in_x11_io_error_handler = true;
     LOG(ERROR) << "X IO error received (X server probably went away)";
-    browser_shutdown::SetShuttingDownWithoutClosingBrowsers(true);
     chrome::SessionEnding();
   }
 
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index ed45cd2..2f5b3a5 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -35,6 +35,7 @@
 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
 #include "chrome/browser/extensions/browser_permissions_policy_delegate.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/extension_web_ui.h"
 #include "chrome/browser/extensions/extension_webkit_preferences.h"
 #include "chrome/browser/extensions/suggest_permission_util.h"
@@ -90,7 +91,6 @@
 #include "chrome/common/env_vars.h"
 #include "chrome/common/extensions/extension_process_policy.h"
 #include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
 #include "chrome/common/logging_chrome.h"
 #include "chrome/common/pepper_permission_util.h"
 #include "chrome/common/pref_names.h"
@@ -138,6 +138,7 @@
 #include "extensions/common/manifest_handlers/shared_module_info.h"
 #include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/socket_permission.h"
 #include "extensions/common/switches.h"
 #include "grit/generated_resources.h"
 #include "grit/ui_resources.h"
@@ -172,6 +173,7 @@
 #elif defined(OS_LINUX)
 #include "chrome/browser/chrome_browser_main_linux.h"
 #elif defined(OS_ANDROID)
+#include "chrome/browser/android/new_tab_page_url_handler.h"
 #include "chrome/browser/android/webapps/single_tab_mode_tab_helper.h"
 #include "chrome/browser/chrome_browser_main_android.h"
 #include "chrome/browser/media/encrypted_media_message_filter_android.h"
@@ -198,6 +200,8 @@
 #endif
 
 #if !defined(OS_CHROMEOS)
+#include "chrome/browser/signin/chrome_signin_client.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #endif
@@ -785,18 +789,8 @@
     // ExtensionService.
     bool is_isolated = !can_be_default;
     if (can_be_default) {
-      const Extension* extension = NULL;
-      Profile* profile = Profile::FromBrowserContext(browser_context);
-      ExtensionService* extension_service =
-          extensions::ExtensionSystem::Get(profile)->extension_service();
-      if (extension_service) {
-        extension =
-            extension_service->extensions()->GetExtensionOrAppByURL(site);
-        if (extension &&
-            extensions::AppIsolationInfo::HasIsolatedStorage(extension)) {
-          is_isolated = true;
-        }
-      }
+      if (extensions::util::SiteHasIsolatedStorage(site, browser_context))
+        is_isolated = true;
     }
 
     if (is_isolated) {
@@ -1189,8 +1183,9 @@
   }
 
 #if !defined(OS_CHROMEOS)
-  SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile);
-  if (signin_manager && signin_manager->IsSigninProcess(process_host->GetID()))
+  ChromeSigninClient* signin_client =
+      ChromeSigninClientFactory::GetForProfile(profile);
+  if (signin_client && signin_client->IsSigninProcess(process_host->GetID()))
     return SigninManager::IsWebBasedSigninFlowURL(site_url);
 #endif
 
@@ -1295,10 +1290,10 @@
   // for signin URLs. The signin process will be cleared from SigninManager
   // when the renderer is destroyed.
   if (SigninManager::IsWebBasedSigninFlowURL(site_instance->GetSiteURL())) {
-    SigninManager* signin_manager =
-        SigninManagerFactory::GetForProfile(profile);
-    if (signin_manager)
-      signin_manager->SetSigninProcess(site_instance->GetProcess()->GetID());
+    ChromeSigninClient* signin_client =
+        ChromeSigninClientFactory::GetForProfile(profile);
+    if (signin_client)
+      signin_client->SetSigninProcess(site_instance->GetProcess()->GetID());
     BrowserThread::PostTask(
         BrowserThread::IO,
         FROM_HERE,
@@ -1550,13 +1545,24 @@
         command_line->AppendSwitch(switches::kInstantProcess);
 
 #if !defined(OS_CHROMEOS)
-      SigninManager* signin_manager =
-          SigninManagerFactory::GetForProfile(profile);
-      if (signin_manager && signin_manager->IsSigninProcess(process->GetID()))
+      ChromeSigninClient* signin_client =
+          ChromeSigninClientFactory::GetForProfile(profile);
+      if (signin_client && signin_client->IsSigninProcess(process->GetID()))
         command_line->AppendSwitch(switches::kSigninProcess);
 #endif
     }
 
+    {
+      // Enable auto-reload if this session is in the field trial or the user
+      // explicitly enabled it.
+      std::string group =
+          base::FieldTrialList::FindFullName("AutoReloadExperiment");
+      if (group == "Enabled" ||
+          browser_command_line.HasSwitch(switches::kEnableOfflineAutoReload)) {
+        command_line->AppendSwitch(switches::kEnableOfflineAutoReload);
+      }
+    }
+
     // Please keep this in alphabetical order.
     static const char* const kSwitchNames[] = {
       autofill::switches::kDisableIgnoreAutocompleteOff,
@@ -1567,7 +1573,6 @@
       autofill::switches::kLocalHeuristicsOnlyForPasswordGeneration,
       extensions::switches::kAllowHTTPBackgroundPage,
       extensions::switches::kAllowLegacyExtensionManifests,
-      extensions::switches::kAllowScriptingGallery,
       extensions::switches::kEnableExperimentalExtensionApis,
       extensions::switches::kExtensionsOnChromeURLs,
       // TODO(victorhsieh): remove the following flag once we move PPAPI FileIO
@@ -1587,7 +1592,6 @@
       switches::kEnableNaClDebug,
       switches::kEnableNaClNonSfiMode,
       switches::kEnableNetBenchmarking,
-      switches::kEnableOfflineAutoReload,
       switches::kEnableStreamlinedHostedApps,
       switches::kEnableWatchdog,
       switches::kMemoryProfiling,
@@ -2404,9 +2408,15 @@
   handler->AddHandlerPair(&WillHandleBrowserAboutURL,
                           BrowserURLHandler::null_handler());
 
+#if defined(OS_ANDROID)
+  // Handler to rewrite chrome://newtab on Android.
+  handler->AddHandlerPair(&chrome::android::HandleAndroidNewTabURL,
+                          BrowserURLHandler::null_handler());
+#else
   // Handler to rewrite chrome://newtab for InstantExtended.
   handler->AddHandlerPair(&chrome::HandleNewTabURLRewrite,
                           &chrome::HandleNewTabURLReverseRewrite);
+#endif
 
   // chrome: & friends.
   handler->AddHandlerPair(&HandleWebUI, &HandleWebUIReverse);
@@ -2557,6 +2567,10 @@
 
 void ChromeContentBrowserClient::GetURLRequestAutoMountHandlers(
     std::vector<fileapi::URLRequestAutoMountHandler>* handlers) {
+#if !defined(OS_ANDROID)
+  handlers->push_back(
+      base::Bind(MediaFileSystemBackend::AttemptAutoMountForURLRequest));
+#endif  // OS_ANDROID
 }
 
 void ChromeContentBrowserClient::GetAdditionalFileSystemBackends(
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h
index 9ba710a..3c8209b 100644
--- a/chrome/browser/chrome_notification_types.h
+++ b/chrome/browser/chrome_notification_types.h
@@ -425,6 +425,12 @@
   // string with details about why the load failed.
   NOTIFICATION_EXTENSION_LOAD_ERROR,
 
+  // Sent when an unpacked extension fails to load. The details are a std::pair,
+  // the first object is a boolean signifying the user's retry response value,
+  // and the second object is a const base::FilePath& of the extension that
+  // failed to load. Source is a Profile.
+  NOTIFICATION_EXTENSION_LOAD_RETRY,
+
   // Sent when an extension is enabled. Under most circumstances, listeners
   // will want to use NOTIFICATION_EXTENSION_LOADED. This notification is only
   // fired when the "Enable" button is hit in the extensions tab.  The details
@@ -624,6 +630,10 @@
   // Sent when the current install is outdated. No details are expected.
   NOTIFICATION_OUTDATED_INSTALL,
 
+  // Sent when the current install is outdated and auto-update (AU) is disabled.
+  // No details are expected.
+  NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+
   // Software incompatibility notifications ----------------------------------
 
   // Sent when Chrome has finished compiling the list of loaded modules (and
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.cc b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
index 8ea3307..ad45e90 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.cc
@@ -308,7 +308,9 @@
       spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE),
       weak_ptr_factory_(this),
       should_speak_chrome_vox_announcements_on_user_screen_(true),
-      system_sounds_enabled_(false) {
+      system_sounds_enabled_(false),
+      braille_display_connected_(false),
+      scoped_braille_observer_(this) {
   notification_registrar_.Add(this,
                               chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
                               content::NotificationService::AllSources());
@@ -322,7 +324,7 @@
                               chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
                               content::NotificationService::AllSources());
 
-  GetBrailleController()->AddObserver(this);
+  input_method::InputMethodManager::Get()->AddObserver(this);
 
   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
   media::SoundsManager* manager = media::SoundsManager::Get();
@@ -343,6 +345,7 @@
       false,
       ash::A11Y_NOTIFICATION_NONE);
   NotifyAccessibilityStatusChanged(details);
+  input_method::InputMethodManager::Get()->RemoveObserver(this);
 }
 
 bool AccessibilityManager::ShouldShowAccessibilityMenu() {
@@ -739,11 +742,19 @@
 #endif
 }
 
+bool AccessibilityManager::IsBrailleDisplayConnected() const {
+  return braille_display_connected_;
+}
+
 void AccessibilityManager::CheckBrailleState() {
+  BrailleController* braille_controller = GetBrailleController();
+  if (!scoped_braille_observer_.IsObserving(braille_controller))
+    scoped_braille_observer_.Add(braille_controller);
   BrowserThread::PostTaskAndReplyWithResult(
-      BrowserThread::IO, FROM_HERE, base::Bind(
-          &BrailleController::GetDisplayState,
-          base::Unretained(GetBrailleController())),
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&BrailleController::GetDisplayState,
+                 base::Unretained(braille_controller)),
       base::Bind(&AccessibilityManager::ReceiveBrailleDisplayState,
                  weak_ptr_factory_.GetWeakPtr()));
 }
@@ -753,6 +764,17 @@
   OnDisplayStateChanged(*state);
 }
 
+// Overridden from InputMethodManager::Observer.
+void AccessibilityManager::InputMethodChanged(
+    input_method::InputMethodManager* manager,
+    bool show_message) {
+#if defined(USE_ASH)
+  // Sticky keys is implemented only in ash.
+  ash::Shell::GetInstance()->sticky_keys_controller()->SetModifiersEnabled(
+      manager->IsISOLevel5ShiftUsedByCurrentInputMethod(),
+      manager->IsAltGrUsedByCurrentInputMethod());
+#endif
+}
 
 void AccessibilityManager::SetProfile(Profile* profile) {
   pref_change_registrar_.reset();
@@ -811,10 +833,12 @@
   autoclick_delay_pref_handler_.HandleProfileChanged(profile_, profile);
   virtual_keyboard_pref_handler_.HandleProfileChanged(profile_, profile);
 
-  if (!profile_ && profile)
+  bool had_profile = (profile_ != NULL);
+  profile_ = profile;
+
+  if (!had_profile && profile)
     CheckBrailleState();
 
-  profile_ = profile;
   UpdateLargeCursorFromPref();
   UpdateStickyKeysFromPref();
   UpdateSpokenFeedbackFromPref();
@@ -962,8 +986,15 @@
 
 void AccessibilityManager::OnDisplayStateChanged(
     const DisplayState& display_state) {
-  if (display_state.available)
+  braille_display_connected_ = display_state.available;
+  if (braille_display_connected_)
     EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_SHOW);
+
+  AccessibilityStatusEventDetails details(
+      ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED,
+      braille_display_connected_,
+      ash::A11Y_NOTIFICATION_SHOW);
+  NotifyAccessibilityStatusChanged(details);
 }
 
 void AccessibilityManager::PostLoadChromeVox(Profile* profile) {
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager.h b/chrome/browser/chromeos/accessibility/accessibility_manager.h
index 5c7b0e7..21584ee 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager.h
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager.h
@@ -12,9 +12,11 @@
 #include "base/callback_list.h"
 #include "base/memory/weak_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
+#include "base/scoped_observer.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_util.h"
 #include "chrome/browser/extensions/api/braille_display_private/braille_controller.h"
+#include "chromeos/ime/input_method_manager.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/browser/event_router.h"
@@ -33,7 +35,8 @@
   ACCESSIBILITY_TOGGLE_LARGE_CURSOR,
   ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER,
   ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK,
-  ACCESSIBILITY_TOGGLE_VIRTUAL_KEYBOARD
+  ACCESSIBILITY_TOGGLE_VIRTUAL_KEYBOARD,
+  ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED
 };
 
 struct AccessibilityStatusEventDetails {
@@ -66,9 +69,11 @@
 // AccessibilityManager changes the statuses of accessibility features
 // watching profile notifications and pref-changes.
 // TODO(yoshiki): merge MagnificationManager with AccessibilityManager.
-class AccessibilityManager : public content::NotificationObserver,
-    extensions::api::braille_display_private::BrailleObserver,
-    public ash::SessionStateObserver {
+class AccessibilityManager
+    : public content::NotificationObserver,
+      public extensions::api::braille_display_private::BrailleObserver,
+      public input_method::InputMethodManager::Observer,
+      public ash::SessionStateObserver {
  public:
   // Creates an instance of AccessibilityManager, this should be called once,
   // because only one instance should exist at the same time.
@@ -93,6 +98,8 @@
 
    private:
     const char* pref_path_;
+
+    DISALLOW_COPY_AND_ASSIGN(PrefHandler);
   };
 
   // Returns true when the accessibility menu should be shown.
@@ -149,6 +156,10 @@
   // Returns true if the virtual keyboard is enabled, otherwise false.
   bool IsVirtualKeyboardEnabled();
 
+  // Returns true if a braille display is connected to the system, otherwise
+  // false.
+  bool IsBrailleDisplayConnected() const;
+
   // SessionStateObserver overrides:
   virtual void ActiveUserChanged(const std::string& user_id) OVERRIDE;
 
@@ -207,7 +218,7 @@
 
   void UpdateChromeOSAccessibilityHistograms();
 
-  // content::NotificationObserver implementation:
+  // content::NotificationObserver
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
@@ -218,6 +229,11 @@
       const extensions::api::braille_display_private::DisplayState&
           display_state) OVERRIDE;
 
+  // InputMethodManager::Observer
+  virtual void InputMethodChanged(input_method::InputMethodManager* manager,
+                                  bool show_message) OVERRIDE;
+
+
   // Profile which has the current a11y context.
   Profile* profile_;
 
@@ -256,6 +272,10 @@
 
   AccessibilityStatusCallbackList callback_list_;
 
+  bool braille_display_connected_;
+  ScopedObserver<extensions::api::braille_display_private::BrailleController,
+                 AccessibilityManager> scoped_braille_observer_;
+
   DISALLOW_COPY_AND_ASSIGN(AccessibilityManager);
 };
 
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
index 37ca71a..d397f23 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/user_manager_impl.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
-#include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
+#include "chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/pref_names.h"
@@ -28,7 +28,7 @@
 
 using extensions::api::braille_display_private::BrailleObserver;
 using extensions::api::braille_display_private::DisplayState;
-using extensions::api::braille_display_private::StubBrailleController;
+using extensions::api::braille_display_private::MockBrailleController;
 
 namespace chromeos {
 
@@ -82,39 +82,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockAccessibilityObserver);
 };
 
-class MockBrailleController : public StubBrailleController {
- public:
-
-  MockBrailleController() : available_(false), observer_(NULL) {}
-
-  virtual scoped_ptr<DisplayState> GetDisplayState() OVERRIDE {
-    scoped_ptr<DisplayState> state(new DisplayState());
-    state->available = available_;
-    return state.Pass();
-  }
-
-  virtual void AddObserver(BrailleObserver* observer) OVERRIDE {
-    ASSERT_EQ(NULL, observer_);
-    observer_ = observer;
-  }
-
-  virtual void RemoveObserver(BrailleObserver* observer) OVERRIDE {
-    ASSERT_EQ(observer_, observer);
-  }
-
-  void SetAvailable(bool available) {
-    available_ = available;
-  }
-
-  BrailleObserver* GetObserver() {
-    return observer_;
-  }
-
- private:
-  bool available_;
-  BrailleObserver* observer_;
-};
-
 void SetLargeCursorEnabled(bool enabled) {
   return AccessibilityManager::Get()->EnableLargeCursor(enabled);
 }
diff --git a/chrome/browser/chromeos/app_mode/app_launch_utils.cc b/chrome/browser/chromeos/app_mode/app_launch_utils.cc
index edae6af..4490e2b 100644
--- a/chrome/browser/chromeos/app_mode/app_launch_utils.cc
+++ b/chrome/browser/chromeos/app_mode/app_launch_utils.cc
@@ -55,6 +55,7 @@
     chrome::AttemptUserExit();
     Cleanup();
   }
+  virtual bool IsShowingNetworkConfigScreen() OVERRIDE { return false; }
 
   scoped_ptr<StartupAppLauncher> startup_app_launcher_;
 
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
index fa6496e..9fab7ce 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.cc
@@ -289,8 +289,11 @@
 void KioskAppManager::GetApps(Apps* apps) const {
   apps->clear();
   apps->reserve(apps_.size());
-  for (size_t i = 0; i < apps_.size(); ++i)
-    apps->push_back(App(*apps_[i]));
+  for (size_t i = 0; i < apps_.size(); ++i) {
+    const KioskAppData& app_data = *apps_[i];
+    if (app_data.status() != KioskAppData::STATUS_ERROR)
+      apps->push_back(App(app_data));
+  }
 }
 
 bool KioskAppManager::GetApp(const std::string& app_id, App* app) const {
@@ -452,7 +455,6 @@
   FOR_EACH_OBSERVER(KioskAppManagerObserver,
                     observers_,
                     OnKioskAppDataLoadFailure(app_id));
-  RemoveApp(app_id);
 }
 
 KioskAppManager::AutoLoginState KioskAppManager::GetAutoLoginState() const {
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
index 5857da7..7c12315 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_manager.h
@@ -119,7 +119,7 @@
   void AddApp(const std::string& app_id);
   void RemoveApp(const std::string& app_id);
 
-  // Gets info of all apps.
+  // Gets info of all apps that have no meta data load error.
   void GetApps(Apps* apps) const;
 
   // Gets app data for the given app id. Returns true if |app_id| is known and
diff --git a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
index cd386b8..a17f493 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.cc
@@ -117,10 +117,10 @@
 // KioskProfileLoader
 
 KioskProfileLoader::KioskProfileLoader(const std::string& app_user_id,
-                                       bool force_ephemeral,
+                                       bool use_guest_mount,
                                        Delegate* delegate)
     : user_id_(app_user_id),
-      force_ephemeral_(force_ephemeral),
+      use_guest_mount_(use_guest_mount),
       delegate_(delegate) {}
 
 KioskProfileLoader::~KioskProfileLoader() {}
@@ -134,7 +134,7 @@
 
 void KioskProfileLoader::LoginAsKioskAccount() {
   login_performer_.reset(new LoginPerformer(this));
-  login_performer_->LoginAsKioskAccount(user_id_, force_ephemeral_);
+  login_performer_->LoginAsKioskAccount(user_id_, use_guest_mount_);
 }
 
 void KioskProfileLoader::ReportLaunchResult(KioskAppLaunchError::Error error) {
diff --git a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h
index 06b9029..2101262 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h
+++ b/chrome/browser/chromeos/app_mode/kiosk_profile_loader.h
@@ -18,8 +18,6 @@
 
 namespace chromeos {
 
-class KioskAppManager;
-
 // KioskProfileLoader loads a special profile for a given app. It first
 // attempts to login for the app's generated user id. If the login is
 // successful, it prepares app profile then calls the delegate.
@@ -36,7 +34,7 @@
   };
 
   KioskProfileLoader(const std::string& app_user_id,
-                     bool force_ephemeral,
+                     bool use_guest_mount,
                      Delegate* delegate);
 
   virtual ~KioskProfileLoader();
@@ -62,7 +60,7 @@
   virtual void OnProfilePrepared(Profile* profile) OVERRIDE;
 
   std::string user_id_;
-  bool force_ephemeral_;
+  bool use_guest_mount_;
   Delegate* delegate_;
   scoped_ptr<CryptohomedChecker> cryptohomed_checker_;
   scoped_ptr<LoginPerformer> login_performer_;
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
index 8318b37..a7b8828 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.cc
@@ -27,7 +27,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/manifest_url_handler.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "extensions/browser/extension_system.h"
@@ -148,6 +148,18 @@
   InitializeTokenService();
 }
 
+void StartupAppLauncher::RestartLauncher() {
+  // If the installer is still running in the background, we don't need to
+  // restart the launch process. We will just wait until it completes and
+  // lunches the kiosk app.
+  if (installer_ != NULL) {
+    LOG(WARNING) << "Installer still running";
+    return;
+  }
+
+  MaybeInitializeNetwork();
+}
+
 void StartupAppLauncher::MaybeInitializeNetwork() {
   network_ready_handled_ = false;
 
@@ -295,6 +307,11 @@
 void StartupAppLauncher::InstallCallback(bool success,
                                          const std::string& error) {
   installer_ = NULL;
+  if (delegate_->IsShowingNetworkConfigScreen()) {
+    LOG(WARNING) << "Showing network config screen";
+    return;
+  }
+
   if (success) {
     // Finish initialization after the callback returns.
     // So that the app finishes its installation.
diff --git a/chrome/browser/chromeos/app_mode/startup_app_launcher.h b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
index 937afed..e13225a 100644
--- a/chrome/browser/chromeos/app_mode/startup_app_launcher.h
+++ b/chrome/browser/chromeos/app_mode/startup_app_launcher.h
@@ -50,6 +50,7 @@
     virtual void OnReadyToLaunch() = 0;
     virtual void OnLaunchSucceeded() = 0;
     virtual void OnLaunchFailed(KioskAppLaunchError::Error error) = 0;
+    virtual bool IsShowingNetworkConfigScreen() = 0;
 
    protected:
     virtual ~Delegate() {}
@@ -71,6 +72,9 @@
   // Launches the app after the initialization is successful.
   void LaunchApp();
 
+  // Restarts launcher;
+  void RestartLauncher();
+
  private:
   // OAuth parameters from /home/chronos/kiosk_auth file.
   struct KioskOAuthParams {
diff --git a/chrome/browser/chromeos/attestation/platform_verification_dialog.cc b/chrome/browser/chromeos/attestation/platform_verification_dialog.cc
index 19ffa25..13da9d4 100644
--- a/chrome/browser/chromeos/attestation/platform_verification_dialog.cc
+++ b/chrome/browser/chromeos/attestation/platform_verification_dialog.cc
@@ -95,6 +95,13 @@
   return true;
 }
 
+bool PlatformVerificationDialog::Close() {
+  // This method is called when the tab is closed and in that case the decision
+  // hasn't been made yet.
+  callback_.Run(PlatformVerificationFlow::CONSENT_RESPONSE_NONE);
+  return true;
+}
+
 base::string16 PlatformVerificationDialog::GetDialogButtonLabel(
     ui::DialogButton button) const {
   switch (button) {
diff --git a/chrome/browser/chromeos/attestation/platform_verification_dialog.h b/chrome/browser/chromeos/attestation/platform_verification_dialog.h
index cff19ae..d283c73 100644
--- a/chrome/browser/chromeos/attestation/platform_verification_dialog.h
+++ b/chrome/browser/chromeos/attestation/platform_verification_dialog.h
@@ -42,6 +42,7 @@
   // Overridden from views::DialogDelegate:
   virtual bool Cancel() OVERRIDE;
   virtual bool Accept() OVERRIDE;
+  virtual bool Close() OVERRIDE;
   virtual base::string16 GetDialogButtonLabel(
       ui::DialogButton button) const OVERRIDE;
 
diff --git a/chrome/browser/chromeos/camera_presence_notifier.cc b/chrome/browser/chromeos/camera_presence_notifier.cc
new file mode 100644
index 0000000..57d3b24
--- /dev/null
+++ b/chrome/browser/chromeos/camera_presence_notifier.cc
@@ -0,0 +1,73 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/camera_presence_notifier.h"
+
+#include "base/bind.h"
+#include "base/memory/singleton.h"
+#include "base/time/time.h"
+#include "chrome/browser/chromeos/camera_detector.h"
+
+namespace chromeos {
+
+namespace {
+
+// Interval between checks for camera presence.
+const int kCameraCheckIntervalSeconds = 3;
+
+}  // namespace
+
+CameraPresenceNotifier::CameraPresenceNotifier() :
+    weak_factory_(this),
+    camera_present_on_last_check_(false) {}
+
+CameraPresenceNotifier::~CameraPresenceNotifier() {}
+
+// static
+CameraPresenceNotifier* CameraPresenceNotifier::GetInstance() {
+  return Singleton<CameraPresenceNotifier>::get();
+}
+
+void CameraPresenceNotifier::AddObserver(
+    CameraPresenceNotifier::Observer* observer) {
+  bool had_no_observers = !observers_.might_have_observers();
+  observers_.AddObserver(observer);
+  observer->OnCameraPresenceCheckDone(camera_present_on_last_check_);
+  if (had_no_observers) {
+    CheckCameraPresence();
+    camera_check_timer_.Start(
+        FROM_HERE,
+        base::TimeDelta::FromSeconds(kCameraCheckIntervalSeconds),
+        this,
+        &CameraPresenceNotifier::CheckCameraPresence);
+  }
+}
+
+void CameraPresenceNotifier::RemoveObserver(
+    CameraPresenceNotifier::Observer* observer) {
+  observers_.RemoveObserver(observer);
+  if (!observers_.might_have_observers()) {
+    camera_check_timer_.Stop();
+    camera_present_on_last_check_ = false;
+  }
+}
+
+void CameraPresenceNotifier::CheckCameraPresence() {
+  CameraDetector::StartPresenceCheck(
+      base::Bind(&CameraPresenceNotifier::OnCameraPresenceCheckDone,
+                 weak_factory_.GetWeakPtr()));
+}
+
+void CameraPresenceNotifier::OnCameraPresenceCheckDone() {
+  bool is_camera_present =
+      CameraDetector::camera_presence() == CameraDetector::kCameraPresent;
+  if (is_camera_present != camera_present_on_last_check_) {
+    camera_present_on_last_check_ = is_camera_present;
+    FOR_EACH_OBSERVER(Observer,
+                      observers_,
+                      OnCameraPresenceCheckDone(camera_present_on_last_check_));
+  }
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/camera_presence_notifier.h b/chrome/browser/chromeos/camera_presence_notifier.h
new file mode 100644
index 0000000..7897a45
--- /dev/null
+++ b/chrome/browser/chromeos/camera_presence_notifier.h
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_CAMERA_PRESENCE_NOTIFIER_H_
+#define CHROME_BROWSER_CHROMEOS_CAMERA_PRESENCE_NOTIFIER_H_
+
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "base/timer/timer.h"
+
+namespace chromeos {
+
+// Camera presence status dispatcher.
+class CameraPresenceNotifier {
+ public:
+  class Observer {
+   public:
+    virtual void OnCameraPresenceCheckDone(bool is_camera_present) = 0;
+   protected:
+    virtual ~Observer() {}
+  };
+
+  static CameraPresenceNotifier* GetInstance();
+
+  void AddObserver(CameraPresenceNotifier::Observer* observer);
+  void RemoveObserver(CameraPresenceNotifier::Observer* observer);
+
+ private:
+  friend struct DefaultSingletonTraits<CameraPresenceNotifier>;
+  CameraPresenceNotifier();
+  ~CameraPresenceNotifier();
+
+  void CheckCameraPresence();
+
+  // Sends out a camera presence status notification.
+  void OnCameraPresenceCheckDone();
+
+  base::WeakPtrFactory<CameraPresenceNotifier> weak_factory_;
+
+  bool camera_present_on_last_check_;
+
+  // Timer for camera check cycle.
+  base::RepeatingTimer<CameraPresenceNotifier> camera_check_timer_;
+
+  ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(CameraPresenceNotifier);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_CAMERA_PRESENCE_NOTIFIER_H_
+
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index 201758d..4dfc642 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -15,7 +15,6 @@
 #include "base/file_util.h"
 #include "base/lazy_instance.h"
 #include "base/linux_util.h"
-#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
@@ -124,20 +123,6 @@
   base::SetLinuxDistro(std::string("CrOS ") + version);
 }
 
-class MessageLoopObserver : public base::MessageLoopForUI::Observer {
-  virtual base::EventStatus WillProcessEvent(
-      const base::NativeEvent& event) OVERRIDE {
-    return base::EVENT_CONTINUE;
-  }
-
-  virtual void DidProcessEvent(
-      const base::NativeEvent& event) OVERRIDE {
-  }
-};
-
-static base::LazyInstance<MessageLoopObserver> g_message_loop_observer =
-    LAZY_INSTANCE_INITIALIZER;
-
 // Login -----------------------------------------------------------------------
 
 // Class is used to login using passed username and password.
@@ -411,9 +396,6 @@
 }
 
 void ChromeBrowserMainPartsChromeos::PostMainMessageLoopStart() {
-  base::MessageLoopForUI* message_loop = base::MessageLoopForUI::current();
-  message_loop->AddObserver(g_message_loop_observer.Pointer());
-
   dbus_services_.reset(new internal::DBusServices(parameters()));
 
   ChromeBrowserMainPartsLinux::PostMainMessageLoopStart();
diff --git a/chrome/browser/chromeos/customization_document.cc b/chrome/browser/chromeos/customization_document.cc
index b5cce96..260531a 100644
--- a/chrome/browser/chromeos/customization_document.cc
+++ b/chrome/browser/chromeos/customization_document.cc
@@ -11,6 +11,7 @@
 #include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
+#include "base/metrics/histogram.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_split.h"
@@ -20,9 +21,12 @@
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "chrome/browser/chromeos/net/delay_network_call.h"
 #include "chrome/browser/extensions/external_loader.h"
 #include "chrome/browser/extensions/external_provider_impl.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
+#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
@@ -31,14 +35,15 @@
 #include "content/public/browser/browser_thread.h"
 #include "net/base/load_flags.h"
 #include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
 #include "net/url_request/url_fetcher.h"
 
 using content::BrowserThread;
 
-// Manifest attributes names.
-
+namespace chromeos {
 namespace {
 
+  // Manifest attributes names.
 const char kVersionAttr[] = "version";
 const char kDefaultAttr[] = "default";
 const char kInitialLocaleAttr[] = "initial_locale";
@@ -50,6 +55,8 @@
 const char kEulaPageAttr[] = "eula_page";
 const char kDefaultWallpaperAttr[] = "default_wallpaper";
 const char kDefaultAppsAttr[] = "default_apps";
+const char kLocalizedContent[] = "localized_content";
+const char kDefaultAppsFolderName[] = "default_apps_folder_name";
 
 const char kAcceptedManifestVersion[] = "1.0";
 
@@ -70,9 +77,56 @@
 // Name of profile option that tracks cached version of service customization.
 const char kServicesCustomizationKey[] = "customization.manifest_cache";
 
-}  // anonymous namespace
+// Empty customization document that doesn't customize anything.
+const char kEmptyServicesCustomizationManifest[] = "{ \"version\": \"1.0\" }";
 
-namespace chromeos {
+// Global overrider for ServicesCustomizationDocument for tests.
+ServicesCustomizationDocument* g_test_services_customization_document = NULL;
+
+// Services customization document load results reported via the
+// "ServicesCustomization.LoadResult" histogram.
+// It is append-only enum due to use in a histogram!
+enum HistogramServicesCustomizationLoadResult {
+  HISTOGRAM_LOAD_RESULT_SUCCESS = 0,
+  HISTOGRAM_LOAD_RESULT_FILE_NOT_FOUND = 1,
+  HISTOGRAM_LOAD_RESULT_PARSING_ERROR = 2,
+  HISTOGRAM_LOAD_RESULT_RETRIES_FAIL = 3,
+  HISTOGRAM_LOAD_RESULT_MAX_VALUE = 4
+};
+
+void LogManifestLoadResult(HistogramServicesCustomizationLoadResult result) {
+  UMA_HISTOGRAM_ENUMERATION("ServicesCustomization.LoadResult",
+                            result,
+                            HISTOGRAM_LOAD_RESULT_MAX_VALUE);
+}
+
+std::string GetLocaleSpecificStringImpl(
+    const base::DictionaryValue* root,
+    const std::string& locale,
+    const std::string& dictionary_name,
+    const std::string& entry_name) {
+  const base::DictionaryValue* dictionary_content = NULL;
+  if (!root || !root->GetDictionary(dictionary_name, &dictionary_content))
+    return std::string();
+
+  const base::DictionaryValue* locale_dictionary = NULL;
+  if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
+    std::string result;
+    if (locale_dictionary->GetString(entry_name, &result))
+      return result;
+  }
+
+  const base::DictionaryValue* default_dictionary = NULL;
+  if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
+    std::string result;
+    if (default_dictionary->GetString(entry_name, &result))
+      return result;
+  }
+
+  return std::string();
+}
+
+}  // anonymous namespace
 
 // Template URL where to fetch OEM services customization manifest from.
 const char ServicesCustomizationDocument::kManifestUrl[] =
@@ -168,26 +222,8 @@
     const std::string& locale,
     const std::string& dictionary_name,
     const std::string& entry_name) const {
-  base::DictionaryValue* dictionary_content = NULL;
-  if (!root_.get() ||
-      !root_->GetDictionary(dictionary_name, &dictionary_content))
-    return std::string();
-
-  base::DictionaryValue* locale_dictionary = NULL;
-  if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
-    std::string result;
-    if (locale_dictionary->GetString(entry_name, &result))
-      return result;
-  }
-
-  base::DictionaryValue* default_dictionary = NULL;
-  if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
-    std::string result;
-    if (default_dictionary->GetString(entry_name, &result))
-      return result;
-  }
-
-  return std::string();
+  return GetLocaleSpecificStringImpl(
+      root_.get(), locale, dictionary_name, entry_name);
 }
 
 // StartupCustomizationDocument implementation. --------------------------------
@@ -294,12 +330,18 @@
 ServicesCustomizationDocument::ServicesCustomizationDocument()
     : CustomizationDocument(kAcceptedManifestVersion),
       num_retries_(0),
-      fetch_started_(false) {
+      fetch_started_(false),
+      network_delay_(base::TimeDelta::FromMilliseconds(
+          kDefaultNetworkRetryDelayMS)),
+      weak_ptr_factory_(this) {
 }
 
 ServicesCustomizationDocument::ServicesCustomizationDocument(
     const std::string& manifest)
-    : CustomizationDocument(kAcceptedManifestVersion) {
+    : CustomizationDocument(kAcceptedManifestVersion),
+      network_delay_(base::TimeDelta::FromMilliseconds(
+          kDefaultNetworkRetryDelayMS)),
+      weak_ptr_factory_(this) {
   LoadManifestFromString(manifest);
 }
 
@@ -307,6 +349,9 @@
 
 // static
 ServicesCustomizationDocument* ServicesCustomizationDocument::GetInstance() {
+  if (g_test_services_customization_document)
+    return g_test_services_customization_document;
+
   return Singleton<ServicesCustomizationDocument,
       DefaultSingletonTraits<ServicesCustomizationDocument> >::get();
 }
@@ -338,34 +383,37 @@
 }
 
 void ServicesCustomizationDocument::StartFetching() {
-  if (!fetch_started_) {
-    if (!url_.is_valid()) {
-      std::string customization_id;
-      chromeos::system::StatisticsProvider* provider =
-          chromeos::system::StatisticsProvider::GetInstance();
-      if (provider->GetMachineStatistic(system::kCustomizationIdKey,
-                                        &customization_id) &&
-          !customization_id.empty()) {
-        url_ = GURL(base::StringPrintf(
-            kManifestUrl, StringToLowerASCII(customization_id).c_str()));
-      }
-    }
+  if (IsReady() || fetch_started_)
+    return;
 
-    if (url_.is_valid()) {
-      fetch_started_ = true;
-      if (url_.SchemeIsFile()) {
-        BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
-            base::Bind(&ServicesCustomizationDocument::ReadFileInBackground,
-                      base::Unretained(this),  // this class is a singleton.
-                      base::FilePath(url_.path())));
-      } else {
-        StartFileFetch();
-      }
+  if (!url_.is_valid()) {
+    std::string customization_id;
+    chromeos::system::StatisticsProvider* provider =
+        chromeos::system::StatisticsProvider::GetInstance();
+    if (provider->GetMachineStatistic(system::kCustomizationIdKey,
+                                      &customization_id) &&
+        !customization_id.empty()) {
+      url_ = GURL(base::StringPrintf(
+          kManifestUrl, StringToLowerASCII(customization_id).c_str()));
+    }
+  }
+
+  if (url_.is_valid()) {
+    fetch_started_ = true;
+    if (url_.SchemeIsFile()) {
+      BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+          base::Bind(&ServicesCustomizationDocument::ReadFileInBackground,
+                     weak_ptr_factory_.GetWeakPtr(),
+                     base::FilePath(url_.path())));
+    } else {
+      StartFileFetch();
     }
   }
 }
 
+// static
 void ServicesCustomizationDocument::ReadFileInBackground(
+    base::WeakPtr<ServicesCustomizationDocument> self,
     const base::FilePath& file) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
@@ -378,7 +426,7 @@
 
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       base::Bind(&ServicesCustomizationDocument::OnManifesteRead,
-                 base::Unretained(this),  // this class is a singleton.
+                 self,
                  manifest));
 }
 
@@ -391,6 +439,12 @@
 }
 
 void ServicesCustomizationDocument::StartFileFetch() {
+  DelayNetworkCall(base::Bind(&ServicesCustomizationDocument::DoStartFileFetch,
+                              weak_ptr_factory_.GetWeakPtr()),
+      network_delay_);
+}
+
+void ServicesCustomizationDocument::DoStartFileFetch() {
   url_fetcher_.reset(net::URLFetcher::Create(
       url_, net::URLFetcher::GET, this));
   url_fetcher_->SetRequestContext(g_browser_process->system_request_context());
@@ -405,9 +459,12 @@
 bool ServicesCustomizationDocument::LoadManifestFromString(
     const std::string& manifest) {
   if (CustomizationDocument::LoadManifestFromString(manifest)) {
+    LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_SUCCESS);
     OnManifestLoaded();
     return true;
   }
+
+  LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_PARSING_ERROR);
   return false;
 }
 
@@ -423,6 +480,7 @@
       UpdateCachedManifest((*it)->profile());
       (*it)->SetCurrentApps(
           scoped_ptr<base::DictionaryValue>(prefs->DeepCopy()));
+      SetOemFolderName((*it)->profile(), *root_);
     }
   }
 }
@@ -432,33 +490,38 @@
   std::string mime_type;
   std::string data;
   if (source->GetStatus().is_success() &&
-      source->GetResponseCode() == 200 &&
+      source->GetResponseCode() == net::HTTP_OK &&
       source->GetResponseHeaders()->GetMimeType(&mime_type) &&
       mime_type == "application/json" &&
       source->GetResponseAsString(&data)) {
     LoadManifestFromString(data);
-    fetch_started_ = false;
+  } else if (source->GetResponseCode() == net::HTTP_NOT_FOUND) {
+    LOG(ERROR) << "Customization manifest is missing on server: "
+               << source->GetURL().spec();
+    OnCustomizationNotFound();
   } else {
-    const NetworkState* default_network =
-        NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
-    // TODO(dpolukhin): wait for network connected state, crbug.com/343589.
-    if (default_network && default_network->IsConnectedState() &&
-        num_retries_ < kMaxFetchRetries) {
+    if (num_retries_ < kMaxFetchRetries) {
       num_retries_++;
-      retry_timer_.Start(FROM_HERE,
-                         base::TimeDelta::FromSeconds(kRetriesDelayInSec),
-                         this, &ServicesCustomizationDocument::StartFileFetch);
+      content::BrowserThread::PostDelayedTask(
+          content::BrowserThread::UI,
+          FROM_HERE,
+          base::Bind(&ServicesCustomizationDocument::StartFileFetch,
+                     weak_ptr_factory_.GetWeakPtr()),
+          base::TimeDelta::FromSeconds(kRetriesDelayInSec));
       return;
     }
+    // This doesn't stop fetching manifest on next restart.
     LOG(ERROR) << "URL fetch for services customization failed:"
                << " response code = " << source->GetResponseCode()
                << " URL = " << source->GetURL().spec();
-    fetch_started_ = false;
+
+    LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_RETRIES_FAIL);
   }
+  fetch_started_ = false;
 }
 
 bool ServicesCustomizationDocument::ApplyOOBECustomization() {
-  // TODO(dpolukhin): apply default wallpaper.
+  // TODO(dpolukhin): apply default wallpaper, crbug.com/348136.
   SetApplied(true);
   return true;
 }
@@ -495,6 +558,14 @@
   return true;
 }
 
+std::string ServicesCustomizationDocument::GetOemAppsFolderName(
+    const std::string& locale) const {
+  if (!IsReady())
+    return std::string();
+
+  return GetOemAppsFolderNameImpl(locale, *root_);
+}
+
 scoped_ptr<base::DictionaryValue>
 ServicesCustomizationDocument::GetDefaultAppsInProviderFormat(
     const base::DictionaryValue& root) {
@@ -532,6 +603,7 @@
   if (IsReady()) {
     UpdateCachedManifest(profile);
     loader->SetCurrentApps(GetDefaultAppsInProviderFormat(*root_));
+    SetOemFolderName(profile, *root_);
   } else {
     const base::DictionaryValue* root =
         profile->GetPrefs()->GetDictionary(kServicesCustomizationKey);
@@ -539,7 +611,7 @@
     if (root && root->GetString(kVersionAttr, &version)) {
       // If version exists, profile has cached version of customization.
       loader->SetCurrentApps(GetDefaultAppsInProviderFormat(*root));
-      // TODO(dpolukhin): periodically refresh cached copy, crbug.com/343589.
+      SetOemFolderName(profile, *root);
     } else {
       // StartFetching will be called from ServicesCustomizationExternalLoader
       // when StartLoading is called. We can't initiate manifest fetch here
@@ -550,4 +622,45 @@
   return loader;
 }
 
+void ServicesCustomizationDocument::OnCustomizationNotFound() {
+  LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_FILE_NOT_FOUND);
+  LoadManifestFromString(kEmptyServicesCustomizationManifest);
+}
+
+void ServicesCustomizationDocument::SetOemFolderName(
+    Profile* profile,
+    const base::DictionaryValue& root) {
+  std::string locale = g_browser_process->GetApplicationLocale();
+  std::string name = GetOemAppsFolderNameImpl(locale, root);
+  if (!name.empty()) {
+    app_list::AppListSyncableService* service =
+        app_list::AppListSyncableServiceFactory::GetForProfile(profile);
+    if (!service) {
+      LOG(WARNING) << "AppListSyncableService is not ready for setting OEM "
+                      "folder name";
+      return;
+    }
+    service->SetOemFolderName(name);
+  }
+}
+
+std::string ServicesCustomizationDocument::GetOemAppsFolderNameImpl(
+    const std::string& locale,
+    const base::DictionaryValue& root) const {
+  return GetLocaleSpecificStringImpl(
+      &root, locale, kLocalizedContent, kDefaultAppsFolderName);
+}
+
+// static
+void ServicesCustomizationDocument::InitializeForTesting() {
+  g_test_services_customization_document = new ServicesCustomizationDocument;
+  g_test_services_customization_document->network_delay_ = base::TimeDelta();
+}
+
+// static
+void ServicesCustomizationDocument::ShutdownForTesting() {
+  delete g_test_services_customization_document;
+  g_test_services_customization_document = NULL;
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/customization_document.h b/chrome/browser/chromeos/customization_document.h
index a6241cc..1c0ea8f 100644
--- a/chrome/browser/chromeos/customization_document.h
+++ b/chrome/browser/chromeos/customization_document.h
@@ -13,7 +13,6 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
 #include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
 #include "base/values.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "url/gurl.h"
@@ -170,6 +169,16 @@
   // Cache of OEM default apps stored in profile preferences.
   extensions::ExternalLoader* CreateExternalLoader(Profile* profile);
 
+  // Returns the name of the folder for OEM apps for given |locale|.
+  std::string GetOemAppsFolderName(const std::string& locale) const;
+
+  // Initialize instance of ServicesCustomizationDocument for tests that will
+  // override singleton until ShutdownForTesting is called.
+  static void InitializeForTesting();
+
+  // Remove instance of ServicesCustomizationDocument for tests.
+  static void ShutdownForTesting();
+
  private:
   friend struct DefaultSingletonTraits<ServicesCustomizationDocument>;
 
@@ -193,11 +202,16 @@
   // Overriden from net::URLFetcherDelegate:
   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
 
-  // Initiate file fetching.
+  // Initiate file fetching. Wait for online status.
   void StartFileFetch();
 
+  // Initiate file fetching. Don't wait for online status.
+  void DoStartFileFetch();
+
   // Executes on FILE thread and reads file to string.
-  void ReadFileInBackground(const base::FilePath& file);
+  static void ReadFileInBackground(
+      base::WeakPtr<ServicesCustomizationDocument> self,
+      const base::FilePath& file);
 
   // Called on UI thread with results of ReadFileInBackground.
   void OnManifesteRead(const std::string& manifest);
@@ -212,24 +226,38 @@
   // Update cached manifest for |profile|.
   void UpdateCachedManifest(Profile* profile);
 
+  // Customization document not found for give ID.
+  void OnCustomizationNotFound();
+
+  // Set OEM apps folder name for AppListSyncableService for |profile|.
+  void SetOemFolderName(Profile* profile, const base::DictionaryValue& root);
+
+  // Returns the name of the folder for OEM apps for given |locale|.
+  std::string GetOemAppsFolderNameImpl(
+      const std::string& locale,
+      const base::DictionaryValue& root) const;
+
   // Services customization manifest URL.
   GURL url_;
 
   // URLFetcher instance.
   scoped_ptr<net::URLFetcher> url_fetcher_;
 
-  // Timer to retry fetching file if network is not available.
-  base::OneShotTimer<ServicesCustomizationDocument> retry_timer_;
-
   // How many times we already tried to fetch customization manifest file.
   int num_retries_;
 
   // Manifest fetch is already in progress.
   bool fetch_started_;
 
+  // Delay between checks for network online state.
+  base::TimeDelta network_delay_;
+
   // Known external loaders.
   ExternalLoaders external_loaders_;
 
+  // Weak factory for callbacks.
+  base::WeakPtrFactory<ServicesCustomizationDocument> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ServicesCustomizationDocument);
 };
 
diff --git a/chrome/browser/chromeos/customization_document_unittest.cc b/chrome/browser/chromeos/customization_document_unittest.cc
index ff71bb2..9dafcfa 100644
--- a/chrome/browser/chromeos/customization_document_unittest.cc
+++ b/chrome/browser/chromeos/customization_document_unittest.cc
@@ -4,17 +4,21 @@
 
 #include "chrome/browser/chromeos/customization_document.h"
 
-#include "base/at_exit.h"
 #include "base/message_loop/message_loop.h"
 #include "base/prefs/testing_pref_service.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/net/network_portal_detector_test_impl.h"
 #include "chrome/browser/extensions/external_provider_impl.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/prefs/pref_service_mock_factory.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
+#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
+#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/network/network_handler.h"
 #include "chromeos/system/mock_statistics_provider.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -76,11 +80,25 @@
     "  \"default_apps\": [\n"
     "    \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",\n"
     "    \"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"\n"
-    "  ]\n"
+    "  ],\n"
+    "  \"localized_content\": {\n"
+    "    \"en-US\": {\n"
+    "      \"default_apps_folder_name\": \"EN-US OEM Name\"\n"
+    "    },\n"
+    "    \"en\": {\n"
+    "      \"default_apps_folder_name\": \"EN OEM Name\"\n"
+    "    },\n"
+    "    \"default\": {\n"
+    "      \"default_apps_folder_name\": \"Default OEM Name\"\n"
+    "    }\n"
+    "  }\n"
     "}";
 
 const char kDummyCustomizationID[] = "test-dummy";
 
+// Note the path name must be the same as in shill stub.
+const char kStubEthernetServicePath[] = "eth1";
+
 }  // anonymous namespace
 
 namespace chromeos {
@@ -182,8 +200,9 @@
                     extensions::Manifest::Location,
                     int,
                     bool));
-  MOCK_METHOD5(OnExternalExtensionUpdateUrlFound,
+  MOCK_METHOD6(OnExternalExtensionUpdateUrlFound,
                bool(const std::string&,
+                    const std::string&,
                     const GURL&,
                     extensions::Manifest::Location,
                     int,
@@ -202,18 +221,37 @@
 
   // testing::Test:
   virtual void SetUp() OVERRIDE {
+    ServicesCustomizationDocument::InitializeForTesting();
+
     EXPECT_CALL(mock_statistics_provider_, GetMachineStatistic(_, NotNull()))
         .WillRepeatedly(Return(false));
     chromeos::system::StatisticsProvider::SetTestProvider(
         &mock_statistics_provider_);
 
+    DBusThreadManager::InitializeWithStub();
+    NetworkHandler::Initialize();
+
+    NetworkPortalDetector::InitializeForTesting(&network_portal_detector_);
+    NetworkPortalDetector::CaptivePortalState online_state;
+    online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
+    online_state.response_code = 204;
+    network_portal_detector_.SetDefaultNetworkPathForTesting(
+        kStubEthernetServicePath);
+    network_portal_detector_.SetDetectionResultsForTesting(
+        kStubEthernetServicePath, online_state);
+
     TestingBrowserProcess::GetGlobal()->SetLocalState(&local_state_);
     ServicesCustomizationDocument::RegisterPrefs(local_state_.registry());
   }
 
   virtual void TearDown() OVERRIDE {
     TestingBrowserProcess::GetGlobal()->SetLocalState(NULL);
+    NetworkHandler::Shutdown();
+    DBusThreadManager::Shutdown();
+    NetworkPortalDetector::InitializeForTesting(NULL);
     chromeos::system::StatisticsProvider::SetTestProvider(NULL);
+
+    ServicesCustomizationDocument::ShutdownForTesting();
   }
 
   void RunUntilIdle() {
@@ -240,6 +278,18 @@
       .WillRepeatedly(Invoke(AddMimeHeader));
   }
 
+  void AddManifestNotFound(const std::string& id) {
+    GURL url(base::StringPrintf(ServicesCustomizationDocument::kManifestUrl,
+                                id.c_str()));
+    factory_.SetFakeResponse(url,
+                             std::string(),
+                             net::HTTP_NOT_FOUND,
+                             net::URLRequestStatus::SUCCESS);
+    EXPECT_CALL(url_callback_, OnRequestCreate(url, _))
+      .Times(Exactly(1))
+      .WillRepeatedly(Invoke(AddMimeHeader));
+  }
+
   scoped_ptr<TestingProfile> CreateProfile() {
     TestingProfile::Builder profile_builder;
     PrefServiceMockFactory factory;
@@ -258,7 +308,7 @@
   TestingPrefServiceSimple local_state_;
   TestURLFetcherCallback url_callback_;
   net::FakeURLFetcherFactory factory_;
-  base::ShadowingAtExitManager at_exit_manager_;
+  NetworkPortalDetectorTestImpl network_portal_detector_;
 };
 
 TEST_F(ServicesCustomizationDocumentTest, Basic) {
@@ -282,9 +332,13 @@
 
   EXPECT_EQ(default_apps[0], "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
   EXPECT_EQ(default_apps[1], "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
+
+  EXPECT_EQ(doc->GetOemAppsFolderName("en-US"), "EN-US OEM Name");
+  EXPECT_EQ(doc->GetOemAppsFolderName("en"), "EN OEM Name");
+  EXPECT_EQ(doc->GetOemAppsFolderName("ru"), "Default OEM Name");
 }
 
-TEST_F(ServicesCustomizationDocumentTest, EmptyCustomization) {
+TEST_F(ServicesCustomizationDocumentTest, NoCustomizationIdInVpd) {
   ServicesCustomizationDocument* doc =
       ServicesCustomizationDocument::GetInstance();
   EXPECT_FALSE(doc->IsReady());
@@ -306,12 +360,13 @@
 
   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
       .Times(0);
-  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _))
+  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
       .Times(0);
   EXPECT_CALL(visitor, OnExternalProviderReady(_))
       .Times(1);
 
   // Manually request a load.
+  RunUntilIdle();
   loader->StartLoading();
   Mock::VerifyAndClearExpectations(&visitor);
 
@@ -344,7 +399,7 @@
 
   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
       .Times(0);
-  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _))
+  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
       .Times(0);
   EXPECT_CALL(visitor, OnExternalProviderReady(_))
       .Times(1);
@@ -355,13 +410,63 @@
 
   EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
       .Times(0);
-  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _))
+  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
       .Times(2);
   EXPECT_CALL(visitor, OnExternalProviderReady(_))
       .Times(1);
 
   RunUntilIdle();
   EXPECT_TRUE(doc->IsReady());
+
+  app_list::AppListSyncableService* service =
+      app_list::AppListSyncableServiceFactory::GetForProfile(profile.get());
+  ASSERT_TRUE(service);
+  EXPECT_EQ(service->GetOemFolderNameForTest(), "EN OEM Name");
+}
+
+TEST_F(ServicesCustomizationDocumentTest, CustomizationManifestNotFound) {
+  AddCustomizationIdToVp(kDummyCustomizationID);
+  AddManifestNotFound(kDummyCustomizationID);
+
+  ServicesCustomizationDocument* doc =
+      ServicesCustomizationDocument::GetInstance();
+  EXPECT_FALSE(doc->IsReady());
+
+  scoped_ptr<TestingProfile> profile = CreateProfile();
+  extensions::ExternalLoader* loader = doc->CreateExternalLoader(profile.get());
+  EXPECT_TRUE(loader);
+
+  MockExternalProviderVisitor visitor;
+  scoped_ptr<extensions::ExternalProviderImpl> provider(
+      new extensions::ExternalProviderImpl(
+          &visitor,
+          loader,
+          profile.get(),
+          extensions::Manifest::EXTERNAL_PREF,
+          extensions::Manifest::EXTERNAL_PREF_DOWNLOAD,
+          extensions::Extension::FROM_WEBSTORE |
+              extensions::Extension::WAS_INSTALLED_BY_DEFAULT));
+
+  EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
+      .Times(0);
+  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
+      .Times(0);
+  EXPECT_CALL(visitor, OnExternalProviderReady(_))
+      .Times(1);
+
+  // Manually request a load.
+  loader->StartLoading();
+  Mock::VerifyAndClearExpectations(&visitor);
+
+  EXPECT_CALL(visitor, OnExternalExtensionFileFound(_, _, _, _, _, _))
+      .Times(0);
+  EXPECT_CALL(visitor, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
+      .Times(0);
+  EXPECT_CALL(visitor, OnExternalProviderReady(_))
+      .Times(1);
+
+  RunUntilIdle();
+  EXPECT_TRUE(doc->IsReady());
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/display/display_preferences.cc b/chrome/browser/chromeos/display/display_preferences.cc
index d7a94b4..70843f0 100644
--- a/chrome/browser/chromeos/display/display_preferences.cc
+++ b/chrome/browser/chromeos/display/display_preferences.cc
@@ -62,6 +62,36 @@
   value->SetInteger(kInsetsRightKey, insets.right());
 }
 
+std::string ColorProfileToString(ui::ColorCalibrationProfile profile) {
+  switch (profile) {
+    case ui::COLOR_PROFILE_STANDARD:
+      return "standard";
+    case ui::COLOR_PROFILE_DYNAMIC:
+      return "dynamic";
+    case ui::COLOR_PROFILE_MOVIE:
+      return "movie";
+    case ui::COLOR_PROFILE_READING:
+      return "reading";
+    case ui::NUM_COLOR_PROFILES:
+      break;
+  }
+  NOTREACHED();
+  return "";
+}
+
+ui::ColorCalibrationProfile StringToColorProfile(std::string value) {
+  if (value == "standard")
+    return ui::COLOR_PROFILE_STANDARD;
+  else if (value == "dynamic")
+    return ui::COLOR_PROFILE_DYNAMIC;
+  else if (value == "movie")
+    return ui::COLOR_PROFILE_MOVIE;
+  else if (value == "reading")
+    return ui::COLOR_PROFILE_READING;
+  NOTREACHED();
+  return ui::COLOR_PROFILE_STANDARD;
+}
+
 ash::internal::DisplayManager* GetDisplayManager() {
   return ash::Shell::GetInstance()->display_manager();
 }
@@ -141,11 +171,17 @@
     gfx::Insets insets;
     if (ValueToInsets(*dict_value, &insets))
       insets_to_set = &insets;
+
+    ui::ColorCalibrationProfile color_profile = ui::COLOR_PROFILE_STANDARD;
+    std::string color_profile_name;
+    if (dict_value->GetString("color_profile_name", &color_profile_name))
+      color_profile = StringToColorProfile(color_profile_name);
     GetDisplayManager()->RegisterDisplayProperty(id,
                                                  rotation,
                                                  ui_scale,
                                                  insets_to_set,
-                                                 resolution_in_pixels);
+                                                 resolution_in_pixels,
+                                                 color_profile);
   }
 }
 
@@ -205,9 +241,12 @@
       property_value->SetInteger("width", mode.size.width());
       property_value->SetInteger("height", mode.size.height());
     }
-
     if (!info.overscan_insets_in_dip().empty())
       InsetsToValue(info.overscan_insets_in_dip(), property_value.get());
+    if (info.color_profile() != ui::COLOR_PROFILE_STANDARD) {
+      property_value->SetString(
+          "color_profile_name", ColorProfileToString(info.color_profile()));
+    }
     pref_data->Set(base::Int64ToString(id), property_value.release());
   }
 }
diff --git a/chrome/browser/chromeos/display/display_preferences_unittest.cc b/chrome/browser/chromeos/display/display_preferences_unittest.cc
index 2c141e4..8dec826 100644
--- a/chrome/browser/chromeos/display/display_preferences_unittest.cc
+++ b/chrome/browser/chromeos/display/display_preferences_unittest.cc
@@ -330,7 +330,8 @@
 
   // Set new display's selected resolution.
   display_manager->RegisterDisplayProperty(
-      id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400));
+      id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400),
+      ui::COLOR_PROFILE_STANDARD);
 
   UpdateDisplay("200x200*2, 600x500#600x500|500x400");
 
@@ -355,7 +356,8 @@
 
   // Set yet another new display's selected resolution.
   display_manager->RegisterDisplayProperty(
-      id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400));
+      id2 + 1, gfx::Display::ROTATE_0, 1.0f, NULL, gfx::Size(500, 400),
+      ui::COLOR_PROFILE_STANDARD);
   // Disconnect 2nd display first to generate new id for external display.
   UpdateDisplay("200x200*2");
   UpdateDisplay("200x200*2, 500x400#600x500|500x400%60.0f");
diff --git a/chrome/browser/chromeos/drive/change_list_processor.cc b/chrome/browser/chromeos/drive/change_list_processor.cc
index b84a620..5ef384d 100644
--- a/chrome/browser/chromeos/drive/change_list_processor.cc
+++ b/chrome/browser/chromeos/drive/change_list_processor.cc
@@ -383,8 +383,8 @@
 FileError ChangeListProcessor::RefreshDirectory(
     ResourceMetadata* resource_metadata,
     const DirectoryFetchInfo& directory_fetch_info,
-    ScopedVector<ChangeList> change_lists,
-    base::FilePath* out_file_path) {
+    scoped_ptr<ChangeList> change_list,
+    std::vector<ResourceEntry>* out_refreshed_entries) {
   DCHECK(!directory_fetch_info.empty());
 
   ResourceEntry directory;
@@ -396,52 +396,45 @@
   if (!directory.file_info().is_directory())
     return FILE_ERROR_NOT_A_DIRECTORY;
 
-  for (size_t i = 0; i < change_lists.size(); ++i) {
-    ChangeList* change_list = change_lists[i];
-    std::vector<ResourceEntry>* entries = change_list->mutable_entries();
-    for (size_t i = 0; i < entries->size(); ++i) {
-      ResourceEntry* entry = &(*entries)[i];
-      const std::string& parent_resource_id =
-          change_list->parent_resource_ids()[i];
+  std::vector<ResourceEntry>* entries = change_list->mutable_entries();
+  for (size_t i = 0; i < entries->size(); ++i) {
+    ResourceEntry* entry = &(*entries)[i];
+    const std::string& parent_resource_id =
+        change_list->parent_resource_ids()[i];
 
-      // Skip if the parent resource ID does not match. This is needed to
-      // handle entries with multiple parents. For such entries, the first
-      // parent is picked and other parents are ignored, hence some entries may
-      // have a parent resource ID which does not match the target directory's.
-      if (parent_resource_id != directory_fetch_info.resource_id()) {
-        DVLOG(1) << "Wrong-parent entry rejected: " << entry->resource_id();
-        continue;
-      }
-
-      entry->set_parent_local_id(directory_fetch_info.local_id());
-
-      std::string local_id;
-      error = resource_metadata->GetIdByResourceId(entry->resource_id(),
-                                                   &local_id);
-      if (error == FILE_ERROR_OK) {
-        entry->set_local_id(local_id);
-        error = resource_metadata->RefreshEntry(*entry);
-      }
-
-      if (error == FILE_ERROR_NOT_FOUND) {  // If refreshing fails, try adding.
-        std::string local_id;
-        entry->clear_local_id();
-        error = resource_metadata->AddEntry(*entry, &local_id);
-      }
-
-      if (error != FILE_ERROR_OK)
-        return error;
+    // Skip if the parent resource ID does not match. This is needed to
+    // handle entries with multiple parents. For such entries, the first
+    // parent is picked and other parents are ignored, hence some entries may
+    // have a parent resource ID which does not match the target directory's.
+    if (parent_resource_id != directory_fetch_info.resource_id()) {
+      DVLOG(1) << "Wrong-parent entry rejected: " << entry->resource_id();
+      continue;
     }
+
+    entry->set_parent_local_id(directory_fetch_info.local_id());
+
+    std::string local_id;
+    error = resource_metadata->GetIdByResourceId(entry->resource_id(),
+                                                 &local_id);
+    if (error == FILE_ERROR_OK) {
+      entry->set_local_id(local_id);
+      error = resource_metadata->RefreshEntry(*entry);
+    }
+
+    if (error == FILE_ERROR_NOT_FOUND) {  // If refreshing fails, try adding.
+      entry->clear_local_id();
+      error = resource_metadata->AddEntry(*entry, &local_id);
+    }
+
+    if (error != FILE_ERROR_OK)
+      return error;
+
+    ResourceEntry result_entry;
+    error = resource_metadata->GetResourceEntryById(local_id, &result_entry);
+    if (error != FILE_ERROR_OK)
+      return error;
+    out_refreshed_entries->push_back(result_entry);
   }
-
-  directory.mutable_directory_specific_info()->set_changestamp(
-      directory_fetch_info.changestamp());
-  error = resource_metadata->RefreshEntry(directory);
-  if (error != FILE_ERROR_OK)
-    return error;
-
-  *out_file_path = resource_metadata->GetFilePath(
-      directory_fetch_info.local_id());
   return FILE_ERROR_OK;
 }
 
diff --git a/chrome/browser/chromeos/drive/change_list_processor.h b/chrome/browser/chromeos/drive/change_list_processor.h
index 5a219c1..56a8fb3 100644
--- a/chrome/browser/chromeos/drive/change_list_processor.h
+++ b/chrome/browser/chromeos/drive/change_list_processor.h
@@ -122,13 +122,12 @@
   // The set of changed directories as a result of change list processing.
   const std::set<base::FilePath>& changed_dirs() const { return changed_dirs_; }
 
-  // Updates the changestamp of a directory according to |directory_fetch_info|
-  // and adds or refreshes the child entries from |change_lists|.
+  // Adds or refreshes the child entries from |change_list| to the directory.
   static FileError RefreshDirectory(
       ResourceMetadata* resource_metadata,
       const DirectoryFetchInfo& directory_fetch_info,
-      ScopedVector<ChangeList> change_lists,
-      base::FilePath* out_file_path);
+      scoped_ptr<ChangeList> change_list,
+      std::vector<ResourceEntry>* out_refreshed_entries);
 
   // Sets |entry|'s parent_local_id.
   static FileError SetParentLocalIdOfEntry(
diff --git a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
index 18e5908..c5bbc87 100644
--- a/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
+++ b/chrome/browser/chromeos/drive/change_list_processor_unittest.cc
@@ -505,45 +505,38 @@
   EXPECT_EQ(FILE_ERROR_OK,
             ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
 
-  // Create change lists.
-  ScopedVector<ChangeList> change_lists;
-  change_lists.push_back(new ChangeList);
+  // Create change list.
+  scoped_ptr<ChangeList> change_list(new ChangeList);
 
-  // Add a new file to the change lists.
+  // Add a new file to the change list.
   ResourceEntry new_file;
   new_file.set_title("new_file");
   new_file.set_resource_id("new_file_id");
-  change_lists[0]->mutable_entries()->push_back(new_file);
-  change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId);
+  change_list->mutable_entries()->push_back(new_file);
+  change_list->mutable_parent_resource_ids()->push_back(kRootId);
 
   // Add "Directory 1" to the map with a new name.
   ResourceEntry dir1;
   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
       util::GetDriveMyDriveRootPath().AppendASCII("Directory 1"), &dir1));
   dir1.set_title(dir1.title() + " (renamed)");
-  change_lists[0]->mutable_entries()->push_back(dir1);
-  change_lists[0]->mutable_parent_resource_ids()->push_back(kRootId);
+  change_list->mutable_entries()->push_back(dir1);
+  change_list->mutable_parent_resource_ids()->push_back(kRootId);
 
   // Update the directory with the map.
   ResourceEntry root;
   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
       util::GetDriveMyDriveRootPath(), &root));
   const int64 kNewChangestamp = 12345;
-  base::FilePath file_path;
+  ResourceEntryVector refreshed_entries;
   EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory(
       metadata_.get(),
       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
-      change_lists.Pass(),
-      &file_path));
-  EXPECT_EQ(util::GetDriveMyDriveRootPath().value(), file_path.value());
-
-  // The new changestamp should be set.
-  ResourceEntry entry;
-  EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
-      util::GetDriveMyDriveRootPath(), &entry));
-  EXPECT_EQ(kNewChangestamp, entry.directory_specific_info().changestamp());
+      change_list.Pass(),
+      &refreshed_entries));
 
   // "new_file" should be added.
+  ResourceEntry entry;
   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
       util::GetDriveMyDriveRootPath().AppendASCII(new_file.title()), &entry));
 
@@ -557,16 +550,15 @@
   EXPECT_EQ(FILE_ERROR_OK,
             ApplyFullResourceList(ParseChangeList(kBaseResourceListFile)));
 
-  // Create change lists and add a new file to it.
-  ScopedVector<ChangeList> change_lists;
-  change_lists.push_back(new ChangeList);
+  // Create change list and add a new file to it.
+  scoped_ptr<ChangeList> change_list(new ChangeList);
   ResourceEntry new_file;
   new_file.set_title("new_file");
   new_file.set_resource_id("new_file_id");
   // This entry should not be added because the parent ID does not match.
-  change_lists[0]->mutable_parent_resource_ids()->push_back(
+  change_list->mutable_parent_resource_ids()->push_back(
       "some-random-resource-id");
-  change_lists[0]->mutable_entries()->push_back(new_file);
+  change_list->mutable_entries()->push_back(new_file);
 
 
   // Update the directory.
@@ -574,13 +566,12 @@
   EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryByPath(
       util::GetDriveMyDriveRootPath(), &root));
   const int64 kNewChangestamp = 12345;
-  base::FilePath file_path;
+  ResourceEntryVector refreshed_entries;
   EXPECT_EQ(FILE_ERROR_OK, ChangeListProcessor::RefreshDirectory(
       metadata_.get(),
       DirectoryFetchInfo(root.local_id(), kRootId, kNewChangestamp),
-      change_lists.Pass(),
-      &file_path));
-  EXPECT_EQ(util::GetDriveMyDriveRootPath().value(), file_path.value());
+      change_list.Pass(),
+      &refreshed_entries));
 
   // "new_file" should not be added.
   ResourceEntry entry;
diff --git a/chrome/browser/chromeos/drive/directory_loader.cc b/chrome/browser/chromeos/drive/directory_loader.cc
index 1e3a51d..0b4ab8c 100644
--- a/chrome/browser/chromeos/drive/directory_loader.cc
+++ b/chrome/browser/chromeos/drive/directory_loader.cc
@@ -36,6 +36,7 @@
                           const google_apis::AboutResource& about_resource,
                           const std::string& local_id,
                           ResourceEntry* entry,
+                          ResourceEntryVector* child_entries,
                           int64* local_changestamp) {
   // Fill My Drive resource ID.
   ResourceEntry mydrive;
@@ -56,40 +57,56 @@
   if (error != FILE_ERROR_OK)
     return error;
 
+  // Get child entries.
+  error = resource_metadata->ReadDirectoryById(local_id, child_entries);
+  if (error != FILE_ERROR_OK)
+    return error;
+
   // Get the local changestamp.
   *local_changestamp = resource_metadata->GetLargestChangestamp();
   return FILE_ERROR_OK;
 }
 
-void ReadDirectoryAfterRead(const std::vector<ReadDirectoryCallback>& callbacks,
-                            scoped_ptr<ResourceEntryVector> entries,
-                            FileError error) {
+FileError UpdateChangestamp(ResourceMetadata* resource_metadata,
+                            const DirectoryFetchInfo& directory_fetch_info,
+                            base::FilePath* directory_path) {
+  // Update the directory changestamp.
+  ResourceEntry directory;
+  FileError error = resource_metadata->GetResourceEntryById(
+      directory_fetch_info.local_id(), &directory);
   if (error != FILE_ERROR_OK)
-    entries.reset();
-  for (size_t i = 0; i < callbacks.size(); ++i) {
-    scoped_ptr<ResourceEntryVector> copied_entries;
-    if (entries)
-      copied_entries.reset(new ResourceEntryVector(*entries));
+    return error;
 
-    callbacks[i].Run(error, copied_entries.Pass(), false /*has_more*/);
-  }
+  if (!directory.file_info().is_directory())
+    return FILE_ERROR_NOT_A_DIRECTORY;
+
+  directory.mutable_directory_specific_info()->set_changestamp(
+      directory_fetch_info.changestamp());
+  error = resource_metadata->RefreshEntry(directory);
+  if (error != FILE_ERROR_OK)
+    return error;
+
+  // Get the directory path.
+  *directory_path = resource_metadata->GetFilePath(
+      directory_fetch_info.local_id());
+  return FILE_ERROR_OK;
 }
 
 }  // namespace
 
+struct DirectoryLoader::ReadDirectoryCallbackState {
+  ReadDirectoryCallback callback;
+  std::set<std::string> sent_entry_names;
+};
+
 // Fetches the resource entries in the directory with |directory_resource_id|.
 class DirectoryLoader::FeedFetcher {
  public:
-  typedef base::Callback<void(FileError, ScopedVector<ChangeList>)>
-      FeedFetcherCallback;
-
-  FeedFetcher(JobScheduler* scheduler,
-              DriveServiceInterface* drive_service,
-              const std::string& directory_resource_id,
+  FeedFetcher(DirectoryLoader* loader,
+              const DirectoryFetchInfo& directory_fetch_info,
               const std::string& root_folder_id)
-      : scheduler_(scheduler),
-        drive_service_(drive_service),
-        directory_resource_id_(directory_resource_id),
+      : loader_(loader),
+        directory_fetch_info_(directory_fetch_info),
         root_folder_id_(root_folder_id),
         weak_ptr_factory_(this) {
   }
@@ -97,10 +114,10 @@
   ~FeedFetcher() {
   }
 
-  void Run(const FeedFetcherCallback& callback) {
+  void Run(const FileOperationCallback& callback) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     DCHECK(!callback.is_null());
-    DCHECK(!directory_resource_id_.empty());
+    DCHECK(!directory_fetch_info_.resource_id().empty());
 
     // Remember the time stamp for usage stats.
     start_time_ = base::TimeTicks::Now();
@@ -110,14 +127,14 @@
     // regression.
     // TODO(hashimoto): Remove this. crbug.com/340931.
 
-    std::string resource_id = directory_resource_id_;
-    if (directory_resource_id_ == root_folder_id_) {
+    std::string resource_id = directory_fetch_info_.resource_id();
+    if (resource_id == root_folder_id_) {
       // GData WAPI doesn't accept the root directory id which is used in Drive
       // API v2. So it is necessary to translate it here.
       resource_id = util::kWapiRootDirectoryResourceId;
     }
 
-    scheduler_->GetResourceListInDirectoryByWapi(
+    loader_->scheduler_->GetResourceListInDirectoryByWapi(
         resource_id,
         base::Bind(&FeedFetcher::OnResourceListFetched,
                    weak_ptr_factory_.GetWeakPtr(), callback));
@@ -125,7 +142,7 @@
 
  private:
   void OnResourceListFetched(
-      const FeedFetcherCallback& callback,
+      const FileOperationCallback& callback,
       google_apis::GDataErrorCode status,
       scoped_ptr<google_apis::ResourceList> resource_list) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -133,20 +150,54 @@
 
     FileError error = GDataToFileError(status);
     if (error != FILE_ERROR_OK) {
-      callback.Run(error, ScopedVector<ChangeList>());
+      callback.Run(error);
       return;
     }
 
-    // Add the current change list to the list of collected lists.
     DCHECK(resource_list);
-    ChangeList* change_list = new ChangeList(*resource_list);
-    FixResourceIdInChangeList(change_list);
-    change_lists_.push_back(change_list);
+    scoped_ptr<ChangeList> change_list(new ChangeList(*resource_list));
+    FixResourceIdInChangeList(change_list.get());
 
     GURL next_url;
-    if (resource_list->GetNextFeedURL(&next_url) && !next_url.is_empty()) {
+    resource_list->GetNextFeedURL(&next_url);
+
+    ResourceEntryVector* entries = new ResourceEntryVector;
+    loader_->loader_controller_->ScheduleRun(base::Bind(
+        base::IgnoreResult(
+            &base::PostTaskAndReplyWithResult<FileError, FileError>),
+        loader_->blocking_task_runner_,
+        FROM_HERE,
+        base::Bind(&ChangeListProcessor::RefreshDirectory,
+                   loader_->resource_metadata_,
+                   directory_fetch_info_,
+                   base::Passed(&change_list),
+                   entries),
+        base::Bind(&FeedFetcher::OnDirectoryRefreshed,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   callback,
+                   next_url,
+                   base::Owned(entries))));
+  }
+
+  void OnDirectoryRefreshed(
+      const FileOperationCallback& callback,
+      const GURL& next_url,
+      const std::vector<ResourceEntry>* refreshed_entries,
+      FileError error) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK(!callback.is_null());
+
+    if (error != FILE_ERROR_OK) {
+      callback.Run(error);
+      return;
+    }
+
+    loader_->SendEntries(directory_fetch_info_.local_id(), *refreshed_entries,
+                         true /*has_more*/);
+
+    if (!next_url.is_empty()) {
       // There is the remaining result so fetch it.
-      scheduler_->GetRemainingResourceList(
+      loader_->scheduler_->GetRemainingResourceList(
           next_url,
           base::Bind(&FeedFetcher::OnResourceListFetched,
                      weak_ptr_factory_.GetWeakPtr(), callback));
@@ -159,7 +210,7 @@
     // Note: The fetcher is managed by DirectoryLoader, and the instance
     // will be deleted in the callback. Do not touch the fields after this
     // invocation.
-    callback.Run(FILE_ERROR_OK, change_lists_.Pass());
+    callback.Run(FILE_ERROR_OK);
   }
 
   // Fixes resource IDs in |change_list| into the format that |drive_service_|
@@ -181,14 +232,13 @@
   std::string FixResourceId(const std::string& resource_id) {
     if (resource_id == util::kWapiRootDirectoryResourceId)
       return root_folder_id_;
-    return drive_service_->GetResourceIdCanonicalizer().Run(resource_id);
+    return loader_->drive_service_->GetResourceIdCanonicalizer().Run(
+        resource_id);
   }
 
-  JobScheduler* scheduler_;
-  DriveServiceInterface* drive_service_;
-  std::string directory_resource_id_;
+  DirectoryLoader* loader_;
+  DirectoryFetchInfo directory_fetch_info_;
   std::string root_folder_id_;
-  ScopedVector<ChangeList> change_lists_;
   base::TimeTicks start_time_;
   base::WeakPtrFactory<FeedFetcher> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(FeedFetcher);
@@ -285,7 +335,9 @@
 
   // Register the callback function to be called when it is loaded.
   const std::string& local_id = directory_fetch_info.local_id();
-  pending_load_callback_[local_id].push_back(callback);
+  ReadDirectoryCallbackState callback_state;
+  callback_state.callback = callback;
+  pending_load_callback_[local_id].push_back(callback_state);
 
   // If loading task for |local_id| is already running, do nothing.
   if (pending_load_callback_[local_id].size() > 1)
@@ -353,6 +405,7 @@
   // Check the current status of local metadata, and start loading if needed.
   google_apis::AboutResource* about_resource_ptr = about_resource.get();
   ResourceEntry* entry = new ResourceEntry;
+  ResourceEntryVector* child_entries = new ResourceEntryVector;
   int64* local_changestamp = new int64;
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_,
@@ -362,12 +415,14 @@
                  *about_resource_ptr,
                  local_id,
                  entry,
+                 child_entries,
                  local_changestamp),
       base::Bind(&DirectoryLoader::ReadDirectoryAfterCheckLocalState,
                  weak_ptr_factory_.GetWeakPtr(),
                  base::Passed(&about_resource),
                  local_id,
                  base::Owned(entry),
+                 base::Owned(child_entries),
                  base::Owned(local_changestamp)));
 }
 
@@ -375,6 +430,7 @@
     scoped_ptr<google_apis::AboutResource> about_resource,
     const std::string& local_id,
     const ResourceEntry* entry,
+    const ResourceEntryVector* child_entries,
     const int64* local_changestamp,
     FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -413,6 +469,8 @@
   if (directory_changestamp + kMinimumChangestampGap > remote_changestamp) {
     OnDirectoryLoadComplete(local_id, FILE_ERROR_OK);
   } else {
+    // Send locally found entries to callbacks.
+    SendEntries(local_id, *child_entries, true /*has_more*/);
     // Start fetching the directory content, and mark it with the changestamp
     // |remote_changestamp|.
     LoadDirectoryFromServer(directory_fetch_info);
@@ -427,22 +485,64 @@
                "Fast-fetch complete: %s => %s",
                local_id.c_str(),
                FileErrorToString(error).c_str());
+
+  ResourceEntryVector* entries = new ResourceEntryVector;
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_.get(),
+      FROM_HERE,
+      base::Bind(&ResourceMetadata::ReadDirectoryById,
+                 base::Unretained(resource_metadata_), local_id, entries),
+      base::Bind(&DirectoryLoader::OnDirectoryLoadCompleteAfterRead,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 local_id,
+                 base::Owned(entries)));
+}
+
+void DirectoryLoader::OnDirectoryLoadCompleteAfterRead(
+    const std::string& local_id,
+    const ResourceEntryVector* entries,
+    FileError error) {
   LoadCallbackMap::iterator it = pending_load_callback_.find(local_id);
   if (it != pending_load_callback_.end()) {
     DVLOG(1) << "Running callback for " << local_id;
-    const std::vector<ReadDirectoryCallback>& callbacks = it->second;
-    ResourceEntryVector* entries = new ResourceEntryVector;
-    base::PostTaskAndReplyWithResult(
-        blocking_task_runner_.get(),
-        FROM_HERE,
-        base::Bind(&ResourceMetadata::ReadDirectoryById,
-                   base::Unretained(resource_metadata_), local_id, entries),
-        base::Bind(&ReadDirectoryAfterRead, callbacks,
-                   base::Passed(scoped_ptr<ResourceEntryVector>(entries))));
+
+    const bool kHasMore = false;
+    if (error == FILE_ERROR_OK) {
+      SendEntries(local_id, *entries, kHasMore);
+    } else {
+      for (size_t i = 0; i < it->second.size(); ++i) {
+        const ReadDirectoryCallbackState& callback_state = it->second[i];
+        callback_state.callback.Run(error, scoped_ptr<ResourceEntryVector>(),
+                                    kHasMore);
+      }
+    }
     pending_load_callback_.erase(it);
   }
 }
 
+void DirectoryLoader::SendEntries(const std::string& local_id,
+                                  const ResourceEntryVector& entries,
+                                  bool has_more) {
+  LoadCallbackMap::iterator it = pending_load_callback_.find(local_id);
+  DCHECK(it != pending_load_callback_.end());
+
+  for (size_t i = 0; i < it->second.size(); ++i) {
+    ReadDirectoryCallbackState* callback_state = &it->second[i];
+
+    // Filter out entries which were already sent.
+    scoped_ptr<ResourceEntryVector> entries_to_send(new ResourceEntryVector);
+    for (size_t i = 0; i < entries.size(); ++i) {
+      const ResourceEntry& entry = entries[i];
+      if (!callback_state->sent_entry_names.count(entry.base_name())) {
+        callback_state->sent_entry_names.insert(entry.base_name());
+        entries_to_send->push_back(entry);
+      }
+    }
+    callback_state->callback.Run(FILE_ERROR_OK, entries_to_send.Pass(),
+                                 has_more);
+  }
+}
+
 void DirectoryLoader::LoadDirectoryFromServer(
     const DirectoryFetchInfo& directory_fetch_info) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -451,9 +551,8 @@
   DVLOG(1) << "Start loading directory: " << directory_fetch_info.ToString();
 
   FeedFetcher* fetcher = new FeedFetcher(
-      scheduler_,
-      drive_service_,
-      directory_fetch_info.resource_id(),
+      this,
+      directory_fetch_info,
       about_resource_loader_->cached_about_resource()->root_folder_id());
   fast_fetch_feed_fetcher_set_.insert(fetcher);
   fetcher->Run(
@@ -466,8 +565,7 @@
 void DirectoryLoader::LoadDirectoryFromServerAfterLoad(
     const DirectoryFetchInfo& directory_fetch_info,
     FeedFetcher* fetcher,
-    FileError error,
-    ScopedVector<ChangeList> change_lists) {
+    FileError error) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!directory_fetch_info.empty());
 
@@ -483,24 +581,23 @@
     return;
   }
 
+  // Update changestamp and get the directory path.
   base::FilePath* directory_path = new base::FilePath;
-  loader_controller_->ScheduleRun(base::Bind(
-      base::IgnoreResult(
-          &base::PostTaskAndReplyWithResult<FileError, FileError>),
-      blocking_task_runner_,
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_.get(),
       FROM_HERE,
-      base::Bind(&ChangeListProcessor::RefreshDirectory,
+      base::Bind(&UpdateChangestamp,
                  resource_metadata_,
                  directory_fetch_info,
-                 base::Passed(&change_lists),
                  directory_path),
-      base::Bind(&DirectoryLoader::LoadDirectoryFromServerAfterRefresh,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 directory_fetch_info,
-                 base::Owned(directory_path))));
+      base::Bind(
+          &DirectoryLoader::LoadDirectoryFromServerAfterUpdateChangestamp,
+          weak_ptr_factory_.GetWeakPtr(),
+          directory_fetch_info,
+          base::Owned(directory_path)));
 }
 
-void DirectoryLoader::LoadDirectoryFromServerAfterRefresh(
+void DirectoryLoader::LoadDirectoryFromServerAfterUpdateChangestamp(
     const DirectoryFetchInfo& directory_fetch_info,
     const base::FilePath* directory_path,
     FileError error) {
diff --git a/chrome/browser/chromeos/drive/directory_loader.h b/chrome/browser/chromeos/drive/directory_loader.h
index 63b60a7..4318ded 100644
--- a/chrome/browser/chromeos/drive/directory_loader.h
+++ b/chrome/browser/chromeos/drive/directory_loader.h
@@ -67,6 +67,7 @@
 
  private:
   class FeedFetcher;
+  struct ReadDirectoryCallbackState;
 
   // Part of ReadDirectory().
   void ReadDirectoryAfterGetEntry(const base::FilePath& directory_path,
@@ -87,6 +88,7 @@
       scoped_ptr<google_apis::AboutResource> about_resource,
       const std::string& local_id,
       const ResourceEntry* entry,
+      const ResourceEntryVector* child_entries,
       const int64* local_changestamp,
       FileError error);
 
@@ -94,6 +96,14 @@
   // This function should be called when the directory load is complete.
   // Flushes the callbacks waiting for the directory to be loaded.
   void OnDirectoryLoadComplete(const std::string& local_id, FileError error);
+  void OnDirectoryLoadCompleteAfterRead(const std::string& local_id,
+                                        const ResourceEntryVector* entries,
+                                        FileError error);
+
+  // Sends |entries| to the callbacks.
+  void SendEntries(const std::string& local_id,
+                   const ResourceEntryVector& entries,
+                   bool has_more);
 
   // ================= Implementation for directory loading =================
   // Loads the directory contents from server, and updates the local metadata.
@@ -104,11 +114,10 @@
   void LoadDirectoryFromServerAfterLoad(
       const DirectoryFetchInfo& directory_fetch_info,
       FeedFetcher* fetcher,
-      FileError error,
-      ScopedVector<ChangeList> change_lists);
+      FileError error);
 
   // Part of LoadDirectoryFromServer().
-  void LoadDirectoryFromServerAfterRefresh(
+  void LoadDirectoryFromServerAfterUpdateChangestamp(
       const DirectoryFetchInfo& directory_fetch_info,
       const base::FilePath* directory_path,
       FileError error);
@@ -121,7 +130,7 @@
   AboutResourceLoader* about_resource_loader_;  // Not owned.
   LoaderController* loader_controller_;  // Not owned.
   ObserverList<ChangeListLoaderObserver> observers_;
-  typedef std::map<std::string, std::vector<ReadDirectoryCallback> >
+  typedef std::map<std::string, std::vector<ReadDirectoryCallbackState> >
       LoadCallbackMap;
   LoadCallbackMap pending_load_callback_;
 
diff --git a/chrome/browser/chromeos/drive/directory_loader_unittest.cc b/chrome/browser/chromeos/drive/directory_loader_unittest.cc
index e426316..bb93d4b 100644
--- a/chrome/browser/chromeos/drive/directory_loader_unittest.cc
+++ b/chrome/browser/chromeos/drive/directory_loader_unittest.cc
@@ -206,6 +206,8 @@
             metadata_->GetResourceEntryByPath(util::GetDriveMyDriveRootPath(),
                                               &entry));
   EXPECT_EQ(drive_service_->GetRootResourceId(), entry.resource_id());
+  EXPECT_EQ(drive_service_->about_resource().largest_change_id(),
+            entry.directory_specific_info().changestamp());
 
   // My Drive's child is present.
   base::FilePath file_path =
diff --git a/chrome/browser/chromeos/drive/drive_file_stream_reader.cc b/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
index e9d97b1..4739398 100644
--- a/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
+++ b/chrome/browser/chromeos/drive/drive_file_stream_reader.cc
@@ -29,12 +29,6 @@
   return net::FileErrorToNetError(FileErrorToBaseFileError(error));
 }
 
-// Runs task on UI thread.
-void RunTaskOnUIThread(const base::Closure& task) {
-  google_apis::RunTaskOnThread(
-      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI), task);
-}
-
 // Computes the concrete |start| offset and the |length| of |range| in a file
 // of |total| size.
 //
@@ -119,6 +113,9 @@
     buffer_length = static_cast<int>(remaining_length_);
   }
 
+  if (!buffer_length)
+    return 0;
+
   file_reader_->Read(buffer, buffer_length,
                      base::Bind(&LocalReaderProxy::OnReadCompleted,
                                 weak_ptr_factory_.GetWeakPtr(), callback));
@@ -273,7 +270,7 @@
 // Calls FileSystemInterface::GetFileContent if the file system
 // is available. If not, the |completion_callback| is invoked with
 // FILE_ERROR_FAILED.
-void GetFileContentOnUIThread(
+base::Closure GetFileContentOnUIThread(
     const DriveFileStreamReader::FileSystemGetter& file_system_getter,
     const base::FilePath& drive_file_path,
     const GetFileContentInitializedCallback& initialized_callback,
@@ -284,13 +281,14 @@
   FileSystemInterface* file_system = file_system_getter.Run();
   if (!file_system) {
     completion_callback.Run(FILE_ERROR_FAILED);
-    return;
+    return base::Closure();
   }
 
-  file_system->GetFileContent(drive_file_path,
-                              initialized_callback,
-                              get_content_callback,
-                              completion_callback);
+  return google_apis::CreateRelayCallback(
+      file_system->GetFileContent(drive_file_path,
+                                  initialized_callback,
+                                  get_content_callback,
+                                  completion_callback));
 }
 
 // Helper to run FileSystemInterface::GetFileContent on UI thread.
@@ -299,10 +297,11 @@
     const base::FilePath& drive_file_path,
     const GetFileContentInitializedCallback& initialized_callback,
     const google_apis::GetContentCallback& get_content_callback,
-    const FileOperationCallback& completion_callback) {
+    const FileOperationCallback& completion_callback,
+    const base::Callback<void(const base::Closure&)>& reply_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 
-  BrowserThread::PostTask(
+  BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::UI,
       FROM_HERE,
       base::Bind(&GetFileContentOnUIThread,
@@ -310,7 +309,8 @@
                  drive_file_path,
                  google_apis::CreateRelayCallback(initialized_callback),
                  google_apis::CreateRelayCallback(get_content_callback),
-                 google_apis::CreateRelayCallback(completion_callback)));
+                 google_apis::CreateRelayCallback(completion_callback)),
+      reply_callback);
 }
 
 }  // namespace
@@ -351,7 +351,9 @@
                  weak_ptr_factory_.GetWeakPtr()),
       base::Bind(&DriveFileStreamReader::OnGetFileContentCompletion,
                  weak_ptr_factory_.GetWeakPtr(),
-                 callback));
+                 callback),
+      base::Bind(&DriveFileStreamReader::StoreCancelDownloadClosure,
+                 weak_ptr_factory_.GetWeakPtr()));
 }
 
 int DriveFileStreamReader::Read(net::IOBuffer* buffer, int buffer_length,
@@ -363,14 +365,21 @@
   return reader_proxy_->Read(buffer, buffer_length, callback);
 }
 
+void DriveFileStreamReader::StoreCancelDownloadClosure(
+    const base::Closure& cancel_download_closure) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  cancel_download_closure_ = cancel_download_closure;
+}
+
 void DriveFileStreamReader::InitializeAfterGetFileContentInitialized(
     const net::HttpByteRange& byte_range,
     const InitializeCompletionCallback& callback,
     FileError error,
-    scoped_ptr<ResourceEntry> entry,
     const base::FilePath& local_cache_file_path,
-    const base::Closure& ui_cancel_download_closure) {
+    scoped_ptr<ResourceEntry> entry) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  // StoreCancelDownloadClosure() should be called before this function.
+  DCHECK(!cancel_download_closure_.is_null());
 
   if (error != FILE_ERROR_OK) {
     callback.Run(FileErrorToNetError(error), scoped_ptr<ResourceEntry>());
@@ -385,8 +394,7 @@
     // At the same time, we cancel the in-flight downloading operation if
     // needed and and invalidate weak pointers so that we won't
     // receive unwanted callbacks.
-    if (!ui_cancel_download_closure.is_null())
-      RunTaskOnUIThread(ui_cancel_download_closure);
+    cancel_download_closure_.Run();
     weak_ptr_factory_.InvalidateWeakPtrs();
     callback.Run(
         net::ERR_REQUEST_RANGE_NOT_SATISFIABLE, scoped_ptr<ResourceEntry>());
@@ -395,11 +403,9 @@
 
   if (local_cache_file_path.empty()) {
     // The file is not cached, and being downloaded.
-    DCHECK(!ui_cancel_download_closure.is_null());
     reader_proxy_.reset(
         new internal::NetworkReaderProxy(
-            range_start, range_length,
-            base::Bind(&RunTaskOnUIThread, ui_cancel_download_closure)));
+            range_start, range_length, cancel_download_closure_));
     callback.Run(net::OK, entry.Pass());
     return;
   }
diff --git a/chrome/browser/chromeos/drive/drive_file_stream_reader.h b/chrome/browser/chromeos/drive/drive_file_stream_reader.h
index c39f285..b6a2b1d 100644
--- a/chrome/browser/chromeos/drive/drive_file_stream_reader.h
+++ b/chrome/browser/chromeos/drive/drive_file_stream_reader.h
@@ -172,15 +172,17 @@
            const net::CompletionCallback& callback);
 
  private:
+  // Used to store the cancel closure returned by FileSystemInterface.
+  void StoreCancelDownloadClosure(const base::Closure& cancel_download_closure);
+
   // Part of Initialize. Called after GetFileContent's initialization
   // is done.
   void InitializeAfterGetFileContentInitialized(
       const net::HttpByteRange& byte_range,
       const InitializeCompletionCallback& callback,
       FileError error,
-      scoped_ptr<ResourceEntry> entry,
       const base::FilePath& local_cache_file_path,
-      const base::Closure& cancel_download_closure);
+      scoped_ptr<ResourceEntry> entry);
 
   // Part of Initialize. Called when the local file open process is done.
   void InitializeAfterLocalFileOpen(
@@ -201,6 +203,7 @@
 
   const FileSystemGetter file_system_getter_;
   scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
+  base::Closure cancel_download_closure_;
   scoped_ptr<internal::ReaderProxy> reader_proxy_;
 
   // This should remain the last member so it'll be destroyed first and
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 15f20c0..82bf6fd 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -37,7 +37,7 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/user_agent.h"
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.cc b/chrome/browser/chromeos/drive/dummy_file_system.cc
new file mode 100644
index 0000000..696d695
--- /dev/null
+++ b/chrome/browser/chromeos/drive/dummy_file_system.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/drive/dummy_file_system.h"
+
+namespace drive {
+
+base::Closure DummyFileSystem::GetFileContent(
+      const base::FilePath& file_path,
+      const GetFileContentInitializedCallback& initialized_callback,
+      const google_apis::GetContentCallback& get_content_callback,
+      const FileOperationCallback& completion_callback) {
+  return base::Bind(&base::DoNothing);
+}
+
+}  // namespace drive
diff --git a/chrome/browser/chromeos/drive/dummy_file_system.h b/chrome/browser/chromeos/drive/dummy_file_system.h
index 493b59c..1147f8c 100644
--- a/chrome/browser/chromeos/drive/dummy_file_system.h
+++ b/chrome/browser/chromeos/drive/dummy_file_system.h
@@ -58,11 +58,11 @@
                        const GetFileCallback& callback) OVERRIDE {}
   virtual void GetFileForSaving(const base::FilePath& file_path,
                                 const GetFileCallback& callback) OVERRIDE {}
-  virtual void GetFileContent(
+  virtual base::Closure GetFileContent(
       const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
       const google_apis::GetContentCallback& get_content_callback,
-      const FileOperationCallback& completion_callback) OVERRIDE {}
+      const FileOperationCallback& completion_callback) OVERRIDE;
   virtual void GetResourceEntry(
       const base::FilePath& file_path,
       const GetResourceEntryCallback& callback) OVERRIDE {}
@@ -96,6 +96,9 @@
                              google_apis::drive::PermissionRole role,
                              const FileOperationCallback& callback) OVERRIDE {}
   virtual void Reset(const FileOperationCallback& callback) OVERRIDE {}
+  virtual void GetPathFromResourceId(const std::string& resource_id,
+                                     const GetFilePathCallback& callback)
+      OVERRIDE {}
 };
 
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/fake_file_system.cc b/chrome/browser/chromeos/drive/fake_file_system.cc
index 97dca44..00555dc 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system.cc
@@ -127,7 +127,7 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
-void FakeFileSystem::GetFileContent(
+base::Closure FakeFileSystem::GetFileContent(
     const base::FilePath& file_path,
     const GetFileContentInitializedCallback& initialized_callback,
     const google_apis::GetContentCallback& get_content_callback,
@@ -140,6 +140,7 @@
                  weak_ptr_factory_.GetWeakPtr(),
                  initialized_callback, get_content_callback,
                  completion_callback));
+  return base::Bind(&base::DoNothing);
 }
 
 void FakeFileSystem::GetResourceEntry(
@@ -231,6 +232,12 @@
 void FakeFileSystem::Reset(const FileOperationCallback& callback) {
 }
 
+void FakeFileSystem::GetPathFromResourceId(
+    const std::string& resource_id,
+    const GetFilePathCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+}
+
 // Implementation of GetFileContent.
 void FakeFileSystem::GetFileContentAfterGetResourceEntry(
     const GetFileContentInitializedCallback& initialized_callback,
@@ -289,14 +296,12 @@
       cache_dir_.path().AppendASCII(entry->resource_id());
   if (base::PathExists(cache_path)) {
     // Cache file is found.
-    initialized_callback.Run(FILE_ERROR_OK, entry.Pass(), cache_path,
-                             base::Closure());
+    initialized_callback.Run(FILE_ERROR_OK, cache_path, entry.Pass());
     completion_callback.Run(FILE_ERROR_OK);
     return;
   }
 
-  initialized_callback.Run(FILE_ERROR_OK, entry.Pass(), base::FilePath(),
-                           base::Bind(&base::DoNothing));
+  initialized_callback.Run(FILE_ERROR_OK, base::FilePath(), entry.Pass());
   drive_service_->DownloadFile(
       cache_path,
       gdata_entry->resource_id(),
diff --git a/chrome/browser/chromeos/drive/fake_file_system.h b/chrome/browser/chromeos/drive/fake_file_system.h
index e93a021..5c4cffb 100644
--- a/chrome/browser/chromeos/drive/fake_file_system.h
+++ b/chrome/browser/chromeos/drive/fake_file_system.h
@@ -87,7 +87,7 @@
                        const GetFileCallback& callback) OVERRIDE;
   virtual void GetFileForSaving(const base::FilePath& file_path,
                                 const GetFileCallback& callback) OVERRIDE;
-  virtual void GetFileContent(
+  virtual base::Closure GetFileContent(
       const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
       const google_apis::GetContentCallback& get_content_callback,
@@ -127,14 +127,11 @@
                              google_apis::drive::PermissionRole role,
                              const FileOperationCallback& callback) OVERRIDE;
   virtual void Reset(const FileOperationCallback& callback) OVERRIDE;
+  virtual void GetPathFromResourceId(const std::string& resource_id,
+                                     const GetFilePathCallback& callback)
+      OVERRIDE;
 
  private:
-  // Helper of GetResourceEntryById.
-  void GetResourceEntryByIdAfterGetResourceEntry(
-      const GetResourceEntryCallback& callback,
-      google_apis::GDataErrorCode error_in,
-      scoped_ptr<google_apis::ResourceEntry> resource_entry);
-
   // Helpers of GetFileContent.
   // How the method works:
   // 1) Gets ResourceEntry of the path.
diff --git a/chrome/browser/chromeos/drive/fake_file_system_unittest.cc b/chrome/browser/chromeos/drive/fake_file_system_unittest.cc
index 6b014ab..a391d12 100644
--- a/chrome/browser/chromeos/drive/fake_file_system_unittest.cc
+++ b/chrome/browser/chromeos/drive/fake_file_system_unittest.cc
@@ -38,7 +38,6 @@
   FileError initialize_error = FILE_ERROR_FAILED;
   scoped_ptr<ResourceEntry> entry;
   base::FilePath cache_file_path;
-  base::Closure cancel_download;
   google_apis::test_util::TestGetContentCallback get_content_callback;
   FileError completion_error = FILE_ERROR_FAILED;
 
@@ -46,10 +45,10 @@
       util::GetDriveMyDriveRootPath().AppendASCII("File 1.txt");
 
   // For the first time, the file should be downloaded from the service.
-  fake_file_system_->GetFileContent(
+  base::Closure cancel_download = fake_file_system_->GetFileContent(
       kDriveFile,
       google_apis::test_util::CreateCopyResultCallback(
-          &initialize_error, &entry, &cache_file_path, &cancel_download),
+          &initialize_error, &cache_file_path, &entry),
       get_content_callback.callback(),
       google_apis::test_util::CreateCopyResultCallback(&completion_error));
   base::RunLoop().RunUntilIdle();
@@ -72,10 +71,10 @@
   completion_error = FILE_ERROR_FAILED;
 
   // For the second time, the cache file should be found.
-  fake_file_system_->GetFileContent(
+  cancel_download = fake_file_system_->GetFileContent(
       kDriveFile,
       google_apis::test_util::CreateCopyResultCallback(
-          &initialize_error, &entry, &cache_file_path, &cancel_download),
+          &initialize_error, &cache_file_path, &entry),
       get_content_callback.callback(),
       google_apis::test_util::CreateCopyResultCallback(&completion_error));
   base::RunLoop().RunUntilIdle();
@@ -103,12 +102,10 @@
   base::FilePath cache_file_path;
   google_apis::test_util::TestGetContentCallback get_content_callback;
   FileError completion_error = FILE_ERROR_FAILED;
-  base::Closure cancel_download;
-
-  fake_file_system_->GetFileContent(
+  base::Closure cancel_download = fake_file_system_->GetFileContent(
       util::GetDriveMyDriveRootPath(),
       google_apis::test_util::CreateCopyResultCallback(
-          &initialize_error, &entry, &cache_file_path, &cancel_download),
+          &initialize_error, &cache_file_path, &entry),
       get_content_callback.callback(),
       google_apis::test_util::CreateCopyResultCallback(&completion_error));
   base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/drive/file_system.cc b/chrome/browser/chromeos/drive/file_system.cc
index 724b185..4e67ffa 100644
--- a/chrome/browser/chromeos/drive/file_system.cc
+++ b/chrome/browser/chromeos/drive/file_system.cc
@@ -205,6 +205,30 @@
  return cache->ClearAll() ? FILE_ERROR_OK : FILE_ERROR_FAILED;
 }
 
+// Part of GetPathFromResourceId().
+// Obtains |file_path| from |resource_id|. The function should be run on the
+// blocking pool.
+FileError GetPathFromResourceIdOnBlockingPool(
+    internal::ResourceMetadata* resource_metadata,
+    const std::string& resource_id,
+    base::FilePath* file_path) {
+  std::string local_id;
+  const FileError error =
+      resource_metadata->GetIdByResourceId(resource_id, &local_id);
+  *file_path = error == FILE_ERROR_OK ?
+      resource_metadata->GetFilePath(local_id) : base::FilePath();
+  return error;
+}
+
+// Part of GetPathFromResourceId().
+// Called when GetPathFromResourceIdInBlockingPool is complete.
+void GetPathFromResourceIdAfterGetPath(base::FilePath* file_path,
+                                       const GetFilePathCallback& callback,
+                                       FileError error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  callback.Run(error, *file_path);
+}
+
 // Excludes hosted documents from the given entries.
 // Used to implement ReadDirectory().
 void FilterHostedDocuments(const ReadDirectoryCallback& callback,
@@ -225,7 +249,6 @@
     }
     entries.swap(filtered);
   }
-  // TODO(hashimoto): Correctly handle empty entries when has_more==true.
   callback.Run(error, entries.Pass(), has_more);
 }
 
@@ -497,8 +520,6 @@
                            const base::Time& last_modified_time,
                            const FileOperationCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK(!last_access_time.is_null());
-  DCHECK(!last_modified_time.is_null());
   DCHECK(!callback.is_null());
   touch_operation_->TouchFile(
       file_path, last_access_time, last_modified_time, callback);
@@ -591,7 +612,7 @@
   get_file_for_saving_operation_->GetFileForSaving(file_path, callback);
 }
 
-void FileSystem::GetFileContent(
+base::Closure FileSystem::GetFileContent(
     const base::FilePath& file_path,
     const GetFileContentInitializedCallback& initialized_callback,
     const google_apis::GetContentCallback& get_content_callback,
@@ -601,7 +622,7 @@
   DCHECK(!get_content_callback.is_null());
   DCHECK(!completion_callback.is_null());
 
-  download_operation_->EnsureFileDownloadedByPath(
+  return download_operation_->EnsureFileDownloadedByPath(
       file_path,
       ClientContext(USER_INITIATED),
       initialized_callback,
@@ -987,4 +1008,21 @@
   open_file_operation_->OpenFile(file_path, open_mode, mime_type, callback);
 }
 
+void FileSystem::GetPathFromResourceId(const std::string& resource_id,
+                                       const GetFilePathCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!callback.is_null());
+
+  base::FilePath* const file_path = new base::FilePath();
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner_,
+      FROM_HERE,
+      base::Bind(&GetPathFromResourceIdOnBlockingPool,
+                 resource_metadata_,
+                 resource_id,
+                 file_path),
+      base::Bind(&GetPathFromResourceIdAfterGetPath,
+                 base::Owned(file_path),
+                 callback));
+}
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/file_system.h b/chrome/browser/chromeos/drive/file_system.h
index 28539fb..062afe9 100644
--- a/chrome/browser/chromeos/drive/file_system.h
+++ b/chrome/browser/chromeos/drive/file_system.h
@@ -127,7 +127,7 @@
                              const GetFileCallback& callback) OVERRIDE;
   virtual void GetFileForSaving(const base::FilePath& file_path,
                                       const GetFileCallback& callback) OVERRIDE;
-  virtual void GetFileContent(
+  virtual base::Closure GetFileContent(
       const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
       const google_apis::GetContentCallback& get_content_callback,
@@ -160,6 +160,9 @@
                              google_apis::drive::PermissionRole role,
                              const FileOperationCallback& callback) OVERRIDE;
   virtual void Reset(const FileOperationCallback& callback) OVERRIDE;
+  virtual void GetPathFromResourceId(const std::string& resource_id,
+                                     const GetFilePathCallback& callback)
+      OVERRIDE;
 
   // file_system::OperationObserver overrides.
   virtual void OnDirectoryChangedByOperation(
diff --git a/chrome/browser/chromeos/drive/file_system/download_operation.cc b/chrome/browser/chromeos/drive/file_system/download_operation.cc
index f1f2af9..778f2b7 100644
--- a/chrome/browser/chromeos/drive/file_system/download_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/download_operation.cc
@@ -263,30 +263,34 @@
       : initialized_callback_(initialized_callback),
         get_content_callback_(get_content_callback),
         completion_callback_(completion_callback),
-        entry_(entry.Pass()) {
+        entry_(entry.Pass()),
+        weak_ptr_factory_(this) {
     DCHECK(!completion_callback_.is_null());
     DCHECK(entry_);
   }
 
+  base::Closure GetCancelClosure() {
+    return base::Bind(&DownloadParams::Cancel, weak_ptr_factory_.GetWeakPtr());
+  }
+
   void OnCacheFileFound(const base::FilePath& cache_file_path) const {
     if (initialized_callback_.is_null())
       return;
 
     DCHECK(entry_);
-    initialized_callback_.Run(
-        FILE_ERROR_OK, make_scoped_ptr(new ResourceEntry(*entry_)),
-        cache_file_path, base::Closure());
+    initialized_callback_.Run(FILE_ERROR_OK, cache_file_path,
+                              make_scoped_ptr(new ResourceEntry(*entry_)));
   }
 
-  void OnStartDownloading(const base::Closure& cancel_download_closure) const {
+  void OnStartDownloading(const base::Closure& cancel_download_closure) {
+    cancel_download_closure_ = cancel_download_closure;
     if (initialized_callback_.is_null()) {
       return;
     }
 
     DCHECK(entry_);
-    initialized_callback_.Run(
-        FILE_ERROR_OK, make_scoped_ptr(new ResourceEntry(*entry_)),
-        base::FilePath(), cancel_download_closure);
+    initialized_callback_.Run(FILE_ERROR_OK, base::FilePath(),
+                              make_scoped_ptr(new ResourceEntry(*entry_)));
   }
 
   void OnError(FileError error) const {
@@ -305,12 +309,19 @@
   const ResourceEntry& entry() const { return *entry_; }
 
  private:
+  void Cancel() {
+    if (!cancel_download_closure_.is_null())
+      cancel_download_closure_.Run();
+  }
+
   const GetFileContentInitializedCallback initialized_callback_;
   const google_apis::GetContentCallback get_content_callback_;
   const GetFileCallback completion_callback_;
 
   scoped_ptr<ResourceEntry> entry_;
+  base::Closure cancel_download_closure_;
 
+  base::WeakPtrFactory<DownloadParams> weak_ptr_factory_;
   DISALLOW_COPY_AND_ASSIGN(DownloadParams);
 };
 
@@ -333,7 +344,7 @@
 DownloadOperation::~DownloadOperation() {
 }
 
-void DownloadOperation::EnsureFileDownloadedByLocalId(
+base::Closure DownloadOperation::EnsureFileDownloadedByLocalId(
     const std::string& local_id,
     const ClientContext& context,
     const GetFileContentInitializedCallback& initialized_callback,
@@ -348,6 +359,7 @@
   scoped_ptr<DownloadParams> params(new DownloadParams(
       initialized_callback, get_content_callback, completion_callback,
       make_scoped_ptr(entry)));
+  base::Closure cancel_closure = params->GetCancelClosure();
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(),
       FROM_HERE,
@@ -365,9 +377,10 @@
                  context,
                  base::Owned(drive_file_path),
                  base::Owned(cache_file_path)));
+  return cancel_closure;
 }
 
-void DownloadOperation::EnsureFileDownloadedByPath(
+base::Closure DownloadOperation::EnsureFileDownloadedByPath(
     const base::FilePath& file_path,
     const ClientContext& context,
     const GetFileContentInitializedCallback& initialized_callback,
@@ -382,6 +395,7 @@
   scoped_ptr<DownloadParams> params(new DownloadParams(
       initialized_callback, get_content_callback, completion_callback,
       make_scoped_ptr(entry)));
+  base::Closure cancel_closure = params->GetCancelClosure();
   base::PostTaskAndReplyWithResult(
       blocking_task_runner_.get(),
       FROM_HERE,
@@ -398,6 +412,7 @@
                  context,
                  base::Owned(drive_file_path),
                  base::Owned(cache_file_path)));
+  return cancel_closure;
 }
 
 void DownloadOperation::EnsureFileDownloadedAfterCheckPreCondition(
diff --git a/chrome/browser/chromeos/drive/file_system/download_operation.h b/chrome/browser/chromeos/drive/file_system/download_operation.h
index 7e739f5..19a4240 100644
--- a/chrome/browser/chromeos/drive/file_system/download_operation.h
+++ b/chrome/browser/chromeos/drive/file_system/download_operation.h
@@ -47,7 +47,7 @@
   ~DownloadOperation();
 
   // Ensures that the file content specified by |local_id| is locally
-  // downloaded.
+  // downloaded and returns a closure to cancel the task.
   // For hosted documents, this method may create a JSON file representing the
   // file.
   // For regular files, if the locally cached file is found, returns it.
@@ -62,7 +62,7 @@
   // |initialized_callback| and |get_content_callback| can be null if not
   // needed.
   // |completion_callback| must not be null.
-  void EnsureFileDownloadedByLocalId(
+  base::Closure EnsureFileDownloadedByLocalId(
       const std::string& local_id,
       const ClientContext& context,
       const GetFileContentInitializedCallback& initialized_callback,
@@ -71,7 +71,7 @@
 
   // Does the same thing as EnsureFileDownloadedByLocalId for the file
   // specified by |file_path|.
-  void EnsureFileDownloadedByPath(
+  base::Closure EnsureFileDownloadedByPath(
       const base::FilePath& file_path,
       const ClientContext& context,
       const GetFileContentInitializedCallback& initialized_callback,
diff --git a/chrome/browser/chromeos/drive/file_system/download_operation_unittest.cc b/chrome/browser/chromeos/drive/file_system/download_operation_unittest.cc
index 652e639..6718f73 100644
--- a/chrome/browser/chromeos/drive/file_system/download_operation_unittest.cc
+++ b/chrome/browser/chromeos/drive/file_system/download_operation_unittest.cc
@@ -298,27 +298,24 @@
     FileError initialized_error = FILE_ERROR_FAILED;
     scoped_ptr<ResourceEntry> entry, entry_dontcare;
     base::FilePath local_path, local_path_dontcare;
-    base::Closure cancel_download;
     google_apis::test_util::TestGetContentCallback get_content_callback;
-
     FileError completion_error = FILE_ERROR_FAILED;
-
-    operation_->EnsureFileDownloadedByPath(
+    base::Closure cancel_download = operation_->EnsureFileDownloadedByPath(
         file_in_root,
         ClientContext(USER_INITIATED),
         google_apis::test_util::CreateCopyResultCallback(
-            &initialized_error, &entry, &local_path, &cancel_download),
+            &initialized_error, &local_path, &entry),
         get_content_callback.callback(),
         google_apis::test_util::CreateCopyResultCallback(
             &completion_error, &local_path_dontcare, &entry_dontcare));
     test_util::RunBlockingPoolTask();
 
     // For the first time, file is downloaded from the remote server.
-    // In this case, |local_path| is empty while |cancel_download| is not.
+    // In this case, |local_path| is empty.
     EXPECT_EQ(FILE_ERROR_OK, initialized_error);
     ASSERT_TRUE(entry);
     ASSERT_TRUE(local_path.empty());
-    EXPECT_TRUE(!cancel_download.is_null());
+    EXPECT_FALSE(cancel_download.is_null());
     // Content is available through the second callback argument.
     EXPECT_EQ(static_cast<size_t>(entry->file_info().size()),
               get_content_callback.GetConcatenatedData().size());
@@ -335,27 +332,24 @@
     FileError initialized_error = FILE_ERROR_FAILED;
     scoped_ptr<ResourceEntry> entry, entry_dontcare;
     base::FilePath local_path, local_path_dontcare;
-    base::Closure cancel_download;
     google_apis::test_util::TestGetContentCallback get_content_callback;
-
     FileError completion_error = FILE_ERROR_FAILED;
-
-    operation_->EnsureFileDownloadedByPath(
+    base::Closure cancel_download = operation_->EnsureFileDownloadedByPath(
         file_in_root,
         ClientContext(USER_INITIATED),
         google_apis::test_util::CreateCopyResultCallback(
-            &initialized_error, &entry, &local_path, &cancel_download),
+            &initialized_error, &local_path, &entry),
         get_content_callback.callback(),
         google_apis::test_util::CreateCopyResultCallback(
             &completion_error, &local_path_dontcare, &entry_dontcare));
     test_util::RunBlockingPoolTask();
 
     // Try second download. In this case, the file should be cached, so
-    // |local_path| should not be empty while |cancel_download| is empty.
+    // |local_path| should not be empty.
     EXPECT_EQ(FILE_ERROR_OK, initialized_error);
     ASSERT_TRUE(entry);
     ASSERT_TRUE(!local_path.empty());
-    EXPECT_TRUE(cancel_download.is_null());
+    EXPECT_FALSE(cancel_download.is_null());
     // The content is available from the cache file.
     EXPECT_TRUE(get_content_callback.data().empty());
     int64 local_file_size = 0;
@@ -439,15 +433,13 @@
   FileError init_error;
   base::FilePath init_path;
   scoped_ptr<ResourceEntry> init_entry;
-  base::Closure cancel_callback;
-
   base::FilePath file_path;
   scoped_ptr<ResourceEntry> entry;
-  operation_->EnsureFileDownloadedByPath(
+  base::Closure cancel_callback = operation_->EnsureFileDownloadedByPath(
       file_in_root,
       ClientContext(USER_INITIATED),
       google_apis::test_util::CreateCopyResultCallback(
-          &init_error, &init_entry, &init_path, &cancel_callback),
+          &init_error, &init_path, &init_entry),
       google_apis::GetContentCallback(),
       google_apis::test_util::CreateCopyResultCallback(
           &error, &file_path, &entry));
diff --git a/chrome/browser/chromeos/drive/file_system/truncate_operation.cc b/chrome/browser/chromeos/drive/file_system/truncate_operation.cc
index 2659760..da64092 100644
--- a/chrome/browser/chromeos/drive/file_system/truncate_operation.cc
+++ b/chrome/browser/chromeos/drive/file_system/truncate_operation.cc
@@ -6,11 +6,10 @@
 
 #include "base/bind.h"
 #include "base/callback_helpers.h"
+#include "base/files/file.h"
 #include "base/files/file_path.h"
-#include "base/files/scoped_platform_file_closer.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop_proxy.h"
-#include "base/platform_file.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task_runner_util.h"
 #include "chrome/browser/chromeos/drive/drive.pb.h"
@@ -42,19 +41,12 @@
   if (error != FILE_ERROR_OK)
     return error;
 
-  base::PlatformFileError result = base::PLATFORM_FILE_ERROR_FAILED;
-  base::PlatformFile file = base::CreatePlatformFile(
-      local_cache_path,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
-      NULL,
-      &result);
-  if (result != base::PLATFORM_FILE_OK)
+  base::File file(local_cache_path,
+                  base::File::FLAG_OPEN | base::File::FLAG_WRITE);
+  if (!file.IsValid())
     return FILE_ERROR_FAILED;
 
-  DCHECK_NE(base::kInvalidPlatformFileValue, file);
-  base::ScopedPlatformFileCloser platform_file_closer(&file);
-
-  if (!base::TruncatePlatformFile(file, length))
+  if (!file.SetLength(length))
     return FILE_ERROR_FAILED;
 
   return FILE_ERROR_OK;
diff --git a/chrome/browser/chromeos/drive/file_system_interface.h b/chrome/browser/chromeos/drive/file_system_interface.h
index 6633c8c..d80e292 100644
--- a/chrome/browser/chromeos/drive/file_system_interface.h
+++ b/chrome/browser/chromeos/drive/file_system_interface.h
@@ -71,15 +71,11 @@
 
 // Used to get file content from the file system.
 // If the file content is available in local cache, |local_file| is filled with
-// the path to the cache file and |cancel_download_closure| is null. If the file
-// content starts to be downloaded from the server, |local_file| is empty and
-// |cancel_download_closure| is filled with a closure by calling which the
-// download job can be cancelled.
-// |cancel_download_closure| must be called on the UI thread.
+// the path to the cache file. If the file content starts to be downloaded from
+// the server, |local_file| is empty.
 typedef base::Callback<void(FileError error,
-                            scoped_ptr<ResourceEntry> entry,
                             const base::FilePath& local_file,
-                            const base::Closure& cancel_download_closure)>
+                            scoped_ptr<ResourceEntry> entry)>
     GetFileContentInitializedCallback;
 
 // Used to get list of entries under a directory.
@@ -137,6 +133,10 @@
 typedef base::Callback<void(bool success, const FileCacheEntry& cache_entry)>
     GetCacheEntryCallback;
 
+// Used to get file path.
+typedef base::Callback<void(FileError error, const base::FilePath& file_path)>
+    GetFilePathCallback;
+
 // The mode of opening a file.
 enum OpenMode {
   // Open the file if exists. If not, failed.
@@ -332,7 +332,8 @@
   virtual void GetFileForSaving(const base::FilePath& file_path,
                                 const GetFileCallback& callback) = 0;
 
-  // Gets a file by the given |file_path|.
+  // Gets a file by the given |file_path| and returns a closure to cancel the
+  // task.
   // Calls |initialized_callback| when either:
   //   1) The cached file (or JSON file for hosted file) is found, or
   //   2) Starting to download the file from drive server.
@@ -343,7 +344,7 @@
   // is successfully done.
   // |initialized_callback|, |get_content_callback| and |completion_callback|
   // must not be null.
-  virtual void GetFileContent(
+  virtual base::Closure GetFileContent(
       const base::FilePath& file_path,
       const GetFileContentInitializedCallback& initialized_callback,
       const google_apis::GetContentCallback& get_content_callback,
@@ -432,6 +433,10 @@
 
   // Resets local data.
   virtual void Reset(const FileOperationCallback& callback) = 0;
+
+  // Finds a path of an entry (a file or a directory) by |resource_id|.
+  virtual void GetPathFromResourceId(const std::string& resource_id,
+                                     const GetFilePathCallback& callback) = 0;
 };
 
 }  // namespace drive
diff --git a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
index f2e2b45..a41a091 100644
--- a/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
+++ b/chrome/browser/chromeos/drive/fileapi/async_file_util.cc
@@ -47,8 +47,6 @@
 
 // Runs CreateOrOpenFile callback based on the given |error| and |file|.
 void RunCreateOrOpenFileCallback(
-    const fileapi_internal::FileSystemGetter& file_system_getter,
-    const base::FilePath& file_path,
     const AsyncFileUtil::CreateOrOpenCallback& callback,
     base::File::Error error,
     base::PlatformFile file,
@@ -144,8 +142,7 @@
       base::Bind(&fileapi_internal::OpenFile,
                  file_path, file_flags,
                  google_apis::CreateRelayCallback(
-                     base::Bind(&RunCreateOrOpenFileCallback,
-                                getter, file_path, callback))),
+                     base::Bind(&RunCreateOrOpenFileCallback, callback))),
       base::Bind(&RunCreateOrOpenFileCallbackOnError,
                  callback, base::File::FILE_ERROR_FAILED));
 }
diff --git a/chrome/browser/chromeos/drive/local_file_reader.cc b/chrome/browser/chromeos/drive/local_file_reader.cc
index f7cf425..062bbb8 100644
--- a/chrome/browser/chromeos/drive/local_file_reader.cc
+++ b/chrome/browser/chromeos/drive/local_file_reader.cc
@@ -4,15 +4,9 @@
 
 #include "chrome/browser/chromeos/drive/local_file_reader.h"
 
-#include <errno.h>
-
 #include "base/bind.h"
-#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
-#include "base/location.h"
-#include "base/platform_file.h"
 #include "base/sequenced_task_runner.h"
-#include "base/task_runner_util.h"
 #include "net/base/completion_callback.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -20,157 +14,55 @@
 namespace drive {
 namespace util {
 
-namespace {
-
-// Opens the file at |file_path| and seeks to the |offset| from begin.
-// Returns the net::Error code. If succeeded, |platform_file| is set to point
-// the opened file.
-// This function should run on the blocking pool.
-int OpenAndSeekOnBlockingPool(const base::FilePath& file_path,
-                              int64 offset,
-                              base::PlatformFile* platform_file) {
-  DCHECK(platform_file);
-  DCHECK_EQ(base::kInvalidPlatformFileValue, *platform_file);
-
-  // First of all, open the file.
-  const int open_flags = base::PLATFORM_FILE_OPEN |
-                         base::PLATFORM_FILE_READ |
-                         base::PLATFORM_FILE_ASYNC;
-  base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
-  base::PlatformFile file =
-      base::CreatePlatformFile(file_path, open_flags, NULL, &error);
-  if (file == base::kInvalidPlatformFileValue) {
-    DCHECK_NE(base::PLATFORM_FILE_OK, error);
-    return net::FileErrorToNetError(static_cast<base::File::Error>(error));
-  }
-
-  // If succeeded, seek to the |offset| from begin.
-  int64 position = base::SeekPlatformFile(
-      file, base::PLATFORM_FILE_FROM_BEGIN, offset);
-  if (position < 0) {
-    // If failed, close the file and return an error.
-    base::ClosePlatformFile(file);
-    return net::ERR_FAILED;
-  }
-
-  *platform_file = file;
-  return net::OK;
-}
-
-// Reads the data from the |platform_file| and copies it to the |buffer| at
-// most |buffer_length| size. Returns the number of copied bytes if succeeded,
-// or the net::Error code.
-// This function should run on the blocking pool.
-int ReadOnBlockingPool(base::PlatformFile platform_file,
-                       scoped_refptr<net::IOBuffer> buffer,
-                       int buffer_length) {
-  DCHECK_NE(base::kInvalidPlatformFileValue, platform_file);
-  int result = base::ReadPlatformFileCurPosNoBestEffort(
-      platform_file, buffer->data(), buffer_length);
-  return result < 0 ? net::MapSystemError(errno) : result;
-}
-
-// Posts a task to close the |platform_file| into |task_runner|.
-// Or, if |platform_file| is kInvalidPlatformFileValue, does nothing.
-void PostCloseIfNeeded(base::TaskRunner* task_runner,
-                       base::PlatformFile platform_file) {
-  DCHECK(task_runner);
-  if (platform_file != base::kInvalidPlatformFileValue) {
-    task_runner->PostTask(
-        FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&base::ClosePlatformFile), platform_file));
-  }
-}
-
-}  // namespace
-
-class LocalFileReader::ScopedPlatformFile {
- public:
-  explicit ScopedPlatformFile(base::TaskRunner* task_runner)
-      : task_runner_(task_runner),
-        platform_file_(base::kInvalidPlatformFileValue) {
-    DCHECK(task_runner);
-  }
-
-  ~ScopedPlatformFile() {
-    PostCloseIfNeeded(task_runner_.get(), platform_file_);
-  }
-
-  base::PlatformFile* ptr() { return &platform_file_; }
-
-  base::PlatformFile release() {
-    base::PlatformFile result = platform_file_;
-    platform_file_ = base::kInvalidPlatformFileValue;
-    return result;
-  }
-
- private:
-  scoped_refptr<base::TaskRunner> task_runner_;
-  base::PlatformFile platform_file_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedPlatformFile);
-};
-
 LocalFileReader::LocalFileReader(
     base::SequencedTaskRunner* sequenced_task_runner)
-    : sequenced_task_runner_(sequenced_task_runner),
-      platform_file_(base::kInvalidPlatformFileValue),
+    : file_stream_(NULL, sequenced_task_runner),
       weak_ptr_factory_(this) {
-  DCHECK(sequenced_task_runner_.get());
 }
 
 LocalFileReader::~LocalFileReader() {
-  PostCloseIfNeeded(sequenced_task_runner_.get(), platform_file_);
 }
 
 void LocalFileReader::Open(const base::FilePath& file_path,
                            int64 offset,
                            const net::CompletionCallback& callback) {
   DCHECK(!callback.is_null());
-  DCHECK_EQ(base::kInvalidPlatformFileValue, platform_file_);
+  int flags = base::File::FLAG_OPEN | base::File::FLAG_READ |
+              base::PLATFORM_FILE_ASYNC;
 
-  ScopedPlatformFile* platform_file =
-      new ScopedPlatformFile(sequenced_task_runner_.get());
-  base::PostTaskAndReplyWithResult(
-      sequenced_task_runner_.get(),
-      FROM_HERE,
-      base::Bind(
-          &OpenAndSeekOnBlockingPool, file_path, offset, platform_file->ptr()),
-      base::Bind(&LocalFileReader::OpenAfterBlockingPoolTask,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 callback,
-                 base::Owned(platform_file)));
+  int rv = file_stream_.Open(file_path, flags,
+                             Bind(&LocalFileReader::DidOpen,
+                                  weak_ptr_factory_.GetWeakPtr(),
+                                  callback, offset));
+  DCHECK_EQ(rv, net::ERR_IO_PENDING);
 }
 
 void LocalFileReader::Read(net::IOBuffer* in_buffer,
                            int buffer_length,
                            const net::CompletionCallback& callback) {
   DCHECK(!callback.is_null());
-  DCHECK_NE(base::kInvalidPlatformFileValue, platform_file_);
-
-  scoped_refptr<net::IOBuffer> buffer(in_buffer);
-  base::PostTaskAndReplyWithResult(
-      sequenced_task_runner_.get(),
-      FROM_HERE,
-      base::Bind(&ReadOnBlockingPool, platform_file_, buffer, buffer_length),
-      callback);
+  DCHECK(file_stream_.IsOpen());
+  int rv = file_stream_.Read(in_buffer, buffer_length, callback);
+  DCHECK_EQ(rv, net::ERR_IO_PENDING);
 }
 
-void LocalFileReader::OpenAfterBlockingPoolTask(
-    const net::CompletionCallback& callback,
-    ScopedPlatformFile* platform_file,
-    int open_result) {
-  DCHECK(!callback.is_null());
-  DCHECK(platform_file);
-  DCHECK_EQ(base::kInvalidPlatformFileValue, platform_file_);
+void LocalFileReader::DidOpen(const net::CompletionCallback& callback,
+                              int64 offset,
+                              int error) {
+  if (error != net::OK)
+    return callback.Run(error);
 
-  if (open_result == net::OK) {
-    DCHECK_NE(base::kInvalidPlatformFileValue, *platform_file->ptr());
-    platform_file_ = platform_file->release();
-  }
+  int rv = file_stream_.Seek(net::FROM_BEGIN, offset,
+                             Bind(&LocalFileReader::DidSeek,
+                                  weak_ptr_factory_.GetWeakPtr(),
+                                  callback, offset));
+  DCHECK_EQ(rv, net::ERR_IO_PENDING);
+}
 
-  callback.Run(open_result);
+void LocalFileReader::DidSeek(const net::CompletionCallback& callback,
+                              int64 offset,
+                              int64 error) {
+  callback.Run(error == offset ? net::OK : net::ERR_FAILED);
 }
 
 }  // namespace util
diff --git a/chrome/browser/chromeos/drive/local_file_reader.h b/chrome/browser/chromeos/drive/local_file_reader.h
index 6577abd..0b824da 100644
--- a/chrome/browser/chromeos/drive/local_file_reader.h
+++ b/chrome/browser/chromeos/drive/local_file_reader.h
@@ -8,8 +8,8 @@
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
-#include "base/platform_file.h"
 #include "net/base/completion_callback.h"
+#include "net/base/file_stream.h"
 
 namespace base {
 class FilePath;
@@ -18,7 +18,7 @@
 
 namespace net {
 class IOBuffer;
-}  // namespace
+}  // namespace net
 
 namespace drive {
 namespace util {
@@ -49,18 +49,14 @@
             const net::CompletionCallback& callback);
 
  private:
-  // The thin wrapper for the platform file to handle closing correctly.
-  class ScopedPlatformFile;
+  void DidOpen(const net::CompletionCallback& callback,
+               int64 offset,
+               int error);
+  void DidSeek(const net::CompletionCallback& callback,
+               int64 offset,
+               int64 error);
 
-  // Part of Open(). Called after the open() operation task running
-  // on blocking pool.
-  void OpenAfterBlockingPoolTask(
-      const net::CompletionCallback& callback,
-      ScopedPlatformFile* result_platform_file,
-      int open_result);
-
-  scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
-  base::PlatformFile platform_file_;
+  net::FileStream file_stream_;
 
   // Note: This should remain the last member so it'll be destroyed and
   // invalidate the weak pointers before any other members are destroyed.
diff --git a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc b/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
index d9c4c6d..7fa3c9e 100644
--- a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
+++ b/chrome/browser/chromeos/drive/sync/entry_update_performer.cc
@@ -323,13 +323,12 @@
   }
 
   // No need to perform update.
-  if (local_state->entry.metadata_edit_state() == ResourceEntry::CLEAN) {
+  if (local_state->entry.metadata_edit_state() == ResourceEntry::CLEAN ||
+      local_state->entry.resource_id().empty()) {
     callback.Run(FILE_ERROR_OK);
     return;
   }
 
-  DCHECK(!local_state->entry.resource_id().empty());
-
   // Perform metadata update.
   scheduler_->UpdateResource(
       local_state->entry.resource_id(), local_state->parent_entry.resource_id(),
diff --git a/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc b/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc
index c87f2c9..b3e090e 100644
--- a/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc
+++ b/chrome/browser/chromeos/drive/sync/entry_update_performer_unittest.cc
@@ -429,6 +429,80 @@
   EXPECT_FALSE(resource_entry->is_folder());
 }
 
+TEST_F(EntryUpdatePerformerTest, UpdateEntry_NewFileOpendForWrite) {
+  // Create a new file locally.
+  const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/New File.txt"));
+
+  ResourceEntry parent;
+  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath.DirName(), &parent));
+
+  ResourceEntry entry;
+  entry.set_parent_local_id(parent.local_id());
+  entry.set_title(kFilePath.BaseName().AsUTF8Unsafe());
+  entry.mutable_file_specific_info()->set_content_mime_type("text/plain");
+  entry.set_metadata_edit_state(ResourceEntry::DIRTY);
+
+  FileError error = FILE_ERROR_FAILED;
+  std::string local_id;
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner(),
+      FROM_HERE,
+      base::Bind(&internal::ResourceMetadata::AddEntry,
+                 base::Unretained(metadata()),
+                 entry,
+                 &local_id),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  const std::string kTestFileContent = "This is a new file.";
+  EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
+
+  // Emulate a situation where someone is writing to the file.
+  scoped_ptr<base::ScopedClosureRunner> file_closer;
+  error = FILE_ERROR_FAILED;
+  base::PostTaskAndReplyWithResult(
+      blocking_task_runner(),
+      FROM_HERE,
+      base::Bind(&FileCache::OpenForWrite,
+                 base::Unretained(cache()),
+                 local_id,
+                 &file_closer),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // Update, but no update is performed because the file is opened.
+  error = FILE_ERROR_FAILED;
+  performer_->UpdateEntry(
+      local_id,
+      ClientContext(USER_INITIATED),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // The entry hasn't got a resource ID yet.
+  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
+  EXPECT_TRUE(entry.resource_id().empty());
+
+  // Close the file.
+  file_closer.reset();
+
+  // Update. This should result in creating a new file on the server.
+  error = FILE_ERROR_FAILED;
+  performer_->UpdateEntry(
+      local_id,
+      ClientContext(USER_INITIATED),
+      google_apis::test_util::CreateCopyResultCallback(&error));
+  test_util::RunBlockingPoolTask();
+  EXPECT_EQ(FILE_ERROR_OK, error);
+
+  // The entry got a resource ID.
+  EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
+  EXPECT_FALSE(entry.resource_id().empty());
+  EXPECT_EQ(ResourceEntry::CLEAN, entry.metadata_edit_state());
+}
+
 TEST_F(EntryUpdatePerformerTest, UpdateEntry_CreateDirectory) {
   // Create a new directory locally.
   const base::FilePath kPath(FILE_PATH_LITERAL("drive/root/New Directory"));
diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc
index 489769c..f76b3b2 100644
--- a/chrome/browser/chromeos/drive/sync_client.cc
+++ b/chrome/browser/chromeos/drive/sync_client.cc
@@ -127,6 +127,12 @@
   DCHECK(!it->HasError());
 }
 
+// Runs the task and returns a dummy cancel closure.
+base::Closure RunTaskAndReturnDummyCancelClosure(const base::Closure& task) {
+  task.Run();
+  return base::Closure();
+}
+
 }  // namespace
 
 SyncClient::SyncTask::SyncTask() : state(PENDING), should_run_again(false) {}
@@ -235,8 +241,7 @@
       base::Unretained(download_operation_.get()),
       local_id,
       ClientContext(BACKGROUND),
-      base::Bind(&SyncClient::OnGetFileContentInitialized,
-                 weak_ptr_factory_.GetWeakPtr()),
+      GetFileContentInitializedCallback(),
       google_apis::GetContentCallback(),
       base::Bind(&SyncClient::OnFetchFileComplete,
                  weak_ptr_factory_.GetWeakPtr(),
@@ -249,13 +254,14 @@
                                        const base::TimeDelta& delay) {
   SyncTask task;
   task.task = base::Bind(
-      &EntryUpdatePerformer::UpdateEntry,
-      base::Unretained(entry_update_performer_.get()),
-      local_id,
-      context,
-      base::Bind(&SyncClient::OnUpdateComplete,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 local_id));
+      &RunTaskAndReturnDummyCancelClosure,
+      base::Bind(&EntryUpdatePerformer::UpdateEntry,
+                 base::Unretained(entry_update_performer_.get()),
+                 local_id,
+                 context,
+                 base::Bind(&SyncClient::OnUpdateComplete,
+                            weak_ptr_factory_.GetWeakPtr(),
+                            local_id)));
   AddTask(SyncTasks::key_type(UPDATE, local_id), task, delay);
 }
 
@@ -296,7 +302,7 @@
   switch (task->state) {
     case PENDING:
       task->state = RUNNING;
-      task->task.Run();
+      task->cancel_closure = task->task.Run();
       break;
     case RUNNING:  // Do nothing.
       break;
@@ -330,23 +336,6 @@
     AddFetchTask((*local_ids)[i]);
 }
 
-void SyncClient::OnGetFileContentInitialized(
-    FileError error,
-    scoped_ptr<ResourceEntry> entry,
-    const base::FilePath& local_cache_file_path,
-    const base::Closure& cancel_download_closure) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
-  if (error != FILE_ERROR_OK)
-    return;
-
-  const SyncTasks::key_type key(FETCH, entry->local_id());
-  SyncTasks::iterator it = tasks_.find(key);
-  DCHECK(it != tasks_.end());
-
-  it->second.cancel_closure = cancel_download_closure;
-}
-
 bool SyncClient::OnTaskComplete(SyncType type, const std::string& local_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
diff --git a/chrome/browser/chromeos/drive/sync_client.h b/chrome/browser/chromeos/drive/sync_client.h
index a68458e..a8f6d1b 100644
--- a/chrome/browser/chromeos/drive/sync_client.h
+++ b/chrome/browser/chromeos/drive/sync_client.h
@@ -101,7 +101,7 @@
     SyncTask();
     ~SyncTask();
     SyncState state;
-    base::Closure task;
+    base::Callback<base::Closure()> task;
     bool should_run_again;
     base::Closure cancel_closure;
   };
@@ -132,13 +132,6 @@
   // Adds fetch tasks.
   void AddFetchTasks(const std::vector<std::string>* local_ids);
 
-  // Used as GetFileContentInitializedCallback.
-  void OnGetFileContentInitialized(
-      FileError error,
-      scoped_ptr<ResourceEntry> entry,
-      const base::FilePath& local_cache_file_path,
-      const base::Closure& cancel_download_closure);
-
   // Erases the task and returns true if task is completed.
   bool OnTaskComplete(SyncType type, const std::string& local_id);
 
diff --git a/chrome/browser/chromeos/events/event_rewriter.cc b/chrome/browser/chromeos/events/event_rewriter.cc
index 7981aaf..5b9dd5c 100644
--- a/chrome/browser/chromeos/events/event_rewriter.cc
+++ b/chrome/browser/chromeos/events/event_rewriter.cc
@@ -40,9 +40,6 @@
 
 const int kBadDeviceId = -1;
 
-const char kNeo2LayoutId[] = "xkb:de:neo:ger";
-const char kCaMultixLayoutId[] = "xkb:ca:multix:fra";
-
 // A key code and a flag we should use when a key is remapped to |remap_to|.
 const struct ModifierRemapping {
   int remap_to;
@@ -119,15 +116,14 @@
       chromeos::switches::kHasChromeOSDiamondKey);
 }
 
-bool IsMod3UsedByCurrentInputMethod() {
+bool IsISOLevel5ShiftUsedByCurrentInputMethod() {
   // Since both German Neo2 XKB layout and Caps Lock depend on Mod3Mask,
   // it's not possible to make both features work. For now, we don't remap
   // Mod3Mask when Neo2 is in use.
   // TODO(yusukes): Remove the restriction.
   chromeos::input_method::InputMethodManager* manager =
       chromeos::input_method::InputMethodManager::Get();
-  return manager->GetCurrentInputMethod().id() == kNeo2LayoutId ||
-      manager->GetCurrentInputMethod().id() == kCaMultixLayoutId;
+  return manager->IsISOLevel5ShiftUsedByCurrentInputMethod();
 }
 
 }  // namespace
@@ -396,7 +392,7 @@
   const bool skip_mod2 = !HasDiamondKey();
   // If Mod3 is used by the current input method, don't allow the CapsLock
   // pref to remap it, or the keyboard behavior will be broken.
-  const bool skip_mod3 = IsMod3UsedByCurrentInputMethod();
+  const bool skip_mod3 = IsISOLevel5ShiftUsedByCurrentInputMethod();
 
   for (size_t i = 0; i < arraysize(kModifierFlagToPrefName); ++i) {
     if ((skip_mod2 && kModifierFlagToPrefName[i].native_modifier == Mod2Mask) ||
@@ -473,9 +469,9 @@
         remapped_key = kModifierRemappingCtrl;
       break;
     // On Chrome OS, XF86XK_Launch7 (F16) with Mod3Mask is sent when Caps Lock
-    // is pressed (with one exception: when IsMod3UsedByCurrentInputMethod() is
-    // true, the key generates XK_ISO_Level3_Shift with Mod3Mask, not
-    // XF86XK_Launch7).
+    // is pressed (with one exception: when
+    // IsISOLevel5ShiftUsedByCurrentInputMethod() is true, the key generates
+    // XK_ISO_Level3_Shift with Mod3Mask, not XF86XK_Launch7).
     case XF86XK_Launch7:
       remapped_key =
           GetRemappedKey(prefs::kLanguageRemapCapsLockKeyTo, *pref_service);
diff --git a/chrome/browser/chromeos/events/event_rewriter_unittest.cc b/chrome/browser/chromeos/events/event_rewriter_unittest.cc
index 1be98d0..c5292f4 100644
--- a/chrome/browser/chromeos/events/event_rewriter_unittest.cc
+++ b/chrome/browser/chromeos/events/event_rewriter_unittest.cc
@@ -1860,7 +1860,7 @@
 
   EventRewriter rewriter;
   rewriter.set_pref_service_for_testing(&prefs);
-  input_method_manager_mock_->SetCurrentInputMethodId("xkb:de:neo:ger");
+  input_method_manager_mock_->set_mod3_used(true);
 
   // Press CapsLock+a. Confirm that Mod3Mask is NOT rewritten to ControlMask
   // when Mod3Mask is already in use by the current XKB layout.
@@ -1877,7 +1877,7 @@
                                       keycode_a_,
                                       Mod3Mask));
 
-  input_method_manager_mock_->SetCurrentInputMethodId("xkb:us::eng");
+  input_method_manager_mock_->set_mod3_used(false);
 }
 
 TEST_F(EventRewriterTest, TestRewriteExtendedKeys) {
diff --git a/chrome/browser/chromeos/extensions/OWNERS b/chrome/browser/chromeos/extensions/OWNERS
index f77501b..eca2510 100644
--- a/chrome/browser/chromeos/extensions/OWNERS
+++ b/chrome/browser/chromeos/extensions/OWNERS
@@ -19,4 +19,6 @@
 # bshe for wallpaper related files
 bshe@chromium.org
 
-per-file input_method_api.cc=nona@chromium.org
+# input method related reviewers. shuchen@ is primary, and nona@ is backup.
+per-file input_method*=shuchen@chromium.org
+per-file input_method*=nona@chromium.org
diff --git a/chrome/browser/chromeos/extensions/accessibility_features_apitest.cc b/chrome/browser/chromeos/extensions/accessibility_features_apitest.cc
new file mode 100644
index 0000000..98f0876
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/accessibility_features_apitest.cc
@@ -0,0 +1,262 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "base/json/json_writer.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/common/pref_names.h"
+
+// API tests for chrome.accessibilityFeatures API.
+// Note that the API is implemented using preference API infrastructure.
+// See preference_api.cc for the list of accessibility features exposed by the
+// API and the related preferences.
+
+namespace extensions {
+
+namespace {
+
+// Keys for data in the test config argument that will be set for the test app
+// to use.
+// The test that the app should run.
+const char kTestNameKey[] = "testName";
+// Key for list of features enabled when the test is initialized.
+const char kEnabledFeaturesKey[] = "enabled";
+// Key for list fo features disabled when the test is initialized.
+const char kDisabledFeaturesKey[] = "disabled";
+
+// A test extension path. The extension has only |accessibilityFeatures.read|
+// permission.
+const char kTestExtensionPathReadPermission[] =
+    "accessibility_features/read_permission/";
+// A test extension path. The extension has only |accessibilityFeatures.modify|
+// permission.
+const char kTestExtensionPathMofifyPermission[] =
+    "accessibility_features/modify_permission/";
+
+// Accessibility features API test.
+// Tests are parameterized by whether the test extension is write-only (the
+// parameter value is true) or read-only (the parameter value is false).
+class AccessibilityFeaturesApiTest : public ExtensionApiTest,
+                                     public testing::WithParamInterface<bool> {
+ public:
+  AccessibilityFeaturesApiTest() {}
+  virtual ~AccessibilityFeaturesApiTest() {}
+
+ protected:
+  // Returns pref service to be used to initialize and later verify
+  // accessibility preference values.
+  PrefService* GetPrefs() { return browser()->profile()->GetPrefs(); }
+
+  // Returns the path of the extension that should be used in a parameterized
+  // test.
+  std::string GetTestExtensionPath() const {
+    if (GetParam())
+      return kTestExtensionPathMofifyPermission;
+    return kTestExtensionPathReadPermission;
+  }
+
+  // Whether a parameterized test should have been able to modify accessibility
+  // preferences (i.e. whether the test extension had modify permission).
+  bool ShouldModifyingFeatureSucceed() const { return GetParam(); }
+
+  // Returns preference path for accessibility features as defined by the API.
+  const char* const GetPrefForFeature(const std::string& feature) {
+    if (feature == "spokenFeedback")
+      return prefs::kSpokenFeedbackEnabled;
+    if (feature == "largeCursor")
+      return prefs::kLargeCursorEnabled;
+    if (feature == "stickyKeys")
+      return prefs::kStickyKeysEnabled;
+    if (feature == "highContrast")
+      return prefs::kHighContrastEnabled;
+    if (feature == "screenMagnifier")
+      return prefs::kScreenMagnifierEnabled;
+    if (feature == "autoclick")
+      return prefs::kAutoclickEnabled;
+    if (feature == "virtualKeyboard")
+      return prefs::kVirtualKeyboardEnabled;
+    return NULL;
+  }
+
+  // Initializes preferences before running the test extension.
+  // |prefs| Pref service which should be initializzed.
+  // |enabled_features| List of boolean preference whose value should be set to
+  //     true.
+  // |disabled_features| List of boolean preferences whose value should be set
+  //     to false.
+  bool InitPrefServiceForTest(
+      PrefService* prefs,
+      const std::vector<std::string>& enabled_features,
+      const std::vector<std::string>& disabled_features) {
+    for (size_t i = 0; i < enabled_features.size(); ++i) {
+      const char* const pref_name = GetPrefForFeature(enabled_features[i]);
+      EXPECT_TRUE(pref_name) << "Invalid feature " << enabled_features[i];
+      if (!pref_name)
+        return false;
+      prefs->SetBoolean(pref_name, true);
+    }
+
+    for (size_t i = 0; i < disabled_features.size(); ++i) {
+      const char* const pref_name = GetPrefForFeature(disabled_features[i]);
+      EXPECT_TRUE(pref_name) << "Invalid feature " << disabled_features[i];
+      if (!pref_name)
+        return false;
+      prefs->SetBoolean(pref_name, false);
+    }
+    return true;
+  }
+
+  // Verifies that preferences have the expected value.
+  // |prefs| The pref service to be verified.
+  // |enabled_features| The list of boolean preferences whose value should be
+  //     true.
+  // |disabled_features| The list of boolean preferences whose value should be
+  //     false.
+  void VerifyPrefServiceState(
+      PrefService* prefs,
+      const std::vector<std::string>& enabled_features,
+      const std::vector<std::string>& disabled_features) {
+    for (size_t i = 0; i < enabled_features.size(); ++i) {
+      const char* const pref_name = GetPrefForFeature(enabled_features[i]);
+      ASSERT_TRUE(pref_name) << "Invalid feature " << enabled_features[i];
+      ASSERT_TRUE(prefs->GetBoolean(pref_name));
+    }
+
+    for (size_t i = 0; i < disabled_features.size(); ++i) {
+      const char* const pref_name = GetPrefForFeature(disabled_features[i]);
+      ASSERT_TRUE(pref_name) << "Invalid feature " << disabled_features[i];
+      ASSERT_FALSE(prefs->GetBoolean(pref_name));
+    }
+  }
+
+  // Given the test name and list of enabled and disabled features, generates
+  // and sets the JSON string that should be given to the test extension as
+  // test configuration.
+  // The result is saved to |result|. The return value is whether the test
+  // argument was successfully generated.
+  bool GenerateTestArg(const std::string& test_name,
+                       const std::vector<std::string>& enabled_features,
+                       const std::vector<std::string>& disabled_features,
+                       std::string* result) {
+    base::DictionaryValue test_arg;
+    test_arg.SetString(kTestNameKey, test_name);
+
+    scoped_ptr<base::ListValue> enabled_list(new base::ListValue);
+    for (size_t i = 0; i < enabled_features.size(); ++i)
+      enabled_list->AppendString(enabled_features[i]);
+    test_arg.Set(kEnabledFeaturesKey, enabled_list.release());
+
+    scoped_ptr<base::ListValue> disabled_list(new base::ListValue);
+    for (size_t i = 0; i < disabled_features.size(); ++i)
+      disabled_list->AppendString(disabled_features[i]);
+    test_arg.Set(kDisabledFeaturesKey, disabled_list.release());
+
+    return base::JSONWriter::Write(&test_arg, result);
+  }
+};
+
+INSTANTIATE_TEST_CASE_P(AccessibilityFeatureaApiTestInstantiatePermission,
+                        AccessibilityFeaturesApiTest,
+                        testing::Bool());
+
+// Tests that an extension with read permission can read accessibility features
+// state, while an extension that doesn't have the permission cannot.
+IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Get) {
+  std::vector<std::string> enabled_features;
+  enabled_features.push_back("largeCursor");
+  enabled_features.push_back("stickyKeys");
+  enabled_features.push_back("highContrast");
+
+  std::vector<std::string> disabled_features;
+  disabled_features.push_back("spokenFeedback");
+  disabled_features.push_back("screenMagnifier");
+  disabled_features.push_back("autoclick");
+  disabled_features.push_back("virtualKeyboard");
+
+  ASSERT_TRUE(
+      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
+
+  std::string test_arg;
+  ASSERT_TRUE(GenerateTestArg(
+      "getterTest", enabled_features, disabled_features, &test_arg));
+  EXPECT_TRUE(
+      RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg.c_str()));
+}
+
+// Tests that an extension with modify permission can modify accessibility
+// features, while an extension that doesn't have the permission can't.
+IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Set) {
+  std::vector<std::string> enabled_features;
+  enabled_features.push_back("spokenFeedback");
+  enabled_features.push_back("stickyKeys");
+  enabled_features.push_back("autoclick");
+  enabled_features.push_back("virtualKeyboard");
+
+  std::vector<std::string> disabled_features;
+  disabled_features.push_back("largeCursor");
+  disabled_features.push_back("highContrast");
+  disabled_features.push_back("screenMagnifier");
+
+  ASSERT_TRUE(
+      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
+
+  std::string test_arg;
+  ASSERT_TRUE(GenerateTestArg(
+      "setterTest", enabled_features, disabled_features, &test_arg));
+
+  // The test extension attempts to flip all feature values.
+  ASSERT_TRUE(
+      RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg.c_str()));
+
+  // The test tries to flip the feature states.
+  if (ShouldModifyingFeatureSucceed()) {
+    VerifyPrefServiceState(GetPrefs(), disabled_features, enabled_features);
+  } else {
+    VerifyPrefServiceState(GetPrefs(), enabled_features, disabled_features);
+  }
+}
+
+// Tests that an extension with read permission is notified when accessibility
+// features change.
+IN_PROC_BROWSER_TEST_F(AccessibilityFeaturesApiTest, ObserveFeatures) {
+  std::vector<std::string> enabled_features;
+  enabled_features.push_back("largeCursor");
+  enabled_features.push_back("stickyKeys");
+  enabled_features.push_back("highContrast");
+
+  std::vector<std::string> disabled_features;
+  disabled_features.push_back("screenMagnifier");
+
+  ASSERT_TRUE(
+      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
+
+  std::string test_arg;
+  ASSERT_TRUE(GenerateTestArg(
+      "observerTest", enabled_features, disabled_features, &test_arg));
+
+  // The test extension is supposed to report result twice when runnign this
+  // test. First time when in initializes it's feature listeners, and second
+  // time, when gets all expected events. This is done so the extension is
+  // running when the accessibility features are flipped; oterwise, the
+  // extension may not see events.
+  ASSERT_TRUE(RunPlatformAppTestWithArg(kTestExtensionPathReadPermission,
+                                        test_arg.c_str()));
+
+  // This should flip all features.
+  ASSERT_TRUE(
+      InitPrefServiceForTest(GetPrefs(), disabled_features, enabled_features));
+
+  // Catch the second result notification sent by the test extension.
+  ResultCatcher result_catcher;
+  ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message();
+}
+
+}  // namespace
+
+}  // namespace extensions
diff --git a/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc b/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
index d997ed1..58c7352 100644
--- a/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
+++ b/chrome/browser/chromeos/extensions/device_local_account_external_policy_loader_unittest.cc
@@ -70,8 +70,9 @@
                     extensions::Manifest::Location,
                     int,
                     bool));
-  MOCK_METHOD5(OnExternalExtensionUpdateUrlFound,
+  MOCK_METHOD6(OnExternalExtensionUpdateUrlFound,
                bool(const std::string&,
+                    const std::string&,
                     const GURL&,
                     extensions::Manifest::Location,
                     int,
@@ -156,7 +157,7 @@
   Mock::VerifyAndClearExpectations(&visitor_);
   EXPECT_CALL(visitor_, OnExternalExtensionFileFound(_, _, _, _, _, _))
       .Times(0);
-  EXPECT_CALL(visitor_, OnExternalExtensionUpdateUrlFound(_, _, _, _, _))
+  EXPECT_CALL(visitor_, OnExternalExtensionUpdateUrlFound(_, _, _, _, _, _))
       .Times(0);
   EXPECT_CALL(visitor_, OnExternalProviderReady(_))
       .Times(0);
diff --git a/chrome/browser/chromeos/extensions/file_manager/event_router.cc b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
index 214d6d2..7ea4d09 100644
--- a/chrome/browser/chromeos/extensions/file_manager/event_router.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/event_router.cc
@@ -25,7 +25,6 @@
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/screen_locker.h"
 #include "chrome/browser/drive/drive_service_interface.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
index 0f683d1..5e6eb5d 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.cc
@@ -45,11 +45,13 @@
 const char kDriveConnectionReasonNoNetwork[] = "no_network";
 const char kDriveConnectionReasonNoService[] = "no_service";
 
-// Copies properties from |entry_proto| to |properties|.
+// Copies properties from |entry_proto| to |properties|. |shared_with_me| is
+// given from the running profile.
 void FillDriveEntryPropertiesValue(
     const drive::ResourceEntry& entry_proto,
+    bool shared_with_me,
     api::file_browser_private::DriveEntryProperties* properties) {
-  properties->shared_with_me.reset(new bool(entry_proto.shared_with_me()));
+  properties->shared_with_me.reset(new bool(shared_with_me));
   properties->shared.reset(new bool(entry_proto.shared()));
 
   if (!entry_proto.has_file_specific_info())
@@ -145,8 +147,9 @@
 
   file_system->GetResourceEntry(
       file_path_,
-      base::Bind(&FileBrowserPrivateGetDriveEntryPropertiesFunction::
-                     OnGetFileInfo, this));
+      base::Bind(
+          &FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetFileInfo,
+          this));
   return true;
 }
 
@@ -157,16 +160,73 @@
     CompleteGetFileProperties(error);
     return;
   }
-
   DCHECK(entry);
+  owner_resource_entry_.swap(entry);
 
-  if (!g_browser_process->profile_manager()->IsValidProfile(
-          file_owner_profile_)) {
-    CompleteGetFileProperties(error);
+  if (GetProfile()->IsSameProfile(file_owner_profile_)) {
+    StartParseFileInfo(owner_resource_entry_->shared_with_me());
     return;
   }
 
-  FillDriveEntryPropertiesValue(*entry, properties_.get());
+  // If the running profile does not own the file, obtain the shared_with_me
+  // flag from the running profile's value.
+  drive::FileSystemInterface* const file_system =
+      drive::util::GetFileSystemByProfile(GetProfile());
+  if (!file_system) {
+    CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
+    return;
+  }
+  file_system->GetPathFromResourceId(
+      owner_resource_entry_->resource_id(),
+      base::Bind(
+          &FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetRunningPath,
+          this));
+}
+
+void FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetRunningPath(
+    drive::FileError error,
+    const base::FilePath& file_path) {
+  if (error != drive::FILE_ERROR_OK) {
+    // The running profile does not know the file.
+    StartParseFileInfo(false);
+    return;
+  }
+
+  drive::FileSystemInterface* const file_system =
+      drive::util::GetFileSystemByProfile(GetProfile());
+  if (!file_system) {
+    // The drive is disable for the running profile.
+    StartParseFileInfo(false);
+    return;
+  }
+  file_system->GetResourceEntry(
+      file_path,
+      base::Bind(
+          &FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetShareInfo,
+          this));
+}
+
+void FileBrowserPrivateGetDriveEntryPropertiesFunction::OnGetShareInfo(
+    drive::FileError error,
+    scoped_ptr<drive::ResourceEntry> entry) {
+  if (error != drive::FILE_ERROR_OK) {
+    CompleteGetFileProperties(error);
+    return;
+  }
+  DCHECK(entry);
+  StartParseFileInfo(entry->shared_with_me());
+}
+
+void FileBrowserPrivateGetDriveEntryPropertiesFunction::StartParseFileInfo(
+    bool shared_with_me) {
+  if (!g_browser_process->profile_manager()->IsValidProfile(
+          file_owner_profile_)) {
+    CompleteGetFileProperties(drive::FILE_ERROR_FAILED);
+    return;
+  }
+
+  FillDriveEntryPropertiesValue(
+      *owner_resource_entry_, shared_with_me, properties_.get());
 
   drive::FileSystemInterface* const file_system =
       drive::util::GetFileSystemByProfile(file_owner_profile_);
@@ -180,16 +240,13 @@
 
   // The properties meaningful for directories are already filled in
   // FillDriveEntryPropertiesValue().
-  if (entry.get() && !entry->has_file_specific_info()) {
-    CompleteGetFileProperties(error);
+  if (owner_resource_entry_->has_file_specific_info()) {
+    CompleteGetFileProperties(drive::FILE_ERROR_OK);
     return;
   }
 
-  // TODO(hirono): Update share_with_me property if the file and its properties
-  // come from non-running profile.
-
   const drive::FileSpecificInfo& file_specific_info =
-      entry->file_specific_info();
+      owner_resource_entry_->file_specific_info();
 
   // Get drive WebApps that can accept this file. We just need to extract the
   // doc icon for the drive app, which is set as default.
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
index 970444e..20c33ba 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_drive.h
@@ -47,6 +47,14 @@
   void OnGetFileInfo(drive::FileError error,
                      scoped_ptr<drive::ResourceEntry> entry);
 
+  void OnGetRunningPath(drive::FileError error,
+                        const base::FilePath& file_path);
+
+  void OnGetShareInfo(drive::FileError error,
+                      scoped_ptr<drive::ResourceEntry> entry);
+
+  void StartParseFileInfo(bool shared_with_me);
+
   void CacheStateReceived(bool success,
                           const drive::FileCacheEntry& cache_entry);
 
@@ -56,6 +64,7 @@
   Profile* file_owner_profile_;
   const scoped_ptr<extensions::api::file_browser_private::DriveEntryProperties>
       properties_;
+  scoped_ptr<drive::ResourceEntry> owner_resource_entry_;
 };
 
 // Implements the chrome.fileBrowserPrivate.pinDriveFile method.
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
index b3bca91..2bbbef2 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -6,6 +6,7 @@
 
 #include "apps/app_window.h"
 #include "apps/app_window_registry.h"
+#include "ash/frame/frame_util.h"
 #include "base/files/file_path.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
@@ -20,7 +21,6 @@
 #include "chrome/browser/drive/event_logger.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_info_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
@@ -30,7 +30,7 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
 #include "chrome/common/extensions/api/file_browser_private.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/page_zoom.h"
@@ -56,7 +56,7 @@
 }
 
 std::vector<linked_ptr<api::file_browser_private::ProfileInfo> >
-GetLoggedInProfileInfoList() {
+GetLoggedInProfileInfoList(content::WebContents* contents) {
   DCHECK(chromeos::UserManager::IsInitialized());
   const std::vector<Profile*>& profiles =
       g_browser_process->profile_manager()->GetLoadedProfiles();
@@ -84,13 +84,14 @@
     profile_info->is_current_profile = true;
 
     // Make an icon URL of the profile.
-    const int kImageSize = 30;
-    const gfx::Image& image = profiles::GetAvatarIconForTitleBar(
-        gfx::Image(user->image()), true, kImageSize, kImageSize);
-    const SkBitmap* const bitmap = image.ToSkBitmap();
-    if (bitmap) {
-      profile_info->image_uri.reset(new std::string(
-          webui::GetBitmapDataUrl(*bitmap)));
+    if (contents) {
+      const gfx::Image& image =
+          ash::GetAvatarImageForContext(contents->GetBrowserContext());
+      const SkBitmap* const bitmap = image.ToSkBitmap();
+      if (bitmap) {
+        profile_info->image_uri.reset(
+            new std::string(webui::GetBitmapDataUrl(*bitmap)));
+      }
     }
     result_profiles.push_back(profile_info);
   }
@@ -369,7 +370,7 @@
 
 bool FileBrowserPrivateGetProfilesFunction::RunImpl() {
   const std::vector<linked_ptr<api::file_browser_private::ProfileInfo> >&
-      profiles = GetLoggedInProfileInfoList();
+      profiles = GetLoggedInProfileInfoList(GetAssociatedWebContents());
 
   // Obtains the display profile ID.
   apps::AppWindow* const app_window = GetCurrentAppWindow(this);
@@ -393,7 +394,7 @@
   using api::file_browser_private::VisitDesktop::Params;
   const scoped_ptr<Params> params(Params::Create(*args_));
   const std::vector<linked_ptr<api::file_browser_private::ProfileInfo> >&
-      profiles = GetLoggedInProfileInfoList();
+      profiles = GetLoggedInProfileInfoList(GetAssociatedWebContents());
 
   // Check the multi-profile support.
   if (!profiles::IsMultipleProfilesEnabled()) {
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
index fd6758f..15c5368 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_util.cc
@@ -159,6 +159,9 @@
       volume_metadata->volume_type =
           file_browser_private::VOLUME_TYPE_CLOUD_DEVICE;
       break;
+    case VOLUME_TYPE_PROVIDED:
+      volume_metadata->volume_type = file_browser_private::VOLUME_TYPE_PROVIDED;
+      break;
     case VOLUME_TYPE_TESTING:
       volume_metadata->volume_type =
           file_browser_private::VOLUME_TYPE_TESTING;
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/OWNERS b/chrome/browser/chromeos/extensions/file_system_provider/OWNERS
index 159f992..e0abbce 100644
--- a/chrome/browser/chromeos/extensions/file_system_provider/OWNERS
+++ b/chrome/browser/chromeos/extensions/file_system_provider/OWNERS
@@ -1 +1,2 @@
+mtomasz@chromium.org
 satorux@chromium.org
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc
index 0d9fc0d..e891b1c 100644
--- a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc
+++ b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.cc
@@ -4,10 +4,10 @@
 
 #include "chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_api.h"
 
+#include "chrome/browser/chromeos/file_system_provider/service.h"
 #include "chrome/common/extensions/api/file_system_provider.h"
 
 namespace extensions {
-
 namespace {
 
 // Error names from
@@ -15,7 +15,9 @@
 const char kSecurityErrorName[] = "SecurityError";
 
 // Error messages.
-const char kEmptyNameErrorMessage[] = "Empty display name is not allowed";
+const char kEmptyNameErrorMessage[] = "Empty display name is not allowed.";
+const char kRegisteringFailedErrorMessage[] =
+    "Registering the file system failed.";
 
 // Creates a dictionary, which looks like a DOMError. The returned dictionary
 // will be converted to a real DOMError object in
@@ -37,22 +39,35 @@
 
   // It's an error if the display name is empty.
   if (params->display_name.empty()) {
-    const std::string file_system_id = "";
-
     base::ListValue* result = new base::ListValue();
-    result->Append(new base::StringValue(file_system_id));
+    result->Append(new base::StringValue(""));
     result->Append(CreateError(kSecurityErrorName,
                                kEmptyNameErrorMessage));
     SetResult(result);
-    SendResponse(true);
-    return true;
+    return false;
   }
 
-  // TODO(satorux): Implement the real logic.
-  const std::string file_system_id = params->display_name;
+  chromeos::file_system_provider::Service* service =
+      chromeos::file_system_provider::Service::Get(GetProfile());
+  DCHECK(service);
+
+  int file_system_id =
+      service->RegisterFileSystem(extension_id(), params->display_name);
+
+  // If the |file_system_id| is zero, then it means that registering the file
+  // system failed.
+  // TODO(mtomasz): Pass more detailed errors, rather than just a bool.
+  if (!file_system_id) {
+    base::ListValue* result = new base::ListValue();
+    result->Append(new base::FundamentalValue(0));
+    result->Append(
+        CreateError(kSecurityErrorName, kRegisteringFailedErrorMessage));
+    SetResult(result);
+    return false;
+  }
 
   base::ListValue* result = new base::ListValue();
-  result->Append(new base::StringValue(file_system_id));
+  result->Append(new base::FundamentalValue(file_system_id));
   // Don't append an error on success.
 
   SetResult(result);
diff --git a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc
index 8c94114..78eeb35 100644
--- a/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc
+++ b/chrome/browser/chromeos/extensions/file_system_provider/file_system_provider_apitest.cc
@@ -18,7 +18,8 @@
 };
 
 IN_PROC_BROWSER_TEST_F(FileSystemProviderApiTest, Mount) {
-  ASSERT_TRUE(RunPlatformAppTest("file_system_provider/mount"))
+  ASSERT_TRUE(RunPlatformAppTestWithFlags("file_system_provider/mount",
+                                          kFlagLoadAsComponent))
       << message_;
 }
 
diff --git a/chrome/browser/chromeos/extensions/first_run_private_api.cc b/chrome/browser/chromeos/extensions/first_run_private_api.cc
index b533ec1..edbda74 100644
--- a/chrome/browser/chromeos/extensions/first_run_private_api.cc
+++ b/chrome/browser/chromeos/extensions/first_run_private_api.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/chromeos/first_run/first_run.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
@@ -28,12 +29,16 @@
         "greetingHeader",
         l10n_util::GetStringUTF16(IDS_FIRST_RUN_GREETING_STEP_HEADER_GENERAL));
   }
+  base::string16 product_name =
+      l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
   localized_strings->SetString(
       "greetingText1",
-      l10n_util::GetStringUTF16(IDS_FIRST_RUN_GREETING_STEP_TEXT_1));
+      l10n_util::GetStringFUTF16(IDS_FIRST_RUN_GREETING_STEP_TEXT_1,
+                                 product_name));
   localized_strings->SetString(
       "greetingText2",
-      l10n_util::GetStringUTF16(IDS_FIRST_RUN_GREETING_STEP_TEXT_2));
+      l10n_util::GetStringFUTF16(IDS_FIRST_RUN_GREETING_STEP_TEXT_2,
+                                 product_name));
   localized_strings->SetString(
       "greetingButton",
       l10n_util::GetStringUTF16(IDS_FIRST_RUN_GREETING_STEP_BUTTON));
diff --git a/chrome/browser/chromeos/extensions/input_method_api.cc b/chrome/browser/chromeos/extensions/input_method_api.cc
index dbe2834..bb46b31 100644
--- a/chrome/browser/chromeos/extensions/input_method_api.cc
+++ b/chrome/browser/chromeos/extensions/input_method_api.cc
@@ -8,7 +8,6 @@
 #include "base/values.h"
 #include "chrome/browser/chromeos/extensions/input_method_event_router.h"
 #include "chrome/browser/extensions/api/input_ime/input_ime_api.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chromeos/ime/extension_ime_util.h"
 #include "chromeos/ime/input_method_manager.h"
 #include "extensions/browser/extension_function_registry.h"
@@ -62,10 +61,14 @@
 #endif
 }
 
+// static
+const char InputMethodAPI::kOnInputMethodChanged[] =
+    "inputMethodPrivate.onChanged";
+
 InputMethodAPI::InputMethodAPI(content::BrowserContext* context)
     : context_(context) {
-  ExtensionSystem::Get(context_)->event_router()->
-      RegisterObserver(this, event_names::kOnInputMethodChanged);
+  ExtensionSystem::Get(context_)->event_router()->RegisterObserver(
+      this, kOnInputMethodChanged);
   ExtensionFunctionRegistry* registry =
       ExtensionFunctionRegistry::GetInstance();
   registry->RegisterFunction<GetInputMethodFunction>();
diff --git a/chrome/browser/chromeos/extensions/input_method_api.h b/chrome/browser/chromeos/extensions/input_method_api.h
index 0245664..c940ebb 100644
--- a/chrome/browser/chromeos/extensions/input_method_api.h
+++ b/chrome/browser/chromeos/extensions/input_method_api.h
@@ -50,6 +50,8 @@
 class InputMethodAPI : public BrowserContextKeyedAPI,
                        public extensions::EventRouter::Observer {
  public:
+  static const char kOnInputMethodChanged[];
+
   explicit InputMethodAPI(content::BrowserContext* context);
   virtual ~InputMethodAPI();
 
diff --git a/chrome/browser/chromeos/extensions/input_method_event_router.cc b/chrome/browser/chromeos/extensions/input_method_event_router.cc
index 069d3ff..39ca79a 100644
--- a/chrome/browser/chromeos/extensions/input_method_event_router.cc
+++ b/chrome/browser/chromeos/extensions/input_method_event_router.cc
@@ -9,7 +9,6 @@
 #include "base/json/json_writer.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/extensions/input_method_api.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_system.h"
@@ -32,8 +31,10 @@
   extensions::EventRouter *router =
       extensions::ExtensionSystem::Get(context_)->event_router();
 
-  if (!router->HasEventListener(extensions::event_names::kOnInputMethodChanged))
+  if (!router->HasEventListener(
+          extensions::InputMethodAPI::kOnInputMethodChanged)) {
     return;
+  }
 
   scoped_ptr<base::ListValue> args(new base::ListValue());
   base::StringValue *input_method_name = new base::StringValue(
@@ -43,7 +44,7 @@
 
   // The router will only send the event to extensions that are listening.
   scoped_ptr<extensions::Event> event(new extensions::Event(
-      extensions::event_names::kOnInputMethodChanged, args.Pass()));
+      extensions::InputMethodAPI::kOnInputMethodChanged, args.Pass()));
   event->restrict_to_browser_context = context_;
   router->BroadcastEvent(event.Pass());
 }
diff --git a/chrome/browser/chromeos/extensions/virtual_keyboard_browsertest.cc b/chrome/browser/chromeos/extensions/virtual_keyboard_browsertest.cc
index 34ec260..aca1050 100644
--- a/chrome/browser/chromeos/extensions/virtual_keyboard_browsertest.cc
+++ b/chrome/browser/chromeos/extensions/virtual_keyboard_browsertest.cc
@@ -118,27 +118,35 @@
   std::string utf8_content_;
 };
 
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, AttributesTest) {
+// Broken due to Polymer version mismatch http://crbug.com/357946.
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, DISABLED_AttributesTest) {
   RunTest(base::FilePath(FILE_PATH_LITERAL("attributes_test.js")));
 }
 
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, TypingTest) {
+// Broken due to Polymer version mismatch http://crbug.com/357946.
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, DISABLED_TypingTest) {
   RunTest(base::FilePath(FILE_PATH_LITERAL("typing_test.js")));
 }
 
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, ControlKeysTest) {
+// Broken due to Polymer version mismatch http://crbug.com/357946.
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, DISABLED_ControlKeysTest) {
   RunTest(base::FilePath(FILE_PATH_LITERAL("control_keys_test.js")));
 }
 
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, HideKeyboardKeyTest) {
+// Broken due to Polymer version mismatch http://crbug.com/357946.
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest,
+                       DISABLED_HideKeyboardKeyTest) {
   RunTest(base::FilePath(FILE_PATH_LITERAL("hide_keyboard_key_test.js")));
 }
 
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, KeysetTransitionTest) {
+// Broken due to Polymer version mismatch http://crbug.com/357946.
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest,
+                       DISABLED_KeysetTransitionTest) {
   RunTest(base::FilePath(FILE_PATH_LITERAL("keyset_transition_test.js")));
 }
 
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, IsKeyboardLoaded) {
+// Broken due to Polymer version mismatch http://crbug.com/357946.
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, DISABLED_IsKeyboardLoaded) {
   content::RenderViewHost* keyboard_rvh = GetKeyboardRenderViewHost();
   ASSERT_TRUE(keyboard_rvh);
   bool loaded = false;
@@ -151,7 +159,8 @@
   ASSERT_TRUE(loaded);
 }
 
-IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, EndToEndTest) {
+// Broken due to Polymer version mismatch http://crbug.com/357946.
+IN_PROC_BROWSER_TEST_F(VirtualKeyboardBrowserTest, DISABLED_EndToEndTest) {
   // Get the virtual keyboard's render view host.
   content::RenderViewHost* keyboard_rvh = GetKeyboardRenderViewHost();
   ASSERT_TRUE(keyboard_rvh);
diff --git a/chrome/browser/chromeos/file_manager/app_id.h b/chrome/browser/chromeos/file_manager/app_id.h
index 6ea4012..9c59660 100644
--- a/chrome/browser/chromeos/file_manager/app_id.h
+++ b/chrome/browser/chromeos/file_manager/app_id.h
@@ -13,6 +13,9 @@
 // name like kAppId would be cryptic inside "file_manager" namespace.
 const char kFileManagerAppId[] = "hhaomjibdihmijegdhdafkllkbggdgoj";
 
+// The video player's app ID.
+const char kVideoPlayerAppId[] = "jcgeabjmjgoblfofpppfkcoakmfobdko";
+
 }  // namespace file_manager
 
 #endif  // CHROME_BROWSER_CHROMEOS_FILE_MANAGER_APP_ID_H_
diff --git a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
index a43b6b5..0fbd512 100644
--- a/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
+++ b/chrome/browser/chromeos/file_manager/external_filesystem_apitest.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
+#include "chrome/browser/chromeos/drive/test_util.h"
 #include "chrome/browser/chromeos/file_manager/drive_test_util.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
 #include "chrome/browser/drive/fake_drive_service.h"
@@ -400,6 +401,39 @@
         profile, NULL, fake_drive_service, std::string(), cache_dir, NULL);
   }
 
+  bool AddTestHostedDocuments() {
+    const char kResourceId[] = "document:unique-id-for-multiprofile-copy-test";
+    drive::FakeDriveService* const main_service =
+        static_cast<drive::FakeDriveService*>(
+            drive::util::GetDriveServiceByProfile(browser()->profile()));
+    drive::FakeDriveService* const sub_service =
+        static_cast<drive::FakeDriveService*>(
+            drive::util::GetDriveServiceByProfile(second_profile));
+
+    google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
+    scoped_ptr<google_apis::ResourceEntry> entry;
+
+    // Place a hosted document under root/test_dir of the sub profile.
+    sub_service->AddNewFileWithResourceId(
+        kResourceId,
+        "application/vnd.google-apps.document", "",
+        "folder:1_folder_resource_id", "hosted_doc", true,
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    drive::test_util::RunBlockingPoolTask();
+    if (error != google_apis::HTTP_CREATED)
+      return false;
+
+    // Place the hosted document with no parent in the main profile, for
+    // simulating the situation that the document is shared to the main profile.
+    error = google_apis::GDATA_OTHER_ERROR;
+    main_service->AddNewFileWithResourceId(
+        kResourceId,
+        "application/vnd.google-apps.document", "", "", "hosted_doc", true,
+        google_apis::test_util::CreateCopyResultCallback(&error, &entry));
+    drive::test_util::RunBlockingPoolTask();
+    return (error == google_apis::HTTP_CREATED);
+  }
+
   DriveIntegrationServiceFactory::FactoryCallback
       create_drive_integration_service_;
   scoped_ptr<DriveIntegrationServiceFactory::ScopedFactoryForTest>
@@ -513,6 +547,7 @@
 
 IN_PROC_BROWSER_TEST_F(MultiProfileDriveFileSystemExtensionApiTest,
                        CrossProfileCopy) {
+  ASSERT_TRUE(AddTestHostedDocuments());
   EXPECT_TRUE(RunFileSystemExtensionApiTest(
       "file_browser/multi_profile_copy",
       FILE_PATH_LITERAL("manifest.json"),
diff --git a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc
index aa1ef26..128e2bc 100644
--- a/chrome/browser/chromeos/file_manager/file_browser_handlers.cc
+++ b/chrome/browser/chromeos/file_manager/file_browser_handlers.cc
@@ -133,25 +133,6 @@
   return results;
 }
 
-// Finds a file browser handler that matches |extension_id| and |action_id|
-// from |handler_list|.  Returns a mutable iterator to the handler if
-// found. Returns handler_list->end() if not found.
-FileBrowserHandlerList::iterator
-FindFileBrowserHandlerForExtensionIdAndActionId(
-    FileBrowserHandlerList* handler_list,
-    const std::string& extension_id,
-    const std::string& action_id) {
-  DCHECK(handler_list);
-
-  FileBrowserHandlerList::iterator iter = handler_list->begin();
-  while (iter != handler_list->end() &&
-         !((*iter)->extension_id() == extension_id &&
-           (*iter)->id() == action_id)) {
-    ++iter;
-  }
-  return iter;
-}
-
 // This class is used to execute a file browser handler task. Here's how this
 // works:
 //
@@ -544,25 +525,6 @@
     }
   }
 
-  // "watch" and "gallery" are defined in the file manager's manifest.json.
-  FileBrowserHandlerList::iterator watch_iter =
-      FindFileBrowserHandlerForExtensionIdAndActionId(
-          &common_handlers, kFileManagerAppId, "watch");
-  FileBrowserHandlerList::iterator gallery_iter =
-      FindFileBrowserHandlerForExtensionIdAndActionId(
-          &common_handlers, kFileManagerAppId, "gallery");
-  if (watch_iter != common_handlers.end() &&
-      gallery_iter != common_handlers.end()) {
-    // Both "watch" and "gallery" actions are applicable which means that the
-    // selection is all videos. Showing them both is confusing, so we only keep
-    // the one that makes more sense ("watch" for single selection, "gallery"
-    // for multiple selection).
-    if (file_list.size() == 1)
-      common_handlers.erase(gallery_iter);
-    else
-      common_handlers.erase(watch_iter);
-  }
-
   return common_handlers;
 }
 
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
index 3006144..9d87340 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -727,13 +727,7 @@
 INSTANTIATE_TEST_CASE_P(
     OpenSpecialTypes,
     FileManagerBrowserTest,
-    ::testing::Values(TestParameter(IN_GUEST_MODE, "videoOpenDownloads"),
-                      TestParameter(NOT_IN_GUEST_MODE, "videoOpenDownloads"),
-                      TestParameter(NOT_IN_GUEST_MODE, "videoOpenDrive"),
-                      TestParameter(IN_GUEST_MODE, "audioOpenDownloads"),
-                      TestParameter(NOT_IN_GUEST_MODE, "audioOpenDownloads"),
-                      TestParameter(NOT_IN_GUEST_MODE, "audioOpenDrive"),
-                      TestParameter(IN_GUEST_MODE, "galleryOpenDownloads"),
+    ::testing::Values(TestParameter(IN_GUEST_MODE, "galleryOpenDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE, "galleryOpenDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE, "galleryOpenDrive"),
                       TestParameter(IN_GUEST_MODE, "zipOpenDownloads"),
@@ -742,6 +736,20 @@
 // DISABLED           TestParameter(NOT_IN_GUEST_MODE, "zipOpenDrive")));
 
 INSTANTIATE_TEST_CASE_P(
+    OpenVideoFiles,
+    FileManagerBrowserTest,
+    ::testing::Values(TestParameter(IN_GUEST_MODE, "videoOpenDownloads"),
+                      TestParameter(NOT_IN_GUEST_MODE, "videoOpenDownloads"),
+                      TestParameter(NOT_IN_GUEST_MODE, "videoOpenDrive")));
+
+INSTANTIATE_TEST_CASE_P(
+    OpenAudioFiles,
+    FileManagerBrowserTest,
+    ::testing::Values(TestParameter(IN_GUEST_MODE, "audioOpenDownloads"),
+                      TestParameter(NOT_IN_GUEST_MODE, "audioOpenDownloads"),
+                      TestParameter(NOT_IN_GUEST_MODE, "audioOpenDrive")));
+
+INSTANTIATE_TEST_CASE_P(
     KeyboardOperations,
     FileManagerBrowserTest,
     ::testing::Values(TestParameter(IN_GUEST_MODE, "keyboardDeleteDownloads"),
@@ -750,7 +758,13 @@
                       TestParameter(NOT_IN_GUEST_MODE, "keyboardDeleteDrive"),
                       TestParameter(IN_GUEST_MODE, "keyboardCopyDownloads"),
                       TestParameter(NOT_IN_GUEST_MODE, "keyboardCopyDownloads"),
-                      TestParameter(NOT_IN_GUEST_MODE, "keyboardCopyDrive")));
+                      TestParameter(NOT_IN_GUEST_MODE, "keyboardCopyDrive"),
+                      TestParameter(IN_GUEST_MODE,
+                                    "createNewFolderDownloads"),
+                      TestParameter(NOT_IN_GUEST_MODE,
+                                    "createNewFolderDownloads"),
+                      TestParameter(NOT_IN_GUEST_MODE,
+                                    "createNewFolderDrive")));
 
 INSTANTIATE_TEST_CASE_P(
     DriveSpecific,
diff --git a/chrome/browser/chromeos/file_manager/file_tasks.cc b/chrome/browser/chromeos/file_manager/file_tasks.cc
index 9572b95..720c401 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks.cc
@@ -107,6 +107,48 @@
   tasks->swap(filtered);
 }
 
+// Finds a task that matches |app_id| and |action_id| from |task_list|.
+// Returns a mutable iterator to the handler if found. Returns task_list->end()
+// if not found.
+std::vector<FullTaskDescriptor>::iterator
+FindTaskForAppIdAndActionId(
+    std::vector<FullTaskDescriptor>* task_list,
+    const std::string& app_id,
+    const std::string& action_id) {
+  DCHECK(task_list);
+
+  std::vector<FullTaskDescriptor>::iterator iter = task_list->begin();
+  while (iter != task_list->end() &&
+         !(iter->task_descriptor().app_id == app_id &&
+           iter->task_descriptor().action_id == action_id)) {
+    ++iter;
+  }
+  return iter;
+}
+
+// Chooses a suitable video handeler and removes other internal video hander.
+// Both "watch" and "gallery-video" actions are applicable which means that the
+// selection is all videos. Showing them both is confusing, so we only keep
+// the one that makes more sense ("watch" for single selection, "gallery"
+// for multiple selection).
+void ChooseSuitableVideoHandler(
+    const std::vector<GURL>& file_urls,
+    std::vector<FullTaskDescriptor>* task_list) {
+  std::vector<FullTaskDescriptor>::iterator video_player_iter =
+      FindTaskForAppIdAndActionId(task_list, kVideoPlayerAppId, "video");
+  std::vector<FullTaskDescriptor>::iterator gallery_video_iter =
+      FindTaskForAppIdAndActionId(
+          task_list, kFileManagerAppId, "gallery-video");
+
+  if (video_player_iter != task_list->end() &&
+      gallery_video_iter != task_list->end()) {
+    if (file_urls.size() == 1)
+      task_list->erase(gallery_video_iter);
+    else
+      task_list->erase(video_player_iter);
+  }
+}
+
 }  // namespace
 
 FullTaskDescriptor::FullTaskDescriptor(
@@ -467,6 +509,8 @@
   if (ContainsGoogleDocument(path_mime_set))
     KeepOnlyFileManagerInternalTasks(result_list);
 
+  ChooseSuitableVideoHandler(file_urls, result_list);
+
   ChooseAndSetDefaultTask(*profile->GetPrefs(), path_mime_set, result_list);
 }
 
diff --git a/chrome/browser/chromeos/file_manager/file_tasks.h b/chrome/browser/chromeos/file_manager/file_tasks.h
index 7ee47eb..1a8251f 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks.h
+++ b/chrome/browser/chromeos/file_manager/file_tasks.h
@@ -18,8 +18,8 @@
 // https://developer.chrome.com/extensions/fileBrowserHandler.html
 //
 // 2) Built-in handlers provided from Files.app. Files.app provides lots of
-// file_browser_handlers, such as "play", "watch", "mount-archive".  These
-// built-in handlers are often handled in special manners inside Files.app.
+// file_browser_handlers, such as "play", "mount-archive".  These built-in
+// handlers are often handled in special manners inside Files.app.
 // This information also comes from FileBrowserHandler::GetHandlers().
 //
 // See also:
@@ -99,9 +99,9 @@
 // chrome.fileBrowserPrivate.executeTasks() is used to open a file with a
 // handler (Chrome Extension/App or Drive App).
 //
-// Some built-in handlers such as "play" and "watch" are handled internally
-// in Files.app. "mount-archive" is handled very differently. The task
-// execution business should be simplified: crbug.com/267313
+// Some built-in handlers such as "play" are handled internally in Files.app.
+// "mount-archive" is handled very differently. The task execution business
+// should be simplified: crbug.com/267313
 //
 // See also:
 // chrome/browser/resources/file_manager/js/file_tasks.js
diff --git a/chrome/browser/chromeos/file_manager/open_util.cc b/chrome/browser/chromeos/file_manager/open_util.cc
index 14cebb3..45d107d 100644
--- a/chrome/browser/chromeos/file_manager/open_util.cc
+++ b/chrome/browser/chromeos/file_manager/open_util.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/chromeos/file_manager/file_tasks.h"
 #include "chrome/browser/chromeos/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/file_manager/mime_util.h"
+#include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/chromeos/file_manager/url_util.h"
 #include "chrome/browser/extensions/api/file_handlers/app_file_handler_util.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -207,11 +208,18 @@
 void OpenItem(Profile* profile, const base::FilePath& file_path) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
+  // The path may have been stored in preferences in old versions.
+  // We need migration here.
+  // TODO(kinaba): crbug.com/313539 remove it in the future.
+  base::FilePath path;
+  if (!util::MigratePathFromOldFormat(profile, file_path, &path))
+    path = file_path;
+
   GURL url;
   if (!ConvertAbsoluteFilePathToFileSystemUrl(
-          profile, file_path, kFileManagerAppId, &url) ||
+          profile, path, kFileManagerAppId, &url) ||
       !GrantFileSystemAccessToFileBrowser(profile)) {
-    ShowWarningMessageBox(profile, file_path);
+    ShowWarningMessageBox(profile, path);
     return;
   }
 
@@ -220,12 +228,19 @@
           profile, kFileManagerAppId);
 
   CheckIfDirectoryExists(file_system_context, url,
-                         base::Bind(&ContinueOpenItem, profile, file_path));
+                         base::Bind(&ContinueOpenItem, profile, path));
 }
 
 void ShowItemInFolder(Profile* profile, const base::FilePath& file_path) {
+  // The path may have been stored in preferences in old versions.
+  // We need migration here.
+  // TODO(kinaba): crbug.com/313539 remove it in the future.
+  base::FilePath path;
+  if (!util::MigratePathFromOldFormat(profile, file_path, &path))
+    path = file_path;
+
   // This action changes the selection so we do not reuse existing tabs.
-  OpenFileManagerWithInternalActionId(profile, file_path, "select");
+  OpenFileManagerWithInternalActionId(profile, path, "select");
 }
 
 }  // namespace util
diff --git a/chrome/browser/chromeos/file_manager/path_util.cc b/chrome/browser/chromeos/file_manager/path_util.cc
index 91ef187..7f5f35d 100644
--- a/chrome/browser/chromeos/file_manager/path_util.cc
+++ b/chrome/browser/chromeos/file_manager/path_util.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/chromeos/drive/file_system_util.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/download/download_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "net/base/escape.h"
@@ -25,8 +26,6 @@
     FILE_PATH_LITERAL("/home/chronos/user/Downloads");
 const base::FilePath::CharType kOldDriveFolderPath[] =
     FILE_PATH_LITERAL("/special/drive");
-const base::FilePath::CharType kNoHashDriveFolderPath[] =
-    FILE_PATH_LITERAL("/special/drive-");
 
 }  // namespace
 
@@ -60,19 +59,32 @@
 
   const base::FilePath downloads = GetDownloadsFolderForProfile(profile);
   const base::FilePath drive = drive::util::GetDriveMountPointPath(profile);
-  const base::FilePath bases[][2] = {
-    {base::FilePath(kOldDownloadsFolderPath),      downloads},
-    {DownloadPrefs::GetDefaultDownloadDirectory(), downloads},
-    {base::FilePath(kOldDriveFolderPath),          drive},
-    // TODO(kinaba): http://crbug.com/341284 Remove after M34 branching.
-    // For a short period we incorrectly set "/special/drive-" as the Drive path
-    // that needs to be fixed.
-    {base::FilePath(kNoHashDriveFolderPath),       drive},
-  };
 
-  for (size_t i = 0; i < arraysize(bases); ++i) {
-    const base::FilePath& old_base = bases[i][0];
-    const base::FilePath& new_base = bases[i][1];
+  std::vector<std::pair<base::FilePath, base::FilePath> > bases;
+  bases.push_back(std::make_pair(base::FilePath(kOldDownloadsFolderPath),
+                                 downloads));
+  bases.push_back(std::make_pair(DownloadPrefs::GetDefaultDownloadDirectory(),
+                                 downloads));
+  bases.push_back(std::make_pair(base::FilePath(kOldDriveFolderPath), drive));
+
+  // Trying migrating u-<hash>/Downloads to the current download path. This is
+  // no-op when multi-profile is enabled. This is necessary for (1) back
+  // migration when multi-profile flag is enabled and then disabled, or (2) in
+  // some edge cases (crbug.com/356322) that u-<hash> path is temporarily used.
+  if (chromeos::UserManager::IsInitialized()) {
+    const chromeos::User* const user =
+        chromeos::UserManager::Get()->GetUserByProfile(profile);
+    if (user) {
+      const base::FilePath hashed_downloads =
+          chromeos::ProfileHelper::GetProfilePathByUserIdHash(
+              user->username_hash()).AppendASCII(kDownloadsFolderName);
+      bases.push_back(std::make_pair(hashed_downloads, downloads));
+    }
+  }
+
+  for (size_t i = 0; i < bases.size(); ++i) {
+    const base::FilePath& old_base = bases[i].first;
+    const base::FilePath& new_base = bases[i].second;
     base::FilePath relative;
     if (old_path == old_base ||
         old_base.AppendRelativePath(old_path, &relative)) {
diff --git a/chrome/browser/chromeos/file_manager/path_util.h b/chrome/browser/chromeos/file_manager/path_util.h
index ac1b75b..3aee1b8 100644
--- a/chrome/browser/chromeos/file_manager/path_util.h
+++ b/chrome/browser/chromeos/file_manager/path_util.h
@@ -33,18 +33,20 @@
 //
 // M34: crbug.com/313539
 //   The "Downloads" folder is changed from /home/chronos/user/Downloads to
-//   /home/chronos/u-<hash>/Downloads to support multi profiles.
+//   /home/chronos/u-<hash>/Downloads when multi-profile is enabled.
 //
 //   The path "/home/chronos/user" is a hard link to the u-<hash> directory of
 //   the primary profile of the current session. The two paths always meant the
 //   same directory before multi-profiles. However, for secondary profiles in
 //   a multi-profile session, the "user" path cannot be used to mean "its own"
 //   Download folder anymore. Thus we are switching to always use "u-<hash>"
-//   that consistently works whether or not multi-profile is enabled.
+//   that consistently works whether or not it is primary.
 //
-// M34: crbug.com/336123
-//   The "Google Drive" folder is changed from /special/drive to
-//   /special/drive-<profile-id> to support multi profiles.
+// M35: crbug.com/356322
+//   It turned out even if multi-profile is disabled, u-<hash> style profile
+//   can be used in some situations. To address the cases, we add a migration
+//   from /home/chronos/u-<hash>/Downloads to current Download path.
+//   This just results in no-op when multi-profile is enabled.
 bool MigratePathFromOldFormat(Profile* profile,
                               const base::FilePath& old_path,
                               base::FilePath* new_path);
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc
index b980caf..0459c57 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager_factory.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager_observer.h"
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/local_discovery/storage/privet_filesystem_constants.h"
 #include "chrome/browser/profiles/profile.h"
@@ -103,6 +104,8 @@
       return "cloud_device";
     case VOLUME_TYPE_TESTING:
       return "testing";
+    case VOLUME_TYPE_PROVIDED:
+      return "provided";
   }
   NOTREACHED();
   return "";
@@ -199,6 +202,18 @@
   return volume_info;
 }
 
+VolumeInfo CreateProvidedFileSystemVolumeInfo(
+    const chromeos::file_system_provider::ProvidedFileSystem& file_system) {
+  VolumeInfo volume_info;
+  volume_info.type = VOLUME_TYPE_PROVIDED;
+  volume_info.mount_path = file_system.mount_path();
+  volume_info.mount_condition = chromeos::disks::MOUNT_CONDITION_NONE;
+  volume_info.is_parent = true;
+  volume_info.is_read_only = true;
+  volume_info.volume_id = GenerateVolumeId(volume_info);
+  return volume_info;
+}
+
 }  // namespace
 
 VolumeInfo::VolumeInfo() {
@@ -211,12 +226,14 @@
     Profile* profile,
     drive::DriveIntegrationService* drive_integration_service,
     chromeos::PowerManagerClient* power_manager_client,
-    chromeos::disks::DiskMountManager* disk_mount_manager)
+    chromeos::disks::DiskMountManager* disk_mount_manager,
+    chromeos::file_system_provider::Service* file_system_provider_service)
     : profile_(profile),
       drive_integration_service_(drive_integration_service),
       disk_mount_manager_(disk_mount_manager),
       mounted_disk_monitor_(
-          new MountedDiskMonitor(power_manager_client, disk_mount_manager)) {
+          new MountedDiskMonitor(power_manager_client, disk_mount_manager)),
+      file_system_provider_service_(file_system_provider_service) {
   DCHECK(disk_mount_manager);
 }
 
@@ -272,6 +289,21 @@
   // Subscribe to DiskMountManager.
   disk_mount_manager_->AddObserver(this);
 
+  // Subscribe to FileSystemProviderService and register currently mounted
+  // volumes for the profile.
+  if (file_system_provider_service_) {
+    using chromeos::file_system_provider::ProvidedFileSystem;
+    file_system_provider_service_->AddObserver(this);
+
+    std::vector<ProvidedFileSystem> provided_file_systems =
+        file_system_provider_service_->GetRegisteredFileSystems();
+    for (size_t i = 0; i < provided_file_systems.size(); ++i) {
+      VolumeInfo volume_info =
+          CreateProvidedFileSystemVolumeInfo(provided_file_systems[i]);
+      DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume_info, kNotRemounting);
+    }
+  }
+
   std::vector<VolumeInfo> archives;
 
   const chromeos::disks::DiskMountManager::MountPointMap& mount_points =
@@ -342,6 +374,9 @@
 
   if (drive_integration_service_)
     drive_integration_service_->RemoveObserver(this);
+
+  if (file_system_provider_service_)
+    file_system_provider_service_->RemoveObserver(this);
 }
 
 void VolumeManager::AddObserver(VolumeManagerObserver* observer) {
@@ -584,6 +619,18 @@
   NOTREACHED();
 }
 
+void VolumeManager::OnProvidedFileSystemRegistered(
+    const chromeos::file_system_provider::ProvidedFileSystem& file_system) {
+  VolumeInfo volume_info = CreateProvidedFileSystemVolumeInfo(file_system);
+  DoMountEvent(chromeos::MOUNT_ERROR_NONE, volume_info, false /* remounting */);
+}
+
+void VolumeManager::OnProvidedFileSystemUnregistered(
+    const chromeos::file_system_provider::ProvidedFileSystem& file_system) {
+  VolumeInfo volume_info = CreateProvidedFileSystemVolumeInfo(file_system);
+  DoUnmountEvent(chromeos::MOUNT_ERROR_NONE, volume_info);
+}
+
 void VolumeManager::OnExternalStorageDisabledChanged() {
   // If the policy just got disabled we have to unmount every device currently
   // mounted. The opposite is fine - we can let the user re-plug her device to
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.h b/chrome/browser/chromeos/file_manager/volume_manager.h
index 7311fcc..3471652 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.h
+++ b/chrome/browser/chromeos/file_manager/volume_manager.h
@@ -14,6 +14,8 @@
 #include "base/observer_list.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
+#include "chrome/browser/chromeos/file_system_provider/observer.h"
+#include "chrome/browser/chromeos/file_system_provider/service.h"
 #include "chrome/browser/local_discovery/storage/privet_volume_lister.h"
 #include "chromeos/dbus/cros_disks_client.h"
 #include "chromeos/disks/disk_mount_manager.h"
@@ -46,6 +48,7 @@
   VOLUME_TYPE_REMOVABLE_DISK_PARTITION,
   VOLUME_TYPE_MOUNTED_ARCHIVE_FILE,
   VOLUME_TYPE_CLOUD_DEVICE,
+  VOLUME_TYPE_PROVIDED,  // File system provided by the FileSystemProvider API.
   VOLUME_TYPE_TESTING
 };
 
@@ -100,12 +103,15 @@
 // - Mounted zip archives.
 class VolumeManager : public KeyedService,
                       public drive::DriveIntegrationServiceObserver,
-                      public chromeos::disks::DiskMountManager::Observer {
+                      public chromeos::disks::DiskMountManager::Observer,
+                      public chromeos::file_system_provider::Observer {
  public:
-  VolumeManager(Profile* profile,
-                drive::DriveIntegrationService* drive_integration_service,
-                chromeos::PowerManagerClient* power_manager_client,
-                chromeos::disks::DiskMountManager* disk_mount_manager);
+  VolumeManager(
+      Profile* profile,
+      drive::DriveIntegrationService* drive_integration_service,
+      chromeos::PowerManagerClient* power_manager_client,
+      chromeos::disks::DiskMountManager* disk_mount_manager,
+      chromeos::file_system_provider::Service* file_system_provider_service);
   virtual ~VolumeManager();
 
   // Returns the instance corresponding to the |context|.
@@ -162,6 +168,14 @@
       chromeos::FormatError error_code,
       const std::string& device_path) OVERRIDE;
 
+  // chromeos::file_system_provider::Observer overrides.
+  virtual void OnProvidedFileSystemRegistered(
+      const chromeos::file_system_provider::ProvidedFileSystem& file_system)
+      OVERRIDE;
+  virtual void OnProvidedFileSystemUnregistered(
+      const chromeos::file_system_provider::ProvidedFileSystem& file_system)
+      OVERRIDE;
+
   // Called on change to kExternalStorageDisabled pref.
   void OnExternalStorageDisabledChanged();
 
@@ -175,13 +189,14 @@
                       const VolumeInfo& volume_info);
 
   Profile* profile_;
-  drive::DriveIntegrationService* drive_integration_service_;
-  chromeos::disks::DiskMountManager* disk_mount_manager_;
+  drive::DriveIntegrationService* drive_integration_service_;  // Not owned.
+  chromeos::disks::DiskMountManager* disk_mount_manager_;      // Not owned.
   scoped_ptr<MountedDiskMonitor> mounted_disk_monitor_;
   PrefChangeRegistrar pref_change_registrar_;
   ObserverList<VolumeManagerObserver> observers_;
   scoped_ptr<local_discovery::PrivetVolumeLister> privet_volume_lister_;
-
+  chromeos::file_system_provider::Service*
+      file_system_provider_service_;  // Not owned by this class.
   std::map<std::string, VolumeInfo> mounted_volumes_;
 
   DISALLOW_COPY_AND_ASSIGN(VolumeManager);
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_factory.cc b/chrome/browser/chromeos/file_manager/volume_manager_factory.cc
index 6000848..6428f0f 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_factory.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_factory.cc
@@ -8,6 +8,7 @@
 #include "base/memory/singleton.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager.h"
+#include "chrome/browser/chromeos/file_system_provider/service_factory.h"
 #include "chrome/browser/profiles/incognito_helpers.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -43,10 +44,12 @@
     content::BrowserContext* profile) const {
   VolumeManager* instance = new VolumeManager(
       Profile::FromBrowserContext(profile),
-      drive::DriveIntegrationServiceFactory::
-          GetForProfileRegardlessOfStates(Profile::FromBrowserContext(profile)),
+      drive::DriveIntegrationServiceFactory::GetForProfileRegardlessOfStates(
+          Profile::FromBrowserContext(profile)),
       chromeos::DBusThreadManager::Get()->GetPowerManagerClient(),
-      chromeos::disks::DiskMountManager::GetInstance());
+      chromeos::disks::DiskMountManager::GetInstance(),
+      chromeos::file_system_provider::ServiceFactory::Get(
+          Profile::FromBrowserContext(profile)));
   instance->Initialize();
   return instance;
 }
@@ -56,6 +59,7 @@
           "VolumeManagerFactory",
           BrowserContextDependencyManager::GetInstance()) {
   DependsOn(drive::DriveIntegrationServiceFactory::GetInstance());
+  DependsOn(chromeos::file_system_provider::ServiceFactory::GetInstance());
 }
 
 VolumeManagerFactory::~VolumeManagerFactory() {
diff --git a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
index dd76c3a..d311301 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/chromeos/file_manager/fake_disk_mount_manager.h"
 #include "chrome/browser/chromeos/file_manager/volume_manager_observer.h"
+#include "chrome/browser/chromeos/file_system_provider/service.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
@@ -146,16 +147,22 @@
     power_manager_client_.reset(new chromeos::FakePowerManagerClient);
     disk_mount_manager_.reset(new FakeDiskMountManager);
     profile_.reset(new TestingProfile);
-    volume_manager_.reset(new VolumeManager(profile_.get(),
-                                            NULL,  // DriveIntegrationService
-                                            power_manager_client_.get(),
-                                            disk_mount_manager_.get()));
+    file_system_provider_service_.reset(
+        new chromeos::file_system_provider::Service(profile_.get()));
+    volume_manager_.reset(
+        new VolumeManager(profile_.get(),
+                          NULL,  // DriveIntegrationService
+                          power_manager_client_.get(),
+                          disk_mount_manager_.get(),
+                          file_system_provider_service_.get()));
   }
 
   content::TestBrowserThreadBundle thread_bundle_;
   scoped_ptr<chromeos::FakePowerManagerClient> power_manager_client_;
   scoped_ptr<FakeDiskMountManager> disk_mount_manager_;
   scoped_ptr<TestingProfile> profile_;
+  scoped_ptr<chromeos::file_system_provider::Service>
+      file_system_provider_service_;
   scoped_ptr<VolumeManager> volume_manager_;
 };
 
diff --git a/chrome/browser/chromeos/file_system_provider/OWNERS b/chrome/browser/chromeos/file_system_provider/OWNERS
new file mode 100644
index 0000000..e0abbce
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/OWNERS
@@ -0,0 +1,2 @@
+mtomasz@chromium.org
+satorux@chromium.org
diff --git a/chrome/browser/chromeos/file_system_provider/observer.h b/chrome/browser/chromeos/file_system_provider/observer.h
new file mode 100644
index 0000000..d2147e6
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/observer.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OBSERVER_H_
+#define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OBSERVER_H_
+
+#include <string>
+
+namespace chromeos {
+namespace file_system_provider {
+
+class ProvidedFileSystem;
+
+// Observes file_system_provider::Service for mounting and unmounting events.
+class Observer {
+ public:
+  // Called when a provided |file_system| is registered successfully.
+  virtual void OnProvidedFileSystemRegistered(
+      const ProvidedFileSystem& file_system) = 0;
+
+  // Called when a provided |file_system| is unregistered successfully.
+  virtual void OnProvidedFileSystemUnregistered(
+      const ProvidedFileSystem& file_system) = 0;
+};
+
+}  // namespace file_system_provider
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_OBSERVER_H_
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
new file mode 100644
index 0000000..8d669af
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
+
+namespace chromeos {
+namespace file_system_provider {
+
+ProvidedFileSystem::ProvidedFileSystem() {}
+
+ProvidedFileSystem::ProvidedFileSystem(const std::string& extension_id,
+                                       int file_system_id,
+                                       const std::string& file_system_name,
+                                       const base::FilePath& mount_path)
+    : extension_id_(extension_id),
+      file_system_id_(file_system_id),
+      file_system_name_(file_system_name),
+      mount_path_(mount_path) {}
+
+ProvidedFileSystem::~ProvidedFileSystem() {}
+
+}  // namespace file_system_provider
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system.h b/chrome/browser/chromeos/file_system_provider/provided_file_system.h
new file mode 100644
index 0000000..10aa0a9
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system.h
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_PROVIDED_FILE_SYSTEM_H_
+#define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_PROVIDED_FILE_SYSTEM_H_
+
+#include <string>
+
+#include "base/files/file_path.h"
+
+namespace chromeos {
+namespace file_system_provider {
+
+// Contains information about the provided file system instance.
+class ProvidedFileSystem {
+ public:
+  ProvidedFileSystem();
+  ProvidedFileSystem(const std::string& extension_id,
+                     int file_system_id,
+                     const std::string& file_system_name,
+                     const base::FilePath& mount_path);
+
+  ~ProvidedFileSystem();
+
+  const std::string& extension_id() const { return extension_id_; }
+  int file_system_id() const { return file_system_id_; }
+  const std::string& file_system_name() const { return file_system_name_; }
+  const base::FilePath& mount_path() const { return mount_path_; }
+
+ private:
+  // ID of the extension providing this file system.
+  std::string extension_id_;
+
+  // ID of the file system, used internally.
+  int file_system_id_;
+
+  // Name of the file system, can be rendered in the UI.
+  std::string file_system_name_;
+
+  // Mount path of the underlying file system.
+  base::FilePath mount_path_;
+};
+
+}  // namespace file_system_provider
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_PROVIDED_FILE_SYSTEM_H_
diff --git a/chrome/browser/chromeos/file_system_provider/service.cc b/chrome/browser/chromeos/file_system_provider/service.cc
new file mode 100644
index 0000000..fcb7d5a
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/service.cc
@@ -0,0 +1,152 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/file_system_provider/service.h"
+
+#include "base/files/file_path.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/chromeos/file_system_provider/observer.h"
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
+#include "chrome/browser/chromeos/file_system_provider/service_factory.h"
+#include "chrome/browser/chromeos/login/user.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "content/public/browser/browser_thread.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+
+namespace chromeos {
+namespace file_system_provider {
+namespace {
+
+// Root mount path for all of the provided file systems.
+const base::FilePath::CharType kProvidedMountPointRoot[] =
+    FILE_PATH_LITERAL("/provided");
+
+// Maximum number of file systems to be mounted in the same time, per profile.
+const size_t kMaxFileSystems = 16;
+
+// Constructs a safe mount point path for the provided file system represented
+// by |file_system_handle|. The handle is a numeric part of the file system id.
+base::FilePath GetMountPointPath(Profile* profile,
+                                 std::string extension_id,
+                                 int file_system_id) {
+  chromeos::User* const user =
+      chromeos::UserManager::IsInitialized()
+          ? chromeos::UserManager::Get()->GetUserByProfile(
+                profile->GetOriginalProfile())
+          : NULL;
+  const std::string user_suffix = user ? "-" + user->username_hash() : "";
+  return base::FilePath(kProvidedMountPointRoot).AppendASCII(
+      extension_id + "-" + base::IntToString(file_system_id) + user_suffix);
+}
+
+}  // namespace
+
+Service::Service(Profile* profile) : profile_(profile), next_id_(1) {}
+
+Service::~Service() {}
+
+// static
+Service* Service::Get(content::BrowserContext* context) {
+  return ServiceFactory::Get(context);
+}
+
+void Service::AddObserver(Observer* observer) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(observer);
+  observers_.AddObserver(observer);
+}
+
+void Service::RemoveObserver(Observer* observer) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(observer);
+  observers_.RemoveObserver(observer);
+}
+
+int Service::RegisterFileSystem(const std::string& extension_id,
+                                const std::string& file_system_name) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  // Restrict number of file systems to prevent system abusing.
+  if (file_systems_.size() + 1 > kMaxFileSystems)
+    return 0;
+
+  // The file system id is unique per service, so per profile.
+  int file_system_id = next_id_;
+
+  fileapi::ExternalMountPoints* const mount_points =
+      fileapi::ExternalMountPoints::GetSystemInstance();
+  DCHECK(mount_points);
+
+  // The mount point path and name are unique per system, since they are system
+  // wide. This is necessary for copying between profiles.
+  const base::FilePath& mount_point_path =
+      GetMountPointPath(profile_, extension_id, file_system_id);
+  const std::string mount_point_name =
+      mount_point_path.BaseName().AsUTF8Unsafe();
+
+  if (!mount_points->RegisterFileSystem(mount_point_name,
+                                        fileapi::kFileSystemTypeProvided,
+                                        fileapi::FileSystemMountOption(),
+                                        mount_point_path)) {
+    return 0;
+  }
+
+  // Store the file system descriptor. Use the mount point name as the file
+  // system provider file system id.
+  // Examples:
+  //   file_system_id = 41
+  //   mount_point_name = file_system_id = b33f1337-41-5aa5
+  //   mount_point_path = /provided/b33f1337-41-5aa5
+  ProvidedFileSystem file_system(
+      extension_id, file_system_id, file_system_name, mount_point_path);
+  file_systems_[file_system_id] = file_system;
+
+  FOR_EACH_OBSERVER(
+      Observer, observers_, OnProvidedFileSystemRegistered(file_system));
+
+  next_id_++;
+  return file_system_id;
+}
+
+bool Service::UnregisterFileSystem(const std::string& extension_id,
+                                   int file_system_id) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  FileSystemMap::iterator file_system_it = file_systems_.find(file_system_id);
+  if (file_system_it == file_systems_.end() ||
+      file_system_it->second.extension_id() != extension_id) {
+    return false;
+  }
+
+  fileapi::ExternalMountPoints* const mount_points =
+      fileapi::ExternalMountPoints::GetSystemInstance();
+  DCHECK(mount_points);
+
+  const std::string mount_point_name =
+      file_system_it->second.mount_path().BaseName().value();
+  if (!mount_points->RevokeFileSystem(mount_point_name))
+    return false;
+
+  FOR_EACH_OBSERVER(Observer,
+                    observers_,
+                    OnProvidedFileSystemUnregistered(file_system_it->second));
+
+  file_systems_.erase(file_system_it);
+  return true;
+}
+
+std::vector<ProvidedFileSystem> Service::GetRegisteredFileSystems() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  std::vector<ProvidedFileSystem> result;
+  for (FileSystemMap::const_iterator it = file_systems_.begin();
+       it != file_systems_.end();
+       ++it) {
+    result.push_back(it->second);
+  }
+  return result;
+}
+
+}  // namespace file_system_provider
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/file_system_provider/service.h b/chrome/browser/chromeos/file_system_provider/service.h
new file mode 100644
index 0000000..f3cb080
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/service.h
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_SERVICE_H_
+#define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_SERVICE_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/observer_list.h"
+#include "chrome/browser/chromeos/file_system_provider/observer.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/api/file_system_provider.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/browser_context.h"
+
+namespace chromeos {
+namespace file_system_provider {
+
+class ServiceFactory;
+
+// Manages and registers the fileSystemProvider service.
+class Service : public KeyedService {
+ public:
+  explicit Service(Profile* profile);
+  virtual ~Service();
+
+  // Registers a file system provided by an extension with the |extension_id|.
+  // For success, it returns a numeric file system id, which is an
+  // auto-incremented non-zero value. For failures, it returns zero.
+  int RegisterFileSystem(const std::string& extension_id,
+                         const std::string& file_system_name);
+
+  // Unregisters a file system with the specified |file_system_id| for the
+  // |extension_id|. For success returns true, otherwise false.
+  bool UnregisterFileSystem(const std::string& extension_id,
+                            int file_system_id);
+
+  // Returns a list of currently registered file systems. All items are copied.
+  std::vector<ProvidedFileSystem> GetRegisteredFileSystems();
+
+  // Adds and removes observers.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  // Gets the singleton instance for the |context|.
+  static Service* Get(content::BrowserContext* context);
+
+ private:
+  typedef std::map<int, ProvidedFileSystem> FileSystemMap;
+
+  Profile* profile_;
+  ObserverList<Observer> observers_;
+  FileSystemMap file_systems_;
+  int next_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(Service);
+};
+
+}  // namespace file_system_provider
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_SERVICE_H_
diff --git a/chrome/browser/chromeos/file_system_provider/service_factory.cc b/chrome/browser/chromeos/file_system_provider/service_factory.cc
new file mode 100644
index 0000000..6fc9e99
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/service_factory.cc
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/file_system_provider/service_factory.h"
+
+#include "chrome/browser/chromeos/file_system_provider/service.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace chromeos {
+namespace file_system_provider {
+
+// static
+Service* ServiceFactory::Get(content::BrowserContext* context) {
+  return static_cast<Service*>(
+      GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+ServiceFactory* ServiceFactory::GetInstance() {
+  return Singleton<ServiceFactory>::get();
+}
+
+ServiceFactory::ServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "Service",
+          BrowserContextDependencyManager::GetInstance()) {}
+
+ServiceFactory::~ServiceFactory() {}
+
+KeyedService* ServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* profile) const {
+  return new Service(static_cast<Profile*>(profile));
+}
+
+bool ServiceFactory::ServiceIsCreatedWithBrowserContext() const { return true; }
+
+}  // namespace file_system_provider
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/file_system_provider/service_factory.h b/chrome/browser/chromeos/file_system_provider/service_factory.h
new file mode 100644
index 0000000..2aad0dd
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/service_factory.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_SERVICE_FACTORY_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "content/public/browser/browser_context.h"
+
+namespace chromeos {
+namespace file_system_provider {
+
+class Service;
+
+// Creates services per profile.
+class ServiceFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  static Service* Get(content::BrowserContext* context);
+  static ServiceFactory* GetInstance();
+
+ private:
+  friend struct DefaultSingletonTraits<ServiceFactory>;
+
+  ServiceFactory();
+  virtual ~ServiceFactory();
+
+  // BrowserContextKeyedServiceFactory overrides:
+  virtual KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* profile) const OVERRIDE;
+  virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;
+
+  DISALLOW_COPY_AND_ASSIGN(ServiceFactory);
+};
+
+}  // namespace file_system_provider
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_FILE_SYSTEM_PROVIDER_SERVICE_FACTORY_H_
diff --git a/chrome/browser/chromeos/file_system_provider/service_unittest.cc b/chrome/browser/chromeos/file_system_provider/service_unittest.cc
new file mode 100644
index 0000000..0e848a5
--- /dev/null
+++ b/chrome/browser/chromeos/file_system_provider/service_unittest.cc
@@ -0,0 +1,193 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "chrome/browser/chromeos/file_system_provider/observer.h"
+#include "chrome/browser/chromeos/file_system_provider/provided_file_system.h"
+#include "chrome/browser/chromeos/file_system_provider/service.h"
+#include "chrome/browser/chromeos/login/fake_user_manager.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+
+namespace chromeos {
+namespace file_system_provider {
+namespace {
+
+const char kExtensionId[] = "mbflcebpggnecokmikipoihdbecnjfoj";
+const char kFileSystemName[] = "Camera Pictures";
+
+// Utility observer, logging events from file_system_provider::Service.
+class LoggingObserver : public Observer {
+ public:
+  LoggingObserver() {}
+  virtual ~LoggingObserver() {}
+
+  // file_system_provider::Observer overrides.
+  virtual void OnProvidedFileSystemRegistered(
+      const ProvidedFileSystem& file_system) OVERRIDE {
+    registered.push_back(new const ProvidedFileSystem(file_system));
+  }
+
+  virtual void OnProvidedFileSystemUnregistered(
+      const ProvidedFileSystem& file_system) OVERRIDE {
+    unregistered.push_back(new const ProvidedFileSystem(file_system));
+  }
+
+  ScopedVector<const ProvidedFileSystem> registered;
+  ScopedVector<const ProvidedFileSystem> unregistered;
+};
+
+}  // namespace
+
+class FileSystemProviderServiceTest : public testing::Test {
+ protected:
+  FileSystemProviderServiceTest() {}
+  virtual ~FileSystemProviderServiceTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    user_manager_ = new FakeUserManager();
+    user_manager_enabler_.reset(new ScopedUserManagerEnabler(user_manager_));
+    profile_.reset(new TestingProfile);
+    user_manager_->AddUser(profile_->GetProfileName());
+    file_system_provider_service_.reset(new Service(profile_.get()));
+  }
+
+  virtual void TearDown() {
+    fileapi::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems();
+  }
+
+  content::TestBrowserThreadBundle thread_bundle_;
+  scoped_ptr<TestingProfile> profile_;
+  scoped_ptr<ScopedUserManagerEnabler> user_manager_enabler_;
+  FakeUserManager* user_manager_;
+  scoped_ptr<Service> file_system_provider_service_;
+};
+
+TEST_F(FileSystemProviderServiceTest, RegisterFileSystem) {
+  LoggingObserver observer;
+  file_system_provider_service_->AddObserver(&observer);
+
+  int file_system_id = file_system_provider_service_->RegisterFileSystem(
+      kExtensionId, kFileSystemName);
+
+  EXPECT_LT(0, file_system_id);
+  ASSERT_EQ(1u, observer.registered.size());
+  EXPECT_EQ(kExtensionId, observer.registered[0]->extension_id());
+  EXPECT_EQ(1, observer.registered[0]->file_system_id());
+  EXPECT_EQ("/provided/mbflcebpggnecokmikipoihdbecnjfoj-1-testing_profile-hash",
+            observer.registered[0]->mount_path().AsUTF8Unsafe());
+  EXPECT_EQ(kFileSystemName, observer.registered[0]->file_system_name());
+  ASSERT_EQ(0u, observer.unregistered.size());
+
+  std::vector<ProvidedFileSystem> provided_file_systems =
+      file_system_provider_service_->GetRegisteredFileSystems();
+  ASSERT_EQ(1u, provided_file_systems.size());
+
+  file_system_provider_service_->RemoveObserver(&observer);
+}
+
+TEST_F(FileSystemProviderServiceTest, RegisterFileSystem_UniqueIds) {
+  LoggingObserver observer;
+  file_system_provider_service_->AddObserver(&observer);
+
+  int file_system_first_id = file_system_provider_service_->RegisterFileSystem(
+      kExtensionId, kFileSystemName);
+  ASSERT_LT(0, file_system_first_id);
+
+  int file_system_second_id = file_system_provider_service_->RegisterFileSystem(
+      kExtensionId, kFileSystemName);
+  ASSERT_LT(0, file_system_second_id);
+
+  ASSERT_NE(file_system_first_id, file_system_second_id);
+  ASSERT_EQ(2u, observer.registered.size());
+
+  std::vector<ProvidedFileSystem> provided_file_systems =
+      file_system_provider_service_->GetRegisteredFileSystems();
+  ASSERT_EQ(2u, provided_file_systems.size());
+
+  file_system_provider_service_->RemoveObserver(&observer);
+}
+
+TEST_F(FileSystemProviderServiceTest, RegisterFileSystem_StressTest) {
+  LoggingObserver observer;
+  file_system_provider_service_->AddObserver(&observer);
+
+  const size_t kMaxFileSystems = 16;
+  for (size_t i = 0; i < kMaxFileSystems; ++i) {
+    int file_system_id = file_system_provider_service_->RegisterFileSystem(
+        kExtensionId, kFileSystemName);
+    ASSERT_LT(0, file_system_id);
+  }
+  ASSERT_EQ(kMaxFileSystems, observer.registered.size());
+
+  // The next file system is out of limit, and registering it should fail.
+  int file_system_id = file_system_provider_service_->RegisterFileSystem(
+      kExtensionId, kFileSystemName);
+  ASSERT_EQ(0, file_system_id);
+  ASSERT_EQ(kMaxFileSystems, observer.registered.size());
+
+  std::vector<ProvidedFileSystem> provided_file_systems =
+      file_system_provider_service_->GetRegisteredFileSystems();
+  ASSERT_EQ(kMaxFileSystems, provided_file_systems.size());
+
+  file_system_provider_service_->RemoveObserver(&observer);
+}
+
+TEST_F(FileSystemProviderServiceTest, UnregisterFileSystem) {
+  LoggingObserver observer;
+  file_system_provider_service_->AddObserver(&observer);
+
+  int file_system_id = file_system_provider_service_->RegisterFileSystem(
+      kExtensionId, kFileSystemName);
+  ASSERT_LT(0, file_system_id);
+  ASSERT_EQ(1u, observer.registered.size());
+
+  const bool result = file_system_provider_service_->UnregisterFileSystem(
+      kExtensionId, file_system_id);
+  ASSERT_TRUE(result);
+  ASSERT_EQ(1u, observer.unregistered.size());
+
+  EXPECT_EQ(kExtensionId, observer.unregistered[0]->extension_id());
+  EXPECT_EQ(1, observer.unregistered[0]->file_system_id());
+  EXPECT_EQ("/provided/mbflcebpggnecokmikipoihdbecnjfoj-1-testing_profile-hash",
+            observer.unregistered[0]->mount_path().AsUTF8Unsafe());
+  EXPECT_EQ(kFileSystemName, observer.unregistered[0]->file_system_name());
+
+  std::vector<ProvidedFileSystem> provided_file_systems =
+      file_system_provider_service_->GetRegisteredFileSystems();
+  ASSERT_EQ(0u, provided_file_systems.size());
+
+  file_system_provider_service_->RemoveObserver(&observer);
+}
+
+TEST_F(FileSystemProviderServiceTest, UnregisterFileSystem_WrongExtensionId) {
+  LoggingObserver observer;
+  file_system_provider_service_->AddObserver(&observer);
+
+  const std::string kWrongExtensionId = "helloworldhelloworldhelloworldhe";
+
+  int file_system_id = file_system_provider_service_->RegisterFileSystem(
+      kExtensionId, kFileSystemName);
+  ASSERT_LT(0, file_system_id);
+  ASSERT_EQ(1u, observer.registered.size());
+
+  const bool result = file_system_provider_service_->UnregisterFileSystem(
+      kWrongExtensionId, file_system_id);
+  ASSERT_FALSE(result);
+  ASSERT_EQ(0u, observer.unregistered.size());
+
+  std::vector<ProvidedFileSystem> provided_file_systems =
+      file_system_provider_service_->GetRegisteredFileSystems();
+  ASSERT_EQ(1u, provided_file_systems.size());
+
+  file_system_provider_service_->RemoveObserver(&observer);
+}
+
+}  // namespace file_system_provider
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/first_run/first_run_controller.cc b/chrome/browser/chromeos/first_run/first_run_controller.cc
index bda1117..f2f6b88 100644
--- a/chrome/browser/chromeos/first_run/first_run_controller.cc
+++ b/chrome/browser/chromeos/first_run/first_run_controller.cc
@@ -28,7 +28,7 @@
 void RecordCompletion(chromeos::first_run::TutorialCompletion type) {
   UMA_HISTOGRAM_ENUMERATION("CrosFirstRun.TutorialCompletion",
                             type,
-                            chromeos::first_run::kTutorialCompletionSize);
+                            chromeos::first_run::TUTORIAL_COMPLETION_SIZE);
 }
 
 }  // namespace
@@ -120,7 +120,7 @@
 }
 
 void FirstRunController::OnHelpButtonClicked() {
-  RecordCompletion(first_run::kTutorialCompletedWithKeepExploring);
+  RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_KEEP_EXPLORING);
   on_actor_finalized_ = base::Bind(chrome::ShowHelpForProfile,
                                    user_profile_,
                                    chrome::HOST_DESKTOP_TYPE_ASH,
@@ -153,7 +153,7 @@
 }
 
 void FirstRunController::OnCancelled() {
-  RecordCompletion(first_run::kTutorialNotFinished);
+  RecordCompletion(first_run::TUTORIAL_NOT_FINISHED);
   Stop();
 }
 
@@ -170,7 +170,7 @@
   AdvanceStep();
   if (!GetCurrentStep()) {
     actor_->Finalize();
-    RecordCompletion(first_run::kTutorialCompletedWithGotIt);
+    RecordCompletion(first_run::TUTORIAL_COMPLETED_WITH_GOT_IT);
     return;
   }
   GetCurrentStep()->Show();
diff --git a/chrome/browser/chromeos/first_run/metrics.h b/chrome/browser/chromeos/first_run/metrics.h
index 66ccd5f..b46e5c6 100644
--- a/chrome/browser/chromeos/first_run/metrics.h
+++ b/chrome/browser/chromeos/first_run/metrics.h
@@ -10,14 +10,17 @@
 
 enum TutorialCompletion {
   // User left tutorial before finish.
-  kTutorialNotFinished,
+  TUTORIAL_NOT_FINISHED,
+
   // Tutorial was completed with "Got It" button.
-  kTutorialCompletedWithGotIt,
+  TUTORIAL_COMPLETED_WITH_GOT_IT,
+
   // Tutorial was completed with "Keep Exploring" button, i.e. Help App was
   // launched after tutorial.
-  kTutorialCompletedWithKeepExploring,
+  TUTORIAL_COMPLETED_WITH_KEEP_EXPLORING,
+
   // Must be the last element.
-  kTutorialCompletionSize
+  TUTORIAL_COMPLETION_SIZE
 };
 
 }  // namespace first_run
diff --git a/chrome/browser/chromeos/idle_detector.cc b/chrome/browser/chromeos/idle_detector.cc
index a439166..57584a2 100644
--- a/chrome/browser/chromeos/idle_detector.cc
+++ b/chrome/browser/chromeos/idle_detector.cc
@@ -35,11 +35,10 @@
 }
 
 void IdleDetector::ResetTimer() {
-  if (timer_.IsRunning()) {
+  if (timer_.IsRunning())
     timer_.Reset();
-  } else {
+  else
     timer_.Start(FROM_HERE, timeout_, idle_callback_);
-  }
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/idle_detector.h b/chrome/browser/chromeos/idle_detector.h
index e585c40..1fa47be 100644
--- a/chrome/browser/chromeos/idle_detector.h
+++ b/chrome/browser/chromeos/idle_detector.h
@@ -7,7 +7,9 @@
 
 #include "ash/wm/user_activity_observer.h"
 #include "base/basictypes.h"
+#include "base/callback.h"
 #include "base/compiler_specific.h"
+#include "base/time/time.h"
 #include "base/timer/timer.h"
 
 namespace chromeos {
diff --git a/chrome/browser/chromeos/input_method/OWNERS b/chrome/browser/chromeos/input_method/OWNERS
index 1f647c3..ad4a955 100644
--- a/chrome/browser/chromeos/input_method/OWNERS
+++ b/chrome/browser/chromeos/input_method/OWNERS
@@ -1,3 +1,8 @@
+# primary reviewer
+shuchen@chromium.org
+
+# backup reviewers
 komatsu@chromium.org
 nona@chromium.org
+yukishiino@chromium.org
 zork@chromium.org
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
index 95546fd..02ce169 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.cc
@@ -192,6 +192,7 @@
 
 // static
 bool ComponentExtensionIMEManagerImpl::ReadEngineComponent(
+    const ComponentExtensionIME& component_extension,
     const base::DictionaryValue& dict,
     ComponentExtensionEngine* out) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
@@ -235,6 +236,33 @@
     if (layouts->GetString(i, &buffer))
       out->layouts.push_back(buffer);
   }
+
+  std::string url_string;
+  if (dict.GetString(extensions::manifest_keys::kInputView,
+                     &url_string)) {
+    GURL url = extensions::Extension::GetResourceURL(
+        extensions::Extension::GetBaseURLFromExtensionId(
+            component_extension.id),
+        url_string);
+    if (!url.is_valid())
+      return false;
+    out->input_view_url = url;
+  }
+
+  if (dict.GetString(extensions::manifest_keys::kOptionsPage,
+                     &url_string)) {
+    GURL url = extensions::Extension::GetResourceURL(
+        extensions::Extension::GetBaseURLFromExtensionId(
+            component_extension.id),
+        url_string);
+    if (!url.is_valid())
+      return false;
+    out->options_page_url = url;
+  } else {
+    // Fallback to extension level options page.
+    out->options_page_url = component_extension.options_page_url;
+  }
+
   return true;
 }
 
@@ -257,15 +285,6 @@
       return false;
     out->options_page_url = url;
   }
-  if (manifest.GetString(extensions::manifest_keys::kInputView,
-                         &url_string)) {
-    GURL url = extensions::Extension::GetResourceURL(
-        extensions::Extension::GetBaseURLFromExtensionId(extension_id),
-        url_string);
-    if (!url.is_valid())
-      return false;
-    out->input_view_url = url;
-  }
   // It's okay to return true on no option page and/or input view page case.
   return true;
 }
@@ -312,7 +331,7 @@
         continue;
 
       ComponentExtensionEngine engine;
-      ReadEngineComponent(*dictionary, &engine);
+      ReadEngineComponent(component_ime, *dictionary, &engine);
       component_ime.engines.push_back(engine);
     }
     out_imes->push_back(component_ime);
diff --git a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h
index 2dc548b..913987a 100644
--- a/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h
+++ b/chrome/browser/chromeos/input_method/component_extension_ime_manager_impl.h
@@ -67,8 +67,10 @@
   // Reads each engine component in |dict|. |dict| is given by GetList with
   // kInputComponents key from manifest. This function returns true on success,
   // otherwise retrun false. This function must be called on FILE thread.
-  static bool ReadEngineComponent(const base::DictionaryValue& dict,
-                                  ComponentExtensionEngine* out);
+  static bool ReadEngineComponent(
+      const ComponentExtensionIME& component_extension,
+      const base::DictionaryValue& dict,
+      ComponentExtensionEngine* out);
 
   // True if initialized.
   bool is_initialized_;
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc
index 775f5ce..fa935fb 100644
--- a/chrome/browser/chromeos/input_method/input_method_engine.cc
+++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -218,7 +218,9 @@
   if (!active_) {
     return false;
   }
-  if (context_id != context_id_ || context_id_ == -1) {
+  // context_id  ==  0, means sending key events to non-input field.
+  // context_id_ == -1, means the focus is not in an input field.
+  if ((context_id != 0 && context_id != context_id_) || context_id_ == -1) {
     return false;
   }
 
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
index 4a8912e..45588b6 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.cc
@@ -715,6 +715,14 @@
   return current_input_method_;
 }
 
+bool InputMethodManagerImpl::IsISOLevel5ShiftUsedByCurrentInputMethod() const {
+  return xkeyboard_->IsISOLevel5ShiftAvailable();
+}
+
+bool InputMethodManagerImpl::IsAltGrUsedByCurrentInputMethod() const {
+  return xkeyboard_->IsAltGrAvailable();
+}
+
 XKeyboard* InputMethodManagerImpl::GetXKeyboard() {
   return xkeyboard_.get();
 }
diff --git a/chrome/browser/chromeos/input_method/input_method_manager_impl.h b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
index 7d6447e..23ec79c 100644
--- a/chrome/browser/chromeos/input_method/input_method_manager_impl.h
+++ b/chrome/browser/chromeos/input_method/input_method_manager_impl.h
@@ -81,6 +81,8 @@
       const ui::Accelerator& accelerator) OVERRIDE;
   virtual bool SwitchInputMethod(const ui::Accelerator& accelerator) OVERRIDE;
   virtual InputMethodDescriptor GetCurrentInputMethod() const OVERRIDE;
+  virtual bool IsISOLevel5ShiftUsedByCurrentInputMethod() const OVERRIDE;
+  virtual bool IsAltGrUsedByCurrentInputMethod() const OVERRIDE;
 
   virtual XKeyboard* GetXKeyboard() OVERRIDE;
   virtual InputMethodUtil* GetInputMethodUtil() OVERRIDE;
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
index 95142a3..6045c7a 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.cc
@@ -10,7 +10,8 @@
 MockInputMethodManager::MockInputMethodManager()
     : add_observer_count_(0),
       remove_observer_count_(0),
-      util_(&delegate_, whitelist_.GetSupportedInputMethods()) {
+      util_(&delegate_, whitelist_.GetSupportedInputMethods()),
+      mod3_used_(false) {
   active_input_method_ids_.push_back("xkb:us::eng");
 }
 
@@ -144,6 +145,14 @@
   return descriptor;
 }
 
+bool MockInputMethodManager::IsISOLevel5ShiftUsedByCurrentInputMethod() const {
+  return mod3_used_;
+}
+
+bool MockInputMethodManager::IsAltGrUsedByCurrentInputMethod() const {
+  return false;
+}
+
 XKeyboard* MockInputMethodManager::GetXKeyboard() {
   return &xkeyboard_;
 }
diff --git a/chrome/browser/chromeos/input_method/mock_input_method_manager.h b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
index 25f21c0..3f9c600 100644
--- a/chrome/browser/chromeos/input_method/mock_input_method_manager.h
+++ b/chrome/browser/chromeos/input_method/mock_input_method_manager.h
@@ -58,6 +58,8 @@
       const ui::Accelerator& accelerator) OVERRIDE;
   virtual bool SwitchInputMethod(const ui::Accelerator& accelerator) OVERRIDE;
   virtual InputMethodDescriptor GetCurrentInputMethod() const OVERRIDE;
+  virtual bool IsISOLevel5ShiftUsedByCurrentInputMethod() const OVERRIDE;
+  virtual bool IsAltGrUsedByCurrentInputMethod() const OVERRIDE;
   virtual XKeyboard* GetXKeyboard() OVERRIDE;
   virtual InputMethodUtil* GetInputMethodUtil() OVERRIDE;
   virtual ComponentExtensionIMEManager*
@@ -74,6 +76,9 @@
   // Set values that will be provided to the InputMethodUtil.
   void set_application_locale(const std::string& value);
 
+  // Set the value returned by IsISOLevel5ShiftUsedByCurrentInputMethod
+  void set_mod3_used(bool value) { mod3_used_ = value; }
+
   // TODO(yusukes): Add more variables for counting the numbers of the API calls
   int add_observer_count_;
   int remove_observer_count_;
@@ -86,6 +91,7 @@
   FakeInputMethodDelegate delegate_;  // used by util_
   InputMethodUtil util_;
   FakeXKeyboard xkeyboard_;
+  bool mod3_used_;
 
   // The active input method ids cache (actually default only)
   std::vector<std::string> active_input_method_ids_;
diff --git a/chrome/browser/chromeos/login/app_launch_controller.cc b/chrome/browser/chromeos/login/app_launch_controller.cc
index 7cda1fc..e7d0196 100644
--- a/chrome/browser/chromeos/login/app_launch_controller.cc
+++ b/chrome/browser/chromeos/login/app_launch_controller.cc
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
+#include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/time/time.h"
@@ -119,6 +120,7 @@
       waiting_for_network_(false),
       network_wait_timedout_(false),
       showing_network_dialog_(false),
+      network_config_requested_(false),
       launch_splash_start_time_(0) {
 }
 
@@ -141,8 +143,8 @@
   app_launch_splash_screen_actor_->Show(app_id_);
 
   KioskAppManager::App app;
-  CHECK(KioskAppManager::Get() &&
-        KioskAppManager::Get()->GetApp(app_id_, &app));
+  CHECK(KioskAppManager::Get());
+  CHECK(KioskAppManager::Get()->GetApp(app_id_, &app));
   kiosk_profile_loader_.reset(
       new KioskProfileLoader(app.user_id, false, this));
   kiosk_profile_loader_->Start();
@@ -216,11 +218,19 @@
   OnLaunchFailed(KioskAppLaunchError::USER_CANCEL);
 }
 
+void AppLaunchController::OnNetworkConfigRequested(bool requested) {
+  network_config_requested_ = requested;
+  if (requested)
+    MaybeShowNetworkConfigureUI();
+  else
+    startup_app_launcher_->RestartLauncher();
+}
+
 void AppLaunchController::OnNetworkStateChanged(bool online) {
   if (!waiting_for_network_)
     return;
 
-  if (online)
+  if (online && !network_config_requested_)
     startup_app_launcher_->ContinueWithNetworkReady();
   else if (network_wait_timedout_)
     MaybeShowNetworkConfigureUI();
@@ -300,7 +310,10 @@
 void AppLaunchController::MaybeShowNetworkConfigureUI() {
   if (CanConfigureNetwork()) {
     if (NeedOwnerAuthToConfigureNetwork()) {
-      app_launch_splash_screen_actor_->ToggleNetworkConfig(true);
+      if (network_config_requested_)
+        OnConfigureNetwork();
+      else
+        app_launch_splash_screen_actor_->ToggleNetworkConfig(true);
     } else {
       showing_network_dialog_ = true;
       app_launch_splash_screen_actor_->ShowNetworkConfigureUI();
@@ -312,7 +325,7 @@
 }
 
 void AppLaunchController::InitializeNetwork() {
-  // Show the network configration dialog if network is not initialized
+  // Show the network configuration dialog if network is not initialized
   // after a brief wait time.
   waiting_for_network_ = true;
   network_wait_timer_.Start(
@@ -357,6 +370,10 @@
 
 void AppLaunchController::OnReadyToLaunch() {
   launcher_ready_ = true;
+
+  if (network_config_requested_)
+    return;
+
   if (!webui_visible_)
     return;
 
@@ -402,4 +419,8 @@
   CleanUp();
 }
 
+bool AppLaunchController::IsShowingNetworkConfigScreen() {
+  return network_config_requested_;
+}
+
 }   // namespace chromeos
diff --git a/chrome/browser/chromeos/login/app_launch_controller.h b/chrome/browser/chromeos/login/app_launch_controller.h
index 4e52f2c..a585b2c 100644
--- a/chrome/browser/chromeos/login/app_launch_controller.h
+++ b/chrome/browser/chromeos/login/app_launch_controller.h
@@ -87,6 +87,7 @@
   // AppLaunchSplashScreenActor::Delegate overrides:
   virtual void OnConfigureNetwork() OVERRIDE;
   virtual void OnCancelAppLaunch() OVERRIDE;
+  virtual void OnNetworkConfigRequested(bool requested) OVERRIDE;
   virtual void OnNetworkStateChanged(bool online) OVERRIDE;
 
   // StartupAppLauncher::Delegate overrides:
@@ -98,6 +99,7 @@
   virtual void OnReadyToLaunch() OVERRIDE;
   virtual void OnLaunchSucceeded() OVERRIDE;
   virtual void OnLaunchFailed(KioskAppLaunchError::Error error) OVERRIDE;
+  virtual bool IsShowingNetworkConfigScreen() OVERRIDE;
 
   // AppLaunchSigninScreen::Delegate overrides:
   virtual void OnOwnerSigninSuccess() OVERRIDE;
@@ -129,6 +131,7 @@
   bool waiting_for_network_;
   bool network_wait_timedout_;
   bool showing_network_dialog_;
+  bool network_config_requested_;
   int64 launch_splash_start_time_;
 
   static bool skip_splash_wait_;
diff --git a/chrome/browser/chromeos/login/authenticator.h b/chrome/browser/chromeos/login/authenticator.h
index 079fb61..b1d38df 100644
--- a/chrome/browser/chromeos/login/authenticator.h
+++ b/chrome/browser/chromeos/login/authenticator.h
@@ -58,9 +58,10 @@
 
   // Initiates login into kiosk mode account identified by |app_user_id|.
   // The |app_user_id| is a generated username for the account.
-  // |force_ephemeral| specifies whether to force the session to be ephemeral.
-  virtual void LoginAsKioskAccount(
-      const std::string& app_user_id, bool force_ephemeral) = 0;
+  // |use_guest_mount| specifies whether to force the session to use a
+  // guest mount. If this is false, we use mount a public cryptohome.
+  virtual void LoginAsKioskAccount(const std::string& app_user_id,
+                                   bool use_guest_mount) = 0;
 
   // Completes retail mode login.
   virtual void OnRetailModeLoginSuccess() = 0;
diff --git a/chrome/browser/chromeos/login/captive_portal_view.cc b/chrome/browser/chromeos/login/captive_portal_view.cc
index 7b3c709..f20e759 100644
--- a/chrome/browser/chromeos/login/captive_portal_view.cc
+++ b/chrome/browser/chromeos/login/captive_portal_view.cc
@@ -84,14 +84,14 @@
   // Note, |url| will be empty for "client3.google.com/generate_204" page.
   if (!redirected_  && url != GURL::EmptyGURL() &&
       url != GURL(CaptivePortalStartURL())) {
-    DLOG(INFO) << CaptivePortalStartURL() << " vs " << url.spec();
     redirected_ = true;
     proxy_->OnRedirected();
   }
 }
 
-void CaptivePortalView::LoadingStateChanged(content::WebContents* source) {
-  SimpleWebViewDialog::LoadingStateChanged(source);
+void CaptivePortalView::LoadingStateChanged(content::WebContents* source,
+    bool to_different_document) {
+  SimpleWebViewDialog::LoadingStateChanged(source, to_different_document);
   // TODO(nkostylev): Fix case of no connectivity, check HTTP code returned.
   // Disable this heuristic as it has false positives.
   // Relying on just shill portal check to close dialog is fine.
diff --git a/chrome/browser/chromeos/login/captive_portal_view.h b/chrome/browser/chromeos/login/captive_portal_view.h
index 1a8b34e..1c8ef90 100644
--- a/chrome/browser/chromeos/login/captive_portal_view.h
+++ b/chrome/browser/chromeos/login/captive_portal_view.h
@@ -31,7 +31,8 @@
   // Overridden from content::WebContentsDelegate:
   virtual void NavigationStateChanged(const content::WebContents* source,
                                       unsigned changed_flags) OVERRIDE;
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
 
  private:
   // Contains CaptivePortalWindowProxy to be notified when redirection state is
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.cc b/chrome/browser/chromeos/login/chrome_restart_request.cc
index 2becd05..c34e699 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.cc
+++ b/chrome/browser/chromeos/login/chrome_restart_request.cc
@@ -72,6 +72,7 @@
     ::switches::kDisableAcceleratedVideoDecode,
     ::switches::kDisableBrowserPluginCompositing,
     ::switches::kDisableDelegatedRenderer,
+    ::switches::kDisableFastTextAutosizing,
     ::switches::kDisableFiltersOverIPC,
     ::switches::kDisableForceCompositingMode,
     ::switches::kDisableGpuShaderDiskCache,
@@ -99,6 +100,7 @@
     ::switches::kEnableCompositingForFixedPosition,
     ::switches::kEnableDelegatedRenderer,
     ::switches::kEnableEncryptedMedia,
+    ::switches::kEnableFastTextAutosizing,
     ::switches::kEnableGestureTapHighlight,
     ::switches::kDisableGestureTapHighlight,
     ::switches::kDisableGpuSandbox,
@@ -122,6 +124,7 @@
     ::switches::kGpuStartupDialog,
     ::switches::kGpuSandboxAllowSysVShm,
     ::switches::kGpuSandboxFailuresFatal,
+    ::switches::kGpuSandboxStartAfterInitialization,
     ::switches::kMultiProfiles,
     ::switches::kNoSandbox,
     ::switches::kNumRasterThreads,
@@ -326,6 +329,7 @@
 
 std::string GetOffTheRecordCommandLine(
     const GURL& start_url,
+    bool is_oobe_completed,
     const CommandLine& base_command_line,
     CommandLine* command_line) {
   base::DictionaryValue otr_switches;
@@ -338,6 +342,12 @@
   otr_switches.SetString(::switches::kHomePage,
                          GURL(chrome::kChromeUINewTabURL).spec());
 
+  // If OOBE is not finished yet, lock down the guest session to not allow
+  // surfing the web. Guest mode is still useful to inspect logs and run network
+  // diagnostics.
+  if (!is_oobe_completed)
+    otr_switches.SetString(switches::kOobeGuestSession, std::string());
+
   return DeriveCommandLine(start_url,
                            base_command_line,
                            otr_switches,
diff --git a/chrome/browser/chromeos/login/chrome_restart_request.h b/chrome/browser/chromeos/login/chrome_restart_request.h
index b9c9ba1..788edb1 100644
--- a/chrome/browser/chromeos/login/chrome_restart_request.h
+++ b/chrome/browser/chromeos/login/chrome_restart_request.h
@@ -19,6 +19,7 @@
 // the given command line.
 std::string GetOffTheRecordCommandLine(
     const GURL& start_url,
+    bool is_oobe_completed,
     const base::CommandLine& base_command_line,
     base::CommandLine* command_line);
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc
index e983d48..05f29d6 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.cc
@@ -5,23 +5,40 @@
 #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
 
 #include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
 #include "chrome/browser/chromeos/app_mode/app_session_lifetime.h"
+#include "chrome/browser/chromeos/login/login_display_host.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/extensions/component_loader.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/extensions/extension_constants.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/common/extension.h"
 #include "grit/browser_resources.h"
+#include "ui/base/window_open_disposition.h"
 
 namespace chromeos {
 
 const char DemoAppLauncher::kDemoUserName[] = "demouser@demo.app.local";
+const base::FilePath::CharType kDefaultDemoAppPath[] =
+    FILE_PATH_LITERAL("/usr/share/chromeos-assets/demo_app");
 
-DemoAppLauncher::DemoAppLauncher() : profile_(NULL) {}
+// static
+base::FilePath* DemoAppLauncher::demo_app_path_ = NULL;
 
-DemoAppLauncher::~DemoAppLauncher() {}
+DemoAppLauncher::DemoAppLauncher() {
+  if (!demo_app_path_)
+    demo_app_path_ = new base::FilePath(kDefaultDemoAppPath);
+}
+
+DemoAppLauncher::~DemoAppLauncher() {
+  delete demo_app_path_;
+}
 
 void DemoAppLauncher::StartDemoAppLaunch() {
   DVLOG(1) << "Launching demo app...";
@@ -33,21 +50,27 @@
 
 // static
 bool DemoAppLauncher::IsDemoAppSession(const std::string& user_id) {
-  return user_id == kDemoUserName ? true : false;
+  return user_id == kDemoUserName;
+}
+
+// static
+void DemoAppLauncher::SetDemoAppPathForTesting(const base::FilePath& path) {
+  delete demo_app_path_;
+  demo_app_path_ = new base::FilePath(path);
 }
 
 void DemoAppLauncher::OnProfileLoaded(Profile* profile) {
   DVLOG(1) << "Profile loaded... Starting demo app launch.";
-  profile_ = profile;
 
   kiosk_profile_loader_.reset();
 
   // Load our demo app, then launch it.
   ExtensionService* extension_service =
-      extensions::ExtensionSystem::Get(profile_)->extension_service();
-  std::string extension_id = extension_service->component_loader()->Add(
+      extensions::ExtensionSystem::Get(profile)->extension_service();
+  CHECK(demo_app_path_);
+  const std::string extension_id = extension_service->component_loader()->Add(
       IDR_DEMO_APP_MANIFEST,
-      base::FilePath("/usr/share/chromeos-assets/demo_app"));
+      *demo_app_path_);
 
   const extensions::Extension* extension =
       extension_service->GetExtensionById(extension_id, true);
@@ -57,8 +80,8 @@
   command_line->AppendSwitchASCII(switches::kAppId, extension_id);
 
   OpenApplication(AppLaunchParams(
-      profile_, extension, extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW));
-  InitAppSession(profile_, extension_id);
+      profile, extension, extensions::LAUNCH_CONTAINER_WINDOW, NEW_WINDOW));
+  InitAppSession(profile, extension_id);
 
   UserManager::Get()->SessionStarted();
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h
index 8579a52..4a82ea8 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h
+++ b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h
@@ -5,10 +5,16 @@
 #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_APP_LAUNCHER_H_
 #define CHROME_BROWSER_CHROMEOS_LOGIN_DEMO_MODE_DEMO_APP_LAUNCHER_H_
 
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_profile_loader.h"
 
-class Profile;
+namespace base {
+class FilePath;
+}
 
 namespace chromeos {
 
@@ -21,16 +27,21 @@
   void StartDemoAppLaunch();
 
   static bool IsDemoAppSession(const std::string& user_id);
+  static void SetDemoAppPathForTesting(const base::FilePath& path);
+
   static const char kDemoUserName[];
 
  private:
+  friend class DemoAppLauncherTest;
+
   // KioskProfileLoader::Delegate overrides:
   virtual void OnProfileLoaded(Profile* profile) OVERRIDE;
   virtual void OnProfileLoadFailed(KioskAppLaunchError::Error error) OVERRIDE;
 
-  Profile* profile_;
   scoped_ptr<KioskProfileLoader> kiosk_profile_loader_;
 
+  static base::FilePath* demo_app_path_;
+
   DISALLOW_COPY_AND_ASSIGN(DemoAppLauncher);
 };
 
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc
new file mode 100644
index 0000000..065f022
--- /dev/null
+++ b/chrome/browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc
@@ -0,0 +1,91 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "apps/app_window_registry.h"
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
+#include "chrome/browser/chromeos/login/test/app_window_waiter.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/common/chrome_paths.h"
+#include "chromeos/chromeos_switches.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+
+char kDemoAppId[] = "klimoghijjogocdbaikffefjfcfheiel";
+
+base::FilePath GetTestDemoAppPath() {
+  base::FilePath test_data_dir;
+  EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
+  return test_data_dir.Append(FILE_PATH_LITERAL("chromeos/demo_app"));
+}
+
+Profile* WaitForProfile() {
+  chromeos::UserManager* user_manager = chromeos::UserManager::Get();
+  if (!user_manager || !user_manager->IsUserLoggedIn()) {
+    content::WindowedNotificationObserver(
+        chrome::NOTIFICATION_SESSION_STARTED,
+        content::NotificationService::AllSources()).Wait();
+  }
+
+  return ProfileManager::GetActiveUserProfile();
+}
+
+bool VerifyDemoAppLaunch() {
+  Profile* profile = WaitForProfile();
+  return AppWindowWaiter(apps::AppWindowRegistry::Get(profile),
+                         kDemoAppId).Wait() != NULL;
+}
+
+}  // namespace
+
+class DemoAppLauncherTest : public ExtensionBrowserTest {
+ public:
+  DemoAppLauncherTest() {
+    set_exit_when_last_browser_closes(false);
+  }
+
+  virtual ~DemoAppLauncherTest() {}
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    command_line->AppendSwitch(switches::kLoginManager);
+    command_line->AppendSwitch(switches::kForceLoginManagerInTests);
+    command_line->AppendSwitchASCII(switches::kLoginProfile, "user");
+
+    command_line->AppendSwitchASCII(switches::kDerelictIdleTimeout, "0");
+    command_line->AppendSwitchASCII(switches::kOobeTimerInterval, "0");
+    command_line->AppendSwitchASCII(switches::kDerelictDetectionTimeout, "0");
+  }
+
+  virtual void SetUp() OVERRIDE {
+    chromeos::DemoAppLauncher::SetDemoAppPathForTesting(GetTestDemoAppPath());
+    ExtensionBrowserTest::SetUp();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(DemoAppLauncherTest);
+};
+
+IN_PROC_BROWSER_TEST_F(DemoAppLauncherTest, Basic) {
+  // This test is fairly unique in the sense that the test actually starts as
+  // soon as Chrome launches, so there isn't any typical "launch this test"
+  // steps that we need to take. All we can do is verify that our demo app
+  // did launch.
+  EXPECT_TRUE(VerifyDemoAppLaunch());
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.cc
new file mode 100644
index 0000000..0c2818d
--- /dev/null
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.cc
@@ -0,0 +1,176 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "chrome/browser/chromeos/login/screens/screen_observer.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+
+namespace chromeos {
+
+AutoEnrollmentCheckStep::AutoEnrollmentCheckStep(
+    ScreenObserver* screen_observer,
+    AutoEnrollmentController* auto_enrollment_controller)
+    : screen_observer_(screen_observer),
+      auto_enrollment_controller_(auto_enrollment_controller),
+      captive_portal_status_(
+          NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN),
+      auto_enrollment_state_(policy::AUTO_ENROLLMENT_STATE_IDLE) {}
+
+AutoEnrollmentCheckStep::~AutoEnrollmentCheckStep() {
+  NetworkPortalDetector::Get()->RemoveObserver(this);
+}
+
+void AutoEnrollmentCheckStep::Start() {
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          chromeos::switches::kEnterpriseEnableForcedReEnrollment)) {
+    SignalCompletion();
+    return;
+  }
+
+  // Make sure the auto-enrollment client is running.
+  auto_enrollment_controller_->Start();
+
+  auto_enrollment_progress_subscription_ =
+      auto_enrollment_controller_->RegisterProgressCallback(
+          base::Bind(&AutoEnrollmentCheckStep::OnAutoEnrollmentCheckProgressed,
+                     base::Unretained(this)));
+  auto_enrollment_state_ = auto_enrollment_controller_->state();
+
+  // NB: AddAndFireObserver below call back into OnPortalDetectionCompleted.
+  // This guarantees that the UI gets synced to current state.
+  NetworkPortalDetector* portal_detector = NetworkPortalDetector::Get();
+  portal_detector->StartDetectionIfIdle();
+  portal_detector->AddAndFireObserver(this);
+}
+
+void AutoEnrollmentCheckStep::OnPortalDetectionCompleted(
+    const NetworkState* /* network */,
+    const NetworkPortalDetector::CaptivePortalState& state) {
+  UpdateState(state.status, auto_enrollment_state_);
+}
+
+void AutoEnrollmentCheckStep::OnAutoEnrollmentCheckProgressed(
+    policy::AutoEnrollmentState state) {
+  UpdateState(captive_portal_status_, state);
+}
+
+void AutoEnrollmentCheckStep::UpdateState(
+    NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status,
+    policy::AutoEnrollmentState new_auto_enrollment_state) {
+  // Configure the error screen to show the approriate error message.
+  if (!UpdateCaptivePortalStatus(new_captive_portal_status))
+    UpdateAutoEnrollmentState(new_auto_enrollment_state);
+
+  // Update the connecting indicator.
+  ErrorScreen* error_screen = screen_observer_->GetErrorScreen();
+  error_screen->ShowConnectingIndicator(
+      new_auto_enrollment_state == policy::AUTO_ENROLLMENT_STATE_PENDING);
+
+  // Determine whether a retry is in order.
+  bool retry = (new_captive_portal_status ==
+                NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) &&
+               (captive_portal_status_ !=
+                NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE);
+
+  // Save the new state.
+  captive_portal_status_ = new_captive_portal_status;
+  auto_enrollment_state_ = new_auto_enrollment_state;
+
+  // Check whether a decision got made.
+  switch (new_auto_enrollment_state) {
+    case policy::AUTO_ENROLLMENT_STATE_IDLE:
+      NOTREACHED();
+      // fall through.
+    case policy::AUTO_ENROLLMENT_STATE_PENDING:
+    case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
+      break;
+    case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
+      // Server errors don't block OOBE.
+    case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
+    case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
+      // Decision made, ready to proceed.
+      SignalCompletion();
+      return;
+  }
+
+  // Retry if applicable. This is last so eventual callbacks find consistent
+  // state.
+  if (retry)
+    auto_enrollment_controller_->Retry();
+}
+
+bool AutoEnrollmentCheckStep::UpdateCaptivePortalStatus(
+    NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status) {
+  switch (new_captive_portal_status) {
+    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
+    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
+      return false;
+    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
+      ShowErrorScreen(ErrorScreen::ERROR_STATE_OFFLINE);
+      return true;
+    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
+      ShowErrorScreen(ErrorScreen::ERROR_STATE_PORTAL);
+      if (captive_portal_status_ != new_captive_portal_status)
+        screen_observer_->GetErrorScreen()->FixCaptivePortal();
+      return true;
+    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
+      ShowErrorScreen(ErrorScreen::ERROR_STATE_PROXY);
+      return true;
+    case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT:
+      // Trigger NOTREACHED() below.
+      break;
+  }
+
+  NOTREACHED() << "Bad status " << new_captive_portal_status;
+  return false;
+}
+
+bool AutoEnrollmentCheckStep::UpdateAutoEnrollmentState(
+    policy::AutoEnrollmentState new_auto_enrollment_state) {
+  switch (new_auto_enrollment_state) {
+    case policy::AUTO_ENROLLMENT_STATE_IDLE:
+      // The client should have been started already.
+      NOTREACHED();
+      return false;
+    case policy::AUTO_ENROLLMENT_STATE_PENDING:
+    case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
+    case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
+    case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
+      return false;
+    case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
+      ShowErrorScreen(ErrorScreen::ERROR_STATE_OFFLINE);
+      return true;
+  }
+
+  NOTREACHED() << "bad state " << new_auto_enrollment_state;
+  return false;
+}
+
+void AutoEnrollmentCheckStep::ShowErrorScreen(
+    ErrorScreen::ErrorState error_state) {
+  const NetworkState* network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  ErrorScreen* error_screen = screen_observer_->GetErrorScreen();
+  error_screen->SetUIState(ErrorScreen::UI_STATE_AUTO_ENROLLMENT_ERROR);
+  error_screen->AllowGuestSignin(true);
+  error_screen->SetErrorState(error_state,
+                              network ? network->name() : std::string());
+  screen_observer_->ShowErrorScreen();
+}
+
+void AutoEnrollmentCheckStep::SignalCompletion() {
+  NetworkPortalDetector::Get()->RemoveObserver(this);
+  auto_enrollment_progress_subscription_.reset();
+  screen_observer_->OnExit(
+      ScreenObserver::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.h b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.h
new file mode 100644
index 0000000..baa3931
--- /dev/null
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.h
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ENROLLMENT_AUTO_ENROLLMENT_CHECK_STEP_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_ENROLLMENT_AUTO_ENROLLMENT_CHECK_STEP_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
+#include "chrome/browser/chromeos/login/screens/error_screen.h"
+#include "chrome/browser/chromeos/net/network_portal_detector.h"
+
+namespace chromeos {
+
+class ScreenObserver;
+
+// Handles the control flow after OOBE auto-update completes to wait for the
+// enterprise auto-enrollment check that happens as part of OOBE. This includes
+// keeping track of current auto-enrollment state and displaying and updating
+// the error screen upon failures. Similar to a screen controller, but it
+// doesn't actually drive a dedicated screen.
+class AutoEnrollmentCheckStep : NetworkPortalDetector::Observer {
+ public:
+  AutoEnrollmentCheckStep(ScreenObserver* screen_observer,
+                          AutoEnrollmentController* auto_enrollment_controller);
+  virtual ~AutoEnrollmentCheckStep();
+
+  // Hands over OOBE control to this AutoEnrollmentCheckStep. It'll return the
+  // flow back to the caller via the |screen_observer_|'s OnExit function.
+  void Start();
+
+  // NetworkPortalDetector::Observer implementation:
+  virtual void OnPortalDetectionCompleted(
+      const NetworkState* network,
+      const NetworkPortalDetector::CaptivePortalState& state) OVERRIDE;
+
+ private:
+  // Handles update notifications regarding the auto-enrollment check.
+  void OnAutoEnrollmentCheckProgressed(policy::AutoEnrollmentState state);
+
+  // Handles a state update, updating the UI and saving the state.
+  void UpdateState(
+      NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status,
+      policy::AutoEnrollmentState new_auto_enrollment_state);
+
+  // Configures the UI to reflect |new_captive_portal_status|. Returns true if
+  // and only if a UI change has been made.
+  bool UpdateCaptivePortalStatus(
+      NetworkPortalDetector::CaptivePortalStatus new_captive_portal_status);
+
+  // Configures the UI to reflect |auto_enrollment_state|. Returns true if and
+  // only if a UI change has been made.
+  bool UpdateAutoEnrollmentState(
+      policy::AutoEnrollmentState auto_enrollment_state);
+
+  // Configures the error screen.
+  void ShowErrorScreen(ErrorScreen::ErrorState error_state);
+
+  // Signals completion. No further code should run after a call to this
+  // function as the owner might destroy |this| in response.
+  void SignalCompletion();
+
+  ScreenObserver* screen_observer_;
+  AutoEnrollmentController* auto_enrollment_controller_;
+
+  scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
+      auto_enrollment_progress_subscription_;
+
+  NetworkPortalDetector::CaptivePortalStatus captive_portal_status_;
+  policy::AutoEnrollmentState auto_enrollment_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentCheckStep);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_ENROLLMENT_AUTO_ENROLLMENT_CHECK_STEP_H_
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
new file mode 100644
index 0000000..1c78f41
--- /dev/null
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.cc
@@ -0,0 +1,171 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
+#include "chromeos/chromeos_switches.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/cloud/device_management_service.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace chromeos {
+
+namespace {
+
+// Returns the int value of the |switch_name| argument, clamped to the [0, 62]
+// interval. Returns 0 if the argument doesn't exist or isn't an int value.
+int GetSanitizedArg(const std::string& switch_name) {
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (!command_line->HasSwitch(switch_name))
+    return 0;
+  std::string value = command_line->GetSwitchValueASCII(switch_name);
+  int int_value;
+  if (!base::StringToInt(value, &int_value)) {
+    LOG(ERROR) << "Switch \"" << switch_name << "\" is not a valid int. "
+               << "Defaulting to 0.";
+    return 0;
+  }
+  if (int_value < 0) {
+    LOG(ERROR) << "Switch \"" << switch_name << "\" can't be negative. "
+               << "Using 0";
+    return 0;
+  }
+  if (int_value > policy::AutoEnrollmentClient::kMaximumPower) {
+    LOG(ERROR) << "Switch \"" << switch_name << "\" can't be greater than "
+               << policy::AutoEnrollmentClient::kMaximumPower << ". Using "
+               << policy::AutoEnrollmentClient::kMaximumPower;
+    return policy::AutoEnrollmentClient::kMaximumPower;
+  }
+  return int_value;
+}
+
+}  // namespace
+
+AutoEnrollmentController::AutoEnrollmentController()
+    : state_(policy::AUTO_ENROLLMENT_STATE_IDLE),
+      weak_factory_(this) {}
+
+AutoEnrollmentController::~AutoEnrollmentController() {}
+
+void AutoEnrollmentController::Start() {
+  // This method is called at the point in the OOBE/login flow at which the
+  // auto-enrollment check can start. This happens either after the EULA is
+  // accepted, or right after a reboot if the EULA has already been accepted.
+
+  // Do not communicate auto-enrollment data to the server if
+  // 1. we are running integration or perf tests with telemetry.
+  // 2. modulus configuration is not present.
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(chromeos::switches::kOobeSkipPostLogin) ||
+      (!command_line->HasSwitch(
+           chromeos::switches::kEnterpriseEnrollmentInitialModulus) &&
+       !command_line->HasSwitch(
+           chromeos::switches::kEnterpriseEnrollmentModulusLimit))) {
+    VLOG(1) << "Auto-enrollment disabled.";
+    UpdateState(policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT);
+    return;
+  }
+
+  // If there already is a client, bail out.
+  if (client_)
+    return;
+
+  // Start by checking if the device has already been owned.
+  UpdateState(policy::AUTO_ENROLLMENT_STATE_PENDING);
+  weak_factory_.InvalidateWeakPtrs();
+  DeviceSettingsService::Get()->GetOwnershipStatusAsync(
+      base::Bind(&AutoEnrollmentController::OnOwnershipStatusCheckDone,
+                 weak_factory_.GetWeakPtr()));
+}
+
+void AutoEnrollmentController::Cancel() {
+  if (client_) {
+    // Cancelling the |client_| allows it to determine whether
+    // its protocol finished before login was complete.
+    client_.release()->CancelAndDeleteSoon();
+  }
+}
+
+void AutoEnrollmentController::Retry() {
+  if (client_)
+    client_->Retry();
+}
+
+scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
+AutoEnrollmentController::RegisterProgressCallback(
+    const ProgressCallbackList::CallbackType& callback) {
+  return progress_callbacks_.Add(callback);
+}
+
+bool AutoEnrollmentController::ShouldEnrollSilently() {
+  return !CommandLine::ForCurrentProcess()->HasSwitch(
+             chromeos::switches::kEnterpriseEnableForcedReEnrollment) &&
+         state_ == policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT;
+}
+
+void AutoEnrollmentController::OnOwnershipStatusCheckDone(
+    DeviceSettingsService::OwnershipStatus status) {
+  if (status != DeviceSettingsService::OWNERSHIP_NONE) {
+    // The device is already owned. No need for auto-enrollment checks.
+    VLOG(1) << "Device already owned, skipping auto-enrollment check";
+    UpdateState(policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT);
+    return;
+  }
+
+  policy::BrowserPolicyConnector* connector =
+      g_browser_process->browser_policy_connector();
+  policy::DeviceManagementService* service =
+      connector->device_management_service();
+  service->ScheduleInitialization(0);
+
+  int power_initial = GetSanitizedArg(
+      chromeos::switches::kEnterpriseEnrollmentInitialModulus);
+  int power_limit = GetSanitizedArg(
+      chromeos::switches::kEnterpriseEnrollmentModulusLimit);
+  if (power_initial > power_limit) {
+    LOG(ERROR) << "Initial auto-enrollment modulus is larger than the limit, "
+               << "clamping to the limit.";
+    power_initial = power_limit;
+  }
+
+  bool retrieve_device_state = false;
+  std::string device_id;
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          chromeos::switches::kEnterpriseEnableForcedReEnrollment)) {
+    retrieve_device_state = true;
+    device_id =
+        policy::DeviceCloudPolicyManagerChromeOS::GetCurrentDeviceStateKey();
+  } else {
+    device_id = policy::DeviceCloudPolicyManagerChromeOS::GetMachineID();
+  }
+
+  client_.reset(new policy::AutoEnrollmentClient(
+      base::Bind(&AutoEnrollmentController::UpdateState,
+                 base::Unretained(this)),
+      service,
+      g_browser_process->local_state(),
+      g_browser_process->system_request_context(),
+      device_id,
+      retrieve_device_state,
+      power_initial,
+      power_limit));
+
+  VLOG(1) << "Starting auto-enrollment client.";
+  client_->Start();
+}
+
+void AutoEnrollmentController::UpdateState(
+    policy::AutoEnrollmentState new_state) {
+  state_ = new_state;
+  progress_callbacks_.Notify(state_);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h
new file mode 100644
index 0000000..2b48dfd
--- /dev/null
+++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_ENROLLMENT_AUTO_ENROLLMENT_CONTROLLER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_ENROLLMENT_AUTO_ENROLLMENT_CONTROLLER_H_
+
+#include "base/callback_list.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
+
+namespace chromeos {
+
+// Drives the auto-enrollment check, running an AutoEnrollmentClient if
+// appropriate to make a decision.
+class AutoEnrollmentController {
+ public:
+  typedef base::CallbackList<void(policy::AutoEnrollmentState)>
+      ProgressCallbackList;
+
+  AutoEnrollmentController();
+  ~AutoEnrollmentController();
+
+  // Starts the auto-enrollment check.
+  void Start();
+
+  // Stops any pending auto-enrollment checking.
+  void Cancel();
+
+  // Retry checking.
+  void Retry();
+
+  // Registers a callback to invoke on state changes.
+  scoped_ptr<ProgressCallbackList::Subscription> RegisterProgressCallback(
+      const ProgressCallbackList::CallbackType& callback);
+
+  // Checks whether legacy auto-enrollment should be performed.
+  bool ShouldEnrollSilently();
+
+  policy::AutoEnrollmentState state() const { return state_; }
+
+ private:
+  // Callback for the ownership status check.
+  void OnOwnershipStatusCheckDone(
+      DeviceSettingsService::OwnershipStatus status);
+
+  // Sets |state_| and notifies |progress_callbacks_|.
+  void UpdateState(policy::AutoEnrollmentState state);
+
+  policy::AutoEnrollmentState state_;
+  ProgressCallbackList progress_callbacks_;
+
+  base::WeakPtrFactory<AutoEnrollmentController> weak_factory_;
+
+  scoped_ptr<policy::AutoEnrollmentClient> client_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentController);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_ENROLLMENT_AUTO_ENROLLMENT_CONTROLLER_H_
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
index 36f532d..a4f3f9e 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.cc
@@ -42,8 +42,7 @@
     EnrollmentScreenActor* actor)
     : WizardScreen(observer),
       actor_(actor),
-      is_auto_enrollment_(false),
-      can_exit_enrollment_(true),
+      enrollment_mode_(EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL),
       enrollment_failed_once_(false),
       lockbox_init_duration_(0),
       weak_ptr_factory_(this) {
@@ -55,13 +54,13 @@
 
 EnrollmentScreen::~EnrollmentScreen() {}
 
-void EnrollmentScreen::SetParameters(bool is_auto_enrollment,
-                                     bool can_exit_enrollment,
-                                     const std::string& user) {
-  is_auto_enrollment_ = is_auto_enrollment;
-  can_exit_enrollment_ = can_exit_enrollment;
+void EnrollmentScreen::SetParameters(
+    EnrollmentScreenActor::EnrollmentMode enrollment_mode,
+    const std::string& management_domain,
+    const std::string& user) {
+  enrollment_mode_ = enrollment_mode;
   user_ = user.empty() ? user : gaia::CanonicalizeEmail(user);
-  actor_->SetParameters(this, is_auto_enrollment_, can_exit_enrollment, user_);
+  actor_->SetParameters(this, enrollment_mode_, management_domain);
 }
 
 void EnrollmentScreen::PrepareToShow() {
@@ -69,7 +68,7 @@
 }
 
 void EnrollmentScreen::Show() {
-  if (is_auto_enrollment_ && !enrollment_failed_once_) {
+  if (is_auto_enrollment() && !enrollment_failed_once_) {
     actor_->Show();
     UMA(policy::kMetricEnrollmentAutoStarted);
     actor_->ShowEnrollmentSpinnerScreen();
@@ -92,8 +91,8 @@
 void EnrollmentScreen::OnLoginDone(const std::string& user) {
   user_ = gaia::CanonicalizeEmail(user);
 
-  UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoRetried
-                          : policy::kMetricEnrollmentStarted);
+  UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoRetried
+                           : policy::kMetricEnrollmentStarted);
 
   actor_->ShowEnrollmentSpinnerScreen();
   actor_->FetchOAuthToken();
@@ -146,7 +145,7 @@
 }
 
 void EnrollmentScreen::OnCancel() {
-  if (!can_exit_enrollment_) {
+  if (enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_FORCED) {
     actor_->ResetAuth(
         base::Bind(&ScreenObserver::OnExit,
                    base::Unretained(get_screen_observer()),
@@ -154,10 +153,10 @@
     return;
   }
 
-  if (is_auto_enrollment_)
+  if (is_auto_enrollment())
     policy::AutoEnrollmentClient::CancelAutoEnrollment();
-  UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoCancelled
-                          : policy::kMetricEnrollmentCancelled);
+  UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoCancelled
+                           : policy::kMetricEnrollmentCancelled);
   actor_->ResetAuth(
       base::Bind(&ScreenObserver::OnExit,
                  base::Unretained(get_screen_observer()),
@@ -174,7 +173,7 @@
     return;
   }
 
-  if (is_auto_enrollment_ &&
+  if (is_auto_enrollment() &&
       !enrollment_failed_once_ &&
       !user_.empty() &&
       LoginUtils::IsWhitelisted(user_, NULL)) {
@@ -203,12 +202,13 @@
     return;
   }
 
-  policy::DeviceCloudPolicyManagerChromeOS::AllowedDeviceModes modes;
-  modes[policy::DEVICE_MODE_ENTERPRISE] = true;
-  modes[policy::DEVICE_MODE_RETAIL_KIOSK] = !is_auto_enrollment_;
+  policy::DeviceCloudPolicyManagerChromeOS::AllowedDeviceModes device_modes;
+  device_modes[policy::DEVICE_MODE_ENTERPRISE] = true;
+  device_modes[policy::DEVICE_MODE_RETAIL_KIOSK] =
+      enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
   connector->ScheduleServiceInitialization(0);
   connector->GetDeviceCloudPolicyManager()->StartEnrollment(
-      token, is_auto_enrollment_, modes,
+      token, is_auto_enrollment(), device_modes,
       base::Bind(&EnrollmentScreen::ReportEnrollmentStatus,
                  weak_ptr_factory_.GetWeakPtr()));
 }
@@ -222,8 +222,8 @@
   switch (status.status()) {
     case policy::EnrollmentStatus::STATUS_SUCCESS:
       StartupUtils::MarkDeviceRegistered();
-      UMA(is_auto_enrollment_ ? policy::kMetricEnrollmentAutoOK
-                              : policy::kMetricEnrollmentOK);
+      UMA(is_auto_enrollment() ? policy::kMetricEnrollmentAutoOK
+                               : policy::kMetricEnrollmentOK);
       return;
     case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED:
     case policy::EnrollmentStatus::STATUS_POLICY_FETCH_FAILED:
@@ -255,6 +255,9 @@
         case policy::DM_STATUS_SERVICE_DEPROVISIONED:
           UMAFailure(policy::kMetricEnrollmentDeprovisioned);
           return;
+        case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
+          UMAFailure(policy::kMetricEnrollmentDomainMismatch);
+          return;
       }
       break;
     case policy::EnrollmentStatus::STATUS_REGISTRATION_BAD_MODE:
@@ -287,7 +290,7 @@
 }
 
 void EnrollmentScreen::UMAFailure(int sample) {
-  if (is_auto_enrollment_)
+  if (is_auto_enrollment())
     sample = policy::kMetricEnrollmentAutoFailed;
   UMA(sample);
 }
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
index 9738882..64a077d 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen.h
@@ -28,8 +28,8 @@
                    EnrollmentScreenActor* actor);
   virtual ~EnrollmentScreen();
 
-  void SetParameters(bool is_auto_enrollment,
-                     bool can_exit_enrollment,
+  void SetParameters(EnrollmentScreenActor::EnrollmentMode enrollment_mode,
+                     const std::string& management_domain,
                      const std::string& enrollment_user);
 
   // WizardScreen implementation:
@@ -70,9 +70,13 @@
   // Shows the signin screen. Used as a callback to run after auth reset.
   void ShowSigninScreen();
 
+  // Convenience helper to check for auto enrollment mode.
+  bool is_auto_enrollment() const {
+    return enrollment_mode_ == EnrollmentScreenActor::ENROLLMENT_MODE_AUTO;
+  }
+
   EnrollmentScreenActor* actor_;
-  bool is_auto_enrollment_;
-  bool can_exit_enrollment_;
+  EnrollmentScreenActor::EnrollmentMode enrollment_mode_;
   bool enrollment_failed_once_;
   std::string user_;
   int lockbox_init_duration_;
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
index 1430309..84a4863 100644
--- a/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
+++ b/chrome/browser/chromeos/login/enrollment/enrollment_screen_actor.h
@@ -29,6 +29,13 @@
     UI_ERROR_FATAL,
   };
 
+  // Describes the enrollment mode.
+  enum EnrollmentMode {
+    ENROLLMENT_MODE_MANUAL,  // Manually triggered enrollment.
+    ENROLLMENT_MODE_FORCED,  // Forced enrollment, user can't skip.
+    ENROLLMENT_MODE_AUTO,    // Auto-enrollment during first sign-in.
+  };
+
   // This defines the interface for controllers which will be called back when
   // something happens on the UI.
   class Controller {
@@ -47,9 +54,8 @@
 
   // Initializes the actor with parameters.
   virtual void SetParameters(Controller* controller,
-                             bool is_auto_enrollment,
-                             bool can_exit_enrollment,
-                             const std::string& user) = 0;
+                             EnrollmentMode enrollment_mode,
+                             const std::string& management_domain) = 0;
 
   // Prepare the contents to showing.
   virtual void PrepareToShow() = 0;
diff --git a/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h b/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h
index 5687331..aabf892 100644
--- a/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h
+++ b/chrome/browser/chromeos/login/enrollment/mock_enrollment_screen.h
@@ -25,8 +25,10 @@
   MockEnrollmentScreenActor();
   virtual ~MockEnrollmentScreenActor();
 
-  MOCK_METHOD4(SetParameters, void(Controller*, bool, bool,
-                                   const std::string&));
+  MOCK_METHOD3(SetParameters,
+               void(Controller*,
+                    EnrollmentScreenActor::EnrollmentMode,
+                    const std::string&));
   MOCK_METHOD0(PrepareToShow, void());
   MOCK_METHOD0(Show, void());
   MOCK_METHOD0(Hide, void());
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 468f475..08eb483 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -758,6 +758,9 @@
   offline_failed_ = false;
   login_display_->set_signin_completed(true);
 
+  UserManager::Get()->GetUserFlow(user_context.username)->HandleLoginSuccess(
+      user_context);
+
   StopPublicSessionAutoLoginTimer();
 
   bool has_cookies =
diff --git a/chrome/browser/chromeos/login/extended_authenticator.cc b/chrome/browser/chromeos/login/extended_authenticator.cc
index 65fdb10..13acb40 100644
--- a/chrome/browser/chromeos/login/extended_authenticator.cc
+++ b/chrome/browser/chromeos/login/extended_authenticator.cc
@@ -135,6 +135,31 @@
                               success_callback));
 }
 
+void ExtendedAuthenticator::UpdateKeyAuthorized(
+    const UserContext& context,
+    const cryptohome::KeyDefinition& key,
+    const std::string& signature,
+    const base::Closure& success_callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  TransformContext(context,
+                   base::Bind(&ExtendedAuthenticator::DoUpdateKeyAuthorized,
+                              this,
+                              key,
+                              signature,
+                              success_callback));
+}
+
+void ExtendedAuthenticator::RemoveKey(const UserContext& context,
+                                      const std::string& key_to_remove,
+                                      const base::Closure& success_callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  TransformContext(context,
+                   base::Bind(&ExtendedAuthenticator::DoRemoveKey,
+                              this,
+                              key_to_remove,
+                              success_callback));
+}
+
 void ExtendedAuthenticator::DoAuthenticateToMount(
     const HashSuccessCallback& success_callback,
     const UserContext& user_context) {
@@ -172,7 +197,7 @@
   cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
       id,
       auth,
-      base::Bind(&ExtendedAuthenticator::OnCheckKeyComplete,
+      base::Bind(&ExtendedAuthenticator::OnOperationComplete,
                  this,
                  "CheckKeyEx",
                  user_context,
@@ -196,13 +221,59 @@
       auth,
       key,
       replace_existing,
-      base::Bind(&ExtendedAuthenticator::OnAddKeyComplete,
+      base::Bind(&ExtendedAuthenticator::OnOperationComplete,
                  this,
                  "AddKeyEx",
                  user_context,
                  success_callback));
 }
 
+void ExtendedAuthenticator::DoUpdateKeyAuthorized(
+    const cryptohome::KeyDefinition& key,
+    const std::string& signature,
+    const base::Closure& success_callback,
+    const UserContext& user_context) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  RecordStartMarker("UpdateKeyAuthorized");
+
+  std::string canonicalized = gaia::CanonicalizeEmail(user_context.username);
+  cryptohome::Identification id(canonicalized);
+  cryptohome::Authorization auth(user_context.password, user_context.key_label);
+
+  cryptohome::HomedirMethods::GetInstance()->UpdateKeyEx(
+      id,
+      auth,
+      key,
+      signature,
+      base::Bind(&ExtendedAuthenticator::OnOperationComplete,
+                 this,
+                 "UpdateKeyAuthorized",
+                 user_context,
+                 success_callback));
+}
+
+void ExtendedAuthenticator::DoRemoveKey(const std::string& key_to_remove,
+                                        const base::Closure& success_callback,
+                                        const UserContext& user_context) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  RecordStartMarker("RemoveKeyEx");
+
+  std::string canonicalized = gaia::CanonicalizeEmail(user_context.username);
+  cryptohome::Identification id(canonicalized);
+  cryptohome::Authorization auth(user_context.password, user_context.key_label);
+
+  cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
+      id,
+      auth,
+      key_to_remove,
+      base::Bind(&ExtendedAuthenticator::OnOperationComplete,
+                 this,
+                 "RemoveKeyEx",
+                 user_context,
+                 success_callback));
+}
+
 void ExtendedAuthenticator::OnMountComplete(
     const std::string& time_marker,
     const UserContext& user_context,
@@ -220,26 +291,26 @@
     success_callback.Run(mount_hash);
     if (old_consumer_)
       old_consumer_->OnLoginSuccess(copy);
-  } else {
-    AuthState state = FAILED_MOUNT;
-    if (return_code && (cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
-                        cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
-                        cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT)) {
-      state = FAILED_TPM;
-    }
-    if (return_code && cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
-      state = NO_MOUNT;
-    }
-    if (consumer_)
-      consumer_->OnAuthenticationFailure(state);
-    if (old_consumer_) {
-      LoginFailure failure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME);
-      old_consumer_->OnLoginFailure(failure);
-    }
+    return;
+  }
+  AuthState state = FAILED_MOUNT;
+  if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
+      return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
+      return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
+    state = FAILED_TPM;
+  }
+  if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) {
+    state = NO_MOUNT;
+  }
+  if (consumer_)
+    consumer_->OnAuthenticationFailure(state);
+  if (old_consumer_) {
+    LoginFailure failure(LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME);
+    old_consumer_->OnLoginFailure(failure);
   }
 }
 
-void ExtendedAuthenticator::OnCheckKeyComplete(
+void ExtendedAuthenticator::OnOperationComplete(
     const std::string& time_marker,
     const UserContext& user_context,
     const base::Closure& success_callback,
@@ -252,53 +323,26 @@
     success_callback.Run();
     if (old_consumer_)
       old_consumer_->OnLoginSuccess(user_context);
-  } else {
-    AuthState state = FAILED_MOUNT;
-
-    if (return_code && (cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
-                        cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
-                        cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT)) {
-      state = FAILED_TPM;
-    }
-
-    if (return_code && cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST)
-      state = NO_MOUNT;
-
-    if (consumer_)
-      consumer_->OnAuthenticationFailure(state);
-
-    if (old_consumer_) {
-      LoginFailure failure(LoginFailure::UNLOCK_FAILED);
-      old_consumer_->OnLoginFailure(failure);
-    }
+    return;
   }
-}
 
-void ExtendedAuthenticator::OnAddKeyComplete(
-    const std::string& time_marker,
-    const UserContext& user_context,
-    const base::Closure& success_callback,
-    bool success,
-    cryptohome::MountError return_code) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  AuthState state = FAILED_MOUNT;
 
-  RecordEndMarker(time_marker);
-  if (return_code == cryptohome::MOUNT_ERROR_NONE) {
-    success_callback.Run();
-  } else {
-    AuthState state = FAILED_MOUNT;
+  if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
+      return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
+      return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) {
+    state = FAILED_TPM;
+  }
 
-    if (return_code && (cryptohome::MOUNT_ERROR_TPM_COMM_ERROR ||
-                        cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK ||
-                        cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT)) {
-      state = FAILED_TPM;
-    }
+  if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST)
+    state = NO_MOUNT;
 
-    if (return_code && cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST)
-      state = NO_MOUNT;
+  if (consumer_)
+    consumer_->OnAuthenticationFailure(state);
 
-    if (consumer_)
-      consumer_->OnAuthenticationFailure(state);
+  if (old_consumer_) {
+    LoginFailure failure(LoginFailure::UNLOCK_FAILED);
+    old_consumer_->OnLoginFailure(failure);
   }
 }
 
diff --git a/chrome/browser/chromeos/login/extended_authenticator.h b/chrome/browser/chromeos/login/extended_authenticator.h
index a814f8c..ca2124a 100644
--- a/chrome/browser/chromeos/login/extended_authenticator.h
+++ b/chrome/browser/chromeos/login/extended_authenticator.h
@@ -37,6 +37,7 @@
   };
 
   typedef base::Callback<void(const std::string& hash)> HashSuccessCallback;
+  typedef base::Callback<void(const UserContext& context)> ContextCallback;
 
   class AuthStatusConsumer {
    public:
@@ -79,7 +80,7 @@
   void HashPasswordWithSalt(const std::string& password,
                             const HashSuccessCallback& success_callback);
 
-  // Attempts to add new |key| for user identified/authorized by |auth|.
+  // Attempts to add new |key| for user identified/authorized by |context|.
   // If if key with same label already exist, behavior depends on
   // |replace_existing| flag. If flag is set, old key will be replaced. If it
   // is not set, attempt will lead to error.
@@ -89,6 +90,27 @@
               bool replace_existing,
               const base::Closure& success_callback);
 
+  // Attempts to perform an authorized update of the key specified in |context|
+  // with new |key|. Update is authorized by providing |signature| of the key.
+  // Original key should have |PRIV_AUTHORIZED_UPDATE| privilege to perform this
+  // operation. Key label in |context| and in |key| should be the same.
+  void UpdateKeyAuthorized(const UserContext& context,
+                           const cryptohome::KeyDefinition& key,
+                           const std::string& signature,
+                           const base::Closure& success_callback);
+
+  // Attempts to  remove |key_to_remove|-labelled key for user
+  // identified/authorized by |context|. It is possible to remove the key used
+  // for authorization, although it should be done with extreme care.
+  void RemoveKey(const UserContext& context,
+                 const std::string& key_to_remove,
+                 const base::Closure& success_callback);
+
+  // Transforms |user_context| so that it can be used by DoNNN methods.
+  // Currently it consists of hashing password with system salt if needed.
+  void TransformContext(const UserContext& user_context,
+                        const ContextCallback& callback);
+
  private:
   friend class base::RefCountedThreadSafe<ExtendedAuthenticator>;
 
@@ -96,7 +118,6 @@
 
   typedef base::Callback<void(const std::string& system_salt)>
       PendingHashCallback;
-  typedef base::Callback<void(const UserContext& context)> ContextCallback;
 
   // Callback for system salt getter.
   void OnSaltObtained(const std::string& system_salt);
@@ -116,6 +137,13 @@
                 bool replace_existing,
                 const base::Closure& success_callback,
                 const UserContext& context);
+  void DoUpdateKeyAuthorized(const cryptohome::KeyDefinition& key,
+                             const std::string& signature,
+                             const base::Closure& success_callback,
+                             const UserContext& context);
+  void DoRemoveKey(const std::string& key_to_remove,
+                   const base::Closure& success_callback,
+                   const UserContext& context);
 
   // Inner operation callbacks.
   void OnMountComplete(const std::string& time_marker,
@@ -124,16 +152,11 @@
                        bool success,
                        cryptohome::MountError return_code,
                        const std::string& mount_hash);
-  void OnCheckKeyComplete(const std::string& time_marker,
-                          const UserContext& context,
-                          const base::Closure& success_callback,
-                          bool success,
-                          cryptohome::MountError return_code);
-  void OnAddKeyComplete(const std::string& time_marker,
-                        const UserContext& user_context,
-                        const base::Closure& success_callback,
-                        bool success,
-                        cryptohome::MountError return_code);
+  void OnOperationComplete(const std::string& time_marker,
+                           const UserContext& context,
+                           const base::Closure& success_callback,
+                           bool success,
+                           cryptohome::MountError return_code);
 
   // Inner implementation for hashing |password| with system salt. Will queue
   // requests if |system_salt| is not known yet.
@@ -142,11 +165,6 @@
                       const HashSuccessCallback& callback,
                       const std::string& system_salt);
 
-  // Transforms |user_context| so that it can be used by DoNNN methods.
-  // Currently it consists of hashing password with system salt if needed.
-  void TransformContext(const UserContext& user_context,
-                        const ContextCallback& callback);
-
   // Callback from previous method.
   void DidTransformContext(const UserContext& user_context,
                            const ContextCallback& callback,
diff --git a/chrome/browser/chromeos/login/help_app_launcher.h b/chrome/browser/chromeos/login/help_app_launcher.h
index 888cd63..b46c7e9 100644
--- a/chrome/browser/chromeos/login/help_app_launcher.h
+++ b/chrome/browser/chromeos/login/help_app_launcher.h
@@ -36,6 +36,8 @@
     HELP_HOSTED_ACCOUNT = 1054228,
     // Showed as "Learn more" about enterprise enrolled devices.
     HELP_ENTERPRISE = 2535613,
+    // Shown at reset screen as "Learn more" about powerwash/rollback options.
+    HELP_POWERWASH = 183084,
   };
 
   // Parent window is used to show dialog.
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc
index f81a2dd..aa57a5b 100644
--- a/chrome/browser/chromeos/login/kiosk_browsertest.cc
+++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/chromeos/login/mock_user_manager.h"
 #include "chrome/browser/chromeos/login/oobe_base_test.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/test/app_window_waiter.h"
 #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
@@ -227,48 +228,6 @@
 
 }  // namespace
 
-// Helper class that monitors app windows to wait for a window to appear.
-class AppWindowObserver : public apps::AppWindowRegistry::Observer {
- public:
-  AppWindowObserver(apps::AppWindowRegistry* registry,
-                    const std::string& app_id)
-      : registry_(registry), app_id_(app_id), window_(NULL), running_(false) {
-    registry_->AddObserver(this);
-  }
-  virtual ~AppWindowObserver() { registry_->RemoveObserver(this); }
-
-  apps::AppWindow* Wait() {
-    running_ = true;
-    message_loop_runner_ = new content::MessageLoopRunner;
-    message_loop_runner_->Run();
-    EXPECT_TRUE(window_);
-    return window_;
-  }
-
-  // AppWindowRegistry::Observer
-  virtual void OnAppWindowAdded(apps::AppWindow* app_window) OVERRIDE {
-    if (!running_)
-      return;
-
-    if (app_window->extension_id() == app_id_) {
-      window_ = app_window;
-      message_loop_runner_->Quit();
-      running_ = false;
-    }
-  }
-  virtual void OnAppWindowIconChanged(apps::AppWindow* app_window) OVERRIDE {}
-  virtual void OnAppWindowRemoved(apps::AppWindow* app_window) OVERRIDE {}
-
- private:
-  apps::AppWindowRegistry* registry_;
-  std::string app_id_;
-  scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
-  apps::AppWindow* window_;
-  bool running_;
-
-  DISALLOW_COPY_AND_ASSIGN(AppWindowObserver);
-};
-
 class KioskTest : public OobeBaseTest {
  public:
   KioskTest() {
@@ -415,7 +374,7 @@
     apps::AppWindowRegistry* app_window_registry =
         apps::AppWindowRegistry::Get(app_profile);
     apps::AppWindow* window =
-        AppWindowObserver(app_window_registry, test_app_id_).Wait();
+        AppWindowWaiter(app_window_registry, test_app_id_).Wait();
     EXPECT_TRUE(window);
 
     // Login screen should be gone or fading out.
@@ -588,6 +547,39 @@
   RunAppLaunchNetworkDownTest();
 }
 
+// TODO(zelidrag): Figure out why this test is flaky on bbots.
+IN_PROC_BROWSER_TEST_F(KioskTest,
+                       DISABLED_LaunchAppWithNetworkConfigAccelerator) {
+  ScopedCanConfigureNetwork can_configure_network(true, false);
+
+  // Start app launch and wait for network connectivity timeout.
+  StartAppLaunchFromLoginScreen(SimulateNetworkOnlineClosure());
+  OobeScreenWaiter splash_waiter(OobeDisplay::SCREEN_APP_LAUNCH_SPLASH);
+  splash_waiter.Wait();
+
+  // A network error screen should be shown after authenticating.
+  OobeScreenWaiter error_screen_waiter(OobeDisplay::SCREEN_ERROR_MESSAGE);
+  // Simulate Ctrl+Alt+N accelerator.
+  GetLoginUI()->CallJavascriptFunction(
+      "cr.ui.Oobe.handleAccelerator",
+      base::StringValue("app_launch_network_config"));
+  error_screen_waiter.Wait();
+  ASSERT_TRUE(GetAppLaunchController()->showing_network_dialog());
+
+  // Continue button should be visible since we are online.
+  JsExpect("$('continue-network-config-btn').hidden == false");
+
+  // Click on [Continue] button.
+  ASSERT_TRUE(content::ExecuteScript(
+      GetLoginUI()->GetWebContents(),
+      "(function() {"
+      "var e = new Event('click');"
+      "$('continue-network-config-btn').dispatchEvent(e);"
+      "})();"));
+
+  WaitForAppLaunchSuccess();
+}
+
 IN_PROC_BROWSER_TEST_F(KioskTest, LaunchAppNetworkDownConfigureNotAllowed) {
   // Mock network could not be configured.
   ScopedCanConfigureNetwork can_configure_network(false, true);
@@ -1191,7 +1183,7 @@
 
   // Wait for the window to appear.
   apps::AppWindow* window =
-      AppWindowObserver(
+      AppWindowWaiter(
           apps::AppWindowRegistry::Get(ProfileManager::GetPrimaryUserProfile()),
           kTestEnterpriseKioskApp).Wait();
   ASSERT_TRUE(window);
diff --git a/chrome/browser/chromeos/login/login_display_host.h b/chrome/browser/chromeos/login/login_display_host.h
index f045313..9a7a3fc 100644
--- a/chrome/browser/chromeos/login/login_display_host.h
+++ b/chrome/browser/chromeos/login/login_display_host.h
@@ -13,7 +13,6 @@
 #include "base/values.h"
 #include "chrome/browser/chromeos/customization_document.h"
 #include "chrome/browser/chromeos/login/login_display.h"
-#include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
 #include "ui/gfx/native_widget_types.h"
 
 namespace views {
@@ -23,6 +22,7 @@
 namespace chromeos {
 
 class AppLaunchController;
+class AutoEnrollmentController;
 class LoginScreenContext;
 class WebUILoginView;
 class WizardController;
@@ -32,15 +32,6 @@
 // UI implementation (such as LoginDisplay).
 class LoginDisplayHost {
  public:
-  // Callback for RegisterAutoEnrollmentProgressHandler. It is invoked with when
-  // the auto-enrollment check progresses.
-  typedef base::Callback<void(policy::AutoEnrollmentClient::State)>
-      AutoEnrollmentProgressCallback;
-  typedef base::CallbackList<void(policy::AutoEnrollmentClient::State)>
-      AutoEnrollmentProgressCallbackList;
-  typedef AutoEnrollmentProgressCallbackList::Subscription
-      AutoEnrollmentProgressCallbackSubscription;
-
   virtual ~LoginDisplayHost() {}
 
   // Creates UI implementation specific login display instance (views/WebUI).
@@ -70,16 +61,8 @@
   // Toggles status area visibility.
   virtual void SetStatusAreaVisible(bool visible) = 0;
 
-  // Signals the LoginDisplayHost that it can proceed with the Enterprise
-  // Auto-Enrollment checks now.
-  virtual void CheckForAutoEnrollment() = 0;
-
-  // Registers a callback for auto enrollment state changes. The callback will
-  // be invoked synchronously once to report the initial state and then whenever
-  // the state changes until the subscription is dropped.
-  virtual scoped_ptr<AutoEnrollmentProgressCallbackSubscription>
-      RegisterAutoEnrollmentProgressHandler(
-          const AutoEnrollmentProgressCallback& callback) = 0;
+  // Gets the auto-enrollment client.
+  virtual AutoEnrollmentController* GetAutoEnrollmentController() = 0;
 
   // Starts out-of-box-experience flow or shows other screen handled by
   // Wizard controller i.e. camera, recovery.
diff --git a/chrome/browser/chromeos/login/login_display_host_impl.cc b/chrome/browser/chromeos/login/login_display_host_impl.cc
index 3672626..51f6897 100644
--- a/chrome/browser/chromeos/login/login_display_host_impl.cc
+++ b/chrome/browser/chromeos/login/login_display_host_impl.cc
@@ -34,6 +34,7 @@
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
 #include "chrome/browser/chromeos/language_preferences.h"
+#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/input_events_blocker.h"
@@ -275,7 +276,6 @@
 LoginDisplayHostImpl::LoginDisplayHostImpl(const gfx::Rect& background_bounds)
     : background_bounds_(background_bounds),
       pointer_factory_(this),
-      auto_enrollment_state_(policy::AutoEnrollmentClient::STATE_PENDING),
       shutting_down_(false),
       oobe_progress_bar_visible_(false),
       session_starting_(false),
@@ -454,10 +454,8 @@
 }
 
 void LoginDisplayHostImpl::OnCompleteLogin() {
-  // Cancelling the |auto_enrollment_client_| now allows it to determine whether
-  // its protocol finished before login was complete.
-  if (auto_enrollment_client_.get())
-    auto_enrollment_client_.release()->CancelAndDeleteSoon();
+  if (auto_enrollment_controller_)
+    auto_enrollment_controller_->Cancel();
 }
 
 void LoginDisplayHostImpl::OpenProxySettings() {
@@ -472,40 +470,21 @@
     login_view_->SetStatusAreaVisible(visible);
 }
 
-void LoginDisplayHostImpl::CheckForAutoEnrollment() {
-  // This method is called when the controller determines that the
-  // auto-enrollment check can start. This happens either after the EULA is
-  // accepted, or right after a reboot if the EULA has already been accepted.
-
-  if (policy::AutoEnrollmentClient::IsDisabled()) {
-    VLOG(1) << "CheckForAutoEnrollment: auto-enrollment disabled";
-    SetAutoEnrollmentState(policy::AutoEnrollmentClient::STATE_NO_ENROLLMENT);
-    return;
+AutoEnrollmentController* LoginDisplayHostImpl::GetAutoEnrollmentController() {
+  if (!auto_enrollment_controller_) {
+    auto_enrollment_controller_.reset(new AutoEnrollmentController());
+    auto_enrollment_progress_subscription_ =
+        auto_enrollment_controller_->RegisterProgressCallback(
+            base::Bind(&LoginDisplayHostImpl::OnAutoEnrollmentProgress,
+                       base::Unretained(this)));
   }
-
-  // Start by checking if the device has already been owned.
-  pointer_factory_.InvalidateWeakPtrs();
-  DeviceSettingsService::Get()->GetOwnershipStatusAsync(
-      base::Bind(&LoginDisplayHostImpl::OnOwnershipStatusCheckDone,
-                 pointer_factory_.GetWeakPtr()));
-}
-
-scoped_ptr<LoginDisplayHost::AutoEnrollmentProgressCallbackSubscription>
-LoginDisplayHostImpl::RegisterAutoEnrollmentProgressHandler(
-    const AutoEnrollmentProgressCallback& callback) {
-  DCHECK(!callback.is_null());
-
-  scoped_ptr<AutoEnrollmentProgressCallbackSubscription>
-      subscription(auto_enrollment_progress_callbacks_.Add(callback));
-
-  callback.Run(auto_enrollment_state_);
-  return subscription.Pass();
+  return auto_enrollment_controller_.get();
 }
 
 void LoginDisplayHostImpl::StartWizard(
     const std::string& first_screen_name,
     scoped_ptr<base::DictionaryValue> screen_parameters) {
-  startup_sound_honors_spoken_feedback_ = false;
+  startup_sound_honors_spoken_feedback_ = true;
   TryToPlayStartupSound();
 
   // Keep parameters to restore if renderer crashes.
@@ -626,7 +605,10 @@
   // We might be here after a reboot that was triggered after OOBE was complete,
   // so check for auto-enrollment again. This might catch a cached decision from
   // a previous oobe flow, or might start a new check with the server.
-  CheckForAutoEnrollment();
+  if (GetAutoEnrollmentController()->ShouldEnrollSilently())
+    sign_in_controller_->DoAutoEnrollment();
+  else
+    GetAutoEnrollmentController()->Start();
 
   // Initiate mobile config load.
   MobileConfig::GetInstance();
@@ -860,56 +842,14 @@
   layer->SetOpacity(0);
 }
 
-void LoginDisplayHostImpl::OnOwnershipStatusCheckDone(
-    DeviceSettingsService::OwnershipStatus status) {
-  if (status != DeviceSettingsService::OWNERSHIP_NONE) {
-    // The device is already owned. No need for auto-enrollment checks.
-    VLOG(1) << "CheckForAutoEnrollment: device already owned";
-    SetAutoEnrollmentState(policy::AutoEnrollmentClient::STATE_NO_ENROLLMENT);
-    return;
-  }
+void LoginDisplayHostImpl::OnAutoEnrollmentProgress(
+    policy::AutoEnrollmentState state) {
+  VLOG(1) << "OnAutoEnrollmentProgress, state " << state;
 
-  // Kick off the auto-enrollment client.
-  if (auto_enrollment_client_.get()) {
-    // They client might have been started after the EULA screen, but we made
-    // it to the login screen before it finished. In that case let the current
-    // client proceed.
-    //
-    // CheckForAutoEnrollment() is also called when we reach the sign-in screen,
-    // because that's what happens after an auto-update.
-    VLOG(1) << "CheckForAutoEnrollment: client already started";
-
-    // If the client already started and already finished too, pass the decision
-    // to the |sign_in_controller_| now.
-    if (ShouldEnrollSilently())
-      ForceAutoEnrollment();
-  } else {
-    VLOG(1) << "CheckForAutoEnrollment: starting auto-enrollment client";
-    auto_enrollment_client_.reset(policy::AutoEnrollmentClient::Create(
-        base::Bind(&LoginDisplayHostImpl::OnAutoEnrollmentClientProgress,
-                   base::Unretained(this))));
-    auto_enrollment_client_->Start();
-  }
-}
-
-void LoginDisplayHostImpl::OnAutoEnrollmentClientProgress(
-    policy::AutoEnrollmentClient::State state) {
-  VLOG(1) << "OnAutoEnrollmentClientProgress, state " << state;
-  SetAutoEnrollmentState(state);
-
-  if (ShouldEnrollSilently())
-    ForceAutoEnrollment();
-}
-
-void LoginDisplayHostImpl::SetAutoEnrollmentState(
-    policy::AutoEnrollmentClient::State new_state) {
-  auto_enrollment_state_ = new_state;
-  auto_enrollment_progress_callbacks_.Notify(auto_enrollment_state_);
-}
-
-void LoginDisplayHostImpl::ForceAutoEnrollment() {
-  if (sign_in_controller_.get())
+  if (sign_in_controller_ &&
+      auto_enrollment_controller_->ShouldEnrollSilently()) {
     sign_in_controller_->DoAutoEnrollment();
+  }
 }
 
 void LoginDisplayHostImpl::LoadURL(const GURL& url) {
@@ -1088,13 +1028,6 @@
   TryToPlayStartupSound();
 }
 
-bool LoginDisplayHostImpl::ShouldEnrollSilently() {
-  return !CommandLine::ForCurrentProcess()->HasSwitch(
-             chromeos::switches::kEnterpriseEnableForcedReEnrollment) &&
-         auto_enrollment_state_ ==
-             policy::AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT;
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // external
 
diff --git a/chrome/browser/chromeos/login/login_display_host_impl.h b/chrome/browser/chromeos/login/login_display_host_impl.h
index 049da91..984172e 100644
--- a/chrome/browser/chromeos/login/login_display_host_impl.h
+++ b/chrome/browser/chromeos/login/login_display_host_impl.h
@@ -13,7 +13,6 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/login/app_launch_controller.h"
 #include "chrome/browser/chromeos/login/auth_prewarmer.h"
-#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/login_display.h"
 #include "chrome/browser/chromeos/login/login_display_host.h"
@@ -33,12 +32,9 @@
 class WebContents;
 }
 
-namespace policy {
-class AutoEnrollmentClient;
-}  // namespace policy
-
 namespace chromeos {
 
+class DemoAppLauncher;
 class FocusRingController;
 class KeyboardDrivenOobeKeyHandler;
 class OobeUI;
@@ -75,10 +71,7 @@
   virtual void OnCompleteLogin() OVERRIDE;
   virtual void OpenProxySettings() OVERRIDE;
   virtual void SetStatusAreaVisible(bool visible) OVERRIDE;
-  virtual void CheckForAutoEnrollment() OVERRIDE;
-  virtual scoped_ptr<AutoEnrollmentProgressCallbackSubscription>
-      RegisterAutoEnrollmentProgressHandler(
-          const AutoEnrollmentProgressCallback& callback) OVERRIDE;
+  virtual AutoEnrollmentController* GetAutoEnrollmentController() OVERRIDE;
   virtual void StartWizard(
       const std::string& first_screen_name,
       scoped_ptr<base::DictionaryValue> screen_parameters) OVERRIDE;
@@ -153,19 +146,8 @@
   // Schedules fade out animation.
   void ScheduleFadeOutAnimation();
 
-  // Callback for the ownership status check.
-  void OnOwnershipStatusCheckDone(
-      DeviceSettingsService::OwnershipStatus status);
-
-  // Progress callback registered with |auto_enrollment_client_|.
-  void OnAutoEnrollmentClientProgress(
-      policy::AutoEnrollmentClient::State state);
-
-  // Records auto-enrollment progress and notifies subscribers.
-  void SetAutoEnrollmentState(policy::AutoEnrollmentClient::State new_state);
-
-  // Forces auto-enrollment on the appropriate controller.
-  void ForceAutoEnrollment();
+  // Progress callback registered with |auto_enrollment_controller_|.
+  void OnAutoEnrollmentProgress(policy::AutoEnrollmentState state);
 
   // Loads given URL. Creates WebUILoginView if needed.
   void LoadURL(const GURL& url);
@@ -197,9 +179,6 @@
   // Called when login-prompt-visible signal is caught.
   void OnLoginPromptVisible();
 
-  // Checks whether to silently enroll on login.
-  bool ShouldEnrollSilently();
-
   // Used to calculate position of the screens and background.
   gfx::Rect background_bounds_;
 
@@ -207,12 +186,6 @@
 
   base::WeakPtrFactory<LoginDisplayHostImpl> pointer_factory_;
 
-  // Current auto-enrollment check state.
-  policy::AutoEnrollmentClient::State auto_enrollment_state_;
-
-  // Callbacks to notify when auto enrollment client progresses.
-  AutoEnrollmentProgressCallbackList auto_enrollment_progress_callbacks_;
-
   // Default LoginDisplayHost.
   static LoginDisplayHost* default_host_;
 
@@ -228,8 +201,12 @@
   // Demo app launcher.
   scoped_ptr<DemoAppLauncher> demo_app_launcher_;
 
-  // Client for enterprise auto-enrollment check.
-  scoped_ptr<policy::AutoEnrollmentClient> auto_enrollment_client_;
+  // The controller driving the auto-enrollment check.
+  scoped_ptr<AutoEnrollmentController> auto_enrollment_controller_;
+
+  // Subscription for progress callbacks from |auto_enrollement_controller_|.
+  scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
+      auto_enrollment_progress_subscription_;
 
   // Has ShutdownDisplayHost() already been called?  Used to avoid posting our
   // own deletion to the message loop twice if the user logs out while we're
diff --git a/chrome/browser/chromeos/login/login_location_monitor.cc b/chrome/browser/chromeos/login/login_location_monitor.cc
new file mode 100644
index 0000000..c1c528a
--- /dev/null
+++ b/chrome/browser/chromeos/login/login_location_monitor.cc
@@ -0,0 +1,143 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/login_location_monitor.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/chromeos/login/wizard_controller.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/geolocation_provider.h"
+
+namespace chromeos {
+
+namespace {
+
+std::string GeopositionToStringForDebug(const content::Geoposition& pos) {
+  return base::StringPrintf(
+      "latitude=%f, longitude=%f, altitude=%f, accuracy=%f, "
+      "altitude_accuracy=%f, heading=%f, speed=%f",
+      pos.latitude,
+      pos.longitude,
+      pos.altitude,
+      pos.accuracy,
+      pos.altitude_accuracy,
+      pos.heading,
+      pos.speed);
+}
+
+}  // namespace
+
+LoginLocationMonitor::~LoginLocationMonitor() {
+}
+
+// static
+LoginLocationMonitor* LoginLocationMonitor::GetInstance() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  return Singleton<LoginLocationMonitor>::get();
+}
+
+// static
+void LoginLocationMonitor::InstallLocationCallback(
+    const base::TimeDelta timeout) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  LoginLocationMonitor* self = GetInstance();
+
+  self->started_ = base::Time::Now();
+  self->request_timeout_.Start(
+      FROM_HERE,
+      timeout,
+      base::Bind(&LoginLocationMonitor::DoRemoveLocationCallback,
+                 self->on_location_update_));
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&DoInstallLocationCallback, self->on_location_update_));
+}
+
+// static
+void LoginLocationMonitor::RemoveLocationCallback() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  LoginLocationMonitor* self = GetInstance();
+  self->request_timeout_.Stop();
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&DoRemoveLocationCallback, self->on_location_update_));
+}
+
+LoginLocationMonitor::LoginLocationMonitor()
+    : weak_factory_(this),
+      on_location_update_(
+          base::Bind(&LoginLocationMonitor::OnLocationUpdatedIO)) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+}
+
+// static
+void LoginLocationMonitor::DoInstallLocationCallback(
+    content::GeolocationProvider::LocationUpdateCallback callback) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  content::GeolocationProvider* provider =
+      content::GeolocationProvider::GetInstance();
+
+  provider->AddLocationUpdateCallback(callback, false);
+  provider->UserDidOptIntoLocationServices();
+}
+
+// static
+void LoginLocationMonitor::DoRemoveLocationCallback(
+    content::GeolocationProvider::LocationUpdateCallback callback) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  content::GeolocationProvider* provider =
+      content::GeolocationProvider::GetInstance();
+  provider->RemoveLocationUpdateCallback(callback);
+}
+
+void LoginLocationMonitor::OnLocationUpdatedIO(
+    const content::Geoposition& position) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  if (!position.Validate()) {
+    VLOG(1)
+        << "LoginLocationMonitor::OnLocationUpdatedIO(): invalid position: {"
+        << GeopositionToStringForDebug(position) << "}";
+    return;
+  }
+  VLOG(1) << "LoginLocationMonitor::OnLocationUpdatedIO(): valid position: {"
+          << GeopositionToStringForDebug(position) << "}";
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&LoginLocationMonitor::OnLocationUpdatedUI, position));
+}
+
+void LoginLocationMonitor::OnLocationUpdatedUI(
+    const content::Geoposition& position) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(position.Validate());
+
+  LoginLocationMonitor* self = GetInstance();
+
+  if (!self->request_timeout_.IsRunning()) {
+    VLOG(1)
+        << "LoginLocationMonitor::OnLocationUpdatedUI(): Service is stopped: {"
+        << GeopositionToStringForDebug(position) << "}";
+    return;
+  }
+
+  RemoveLocationCallback();
+
+  // We need a cumulative timeout for timezone resolve, that is
+  // (location resolve + timezone resolve). This is used to measure
+  // timeout for the following timezone resolve.
+  const base::TimeDelta elapsed = base::Time::Now() - self->started_;
+
+  WizardController::OnLocationUpdated(position, elapsed);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/login_location_monitor.h b/chrome/browser/chromeos/login/login_location_monitor.h
new file mode 100644
index 0000000..40c8754
--- /dev/null
+++ b/chrome/browser/chromeos/login/login_location_monitor.h
@@ -0,0 +1,58 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_LOCATION_MONITOR_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_LOCATION_MONITOR_H_
+
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "base/memory/weak_ptr.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "content/public/browser/geolocation_provider.h"
+
+namespace chromeos {
+
+// This class does one-time Geoposition resolve for OOBE.
+// It stops after first valid position received or when timeout occurs.
+// Valid position is sent to WizardController to resolve timezone.
+class LoginLocationMonitor {
+ public:
+  ~LoginLocationMonitor();
+
+  // Called on UI thread.
+  static void InstallLocationCallback(const base::TimeDelta timeout);
+  static void RemoveLocationCallback();
+
+ private:
+  friend struct DefaultSingletonTraits<LoginLocationMonitor>;
+  friend class Singleton<chromeos::LoginLocationMonitor>;
+
+  LoginLocationMonitor();
+
+  // Called on UI thread.
+  static LoginLocationMonitor* GetInstance();
+
+  // Called on IO thread.
+  static void DoInstallLocationCallback(
+      content::GeolocationProvider::LocationUpdateCallback callback);
+  static void DoRemoveLocationCallback(
+      content::GeolocationProvider::LocationUpdateCallback callback);
+
+  // OnLocationUpdated comes on IO thread and should be passed to UI thread.
+  static void OnLocationUpdatedIO(const content::Geoposition& position);
+  static void OnLocationUpdatedUI(const content::Geoposition& position);
+
+  base::WeakPtrFactory<LoginLocationMonitor> weak_factory_;
+  content::GeolocationProvider::LocationUpdateCallback on_location_update_;
+  base::OneShotTimer<LoginLocationMonitor> request_timeout_;
+
+  base::Time started_;
+
+  DISALLOW_COPY_AND_ASSIGN(LoginLocationMonitor);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_LOGIN_LOCATION_MONITOR_H_
diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc
index 7c5d962..1fd20d1 100644
--- a/chrome/browser/chromeos/login/login_performer.cc
+++ b/chrome/browser/chromeos/login/login_performer.cc
@@ -302,13 +302,13 @@
                  username));
 }
 
-void LoginPerformer::LoginAsKioskAccount(
-    const std::string& app_user_id, bool force_ephemeral) {
+void LoginPerformer::LoginAsKioskAccount(const std::string& app_user_id,
+                                         bool use_guest_mount) {
   authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
       base::Bind(&Authenticator::LoginAsKioskAccount, authenticator_.get(),
-                 app_user_id, force_ephemeral));
+                 app_user_id, use_guest_mount));
 }
 
 void LoginPerformer::RecoverEncryptedData(const std::string& old_password) {
diff --git a/chrome/browser/chromeos/login/login_performer.h b/chrome/browser/chromeos/login/login_performer.h
index 293a4cb..aa9884a 100644
--- a/chrome/browser/chromeos/login/login_performer.h
+++ b/chrome/browser/chromeos/login/login_performer.h
@@ -85,7 +85,7 @@
 
   // Performs a login into the kiosk mode account with |app_user_id|.
   void LoginAsKioskAccount(const std::string& app_user_id,
-                           bool force_ephemeral);
+                           bool use_guest_mount);
 
   // Migrates cryptohome using |old_password| specified.
   void RecoverEncryptedData(const std::string& old_password);
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc
index ebe1dd4..2ae990b 100644
--- a/chrome/browser/chromeos/login/login_utils.cc
+++ b/chrome/browser/chromeos/login/login_utils.cc
@@ -47,6 +47,7 @@
 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
 #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
 #include "chrome/browser/chromeos/login/screen_locker.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
@@ -415,10 +416,9 @@
   delegate_ = delegate;
   InitSessionRestoreStrategy();
 
-  base::FilePath profile_dir;
   if (DemoAppLauncher::IsDemoAppSession(user_context.username)) {
     g_browser_process->profile_manager()->CreateProfileAsync(
-        ProfileManager::GetGuestProfilePath(),
+        user_manager->GetUserProfileDir(user_context.username),
         base::Bind(&LoginUtilsImpl::OnOTRProfileCreated, AsWeakPtr(),
                    user_context.username),
         base::string16(), base::string16(), std::string());
@@ -712,9 +712,11 @@
   // flag. We keep only some of the arguments of this process.
   const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
   CommandLine command_line(browser_command_line.GetProgram());
-  std::string cmd_line_str = GetOffTheRecordCommandLine(start_url,
-                                                        browser_command_line,
-                                                        &command_line);
+  std::string cmd_line_str =
+      GetOffTheRecordCommandLine(start_url,
+                                 StartupUtils::IsOobeCompleted(),
+                                 browser_command_line,
+                                 &command_line);
 
   RestartChrome(cmd_line_str);
 }
@@ -919,6 +921,7 @@
 // static
 void LoginUtils::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kFactoryResetRequested, false);
+  registry->RegisterBooleanPref(prefs::kRollbackRequested, false);
   registry->RegisterStringPref(prefs::kRLZBrand, std::string());
   registry->RegisterBooleanPref(prefs::kRLZDisabled, false);
 }
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_constants.cc b/chrome/browser/chromeos/login/managed/locally_managed_user_constants.cc
index 53a5d84..99bb39a 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_constants.cc
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_constants.cc
@@ -4,11 +4,20 @@
 
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
 
+#include "chromeos/cryptohome/cryptohome_parameters.h"
+
 namespace chromeos {
 
 const char kManagedUserTokenFilename[] = "token";
 
 const char kCryptohomeManagedUserKeyLabel[] = "managed";
 const char kCryptohomeMasterKeyLabel[] = "master";
+const char kLegacyCryptohomeManagedUserKeyLabel[] = "default-0";
+const char kLegacyCryptohomeMasterKeyLabel[] = "default-1";
+
+const int kCryptohomeManagedUserKeyPrivileges =
+    cryptohome::PRIV_AUTHORIZED_UPDATE | cryptohome::PRIV_MOUNT;
+const int kCryptohomeManagedUserIncompleteKeyPrivileges =
+    cryptohome::PRIV_MIGRATE | cryptohome::PRIV_MOUNT;
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_constants.h b/chrome/browser/chromeos/login/managed/locally_managed_user_constants.h
index 0fd9d0c..f7e6af8 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_constants.h
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_constants.h
@@ -13,6 +13,18 @@
 
 extern const char kCryptohomeManagedUserKeyLabel[];
 extern const char kCryptohomeMasterKeyLabel[];
+extern const char kLegacyCryptohomeManagedUserKeyLabel[];
+extern const char kLegacyCryptohomeMasterKeyLabel[];
+
+// Set of privileges for usual Managed User : Mount and UpdatePrivileged
+// (update with signed key).
+extern const int kCryptohomeManagedUserKeyPrivileges;
+
+// Set of privileges for corner case when pre-M35 managed user got new password.
+// As we don't have signature yet, Migrate is used instead of UpdatePrivileged.
+// Privileges are reset to kCryptohomeManagedUserKeyPrivileges as soon as
+// manager signs in on the machine.
+extern const int kCryptohomeManagedUserIncompleteKeyPrivileges;
 
 }  // namespace chromeos
 
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.cc b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.cc
index 7e5f388..1244e6d 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.cc
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.cc
@@ -75,6 +75,9 @@
   return true;
 }
 
+void LocallyManagedUserCreationFlow::HandleLoginSuccess(
+    const UserContext& context) {}
+
 bool LocallyManagedUserCreationFlow::HandlePasswordChangeDetected() {
   GetScreen(host())->ShowManagerInconsistentStateErrorScreen();
   return true;
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.h b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.h
index 1cd7651..1d017fc 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.h
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.h
@@ -25,6 +25,7 @@
   virtual bool ShouldLaunchBrowser() OVERRIDE;
   virtual bool ShouldSkipPostLoginScreens() OVERRIDE;
   virtual bool HandleLoginFailure(const LoginFailure& failure) OVERRIDE;
+  virtual void HandleLoginSuccess(const UserContext& context) OVERRIDE;
   virtual bool HandlePasswordChangeDetected() OVERRIDE;
   virtual void HandleOAuthTokenStatusChange(User::OAuthTokenStatus status)
       OVERRIDE;
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc
index d68cba8..f44f6fd 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.cc
@@ -90,8 +90,7 @@
       last_page_(kNameOfIntroScreen),
       image_decoder_(NULL),
       apply_photo_after_decoding_(false),
-      selected_image_(0),
-      was_camera_present_(false) {
+      selected_image_(0) {
   DCHECK(actor_);
   if (actor_)
     actor_->SetDelegate(this);
@@ -444,21 +443,10 @@
   ApplyPicture();
 }
 
-void LocallyManagedUserCreationScreen::CheckCameraPresence() {
-  CameraDetector::StartPresenceCheck(
-      base::Bind(&LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone() {
-  bool is_camera_present = CameraDetector::camera_presence() ==
-                           CameraDetector::kCameraPresent;
-  if (actor_) {
-    if (is_camera_present != was_camera_present_) {
-      actor_->SetCameraPresent(is_camera_present);
-      was_camera_present_ = is_camera_present;
-    }
-  }
+void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone(
+    bool is_camera_present) {
+  if (actor_)
+    actor_->SetCameraPresent(is_camera_present);
 }
 
 void LocallyManagedUserCreationScreen::OnGetManagedUsers(
diff --git a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h
index b443590..4b31f34 100644
--- a/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h
+++ b/chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h
@@ -99,7 +99,7 @@
   // It should be removed by issue 251179.
 
   // LocallyManagedUserCreationScreenHandler::Delegate (image) implementation:
-  virtual void CheckCameraPresence() OVERRIDE;
+  virtual void OnCameraPresenceCheckDone(bool is_camera_present) OVERRIDE;
   virtual void OnPhotoTaken(const std::string& raw_data) OVERRIDE;
   virtual void OnImageSelected(const std::string& image_url,
                                const std::string& image_type) OVERRIDE;
@@ -111,7 +111,6 @@
 
  private:
   void ApplyPicture();
-  void OnCameraPresenceCheckDone();
   void OnGetManagedUsers(const base::DictionaryValue* users);
 
   base::WeakPtrFactory<LocallyManagedUserCreationScreen> weak_factory_;
@@ -128,9 +127,6 @@
   bool apply_photo_after_decoding_;
   int selected_image_;
 
-  // True if camera was available last time.
-  bool was_camera_present_;
-
   DISALLOW_COPY_AND_ASSIGN(LocallyManagedUserCreationScreen);
 };
 
diff --git a/chrome/browser/chromeos/login/managed/managed_user_creation_controller_new.cc b/chrome/browser/chromeos/login/managed/managed_user_creation_controller_new.cc
index 4b5282e..b2eee45 100644
--- a/chrome/browser/chromeos/login/managed/managed_user_creation_controller_new.cc
+++ b/chrome/browser/chromeos/login/managed/managed_user_creation_controller_new.cc
@@ -210,11 +210,9 @@
 
   // First is plain text password, hashed and salted with individual salt.
   // It can be used for mounting homedir, and can be replaced only when signed.
-  cryptohome::KeyDefinition password_key(
-      creation_context_->salted_password,
-      kCryptohomeManagedUserKeyLabel,
-      static_cast<cryptohome::AuthKeyPrivileges>(
-          cryptohome::PRIV_AUTHORIZED_UPDATE | cryptohome::PRIV_MOUNT));
+  cryptohome::KeyDefinition password_key(creation_context_->salted_password,
+                                         kCryptohomeManagedUserKeyLabel,
+                                         kCryptohomeManagedUserKeyPrivileges);
   base::Base64Decode(creation_context_->encryption_key,
                      &password_key.encryption_key);
   base::Base64Decode(creation_context_->signature_key,
diff --git a/chrome/browser/chromeos/login/managed/supervised_user_authentication.cc b/chrome/browser/chromeos/login/managed/supervised_user_authentication.cc
index a36b4f9..a9b92cb 100644
--- a/chrome/browser/chromeos/login/managed/supervised_user_authentication.cc
+++ b/chrome/browser/chromeos/login/managed/supervised_user_authentication.cc
@@ -7,14 +7,19 @@
 #include "base/base64.h"
 #include "base/command_line.h"
 #include "base/json/json_file_value_serializer.h"
+#include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
+#include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chromeos/chromeos_switches.h"
+#include "chromeos/cryptohome/signed_secret.pb.h"
+#include "content/public/browser/browser_thread.h"
+#include "crypto/hmac.h"
 #include "crypto/random.h"
 #include "crypto/symmetric_key.h"
 
@@ -25,11 +30,15 @@
 // Byte size of hash salt.
 const unsigned kSaltSize = 32;
 
-// Parameters of cryptographic hashing.
+// Parameters of cryptographic hashing for new user schema.
 const unsigned kNumIterations = 1234;
 const unsigned kKeySizeInBits = 256;
 
+// Size of key signature.
 const unsigned kHMACKeySizeInBits = 256;
+const int kSignatureLength = 32;
+
+// Size of master key (in bytes).
 const int kMasterKeySize = 32;
 
 std::string CreateSalt() {
@@ -66,12 +75,59 @@
 std::string BuildPasswordSignature(const std::string& password,
                                    int revision,
                                    const std::string& base64_signature_key) {
-  std::string raw_result, result;
-  // TODO(antrim) : implement signature as soon as wad@ lands sample code.
+  ac::chrome::managedaccounts::account::Secret secret;
+  secret.set_revision(revision);
+  secret.set_secret(password);
+  std::string buffer;
+  if (!secret.SerializeToString(&buffer))
+    LOG(FATAL) << "Protobuf::SerializeToString failed";
+  std::string signature_key;
+  base::Base64Decode(base64_signature_key, &signature_key);
+
+  crypto::HMAC hmac(crypto::HMAC::SHA256);
+  if (!hmac.Init(signature_key))
+    LOG(FATAL) << "HMAC::Init failed";
+
+  unsigned char out_bytes[kSignatureLength];
+  if (!hmac.Sign(buffer, out_bytes, sizeof(out_bytes)))
+    LOG(FATAL) << "HMAC::Sign failed";
+
+  std::string raw_result(out_bytes, out_bytes + sizeof(out_bytes));
+
+  std::string result;
   base::Base64Encode(raw_result, &result);
   return result;
 }
 
+base::DictionaryValue* LoadPasswordData(base::FilePath profile_dir) {
+  JSONFileValueSerializer serializer(profile_dir.Append(kPasswordUpdateFile));
+  std::string error_message;
+  int error_code;
+  scoped_ptr<base::Value> value(
+      serializer.Deserialize(&error_code, &error_message));
+  if (JSONFileValueSerializer::JSON_NO_ERROR != error_code) {
+    return NULL;
+  }
+  base::DictionaryValue* result;
+  if (!value->GetAsDictionary(&result)) {
+    return NULL;
+  }
+  value.Pass();
+  return result;
+}
+
+void OnPasswordDataLoaded(
+    const SupervisedUserAuthentication::PasswordDataCallback& success_callback,
+    const base::Closure& failure_callback,
+    base::DictionaryValue* value) {
+  if (!value) {
+    failure_callback.Run();
+    return;
+  }
+  success_callback.Run(value);
+  delete value;
+}
+
 }  // namespace
 
 SupervisedUserAuthentication::SupervisedUserAuthentication(
@@ -236,12 +292,67 @@
   base::FilePath profile_path = ProfileHelper::GetProfilePathByUserIdHash(
       user->username_hash());
   JSONFileValueSerializer serializer(profile_path.Append(kPasswordUpdateFile));
-  if (!serializer.Serialize(*password_data))
+  if (!serializer.Serialize(*password_data)) {
+    LOG(ERROR) << "Failed to schedule password update for supervised user "
+               << supervised_user_id;
+    UMA_HISTOGRAM_ENUMERATION(
+        "ManagedUsers.ChromeOS.PasswordChange",
+        SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_STORE_DATA,
+        SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
     return;
+  }
   base::DictionaryValue holder;
   owner_->GetPasswordInformation(supervised_user_id, &holder);
   holder.SetBoolean(kRequirePasswordUpdate, true);
   owner_->SetPasswordInformation(supervised_user_id, &holder);
 }
 
+bool SupervisedUserAuthentication::HasScheduledPasswordUpdate(
+    const std::string& user_id) {
+  base::DictionaryValue holder;
+  owner_->GetPasswordInformation(user_id, &holder);
+  bool require_update = false;
+  holder.GetBoolean(kRequirePasswordUpdate, &require_update);
+  return require_update;
+}
+
+void SupervisedUserAuthentication::ClearScheduledPasswordUpdate(
+    const std::string& user_id) {
+  base::DictionaryValue holder;
+  owner_->GetPasswordInformation(user_id, &holder);
+  holder.SetBoolean(kRequirePasswordUpdate, false);
+  owner_->SetPasswordInformation(user_id, &holder);
+}
+
+bool SupervisedUserAuthentication::HasIncompleteKey(
+    const std::string& user_id) {
+  base::DictionaryValue holder;
+  owner_->GetPasswordInformation(user_id, &holder);
+  bool incomplete_key = false;
+  holder.GetBoolean(kHasIncompleteKey, &incomplete_key);
+  return incomplete_key;
+}
+
+void SupervisedUserAuthentication::MarkKeyIncomplete(
+    const std::string& user_id) {
+  base::DictionaryValue holder;
+  owner_->GetPasswordInformation(user_id, &holder);
+  holder.SetBoolean(kHasIncompleteKey, true);
+  owner_->SetPasswordInformation(user_id, &holder);
+}
+
+void SupervisedUserAuthentication::LoadPasswordUpdateData(
+    const std::string& user_id,
+    const PasswordDataCallback& success_callback,
+    const base::Closure& failure_callback) {
+  const User* user = UserManager::Get()->FindUser(user_id);
+  base::FilePath profile_path =
+      ProfileHelper::GetProfilePathByUserIdHash(user->username_hash());
+  PostTaskAndReplyWithResult(
+      content::BrowserThread::GetBlockingPool(),
+      FROM_HERE,
+      base::Bind(&LoadPasswordData, profile_path),
+      base::Bind(&OnPasswordDataLoaded, success_callback, failure_callback));
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/managed/supervised_user_authentication.h b/chrome/browser/chromeos/login/managed/supervised_user_authentication.h
index b9bf6b0..f494ed6 100644
--- a/chrome/browser/chromeos/login/managed/supervised_user_authentication.h
+++ b/chrome/browser/chromeos/login/managed/supervised_user_authentication.h
@@ -39,9 +39,16 @@
     PASSWORD_CHANGE_FAILED_NO_SIGNATURE_KEY = 3,
     PASSWORD_CHANGE_FAILED_NO_PASSWORD_DATA = 4,
     PASSWORD_CHANGE_FAILED_MASTER_KEY_FAILURE = 5,
-    PASSWORD_CHANGE_RESULT_MAX_VALUE = 6
+    PASSWORD_CHANGE_FAILED_LOADING_DATA = 6,
+    PASSWORD_CHANGE_FAILED_INCOMPLETE_DATA = 7,
+    PASSWORD_CHANGE_FAILED_AUTHENTICATION_FAILURE = 8,
+    PASSWORD_CHANGE_FAILED_STORE_DATA = 9,
+    PASSWORD_CHANGE_RESULT_MAX_VALUE = 10
   };
 
+  typedef base::Callback<void(const base::DictionaryValue* password_data)>
+      PasswordDataCallback;
+
   explicit SupervisedUserAuthentication(SupervisedUserManager* owner);
   virtual ~SupervisedUserAuthentication();
 
@@ -56,12 +63,6 @@
   // Transforms password according to schema specified in Local State.
   UserContext TransformPasswordInContext(const UserContext& context);
 
-  // Schedules password migration for |user_id| with |password| as a plain text
-  // password. Migration should happen during |user_login_flow|.
-  void SchedulePasswordMigration(const std::string& user_id,
-                                 const std::string& password,
-                                 SupervisedUserLoginFlow* user_login_flow);
-
   // Fills |password_data| with |password|-specific data for |user_id|,
   // depending on target schema. Does not affect Local State.
   bool FillDataForNewUser(const std::string& user_id,
@@ -77,11 +78,26 @@
   bool NeedPasswordChange(const std::string& user_id,
                           const base::DictionaryValue* password_data);
 
+  // Checks if given user should update password upon signin.
+  bool HasScheduledPasswordUpdate(const std::string& user_id);
+  void ClearScheduledPasswordUpdate(const std::string& user_id);
+
+  // Checks if password was migrated to new schema by supervised user.
+  // In this case it does not have encryption key, and should be updated by
+  // manager even if password versions match.
+  bool HasIncompleteKey(const std::string& user_id);
+  void MarkKeyIncomplete(const std::string& user_id);
+
+  // Loads password data stored by ScheduleSupervisedPasswordChange.
+  void LoadPasswordUpdateData(const std::string& user_id,
+                              const PasswordDataCallback& success_callback,
+                              const base::Closure& failure_callback);
+
   // Creates a random string that can be used as a master key for managed
   // user's homedir.
   std::string GenerateMasterKey();
 
-  // Called by supervised user
+  // Called by supervised user to store password data for migration upon signin.
   void ScheduleSupervisedPasswordChange(
       const std::string& supervised_user_id,
       const base::DictionaryValue* password_data);
diff --git a/chrome/browser/chromeos/login/managed/supervised_user_login_flow.cc b/chrome/browser/chromeos/login/managed/supervised_user_login_flow.cc
index 24be34e..d28681f 100644
--- a/chrome/browser/chromeos/login/managed/supervised_user_login_flow.cc
+++ b/chrome/browser/chromeos/login/managed/supervised_user_login_flow.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/chromeos/login/managed/supervised_user_login_flow.h"
 
+#include "base/base64.h"
 #include "base/logging.h"
+#include "base/metrics/histogram.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/values.h"
@@ -12,6 +14,7 @@
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_constants.h"
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
+#include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
@@ -68,7 +71,175 @@
   // See also: http://crbug.com/312751
   UserManager::Get()->GetSupervisedUserManager()->ConfigureSyncWithToken(
       profile_, token);
+  SupervisedUserAuthentication* auth =
+      UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
 
+  if (auth->HasScheduledPasswordUpdate(user_id())) {
+    auth->LoadPasswordUpdateData(
+        user_id(),
+        base::Bind(&SupervisedUserLoginFlow::OnPasswordChangeDataLoaded,
+                   weak_factory_.GetWeakPtr()),
+        base::Bind(&SupervisedUserLoginFlow::OnPasswordChangeDataLoadFailed,
+                   weak_factory_.GetWeakPtr()));
+    return;
+  }
+  Finish();
+}
+
+void SupervisedUserLoginFlow::HandleLoginSuccess(
+    const UserContext& login_context) {
+  context_.CopyFrom(login_context);
+}
+
+void SupervisedUserLoginFlow::OnPasswordChangeDataLoaded(
+    const base::DictionaryValue* password_data) {
+  // Edge case, when manager has signed in and already updated the password.
+  SupervisedUserAuthentication* auth =
+      UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
+  if (!auth->NeedPasswordChange(user_id(), password_data)) {
+    VLOG(1) << "Password already changed for " << user_id();
+    auth->ClearScheduledPasswordUpdate(user_id());
+    Finish();
+    return;
+  }
+
+  // Two cases now - we can currently have either old-style password, or new
+  // password.
+  std::string base64_signature;
+  std::string signature;
+  std::string password;
+  int revision = 0;
+  int schema = 0;
+  bool success = password_data->GetStringWithoutPathExpansion(
+      kPasswordSignatureKey, &base64_signature);
+  success &= password_data->GetIntegerWithoutPathExpansion(kPasswordRevision,
+                                                           &revision);
+  success &=
+      password_data->GetIntegerWithoutPathExpansion(kSchemaVersion, &schema);
+  success &= password_data->GetStringWithoutPathExpansion(kEncryptedPassword,
+                                                          &password);
+  if (!success) {
+    LOG(ERROR) << "Incomplete data for password change";
+
+    UMA_HISTOGRAM_ENUMERATION(
+        "ManagedUsers.ChromeOS.PasswordChange",
+        SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_INCOMPLETE_DATA,
+        SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
+    Finish();
+    return;
+  }
+  base::Base64Decode(base64_signature, &signature);
+  scoped_ptr<base::DictionaryValue> data_copy(password_data->DeepCopy());
+  cryptohome::KeyDefinition key(password,
+                                kCryptohomeManagedUserKeyLabel,
+                                kCryptohomeManagedUserKeyPrivileges);
+
+  authenticator_ = new ExtendedAuthenticator(this);
+  SupervisedUserAuthentication::Schema current_schema =
+      auth->GetPasswordSchema(user_id());
+
+  key.revision = revision;
+
+  if (SupervisedUserAuthentication::SCHEMA_PLAIN == current_schema) {
+    // We need to add new key, and block old one. As we don't actually have
+    // signature key, use Migrate privilege instead of AuthorizedUpdate.
+    key.privileges = kCryptohomeManagedUserIncompleteKeyPrivileges;
+
+    VLOG(1) << "Adding new schema key";
+    DCHECK_EQ(context_.key_label, std::string());
+    authenticator_->AddKey(context_,
+                           key,
+                           false /* no key exists */,
+                           base::Bind(&SupervisedUserLoginFlow::OnNewKeyAdded,
+                                      weak_factory_.GetWeakPtr(),
+                                      Passed(&data_copy)));
+  } else if (SupervisedUserAuthentication::SCHEMA_PLAIN == current_schema) {
+    VLOG(1) << "Updating the key";
+
+    if (auth->HasIncompleteKey(user_id())) {
+      // We need to use Migrate instead of Authorized Update privilege.
+      key.privileges = kCryptohomeManagedUserIncompleteKeyPrivileges;
+    }
+
+    // Just update the key.
+    DCHECK_EQ(context_.key_label, kCryptohomeManagedUserKeyLabel);
+    authenticator_->UpdateKeyAuthorized(
+        context_,
+        key,
+        signature,
+        base::Bind(&SupervisedUserLoginFlow::OnPasswordUpdated,
+                   weak_factory_.GetWeakPtr(),
+                   Passed(&data_copy)));
+  } else {
+    NOTREACHED() << "Unsupported password schema";
+  }
+}
+
+void SupervisedUserLoginFlow::OnNewKeyAdded(
+    scoped_ptr<base::DictionaryValue> password_data) {
+  VLOG(1) << "New key added";
+  SupervisedUserAuthentication* auth =
+      UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
+  auth->StorePasswordData(user_id(), *password_data.get());
+  auth->MarkKeyIncomplete(user_id());
+  authenticator_->RemoveKey(
+      context_,
+      kLegacyCryptohomeManagedUserKeyLabel,
+      base::Bind(&SupervisedUserLoginFlow::OnOldKeyRemoved,
+                 weak_factory_.GetWeakPtr()));
+}
+
+void SupervisedUserLoginFlow::OnOldKeyRemoved() {
+  UMA_HISTOGRAM_ENUMERATION(
+      "ManagedUsers.ChromeOS.PasswordChange",
+      SupervisedUserAuthentication::PASSWORD_CHANGED_IN_USER_SESSION,
+      SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
+  Finish();
+}
+
+void SupervisedUserLoginFlow::OnPasswordChangeDataLoadFailed() {
+  LOG(ERROR) << "Could not load data for password change";
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "ManagedUsers.ChromeOS.PasswordChange",
+      SupervisedUserAuthentication::PASSWORD_CHANGE_FAILED_LOADING_DATA,
+      SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
+  Finish();
+}
+
+void SupervisedUserLoginFlow::OnAuthenticationFailure(
+    ExtendedAuthenticator::AuthState state) {
+  LOG(ERROR) << "Authentication error during password change";
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "ManagedUsers.ChromeOS.PasswordChange",
+      SupervisedUserAuthentication::
+          PASSWORD_CHANGE_FAILED_AUTHENTICATION_FAILURE,
+      SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
+  Finish();
+}
+
+void SupervisedUserLoginFlow::OnPasswordUpdated(
+    scoped_ptr<base::DictionaryValue> password_data) {
+  VLOG(1) << "Updated password for supervised user";
+
+  SupervisedUserAuthentication* auth =
+      UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
+
+  // Incomplete state is not there in password_data, carry it from old state.
+  bool was_incomplete = auth->HasIncompleteKey(user_id());
+  auth->StorePasswordData(user_id(), *password_data.get());
+  if (was_incomplete)
+    auth->MarkKeyIncomplete(user_id());
+
+  UMA_HISTOGRAM_ENUMERATION(
+      "ManagedUsers.ChromeOS.PasswordChange",
+      SupervisedUserAuthentication::PASSWORD_CHANGED_IN_USER_SESSION,
+      SupervisedUserAuthentication::PASSWORD_CHANGE_RESULT_MAX_VALUE);
+  Finish();
+}
+
+void SupervisedUserLoginFlow::Finish() {
   LoginUtils::Get()->DoBrowserLaunch(profile_, host());
   profile_ = NULL;
   UnregisterFlowSoon();
diff --git a/chrome/browser/chromeos/login/managed/supervised_user_login_flow.h b/chrome/browser/chromeos/login/managed/supervised_user_login_flow.h
index 32098d0..f14608d 100644
--- a/chrome/browser/chromeos/login/managed/supervised_user_login_flow.h
+++ b/chrome/browser/chromeos/login/managed/supervised_user_login_flow.h
@@ -9,35 +9,50 @@
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/chromeos/login/extended_authenticator.h"
 #include "chrome/browser/chromeos/login/user_flow.h"
 
 namespace chromeos {
 
 // UserFlow implementation for signing in locally managed user.
-class SupervisedUserLoginFlow : public ExtendedUserFlow {
+class SupervisedUserLoginFlow
+    : public ExtendedUserFlow,
+      public ExtendedAuthenticator::AuthStatusConsumer {
  public:
   explicit SupervisedUserLoginFlow(const std::string& user_id);
   virtual ~SupervisedUserLoginFlow();
 
-  // Registers flow preferences.
-  //  static void RegisterPrefs(PrefRegistrySimple* registry);
-
+  // ExtendedUserFlow overrides.
   virtual bool CanLockScreen() OVERRIDE;
   virtual bool ShouldLaunchBrowser() OVERRIDE;
   virtual bool ShouldSkipPostLoginScreens() OVERRIDE;
   virtual bool HandleLoginFailure(const LoginFailure& failure) OVERRIDE;
+  virtual void HandleLoginSuccess(const UserContext& context) OVERRIDE;
   virtual bool HandlePasswordChangeDetected() OVERRIDE;
   virtual void HandleOAuthTokenStatusChange(User::OAuthTokenStatus status)
       OVERRIDE;
   virtual void LaunchExtraSteps(Profile* profile) OVERRIDE;
 
-  virtual void OnSyncSetupDataLoaded(const std::string& token);
-  virtual void ConfigureSync(const std::string& token);
+  // ExtendedAuthenticator::AuthStatusConsumer overrides.
+  virtual void OnAuthenticationFailure(ExtendedAuthenticator::AuthState state)
+      OVERRIDE;
 
  private:
   void Launch();
+  void Finish();
+
+  void OnSyncSetupDataLoaded(const std::string& token);
+  void ConfigureSync(const std::string& token);
+  void OnPasswordChangeDataLoaded(const base::DictionaryValue* password_data);
+  void OnPasswordChangeDataLoadFailed();
+  void OnNewKeyAdded(scoped_ptr<base::DictionaryValue> password_data);
+  void OnOldKeyRemoved();
+  void OnPasswordUpdated(scoped_ptr<base::DictionaryValue> password_data);
+
+  scoped_refptr<ExtendedAuthenticator> authenticator_;
 
   bool data_loaded_;
+  UserContext context_;
   Profile* profile_;
   base::WeakPtrFactory<SupervisedUserLoginFlow> weak_factory_;
 
diff --git a/chrome/browser/chromeos/login/mock_authenticator.cc b/chrome/browser/chromeos/login/mock_authenticator.cc
index 4fa4ee4..dda4670 100644
--- a/chrome/browser/chromeos/login/mock_authenticator.cc
+++ b/chrome/browser/chromeos/login/mock_authenticator.cc
@@ -61,8 +61,8 @@
                                         expected_username_));
 }
 
-void MockAuthenticator::LoginAsKioskAccount(
-    const std::string& app_user_id, bool force_ephemeral) {
+void MockAuthenticator::LoginAsKioskAccount(const std::string& app_user_id,
+                                            bool use_guest_mount) {
   consumer_->OnLoginSuccess(UserContext(expected_username_,
                                         std::string(),
                                         std::string(),
diff --git a/chrome/browser/chromeos/login/mock_authenticator.h b/chrome/browser/chromeos/login/mock_authenticator.h
index 600cb22..2c317d2 100644
--- a/chrome/browser/chromeos/login/mock_authenticator.h
+++ b/chrome/browser/chromeos/login/mock_authenticator.h
@@ -38,8 +38,8 @@
       const UserContext& user_context) OVERRIDE;
   virtual void LoginRetailMode() OVERRIDE;
   virtual void LoginAsPublicAccount(const std::string& username) OVERRIDE;
-  virtual void LoginAsKioskAccount(
-      const std::string& app_user_id, bool force_ephemeral) OVERRIDE;
+  virtual void LoginAsKioskAccount(const std::string& app_user_id,
+                                   bool use_guest_mount) OVERRIDE;
   virtual void LoginOffTheRecord() OVERRIDE;
 
   virtual void OnRetailModeLoginSuccess() OVERRIDE;
diff --git a/chrome/browser/chromeos/login/mock_login_display_host.cc b/chrome/browser/chromeos/login/mock_login_display_host.cc
index 832eab2..9cb6df1 100644
--- a/chrome/browser/chromeos/login/mock_login_display_host.cc
+++ b/chrome/browser/chromeos/login/mock_login_display_host.cc
@@ -14,12 +14,6 @@
 MockLoginDisplayHost::~MockLoginDisplayHost() {
 }
 
-scoped_ptr<LoginDisplayHost::AutoEnrollmentProgressCallbackSubscription>
-MockLoginDisplayHost::RegisterAutoEnrollmentProgressHandler(
-    const AutoEnrollmentProgressCallback& callback) {
-  return make_scoped_ptr(RegisterAutoEnrollmentProgressHandlerPtr(callback));
-}
-
 void MockLoginDisplayHost::StartWizard(
     const std::string& name,
     scoped_ptr<base::DictionaryValue> value) {
diff --git a/chrome/browser/chromeos/login/mock_login_display_host.h b/chrome/browser/chromeos/login/mock_login_display_host.h
index 43da398..a653802 100644
--- a/chrome/browser/chromeos/login/mock_login_display_host.h
+++ b/chrome/browser/chromeos/login/mock_login_display_host.h
@@ -27,15 +27,9 @@
   MOCK_METHOD0(OpenProxySettings, void(void));
   MOCK_METHOD1(SetStatusAreaVisible, void(bool));
   MOCK_METHOD0(ShowBackground, void(void));
-  MOCK_METHOD0(CheckForAutoEnrollment, void(void));
+  MOCK_METHOD0(GetAutoEnrollmentController, AutoEnrollmentController*(void));
   // GMock currently doesn't support move-only arguments, so we have
   // to use this hack here.
-  MOCK_METHOD1(RegisterAutoEnrollmentProgressHandlerPtr,
-               AutoEnrollmentProgressCallbackSubscription*(
-                   const AutoEnrollmentProgressCallback&));
-  virtual scoped_ptr<AutoEnrollmentProgressCallbackSubscription>(
-      RegisterAutoEnrollmentProgressHandler(
-          const AutoEnrollmentProgressCallback& callback)) OVERRIDE;
   MOCK_METHOD2(StartWizardPtr, void(const std::string&,
                                     base::DictionaryValue*));
   virtual void StartWizard(const std::string& name,
diff --git a/chrome/browser/chromeos/login/oauth2_browsertest.cc b/chrome/browser/chromeos/login/oauth2_browsertest.cc
index 574d672..ee1f761 100644
--- a/chrome/browser/chromeos/login/oauth2_browsertest.cc
+++ b/chrome/browser/chromeos/login/oauth2_browsertest.cc
@@ -24,7 +24,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/browser/process_manager.h"
diff --git a/chrome/browser/chromeos/login/oauth2_login_manager.cc b/chrome/browser/chromeos/login/oauth2_login_manager.cc
index fd614a3..0f24937 100644
--- a/chrome/browser/chromeos/login/oauth2_login_manager.cc
+++ b/chrome/browser/chromeos/login/oauth2_login_manager.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/chrome_switches.h"
 #include "chromeos/chromeos_switches.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
diff --git a/chrome/browser/chromeos/login/oauth2_login_verifier.cc b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
index fa0cf0a..8a76d4c 100644
--- a/chrome/browser/chromeos/login/oauth2_login_verifier.cc
+++ b/chrome/browser/chromeos/login/oauth2_login_verifier.cc
@@ -11,17 +11,13 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
-#include "chrome/browser/chromeos/net/network_portal_detector.h"
+#include "chrome/browser/chromeos/net/delay_network_call.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "chromeos/network/network_handler.h"
-#include "chromeos/network/network_state.h"
-#include "chromeos/network/network_state_handler.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_constants.h"
-#include "third_party/cros_system_api/dbus/service_constants.h"
 
 using content::BrowserThread;
 
@@ -70,23 +66,27 @@
 void OAuth2LoginVerifier::VerifyUserCookies(Profile* profile) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (DelayNetworkCall(base::Bind(&OAuth2LoginVerifier::VerifyUserCookies,
-                                  AsWeakPtr(),
-                                  profile))) {
-    return;
-  }
-
-  StartAuthCookiesVerification();
+  // Delay the verification if the network is not connected or on a captive
+  // portal.
+  DelayNetworkCall(
+      base::Bind(&OAuth2LoginVerifier::StartAuthCookiesVerification,
+                 AsWeakPtr()),
+      base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
 }
 
 void OAuth2LoginVerifier::VerifyProfileTokens(Profile* profile) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (DelayNetworkCall(base::Bind(&OAuth2LoginVerifier::VerifyProfileTokens,
-                                  AsWeakPtr(),
-                                  profile))) {
-    return;
-  }
+  // Delay the verification if the network is not connected or on a captive
+  // portal.
+  DelayNetworkCall(
+      base::Bind(
+          &OAuth2LoginVerifier::VerifyProfileTokensImpl, AsWeakPtr(), profile),
+      base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
+}
+
+void OAuth2LoginVerifier::VerifyProfileTokensImpl(Profile* profile) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   gaia_token_.clear();
   if (access_token_.empty()) {
@@ -269,28 +269,4 @@
   error_handler.Run(IsConnectionOrServiceError(error));
 }
 
-bool OAuth2LoginVerifier::DelayNetworkCall(const base::Closure& callback) {
-  // Delay the verification if the network is not connected or on a captive
-  // portal.
-  const NetworkState* default_network =
-      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
-  NetworkPortalDetector* detector = NetworkPortalDetector::Get();
-  if (!default_network ||
-      default_network->connection_state() == shill::kStatePortal ||
-      (detector &&
-       detector->GetCaptivePortalState(default_network->path()).status !=
-           NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE)) {
-    // If network is offline, defer the token fetching until online.
-    LOG(WARNING) << "Network is offline. Deferring call.";
-    BrowserThread::PostDelayedTask(
-        BrowserThread::UI,
-        FROM_HERE,
-        callback,
-        base::TimeDelta::FromMilliseconds(kRequestRestartDelay));
-    return true;
-  }
-
-  return false;
-}
-
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/oauth2_login_verifier.h b/chrome/browser/chromeos/login/oauth2_login_verifier.h
index 090c105..e6807af 100644
--- a/chrome/browser/chromeos/login/oauth2_login_verifier.h
+++ b/chrome/browser/chromeos/login/oauth2_login_verifier.h
@@ -106,9 +106,8 @@
                     const base::Closure& task_to_retry,
                     const ErrorHandler& error_handler);
 
-  // Delays operation defined with |callback| based on the current networking
-  // conditions.
-  bool DelayNetworkCall(const base::Closure& callback);
+  // Called when network is connected.
+  void VerifyProfileTokensImpl(Profile* profile);
 
   OAuth2LoginVerifier::Delegate* delegate_;
   scoped_refptr<net::URLRequestContextGetter> system_request_context_;
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc
index d3f5f2a..2e0a4d6 100644
--- a/chrome/browser/chromeos/login/oobe_browsertest.cc
+++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -37,7 +37,7 @@
     command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
     command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, "user");
     command_line->AppendSwitchASCII(
-        chromeos::switches::kAuthExtensionPath, "gaia_auth");
+        ::switches::kAuthExtensionPath, "gaia_auth");
     fake_gaia_.Initialize();
   }
 
diff --git a/chrome/browser/chromeos/login/oobe_display.h b/chrome/browser/chromeos/login/oobe_display.h
index e76af7c..e2c3b59 100644
--- a/chrome/browser/chromeos/login/oobe_display.h
+++ b/chrome/browser/chromeos/login/oobe_display.h
@@ -38,6 +38,7 @@
     SCREEN_OOBE_EULA,
     SCREEN_OOBE_UPDATE,
     SCREEN_OOBE_ENROLLMENT,
+    SCREEN_OOBE_RESET,
     SCREEN_GAIA_SIGNIN,
     SCREEN_ACCOUNT_PICKER,
     SCREEN_KIOSK_AUTOLAUNCH,
diff --git a/chrome/browser/chromeos/login/parallel_authenticator.cc b/chrome/browser/chromeos/login/parallel_authenticator.cc
index 29ffe01..ba7e6f4 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator.cc
+++ b/chrome/browser/chromeos/login/parallel_authenticator.cc
@@ -110,6 +110,24 @@
                  resolver));
 }
 
+// Calls cryptohome's mount method for guest and also get the user hash from
+// cryptohome.
+void MountGuestAndGetHash(AuthAttemptState* attempt,
+                          scoped_refptr<ParallelAuthenticator> resolver) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  attempt->UsernameHashRequested();
+  cryptohome::AsyncMethodCaller::GetInstance()->AsyncMountGuest(
+      base::Bind(&TriggerResolveWithLoginTimeMarker,
+                 "CryptohomeMount-End",
+                 attempt,
+                 resolver));
+  cryptohome::AsyncMethodCaller::GetInstance()->AsyncGetSanitizedUsername(
+      attempt->user_context.username,
+      base::Bind(&TriggerResolveHash,
+                 attempt,
+                 resolver));
+}
+
 // Calls cryptohome's MountPublic method
 void MountPublic(AuthAttemptState* attempt,
                  scoped_refptr<ParallelAuthenticator> resolver,
@@ -346,11 +364,12 @@
 }
 
 void ParallelAuthenticator::LoginAsKioskAccount(
-    const std::string& app_user_id, bool force_ephemeral) {
+    const std::string& app_user_id,
+    bool use_guest_mount) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  std::string user_id =
-      force_ephemeral ? UserManager::kGuestUserName : app_user_id;
+  const std::string user_id =
+      use_guest_mount ? UserManager::kGuestUserName : app_user_id;
   current_state_.reset(new AuthAttemptState(
       UserContext(user_id,
                   std::string(),  // password
@@ -361,14 +380,14 @@
       false));
 
   remove_user_data_on_failure_ = true;
-  if (!force_ephemeral) {
+  if (!use_guest_mount) {
     MountPublic(current_state_.get(),
           scoped_refptr<ParallelAuthenticator>(this),
           cryptohome::CREATE_IF_MISSING);
   } else {
     ephemeral_mount_attempted_ = true;
-    MountGuest(current_state_.get(),
-               scoped_refptr<ParallelAuthenticator>(this));
+    MountGuestAndGetHash(current_state_.get(),
+                         scoped_refptr<ParallelAuthenticator>(this));
   }
 }
 
diff --git a/chrome/browser/chromeos/login/parallel_authenticator.h b/chrome/browser/chromeos/login/parallel_authenticator.h
index 8ea765a..0bb80df 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator.h
+++ b/chrome/browser/chromeos/login/parallel_authenticator.h
@@ -132,10 +132,12 @@
   virtual void LoginAsPublicAccount(const std::string& username) OVERRIDE;
 
   // Initiates login into the kiosk mode account identified by |app_user_id|.
-  // Mounts an public but non-ephemeral cryptohome and notifies consumer on the
-  // success/failure.
-  virtual void LoginAsKioskAccount(
-      const std::string& app_user_id, bool force_ephemeral) OVERRIDE;
+  // Mounts an ephemeral guest cryptohome if |use_guest_mount| is |true|.
+  // Otherwise, mounts a public cryptohome, which will be ephemeral if the
+  // |DeviceEphemeralUsersEnabled| policy is enabled and non-ephemeral
+  // otherwise.
+  virtual void LoginAsKioskAccount(const std::string& app_user_id,
+                                   bool use_guest_mount) OVERRIDE;
 
   // These methods must be called on the UI thread, as they make DBus calls
   // and also call back to the login UI.
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index 3287ad5..aece947 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -245,17 +245,7 @@
   }
 
   virtual void SetUpOnMainThread() OVERRIDE {
-    FakeGaia::MergeSessionParams params;
-    params.auth_sid_cookie = kTestAuthSIDCookie;
-    params.auth_lsid_cookie = kTestAuthLSIDCookie;
-    params.auth_code = kTestAuthCode;
-    params.refresh_token = kTestRefreshToken;
-    params.access_token = kTestAuthLoginAccessToken;
-    params.gaia_uber_token = kTestGaiaUberToken;
-    params.session_sid_cookie = kTestSessionSIDCookie;
-    params.session_lsid_cookie = kTestSessionLSIDCookie;
-    params.email = kFirstSAMLUserEmail;
-    fake_gaia_.SetMergeSessionParams(params);
+    SetMergeSessionParams(kFirstSAMLUserEmail);
 
     embedded_test_server()->RegisterRequestHandler(
         base::Bind(&FakeGaia::HandleRequest, base::Unretained(&fake_gaia_)));
@@ -279,6 +269,20 @@
     }
   }
 
+  void SetMergeSessionParams(const std::string& email) {
+    FakeGaia::MergeSessionParams params;
+    params.auth_sid_cookie = kTestAuthSIDCookie;
+    params.auth_lsid_cookie = kTestAuthLSIDCookie;
+    params.auth_code = kTestAuthCode;
+    params.refresh_token = kTestRefreshToken;
+    params.access_token = kTestAuthLoginAccessToken;
+    params.gaia_uber_token = kTestGaiaUberToken;
+    params.session_sid_cookie = kTestSessionSIDCookie;
+    params.session_lsid_cookie = kTestSessionLSIDCookie;
+    params.email = email;
+    fake_gaia_.SetMergeSessionParams(params);
+  }
+
   WebUILoginDisplay* GetLoginDisplay() {
     ExistingUserController* controller =
         ExistingUserController::current_controller();
@@ -504,6 +508,20 @@
   EXPECT_EQ(kFirstSAMLUserEmail, user->email());
 }
 
+// Verifies that if the authenticated user's e-mail address cannot be retrieved,
+// an error message is shown.
+IN_PROC_BROWSER_TEST_F(SamlTest, FailToRetrieveAutenticatedUserEmailAddress) {
+  fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
+  StartSamlAndWaitForIdpPageLoad(kFirstSAMLUserEmail);
+
+  SetMergeSessionParams("");
+  SetSignFormField("Email", "fake_user");
+  SetSignFormField("Password", "fake_password");
+  ExecuteJsInSigninFrame("document.getElementById('Submit').click();");
+
+  OobeScreenWaiter(OobeDisplay::SCREEN_FATAL_ERROR).Wait();
+}
+
 // Tests the password confirm flow: show error on the first failure and
 // fatal error on the second failure.
 IN_PROC_BROWSER_TEST_F(SamlTest, PasswordConfirmFlow) {
diff --git a/chrome/browser/chromeos/login/screen_locker_browsertest.cc b/chrome/browser/chromeos/login/screen_locker_browsertest.cc
index a1951c8..0288f91 100644
--- a/chrome/browser/chromeos/login/screen_locker_browsertest.cc
+++ b/chrome/browser/chromeos/login/screen_locker_browsertest.cc
@@ -146,7 +146,7 @@
   content::WindowedNotificationObserver lock_state_observer(
       chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
       content::NotificationService::AllSources());
-  if (!chromeos::ScreenLocker::GetTester()->IsLocked())
+  if (!tester->IsLocked())
     lock_state_observer.Wait();
 
   // Test to make sure that the widget is actually appearing and is of
diff --git a/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h b/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h
index 9010f89..0f2cde5 100644
--- a/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h
+++ b/chrome/browser/chromeos/login/screens/app_launch_splash_screen_actor.h
@@ -29,6 +29,9 @@
     // Invoked when the app launch bailout shortcut key is pressed.
     virtual void OnCancelAppLaunch() = 0;
 
+    // Invoked when the network config shortcut key is pressed.
+    virtual void OnNetworkConfigRequested(bool requested) = 0;
+
     // Invoked when network state is changed. |online| is true if the device
     // is connected to the Internet.
     virtual void OnNetworkStateChanged(bool online) = 0;
diff --git a/chrome/browser/chromeos/login/screens/error_screen.cc b/chrome/browser/chromeos/login/screens/error_screen.cc
index c5d51a9..a7a7bab 100644
--- a/chrome/browser/chromeos/login/screens/error_screen.cc
+++ b/chrome/browser/chromeos/login/screens/error_screen.cc
@@ -4,9 +4,13 @@
 
 #include "chrome/browser/chromeos/login/screens/error_screen.h"
 
+#include "base/command_line.h"
+#include "chrome/browser/chromeos/login/chrome_restart_request.h"
 #include "chrome/browser/chromeos/login/screens/error_screen_actor.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
 
 namespace chromeos {
 
@@ -14,7 +18,8 @@
                          ErrorScreenActor* actor)
     : WizardScreen(screen_observer),
       actor_(actor),
-      parent_screen_(OobeDisplay::SCREEN_UNKNOWN) {
+      parent_screen_(OobeDisplay::SCREEN_UNKNOWN),
+      weak_factory_(this) {
   DCHECK(actor_);
   actor_->SetDelegate(this);
   AddObserver(NetworkPortalDetector::Get());
@@ -60,6 +65,53 @@
   FOR_EACH_OBSERVER(Observer, observers_, OnErrorScreenHide());
 }
 
+void ErrorScreen::OnLaunchOobeGuestSession() {
+  DeviceSettingsService::Get()->GetOwnershipStatusAsync(
+      base::Bind(&ErrorScreen::StartGuestSessionAfterOwnershipCheck,
+                 weak_factory_.GetWeakPtr()));
+}
+
+void ErrorScreen::OnLoginFailure(const LoginFailure& error) {
+  // The only condition leading here is guest mount failure, which should not
+  // happen in practice. For now, just log an error so this situation is visible
+  // in logs if it ever occurs.
+  NOTREACHED() << "Guest login failed.";
+  guest_login_performer_.reset();
+}
+
+void ErrorScreen::OnLoginSuccess(const UserContext& user_context) {
+  LOG(FATAL);
+}
+
+void ErrorScreen::OnOffTheRecordLoginSuccess() {
+  // Restart Chrome to enter the guest session.
+  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+  CommandLine command_line(browser_command_line.GetProgram());
+  std::string cmd_line_str =
+      GetOffTheRecordCommandLine(GURL(),
+                                 StartupUtils::IsOobeCompleted(),
+                                 browser_command_line,
+                                 &command_line);
+
+  RestartChrome(cmd_line_str);
+}
+
+void ErrorScreen::OnPasswordChangeDetected() {
+  LOG(FATAL);
+}
+
+void ErrorScreen::WhiteListCheckFailed(const std::string& email) {
+  LOG(FATAL);
+}
+
+void ErrorScreen::PolicyLoadFailed() {
+  LOG(FATAL);
+}
+
+void ErrorScreen::OnOnlineChecked(const std::string& username, bool success) {
+  LOG(FATAL);
+}
+
 void ErrorScreen::FixCaptivePortal() {
   DCHECK(actor_);
   actor_->FixCaptivePortal();
@@ -91,9 +143,49 @@
   actor_->SetErrorState(error_state, network);
 }
 
+void ErrorScreen::AllowGuestSignin(bool allow) {
+  DCHECK(actor_);
+  actor_->AllowGuestSignin(allow);
+}
+
 void ErrorScreen::ShowConnectingIndicator(bool show) {
   DCHECK(actor_);
   actor_->ShowConnectingIndicator(show);
 }
 
+void ErrorScreen::StartGuestSessionAfterOwnershipCheck(
+    DeviceSettingsService::OwnershipStatus ownership_status) {
+
+  // Make sure to disallow guest login if it's explicitly disabled.
+  CrosSettingsProvider::TrustedStatus trust_status =
+      CrosSettings::Get()->PrepareTrustedValues(
+          base::Bind(&ErrorScreen::StartGuestSessionAfterOwnershipCheck,
+                     weak_factory_.GetWeakPtr(),
+                     ownership_status));
+  switch (trust_status) {
+    case CrosSettingsProvider::TEMPORARILY_UNTRUSTED:
+      // Wait for a callback.
+      return;
+    case CrosSettingsProvider::PERMANENTLY_UNTRUSTED:
+      // Only allow guest sessions if there is no owner yet.
+      if (ownership_status == DeviceSettingsService::OWNERSHIP_NONE)
+        break;
+      return;
+    case CrosSettingsProvider::TRUSTED: {
+      // Honor kAccountsPrefAllowGuest.
+      bool allow_guest = false;
+      CrosSettings::Get()->GetBoolean(kAccountsPrefAllowGuest, &allow_guest);
+      if (allow_guest)
+        break;
+      return;
+    }
+  }
+
+  if (guest_login_performer_)
+    return;
+
+  guest_login_performer_.reset(new LoginPerformer(this));
+  guest_login_performer_->LoginOffTheRecord();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/error_screen.h b/chrome/browser/chromeos/login/screens/error_screen.h
index 2721c44..bd20d81 100644
--- a/chrome/browser/chromeos/login/screens/error_screen.h
+++ b/chrome/browser/chromeos/login/screens/error_screen.h
@@ -7,11 +7,14 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
-#include "chrome/browser/chromeos/login/oobe_display.h"
+#include "chrome/browser/chromeos/login/login_performer.h"
 #include "chrome/browser/chromeos/login/oobe_display.h"
 #include "chrome/browser/chromeos/login/screens/error_screen_actor_delegate.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
 
 namespace chromeos {
 
@@ -19,7 +22,8 @@
 
 // Controller for the error screen.
 class ErrorScreen : public WizardScreen,
-                    public ErrorScreenActorDelegate {
+                    public ErrorScreenActorDelegate,
+                    public LoginPerformer::Delegate {
  public:
   class Observer {
    public:
@@ -35,7 +39,7 @@
     UI_STATE_LOCALLY_MANAGED,
     UI_STATE_KIOSK_MODE,
     UI_STATE_LOCAL_STATE_ERROR,
-    UI_STATE_AUTO_ENROLLMENT_ERROR
+    UI_STATE_AUTO_ENROLLMENT_ERROR,
   };
 
   enum ErrorState {
@@ -43,7 +47,8 @@
     ERROR_STATE_PORTAL,
     ERROR_STATE_OFFLINE,
     ERROR_STATE_PROXY,
-    ERROR_STATE_AUTH_EXT_TIMEOUT
+    ERROR_STATE_AUTH_EXT_TIMEOUT,
+    ERROR_STATE_KIOSK_ONLINE
   };
 
   ErrorScreen(ScreenObserver* screen_observer, ErrorScreenActor* actor);
@@ -61,6 +66,17 @@
   // ErrorScreenActorDelegate implementation:
   virtual void OnErrorShow() OVERRIDE;
   virtual void OnErrorHide() OVERRIDE;
+  virtual void OnLaunchOobeGuestSession() OVERRIDE;
+
+  // LoginPerformer::Delegate implementation:
+  virtual void OnLoginFailure(const LoginFailure& error) OVERRIDE;
+  virtual void OnLoginSuccess(const UserContext& user_context) OVERRIDE;
+  virtual void OnOffTheRecordLoginSuccess() OVERRIDE;
+  virtual void OnPasswordChangeDetected() OVERRIDE;
+  virtual void WhiteListCheckFailed(const std::string& email) OVERRIDE;
+  virtual void PolicyLoadFailed() OVERRIDE;
+  virtual void OnOnlineChecked(const std::string& username,
+                               bool success) OVERRIDE;
 
   // Initializes captive portal dialog and shows that if needed.
   void FixCaptivePortal();
@@ -80,6 +96,9 @@
   // |error_state|, and |network|.
   void SetErrorState(ErrorState error_state, const std::string& network);
 
+  // Toggles the guest sign-in prompt.
+  void AllowGuestSignin(bool allow);
+
   // Toggles the connection pending indicator.
   void ShowConnectingIndicator(bool show);
 
@@ -89,12 +108,21 @@
   OobeDisplay::Screen parent_screen() const { return parent_screen_; }
 
  private:
+  // Handles the response of an ownership check and starts the guest session if
+  // applicable.
+  void StartGuestSessionAfterOwnershipCheck(
+      DeviceSettingsService::OwnershipStatus ownership_status);
+
   ErrorScreenActor* actor_;
 
   OobeDisplay::Screen parent_screen_;
 
+  base::WeakPtrFactory<ErrorScreen> weak_factory_;
+
   ObserverList<Observer> observers_;
 
+  scoped_ptr<LoginPerformer> guest_login_performer_;
+
   DISALLOW_COPY_AND_ASSIGN(ErrorScreen);
 };
 
diff --git a/chrome/browser/chromeos/login/screens/error_screen_actor_delegate.h b/chrome/browser/chromeos/login/screens/error_screen_actor_delegate.h
index da81976..c8f2d3d 100644
--- a/chrome/browser/chromeos/login/screens/error_screen_actor_delegate.h
+++ b/chrome/browser/chromeos/login/screens/error_screen_actor_delegate.h
@@ -12,6 +12,7 @@
   virtual ~ErrorScreenActorDelegate() {}
   virtual void OnErrorShow() = 0;
   virtual void OnErrorHide() = 0;
+  virtual void OnLaunchOobeGuestSession() = 0;
 };
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/screen_observer.h b/chrome/browser/chromeos/login/screens/screen_observer.h
index c8ad239..4138f89 100644
--- a/chrome/browser/chromeos/login/screens/screen_observer.h
+++ b/chrome/browser/chromeos/login/screens/screen_observer.h
@@ -33,6 +33,7 @@
     USER_IMAGE_SELECTED,
     EULA_ACCEPTED,
     EULA_BACK,
+    ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED,
     ENTERPRISE_ENROLLMENT_COMPLETED,
     ENTERPRISE_AUTO_MAGIC_ENROLLMENT_COMPLETED,
     ENTERPRISE_ENROLLMENT_BACK,
diff --git a/chrome/browser/chromeos/login/screens/update_screen.cc b/chrome/browser/chromeos/login/screens/update_screen.cc
index 8e4b07a..64a9a1d 100644
--- a/chrome/browser/chromeos/login/screens/update_screen.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen.cc
@@ -70,12 +70,6 @@
   }
 }
 
-// Returns true if blocking AU is enabled in command line.
-bool IsBlockingUpdateEnabledInCommandLine() {
-  return !CommandLine::ForCurrentProcess()->HasSwitch(
-      chromeos::switches::kDisableOOBEBlockingUpdate);
-}
-
 }  // anonymous namespace
 
 // static
@@ -145,12 +139,10 @@
       actor_->SetProgress(kBeforeDownloadProgress);
       actor_->ShowEstimatedTimeLeft(false);
       if (!HasCriticalUpdate()) {
-        LOG(INFO) << "Noncritical update available: "
-                  << status.new_version;
+        VLOG(1) << "Noncritical update available: " << status.new_version;
         ExitUpdate(REASON_UPDATE_NON_CRITICAL);
       } else {
-        LOG(INFO) << "Critical update available: "
-                  << status.new_version;
+        VLOG(1) << "Critical update available: " << status.new_version;
         actor_->SetProgressMessage(
             UpdateScreenActor::PROGRESS_MESSAGE_UPDATE_AVAILABLE);
         actor_->ShowProgressMessage(true);
@@ -170,12 +162,10 @@
           is_download_average_speed_computed_ = false;
           download_average_speed_ = 0.0;
           if (!HasCriticalUpdate()) {
-            LOG(INFO) << "Non-critical update available: "
-                      << status.new_version;
+            VLOG(1) << "Non-critical update available: " << status.new_version;
             ExitUpdate(REASON_UPDATE_NON_CRITICAL);
           } else {
-            LOG(INFO) << "Critical update available: "
-                      << status.new_version;
+            VLOG(1) << "Critical update available: " << status.new_version;
             actor_->SetProgressMessage(
                 UpdateScreenActor::PROGRESS_MESSAGE_INSTALLING_UPDATE);
             actor_->ShowProgressMessage(true);
@@ -285,8 +275,7 @@
   // If portal detector is enabled and portal detection before AU is
   // allowed, initiate network state check. Otherwise, directly
   // proceed to update.
-  if (!NetworkPortalDetector::Get()->IsEnabled() ||
-      !IsBlockingUpdateEnabledInCommandLine()) {
+  if (!NetworkPortalDetector::Get()->IsEnabled()) {
     StartUpdateCheck();
     return;
   }
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.cc b/chrome/browser/chromeos/login/screens/user_image_screen.cc
index 23e0a0a..014ae5b 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen.cc
+++ b/chrome/browser/chromeos/login/screens/user_image_screen.cc
@@ -17,7 +17,6 @@
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#include "chrome/browser/chromeos/camera_detector.h"
 #include "chrome/browser/chromeos/login/default_user_images.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
@@ -52,7 +51,7 @@
 // Time histogram suffix for profile image download.
 const char kProfileDownloadReason[] = "OOBE";
 
-// Maximum ammount of time to wait for the user image to sync.
+// Maximum amount of time to wait for the user image to sync.
 // The screen is shown iff sync failed or time limit exceeded.
 const int kSyncTimeoutSeconds = 10;
 
@@ -62,15 +61,13 @@
                                  UserImageScreenActor* actor)
     : WizardScreen(screen_observer),
       actor_(actor),
-      weak_factory_(this),
       accept_photo_after_decoding_(false),
       selected_image_(User::kInvalidImageIndex),
       profile_picture_enabled_(false),
       profile_picture_data_url_(content::kAboutBlankURL),
       profile_picture_absent_(false),
       is_screen_ready_(false),
-      user_has_selected_image_(false),
-      was_camera_present_(false) {
+      user_has_selected_image_(false) {
   actor_->SetDelegate(this);
   SetProfilePictureEnabled(true);
   notification_registrar_.Add(this,
@@ -103,21 +100,9 @@
   image_decoder_->Start(task_runner);
 }
 
-void UserImageScreen::CheckCameraPresence() {
-  CameraDetector::StartPresenceCheck(
-      base::Bind(&UserImageScreen::OnCameraPresenceCheckDone,
-                 weak_factory_.GetWeakPtr()));
-}
-
-void UserImageScreen::OnCameraPresenceCheckDone() {
-  bool is_camera_present = CameraDetector::camera_presence() ==
-                           CameraDetector::kCameraPresent;
-  if (actor_) {
-    if (is_camera_present != was_camera_present_) {
-      actor_->SetCameraPresent(is_camera_present);
-      was_camera_present_ = is_camera_present;
-    }
-  }
+void UserImageScreen::OnCameraPresenceCheckDone(bool is_camera_present) {
+  if (actor_)
+    actor_->SetCameraPresent(is_camera_present);
 }
 
 void UserImageScreen::HideCurtain() {
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen.h b/chrome/browser/chromeos/login/screens/user_image_screen.h
index 8840719..a002269 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen.h
+++ b/chrome/browser/chromeos/login/screens/user_image_screen.h
@@ -7,7 +7,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
 #include "chrome/browser/chromeos/login/screens/user_image_screen_actor.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/chromeos/login/user.h"
@@ -51,7 +50,6 @@
   // UserImageScreenActor::Delegate implementation:
   virtual void OnScreenReady() OVERRIDE;
   virtual void OnPhotoTaken(const std::string& raw_data) OVERRIDE;
-  virtual void CheckCameraPresence() OVERRIDE;
   virtual void OnImageSelected(const std::string& image_url,
                                const std::string& image_type,
                                bool is_user_selection) OVERRIDE;
@@ -71,6 +69,7 @@
   virtual void OnImageDecoded(const ImageDecoder* decoder,
                               const SkBitmap& decoded_image) OVERRIDE;
   virtual void OnDecodeImageFailed(const ImageDecoder* decoder) OVERRIDE;
+  virtual void OnCameraPresenceCheckDone(bool is_camera_present) OVERRIDE;
 
   // UserImageSyncObserver::Observer implementation:
   virtual void OnInitialSync(bool local_image_updated) OVERRIDE;
@@ -98,9 +97,6 @@
   // Returns UserImageSyncObserver for the current user.
   UserImageSyncObserver* GetSyncObserver();
 
-  // Called when the camera presence check has been completed.
-  void OnCameraPresenceCheckDone();
-
   // Called when it's decided not to skip the screen.
   void HideCurtain();
 
@@ -113,8 +109,6 @@
 
   UserImageScreenActor* actor_;
 
-  base::WeakPtrFactory<UserImageScreen> weak_factory_;
-
   // Last ImageDecoder instance used to decode an image blob received by
   // HandlePhotoTaken.
   scoped_refptr<ImageDecoder> image_decoder_;
@@ -149,9 +143,6 @@
   // True if user has explicitly selected some image.
   bool user_has_selected_image_;
 
-  // True if camera was available last time.
-  bool was_camera_present_;
-
   DISALLOW_COPY_AND_ASSIGN(UserImageScreen);
 };
 
diff --git a/chrome/browser/chromeos/login/screens/user_image_screen_actor.h b/chrome/browser/chromeos/login/screens/user_image_screen_actor.h
index 5e5d073..00948e5 100644
--- a/chrome/browser/chromeos/login/screens/user_image_screen_actor.h
+++ b/chrome/browser/chromeos/login/screens/user_image_screen_actor.h
@@ -7,6 +7,8 @@
 
 #include <string>
 
+#include "chrome/browser/chromeos/camera_presence_notifier.h"
+
 class SkBitmap;
 
 namespace gfx {
@@ -19,16 +21,18 @@
 // representation, either views based or WebUI.
 class UserImageScreenActor {
  public:
-  class Delegate {
+  class Delegate : public CameraPresenceNotifier::Observer {
    public:
     virtual ~Delegate() {}
 
+    // CameraPresenceNotifier::Observer implementation:
+    virtual void OnCameraPresenceCheckDone(bool is_camera_present) = 0;
+
     // Called when UI ready to be shown.
     virtual void OnScreenReady() = 0;
     // Called when user accepts photo as login user image.
     virtual void OnPhotoTaken(const std::string& raw_data) = 0;
-    // Called to check camera presence.
-    virtual void CheckCameraPresence() = 0;
+
     // Called when some image was selected. |is_user_selection| indicates if
     // it was user selection or image was selected programmatically.
     virtual void OnImageSelected(const std::string& image_url,
diff --git a/chrome/browser/chromeos/login/simple_web_view_dialog.cc b/chrome/browser/chromeos/login/simple_web_view_dialog.cc
index 14b38de..607481b 100644
--- a/chrome/browser/chromeos/login/simple_web_view_dialog.cc
+++ b/chrome/browser/chromeos/login/simple_web_view_dialog.cc
@@ -265,9 +265,10 @@
   }
 }
 
-void SimpleWebViewDialog::LoadingStateChanged(WebContents* source) {
+void SimpleWebViewDialog::LoadingStateChanged(WebContents* source,
+    bool to_different_document) {
   bool is_loading = source->IsLoading();
-  UpdateReload(is_loading, false);
+  UpdateReload(is_loading && to_different_document, false);
   command_updater_->UpdateCommandEnabled(IDC_STOP, is_loading);
 }
 
diff --git a/chrome/browser/chromeos/login/simple_web_view_dialog.h b/chrome/browser/chromeos/login/simple_web_view_dialog.h
index 69f689b..68b91f8 100644
--- a/chrome/browser/chromeos/login/simple_web_view_dialog.h
+++ b/chrome/browser/chromeos/login/simple_web_view_dialog.h
@@ -70,7 +70,8 @@
   // Implements content::WebContentsDelegate:
   virtual void NavigationStateChanged(const content::WebContents* source,
                                       unsigned changed_flags) OVERRIDE;
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
 
   // Implements LocationBarView::Delegate:
   virtual content::WebContents* GetWebContents() OVERRIDE;
diff --git a/chrome/browser/chromeos/login/supervised_user_manager.h b/chrome/browser/chromeos/login/supervised_user_manager.h
index 2bfcda7..72f9d18 100644
--- a/chrome/browser/chromeos/login/supervised_user_manager.h
+++ b/chrome/browser/chromeos/login/supervised_user_manager.h
@@ -25,6 +25,7 @@
 extern const char kPasswordRevision[];
 extern const char kSalt[];
 extern const char kRequirePasswordUpdate[];
+extern const char kHasIncompleteKey[];
 extern const int kMinPasswordRevision;
 
 // Values for these keys are not stored in local state.
diff --git a/chrome/browser/chromeos/login/supervised_user_manager_impl.cc b/chrome/browser/chromeos/login/supervised_user_manager_impl.cc
index 89bb17e..72c02e6 100644
--- a/chrome/browser/chromeos/login/supervised_user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/supervised_user_manager_impl.cc
@@ -94,6 +94,7 @@
 const char kPasswordSignature[] = "PasswordSignature";
 const char kEncryptedPassword[] = "EncryptedPassword";
 const char kRequirePasswordUpdate[] = "RequirePasswordUpdate";
+const char kHasIncompleteKey[] = "HasIncompleteKey";
 const char kPasswordEncryptionKey[] = "password.hmac.encryption";
 const char kPasswordSignatureKey[] = "password.hmac.signature";
 
diff --git a/chrome/browser/chromeos/login/test/app_window_waiter.cc b/chrome/browser/chromeos/login/test/app_window_waiter.cc
new file mode 100644
index 0000000..5c69bb0
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/app_window_waiter.cc
@@ -0,0 +1,45 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/test/app_window_waiter.h"
+
+#include "apps/app_window.h"
+
+namespace chromeos {
+
+AppWindowWaiter::AppWindowWaiter(apps::AppWindowRegistry* registry,
+                                 const std::string& app_id)
+    : registry_(registry), app_id_(app_id), window_(NULL) {
+  registry_->AddObserver(this);
+}
+
+AppWindowWaiter::~AppWindowWaiter() {
+  registry_->RemoveObserver(this);
+}
+
+apps::AppWindow* AppWindowWaiter::Wait() {
+  window_ = registry_->GetCurrentAppWindowForApp(app_id_);
+  if (window_)
+    return window_;
+
+  run_loop_.Run();
+
+  return window_;
+}
+
+void AppWindowWaiter::OnAppWindowAdded(apps::AppWindow* app_window) {
+  if (!run_loop_.running())
+    return;
+
+  if (app_window->extension_id() == app_id_) {
+    window_ = app_window;
+    run_loop_.Quit();
+  }
+}
+
+void AppWindowWaiter::OnAppWindowIconChanged(apps::AppWindow* app_window) {}
+
+void AppWindowWaiter::OnAppWindowRemoved(apps::AppWindow* app_window) {}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/app_window_waiter.h b/chrome/browser/chromeos/login/test/app_window_waiter.h
new file mode 100644
index 0000000..3fcb9ec
--- /dev/null
+++ b/chrome/browser/chromeos/login/test/app_window_waiter.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_TEST_APP_WINDOW_WAITER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_APP_WINDOW_WAITER_H_
+
+#include <string>
+
+#include "apps/app_window_registry.h"
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/run_loop.h"
+
+namespace apps {
+class AppWindow;
+}
+
+namespace chromeos {
+
+// Helper class that monitors app windows to wait for a window to appear.
+// Use a new instance for each use, one instance will only work for one Wait.
+class AppWindowWaiter : public apps::AppWindowRegistry::Observer {
+ public:
+  AppWindowWaiter(apps::AppWindowRegistry* registry,
+                  const std::string& app_id);
+  virtual ~AppWindowWaiter();
+
+  apps::AppWindow* Wait();
+
+  // AppWindowRegistry::Observer:
+  virtual void OnAppWindowAdded(apps::AppWindow* app_window) OVERRIDE;
+  virtual void OnAppWindowIconChanged(apps::AppWindow* app_window) OVERRIDE;
+  virtual void OnAppWindowRemoved(apps::AppWindow* app_window) OVERRIDE;
+
+ private:
+  apps::AppWindowRegistry* registry_;
+  std::string app_id_;
+  base::RunLoop run_loop_;
+  apps::AppWindow* window_;
+
+  DISALLOW_COPY_AND_ASSIGN(AppWindowWaiter);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_APP_WINDOW_WAITER_H_
diff --git a/chrome/browser/chromeos/login/user_flow.cc b/chrome/browser/chromeos/login/user_flow.cc
index 7a5473d..1b414eb 100644
--- a/chrome/browser/chromeos/login/user_flow.cc
+++ b/chrome/browser/chromeos/login/user_flow.cc
@@ -44,6 +44,8 @@
   return false;
 }
 
+void DefaultUserFlow::HandleLoginSuccess(const UserContext& context) {}
+
 bool DefaultUserFlow::HandlePasswordChangeDetected() {
   return false;
 }
diff --git a/chrome/browser/chromeos/login/user_flow.h b/chrome/browser/chromeos/login/user_flow.h
index d802d17..1252763 100644
--- a/chrome/browser/chromeos/login/user_flow.h
+++ b/chrome/browser/chromeos/login/user_flow.h
@@ -25,6 +25,7 @@
   virtual bool ShouldLaunchBrowser() = 0;
   virtual bool ShouldSkipPostLoginScreens() = 0;
   virtual bool HandleLoginFailure(const LoginFailure& failure) = 0;
+  virtual void HandleLoginSuccess(const UserContext& context) = 0;
   virtual bool HandlePasswordChangeDetected() = 0;
   virtual void HandleOAuthTokenStatusChange(User::OAuthTokenStatus status) = 0;
   virtual void LaunchExtraSteps(Profile* profile) = 0;
@@ -51,6 +52,7 @@
   virtual bool ShouldLaunchBrowser() OVERRIDE;
   virtual bool ShouldSkipPostLoginScreens() OVERRIDE;
   virtual bool HandleLoginFailure(const LoginFailure& failure) OVERRIDE;
+  virtual void HandleLoginSuccess(const UserContext& context) OVERRIDE;
   virtual bool HandlePasswordChangeDetected() OVERRIDE;
   virtual void HandleOAuthTokenStatusChange(User::OAuthTokenStatus status)
       OVERRIDE;
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.cc b/chrome/browser/chromeos/login/wallpaper_manager.cc
index e54b3ac..a036ca9 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.cc
+++ b/chrome/browser/chromeos/login/wallpaper_manager.cc
@@ -828,7 +828,7 @@
     GetPendingWallpaper(user_id, delayed)
         ->ResetSetWallpaperImage(user_wallpaper, info);
   } else {
-    if (info.type == User::CUSTOMIZED) {
+    if (info.type == User::CUSTOMIZED || info.type == User::POLICY) {
       ash::WallpaperResolution resolution =
           ash::Shell::GetInstance()->
               desktop_background_controller()->
@@ -952,7 +952,7 @@
   if (GetUserWallpaperInfo(user_id, &info)) {
     base::FilePath wallpaper_dir;
     base::FilePath wallpaper_path;
-    if (info.type == User::CUSTOMIZED) {
+    if (info.type == User::CUSTOMIZED || info.type == User::POLICY) {
       ash::WallpaperResolution resolution = ash::Shell::GetInstance()->
           desktop_background_controller()->GetAppropriateResolution();
       const char* sub_dir  = (resolution == ash::WALLPAPER_RESOLUTION_SMALL) ?
diff --git a/chrome/browser/chromeos/login/wallpaper_manager.h b/chrome/browser/chromeos/login/wallpaper_manager.h
index aed11eb..203e35f 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager.h
+++ b/chrome/browser/chromeos/login/wallpaper_manager.h
@@ -308,6 +308,8 @@
  private:
   friend class TestApi;
   friend class WallpaperManagerBrowserTest;
+  friend class WallpaperManagerPolicyTest;
+
   typedef std::map<std::string, gfx::ImageSkia> CustomWallpaperMap;
 
   // Set |wallpaper| controlled by policy.
diff --git a/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc b/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc
index 4647619..821fd98 100644
--- a/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc
+++ b/chrome/browser/chromeos/login/wallpaper_manager_browsertest.cc
@@ -81,9 +81,8 @@
     controller_ = NULL;
   }
 
-  // Update the display configuration as given in |display_specs|.
-  // See ash::test::DisplayManagerTestApi::UpdateDisplay for more
-  // details.
+  // Update the display configuration as given in |display_specs|.  See
+  // ash::test::DisplayManagerTestApi::UpdateDisplay for more details.
   void UpdateDisplay(const std::string& display_specs) {
     ash::test::DisplayManagerTestApi display_manager_test_api(
         ash::Shell::GetInstance()->display_manager());
@@ -501,9 +500,9 @@
 // Tests for crbug.com/339576. Wallpaper cache should be updated in
 // multi-profile mode when user:
 // 1. chooses an online wallpaper from wallpaper
-//    picker(calls SetWallpaperFromImageSkia);
+//    picker (calls SetWallpaperFromImageSkia);
 // 2. chooses a custom wallpaper from wallpaper
-//    picker(calls SetCustomWallpaper);
+//    picker (calls SetCustomWallpaper);
 // 3. reverts to a default wallpaper.
 // Also, when user login at multi-profile mode, previous logged in users'
 // wallpaper cache should not be deleted.
diff --git a/chrome/browser/chromeos/login/wallpaper_manager_policy_browsertest.cc b/chrome/browser/chromeos/login/wallpaper_manager_policy_browsertest.cc
new file mode 100644
index 0000000..4708839
--- /dev/null
+++ b/chrome/browser/chromeos/login/wallpaper_manager_policy_browsertest.cc
@@ -0,0 +1,357 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+#include <vector>
+
+#include "ash/desktop_background/desktop_background_controller.h"
+#include "ash/desktop_background/desktop_background_controller_observer.h"
+#include "ash/shell.h"
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/json/json_writer.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "chrome/browser/chromeos/login/login_manager_test.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
+#include "chrome/browser/chromeos/login/user.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/login/wallpaper_manager.h"
+#include "chrome/browser/chromeos/policy/cloud_external_data_manager_base_test_util.h"
+#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
+#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
+#include "chromeos/chromeos_paths.h"
+#include "chromeos/chromeos_switches.h"
+#include "chromeos/dbus/cryptohome_client.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_dbus_thread_manager.h"
+#include "chromeos/dbus/fake_session_manager_client.h"
+#include "chromeos/dbus/session_manager_client.h"
+#include "components/policy/core/common/cloud/cloud_policy_core.h"
+#include "components/policy/core/common/cloud/cloud_policy_store.h"
+#include "components/policy/core/common/cloud/cloud_policy_validator.h"
+#include "components/policy/core/common/cloud/policy_builder.h"
+#include "crypto/rsa_private_key.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "policy/proto/cloud_policy.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
+
+namespace chromeos {
+
+namespace {
+
+const char kTestUsers[2][19] = { "test-0@example.com", "test-1@example.com" };
+
+const char kRedImageFileName[] = "chromeos/wallpapers/red.jpg";
+const char kGreenImageFileName[] = "chromeos/wallpapers/green.jpg";
+const char kBlueImageFileName[] = "chromeos/wallpapers/blue.jpg";
+
+const SkColor kRedImageColor = SkColorSetARGB(255, 199, 6, 7);
+const SkColor kGreenImageColor = SkColorSetARGB(255, 38, 196, 15);
+
+policy::CloudPolicyStore* GetStoreForUser(const User* user) {
+  Profile* profile = UserManager::Get()->GetProfileByUser(user);
+  if (!profile) {
+    ADD_FAILURE();
+    return NULL;
+  }
+  policy::UserCloudPolicyManagerChromeOS* policy_manager =
+      policy::UserCloudPolicyManagerFactoryChromeOS::GetForProfile(profile);
+  if (!policy_manager) {
+    ADD_FAILURE();
+    return NULL;
+  }
+  return policy_manager->core()->store();
+}
+
+// Compute the average ARGB color of |bitmap|.
+SkColor ComputeAverageColor(const SkBitmap& bitmap) {
+  if (bitmap.empty() || bitmap.width() < 1 || bitmap.height() < 1) {
+    ADD_FAILURE() << "Empty or invalid bitmap.";
+    return SkColorSetARGB(0, 0, 0, 0);
+  }
+  if (bitmap.isNull()) {
+    ADD_FAILURE() << "Bitmap has no pixelref.";
+    return SkColorSetARGB(0, 0, 0, 0);
+  }
+  if (bitmap.config() == SkBitmap::kNo_Config) {
+    ADD_FAILURE() << "Bitmap has not been configured.";
+    return SkColorSetARGB(0, 0, 0, 0);
+  }
+  uint64 a = 0, r = 0, g = 0, b = 0;
+  bitmap.lockPixels();
+  for (int x = 0; x < bitmap.width(); ++x) {
+    for (int y = 0; y < bitmap.height(); ++y) {
+      const SkColor color = bitmap.getColor(x, y);
+      a += SkColorGetA(color);
+      r += SkColorGetR(color);
+      g += SkColorGetG(color);
+      b += SkColorGetB(color);
+    }
+  }
+  bitmap.unlockPixels();
+  uint64 pixel_number = bitmap.width() * bitmap.height();
+  return SkColorSetARGB((a + pixel_number / 2) / pixel_number,
+                        (r + pixel_number / 2) / pixel_number,
+                        (g + pixel_number / 2) / pixel_number,
+                        (b + pixel_number / 2) / pixel_number);
+}
+
+// Obtain background image and return its average ARGB color.
+SkColor GetAverageBackgroundColor() {
+  const gfx::ImageSkia image =
+      ash::Shell::GetInstance()->desktop_background_controller()->
+      GetWallpaper();
+
+  const gfx::ImageSkiaRep& representation = image.GetRepresentation(1.);
+  if (representation.is_null()) {
+    ADD_FAILURE() << "No image representation.";
+    return SkColorSetARGB(0, 0, 0, 0);
+  }
+
+  const SkBitmap& bitmap = representation.sk_bitmap();
+  return ComputeAverageColor(bitmap);
+}
+
+}  // namespace
+
+class WallpaperManagerPolicyTest
+    : public LoginManagerTest,
+      public ash::DesktopBackgroundControllerObserver,
+      public testing::WithParamInterface<bool> {
+ protected:
+  WallpaperManagerPolicyTest()
+      : LoginManagerTest(true),
+        wallpaper_change_count_(0),
+        fake_dbus_thread_manager_(new FakeDBusThreadManager),
+        fake_session_manager_client_(new FakeSessionManagerClient) {
+    fake_dbus_thread_manager_->SetFakeClients();
+    fake_dbus_thread_manager_->SetSessionManagerClient(
+        scoped_ptr<SessionManagerClient>(fake_session_manager_client_));
+  }
+
+  scoped_ptr<policy::UserPolicyBuilder> GetUserPolicyBuilder(
+      const std::string& user_id) {
+    scoped_ptr<policy::UserPolicyBuilder>
+        user_policy_builder(new policy::UserPolicyBuilder());
+    base::FilePath user_keys_dir;
+    EXPECT_TRUE(PathService::Get(DIR_USER_POLICY_KEYS, &user_keys_dir));
+    const std::string sanitized_user_id =
+        CryptohomeClient::GetStubSanitizedUsername(user_id);
+    const base::FilePath user_key_file =
+        user_keys_dir.AppendASCII(sanitized_user_id)
+                     .AppendASCII("policy.pub");
+    std::vector<uint8> user_key_bits;
+    EXPECT_TRUE(user_policy_builder->GetSigningKey()->
+                ExportPublicKey(&user_key_bits));
+    EXPECT_TRUE(base::CreateDirectory(user_key_file.DirName()));
+    EXPECT_EQ(base::WriteFile(
+                  user_key_file,
+                  reinterpret_cast<const char*>(user_key_bits.data()),
+                  user_key_bits.size()),
+              static_cast<int>(user_key_bits.size()));
+    user_policy_builder->policy_data().set_username(user_id);
+    return user_policy_builder.Pass();
+  }
+
+  // LoginManagerTest:
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+    DBusThreadManager::SetInstanceForTesting(fake_dbus_thread_manager_);
+    LoginManagerTest::SetUpInProcessBrowserTestFixture();
+    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_));
+  }
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    // Set the same switches as LoginManagerTest, except that kMultiProfiles is
+    // only set when GetParam() is true and except that kLoginProfile is set
+    // when GetParam() is false.  The latter seems to be required for the sane
+    // start-up of user profiles.
+    command_line->AppendSwitch(switches::kLoginManager);
+    command_line->AppendSwitch(switches::kForceLoginManagerInTests);
+    if (GetParam())
+      command_line->AppendSwitch(::switches::kMultiProfiles);
+    else
+      command_line->AppendSwitchASCII(switches::kLoginProfile, kTestUsers[0]);
+  }
+
+  virtual void SetUpOnMainThread() OVERRIDE {
+    LoginManagerTest::SetUpOnMainThread();
+    ash::Shell::GetInstance()->
+        desktop_background_controller()->AddObserver(this);
+
+    // Set up policy signing.
+    user_policy_builders_[0] = GetUserPolicyBuilder(kTestUsers[0]);
+    user_policy_builders_[1] = GetUserPolicyBuilder(kTestUsers[1]);
+
+    ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+  }
+
+  virtual void TearDownOnMainThread() OVERRIDE {
+    ash::Shell::GetInstance()->
+        desktop_background_controller()->RemoveObserver(this);
+    LoginManagerTest::TearDownOnMainThread();
+  }
+
+  // ash::DesktopBackgroundControllerObserver:
+  virtual void OnWallpaperDataChanged() OVERRIDE {
+    ++wallpaper_change_count_;
+    if (run_loop_)
+      run_loop_->Quit();
+  }
+
+  // Runs the loop until wallpaper has changed at least |count| times in total.
+  void RunUntilWallpaperChangeCount(int count) {
+    while (wallpaper_change_count_ < count) {
+      run_loop_.reset(new base::RunLoop);
+      run_loop_->Run();
+    }
+  }
+
+  std::string ConstructPolicy(const std::string& relative_path) const {
+    std::string image_data;
+    if (!base::ReadFileToString(test_data_dir_.Append(relative_path),
+                                &image_data)) {
+      ADD_FAILURE();
+    }
+    std::string policy;
+    base::JSONWriter::Write(policy::test::ConstructExternalDataReference(
+        embedded_test_server()->GetURL(std::string("/") + relative_path).spec(),
+        image_data).get(),
+        &policy);
+    return policy;
+  }
+
+  // Inject |filename| as wallpaper policy for test user |user_number|.  Set
+  // empty |filename| to clear policy.
+  void InjectPolicy(int user_number, const std::string& filename) {
+    ASSERT_TRUE(user_number == 0 || user_number == 1);
+    const std::string user_id = kTestUsers[user_number];
+    policy::UserPolicyBuilder* builder =
+        user_policy_builders_[user_number].get();
+    if (filename != "") {
+      builder->payload().
+          mutable_wallpaperimage()->set_value(ConstructPolicy(filename));
+    } else {
+      builder->payload().Clear();
+    }
+    builder->Build();
+    fake_session_manager_client_->set_user_policy(user_id, builder->GetBlob());
+    const User* user = UserManager::Get()->FindUser(user_id);
+    ASSERT_TRUE(user);
+    policy::CloudPolicyStore* store = GetStoreForUser(user);
+    ASSERT_TRUE(store);
+    store->Load();
+    ASSERT_EQ(policy::CloudPolicyStore::STATUS_OK, store->status());
+    ASSERT_EQ(policy::CloudPolicyValidatorBase::VALIDATION_OK,
+              store->validation_status());
+  }
+
+  // Obtain WallpaperInfo for |user_number| from WallpaperManager.
+  void GetUserWallpaperInfo(int user_number, WallpaperInfo* wallpaper_info) {
+    WallpaperManager::Get()->
+        GetUserWallpaperInfo(kTestUsers[user_number], wallpaper_info);
+  }
+
+  base::FilePath test_data_dir_;
+  scoped_ptr<base::RunLoop> run_loop_;
+  int wallpaper_change_count_;
+  scoped_ptr<policy::UserPolicyBuilder> user_policy_builders_[2];
+  FakeDBusThreadManager* fake_dbus_thread_manager_;
+  FakeSessionManagerClient* fake_session_manager_client_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WallpaperManagerPolicyTest);
+};
+
+IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, PRE_SetResetClear) {
+  RegisterUser(kTestUsers[0]);
+  RegisterUser(kTestUsers[1]);
+  StartupUtils::MarkOobeCompleted();
+}
+
+// Verifies that the wallpaper can be set and re-set through policy and that
+// setting policy for a user that is not logged in doesn't affect the current
+// user.  Also verifies that after the policy has been cleared, the wallpaper
+// reverts to default.
+IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, SetResetClear) {
+  WallpaperInfo info;
+  LoginUser(kTestUsers[0]);
+  base::RunLoop().RunUntilIdle();
+
+  // First user: Wait until default wallpaper has been loaded (happens
+  // automatically) and store color to recognize it later.
+  RunUntilWallpaperChangeCount(1);
+  const SkColor original_background_color = GetAverageBackgroundColor();
+
+  // Second user: Set wallpaper policy to blue image.  This should not result in
+  // a wallpaper change, which is checked at the very end of this test.
+  InjectPolicy(1, kBlueImageFileName);
+
+  // First user: Set wallpaper policy to red image and verify average color.
+  InjectPolicy(0, kRedImageFileName);
+  RunUntilWallpaperChangeCount(2);
+  GetUserWallpaperInfo(0, &info);
+  ASSERT_EQ(User::POLICY, info.type);
+  ASSERT_EQ(kRedImageColor, GetAverageBackgroundColor());
+
+  // First user: Set wallpaper policy to green image and verify average color.
+  InjectPolicy(0, kGreenImageFileName);
+  RunUntilWallpaperChangeCount(3);
+  GetUserWallpaperInfo(0, &info);
+  ASSERT_EQ(User::POLICY, info.type);
+  ASSERT_EQ(kGreenImageColor, GetAverageBackgroundColor());
+
+  // First user: Clear wallpaper policy and verify that the default wallpaper is
+  // set again.
+  InjectPolicy(0, "");
+  RunUntilWallpaperChangeCount(4);
+  GetUserWallpaperInfo(0, &info);
+  ASSERT_EQ(User::DEFAULT, info.type);
+  ASSERT_EQ(original_background_color, GetAverageBackgroundColor());
+
+  // Check wallpaper change count to ensure that setting the second user's
+  // wallpaper didn't have any effect.
+  ASSERT_EQ(4, wallpaper_change_count_);
+}
+
+IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest,
+                       PRE_PRE_WallpaperOnLoginScreen) {
+  RegisterUser(kTestUsers[0]);
+  StartupUtils::MarkOobeCompleted();
+}
+
+IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, PRE_WallpaperOnLoginScreen) {
+  LoginUser(kTestUsers[0]);
+
+  // Wait until default wallpaper has been loaded.
+  RunUntilWallpaperChangeCount(1);
+
+  // Set wallpaper policy to red image.
+  InjectPolicy(0, kRedImageFileName);
+
+  // Run until wallpaper has changed.
+  RunUntilWallpaperChangeCount(2);
+}
+
+IN_PROC_BROWSER_TEST_P(WallpaperManagerPolicyTest, WallpaperOnLoginScreen) {
+  // Wait for active pod's wallpaper to be loaded.
+  RunUntilWallpaperChangeCount(1);
+  ASSERT_EQ(kRedImageColor, GetAverageBackgroundColor());
+}
+
+INSTANTIATE_TEST_CASE_P(WallpaperManagerPolicyTestInstantiation,
+                        WallpaperManagerPolicyTest, testing::Bool());
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/webui_login_view.cc b/chrome/browser/chromeos/login/webui_login_view.cc
index aa0e24b..9f1f463 100644
--- a/chrome/browser/chromeos/login/webui_login_view.cc
+++ b/chrome/browser/chromeos/login/webui_login_view.cc
@@ -61,6 +61,7 @@
 const char kAccelNameDeviceRequisition[] = "device_requisition";
 const char kAccelNameDeviceRequisitionRemora[] = "device_requisition_remora";
 const char kAccelNameAppLaunchBailout[] = "app_launch_bailout";
+const char kAccelNameAppLaunchNetworkConfig[] = "app_launch_network_config";
 
 // A class to change arrow key traversal behavior when it's alive.
 class ScopedArrowKeyTraversal {
@@ -142,6 +143,10 @@
                              ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)] =
       kAccelNameAppLaunchBailout;
 
+  accel_map_[ui::Accelerator(ui::VKEY_N,
+                             ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)] =
+      kAccelNameAppLaunchNetworkConfig;
+
   for (AccelMap::iterator i(accel_map_.begin()); i != accel_map_.end(); ++i)
     AddAccelerator(i->first);
 }
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index 036007d..fa322cb 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -12,11 +12,11 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
@@ -24,11 +24,13 @@
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/customization_document.h"
+#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_check_step.h"
 #include "chrome/browser/chromeos/login/enrollment/enrollment_screen.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/helper.h"
 #include "chrome/browser/chromeos/login/hwid_checker.h"
 #include "chrome/browser/chromeos/login/login_display_host.h"
+#include "chrome/browser/chromeos/login/login_location_monitor.h"
 #include "chrome/browser/chromeos/login/login_utils.h"
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
 #include "chrome/browser/chromeos/login/oobe_display.h"
@@ -44,10 +46,12 @@
 #include "chrome/browser/chromeos/login/screens/wrong_hwid_screen.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
+#include "chrome/browser/chromeos/net/delay_network_call.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
+#include "chrome/browser/chromeos/timezone/timezone_provider.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/options/options_util.h"
@@ -56,26 +60,32 @@
 #include "chrome/common/pref_names.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/chromeos_constants.h"
-#include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/session_manager_client.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/settings/cros_settings_names.h"
+#include "chromeos/settings/timezone_settings.h"
 #include "components/breakpad/app/breakpad_linux.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_types.h"
+#include "content/public/common/geoposition.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/l10n/l10n_util.h"
 
 using content::BrowserThread;
 
+namespace {
 // If reboot didn't happen, ask user to reboot device manually.
 const int kWaitForRebootTimeSec = 3;
 
 // Interval in ms which is used for smooth screen showing.
 static int kShowDelayMs = 400;
 
+// Total timezone resolving process timeout.
+const unsigned int kResolveTimeZoneTimeoutSeconds = 60;
+}  // namespace
+
 namespace chromeos {
 
 const char WizardController::kNetworkScreenName[] = "network";
@@ -148,6 +158,7 @@
 WizardController::~WizardController() {
   if (default_controller_ == this) {
     default_controller_ = NULL;
+    LoginLocationMonitor::RemoveLocationCallback();
   } else {
     NOTREACHED() << "More than one controller are alive.";
   }
@@ -372,10 +383,15 @@
     screen_parameters_->GetString("user", &user);
   }
 
+  EnrollmentScreenActor::EnrollmentMode mode =
+      EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL;
+  if (is_auto_enrollment)
+    mode = EnrollmentScreenActor::ENROLLMENT_MODE_AUTO;
+  else if (ShouldAutoStartEnrollment() && !CanExitEnrollment())
+    mode = EnrollmentScreenActor::ENROLLMENT_MODE_FORCED;
+
   EnrollmentScreen* screen = GetEnrollmentScreen();
-  screen->SetParameters(is_auto_enrollment,
-                        !ShouldAutoStartEnrollment() || CanExitEnrollment(),
-                        user);
+  screen->SetParameters(mode, GetForcedEnrollmentDomain(), user);
   SetCurrentScreen(screen);
 }
 
@@ -431,7 +447,7 @@
     const LoginScreenContext& context) {
   StartupUtils::MarkEulaAccepted();
   PerformPostEulaActions();
-  PerformPostUpdateActions();
+  PerformOOBECompletedActions();
   ShowLoginScreen(context);
 }
 
@@ -481,7 +497,7 @@
 }
 
 void WizardController::OnUpdateCompleted() {
-  CheckAutoEnrollmentState();
+  StartAutoEnrollmentCheck();
 }
 
 void WizardController::OnEulaAccepted() {
@@ -501,7 +517,7 @@
 
   if (skip_update_enroll_after_eula_) {
     PerformPostEulaActions();
-    PerformPostUpdateActions();
+    PerformOOBECompletedActions();
     ShowEnrollmentScreen();
   } else {
     InitiateOOBEUpdate();
@@ -557,7 +573,7 @@
   // Mark OOBE as completed only if enterprise enrollment was part of the
   // forced flow (i.e. app kiosk).
   if (ShouldAutoStartEnrollment())
-    PerformPostUpdateActions();
+    PerformOOBECompletedActions();
 
   // TODO(mnissler): Unify the logic for auto-login for Public Sessions and
   // Kiosk Apps and make this code cover both cases: http://crbug.com/234694.
@@ -600,10 +616,11 @@
 }
 
 void WizardController::OnOOBECompleted() {
+  auto_enrollment_check_step_.reset();
   if (ShouldAutoStartEnrollment()) {
     ShowEnrollmentScreen();
   } else {
-    PerformPostUpdateActions();
+    PerformOOBECompletedActions();
     ShowLoginScreen(LoginScreenContext());
   }
 }
@@ -625,17 +642,27 @@
   GetUpdateScreen()->StartNetworkCheck();
 }
 
+void WizardController::StartTimezoneResolve() const {
+  LoginLocationMonitor::InstallLocationCallback(
+      base::TimeDelta::FromSeconds(kResolveTimeZoneTimeoutSeconds));
+}
+
 void WizardController::PerformPostEulaActions() {
+  DelayNetworkCall(
+      base::Bind(&WizardController::StartTimezoneResolve,
+                 weak_factory_.GetWeakPtr()),
+      base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS));
+
   // Now that EULA has been accepted (for official builds), enable portal check.
   // ChromiumOS builds would go though this code path too.
   NetworkHandler::Get()->network_state_handler()->SetCheckPortalList(
       NetworkStateHandler::kDefaultCheckPortalList);
-  host_->CheckForAutoEnrollment();
+  host_->GetAutoEnrollmentController()->Start();
   host_->PrewarmAuthentication();
   NetworkPortalDetector::Get()->Enable(true);
 }
 
-void WizardController::PerformPostUpdateActions() {
+void WizardController::PerformOOBECompletedActions() {
   StartupUtils::MarkOobeCompleted();
 }
 
@@ -760,6 +787,9 @@
     case EULA_BACK:
       ShowNetworkScreen();
       break;
+    case ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED:
+      OnOOBECompleted();
+      break;
     case ENTERPRISE_ENROLLMENT_COMPLETED:
       OnEnrollmentDone();
       break;
@@ -878,12 +908,20 @@
   return connector->GetDeviceCloudPolicyManager()->ShouldAutoStartEnrollment();
 }
 
-bool WizardController::CanExitEnrollment() const {
+// static
+bool WizardController::CanExitEnrollment() {
   policy::BrowserPolicyConnectorChromeOS* connector =
       g_browser_process->platform_part()->browser_policy_connector_chromeos();
   return connector->GetDeviceCloudPolicyManager()->CanExitEnrollment();
 }
 
+// static
+std::string WizardController::GetForcedEnrollmentDomain() {
+  policy::BrowserPolicyConnectorChromeOS* connector =
+      g_browser_process->platform_part()->browser_policy_connector_chromeos();
+  return connector->GetDeviceCloudPolicyManager()->GetForcedEnrollmentDomain();
+}
+
 void WizardController::OnLocalStateInitialized(bool /* succeeded */) {
   if (GetLocalState()->GetInitializationStatus() !=
       PrefService::INITIALIZATION_STATUS_ERROR) {
@@ -894,53 +932,10 @@
   ShowErrorScreen();
 }
 
-void WizardController::CheckAutoEnrollmentState() {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kEnterpriseEnableForcedReEnrollment)) {
-    auto_enrollment_progress_subscription_ =
-        host_->RegisterAutoEnrollmentProgressHandler(
-            base::Bind(&WizardController::OnAutoEnrollmentCheckProgressed,
-                       weak_factory_.GetWeakPtr()));
-  } else {
-    OnOOBECompleted();
-  }
-}
-
-void WizardController::OnAutoEnrollmentCheckProgressed(
-    policy::AutoEnrollmentClient::State state) {
-  ErrorScreen* error_screen = GetErrorScreen();
-  switch (state) {
-    case policy::AutoEnrollmentClient::STATE_PENDING:
-      if (current_screen_ == error_screen &&
-          error_screen->GetUIState() ==
-              ErrorScreen::UI_STATE_AUTO_ENROLLMENT_ERROR) {
-        error_screen->ShowConnectingIndicator(true);
-      }
-      return;
-    case policy::AutoEnrollmentClient::STATE_CONNECTION_ERROR: {
-      // Show an error screen and ask the user to fix the network connection.
-      const NetworkState* default_network =
-          NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
-      DCHECK(default_network);
-      error_screen->SetUIState(ErrorScreen::UI_STATE_AUTO_ENROLLMENT_ERROR);
-      error_screen->SetErrorState(
-          ErrorScreen::ERROR_STATE_OFFLINE,
-          default_network ? default_network->name() : std::string());
-      error_screen->ShowConnectingIndicator(false);
-      ShowErrorScreen();
-      return;
-    }
-    case policy::AutoEnrollmentClient::STATE_SERVER_ERROR:
-      // Server errors don't block OOBE.
-    case policy::AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT:
-    case policy::AutoEnrollmentClient::STATE_NO_ENROLLMENT:
-      // Decision made, ready to proceed.
-      auto_enrollment_progress_subscription_.reset();
-      OnOOBECompleted();
-      return;
-  }
-
-  NOTREACHED();
+void WizardController::StartAutoEnrollmentCheck() {
+  auto_enrollment_check_step_.reset(
+      new AutoEnrollmentCheckStep(this, host_->GetAutoEnrollmentController()));
+  auto_enrollment_check_step_->Start();
 }
 
 PrefService* WizardController::GetLocalState() {
@@ -949,4 +944,84 @@
   return g_browser_process->local_state();
 }
 
+// static
+void WizardController::OnLocationUpdated(const content::Geoposition& position,
+                                         const base::TimeDelta elapsed) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  const base::TimeDelta timeout =
+      base::TimeDelta::FromSeconds(kResolveTimeZoneTimeoutSeconds);
+  if (elapsed >= timeout) {
+    LOG(WARNING) << "Resolve TimeZone: got location after timeout ("
+                 << elapsed.InSecondsF() << " seconds elapsed). Ignored.";
+    return;
+  }
+
+  WizardController* self = default_controller();
+
+  if (self == NULL) {
+    LOG(WARNING) << "Resolve TimeZone: got location after WizardController "
+                 << "has finished. (" << elapsed.InSecondsF() << " seconds "
+                 << "elapsed). Ignored.";
+    return;
+  }
+
+  // WizardController owns TimezoneProvider, so timezone request is silently
+  // cancelled on destruction.
+  self->GetTimezoneProvider()->RequestTimezone(
+      position,
+      false,  // sensor
+      timeout - elapsed,
+      base::Bind(&WizardController::OnTimezoneResolved,
+                 base::Unretained(self)));
+}
+
+void WizardController::OnTimezoneResolved(
+    scoped_ptr<TimeZoneResponseData> timezone,
+    bool server_error) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(timezone.get());
+  // To check that "this" is not destroyed try to access some member
+  // (timezone_provider_) in this case. Expect crash here.
+  DCHECK(timezone_provider_.get());
+
+  VLOG(1) << "Resolved local timezone={" << timezone->ToStringForDebug()
+          << "}.";
+
+  if (timezone->status != TimeZoneResponseData::OK) {
+    LOG(WARNING) << "Resolve TimeZone: failed to resolve timezone.";
+    return;
+  }
+
+  policy::BrowserPolicyConnectorChromeOS* connector =
+      g_browser_process->platform_part()->browser_policy_connector_chromeos();
+  if (connector->IsEnterpriseManaged()) {
+    std::string policy_timezone;
+    if (chromeos::CrosSettings::Get()->GetString(
+            chromeos::kSystemTimezonePolicy, &policy_timezone) &&
+        !policy_timezone.empty()) {
+      VLOG(1) << "Resolve TimeZone: TimeZone settings are overridden"
+              << " by DevicePolicy.";
+      return;
+    }
+  }
+
+  if (!timezone->timeZoneId.empty()) {
+    VLOG(1) << "Resolve TimeZone: setting timezone to '" << timezone->timeZoneId
+            << "'";
+
+    chromeos::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
+        base::UTF8ToUTF16(timezone->timeZoneId));
+  }
+}
+
+TimeZoneProvider* WizardController::GetTimezoneProvider() {
+  if (!timezone_provider_) {
+    timezone_provider_.reset(
+        new TimeZoneProvider(g_browser_process->system_request_context(),
+                             DefaultTimezoneProviderURL()));
+  }
+  return timezone_provider_.get();
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index a4a4e8d..49c5053 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -15,10 +15,10 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#include "chrome/browser/chromeos/login/login_display_host.h"
 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
 #include "chrome/browser/chromeos/login/screens/wizard_screen.h"
 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
+#include "content/public/common/geoposition.h"
 #include "ui/gfx/rect.h"
 #include "url/gurl.h"
 
@@ -29,19 +29,27 @@
 class DictionaryValue;
 }
 
+namespace content {
+struct Geoposition;
+}
+
 namespace chromeos {
 
+class AutoEnrollmentCheckStep;
 class EnrollmentScreen;
 class ErrorScreen;
 class EulaScreen;
 class KioskAutolaunchScreen;
 class KioskEnableScreen;
 class LocallyManagedUserCreationScreen;
+class LoginDisplayHost;
 class LoginScreenContext;
 class NetworkScreen;
 class OobeDisplay;
 class ResetScreen;
 class TermsOfServiceScreen;
+class TimeZoneProvider;
+struct TimeZoneResponseData;
 class UpdateScreen;
 class UserImageScreen;
 class WizardScreen;
@@ -158,6 +166,10 @@
   // Volume percent at which spoken feedback is still audible.
   static const int kMinAudibleOutputVolumePercent;
 
+  // Called from LoginLocationMonitor when location is resolved.
+  static void OnLocationUpdated(const content::Geoposition& position,
+                                base::TimeDelta elapsed);
+
  private:
   // Show specific screen.
   void ShowNetworkScreen();
@@ -213,7 +225,7 @@
   void PerformPostEulaActions();
 
   // Actions that should be done right after update stage is finished.
-  void PerformPostUpdateActions();
+  void PerformOOBECompletedActions();
 
   // Overridden from ScreenObserver:
   virtual void OnExit(ExitCodes exit_code) OVERRIDE;
@@ -247,17 +259,17 @@
   void AutoLaunchKioskApp();
 
   // Checks whether the user is allowed to exit enrollment.
-  bool CanExitEnrollment() const;
+  static bool CanExitEnrollment();
+
+  // Gets the management domain.
+  static std::string GetForcedEnrollmentDomain();
 
   // Called when LocalState is initialized.
   void OnLocalStateInitialized(bool /* succeeded */);
 
-  // Checks auto enrollment state and eventually triggers the next wizard step.
-  void CheckAutoEnrollmentState();
-
-  // Handles update notifications regarding the auto-enrollment check.
-  void OnAutoEnrollmentCheckProgressed(
-      policy::AutoEnrollmentClient::State state);
+  // Kicks off the auto-enrollment check step. Once it finishes, it'll call
+  // back via ScreenObserver::OnExit().
+  void StartAutoEnrollmentCheck();
 
   // Returns local state.
   PrefService* GetLocalState();
@@ -266,6 +278,16 @@
     local_state_for_testing_ = local_state;
   }
 
+  // Called when network is UP.
+  void StartTimezoneResolve() const;
+
+  // Creates provider on demand.
+  TimeZoneProvider* GetTimezoneProvider();
+
+  // TimeZoneRequest::TimeZoneResponseCallback implementation.
+  void OnTimezoneResolved(scoped_ptr<TimeZoneResponseData> timezone,
+                          bool server_error);
+
   // Whether to skip any screens that may normally be shown after login
   // (registration, Terms of Service, user image selection).
   static bool skip_post_login_screens_;
@@ -311,6 +333,9 @@
   // Default WizardController.
   static WizardController* default_controller_;
 
+  // The auto-enrollment check step, currently active.
+  scoped_ptr<AutoEnrollmentCheckStep> auto_enrollment_check_step_;
+
   // Parameters for the first screen. May be NULL.
   scoped_ptr<base::DictionaryValue> screen_parameters_;
 
@@ -348,11 +373,11 @@
   friend class WizardControllerBrokenLocalStateTest;
 
   scoped_ptr<AccessibilityStatusSubscription> accessibility_subscription_;
-  scoped_ptr<LoginDisplayHost::AutoEnrollmentProgressCallbackSubscription>
-      auto_enrollment_progress_subscription_;
 
   base::WeakPtrFactory<WizardController> weak_factory_;
 
+  scoped_ptr<TimeZoneProvider> timezone_provider_;
+
   DISALLOW_COPY_AND_ASSIGN(WizardController);
 };
 
diff --git a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
index 13716db..80efe43 100644
--- a/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/wizard_controller_browsertest.cc
@@ -36,11 +36,13 @@
 #include "chrome/browser/chromeos/login/webui_login_view.h"
 #include "chrome/browser/chromeos/login/wizard_controller.h"
 #include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
+#include "chrome/browser/chromeos/policy/server_backed_device_state.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
 #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/chromeos_switches.h"
@@ -49,6 +51,8 @@
 #include "chromeos/dbus/fake_dbus_thread_manager.h"
 #include "chromeos/dbus/fake_session_manager_client.h"
 #include "chromeos/network/network_state_handler.h"
+#include "chromeos/system/mock_statistics_provider.h"
+#include "chromeos/system/statistics_provider.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "grit/generated_resources.h"
@@ -60,6 +64,7 @@
 #include "ui/base/l10n/l10n_util.h"
 
 using ::testing::Exactly;
+using ::testing::Invoke;
 using ::testing::Return;
 
 namespace chromeos {
@@ -137,6 +142,25 @@
   base::RunLoop().RunUntilIdle();
 }
 
+void QuitLoopOnAutoEnrollmentProgress(
+    policy::AutoEnrollmentState expected_state,
+    base::RunLoop* loop,
+    policy::AutoEnrollmentState actual_state) {
+  if (expected_state == actual_state)
+    loop->Quit();
+}
+
+void WaitForAutoEnrollmentState(policy::AutoEnrollmentState state) {
+  base::RunLoop loop;
+  AutoEnrollmentController* auto_enrollment_controller =
+      LoginDisplayHostImpl::default_host()->GetAutoEnrollmentController();
+  scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
+      progress_subscription(
+          auto_enrollment_controller->RegisterProgressCallback(
+              base::Bind(&QuitLoopOnAutoEnrollmentProgress, state, &loop)));
+  loop.Run();
+}
+
 }  // namespace
 
 using ::testing::_;
@@ -176,6 +200,11 @@
     WizardInProcessBrowserTest::SetUpOnMainThread();
   }
 
+  ErrorScreen* GetErrorScreen() {
+    return static_cast<ScreenObserver*>(WizardController::default_controller())
+        ->GetErrorScreen();
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(WizardControllerTest);
 };
@@ -358,8 +387,7 @@
   WizardController::default_controller()->SkipUpdateEnrollAfterEula();
   EXPECT_CALL(*mock_enrollment_screen_->actor(),
               SetParameters(mock_enrollment_screen_,
-                            false,  // is_auto_enrollment
-                            true,   // can_exit_enrollment
+                            EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL,
                             ""))
       .Times(1);
   EXPECT_CALL(*mock_enrollment_screen_, Show()).Times(1);
@@ -401,8 +429,7 @@
   EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(0);
   EXPECT_CALL(*mock_enrollment_screen_->actor(),
               SetParameters(mock_enrollment_screen_,
-                            false,  // is_auto_enrollment
-                            true,   // can_exit_enrollment
+                            EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL,
                             ""))
       .Times(1);
   EXPECT_CALL(*mock_enrollment_screen_, Show()).Times(1);
@@ -490,6 +517,104 @@
   EXPECT_FALSE(ExistingUserController::current_controller() == NULL);
 }
 
+class WizardControllerEnrollmentFlowTest : public WizardControllerFlowTest {
+ protected:
+  WizardControllerEnrollmentFlowTest() {}
+
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    WizardControllerFlowTest::SetUpCommandLine(command_line);
+
+    command_line->AppendSwitch(
+        switches::kEnterpriseEnableForcedReEnrollment);
+    command_line->AppendSwitchASCII(
+        switches::kEnterpriseEnrollmentInitialModulus, "1");
+    command_line->AppendSwitchASCII(
+        switches::kEnterpriseEnrollmentModulusLimit, "2");
+  }
+
+  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
+    WizardControllerFlowTest::SetUpInProcessBrowserTestFixture();
+    system::StatisticsProvider::SetTestProvider(&statistics_provider_);
+    EXPECT_CALL(statistics_provider_, StartLoadingMachineStatistics(_, _));
+    EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, _)).WillRepeatedly(
+        Invoke(this, &WizardControllerEnrollmentFlowTest::GetMachineStatistic));
+    EXPECT_CALL(statistics_provider_, GetMachineFlag(_, _)).WillRepeatedly(
+        Return(false));
+    EXPECT_CALL(statistics_provider_, Shutdown());
+  }
+
+  virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
+    system::StatisticsProvider::SetTestProvider(NULL);
+    WizardControllerFlowTest::TearDownInProcessBrowserTestFixture();
+  }
+
+  bool GetMachineStatistic(const std::string& name, std::string* result) {
+    if (name == system::kDiskSerialNumber) {
+      *result = "fake-disk-serial-number";
+      return true;
+    } else if (name == "serial_number") {
+      *result = "fake-machine-serial-number";
+      return true;
+    }
+
+    return false;
+  }
+
+ private:
+  system::MockStatisticsProvider statistics_provider_;
+
+  DISALLOW_COPY_AND_ASSIGN(WizardControllerEnrollmentFlowTest);
+};
+
+IN_PROC_BROWSER_TEST_F(WizardControllerEnrollmentFlowTest,
+                       ControlFlowForcedReEnrollment) {
+  EXPECT_EQ(WizardController::default_controller()->GetNetworkScreen(),
+            WizardController::default_controller()->current_screen());
+  EXPECT_CALL(*mock_network_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_eula_screen_, Show()).Times(1);
+  OnExit(ScreenObserver::NETWORK_CONNECTED);
+
+  EXPECT_EQ(WizardController::default_controller()->GetEulaScreen(),
+            WizardController::default_controller()->current_screen());
+  EXPECT_CALL(*mock_eula_screen_, Hide()).Times(1);
+  EXPECT_CALL(*mock_update_screen_, StartNetworkCheck()).Times(1);
+  EXPECT_CALL(*mock_update_screen_, Show()).Times(1);
+  OnExit(ScreenObserver::EULA_ACCEPTED);
+  // Let update screen smooth time process (time = 0ms).
+  content::RunAllPendingInMessageLoop();
+
+  EXPECT_EQ(WizardController::default_controller()->GetUpdateScreen(),
+            WizardController::default_controller()->current_screen());
+  EXPECT_CALL(*mock_update_screen_, Hide()).Times(1);
+  OnExit(ScreenObserver::UPDATE_INSTALLED);
+
+  // Wait for auto-enrollment controller to encounter the connection error.
+  WaitForAutoEnrollmentState(policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR);
+
+  // The error screen shows up if there's no auto-enrollment decision.
+  EXPECT_FALSE(StartupUtils::IsOobeCompleted());
+  EXPECT_EQ(GetErrorScreen(),
+            WizardController::default_controller()->current_screen());
+  base::DictionaryValue device_state;
+  device_state.SetString(policy::kDeviceStateRestoreMode,
+                         policy::kDeviceStateRestoreModeReEnrollmentEnforced);
+  g_browser_process->local_state()->Set(prefs::kServerBackedDeviceState,
+                                        device_state);
+  EXPECT_CALL(*mock_enrollment_screen_, Show()).Times(1);
+  EXPECT_CALL(*mock_enrollment_screen_->actor(),
+              SetParameters(mock_enrollment_screen_,
+                            EnrollmentScreenActor::ENROLLMENT_MODE_FORCED,
+                            "")).Times(1);
+  OnExit(ScreenObserver::ENTERPRISE_AUTO_ENROLLMENT_CHECK_COMPLETED);
+
+  // Make sure enterprise enrollment page shows up.
+  EXPECT_EQ(WizardController::default_controller()->GetEnrollmentScreen(),
+            WizardController::default_controller()->current_screen());
+  OnExit(ScreenObserver::ENTERPRISE_ENROLLMENT_COMPLETED);
+
+  EXPECT_TRUE(StartupUtils::IsOobeCompleted());
+}
+
 class WizardControllerBrokenLocalStateTest : public WizardControllerTest {
  protected:
   WizardControllerBrokenLocalStateTest()
@@ -526,11 +651,6 @@
     WizardControllerTest::TearDownInProcessBrowserTestFixture();
   }
 
-  ErrorScreen* GetErrorScreen() {
-    return ((ScreenObserver*) WizardController::default_controller())->
-        GetErrorScreen();
-  }
-
   content::WebContents* GetWebContents() {
     LoginDisplayHostImpl* host = static_cast<LoginDisplayHostImpl*>(
         LoginDisplayHostImpl::default_host());
@@ -671,8 +791,7 @@
                        ControlFlowKioskForcedEnrollment) {
   EXPECT_CALL(*mock_enrollment_screen_->actor(),
               SetParameters(mock_enrollment_screen_,
-                            false,  // is_auto_enrollment
-                            false,  // can_exit_enrollment
+                            EnrollmentScreenActor::ENROLLMENT_MODE_FORCED,
                             ""))
       .Times(1);
 
@@ -715,8 +834,7 @@
 
   EXPECT_CALL(*mock_enrollment_screen_->actor(),
               SetParameters(mock_enrollment_screen_,
-                            false,  // is_auto_enrollment
-                            false,  // can_exit_enrollment
+                            EnrollmentScreenActor::ENROLLMENT_MODE_FORCED,
                             ""))
       .Times(1);
 
@@ -761,7 +879,7 @@
 
 // TODO(nkostylev): Add test for WebUI accelerators http://crosbug.com/22571
 
-COMPILE_ASSERT(ScreenObserver::EXIT_CODES_COUNT == 19,
+COMPILE_ASSERT(ScreenObserver::EXIT_CODES_COUNT == 20,
                add_tests_for_new_control_flow_you_just_introduced);
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/delay_network_call.cc b/chrome/browser/chromeos/net/delay_network_call.cc
new file mode 100644
index 0000000..8bcfff6
--- /dev/null
+++ b/chrome/browser/chromeos/net/delay_network_call.cc
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/net/delay_network_call.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "chrome/browser/chromeos/net/network_portal_detector.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "content/public/browser/browser_thread.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+const unsigned chromeos::kDefaultNetworkRetryDelayMS = 3000;
+
+void chromeos::DelayNetworkCall(const base::Closure& callback,
+                                base::TimeDelta retry) {
+  const NetworkState* default_network =
+      NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
+  bool delay_network_call = !default_network ||
+    !NetworkState::StateIsConnected(default_network->connection_state());
+  if (!delay_network_call && NetworkPortalDetector::IsInitialized()) {
+    NetworkPortalDetector* detector = NetworkPortalDetector::Get();
+    if (detector->GetCaptivePortalState(default_network->path()).status !=
+            NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE)
+      delay_network_call = true;
+  }
+  if (delay_network_call) {
+    content::BrowserThread::PostDelayedTask(
+        content::BrowserThread::UI,
+        FROM_HERE,
+        base::Bind(&chromeos::DelayNetworkCall, callback, retry),
+        retry);
+  } else {
+    callback.Run();
+  }
+}
diff --git a/chrome/browser/chromeos/net/delay_network_call.h b/chrome/browser/chromeos/net/delay_network_call.h
new file mode 100644
index 0000000..e3dfb99
--- /dev/null
+++ b/chrome/browser/chromeos/net/delay_network_call.h
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file contains utility functions to wait for network state.
+
+#ifndef CHROME_BROWSER_CHROMEOS_NET_DELAY_NETWORK_CALL_H_
+#define CHROME_BROWSER_CHROMEOS_NET_DELAY_NETWORK_CALL_H_
+
+namespace base {
+
+template <typename T>
+class Callback;
+
+typedef Callback<void(void)> Closure;
+
+class TimeDelta;
+
+}  // namespace base
+
+namespace chromeos {
+
+// Default delay to be used as an argument to DelayNetworkCall().
+extern const unsigned kDefaultNetworkRetryDelayMS;
+
+// Delay callback until the network is connected or while on a captive portal.
+void DelayNetworkCall(const base::Closure& callback, base::TimeDelta retry);
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_NET_DELAY_NETWORK_CALL_H_
diff --git a/chrome/browser/chromeos/net/network_portal_detector.cc b/chrome/browser/chromeos/net/network_portal_detector.cc
index d9b330a..5c52288 100644
--- a/chrome/browser/chromeos/net/network_portal_detector.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector.cc
@@ -54,12 +54,17 @@
 
 void NetworkPortalDetector::InitializeForTesting(
     NetworkPortalDetector* network_portal_detector) {
-  CHECK(!g_network_portal_detector_set_for_testing)
-      << "NetworkPortalDetector::InitializeForTesting is called twice";
-  CHECK(network_portal_detector);
-  delete g_network_portal_detector;
-  g_network_portal_detector = network_portal_detector;
-  g_network_portal_detector_set_for_testing = true;
+  if (network_portal_detector) {
+    CHECK(!g_network_portal_detector_set_for_testing)
+        << "NetworkPortalDetector::InitializeForTesting is called twice";
+    CHECK(network_portal_detector);
+    delete g_network_portal_detector;
+    g_network_portal_detector = network_portal_detector;
+    g_network_portal_detector_set_for_testing = true;
+  } else {
+    g_network_portal_detector = NULL;
+    g_network_portal_detector_set_for_testing = false;
+  }
 }
 
 // static
@@ -83,10 +88,8 @@
   CHECK(g_network_portal_detector || g_network_portal_detector_set_for_testing)
       << "NetworkPortalDetectorImpl::Shutdown() is called "
       << "without previous call to Initialize()";
-  if (g_network_portal_detector) {
-    delete g_network_portal_detector;
-    g_network_portal_detector = NULL;
-  }
+  delete g_network_portal_detector;
+  g_network_portal_detector = NULL;
 }
 
 // static
@@ -116,4 +119,9 @@
   return kCaptivePortalStatusUnrecognized;
 }
 
+// static
+bool NetworkPortalDetector::IsInitialized() {
+  return g_network_portal_detector;
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_portal_detector.h b/chrome/browser/chromeos/net/network_portal_detector.h
index 28c2d94..1bf9ba6 100644
--- a/chrome/browser/chromeos/net/network_portal_detector.h
+++ b/chrome/browser/chromeos/net/network_portal_detector.h
@@ -118,6 +118,10 @@
   // Returns non-localized string representation of |status|.
   static std::string CaptivePortalStatusString(CaptivePortalStatus status);
 
+  // Returns |true| if NetworkPortalDetector was Initialized and it is safe to
+  // call Get.
+  static bool IsInitialized();
+
  protected:
   NetworkPortalDetector() {}
   virtual ~NetworkPortalDetector() {}
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.cc b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
index f7d1cd6..e9c8a5a 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.cc
@@ -36,24 +36,72 @@
   return NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
 }
 
+bool InSession() {
+  return UserManager::IsInitialized() && UserManager::Get()->IsUserLoggedIn();
+}
+
+void RecordDetectionResult(NetworkPortalDetector::CaptivePortalStatus status) {
+  if (InSession()) {
+    UMA_HISTOGRAM_ENUMERATION(
+        NetworkPortalDetectorImpl::kSessionDetectionResultHistogram,
+        status,
+        NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+  } else {
+    UMA_HISTOGRAM_ENUMERATION(
+        NetworkPortalDetectorImpl::kOobeDetectionResultHistogram,
+        status,
+        NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+  }
+}
+
+void RecordDetectionDuration(const base::TimeDelta& duration) {
+  if (InSession()) {
+    UMA_HISTOGRAM_MEDIUM_TIMES(
+        NetworkPortalDetectorImpl::kSessionDetectionDurationHistogram,
+        duration);
+  } else {
+    UMA_HISTOGRAM_MEDIUM_TIMES(
+        NetworkPortalDetectorImpl::kOobeDetectionDurationHistogram, duration);
+  }
+}
+
 void RecordDiscrepancyWithShill(
     const NetworkState* network,
     const NetworkPortalDetector::CaptivePortalStatus status) {
-  if (network->connection_state() == shill::kStateOnline) {
-    UMA_HISTOGRAM_ENUMERATION(
-        NetworkPortalDetectorImpl::kShillOnlineHistogram,
-        status,
-        NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
-  } else if (network->connection_state() == shill::kStatePortal) {
-    UMA_HISTOGRAM_ENUMERATION(
-        NetworkPortalDetectorImpl::kShillPortalHistogram,
-        status,
-        NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
-  } else if (network->connection_state() == shill::kStateOffline) {
-    UMA_HISTOGRAM_ENUMERATION(
-        NetworkPortalDetectorImpl::kShillOfflineHistogram,
-        status,
-        NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+  if (InSession()) {
+    if (network->connection_state() == shill::kStateOnline) {
+      UMA_HISTOGRAM_ENUMERATION(
+          NetworkPortalDetectorImpl::kSessionShillOnlineHistogram,
+          status,
+          NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+    } else if (network->connection_state() == shill::kStatePortal) {
+      UMA_HISTOGRAM_ENUMERATION(
+          NetworkPortalDetectorImpl::kSessionShillPortalHistogram,
+          status,
+          NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+    } else if (network->connection_state() == shill::kStateOffline) {
+      UMA_HISTOGRAM_ENUMERATION(
+          NetworkPortalDetectorImpl::kSessionShillOfflineHistogram,
+          status,
+          NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+    }
+  } else {
+    if (network->connection_state() == shill::kStateOnline) {
+      UMA_HISTOGRAM_ENUMERATION(
+          NetworkPortalDetectorImpl::kOobeShillOnlineHistogram,
+          status,
+          NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+    } else if (network->connection_state() == shill::kStatePortal) {
+      UMA_HISTOGRAM_ENUMERATION(
+          NetworkPortalDetectorImpl::kOobeShillPortalHistogram,
+          status,
+          NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+    } else if (network->connection_state() == shill::kStateOffline) {
+      UMA_HISTOGRAM_ENUMERATION(
+          NetworkPortalDetectorImpl::kOobeShillOfflineHistogram,
+          status,
+          NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+    }
   }
 }
 
@@ -62,17 +110,28 @@
 ////////////////////////////////////////////////////////////////////////////////
 // NetworkPortalDetectorImpl, public:
 
-const char NetworkPortalDetectorImpl::kDetectionResultHistogram[] =
+const char NetworkPortalDetectorImpl::kOobeDetectionResultHistogram[] =
     "CaptivePortal.OOBE.DetectionResult";
-const char NetworkPortalDetectorImpl::kDetectionDurationHistogram[] =
+const char NetworkPortalDetectorImpl::kOobeDetectionDurationHistogram[] =
     "CaptivePortal.OOBE.DetectionDuration";
-const char NetworkPortalDetectorImpl::kShillOnlineHistogram[] =
+const char NetworkPortalDetectorImpl::kOobeShillOnlineHistogram[] =
     "CaptivePortal.OOBE.DiscrepancyWithShill_Online";
-const char NetworkPortalDetectorImpl::kShillPortalHistogram[] =
+const char NetworkPortalDetectorImpl::kOobeShillPortalHistogram[] =
     "CaptivePortal.OOBE.DiscrepancyWithShill_RestrictedPool";
-const char NetworkPortalDetectorImpl::kShillOfflineHistogram[] =
+const char NetworkPortalDetectorImpl::kOobeShillOfflineHistogram[] =
     "CaptivePortal.OOBE.DiscrepancyWithShill_Offline";
 
+const char NetworkPortalDetectorImpl::kSessionDetectionResultHistogram[] =
+    "CaptivePortal.Session.DetectionResult";
+const char NetworkPortalDetectorImpl::kSessionDetectionDurationHistogram[] =
+    "CaptivePortal.Session.DetectionDuration";
+const char NetworkPortalDetectorImpl::kSessionShillOnlineHistogram[] =
+    "CaptivePortal.Session.DiscrepancyWithShill_Online";
+const char NetworkPortalDetectorImpl::kSessionShillPortalHistogram[] =
+    "CaptivePortal.Session.DiscrepancyWithShill_RestrictedPool";
+const char NetworkPortalDetectorImpl::kSessionShillOfflineHistogram[] =
+    "CaptivePortal.Session.DiscrepancyWithShill_Offline";
+
 NetworkPortalDetectorImpl::NetworkPortalDetectorImpl(
     const scoped_refptr<net::URLRequestContextGetter>& request_context)
     : state_(STATE_IDLE),
@@ -448,13 +507,10 @@
   if (!network)
     return;
 
-  if (!detection_start_time_.is_null()) {
-    UMA_HISTOGRAM_MEDIUM_TIMES(kDetectionDurationHistogram,
-                               GetCurrentTimeTicks() - detection_start_time_);
-  }
-  UMA_HISTOGRAM_ENUMERATION(kDetectionResultHistogram,
-                            status,
-                            NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT);
+  if (!detection_start_time_.is_null())
+    RecordDetectionDuration(GetCurrentTimeTicks() - detection_start_time_);
+  RecordDetectionResult(status);
+
   switch (status) {
     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
       NOTREACHED();
@@ -484,7 +540,7 @@
 }
 
 void NetworkPortalDetectorImpl::UpdateCurrentStrategy() {
-  if (UserManager::IsInitialized() && UserManager::Get()->IsUserLoggedIn()) {
+  if (InSession()) {
     SetStrategy(PortalDetectorStrategy::STRATEGY_ID_SESSION);
     return;
   }
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl.h b/chrome/browser/chromeos/net/network_portal_detector_impl.h
index ca2ce90..9a10f06 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl.h
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl.h
@@ -45,11 +45,17 @@
       public content::NotificationObserver,
       public PortalDetectorStrategy::Delegate {
  public:
-  static const char kDetectionResultHistogram[];
-  static const char kDetectionDurationHistogram[];
-  static const char kShillOnlineHistogram[];
-  static const char kShillPortalHistogram[];
-  static const char kShillOfflineHistogram[];
+  static const char kOobeDetectionResultHistogram[];
+  static const char kOobeDetectionDurationHistogram[];
+  static const char kOobeShillOnlineHistogram[];
+  static const char kOobeShillPortalHistogram[];
+  static const char kOobeShillOfflineHistogram[];
+
+  static const char kSessionDetectionResultHistogram[];
+  static const char kSessionDetectionDurationHistogram[];
+  static const char kSessionShillOnlineHistogram[];
+  static const char kSessionShillPortalHistogram[];
+  static const char kSessionShillOfflineHistogram[];
 
   explicit NetworkPortalDetectorImpl(
       const scoped_refptr<net::URLRequestContextGetter>& request_context);
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
index a58f4c1..e7525f3 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/captive_portal/testing_utils.h"
@@ -12,6 +13,7 @@
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
 #include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
 #include "chrome/browser/chromeos/net/network_portal_detector_strategy.h"
+#include "chrome/browser/chromeos/net/network_portal_detector_test_utils.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/shill_service_client.h"
@@ -19,11 +21,23 @@
 #include "dbus/object_path.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 #include "ui/message_center/message_center.h"
+#include "ui/message_center/message_center_observer.h"
+
+using base::MessageLoop;
+using message_center::MessageCenter;
+using message_center::MessageCenterObserver;
 
 namespace chromeos {
 
 namespace {
 
+const char* kNotificationId =
+    NetworkPortalNotificationController::kNotificationId;
+const char* kNotificationMetric =
+    NetworkPortalNotificationController::kNotificationMetric;
+const char* kUserActionMetric =
+    NetworkPortalNotificationController::kUserActionMetric;
+
 const char kTestUser[] = "test-user@gmail.com";
 const char kWifi[] = "wifi";
 
@@ -40,6 +54,39 @@
   base::RunLoop().RunUntilIdle();
 }
 
+class TestObserver : public MessageCenterObserver {
+ public:
+  TestObserver() : run_loop_(new base::RunLoop()) {
+    MessageCenter::Get()->AddObserver(this);
+  }
+
+  virtual ~TestObserver() {
+    MessageCenter::Get()->RemoveObserver(this);
+  }
+
+  void WaitAndReset() {
+    run_loop_->Run();
+    run_loop_.reset(new base::RunLoop());
+  }
+
+  virtual void OnNotificationDisplayed(const std::string& notification_id)
+      OVERRIDE {
+    if (notification_id == kNotificationId)
+      MessageLoop::current()->PostTask(FROM_HERE, run_loop_->QuitClosure());
+  }
+
+  virtual void OnNotificationRemoved(const std::string& notification_id,
+                                     bool by_user) OVERRIDE {
+    if (notification_id == kNotificationId && by_user)
+      MessageLoop::current()->PostTask(FROM_HERE, run_loop_->QuitClosure());
+  }
+
+ private:
+  scoped_ptr<base::RunLoop> run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestObserver);
+};
+
 }  // namespace
 
 class NetworkPortalDetectorImplBrowserTest
@@ -89,6 +136,8 @@
     return network_portal_detector_->strategy_.get();
   }
 
+  MessageCenter* message_center() { return MessageCenter::Get(); }
+
  private:
   NetworkPortalDetectorImpl* network_portal_detector_;
 
@@ -104,24 +153,50 @@
 
 IN_PROC_BROWSER_TEST_F(NetworkPortalDetectorImplBrowserTest,
                        InSessionDetection) {
+  typedef NetworkPortalNotificationController Controller;
+
+  TestObserver observer;
+
+  EnumHistogramChecker ui_checker(
+      kNotificationMetric, Controller::NOTIFICATION_METRIC_COUNT, NULL);
+  EnumHistogramChecker action_checker(
+      kUserActionMetric, Controller::USER_ACTION_METRIC_COUNT, NULL);
+
   LoginUser(kTestUser);
   content::RunAllPendingInMessageLoop();
+
+  // User connects to wifi.
   SetConnected(kWifi);
 
   ASSERT_EQ(PortalDetectorStrategy::STRATEGY_ID_SESSION, strategy()->Id());
 
   // No notification until portal detection is completed.
-  ASSERT_FALSE(message_center::MessageCenter::Get()->HasNotification(
-      NetworkPortalNotificationController::kNotificationId));
+  ASSERT_FALSE(message_center()->HasNotification(kNotificationId));
   RestartDetection();
   CompleteURLFetch(net::OK, 200, NULL);
 
   // Check that wifi is marked as behind the portal and that notification
   // is displayed.
+  ASSERT_TRUE(message_center()->HasNotification(kNotificationId));
   ASSERT_EQ(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
             NetworkPortalDetector::Get()->GetCaptivePortalState(kWifi).status);
-  ASSERT_TRUE(message_center::MessageCenter::Get()->HasNotification(
-      NetworkPortalNotificationController::kNotificationId));
+
+  // Wait until notification is displayed.
+  observer.WaitAndReset();
+
+  ASSERT_TRUE(
+      ui_checker.Expect(Controller::NOTIFICATION_METRIC_DISPLAYED, 1)->Check());
+  ASSERT_TRUE(action_checker.Check());
+
+  // User explicitly closes the notification.
+  message_center()->RemoveNotification(kNotificationId, true);
+
+  // Wait until notification is closed.
+  observer.WaitAndReset();
+
+  ASSERT_TRUE(ui_checker.Check());
+  ASSERT_TRUE(
+      action_checker.Expect(Controller::USER_ACTION_METRIC_CLOSED, 1)->Check());
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
index d2efbf5..18bd965 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/captive_portal/captive_portal_detector.h"
 #include "chrome/browser/captive_portal/testing_utils.h"
 #include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
+#include "chrome/browser/chromeos/net/network_portal_detector_test_utils.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -59,67 +60,6 @@
                     const NetworkPortalDetector::CaptivePortalState& state));
 };
 
-class ResultHistogramChecker {
- public:
-  explicit ResultHistogramChecker(base::HistogramSamples* base)
-      : base_(base),
-        count_(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT) {}
-  virtual ~ResultHistogramChecker() {}
-
-  ResultHistogramChecker* Expect(
-      NetworkPortalDetector::CaptivePortalStatus status,
-      int count) {
-    count_[status] = count;
-    return this;
-  }
-
-  bool Check() const {
-    base::HistogramBase* histogram = base::StatisticsRecorder::FindHistogram(
-        NetworkPortalDetectorImpl::kDetectionResultHistogram);
-    bool empty = false;
-    if (static_cast<size_t>(std::count(count_.begin(), count_.end(), 0)) ==
-        count_.size()) {
-      empty = true;
-    }
-
-    if (!histogram) {
-      if (empty)
-        return true;
-      LOG(ERROR) << "Can't get histogram for "
-                 << NetworkPortalDetectorImpl::kDetectionResultHistogram;
-      return false;
-    }
-    scoped_ptr<base::HistogramSamples> samples = histogram->SnapshotSamples();
-    if (!samples.get()) {
-      if (empty)
-        return true;
-      LOG(ERROR) << "Can't get samples for "
-                 << NetworkPortalDetectorImpl::kDetectionResultHistogram;
-      return false;
-    }
-    bool ok = true;
-    for (size_t i = 0; i < count_.size(); ++i) {
-      const int base = base_ ? base_->GetCount(i) : 0;
-      const int actual = samples->GetCount(i) - base;
-      const NetworkPortalDetector::CaptivePortalStatus status =
-          static_cast<NetworkPortalDetector::CaptivePortalStatus>(i);
-      if (actual != count_[i]) {
-        LOG(ERROR) << "Expected: " << count_[i] << ", "
-                   << "actual: " << actual << " for "
-                   << NetworkPortalDetector::CaptivePortalStatusString(status);
-        ok = false;
-      }
-    }
-    return ok;
-  }
-
- private:
-  base::HistogramSamples* base_;
-  std::vector<int> count_;
-
-  DISALLOW_COPY_AND_ASSIGN(ResultHistogramChecker);
-};
-
 }  // namespace
 
 class NetworkPortalDetectorImplTest
@@ -146,7 +86,7 @@
 
     if (base::HistogramBase* histogram =
             base::StatisticsRecorder::FindHistogram(
-                NetworkPortalDetectorImpl::kDetectionResultHistogram)) {
+                "CaptivePortal.OOBE.DetectionResult")) {
       original_samples_.reset(histogram->SnapshotSamples().release());
     }
   }
@@ -201,9 +141,7 @@
     network_portal_detector()->OnErrorScreenHide();
   }
 
-  void stop_detection() {
-    network_portal_detector()->StopDetection();
-  }
+  void stop_detection() { network_portal_detector()->StopDetection(); }
 
   bool attempt_timeout_is_cancelled() {
     return network_portal_detector()->AttemptTimeoutIsCancelledForTesting();
@@ -229,8 +167,6 @@
     return (NetworkPortalDetectorImpl::STATE_CHECKING_FOR_PORTAL == state());
   }
 
-
-
   const base::TimeDelta& next_attempt_delay() {
     return network_portal_detector()->next_attempt_delay_for_testing();
   }
@@ -285,9 +221,12 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  scoped_ptr<ResultHistogramChecker> MakeResultHistogramChecker() {
-    return scoped_ptr<ResultHistogramChecker>(
-        new ResultHistogramChecker(original_samples_.get())).Pass();
+  scoped_ptr<EnumHistogramChecker> MakeResultHistogramChecker() {
+    return scoped_ptr<EnumHistogramChecker>(
+               new EnumHistogramChecker(
+                   "CaptivePortal.OOBE.DetectionResult",
+                   NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT,
+                   original_samples_.get()));
   }
 
  private:
diff --git a/chrome/browser/chromeos/net/network_portal_detector_test_utils.cc b/chrome/browser/chromeos/net/network_portal_detector_test_utils.cc
new file mode 100644
index 0000000..45e7dd0
--- /dev/null
+++ b/chrome/browser/chromeos/net/network_portal_detector_test_utils.cc
@@ -0,0 +1,68 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/net/network_portal_detector_test_utils.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/metrics/histogram_base.h"
+#include "base/metrics/histogram_samples.h"
+#include "base/metrics/statistics_recorder.h"
+
+namespace chromeos {
+
+EnumHistogramChecker::EnumHistogramChecker(const std::string& histogram,
+                                           int count,
+                                           base::HistogramSamples* base)
+    : histogram_(histogram), expect_(count), base_(base) {}
+
+EnumHistogramChecker::~EnumHistogramChecker() {}
+
+EnumHistogramChecker* EnumHistogramChecker::Expect(int key, int value) {
+  expect_[key] = value;
+  return this;
+}
+
+bool EnumHistogramChecker::Check() {
+  bool empty = false;
+  size_t num_zeroes =
+      static_cast<size_t>(std::count(expect_.begin(), expect_.end(), 0));
+  if (num_zeroes == expect_.size())
+    empty = true;
+  base::HistogramBase* histogram =
+      base::StatisticsRecorder::FindHistogram(histogram_);
+  if (!histogram) {
+    if (!empty) {
+      LOG(ERROR) << "Non-empty expectations for " << histogram_ << " "
+                 << "which does not exists.";
+      return false;
+    }
+    return true;
+  }
+  scoped_ptr<base::HistogramSamples> samples = histogram->SnapshotSamples();
+  if (!samples.get()) {
+    if (!empty) {
+      LOG(ERROR) << "Non-empty expectations for " << histogram_ << " "
+                 << "for which samples do not exist.";
+      return false;
+    }
+    return true;
+  }
+
+  bool ok = true;
+  for (size_t i = 0; i < expect_.size(); ++i) {
+    const int base = base_ ? base_->GetCount(i) : 0;
+    const int actual = samples->GetCount(i) - base;
+    if (actual != expect_[i]) {
+      LOG(ERROR) << "Histogram: " << histogram_ << ", value #" << i << ", "
+                 << "expected: " << expect_[i] << ", actual: " << actual;
+      ok = false;
+    }
+  }
+  return ok;
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_portal_detector_test_utils.h b/chrome/browser/chromeos/net/network_portal_detector_test_utils.h
new file mode 100644
index 0000000..e1a753b
--- /dev/null
+++ b/chrome/browser/chromeos/net/network_portal_detector_test_utils.h
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_TEST_UTILS_H_
+#define CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_TEST_UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+
+namespace base {
+class HistogramSamples;
+}
+
+namespace chromeos {
+
+// Checks enum values in a histogram.
+class EnumHistogramChecker {
+ public:
+  EnumHistogramChecker(const std::string& histogram, int count,
+                       base::HistogramSamples* base);
+  ~EnumHistogramChecker();
+
+  // Sets expectation for a given enum key. |key| must be between 0
+  // and expect_.size().
+  EnumHistogramChecker* Expect(int key, int value);
+
+  // Actually accesses histogram and checks values for all keys.
+  bool Check();
+
+ private:
+  // Name of a histogram.
+  std::string histogram_;
+
+  // List of expectations.
+  std::vector<int> expect_;
+
+  // When not NULL, expected values are compared with actual values
+  // minus base.
+  base::HistogramSamples* base_;
+
+  DISALLOW_COPY_AND_ASSIGN(EnumHistogramChecker);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_NET_NETWORK_PORTAL_DETECTOR_TEST_UTILS_H_
diff --git a/chrome/browser/chromeos/net/network_portal_notification_controller.cc b/chrome/browser/chromeos/net/network_portal_notification_controller.cc
index 7633e69..579c2f9 100644
--- a/chrome/browser/chromeos/net/network_portal_notification_controller.cc
+++ b/chrome/browser/chromeos/net/network_portal_notification_controller.cc
@@ -12,6 +12,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/captive_portal/captive_portal_detector.h"
@@ -49,21 +50,56 @@
 class NetworkPortalNotificationControllerDelegate
     : public message_center::NotificationDelegate {
  public:
-  NetworkPortalNotificationControllerDelegate() {}
+  NetworkPortalNotificationControllerDelegate(): clicked_(false) {}
 
   // Overridden from message_center::NotificationDelegate:
-  virtual void Display() OVERRIDE {}
-  virtual void Error() OVERRIDE {}
-  virtual void Close(bool /* by_user */) OVERRIDE {}
+  virtual void Display() OVERRIDE;
+  virtual void Error() OVERRIDE;
+  virtual void Close(bool by_user) OVERRIDE;
   virtual void Click() OVERRIDE;
 
  private:
   virtual ~NetworkPortalNotificationControllerDelegate() {}
 
+  bool clicked_;
+
   DISALLOW_COPY_AND_ASSIGN(NetworkPortalNotificationControllerDelegate);
 };
 
+void NetworkPortalNotificationControllerDelegate::Display() {
+  UMA_HISTOGRAM_ENUMERATION(
+      NetworkPortalNotificationController::kNotificationMetric,
+      NetworkPortalNotificationController::NOTIFICATION_METRIC_DISPLAYED,
+      NetworkPortalNotificationController::NOTIFICATION_METRIC_COUNT);
+}
+
+void NetworkPortalNotificationControllerDelegate::Error() {
+  UMA_HISTOGRAM_ENUMERATION(
+      NetworkPortalNotificationController::kNotificationMetric,
+      NetworkPortalNotificationController::NOTIFICATION_METRIC_ERROR,
+      NetworkPortalNotificationController::NOTIFICATION_METRIC_COUNT);
+}
+
+void NetworkPortalNotificationControllerDelegate::Close(bool by_user) {
+  if (clicked_)
+    return;
+  NetworkPortalNotificationController::UserActionMetric metric =
+      by_user
+      ? NetworkPortalNotificationController::USER_ACTION_METRIC_CLOSED
+      : NetworkPortalNotificationController::USER_ACTION_METRIC_IGNORED;
+  UMA_HISTOGRAM_ENUMERATION(
+      NetworkPortalNotificationController::kUserActionMetric,
+      metric,
+      NetworkPortalNotificationController::USER_ACTION_METRIC_COUNT);
+}
+
 void NetworkPortalNotificationControllerDelegate::Click() {
+  clicked_ = true;
+  UMA_HISTOGRAM_ENUMERATION(
+      NetworkPortalNotificationController::kUserActionMetric,
+      NetworkPortalNotificationController::USER_ACTION_METRIC_CLICKED,
+      NetworkPortalNotificationController::USER_ACTION_METRIC_COUNT);
+
   Profile* profile = ProfileManager::GetActiveUserProfile();
   if (!profile)
     return;
@@ -77,9 +113,18 @@
 
 }  // namespace
 
+// static
 const char NetworkPortalNotificationController::kNotificationId[] =
     "chrome://net/network_portal_detector";
 
+// static
+const char NetworkPortalNotificationController::kNotificationMetric[] =
+    "CaptivePortal.Notification.Status";
+
+// static
+const char NetworkPortalNotificationController::kUserActionMetric[] =
+    "CaptivePortal.Notification.UserAction";
+
 NetworkPortalNotificationController::NetworkPortalNotificationController() {}
 
 NetworkPortalNotificationController::~NetworkPortalNotificationController() {}
diff --git a/chrome/browser/chromeos/net/network_portal_notification_controller.h b/chrome/browser/chromeos/net/network_portal_notification_controller.h
index 6160858..b75118e 100644
--- a/chrome/browser/chromeos/net/network_portal_notification_controller.h
+++ b/chrome/browser/chromeos/net/network_portal_notification_controller.h
@@ -16,8 +16,24 @@
 
 class NetworkPortalNotificationController {
  public:
+  enum NotificationMetric {
+    NOTIFICATION_METRIC_DISPLAYED = 0,
+    NOTIFICATION_METRIC_ERROR,
+    NOTIFICATION_METRIC_COUNT
+  };
+
+  enum UserActionMetric {
+    USER_ACTION_METRIC_CLICKED,
+    USER_ACTION_METRIC_CLOSED,
+    USER_ACTION_METRIC_IGNORED,
+    USER_ACTION_METRIC_COUNT
+  };
+
   static const char kNotificationId[];
 
+  static const char kNotificationMetric[];
+  static const char kUserActionMetric[];
+
   NetworkPortalNotificationController();
   virtual ~NetworkPortalNotificationController();
 
diff --git a/chrome/browser/chromeos/options/network_config_view.cc b/chrome/browser/chromeos/options/network_config_view.cc
index 7999cda..51c5282 100644
--- a/chrome/browser/chromeos/options/network_config_view.cc
+++ b/chrome/browser/chromeos/options/network_config_view.cc
@@ -87,12 +87,14 @@
 bool NetworkConfigView::InitWithNetworkState(const NetworkState* network) {
   DCHECK(network);
   std::string service_path = network->path();
-  if (network->type() == shill::kTypeWifi)
+  if (network->type() == shill::kTypeWifi ||
+      network->type() == shill::kTypeEthernet) {
     child_config_view_ = new WifiConfigView(this, service_path, false);
-  else if (network->type() == shill::kTypeWimax)
+  } else if (network->type() == shill::kTypeWimax) {
     child_config_view_ = new WimaxConfigView(this, service_path);
-  else if (network->type() == shill::kTypeVPN)
+  } else if (network->type() == shill::kTypeVPN) {
     child_config_view_ = new VPNConfigView(this, service_path);
+  }
   return child_config_view_ != NULL;
 }
 
@@ -158,8 +160,11 @@
 
 base::string16 NetworkConfigView::GetDialogButtonLabel(
     ui::DialogButton button) const {
-  if (button == ui::DIALOG_BUTTON_OK)
+  if (button == ui::DIALOG_BUTTON_OK) {
+    if (child_config_view_->IsConfigureDialog())
+      return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONFIGURE);
     return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONNECT);
+  }
   return views::DialogDelegateView::GetDialogButtonLabel(button);
 }
 
@@ -291,6 +296,10 @@
 ChildNetworkConfigView::~ChildNetworkConfigView() {
 }
 
+bool ChildNetworkConfigView::IsConfigureDialog() {
+  return false;
+}
+
 // ControlledSettingIndicatorView
 
 ControlledSettingIndicatorView::ControlledSettingIndicatorView()
diff --git a/chrome/browser/chromeos/options/network_config_view.h b/chrome/browser/chromeos/options/network_config_view.h
index a6c4c22..8022b9f 100644
--- a/chrome/browser/chromeos/options/network_config_view.h
+++ b/chrome/browser/chromeos/options/network_config_view.h
@@ -141,6 +141,9 @@
   // being active. For example, clicking on "Advanced" button.
   virtual void InitFocus() = 0;
 
+  // Returns 'true' if the dialog is for configuration only (default is false).
+  virtual bool IsConfigureDialog();
+
   // Minimum with of input fields / combo boxes.
   static const int kInputFieldMinWidth;
 
diff --git a/chrome/browser/chromeos/options/wifi_config_view.cc b/chrome/browser/chromeos/options/wifi_config_view.cc
index 38e4058..675caa5 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.cc
+++ b/chrome/browser/chromeos/options/wifi_config_view.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/chromeos/options/passphrase_textfield.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chromeos/login/login_state.h"
+#include "chromeos/network/favorite_state.h"
 #include "chromeos/network/network_configuration_handler.h"
 #include "chromeos/network/network_event_log.h"
 #include "chromeos/network/network_handler.h"
@@ -21,6 +22,7 @@
 #include "chromeos/network/network_state_handler.h"
 #include "chromeos/network/network_ui_data.h"
 #include "chromeos/network/shill_property_util.h"
+#include "chromeos/tpm_token_loader.h"
 #include "components/onc/onc_constants.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -382,6 +384,9 @@
 }
 
 base::string16 WifiConfigView::GetTitle() const {
+  const NetworkState* network = GetNetworkState();
+  if (network && network->type() == shill::kTypeEthernet)
+    return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_CONFIGURE_ETHERNET);
   return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_JOIN_WIFI_NETWORKS);
 }
 
@@ -401,7 +406,7 @@
 bool WifiConfigView::CanLogin() {
   static const size_t kMinWirelessPasswordLen = 5;
 
-  // We either have an existing wifi network or the user entered an SSID.
+  // We either have an existing network or the user entered an SSID.
   if (service_path_.empty() && GetSsid().empty())
     return false;
 
@@ -583,11 +588,11 @@
     }
   }
   if (error_msg.empty() && !service_path_.empty()) {
-    const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
-        GetNetworkState(service_path_);
-    if (wifi && wifi->connection_state() == shill::kStateFailure)
+    const NetworkState* network = GetNetworkState();
+    if (network && network->connection_state() == shill::kStateFailure) {
       error_msg = ash::network_connect::ErrorString(
-          wifi->last_error(), wifi->path());
+          network->last_error(), network->path());
+    }
   }
   if (!error_msg.empty()) {
     error_label_->SetText(error_msg);
@@ -651,16 +656,13 @@
 }
 
 bool WifiConfigView::Login() {
-  const NetworkState* wifi = !service_path_.empty() ?
-      NetworkHandler::Get()->network_state_handler()->
-          GetNetworkState(service_path_) :
-      NULL;
+  const NetworkState* network = GetNetworkState();
 
   // Set configuration properties.
   base::DictionaryValue properties;
 
   // Default shared state for non-private networks is true.
-  const bool share_default = !wifi || !wifi->IsPrivate();
+  const bool share_default = !network || !network->IsPrivate();
   bool share_network = GetShareNetwork(share_default);
   bool only_policy_autoconnect =
       onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!share_network);
@@ -670,6 +672,8 @@
   }
 
   if (service_path_.empty()) {
+    // TODO(stevenjb): Support modifying existing EAP configurations.
+    // Will probably wait to do this in WebUI instead.
     properties.SetStringWithoutPathExpansion(
         shill::kTypeProperty, shill::kTypeWifi);
     shill_property_util::SetSSID(GetSsid(), &properties);
@@ -679,7 +683,6 @@
         shill::kSaveCredentialsProperty, GetSaveCredentials());
     std::string security = shill::kSecurityNone;
     if (!eap_method_combobox_) {
-      // Hidden ordinary Wi-Fi connection.
       switch (security_combobox_->selected_index()) {
         case SECURITY_INDEX_NONE:
           security = shill::kSecurityNone;
@@ -697,7 +700,6 @@
             shill::kPassphraseProperty, GetPassphrase());
       }
     } else {
-      // Hidden 802.1X EAP Wi-Fi connection.
       security = shill::kSecurity8021x;
       SetEapProperties(&properties);
     }
@@ -708,27 +710,38 @@
     ash::network_connect::CreateConfigurationAndConnect(&properties,
                                                         share_network);
   } else {
-    if (!wifi) {
-      // Shill no longer knows about this wifi network (edge case).
+    if (!network) {
+      // Shill no longer knows about this network (edge case).
       // TODO(stevenjb): Add notification for this.
       NET_LOG_ERROR("Network not found", service_path_);
       return true;  // Close dialog
     }
     if (eap_method_combobox_) {
-      // Visible 802.1X EAP Wi-Fi connection.
       SetEapProperties(&properties);
       properties.SetBooleanWithoutPathExpansion(
           shill::kSaveCredentialsProperty, GetSaveCredentials());
     } else {
-      // Visible ordinary Wi-Fi connection.
       const std::string passphrase = GetPassphrase();
       if (!passphrase.empty()) {
         properties.SetStringWithoutPathExpansion(
             shill::kPassphraseProperty, passphrase);
       }
     }
-    ash::network_connect::ConfigureNetworkAndConnect(
-        service_path_, properties, share_network);
+    if (network->type() == shill::kTypeEthernet) {
+      // When configuring an ethernet service, we actually configure the
+      // EthernetEap service, which exists in the Profile only.
+      // See crbug.com/126870 for more info.
+      properties.SetStringWithoutPathExpansion(shill::kTypeProperty,
+                                               shill::kTypeEthernetEap);
+      share_network = false;
+      // Set the TPM PIN.
+      properties.SetStringWithoutPathExpansion(
+          shill::kEapPinProperty, TPMTokenLoader::Get()->tpm_user_pin());
+      ash::network_connect::CreateConfiguration(&properties, share_network);
+    } else {
+      ash::network_connect::ConfigureNetworkAndConnect(
+          service_path_, properties, share_network);
+    }
   }
   return true;  // dialog will be closed
 }
@@ -882,38 +895,37 @@
 void WifiConfigView::Cancel() {
 }
 
-// This will initialize the view depending on if we have a wifi network or not.
-// And if we are doing simple password encryption or the more complicated
-// 802.1x encryption.
-// If we are creating the "Join other network..." dialog, we will allow user
-// to enter the data. And if they select the 802.1x encryption, we will show
-// the 802.1x fields.
 void WifiConfigView::Init(bool show_8021x) {
-  const NetworkState* wifi = NetworkHandler::Get()->network_state_handler()->
-      GetNetworkState(service_path_);
-  if (wifi) {
-    DCHECK(wifi->type() == shill::kTypeWifi);
-    if (wifi->security() == shill::kSecurity8021x)
+  const NetworkState* network = GetNetworkState();
+  if (network) {
+    if (network->type() == shill::kTypeWifi) {
+      if (network->security() == shill::kSecurity8021x)
+        show_8021x = true;
+    } else if (network->type() == shill::kTypeEthernet) {
       show_8021x = true;
-    ParseWiFiEAPUIProperty(&eap_method_ui_data_, wifi, ::onc::eap::kOuter);
-    ParseWiFiEAPUIProperty(&phase_2_auth_ui_data_, wifi, ::onc::eap::kInner);
-    ParseWiFiEAPUIProperty(&user_cert_ui_data_, wifi,
-                           ::onc::eap::kClientCertRef);
-    ParseWiFiEAPUIProperty(&server_ca_cert_ui_data_, wifi,
-                           ::onc::eap::kServerCARef);
-    if (server_ca_cert_ui_data_.IsManaged()) {
-      ParseWiFiEAPUIProperty(&server_ca_cert_ui_data_, wifi,
-                             ::onc::eap::kUseSystemCAs);
+    } else {
+      NOTREACHED() << "Unexpected network type for WifiConfigView: "
+                   << network->type() << " Path: " << service_path_;
     }
-    ParseWiFiEAPUIProperty(&identity_ui_data_, wifi, ::onc::eap::kIdentity);
-    ParseWiFiEAPUIProperty(&identity_anonymous_ui_data_, wifi,
-                           ::onc::eap::kAnonymousIdentity);
-    ParseWiFiEAPUIProperty(&save_credentials_ui_data_, wifi,
-                           ::onc::eap::kSaveCredentials);
+    ParseEAPUIProperty(&eap_method_ui_data_, network, ::onc::eap::kOuter);
+    ParseEAPUIProperty(&phase_2_auth_ui_data_, network, ::onc::eap::kInner);
+    ParseEAPUIProperty(
+        &user_cert_ui_data_, network, ::onc::eap::kClientCertRef);
+    ParseEAPUIProperty(
+        &server_ca_cert_ui_data_, network, ::onc::eap::kServerCARef);
+    if (server_ca_cert_ui_data_.IsManaged()) {
+      ParseEAPUIProperty(
+          &server_ca_cert_ui_data_, network, ::onc::eap::kUseSystemCAs);
+    }
+    ParseEAPUIProperty(&identity_ui_data_, network, ::onc::eap::kIdentity);
+    ParseEAPUIProperty(
+        &identity_anonymous_ui_data_, network, ::onc::eap::kAnonymousIdentity);
+    ParseEAPUIProperty(
+        &save_credentials_ui_data_, network, ::onc::eap::kSaveCredentials);
     if (show_8021x)
-      ParseWiFiEAPUIProperty(&passphrase_ui_data_, wifi, ::onc::eap::kPassword);
+      ParseEAPUIProperty(&passphrase_ui_data_, network, ::onc::eap::kPassword);
     else
-      ParseWiFiUIProperty(&passphrase_ui_data_, wifi, ::onc::wifi::kPassphrase);
+      ParseUIProperty(&passphrase_ui_data_, network, ::onc::wifi::kPassphrase);
   }
 
   views::GridLayout* layout = views::GridLayout::CreatePanel(this);
@@ -936,24 +948,27 @@
                         views::GridLayout::USE_PREF, 0, kPasswordVisibleWidth);
 
   // SSID input
-  layout->StartRow(0, column_view_set_id);
-  layout->AddView(new views::Label(l10n_util::GetStringUTF16(
-      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID)));
-  if (!wifi) {
-    ssid_textfield_ = new views::Textfield();
-    ssid_textfield_->set_controller(this);
-    ssid_textfield_->SetAccessibleName(l10n_util::GetStringUTF16(
-        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID));
-    layout->AddView(ssid_textfield_);
-  } else {
-    views::Label* label = new views::Label(base::UTF8ToUTF16(wifi->name()));
-    label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
-    layout->AddView(label);
+  if (!network || network->type() != shill::kTypeEthernet) {
+    layout->StartRow(0, column_view_set_id);
+    layout->AddView(new views::Label(l10n_util::GetStringUTF16(
+        IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID)));
+    if (!network) {
+      ssid_textfield_ = new views::Textfield();
+      ssid_textfield_->set_controller(this);
+      ssid_textfield_->SetAccessibleName(l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_NETWORK_ID));
+      layout->AddView(ssid_textfield_);
+    } else {
+      views::Label* label =
+          new views::Label(base::UTF8ToUTF16(network->name()));
+      label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+      layout->AddView(label);
+    }
+    layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
   }
-  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
 
   // Security select
-  if (!wifi && !show_8021x) {
+  if (!network && !show_8021x) {
     layout->StartRow(0, column_view_set_id);
     base::string16 label_text = l10n_util::GetStringUTF16(
         IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SECURITY);
@@ -1077,8 +1092,9 @@
   passphrase_textfield_ = new PassphraseTextfield();
   passphrase_textfield_->set_controller(this);
   // Disable passphrase input initially for other network.
-  passphrase_label_->SetEnabled(wifi);
-  passphrase_textfield_->SetEnabled(wifi && passphrase_ui_data_.IsEditable());
+  passphrase_label_->SetEnabled(network);
+  passphrase_textfield_->SetEnabled(network &&
+                                    passphrase_ui_data_.IsEditable());
   passphrase_textfield_->SetAccessibleName(passphrase_label_text);
   layout->AddView(passphrase_textfield_);
 
@@ -1151,7 +1167,7 @@
   }
 
   // Share network
-  if (!wifi || wifi->profile_path().empty()) {
+  if (!network || network->profile_path().empty()) {
     layout->StartRow(0, column_view_set_id);
     share_network_checkbox_ = new views::Checkbox(
         l10n_util::GetStringUTF16(
@@ -1171,17 +1187,18 @@
 
   // Initialize the field and checkbox values.
 
-  if (!wifi && show_8021x)
+  if (!network && show_8021x)
     RefreshEapFields();
 
   RefreshShareCheckbox();
   UpdateErrorLabel();
 
-  if (wifi) {
+  if (network) {
     NetworkHandler::Get()->network_configuration_handler()->GetProperties(
         service_path_,
         base::Bind(&WifiConfigView::InitFromProperties,
-                   weak_ptr_factory_.GetWeakPtr(), show_8021x),
+                   weak_ptr_factory_.GetWeakPtr(),
+                   show_8021x),
         base::Bind(&ShillError, "GetProperties"));
   }
 }
@@ -1324,35 +1341,45 @@
     view_to_focus->RequestFocus();
 }
 
+bool WifiConfigView::IsConfigureDialog() {
+  const NetworkState* network = GetNetworkState();
+  return network && network->type() == shill::kTypeEthernet;
+}
+
 void WifiConfigView::NetworkPropertiesUpdated(const NetworkState* network) {
   if (network->path() != service_path_)
     return;
   UpdateErrorLabel();
 }
 
-// static
-void WifiConfigView::ParseWiFiUIProperty(
-    NetworkPropertyUIData* property_ui_data,
-    const NetworkState* network,
-    const std::string& key) {
-  ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
-  const base::DictionaryValue* onc =
-      onc::FindPolicyForActiveUser(network->guid(), &onc_source);
-
-  property_ui_data->ParseOncProperty(
-      onc_source,
-      onc,
-      base::StringPrintf("%s.%s", ::onc::network_config::kWiFi, key.c_str()));
+const NetworkState* WifiConfigView::GetNetworkState() const {
+  if (service_path_.empty())
+    return NULL;
+  return NetworkHandler::Get()->network_state_handler()->GetNetworkState(
+      service_path_);
 }
 
 // static
-void WifiConfigView::ParseWiFiEAPUIProperty(
-    NetworkPropertyUIData* property_ui_data,
-    const NetworkState* network,
-    const std::string& key) {
-  ParseWiFiUIProperty(
-      property_ui_data, network,
-      base::StringPrintf("%s.%s", ::onc::wifi::kEAP, key.c_str()));
+void WifiConfigView::ParseUIProperty(NetworkPropertyUIData* property_ui_data,
+                                     const NetworkState* network,
+                                     const std::string& key) {
+  ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_NONE;
+  const base::DictionaryValue* onc =
+      onc::FindPolicyForActiveUser(network->guid(), &onc_source);
+  std::string onc_tag = network->type() == shill::kTypeEthernet
+                            ? ::onc::network_config::kWiFi
+                            : ::onc::network_config::kEthernet;
+  property_ui_data->ParseOncProperty(onc_source, onc, onc_tag + '.' + key);
+}
+
+// static
+void WifiConfigView::ParseEAPUIProperty(NetworkPropertyUIData* property_ui_data,
+                                        const NetworkState* network,
+                                        const std::string& key) {
+  std::string onc_tag = network->type() == shill::kTypeEthernet
+                            ? ::onc::ethernet::kEAP
+                            : ::onc::wifi::kEAP;
+  ParseUIProperty(property_ui_data, network, onc_tag + '.' + key);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/options/wifi_config_view.h b/chrome/browser/chromeos/options/wifi_config_view.h
index 4757934..da8d78d 100644
--- a/chrome/browser/chromeos/options/wifi_config_view.h
+++ b/chrome/browser/chromeos/options/wifi_config_view.h
@@ -42,7 +42,8 @@
 class UserCertComboboxModel;
 }
 
-// A dialog box for showing a password textfield.
+// A dialog box for configuring Wifi and Ethernet networks
+
 class WifiConfigView : public ChildNetworkConfigView,
                        public views::TextfieldController,
                        public views::ButtonListener,
@@ -50,9 +51,9 @@
                        public CertLibrary::Observer,
                        public NetworkStateHandlerObserver {
  public:
-  // Configuration dialog for a WiFi network. If |service_path| is not empty
-  // it identifies the network to be configured. Otherwise |show_8021x|
-  // determines whether or not to show the 'advanced' 8021x configuration UI.
+  // If |service_path| is not empty it identifies the network to be configured.
+  // Otherwise |show_8021x| determines whether or not to show the 'advanced'
+  // 8021x configuration UI for a hidden WiFi network.
   WifiConfigView(NetworkConfigView* parent,
                  const std::string& service_path,
                  bool show_8021x);
@@ -81,26 +82,29 @@
   virtual bool Login() OVERRIDE;
   virtual void Cancel() OVERRIDE;
   virtual void InitFocus() OVERRIDE;
+  virtual bool IsConfigureDialog() OVERRIDE;
 
   // NetworkStateHandlerObserver
   virtual void NetworkPropertiesUpdated(const NetworkState* network) OVERRIDE;
 
-  // Parses a WiFi UI |property| from the ONC associated with |network|. |key|
-  // is the property name within the ONC WiFi dictionary.
-  static void ParseWiFiUIProperty(NetworkPropertyUIData* property_ui_data,
-                                  const NetworkState* network,
-                                  const std::string& key);
+  // Parses a UI |property| from the ONC associated with |network|. |key|
+  // is the property name within the ONC dictionary.
+  static void ParseUIProperty(NetworkPropertyUIData* property_ui_data,
+                              const NetworkState* network,
+                              const std::string& key);
 
-  // Parses a WiFi EAP UI |property| from the ONC associated with |network|.
-  // |key| is the property name within the ONC WiFi.EAP dictionary.
-  static void ParseWiFiEAPUIProperty(NetworkPropertyUIData* property_ui_data,
-                                     const NetworkState* network,
-                                     const std::string& key);
+  // Parses an EAP UI |property| from the ONC associated with |network|.
+  // |key| is the property name within the ONC EAP dictionary.
+  static void ParseEAPUIProperty(NetworkPropertyUIData* property_ui_data,
+                                 const NetworkState* network,
+                                 const std::string& key);
 
  private:
   friend class internal::UserCertComboboxModel;
 
-  // Initializes UI.  If |show_8021x| includes 802.1x config options.
+  // This will initialize the view depending on whether an existing network
+  // is being configured, the type of network, and the security model (i.e.
+  // simple password encryption or 802.1x).
   void Init(bool show_8021x);
 
   // Callback to initialize fields from uncached network properties.
@@ -160,6 +164,10 @@
   // Updates the error text label.
   void UpdateErrorLabel();
 
+  // Helper method, returns NULL if |service_path_| is empty, otherwise returns
+  // the NetworkState* associated with |service_path_| or NULL if none exists.
+  const NetworkState* GetNetworkState() const;
+
   NetworkPropertyUIData eap_method_ui_data_;
   NetworkPropertyUIData phase_2_auth_ui_data_;
   NetworkPropertyUIData user_cert_ui_data_;
diff --git a/chrome/browser/chromeos/options/wimax_config_view.cc b/chrome/browser/chromeos/options/wimax_config_view.cc
index db669db..a1752be 100644
--- a/chrome/browser/chromeos/options/wimax_config_view.cc
+++ b/chrome/browser/chromeos/options/wimax_config_view.cc
@@ -204,11 +204,11 @@
       GetNetworkState(service_path_);
   DCHECK(wimax && wimax->type() == shill::kTypeWimax);
 
-  WifiConfigView::ParseWiFiEAPUIProperty(
+  WifiConfigView::ParseEAPUIProperty(
       &save_credentials_ui_data_, wimax, ::onc::eap::kSaveCredentials);
-  WifiConfigView::ParseWiFiEAPUIProperty(
+  WifiConfigView::ParseEAPUIProperty(
       &identity_ui_data_, wimax, ::onc::eap::kIdentity);
-  WifiConfigView::ParseWiFiUIProperty(
+  WifiConfigView::ParseUIProperty(
       &passphrase_ui_data_, wimax, ::onc::wifi::kPassphrase);
 
   views::GridLayout* layout = views::GridLayout::CreatePanel(this);
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client.cc b/chrome/browser/chromeos/policy/auto_enrollment_client.cc
index ac7ee69..2b7bdde 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client.cc
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
 
 #include "base/bind.h"
-#include "base/command_line.h"
 #include "base/guid.h"
 #include "base/location.h"
 #include "base/logging.h"
@@ -15,14 +14,10 @@
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
-#include "base/strings/string_number_conversions.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/policy/server_backed_device_state.h"
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/common/pref_names.h"
-#include "chromeos/chromeos_switches.h"
-#include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/cloud/device_management_service.h"
 #include "components/policy/core/common/cloud/system_policy_request_context.h"
 #include "content/public/browser/browser_thread.h"
@@ -46,45 +41,14 @@
 const char kUMANetworkErrorCode[] =
     "Enterprise.AutoEnrollmentRequestNetworkErrorCode";
 
-// The modulus value is sent in an int64 field in the protobuf, whose maximum
-// value is 2^63-1. So 2^64 and 2^63 can't be represented as moduli and the
-// max is 2^62 (when the moduli are restricted to powers-of-2).
-const int kMaximumPower = 62;
-
-// Returns the int value of the |switch_name| argument, clamped to the [0, 62]
-// interval. Returns 0 if the argument doesn't exist or isn't an int value.
-int GetSanitizedArg(const std::string& switch_name) {
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (!command_line->HasSwitch(switch_name))
-    return 0;
-  std::string value = command_line->GetSwitchValueASCII(switch_name);
-  int int_value;
-  if (!base::StringToInt(value, &int_value)) {
-    LOG(ERROR) << "Switch \"" << switch_name << "\" is not a valid int. "
-               << "Defaulting to 0.";
-    return 0;
-  }
-  if (int_value < 0) {
-    LOG(ERROR) << "Switch \"" << switch_name << "\" can't be negative. "
-               << "Using 0";
-    return 0;
-  }
-  if (int_value > kMaximumPower) {
-    LOG(ERROR) << "Switch \"" << switch_name << "\" can't be greater than "
-               << kMaximumPower << ". Using " << kMaximumPower;
-    return kMaximumPower;
-  }
-  return int_value;
-}
-
 // Returns the power of the next power-of-2 starting at |value|.
 int NextPowerOf2(int64 value) {
-  for (int i = 0; i <= kMaximumPower; ++i) {
+  for (int i = 0; i <= AutoEnrollmentClient::kMaximumPower; ++i) {
     if ((GG_INT64_C(1) << i) >= value)
       return i;
   }
   // No other value can be represented in an int64.
-  return kMaximumPower + 1;
+  return AutoEnrollmentClient::kMaximumPower + 1;
 }
 
 // Sets or clears a value in a dictionary.
@@ -128,7 +92,7 @@
     int power_initial,
     int power_limit)
     : progress_callback_(callback),
-      state_(STATE_PENDING),
+      state_(AUTO_ENROLLMENT_STATE_IDLE),
       has_server_state_(false),
       device_state_available_(false),
       device_id_(base::GenerateGUID()),
@@ -148,7 +112,6 @@
     server_backed_state_key_hash_ =
         crypto::SHA256HashString(server_backed_state_key_);
   }
-  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
 }
 
 AutoEnrollmentClient::~AutoEnrollmentClient() {
@@ -162,64 +125,6 @@
 }
 
 // static
-bool AutoEnrollmentClient::IsDisabled() {
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  // Do not communicate auto-enrollment data to the server if
-  // 1. we are running integration or perf tests with telemetry.
-  // 2. modulus configuration is not present.
-  return command_line->HasSwitch(chromeos::switches::kOobeSkipPostLogin) ||
-         (!command_line->HasSwitch(
-              chromeos::switches::kEnterpriseEnrollmentInitialModulus) &&
-          !command_line->HasSwitch(
-              chromeos::switches::kEnterpriseEnrollmentModulusLimit));
-}
-
-// static
-AutoEnrollmentClient* AutoEnrollmentClient::Create(
-    const ProgressCallback& progress_callback) {
-  // The client won't do anything if |service| is NULL.
-  DeviceManagementService* service = NULL;
-  if (IsDisabled()) {
-    VLOG(1) << "Auto-enrollment is disabled";
-  } else {
-    BrowserPolicyConnector* connector =
-        g_browser_process->browser_policy_connector();
-    service = connector->device_management_service();
-    service->ScheduleInitialization(0);
-  }
-
-  int power_initial = GetSanitizedArg(
-      chromeos::switches::kEnterpriseEnrollmentInitialModulus);
-  int power_limit = GetSanitizedArg(
-      chromeos::switches::kEnterpriseEnrollmentModulusLimit);
-  if (power_initial > power_limit) {
-    LOG(ERROR) << "Initial auto-enrollment modulus is larger than the limit, "
-               << "clamping to the limit.";
-    power_initial = power_limit;
-  }
-
-  bool retrieve_device_state = false;
-  std::string device_id;
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kEnterpriseEnableForcedReEnrollment)) {
-    retrieve_device_state = true;
-    device_id = DeviceCloudPolicyManagerChromeOS::GetDeviceStateKey();
-  } else {
-    device_id = DeviceCloudPolicyManagerChromeOS::GetMachineID();
-  }
-
-  return new AutoEnrollmentClient(
-      progress_callback,
-      service,
-      g_browser_process->local_state(),
-      g_browser_process->system_request_context(),
-      device_id,
-      retrieve_device_state,
-      power_initial,
-      power_limit);
-}
-
-// static
 void AutoEnrollmentClient::CancelAutoEnrollment() {
   PrefService* local_state = g_browser_process->local_state();
   local_state->SetBoolean(prefs::kShouldAutoEnroll, false);
@@ -228,9 +133,13 @@
 }
 
 void AutoEnrollmentClient::Start() {
+  // (Re-)register the network change observer.
+  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
+
   // Drop the previous job and reset state.
   request_job_.reset();
-  state_ = STATE_PENDING;
+  state_ = AUTO_ENROLLMENT_STATE_PENDING;
   time_start_ = base::Time::Now();
   modulus_updates_received_ = 0;
   has_server_state_ = false;
@@ -239,6 +148,10 @@
   NextStep();
 }
 
+void AutoEnrollmentClient::Retry() {
+  RetryStep();
+}
+
 void AutoEnrollmentClient::CancelAndDeleteSoon() {
   if (time_start_.is_null() || !request_job_) {
     // The client isn't running, just delete it.
@@ -305,7 +218,7 @@
   return false;
 }
 
-void AutoEnrollmentClient::ReportProgress(State state) {
+void AutoEnrollmentClient::ReportProgress(AutoEnrollmentState state) {
   state_ = state;
   if (progress_callback_.is_null()) {
     base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this);
@@ -330,8 +243,8 @@
       trigger_enrollment = has_server_state_;
     }
 
-    ReportProgress(trigger_enrollment ? STATE_TRIGGER_ENROLLMENT
-                                      : STATE_NO_ENROLLMENT);
+    ReportProgress(trigger_enrollment ? AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT
+                                      : AUTO_ENROLLMENT_STATE_NO_ENROLLMENT);
   }
 }
 
@@ -348,7 +261,7 @@
   }
   remainder = remainder & ((GG_UINT64_C(1) << current_power_) - 1);
 
-  ReportProgress(STATE_PENDING);
+  ReportProgress(AUTO_ENROLLMENT_STATE_PENDING);
 
   request_job_.reset(
       device_management_service_->CreateJob(
@@ -367,7 +280,7 @@
 }
 
 bool AutoEnrollmentClient::SendDeviceStateRequest() {
-  ReportProgress(STATE_PENDING);
+  ReportProgress(AUTO_ENROLLMENT_STATE_PENDING);
 
   request_job_.reset(
       device_management_service_->CreateJob(
@@ -400,8 +313,9 @@
     if (progress_callback_.is_null()) {
       base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this);
     } else {
-      ReportProgress(status == DM_STATUS_REQUEST_FAILED ? STATE_CONNECTION_ERROR
-                                                        : STATE_SERVER_ERROR);
+      ReportProgress(status == DM_STATUS_REQUEST_FAILED
+                         ? AUTO_ENROLLMENT_STATE_CONNECTION_ERROR
+                         : AUTO_ENROLLMENT_STATE_SERVER_ERROR);
     }
     return;
   }
@@ -411,7 +325,7 @@
   if (progress)
     NextStep();
   else
-    ReportProgress(STATE_SERVER_ERROR);
+    ReportProgress(AUTO_ENROLLMENT_STATE_SERVER_ERROR);
 }
 
 bool AutoEnrollmentClient::OnBucketDownloadRequestCompletion(
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client.h b/chrome/browser/chromeos/policy/auto_enrollment_client.h
index 39c07f6..1adc415 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client.h
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client.h
@@ -32,28 +32,35 @@
 class DeviceManagementRequestJob;
 class DeviceManagementService;
 
+// Indicates the current state of the auto-enrollment check.
+enum AutoEnrollmentState {
+  // Not yet started.
+  AUTO_ENROLLMENT_STATE_IDLE,
+  // Working, another event will be fired eventually.
+  AUTO_ENROLLMENT_STATE_PENDING,
+  // Failed to connect to DMServer.
+  AUTO_ENROLLMENT_STATE_CONNECTION_ERROR,
+  // Connection successful, but the server failed to generate a valid reply.
+  AUTO_ENROLLMENT_STATE_SERVER_ERROR,
+  // Check completed successfully, enrollment should be triggered.
+  AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT,
+  // Check completed successfully, enrollment not applicable.
+  AUTO_ENROLLMENT_STATE_NO_ENROLLMENT,
+};
+
 // Interacts with the device management service and determines whether this
 // machine should automatically enter the Enterprise Enrollment screen during
 // OOBE.
 class AutoEnrollmentClient
     : public net::NetworkChangeNotifier::NetworkChangeObserver {
  public:
-  // Indicates the current state of the auto-enrollment check.
-  enum State {
-    // Working, another event will be fired eventually.
-    STATE_PENDING,
-    // Failed to connect to DMServer.
-    STATE_CONNECTION_ERROR,
-    // Connection successful, but the server failed to generate a valid reply.
-    STATE_SERVER_ERROR,
-    // Check completed successfully, enrollment should be triggered.
-    STATE_TRIGGER_ENROLLMENT,
-    // Check completed successfully, enrollment not applicable.
-    STATE_NO_ENROLLMENT,
-  };
+  // The modulus value is sent in an int64 field in the protobuf, whose maximum
+  // value is 2^63-1. So 2^64 and 2^63 can't be represented as moduli and the
+  // max is 2^62 (when the moduli are restricted to powers-of-2).
+  static const int kMaximumPower = 62;
 
   // Used for signaling progress to a consumer.
-  typedef base::Callback<void(State)> ProgressCallback;
+  typedef base::Callback<void(AutoEnrollmentState)> ProgressCallback;
 
   // |progress_callback| will be invoked whenever some significant event happens
   // as part of the protocol, after Start() is invoked.
@@ -74,14 +81,6 @@
   // Registers preferences in local state.
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
-  // Returns true if auto-enrollment is disabled in this device. In that case,
-  // instances returned by Create() fail immediately once Start() is invoked.
-  static bool IsDisabled();
-
-  // Convenience method to create instances of this class.
-  static AutoEnrollmentClient* Create(
-      const ProgressCallback& progress_callback);
-
   // Cancels auto-enrollment.
   // This function does not interrupt a running auto-enrollment check. It only
   // stores a pref in |local_state| that prevents the client from entering
@@ -93,6 +92,11 @@
   // call can invoke the |progress_callback_| if errors occur.
   void Start();
 
+  // Triggers a retry of the currently pending step. This is intended to be
+  // called by consumers when they become aware of environment changes (such as
+  // captive portal setup being complete).
+  void Retry();
+
   // Cancels any pending requests. |progress_callback_| will not be invoked.
   // |this| will delete itself.
   void CancelAndDeleteSoon();
@@ -102,7 +106,7 @@
   std::string device_id() const { return device_id_; }
 
   // Current state.
-  State state() const { return state_; }
+  AutoEnrollmentState state() const { return state_; }
 
   // Implementation of net::NetworkChangeNotifier::NetworkChangeObserver:
   virtual void OnNetworkChanged(
@@ -123,7 +127,7 @@
   bool RetryStep();
 
   // Cleans up and invokes |progress_callback_|.
-  void ReportProgress(State state);
+  void ReportProgress(AutoEnrollmentState state);
 
   // Calls RetryStep() to make progress or determine that all is done. In the
   // latter case, calls ReportProgress().
@@ -167,7 +171,7 @@
   ProgressCallback progress_callback_;
 
   // Current state.
-  State state_;
+  AutoEnrollmentState state_;
 
   // Whether the hash bucket check succeeded, indicating that the server knows
   // this device and might have keep state for it.
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_unittest.cc b/chrome/browser/chromeos/policy/auto_enrollment_client_unittest.cc
index 58d2f70..d8fb571 100644
--- a/chrome/browser/chromeos/policy/auto_enrollment_client_unittest.cc
+++ b/chrome/browser/chromeos/policy/auto_enrollment_client_unittest.cc
@@ -46,7 +46,7 @@
       : scoped_testing_local_state_(
             TestingBrowserProcess::GetGlobal()),
         local_state_(scoped_testing_local_state_.Get()),
-        state_(AutoEnrollmentClient::STATE_PENDING) {}
+        state_(AUTO_ENROLLMENT_STATE_PENDING) {}
 
   virtual void SetUp() OVERRIDE {
     CreateClient(kStateKey, true, 4, 8);
@@ -63,7 +63,7 @@
                     bool retrieve_device_state,
                     int power_initial,
                     int power_limit) {
-    state_ = AutoEnrollmentClient::STATE_PENDING;
+    state_ = AUTO_ENROLLMENT_STATE_PENDING;
     service_.reset(new MockDeviceManagementService());
     EXPECT_CALL(*service_, StartJob(_, _, _, _, _, _, _))
         .WillRepeatedly(SaveArg<6>(&last_request_));
@@ -80,7 +80,7 @@
         power_limit));
   }
 
-  void ProgressCallback(AutoEnrollmentClient::State state) {
+  void ProgressCallback(AutoEnrollmentState state) {
     state_ = state;
   }
 
@@ -158,7 +158,7 @@
   scoped_ptr<MockDeviceManagementService> service_;
   scoped_ptr<AutoEnrollmentClient> client_;
   em::DeviceManagementRequest last_request_;
-  AutoEnrollmentClient::State state_;
+  AutoEnrollmentState state_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClientTest);
@@ -167,21 +167,21 @@
 TEST_F(AutoEnrollmentClientTest, NetworkFailure) {
   ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
 }
 
 TEST_F(AutoEnrollmentClientTest, EmptyReply) {
   ServerWillReply(-1, false, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
   VerifyCachedResult(false, 8);
 }
 
 TEST_F(AutoEnrollmentClientTest, ClientUploadsRightBits) {
   ServerWillReply(-1, false, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
 
   EXPECT_TRUE(auto_enrollment_request().has_remainder());
   EXPECT_TRUE(auto_enrollment_request().has_modulus());
@@ -195,7 +195,7 @@
   ServerWillReply(32, false, false);
   ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
 }
 
@@ -204,7 +204,7 @@
   ServerWillReply(32, false, false);
   ServerWillReply(64, false, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
 }
 
@@ -216,7 +216,7 @@
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyCachedResult(true, 8);
 }
 
@@ -228,7 +228,7 @@
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyCachedResult(true, 8);
 }
 
@@ -237,14 +237,14 @@
   ServerWillReply(16, false, false);
   ServerWillReply(16, false, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
 }
 
 TEST_F(AutoEnrollmentClientTest, AskForTooMuch) {
   ServerWillReply(512, false, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
 }
 
@@ -253,7 +253,7 @@
   ServerWillReply(100, false, false);
   ServerWillReply(-1, false, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
   EXPECT_TRUE(auto_enrollment_request().has_remainder());
   EXPECT_TRUE(auto_enrollment_request().has_modulus());
   EXPECT_EQ(128, auto_enrollment_request().modulus());
@@ -264,13 +264,13 @@
 TEST_F(AutoEnrollmentClientTest, ConsumerDevice) {
   ServerWillReply(-1, true, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
   VerifyCachedResult(false, 8);
 
   // Network changes don't trigger retries after obtaining a response from
   // the server.
   client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
 }
 
 TEST_F(AutoEnrollmentClientTest, EnterpriseDevice) {
@@ -279,19 +279,19 @@
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyCachedResult(true, 8);
 
   // Network changes don't trigger retries after obtaining a response from
   // the server.
   client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
 }
 
 TEST_F(AutoEnrollmentClientTest, NoSerial) {
   CreateClient("", true, 4, 8);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
   EXPECT_FALSE(HasCachedDecision());
 }
 
@@ -299,7 +299,7 @@
   CreateClient(kStateKey, true, 0, 0);
   ServerWillReply(-1, false, false);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
   EXPECT_TRUE(auto_enrollment_request().has_remainder());
   EXPECT_TRUE(auto_enrollment_request().has_modulus());
   EXPECT_EQ(1, auto_enrollment_request().modulus());
@@ -313,7 +313,7 @@
     CreateClient(kStateKey, true, i, i);
     ServerWillReply(-1, false, false);
     client_->Start();
-    EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+    EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
     EXPECT_TRUE(auto_enrollment_request().has_remainder());
     EXPECT_TRUE(auto_enrollment_request().has_modulus());
     EXPECT_EQ(GG_INT64_C(1) << i, auto_enrollment_request().modulus());
@@ -332,50 +332,50 @@
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyCachedResult(true, 37);
 }
 
 TEST_F(AutoEnrollmentClientTest, ReuseCachedDecision) {
   EXPECT_CALL(*service_, CreateJob(_, _)).Times(0);
   local_state_->SetUserPref(prefs::kShouldAutoEnroll,
-                            base::Value::CreateBooleanValue(true));
+                            new base::FundamentalValue(true));
   local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit,
-                            base::Value::CreateIntegerValue(8));
+                            new base::FundamentalValue(8));
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   AutoEnrollmentClient::CancelAutoEnrollment();
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_NO_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_NO_ENROLLMENT, state_);
 }
 
 TEST_F(AutoEnrollmentClientTest, RetryIfPowerLargerThanCached) {
   local_state_->SetUserPref(prefs::kShouldAutoEnroll,
-                            base::Value::CreateBooleanValue(false));
+                            new base::FundamentalValue(false));
   local_state_->SetUserPref(prefs::kAutoEnrollmentPowerLimit,
-                            base::Value::CreateIntegerValue(8));
+                            new base::FundamentalValue(8));
   CreateClient(kStateKey, true, 5, 10);
   ServerWillReply(-1, true, true);
   ServerWillSendState(
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
 }
 
 TEST_F(AutoEnrollmentClientTest, NetworkChangeRetryAfterErrors) {
   ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
   client_->Start();
   // Don't invoke the callback if there was a network failure.
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
 
   // The client doesn't retry if no new connection became available.
   client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
 
   // Retry once the network is back.
@@ -384,13 +384,13 @@
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   EXPECT_TRUE(HasCachedDecision());
 
   // Subsequent network changes don't trigger retries.
   client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_NONE);
   client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   EXPECT_TRUE(HasCachedDecision());
 }
 
@@ -400,7 +400,7 @@
   EXPECT_FALSE(job);
   client_->Start();
   ASSERT_TRUE(job);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_PENDING, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
 
   // Cancel while a request is in flight.
   EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
@@ -412,7 +412,7 @@
                     em::DeviceManagementResponse());
   // The DeleteSoon task has been posted:
   EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting());
-  EXPECT_EQ(AutoEnrollmentClient::STATE_PENDING, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
 }
 
 TEST_F(AutoEnrollmentClientTest, NetworkChangedAfterCancelAndDeleteSoon) {
@@ -421,7 +421,7 @@
   EXPECT_FALSE(job);
   client_->Start();
   ASSERT_TRUE(job);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_PENDING, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
 
   // Cancel while a request is in flight.
   EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
@@ -431,18 +431,18 @@
 
   // Network change events are ignored while a request is pending.
   client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_PENDING, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
 
   // The client cleans itself up once a reply is received.
   job->SendResponse(DM_STATUS_TEMPORARY_UNAVAILABLE,
                     em::DeviceManagementResponse());
   // The DeleteSoon task has been posted:
   EXPECT_FALSE(base::MessageLoop::current()->IsIdleForTesting());
-  EXPECT_EQ(AutoEnrollmentClient::STATE_PENDING, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
 
   // Network changes that have been posted before are also ignored:
   client->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_PENDING, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_PENDING, state_);
 }
 
 TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterCompletion) {
@@ -451,7 +451,7 @@
       "example.com",
       em::DeviceStateRetrievalResponse::RESTORE_MODE_REENROLLMENT_ENFORCED);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
 
   // The client will delete itself immediately if there are no pending
   // requests.
@@ -463,7 +463,7 @@
 TEST_F(AutoEnrollmentClientTest, CancelAndDeleteSoonAfterNetworkFailure) {
   ServerWillFail(DM_STATUS_TEMPORARY_UNAVAILABLE);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_SERVER_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_SERVER_ERROR, state_);
 
   // The client will delete itself immediately if there are no pending
   // requests.
@@ -480,7 +480,7 @@
   ServerWillFail(DM_STATUS_REQUEST_FAILED);
   client_->Start();
   // Callback should signal the connection error.
-  EXPECT_EQ(AutoEnrollmentClient::STATE_CONNECTION_ERROR, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_CONNECTION_ERROR, state_);
   EXPECT_FALSE(HasCachedDecision());
   Mock::VerifyAndClearExpectations(service_.get());
 
@@ -499,7 +499,7 @@
 
   // Trigger a network change event.
   client_->OnNetworkChanged(net::NetworkChangeNotifier::CONNECTION_ETHERNET);
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   EXPECT_TRUE(HasCachedDecision());
   Mock::VerifyAndClearExpectations(service_.get());
 }
@@ -511,7 +511,7 @@
               CreateJob(DeviceManagementRequestJob::TYPE_DEVICE_STATE_RETRIEVAL,
                         _)).Times(0);
   client_->Start();
-  EXPECT_EQ(AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT, state_);
+  EXPECT_EQ(AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT, state_);
   VerifyCachedResult(true, 8);
 }
 
diff --git a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
index 64ceaa4..7dbcf1b 100644
--- a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.cc
@@ -17,7 +17,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
-#include "chrome/browser/chromeos/policy/login_screen_power_management_policy.h"
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/dbus/power_policy_controller.h"
@@ -302,7 +301,7 @@
   base::JSONWriter::WriteWithOptions(toplevel_dict.get(),
                                      base::JSONWriter::OPTIONS_PRETTY_PRINT,
                                      &json_string);
-  return base::Value::CreateStringValue(json_string);
+  return new base::StringValue(json_string);
 }
 
 PinnedLauncherAppsPolicyHandler::PinnedLauncherAppsPolicyHandler()
@@ -348,37 +347,24 @@
   int value_in_range;
   if (value && EnsureInRange(value, &value_in_range, NULL)) {
     prefs->SetValue(prefs::kScreenMagnifierEnabled,
-                    base::Value::CreateBooleanValue(value_in_range != 0));
+                    new base::FundamentalValue(value_in_range != 0));
     prefs->SetValue(prefs::kScreenMagnifierType,
-                    base::Value::CreateIntegerValue(value_in_range));
+                    new base::FundamentalValue(value_in_range));
   }
 }
 
 LoginScreenPowerManagementPolicyHandler::
-    LoginScreenPowerManagementPolicyHandler()
-    : TypeCheckingPolicyHandler(key::kDeviceLoginScreenPowerManagement,
-                                base::Value::TYPE_STRING) {
+    LoginScreenPowerManagementPolicyHandler(const Schema& chrome_schema)
+    : SchemaValidatingPolicyHandler(key::kDeviceLoginScreenPowerManagement,
+                                    chrome_schema.GetKnownProperty(
+                                        key::kDeviceLoginScreenPowerManagement),
+                                    SCHEMA_ALLOW_UNKNOWN) {
 }
 
 LoginScreenPowerManagementPolicyHandler::
     ~LoginScreenPowerManagementPolicyHandler() {
 }
 
-bool LoginScreenPowerManagementPolicyHandler::CheckPolicySettings(
-    const PolicyMap& policies,
-    PolicyErrorMap* errors) {
-  const base::Value* value;
-  if (!CheckAndGetValue(policies, errors, &value))
-    return false;
-
-  if (!value)
-    return true;
-
-  std::string json;
-  value->GetAsString(&json);
-  return LoginScreenPowerManagementPolicy().Init(json, errors);
-}
-
 void LoginScreenPowerManagementPolicyHandler::ApplyPolicySettings(
     const PolicyMap& policies,
     PrefValueMap* prefs) {
diff --git a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h
index ad27a41..66f6deb 100644
--- a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h
+++ b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h
@@ -105,18 +105,16 @@
   DISALLOW_COPY_AND_ASSIGN(ScreenMagnifierPolicyHandler);
 };
 
-// ConfigurationPolicyHandler for login screen power management settings. This
-// does not actually set any prefs, it just checks whether the settings are
-// valid and generates errors if appropriate.
+// Policy handler for login screen power management settings. This does not
+// actually set any prefs, it just checks whether the settings are valid and
+// generates errors if appropriate.
 class LoginScreenPowerManagementPolicyHandler
-    : public TypeCheckingPolicyHandler {
+    : public SchemaValidatingPolicyHandler {
  public:
-  LoginScreenPowerManagementPolicyHandler();
+  explicit LoginScreenPowerManagementPolicyHandler(const Schema& chrome_schema);
   virtual ~LoginScreenPowerManagementPolicyHandler();
 
-  // TypeCheckingPolicyHandler:
-  virtual bool CheckPolicySettings(const PolicyMap& policies,
-                                   PolicyErrorMap* errors) OVERRIDE;
+  // SchemaValidatingPolicyHandler:
   virtual void ApplyPolicySettings(const PolicyMap& policies,
                                    PrefValueMap* prefs) OVERRIDE;
 
diff --git a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc
index d886a35..36c2e6f 100644
--- a/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/configuration_policy_handler_chromeos_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/policy/configuration_policy_handler_chromeos.h"
 
 #include "base/callback.h"
+#include "base/json/json_reader.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_value_map.h"
 #include "base/values.h"
@@ -13,6 +14,7 @@
 #include "components/policy/core/browser/policy_error_map.h"
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/schema.h"
 #include "policy/policy_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -28,6 +30,26 @@
   ScreenMagnifierPolicyHandler handler_;
 };
 
+class LoginScreenPowerManagementPolicyHandlerTest : public testing::Test {
+ protected:
+  LoginScreenPowerManagementPolicyHandlerTest();
+
+  virtual void SetUp() OVERRIDE;
+
+  Schema chrome_schema_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(LoginScreenPowerManagementPolicyHandlerTest);
+};
+
+LoginScreenPowerManagementPolicyHandlerTest::
+    LoginScreenPowerManagementPolicyHandlerTest() {
+}
+
+void LoginScreenPowerManagementPolicyHandlerTest::SetUp() {
+  chrome_schema_ = Schema::Wrap(GetChromeSchemaData());
+}
+
 TEST_F(ScreenMagnifierPolicyHandlerTest, Default) {
   handler_.ApplyPolicySettings(policy_, &prefs_);
   EXPECT_FALSE(prefs_.GetValue(prefs::kScreenMagnifierEnabled, NULL));
@@ -38,7 +60,7 @@
   policy_.Set(key::kScreenMagnifierType,
               POLICY_LEVEL_MANDATORY,
               POLICY_SCOPE_USER,
-              base::Value::CreateIntegerValue(0),
+              new base::FundamentalValue(0),
               NULL);
   handler_.ApplyPolicySettings(policy_, &prefs_);
 
@@ -57,7 +79,7 @@
   policy_.Set(key::kScreenMagnifierType,
               POLICY_LEVEL_MANDATORY,
               POLICY_SCOPE_USER,
-              base::Value::CreateIntegerValue(1),
+              new base::FundamentalValue(1),
               NULL);
   handler_.ApplyPolicySettings(policy_, &prefs_);
 
@@ -224,7 +246,7 @@
   policy_map.Set(key::kOpenNetworkConfiguration,
                  POLICY_LEVEL_MANDATORY,
                  POLICY_SCOPE_USER,
-                 base::Value::CreateStringValue(kTestONC),
+                 new base::StringValue(kTestONC),
                  NULL);
   scoped_ptr<NetworkConfigurationPolicyHandler> handler(
       NetworkConfigurationPolicyHandler::CreateForUserPolicy());
@@ -238,7 +260,7 @@
   policy_map.Set(key::kOpenNetworkConfiguration,
                  POLICY_LEVEL_MANDATORY,
                  POLICY_SCOPE_USER,
-                 base::Value::CreateBooleanValue(false),
+                 new base::FundamentalValue(false),
                  NULL);
   scoped_ptr<NetworkConfigurationPolicyHandler> handler(
       NetworkConfigurationPolicyHandler::CreateForUserPolicy());
@@ -253,7 +275,7 @@
   policy_map.Set(key::kOpenNetworkConfiguration,
                  POLICY_LEVEL_MANDATORY,
                  POLICY_SCOPE_USER,
-                 base::Value::CreateStringValue(kTestONC),
+                 new base::StringValue(kTestONC),
                  NULL);
   scoped_ptr<NetworkConfigurationPolicyHandler> handler(
       NetworkConfigurationPolicyHandler::CreateForUserPolicy());
@@ -281,7 +303,7 @@
   policy_map.Set(key::kOpenNetworkConfiguration,
                  POLICY_LEVEL_MANDATORY,
                  POLICY_SCOPE_USER,
-                 base::Value::CreateStringValue(kTestONC),
+                 new base::StringValue(kTestONC),
                  NULL);
   scoped_ptr<NetworkConfigurationPolicyHandler> handler(
       NetworkConfigurationPolicyHandler::CreateForUserPolicy());
@@ -323,51 +345,35 @@
   EXPECT_TRUE(base::Value::Equals(&expected_pinned_apps, value));
 }
 
-TEST(LoginScreenPowerManagementPolicyHandlerTest, Empty) {
+TEST_F(LoginScreenPowerManagementPolicyHandlerTest, Empty) {
   PolicyMap policy_map;
-  LoginScreenPowerManagementPolicyHandler handler;
+  LoginScreenPowerManagementPolicyHandler handler(chrome_schema_);
   PolicyErrorMap errors;
   EXPECT_TRUE(handler.CheckPolicySettings(policy_map, &errors));
   EXPECT_TRUE(errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
 }
 
-TEST(LoginScreenPowerManagementPolicyHandlerTest, ValidPolicy) {
+TEST_F(LoginScreenPowerManagementPolicyHandlerTest, ValidPolicy) {
   PolicyMap policy_map;
-  policy_map.Set(
-      key::kDeviceLoginScreenPowerManagement,
-      POLICY_LEVEL_MANDATORY,
-      POLICY_SCOPE_USER,
-      base::Value::CreateStringValue(kLoginScreenPowerManagementPolicy),
-      NULL);
-  LoginScreenPowerManagementPolicyHandler handler;
+  policy_map.Set(key::kDeviceLoginScreenPowerManagement,
+                 POLICY_LEVEL_MANDATORY,
+                 POLICY_SCOPE_USER,
+                 base::JSONReader::Read(kLoginScreenPowerManagementPolicy),
+                 NULL);
+  LoginScreenPowerManagementPolicyHandler handler(chrome_schema_);
   PolicyErrorMap errors;
   EXPECT_TRUE(handler.CheckPolicySettings(policy_map, &errors));
   EXPECT_TRUE(errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
 }
 
-TEST(LoginScreenPowerManagementPolicyHandlerTest, WrongType) {
+TEST_F(LoginScreenPowerManagementPolicyHandlerTest, WrongType) {
   PolicyMap policy_map;
   policy_map.Set(key::kDeviceLoginScreenPowerManagement,
                  POLICY_LEVEL_MANDATORY,
                  POLICY_SCOPE_USER,
-                 base::Value::CreateBooleanValue(false),
+                 new base::FundamentalValue(false),
                  NULL);
-  LoginScreenPowerManagementPolicyHandler handler;
-  PolicyErrorMap errors;
-  EXPECT_FALSE(handler.CheckPolicySettings(policy_map, &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-}
-
-TEST(LoginScreenPowerManagementPolicyHandlerTest, JSONParseError) {
-  const std::string policy("I'm not proper JSON!");
-  PolicyMap policy_map;
-  policy_map.Set(key::kDeviceLoginScreenPowerManagement,
-                 POLICY_LEVEL_MANDATORY,
-                 POLICY_SCOPE_USER,
-                 base::Value::CreateStringValue(policy),
-                 NULL);
-  LoginScreenPowerManagementPolicyHandler handler;
+  LoginScreenPowerManagementPolicyHandler handler(chrome_schema_);
   PolicyErrorMap errors;
   EXPECT_FALSE(handler.CheckPolicySettings(policy_map, &errors));
   EXPECT_FALSE(
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
index d849f33..ec89b27 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.cc
@@ -7,8 +7,11 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
+#include "base/port.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/attestation/attestation_policy_observer.h"
 #include "chrome/browser/chromeos/login/startup_utils.h"
@@ -44,13 +47,10 @@
 // Overridden no requisition value.
 const char kRemoraRequisition[] = "remora";
 
-// MachineInfo key names.
-const char kMachineInfoSystemHwqual[] = "hardware_class";
-
 // These are the machine serial number keys that we check in order until we
 // find a non-empty serial number. The VPD spec says the serial number should be
 // in the "serial_number" key for v2+ VPDs. However, legacy devices used a
-// different keys to report their serial number, which we fall back to if
+// different key to report their serial number, which we fall back to if
 // "serial_number" is not present.
 //
 // Product_S/N is still special-cased due to inconsistencies with serial
@@ -96,6 +96,12 @@
 
 }  // namespace
 
+const int
+DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyTimeQuantumPower;
+
+const int
+DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyFutureQuanta;
+
 DeviceCloudPolicyManagerChromeOS::DeviceCloudPolicyManagerChromeOS(
     scoped_ptr<DeviceCloudPolicyStoreChromeOS> store,
     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
@@ -145,7 +151,8 @@
           device_store_.get(), install_attributes_, CreateClient(),
           background_task_runner_, auth_token,
           install_attributes_->GetDeviceId(), is_auto_enrollment,
-          GetDeviceRequisition(), allowed_device_modes,
+          GetDeviceRequisition(), GetCurrentDeviceStateKey(),
+          allowed_device_modes,
           base::Bind(&DeviceCloudPolicyManagerChromeOS::EnrollmentCompleted,
                      base::Unretained(this), callback)));
   enrollment_handler_->StartEnrollment();
@@ -215,6 +222,16 @@
                         true);
 }
 
+std::string
+DeviceCloudPolicyManagerChromeOS::GetForcedEnrollmentDomain() const {
+  const base::DictionaryValue* device_state_dict =
+      local_state_->GetDictionary(prefs::kServerBackedDeviceState);
+  std::string management_domain;
+  device_state_dict->GetString(kDeviceStateManagementDomain,
+                               &management_domain);
+  return management_domain;
+}
+
 void DeviceCloudPolicyManagerChromeOS::Shutdown() {
   CloudPolicyManager::Shutdown();
   device_status_provider_.reset();
@@ -258,16 +275,19 @@
 
 // static
 std::string DeviceCloudPolicyManagerChromeOS::GetMachineModel() {
-  return GetMachineStatistic(kMachineInfoSystemHwqual);
+  return GetMachineStatistic(chromeos::system::kHardwareClassKey);
 }
 
 // static
-std::string DeviceCloudPolicyManagerChromeOS::GetDeviceStateKey() {
-  // TODO(mnissler): Figure out which stable device identifiers should be used
-  // here and update the code. See http://crbug.com/352599.
-  std::string group_code_key =
-      GetMachineStatistic(chromeos::system::kOffersGroupCodeKey);
-  return crypto::SHA256HashString(group_code_key + GetMachineID());
+std::string DeviceCloudPolicyManagerChromeOS::GetCurrentDeviceStateKey() {
+  std::vector<std::string> state_keys;
+  if (GetDeviceStateKeys(base::Time::Now(), &state_keys) &&
+      !state_keys.empty()) {
+    // The key for the current time is always the first one.
+    return state_keys[0];
+  }
+
+  return std::string();
 }
 
 scoped_ptr<CloudPolicyClient> DeviceCloudPolicyManagerChromeOS::CreateClient() {
@@ -288,8 +308,8 @@
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           chromeos::switches::kEnterpriseEnableForcedReEnrollment)) {
     std::vector<std::string> state_keys;
-    state_keys.push_back(GetDeviceStateKey());
-    client->SetStateKeysToUpload(state_keys);
+    if (GetDeviceStateKeys(base::Time::Now(), &state_keys))
+      client->SetStateKeysToUpload(state_keys);
   }
 
   return client.Pass();
@@ -367,4 +387,41 @@
   return restore_mode;
 }
 
+// static
+bool DeviceCloudPolicyManagerChromeOS::GetDeviceStateKeys(
+    const base::Time& timestamp,
+    std::vector<std::string>* state_keys) {
+  state_keys->clear();
+
+  std::string disk_serial_number =
+      GetMachineStatistic(chromeos::system::kDiskSerialNumber);
+  if (disk_serial_number.empty()) {
+    LOG(ERROR) << "Missing disk serial number";
+    return false;
+  }
+
+  std::string machine_id = GetMachineID();
+  if (machine_id.empty())
+    return false;
+
+  // Tolerate missing group code keys, some old devices may not have it.
+  std::string group_code_key =
+      GetMachineStatistic(chromeos::system::kOffersGroupCodeKey);
+
+  // Get the current time in quantized form.
+  int64 quantum_size = GG_INT64_C(1) << kDeviceStateKeyTimeQuantumPower;
+  int64 quantized_time =
+      (timestamp - base::Time::UnixEpoch()).InSeconds() & ~(quantum_size - 1);
+  for (int i = 0; i < kDeviceStateKeyFutureQuanta; ++i) {
+    state_keys->push_back(crypto::SHA256HashString(
+        crypto::SHA256HashString(group_code_key) +
+        crypto::SHA256HashString(disk_serial_number) +
+        crypto::SHA256HashString(machine_id) +
+        crypto::SHA256HashString(base::Int64ToString(quantized_time))));
+    quantized_time += quantum_size;
+  }
+
+  return true;
+}
+
 }  // namespace policy
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
index 05ecbc4..735a747 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h
@@ -7,6 +7,7 @@
 
 #include <bitset>
 #include <string>
+#include <vector>
 
 #include "base/basictypes.h"
 #include "base/callback.h"
@@ -45,6 +46,22 @@
   typedef std::bitset<32> AllowedDeviceModes;
   typedef base::Callback<void(EnrollmentStatus)> EnrollmentCallback;
 
+  // The power of two determining the size of the time quanta for device state
+  // keys, i.e. the quanta will be of size 2^kDeviceStateKeyTimeQuantumPower
+  // seconds. 2^23 seconds corresponds to 97.09 days.
+  static const int kDeviceStateKeyTimeQuantumPower = 23;
+
+  // The number of future time quanta to generate device state identifiers for.
+  // This determines the interval after which a device will no longer receive
+  // server-backed state information and thus corresponds to the delay until a
+  // device becomes anonymous to the server again.
+  //
+  // The goal here is to guarantee state key validity for 1 year into the
+  // future. 4 quanta are needed to cover a year, but the current quantum is
+  // clipped short in the general case. Hence, one buffer quantum is needed to
+  // make up for the clipping, yielding a total of 5 quanta.
+  static const int kDeviceStateKeyFutureQuanta = 5;
+
   // |task_runner| is the runner for policy refresh tasks.
   // |background_task_runner| is used to execute long-running background tasks
   // that may involve file I/O.
@@ -83,6 +100,9 @@
   // Checks whether the user can cancel enrollment.
   bool CanExitEnrollment() const;
 
+  // Gets the domain this device is supposed to be enrolled to.
+  std::string GetForcedEnrollmentDomain() const;
+
   // CloudPolicyManager:
   virtual void Shutdown() OVERRIDE;
 
@@ -98,8 +118,14 @@
   // Returns the machine model, or an empty string if not available.
   static std::string GetMachineModel();
 
-  // Returns the stable device state key.
-  static std::string GetDeviceStateKey();
+  // Gets the device state keys for |timestamp|. These will cover a time frame
+  // including |timestamp| and extending into the future as configured by the
+  // constants declared above.
+  static bool GetDeviceStateKeys(const base::Time& timestamp,
+                                 std::vector<std::string>* state_keys);
+
+  // Returns the currently valid device state key.
+  static std::string GetCurrentDeviceStateKey();
 
   // Returns the robot 'email address' associated with the device robot
   // account (sometimes called a service account) associated with this device
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
index 93fbb4d..5abfe5a 100644
--- a/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h"
 
+#include <algorithm>
+
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
@@ -142,7 +144,7 @@
         .Set(key::kDeviceMetricsReportingEnabled,
              POLICY_LEVEL_MANDATORY,
              POLICY_SCOPE_MACHINE,
-             base::Value::CreateBooleanValue(false),
+             new base::FundamentalValue(false),
              NULL);
     EXPECT_TRUE(manager_->policies().Equals(bundle));
   }
@@ -261,6 +263,70 @@
   EXPECT_TRUE(manager_->policies().Equals(bundle));
 }
 
+class DeviceCloudPolicyManagerChromeOSStateKeyTest : public testing::Test {
+ protected:
+  DeviceCloudPolicyManagerChromeOSStateKeyTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    chromeos::system::StatisticsProvider::SetTestProvider(
+        &statistics_provider_);
+    EXPECT_CALL(statistics_provider_, GetMachineStatistic(_, _))
+        .WillRepeatedly(Invoke(this,
+                               &DeviceCloudPolicyManagerChromeOSStateKeyTest::
+                                   GetMachineStatistic));
+  }
+
+  virtual void TearDown() OVERRIDE {
+    chromeos::system::StatisticsProvider::SetTestProvider(NULL);
+  }
+
+  bool GetMachineStatistic(const std::string& name, std::string* result) {
+    *result = "fake-" + name;
+    return true;
+  }
+
+ private:
+  chromeos::system::MockStatisticsProvider statistics_provider_;
+
+  DISALLOW_COPY_AND_ASSIGN(DeviceCloudPolicyManagerChromeOSStateKeyTest);
+};
+
+TEST_F(DeviceCloudPolicyManagerChromeOSStateKeyTest, GetDeviceStateKeys) {
+  base::Time current = base::Time::UnixEpoch() + base::TimeDelta::FromDays(100);
+
+  // The correct number of state keys gets returned.
+  std::vector<std::string> state_keys;
+  EXPECT_TRUE(DeviceCloudPolicyManagerChromeOS::GetDeviceStateKeys(
+      current, &state_keys));
+  EXPECT_EQ(DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyFutureQuanta,
+            static_cast<int>(state_keys.size()));
+
+  // All state keys are different.
+  std::set<std::string> state_key_set(state_keys.begin(), state_keys.end());
+  EXPECT_EQ(DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyFutureQuanta,
+            static_cast<int>(state_key_set.size()));
+
+  // Moving forward just a little yields the same keys.
+  std::vector<std::string> new_state_keys;
+  current += base::TimeDelta::FromDays(1);
+  EXPECT_TRUE(DeviceCloudPolicyManagerChromeOS::GetDeviceStateKeys(
+      current, &new_state_keys));
+  EXPECT_EQ(state_keys, new_state_keys);
+
+  // Jumping to a future quantum results in the state keys rolling forward.
+  int64 step =
+      GG_INT64_C(1)
+      << DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyTimeQuantumPower;
+  current += 2 * base::TimeDelta::FromSeconds(step);
+
+  EXPECT_TRUE(DeviceCloudPolicyManagerChromeOS::GetDeviceStateKeys(
+      current, &new_state_keys));
+  ASSERT_EQ(DeviceCloudPolicyManagerChromeOS::kDeviceStateKeyFutureQuanta,
+            static_cast<int>(new_state_keys.size()));
+  EXPECT_TRUE(std::equal(state_keys.begin() + 2, state_keys.end(),
+                         new_state_keys.begin()));
+}
+
 class DeviceCloudPolicyManagerChromeOSEnrollmentTest
     : public DeviceCloudPolicyManagerChromeOSTest {
  public:
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc b/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc
index a662c5e..b6ed507 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_provider.cc
@@ -58,7 +58,7 @@
         key::kLidCloseAction,
         POLICY_LEVEL_MANDATORY,
         POLICY_SCOPE_MACHINE,
-        base::Value::CreateIntegerValue(
+        new base::FundamentalValue(
             chromeos::PowerPolicyController::ACTION_STOP_SESSION),
         NULL);
     // Force the |ShelfAutoHideBehavior| policy to |Never|, ensuring that the
@@ -67,7 +67,7 @@
         key::kShelfAutoHideBehavior,
         POLICY_LEVEL_MANDATORY,
         POLICY_SCOPE_MACHINE,
-        base::Value::CreateStringValue("Never"),
+        new base::StringValue("Never"),
         NULL);
     // Force the |ShowLogoutButtonInTray| policy to |true|, ensuring that a big,
     // red logout button is shown in the ash system tray.
@@ -75,7 +75,7 @@
         key::kShowLogoutButtonInTray,
         POLICY_LEVEL_MANDATORY,
         POLICY_SCOPE_MACHINE,
-        base::Value::CreateBooleanValue(true),
+        new base::FundamentalValue(true),
         NULL);
     // Force the |FullscreenAllowed| policy to |false|, ensuring that the ash
     // shelf cannot be hidden by entering fullscreen mode.
@@ -83,7 +83,7 @@
         key::kFullscreenAllowed,
         POLICY_LEVEL_MANDATORY,
         POLICY_SCOPE_MACHINE,
-        base::Value::CreateBooleanValue(false),
+        new base::FundamentalValue(false),
         NULL);
   }
 
diff --git a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
index 12bc4d2..bfef63c 100644
--- a/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_local_account_policy_service_unittest.cc
@@ -138,7 +138,7 @@
   expected_policy_map_.Set(key::kDisableSpdy,
                            POLICY_LEVEL_MANDATORY,
                            POLICY_SCOPE_USER,
-                           base::Value::CreateBooleanValue(true),
+                           new base::FundamentalValue(true),
                            NULL);
 
   device_local_account_policy_.payload().mutable_disablespdy()->set_value(
@@ -779,24 +779,24 @@
   expected_policy_map_.Set(key::kLidCloseAction,
                            POLICY_LEVEL_MANDATORY,
                            POLICY_SCOPE_MACHINE,
-                           base::Value::CreateIntegerValue(
+                           new base::FundamentalValue(
                                chromeos::PowerPolicyController::
                                    ACTION_STOP_SESSION),
                            NULL);
   expected_policy_map_.Set(key::kShelfAutoHideBehavior,
                            POLICY_LEVEL_MANDATORY,
                            POLICY_SCOPE_MACHINE,
-                           base::Value::CreateStringValue("Never"),
+                           new base::StringValue("Never"),
                            NULL);
   expected_policy_map_.Set(key::kShowLogoutButtonInTray,
                            POLICY_LEVEL_MANDATORY,
                            POLICY_SCOPE_MACHINE,
-                           base::Value::CreateBooleanValue(true),
+                           new base::FundamentalValue(true),
                            NULL);
   expected_policy_map_.Set(key::kFullscreenAllowed,
                            POLICY_LEVEL_MANDATORY,
                            POLICY_SCOPE_MACHINE,
-                           base::Value::CreateBooleanValue(false),
+                           new base::FundamentalValue(false),
                            NULL);
 }
 
@@ -862,7 +862,7 @@
       .Set(key::kDisableSpdy,
            POLICY_LEVEL_MANDATORY,
            POLICY_SCOPE_USER,
-           base::Value::CreateBooleanValue(false),
+           new base::FundamentalValue(false),
            NULL);
   EXPECT_TRUE(expected_policy_bundle.Equals(provider_->policies()));
 
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
index 6f9e606..961252f 100644
--- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
+++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -5,18 +5,23 @@
 #include "chrome/browser/chromeos/policy/device_policy_decoder_chromeos.h"
 
 #include <limits>
+#include <string>
 
 #include "base/callback.h"
+#include "base/json/json_reader.h"
 #include "base/logging.h"
 #include "base/values.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/policy/device_local_account.h"
 #include "chrome/browser/chromeos/policy/enterprise_install_attributes.h"
 #include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/update_engine_client.h"
 #include "chromeos/settings/cros_settings_names.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/policy_map.h"
+#include "components/policy/core/common/schema.h"
 #include "policy/policy_constants.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
 
@@ -29,17 +34,63 @@
 
 namespace {
 
-// Decodes a protobuf integer to an IntegerValue. The caller assumes ownership
-// of the return Value*. Returns NULL in case the input value is out of bounds.
-base::Value* DecodeIntegerValue(google::protobuf::int64 value) {
+// Decodes a protobuf integer to an IntegerValue. Returns NULL in case the input
+// value is out of bounds.
+scoped_ptr<base::Value> DecodeIntegerValue(google::protobuf::int64 value) {
   if (value < std::numeric_limits<int>::min() ||
       value > std::numeric_limits<int>::max()) {
     LOG(WARNING) << "Integer value " << value
                  << " out of numeric limits, ignoring.";
-    return NULL;
+    return scoped_ptr<base::Value>();
   }
 
-  return base::Value::CreateIntegerValue(static_cast<int>(value));
+  return scoped_ptr<base::Value>(
+      new base::FundamentalValue(static_cast<int>(value)));
+}
+
+// Decodes a JSON string to a base::Value, and drops unknown properties
+// according to a policy schema. |policy_name| is the name of a policy schema
+// defined in policy_templates.json. Returns NULL in case the input is not a
+// valid JSON string.
+scoped_ptr<base::Value> DecodeJsonStringAndDropUnknownBySchema(
+    const std::string& json_string,
+    const std::string& policy_name) {
+  std::string error;
+  base::Value* root(base::JSONReader::ReadAndReturnError(
+      json_string, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
+
+  if (!root) {
+    LOG(WARNING) << "Invalid JSON string: " << error << ", ignoring.";
+    return scoped_ptr<base::Value>();
+  }
+
+  const Schema& schema = g_browser_process
+                             ->browser_policy_connector()
+                             ->GetChromeSchema()
+                             .GetKnownProperty(policy_name);
+
+  if (schema.valid()) {
+    std::string error_path;
+    bool changed = false;
+
+    if (!schema.Normalize(
+            root, SCHEMA_ALLOW_UNKNOWN, &error_path, &error, &changed)) {
+      LOG(WARNING) << "Invalid policy value for " << policy_name << ": "
+                   << error << " at " << error_path << ".";
+      return scoped_ptr<base::Value>();
+    }
+
+    if (changed) {
+      LOG(WARNING) << "Some properties in " << policy_name
+                   << " were dropped: " << error << " at " << error_path << ".";
+    }
+  } else {
+    LOG(WARNING) << "Unknown or invalid policy schema for " << policy_name
+                 << ".";
+    return scoped_ptr<base::Value>();
+  }
+
+  return scoped_ptr<base::Value>(root);
 }
 
 base::Value* DecodeConnectionType(int value) {
@@ -54,7 +105,7 @@
   if (value < 0 || value >= static_cast<int>(arraysize(kConnectionTypes)))
     return NULL;
 
-  return base::Value::CreateStringValue(kConnectionTypes[value]);
+  return new base::StringValue(kConnectionTypes[value]);
 }
 
 void DecodeLoginPolicies(const em::ChromeDeviceSettingsProto& policy,
@@ -65,7 +116,7 @@
       policies->Set(key::kDeviceGuestModeEnabled,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.guest_mode_enabled()),
                     NULL);
     }
@@ -77,7 +128,7 @@
       policies->Set(key::kDeviceShowUserNamesOnSignin,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.show_user_names()),
                     NULL);
     }
@@ -89,7 +140,7 @@
       policies->Set(key::kDeviceAllowNewUsers,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.allow_new_users()),
                     NULL);
     }
@@ -102,7 +153,7 @@
     for (entry = container.user_whitelist().begin();
          entry != container.user_whitelist().end();
          ++entry) {
-      whitelist->Append(base::Value::CreateStringValue(*entry));
+      whitelist->Append(new base::StringValue(*entry));
     }
     policies->Set(key::kDeviceUserWhitelist,
                   POLICY_LEVEL_MANDATORY,
@@ -118,7 +169,7 @@
       policies->Set(key::kDeviceEphemeralUsersEnabled,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.ephemeral_users_enabled()),
                     NULL);
     }
@@ -167,21 +218,21 @@
       policies->Set(key::kDeviceLocalAccountAutoLoginId,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(container.auto_login_id()),
+                    new base::StringValue(container.auto_login_id()),
                     NULL);
     }
     if (container.has_auto_login_delay()) {
       policies->Set(key::kDeviceLocalAccountAutoLoginDelay,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    DecodeIntegerValue(container.auto_login_delay()),
+                    DecodeIntegerValue(container.auto_login_delay()).release(),
                     NULL);
     }
     if (container.has_enable_auto_login_bailout()) {
       policies->Set(key::kDeviceLocalAccountAutoLoginBailoutEnabled,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.enable_auto_login_bailout()),
                     NULL);
     }
@@ -189,7 +240,7 @@
       policies->Set(key::kDeviceLocalAccountPromptForNetworkWhenOffline,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.prompt_for_network_when_offline()),
                     NULL);
     }
@@ -199,7 +250,7 @@
     const em::SupervisedUsersSettingsProto& container =
         policy.supervised_users_settings();
     if (container.has_supervised_users_enabled()) {
-      base::Value* value = base::Value::CreateBooleanValue(
+      base::Value* value = new base::FundamentalValue(
           container.supervised_users_enabled());
       policies->Set(key::kSupervisedUsersEnabled,
                     POLICY_LEVEL_MANDATORY,
@@ -221,18 +272,19 @@
     const em::ForcedLogoutTimeoutsProto& container(
         policy.forced_logout_timeouts());
     if (container.has_idle_logout_timeout()) {
-      policies->Set(key::kDeviceIdleLogoutTimeout,
-                    POLICY_LEVEL_MANDATORY,
-                    POLICY_SCOPE_MACHINE,
-                    DecodeIntegerValue(container.idle_logout_timeout()),
-                    NULL);
+      policies->Set(
+          key::kDeviceIdleLogoutTimeout,
+          POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE,
+          DecodeIntegerValue(container.idle_logout_timeout()).release(),
+          NULL);
     }
     if (container.has_idle_logout_warning_duration()) {
       policies->Set(key::kDeviceIdleLogoutWarningDuration,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    DecodeIntegerValue(
-                        container.idle_logout_warning_duration()),
+                    DecodeIntegerValue(container.idle_logout_warning_duration())
+                        .release(),
                     NULL);
     }
   }
@@ -244,16 +296,17 @@
       policies->Set(key::kDeviceLoginScreenSaverId,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(
+                    new base::StringValue(
                         container.screen_saver_extension_id()),
                     NULL);
     }
     if (container.has_screen_saver_timeout()) {
-      policies->Set(key::kDeviceLoginScreenSaverTimeout,
-                    POLICY_LEVEL_MANDATORY,
-                    POLICY_SCOPE_MACHINE,
-                    DecodeIntegerValue(container.screen_saver_timeout()),
-                    NULL);
+      policies->Set(
+          key::kDeviceLoginScreenSaverTimeout,
+          POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE,
+          DecodeIntegerValue(container.screen_saver_timeout()).release(),
+          NULL);
     }
   }
 
@@ -281,7 +334,7 @@
     base::ListValue* pinned_apps_list = new base::ListValue();
     for (int i = 0; i < container.app_id_size(); ++i) {
       pinned_apps_list->Append(
-          base::Value::CreateStringValue(container.app_id(i)));
+          new base::StringValue(container.app_id(i)));
     }
 
     policies->Set(key::kPinnedLauncherApps,
@@ -330,7 +383,7 @@
       policies->Set(key::kDeviceDataRoamingEnabled,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.data_roaming_enabled()),
                     NULL);
     }
@@ -343,7 +396,7 @@
     policies->Set(key::kDeviceOpenNetworkConfiguration,
                   POLICY_LEVEL_MANDATORY,
                   POLICY_SCOPE_MACHINE,
-                  base::Value::CreateStringValue(config),
+                  new base::StringValue(config),
                   NULL);
   }
 }
@@ -356,7 +409,7 @@
       policies->Set(key::kReportDeviceVersionInfo,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.report_version_info()),
                     NULL);
     }
@@ -364,7 +417,7 @@
       policies->Set(key::kReportDeviceActivityTimes,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.report_activity_times()),
                     NULL);
     }
@@ -372,7 +425,7 @@
       policies->Set(key::kReportDeviceBootMode,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.report_boot_mode()),
                     NULL);
     }
@@ -380,7 +433,7 @@
       policies->Set(key::kReportDeviceLocation,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.report_location()),
                     NULL);
     }
@@ -388,7 +441,7 @@
       policies->Set(key::kReportDeviceNetworkInterfaces,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.report_network_interfaces()),
                     NULL);
     }
@@ -396,7 +449,7 @@
       policies->Set(key::kReportDeviceUsers,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(container.report_users()),
+                    new base::FundamentalValue(container.report_users()),
                     NULL);
     }
   }
@@ -411,7 +464,7 @@
       policies->Set(key::kChromeOsReleaseChannel,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(channel),
+                    new base::StringValue(channel),
                     NULL);
       // TODO(dubroy): Once http://crosbug.com/17015 is implemented, we won't
       // have to pass the channel in here, only ping the update engine to tell
@@ -423,7 +476,7 @@
       policies->Set(key::kChromeOsReleaseChannelDelegated,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.release_channel_delegated()),
                     NULL);
     }
@@ -435,7 +488,7 @@
       policies->Set(key::kDeviceAutoUpdateDisabled,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.update_disabled()),
                     NULL);
     }
@@ -444,7 +497,7 @@
       policies->Set(key::kDeviceTargetVersionPrefix,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(
+                    new base::StringValue(
                         container.target_version_prefix()),
                     NULL);
     }
@@ -456,8 +509,8 @@
       policies->Set(key::kDeviceUpdateScatterFactor,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateIntegerValue(
-                        container.scatter_factor_in_seconds()),
+                    new base::FundamentalValue(static_cast<int>(
+                        container.scatter_factor_in_seconds())),
                     NULL);
     }
 
@@ -483,7 +536,7 @@
           key::kDeviceUpdateHttpDownloadsEnabled,
           POLICY_LEVEL_MANDATORY,
           POLICY_SCOPE_MACHINE,
-          base::Value::CreateBooleanValue(container.http_downloads_enabled()),
+          new base::FundamentalValue(container.http_downloads_enabled()),
           NULL);
     }
 
@@ -491,7 +544,7 @@
       policies->Set(key::kRebootAfterUpdate,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.reboot_after_update()),
                     NULL);
     }
@@ -500,7 +553,7 @@
       policies->Set(key::kDeviceAutoUpdateP2PEnabled,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(container.p2p_enabled()),
+                    new base::FundamentalValue(container.p2p_enabled()),
                     NULL);
     }
   }
@@ -517,7 +570,7 @@
           key::kDeviceLoginScreenDefaultLargeCursorEnabled,
           POLICY_LEVEL_MANDATORY,
           POLICY_SCOPE_MACHINE,
-          base::Value::CreateBooleanValue(
+          new base::FundamentalValue(
               container.login_screen_default_large_cursor_enabled()),
           NULL);
     }
@@ -527,7 +580,7 @@
           key::kDeviceLoginScreenDefaultSpokenFeedbackEnabled,
           POLICY_LEVEL_MANDATORY,
           POLICY_SCOPE_MACHINE,
-          base::Value::CreateBooleanValue(
+          new base::FundamentalValue(
               container.login_screen_default_spoken_feedback_enabled()),
           NULL);
     }
@@ -537,7 +590,7 @@
           key::kDeviceLoginScreenDefaultHighContrastEnabled,
           POLICY_LEVEL_MANDATORY,
           POLICY_SCOPE_MACHINE,
-          base::Value::CreateBooleanValue(
+          new base::FundamentalValue(
               container.login_screen_default_high_contrast_enabled()),
           NULL);
     }
@@ -548,7 +601,7 @@
           POLICY_LEVEL_MANDATORY,
           POLICY_SCOPE_MACHINE,
           DecodeIntegerValue(
-              container.login_screen_default_screen_magnifier_type()),
+              container.login_screen_default_screen_magnifier_type()).release(),
           NULL);
     }
     if (container.has_login_screen_default_virtual_keyboard_enabled()) {
@@ -556,7 +609,7 @@
           key::kDeviceLoginScreenDefaultVirtualKeyboardEnabled,
           POLICY_LEVEL_MANDATORY,
           POLICY_SCOPE_MACHINE,
-          base::Value::CreateBooleanValue(
+          new base::FundamentalValue(
               container.login_screen_default_virtual_keyboard_enabled()),
           NULL);
     }
@@ -569,11 +622,12 @@
     const em::DevicePolicyRefreshRateProto& container(
         policy.device_policy_refresh_rate());
     if (container.has_device_policy_refresh_rate()) {
-      policies->Set(key::kDevicePolicyRefreshRate,
-                    POLICY_LEVEL_MANDATORY,
-                    POLICY_SCOPE_MACHINE,
-                    DecodeIntegerValue(container.device_policy_refresh_rate()),
-                    NULL);
+      policies->Set(
+          key::kDevicePolicyRefreshRate,
+          POLICY_LEVEL_MANDATORY,
+          POLICY_SCOPE_MACHINE,
+          DecodeIntegerValue(container.device_policy_refresh_rate()).release(),
+          NULL);
     }
   }
 
@@ -583,7 +637,7 @@
       policies->Set(key::kDeviceMetricsReportingEnabled,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.metrics_enabled()),
                     NULL);
     }
@@ -596,7 +650,7 @@
     for (entry = container.start_up_urls().begin();
          entry != container.start_up_urls().end();
          ++entry) {
-      urls->Append(base::Value::CreateStringValue(*entry));
+      urls->Append(new base::StringValue(*entry));
     }
     policies->Set(key::kDeviceStartUpUrls,
                   POLICY_LEVEL_MANDATORY,
@@ -610,7 +664,7 @@
       policies->Set(key::kSystemTimezone,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(
+                    new base::StringValue(
                         policy.system_timezone().timezone()),
                     NULL);
     }
@@ -621,7 +675,7 @@
       policies->Set(key::kSystemUse24HourClock,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         policy.use_24hour_clock().use_24hour_clock()),
                     NULL);
     }
@@ -634,7 +688,7 @@
       policies->Set(key::kDeviceAllowRedeemChromeOsRegistrationOffers,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         container.allow_redeem_offers()),
                     NULL);
     }
@@ -646,7 +700,7 @@
       policies->Set(key::kUptimeLimit,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    DecodeIntegerValue(container.uptime_limit()),
+                    DecodeIntegerValue(container.uptime_limit()).release(),
                     NULL);
     }
   }
@@ -658,7 +712,7 @@
     for (entry = container.flags().begin();
          entry != container.flags().end();
          ++entry) {
-      flags->Append(base::Value::CreateStringValue(*entry));
+      flags->Append(new base::StringValue(*entry));
     }
     policies->Set(key::kDeviceStartUpFlags,
                   POLICY_LEVEL_MANDATORY,
@@ -672,7 +726,7 @@
       policies->Set(key::kDeviceVariationsRestrictParameter,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(
+                    new base::StringValue(
                         policy.variations_parameter().parameter()),
                     NULL);
     }
@@ -683,7 +737,7 @@
       policies->Set(key::kAttestationEnabledForDevice,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateBooleanValue(
+                    new base::FundamentalValue(
                         policy.attestation_settings().attestation_enabled()),
                     NULL);
     }
@@ -692,7 +746,7 @@
           key::kAttestationForContentProtectionEnabled,
           POLICY_LEVEL_MANDATORY,
           POLICY_SCOPE_MACHINE,
-          base::Value::CreateBooleanValue(
+          new base::FundamentalValue(
               policy.attestation_settings().content_protection_enabled()),
           NULL);
     }
@@ -702,12 +756,17 @@
     const em::LoginScreenPowerManagementProto& container(
         policy.login_screen_power_management());
     if (container.has_login_screen_power_management()) {
-      policies->Set(key::kDeviceLoginScreenPowerManagement,
-                    POLICY_LEVEL_MANDATORY,
-                    POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(
-                        container.login_screen_power_management()),
-                    NULL);
+      scoped_ptr<base::Value> decoded_json;
+      decoded_json = DecodeJsonStringAndDropUnknownBySchema(
+          container.login_screen_power_management(),
+          key::kDeviceLoginScreenPowerManagement);
+      if (decoded_json) {
+        policies->Set(key::kDeviceLoginScreenPowerManagement,
+                      POLICY_LEVEL_MANDATORY,
+                      POLICY_SCOPE_MACHINE,
+                      decoded_json.release(),
+                      NULL);
+      }
     }
   }
   if (policy.has_auto_clean_up_settings()) {
@@ -717,7 +776,7 @@
       policies->Set(key::kAutoCleanUpStrategy,
                     POLICY_LEVEL_MANDATORY,
                     POLICY_SCOPE_MACHINE,
-                    base::Value::CreateStringValue(
+                    new base::StringValue(
                         container.clean_up_strategy()),
                     NULL);
     }
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
index 2418388..48c6d34 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.cc
@@ -46,6 +46,7 @@
     const std::string& client_id,
     bool is_auto_enrollment,
     const std::string& requisition,
+    const std::string& current_state_key,
     const AllowedDeviceModes& allowed_device_modes,
     const EnrollmentCallback& completion_callback)
     : store_(store),
@@ -56,6 +57,7 @@
       client_id_(client_id),
       is_auto_enrollment_(is_auto_enrollment),
       requisition_(requisition),
+      current_state_key_(current_state_key),
       allowed_device_modes_(allowed_device_modes),
       completion_callback_(completion_callback),
       device_mode_(DEVICE_MODE_NOT_SET),
@@ -193,7 +195,7 @@
     enrollment_step_ = STEP_REGISTRATION;
     client_->Register(em::DeviceRegisterRequest::DEVICE,
                       auth_token_, client_id_, is_auto_enrollment_,
-                      requisition_);
+                      requisition_, current_state_key_);
   }
 }
 
diff --git a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
index 402d1f4..e92accf 100644
--- a/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
+++ b/chrome/browser/chromeos/policy/enrollment_handler_chromeos.h
@@ -63,6 +63,7 @@
       const std::string& client_id,
       bool is_auto_enrollment,
       const std::string& requisition,
+      const std::string& current_state_key,
       const AllowedDeviceModes& allowed_device_modes,
       const EnrollmentCallback& completion_callback);
   virtual ~EnrollmentHandlerChromeOS();
@@ -151,6 +152,7 @@
   std::string client_id_;
   bool is_auto_enrollment_;
   std::string requisition_;
+  std::string current_state_key_;
   std::string refresh_token_;
   AllowedDeviceModes allowed_device_modes_;
   EnrollmentCallback completion_callback_;
diff --git a/chrome/browser/chromeos/policy/login_profile_policy_provider.cc b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
index 740475b..f0fe77f 100644
--- a/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
+++ b/chrome/browser/chromeos/policy/login_profile_policy_provider.cc
@@ -10,7 +10,7 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/values.h"
-#include "chrome/browser/chromeos/policy/login_screen_power_management_policy.h"
+#include "chromeos/dbus/power_policy_controller.h"
 #include "components/policy/core/browser/policy_error_map.h"
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/policy_bundle.h"
@@ -22,6 +22,36 @@
 
 namespace {
 
+const char kLidCloseAction[] = "LidCloseAction";
+const char kUserActivityScreenDimDelayScale[] =
+    "UserActivityScreenDimDelayScale";
+
+const char kActionSuspend[] = "Suspend";
+const char kActionLogout[] = "Logout";
+const char kActionShutdown[]  = "Shutdown";
+const char kActionDoNothing[] = "DoNothing";
+
+scoped_ptr<base::Value> GetAction(const std::string &action) {
+  if (action == kActionSuspend) {
+    return scoped_ptr<base::Value>(new base::FundamentalValue(
+        chromeos::PowerPolicyController::ACTION_SUSPEND));
+  }
+  if (action == kActionLogout) {
+    return scoped_ptr<base::Value>(new base::FundamentalValue(
+        chromeos::PowerPolicyController::ACTION_STOP_SESSION));
+  }
+  if (action == kActionShutdown) {
+    return scoped_ptr<base::Value>(new base::FundamentalValue(
+        chromeos::PowerPolicyController::ACTION_SHUT_DOWN));
+  }
+  if (action == kActionDoNothing) {
+    return scoped_ptr<base::Value>(new base::FundamentalValue(
+        chromeos::PowerPolicyController::ACTION_DO_NOTHING));
+  }
+  return scoped_ptr<base::Value>();
+}
+
+
 // Applies the value of |device_policy| in |device_policy_map| as the
 // recommended value of |user_policy| in |user_policy_map|. If the value of
 // |device_policy| is unset, does nothing.
@@ -136,48 +166,38 @@
       key::kVirtualKeyboardEnabled,
       device_policy_map, &user_policy_map);
 
-  // TODO(bartfab): Consolidate power management user policies into a single
-  // JSON policy, allowing the value of the device policy to be simply forwarded
-  // here. http://crbug.com/258339
   const base::Value* value =
       device_policy_map.GetValue(key::kDeviceLoginScreenPowerManagement);
-  std::string json;
-  if (value && value->GetAsString(&json)) {
-    LoginScreenPowerManagementPolicy power_management_policy;
-    power_management_policy.Init(json, NULL);
-    ApplyValueAsMandatoryPolicy(power_management_policy.GetScreenDimDelayAC(),
-                                key::kScreenDimDelayAC,
-                                &user_policy_map);
-    ApplyValueAsMandatoryPolicy(power_management_policy.GetScreenOffDelayAC(),
-                                key::kScreenOffDelayAC,
-                                &user_policy_map);
-    ApplyValueAsMandatoryPolicy(power_management_policy.GetIdleDelayAC(),
-                                key::kIdleDelayAC,
-                                &user_policy_map);
-    ApplyValueAsMandatoryPolicy(
-        power_management_policy.GetScreenDimDelayBattery(),
-        key::kScreenDimDelayBattery,
-        &user_policy_map);
-    ApplyValueAsMandatoryPolicy(
-        power_management_policy.GetScreenOffDelayBattery(),
-        key::kScreenOffDelayBattery,
-        &user_policy_map);
-    ApplyValueAsMandatoryPolicy(power_management_policy.GetIdleDelayBattery(),
-                                key::kIdleDelayBattery,
-                                &user_policy_map);
-    ApplyValueAsMandatoryPolicy(power_management_policy.GetIdleActionAC(),
-                                key::kIdleActionAC,
-                                &user_policy_map);
-    ApplyValueAsMandatoryPolicy(power_management_policy.GetIdleActionBattery(),
-                                key::kIdleActionBattery,
-                                &user_policy_map);
-    ApplyValueAsMandatoryPolicy(power_management_policy.GetLidCloseAction(),
-                                key::kLidCloseAction,
-                                &user_policy_map);
-    ApplyValueAsMandatoryPolicy(
-        power_management_policy.GetUserActivityScreenDimDelayScale(),
-        key::kUserActivityScreenDimDelayScale,
-        &user_policy_map);
+  const base::DictionaryValue* dict = NULL;
+  if (value && value->GetAsDictionary(&dict)) {
+    scoped_ptr<base::DictionaryValue> policy_value(dict->DeepCopy());
+    std::string lid_close_action;
+    base::Value* screen_dim_delay_scale = NULL;
+
+    if (policy_value->GetString(kLidCloseAction, &lid_close_action)) {
+      scoped_ptr<base::Value> action = GetAction(lid_close_action);
+      if (action) {
+        ApplyValueAsMandatoryPolicy(
+            action.get(), key::kLidCloseAction, &user_policy_map);
+      }
+      policy_value->Remove(kLidCloseAction, NULL);
+    }
+
+    if (policy_value->Get(kUserActivityScreenDimDelayScale,
+                          &screen_dim_delay_scale)) {
+      ApplyValueAsMandatoryPolicy(screen_dim_delay_scale,
+                                  key::kUserActivityScreenDimDelayScale,
+                                  &user_policy_map);
+      policy_value->Remove(kUserActivityScreenDimDelayScale, NULL);
+    }
+
+    // |policy_value| is expected to be a valid value for the
+    // PowerManagementIdleSettings policy now.
+    if (!policy_value->empty()) {
+      ApplyValueAsMandatoryPolicy(policy_value.get(),
+                                  key::kPowerManagementIdleSettings,
+                                  &user_policy_map);
+    }
   }
 
   UpdatePolicy(bundle.Pass());
diff --git a/chrome/browser/chromeos/policy/login_screen_power_management_policy.cc b/chrome/browser/chromeos/policy/login_screen_power_management_policy.cc
deleted file mode 100644
index 2e8ce27..0000000
--- a/chrome/browser/chromeos/policy/login_screen_power_management_policy.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/policy/login_screen_power_management_policy.h"
-
-#include "base/json/json_reader.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/values.h"
-#include "chromeos/dbus/power_policy_controller.h"
-#include "components/policy/core/browser/configuration_policy_handler.h"
-#include "components/policy/core/browser/policy_error_map.h"
-#include "grit/component_strings.h"
-#include "policy/policy_constants.h"
-
-namespace policy {
-
-namespace {
-  const char kScreenDimDelayAC[] = "AC.Delays.ScreenDim";
-  const char kScreenOffDelayAC[] = "AC.Delays.ScreenOff";
-  const char kIdleDelayAC[] = "AC.Delays.Idle";
-  const char kScreenDimDelayBattery[] = "Battery.Delays.ScreenDim";
-  const char kScreenOffDelayBattery[] = "Battery.Delays.ScreenOff";
-  const char kIdleDelayBattery[] = "Battery.Delays.Idle";
-  const char kIdleActionAC[] = "AC.IdleAction";
-  const char kIdleActionBattery[] = "Battery.IdleAction";
-  const char kLidCloseAction[] = "LidCloseAction";
-  const char kUserActivityScreenDimDelayScale[] =
-      "UserActivityScreenDimDelayScale";
-
-  const char kActionSuspend[]   = "Suspend";
-  const char kActionShutdown[]  = "Shutdown";
-  const char kActionDoNothing[] = "DoNothing";
-
-scoped_ptr<base::Value> GetValue(const base::DictionaryValue* dict,
-                                 const std::string& key,
-                                 base::Value::Type type,
-                                 PolicyErrorMap* errors) {
-  const base::Value* value;
-  if (!dict->Get(key, &value))
-    return scoped_ptr<base::Value>();
-
-  if (!value->IsType(type)) {
-    if (errors) {
-      errors->AddError(key::kDeviceLoginScreenPowerManagement,
-                       key,
-                       IDS_POLICY_TYPE_ERROR,
-                       ConfigurationPolicyHandler::ValueTypeToString(type));
-    }
-    return scoped_ptr<base::Value>();
-  }
-
-  return scoped_ptr<base::Value>(value->DeepCopy());
-}
-
-scoped_ptr<base::Value> GetInteger(const base::DictionaryValue* dict,
-                                   const std::string& key,
-                                   int minimum,
-                                   PolicyErrorMap* errors) {
-  scoped_ptr<base::Value> value =
-      GetValue(dict, key, base::Value::TYPE_INTEGER, errors);
-  int integer;
-  if (!value || !value->GetAsInteger(&integer) || integer >= minimum)
-    return value.Pass();
-
-  if (errors) {
-    errors->AddError(key::kDeviceLoginScreenPowerManagement,
-                     key,
-                     IDS_POLICY_OUT_OF_RANGE_ERROR,
-                     base::IntToString(integer));
-  }
-  return scoped_ptr<base::Value>();
-}
-
-scoped_ptr<base::Value> GetAction(const base::DictionaryValue* dict,
-                                  const std::string& key,
-                                  PolicyErrorMap* errors) {
-  scoped_ptr<base::Value> value =
-      GetValue(dict, key, base::Value::TYPE_STRING, errors);
-  std::string action;
-  if (!value || !value->GetAsString(&action))
-    return value.Pass();
-
-  if (action == kActionSuspend) {
-    return scoped_ptr<base::Value>(new base::FundamentalValue(
-        chromeos::PowerPolicyController::ACTION_SUSPEND));
-  }
-  if (action == kActionShutdown) {
-    return scoped_ptr<base::Value>(new base::FundamentalValue(
-        chromeos::PowerPolicyController::ACTION_SHUT_DOWN));
-  }
-  if (action == kActionDoNothing) {
-    return scoped_ptr<base::Value>(new base::FundamentalValue(
-        chromeos::PowerPolicyController::ACTION_DO_NOTHING));
-  }
-
-  if (errors) {
-    errors->AddError(key::kDeviceLoginScreenPowerManagement,
-                     key,
-                     IDS_POLICY_OUT_OF_RANGE_ERROR,
-                     action);
-  }
-  return scoped_ptr<base::Value>();
-}
-
-}  // namespace
-
-LoginScreenPowerManagementPolicy::LoginScreenPowerManagementPolicy() {
-}
-
-LoginScreenPowerManagementPolicy::~LoginScreenPowerManagementPolicy() {
-}
-
-bool LoginScreenPowerManagementPolicy::Init(const std::string& json,
-                                            PolicyErrorMap* errors) {
-  std::string error;
-  scoped_ptr<base::Value> root(base::JSONReader::ReadAndReturnError(
-      json, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
-  base::DictionaryValue* dict = NULL;
-  if (!root || !root->GetAsDictionary(&dict)) {
-    if (errors) {
-      errors->AddError(key::kDeviceLoginScreenPowerManagement,
-                       IDS_POLICY_JSON_PARSE_ERROR,
-                       error);
-    }
-    // Errors in JSON decoding are fatal.
-    return false;
-  }
-
-  screen_dim_delay_ac_ = GetInteger(dict, kScreenDimDelayAC, 0, errors);
-  screen_off_delay_ac_ = GetInteger(dict, kScreenOffDelayAC, 0, errors);
-  idle_delay_ac_ = GetInteger(dict, kIdleDelayAC, 0, errors);
-  screen_dim_delay_battery_ =
-      GetInteger(dict, kScreenDimDelayBattery, 0, errors);
-  screen_off_delay_battery_ =
-      GetInteger(dict, kScreenOffDelayBattery, 0, errors);
-  idle_delay_battery_ = GetInteger(dict, kIdleDelayBattery, 0, errors);
-  idle_action_ac_ = GetAction(dict, kIdleActionAC, errors);
-  idle_action_battery_ = GetAction(dict, kIdleActionBattery, errors);
-  lid_close_action_ = GetAction(dict, kLidCloseAction, errors);
-  user_activity_screen_dim_delay_scale_ =
-      GetInteger(dict, kUserActivityScreenDimDelayScale, 100, errors);
-
-  // Validation errors for individual power policies are non-fatal as other
-  // power policies that pass validation will still be applied.
-  return true;
-}
-
-const base::Value*
-    LoginScreenPowerManagementPolicy::GetScreenDimDelayAC() const {
-  return screen_dim_delay_ac_.get();
-}
-
-const base::Value*
-    LoginScreenPowerManagementPolicy::GetScreenOffDelayAC() const {
-  return screen_off_delay_ac_.get();
-}
-
-const base::Value* LoginScreenPowerManagementPolicy::GetIdleDelayAC() const {
-  return idle_delay_ac_.get();
-}
-
-const base::Value*
-    LoginScreenPowerManagementPolicy::GetScreenDimDelayBattery() const {
-  return screen_dim_delay_battery_.get();
-}
-
-const base::Value*
-    LoginScreenPowerManagementPolicy::GetScreenOffDelayBattery() const {
-  return screen_off_delay_battery_.get();
-}
-
-const base::Value*
-    LoginScreenPowerManagementPolicy::GetIdleDelayBattery() const {
-  return idle_delay_battery_.get();
-}
-
-const base::Value* LoginScreenPowerManagementPolicy::GetIdleActionAC() const {
-  return idle_action_ac_.get();
-}
-
-const base::Value*
-    LoginScreenPowerManagementPolicy::GetIdleActionBattery() const {
-  return idle_action_battery_.get();
-}
-
-const base::Value* LoginScreenPowerManagementPolicy::GetLidCloseAction() const {
-  return lid_close_action_.get();
-}
-
-const base::Value* LoginScreenPowerManagementPolicy::
-    GetUserActivityScreenDimDelayScale() const {
-  return user_activity_screen_dim_delay_scale_.get();
-}
-
-} // namespace policy
diff --git a/chrome/browser/chromeos/policy/login_screen_power_management_policy.h b/chrome/browser/chromeos/policy/login_screen_power_management_policy.h
deleted file mode 100644
index c651d06..0000000
--- a/chrome/browser/chromeos/policy/login_screen_power_management_policy.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_SCREEN_POWER_MANAGEMENT_POLICY_H_
-#define CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_SCREEN_POWER_MANAGEMENT_POLICY_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-
-namespace base {
-class Value;
-}
-
-namespace policy {
-
-class PolicyErrorMap;
-
-// Parses power management policy encoded as a JSON string and extracts the
-// individual settings.
-// TODO(bartfab): Remove this code once the policy system has full support for
-// the 'dict' policy type, parsing JSON strings and verifying them against a
-// JSON schema internally. http://crbug.com/258339
-class LoginScreenPowerManagementPolicy {
- public:
-  LoginScreenPowerManagementPolicy();
-  ~LoginScreenPowerManagementPolicy();
-
-  bool Init(const std::string& json, PolicyErrorMap* errors);
-
-  const base::Value* GetScreenDimDelayAC() const;
-  const base::Value* GetScreenOffDelayAC() const;
-  const base::Value* GetIdleDelayAC() const;
-  const base::Value* GetScreenDimDelayBattery() const;
-  const base::Value* GetScreenOffDelayBattery() const;
-  const base::Value* GetIdleDelayBattery() const;
-  const base::Value* GetIdleActionAC() const;
-  const base::Value* GetIdleActionBattery() const;
-  const base::Value* GetLidCloseAction() const;
-  const base::Value* GetUserActivityScreenDimDelayScale() const;
-
- private:
-  scoped_ptr<base::Value> screen_dim_delay_ac_;
-  scoped_ptr<base::Value> screen_off_delay_ac_;
-  scoped_ptr<base::Value> idle_delay_ac_;
-  scoped_ptr<base::Value> screen_dim_delay_battery_;
-  scoped_ptr<base::Value> screen_off_delay_battery_;
-  scoped_ptr<base::Value> idle_delay_battery_;
-  scoped_ptr<base::Value> idle_action_ac_;
-  scoped_ptr<base::Value> idle_action_battery_;
-  scoped_ptr<base::Value> lid_close_action_;
-  scoped_ptr<base::Value> user_activity_screen_dim_delay_scale_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoginScreenPowerManagementPolicy);
-};
-
-}  // namespace policy
-
-#endif  // CHROME_BROWSER_CHROMEOS_POLICY_LOGIN_SCREEN_POWER_MANAGEMENT_POLICY_H_
diff --git a/chrome/browser/chromeos/policy/login_screen_power_management_policy_unittest.cc b/chrome/browser/chromeos/policy/login_screen_power_management_policy_unittest.cc
deleted file mode 100644
index 61bcb7c..0000000
--- a/chrome/browser/chromeos/policy/login_screen_power_management_policy_unittest.cc
+++ /dev/null
@@ -1,187 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/chromeos/policy/login_screen_power_management_policy.h"
-
-#include "chromeos/dbus/power_policy_controller.h"
-#include "components/policy/core/browser/policy_error_map.h"
-#include "policy/policy_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace policy {
-
-namespace {
-
-const char kLoginScreenPowerManagementPolicy[] =
-    "{"
-    "  \"AC\": {"
-    "    \"Delays\": {"
-    "      \"ScreenDim\": 5000,"
-    "      \"ScreenOff\": 7000,"
-    "      \"Idle\": 9000"
-    "    },"
-    "    \"IdleAction\": \"DoNothing\""
-    "  },"
-    "  \"Battery\": {"
-    "    \"Delays\": {"
-    "      \"ScreenDim\": 1000,"
-    "      \"ScreenOff\": 3000,"
-    "      \"Idle\": 4000"
-    "    },"
-    "    \"IdleAction\": \"DoNothing\""
-    "  },"
-    "  \"LidCloseAction\": \"DoNothing\","
-    "  \"UserActivityScreenDimDelayScale\": 300"
-    "}";
-
-}  // namespace
-
-TEST(LoginScreenPowerManagementPolicyTest, InvalidJSON) {
-  PolicyErrorMap errors;
-  LoginScreenPowerManagementPolicy policy;
-  EXPECT_FALSE(policy.Init("Invalid JSON!", &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  EXPECT_FALSE(policy.GetScreenDimDelayAC());
-  EXPECT_FALSE(policy.GetScreenOffDelayAC());
-  EXPECT_FALSE(policy.GetIdleDelayAC());
-  EXPECT_FALSE(policy.GetScreenDimDelayBattery());
-  EXPECT_FALSE(policy.GetScreenOffDelayBattery());
-  EXPECT_FALSE(policy.GetIdleDelayBattery());
-  EXPECT_FALSE(policy.GetIdleActionAC());
-  EXPECT_FALSE(policy.GetIdleActionBattery());
-  EXPECT_FALSE(policy.GetLidCloseAction());
-  EXPECT_FALSE(policy.GetUserActivityScreenDimDelayScale());
-}
-
-TEST(LoginScreenPowerManagementPolicyTest, InitInvalidValues) {
-  PolicyErrorMap errors;
-  scoped_ptr<LoginScreenPowerManagementPolicy> policy;
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init("{ \"AC\": { \"Delays\": { \"ScreenDim\": -1 } } }",
-                           &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetScreenDimDelayAC());
-
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init("{ \"AC\": { \"Delays\": { \"ScreenOff\": -1 } } }",
-                           &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetScreenOffDelayAC());
-
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init("{ \"AC\": { \"Delays\": { \"Idle\": -1 } } }",
-                           &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetIdleDelayAC());
-
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init(
-      "{ \"Battery\": { \"Delays\": { \"ScreenDim\": -1 } } }", &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetScreenDimDelayBattery());
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init(
-      "{ \"Battery\": { \"Delays\": { \"ScreenOff\": -1 } } }", &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetScreenOffDelayBattery());
-
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init("{ \"Battery\": { \"Delays\": { \"Idle\": -1 } } }",
-                           &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetIdleDelayBattery());
-
-  errors.Clear();
-  EXPECT_TRUE(policy->Init("{ \"AC\": { \"IdleAction\": \"SignOut\" } }",
-                           &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  EXPECT_FALSE(policy->GetIdleActionAC());
-
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init("{ \"Battery\": { \"IdleAction\": \"SignOut\" } }",
-                           &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetIdleActionBattery());
-
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init("{ \"LidCloseAction\": \"SignOut\" }", &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetLidCloseAction());
-
-  errors.Clear();
-  policy.reset(new LoginScreenPowerManagementPolicy);
-  EXPECT_TRUE(policy->Init("{ \"UserActivityScreenDimDelayScale\": 50 }",
-                           &errors));
-  EXPECT_FALSE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy);
-  EXPECT_FALSE(policy->GetUserActivityScreenDimDelayScale());
-}
-
-TEST(LoginScreenPowerManagementPolicyTest, ValidJSON) {
-  PolicyErrorMap errors;
-  LoginScreenPowerManagementPolicy policy;
-  EXPECT_TRUE(policy.Init(kLoginScreenPowerManagementPolicy, &errors));
-  EXPECT_TRUE(
-      errors.GetErrors(key::kDeviceLoginScreenPowerManagement).empty());
-  ASSERT_TRUE(policy.GetScreenDimDelayAC());
-  EXPECT_TRUE(base::FundamentalValue(5000).Equals(
-      policy.GetScreenDimDelayAC()));
-  ASSERT_TRUE(policy.GetScreenOffDelayAC());
-  EXPECT_TRUE(base::FundamentalValue(7000).Equals(
-      policy.GetScreenOffDelayAC()));
-  ASSERT_TRUE(policy.GetIdleDelayAC());
-  EXPECT_TRUE(base::FundamentalValue(9000).Equals(policy.GetIdleDelayAC()));
-  ASSERT_TRUE(policy.GetScreenDimDelayBattery());
-  EXPECT_TRUE(base::FundamentalValue(1000).Equals(
-      policy.GetScreenDimDelayBattery()));
-  ASSERT_TRUE(policy.GetScreenOffDelayBattery());
-  EXPECT_TRUE(base::FundamentalValue(3000).Equals(
-      policy.GetScreenOffDelayBattery()));
-  ASSERT_TRUE(policy.GetIdleDelayBattery());
-  EXPECT_TRUE(base::FundamentalValue(4000).Equals(
-      policy.GetIdleDelayBattery()));
-  ASSERT_TRUE(policy.GetIdleActionAC());
-  EXPECT_TRUE(base::FundamentalValue(
-      chromeos::PowerPolicyController::ACTION_DO_NOTHING).Equals(
-          policy.GetIdleActionAC()));
-  ASSERT_TRUE(policy.GetIdleActionBattery());
-  EXPECT_TRUE(base::FundamentalValue(
-      chromeos::PowerPolicyController::ACTION_DO_NOTHING).Equals(
-          policy.GetIdleActionBattery()));
-  ASSERT_TRUE(policy.GetLidCloseAction());
-  EXPECT_TRUE(base::FundamentalValue(
-      chromeos::PowerPolicyController::ACTION_DO_NOTHING).Equals(
-          policy.GetLidCloseAction()));
-  ASSERT_TRUE(policy.GetUserActivityScreenDimDelayScale());
-  EXPECT_TRUE(base::FundamentalValue(300).Equals(
-      policy.GetUserActivityScreenDimDelayScale()));
-}
-
-}  // namespace policy
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
index a8acd1f..2483a07 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.cc
@@ -305,8 +305,8 @@
   if (error.state() == GoogleServiceAuthError::NONE) {
     // Start client registration. Either OnRegistrationStateChanged() or
     // OnClientError() will be called back.
-    client()->Register(em::DeviceRegisterRequest::USER,
-                       policy_token, std::string(), false, std::string());
+    client()->Register(em::DeviceRegisterRequest::USER, policy_token,
+                       std::string(), false, std::string(), std::string());
   } else {
     // Failed to get a token, stop waiting and use an empty policy.
     CancelWaitForPolicyFetch();
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
index 8885d3f..07bf41f 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -35,7 +35,7 @@
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/core/common/schema_registry.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
 #include "google_apis/gaia/gaia_constants.h"
@@ -95,7 +95,7 @@
     TestingProfile::TestingFactories factories;
     factories.push_back(
         std::make_pair(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                       FakeProfileOAuth2TokenServiceWrapper::Build));
+                       BuildFakeProfileOAuth2TokenService));
     profile_ = profile_manager_->CreateTestingProfile(
         chrome::kInitialProfile, scoped_ptr<PrefServiceSyncable>(),
         base::UTF8ToUTF16("testing_profile"), 0, std::string(), factories);
@@ -113,7 +113,7 @@
     // Set up a policy map for testing.
     policy_map_.Set("HomepageLocation",
                     POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-                    base::Value::CreateStringValue("http://chromium.org"),
+                    new base::StringValue("http://chromium.org"),
                     NULL);
     expected_bundle_.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
         .CopyFrom(policy_map_);
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc
index 6ab114b..7595a4e 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_store_chromeos_unittest.cc
@@ -159,7 +159,7 @@
       previous_policy.Set(key::kHomepageLocation,
                           POLICY_LEVEL_MANDATORY,
                           POLICY_SCOPE_USER,
-                          base::Value::CreateStringValue(previous_value), NULL);
+                          new base::StringValue(previous_value), NULL);
     }
     EXPECT_TRUE(previous_policy.Equals(store_->policy_map()));
     EXPECT_EQ(CloudPolicyStore::STATUS_OK, store_->status());
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc
index 3d91613..1a3b2d3 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder.cc
@@ -8,7 +8,7 @@
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "components/policy/core/common/cloud/cloud_policy_core.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/notification_source.h"
 #include "google_apis/gaia/gaia_constants.h"
 
diff --git a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_factory.cc b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_factory.cc
index ef1abff..c973074 100644
--- a/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_factory.cc
+++ b/chrome/browser/chromeos/policy/user_cloud_policy_token_forwarder_factory.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 namespace policy {
 
diff --git a/chrome/browser/chromeos/reset/metrics.h b/chrome/browser/chromeos/reset/metrics.h
new file mode 100644
index 0000000..44f848d
--- /dev/null
+++ b/chrome/browser/chromeos/reset/metrics.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_RESET_METRICS_H_
+#define CHROME_BROWSER_CHROMEOS_RESET_METRICS_H_
+
+namespace chromeos {
+namespace reset {
+
+enum DialogViewType {
+
+  // User invoked the dialog from options page.
+  DIALOG_FROM_OPTIONS,
+
+  // Invoked with shortcut. Confirming form for powerwash.
+  DIALOG_SHORTCUT_CONFIRMING_POWERWASH_ONLY,
+
+  // Invoked with shortcut. Confirming form for powerwash and rollback.
+  DIALOG_SHORTCUT_CONFIRMING_POWERWASH_AND_ROLLBACK,
+
+  // Invoked with shortcut. Offering form, rollback checkbox unavailable.
+  DIALOG_SHORTCUT_OFFERING_ROLLBACK_UNAVAILABLE,
+
+  // Invoked with shortcut. Offering form, rollback checkbox available.
+  DIALOG_SHORTCUT_OFFERING_ROLLBACK_AVAILABLE,
+
+  // Must be last enum element.
+  DIALOG_VIEW_TYPE_SIZE
+};
+
+}  // namespace reset
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_RESET_METRICS_H_
diff --git a/chrome/browser/chromeos/system/automatic_reboot_manager.cc b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
index 2ca1409..cdf07d4 100644
--- a/chrome/browser/chromeos/system/automatic_reboot_manager.cc
+++ b/chrome/browser/chromeos/system/automatic_reboot_manager.cc
@@ -65,7 +65,7 @@
   std::string contents;
   char buffer[kOneKilobyte];
   ssize_t length;
-  while ((length = read(fd.get(), buffer, sizeof(buffer))) > 0)
+  while ((length = HANDLE_EINTR(read(fd.get(), buffer, sizeof(buffer)))) > 0)
     contents.append(buffer, length);
 
   double seconds;
diff --git a/chrome/browser/chromeos/system/input_device_settings.cc b/chrome/browser/chromeos/system/input_device_settings.cc
index c377025..10cc5a6 100644
--- a/chrome/browser/chromeos/system/input_device_settings.cc
+++ b/chrome/browser/chromeos/system/input_device_settings.cc
@@ -33,8 +33,9 @@
 InputDeviceSettings* g_instance_;
 InputDeviceSettings* g_test_instance_;
 
-const char kTpControl[] = "/opt/google/touchpad/tpcontrol";
-const char kMouseControl[] = "/opt/google/mouse/mousecontrol";
+const char kDeviceTypeTouchpad[] = "touchpad";
+const char kDeviceTypeMouse[] = "mouse";
+const char kInputControl[] = "/opt/google/input/inputcontrol";
 
 const char kRemoraRequisition[] = "remora";
 
@@ -81,34 +82,35 @@
   runner->PostTask(FROM_HERE, base::Bind(&ExecuteScriptOnFileThread, argv));
 }
 
-void AddSensitivityArguments(int value, std::vector<std::string>* argv) {
+void AddSensitivityArguments(const char* device_type, int value,
+                             std::vector<std::string>* argv) {
   DCHECK(value >= kMinPointerSensitivity && value <= kMaxPointerSensitivity);
-  argv->push_back("sensitivity");
-  argv->push_back(base::StringPrintf("%d", value));
+  argv->push_back(base::StringPrintf("--%s_sensitivity=%d",
+                                     device_type, value));
 }
 
 void AddTPControlArguments(const char* control,
                            bool enabled,
                            std::vector<std::string>* argv) {
-  argv->push_back(control);
-  argv->push_back(enabled ? "on" : "off");
+  argv->push_back(base::StringPrintf("--%s=%d", control, enabled ? 1 : 0));
 }
 
-void DeviceExistsBlockingPool(const char* script,
+void DeviceExistsBlockingPool(const char* device_type,
                               scoped_refptr<RefCountedBool> exists) {
   DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
   exists->data = false;
-  if (!ScriptExists(script))
+  if (!ScriptExists(kInputControl))
     return;
 
   std::vector<std::string> argv;
-  argv.push_back(script);
-  argv.push_back("status");
+  argv.push_back(kInputControl);
+  argv.push_back(base::StringPrintf("--type=%s", device_type));
+  argv.push_back("--list");
   std::string output;
   // Output is empty if the device is not found.
   exists->data = base::GetAppOutput(CommandLine(argv), &output) &&
       !output.empty();
-  DVLOG(1) << "DeviceExistsBlockingPool:" << script << "=" << exists->data;
+  DVLOG(1) << "DeviceExistsBlockingPool:" << device_type << "=" << exists->data;
 }
 
 void RunCallbackUIThread(
@@ -168,7 +170,7 @@
 
 void InputDeviceSettingsImpl::TouchpadExists(
     const DeviceExistsCallback& callback) {
-  DeviceExists(kTpControl, callback);
+  DeviceExists(kDeviceTypeTouchpad, callback);
 }
 
 void InputDeviceSettingsImpl::UpdateTouchpadSettings(
@@ -206,7 +208,7 @@
 void InputDeviceSettingsImpl::MouseExists(
     const DeviceExistsCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  DeviceExists(kMouseControl, callback);
+  DeviceExists(kDeviceTypeMouse, callback);
 }
 
 void InputDeviceSettingsImpl::UpdateMouseSettings(const MouseSettings& update) {
@@ -313,17 +315,17 @@
 bool TouchpadSettings::Update(const TouchpadSettings& settings,
                               std::vector<std::string>* argv) {
   if (argv)
-    argv->push_back(kTpControl);
+    argv->push_back(kInputControl);
   bool updated = false;
   if (sensitivity_.Update(settings.sensitivity_)) {
     updated = true;
     if (argv)
-      AddSensitivityArguments(sensitivity_.value(), argv);
+      AddSensitivityArguments(kDeviceTypeTouchpad, sensitivity_.value(), argv);
   }
   if (tap_to_click_.Update(settings.tap_to_click_)) {
     updated = true;
     if (argv)
-      AddTPControlArguments("taptoclick", tap_to_click_.value(), argv);
+      AddTPControlArguments("tapclick", tap_to_click_.value(), argv);
   }
   if (three_finger_click_.Update(settings.three_finger_click_)) {
     updated = true;
@@ -335,7 +337,7 @@
   if (tap_dragging_.Update(settings.tap_dragging_)) {
     updated = true;
     if (argv)
-      AddTPControlArguments("tap_dragging", tap_dragging_.value(), argv);
+      AddTPControlArguments("tapdrag", tap_dragging_.value(), argv);
   }
   return updated;
 }
@@ -369,18 +371,18 @@
 bool MouseSettings::Update(const MouseSettings& settings,
                            std::vector<std::string>* argv) {
   if (argv)
-    argv->push_back(kMouseControl);
+    argv->push_back(kInputControl);
   bool updated = false;
   if (sensitivity_.Update(settings.sensitivity_)) {
     updated = true;
     if (argv)
-      AddSensitivityArguments(sensitivity_.value(), argv);
+      AddSensitivityArguments(kDeviceTypeMouse, sensitivity_.value(), argv);
   }
   if (primary_button_right_.Update(settings.primary_button_right_)) {
     updated = true;
     if (argv) {
-      argv->push_back("swap_left_right");
-      argv->push_back(settings.GetPrimaryButtonRight() ? "1" : "0");
+      AddTPControlArguments("mouse_swap_lr", primary_button_right_.value(),
+                            argv);
     }
   }
   return updated;
diff --git a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
index e7f1ef4..1426fe0 100644
--- a/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
+++ b/chrome/browser/chromeos/system/tray_accessibility_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
@@ -19,6 +20,7 @@
 #include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/user_manager_impl.h"
+#include "chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/chrome_switches.h"
@@ -34,8 +36,12 @@
 #include "content/public/test/test_utils.h"
 #include "policy/policy_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/label.h"
 #include "ui/views/widget/widget.h"
 
+using extensions::api::braille_display_private::BrailleObserver;
+using extensions::api::braille_display_private::DisplayState;
+using extensions::api::braille_display_private::MockBrailleController;
 using testing::Return;
 using testing::_;
 using testing::WithParamInterface;
@@ -58,13 +64,14 @@
   TrayAccessibilityTest() {}
   virtual ~TrayAccessibilityTest() {}
 
-  // The profile which should be used by tese tests.
+  // The profile which should be used by these tests.
   Profile* GetProfile() { return ProfileManager::GetActiveUserProfile(); }
 
   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
     EXPECT_CALL(provider_, IsInitializationComplete(_))
         .WillRepeatedly(Return(true));
     policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+    AccessibilityManager::SetBrailleControllerForTest(&braille_controller_);
   }
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
@@ -84,6 +91,10 @@
     InProcessBrowserTest::RunTestOnMainThreadLoop();
   }
 
+  virtual void CleanUpOnMainThread() OVERRIDE {
+    AccessibilityManager::SetBrailleControllerForTest(NULL);
+  }
+
   void SetShowAccessibilityOptionsInSystemTrayMenu(bool value) {
     if (GetParam() == PREF_SERVICE) {
       PrefService* prefs = GetProfile()->GetPrefs();
@@ -107,10 +118,14 @@
         GetTrayAccessibilityForTest();
   }
 
-  bool IsTrayIconVisible() {
-    return tray()->tray_icon_visible_;
+  const ash::internal::TrayAccessibility* tray() const {
+    return ash::Shell::GetInstance()
+        ->GetPrimarySystemTray()
+        ->GetTrayAccessibilityForTest();
   }
 
+  bool IsTrayIconVisible() const { return tray()->tray_icon_visible_; }
+
   views::View* CreateMenuItem() {
     return tray()->CreateDefaultView(GetLoginStatus());
   }
@@ -174,55 +189,74 @@
     tray()->detailed_menu_->OnViewClicked(button);
   }
 
-  bool IsSpokenFeedbackEnabledOnDetailMenu() {
+  bool IsSpokenFeedbackEnabledOnDetailMenu() const {
     return tray()->detailed_menu_->spoken_feedback_enabled_;
   }
 
-  bool IsHighContrastEnabledOnDetailMenu() {
+  bool IsHighContrastEnabledOnDetailMenu() const {
     return tray()->detailed_menu_->high_contrast_enabled_;
   }
 
-  bool IsScreenMagnifierEnabledOnDetailMenu() {
+  bool IsScreenMagnifierEnabledOnDetailMenu() const {
     return tray()->detailed_menu_->screen_magnifier_enabled_;
   }
 
-  bool IsLargeCursorEnabledOnDetailMenu() {
+  bool IsLargeCursorEnabledOnDetailMenu() const {
     return tray()->detailed_menu_->large_cursor_enabled_;
   }
 
-  bool IsAutoclickEnabledOnDetailMenu() {
+  bool IsAutoclickEnabledOnDetailMenu() const {
     return tray()->detailed_menu_->autoclick_enabled_;
   }
 
-  bool IsVirtualKeyboardEnabledOnDetailMenu() {
+  bool IsVirtualKeyboardEnabledOnDetailMenu() const {
     return tray()->detailed_menu_->virtual_keyboard_enabled_;
   }
 
-  bool IsSpokenFeedbackMenuShownOnDetailMenu() {
+  bool IsSpokenFeedbackMenuShownOnDetailMenu() const {
     return tray()->detailed_menu_->spoken_feedback_view_;
   }
 
-  bool IsHighContrastMenuShownOnDetailMenu() {
+  bool IsHighContrastMenuShownOnDetailMenu() const {
     return tray()->detailed_menu_->high_contrast_view_;
   }
 
-  bool IsScreenMagnifierMenuShownOnDetailMenu() {
+  bool IsScreenMagnifierMenuShownOnDetailMenu() const {
     return tray()->detailed_menu_->screen_magnifier_view_;
   }
 
-  bool IsLargeCursorMenuShownOnDetailMenu() {
+  bool IsLargeCursorMenuShownOnDetailMenu() const {
     return tray()->detailed_menu_->large_cursor_view_;
   }
 
-  bool IsAutoclickMenuShownOnDetailMenu() {
+  bool IsAutoclickMenuShownOnDetailMenu() const {
     return tray()->detailed_menu_->autoclick_view_;
   }
 
-  bool IsVirtualKeyboardMenuShownOnDetailMenu() {
+  bool IsVirtualKeyboardMenuShownOnDetailMenu() const {
     return tray()->detailed_menu_->virtual_keyboard_view_;
   }
 
+  bool IsNotificationShown() const {
+    return (tray()->detailed_popup_ &&
+            !tray()->detailed_popup_->GetWidget()->IsClosed());
+  }
+
+  base::string16 GetNotificationText() const {
+    if (IsNotificationShown())
+      return tray()->detailed_popup_->label_for_test()->text();
+    else
+      return base::string16();
+  }
+
+  void SetBrailleConnected(bool connected) {
+    braille_controller_.SetAvailable(connected);
+    braille_controller_.GetObserver()->OnDisplayStateChanged(
+        *braille_controller_.GetDisplayState());
+  }
+
   policy::MockConfigurationPolicyProvider provider_;
+  MockBrailleController braille_controller_;
 };
 
 IN_PROC_BROWSER_TEST_P(TrayAccessibilityTest, LoginStatus) {
@@ -508,6 +542,43 @@
   EXPECT_TRUE(CanCreateMenuItem());
 }
 
+IN_PROC_BROWSER_TEST_P(TrayAccessibilityTest, ShowNotification) {
+  const base::string16 BRAILLE_CONNECTED =
+      base::ASCIIToUTF16("Braille display connected.");
+  const base::string16 CHROMEVOX_ENABLED = base::ASCIIToUTF16(
+      "ChromeVox (spoken feedback) is enabled.\nPress Ctrl+Alt+Z to disable.");
+  const base::string16 BRAILLE_CONNECTED_AND_CHROMEVOX_ENABLED(
+      BRAILLE_CONNECTED + base::ASCIIToUTF16(" ") + CHROMEVOX_ENABLED);
+
+  EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
+
+  // Enabling spoken feedback should show the notification.
+  AccessibilityManager::Get()->EnableSpokenFeedback(
+      true, ash::A11Y_NOTIFICATION_SHOW);
+  EXPECT_EQ(CHROMEVOX_ENABLED, GetNotificationText());
+
+  // Connecting a braille display when spoken feedback is already enabled
+  // should only show the message about the braille display.
+  SetBrailleConnected(true);
+  EXPECT_EQ(BRAILLE_CONNECTED, GetNotificationText());
+
+  // Neither disconnecting a braille display, nor disabling spoken feedback
+  // should show any notification.
+  SetBrailleConnected(false);
+  EXPECT_TRUE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
+  EXPECT_FALSE(IsNotificationShown());
+  AccessibilityManager::Get()->EnableSpokenFeedback(
+      false, ash::A11Y_NOTIFICATION_SHOW);
+  EXPECT_FALSE(IsNotificationShown());
+  EXPECT_FALSE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
+
+  // Connecting a braille display should enable spoken feedback and show
+  // both messages.
+  SetBrailleConnected(true);
+  EXPECT_TRUE(AccessibilityManager::Get()->IsSpokenFeedbackEnabled());
+  EXPECT_EQ(BRAILLE_CONNECTED_AND_CHROMEVOX_ENABLED, GetNotificationText());
+}
+
 IN_PROC_BROWSER_TEST_P(TrayAccessibilityTest, KeepMenuVisibilityOnLockScreen) {
   // Enables high contrast mode.
   AccessibilityManager::Get()->EnableHighContrast(true);
diff --git a/chrome/browser/chromeos/timezone/timezone_provider.cc b/chrome/browser/chromeos/timezone/timezone_provider.cc
new file mode 100644
index 0000000..bc697b5
--- /dev/null
+++ b/chrome/browser/chromeos/timezone/timezone_provider.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/timezone/timezone_provider.h"
+
+#include <algorithm>
+#include <iterator>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "content/public/common/geoposition.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "url/gurl.h"
+
+namespace chromeos {
+
+TimeZoneProvider::TimeZoneProvider(
+    net::URLRequestContextGetter* url_context_getter,
+    const GURL& url)
+    : url_context_getter_(url_context_getter), url_(url) {
+}
+
+TimeZoneProvider::~TimeZoneProvider() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void TimeZoneProvider::RequestTimezone(
+    const content::Geoposition& position,
+    bool sensor,
+    base::TimeDelta timeout,
+    TimeZoneRequest::TimeZoneResponseCallback callback) {
+  TimeZoneRequest* request(new TimeZoneRequest(
+      url_context_getter_, url_, position, sensor, timeout));
+  requests_.push_back(request);
+
+  // TimeZoneProvider owns all requests. It is safe to pass unretained "this"
+  // because destruction of TimeZoneProvider cancels all requests.
+  TimeZoneRequest::TimeZoneResponseCallback callback_tmp(
+      base::Bind(&TimeZoneProvider::OnTimezoneResponse,
+                 base::Unretained(this),
+                 request,
+                 callback));
+  request->MakeRequest(callback_tmp);
+}
+
+void TimeZoneProvider::OnTimezoneResponse(
+    TimeZoneRequest* request,
+    TimeZoneRequest::TimeZoneResponseCallback callback,
+    scoped_ptr<TimeZoneResponseData> timezone,
+    bool server_error) {
+  ScopedVector<TimeZoneRequest>::iterator new_end =
+      std::remove(requests_.begin(), requests_.end(), request);
+  DCHECK_EQ(std::distance(new_end, requests_.end()), 1);
+  requests_.erase(new_end, requests_.end());
+
+  callback.Run(timezone.Pass(), server_error);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/timezone/timezone_provider.h b/chrome/browser/chromeos/timezone/timezone_provider.h
new file mode 100644
index 0000000..d6a9ee9
--- /dev/null
+++ b/chrome/browser/chromeos/timezone/timezone_provider.h
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_TIMEZONE_TIMEZONE_PROVIDER_H_
+#define CHROME_BROWSER_CHROMEOS_TIMEZONE_TIMEZONE_PROVIDER_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
+#include "chrome/browser/chromeos/timezone/timezone_request.h"
+#include "url/gurl.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace content {
+struct Geoposition;
+}
+
+namespace chromeos {
+
+// This class implements Google TimeZone API.
+//
+// Note: this should probably be a singleton to monitor requests rate.
+// But as it is used only from WizardController, it can be owned by it for now.
+class TimeZoneProvider {
+ public:
+  TimeZoneProvider(net::URLRequestContextGetter* url_context_getter,
+                   const GURL& url);
+  virtual ~TimeZoneProvider();
+
+  // Initiates new request (See TimeZoneRequest for parameters description.)
+  void RequestTimezone(const content::Geoposition& position,
+                       bool sensor,
+                       base::TimeDelta timeout,
+                       TimeZoneRequest::TimeZoneResponseCallback callback);
+
+ private:
+  // Deletes request from requests_.
+  void OnTimezoneResponse(TimeZoneRequest* request,
+                          TimeZoneRequest::TimeZoneResponseCallback callback,
+                          scoped_ptr<TimeZoneResponseData> timezone,
+                          bool server_error);
+
+  scoped_refptr<net::URLRequestContextGetter> url_context_getter_;
+  const GURL url_;
+
+  // Requests in progress.
+  // TimeZoneProvider owns all requests, so this vector is deleted on destroy.
+  ScopedVector<TimeZoneRequest> requests_;
+
+  // Creation and destruction should happen on the same thread.
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(TimeZoneProvider);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_TIMEZONE_TIMEZONE_PROVIDER_H_
diff --git a/chrome/browser/chromeos/timezone/timezone_request.cc b/chrome/browser/chromeos/timezone/timezone_request.cc
new file mode 100644
index 0000000..ee2ea42
--- /dev/null
+++ b/chrome/browser/chromeos/timezone/timezone_request.cc
@@ -0,0 +1,428 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/timezone/timezone_request.h"
+
+#include <string>
+
+#include "base/json/json_reader.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "content/public/common/geoposition.h"
+#include "google_apis/google_api_keys.h"
+#include "net/base/escape.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/url_request/url_request_status.h"
+
+namespace chromeos {
+
+namespace {
+
+const char kDefaultTimezoneProviderUrl[] =
+    "https://maps.googleapis.com/maps/api/timezone/json?";
+
+const char kKeyString[] = "key";
+// Language parameter is unsupported for now.
+// const char kLanguageString[] = "language";
+const char kLocationString[] = "location";
+const char kSensorString[] = "sensor";
+const char kTimestampString[] = "timestamp";
+
+const char kDstOffsetString[] = "dstOffset";
+const char kRawOffsetString[] = "rawOffset";
+const char kTimeZoneIdString[] = "timeZoneId";
+const char kTimeZoneNameString[] = "timeZoneName";
+const char kStatusString[] = "status";
+const char kErrorMessageString[] = "error_message";
+
+// Sleep between timezone request retry on HTTP error.
+const unsigned int kResolveTimeZoneRetrySleepOnServerErrorSeconds = 5;
+
+// Sleep between timezone request retry on bad server response.
+const unsigned int kResolveTimeZoneRetrySleepBadResponseSeconds = 10;
+
+struct StatusString2Enum {
+  const char* string;
+  TimeZoneResponseData::Status value;
+};
+
+const StatusString2Enum statusString2Enum[] = {
+    {"OK", TimeZoneResponseData::OK},
+    {"INVALID_REQUEST", TimeZoneResponseData::INVALID_REQUEST},
+    {"OVER_QUERY_LIMIT", TimeZoneResponseData::OVER_QUERY_LIMIT},
+    {"REQUEST_DENIED", TimeZoneResponseData::REQUEST_DENIED},
+    {"UNKNOWN_ERROR", TimeZoneResponseData::UNKNOWN_ERROR},
+    {"ZERO_RESULTS", TimeZoneResponseData::ZERO_RESULTS}, };
+
+enum TimeZoneRequestEvent {
+  // NOTE: Do not renumber these as that would confuse interpretation of
+  // previously logged data. When making changes, also update the enum list
+  // in tools/metrics/histograms/histograms.xml to keep it in sync.
+  TIMEZONE_REQUEST_EVENT_REQUEST_START = 0,
+  TIMEZONE_REQUEST_EVENT_RESPONSE_SUCCESS = 1,
+  TIMEZONE_REQUEST_EVENT_RESPONSE_NOT_OK = 2,
+  TIMEZONE_REQUEST_EVENT_RESPONSE_EMPTY = 3,
+  TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED = 4,
+
+  // NOTE: Add entries only immediately above this line.
+  TIMEZONE_REQUEST_EVENT_COUNT = 5
+};
+
+enum TimeZoneRequestResult {
+  // NOTE: Do not renumber these as that would confuse interpretation of
+  // previously logged data. When making changes, also update the enum list
+  // in tools/metrics/histograms/histograms.xml to keep it in sync.
+  TIMEZONE_REQUEST_RESULT_SUCCESS = 0,
+  TIMEZONE_REQUEST_RESULT_FAILURE = 1,
+  TIMEZONE_REQUEST_RESULT_SERVER_ERROR = 2,
+  TIMEZONE_REQUEST_RESULT_CANCELLED = 3,
+
+  // NOTE: Add entries only immediately above this line.
+  TIMEZONE_REQUEST_RESULT_COUNT = 4
+};
+
+// Too many requests (more than 1) mean there is a problem in implementation.
+void RecordUmaEvent(TimeZoneRequestEvent event) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "TimeZone.TimeZoneRequest.Event", event, TIMEZONE_REQUEST_EVENT_COUNT);
+}
+
+void RecordUmaResponseCode(int code) {
+  UMA_HISTOGRAM_SPARSE_SLOWLY("TimeZone.TimeZoneRequest.ResponseCode", code);
+}
+
+// Slow timezone resolve leads to bad user experience.
+void RecordUmaResponseTime(base::TimeDelta elapsed, bool success) {
+  if (success) {
+    UMA_HISTOGRAM_TIMES("TimeZone.TimeZoneRequest.ResponseSuccessTime",
+                        elapsed);
+  } else {
+    UMA_HISTOGRAM_TIMES("TimeZone.TimeZoneRequest.ResponseFailureTime",
+                        elapsed);
+  }
+}
+
+void RecordUmaResult(TimeZoneRequestResult result, unsigned retries) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "TimeZone.TimeZoneRequest.Result", result, TIMEZONE_REQUEST_RESULT_COUNT);
+  UMA_HISTOGRAM_SPARSE_SLOWLY("TimeZone.TimeZoneRequest.Retries", retries);
+}
+
+// Creates the request url to send to the server.
+GURL TimeZoneRequestURL(const GURL& url,
+                        const content::Geoposition& geoposition,
+                        bool sensor) {
+  std::string query(url.query());
+  query += base::StringPrintf(
+      "%s=%f,%f", kLocationString, geoposition.latitude, geoposition.longitude);
+  if (url == DefaultTimezoneProviderURL()) {
+    std::string api_key = google_apis::GetAPIKey();
+    if (!api_key.empty()) {
+      query += "&";
+      query += kKeyString;
+      query += "=";
+      query += net::EscapeQueryParamValue(api_key, true);
+    }
+  }
+  if (!geoposition.timestamp.is_null()) {
+    query += base::StringPrintf(
+        "&%s=%ld", kTimestampString, geoposition.timestamp.ToTimeT());
+  }
+  query += "&";
+  query += kSensorString;
+  query += "=";
+  query += (sensor ? "true" : "false");
+
+  GURL::Replacements replacements;
+  replacements.SetQueryStr(query);
+  return url.ReplaceComponents(replacements);
+}
+
+void PrintTimeZoneError(const GURL& server_url,
+                        const std::string& message,
+                        TimeZoneResponseData* timezone) {
+  timezone->status = TimeZoneResponseData::REQUEST_ERROR;
+  timezone->error_message =
+      base::StringPrintf("TimeZone provider at '%s' : %s.",
+                         server_url.GetOrigin().spec().c_str(),
+                         message.c_str());
+  LOG(WARNING) << "TimeZoneRequest::GetTimeZoneFromResponse() : "
+               << timezone->error_message;
+}
+
+// Parses the server response body. Returns true if parsing was successful.
+// Sets |*timezone| to the parsed TimeZone if a valid timezone was received,
+// otherwise leaves it unchanged.
+bool ParseServerResponse(const GURL& server_url,
+                         const std::string& response_body,
+                         TimeZoneResponseData* timezone) {
+  DCHECK(timezone);
+
+  if (response_body.empty()) {
+    PrintTimeZoneError(server_url, "Server returned empty response", timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_EMPTY);
+    return false;
+  }
+  VLOG(1) << "TimeZoneRequest::ParseServerResponse() : Parsing response "
+          << response_body;
+
+  // Parse the response, ignoring comments.
+  std::string error_msg;
+  scoped_ptr<base::Value> response_value(base::JSONReader::ReadAndReturnError(
+      response_body, base::JSON_PARSE_RFC, NULL, &error_msg));
+  if (response_value == NULL) {
+    PrintTimeZoneError(server_url, "JSONReader failed: " + error_msg, timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  const base::DictionaryValue* response_object = NULL;
+  if (!response_value->GetAsDictionary(&response_object)) {
+    PrintTimeZoneError(server_url,
+                       "Unexpected response type : " +
+                           base::StringPrintf("%u", response_value->GetType()),
+                       timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  std::string status;
+
+  if (!response_object->GetStringWithoutPathExpansion(kStatusString, &status)) {
+    PrintTimeZoneError(server_url, "Missing status attribute.", timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  bool found = false;
+  for (size_t i = 0; i < arraysize(statusString2Enum); ++i) {
+    if (status != statusString2Enum[i].string)
+      continue;
+
+    timezone->status = statusString2Enum[i].value;
+    found = true;
+    break;
+  }
+
+  if (!found) {
+    PrintTimeZoneError(
+        server_url, "Bad status attribute value: '" + status + "'", timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  const bool status_ok = (timezone->status == TimeZoneResponseData::OK);
+
+  if (!response_object->GetDoubleWithoutPathExpansion(kDstOffsetString,
+                                                      &timezone->dstOffset) &&
+      status_ok) {
+    PrintTimeZoneError(server_url, "Missing dstOffset attribute.", timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  if (!response_object->GetDoubleWithoutPathExpansion(kRawOffsetString,
+                                                      &timezone->rawOffset) &&
+      status_ok) {
+    PrintTimeZoneError(server_url, "Missing rawOffset attribute.", timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  if (!response_object->GetStringWithoutPathExpansion(kTimeZoneIdString,
+                                                      &timezone->timeZoneId) &&
+      status_ok) {
+    PrintTimeZoneError(server_url, "Missing timeZoneId attribute.", timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  if (!response_object->GetStringWithoutPathExpansion(
+          kTimeZoneNameString, &timezone->timeZoneName) &&
+      status_ok) {
+    PrintTimeZoneError(server_url, "Missing timeZoneName attribute.", timezone);
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_MALFORMED);
+    return false;
+  }
+
+  // "error_message" field is optional. Ignore result.
+  response_object->GetStringWithoutPathExpansion(kErrorMessageString,
+                                                 &timezone->error_message);
+
+  return true;
+}
+
+// Attempts to extract a position from the response. Detects and indicates
+// various failure cases.
+scoped_ptr<TimeZoneResponseData> GetTimeZoneFromResponse(
+    bool http_success,
+    int status_code,
+    const std::string& response_body,
+    const GURL& server_url) {
+  scoped_ptr<TimeZoneResponseData> timezone(new TimeZoneResponseData);
+
+  // HttpPost can fail for a number of reasons. Most likely this is because
+  // we're offline, or there was no response.
+  if (!http_success) {
+    PrintTimeZoneError(server_url, "No response received", timezone.get());
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_EMPTY);
+    return timezone.Pass();
+  }
+  if (status_code != net::HTTP_OK) {
+    std::string message = "Returned error code ";
+    message += base::IntToString(status_code);
+    PrintTimeZoneError(server_url, message, timezone.get());
+    RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_NOT_OK);
+    return timezone.Pass();
+  }
+
+  if (!ParseServerResponse(server_url, response_body, timezone.get()))
+    return timezone.Pass();
+
+  RecordUmaEvent(TIMEZONE_REQUEST_EVENT_RESPONSE_SUCCESS);
+  return timezone.Pass();
+}
+
+}  // namespace
+
+TimeZoneResponseData::TimeZoneResponseData()
+    : dstOffset(0), rawOffset(0), status(ZERO_RESULTS) {
+}
+
+GURL DefaultTimezoneProviderURL() {
+  return GURL(kDefaultTimezoneProviderUrl);
+}
+
+TimeZoneRequest::TimeZoneRequest(
+    net::URLRequestContextGetter* url_context_getter,
+    const GURL& service_url,
+    const content::Geoposition& geoposition,
+    bool sensor,
+    base::TimeDelta retry_timeout)
+    : url_context_getter_(url_context_getter),
+      service_url_(service_url),
+      geoposition_(geoposition),
+      sensor_(sensor),
+      retry_timeout_abs_(base::Time::Now() + retry_timeout),
+      retries_(0) {
+}
+
+TimeZoneRequest::~TimeZoneRequest() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  // If callback is not empty, request is cancelled.
+  if (!callback_.is_null()) {
+    RecordUmaResponseTime(base::Time::Now() - request_started_at_, false);
+    RecordUmaResult(TIMEZONE_REQUEST_RESULT_CANCELLED, retries_);
+  }
+}
+
+void TimeZoneRequest::StartRequest() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  RecordUmaEvent(TIMEZONE_REQUEST_EVENT_REQUEST_START);
+  request_started_at_ = base::Time::Now();
+  ++retries_;
+
+  url_fetcher_.reset(
+      net::URLFetcher::Create(request_url_, net::URLFetcher::GET, this));
+  url_fetcher_->SetRequestContext(url_context_getter_);
+  url_fetcher_->SetLoadFlags(net::LOAD_BYPASS_CACHE |
+                             net::LOAD_DISABLE_CACHE |
+                             net::LOAD_DO_NOT_SAVE_COOKIES |
+                             net::LOAD_DO_NOT_SEND_COOKIES |
+                             net::LOAD_DO_NOT_SEND_AUTH_DATA);
+  url_fetcher_->Start();
+}
+
+void TimeZoneRequest::MakeRequest(TimeZoneResponseCallback callback) {
+  callback_ = callback;
+  request_url_ =
+      TimeZoneRequestURL(service_url_, geoposition_, false /* sensor */);
+  StartRequest();
+}
+
+void TimeZoneRequest::Retry(bool server_error) {
+  const base::TimeDelta delay = base::TimeDelta::FromSeconds(
+      server_error ? kResolveTimeZoneRetrySleepOnServerErrorSeconds
+                   : kResolveTimeZoneRetrySleepBadResponseSeconds);
+  timezone_request_scheduled_.Start(
+      FROM_HERE, delay, this, &TimeZoneRequest::StartRequest);
+}
+
+void TimeZoneRequest::OnURLFetchComplete(const net::URLFetcher* source) {
+  DCHECK_EQ(url_fetcher_.get(), source);
+
+  net::URLRequestStatus status = source->GetStatus();
+  int response_code = source->GetResponseCode();
+  RecordUmaResponseCode(response_code);
+
+  std::string data;
+  source->GetResponseAsString(&data);
+  scoped_ptr<TimeZoneResponseData> timezone = GetTimeZoneFromResponse(
+      status.is_success(), response_code, data, source->GetURL());
+  const bool server_error =
+      !status.is_success() || (response_code >= 500 && response_code < 600);
+  url_fetcher_.reset();
+
+  DVLOG(1) << "TimeZoneRequest::OnURLFetchComplete(): timezone={"
+           << timezone->ToStringForDebug() << "}";
+
+  const base::Time now = base::Time::Now();
+  const bool retry_timeout = (now >= retry_timeout_abs_);
+
+  const bool success = (timezone->status == TimeZoneResponseData::OK);
+  if (!success && !retry_timeout) {
+    Retry(server_error);
+    return;
+  }
+  RecordUmaResponseTime(base::Time::Now() - request_started_at_, success);
+
+  const TimeZoneRequestResult result =
+      (server_error ? TIMEZONE_REQUEST_RESULT_SERVER_ERROR
+                    : (success ? TIMEZONE_REQUEST_RESULT_SUCCESS
+                               : TIMEZONE_REQUEST_RESULT_FAILURE));
+  RecordUmaResult(result, retries_);
+
+  TimeZoneResponseCallback callback = callback_;
+
+  // Empty callback is used to identify "completed or not yet started request".
+  callback_.Reset();
+
+  // callback.Run() usually destroys TimeZoneRequest, because this is the way
+  // callback is implemented in TimeZoneProvider.
+  callback.Run(timezone.Pass(), server_error);
+  // "this" is already destroyed here.
+}
+
+std::string TimeZoneResponseData::ToStringForDebug() const {
+  static const char* const status2string[] = {
+      "OK",
+      "INVALID_REQUEST",
+      "OVER_QUERY_LIMIT",
+      "REQUEST_DENIED",
+      "UNKNOWN_ERROR",
+      "ZERO_RESULTS",
+      "REQUEST_ERROR"
+  };
+
+  return base::StringPrintf(
+      "dstOffset=%f, rawOffset=%f, timeZoneId='%s', timeZoneName='%s', "
+      "error_message='%s', status=%u (%s)",
+      dstOffset,
+      rawOffset,
+      timeZoneId.c_str(),
+      timeZoneName.c_str(),
+      error_message.c_str(),
+      (unsigned)status,
+      (status < arraysize(status2string) ? status2string[status] : "unknown"));
+};
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/timezone/timezone_request.h b/chrome/browser/chromeos/timezone/timezone_request.h
new file mode 100644
index 0000000..ee46930
--- /dev/null
+++ b/chrome/browser/chromeos/timezone/timezone_request.h
@@ -0,0 +1,126 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_TIMEZONE_TIMEZONE_REQUEST_H_
+#define CHROME_BROWSER_CHROMEOS_TIMEZONE_TIMEZONE_REQUEST_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
+#include "content/public/common/geoposition.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "url/gurl.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+namespace chromeos {
+
+struct TimeZoneResponseData {
+  enum Status {
+    OK,
+    INVALID_REQUEST,
+    OVER_QUERY_LIMIT,
+    REQUEST_DENIED,
+    UNKNOWN_ERROR,
+    ZERO_RESULTS,
+    REQUEST_ERROR  // local problem
+  };
+
+  TimeZoneResponseData();
+
+  std::string ToStringForDebug() const;
+
+  double dstOffset;
+  double rawOffset;
+  std::string timeZoneId;
+  std::string timeZoneName;
+  std::string error_message;
+  Status status;
+};
+
+// Returns default timezone service URL.
+GURL DefaultTimezoneProviderURL();
+
+// Takes Geoposition and sends it to a server to get local timezone information.
+// It performs formatting of the request and interpretation of the response.
+// If error occurs, request is retried until timeout.
+// Zero timeout indicates single request.
+// Request is owned and destroyed by caller (usually TimeZoneProvider).
+// If request is destroyed while callback has not beed called yet, request
+// is silently cancelled.
+class TimeZoneRequest : private net::URLFetcherDelegate {
+ public:
+  // Called when a new geo timezone information is available.
+  // The second argument indicates whether there was a server error or not.
+  // It is true when there was a server or network error - either no response
+  // or a 500 error code.
+  typedef base::Callback<void(scoped_ptr<TimeZoneResponseData> /* timezone */,
+                              bool /* server_error */)>
+      TimeZoneResponseCallback;
+
+  // |url| is the server address to which the request wil be sent.
+  // |geoposition| is the location to query timezone for.
+  // |sensor| if this location was determined using hardware sensor.
+  // |retry_timeout| retry request on error until timeout.
+  TimeZoneRequest(net::URLRequestContextGetter* url_context_getter,
+                  const GURL& service_url,
+                  const content::Geoposition& geoposition,
+                  bool sensor,
+                  base::TimeDelta retry_timeout);
+
+  virtual ~TimeZoneRequest();
+
+  // Initiates request.
+  // Note: if request object is destroyed before callback is called,
+  // request will be silently cancelled.
+  void MakeRequest(TimeZoneResponseCallback callback);
+
+ private:
+  // net::URLFetcherDelegate
+  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
+
+  // Start new request.
+  void StartRequest();
+
+  // Schedules retry.
+  void Retry(bool server_error);
+
+  scoped_refptr<net::URLRequestContextGetter> url_context_getter_;
+  const GURL service_url_;
+  content::Geoposition geoposition_;
+  const bool sensor_;
+
+  TimeZoneResponseCallback callback_;
+
+  GURL request_url_;
+  scoped_ptr<net::URLFetcher> url_fetcher_;
+
+  // When request was actually started.
+  base::Time request_started_at_;
+
+  // Absolute time, when it is passed no more retry requests are allowed.
+  base::Time retry_timeout_abs_;
+
+  // Pending retry.
+  base::OneShotTimer<TimeZoneRequest> timezone_request_scheduled_;
+
+  // Number of retry attempts.
+  unsigned retries_;
+
+  // Creation and destruction should happen on the same thread.
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(TimeZoneRequest);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_TIMEZONE_TIMEZONE_REQUEST_H_
diff --git a/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.cc b/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.cc
index eed66dc..ffb59e0 100644
--- a/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.cc
+++ b/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.cc
@@ -22,10 +22,11 @@
   ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenCaptureStop();
 }
 
-void ScreenCaptureNotificationUIChromeOS::OnStarted(
+gfx::NativeViewId ScreenCaptureNotificationUIChromeOS::OnStarted(
     const base::Closure& stop_callback) {
   ash::Shell::GetInstance()->system_tray_notifier()->NotifyScreenCaptureStart(
       stop_callback, text_);
+  return 0;
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.h b/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.h
index 5c87b2d..4b0a170 100644
--- a/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.h
+++ b/chrome/browser/chromeos/ui/screen_capture_notification_ui_chromeos.h
@@ -18,7 +18,8 @@
   virtual ~ScreenCaptureNotificationUIChromeOS();
 
   // ScreenCaptureNotificationUI overrides.
-  virtual void OnStarted(const base::Closure& stop_callback) OVERRIDE;
+  virtual gfx::NativeViewId OnStarted(const base::Closure& stop_callback)
+      OVERRIDE;
 
  private:
   const base::string16 text_;
diff --git a/chrome/browser/common/OWNERS b/chrome/browser/common/OWNERS
index c892b3b..82e44d8 100644
--- a/chrome/browser/common/OWNERS
+++ b/chrome/browser/common/OWNERS
@@ -1,3 +1 @@
 erikwright@chromium.org
-joi@chromium.org
-kaiwang@chromium.org
diff --git a/chrome/browser/component_updater/DEPS b/chrome/browser/component_updater/DEPS
index 6858ef7..6452369 100644
--- a/chrome/browser/component_updater/DEPS
+++ b/chrome/browser/component_updater/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+courgette",
   "+media/cdm/ppapi/supported_cdm_versions.h",
   "+ppapi/shared_impl/ppapi_permissions.h",
   "+ppapi/thunk",
diff --git a/chrome/browser/component_updater/component_patcher.cc b/chrome/browser/component_updater/component_patcher.cc
index 59f283a..7806430 100644
--- a/chrome/browser/component_updater/component_patcher.cc
+++ b/chrome/browser/component_updater/component_patcher.cc
@@ -7,11 +7,15 @@
 #include <string>
 #include <vector>
 
+#include "base/basictypes.h"
 #include "base/file_util.h"
+#include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
+#include "base/memory/weak_ptr.h"
 #include "base/values.h"
 #include "chrome/browser/component_updater/component_patcher_operation.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
+#include "content/public/browser/browser_thread.h"
 
 namespace component_updater {
 
@@ -34,58 +38,83 @@
 
 }  // namespace
 
-// The patching support is not cross-platform at the moment.
-ComponentPatcherCrossPlatform::ComponentPatcherCrossPlatform() {}
-
-ComponentUnpacker::Error ComponentPatcherCrossPlatform::Patch(
-    PatchType patch_type,
-    const base::FilePath& input_file,
-    const base::FilePath& patch_file,
-    const base::FilePath& output_file,
-    int* error) {
-  return ComponentUnpacker::kDeltaUnsupportedCommand;
-}
-
-
-// Takes the contents of a differential component update in input_dir
-// and produces the contents of a full component update in unpack_dir
-// using input_abs_path_ files that the installer knows about.
-void DifferentialUpdatePatch(
+ComponentPatcher::ComponentPatcher(
     const base::FilePath& input_dir,
     const base::FilePath& unpack_dir,
-    ComponentPatcher* patcher,
     ComponentInstaller* installer,
-    base::Callback<void(ComponentUnpacker::Error, int)> callback) {
-  int error = 0;
-  scoped_ptr<base::ListValue> commands(ReadCommands(input_dir));
-  if (!commands.get()) {
-    callback.Run(ComponentUnpacker::kDeltaBadCommands, error);
+    bool in_process,
+    scoped_refptr<base::SequencedTaskRunner> task_runner)
+    : input_dir_(input_dir),
+      unpack_dir_(unpack_dir),
+      installer_(installer),
+      in_process_(in_process),
+      task_runner_(task_runner) {
+}
+
+ComponentPatcher::~ComponentPatcher() {
+}
+
+void ComponentPatcher::Start(const ComponentUnpacker::Callback& callback) {
+  callback_ = callback;
+  task_runner_->PostTask(FROM_HERE,
+                         base::Bind(&ComponentPatcher::StartPatching,
+                                    scoped_refptr<ComponentPatcher>(this)));
+}
+
+void ComponentPatcher::StartPatching() {
+  commands_.reset(ReadCommands(input_dir_));
+  if (!commands_.get()) {
+    DonePatching(ComponentUnpacker::kDeltaBadCommands, 0);
+  } else {
+    next_command_ = commands_->begin();
+    PatchNextFile();
+  }
+}
+
+void ComponentPatcher::PatchNextFile() {
+  if (next_command_ == commands_->end()) {
+    DonePatching(ComponentUnpacker::kNone, 0);
     return;
   }
-
-  for (base::ValueVector::const_iterator command = commands->begin(),
-      end = commands->end(); command != end; command++) {
-    if (!(*command)->IsType(base::Value::TYPE_DICTIONARY)) {
-      callback.Run(ComponentUnpacker::kDeltaBadCommands, error);
-      return;
-    }
-    base::DictionaryValue* command_args =
-        static_cast<base::DictionaryValue*>(*command);
-    scoped_ptr<DeltaUpdateOp> operation(CreateDeltaUpdateOp(command_args));
-    if (!operation) {
-      callback.Run(ComponentUnpacker::kDeltaUnsupportedCommand, error);
-      return;
-    }
-
-    ComponentUnpacker::Error result = operation->Run(
-        command_args, input_dir, unpack_dir, patcher, installer, &error);
-    if (result != ComponentUnpacker::kNone) {
-      callback.Run(result, error);
-      return;
-    }
+  if (!(*next_command_)->IsType(base::Value::TYPE_DICTIONARY)) {
+    DonePatching(ComponentUnpacker::kDeltaBadCommands, 0);
+    return;
   }
+  const base::DictionaryValue* command_args =
+      static_cast<base::DictionaryValue*>(*next_command_);
+  current_operation_ = CreateDeltaUpdateOp(*command_args);
+  if (!current_operation_) {
+    DonePatching(ComponentUnpacker::kDeltaUnsupportedCommand, 0);
+    return;
+  }
+  current_operation_->Run(
+      command_args,
+      input_dir_,
+      unpack_dir_,
+      installer_,
+      in_process_,
+      base::Bind(&ComponentPatcher::DonePatchingFile,
+                 scoped_refptr<ComponentPatcher>(this)),
+      task_runner_);
+}
 
-  callback.Run(ComponentUnpacker::kNone, error);
+void ComponentPatcher::DonePatchingFile(ComponentUnpacker::Error error,
+                                        int extended_error) {
+  if (error != ComponentUnpacker::kNone) {
+    DonePatching(error, extended_error);
+  } else {
+    ++next_command_;
+    PatchNextFile();
+  }
+}
+
+void ComponentPatcher::DonePatching(ComponentUnpacker::Error error,
+                                    int extended_error) {
+  current_operation_ = NULL;
+  task_runner_->PostTask(FROM_HERE, base::Bind(callback_,
+                                               error,
+                                               extended_error));
+  callback_.Reset();
 }
 
 }  // namespace component_updater
diff --git a/chrome/browser/component_updater/component_patcher.h b/chrome/browser/component_updater/component_patcher.h
index 6a6cb8f..9269967 100644
--- a/chrome/browser/component_updater/component_patcher.h
+++ b/chrome/browser/component_updater/component_patcher.h
@@ -28,9 +28,9 @@
 #ifndef CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_H_
 #define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_H_
 
-#include "base/basictypes.h"
 #include "base/callback_forward.h"
-#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/values.h"
 #include "chrome/browser/component_updater/component_unpacker.h"
 
 namespace base {
@@ -40,52 +40,60 @@
 namespace component_updater {
 
 class ComponentInstaller;
+class DeltaUpdateOp;
 
-// Applies a delta patch to a single file. Specifically, creates a file at
-// |output_file| using |input_file| patched according to the algorithm
-// specified by |patch_type| using |patch_file|. Sets the value of error to
-// the error code of the failing patch operation, if there is such a failure.
-class ComponentPatcher {
- public:
-  // The type of a patch file.
-  enum PatchType {
-    kPatchTypeUnknown,
-    kPatchTypeCourgette,
-    kPatchTypeBsdiff,
-  };
-
-  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
-                                         const base::FilePath& input_file,
-                                         const base::FilePath& patch_file,
-                                         const base::FilePath& output_file,
-                                         int* error) = 0;
-  virtual ~ComponentPatcher() {}
+// The type of a patch file.
+enum PatchType {
+  kPatchTypeUnknown,
+  kPatchTypeCourgette,
+  kPatchTypeBsdiff,
 };
 
-class ComponentPatcherCrossPlatform : public ComponentPatcher {
+// Encapsulates a task for applying a differential update to a component.
+class ComponentPatcher : public base::RefCountedThreadSafe<ComponentPatcher> {
  public:
-  ComponentPatcherCrossPlatform();
-  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
-                                         const base::FilePath& input_file,
-                                         const base::FilePath& patch_file,
-                                         const base::FilePath& output_file,
-                                         int* error) OVERRIDE;
+  // Takes an unpacked differential CRX (|input_dir|) and a component installer,
+  // and sets up the class to create a new (non-differential) unpacked CRX.
+  // If |in_process| is true, patching will be done completely within the
+  // existing process. Otherwise, some steps of patching may be done
+  // out-of-process.
+  ComponentPatcher(const base::FilePath& input_dir,
+                   const base::FilePath& unpack_dir,
+                   ComponentInstaller* installer,
+                   bool in_process,
+                   scoped_refptr<base::SequencedTaskRunner> task_runner);
+
+  // Starts patching files. This member function returns immediately, after
+  // posting a task to do the patching. When patching has been completed,
+  // |callback| will be called with the error codes if any error codes were
+  // encountered.
+  void Start(const ComponentUnpacker::Callback& callback);
+
  private:
-  DISALLOW_COPY_AND_ASSIGN(ComponentPatcherCrossPlatform);
-};
+  friend class base::RefCountedThreadSafe<ComponentPatcher>;
 
-// This function takes an unpacked differential CRX (|input_dir|) and a
-// component installer, and creates a new (non-differential) unpacked CRX, which
-// is then installed normally.
-// The non-differential files are written into the |unpack_dir| directory.
-// When finished, calls the callback, passing error codes if any errors were
-// encountered.
-void DifferentialUpdatePatch(
-    const base::FilePath& input_dir,
-    const base::FilePath& unpack_dir,
-    ComponentPatcher* component_patcher,
-    ComponentInstaller* installer,
-    base::Callback<void(ComponentUnpacker::Error, int)> callback);
+  virtual ~ComponentPatcher();
+
+  void StartPatching();
+
+  void PatchNextFile();
+
+  void DonePatchingFile(ComponentUnpacker::Error error, int extended_error);
+
+  void DonePatching(ComponentUnpacker::Error error, int extended_error);
+
+  const base::FilePath input_dir_;
+  const base::FilePath unpack_dir_;
+  ComponentInstaller* const installer_;
+  const bool in_process_;
+  ComponentUnpacker::Callback callback_;
+  scoped_ptr<base::ListValue> commands_;
+  base::ValueVector::const_iterator next_command_;
+  scoped_refptr<DeltaUpdateOp> current_operation_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(ComponentPatcher);
+};
 
 }  // namespace component_updater
 
diff --git a/chrome/browser/component_updater/component_patcher_operation.cc b/chrome/browser/component_updater/component_patcher_operation.cc
index 6b86d9f..d9fb069 100644
--- a/chrome/browser/component_updater/component_patcher_operation.cc
+++ b/chrome/browser/component_updater/component_patcher_operation.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <vector>
 
+#include "base/bind.h"
 #include "base/file_util.h"
 #include "base/files/memory_mapped_file.h"
 #include "base/json/json_file_value_serializer.h"
@@ -15,11 +16,17 @@
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
+#include "chrome/common/chrome_utility_messages.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/utility_process_host.h"
+#include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
 #include "crypto/secure_hash.h"
 #include "crypto/sha2.h"
 #include "crypto/signature_verifier.h"
 #include "extensions/common/crx_file.h"
+#include "ipc/ipc_message_macros.h"
 #include "third_party/zlib/google/zip.h"
 
 using crypto::SecureHash;
@@ -34,56 +41,165 @@
 const char kPatch[] = "patch";
 const char kSha256[] = "sha256";
 
+// The integer offset disambiguates between overlapping error ranges.
+const int kCourgetteErrorOffset = 300;
+const int kBsdiffErrorOffset = 600;
+
+class CourgetteTraits : public DeltaUpdateOpPatchStrategy {
+ public:
+  virtual int GetErrorOffset() const OVERRIDE;
+  virtual int GetSuccessCode() const OVERRIDE;
+  virtual scoped_ptr<IPC::Message> GetPatchMessage(
+      base::FilePath input_abs_path,
+      base::FilePath patch_abs_path,
+      base::FilePath output_abs_path) OVERRIDE;
+  virtual int Patch(base::FilePath input_abs_path,
+                    base::FilePath patch_abs_path,
+                    base::FilePath output_abs_path) OVERRIDE;
+};
+
+int CourgetteTraits::GetErrorOffset() const {
+  return kCourgetteErrorOffset;
+}
+
+int CourgetteTraits::GetSuccessCode() const {
+  return courgette::C_OK;
+}
+
+scoped_ptr<IPC::Message> CourgetteTraits::GetPatchMessage(
+    base::FilePath input_abs_path,
+    base::FilePath patch_abs_path,
+    base::FilePath output_abs_path) {
+  return scoped_ptr<IPC::Message>(
+      new ChromeUtilityMsg_PatchFileCourgette(input_abs_path,
+                                              patch_abs_path,
+                                              output_abs_path));
+}
+
+int CourgetteTraits::Patch(base::FilePath input_abs_path,
+                           base::FilePath patch_abs_path,
+                           base::FilePath output_abs_path) {
+  return courgette::ApplyEnsemblePatch(input_abs_path.value().c_str(),
+                                       patch_abs_path.value().c_str(),
+                                       output_abs_path.value().c_str());
+}
+
+class BsdiffTraits : public DeltaUpdateOpPatchStrategy {
+ public:
+  virtual int GetErrorOffset() const OVERRIDE;
+  virtual int GetSuccessCode() const OVERRIDE;
+  virtual scoped_ptr<IPC::Message> GetPatchMessage(
+      base::FilePath input_abs_path,
+      base::FilePath patch_abs_path,
+      base::FilePath output_abs_path) OVERRIDE;
+  virtual int Patch(base::FilePath input_abs_path,
+                    base::FilePath patch_abs_path,
+                    base::FilePath output_abs_path) OVERRIDE;
+};
+
+int BsdiffTraits::GetErrorOffset() const {
+  return kBsdiffErrorOffset;
+}
+
+int BsdiffTraits::GetSuccessCode() const {
+  return courgette::OK;
+}
+
+scoped_ptr<IPC::Message> BsdiffTraits::GetPatchMessage(
+    base::FilePath input_abs_path,
+    base::FilePath patch_abs_path,
+    base::FilePath output_abs_path) {
+  return scoped_ptr<IPC::Message>(
+      new ChromeUtilityMsg_PatchFileBsdiff(input_abs_path,
+                                           patch_abs_path,
+                                           output_abs_path));
+}
+
+int BsdiffTraits::Patch(base::FilePath input_abs_path,
+                        base::FilePath patch_abs_path,
+                        base::FilePath output_abs_path) {
+  return courgette::ApplyBinaryPatch(input_abs_path,
+                                     patch_abs_path,
+                                     output_abs_path);
+}
+
 }  // namespace
 
-DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command) {
-  std::string operation;
-  if (!command->GetString(kOp, &operation))
-    return NULL;
-  if (operation == "copy")
+DeltaUpdateOpPatchStrategy::~DeltaUpdateOpPatchStrategy() {
+}
+
+DeltaUpdateOp* CreateDeltaUpdateOp(const std::string& operation) {
+  if (operation == "copy") {
     return new DeltaUpdateOpCopy();
-  else if (operation == "create")
+  } else if (operation == "create") {
     return new DeltaUpdateOpCreate();
-  else if (operation == "bsdiff")
-    return new DeltaUpdateOpPatchBsdiff();
-  else if (operation == "courgette")
-    return new DeltaUpdateOpPatchCourgette();
+  } else if (operation == "bsdiff") {
+    scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new BsdiffTraits());
+    return new DeltaUpdateOpPatch(strategy.Pass());
+  } else if (operation == "courgette") {
+    scoped_ptr<DeltaUpdateOpPatchStrategy> strategy(new CourgetteTraits());
+    return new DeltaUpdateOpPatch(strategy.Pass());
+  }
   return NULL;
 }
 
-DeltaUpdateOp::DeltaUpdateOp() {}
+DeltaUpdateOp* CreateDeltaUpdateOp(const base::DictionaryValue& command) {
+  std::string operation;
+  if (!command.GetString(kOp, &operation))
+    return NULL;
+  return CreateDeltaUpdateOp(operation);
+}
+
+DeltaUpdateOp::DeltaUpdateOp() : in_process_(false) {}
 
 DeltaUpdateOp::~DeltaUpdateOp() {}
 
-ComponentUnpacker::Error DeltaUpdateOp::Run(base::DictionaryValue* command_args,
-                                            const base::FilePath& input_dir,
-                                            const base::FilePath& unpack_dir,
-                                            ComponentPatcher* patcher,
-                                            ComponentInstaller* installer,
-                                            int* error) {
+void DeltaUpdateOp::Run(
+    const base::DictionaryValue* command_args,
+    const base::FilePath& input_dir,
+    const base::FilePath& unpack_dir,
+    ComponentInstaller* installer,
+    bool in_process,
+    const ComponentUnpacker::Callback& callback,
+    scoped_refptr<base::SequencedTaskRunner> task_runner) {
+  callback_ = callback;
+  in_process_ = in_process;
+  task_runner_ = task_runner;
   std::string output_rel_path;
   if (!command_args->GetString(kOutput, &output_rel_path) ||
-      !command_args->GetString(kSha256, &output_sha256_))
-    return ComponentUnpacker::kDeltaBadCommands;
+      !command_args->GetString(kSha256, &output_sha256_)) {
+    DoneRunning(ComponentUnpacker::kDeltaBadCommands, 0);
+    return;
+  }
 
   output_abs_path_ = unpack_dir.Append(
       base::FilePath::FromUTF8Unsafe(output_rel_path));
   ComponentUnpacker::Error parse_result = DoParseArguments(
       command_args, input_dir, installer);
-  if (parse_result != ComponentUnpacker::kNone)
-    return parse_result;
+  if (parse_result != ComponentUnpacker::kNone) {
+    DoneRunning(parse_result, 0);
+    return;
+  }
 
   const base::FilePath parent = output_abs_path_.DirName();
   if (!base::DirectoryExists(parent)) {
-    if (!base::CreateDirectory(parent))
-      return ComponentUnpacker::kIoError;
+    if (!base::CreateDirectory(parent)) {
+      DoneRunning(ComponentUnpacker::kIoError, 0);
+      return;
+    }
   }
 
-  ComponentUnpacker::Error run_result = DoRun(patcher, error);
-  if (run_result != ComponentUnpacker::kNone)
-    return run_result;
+  DoRun(base::Bind(&DeltaUpdateOp::DoneRunning,
+                   scoped_refptr<DeltaUpdateOp>(this)));
+}
 
-  return CheckHash();
+void DeltaUpdateOp::DoneRunning(ComponentUnpacker::Error error,
+                                int extended_error) {
+  if (error == ComponentUnpacker::kNone)
+    error = CheckHash();
+  task_runner_->PostTask(FROM_HERE,
+                         base::Bind(callback_, error, extended_error));
+  callback_.Reset();
 }
 
 // Uses the hash as a checksum to confirm that the file now residing in the
@@ -108,10 +224,16 @@
   return ComponentUnpacker::kNone;
 }
 
+bool DeltaUpdateOp::InProcess() {
+  return in_process_;
+}
+
 DeltaUpdateOpCopy::DeltaUpdateOpCopy() {}
 
+DeltaUpdateOpCopy::~DeltaUpdateOpCopy() {}
+
 ComponentUnpacker::Error DeltaUpdateOpCopy::DoParseArguments(
-    base::DictionaryValue* command_args,
+    const base::DictionaryValue* command_args,
     const base::FilePath& input_dir,
     ComponentInstaller* installer) {
   std::string input_rel_path;
@@ -124,19 +246,19 @@
   return ComponentUnpacker::kNone;
 }
 
-ComponentUnpacker::Error DeltaUpdateOpCopy::DoRun(ComponentPatcher*,
-                                                  int* error) {
-  *error = 0;
+void DeltaUpdateOpCopy::DoRun(const ComponentUnpacker::Callback& callback) {
   if (!base::CopyFile(input_abs_path_, output_abs_path_))
-    return ComponentUnpacker::kDeltaOperationFailure;
-
-  return ComponentUnpacker::kNone;
+    callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
+  else
+    callback.Run(ComponentUnpacker::kNone, 0);
 }
 
 DeltaUpdateOpCreate::DeltaUpdateOpCreate() {}
 
+DeltaUpdateOpCreate::~DeltaUpdateOpCreate() {}
+
 ComponentUnpacker::Error DeltaUpdateOpCreate::DoParseArguments(
-    base::DictionaryValue* command_args,
+    const base::DictionaryValue* command_args,
     const base::FilePath& input_dir,
     ComponentInstaller* installer) {
   std::string patch_rel_path;
@@ -149,19 +271,67 @@
   return ComponentUnpacker::kNone;
 }
 
-ComponentUnpacker::Error DeltaUpdateOpCreate::DoRun(ComponentPatcher*,
-                                                    int* error) {
-  *error = 0;
+void DeltaUpdateOpCreate::DoRun(const ComponentUnpacker::Callback& callback) {
   if (!base::Move(patch_abs_path_, output_abs_path_))
-    return ComponentUnpacker::kDeltaOperationFailure;
-
-  return ComponentUnpacker::kNone;
+    callback.Run(ComponentUnpacker::kDeltaOperationFailure, 0);
+  else
+    callback.Run(ComponentUnpacker::kNone, 0);
 }
 
-DeltaUpdateOpPatchBsdiff::DeltaUpdateOpPatchBsdiff() {}
+DeltaUpdateOpPatchHost::DeltaUpdateOpPatchHost(
+    scoped_refptr<DeltaUpdateOpPatch> patcher) : patcher_(patcher) {
+}
 
-ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoParseArguments(
-    base::DictionaryValue* command_args,
+DeltaUpdateOpPatchHost::~DeltaUpdateOpPatchHost() {
+}
+
+void DeltaUpdateOpPatchHost::StartProcess(scoped_ptr<IPC::Message> message) {
+  // The DeltaUpdateOpPatchHost is not responsible for deleting the
+  // UtilityProcessHost object.
+  content::UtilityProcessHost* host = content::UtilityProcessHost::Create(
+      this, base::MessageLoopProxy::current().get());
+  host->DisableSandbox();
+  host->Send(message.release());
+}
+
+bool DeltaUpdateOpPatchHost::OnMessageReceived(const IPC::Message& message) {
+  bool handled = true;
+  IPC_BEGIN_MESSAGE_MAP(DeltaUpdateOpPatchHost, message)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PatchFile_Succeeded,
+                        OnPatchSucceeded)
+    IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PatchFile_Failed,
+                        OnPatchFailed)
+    IPC_MESSAGE_UNHANDLED(handled = false)
+  IPC_END_MESSAGE_MAP()
+  return handled;
+}
+
+void DeltaUpdateOpPatchHost::OnPatchSucceeded() {
+  patcher_->DonePatching(ComponentUnpacker::kNone, 0);
+  patcher_ = NULL;
+}
+
+void DeltaUpdateOpPatchHost::OnPatchFailed(int error_code) {
+  patcher_->DonePatching(ComponentUnpacker::kDeltaOperationFailure, error_code);
+  patcher_ = NULL;
+}
+
+void DeltaUpdateOpPatchHost::OnProcessCrashed(int exit_code) {
+  patcher_->DonePatching(ComponentUnpacker::kDeltaPatchProcessFailure,
+                        exit_code);
+  patcher_ = NULL;
+}
+
+DeltaUpdateOpPatch::DeltaUpdateOpPatch(
+    scoped_ptr<DeltaUpdateOpPatchStrategy> strategy) {
+  strategy_ = strategy.Pass();
+}
+
+DeltaUpdateOpPatch::~DeltaUpdateOpPatch() {
+}
+
+ComponentUnpacker::Error DeltaUpdateOpPatch::DoParseArguments(
+    const base::DictionaryValue* command_args,
     const base::FilePath& input_dir,
     ComponentInstaller* installer) {
   std::string patch_rel_path;
@@ -179,47 +349,39 @@
   return ComponentUnpacker::kNone;
 }
 
-ComponentUnpacker::Error DeltaUpdateOpPatchBsdiff::DoRun(
-    ComponentPatcher* patcher,
-    int* error) {
-  *error = 0;
-  return patcher->Patch(ComponentPatcher::kPatchTypeBsdiff,
-                        input_abs_path_,
-                        patch_abs_path_,
-                        output_abs_path_,
-                        error);
+void DeltaUpdateOpPatch::DoRun(const ComponentUnpacker::Callback& callback) {
+  callback_ = callback;
+  if (!InProcess()) {
+    host_ = new DeltaUpdateOpPatchHost(scoped_refptr<DeltaUpdateOpPatch>(this));
+    content::BrowserThread::PostTask(
+        content::BrowserThread::IO,
+        FROM_HERE,
+        base::Bind(&DeltaUpdateOpPatchHost::StartProcess,
+                   host_,
+                   base::Passed(strategy_->GetPatchMessage(input_abs_path_,
+                                                           patch_abs_path_,
+                                                           output_abs_path_))));
+    return;
+  }
+  const int result = strategy_->Patch(input_abs_path_,
+                                      patch_abs_path_,
+                                      output_abs_path_);
+  if (result == strategy_->GetSuccessCode())
+    DonePatching(ComponentUnpacker::kNone, 0);
+  else
+    DonePatching(ComponentUnpacker::kDeltaOperationFailure, result);
 }
 
-DeltaUpdateOpPatchCourgette::DeltaUpdateOpPatchCourgette() {}
-
-ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoParseArguments(
-    base::DictionaryValue* command_args,
-    const base::FilePath& input_dir,
-    ComponentInstaller* installer) {
-  std::string patch_rel_path;
-  std::string input_rel_path;
-  if (!command_args->GetString(kPatch, &patch_rel_path) ||
-      !command_args->GetString(kInput, &input_rel_path))
-    return ComponentUnpacker::kDeltaBadCommands;
-
-  if (!installer->GetInstalledFile(input_rel_path, &input_abs_path_))
-    return ComponentUnpacker::kDeltaMissingExistingFile;
-
-  patch_abs_path_ = input_dir.Append(
-      base::FilePath::FromUTF8Unsafe(patch_rel_path));
-
-  return ComponentUnpacker::kNone;
-}
-
-ComponentUnpacker::Error DeltaUpdateOpPatchCourgette::DoRun(
-    ComponentPatcher* patcher,
-    int* error) {
-  *error = 0;
-  return patcher->Patch(ComponentPatcher::kPatchTypeCourgette,
-                        input_abs_path_,
-                        patch_abs_path_,
-                        output_abs_path_,
-                        error);
+void DeltaUpdateOpPatch::DonePatching(ComponentUnpacker::Error error,
+                                      int error_code) {
+  host_ = NULL;
+  if (error != ComponentUnpacker::kNone) {
+    error_code += strategy_->GetErrorOffset();
+  }
+  callback_.Run(error, error_code);
+  // The callback is no longer needed - it is best to release it in case it
+  // contains a reference to this object.
+  callback_.Reset();
 }
 
 }  // namespace component_updater
diff --git a/chrome/browser/component_updater/component_patcher_operation.h b/chrome/browser/component_updater/component_patcher_operation.h
index c9bc0b1..91c3a16 100644
--- a/chrome/browser/component_updater/component_patcher_operation.h
+++ b/chrome/browser/component_updater/component_patcher_operation.h
@@ -6,10 +6,15 @@
 #define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_OPERATION_H_
 
 #include <string>
+
 #include "base/basictypes.h"
+#include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/browser/component_updater/component_unpacker.h"
+#include "content/public/browser/utility_process_host_client.h"
 
 namespace base {
 class DictionaryValue;
@@ -18,44 +23,56 @@
 namespace component_updater {
 
 class ComponentInstaller;
-class ComponentPatcher;
 
-class DeltaUpdateOp {
+class DeltaUpdateOp : public base::RefCountedThreadSafe<DeltaUpdateOp> {
  public:
-
   DeltaUpdateOp();
-  virtual ~DeltaUpdateOp();
 
-  // Parses, runs, and verifies the operation, returning an error code if an
-  // error is encountered, and DELTA_OK otherwise. In case of errors,
-  // extended error information can be returned in the |error| parameter.
-  ComponentUnpacker::Error Run(base::DictionaryValue* command_args,
-                               const base::FilePath& input_dir,
-                               const base::FilePath& unpack_dir,
-                               ComponentPatcher* patcher,
-                               ComponentInstaller* installer,
-                               int* error);
+  // Parses, runs, and verifies the operation. Calls |callback| with the
+  // result of the operation. The callback is called using |task_runner|.
+  void Run(const base::DictionaryValue* command_args,
+           const base::FilePath& input_dir,
+           const base::FilePath& unpack_dir,
+           ComponentInstaller* installer,
+           bool in_process,
+           const ComponentUnpacker::Callback& callback,
+           scoped_refptr<base::SequencedTaskRunner> task_runner);
 
  protected:
+  virtual ~DeltaUpdateOp();
+
+  bool InProcess();
+
   std::string output_sha256_;
   base::FilePath output_abs_path_;
 
  private:
+  friend class base::RefCountedThreadSafe<DeltaUpdateOp>;
+
+
   ComponentUnpacker::Error CheckHash();
 
   // Subclasses must override DoParseArguments to parse operation-specific
   // arguments. DoParseArguments returns DELTA_OK on success; any other code
   // represents failure.
   virtual ComponentUnpacker::Error DoParseArguments(
-      base::DictionaryValue* command_args,
+      const base::DictionaryValue* command_args,
       const base::FilePath& input_dir,
       ComponentInstaller* installer) = 0;
 
   // Subclasses must override DoRun to actually perform the patching operation.
-  // DoRun returns DELTA_OK on success; any other code represents failure.
-  // Additional error information can be returned in the |error| parameter.
-  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
-                                         int* error) = 0;
+  // They must call the provided callback when they have completed their
+  // operations. In practice, the provided callback is always for "DoneRunning".
+  virtual void DoRun(const ComponentUnpacker::Callback& callback) = 0;
+
+  // Callback given to subclasses for when they complete their operation.
+  // Validates the output, and posts a task to the patching operation's
+  // callback.
+  void DoneRunning(ComponentUnpacker::Error error, int extended_error);
+
+  bool in_process_;
+  ComponentUnpacker::Callback callback_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOp);
 };
@@ -68,14 +85,15 @@
   DeltaUpdateOpCopy();
 
  private:
+  virtual ~DeltaUpdateOpCopy();
+
   // Overrides of DeltaUpdateOp.
   virtual ComponentUnpacker::Error DoParseArguments(
-      base::DictionaryValue* command_args,
+      const base::DictionaryValue* command_args,
       const base::FilePath& input_dir,
       ComponentInstaller* installer) OVERRIDE;
 
-  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
-                                         int* error) OVERRIDE;
+  virtual void DoRun(const ComponentUnpacker::Callback& callback) OVERRIDE;
 
   base::FilePath input_abs_path_;
 
@@ -91,68 +109,101 @@
   DeltaUpdateOpCreate();
 
  private:
+  virtual ~DeltaUpdateOpCreate();
+
   // Overrides of DeltaUpdateOp.
   virtual ComponentUnpacker::Error DoParseArguments(
-      base::DictionaryValue* command_args,
+      const base::DictionaryValue* command_args,
       const base::FilePath& input_dir,
       ComponentInstaller* installer) OVERRIDE;
 
-  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
-                                         int* error) OVERRIDE;
+  virtual void DoRun(const ComponentUnpacker::Callback& callback) OVERRIDE;
 
   base::FilePath patch_abs_path_;
 
   DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpCreate);
 };
 
-// A 'bsdiff' operation takes an existing file on disk, and a bsdiff-
-// format patch file provided in the delta update package, and runs bsdiff
-// to construct an output file in the unpacking directory.
-class DeltaUpdateOpPatchBsdiff : public DeltaUpdateOp {
+class DeltaUpdateOpPatchStrategy {
  public:
-  DeltaUpdateOpPatchBsdiff();
+  virtual ~DeltaUpdateOpPatchStrategy();
+
+  // Returns an integer to add to error codes to disambiguate their source.
+  virtual int GetErrorOffset() const = 0;
+
+  // Returns the "error code" that is expected in the successful install case.
+  virtual int GetSuccessCode() const = 0;
+
+  // Returns an IPC message that will start patching if it is sent to a
+  // UtilityProcessClient.
+  virtual scoped_ptr<IPC::Message> GetPatchMessage(
+      base::FilePath input_abs_path,
+      base::FilePath patch_abs_path,
+      base::FilePath output_abs_path) = 0;
+
+  // Does the actual patching operation, and returns an error code.
+  virtual int Patch(base::FilePath input_abs_path,
+                    base::FilePath patch_abs_path,
+                    base::FilePath output_abs_path) = 0;
+};
+
+class DeltaUpdateOpPatch;
+
+class DeltaUpdateOpPatchHost : public content::UtilityProcessHostClient {
+ public:
+  explicit DeltaUpdateOpPatchHost(scoped_refptr<DeltaUpdateOpPatch> patcher);
+
+  void StartProcess(scoped_ptr<IPC::Message> message);
 
  private:
+  virtual ~DeltaUpdateOpPatchHost();
+
+  void OnPatchSucceeded();
+
+  void OnPatchFailed(int error_code);
+
+  // Overrides of content::UtilityProcessHostClient.
+  virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+
+  virtual void OnProcessCrashed(int exit_code) OVERRIDE;
+
+  scoped_refptr<DeltaUpdateOpPatch> patcher_;
+};
+
+// Both 'bsdiff' and 'courgette' operations take an existing file on disk,
+// and a bsdiff- or Courgette-format patch file provided in the delta update
+// package, and run bsdiff or Courgette to construct an output file in the
+// unpacking directory.
+class DeltaUpdateOpPatch : public DeltaUpdateOp {
+ public:
+  explicit DeltaUpdateOpPatch(scoped_ptr<DeltaUpdateOpPatchStrategy> strategy);
+
+  void DonePatching(ComponentUnpacker::Error error, int error_code);
+
+ private:
+  virtual ~DeltaUpdateOpPatch();
+
   // Overrides of DeltaUpdateOp.
   virtual ComponentUnpacker::Error DoParseArguments(
-      base::DictionaryValue* command_args,
+      const base::DictionaryValue* command_args,
       const base::FilePath& input_dir,
       ComponentInstaller* installer) OVERRIDE;
 
-  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
-                                         int* error) OVERRIDE;
+  virtual void DoRun(const ComponentUnpacker::Callback& callback) OVERRIDE;
 
+  ComponentUnpacker::Callback callback_;
   base::FilePath patch_abs_path_;
   base::FilePath input_abs_path_;
+  scoped_ptr<DeltaUpdateOpPatchStrategy> strategy_;
+  scoped_refptr<DeltaUpdateOpPatchHost> host_;
 
-  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpPatchBsdiff);
+  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpPatch);
 };
 
-// A 'courgette' operation takes an existing file on disk, and a Courgette-
-// format patch file provided in the delta update package, and runs Courgette
-// to construct an output file in the unpacking directory.
-class DeltaUpdateOpPatchCourgette : public DeltaUpdateOp {
- public:
-  DeltaUpdateOpPatchCourgette();
+// Factory functions to create DeltaUpdateOp instances.
+DeltaUpdateOp* CreateDeltaUpdateOp(const base::DictionaryValue& command);
 
- private:
-  // Overrides of DeltaUpdateOp.
-  virtual ComponentUnpacker::Error DoParseArguments(
-      base::DictionaryValue* command_args,
-      const base::FilePath& input_dir,
-      ComponentInstaller* installer) OVERRIDE;
-
-  virtual ComponentUnpacker::Error DoRun(ComponentPatcher* patcher,
-                                         int* error) OVERRIDE;
-
-  base::FilePath patch_abs_path_;
-  base::FilePath input_abs_path_;
-
-  DISALLOW_COPY_AND_ASSIGN(DeltaUpdateOpPatchCourgette);
-};
-
-// Factory function to create DeltaUpdateOp instances.
-DeltaUpdateOp* CreateDeltaUpdateOp(base::DictionaryValue* command);
+DeltaUpdateOp* CreateDeltaUpdateOp(const std::string& operation);
 
 }  // namespace component_updater
 
diff --git a/chrome/browser/component_updater/component_patcher_win.cc b/chrome/browser/component_updater/component_patcher_win.cc
deleted file mode 100644
index 8935f42..0000000
--- a/chrome/browser/component_updater/component_patcher_win.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/component_updater/component_patcher_win.h"
-
-#include <string>
-
-#include "base/base_paths.h"
-#include "base/command_line.h"
-#include "base/file_util.h"
-#include "base/path_service.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/scoped_handle.h"
-#include "chrome/installer/util/util_constants.h"
-
-namespace component_updater {
-
-namespace {
-
-std::string PatchTypeToCommandLineSwitch(
-    ComponentPatcher::PatchType patch_type) {
-  if (patch_type == ComponentPatcher::kPatchTypeCourgette)
-    return std::string(installer::kCourgette);
-  else if (patch_type == ComponentPatcher::kPatchTypeBsdiff)
-    return std::string(installer::kBsdiff);
-  else
-    return std::string();
-}
-
-// Finds the path to the setup.exe. First, it looks for the program in the
-// "installer" directory. If the program is not found there, it tries to find it
-// in the directory where chrome.dll lives. Returns the path to the setup.exe,
-// if the path exists, otherwise it returns an an empty path.
-base::FilePath FindSetupProgram() {
-  base::FilePath exe_dir;
-  if (!PathService::Get(base::DIR_MODULE, &exe_dir))
-    return base::FilePath();
-
-  const std::string installer_dir(base::UTF16ToASCII(installer::kInstallerDir));
-  const std::string setup_exe(base::UTF16ToASCII(installer::kSetupExe));
-
-  base::FilePath setup_path = exe_dir;
-  setup_path = setup_path.AppendASCII(installer_dir);
-  setup_path = setup_path.AppendASCII(setup_exe);
-  if (base::PathExists(setup_path))
-    return setup_path;
-
-  setup_path = exe_dir;
-  setup_path = setup_path.AppendASCII(setup_exe);
-  if (base::PathExists(setup_path))
-    return setup_path;
-
-  return base::FilePath();
-}
-
-}  // namespace
-
-// Applies the patch to the input file. Returns kNone if the patch was
-// successfully applied, kDeltaOperationFailure if the patch operation
-// encountered errors, and kDeltaPatchProcessFailure if there was an error
-// when running the patch code out of process. In the error case, detailed error
-// information could be returned in the error parameter.
-ComponentUnpacker::Error ComponentPatcherWin::Patch(
-    PatchType patch_type,
-    const base::FilePath& input_file,
-    const base::FilePath& patch_file,
-    const base::FilePath& output_file,
-    int* error) {
-  *error = 0;
-
-  const base::FilePath exe_path = FindSetupProgram();
-  if (exe_path.empty())
-    return ComponentUnpacker::kDeltaPatchProcessFailure;
-
-  const std::string patch_type_str(PatchTypeToCommandLineSwitch(patch_type));
-
-  CommandLine cl(CommandLine::NO_PROGRAM);
-  cl.AppendSwitchASCII(installer::switches::kPatch, patch_type_str.c_str());
-  cl.AppendSwitchPath(installer::switches::kInputFile, input_file);
-  cl.AppendSwitchPath(installer::switches::kPatchFile, patch_file);
-  cl.AppendSwitchPath(installer::switches::kOutputFile, output_file);
-
-  // Create the child process in a job object. The job object prevents leaving
-  // child processes around when the parent process exits, either gracefully or
-  // accidentally.
-  base::win::ScopedHandle job(CreateJobObject(NULL, NULL));
-  if (!job ||
-      !base::SetJobObjectLimitFlags(job, JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE)) {
-    *error = GetLastError();
-    return ComponentUnpacker::kDeltaPatchProcessFailure;
-  }
-
-  base::LaunchOptions launch_options;
-  launch_options.wait = true;
-  launch_options.job_handle = job;
-  launch_options.start_hidden = true;
-  CommandLine setup_path(exe_path);
-  setup_path.AppendArguments(cl, false);
-
-  // |ph| is closed by WaitForExitCode.
-  base::ProcessHandle ph = base::kNullProcessHandle;
-  int exit_code = 0;
-  if (!base::LaunchProcess(setup_path, launch_options, &ph) ||
-      !base::WaitForExitCode(ph, &exit_code)) {
-    *error = GetLastError();
-    return ComponentUnpacker::kDeltaPatchProcessFailure;
-  }
-
-  *error = exit_code;
-  return *error ? ComponentUnpacker::kDeltaOperationFailure :
-                  ComponentUnpacker::kNone;
-}
-
-}  // namespace component_updater
diff --git a/chrome/browser/component_updater/component_patcher_win.h b/chrome/browser/component_updater/component_patcher_win.h
deleted file mode 100644
index b50aa89..0000000
--- a/chrome/browser/component_updater/component_patcher_win.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_WIN_H_
-#define CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_WIN_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/component_updater/component_patcher.h"
-
-namespace component_updater {
-
-class ComponentPatcherWin : public ComponentPatcher {
- public:
-  ComponentPatcherWin() {}
-  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
-                                         const base::FilePath& input_file,
-                                         const base::FilePath& patch_file,
-                                         const base::FilePath& output_file,
-                                         int* error) OVERRIDE;
- private:
-  DISALLOW_COPY_AND_ASSIGN(ComponentPatcherWin);
-};
-
-}  // namespace component_updater
-
-#endif  // CHROME_BROWSER_COMPONENT_UPDATER_COMPONENT_PATCHER_WIN_H_
diff --git a/chrome/browser/component_updater/component_unpacker.cc b/chrome/browser/component_updater/component_unpacker.cc
index 4134b3e..f179262 100644
--- a/chrome/browser/component_updater/component_unpacker.cc
+++ b/chrome/browser/component_updater/component_unpacker.cc
@@ -98,18 +98,17 @@
     const std::vector<uint8>& pk_hash,
     const base::FilePath& path,
     const std::string& fingerprint,
-    ComponentPatcher* patcher,
     ComponentInstaller* installer,
+    bool in_process,
     scoped_refptr<base::SequencedTaskRunner> task_runner)
     : pk_hash_(pk_hash),
       path_(path),
       is_delta_(false),
       fingerprint_(fingerprint),
-      patcher_(patcher),
       installer_(installer),
+      in_process_(in_process),
       error_(kNone),
       extended_error_(0),
-      ptr_factory_(this),
       task_runner_(task_runner) {
 }
 
@@ -137,8 +136,7 @@
   return Verify() && Unzip() && BeginPatching();
 }
 
-void ComponentUnpacker::Unpack(
-    const base::Callback<void(Error, int)>& callback) {
+void ComponentUnpacker::Unpack(const Callback& callback) {
   callback_ = callback;
   if (!UnpackInternal())
     Finish();
@@ -202,20 +200,23 @@
       error_ = kUnzipPathError;
       return false;
     }
+    patcher_ = new ComponentPatcher(unpack_diff_path_,
+                                    unpack_path_,
+                                    installer_,
+                                    in_process_,
+                                    task_runner_);
     task_runner_->PostTask(
-        FROM_HERE, base::Bind(&DifferentialUpdatePatch,
-                              unpack_diff_path_,
-                              unpack_path_,
-                              patcher_,
-                              installer_,
-                              base::Bind(&ComponentUnpacker::EndPatching,
-                                         GetWeakPtr())));
+        FROM_HERE,
+        base::Bind(&ComponentPatcher::Start,
+                   patcher_,
+                   base::Bind(&ComponentUnpacker::EndPatching,
+                              scoped_refptr<ComponentUnpacker>(this))));
   } else {
-    task_runner_->PostTask(
-        FROM_HERE, base::Bind(&ComponentUnpacker::EndPatching,
-                              GetWeakPtr(),
-                              kNone,
-                              0));
+    task_runner_->PostTask(FROM_HERE,
+                           base::Bind(&ComponentUnpacker::EndPatching,
+                                      scoped_refptr<ComponentUnpacker>(this),
+                                      kNone,
+                                      0));
   }
   return true;
 }
@@ -223,6 +224,7 @@
 void ComponentUnpacker::EndPatching(Error error, int extended_error) {
   error_ = error;
   extended_error_ = extended_error;
+  patcher_ = NULL;
   if (error_ != kNone) {
     Finish();
     return;
@@ -267,10 +269,6 @@
   callback_.Run(error_, extended_error_);
 }
 
-base::WeakPtr<ComponentUnpacker> ComponentUnpacker::GetWeakPtr() {
-  return ptr_factory_.GetWeakPtr();
-}
-
 ComponentUnpacker::~ComponentUnpacker() {
 }
 
diff --git a/chrome/browser/component_updater/component_unpacker.h b/chrome/browser/component_updater/component_unpacker.h
index ce72280..ffd69dd 100644
--- a/chrome/browser/component_updater/component_unpacker.h
+++ b/chrome/browser/component_updater/component_unpacker.h
@@ -12,8 +12,8 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/json/json_file_value_serializer.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
 #include "base/sequenced_task_runner.h"
 
 namespace component_updater {
@@ -63,7 +63,7 @@
 //
 // In both cases, if there is an error at any point, the remaining steps will
 // be skipped and Finish will be called.
-class ComponentUnpacker {
+class ComponentUnpacker : public base::RefCountedThreadSafe<ComponentUnpacker> {
  public:
   // Possible error conditions.
   // Add only to the bottom of this enum; the order must be kept stable.
@@ -88,24 +88,27 @@
     kFingerprintWriteFailed,
   };
 
+  typedef base::Callback<void(Error, int)> Callback;
+
   // Constructs an unpacker for a specific component unpacking operation.
   // |pk_hash| is the expected/ public key SHA256 hash. |path| is the current
   // location of the CRX.
   ComponentUnpacker(const std::vector<uint8>& pk_hash,
                     const base::FilePath& path,
                     const std::string& fingerprint,
-                    ComponentPatcher* patcher,
                     ComponentInstaller* installer,
+                    bool in_process,
                     scoped_refptr<base::SequencedTaskRunner> task_runner);
 
-  virtual ~ComponentUnpacker();
-
   // Begins the actual unpacking of the files. May invoke a patcher if the
   // package is a differential update. Calls |callback| with the result.
-  void Unpack(
-      const base::Callback<void(Error, int)>& callback);
+  void Unpack(const Callback& callback);
 
  private:
+  friend class base::RefCountedThreadSafe<ComponentUnpacker>;
+
+  virtual ~ComponentUnpacker();
+
   bool UnpackInternal();
 
   // The first step of unpacking is to verify the file. Returns false if an
@@ -135,21 +138,18 @@
   // Finish is responsible for calling the callback provided in Start().
   void Finish();
 
-  // Returns a weak pointer to this object.
-  base::WeakPtr<ComponentUnpacker> GetWeakPtr();
-
   std::vector<uint8> pk_hash_;
   base::FilePath path_;
   base::FilePath unpack_path_;
   base::FilePath unpack_diff_path_;
   bool is_delta_;
   std::string fingerprint_;
-  ComponentPatcher* patcher_;
+  scoped_refptr<ComponentPatcher> patcher_;
   ComponentInstaller* installer_;
-  base::Callback<void(Error, int)> callback_;
+  Callback callback_;
+  const bool in_process_;
   Error error_;
   int extended_error_;
-  base::WeakPtrFactory<ComponentUnpacker> ptr_factory_;
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   DISALLOW_COPY_AND_ASSIGN(ComponentUnpacker);
diff --git a/chrome/browser/component_updater/component_updater_configurator.cc b/chrome/browser/component_updater/component_updater_configurator.cc
index 87046bf..65b1f85 100644
--- a/chrome/browser/component_updater/component_updater_configurator.cc
+++ b/chrome/browser/component_updater/component_updater_configurator.cc
@@ -17,10 +17,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "net/url_request/url_request_context_getter.h"
 
-#if defined(OS_WIN)
-#include "chrome/browser/component_updater/component_patcher_win.h"
-#endif
-
 namespace component_updater {
 
 namespace {
@@ -53,9 +49,10 @@
 // The url to send the pings to.
 const char kPingUrl[] = "http:" COMPONENT_UPDATER_SERVICE_ENDPOINT;
 
-#if defined(OS_WIN)
 // Disables differential updates.
 const char kSwitchDisableDeltaUpdates[] = "disable-delta-updates";
+
+#if defined(OS_WIN)
 // Disables background downloads.
 const char kSwitchDisableBackgroundDownloads[] = "disable-background-downloads";
 #endif  // defined(OS_WIN)
@@ -109,7 +106,6 @@
   virtual size_t UrlSizeLimit() OVERRIDE;
   virtual net::URLRequestContextGetter* RequestContext() OVERRIDE;
   virtual bool InProcess() OVERRIDE;
-  virtual ComponentPatcher* CreateComponentPatcher() OVERRIDE;
   virtual bool DeltasEnabled() const OVERRIDE;
   virtual bool UseBackgroundDownloader() const OVERRIDE;
 
@@ -136,12 +132,12 @@
       ",", &switch_values);
   fast_update_ = HasSwitchValue(switch_values, kSwitchFastUpdate);
   pings_enabled_ = !HasSwitchValue(switch_values, kSwitchDisablePings);
-#if defined(OS_WIN)
   deltas_enabled_ = !HasSwitchValue(switch_values, kSwitchDisableDeltaUpdates);
+
+#if defined(OS_WIN)
   background_downloads_enabled_ =
       !HasSwitchValue(switch_values, kSwitchDisableBackgroundDownloads);
 #else
-  deltas_enabled_ = false;
   background_downloads_enabled_ = false;
 #endif
 
@@ -202,14 +198,6 @@
   return false;
 }
 
-ComponentPatcher* ChromeConfigurator::CreateComponentPatcher() {
-#if defined(OS_WIN)
-  return new ComponentPatcherWin();
-#else
-  return new ComponentPatcherCrossPlatform();
-#endif
-}
-
 bool ChromeConfigurator::DeltasEnabled() const {
   return deltas_enabled_;
 }
diff --git a/chrome/browser/component_updater/component_updater_service.cc b/chrome/browser/component_updater/component_updater_service.cc
index fa04986..903674a 100644
--- a/chrome/browser/component_updater/component_updater_service.cc
+++ b/chrome/browser/component_updater/component_updater_service.cc
@@ -21,7 +21,6 @@
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/browser/component_updater/component_unpacker.h"
 #include "chrome/browser/component_updater/component_updater_ping_manager.h"
 #include "chrome/browser/component_updater/component_updater_utils.h"
@@ -252,13 +251,11 @@
 
   scoped_ptr<ComponentUpdateService::Configurator> config_;
 
-  scoped_ptr<ComponentPatcher> component_patcher_;
-
   scoped_ptr<UpdateChecker> update_checker_;
 
   scoped_ptr<PingManager> ping_manager_;
 
-  scoped_ptr<ComponentUnpacker> unpacker_;
+  scoped_refptr<ComponentUnpacker> unpacker_;
 
   scoped_ptr<CrxDownloader> crx_downloader_;
 
@@ -281,7 +278,6 @@
 
 CrxUpdateService::CrxUpdateService(ComponentUpdateService::Configurator* config)
     : config_(config),
-      component_patcher_(config->CreateComponentPatcher()),
       ping_manager_(new PingManager(config->PingUrl(),
                                     config->RequestContext())),
       blocking_task_runner_(BrowserThread::GetBlockingPool()->
@@ -856,12 +852,12 @@
 void CrxUpdateService::Install(scoped_ptr<CRXContext> context,
                                const base::FilePath& crx_path) {
   // This function owns the file at |crx_path| and the |context| object.
-  unpacker_.reset(new ComponentUnpacker(context->pk_hash,
-                                        crx_path,
-                                        context->fingerprint,
-                                        component_patcher_.get(),
-                                        context->installer,
-                                        blocking_task_runner_));
+  unpacker_ = new ComponentUnpacker(context->pk_hash,
+                                    crx_path,
+                                    context->fingerprint,
+                                    context->installer,
+                                    config_->InProcess(),
+                                    blocking_task_runner_);
   unpacker_->Unpack(base::Bind(&CrxUpdateService::EndUnpacking,
                                base::Unretained(this),
                                context->id,
@@ -880,6 +876,8 @@
       base::Bind(&CrxUpdateService::DoneInstalling, base::Unretained(this),
                  component_id, error, extended_error),
       base::TimeDelta::FromMilliseconds(config_->StepDelay()));
+  // Reset the unpacker last, otherwise we free our own arguments.
+  unpacker_ = NULL;
 }
 
 // Installation has been completed. Adjust the component status and
diff --git a/chrome/browser/component_updater/component_updater_service.h b/chrome/browser/component_updater/component_updater_service.h
index fa59340..bd9e37b 100644
--- a/chrome/browser/component_updater/component_updater_service.h
+++ b/chrome/browser/component_updater/component_updater_service.h
@@ -30,7 +30,6 @@
 namespace component_updater {
 
 class OnDemandTester;
-class ComponentPatcher;
 
 // Component specific installers must derive from this class and implement
 // OnUpdateError() and Install(). A valid instance of this class must be
@@ -178,9 +177,6 @@
     virtual net::URLRequestContextGetter* RequestContext() = 0;
     // True means that all ops are performed in this process.
     virtual bool InProcess() = 0;
-    // Creates a new ComponentPatcher in a platform-specific way. This is useful
-    // for dependency injection.
-    virtual ComponentPatcher* CreateComponentPatcher() = 0;
     // True means that this client can handle delta updates.
     virtual bool DeltasEnabled() const = 0;
     // True means that the background downloader can be used for downloading
diff --git a/chrome/browser/component_updater/ppapi_utils.cc b/chrome/browser/component_updater/ppapi_utils.cc
index 0de0ead..ec18493 100644
--- a/chrome/browser/component_updater/ppapi_utils.cc
+++ b/chrome/browser/component_updater/ppapi_utils.cc
@@ -14,7 +14,6 @@
 #include "ppapi/c/dev/ppb_cursor_control_dev.h"
 #include "ppapi/c/dev/ppb_device_ref_dev.h"
 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
-#include "ppapi/c/dev/ppb_find_dev.h"
 #include "ppapi/c/dev/ppb_font_dev.h"
 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
 #include "ppapi/c/dev/ppb_graphics_2d_dev.h"
@@ -78,6 +77,7 @@
 #include "ppapi/c/private/ppb_ext_crx_file_system_private.h"
 #include "ppapi/c/private/ppb_file_io_private.h"
 #include "ppapi/c/private/ppb_file_ref_private.h"
+#include "ppapi/c/private/ppb_find_private.h"
 #include "ppapi/c/private/ppb_flash.h"
 #include "ppapi/c/private/ppb_flash_clipboard.h"
 #include "ppapi/c/private/ppb_flash_device_id.h"
diff --git a/chrome/browser/component_updater/test/DEPS b/chrome/browser/component_updater/test/DEPS
index 397b12e..e63018d 100644
--- a/chrome/browser/component_updater/test/DEPS
+++ b/chrome/browser/component_updater/test/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
   # For access to the ppapi test globals.
   "+ppapi/shared_impl",
-  "+courgette",
 ]
diff --git a/chrome/browser/component_updater/test/component_patcher_mock.h b/chrome/browser/component_updater/test/component_patcher_mock.h
deleted file mode 100644
index 48c7901..0000000
--- a/chrome/browser/component_updater/test/component_patcher_mock.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_MOCK_H_
-#define CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_MOCK_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "chrome/browser/component_updater/component_patcher.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace component_updater {
-
-class MockComponentPatcher : public ComponentPatcher {
- public:
-  MockComponentPatcher() {}
-  virtual ComponentUnpacker::Error Patch(PatchType patch_type,
-                                         const base::FilePath& input_file,
-                                         const base::FilePath& patch_file,
-                                         const base::FilePath& output_file,
-                                         int* error) OVERRIDE;
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockComponentPatcher);
-};
-
-}  // namespace component_updater
-
-#endif  // CHROME_BROWSER_COMPONENT_UPDATER_TEST_COMPONENT_PATCHER_MOCK_H_
diff --git a/chrome/browser/component_updater/test/component_patcher_unittest.cc b/chrome/browser/component_updater/test/component_patcher_unittest.cc
index 3cc4f65..8769545 100644
--- a/chrome/browser/component_updater/test/component_patcher_unittest.cc
+++ b/chrome/browser/component_updater/test/component_patcher_unittest.cc
@@ -2,23 +2,55 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
 #include "base/path_service.h"
+#include "base/run_loop.h"
 #include "base/values.h"
 #include "chrome/browser/component_updater/component_patcher.h"
 #include "chrome/browser/component_updater/component_patcher_operation.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
-#include "chrome/browser/component_updater/test/component_patcher_mock.h"
 #include "chrome/browser/component_updater/test/component_patcher_unittest.h"
 #include "chrome/browser/component_updater/test/test_installer.h"
 #include "chrome/common/chrome_paths.h"
+#include "content/public/browser/browser_thread.h"
 #include "courgette/courgette.h"
 #include "courgette/third_party/bsdiff.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace {
+
+class TestCallback {
+ public:
+  TestCallback();
+  virtual ~TestCallback() {}
+  void Set(component_updater::ComponentUnpacker::Error error, int extra_code);
+
+  int error_;
+  int extra_code_;
+  bool called_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestCallback);
+};
+
+TestCallback::TestCallback()
+    : error_(-1), extra_code_(-1), called_(false) {
+}
+
+void TestCallback::Set(component_updater::ComponentUnpacker::Error error,
+                       int extra_code) {
+  error_ = error;
+  extra_code_ = extra_code;
+  called_ = true;
+}
+
+}  // namespace
+
 namespace component_updater {
 
 namespace {
@@ -35,39 +67,14 @@
   EXPECT_TRUE(unpack_dir_.CreateUniqueTempDir());
   EXPECT_TRUE(input_dir_.CreateUniqueTempDir());
   EXPECT_TRUE(installed_dir_.CreateUniqueTempDir());
-  patcher_.reset(new MockComponentPatcher());
   installer_.reset(new ReadOnlyTestInstaller(installed_dir_.path()));
+  task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
+      content::BrowserThread::FILE);
 }
 
 ComponentPatcherOperationTest::~ComponentPatcherOperationTest() {
 }
 
-ComponentUnpacker::Error MockComponentPatcher::Patch(
-    PatchType patch_type,
-    const base::FilePath& input_file,
-    const base::FilePath& patch_file,
-    const base::FilePath& output_file,
-    int* error) {
-  *error = 0;
-  int exit_code;
-  if (patch_type == kPatchTypeCourgette) {
-    exit_code = courgette::ApplyEnsemblePatch(input_file.value().c_str(),
-                                              patch_file.value().c_str(),
-                                              output_file.value().c_str());
-    if (exit_code == courgette::C_OK)
-      return ComponentUnpacker::kNone;
-    *error = exit_code + kCourgetteErrorOffset;
-  } else if (patch_type == kPatchTypeBsdiff) {
-    exit_code = courgette::ApplyBinaryPatch(input_file,
-                                            patch_file,
-                                            output_file);
-    if (exit_code == courgette::OK)
-      return ComponentUnpacker::kNone;
-    *error = exit_code + kBsdiffErrorOffset;
-  }
-  return ComponentUnpacker::kDeltaOperationFailure;
-}
-
 // Verify that a 'create' delta update operation works correctly.
 TEST_F(ComponentPatcherOperationTest, CheckCreateOperation) {
   EXPECT_TRUE(base::CopyFile(
@@ -80,17 +87,20 @@
   command_args->SetString("op", "create");
   command_args->SetString("patch", "binary_output.bin");
 
-  int error = 0;
-  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpCreate());
-  ComponentUnpacker::Error result = op->Run(command_args.get(),
-                                            input_dir_.path(),
-                                            unpack_dir_.path(),
-                                            patcher_.get(),
-                                            NULL,
-                                            &error);
+  TestCallback callback;
+  scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCreate();
+  op->Run(command_args.get(),
+          input_dir_.path(),
+          unpack_dir_.path(),
+          NULL,
+          true,
+          base::Bind(&TestCallback::Set, base::Unretained(&callback)),
+          task_runner_);
+  base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(ComponentUnpacker::kNone, result);
-  EXPECT_EQ(0, error);
+  EXPECT_EQ(true, callback.called_);
+  EXPECT_EQ(ComponentUnpacker::kNone, callback.error_);
+  EXPECT_EQ(0, callback.extra_code_);
   EXPECT_TRUE(base::ContentsEqual(
       unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
       test_file("binary_output.bin")));
@@ -108,16 +118,20 @@
   command_args->SetString("op", "copy");
   command_args->SetString("input", "binary_output.bin");
 
-  int error = 0;
-  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpCopy());
-  ComponentUnpacker::Error result = op->Run(command_args.get(),
-                                            input_dir_.path(),
-                                            unpack_dir_.path(),
-                                            patcher_.get(),
-                                            installer_.get(),
-                                            &error);
-  EXPECT_EQ(ComponentUnpacker::kNone, result);
-  EXPECT_EQ(0, error);
+  TestCallback callback;
+  scoped_refptr<DeltaUpdateOp> op = new DeltaUpdateOpCopy();
+  op->Run(command_args.get(),
+          input_dir_.path(),
+          unpack_dir_.path(),
+          installer_.get(),
+          true,
+          base::Bind(&TestCallback::Set, base::Unretained(&callback)),
+          task_runner_);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(true, callback.called_);
+  EXPECT_EQ(ComponentUnpacker::kNone, callback.error_);
+  EXPECT_EQ(0, callback.extra_code_);
   EXPECT_TRUE(base::ContentsEqual(
       unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
       test_file("binary_output.bin")));
@@ -140,16 +154,20 @@
   command_args->SetString("input", "binary_input.bin");
   command_args->SetString("patch", "binary_courgette_patch.bin");
 
-  int error = 0;
-  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpPatchCourgette());
-  ComponentUnpacker::Error result = op->Run(command_args.get(),
-                                            input_dir_.path(),
-                                            unpack_dir_.path(),
-                                            patcher_.get(),
-                                            installer_.get(),
-                                            &error);
-  EXPECT_EQ(ComponentUnpacker::kNone, result);
-  EXPECT_EQ(0, error);
+  TestCallback callback;
+  scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("courgette");
+  op->Run(command_args.get(),
+          input_dir_.path(),
+          unpack_dir_.path(),
+          installer_.get(),
+          true,
+          base::Bind(&TestCallback::Set, base::Unretained(&callback)),
+          task_runner_);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(true, callback.called_);
+  EXPECT_EQ(ComponentUnpacker::kNone, callback.error_);
+  EXPECT_EQ(0, callback.extra_code_);
   EXPECT_TRUE(base::ContentsEqual(
       unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
       test_file("binary_output.bin")));
@@ -171,16 +189,20 @@
   command_args->SetString("input", "binary_input.bin");
   command_args->SetString("patch", "binary_bsdiff_patch.bin");
 
-  int error = 0;
-  scoped_ptr<DeltaUpdateOp> op(new DeltaUpdateOpPatchBsdiff());
-  ComponentUnpacker::Error result = op->Run(command_args.get(),
-                                            input_dir_.path(),
-                                            unpack_dir_.path(),
-                                            patcher_.get(),
-                                            installer_.get(),
-                                            &error);
-  EXPECT_EQ(ComponentUnpacker::kNone, result);
-  EXPECT_EQ(0, error);
+  TestCallback callback;
+  scoped_refptr<DeltaUpdateOp> op = CreateDeltaUpdateOp("bsdiff");
+  op->Run(command_args.get(),
+          input_dir_.path(),
+          unpack_dir_.path(),
+          installer_.get(),
+          true,
+          base::Bind(&TestCallback::Set, base::Unretained(&callback)),
+          task_runner_);
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(true, callback.called_);
+  EXPECT_EQ(ComponentUnpacker::kNone, callback.error_);
+  EXPECT_EQ(0, callback.extra_code_);
   EXPECT_TRUE(base::ContentsEqual(
       unpack_dir_.path().Append(FILE_PATH_LITERAL("output.bin")),
       test_file("binary_output.bin")));
diff --git a/chrome/browser/component_updater/test/component_patcher_unittest.h b/chrome/browser/component_updater/test/component_patcher_unittest.h
index ac30f35..de6dd24 100644
--- a/chrome/browser/component_updater/test/component_patcher_unittest.h
+++ b/chrome/browser/component_updater/test/component_patcher_unittest.h
@@ -9,6 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/common/chrome_paths.h"
+#include "content/public/test/test_browser_thread_bundle.h"
 #include "courgette/courgette.h"
 #include "courgette/third_party/bsdiff.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -35,8 +36,11 @@
   base::ScopedTempDir input_dir_;
   base::ScopedTempDir installed_dir_;
   base::ScopedTempDir unpack_dir_;
-  scoped_ptr<MockComponentPatcher> patcher_;
   scoped_ptr<ReadOnlyTestInstaller> installer_;
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
+ private:
+  content::TestBrowserThreadBundle thread_bundle_;
 };
 
 }  // namespace component_updater
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.cc b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
index a08ad22..4fa28f7 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.cc
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.cc
@@ -108,10 +108,6 @@
 // Don't use the utility process to run code out-of-process.
 bool TestConfigurator::InProcess() { return true; }
 
-ComponentPatcher* TestConfigurator::CreateComponentPatcher() {
-  return new MockComponentPatcher();
-}
-
 bool TestConfigurator::DeltasEnabled() const {
   return true;
 }
diff --git a/chrome/browser/component_updater/test/component_updater_service_unittest.h b/chrome/browser/component_updater/test/component_updater_service_unittest.h
index 435510b..23ae170 100644
--- a/chrome/browser/component_updater/test/component_updater_service_unittest.h
+++ b/chrome/browser/component_updater/test/component_updater_service_unittest.h
@@ -17,7 +17,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/component_updater/component_updater_service.h"
-#include "chrome/browser/component_updater/test/component_patcher_mock.h"
 #include "chrome/browser/component_updater/test/url_request_post_interceptor.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/test/net/url_request_prepackaged_interceptor.h"
@@ -91,7 +90,6 @@
   virtual size_t UrlSizeLimit() OVERRIDE;
   virtual net::URLRequestContextGetter* RequestContext() OVERRIDE;
   virtual bool InProcess() OVERRIDE;
-  virtual ComponentPatcher* CreateComponentPatcher() OVERRIDE;
   virtual bool DeltasEnabled() const OVERRIDE;
   virtual bool UseBackgroundDownloader() const OVERRIDE;
 
diff --git a/chrome/browser/component_updater/widevine_cdm_component_installer.cc b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
index 8fbfbe6..f8c494a 100644
--- a/chrome/browser/component_updater/widevine_cdm_component_installer.cc
+++ b/chrome/browser/component_updater/widevine_cdm_component_installer.cc
@@ -201,11 +201,6 @@
     additional_param_values->push_back(codecs);
   } else {
     DLOG(WARNING) << "Widevine CDM component manifest is missing codecs";
-    // TODO(ddorwin): Remove this once all users have been updated.
-    // The original manifests did not include this string, so add the base set.
-    additional_param_names->push_back(
-        base::ASCIIToUTF16(kCdmSupportedCodecsParamName));
-    additional_param_values->push_back(base::ASCIIToUTF16("vp8,vorbis"));
   }
 }
 
diff --git a/chrome/browser/devtools/android_device.h b/chrome/browser/devtools/android_device.h
index 4c34f5c..f67e70f 100644
--- a/chrome/browser/devtools/android_device.h
+++ b/chrome/browser/devtools/android_device.h
@@ -80,6 +80,8 @@
 #if defined(DEBUG_DEVTOOLS)
   static scoped_refptr<AndroidDeviceProvider> GetSelfAsDeviceProvider();
 #endif
+  // Implemented in browser_tests.
+  static scoped_refptr<AndroidDeviceProvider> GetMockDeviceProviderForTest();
 
  protected:
   friend struct
diff --git a/chrome/browser/devtools/devtools_adb_bridge.cc b/chrome/browser/devtools/devtools_adb_bridge.cc
index b55dcf1..59226c2 100644
--- a/chrome/browser/devtools/devtools_adb_bridge.cc
+++ b/chrome/browser/devtools/devtools_adb_bridge.cc
@@ -103,6 +103,11 @@
     "Chrome Dev"
   },
   {
+    "com.chrome.canary",
+    kChromeDefaultSocket,
+    "Chrome Canary"
+  },
+  {
     "com.google.android.apps.chrome",
     kChromeDefaultSocket,
     "Chromium"
@@ -1096,6 +1101,12 @@
       has_message_loop_(adb_thread_->message_loop() != NULL) {
 }
 
+void DevToolsAdbBridge::set_device_provider_for_test(
+    scoped_refptr<AndroidDeviceProvider> device_provider) {
+  device_providers_for_test_.clear();
+  device_providers_for_test_.push_back(device_provider);
+}
+
 void DevToolsAdbBridge::AddListener(Listener* listener) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (listeners_.empty())
@@ -1127,7 +1138,10 @@
     return;
 
   new AdbPagesCommand(
-      adb_thread_, device_providers_,
+      adb_thread_,
+      device_providers_for_test_.size() ?
+          device_providers_for_test_ :
+          device_providers_,
       base::Bind(&DevToolsAdbBridge::ReceivedRemoteDevices, this));
 }
 
diff --git a/chrome/browser/devtools/devtools_adb_bridge.h b/chrome/browser/devtools/devtools_adb_bridge.h
index c1cf53c..6f6dde2 100644
--- a/chrome/browser/devtools/devtools_adb_bridge.h
+++ b/chrome/browser/devtools/devtools_adb_bridge.h
@@ -180,6 +180,11 @@
   void set_device_providers(DeviceProviders device_providers) {
     device_providers_ = device_providers;
   }
+
+  // If the test device provider is set all other providers are ignored.
+  void set_device_provider_for_test(
+      scoped_refptr<AndroidDeviceProvider> device_provider);
+
   static bool HasDevToolsWindow(const std::string& agent_id);
 
  private:
@@ -197,6 +202,7 @@
   typedef std::vector<Listener*> Listeners;
   Listeners listeners_;
   DeviceProviders device_providers_;
+  DeviceProviders device_providers_for_test_;
   DISALLOW_COPY_AND_ASSIGN(DevToolsAdbBridge);
 };
 
diff --git a/chrome/browser/devtools/devtools_adb_bridge_browsertest.cc b/chrome/browser/devtools/devtools_adb_bridge_browsertest.cc
index e8d7b50..056bed5 100644
--- a/chrome/browser/devtools/devtools_adb_bridge_browsertest.cc
+++ b/chrome/browser/devtools/devtools_adb_bridge_browsertest.cc
@@ -247,6 +247,12 @@
   }
 };
 
+// static
+scoped_refptr<AndroidDeviceProvider>
+AndroidDeviceProvider::GetMockDeviceProviderForTest() {
+  return new MockDeviceProvider();
+}
+
 static scoped_refptr<DevToolsAdbBridge::RemoteBrowser>
 FindBrowserByDisplayName(DevToolsAdbBridge::RemoteBrowsers browsers,
                          const std::string& name) {
@@ -355,7 +361,7 @@
       DevToolsAdbBridge::Factory::GetForProfile(browser()->profile());
 
   DevToolsAdbBridge::DeviceProviders providers;
-  providers.push_back(new MockDeviceProvider());
+  providers.push_back(AndroidDeviceProvider::GetMockDeviceProviderForTest());
 
   adb_bridge->set_device_providers(providers);
 
diff --git a/chrome/browser/devtools/port_forwarding_controller.cc b/chrome/browser/devtools/port_forwarding_controller.cc
index 72179dd..2dd9e11 100644
--- a/chrome/browser/devtools/port_forwarding_controller.cc
+++ b/chrome/browser/devtools/port_forwarding_controller.cc
@@ -11,7 +11,6 @@
 #include "base/compiler_specific.h"
 #include "base/memory/singleton.h"
 #include "base/message_loop/message_loop.h"
-#include "base/prefs/pref_change_registrar.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -355,19 +354,15 @@
   ForwardingMap new_forwarding_map;
 
   PrefService* pref_service = pref_change_registrar_.prefs();
-  bool enabled =
-      pref_service->GetBoolean(prefs::kDevToolsPortForwardingEnabled);
-  if (enabled) {
-    const base::DictionaryValue* dict =
-        pref_service->GetDictionary(prefs::kDevToolsPortForwardingConfig);
-    for (base::DictionaryValue::Iterator it(*dict);
-         !it.IsAtEnd(); it.Advance()) {
-      int port_num;
-      std::string location;
-      if (base::StringToInt(it.key(), &port_num) &&
-          dict->GetString(it.key(), &location))
-        new_forwarding_map[port_num] = location;
-    }
+  const base::DictionaryValue* dict =
+      pref_service->GetDictionary(prefs::kDevToolsPortForwardingConfig);
+  for (base::DictionaryValue::Iterator it(*dict);
+       !it.IsAtEnd(); it.Advance()) {
+    int port_num;
+    std::string location;
+    if (base::StringToInt(it.key(), &port_num) &&
+        dict->GetString(it.key(), &location))
+      new_forwarding_map[port_num] = location;
   }
 
   adb_thread_->message_loop()->PostTask(
@@ -510,12 +505,9 @@
     return;
   }
   OnPrefsChange();
-  base::Closure pref_callback = base::Bind(
-      &Connection::OnPrefsChange, base::Unretained(this));
   pref_change_registrar_.Add(
-      prefs::kDevToolsPortForwardingEnabled, pref_callback);
-  pref_change_registrar_.Add(
-      prefs::kDevToolsPortForwardingConfig, pref_callback);
+      prefs::kDevToolsPortForwardingConfig,
+          base::Bind(&Connection::OnPrefsChange, base::Unretained(this)));
 }
 
 void PortForwardingController::Connection::OnFrameRead(
@@ -569,17 +561,24 @@
 PortForwardingController::PortForwardingController(PrefService* pref_service)
     : adb_thread_(RefCountedAdbThread::GetInstance()),
       pref_service_(pref_service) {
+  pref_change_registrar_.Init(pref_service);
+  base::Closure callback = base::Bind(
+      &PortForwardingController::OnPrefsChange, base::Unretained(this));
+  pref_change_registrar_.Add(prefs::kDevToolsPortForwardingEnabled, callback);
+  pref_change_registrar_.Add(prefs::kDevToolsPortForwardingConfig, callback);
 }
 
 PortForwardingController::~PortForwardingController() {
-  for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it)
-    it->second->Shutdown();
+  ShutdownConnections();
 }
 
 PortForwardingController::DevicesStatus
 PortForwardingController::UpdateDeviceList(
     const DevToolsAdbBridge::RemoteDevices& devices) {
   DevicesStatus status;
+  if (!ShouldCreateConnections())
+    return status;
+
   for (DevToolsAdbBridge::RemoteDevices::const_iterator it = devices.begin();
        it != devices.end(); ++it) {
     scoped_refptr<DevToolsAdbBridge::RemoteDevice> device = *it;
@@ -599,6 +598,26 @@
   return status;
 }
 
+void PortForwardingController::OnPrefsChange() {
+  if (!ShouldCreateConnections())
+    ShutdownConnections();
+}
+
+bool PortForwardingController::ShouldCreateConnections() {
+  if (!pref_service_->GetBoolean(prefs::kDevToolsPortForwardingEnabled))
+    return false;
+
+  const base::DictionaryValue* dict =
+      pref_service_->GetDictionary(prefs::kDevToolsPortForwardingConfig);
+  return !base::DictionaryValue::Iterator(*dict).IsAtEnd();
+}
+
+void PortForwardingController::ShutdownConnections() {
+  for (Registry::iterator it = registry_.begin(); it != registry_.end(); ++it)
+    it->second->Shutdown();
+  registry_.clear();
+}
+
 // static
 PortForwardingController::Factory*
 PortForwardingController::Factory::GetInstance() {
diff --git a/chrome/browser/devtools/port_forwarding_controller.h b/chrome/browser/devtools/port_forwarding_controller.h
index 36e258b..72be133 100644
--- a/chrome/browser/devtools/port_forwarding_controller.h
+++ b/chrome/browser/devtools/port_forwarding_controller.h
@@ -7,6 +7,7 @@
 
 #include <map>
 
+#include "base/prefs/pref_change_registrar.h"
 #include "chrome/browser/devtools/devtools_adb_bridge.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -50,8 +51,13 @@
   class Connection;
   typedef std::map<std::string, Connection* > Registry;
 
+  void OnPrefsChange();
+  bool ShouldCreateConnections();
+  void ShutdownConnections();
+
   scoped_refptr<RefCountedAdbThread> adb_thread_;
   PrefService* pref_service_;
+  PrefChangeRegistrar pref_change_registrar_;
   Registry registry_;
 
   DISALLOW_COPY_AND_ASSIGN(PortForwardingController);
diff --git a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
index 74f1ab2..3489f66 100644
--- a/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
+++ b/chrome/browser/dom_distiller/dom_distiller_viewer_source_browsertest.cc
@@ -152,8 +152,9 @@
 
 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings
 // are enabled when the article exists in the database.
+// Flakiness: crbug.com/356866
 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest,
-                       NoWebUIBindingsArticleExists) {
+                       FLAKY_NoWebUIBindingsArticleExists) {
   // Ensure there is one item in the database, which will trigger distillation.
   const ArticleEntry entry = CreateEntry("DISTILLED", "http://example.com/1");
   AddEntry(entry, database_model_);
@@ -176,8 +177,9 @@
 
 // The DomDistillerViewerSource renders untrusted content, so ensure no bindings
 // are enabled when requesting to view an arbitrary URL.
+// Flakiness: crbug.com/356866
 IN_PROC_BROWSER_TEST_F(DomDistillerViewerSourceBrowserTest,
-                       NoWebUIBindingsViewUrl) {
+                       FLAKY_NoWebUIBindingsViewUrl) {
   // We should expect distillation for any valid URL.
   expect_distillation_ = true;
   GURL view_url("http://www.example.com/1");
diff --git a/chrome/browser/download/download_query_unittest.cc b/chrome/browser/download/download_query_unittest.cc
index 2d8163c..a11446b 100644
--- a/chrome/browser/download/download_query_unittest.cc
+++ b/chrome/browser/download/download_query_unittest.cc
@@ -112,21 +112,17 @@
 
 template<> void DownloadQueryTest::AddFilter(
     DownloadQuery::FilterType name, const char* cpp_value) {
-  scoped_ptr<base::Value> value(base::Value::CreateStringValue(cpp_value));
-  CHECK(query_.AddFilter(name, *value.get()));
+  CHECK(query_.AddFilter(name, base::StringValue(cpp_value)));
 }
 
 template<> void DownloadQueryTest::AddFilter(
     DownloadQuery::FilterType name, std::string cpp_value) {
-  scoped_ptr<base::Value> value(base::Value::CreateStringValue(cpp_value));
-  CHECK(query_.AddFilter(name, *value.get()));
+  CHECK(query_.AddFilter(name, base::StringValue(cpp_value)));
 }
 
 template<> void DownloadQueryTest::AddFilter(
     DownloadQuery::FilterType name, const base::char16* cpp_value) {
-  scoped_ptr<base::Value> value(
-      base::Value::CreateStringValue(base::string16(cpp_value)));
-  CHECK(query_.AddFilter(name, *value.get()));
+  CHECK(query_.AddFilter(name, base::StringValue(cpp_value)));
 }
 
 template<> void DownloadQueryTest::AddFilter(
@@ -134,7 +130,7 @@
   scoped_ptr<base::ListValue> list(new base::ListValue());
   for (std::vector<base::string16>::const_iterator it = cpp_value.begin();
        it != cpp_value.end(); ++it) {
-    list->Append(base::Value::CreateStringValue(*it));
+    list->Append(new base::StringValue(*it));
   }
   CHECK(query_.AddFilter(name, *list.get()));
 }
@@ -144,7 +140,7 @@
   scoped_ptr<base::ListValue> list(new base::ListValue());
   for (std::vector<std::string>::const_iterator it = cpp_value.begin();
        it != cpp_value.end(); ++it) {
-    list->Append(base::Value::CreateStringValue(*it));
+    list->Append(new base::StringValue(*it));
   }
   CHECK(query_.AddFilter(name, *list.get()));
 }
@@ -152,8 +148,7 @@
 #if defined(OS_WIN)
 template<> void DownloadQueryTest::AddFilter(
     DownloadQuery::FilterType name, std::wstring cpp_value) {
-  scoped_ptr<base::Value> value(base::Value::CreateStringValue(cpp_value));
-  CHECK(query_.AddFilter(name, *value.get()));
+  CHECK(query_.AddFilter(name, base::StringValue(cpp_value)));
 }
 #endif
 
diff --git a/chrome/browser/download/drag_download_item_views.cc b/chrome/browser/download/drag_download_item_views.cc
index d334d40..5ecfbc8 100644
--- a/chrome/browser/download/drag_download_item_views.cc
+++ b/chrome/browser/download/drag_download_item_views.cc
@@ -12,17 +12,19 @@
 #include "net/base/net_util.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/drag_utils.h"
+#include "ui/base/dragdrop/file_info.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/point.h"
 #include "ui/gfx/screen.h"
 #include "ui/views/widget/widget.h"
 #include "url/gurl.h"
 
 #if defined(USE_AURA)
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
+#include "ui/wm/public/drag_drop_client.h"
 #endif
 
 #if defined(OS_CHROMEOS)
@@ -38,10 +40,10 @@
   // Set up our OLE machinery
   ui::OSExchangeData data;
 
-  if (icon) {
-    drag_utils::CreateDragImageForFile(
-        download->GetFileNameToReportUser(), icon->ToImageSkia(), &data);
-  }
+  drag_utils::CreateDragImageForFile(
+      download->GetFileNameToReportUser(),
+      icon ? icon->AsImageSkia() : gfx::ImageSkia(),
+      &data);
 
   base::FilePath full_path = download->GetTargetFilePath();
 #if defined(OS_CHROMEOS)
@@ -53,15 +55,11 @@
       drive_download_handler->IsDriveDownload(download))
     full_path = drive_download_handler->GetCacheFilePath(download);
 #endif
-  std::vector<ui::OSExchangeData::FileInfo> file_infos;
-  file_infos.push_back(ui::OSExchangeData::FileInfo(
-      full_path, download->GetFileNameToReportUser()));
+  std::vector<ui::FileInfo> file_infos;
+  file_infos.push_back(
+      ui::FileInfo(full_path, download->GetFileNameToReportUser()));
   data.SetFilenames(file_infos);
 
-  // Add URL so that we can load supported files when dragged to WebContents.
-  data.SetURL(net::FilePathToFileURL(full_path),
-              download->GetFileNameToReportUser().LossyDisplayName());
-
 #if !defined(TOOLKIT_GTK)
 #if defined(USE_AURA)
   aura::Window* root_window = view->GetRootWindow();
diff --git a/chrome/browser/drive/drive_api_util.cc b/chrome/browser/drive/drive_api_util.cc
index 5ac7222..cf80766 100644
--- a/chrome/browser/drive/drive_api_util.cc
+++ b/chrome/browser/drive/drive_api_util.cc
@@ -6,10 +6,9 @@
 
 #include <string>
 
-#include "base/files/scoped_platform_file_closer.h"
+#include "base/files/file.h"
 #include "base/logging.h"
 #include "base/md5.h"
-#include "base/platform_file.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
@@ -344,21 +343,20 @@
   image_media_metadata->set_height(entry.image_height());
   image_media_metadata->set_rotation(entry.image_rotation());
 
-  ScopedVector<google_apis::ParentReference> parents;
+  std::vector<google_apis::ParentReference>* parents = file->mutable_parents();
   for (size_t i = 0; i < entry.links().size(); ++i) {
     using google_apis::Link;
     const Link& link = *entry.links()[i];
     switch (link.type()) {
       case Link::LINK_PARENT: {
-        scoped_ptr<google_apis::ParentReference> parent(
-            new google_apis::ParentReference);
-        parent->set_parent_link(link.href());
+        google_apis::ParentReference parent;
+        parent.set_parent_link(link.href());
 
         std::string file_id =
             drive::util::ExtractResourceIdFromUrl(link.href());
-        parent->set_file_id(file_id);
-        parent->set_is_root(file_id == kWapiRootDirectoryResourceId);
-        parents.push_back(parent.release());
+        parent.set_file_id(file_id);
+        parent.set_is_root(file_id == kWapiRootDirectoryResourceId);
+        parents->push_back(parent);
         break;
       }
       case Link::LINK_ALTERNATE:
@@ -368,7 +366,6 @@
         break;
     }
   }
-  file->set_parents(parents.Pass());
 
   file->set_modified_date(entry.updated_time());
   file->set_last_viewed_by_me_date(entry.last_viewed_time());
@@ -450,7 +447,7 @@
   for (size_t i = 0; i < file_resource.parents().size(); ++i) {
     google_apis::Link* link = new google_apis::Link;
     link->set_type(google_apis::Link::LINK_PARENT);
-    link->set_href(file_resource.parents()[i]->parent_link());
+    link->set_href(file_resource.parents()[i].parent_link());
     links.push_back(link);
   }
   if (!file_resource.alternate_link().is_empty()) {
@@ -538,12 +535,9 @@
 std::string GetMd5Digest(const base::FilePath& file_path) {
   const int kBufferSize = 512 * 1024;  // 512kB.
 
-  base::PlatformFile file = base::CreatePlatformFile(
-      file_path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
-      NULL, NULL);
-  if (file == base::kInvalidPlatformFileValue)
+  base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!file.IsValid())
     return std::string();
-  base::ScopedPlatformFileCloser file_closer(&file);
 
   base::MD5Context context;
   base::MD5Init(&context);
@@ -551,11 +545,7 @@
   int64 offset = 0;
   scoped_ptr<char[]> buffer(new char[kBufferSize]);
   while (true) {
-    // Avoid using ReadPlatformFileCurPosNoBestEffort for now.
-    // http://crbug.com/145873
-    int result = base::ReadPlatformFileNoBestEffort(
-        file, offset, buffer.get(), kBufferSize);
-
+    int result = file.Read(offset, buffer.get(), kBufferSize);
     if (result < 0) {
       // Found an error.
       return std::string();
diff --git a/chrome/browser/drive/drive_api_util_unittest.cc b/chrome/browser/drive/drive_api_util_unittest.cc
index afb4a13..af405f3 100644
--- a/chrome/browser/drive/drive_api_util_unittest.cc
+++ b/chrome/browser/drive/drive_api_util_unittest.cc
@@ -202,13 +202,11 @@
   expected_links.push_back(GURL("http://server/id2"));
   expected_links.push_back(GURL("http://server/id3"));
 
-  ScopedVector<google_apis::ParentReference> parents;
   for (size_t i = 0; i < expected_links.size(); ++i) {
-    google_apis::ParentReference* parent = new google_apis::ParentReference;
-    parent->set_parent_link(expected_links[i]);
-    parents.push_back(parent);
+    google_apis::ParentReference parent;
+    parent.set_parent_link(expected_links[i]);
+    file_resource.mutable_parents()->push_back(parent);
   }
-  file_resource.set_parents(parents.Pass());
 
   scoped_ptr<google_apis::ResourceEntry> entry(
       ConvertFileResourceToResourceEntry(file_resource));
diff --git a/chrome/browser/drive/fake_drive_service.cc b/chrome/browser/drive/fake_drive_service.cc
index 5554c5e..3931727 100644
--- a/chrome/browser/drive/fake_drive_service.cc
+++ b/chrome/browser/drive/fake_drive_service.cc
@@ -724,12 +724,8 @@
     scoped_ptr<EntryInfo> copied_entry(new EntryInfo);
     copied_entry->content_data = entry->content_data;
     copied_entry->share_url = entry->share_url;
-
-    // TODO(hashimoto): Implement a proper way to copy FileResource.
-    scoped_ptr<ResourceEntry> copied_resource_entry =
-        util::ConvertChangeResourceToResourceEntry(entry->change_resource);
     copied_entry->change_resource.set_file(
-        util::ConvertResourceEntryToFileResource(*copied_resource_entry));
+        make_scoped_ptr(new FileResource(*entry->change_resource.file())));
 
     ChangeResource* new_change = &copied_entry->change_resource;
     FileResource* new_file = new_change->mutable_file();
@@ -738,13 +734,13 @@
     new_file->set_file_id(new_resource_id);
     new_file->set_title(new_title);
 
-    scoped_ptr<ParentReference> parent(new ParentReference);
-    parent->set_file_id(parent_resource_id);
-    parent->set_parent_link(GetFakeLinkUrl(parent_resource_id));
-    parent->set_is_root(parent_resource_id == GetRootResourceId());
-    ScopedVector<ParentReference> parents;
-    parents.push_back(parent.release());
-    new_file->set_parents(parents.Pass());
+    ParentReference parent;
+    parent.set_file_id(parent_resource_id);
+    parent.set_parent_link(GetFakeLinkUrl(parent_resource_id));
+    parent.set_is_root(parent_resource_id == GetRootResourceId());
+    std::vector<ParentReference> parents;
+    parents.push_back(parent);
+    *new_file->mutable_parents() = parents;
 
     if (!last_modified.is_null())
       new_file->set_modified_date(last_modified);
@@ -797,14 +793,14 @@
 
     // Set parent if necessary.
     if (!parent_resource_id.empty()) {
-      scoped_ptr<ParentReference> parent(new ParentReference);
-      parent->set_file_id(parent_resource_id);
-      parent->set_parent_link(GetFakeLinkUrl(parent_resource_id));
-      parent->set_is_root(parent_resource_id == GetRootResourceId());
+      ParentReference parent;
+      parent.set_file_id(parent_resource_id);
+      parent.set_parent_link(GetFakeLinkUrl(parent_resource_id));
+      parent.set_is_root(parent_resource_id == GetRootResourceId());
 
-      ScopedVector<ParentReference> parents;
-      parents.push_back(parent.release());
-      file->set_parents(parents.Pass());
+      std::vector<ParentReference> parents;
+      parents.push_back(parent);
+      *file->mutable_parents() = parents;
     }
 
     if (!last_modified.is_null())
@@ -863,11 +859,11 @@
     // structure. That is, each resource can have multiple parent.
     // We mimic the behavior here; AddResourceToDirectoy just adds
     // one more parent, not overwriting old ones.
-    scoped_ptr<ParentReference> parent(new ParentReference);
-    parent->set_file_id(parent_resource_id);
-    parent->set_parent_link(GetFakeLinkUrl(parent_resource_id));
-    parent->set_is_root(parent_resource_id == GetRootResourceId());
-    change->mutable_file()->mutable_parents()->push_back(parent.release());
+    ParentReference parent;
+    parent.set_file_id(parent_resource_id);
+    parent.set_parent_link(GetFakeLinkUrl(parent_resource_id));
+    parent.set_is_root(parent_resource_id == GetRootResourceId());
+    change->mutable_file()->mutable_parents()->push_back(parent);
 
     AddNewChangestamp(change);
     base::MessageLoop::current()->PostTask(
@@ -897,9 +893,9 @@
   if (entry) {
     ChangeResource* change = &entry->change_resource;
     FileResource* file = change->mutable_file();
-    ScopedVector<ParentReference>* parents = file->mutable_parents();
+    std::vector<ParentReference>* parents = file->mutable_parents();
     for (size_t i = 0; i < parents->size(); ++i) {
-      if ((*parents)[i]->file_id() == parent_resource_id) {
+      if ((*parents)[i].file_id() == parent_resource_id) {
         parents->erase(parents->begin() + i);
         AddNewChangestamp(change);
         base::MessageLoop::current()->PostTask(
@@ -932,7 +928,8 @@
     return CancelCallback();
   }
 
-  const EntryInfo* new_entry = AddNewEntry(kDriveFolderMimeType,
+  const EntryInfo* new_entry = AddNewEntry("",  // resource_id,
+                                           kDriveFolderMimeType,
                                            "",  // content_data
                                            parent_resource_id,
                                            directory_title,
@@ -1117,6 +1114,7 @@
     DCHECK(!session->parent_resource_id.empty());
     DCHECK(!session->title.empty());
     const EntryInfo* new_entry = AddNewEntry(
+        "",  // auto generate resource id.
         session->content_type,
         content_data,
         session->parent_resource_id,
@@ -1261,6 +1259,18 @@
                                   const std::string& title,
                                   bool shared_with_me,
                                   const GetResourceEntryCallback& callback) {
+  AddNewFileWithResourceId("", content_type, content_data, parent_resource_id,
+                           title, shared_with_me, callback);
+}
+
+void FakeDriveService::AddNewFileWithResourceId(
+    const std::string& resource_id,
+    const std::string& content_type,
+    const std::string& content_data,
+    const std::string& parent_resource_id,
+    const std::string& title,
+    bool shared_with_me,
+    const GetResourceEntryCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!callback.is_null());
 
@@ -1274,7 +1284,8 @@
     return;
   }
 
-  const EntryInfo* new_entry = AddNewEntry(content_type,
+  const EntryInfo* new_entry = AddNewEntry(resource_id,
+                                           content_type,
                                            content_data,
                                            parent_resource_id,
                                            title,
@@ -1360,6 +1371,7 @@
 }
 
 const FakeDriveService::EntryInfo* FakeDriveService::AddNewEntry(
+    const std::string& given_resource_id,
     const std::string& content_type,
     const std::string& content_data,
     const std::string& parent_resource_id,
@@ -1373,7 +1385,10 @@
     return NULL;
   }
 
-  std::string resource_id = GetNewResourceId();
+  const std::string resource_id =
+      given_resource_id.empty() ? GetNewResourceId() : given_resource_id;
+  if (entries_.count(resource_id))
+    return NULL;
   GURL upload_url = GURL("https://xxx/upload/" + resource_id);
 
   scoped_ptr<EntryInfo> new_entry(new EntryInfo);
@@ -1403,16 +1418,16 @@
   new_file->set_mime_type(content_type);
 
   // Set parents.
-  scoped_ptr<ParentReference> parent(new ParentReference);
+  ParentReference parent;
   if (parent_resource_id.empty())
-    parent->set_file_id(GetRootResourceId());
+    parent.set_file_id(GetRootResourceId());
   else
-    parent->set_file_id(parent_resource_id);
-  parent->set_parent_link(GetFakeLinkUrl(parent->file_id()));
-  parent->set_is_root(parent->file_id() == GetRootResourceId());
-  ScopedVector<ParentReference> parents;
-  parents.push_back(parent.release());
-  new_file->set_parents(parents.Pass());
+    parent.set_file_id(parent_resource_id);
+  parent.set_parent_link(GetFakeLinkUrl(parent.file_id()));
+  parent.set_is_root(parent.file_id() == GetRootResourceId());
+  std::vector<ParentReference> parents;
+  parents.push_back(parent);
+  *new_file->mutable_parents() = parents;
 
   new_entry->share_url = net::AppendOrReplaceQueryParameter(
       share_url_base_, "name", title);
diff --git a/chrome/browser/drive/fake_drive_service.h b/chrome/browser/drive/fake_drive_service.h
index 6b8f13a..f852fd6 100644
--- a/chrome/browser/drive/fake_drive_service.h
+++ b/chrome/browser/drive/fake_drive_service.h
@@ -254,6 +254,19 @@
                   bool shared_with_me,
                   const google_apis::GetResourceEntryCallback& callback);
 
+  // Adds a new file with the given |resource_id|. If the id already exists,
+  // it's an error. This is used for testing cross profile file sharing that
+  // needs to have matching resource IDs in different fake service instances.
+  // |callback| must not be null.
+  void AddNewFileWithResourceId(
+      const std::string& resource_id,
+      const std::string& content_type,
+      const std::string& content_data,
+      const std::string& parent_resource_id,
+      const std::string& title,
+      bool shared_with_me,
+      const google_apis::GetResourceEntryCallback& callback);
+
   // Sets the last modified time for an entry specified by |resource_id|.
   // On success, returns HTTP_SUCCESS with the parsed entry.
   // |callback| must not be null.
@@ -281,13 +294,15 @@
   void UpdateETag(google_apis::FileResource* file);
 
   // Adds a new entry based on the given parameters.
+  // |resource_id| can be empty, in the case, the id is automatically generated.
   // Returns a pointer to the newly added entry, or NULL if failed.
   const EntryInfo* AddNewEntry(
-    const std::string& content_type,
-    const std::string& content_data,
-    const std::string& parent_resource_id,
-    const std::string& title,
-    bool shared_with_me);
+      const std::string& resource_id,
+      const std::string& content_type,
+      const std::string& content_data,
+      const std::string& parent_resource_id,
+      const std::string& title,
+      bool shared_with_me);
 
   // Core implementation of GetResourceList.
   // This method returns the slice of the all matched entries, and its range
diff --git a/chrome/browser/errorpage_browsertest.cc b/chrome/browser/errorpage_browsertest.cc
index 4613e19..a82698f 100644
--- a/chrome/browser/errorpage_browsertest.cc
+++ b/chrome/browser/errorpage_browsertest.cc
@@ -252,14 +252,12 @@
   // a stale copy in the cache has been set to |expected|.
   bool ProbeStaleCopyValue(bool expected) {
     const char* js_cache_probe =
-        "(function () {\n"
-        "  if ('staleCopyInCache' in templateData) {\n"
+        "try {\n"
         "    domAutomationController.send(\n"
-        "      templateData.staleCopyInCache ? 'yes' : 'no');\n"
-        "  } else {\n"
-        "    domAutomationController.send('absent');\n"
-        "  }\n"
-        "})();";
+        "        templateData.staleCopyInCache ? 'yes' : 'no');\n"
+        "} catch (e) {\n"
+        "    domAutomationController.send(e.message);\n"
+        "}\n";
 
     std::string result;
     bool ret =
@@ -274,6 +272,27 @@
     return ((expected ? "yes" : "no") == result);
   }
 
+  testing::AssertionResult ReloadStaleCopyFromCache() {
+    const char* js_reload_script =
+        "try {\n"
+        "    errorCacheLoad.reloadStaleInstance();\n"
+        "    domAutomationController.send('success');\n"
+        "} catch (e) {\n"
+        "    domAutomationController.send(e.message);\n"
+        "}\n";
+
+    std::string result;
+    bool ret = content::ExecuteScriptAndExtractString(
+        browser()->tab_strip_model()->GetActiveWebContents(),
+        js_reload_script,
+        &result);
+    EXPECT_TRUE(ret);
+    if (!ret)
+      return testing::AssertionFailure();
+    return ("success" == result ? testing::AssertionSuccess() :
+            (testing::AssertionFailure() << "Exception message is " << result));
+  }
+
  protected:
   static void EnableMocks(const GURL& search_url) {
     chrome_browser_net::SetUrlRequestMocksEnabled(true);
@@ -640,7 +659,8 @@
 }
 
 // Checks that when an error occurs, the stale cache status of the page
-// is correctly transferred.
+// is correctly transferred, and that stale cached copied can be loaded
+// from the javascript.
 IN_PROC_BROWSER_TEST_F(ErrorPageTest, StaleCacheStatus) {
   ASSERT_TRUE(test_server()->Start());
   // Load cache with entry with "nocache" set, to create stale
@@ -661,6 +681,16 @@
       // With no navigation corrections to load, there's only one navigation.
       browser(), test_url, 1);
   EXPECT_TRUE(ProbeStaleCopyValue(true));
+  EXPECT_NE(base::ASCIIToUTF16("Nocache Test Page"),
+            browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
+
+  // Confirm that loading the stale copy from the cache works.
+  content::TestNavigationObserver same_tab_observer(
+      browser()->tab_strip_model()->GetActiveWebContents(), 1);
+  ASSERT_TRUE(ReloadStaleCopyFromCache());
+  same_tab_observer.Wait();
+  EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
+            browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
 
   // Clear the cache and reload the same URL; confirm the error page is told
   // that there is no cached copy.
@@ -810,8 +840,9 @@
 }
 
 // Checks that when an error occurs and a corrections fail to load, the stale
-// cache status of the page is correctly transferred.  Most logic copied
-// from StaleCacheStatus above.
+// cache status of the page is correctly transferred, and we can load the
+// stale copy from the javascript.  Most logic copied from StaleCacheStatus
+// above.
 IN_PROC_BROWSER_TEST_F(ErrorPageNavigationCorrectionsFailTest,
                        StaleCacheStatusFailedCorrections) {
   ASSERT_TRUE(test_server()->Start());
@@ -833,6 +864,14 @@
       browser(), test_url, 2);
   ProbeStaleCopyValue(true);
 
+  // Confirm that loading the stale copy from the cache works.
+  content::TestNavigationObserver same_tab_observer(
+      browser()->tab_strip_model()->GetActiveWebContents(), 1);
+  ASSERT_TRUE(ReloadStaleCopyFromCache());
+  same_tab_observer.Wait();
+  EXPECT_EQ(base::ASCIIToUTF16("Nocache Test Page"),
+            browser()->tab_strip_model()->GetActiveWebContents()->GetTitle());
+
   // Clear the cache and reload the same URL; confirm the error page is told
   // that there is no cached copy.
   BrowsingDataRemover* remover =
diff --git a/chrome/browser/extensions/PRESUBMIT.py b/chrome/browser/extensions/PRESUBMIT.py
deleted file mode 100644
index 31cac0c..0000000
--- a/chrome/browser/extensions/PRESUBMIT.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Chromium presubmit script for src/chrome/browser/extensions.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
-for more details on the presubmit API built into gcl.
-"""
-
-def GetPreferredTryMasters(project, change):
-  return {
-    'tryserver.chromium': {
-      'linux_chromium_chromeos_rel': set(['defaulttests']),
-    }
-  }
-
-def CheckChangeOnUpload(input_api, output_api):
-  results = []
-  results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
-  return results
-
diff --git a/chrome/browser/extensions/active_tab_apitest.cc b/chrome/browser/extensions/active_tab_apitest.cc
index 3e91b92..1ad461c 100644
--- a/chrome/browser/extensions/active_tab_apitest.cc
+++ b/chrome/browser/extensions/active_tab_apitest.cc
@@ -13,8 +13,8 @@
 namespace extensions {
 namespace {
 
-// Times out on win asan, http://crbug.com/166026
-#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
+// Times out on win syzyasan, http://crbug.com/166026
+#if defined(SYZYASAN)
 #define MAYBE_ActiveTab DISABLED_ActiveTab
 #else
 #define MAYBE_ActiveTab ActiveTab
diff --git a/chrome/browser/extensions/activity_log/activity_database.cc b/chrome/browser/extensions/activity_log/activity_database.cc
index 66844af..09b868b 100644
--- a/chrome/browser/extensions/activity_log/activity_database.cc
+++ b/chrome/browser/extensions/activity_log/activity_database.cc
@@ -57,7 +57,7 @@
   if (did_init_) return;
   did_init_ = true;
   if (BrowserThread::IsMessageLoopValid(BrowserThread::DB))
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+    DCHECK_CURRENTLY_ON(BrowserThread::DB);
   db_.set_histogram_tag("Activity");
   db_.set_error_callback(
       base::Bind(&ActivityDatabase::DatabaseErrorCallback,
@@ -136,7 +136,7 @@
 
 sql::Connection* ActivityDatabase::GetSqlConnection() {
   if (BrowserThread::IsMessageLoopValid(BrowserThread::DB))
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+    DCHECK_CURRENTLY_ON(BrowserThread::DB);
   if (valid_db_) {
     return &db_;
   } else {
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index d959da7..c148ed2 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -617,7 +617,7 @@
 void ActivityLog::OnApiEventDispatched(const std::string& extension_id,
                                        const std::string& event_name,
                                        scoped_ptr<base::ListValue> event_args) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_refptr<Action> action = new Action(extension_id,
                                             base::Time::Now(),
                                             Action::ACTION_API_EVENT,
@@ -629,7 +629,7 @@
 void ActivityLog::OnApiFunctionCalled(const std::string& extension_id,
                                       const std::string& api_name,
                                       scoped_ptr<base::ListValue> args) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_refptr<Action> action = new Action(extension_id,
                                             base::Time::Now(),
                                             Action::ACTION_API_CALL,
diff --git a/chrome/browser/extensions/activity_log/counting_policy.cc b/chrome/browser/extensions/activity_log/counting_policy.cc
index 432a627..299e8fb 100644
--- a/chrome/browser/extensions/activity_log/counting_policy.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy.cc
@@ -77,6 +77,9 @@
     {Action::ACTION_API_CALL, "socket.listen"},
     {Action::ACTION_API_CALL, "tabs.executeScript"},
     {Action::ACTION_API_CALL, "tabs.insertCSS"},
+    {Action::ACTION_API_CALL, "types.ChromeSetting.clear"},
+    {Action::ACTION_API_CALL, "types.ChromeSetting.get"},
+    {Action::ACTION_API_CALL, "types.ChromeSetting.set"},
     {Action::ACTION_CONTENT_SCRIPT, ""},
     {Action::ACTION_DOM_ACCESS, "Document.createElement"},
     {Action::ACTION_DOM_ACCESS, "Document.createElementNS"},
diff --git a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
index 2277942..ffe9e8c 100644
--- a/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
+++ b/chrome/browser/extensions/api/app_current_window_internal/app_current_window_internal_api.cc
@@ -365,6 +365,11 @@
     "0F42756099D914A026DADFA182871C015735DD95",  // http://crbug.com/323773
     "2D22CDB6583FD0A13758AEBE8B15E45208B4E9A7",
 
+    "E7E2461CE072DF036CF9592740196159E2D7C089",  // http://crbug.com/356200
+    "A74A4D44C7CFCD8844830E6140C8D763E12DD8F3",
+    "312745D9BF916161191143F6490085EEA0434997",
+    "53041A2FA309EECED01FFC751E7399186E860B2C",
+
     "EBA908206905323CECE6DC4B276A58A0F4AC573F",
     "2775E568AC98F9578791F1EAB65A1BF5F8CEF414",
     "4AA3C5D69A4AECBD236CAD7884502209F0F5C169",
@@ -376,7 +381,19 @@
     "5DF6ADC8708DF59FCFDDBF16AFBFB451380C2059",
     "1037DEF5F6B06EA46153AD87B6C5C37440E3F2D1",
     "F5815DAFEB8C53B078DD1853B2059E087C42F139",
-    "6A08EFFF9C16E090D6DCC7EC55A01CADAE840513"
+    "6A08EFFF9C16E090D6DCC7EC55A01CADAE840513",
+
+    "C32D6D93E12F5401DAA3A723E0C3CC5F25429BA4",  // http://crbug.com/354258
+    "9099782647D39C778E15C8C6E0D23C88F5CDE170",
+    "B7D5B52D1E5B106288BD7F278CAFA5E8D76108B0",
+    "89349DBAA2C4022FB244AA50182AB60934EB41EE",
+    "CB593E510640572A995CB1B6D41BD85ED51E63F8",
+    "1AD1AC86C87969CD3434FA08D99DBA6840AEA612",
+    "9C2EA21D7975BDF2B3C01C3A454EE44854067A6D",
+    "D2C488C80C3C90C3E01A991112A05E37831E17D0",
+    "6EEC061C0E74B46C7B5BE2EEFA49436368F4988F",
+    "8B344D9E8A4C505EF82A0DBBC25B8BD1F984E777",
+    "E06AFCB1EB0EFD237824CC4AC8FDD3D43E8BC868"
   };
   if (GetCurrentChannel() > chrome::VersionInfo::CHANNEL_DEV &&
       !SimpleFeature::IsIdInWhitelist(
diff --git a/chrome/browser/extensions/api/audio/audio_service_chromeos.cc b/chrome/browser/extensions/api/audio/audio_service_chromeos.cc
index abce101..5e80185 100644
--- a/chrome/browser/extensions/api/audio/audio_service_chromeos.cc
+++ b/chrome/browser/extensions/api/audio/audio_service_chromeos.cc
@@ -107,7 +107,7 @@
 }
 
 void AudioServiceImpl::StartGetInfo(const GetInfoCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(cras_audio_client_);
   // TODO(jennyz,rkc): Replace cras_audio_client_ call with CrasAudioHandler
   // Api call.
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc
index 9cd5471..7630d16 100644
--- a/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -3,7 +3,11 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
@@ -20,9 +24,24 @@
   }
 };
 
-// http://crbug.com/353039
 IN_PROC_BROWSER_TEST_F(AutomationApiTest, SanityCheck) {
+  ASSERT_EQ(1, browser()->tab_strip_model()->count());
+  content::WebContents* const tab =
+      browser()->tab_strip_model()->GetWebContentsAt(0);
+  content::RenderWidgetHost* rwh =
+      tab->GetRenderWidgetHostView()->GetRenderWidgetHost();
+  ASSERT_NE((content::RenderWidgetHost*)NULL, rwh)
+      << "Couldn't get RenderWidgetHost";
+  ASSERT_FALSE(rwh->IsFullAccessibilityModeForTesting());
+  ASSERT_FALSE(rwh->IsTreeOnlyAccessibilityModeForTesting());
+
   ASSERT_TRUE(RunComponentExtensionTest("automation/sanity_check")) << message_;
+
+  rwh = tab->GetRenderWidgetHostView()->GetRenderWidgetHost();
+  ASSERT_NE((content::RenderWidgetHost*)NULL, rwh)
+      << "Couldn't get RenderWidgetHost";
+  ASSERT_FALSE(rwh->IsFullAccessibilityModeForTesting());
+  ASSERT_TRUE(rwh->IsTreeOnlyAccessibilityModeForTesting());
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 9ed4a39..f48c91b 100644
--- a/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -214,10 +214,9 @@
   if (!rwh)
     return false;
 
-  // TODO(aboxhall): observe WebContents here - add to map??
   AutomationWebContentsObserver::CreateForWebContents(contents);
 
-  rwh->EnableFullAccessibilityMode();
+  rwh->EnableTreeOnlyAccessibilityMode();
 
   results_ = api::automation_internal::EnableCurrentTab::Results::Create(
       rwh->GetRoutingID());
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
index d556a1b..e4af08c 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_api.cc
@@ -10,7 +10,6 @@
 #include "base/memory/ref_counted.h"
 #include "chrome/browser/extensions/api/bluetooth/bluetooth_api_utils.h"
 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/common/extensions/api/bluetooth.h"
 #include "chrome/common/extensions/api/bluetooth/bluetooth_manifest_data.h"
 #include "content/public/browser/browser_thread.h"
@@ -247,7 +246,7 @@
 
 bool BluetoothGetDevicesFunction::DoWork(
     scoped_refptr<BluetoothAdapter> adapter) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   base::ListValue* device_list = new base::ListValue;
   SetResult(device_list);
@@ -272,7 +271,7 @@
 
 bool BluetoothGetDeviceFunction::DoWork(
     scoped_refptr<BluetoothAdapter> adapter) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   scoped_ptr<GetDevice::Params> params(GetDevice::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get() != NULL);
@@ -364,7 +363,7 @@
 }
 
 void BluetoothReadFunction::Work() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   if (!socket_.get())
     return;
@@ -416,7 +415,7 @@
 }
 
 void BluetoothWriteFunction::Work() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   if (socket_.get() == NULL)
     return;
diff --git a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc
index a444d63..cf63775 100644
--- a/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc
+++ b/chrome/browser/extensions/api/bluetooth/bluetooth_event_router_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/run_loop.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/api/bluetooth/bluetooth_event_router.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/common/extensions/api/bluetooth.h"
diff --git a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc
index 6a0b3e3..580c404 100644
--- a/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc
+++ b/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc
@@ -16,8 +16,8 @@
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/user_prefs.h"
 
-// Times out on win asan, http://crbug.com/166026
-#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
+// Times out on win syzyasan, http://crbug.com/166026
+#if defined(SYZYASAN)
 #define MAYBE_BookmarkManager DISABLED_BookmarkManager
 #else
 #define MAYBE_BookmarkManager BookmarkManager
diff --git a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
index 1756cf9..38431ad 100644
--- a/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
+++ b/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
@@ -65,7 +65,7 @@
 }
 
 void BrailleControllerImpl::TryLoadLibBrlApi() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (libbrlapi_loader_.loaded())
     return;
   // These versions of libbrlapi work the same for the functions we
@@ -82,7 +82,7 @@
 }
 
 scoped_ptr<DisplayState> BrailleControllerImpl::GetDisplayState() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   StartConnecting();
   scoped_ptr<DisplayState> display_state(new DisplayState);
   if (connection_.get() && connection_->Connected()) {
@@ -98,7 +98,7 @@
 }
 
 void BrailleControllerImpl::WriteDots(const std::string& cells) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (connection_ && connection_->Connected()) {
     size_t size;
     if (!connection_->GetDisplaySize(&size)) {
@@ -114,7 +114,7 @@
 }
 
 void BrailleControllerImpl::AddObserver(BrailleObserver* observer) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
                                base::Bind(
                                    &BrailleControllerImpl::StartConnecting,
@@ -125,7 +125,7 @@
 }
 
 void BrailleControllerImpl::RemoveObserver(BrailleObserver* observer) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   observers_.RemoveObserver(observer);
 }
 
@@ -145,7 +145,7 @@
 }
 
 void BrailleControllerImpl::StartConnecting() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (started_connecting_)
     return;
   started_connecting_ = true;
@@ -170,7 +170,7 @@
 }
 
 void BrailleControllerImpl::StartWatchingSocketDirOnFileThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   base::FilePath brlapi_dir(BRLAPI_SOCKETPATH);
   if (!file_path_watcher_.Watch(
           brlapi_dir, false, base::Bind(
@@ -182,7 +182,7 @@
 
 void BrailleControllerImpl::OnSocketDirChangedOnFileThread(
     const base::FilePath& path, bool error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (error) {
     LOG(ERROR) << "Error watching brlapi directory: " << path.value();
     return;
@@ -194,7 +194,7 @@
 }
 
 void BrailleControllerImpl::OnSocketDirChangedOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   VLOG(1) << "BrlAPI directory changed";
   // Every directory change resets the max retry time to the appropriate delay
   // into the future.
@@ -204,7 +204,7 @@
 }
 
 void BrailleControllerImpl::TryToConnect() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(libbrlapi_loader_.loaded());
   connect_scheduled_ = false;
   if (!connection_.get())
@@ -230,13 +230,13 @@
 }
 
 void BrailleControllerImpl::ResetRetryConnectHorizon() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   retry_connect_horizon_ = Time::Now() + TimeDelta::FromMilliseconds(
       kConnectRetryTimeout);
 }
 
 void BrailleControllerImpl::ScheduleTryToConnect() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   TimeDelta delay(TimeDelta::FromMilliseconds(kConnectionDelayMs));
   // Don't reschedule if there's already a connect scheduled or
   // the next attempt would fall outside of the retry limit.
@@ -256,7 +256,7 @@
 }
 
 void BrailleControllerImpl::Disconnect() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!connection_ || !connection_->Connected())
     return;
   connection_->Disconnect();
diff --git a/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc b/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
new file mode 100644
index 0000000..e0413cf
--- /dev/null
+++ b/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h"
+
+namespace extensions {
+namespace api {
+namespace braille_display_private {
+
+MockBrailleController::MockBrailleController()
+    : available_(false), observer_(NULL) {}
+
+scoped_ptr<DisplayState> MockBrailleController::GetDisplayState() {
+  scoped_ptr<DisplayState> state(new DisplayState());
+  state->available = available_;
+  if (available_)
+    state->text_cell_count.reset(new int(18));
+  return state.Pass();
+}
+
+void MockBrailleController::AddObserver(BrailleObserver* observer) {
+  CHECK(observer_ == NULL);
+  observer_ = observer;
+}
+
+void MockBrailleController::RemoveObserver(BrailleObserver* observer) {
+  CHECK(observer == observer_);
+  observer_ = NULL;
+}
+
+void MockBrailleController::SetAvailable(bool available) {
+  available_ = available;
+}
+
+BrailleObserver* MockBrailleController::GetObserver() const {
+  return observer_;
+}
+
+}  // namespace braille_display_private
+}  // namespace api
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h b/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h
new file mode 100644
index 0000000..6eeb8b4
--- /dev/null
+++ b/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_BRAILLE_DISPLAY_PRIVATE_MOCK_BRAILLE_CONTROLLER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_BRAILLE_DISPLAY_PRIVATE_MOCK_BRAILLE_CONTROLLER_H_
+
+#include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h"
+
+namespace extensions {
+namespace api {
+namespace braille_display_private {
+
+// Mock implementation of the BrailleController interface.
+class MockBrailleController : public StubBrailleController {
+ public:
+  MockBrailleController();
+
+  virtual scoped_ptr<DisplayState> GetDisplayState() OVERRIDE;
+  virtual void AddObserver(BrailleObserver* observer) OVERRIDE;
+  virtual void RemoveObserver(BrailleObserver* observer) OVERRIDE;
+
+  // Sets the available flag without calling the observer.
+  void SetAvailable(bool available);
+  BrailleObserver* GetObserver() const;
+
+ private:
+  bool available_;
+  BrailleObserver* observer_;
+};
+
+}  // namespace braille_display_private
+}  // namespace api
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_BRAILLE_DISPLAY_PRIVATE_MOCK_BRAILLE_CONTROLLER_H_
diff --git a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
index 573953b..3478197 100644
--- a/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
+++ b/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -218,7 +218,7 @@
 }
 
 void BrowsingDataRemoverFunction::OnBrowsingDataRemoverDone() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   this->SendResponse(true);
 
   Release();  // Balanced in RunImpl.
diff --git a/chrome/browser/extensions/api/cast_channel/cast_channel_api.cc b/chrome/browser/extensions/api/cast_channel/cast_channel_api.cc
index b662a15..cd9b8ba 100644
--- a/chrome/browser/extensions/api/cast_channel/cast_channel_api.cc
+++ b/chrome/browser/extensions/api/cast_channel/cast_channel_api.cc
@@ -79,7 +79,7 @@
 
 void CastChannelAPI::OnError(const CastSocket* socket,
                              cast_channel::ChannelError error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   ChannelInfo channel_info;
   socket->FillChannelInfo(&channel_info);
   channel_info.error_state = error;
@@ -92,7 +92,7 @@
 
 void CastChannelAPI::OnMessage(const CastSocket* socket,
                                const MessageInfo& message_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   ChannelInfo channel_info;
   socket->FillChannelInfo(&channel_info);
   scoped_ptr<base::ListValue> results =
@@ -132,7 +132,7 @@
 }
 
 int CastChannelAsyncApiFunction::AddSocket(CastSocket* socket) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(socket);
   DCHECK(manager_);
   const int id = manager_->Add(socket);
@@ -141,7 +141,7 @@
 }
 
 void CastChannelAsyncApiFunction::RemoveSocket(int channel_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(manager_);
   manager_->Remove(extension_->id(), channel_id);
 }
@@ -166,14 +166,14 @@
 }
 
 CastSocket* CastChannelAsyncApiFunction::GetSocket(int channel_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(manager_);
   return manager_->Get(extension_->id(), channel_id);
 }
 
 void CastChannelAsyncApiFunction::SetResultFromChannelInfo(
     const ChannelInfo& channel_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   SetResult(channel_info.ToValue().release());
 }
 
@@ -203,7 +203,7 @@
 }
 
 void CastChannelOpenFunction::OnOpen(int result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   SetResultFromSocket(new_channel_id_);
   AsyncWorkCompleted();
 }
@@ -227,7 +227,7 @@
 }
 
 void CastChannelSendFunction::OnSend(int result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (result < 0) {
     SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR);
   } else {
@@ -254,7 +254,7 @@
 }
 
 void CastChannelCloseFunction::OnClose(int result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   VLOG(1) << "CastChannelCloseFunction::OnClose result = " << result;
   if (result < 0) {
     SetResultFromError(cast_channel::CHANNEL_ERROR_SOCKET_ERROR);
diff --git a/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc b/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc
index fb6aba6..ea2a5b4 100644
--- a/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc
+++ b/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc
@@ -304,8 +304,7 @@
   // Start the in-process receiver that examines audio/video for the expected
   // test patterns.
   const scoped_refptr<media::cast::StandaloneCastEnvironment> cast_environment(
-      new media::cast::StandaloneCastEnvironment(
-          media::cast::CastLoggingConfig()));
+      new media::cast::StandaloneCastEnvironment());
   TestPatternReceiver* const receiver =
       new TestPatternReceiver(cast_environment, receiver_end_point);
   receiver->Start();
diff --git a/chrome/browser/extensions/api/cast_streaming/performance_test.cc b/chrome/browser/extensions/api/cast_streaming/performance_test.cc
index 38180aa..08f042a 100644
--- a/chrome/browser/extensions/api/cast_streaming/performance_test.cc
+++ b/chrome/browser/extensions/api/cast_streaming/performance_test.cc
@@ -546,10 +546,8 @@
 
     // Start the in-process receiver that examines audio/video for the expected
     // test patterns.
-    media::cast::CastLoggingConfig logging_config =
-        media::cast::GetDefaultCastReceiverLoggingConfig();
     scoped_refptr<media::cast::StandaloneCastEnvironment> cast_environment(
-        new media::cast::StandaloneCastEnvironment(logging_config));
+        new media::cast::StandaloneCastEnvironment);
     TestPatternReceiver* const receiver =
         new TestPatternReceiver(cast_environment, receiver_end_point);
     receiver->Start();
diff --git a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
index ab18eae..4c5f73e 100644
--- a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
+++ b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
@@ -49,19 +49,22 @@
         params->credentials,
         params->user_settings);
   } else {
-    if (!CloudPrintProxyServiceFactory::GetForProfile(GetProfile()))
+    CloudPrintProxyService* service =
+        CloudPrintProxyServiceFactory::GetForProfile(GetProfile());
+    if (!service)
       return false;
     scoped_ptr<base::DictionaryValue> user_setings(
         params->user_settings.ToValue());
-    CloudPrintProxyServiceFactory::GetForProfile(GetProfile())
-        ->EnableForUserWithRobot(params->credentials,
-                                 params->robot_email,
-                                 params->user_email,
-                                 *user_setings);
+    service->EnableForUserWithRobot(params->credentials,
+                                    params->robot_email,
+                                    params->user_email,
+                                    *user_setings);
   }
   SendResponse(true);
-#endif
   return true;
+#else
+  return false;
+#endif
 }
 
 CloudPrintPrivateGetHostNameFunction::CloudPrintPrivateGetHostNameFunction() {
@@ -85,26 +88,29 @@
 CloudPrintPrivateGetPrintersFunction::~CloudPrintPrivateGetPrintersFunction() {
 }
 
-void CloudPrintPrivateGetPrintersFunction::CollectPrinters() {
+void CloudPrintPrivateGetPrintersFunction::SendResults(
+    const std::vector<std::string>& printers) {
+  results_ = api::cloud_print_private::GetPrinters::Results::Create(printers);
+  SendResponse(true);
+}
+
+bool CloudPrintPrivateGetPrintersFunction::RunImpl() {
 #if defined(ENABLE_FULL_PRINTING)
   std::vector<std::string> result;
   if (CloudPrintTestsDelegate::instance()) {
-    result = CloudPrintTestsDelegate::instance()->GetPrinters();
+    SendResults(CloudPrintTestsDelegate::instance()->GetPrinters());
   } else {
-    CloudPrintProxyService::GetPrintersAvalibleForRegistration(&result);
+    CloudPrintProxyService* service =
+        CloudPrintProxyServiceFactory::GetForProfile(GetProfile());
+    if (!service)
+      return false;
+    service->GetPrinters(
+        base::Bind(&CloudPrintPrivateGetPrintersFunction::SendResults, this));
   }
-  results_ = api::cloud_print_private::GetPrinters::Results::Create(result);
-  content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
-      base::Bind(&CloudPrintPrivateGetPrintersFunction::SendResponse,
-                 this, true));
-#endif
-}
-
-
-bool CloudPrintPrivateGetPrintersFunction::RunImpl() {
-  content::BrowserThread::GetBlockingPool()->PostTask(FROM_HERE,
-      base::Bind(&CloudPrintPrivateGetPrintersFunction::CollectPrinters, this));
   return true;
+#else
+  return false;
+#endif
 }
 
 
diff --git a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h
index 9da2d44..8f1cc32 100644
--- a/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h
+++ b/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h
@@ -87,7 +87,8 @@
  protected:
   virtual ~CloudPrintPrivateGetPrintersFunction();
 
-  void CollectPrinters();
+ private:
+  void SendResults(const std::vector<std::string>& printers);
 
   // ExtensionFunction:
   virtual bool RunImpl() OVERRIDE;
diff --git a/chrome/browser/extensions/api/commands/command_service.cc b/chrome/browser/extensions/api/commands/command_service.cc
index a07d76b..73447bf 100644
--- a/chrome/browser/extensions/api/commands/command_service.cc
+++ b/chrome/browser/extensions/api/commands/command_service.cc
@@ -35,6 +35,8 @@
 
 using extensions::Extension;
 using extensions::ExtensionPrefs;
+using extensions::SettingsOverrides;
+using extensions::UIOverrides;
 
 namespace {
 
@@ -173,8 +175,6 @@
 // static
 bool CommandService::RemovesBookmarkShortcut(
     const extensions::Extension* extension) {
-  using extensions::UIOverrides;
-  using extensions::SettingsOverrides;
   const UIOverrides* ui_overrides = UIOverrides::Get(extension);
   const SettingsOverrides* settings_overrides =
       SettingsOverrides::Get(extension);
@@ -190,6 +190,23 @@
            IsEnabled());
 }
 
+// static
+bool CommandService::RemovesBookmarkOpenPagesShortcut(
+    const extensions::Extension* extension) {
+  const UIOverrides* ui_overrides = UIOverrides::Get(extension);
+  const SettingsOverrides* settings_overrides =
+      SettingsOverrides::Get(extension);
+
+  return ((settings_overrides &&
+           SettingsOverrides::RemovesBookmarkOpenPagesShortcut(
+               *settings_overrides)) ||
+          (ui_overrides &&
+           UIOverrides::RemovesBookmarkOpenPagesShortcut(*ui_overrides))) &&
+      extensions::PermissionsData::HasAPIPermission(
+          extension,
+          extensions::APIPermission::kBookmarkManagerPrivate);
+}
+
 bool CommandService::GetBrowserActionCommand(const std::string& extension_id,
                                              QueryType type,
                                              extensions::Command* command,
diff --git a/chrome/browser/extensions/api/commands/command_service.h b/chrome/browser/extensions/api/commands/command_service.h
index e3e2e95..0cbcd84 100644
--- a/chrome/browser/extensions/api/commands/command_service.h
+++ b/chrome/browser/extensions/api/commands/command_service.h
@@ -82,6 +82,11 @@
   // shortcut key.
   static bool RemovesBookmarkShortcut(const extensions::Extension* extension);
 
+  // Returns true if |extension| is permitted to and does remove the bookmark
+  // open pages shortcut key.
+  static bool RemovesBookmarkOpenPagesShortcut(
+      const extensions::Extension* extension);
+
   // Gets the command (if any) for the browser action of an extension given
   // its |extension_id|. The function consults the master list to see if
   // the command is active. Returns false if the extension has no browser
diff --git a/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc b/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
index 85d2441..b0afc15 100644
--- a/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
+++ b/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
@@ -11,8 +11,8 @@
 
 namespace extensions {
 
-// Times out on win asan, http://crbug.com/166026
-#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
+// Times out on win syzyasan, http://crbug.com/166026
+#if defined(SYZYASAN)
 #define MAYBE_ContextMenus DISABLED_ContextMenus
 #else
 #define MAYBE_ContextMenus ContextMenus
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.cc b/chrome/browser/extensions/api/cookies/cookies_api.cc
index 2255a09..78ff3d7 100644
--- a/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -232,7 +232,7 @@
 }
 
 void CookiesGetFunction::GetCookieOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   net::CookieStore* cookie_store =
       store_browser_context_->GetURLRequestContext()->cookie_store();
   cookies_helpers::GetCookieListFromStore(
@@ -265,7 +265,7 @@
 }
 
 void CookiesGetFunction::RespondOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   SendResponse(true);
 }
 
@@ -304,7 +304,7 @@
 }
 
 void CookiesGetAllFunction::GetAllCookiesOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   net::CookieStore* cookie_store =
       store_browser_context_->GetURLRequestContext()->cookie_store();
   cookies_helpers::GetCookieListFromStore(
@@ -330,7 +330,7 @@
 }
 
 void CookiesGetAllFunction::RespondOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   SendResponse(true);
 }
 
@@ -368,7 +368,7 @@
 }
 
 void CookiesSetFunction::SetCookieOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   net::CookieMonster* cookie_monster =
       store_browser_context_->GetURLRequestContext()
           ->cookie_store()
@@ -439,7 +439,7 @@
 }
 
 void CookiesSetFunction::RespondOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!success_) {
     std::string name =
         parsed_args_->details.name.get() ? *parsed_args_->details.name
@@ -484,7 +484,7 @@
 }
 
 void CookiesRemoveFunction::RemoveCookieOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Remove the cookie
   net::CookieStore* cookie_store =
@@ -510,7 +510,7 @@
 }
 
 void CookiesRemoveFunction::RespondOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   SendResponse(true);
 }
 
diff --git a/chrome/browser/extensions/api/cookies/cookies_apitest.cc b/chrome/browser/extensions/api/cookies/cookies_apitest.cc
index 1be7ba1..1144669 100644
--- a/chrome/browser/extensions/api/cookies/cookies_apitest.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_apitest.cc
@@ -8,8 +8,8 @@
 
 namespace extensions {
 
-// Times out on win asan, http://crbug.com/166026
-#if defined(OS_WIN) && defined(ADDRESS_SANITIZER)
+// Times out on win syzyasan, http://crbug.com/166026
+#if defined(SYZYASAN)
 #define MAYBE_Cookies DISABLED_Cookies
 #else
 #define MAYBE_Cookies Cookies
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc
index 622feda..46cc678 100644
--- a/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -494,8 +494,7 @@
             web_contents->GetURL().scheme());
         return false;
       }
-      agent_host_ = DevToolsAgentHost::GetOrCreateFor(
-          web_contents->GetRenderViewHost());
+      agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents);
     }
   } else if (debuggee_.extension_id) {
     extensions::ExtensionHost* extension_host =
diff --git a/chrome/browser/extensions/api/declarative/rules_cache_delegate.cc b/chrome/browser/extensions/api/declarative/rules_cache_delegate.cc
index d4bfcc6..78de68a 100644
--- a/chrome/browser/extensions/api/declarative/rules_cache_delegate.cc
+++ b/chrome/browser/extensions/api/declarative/rules_cache_delegate.cc
@@ -60,7 +60,7 @@
 // 2. does not create scoped_refptr holding the registry. (A short-lived
 // scoped_refptr might delete the rules registry before it is constructed.)
 void RulesCacheDelegate::Init(RulesRegistry* registry) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // WARNING: The first use of |registry_| will bind it to the calling thread
   // so don't use this here.
@@ -93,7 +93,7 @@
 
 void RulesCacheDelegate::WriteToStorage(const std::string& extension_id,
                                      scoped_ptr<base::Value> value) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!profile_)
     return;
 
@@ -111,7 +111,7 @@
 }
 
 void RulesCacheDelegate::CheckIfReady() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (notified_registry_ || !waiting_for_extensions_.empty())
     return;
 
@@ -148,7 +148,7 @@
 }
 
 void RulesCacheDelegate::ReadFromStorage(const std::string& extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!profile_)
     return;
 
@@ -177,7 +177,7 @@
 void RulesCacheDelegate::ReadFromStorageCallback(
     const std::string& extension_id,
     scoped_ptr<base::Value> value) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   content::BrowserThread::PostTask(
       rules_registry_thread_,
       FROM_HERE,
diff --git a/chrome/browser/extensions/api/declarative/rules_cache_delegate.h b/chrome/browser/extensions/api/declarative/rules_cache_delegate.h
index 7eccc86..f8bc312 100644
--- a/chrome/browser/extensions/api/declarative/rules_cache_delegate.h
+++ b/chrome/browser/extensions/api/declarative/rules_cache_delegate.h
@@ -42,7 +42,7 @@
                       scoped_ptr<base::Value> value);
 
   base::WeakPtr<RulesCacheDelegate> GetWeakPtr() {
-    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     return weak_ptr_factory_.GetWeakPtr();
   }
 
diff --git a/chrome/browser/extensions/api/declarative/rules_registry.cc b/chrome/browser/extensions/api/declarative/rules_registry.cc
index 0d6375a..d51416c 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry.cc
+++ b/chrome/browser/extensions/api/declarative/rules_registry.cc
@@ -95,7 +95,7 @@
 std::string RulesRegistry::AddRulesNoFill(
     const std::string& extension_id,
     const std::vector<linked_ptr<Rule> >& rules) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   // Verify that all rule IDs are new.
   for (std::vector<linked_ptr<Rule> >::const_iterator i =
@@ -128,7 +128,7 @@
 std::string RulesRegistry::AddRules(
     const std::string& extension_id,
     const std::vector<linked_ptr<Rule> >& rules) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   std::string error = CheckAndFillInOptionalRules(extension_id, rules);
   if (!error.empty())
@@ -141,7 +141,7 @@
 std::string RulesRegistry::RemoveRules(
     const std::string& extension_id,
     const std::vector<std::string>& rule_identifiers) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   std::string error = RemoveRulesImpl(extension_id, rule_identifiers);
 
@@ -168,7 +168,7 @@
 
 std::string RulesRegistry::RemoveAllRulesNoStoreUpdate(
     const std::string& extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   std::string error = RemoveAllRulesImpl(extension_id);
 
@@ -190,7 +190,7 @@
 void RulesRegistry::GetRules(const std::string& extension_id,
                              const std::vector<std::string>& rule_identifiers,
                              std::vector<linked_ptr<Rule> >* out) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   for (std::vector<std::string>::const_iterator i = rule_identifiers.begin();
       i != rule_identifiers.end(); ++i) {
@@ -203,7 +203,7 @@
 
 void RulesRegistry::GetAllRules(const std::string& extension_id,
                                 std::vector<linked_ptr<Rule> >* out) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   for (RulesDictionary::const_iterator i = rules_.begin();
       i != rules_.end(); ++i) {
@@ -214,21 +214,21 @@
 }
 
 void RulesRegistry::OnExtensionUnloaded(const std::string& extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
   std::string error = RemoveAllRulesImpl(extension_id);
   if (!error.empty())
     LOG(ERROR) << error;
 }
 
 void RulesRegistry::OnExtensionUninstalled(const std::string& extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
   std::string error = RemoveAllRulesNoStoreUpdate(extension_id);
   if (!error.empty())
     LOG(ERROR) << error;
 }
 
 void RulesRegistry::OnExtensionLoaded(const std::string& extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
   std::vector<linked_ptr<Rule> > rules;
   GetAllRules(extension_id, &rules);
   std::string error = AddRulesImpl(extension_id, rules);
@@ -252,7 +252,7 @@
 void RulesRegistry::DeserializeAndAddRules(
     const std::string& extension_id,
     scoped_ptr<base::Value> rules) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   AddRulesNoFill(extension_id, RulesFromValue(rules.get()));
 }
@@ -261,7 +261,7 @@
 }
 
 void RulesRegistry::MarkReady(base::Time storage_init_time) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   if (!storage_init_time.is_null()) {
     UMA_HISTOGRAM_TIMES("Extensions.DeclarativeRulesStorageInitialization",
@@ -272,7 +272,7 @@
 }
 
 void RulesRegistry::ProcessChangedRules(const std::string& extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(owner_thread()));
+  DCHECK_CURRENTLY_ON(owner_thread());
 
   DCHECK(ContainsKey(process_changed_rules_requested_, extension_id));
   process_changed_rules_requested_[extension_id] = NOT_SCHEDULED_FOR_PROCESSING;
diff --git a/chrome/browser/extensions/api/declarative/rules_registry.h b/chrome/browser/extensions/api/declarative/rules_registry.h
index d4a6ac2..775e4a3 100644
--- a/chrome/browser/extensions/api/declarative/rules_registry.h
+++ b/chrome/browser/extensions/api/declarative/rules_registry.h
@@ -196,7 +196,7 @@
   typedef std::map<ExtensionId, ProcessChangedRulesState> ProcessStateMap;
 
   base::WeakPtr<RulesRegistry> GetWeakPtr() {
-    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
     return weak_ptr_factory_.GetWeakPtr();
   }
 
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
index 8731d28..739d074 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action.cc
@@ -582,7 +582,7 @@
 //
 
 WebRequestRedirectAction::WebRequestRedirectAction(const GURL& redirect_url)
-    : WebRequestAction(ON_BEFORE_REQUEST,
+    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                        ACTION_REDIRECT_REQUEST,
                        std::numeric_limits<int>::min(),
                        STRATEGY_DEFAULT),
@@ -619,7 +619,7 @@
 
 WebRequestRedirectToTransparentImageAction::
     WebRequestRedirectToTransparentImageAction()
-    : WebRequestAction(ON_BEFORE_REQUEST,
+    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                        ACTION_REDIRECT_TO_TRANSPARENT_IMAGE,
                        std::numeric_limits<int>::min(),
                        STRATEGY_NONE) {}
@@ -649,7 +649,7 @@
 
 WebRequestRedirectToEmptyDocumentAction::
     WebRequestRedirectToEmptyDocumentAction()
-    : WebRequestAction(ON_BEFORE_REQUEST,
+    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                        ACTION_REDIRECT_TO_EMPTY_DOCUMENT,
                        std::numeric_limits<int>::min(),
                        STRATEGY_NONE) {}
@@ -680,7 +680,7 @@
 WebRequestRedirectByRegExAction::WebRequestRedirectByRegExAction(
     scoped_ptr<RE2> from_pattern,
     const std::string& to_pattern)
-    : WebRequestAction(ON_BEFORE_REQUEST,
+    : WebRequestAction(ON_BEFORE_REQUEST | ON_HEADERS_RECEIVED,
                        ACTION_REDIRECT_BY_REGEX_DOCUMENT,
                        std::numeric_limits<int>::min(),
                        STRATEGY_DEFAULT),
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
index 4952dc8..fbb7aa6 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc
@@ -279,6 +279,7 @@
       " \"redirectUrl\": \"http://www.foobar.com\""
       "}]";
   CheckActionNeedsAllUrls(kAction, ON_BEFORE_REQUEST);
+  CheckActionNeedsAllUrls(kAction, ON_HEADERS_RECEIVED);
 }
 
 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectByRegEx) {
@@ -442,6 +443,10 @@
                                    extension_->id(),
                                    action_set.get(),
                                    ON_BEFORE_REQUEST));
+  EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
+                                   extension_->id(),
+                                   action_set.get(),
+                                   ON_HEADERS_RECEIVED));
 }
 
 TEST_F(WebRequestActionWithThreadsTest, PermissionsToRedirectToEmptyDocument) {
@@ -456,6 +461,10 @@
                                    extension_->id(),
                                    action_set.get(),
                                    ON_BEFORE_REQUEST));
+  EXPECT_TRUE(ActionWorksOnRequest("http://test.org",
+                                   extension_->id(),
+                                   action_set.get(),
+                                   ON_HEADERS_RECEIVED));
 }
 
 TEST_F(WebRequestActionWithThreadsTest, PermissionsToIgnore) {
diff --git a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
index 7ef5524..0efc927 100644
--- a/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
+++ b/chrome/browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc
@@ -667,26 +667,28 @@
 
 TEST(WebRequestRulesRegistrySimpleTest, StageChecker) {
   // The contentType condition can only be evaluated during ON_HEADERS_RECEIVED
-  // but the redirect action can only be executed during ON_BEFORE_REQUEST.
+  // but the SetRequestHeader action can only be executed during
+  // ON_BEFORE_SEND_HEADERS.
   // Therefore, this is an inconsistent rule that needs to be flagged.
   const char kRule[] =
-      "{                                                                 \n"
-      "  \"id\": \"rule1\",                                              \n"
-      "  \"conditions\": [                                               \n"
-      "    {                                                             \n"
-      "      \"instanceType\": \"declarativeWebRequest.RequestMatcher\", \n"
-      "      \"url\": {\"hostSuffix\": \"foo.com\"},                     \n"
-      "      \"contentType\": [\"image/jpeg\"]                           \n"
-      "    }                                                             \n"
-      "  ],                                                              \n"
-      "  \"actions\": [                                                  \n"
-      "    {                                                             \n"
-      "      \"instanceType\": \"declarativeWebRequest.RedirectRequest\",\n"
-      "      \"redirectUrl\": \"http://bar.com\"                         \n"
-      "    }                                                             \n"
-      "  ],                                                              \n"
-      "  \"priority\": 200                                               \n"
-      "}                                                                 ";
+      "{                                                                  \n"
+      "  \"id\": \"rule1\",                                               \n"
+      "  \"conditions\": [                                                \n"
+      "    {                                                              \n"
+      "      \"instanceType\": \"declarativeWebRequest.RequestMatcher\",  \n"
+      "      \"url\": {\"hostSuffix\": \"foo.com\"},                      \n"
+      "      \"contentType\": [\"image/jpeg\"]                            \n"
+      "    }                                                              \n"
+      "  ],                                                               \n"
+      "  \"actions\": [                                                   \n"
+      "    {                                                              \n"
+      "      \"instanceType\": \"declarativeWebRequest.SetRequestHeader\",\n"
+      "      \"name\": \"Content-Type\",                                  \n"
+      "      \"value\": \"text/plain\"                                    \n"
+      "    }                                                              \n"
+      "  ],                                                               \n"
+      "  \"priority\": 200                                                \n"
+      "}                                                                  ";
 
   scoped_ptr<base::Value> value(base::JSONReader::Read(kRule));
   ASSERT_TRUE(value);
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 729a2c8..b6170b9 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -843,7 +843,8 @@
   } else {
     ExtensionErrorReporter::GetInstance()->ReportError(
         base::UTF8ToUTF16(JoinString(requirements_errors, ' ')),
-        true /* be noisy */);
+        true,   // Be noisy.
+        NULL);  // Caller expects no response.
   }
   Release();
 }
diff --git a/chrome/browser/extensions/api/dial/dial_api.cc b/chrome/browser/extensions/api/dial/dial_api.cc
index d33b4cf..36f9805 100644
--- a/chrome/browser/extensions/api/dial/dial_api.cc
+++ b/chrome/browser/extensions/api/dial/dial_api.cc
@@ -46,7 +46,7 @@
 DialAPI::~DialAPI() {}
 
 DialRegistry* DialAPI::dial_registry() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!dial_registry_.get()) {
     dial_registry_.reset(new DialRegistry(this,
         TimeDelta::FromSeconds(kDialRefreshIntervalSecs),
@@ -57,45 +57,45 @@
 }
 
 void DialAPI::OnListenerAdded(const EventListenerInfo& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::Bind(&DialAPI::NotifyListenerAddedOnIOThread, this));
 }
 
 void DialAPI::OnListenerRemoved(const EventListenerInfo& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::Bind(&DialAPI::NotifyListenerRemovedOnIOThread, this));
 }
 
 void DialAPI::NotifyListenerAddedOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   VLOG(1) << "DIAL device event listener added.";
   dial_registry()->OnListenerAdded();
 }
 
 void DialAPI::NotifyListenerRemovedOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   VLOG(1) << "DIAL device event listener removed";
   dial_registry()->OnListenerRemoved();
 }
 
 void DialAPI::OnDialDeviceEvent(const DialRegistry::DeviceList& devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       base::Bind(&DialAPI::SendEventOnUIThread, this, devices));
 }
 
 void DialAPI::OnDialError(const DialRegistry::DialErrorCode code) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
       base::Bind(&DialAPI::SendErrorOnUIThread, this, code));
 }
 
 void DialAPI::SendEventOnUIThread(const DialRegistry::DeviceList& devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::vector<linked_ptr<api::dial::DialDevice> > args;
   for (DialRegistry::DeviceList::const_iterator it = devices.begin();
@@ -113,7 +113,7 @@
 }
 
 void DialAPI::SendErrorOnUIThread(const DialRegistry::DialErrorCode code) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   api::dial::DialError dial_error;
   switch (code) {
@@ -152,19 +152,19 @@
 }
 
 bool DialDiscoverNowFunction::Prepare() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(browser_context());
   dial_ = DialAPIFactory::GetForBrowserContext(browser_context()).get();
   return true;
 }
 
 void DialDiscoverNowFunction::Work() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   result_ = dial_->dial_registry()->DiscoverNow();
 }
 
 bool DialDiscoverNowFunction::Respond() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!result_)
     error_ = kDialServiceError;
 
diff --git a/chrome/browser/extensions/api/dial/dial_registry.cc b/chrome/browser/extensions/api/dial/dial_registry.cc
index eb80c39..66d88b4 100644
--- a/chrome/browser/extensions/api/dial/dial_registry.cc
+++ b/chrome/browser/extensions/api/dial/dial_registry.cc
@@ -13,7 +13,6 @@
 #include "chrome/browser/extensions/api/dial/dial_api.h"
 #include "chrome/browser/extensions/api/dial/dial_device_data.h"
 #include "chrome/browser/extensions/api/dial/dial_service.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/net/chrome_net_log.h"
 #include "chrome/common/extensions/api/dial.h"
 
diff --git a/chrome/browser/extensions/api/dns/dns_api.cc b/chrome/browser/extensions/api/dns/dns_api.cc
deleted file mode 100644
index 7ae9dac..0000000
--- a/chrome/browser/extensions/api/dns/dns_api.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/dns/dns_api.h"
-
-#include "base/bind.h"
-#include "base/values.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
-#include "chrome/browser/io_thread.h"
-#include "chrome/common/extensions/api/dns.h"
-#include "content/public/browser/browser_thread.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_log.h"
-
-using content::BrowserThread;
-using extensions::api::dns::ResolveCallbackResolveInfo;
-
-namespace Resolve = extensions::api::dns::Resolve;
-
-namespace extensions {
-
-DnsResolveFunction::DnsResolveFunction()
-    : response_(false),
-      io_thread_(g_browser_process->io_thread()),
-      request_handle_(new net::HostResolver::RequestHandle()),
-      addresses_(new net::AddressList) {
-}
-
-DnsResolveFunction::~DnsResolveFunction() {}
-
-bool DnsResolveFunction::RunImpl() {
-  scoped_ptr<Resolve::Params> params(Resolve::Params::Create(*args_));
-  EXTENSION_FUNCTION_VALIDATE(params.get());
-
-  hostname_ = params->hostname;
-
-  bool result = BrowserThread::PostTask(
-      BrowserThread::IO, FROM_HERE,
-      base::Bind(&DnsResolveFunction::WorkOnIOThread, this));
-  DCHECK(result);
-  return true;
-}
-
-void DnsResolveFunction::WorkOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-
-  net::HostResolver* host_resolver =
-      HostResolverWrapper::GetInstance()->GetHostResolver(
-          io_thread_->globals()->host_resolver.get());
-  DCHECK(host_resolver);
-
-  // Yes, we are passing zero as the port. There are some interesting but not
-  // presently relevant reasons why HostResolver asks for the port of the
-  // hostname you'd like to resolve, even though it doesn't use that value in
-  // determining its answer.
-  net::HostPortPair host_port_pair(hostname_, 0);
-
-  net::HostResolver::RequestInfo request_info(host_port_pair);
-  int resolve_result = host_resolver->Resolve(
-      request_info,
-      net::DEFAULT_PRIORITY,
-      addresses_.get(),
-      base::Bind(&DnsResolveFunction::OnLookupFinished, this),
-      request_handle_.get(),
-      net::BoundNetLog());
-
-  // Balanced in OnLookupFinished.
-  AddRef();
-
-  if (resolve_result != net::ERR_IO_PENDING)
-    OnLookupFinished(resolve_result);
-}
-
-void DnsResolveFunction::RespondOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  SendResponse(response_);
-}
-
-void DnsResolveFunction::OnLookupFinished(int resolve_result) {
-  scoped_ptr<ResolveCallbackResolveInfo> resolve_info(
-      new ResolveCallbackResolveInfo());
-  resolve_info->result_code = resolve_result;
-  if (resolve_result == net::OK) {
-    DCHECK(!addresses_->empty());
-    resolve_info->address.reset(
-        new std::string(addresses_->front().ToStringWithoutPort()));
-  }
-  results_ = Resolve::Results::Create(*resolve_info);
-  response_ = true;
-
-  bool post_task_result = BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&DnsResolveFunction::RespondOnUIThread, this));
-  DCHECK(post_task_result);
-
-  Release();  // Added in WorkOnIOThread().
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/dns/dns_api.h b/chrome/browser/extensions/api/dns/dns_api.h
deleted file mode 100644
index c183304..0000000
--- a/chrome/browser/extensions/api/dns/dns_api.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_DNS_DNS_API_H_
-#define CHROME_BROWSER_EXTENSIONS_API_DNS_DNS_API_H_
-
-#include <string>
-
-#include "chrome/browser/io_thread.h"
-#include "extensions/browser/extension_function.h"
-#include "net/base/address_list.h"
-#include "net/base/completion_callback.h"
-#include "net/dns/host_resolver.h"
-
-class IOThread;
-
-namespace extensions {
-
-class DnsResolveFunction : public AsyncExtensionFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("dns.resolve", DNS_RESOLVE)
-
-  DnsResolveFunction();
-
- protected:
-  virtual ~DnsResolveFunction();
-
-  // ExtensionFunction:
-  virtual bool RunImpl() OVERRIDE;
-
-  void WorkOnIOThread();
-  void RespondOnUIThread();
-
- private:
-  void OnLookupFinished(int result);
-
-  std::string hostname_;
-
-  bool response_;  // The value sent in SendResponse().
-
-  // This instance is widely available through BrowserProcess, but we need to
-  // acquire it on the UI thread and then use it on the IO thread, so we keep a
-  // plain pointer to it here as we move from thread to thread.
-  IOThread* io_thread_;
-
-  scoped_ptr<net::HostResolver::RequestHandle> request_handle_;
-  scoped_ptr<net::AddressList> addresses_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_DNS_DNS_API_H_
diff --git a/chrome/browser/extensions/api/dns/dns_apitest.cc b/chrome/browser/extensions/api/dns/dns_apitest.cc
index 3e12984..0918425 100644
--- a/chrome/browser/extensions/api/dns/dns_apitest.cc
+++ b/chrome/browser/extensions/api/dns/dns_apitest.cc
@@ -4,11 +4,11 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "chrome/browser/extensions/api/dns/dns_api.h"
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
 #include "chrome/browser/extensions/api/dns/mock_host_resolver_creator.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "extensions/browser/api/dns/dns_api.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
 #include "extensions/common/switches.h"
 #include "net/base/net_errors.h"
 #include "net/base/net_util.h"
diff --git a/chrome/browser/extensions/api/dns/host_resolver_wrapper.cc b/chrome/browser/extensions/api/dns/host_resolver_wrapper.cc
deleted file mode 100644
index 1af73d6..0000000
--- a/chrome/browser/extensions/api/dns/host_resolver_wrapper.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
-
-namespace extensions {
-
-HostResolverWrapper::HostResolverWrapper()
-    : resolver_(NULL) {
-}
-
-// static
-HostResolverWrapper* HostResolverWrapper::GetInstance() {
-  return Singleton<extensions::HostResolverWrapper>::get();
-}
-
-net::HostResolver* HostResolverWrapper::GetHostResolver(
-    net::HostResolver* real_resolver) {
-  return resolver_ ? resolver_ : real_resolver;
-}
-
-void HostResolverWrapper::SetHostResolverForTesting(
-    net::HostResolver* mock_resolver) {
-  resolver_ = mock_resolver;
-}
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/api/dns/host_resolver_wrapper.h b/chrome/browser/extensions/api/dns/host_resolver_wrapper.h
deleted file mode 100644
index ea8dc9d..0000000
--- a/chrome/browser/extensions/api/dns/host_resolver_wrapper.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_API_DNS_HOST_RESOLVER_WRAPPER_H_
-#define CHROME_BROWSER_EXTENSIONS_API_DNS_HOST_RESOLVER_WRAPPER_H_
-
-#include "base/memory/singleton.h"
-#include "net/dns/host_resolver.h"
-
-namespace extensions {
-
-// Used for testing. In production code, this class does nothing interesting.
-// This class is a singleton that holds a pointer to a mock HostResolver, or
-// else to NULL. API classes that need to resolve hostnames ask this class for
-// the correct HostResolver to use, passing in the one that they want to use,
-// thereby avoiding most lifetime issues, and it will reply with either that
-// same one, or else the test version to use instead.
-//
-// This is a pretty complicated way to replace a single pointer with another.
-// TODO(miket): make the previous statement obsolete.
-class HostResolverWrapper {
- public:
-  static HostResolverWrapper* GetInstance();
-
-  // Given a pointer to a real host resolver, returns the same pointer or else
-  // a substitute MockHostResolver to use instead. If
-  // SetHostResolverForTesting() hasn't been called, then this method returns
-  // the supplied argument as its result.
-  net::HostResolver* GetHostResolver(net::HostResolver* real_resolver);
-
-  // Sets the MockHostResolver to return in GetHostResolver().
-  void SetHostResolverForTesting(net::HostResolver* mock_resolver);
-
- private:
-  HostResolverWrapper();
-  friend struct DefaultSingletonTraits<HostResolverWrapper>;
-
-  net::HostResolver* resolver_;
-
-  DISALLOW_COPY_AND_ASSIGN(HostResolverWrapper);
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_API_DNS_HOST_RESOLVER_WRAPPER_H_
diff --git a/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc b/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc
index fa49956..5111c3e 100644
--- a/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc
+++ b/chrome/browser/extensions/api/dns/mock_host_resolver_creator.cc
@@ -25,7 +25,7 @@
 
 net::MockHostResolver* MockHostResolverCreator::CreateMockHostResolver() {
   DCHECK(!mock_host_resolver_);
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   bool result = BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
@@ -47,7 +47,7 @@
 }
 
 void MockHostResolverCreator::DeleteMockHostResolver() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!mock_host_resolver_)
     return;
   resolver_event_.Reset();
diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
index a96091c..209ffb3 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -334,7 +334,7 @@
 
 void DownloadFileIconExtractorImpl::OnIconLoadComplete(
     float scale, const IconURLCallback& callback, gfx::Image* icon) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   callback.Run(!icon ? std::string() : webui::GetBitmapDataUrl(
       icon->ToImageSkia()->GetRepresentation(scale).sk_bitmap()));
 }
@@ -600,7 +600,7 @@
             downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY),
         determined_conflict_action_(
             downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     download_item->SetUserData(kKey, this);
   }
 
@@ -622,7 +622,7 @@
   void set_filename_change_callbacks(
       const base::Closure& no_change,
       const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     filename_no_change_ = no_change;
     filename_change_ = change;
     determined_filename_ = creator_suggested_filename_;
@@ -632,7 +632,7 @@
   }
 
   void ClearPendingDeterminers() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     determined_filename_.clear();
     determined_conflict_action_ =
       downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY;
@@ -644,7 +644,7 @@
   }
 
   void DeterminerRemoved(const std::string& extension_id) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     for (DeterminerInfoVector::iterator iter = determiners_.begin();
          iter != determiners_.end();) {
       if (iter->extension_id == extension_id) {
@@ -660,7 +660,7 @@
 
   void AddPendingDeterminer(const std::string& extension_id,
                             const base::Time& installed) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     for (size_t index = 0; index < determiners_.size(); ++index) {
       if (determiners_[index].extension_id == extension_id) {
         DCHECK(false) << extension_id;
@@ -671,7 +671,7 @@
   }
 
   bool DeterminerAlreadyReported(const std::string& extension_id) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     for (size_t index = 0; index < determiners_.size(); ++index) {
       if (determiners_[index].extension_id == extension_id) {
         return determiners_[index].reported;
@@ -683,7 +683,7 @@
   void CreatorSuggestedFilename(
       const base::FilePath& filename,
       downloads::FilenameConflictAction conflict_action) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     creator_suggested_filename_ = filename;
     creator_conflict_action_ = conflict_action;
   }
@@ -698,7 +698,7 @@
   }
 
   void ResetCreatorSuggestion() {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     creator_suggested_filename_.clear();
     creator_conflict_action_ =
       downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY;
@@ -712,7 +712,7 @@
       const std::string& extension_id,
       const base::FilePath& filename,
       downloads::FilenameConflictAction conflict_action) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     bool found_info = false;
     for (size_t index = 0; index < determiners_.size(); ++index) {
       if (determiners_[index].extension_id == extension_id) {
@@ -1043,7 +1043,7 @@
     downloads::FilenameConflictAction creator_conflict_action,
     DownloadItem* item,
     content::DownloadInterruptReason interrupt_reason) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   VLOG(1) << __FUNCTION__ << " " << item << " " << interrupt_reason;
   if (item) {
     DCHECK_EQ(content::DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
@@ -1226,7 +1226,7 @@
 }
 
 void DownloadsRemoveFileFunction::Done(bool success) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!success) {
     error_ = errors::kFileNotRemoved;
   }
@@ -1293,7 +1293,7 @@
 
 void DownloadsAcceptDangerFunction::DangerPromptCallback(
     int download_id, DownloadDangerPrompt::Action action) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DownloadItem* download_item =
       GetDownload(GetProfile(), include_incognito(), download_id);
   if (InvalidId(download_item, &error_) ||
@@ -1502,7 +1502,7 @@
 }
 
 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (Fault(url.empty(), errors::kIconNotFound, &error_)) {
     SendResponse(false);
     return;
@@ -1517,7 +1517,7 @@
     DownloadManager* manager)
     : profile_(profile),
       notifier_(manager, this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(profile_);
   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
                  content::Source<Profile>(profile_));
@@ -1529,7 +1529,7 @@
 }
 
 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)->
       event_router();
   if (router)
@@ -1582,7 +1582,7 @@
     const base::FilePath& suggested_path,
     const base::Closure& no_change,
     const FilenameChangedCallback& change) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ExtensionDownloadsEventRouterData* data =
       ExtensionDownloadsEventRouterData::Get(item);
   if (!data) {
@@ -1666,7 +1666,7 @@
     const base::FilePath& const_filename,
     downloads::FilenameConflictAction conflict_action,
     std::string* error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DownloadItem* item = GetDownload(profile, include_incognito, download_id);
   ExtensionDownloadsEventRouterData* data =
       item ? ExtensionDownloadsEventRouterData::Get(item) : NULL;
@@ -1702,7 +1702,7 @@
 
 void ExtensionDownloadsEventRouter::OnListenerRemoved(
     const extensions::EventListenerInfo& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DownloadManager* manager = notifier_.GetManager();
   if (!manager)
     return;
@@ -1744,7 +1744,7 @@
 
 void ExtensionDownloadsEventRouter::OnDownloadCreated(
     DownloadManager* manager, DownloadItem* download_item) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (download_item->IsTemporary())
     return;
 
@@ -1775,7 +1775,7 @@
 
 void ExtensionDownloadsEventRouter::OnDownloadUpdated(
     DownloadManager* manager, DownloadItem* download_item) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)->
       event_router();
   ExtensionDownloadsEventRouterData* data =
@@ -1845,7 +1845,7 @@
 
 void ExtensionDownloadsEventRouter::OnDownloadRemoved(
     DownloadManager* manager, DownloadItem* download_item) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (download_item->IsTemporary())
     return;
   DispatchEvent(downloads::OnErased::kEventName,
@@ -1860,7 +1860,7 @@
     bool include_incognito,
     const extensions::Event::WillDispatchCallback& will_dispatch_callback,
     base::Value* arg) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!extensions::ExtensionSystem::Get(profile_)->event_router())
     return;
   scoped_ptr<base::ListValue> args(new base::ListValue());
@@ -1894,7 +1894,7 @@
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   switch (type) {
     case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
       extensions::UnloadedExtensionInfo* unloaded =
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index 7b95e6d..165289b 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -732,7 +732,7 @@
   static void CopyInCompletion(bool* result,
                                base::WaitableEvent* done_event,
                                base::File::Error error) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     *result = error == base::File::FILE_OK;
     done_event->Signal();
   }
@@ -743,7 +743,7 @@
       const base::FilePath& temp_file,
       bool* result,
       base::WaitableEvent* done_event) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     context->operation_runner()->CopyInForeignFile(
         temp_file, path,
         base::Bind(&CopyInCompletion,
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index 05c62a5..44a0db9 100644
--- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -10,7 +10,6 @@
 
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/browser_action_test_util.h"
-#include "chrome/browser/extensions/dev_mode_bubble_controller.h"
 #include "chrome/browser/extensions/extension_action.h"
 #include "chrome/browser/extensions/extension_action_icon_factory.h"
 #include "chrome/browser/extensions/extension_action_manager.h"
@@ -29,6 +28,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/common/feature_switch.h"
 #include "grit/theme_resources.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/image/image_skia.h"
@@ -49,15 +49,10 @@
 
 // Views implementation of browser action button will return icon whose
 // background will be set.
-gfx::ImageSkia AddBackgroundForViews(const Extension* extension,
-                                     const gfx::ImageSkia& icon) {
+gfx::ImageSkia AddBackgroundForViews(const gfx::ImageSkia& icon) {
 #if defined(TOOLKIT_VIEWS)
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
   gfx::ImageSkia bg = *rb.GetImageSkiaNamed(IDR_BROWSER_ACTION);
-  // We may have a different background than the default - see
-  // BrowserActionButton::UpdateState.
-  if (extensions::DevModeBubbleController::IsDevModeExtension(extension))
-    bg = *rb.GetImageSkiaNamed(IDR_BROWSER_ACTION_HIGHLIGHT);
   return gfx::ImageSkiaOperations::CreateSuperimposedImage(bg, icon);
 #else
   return icon;
@@ -180,10 +175,10 @@
 
   EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
 
-  EXPECT_TRUE(ImagesAreEqualAtScale(
-      AddBackgroundForViews(extension, *action_icon.ToImageSkia()),
-      *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
-      1.0f));
+  EXPECT_TRUE(
+      ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()),
+                            *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
+                            1.0f));
 
   // Tell the extension to update the icon using path.
   GetBrowserActionsBar().Press(0);
@@ -198,10 +193,10 @@
   EXPECT_FALSE(
       action_icon.ToImageSkia()->HasRepresentation(2.0f));
 
-  EXPECT_TRUE(ImagesAreEqualAtScale(
-      AddBackgroundForViews(extension, *action_icon.ToImageSkia()),
-      *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
-      1.0f));
+  EXPECT_TRUE(
+      ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()),
+                            *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
+                            1.0f));
 
   // Tell the extension to update the icon using dictionary of ImageData
   // objects.
@@ -216,10 +211,10 @@
 
   EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
 
-  EXPECT_TRUE(ImagesAreEqualAtScale(
-      AddBackgroundForViews(extension, *action_icon.ToImageSkia()),
-      *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
-      1.0f));
+  EXPECT_TRUE(
+      ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()),
+                            *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
+                            1.0f));
 
   // Tell the extension to update the icon using dictionary of paths.
   GetBrowserActionsBar().Press(0);
@@ -233,10 +228,10 @@
 
   EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
 
-  EXPECT_TRUE(ImagesAreEqualAtScale(
-      AddBackgroundForViews(extension, *action_icon.ToImageSkia()),
-      *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
-      1.0f));
+  EXPECT_TRUE(
+      ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()),
+                            *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
+                            1.0f));
 
   // Tell the extension to update the icon using dictionary of ImageData
   // objects, but setting only size 19.
@@ -251,10 +246,10 @@
 
   EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
 
-  EXPECT_TRUE(ImagesAreEqualAtScale(
-      AddBackgroundForViews(extension, *action_icon.ToImageSkia()),
-      *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
-      1.0f));
+  EXPECT_TRUE(
+      ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()),
+                            *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
+                            1.0f));
 
   // Tell the extension to update the icon using dictionary of paths, but
   // setting only size 19.
@@ -269,10 +264,10 @@
 
   EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
 
-  EXPECT_TRUE(ImagesAreEqualAtScale(
-      AddBackgroundForViews(extension, *action_icon.ToImageSkia()),
-      *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
-      1.0f));
+  EXPECT_TRUE(
+      ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon.ToImageSkia()),
+                            *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
+                            1.0f));
 
   // Tell the extension to update the icon using dictionary of ImageData
   // objects, but setting only size 38.
@@ -295,7 +290,7 @@
       action_icon_skia->GetRepresentation(2.0f).sk_bitmap()));
 
   EXPECT_TRUE(
-      ImagesAreEqualAtScale(AddBackgroundForViews(extension, *action_icon_skia),
+      ImagesAreEqualAtScale(AddBackgroundForViews(*action_icon_skia),
                             *GetBrowserActionsBar().GetIcon(0).ToImageSkia(),
                             2.0f));
 
@@ -344,10 +339,11 @@
 // http://code.google.com/p/chromium/issues/detail?id=70829
 // Mac used to be ok, but then mac 10.5 started failing too. =(
 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DISABLED_BrowserActionPopup) {
-  const Extension* extension =
-      LoadExtension(test_data_dir_.AppendASCII("browser_action/popup"));
-  ASSERT_TRUE(extension) << message_;
+  ASSERT_TRUE(
+      LoadExtension(test_data_dir_.AppendASCII("browser_action/popup")));
   BrowserActionTestUtil actions_bar = GetBrowserActionsBar();
+  const Extension* extension = GetSingleLoadedExtension();
+  ASSERT_TRUE(extension) << message_;
 
   // The extension's popup's size grows by |growFactor| each click.
   const int growFactor = 500;
@@ -508,18 +504,19 @@
       browser()->profile())->extension_service();
 
   // The tooltips for each respective browser action.
-  const char kTooltipA[] = "Make this page red";
-  const char kTooltipB[] = "grow";
-  const char kTooltipC[] = "Test setPopup()";
+  const char kTooltipA[] = "Alpha";
+  const char kTooltipB[] = "Beta";
+  const char kTooltipC[] = "Gamma";
 
   const size_t size_before = service->extensions()->size();
 
-  const Extension* extension_a = LoadExtension(test_data_dir_.AppendASCII(
-      "browser_action/basics"));
-  const Extension* extension_b = LoadExtension(test_data_dir_.AppendASCII(
-      "browser_action/popup"));
-  const Extension* extension_c = LoadExtension(test_data_dir_.AppendASCII(
-      "browser_action/add_popup"));
+  base::FilePath test_dir = test_data_dir_.AppendASCII("browser_action");
+  const Extension* extension_a = InstallExtension(
+      test_dir.AppendASCII("empty_browser_action_alpha.crx"), 1);
+  const Extension* extension_b = InstallExtension(
+      test_dir.AppendASCII("empty_browser_action_beta.crx"), 1);
+  const Extension* extension_c = InstallExtension(
+      test_dir.AppendASCII("empty_browser_action_gamma.crx"), 1);
   ASSERT_TRUE(extension_a);
   ASSERT_TRUE(extension_b);
   ASSERT_TRUE(extension_c);
@@ -614,9 +611,9 @@
 // Disabled because of failures (crashes) on ASAN bot.
 // See http://crbug.com/98861.
 IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DISABLED_CloseBackgroundPage) {
-  const Extension* extension = LoadExtension(
-      test_data_dir_.AppendASCII("browser_action/close_background"));
-  ASSERT_TRUE(extension) << message_;
+  ASSERT_TRUE(LoadExtension(
+      test_data_dir_.AppendASCII("browser_action/close_background")));
+  const Extension* extension = GetSingleLoadedExtension();
 
   // There is a background page and a browser action with no badge text.
   extensions::ProcessManager* manager =
diff --git a/chrome/browser/extensions/api/feedback_private/feedback_service.cc b/chrome/browser/extensions/api/feedback_private/feedback_service.cc
index fbe271e..f32840c 100644
--- a/chrome/browser/extensions/api/feedback_private/feedback_service.cc
+++ b/chrome/browser/extensions/api/feedback_private/feedback_service.cc
@@ -68,8 +68,9 @@
 
 void FeedbackService::AttachedFileCallback(scoped_ptr<std::string> data,
                                            int64 /* total_blob_length */) {
-  feedback_data_->set_attached_file_uuid(std::string());
-  if (data.get())
+  if (!data.get())
+    feedback_data_->set_attached_file_uuid(std::string());
+  else
     feedback_data_->AttachAndCompressFileData(data.Pass());
 
   CompleteSendFeedback();
@@ -77,8 +78,9 @@
 
 void FeedbackService::ScreenshotCallback(scoped_ptr<std::string> data,
                                          int64 /* total_blob_length */) {
-  feedback_data_->set_screenshot_uuid(std::string());
-  if (data.get())
+  if (!data.get())
+    feedback_data_->set_screenshot_uuid(std::string());
+  else
     feedback_data_->set_image(data.Pass());
 
   CompleteSendFeedback();
@@ -118,8 +120,12 @@
   // b.) The associated data object exists, meaning that the data has been read
   //     and the read callback has updated the associated data on the feedback
   //     object.
-  bool attached_file_completed = feedback_data_->attached_file_uuid().empty();
-  bool screenshot_completed = feedback_data_->screenshot_uuid().empty();
+  bool attached_file_completed =
+      feedback_data_->attached_file_uuid().empty() ||
+      feedback_data_->attached_filedata();
+  bool screenshot_completed =
+      feedback_data_->screenshot_uuid().empty() ||
+      feedback_data_->image();
 
   if (screenshot_completed && attached_file_completed) {
     // Signal the feedback object that the data from the feedback page has been
diff --git a/chrome/browser/extensions/api/file_handlers/app_file_handler_util.cc b/chrome/browser/extensions/api/file_handlers/app_file_handler_util.cc
index f79af9f..2cea377 100644
--- a/chrome/browser/extensions/api/file_handlers/app_file_handler_util.cc
+++ b/chrome/browser/extensions/api/file_handlers/app_file_handler_util.cc
@@ -175,7 +175,7 @@
 WritableFileChecker::~WritableFileChecker() {}
 
 void WritableFileChecker::TaskDone() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (--outstanding_tasks_ == 0) {
     if (error_path_.empty())
       on_success_.Run();
@@ -193,7 +193,7 @@
 }
 
 void WritableFileChecker::CheckLocalWritableFiles() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
   std::string error;
   for (std::vector<base::FilePath>::const_iterator it = paths_.begin();
        it != paths_.end();
diff --git a/chrome/browser/extensions/api/file_system/file_system_api.cc b/chrome/browser/extensions/api/file_system/file_system_api.cc
index b01b0be..2e4d2e2 100644
--- a/chrome/browser/extensions/api/file_system/file_system_api.cc
+++ b/chrome/browser/extensions/api/file_system/file_system_api.cc
@@ -284,7 +284,7 @@
 
 void FileSystemEntryFunction::CheckWritableFiles(
     const std::vector<base::FilePath>& paths) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   app_file_handler_util::CheckWritableFiles(
       paths,
       GetProfile(),
@@ -297,7 +297,7 @@
 
 void FileSystemEntryFunction::RegisterFileSystemsAndSendResponse(
     const std::vector<base::FilePath>& paths) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!render_view_host_)
     return;
 
@@ -346,7 +346,7 @@
 
 void FileSystemEntryFunction::HandleWritableFileError(
     const base::FilePath& error_path) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   error_ = base::StringPrintf(kWritableFileErrorFormat,
                               error_path.BaseName().AsUTF8Unsafe().c_str());
   SendResponse(false);
@@ -383,7 +383,7 @@
 }
 
 void FileSystemGetWritableEntryFunction::CheckPermissionAndSendResponse() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (is_directory_ &&
       !extension_->HasAPIPermission(APIPermission::kFileSystemDirectory)) {
     error_ = kRequiresFileSystemDirectoryError;
@@ -395,7 +395,7 @@
 }
 
 void FileSystemGetWritableEntryFunction::SetIsDirectoryOnFileThread() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
   if (base::DirectoryExists(path_)) {
     is_directory_ = true;
   }
@@ -639,7 +639,7 @@
 void FileSystemChooseEntryFunction::SetInitialPathOnFileThread(
     const base::FilePath& suggested_name,
     const base::FilePath& previous_path) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
   if (!previous_path.empty() && base::DirectoryExists(previous_path)) {
     initial_path_ = previous_path.Append(suggested_name);
   } else {
diff --git a/chrome/browser/extensions/api/gcm/gcm_api.cc b/chrome/browser/extensions/api/gcm/gcm_api.cc
index f0196e3..65b1d49 100644
--- a/chrome/browser/extensions/api/gcm/gcm_api.cc
+++ b/chrome/browser/extensions/api/gcm/gcm_api.cc
@@ -122,7 +122,7 @@
 void GcmRegisterFunction::CompleteFunctionWithResult(
     const std::string& registration_id,
     gcm::GCMClient::Result result) {
-  SetResult(base::Value::CreateStringValue(registration_id));
+  SetResult(new base::StringValue(registration_id));
   SetError(GcmResultToError(result));
   SendResponse(gcm::GCMClient::SUCCESS == result);
 }
@@ -174,7 +174,7 @@
 void GcmSendFunction::CompleteFunctionWithResult(
     const std::string& message_id,
     gcm::GCMClient::Result result) {
-  SetResult(base::Value::CreateStringValue(message_id));
+  SetResult(new base::StringValue(message_id));
   SetError(GcmResultToError(result));
   SendResponse(gcm::GCMClient::SUCCESS == result);
 }
diff --git a/chrome/browser/extensions/api/hid/hid_api.cc b/chrome/browser/extensions/api/hid/hid_api.cc
index 11d559a..df184e5 100644
--- a/chrome/browser/extensions/api/hid/hid_api.cc
+++ b/chrome/browser/extensions/api/hid/hid_api.cc
@@ -8,12 +8,12 @@
 #include <vector>
 
 #include "chrome/common/extensions/api/hid.h"
-#include "chrome/common/extensions/permissions/usb_device_permission.h"
 #include "device/hid/hid_connection.h"
 #include "device/hid/hid_device_info.h"
 #include "device/hid/hid_service.h"
 #include "extensions/browser/api/api_resource_manager.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/usb_device_permission.h"
 #include "net/base/io_buffer.h"
 
 namespace hid = extensions::api::hid;
diff --git a/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc b/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
index a6ea917..1e1c7ef 100644
--- a/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
+++ b/chrome/browser/extensions/api/hotword_private/hotword_private_api.cc
@@ -76,6 +76,16 @@
   return true;
 }
 
+bool HotwordPrivateSetAudioLoggingEnabledFunction::RunImpl() {
+  scoped_ptr<api::hotword_private::SetEnabled::Params> params(
+      api::hotword_private::SetEnabled::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params.get());
+
+  PrefService* prefs = GetProfile()->GetPrefs();
+  prefs->SetBoolean(prefs::kHotwordAudioLoggingEnabled, params->state);
+  return true;
+}
+
 bool HotwordPrivateGetStatusFunction::RunImpl() {
   api::hotword_private::StatusDetails result;
 
@@ -88,8 +98,10 @@
 
   PrefService* prefs = GetProfile()->GetPrefs();
   result.enabled_set = prefs->HasPrefPath(prefs::kHotwordSearchEnabled);
-  result.enabled =
-      prefs->GetBoolean(prefs::kHotwordSearchEnabled);
+  result.enabled = prefs->GetBoolean(prefs::kHotwordSearchEnabled);
+  result.audio_logging_enabled = false;
+  if (hotword_service)
+    result.audio_logging_enabled = hotword_service->IsOptedIntoAudioLogging();
 
   SetResult(result.ToValue().release());
   return true;
diff --git a/chrome/browser/extensions/api/hotword_private/hotword_private_api.h b/chrome/browser/extensions/api/hotword_private/hotword_private_api.h
index 31ec13f..6c1e4c1 100644
--- a/chrome/browser/extensions/api/hotword_private/hotword_private_api.h
+++ b/chrome/browser/extensions/api/hotword_private/hotword_private_api.h
@@ -52,6 +52,19 @@
   virtual bool RunImpl() OVERRIDE;
 };
 
+class HotwordPrivateSetAudioLoggingEnabledFunction
+    : public ChromeSyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("hotwordPrivate.setAudioLoggingEnabled",
+                             HOTWORDPRIVATE_SETAUDIOLOGGINGENABLED)
+
+ protected:
+  virtual ~HotwordPrivateSetAudioLoggingEnabledFunction() {}
+
+  // ExtensionFunction:
+  virtual bool RunImpl() OVERRIDE;
+};
+
 class HotwordPrivateGetStatusFunction : public ChromeSyncExtensionFunction {
  public:
   DECLARE_EXTENSION_FUNCTION("hotwordPrivate.getStatus",
diff --git a/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc b/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc
index 5cf863f..bd7c08f 100644
--- a/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc
+++ b/chrome/browser/extensions/api/hotword_private/hotword_private_apitest.cc
@@ -79,6 +79,28 @@
   EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled));
 }
 
+IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, SetAudioLoggingEnabled) {
+  EXPECT_FALSE(service()->IsOptedIntoAudioLogging());
+  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
+      prefs::kHotwordAudioLoggingEnabled));
+
+  ExtensionTestMessageListener listenerTrue("ready", false);
+  EXPECT_TRUE(
+      RunComponentExtensionTest("setAudioLoggingEnableTrue")) << message_;
+  EXPECT_TRUE(listenerTrue.WaitUntilSatisfied());
+  EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(
+      prefs::kHotwordAudioLoggingEnabled));
+  EXPECT_TRUE(service()->IsOptedIntoAudioLogging());
+
+  ExtensionTestMessageListener listenerFalse("ready", false);
+  EXPECT_TRUE(
+      RunComponentExtensionTest("setAudioLoggingEnableFalse")) << message_;
+  EXPECT_TRUE(listenerFalse.WaitUntilSatisfied());
+  EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(
+      prefs::kHotwordAudioLoggingEnabled));
+  EXPECT_FALSE(service()->IsOptedIntoAudioLogging());
+}
+
 IN_PROC_BROWSER_TEST_F(HotwordPrivateApiTest, GetStatus) {
   EXPECT_TRUE(RunComponentExtensionTest("getEnabled")) << message_;
 }
diff --git a/chrome/browser/extensions/api/identity/account_tracker.cc b/chrome/browser/extensions/api/identity/account_tracker.cc
index 9d7b43f..daea002 100644
--- a/chrome/browser/extensions/api/identity/account_tracker.cc
+++ b/chrome/browser/extensions/api/identity/account_tracker.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/notification_details.h"
 #include "extensions/browser/extension_system.h"
 
diff --git a/chrome/browser/extensions/api/identity/account_tracker.h b/chrome/browser/extensions/api/identity/account_tracker.h
index cbf0055..1ec914c 100644
--- a/chrome/browser/extensions/api/identity/account_tracker.h
+++ b/chrome/browser/extensions/api/identity/account_tracker.h
@@ -9,8 +9,8 @@
 #include <string>
 
 #include "base/observer_list.h"
-#include "chrome/browser/signin/signin_manager_base.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/signin_error_controller.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 
diff --git a/chrome/browser/extensions/api/identity/account_tracker_unittest.cc b/chrome/browser/extensions/api/identity/account_tracker_unittest.cc
index e63b3d3..81d59ec 100644
--- a/chrome/browser/extensions/api/identity/account_tracker_unittest.cc
+++ b/chrome/browser/extensions/api/identity/account_tracker_unittest.cc
@@ -9,12 +9,12 @@
 
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
 #include "net/http/http_status_code.h"
@@ -272,7 +272,7 @@
   virtual void SetUp() OVERRIDE {
     TestingProfile::Builder builder;
     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                              FakeProfileOAuth2TokenServiceWrapper::Build);
+                              BuildFakeProfileOAuth2TokenService);
     builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
                               FakeSigninManagerBase::Build);
 
diff --git a/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc b/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
index 6899159..e694ee1 100644
--- a/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/escape.h"
 
diff --git a/chrome/browser/extensions/api/identity/identity_api.cc b/chrome/browser/extensions/api/identity/identity_api.cc
index 7881576..3c4521b 100644
--- a/chrome/browser/extensions/api/identity/identity_api.cc
+++ b/chrome/browser/extensions/api/identity/identity_api.cc
@@ -27,7 +27,7 @@
 #include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_function_dispatcher.h"
 #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/extensions/api/identity/identity_signin_flow.cc b/chrome/browser/extensions/api/identity/identity_signin_flow.cc
index 380f45a..eb2c005 100644
--- a/chrome/browser/extensions/api/identity/identity_signin_flow.cc
+++ b/chrome/browser/extensions/api/identity/identity_signin_flow.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 namespace extensions {
 
diff --git a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
index deff3ab..9c5c09b 100644
--- a/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
+++ b/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.cc
@@ -20,7 +20,7 @@
                                      const ErrorCallback& error_callback,
                                      const base::FilePath& source,
                                      const base::FilePath& target) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   StartHost();
 
@@ -40,7 +40,7 @@
                                       const ErrorCallback& error_callback,
                                       const base::FilePath& source,
                                       const base::FilePath& target) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   StartHost();
 
@@ -56,7 +56,7 @@
 }
 
 void ImageWriterUtilityClient::Cancel(const CancelCallback& cancel_callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!utility_process_host_) {
     // If we haven't connected, there is nothing to cancel.
diff --git a/chrome/browser/extensions/api/image_writer_private/operation.cc b/chrome/browser/extensions/api/image_writer_private/operation.cc
index 1ad4160..b12f1d4 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -41,7 +41,7 @@
 Operation::~Operation() {}
 
 void Operation::Cancel() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   stage_ = image_writer_api::STAGE_NONE;
 
@@ -88,7 +88,7 @@
 }
 
 void Operation::Unzip(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (IsCancelled()) {
     return;
   }
@@ -225,25 +225,25 @@
 }
 
 bool Operation::IsCancelled() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   return stage_ == image_writer_api::STAGE_NONE;
 }
 
 void Operation::AddCleanUpFunction(const base::Closure& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   cleanup_functions_.push_back(callback);
 }
 
 void Operation::CompleteAndContinue(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   SetProgress(kProgressComplete);
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, continuation);
 }
 
 #if !defined(OS_CHROMEOS)
 void Operation::StartUtilityClient() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (!image_writer_client_) {
     image_writer_client_ = new ImageWriterUtilityClient();
     AddCleanUpFunction(base::Bind(&Operation::StopUtilityClient, this));
@@ -251,7 +251,7 @@
 }
 
 void Operation::StopUtilityClient() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
@@ -259,7 +259,7 @@
 }
 
 void Operation::WriteImageProgress(int64 total_bytes, int64 curr_bytes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (IsCancelled()) {
     return;
   }
@@ -362,19 +362,19 @@
 }
 
 void Operation::OnUnzipFailure() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   Error(error::kUnzipGenericError);
 }
 
 void Operation::OnUnzipProgress(int64 total_bytes, int64 progress_bytes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   int progress_percent = kProgressComplete * progress_bytes / total_bytes;
   SetProgress(progress_percent);
 }
 
 void Operation::CleanUp() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   for (std::vector<base::Closure>::iterator it = cleanup_functions_.begin();
        it != cleanup_functions_.end();
        ++it) {
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc b/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
index d7fe5ec..ceaf76b 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
@@ -32,7 +32,7 @@
 }  // namespace
 
 void Operation::Write(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   SetStage(image_writer_api::STAGE_WRITE);
 
   BrowserThread::PostTask(
@@ -44,14 +44,14 @@
 }
 
 void Operation::VerifyWrite(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   // No verification is available in Chrome OS currently.
   continuation.Run();
 }
 
 void Operation::StartWriteOnUIThread(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ImageBurnerClient* burner =
       chromeos::DBusThreadManager::Get()->GetImageBurnerClient();
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index b17cc7f..794858b 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -139,7 +139,7 @@
 void OperationManager::OnProgress(const ExtensionId& extension_id,
                                   image_writer_api::Stage stage,
                                   int progress) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   image_writer_api::ProgressInfo info;
   info.stage = stage;
@@ -155,7 +155,7 @@
 }
 
 void OperationManager::OnComplete(const ExtensionId& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   scoped_ptr<base::ListValue> args(image_writer_api::OnWriteComplete::Create());
   scoped_ptr<Event> event(new Event(
@@ -171,7 +171,7 @@
                                image_writer_api::Stage stage,
                                int progress,
                                const std::string& error_message) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   image_writer_api::ProgressInfo info;
 
   DLOG(ERROR) << "ImageWriter error: " << error_message;
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc b/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc
index b5a7e1c..1cec1ec 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_nonchromeos.cc
@@ -16,7 +16,7 @@
 using content::BrowserThread;
 
 void Operation::Write(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (IsCancelled()) {
     return;
   }
@@ -44,7 +44,7 @@
 }
 
 void Operation::VerifyWrite(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (IsCancelled()) {
     return;
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
new file mode 100644
index 0000000..59d71da
--- /dev/null
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
+#include "chromeos/disks/disk_mount_manager.h"
+
+namespace extensions {
+
+const char kUnknownSDDiskModel[] = "SD Card";
+const char kUnknownUSBDiskModel[] = "USB Drive";
+
+using chromeos::disks::DiskMountManager;
+
+// The Chrome OS implementation takes advantage of the Chrome OS
+// DiskMountManager.  This does not expose whether the device is a removable or
+// fixed disk.  In fact, some SD cards will present themselves as fixed disks
+// (see http://crbug.com/340761).  Thus we just expose all USB and SD drives.
+// static
+void RemovableStorageProvider::GetAllDevices(DeviceListReadyCallback callback) {
+  scoped_refptr<StorageDeviceList> device_list(new StorageDeviceList());
+
+  DiskMountManager* disk_mount_manager = DiskMountManager::GetInstance();
+  const DiskMountManager::DiskMap& disks = disk_mount_manager->disks();
+
+  for (DiskMountManager::DiskMap::const_iterator iter = disks.begin();
+       iter != disks.end();
+       ++iter) {
+    const DiskMountManager::Disk& disk = *iter->second;
+    if (disk.is_parent() && !disk.on_boot_device() && disk.has_media() &&
+        (disk.device_type() == chromeos::DEVICE_TYPE_USB ||
+         disk.device_type() == chromeos::DEVICE_TYPE_SD)) {
+      linked_ptr<api::image_writer_private::RemovableStorageDevice> device(
+          new api::image_writer_private::RemovableStorageDevice());
+      device->storage_unit_id = disk.file_path();
+      device->capacity = disk.total_size_in_bytes();
+      device->vendor = disk.vendor_name();
+      device->model = disk.product_name();
+
+      if (device->model.empty() && device->vendor.empty()) {
+        if (disk.device_type() == chromeos::DEVICE_TYPE_USB) {
+          device->model = kUnknownUSBDiskModel;
+        } else {
+          device->model = kUnknownSDDiskModel;
+        }
+      }
+
+      device_list->data.push_back(device);
+    }
+  }
+
+  callback.Run(device_list, true);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
new file mode 100644
index 0000000..1c9daa0
--- /dev/null
+++ b/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc
@@ -0,0 +1,154 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
+#include "chromeos/disks/mock_disk_mount_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+namespace {
+
+using namespace chromeos::disks;
+using namespace api::image_writer_private;
+
+const char kDevicePathUSB[] = "/dev/test-usb";
+const char kDevicePathSD[] = "/dev/test-sd";
+const char kMountPath[] = "/test-mount";
+const char kDeviceId[] = "FFFF-FFFF";
+const char kDeviceName[] = "Test Device Name";
+const char kVendorName[] = "Test Vendor";
+const char kProductName[] = "Test Product";
+const uint64 kDeviceSize = 1024 * 1024 * 1024;
+
+const char kUnknownSDDiskModel[] = "SD Card";
+const char kUnknownUSBDiskModel[] = "USB Drive";
+
+class RemovableStorageProviderChromeOsUnitTest : public testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    disk_mount_manager_mock_ = new MockDiskMountManager();
+    DiskMountManager::InitializeForTesting(disk_mount_manager_mock_);
+    disk_mount_manager_mock_->SetupDefaultReplies();
+  }
+
+  virtual void TearDown() OVERRIDE { DiskMountManager::Shutdown(); }
+
+  void DevicesCallback(scoped_refptr<StorageDeviceList> devices, bool success) {
+    devices_ = devices;
+  }
+
+  void CreateDisk(const std::string& device_path,
+                  chromeos::DeviceType device_type,
+                  bool is_parent,
+                  bool has_media,
+                  bool on_boot_device) {
+    return CreateDisk(device_path,
+                      kVendorName,
+                      kProductName,
+                      device_type,
+                      is_parent,
+                      has_media,
+                      on_boot_device);
+  }
+
+  void CreateDisk(const std::string& device_path,
+                  const std::string& vendor_name,
+                  const std::string& product_name,
+                  chromeos::DeviceType device_type,
+                  bool is_parent,
+                  bool has_media,
+                  bool on_boot_device) {
+    DiskMountManager::MountPointInfo mount_info(
+        device_path,
+        kMountPath,
+        chromeos::MOUNT_TYPE_DEVICE,
+        chromeos::disks::MOUNT_CONDITION_NONE);
+    disk_mount_manager_mock_->CreateDiskEntryForMountDevice(mount_info,
+                                                            kDeviceId,
+                                                            kDeviceName,
+                                                            vendor_name,
+                                                            product_name,
+                                                            device_type,
+                                                            kDeviceSize,
+                                                            is_parent,
+                                                            has_media,
+                                                            on_boot_device);
+  }
+
+  // Checks if the DeviceList has a specific entry.
+  RemovableStorageDevice* FindDevice(StorageDeviceList* list,
+                                     const std::string& file_path) {
+    for (std::vector<linked_ptr<RemovableStorageDevice> >::const_iterator iter =
+             list->data.begin();
+         iter != list->data.end();
+         ++iter) {
+      if ((*iter)->storage_unit_id == file_path) {
+        return (*iter).get();
+      }
+    }
+    return NULL;
+  }
+
+  void ExpectDevice(StorageDeviceList* list,
+                    const std::string& device_path,
+                    const std::string& vendor,
+                    const std::string& model,
+                    uint64 capacity) {
+    RemovableStorageDevice* device = FindDevice(devices_, device_path);
+
+    ASSERT_TRUE(device != NULL);
+
+    EXPECT_EQ(device_path, device->storage_unit_id);
+    EXPECT_EQ(vendor, device->vendor);
+    EXPECT_EQ(model, device->model);
+    EXPECT_EQ(capacity, device->capacity);
+  }
+
+  MockDiskMountManager* disk_mount_manager_mock_;
+  scoped_refptr<StorageDeviceList> devices_;
+};
+
+}  // namespace
+
+// Tests that GetAllDevices works as expected, only exposing USB and SD cards
+// that are parents, have media and are not boot devices.  Other flags are
+// uninteresting or should not occur for these device types.
+TEST_F(RemovableStorageProviderChromeOsUnitTest, GetAllDevices) {
+  CreateDisk(kDevicePathUSB, chromeos::DEVICE_TYPE_USB, true, true, false);
+  CreateDisk(kDevicePathSD, chromeos::DEVICE_TYPE_SD, true, true, false);
+  CreateDisk("/dev/NotParent", chromeos::DEVICE_TYPE_USB, false, true, false);
+  CreateDisk("/dev/NoMedia", chromeos::DEVICE_TYPE_USB, true, false, false);
+  CreateDisk("/dev/OnBootDevice", chromeos::DEVICE_TYPE_USB, true, true, true);
+
+  RemovableStorageProvider::GetAllDevices(
+      base::Bind(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
+                 base::Unretained(this)));
+
+  ASSERT_EQ(2U, devices_->data.size());
+
+  ExpectDevice(
+      devices_, kDevicePathUSB, kVendorName, kProductName, kDeviceSize);
+  ExpectDevice(devices_, kDevicePathSD, kVendorName, kProductName, kDeviceSize);
+}
+
+// Tests that a USB drive with an empty vendor and product gets a generic name.
+TEST_F(RemovableStorageProviderChromeOsUnitTest, EmptyProductAndModel) {
+  CreateDisk(
+      kDevicePathUSB, "", "", chromeos::DEVICE_TYPE_USB, true, true, false);
+  CreateDisk(
+      kDevicePathSD, "", "", chromeos::DEVICE_TYPE_SD, true, true, false);
+
+  RemovableStorageProvider::GetAllDevices(
+      base::Bind(&RemovableStorageProviderChromeOsUnitTest::DevicesCallback,
+                 base::Unretained(this)));
+
+  ASSERT_EQ(2U, devices_->data.size());
+
+  ExpectDevice(devices_, kDevicePathUSB, "", kUnknownUSBDiskModel, kDeviceSize);
+  ExpectDevice(devices_, kDevicePathSD, "", kUnknownSDDiskModel, kDeviceSize);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
index 2e8fbd6..01dab54 100644
--- a/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
+++ b/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
@@ -31,7 +31,7 @@
 }
 
 void WriteFromUrlOperation::StartImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   GetDownloadTarget(base::Bind(
       &WriteFromUrlOperation::Download,
@@ -52,7 +52,7 @@
 
 void WriteFromUrlOperation::GetDownloadTarget(
     const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (IsCancelled()) {
     return;
   }
@@ -72,7 +72,7 @@
 }
 
 void WriteFromUrlOperation::Download(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (IsCancelled()) {
     return;
@@ -110,7 +110,7 @@
     const net::URLFetcher* source,
     int64 current,
     int64 total) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (IsCancelled()) {
     url_fetcher_.reset(NULL);
@@ -122,7 +122,7 @@
 }
 
 void WriteFromUrlOperation::OnURLFetchComplete(const net::URLFetcher* source) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
     SetProgress(kProgressComplete);
@@ -137,7 +137,7 @@
 }
 
 void WriteFromUrlOperation::VerifyDownload(const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (IsCancelled()) {
     return;
@@ -163,7 +163,7 @@
 void WriteFromUrlOperation::VerifyDownloadCompare(
     const base::Closure& continuation,
     const std::string& download_hash) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (download_hash != hash_) {
     Error(error::kDownloadHashError);
     return;
@@ -178,7 +178,7 @@
 
 void WriteFromUrlOperation::VerifyDownloadComplete(
     const base::Closure& continuation) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (IsCancelled()) {
     return;
   }
diff --git a/chrome/browser/extensions/api/input/input.cc b/chrome/browser/extensions/api/input/input.cc
index fcc5c7e..1a18af7 100644
--- a/chrome/browser/extensions/api/input/input.cc
+++ b/chrome/browser/extensions/api/input/input.cc
@@ -34,7 +34,7 @@
 namespace extensions {
 
 bool VirtualKeyboardPrivateInsertTextFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(USE_ASH)
   base::string16 text;
   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &text));
@@ -47,7 +47,7 @@
 }
 
 bool VirtualKeyboardPrivateMoveCursorFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(USE_ASH)
   if (!CommandLine::ForCurrentProcess()->HasSwitch(
       keyboard::switches::kEnableSwipeSelection)) {
@@ -70,7 +70,7 @@
 }
 
 bool VirtualKeyboardPrivateSendKeyEventFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(USE_ASH)
   base::Value* options_value = NULL;
   base::DictionaryValue* params = NULL;
@@ -102,7 +102,7 @@
 }
 
 bool VirtualKeyboardPrivateHideKeyboardFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(USE_ASH)
   UMA_HISTOGRAM_ENUMERATION(
       "VirtualKeyboard.KeyboardControlEvent",
@@ -122,7 +122,7 @@
 }
 
 bool VirtualKeyboardPrivateLockKeyboardFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(USE_ASH)
   bool lock;
   EXTENSION_FUNCTION_VALIDATE(args_->GetBoolean(0, &lock));
@@ -135,7 +135,7 @@
 }
 
 bool VirtualKeyboardPrivateKeyboardLoadedFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(USE_ASH)
   keyboard::MarkKeyboardLoadFinished();
   base::UserMetricsAction("VirtualKeyboardLoaded");
@@ -147,7 +147,7 @@
 }
 
 bool VirtualKeyboardPrivateGetKeyboardConfigFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(USE_ASH)
   base::DictionaryValue* results = new base::DictionaryValue();
   results->SetString("layout", keyboard::GetKeyboardLayout());
diff --git a/chrome/browser/extensions/api/input_ime/OWNERS b/chrome/browser/extensions/api/input_ime/OWNERS
index 24d7cbb..a6b0311 100644
--- a/chrome/browser/extensions/api/input_ime/OWNERS
+++ b/chrome/browser/extensions/api/input_ime/OWNERS
@@ -1,2 +1,6 @@
+# primary reviewer
+shuchen@chromium.org
+
+# backup reviewer
 komatsu@chromium.org
 nona@chromium.org
diff --git a/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index a146960..a309e41 100644
--- a/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -8,7 +8,9 @@
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/input_method/input_method_engine.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/common/extensions/api/input_ime.h"
 #include "chrome/common/extensions/api/input_ime/input_components_handler.h"
 #include "content/public/browser/notification_details.h"
@@ -85,7 +87,16 @@
 class ImeObserver : public InputMethodEngineInterface::Observer {
  public:
   ImeObserver(Profile* profile, const std::string& extension_id)
-      : profile_(profile), extension_id_(extension_id) {}
+      : profile_(profile), extension_id_(extension_id) {
+    // The original profile for login screen is called signin profile.
+    // And the active profile is the incognito profile based on signin profile.
+    // So if |profile| is signin profile, we need to make sure the
+    // observer runs under its incognito profile, because the component
+    // extensions were installed under its incognito profile.
+    if (ProfileHelper::IsSigninProfile(profile)) {
+      profile_ = ProfileManager::GetActiveUserProfile();
+    }
+  }
 
   virtual ~ImeObserver() {}
 
diff --git a/chrome/browser/extensions/api/location/location_manager.cc b/chrome/browser/extensions/api/location/location_manager.cc
index 25c1857..35ed634 100644
--- a/chrome/browser/extensions/api/location/location_manager.cc
+++ b/chrome/browser/extensions/api/location/location_manager.cc
@@ -213,7 +213,7 @@
       extension_id_(extension_id),
       location_manager_(location_manager) {
   // TODO(vadimt): use request_info.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (time_between_updates_ms) {
     update_policies_.push_back(
@@ -229,7 +229,7 @@
 }
 
 void LocationRequest::Initialize() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   callback_ = base::Bind(&LocationRequest::OnLocationUpdate,
                          base::Unretained(this));
 
@@ -241,18 +241,18 @@
 }
 
 void LocationRequest::GrantPermission() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices();
 }
 
 LocationRequest::~LocationRequest() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   content::GeolocationProvider::GetInstance()->RemoveLocationUpdateCallback(
       callback_);
 }
 
 void LocationRequest::AddObserverOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // TODO(vadimt): This can get a location cached by GeolocationProvider,
   // contrary to the API definition which says that creating a location watch
@@ -262,7 +262,7 @@
 }
 
 void LocationRequest::OnLocationUpdate(const content::Geoposition& position) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (ShouldSendUpdate(position)) {
     OnPositionReported(position);
     BrowserThread::PostTask(
@@ -277,7 +277,7 @@
 }
 
 bool LocationRequest::ShouldSendUpdate(const content::Geoposition& position) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   for (UpdatePolicyVector::iterator it = update_policies_.begin();
        it != update_policies_.end();
        ++it) {
@@ -289,7 +289,7 @@
 }
 
 void LocationRequest::OnPositionReported(const content::Geoposition& position) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   for (UpdatePolicyVector::iterator it = update_policies_.begin();
        it != update_policies_.end();
        ++it) {
@@ -310,7 +310,7 @@
     const std::string& request_name,
     const double* distance_update_threshold_meters,
     const double* time_between_updates_ms) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // TODO(vadimt): Consider resuming requests after restarting the browser.
 
   // Override any old request with the same name.
@@ -329,7 +329,7 @@
 
 void LocationManager::RemoveLocationRequest(const std::string& extension_id,
                                             const std::string& name) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::pair<LocationRequestMap::iterator, LocationRequestMap::iterator>
       extension_range = location_requests_.equal_range(extension_id);
@@ -369,7 +369,7 @@
     const std::string& extension_id,
     const std::string& request_name,
     const content::Geoposition& position) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   scoped_ptr<base::ListValue> args(new base::ListValue());
   std::string event_name;
@@ -400,7 +400,7 @@
 void LocationManager::Observe(int type,
                               const content::NotificationSource& source,
                               const content::NotificationDetails& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   switch (type) {
     case chrome::NOTIFICATION_EXTENSION_LOADED: {
diff --git a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
index 5635f80..2a595cc 100644
--- a/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
+++ b/chrome/browser/extensions/api/log_private/log_private_api_chromeos.cc
@@ -105,7 +105,7 @@
 }
 
 void LogPrivateAPI::OnAddEntry(const net::NetLog::Entry& entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!pending_entries_.get()) {
     pending_entries_.reset(new base::ListValue());
     BrowserThread::PostDelayedTask(
@@ -125,7 +125,7 @@
 }
 
 void LogPrivateAPI::AddEntriesOnUI(scoped_ptr<base::ListValue> value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   for (std::set<std::string>::iterator ix = net_internal_watches_.begin();
        ix != net_internal_watches_.end(); ++ix) {
@@ -140,7 +140,7 @@
 }
 
 void LogPrivateAPI::MaybeStartNetInternalLogging() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!logging_net_internals_) {
     g_browser_process->io_thread()->net_log()->AddThreadSafeObserver(
         this, net::NetLog::LOG_ALL_BUT_BYTES);
@@ -158,7 +158,7 @@
 }
 
 void LogPrivateAPI::StopNetInternalLogging() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (net_log() && logging_net_internals_) {
     net_log()->RemoveThreadSafeObserver(this);
     logging_net_internals_ = false;
diff --git a/chrome/browser/extensions/api/management/management_browsertest.cc b/chrome/browser/extensions/api/management/management_browsertest.cc
index 29bedb2..c0aec95 100644
--- a/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -425,8 +425,12 @@
   // of external_extensions.json before this test function starts.
 
   EXPECT_TRUE(pending_extension_manager->AddFromExternalUpdateUrl(
-      kExtensionId, GURL("http://localhost/autoupdate/manifest"),
-      Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS, false));
+      kExtensionId,
+      std::string(),
+      GURL("http://localhost/autoupdate/manifest"),
+      Manifest::EXTERNAL_PREF_DOWNLOAD,
+      Extension::NO_FLAGS,
+      false));
 
   // Run autoupdate and make sure version 2 of the extension was installed.
   service->updater()->CheckNow(params);
@@ -449,8 +453,12 @@
   // Try to install the extension again from an external source. It should fail
   // because of the killbit.
   EXPECT_FALSE(pending_extension_manager->AddFromExternalUpdateUrl(
-      kExtensionId, GURL("http://localhost/autoupdate/manifest"),
-      Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS, false));
+      kExtensionId,
+      std::string(),
+      GURL("http://localhost/autoupdate/manifest"),
+      Manifest::EXTERNAL_PREF_DOWNLOAD,
+      Extension::NO_FLAGS,
+      false));
   EXPECT_FALSE(pending_extension_manager->IsIdPending(kExtensionId))
       << "External reinstall of a killed extension shouldn't work.";
   EXPECT_TRUE(extension_prefs->IsExternalExtensionUninstalled(kExtensionId))
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
index 7d07dec..10bd8fb 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
@@ -34,7 +34,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/common/extensions/api/media_galleries.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "chrome/common/pref_names.h"
 #include "components/storage_monitor/storage_info.h"
 #include "components/web_modal/web_contents_modal_dialog_manager.h"
@@ -49,6 +48,7 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "grit/generated_resources.h"
 #include "net/base/mime_sniffer.h"
@@ -176,11 +176,11 @@
     if (has_read_permission) {
       content::ChildProcessSecurityPolicy* policy =
           content::ChildProcessSecurityPolicy::GetInstance();
-      policy->GrantReadFileSystem(child_id, filesystems[i].fsid);
+      policy->GrantReadFile(child_id, filesystems[i].path);
       if (has_delete_permission) {
-        policy->GrantDeleteFromFileSystem(child_id, filesystems[i].fsid);
+        policy->GrantDeleteFrom(child_id, filesystems[i].path);
         if (has_copy_to_permission) {
-          policy->GrantCopyIntoFileSystem(child_id, filesystems[i].fsid);
+          policy->GrantCopyInto(child_id, filesystems[i].path);
         }
       }
     }
@@ -262,7 +262,7 @@
 MediaGalleriesEventRouter::MediaGalleriesEventRouter(
     content::BrowserContext* context)
     : profile_(Profile::FromBrowserContext(context)), weak_ptr_factory_(this) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(profile_);
   media_scan_manager()->AddObserver(profile_, this);
 }
@@ -271,7 +271,7 @@
 }
 
 void MediaGalleriesEventRouter::Shutdown() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   weak_ptr_factory_.InvalidateWeakPtrs();
   media_scan_manager()->RemoveObserver(profile_);
   media_scan_manager()->CancelScansForProfile(profile_);
@@ -353,7 +353,7 @@
     const std::string& extension_id,
     const std::string& event_name,
     scoped_ptr<base::ListValue> event_args) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   EventRouter* router =
       extensions::ExtensionSystem::Get(profile_)->event_router();
   if (!router->ExtensionHasEventListener(extension_id, event_name))
@@ -657,7 +657,7 @@
 }
 
 void MediaGalleriesStartMediaScanFunction::OnPreferencesInit() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   MediaGalleriesEventRouter* api = MediaGalleriesEventRouter::Get(GetProfile());
   if (!api->ExtensionHasScanProgressListener(GetExtension()->id())) {
     error_ = kMissingEventListener;
@@ -685,7 +685,7 @@
 }
 
 void MediaGalleriesCancelMediaScanFunction::OnPreferencesInit() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   media_scan_manager()->CancelScan(GetProfile(), GetExtension());
   SendResponse(true);
 }
@@ -716,7 +716,7 @@
 }
 
 void MediaGalleriesAddScanResultsFunction::OnPreferencesInit() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const Extension* extension = GetExtension();
   MediaGalleriesPreferences* preferences =
       media_file_system_registry()->GetPreferences(GetProfile());
@@ -789,7 +789,7 @@
 
 void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
     bool mime_type_only, const std::string& blob_uuid) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // BlobReader is self-deleting.
   BlobReader* reader = new BlobReader(
@@ -804,7 +804,7 @@
 void MediaGalleriesGetMetadataFunction::SniffMimeType(
     bool mime_type_only, const std::string& blob_uuid,
     scoped_ptr<std::string> blob_header, int64 total_blob_length) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   std::string mime_type;
   bool mime_type_sniffed = net::SniffMimeTypeFromLocalData(
diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
index e2f9070..45a1a5f 100644
--- a/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
+++ b/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc
@@ -195,7 +195,7 @@
   // This function makes a single fake gallery. This is needed to test platforms
   // with no default media galleries, such as CHROMEOS. This fake gallery is
   // pre-populated with a test.jpg and test.txt.
-  void MakeSingleFakeGallery() {
+  void MakeSingleFakeGallery(MediaGalleryPrefId* pref_id) {
     ASSERT_FALSE(fake_gallery_temp_dir_.IsValid());
     ASSERT_TRUE(fake_gallery_temp_dir_.CreateUniqueTempDir());
 
@@ -204,15 +204,18 @@
     MediaGalleryPrefInfo gallery_info;
     ASSERT_FALSE(preferences->LookUpGalleryByPath(fake_gallery_temp_dir_.path(),
                                                   &gallery_info));
-    preferences->AddGallery(gallery_info.device_id,
-                            gallery_info.path,
-                            MediaGalleryPrefInfo::kAutoDetected,
-                            gallery_info.volume_label,
-                            gallery_info.vendor_name,
-                            gallery_info.model_name,
-                            gallery_info.total_size_in_bytes,
-                            gallery_info.last_attach_time,
-                            0, 0, 0);
+    MediaGalleryPrefId id = preferences->AddGallery(
+        gallery_info.device_id,
+        gallery_info.path,
+        MediaGalleryPrefInfo::kAutoDetected,
+        gallery_info.volume_label,
+        gallery_info.vendor_name,
+        gallery_info.model_name,
+        gallery_info.total_size_in_bytes,
+        gallery_info.last_attach_time,
+        0, 0, 0);
+    if (pref_id)
+      *pref_id = id;
 
     content::RunAllPendingInMessageLoop();
 
@@ -427,7 +430,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
                        MAYBE_MediaGalleriesNoAccess) {
-  MakeSingleFakeGallery();
+  MakeSingleFakeGallery(NULL);
 
   base::ListValue custom_args;
   custom_args.AppendInteger(num_galleries() + 1);
@@ -448,7 +451,7 @@
 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
                        MediaGalleriesRead) {
   RemoveAllGalleries();
-  MakeSingleFakeGallery();
+  MakeSingleFakeGallery(NULL);
   base::ListValue custom_args;
   custom_args.AppendInteger(test_jpg_size());
 
@@ -466,13 +469,13 @@
 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
                        MAYBE_MediaGalleriesCopyTo) {
   RemoveAllGalleries();
-  MakeSingleFakeGallery();
+  MakeSingleFakeGallery(NULL);
   ASSERT_TRUE(RunMediaGalleriesTest("copy_to_access")) << message_;
 }
 
 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest,
                        MediaGalleriesDelete) {
-  MakeSingleFakeGallery();
+  MakeSingleFakeGallery(NULL);
   base::ListValue custom_args;
   custom_args.AppendInteger(num_galleries() + 1);
   ASSERT_TRUE(RunMediaGalleriesTestWithArg("delete_access", custom_args))
@@ -584,9 +587,22 @@
   ASSERT_TRUE(RunMediaGalleriesTest("scan")) << message_;
 }
 
+IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, ToURL) {
+  RemoveAllGalleries();
+  MediaGalleryPrefId pref_id;
+  MakeSingleFakeGallery(&pref_id);
+
+  base::ListValue custom_args;
+  custom_args.AppendInteger(base::checked_cast<int>(pref_id));
+  custom_args.AppendString(
+      browser()->profile()->GetPath().BaseName().MaybeAsASCII());
+
+  ASSERT_TRUE(RunMediaGalleriesTestWithArg("tourl", custom_args)) << message_;
+}
+
 IN_PROC_BROWSER_TEST_F(MediaGalleriesPlatformAppBrowserTest, GetMetadata) {
   RemoveAllGalleries();
-  MakeSingleFakeGallery();
+  MakeSingleFakeGallery(NULL);
 
   AddFileToSingleFakeGallery(media::GetTestDataFilePath("90rotation.mp4"));
   AddFileToSingleFakeGallery(media::GetTestDataFilePath("id3_png_test.mp3"));
diff --git a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc
index 2da647a..539ac30 100644
--- a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.cc
@@ -38,7 +38,7 @@
     base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router,
     MediaGalleryPrefId gallery_id,
     const std::set<std::string>& extension_ids) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (event_router.get())
     event_router->OnGalleryChanged(gallery_id, extension_ids);
 }
@@ -134,14 +134,14 @@
       gallery_id_(gallery_id),
       on_destroyed_callback_(on_destroyed_callback),
       weak_ptr_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   gallery_path_ = path;
   AddExtension(extension_id);
 }
 
 void GalleryWatchManager::GalleryFilePathWatcher::AddExtension(
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (ContainsKey(extension_watch_info_map_, extension_id))
     return;
   extension_watch_info_map_[extension_id] = base::Time();
@@ -150,19 +150,19 @@
 
 void GalleryWatchManager::GalleryFilePathWatcher::RemoveExtension(
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (extension_watch_info_map_.erase(extension_id) == 1)
     Release();
 }
 
 void GalleryWatchManager::GalleryFilePathWatcher::OnExtensionUnloaded(
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   RemoveExtensionReferences(extension_id);
 }
 
 bool GalleryWatchManager::GalleryFilePathWatcher::SetupWatch() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return file_watcher_.Watch(
       gallery_path_, true,
       base::Bind(&GalleryFilePathWatcher::OnFilePathChanged,
@@ -170,7 +170,7 @@
 }
 
 void GalleryWatchManager::GalleryFilePathWatcher::RemoveAllWatchReferences() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   std::set<std::string> extension_ids;
   for (ExtensionWatchInfoMap::iterator iter = extension_watch_info_map_.begin();
        iter != extension_watch_info_map_.end(); ++iter)
@@ -182,14 +182,14 @@
 }
 
 GalleryWatchManager::GalleryFilePathWatcher::~GalleryFilePathWatcher() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   on_destroyed_callback_.Run();
 }
 
 void GalleryWatchManager::GalleryFilePathWatcher::OnFilePathChanged(
     const base::FilePath& path,
     bool error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (error || (path != gallery_path_))
     return;
 
@@ -220,7 +220,7 @@
 
 void GalleryWatchManager::GalleryFilePathWatcher::RemoveExtensionReferences(
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   ExtensionWatchInfoMap::iterator it =
       extension_watch_info_map_.find(extension_id);
   if (it == extension_watch_info_map_.end())
@@ -236,7 +236,7 @@
 // static
 GalleryWatchManager* GalleryWatchManager::GetForProfile(
     void* profile_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(profile_id);
   bool has_watch_manager = (g_gallery_watch_managers &&
                             GalleryWatchManager::HasForProfile(profile_id));
@@ -249,7 +249,7 @@
 
 // static
 bool GalleryWatchManager::HasForProfile(void* profile_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(profile_id);
   if (!g_gallery_watch_managers)
     return false;
@@ -260,7 +260,7 @@
 
 // static
 void GalleryWatchManager::OnProfileShutdown(void* profile_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(profile_id);
   if (!g_gallery_watch_managers || g_gallery_watch_managers->empty())
     return;
@@ -280,7 +280,7 @@
     const base::FilePath& watch_path,
     const std::string& extension_id,
     base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return GalleryWatchManager::GetForProfile(profile_id)->StartGalleryWatch(
       gallery_id, watch_path, extension_id, event_router);
 }
@@ -289,7 +289,7 @@
 void GalleryWatchManager::RemoveGalleryWatch(void* profile_id,
                                              const base::FilePath& watch_path,
                                              const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (!GalleryWatchManager::HasForProfile(profile_id))
     return;
   GalleryWatchManager::GetForProfile(profile_id)->StopGalleryWatch(
@@ -298,7 +298,7 @@
 
 void GalleryWatchManager::OnExtensionUnloaded(void* profile_id,
                                               const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (!GalleryWatchManager::HasForProfile(profile_id))
     return;
   GalleryWatchManager::GetForProfile(profile_id)->HandleExtensionUnloadedEvent(
@@ -306,11 +306,11 @@
 }
 
 GalleryWatchManager::GalleryWatchManager() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 }
 
 GalleryWatchManager::~GalleryWatchManager() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DeleteAllWatchers();
 }
 
@@ -319,7 +319,7 @@
     const base::FilePath& watch_path,
     const std::string& extension_id,
     base::WeakPtr<MediaGalleriesPrivateEventRouter> event_router) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   WatcherMap::const_iterator iter = gallery_watchers_.find(watch_path);
   if (iter != gallery_watchers_.end()) {
     // Already watched.
@@ -343,7 +343,7 @@
 void GalleryWatchManager::StopGalleryWatch(
     const base::FilePath& watch_path,
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   WatcherMap::iterator iter = gallery_watchers_.find(watch_path);
   if (iter == gallery_watchers_.end())
     return;
@@ -353,7 +353,7 @@
 
 void GalleryWatchManager::HandleExtensionUnloadedEvent(
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   std::list<base::FilePath> watchers_to_notify;
   for (WatcherMap::iterator iter = gallery_watchers_.begin();
        iter != gallery_watchers_.end(); ++iter)
@@ -370,7 +370,7 @@
 }
 
 void GalleryWatchManager::DeleteAllWatchers() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (gallery_watchers_.empty())
     return;
 
@@ -386,7 +386,7 @@
 
 void GalleryWatchManager::RemoveGalleryFilePathWatcherEntry(
     const base::FilePath& watch_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   gallery_watchers_.erase(watch_path);
 }
 
diff --git a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc
index 4803696..7bda3b8 100644
--- a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.cc
@@ -13,7 +13,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.h"
 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"
 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
@@ -23,8 +22,7 @@
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_service.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 
@@ -38,7 +36,7 @@
 // Converts the storage |list| value to WatchedGalleryIds.
 MediaGalleryPrefIdSet WatchedGalleryIdsFromValue(
     const base::ListValue* list) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   MediaGalleryPrefIdSet gallery_ids;
   std::string gallery_id_str;
   for (size_t i = 0; i < list->GetSize(); ++i) {
@@ -54,7 +52,7 @@
 // Converts WatchedGalleryIds to a storage list value.
 scoped_ptr<base::ListValue> WatchedGalleryIdsToValue(
     const MediaGalleryPrefIdSet gallery_ids) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   scoped_ptr<base::ListValue> list(new base::ListValue());
   for (MediaGalleryPrefIdSet::const_iterator id_iter = gallery_ids.begin();
        id_iter != gallery_ids.end(); ++id_iter)
@@ -74,20 +72,18 @@
 }  // namespace
 
 GalleryWatchStateTracker::GalleryWatchStateTracker(Profile* profile)
-    : profile_(profile) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+    : profile_(profile),
+      scoped_extension_registry_observer_(this) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(profile_);
-  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
-                 content::Source<Profile>(profile_));
-  registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
-                 content::Source<Profile>(profile_));
+  scoped_extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
   MediaGalleriesPreferences* preferences =
       g_browser_process->media_file_system_registry()->GetPreferences(profile);
   preferences->AddGalleryChangeObserver(this);
 }
 
 GalleryWatchStateTracker::~GalleryWatchStateTracker() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   MediaGalleriesPreferences* preferences =
       g_browser_process->media_file_system_registry()->GetPreferences(profile_);
   preferences->RemoveGalleryChangeObserver(this);
@@ -96,7 +92,7 @@
 // static
 GalleryWatchStateTracker* GalleryWatchStateTracker::GetForProfile(
     Profile* profile) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 #if defined(OS_WIN)
   // Gallery watch operation is supported only on windows.
   // Please refer to crbug.com/144491 for more details.
@@ -114,7 +110,7 @@
     MediaGalleriesPreferences* preferences,
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // Granted gallery permission.
   if (HasGalleryWatchInfo(extension_id, gallery_id, false))
     SetupGalleryWatch(extension_id, gallery_id, preferences);
@@ -124,7 +120,7 @@
     MediaGalleriesPreferences* preferences,
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // Revoked gallery permission.
   if (HasGalleryWatchInfo(extension_id, gallery_id, true))
     RemoveGalleryWatch(extension_id, gallery_id, preferences);
@@ -176,7 +172,7 @@
 void GalleryWatchStateTracker::OnGalleryWatchAdded(
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   bool update_storage =
       AddWatchedGalleryIdInfoForExtension(extension_id, gallery_id);
   if (update_storage)
@@ -186,7 +182,7 @@
 void GalleryWatchStateTracker::OnGalleryWatchRemoved(
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!ContainsKey(watched_extensions_map_, extension_id))
     return;
   watched_extensions_map_[extension_id].erase(gallery_id);
@@ -195,52 +191,38 @@
   WriteToStorage(extension_id);
 }
 
-void GalleryWatchStateTracker::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  switch (type) {
-    case chrome::NOTIFICATION_EXTENSION_LOADED: {
-      const Extension* extension =
-          content::Details<const Extension>(details).ptr();
-      StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
-      if (!storage)
-        return;
-      storage->GetExtensionValue(
-          extension->id(),
-          kRegisteredGalleryWatchers,
-          base::Bind(&GalleryWatchStateTracker::ReadFromStorage,
-                     AsWeakPtr(),
-                     extension->id()));
-      break;
-    }
-    case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
-      Extension* extension = const_cast<Extension*>(
-          content::Details<extensions::UnloadedExtensionInfo>(
-              details)->extension);
-      DCHECK(extension);
-      if (!ContainsKey(watched_extensions_map_, extension->id()))
-        return;
-      content::BrowserThread::PostTask(
-          content::BrowserThread::FILE, FROM_HERE,
-          base::Bind(&GalleryWatchManager::OnExtensionUnloaded,
-                     profile_,
-                     extension->id()));
-      for (WatchedGalleriesMap::iterator iter =
-               watched_extensions_map_[extension->id()].begin();
-           iter != watched_extensions_map_[extension->id()].end(); ++iter) {
-        iter->second = false;
-      }
-      break;
-    }
-    default:
-      NOTREACHED();
+void GalleryWatchStateTracker::OnExtensionLoaded(const Extension* extension) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
+  if (!storage)
+    return;
+  storage->GetExtensionValue(
+      extension->id(),
+      kRegisteredGalleryWatchers,
+      base::Bind(&GalleryWatchStateTracker::ReadFromStorage,
+                 AsWeakPtr(),
+                 extension->id()));
+}
+
+void GalleryWatchStateTracker::OnExtensionUnloaded(
+    const Extension* extension) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  if (!ContainsKey(watched_extensions_map_, extension->id()))
+    return;
+  content::BrowserThread::PostTask(
+      content::BrowserThread::FILE, FROM_HERE,
+      base::Bind(&GalleryWatchManager::OnExtensionUnloaded,
+                 profile_,
+                 extension->id()));
+  for (WatchedGalleriesMap::iterator iter =
+       watched_extensions_map_[extension->id()].begin();
+       iter != watched_extensions_map_[extension->id()].end(); ++iter) {
+    iter->second = false;
   }
 }
 
 void GalleryWatchStateTracker::WriteToStorage(const std::string& extension_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   StateStore* storage = ExtensionSystem::Get(profile_)->state_store();
   if (!storage)
     return;
@@ -255,7 +237,7 @@
 void GalleryWatchStateTracker::ReadFromStorage(
     const std::string& extension_id,
     scoped_ptr<base::Value> value) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   MediaGalleriesPreferences* preferences =
       g_browser_process->media_file_system_registry()->GetPreferences(profile_);
   base::ListValue* list = NULL;
@@ -276,7 +258,7 @@
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id,
     MediaGalleriesPreferences* preferences) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const Extension* extension = GetExtensionById(profile_, extension_id);
   DCHECK(extension);
   base::FilePath gallery_file_path(preferences->LookUpGalleryPathForExtension(
@@ -305,7 +287,7 @@
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id,
     MediaGalleriesPreferences* preferences) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   const Extension* extension = GetExtensionById(profile_, extension_id);
   DCHECK(extension);
   base::FilePath gallery_file_path(preferences->LookUpGalleryPathForExtension(
@@ -325,7 +307,7 @@
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id,
     bool has_active_watcher) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   return (ContainsKey(watched_extensions_map_, extension_id) &&
           ContainsKey(watched_extensions_map_[extension_id], gallery_id) &&
           watched_extensions_map_[extension_id][gallery_id] ==
@@ -336,7 +318,7 @@
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id,
     bool success) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success)
     return;  // Failed to setup the gallery watch for the given extension.
   AddWatchedGalleryIdInfoForExtension(extension_id, gallery_id);
@@ -345,7 +327,7 @@
 bool GalleryWatchStateTracker::AddWatchedGalleryIdInfoForExtension(
     const std::string& extension_id,
     MediaGalleryPrefId gallery_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (HasGalleryWatchInfo(extension_id, gallery_id, true))
     return false;
   watched_extensions_map_[extension_id][gallery_id] = true;
diff --git a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.h b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.h
index 65bb9cd..381354a 100644
--- a/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.h
+++ b/chrome/browser/extensions/api/media_galleries_private/gallery_watch_state_tracker.h
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // GalleryWatchStateTracker tracks the gallery watchers, updates the
-// extension state storage and observes the notification events.
+// extension state storage and observes the extension registry events.
 // GalleryWatchStateTracker lives on the UI thread.
 
 #ifndef CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_PRIVATE_GALLERY_WATCH_STATE_TRACKER_H_
@@ -15,9 +15,9 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "extensions/browser/extension_registry_observer.h"
 
 class Profile;
 
@@ -27,10 +27,12 @@
 
 namespace extensions {
 
+class ExtensionRegistry;
+
 // This class is owned by the MediaGalleriesPrivateAPI, and is created on demand
 // along with the MediaGalleriesPrivateEventRouter.
 class GalleryWatchStateTracker
-    : public content::NotificationObserver,
+    : public extensions::ExtensionRegistryObserver,
       public base::SupportsWeakPtr<GalleryWatchStateTracker>,
       public MediaGalleriesPreferences::GalleryChangeObserver {
  public:
@@ -87,10 +89,9 @@
   // Value: Map of watched gallery information.
   typedef std::map<std::string, WatchedGalleriesMap> WatchedExtensionsMap;
 
-  // content::NotificationObserver implementation.
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
+  // extensions::ExtensionRegistryObserver implementation.
+  virtual void OnExtensionLoaded(const Extension* extension) OVERRIDE;
+  virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE;
 
   // Syncs media gallery watch data for the given extension to/from the state
   // storage.
@@ -133,9 +134,8 @@
   // Current profile.
   Profile* profile_;
 
-  // Used to listen for NOTIFICATION_EXTENSION_LOADED and
-  // NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED events.
-  content::NotificationRegistrar registrar_;
+  ScopedObserver<ExtensionRegistry,
+                 ExtensionRegistryObserver> scoped_extension_registry_observer_;
 
   // A map of watched gallery details, per extension.
   WatchedExtensionsMap watched_extensions_map_;
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc
index 2102334..f5801f0 100644
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/api/media_galleries_private/gallery_watch_manager.h"
 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
@@ -48,7 +47,7 @@
 // Handles the profile shutdown event on the file thread to clean up
 // GalleryWatchManager.
 void HandleProfileShutdownOnFileThread(void* profile_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::FILE);
   GalleryWatchManager::OnProfileShutdown(profile_id);
 }
 
@@ -87,10 +86,6 @@
   DCHECK(profile_);
   EventRouter* event_router = ExtensionSystem::Get(profile_)->event_router();
   event_router->RegisterObserver(
-      this, media_galleries_private::OnDeviceAttached::kEventName);
-  event_router->RegisterObserver(
-      this, media_galleries_private::OnDeviceDetached::kEventName);
-  event_router->RegisterObserver(
       this, media_galleries_private::OnGalleryChanged::kEventName);
 }
 
@@ -166,7 +161,7 @@
 
 bool MediaGalleriesPrivateAddGalleryWatchFunction::RunImpl() {
   DCHECK(GetProfile());
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!render_view_host() || !render_view_host()->GetProcess())
     return false;
 
@@ -225,7 +220,7 @@
 void MediaGalleriesPrivateAddGalleryWatchFunction::HandleResponse(
     MediaGalleryPrefId gallery_id,
     bool success) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   media_galleries_private::AddGalleryWatchResult result;
   result.gallery_id = base::Uint64ToString(gallery_id);
   result.success = success;
@@ -251,7 +246,7 @@
 }
 
 bool MediaGalleriesPrivateRemoveGalleryWatchFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!render_view_host() || !render_view_host()->GetProcess())
     return false;
 
@@ -310,7 +305,7 @@
 }
 
 bool MediaGalleriesPrivateGetAllGalleryWatchFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!render_view_host() || !render_view_host()->GetProcess())
     return false;
 
@@ -348,7 +343,7 @@
 }
 
 bool MediaGalleriesPrivateRemoveAllGalleryWatchFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!render_view_host() || !render_view_host()->GetProcess())
     return false;
 
@@ -383,7 +378,7 @@
 }
 
 bool MediaGalleriesPrivateGetHandlersFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   ExtensionService* service =
       extensions::ExtensionSystem::Get(GetProfile())->extension_service();
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc
deleted file mode 100644
index ccb7db1..0000000
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_api.h"
-#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/extensions/extension_test_message_listener.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/test/base/ui_test_utils.h"
-#include "components/storage_monitor/storage_info.h"
-#include "components/storage_monitor/storage_monitor.h"
-#include "components/storage_monitor/test_storage_monitor.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/test/browser_test_utils.h"
-#include "extensions/browser/extension_system.h"
-#include "extensions/common/extension.h"
-
-using storage_monitor::StorageInfo;
-using storage_monitor::StorageMonitor;
-using storage_monitor::TestStorageMonitor;
-
-namespace {
-
-// Id of test extension from
-// chrome/test/data/extensions/api_test/|kTestExtensionPath|
-const char kTestExtensionId[] = "lkegdcleigedmkiikoijjgfchobofdbe";
-const char kTestExtensionPath[] = "media_galleries_private/attachdetach";
-
-// JS commands.
-const char kAddAttachListenerCmd[] = "addAttachListener()";
-const char kAddDetachListenerCmd[] = "addDetachListener()";
-const char kAddDummyDetachListenerCmd[] = "addDummyDetachListener()";
-const char kRemoveAttachListenerCmd[] = "removeAttachListener()";
-const char kRemoveDummyDetachListenerCmd[] = "removeDummyDetachListener()";
-
-// And JS reply messages.
-const char kAddAttachListenerOk[] = "add_attach_ok";
-const char kAddDetachListenerOk[] = "add_detach_ok";
-const char kAddDummyDetachListenerOk[] = "add_dummy_detach_ok";
-const char kRemoveAttachListenerOk[] = "remove_attach_ok";
-const char kRemoveDummyDetachListenerOk[] = "remove_dummy_detach_ok";
-
-// Test reply messages.
-const char kAttachTestOk[] = "attach_test_ok";
-const char kDetachTestOk[] = "detach_test_ok";
-
-// Dummy device properties.
-const char kDeviceId[] = "testDeviceId";
-const char kVolumeLabel[] = "foobar";
-base::FilePath::CharType kDevicePath[] = FILE_PATH_LITERAL("/qux");
-
-}  // namespace
-
-class MediaGalleriesPrivateApiTest : public ExtensionApiTest {
- public:
-  MediaGalleriesPrivateApiTest() {}
-  virtual ~MediaGalleriesPrivateApiTest() {}
-
-  // ExtensionApiTest overrides.
-  virtual void SetUp() OVERRIDE {
-    device_id_ = StorageInfo::MakeDeviceId(
-        StorageInfo::REMOVABLE_MASS_STORAGE_WITH_DCIM, kDeviceId);
-    ExtensionApiTest::SetUp();
-  }
-
- protected:
-  // ExtensionApiTest overrides.
-  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
-    ExtensionApiTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitchASCII(switches::kWhitelistedExtensionID,
-                                    kTestExtensionId);
-  }
-
-  void ChangeListener(content::RenderViewHost* host,
-                      const std::string& js_command,
-                      const std::string& ok_message) {
-    ExtensionTestMessageListener listener(ok_message, false  /* no reply */);
-    host->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16(js_command));
-    EXPECT_TRUE(listener.WaitUntilSatisfied());
-  }
-
-  void AttachDetach() {
-    Attach();
-    Detach();
-  }
-
-  void Attach() {
-    DCHECK(StorageMonitor::GetInstance()->IsInitialized());
-    const StorageInfo info(device_id_, kDevicePath,
-                           base::ASCIIToUTF16(kVolumeLabel), base::string16(),
-                           base::string16(), 0);
-    StorageMonitor::GetInstance()->receiver()->ProcessAttach(info);
-    content::RunAllPendingInMessageLoop();
-  }
-
-  void Detach() {
-    DCHECK(StorageMonitor::GetInstance()->IsInitialized());
-    StorageMonitor::GetInstance()->receiver()->ProcessDetach(device_id_);
-    content::RunAllPendingInMessageLoop();
-  }
-
- private:
-  std::string device_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(MediaGalleriesPrivateApiTest);
-};
-
-// Fails on official Linux bot. See http://crbug.com/315276
-// Flaky on Mac trybots. See http://crbug.com/326324
-// Times out on Win7 x64. See http://crbug.com/353955
-#if (defined(GOOGLE_CHROME_BUILD) && defined(OS_LINUX)) || \
-    defined(OS_MACOSX) || (defined(OS_WIN) && defined(ARCH_CPU_X86_64))
-#define MAYBE_DeviceAttachDetachEvents DISABLED_DeviceAttachDetachEvents
-#else
-#define MAYBE_DeviceAttachDetachEvents DeviceAttachDetachEvents
-#endif
-IN_PROC_BROWSER_TEST_F(MediaGalleriesPrivateApiTest,
-                       MAYBE_DeviceAttachDetachEvents) {
-  // Setup.
-  TestStorageMonitor::SyncInitialize();
-  const extensions::Extension* extension =
-      LoadExtension(test_data_dir_.AppendASCII(kTestExtensionPath));
-  ASSERT_TRUE(extension);
-
-  content::RenderViewHost* host =
-      extensions::ExtensionSystem::Get(browser()->profile())->
-          process_manager()->GetBackgroundHostForExtension(extension->id())->
-              render_view_host();
-  ASSERT_TRUE(host);
-
-  // No listeners, attach and detach a couple times.
-  AttachDetach();
-  AttachDetach();
-
-  // Add attach listener.
-  ChangeListener(host, kAddAttachListenerCmd, kAddAttachListenerOk);
-
-  // Attach / detach
-  const std::string expect_attach_msg =
-      base::StringPrintf("%s,%s", kAttachTestOk, kVolumeLabel);
-  ExtensionTestMessageListener attach_finished_listener(expect_attach_msg,
-                                                        false  /* no reply */);
-  Attach();
-  EXPECT_TRUE(attach_finished_listener.WaitUntilSatisfied());
-  Detach();
-
-  // Attach / detach
-  Attach();
-  EXPECT_TRUE(attach_finished_listener.WaitUntilSatisfied());
-  // Detach
-  Detach();
-
-  // Remove attach listener.
-  ChangeListener(host, kRemoveAttachListenerCmd, kRemoveAttachListenerOk);
-
-  // No listeners, attach and detach a couple times.
-  AttachDetach();
-  AttachDetach();
-
-  // Add detach listener.
-  ChangeListener(host, kAddDummyDetachListenerCmd, kAddDummyDetachListenerOk);
-
-  // Attach / detach
-  Attach();
-
-  ExtensionTestMessageListener detach_finished_listener(kDetachTestOk,
-                                                        false  /* no reply */);
-  Detach();
-  EXPECT_TRUE(detach_finished_listener.WaitUntilSatisfied());
-
-  // Attach / detach
-  Attach();
-  Detach();
-  EXPECT_TRUE(detach_finished_listener.WaitUntilSatisfied());
-
-  // Switch ok dummy detach listener for the regular one.
-  ChangeListener(host, kRemoveDummyDetachListenerCmd,
-                 kRemoveDummyDetachListenerOk);
-  ChangeListener(host, kAddDetachListenerCmd, kAddDetachListenerOk);
-
-  // Add attach listener.
-  ChangeListener(host, kAddAttachListenerCmd, kAddAttachListenerOk);
-
-  Attach();
-  EXPECT_TRUE(attach_finished_listener.WaitUntilSatisfied());
-  Detach();
-  EXPECT_TRUE(detach_finished_listener.WaitUntilSatisfied());
-
-  Attach();
-  EXPECT_TRUE(attach_finished_listener.WaitUntilSatisfied());
-  Detach();
-  EXPECT_TRUE(detach_finished_listener.WaitUntilSatisfied());
-}
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc
index 13d8ac5..51f8450 100644
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc
+++ b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.cc
@@ -6,57 +6,34 @@
 
 #include "chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h"
 
-#include <map>
-
-#include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/media_galleries_private.h"
-#include "components/storage_monitor/storage_monitor.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_system.h"
 
-using storage_monitor::StorageMonitor;
-
 namespace media_galleries_private = extensions::api::media_galleries_private;
 
 namespace extensions {
 
-namespace {
-
-std::string GetTransientIdForDeviceId(const std::string& device_id) {
-  StorageMonitor* monitor = StorageMonitor::GetInstance();
-  return monitor->GetTransientIdForDeviceId(device_id);
-}
-
-}  // namespace
-
-using media_galleries_private::DeviceAttachmentDetails;
-using media_galleries_private::DeviceDetachmentDetails;
 using media_galleries_private::GalleryChangeDetails;
 
 MediaGalleriesPrivateEventRouter::MediaGalleriesPrivateEventRouter(
     Profile* profile)
     : profile_(profile) {
   DCHECK(profile_);
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  StorageMonitor::GetInstance()->AddObserver(this);
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 MediaGalleriesPrivateEventRouter::~MediaGalleriesPrivateEventRouter() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  // TODO(gbillock): Remove this check once we have destruction order
-  // fixed up for profile services and the storage monitor.
-  if (StorageMonitor::GetInstance())
-    StorageMonitor::GetInstance()->RemoveObserver(this);
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 void MediaGalleriesPrivateEventRouter::OnGalleryChanged(
     MediaGalleryPrefId gallery_id,
     const std::set<std::string>& extension_ids) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   EventRouter* router =
       extensions::ExtensionSystem::Get(profile_)->event_router();
   if (!router->HasEventListener(
@@ -83,55 +60,4 @@
   }
 }
 
-void MediaGalleriesPrivateEventRouter::OnRemovableStorageAttached(
-    const storage_monitor::StorageInfo& info) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  EventRouter* router =
-      extensions::ExtensionSystem::Get(profile_)->event_router();
-  if (!router->HasEventListener(
-          media_galleries_private::OnDeviceAttached::kEventName))
-    return;
-
-  DeviceAttachmentDetails details;
-  details.device_name = base::UTF16ToUTF8(info.GetDisplayName(true));
-  details.device_id = GetTransientIdForDeviceId(info.device_id());
-
-  scoped_ptr<base::ListValue> args(new base::ListValue());
-  args->Append(details.ToValue().release());
-  DispatchEvent(
-      media_galleries_private::OnDeviceAttached::kEventName, args.Pass());
-}
-
-void MediaGalleriesPrivateEventRouter::OnRemovableStorageDetached(
-    const storage_monitor::StorageInfo& info) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  EventRouter* router =
-      extensions::ExtensionSystem::Get(profile_)->event_router();
-  if (!router->HasEventListener(
-          media_galleries_private::OnDeviceDetached::kEventName))
-    return;
-
-  DeviceDetachmentDetails details;
-  details.device_id = GetTransientIdForDeviceId(info.device_id());
-
-  scoped_ptr<base::ListValue> args(new base::ListValue());
-  args->Append(details.ToValue().release());
-  DispatchEvent(
-      media_galleries_private::OnDeviceDetached::kEventName, args.Pass());
-}
-
-void MediaGalleriesPrivateEventRouter::DispatchEvent(
-    const std::string& event_name,
-    scoped_ptr<base::ListValue> event_args) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-  EventRouter* router =
-      extensions::ExtensionSystem::Get(profile_)->event_router();
-  if (!router)
-    return;
-  scoped_ptr<extensions::Event> event(new extensions::Event(
-      event_name, event_args.Pass()));
-  event->restrict_to_browser_context = profile_;
-  router->BroadcastEvent(event.Pass());
-}
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h
index 948139e..e735271 100644
--- a/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h
+++ b/chrome/browser/extensions/api/media_galleries_private/media_galleries_private_event_router.h
@@ -14,10 +14,8 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
-#include "components/storage_monitor/removable_storage_observer.h"
 
 class Profile;
 
@@ -28,8 +26,7 @@
 namespace extensions {
 
 class MediaGalleriesPrivateEventRouter
-    : public storage_monitor::RemovableStorageObserver,
-      public base::SupportsWeakPtr<MediaGalleriesPrivateEventRouter> {
+    : public base::SupportsWeakPtr<MediaGalleriesPrivateEventRouter> {
  public:
   explicit MediaGalleriesPrivateEventRouter(Profile* profile);
   virtual ~MediaGalleriesPrivateEventRouter();
@@ -39,15 +36,6 @@
                         const std::set<std::string>& extension_ids);
 
  private:
-  // RemovableStorageObserver implementation.
-  virtual void OnRemovableStorageAttached(
-      const storage_monitor::StorageInfo& info) OVERRIDE;
-  virtual void OnRemovableStorageDetached(
-      const storage_monitor::StorageInfo& info) OVERRIDE;
-
-  void DispatchEvent(const std::string& event_name,
-                     scoped_ptr<base::ListValue> event_args);
-
   // Current profile.
   Profile* profile_;
 
diff --git a/chrome/browser/extensions/api/messaging/message_property_provider.cc b/chrome/browser/extensions/api/messaging/message_property_provider.cc
index 85b0072..c15c3ad 100644
--- a/chrome/browser/extensions/api/messaging/message_property_provider.cc
+++ b/chrome/browser/extensions/api/messaging/message_property_provider.cc
@@ -57,7 +57,7 @@
     scoped_refptr<net::URLRequestContextGetter> request_context_getter,
     const std::string& host,
     const DomainBoundCertCallback& reply) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   net::ServerBoundCertService* server_bound_cert_service =
       request_context_getter->GetURLRequestContext()->
           server_bound_cert_service();
diff --git a/chrome/browser/extensions/api/messaging/message_service.h b/chrome/browser/extensions/api/messaging/message_service.h
index d5693f2..704a4d4 100644
--- a/chrome/browser/extensions/api/messaging/message_service.h
+++ b/chrome/browser/extensions/api/messaging/message_service.h
@@ -15,10 +15,10 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/extensions/api/messaging/message_property_provider.h"
 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h"
-#include "chrome/common/extensions/api/messaging/message.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
+#include "extensions/common/api/messaging/message.h"
 
 class GURL;
 class Profile;
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index 170a25e..8d3352a 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -109,7 +109,7 @@
 #endif
       read_pending_(false),
       write_pending_(false) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   // It's safe to use base::Unretained() here because NativeMessagePort always
   // deletes us on the IO thread.
@@ -119,7 +119,7 @@
 }
 
 NativeMessageProcessHost::~NativeMessageProcessHost() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   Close(std::string());
 }
 
@@ -145,7 +145,7 @@
     const std::string& native_host_name,
     int destination_port,
     scoped_ptr<NativeProcessLauncher> launcher) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   scoped_ptr<NativeMessageProcessHost> process(new NativeMessageProcessHost(
       weak_client_ui, source_extension_id, native_host_name,
@@ -155,7 +155,7 @@
 }
 
 void NativeMessageProcessHost::LaunchHostProcess() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_);
   launcher_->Launch(origin, native_host_name_,
@@ -168,7 +168,7 @@
     base::ProcessHandle process_handle,
     base::File read_file,
     base::File write_file) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   switch (result) {
     case NativeProcessLauncher::RESULT_INVALID_NAME:
@@ -212,7 +212,7 @@
 }
 
 void NativeMessageProcessHost::Send(const std::string& json) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   if (closed_)
     return;
@@ -271,7 +271,7 @@
 }
 
 void NativeMessageProcessHost::DoRead() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   while (!closed_ && !read_pending_) {
     read_buffer_ = new net::IOBuffer(kReadBufferSize);
@@ -284,7 +284,7 @@
 }
 
 void NativeMessageProcessHost::OnRead(int result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   DCHECK(read_pending_);
   read_pending_ = false;
 
@@ -293,7 +293,7 @@
 }
 
 void NativeMessageProcessHost::HandleReadResult(int result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   if (closed_)
     return;
@@ -314,7 +314,7 @@
 
 void NativeMessageProcessHost::ProcessIncomingData(
     const char* data, int data_size) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   incoming_data_.append(data, data_size);
 
@@ -345,7 +345,7 @@
 }
 
 void NativeMessageProcessHost::DoWrite() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   while (!write_pending_ && !closed_) {
     if (!current_write_buffer_.get() ||
@@ -367,7 +367,7 @@
 }
 
 void NativeMessageProcessHost::HandleWriteResult(int result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   if (result <= 0) {
     if (result == net::ERR_IO_PENDING) {
@@ -383,7 +383,7 @@
 }
 
 void NativeMessageProcessHost::OnWritten(int result) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   DCHECK(write_pending_);
   write_pending_ = false;
@@ -393,7 +393,7 @@
 }
 
 void NativeMessageProcessHost::Close(const std::string& error_message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   if (!closed_) {
     closed_ = true;
diff --git a/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index 32f4741..fa8c7e9 100644
--- a/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -34,29 +34,6 @@
 const char kParentWindowSwitchName[] = "parent-window";
 #endif  // defined(OS_WIN)
 
-base::FilePath GetHostManifestPathFromCommandLine(
-    const std::string& native_host_name) {
-  const std::string& value =
-      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-          switches::kNativeMessagingHosts);
-  if (value.empty())
-    return base::FilePath();
-
-  std::vector<std::string> hosts;
-  base::SplitString(value, ',', &hosts);
-  for (size_t i = 0; i < hosts.size(); ++i) {
-    std::vector<std::string> key_and_value;
-    base::SplitString(hosts[i], '=', &key_and_value);
-    if (key_and_value.size() != 2)
-      continue;
-    if (key_and_value[0] == native_host_name)
-      return base::FilePath::FromUTF8Unsafe(key_and_value[1]);
-  }
-
-  return base::FilePath();
-}
-
-
 // Default implementation on NativeProcessLauncher interface.
 class NativeProcessLauncherImpl : public NativeProcessLauncher {
  public:
@@ -122,7 +99,7 @@
 }
 
 void NativeProcessLauncherImpl::Core::Detach() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   detached_ = true;
 }
 
@@ -147,15 +124,8 @@
   }
 
   std::string error_message;
-  scoped_ptr<NativeMessagingHostManifest> manifest;
-
-  // First check if the manifest location is specified in the command line.
   base::FilePath manifest_path =
-      GetHostManifestPathFromCommandLine(native_host_name);
-  if (manifest_path.empty()) {
-    manifest_path =
-        FindManifest(native_host_name, allow_user_level_hosts_, &error_message);
-  }
+      FindManifest(native_host_name, allow_user_level_hosts_, &error_message);
 
   if (manifest_path.empty()) {
     LOG(ERROR) << "Can't find manifest for native messaging host "
@@ -164,7 +134,8 @@
     return;
   }
 
-  manifest = NativeMessagingHostManifest::Load(manifest_path, &error_message);
+  scoped_ptr<NativeMessagingHostManifest> manifest =
+      NativeMessagingHostManifest::Load(manifest_path, &error_message);
 
   if (!manifest) {
     LOG(ERROR) << "Failed to load manifest for native messaging host "
@@ -228,7 +199,7 @@
     base::ProcessHandle process_handle,
     base::File read_file,
     base::File write_file) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
   if (detached_)
     return;
 
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
index f910a35..c7d23d3 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc
@@ -38,6 +38,9 @@
       {"test.h.1", base::HISTOGRAM, 1, 100, 50, 1},          // custom
       {"test.h.2", base::LINEAR_HISTOGRAM, 1, 200, 50, 1},   // custom
       {"test.h.3", base::LINEAR_HISTOGRAM, 1, 101, 102, 2},  // percentage
+      {"test.sparse.1", base::SPARSE_HISTOGRAM, 0, 0, 0, 1},
+      {"test.sparse.2", base::SPARSE_HISTOGRAM, 0, 0, 0, 2},
+      {"test.sparse.3", base::SPARSE_HISTOGRAM, 0, 0, 0, 6},
       {"test.time", base::HISTOGRAM, 1, 10000, 50, 1},
       {"test.medium.time", base::HISTOGRAM, 1, 180000, 50, 1},
       {"test.long.time", base::HISTOGRAM, 1, 3600000, 50, 1},
@@ -47,6 +50,22 @@
       {"test.bucketchange.linear", base::LINEAR_HISTOGRAM, 1, 100, 10, 2},
       {"test.bucketchange.log", base::HISTOGRAM, 1, 100, 10, 2}, };
 
+// Represents a bucket in a sparse histogram.
+struct Bucket {
+  int histogram_value;
+  int count;
+};
+
+// We expect the following sparse histograms.
+struct SparseHistogram {
+  const char* name;
+  int bucket_count;
+  Bucket buckets[10];
+} g_sparse_histograms[] = {
+  {"test.sparse.1", 1, {{42, 1}}},
+  {"test.sparse.2", 1, {{24, 2}}},
+  {"test.sparse.3", 3, {{1, 1}, {2, 2}, {3, 3}}}};
+
 // This class observes and collects user action notifications that are sent
 // by the tests, so that they can be examined afterwards for correctness.
 class UserActionObserver {
@@ -99,6 +118,20 @@
   }
 }
 
+void ValidateSparseHistogramSamples(
+    const std::string& name,
+    const base::HistogramSamples& samples) {
+  for (unsigned int i = 0; i < arraysize(g_sparse_histograms); ++i) {
+    const SparseHistogram& sparse_histogram = g_sparse_histograms[i];
+    if (std::string(name) == sparse_histogram.name) {
+      for (int j = 0; j < sparse_histogram.bucket_count; ++j) {
+        const Bucket& bucket = sparse_histogram.buckets[j];
+        EXPECT_EQ(bucket.count, samples.GetCount(bucket.histogram_value));
+      }
+    }
+  }
+}
+
 void ValidateHistograms(const RecordedHistogram* recorded,
                         int count) {
   base::StatisticsRecorder::Histograms histograms;
@@ -113,15 +146,19 @@
     size_t j = 0;
     for (j = 0; j < histograms.size(); ++j) {
       base::HistogramBase* histogram(histograms[j]);
-
       if (r.name == histogram->histogram_name()) {
-        EXPECT_EQ(r.type, histogram->GetHistogramType());
-        EXPECT_TRUE(
-            histogram->HasConstructionArguments(r.min, r.max, r.buckets));
         scoped_ptr<base::HistogramSamples> snapshot =
             histogram->SnapshotSamples();
         base::HistogramBase::Count sample_count = snapshot->TotalCount();
-        EXPECT_EQ(sample_count, r.count);
+        EXPECT_EQ(r.count, sample_count);
+
+        EXPECT_EQ(r.type, histogram->GetHistogramType());
+        if (r.type == base::SPARSE_HISTOGRAM) {
+          ValidateSparseHistogramSamples(r.name, *snapshot);
+        } else {
+          EXPECT_TRUE(
+              histogram->HasConstructionArguments(r.min, r.max, r.buckets));
+        }
         break;
       }
     }
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc b/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
index deada1e..6493f42 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.cc
@@ -8,18 +8,13 @@
 
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
-#include "base/prefs/pref_service.h"
-#include "chrome/browser/browser_process.h"
+#include "base/metrics/sparse_histogram.h"
+#include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/common/extensions/api/metrics_private.h"
-#include "chrome/common/pref_names.h"
 #include "components/variations/variations_associated_data.h"
 #include "content/public/browser/user_metrics.h"
 #include "extensions/common/extension.h"
 
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/settings/cros_settings.h"
-#endif  // OS_CHROMEOS
-
 namespace extensions {
 
 namespace GetIsCrashReportingEnabled =
@@ -28,6 +23,7 @@
 namespace GetFieldTrial = api::metrics_private::GetFieldTrial;
 namespace RecordUserAction = api::metrics_private::RecordUserAction;
 namespace RecordValue = api::metrics_private::RecordValue;
+namespace RecordSparseValue = api::metrics_private::RecordSparseValue;
 namespace RecordPercentage = api::metrics_private::RecordPercentage;
 namespace RecordCount = api::metrics_private::RecordCount;
 namespace RecordSmallCount = api::metrics_private::RecordSmallCount;
@@ -43,30 +39,9 @@
                                   // and would cause crazy memory usage
 } // namespace
 
-// Returns true if the user opted in to sending crash reports.
-// TODO(vadimt): Unify with CrashesUI::CrashReportingUIEnabled
-static bool IsCrashReportingEnabled() {
-#if defined(GOOGLE_CHROME_BUILD)
-#if defined(OS_CHROMEOS)
-  bool reporting_enabled = false;
-  chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
-                                            &reporting_enabled);
-  return reporting_enabled;
-#elif defined(OS_ANDROID)
-  // Android has its own settings for metrics / crash uploading.
-  PrefService* prefs = g_browser_process->local_state();
-  return prefs->GetBoolean(prefs::kCrashReportingEnabled);
-#else
-  PrefService* prefs = g_browser_process->local_state();
-  return prefs->GetBoolean(prefs::kMetricsReportingEnabled);
-#endif
-#else
-  return false;
-#endif
-}
-
 bool MetricsPrivateGetIsCrashReportingEnabledFunction::RunImpl() {
-  SetResult(new base::FundamentalValue(IsCrashReportingEnabled()));
+  SetResult(new base::FundamentalValue(
+      MetricsServiceHelper::IsCrashReportingEnabled()));
   return true;
 }
 
@@ -154,6 +129,16 @@
                      params->metric.buckets, params->value);
 }
 
+bool MetricsPrivateRecordSparseValueFunction::RunImpl() {
+  scoped_ptr<RecordSparseValue::Params> params(
+      RecordSparseValue::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params.get());
+  // This particular UMA_HISTOGRAM_ macro is okay for
+  // non-runtime-constant strings.
+  UMA_HISTOGRAM_SPARSE_SLOWLY(params->metric_name, params->value);
+  return true;
+}
+
 bool MetricsPrivateRecordPercentageFunction::RunImpl() {
   scoped_ptr<RecordPercentage::Params> params(
       RecordPercentage::Params::Create(*args_));
diff --git a/chrome/browser/extensions/api/metrics_private/metrics_private_api.h b/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
index fce8f88..8426416 100644
--- a/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
+++ b/chrome/browser/extensions/api/metrics_private/metrics_private_api.h
@@ -83,6 +83,19 @@
   virtual bool RunImpl() OVERRIDE;
 };
 
+class MetricsPrivateRecordSparseValueFunction
+    : public MetricsHistogramHelperFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("metricsPrivate.recordSparseValue",
+                             METRICSPRIVATE_RECORDSPARSEVALUE)
+
+ protected:
+  virtual ~MetricsPrivateRecordSparseValueFunction() {}
+
+  // ExtensionFunction:
+  virtual bool RunImpl() OVERRIDE;
+};
+
 class MetricsPrivateRecordPercentageFunction
     : public MetricsHistogramHelperFunction {
  public:
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id.cc b/chrome/browser/extensions/api/music_manager_private/device_id.cc
index 1bc87f5..880d722 100644
--- a/chrome/browser/extensions/api/music_manager_private/device_id.cc
+++ b/chrome/browser/extensions/api/music_manager_private/device_id.cc
@@ -33,7 +33,7 @@
 void GetRawDeviceIdCallback(const std::string& extension_id,
                             const DeviceId::IdCallback& callback,
                             const std::string& raw_device_id) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   if (raw_device_id.empty()) {
     callback.Run("");
@@ -179,7 +179,7 @@
 // static
 void DeviceId::GetDeviceId(const std::string& extension_id,
                            const IdCallback& callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   CHECK(!extension_id.empty());
 
   // Forward call to platform specific implementation, then compute the HMAC
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc b/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc
index a6e09c0..b370bb2 100644
--- a/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc
+++ b/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc
@@ -192,7 +192,7 @@
 
 // static
 void DeviceId::GetRawDeviceId(const IdCallback& callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   content::BrowserThread::PostTask(
       content::BrowserThread::FILE,
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc b/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
index d9f1388..bdc01de 100644
--- a/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
+++ b/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
@@ -240,7 +240,7 @@
 
 // static
 void DeviceId::GetRawDeviceId(const IdCallback& callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   content::BrowserThread::PostTask(
       content::BrowserThread::FILE,
diff --git a/chrome/browser/extensions/api/music_manager_private/device_id_win.cc b/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
index 1bbe3c2..2245c0c 100644
--- a/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
+++ b/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
@@ -193,7 +193,7 @@
 
 void GetMacAddressCallback(const DeviceId::IdCallback& callback,
                            const std::string& mac_address) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   std::string machine_id = GetRlzMachineId();
   if (mac_address.empty() || machine_id.empty()) {
@@ -210,7 +210,7 @@
 
 // static
 void DeviceId::GetRawDeviceId(const IdCallback& callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   content::BrowserThread::PostTask(
       content::BrowserThread::FILE,
diff --git a/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc b/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc
index 5cca660..0495981 100644
--- a/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc
+++ b/chrome/browser/extensions/api/music_manager_private/music_manager_private_api.cc
@@ -27,7 +27,7 @@
 }
 
 bool MusicManagerPrivateGetDeviceIdFunction::RunImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DeviceId::GetDeviceId(
       this->extension_id(),
       base::Bind(
@@ -38,7 +38,7 @@
 
 void MusicManagerPrivateGetDeviceIdFunction::DeviceIdCallback(
     const std::string& device_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   bool response;
   if (device_id.empty()) {
     SetError(kDeviceIdNotSupported);
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc
index 16fb3ba..0da39c9 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_win.cc
@@ -90,7 +90,7 @@
     const std::string& public_key,
     const extensions::NetworkingPrivateServiceClient::CryptoVerify::
         VerifyAndEncryptCredentialsCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   std::vector<uint8> public_key_data(public_key.begin(), public_key.end());
   UtilityProcessHost* host =
       UtilityProcessHost::Create(this, base::MessageLoopProxy::current());
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_service_client.cc b/chrome/browser/extensions/api/networking_private/networking_private_service_client.cc
index 6865dcd..fb65df3 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_service_client.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_service_client.cc
@@ -186,7 +186,7 @@
 NetworkingPrivateServiceClient::ServiceCallbacks::~ServiceCallbacks() {}
 
 void NetworkingPrivateServiceClient::Shutdown() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
   // Clear callbacks map to release callbacks from UI thread.
   callbacks_map_.Clear();
@@ -615,7 +615,7 @@
     ServiceCallbacksID callback_id,
     const std::string& encrypted_data,
     const std::string& error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ServiceCallbacks* service_callbacks = callbacks_map_.Lookup(callback_id);
   DCHECK(service_callbacks);
   if (!error.empty()) {
@@ -648,7 +648,7 @@
 
 void NetworkingPrivateServiceClient::OnNetworksChangedEventOnUIThread(
     const std::vector<std::string>& network_guids) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   FOR_EACH_OBSERVER(Observer,
                     network_events_observers_,
                     OnNetworksChangedEvent(network_guids));
@@ -656,7 +656,7 @@
 
 void NetworkingPrivateServiceClient::OnNetworkListChangedEventOnUIThread(
     const std::vector<std::string>& network_guids) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   FOR_EACH_OBSERVER(Observer,
                     network_events_observers_,
                     OnNetworkListChangedEvent(network_guids));
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_service_client_factory.cc b/chrome/browser/extensions/api/networking_private/networking_private_service_client_factory.cc
index c7b00cf..98f3fed 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_service_client_factory.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_service_client_factory.cc
@@ -39,7 +39,7 @@
 
 KeyedService* NetworkingPrivateServiceClientFactory::BuildServiceInstanceFor(
     content::BrowserContext* profile) const {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   return new NetworkingPrivateServiceClient(
       wifi::WiFiService::Create(),
       NetworkingPrivateServiceClient::CryptoVerify::Create());
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc
index 362b63c..1ee1c10 100644
--- a/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -11,7 +11,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/notifications/desktop_notification_service.h"
 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
 #include "chrome/browser/notifications/notification.h"
@@ -144,10 +143,7 @@
 
   virtual void Display() OVERRIDE { }
 
-  virtual void Error() OVERRIDE {
-    scoped_ptr<base::ListValue> args(CreateBaseEventArgs());
-    SendEvent(event_names::kOnNotificationError, args.Pass());
-  }
+  virtual void Error() OVERRIDE {}
 
   virtual void Close(bool by_user) OVERRIDE {
     scoped_ptr<base::ListValue> args(CreateBaseEventArgs());
diff --git a/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
index fec85b0..d82487c 100644
--- a/chrome/browser/extensions/api/page_capture/page_capture_api.cc
+++ b/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -89,7 +89,7 @@
 }
 
 void PageCaptureSaveAsMHTMLFunction::CreateTemporaryFile() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   bool success = base::CreateTemporaryFile(&mhtml_path_);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
@@ -115,7 +115,7 @@
     return;
   }
 
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!success) {
     ReturnFailure(kTemporaryFileError);
     return;
@@ -151,7 +151,7 @@
 }
 
 void PageCaptureSaveAsMHTMLFunction::ReturnFailure(const std::string& error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   error_ = error;
 
@@ -161,7 +161,7 @@
 }
 
 void PageCaptureSaveAsMHTMLFunction::ReturnSuccess(int64 file_size) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   WebContents* web_contents = GetWebContents();
   if (!web_contents || !render_view_host()) {
diff --git a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
index fd70ba7..0caa191 100644
--- a/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
+++ b/chrome/browser/extensions/api/permissions/permissions_api_helpers.cc
@@ -8,11 +8,11 @@
 #include "base/json/json_writer.h"
 #include "base/values.h"
 #include "chrome/common/extensions/api/permissions.h"
-#include "chrome/common/extensions/permissions/usb_device_permission.h"
 #include "extensions/common/error_utils.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/usb_device_permission.h"
 #include "extensions/common/url_pattern_set.h"
 
 using extensions::APIPermission;
diff --git a/chrome/browser/extensions/api/preference/preference_api.cc b/chrome/browser/extensions/api/preference/preference_api.cc
index bffab60..dd1ae43 100644
--- a/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chrome/browser/extensions/api/preference/preference_api.cc
@@ -49,10 +49,15 @@
   // Name of the preference in the PrefStores.
   const char* browser_pref;
 
-  // Permission required to access this preference.
-  // Use APIPermission::kInvalid for |permission| to express that no
-  // permission is necessary.
-  APIPermission::ID permission;
+  // Permission required to read and observe this preference.
+  // Use APIPermission::kInvalid for |read_permission| to express that the read
+  // permission should not be granted.
+  APIPermission::ID read_permission;
+
+  // Permission required to write this preference.
+  // Use APIPermission::kInvalid for |write_permission| to express that the
+  // write permission should not be granted.
+  APIPermission::ID write_permission;
 };
 
 const char kOnPrefChangeFormat[] = "types.ChromeSetting.%s.onChange";
@@ -61,54 +66,52 @@
     "properly.";
 
 PrefMappingEntry kPrefMapping[] = {
-  { "protectedContentEnabled",
-    prefs::kEnableDRM,
-    APIPermission::kPrivacy
-  },
-  { "alternateErrorPagesEnabled",
-    prefs::kAlternateErrorPagesEnabled,
-    APIPermission::kPrivacy
-  },
-  { "autofillEnabled",
-    autofill::prefs::kAutofillEnabled,
-    APIPermission::kPrivacy
-  },
-  { "hyperlinkAuditingEnabled",
-    prefs::kEnableHyperlinkAuditing,
-    APIPermission::kPrivacy
-  },
-  { "networkPredictionEnabled",
-    prefs::kNetworkPredictionEnabled,
-    APIPermission::kPrivacy
-  },
-  { "proxy",
-    prefs::kProxy,
-    APIPermission::kProxy
-  },
-  { "referrersEnabled",
-    prefs::kEnableReferrers,
-    APIPermission::kPrivacy
-  },
-  { "safeBrowsingEnabled",
-    prefs::kSafeBrowsingEnabled,
-    APIPermission::kPrivacy
-  },
-  { "searchSuggestEnabled",
-    prefs::kSearchSuggestEnabled,
-    APIPermission::kPrivacy
-  },
-  { "spellingServiceEnabled",
-    prefs::kSpellCheckUseSpellingService,
-    APIPermission::kPrivacy
-  },
-  { "thirdPartyCookiesAllowed",
-    prefs::kBlockThirdPartyCookies,
-    APIPermission::kPrivacy
-  },
-  { "translationServiceEnabled",
-    prefs::kEnableTranslate,
-    APIPermission::kPrivacy
-  },
+    {"protectedContentEnabled", prefs::kEnableDRM, APIPermission::kPrivacy,
+     APIPermission::kPrivacy},
+    {"alternateErrorPagesEnabled", prefs::kAlternateErrorPagesEnabled,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"autofillEnabled", autofill::prefs::kAutofillEnabled,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"hyperlinkAuditingEnabled", prefs::kEnableHyperlinkAuditing,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"networkPredictionEnabled", prefs::kNetworkPredictionEnabled,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"proxy", prefs::kProxy, APIPermission::kProxy, APIPermission::kProxy},
+    {"referrersEnabled", prefs::kEnableReferrers, APIPermission::kPrivacy,
+     APIPermission::kPrivacy},
+    {"safeBrowsingEnabled", prefs::kSafeBrowsingEnabled,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"searchSuggestEnabled", prefs::kSearchSuggestEnabled,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"spellingServiceEnabled", prefs::kSpellCheckUseSpellingService,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"thirdPartyCookiesAllowed", prefs::kBlockThirdPartyCookies,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+    {"translationServiceEnabled", prefs::kEnableTranslate,
+     APIPermission::kPrivacy, APIPermission::kPrivacy},
+#if defined(OS_CHROMEOS)
+    {"autoclick", prefs::kAutoclickEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"highContrast", prefs::kHighContrastEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"largeCursor", prefs::kLargeCursorEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"screenMagnifier", prefs::kScreenMagnifierEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"spokenFeedback", prefs::kSpokenFeedbackEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"stickyKeys", prefs::kStickyKeysEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+    {"virtualKeyboard", prefs::kVirtualKeyboardEnabled,
+     APIPermission::kAccessibilityFeaturesRead,
+     APIPermission::kAccessibilityFeaturesModify},
+#endif
 };
 
 class IdentityPrefTransformer : public PrefTransformerInterface {
@@ -155,11 +158,13 @@
 
   bool FindBrowserPrefForExtensionPref(const std::string& extension_pref,
                                        std::string* browser_pref,
-                                       APIPermission::ID* permission) {
+                                       APIPermission::ID* read_permission,
+                                       APIPermission::ID* write_permission) {
     PrefMap::iterator it = mapping_.find(extension_pref);
     if (it != mapping_.end()) {
-      *browser_pref = it->second.first;
-      *permission = it->second.second;
+      *browser_pref = it->second.pref_name;
+      *read_permission = it->second.read_permission;
+      *write_permission = it->second.write_permission;
       return true;
     }
     return false;
@@ -170,8 +175,8 @@
                                APIPermission::ID* permission) {
     PrefMap::iterator it = event_mapping_.find(browser_pref);
     if (it != event_mapping_.end()) {
-      *event_name = it->second.first;
-      *permission = it->second.second;
+      *event_name = it->second.pref_name;
+      *permission = it->second.read_permission;
       return true;
     }
     return false;
@@ -194,13 +199,16 @@
     identity_transformer_.reset(new IdentityPrefTransformer());
     for (size_t i = 0; i < arraysize(kPrefMapping); ++i) {
       mapping_[kPrefMapping[i].extension_pref] =
-          std::make_pair(kPrefMapping[i].browser_pref,
-                         kPrefMapping[i].permission);
+          PrefMapData(kPrefMapping[i].browser_pref,
+                      kPrefMapping[i].read_permission,
+                      kPrefMapping[i].write_permission);
       std::string event_name =
           base::StringPrintf(kOnPrefChangeFormat,
                              kPrefMapping[i].extension_pref);
       event_mapping_[kPrefMapping[i].browser_pref] =
-          std::make_pair(event_name, kPrefMapping[i].permission);
+          PrefMapData(event_name,
+                      kPrefMapping[i].read_permission,
+                      kPrefMapping[i].write_permission);
     }
     DCHECK_EQ(arraysize(kPrefMapping), mapping_.size());
     DCHECK_EQ(arraysize(kPrefMapping), event_mapping_.size());
@@ -221,9 +229,29 @@
     transformers_[browser_pref] = transformer;
   }
 
-  typedef std::map<std::string,
-                   std::pair<std::string, APIPermission::ID> >
-          PrefMap;
+  struct PrefMapData {
+    PrefMapData()
+        : read_permission(APIPermission::kInvalid),
+          write_permission(APIPermission::kInvalid) {}
+
+    PrefMapData(const std::string& pref_name,
+                APIPermission::ID read,
+                APIPermission::ID write)
+        : pref_name(pref_name),
+          read_permission(read),
+          write_permission(write) {}
+
+    // Browser or extension preference to which the data maps.
+    std::string pref_name;
+
+    // Permission needed to read the preference.
+    APIPermission::ID read_permission;
+
+    // Permission needed to write the preference.
+    APIPermission::ID write_permission;
+  };
+
+  typedef std::map<std::string, PrefMapData> PrefMap;
 
   // Mapping from extension pref keys to browser pref keys and permissions.
   PrefMap mapping_;
@@ -419,82 +447,6 @@
   ExtensionSystem::Get(profile_)->event_router()->UnregisterObserver(this);
 }
 
-// static
-void PreferenceAPI::LoadExtensionControlledPrefs(
-    ExtensionPrefs* prefs,
-    ExtensionPrefValueMap* value_map,
-    const std::string& extension_id,
-    ExtensionPrefsScope scope) {
-  std::string scope_string;
-  if (!pref_names::ScopeToPrefName(scope, &scope_string))
-    return;
-  std::string key = extension_id + "." + scope_string;
-
-  const base::DictionaryValue* source_dict = prefs->pref_service()->
-      GetDictionary(pref_names::kExtensions);
-  const base::DictionaryValue* preferences = NULL;
-  if (!source_dict->GetDictionary(key, &preferences))
-    return;
-
-  for (base::DictionaryValue::Iterator iter(*preferences);
-       !iter.IsAtEnd(); iter.Advance()) {
-    value_map->SetExtensionPref(
-        extension_id, iter.key(), scope, iter.value().DeepCopy());
-  }
-}
-
-// static
-void PreferenceAPI::InitExtensionControlledPrefs(
-    ExtensionPrefs* prefs,
-    ExtensionPrefValueMap* value_map) {
-  ExtensionIdList extension_ids;
-  prefs->GetExtensions(&extension_ids);
-
-  for (ExtensionIdList::iterator extension_id = extension_ids.begin();
-       extension_id != extension_ids.end(); ++extension_id) {
-    base::Time install_time = prefs->GetInstallTime(*extension_id);
-    bool is_enabled = !prefs->IsExtensionDisabled(*extension_id);
-    bool is_incognito_enabled = prefs->IsIncognitoEnabled(*extension_id);
-    value_map->RegisterExtension(
-        *extension_id, install_time, is_enabled, is_incognito_enabled);
-    prefs->content_settings_store()->RegisterExtension(
-        *extension_id, install_time, is_enabled);
-
-    // Set regular extension controlled prefs.
-    LoadExtensionControlledPrefs(prefs,
-                                 value_map,
-                                 *extension_id,
-                                 kExtensionPrefsScopeRegular);
-    // Set incognito extension controlled prefs.
-    LoadExtensionControlledPrefs(prefs,
-                                 value_map,
-                                 *extension_id,
-                                 kExtensionPrefsScopeIncognitoPersistent);
-    // Set regular-only extension controlled prefs.
-    LoadExtensionControlledPrefs(prefs,
-                                 value_map,
-                                 *extension_id,
-                                 kExtensionPrefsScopeRegularOnly);
-
-    // Set content settings.
-    const base::ListValue* content_settings = NULL;
-    if (prefs->ReadPrefAsList(*extension_id,
-                              pref_names::kPrefContentSettings,
-                              &content_settings)) {
-      prefs->content_settings_store()->SetExtensionContentSettingFromList(
-          *extension_id, content_settings, kExtensionPrefsScopeRegular);
-    }
-    if (prefs->ReadPrefAsList(*extension_id,
-                              pref_names::kPrefIncognitoContentSettings,
-                              &content_settings)) {
-      prefs->content_settings_store()->SetExtensionContentSettingFromList(
-          *extension_id,
-          content_settings,
-          kExtensionPrefsScopeIncognitoPersistent);
-    }
-  }
-}
-
 void PreferenceAPI::OnContentSettingChanged(const std::string& extension_id,
                                             bool incognito) {
   if (incognito) {
@@ -544,11 +496,19 @@
 
 bool PreferenceFunction::ValidateBrowserPref(
     const std::string& extension_pref_key,
+    PreferenceFunction::PermissionType permission_type,
     std::string* browser_pref_key) {
-  APIPermission::ID permission = APIPermission::kInvalid;
+  APIPermission::ID read_permission = APIPermission::kInvalid;
+  APIPermission::ID write_permission = APIPermission::kInvalid;
   EXTENSION_FUNCTION_VALIDATE(
       PrefMapping::GetInstance()->FindBrowserPrefForExtensionPref(
-          extension_pref_key, browser_pref_key, &permission));
+          extension_pref_key,
+          browser_pref_key,
+          &read_permission,
+          &write_permission));
+  APIPermission::ID permission = permission_type == PERMISSION_TYPE_READ
+                                     ? read_permission
+                                     : write_permission;
   if (!GetExtension()->HasAPIPermission(permission)) {
     error_ = ErrorUtils::FormatErrorMessage(
         keys::kPermissionErrorMessage, extension_pref_key);
@@ -578,8 +538,10 @@
 
   // Obtain pref.
   std::string browser_pref;
-  if (!ValidateBrowserPref(pref_key, &browser_pref))
+  if (!ValidateBrowserPref(
+          pref_key, PreferenceFunction::PERMISSION_TYPE_READ, &browser_pref)) {
     return false;
+  }
   PrefService* prefs = incognito ? GetProfile()->GetOffTheRecordPrefs()
                                  : GetProfile()->GetPrefs();
   const PrefService::Preference* pref =
@@ -664,8 +626,10 @@
 
   // Obtain pref.
   std::string browser_pref;
-  if (!ValidateBrowserPref(pref_key, &browser_pref))
+  if (!ValidateBrowserPref(
+          pref_key, PreferenceFunction::PERMISSION_TYPE_WRITE, &browser_pref)) {
     return false;
+  }
   ExtensionPrefs* prefs = ExtensionPrefs::Get(GetProfile());
   const PrefService::Preference* pref =
       prefs->pref_service()->FindPreference(browser_pref.c_str());
@@ -735,8 +699,10 @@
   }
 
   std::string browser_pref;
-  if (!ValidateBrowserPref(pref_key, &browser_pref))
+  if (!ValidateBrowserPref(
+          pref_key, PreferenceFunction::PERMISSION_TYPE_WRITE, &browser_pref)) {
     return false;
+  }
 
   PreferenceAPI::Get(GetProfile())
       ->RemoveExtensionControlledPref(extension_id(), browser_pref, scope);
diff --git a/chrome/browser/extensions/api/preference/preference_api.h b/chrome/browser/extensions/api/preference/preference_api.h
index 55df7a5..bbb35e4 100644
--- a/chrome/browser/extensions/api/preference/preference_api.h
+++ b/chrome/browser/extensions/api/preference/preference_api.h
@@ -108,19 +108,6 @@
   // EventRouter::Observer implementation.
   virtual void OnListenerAdded(const EventListenerInfo& details) OVERRIDE;
 
-  // Loads the preferences controlled by the specified extension from their
-  // dictionary and sets them in the |value_map|.
-  static void LoadExtensionControlledPrefs(ExtensionPrefs* prefs,
-                                           ExtensionPrefValueMap* value_map,
-                                           const std::string& extension_id,
-                                           ExtensionPrefsScope scope);
-
-  // Store extension controlled preference values in the |value_map|,
-  // which then informs the subscribers (ExtensionPrefStores) about the winning
-  // values.
-  static void InitExtensionControlledPrefs(ExtensionPrefs* prefs,
-                                           ExtensionPrefValueMap* value_map);
-
  private:
   friend class BrowserContextKeyedAPIFactory<PreferenceAPI>;
 
@@ -177,6 +164,8 @@
 // classes.
 class PreferenceFunction : public ChromeSyncExtensionFunction {
  protected:
+  enum PermissionType { PERMISSION_TYPE_READ, PERMISSION_TYPE_WRITE };
+
   virtual ~PreferenceFunction();
 
   // Given an |extension_pref_key|, provides its |browser_pref_key| from the
@@ -185,6 +174,7 @@
   // modify that pref. Sets |error_| if the extension doesn't have the needed
   // permission.
   bool ValidateBrowserPref(const std::string& extension_pref_key,
+                           PermissionType permission_type,
                            std::string* browser_pref_key);
 };
 
diff --git a/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc b/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc
index 5f2ef28..726e097 100644
--- a/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc
+++ b/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc
@@ -152,7 +152,8 @@
       prefs()->OnExtensionInstalled(extension,
                                     Extension::ENABLED,
                                     false,
-                                    syncer::StringOrdinal());
+                                    syncer::StringOrdinal(),
+                                    std::string());
       prefs()->SetIsIncognitoEnabled(extension->id(), true);
       installed_[i] = true;
       break;
diff --git a/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc b/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc
index e521c3f..65d1ed7 100644
--- a/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc
+++ b/chrome/browser/extensions/api/preferences_private/preferences_private_apitest.cc
@@ -122,12 +122,13 @@
 
     ProfileManager* profile_manager = g_browser_process->profile_manager();
     profile_manager->RegisterTestingProfile(profile, true, false);
-    browser_ = new Browser(Browser::CreateParams(
-        profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
 
     service_ = static_cast<FakeProfileSyncService*>(
         ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
         profile, &FakeProfileSyncService::BuildFakeProfileSyncService));
+
+    browser_ = new Browser(Browser::CreateParams(
+        profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
   }
 
   // Calls GetSyncCategoriesWithoutPassphraseFunction and verifies that the
diff --git a/chrome/browser/extensions/api/principals_private/principals_private_api.cc b/chrome/browser/extensions/api/principals_private/principals_private_api.cc
index b4fa4a2..0b7b8b9 100644
--- a/chrome/browser/extensions/api/principals_private/principals_private_api.cc
+++ b/chrome/browser/extensions/api/principals_private/principals_private_api.cc
@@ -32,8 +32,10 @@
 
 bool PrincipalsPrivateShowAvatarBubbleFunction::RunImplSafe() {
   Browser* browser = GetCurrentBrowser();
-  if (browser)
-    browser->window()->ShowAvatarBubbleFromAvatarButton();
+  if (browser) {
+    browser->window()->ShowAvatarBubbleFromAvatarButton(
+        BrowserWindow::AVATAR_BUBBLE_MODE_ACCOUNT_MANAGEMENT);
+  }
   return true;
 }
 
diff --git a/chrome/browser/extensions/api/processes/processes_api.cc b/chrome/browser/extensions/api/processes/processes_api.cc
index ce03675..852a64c 100644
--- a/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chrome/browser/extensions/api/processes/processes_api.cc
@@ -640,6 +640,7 @@
 
 
 void TerminateFunction::TerminateProcess() {
+#if defined(ENABLE_TASK_MANAGER)
   TaskManagerModel* model = TaskManager::GetInstance()->model();
 
   int count = model->ResourceCount();
@@ -669,6 +670,10 @@
 
   // Balance the AddRef in the RunImpl.
   Release();
+#else
+  error_ = errors::kExtensionNotSupported;
+  SendResponse(false);
+#endif  // defined(ENABLE_TASK_MANAGER)
 }
 
 GetProcessInfoFunction::GetProcessInfoFunction()
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
index 0cf9f74..1f05308 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_api.cc
@@ -24,7 +24,7 @@
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/extensions/api/push_messaging.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
@@ -167,7 +167,7 @@
 void PushMessagingGetChannelIdFunction::StartGaiaIdFetch(
     const std::string& access_token) {
   // Start the async fetch of the Gaia Id.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   net::URLRequestContextGetter* context = GetProfile()->GetRequestContext();
   fetcher_.reset(new ObfuscatedGaiaIdFetcher(context, this, access_token));
 
@@ -197,7 +197,7 @@
 
 void PushMessagingGetChannelIdFunction::ReportResult(
     const std::string& gaia_id, const std::string& error_string) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   BuildAndSendResult(gaia_id, error_string);
 
diff --git a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
index b0cad99..018f2f6 100644
--- a/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
+++ b/chrome/browser/extensions/api/push_messaging/push_messaging_invalidation_handler_unittest.cc
@@ -36,8 +36,8 @@
   MOCK_CONST_METHOD0(GetInvalidatorState, syncer::InvalidatorState());
   MOCK_CONST_METHOD0(GetInvalidatorClientId, std::string());
   MOCK_METHOD0(GetInvalidationLogger, invalidation::InvalidationLogger*());
-  MOCK_METHOD1(RequestDetailedStatus,
-               void(base::Callback<void(const base::DictionaryValue&)>));
+  MOCK_CONST_METHOD1(RequestDetailedStatus,
+                     void(base::Callback<void(const base::DictionaryValue&)>));
   MOCK_METHOD0(GetInvalidationAuthProvider,
                invalidation::InvalidationAuthProvider*());
 
diff --git a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
index 90ed076..f675fe5 100644
--- a/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
+++ b/chrome/browser/extensions/api/push_messaging/sync_setup_helper.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
+#include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/extensions/api/serial/serial_api.cc b/chrome/browser/extensions/api/serial/serial_api.cc
index a9ab198..827ce2b 100644
--- a/chrome/browser/extensions/api/serial/serial_api.cc
+++ b/chrome/browser/extensions/api/serial/serial_api.cc
@@ -83,7 +83,7 @@
 }
 
 void SerialGetDevicesFunction::Work() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   device::SerialDeviceInfoList devices;
   scoped_ptr<device::SerialDeviceEnumerator> enumerator =
@@ -142,7 +142,7 @@
 }
 
 void SerialConnectFunction::AsyncWorkStart() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   connection_ = CreateSerialConnection(params_->path, extension_->id());
   connection_->Open(base::Bind(&SerialConnectFunction::OnConnected, this));
 }
@@ -167,7 +167,7 @@
 }
 
 void SerialConnectFunction::FinishConnect() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!connection_) {
     error_ = kErrorConnectFailed;
   } else {
diff --git a/chrome/browser/extensions/api/serial/serial_connection.cc b/chrome/browser/extensions/api/serial/serial_connection.cc
index aee95a2..8ff045e 100644
--- a/chrome/browser/extensions/api/serial/serial_connection.cc
+++ b/chrome/browser/extensions/api/serial/serial_connection.cc
@@ -40,7 +40,7 @@
       send_timeout_(0),
       paused_(false),
       io_handler_(SerialIoHandler::Create()) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 }
 
 SerialConnection::~SerialConnection() {
@@ -72,7 +72,7 @@
 }
 
 void SerialConnection::Open(const OpenCompleteCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(open_complete_.is_null());
   open_complete_ = callback;
   BrowserThread::PostTask(
@@ -83,7 +83,7 @@
 
 void SerialConnection::Close() {
   DCHECK(open_complete_.is_null());
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (file_.IsValid()) {
     BrowserThread::PostTask(
         BrowserThread::FILE,
@@ -93,7 +93,7 @@
 }
 
 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!receive_complete_.is_null())
     return false;
   receive_complete_ = callback;
@@ -109,7 +109,7 @@
 
 bool SerialConnection::Send(const std::string& data,
                             const SendCompleteCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!send_complete_.is_null())
     return false;
   send_complete_ = callback;
@@ -125,7 +125,7 @@
 
 bool SerialConnection::Configure(
     const api::serial::ConnectionOptions& options) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (options.persistent.get())
     set_persistent(*options.persistent);
   if (options.name.get())
@@ -147,7 +147,7 @@
 }
 
 bool SerialConnection::GetInfo(api::serial::ConnectionInfo* info) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   info->paused = paused_;
   info->persistent = persistent_;
   info->name = name_;
@@ -159,7 +159,7 @@
 
 void SerialConnection::StartOpen() {
   DCHECK(!open_complete_.is_null());
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(!file_.IsValid());
   // It's the responsibility of the API wrapper around SerialConnection to
   // validate the supplied path against the set of valid port names, and
@@ -180,7 +180,7 @@
 }
 
 void SerialConnection::FinishOpen(base::File file) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!open_complete_.is_null());
   DCHECK(!file_.IsValid());
   OpenCompleteCallback callback = open_complete_;
@@ -209,23 +209,23 @@
 
 // static
 void SerialConnection::DoClose(base::File port) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   // port closed by destructor.
 }
 
 void SerialConnection::OnReceiveTimeout() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   io_handler_->CancelRead(api::serial::RECEIVE_ERROR_TIMEOUT);
 }
 
 void SerialConnection::OnSendTimeout() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   io_handler_->CancelWrite(api::serial::SEND_ERROR_TIMEOUT);
 }
 
 void SerialConnection::OnAsyncReadComplete(const std::string& data,
                                            api::serial::ReceiveError error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!receive_complete_.is_null());
   ReceiveCompleteCallback callback = receive_complete_;
   receive_complete_.Reset();
@@ -235,7 +235,7 @@
 
 void SerialConnection::OnAsyncWriteComplete(int bytes_sent,
                                             api::serial::SendError error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!send_complete_.is_null());
   SendCompleteCallback callback = send_complete_;
   send_complete_.Reset();
diff --git a/chrome/browser/extensions/api/serial/serial_event_dispatcher.cc b/chrome/browser/extensions/api/serial/serial_event_dispatcher.cc
index 06bbf8b..dc93796 100644
--- a/chrome/browser/extensions/api/serial/serial_event_dispatcher.cc
+++ b/chrome/browser/extensions/api/serial/serial_event_dispatcher.cc
@@ -57,7 +57,7 @@
 
 void SerialEventDispatcher::PollConnection(const std::string& extension_id,
                                            int connection_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   ReceiveParams params;
   params.thread_id = thread_id_;
@@ -71,7 +71,7 @@
 
 // static
 void SerialEventDispatcher::StartReceive(const ReceiveParams& params) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   SerialConnection* connection =
       params.connections->Get(params.extension_id, params.connection_id);
@@ -89,7 +89,7 @@
 void SerialEventDispatcher::ReceiveCallback(const ReceiveParams& params,
                                             const std::string& data,
                                             serial::ReceiveError error) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   // Note that an error (e.g. timeout) does not necessarily mean that no data
   // was read, so we may fire an onReceive regardless of any error code.
@@ -129,7 +129,7 @@
 // static
 void SerialEventDispatcher::PostEvent(const ReceiveParams& params,
                                       scoped_ptr<extensions::Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   BrowserThread::PostTask(
       BrowserThread::UI, FROM_HERE,
@@ -143,7 +143,7 @@
 void SerialEventDispatcher::DispatchEvent(void* profile_id,
                                           const std::string& extension_id,
                                           scoped_ptr<extensions::Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   Profile* profile = reinterpret_cast<Profile*>(profile_id);
   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
diff --git a/chrome/browser/extensions/api/sessions/sessions_api.cc b/chrome/browser/extensions/api/sessions/sessions_api.cc
index 5523200..eca014e 100644
--- a/chrome/browser/extensions/api/sessions/sessions_api.cc
+++ b/chrome/browser/extensions/api/sessions/sessions_api.cc
@@ -53,6 +53,8 @@
 const char kNoBrowserToRestoreSession[] =
     "There are no browser windows to restore the session.";
 const char kSessionSyncError[] = "Synced sessions are not available.";
+const char kRestoreInIncognitoError[] =
+    "Can not restore sessions in incognito mode.";
 
 // Comparator function for use with std::sort that will sort sessions by
 // descending modified_time (i.e., most recent first).
@@ -205,7 +207,16 @@
   std::vector<linked_ptr<api::sessions::Session> > result;
   TabRestoreService* tab_restore_service =
       TabRestoreServiceFactory::GetForProfile(GetProfile());
-  DCHECK(tab_restore_service);
+
+  // TabRestoreServiceFactory::GetForProfile() can return NULL (i.e., when in
+  // incognito mode)
+  if (!tab_restore_service) {
+    DCHECK_NE(GetProfile(), GetProfile()->GetOriginalProfile())
+        << "TabRestoreService expected for normal profiles";
+    results_ = GetRecentlyClosed::Results::Create(
+        std::vector<linked_ptr<api::sessions::Session> >());
+    return true;
+  }
 
   // List of entries. They are ordered from most to least recent.
   // We prune the list to contain max 25 entries at any time and removes
@@ -563,6 +574,11 @@
     return false;
   }
 
+  if (GetProfile() != GetProfile()->GetOriginalProfile()) {
+    SetError(kRestoreInIncognitoError);
+    return false;
+  }
+
   if (!params->session_id)
     return RestoreMostRecentlyClosed(browser);
 
diff --git a/chrome/browser/extensions/api/sessions/sessions_apitest.cc b/chrome/browser/extensions/api/sessions/sessions_apitest.cc
index 28df32e..398659d 100644
--- a/chrome/browser/extensions/api/sessions/sessions_apitest.cc
+++ b/chrome/browser/extensions/api/sessions/sessions_apitest.cc
@@ -111,11 +111,11 @@
   Profile* profile =
       Profile::CreateProfile(path, NULL, Profile::CREATE_MODE_SYNCHRONOUS);
   profile_manager->RegisterTestingProfile(profile, true, false);
-  browser_ = new Browser(Browser::CreateParams(
-      profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
   ProfileSyncServiceMock* service = static_cast<ProfileSyncServiceMock*>(
       ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
       profile, &ProfileSyncServiceMock::BuildMockProfileSyncService));
+  browser_ = new Browser(Browser::CreateParams(
+      profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
 
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kDisableSyncSessionsV2)) {
@@ -311,6 +311,27 @@
       browser_), "Invalid session id: \"tag3.0\"."));
 }
 
+IN_PROC_BROWSER_TEST_F(ExtensionSessionsTest, RestoreInIncognito) {
+  CreateSessionModels();
+
+  EXPECT_TRUE(MatchPattern(utils::RunFunctionAndReturnError(
+      CreateFunction<SessionsRestoreFunction>(true).get(),
+      "[\"1\"]",
+      CreateIncognitoBrowser()),
+      "Can not restore sessions in incognito mode."));
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionSessionsTest, GetRecentlyClosedIncognito) {
+  scoped_ptr<base::ListValue> result(utils::ToList(
+      utils::RunFunctionAndReturnSingleResult(
+          CreateFunction<SessionsGetRecentlyClosedFunction>(true).get(),
+          "[]",
+          CreateIncognitoBrowser())));
+  ASSERT_TRUE(result);
+  base::ListValue* sessions = result.get();
+  EXPECT_EQ(0u, sessions->GetSize());
+}
+
 // Flaky on ChromeOS, times out on OSX Debug http://crbug.com/251199
 #if defined(OS_CHROMEOS) || (defined(OS_MACOSX) && !defined(NDEBUG))
 #define MAYBE_SessionsApis DISABLED_SessionsApis
diff --git a/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc b/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
index 9752129..73a3d60 100644
--- a/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
+++ b/chrome/browser/extensions/api/settings_overrides/settings_overrides_api.cc
@@ -24,6 +24,7 @@
 namespace extensions {
 
 namespace {
+
 base::LazyInstance<BrowserContextKeyedAPIFactory<SettingsOverridesAPI> >
     g_factory = LAZY_INSTANCE_INITIALIZER;
 
@@ -32,19 +33,33 @@
 
 using api::manifest_types::ChromeSettingsOverrides;
 
+std::string SubstituteInstallParam(std::string str,
+                                   const std::string& install_parameter) {
+  ReplaceSubstringsAfterOffset(&str, 0, "__PARAM__", install_parameter);
+  return str;
+}
+
 TemplateURLData ConvertSearchProvider(
-    const ChromeSettingsOverrides::Search_provider& search_provider) {
+    const ChromeSettingsOverrides::Search_provider& search_provider,
+    const std::string& install_parameter) {
   TemplateURLData data;
 
   data.short_name = base::UTF8ToUTF16(search_provider.name);
   data.SetKeyword(base::UTF8ToUTF16(search_provider.keyword));
-  data.SetURL(search_provider.search_url);
-  if (search_provider.suggest_url)
-    data.suggestions_url = *search_provider.suggest_url;
-  if (search_provider.instant_url)
-    data.instant_url = *search_provider.instant_url;
-  if (search_provider.image_url)
-    data.image_url = *search_provider.image_url;
+  data.SetURL(
+      SubstituteInstallParam(search_provider.search_url, install_parameter));
+  if (search_provider.suggest_url) {
+    data.suggestions_url =
+        SubstituteInstallParam(*search_provider.suggest_url, install_parameter);
+  }
+  if (search_provider.instant_url) {
+    data.instant_url =
+        SubstituteInstallParam(*search_provider.instant_url, install_parameter);
+  }
+  if (search_provider.image_url) {
+    data.image_url =
+        SubstituteInstallParam(*search_provider.image_url, install_parameter);
+  }
   if (search_provider.search_url_post_params)
     data.search_url_post_params = *search_provider.search_url_post_params;
   if (search_provider.suggest_url_post_params)
@@ -53,7 +68,8 @@
     data.instant_url_post_params = *search_provider.instant_url_post_params;
   if (search_provider.image_url_post_params)
     data.image_url_post_params = *search_provider.image_url_post_params;
-  data.favicon_url = GURL(search_provider.favicon_url);
+  data.favicon_url = GURL(
+      SubstituteInstallParam(search_provider.favicon_url, install_parameter));
   data.show_in_default_list = true;
   data.safe_for_autoreplace = false;
   data.input_encodings.push_back(search_provider.encoding);
@@ -63,11 +79,13 @@
   if (search_provider.alternate_urls) {
     for (size_t i = 0; i < search_provider.alternate_urls->size(); ++i) {
       if (!search_provider.alternate_urls->at(i).empty())
-        data.alternate_urls.push_back(search_provider.alternate_urls->at(i));
+        data.alternate_urls.push_back(SubstituteInstallParam(
+            search_provider.alternate_urls->at(i), install_parameter));
     }
   }
   return data;
 }
+
 }  // namespace
 
 SettingsOverridesAPI::SettingsOverridesAPI(content::BrowserContext* context)
@@ -119,9 +137,13 @@
       const SettingsOverrides* settings =
           SettingsOverrides::Get(extension);
       if (settings) {
+        std::string install_parameter =
+            ExtensionPrefs::Get(profile_)->GetInstallParam(extension->id());
         if (settings->homepage) {
-          SetPref(extension->id(), prefs::kHomePage,
-                  new base::StringValue(settings->homepage->spec()));
+          SetPref(extension->id(),
+                  prefs::kHomePage,
+                  new base::StringValue(SubstituteInstallParam(
+                      settings->homepage->spec(), install_parameter)));
           SetPref(extension->id(), prefs::kHomePageIsNewTabPage,
                   new base::FundamentalValue(false));
         }
@@ -134,8 +156,8 @@
                 kManyStartupPagesWarning, manifest_keys::kSettingsOverride);
           }
           scoped_ptr<base::ListValue> url_list(new base::ListValue);
-          url_list->Append(
-              new base::StringValue(settings->startup_pages[0].spec()));
+          url_list->Append(new base::StringValue(SubstituteInstallParam(
+              settings->startup_pages[0].spec(), install_parameter)));
           SetPref(extension->id(), prefs::kURLsToRestoreOnStartup,
                   url_list.release());
         }
@@ -213,9 +235,11 @@
   scoped_ptr<AssociatedExtensionInfo> info(new AssociatedExtensionInfo);
   info->extension_id = extension->id();
   info->wants_to_be_default_engine = settings->search_engine->is_default;
-  info->install_time =
-      ExtensionPrefs::Get(profile_)->GetInstallTime(extension->id());
-  TemplateURLData data = ConvertSearchProvider(*settings->search_engine);
+  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
+  info->install_time = prefs->GetInstallTime(extension->id());
+  std::string install_parameter = prefs->GetInstallParam(extension->id());
+  TemplateURLData data =
+      ConvertSearchProvider(*settings->search_engine, install_parameter);
   url_service_->AddExtensionControlledTURL(new TemplateURL(profile_, data),
                                            info.Pass());
 }
diff --git a/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc b/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
index 6170f9e..6774c61 100644
--- a/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
+++ b/chrome/browser/extensions/api/settings_overrides/settings_overrides_browsertest.cc
@@ -68,38 +68,41 @@
   EXPECT_EQ(TemplateURL::NORMAL, default_provider->GetType());
 
 #if defined(OS_WIN)
-  const extensions::Extension* extension = LoadExtension(
-      test_data_dir_.AppendASCII("settings_override"));
+  const extensions::Extension* extension = LoadExtensionWithInstallParam(
+      test_data_dir_.AppendASCII("settings_override"),
+      kFlagEnableFileAccess,
+      "10");
   ASSERT_TRUE(extension);
-  EXPECT_EQ("http://www.homepage.com/", prefs->GetString(prefs::kHomePage));
+  EXPECT_EQ("http://www.homepage.de/?param=10",
+            prefs->GetString(prefs::kHomePage));
   EXPECT_FALSE(prefs->GetBoolean(prefs::kHomePageIsNewTabPage));
   startup_pref = SessionStartupPref::GetStartupPref(prefs);
   EXPECT_EQ(SessionStartupPref::URLS, startup_pref.type);
-  EXPECT_EQ(std::vector<GURL>(1, GURL("http://www.startup.com")),
+  EXPECT_EQ(std::vector<GURL>(1, GURL("http://www.startup.de/?param=10")),
             startup_pref.urls);
   TemplateURL* extension_provider = url_service->GetDefaultSearchProvider();
   EXPECT_EQ(TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION,
             extension_provider->GetType());
   EXPECT_EQ(base::ASCIIToUTF16("name.de"), extension_provider->short_name());
   EXPECT_EQ(base::ASCIIToUTF16("keyword.de"), extension_provider->keyword());
-  EXPECT_EQ("http://www.foo.de/s?q={searchTerms}", extension_provider->url());
-  EXPECT_EQ(GURL("http://www.foo.de/favicon.ico"),
+  EXPECT_EQ("http://www.foo.de/s?q={searchTerms}&id=10",
+            extension_provider->url());
+  EXPECT_EQ(GURL("http://www.foo.de/favicon.ico?id=10"),
             extension_provider->favicon_url());
-  EXPECT_EQ("http://www.foo.de/suggest?q={searchTerms}",
+  EXPECT_EQ("http://www.foo.de/suggest?q={searchTerms}&id=10",
             extension_provider->suggestions_url());
-  EXPECT_EQ("http://www.foo.de/instant?q={searchTerms}",
+  EXPECT_EQ("http://www.foo.de/instant?q={searchTerms}&id=10",
             extension_provider->instant_url());
-  EXPECT_EQ("http://www.foo.de/image?q={searchTerms}",
-              extension_provider->image_url());
+  EXPECT_EQ("http://www.foo.de/image?q={searchTerms}&id=10",
+            extension_provider->image_url());
   EXPECT_EQ("search_lang=de", extension_provider->search_url_post_params());
   EXPECT_EQ("suggest_lang=de",
             extension_provider->suggestions_url_post_params());
   EXPECT_EQ("instant_lang=de", extension_provider->instant_url_post_params());
   EXPECT_EQ("image_lang=de", extension_provider->image_url_post_params());
   const std::string alternate_urls[] = {
-      "http://www.moo.de/s?q={searchTerms}",
-      "http://www.noo.de/s?q={searchTerms}"
-  };
+      "http://www.moo.de/s?q={searchTerms}&id=10",
+      "http://www.noo.de/s?q={searchTerms}&id=10"};
   EXPECT_EQ(std::vector<std::string>(
                 alternate_urls, alternate_urls + arraysize(alternate_urls)),
             extension_provider->alternate_urls());
diff --git a/chrome/browser/extensions/api/socket/socket_apitest.cc b/chrome/browser/extensions/api/socket/socket_apitest.cc
index 7d38649..b01e6a6 100644
--- a/chrome/browser/extensions/api/socket/socket_apitest.cc
+++ b/chrome/browser/extensions/api/socket/socket_apitest.cc
@@ -5,7 +5,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
 #include "chrome/browser/extensions/api/dns/mock_host_resolver_creator.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
@@ -16,6 +15,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
 #include "extensions/browser/api/socket/socket_api.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
diff --git a/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_apitest.cc b/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_apitest.cc
index 60546e4..0b419ad 100644
--- a/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_apitest.cc
+++ b/chrome/browser/extensions/api/sockets_tcp/sockets_tcp_apitest.cc
@@ -5,7 +5,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
 #include "chrome/browser/extensions/api/dns/mock_host_resolver_creator.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
@@ -16,6 +15,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
 #include "extensions/browser/api/sockets_tcp/sockets_tcp_api.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
diff --git a/chrome/browser/extensions/api/sockets_tcp_server/sockets_tcp_server_apitest.cc b/chrome/browser/extensions/api/sockets_tcp_server/sockets_tcp_server_apitest.cc
index c93a926..f4a4006 100644
--- a/chrome/browser/extensions/api/sockets_tcp_server/sockets_tcp_server_apitest.cc
+++ b/chrome/browser/extensions/api/sockets_tcp_server/sockets_tcp_server_apitest.cc
@@ -5,7 +5,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
 #include "chrome/browser/extensions/api/dns/mock_host_resolver_creator.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
@@ -16,6 +15,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
 #include "extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
diff --git a/chrome/browser/extensions/api/sockets_udp/sockets_udp_apitest.cc b/chrome/browser/extensions/api/sockets_udp/sockets_udp_apitest.cc
index e9b4564..0f203c7 100644
--- a/chrome/browser/extensions/api/sockets_udp/sockets_udp_apitest.cc
+++ b/chrome/browser/extensions/api/sockets_udp/sockets_udp_apitest.cc
@@ -5,7 +5,6 @@
 #include "base/memory/ref_counted.h"
 #include "base/path_service.h"
 #include "base/strings/stringprintf.h"
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
 #include "chrome/browser/extensions/api/dns/mock_host_resolver_creator.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/extensions/extension_function_test_utils.h"
@@ -17,6 +16,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
 #include "extensions/browser/api/sockets_udp/sockets_udp_api.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
diff --git a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
index 562117b..814d949 100644
--- a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
+++ b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc
@@ -221,7 +221,7 @@
 
 void ManagedValueStoreCache::ExtensionTracker::Register(
     const policy::ComponentMap* components) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   schema_registry_->RegisterComponents(policy::POLICY_DOMAIN_EXTENSIONS,
                                        *components);
 
@@ -245,7 +245,7 @@
       observers_(observers),
       base_path_(profile_->GetPath().AppendASCII(
           extensions::kManagedSettingsDirectoryName)) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   policy_service_->AddObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
 
@@ -258,13 +258,13 @@
 }
 
 ManagedValueStoreCache::~ManagedValueStoreCache() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   // Delete the PolicyValueStores on FILE.
   store_map_.clear();
 }
 
 void ManagedValueStoreCache::ShutdownOnUI() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   policy_service_->RemoveObserver(policy::POLICY_DOMAIN_EXTENSIONS, this);
   extension_tracker_.reset();
 }
@@ -272,13 +272,13 @@
 void ManagedValueStoreCache::RunWithValueStoreForExtension(
     const StorageCallback& callback,
     scoped_refptr<const Extension> extension) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   callback.Run(GetStoreFor(extension->id()));
 }
 
 void ManagedValueStoreCache::DeleteStorageSoon(
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   // It's possible that the store exists, but hasn't been loaded yet
   // (because the extension is unloaded, for example). Open the database to
   // clear it if it exists.
@@ -290,7 +290,7 @@
 
 void ManagedValueStoreCache::OnPolicyServiceInitialized(
     policy::PolicyDomain domain) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (domain != policy::POLICY_DOMAIN_EXTENSIONS)
     return;
@@ -318,7 +318,7 @@
 void ManagedValueStoreCache::OnPolicyUpdated(const policy::PolicyNamespace& ns,
                                              const policy::PolicyMap& previous,
                                              const policy::PolicyMap& current) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!policy_service_->IsInitializationComplete(
            policy::POLICY_DOMAIN_EXTENSIONS)) {
@@ -339,7 +339,7 @@
 void ManagedValueStoreCache::UpdatePolicyOnFILE(
     const std::string& extension_id,
     scoped_ptr<policy::PolicyMap> current_policy) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (!HasStore(extension_id) && current_policy->empty()) {
     // Don't create the store now if there are no policies configured for this
@@ -353,7 +353,7 @@
 
 PolicyValueStore* ManagedValueStoreCache::GetStoreFor(
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   PolicyValueStoreMap::iterator it = store_map_.find(extension_id);
   if (it != store_map_.end())
diff --git a/chrome/browser/extensions/api/storage/policy_value_store.cc b/chrome/browser/extensions/api/storage/policy_value_store.cc
index 4700095..900b7c7 100644
--- a/chrome/browser/extensions/api/storage/policy_value_store.cc
+++ b/chrome/browser/extensions/api/storage/policy_value_store.cc
@@ -39,7 +39,7 @@
 PolicyValueStore::~PolicyValueStore() {}
 
 void PolicyValueStore::SetCurrentPolicy(const policy::PolicyMap& policy) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   // Convert |policy| to a dictionary value. Only include mandatory policies
   // for now.
   base::DictionaryValue current_policy;
diff --git a/chrome/browser/extensions/api/storage/settings_sync_processor.cc b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
index 95e0df5..96ef468 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_processor.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_processor.cc
@@ -22,17 +22,17 @@
       type_(type),
       sync_processor_(sync_processor),
       initialized_(false) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   CHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS);
   CHECK(sync_processor);
 }
 
 SettingsSyncProcessor::~SettingsSyncProcessor() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 }
 
 void SettingsSyncProcessor::Init(const base::DictionaryValue& initial_state) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   CHECK(!initialized_) << "Init called multiple times";
 
   for (base::DictionaryValue::Iterator i(initial_state); !i.IsAtEnd();
@@ -44,7 +44,7 @@
 
 syncer::SyncError SettingsSyncProcessor::SendChanges(
     const ValueStoreChangeList& changes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   CHECK(initialized_) << "Init not called";
 
   syncer::SyncChangeList sync_changes;
@@ -96,7 +96,7 @@
 }
 
 void SettingsSyncProcessor::NotifyChanges(const ValueStoreChangeList& changes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   CHECK(initialized_) << "Init not called";
 
   for (ValueStoreChangeList::const_iterator i = changes.begin();
diff --git a/chrome/browser/extensions/api/storage/settings_sync_util.cc b/chrome/browser/extensions/api/storage/settings_sync_util.cc
index b326661..c187c52 100644
--- a/chrome/browser/extensions/api/storage/settings_sync_util.cc
+++ b/chrome/browser/extensions/api/storage/settings_sync_util.cc
@@ -112,7 +112,7 @@
 
 syncer::SyncableService* GetSyncableService(content::BrowserContext* context,
                                             syncer::ModelType type) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(type == syncer::APP_SETTINGS || type == syncer::EXTENSION_SETTINGS);
   StorageFrontend* frontend = StorageFrontend::Get(context);
   SyncValueStoreCache* sync_cache = static_cast<SyncValueStoreCache*>(
diff --git a/chrome/browser/extensions/api/storage/sync_storage_backend.cc b/chrome/browser/extensions/api/storage/sync_storage_backend.cc
index e3c97d5..eb4effa 100644
--- a/chrome/browser/extensions/api/storage/sync_storage_backend.cc
+++ b/chrome/browser/extensions/api/storage/sync_storage_backend.cc
@@ -43,7 +43,7 @@
       observers_(observers),
       sync_type_(sync_type),
       flare_(flare) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(sync_type_ == syncer::EXTENSION_SETTINGS ||
          sync_type_ == syncer::APP_SETTINGS);
 }
@@ -51,7 +51,7 @@
 SyncStorageBackend::~SyncStorageBackend() {}
 
 ValueStore* SyncStorageBackend::GetStorage(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   base::DictionaryValue empty;
   return GetOrCreateStorageWithSyncData(extension_id, empty);
 }
@@ -59,7 +59,7 @@
 SyncableSettingsStorage* SyncStorageBackend::GetOrCreateStorageWithSyncData(
     const std::string& extension_id,
     const base::DictionaryValue& sync_data) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id);
   if (maybe_storage != storage_objs_.end()) {
@@ -87,7 +87,7 @@
 }
 
 void SyncStorageBackend::DeleteStorage(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   // Clear settings when the extension is uninstalled.  Leveldb implementations
   // will also delete the database from disk when the object is destroyed as a
@@ -105,7 +105,7 @@
 }
 
 std::set<std::string> SyncStorageBackend::GetKnownExtensionIDs() const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   std::set<std::string> result;
 
   // Storage areas can be in-memory as well as on disk. |storage_objs_| will
@@ -134,7 +134,7 @@
 
 syncer::SyncDataList SyncStorageBackend::GetAllSyncData(syncer::ModelType type)
     const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   // Ignore the type, it's just for sanity checking; assume that whatever base
   // path we're constructed with is correct for the sync type.
   DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS);
@@ -165,7 +165,7 @@
     const syncer::SyncDataList& initial_sync_data,
     scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
     scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK_EQ(sync_type_, type);
   DCHECK(!sync_processor_.get());
   DCHECK(sync_processor.get());
@@ -231,7 +231,7 @@
 syncer::SyncError SyncStorageBackend::ProcessSyncChanges(
     const tracked_objects::Location& from_here,
     const syncer::SyncChangeList& sync_changes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(sync_processor_.get());
 
   // Group changes by extension, to pass all changes in a single method call.
@@ -260,7 +260,7 @@
 }
 
 void SyncStorageBackend::StopSyncing(syncer::ModelType type) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS);
   DCHECK_EQ(sync_type_, type);
 
diff --git a/chrome/browser/extensions/api/storage/sync_value_store_cache.cc b/chrome/browser/extensions/api/storage/sync_value_store_cache.cc
index 079bae7..c8fe8ed 100644
--- a/chrome/browser/extensions/api/storage/sync_value_store_cache.cc
+++ b/chrome/browser/extensions/api/storage/sync_value_store_cache.cc
@@ -41,7 +41,7 @@
     const scoped_refptr<SettingsObserverList>& observers,
     const base::FilePath& profile_path)
     : initialized_(false) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // This post is safe since the destructor can only be invoked from the
   // same message loop, and any potential post of a deletion task must come
@@ -54,12 +54,12 @@
 }
 
 SyncValueStoreCache::~SyncValueStoreCache() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 }
 
 syncer::SyncableService* SyncValueStoreCache::GetSyncableService(
     syncer::ModelType type) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(initialized_);
 
   switch (type) {
@@ -76,7 +76,7 @@
 void SyncValueStoreCache::RunWithValueStoreForExtension(
     const StorageCallback& callback,
     scoped_refptr<const Extension> extension) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(initialized_);
   SyncStorageBackend* backend =
       extension->is_app() ? app_backend_.get() : extension_backend_.get();
@@ -84,7 +84,7 @@
 }
 
 void SyncValueStoreCache::DeleteStorageSoon(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   app_backend_->DeleteStorage(extension_id);
   extension_backend_->DeleteStorage(extension_id);
 }
@@ -93,7 +93,7 @@
     const scoped_refptr<SettingsStorageFactory>& factory,
     const scoped_refptr<SettingsObserverList>& observers,
     const base::FilePath& profile_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(!initialized_);
   app_backend_.reset(new SyncStorageBackend(
       factory,
diff --git a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
index dfbb091..95d95ec 100644
--- a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
+++ b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
@@ -28,49 +28,49 @@
       delegate_(delegate),
       sync_type_(sync_type),
       flare_(flare) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 }
 
 SyncableSettingsStorage::~SyncableSettingsStorage() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 }
 
 size_t SyncableSettingsStorage::GetBytesInUse(const std::string& key) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return delegate_->GetBytesInUse(key);
 }
 
 size_t SyncableSettingsStorage::GetBytesInUse(
     const std::vector<std::string>& keys) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return delegate_->GetBytesInUse(keys);
 }
 
 size_t SyncableSettingsStorage::GetBytesInUse() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return delegate_->GetBytesInUse();
 }
 
 ValueStore::ReadResult SyncableSettingsStorage::Get(
     const std::string& key) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return delegate_->Get(key);
 }
 
 ValueStore::ReadResult SyncableSettingsStorage::Get(
     const std::vector<std::string>& keys) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return delegate_->Get(keys);
 }
 
 ValueStore::ReadResult SyncableSettingsStorage::Get() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return delegate_->Get();
 }
 
 ValueStore::WriteResult SyncableSettingsStorage::Set(
     WriteOptions options, const std::string& key, const base::Value& value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   WriteResult result = delegate_->Set(options, key, value);
   if (result->HasError()) {
     return result.Pass();
@@ -81,7 +81,7 @@
 
 ValueStore::WriteResult SyncableSettingsStorage::Set(
     WriteOptions options, const base::DictionaryValue& values) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   WriteResult result = delegate_->Set(options, values);
   if (result->HasError()) {
     return result.Pass();
@@ -92,7 +92,7 @@
 
 ValueStore::WriteResult SyncableSettingsStorage::Remove(
     const std::string& key) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   WriteResult result = delegate_->Remove(key);
   if (result->HasError()) {
     return result.Pass();
@@ -103,7 +103,7 @@
 
 ValueStore::WriteResult SyncableSettingsStorage::Remove(
     const std::vector<std::string>& keys) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   WriteResult result = delegate_->Remove(keys);
   if (result->HasError()) {
     return result.Pass();
@@ -113,7 +113,7 @@
 }
 
 ValueStore::WriteResult SyncableSettingsStorage::Clear() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   WriteResult result = delegate_->Clear();
   if (result->HasError()) {
     return result.Pass();
@@ -166,7 +166,7 @@
 syncer::SyncError SyncableSettingsStorage::StartSyncing(
     const base::DictionaryValue& sync_state,
     scoped_ptr<SettingsSyncProcessor> sync_processor) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(!sync_processor_.get());
 
   sync_processor_ = sync_processor.Pass();
@@ -190,7 +190,7 @@
 
 syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync(
     const base::DictionaryValue& settings) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   ValueStoreChangeList changes;
   for (base::DictionaryValue::Iterator i(settings); !i.IsAtEnd(); i.Advance()) {
@@ -210,7 +210,7 @@
 syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync(
     const base::DictionaryValue& sync_state,
     const base::DictionaryValue& settings) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   // Treat this as a list of changes to sync and use ProcessSyncChanges.
   // This gives notifications etc for free.
   scoped_ptr<base::DictionaryValue> new_sync_state(sync_state.DeepCopy());
@@ -263,13 +263,13 @@
 }
 
 void SyncableSettingsStorage::StopSyncing() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   sync_processor_.reset();
 }
 
 syncer::SyncError SyncableSettingsStorage::ProcessSyncChanges(
     const SettingSyncDataList& sync_changes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(!sync_changes.empty()) << "No sync changes for " << extension_id_;
 
   if (!sync_processor_.get()) {
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_api.cc b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
index 7909b11..9327399 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_api.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_api.cc
@@ -19,6 +19,31 @@
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_function_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "net/http/http_response_headers.h"
+
+namespace {
+
+void CreateResponseHeadersDictionary(const net::HttpResponseHeaders* headers,
+                                     base::DictionaryValue* result) {
+  if (!headers)
+    return;
+
+  void* iter = NULL;
+  std::string header_name;
+  std::string header_value;
+  while (headers->EnumerateHeaderLines(&iter, &header_name, &header_value)) {
+    base::Value* existing_value = NULL;
+    if (result->Get(header_name, &existing_value)) {
+      base::StringValue* existing_string_value =
+          static_cast<base::StringValue*>(existing_value);
+      existing_string_value->GetString()->append(", ").append(header_value);
+    } else {
+      result->SetString(header_name, header_value);
+    }
+  }
+}
+
+}  // namespace
 
 namespace extensions {
 
@@ -55,7 +80,9 @@
   if (expected_content_size <= INT_MAX)
     size = expected_content_size;
   info.expected_content_size = size;
-  info.response_headers = stream->GetResponseHeaders();
+
+  CreateResponseHeadersDictionary(stream->GetResponseHeaders().get(),
+                                  &info.response_headers.additional_properties);
 
   scoped_ptr<Event> event(
       new Event(streams_private::OnExecuteMimeTypeHandler::kEventName,
diff --git a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
index 378b924..fd418c9 100644
--- a/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
+++ b/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc
@@ -61,6 +61,17 @@
     return response.PassAs<HttpResponse>();
   }
 
+  // For relative path "/spreadsheet_path.xls", return success response with
+  // MIME type "application/xls".
+  if (request.relative_url == "/spreadsheet_path.xls") {
+    response->set_code(net::HTTP_OK);
+    response->set_content_type("application/msexcel");
+    // Test that multiple headers with the same name are merged.
+    response->AddCustomHeader("Test-Header", "part1");
+    response->AddCustomHeader("Test-Header", "part2");
+    return response.PassAs<HttpResponse>();
+  }
+
   // For relative path "/text_path_attch.txt", return success response with
   // MIME type "text/plain" and content "txt content". Also, set content
   // disposition to be attachment.
@@ -380,4 +391,34 @@
   EXPECT_TRUE(catcher.GetNextResult());
 }
 
+// Tests that response headers are correctly passed to the API and that multiple
+// repsonse headers with the same name are merged correctly.
+IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Headers) {
+#if defined(OS_WIN) && defined(USE_ASH)
+  // Disable this test in Metro+Ash for now (http://crbug.com/262796).
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
+    return;
+#endif
+
+  ASSERT_TRUE(LoadTestExtension()) << message_;
+
+  ResultCatcher catcher;
+
+  ui_test_utils::NavigateToURL(browser(),
+                               test_server_->GetURL("/spreadsheet_path.xls"));
+
+  // Wait for the response from the test server.
+  base::MessageLoop::current()->RunUntilIdle();
+
+  // There should be no downloads started by the navigation.
+  DownloadManager* download_manager = GetDownloadManager();
+  std::vector<DownloadItem*> downloads;
+  download_manager->GetAllDownloads(&downloads);
+  ASSERT_EQ(0u, downloads.size());
+
+  // The test extension should receive onExecuteContentHandler event with MIME
+  // type 'application/msexcel' (and call chrome.test.notifySuccess).
+  EXPECT_TRUE(catcher.GetNextResult());
+}
+
 }  // namespace
diff --git a/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc b/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
index b548029..5323dc6 100644
--- a/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
+++ b/chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.cc
@@ -6,7 +6,6 @@
 
 #include "base/lazy_instance.h"
 #include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/sync_file_system/sync_event_observer.h"
 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
index e55a2d2..a788cd7 100644
--- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
+++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_api.cc
@@ -92,7 +92,7 @@
     base::File::Error error) {
   // Repost to switch from IO thread to UI thread for SendResponse().
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     BrowserThread::PostTask(
         BrowserThread::UI,
         FROM_HERE,
@@ -101,7 +101,7 @@
     return;
   }
 
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (error != base::File::FILE_OK) {
     error_ = ErrorToString(sync_file_system::FileErrorToSyncStatusCode(error));
     SetResult(new base::FundamentalValue(false));
@@ -146,7 +146,7 @@
     base::File::Error error) {
   // Repost to switch from IO thread to UI thread for SendResponse().
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     BrowserThread::PostTask(
         BrowserThread::UI, FROM_HERE,
         Bind(&SyncFileSystemRequestFileSystemFunction::DidOpenFileSystem,
@@ -154,7 +154,7 @@
     return;
   }
 
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (error != base::File::FILE_OK) {
     error_ = ErrorToString(sync_file_system::FileErrorToSyncStatusCode(error));
     SendResponse(false);
@@ -188,7 +188,7 @@
 void SyncFileSystemGetFileStatusFunction::DidGetFileStatus(
     const SyncStatusCode sync_status_code,
     const SyncFileStatus sync_file_status) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (sync_status_code != sync_file_system::SYNC_STATUS_OK) {
     error_ = ErrorToString(sync_status_code);
     SendResponse(false);
@@ -243,7 +243,7 @@
     const fileapi::FileSystemURL& file_system_url,
     SyncStatusCode sync_status_code,
     SyncFileStatus sync_file_status) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   num_results_received_++;
   DCHECK_LE(num_results_received_, num_expected_results_);
 
@@ -317,7 +317,7 @@
       quota::QuotaStatusCode status, int64 usage, int64 quota) {
   // Repost to switch from IO thread to UI thread for SendResponse().
   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     BrowserThread::PostTask(
         BrowserThread::UI,
         FROM_HERE,
@@ -326,7 +326,7 @@
     return;
   }
 
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (status != quota::kQuotaStatusOk) {
     error_ = QuotaStatusCodeToString(status);
     SendResponse(false);
diff --git a/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc b/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc
index 6ae688e..aeab4b6 100644
--- a/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc
+++ b/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc
@@ -6,7 +6,6 @@
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
 #include "chrome/browser/sync_file_system/file_status_observer.h"
@@ -104,12 +103,6 @@
 
 }  // namespace
 
-// deleteFileSystem is disabled for now. http://crbug.com/159804
-IN_PROC_BROWSER_TEST_F(SyncFileSystemApiTest, DISABLED_DeleteFileSystem) {
-  ASSERT_TRUE(RunPlatformAppTest("sync_file_system/delete_file_system"))
-      << message_;
-}
-
 // Flaky on WinXP Tests(1): http://crbug.com/354425
 #if defined(OS_WIN) && defined(ARCH_CPU_X86)
 #define MAYBE_GetFileStatus DISABLED_GetFileStatus
@@ -122,7 +115,7 @@
       << message_;
 }
 
-#if defined(ADDRESS_SANITIZER) || (defined(OS_WIN) && defined(ARCH_CPU_X86))
+#if defined(OS_WIN) && defined(ARCH_CPU_X86)
 // SyncFileSystemApiTest.GetFileStatuses fails under AddressSanitizer
 // on Precise. See http://crbug.com/230779.
 // Also fails on WinXP Tests(1). See crbug.com/354425 .
diff --git a/chrome/browser/extensions/api/system_info/system_info_api.cc b/chrome/browser/extensions/api/system_info/system_info_api.cc
index 099cfd5..a73a368 100644
--- a/chrome/browser/extensions/api/system_info/system_info_api.cc
+++ b/chrome/browser/extensions/api/system_info/system_info_api.cc
@@ -114,7 +114,7 @@
 }
 
 void SystemInfoEventRouter::AddEventListener(const std::string& event_name) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   watching_event_set_.insert(event_name);
   if (watching_event_set_.count(event_name) > 1)
@@ -136,7 +136,7 @@
 }
 
 void SystemInfoEventRouter::RemoveEventListener(const std::string& event_name) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::multiset<std::string>::iterator it =
       watching_event_set_.find(event_name);
diff --git a/chrome/browser/extensions/api/system_info/system_info_provider.cc b/chrome/browser/extensions/api/system_info/system_info_provider.cc
index dae986d..3ecccb4 100644
--- a/chrome/browser/extensions/api/system_info/system_info_provider.cc
+++ b/chrome/browser/extensions/api/system_info/system_info_provider.cc
@@ -28,7 +28,7 @@
 
 void SystemInfoProvider::StartQueryInfo(
     const QueryInfoCompletionCallback& callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK(!callback.is_null());
 
   callbacks_.push(callback);
@@ -43,7 +43,7 @@
 }
 
 void SystemInfoProvider::OnQueryCompleted(bool success) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   while (!callbacks_.empty()) {
     QueryInfoCompletionCallback callback = callbacks_.front();
diff --git a/chrome/browser/extensions/api/system_network/system_network_api.cc b/chrome/browser/extensions/api/system_network/system_network_api.cc
index 633cea3..6710052 100644
--- a/chrome/browser/extensions/api/system_network/system_network_api.cc
+++ b/chrome/browser/extensions/api/system_network/system_network_api.cc
@@ -43,14 +43,14 @@
 }
 
 void SystemNetworkGetNetworkInterfacesFunction::HandleGetListError() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   error_ = kNetworkListError;
   SendResponse(false);
 }
 
 void SystemNetworkGetNetworkInterfacesFunction::SendResponseOnUIThread(
     const net::NetworkInterfaceList& interface_list) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   std::vector<linked_ptr<api::system_network::NetworkInterface> >
       create_arg;
diff --git a/chrome/browser/extensions/api/system_storage/storage_info_provider.cc b/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
index 1869ced..366a4c2 100644
--- a/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
+++ b/chrome/browser/extensions/api/system_storage/storage_info_provider.cc
@@ -64,7 +64,7 @@
 
 void StorageInfoProvider::InitializeProvider(
     const base::Closure& do_query_info_callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // Register the |do_query_info_callback| callback to StorageMonitor.
   // See the comments of StorageMonitor::EnsureInitialized about when the
   // callback gets run.
@@ -93,7 +93,7 @@
 
 double StorageInfoProvider::GetStorageFreeSpaceFromTransientIdOnFileThread(
     const std::string& transient_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   std::vector<StorageInfo> storage_list =
       StorageMonitor::GetInstance()->GetAllAvailableStorages();
 
diff --git a/chrome/browser/extensions/api/system_storage/system_storage_api.cc b/chrome/browser/extensions/api/system_storage/system_storage_api.cc
index c69c463..6d8da0d 100644
--- a/chrome/browser/extensions/api/system_storage/system_storage_api.cc
+++ b/chrome/browser/extensions/api/system_storage/system_storage_api.cc
@@ -40,7 +40,7 @@
 }
 
 bool SystemStorageEjectDeviceFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   scoped_ptr<EjectDevice::Params> params(EjectDevice::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
@@ -104,7 +104,7 @@
 }
 
 bool SystemStorageGetAvailableCapacityFunction::RunImpl() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   scoped_ptr<GetAvailableCapacity::Params> params(
       GetAvailableCapacity::Params::Create(*args_));
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
index 8f9cd6e..54cd55b 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
@@ -14,7 +14,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_renderer_state.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
index af5a28e..4f51f8e 100644
--- a/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
+++ b/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
@@ -136,7 +136,7 @@
 
 const TabCaptureRegistry::RegistryCaptureInfo
     TabCaptureRegistry::GetCapturedTabs(const std::string& extension_id) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   RegistryCaptureInfo list;
   for (ScopedVector<TabCaptureRequest>::const_iterator it = requests_.begin();
        it != requests_.end(); ++it) {
@@ -150,7 +150,7 @@
 void TabCaptureRegistry::Observe(int type,
                                  const content::NotificationSource& source,
                                  const content::NotificationDetails& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   switch (type) {
     case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
       // Cleanup all the requested media streams for this extension.
@@ -230,7 +230,7 @@
 
 bool TabCaptureRegistry::VerifyRequest(int render_process_id,
                                        int render_view_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DVLOG(1) << "Verifying tabCapture request for "
            << render_process_id << ":" << render_view_id;
   // TODO(justinlin): Verify extension too.
@@ -242,7 +242,7 @@
     int render_view_id,
     const content::MediaStreamDevice& device,
     const content::MediaRequestState new_state) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (device.type != content::MEDIA_TAB_VIDEO_CAPTURE &&
       device.type != content::MEDIA_TAB_AUDIO_CAPTURE) {
     return;
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc
index 4d2e46e..0d23ae9 100644
--- a/chrome/browser/extensions/api/usb/usb_api.cc
+++ b/chrome/browser/extensions/api/usb/usb_api.cc
@@ -13,9 +13,9 @@
 #include "chrome/browser/usb/usb_device_handle.h"
 #include "chrome/browser/usb/usb_service.h"
 #include "chrome/common/extensions/api/usb.h"
-#include "chrome/common/extensions/permissions/usb_device_permission.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/usb_device_permission.h"
 
 namespace usb = extensions::api::usb;
 namespace BulkTransfer = usb::BulkTransfer;
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
index f8b7a60..c64b630 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -164,7 +164,7 @@
 }
 
 void WebNavigationEventRouter::Retargeting(const RetargetingDetails* details) {
-  if (details->source_frame_id == 0)
+  if (details->source_render_frame_id == 0)
     return;
   WebNavigationTabObserver* tab_observer =
       WebNavigationTabObserver::Get(details->source_web_contents);
@@ -178,7 +178,7 @@
       tab_observer->frame_navigation_state();
 
   FrameNavigationState::FrameID frame_id(
-      details->source_frame_id,
+      details->source_render_frame_id,
       details->source_web_contents->GetRenderViewHost());
   if (!frame_navigation_state.CanSendEvents(frame_id))
     return;
@@ -189,7 +189,7 @@
     pending_web_contents_[details->target_web_contents] =
         PendingWebContents(
             details->source_web_contents,
-            details->source_frame_id,
+            details->source_render_frame_id,
             frame_navigation_state.IsMainFrame(frame_id),
             details->target_web_contents,
             details->target_url);
@@ -197,7 +197,7 @@
     helpers::DispatchOnCreatedNavigationTarget(
         details->source_web_contents,
         details->target_web_contents->GetBrowserContext(),
-        details->source_frame_id,
+        details->source_render_frame_id,
         frame_navigation_state.IsMainFrame(frame_id),
         details->target_web_contents,
         details->target_url);
diff --git a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index dbd46e4..8418a66 100644
--- a/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -92,7 +92,7 @@
   content::ResourceThrottle* CreateResourceThrottle(
       const GURL& url,
       ResourceType::Type resource_type) {
-    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
     if (urls_to_delay_.find(url) == urls_to_delay_.end())
       return NULL;
 
@@ -427,8 +427,6 @@
   params.is_editable = false;
   params.media_type = blink::WebContextMenuData::MediaTypeNone;
   params.page_url = url;
-  params.frame_id = WebNavigationTabObserver::Get(tab)->
-      frame_navigation_state().GetMainFrameID().frame_num;
   params.link_url = extension->GetResourceURL("b.html");
 
   TestRenderViewContextMenu menu(tab->GetMainFrame(), params);
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.cc b/chrome/browser/extensions/api/web_request/web_request_api.cc
index dc884f8..2b98bd7 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api.cc
@@ -345,7 +345,7 @@
   const std::string& event_name,
   int process_id,
   const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   Profile* profile = reinterpret_cast<Profile*>(profile_id);
   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
@@ -371,7 +371,7 @@
     void* profile_id,
     const std::string& extension_id,
     scoped_ptr<base::DictionaryValue> event_argument) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   Profile* profile = reinterpret_cast<Profile*>(profile_id);
   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
@@ -433,7 +433,7 @@
 }
 
 void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // Note that details.event_name includes the sub-event details (e.g. "/123").
   BrowserThread::PostTask(BrowserThread::IO,
                           FROM_HERE,
@@ -498,7 +498,7 @@
   net::CompletionCallback callback;
 
   // If non-empty, this contains the new URL that the request will redirect to.
-  // Only valid for OnBeforeRequest.
+  // Only valid for OnBeforeRequest and OnHeadersReceived.
   GURL* new_url;
 
   // The request headers that will be issued along with this request. Only valid
@@ -831,7 +831,8 @@
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     const net::HttpResponseHeaders* original_response_headers,
-    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   // We hide events from the system context as well as sensitive requests.
   if (!profile ||
       WebRequestPermissions::HideRequest(extension_info_map, request))
@@ -881,6 +882,8 @@
       override_response_headers;
   blocked_requests_[request->identifier()].original_response_headers =
       original_response_headers;
+  blocked_requests_[request->identifier()].new_url =
+      allowed_unsafe_redirect_url;
 
   if (blocked_requests_[request->identifier()].num_handlers_blocking == 0) {
     // If there are no blocking handlers, only the declarative rules tried
@@ -1557,8 +1560,12 @@
       helpers::ResponseHeaders* new_headers =
           response->response_headers.get();
       return helpers::CalculateOnHeadersReceivedDelta(
-          response->extension_id, response->extension_install_time,
-          response->cancel, old_headers, new_headers);
+          response->extension_id,
+          response->extension_install_time,
+          response->cancel,
+          response->new_url,
+          old_headers,
+          new_headers);
     }
     case ExtensionWebRequestEventRouter::kOnAuthRequired:
       return helpers::CalculateOnAuthRequiredDelta(
@@ -1848,6 +1855,7 @@
         blocked_request.response_deltas,
         blocked_request.original_response_headers.get(),
         blocked_request.override_response_headers,
+        blocked_request.new_url,
         &warnings,
         blocked_request.net_log);
   } else if (blocked_request.event == kOnAuthRequired) {
@@ -2221,14 +2229,13 @@
   return true;
 }
 
-void WebRequestEventHandled::CancelWithError(
+void WebRequestEventHandled::RespondWithError(
     const std::string& event_name,
     const std::string& sub_event_name,
     uint64 request_id,
     scoped_ptr<ExtensionWebRequestEventRouter::EventResponse> response,
     const std::string& error) {
   error_ = error;
-  response->cancel = true;
   ExtensionWebRequestEventRouter::GetInstance()->OnEventHandled(
       profile_id(),
       extension_id(),
@@ -2266,11 +2273,11 @@
     if (value->HasKey("cancel")) {
       // Don't allow cancel mixed with other keys.
       if (value->size() != 1) {
-        CancelWithError(event_name,
-                        sub_event_name,
-                        request_id,
-                        response.Pass(),
-                        keys::kInvalidBlockingResponse);
+        RespondWithError(event_name,
+                         sub_event_name,
+                         request_id,
+                         response.Pass(),
+                         keys::kInvalidBlockingResponse);
         return false;
       }
 
@@ -2285,12 +2292,12 @@
                                                    &new_url_str));
       response->new_url = GURL(new_url_str);
       if (!response->new_url.is_valid()) {
-        CancelWithError(event_name,
-                        sub_event_name,
-                        request_id,
-                        response.Pass(),
-                        ErrorUtils::FormatErrorMessage(
-                            keys::kInvalidRedirectUrl, new_url_str));
+        RespondWithError(event_name,
+                         sub_event_name,
+                         request_id,
+                         response.Pass(),
+                         ErrorUtils::FormatErrorMessage(
+                             keys::kInvalidRedirectUrl, new_url_str));
         return false;
       }
     }
@@ -2300,21 +2307,23 @@
     if (hasRequestHeaders || hasResponseHeaders) {
       if (hasRequestHeaders && hasResponseHeaders) {
         // Allow only one of the keys, not both.
-        CancelWithError(event_name,
-                        sub_event_name,
-                        request_id,
-                        response.Pass(),
-                        keys::kInvalidHeaderKeyCombination);
+        RespondWithError(event_name,
+                         sub_event_name,
+                         request_id,
+                         response.Pass(),
+                         keys::kInvalidHeaderKeyCombination);
         return false;
       }
 
       base::ListValue* headers_value = NULL;
+      scoped_ptr<net::HttpRequestHeaders> request_headers;
+      scoped_ptr<helpers::ResponseHeaders> response_headers;
       if (hasRequestHeaders) {
-        response->request_headers.reset(new net::HttpRequestHeaders());
+        request_headers.reset(new net::HttpRequestHeaders());
         EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kRequestHeadersKey,
                                                    &headers_value));
       } else {
-        response->response_headers.reset(new helpers::ResponseHeaders());
+        response_headers.reset(new helpers::ResponseHeaders());
         EXTENSION_FUNCTION_VALIDATE(value->GetList(keys::kResponseHeadersKey,
                                                    &headers_value));
       }
@@ -2328,37 +2337,40 @@
         if (!FromHeaderDictionary(header_value, &name, &value)) {
           std::string serialized_header;
           base::JSONWriter::Write(header_value, &serialized_header);
-          CancelWithError(event_name,
-                          sub_event_name,
-                          request_id,
-                          response.Pass(),
-                          ErrorUtils::FormatErrorMessage(keys::kInvalidHeader,
-                                                         serialized_header));
+          RespondWithError(event_name,
+                           sub_event_name,
+                           request_id,
+                           response.Pass(),
+                           ErrorUtils::FormatErrorMessage(keys::kInvalidHeader,
+                                                          serialized_header));
           return false;
         }
         if (!helpers::IsValidHeaderName(name)) {
-          CancelWithError(event_name,
-                          sub_event_name,
-                          request_id,
-                          response.Pass(),
-                          keys::kInvalidHeaderName);
+          RespondWithError(event_name,
+                           sub_event_name,
+                           request_id,
+                           response.Pass(),
+                           keys::kInvalidHeaderName);
           return false;
         }
         if (!helpers::IsValidHeaderValue(value)) {
-          CancelWithError(event_name,
-                          sub_event_name,
-                          request_id,
-                          response.Pass(),
-                          ErrorUtils::FormatErrorMessage(
-                              keys::kInvalidHeaderValue, name));
+          RespondWithError(event_name,
+                           sub_event_name,
+                           request_id,
+                           response.Pass(),
+                           ErrorUtils::FormatErrorMessage(
+                               keys::kInvalidHeaderValue, name));
           return false;
         }
         if (hasRequestHeaders)
-          response->request_headers->SetHeader(name, value);
+          request_headers->SetHeader(name, value);
         else
-          response->response_headers->push_back(helpers::ResponseHeader(name,
-                                                                        value));
+          response_headers->push_back(helpers::ResponseHeader(name, value));
       }
+      if (hasRequestHeaders)
+        response->request_headers.reset(request_headers.release());
+      else
+        response->response_headers.reset(response_headers.release());
     }
 
     if (value->HasKey(keys::kAuthCredentialsKey)) {
diff --git a/chrome/browser/extensions/api/web_request/web_request_api.h b/chrome/browser/extensions/api/web_request/web_request_api.h
index 9efddb0..c3bf24c 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api.h
@@ -205,9 +205,9 @@
   // requests only, and allows modification of incoming response headers.
   // Returns net::ERR_IO_PENDING if an extension is intercepting the request,
   // OK otherwise. |original_response_headers| is reference counted. |callback|
-  // and |override_response_headers| are owned by a URLRequestJob. They are
-  // guaranteed to be valid until |callback| is called or OnURLRequestDestroyed
-  // is called (whatever comes first).
+  // |override_response_headers| and |allowed_unsafe_redirect_url| are owned by
+  // a URLRequestJob. They are guaranteed to be valid until |callback| is called
+  // or OnURLRequestDestroyed is called (whatever comes first).
   // Do not modify |original_response_headers| directly but write new ones
   // into |override_response_headers|.
   int OnHeadersReceived(
@@ -216,7 +216,8 @@
       net::URLRequest* request,
       const net::CompletionCallback& callback,
       const net::HttpResponseHeaders* original_response_headers,
-      scoped_refptr<net::HttpResponseHeaders>* override_response_headers);
+      scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url);
 
   // Dispatches the OnAuthRequired event to any extensions whose filters match
   // the given request. If the listener is not registered as "blocking", then
@@ -486,11 +487,11 @@
  protected:
   virtual ~WebRequestEventHandled() {}
 
-  // Cancels and unblocks the network request, and sets error_ such that the
-  // developer console will show the respective error message. Use this function
-  // to handle incorrect requests from the extension that cannot be detected by
-  // the schema validator.
-  void CancelWithError(
+  // Unblocks the network request and sets |error_| such that the developer
+  // console will show the respective error message. Use this function to handle
+  // incorrect requests from the extension that cannot be detected by the schema
+  // validator.
+  void RespondWithError(
       const std::string& event_name,
       const std::string& sub_event_name,
       uint64 request_id,
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
index c48bae2..1c62081 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.cc
@@ -324,11 +324,13 @@
     const std::string& extension_id,
     const base::Time& extension_install_time,
     bool cancel,
+    const GURL& new_url,
     const net::HttpResponseHeaders* old_response_headers,
     ResponseHeaders* new_response_headers) {
   EventResponseDelta* result =
       new EventResponseDelta(extension_id, extension_install_time);
   result->cancel = cancel;
+  result->new_url = new_url;
 
   if (!new_response_headers)
     return result;
@@ -403,14 +405,14 @@
   }
 }
 
-// Helper function for MergeOnBeforeRequestResponses() that allows ignoring
+// Helper function for MergeRedirectUrlOfResponses() that allows ignoring
 // all redirects but those to data:// urls and about:blank. This is important
 // to treat these URLs as "cancel urls", i.e. URLs that extensions redirect
 // to if they want to express that they want to cancel a request. This reduces
 // the number of conflicts that we need to flag, as canceling is considered
 // a higher precedence operation that redirects.
 // Returns whether a redirect occurred.
-static bool MergeOnBeforeRequestResponsesHelper(
+static bool MergeRedirectUrlOfResponsesHelper(
     const EventResponseDeltas& deltas,
     GURL* new_url,
     extensions::ExtensionWarningSet* conflicting_extensions,
@@ -452,7 +454,7 @@
   return redirected;
 }
 
-void MergeOnBeforeRequestResponses(
+void MergeRedirectUrlOfResponses(
     const EventResponseDeltas& deltas,
     GURL* new_url,
     extensions::ExtensionWarningSet* conflicting_extensions,
@@ -460,7 +462,7 @@
 
   // First handle only redirects to data:// URLs and about:blank. These are a
   // special case as they represent a way of cancelling a request.
-  if (MergeOnBeforeRequestResponsesHelper(
+  if (MergeRedirectUrlOfResponsesHelper(
           deltas, new_url, conflicting_extensions, net_log, true)) {
     // If any extension cancelled a request by redirecting to a data:// URL or
     // about:blank, we don't consider the other redirects.
@@ -468,10 +470,18 @@
   }
 
   // Handle all other redirects.
-  MergeOnBeforeRequestResponsesHelper(
+  MergeRedirectUrlOfResponsesHelper(
       deltas, new_url, conflicting_extensions, net_log, false);
 }
 
+void MergeOnBeforeRequestResponses(
+    const EventResponseDeltas& deltas,
+    GURL* new_url,
+    extensions::ExtensionWarningSet* conflicting_extensions,
+    const net::BoundNetLog* net_log) {
+  MergeRedirectUrlOfResponses(deltas, new_url, conflicting_extensions, net_log);
+}
+
 // Assumes that |header_value| is the cookie header value of a HTTP Request
 // following the cookie-string schema of RFC 6265, section 4.2.1, and returns
 // cookie name/value pairs. If cookie values are presented in double quotes,
@@ -1100,6 +1110,7 @@
     const EventResponseDeltas& deltas,
     const net::HttpResponseHeaders* original_response_headers,
     scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url,
     extensions::ExtensionWarningSet* conflicting_extensions,
     const net::BoundNetLog* net_log) {
   EventResponseDeltas::const_iterator delta;
@@ -1181,6 +1192,23 @@
 
   MergeCookiesInOnHeadersReceivedResponses(deltas, original_response_headers,
       override_response_headers, conflicting_extensions, net_log);
+
+  GURL new_url;
+  MergeRedirectUrlOfResponses(
+      deltas, &new_url, conflicting_extensions, net_log);
+  if (new_url.is_valid()) {
+    // Only create a copy if we really want to modify the response headers.
+    if (override_response_headers->get() == NULL) {
+      *override_response_headers = new net::HttpResponseHeaders(
+          original_response_headers->raw_headers());
+    }
+    (*override_response_headers)->ReplaceStatusLine("HTTP/1.1 302 Found");
+    (*override_response_headers)->RemoveHeader("location");
+    (*override_response_headers)->AddHeader("Location: " + new_url.spec());
+    // Explicitly mark the URL as safe for redirection, to prevent the request
+    // from being blocked because of net::ERR_UNSAFE_REDIRECT.
+    *allowed_unsafe_redirect_url = new_url;
+  }
 }
 
 bool MergeOnAuthRequiredResponses(
@@ -1260,7 +1288,7 @@
 void NotifyWebRequestAPIUsed(
     void* profile_id,
     scoped_refptr<const extensions::Extension> extension) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   Profile* profile = reinterpret_cast<Profile*>(profile_id);
   if (!g_browser_process->profile_manager()->IsValidProfile(profile))
     return;
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_helpers.h b/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
index bbaf846..5901d22 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
+++ b/chrome/browser/extensions/api/web_request/web_request_api_helpers.h
@@ -214,6 +214,7 @@
     const std::string& extension_id,
     const base::Time& extension_install_time,
     bool cancel,
+    const GURL& new_url,
     const net::HttpResponseHeaders* old_response_headers,
     ResponseHeaders* new_response_headers);
 // Destructively moves the auth credentials from |auth_credentials| to the
@@ -238,6 +239,14 @@
 // Stores in |*new_url| the redirect request of the extension with highest
 // precedence. Extensions that did not command to redirect the request are
 // ignored in this logic.
+void MergeRedirectUrlOfResponses(
+    const EventResponseDeltas& deltas,
+    GURL* new_url,
+    extensions::ExtensionWarningSet* conflicting_extensions,
+    const net::BoundNetLog* net_log);
+// Stores in |*new_url| the redirect request of the extension with highest
+// precedence. Extensions that did not command to redirect the request are
+// ignored in this logic.
 void MergeOnBeforeRequestResponses(
     const EventResponseDeltas& deltas,
     GURL* new_url,
@@ -271,10 +280,14 @@
 // Stores a copy of |original_response_header| into |override_response_headers|
 // that is modified according to |deltas|. If |deltas| does not instruct to
 // modify the response headers, |override_response_headers| remains empty.
+// Extension-initiated redirects are written to |override_response_headers|
+// (to request redirection) and |*allowed_unsafe_redirect_url| (to make sure
+// that the request is not cancelled with net::ERR_UNSAFE_REDIRECT).
 void MergeOnHeadersReceivedResponses(
     const EventResponseDeltas& deltas,
     const net::HttpResponseHeaders* original_response_headers,
     scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url,
     extensions::ExtensionWarningSet* conflicting_extensions,
     const net::BoundNetLog* net_log);
 // Merge the responses of blocked onAuthRequired handlers. The first
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index cafc124..eaeece0 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -1274,9 +1274,15 @@
   new_headers.push_back(ResponseHeader("Key2", "Value1"));  // Modified
   // Key3 is deleted
   new_headers.push_back(ResponseHeader("Key4", "Value4"));  // Added
+  GURL effective_new_url;
 
-  scoped_ptr<EventResponseDelta> delta(CalculateOnHeadersReceivedDelta(
-      "extid", base::Time::Now(), cancel, base_headers.get(), &new_headers));
+  scoped_ptr<EventResponseDelta> delta(
+      CalculateOnHeadersReceivedDelta("extid",
+                                      base::Time::Now(),
+                                      cancel,
+                                      effective_new_url,
+                                      base_headers.get(),
+                                      &new_headers));
   ASSERT_TRUE(delta.get());
   EXPECT_TRUE(delta->cancel);
   EXPECT_EQ(2u, delta->added_response_headers.size());
@@ -1959,9 +1965,15 @@
       new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
   deltas.push_back(d0);
   scoped_refptr<net::HttpResponseHeaders> new_headers0;
-  MergeOnHeadersReceivedResponses(deltas, base_headers.get(), &new_headers0,
-                                  &warning_set, &net_log);
+  GURL allowed_unsafe_redirect_url0;
+  MergeOnHeadersReceivedResponses(deltas,
+                                  base_headers.get(),
+                                  &new_headers0,
+                                  &allowed_unsafe_redirect_url0,
+                                  &warning_set,
+                                  &net_log);
   EXPECT_FALSE(new_headers0.get());
+  EXPECT_TRUE(allowed_unsafe_redirect_url0.is_empty());
   EXPECT_EQ(0u, warning_set.size());
   EXPECT_EQ(0u, capturing_net_log.GetSize());
 
@@ -1975,9 +1987,15 @@
   warning_set.clear();
   capturing_net_log.Clear();
   scoped_refptr<net::HttpResponseHeaders> new_headers1;
-  MergeOnHeadersReceivedResponses(
-      deltas, base_headers.get(), &new_headers1, &warning_set, &net_log);
+  GURL allowed_unsafe_redirect_url1;
+  MergeOnHeadersReceivedResponses(deltas,
+                                  base_headers.get(),
+                                  &new_headers1,
+                                  &allowed_unsafe_redirect_url1,
+                                  &warning_set,
+                                  &net_log);
   ASSERT_TRUE(new_headers1.get());
+  EXPECT_TRUE(allowed_unsafe_redirect_url1.is_empty());
   std::multimap<std::string, std::string> expected1;
   expected1.insert(std::pair<std::string, std::string>("Key2", "Value3"));
   void* iter = NULL;
@@ -2003,9 +2021,15 @@
   warning_set.clear();
   capturing_net_log.Clear();
   scoped_refptr<net::HttpResponseHeaders> new_headers2;
-  MergeOnHeadersReceivedResponses(
-      deltas, base_headers.get(), &new_headers2, &warning_set, &net_log);
+  GURL allowed_unsafe_redirect_url2;
+  MergeOnHeadersReceivedResponses(deltas,
+                                  base_headers.get(),
+                                  &new_headers2,
+                                  &allowed_unsafe_redirect_url2,
+                                  &warning_set,
+                                  &net_log);
   ASSERT_TRUE(new_headers2.get());
+  EXPECT_TRUE(allowed_unsafe_redirect_url2.is_empty());
   iter = NULL;
   std::multimap<std::string, std::string> actual2;
   while (new_headers2->EnumerateHeaderLines(&iter, &name, &value)) {
@@ -2043,9 +2067,15 @@
   d1->deleted_response_headers.push_back(ResponseHeader("KEY1", "Value2"));
   deltas.push_back(d1);
   scoped_refptr<net::HttpResponseHeaders> new_headers1;
-  MergeOnHeadersReceivedResponses(
-      deltas, base_headers.get(), &new_headers1, &warning_set, &net_log);
+  GURL allowed_unsafe_redirect_url1;
+  MergeOnHeadersReceivedResponses(deltas,
+                                  base_headers.get(),
+                                  &new_headers1,
+                                  &allowed_unsafe_redirect_url1,
+                                  &warning_set,
+                                  &net_log);
   ASSERT_TRUE(new_headers1.get());
+  EXPECT_TRUE(allowed_unsafe_redirect_url1.is_empty());
   std::multimap<std::string, std::string> expected1;
   expected1.insert(std::pair<std::string, std::string>("Key1", "Value1"));
   expected1.insert(std::pair<std::string, std::string>("Key1", "Value3"));
@@ -2062,6 +2092,64 @@
   EXPECT_EQ(1u, capturing_net_log.GetSize());
 }
 
+// Tests whether onHeadersReceived can initiate a redirect.
+// The URL merge logic is shared with onBeforeRequest, so we only need to test
+// whether the URLs are merged at all.
+TEST(ExtensionWebRequestHelpersTest,
+     TestMergeOnHeadersReceivedResponsesRedirect) {
+  EventResponseDeltas deltas;
+  net::CapturingBoundNetLog capturing_net_log;
+  net::BoundNetLog net_log = capturing_net_log.bound();
+  ExtensionWarningSet warning_set;
+
+  char base_headers_string[] =
+      "HTTP/1.0 200 OK\r\n"
+      "\r\n";
+  scoped_refptr<net::HttpResponseHeaders> base_headers(
+      new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
+          base_headers_string, sizeof(base_headers_string))));
+
+  // No redirect
+  linked_ptr<EventResponseDelta> d0(
+      new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
+  deltas.push_back(d0);
+  scoped_refptr<net::HttpResponseHeaders> new_headers0;
+  GURL allowed_unsafe_redirect_url0;
+  MergeOnHeadersReceivedResponses(deltas,
+                                  base_headers.get(),
+                                  &new_headers0,
+                                  &allowed_unsafe_redirect_url0,
+                                  &warning_set,
+                                  &net_log);
+  EXPECT_FALSE(new_headers0.get());
+  EXPECT_TRUE(allowed_unsafe_redirect_url0.is_empty());
+  EXPECT_EQ(0u, warning_set.size());
+  EXPECT_EQ(0u, capturing_net_log.GetSize());
+
+  // Single redirect.
+  GURL new_url_1("http://foo.com");
+  linked_ptr<EventResponseDelta> d1(
+      new EventResponseDelta("extid1", base::Time::FromInternalValue(1000)));
+  d1->new_url = GURL(new_url_1);
+  deltas.push_back(d1);
+  deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
+  capturing_net_log.Clear();
+  scoped_refptr<net::HttpResponseHeaders> new_headers1;
+  GURL allowed_unsafe_redirect_url1;
+  MergeOnHeadersReceivedResponses(deltas,
+                                  base_headers.get(),
+                                  &new_headers1,
+                                  &allowed_unsafe_redirect_url1,
+                                  &warning_set,
+                                  &net_log);
+
+  EXPECT_TRUE(new_headers1.get());
+  EXPECT_TRUE(new_headers1->HasHeaderValue("Location", new_url_1.spec()));
+  EXPECT_EQ(new_url_1, allowed_unsafe_redirect_url1);
+  EXPECT_TRUE(warning_set.empty());
+  EXPECT_EQ(1u, capturing_net_log.GetSize());
+}
+
 TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
   net::CapturingBoundNetLog capturing_net_log;
   net::BoundNetLog net_log = capturing_net_log.bound();
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/OWNERS b/chrome/browser/extensions/api/webrtc_audio_private/OWNERS
deleted file mode 100644
index 4975363..0000000
--- a/chrome/browser/extensions/api/webrtc_audio_private/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-joi@chromium.org
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
index a45e5fe..49bbf0c 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc
@@ -109,7 +109,7 @@
   scoped_refptr<base::SingleThreadTaskRunner> audio_manager_runner =
       AudioManager::Get()->GetTaskRunner();
   if (!audio_manager_runner->BelongsToCurrentThread()) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     audio_manager_runner->PostTask(
         FROM_HERE,
         base::Bind(&WebrtcAudioPrivateFunction::GetOutputDeviceNames, this));
@@ -178,7 +178,7 @@
 
 std::string WebrtcAudioPrivateFunction::CalculateHMACImpl(
     const std::string& raw_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // We don't hash the default device name, and we always return
   // "default" for the default device. There is code in SetActiveSink
@@ -205,7 +205,7 @@
 }
 
 bool WebrtcAudioPrivateGetSinksFunction::RunImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   InitResourceContext();
   GetOutputDeviceNames();
@@ -215,7 +215,7 @@
 
 void WebrtcAudioPrivateGetSinksFunction::OnOutputDeviceNames(
     scoped_ptr<AudioDeviceNames> raw_ids) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   std::vector<linked_ptr<wap::SinkInfo> > results;
   for (AudioDeviceNames::const_iterator it = raw_ids->begin();
@@ -249,7 +249,7 @@
 }
 
 bool WebrtcAudioPrivateGetActiveSinkFunction::RunImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   InitResourceContext();
 
   scoped_ptr<wap::GetActiveSink::Params> params(
@@ -261,7 +261,7 @@
 
 void WebrtcAudioPrivateGetActiveSinkFunction::OnControllerList(
     const RenderViewHost::AudioOutputControllerList& controllers) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (controllers.empty()) {
     // If there is no current audio stream for the rvh, we return an
@@ -285,7 +285,7 @@
 
 void WebrtcAudioPrivateGetActiveSinkFunction::OnHMACCalculated(
     const std::string& hmac_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::string result = hmac_id;
   if (result.empty()) {
@@ -307,7 +307,7 @@
 }
 
 bool WebrtcAudioPrivateSetActiveSinkFunction::RunImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_ptr<wap::SetActiveSink::Params> params(
       wap::SetActiveSink::Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params.get());
@@ -322,7 +322,7 @@
 
 void WebrtcAudioPrivateSetActiveSinkFunction::OnControllerList(
     const RenderViewHost::AudioOutputControllerList& controllers) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   controllers_ = controllers;
   num_remaining_sink_ids_ = controllers_.size();
@@ -341,7 +341,7 @@
 
 void WebrtcAudioPrivateSetActiveSinkFunction::OnOutputDeviceNames(
     scoped_ptr<AudioDeviceNames> device_names) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   std::string raw_sink_id;
   if (sink_id_ == media::AudioManagerBase::kDefaultDeviceId) {
@@ -393,7 +393,7 @@
 
 bool WebrtcAudioPrivateGetAssociatedSinkFunction::RunImpl() {
   params_ = wap::GetAssociatedSink::Params::Create(*args_);
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   EXTENSION_FUNCTION_VALIDATE(params_.get());
 
   InitResourceContext();
@@ -420,7 +420,7 @@
 
 void
 WebrtcAudioPrivateGetAssociatedSinkFunction::GetRawSourceIDOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   GURL security_origin(params_->security_origin);
   std::string source_id_in_origin(params_->source_id_in_origin);
@@ -468,7 +468,7 @@
 
 void WebrtcAudioPrivateGetAssociatedSinkFunction::OnHMACCalculated(
     const std::string& associated_sink_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (associated_sink_id == media::AudioManagerBase::kDefaultDeviceId) {
     DVLOG(2) << "Got default ID, replacing with empty ID.";
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
index 94ae182..ee154a2 100644
--- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
+++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -410,6 +410,9 @@
   title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("failure"));
   base::string16 result = title_watcher.WaitAndGetTitle();
   EXPECT_EQ(base::ASCIIToUTF16("success"), result);
+
+  g_browser_process->webrtc_log_uploader()->OverrideUploadWithBufferForTesting(
+      NULL);
 }
 #endif  // defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
 
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
index 0100027..6ea1163 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -94,7 +94,7 @@
 
 void WebrtcLoggingPrivateSetMetaDataFunction::SetMetaDataCallback(
     bool success, const std::string& error_message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success)
     SetError(error_message);
   SendResponse(success);
@@ -128,7 +128,7 @@
 
 void WebrtcLoggingPrivateStartFunction::StartCallback(
     bool success, const std::string& error_message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success)
     SetError(error_message);
   SendResponse(success);
@@ -187,7 +187,7 @@
 
 void WebrtcLoggingPrivateStopFunction::StopCallback(
     bool success, const std::string& error_message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success)
     SetError(error_message);
   SendResponse(success);
@@ -222,7 +222,7 @@
 void WebrtcLoggingPrivateUploadFunction::UploadCallback(
     bool success, const std::string& report_id,
     const std::string& error_message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (success) {
     api::webrtc_logging_private::UploadResult result;
     result.report_id = report_id;
@@ -261,7 +261,7 @@
 
 void WebrtcLoggingPrivateDiscardFunction::DiscardCallback(
     bool success, const std::string& error_message) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!success)
     SetError(error_message);
   SendResponse(success);
diff --git a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
index f320eaf..37df1c8 100644
--- a/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
+++ b/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
@@ -80,6 +80,9 @@
   ASSERT_FALSE(result.get());
 
   ASSERT_TRUE(multipart.empty());
+
+  g_browser_process->webrtc_log_uploader()->OverrideUploadWithBufferForTesting(
+      NULL);
 }
 
 // Tests WebRTC diagnostic logging. Sets up the browser to save the multipart
@@ -269,4 +272,7 @@
   final_delimiter += "--";
   EXPECT_STREQ(final_delimiter.c_str(), multipart_lines[29].c_str());
   EXPECT_TRUE(multipart_lines[30].empty());
+
+  g_browser_process->webrtc_log_uploader()->OverrideUploadWithBufferForTesting(
+      NULL);
 }
diff --git a/chrome/browser/extensions/api/webstore/webstore_api.cc b/chrome/browser/extensions/api/webstore/webstore_api.cc
new file mode 100644
index 0000000..a0def2a
--- /dev/null
+++ b/chrome/browser/extensions/api/webstore/webstore_api.cc
@@ -0,0 +1,142 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/webstore/webstore_api.h"
+
+#include "base/lazy_instance.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/install_tracker.h"
+#include "chrome/browser/extensions/install_tracker_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/extensions/chrome_extension_messages.h"
+#include "extensions/browser/extension_system.h"
+#include "ipc/ipc_sender.h"
+
+namespace extensions {
+
+namespace {
+
+base::LazyInstance<BrowserContextKeyedAPIFactory<WebstoreAPI> > g_factory =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+struct WebstoreAPI::ObservedInstallInfo {
+  ObservedInstallInfo(int routing_id,
+                      const std::string& extension_id,
+                      IPC::Sender* ipc_sender);
+  ~ObservedInstallInfo();
+
+  int routing_id;
+  std::string extension_id;
+  IPC::Sender* ipc_sender;
+};
+
+WebstoreAPI::ObservedInstallInfo::ObservedInstallInfo(
+    int routing_id,
+    const std::string& extension_id,
+    IPC::Sender* ipc_sender)
+    : routing_id(routing_id),
+      extension_id(extension_id),
+      ipc_sender(ipc_sender) {}
+
+WebstoreAPI::ObservedInstallInfo::~ObservedInstallInfo() {}
+
+WebstoreAPI::WebstoreAPI(content::BrowserContext* browser_context)
+    : browser_context_(browser_context),
+      install_observer_(
+          new ScopedObserver<InstallTracker, InstallObserver>(this)) {
+  install_observer_->Add(InstallTrackerFactory::GetForProfile(
+      Profile::FromBrowserContext(browser_context)));
+}
+
+WebstoreAPI::~WebstoreAPI() {}
+
+// static
+WebstoreAPI* WebstoreAPI::Get(content::BrowserContext* browser_context) {
+  return BrowserContextKeyedAPIFactory<WebstoreAPI>::Get(browser_context);
+}
+
+void WebstoreAPI::OnInlineInstallStart(int routing_id,
+                                       IPC::Sender* ipc_sender,
+                                       const std::string& extension_id,
+                                       int listeners_mask) {
+  if (listeners_mask & api::webstore::INSTALL_STAGE_LISTENER) {
+    install_stage_listeners_.push_back(
+        ObservedInstallInfo(routing_id, extension_id, ipc_sender));
+  }
+
+  if (listeners_mask & api::webstore::DOWNLOAD_PROGRESS_LISTENER) {
+    download_progress_listeners_.push_back(
+        ObservedInstallInfo(routing_id, extension_id, ipc_sender));
+  }
+}
+
+void WebstoreAPI::OnInlineInstallFinished(int routing_id,
+                                          const std::string& extension_id) {
+  RemoveListeners(routing_id, extension_id, &download_progress_listeners_);
+  RemoveListeners(routing_id, extension_id, &install_stage_listeners_);
+}
+
+void WebstoreAPI::OnBeginExtensionDownload(const std::string& extension_id) {
+  SendInstallMessageIfObserved(extension_id,
+                               api::webstore::INSTALL_STAGE_DOWNLOADING);
+}
+
+void WebstoreAPI::OnDownloadProgress(const std::string& extension_id,
+                                     int percent_downloaded) {
+  for (ObservedInstallInfoList::const_iterator iter =
+           download_progress_listeners_.begin();
+       iter != download_progress_listeners_.end();
+       ++iter) {
+    if (iter->extension_id == extension_id) {
+      iter->ipc_sender->Send(new ExtensionMsg_InlineInstallDownloadProgress(
+          iter->routing_id, percent_downloaded));
+    }
+  }
+}
+
+void WebstoreAPI::OnBeginCrxInstall(const std::string& extension_id) {
+  SendInstallMessageIfObserved(extension_id,
+                               api::webstore::INSTALL_STAGE_INSTALLING);
+}
+
+void WebstoreAPI::OnShutdown() {
+  install_observer_.reset();
+}
+
+void WebstoreAPI::Shutdown() {}
+
+// static
+BrowserContextKeyedAPIFactory<WebstoreAPI>* WebstoreAPI::GetFactoryInstance() {
+  return g_factory.Pointer();
+}
+
+void WebstoreAPI::SendInstallMessageIfObserved(
+    const std::string& extension_id,
+    api::webstore::InstallStage install_stage) {
+  for (ObservedInstallInfoList::const_iterator iter =
+           install_stage_listeners_.begin();
+       iter != install_stage_listeners_.end();
+       ++iter) {
+    if (iter->extension_id == extension_id) {
+      iter->ipc_sender->Send(new ExtensionMsg_InlineInstallStageChanged(
+          iter->routing_id, install_stage));
+    }
+  }
+}
+
+void WebstoreAPI::RemoveListeners(int routing_id,
+                                  const std::string& extension_id,
+                                  ObservedInstallInfoList* listeners) {
+  for (ObservedInstallInfoList::iterator iter = listeners->begin();
+       iter != listeners->end();) {
+    if (iter->extension_id == extension_id && iter->routing_id == routing_id)
+      iter = listeners->erase(iter);
+    else
+      ++iter;
+  }
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/webstore/webstore_api.h b/chrome/browser/extensions/api/webstore/webstore_api.h
new file mode 100644
index 0000000..e345491
--- /dev/null
+++ b/chrome/browser/extensions/api/webstore/webstore_api.h
@@ -0,0 +1,104 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_WEBSTORE_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_WEBSTORE_API_H_
+
+#include <list>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/scoped_observer.h"
+#include "chrome/browser/extensions/install_observer.h"
+#include "chrome/common/extensions/api/webstore/webstore_api_constants.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
+#include "extensions/browser/event_router.h"
+
+namespace base {
+class ListValue;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+namespace ipc {
+class Sender;
+}
+
+namespace extensions {
+class InstallTracker;
+
+class WebstoreAPI : public BrowserContextKeyedAPI,
+                    public InstallObserver {
+ public:
+  explicit WebstoreAPI(content::BrowserContext* browser_context);
+  virtual ~WebstoreAPI();
+
+  static WebstoreAPI* Get(content::BrowserContext* browser_context);
+
+  // Called whenever an inline extension install is started. Examines
+  // |listener_mask| to determine if a download progress or install
+  // stage listener should be added.
+  // |routing_id| refers to the id to which we send any return messages;
+  // |ipc_sender| is the sender through which we send them (typically this
+  // is the TabHelper which started the inline install).
+  void OnInlineInstallStart(int routing_id,
+                            IPC::Sender* ipc_sender,
+                            const std::string& extension_id,
+                            int listener_mask);
+
+  // Called when an inline extension install finishes. Removes any listeners
+  // related to the |routing_id|-|extension_id| pair.
+  void OnInlineInstallFinished(int routing_id, const std::string& extension_id);
+
+  // BrowserContextKeyedAPI implementation.
+  static BrowserContextKeyedAPIFactory<WebstoreAPI>* GetFactoryInstance();
+
+ private:
+  friend class BrowserContextKeyedAPIFactory<WebstoreAPI>;
+
+  // A simple struct to hold our listeners' information for each observed
+  // install.
+  struct ObservedInstallInfo;
+  typedef std::list<ObservedInstallInfo> ObservedInstallInfoList;
+
+  // Sends an installation stage update message if we are observing
+  // the extension's install.
+  void SendInstallMessageIfObserved(const std::string& extension_id,
+                                    api::webstore::InstallStage install_stage);
+
+  // Removes listeners for the given |extension_id|-|routing_id| pair from
+  // |listeners|.
+  void RemoveListeners(int routing_id,
+                       const std::string& extension_id,
+                       ObservedInstallInfoList* listeners);
+
+  // InstallObserver implementation.
+  virtual void OnBeginExtensionDownload(const std::string& extension_id)
+      OVERRIDE;
+  virtual void OnDownloadProgress(const std::string& extension_id,
+                                  int percent_downloaded) OVERRIDE;
+  virtual void OnBeginCrxInstall(const std::string& extension_id) OVERRIDE;
+  virtual void OnShutdown() OVERRIDE;
+
+  // BrowserContextKeyedService implementation.
+  virtual void Shutdown() OVERRIDE;
+
+  // BrowserContextKeyedAPI implementation.
+  static const char* service_name() { return "WebstoreAPI"; }
+  static const bool kServiceIsNULLWhileTesting = true;
+
+  ObservedInstallInfoList download_progress_listeners_;
+  ObservedInstallInfoList install_stage_listeners_;
+  content::BrowserContext* browser_context_;
+  scoped_ptr<ScopedObserver<InstallTracker, InstallObserver> >
+      install_observer_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebstoreAPI);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_WEBSTORE_API_H_
diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc
index 5c8ed79..e7fb17c 100644
--- a/chrome/browser/extensions/app_background_page_apitest.cc
+++ b/chrome/browser/extensions/app_background_page_apitest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
+#include "components/nacl/browser/nacl_process_host.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_notification_tracker.h"
 #include "content/public/test/test_utils.h"
@@ -27,7 +28,6 @@
 #include "extensions/common/switches.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
-#include "ppapi/shared_impl/ppapi_switches.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/scoped_nsautorelease_pool.h"
@@ -127,8 +127,9 @@
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     AppBackgroundPageApiTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitchASCII(
-        switches::kPpapiKeepAliveThrottle, "50");
+#if !defined(DISABLE_NACL)
+    nacl::NaClProcessHost::SetPpapiKeepAliveThrottleForTesting(50);
+#endif
     command_line->AppendSwitchASCII(
         extensions::switches::kEventPageIdleTime, "1000");
     command_line->AppendSwitchASCII(
@@ -607,6 +608,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageNaClTest,
                        MAYBE_BackgroundKeepaliveActive) {
+#if !defined(DISABLE_NACL)
   ExtensionTestMessageListener nacl_modules_loaded("nacl_modules_loaded", true);
   LaunchTestingApp();
   extensions::ProcessManager* manager =
@@ -618,6 +620,7 @@
   manager->SetKeepaliveImpulseCallbackForTesting(
       active_impulse_counter.SetGoalAndGetCallback(20));
   active_impulse_counter.Wait();
+#endif
 }
 
 // Verify that nacl modules that go idle will not send keepalive impulses.
@@ -631,6 +634,7 @@
 #endif
 IN_PROC_BROWSER_TEST_F(AppBackgroundPageNaClTest,
                        MAYBE_BackgroundKeepaliveIdle) {
+#if !defined(DISABLE_NACL)
   ExtensionTestMessageListener nacl_modules_loaded("nacl_modules_loaded", true);
   LaunchTestingApp();
   extensions::ProcessManager* manager =
@@ -642,5 +646,6 @@
       idle_impulse_counter.SetGoalAndGetCallback(1));
   nacl_modules_loaded.Reply("be idle");
   idle_impulse_counter.Wait();
+#endif
 }
 
diff --git a/chrome/browser/extensions/blacklist.cc b/chrome/browser/extensions/blacklist.cc
index dc4439f..56079f0 100644
--- a/chrome/browser/extensions/blacklist.cc
+++ b/chrome/browser/extensions/blacklist.cc
@@ -90,7 +90,7 @@
   // SafeBrowsingService on the IO thread.
   void StartCheck(scoped_refptr<SafeBrowsingDatabaseManager> database_manager,
                   const std::set<std::string>& extension_ids) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     if (database_manager->CheckExtensionIDs(extension_ids, this)) {
       // Definitely not blacklisted. Callback immediately.
       callback_message_loop_->PostTask(
@@ -105,7 +105,7 @@
 
   virtual void OnCheckExtensionsResult(
       const std::set<std::string>& hits) OVERRIDE {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     callback_message_loop_->PostTask(FROM_HERE, base::Bind(callback_, hits));
     Release();  // Balanced in StartCheck.
   }
@@ -184,7 +184,7 @@
 
 void Blacklist::GetBlacklistedIDs(const std::set<std::string>& ids,
                                   const GetBlacklistedIDsCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (ids.empty() || !g_database_manager.Get().get().get()) {
     base::MessageLoopProxy::current()->PostTask(
@@ -218,7 +218,7 @@
 void Blacklist::GetBlacklistStateForIDs(
     const GetBlacklistedIDsCallback& callback,
     const std::set<std::string>& blacklisted_ids) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::set<std::string> ids_unknown_state;
   BlacklistStateMap extensions_state;
@@ -267,7 +267,7 @@
 
 void Blacklist::RequestExtensionsBlacklistState(
     const std::set<std::string>& ids, const base::Callback<void()>& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!state_fetcher_)
     state_fetcher_.reset(new BlacklistStateFetcher());
 
@@ -284,7 +284,7 @@
 
 void Blacklist::OnBlacklistStateReceived(const std::string& id,
                                          BlacklistState state) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   blacklist_state_cache_[id] = state;
 
   // Go through the opened requests and call the callbacks for those requests
@@ -322,12 +322,12 @@
 }
 
 void Blacklist::AddObserver(Observer* observer) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   observers_.AddObserver(observer);
 }
 
 void Blacklist::RemoveObserver(Observer* observer) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   observers_.RemoveObserver(observer);
 }
 
diff --git a/chrome/browser/extensions/blacklist_state_fetcher.cc b/chrome/browser/extensions/blacklist_state_fetcher.cc
index 82bea2e..c28afa0 100644
--- a/chrome/browser/extensions/blacklist_state_fetcher.cc
+++ b/chrome/browser/extensions/blacklist_state_fetcher.cc
@@ -27,7 +27,7 @@
       net::URLRequestContextGetter* parent_context_getter) :
           network_task_runner_(
               BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     url_request_context_.reset(new net::URLRequestContext());
     url_request_context_->CopyFrom(
         parent_context_getter->GetURLRequestContext());
@@ -37,7 +37,7 @@
       scoped_refptr<net::URLRequestContextGetter> parent_context_getter,
       base::Callback<void(scoped_refptr<net::URLRequestContextGetter>)>
           callback) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
     scoped_refptr<net::URLRequestContextGetter> context_getter =
         new BlacklistRequestContextGetter(parent_context_getter);
@@ -47,7 +47,7 @@
   }
 
   virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(BrowserThread::IO);
     return url_request_context_.get();
   }
 
@@ -75,14 +75,14 @@
       weak_ptr_factory_(this) {}
 
 BlacklistStateFetcher::~BlacklistStateFetcher() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   STLDeleteContainerPairFirstPointers(requests_.begin(), requests_.end());
   requests_.clear();
 }
 
 void BlacklistStateFetcher::Request(const std::string& id,
                                     const RequestCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!safe_browsing_config_) {
     if (g_browser_process && g_browser_process->safe_browsing_service()) {
       SetSafeBrowsingConfig(
@@ -124,14 +124,14 @@
 void BlacklistStateFetcher::SaveRequestContext(
     const std::string& id,
     scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!url_request_context_getter_)
     url_request_context_getter_ = request_context_getter;
   SendRequest(id);
 }
 
 void BlacklistStateFetcher::SendRequest(const std::string& id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ClientCRXListInfoRequest request;
   request.set_id(id);
@@ -176,7 +176,7 @@
 }
 
 void BlacklistStateFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::map<const net::URLFetcher*, std::string>::iterator it =
      requests_.find(source);
diff --git a/chrome/browser/extensions/blob_reader.cc b/chrome/browser/extensions/blob_reader.cc
index 3b4fde6..bab8634 100644
--- a/chrome/browser/extensions/blob_reader.cc
+++ b/chrome/browser/extensions/blob_reader.cc
@@ -19,7 +19,7 @@
                        const std::string& blob_uuid,
                        BlobReadCallback callback)
     : callback_(callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   GURL blob_url;
   if (StartsWithASCII(blob_uuid, "blob:blobinternal", true)) {
     // TODO(michaeln): remove support for deprecated blob urls
@@ -34,12 +34,10 @@
   fetcher_->SetRequestContext(profile->GetRequestContext());
 }
 
-BlobReader::~BlobReader() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-}
+BlobReader::~BlobReader() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); }
 
 void BlobReader::SetByteRange(int64 offset, int64 length) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   CHECK_GE(offset, 0);
   CHECK_GT(length, 0);
   CHECK_LE(offset, kint64max - length);
@@ -53,13 +51,13 @@
 }
 
 void BlobReader::Start() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   fetcher_->Start();
 }
 
 // Overridden from net::URLFetcherDelegate.
 void BlobReader::OnURLFetchComplete(const net::URLFetcher* source) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   scoped_ptr<std::string> response(new std::string);
   int64 first = 0, last = 0, length = 0;
   source->GetResponseAsString(response.get());
diff --git a/chrome/browser/extensions/bookmark_app_helper.cc b/chrome/browser/extensions/bookmark_app_helper.cc
new file mode 100644
index 0000000..24ce2f8
--- /dev/null
+++ b/chrome/browser/extensions/bookmark_app_helper.cc
@@ -0,0 +1,285 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/bookmark_app_helper.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/crx_installer.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/favicon_downloader.h"
+#include "chrome/browser/extensions/tab_helper.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/common/extension.h"
+#include "skia/ext/image_operations.h"
+#include "skia/ext/platform_canvas.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/color_analysis.h"
+#include "ui/gfx/image/image.h"
+
+namespace extensions {
+
+// static
+std::map<int, SkBitmap> BookmarkAppHelper::ConstrainBitmapsToSizes(
+    const std::vector<SkBitmap>& bitmaps,
+    const std::set<int>& sizes) {
+  std::map<int, SkBitmap> output_bitmaps;
+  std::map<int, SkBitmap> ordered_bitmaps;
+  for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
+       it != bitmaps.end();
+       ++it) {
+    DCHECK(it->width() == it->height());
+    ordered_bitmaps[it->width()] = *it;
+  }
+
+  std::set<int>::const_iterator sizes_it = sizes.begin();
+  std::map<int, SkBitmap>::const_iterator bitmaps_it = ordered_bitmaps.begin();
+  while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) {
+    int size = *sizes_it;
+    // Find the closest not-smaller bitmap.
+    bitmaps_it = ordered_bitmaps.lower_bound(size);
+    ++sizes_it;
+    // Ensure the bitmap is valid and smaller than the next allowed size.
+    if (bitmaps_it != ordered_bitmaps.end() &&
+        (sizes_it == sizes.end() || bitmaps_it->second.width() < *sizes_it)) {
+      // Resize the bitmap if it does not exactly match the desired size.
+      output_bitmaps[size] = bitmaps_it->second.width() == size
+                                 ? bitmaps_it->second
+                                 : skia::ImageOperations::Resize(
+                                       bitmaps_it->second,
+                                       skia::ImageOperations::RESIZE_LANCZOS3,
+                                       size,
+                                       size);
+    }
+  }
+  return output_bitmaps;
+}
+
+// static
+void BookmarkAppHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
+                                              int output_size) {
+  std::map<int, SkBitmap>::const_iterator it =
+      bitmaps->lower_bound(output_size);
+  // Do nothing if there is no icon smaller than the desired size or there is
+  // already an icon of |output_size|.
+  if (it == bitmaps->begin() || bitmaps->count(output_size))
+    return;
+
+  --it;
+  // This is the biggest icon smaller than |output_size|.
+  const SkBitmap& base_icon = it->second;
+
+  const size_t kBorderRadius = 5;
+  const size_t kColorStripHeight = 3;
+  const SkColor kBorderColor = 0xFFD5D5D5;
+  const SkColor kBackgroundColor = 0xFFFFFFFF;
+
+  // Create a separate canvas for the color strip.
+  scoped_ptr<SkCanvas> color_strip_canvas(
+      skia::CreateBitmapCanvas(output_size, output_size, false));
+  DCHECK(color_strip_canvas);
+
+  // Draw a rounded rect of the |base_icon|'s dominant color.
+  SkPaint color_strip_paint;
+  color_utils::GridSampler sampler;
+  color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
+  color_strip_paint.setColor(color_utils::CalculateKMeanColorOfPNG(
+      gfx::Image::CreateFrom1xBitmap(base_icon).As1xPNGBytes(),
+      100,
+      665,
+      &sampler));
+  color_strip_canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
+                                    kBorderRadius,
+                                    kBorderRadius,
+                                    color_strip_paint);
+
+  // Erase the top of the rounded rect to leave a color strip.
+  SkPaint clear_paint;
+  clear_paint.setColor(SK_ColorTRANSPARENT);
+  clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+  color_strip_canvas->drawRect(
+      SkRect::MakeWH(output_size, output_size - kColorStripHeight),
+      clear_paint);
+
+  // Draw each element to an output canvas.
+  scoped_ptr<SkCanvas> canvas(
+      skia::CreateBitmapCanvas(output_size, output_size, false));
+  DCHECK(canvas);
+
+  // Draw the background.
+  SkPaint background_paint;
+  background_paint.setColor(kBackgroundColor);
+  background_paint.setFlags(SkPaint::kAntiAlias_Flag);
+  canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
+                        kBorderRadius,
+                        kBorderRadius,
+                        background_paint);
+
+  // Draw the color strip.
+  canvas->drawBitmap(
+      color_strip_canvas->getDevice()->accessBitmap(false), 0, 0);
+
+  // Draw the border.
+  SkPaint border_paint;
+  border_paint.setColor(kBorderColor);
+  border_paint.setStyle(SkPaint::kStroke_Style);
+  border_paint.setFlags(SkPaint::kAntiAlias_Flag);
+  canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size),
+                        kBorderRadius,
+                        kBorderRadius,
+                        border_paint);
+
+  // Draw the centered base icon to the output canvas.
+  canvas->drawBitmap(base_icon,
+                     (output_size - base_icon.width()) / 2,
+                     (output_size - base_icon.height()) / 2);
+
+  const SkBitmap& generated_icon = canvas->getDevice()->accessBitmap(false);
+  generated_icon.deepCopyTo(&(*bitmaps)[output_size]);
+}
+
+BookmarkAppHelper::BookmarkAppHelper(ExtensionService* service,
+                                     WebApplicationInfo web_app_info,
+                                     content::WebContents* contents)
+    : web_app_info_(web_app_info),
+      crx_installer_(extensions::CrxInstaller::CreateSilent(service)) {
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
+                 content::Source<CrxInstaller>(crx_installer_.get()));
+
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
+                 content::Source<CrxInstaller>(crx_installer_.get()));
+
+  crx_installer_->set_error_on_unsupported_requirements(true);
+
+  // Add urls from the WebApplicationInfo.
+  std::vector<GURL> web_app_info_icon_urls;
+  for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
+           web_app_info_.icons.begin();
+       it != web_app_info_.icons.end();
+       ++it) {
+    if (it->url.is_valid())
+      web_app_info_icon_urls.push_back(it->url);
+  }
+
+  favicon_downloader_.reset(
+      new FaviconDownloader(contents,
+                            web_app_info_icon_urls,
+                            base::Bind(&BookmarkAppHelper::OnIconsDownloaded,
+                                       base::Unretained(this))));
+}
+
+BookmarkAppHelper::~BookmarkAppHelper() {}
+
+void BookmarkAppHelper::Create(const CreateBookmarkAppCallback& callback) {
+  callback_ = callback;
+  favicon_downloader_->Start();
+}
+
+void BookmarkAppHelper::OnIconsDownloaded(
+    bool success,
+    const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
+  // The tab has navigated away during the icon download. Cancel the bookmark
+  // app creation.
+  if (!success) {
+    favicon_downloader_.reset();
+    callback_.Run(NULL, web_app_info_);
+    return;
+  }
+
+  // Add the downloaded icons. Extensions only allow certain icon sizes. First
+  // populate icons that match the allowed sizes exactly and then downscale
+  // remaining icons to the closest allowed size that doesn't yet have an icon.
+  std::set<int> allowed_sizes(extension_misc::kExtensionIconSizes,
+                              extension_misc::kExtensionIconSizes +
+                                  extension_misc::kNumExtensionIconSizes);
+  std::vector<SkBitmap> downloaded_icons;
+  for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
+       map_it != bitmaps.end();
+       ++map_it) {
+    for (std::vector<SkBitmap>::const_iterator bitmap_it =
+             map_it->second.begin();
+         bitmap_it != map_it->second.end();
+         ++bitmap_it) {
+      if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height())
+        continue;
+
+      downloaded_icons.push_back(*bitmap_it);
+    }
+  }
+
+  // If there are icons that don't match the accepted icon sizes, find the
+  // closest bigger icon to the accepted sizes and resize the icon to it. An
+  // icon will be resized and used for at most one size.
+  std::map<int, SkBitmap> resized_bitmaps(
+      ConstrainBitmapsToSizes(downloaded_icons, allowed_sizes));
+
+  // Generate container icons from smaller icons.
+  const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL,
+                                      extension_misc::EXTENSION_ICON_MEDIUM, };
+  const std::set<int> generate_sizes(
+      kIconSizesToGenerate,
+      kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
+
+  // Only generate icons if larger icons don't exist. This means the app
+  // launcher and the taskbar will do their best downsizing large icons and
+  // these container icons are only generated as a last resort against upscaling
+  // a smaller icon.
+  if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
+      resized_bitmaps.end()) {
+    // Generate these from biggest to smallest so we don't end up with
+    // concentric container icons.
+    for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin();
+         it != generate_sizes.rend();
+         ++it) {
+      GenerateContainerIcon(&resized_bitmaps, *it);
+    }
+  }
+
+  // Populate the icon data into the WebApplicationInfo we are using to
+  // install the bookmark app.
+  for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
+           resized_bitmaps.begin();
+       resized_bitmaps_it != resized_bitmaps.end();
+       ++resized_bitmaps_it) {
+    WebApplicationInfo::IconInfo icon_info;
+    icon_info.data = resized_bitmaps_it->second;
+    icon_info.width = icon_info.data.width();
+    icon_info.height = icon_info.data.height();
+    web_app_info_.icons.push_back(icon_info);
+  }
+
+  // Install the app.
+  crx_installer_->InstallWebApp(web_app_info_);
+  favicon_downloader_.reset();
+}
+
+void BookmarkAppHelper::Observe(int type,
+                                const content::NotificationSource& source,
+                                const content::NotificationDetails& details) {
+  switch (type) {
+    case chrome::NOTIFICATION_CRX_INSTALLER_DONE: {
+      const Extension* extension =
+          content::Details<const Extension>(details).ptr();
+      DCHECK(extension);
+      DCHECK_EQ(AppLaunchInfo::GetLaunchWebURL(extension),
+                web_app_info_.app_url);
+      callback_.Run(extension, web_app_info_);
+      break;
+    }
+    case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR:
+      callback_.Run(NULL, web_app_info_);
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/bookmark_app_helper.h b/chrome/browser/extensions/bookmark_app_helper.h
new file mode 100644
index 0000000..6218dc3
--- /dev/null
+++ b/chrome/browser/extensions/bookmark_app_helper.h
@@ -0,0 +1,93 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_HELPER_H_
+#define CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_HELPER_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/common/web_application_info.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class ExtensionService;
+class FaviconDownloader;
+class SkBitmap;
+
+namespace content {
+class WebContents;
+}
+
+namespace extensions {
+class CrxInstaller;
+class Extension;
+
+// A helper class for creating bookmark apps from a WebContents.
+class BookmarkAppHelper : public content::NotificationObserver {
+ public:
+  typedef base::Callback<void(const Extension*, const WebApplicationInfo&)>
+      CreateBookmarkAppCallback;
+
+  // This helper class will create a bookmark app out of |web_app_info| and
+  // install it to |service|. Icons will be downloaded from the URLs in
+  // |web_app_info.icons| using |contents|.
+  BookmarkAppHelper(ExtensionService* service,
+                    WebApplicationInfo web_app_info,
+                    content::WebContents* contents);
+  virtual ~BookmarkAppHelper();
+
+  // This finds the closest not-smaller bitmap in |bitmaps| for each size in
+  // |sizes| and resizes it to that size. This returns a map of sizes to bitmaps
+  // which contains only bitmaps of a size in |sizes| and at most one bitmap of
+  // each size.
+  static std::map<int, SkBitmap> ConstrainBitmapsToSizes(
+      const std::vector<SkBitmap>& bitmaps,
+      const std::set<int>& sizes);
+
+  // Adds a square container icon of |output_size| pixels to |bitmaps| by
+  // centering the biggest smaller icon in |bitmaps| and drawing a rounded
+  // rectangle with strip of the that icon's dominant color at the bottom.
+  // Does nothing if an icon of |output_size| already exists in |bitmaps|.
+  static void GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
+                                    int output_size);
+
+  // Begins the asynchronous bookmark app creation.
+  void Create(const CreateBookmarkAppCallback& callback);
+
+ private:
+  friend class TestBookmarkAppHelper;
+
+  // Performs post icon download tasks including installing the bookmark app.
+  void OnIconsDownloaded(bool success,
+                         const std::map<GURL, std::vector<SkBitmap> >& bitmaps);
+
+  // Overridden from content::NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+  // The WebApplicationInfo that the bookmark app is being created for.
+  WebApplicationInfo web_app_info_;
+
+  // Called on app creation or failure.
+  CreateBookmarkAppCallback callback_;
+
+  // Downloads icons from the given WebApplicationInfo using the given
+  // WebContents.
+  scoped_ptr<FaviconDownloader> favicon_downloader_;
+
+  // Used to install the created bookmark app.
+  scoped_refptr<extensions::CrxInstaller> crx_installer_;
+
+  content::NotificationRegistrar registrar_;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_BOOKMARK_APP_HELPER_H_
diff --git a/chrome/browser/extensions/bookmark_app_helper_unittest.cc b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
new file mode 100644
index 0000000..bac705e
--- /dev/null
+++ b/chrome/browser/extensions/bookmark_app_helper_unittest.cc
@@ -0,0 +1,195 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/bookmark_app_helper.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_service_unittest.h"
+#include "chrome/common/extensions/extension_icon_set.h"
+#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
+#include "chrome/common/extensions/manifest_handlers/icons_handler.h"
+#include "chrome/test/base/testing_profile.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace {
+
+#if !defined(OS_ANDROID)
+const char kAppUrl[] = "http://www.chromium.org";
+const char kAppTitle[] = "Test title";
+const char kAppDescription[] = "Test description";
+
+const int kIconSizeSmall = extension_misc::EXTENSION_ICON_SMALL;
+#endif
+
+class BookmarkAppHelperTest : public testing::Test {
+ public:
+  BookmarkAppHelperTest() {}
+  virtual ~BookmarkAppHelperTest() {}
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperTest);
+};
+
+class BookmarkAppHelperExtensionServiceTest : public ExtensionServiceTestBase {
+ public:
+  BookmarkAppHelperExtensionServiceTest() {}
+  virtual ~BookmarkAppHelperExtensionServiceTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    ExtensionServiceTestBase::SetUp();
+    InitializeEmptyExtensionService();
+    service_->Init();
+    EXPECT_EQ(0u, service_->extensions()->size());
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BookmarkAppHelperExtensionServiceTest);
+};
+
+SkBitmap CreateSquareBitmapWithColor(int size, SkColor color) {
+  SkBitmap bitmap;
+  bitmap.setConfig(SkBitmap::kARGB_8888_Config, size, size);
+  bitmap.allocPixels();
+  bitmap.eraseColor(color);
+  return bitmap;
+}
+
+void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) {
+  // Obtain pixel lock to access pixels.
+  SkAutoLockPixels lock(bitmap);
+  EXPECT_EQ(color, bitmap.getColor(0, 0));
+  EXPECT_EQ(size, bitmap.width());
+  EXPECT_EQ(size, bitmap.height());
+}
+
+}  // namespace
+
+namespace extensions {
+
+class TestBookmarkAppHelper : public BookmarkAppHelper {
+ public:
+  TestBookmarkAppHelper(ExtensionService* service,
+                        WebApplicationInfo web_app_info,
+                        content::WebContents* contents)
+      : BookmarkAppHelper(service, web_app_info, contents) {}
+
+  virtual ~TestBookmarkAppHelper() {}
+
+  void CreationComplete(const extensions::Extension* extension,
+                        const WebApplicationInfo& web_app_info) {
+    extension_ = extension;
+  }
+
+  void CompleteIconDownload(
+      bool success,
+      const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
+    BookmarkAppHelper::OnIconsDownloaded(success, bitmaps);
+  }
+
+  const Extension* extension() { return extension_; }
+
+ private:
+  const Extension* extension_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestBookmarkAppHelper);
+};
+
+// Android doesn't support extensions.
+#if !defined(OS_ANDROID)
+TEST_F(BookmarkAppHelperExtensionServiceTest, CreateBookmarkApp) {
+  WebApplicationInfo web_app_info;
+  web_app_info.app_url = GURL(kAppUrl);
+  web_app_info.title = base::UTF8ToUTF16(kAppTitle);
+  web_app_info.description = base::UTF8ToUTF16(kAppDescription);
+
+  TestBookmarkAppHelper helper(service_, web_app_info, NULL);
+  helper.Create(base::Bind(&TestBookmarkAppHelper::CreationComplete,
+                           base::Unretained(&helper)));
+
+  std::map<GURL, std::vector<SkBitmap> > icon_map;
+  icon_map[GURL(kAppUrl)].push_back(
+      CreateSquareBitmapWithColor(kIconSizeSmall, SK_ColorRED));
+  helper.CompleteIconDownload(true, icon_map);
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(helper.extension());
+  const Extension* extension =
+      service_->GetInstalledExtension(helper.extension()->id());
+  EXPECT_TRUE(extension);
+  EXPECT_EQ(1u, service_->extensions()->size());
+  EXPECT_TRUE(extension->from_bookmark());
+  EXPECT_EQ(kAppTitle, extension->name());
+  EXPECT_EQ(kAppDescription, extension->description());
+  EXPECT_EQ(GURL(kAppUrl), AppLaunchInfo::GetLaunchWebURL(extension));
+  EXPECT_FALSE(
+      IconsInfo::GetIconResource(
+          extension, kIconSizeSmall, ExtensionIconSet::MATCH_EXACTLY).empty());
+}
+#endif
+
+TEST_F(BookmarkAppHelperTest, ConstrainBitmapsToSizes) {
+  std::set<int> desired_sizes;
+  desired_sizes.insert(16);
+  desired_sizes.insert(32);
+  desired_sizes.insert(128);
+  desired_sizes.insert(256);
+
+  {
+    std::vector<SkBitmap> bitmaps;
+    bitmaps.push_back(CreateSquareBitmapWithColor(16, SK_ColorRED));
+    bitmaps.push_back(CreateSquareBitmapWithColor(32, SK_ColorGREEN));
+    bitmaps.push_back(CreateSquareBitmapWithColor(48, SK_ColorBLUE));
+    bitmaps.push_back(CreateSquareBitmapWithColor(144, SK_ColorYELLOW));
+
+    std::map<int, SkBitmap> results(
+        BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
+
+    EXPECT_EQ(3u, results.size());
+    ValidateBitmapSizeAndColor(results[16], 16, SK_ColorRED);
+    ValidateBitmapSizeAndColor(results[32], 32, SK_ColorGREEN);
+    ValidateBitmapSizeAndColor(results[128], 128, SK_ColorYELLOW);
+  }
+  {
+    std::vector<SkBitmap> bitmaps;
+    bitmaps.push_back(CreateSquareBitmapWithColor(512, SK_ColorRED));
+    bitmaps.push_back(CreateSquareBitmapWithColor(18, SK_ColorGREEN));
+    bitmaps.push_back(CreateSquareBitmapWithColor(33, SK_ColorBLUE));
+    bitmaps.push_back(CreateSquareBitmapWithColor(17, SK_ColorYELLOW));
+
+    std::map<int, SkBitmap> results(
+        BookmarkAppHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
+
+    EXPECT_EQ(3u, results.size());
+    ValidateBitmapSizeAndColor(results[16], 16, SK_ColorYELLOW);
+    ValidateBitmapSizeAndColor(results[32], 32, SK_ColorBLUE);
+    ValidateBitmapSizeAndColor(results[256], 256, SK_ColorRED);
+  }
+}
+
+TEST_F(BookmarkAppHelperTest, GenerateIcons) {
+  {
+    // The 32x32 icon should be generated from the 16x16 icon.
+    std::map<int, SkBitmap> bitmaps;
+    bitmaps[16] = CreateSquareBitmapWithColor(16, SK_ColorRED);
+    BookmarkAppHelper::GenerateContainerIcon(&bitmaps, 32);
+    EXPECT_EQ(1u, bitmaps.count(32));
+    EXPECT_EQ(32, bitmaps[32].width());
+  }
+  {
+    // The 32x32 icon should not be generated because no smaller icon exists.
+    std::map<int, SkBitmap> bitmaps;
+    bitmaps[48] = CreateSquareBitmapWithColor(48, SK_ColorRED);
+    BookmarkAppHelper::GenerateContainerIcon(&bitmaps, 32);
+    EXPECT_EQ(0u, bitmaps.count(32));
+  }
+  {
+    // The 32x32 icon should not be generated with no base icons.
+    std::map<int, SkBitmap> bitmaps;
+    BookmarkAppHelper::GenerateContainerIcon(&bitmaps, 32);
+    EXPECT_EQ(0u, bitmaps.count(32));
+  }
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/browser_context_keyed_service_factories.cc b/chrome/browser/extensions/browser_context_keyed_service_factories.cc
index 7bcd85a..7a4a27d 100644
--- a/chrome/browser/extensions/browser_context_keyed_service_factories.cc
+++ b/chrome/browser/extensions/browser_context_keyed_service_factories.cc
@@ -46,6 +46,8 @@
 #include "chrome/browser/extensions/api/web_navigation/web_navigation_api.h"
 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
 #include "chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.h"
+#include "chrome/browser/extensions/api/webstore/webstore_api.h"
+#include "chrome/browser/extensions/extension_gcm_app_handler.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/extensions/extension_toolbar_model_factory.h"
 #include "chrome/browser/extensions/extension_web_ui_override_registrar.h"
@@ -91,6 +93,7 @@
   extensions::DialAPIFactory::GetInstance();
   extensions::ExtensionActionAPI::GetFactoryInstance();
   extensions::ExtensionSystemFactory::GetInstance();
+  extensions::ExtensionToolbarModelFactory::GetInstance();
   extensions::ExtensionWebUIOverrideRegistrar::GetFactoryInstance();
   extensions::FeedbackPrivateAPI::GetFactoryInstance();
   extensions::FontSettingsAPI::GetFactoryInstance();
@@ -142,11 +145,12 @@
   extensions::WebNavigationAPI::GetFactoryInstance();
   extensions::WebRequestAPI::GetFactoryInstance();
   extensions::WebrtcAudioPrivateEventService::GetFactoryInstance();
-  ExtensionToolbarModelFactory::GetInstance();
+  extensions::WebstoreAPI::GetFactoryInstance();
 #if defined(OS_CHROMEOS)
   file_manager::FileBrowserPrivateAPIFactory::GetInstance();
 #endif
   TokenCacheServiceFactory::GetInstance();
+  extensions::ExtensionGCMAppHandler::GetFactoryInstance();
 }
 
 }  // namespace chrome_extensions
diff --git a/chrome/browser/extensions/browser_permissions_policy_delegate.cc b/chrome/browser/extensions/browser_permissions_policy_delegate.cc
index d948e73..d94fcc8 100644
--- a/chrome/browser/extensions/browser_permissions_policy_delegate.cc
+++ b/chrome/browser/extensions/browser_permissions_policy_delegate.cc
@@ -11,8 +11,8 @@
 #include "extensions/common/manifest_constants.h"
 
 #if !defined(OS_CHROMEOS)
-#include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/chrome_signin_client.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #endif
 
 namespace extensions {
@@ -34,7 +34,7 @@
     const UserScript* script,
     int process_id,
     std::string* error) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
 #if !defined(OS_CHROMEOS)
   // NULL in unit tests.
@@ -48,9 +48,9 @@
       g_browser_process->profile_manager()->GetLoadedProfiles();
   for (std::vector<Profile*>::iterator profile = profiles.begin();
        profile != profiles.end(); ++profile) {
-    SigninManager* signin_manager =
-        SigninManagerFactory::GetForProfile(*profile);
-    if (signin_manager && signin_manager->IsSigninProcess(process_id)) {
+    ChromeSigninClient* signin_client =
+        ChromeSigninClientFactory::GetForProfile(*profile);
+    if (signin_client && signin_client->IsSigninProcess(process_id)) {
       if (error)
         *error = errors::kCannotScriptSigninPage;
       return false;
diff --git a/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc b/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc
index 401ac5c..32551ee 100644
--- a/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc
+++ b/chrome/browser/extensions/browser_permissions_policy_delegate_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/signin/chrome_signin_client.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -62,9 +64,10 @@
 
   content::MockRenderProcessHost signin_process(profile_);
   content::MockRenderProcessHost normal_process(profile_);
-  SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile_);
-  ASSERT_TRUE(signin_manager);
-  signin_manager->SetSigninProcess(signin_process.GetID());
+  ChromeSigninClient* signin_client =
+      ChromeSigninClientFactory::GetForProfile(profile_);
+  ASSERT_TRUE(signin_client);
+  signin_client->SetSigninProcess(signin_process.GetID());
 
   scoped_refptr<const Extension> extension(CreateTestExtension("a"));
   std::string error;
diff --git a/chrome/browser/extensions/chrome_app_api_browsertest.cc b/chrome/browser/extensions/chrome_app_api_browsertest.cc
index b0ace91..86428bf 100644
--- a/chrome/browser/extensions/chrome_app_api_browsertest.cc
+++ b/chrome/browser/extensions/chrome_app_api_browsertest.cc
@@ -27,51 +27,66 @@
 
 class ChromeAppAPITest : public ExtensionBrowserTest {
  protected:
-  bool IsAppInstalled() { return IsAppInstalled(""); }
-  bool IsAppInstalled(const char* frame_xpath) {
+  bool IsAppInstalledInMainFrame() {
+    return IsAppInstalledInFrame(
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
+  }
+  bool IsAppInstalledInIFrame() {
+    return IsAppInstalledInFrame(GetIFrame());
+  }
+  bool IsAppInstalledInFrame(content::RenderFrameHost* frame) {
     const char kGetAppIsInstalled[] =
         "window.domAutomationController.send(window.chrome.app.isInstalled);";
     bool result;
-    CHECK(
-        content::ExecuteScriptInFrameAndExtractBool(
-            browser()->tab_strip_model()->GetActiveWebContents(),
-            frame_xpath,
-            kGetAppIsInstalled,
-            &result));
+    CHECK(content::ExecuteScriptAndExtractBool(frame,
+                                               kGetAppIsInstalled,
+                                               &result));
     return result;
   }
 
-  std::string InstallState() { return InstallState(""); }
-  std::string InstallState(const char* frame_xpath) {
+  std::string InstallStateInMainFrame() {
+    return InstallStateInFrame(
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
+  }
+  std::string InstallStateInIFrame() {
+    return InstallStateInFrame(GetIFrame());
+  }
+  std::string InstallStateInFrame(content::RenderFrameHost* frame) {
     const char kGetAppInstallState[] =
         "window.chrome.app.installState("
         "    function(s) { window.domAutomationController.send(s); });";
     std::string result;
-    CHECK(
-        content::ExecuteScriptInFrameAndExtractString(
-            browser()->tab_strip_model()->GetActiveWebContents(),
-            frame_xpath,
-            kGetAppInstallState,
-            &result));
+    CHECK(content::ExecuteScriptAndExtractString(frame,
+                                                 kGetAppInstallState,
+                                                 &result));
     return result;
   }
 
-  std::string RunningState() { return RunningState(""); }
-  std::string RunningState(const char* frame_xpath) {
+  std::string RunningStateInMainFrame() {
+    return RunningStateInFrame(
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
+  }
+  std::string RunningStateInIFrame() {
+    return RunningStateInFrame(GetIFrame());
+  }
+  std::string RunningStateInFrame(content::RenderFrameHost* frame) {
     const char kGetAppRunningState[] =
         "window.domAutomationController.send("
         "    window.chrome.app.runningState());";
     std::string result;
-    CHECK(
-        content::ExecuteScriptInFrameAndExtractString(
-            browser()->tab_strip_model()->GetActiveWebContents(),
-            frame_xpath,
-            kGetAppRunningState,
-            &result));
+    CHECK(content::ExecuteScriptAndExtractString(frame,
+                                                 kGetAppRunningState,
+                                                 &result));
     return result;
   }
 
  private:
+  content::RenderFrameHost* GetIFrame() {
+    return content::FrameMatchingPredicate(
+        browser()->tab_strip_model()->GetActiveWebContents(),
+        base::Bind(&content::FrameIsChildOfMainFrame));
+  }
+
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     ExtensionBrowserTest::SetUpCommandLine(command_line);
     command_line->AppendSwitchASCII(switches::kAppsCheckoutURL,
@@ -104,7 +119,7 @@
 
   // Before the app is installed, app.com does not think that it is installed
   ui_test_utils::NavigateToURL(browser(), app_url);
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
   // Load an app which includes app.com in its extent.
   const Extension* extension = LoadExtension(
@@ -113,11 +128,11 @@
 
   // Even after the app is installed, the existing app.com tab is not in an
   // app process, so chrome.app.isInstalled should return false.
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
   // Test that a non-app page has chrome.app.isInstalled = false.
   ui_test_utils::NavigateToURL(browser(), non_app_url);
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
   // Test that a non-app page returns null for chrome.app.getDetails().
   const char kGetAppDetails[] =
@@ -133,7 +148,7 @@
 
   // Check that an app page has chrome.app.isInstalled = true.
   ui_test_utils::NavigateToURL(browser(), app_url);
-  EXPECT_TRUE(IsAppInstalled());
+  EXPECT_TRUE(IsAppInstalledInMainFrame());
 
   // Check that an app page returns the correct result for
   // chrome.app.getDetails().
@@ -252,48 +267,48 @@
   // Before the app is installed, app.com does not think that it is installed
   ui_test_utils::NavigateToURL(browser(), app_url);
 
-  EXPECT_EQ("not_installed", InstallState());
-  EXPECT_EQ("cannot_run", RunningState());
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_EQ("not_installed", InstallStateInMainFrame());
+  EXPECT_EQ("cannot_run", RunningStateInMainFrame());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
   const Extension* extension = LoadExtension(
       test_data_dir_.AppendASCII("app_dot_com_app"));
   ASSERT_TRUE(extension);
 
-  EXPECT_EQ("installed", InstallState());
-  EXPECT_EQ("ready_to_run", RunningState());
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_EQ("installed", InstallStateInMainFrame());
+  EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
   // Reloading the page should put the tab in an app process.
   ui_test_utils::NavigateToURL(browser(), app_url);
-  EXPECT_EQ("installed", InstallState());
-  EXPECT_EQ("running", RunningState());
-  EXPECT_TRUE(IsAppInstalled());
+  EXPECT_EQ("installed", InstallStateInMainFrame());
+  EXPECT_EQ("running", RunningStateInMainFrame());
+  EXPECT_TRUE(IsAppInstalledInMainFrame());
 
   // Disable the extension and verify the state.
   browser()->profile()->GetExtensionService()->DisableExtension(
       extension->id(), Extension::DISABLE_PERMISSIONS_INCREASE);
   ui_test_utils::NavigateToURL(browser(), app_url);
 
-  EXPECT_EQ("disabled", InstallState());
-  EXPECT_EQ("cannot_run", RunningState());
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_EQ("disabled", InstallStateInMainFrame());
+  EXPECT_EQ("cannot_run", RunningStateInMainFrame());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
   browser()->profile()->GetExtensionService()->EnableExtension(extension->id());
-  EXPECT_EQ("installed", InstallState());
-  EXPECT_EQ("ready_to_run", RunningState());
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_EQ("installed", InstallStateInMainFrame());
+  EXPECT_EQ("ready_to_run", RunningStateInMainFrame());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
   // The non-app URL should still not be installed or running.
   ui_test_utils::NavigateToURL(browser(), non_app_url);
 
-  EXPECT_EQ("not_installed", InstallState());
-  EXPECT_EQ("cannot_run", RunningState());
-  EXPECT_FALSE(IsAppInstalled());
+  EXPECT_EQ("not_installed", InstallStateInMainFrame());
+  EXPECT_EQ("cannot_run", RunningStateInMainFrame());
+  EXPECT_FALSE(IsAppInstalledInMainFrame());
 
-  EXPECT_EQ("installed", InstallState("//html/iframe[1]"));
-  EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
-  EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
+  EXPECT_EQ("installed", InstallStateInIFrame());
+  EXPECT_EQ("cannot_run", RunningStateInIFrame());
+  EXPECT_FALSE(IsAppInstalledInIFrame());
 
 }
 
@@ -319,7 +334,7 @@
   // within an app.
   ui_test_utils::NavigateToURL(browser(), app_url);
 
-  EXPECT_EQ("not_installed", InstallState("//html/iframe[1]"));
-  EXPECT_EQ("cannot_run", RunningState("//html/iframe[1]"));
-  EXPECT_FALSE(IsAppInstalled("//html/iframe[1]"));
+  EXPECT_EQ("not_installed", InstallStateInIFrame());
+  EXPECT_EQ("cannot_run", RunningStateInIFrame());
+  EXPECT_FALSE(IsAppInstalledInIFrame());
 }
diff --git a/chrome/browser/extensions/chrome_app_sorting_unittest.cc b/chrome/browser/extensions/chrome_app_sorting_unittest.cc
index e32668d..2616797 100644
--- a/chrome/browser/extensions/chrome_app_sorting_unittest.cc
+++ b/chrome/browser/extensions/chrome_app_sorting_unittest.cc
@@ -31,7 +31,8 @@
     prefs()->OnExtensionInstalled(extension_.get(),
                                   Extension::ENABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  std::string());
   }
 
   virtual void Verify() OVERRIDE {
@@ -59,7 +60,8 @@
     prefs()->OnExtensionInstalled(extension_.get(),
                                   Extension::ENABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  std::string());
   }
 
   virtual void Verify() OVERRIDE {
@@ -111,7 +113,8 @@
     prefs()->OnExtensionInstalled(extension_.get(),
                                   Extension::ENABLED,
                                   false,
-                                  first_page_);
+                                  first_page_,
+                                  std::string());
     EXPECT_TRUE(first_page_.Equals(
         app_sorting()->GetPageOrdinal(extension_->id())));
     EXPECT_EQ(0, app_sorting()->PageStringOrdinalAsInteger(first_page_));
@@ -121,7 +124,8 @@
     prefs()->OnExtensionInstalled(extension2.get(),
                                   Extension::ENABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  std::string());
     EXPECT_TRUE(first_page_.Equals(
         app_sorting()->GetPageOrdinal(extension2->id())));
   }
@@ -636,7 +640,8 @@
     prefs()->OnExtensionInstalled(app1_scoped_.get(),
                                   Extension::ENABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  std::string());
 
     app2_scoped_ = Extension::Create(
         prefs_.temp_dir().AppendASCII("app2_"), Manifest::EXTERNAL_PREF,
@@ -644,7 +649,8 @@
     prefs()->OnExtensionInstalled(app2_scoped_.get(),
                                   Extension::ENABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  std::string());
 
     app1_ = app1_scoped_.get();
     app2_ = app2_scoped_.get();
@@ -830,7 +836,8 @@
     prefs()->OnExtensionInstalled(app_.get(),
                                   Extension::ENABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  std::string());
   }
 
   scoped_refptr<Extension> app_;
@@ -874,10 +881,8 @@
  protected:
   virtual void InstallApps() OVERRIDE {
     install_page_ = default_page_ordinal_.CreateAfter();
-    prefs()->OnExtensionInstalled(app_.get(),
-                                  Extension::ENABLED,
-                                  false,
-                                  install_page_);
+    prefs()->OnExtensionInstalled(
+        app_.get(), Extension::ENABLED, false, install_page_, std::string());
   }
 
  private:
diff --git a/chrome/browser/extensions/chrome_extension_web_contents_observer.cc b/chrome/browser/extensions/chrome_extension_web_contents_observer.cc
index 088338b..0723139 100644
--- a/chrome/browser/extensions/chrome_extension_web_contents_observer.cc
+++ b/chrome/browser/extensions/chrome_extension_web_contents_observer.cc
@@ -7,13 +7,13 @@
 #include "chrome/browser/extensions/api/messaging/message_service.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
 #include "chrome/browser/extensions/extension_service.h"
-#include "chrome/common/extensions/api/messaging/message.h"
 #include "chrome/common/render_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/common/api/messaging/message.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/extension_urls.h"
 
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc
index 222e0d6..88d497f 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -11,7 +11,6 @@
 #include "chrome/browser/extensions/activity_log/activity_log.h"
 #include "chrome/browser/extensions/api/preference/chrome_direct_setting.h"
 #include "chrome/browser/extensions/api/preference/preference_api.h"
-#include "chrome/browser/extensions/api/runtime/runtime_api.h"
 #include "chrome/browser/extensions/api/web_request/web_request_api.h"
 #include "chrome/browser/extensions/chrome_app_sorting.h"
 #include "chrome/browser/extensions/chrome_extension_host_delegate.h"
@@ -229,13 +228,6 @@
   registry->RegisterFunction<
       extensions::chromedirectsetting::ClearDirectSettingFunction>();
 
-  // Runtime.
-  registry->RegisterFunction<extensions::RuntimeGetBackgroundPageFunction>();
-  registry->RegisterFunction<extensions::RuntimeSetUninstallURLFunction>();
-  registry->RegisterFunction<extensions::RuntimeReloadFunction>();
-  registry->RegisterFunction<extensions::RuntimeRequestUpdateCheckFunction>();
-  registry->RegisterFunction<extensions::RuntimeRestartFunction>();
-
   // Generated APIs.
   extensions::core_api::GeneratedFunctionRegistry::RegisterAll(registry);
   extensions::api::GeneratedFunctionRegistry::RegisterAll(registry);
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc
index 994b62e..b97be23 100644
--- a/chrome/browser/extensions/component_loader.cc
+++ b/chrome/browser/extensions/component_loader.cc
@@ -287,6 +287,11 @@
 #endif  // defined(OS_CHROMEOS)
 }
 
+void ComponentLoader::AddVideoPlayerExtension() {
+  Add(IDR_VIDEOPLAYER_MANIFEST,
+      base::FilePath(FILE_PATH_LITERAL("video_player")));
+}
+
 void ComponentLoader::AddHangoutServicesExtension() {
 #if defined(GOOGLE_CHROME_BUILD) || defined(ENABLE_HANGOUT_SERVICES_EXTENSION)
   Add(IDR_HANGOUT_SERVICES_MANIFEST,
@@ -435,6 +440,7 @@
     return;
 
   // Component extensions needed for kiosk apps.
+  AddVideoPlayerExtension();
   AddFileManagerExtension();
 
   // Add virtual keyboard.
@@ -465,7 +471,9 @@
 #endif
 
   if (!skip_session_components) {
+    AddVideoPlayerExtension();
     AddFileManagerExtension();
+
     AddHangoutServicesExtension();
     AddHotwordHelperExtension();
     AddImageLoaderExtension();
diff --git a/chrome/browser/extensions/component_loader.h b/chrome/browser/extensions/component_loader.h
index b01e18a..e60c824 100644
--- a/chrome/browser/extensions/component_loader.h
+++ b/chrome/browser/extensions/component_loader.h
@@ -126,6 +126,7 @@
   void AddDefaultComponentExtensionsWithBackgroundPages(
       bool skip_session_components);
   void AddFileManagerExtension();
+  void AddVideoPlayerExtension();
   void AddHangoutServicesExtension();
   void AddHotwordHelperExtension();
   void AddImageLoaderExtension();
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc
index cdf1c95..ad7c18d 100644
--- a/chrome/browser/extensions/crx_installer.cc
+++ b/chrome/browser/extensions/crx_installer.cc
@@ -28,6 +28,8 @@
 #include "chrome/browser/extensions/extension_error_reporter.h"
 #include "chrome/browser/extensions/extension_install_ui.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/install_tracker.h"
+#include "chrome/browser/extensions/install_tracker_factory.h"
 #include "chrome/browser/extensions/permissions_updater.h"
 #include "chrome/browser/extensions/webstore_installer.h"
 #include "chrome/browser/profiles/profile.h"
@@ -176,6 +178,9 @@
   if (!service || service->browser_terminating())
     return;
 
+  InstallTrackerFactory::GetForProfile(profile())
+      ->OnBeginCrxInstall(expected_id_);
+
   source_file_ = source_file;
 
   scoped_refptr<SandboxedUnpacker> unpacker(
@@ -472,7 +477,7 @@
 }
 
 void CrxInstaller::CheckImportsAndRequirements() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ExtensionService* service = service_weak_.get();
   if (!service || service->browser_terminating())
     return;
@@ -501,7 +506,7 @@
 
 void CrxInstaller::OnRequirementsChecked(
     std::vector<std::string> requirement_errors) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!service_weak_)
     return;
 
@@ -521,7 +526,7 @@
 
 void CrxInstaller::OnBlacklistChecked(
     extensions::BlacklistState blacklist_state) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!service_weak_)
     return;
 
@@ -548,7 +553,7 @@
 }
 
 void CrxInstaller::ConfirmInstall() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ExtensionService* service = service_weak_.get();
   if (!service || service->browser_terminating())
     return;
@@ -613,7 +618,7 @@
 }
 
 void CrxInstaller::InstallUIProceed() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ExtensionService* service = service_weak_.get();
   if (!service || service->browser_terminating())
@@ -725,7 +730,7 @@
 }
 
 void CrxInstaller::ReportFailureFromUIThread(const CrxInstallerError& error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   content::NotificationService* service =
       content::NotificationService::current();
@@ -739,7 +744,9 @@
   // TODO(aa): Need to go through unit tests and clean them up too, probably get
   // rid of this line.
   ExtensionErrorReporter::GetInstance()->ReportError(
-      error.message(), false);  // quiet
+      error.message(),
+      false,  // Be quiet.
+      NULL);  // Caller expects no response.
 
   if (client_)
     client_->OnInstallFailure(error);
@@ -767,7 +774,7 @@
 }
 
 void CrxInstaller::ReportSuccessFromUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!service_weak_.get() || service_weak_->browser_terminating())
     return;
@@ -833,7 +840,7 @@
 }
 
 void CrxInstaller::CheckUpdateFromSettingsPage() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ExtensionService* service = service_weak_.get();
   if (!service || service->browser_terminating())
@@ -854,7 +861,7 @@
 }
 
 void CrxInstaller::ConfirmReEnable() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ExtensionService* service = service_weak_.get();
   if (!service || service->browser_terminating())
diff --git a/chrome/browser/extensions/data_deleter.cc b/chrome/browser/extensions/data_deleter.cc
index f0d0721..9d8ffb7 100644
--- a/chrome/browser/extensions/data_deleter.cc
+++ b/chrome/browser/extensions/data_deleter.cc
@@ -38,7 +38,7 @@
 void DeleteOrigin(Profile* profile,
                   StoragePartition* partition,
                   const GURL& origin) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(profile);
   DCHECK(partition);
 
diff --git a/chrome/browser/extensions/dev_mode_bubble_controller.cc b/chrome/browser/extensions/dev_mode_bubble_controller.cc
index 7b30512..b1dec7e 100644
--- a/chrome/browser/extensions/dev_mode_bubble_controller.cc
+++ b/chrome/browser/extensions/dev_mode_bubble_controller.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/extensions/extension_action_manager.h"
 #include "chrome/browser/extensions/extension_message_bubble.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_toolbar_model.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -26,6 +27,8 @@
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
+namespace extensions {
+
 namespace {
 
 base::LazyInstance<std::set<Profile*> > g_shown_for_profiles =
@@ -34,20 +37,19 @@
 ////////////////////////////////////////////////////////////////////////////////
 // DevModeBubbleDelegate
 
-DevModeBubbleDelegate::DevModeBubbleDelegate(ExtensionService* service)
-    : service_(service) {
-}
+DevModeBubbleDelegate::DevModeBubbleDelegate(Profile* profile)
+    : profile_(profile),
+      service_(ExtensionSystem::Get(profile)->extension_service()) {}
 
 DevModeBubbleDelegate::~DevModeBubbleDelegate() {
 }
 
 bool DevModeBubbleDelegate::ShouldIncludeExtension(
     const std::string& extension_id) {
-  const extensions::Extension* extension =
-      service_->GetExtensionById(extension_id, false);
+  const Extension* extension = service_->GetExtensionById(extension_id, false);
   if (!extension)
     return false;
-  return extensions::DevModeBubbleController::IsDevModeExtension(extension);
+  return DevModeBubbleController::IsDevModeExtension(extension);
 }
 
 void DevModeBubbleDelegate::AcknowledgeExtension(
@@ -55,12 +57,15 @@
     ExtensionMessageBubbleController::BubbleAction user_action) {
 }
 
-void DevModeBubbleDelegate::PerformAction(
-    const extensions::ExtensionIdList& list) {
-  for (size_t i = 0; i < list.size(); ++i) {
-    service_->DisableExtension(
-        list[i], extensions::Extension::DISABLE_USER_ACTION);
-  }
+void DevModeBubbleDelegate::PerformAction(const ExtensionIdList& list) {
+  for (size_t i = 0; i < list.size(); ++i)
+    service_->DisableExtension(list[i], Extension::DISABLE_USER_ACTION);
+}
+
+void DevModeBubbleDelegate::OnClose() {
+  ExtensionToolbarModel* toolbar_model = ExtensionToolbarModel::Get(profile_);
+  if (toolbar_model)
+    toolbar_model->StopHighlighting();
 }
 
 base::string16 DevModeBubbleDelegate::GetTitle() const {
@@ -112,8 +117,6 @@
 
 }  // namespace
 
-namespace extensions {
-
 ////////////////////////////////////////////////////////////////////////////////
 // DevModeBubbleController
 
@@ -135,10 +138,8 @@
 }
 
 DevModeBubbleController::DevModeBubbleController(Profile* profile)
-    : ExtensionMessageBubbleController(
-          new DevModeBubbleDelegate(
-              ExtensionSystem::Get(profile)->extension_service()),
-          profile),
+    : ExtensionMessageBubbleController(new DevModeBubbleDelegate(profile),
+                                       profile),
       profile_(profile) {}
 
 DevModeBubbleController::~DevModeBubbleController() {
diff --git a/chrome/browser/extensions/dev_mode_bubble_controller.h b/chrome/browser/extensions/dev_mode_bubble_controller.h
index 2a65c82..3a83782 100644
--- a/chrome/browser/extensions/dev_mode_bubble_controller.h
+++ b/chrome/browser/extensions/dev_mode_bubble_controller.h
@@ -14,14 +14,14 @@
 class Browser;
 class ExtensionService;
 
-using extensions::ExtensionMessageBubbleController;
+namespace extensions {
 
 namespace {
 
 class DevModeBubbleDelegate
     : public ExtensionMessageBubbleController::Delegate {
  public:
-  explicit DevModeBubbleDelegate(ExtensionService* service);
+  explicit DevModeBubbleDelegate(Profile* profile);
   virtual ~DevModeBubbleDelegate();
 
   // ExtensionMessageBubbleController::Delegate methods.
@@ -29,7 +29,8 @@
   virtual void AcknowledgeExtension(
       const std::string& extension_id,
       ExtensionMessageBubbleController::BubbleAction user_action) OVERRIDE;
-  virtual void PerformAction(const extensions::ExtensionIdList& list) OVERRIDE;
+  virtual void PerformAction(const ExtensionIdList& list) OVERRIDE;
+  virtual void OnClose() OVERRIDE;
   virtual base::string16 GetTitle() const OVERRIDE;
   virtual base::string16 GetMessageBody() const OVERRIDE;
   virtual base::string16 GetOverflowText(
@@ -44,6 +45,9 @@
       ExtensionMessageBubbleController::BubbleAction action) OVERRIDE;
 
  private:
+  // The associated profile (weak).
+  Profile* profile_;
+
   // Our extension service. Weak, not owned by us.
   ExtensionService* service_;
 
@@ -52,8 +56,6 @@
 
 }  // namespace
 
-namespace extensions {
-
 class DevModeBubble;
 
 class DevModeBubbleController
diff --git a/chrome/browser/extensions/event_names.cc b/chrome/browser/extensions/event_names.cc
deleted file mode 100644
index a2833b9..0000000
--- a/chrome/browser/extensions/event_names.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/event_names.h"
-
-namespace extensions {
-
-namespace event_names {
-
-const char kOnInputMethodChanged[] = "inputMethodPrivate.onChanged";
-
-const char kOnContextMenus[] = "contextMenus";
-const char kOnWebviewContextMenus[] = "webview.contextMenus";
-
-const char kOnNotificationError[] = "notifications.onError";
-
-}  // namespace event_names
-
-}  // namespace extensions
diff --git a/chrome/browser/extensions/event_names.h b/chrome/browser/extensions/event_names.h
deleted file mode 100644
index 3ba5c0b..0000000
--- a/chrome/browser/extensions/event_names.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Constants for the event names sent to extensions.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EVENT_NAMES_H_
-#define CHROME_BROWSER_EXTENSIONS_EVENT_NAMES_H_
-
-namespace extensions {
-
-namespace event_names {
-
-// FileBrowser.
-extern const char kOnDirectoryChanged[];
-extern const char kOnFileBrowserMountCompleted[];
-extern const char kOnFileTransfersUpdated[];
-extern const char kOnFileBrowserPreferencesChanged[];
-extern const char kOnFileBrowserDriveConnectionStatusChanged[];
-extern const char kOnFileBrowserCopyProgress[];
-
-// InputMethod.
-extern const char kOnInputMethodChanged[];
-
-// Context menus.
-extern const char kOnContextMenus[];
-extern const char kOnWebviewContextMenus[];
-
-// Notifications.
-extern const char kOnNotificationError[];
-
-}  // namespace event_names
-
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EVENT_NAMES_H_
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index dc580db..5c665ba 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -124,8 +124,27 @@
   observer_.reset(new ExtensionTestNotificationObserver(browser()));
 }
 
+const Extension* ExtensionBrowserTest::LoadExtension(
+    const base::FilePath& path) {
+  return LoadExtensionWithFlags(path, kFlagEnableFileAccess);
+}
+
+const Extension* ExtensionBrowserTest::LoadExtensionIncognito(
+    const base::FilePath& path) {
+  return LoadExtensionWithFlags(path,
+                                kFlagEnableFileAccess | kFlagEnableIncognito);
+}
+
 const Extension* ExtensionBrowserTest::LoadExtensionWithFlags(
     const base::FilePath& path, int flags) {
+  return LoadExtensionWithInstallParam(path, flags, std::string());
+}
+
+const extensions::Extension*
+ExtensionBrowserTest::LoadExtensionWithInstallParam(
+    const base::FilePath& path,
+    int flags,
+    const std::string& install_param) {
   ExtensionService* service = extensions::ExtensionSystem::Get(
       profile())->extension_service();
   {
@@ -169,13 +188,22 @@
 
   const std::string extension_id = extension->id();
 
-  // The call to OnExtensionInstalled ensures the other extension prefs
-  // are set up with the defaults.
-  extensions::ExtensionPrefs::Get(profile())
-      ->OnExtensionInstalled(extension,
-                             Extension::ENABLED,
-                             false,
-                             syncer::StringOrdinal::CreateInitialOrdinal());
+  if (!install_param.empty()) {
+    extensions::ExtensionPrefs::Get(profile())
+        ->SetInstallParam(extension_id, install_param);
+    // Re-enable the extension if needed.
+    if (service->extensions()->Contains(extension_id)) {
+      content::WindowedNotificationObserver load_signal(
+          chrome::NOTIFICATION_EXTENSION_LOADED,
+          content::Source<Profile>(profile()));
+      // Reload the extension so that the NOTIFICATION_EXTENSION_LOADED
+      // observers may access |install_param|.
+      service->ReloadExtension(extension_id);
+      load_signal.Wait();
+      extension = service->GetExtensionById(extension_id, false);
+      CHECK(extension) << extension_id << " not found after reloading.";
+    }
+  }
 
   // Toggling incognito or file access will reload the extension, so wait for
   // the reload and grab the new extension instance. The default state is
@@ -214,17 +242,6 @@
   return extension;
 }
 
-const Extension* ExtensionBrowserTest::LoadExtension(
-    const base::FilePath& path) {
-  return LoadExtensionWithFlags(path, kFlagEnableFileAccess);
-}
-
-const Extension* ExtensionBrowserTest::LoadExtensionIncognito(
-    const base::FilePath& path) {
-  return LoadExtensionWithFlags(path,
-                                kFlagEnableFileAccess | kFlagEnableIncognito);
-}
-
 const Extension* ExtensionBrowserTest::LoadExtensionAsComponentWithManifest(
     const base::FilePath& path,
     const base::FilePath::CharType* manifest_relative_path) {
diff --git a/chrome/browser/extensions/extension_browsertest.h b/chrome/browser/extensions/extension_browsertest.h
index a9bf4ba..d8f19e9 100644
--- a/chrome/browser/extensions/extension_browsertest.h
+++ b/chrome/browser/extensions/extension_browsertest.h
@@ -80,13 +80,22 @@
 
   const extensions::Extension* LoadExtension(const base::FilePath& path);
 
-  // Same as above, but enables the extension in incognito mode first.
+  // Load extension and enable it in incognito mode.
   const extensions::Extension* LoadExtensionIncognito(
       const base::FilePath& path);
 
+  // Load extension from the |path| folder. |flags| is bit mask of values from
+  // |Flags| enum.
   const extensions::Extension* LoadExtensionWithFlags(
       const base::FilePath& path, int flags);
 
+  // Same as above, but sets the installation parameter to the extension
+  // preferences.
+  const extensions::Extension* LoadExtensionWithInstallParam(
+      const base::FilePath& path,
+      int flags,
+      const std::string& install_param);
+
   // Loads unpacked extension from |path| with manifest |manifest_relative_path|
   // and imitates that it is a component extension.
   // |manifest_relative_path| is relative to |path|.
diff --git a/chrome/browser/extensions/extension_commands_global_registry.cc b/chrome/browser/extensions/extension_commands_global_registry.cc
index b3b19b0..1982add 100644
--- a/chrome/browser/extensions/extension_commands_global_registry.cc
+++ b/chrome/browser/extensions/extension_commands_global_registry.cc
@@ -21,8 +21,17 @@
 }
 
 ExtensionCommandsGlobalRegistry::~ExtensionCommandsGlobalRegistry() {
-  if (!IsEventTargetsEmpty())
-    GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
+  if (!IsEventTargetsEmpty()) {
+    GlobalShortcutListener* global_shortcut_listener =
+        GlobalShortcutListener::GetInstance();
+
+    // Resume GlobalShortcutListener before we clean up if the shortcut handling
+    // is currently suspended.
+    if (global_shortcut_listener->IsShortcutHandlingSuspended())
+      global_shortcut_listener->SetShortcutHandlingSuspended(false);
+
+    global_shortcut_listener->UnregisterAccelerators(this);
+  }
 }
 
 static base::LazyInstance<
@@ -42,6 +51,13 @@
       context);
 }
 
+// static
+void ExtensionCommandsGlobalRegistry::SetShortcutHandlingSuspended(
+    bool suspended) {
+  GlobalShortcutListener::GetInstance()->SetShortcutHandlingSuspended(
+      suspended);
+}
+
 void ExtensionCommandsGlobalRegistry::AddExtensionKeybinding(
     const extensions::Extension* extension,
     const std::string& command_name) {
diff --git a/chrome/browser/extensions/extension_commands_global_registry.h b/chrome/browser/extensions/extension_commands_global_registry.h
index 29d7171..92a7a8e 100644
--- a/chrome/browser/extensions/extension_commands_global_registry.h
+++ b/chrome/browser/extensions/extension_commands_global_registry.h
@@ -41,6 +41,9 @@
   // profile.
   static ExtensionCommandsGlobalRegistry* Get(content::BrowserContext* context);
 
+  // Enables/Disables global shortcut handling in Chrome.
+  static void SetShortcutHandlingSuspended(bool suspended);
+
   explicit ExtensionCommandsGlobalRegistry(content::BrowserContext* context);
   virtual ~ExtensionCommandsGlobalRegistry();
 
diff --git a/chrome/browser/extensions/extension_error_reporter.cc b/chrome/browser/extensions/extension_error_reporter.cc
index eb9b595..0b729ca 100644
--- a/chrome/browser/extensions/extension_error_reporter.cc
+++ b/chrome/browser/extensions/extension_error_reporter.cc
@@ -36,17 +36,12 @@
 ExtensionErrorReporter::~ExtensionErrorReporter() {}
 
 void ExtensionErrorReporter::ReportError(const base::string16& message,
-                                         bool be_noisy) {
+                                         bool be_noisy,
+                                         bool* user_response) {
   // NOTE: There won't be a ui_loop_ in the unit test environment.
-  if (ui_loop_ && base::MessageLoop::current() != ui_loop_) {
-    // base::Unretained is okay since the ExtensionErrorReporter is a singleton
-    // that lives until the end of the process.
-    ui_loop_->PostTask(FROM_HERE,
-        base::Bind(&ExtensionErrorReporter::ReportError,
-                   base::Unretained(this),
-                   message,
-                   be_noisy));
-    return;
+  if (ui_loop_) {
+    CHECK(base::MessageLoop::current() == ui_loop_)
+        << "ReportError can only be called from the UI thread.";
   }
 
   errors_.push_back(message);
@@ -56,8 +51,19 @@
   LOG(WARNING) << "Extension error: " << message;
 
   if (enable_noisy_errors_ && be_noisy) {
-    chrome::ShowMessageBox(NULL, base::ASCIIToUTF16("Extension error"), message,
-                           chrome::MESSAGE_BOX_TYPE_WARNING);
+    if (user_response) {
+      *user_response =
+          chrome::MESSAGE_BOX_RESULT_YES ==
+          chrome::ShowMessageBox(NULL,
+                                 base::ASCIIToUTF16("Extension error"),
+                                 message,
+                                 chrome::MESSAGE_BOX_TYPE_QUESTION);
+    } else {
+      chrome::ShowMessageBox(NULL,
+                             base::ASCIIToUTF16("Extension error"),
+                             message,
+                             chrome::MESSAGE_BOX_TYPE_WARNING);
+    }
   }
 }
 
diff --git a/chrome/browser/extensions/extension_error_reporter.h b/chrome/browser/extensions/extension_error_reporter.h
index fbb4ddd..17f657f 100644
--- a/chrome/browser/extensions/extension_error_reporter.h
+++ b/chrome/browser/extensions/extension_error_reporter.h
@@ -32,8 +32,14 @@
   static ExtensionErrorReporter* GetInstance();
 
   // Report an error. Errors always go to VLOG(1). Optionally, they can also
-  // cause a noisy alert box. This method can be called from any thread.
-  void ReportError(const base::string16& message, bool be_noisy);
+  // cause a noisy alert box.
+  //
+  // If |user_response| is non-NULL and |be_noisy| is true (and the
+  // ErrorReporter hasn't turned off noisy errors), the user will be asked if
+  // they want to retry and the answer noted in |user_response|.
+  void ReportError(const base::string16& message,
+                   bool be_noisy,
+                   bool* user_response);
 
   // Get the errors that have been reported so far.
   const std::vector<base::string16>* GetErrors();
diff --git a/chrome/browser/extensions/extension_gcm_app_handler.cc b/chrome/browser/extensions/extension_gcm_app_handler.cc
index 3ed99a0..e0b2545 100644
--- a/chrome/browser/extensions/extension_gcm_app_handler.cc
+++ b/chrome/browser/extensions/extension_gcm_app_handler.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/extensions/extension_gcm_app_handler.h"
 
 #include "base/bind.h"
+#include "base/lazy_instance.h"
 #include "base/location.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
@@ -15,7 +16,6 @@
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/one_shot_event.h"
 #include "extensions/common/permissions/permissions_data.h"
 
 #if !defined(OS_ANDROID)
@@ -26,14 +26,24 @@
 
 namespace {
 
+base::LazyInstance<BrowserContextKeyedAPIFactory<ExtensionGCMAppHandler> >
+    g_factory = LAZY_INSTANCE_INITIALIZER;
+
 bool IsGCMPermissionEnabled(const Extension* extension) {
   return PermissionsData::HasAPIPermission(extension, APIPermission::kGcm);
 }
 
 }  // namespace
 
-ExtensionGCMAppHandler::ExtensionGCMAppHandler(Profile* profile)
-    : profile_(profile),
+
+// static
+BrowserContextKeyedAPIFactory<ExtensionGCMAppHandler>*
+ExtensionGCMAppHandler::GetFactoryInstance() {
+  return g_factory.Pointer();
+}
+
+ExtensionGCMAppHandler::ExtensionGCMAppHandler(content::BrowserContext* context)
+    : profile_(Profile::FromBrowserContext(context)),
       weak_factory_(this) {
   // Listen to various extension related notifications.
   registrar_.Add(this,
@@ -46,13 +56,6 @@
                  chrome::NOTIFICATION_EXTENSION_UNINSTALLED,
                  content::Source<Profile>(profile_));
 
-  // Register app handlers when the extension system is ready. It might be ready
-  // now.
-  ExtensionSystem::Get(profile_)->ready().Post(
-      FROM_HERE,
-      base::Bind(&ExtensionGCMAppHandler::OnExtensionsReady,
-                 weak_factory_.GetWeakPtr()));
-
 #if !defined(OS_ANDROID)
   js_event_router_.reset(new extensions::GcmJsEventRouter(profile_));
 #endif
@@ -136,18 +139,6 @@
   return gcm::GCMProfileServiceFactory::GetForProfile(profile_);
 }
 
-void ExtensionGCMAppHandler::OnExtensionsReady() {
-  // Register app handler for those loaded extensions that use GCM.
-  const ExtensionSet& enabled_extensions =
-      ExtensionRegistry::Get(profile_)->enabled_extensions();
-  for (ExtensionSet::const_iterator extension = enabled_extensions.begin();
-       extension != enabled_extensions.end();
-       ++extension) {
-    if (IsGCMPermissionEnabled(extension->get()))
-      GetGCMProfileService()->AddAppHandler((*extension)->id(), this);
-  }
-}
-
 void ExtensionGCMAppHandler::OnUnregisterCompleted(
     const std::string& app_id, gcm::GCMClient::Result result) {
   // Nothing to do.
diff --git a/chrome/browser/extensions/extension_gcm_app_handler.h b/chrome/browser/extensions/extension_gcm_app_handler.h
index 5edf0a9..af22e21 100644
--- a/chrome/browser/extensions/extension_gcm_app_handler.h
+++ b/chrome/browser/extensions/extension_gcm_app_handler.h
@@ -10,10 +10,13 @@
 #include "chrome/browser/services/gcm/gcm_app_handler.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
-#include "extensions/browser/event_router.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "google_apis/gcm/gcm_client.h"
 
 class Profile;
+namespace content {
+class BrowserContext;
+}
 namespace gcm {
 class GCMProfileService;
 }
@@ -24,12 +27,17 @@
 
 // Defines the interface to provide handling logic for a given app.
 class ExtensionGCMAppHandler : public gcm::GCMAppHandler,
+                               public BrowserContextKeyedAPI,
                                public content::NotificationObserver {
  public:
-  explicit ExtensionGCMAppHandler(Profile* profile);
+  explicit ExtensionGCMAppHandler(content::BrowserContext* context);
   virtual ~ExtensionGCMAppHandler();
 
-  // Overridden from gcm::GCMAppHandler:
+  // BrowserContextKeyedAPI implementation.
+  static BrowserContextKeyedAPIFactory<ExtensionGCMAppHandler>*
+  GetFactoryInstance();
+
+  // gcm::GCMAppHandler implementation.
   virtual void ShutdownHandler() OVERRIDE;
   virtual void OnMessage(
       const std::string& app_id,
@@ -40,16 +48,21 @@
       const gcm::GCMClient::SendErrorDetails& send_error_details) OVERRIDE;
 
  private:
-  // Overridden from content::NotificationObserver:
+  friend class BrowserContextKeyedAPIFactory<ExtensionGCMAppHandler>;
+
+  // content::NotificationObserver implementation.
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
   gcm::GCMProfileService* GetGCMProfileService() const;
-  void OnExtensionsReady();
   void OnUnregisterCompleted(const std::string& app_id,
                              gcm::GCMClient::Result result);
 
+  // BrowserContextKeyedAPI implementation.
+  static const char* service_name() { return "ExtensionGCMAppHandler"; }
+  static const bool kServiceIsNULLWhileTesting = true;
+
   Profile* profile_;
   content::NotificationRegistrar registrar_;
 
diff --git a/chrome/browser/extensions/extension_install_prompt.cc b/chrome/browser/extensions/extension_install_prompt.cc
index 433c173..d3760ce 100644
--- a/chrome/browser/extensions/extension_install_prompt.cc
+++ b/chrome/browser/extensions/extension_install_prompt.cc
@@ -26,7 +26,7 @@
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "extensions/common/extension.h"
diff --git a/chrome/browser/extensions/extension_installer.cc b/chrome/browser/extensions/extension_installer.cc
index c43421d..e37f402 100644
--- a/chrome/browser/extensions/extension_installer.cc
+++ b/chrome/browser/extensions/extension_installer.cc
@@ -23,7 +23,7 @@
 
 void ExtensionInstaller::CheckRequirements(
     const RequirementsCallback& callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   requirements_checker_->Check(extension_, callback);
 }
 
diff --git a/chrome/browser/extensions/extension_keybinding_registry.h b/chrome/browser/extensions/extension_keybinding_registry.h
index 1dc304f..5c4cc50 100644
--- a/chrome/browser/extensions/extension_keybinding_registry.h
+++ b/chrome/browser/extensions/extension_keybinding_registry.h
@@ -55,7 +55,7 @@
 
   virtual ~ExtensionKeybindingRegistry();
 
-  // Enables/Disables general shortcut handing in Chrome. Implemented in
+  // Enables/Disables general shortcut handling in Chrome. Implemented in
   // platform-specific ExtensionKeybindingsRegistry* files.
   static void SetShortcutHandlingSuspended(bool suspended);
 
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.cc b/chrome/browser/extensions/extension_message_bubble_controller.cc
index c5beb13..20e18ca 100644
--- a/chrome/browser/extensions/extension_message_bubble_controller.cc
+++ b/chrome/browser/extensions/extension_message_bubble_controller.cc
@@ -70,6 +70,8 @@
   return *GetOrCreateExtensionList();
 }
 
+bool ExtensionMessageBubbleController::CloseOnDeactivate() { return false; }
+
 void ExtensionMessageBubbleController::Show(ExtensionMessageBubble* bubble) {
   // Wire up all the callbacks, to get notified what actions the user took.
   base::Closure dismiss_button_callback =
@@ -95,14 +97,23 @@
   delegate_->LogAction(ACTION_EXECUTE);
   delegate_->PerformAction(*GetOrCreateExtensionList());
   AcknowledgeExtensions();
+  delegate_->OnClose();
 }
 
 void ExtensionMessageBubbleController::OnBubbleDismiss() {
-  DCHECK_EQ(ACTION_BOUNDARY, user_action_);
+  // OnBubbleDismiss() can be called twice when we receive multiple
+  // "OnWidgetDestroying" notifications (this can at least happen when we close
+  // a window with a notification open). Handle this gracefully.
+  if (user_action_ != ACTION_BOUNDARY) {
+    DCHECK(user_action_ == ACTION_DISMISS);
+    return;
+  }
+
   user_action_ = ACTION_DISMISS;
 
   delegate_->LogAction(ACTION_DISMISS);
   AcknowledgeExtensions();
+  delegate_->OnClose();
 }
 
 void ExtensionMessageBubbleController::OnLinkClicked() {
@@ -121,6 +132,7 @@
                                false));
   }
   AcknowledgeExtensions();
+  delegate_->OnClose();
 }
 
 void ExtensionMessageBubbleController::AcknowledgeExtensions() {
diff --git a/chrome/browser/extensions/extension_message_bubble_controller.h b/chrome/browser/extensions/extension_message_bubble_controller.h
index bbadca1..a6ec56e 100644
--- a/chrome/browser/extensions/extension_message_bubble_controller.h
+++ b/chrome/browser/extensions/extension_message_bubble_controller.h
@@ -38,6 +38,7 @@
         const std::string& extension_id,
         BubbleAction action) = 0;
     virtual void PerformAction(const ExtensionIdList& list) = 0;
+    virtual void OnClose() {}
 
     // Text for various UI labels shown in the bubble.
     virtual base::string16 GetTitle() const = 0;
@@ -68,6 +69,9 @@
   // Obtains a list of all extensions (by id) the controller knows about.
   const ExtensionIdList& GetExtensionIdList();
 
+  // Whether to close the bubble when it loses focus.
+  virtual bool CloseOnDeactivate();
+
   // Sets up the callbacks and shows the bubble.
   virtual void Show(ExtensionMessageBubble* bubble);
 
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index 36e2f38..047e232 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -166,49 +166,51 @@
     return result;
   }
 
-  Result CanConnectAndSendMessages(const std::string& extension_id) {
-    return CanConnectAndSendMessages(browser(), extension_id, "");
+  Result CanConnectAndSendMessagesToMainFrame(const std::string& extension_id,
+                                              const char* message = NULL) {
+    return CanConnectAndSendMessagesToFrame(
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
+        extension_id,
+        message);
   }
 
-  Result CanConnectAndSendMessages(const std::string& extension_id,
-                                   const char* frame_xpath,
-                                   const char* message) {
-    return CanConnectAndSendMessages(browser(), extension_id, frame_xpath,
-                                     message);
+  Result CanConnectAndSendMessagesToIFrame(const std::string& extension_id,
+                                           const char* message = NULL) {
+    content::RenderFrameHost* frame = content::FrameMatchingPredicate(
+        browser()->tab_strip_model()->GetActiveWebContents(),
+        base::Bind(&content::FrameIsChildOfMainFrame));
+    return CanConnectAndSendMessagesToFrame(frame, extension_id, message);
   }
 
-  Result CanConnectAndSendMessages(Browser* browser,
-                                   const std::string& extension_id) {
-    return CanConnectAndSendMessages(browser, extension_id, "");
-  }
-
-  Result CanConnectAndSendMessages(const std::string& extension_id,
-                                   const char* frame_xpath) {
-    return CanConnectAndSendMessages(browser(), extension_id, frame_xpath);
-  }
-
-  Result CanConnectAndSendMessages(Browser* browser,
-                                   const std::string& extension_id,
-                                   const char* frame_xpath,
-                                   const char* message = NULL) {
+  Result CanConnectAndSendMessagesToFrame(content::RenderFrameHost* frame,
+                                          const std::string& extension_id,
+                                          const char* message) {
     int result;
     std::string args = "'" + extension_id + "'";
     if (message)
       args += std::string(", '") + message + "'";
-    CHECK(content::ExecuteScriptInFrameAndExtractInt(
-        browser->tab_strip_model()->GetActiveWebContents(),
-        frame_xpath,
+    CHECK(content::ExecuteScriptAndExtractInt(
+        frame,
         base::StringPrintf("assertions.canConnectAndSendMessages(%s)",
                            args.c_str()),
         &result));
     return static_cast<Result>(result);
   }
 
-  testing::AssertionResult AreAnyNonWebApisDefined() {
-    return AreAnyNonWebApisDefined("");
+  testing::AssertionResult AreAnyNonWebApisDefinedForMainFrame() {
+    return AreAnyNonWebApisDefinedForFrame(
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame());
   }
 
-  testing::AssertionResult AreAnyNonWebApisDefined(const char* frame_xpath) {
+  testing::AssertionResult AreAnyNonWebApisDefinedForIFrame() {
+    content::RenderFrameHost* frame = content::FrameMatchingPredicate(
+        browser()->tab_strip_model()->GetActiveWebContents(),
+        base::Bind(&content::FrameIsChildOfMainFrame));
+    return AreAnyNonWebApisDefinedForFrame(frame);
+  }
+
+  testing::AssertionResult AreAnyNonWebApisDefinedForFrame(
+      content::RenderFrameHost* frame) {
     // All runtime API methods are non-web except for sendRequest and connect.
     const char* non_messaging_apis[] = {
         "getBackgroundPage",
@@ -243,9 +245,8 @@
     as_js_array += "]";
 
     bool any_defined;
-    CHECK(content::ExecuteScriptInFrameAndExtractBool(
-        browser()->tab_strip_model()->GetActiveWebContents(),
-        frame_xpath,
+    CHECK(content::ExecuteScriptAndExtractBool(
+        frame,
         "assertions.areAnyRuntimePropertiesDefined(" + as_js_array + ")",
         &any_defined));
     return any_defined ?
@@ -425,12 +426,14 @@
   const char kFakeId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
 
   ui_test_utils::NavigateToURL(browser(), chromium_org_url());
-  EXPECT_EQ(NAMESPACE_NOT_DEFINED, CanConnectAndSendMessages(kFakeId));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+  EXPECT_EQ(NAMESPACE_NOT_DEFINED,
+            CanConnectAndSendMessagesToMainFrame(kFakeId));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 
   ui_test_utils::NavigateToURL(browser(), google_com_url());
-  EXPECT_EQ(NAMESPACE_NOT_DEFINED, CanConnectAndSendMessages(kFakeId));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+  EXPECT_EQ(NAMESPACE_NOT_DEFINED,
+            CanConnectAndSendMessagesToMainFrame(kFakeId));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 }
 
 // Tests two extensions on the same sites: one web connectable, one not.
@@ -443,13 +446,14 @@
   const Extension* chromium_connectable = LoadChromiumConnectableExtension();
 
   ui_test_utils::NavigateToURL(browser(), chromium_org_url());
-  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id()));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+  EXPECT_EQ(OK,
+            CanConnectAndSendMessagesToMainFrame(chromium_connectable->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 
   ui_test_utils::NavigateToURL(browser(), google_com_url());
   EXPECT_EQ(NAMESPACE_NOT_DEFINED,
-            CanConnectAndSendMessages(chromium_connectable->id()));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+            CanConnectAndSendMessagesToMainFrame(chromium_connectable->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 
   // Install the non-connectable extension. Nothing can connect to it.
   const Extension* not_connectable = LoadNotConnectableExtension();
@@ -458,13 +462,13 @@
   // Namespace will be defined here because |chromium_connectable| can connect
   // to it - so this will be the "cannot establish connection" error.
   EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
-            CanConnectAndSendMessages(not_connectable->id()));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+            CanConnectAndSendMessagesToMainFrame(not_connectable->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 
   ui_test_utils::NavigateToURL(browser(), google_com_url());
   EXPECT_EQ(NAMESPACE_NOT_DEFINED,
-            CanConnectAndSendMessages(not_connectable->id()));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+            CanConnectAndSendMessagesToMainFrame(not_connectable->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 }
 
 // See http://crbug.com/297866
@@ -478,11 +482,12 @@
   ui_test_utils::NavigateToURL(browser(), chromium_org_url());
   // If the background page closes after receipt of the message, it will still
   // reply to this message...
-  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id(),
-                                          "",
-                                          close_background_message()));
+  EXPECT_EQ(OK,
+            CanConnectAndSendMessagesToMainFrame(chromium_connectable->id(),
+                                                 close_background_message()));
   // and be re-opened by receipt of a subsequent message.
-  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id()));
+  EXPECT_EQ(OK,
+            CanConnectAndSendMessagesToMainFrame(chromium_connectable->id()));
 }
 
 // Tests a web connectable extension that doesn't receive TLS channel id.
@@ -599,18 +604,20 @@
   const Extension* not_connectable = LoadNotConnectableExtension();
 
   ui_test_utils::NavigateToURL(browser(), chromium_org_url());
-  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id()));
+  EXPECT_EQ(OK,
+            CanConnectAndSendMessagesToMainFrame(chromium_connectable->id()));
   EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
-            CanConnectAndSendMessages(not_connectable->id()));
+            CanConnectAndSendMessagesToMainFrame(not_connectable->id()));
 
   DisableExtension(chromium_connectable->id());
   EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
-            CanConnectAndSendMessages(chromium_connectable->id()));
+            CanConnectAndSendMessagesToMainFrame(chromium_connectable->id()));
 
   EnableExtension(chromium_connectable->id());
-  EXPECT_EQ(OK, CanConnectAndSendMessages(chromium_connectable->id()));
+  EXPECT_EQ(OK,
+            CanConnectAndSendMessagesToMainFrame(chromium_connectable->id()));
   EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
-            CanConnectAndSendMessages(not_connectable->id()));
+            CanConnectAndSendMessagesToMainFrame(not_connectable->id()));
 }
 
 // Tests connection from incognito tabs when the user denies the connection
@@ -630,6 +637,8 @@
   Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
       profile()->GetOffTheRecordProfile(),
       chromium_org_url());
+  content::RenderFrameHost* incognito_frame = incognito_browser->
+      tab_strip_model()->GetActiveWebContents()->GetMainFrame();
 
   // No connection because incognito-enabled hasn't been set for the extension,
   // and the user denied our interactive request.
@@ -638,18 +647,18 @@
         IncognitoConnectability::ScopedAlertTracker::ALWAYS_DENY);
 
     EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
-              CanConnectAndSendMessages(incognito_browser, id));
+              CanConnectAndSendMessagesToFrame(incognito_frame, id, NULL));
     EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
 
     // Try again. User has already denied.
     EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR,
-              CanConnectAndSendMessages(incognito_browser, id));
+              CanConnectAndSendMessagesToFrame(incognito_frame, id, NULL));
     EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
   }
 
   // Allowing the extension in incognito mode will bypass the deny.
   ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(id, true);
-  EXPECT_EQ(OK, CanConnectAndSendMessages(incognito_browser, id));
+  EXPECT_EQ(OK, CanConnectAndSendMessagesToFrame(incognito_frame, id, NULL));
 }
 
 // Tests connection from incognito tabs when the user accepts the connection
@@ -665,6 +674,8 @@
   Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord(
       profile()->GetOffTheRecordProfile(),
       chromium_org_url());
+  content::RenderFrameHost* incognito_frame = incognito_browser->
+      tab_strip_model()->GetActiveWebContents()->GetMainFrame();
 
   // Connection allowed even with incognito disabled, because the user accepted
   // the interactive request.
@@ -672,17 +683,17 @@
     IncognitoConnectability::ScopedAlertTracker alert_tracker(
         IncognitoConnectability::ScopedAlertTracker::ALWAYS_ALLOW);
 
-    EXPECT_EQ(OK, CanConnectAndSendMessages(incognito_browser, id));
+    EXPECT_EQ(OK, CanConnectAndSendMessagesToFrame(incognito_frame, id, NULL));
     EXPECT_EQ(1, alert_tracker.GetAndResetAlertCount());
 
     // Try again. User has already allowed.
-    EXPECT_EQ(OK, CanConnectAndSendMessages(incognito_browser, id));
+    EXPECT_EQ(OK, CanConnectAndSendMessagesToFrame(incognito_frame, id, NULL));
     EXPECT_EQ(0, alert_tracker.GetAndResetAlertCount());
   }
 
   // Allowing the extension in incognito mode will continue to allow.
   ExtensionPrefs::Get(profile())->SetIsIncognitoEnabled(id, true);
-  EXPECT_EQ(OK, CanConnectAndSendMessages(incognito_browser, id));
+  EXPECT_EQ(OK, CanConnectAndSendMessagesToFrame(incognito_frame, id, NULL));
 }
 
 // Tests a connection from an iframe within a tab which doesn't have
@@ -694,14 +705,14 @@
   const Extension* extension = LoadChromiumConnectableExtension();
 
   ui_test_utils::NavigateToURL(browser(), google_com_url());
-  EXPECT_EQ(NAMESPACE_NOT_DEFINED, CanConnectAndSendMessages(extension->id()));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+  EXPECT_EQ(NAMESPACE_NOT_DEFINED,
+            CanConnectAndSendMessagesToMainFrame(extension->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 
   ASSERT_TRUE(AppendIframe(chromium_org_url()));
 
-  const char* frame_xpath = "//iframe[1]";
-  EXPECT_EQ(OK, CanConnectAndSendMessages(extension->id(), frame_xpath));
-  EXPECT_FALSE(AreAnyNonWebApisDefined(frame_xpath));
+  EXPECT_EQ(OK, CanConnectAndSendMessagesToIFrame(extension->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForIFrame());
 }
 
 // Tests connection from an iframe without permission within a tab that does.
@@ -713,15 +724,14 @@
   const Extension* extension = LoadChromiumConnectableExtension();
 
   ui_test_utils::NavigateToURL(browser(), chromium_org_url());
-  EXPECT_EQ(OK, CanConnectAndSendMessages(extension->id()));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+  EXPECT_EQ(OK, CanConnectAndSendMessagesToMainFrame(extension->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 
   ASSERT_TRUE(AppendIframe(google_com_url()));
 
-  const char* frame_xpath = "//iframe[1]";
   EXPECT_EQ(NAMESPACE_NOT_DEFINED,
-            CanConnectAndSendMessages(extension->id(), frame_xpath));
-  EXPECT_FALSE(AreAnyNonWebApisDefined(frame_xpath));
+            CanConnectAndSendMessagesToIFrame(extension->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForIFrame());
 }
 
 // Tests externally_connectable between a web page and an extension with a
@@ -767,7 +777,7 @@
       std::string* domain_bound_cert,
       net::ServerBoundCertService::RequestHandle* request_handle,
       scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
-    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+    DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
     net::ServerBoundCertService* server_bound_cert_service =
         request_context_getter->GetURLRequestContext()->
             server_bound_cert_service();
@@ -930,13 +940,13 @@
 
   // The presence of the hosted app shouldn't give the ability to send messages.
   ui_test_utils::NavigateToURL(browser(), chromium_org_url());
-  EXPECT_EQ(NAMESPACE_NOT_DEFINED, CanConnectAndSendMessages(""));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+  EXPECT_EQ(NAMESPACE_NOT_DEFINED, CanConnectAndSendMessagesToMainFrame(""));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 
   // Once a connectable extension is installed, it should.
   const Extension* extension = LoadChromiumConnectableExtension();
-  EXPECT_EQ(OK, CanConnectAndSendMessages(extension->id()));
-  EXPECT_FALSE(AreAnyNonWebApisDefined());
+  EXPECT_EQ(OK, CanConnectAndSendMessagesToMainFrame(extension->id()));
+  EXPECT_FALSE(AreAnyNonWebApisDefinedForMainFrame());
 }
 
 // Tests that an invalid extension ID specified in a hosted app does not crash
@@ -954,7 +964,7 @@
 
   ui_test_utils::NavigateToURL(browser(), chromium_org_url());
   EXPECT_EQ(COULD_NOT_ESTABLISH_CONNECTION_ERROR ,
-            CanConnectAndSendMessages("invalid"));
+            CanConnectAndSendMessagesToMainFrame("invalid"));
 }
 
 #endif  // !defined(OS_WIN) - http://crbug.com/350517.
diff --git a/chrome/browser/extensions/extension_prefs_unittest.cc b/chrome/browser/extensions/extension_prefs_unittest.cc
index df35ecb..8b2f41e 100644
--- a/chrome/browser/extensions/extension_prefs_unittest.cc
+++ b/chrome/browser/extensions/extension_prefs_unittest.cc
@@ -486,7 +486,8 @@
                                    Extension::ENABLED,
                                    false,
                                    ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
-                                   syncer::StringOrdinal());
+                                   syncer::StringOrdinal(),
+                                   std::string());
   }
 
   // Verifies that we get back expected idle install information previously
@@ -610,7 +611,8 @@
                                    Extension::ENABLED,
                                    false,
                                    ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
-                                   syncer::StringOrdinal());
+                                   syncer::StringOrdinal(),
+                                   "Param");
 
     // Finish idle installation
     ASSERT_TRUE(prefs()->FinishDelayedInstallInfo(id_));
@@ -618,6 +620,7 @@
 
   virtual void Verify() OVERRIDE {
     EXPECT_FALSE(prefs()->GetDelayedInstallInfo(id_));
+    EXPECT_EQ(std::string("Param"), prefs()->GetInstallParam(id_));
 
     const base::DictionaryValue* manifest;
     ASSERT_TRUE(prefs()->ReadPrefAsDictionary(id_, "manifest", &manifest));
@@ -646,11 +649,13 @@
     prefs()->OnExtensionInstalled(extension_.get(),
                                   Extension::DISABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  "Param");
   }
 
   virtual void Verify() OVERRIDE {
     EXPECT_TRUE(prefs()->IsExtensionDisabled(extension_->id()));
+    EXPECT_EQ(std::string("Param"), prefs()->GetInstallParam(extension_->id()));
   }
 
  private:
@@ -667,7 +672,8 @@
     prefs()->OnExtensionInstalled(extension_.get(),
                                   Extension::ENABLED,
                                   false,
-                                  syncer::StringOrdinal());
+                                  syncer::StringOrdinal(),
+                                  std::string());
   }
 
   virtual void Verify() OVERRIDE {
diff --git a/chrome/browser/extensions/extension_renderer_state.cc b/chrome/browser/extensions/extension_renderer_state.cc
index bb3621a..341db27 100644
--- a/chrome/browser/extensions/extension_renderer_state.cc
+++ b/chrome/browser/extensions/extension_renderer_state.cc
@@ -81,7 +81,7 @@
 };
 
 ExtensionRendererState::TabObserver::TabObserver() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   registrar_.Add(this,
                  content::NOTIFICATION_WEB_CONTENTS_RENDER_VIEW_HOST_CREATED,
                  content::NotificationService::AllBrowserContextsAndSources());
@@ -92,7 +92,7 @@
 }
 
 ExtensionRendererState::TabObserver::~TabObserver() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
 void ExtensionRendererState::TabObserver::Observe(
@@ -189,21 +189,21 @@
 
 void ExtensionRendererState::SetTabAndWindowId(
     int render_process_host_id, int routing_id, int tab_id, int window_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   RenderId render_id(render_process_host_id, routing_id);
   map_[render_id] = TabAndWindowId(tab_id, window_id);
 }
 
 void ExtensionRendererState::ClearTabAndWindowId(
     int render_process_host_id, int routing_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   RenderId render_id(render_process_host_id, routing_id);
   map_.erase(render_id);
 }
 
 bool ExtensionRendererState::GetTabAndWindowId(
     const  content::ResourceRequestInfo* info, int* tab_id, int* window_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   int render_process_id;
   if (info->GetProcessType() == content::PROCESS_TYPE_PLUGIN) {
     render_process_id = info->GetOriginPID();
@@ -222,7 +222,7 @@
 }
 
 bool ExtensionRendererState::IsWebViewRenderer(int render_process_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   for (WebViewInfoMap::iterator i = webview_info_map_.begin();
        i != webview_info_map_.end(); ++i) {
     if (i->first.first == render_process_id)
@@ -234,14 +234,14 @@
 void ExtensionRendererState::AddWebView(int guest_process_id,
                                         int guest_routing_id,
                                         const WebViewInfo& webview_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   RenderId render_id(guest_process_id, guest_routing_id);
   webview_info_map_[render_id] = webview_info;
 }
 
 void ExtensionRendererState::RemoveWebView(int guest_process_id,
                                            int guest_routing_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   RenderId render_id(guest_process_id, guest_routing_id);
   webview_info_map_.erase(render_id);
 }
@@ -249,7 +249,7 @@
 bool ExtensionRendererState::GetWebViewInfo(int guest_process_id,
                                             int guest_routing_id,
                                             WebViewInfo* webview_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   RenderId render_id(guest_process_id, guest_routing_id);
   WebViewInfoMap::iterator iter = webview_info_map_.find(render_id);
   if (iter != webview_info_map_.end()) {
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc
index 962a050..f4db209 100644
--- a/chrome/browser/extensions/extension_service.cc
+++ b/chrome/browser/extensions/extension_service.cc
@@ -185,37 +185,6 @@
   DISALLOW_COPY_AND_ASSIGN(SharedModuleProvider);
 };
 
-enum VerifyAllSuccess {
-  VERIFY_ALL_BOOTSTRAP_SUCCESS = 0,
-  VERIFY_ALL_BOOTSTRAP_FAILURE,
-  VERIFY_ALL_NON_BOOTSTRAP_SUCCESS,
-  VERIFY_ALL_NON_BOOTSTRAP_FAILURE,
-
-  // Used in histograms. Do not remove/reorder any entries above, and the below
-  // MAX entry should always come last.
-
-  VERIFY_ALL_SUCCESS_MAX
-};
-
-void LogVerifyAllSuccessHistogram(bool bootstrap, bool success) {
-  VerifyAllSuccess result;
-  if (bootstrap && success)
-    result = VERIFY_ALL_BOOTSTRAP_SUCCESS;
-  else if (bootstrap && !success)
-    result = VERIFY_ALL_BOOTSTRAP_FAILURE;
-  else if (!bootstrap && success)
-    result = VERIFY_ALL_NON_BOOTSTRAP_SUCCESS;
-  else
-    result = VERIFY_ALL_NON_BOOTSTRAP_FAILURE;
-
-  UMA_HISTOGRAM_ENUMERATION("ExtensionService.VerifyAllSuccess",
-                            result, VERIFY_ALL_SUCCESS_MAX);
-}
-
-void LogAddVerifiedSuccess(bool success) {
-  UMA_HISTOGRAM_BOOLEAN("ExtensionService.AddVerified", success);
-}
-
 }  // namespace
 
 // ExtensionService.
@@ -265,6 +234,7 @@
 
 bool ExtensionService::OnExternalExtensionUpdateUrlFound(
     const std::string& id,
+    const std::string& install_parameter,
     const GURL& update_url,
     Manifest::Location location,
     int creation_flags,
@@ -292,7 +262,12 @@
   // source.  In this case, signal that this extension will not be
   // installed by returning false.
   if (!pending_extension_manager()->AddFromExternalUpdateUrl(
-          id, update_url, location, creation_flags, mark_acknowledged)) {
+          id,
+          install_parameter,
+          update_url,
+          location,
+          creation_flags,
+          mark_acknowledged)) {
     return false;
   }
 
@@ -356,7 +331,7 @@
       blacklist_(blacklist),
       extension_sync_service_(NULL),
       registry_(extensions::ExtensionRegistry::Get(profile)),
-      pending_extension_manager_(*this),
+      pending_extension_manager_(*this, profile),
       install_directory_(install_directory),
       extensions_enabled_(extensions_enabled),
       show_extensions_prompts_(true),
@@ -554,7 +529,6 @@
     // rather than running immediately at startup.
     CheckForExternalUpdates();
 
-    MaybeBootstrapVerifier();
     base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
         base::Bind(&ExtensionService::GarbageCollectExtensions, AsWeakPtr()),
@@ -589,83 +563,6 @@
   }
 }
 
-void ExtensionService::MaybeBootstrapVerifier() {
-  InstallVerifier* verifier = system_->install_verifier();
-  bool do_bootstrap = false;
-
-  if (verifier->NeedsBootstrap()) {
-    do_bootstrap = true;
-  } else {
-    scoped_ptr<extensions::ExtensionSet> extensions =
-        registry_->GenerateInstalledExtensionsSet();
-    for (extensions::ExtensionSet::const_iterator i = extensions->begin();
-         i != extensions->end();
-         ++i) {
-      const Extension& extension = **i;
-
-      if (verifier->NeedsVerification(extension) &&
-          !verifier->IsKnownId(extension.id())) {
-        do_bootstrap = true;
-        break;
-      }
-    }
-  }
-  if (do_bootstrap)
-    VerifyAllExtensions(true);  // bootstrap=true.
-}
-
-void ExtensionService::VerifyAllExtensions(bool bootstrap) {
-  ExtensionIdSet to_add;
-  scoped_ptr<ExtensionSet> all_extensions =
-      registry_->GenerateInstalledExtensionsSet();
-
-  for (ExtensionSet::const_iterator i = all_extensions->begin();
-       i != all_extensions->end(); ++i) {
-    const Extension& extension = **i;
-
-    if (InstallVerifier::NeedsVerification(extension))
-      to_add.insert(extension.id());
-  }
-  system_->install_verifier()->AddMany(
-      to_add,
-      base::Bind(&ExtensionService::FinishVerifyAllExtensions,
-                 AsWeakPtr(),
-                 bootstrap));
-}
-
-void ExtensionService::FinishVerifyAllExtensions(bool bootstrap, bool success) {
-  LogVerifyAllSuccessHistogram(bootstrap, success);
-  if (success) {
-    // Check to see if any currently unverified extensions became verified.
-    InstallVerifier* verifier = system_->install_verifier();
-    const ExtensionSet& disabled_extensions = registry_->disabled_extensions();
-    for (ExtensionSet::const_iterator i = disabled_extensions.begin();
-         i != disabled_extensions.end(); ++i) {
-      const Extension& extension = **i;
-      int disable_reasons = extension_prefs_->GetDisableReasons(extension.id());
-      if (disable_reasons & Extension::DISABLE_NOT_VERIFIED &&
-          !verifier->MustRemainDisabled(&extension, NULL, NULL)) {
-        extension_prefs_->RemoveDisableReason(extension.id(),
-                                              Extension::DISABLE_NOT_VERIFIED);
-        // Notify interested observers (eg the extensions settings page) by
-        // sending an UNLOADED notification.
-        //
-        // TODO(asargent) - this is a slight hack because it's already
-        // disabled; the right solution might be to add a separate listener
-        // interface for DisableReason's changing. http://crbug.com/328916
-        UnloadedExtensionInfo details(&extension,
-                                      UnloadedExtensionInfo::REASON_DISABLE);
-        content::NotificationService::current()->Notify(
-            chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
-            content::Source<Profile>(profile_),
-            content::Details<UnloadedExtensionInfo>(&details));
-      }
-    }
-    // Might disable some extensions.
-    CheckManagementPolicy();
-  }
-}
-
 bool ExtensionService::UpdateExtension(const std::string& id,
                                        const base::FilePath& extension_path,
                                        bool file_ownership_passed,
@@ -896,7 +793,10 @@
       NOTREACHED();
   }
 
-  extensions::DataDeleter::StartDeleting(profile_, extension.get());
+  // Do not remove the data of ephemeral apps. They will be garbage collected by
+  // EphemeralAppService.
+  if (!extension->is_ephemeral())
+    extensions::DataDeleter::StartDeleting(profile_, extension.get());
 
   UntrackTerminatedExtension(extension_id);
 
@@ -942,11 +842,6 @@
          !extension_prefs_->IsExternalExtensionUninstalled(extension_id);
 }
 
-bool ExtensionService::IsExternalExtensionUninstalled(
-    const std::string& extension_id) const {
-  return extension_prefs_->IsExternalExtensionUninstalled(extension_id);
-}
-
 void ExtensionService::EnableExtension(const std::string& extension_id) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -1151,19 +1046,23 @@
   //
   // NOTE: It is important that this happen after notifying the renderers about
   // the new extensions so that if we navigate to an extension URL in
-  // NOTIFICATION_EXTENSION_LOADED, the renderer is guaranteed to know about it.
+  // ExtensionRegistryObserver::OnLoaded or NOTIFICATION_EXTENSION_LOADED, the
+  // renderer is guaranteed to know about it.
+  registry_->TriggerOnLoaded(extension);
+
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_EXTENSION_LOADED,
       content::Source<Profile>(profile_),
       content::Details<const Extension>(extension));
 
-  // Tell a random-ass collection of other subsystems about the new extension.
-  // TODO(aa): What should we do with all this goop? Can it move into the
-  // relevant objects via EXTENSION_LOADED?
-
+  // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a
+  // BrowserContextKeyedService and use ExtensionRegistryObserver.
   profile_->GetExtensionSpecialStoragePolicy()->
       GrantRightsForExtension(extension);
 
+  // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't
+  // work properly multi-profile. Besides which, it should be using
+  // ExtensionRegistryObserver. See http://crbug.com/355029.
   UpdateActiveExtensionsInCrashReporter();
 
   // If the extension has permission to load chrome://favicon/ resources we need
@@ -1215,6 +1114,9 @@
   }
 
   system_->UnregisterExtensionWithRequestContexts(extension->id(), reason);
+
+  // TODO(kalman): Convert ExtensionSpecialStoragePolicy to a
+  // BrowserContextKeyedService and use ExtensionRegistryObserver.
   profile_->GetExtensionSpecialStoragePolicy()->
       RevokeRightsForExtension(extension);
 
@@ -1233,6 +1135,9 @@
   }
 #endif
 
+  // TODO(kalman): This is broken. The crash reporter is process-wide so doesn't
+  // work properly multi-profile. Besides which, it should be using
+  // ExtensionRegistryObserver::OnExtensionLoaded. See http://crbug.com/355029.
   UpdateActiveExtensionsInCrashReporter();
 }
 
@@ -1823,7 +1728,8 @@
     AddNewOrUpdatedExtension(extension,
                              Extension::ENABLED_COMPONENT,
                              extensions::NOT_BLACKLISTED,
-                             syncer::StringOrdinal());
+                             syncer::StringOrdinal(),
+                             std::string());
     return;
   }
 
@@ -1972,6 +1878,9 @@
       extension_ids.insert(extension->id());
   }
 
+  // TODO(kalman): This is broken. ExtensionService is per-profile.
+  // crash_keys::SetActiveExtensions is per-process. See
+  // http://crbug.com/355029.
   crash_keys::SetActiveExtensions(extension_ids);
 }
 
@@ -2083,6 +1992,7 @@
 
   const std::string& id = extension->id();
   bool initial_enable = ShouldEnableOnInstall(extension);
+  std::string install_parameter;
   const extensions::PendingExtensionInfo* pending_extension_info = NULL;
   if ((pending_extension_info = pending_extension_manager()->GetById(id))) {
     if (!pending_extension_info->ShouldAllowInstall(extension)) {
@@ -2105,12 +2015,13 @@
       return;
     }
 
+    install_parameter = pending_extension_info->install_parameter();
     pending_extension_manager()->Remove(id);
   } else {
     // We explicitly want to re-enable an uninstalled external
     // extension; if we're here, that means the user is manually
     // installing the extension.
-    if (IsExternalExtensionUninstalled(id)) {
+    if (extension_prefs_->IsExternalExtensionUninstalled(id)) {
       initial_enable = true;
     }
   }
@@ -2170,7 +2081,8 @@
         initial_state,
         blacklisted_for_malware,
         extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IDLE,
-        page_ordinal);
+        page_ordinal,
+        install_parameter);
 
     // Transfer ownership of |extension|.
     delayed_installs_.Insert(extension);
@@ -2188,7 +2100,8 @@
         initial_state,
         blacklisted_for_malware,
         extensions::ExtensionPrefs::DELAY_REASON_GC,
-        page_ordinal);
+        page_ordinal,
+        install_parameter);
     delayed_installs_.Insert(extension);
   } else if (status != IMPORT_STATUS_OK) {
     if (status == IMPORT_STATUS_UNSATISFIED) {
@@ -2197,14 +2110,16 @@
           initial_state,
           blacklisted_for_malware,
           extensions::ExtensionPrefs::DELAY_REASON_WAIT_FOR_IMPORTS,
-          page_ordinal);
+          page_ordinal,
+          install_parameter);
       delayed_installs_.Insert(extension);
     }
   } else {
     AddNewOrUpdatedExtension(extension,
                              initial_state,
                              blacklist_state,
-                             page_ordinal);
+                             page_ordinal,
+                             install_parameter);
   }
 }
 
@@ -2212,19 +2127,19 @@
     const Extension* extension,
     Extension::State initial_state,
     extensions::BlacklistState blacklist_state,
-    const syncer::StringOrdinal& page_ordinal) {
+    const syncer::StringOrdinal& page_ordinal,
+    const std::string& install_parameter) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   const bool blacklisted_for_malware =
       blacklist_state == extensions::BLACKLISTED_MALWARE;
   extension_prefs_->OnExtensionInstalled(extension,
                                          initial_state,
                                          blacklisted_for_malware,
-                                         page_ordinal);
+                                         page_ordinal,
+                                         install_parameter);
   delayed_installs_.Remove(extension->id());
-  if (InstallVerifier::NeedsVerification(*extension)) {
-    system_->install_verifier()->Add(extension->id(),
-                                     base::Bind(LogAddVerifiedSuccess));
-  }
+  if (InstallVerifier::NeedsVerification(*extension))
+    system_->install_verifier()->VerifyExtension(extension->id());
   FinishInstallation(extension);
 }
 
@@ -2352,11 +2267,6 @@
   }
 }
 
-const Extension* ExtensionService::GetTerminatedExtension(
-    const std::string& id) const {
-  return registry_->GetExtensionById(id, ExtensionRegistry::TERMINATED);
-}
-
 const Extension* ExtensionService::GetInstalledExtension(
     const std::string& id) const {
   return registry_->GetExtensionById(id, ExtensionRegistry::EVERYTHING);
@@ -2453,10 +2363,22 @@
       content::Details<const std::string>(&error));
 
   std::string path_str = base::UTF16ToUTF8(extension_path.LossyDisplayName());
-  base::string16 message = base::UTF8ToUTF16(base::StringPrintf(
-      "Could not load extension from '%s'. %s",
-      path_str.c_str(), error.c_str()));
-  ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy);
+  bool retry = false;
+  std::string retry_prompt;
+  if (be_noisy)
+    retry_prompt = "\n\nWould you like to retry?";
+
+  base::string16 message = base::UTF8ToUTF16(
+      base::StringPrintf("Could not load extension from '%s'. %s%s",
+                         path_str.c_str(),
+                         error.c_str(),
+                         retry_prompt.c_str()));
+  ExtensionErrorReporter::GetInstance()->ReportError(message, be_noisy, &retry);
+  std::pair<bool, const base::FilePath&> details(retry, extension_path);
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_EXTENSION_LOAD_RETRY,
+      content::Source<Profile>(profile_),
+      content::Details<std::pair<bool, const base::FilePath&> >(&details));
 }
 
 void ExtensionService::DidCreateRenderViewForBackgroundPage(
@@ -2560,22 +2482,6 @@
   CheckManagementPolicy();
 }
 
-bool ExtensionService::HasApps() const {
-  return !GetAppIds().empty();
-}
-
-ExtensionIdSet ExtensionService::GetAppIds() const {
-  ExtensionIdSet result;
-  const ExtensionSet& extensions = registry_->enabled_extensions();
-  for (ExtensionSet::const_iterator it = extensions.begin();
-       it != extensions.end(); ++it) {
-    if ((*it)->is_app() && (*it)->location() != Manifest::COMPONENT)
-      result.insert((*it)->id());
-  }
-
-  return result;
-}
-
 bool ExtensionService::IsBeingReloaded(
     const std::string& extension_id) const {
   return ContainsKey(extensions_being_reloaded_, extension_id);
@@ -2657,6 +2563,20 @@
     }
   }
 
+  // The data of ephemeral apps can outlive their cache lifetime. Ensure
+  // they are not garbage collected.
+  scoped_ptr<extensions::ExtensionPrefs::ExtensionsInfo> evicted_apps_info(
+      extension_prefs_->GetEvictedEphemeralAppsInfo());
+  for (size_t i = 0; i < evicted_apps_info->size(); ++i) {
+    extensions::ExtensionInfo* info = evicted_apps_info->at(i).get();
+    if (extensions::util::HasIsolatedStorage(*info)) {
+      active_paths->insert(BrowserContext::GetStoragePartitionForSite(
+          profile_,
+          extensions::util::GetSiteForExtensionId(
+              info->extension_id, profile()))->GetPath());
+    }
+  }
+
   DCHECK(!installs_delayed_for_gc());
   set_installs_delayed_for_gc(true);
   BrowserContext::GarbageCollectStoragePartitions(
@@ -2692,7 +2612,7 @@
 
 void ExtensionService::ManageBlacklist(
     const extensions::Blacklist::BlacklistStateMap& state_map) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::set<std::string> blocked;
   ExtensionIdSet greylist;
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index 2668332..266f47c 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -37,7 +37,6 @@
 #include "extensions/common/one_shot_event.h"
 
 class ExtensionErrorUI;
-class ExtensionToolbarModel;
 class GURL;
 class Profile;
 
@@ -54,6 +53,7 @@
 class ExtensionActionStorageManager;
 class ExtensionRegistry;
 class ExtensionSystem;
+class ExtensionToolbarModel;
 class ExtensionUpdater;
 class PendingExtensionManager;
 class RendererStartupHelper;
@@ -98,8 +98,6 @@
   virtual void FinishDelayedInstallation(const std::string& extension_id) = 0;
 
   virtual bool IsExtensionEnabled(const std::string& extension_id) const = 0;
-  virtual bool IsExternalExtensionUninstalled(
-      const std::string& extension_id) const = 0;
 
   virtual void CheckManagementPolicy() = 0;
 
@@ -182,19 +180,6 @@
   // Initialize and start all installed extensions.
   void Init();
 
-  // See if we need to bootstrap the install verifier.
-  void MaybeBootstrapVerifier();
-
-  // Attempts to verify all extensions using the InstallVerifier. The
-  // |bootstrap| parameter indicates whether we're doing this because the
-  // InstallVerifier needed to be bootstrapped (otherwise it's for another
-  // reason, e.g. extension install/uninstall).
-  void VerifyAllExtensions(bool bootstrap);
-
-  // Once the verifier work is finished, we may want to re-check management
-  // policy if |success| indicates the verifier got a new signature back.
-  void FinishVerifyAllExtensions(bool bootstrap, bool success);
-
   // Called when the associated Profile is going to be destroyed.
   void Shutdown();
 
@@ -203,12 +188,6 @@
   virtual const extensions::Extension* GetExtensionById(
       const std::string& id, bool include_disabled) const OVERRIDE;
 
-  // Looks up a terminated (crashed) extension by ID.
-  // DEPRECATED: Replace with:
-  // ExtensionRegistry::GetExtensionById(id, ExtensionRegistry::TERMINATED).
-  const extensions::Extension*
-      GetTerminatedExtension(const std::string& id) const;
-
   // Looks up an extension by ID, regardless of whether it's enabled,
   // disabled, blacklisted, or terminated.
   // DEPRECATED: Replace with:
@@ -248,8 +227,6 @@
 
   virtual bool IsExtensionEnabled(
       const std::string& extension_id) const OVERRIDE;
-  virtual bool IsExternalExtensionUninstalled(
-      const std::string& extension_id) const OVERRIDE;
 
   // Enables the extension.  If the extension is already enabled, does
   // nothing.
@@ -452,6 +429,7 @@
 
   virtual bool OnExternalExtensionUpdateUrlFound(
       const std::string& id,
+      const std::string& install_parameter,
       const GURL& update_url,
       extensions::Manifest::Location location,
       int creation_flags,
@@ -508,12 +486,6 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  // Whether there are any apps installed. Component apps are not included.
-  bool HasApps() const;
-
-  // Gets the set of loaded app ids. Component apps are not included.
-  extensions::ExtensionIdSet GetAppIds() const;
-
   // Record a histogram using the PermissionMessage enum values for each
   // permission in |e|.
   // NOTE: If this is ever called with high frequency, the implementation may
@@ -589,11 +561,11 @@
   // the extension is installed, e.g., to update event handlers on background
   // pages; and perform other extension install tasks before calling
   // AddExtension.
-  void AddNewOrUpdatedExtension(
-      const extensions::Extension* extension,
-      extensions::Extension::State initial_state,
-      extensions::BlacklistState blacklist_state,
-      const syncer::StringOrdinal& page_ordinal);
+  void AddNewOrUpdatedExtension(const extensions::Extension* extension,
+                                extensions::Extension::State initial_state,
+                                extensions::BlacklistState blacklist_state,
+                                const syncer::StringOrdinal& page_ordinal,
+                                const std::string& install_parameter);
 
   // Handles sending notification that |extension| was loaded.
   void NotifyExtensionLoaded(const extensions::Extension* extension);
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index eaea30c..3834a7c 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -407,7 +407,9 @@
   }
 
   virtual bool OnExternalExtensionUpdateUrlFound(
-      const std::string& id, const GURL& update_url,
+      const std::string& id,
+      const std::string& install_parameter,
+      const GURL& update_url,
       Manifest::Location location,
       int creation_flags,
       bool mark_acknowledged) OVERRIDE {
@@ -430,6 +432,10 @@
       EXPECT_FALSE(v1.get());
       EXPECT_EQ(Manifest::EXTERNAL_PREF_DOWNLOAD, location1);
 
+      std::string parsed_install_parameter;
+      pref->GetString("install_parameter", &parsed_install_parameter);
+      EXPECT_EQ(parsed_install_parameter, install_parameter);
+
       // Remove it so we won't count it again.
       prefs_->Remove(id, NULL);
     }
@@ -1823,6 +1829,7 @@
   // Try adding the same extension from an external update URL.
   ASSERT_FALSE(service_->pending_extension_manager()->AddFromExternalUpdateUrl(
       good_crx,
+      std::string(),
       GURL("http:://fake.update/url"),
       Manifest::EXTERNAL_PREF_DOWNLOAD,
       Extension::NO_FLAGS,
@@ -3197,7 +3204,11 @@
 TEST_F(ExtensionServiceTest, MAYBE_UpdatePendingExternalCrx) {
   InitializeEmptyExtensionService();
   EXPECT_TRUE(service_->pending_extension_manager()->AddFromExternalUpdateUrl(
-      theme_crx, GURL(), Manifest::EXTERNAL_PREF_DOWNLOAD, Extension::NO_FLAGS,
+      theme_crx,
+      std::string(),
+      GURL(),
+      Manifest::EXTERNAL_PREF_DOWNLOAD,
+      Extension::NO_FLAGS,
       false));
 
   EXPECT_TRUE(service_->pending_extension_manager()->IsIdPending(theme_crx));
@@ -3236,8 +3247,12 @@
 
   // Add a crx to be updated, with the same ID, from a non-sync source.
   EXPECT_TRUE(service_->pending_extension_manager()->AddFromExternalUpdateUrl(
-      kGoodId, GURL(kGoodUpdateURL), Manifest::EXTERNAL_PREF_DOWNLOAD,
-      Extension::NO_FLAGS, false));
+      kGoodId,
+      std::string(),
+      GURL(kGoodUpdateURL),
+      Manifest::EXTERNAL_PREF_DOWNLOAD,
+      Extension::NO_FLAGS,
+      false));
 
   // Check that there is a pending crx, with is_from_sync set to false.
   ASSERT_TRUE((pending_extension_info = service_->pending_extension_manager()->
@@ -3324,10 +3339,16 @@
 
   // Use AddExtensionImpl() as AddFrom*() would balk.
   service_->pending_extension_manager()->AddExtensionImpl(
-      good->id(), extensions::ManifestURL::GetUpdateURL(good),
-      Version(), &IsExtension, kGoodIsFromSync,
-      kGoodInstallSilently, Manifest::INTERNAL,
-      Extension::NO_FLAGS, false);
+      good->id(),
+      std::string(),
+      extensions::ManifestURL::GetUpdateURL(good),
+      Version(),
+      &IsExtension,
+      kGoodIsFromSync,
+      kGoodInstallSilently,
+      Manifest::INTERNAL,
+      Extension::NO_FLAGS,
+      false);
   UpdateExtension(good->id(), path, ENABLED);
 
   EXPECT_FALSE(service_->pending_extension_manager()->IsIdPending(kGoodId));
@@ -4115,12 +4136,14 @@
 
   InstallCRX(data_dir_.AppendASCII("good.crx"), INSTALL_NEW);
   TerminateExtension(good_crx);
-  EXPECT_TRUE(service_->GetTerminatedExtension(good_crx));
+  EXPECT_TRUE(registry_->GetExtensionById(
+      good_crx, extensions::ExtensionRegistry::TERMINATED));
 
   // Disable it.
   service_->DisableExtension(good_crx, Extension::DISABLE_USER_ACTION);
 
-  EXPECT_FALSE(service_->GetTerminatedExtension(good_crx));
+  EXPECT_FALSE(registry_->GetExtensionById(
+      good_crx, extensions::ExtensionRegistry::TERMINATED));
   EXPECT_TRUE(service_->GetExtensionById(good_crx, true));
 
   EXPECT_EQ(0u, registry_->enabled_extensions().size());
@@ -5028,7 +5051,8 @@
       "    \"external_version\": \"2.0\""
       "  },"
       "  \"cccccccccccccccccccccccccccccccc\": {"
-      "    \"external_update_url\": \"http:\\\\foo.com/update\""
+      "    \"external_update_url\": \"http:\\\\foo.com/update\","
+      "    \"install_parameter\": \"id\""
       "  }"
       "}";
   EXPECT_EQ(3, visitor.Visit(json_data));
@@ -5734,7 +5758,8 @@
       scoped_ptr<syncer::SyncErrorFactory>(new syncer::SyncErrorFactoryMock()));
 
   UninstallExtension(good_crx, false);
-  EXPECT_TRUE(service_->IsExternalExtensionUninstalled(good_crx));
+  EXPECT_TRUE(ExtensionPrefs::Get(profile_.get())
+                  ->IsExternalExtensionUninstalled(good_crx));
 
   sync_pb::EntitySpecifics specifics;
   sync_pb::AppSpecifics* app_specifics = specifics.mutable_app();
@@ -5753,7 +5778,8 @@
   list[0] = sync_change;
 
   extension_sync_service_->ProcessSyncChanges(FROM_HERE, list);
-  EXPECT_TRUE(service_->IsExternalExtensionUninstalled(good_crx));
+  EXPECT_TRUE(ExtensionPrefs::Get(profile_.get())
+                  ->IsExternalExtensionUninstalled(good_crx));
 }
 
 TEST_F(ExtensionServiceTest, GetSyncAppDataUserSettings) {
@@ -6217,24 +6243,32 @@
   EXPECT_FALSE(pending->IsIdPending(kGoodId));
 
   // Skip install when the location is the same.
-  EXPECT_FALSE(
-      service_->OnExternalExtensionUpdateUrlFound(
-          kGoodId, GURL(kGoodUpdateURL), Manifest::INTERNAL,
-          Extension::NO_FLAGS, false));
+  EXPECT_FALSE(service_->OnExternalExtensionUpdateUrlFound(kGoodId,
+                                                           std::string(),
+                                                           GURL(kGoodUpdateURL),
+                                                           Manifest::INTERNAL,
+                                                           Extension::NO_FLAGS,
+                                                           false));
   EXPECT_FALSE(pending->IsIdPending(kGoodId));
 
   // Install when the location has higher priority.
-  EXPECT_TRUE(
-      service_->OnExternalExtensionUpdateUrlFound(
-          kGoodId, GURL(kGoodUpdateURL), Manifest::EXTERNAL_POLICY_DOWNLOAD,
-          Extension::NO_FLAGS, false));
+  EXPECT_TRUE(service_->OnExternalExtensionUpdateUrlFound(
+      kGoodId,
+      std::string(),
+      GURL(kGoodUpdateURL),
+      Manifest::EXTERNAL_POLICY_DOWNLOAD,
+      Extension::NO_FLAGS,
+      false));
   EXPECT_TRUE(pending->IsIdPending(kGoodId));
 
   // Try the low priority again.  Should be rejected.
-  EXPECT_FALSE(
-      service_->OnExternalExtensionUpdateUrlFound(
-          kGoodId, GURL(kGoodUpdateURL), Manifest::EXTERNAL_PREF_DOWNLOAD,
-          Extension::NO_FLAGS, false));
+  EXPECT_FALSE(service_->OnExternalExtensionUpdateUrlFound(
+      kGoodId,
+      std::string(),
+      GURL(kGoodUpdateURL),
+      Manifest::EXTERNAL_PREF_DOWNLOAD,
+      Extension::NO_FLAGS,
+      false));
   // The existing record should still be present in the pending extension
   // manager.
   EXPECT_TRUE(pending->IsIdPending(kGoodId));
@@ -6243,9 +6277,12 @@
 
   // Skip install when the location has the same priority as the installed
   // location.
-  EXPECT_FALSE(service_->OnExternalExtensionUpdateUrlFound(
-      kGoodId, GURL(kGoodUpdateURL), Manifest::INTERNAL,
-      Extension::NO_FLAGS, false));
+  EXPECT_FALSE(service_->OnExternalExtensionUpdateUrlFound(kGoodId,
+                                                           std::string(),
+                                                           GURL(kGoodUpdateURL),
+                                                           Manifest::INTERNAL,
+                                                           Extension::NO_FLAGS,
+                                                           false));
 
   EXPECT_FALSE(pending->IsIdPending(kGoodId));
 }
@@ -6483,10 +6520,13 @@
 
   // Adding the latest version from the webstore overrides a specific version.
   GURL kUpdateUrl("http://example.com/update");
-  EXPECT_TRUE(
-      service_->OnExternalExtensionUpdateUrlFound(
-          kGoodId, kUpdateUrl, Manifest::EXTERNAL_POLICY_DOWNLOAD,
-          Extension::NO_FLAGS, false));
+  EXPECT_TRUE(service_->OnExternalExtensionUpdateUrlFound(
+      kGoodId,
+      std::string(),
+      kUpdateUrl,
+      Manifest::EXTERNAL_POLICY_DOWNLOAD,
+      Extension::NO_FLAGS,
+      false));
   EXPECT_TRUE((info = pending->GetById(kGoodId)));
   EXPECT_FALSE(info->version().IsValid());
 }
@@ -6530,8 +6570,12 @@
   // Fake an external source adding a URL to fetch an extension from.
   bool AddPendingExternalPrefUrl() {
     return service_->pending_extension_manager()->AddFromExternalUpdateUrl(
-        crx_id_, GURL(), Manifest::EXTERNAL_PREF_DOWNLOAD,
-        Extension::NO_FLAGS, false);
+        crx_id_,
+        std::string(),
+        GURL(),
+        Manifest::EXTERNAL_PREF_DOWNLOAD,
+        Extension::NO_FLAGS,
+        false);
   }
 
   // Fake an external file from external_extensions.json.
@@ -6553,8 +6597,12 @@
   bool AddPendingPolicyInstall() {
     // Get path to the CRX with id |kGoodId|.
     return service_->OnExternalExtensionUpdateUrlFound(
-        crx_id_, GURL(), Manifest::EXTERNAL_POLICY_DOWNLOAD,
-        Extension::NO_FLAGS, false);
+        crx_id_,
+        std::string(),
+        GURL(),
+        Manifest::EXTERNAL_POLICY_DOWNLOAD,
+        Extension::NO_FLAGS,
+        false);
   }
 
   // Get the install source of a pending extension.
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc
index e5de8db..472c5d5 100644
--- a/chrome/browser/extensions/extension_sync_service.cc
+++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -11,7 +11,6 @@
 #include "base/threading/thread_restrictions.h"
 #include "chrome/browser/extensions/app_sync_data.h"
 #include "chrome/browser/extensions/extension_error_ui.h"
-#include "chrome/browser/extensions/extension_gcm_app_handler.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_sync_data.h"
 #include "chrome/browser/extensions/extension_sync_service_factory.h"
@@ -34,7 +33,6 @@
 using extensions::ExtensionPrefs;
 using extensions::ExtensionRegistry;
 using extensions::FeatureSwitch;
-using extensions::ExtensionGCMAppHandler;
 
 ExtensionSyncService::ExtensionSyncService(Profile* profile,
                                            ExtensionPrefs* extension_prefs,
@@ -51,8 +49,7 @@
       pending_extension_enables_(make_scoped_ptr(new sync_driver::SyncPrefs(
                                      extension_prefs_->pref_service())),
                                  &extension_sync_bundle_,
-                                 syncer::EXTENSIONS),
-      extesnion_gcm_app_handler_(new ExtensionGCMAppHandler(profile)) {
+                                 syncer::EXTENSIONS) {
   SetSyncStartFlare(sync_start_util::GetFlareForSyncableService(
       profile_->GetPath()));
 
@@ -388,7 +385,8 @@
 
   // Extension from sync was uninstalled by the user as external extensions.
   // Honor user choice and skip installation/enabling.
-  if (extension_service_->IsExternalExtensionUninstalled(id)) {
+  if (extensions::ExtensionPrefs::Get(profile_)
+          ->IsExternalExtensionUninstalled(id)) {
     LOG(WARNING) << "Extension with id " << id
                  << " from sync was uninstalled as external extension";
     return true;
diff --git a/chrome/browser/extensions/extension_sync_service.h b/chrome/browser/extensions/extension_sync_service.h
index e8a8fe5..e5e3af7 100644
--- a/chrome/browser/extensions/extension_sync_service.h
+++ b/chrome/browser/extensions/extension_sync_service.h
@@ -29,7 +29,6 @@
 
 namespace extensions {
 class AppSyncData;
-class ExtensionGCMAppHandler;
 class ExtensionPrefs;
 class ExtensionSyncData;
 }  // namespace extensions
@@ -152,9 +151,6 @@
   // asynchronously via MergeDataAndStartSyncing as soon as possible.
   syncer::SyncableService::StartSyncFlare flare_;
 
-  // Used to provide the extension specific logic for GCMProfileService.
-  scoped_ptr<extensions::ExtensionGCMAppHandler> extesnion_gcm_app_handler_;
-
   DISALLOW_COPY_AND_ASSIGN(ExtensionSyncService);
 };
 
diff --git a/chrome/browser/extensions/extension_system_impl.cc b/chrome/browser/extensions/extension_system_impl.cc
index 73c17a2..169b779 100644
--- a/chrome/browser/extensions/extension_system_impl.cc
+++ b/chrome/browser/extensions/extension_system_impl.cc
@@ -168,8 +168,8 @@
   // These services must be registered before the ExtensionService tries to
   // load any extensions.
   {
-    install_verifier_.reset(new InstallVerifier(ExtensionPrefs::Get(profile_),
-                                                profile_->GetRequestContext()));
+    install_verifier_.reset(
+        new InstallVerifier(ExtensionPrefs::Get(profile_), profile_));
     install_verifier_->Init();
 
     management_policy_.reset(new ManagementPolicy);
diff --git a/chrome/browser/extensions/extension_test_message_listener.cc b/chrome/browser/extensions/extension_test_message_listener.cc
index 9314723..e1aea6c 100644
--- a/chrome/browser/extensions/extension_test_message_listener.cc
+++ b/chrome/browser/extensions/extension_test_message_listener.cc
@@ -5,11 +5,13 @@
 #include "chrome/browser/extensions/extension_test_message_listener.h"
 
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/api/test/test_api.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
 
 ExtensionTestMessageListener::ExtensionTestMessageListener(
     const std::string& expected_message,
@@ -17,12 +19,26 @@
     : expected_message_(expected_message),
       satisfied_(false),
       waiting_(false),
+      wait_for_any_message_(false),
       will_reply_(will_reply),
+      replied_(false),
       failed_(false) {
   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE,
                  content::NotificationService::AllSources());
 }
 
+ExtensionTestMessageListener::ExtensionTestMessageListener(bool will_reply)
+    : satisfied_(false),
+      waiting_(false),
+      wait_for_any_message_(true),
+      will_reply_(will_reply),
+      replied_(false),
+      failed_(false) {
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_EXTENSION_TEST_MESSAGE,
+                 content::NotificationService::AllSources());
+}
+
 ExtensionTestMessageListener::~ExtensionTestMessageListener() {}
 
 bool ExtensionTestMessageListener::WaitUntilSatisfied()  {
@@ -34,34 +50,53 @@
 }
 
 void ExtensionTestMessageListener::Reply(const std::string& message) {
-  DCHECK(satisfied_);
-  DCHECK(will_reply_);
+  CHECK(satisfied_);
+  CHECK(!replied_);
+
+  replied_ = true;
   function_->Reply(message);
   function_ = NULL;
-  will_reply_ = false;
 }
 
 void ExtensionTestMessageListener::Reply(int message) {
   Reply(base::IntToString(message));
 }
 
+void ExtensionTestMessageListener::Reset() {
+  satisfied_ = false;
+  failed_ = false;
+  message_.clear();
+  replied_ = false;
+}
+
 void ExtensionTestMessageListener::Observe(
     int type,
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
-  const std::string& content = *content::Details<std::string>(details).ptr();
-  if (!satisfied_ && (content == expected_message_ ||
-      (!failure_message_.empty() && (content == failure_message_)))) {
-    if (!failed_)
-      failed_ = (content == failure_message_);
-    function_ = content::Source<extensions::TestSendMessageFunction>(
-        source).ptr();
+  // Return immediately if we're already satisfied or it's not the right
+  // extension.
+  extensions::TestSendMessageFunction* function =
+      content::Source<extensions::TestSendMessageFunction>(source).ptr();
+  if (satisfied_ ||
+      (!extension_id_.empty() && function->extension_id() != extension_id_)) {
+    return;
+  }
+
+  // We should have an empty message if we're not already satisfied.
+  CHECK(message_.empty());
+
+  const std::string& message = *content::Details<std::string>(details).ptr();
+  if (message == expected_message_ || wait_for_any_message_ ||
+      (!failure_message_.empty() && message == failure_message_)) {
+    message_ = message;
     satisfied_ = true;
-    registrar_.RemoveAll();  // Stop listening for more messages.
-    if (!will_reply_) {
-      function_->Reply(std::string());
-      function_ = NULL;
-    }
+    failed_ = (message_ == failure_message_);
+
+    // Reply immediately, or save the function for future use.
+    function_ = function;
+    if (!will_reply_)
+      Reply(base::EmptyString());
+
     if (waiting_) {
       waiting_ = false;
       base::MessageLoopForUI::current()->Quit();
diff --git a/chrome/browser/extensions/extension_test_message_listener.h b/chrome/browser/extensions/extension_test_message_listener.h
index f077a49..7da133e 100644
--- a/chrome/browser/extensions/extension_test_message_listener.h
+++ b/chrome/browser/extensions/extension_test_message_listener.h
@@ -19,7 +19,7 @@
 // This class helps us wait for incoming messages sent from javascript via
 // chrome.test.sendMessage(). A sample usage would be:
 //
-//   ExtensionTestMessageListener listener("foo");
+//   ExtensionTestMessageListener listener("foo", false);  // won't reply
 //   ... do some work
 //   ASSERT_TRUE(listener.WaitUntilSatisfied());
 //
@@ -27,18 +27,56 @@
 // useful for coordinating multiple pages/processes and having them wait on
 // each other. Example:
 //
-//   ExtensionTestMessageListener listener1("foo1");
-//   ExtensionTestMessageListener listener2("foo2");
+//   ExtensionTestMessageListener listener1("foo1", true);  // will reply
+//   ExtensionTestMessageListener listener2("foo2", true);  // will reply
 //   ASSERT_TRUE(listener1.WaitUntilSatisfied());
 //   ASSERT_TRUE(listener2.WaitUntilSatisfied());
 //   ... do some work
 //   listener1.Reply("foo2 is ready");
 //   listener2.Reply("foo1 is ready");
 //
-// TODO(asargent) - In the future we may want to add the ability to listen for
-// multiple messages, and/or to wait for "any" message and then retrieve the
-// contents of that message. We may also want to specify an extension id as
-// satisfaction criteria in addition to message content.
+// Further, we can use this to listen for a success and failure message:
+//
+//   ExtensionTestMessageListener listener("success", will_reply);
+//   listener.set_failure_message("failure");
+//   ASSERT_TRUE(listener.WaitUntilSatisfied());
+//   if (listener.message() == "success") {
+//     HandleSuccess();
+//   } else {
+//     ASSERT_EQ("failure", listener.message());
+//     HandleFailure();
+//   }
+//
+// Or, use it to listen to any arbitrary message:
+//
+//   ExtensionTestMessageListener listener(will_reply);
+//   ASSERT_TRUE(listener.WaitUntilSatisfied());
+//   if (listener.message() == "foo")
+//     HandleFoo();
+//   else if (listener.message() == "bar")
+//     HandleBar();
+//   else if (listener.message() == "baz")
+//     HandleBaz();
+//   else
+//     NOTREACHED();
+//
+// You can also use the class to listen for messages from a specified extension:
+//
+//   ExtensionTestMessageListener listener(will_reply);
+//   listener.set_extension_id(extension->id());
+//   ASSERT_TRUE(listener.WaitUntilSatisfied());
+//   ... do some work.
+//
+// Finally, you can reset the listener to reuse it.
+//
+//   ExtensionTestMessageListener listener(true);  // will reply
+//   ASSERT_TRUE(listener.WaitUntilSatisfied());
+//   while (listener.message() != "end") {
+//     Handle(listener.message());
+//     listener.Reply("bar");
+//     listener.Reset();
+//     ASSERT_TRUE(listener.WaitUntilSatisfied());
+//   }
 //
 // Note that when using it in browser tests, you need to make sure it gets
 // destructed *before* the browser gets torn down. Two common patterns are to
@@ -50,15 +88,15 @@
   // We immediately start listening for |expected_message|.
   ExtensionTestMessageListener(const std::string& expected_message,
                                bool will_reply);
+  // Construct a message listener which will listen for any message.
+  explicit ExtensionTestMessageListener(bool will_reply);
+
   virtual ~ExtensionTestMessageListener();
 
-  void AlsoListenForFailureMessage(const std::string& failure_message) {
-    failure_message_ = failure_message;
-  }
-
   // This returns true immediately if we've already gotten the expected
-  // message, or waits until it arrives. Returns false if the wait is
-  // interrupted and we still haven't gotten the message.
+  // message, or waits until it arrives.
+  // Returns false if the wait is interrupted and we still haven't gotten the
+  // message, or if the message was equal to |failure_message_|.
   bool WaitUntilSatisfied();
 
   // Send the given message as a reply. It is only valid to call this after
@@ -68,19 +106,39 @@
   // Convenience method that formats int as a string and sends it.
   void Reply(int message);
 
+  // Reset the listener to listen again. No settings (such as messages to
+  // listen for) are modified.
+  void Reset();
+
+  // Getters and setters.
+
+  bool was_satisfied() const { return satisfied_; }
+
+  void set_failure_message(const std::string& failure_message) {
+    failure_message_ = failure_message;
+  }
+
+  const std::string& extension_id() const { return extension_id_; }
+  void set_extension_id(const std::string& extension_id) {
+    extension_id_ = extension_id;
+  }
+
+  const std::string& message() const { return message_; }
+
+ private:
   // Implements the content::NotificationObserver interface.
   virtual void Observe(int type,
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  bool was_satisfied() const { return satisfied_; }
-
- private:
   content::NotificationRegistrar registrar_;
 
   // The message we're expecting.
   std::string expected_message_;
 
+  // The last message we received.
+  std::string message_;
+
   // Whether we've seen expected_message_ yet.
   bool satisfied_;
 
@@ -88,10 +146,19 @@
   // message arrives.
   bool waiting_;
 
+  // Whether or not we will wait for any message, regardless of contents.
+  bool wait_for_any_message_;
+
   // If true, we expect the calling code to manually send a reply. Otherwise,
   // we send an automatic empty reply to the extension.
   bool will_reply_;
 
+  // Whether or not we have already replied (we can only reply once).
+  bool replied_;
+
+  // The extension id that we listen for, or empty.
+  std::string extension_id_;
+
   // The message that signals failure.
   std::string failure_message_;
 
diff --git a/chrome/browser/extensions/extension_test_message_listener_unittest.cc b/chrome/browser/extensions/extension_test_message_listener_unittest.cc
new file mode 100644
index 0000000..f170863
--- /dev/null
+++ b/chrome/browser/extensions/extension_test_message_listener_unittest.cc
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/extensions/api/test/test_api.h"
+#include "chrome/browser/extensions/extension_api_unittest.h"
+#include "chrome/browser/extensions/extension_test_message_listener.h"
+
+namespace extensions {
+
+namespace {
+
+const char kTestMessage[] = "test message";
+const char kTestMessage2[] = "test message 2";
+const char kFailureMessage[] = "failure";
+
+}  // namespace
+
+class ExtensionTestMessageListenerUnittest : public ExtensionApiUnittest {};
+
+TEST_F(ExtensionTestMessageListenerUnittest, BasicTestExtensionMessageTest) {
+  // A basic test of sending a message and ensuring the listener is satisfied.
+  {
+    ExtensionTestMessageListener listener(kTestMessage, false);  // won't reply
+    EXPECT_FALSE(listener.was_satisfied());
+    RunFunction(new TestSendMessageFunction,
+                base::StringPrintf("[\"%s\"]", kTestMessage));
+    EXPECT_TRUE(listener.was_satisfied());
+    EXPECT_EQ(kTestMessage, listener.message());
+  }
+
+  // Test that we can receive an arbitrary message.
+  {
+    ExtensionTestMessageListener listener(false);  // won't reply
+    EXPECT_FALSE(listener.was_satisfied());
+    RunFunction(new TestSendMessageFunction,
+                base::StringPrintf("[\"%s\"]", kTestMessage2));
+    EXPECT_TRUE(listener.was_satisfied());
+    EXPECT_EQ(kTestMessage2, listener.message());
+  }
+
+  // Test that we can set the listener to be reused, and send/receive multiple
+  // messages.
+  {
+    ExtensionTestMessageListener listener(false);  // won't reply
+    EXPECT_FALSE(listener.was_satisfied());
+    RunFunction(new TestSendMessageFunction,
+                base::StringPrintf("[\"%s\"]", kTestMessage));
+    EXPECT_EQ(kTestMessage, listener.message());
+    EXPECT_TRUE(listener.was_satisfied());
+    listener.Reset();
+    EXPECT_FALSE(listener.was_satisfied());
+    EXPECT_EQ(base::EmptyString(), listener.message());
+    RunFunction(new TestSendMessageFunction,
+                base::StringPrintf("[\"%s\"]", kTestMessage2));
+    EXPECT_TRUE(listener.was_satisfied());
+    EXPECT_EQ(kTestMessage2, listener.message());
+  }
+
+  // Test that we can listen for two explicit messages: a success, and a
+  // failure.
+  {
+    ExtensionTestMessageListener listener(kTestMessage, false);  // won't reply
+    listener.set_failure_message(kFailureMessage);
+    RunFunction(new TestSendMessageFunction,
+                base::StringPrintf("[\"%s\"]", kTestMessage));
+    EXPECT_TRUE(listener.WaitUntilSatisfied());  // succeeds
+    EXPECT_EQ(kTestMessage, listener.message());
+    listener.Reset();
+    RunFunction(new TestSendMessageFunction,
+                base::StringPrintf("[\"%s\"]", kFailureMessage));
+    EXPECT_FALSE(listener.WaitUntilSatisfied());  // fails
+    EXPECT_EQ(kFailureMessage, listener.message());
+  }
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_toolbar_model.cc b/chrome/browser/extensions/extension_toolbar_model.cc
index 7d72ae9..878a23d 100644
--- a/chrome/browser/extensions/extension_toolbar_model.cc
+++ b/chrome/browser/extensions/extension_toolbar_model.cc
@@ -32,9 +32,7 @@
 #include "extensions/common/extension_set.h"
 #include "extensions/common/feature_switch.h"
 
-using extensions::Extension;
-using extensions::ExtensionIdList;
-using extensions::ExtensionList;
+namespace extensions {
 
 bool ExtensionToolbarModel::Observer::BrowserActionShowPopup(
     const extensions::Extension* extension) {
@@ -48,6 +46,7 @@
       extension_prefs_(extension_prefs),
       prefs_(profile_->GetPrefs()),
       extensions_initialized_(false),
+      is_highlighting_(false),
       weak_ptr_factory_(this) {
   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
                  content::Source<Profile>(profile_));
@@ -171,7 +170,13 @@
 void ExtensionToolbarModel::SetVisibleIconCount(int count) {
   visible_icon_count_ =
       count == static_cast<int>(toolbar_items_.size()) ? -1 : count;
-  prefs_->SetInteger(extensions::pref_names::kToolbarSize, visible_icon_count_);
+  // Only set the prefs if we're not in highlight mode. Highlight mode is
+  // designed to be a transitory state, and should not persist across browser
+  // restarts (though it may be re-entered).
+  if (!is_highlighting_) {
+    prefs_->SetInteger(extensions::pref_names::kToolbarSize,
+                       visible_icon_count_);
+  }
 }
 
 void ExtensionToolbarModel::Observe(
@@ -207,7 +212,7 @@
       if (toolbar_items_[i].get() == extension)
         return;  // Already exists.
     }
-    if (extensions::ExtensionActionAPI::GetBrowserActionVisibility(
+    if (ExtensionActionAPI::GetBrowserActionVisibility(
             extension_prefs_, extension->id())) {
       AddExtension(extension);
     }
@@ -217,7 +222,7 @@
     UninstalledExtension(extension);
   } else if (type ==
       chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_VISIBILITY_CHANGED) {
-    if (extensions::ExtensionActionAPI::GetBrowserActionVisibility(
+    if (ExtensionActionAPI::GetBrowserActionVisibility(
             extension_prefs_, extension->id())) {
       AddExtension(extension);
     } else {
@@ -254,10 +259,8 @@
 
 void ExtensionToolbarModel::AddExtension(const Extension* extension) {
   // We only care about extensions with browser actions.
-  if (!extensions::ExtensionActionManager::Get(profile_)->
-      GetBrowserAction(*extension)) {
+  if (!ExtensionActionManager::Get(profile_)->GetBrowserAction(*extension))
     return;
-  }
 
   size_t new_index = -1;
 
@@ -282,8 +285,13 @@
     UpdatePrefs();
   }
 
-  FOR_EACH_OBSERVER(Observer, observers_,
-                    BrowserActionAdded(extension, new_index));
+  // If we're currently highlighting, then even though we add a browser action
+  // to the full list (|toolbar_items_|, there won't be another *visible*
+  // browser action, which was what the observers care about.
+  if (!is_highlighting_) {
+    FOR_EACH_OBSERVER(Observer, observers_,
+                      BrowserActionAdded(extension, new_index));
+  }
 }
 
 void ExtensionToolbarModel::RemoveExtension(const Extension* extension) {
@@ -293,8 +301,23 @@
     return;
 
   toolbar_items_.erase(pos);
-  FOR_EACH_OBSERVER(Observer, observers_,
-                    BrowserActionRemoved(extension));
+
+  // If we're in highlight mode, we also have to remove the extension from
+  // the highlighted list.
+  if (is_highlighting_) {
+    pos = std::find(highlighted_items_.begin(),
+                    highlighted_items_.end(),
+                    extension);
+    if (pos != highlighted_items_.end()) {
+      highlighted_items_.erase(pos);
+      FOR_EACH_OBSERVER(Observer, observers_, BrowserActionRemoved(extension));
+      // If the highlighted list is now empty, we stop highlighting.
+      if (highlighted_items_.empty())
+        StopHighlighting();
+    }
+  } else {
+    FOR_EACH_OBSERVER(Observer, observers_, BrowserActionRemoved(extension));
+  }
 
   UpdatePrefs();
 }
@@ -330,7 +353,7 @@
 }
 
 void ExtensionToolbarModel::Populate(
-    const extensions::ExtensionIdList& positions,
+    const ExtensionIdList& positions,
     ExtensionService* service) {
   // Items that have explicit positions.
   ExtensionList sorted;
@@ -338,8 +361,8 @@
   // The items that don't have explicit positions.
   ExtensionList unsorted;
 
-  extensions::ExtensionActionManager* extension_action_manager =
-      extensions::ExtensionActionManager::Get(profile_);
+  ExtensionActionManager* extension_action_manager =
+      ExtensionActionManager::Get(profile_);
 
   // Create the lists.
   int hidden = 0;
@@ -349,13 +372,13 @@
     const Extension* extension = it->get();
     if (!extension_action_manager->GetBrowserAction(*extension))
       continue;
-    if (!extensions::ExtensionActionAPI::GetBrowserActionVisibility(
+    if (!ExtensionActionAPI::GetBrowserActionVisibility(
             extension_prefs_, extension->id())) {
       ++hidden;
       continue;
     }
 
-    extensions::ExtensionIdList::const_iterator pos =
+    ExtensionIdList::const_iterator pos =
         std::find(positions.begin(), positions.end(), extension->id());
     if (pos != positions.end())
       sorted[pos - positions.begin()] = extension;
@@ -413,10 +436,9 @@
     return;
 
   // Don't observe change caused by self.
-  pref_change_registrar_.Remove(extensions::pref_names::kToolbar);
+  pref_change_registrar_.Remove(pref_names::kToolbar);
   extension_prefs_->SetToolbarOrder(last_known_positions_);
-  pref_change_registrar_.Add(extensions::pref_names::kToolbar,
-                             pref_change_callback_);
+  pref_change_registrar_.Add(pref_names::kToolbar, pref_change_callback_);
 }
 
 int ExtensionToolbarModel::IncognitoIndexToOriginal(int incognito_index) {
@@ -424,7 +446,7 @@
   for (ExtensionList::iterator iter = toolbar_items_.begin();
        iter != toolbar_items_.end();
        ++iter, ++original_index) {
-    if (extensions::util::IsIncognitoEnabled((*iter)->id(), profile_)) {
+    if (util::IsIncognitoEnabled((*iter)->id(), profile_)) {
       if (incognito_index == i)
         break;
       ++i;
@@ -440,7 +462,7 @@
        ++iter, ++i) {
     if (original_index == i)
       break;
-    if (extensions::util::IsIncognitoEnabled((*iter)->id(), profile_))
+    if (util::IsIncognitoEnabled((*iter)->id(), profile_))
       ++incognito_index;
   }
   return incognito_index;
@@ -453,8 +475,7 @@
 
   // Recalculate |last_known_positions_| to be |pref_positions| followed by
   // ones that are only in |last_known_positions_|.
-  extensions::ExtensionIdList pref_positions =
-      extension_prefs_->GetToolbarOrder();
+  ExtensionIdList pref_positions = extension_prefs_->GetToolbarOrder();
   size_t pref_position_size = pref_positions.size();
   for (size_t i = 0; i < last_known_positions_.size(); ++i) {
     if (std::find(pref_positions.begin(), pref_positions.end(),
@@ -466,7 +487,7 @@
 
   // Re-populate.
   Populate(last_known_positions_,
-           extensions::ExtensionSystem::Get(profile_)->extension_service());
+           ExtensionSystem::Get(profile_)->extension_service());
 
   if (last_known_positions_.size() > pref_position_size) {
     // Need to update pref because we have extra icons. But can't call
@@ -478,8 +499,7 @@
   }
 }
 
-bool ExtensionToolbarModel::ShowBrowserActionPopup(
-    const extensions::Extension* extension) {
+bool ExtensionToolbarModel::ShowBrowserActionPopup(const Extension* extension) {
   ObserverListBase<Observer>::Iterator it(observers_);
   Observer* obs = NULL;
   while ((obs = it.GetNext()) != NULL) {
@@ -491,7 +511,7 @@
 }
 
 void ExtensionToolbarModel::EnsureVisibility(
-    const extensions::ExtensionIdList& extension_ids) {
+    const ExtensionIdList& extension_ids) {
   if (visible_icon_count_ == -1)
     return;  // Already showing all.
 
@@ -520,3 +540,54 @@
     }
   }
 }
+
+bool ExtensionToolbarModel::HighlightExtensions(
+    const ExtensionIdList& extension_ids) {
+  highlighted_items_.clear();
+
+  for (ExtensionIdList::const_iterator id = extension_ids.begin();
+       id != extension_ids.end();
+       ++id) {
+    for (ExtensionList::const_iterator extension = toolbar_items_.begin();
+         extension != toolbar_items_.end();
+         ++extension) {
+      if (*id == (*extension)->id())
+        highlighted_items_.push_back(*extension);
+    }
+  }
+
+  // If we have any items in |highlighted_items_|, then we entered highlighting
+  // mode.
+  if (highlighted_items_.size()) {
+    old_visible_icon_count_ = visible_icon_count_;
+    is_highlighting_ = true;
+    if (visible_icon_count_ != -1 &&
+        visible_icon_count_ < static_cast<int>(extension_ids.size())) {
+      SetVisibleIconCount(extension_ids.size());
+      FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged());
+    }
+
+    FOR_EACH_OBSERVER(Observer, observers_, HighlightModeChanged(true));
+    return true;
+  }
+
+  // Otherwise, we didn't enter highlighting mode (and, in fact, exited it if
+  // we were otherwise in it).
+  if (is_highlighting_)
+    StopHighlighting();
+  return false;
+}
+
+void ExtensionToolbarModel::StopHighlighting() {
+  if (is_highlighting_) {
+    highlighted_items_.clear();
+    is_highlighting_ = false;
+    if (old_visible_icon_count_ != visible_icon_count_) {
+      SetVisibleIconCount(old_visible_icon_count_);
+      FOR_EACH_OBSERVER(Observer, observers_, VisibleCountChanged());
+    }
+    FOR_EACH_OBSERVER(Observer, observers_, HighlightModeChanged(false));
+  }
+};
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_toolbar_model.h b/chrome/browser/extensions/extension_toolbar_model.h
index 5938efb..1bf95e9 100644
--- a/chrome/browser/extensions/extension_toolbar_model.h
+++ b/chrome/browser/extensions/extension_toolbar_model.h
@@ -19,12 +19,13 @@
 class PrefService;
 class Profile;
 
+namespace extensions {
+
 // Model for the browser actions toolbar.
 class ExtensionToolbarModel : public content::NotificationObserver,
                               public KeyedService {
  public:
-  ExtensionToolbarModel(Profile* profile,
-                        extensions::ExtensionPrefs* extension_prefs);
+  ExtensionToolbarModel(Profile* profile, ExtensionPrefs* extension_prefs);
   virtual ~ExtensionToolbarModel();
 
   // The action that should be taken as a result of clicking a browser action.
@@ -42,24 +43,31 @@
    public:
     // An extension with a browser action button has been added, and should go
     // in the toolbar at |index|.
-    virtual void BrowserActionAdded(const extensions::Extension* extension,
-                                    int index) {}
+    virtual void BrowserActionAdded(const Extension* extension, int index) {}
 
     // The browser action button for |extension| should no longer show.
-    virtual void BrowserActionRemoved(const extensions::Extension* extension) {}
+    virtual void BrowserActionRemoved(const Extension* extension) {}
 
     // The browser action button for |extension| has been moved to |index|.
-    virtual void BrowserActionMoved(const extensions::Extension* extension,
-                                    int index) {}
+    virtual void BrowserActionMoved(const Extension* extension, int index) {}
 
     // Signal the |extension| to show the popup now in the active window.
     // Returns true if a popup was slated to be shown.
-    virtual bool BrowserActionShowPopup(const extensions::Extension* extension);
+    virtual bool BrowserActionShowPopup(const Extension* extension);
 
     // Signal when the container needs to be redrawn because of a size change,
     // and when the model has finished loading.
     virtual void VisibleCountChanged() {}
 
+    // Signal that the model has entered or exited highlighting mode, or that
+    // the extensions being highlighted have (probably*) changed. Highlighting
+    // mode indicates that only a subset of the extensions are actively
+    // displayed, and those extensions should be highlighted for extra emphasis.
+    // * probably, because if we are in highlight mode and receive a call to
+    //   highlight a new set of extensions, we do not compare the current set
+    //   with the new set (and just assume the new set is different).
+    virtual void HighlightModeChanged(bool is_highlighting) {}
+
    protected:
     virtual ~Observer() {}
   };
@@ -70,7 +78,7 @@
   // Functions called by the view.
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
-  void MoveBrowserAction(const extensions::Extension* extension, int index);
+  void MoveBrowserAction(const Extension* extension, int index);
   // Executes the browser action for an extension and returns the action that
   // the UI should perform in response.
   // |popup_url_out| will be set if the extension should show a popup, with
@@ -78,7 +86,7 @@
   // the extension should be granted page tab permissions, which is what happens
   // when the user clicks the browser action, but not, for example, when the
   // showPopup API is called.
-  Action ExecuteBrowserAction(const extensions::Extension* extension,
+  Action ExecuteBrowserAction(const Extension* extension,
                               Browser* browser,
                               GURL* popup_url_out,
                               bool should_grant);
@@ -90,10 +98,12 @@
 
   bool extensions_initialized() const { return extensions_initialized_; }
 
-  const extensions::ExtensionList& toolbar_items() const {
-    return toolbar_items_;
+  const ExtensionList& toolbar_items() const {
+    return is_highlighting_ ? highlighted_items_ : toolbar_items_;
   }
 
+  bool is_highlighting() const { return is_highlighting_; }
+
   // Utility functions for converting between an index into the list of
   // incognito-enabled browser actions, and the list of all browser actions.
   int IncognitoIndexToOriginal(int incognito_index);
@@ -103,12 +113,23 @@
 
   // Tells observers to display a popup without granting tab permissions and
   // returns whether the popup was slated to be shown.
-  bool ShowBrowserActionPopup(const extensions::Extension* extension);
+  bool ShowBrowserActionPopup(const Extension* extension);
 
   // Ensures that the extensions in the |extension_ids| list are visible on the
   // toolbar. This might mean they need to be moved to the front (if they are in
   // the overflow bucket).
-  void EnsureVisibility(const extensions::ExtensionIdList& extension_ids);
+  void EnsureVisibility(const ExtensionIdList& extension_ids);
+
+  // Highlight the extensions specified by |extension_ids|. This will cause
+  // the ToolbarModel to only display those extensions.
+  // Highlighting mode is only entered if there is at least one extension to
+  // be shown.
+  // Returns true if highlighting mode is entered, false otherwise.
+  bool HighlightExtensions(const ExtensionIdList& extension_ids);
+
+  // Stop highlighting extensions. All extensions can be shown again, and the
+  // number of visible icons will be reset to what it was before highlighting.
+  void StopHighlighting();
 
  private:
   // content::NotificationObserver implementation.
@@ -120,11 +141,10 @@
   // from the extension service and their saved order from the pref service
   // and constructs |toolbar_items_| from these data.
   void InitializeExtensionList(ExtensionService* service);
-  void Populate(const extensions::ExtensionIdList& positions,
-                ExtensionService* service);
+  void Populate(const ExtensionIdList& positions, ExtensionService* service);
 
   // Fills |list| with extensions based on provided |order|.
-  void FillExtensionList(const extensions::ExtensionIdList& order,
+  void FillExtensionList(const ExtensionIdList& order,
                          ExtensionService* service);
 
   // Save the model to prefs.
@@ -132,29 +152,40 @@
 
   // Finds the last known visible position of the icon for an |extension|. The
   // value returned is a zero-based index into the vector of visible items.
-  size_t FindNewPositionFromLastKnownGood(
-      const extensions::Extension* extension);
+  size_t FindNewPositionFromLastKnownGood(const Extension* extension);
 
   // Our observers.
   ObserverList<Observer> observers_;
 
-  void AddExtension(const extensions::Extension* extension);
-  void RemoveExtension(const extensions::Extension* extension);
-  void UninstalledExtension(const extensions::Extension* extension);
+  void AddExtension(const Extension* extension);
+  void RemoveExtension(const Extension* extension);
+  void UninstalledExtension(const Extension* extension);
 
   // The Profile this toolbar model is for.
   Profile* profile_;
 
-  extensions::ExtensionPrefs* extension_prefs_;
+  ExtensionPrefs* extension_prefs_;
   PrefService* prefs_;
 
   // True if we've handled the initial EXTENSIONS_READY notification.
   bool extensions_initialized_;
 
   // Ordered list of browser action buttons.
-  extensions::ExtensionList toolbar_items_;
+  ExtensionList toolbar_items_;
 
-  extensions::ExtensionIdList last_known_positions_;
+  // List of browser action buttons which should be highlighted.
+  ExtensionList highlighted_items_;
+
+  // Indication whether or not we are currently in highlight mode; typically,
+  // this is equivalent to !highlighted_items_.empty(), but can be different
+  // if we are exiting highlight mode due to no longer having highlighted items.
+  bool is_highlighting_;
+
+  // The number of icons which were visible before highlighting a subset, in
+  // order to restore the count when finished.
+  int old_visible_icon_count_;
+
+  ExtensionIdList last_known_positions_;
 
   // The number of icons visible (the rest should be hidden in the overflow
   // chevron).
@@ -171,4 +202,6 @@
   DISALLOW_COPY_AND_ASSIGN(ExtensionToolbarModel);
 };
 
+}  // namespace extensions
+
 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_H_
diff --git a/chrome/browser/extensions/extension_toolbar_model_browsertest.cc b/chrome/browser/extensions/extension_toolbar_model_browsertest.cc
index 6936213..a3759f4 100644
--- a/chrome/browser/extensions/extension_toolbar_model_browsertest.cc
+++ b/chrome/browser/extensions/extension_toolbar_model_browsertest.cc
@@ -2,13 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/macros.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
 #include "chrome/browser/extensions/extension_toolbar_model.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
 
-using extensions::Extension;
+namespace extensions {
 
 // An InProcessBrowserTest for testing the ExtensionToolbarModel.
 // TODO(erikkay) It's unfortunate that this needs to be an in-proc browser test.
@@ -21,6 +22,7 @@
     inserted_count_ = 0;
     removed_count_ = 0;
     moved_count_ = 0;
+    highlight_mode_count_ = 0;
 
     ExtensionBrowserTest::SetUp();
   }
@@ -48,9 +50,14 @@
     moved_count_++;
   }
 
+  virtual void HighlightModeChanged(bool is_highlighting) OVERRIDE {
+    // Add one if highlighting, subtract one if not.
+    highlight_mode_count_ += is_highlighting ? 1 : -1;
+  }
+
   const Extension* ExtensionAt(int index) {
-    const extensions::ExtensionList& toolbar_items = model_->toolbar_items();
-    for (extensions::ExtensionList::const_iterator i = toolbar_items.begin();
+    const ExtensionList& toolbar_items = model_->toolbar_items();
+    for (ExtensionList::const_iterator i = toolbar_items.begin();
          i < toolbar_items.end(); ++i) {
       if (index-- == 0)
         return i->get();
@@ -64,6 +71,7 @@
   int inserted_count_;
   int removed_count_;
   int moved_count_;
+  int highlight_mode_count_;
 };
 
 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, Basic) {
@@ -362,14 +370,211 @@
   std::string id_c = ExtensionAt(2)->id();
 
   // Change value of toolbar preference.
-  extensions::ExtensionIdList new_order;
+  ExtensionIdList new_order;
   new_order.push_back(id_c);
   new_order.push_back(id_b);
-  extensions::ExtensionPrefs::Get(browser()->profile())->SetToolbarOrder(
-      new_order);
+  ExtensionPrefs::Get(browser()->profile())->SetToolbarOrder(new_order);
 
   // Verify order is changed.
   EXPECT_EQ(id_c, ExtensionAt(0)->id());
   EXPECT_EQ(id_b, ExtensionAt(1)->id());
   EXPECT_EQ(id_a, ExtensionAt(2)->id());
 }
+
+IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, HighlightMode) {
+  EXPECT_FALSE(model_->HighlightExtensions(ExtensionIdList()));
+  EXPECT_EQ(0, highlight_mode_count_);
+
+  // Load three extensions with browser action.
+  base::FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("basics"));
+  ASSERT_TRUE(LoadExtension(extension_a_path));
+  base::FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("popup"));
+  ASSERT_TRUE(LoadExtension(extension_b_path));
+  base::FilePath extension_c_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("remove_popup"));
+  ASSERT_TRUE(LoadExtension(extension_c_path));
+  std::string id_a = ExtensionAt(0)->id();
+  std::string id_b = ExtensionAt(1)->id();
+  std::string id_c = ExtensionAt(2)->id();
+
+  // Highlight one extension.
+  ExtensionIdList extension_ids;
+  extension_ids.push_back(id_b);
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_EQ(1, highlight_mode_count_);
+  EXPECT_TRUE(model_->is_highlighting());
+
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_b, ExtensionAt(0)->id());
+
+  // Stop highlighting.
+  model_->StopHighlighting();
+  EXPECT_EQ(0, highlight_mode_count_);
+  EXPECT_FALSE(model_->is_highlighting());
+
+  // Verify that the extensions are back to normal.
+  EXPECT_EQ(3u, model_->toolbar_items().size());
+  EXPECT_EQ(id_a, ExtensionAt(0)->id());
+  EXPECT_EQ(id_b, ExtensionAt(1)->id());
+  EXPECT_EQ(id_c, ExtensionAt(2)->id());
+
+  // Call stop highlighting a second time (shouldn't be notified).
+  model_->StopHighlighting();
+  EXPECT_EQ(0, highlight_mode_count_);
+  EXPECT_FALSE(model_->is_highlighting());
+
+  // Highlight all extensions.
+  extension_ids.clear();
+  extension_ids.push_back(id_a);
+  extension_ids.push_back(id_b);
+  extension_ids.push_back(id_c);
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_EQ(1, highlight_mode_count_);
+  EXPECT_EQ(3u, model_->toolbar_items().size());
+  EXPECT_EQ(id_a, ExtensionAt(0)->id());
+  EXPECT_EQ(id_b, ExtensionAt(1)->id());
+  EXPECT_EQ(id_c, ExtensionAt(2)->id());
+
+  // Highlight only extension b (shrink the highlight list).
+  extension_ids.clear();
+  extension_ids.push_back(id_b);
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_EQ(2, highlight_mode_count_);
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_b, ExtensionAt(0)->id());
+
+  // Highlight extensions a and b (grow the highlight list).
+  extension_ids.clear();
+  extension_ids.push_back(id_a);
+  extension_ids.push_back(id_b);
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_EQ(3, highlight_mode_count_);
+  EXPECT_EQ(2u, model_->toolbar_items().size());
+  EXPECT_EQ(id_a, ExtensionAt(0)->id());
+  EXPECT_EQ(id_b, ExtensionAt(1)->id());
+
+  // Highlight no extensions (empty the highlight list).
+  extension_ids.clear();
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_EQ(2, highlight_mode_count_);
+  EXPECT_FALSE(model_->is_highlighting());
+  EXPECT_EQ(id_a, ExtensionAt(0)->id());
+  EXPECT_EQ(id_b, ExtensionAt(1)->id());
+  EXPECT_EQ(id_c, ExtensionAt(2)->id());
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, HighlightModeRemove) {
+  // Load three extensions with browser action.
+  base::FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("basics"));
+  ASSERT_TRUE(LoadExtension(extension_a_path));
+  base::FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("popup"));
+  ASSERT_TRUE(LoadExtension(extension_b_path));
+  base::FilePath extension_c_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("remove_popup"));
+  ASSERT_TRUE(LoadExtension(extension_c_path));
+  std::string id_a = ExtensionAt(0)->id();
+  std::string id_b = ExtensionAt(1)->id();
+  std::string id_c = ExtensionAt(2)->id();
+
+  // Highlight two of the extensions.
+  ExtensionIdList extension_ids;
+  extension_ids.push_back(id_a);
+  extension_ids.push_back(id_b);
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_TRUE(model_->is_highlighting());
+  EXPECT_EQ(1, highlight_mode_count_);
+  EXPECT_EQ(2u, model_->toolbar_items().size());
+
+  // Disable one of them - only one should remain highlighted.
+  DisableExtension(id_a);
+  EXPECT_TRUE(model_->is_highlighting());
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_b, ExtensionAt(0)->id());
+
+  // Uninstall the remaining highlighted extension. This should result in
+  // highlight mode exiting.
+  UninstallExtension(id_b);
+  EXPECT_FALSE(model_->is_highlighting());
+  EXPECT_EQ(0, highlight_mode_count_);
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_c, ExtensionAt(0)->id());
+
+  // Test that removing an unhighlighted extension still works.
+  // Reinstall extension b, and then highlight extension c.
+  ASSERT_TRUE(LoadExtension(extension_b_path));
+  EXPECT_EQ(id_b, ExtensionAt(1)->id());
+  extension_ids.clear();
+  extension_ids.push_back(id_c);
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_EQ(1, highlight_mode_count_);
+  EXPECT_TRUE(model_->is_highlighting());
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_c, ExtensionAt(0)->id());
+
+  // Uninstalling b should not have visible impact.
+  UninstallExtension(id_b);
+  EXPECT_TRUE(model_->is_highlighting());
+  EXPECT_EQ(1, highlight_mode_count_);
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_c, ExtensionAt(0)->id());
+
+  // When we stop, only extension c should remain.
+  model_->StopHighlighting();
+  EXPECT_FALSE(model_->is_highlighting());
+  EXPECT_EQ(0, highlight_mode_count_);
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_c, ExtensionAt(0)->id());
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest, HighlightModeAdd) {
+  // Load two extensions with browser action.
+  base::FilePath extension_a_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("basics"));
+  ASSERT_TRUE(LoadExtension(extension_a_path));
+  base::FilePath extension_b_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("popup"));
+  ASSERT_TRUE(LoadExtension(extension_b_path));
+  std::string id_a = ExtensionAt(0)->id();
+  std::string id_b = ExtensionAt(1)->id();
+
+  // Highlight one of the extensions.
+  ExtensionIdList extension_ids;
+  extension_ids.push_back(id_a);
+  model_->HighlightExtensions(extension_ids);
+  EXPECT_TRUE(model_->is_highlighting());
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_a, ExtensionAt(0)->id());
+
+  // Adding the new extension should have no visible effect.
+  base::FilePath extension_c_path(test_data_dir_.AppendASCII("api_test")
+                                                .AppendASCII("browser_action")
+                                                .AppendASCII("remove_popup"));
+  const Extension* extension_c = LoadExtension(extension_c_path);
+  ASSERT_TRUE(extension_c);
+  std::string id_c = extension_c->id();
+  EXPECT_TRUE(model_->is_highlighting());
+  EXPECT_EQ(1u, model_->toolbar_items().size());
+  EXPECT_EQ(id_a, ExtensionAt(0)->id());
+
+  // When we stop highlighting, we should see the new extension show up.
+  model_->StopHighlighting();
+  EXPECT_FALSE(model_->is_highlighting());
+  EXPECT_EQ(3u, model_->toolbar_items().size());
+  EXPECT_EQ(id_a, ExtensionAt(0)->id());
+  EXPECT_EQ(id_b, ExtensionAt(1)->id());
+  EXPECT_EQ(id_c, ExtensionAt(2)->id());
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_toolbar_model_factory.cc b/chrome/browser/extensions/extension_toolbar_model_factory.cc
index 342fb1d..cf9b98d 100644
--- a/chrome/browser/extensions/extension_toolbar_model_factory.cc
+++ b/chrome/browser/extensions/extension_toolbar_model_factory.cc
@@ -11,6 +11,8 @@
 #include "extensions/browser/extension_prefs_factory.h"
 #include "extensions/browser/extensions_browser_client.h"
 
+namespace extensions {
+
 // static
 ExtensionToolbarModel* ExtensionToolbarModelFactory::GetForProfile(
     Profile* profile) {
@@ -27,7 +29,7 @@
     : BrowserContextKeyedServiceFactory(
         "ExtensionToolbarModel",
         BrowserContextDependencyManager::GetInstance()) {
-  DependsOn(extensions::ExtensionPrefsFactory::GetInstance());
+  DependsOn(ExtensionPrefsFactory::GetInstance());
 }
 
 ExtensionToolbarModelFactory::~ExtensionToolbarModelFactory() {}
@@ -36,13 +38,12 @@
     content::BrowserContext* context) const {
   return new ExtensionToolbarModel(
       Profile::FromBrowserContext(context),
-      extensions::ExtensionPrefsFactory::GetForBrowserContext(context));
+      ExtensionPrefsFactory::GetForBrowserContext(context));
 }
 
 content::BrowserContext* ExtensionToolbarModelFactory::GetBrowserContextToUse(
     content::BrowserContext* context) const {
-  return extensions::ExtensionsBrowserClient::Get()->
-      GetOriginalContext(context);
+  return ExtensionsBrowserClient::Get()->GetOriginalContext(context);
 }
 
 bool ExtensionToolbarModelFactory::ServiceIsCreatedWithBrowserContext() const {
@@ -52,3 +53,5 @@
 bool ExtensionToolbarModelFactory::ServiceIsNULLWhileTesting() const {
   return true;
 }
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/extension_toolbar_model_factory.h b/chrome/browser/extensions/extension_toolbar_model_factory.h
index 564f2c2..177eb16 100644
--- a/chrome/browser/extensions/extension_toolbar_model_factory.h
+++ b/chrome/browser/extensions/extension_toolbar_model_factory.h
@@ -9,9 +9,12 @@
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
-class ExtensionToolbarModel;
 class Profile;
 
+namespace extensions {
+
+class ExtensionToolbarModel;
+
 class ExtensionToolbarModelFactory : public BrowserContextKeyedServiceFactory {
  public:
   static ExtensionToolbarModel* GetForProfile(Profile* profile);
@@ -32,4 +35,6 @@
   virtual bool ServiceIsNULLWhileTesting() const OVERRIDE;
 };
 
+}  // namespace extensions
+
 #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_TOOLBAR_MODEL_FACTORY_H_
diff --git a/chrome/browser/extensions/extension_util.cc b/chrome/browser/extensions/extension_util.cc
index 4faa0dc..2cdd2cc 100644
--- a/chrome/browser/extensions/extension_util.cc
+++ b/chrome/browser/extensions/extension_util.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_icon_set.h"
+#include "chrome/common/extensions/manifest_handlers/app_isolation_info.h"
 #include "chrome/common/extensions/sync_helper.h"
 #include "content/public/browser/site_instance.h"
 #include "extensions/browser/extension_prefs.h"
@@ -199,5 +200,45 @@
   return dict.Pass();
 }
 
+bool HasIsolatedStorage(const ExtensionInfo& info) {
+  if (!info.extension_manifest.get())
+    return false;
+
+  std::string error;
+  scoped_refptr<const Extension> extension(Extension::Create(
+      info.extension_path,
+      info.extension_location,
+      *info.extension_manifest,
+      Extension::NO_FLAGS,
+      info.extension_id,
+      &error));
+  if (!extension.get())
+    return false;
+
+  return AppIsolationInfo::HasIsolatedStorage(extension.get());
+}
+
+bool SiteHasIsolatedStorage(const GURL& extension_site_url,
+                            content::BrowserContext* context) {
+  const Extension* extension = ExtensionRegistry::Get(context)->
+      enabled_extensions().GetExtensionOrAppByURL(extension_site_url);
+  if (extension)
+    return AppIsolationInfo::HasIsolatedStorage(extension);
+
+  if (extension_site_url.SchemeIs(kExtensionScheme)) {
+    // The site URL may also be from an evicted ephemeral app. We do not
+    // immediately delete their data when they are removed from extension
+    // system.
+    ExtensionPrefs* prefs = ExtensionPrefs::Get(context);
+    DCHECK(prefs);
+    scoped_ptr<ExtensionInfo> info = prefs->GetEvictedEphemeralAppInfo(
+        extension_site_url.host());
+    if (info.get())
+      return HasIsolatedStorage(*info);
+  }
+
+  return false;
+}
+
 }  // namespace util
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_util.h b/chrome/browser/extensions/extension_util.h
index 45e3b57..fb3b7ae 100644
--- a/chrome/browser/extensions/extension_util.h
+++ b/chrome/browser/extensions/extension_util.h
@@ -21,6 +21,7 @@
 namespace extensions {
 
 class Extension;
+struct ExtensionInfo;
 
 namespace util {
 
@@ -82,6 +83,14 @@
 // returned dictionary.
 scoped_ptr<base::DictionaryValue> GetExtensionInfo(const Extension* extension);
 
+// Returns true if the extension has isolated storage.
+bool HasIsolatedStorage(const ExtensionInfo& info);
+
+// Returns true if the site URL corresponds to an extension or app and has
+// isolated storage.
+bool SiteHasIsolatedStorage(const GURL& extension_site_url,
+                            content::BrowserContext* context);
+
 }  // namespace util
 }  // namespace extensions
 
diff --git a/chrome/browser/extensions/extension_warning_service.cc b/chrome/browser/extensions/extension_warning_service.cc
index 2acda5f..37ce1ee 100644
--- a/chrome/browser/extensions/extension_warning_service.cc
+++ b/chrome/browser/extensions/extension_warning_service.cc
@@ -93,7 +93,7 @@
 void ExtensionWarningService::NotifyWarningsOnUI(
     void* profile_id,
     const ExtensionWarningSet& warnings) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   Profile* profile = reinterpret_cast<Profile*>(profile_id);
   if (!profile ||
       !g_browser_process->profile_manager() ||
diff --git a/chrome/browser/extensions/extension_warning_set.cc b/chrome/browser/extensions/extension_warning_set.cc
index a58fe84..a68f9cd 100644
--- a/chrome/browser/extensions/extension_warning_set.cc
+++ b/chrome/browser/extensions/extension_warning_set.cc
@@ -179,7 +179,7 @@
 
 std::string ExtensionWarning::GetLocalizedMessage(
     const ExtensionSet* extensions) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // These parameters may be unsafe (URLs and Extension names) and need
   // to be HTML-escaped before being embedded in the UI. Also extension IDs
diff --git a/chrome/browser/extensions/external_install_ui.cc b/chrome/browser/extensions/external_install_ui.cc
index a071228..665b1e1 100644
--- a/chrome/browser/extensions/external_install_ui.cc
+++ b/chrome/browser/extensions/external_install_ui.cc
@@ -62,6 +62,7 @@
 class ExternalInstallDialogDelegate
     : public ExtensionInstallPrompt::Delegate,
       public WebstoreDataFetcherDelegate,
+      public content::NotificationObserver,
       public base::RefCountedThreadSafe<ExternalInstallDialogDelegate> {
  public:
   ExternalInstallDialogDelegate(Browser* browser,
@@ -88,6 +89,11 @@
   virtual void OnWebstoreResponseParseFailure(
       const std::string& error) OVERRIDE;
 
+  // NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
   // Show the install dialog to the user.
   void ShowInstallUI();
 
@@ -98,6 +104,7 @@
   Browser* browser_;
   base::WeakPtr<ExtensionService> service_weak_;
   scoped_ptr<WebstoreDataFetcher> webstore_data_fetcher_;
+  content::NotificationRegistrar registrar_;
   std::string extension_id_;
   bool use_global_error_;
 
@@ -230,6 +237,11 @@
     return;
   }
 
+  // Make sure to be notified if the owning profile is destroyed.
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_PROFILE_DESTROYED,
+                 content::Source<Profile>(browser->profile()));
+
   webstore_data_fetcher_.reset(new WebstoreDataFetcher(
       this,
       browser->profile()->GetRequestContext(),
@@ -272,6 +284,15 @@
   ShowInstallUI();
 }
 
+void ExternalInstallDialogDelegate::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  DCHECK_EQ(type, chrome::NOTIFICATION_PROFILE_DESTROYED);
+  // If the owning profile is destroyed, we need to abort so that we don't leak.
+  InstallUIAbort(false);  // Not user initiated.
+}
+
 void ExternalInstallDialogDelegate::ShowInstallUI() {
   const Extension* extension = NULL;
   if (!service_weak_.get() ||
@@ -296,21 +317,19 @@
 
 void ExternalInstallDialogDelegate::InstallUIProceed() {
   const Extension* extension = NULL;
-  if (!service_weak_.get() ||
-      !(extension = service_weak_->GetInstalledExtension(extension_id_))) {
-    return;
+  if (service_weak_.get() &&
+      (extension = service_weak_->GetInstalledExtension(extension_id_))) {
+    service_weak_->GrantPermissionsAndEnableExtension(extension);
   }
-  service_weak_->GrantPermissionsAndEnableExtension(extension);
   Release();
 }
 
 void ExternalInstallDialogDelegate::InstallUIAbort(bool user_initiated) {
   const Extension* extension = NULL;
-  if (!service_weak_.get() ||
-      !(extension = service_weak_->GetInstalledExtension(extension_id_))) {
-    return;
+  if (service_weak_.get() &&
+      (extension = service_weak_->GetInstalledExtension(extension_id_))) {
+    service_weak_->UninstallExtension(extension_id_, false, NULL);
   }
-  service_weak_->UninstallExtension(extension_id_, false, NULL);
   Release();
 }
 
diff --git a/chrome/browser/extensions/external_policy_loader_unittest.cc b/chrome/browser/extensions/external_policy_loader_unittest.cc
index 74d00d5..323d1b9 100644
--- a/chrome/browser/extensions/external_policy_loader_unittest.cc
+++ b/chrome/browser/extensions/external_policy_loader_unittest.cc
@@ -78,8 +78,12 @@
   }
 
   virtual bool OnExternalExtensionUpdateUrlFound(
-      const std::string& id, const GURL& update_url,
-      Manifest::Location location, int unused1, bool unused2) OVERRIDE {
+      const std::string& id,
+      const std::string& install_parameter,
+      const GURL& update_url,
+      Manifest::Location location,
+      int unused1,
+      bool unused2) OVERRIDE {
     // Extension has the correct location.
     EXPECT_EQ(Manifest::EXTERNAL_POLICY_DOWNLOAD, location);
 
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc
index 4d49437..01cb62b 100644
--- a/chrome/browser/extensions/external_provider_impl.cc
+++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -55,6 +55,7 @@
 namespace extensions {
 
 // Constants for keeping track of extension preferences in a dictionary.
+const char ExternalProviderImpl::kInstallParam[] = "install_parameter";
 const char ExternalProviderImpl::kExternalCrx[] = "external_crx";
 const char ExternalProviderImpl::kExternalVersion[] = "external_version";
 const char ExternalProviderImpl::kExternalUpdateUrl[] = "external_update_url";
@@ -220,6 +221,9 @@
       }
     }
 
+    std::string install_parameter;
+    extension->GetString(kInstallParam, &install_parameter);
+
     if (has_external_crx) {
       if (crx_location_ == Manifest::INVALID_LOCATION) {
         LOG(WARNING) << "This provider does not support installing external "
@@ -271,9 +275,12 @@
                      << "\", which is not a valid URL.";
         continue;
       }
-      service_->OnExternalExtensionUpdateUrlFound(
-          extension_id, update_url, download_location_, creation_flags,
-          auto_acknowledge_);
+      service_->OnExternalExtensionUpdateUrlFound(extension_id,
+                                                  install_parameter,
+                                                  update_url,
+                                                  download_location_,
+                                                  creation_flags,
+                                                  auto_acknowledge_);
     }
   }
 
diff --git a/chrome/browser/extensions/external_provider_impl.h b/chrome/browser/extensions/external_provider_impl.h
index d96817b..8bb80ed 100644
--- a/chrome/browser/extensions/external_provider_impl.h
+++ b/chrome/browser/extensions/external_provider_impl.h
@@ -67,10 +67,11 @@
   static const char kExternalCrx[];
   static const char kExternalVersion[];
   static const char kExternalUpdateUrl[];
-  static const char kSupportedLocales[];
+  static const char kInstallParam[];
   static const char kIsBookmarkApp[];
   static const char kIsFromWebstore[];
   static const char kKeepIfPresent[];
+  static const char kSupportedLocales[];
 
   void set_auto_acknowledge(bool auto_acknowledge) {
     auto_acknowledge_ = auto_acknowledge;
diff --git a/chrome/browser/extensions/external_registry_loader_win.cc b/chrome/browser/extensions/external_registry_loader_win.cc
index d988f49..5bd5617 100644
--- a/chrome/browser/extensions/external_registry_loader_win.cc
+++ b/chrome/browser/extensions/external_registry_loader_win.cc
@@ -26,6 +26,9 @@
 // The Registry subkey that contains information about external extensions.
 const char kRegistryExtensions[] = "Software\\Google\\Chrome\\Extensions";
 
+// Registry value of the key that defines the installation parameter.
+const wchar_t kRegistryExtensionInstallParam[] = L"install_parameter";
+
 // Registry value of the key that defines the path to the .crx file.
 const wchar_t kRegistryExtensionPath[] = L"path";
 
@@ -94,6 +97,13 @@
       continue;
     }
 
+    base::string16 extension_dist_id;
+    if (key.ReadValue(kRegistryExtensionInstallParam, &extension_dist_id) ==
+        ERROR_SUCCESS) {
+      prefs->SetString(id + "." + ExternalProviderImpl::kInstallParam,
+                       base::UTF16ToASCII(extension_dist_id));
+    }
+
     // If there is an update URL present, copy it to prefs and ignore
     // path and version keys for this entry.
     base::string16 extension_update_url;
diff --git a/chrome/browser/extensions/global_shortcut_listener.cc b/chrome/browser/extensions/global_shortcut_listener.cc
index d37a166..925cb40 100644
--- a/chrome/browser/extensions/global_shortcut_listener.cc
+++ b/chrome/browser/extensions/global_shortcut_listener.cc
@@ -12,7 +12,8 @@
 
 namespace extensions {
 
-GlobalShortcutListener::GlobalShortcutListener() {
+GlobalShortcutListener::GlobalShortcutListener()
+    : shortcut_handling_suspended_(false) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 }
 
@@ -24,6 +25,8 @@
 bool GlobalShortcutListener::RegisterAccelerator(
     const ui::Accelerator& accelerator, Observer* observer) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (IsShortcutHandlingSuspended())
+    return false;
 
   AcceleratorMap::const_iterator it = accelerator_map_.find(accelerator);
   if (it != accelerator_map_.end()) {
@@ -47,6 +50,8 @@
 void GlobalShortcutListener::UnregisterAccelerator(
     const ui::Accelerator& accelerator, Observer* observer) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (IsShortcutHandlingSuspended())
+    return;
 
   AcceleratorMap::iterator it = accelerator_map_.find(accelerator);
   // We should never get asked to unregister something that we didn't register.
@@ -62,6 +67,8 @@
 
 void GlobalShortcutListener::UnregisterAccelerators(Observer* observer) {
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (IsShortcutHandlingSuspended())
+    return;
 
   AcceleratorMap::iterator it = accelerator_map_.begin();
   while (it != accelerator_map_.end()) {
@@ -74,6 +81,31 @@
   }
 }
 
+void GlobalShortcutListener::SetShortcutHandlingSuspended(bool suspended) {
+  CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (shortcut_handling_suspended_ == suspended)
+    return;
+
+  shortcut_handling_suspended_ = suspended;
+  for (AcceleratorMap::iterator it = accelerator_map_.begin();
+       it != accelerator_map_.end();
+       ++it) {
+    // On Linux, when shortcut handling is suspended we cannot simply early
+    // return in NotifyKeyPressed (similar to what we do for non-global
+    // shortcuts) because we'd eat the keyboard event thereby preventing the
+    // user from setting the shortcut. Therefore we must unregister while
+    // handling is suspended and register when handling resumes.
+    if (shortcut_handling_suspended_)
+      UnregisterAcceleratorImpl(it->first);
+    else
+      RegisterAcceleratorImpl(it->first);
+  }
+}
+
+bool GlobalShortcutListener::IsShortcutHandlingSuspended() const {
+  return shortcut_handling_suspended_;
+}
+
 void GlobalShortcutListener::NotifyKeyPressed(
     const ui::Accelerator& accelerator) {
   AcceleratorMap::iterator iter = accelerator_map_.find(accelerator);
diff --git a/chrome/browser/extensions/global_shortcut_listener.h b/chrome/browser/extensions/global_shortcut_listener.h
index 7d5ab0e..1f07df2 100644
--- a/chrome/browser/extensions/global_shortcut_listener.h
+++ b/chrome/browser/extensions/global_shortcut_listener.h
@@ -32,21 +32,33 @@
   static GlobalShortcutListener* GetInstance();
 
   // Register an observer for when a certain |accelerator| is struck. Returns
-  // true if register successfully, or false if the specificied |accelerator|
-  // has been registered by another caller or other native applications. Note
-  // that we do not support recognizing that an accelerator has been registered
-  // by another application on all platforms. This is a per-platform
+  // true if register successfully, or false if 1) the specificied |accelerator|
+  // has been registered by another caller or other native applications, or
+  // 2) shortcut handling is suspended.
+  //
+  // Note that we do not support recognizing that an accelerator has been
+  // registered by another application on all platforms. This is a per-platform
   // consideration.
   bool RegisterAccelerator(const ui::Accelerator& accelerator,
                            Observer* observer);
 
-  // Stop listening for the given |accelerator|.
+  // Stop listening for the given |accelerator|, does nothing if shortcut
+  // handling is suspended.
   void UnregisterAccelerator(const ui::Accelerator& accelerator,
                              Observer* observer);
 
-  // Stop listening for all accelerators of the given |observer|.
+  // Stop listening for all accelerators of the given |observer|, does nothing
+  // if shortcut handling is suspended.
   void UnregisterAccelerators(Observer* observer);
 
+  // Suspend/Resume global shortcut handling. Note that when suspending,
+  // RegisterAccelerator/UnregisterAccelerator/UnregisterAccelerators are not
+  // allowed to be called until shortcut handling has been resumed.
+  void SetShortcutHandlingSuspended(bool suspended);
+
+  // Returns whether shortcut handling is currently suspended.
+  bool IsShortcutHandlingSuspended() const;
+
  protected:
   GlobalShortcutListener();
 
@@ -76,6 +88,9 @@
   typedef std::map<ui::Accelerator, Observer*> AcceleratorMap;
   AcceleratorMap accelerator_map_;
 
+  // Keeps track of whether shortcut handling is currently suspended.
+  bool shortcut_handling_suspended_;
+
   DISALLOW_COPY_AND_ASSIGN(GlobalShortcutListener);
 };
 
diff --git a/chrome/browser/extensions/image_loader.cc b/chrome/browser/extensions/image_loader.cc
index c6c732e..8c39052 100644
--- a/chrome/browser/extensions/image_loader.cc
+++ b/chrome/browser/extensions/image_loader.cc
@@ -71,7 +71,7 @@
 }
 
 void LoadResourceOnUIThread(int resource_id, SkBitmap* bitmap) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   gfx::ImageSkia image(
       *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id));
@@ -320,7 +320,7 @@
     const Extension* extension,
     const std::vector<ImageRepresentation>& info_list,
     const ImageLoaderImageCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
   base::PostTaskAndReplyWithResult(
       BrowserThread::GetBlockingPool(),
@@ -336,7 +336,7 @@
     const extensions::Extension* extension,
     const std::vector<ImageRepresentation>& info_list,
     const ImageLoaderImageFamilyCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
   base::PostTaskAndReplyWithResult(
       BrowserThread::GetBlockingPool(),
@@ -351,7 +351,7 @@
 
 void ImageLoader::ReplyBack(const ImageLoaderImageCallback& callback,
                             const std::vector<LoadResult>& load_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   gfx::ImageSkia image_skia;
 
@@ -377,7 +377,7 @@
 void ImageLoader::ReplyBackWithImageFamily(
     const ImageLoaderImageFamilyCallback& callback,
     const std::vector<LoadResult>& load_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   std::map<std::pair<int, int>, gfx::ImageSkia> image_skia_map;
   gfx::ImageFamily image_family;
diff --git a/chrome/browser/extensions/install_observer.cc b/chrome/browser/extensions/install_observer.cc
index d713a09..37c7565 100644
--- a/chrome/browser/extensions/install_observer.cc
+++ b/chrome/browser/extensions/install_observer.cc
@@ -19,19 +19,4 @@
           is_platform_app(is_platform_app),
           is_ephemeral(false) {}
 
-void InstallObserver::OnBeginExtensionInstall(
-    const ExtensionInstallParams& params) {}
-void InstallObserver::OnDownloadProgress(const std::string& extension_id,
-                                         int percent_downloaded) {}
-void InstallObserver::OnInstallFailure(const std::string& extension_id) {}
-void InstallObserver::OnExtensionInstalled(const Extension* extension) {}
-void InstallObserver::OnExtensionLoaded(const Extension* extension) {}
-void InstallObserver::OnExtensionUnloaded(const Extension* extension) {}
-void InstallObserver::OnExtensionUninstalled(const Extension* extension) {}
-void InstallObserver::OnDisabledExtensionUpdated(const Extension* extension) {}
-void InstallObserver::OnAppInstalledToAppList(const std::string& extension_id) {
-}
-void InstallObserver::OnAppsReordered() {}
-void InstallObserver::OnShutdown() {}
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/install_observer.h b/chrome/browser/extensions/install_observer.h
index 72a7a09..1823170 100644
--- a/chrome/browser/extensions/install_observer.h
+++ b/chrome/browser/extensions/install_observer.h
@@ -33,35 +33,44 @@
 
   // Called at the beginning of the complete installation process, i.e., this
   // is called before the extension download begins.
-  virtual void OnBeginExtensionInstall(const ExtensionInstallParams& params);
+  virtual void OnBeginExtensionInstall(const ExtensionInstallParams& params) {}
+
+  // Called when the Extension begins the download process. This typically
+  // happens right after OnBeginExtensionInstall(), unless the extension has
+  // already been downloaded.
+  virtual void OnBeginExtensionDownload(const std::string& extension_id) {}
 
   // Called whenever the extension download is updated.
   // Note: Some extensions have multiple modules, so the percent included here
   // is a simple calculation of:
   // (finished_files * 100 + current_file_progress) / (total files * 100).
   virtual void OnDownloadProgress(const std::string& extension_id,
-                                  int percent_downloaded);
+                                  int percent_downloaded) {}
+
+  // Called when the necessary downloads have completed, and the crx
+  // installation is due to start.
+  virtual void OnBeginCrxInstall(const std::string& extension_id) {}
 
   // Called if the extension fails to install.
-  virtual void OnInstallFailure(const std::string& extension_id);
+  virtual void OnInstallFailure(const std::string& extension_id) {}
 
   // Called if the installation succeeds.
-  virtual void OnExtensionInstalled(const Extension* extension);
+  virtual void OnExtensionInstalled(const Extension* extension) {}
 
   // Called when an extension is [Loaded, Unloaded, Uninstalled] or an app is
   // installed to the app list. These are simply forwarded from the
   // chrome::NOTIFICATIONs.
-  virtual void OnExtensionLoaded(const Extension* extension);
-  virtual void OnExtensionUnloaded(const Extension* extension);
-  virtual void OnExtensionUninstalled(const Extension* extension);
-  virtual void OnDisabledExtensionUpdated(const Extension* extension);
-  virtual void OnAppInstalledToAppList(const std::string& extension_id);
+  virtual void OnExtensionLoaded(const Extension* extension) {}
+  virtual void OnExtensionUnloaded(const Extension* extension) {}
+  virtual void OnExtensionUninstalled(const Extension* extension) {}
+  virtual void OnDisabledExtensionUpdated(const Extension* extension) {}
+  virtual void OnAppInstalledToAppList(const std::string& extension_id) {}
 
   // Called when the app list is reordered.
-  virtual void OnAppsReordered();
+  virtual void OnAppsReordered() {}
 
   // Notifies observers that the observed object is going away.
-  virtual void OnShutdown();
+  virtual void OnShutdown() {}
 
  protected:
   virtual ~InstallObserver() {}
diff --git a/chrome/browser/extensions/install_tracker.cc b/chrome/browser/extensions/install_tracker.cc
index 0c79c1c..fc5b504 100644
--- a/chrome/browser/extensions/install_tracker.cc
+++ b/chrome/browser/extensions/install_tracker.cc
@@ -56,12 +56,22 @@
                     OnBeginExtensionInstall(params));
 }
 
+void InstallTracker::OnBeginExtensionDownload(const std::string& extension_id) {
+  FOR_EACH_OBSERVER(
+      InstallObserver, observers_, OnBeginExtensionDownload(extension_id));
+}
+
 void InstallTracker::OnDownloadProgress(const std::string& extension_id,
                                         int percent_downloaded) {
   FOR_EACH_OBSERVER(InstallObserver, observers_,
                     OnDownloadProgress(extension_id, percent_downloaded));
 }
 
+void InstallTracker::OnBeginCrxInstall(const std::string& extension_id) {
+  FOR_EACH_OBSERVER(
+      InstallObserver, observers_, OnBeginCrxInstall(extension_id));
+}
+
 void InstallTracker::OnInstallFailure(
     const std::string& extension_id) {
   FOR_EACH_OBSERVER(InstallObserver, observers_,
diff --git a/chrome/browser/extensions/install_tracker.h b/chrome/browser/extensions/install_tracker.h
index 3997370..d3101d2 100644
--- a/chrome/browser/extensions/install_tracker.h
+++ b/chrome/browser/extensions/install_tracker.h
@@ -30,8 +30,10 @@
 
   void OnBeginExtensionInstall(
       const InstallObserver::ExtensionInstallParams& params);
+  void OnBeginExtensionDownload(const std::string& extension_id);
   void OnDownloadProgress(const std::string& extension_id,
                           int percent_downloaded);
+  void OnBeginCrxInstall(const std::string& extension_id);
   void OnInstallFailure(const std::string& extension_id);
 
   // Overriddes for KeyedService:
diff --git a/chrome/browser/extensions/install_verifier.cc b/chrome/browser/extensions/install_verifier.cc
index bab1f9d..d035436 100644
--- a/chrome/browser/extensions/install_verifier.cc
+++ b/chrome/browser/extensions/install_verifier.cc
@@ -13,17 +13,25 @@
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/install_signer.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/manifest_url_handler.h"
 #include "chrome/common/pref_names.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/common/content_switches.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
 #include "extensions/browser/pref_names.h"
+#include "extensions/common/extension_set.h"
 #include "extensions/common/manifest.h"
+#include "extensions/common/one_shot_event.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
+namespace extensions {
+
 namespace {
 
 enum VerifyStatus {
@@ -71,7 +79,7 @@
 
 VerifyStatus GetCommandLineStatus() {
   const CommandLine* cmdline = CommandLine::ForCurrentProcess();
-  if (!extensions::InstallSigner::GetForcedNotFromWebstore().empty())
+  if (!InstallSigner::GetForcedNotFromWebstore().empty())
     return ENFORCE;
 
   if (cmdline->HasSwitch(switches::kExtensionsInstallVerification)) {
@@ -99,19 +107,6 @@
   return GetStatus() == ENFORCE;
 }
 
-}  // namespace
-
-namespace extensions {
-
-InstallVerifier::InstallVerifier(ExtensionPrefs* prefs,
-                                 net::URLRequestContextGetter* context_getter)
-    : prefs_(prefs), context_getter_(context_getter) {
-}
-
-InstallVerifier::~InstallVerifier() {}
-
-namespace {
-
 enum InitResult {
   INIT_NO_PREF = 0,
   INIT_UNPARSEABLE_PREF,
@@ -146,8 +141,51 @@
   return extension.is_extension() || extension.is_legacy_packaged_app();
 }
 
+enum VerifyAllSuccess {
+  VERIFY_ALL_BOOTSTRAP_SUCCESS = 0,
+  VERIFY_ALL_BOOTSTRAP_FAILURE,
+  VERIFY_ALL_NON_BOOTSTRAP_SUCCESS,
+  VERIFY_ALL_NON_BOOTSTRAP_FAILURE,
+
+  // Used in histograms. Do not remove/reorder any entries above, and the below
+  // MAX entry should always come last.
+  VERIFY_ALL_SUCCESS_MAX
+};
+
+// Record the success or failure of verifying all extensions, and whether or
+// not it was a bootstrapping.
+void LogVerifyAllSuccessHistogram(bool bootstrap, bool success) {
+  VerifyAllSuccess result;
+  if (bootstrap && success)
+    result = VERIFY_ALL_BOOTSTRAP_SUCCESS;
+  else if (bootstrap && !success)
+    result = VERIFY_ALL_BOOTSTRAP_FAILURE;
+  else if (!bootstrap && success)
+    result = VERIFY_ALL_NON_BOOTSTRAP_SUCCESS;
+  else
+    result = VERIFY_ALL_NON_BOOTSTRAP_FAILURE;
+
+  // This used to be part of ExtensionService, but moved here. In order to keep
+  // our histograms accurate, the name is unchanged.
+  UMA_HISTOGRAM_ENUMERATION(
+      "ExtensionService.VerifyAllSuccess", result, VERIFY_ALL_SUCCESS_MAX);
+}
+
+// Record the success or failure of a single verification.
+void LogAddVerifiedSuccess(bool success) {
+  // This used to be part of ExtensionService, but moved here. In order to keep
+  // our histograms accurate, the name is unchanged.
+  UMA_HISTOGRAM_BOOLEAN("ExtensionService.AddVerified", success);
+}
+
 }  // namespace
 
+InstallVerifier::InstallVerifier(ExtensionPrefs* prefs,
+                                 content::BrowserContext* context)
+    : prefs_(prefs), context_(context), weak_factory_(this) {}
+
+InstallVerifier::~InstallVerifier() {}
+
 // static
 bool InstallVerifier::NeedsVerification(const Extension& extension) {
   return FromStore(extension) && CanUseExtensionApis(extension);
@@ -178,10 +216,15 @@
   } else {
     LogInitResultHistogram(INIT_NO_PREF);
   }
+
+  ExtensionSystem::Get(context_)->ready().Post(
+      FROM_HERE,
+      base::Bind(&InstallVerifier::MaybeBootstrapSelf,
+                 weak_factory_.GetWeakPtr()));
 }
 
-bool InstallVerifier::NeedsBootstrap() {
-  return signature_.get() == NULL && ShouldFetchSignature();
+void InstallVerifier::VerifyAllExtensions() {
+  AddMany(GetExtensionsToVerify(), ADD_ALL);
 }
 
 base::Time InstallVerifier::SignatureTimestamp() {
@@ -196,18 +239,15 @@
                               ContainsKey(signature_->invalid_ids, id));
 }
 
-void InstallVerifier::Add(const std::string& id,
-                          const AddResultCallback& callback) {
+void InstallVerifier::VerifyExtension(const std::string& extension_id) {
   ExtensionIdSet ids;
-  ids.insert(id);
-  AddMany(ids, callback);
+  ids.insert(extension_id);
+  AddMany(ids, ADD_SINGLE);
 }
 
-void InstallVerifier::AddMany(const ExtensionIdSet& ids,
-                              const AddResultCallback& callback) {
+void InstallVerifier::AddMany(const ExtensionIdSet& ids, OperationType type) {
   if (!ShouldFetchSignature()) {
-    if (!callback.is_null())
-      callback.Run(true);
+    OnVerificationComplete(true, type);  // considered successful.
     return;
   }
 
@@ -215,17 +255,14 @@
     ExtensionIdSet not_allowed_yet =
         base::STLSetDifference<ExtensionIdSet>(ids, signature_->ids);
     if (not_allowed_yet.empty()) {
-      if (!callback.is_null())
-        callback.Run(true);
+      OnVerificationComplete(true, type);  // considered successful.
       return;
     }
   }
 
   InstallVerifier::PendingOperation* operation =
-    new InstallVerifier::PendingOperation();
-  operation->type = InstallVerifier::ADD;
+      new InstallVerifier::PendingOperation(type);
   operation->ids.insert(ids.begin(), ids.end());
-  operation->callback = callback;
 
   operation_queue_.push(linked_ptr<PendingOperation>(operation));
 
@@ -236,7 +273,7 @@
 
 void InstallVerifier::AddProvisional(const ExtensionIdSet& ids) {
   provisional_.insert(ids.begin(), ids.end());
-  AddMany(ids, AddResultCallback());
+  AddMany(ids, ADD_PROVISIONAL);
 }
 
 void InstallVerifier::Remove(const std::string& id) {
@@ -261,8 +298,7 @@
     return;
 
   InstallVerifier::PendingOperation* operation =
-    new InstallVerifier::PendingOperation();
-  operation->type = InstallVerifier::REMOVE;
+      new InstallVerifier::PendingOperation(InstallVerifier::REMOVE);
   operation->ids = ids;
 
   operation_queue_.push(linked_ptr<PendingOperation>(operation));
@@ -334,9 +370,8 @@
   } else if (signature_.get() == NULL) {
     // If we don't have a signature yet, we'll temporarily consider every
     // extension from the webstore verified to avoid false positives on existing
-    // profiles hitting this code for the first time, and rely on consumers of
-    // this class to check NeedsBootstrap() and schedule a first check so we can
-    // get a signature.
+    // profiles hitting this code for the first time. The InstallVerifier
+    // will bootstrap itself once the ExtensionsSystem is ready.
     outcome = NO_SIGNATURE;
   } else if (!IsVerified(extension->id())) {
     if (!ContainsKey(signature_->invalid_ids, extension->id())) {
@@ -363,13 +398,84 @@
   return !verified;
 }
 
-InstallVerifier::PendingOperation::PendingOperation() {
-  type = InstallVerifier::ADD;
-}
+InstallVerifier::PendingOperation::PendingOperation(OperationType type)
+    : type(type) {}
 
 InstallVerifier::PendingOperation::~PendingOperation() {
 }
 
+ExtensionIdSet InstallVerifier::GetExtensionsToVerify() const {
+  ExtensionIdSet result;
+  scoped_ptr<ExtensionSet> extensions =
+      ExtensionRegistry::Get(context_)->GenerateInstalledExtensionsSet();
+  for (ExtensionSet::const_iterator iter = extensions->begin();
+       iter != extensions->end();
+       ++iter) {
+    if (NeedsVerification(**iter))
+      result.insert((*iter)->id());
+  }
+  return result;
+}
+
+void InstallVerifier::MaybeBootstrapSelf() {
+  bool needs_bootstrap = false;
+
+  ExtensionIdSet extension_ids = GetExtensionsToVerify();
+  if (signature_.get() == NULL && ShouldFetchSignature()) {
+    needs_bootstrap = true;
+  } else {
+    for (ExtensionIdSet::const_iterator iter = extension_ids.begin();
+         iter != extension_ids.end();
+         ++iter) {
+      if (!IsKnownId(*iter)) {
+        needs_bootstrap = true;
+        break;
+      }
+    }
+  }
+
+  if (needs_bootstrap)
+    AddMany(extension_ids, ADD_ALL_BOOTSTRAP);
+}
+
+void InstallVerifier::OnVerificationComplete(bool success,
+                                             OperationType type) const {
+  switch (type) {
+    case ADD_SINGLE:
+      LogAddVerifiedSuccess(success);
+      break;
+    case ADD_ALL:
+    case ADD_ALL_BOOTSTRAP:
+      LogVerifyAllSuccessHistogram(type == ADD_ALL_BOOTSTRAP, success);
+      if (success) {
+        // Iterate through the extensions and, if any are newly-verified and
+        // should have the DISABLE_NOT_VERIFIED reason lifted, do so.
+        const ExtensionSet& disabled_extensions =
+            ExtensionRegistry::Get(context_)->disabled_extensions();
+        for (ExtensionSet::const_iterator iter = disabled_extensions.begin();
+             iter != disabled_extensions.end();
+             ++iter) {
+          int disable_reasons = prefs_->GetDisableReasons((*iter)->id());
+          if (disable_reasons & Extension::DISABLE_NOT_VERIFIED &&
+              !MustRemainDisabled(*iter, NULL, NULL)) {
+            prefs_->RemoveDisableReason((*iter)->id(),
+                                        Extension::DISABLE_NOT_VERIFIED);
+          }
+        }
+
+        ExtensionSystem::Get(context_)
+            ->extension_service()
+            ->CheckManagementPolicy();
+      }
+      break;
+    // We don't need to check disable reasons or report UMA stats for
+    // provisional adds or removals.
+    case ADD_PROVISIONAL:
+    case REMOVE:
+      break;
+  }
+}
+
 void InstallVerifier::GarbageCollect() {
   if (!ShouldFetchSignature()) {
     return;
@@ -419,7 +525,7 @@
 
   // TODO(asargent) - It would be possible to coalesce all operations in the
   // queue into one fetch - we'd probably just need to change the queue to
-  // hold (set of ids, list of callbacks) pairs.
+  // hold (set of ids, list of operation type) pairs.
   CHECK(!operation_queue_.empty());
   const PendingOperation& operation = *operation_queue_.front();
 
@@ -427,19 +533,19 @@
   if (signature_.get()) {
     ids_to_sign.insert(signature_->ids.begin(), signature_->ids.end());
   }
-  if (operation.type == InstallVerifier::ADD) {
-    ids_to_sign.insert(operation.ids.begin(), operation.ids.end());
-  } else {
+  if (operation.type == InstallVerifier::REMOVE) {
     for (ExtensionIdSet::const_iterator i = operation.ids.begin();
          i != operation.ids.end(); ++i) {
       if (ContainsKey(ids_to_sign, *i))
         ids_to_sign.erase(*i);
     }
+  } else {  // All other operation types are some form of "ADD".
+    ids_to_sign.insert(operation.ids.begin(), operation.ids.end());
   }
 
-  signer_.reset(new InstallSigner(context_getter_, ids_to_sign));
+  signer_.reset(new InstallSigner(context_->GetRequestContext(), ids_to_sign));
   signer_->GetSignature(base::Bind(&InstallVerifier::SignatureCallback,
-                                   base::Unretained(this)));
+                                   weak_factory_.GetWeakPtr()));
 }
 
 void InstallVerifier::SaveToPrefs() {
@@ -501,8 +607,7 @@
   }
 
   if (!success) {
-    if (!operation->callback.is_null())
-      operation->callback.Run(false);
+    OnVerificationComplete(false, operation->type);
 
     // TODO(asargent) - if this was something like a network error, we need to
     // do retries with exponential back off.
@@ -516,13 +621,11 @@
           provisional_, signature_->ids);
     }
 
-    if (!operation->callback.is_null())
-      operation->callback.Run(success);
+    OnVerificationComplete(success, operation->type);
   }
 
   if (!operation_queue_.empty())
     BeginFetch();
 }
 
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/install_verifier.h b/chrome/browser/extensions/install_verifier.h
index 62885ce..60621d6 100644
--- a/chrome/browser/extensions/install_verifier.h
+++ b/chrome/browser/extensions/install_verifier.h
@@ -13,9 +13,14 @@
 #include "base/callback.h"
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "extensions/browser/management_policy.h"
 #include "extensions/common/extension.h"
 
+namespace content {
+class BrowserContext;
+}
+
 namespace net {
 class URLRequestContextGetter;
 }
@@ -37,8 +42,7 @@
 // extensions installed from the webstore.
 class InstallVerifier : public ManagementPolicy::Provider {
  public:
-  InstallVerifier(ExtensionPrefs* prefs,
-                  net::URLRequestContextGetter* context_getter);
+  InstallVerifier(ExtensionPrefs* prefs, content::BrowserContext* context);
   virtual ~InstallVerifier();
 
   // Returns whether |extension| is of a type that needs verification.
@@ -48,11 +52,6 @@
   // validating the stored signature.
   void Init();
 
-  // Do we need to be bootstrapped? (i.e. do we have a signature already). If
-  // this is true, then consumers of this class should use Add/AddMany to get
-  // an initial one so that MustRemainDisabled can actually check against it.
-  bool NeedsBootstrap();
-
   // Returns the timestamp of our InstallSignature, if we have one.
   base::Time SignatureTimestamp();
 
@@ -60,15 +59,11 @@
   // tells us that it was invalid when we asked the server about it.
   bool IsKnownId(const std::string& id);
 
-  // A callback for indicating success/failure of adding new ids.
-  typedef base::Callback<void(bool)> AddResultCallback;
+  // Attempts to verify a single extension and add it to the verified list.
+  void VerifyExtension(const std::string& extension_id);
 
-  // Try adding a new |id| (or set of ids) to the list of verified ids. When
-  // this process is finished |callback| will be run with success/failure of
-  // the signature request (not necessarily whether the ids were verified).
-  void Add(const std::string& id, const AddResultCallback& callback);
-  void AddMany(const ExtensionIdSet& ids,
-               const AddResultCallback& callback);
+  // Attempts to verify all extensions.
+  void VerifyAllExtensions();
 
   // Call this to add a set of ids that will immediately be considered allowed,
   // and kick off an aysnchronous request to Add.
@@ -85,11 +80,13 @@
                                   base::string16* error) const OVERRIDE;
 
  private:
-  // We keep a list of operations to the current set of extensions - either
-  // additions or removals.
+  // We keep a list of operations to the current set of extensions.
   enum OperationType {
-    ADD,
-    REMOVE
+    ADD_SINGLE,         // Adding a single extension to be verified.
+    ADD_ALL,            // Adding all extensions to be verified.
+    ADD_ALL_BOOTSTRAP,  // Adding all extensions because of a bootstrapping.
+    ADD_PROVISIONAL,    // Adding one or more provisionally-allowed extensions.
+    REMOVE              // Remove one or more extensions.
   };
 
   // This is an operation we want to apply to the current set of verified ids.
@@ -99,12 +96,25 @@
     // This is the set of ids being either added or removed.
     ExtensionIdSet ids;
 
-    AddResultCallback callback;
-
-    explicit PendingOperation();
+    explicit PendingOperation(OperationType type);
     ~PendingOperation();
   };
 
+  // Returns the set of IDs for all extensions that potentially need to be
+  // verified.
+  ExtensionIdSet GetExtensionsToVerify() const;
+
+  // Bootstrap the InstallVerifier if we do not already have a signature, or if
+  // there are unknown extensions which need to be verified.
+  void MaybeBootstrapSelf();
+
+  // Try adding a new set of |ids| to the list of verified ids.
+  void AddMany(const ExtensionIdSet& ids, OperationType type);
+
+  // Record the result of the verification for the histograms, and notify the
+  // ExtensionPrefs if we verified all extensions.
+  void OnVerificationComplete(bool success, OperationType type) const;
+
   // Removes any no-longer-installed ids, requesting a new signature if needed.
   void GarbageCollect();
 
@@ -130,7 +140,9 @@
   void SignatureCallback(scoped_ptr<InstallSignature> signature);
 
   ExtensionPrefs* prefs_;
-  net::URLRequestContextGetter* context_getter_;
+
+  // The context with which the InstallVerifier is associated.
+  content::BrowserContext* context_;
 
   // This is the most up-to-date signature, read out of |prefs_| during
   // initialization and updated anytime we get new id's added.
@@ -146,6 +158,8 @@
   // consider allowed until we hear back from the server signature request.
   ExtensionIdSet provisional_;
 
+  base::WeakPtrFactory<InstallVerifier> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(InstallVerifier);
 };
 
diff --git a/chrome/browser/extensions/menu_manager.cc b/chrome/browser/extensions/menu_manager.cc
index e0bffce..27accff 100644
--- a/chrome/browser/extensions/menu_manager.cc
+++ b/chrome/browser/extensions/menu_manager.cc
@@ -13,7 +13,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/extensions/menu_manager_factory.h"
@@ -298,6 +297,10 @@
   return true;
 }
 
+// static
+const char MenuManager::kOnContextMenus[] = "contextMenus";
+const char MenuManager::kOnWebviewContextMenus[] = "webview.contextMenus";
+
 MenuManager::MenuManager(Profile* profile, StateStore* store)
     : profile_(profile), store_(store) {
   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
@@ -699,8 +702,8 @@
   {
     // Dispatch to menu item's .onclick handler.
     scoped_ptr<Event> event(
-        new Event(webview_guest ? event_names::kOnWebviewContextMenus
-                                : event_names::kOnContextMenus,
+        new Event(webview_guest ? kOnWebviewContextMenus
+                                : kOnContextMenus,
                   scoped_ptr<base::ListValue>(args->DeepCopy())));
     event->restrict_to_browser_context = profile;
     event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
diff --git a/chrome/browser/extensions/menu_manager.h b/chrome/browser/extensions/menu_manager.h
index e25e58a..9fdf1168 100644
--- a/chrome/browser/extensions/menu_manager.h
+++ b/chrome/browser/extensions/menu_manager.h
@@ -269,6 +269,9 @@
                     public base::SupportsWeakPtr<MenuManager>,
                     public KeyedService {
  public:
+  static const char kOnContextMenus[];
+  static const char kOnWebviewContextMenus[];
+
   MenuManager(Profile* profile, StateStore* store_);
   virtual ~MenuManager();
 
diff --git a/chrome/browser/extensions/menu_manager_unittest.cc b/chrome/browser/extensions/menu_manager_unittest.cc
index 3a9d37d..3b16b7f 100644
--- a/chrome/browser/extensions/menu_manager_unittest.cc
+++ b/chrome/browser/extensions/menu_manager_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_system_factory.h"
 #include "chrome/browser/extensions/menu_manager.h"
 #include "chrome/browser/extensions/test_extension_prefs.h"
@@ -586,15 +585,14 @@
   {
     InSequence s;
     EXPECT_CALL(*mock_event_router,
-                DispatchEventToExtensionMock(
-                    item->extension_id(),
-                    extensions::event_names::kOnContextMenus,
-                    _,
-                    &profile,
-                    GURL(),
-                    EventRouter::USER_GESTURE_ENABLED))
-      .Times(1)
-      .WillOnce(SaveArg<2>(&list));
+                DispatchEventToExtensionMock(item->extension_id(),
+                                             MenuManager::kOnContextMenus,
+                                             _,
+                                             &profile,
+                                             GURL(),
+                                             EventRouter::USER_GESTURE_ENABLED))
+        .Times(1)
+        .WillOnce(SaveArg<2>(&list));
     EXPECT_CALL(*mock_event_router,
               DispatchEventToExtensionMock(
                   item->extension_id(),
diff --git a/chrome/browser/extensions/pending_extension_info.cc b/chrome/browser/extensions/pending_extension_info.cc
index bb0d452..0fa105b 100644
--- a/chrome/browser/extensions/pending_extension_info.cc
+++ b/chrome/browser/extensions/pending_extension_info.cc
@@ -10,6 +10,7 @@
 
 PendingExtensionInfo::PendingExtensionInfo(
     const std::string& id,
+    const std::string& install_parameter,
     const GURL& update_url,
     const Version& version,
     ShouldAllowInstallPredicate should_allow_install,
@@ -21,6 +22,7 @@
     : id_(id),
       update_url_(update_url),
       version_(version),
+      install_parameter_(install_parameter),
       should_allow_install_(should_allow_install),
       is_from_sync_(is_from_sync),
       install_silently_(install_silently),
@@ -35,6 +37,8 @@
       install_silently_(false),
       install_source_(Manifest::INVALID_LOCATION) {}
 
+PendingExtensionInfo::~PendingExtensionInfo() {}
+
 bool PendingExtensionInfo::operator==(const PendingExtensionInfo& rhs) const {
   return id_ == rhs.id_;
 }
diff --git a/chrome/browser/extensions/pending_extension_info.h b/chrome/browser/extensions/pending_extension_info.h
index fd803bd..a3ea47b 100644
--- a/chrome/browser/extensions/pending_extension_info.h
+++ b/chrome/browser/extensions/pending_extension_info.h
@@ -27,26 +27,29 @@
  public:
   typedef bool (*ShouldAllowInstallPredicate)(const Extension*);
 
-  PendingExtensionInfo(
-      const std::string& id,
-      const GURL& update_url,
-      const Version& version,
-      ShouldAllowInstallPredicate should_allow_install,
-      bool is_from_sync,
-      bool install_silently,
-      Manifest::Location install_source,
-      int creation_flags,
-      bool mark_acknowledged);
+  PendingExtensionInfo(const std::string& id,
+                       const std::string& install_parameter,
+                       const GURL& update_url,
+                       const Version& version,
+                       ShouldAllowInstallPredicate should_allow_install,
+                       bool is_from_sync,
+                       bool install_silently,
+                       Manifest::Location install_source,
+                       int creation_flags,
+                       bool mark_acknowledged);
 
   // Required for STL container membership.  Should not be used directly.
   PendingExtensionInfo();
 
+  ~PendingExtensionInfo();
+
   // Consider two PendingExtensionInfos equal if their ids are equal.
   bool operator==(const PendingExtensionInfo& rhs) const;
 
   const std::string& id() const { return id_; }
   const GURL& update_url() const { return update_url_; }
   const Version& version() const { return version_; }
+  const std::string& install_parameter() const { return install_parameter_; }
 
   // ShouldAllowInstall() returns the result of running constructor argument
   // |should_allow_install| on an extension. After an extension is unpacked,
@@ -75,6 +78,7 @@
 
   GURL update_url_;
   Version version_;
+  std::string install_parameter_;
 
   // When the extension is about to be installed, this function is
   // called.  If this function returns true, the install proceeds.  If
diff --git a/chrome/browser/extensions/pending_extension_manager.cc b/chrome/browser/extensions/pending_extension_manager.cc
index e2a636d..1a4ed42 100644
--- a/chrome/browser/extensions/pending_extension_manager.cc
+++ b/chrome/browser/extensions/pending_extension_manager.cc
@@ -10,6 +10,7 @@
 #include "base/version.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "content/public/browser/browser_thread.h"
+#include "extensions/browser/extension_prefs.h"
 #include "extensions/common/extension.h"
 #include "url/gurl.h"
 
@@ -31,9 +32,9 @@
 namespace extensions {
 
 PendingExtensionManager::PendingExtensionManager(
-    const ExtensionServiceInterface& service)
-    : service_(service) {
-}
+    const ExtensionServiceInterface& service,
+    content::BrowserContext* context)
+    : service_(service), context_(context) {}
 
 PendingExtensionManager::~PendingExtensionManager() {}
 
@@ -109,9 +110,16 @@
   const Manifest::Location kSyncLocation = Manifest::INTERNAL;
   const bool kMarkAcknowledged = false;
 
-  return AddExtensionImpl(id, update_url, Version(), should_allow_install,
-                          kIsFromSync, install_silently, kSyncLocation,
-                          Extension::NO_FLAGS, kMarkAcknowledged);
+  return AddExtensionImpl(id,
+                          std::string(),
+                          update_url,
+                          Version(),
+                          should_allow_install,
+                          kIsFromSync,
+                          install_silently,
+                          kSyncLocation,
+                          Extension::NO_FLAGS,
+                          kMarkAcknowledged);
 }
 
 bool PendingExtensionManager::AddFromExtensionImport(
@@ -131,13 +139,21 @@
   const Manifest::Location kManifestLocation = Manifest::INTERNAL;
   const bool kMarkAcknowledged = false;
 
-  return AddExtensionImpl(id, update_url, Version(), should_allow_install,
-                          kIsFromSync, kInstallSilently, kManifestLocation,
-                          Extension::NO_FLAGS, kMarkAcknowledged);
+  return AddExtensionImpl(id,
+                          std::string(),
+                          update_url,
+                          Version(),
+                          should_allow_install,
+                          kIsFromSync,
+                          kInstallSilently,
+                          kManifestLocation,
+                          Extension::NO_FLAGS,
+                          kMarkAcknowledged);
 }
 
 bool PendingExtensionManager::AddFromExternalUpdateUrl(
     const std::string& id,
+    const std::string& install_parameter,
     const GURL& update_url,
     Manifest::Location location,
     int creation_flags,
@@ -148,13 +164,12 @@
   const bool kInstallSilently = true;
 
   const Extension* extension = service_.GetInstalledExtension(id);
-  if (extension &&
-      location == Manifest::GetHigherPriorityLocation(location,
-                                                       extension->location())) {
+  if (extension && location == Manifest::GetHigherPriorityLocation(
+                                   location, extension->location())) {
     // If the new location has higher priority than the location of an existing
     // extension, let the update process overwrite the existing extension.
   } else {
-    if (service_.IsExternalExtensionUninstalled(id))
+    if (ExtensionPrefs::Get(context_)->IsExternalExtensionUninstalled(id))
       return false;
 
     if (extension) {
@@ -164,9 +179,16 @@
     }
   }
 
-  return AddExtensionImpl(id, update_url, Version(), &AlwaysInstall,
-                          kIsFromSync, kInstallSilently,
-                          location, creation_flags, mark_acknowledged);
+  return AddExtensionImpl(id,
+                          install_parameter,
+                          update_url,
+                          Version(),
+                          &AlwaysInstall,
+                          kIsFromSync,
+                          kInstallSilently,
+                          location,
+                          creation_flags,
+                          mark_acknowledged);
 }
 
 
@@ -184,16 +206,16 @@
   bool kIsFromSync = false;
   bool kInstallSilently = true;
 
-  return AddExtensionImpl(
-      id,
-      kUpdateUrl,
-      version,
-      &AlwaysInstall,
-      kIsFromSync,
-      kInstallSilently,
-      install_source,
-      creation_flags,
-      mark_acknowledged);
+  return AddExtensionImpl(id,
+                          std::string(),
+                          kUpdateUrl,
+                          version,
+                          &AlwaysInstall,
+                          kIsFromSync,
+                          kInstallSilently,
+                          install_source,
+                          creation_flags,
+                          mark_acknowledged);
 }
 
 void PendingExtensionManager::GetPendingIdsForUpdateCheck(
@@ -217,6 +239,7 @@
 
 bool PendingExtensionManager::AddExtensionImpl(
     const std::string& id,
+    const std::string& install_parameter,
     const GURL& update_url,
     const Version& version,
     PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
@@ -228,6 +251,7 @@
   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
   PendingExtensionInfo info(id,
+                            install_parameter,
                             update_url,
                             version,
                             should_allow_install,
diff --git a/chrome/browser/extensions/pending_extension_manager.h b/chrome/browser/extensions/pending_extension_manager.h
index 4c3572c..96dfa6e 100644
--- a/chrome/browser/extensions/pending_extension_manager.h
+++ b/chrome/browser/extensions/pending_extension_manager.h
@@ -18,6 +18,10 @@
 class Version;
 }
 
+namespace content {
+class BrowserContext;
+}
+
 FORWARD_DECLARE_TEST(ExtensionServiceTest,
                      UpdatePendingExtensionAlreadyInstalled);
 
@@ -43,7 +47,8 @@
   // extensions we are managing. The service creates an instance of
   // this class on construction, and destroys it on destruction.
   // The service remains valid over the entire lifetime of this class.
-  explicit PendingExtensionManager(const ExtensionServiceInterface& service);
+  explicit PendingExtensionManager(const ExtensionServiceInterface& service,
+                                   content::BrowserContext* context);
   ~PendingExtensionManager();
 
   // TODO(skerner): Many of these methods can be private once code in
@@ -90,6 +95,7 @@
   // Given an extension id and an update URL, schedule the extension
   // to be fetched, installed, and activated.
   bool AddFromExternalUpdateUrl(const std::string& id,
+                                const std::string& install_parameter,
                                 const GURL& update_url,
                                 Manifest::Location location,
                                 int creation_flags,
@@ -118,6 +124,7 @@
   // Return true if the extension was added.
   bool AddExtensionImpl(
       const std::string& id,
+      const std::string& install_parameter,
       const GURL& update_url,
       const base::Version& version,
       PendingExtensionInfo::ShouldAllowInstallPredicate should_allow_install,
@@ -138,6 +145,9 @@
   // ExtensionServiceInterface.
   const ExtensionServiceInterface& service_;
 
+  // The BrowserContext with which the manager is associated.
+  content::BrowserContext* context_;
+
   PendingExtensionList pending_extension_list_;
 
   FRIEND_TEST_ALL_PREFIXES(::ExtensionServiceTest,
diff --git a/chrome/browser/extensions/requirements_checker.cc b/chrome/browser/extensions/requirements_checker.cc
index 4eba575..c1bbadd 100644
--- a/chrome/browser/extensions/requirements_checker.cc
+++ b/chrome/browser/extensions/requirements_checker.cc
@@ -30,7 +30,7 @@
 
 void RequirementsChecker::Check(scoped_refptr<const Extension> extension,
     base::Callback<void(std::vector<std::string> errors)> callback) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   callback_ = callback;
   const RequirementsInfo& requirements =
diff --git a/chrome/browser/extensions/settings_api_bubble_controller.cc b/chrome/browser/extensions/settings_api_bubble_controller.cc
new file mode 100644
index 0000000..a5819bc
--- /dev/null
+++ b/chrome/browser/extensions/settings_api_bubble_controller.cc
@@ -0,0 +1,300 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/settings_api_bubble_controller.h"
+
+#include "base/metrics/histogram.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/startup/startup_browser_creator.h"
+#include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
+#include "chrome/common/url_constants.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using extensions::ExtensionMessageBubbleController;
+using extensions::SettingsApiBubbleController;
+using extensions::SettingsOverrides;
+
+namespace {
+
+////////////////////////////////////////////////////////////////////////////////
+// SettingsApiBubbleDelegate
+
+class SettingsApiBubbleDelegate
+    : public extensions::ExtensionMessageBubbleController::Delegate {
+ public:
+  explicit SettingsApiBubbleDelegate(ExtensionService* service,
+                                     Profile* profile,
+                                     extensions::SettingsApiOverrideType type);
+  virtual ~SettingsApiBubbleDelegate();
+
+  // ExtensionMessageBubbleController::Delegate methods.
+  virtual bool ShouldIncludeExtension(const std::string& extension_id) OVERRIDE;
+  virtual void AcknowledgeExtension(
+      const std::string& extension_id,
+      extensions::ExtensionMessageBubbleController::BubbleAction user_action)
+      OVERRIDE;
+  virtual void PerformAction(const extensions::ExtensionIdList& list) OVERRIDE;
+  virtual base::string16 GetTitle() const OVERRIDE;
+  virtual base::string16 GetMessageBody() const OVERRIDE;
+  virtual base::string16 GetOverflowText(
+      const base::string16& overflow_count) const OVERRIDE;
+  virtual base::string16 GetLearnMoreLabel() const OVERRIDE;
+  virtual GURL GetLearnMoreUrl() const OVERRIDE;
+  virtual base::string16 GetActionButtonLabel() const OVERRIDE;
+  virtual base::string16 GetDismissButtonLabel() const OVERRIDE;
+  virtual bool ShouldShowExtensionList() const OVERRIDE;
+  virtual void LogExtensionCount(size_t count) OVERRIDE;
+  virtual void LogAction(
+      extensions::ExtensionMessageBubbleController::BubbleAction action)
+      OVERRIDE;
+
+ private:
+  // Our extension service. Weak, not owned by us.
+  ExtensionService* service_;
+
+  // A weak pointer to the profile we are associated with. Not owned by us.
+  Profile* profile_;
+
+  // The type of settings override this bubble will report on. This can be, for
+  // example, a bubble to notify the user that the search engine has been
+  // changed by an extension (or homepage/startup pages/etc).
+  extensions::SettingsApiOverrideType type_;
+
+  // The ID of the extension we are showing the bubble for.
+  std::string extension_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(SettingsApiBubbleDelegate);
+};
+
+SettingsApiBubbleDelegate::SettingsApiBubbleDelegate(
+    ExtensionService* service,
+    Profile* profile,
+    extensions::SettingsApiOverrideType type)
+    : service_(service), profile_(profile), type_(type) {}
+
+SettingsApiBubbleDelegate::~SettingsApiBubbleDelegate() {}
+
+bool SettingsApiBubbleDelegate::ShouldIncludeExtension(
+    const std::string& extension_id) {
+  using extensions::ExtensionRegistry;
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
+  const extensions::Extension* extension =
+      registry->GetExtensionById(extension_id, ExtensionRegistry::ENABLED);
+  if (!extension)
+    return false;  // The extension provided is no longer enabled.
+
+  extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
+  if (prefs->HasSettingsApiBubbleBeenAcknowledged(extension_id))
+    return false;
+
+  const SettingsOverrides* settings = SettingsOverrides::Get(extension);
+  if (!settings)
+    return false;
+
+  bool should_include = false;
+  switch (type_) {
+    case extensions::BUBBLE_TYPE_HOME_PAGE:
+      should_include = settings->homepage != NULL;
+      break;
+    case extensions::BUBBLE_TYPE_STARTUP_PAGES:
+      should_include = !settings->startup_pages.empty();
+      break;
+    case extensions::BUBBLE_TYPE_SEARCH_ENGINE:
+      should_include = settings->search_engine != NULL;
+      break;
+  }
+
+  if (should_include && extension_id_ != extension_id) {
+    DCHECK(extension_id_.empty());
+    extension_id_ = extension_id;
+  }
+  return should_include;
+}
+
+void SettingsApiBubbleDelegate::AcknowledgeExtension(
+    const std::string& extension_id,
+    ExtensionMessageBubbleController::BubbleAction user_action) {
+  extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
+  prefs->SetSettingsApiBubbleBeenAcknowledged(extension_id, true);
+}
+
+void SettingsApiBubbleDelegate::PerformAction(
+    const extensions::ExtensionIdList& list) {
+  for (size_t i = 0; i < list.size(); ++i) {
+    service_->DisableExtension(list[i],
+                               extensions::Extension::DISABLE_USER_ACTION);
+  }
+}
+
+base::string16 SettingsApiBubbleDelegate::GetTitle() const {
+  switch (type_) {
+    case extensions::BUBBLE_TYPE_HOME_PAGE:
+      return l10n_util::GetStringUTF16(
+          IDS_EXTENSIONS_SETTINGS_API_TITLE_HOME_PAGE_BUBBLE);
+    case extensions::BUBBLE_TYPE_STARTUP_PAGES:
+      return l10n_util::GetStringUTF16(
+          IDS_EXTENSIONS_SETTINGS_API_TITLE_STARTUP_PAGES_BUBBLE);
+    case extensions::BUBBLE_TYPE_SEARCH_ENGINE:
+      return l10n_util::GetStringUTF16(
+          IDS_EXTENSIONS_SETTINGS_API_TITLE_SEARCH_ENGINE_BUBBLE);
+  }
+  NOTREACHED();
+  return base::string16();
+}
+
+base::string16 SettingsApiBubbleDelegate::GetMessageBody() const {
+  using extensions::ExtensionRegistry;
+  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
+  const extensions::Extension* extension =
+      registry->GetExtensionById(extension_id_, ExtensionRegistry::ENABLED);
+  const SettingsOverrides* settings =
+      extension ? SettingsOverrides::Get(extension) : NULL;
+  if (!extension || !settings) {
+    NOTREACHED();
+    return base::string16();
+  }
+
+  bool home_change = settings->homepage != NULL;
+  bool startup_change = !settings->startup_pages.empty();
+  bool search_change = settings->search_engine != NULL;
+
+  base::string16 body;
+  switch (type_) {
+    case extensions::BUBBLE_TYPE_HOME_PAGE:
+      body = l10n_util::GetStringUTF16(
+          IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_HOME_PAGE);
+      if (startup_change && search_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_SEARCH);
+      } else if (startup_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES);
+      } else if (search_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE);
+      }
+      break;
+    case extensions::BUBBLE_TYPE_STARTUP_PAGES:
+      body = l10n_util::GetStringUTF16(
+          IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_START_PAGES);
+      if (home_change && search_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_AND_SEARCH);
+      } else if (home_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_PAGE);
+      } else if (search_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_SEARCH_ENGINE);
+      }
+      break;
+    case extensions::BUBBLE_TYPE_SEARCH_ENGINE:
+      body = l10n_util::GetStringUTF16(
+          IDS_EXTENSIONS_SETTINGS_API_FIRST_LINE_SEARCH_ENGINE);
+      if (startup_change && home_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_AND_HOME);
+      } else if (startup_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_START_PAGES);
+      } else if (home_change) {
+        body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_SECOND_LINE_HOME_PAGE);
+      }
+      break;
+  }
+  if (!body.empty())
+    body += l10n_util::GetStringUTF16(
+            IDS_EXTENSIONS_SETTINGS_API_THIRD_LINE_CONFIRMATION);
+  return body;
+}
+
+base::string16 SettingsApiBubbleDelegate::GetOverflowText(
+    const base::string16& overflow_count) const {
+  // Does not have more than one extension in the list at a time.
+  NOTREACHED();
+  return base::string16();
+}
+
+base::string16 SettingsApiBubbleDelegate::GetLearnMoreLabel() const {
+  return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
+}
+
+GURL SettingsApiBubbleDelegate::GetLearnMoreUrl() const {
+  return GURL(chrome::kSettingsApiLearnMoreURL);
+}
+
+base::string16 SettingsApiBubbleDelegate::GetActionButtonLabel() const {
+  return l10n_util::GetStringUTF16(
+      IDS_EXTENSIONS_SETTINGS_API_RESTORE_SETTINGS);
+}
+
+base::string16 SettingsApiBubbleDelegate::GetDismissButtonLabel() const {
+  return l10n_util::GetStringUTF16(IDS_EXTENSIONS_SETTINGS_API_KEEP_CHANGES);
+}
+
+bool SettingsApiBubbleDelegate::ShouldShowExtensionList() const {
+  return false;
+}
+
+void SettingsApiBubbleDelegate::LogExtensionCount(size_t count) {
+  UMA_HISTOGRAM_COUNTS_100("SettingsApiBubble.ExtensionCount", count);
+}
+
+void SettingsApiBubbleDelegate::LogAction(
+    ExtensionMessageBubbleController::BubbleAction action) {
+  UMA_HISTOGRAM_ENUMERATION("SettingsApiBubble.UserSelection",
+                            action,
+                            ExtensionMessageBubbleController::ACTION_BOUNDARY);
+}
+
+}  // namespace
+
+namespace extensions {
+
+////////////////////////////////////////////////////////////////////////////////
+// SettingsApiBubbleController
+
+SettingsApiBubbleController::SettingsApiBubbleController(
+    Profile* profile,
+    SettingsApiOverrideType type)
+    : ExtensionMessageBubbleController(
+          new SettingsApiBubbleDelegate(
+              ExtensionSystem::Get(profile)->extension_service(),
+              profile,
+              type),
+          profile),
+      profile_(profile),
+      type_(type) {}
+
+SettingsApiBubbleController::~SettingsApiBubbleController() {}
+
+bool SettingsApiBubbleController::ShouldShow(const std::string& extension_id) {
+  extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_);
+  if (prefs->HasSettingsApiBubbleBeenAcknowledged(extension_id))
+    return false;
+
+  if (!delegate()->ShouldIncludeExtension(extension_id))
+    return false;
+
+  // If the browser is showing the 'Chrome crashed' infobar, it won't be showing
+  // the startup pages, so there's no point in showing the bubble now.
+  if (type_ == BUBBLE_TYPE_STARTUP_PAGES)
+    return profile_->GetLastSessionExitType() != Profile::EXIT_CRASHED;
+
+  return true;
+}
+
+bool SettingsApiBubbleController::CloseOnDeactivate() {
+  // Startup bubbles tend to get lost in the focus storm that happens on
+  // startup. Other types should dismiss on focus loss.
+  return type_ != BUBBLE_TYPE_STARTUP_PAGES;
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/settings_api_bubble_controller.h b/chrome/browser/extensions/settings_api_bubble_controller.h
new file mode 100644
index 0000000..db734b4
--- /dev/null
+++ b/chrome/browser/extensions/settings_api_bubble_controller.h
@@ -0,0 +1,42 @@
+// ::Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_SETTINGS_API_BUBBLE_CONTROLLER_H_
+#define CHROME_BROWSER_EXTENSIONS_SETTINGS_API_BUBBLE_CONTROLLER_H_
+
+#include <string>
+#include "chrome/browser/extensions/extension_message_bubble_controller.h"
+#include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
+
+class ExtensionService;
+
+namespace extensions {
+
+class SettingsApiBubble;
+
+class SettingsApiBubbleController : public ExtensionMessageBubbleController {
+ public:
+  SettingsApiBubbleController(Profile* profile, SettingsApiOverrideType type);
+  virtual ~SettingsApiBubbleController();
+
+  // Whether the controller knows that we should show the bubble for extension
+  // with |extension_id|. Returns true if so.
+  bool ShouldShow(const std::string& extension_id);
+
+  // ExtensionMessageBubbleController:
+  virtual bool CloseOnDeactivate() OVERRIDE;
+
+ private:
+  // A weak pointer to the profile we are associated with. Not owned by us.
+  Profile* profile_;
+
+  // The type of settings override this bubble will report on.
+  SettingsApiOverrideType type_;
+
+  DISALLOW_COPY_AND_ASSIGN(SettingsApiBubbleController);
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_SETTINGS_API_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/extensions/signin/gaia_auth_extension_loader.cc b/chrome/browser/extensions/signin/gaia_auth_extension_loader.cc
index 2f6b5e2..e2e8cde 100644
--- a/chrome/browser/extensions/signin/gaia_auth_extension_loader.cc
+++ b/chrome/browser/extensions/signin/gaia_auth_extension_loader.cc
@@ -40,7 +40,7 @@
 }
 
 void LoadGaiaAuthExtension(BrowserContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   extensions::ComponentLoader* component_loader = GetComponentLoader(context);
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -79,7 +79,7 @@
 }
 
 void UnloadGaiaAuthExtension(BrowserContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   content::StoragePartition* partition =
       content::BrowserContext::GetStoragePartitionForSite(
diff --git a/chrome/browser/extensions/subscribe_page_action_browsertest.cc b/chrome/browser/extensions/subscribe_page_action_browsertest.cc
index 37bd56b..f0a6515 100644
--- a/chrome/browser/extensions/subscribe_page_action_browsertest.cc
+++ b/chrome/browser/extensions/subscribe_page_action_browsertest.cc
@@ -76,15 +76,14 @@
   }
 }
 
-bool ValidatePageElement(WebContents* tab,
-                         const std::string& frame_xpath,
+bool ValidatePageElement(content::RenderFrameHost* frame,
                          const std::string& javascript,
                          const std::string& expected_value) {
   std::string returned_value;
 
-  if (!content::ExecuteScriptInFrameAndExtractString(tab, frame_xpath,
-                                                     javascript,
-                                                     &returned_value))
+  if (!content::ExecuteScriptAndExtractString(frame,
+                                              javascript,
+                                              &returned_value))
     return false;
 
   EXPECT_STREQ(expected_value.c_str(), returned_value.c_str());
@@ -113,20 +112,13 @@
                                GetFeedUrl(server, url, true, extension_id));
 
   WebContents* tab = browser->tab_strip_model()->GetActiveWebContents();
+  content::RenderFrameHost* frame = content::FrameMatchingPredicate(
+      tab, base::Bind(&content::FrameIsChildOfMainFrame));
   ASSERT_TRUE(ValidatePageElement(
-      tab, std::string(), kScriptFeedTitle, expected_feed_title));
-  ASSERT_TRUE(ValidatePageElement(tab,
-                                  "//html/body/div/iframe[1]",
-                                  kScriptAnchor,
-                                  expected_item_title));
-  ASSERT_TRUE(ValidatePageElement(tab,
-                                  "//html/body/div/iframe[1]",
-                                  kScriptDesc,
-                                  expected_item_desc));
-  ASSERT_TRUE(ValidatePageElement(tab,
-                                  "//html/body/div/iframe[1]",
-                                  kScriptError,
-                                  expected_error));
+      tab->GetMainFrame(), kScriptFeedTitle, expected_feed_title));
+  ASSERT_TRUE(ValidatePageElement(frame, kScriptAnchor, expected_item_title));
+  ASSERT_TRUE(ValidatePageElement(frame, kScriptDesc, expected_item_desc));
+  ASSERT_TRUE(ValidatePageElement(frame, kScriptError, expected_error));
 }
 
 } // namespace
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index 5bc94af..16eed18 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -12,13 +12,14 @@
 #include "chrome/browser/extensions/activity_log/activity_log.h"
 #include "chrome/browser/extensions/api/declarative/rules_registry_service.h"
 #include "chrome/browser/extensions/api/declarative_content/content_rules_registry.h"
+#include "chrome/browser/extensions/api/webstore/webstore_api.h"
+#include "chrome/browser/extensions/bookmark_app_helper.h"
 #include "chrome/browser/extensions/crx_installer.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
 #include "chrome/browser/extensions/extension_action.h"
 #include "chrome/browser/extensions/extension_action_manager.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_tab_util.h"
-#include "chrome/browser/extensions/favicon_downloader.h"
 #include "chrome/browser/extensions/image_loader.h"
 #include "chrome/browser/extensions/page_action_controller.h"
 #include "chrome/browser/extensions/script_executor.h"
@@ -64,10 +65,6 @@
 #include "extensions/common/extension_resource.h"
 #include "extensions/common/extension_urls.h"
 #include "extensions/common/feature_switch.h"
-#include "skia/ext/image_operations.h"
-#include "skia/ext/platform_canvas.h"
-#include "ui/gfx/color_analysis.h"
-#include "ui/gfx/image/image.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
@@ -97,118 +94,6 @@
     tab_helper_->RemoveScriptExecutionObserver(this);
 }
 
-// static
-std::map<int, SkBitmap> TabHelper::ConstrainBitmapsToSizes(
-    const std::vector<SkBitmap>& bitmaps,
-    const std::set<int>& sizes) {
-  std::map<int, SkBitmap> output_bitmaps;
-  std::map<int, SkBitmap> ordered_bitmaps;
-  for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
-       it != bitmaps.end(); ++it) {
-    DCHECK(it->width() == it->height());
-    ordered_bitmaps[it->width()] = *it;
-  }
-
-  std::set<int>::const_iterator sizes_it = sizes.begin();
-  std::map<int, SkBitmap>::const_iterator bitmaps_it = ordered_bitmaps.begin();
-  while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) {
-    int size = *sizes_it;
-    // Find the closest not-smaller bitmap.
-    bitmaps_it = ordered_bitmaps.lower_bound(size);
-    ++sizes_it;
-    // Ensure the bitmap is valid and smaller than the next allowed size.
-    if (bitmaps_it != ordered_bitmaps.end() &&
-        (sizes_it == sizes.end() || bitmaps_it->second.width() < *sizes_it)) {
-      // Resize the bitmap if it does not exactly match the desired size.
-      output_bitmaps[size] = bitmaps_it->second.width() == size
-          ? bitmaps_it->second
-          : skia::ImageOperations::Resize(
-                bitmaps_it->second, skia::ImageOperations::RESIZE_LANCZOS3,
-                size, size);
-    }
-  }
-  return output_bitmaps;
-}
-
-// static
-void TabHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
-                                      int output_size) {
-  std::map<int, SkBitmap>::const_iterator it =
-      bitmaps->lower_bound(output_size);
-  // Do nothing if there is no icon smaller than the desired size or there is
-  // already an icon of |output_size|.
-  if (it == bitmaps->begin() || bitmaps->count(output_size))
-    return;
-
-  --it;
-  // This is the biggest icon smaller than |output_size|.
-  const SkBitmap& base_icon = it->second;
-
-  const size_t kBorderRadius = 5;
-  const size_t kColorStripHeight = 3;
-  const SkColor kBorderColor = 0xFFD5D5D5;
-  const SkColor kBackgroundColor = 0xFFFFFFFF;
-
-  // Create a separate canvas for the color strip.
-  SkBitmap color_strip_bitmap;
-  color_strip_bitmap.allocN32Pixels(output_size, output_size);
-  SkCanvas color_strip_canvas(color_strip_bitmap);
-  color_strip_canvas.clear(SK_ColorTRANSPARENT);
-
-  // Draw a rounded rect of the |base_icon|'s dominant color.
-  SkPaint color_strip_paint;
-  color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag);
-  color_strip_paint.setColor(
-      color_utils::CalculateKMeanColorOfBitmap(base_icon));
-  color_strip_canvas.drawRoundRect(SkRect::MakeWH(output_size, output_size),
-                                   kBorderRadius,
-                                   kBorderRadius,
-                                   color_strip_paint);
-
-  // Erase the top of the rounded rect to leave a color strip.
-  SkPaint clear_paint;
-  clear_paint.setColor(SK_ColorTRANSPARENT);
-  clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode);
-  color_strip_canvas.drawRect(
-      SkRect::MakeWH(output_size, output_size - kColorStripHeight),
-      clear_paint);
-
-  // Draw each element to an output canvas.
-  SkBitmap generated_icon;
-  generated_icon.allocN32Pixels(output_size, output_size);
-  SkCanvas generated_icon_canvas(generated_icon);
-  generated_icon_canvas.clear(SK_ColorTRANSPARENT);
-
-  // Draw the background.
-  SkPaint background_paint;
-  background_paint.setColor(kBackgroundColor);
-  background_paint.setFlags(SkPaint::kAntiAlias_Flag);
-  generated_icon_canvas.drawRoundRect(SkRect::MakeWH(output_size, output_size),
-                                      kBorderRadius,
-                                      kBorderRadius,
-                                      background_paint);
-
-  // Draw the color strip.
-  generated_icon_canvas.drawBitmap(color_strip_bitmap, 0, 0);
-
-  // Draw the border.
-  SkPaint border_paint;
-  border_paint.setColor(kBorderColor);
-  border_paint.setStyle(SkPaint::kStroke_Style);
-  border_paint.setFlags(SkPaint::kAntiAlias_Flag);
-  generated_icon_canvas.drawRoundRect(SkRect::MakeWH(output_size, output_size),
-                                      kBorderRadius,
-                                      kBorderRadius,
-                                      border_paint);
-
-  // Draw the centered base icon to the output canvas.
-  generated_icon_canvas.drawBitmap(base_icon,
-                                   (output_size - base_icon.width()) / 2,
-                                   (output_size - base_icon.height()) / 2);
-
-  generated_icon.deepCopyTo(&(*bitmaps)[output_size]);
-}
-
 TabHelper::TabHelper(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       extension_app_(NULL),
@@ -242,14 +127,6 @@
                  content::NOTIFICATION_LOAD_STOP,
                  content::Source<NavigationController>(
                      &web_contents->GetController()));
-
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_CRX_INSTALLER_DONE,
-                 content::Source<CrxInstaller>(NULL));
-
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR,
-                 content::NotificationService::AllSources());
 }
 
 TabHelper::~TabHelper() {
@@ -329,6 +206,28 @@
   return &extension_app_icon_;
 }
 
+void TabHelper::FinishCreateBookmarkApp(
+    const extensions::Extension* extension,
+    const WebApplicationInfo& web_app_info) {
+  pending_web_app_action_ = NONE;
+
+  // There was an error with downloading the icons or installing the app.
+  if (!extension)
+    return;
+
+#if defined(OS_CHROMEOS)
+  ChromeLauncherController::instance()->PinAppWithID(extension->id());
+#endif
+
+// Android does not implement browser_finder.cc.
+#if !defined(OS_ANDROID)
+  Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
+  if (browser) {
+    browser->window()->ShowBookmarkAppBubble(web_app_info, extension->id());
+  }
+#endif
+}
+
 void TabHelper::RenderViewCreated(RenderViewHost* render_view_host) {
   SetTabId(render_view_host);
 }
@@ -405,115 +304,6 @@
   return handled;
 }
 
-void TabHelper::CreateHostedApp() {
-  // Add urls from the WebApplicationInfo.
-  std::vector<GURL> web_app_info_icon_urls;
-  for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
-           web_app_info_.icons.begin();
-       it != web_app_info_.icons.end(); ++it) {
-    if (it->url.is_valid())
-      web_app_info_icon_urls.push_back(it->url);
-  }
-
-  favicon_downloader_.reset(
-      new FaviconDownloader(web_contents(),
-                            web_app_info_icon_urls,
-                            base::Bind(&TabHelper::FinishCreateHostedApp,
-                                       base::Unretained(this))));
-  favicon_downloader_->Start();
-}
-
-// TODO(calamity): Move hosted app generation into its own file.
-void TabHelper::FinishCreateHostedApp(
-    bool success,
-    const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
-  // The tab has navigated away during the icon download. Cancel the hosted app
-  // creation.
-  if (!success) {
-    favicon_downloader_.reset();
-    return;
-  }
-
-  if (web_app_info_.app_url.is_empty())
-    web_app_info_.app_url = web_contents()->GetURL();
-
-  if (web_app_info_.title.empty())
-    web_app_info_.title = web_contents()->GetTitle();
-  if (web_app_info_.title.empty())
-    web_app_info_.title = base::UTF8ToUTF16(web_app_info_.app_url.spec());
-
-  // Add the downloaded icons. Extensions only allow certain icon sizes. First
-  // populate icons that match the allowed sizes exactly and then downscale
-  // remaining icons to the closest allowed size that doesn't yet have an icon.
-  std::set<int> allowed_sizes(
-      extension_misc::kExtensionIconSizes,
-      extension_misc::kExtensionIconSizes +
-          extension_misc::kNumExtensionIconSizes);
-  std::vector<SkBitmap> downloaded_icons;
-  for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
-       map_it != bitmaps.end(); ++map_it) {
-    for (std::vector<SkBitmap>::const_iterator bitmap_it =
-             map_it->second.begin();
-         bitmap_it != map_it->second.end(); ++bitmap_it) {
-      if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height())
-        continue;
-
-      downloaded_icons.push_back(*bitmap_it);
-    }
-  }
-
-  // If there are icons that don't match the accepted icon sizes, find the
-  // closest bigger icon to the accepted sizes and resize the icon to it. An
-  // icon will be resized and used for at most one size.
-  std::map<int, SkBitmap> resized_bitmaps(
-      TabHelper::ConstrainBitmapsToSizes(downloaded_icons,
-                                         allowed_sizes));
-
-  // Generate container icons from smaller icons.
-  const int kIconSizesToGenerate[] = {
-    extension_misc::EXTENSION_ICON_SMALL,
-    extension_misc::EXTENSION_ICON_MEDIUM,
-  };
-  const std::set<int> generate_sizes(
-      kIconSizesToGenerate,
-      kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
-
-  // Only generate icons if larger icons don't exist. This means the app
-  // launcher and the taskbar will do their best downsizing large icons and
-  // these container icons are only generated as a last resort against upscaling
-  // a smaller icon.
-  if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) ==
-      resized_bitmaps.end()) {
-    // Generate these from biggest to smallest so we don't end up with
-    // concentric container icons.
-    for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin();
-         it != generate_sizes.rend(); ++it) {
-      TabHelper::GenerateContainerIcon(&resized_bitmaps, *it);
-    }
-  }
-
-  // Populate a the icon data into the WebApplicationInfo we are using to
-  // install the bookmark app.
-  for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it =
-           resized_bitmaps.begin();
-       resized_bitmaps_it != resized_bitmaps.end(); ++resized_bitmaps_it) {
-    WebApplicationInfo::IconInfo icon_info;
-    icon_info.data = resized_bitmaps_it->second;
-    icon_info.width = icon_info.data.width();
-    icon_info.height = icon_info.data.height();
-    web_app_info_.icons.push_back(icon_info);
-  }
-
-  // Install the app.
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-  scoped_refptr<extensions::CrxInstaller> installer(
-      extensions::CrxInstaller::CreateSilent(profile->GetExtensionService()));
-  installer->set_error_on_unsupported_requirements(true);
-  installer->InstallWebApp(web_app_info_);
-  favicon_downloader_.reset();
-}
-
 void TabHelper::DidCloneToNewWebContents(WebContents* old_web_contents,
                                          WebContents* new_web_contents) {
   // When the WebContents that this is attached to is cloned, give the new clone
@@ -544,7 +334,18 @@
       break;
     }
     case CREATE_HOSTED_APP: {
-      CreateHostedApp();
+      if (web_app_info_.app_url.is_empty())
+        web_app_info_.app_url = web_contents()->GetURL();
+
+      if (web_app_info_.title.empty())
+        web_app_info_.title = web_contents()->GetTitle();
+      if (web_app_info_.title.empty())
+        web_app_info_.title = base::UTF8ToUTF16(web_app_info_.app_url.spec());
+
+      bookmark_app_helper_.reset(new BookmarkAppHelper(
+          profile_->GetExtensionService(), web_app_info_, web_contents()));
+      bookmark_app_helper_->Create(base::Bind(
+          &TabHelper::FinishCreateBookmarkApp, base::Unretained(this)));
       break;
     }
     case UPDATE_SHORTCUT: {
@@ -563,11 +364,27 @@
 #endif
 }
 
-void TabHelper::OnInlineWebstoreInstall(
-    int install_id,
-    int return_route_id,
-    const std::string& webstore_item_id,
-    const GURL& requestor_url) {
+void TabHelper::OnInlineWebstoreInstall(int install_id,
+                                        int return_route_id,
+                                        const std::string& webstore_item_id,
+                                        const GURL& requestor_url,
+                                        int listeners_mask) {
+#if defined(ENABLE_EXTENSIONS)
+  // Check that the listener is reasonable. We should never get anything other
+  // than an install stage listener, a download listener, or both.
+  if ((listeners_mask & ~(api::webstore::INSTALL_STAGE_LISTENER |
+                          api::webstore::DOWNLOAD_PROGRESS_LISTENER)) != 0) {
+    NOTREACHED();
+    return;
+  }
+  // Inform the Webstore API that an inline install is happening, in case the
+  // page requested status updates.
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+  WebstoreAPI::Get(profile)->OnInlineInstallStart(
+      return_route_id, this, webstore_item_id, listeners_mask);
+#endif
+
   WebstoreStandaloneInstaller::Callback callback =
       base::Bind(&TabHelper::OnInlineInstallComplete, base::Unretained(this),
                  install_id, return_route_id);
@@ -745,37 +562,6 @@
       }
       break;
     }
-    case chrome::NOTIFICATION_CRX_INSTALLER_DONE: {
-      if (pending_web_app_action_ != CREATE_HOSTED_APP)
-        return;
-
-      pending_web_app_action_ = NONE;
-
-      const Extension* extension =
-          content::Details<const Extension>(details).ptr();
-      if (!extension ||
-          AppLaunchInfo::GetLaunchWebURL(extension) != web_app_info_.app_url)
-        return;
-
-#if defined(OS_CHROMEOS)
-      ChromeLauncherController::instance()->PinAppWithID(extension->id());
-#endif
-
-      // Android does not implement browser_finder.cc.
-#if !defined(OS_ANDROID)
-      Browser* browser =
-          chrome::FindBrowserWithWebContents(web_contents());
-      if (browser) {
-        browser->window()->ShowBookmarkAppBubble(web_app_info_,
-                                                 extension->id());
-      }
-#endif
-    }
-    case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: {
-      if (pending_web_app_action_ == CREATE_HOSTED_APP)
-        pending_web_app_action_ = NONE;
-      break;
-    }
   }
 }
 
diff --git a/chrome/browser/extensions/tab_helper.h b/chrome/browser/extensions/tab_helper.h
index bb30c76..dcfa66b 100644
--- a/chrome/browser/extensions/tab_helper.h
+++ b/chrome/browser/extensions/tab_helper.h
@@ -35,6 +35,7 @@
 }
 
 namespace extensions {
+class BookmarkAppHelper;
 class Extension;
 class LocationBarController;
 class ScriptExecutor;
@@ -86,21 +87,6 @@
     TabHelper* tab_helper_;
   };
 
-  // This finds the closest not-smaller bitmap in |bitmaps| for each size in
-  // |sizes| and resizes it to that size. This returns a map of sizes to bitmaps
-  // which contains only bitmaps of a size in |sizes| and at most one bitmap of
-  // each size.
-  static std::map<int, SkBitmap> ConstrainBitmapsToSizes(
-      const std::vector<SkBitmap>& bitmaps,
-      const std::set<int>& sizes);
-
-  // Adds a square container icon of |output_size| pixels to |bitmaps| by
-  // centering the biggest smaller icon in |bitmaps| and drawing a rounded
-  // rectangle with strip of the that icon's dominant color at the bottom.
-  // Does nothing if an icon of |output_size| already exists in |bitmaps|.
-  static void GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps,
-                                    int output_size);
-
   virtual ~TabHelper();
 
   void AddScriptExecutionObserver(ScriptExecutionObserver* observer) {
@@ -180,11 +166,9 @@
   explicit TabHelper(content::WebContents* web_contents);
   friend class content::WebContentsUserData<TabHelper>;
 
-  // Creates a hosted app for the current tab. Requires the |web_app_info_| to
-  // be populated.
-  void CreateHostedApp();
-  void FinishCreateHostedApp(
-      bool success, const std::map<GURL, std::vector<SkBitmap> >& bitmaps);
+  // Displays UI for completion of creating a bookmark hosted app.
+  void FinishCreateBookmarkApp(const extensions::Extension* extension,
+                               const WebApplicationInfo& web_app_info);
 
   // content::WebContentsObserver overrides.
   virtual void RenderViewCreated(
@@ -207,7 +191,8 @@
   void OnInlineWebstoreInstall(int install_id,
                                int return_route_id,
                                const std::string& webstore_item_id,
-                               const GURL& requestor_url);
+                               const GURL& requestor_url,
+                               int listeners_mask);
   void OnGetAppInstallState(const GURL& requestor_url,
                             int return_route_id,
                             int callback_id);
@@ -283,7 +268,7 @@
 
   scoped_ptr<ActiveTabPermissionGranter> active_tab_permission_granter_;
 
-  scoped_ptr<FaviconDownloader> favicon_downloader_;
+  scoped_ptr<BookmarkAppHelper> bookmark_app_helper_;
 
   Profile* profile_;
 
diff --git a/chrome/browser/extensions/tab_helper_unittest.cc b/chrome/browser/extensions/tab_helper_unittest.cc
deleted file mode 100644
index 7169063..0000000
--- a/chrome/browser/extensions/tab_helper_unittest.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/extensions/tab_helper.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-
-namespace {
-
-SkBitmap CreateSquareBitmapWithColor(int size, SkColor color) {
-  SkBitmap bitmap;
-  bitmap.setConfig(SkBitmap::kARGB_8888_Config, size, size);
-  bitmap.allocPixels();
-  bitmap.eraseColor(color);
-  return bitmap;
-}
-
-void ValidateBitmapSizeAndColor(SkBitmap bitmap, int size, SkColor color) {
-  // Obtain pixel lock to access pixels.
-  SkAutoLockPixels lock(bitmap);
-  EXPECT_EQ(color, bitmap.getColor(0, 0));
-  EXPECT_EQ(size, bitmap.width());
-  EXPECT_EQ(size, bitmap.height());
-}
-
-class TabHelperTest : public testing::Test {
- protected:
-  TabHelperTest() {
-  }
-
-  virtual ~TabHelperTest() {
-  }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TabHelperTest);
-};
-
-}  // namespace
-
-TEST_F(TabHelperTest, ConstrainBitmapsToSizes) {
-  std::set<int> desired_sizes;
-  desired_sizes.insert(16);
-  desired_sizes.insert(32);
-  desired_sizes.insert(128);
-  desired_sizes.insert(256);
-
-  {
-    std::vector<SkBitmap> bitmaps;
-    bitmaps.push_back(CreateSquareBitmapWithColor(16, SK_ColorRED));
-    bitmaps.push_back(CreateSquareBitmapWithColor(32, SK_ColorGREEN));
-    bitmaps.push_back(CreateSquareBitmapWithColor(48, SK_ColorBLUE));
-    bitmaps.push_back(CreateSquareBitmapWithColor(144, SK_ColorYELLOW));
-
-    std::map<int, SkBitmap> results(
-        extensions::TabHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
-
-    EXPECT_EQ(3u, results.size());
-    ValidateBitmapSizeAndColor(results[16], 16, SK_ColorRED);
-    ValidateBitmapSizeAndColor(results[32], 32, SK_ColorGREEN);
-    ValidateBitmapSizeAndColor(results[128], 128, SK_ColorYELLOW);
-  }
-  {
-    std::vector<SkBitmap> bitmaps;
-    bitmaps.push_back(CreateSquareBitmapWithColor(512, SK_ColorRED));
-    bitmaps.push_back(CreateSquareBitmapWithColor(18, SK_ColorGREEN));
-    bitmaps.push_back(CreateSquareBitmapWithColor(33, SK_ColorBLUE));
-    bitmaps.push_back(CreateSquareBitmapWithColor(17, SK_ColorYELLOW));
-
-    std::map<int, SkBitmap> results(
-        extensions::TabHelper::ConstrainBitmapsToSizes(bitmaps, desired_sizes));
-
-    EXPECT_EQ(3u, results.size());
-    ValidateBitmapSizeAndColor(results[16], 16, SK_ColorYELLOW);
-    ValidateBitmapSizeAndColor(results[32], 32, SK_ColorBLUE);
-    ValidateBitmapSizeAndColor(results[256], 256, SK_ColorRED);
-  }
-}
-
-TEST_F(TabHelperTest, GenerateIcons) {
-  {
-    // The 32x32 icon should be generated from the 16x16 icon.
-    std::map<int, SkBitmap> bitmaps;
-    bitmaps[16] = CreateSquareBitmapWithColor(16, SK_ColorRED);
-    extensions::TabHelper::GenerateContainerIcon(&bitmaps, 32);
-    EXPECT_EQ(1u, bitmaps.count(32));
-    EXPECT_EQ(32, bitmaps[32].width());
-  }
-  {
-    // The 32x32 icon should not be generated because no smaller icon exists.
-    std::map<int, SkBitmap> bitmaps;
-    bitmaps[48] = CreateSquareBitmapWithColor(48, SK_ColorRED);
-    extensions::TabHelper::GenerateContainerIcon(&bitmaps, 32);
-    EXPECT_EQ(0u, bitmaps.count(32));
-  }
-  {
-    // The 32x32 icon should not be generated with no base icons.
-    std::map<int, SkBitmap> bitmaps;
-    extensions::TabHelper::GenerateContainerIcon(&bitmaps, 32);
-    EXPECT_EQ(0u, bitmaps.count(32));
-  }
-}
diff --git a/chrome/browser/extensions/test_extension_prefs.cc b/chrome/browser/extensions/test_extension_prefs.cc
index e65fb58..276980a 100644
--- a/chrome/browser/extensions/test_extension_prefs.cc
+++ b/chrome/browser/extensions/test_extension_prefs.cc
@@ -164,7 +164,8 @@
   prefs_->OnExtensionInstalled(extension.get(),
                                Extension::ENABLED,
                                false,
-                               syncer::StringOrdinal::CreateInitialOrdinal());
+                               syncer::StringOrdinal::CreateInitialOrdinal(),
+                               std::string());
   return extension;
 }
 
diff --git a/chrome/browser/extensions/test_extension_service.cc b/chrome/browser/extensions/test_extension_service.cc
index 856bce0..af82db2 100644
--- a/chrome/browser/extensions/test_extension_service.cc
+++ b/chrome/browser/extensions/test_extension_service.cc
@@ -60,12 +60,6 @@
   return false;
 }
 
-bool TestExtensionService::IsExternalExtensionUninstalled(
-    const std::string& extension_id) const {
-  ADD_FAILURE();
-  return false;
-}
-
 void TestExtensionService::CheckManagementPolicy() {
   ADD_FAILURE();
 }
diff --git a/chrome/browser/extensions/test_extension_service.h b/chrome/browser/extensions/test_extension_service.h
index b08f055..e92e034 100644
--- a/chrome/browser/extensions/test_extension_service.h
+++ b/chrome/browser/extensions/test_extension_service.h
@@ -43,8 +43,6 @@
       const std::string& extension_id) OVERRIDE;
   virtual bool IsExtensionEnabled(
       const std::string& extension_id) const OVERRIDE;
-  virtual bool IsExternalExtensionUninstalled(
-      const std::string& extension_id) const OVERRIDE;
 
   virtual void CheckManagementPolicy() OVERRIDE;
   virtual void CheckForUpdatesSoon() OVERRIDE;
diff --git a/chrome/browser/extensions/test_extension_system.cc b/chrome/browser/extensions/test_extension_system.cc
index d70ad57..3a60db3 100644
--- a/chrome/browser/extensions/test_extension_system.cc
+++ b/chrome/browser/extensions/test_extension_system.cc
@@ -86,8 +86,8 @@
     bool autoupdate_enabled) {
   if (!ExtensionPrefs::Get(profile_))
     CreateExtensionPrefs(command_line, install_directory);
-  install_verifier_.reset(new InstallVerifier(ExtensionPrefs::Get(profile_),
-                                              NULL));
+  install_verifier_.reset(
+      new InstallVerifier(ExtensionPrefs::Get(profile_), profile_));
   // The ownership of |value_store_| is immediately transferred to state_store_,
   // but we keep a naked pointer to the TestingValueStore.
   scoped_ptr<TestingValueStore> value_store(new TestingValueStore());
diff --git a/chrome/browser/extensions/token_cache/token_cache_service.h b/chrome/browser/extensions/token_cache/token_cache_service.h
index dcda111..c6279a1 100644
--- a/chrome/browser/extensions/token_cache/token_cache_service.h
+++ b/chrome/browser/extensions/token_cache/token_cache_service.h
@@ -11,8 +11,8 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/time/time.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 
 class Profile;
 
diff --git a/chrome/browser/extensions/unpacked_installer.cc b/chrome/browser/extensions/unpacked_installer.cc
index 783b888..cb197ec 100644
--- a/chrome/browser/extensions/unpacked_installer.cc
+++ b/chrome/browser/extensions/unpacked_installer.cc
@@ -298,7 +298,7 @@
 }
 
 void UnpackedInstaller::ConfirmInstall() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   base::string16 error = installer_.CheckManagementPolicy();
   if (!error.empty()) {
     ReportExtensionLoadError(base::UTF16ToUTF8(error));
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index e47ae02..6cc7978 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -254,8 +254,7 @@
 class MockService : public TestExtensionService {
  public:
   explicit MockService(TestExtensionPrefs* prefs)
-      : prefs_(prefs), pending_extension_manager_(*this) {
-  }
+      : prefs_(prefs), pending_extension_manager_(*this, &profile_) {}
 
   virtual ~MockService() {}
 
@@ -300,8 +299,8 @@
 
  protected:
   TestExtensionPrefs* const prefs_;
-  PendingExtensionManager pending_extension_manager_;
   TestingProfile profile_;
+  PendingExtensionManager pending_extension_manager_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockService);
@@ -335,6 +334,7 @@
 
     pending_extension_manager->AddForTesting(
         PendingExtensionInfo(id,
+                             std::string(),
                              update_url,
                              Version(),
                              should_allow_install,
@@ -1022,8 +1022,12 @@
       PendingExtensionManager* pending_extension_manager =
           service->pending_extension_manager();
       pending_extension_manager->AddForTesting(
-          PendingExtensionInfo(id, test_url, version,
-                               &ShouldAlwaysInstall, kIsFromSync,
+          PendingExtensionInfo(id,
+                               std::string(),
+                               test_url,
+                               version,
+                               &ShouldAlwaysInstall,
+                               kIsFromSync,
                                kInstallSilently,
                                Manifest::INTERNAL,
                                Extension::NO_FLAGS,
diff --git a/chrome/browser/extensions/updater/safe_manifest_parser.cc b/chrome/browser/extensions/updater/safe_manifest_parser.cc
index 2eaa5a7..fa5a61c 100644
--- a/chrome/browser/extensions/updater/safe_manifest_parser.cc
+++ b/chrome/browser/extensions/updater/safe_manifest_parser.cc
@@ -24,11 +24,11 @@
     : xml_(xml),
       fetch_data_(fetch_data),
       update_callback_(update_callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
 void SafeManifestParser::Start() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!BrowserThread::PostTask(
           BrowserThread::IO, FROM_HERE,
           base::Bind(&SafeManifestParser::ParseInSandbox, this))) {
@@ -42,7 +42,7 @@
 }
 
 void SafeManifestParser::ParseInSandbox() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   content::UtilityProcessHost* host = content::UtilityProcessHost::Create(
       this,
@@ -65,14 +65,14 @@
 void SafeManifestParser::OnParseUpdateManifestSucceeded(
     const UpdateManifest::Results& results) {
   VLOG(2) << "parsing manifest succeeded (" << fetch_data_->full_url() << ")";
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   update_callback_.Run(*fetch_data_, &results);
 }
 
 void SafeManifestParser::OnParseUpdateManifestFailed(
     const std::string& error_message) {
   VLOG(2) << "parsing manifest failed (" << fetch_data_->full_url() << ")";
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   LOG(WARNING) << "Error parsing update manifest:\n" << error_message;
   update_callback_.Run(*fetch_data_, NULL);
 }
diff --git a/chrome/browser/extensions/user_script_listener.cc b/chrome/browser/extensions/user_script_listener.cc
index 2df17f5..ff40738 100644
--- a/chrome/browser/extensions/user_script_listener.cc
+++ b/chrome/browser/extensions/user_script_listener.cc
@@ -68,7 +68,7 @@
 
 UserScriptListener::UserScriptListener()
     : user_scripts_ready_(false) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
                  content::NotificationService::AllSources());
@@ -96,7 +96,7 @@
 
 bool UserScriptListener::ShouldDelayRequest(const GURL& url,
                                             ResourceType::Type resource_type) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // If it's a frame load, then we need to check the URL against the list of
   // user scripts to see if we need to wait.
@@ -136,7 +136,7 @@
 }
 
 void UserScriptListener::CheckIfAllUserScriptsReady() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   bool was_ready = user_scripts_ready_;
 
   user_scripts_ready_ = true;
@@ -151,14 +151,14 @@
 }
 
 void UserScriptListener::UserScriptsReady(void* profile_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   profile_data_[profile_id].user_scripts_ready = true;
   CheckIfAllUserScriptsReady();
 }
 
 void UserScriptListener::ProfileDestroyed(void* profile_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   profile_data_.erase(profile_id);
 
   // We may have deleted the only profile we were waiting on.
@@ -167,7 +167,7 @@
 
 void UserScriptListener::AppendNewURLPatterns(void* profile_id,
                                               const URLPatterns& new_patterns) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   user_scripts_ready_ = false;
 
@@ -180,7 +180,7 @@
 
 void UserScriptListener::ReplaceURLPatterns(void* profile_id,
                                             const URLPatterns& patterns) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   ProfileData& data = profile_data_[profile_id];
   data.url_patterns = patterns;
@@ -188,7 +188,7 @@
 
 void UserScriptListener::CollectURLPatterns(const Extension* extension,
                                             URLPatterns* patterns) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   const UserScriptList& scripts =
       ContentScriptsInfo::GetContentScripts(extension);
@@ -203,7 +203,7 @@
 void UserScriptListener::Observe(int type,
                                  const content::NotificationSource& source,
                                  const content::NotificationDetails& details) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   switch (type) {
     case chrome::NOTIFICATION_EXTENSION_LOADED: {
diff --git a/chrome/browser/extensions/webstore_inline_installer_browsertest.cc b/chrome/browser/extensions/webstore_inline_installer_browsertest.cc
index 60b6aab..921cb61 100644
--- a/chrome/browser/extensions/webstore_inline_installer_browsertest.cc
+++ b/chrome/browser/extensions/webstore_inline_installer_browsertest.cc
@@ -167,4 +167,33 @@
   ASSERT_TRUE(extension_service->IsExtensionEnabled(kTestExtensionId));
 }
 
+class WebstoreInlineInstallerListenerTest : public WebstoreInlineInstallerTest {
+ public:
+  WebstoreInlineInstallerListenerTest() {}
+  virtual ~WebstoreInlineInstallerListenerTest() {}
+
+ protected:
+  void RunTest(const std::string& file_name) {
+    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kAppsGalleryInstallAutoConfirmForTests, "accept");
+    ui_test_utils::NavigateToURL(browser(),
+                                 GenerateTestServerUrl(kAppDomain, file_name));
+    WebstoreInstallerTest::RunTest("runTest");
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,
+                       InstallStageListenerTest) {
+  RunTest("install_stage_listener.html");
+}
+
+IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest,
+                       DownloadProgressListenerTest) {
+  RunTest("download_progress_listener.html");
+}
+
+IN_PROC_BROWSER_TEST_F(WebstoreInlineInstallerListenerTest, BothListenersTest) {
+  RunTest("both_listeners.html");
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/webstore_installer.cc b/chrome/browser/extensions/webstore_installer.cc
index 5442408..f9cfafa 100644
--- a/chrome/browser/extensions/webstore_installer.cc
+++ b/chrome/browser/extensions/webstore_installer.cc
@@ -19,6 +19,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/download/download_crx_util.h"
 #include "chrome/browser/download/download_prefs.h"
@@ -84,6 +85,8 @@
 const char kDefaultInstallSource[] = "ondemand";
 const char kAppLauncherInstallSource[] = "applauncher";
 
+const size_t kTimeRemainingMinutesThreshold = 1u;
+
 // Folder for downloading crx files from the webstore. This is used so that the
 // crx files don't go via the usual downloads folder.
 const base::FilePath::CharType kWebstoreDownloadFolder[] =
@@ -255,7 +258,7 @@
       approval_(approval.release()),
       total_modules_(0),
       download_started_(false) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(web_contents);
 
   registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE,
@@ -267,7 +270,7 @@
 }
 
 void WebstoreInstaller::Start() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   AddRef();  // Balanced in ReportSuccess and ReportFailure.
 
   if (!Extension::IdIsValid(id_)) {
@@ -303,10 +306,6 @@
   }
   ExtensionSystem::Get(profile_)->install_verifier()->AddProvisional(ids);
 
-  // TODO(crbug.com/305343): Query manifest of dependencises before
-  // downloading & installing those dependencies.
-  DownloadNextPendingModule();
-
   std::string name;
   if (!approval_->manifest->value()->GetString(manifest_keys::kName, &name)) {
     NOTREACHED();
@@ -321,6 +320,12 @@
       approval_->manifest->is_platform_app());
   params.is_ephemeral = approval_->is_ephemeral;
   tracker->OnBeginExtensionInstall(params);
+
+  tracker->OnBeginExtensionDownload(id_);
+
+  // TODO(crbug.com/305343): Query manifest of dependencies before
+  // downloading & installing those dependencies.
+  DownloadNextPendingModule();
 }
 
 void WebstoreInstaller::Observe(int type,
@@ -473,21 +478,15 @@
             extensions::InstallTrackerFactory::GetForProfile(profile_);
         tracker->OnDownloadProgress(id_, 100);
       }
+      // Stop the progress timer if it's running.
+      download_progress_timer_.Stop();
       break;
     case DownloadItem::IN_PROGRESS: {
       if (delegate_ && pending_modules_.size() == 1) {
         // Only report download progress for the main module to |delegrate_|.
         delegate_->OnExtensionDownloadProgress(id_, download);
       }
-      int percent = download->PercentComplete();
-      // Only report progress if precent is more than 0
-      if (percent >= 0) {
-        int finished_modules = total_modules_ - pending_modules_.size();
-        percent = (percent + finished_modules * 100) / total_modules_;
-        extensions::InstallTracker* tracker =
-          extensions::InstallTrackerFactory::GetForProfile(profile_);
-        tracker->OnDownloadProgress(id_, percent);
-      }
+      UpdateDownloadProgress();
       break;
     }
     default:
@@ -553,7 +552,7 @@
 // early-returns into a single branch makes it hard to see exactly which pointer
 // it is.
 void WebstoreInstaller::StartDownload(const base::FilePath& file) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (file.empty()) {
     ReportFailure(kDownloadDirectoryError, FAILURE_REASON_OTHER);
@@ -614,6 +613,42 @@
   download_manager->DownloadUrl(params.Pass());
 }
 
+void WebstoreInstaller::UpdateDownloadProgress() {
+  // If the download has gone away, or isn't in progress (in which case we can't
+  // give a good progress estimate), stop any running timers and return.
+  if (!download_item_ ||
+      download_item_->GetState() != DownloadItem::IN_PROGRESS) {
+    download_progress_timer_.Stop();
+    return;
+  }
+
+  int percent = download_item_->PercentComplete();
+  // Only report progress if precent is more than 0
+  if (percent >= 0) {
+    int finished_modules = total_modules_ - pending_modules_.size();
+    percent = (percent + (finished_modules * 100)) / total_modules_;
+    extensions::InstallTracker* tracker =
+        extensions::InstallTrackerFactory::GetForProfile(profile_);
+    tracker->OnDownloadProgress(id_, percent);
+  }
+
+  // If there's enough time remaining on the download to warrant an update,
+  // set the timer (overwriting any current timers). Otherwise, stop the
+  // timer.
+  base::TimeDelta time_remaining;
+  if (download_item_->TimeRemaining(&time_remaining) &&
+      time_remaining >
+          base::TimeDelta::FromSeconds(kTimeRemainingMinutesThreshold)) {
+    download_progress_timer_.Start(
+        FROM_HERE,
+        base::TimeDelta::FromSeconds(kTimeRemainingMinutesThreshold),
+        this,
+        &WebstoreInstaller::UpdateDownloadProgress);
+  } else {
+    download_progress_timer_.Stop();
+  }
+}
+
 void WebstoreInstaller::ReportFailure(const std::string& error,
                                       FailureReason reason) {
   if (delegate_) {
diff --git a/chrome/browser/extensions/webstore_installer.h b/chrome/browser/extensions/webstore_installer.h
index a8b6ce4..25b2181 100644
--- a/chrome/browser/extensions/webstore_installer.h
+++ b/chrome/browser/extensions/webstore_installer.h
@@ -12,6 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/supports_user_data.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "base/version.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
@@ -224,6 +225,9 @@
   // Starts downloading the extension to |file_path|.
   void StartDownload(const base::FilePath& file_path);
 
+  // Updates the InstallTracker with the latest download progress.
+  void UpdateDownloadProgress();
+
   // Reports an install |error| to the delegate for the given extension if this
   // managed its installation. This also removes the associated PendingInstall.
   void ReportFailure(const std::string& error, FailureReason reason);
@@ -244,6 +248,10 @@
   // The DownloadItem is owned by the DownloadManager and is valid from when
   // OnDownloadStarted is called (with no error) until OnDownloadDestroyed().
   content::DownloadItem* download_item_;
+  // Used to periodically update the extension's download status. This will
+  // trigger at least every second, though sometimes more frequently (depending
+  // on number of modules, etc).
+  base::OneShotTimer<WebstoreInstaller> download_progress_timer_;
   scoped_ptr<Approval> approval_;
   GURL download_url_;
 
diff --git a/chrome/browser/feedback/feedback_common.cc b/chrome/browser/feedback/feedback_common.cc
deleted file mode 100644
index dc1d644..0000000
--- a/chrome/browser/feedback/feedback_common.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/feedback/feedback_common.h"
-
-#include "base/strings/string_util.h"
-#include "chrome/browser/feedback/proto/common.pb.h"
-#include "chrome/browser/feedback/proto/dom.pb.h"
-#include "chrome/browser/feedback/proto/extension.pb.h"
-#include "chrome/browser/feedback/proto/math.pb.h"
-
-namespace {
-
-const char kMultilineIndicatorString[] = "<multiline>\n";
-const char kMultilineStartString[] = "---------- START ----------\n";
-const char kMultilineEndString[] = "---------- END ----------\n\n";
-
-const size_t kFeedbackMaxLength = 4 * 1024;
-const size_t kFeedbackMaxLineCount = 40;
-
-const base::FilePath::CharType kLogsFilename[] =
-    FILE_PATH_LITERAL("system_logs.txt");
-const char kLogsAttachmentName[] = "system_logs.zip";
-
-const char kZipExt[] = ".zip";
-
-const char kPngMimeType[] = "image/png";
-const char kArbitraryMimeType[] = "application/octet-stream";
-
-// Converts the system logs into a string that we can compress and send
-// with the report. This method only converts those logs that we want in
-// the compressed zip file sent with the report, hence it ignores any logs
-// below the size threshold of what we want compressed.
-std::string* LogsToString(const FeedbackCommon::SystemLogsMap& sys_info) {
-  std::string* syslogs_string = new std::string;
-  for (FeedbackCommon::SystemLogsMap::const_iterator it = sys_info.begin();
-       it != sys_info.end();
-       ++it) {
-    std::string key = it->first;
-    std::string value = it->second;
-
-    if (FeedbackCommon::BelowCompressionThreshold(value))
-      continue;
-
-    base::TrimString(key, "\n ", &key);
-    base::TrimString(value, "\n ", &value);
-
-    if (value.find("\n") != std::string::npos) {
-      syslogs_string->append(key + "=" + kMultilineIndicatorString +
-                             kMultilineStartString + value + "\n" +
-                             kMultilineEndString);
-    } else {
-      syslogs_string->append(key + "=" + value + "\n");
-    }
-  }
-  return syslogs_string;
-}
-
-void AddFeedbackData(userfeedback::ExtensionSubmit* feedback_data,
-                     const std::string& key,
-                     const std::string& value) {
-  // Don't bother with empty keys or values.
-  if (key == "" || value == "")
-    return;
-  // Create log_value object and add it to the web_data object.
-  userfeedback::ProductSpecificData log_value;
-  log_value.set_key(key);
-  log_value.set_value(value);
-  userfeedback::WebData* web_data = feedback_data->mutable_web_data();
-  *(web_data->add_product_specific_data()) = log_value;
-}
-
-// Adds data as an attachment to feedback_data if the data is non-empty.
-void AddAttachment(userfeedback::ExtensionSubmit* feedback_data,
-                   const char* name,
-                   const std::string& data) {
-  if (data.empty())
-    return;
-
-  userfeedback::ProductSpecificBinaryData* attachment =
-      feedback_data->add_product_specific_binary_data();
-  attachment->set_mime_type(kArbitraryMimeType);
-  attachment->set_name(name);
-  attachment->set_data(data);
-}
-
-}  // namespace
-
-FeedbackCommon::AttachedFile::AttachedFile(const std::string& filename)
-    : name(filename) {}
-
-FeedbackCommon::FeedbackCommon() {}
-
-FeedbackCommon::~FeedbackCommon() {}
-
-// static
-bool FeedbackCommon::BelowCompressionThreshold(const std::string& content) {
-  if (content.length() > kFeedbackMaxLength)
-    return false;
-  const size_t line_count = std::count(content.begin(), content.end(), '\n');
-  if (line_count > kFeedbackMaxLineCount)
-    return false;
-  return true;
-}
-
-void FeedbackCommon::CompressFile(const base::FilePath& filename,
-                                  const std::string& zipname,
-                                  scoped_ptr<std::string> data) {
-  AttachedFile* file = new AttachedFile(zipname);
-  if (file->name.empty()) {
-    // We need to use the UTF8Unsafe methods here to accomodate Windows, which
-    // uses wide strings to store filepaths.
-    file->name = filename.BaseName().AsUTF8Unsafe();
-    file->name.append(kZipExt);
-  }
-  if (feedback_util::ZipString(filename, *(data.get()), &file->data)) {
-    base::AutoLock lock(attachments_lock_);
-    attachments_.push_back(file);
-  } else {
-    delete file;
-  }
-}
-
-void FeedbackCommon::AddFile(const std::string& filename,
-                             scoped_ptr<std::string> data) {
-  AttachedFile* file = new AttachedFile(filename);
-  file->data = *(data.get());
-
-  base::AutoLock lock(attachments_lock_);
-  attachments_.push_back(file);
-}
-
-void FeedbackCommon::AddLog(const std::string& name, const std::string& value) {
-  if (!logs_.get())
-    logs_ = scoped_ptr<SystemLogsMap>(new SystemLogsMap);
-  (*logs_.get())[name] = value;
-}
-
-void FeedbackCommon::AddLogs(scoped_ptr<SystemLogsMap> logs) {
-  if (logs_.get()) {
-    for (FeedbackCommon::SystemLogsMap::const_iterator i = logs->begin();
-         i != logs->end();
-         ++i) {
-      (*logs_.get())[i->first] = i->second;
-    }
-  } else {
-    logs_ = logs.Pass();
-  }
-}
-
-void FeedbackCommon::CompressLogs() {
-  std::string* logs = LogsToString(*logs_.get());
-  CompressFile(
-      base::FilePath(kLogsFilename), kLogsAttachmentName,
-      scoped_ptr<std::string>(logs));
-}
-
-void FeedbackCommon::AddFilesAndLogsToReport(
-    userfeedback::ExtensionSubmit* feedback_data) {
-  if (sys_info()) {
-    for (FeedbackCommon::SystemLogsMap::const_iterator i = sys_info()->begin();
-         i != sys_info()->end();
-         ++i) {
-      if (BelowCompressionThreshold(i->second))
-        AddFeedbackData(feedback_data, i->first, i->second);
-    }
-  }
-
-  for (size_t i = 0; i < attachments(); i++) {
-    const AttachedFile* file = attachment(i);
-    AddAttachment(feedback_data, file->name.c_str(), file->data);
-  }
-}
-
-void FeedbackCommon::PrepareReport(
-    userfeedback::ExtensionSubmit* feedback_data) {
-  // Unused field, needs to be 0 though.
-  feedback_data->set_type_id(0);
-
-  userfeedback::CommonData* common_data = feedback_data->mutable_common_data();
-  // We're not using gaia ids, we're using the e-mail field instead.
-  common_data->set_gaia_id(0);
-  common_data->set_user_email(user_email());
-  common_data->set_description(description());
-
-  userfeedback::WebData* web_data = feedback_data->mutable_web_data();
-  web_data->set_url(page_url());
-
-  AddFilesAndLogsToReport(feedback_data);
-
-  if (image() && image()->size()) {
-    userfeedback::PostedScreenshot screenshot;
-    screenshot.set_mime_type(kPngMimeType);
-
-    // Set that we 'have' dimensions of the screenshot. These dimensions are
-    // ignored by the server but are a 'required' field in the protobuf.
-    userfeedback::Dimensions dimensions;
-    dimensions.set_width(0.0);
-    dimensions.set_height(0.0);
-
-    *(screenshot.mutable_dimensions()) = dimensions;
-    screenshot.set_binary_content(*image());
-
-    *(feedback_data->mutable_screenshot()) = screenshot;
-  }
-
-  if (category_tag().size())
-    feedback_data->set_bucket(category_tag());
-}
diff --git a/chrome/browser/feedback/feedback_common.h b/chrome/browser/feedback/feedback_common.h
deleted file mode 100644
index 49d6e2e..0000000
--- a/chrome/browser/feedback/feedback_common.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_FEEDBACK_FEEDBACK_COMMON_H_
-#define CHROME_BROWSER_FEEDBACK_FEEDBACK_COMMON_H_
-
-#include <map>
-#include <string>
-
-#include "base/file_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/synchronization/lock.h"
-
-namespace userfeedback {
-class ExtensionSubmit;
-}
-
-namespace feedback_util {
-bool ZipString(const base::FilePath& filename,
-               const std::string& data,
-               std::string* compressed_data);
-}
-
-// This is the base class for FeedbackData. It primarily knows about
-// data common to all feedback reports and how to zip things.
-class FeedbackCommon : public base::RefCountedThreadSafe<FeedbackCommon> {
- public:
-  typedef std::map<std::string, std::string> SystemLogsMap;
-
-  struct AttachedFile {
-    explicit AttachedFile(const std::string& filename);
-
-    std::string name;
-    std::string data;
-  };
-
-  // Determine if the given feedback value is small enough to not need to
-  // be compressed.
-  static bool BelowCompressionThreshold(const std::string& content);
-
-  FeedbackCommon();
-
-  void CompressFile(const base::FilePath& filename,
-                    const std::string& zipname,
-                    scoped_ptr<std::string> data);
-  void AddFile(const std::string& filename, scoped_ptr<std::string> data);
-
-  void AddLog(const std::string& name, const std::string& value);
-  void AddLogs(scoped_ptr<SystemLogsMap> logs);
-  void CompressLogs();
-
-  void AddFilesAndLogsToReport(userfeedback::ExtensionSubmit* feedback_data);
-
-  // Fill in |feedback_data| with all the data that we have collected.
-  // CompressLogs() must have already been called.
-  void PrepareReport(userfeedback::ExtensionSubmit* feedback_data);
-
-  // Getters
-  const std::string& category_tag() const { return category_tag_; }
-  const std::string& page_url() const { return page_url_; }
-  const std::string& description() const { return description_; }
-  const std::string& user_email() const { return user_email_; }
-  std::string* image() const { return image_.get(); }
-  SystemLogsMap* sys_info() const { return logs_.get(); }
-
-  const AttachedFile* attachment(size_t i) const { return attachments_[i]; }
-  size_t attachments() const { return attachments_.size(); }
-
-  // Setters
-  void set_category_tag(const std::string& category_tag) {
-    category_tag_ = category_tag;
-  }
-  void set_page_url(const std::string& page_url) { page_url_ = page_url; }
-  void set_description(const std::string& description) {
-    description_ = description;
-  }
-  void set_user_email(const std::string& user_email) {
-    user_email_ = user_email;
-  }
-  void set_image(scoped_ptr<std::string> image) { image_ = image.Pass(); }
-
- protected:
-  friend class base::RefCountedThreadSafe<FeedbackCommon>;
-  friend class FeedbackCommonTest;
-
-  virtual ~FeedbackCommon();
-
- private:
-  std::string category_tag_;
-  std::string page_url_;
-  std::string description_;
-  std::string user_email_;
-
-  scoped_ptr<std::string> image_;
-
-  // It is possible that multiple attachment add calls are running in
-  // parallel, so synchronize access.
-  base::Lock attachments_lock_;
-  ScopedVector<AttachedFile> attachments_;
-
-  scoped_ptr<SystemLogsMap> logs_;
-};
-
-#endif  // CHROME_BROWSER_FEEDBACK_FEEDBACK_COMMON_H_
diff --git a/chrome/browser/feedback/feedback_common_unittest.cc b/chrome/browser/feedback/feedback_common_unittest.cc
deleted file mode 100644
index 3b3bc88..0000000
--- a/chrome/browser/feedback/feedback_common_unittest.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/feedback/feedback_common.h"
-
-#include "base/bind.h"
-#include "chrome/browser/feedback/proto/common.pb.h"
-#include "chrome/browser/feedback/proto/dom.pb.h"
-#include "chrome/browser/feedback/proto/extension.pb.h"
-#include "chrome/browser/feedback/proto/math.pb.h"
-#include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-const char kOne[] = "one";
-const char kTwo[] = "two";
-const char kThree[] = "three";
-const char kFour[] = "four";
-#define TEN_LINES "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n"
-const char kLongLog[] = TEN_LINES TEN_LINES TEN_LINES TEN_LINES TEN_LINES;
-const char kLogsAttachmentName[] = "system_logs.zip";
-}  // namespace
-
-class FeedbackCommonTest : public testing::Test {
- protected:
-  FeedbackCommonTest() {
-    feedback = scoped_refptr<FeedbackCommon>(new FeedbackCommon());
-  }
-
-  virtual ~FeedbackCommonTest() {}
-
-  scoped_refptr<FeedbackCommon> feedback;
-  userfeedback::ExtensionSubmit report;
-};
-
-TEST_F(FeedbackCommonTest, TestBasicData) {
-  // Test that basic data can be set and propagates to the request.
-  feedback->set_category_tag(kOne);
-  feedback->set_description(kTwo);
-  feedback->set_page_url(kThree);
-  feedback->set_user_email(kFour);
-  feedback->PrepareReport(&report);
-
-  EXPECT_EQ(kOne, report.bucket());
-  EXPECT_EQ(kTwo, report.common_data().description());
-  EXPECT_EQ(kThree, report.web_data().url());
-  EXPECT_EQ(kFour, report.common_data().user_email());
-}
-
-TEST_F(FeedbackCommonTest, TestAddLogs) {
-  feedback->AddLog(kOne, kTwo);
-  feedback->AddLog(kThree, kFour);
-
-  EXPECT_EQ(2U, feedback->sys_info()->size());
-}
-
-TEST_F(FeedbackCommonTest, TestCompressionThreshold) {
-  // Add a large and small log, verify that only the small log gets
-  // included in the report.
-  feedback->AddLog(kOne, kTwo);
-  feedback->AddLog(kThree, kLongLog);
-  feedback->PrepareReport(&report);
-
-  EXPECT_EQ(1, report.web_data().product_specific_data_size());
-  EXPECT_EQ(kOne, report.web_data().product_specific_data(0).key());
-}
-
-TEST_F(FeedbackCommonTest, TestCompression) {
-  // Add a large and small log, verify that an attachment has been
-  // added with the right name.
-  feedback->AddLog(kOne, kTwo);
-  feedback->AddLog(kThree, kLongLog);
-  feedback->CompressLogs();
-  feedback->PrepareReport(&report);
-
-  EXPECT_EQ(1, report.product_specific_binary_data_size());
-  EXPECT_EQ(kLogsAttachmentName, report.product_specific_binary_data(0).name());
-}
diff --git a/chrome/browser/feedback/feedback_data.cc b/chrome/browser/feedback/feedback_data.cc
index a91555f..e5dde6a 100644
--- a/chrome/browser/feedback/feedback_data.cc
+++ b/chrome/browser/feedback/feedback_data.cc
@@ -25,23 +25,108 @@
 
 namespace {
 
+const char kMultilineIndicatorString[] = "<multiline>\n";
+const char kMultilineStartString[] = "---------- START ----------\n";
+const char kMultilineEndString[] = "---------- END ----------\n\n";
+
+const size_t kFeedbackMaxLength = 4 * 1024;
+const size_t kFeedbackMaxLineCount = 40;
+
 const char kTraceFilename[] = "tracing.zip\n";
 const char kPerformanceCategoryTag[] = "Performance";
 
+const char kZipExt[] = ".zip";
+
+const base::FilePath::CharType kLogsFilename[] =
+    FILE_PATH_LITERAL("system_logs.txt");
 const base::FilePath::CharType kHistogramsFilename[] =
     FILE_PATH_LITERAL("histograms.txt");
-const char kHistogramsAttachmentName[] = "histograms.zip";
+
+// Converts the system logs into a string that we can compress and send
+// with the report. This method only converts those logs that we want in
+// the compressed zip file sent with the report, hence it ignores any logs
+// below the size threshold of what we want compressed.
+std::string LogsToString(const FeedbackData::SystemLogsMap& sys_info) {
+  std::string syslogs_string;
+  for (FeedbackData::SystemLogsMap::const_iterator it = sys_info.begin();
+      it != sys_info.end(); ++it) {
+    std::string key = it->first;
+    std::string value = it->second;
+
+    if (FeedbackData::BelowCompressionThreshold(value))
+      continue;
+
+    base::TrimString(key, "\n ", &key);
+    base::TrimString(value, "\n ", &value);
+
+    if (value.find("\n") != std::string::npos) {
+      syslogs_string.append(
+          key + "=" + kMultilineIndicatorString +
+          kMultilineStartString +
+          value + "\n" +
+          kMultilineEndString);
+    } else {
+      syslogs_string.append(key + "=" + value + "\n");
+    }
+  }
+  return syslogs_string;
+}
+
+void ZipFile(const base::FilePath& filename,
+             const std::string& data, std::string* compressed_data) {
+  if (!feedback_util::ZipString(filename, data, compressed_data))
+    compressed_data->clear();
+}
+
+void ZipLogs(const FeedbackData::SystemLogsMap& sys_info,
+             std::string* compressed_logs) {
+  DCHECK(compressed_logs);
+  std::string logs_string = LogsToString(sys_info);
+  if (logs_string.empty() ||
+      !feedback_util::ZipString(
+          base::FilePath(kLogsFilename), logs_string, compressed_logs)) {
+    compressed_logs->clear();
+  }
+}
+
+void ZipHistograms(const std::string& histograms,
+                   std::string* compressed_histograms) {
+  DCHECK(compressed_histograms);
+  if (histograms.empty() ||
+      !feedback_util::ZipString(
+          base::FilePath(kHistogramsFilename),
+          histograms,
+          compressed_histograms)) {
+    compressed_histograms->clear();
+  }
+}
 
 }  // namespace
 
-FeedbackData::FeedbackData()
-    : profile_(NULL), trace_id_(0), pending_op_count_(1), report_sent_(false) {}
+// static
+bool FeedbackData::BelowCompressionThreshold(const std::string& content) {
+  if (content.length() > kFeedbackMaxLength)
+    return false;
+  const size_t line_count = std::count(content.begin(), content.end(), '\n');
+  if (line_count > kFeedbackMaxLineCount)
+    return false;
+  return true;
+}
+
+FeedbackData::FeedbackData() : profile_(NULL),
+                               trace_id_(0),
+                               feedback_page_data_complete_(false),
+                               syslogs_compression_complete_(false),
+                               histograms_compression_complete_(false),
+                               attached_file_compression_complete_(false),
+                               report_sent_(false) {
+}
 
 FeedbackData::~FeedbackData() {
 }
 
 void FeedbackData::OnFeedbackPageDataComplete() {
-  pending_op_count_--;
+  feedback_page_data_complete_ = true;
   SendReport();
 }
 
@@ -51,23 +136,26 @@
 
   if (trace_id_ != 0) {
     TracingManager* manager = TracingManager::Get();
-    pending_op_count_++;
     if (!manager ||
         !manager->GetTraceData(
             trace_id_,
             base::Bind(&FeedbackData::OnGetTraceData, this, trace_id_))) {
-      pending_op_count_--;
       trace_id_ = 0;
     }
   }
 
-  AddLogs(sys_info.Pass());
-  if (sys_info.get()) {
-    pending_op_count_++;
+  sys_info_ = sys_info.Pass();
+  if (sys_info_.get()) {
+    std::string* compressed_logs_ptr = new std::string;
+    scoped_ptr<std::string> compressed_logs(compressed_logs_ptr);
     BrowserThread::PostBlockingPoolTaskAndReply(
         FROM_HERE,
-        base::Bind(&FeedbackCommon::CompressLogs, this),
-        base::Bind(&FeedbackData::OnCompressComplete, this));
+        base::Bind(&ZipLogs,
+                   *sys_info_,
+                   compressed_logs_ptr),
+        base::Bind(&FeedbackData::OnCompressLogsComplete,
+                   this,
+                   base::Passed(&compressed_logs)));
   }
 }
 
@@ -75,39 +163,45 @@
     scoped_ptr<std::string> histograms) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (!histograms.get())
-    return;
-  pending_op_count_++;
-  BrowserThread::PostBlockingPoolTaskAndReply(
-      FROM_HERE,
-      base::Bind(&FeedbackCommon::CompressFile,
-                 this,
-                 base::FilePath(kHistogramsFilename),
-                 kHistogramsAttachmentName,
-                 base::Passed(&histograms)),
-      base::Bind(&FeedbackData::OnCompressComplete, this));
+  histograms_ = histograms.Pass();
+  if (histograms_.get()) {
+    std::string* compressed_histograms_ptr = new std::string;
+    scoped_ptr<std::string> compressed_histograms(compressed_histograms_ptr);
+    BrowserThread::PostBlockingPoolTaskAndReply(
+        FROM_HERE,
+        base::Bind(&ZipHistograms,
+                   *histograms_,
+                   compressed_histograms_ptr),
+        base::Bind(&FeedbackData::OnCompressHistogramsComplete,
+                   this,
+                   base::Passed(&compressed_histograms)));
+  }
 }
 
 void FeedbackData::AttachAndCompressFileData(
     scoped_ptr<std::string> attached_filedata) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  if (!attached_filedata.get() || attached_filedata->empty())
-    return;
-  pending_op_count_++;
+  attached_filedata_ = attached_filedata.Pass();
+
+  if (!attached_filename_.empty() && attached_filedata_.get()) {
+    std::string* compressed_file_ptr = new std::string;
+    scoped_ptr<std::string> compressed_file(compressed_file_ptr);
 #if defined(OS_WIN)
-  base::FilePath attached_file(base::UTF8ToWide(attached_filename_));
+    base::FilePath attached_file(base::UTF8ToWide(attached_filename_));
 #else
-  base::FilePath attached_file(attached_filename_);
+    base::FilePath attached_file(attached_filename_);
 #endif
-  BrowserThread::PostBlockingPoolTaskAndReply(
-      FROM_HERE,
-      base::Bind(&FeedbackCommon::CompressFile,
-                 this,
-                 attached_file,
-                 std::string(),
-                 base::Passed(&attached_filedata)),
-      base::Bind(&FeedbackData::OnCompressComplete, this));
+    BrowserThread::PostBlockingPoolTaskAndReply(
+        FROM_HERE,
+        base::Bind(&ZipFile,
+                   attached_file,
+                   *(attached_filedata_.get()),
+                   compressed_file_ptr),
+        base::Bind(&FeedbackData::OnCompressFileComplete,
+                   this,
+                   base::Passed(&compressed_file)));
+  }
 }
 
 void FeedbackData::OnGetTraceData(
@@ -121,22 +215,58 @@
   scoped_ptr<std::string> data(new std::string);
   data->swap(trace_data->data());
 
-  AddFile(kTraceFilename, data.Pass());
+  attached_filename_ = kTraceFilename;
+  attached_filedata_ = data.Pass();
+  attached_file_compression_complete_ = true;
+  trace_id_ = 0;
 
   set_category_tag(kPerformanceCategoryTag);
-  pending_op_count_--;
-  trace_id_ = 0;
+
   SendReport();
 }
 
-void FeedbackData::OnCompressComplete() {
+void FeedbackData::OnCompressLogsComplete(
+    scoped_ptr<std::string> compressed_logs) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  pending_op_count_--;
+
+  compressed_logs_ = compressed_logs.Pass();
+  syslogs_compression_complete_ = true;
+
+  SendReport();
+}
+
+void FeedbackData::OnCompressHistogramsComplete(
+    scoped_ptr<std::string> compressed_histograms) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  compressed_histograms_ = compressed_histograms.Pass();
+  histograms_compression_complete_ = true;
+
+  SendReport();
+}
+
+void FeedbackData::OnCompressFileComplete(
+    scoped_ptr<std::string> compressed_file) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  if (compressed_file.get()) {
+    attached_filedata_ = compressed_file.Pass();
+    attached_filename_.append(kZipExt);
+    attached_file_compression_complete_ = true;
+  } else {
+    attached_filename_.clear();
+    attached_filedata_.reset(NULL);
+  }
+
   SendReport();
 }
 
 bool FeedbackData::IsDataComplete() {
-  return pending_op_count_ == 0;
+  return (!sys_info_.get() || syslogs_compression_complete_) &&
+      (!histograms_.get() || histograms_compression_complete_) &&
+      (!attached_filedata_.get() || attached_file_compression_complete_) &&
+      !trace_id_ &&
+      feedback_page_data_complete_;
 }
 
 void FeedbackData::SendReport() {
diff --git a/chrome/browser/feedback/feedback_data.h b/chrome/browser/feedback/feedback_data.h
index 21c7dde..bc566f5 100644
--- a/chrome/browser/feedback/feedback_data.h
+++ b/chrome/browser/feedback/feedback_data.h
@@ -5,9 +5,12 @@
 #ifndef CHROME_BROWSER_FEEDBACK_FEEDBACK_DATA_H_
 #define CHROME_BROWSER_FEEDBACK_FEEDBACK_DATA_H_
 
+#include <map>
 #include <string>
+#include <vector>
 
-#include "chrome/browser/feedback/feedback_common.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -16,8 +19,13 @@
 }
 class Profile;
 
-class FeedbackData : public FeedbackCommon {
+class FeedbackData : public base::RefCountedThreadSafe<FeedbackData> {
  public:
+  typedef std::map<std::string, std::string> SystemLogsMap;
+
+  // Determine if the given feedback value is small enough to not need to
+  // be compressed.
+  static bool BelowCompressionThreshold(const std::string& content);
 
   FeedbackData();
 
@@ -38,6 +46,10 @@
   // Called once we have compressed our system logs.
   void OnCompressLogsComplete(scoped_ptr<std::string> compressed_logs);
 
+  // Called once we have compressed our histograms.
+  void OnCompressHistogramsComplete(
+      scoped_ptr<std::string> compressed_histograms);
+
   // Called once we have compressed our attached file.
   void OnCompressFileComplete(scoped_ptr<std::string> compressed_file);
 
@@ -51,13 +63,36 @@
 
   // Getters
   Profile* profile() const { return profile_; }
+  const std::string& category_tag() const { return category_tag_; }
+  const std::string& page_url() const { return page_url_; }
+  const std::string& description() const { return description_; }
+  const std::string& user_email() const { return user_email_; }
+  std::string* image() const { return image_.get(); }
   const std::string attached_filename() const { return attached_filename_; }
   const std::string attached_file_uuid() const { return attached_file_uuid_; }
+  std::string* attached_filedata() const { return attached_filedata_.get(); }
   const std::string screenshot_uuid() const { return screenshot_uuid_; }
   int trace_id() const { return trace_id_; }
+  SystemLogsMap* sys_info() const { return sys_info_.get(); }
+  std::string* compressed_logs() const { return compressed_logs_.get(); }
+  std::string* histograms() const { return histograms_.get(); }
+  std::string* compressed_histograms() const {
+    return compressed_histograms_.get();
+  }
 
   // Setters
   void set_profile(Profile* profile) { profile_ = profile; }
+  void set_category_tag(const std::string& category_tag) {
+    category_tag_ = category_tag;
+  }
+  void set_page_url(const std::string& page_url) { page_url_ = page_url; }
+  void set_description(const std::string& description) {
+    description_ = description;
+  }
+  void set_user_email(const std::string& user_email) {
+    user_email_ = user_email;
+  }
+  void set_image(scoped_ptr<std::string> image) { image_ = image.Pass(); }
   void set_attached_filename(const std::string& attached_filename) {
     attached_filename_ = attached_filename;
   }
@@ -70,23 +105,39 @@
   void set_trace_id(int trace_id) { trace_id_ = trace_id; }
 
  private:
-  virtual ~FeedbackData();
+  friend class base::RefCountedThreadSafe<FeedbackData>;
 
-  // Called once a compression operation is complete.
-  void OnCompressComplete();
+  virtual ~FeedbackData();
 
   void OnGetTraceData(int trace_id,
                       scoped_refptr<base::RefCountedString> trace_data);
 
   Profile* profile_;
 
+  std::string category_tag_;
+  std::string page_url_;
+  std::string description_;
+  std::string user_email_;
+  scoped_ptr<std::string> image_;
   std::string attached_filename_;
+  scoped_ptr<std::string> attached_filedata_;
+
   std::string attached_file_uuid_;
   std::string screenshot_uuid_;
 
   int trace_id_;
 
-  int pending_op_count_;
+  scoped_ptr<SystemLogsMap> sys_info_;
+  scoped_ptr<std::string> compressed_logs_;
+
+  scoped_ptr<std::string> histograms_;
+  scoped_ptr<std::string> compressed_histograms_;
+
+  // TODO(rkc): Refactor compressing logic into a simpler common implementation.
+  bool feedback_page_data_complete_;
+  bool syslogs_compression_complete_;
+  bool histograms_compression_complete_;
+  bool attached_file_compression_complete_;
   bool report_sent_;
 
   DISALLOW_COPY_AND_ASSIGN(FeedbackData);
diff --git a/chrome/browser/feedback/feedback_util.cc b/chrome/browser/feedback/feedback_util.cc
index 851291c..688891a 100644
--- a/chrome/browser/feedback/feedback_util.cc
+++ b/chrome/browser/feedback/feedback_util.cc
@@ -68,6 +68,10 @@
   return GURL();
 }
 
+const char kPngMimeType[] = "image/png";
+const char kArbitraryMimeType[] = "application/octet-stream";
+const char kHistogramsAttachmentName[] = "histograms.zip";
+const char kLogsAttachmentName[] = "system_logs.zip";
 
 #if defined(OS_CHROMEOS)
 const int kChromeOSProductId = 208;
@@ -75,6 +79,32 @@
 const int kChromeBrowserProductId = 237;
 #endif
 
+void AddFeedbackData(userfeedback::ExtensionSubmit* feedback_data,
+                     const std::string& key, const std::string& value) {
+  // Don't bother with empty keys or values
+  if (key == "" || value == "") return;
+  // Create log_value object and add it to the web_data object
+  userfeedback::ProductSpecificData log_value;
+  log_value.set_key(key);
+  log_value.set_value(value);
+  userfeedback::WebData* web_data = feedback_data->mutable_web_data();
+  *(web_data->add_product_specific_data()) = log_value;
+}
+
+// Adds data as an attachment to feedback_data if the data is non-empty.
+void AddAttachment(userfeedback::ExtensionSubmit* feedback_data,
+                   const char* name,
+                   std::string* data) {
+  if (data == NULL || data->empty())
+    return;
+
+  userfeedback::ProductSpecificBinaryData* attachment =
+      feedback_data->add_product_specific_binary_data();
+  attachment->set_mime_type(kArbitraryMimeType);
+  attachment->set_name(name);
+  attachment->set_data(*data);
+}
+
 }  // namespace
 
 namespace chrome {
@@ -101,6 +131,10 @@
     return;
   }
 
+  // We do not want to launch on an OTR profile.
+  profile = profile->GetOriginalProfile();
+  DCHECK(profile);
+
   extensions::FeedbackPrivateAPI* api =
       extensions::FeedbackPrivateAPI::GetFactoryInstance()->Get(profile);
 
@@ -121,15 +155,67 @@
   }
 
   userfeedback::ExtensionSubmit feedback_data;
-  data->PrepareReport(&feedback_data);
+  // Unused field, needs to be 0 though.
+  feedback_data.set_type_id(0);
+
+  userfeedback::CommonData* common_data = feedback_data.mutable_common_data();
+  // We're not using gaia ids, we're using the e-mail field instead.
+  common_data->set_gaia_id(0);
+  common_data->set_user_email(data->user_email());
+  common_data->set_description(data->description());
 
   std::string chrome_locale = g_browser_process->GetApplicationLocale();
+  common_data->set_source_description_language(chrome_locale);
 
-  feedback_data.mutable_common_data()->set_source_description_language(
-      chrome_locale);
+  userfeedback::WebData* web_data = feedback_data.mutable_web_data();
+  web_data->set_url(data->page_url());
+  web_data->mutable_navigator()->set_user_agent(GetUserAgent());
 
-  feedback_data.mutable_web_data()->mutable_navigator()->set_user_agent(
-      GetUserAgent());
+  gfx::Rect screen_size;
+  if (data->sys_info()) {
+    for (FeedbackData::SystemLogsMap::const_iterator i =
+        data->sys_info()->begin(); i != data->sys_info()->end(); ++i) {
+      if (FeedbackData::BelowCompressionThreshold(i->second))
+        AddFeedbackData(&feedback_data, i->first, i->second);
+    }
+
+    AddAttachment(&feedback_data, kLogsAttachmentName, data->compressed_logs());
+  }
+
+  if (data->histograms()) {
+    AddAttachment(&feedback_data,
+                  kHistogramsAttachmentName,
+                  data->compressed_histograms());
+  }
+
+  if (!data->attached_filename().empty()) {
+    // We need to use the UTF8Unsafe methods here to accomodate Windows, which
+    // uses wide strings to store filepaths.
+    std::string name = base::FilePath::FromUTF8Unsafe(
+        data->attached_filename()).BaseName().AsUTF8Unsafe();
+    AddAttachment(&feedback_data, name.c_str(), data->attached_filedata());
+  }
+
+  // NOTE: Screenshot needs to be processed after system info since we'll get
+  // the screenshot dimensions from system info.
+  if (data->image() && data->image()->size()) {
+    userfeedback::PostedScreenshot screenshot;
+    screenshot.set_mime_type(kPngMimeType);
+
+    // Set that we 'have' dimensions of the screenshot. These dimensions are
+    // ignored by the server but are a 'required' field in the protobuf.
+    userfeedback::Dimensions dimensions;
+    dimensions.set_width(0.0);
+    dimensions.set_height(0.0);
+
+    *(screenshot.mutable_dimensions()) = dimensions;
+    screenshot.set_binary_content(*data->image());
+
+    *(feedback_data.mutable_screenshot()) = screenshot;
+  }
+
+  if (data->category_tag().size())
+    feedback_data.set_bucket(data->category_tag());
 
   // Set whether we're reporting from ChromeOS or Chrome on another platform.
   userfeedback::ChromeData chrome_data;
@@ -184,6 +270,6 @@
   base::DeleteFile(zip_file, false);
 
   return succeed;
-}  // feedback_util
+}
 
 }  // namespace feedback_util
diff --git a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
index ebcc786..6db19b3 100644
--- a/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
+++ b/chrome/browser/feedback/system_logs/log_sources/chrome_internal_log_source.cc
@@ -8,10 +8,10 @@
 #include "base/sys_info.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/sync/about_sync_util.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/browser/ui/webui/crashes_ui.h"
 #include "chrome/common/chrome_version_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_system.h"
@@ -94,7 +94,7 @@
 
 void ChromeInternalLogSource::PopulateExtensionInfoLogs(
     SystemLogsResponse* response) {
-  if (!CrashesUI::CrashReportingUIEnabled())
+  if (!MetricsServiceHelper::IsCrashReportingEnabled())
     return;
 
   Profile* primary_profile =
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc
index 423e885..e2cb494 100644
--- a/chrome/browser/file_select_helper.cc
+++ b/chrome/browser/file_select_helper.cc
@@ -199,13 +199,11 @@
     const net::DirectoryLister::DirectoryListerData& data) {
   ActiveDirectoryEnumeration* entry = directory_enumerations_[id];
 
-  // Directory upload returns directories via a "." file, so that
-  // empty directories are included.  This util call just checks
-  // the flags in the structure; there's no file I/O going on.
+  // Directory upload only cares about files.
   if (data.info.IsDirectory())
-    entry->results_.push_back(data.path.Append(FILE_PATH_LITERAL(".")));
-  else
-    entry->results_.push_back(data.path);
+    return;
+
+  entry->results_.push_back(data.path);
 }
 
 void FileSelectHelper::OnListDone(int id, int error) {
diff --git a/chrome/browser/first_run/first_run.cc b/chrome/browser/first_run/first_run.cc
index d89e76b..5239ea6 100644
--- a/chrome/browser/first_run/first_run.cc
+++ b/chrome/browser/first_run/first_run.cc
@@ -31,6 +31,7 @@
 #include "chrome/browser/importer/importer_uma.h"
 #include "chrome/browser/importer/profile_writer.h"
 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -41,10 +42,12 @@
 #include "chrome/browser/signin/signin_tracker.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/global_error/global_error_service.h"
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
+#include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
@@ -361,8 +364,8 @@
            chrome::kChromeUIChromeSigninURL ||
        gaia::IsGaiaSignonRealm(contents->GetURL().GetOrigin()) ||
        signin::IsContinueUrlForWebBasedSigninFlow(contents->GetURL()) ||
-       contents->GetURL() == GURL(std::string(chrome::kChromeUISettingsURL) +
-                                  chrome::kSyncSetupSubPage))) {
+       (contents->GetURL() ==
+        chrome::GetSettingsUrl(chrome::kSyncSetupSubPage)))) {
     return;
   }
 
@@ -446,30 +449,6 @@
   }
 }
 
-bool IsFirstRunSentinelPresent() {
-  base::FilePath first_run_sentinel;
-  // Treat sentinel as being present if the path can't be obtained.
-  if (!first_run::internal::GetFirstRunSentinelFilePath(&first_run_sentinel) ||
-      base::PathExists(first_run_sentinel)) {
-    return true;
-  }
-  // Sentinel is truly absent if there's no legacy path or legacy doesn't exist.
-  base::FilePath legacy_first_run_sentinel;
-  if (!first_run::internal::GetLegacyFirstRunSentinelFilePath(
-          &legacy_first_run_sentinel) ||
-      !base::PathExists(legacy_first_run_sentinel)) {
-    return false;
-  }
-  // Migrate the legacy sentinel to the new location if it was found. This does
-  // a copy instead of a move to avoid breaking the developer build case where
-  // the First Run sentinel is dropped beside chrome.exe by a build action
-  // (i.e., at the legacy path).
-  bool migrated = base::CopyFile(legacy_first_run_sentinel, first_run_sentinel);
-  DPCHECK(migrated);
-  // Sentinel is present regardless of whether or not it was migrated.
-  return true;
-}
-
 }  // namespace
 
 namespace first_run {
@@ -564,11 +543,18 @@
       &out_prefs->suppress_default_browser_prompt_for_version);
 }
 
+bool GetFirstRunSentinelFilePath(base::FilePath* path) {
+  base::FilePath user_data_dir;
+  if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir))
+    return false;
+  *path = user_data_dir.Append(chrome::kFirstRunSentinel);
+  return true;
+}
+
 bool CreateSentinel() {
   base::FilePath first_run_sentinel;
-  if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel))
-    return false;
-  return base::WriteFile(first_run_sentinel, "", 0) != -1;
+  return GetFirstRunSentinelFilePath(&first_run_sentinel) &&
+      base::WriteFile(first_run_sentinel, "", 0) != -1;
 }
 
 // -- Platform-specific functions --
@@ -595,20 +581,15 @@
 MasterPrefs::~MasterPrefs() {}
 
 bool IsChromeFirstRun() {
-  if (internal::first_run_ != internal::FIRST_RUN_UNKNOWN)
-    return internal::first_run_ == internal::FIRST_RUN_TRUE;
-
-  internal::first_run_ = internal::FIRST_RUN_FALSE;
-
-  base::FilePath first_run_sentinel;
-  const CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kForceFirstRun)) {
-    internal::first_run_ = internal::FIRST_RUN_TRUE;
-  } else if (!command_line->HasSwitch(switches::kNoFirstRun) &&
-             !IsFirstRunSentinelPresent()) {
-    internal::first_run_ = internal::FIRST_RUN_TRUE;
+  if (internal::first_run_ == internal::FIRST_RUN_UNKNOWN) {
+    internal::first_run_ = internal::FIRST_RUN_FALSE;
+    const CommandLine* command_line = CommandLine::ForCurrentProcess();
+    if (command_line->HasSwitch(switches::kForceFirstRun) ||
+        (!command_line->HasSwitch(switches::kNoFirstRun) &&
+         !internal::IsFirstRunSentinelPresent())) {
+      internal::first_run_ = internal::FIRST_RUN_TRUE;
+    }
   }
-
   return internal::first_run_ == internal::FIRST_RUN_TRUE;
 }
 
@@ -636,9 +617,8 @@
 
 bool RemoveSentinel() {
   base::FilePath first_run_sentinel;
-  if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel))
-    return false;
-  return base::DeleteFile(first_run_sentinel, false);
+  return internal::GetFirstRunSentinelFilePath(&first_run_sentinel) &&
+      base::DeleteFile(first_run_sentinel, false);
 }
 
 bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) {
diff --git a/chrome/browser/first_run/first_run.h b/chrome/browser/first_run/first_run.h
index f9683fa..9a118a7 100644
--- a/chrome/browser/first_run/first_run.h
+++ b/chrome/browser/first_run/first_run.h
@@ -101,8 +101,7 @@
 // Register user preferences used by the MasterPrefs structure.
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
-// Removes the sentinel file created in ConfigDone(). Returns false if the
-// sentinel file could not be removed.
+// Remove the first run sentinel file; returns false on failure.
 bool RemoveSentinel();
 
 // Sets the kShowFirstRunBubbleOption local state pref so that the browser
diff --git a/chrome/browser/first_run/first_run_internal.h b/chrome/browser/first_run/first_run_internal.h
index 42e6089..70e3de5 100644
--- a/chrome/browser/first_run/first_run_internal.h
+++ b/chrome/browser/first_run/first_run_internal.h
@@ -34,22 +34,19 @@
     const installer::MasterPreferences& install_prefs,
     MasterPrefs* out_prefs);
 
-// Creates the sentinel file that signals that chrome has been configured.
+// Get the file path of the first run sentinel; returns false on failure.
+bool GetFirstRunSentinelFilePath(base::FilePath* path);
+
+// Create the first run sentinel file; returns false on failure.
 bool CreateSentinel();
 
 // -- Platform-specific functions --
 
 void DoPostImportPlatformSpecificTasks(Profile* profile);
 
-// Gives the full path to the sentinel file. The file might not exist.
-// This function has a common implementation on OS_POSIX and a windows specific
-// implementation.
-bool GetFirstRunSentinelFilePath(base::FilePath* path);
-
-// Populates |path| with the old path to first run sentinel for the current
-// configuration. Returns true if there is a legacy path for this configuration
-// and it could be obtained.
-bool GetLegacyFirstRunSentinelFilePath(base::FilePath* path);
+// Returns true if the sentinel file exists (or the path cannot be obtained).
+// Migrates Windows legacy sentinel files to the corrent location, if needed.
+bool IsFirstRunSentinelPresent();
 
 // This function has a common implementationin for all non-linux platforms, and
 // a linux specific implementation.
diff --git a/chrome/browser/first_run/first_run_internal_posix.cc b/chrome/browser/first_run/first_run_internal_posix.cc
index 8cd91a4..2cd4b61 100644
--- a/chrome/browser/first_run/first_run_internal_posix.cc
+++ b/chrome/browser/first_run/first_run_internal_posix.cc
@@ -23,8 +23,6 @@
 
 void DoPostImportPlatformSpecificTasks(Profile* profile) {
 #if !defined(OS_CHROMEOS)
-  // Aura needs a views implementation of the first run dialog for Linux.
-  // http://crbug.com/234637
   base::FilePath local_state_path;
   PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
   bool local_state_file_exists = base::PathExists(local_state_path);
@@ -45,19 +43,9 @@
 #endif
 }
 
-bool GetFirstRunSentinelFilePath(base::FilePath* path) {
-  base::FilePath first_run_sentinel;
-
-  if (!PathService::Get(chrome::DIR_USER_DATA, &first_run_sentinel))
-    return false;
-
-  *path = first_run_sentinel.Append(chrome::kFirstRunSentinel);
-  return true;
-}
-
-bool GetLegacyFirstRunSentinelFilePath(base::FilePath* path) {
-  // There is no legacy first run sentinel path on Posix.
-  return false;
+bool IsFirstRunSentinelPresent() {
+  base::FilePath sentinel;
+  return !GetFirstRunSentinelFilePath(&sentinel) || base::PathExists(sentinel);
 }
 
 bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) {
diff --git a/chrome/browser/first_run/first_run_internal_win.cc b/chrome/browser/first_run/first_run_internal_win.cc
index 2225cc8..494a01d 100644
--- a/chrome/browser/first_run/first_run_internal_win.cc
+++ b/chrome/browser/first_run/first_run_internal_win.cc
@@ -145,21 +145,28 @@
   }
 }
 
-bool GetFirstRunSentinelFilePath(base::FilePath* path) {
-  return InstallUtil::GetSentinelFilePath(
-      chrome::kFirstRunSentinel, BrowserDistribution::GetDistribution(), path);
-}
+bool IsFirstRunSentinelPresent() {
+  base::FilePath sentinel;
+  if (!GetFirstRunSentinelFilePath(&sentinel) || base::PathExists(sentinel))
+    return true;
 
-bool GetLegacyFirstRunSentinelFilePath(base::FilePath* path) {
-  // The first run sentinel for user-level installs on Windows used to
-  // be in the application directory.
+  // Copy any legacy first run sentinel file for Windows user-level installs
+  // from the application directory to the user data directory.
   base::FilePath exe_path;
-  if (!PathService::Get(base::DIR_EXE, &exe_path) ||
-      !InstallUtil::IsPerUserInstall(exe_path.value().c_str())) {
-    return false;
+  if (PathService::Get(base::DIR_EXE, &exe_path) &&
+      InstallUtil::IsPerUserInstall(exe_path.value().c_str())) {
+    base::FilePath legacy_sentinel = exe_path.Append(chrome::kFirstRunSentinel);
+    if (base::PathExists(legacy_sentinel)) {
+      // Copy the file instead of moving it to avoid breaking developer builds
+      // where the sentinel is dropped beside chrome.exe by a build action.
+      bool migrated = base::CopyFile(legacy_sentinel, sentinel);
+      DPCHECK(migrated);
+      // The sentinel is present regardless of whether or not it was migrated.
+      return true;
+    }
   }
-  *path = exe_path.Append(chrome::kFirstRunSentinel);
-  return true;
+
+  return false;
 }
 
 bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) {
diff --git a/chrome/browser/first_run/first_run_unittest.cc b/chrome/browser/first_run/first_run_unittest.cc
index bccc9e8..c5e0c70 100644
--- a/chrome/browser/first_run/first_run_unittest.cc
+++ b/chrome/browser/first_run/first_run_unittest.cc
@@ -21,12 +21,6 @@
   FirstRunTest() : user_data_dir_override_(chrome::DIR_USER_DATA) {}
   virtual ~FirstRunTest() {}
 
-  virtual void SetUp() OVERRIDE {
-    internal::GetFirstRunSentinelFilePath(&sentinel_path_);
-  }
-
-  base::FilePath sentinel_path_;
-
  private:
   base::ScopedPathOverride user_data_dir_override_;
 
@@ -34,11 +28,14 @@
 };
 
 TEST_F(FirstRunTest, RemoveSentinel) {
+  base::FilePath sentinel_path;
+  EXPECT_TRUE(internal::GetFirstRunSentinelFilePath(&sentinel_path));
+
   EXPECT_TRUE(internal::CreateSentinel());
-  EXPECT_TRUE(base::PathExists(sentinel_path_));
+  EXPECT_TRUE(base::PathExists(sentinel_path));
 
   EXPECT_TRUE(RemoveSentinel());
-  EXPECT_FALSE(base::PathExists(sentinel_path_));
+  EXPECT_FALSE(base::PathExists(sentinel_path));
 }
 
 TEST_F(FirstRunTest, SetupMasterPrefsFromInstallPrefs_VariationsSeed) {
diff --git a/chrome/browser/geolocation/chrome_access_token_store.cc b/chrome/browser/geolocation/chrome_access_token_store.cc
index 8b72425..bfed436 100644
--- a/chrome/browser/geolocation/chrome_access_token_store.cc
+++ b/chrome/browser/geolocation/chrome_access_token_store.cc
@@ -119,7 +119,7 @@
                               prefs::kGeolocationAccessToken);
   base::DictionaryValue* access_token_dictionary = update.Get();
   access_token_dictionary->SetWithoutPathExpansion(
-      server_url.spec(), base::Value::CreateStringValue(token));
+      server_url.spec(), new base::StringValue(token));
 }
 
 void ChromeAccessTokenStore::SaveAccessToken(
diff --git a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
index 456b68c..e63d448 100644
--- a/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
+++ b/chrome/browser/geolocation/chrome_geolocation_permission_context.cc
@@ -79,7 +79,7 @@
 GeolocationPermissionRequest::~GeolocationPermissionRequest() {}
 
 int GeolocationPermissionRequest::GetIconID() const {
-  return IDR_GEOLOCATION_INFOBAR_ICON;
+  return IDR_INFOBAR_GEOLOCATION;
 }
 
 base::string16 GeolocationPermissionRequest::GetMessageText() const {
diff --git a/chrome/browser/geolocation/geolocation_infobar_delegate.cc b/chrome/browser/geolocation/geolocation_infobar_delegate.cc
index da028ec..adec888 100644
--- a/chrome/browser/geolocation/geolocation_infobar_delegate.cc
+++ b/chrome/browser/geolocation/geolocation_infobar_delegate.cc
@@ -125,7 +125,7 @@
 }
 
 int GeolocationInfoBarDelegate::GetIconID() const {
-  return IDR_GEOLOCATION_INFOBAR_ICON;
+  return IDR_INFOBAR_GEOLOCATION;
 }
 
 InfoBarDelegate::Type GeolocationInfoBarDelegate::GetInfoBarType() const {
diff --git a/chrome/browser/google/google_util.cc b/chrome/browser/google/google_util.cc
index 53c4626..359cb73 100644
--- a/chrome/browser/google/google_util.cc
+++ b/chrome/browser/google/google_util.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/google/google_url_tracker.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/net/url_fixer_upper.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "net/base/url_util.h"
@@ -176,22 +177,35 @@
 
 #endif
 
+GURL CommandLineGoogleBaseURL() {
+  // Unit tests may add command-line flags after the first call to this
+  // function, so we don't simply initialize a static |base_url| directly and
+  // then unconditionally return it.
+  CR_DEFINE_STATIC_LOCAL(std::string, switch_value, ());
+  CR_DEFINE_STATIC_LOCAL(GURL, base_url, ());
+  std::string current_switch_value(
+      CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+          switches::kGoogleBaseURL));
+  if (current_switch_value != switch_value) {
+    switch_value = current_switch_value;
+    base_url = URLFixerUpper::FixupURL(switch_value, std::string());
+    if (!base_url.is_valid() || base_url.has_query() || base_url.has_ref())
+      base_url = GURL();
+  }
+  return base_url;
+}
+
 bool StartsWithCommandLineGoogleBaseURL(const GURL& url) {
-  const std::string base_url(CommandLine::ForCurrentProcess()->
-      GetSwitchValueASCII(switches::kGoogleBaseURL));
-  return !base_url.empty() &&
-      StartsWithASCII(url.possibly_invalid_spec(), base_url, true);
+  GURL base_url(CommandLineGoogleBaseURL());
+  return base_url.is_valid() &&
+      StartsWithASCII(url.possibly_invalid_spec(), base_url.spec(), true);
 }
 
 bool IsGoogleHostname(const std::string& host,
                       SubdomainPermission subdomain_permission) {
-  const std::string base_url(CommandLine::ForCurrentProcess()->
-      GetSwitchValueASCII(switches::kGoogleBaseURL));
-  if (!base_url.empty()) {
-    GURL base_gurl(base_url);
-    if (base_gurl.is_valid() && (host == base_gurl.host()))
-      return true;
-  }
+  GURL base_url(CommandLineGoogleBaseURL());
+  if (base_url.is_valid() && (host == base_url.host()))
+    return true;
 
   size_t tld_length = net::registry_controlled_domains::GetRegistryLength(
       host,
diff --git a/chrome/browser/google/google_util.h b/chrome/browser/google/google_util.h
index d9f08c9..717944c 100644
--- a/chrome/browser/google/google_util.h
+++ b/chrome/browser/google/google_util.h
@@ -55,6 +55,15 @@
 // install. Returns false if the information is not available.
 bool GetReactivationBrand(std::string* brand);
 
+// Returns the Google base URL specified on the command line, if it exists.
+// This performs some fixup and sanity-checking to ensure that the resulting URL
+// is valid and has no query or ref.
+GURL CommandLineGoogleBaseURL();
+
+// Returns true if a Google base URL was specified on the command line and |url|
+// begins with that base URL.  This uses a simple string equality check.
+bool StartsWithCommandLineGoogleBaseURL(const GURL& url);
+
 // WARNING: The following IsGoogleXXX() functions use heuristics to rule out
 // "obviously false" answers.  They do NOT guarantee that the string in question
 // is actually on a Google-owned domain, just that it looks plausible.  If you
@@ -75,10 +84,6 @@
   DISALLOW_NON_STANDARD_PORTS,
 };
 
-// Returns true if a Google base URL was specified on the command line and |url|
-// begins with that base URL.  This uses a simple string equality check.
-bool StartsWithCommandLineGoogleBaseURL(const GURL& url);
-
 // True if |host| is "[www.]google.<TLD>" with a valid TLD. If
 // |subdomain_permission| is ALLOW_SUBDOMAIN, we check against host
 // "*.google.<TLD>" instead.
diff --git a/chrome/browser/google/google_util_unittest.cc b/chrome/browser/google/google_util_unittest.cc
index 3701758..83794e2 100644
--- a/chrome/browser/google/google_util_unittest.cc
+++ b/chrome/browser/google/google_util_unittest.cc
@@ -289,7 +289,7 @@
                                  google_util::DISALLOW_NON_STANDARD_PORTS));
 }
 
-TEST(GoogleUtilTest, GoogleBaseURL) {
+TEST(GoogleUtilTest, GoogleBaseURLNotSpecified) {
   // When no command-line flag is specified, no input to
   // StartsWithCommandLineGoogleBaseURL() should return true.
   EXPECT_FALSE(StartsWithBaseURL(std::string()));
@@ -334,3 +334,23 @@
   EXPECT_FALSE(IsHomePage("http://www.foo.com/xyz"));
   EXPECT_TRUE(IsSearch("http://www.foo.com/search?q=a"));
 }
+
+TEST(GoogleUtilTest, GoogleBaseURLDisallowQuery) {
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "http://www.foo.com/?q=");
+  EXPECT_FALSE(google_util::CommandLineGoogleBaseURL().is_valid());
+}
+
+TEST(GoogleUtilTest, GoogleBaseURLDisallowRef) {
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "http://www.foo.com/#q=");
+  EXPECT_FALSE(google_util::CommandLineGoogleBaseURL().is_valid());
+}
+
+TEST(GoogleUtilTest, GoogleBaseURLFixup) {
+  CommandLine::ForCurrentProcess()->AppendSwitchASCII(switches::kGoogleBaseURL,
+                                                      "www.foo.com");
+  ASSERT_TRUE(google_util::CommandLineGoogleBaseURL().is_valid());
+  EXPECT_EQ("http://www.foo.com/",
+            google_util::CommandLineGoogleBaseURL().spec());
+}
diff --git a/chrome/browser/history/web_history_service.cc b/chrome/browser/history/web_history_service.cc
index 4573135..fe3008a 100644
--- a/chrome/browser/history/web_history_service.cc
+++ b/chrome/browser/history/web_history_service.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_token_service.h"
diff --git a/chrome/browser/infobars/infobar_container.cc b/chrome/browser/infobars/infobar_container.cc
index 8ef5b7e..703df3d 100644
--- a/chrome/browser/infobars/infobar_container.cc
+++ b/chrome/browser/infobars/infobar_container.cc
@@ -9,12 +9,9 @@
 #include <algorithm>
 
 #include "base/logging.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/infobars/infobar.h"
 #include "chrome/browser/infobars/infobar_delegate.h"
 #include "chrome/browser/infobars/infobar_service.h"
-#include "content/public/browser/notification_details.h"
-#include "content/public/browser/notification_source.h"
 #include "ui/gfx/animation/slide_animation.h"
 
 InfoBarContainer::Delegate::~Delegate() {
@@ -29,20 +26,26 @@
 InfoBarContainer::~InfoBarContainer() {
   // RemoveAllInfoBarsForDestruction() should have already cleared our infobars.
   DCHECK(infobars_.empty());
+  if (infobar_service_)
+    infobar_service_->RemoveObserver(this);
 }
 
 void InfoBarContainer::ChangeInfoBarService(InfoBarService* infobar_service) {
-  HideAllInfoBars();
+  if (infobar_service_)
+    infobar_service_->RemoveObserver(this);
+
+  // Hides all infobars in this container without animation.
+  while (!infobars_.empty()) {
+    InfoBar* infobar = infobars_.front();
+    // Inform the infobar that it's hidden.  If it was already closing, this
+    // deletes it.  Otherwise, this ensures the infobar will be deleted if it's
+    // closed while it's not in an InfoBarContainer.
+    infobar->Hide(false);
+  }
 
   infobar_service_ = infobar_service;
   if (infobar_service_) {
-    content::Source<InfoBarService> source(infobar_service_);
-    registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
-                   source);
-    registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
-                   source);
-    registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED,
-                   source);
+    infobar_service_->AddObserver(this);
 
     for (size_t i = 0; i < infobar_service_->infobar_count(); ++i) {
       // As when we removed the infobars above, we prevent callbacks to
@@ -107,54 +110,30 @@
   ChangeInfoBarService(NULL);
 }
 
-void InfoBarContainer::Observe(int type,
-                               const content::NotificationSource& source,
-                               const content::NotificationDetails& details) {
-  switch (type) {
-    case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED:
-      AddInfoBar(content::Details<InfoBar::AddedDetails>(details).ptr(),
-                 infobars_.size(), true, WANT_CALLBACK);
-      break;
-
-    case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED: {
-      InfoBar::RemovedDetails* removed_details =
-          content::Details<InfoBar::RemovedDetails>(details).ptr();
-      removed_details->first->Hide(removed_details->second);
-      UpdateInfoBarArrowTargetHeights();
-      break;
-    }
-
-    case chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED: {
-      InfoBar::ReplacedDetails* replaced_details =
-          content::Details<InfoBar::ReplacedDetails>(details).ptr();
-      InfoBar* old_infobar = replaced_details->first;
-      InfoBar* new_infobar = replaced_details->second;
-      PlatformSpecificReplaceInfoBar(old_infobar, new_infobar);
-      InfoBars::const_iterator i(std::find(infobars_.begin(), infobars_.end(),
-                                           old_infobar));
-      DCHECK(i != infobars_.end());
-      size_t position = i - infobars_.begin();
-      old_infobar->Hide(false);
-      AddInfoBar(new_infobar, position, false, WANT_CALLBACK);
-      break;
-    }
-
-    default:
-      NOTREACHED();
-      break;
-  }
+void InfoBarContainer::OnInfoBarAdded(InfoBar* infobar) {
+  AddInfoBar(infobar, infobars_.size(), true, WANT_CALLBACK);
 }
 
-void InfoBarContainer::HideAllInfoBars() {
-  registrar_.RemoveAll();
+void InfoBarContainer::OnInfoBarRemoved(InfoBar* infobar, bool animate) {
+  infobar->Hide(animate);
+  UpdateInfoBarArrowTargetHeights();
+}
 
-  while (!infobars_.empty()) {
-    InfoBar* infobar = infobars_.front();
-    // Inform the infobar that it's hidden.  If it was already closing, this
-    // deletes it.  Otherwise, this ensures the infobar will be deleted if it's
-    // closed while it's not in an InfoBarContainer.
-    infobar->Hide(false);
-  }
+void InfoBarContainer::OnInfoBarReplaced(InfoBar* old_infobar,
+                                         InfoBar* new_infobar) {
+  PlatformSpecificReplaceInfoBar(old_infobar, new_infobar);
+  InfoBars::const_iterator i(std::find(infobars_.begin(), infobars_.end(),
+                                       old_infobar));
+  DCHECK(i != infobars_.end());
+  size_t position = i - infobars_.begin();
+  old_infobar->Hide(false);
+  AddInfoBar(new_infobar, position, false, WANT_CALLBACK);
+}
+
+void InfoBarContainer::OnServiceShuttingDown(InfoBarService* service) {
+  DCHECK_EQ(infobar_service_, service);
+  infobar_service_->RemoveObserver(this);
+  infobar_service_ = NULL;
 }
 
 void InfoBarContainer::AddInfoBar(InfoBar* infobar,
diff --git a/chrome/browser/infobars/infobar_container.h b/chrome/browser/infobars/infobar_container.h
index 6cfaacf..c605138 100644
--- a/chrome/browser/infobars/infobar_container.h
+++ b/chrome/browser/infobars/infobar_container.h
@@ -9,12 +9,10 @@
 
 #include "base/compiler_specific.h"
 #include "base/time/time.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "chrome/browser/infobars/infobar_service.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 class InfoBar;
-class InfoBarService;
 
 // InfoBarContainer is a cross-platform base class to handle the visibility-
 // related aspects of InfoBars.  While InfoBarService owns the InfoBars, the
@@ -23,7 +21,7 @@
 //
 // Platforms need to subclass this to implement a few platform-specific
 // functions, which are pure virtual here.
-class InfoBarContainer : public content::NotificationObserver {
+class InfoBarContainer : public InfoBarService::Observer {
  public:
   class Delegate {
    public:
@@ -101,13 +99,12 @@
  private:
   typedef std::vector<InfoBar*> InfoBars;
 
-  // content::NotificationObserver:
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
-  // Hides all infobars in this container without animation.
-  void HideAllInfoBars();
+  // InfoBarService::Observer:
+  virtual void OnInfoBarAdded(InfoBar* infobar) OVERRIDE;
+  virtual void OnInfoBarRemoved(InfoBar* infobar, bool animate) OVERRIDE;
+  virtual void OnInfoBarReplaced(InfoBar* old_infobar,
+                                 InfoBar* new_infobar) OVERRIDE;
+  virtual void OnServiceShuttingDown(InfoBarService* service) OVERRIDE;
 
   // Adds |infobar| to this container before the existing infobar at position
   // |position| and calls Show() on it.  |animate| is passed along to
@@ -123,7 +120,6 @@
   void UpdateInfoBarArrowTargetHeights();
   int ArrowTargetHeightForInfoBar(size_t infobar_index) const;
 
-  content::NotificationRegistrar registrar_;
   Delegate* delegate_;
   InfoBarService* infobar_service_;
   InfoBars infobars_;
diff --git a/chrome/browser/infobars/infobar_delegate.cc b/chrome/browser/infobars/infobar_delegate.cc
index bef38aa..7039c9e 100644
--- a/chrome/browser/infobars/infobar_delegate.cc
+++ b/chrome/browser/infobars/infobar_delegate.cc
@@ -91,10 +91,6 @@
   return NULL;
 }
 
-ThreeDAPIInfoBarDelegate* InfoBarDelegate::AsThreeDAPIInfoBarDelegate() {
-  return NULL;
-}
-
 TranslateInfoBarDelegate* InfoBarDelegate::AsTranslateInfoBarDelegate() {
   return NULL;
 }
diff --git a/chrome/browser/infobars/infobar_delegate.h b/chrome/browser/infobars/infobar_delegate.h
index fc37ddd..9d6a041 100644
--- a/chrome/browser/infobars/infobar_delegate.h
+++ b/chrome/browser/infobars/infobar_delegate.h
@@ -94,7 +94,6 @@
       AsRegisterProtocolHandlerInfoBarDelegate();
   virtual ScreenCaptureInfoBarDelegate* AsScreenCaptureInfoBarDelegate();
   virtual ThemeInstalledInfoBarDelegate* AsThemePreviewInfobarDelegate();
-  virtual ThreeDAPIInfoBarDelegate* AsThreeDAPIInfoBarDelegate();
   virtual TranslateInfoBarDelegate* AsTranslateInfoBarDelegate();
 
   void set_infobar(InfoBar* infobar) { infobar_ = infobar; }
diff --git a/chrome/browser/infobars/infobar_service.cc b/chrome/browser/infobars/infobar_service.cc
index b3bcaa0..a97d3a5 100644
--- a/chrome/browser/infobars/infobar_service.cc
+++ b/chrome/browser/infobars/infobar_service.cc
@@ -35,6 +35,9 @@
   infobars_.push_back(infobar_ptr);
   infobar_ptr->SetOwner(this);
 
+  FOR_EACH_OBSERVER(Observer, observer_list_, OnInfoBarAdded(infobar_ptr));
+  // TODO(droger): Remove the notifications and use observers instead.
+  // See http://crbug.com/354380
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_ADDED,
       content::Source<InfoBarService>(this),
@@ -66,6 +69,11 @@
   // to AddInfoBar() or similar, we don't dupe-check against this infobar.
   infobars_.erase(++i);
 
+  FOR_EACH_OBSERVER(Observer,
+                    observer_list_,
+                    OnInfoBarReplaced(old_infobar, new_infobar_ptr));
+  // TODO(droger): Remove the notifications and use observers instead.
+  // See http://crbug.com/354380
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REPLACED,
       content::Source<InfoBarService>(this),
@@ -75,6 +83,14 @@
   return new_infobar_ptr;
 }
 
+void InfoBarService::AddObserver(Observer* obs) {
+  observer_list_.AddObserver(obs);
+}
+
+void InfoBarService::RemoveObserver(Observer* obs) {
+  observer_list_.RemoveObserver(obs);
+}
+
 InfoBarService::InfoBarService(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       infobars_enabled_(true) {
@@ -87,6 +103,7 @@
   // Destroy all remaining InfoBars.  It's important to not animate here so that
   // we guarantee that we'll delete all delegates before we do anything else.
   RemoveAllInfoBars(false);
+  FOR_EACH_OBSERVER(Observer, observer_list_, OnServiceShuttingDown(this));
 }
 
 void InfoBarService::RenderProcessGone(base::TerminationStatus status) {
@@ -142,6 +159,10 @@
 
   // This notification must happen before the call to CloseSoon() below, since
   // observers may want to access |infobar| and that call can delete it.
+  FOR_EACH_OBSERVER(Observer, observer_list_,
+                    OnInfoBarRemoved(infobar, animate));
+  // TODO(droger): Remove the notifications and use observers instead.
+  // See http://crbug.com/354380
   InfoBar::RemovedDetails removed_details(infobar, animate);
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_TAB_CONTENTS_INFOBAR_REMOVED,
diff --git a/chrome/browser/infobars/infobar_service.h b/chrome/browser/infobars/infobar_service.h
index f5fd8b1..7be2e7c 100644
--- a/chrome/browser/infobars/infobar_service.h
+++ b/chrome/browser/infobars/infobar_service.h
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 
@@ -18,6 +19,17 @@
 class InfoBarService : public content::WebContentsObserver,
                        public content::WebContentsUserData<InfoBarService> {
  public:
+
+  // Observer class for infobar events.
+  class Observer {
+   public:
+    virtual void OnInfoBarAdded(InfoBar* infobar) = 0;
+    virtual void OnInfoBarRemoved(InfoBar* infobar, bool animate) = 0;
+    virtual void OnInfoBarReplaced(InfoBar* old_infobar,
+                                   InfoBar* new_infobar) = 0;
+    virtual void OnServiceShuttingDown(InfoBarService* service) = 0;
+  };
+
   // Adds the specified |infobar|, which already owns a delegate.
   //
   // If infobars are disabled for this tab or the tab already has an infobar
@@ -62,6 +74,9 @@
     return content::WebContentsObserver::web_contents();
   }
 
+  void AddObserver(Observer* obs);
+  void RemoveObserver(Observer* obs);
+
  private:
   friend class content::WebContentsUserData<InfoBarService>;
 
@@ -92,6 +107,7 @@
 
   InfoBars infobars_;
   bool infobars_enabled_;
+  ObserverList<Observer, true> observer_list_;
 
   DISALLOW_COPY_AND_ASSIGN(InfoBarService);
 };
diff --git a/chrome/browser/invalidation/fake_invalidation_service.cc b/chrome/browser/invalidation/fake_invalidation_service.cc
index 56b41e9..8c34f00 100644
--- a/chrome/browser/invalidation/fake_invalidation_service.cc
+++ b/chrome/browser/invalidation/fake_invalidation_service.cc
@@ -68,7 +68,7 @@
 }
 
 void FakeInvalidationService::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> caller) {
+    base::Callback<void(const base::DictionaryValue&)> caller) const {
   base::DictionaryValue value;
   caller.Run(value);
 }
diff --git a/chrome/browser/invalidation/fake_invalidation_service.h b/chrome/browser/invalidation/fake_invalidation_service.h
index 661c9d0..d958bf5 100644
--- a/chrome/browser/invalidation/fake_invalidation_service.h
+++ b/chrome/browser/invalidation/fake_invalidation_service.h
@@ -70,7 +70,7 @@
   virtual std::string GetInvalidatorClientId() const OVERRIDE;
   virtual InvalidationLogger* GetInvalidationLogger() OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> caller) OVERRIDE;
+      base::Callback<void(const base::DictionaryValue&)> caller) const OVERRIDE;
   virtual InvalidationAuthProvider* GetInvalidationAuthProvider() OVERRIDE;
 
   void SetInvalidatorState(syncer::InvalidatorState state);
diff --git a/chrome/browser/invalidation/gcm_invalidation_bridge.cc b/chrome/browser/invalidation/gcm_invalidation_bridge.cc
index c02282a..0a17588 100644
--- a/chrome/browser/invalidation/gcm_invalidation_bridge.cc
+++ b/chrome/browser/invalidation/gcm_invalidation_bridge.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_constants.h"
 
 namespace invalidation {
@@ -153,6 +153,7 @@
     : OAuth2TokenService::Consumer("gcm_network_channel"),
       gcm_profile_service_(gcm_profile_service),
       auth_provider_(auth_provider),
+      subscribed_for_incoming_messages_(false),
       weak_factory_(this) {}
 
 GCMInvalidationBridge::~GCMInvalidationBridge() {
@@ -296,8 +297,6 @@
   it = message.data.find(kEchoTokenKey);
   if (it != message.data.end())
     echo_token = it->second;
-  if (content.empty())
-    return;
 
   core_thread_task_runner_->PostTask(
       FROM_HERE,
diff --git a/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc b/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc
index 2a99ec3..22243e0 100644
--- a/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc
+++ b/chrome/browser/invalidation/gcm_invalidation_bridge_unittest.cc
@@ -8,10 +8,10 @@
 #include "chrome/browser/services/gcm/gcm_profile_service.h"
 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -73,9 +73,8 @@
 
   virtual void SetUp() OVERRIDE {
     TestingProfile::Builder builder;
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        &FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
+    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
+                              &BuildAutoIssuingFakeProfileOAuth2TokenService);
     builder.AddTestingFactory(gcm::GCMProfileServiceFactory::GetInstance(),
                               &FakeGCMProfileService::Build);
     profile_ = builder.Build();
diff --git a/chrome/browser/invalidation/invalidation_service.h b/chrome/browser/invalidation/invalidation_service.h
index ed026c3..f5f8717 100644
--- a/chrome/browser/invalidation/invalidation_service.h
+++ b/chrome/browser/invalidation/invalidation_service.h
@@ -107,7 +107,7 @@
 
   // Triggers requests of internal status.
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> post_caller) = 0;
+      base::Callback<void(const base::DictionaryValue&)> post_caller) const = 0;
 
   // Returns the authentication provider.
   virtual InvalidationAuthProvider* GetInvalidationAuthProvider() = 0;
diff --git a/chrome/browser/invalidation/invalidation_service_android.cc b/chrome/browser/invalidation/invalidation_service_android.cc
index c7bc445..f53f5be 100644
--- a/chrome/browser/invalidation/invalidation_service_android.cc
+++ b/chrome/browser/invalidation/invalidation_service_android.cc
@@ -65,7 +65,7 @@
 }
 
 void InvalidationServiceAndroid::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> return_callback) {
+    base::Callback<void(const base::DictionaryValue&)> return_callback) const {
 }
 
 InvalidationAuthProvider*
diff --git a/chrome/browser/invalidation/invalidation_service_android.h b/chrome/browser/invalidation/invalidation_service_android.h
index 917d9a3..039bacb 100644
--- a/chrome/browser/invalidation/invalidation_service_android.h
+++ b/chrome/browser/invalidation/invalidation_service_android.h
@@ -53,7 +53,8 @@
   virtual std::string GetInvalidatorClientId() const OVERRIDE;
   virtual InvalidationLogger* GetInvalidationLogger() OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> caller) OVERRIDE;
+      base::Callback<void(const base::DictionaryValue&)> caller) const
+      OVERRIDE;
   virtual InvalidationAuthProvider* GetInvalidationAuthProvider() OVERRIDE;
 
   // content::NotificationObserver implementation.
diff --git a/chrome/browser/invalidation/invalidation_service_factory.cc b/chrome/browser/invalidation/invalidation_service_factory.cc
index b0907b5..430d8ca 100644
--- a/chrome/browser/invalidation/invalidation_service_factory.cc
+++ b/chrome/browser/invalidation/invalidation_service_factory.cc
@@ -18,8 +18,10 @@
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
+#include "chrome/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/user_prefs/pref_registry_syncable.h"
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/invalidation/invalidation_controller_android.h"
@@ -107,6 +109,10 @@
 
 void InvalidationServiceFactory::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
+  registry->RegisterBooleanPref(
+      prefs::kInvalidationServiceUseGCMChannel,
+      false,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
   InvalidatorStorage::RegisterProfilePrefs(registry);
 }
 
diff --git a/chrome/browser/invalidation/p2p_invalidation_service.cc b/chrome/browser/invalidation/p2p_invalidation_service.cc
index 4ee9f91..d9cde3f 100644
--- a/chrome/browser/invalidation/p2p_invalidation_service.cc
+++ b/chrome/browser/invalidation/p2p_invalidation_service.cc
@@ -79,7 +79,7 @@
 }
 
 void P2PInvalidationService::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> caller) {
+    base::Callback<void(const base::DictionaryValue&)> caller) const {
   base::DictionaryValue value;
   caller.Run(value);
 }
diff --git a/chrome/browser/invalidation/p2p_invalidation_service.h b/chrome/browser/invalidation/p2p_invalidation_service.h
index 0eb7e53..af493a4 100644
--- a/chrome/browser/invalidation/p2p_invalidation_service.h
+++ b/chrome/browser/invalidation/p2p_invalidation_service.h
@@ -47,7 +47,7 @@
   virtual std::string GetInvalidatorClientId() const OVERRIDE;
   virtual InvalidationLogger* GetInvalidationLogger() OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> caller) OVERRIDE;
+      base::Callback<void(const base::DictionaryValue&)> caller) const OVERRIDE;
   virtual InvalidationAuthProvider* GetInvalidationAuthProvider() OVERRIDE;
 
   void UpdateCredentials(const std::string& username,
diff --git a/chrome/browser/invalidation/profile_invalidation_auth_provider.cc b/chrome/browser/invalidation/profile_invalidation_auth_provider.cc
index 8ccfa0e..468520d 100644
--- a/chrome/browser/invalidation/profile_invalidation_auth_provider.cc
+++ b/chrome/browser/invalidation/profile_invalidation_auth_provider.cc
@@ -5,7 +5,7 @@
 #include "chrome/browser/invalidation/profile_invalidation_auth_provider.h"
 
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 namespace invalidation {
 
diff --git a/chrome/browser/invalidation/profile_invalidation_auth_provider.h b/chrome/browser/invalidation/profile_invalidation_auth_provider.h
index 7c8c713..aa98828 100644
--- a/chrome/browser/invalidation/profile_invalidation_auth_provider.h
+++ b/chrome/browser/invalidation/profile_invalidation_auth_provider.h
@@ -7,7 +7,7 @@
 
 #include "base/macros.h"
 #include "chrome/browser/invalidation/invalidation_auth_provider.h"
-#include "chrome/browser/signin/signin_manager_base.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 
 class LoginUIService;
 class ProfileOAuth2TokenService;
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.cc b/chrome/browser/invalidation/ticl_invalidation_service.cc
index 8da391e..536d965 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service.cc
@@ -6,14 +6,18 @@
 
 #include "base/command_line.h"
 #include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
 #include "chrome/browser/invalidation/gcm_invalidation_bridge.h"
 #include "chrome/browser/invalidation/invalidation_auth_provider.h"
 #include "chrome/browser/invalidation/invalidation_logger.h"
 #include "chrome/browser/invalidation/invalidation_service_util.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/services/gcm/gcm_profile_service.h"
 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
 #include "chrome/common/chrome_content_client.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "sync/notifier/gcm_network_channel_delegate.h"
 #include "sync/notifier/invalidation_util.h"
@@ -64,6 +68,7 @@
       auth_provider_(auth_provider.Pass()),
       invalidator_registrar_(new syncer::InvalidatorRegistrar()),
       request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy),
+      network_channel_type_(PUSH_CLIENT_CHANNEL),
       logger_() {}
 
 TiclInvalidationService::~TiclInvalidationService() {
@@ -80,8 +85,23 @@
     invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
   }
 
+  pref_change_registrar_.Init(profile_->GetPrefs());
+  pref_change_registrar_.Add(
+      prefs::kInvalidationServiceUseGCMChannel,
+      base::Bind(&TiclInvalidationService::UpdateInvalidationNetworkChannel,
+                 base::Unretained(this)));
+  pref_change_registrar_.Add(
+      prefs::kGCMChannelEnabled,
+      base::Bind(&TiclInvalidationService::UpdateInvalidationNetworkChannel,
+                 base::Unretained(this)));
+
+  UpdateInvalidationNetworkChannel();
+  UMA_HISTOGRAM_ENUMERATION("Invalidations.NetworkChannel",
+                            network_channel_type_,
+                            NETWORK_CHANNELS_COUNT);
+
   if (IsReadyToStart()) {
-    StartInvalidator(PUSH_CLIENT_CHANNEL);
+    StartInvalidator(network_channel_type_);
   }
 
   auth_provider_->AddObserver(this);
@@ -162,9 +182,11 @@
 }
 
 void TiclInvalidationService::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> return_callback) {
-  return_callback.Run(network_channel_options_);
-  invalidator_->RequestDetailedStatus(return_callback);
+    base::Callback<void(const base::DictionaryValue&)> return_callback) const {
+  if (IsStarted()) {
+    return_callback.Run(network_channel_options_);
+    invalidator_->RequestDetailedStatus(return_callback);
+  }
 }
 
 void TiclInvalidationService::RequestAccessToken() {
@@ -195,7 +217,7 @@
   request_access_token_backoff_.Reset();
   access_token_ = access_token;
   if (!IsStarted() && IsReadyToStart()) {
-    StartInvalidator(PUSH_CLIENT_CHANNEL);
+    StartInvalidator(network_channel_type_);
   } else {
     UpdateInvalidatorCredentials();
   }
@@ -235,7 +257,7 @@
     const std::string& account_id) {
   if (auth_provider_->GetAccountId() == account_id) {
     if (!IsStarted() && IsReadyToStart()) {
-      StartInvalidator(PUSH_CLIENT_CHANNEL);
+      StartInvalidator(network_channel_type_);
     }
   }
 }
@@ -335,7 +357,7 @@
   return true;
 }
 
-bool TiclInvalidationService::IsStarted() {
+bool TiclInvalidationService::IsStarted() const {
   return invalidator_.get() != NULL;
 }
 
@@ -346,7 +368,9 @@
   DCHECK(invalidator_storage_);
   DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty());
 
-  if (access_token_.empty()) {
+  // Request access token for PushClientChannel. GCMNetworkChannel will request
+  // access token before sending message to server.
+  if (network_channel == PUSH_CLIENT_CHANNEL && access_token_.empty()) {
     DVLOG(1)
         << "TiclInvalidationService: "
         << "Deferring start until we have an access token.";
@@ -405,6 +429,25 @@
       invalidator_registrar_->GetAllRegisteredIds());
 }
 
+void TiclInvalidationService::UpdateInvalidationNetworkChannel() {
+  InvalidationNetworkChannel network_channel_type = PUSH_CLIENT_CHANNEL;
+  if (gcm::GCMProfileService::GetGCMEnabledState(profile_) ==
+          gcm::GCMProfileService::ALWAYS_ENABLED &&
+      (profile_->GetPrefs()->GetBoolean(
+           prefs::kInvalidationServiceUseGCMChannel) ||
+       CommandLine::ForCurrentProcess()->HasSwitch(
+           switches::kInvalidationUseGCMChannel))) {
+    network_channel_type = GCM_NETWORK_CHANNEL;
+  }
+  if (network_channel_type_ == network_channel_type)
+    return;
+  network_channel_type_ = network_channel_type;
+  if (IsStarted()) {
+    StopInvalidator();
+    StartInvalidator(network_channel_type_);
+  }
+}
+
 void TiclInvalidationService::UpdateInvalidatorCredentials() {
   std::string email = auth_provider_->GetAccountId();
 
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.h b/chrome/browser/invalidation/ticl_invalidation_service.h
index c28e585..684ed2a 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.h
+++ b/chrome/browser/invalidation/ticl_invalidation_service.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_change_registrar.h"
 #include "base/threading/non_thread_safe.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/invalidation/invalidation_auth_provider.h"
@@ -15,7 +16,7 @@
 #include "chrome/browser/invalidation/invalidation_service.h"
 #include "chrome/browser/invalidation/invalidator_storage.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "net/base/backoff_entry.h"
 #include "sync/notifier/invalidation_handler.h"
@@ -39,6 +40,15 @@
                                 public InvalidationAuthProvider::Observer,
                                 public syncer::InvalidationHandler {
  public:
+  enum InvalidationNetworkChannel {
+    PUSH_CLIENT_CHANNEL = 0,
+    GCM_NETWORK_CHANNEL = 1,
+
+    // This enum is used in UMA_HISTOGRAM_ENUMERATION. Insert new values above
+    // this line.
+    NETWORK_CHANNELS_COUNT = 2
+  };
+
   TiclInvalidationService(scoped_ptr<InvalidationAuthProvider> auth_provider,
                           Profile* profile);
   virtual ~TiclInvalidationService();
@@ -58,7 +68,7 @@
   virtual std::string GetInvalidatorClientId() const OVERRIDE;
   virtual InvalidationLogger* GetInvalidationLogger() OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> caller) OVERRIDE;
+      base::Callback<void(const base::DictionaryValue&)> caller) const OVERRIDE;
   virtual InvalidationAuthProvider* GetInvalidationAuthProvider() OVERRIDE;
 
   void RequestAccessToken();
@@ -94,17 +104,14 @@
   void InitForTest(syncer::Invalidator* invalidator);
 
   friend class TiclInvalidationServiceTestDelegate;
+  friend class TiclInvalidationServiceChannelTest;
 
  private:
-  enum InvalidationNetworkChannel {
-    PUSH_CLIENT_CHANNEL = 0,
-    GCM_NETWORK_CHANNEL = 1
-  };
-
   bool IsReadyToStart();
-  bool IsStarted();
+  bool IsStarted() const;
 
   void StartInvalidator(InvalidationNetworkChannel network_channel);
+  void UpdateInvalidationNetworkChannel();
   void UpdateInvalidatorCredentials();
   void StopInvalidator();
 
@@ -125,6 +132,8 @@
   base::OneShotTimer<TiclInvalidationService> request_access_token_retry_timer_;
   net::BackoffEntry request_access_token_backoff_;
 
+  PrefChangeRegistrar pref_change_registrar_;
+  InvalidationNetworkChannel network_channel_type_;
   scoped_ptr<GCMInvalidationBridge> gcm_invalidation_bridge_;
 
   // The invalidation logger object we use to record state changes
diff --git a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
index f86dc5a..c78101c 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
@@ -4,12 +4,15 @@
 
 #include "chrome/browser/invalidation/ticl_invalidation_service.h"
 
+#include "base/prefs/pref_service.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/invalidation/invalidation_service_test_template.h"
 #include "chrome/browser/invalidation/profile_invalidation_auth_provider.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
+#include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "sync/notifier/fake_invalidation_handler.h"
 #include "sync/notifier/fake_invalidator.h"
@@ -67,4 +70,80 @@
     TiclInvalidationServiceTest, InvalidationServiceTest,
     TiclInvalidationServiceTestDelegate);
 
+class TiclInvalidationServiceChannelTest : public ::testing::Test {
+ public:
+  TiclInvalidationServiceChannelTest() {}
+  virtual ~TiclInvalidationServiceChannelTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              FakeSigninManagerBase::Build);
+    profile_ = builder.Build();
+    fake_signin_manager_ = static_cast<SigninManagerBase*>(
+        SigninManagerFactory::GetForProfile(profile_.get()));
+    token_service_.reset(new FakeProfileOAuth2TokenService);
+
+    scoped_ptr<InvalidationAuthProvider> auth_provider(
+        new ProfileInvalidationAuthProvider(
+            fake_signin_manager_, token_service_.get(), NULL));
+    invalidation_service_.reset(
+        new TiclInvalidationService(auth_provider.Pass(), profile_.get()));
+    invalidation_service_->Init();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    invalidation_service_->Shutdown();
+  }
+
+  TiclInvalidationService::InvalidationNetworkChannel GetNetworkChannel() {
+    return invalidation_service_->network_channel_type_;
+  }
+
+ protected:
+  scoped_ptr<TestingProfile> profile_;
+  SigninManagerBase* fake_signin_manager_;
+  scoped_ptr<FakeProfileOAuth2TokenService> token_service_;
+  scoped_ptr<TiclInvalidationService> invalidation_service_;
+};
+
+TEST_F(TiclInvalidationServiceChannelTest, ChannelSelectionTest) {
+  EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+  // If stars allign use GCM channel.
+  profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
+  profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+                                   true);
+  EXPECT_EQ(TiclInvalidationService::GCM_NETWORK_CHANNEL, GetNetworkChannel());
+
+  // If Invalidation channel setting is not set or says false fall back to push
+  // channel.
+  profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
+
+  profile_->GetPrefs()->ClearPref(prefs::kInvalidationServiceUseGCMChannel);
+  EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+  profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+                                   false);
+  EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+  // If invalidation channel setting says use GCM but GCM is not ALWAYS_ENABLED
+  // then fall back to push channel.
+  profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+                                   false);
+
+  profile_->GetPrefs()->ClearPref(prefs::kGCMChannelEnabled);
+  EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+  profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, false);
+  EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+  // If first invalidation setting gets enabled and after that gcm setting gets
+  // enabled then should still switch to GCM channel.
+  profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+                                   true);
+  profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
+  EXPECT_EQ(TiclInvalidationService::GCM_NETWORK_CHANNEL, GetNetworkChannel());
+}
+
 }  // namespace invalidation
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index 5e40680..46e04bf 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -48,7 +48,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/cookie_store_factory.h"
 #include "net/base/host_mapping_rules.h"
-#include "net/base/ip_mapping_rules.h"
 #include "net/base/net_util.h"
 #include "net/base/network_time_notifier.h"
 #include "net/base/sdch_manager.h"
@@ -61,7 +60,6 @@
 #include "net/dns/host_cache.h"
 #include "net/dns/host_resolver.h"
 #include "net/dns/mapped_host_resolver.h"
-#include "net/dns/mapped_ip_resolver.h"
 #include "net/ftp/ftp_network_layer.h"
 #include "net/http/http_auth_filter.h"
 #include "net/http/http_auth_handler_factory.h"
@@ -201,28 +199,17 @@
     global_host_resolver->SetDefaultAddressFamily(net::ADDRESS_FAMILY_IPV4);
   }
 
-  // If hostname or IP remappings were specified on the command-line, layer
-  // these rules on top of the real host resolver. Hostname remapping allows
-  // forwarding of all requests to hosts (matching a pattern) through a
-  // designated test server.   IP remapping allows for all IP resolutions that
-  // match a given pattern, such as those destined for a specific CDN, to be
-  // instead directed to a specific/alternate IP address.
-  if (command_line.HasSwitch(switches::kHostResolverRules)) {
-    scoped_ptr<net::MappedHostResolver> remapped_resolver(
-        new net::MappedHostResolver(global_host_resolver.Pass()));
-    remapped_resolver->SetRulesFromString(
-        command_line.GetSwitchValueASCII(switches::kHostResolverRules));
-    global_host_resolver = remapped_resolver.Pass();
-  }
+  // If hostname remappings were specified on the command-line, layer these
+  // rules on top of the real host resolver. This allows forwarding all requests
+  // through a designated test server.
+  if (!command_line.HasSwitch(switches::kHostResolverRules))
+    return global_host_resolver.PassAs<net::HostResolver>();
 
-  if (command_line.HasSwitch(switches::kIpResolverRules)) {
-    scoped_ptr<net::MappedIPResolver> remapped_resolver(
-        new net::MappedIPResolver(global_host_resolver.Pass()));
-    remapped_resolver->SetRulesFromString(
-        command_line.GetSwitchValueASCII(switches::kIpResolverRules));
-    global_host_resolver = remapped_resolver.Pass();
-  }
-  return global_host_resolver.Pass();
+  scoped_ptr<net::MappedHostResolver> remapped_resolver(
+      new net::MappedHostResolver(global_host_resolver.Pass()));
+  remapped_resolver->SetRulesFromString(
+      command_line.GetSwitchValueASCII(switches::kHostResolverRules));
+  return remapped_resolver.PassAs<net::HostResolver>();
 }
 
 // TODO(willchan): Remove proxy script fetcher context since it's not necessary
diff --git a/chrome/browser/lifetime/application_lifetime.cc b/chrome/browser/lifetime/application_lifetime.cc
index b7eb115..ca2b639 100644
--- a/chrome/browser/lifetime/application_lifetime.cc
+++ b/chrome/browser/lifetime/application_lifetime.cc
@@ -113,9 +113,8 @@
   // If there are no browsers and closing the last browser would quit the
   // application, send the APP_TERMINATING action here. Otherwise, it will be
   // sent by RemoveBrowser() when the last browser has closed.
-  if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() ||
-      (chrome::GetTotalBrowserCount() == 0 &&
-       (browser_shutdown::IsTryingToQuit() || !chrome::WillKeepAlive()))) {
+  if (chrome::GetTotalBrowserCount() == 0 &&
+      (browser_shutdown::IsTryingToQuit() || !chrome::WillKeepAlive())) {
     // Tell everyone that we are shutting down.
     browser_shutdown::SetTryingToQuit(true);
 
diff --git a/chrome/browser/load_library_perf_test.cc b/chrome/browser/load_library_perf_test.cc
index c35cd0b..d869e54 100644
--- a/chrome/browser/load_library_perf_test.cc
+++ b/chrome/browser/load_library_perf_test.cc
@@ -28,12 +28,12 @@
                          "bytes",
                          true);
 
-  std::string error;
+  base::NativeLibraryLoadError error;
   base::TimeTicks start = base::TimeTicks::HighResNow();
   base::NativeLibrary native_library =
       base::LoadNativeLibrary(library_path, &error);
   double delta = (base::TimeTicks::HighResNow() - start).InMillisecondsF();
-  ASSERT_TRUE(native_library) << "Error loading library: " << error;
+  ASSERT_TRUE(native_library) << "Error loading library: " << error.ToString();
   base::UnloadNativeLibrary(native_library);
   perf_test::PrintResult("time_to_load_library",
                          "",
diff --git a/chrome/browser/local_discovery/privet_http.h b/chrome/browser/local_discovery/privet_http.h
index 89bd387..9a81ca7 100644
--- a/chrome/browser/local_discovery/privet_http.h
+++ b/chrome/browser/local_discovery/privet_http.h
@@ -141,6 +141,8 @@
   // Optional attributes for /submitdoc. Call before calling |Start()|
   // |ticket| should be in CJT format.
   virtual void SetTicket(const std::string& ticket) = 0;
+  // |capabilities| should be in CDD format.
+  virtual void SetCapabilities(const std::string& capabilities) = 0;
   // Username and jobname are for display only.
   virtual void SetUsername(const std::string& username) = 0;
   virtual void SetJobname(const std::string& jobname) = 0;
diff --git a/chrome/browser/local_discovery/privet_http_impl.cc b/chrome/browser/local_discovery/privet_http_impl.cc
index 6d2b999..0adfcfe 100644
--- a/chrome/browser/local_discovery/privet_http_impl.cc
+++ b/chrome/browser/local_discovery/privet_http_impl.cc
@@ -16,10 +16,13 @@
 #include "chrome/browser/local_discovery/privet_constants.h"
 #include "components/cloud_devices/printer_description.h"
 #include "net/base/url_util.h"
+#include "printing/pwg_raster_settings.h"
 #include "printing/units.h"
 #include "ui/gfx/text_elider.h"
 #include "url/gurl.h"
 
+using namespace cloud_devices::printer;
+
 namespace local_discovery {
 
 namespace {
@@ -94,7 +97,7 @@
       CreatePrivetURL(kPrivetInfoPath), net::URLFetcher::GET, this);
 
   url_fetcher_->DoNotRetryOnTransientError();
-  url_fetcher_->AllowEmptyPrivetToken();
+  url_fetcher_->SendEmptyPrivetToken();
 
   url_fetcher_->Start();
 }
@@ -457,7 +460,6 @@
     : privet_client_(privet_client),
       delegate_(delegate),
       use_pdf_(false),
-      has_capabilities_(false),
       has_extended_workflow_(false),
       started_(false),
       offline_(false),
@@ -485,7 +487,6 @@
 void PrivetLocalPrintOperationImpl::OnPrivetInfoDone(
     const base::DictionaryValue* value) {
   if (value && !value->HasKey(kPrivetKeyError)) {
-    has_capabilities_ = false;
     has_extended_workflow_ = false;
     bool has_printing = false;
 
@@ -494,9 +495,7 @@
       for (size_t i = 0; i < api_list->GetSize(); i++) {
         std::string api;
         api_list->GetString(i, &api);
-        if (api == kPrivetCapabilitiesPath) {
-          has_capabilities_ = true;
-        } else if (api == kPrivetSubmitdocPath) {
+        if (api == kPrivetSubmitdocPath) {
           has_printing = true;
         } else if (api == kPrivetCreatejobPath) {
           has_extended_workflow_ = true;
@@ -516,36 +515,40 @@
 }
 
 void PrivetLocalPrintOperationImpl::StartInitialRequest() {
-  if (has_capabilities_) {
-    GetCapabilities();
+  use_pdf_ = false;
+  ContentTypesCapability content_types;
+  if (content_types.LoadFrom(capabilities_)) {
+    use_pdf_ = content_types.Contains(kPrivetContentTypePDF) ||
+               content_types.Contains(kPrivetContentTypeAny);
+  }
+
+  if (use_pdf_) {
+    StartPrinting();
   } else {
-    // Since we have no capabilities, the only reasonable format we can
-    // request is PWG Raster.
-    use_pdf_ = false;
+    DpiCapability dpis;
+    if (dpis.LoadFrom(capabilities_)) {
+      dpi_ = std::max(dpis.GetDefault().horizontal, dpis.GetDefault().vertical);
+    }
     StartConvertToPWG();
   }
 }
 
-void PrivetLocalPrintOperationImpl::GetCapabilities() {
-  current_response_ = base::Bind(
-      &PrivetLocalPrintOperationImpl::OnCapabilitiesResponse,
-      base::Unretained(this));
-
-  url_fetcher_= privet_client_->CreateURLFetcher(
-      CreatePrivetURL(kPrivetCapabilitiesPath), net::URLFetcher::GET, this);
-  url_fetcher_->DoNotRetryOnTransientError();
-
-  url_fetcher_->Start();
-}
-
 void PrivetLocalPrintOperationImpl::DoCreatejob() {
   current_response_ = base::Bind(
       &PrivetLocalPrintOperationImpl::OnCreatejobResponse,
       base::Unretained(this));
 
+  // Add PWG raster settings to ticket if they are supplied by the printer.
+  PwgRasterConfigCapability raster_capability;
+  PwgRasterConfigTicketItem raster_ticket_item;
+  if (raster_capability.LoadFrom(capabilities_)) {
+    raster_ticket_item.set_value(raster_capability.value());
+    raster_ticket_item.SaveTo(&ticket_);
+  }
+
   url_fetcher_= privet_client_->CreateURLFetcher(
       CreatePrivetURL(kPrivetCreatejobPath), net::URLFetcher::POST, this);
-  url_fetcher_->SetUploadData(kPrivetContentTypeCJT, ticket_);
+  url_fetcher_->SetUploadData(kPrivetContentTypeCJT, ticket_.ToString());
 
   url_fetcher_->Start();
 }
@@ -606,16 +609,67 @@
 }
 
 void PrivetLocalPrintOperationImpl::StartPrinting() {
-  if (has_extended_workflow_ && !ticket_.empty() && jobid_.empty()) {
+  if (has_extended_workflow_ && jobid_.empty()) {
     DoCreatejob();
   } else {
     DoSubmitdoc();
   }
 }
 
+void PrivetLocalPrintOperationImpl::FillPwgRasterSettings(
+    printing::PwgRasterSettings* transform_settings) {
+  PwgRasterConfigCapability raster_capability;
+  // If the raster capability fails to load, raster_capability will contain
+  // the default value.
+  raster_capability.LoadFrom(capabilities_);
+
+  DuplexTicketItem duplex_item;
+  DuplexType duplex_value = NO_DUPLEX;
+
+  DocumentSheetBack document_sheet_back =
+      raster_capability.value().document_sheet_back;
+
+  if (duplex_item.LoadFrom(ticket_)) {
+    duplex_value = duplex_item.value();
+  }
+
+  transform_settings->odd_page_transform = printing::TRANSFORM_NORMAL;
+  switch (duplex_value) {
+    case NO_DUPLEX:
+      transform_settings->odd_page_transform = printing::TRANSFORM_NORMAL;
+      break;
+    case LONG_EDGE:
+      if (document_sheet_back == ROTATED) {
+        transform_settings->odd_page_transform = printing::TRANSFORM_ROTATE_180;
+      } else if (document_sheet_back == FLIPPED) {
+        transform_settings->odd_page_transform =
+            printing::TRANSFORM_FLIP_VERTICAL;
+      }
+      break;
+    case SHORT_EDGE:
+      if (document_sheet_back == MANUAL_TUMBLE) {
+        transform_settings->odd_page_transform = printing::TRANSFORM_ROTATE_180;
+      } else if (document_sheet_back == FLIPPED) {
+        transform_settings->odd_page_transform =
+            printing::TRANSFORM_FLIP_HORIZONTAL;
+      }
+  }
+
+  transform_settings->rotate_all_pages =
+      raster_capability.value().rotate_all_pages;
+
+  transform_settings->reverse_page_order =
+      raster_capability.value().reverse_order_streaming;
+}
+
 void PrivetLocalPrintOperationImpl::StartConvertToPWG() {
+  printing::PwgRasterSettings transform_settings;
+
+  FillPwgRasterSettings(&transform_settings);
+
   if (!pwg_raster_converter_)
     pwg_raster_converter_ = PWGRasterConverter::CreateDefault();
+
   double scale = dpi_;
   scale /= printing::kPointsPerInch;
   // Make vertical rectangle to optimize streaming to printer. Fix orientation
@@ -623,43 +677,13 @@
   gfx::Rect area(std::min(page_size_.width(), page_size_.height()) * scale,
                  std::max(page_size_.width(), page_size_.height()) * scale);
   pwg_raster_converter_->Start(
-      data_, printing::PdfRenderSettings(area, dpi_, true),
+      data_,
+      printing::PdfRenderSettings(area, dpi_, true),
+      transform_settings,
       base::Bind(&PrivetLocalPrintOperationImpl::OnPWGRasterConverted,
                  base::Unretained(this)));
 }
 
-void PrivetLocalPrintOperationImpl::OnCapabilitiesResponse(
-    bool has_error,
-    const base::DictionaryValue* value) {
-  if (has_error) {
-    delegate_->OnPrivetPrintingError(this, 200);
-    return;
-  }
-
-  cloud_devices::CloudDeviceDescription description;
-  if (!description.InitFromDictionary(make_scoped_ptr(value->DeepCopy()))) {
-    delegate_->OnPrivetPrintingError(this, 200);
-    return;
-  }
-
-  use_pdf_ = false;
-  cloud_devices::printer::ContentTypesCapability content_types;
-  if (content_types.LoadFrom(description)) {
-    use_pdf_ = content_types.Contains(kPrivetContentTypePDF) ||
-               content_types.Contains(kPrivetContentTypeAny);
-  }
-
-  if (use_pdf_) {
-    StartPrinting();
-  } else {
-    cloud_devices::printer::DpiCapability dpis;
-    if (dpis.LoadFrom(description)) {
-      dpi_ = std::max(dpis.GetDefault().horizontal, dpis.GetDefault().vertical);
-    }
-    StartConvertToPWG();
-  }
-}
-
 void PrivetLocalPrintOperationImpl::OnSubmitdocResponse(
     bool has_error,
     const base::DictionaryValue* value) {
@@ -762,7 +786,13 @@
 
 void PrivetLocalPrintOperationImpl::SetTicket(const std::string& ticket) {
   DCHECK(!started_);
-  ticket_ = ticket;
+  ticket_.InitFromString(ticket);
+}
+
+void PrivetLocalPrintOperationImpl::SetCapabilities(
+    const std::string& capabilities) {
+  DCHECK(!started_);
+  capabilities_.InitFromString(capabilities);
 }
 
 void PrivetLocalPrintOperationImpl::SetUsername(const std::string& user) {
diff --git a/chrome/browser/local_discovery/privet_http_impl.h b/chrome/browser/local_discovery/privet_http_impl.h
index 8d0ae3f..535664a 100644
--- a/chrome/browser/local_discovery/privet_http_impl.h
+++ b/chrome/browser/local_discovery/privet_http_impl.h
@@ -12,8 +12,13 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/local_discovery/privet_http.h"
+#include "components/cloud_devices/cloud_device_description.h"
 #include "printing/pdf_render_settings.h"
 
+namespace printing {
+struct PwgRasterSettings;
+};
+
 namespace local_discovery {
 
 class PrivetHTTPClientImpl;
@@ -94,7 +99,6 @@
   void StartInfoOperation();
   void OnPrivetInfoDone(const base::DictionaryValue* value);
 
-
   void StartResponse(const base::DictionaryValue& value);
   void GetClaimTokenResponse(const base::DictionaryValue& value);
   void CompleteResponse(const base::DictionaryValue& value);
@@ -204,6 +208,8 @@
 
   virtual void SetData(base::RefCountedBytes* data) OVERRIDE;
 
+  virtual void SetCapabilities(const std::string& capabilities) OVERRIDE;
+
   virtual void SetTicket(const std::string& ticket) OVERRIDE;
 
   virtual void SetUsername(const std::string& user) OVERRIDE;
@@ -233,7 +239,6 @@
       ResponseCallback;
 
   void StartInitialRequest();
-  void GetCapabilities();
   void DoCreatejob();
   void DoSubmitdoc();
 
@@ -241,25 +246,25 @@
   void StartPrinting();
 
   void OnPrivetInfoDone(const base::DictionaryValue* value);
-  void OnCapabilitiesResponse(bool has_error,
-                              const base::DictionaryValue* value);
   void OnSubmitdocResponse(bool has_error,
                            const base::DictionaryValue* value);
   void OnCreatejobResponse(bool has_error,
                            const base::DictionaryValue* value);
   void OnPWGRasterConverted(bool success, const base::FilePath& pwg_file_path);
+  void FillPwgRasterSettings(printing::PwgRasterSettings* transfrom_settings);
 
   PrivetHTTPClientImpl* privet_client_;
   PrivetLocalPrintOperation::Delegate* delegate_;
 
   ResponseCallback current_response_;
 
-  std::string ticket_;
+  cloud_devices::CloudDeviceDescription ticket_;
+  cloud_devices::CloudDeviceDescription capabilities_;
+
   scoped_refptr<base::RefCountedBytes> data_;
   base::FilePath pwg_file_path_;
 
   bool use_pdf_;
-  bool has_capabilities_;
   bool has_extended_workflow_;
   bool started_;
   bool offline_;
diff --git a/chrome/browser/local_discovery/privet_http_unittest.cc b/chrome/browser/local_discovery/privet_http_unittest.cc
index 38b5938..1159696 100644
--- a/chrome/browser/local_discovery/privet_http_unittest.cc
+++ b/chrome/browser/local_discovery/privet_http_unittest.cc
@@ -3,12 +3,15 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/local_discovery/privet_http_impl.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
+#include "printing/pwg_raster_settings.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -185,6 +188,50 @@
 
 const char kSampleEmptyJSONResponse[] = "{}";
 
+const char kSampleCJT[] = "{ \"version\" : \"1.0\" }";
+
+const char kSampleCapabilitiesResponsePWGSettings[] =
+    "{"
+    "\"version\" : \"1.0\","
+    "\"printer\" : {"
+    " \"pwg_raster_config\" : {"
+    "   \"document_sheet_back\" : \"MANUAL_TUMBLE\","
+    "   \"reverse_order_streaming\": true"
+    "  },"
+    "  \"supported_content_type\" : ["
+    "   { \"content_type\" : \"image/pwg-raster\" }"
+    "  ]"
+    "}"
+    "}";
+
+const char kSampleCJTDuplex[] =
+    "{"
+    "\"version\" : \"1.0\","
+    "\"print\": { \"duplex\": {\"type\": \"SHORT_EDGE\"} }"
+    "}";
+
+const char kSampleCJTDuplexPWGSettings[] =
+    "{"
+    "\"version\" : \"1.0\","
+    "\"print\": {"
+    "  \"pwg_raster_config\" : {"
+    "    \"document_sheet_back\" : \"MANUAL_TUMBLE\","
+    "    \"reverse_order_streaming\": true"
+    "   },"
+    "  \"duplex\": {\"type\": \"SHORT_EDGE\"} }"
+    "}";
+
+// Return the representation of the given JSON that would be outputted by
+// JSONWriter. This ensures the same JSON values are represented by the same
+// string.
+std::string NormalizeJson(const std::string& json) {
+  std::string result = json;
+  scoped_ptr<base::Value> value(base::JSONReader::Read(result));
+  DCHECK(value);
+  base::JSONWriter::Write(value.get(), &result);
+  return result;
+}
+
 class MockTestURLFetcherFactoryDelegate
     : public net::TestURLFetcher::DelegateForTests {
  public:
@@ -248,6 +295,25 @@
     return SuccessfulResponseToURL(url, response);
   }
 
+  bool SuccessfulResponseToURLAndJSONData(const GURL& url,
+                                          const std::string& data,
+                                          const std::string& response) {
+    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
+    EXPECT_TRUE(fetcher);
+    EXPECT_EQ(url, fetcher->GetOriginalURL());
+
+    if (!fetcher)
+      return false;
+
+    std::string normalized_data = NormalizeJson(data);
+    std::string normalized_upload_data = NormalizeJson(fetcher->upload_data());
+    EXPECT_EQ(normalized_data, normalized_upload_data);
+    if (normalized_data != normalized_upload_data)
+      return false;
+
+    return SuccessfulResponseToURL(url, response);
+  }
+
   bool SuccessfulResponseToURLAndFilePath(const GURL& url,
                                           const base::FilePath& file_path,
                                           const std::string& response) {
@@ -389,10 +455,19 @@
 
   virtual void Start(base::RefCountedMemory* data,
                      const printing::PdfRenderSettings& conversion_settings,
+                     const printing::PwgRasterSettings& bitmap_settings,
                      const ResultCallback& callback) OVERRIDE {
+    bitmap_settings_ = bitmap_settings;
     std::string data_str(data->front_as<char>(), data->size());
     callback.Run(true, base::FilePath().AppendASCII(data_str + "test.pdf"));
   }
+
+  const printing::PwgRasterSettings& bitmap_settings() {
+    return bitmap_settings_;
+  }
+
+ private:
+  printing::PwgRasterSettings bitmap_settings_;
 };
 
 TEST_F(PrivetHTTPTest, CreatePrivetStorageList) {
@@ -742,8 +817,11 @@
     local_print_operation_ = privet_client_->CreateLocalPrintOperation(
         &local_print_delegate_);
 
+    scoped_ptr<FakePWGRasterConverter> pwg_converter(
+        new FakePWGRasterConverter);
+    pwg_converter_ = pwg_converter.get();
     local_print_operation_->SetPWGRasterConverterForTesting(
-        scoped_ptr<PWGRasterConverter>(new FakePWGRasterConverter));
+        pwg_converter.PassAs<PWGRasterConverter>());
   }
 
   scoped_refptr<base::RefCountedBytes> RefCountedBytesFromString(
@@ -757,6 +835,7 @@
  protected:
   scoped_ptr<PrivetLocalPrintOperation> local_print_operation_;
   StrictMock<MockLocalPrintDelegate> local_print_delegate_;
+  FakePWGRasterConverter* pwg_converter_;
 };
 
 TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrint) {
@@ -764,6 +843,7 @@
   local_print_operation_->SetJobname("Sample job name");
   local_print_operation_->SetData(RefCountedBytesFromString(
       "Sample print data"));
+  local_print_operation_->SetCapabilities(kSampleCapabilitiesResponse);
   local_print_operation_->Start();
 
   EXPECT_TRUE(SuccessfulResponseToURL(
@@ -773,10 +853,6 @@
   EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
                                       kSampleInfoResponse));
 
-  EXPECT_TRUE(
-      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
-                              kSampleCapabilitiesResponse));
-
   EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
 
   // TODO(noamsml): Is encoding spaces as pluses standard?
@@ -793,6 +869,8 @@
   local_print_operation_->SetJobname("Sample job name");
   local_print_operation_->SetData(
       RefCountedBytesFromString("Sample print data"));
+  local_print_operation_->SetCapabilities(
+      kSampleCapabilitiesResponseWithAnyMimetype);
   local_print_operation_->Start();
 
   EXPECT_TRUE(SuccessfulResponseToURL(
@@ -802,10 +880,6 @@
   EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
                                       kSampleInfoResponse));
 
-  EXPECT_TRUE(
-      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
-                              kSampleCapabilitiesResponseWithAnyMimetype));
-
   EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
 
   // TODO(noamsml): Is encoding spaces as pluses standard?
@@ -822,6 +896,7 @@
   local_print_operation_->SetJobname("Sample job name");
   local_print_operation_->SetData(
       RefCountedBytesFromString("path/to/"));
+  local_print_operation_->SetCapabilities(kSampleCapabilitiesResponsePWGOnly);
   local_print_operation_->Start();
 
   EXPECT_TRUE(SuccessfulResponseToURL(
@@ -831,10 +906,6 @@
   EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
                                       kSampleInfoResponse));
 
-  EXPECT_TRUE(
-      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
-                              kSampleCapabilitiesResponsePWGOnly));
-
   EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
 
   // TODO(noamsml): Is encoding spaces as pluses standard?
@@ -844,14 +915,57 @@
            "&job_name=Sample+job+name"),
       base::FilePath(FILE_PATH_LITERAL("path/to/test.pdf")),
       kSampleLocalPrintResponse));
+
+  EXPECT_EQ(printing::TRANSFORM_NORMAL,
+            pwg_converter_->bitmap_settings().odd_page_transform);
+  EXPECT_FALSE(pwg_converter_->bitmap_settings().rotate_all_pages);
+  EXPECT_FALSE(pwg_converter_->bitmap_settings().reverse_page_order);
+};
+
+TEST_F(PrivetLocalPrintTest, SuccessfulPWGLocalPrintDuplex) {
+  local_print_operation_->SetUsername("sample@gmail.com");
+  local_print_operation_->SetJobname("Sample job name");
+  local_print_operation_->SetData(RefCountedBytesFromString("path/to/"));
+  local_print_operation_->SetTicket(kSampleCJTDuplex);
+  local_print_operation_->SetCapabilities(
+      kSampleCapabilitiesResponsePWGSettings);
+  local_print_operation_->Start();
+
+  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
+                                      kSampleInfoResponseWithCreatejob));
+
+  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
+                                      kSampleInfoResponse));
+
+  EXPECT_TRUE(SuccessfulResponseToURLAndJSONData(
+      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
+      kSampleCJTDuplexPWGSettings,
+      kSampleCreatejobResponse));
+
+  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
+
+  // TODO(noamsml): Is encoding spaces as pluses standard?
+  EXPECT_TRUE(SuccessfulResponseToURLAndFilePath(
+      GURL(
+          "http://10.0.0.8:6006/privet/printer/submitdoc?"
+          "client_name=Chrome&user_name=sample%40gmail.com"
+          "&job_name=Sample+job+name&job_id=1234"),
+      base::FilePath(FILE_PATH_LITERAL("path/to/test.pdf")),
+      kSampleLocalPrintResponse));
+
+  EXPECT_EQ(printing::TRANSFORM_ROTATE_180,
+            pwg_converter_->bitmap_settings().odd_page_transform);
+  EXPECT_FALSE(pwg_converter_->bitmap_settings().rotate_all_pages);
+  EXPECT_TRUE(pwg_converter_->bitmap_settings().reverse_page_order);
 };
 
 TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrintWithCreatejob) {
   local_print_operation_->SetUsername("sample@gmail.com");
   local_print_operation_->SetJobname("Sample job name");
-  local_print_operation_->SetTicket("Sample print ticket");
+  local_print_operation_->SetTicket(kSampleCJT);
   local_print_operation_->SetData(
       RefCountedBytesFromString("Sample print data"));
+  local_print_operation_->SetCapabilities(kSampleCapabilitiesResponse);
   local_print_operation_->Start();
 
   EXPECT_TRUE(SuccessfulResponseToURL(
@@ -861,13 +975,9 @@
   EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
                                       kSampleInfoResponse));
 
-  EXPECT_TRUE(
-      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
-                              kSampleCapabilitiesResponse));
-
-  EXPECT_TRUE(SuccessfulResponseToURLAndData(
+  EXPECT_TRUE(SuccessfulResponseToURLAndJSONData(
       GURL("http://10.0.0.8:6006/privet/printer/createjob"),
-      "Sample print ticket",
+      kSampleCJT,
       kSampleCreatejobResponse));
 
   EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
@@ -885,7 +995,8 @@
   local_print_operation_->SetUsername("sample@gmail.com");
   local_print_operation_->SetJobname(
       "123456789:123456789:123456789:123456789:123456789:123456789:123456789:");
-  local_print_operation_->SetTicket("Sample print ticket");
+  local_print_operation_->SetTicket(kSampleCJT);
+  local_print_operation_->SetCapabilities(kSampleCapabilitiesResponse);
   local_print_operation_->SetData(
       RefCountedBytesFromString("Sample print data"));
   local_print_operation_->Start();
@@ -896,13 +1007,9 @@
   EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
                                       kSampleInfoResponse));
 
-  EXPECT_TRUE(
-      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
-                              kSampleCapabilitiesResponse));
-
-  EXPECT_TRUE(SuccessfulResponseToURLAndData(
+  EXPECT_TRUE(SuccessfulResponseToURLAndJSONData(
       GURL("http://10.0.0.8:6006/privet/printer/createjob"),
-      "Sample print ticket",
+      kSampleCJT,
       kSampleCreatejobResponse));
 
   EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
@@ -921,7 +1028,8 @@
 TEST_F(PrivetLocalPrintTest, PDFPrintInvalidDocumentTypeRetry) {
   local_print_operation_->SetUsername("sample@gmail.com");
   local_print_operation_->SetJobname("Sample job name");
-  local_print_operation_->SetTicket("Sample print ticket");
+  local_print_operation_->SetTicket(kSampleCJT);
+  local_print_operation_->SetCapabilities(kSampleCapabilitiesResponse);
   local_print_operation_->SetData(
       RefCountedBytesFromString("sample/path/"));
   local_print_operation_->Start();
@@ -933,13 +1041,9 @@
   EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
                                       kSampleInfoResponse));
 
-  EXPECT_TRUE(
-      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
-                              kSampleCapabilitiesResponse));
-
-  EXPECT_TRUE(SuccessfulResponseToURLAndData(
+  EXPECT_TRUE(SuccessfulResponseToURLAndJSONData(
       GURL("http://10.0.0.8:6006/privet/printer/createjob"),
-      "Sample print ticket",
+      kSampleCJT,
       kSampleCreatejobResponse));
 
   // TODO(noamsml): Is encoding spaces as pluses standard?
@@ -963,7 +1067,8 @@
 TEST_F(PrivetLocalPrintTest, LocalPrintRetryOnInvalidJobID) {
   local_print_operation_->SetUsername("sample@gmail.com");
   local_print_operation_->SetJobname("Sample job name");
-  local_print_operation_->SetTicket("Sample print ticket");
+  local_print_operation_->SetTicket(kSampleCJT);
+  local_print_operation_->SetCapabilities(kSampleCapabilitiesResponse);
   local_print_operation_->SetData(
       RefCountedBytesFromString("Sample print data"));
   local_print_operation_->Start();
@@ -975,13 +1080,9 @@
   EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
                                       kSampleInfoResponse));
 
-  EXPECT_TRUE(SuccessfulResponseToURL(
-      GURL("http://10.0.0.8:6006/privet/capabilities"),
-      kSampleCapabilitiesResponse));
-
-  EXPECT_TRUE(SuccessfulResponseToURLAndData(
+  EXPECT_TRUE(SuccessfulResponseToURLAndJSONData(
       GURL("http://10.0.0.8:6006/privet/printer/createjob"),
-      "Sample print ticket",
+      kSampleCJT,
       kSampleCreatejobResponse));
 
   EXPECT_TRUE(SuccessfulResponseToURLAndData(
diff --git a/chrome/browser/local_discovery/privet_notifications.cc b/chrome/browser/local_discovery/privet_notifications.cc
index ffa5ec3..f242d1b 100644
--- a/chrome/browser/local_discovery/privet_notifications.cc
+++ b/chrome/browser/local_discovery/privet_notifications.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -28,6 +27,7 @@
 #include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/local_discovery/privet_url_fetcher.cc b/chrome/browser/local_discovery/privet_url_fetcher.cc
index 9782893..cb51955 100644
--- a/chrome/browser/local_discovery/privet_url_fetcher.cc
+++ b/chrome/browser/local_discovery/privet_url_fetcher.cc
@@ -72,7 +72,7 @@
       request_context_(request_context),
       delegate_(delegate),
       do_not_retry_on_transient_error_(false),
-      allow_empty_privet_token_(false),
+      send_empty_privet_token_(false),
       has_byte_range_(false),
       make_response_file_(false),
       byte_range_start_(0),
@@ -99,12 +99,16 @@
   do_not_retry_on_transient_error_ = true;
 }
 
-void PrivetURLFetcher::AllowEmptyPrivetToken() {
+void PrivetURLFetcher::SendEmptyPrivetToken() {
   DCHECK(tries_ == 0);
-  allow_empty_privet_token_ = true;
+  send_empty_privet_token_ = true;
 }
 
 std::string PrivetURLFetcher::GetPrivetAccessToken() {
+  if (send_empty_privet_token_) {
+    return std::string();
+  }
+
   TokenMapHolder* token_map_holder = TokenMapHolder::GetInstance();
   TokenMap::iterator found = token_map_holder->map.find(GetHostString());
   return found != token_map_holder->map.end() ? found->second : std::string();
@@ -173,12 +177,16 @@
 void PrivetURLFetcher::Start() {
   DCHECK_EQ(tries_, 0);  // We haven't called |Start()| yet.
 
-  std::string privet_access_token = GetPrivetAccessToken();
-  if (privet_access_token.empty() && !allow_empty_privet_token_) {
-    RequestTokenRefresh();
-  } else {
-    Try();
+  if (!send_empty_privet_token_) {
+    std::string privet_access_token;
+    privet_access_token = GetPrivetAccessToken();
+    if (privet_access_token.empty()) {
+      RequestTokenRefresh();
+      return;
+    }
   }
+
+  Try();
 }
 
 void PrivetURLFetcher::SetUploadData(const std::string& upload_content_type,
diff --git a/chrome/browser/local_discovery/privet_url_fetcher.h b/chrome/browser/local_discovery/privet_url_fetcher.h
index 06874ec..2bb31fa 100644
--- a/chrome/browser/local_discovery/privet_url_fetcher.h
+++ b/chrome/browser/local_discovery/privet_url_fetcher.h
@@ -76,7 +76,7 @@
 
   void DoNotRetryOnTransientError();
 
-  void AllowEmptyPrivetToken();
+  void SendEmptyPrivetToken();
 
   // Set the contents of the Range header. |OnRawData| must return true if this
   // is called.
@@ -116,7 +116,7 @@
   Delegate* delegate_;
 
   bool do_not_retry_on_transient_error_;
-  bool allow_empty_privet_token_;
+  bool send_empty_privet_token_;
   bool has_byte_range_;
   bool make_response_file_;
 
diff --git a/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc b/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc
index 2737755..bfa78a7 100644
--- a/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc
+++ b/chrome/browser/local_discovery/privet_url_fetcher_unittest.cc
@@ -209,7 +209,24 @@
   PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL).GetOrigin().spec(),
                                     "");
 
-  privet_urlfetcher_->AllowEmptyPrivetToken();
+  privet_urlfetcher_->SendEmptyPrivetToken();
+  privet_urlfetcher_->Start();
+
+  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
+  ASSERT_TRUE(fetcher != NULL);
+  net::HttpRequestHeaders headers;
+  fetcher->GetExtraRequestHeaders(&headers);
+
+  std::string header_token;
+  ASSERT_TRUE(headers.GetHeader("X-Privet-Token", &header_token));
+  EXPECT_EQ(kEmptyPrivetToken, header_token);
+}
+
+TEST_F(PrivetURLFetcherTest, AlwaysSendEmpty) {
+  PrivetURLFetcher::SetTokenForHost(GURL(kSamplePrivetURL).GetOrigin().spec(),
+                                    "SampleToken");
+
+  privet_urlfetcher_->SendEmptyPrivetToken();
   privet_urlfetcher_->Start();
 
   net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
diff --git a/chrome/browser/local_discovery/pwg_raster_converter.cc b/chrome/browser/local_discovery/pwg_raster_converter.cc
index ce3e0ea..b912f38 100644
--- a/chrome/browser/local_discovery/pwg_raster_converter.cc
+++ b/chrome/browser/local_discovery/pwg_raster_converter.cc
@@ -7,6 +7,7 @@
 #include "base/bind_helpers.h"
 #include "base/cancelable_callback.h"
 #include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "chrome/common/chrome_utility_messages.h"
@@ -23,15 +24,10 @@
 
 class FileHandlers {
  public:
-  FileHandlers() : pdf_file_(base::kInvalidPlatformFileValue),
-                   pwg_file_(base::kInvalidPlatformFileValue) { }
+  FileHandlers() {}
 
   ~FileHandlers() {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
-    if (pdf_file_ != base::kInvalidPlatformFileValue)
-      base::ClosePlatformFile(pdf_file_);
-    if (pwg_file_ != base::kInvalidPlatformFileValue)
-      base::ClosePlatformFile(pwg_file_);
   }
 
   void Init(base::RefCountedMemory* data);
@@ -46,25 +42,23 @@
   }
 
   IPC::PlatformFileForTransit GetPdfForProcess(base::ProcessHandle process) {
-    DCHECK_NE(pdf_file_, base::kInvalidPlatformFileValue);
+    DCHECK(pdf_file_.IsValid());
     IPC::PlatformFileForTransit transit =
-        IPC::GetFileHandleForProcess(pdf_file_, process, true);
-    pdf_file_ = base::kInvalidPlatformFileValue;
+        IPC::TakeFileHandleForProcess(pdf_file_.Pass(), process);
     return transit;
   }
 
   IPC::PlatformFileForTransit GetPwgForProcess(base::ProcessHandle process) {
-    DCHECK_NE(pwg_file_, base::kInvalidPlatformFileValue);
+    DCHECK(pwg_file_.IsValid());
     IPC::PlatformFileForTransit transit =
-        IPC::GetFileHandleForProcess(pwg_file_, process, true);
-    pwg_file_ = base::kInvalidPlatformFileValue;
+        IPC::TakeFileHandleForProcess(pwg_file_.Pass(), process);
     return transit;
   }
 
  private:
   base::ScopedTempDir temp_dir_;
-  base::PlatformFile pdf_file_;
-  base::PlatformFile pwg_file_;
+  base::File pdf_file_;
+  base::File pwg_file_;
 };
 
 void FileHandlers::Init(base::RefCountedMemory* data) {
@@ -80,17 +74,14 @@
   }
 
   // Reopen in read only mode.
-  pdf_file_ = base::CreatePlatformFile(GetPdfPath(), base::PLATFORM_FILE_OPEN |
-                                                     base::PLATFORM_FILE_READ,
-                                       NULL, NULL);
-  pwg_file_ = base::CreatePlatformFile(GetPwgPath(),
-                                       base::PLATFORM_FILE_CREATE_ALWAYS |
-                                       base::PLATFORM_FILE_APPEND, NULL, NULL);
+  pdf_file_.Initialize(GetPdfPath(),
+                       base::File::FLAG_OPEN | base::File::FLAG_READ);
+  pwg_file_.Initialize(GetPwgPath(),
+                       base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
 }
 
 bool FileHandlers::IsValid() {
-  return pdf_file_ != base::kInvalidPlatformFileValue &&
-         pwg_file_ != base::kInvalidPlatformFileValue;
+  return pdf_file_.IsValid() && pwg_file_.IsValid();
 }
 
 // Converts PDF into PWG raster.
@@ -108,7 +99,8 @@
 class PwgUtilityProcessHostClient : public content::UtilityProcessHostClient {
  public:
   explicit PwgUtilityProcessHostClient(
-      const printing::PdfRenderSettings& settings);
+      const printing::PdfRenderSettings& settings,
+      const printing::PwgRasterSettings& bitmap_settings);
 
   void Convert(base::RefCountedMemory* data,
                const PWGRasterConverter::ResultCallback& callback);
@@ -134,6 +126,7 @@
 
   scoped_ptr<FileHandlers> files_;
   printing::PdfRenderSettings settings_;
+  printing::PwgRasterSettings bitmap_settings_;
   PWGRasterConverter::ResultCallback callback_;
   base::WeakPtr<content::UtilityProcessHost> utility_process_host_;
 
@@ -141,8 +134,9 @@
 };
 
 PwgUtilityProcessHostClient::PwgUtilityProcessHostClient(
-    const printing::PdfRenderSettings& settings) : settings_(settings) {
-}
+    const printing::PdfRenderSettings& settings,
+    const printing::PwgRasterSettings& bitmap_settings)
+    : settings_(settings), bitmap_settings_(bitmap_settings) {}
 
 PwgUtilityProcessHostClient::~PwgUtilityProcessHostClient() {
   // Delete temp directory.
@@ -189,11 +183,11 @@
   }
 
   base::ProcessHandle process = utility_process_host_->GetData().handle;
-  utility_process_host_->Send(
-      new ChromeUtilityMsg_RenderPDFPagesToPWGRaster(
-          files_->GetPdfForProcess(process),
-          settings_,
-          files_->GetPwgForProcess(process)));
+  utility_process_host_->Send(new ChromeUtilityMsg_RenderPDFPagesToPWGRaster(
+      files_->GetPdfForProcess(process),
+      settings_,
+      bitmap_settings_,
+      files_->GetPwgForProcess(process)));
   utility_process_host_.reset();
 }
 
@@ -252,7 +246,9 @@
 
   virtual void Start(base::RefCountedMemory* data,
                      const printing::PdfRenderSettings& conversion_settings,
+                     const printing::PwgRasterSettings& bitmap_settings,
                      const ResultCallback& callback) OVERRIDE;
+
  private:
   scoped_refptr<PwgUtilityProcessHostClient> utility_client_;
   base::CancelableCallback<ResultCallback::RunType> callback_;
@@ -269,11 +265,13 @@
 void PWGRasterConverterImpl::Start(
     base::RefCountedMemory* data,
     const printing::PdfRenderSettings& conversion_settings,
+    const printing::PwgRasterSettings& bitmap_settings,
     const ResultCallback& callback) {
   // Rebind cancelable callback to avoid calling callback if
   // PWGRasterConverterImpl is destroyed.
   callback_.Reset(callback);
-  utility_client_ = new PwgUtilityProcessHostClient(conversion_settings);
+  utility_client_ =
+      new PwgUtilityProcessHostClient(conversion_settings, bitmap_settings);
   utility_client_->Convert(data, callback_.callback());
 }
 
diff --git a/chrome/browser/local_discovery/pwg_raster_converter.h b/chrome/browser/local_discovery/pwg_raster_converter.h
index 47c8ade..f31c59b 100644
--- a/chrome/browser/local_discovery/pwg_raster_converter.h
+++ b/chrome/browser/local_discovery/pwg_raster_converter.h
@@ -18,6 +18,7 @@
 
 namespace printing {
 class PdfRenderSettings;
+struct PwgRasterSettings;
 }
 
 namespace local_discovery {
@@ -37,6 +38,7 @@
 
   virtual void Start(base::RefCountedMemory* data,
                      const printing::PdfRenderSettings& conversion_settings,
+                     const printing::PwgRasterSettings& bitmap_settings,
                      const ResultCallback& callback) = 0;
 };
 
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac.mm b/chrome/browser/local_discovery/service_discovery_client_mac.mm
index 9ea6f7f..6e91e62 100644
--- a/chrome/browser/local_discovery/service_discovery_client_mac.mm
+++ b/chrome/browser/local_discovery/service_discovery_client_mac.mm
@@ -393,9 +393,9 @@
   VLOG(1) << "ServiceResolverImplMac::OnResolveComplete: " << service_name_
           << ", " << status;
 
-  callback_.Run(status, description);
-
   has_resolved_ = true;
+
+  callback_.Run(status, description);
 }
 
 ServiceResolverImplMac::NetServiceContainer*
diff --git a/chrome/browser/managed_mode/chromeos/managed_user_password_service.cc b/chrome/browser/managed_mode/chromeos/managed_user_password_service.cc
index e5a3c03..142a723 100644
--- a/chrome/browser/managed_mode/chromeos/managed_user_password_service.cc
+++ b/chrome/browser/managed_mode/chromeos/managed_user_password_service.cc
@@ -12,6 +12,8 @@
 #include "chrome/browser/managed_mode/managed_user_constants.h"
 #include "chrome/browser/managed_mode/managed_user_sync_service.h"
 
+namespace chromeos {
+
 ManagedUserPasswordService::ManagedUserPasswordService()
     : weak_ptr_factory_(this) {}
 
@@ -70,3 +72,5 @@
 void ManagedUserPasswordService::Shutdown() {
     settings_service_subscription_.reset();
 }
+
+}  // namespace chromeos
diff --git a/chrome/browser/managed_mode/chromeos/managed_user_password_service.h b/chrome/browser/managed_mode/chromeos/managed_user_password_service.h
index e6fbb52..165332c 100644
--- a/chrome/browser/managed_mode/chromeos/managed_user_password_service.h
+++ b/chrome/browser/managed_mode/chromeos/managed_user_password_service.h
@@ -14,6 +14,8 @@
 #include "chrome/browser/managed_mode/managed_users.h"
 #include "components/keyed_service/core/keyed_service.h"
 
+namespace chromeos {
+
 class ManagedUserPasswordService : public KeyedService {
  public:
   ManagedUserPasswordService();
@@ -39,4 +41,5 @@
   DISALLOW_COPY_AND_ASSIGN(ManagedUserPasswordService);
 };
 
+}  // namespace chromeos
 #endif  // CHROME_BROWSER_MANAGED_MODE_CHROMEOS_MANAGED_USER_PASSWORD_SERVICE_H_
diff --git a/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.cc b/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.cc
index 78ce695..4834796 100644
--- a/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.cc
+++ b/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.cc
@@ -13,6 +13,8 @@
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
+namespace chromeos {
+
 // static
 ManagedUserPasswordService*
 ManagedUserPasswordServiceFactory::GetForProfile(Profile* profile) {
@@ -39,9 +41,8 @@
 KeyedService* ManagedUserPasswordServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   Profile* profile= static_cast<Profile*>(context);
-  chromeos::User* user = chromeos::UserManager::Get()->
-      GetUserByProfile(profile);
-  if (user->GetType() != chromeos::User::USER_TYPE_LOCALLY_MANAGED)
+  User* user = UserManager::Get()->GetUserByProfile(profile);
+  if (user->GetType() != User::USER_TYPE_LOCALLY_MANAGED)
     return NULL;
   ManagedUserPasswordService* result = new ManagedUserPasswordService();
   result->Init(
@@ -55,3 +56,5 @@
     content::BrowserContext* context) const {
   return chrome::GetBrowserContextRedirectedInIncognito(context);
 }
+
+}  // namespace chromeos
diff --git a/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.h b/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.h
index 5369b3d..1c14dd8 100644
--- a/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.h
+++ b/chrome/browser/managed_mode/chromeos/managed_user_password_service_factory.h
@@ -9,9 +9,12 @@
 #include "chrome/browser/managed_mode/managed_users.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
-class ManagedUserPasswordService;
 class Profile;
 
+namespace chromeos {
+
+class ManagedUserPasswordService;
+
 class ManagedUserPasswordServiceFactory
     : public BrowserContextKeyedServiceFactory {
  public:
@@ -32,4 +35,5 @@
       content::BrowserContext* context) const OVERRIDE;
 };
 
+}  // namespace chromeos
 #endif  // CHROME_BROWSER_MANAGED_MODE_CHROMEOS_MANAGED_USER_PASSWORD_SERVICE_FACTORY_H_
diff --git a/chrome/browser/managed_mode/chromeos/manager_password_service.cc b/chrome/browser/managed_mode/chromeos/manager_password_service.cc
index ef5c3fe..379254d 100644
--- a/chrome/browser/managed_mode/chromeos/manager_password_service.cc
+++ b/chrome/browser/managed_mode/chromeos/manager_password_service.cc
@@ -79,21 +79,23 @@
   SupervisedUserAuthentication* auth =
       supervised_user_manager->GetAuthentication();
 
-  if (!auth->NeedPasswordChange(user->email(), dict))
+  if (!auth->NeedPasswordChange(user->email(), dict) &&
+      !auth->HasIncompleteKey(user->email())) {
     return;
-
+  }
+  scoped_ptr<base::DictionaryValue> wrapper(dict->DeepCopy());
   user_service_->GetManagedUsersAsync(
       base::Bind(&ManagerPasswordService::GetManagedUsersCallback,
                  weak_ptr_factory_.GetWeakPtr(),
                  mu_id,
                  user->email(),
-                 dict));
+                 Passed(&wrapper)));
 }
 
 void ManagerPasswordService::GetManagedUsersCallback(
     const std::string& sync_mu_id,
     const std::string& user_id,
-    const base::DictionaryValue* password_data,
+    scoped_ptr<base::DictionaryValue> password_data,
     const base::DictionaryValue* managed_users) {
   const base::DictionaryValue* managed_user = NULL;
   if (!managed_users->GetDictionary(sync_mu_id, &managed_user))
@@ -162,8 +164,9 @@
                          true /* replace existing */,
                          base::Bind(&ManagerPasswordService::OnAddKeySuccess,
                                     weak_ptr_factory_.GetWeakPtr(),
+                                    manager_key,
                                     user_id,
-                                    password_data));
+                                    Passed(&password_data)));
 }
 
 void ManagerPasswordService::OnAuthenticationFailure(
@@ -176,8 +179,9 @@
 }
 
 void ManagerPasswordService::OnAddKeySuccess(
+    const UserContext& master_key_context,
     const std::string& user_id,
-    const base::DictionaryValue* password_data) {
+    scoped_ptr<base::DictionaryValue> password_data) {
   VLOG(0) << "Password changed for " << user_id;
   UMA_HISTOGRAM_ENUMERATION(
       "ManagedUsers.ChromeOS.PasswordChange",
@@ -186,7 +190,59 @@
 
   SupervisedUserAuthentication* auth =
       UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
-  auth->StorePasswordData(user_id, *password_data);
+  int old_schema = auth->GetPasswordSchema(user_id);
+  auth->StorePasswordData(user_id, *password_data.get());
+  if (old_schema == SupervisedUserAuthentication::SCHEMA_PLAIN) {
+    // 1) Add new manager key (using old key).
+    // 2) Remove old supervised user key.
+    // 3) Remove old manager key.
+    authenticator_->TransformContext(
+        master_key_context,
+        base::Bind(&ManagerPasswordService::OnContextTransformed,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
+void ManagerPasswordService::OnContextTransformed(
+    const UserContext& master_key_context) {
+  DCHECK(!master_key_context.need_password_hashing);
+  cryptohome::KeyDefinition new_master_key(master_key_context.password,
+                                           kCryptohomeMasterKeyLabel,
+                                           cryptohome::PRIV_DEFAULT);
+  authenticator_->AddKey(
+      master_key_context,
+      new_master_key,
+      true /* replace existing */,
+      base::Bind(&ManagerPasswordService::OnNewManagerKeySuccess,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 master_key_context));
+}
+
+void ManagerPasswordService::OnNewManagerKeySuccess(
+    const UserContext& master_key_context) {
+  VLOG(1) << "Added new master key for " << master_key_context.username;
+  authenticator_->RemoveKey(
+      master_key_context,
+      kLegacyCryptohomeManagedUserKeyLabel,
+      base::Bind(&ManagerPasswordService::OnOldManagedUserKeyDeleted,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 master_key_context));
+}
+
+void ManagerPasswordService::OnOldManagedUserKeyDeleted(
+    const UserContext& master_key_context) {
+  VLOG(1) << "Removed old managed user key for " << master_key_context.username;
+  authenticator_->RemoveKey(
+      master_key_context,
+      kLegacyCryptohomeMasterKeyLabel,
+      base::Bind(&ManagerPasswordService::OnOldManagerKeyDeleted,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 master_key_context));
+}
+
+void ManagerPasswordService::OnOldManagerKeyDeleted(
+    const UserContext& master_key_context) {
+  VLOG(1) << "Removed old master key for " << master_key_context.username;
 }
 
 void ManagerPasswordService::Shutdown() {
diff --git a/chrome/browser/managed_mode/chromeos/manager_password_service.h b/chrome/browser/managed_mode/chromeos/manager_password_service.h
index 40ce56f..ba2d458 100644
--- a/chrome/browser/managed_mode/chromeos/manager_password_service.h
+++ b/chrome/browser/managed_mode/chromeos/manager_password_service.h
@@ -18,6 +18,14 @@
 
 namespace chromeos {
 
+// Handles managed user password change that is detected while manager is
+// signed in.
+// It uses manager's master key to authorize update of managed user's key.
+// Edge case: Pre-M35 supervised users don't have correct labels for keys.
+// After new managed user key is added, migration is done in following way:
+// 1) Master key is added with correct label
+// 2) Old managed user's key is deleted.
+// 3) Old master key is deleted.
 class ManagerPasswordService
     : public KeyedService,
       public chromeos::ExtendedAuthenticator::AuthStatusConsumer {
@@ -39,10 +47,15 @@
   void OnSharedSettingsChange(const std::string& mu_id, const std::string& key);
   void GetManagedUsersCallback(const std::string& sync_mu_id,
                                const std::string& user_id,
-                               const base::DictionaryValue* password_data,
+                               scoped_ptr<base::DictionaryValue> password_data,
                                const base::DictionaryValue* managed_users);
-  void OnAddKeySuccess(const std::string& user_id,
-                       const base::DictionaryValue* password_data);
+  void OnAddKeySuccess(const UserContext& master_key_context,
+                       const std::string& user_id,
+                       scoped_ptr<base::DictionaryValue> password_data);
+  void OnContextTransformed(const UserContext& master_key_context);
+  void OnNewManagerKeySuccess(const UserContext& master_key_context);
+  void OnOldManagedUserKeyDeleted(const UserContext& master_key_context);
+  void OnOldManagerKeyDeleted(const UserContext& master_key_context);
 
   // Cached value from Init().
   // User id of currently logged in user, that have managed users on device.
diff --git a/chrome/browser/managed_mode/managed_user_registration_utility.cc b/chrome/browser/managed_mode/managed_user_registration_utility.cc
index ff636e9..3053f09 100644
--- a/chrome/browser/managed_mode/managed_user_registration_utility.cc
+++ b/chrome/browser/managed_mode/managed_user_registration_utility.cc
@@ -25,7 +25,7 @@
 #include "chrome/browser/sync/glue/device_info.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
@@ -109,10 +109,10 @@
   std::string pending_managed_user_id_;
   std::string pending_managed_user_token_;
   bool pending_managed_user_acknowledged_;
-  bool pending_password_acknowledged_;
   bool is_existing_managed_user_;
   bool avatar_updated_;
   RegistrationCallback callback_;
+  scoped_ptr<ManagedUserSharedSettingsUpdate> password_update_;
 
   base::WeakPtrFactory<ManagedUserRegistrationUtilityImpl> weak_ptr_factory_;
 
@@ -209,7 +209,6 @@
       managed_user_sync_service_(service),
       managed_user_shared_settings_service_(shared_settings_service),
       pending_managed_user_acknowledged_(false),
-      pending_password_acknowledged_(true),
       is_existing_managed_user_(false),
       avatar_updated_(false),
       weak_ptr_factory_(this) {
@@ -280,16 +279,14 @@
       pending_managed_user_id_, kAvatarKey,
       base::FundamentalValue(info.avatar_index));
   if (!info.password_data.empty()) {
-    pending_password_acknowledged_ = false;
-
-    ManagedUserSharedSettingsUpdate update(
+    password_update_.reset(new ManagedUserSharedSettingsUpdate(
         managed_user_shared_settings_service_,
         pending_managed_user_id_,
         managed_users::kChromeOSPasswordData,
         scoped_ptr<base::Value>(info.password_data.DeepCopy()),
         base::Bind(
             &ManagedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged,
-            weak_ptr_factory_.GetWeakPtr()));
+            weak_ptr_factory_.GetWeakPtr())));
   }
 
   browser_sync::DeviceInfo::GetClientName(
@@ -313,9 +310,9 @@
 
 void ManagedUserRegistrationUtilityImpl::OnPasswordChangeAcknowledged(
     bool success) {
-  DCHECK(!pending_password_acknowledged_);
+  DCHECK(password_update_);
   DCHECK(success);
-  pending_password_acknowledged_ = true;
+  password_update_.reset();
   CompleteRegistrationIfReady();
 }
 
@@ -354,7 +351,7 @@
 
   if (!pending_managed_user_acknowledged_ && !skip_check)
     return;
-  if (!pending_password_acknowledged_ && !skip_check)
+  if (password_update_ && !skip_check)
     return;
   if (pending_managed_user_token_.empty())
     return;
diff --git a/chrome/browser/managed_mode/managed_user_service.cc b/chrome/browser/managed_mode/managed_user_service.cc
index 6cdbd76..9d10f8e 100644
--- a/chrome/browser/managed_mode/managed_user_service.cc
+++ b/chrome/browser/managed_mode/managed_user_service.cc
@@ -30,7 +30,6 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -39,7 +38,8 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/api/managed_mode_private/managed_mode_handler.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
diff --git a/chrome/browser/managed_mode/managed_user_service_unittest.cc b/chrome/browser/managed_mode/managed_user_service_unittest.cc
index 81d97c0..f133ed6 100644
--- a/chrome/browser/managed_mode/managed_user_service_unittest.cc
+++ b/chrome/browser/managed_mode/managed_user_service_unittest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/managed_mode/managed_user_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/chrome_paths.h"
@@ -75,7 +75,7 @@
   virtual void SetUp() OVERRIDE {
     TestingProfile::Builder builder;
     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                              FakeProfileOAuth2TokenServiceWrapper::Build);
+                              BuildFakeProfileOAuth2TokenService);
     profile_ = builder.Build();
     managed_user_service_ =
         ManagedUserServiceFactory::GetForProfile(profile_.get());
diff --git a/chrome/browser/managed_mode/managed_user_signin_manager_wrapper.cc b/chrome/browser/managed_mode/managed_user_signin_manager_wrapper.cc
deleted file mode 100644
index db63ca0..0000000
--- a/chrome/browser/managed_mode/managed_user_signin_manager_wrapper.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
-
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_manager_base.h"
-
-#if defined(ENABLE_MANAGED_USERS)
-#include "chrome/browser/managed_mode/managed_user_constants.h"
-#endif
-
-ManagedUserSigninManagerWrapper::ManagedUserSigninManagerWrapper(
-    SigninManagerBase* original) : original_(original) {
-}
-
-ManagedUserSigninManagerWrapper::~ManagedUserSigninManagerWrapper() {
-}
-
-SigninManagerBase* ManagedUserSigninManagerWrapper::GetOriginal() {
-  return original_;
-}
-
-std::string ManagedUserSigninManagerWrapper::GetEffectiveUsername() const {
-  if (original_->profile()->IsManaged()) {
-#if defined(ENABLE_MANAGED_USERS)
-    DCHECK_EQ(std::string(), original_->GetAuthenticatedUsername());
-    return managed_users::kManagedUserPseudoEmail;
-#else
-    NOTREACHED();
-#endif
-  }
-
-  return original_->GetAuthenticatedUsername();
-}
-
-std::string ManagedUserSigninManagerWrapper::GetAccountIdToUse() const {
-  if (original_->profile()->IsManaged()) {
-#if defined(ENABLE_MANAGED_USERS)
-    return managed_users::kManagedUserPseudoEmail;
-#else
-    NOTREACHED();
-#endif
-  }
-
-  return original_->GetAuthenticatedAccountId();
-}
diff --git a/chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h b/chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h
deleted file mode 100644
index ef4191b..0000000
--- a/chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MANAGED_MODE_MANAGED_USER_SIGNIN_MANAGER_WRAPPER_H_
-#define CHROME_BROWSER_MANAGED_MODE_MANAGED_USER_SIGNIN_MANAGER_WRAPPER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-
-class SigninManagerBase;
-
-// Some chrome cloud services support managed users as well as normally
-// authenticated users that sign in through SigninManager.  To facilitate
-// getting the "effective" username and account identifiers, services can
-// use this class to wrap the SigninManager and return managed user account
-// information when appropriate.
-class ManagedUserSigninManagerWrapper {
- public:
-  explicit ManagedUserSigninManagerWrapper(SigninManagerBase* original);
-  virtual ~ManagedUserSigninManagerWrapper();
-
-  virtual std::string GetEffectiveUsername() const;
-  virtual std::string GetAccountIdToUse() const;
-
-  SigninManagerBase* GetOriginal();
-
- private:
-  SigninManagerBase* original_;
-  DISALLOW_COPY_AND_ASSIGN(ManagedUserSigninManagerWrapper);
-};
-
-#endif  // CHROME_BROWSER_MANAGED_MODE_MANAGED_USER_SIGNIN_MANAGER_WRAPPER_H_
diff --git a/chrome/browser/media/DEPS b/chrome/browser/media/DEPS
index 87894e2..c230b82 100644
--- a/chrome/browser/media/DEPS
+++ b/chrome/browser/media/DEPS
@@ -4,6 +4,4 @@
   "+media/cast",
   "+third_party/libyuv",
   "+third_party/webrtc",
-  "+third_party/zlib"
-  "+ui/gl/gl_switches.h"
 ]
diff --git a/chrome/browser/media/cast_transport_host_filter.cc b/chrome/browser/media/cast_transport_host_filter.cc
index 42dbc1f..6b2c4fb 100644
--- a/chrome/browser/media/cast_transport_host_filter.cc
+++ b/chrome/browser/media/cast_transport_host_filter.cc
@@ -74,8 +74,7 @@
 
 void CastTransportHostFilter::OnNew(
     int32 channel_id,
-    const net::IPEndPoint& remote_end_point,
-    const media::cast::CastLoggingConfig& logging_config) {
+    const net::IPEndPoint& remote_end_point) {
   if (id_map_.Lookup(channel_id)) {
     id_map_.Remove(channel_id);
   }
@@ -85,7 +84,6 @@
           g_browser_process->net_log(),
           &clock_,
           remote_end_point,
-          logging_config,
           base::Bind(&CastTransportHostFilter::NotifyStatusChange,
                      base::Unretained(this),
                      channel_id),
diff --git a/chrome/browser/media/cast_transport_host_filter.h b/chrome/browser/media/cast_transport_host_filter.h
index 32b1667..8f420b0 100644
--- a/chrome/browser/media/cast_transport_host_filter.h
+++ b/chrome/browser/media/cast_transport_host_filter.h
@@ -67,8 +67,7 @@
       const media::cast::MissingFramesAndPacketsMap& missing_packets);
   void OnNew(
       int32 channel_id,
-      const net::IPEndPoint& remote_end_point,
-      const media::cast::CastLoggingConfig& logging_config);
+      const net::IPEndPoint& remote_end_point);
   void OnDelete(int32 channel_id);
 
   IDMap<media::cast::transport::CastTransportSender, IDMapOwnPointer> id_map_;
diff --git a/chrome/browser/media/cast_transport_host_filter_unittest.cc b/chrome/browser/media/cast_transport_host_filter_unittest.cc
index 62c65a0..01318b6 100644
--- a/chrome/browser/media/cast_transport_host_filter_unittest.cc
+++ b/chrome/browser/media/cast_transport_host_filter_unittest.cc
@@ -16,9 +16,7 @@
  public:
   CastTransportHostFilterTest()
       : browser_thread_bundle_(
-            content::TestBrowserThreadBundle::IO_MAINLOOP),
-        logging_config_(
-            media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled()) {
+            content::TestBrowserThreadBundle::IO_MAINLOOP) {
     filter_ = new cast::CastTransportHostFilter();
     // 127.0.0.1:7 is the local echo service port, which
     // is probably not going to respond, but that's ok.
@@ -41,12 +39,11 @@
   scoped_refptr<content::BrowserMessageFilter> filter_;
   net::IPAddressNumber receiver_address_;
   net::IPEndPoint receive_endpoint_;
-  media::cast::CastLoggingConfig logging_config_;
 };
 
 TEST_F(CastTransportHostFilterTest, NewDelete) {
   const int kChannelId = 17;
-  CastHostMsg_New new_msg(kChannelId, receive_endpoint_, logging_config_);
+  CastHostMsg_New new_msg(kChannelId, receive_endpoint_);
   CastHostMsg_Delete delete_msg(kChannelId);
 
   // New, then delete, as expected.
@@ -69,7 +66,7 @@
 
 TEST_F(CastTransportHostFilterTest, NewMany) {
   for (int i = 0; i < 100; i++) {
-    CastHostMsg_New new_msg(i, receive_endpoint_, logging_config_);
+    CastHostMsg_New new_msg(i, receive_endpoint_);
     FakeSend(new_msg);
   }
 
@@ -84,7 +81,7 @@
 TEST_F(CastTransportHostFilterTest, SimpleMessages) {
   // Create a cast transport sender.
   const int32 kChannelId = 42;
-  CastHostMsg_New new_msg(kChannelId, receive_endpoint_, logging_config_);
+  CastHostMsg_New new_msg(kChannelId, receive_endpoint_);
   FakeSend(new_msg);
 
   media::cast::transport::CastTransportAudioConfig audio_config;
diff --git a/chrome/browser/media/chrome_midi_permission_context.cc b/chrome/browser/media/chrome_midi_permission_context.cc
index 062be1c..657b265 100644
--- a/chrome/browser/media/chrome_midi_permission_context.cc
+++ b/chrome/browser/media/chrome_midi_permission_context.cc
@@ -27,6 +27,7 @@
       ChromeMidiPermissionContext* context,
       const PermissionRequestID& id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const std::string& display_languages,
       const content::BrowserContext::MidiSysExPermissionCallback& callback);
   virtual ~MidiPermissionRequest();
@@ -46,6 +47,7 @@
   ChromeMidiPermissionContext* context_;
   const PermissionRequestID id_;
   GURL requesting_frame_;
+  bool user_gesture_;
   std::string display_languages_;
   const content::BrowserContext::MidiSysExPermissionCallback& callback_;
 
@@ -56,11 +58,13 @@
     ChromeMidiPermissionContext* context,
     const PermissionRequestID& id,
     const GURL& requesting_frame,
+    bool user_gesture,
     const std::string& display_languages,
     const content::BrowserContext::MidiSysExPermissionCallback& callback)
     : context_(context),
       id_(id),
       requesting_frame_(requesting_frame),
+      user_gesture_(user_gesture),
       display_languages_(display_languages),
       callback_(callback) {}
 
@@ -81,8 +85,7 @@
 }
 
 bool MidiPermissionRequest::HasUserGesture() const {
-  // TODO(gbillock): plumb through.
-  return false;
+  return user_gesture_;
 }
 
 GURL MidiPermissionRequest::GetRequestingHostname() const {
@@ -127,6 +130,7 @@
     int render_view_id,
     int bridge_id,
     const GURL& requesting_frame,
+    bool user_gesture,
     const content::BrowserContext::MidiSysExPermissionCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   DCHECK(!shutting_down_);
@@ -156,7 +160,8 @@
     return;
   }
 
-  DecidePermission(web_contents, id, requesting_frame, embedder, callback);
+  DecidePermission(web_contents, id, requesting_frame, embedder, user_gesture,
+                   callback);
 }
 
 void ChromeMidiPermissionContext::CancelMidiSysExPermissionRequest(
@@ -173,6 +178,7 @@
     const PermissionRequestID& id,
     const GURL& requesting_frame,
     const GURL& embedder,
+    bool user_gesture,
     const content::BrowserContext::MidiSysExPermissionCallback& callback) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
@@ -194,7 +200,7 @@
         PermissionBubbleManager* bubble_manager =
             PermissionBubbleManager::FromWebContents(web_contents);
         bubble_manager->AddRequest(new MidiPermissionRequest(
-            this, id, requesting_frame,
+            this, id, requesting_frame, user_gesture,
             profile_->GetPrefs()->GetString(prefs::kAcceptLanguages),
             callback));
         return;
diff --git a/chrome/browser/media/chrome_midi_permission_context.h b/chrome/browser/media/chrome_midi_permission_context.h
index 0bc1daa..f292e7b 100644
--- a/chrome/browser/media/chrome_midi_permission_context.h
+++ b/chrome/browser/media/chrome_midi_permission_context.h
@@ -33,6 +33,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const content::BrowserContext::MidiSysExPermissionCallback& callback);
 
   // Cancel a pending MIDI permission request.
@@ -59,6 +60,7 @@
       const PermissionRequestID& id,
       const GURL& requesting_frame,
       const GURL& embedder,
+      bool user_gesture,
       const content::BrowserContext::MidiSysExPermissionCallback& callback);
 
   // Called when permission is granted without interactively asking the user.
diff --git a/chrome/browser/media/encrypted_media_browsertest.cc b/chrome/browser/media/encrypted_media_browsertest.cc
index e82276e..2a75620 100644
--- a/chrome/browser/media/encrypted_media_browsertest.cc
+++ b/chrome/browser/media/encrypted_media_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest-spi.h"
 #if defined(OS_ANDROID)
 #include "base/android/build_info.h"
 #endif
@@ -457,9 +458,7 @@
                         Combine(Values(kExternalClearKeyKeySystem),
                                 Values(SRC),
                                 Values(PREFIXED)));
-// TODO(jrummell): Enable unprefixed tests once the CDM can be loaded using
-// MediaKeys.
-INSTANTIATE_TEST_CASE_P(DISABLED_SRC_ExternalClearKey,
+INSTANTIATE_TEST_CASE_P(SRC_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyKeySystem),
                                 Values(SRC),
@@ -469,9 +468,7 @@
                         Combine(Values(kExternalClearKeyKeySystem),
                                 Values(MSE),
                                 Values(PREFIXED)));
-// TODO(jrummell): Enable unprefixed tests once the CDM can be loaded using
-// MediaKeys.
-INSTANTIATE_TEST_CASE_P(DISABLED_MSE_ExternalClearKey,
+INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKey,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyKeySystem),
                                 Values(MSE),
@@ -482,9 +479,7 @@
                         Combine(Values(kExternalClearKeyDecryptOnlyKeySystem),
                                 Values(MSE),
                                 Values(PREFIXED)));
-// TODO(jrummell): Enable unprefixed tests once the CDM can be loaded using
-// MediaKeys.
-INSTANTIATE_TEST_CASE_P(DISABLED_MSE_ExternalClearKeyDecryptOnly,
+INSTANTIATE_TEST_CASE_P(MSE_ExternalClearKeyDecryptOnly,
                         EncryptedMediaTest,
                         Combine(Values(kExternalClearKeyDecryptOnlyKeySystem),
                                 Values(MSE),
@@ -500,13 +495,15 @@
                         Combine(Values(kWidevineKeySystem),
                                 Values(MSE),
                                 Values(PREFIXED)));
-// TODO(jrummell): Enable unprefixed tests once the CDM can be loaded using
-// MediaKeys.
-INSTANTIATE_TEST_CASE_P(DISABLED_MSE_Widevine,
+
+// Following tests fail if Widevine is loaded as a component, crbug.com/356833.
+#if !defined(WIDEVINE_CDM_IS_COMPONENT)
+INSTANTIATE_TEST_CASE_P(MSE_Widevine,
                         EncryptedMediaTest,
                         Combine(Values(kWidevineKeySystem),
                                 Values(MSE),
                                 Values(UNPREFIXED)));
+#endif  // !defined(WIDEVINE_CDM_IS_COMPONENT)
 #endif  // defined(WIDEVINE_CDM_AVAILABLE)
 
 IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM) {
@@ -626,9 +623,18 @@
 
 // When CDM crashes, we should still get a decode error.
 IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, CDMCrashDuringDecode) {
+  IgnorePluginCrash();
   TestNonPlaybackCases(kExternalClearKeyCrashKeySystem, kError);
 }
 
+// Testing that the media browser test does fail on plugin crash.
+IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, CDMExpectedCrash) {
+  // Plugin crash is not ignored by default, the test is expected to fail.
+  EXPECT_NONFATAL_FAILURE(
+      TestNonPlaybackCases(kExternalClearKeyCrashKeySystem, kError),
+      "plugin crash");
+}
+
 IN_PROC_BROWSER_TEST_F(ECKEncryptedMediaTest, FileIOTest) {
   TestNonPlaybackCases(kExternalClearKeyFileIOTestKeySystem,
                        kFileIOTestSuccess);
diff --git a/chrome/browser/media/media_browsertest.cc b/chrome/browser/media/media_browsertest.cc
index c8f3d67..0875a83 100644
--- a/chrome/browser/media/media_browsertest.cc
+++ b/chrome/browser/media/media_browsertest.cc
@@ -11,14 +11,18 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 
 // Common test results.
 const char MediaBrowserTest::kEnded[] = "ENDED";
 const char MediaBrowserTest::kError[] = "ERROR";
 const char MediaBrowserTest::kFailed[] = "FAILED";
+const char MediaBrowserTest::kPluginCrashed[] = "PLUGIN_CRASHED";
 
-MediaBrowserTest::MediaBrowserTest() {
+MediaBrowserTest::MediaBrowserTest() : ignore_plugin_crash_(false) {
 }
 
 MediaBrowserTest::~MediaBrowserTest() {
@@ -55,6 +59,8 @@
 base::string16 MediaBrowserTest::RunTest(const GURL& gurl,
                                          const std::string& expected_title) {
   DVLOG(1) << "Running test URL: " << gurl;
+  // Observe the web contents for plugin crashes.
+  Observe(browser()->tab_strip_model()->GetActiveWebContents());
   content::TitleWatcher title_watcher(
       browser()->tab_strip_model()->GetActiveWebContents(),
       base::ASCIIToUTF16(expected_title));
@@ -68,4 +74,21 @@
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kEnded));
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kError));
   title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kFailed));
+  title_watcher->AlsoWaitForTitle(base::ASCIIToUTF16(kPluginCrashed));
 }
+
+void MediaBrowserTest::PluginCrashed(const base::FilePath& plugin_path,
+                                     base::ProcessId plugin_pid) {
+  VLOG(0) << "Plugin crashed: " << plugin_path.value();
+  if (ignore_plugin_crash_)
+    return;
+  // Update document title to quit TitleWatcher early.
+  web_contents()->GetController().GetActiveEntry()
+      ->SetTitle(base::ASCIIToUTF16(kPluginCrashed));
+  ADD_FAILURE() << "Failing test due to plugin crash.";
+}
+
+void MediaBrowserTest::IgnorePluginCrash() {
+  ignore_plugin_crash_ = true;
+}
+
diff --git a/chrome/browser/media/media_browsertest.h b/chrome/browser/media/media_browsertest.h
index d84816b..be62f7a 100644
--- a/chrome/browser/media/media_browsertest.h
+++ b/chrome/browser/media/media_browsertest.h
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/browser/web_contents_observer.h"
 
 namespace content {
 class TitleWatcher;
@@ -17,7 +18,8 @@
 // Class used to automate running media related browser tests. The functions
 // assume that media files are located under files/media/ folder known to
 // the test http server.
-class MediaBrowserTest : public InProcessBrowserTest {
+class MediaBrowserTest : public InProcessBrowserTest,
+                         public content::WebContentsObserver {
  protected:
   typedef std::pair<std::string, std::string> StringPair;
 
@@ -26,6 +28,7 @@
   // TODO(xhwang): Report detailed errors, e.g. "ERROR-3".
   static const char kError[];
   static const char kFailed[];
+  static const char kPluginCrashed[];
 
   MediaBrowserTest();
   virtual ~MediaBrowserTest();
@@ -43,6 +46,17 @@
   base::string16 RunTest(const GURL& gurl, const std::string& expected);
 
   virtual void AddWaitForTitles(content::TitleWatcher* title_watcher);
+
+  // Fails test and sets document title to kPluginCrashed when a plugin crashes.
+  // If IgnorePluginCrash(true) is called then plugin crash is ignored.
+  virtual void PluginCrashed(const base::FilePath& plugin_path,
+                             base::ProcessId plugin_pid) OVERRIDE;
+
+  // When called, the test will ignore any plugin crashes and not fail the test.
+  void IgnorePluginCrash();
+
+ private:
+  bool ignore_plugin_crash_;
 };
 
 #endif  // CHROME_BROWSER_MEDIA_MEDIA_BROWSERTEST_H_
diff --git a/chrome/browser/media/media_stream_capture_indicator.cc b/chrome/browser/media/media_stream_capture_indicator.cc
index 794eb96..7c47dcf 100644
--- a/chrome/browser/media/media_stream_capture_indicator.cc
+++ b/chrome/browser/media/media_stream_capture_indicator.cc
@@ -179,11 +179,13 @@
 
  private:
   // content::MediaStreamUI interface.
-  virtual void OnStarted(const base::Closure& close_callback) OVERRIDE {
+  virtual gfx::NativeViewId OnStarted(const base::Closure& close_callback)
+      OVERRIDE {
     DCHECK(!started_);
     started_ = true;
     if (device_usage_.get())
       device_usage_->AddDevices(devices_);
+    return 0;
   }
 
   base::WeakPtr<WebContentsDeviceUsage> device_usage_;
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc
index 8ea3db3..cbe41d7 100644
--- a/chrome/browser/media/media_stream_devices_controller.cc
+++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -37,13 +37,17 @@
 
 namespace {
 
-bool HasAnyAvailableDevice() {
-  const content::MediaStreamDevices& audio_devices =
-      MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices();
-  const content::MediaStreamDevices& video_devices =
-      MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();
+bool HasAvailableDevicesForRequest(const content::MediaStreamRequest& request) {
+  bool has_audio_device =
+      request.audio_type == content::MEDIA_NO_SERVICE ||
+      !MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices()
+          .empty();
+  bool has_video_device =
+      request.video_type == content::MEDIA_NO_SERVICE ||
+      !MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices()
+          .empty();
 
-  return !audio_devices.empty() || !video_devices.empty();
+  return has_audio_device && has_video_device;
 }
 
 bool IsInKioskMode() {
@@ -169,8 +173,10 @@
     return true;
   }
 
-  // Deny the request if there is no device attached to the OS.
-  if (!HasAnyAvailableDevice()) {
+  // Deny the request if there is no device attached to the OS of the
+  // requested type. If both audio and video is requested, both types must be
+  // available.
+  if (!HasAvailableDevicesForRequest(request_)) {
     Deny(false, content::MEDIA_DEVICE_NO_HARDWARE);
     return true;
   }
@@ -382,8 +388,7 @@
 }
 
 bool MediaStreamDevicesController::HasUserGesture() const {
-  // TODO(gbillock): plumb this through
-  return false;
+  return request_.user_gesture;
 }
 
 GURL MediaStreamDevicesController::GetRequestingHostname() const {
diff --git a/chrome/browser/media/midi_permission_infobar_delegate.cc b/chrome/browser/media/midi_permission_infobar_delegate.cc
index bc10f8d..8d08847 100644
--- a/chrome/browser/media/midi_permission_infobar_delegate.cc
+++ b/chrome/browser/media/midi_permission_infobar_delegate.cc
@@ -55,7 +55,7 @@
 }
 
 int MidiPermissionInfoBarDelegate::GetIconID() const {
-  return IDR_INFOBAR_MIDI_SYSEX;
+  return IDR_INFOBAR_MIDI;
 }
 
 InfoBarDelegate::Type MidiPermissionInfoBarDelegate::GetInfoBarType() const {
diff --git a/chrome/browser/media/native_desktop_media_list_unittest.cc b/chrome/browser/media/native_desktop_media_list_unittest.cc
index db4ae73..085c454 100644
--- a/chrome/browser/media/native_desktop_media_list_unittest.cc
+++ b/chrome/browser/media/native_desktop_media_list_unittest.cc
@@ -119,6 +119,10 @@
     return true;
   }
 
+  virtual bool BringSelectedWindowToFront() OVERRIDE {
+    return true;
+  }
+
  private:
   Callback* callback_;
   WindowList window_list_;
diff --git a/chrome/browser/media/protected_media_identifier_infobar_delegate.cc b/chrome/browser/media/protected_media_identifier_infobar_delegate.cc
index 4f1c5b8..1b06aac 100644
--- a/chrome/browser/media/protected_media_identifier_infobar_delegate.cc
+++ b/chrome/browser/media/protected_media_identifier_infobar_delegate.cc
@@ -72,7 +72,7 @@
 }
 
 int ProtectedMediaIdentifierInfoBarDelegate::GetIconID() const {
-  return IDR_PROTECTED_MEDIA_IDENTIFIER_INFOBAR_ICON;
+  return IDR_INFOBAR_PROTECTED_MEDIA_IDENTIFIER;
 }
 
 InfoBarDelegate::Type
diff --git a/chrome/browser/media/webrtc_browsertest_perf.cc b/chrome/browser/media/webrtc_browsertest_perf.cc
index c286430..1832742 100644
--- a/chrome/browser/media/webrtc_browsertest_perf.cc
+++ b/chrome/browser/media/webrtc_browsertest_perf.cc
@@ -45,12 +45,12 @@
   }
 
   EXPECT_TRUE(pc_dict.GetString(Statistic("bytesSent", ssrc), &value));
-  perf_test::PrintResult("audio_recv", "", "bytes_sent", value, "bytes", false);
+  perf_test::PrintResult("audio_send", "", "bytes_sent", value, "bytes", false);
   EXPECT_TRUE(pc_dict.GetString(Statistic("googJitterReceived", ssrc), &value));
-  perf_test::PrintResult("audio_recv", "", "goog_jitter_recv", value, "",
+  perf_test::PrintResult("audio_send", "", "goog_jitter_recv", value, "",
                          false);
   EXPECT_TRUE(pc_dict.GetString(Statistic("googRtt", ssrc), &value));
-  perf_test::PrintResult("audio_recv", "", "goog_rtt", value, "ms", false);
+  perf_test::PrintResult("audio_send", "", "goog_rtt", value, "ms", false);
   return true;
 }
 
@@ -81,6 +81,23 @@
       pc_dict.GetString(Statistic("googFrameHeightSent", ssrc), &value));
   perf_test::PrintResult("video_recv", "", "goog_frame_height_sent", value,
                          "pixels", false);
+  EXPECT_TRUE(pc_dict.GetString(
+      Statistic("googCaptureJitterMs", ssrc), &value));
+  perf_test::PrintResult("video_recv", "", "goog_capture_jitter_ms", value,
+                         "ms", false);
+  EXPECT_TRUE(pc_dict.GetString(
+      Statistic("googCaptureQueueDelayMsPerS", ssrc), &value));
+  perf_test::PrintResult("video_recv", "", "goog_capture_queue_delay_ms_per_s",
+                         value, "ms/s", false);
+  EXPECT_TRUE(pc_dict.GetString(
+      Statistic("googEncodeUsagePercent", ssrc), &value));
+  perf_test::PrintResult("video_recv", "", "goog_encode_usage_percent",
+                         value, "%", false);
+  EXPECT_TRUE(pc_dict.GetString(Statistic("googAvgEncodeMs", ssrc), &value));
+  perf_test::PrintResult("video_recv", "", "goog_avg_encode_ms", value, "ms",
+                         false);
+  EXPECT_TRUE(pc_dict.GetString(Statistic("googRtt", ssrc), &value));
+  perf_test::PrintResult("video_recv", "", "goog_rtt", value, "ms", false);
   return true;
 }
 
diff --git a/chrome/browser/media/webrtc_log_list.cc b/chrome/browser/media/webrtc_log_list.cc
new file mode 100644
index 0000000..66b03c9
--- /dev/null
+++ b/chrome/browser/media/webrtc_log_list.cc
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/webrtc_log_list.h"
+
+#include "base/file_util.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+
+namespace {
+
+const char kWebRtcLogDirectory[] = "WebRTC Logs";
+const char kWebRtcLogListFilename[] = "Log List";
+
+}
+
+// static
+UploadList* WebRtcLogList::CreateWebRtcLogList(UploadList::Delegate* delegate,
+                                               Profile* profile) {
+  base::FilePath log_list_path = GetWebRtcLogListFileForDirectory(
+      GetWebRtcLogDirectoryForProfile(profile->GetPath()));
+  return new UploadList(delegate, log_list_path);
+}
+
+// static
+base::FilePath WebRtcLogList::GetWebRtcLogDirectoryForProfile(
+    const base::FilePath& profile_path) {
+  DCHECK(!profile_path.empty());
+  return profile_path.AppendASCII(kWebRtcLogDirectory);
+}
+
+// static
+base::FilePath WebRtcLogList::GetWebRtcLogListFileForDirectory(
+    const base::FilePath& dir) {
+  DCHECK(!dir.empty());
+  return dir.AppendASCII(kWebRtcLogListFilename);
+}
diff --git a/chrome/browser/media/webrtc_log_list.h b/chrome/browser/media/webrtc_log_list.h
new file mode 100644
index 0000000..0d0bbce
--- /dev/null
+++ b/chrome/browser/media/webrtc_log_list.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_WEBRTC_LOG_LIST_H_
+#define CHROME_BROWSER_MEDIA_WEBRTC_LOG_LIST_H_
+
+#include "chrome/browser/upload_list.h"
+
+class Profile;
+
+class WebRtcLogList {
+ public:
+  // Creates the upload list with the given callback delegate for a
+  // profile. The upload list loads and parses a text file list of WebRTC
+  // logs stored locally and/or uploaded.
+  static UploadList* CreateWebRtcLogList(UploadList::Delegate* delegate,
+                                         Profile* profile);
+
+  // Get the file path for the log directory for a profile.
+  static base::FilePath GetWebRtcLogDirectoryForProfile(
+      const base::FilePath& profile_path);
+
+  // Get the file path for the log list file in a directory. The log list file
+  // name will be appended to |dir| and returned.
+  static base::FilePath GetWebRtcLogListFileForDirectory(
+      const base::FilePath& dir);
+};
+
+#endif  // CHROME_BROWSER_MEDIA_WEBRTC_LOG_LIST_H_
diff --git a/chrome/browser/media/webrtc_log_upload_list.cc b/chrome/browser/media/webrtc_log_upload_list.cc
deleted file mode 100644
index 15c2963..0000000
--- a/chrome/browser/media/webrtc_log_upload_list.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/media/webrtc_log_upload_list.h"
-
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/chrome_paths.h"
-
-namespace {
-
-const char* kWebRtcLogListFilename = "webrtc_log_uploads.log";
-
-}
-
-// static
-WebRtcLogUploadList* WebRtcLogUploadList::Create(Delegate* delegate,
-                                                 Profile* profile) {
-  return new WebRtcLogUploadList(delegate, GetFilePathForProfile(profile));
-}
-
-// static
-base::FilePath WebRtcLogUploadList::GetFilePathForProfile(Profile* profile) {
-  base::FilePath log_dir_path = profile->GetPath();
-  return log_dir_path.AppendASCII(kWebRtcLogListFilename);
-}
-
-WebRtcLogUploadList::WebRtcLogUploadList(Delegate* delegate,
-                                         const base::FilePath& upload_log_path)
-    : UploadList(delegate, upload_log_path) {}
-
-WebRtcLogUploadList::~WebRtcLogUploadList() {}
diff --git a/chrome/browser/media/webrtc_log_upload_list.h b/chrome/browser/media/webrtc_log_upload_list.h
deleted file mode 100644
index 51e2c80..0000000
--- a/chrome/browser/media/webrtc_log_upload_list.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
-#define CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
-
-#include "chrome/browser/upload_list.h"
-
-class Profile;
-
-// Loads and parses a text file list of uploaded WebRTC logs.
-class WebRtcLogUploadList : public UploadList {
- public:
-  // Creates the WebRTC log upload list with the given callback delegate for
-  // a profile.
-  static WebRtcLogUploadList* Create(Delegate* delegate, Profile* profile);
-
-  // Get the file path for the log list file for a profile.
-  static base::FilePath GetFilePathForProfile(Profile* profile);
-
-  // Creates a new WebRTC log upload list with the given callback delegate.
-  // |upload_log_path| is the full path to the file to read the list from.
-  explicit WebRtcLogUploadList(Delegate* delegate,
-                               const base::FilePath& upload_log_path);
-
- protected:
-  virtual ~WebRtcLogUploadList();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(WebRtcLogUploadList);
-};
-
-#endif  // CHROME_BROWSER_MEDIA_WEBRTC_LOG_UPLOAD_LIST_H_
diff --git a/chrome/browser/media/webrtc_log_uploader.cc b/chrome/browser/media/webrtc_log_uploader.cc
index 563cf9d..cbe8424 100644
--- a/chrome/browser/media/webrtc_log_uploader.cc
+++ b/chrome/browser/media/webrtc_log_uploader.cc
@@ -5,27 +5,22 @@
 #include "chrome/browser/media/webrtc_log_uploader.h"
 
 #include "base/file_util.h"
+#include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#include "base/memory/shared_memory.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
-#include "chrome/browser/media/webrtc_log_upload_list.h"
-#include "chrome/common/chrome_paths.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/media/webrtc_log_list.h"
+#include "chrome/browser/media/webrtc_log_util.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/partial_circular_buffer.h"
 #include "content/public/browser/browser_thread.h"
 #include "net/base/mime_util.h"
-#include "net/base/network_delegate.h"
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_config_service.h"
 #include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_builder.h"
-#include "net/url_request/url_request_context_getter.h"
 #include "third_party/zlib/zlib.h"
 
 namespace {
@@ -43,40 +38,52 @@
 
 }  // namespace
 
+WebRtcLogUploadDoneData::WebRtcLogUploadDoneData() {}
+
+WebRtcLogUploadDoneData::~WebRtcLogUploadDoneData() {}
+
 WebRtcLogUploader::WebRtcLogUploader()
     : log_count_(0),
-      post_data_(NULL) {
+      post_data_(NULL),
+      shutting_down_(false) {
   file_thread_checker_.DetachFromThread();
 }
 
 WebRtcLogUploader::~WebRtcLogUploader() {
   DCHECK(create_thread_checker_.CalledOnValidThread());
-  // Delete all pending URLFetcher and release all references to
-  // WebRtcLoggingHandlerHost.
-  for (UploadDoneDataMap::iterator it = upload_done_data_.begin();
-       it != upload_done_data_.end(); ++it) {
-    delete it->first;
-  }
-  upload_done_data_.clear();
+  DCHECK(upload_done_data_.empty());
+  DCHECK(shutting_down_);
 }
 
 void WebRtcLogUploader::OnURLFetchComplete(
     const net::URLFetcher* source) {
   DCHECK(create_thread_checker_.CalledOnValidThread());
   DCHECK(upload_done_data_.find(source) != upload_done_data_.end());
+  DCHECK(!shutting_down_);
   int response_code = source->GetResponseCode();
-  std::string report_id;
-  if (response_code == kHttpResponseOk &&
-      source->GetResponseAsString(&report_id)) {
-  content::BrowserThread::PostTask(
-      content::BrowserThread::FILE, FROM_HERE,
-      base::Bind(&WebRtcLogUploader::AddUploadedLogInfoToUploadListFile,
-                 base::Unretained(this),
-                 upload_done_data_[source].upload_list_path,
-                 report_id));
+  UploadDoneDataMap::iterator it = upload_done_data_.find(source);
+  if (it != upload_done_data_.end()) {
+    // The log path can be empty here if we failed getting it before. We still
+    // upload the log if that's the case.
+    std::string report_id;
+    if (response_code == kHttpResponseOk &&
+        source->GetResponseAsString(&report_id) &&
+        !it->second.log_path.empty()) {
+      base::FilePath log_list_path =
+          WebRtcLogList::GetWebRtcLogListFileForDirectory(it->second.log_path);
+      content::BrowserThread::PostTask(
+          content::BrowserThread::FILE,
+          FROM_HERE,
+          base::Bind(&WebRtcLogUploader::AddUploadedLogInfoToUploadListFile,
+                     base::Unretained(this),
+                     log_list_path,
+                     it->second.local_log_id,
+                     report_id));
+    }
+    NotifyUploadDone(response_code, report_id, it->second);
+    upload_done_data_.erase(it);
   }
-  NotifyUploadDone(response_code, report_id, upload_done_data_[source]);
-  upload_done_data_.erase(source);
+
   delete source;
 }
 
@@ -86,7 +93,7 @@
 
 bool WebRtcLogUploader::ApplyForStartLogging() {
   DCHECK(create_thread_checker_.CalledOnValidThread());
-  if (log_count_ < kLogCountLimit) {
+  if (log_count_ < kLogCountLimit && !shutting_down_) {
     ++log_count_;
     return true;
   }
@@ -99,21 +106,40 @@
 }
 
 void WebRtcLogUploader::LoggingStoppedDoUpload(
-    net::URLRequestContextGetter* request_context,
     scoped_ptr<unsigned char[]> log_buffer,
     uint32 length,
     const std::map<std::string, std::string>& meta_data,
     const WebRtcLogUploadDoneData& upload_done_data) {
   DCHECK(file_thread_checker_.CalledOnValidThread());
   DCHECK(log_buffer.get());
-  DCHECK(!upload_done_data.upload_list_path.empty());
+  DCHECK(!upload_done_data.log_path.empty());
 
-  scoped_ptr<std::string> post_data;
-  post_data.reset(new std::string);
-  SetupMultipart(post_data.get(),
-                 reinterpret_cast<uint8*>(log_buffer.get()),
-                 length,
-                 meta_data);
+  std::vector<uint8> compressed_log;
+  CompressLog(
+      &compressed_log, reinterpret_cast<uint8*>(&log_buffer[0]), length);
+
+  std::string local_log_id;
+
+  if (base::PathExists(upload_done_data.log_path)) {
+    WebRtcLogUtil::DeleteOldWebRtcLogFiles(upload_done_data.log_path);
+
+    local_log_id = base::DoubleToString(base::Time::Now().ToDoubleT());
+    base::FilePath log_file_path =
+        upload_done_data.log_path.AppendASCII(local_log_id)
+            .AddExtension(FILE_PATH_LITERAL(".gz"));
+    WriteCompressedLogToFile(compressed_log, log_file_path);
+
+    base::FilePath log_list_path =
+        WebRtcLogList::GetWebRtcLogListFileForDirectory(
+            upload_done_data.log_path);
+    AddLocallyStoredLogInfoToUploadListFile(log_list_path, local_log_id);
+  }
+
+  WebRtcLogUploadDoneData upload_done_data_with_log_id = upload_done_data;
+  upload_done_data_with_log_id.local_log_id = local_log_id;
+
+  scoped_ptr<std::string> post_data(new std::string());
+  SetupMultipart(post_data.get(), compressed_log, meta_data);
 
   // If a test has set the test string pointer, write to it and skip uploading.
   // Still fire the upload callback so that we can run an extension API test
@@ -122,24 +148,39 @@
   // implemented according to the test plan. http://crbug.com/257329.
   if (post_data_) {
     *post_data_ = *post_data;
-    NotifyUploadDone(kHttpResponseOk, "", upload_done_data);
+    NotifyUploadDone(kHttpResponseOk, "", upload_done_data_with_log_id);
     return;
   }
 
   content::BrowserThread::PostTask(
-      content::BrowserThread::UI, FROM_HERE,
+      content::BrowserThread::UI,
+      FROM_HERE,
       base::Bind(&WebRtcLogUploader::CreateAndStartURLFetcher,
                  base::Unretained(this),
-                 make_scoped_refptr(request_context),
-                 upload_done_data,
+                 upload_done_data_with_log_id,
                  Passed(&post_data)));
 
   content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
       base::Bind(&WebRtcLogUploader::DecreaseLogCount, base::Unretained(this)));
 }
 
+void WebRtcLogUploader::StartShutdown() {
+  DCHECK(create_thread_checker_.CalledOnValidThread());
+  DCHECK(!shutting_down_);
+
+  // Delete all URLFetchers first and clear the upload done map.
+  for (UploadDoneDataMap::iterator it = upload_done_data_.begin();
+       it != upload_done_data_.end();
+       ++it) {
+    delete it->first;
+  }
+  upload_done_data_.clear();
+  shutting_down_ = true;
+}
+
 void WebRtcLogUploader::SetupMultipart(
-    std::string* post_data, uint8* log_buffer, uint32 log_buffer_length,
+    std::string* post_data,
+    const std::vector<uint8>& compressed_log,
     const std::map<std::string, std::string>& meta_data) {
 #if defined(OS_WIN)
   const char product[] = "Chrome";
@@ -175,26 +216,24 @@
                                     "", post_data);
   }
 
-  AddLogData(post_data, log_buffer, log_buffer_length);
+  AddLogData(post_data, compressed_log);
   net::AddMultipartFinalDelimiterForUpload(kMultipartBoundary, post_data);
 }
 
 void WebRtcLogUploader::AddLogData(std::string* post_data,
-                                   uint8* log_buffer,
-                                   uint32 log_buffer_length) {
+                                   const std::vector<uint8>& compressed_log) {
   post_data->append("--");
   post_data->append(kMultipartBoundary);
   post_data->append("\r\n");
   post_data->append("Content-Disposition: form-data; name=\"webrtc_log\"");
   post_data->append("; filename=\"webrtc_log.gz\"\r\n");
   post_data->append("Content-Type: application/gzip\r\n\r\n");
-
-  CompressLog(post_data, log_buffer, log_buffer_length);
-
+  post_data->append(reinterpret_cast<const char*>(&compressed_log[0]),
+                    compressed_log.size());
   post_data->append("\r\n");
 }
 
-void WebRtcLogUploader::CompressLog(std::string* post_data,
+void WebRtcLogUploader::CompressLog(std::vector<uint8>* compressed_log,
                                     uint8* input,
                                     uint32 input_size) {
   PartialCircularBuffer read_pcb(input, input_size);
@@ -209,7 +248,7 @@
   DCHECK_EQ(Z_OK, result);
 
   uint8 intermediate_buffer[kIntermediateCompressionBufferBytes] = {0};
-  ResizeForNextOutput(post_data, &stream);
+  ResizeForNextOutput(compressed_log, &stream);
   uint32 read = 0;
 
   do {
@@ -224,42 +263,45 @@
     result = deflate(&stream, Z_SYNC_FLUSH);
     DCHECK_EQ(Z_OK, result);
     if (stream.avail_out == 0)
-      ResizeForNextOutput(post_data, &stream);
+      ResizeForNextOutput(compressed_log, &stream);
   } while (true);
 
   // Ensure we have enough room in the output buffer. Easier to always just do a
   // resize than looping around and resize if needed.
   if (stream.avail_out < kIntermediateCompressionBufferBytes)
-    ResizeForNextOutput(post_data, &stream);
+    ResizeForNextOutput(compressed_log, &stream);
 
   result = deflate(&stream, Z_FINISH);
   DCHECK_EQ(Z_STREAM_END, result);
   result = deflateEnd(&stream);
   DCHECK_EQ(Z_OK, result);
 
-  post_data->resize(post_data->size() - stream.avail_out);
+  compressed_log->resize(compressed_log->size() - stream.avail_out);
 }
 
-void WebRtcLogUploader::ResizeForNextOutput(std::string* post_data,
+void WebRtcLogUploader::ResizeForNextOutput(std::vector<uint8>* compressed_log,
                                             z_stream* stream) {
-  size_t old_size = post_data->size() - stream->avail_out;
-  post_data->resize(old_size + kIntermediateCompressionBufferBytes);
-  stream->next_out = reinterpret_cast<uint8*>(&(*post_data)[old_size]);
+  size_t old_size = compressed_log->size() - stream->avail_out;
+  compressed_log->resize(old_size + kIntermediateCompressionBufferBytes);
+  stream->next_out = &(*compressed_log)[old_size];
   stream->avail_out = kIntermediateCompressionBufferBytes;
 }
 
 void WebRtcLogUploader::CreateAndStartURLFetcher(
-    scoped_refptr<net::URLRequestContextGetter> request_context,
     const WebRtcLogUploadDoneData& upload_done_data,
     scoped_ptr<std::string> post_data) {
   DCHECK(create_thread_checker_.CalledOnValidThread());
+
+  if (shutting_down_)
+    return;
+
   std::string content_type = kUploadContentType;
   content_type.append("; boundary=");
   content_type.append(kMultipartBoundary);
 
   net::URLFetcher* url_fetcher =
       net::URLFetcher::Create(GURL(kUploadURL), net::URLFetcher::POST, this);
-  url_fetcher->SetRequestContext(request_context);
+  url_fetcher->SetRequestContext(g_browser_process->system_request_context());
   url_fetcher->SetUploadData(content_type, *post_data);
   url_fetcher->Start();
   upload_done_data_[url_fetcher] = upload_done_data;
@@ -270,15 +312,30 @@
   --log_count_;
 }
 
-void WebRtcLogUploader::AddUploadedLogInfoToUploadListFile(
-    const base::FilePath& upload_list_path,
-    const std::string& report_id) {
+void WebRtcLogUploader::WriteCompressedLogToFile(
+    const std::vector<uint8>& compressed_log,
+    const base::FilePath& log_file_path) {
   DCHECK(file_thread_checker_.CalledOnValidThread());
+  DCHECK(!compressed_log.empty());
+  base::WriteFile(log_file_path,
+                  reinterpret_cast<const char*>(&compressed_log[0]),
+                  compressed_log.size());
+}
+
+void WebRtcLogUploader::AddLocallyStoredLogInfoToUploadListFile(
+    const base::FilePath& upload_list_path,
+    const std::string& local_log_id) {
+  DCHECK(file_thread_checker_.CalledOnValidThread());
+  DCHECK(!upload_list_path.empty());
+  DCHECK(!local_log_id.empty());
+
   std::string contents;
 
   if (base::PathExists(upload_list_path)) {
-    bool read_ok = base::ReadFileToString(upload_list_path, &contents);
-    DPCHECK(read_ok);
+    if (!base::ReadFileToString(upload_list_path, &contents)) {
+      DPLOG(WARNING) << "Could not read WebRTC log list file.";
+      return;
+    }
 
     // Limit the number of log entries to |kLogListLimitLines| - 1, to make room
     // for the new entry. Each line including the last ends with a '\n', so hit
@@ -296,14 +353,55 @@
     }
   }
 
-  // Write the Unix time and report ID to the log list file.
-  base::Time time_now = base::Time::Now();
-  contents += base::DoubleToString(time_now.ToDoubleT()) +
-              "," + report_id + '\n';
+  // Write the log ID to the log list file. Leave the upload time and report ID
+  // empty.
+  contents += ",," + local_log_id + '\n';
 
   int written =
       base::WriteFile(upload_list_path, &contents[0], contents.size());
-  DPCHECK(written == static_cast<int>(contents.size()));
+  if (written != static_cast<int>(contents.size())) {
+    DPLOG(WARNING) << "Could not write all data to WebRTC log list file: "
+                   << written;
+  }
+}
+
+void WebRtcLogUploader::AddUploadedLogInfoToUploadListFile(
+    const base::FilePath& upload_list_path,
+    const std::string& local_log_id,
+    const std::string& report_id) {
+  DCHECK(file_thread_checker_.CalledOnValidThread());
+  DCHECK(!upload_list_path.empty());
+  DCHECK(!local_log_id.empty());
+  DCHECK(!report_id.empty());
+
+  std::string contents;
+
+  if (base::PathExists(upload_list_path)) {
+    if (!base::ReadFileToString(upload_list_path, &contents)) {
+      DPLOG(WARNING) << "Could not read WebRTC log list file.";
+      return;
+    }
+  }
+
+  // Write the Unix time and report ID to the log list file. We should be able
+  // to find the local log ID, in that case insert the data into the existing
+  // line. Otherwise add it in the end.
+  base::Time time_now = base::Time::Now();
+  std::string time_now_str = base::DoubleToString(time_now.ToDoubleT());
+  size_t pos = contents.find(",," + local_log_id);
+  if (pos != std::string::npos) {
+    contents.insert(pos, time_now_str);
+    contents.insert(pos + time_now_str.length() + 1, report_id);
+  } else {
+    contents += time_now_str + "," + report_id + ",\n";
+  }
+
+  int written =
+      base::WriteFile(upload_list_path, &contents[0], contents.size());
+  if (written != static_cast<int>(contents.size())) {
+    DPLOG(WARNING) << "Could not write all data to WebRTC log list file: "
+                   << written;
+  }
 }
 
 void WebRtcLogUploader::NotifyUploadDone(
diff --git a/chrome/browser/media/webrtc_log_uploader.h b/chrome/browser/media/webrtc_log_uploader.h
index 2a33417..40d9554 100644
--- a/chrome/browser/media/webrtc_log_uploader.h
+++ b/chrome/browser/media/webrtc_log_uploader.h
@@ -7,11 +7,10 @@
 
 #include <map>
 #include <string>
+#include <vector>
 
 #include "base/basictypes.h"
 #include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/platform_file.h"
 #include "base/threading/thread_checker.h"
 #include "chrome/browser/media/webrtc_logging_handler_host.h"
 #include "net/url_request/url_fetcher_delegate.h"
@@ -24,19 +23,21 @@
 
 namespace net {
 class URLFetcher;
-class URLRequestContextGetter;
 }
 
 typedef struct z_stream_s z_stream;
 
-// Used when uploading is done to perform post-upload actions.
-typedef struct {
-  base::FilePath upload_list_path;
+// Used when uploading is done to perform post-upload actions. |log_path| is
+// also used pre-upload.
+struct WebRtcLogUploadDoneData {
+  WebRtcLogUploadDoneData();
+  ~WebRtcLogUploadDoneData();
+
+  base::FilePath log_path;
   WebRtcLoggingHandlerHost::UploadDoneCallback callback;
   scoped_refptr<WebRtcLoggingHandlerHost> host;
-} WebRtcLogUploadDoneData;
-
-class WebRtcLogURLRequestContextGetter;
+  std::string local_log_id;
+};
 
 // WebRtcLogUploader uploads WebRTC logs, keeps count of how many logs have
 // been started and denies further logs if a limit is reached. It also adds
@@ -68,51 +69,81 @@
   // granted by calling ApplyForStartLogging() and getting true in return. After
   // this function has been called, a new permission must be granted. Call
   // either this function or LoggingStoppedDontUpload().
+  // |upload_done_data.local_log_id| is set and used internally and should be
+  // left empty.
   void LoggingStoppedDoUpload(
-      net::URLRequestContextGetter* request_context,
       scoped_ptr<unsigned char[]> log_buffer,
       uint32 length,
       const std::map<std::string, std::string>& meta_data,
       const WebRtcLogUploadDoneData& upload_done_data);
 
+  // Cancels URL fetcher operation by deleting all URL fetchers. This cancels
+  // any pending uploads and releases SystemURLRequestContextGetter references.
+  // Sets |shutting_down_| which prevent new fetchers to be created.
+  void StartShutdown();
+
   // For testing purposes. If called, the multipart will not be uploaded, but
   // written to |post_data_| instead.
   void OverrideUploadWithBufferForTesting(std::string* post_data) {
+    DCHECK((post_data && !post_data_) || (!post_data && post_data_));
     post_data_ = post_data;
   }
 
  private:
   FRIEND_TEST_ALL_PREFIXES(WebRtcLogUploaderTest,
+                           AddLocallyStoredLogInfoToUploadListFile);
+  FRIEND_TEST_ALL_PREFIXES(WebRtcLogUploaderTest,
                            AddUploadedLogInfoToUploadListFile);
 
   // Sets up a multipart body to be uploaded. The body is produced according
   // to RFC 2046.
-  void SetupMultipart(std::string* post_data, uint8* log_buffer,
-                      uint32 log_buffer_length,
+  void SetupMultipart(std::string* post_data,
+                      const std::vector<uint8>& compressed_log,
                       const std::map<std::string, std::string>& meta_data);
 
-  void AddLogData(std::string* post_data, uint8* log_buffer,
-                  uint32 log_buffer_length);
-  void CompressLog(std::string* post_data, uint8* input, uint32 input_size);
-  void ResizeForNextOutput(std::string* post_data, z_stream* stream);
+  // Adds |compressed_log| to |post_data|.
+  void AddLogData(std::string* post_data,
+                  const std::vector<uint8>& compressed_log);
+
+  void CompressLog(std::vector<uint8>* compressed_log,
+                   uint8* input,
+                   uint32 input_size);
+
+  void ResizeForNextOutput(std::vector<uint8>* compressed_log,
+                           z_stream* stream);
 
   void CreateAndStartURLFetcher(
-      scoped_refptr<net::URLRequestContextGetter> request_context,
       const WebRtcLogUploadDoneData& upload_done_data,
       scoped_ptr<std::string> post_data);
 
   void DecreaseLogCount();
 
-  // Append information (time and report ID) about this uploaded log to a log
-  // list file, limited to |kLogListLimitLines| entries. This list is used for
-  // viewing the uploaded logs under chrome://webrtc-logs, see
-  // WebRtcLogUploadList. The list has the format
-  // time,id
-  // time,id
+  // Must be called on the FILE thread.
+  void WriteCompressedLogToFile(const std::vector<uint8>& compressed_log,
+                                const base::FilePath& log_file_path);
+
+  // Append information (upload time, report ID and local ID) about a log to a
+  // log list file, limited to |kLogListLimitLines| entries. This list is used
+  // for viewing the logs under chrome://webrtc-logs, see WebRtcLogUploadList.
+  // The list has the format
+  // upload_time,report_id,local_id
+  // upload_time,report_id,local_id
   // etc.
-  // where each line represents an uploaded log and "time" is Unix time.
+  // where each line represents a log. "upload_time" is the time when the log
+  // was uploaded in Unix time. "report_id" is the ID reported back by the
+  // server. "local_id" is the ID for the locally stored log. It's the time
+  // stored in Unix time and it's also used as file name.
+  // AddLocallyStoredLogInfoToUploadListFile() will first be called,
+  // "upload_time" and "report_id" is the left empty in the entry written to the
+  // list file. If uploading is successful, AddUploadedLogInfoToUploadListFile()
+  // is called and those empty items are filled out.
+  // Must be called on the FILE thread.
+  void AddLocallyStoredLogInfoToUploadListFile(
+      const base::FilePath& upload_list_path,
+      const std::string& local_log_id);
   void AddUploadedLogInfoToUploadListFile(
       const base::FilePath& upload_list_path,
+      const std::string& local_log_id,
       const std::string& report_id);
 
   void NotifyUploadDone(int response_code,
@@ -125,6 +156,8 @@
   // This is the FILE thread for Chromium. Some other thread for tests.
   base::ThreadChecker file_thread_checker_;
 
+  // Keeps track of number of currently open logs. Must be accessed on the UI
+  // thread.
   int log_count_;
 
   // For testing purposes, see OverrideUploadWithBufferForTesting. Only accessed
@@ -136,6 +169,9 @@
   // Only accessed on the UI thread.
   UploadDoneDataMap upload_done_data_;
 
+  // When shutting down, don't create new URLFetchers.
+  bool shutting_down_;
+
   DISALLOW_COPY_AND_ASSIGN(WebRtcLogUploader);
 };
 
diff --git a/chrome/browser/media/webrtc_log_uploader_unittest.cc b/chrome/browser/media/webrtc_log_uploader_unittest.cc
index 3e13f45..21cdfba 100644
--- a/chrome/browser/media/webrtc_log_uploader_unittest.cc
+++ b/chrome/browser/media/webrtc_log_uploader_unittest.cc
@@ -5,87 +5,133 @@
 #include <string>
 
 #include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
-#include "base/platform_file.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/time/time.h"
 #include "chrome/browser/media/webrtc_log_uploader.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-const char kTestReportId[] = "123456789";
-const char kTestTime[] = "987654321";
+const char kTestTime[] = "time";
+const char kTestReportId[] = "report-id";
+const char kTestLocalId[] = "local-id";
 
 class WebRtcLogUploaderTest : public testing::Test {
  public:
   WebRtcLogUploaderTest() {}
 
-  bool VerifyNumberOfLinesAndContentsOfLastLine(int expected_lines) {
-    std::string contents;
-    int read = base::ReadFileToString(test_list_path_, &contents);
-    EXPECT_GT(read, 0);
-    if (read <= 0)
-      return false;
+  bool VerifyNumberOfLines(int expected_lines) {
+    std::vector<std::string> lines = GetLinesFromListFile();
+    EXPECT_EQ(expected_lines, static_cast<int>(lines.size()));
+    return expected_lines == static_cast<int>(lines.size());
+  }
 
-    // Verify expected number of lines. Since every line should end with '\n',
-    // there should be an additional empty line after splitting.
-    std::vector<std::string> lines;
-    base::SplitString(contents, '\n', &lines);
-    EXPECT_EQ(expected_lines + 1, static_cast<int>(lines.size()));
-    if (expected_lines + 1 != static_cast<int>(lines.size()))
+  bool VerifyLastLineHasAllInfo() {
+    std::string last_line = GetLastLineFromListFile();
+    if (last_line.empty())
       return false;
-    EXPECT_TRUE(lines[expected_lines].empty());
-
-    // Verify the contents of the last line. The time (line_parts[0]) is the
-    // time when the info was written to the file which we don't know, so just
-    // verify that it's not empty.
     std::vector<std::string> line_parts;
-    base::SplitString(lines[expected_lines - 1], ',', &line_parts);
-    EXPECT_EQ(2u, line_parts.size());
-    if (2u != line_parts.size())
+    base::SplitString(last_line, ',', &line_parts);
+    EXPECT_EQ(3u, line_parts.size());
+    if (3u != line_parts.size())
+      return false;
+    // The time (line_parts[0]) is the time when the info was written to the
+    // file which we don't know, so just verify that it's not empty.
+    EXPECT_FALSE(line_parts[0].empty());
+    EXPECT_STREQ(kTestReportId, line_parts[1].c_str());
+    EXPECT_STREQ(kTestLocalId, line_parts[2].c_str());
+    return true;
+  }
+
+  bool VerifyLastLineHasLocalIdOnly() {
+    std::string last_line = GetLastLineFromListFile();
+    if (last_line.empty())
+      return false;
+    std::vector<std::string> line_parts;
+    base::SplitString(last_line, ',', &line_parts);
+    EXPECT_EQ(3u, line_parts.size());
+    if (3u != line_parts.size())
+      return false;
+    EXPECT_TRUE(line_parts[0].empty());
+    EXPECT_TRUE(line_parts[1].empty());
+    EXPECT_STREQ(kTestLocalId, line_parts[2].c_str());
+    return true;
+  }
+
+  bool VerifyLastLineHasUploadTimeAndIdOnly() {
+    std::string last_line = GetLastLineFromListFile();
+    if (last_line.empty())
+      return false;
+    std::vector<std::string> line_parts;
+    base::SplitString(last_line, ',', &line_parts);
+    EXPECT_EQ(3u, line_parts.size());
+    if (3u != line_parts.size())
       return false;
     EXPECT_FALSE(line_parts[0].empty());
     EXPECT_STREQ(kTestReportId, line_parts[1].c_str());
-
+    EXPECT_TRUE(line_parts[2].empty());
     return true;
   }
 
   bool AddLinesToTestFile(int number_of_lines) {
-    int flags = base::PLATFORM_FILE_OPEN |
-                base::PLATFORM_FILE_APPEND;
-    base::PlatformFileError error = base::PLATFORM_FILE_OK;
-    base::PlatformFile test_list_file =
-        base::CreatePlatformFile(test_list_path_, flags, NULL, &error);
-    EXPECT_EQ(base::PLATFORM_FILE_OK, error);
-    EXPECT_NE(base::kInvalidPlatformFileValue, test_list_file);
-    if (base::PLATFORM_FILE_OK != error ||
-        base::kInvalidPlatformFileValue == test_list_file) {
+    base::File test_list_file(test_list_path_,
+                              base::File::FLAG_OPEN | base::File::FLAG_APPEND);
+    EXPECT_TRUE(test_list_file.IsValid());
+    if (!test_list_file.IsValid())
       return false;
-    }
 
     for (int i = 0; i < number_of_lines; ++i) {
       EXPECT_EQ(static_cast<int>(sizeof(kTestTime)) - 1,
-                base::WritePlatformFileAtCurrentPos(test_list_file,
-                                                    kTestTime,
-                                                    sizeof(kTestTime) - 1));
-      EXPECT_EQ(1, base::WritePlatformFileAtCurrentPos(test_list_file, ",", 1));
+                test_list_file.WriteAtCurrentPos(kTestTime,
+                                                 sizeof(kTestTime) - 1));
+      EXPECT_EQ(1, test_list_file.WriteAtCurrentPos(",", 1));
       EXPECT_EQ(static_cast<int>(sizeof(kTestReportId)) - 1,
-                base::WritePlatformFileAtCurrentPos(test_list_file,
-                                                    kTestReportId,
-                                                    sizeof(kTestReportId) - 1));
-      EXPECT_EQ(1, base::WritePlatformFileAtCurrentPos(test_list_file,
-                                                       "\n", 1));
+                test_list_file.WriteAtCurrentPos(kTestReportId,
+                                                 sizeof(kTestReportId) - 1));
+      EXPECT_EQ(1, test_list_file.WriteAtCurrentPos(",", 1));
+      EXPECT_EQ(static_cast<int>(sizeof(kTestLocalId)) - 1,
+                test_list_file.WriteAtCurrentPos(kTestLocalId,
+                                                 sizeof(kTestLocalId) - 1));
+      EXPECT_EQ(1, test_list_file.WriteAtCurrentPos("\n", 1));
     }
-    EXPECT_TRUE(base::ClosePlatformFile(test_list_file));
-
     return true;
   }
 
+  std::vector<std::string> GetLinesFromListFile() {
+    std::string contents;
+    int read = base::ReadFileToString(test_list_path_, &contents);
+    EXPECT_GT(read, 0);
+    if (read == 0)
+      return std::vector<std::string>();
+    // Since every line should end with '\n', the last line should be empty. So
+    // we expect at least two lines including the final empty. Remove the empty
+    // line before returning.
+    std::vector<std::string> lines;
+    base::SplitString(contents, '\n', &lines);
+    EXPECT_GT(lines.size(), 1u);
+    if (lines.size() < 2)
+      return std::vector<std::string>();
+    EXPECT_TRUE(lines[lines.size() - 1].empty());
+    if (!lines[lines.size() - 1].empty())
+      return std::vector<std::string>();
+    lines.pop_back();
+    return lines;
+  }
+
+  std::string GetLastLineFromListFile() {
+    std::vector<std::string> lines = GetLinesFromListFile();
+    EXPECT_GT(lines.size(), 0u);
+    if (lines.empty())
+      return std::string();
+    return lines[lines.size() - 1];
+  }
+
   base::FilePath test_list_path_;
 };
 
-TEST_F(WebRtcLogUploaderTest, AddUploadedLogInfoToUploadListFile) {
+TEST_F(WebRtcLogUploaderTest, AddLocallyStoredLogInfoToUploadListFile) {
   // Get a temporary filename. We don't want the file to exist to begin with
   // since that's the normal use case, hence the delete.
   ASSERT_TRUE(base::CreateTemporaryFile(&test_list_path_));
@@ -93,24 +139,57 @@
   scoped_ptr<WebRtcLogUploader> webrtc_log_uploader_(
       new WebRtcLogUploader());
 
-  webrtc_log_uploader_->AddUploadedLogInfoToUploadListFile(test_list_path_,
-                                                           kTestReportId);
-  webrtc_log_uploader_->AddUploadedLogInfoToUploadListFile(test_list_path_,
-                                                           kTestReportId);
-  ASSERT_TRUE(VerifyNumberOfLinesAndContentsOfLastLine(2));
+  webrtc_log_uploader_->AddLocallyStoredLogInfoToUploadListFile(test_list_path_,
+                                                                kTestLocalId);
+  webrtc_log_uploader_->AddLocallyStoredLogInfoToUploadListFile(test_list_path_,
+                                                                kTestLocalId);
+  ASSERT_TRUE(VerifyNumberOfLines(2));
+  ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
 
   const int expected_line_limit = 50;
   ASSERT_TRUE(AddLinesToTestFile(expected_line_limit - 2));
-  ASSERT_TRUE(VerifyNumberOfLinesAndContentsOfLastLine(expected_line_limit));
+  ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit));
+  ASSERT_TRUE(VerifyLastLineHasAllInfo());
 
-  webrtc_log_uploader_->AddUploadedLogInfoToUploadListFile(test_list_path_,
-                                                           kTestReportId);
-  ASSERT_TRUE(VerifyNumberOfLinesAndContentsOfLastLine(expected_line_limit));
+  webrtc_log_uploader_->AddLocallyStoredLogInfoToUploadListFile(test_list_path_,
+                                                                kTestLocalId);
+  ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit));
+  ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
 
   ASSERT_TRUE(AddLinesToTestFile(10));
-  ASSERT_TRUE(VerifyNumberOfLinesAndContentsOfLastLine(60));
+  ASSERT_TRUE(VerifyNumberOfLines(60));
+  ASSERT_TRUE(VerifyLastLineHasAllInfo());
 
-  webrtc_log_uploader_->AddUploadedLogInfoToUploadListFile(test_list_path_,
-                                                           kTestReportId);
-  ASSERT_TRUE(VerifyNumberOfLinesAndContentsOfLastLine(expected_line_limit));
+  webrtc_log_uploader_->AddLocallyStoredLogInfoToUploadListFile(test_list_path_,
+                                                                kTestLocalId);
+  ASSERT_TRUE(VerifyNumberOfLines(expected_line_limit));
+  ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
+
+  webrtc_log_uploader_->StartShutdown();
+}
+
+TEST_F(WebRtcLogUploaderTest, AddUploadedLogInfoToUploadListFile) {
+  // Get a temporary filename. We don't want the file to exist to begin with
+  // since that's the normal use case, hence the delete.
+  ASSERT_TRUE(base::CreateTemporaryFile(&test_list_path_));
+  EXPECT_TRUE(base::DeleteFile(test_list_path_, false));
+  scoped_ptr<WebRtcLogUploader> webrtc_log_uploader_(new WebRtcLogUploader());
+
+  webrtc_log_uploader_->AddLocallyStoredLogInfoToUploadListFile(test_list_path_,
+                                                                kTestLocalId);
+  ASSERT_TRUE(VerifyNumberOfLines(1));
+  ASSERT_TRUE(VerifyLastLineHasLocalIdOnly());
+
+  webrtc_log_uploader_->AddUploadedLogInfoToUploadListFile(
+      test_list_path_, kTestLocalId, kTestReportId);
+  ASSERT_TRUE(VerifyNumberOfLines(1));
+  ASSERT_TRUE(VerifyLastLineHasAllInfo());
+
+  // Use a local ID that should not be found in the list.
+  webrtc_log_uploader_->AddUploadedLogInfoToUploadListFile(
+      test_list_path_, "dummy id", kTestReportId);
+  ASSERT_TRUE(VerifyNumberOfLines(2));
+  ASSERT_TRUE(VerifyLastLineHasUploadTimeAndIdOnly());
+
+  webrtc_log_uploader_->StartShutdown();
 }
diff --git a/chrome/browser/media/webrtc_log_util.cc b/chrome/browser/media/webrtc_log_util.cc
new file mode 100644
index 0000000..d443f27
--- /dev/null
+++ b/chrome/browser/media/webrtc_log_util.cc
@@ -0,0 +1,118 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/webrtc_log_util.h"
+
+#include "base/file_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/logging.h"
+#include "base/time/time.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/media/webrtc_log_list.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace {
+
+const int kDaysToKeepLogs = 5;
+
+// Remove any empty entries from the log list. One line is one log entry, see
+// WebRtcLogUploader::AddLocallyStoredLogInfoToUploadListFile for more
+// information about the format.
+void RemoveEmptyEntriesInLogList(std::string* log_list) {
+  static const char kEmptyLine[] = ",,\n";
+  size_t pos = 0;
+  do {
+    pos = log_list->find(kEmptyLine, pos);
+    if (pos == std::string::npos)
+      break;
+    DCHECK(pos == 0 || (*log_list)[pos - 1] == '\n');
+    log_list->erase(pos, arraysize(kEmptyLine) - 1);
+  } while (true);
+}
+
+}  // namespace
+
+// static
+void WebRtcLogUtil::DeleteOldWebRtcLogFiles(const base::FilePath& log_dir) {
+  DeleteOldAndRecentWebRtcLogFiles(log_dir, base::Time::Max());
+}
+
+// static
+void WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles(
+    const base::FilePath& log_dir,
+    const base::Time& delete_begin_time) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+
+  if (!base::PathExists(log_dir)) {
+    // This will happen if no logs have been stored or uploaded.
+    DVLOG(3) << "Could not find directory: " << log_dir.value();
+    return;
+  }
+
+  const base::Time now = base::Time::Now();
+  const base::TimeDelta time_to_keep_logs =
+      base::TimeDelta::FromDays(kDaysToKeepLogs);
+
+  base::FilePath log_list_path =
+      WebRtcLogList::GetWebRtcLogListFileForDirectory(log_dir);
+  std::string log_list;
+  const bool update_log_list = base::PathExists(log_list_path);
+  if (update_log_list) {
+    bool read_ok = base::ReadFileToString(log_list_path, &log_list);
+    DPCHECK(read_ok);
+  }
+
+  base::FileEnumerator log_files(log_dir, false, base::FileEnumerator::FILES);
+  bool delete_ok = true;
+  for (base::FilePath name = log_files.Next(); !name.empty();
+       name = log_files.Next()) {
+    if (name == log_list_path)
+      continue;
+    base::FileEnumerator::FileInfo file_info(log_files.GetInfo());
+    base::TimeDelta file_age = now - file_info.GetLastModifiedTime();
+    if (file_age > time_to_keep_logs ||
+        (!delete_begin_time.is_max() &&
+         file_info.GetLastModifiedTime() > delete_begin_time)) {
+      if (!base::DeleteFile(name, false))
+        delete_ok = false;
+
+      // Remove the local ID from the log list file. The ID is guaranteed to be
+      // unique.
+      std::string id = file_info.GetName().RemoveExtension().MaybeAsASCII();
+      size_t id_pos = log_list.find(id);
+      if (id_pos == std::string::npos)
+        continue;
+      log_list.erase(id_pos, id.size());
+    }
+  }
+
+  if (!delete_ok)
+    LOG(WARNING) << "Could not delete all old WebRTC logs.";
+
+  RemoveEmptyEntriesInLogList(&log_list);
+
+  if (update_log_list) {
+    int written = base::WriteFile(log_list_path, &log_list[0], log_list.size());
+    DPCHECK(written == static_cast<int>(log_list.size()));
+  }
+}
+
+// static
+void WebRtcLogUtil::DeleteOldWebRtcLogFilesForAllProfiles() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  ProfileInfoCache& profile_cache =
+      g_browser_process->profile_manager()->GetProfileInfoCache();
+  size_t profiles_count = profile_cache.GetNumberOfProfiles();
+  for (size_t i = 0; i < profiles_count; ++i) {
+    content::BrowserThread::PostTask(
+        content::BrowserThread::FILE,
+        FROM_HERE,
+        base::Bind(&DeleteOldWebRtcLogFiles,
+                   WebRtcLogList::GetWebRtcLogDirectoryForProfile(
+                       profile_cache.GetPathOfProfileAtIndex(i))));
+  }
+}
diff --git a/chrome/browser/media/webrtc_log_util.h b/chrome/browser/media/webrtc_log_util.h
new file mode 100644
index 0000000..1a0fb55
--- /dev/null
+++ b/chrome/browser/media/webrtc_log_util.h
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_WEBRTC_LOG_UTIL_H_
+#define CHROME_BROWSER_MEDIA_WEBRTC_LOG_UTIL_H_
+
+#include "base/platform_file.h"
+
+class WebRtcLogUtil {
+ public:
+  // Deletes logs files older that 5 days. Updates the log file list. Must be
+  // called on the FILE thread.
+  static void DeleteOldWebRtcLogFiles(const base::FilePath& log_dir);
+
+  // Deletes logs files older that 5 days and logs younger than
+  // |delete_begin_time|. Updates the log file list. If |delete_begin_time| is
+  // base::time::Max(), no recent logs will be deleted, and the function is
+  // equal to DeleteOldWebRtcLogFiles(). Must be called on the FILE thread.
+  static void DeleteOldAndRecentWebRtcLogFiles(
+      const base::FilePath& log_dir,
+      const base::Time& delete_begin_time);
+
+  // Calls DeleteOldWebRtcLogFiles() for all profiles. Must be called on the UI
+  // thread.
+  static void DeleteOldWebRtcLogFilesForAllProfiles();
+};
+
+#endif  // CHROME_BROWSER_MEDIA_WEBRTC_LOG_UTIL_H_
diff --git a/chrome/browser/media/webrtc_log_util_unittest.cc b/chrome/browser/media/webrtc_log_util_unittest.cc
new file mode 100644
index 0000000..f576c17
--- /dev/null
+++ b/chrome/browser/media/webrtc_log_util_unittest.cc
@@ -0,0 +1,70 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/file_util.h"
+#include "base/files/file_enumerator.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/message_loop/message_loop.h"
+#include "base/time/time.h"
+#include "chrome/browser/media/webrtc_log_util.h"
+#include "content/public/test/test_browser_thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+const int kExpectedDaysToKeepLogFiles = 5;
+
+class WebRtcLogUtilTest : public testing::Test {
+ public:
+  WebRtcLogUtilTest()
+      : file_thread_(content::BrowserThread::FILE, &message_loop_) {}
+
+  virtual void SetUp() {
+    // Create three files. One with modified date as of now, one with date one
+    // day younger than the keep limit, one with date one day older than the
+    // limit. The two former are expected to be kept and the last to be deleted
+    // when deleting old logs.
+    ASSERT_TRUE(dir_.CreateUniqueTempDir());
+    base::FilePath file;
+    ASSERT_TRUE(CreateTemporaryFileInDir(dir_.path(), &file));
+    ASSERT_TRUE(CreateTemporaryFileInDir(dir_.path(), &file));
+    base::Time time_expect_to_keep =
+        base::Time::Now() -
+        base::TimeDelta::FromDays(kExpectedDaysToKeepLogFiles - 1);
+    TouchFile(file, time_expect_to_keep, time_expect_to_keep);
+    ASSERT_TRUE(CreateTemporaryFileInDir(dir_.path(), &file));
+    base::Time time_expect_to_delete =
+        base::Time::Now() -
+        base::TimeDelta::FromDays(kExpectedDaysToKeepLogFiles + 1);
+    TouchFile(file, time_expect_to_delete, time_expect_to_delete);
+  }
+
+  void VerifyFiles(int expected_files) {
+    base::FileEnumerator files(dir_.path(), false, base::FileEnumerator::FILES);
+    int file_counter = 0;
+    for (base::FilePath name = files.Next(); !name.empty();
+         name = files.Next()) {
+      EXPECT_LT(base::Time::Now() - files.GetInfo().GetLastModifiedTime(),
+                base::TimeDelta::FromDays(kExpectedDaysToKeepLogFiles));
+      ++file_counter;
+    }
+    EXPECT_EQ(expected_files, file_counter);
+  }
+
+  base::MessageLoopForUI message_loop_;
+  content::TestBrowserThread file_thread_;
+  base::ScopedTempDir dir_;
+};
+
+TEST_F(WebRtcLogUtilTest, DeleteOldWebRtcLogFiles) {
+  WebRtcLogUtil::DeleteOldWebRtcLogFiles(dir_.path());
+  VerifyFiles(2);
+}
+
+TEST_F(WebRtcLogUtilTest, DeleteOldAndRecentWebRtcLogFiles) {
+  base::Time time_begin_delete =
+      base::Time::Now() - base::TimeDelta::FromDays(1);
+  WebRtcLogUtil::DeleteOldAndRecentWebRtcLogFiles(dir_.path(),
+                                                  time_begin_delete);
+  VerifyFiles(1);
+}
diff --git a/chrome/browser/media/webrtc_logging_handler_host.cc b/chrome/browser/media/webrtc_logging_handler_host.cc
index 52d4d54..e1919d2 100644
--- a/chrome/browser/media/webrtc_logging_handler_host.cc
+++ b/chrome/browser/media/webrtc_logging_handler_host.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/cpu.h"
+#include "base/file_util.h"
 #include "base/logging.h"
 #include "base/prefs/pref_service.h"
 #include "base/strings/string_number_conversions.h"
@@ -16,7 +17,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
-#include "chrome/browser/media/webrtc_log_upload_list.h"
+#include "chrome/browser/media/webrtc_log_list.h"
 #include "chrome/browser/media/webrtc_log_uploader.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
@@ -183,7 +184,12 @@
     return;
   }
   upload_callback_ = callback;
-  TriggerUploadLog();
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
+                 this),
+      base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this));
 }
 
 void WebRtcLoggingHandlerHost::UploadLogDone() {
@@ -221,7 +227,12 @@
   if (logging_state_ == STARTED || logging_state_ == STOPPED) {
     if (upload_log_on_render_close_) {
       logging_state_ = STOPPED;
-      TriggerUploadLog();
+      content::BrowserThread::PostTaskAndReplyWithResult(
+          content::BrowserThread::FILE,
+          FROM_HERE,
+          base::Bind(&WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists,
+                     this),
+          base::Bind(&WebRtcLoggingHandlerHost::TriggerUploadLog, this));
     } else {
       g_browser_process->webrtc_log_uploader()->LoggingStoppedDontUpload();
     }
@@ -283,7 +294,6 @@
           "simultaneuos logs has been reached.");
     return;
   }
-  system_request_context_ = g_browser_process->system_request_context();
   BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
       &WebRtcLoggingHandlerHost::DoStartLogging, this));
 }
@@ -400,14 +410,27 @@
   circular_buffer_->Write(&eol, 1);
 }
 
-void WebRtcLoggingHandlerHost::TriggerUploadLog() {
+base::FilePath WebRtcLoggingHandlerHost::GetLogDirectoryAndEnsureExists() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  base::FilePath log_dir_path =
+      WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile_->GetPath());
+  base::File::Error error;
+  if (!base::CreateDirectoryAndGetError(log_dir_path, &error)) {
+    DLOG(ERROR) << "Could not create WebRTC log directory, error: " << error;
+    return base::FilePath();
+  }
+  return log_dir_path;
+}
+
+void WebRtcLoggingHandlerHost::TriggerUploadLog(
+    const base::FilePath& log_directory) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
   DCHECK(logging_state_ == STOPPED);
 
   logging_state_ = UPLOADING;
   WebRtcLogUploadDoneData upload_done_data;
-  upload_done_data.upload_list_path =
-      WebRtcLogUploadList::GetFilePathForProfile(profile_);
+
+  upload_done_data.log_path = log_directory;
   upload_done_data.callback = upload_callback_;
   upload_done_data.host = this;
   upload_callback_.Reset();
@@ -415,7 +438,6 @@
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, base::Bind(
       &WebRtcLogUploader::LoggingStoppedDoUpload,
       base::Unretained(g_browser_process->webrtc_log_uploader()),
-      system_request_context_,
       Passed(&log_buffer_),
       kWebRtcLogSize,
       meta_data_,
diff --git a/chrome/browser/media/webrtc_logging_handler_host.h b/chrome/browser/media/webrtc_logging_handler_host.h
index 6831799..8644986 100644
--- a/chrome/browser/media/webrtc_logging_handler_host.h
+++ b/chrome/browser/media/webrtc_logging_handler_host.h
@@ -119,14 +119,16 @@
   // Writes a formatted log |message| to the |circular_buffer_|.
   void LogToCircularBuffer(const std::string& message);
 
-  void TriggerUploadLog();
+  // Gets the log directory path for |profile_| and ensure it exists. Must be
+  // called on the FILE thread.
+  base::FilePath GetLogDirectoryAndEnsureExists();
+
+  void TriggerUploadLog(const base::FilePath& log_directory);
 
   void FireGenericDoneCallback(GenericDoneCallback* callback,
                                bool success,
                                const std::string& error_message);
 
-  scoped_refptr<net::URLRequestContextGetter> system_request_context_;
-
   scoped_ptr<unsigned char[]> log_buffer_;
   scoped_ptr<PartialCircularBuffer> circular_buffer_;
 
diff --git a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
index da66f2e..f04a5c9 100644
--- a/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/device_media_async_file_util.cc
@@ -49,13 +49,13 @@
     const base::FilePath& profile_path,
     base::FilePath* snapshot_file_path) {
   DCHECK(snapshot_file_path);
-  base::FilePath isolated_media_file_system_dir_path =
+  base::FilePath media_file_system_dir_path =
       profile_path.AppendASCII(kDeviceMediaAsyncFileUtilTempDir);
-  if (!base::CreateDirectory(isolated_media_file_system_dir_path) ||
-      !base::CreateTemporaryFileInDir(isolated_media_file_system_dir_path,
+  if (!base::CreateDirectory(media_file_system_dir_path) ||
+      !base::CreateTemporaryFileInDir(media_file_system_dir_path,
                                       snapshot_file_path)) {
     LOG(WARNING) << "Could not create media snapshot file "
-                 << isolated_media_file_system_dir_path.value();
+                 << media_file_system_dir_path.value();
     *snapshot_file_path = base::FilePath();
   }
 }
diff --git a/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc b/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc
index f355957..38ae639 100644
--- a/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/iphoto_file_util.cc
@@ -47,6 +47,21 @@
   return false;
 }
 
+std::vector<std::string> GetVirtualPathComponents(
+    const fileapi::FileSystemURL& url) {
+  ImportedMediaGalleryRegistry* imported_registry =
+      ImportedMediaGalleryRegistry::GetInstance();
+  base::FilePath root = imported_registry->ImportedRoot().AppendASCII("iphoto");
+
+  DCHECK(root.IsParent(url.path()) || root == url.path());
+  base::FilePath virtual_path;
+  root.AppendRelativePath(url.path(), &virtual_path);
+
+  std::vector<std::string> result;
+  fileapi::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result);
+  return result;
+}
+
 }  // namespace
 
 const char kIPhotoAlbumsDir[] = "Albums";
@@ -156,8 +171,7 @@
     const fileapi::FileSystemURL& url,
     base::File::Info* file_info,
     base::FilePath* platform_path) {
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   if (components.size() == 0) {
     return MakeDirectoryFileInfo(file_info);
@@ -206,8 +220,7 @@
     const fileapi::FileSystemURL& url,
     EntryList* file_list) {
   DCHECK(file_list->empty());
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   // Root directory. Child is the /Albums dir.
   if (components.size() == 0) {
@@ -290,8 +303,7 @@
     fileapi::FileSystemOperationContext* context,
     const fileapi::FileSystemURL& url,
     base::FilePath* local_file_path) {
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   if (components.size() == 3 && components[0] == kIPhotoAlbumsDir) {
     base::FilePath location = GetDataProvider()->GetPhotoLocationInAlbum(
diff --git a/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc
index 645beaf..9ffcceb 100644
--- a/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/iphoto_file_util_unittest.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/media_galleries/fileapi/iphoto_file_util.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
+#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_file_system_options.h"
@@ -185,6 +186,7 @@
 
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
+    ImportedMediaGalleryRegistry::GetInstance()->Initialize();
 
     scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
         new quota::MockSpecialStoragePolicy();
@@ -229,10 +231,14 @@
     ASSERT_FALSE(completed);
   }
 
-  FileSystemURL CreateURL(const std::string& virtual_path) const {
+  FileSystemURL CreateURL(const std::string& path) const {
+    base::FilePath virtual_path =
+        ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot();
+    virtual_path = virtual_path.AppendASCII("iphoto");
+    virtual_path = virtual_path.AppendASCII(path);
     return file_system_context_->CreateCrackedFileSystemURL(
         GURL("http://www.example.com"), fileapi::kFileSystemTypeIphoto,
-        base::FilePath::FromUTF8Unsafe(virtual_path));
+        virtual_path);
   }
 
   fileapi::FileSystemOperationRunner* operation_runner() const {
diff --git a/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc b/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc
index affd5ec..c714a67 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_data_provider.cc
@@ -9,6 +9,8 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/format_macros.h"
+#include "base/i18n/i18n_constants.h"
+#include "base/i18n/icu_string_conversions.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/platform_file.h"
@@ -28,9 +30,10 @@
 namespace {
 
 // Colon and slash are not allowed in filenames, replace them with underscore.
-std::string EscapeBadCharacters(const std::string& input) {
+std::string SanitizeName(const std::string& input) {
   std::string result;
-  base::ReplaceChars(input, ":/", "_", &result);
+  base::ConvertToUtf8AndNormalize(input, base::kCodepageUTF8, &result);
+  base::ReplaceChars(result, ":/", "_", &result);
   return result;
 }
 
@@ -47,8 +50,7 @@
   parser::Album::const_iterator album_it;
   for (album_it = album.begin(); album_it != album.end(); ++album_it) {
     const parser::Track& track = *album_it;
-    std::string name =
-        EscapeBadCharacters(track.location.BaseName().AsUTF8Unsafe());
+    std::string name = SanitizeName(track.location.BaseName().AsUTF8Unsafe());
     duped_tracks[name].insert(&track);
   }
 
@@ -67,8 +69,7 @@
             base::StringPrintf(" (%" PRId64 ")", (*track_it)->id);
         std::string uniquified_track_name =
             track_file_name.InsertBeforeExtensionASCII(id).AsUTF8Unsafe();
-        std::string escaped_track_name =
-            EscapeBadCharacters(uniquified_track_name);
+        std::string escaped_track_name = SanitizeName(uniquified_track_name);
         result[escaped_track_name] = (*track_it)->location;
       }
     }
@@ -286,11 +287,11 @@
     for (parser::Library::const_iterator artist_it = library.begin();
          artist_it != library.end();
          ++artist_it) {
-      std::string artist_name = EscapeBadCharacters(artist_it->first);
+      std::string artist_name = SanitizeName(artist_it->first);
       for (parser::Albums::const_iterator album_it = artist_it->second.begin();
            album_it != artist_it->second.end();
            ++album_it) {
-        std::string album_name = EscapeBadCharacters(album_it->first);
+        std::string album_name = SanitizeName(album_it->first);
         library_[artist_name][album_name] =
             MakeUniqueTrackNames(album_it->second);
       }
diff --git a/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc b/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc
index e8a6c80..979dc01 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_data_provider_browsertest.cc
@@ -38,6 +38,13 @@
   base::FilePath location;
 };
 
+// 'c' with combinding cedilla.
+const char kDeNormalizedName[] = {
+    'c', static_cast<unsigned char>(0xCC), static_cast<unsigned char>(0xA7), 0};
+// 'c' with cedilla.
+const char kNormalizedName[] = {
+    static_cast<unsigned char>(0xC3), static_cast<unsigned char>(0xA7), 0};
+
 }  // namespace
 
 class TestITunesDataProvider : public ITunesDataProvider {
@@ -410,6 +417,7 @@
     entries.push_back(LibraryEntry("Artist:/name", "Album:name/", track));
     entries.push_back(LibraryEntry("Artist/name", "Album:name", track));
     entries.push_back(LibraryEntry("Artist/name", "Album:name", track));
+    entries.push_back(LibraryEntry(kDeNormalizedName, kNormalizedName, track));
     return entries;
   }
 
@@ -430,6 +438,10 @@
               data_provider()->GetTrackLocation(
                   "Artist_name", "Album_name",
                   "Track_1 (3).mp3").NormalizePathSeparators().value());
+    EXPECT_EQ(track.value(),
+              data_provider()->GetTrackLocation(
+                  kNormalizedName, kNormalizedName,
+                  "Track_1.mp3").NormalizePathSeparators().value());
 
     TestDone();
   }
diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc
index 07371f5..9b49c94 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_file_util.cc
@@ -34,6 +34,21 @@
   return base::File::FILE_OK;
 }
 
+std::vector<std::string> GetVirtualPathComponents(
+    const fileapi::FileSystemURL& url) {
+  ImportedMediaGalleryRegistry* imported_registry =
+      ImportedMediaGalleryRegistry::GetInstance();
+  base::FilePath root = imported_registry->ImportedRoot().AppendASCII("itunes");
+
+  DCHECK(root.IsParent(url.path()) || root == url.path());
+  base::FilePath virtual_path;
+  root.AppendRelativePath(url.path(), &virtual_path);
+
+  std::vector<std::string> result;
+  fileapi::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result);
+  return result;
+}
+
 }  // namespace
 
 const char kITunesLibraryXML[] = "iTunes Music Library.xml";
@@ -91,8 +106,7 @@
     const fileapi::FileSystemURL& url,
     base::File::Info* file_info,
     base::FilePath* platform_path) {
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   if (components.size() == 0)
     return MakeDirectoryFileInfo(file_info);
@@ -153,8 +167,7 @@
     const fileapi::FileSystemURL& url,
     EntryList* file_list) {
   DCHECK(file_list->empty());
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   if (components.size() == 0) {
     base::File::Info xml_info;
@@ -264,8 +277,8 @@
     base::File::Info* file_info,
     base::FilePath* platform_path,
     scoped_refptr<webkit_blob::ShareableFileReference>* file_ref) {
-  DCHECK(!url.path().IsAbsolute());
-  if (url.path() != base::FilePath().AppendASCII(kITunesLibraryXML)) {
+  std::vector<std::string> components = GetVirtualPathComponents(url);
+  if (components.size() != 1 || components[0] != kITunesLibraryXML) {
     return NativeMediaFileUtil::CreateSnapshotFileSync(context, url, file_info,
                                                        platform_path, file_ref);
   }
@@ -284,8 +297,7 @@
     fileapi::FileSystemOperationContext* context,
     const fileapi::FileSystemURL& url,
     base::FilePath* local_file_path) {
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   if (components.size() == 1 && components[0] == kITunesLibraryXML) {
     *local_file_path = GetDataProvider()->library_path();
diff --git a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc
index 43a09be..11b5973 100644
--- a/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/itunes_file_util_unittest.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/media_galleries/fileapi/itunes_file_util.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
+#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_file_system_options.h"
@@ -153,6 +154,7 @@
 
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
+    ImportedMediaGalleryRegistry::GetInstance()->Initialize();
 
     scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
         new quota::MockSpecialStoragePolicy();
@@ -197,10 +199,14 @@
     ASSERT_FALSE(completed);
   }
 
-  FileSystemURL CreateURL(const std::string& virtual_path) const {
+  FileSystemURL CreateURL(const std::string& path) const {
+    base::FilePath virtual_path =
+        ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot();
+    virtual_path = virtual_path.AppendASCII("itunes");
+    virtual_path = virtual_path.AppendASCII(path);
     return file_system_context_->CreateCrackedFileSystemURL(
         GURL("http://www.example.com"), fileapi::kFileSystemTypeItunes,
-        base::FilePath::FromUTF8Unsafe(virtual_path));
+        virtual_path);
   }
 
   fileapi::FileSystemOperationRunner* operation_runner() const {
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
index eab10d4..3be12a7 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.cc
@@ -12,19 +12,31 @@
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/platform_file.h"
 #include "base/sequenced_task_runner.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/media_galleries/fileapi/device_media_async_file_util.h"
 #include "chrome/browser/media_galleries/fileapi/media_file_validator_factory.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
 #include "chrome/browser/media_galleries/fileapi/native_media_file_util.h"
+#include "chrome/browser/media_galleries/media_file_system_registry.h"
+#include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/resource_request_info.h"
+#include "extensions/browser/extension_system.h"
+#include "net/url_request/url_request.h"
 #include "webkit/browser/blob/file_stream_reader.h"
 #include "webkit/browser/fileapi/copy_or_move_file_validator.h"
 #include "webkit/browser/fileapi/file_stream_writer.h"
 #include "webkit/browser/fileapi/file_system_context.h"
 #include "webkit/browser/fileapi/file_system_operation.h"
 #include "webkit/browser/fileapi/file_system_operation_context.h"
-#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/file_system_url.h"
 #include "webkit/browser/fileapi/native_file_util.h"
 #include "webkit/common/fileapi/file_system_types.h"
 #include "webkit/common/fileapi/file_system_util.h"
@@ -41,6 +53,67 @@
 using fileapi::FileSystemContext;
 using fileapi::FileSystemURL;
 
+namespace {
+
+const char kMediaGalleryMountPrefix[] = "media_galleries-";
+
+void OnPreferencesInit(
+    const content::RenderViewHost* rvh,
+    const extensions::Extension* extension,
+    MediaGalleryPrefId pref_id,
+    const base::Callback<void(base::File::Error result)>& callback) {
+  MediaFileSystemRegistry* registry =
+      g_browser_process->media_file_system_registry();
+  registry->RegisterMediaFileSystemForExtension(rvh, extension, pref_id,
+                                                callback);
+}
+
+void AttemptAutoMountOnUIThread(
+    int32 process_id,
+    int32 routing_id,
+    const std::string& storage_domain,
+    const std::string& mount_point,
+    const base::Callback<void(base::File::Error result)>& callback) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  content::RenderViewHost* rvh =
+      content::RenderViewHost::FromID(process_id, routing_id);
+  if (rvh) {
+    Profile* profile =
+        Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext());
+
+    ExtensionService* extension_service =
+        extensions::ExtensionSystem::Get(profile)->extension_service();
+    const extensions::Extension* extension =
+        extension_service->GetExtensionById(storage_domain,
+                                            false /*include disabled*/);
+    std::string expected_mount_prefix =
+        MediaFileSystemBackend::ConstructMountName(
+            profile->GetPath(), storage_domain, kInvalidMediaGalleryPrefId);
+    MediaGalleryPrefId pref_id = kInvalidMediaGalleryPrefId;
+    if (extension &&
+        extension->id() == storage_domain &&
+        StartsWithASCII(mount_point, expected_mount_prefix, true) &&
+        base::StringToUint64(mount_point.substr(expected_mount_prefix.size()),
+                             &pref_id) &&
+        pref_id != kInvalidMediaGalleryPrefId) {
+      MediaGalleriesPreferences* preferences =
+          g_browser_process->media_file_system_registry()->GetPreferences(
+              profile);
+      preferences->EnsureInitialized(
+          base::Bind(&OnPreferencesInit, rvh, extension, pref_id, callback));
+      return;
+    }
+  }
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND));
+}
+
+}  // namespace
+
 const char MediaFileSystemBackend::kMediaTaskRunnerName[] =
     "media-task-runner";
 
@@ -87,6 +160,59 @@
   return pool->GetSequencedTaskRunner(media_sequence_token);
 }
 
+// static
+std::string MediaFileSystemBackend::ConstructMountName(
+    const base::FilePath& profile_path,
+    const std::string& extension_id,
+    MediaGalleryPrefId pref_id) {
+  std::string name(kMediaGalleryMountPrefix);
+  name.append(profile_path.BaseName().MaybeAsASCII());
+  name.append("-");
+  name.append(extension_id);
+  name.append("-");
+  if (pref_id != kInvalidMediaGalleryPrefId)
+    name.append(base::Uint64ToString(pref_id));
+  base::ReplaceChars(name, " /", "_", &name);
+  return name;
+}
+
+// static
+bool MediaFileSystemBackend::AttemptAutoMountForURLRequest(
+    const net::URLRequest* url_request,
+    const fileapi::FileSystemURL& filesystem_url,
+    const std::string& storage_domain,
+    const base::Callback<void(base::File::Error result)>& callback) {
+  if (storage_domain.empty() ||
+      filesystem_url.type() != fileapi::kFileSystemTypeExternal ||
+      storage_domain != filesystem_url.origin().host()) {
+    return false;
+  }
+
+  const base::FilePath& virtual_path = filesystem_url.path();
+  if (virtual_path.ReferencesParent())
+    return false;
+  std::vector<base::FilePath::StringType> components;
+  virtual_path.GetComponents(&components);
+  if (components.empty())
+    return false;
+  std::string mount_point = base::FilePath(components[0]).AsUTF8Unsafe();
+  if (!StartsWithASCII(mount_point, kMediaGalleryMountPrefix, true))
+    return false;
+
+  const content::ResourceRequestInfo* request_info =
+      content::ResourceRequestInfo::ForRequest(url_request);
+  if (!request_info)
+    return false;
+
+  content::BrowserThread::PostTask(
+      content::BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&AttemptAutoMountOnUIThread, request_info->GetChildID(),
+                 request_info->GetRouteID(), storage_domain, mount_point,
+                 callback));
+  return true;
+}
+
 bool MediaFileSystemBackend::CanHandleType(
     fileapi::FileSystemType type) const {
   switch (type) {
@@ -112,7 +238,7 @@
     const FileSystemURL& url,
     fileapi::OpenFileSystemMode mode,
     const OpenFileSystemCallback& callback) {
-  // We never allow opening a new isolated FileSystem via usual ResolveURL.
+  // We never allow opening a new FileSystem via usual ResolveURL.
   base::MessageLoopProxy::current()->PostTask(
       FROM_HERE,
       base::Bind(callback,
diff --git a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
index 7dbfbd1..c5b7991 100644
--- a/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
+++ b/chrome/browser/media_galleries/fileapi/media_file_system_backend.h
@@ -5,20 +5,28 @@
 #ifndef CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_MEDIA_FILE_SYSTEM_BACKEND_H_
 #define CHROME_BROWSER_MEDIA_GALLERIES_FILEAPI_MEDIA_FILE_SYSTEM_BACKEND_H_
 
+#include <string>
+
+#include "base/callback.h"
+#include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "chrome/browser/media_galleries/media_galleries_preferences.h"
 #include "webkit/browser/fileapi/file_system_backend.h"
 
 namespace base {
 class SequencedTaskRunner;
 }
 
+namespace fileapi {
+class FileSystemURL;
+}
+
 namespace net {
 class URLRequest;
 }
 
 class MediaPathFilter;
-
 class DeviceMediaAsyncFileUtil;
 
 class MediaFileSystemBackend : public fileapi::FileSystemBackend {
@@ -33,6 +41,12 @@
   static bool CurrentlyOnMediaTaskRunnerThread();
   static scoped_refptr<base::SequencedTaskRunner> MediaTaskRunner();
 
+  // Construct the mount point for the gallery specified by |pref_id| in
+  // the profile located in |profile_path|.
+  static std::string ConstructMountName(const base::FilePath& profile_path,
+                                        const std::string& extension_id,
+                                        MediaGalleryPrefId pref_id);
+
   static bool AttemptAutoMountForURLRequest(
       const net::URLRequest* url_request,
       const fileapi::FileSystemURL& filesystem_url,
diff --git a/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h b/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h
index a6cfebf..e28c9a6 100644
--- a/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h
+++ b/chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h
@@ -19,7 +19,7 @@
 }
 
 // Asynchronous delegate for media transfer protocol (MTP) device to perform
-// media device isolated file system operations. Class that implements this
+// media device file system operations. Class that implements this
 // delegate does the actual communication with the MTP device.
 // The lifetime of the delegate is managed by the MTPDeviceMapService class.
 // Member functions and callbacks run on the IO thread.
diff --git a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc
index 69d8d07..295c019 100644
--- a/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc
+++ b/chrome/browser/media_galleries/fileapi/mtp_device_map_service.cc
@@ -10,7 +10,7 @@
 #include "base/stl_util.h"
 #include "chrome/browser/media_galleries/fileapi/mtp_device_async_delegate.h"
 #include "content/public/browser/browser_thread.h"
-#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
 
 namespace {
 
@@ -85,7 +85,7 @@
     const std::string& filesystem_id) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
   base::FilePath device_path;
-  if (!fileapi::IsolatedContext::GetInstance()->GetRegisteredPath(
+  if (!fileapi::ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(
           filesystem_id, &device_path)) {
     return NULL;
   }
diff --git a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
index 4853c65..1f6098b 100644
--- a/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/native_media_file_util.cc
@@ -10,7 +10,6 @@
 #include "base/bind_helpers.h"
 #include "base/file_util.h"
 #include "base/files/file_enumerator.h"
-#include "base/files/scoped_platform_file_closer.h"
 #include "base/strings/string_util.h"
 #include "base/task_runner_util.h"
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
@@ -60,19 +59,14 @@
 // static
 base::File::Error NativeMediaFileUtil::IsMediaFile(
     const base::FilePath& path) {
-  base::PlatformFile file_handle;
-  const int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
-  base::File::Error error =
-      fileapi::NativeFileUtil::CreateOrOpen(path, flags, &file_handle, NULL);
-  if (error != base::File::FILE_OK)
-    return error;
+  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!file.IsValid())
+    return file.error_details();
 
-  base::ScopedPlatformFileCloser scoped_platform_file(&file_handle);
   char buffer[net::kMaxBytesToSniff];
 
   // Read as much as net::SniffMimeTypeFromLocalData() will bother looking at.
-  int64 len =
-      base::ReadPlatformFile(file_handle, 0, buffer, net::kMaxBytesToSniff);
+  int64 len = file.Read(0, buffer, net::kMaxBytesToSniff);
   if (len < 0)
     return base::File::FILE_ERROR_FAILED;
 
diff --git a/chrome/browser/media_galleries/fileapi/picasa_file_util.cc b/chrome/browser/media_galleries/fileapi/picasa_file_util.cc
index 646f954..6b3ca1f 100644
--- a/chrome/browser/media_galleries/fileapi/picasa_file_util.cc
+++ b/chrome/browser/media_galleries/fileapi/picasa_file_util.cc
@@ -49,11 +49,24 @@
   return base::File::FILE_OK;
 }
 
+std::vector<std::string> GetVirtualPathComponents(
+    const fileapi::FileSystemURL& url) {
+  ImportedMediaGalleryRegistry* imported_registry =
+      ImportedMediaGalleryRegistry::GetInstance();
+  base::FilePath root = imported_registry->ImportedRoot().AppendASCII("picasa");
+
+  DCHECK(root.IsParent(url.path()) || root == url.path());
+  base::FilePath virtual_path;
+  root.AppendRelativePath(url.path(), &virtual_path);
+
+  std::vector<std::string> result;
+  fileapi::VirtualPath::GetComponentsUTF8Unsafe(virtual_path, &result);
+  return result;
+}
+
 PicasaDataProvider::DataType GetDataTypeForURL(
     const fileapi::FileSystemURL& url) {
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
-
+  std::vector<std::string> components = GetVirtualPathComponents(url);
   if (components.size() >= 2 && components[0] == kPicasaDirAlbums)
     return PicasaDataProvider::ALBUMS_IMAGES_DATA;
 
@@ -107,8 +120,7 @@
   if (platform_path)
     *platform_path = base::FilePath();
 
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   switch (components.size()) {
     case 0:
@@ -176,9 +188,7 @@
   if (!file_info.is_directory)
     return base::File::FILE_ERROR_NOT_A_DIRECTORY;
 
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
-
+  std::vector<std::string> components = GetVirtualPathComponents(url);
   switch (components.size()) {
     case 0: {
       // Root directory.
@@ -283,8 +293,7 @@
     base::FilePath* local_file_path) {
   DCHECK(local_file_path);
   DCHECK(url.is_valid());
-  std::vector<std::string> components;
-  fileapi::VirtualPath::GetComponentsUTF8Unsafe(url.path(), &components);
+  std::vector<std::string> components = GetVirtualPathComponents(url);
 
   switch (components.size()) {
     case 2:
diff --git a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc
index c70c2ca..edd294c 100644
--- a/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc
+++ b/chrome/browser/media_galleries/fileapi/picasa_file_util_unittest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/media_galleries/fileapi/media_path_filter.h"
 #include "chrome/browser/media_galleries/fileapi/picasa_data_provider.h"
 #include "chrome/browser/media_galleries/fileapi/picasa_file_util.h"
+#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
 #include "chrome/common/media_galleries/picasa_types.h"
 #include "chrome/common/media_galleries/pmp_constants.h"
 #include "content/public/browser/browser_thread.h"
@@ -228,6 +229,7 @@
 
   virtual void SetUp() OVERRIDE {
     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
+    ImportedMediaGalleryRegistry::GetInstance()->Initialize();
 
     scoped_refptr<quota::SpecialStoragePolicy> storage_policy =
         new quota::MockSpecialStoragePolicy();
@@ -356,10 +358,14 @@
     EXPECT_EQ(0u, contents.size());
   }
 
-  FileSystemURL CreateURL(const std::string& virtual_path) const {
+  FileSystemURL CreateURL(const std::string& path) const {
+    base::FilePath virtual_path =
+        ImportedMediaGalleryRegistry::GetInstance()->ImportedRoot();
+    virtual_path = virtual_path.AppendASCII("picasa");
+    virtual_path = virtual_path.AppendASCII(path);
     return file_system_context_->CreateCrackedFileSystemURL(
         GURL("http://www.example.com"), fileapi::kFileSystemTypePicasa,
-        base::FilePath::FromUTF8Unsafe(virtual_path));
+        virtual_path);
   }
 
   fileapi::FileSystemOperationRunner* operation_runner() const {
diff --git a/chrome/browser/media_galleries/imported_media_gallery_registry.cc b/chrome/browser/media_galleries/imported_media_gallery_registry.cc
index 245d051..506b8c9 100644
--- a/chrome/browser/media_galleries/imported_media_gallery_registry.cc
+++ b/chrome/browser/media_galleries/imported_media_gallery_registry.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
 
 #include "base/bind.h"
+#include "base/file_util.h"
 #include "base/logging.h"
 #include "chrome/browser/media_galleries/fileapi/iphoto_data_provider.h"
 #include "chrome/browser/media_galleries/fileapi/itunes_data_provider.h"
@@ -12,10 +13,11 @@
 #include "chrome/browser/media_galleries/fileapi/picasa_data_provider.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "content/public/browser/browser_thread.h"
-#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/common/fileapi/file_system_mount_option.h"
 
 using base::Bind;
-using fileapi::IsolatedContext;
+using fileapi::ExternalMountPoints;
 
 namespace {
 
@@ -29,25 +31,38 @@
   return g_imported_media_gallery_registry.Pointer();
 }
 
-std::string ImportedMediaGalleryRegistry::RegisterPicasaFilesystemOnUIThread(
-    const base::FilePath& database_path) {
+void ImportedMediaGalleryRegistry::Initialize() {
+  base::ThreadRestrictions::AssertIOAllowed();
+  if (imported_root_.empty()) {
+    if (!base::CreateTemporaryFile(&imported_root_))
+      imported_root_ = base::FilePath();
+    // TODO(vandebo) Setting the permissions of |imported_root_| in CPSP to
+    // zero would be an extra step to ensure permissions are correctly
+    // enforced.
+  }
+}
+
+bool ImportedMediaGalleryRegistry::RegisterPicasaFilesystemOnUIThread(
+    const std::string& fs_name, const base::FilePath& database_path) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK(!fs_name.empty());
   DCHECK(!database_path.empty());
 
-  std::string fsid;
+  bool result = false;
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
-  fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
-           fileapi::kFileSystemTypePicasa,
-           extension_misc::kMediaFileSystemPathPart,
-           base::FilePath());
+  base::FilePath root = ImportedRoot();
+  if (root.empty())
+    return false;
+  result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+      fs_name, fileapi::kFileSystemTypePicasa, fileapi::FileSystemMountOption(),
+      root.AppendASCII("picasa"));
+  if (!result)
+    return result;
 
-  if (fsid.empty())
-    return fsid;
+  picasa_fs_names_.insert(fs_name);
 
-  picasa_fsids_.insert(fsid);
-
-  if (picasa_fsids_.size() == 1) {
+  if (picasa_fs_names_.size() == 1) {
     MediaFileSystemBackend::MediaTaskRunner()->PostTask(
         FROM_HERE,
         Bind(&ImportedMediaGalleryRegistry::RegisterPicasaFileSystem,
@@ -60,28 +75,29 @@
   }
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
-  return fsid;
+  return result;
 }
 
-std::string ImportedMediaGalleryRegistry::RegisterITunesFilesystemOnUIThread(
-    const base::FilePath& library_xml_path) {
+bool ImportedMediaGalleryRegistry::RegisterITunesFilesystemOnUIThread(
+    const std::string& fs_name, const base::FilePath& library_xml_path) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   DCHECK(!library_xml_path.empty());
 
-  std::string fsid;
+  bool result = false;
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
-  fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
-           fileapi::kFileSystemTypeItunes,
-           extension_misc::kMediaFileSystemPathPart,
-           base::FilePath());
+  base::FilePath root = ImportedRoot();
+  if (root.empty())
+    return false;
+  result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+      fs_name, fileapi::kFileSystemTypeItunes, fileapi::FileSystemMountOption(),
+      root.AppendASCII("itunes"));
+  if (!result)
+    return result;
 
-  if (fsid.empty())
-    return fsid;
+  itunes_fs_names_.insert(fs_name);
 
-  itunes_fsids_.insert(fsid);
-
-  if (itunes_fsids_.size() == 1) {
+  if (itunes_fs_names_.size() == 1) {
     MediaFileSystemBackend::MediaTaskRunner()->PostTask(
         FROM_HERE,
         Bind(&ImportedMediaGalleryRegistry::RegisterITunesFileSystem,
@@ -94,30 +110,31 @@
   }
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
-  return fsid;
+  return result;
 }
 
-std::string ImportedMediaGalleryRegistry::RegisterIPhotoFilesystemOnUIThread(
-    const base::FilePath& library_xml_path) {
+bool ImportedMediaGalleryRegistry::RegisterIPhotoFilesystemOnUIThread(
+    const std::string& fs_name, const base::FilePath& library_xml_path) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   DCHECK(!library_xml_path.empty());
 
-  std::string fsid;
+  bool result = false;
 
   // TODO(gbillock): Investigate how to refactor this to reduce duplicated
   // code.
 #if defined(OS_MACOSX)
-  fsid = IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
-           fileapi::kFileSystemTypeIphoto,
-           extension_misc::kMediaFileSystemPathPart,
-           base::FilePath());
+  base::FilePath root = ImportedRoot();
+  if (root.empty())
+    return false;
+  result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+      fs_name, fileapi::kFileSystemTypeIphoto, fileapi::FileSystemMountOption(),
+      root.AppendASCII("iphoto"));
+  if (!result)
+    return result;
 
-  if (fsid.empty())
-    return fsid;
+  iphoto_fs_names_.insert(fs_name);
 
-  iphoto_fsids_.insert(fsid);
-
-  if (iphoto_fsids_.size() == 1) {
+  if (iphoto_fs_names_.size() == 1) {
     MediaFileSystemBackend::MediaTaskRunner()->PostTask(
         FROM_HERE,
         Bind(&ImportedMediaGalleryRegistry::RegisterIPhotoFileSystem,
@@ -130,50 +147,55 @@
   }
 #endif  // defined(OS_MACOSX)
 
-  return fsid;
+  return result;
 }
 
 bool ImportedMediaGalleryRegistry::RevokeImportedFilesystemOnUIThread(
-    const std::string& fsid) {
+    const std::string& fs_name) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
-  if (picasa_fsids_.erase(fsid)) {
-    if (picasa_fsids_.empty()) {
+  if (picasa_fs_names_.erase(fs_name)) {
+    if (picasa_fs_names_.empty()) {
       MediaFileSystemBackend::MediaTaskRunner()->PostTask(
           FROM_HERE,
           Bind(&ImportedMediaGalleryRegistry::RevokePicasaFileSystem,
                base::Unretained(this)));
     }
-    return IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+    return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name);
   }
 
-  if (itunes_fsids_.erase(fsid)) {
-    if (itunes_fsids_.empty()) {
+  if (itunes_fs_names_.erase(fs_name)) {
+    if (itunes_fs_names_.empty()) {
       MediaFileSystemBackend::MediaTaskRunner()->PostTask(
           FROM_HERE,
           Bind(&ImportedMediaGalleryRegistry::RevokeITunesFileSystem,
                base::Unretained(this)));
     }
-    return IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+    return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name);
   }
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 
 #if defined(OS_MACOSX)
-  if (iphoto_fsids_.erase(fsid)) {
-    if (iphoto_fsids_.empty()) {
+  if (iphoto_fs_names_.erase(fs_name)) {
+    if (iphoto_fs_names_.empty()) {
       MediaFileSystemBackend::MediaTaskRunner()->PostTask(
           FROM_HERE,
           Bind(&ImportedMediaGalleryRegistry::RevokeIPhotoFileSystem,
                base::Unretained(this)));
     }
-    return IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+    return ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name);
   }
 #endif  // defined(OS_MACOSX)
 
   return false;
 }
 
+base::FilePath ImportedMediaGalleryRegistry::ImportedRoot() {
+  DCHECK(!imported_root_.empty());
+  return imported_root_;
+}
+
 #if defined(OS_WIN) || defined(OS_MACOSX)
 // static
 picasa::PicasaDataProvider*
@@ -205,12 +227,14 @@
 ImportedMediaGalleryRegistry::ImportedMediaGalleryRegistry() {}
 
 ImportedMediaGalleryRegistry::~ImportedMediaGalleryRegistry() {
+  if (!imported_root_.empty())
+    base::DeleteFile(imported_root_, false);
 #if defined(OS_WIN) || defined(OS_MACOSX)
-  DCHECK_EQ(0U, picasa_fsids_.size());
-  DCHECK_EQ(0U, itunes_fsids_.size());
+  DCHECK_EQ(0U, picasa_fs_names_.size());
+  DCHECK_EQ(0U, itunes_fs_names_.size());
 #endif  // defined(OS_WIN) || defined(OS_MACOSX)
 #if defined(OS_MACOSX)
-  DCHECK_EQ(0U, iphoto_fsids_.size());
+  DCHECK_EQ(0U, iphoto_fs_names_.size());
 #endif  // defined(OS_MACOSX)
 }
 
diff --git a/chrome/browser/media_galleries/imported_media_gallery_registry.h b/chrome/browser/media_galleries/imported_media_gallery_registry.h
index 9e7e2a2..8c343c1 100644
--- a/chrome/browser/media_galleries/imported_media_gallery_registry.h
+++ b/chrome/browser/media_galleries/imported_media_gallery_registry.h
@@ -37,17 +37,24 @@
  public:
   static ImportedMediaGalleryRegistry* GetInstance();
 
+  void Initialize();
+
   // Should be called on the UI thread only.
-  std::string RegisterPicasaFilesystemOnUIThread(
-      const base::FilePath& database_path);
+  bool RegisterPicasaFilesystemOnUIThread(const std::string& fs_name,
+                                          const base::FilePath& database_path);
 
-  std::string RegisterITunesFilesystemOnUIThread(
+  bool RegisterITunesFilesystemOnUIThread(
+      const std::string& fs_name,
       const base::FilePath& xml_library_path);
 
-  std::string RegisterIPhotoFilesystemOnUIThread(
+  bool RegisterIPhotoFilesystemOnUIThread(
+      const std::string& fs_name,
       const base::FilePath& xml_library_path);
 
-  bool RevokeImportedFilesystemOnUIThread(const std::string& fsid);
+  bool RevokeImportedFilesystemOnUIThread(const std::string& fs_name);
+
+  // Path where all virtual file systems are "mounted."
+  base::FilePath ImportedRoot();
 
   // Should be called on the MediaTaskRunner thread only.
 #if defined(OS_WIN) || defined(OS_MACOSX)
@@ -81,14 +88,16 @@
   void RevokeIPhotoFileSystem();
 #endif  // defined(OS_MACOSX)
 
+  base::FilePath imported_root_;
+
 #if defined(OS_WIN) || defined(OS_MACOSX)
   // The data providers are only set or accessed on the task runner thread.
   scoped_ptr<picasa::PicasaDataProvider> picasa_data_provider_;
   scoped_ptr<itunes::ITunesDataProvider> itunes_data_provider_;
 
   // The remaining members are only accessed on the IO thread.
-  std::set<std::string> picasa_fsids_;
-  std::set<std::string> itunes_fsids_;
+  std::set<std::string> picasa_fs_names_;
+  std::set<std::string> itunes_fs_names_;
 
 #ifndef NDEBUG
   base::FilePath picasa_database_path_;
@@ -99,7 +108,7 @@
 #if defined(OS_MACOSX)
   scoped_ptr<iphoto::IPhotoDataProvider> iphoto_data_provider_;
 
-  std::set<std::string> iphoto_fsids_;
+  std::set<std::string> iphoto_fs_names_;
 
 #ifndef NDEBUG
   base::FilePath iphoto_xml_library_path_;
diff --git a/chrome/browser/media_galleries/media_file_system_context.h b/chrome/browser/media_galleries/media_file_system_context.h
index 0ecafd6..a430b31 100644
--- a/chrome/browser/media_galleries/media_file_system_context.h
+++ b/chrome/browser/media_galleries/media_file_system_context.h
@@ -19,13 +19,18 @@
  public:
   virtual ~MediaFileSystemContext() {}
 
-  // Register a new media file system for |path| and return the corresponding
-  // filesystem ID.
-  virtual std::string RegisterFileSystem(
-      const std::string& device_id, const base::FilePath& path) = 0;
+  // Register a new media file system for |path| as |fs_name|.
+  virtual bool RegisterFileSystem(const std::string& device_id,
+                                  const std::string& fs_name,
+                                  const base::FilePath& path) = 0;
 
-  // Revoke the passed |fsid|.
-  virtual void RevokeFileSystem(const std::string& fsid) = 0;
+  // Revoke the passed |fs_name|.
+  virtual void RevokeFileSystem(const std::string& fs_name) = 0;
+
+  // Return the mount point root for the given |fs_name|. Returns an empty path
+  // if |fs_name| is not valid.
+  virtual base::FilePath GetRegisteredPath(
+      const std::string& fs_name) const = 0;
 };
 
 #endif  // CHROME_BROWSER_MEDIA_GALLERIES_MEDIA_FILE_SYSTEM_CONTEXT_H_
diff --git a/chrome/browser/media_galleries/media_file_system_registry.cc b/chrome/browser/media_galleries/media_file_system_registry.cc
index 1010eb6..9451af8 100644
--- a/chrome/browser/media_galleries/media_file_system_registry.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry.cc
@@ -13,6 +13,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/media_galleries/fileapi/media_file_system_backend.h"
 #include "chrome/browser/media_galleries/fileapi/mtp_device_map_service.h"
 #include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
 #include "chrome/browser/media_galleries/media_file_system_context.h"
@@ -36,14 +37,15 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
-#include "webkit/browser/fileapi/isolated_context.h"
+#include "webkit/browser/fileapi/external_mount_points.h"
+#include "webkit/common/fileapi/file_system_mount_option.h"
 #include "webkit/common/fileapi/file_system_types.h"
 
 using content::BrowserThread;
 using content::NavigationController;
 using content::RenderProcessHost;
 using content::WebContents;
-using fileapi::IsolatedContext;
+using fileapi::ExternalMountPoints;
 using storage_monitor::MediaStorageUtil;
 using storage_monitor::StorageInfo;
 using storage_monitor::StorageMonitor;
@@ -261,15 +263,19 @@
   // |no_references_callback| is called when the last RenderViewHost reference
   // goes away. RenderViewHost references are added through ReferenceFromRVH().
   ExtensionGalleriesHost(MediaFileSystemContext* file_system_context,
+                         const base::FilePath& profile_path,
+                         const std::string& extension_id,
                          const base::Closure& no_references_callback)
       : file_system_context_(file_system_context),
+        profile_path_(profile_path),
+        extension_id_(extension_id),
         no_references_callback_(no_references_callback),
         rph_refs_(base::Bind(&ExtensionGalleriesHost::CleanUp,
                              base::Unretained(this))) {
   }
 
   // For each gallery in the list of permitted |galleries|, checks if the
-  // device is attached and if so looks up or creates a file system id and
+  // device is attached and if so looks up or creates a file system name and
   // passes the information needed for the renderer to create those file
   // system objects to the |callback|.
   void GetMediaFileSystems(const MediaGalleryPrefIdSet& galleries,
@@ -288,6 +294,20 @@
         base::Owned(device_ids), galleries, galleries_info, callback));
   }
 
+  // Checks if |gallery| is attached and if so, registers the file system and
+  // then calls |callback| with the result.
+  void RegisterMediaFileSystem(
+      const MediaGalleryPrefInfo& gallery,
+      const base::Callback<void(base::File::Error result)>& callback) {
+    // Extract all the device ids so we can make sure they are attached.
+    MediaStorageUtil::DeviceIdSet* device_ids =
+        new MediaStorageUtil::DeviceIdSet;
+    device_ids->insert(gallery.device_id);
+    MediaStorageUtil::FilterAttachedDevices(device_ids, base::Bind(
+        &ExtensionGalleriesHost::RegisterAttachedMediaFileSystem, this,
+        base::Owned(device_ids), gallery, callback));
+  }
+
   // Revoke the file system for |id| if this extension has created one for |id|.
   void RevokeGalleryByPrefId(MediaGalleryPrefId id) {
     PrefIdFsInfoMap::iterator gallery = pref_id_map_.find(id);
@@ -357,15 +377,15 @@
       if (!MediaStorageUtil::CanCreateFileSystem(device_id, path))
         continue;
 
-      std::string fsid =
-          file_system_context_->RegisterFileSystem(device_id, path);
-      if (fsid.empty())
+      std::string fs_name = MediaFileSystemBackend::ConstructMountName(
+          profile_path_, extension_id_, pref_id);
+      if (!file_system_context_->RegisterFileSystem(device_id, fs_name, path))
         continue;
 
       MediaFileSystemInfo new_entry(
           gallery_info.GetGalleryDisplayName(),
-          path,
-          fsid,
+          file_system_context_->GetRegisteredPath(fs_name),
+          fs_name,
           pref_id,
           GetTransientIdForRemovableDeviceId(device_id),
           StorageInfo::IsRemovableDevice(device_id),
@@ -383,6 +403,46 @@
     callback.Run(result);
   }
 
+  void RegisterAttachedMediaFileSystem(
+      const MediaStorageUtil::DeviceIdSet* attached_device,
+      const MediaGalleryPrefInfo& gallery,
+      const base::Callback<void(base::File::Error result)>& callback) {
+    base::File::Error result = base::File::FILE_ERROR_NOT_FOUND;
+
+    // If rph_refs is empty then we're actually in the middle of shutdown, and
+    // Filter...() lagging which can invoke this method interleaved in the
+    // destruction callback sequence and re-populate pref_id_map_.
+    if (!attached_device->empty() && !rph_refs_.empty()) {
+      std::string fs_name = MediaFileSystemBackend::ConstructMountName(
+          profile_path_, extension_id_, gallery.pref_id);
+      base::FilePath path = gallery.AbsolutePath();
+      const std::string& device_id = gallery.device_id;
+
+      if (ContainsKey(pref_id_map_, gallery.pref_id)) {
+        result = base::File::FILE_OK;
+      } else if (MediaStorageUtil::CanCreateFileSystem(device_id, path) &&
+                 file_system_context_->RegisterFileSystem(device_id, fs_name,
+                                                          path)) {
+        result = base::File::FILE_OK;
+        pref_id_map_[gallery.pref_id] = MediaFileSystemInfo(
+            gallery.GetGalleryDisplayName(),
+            file_system_context_->GetRegisteredPath(fs_name),
+            fs_name,
+            gallery.pref_id,
+            GetTransientIdForRemovableDeviceId(device_id),
+            StorageInfo::IsRemovableDevice(device_id),
+            StorageInfo::IsMediaDevice(device_id));
+      }
+    }
+
+    if (pref_id_map_.empty()) {
+      rph_refs_.Reset();
+      CleanUp();
+    }
+    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+                            base::Bind(callback, result));
+  }
+
   std::string GetTransientIdForRemovableDeviceId(const std::string& device_id) {
     if (!StorageInfo::IsRemovableDevice(device_id))
       return std::string();
@@ -406,6 +466,12 @@
   // safe to store a raw pointer.
   MediaFileSystemContext* file_system_context_;
 
+  // Path for the active profile.
+  const base::FilePath profile_path_;
+
+  // Id of the extension this host belongs to.
+  const std::string extension_id_;
+
   // A callback to call when the last RVH reference goes away.
   base::Closure no_references_callback_;
 
@@ -440,22 +506,9 @@
     return;
   }
 
-  ExtensionGalleriesHostMap::iterator extension_hosts =
-      extension_hosts_map_.find(profile);
-  if (extension_hosts->second.empty())
-    preferences->AddGalleryChangeObserver(this);
-
   ExtensionGalleriesHost* extension_host =
-      extension_hosts->second[extension->id()].get();
-  if (!extension_host) {
-    extension_host = new ExtensionGalleriesHost(
-        file_system_context_.get(),
-        base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty,
-                   base::Unretained(this),
-                   profile,
-                   extension->id()));
-    extension_hosts_map_[profile][extension->id()] = extension_host;
-  }
+      GetExtensionGalleryHost(profile, preferences, extension->id());
+
   // This must come before the GetMediaFileSystems call to make sure the
   // RVH of the context is referenced before the filesystems are retrieved.
   extension_host->ReferenceFromRVH(rvh);
@@ -464,6 +517,40 @@
                                       callback);
 }
 
+void MediaFileSystemRegistry::RegisterMediaFileSystemForExtension(
+    const content::RenderViewHost* rvh,
+    const extensions::Extension* extension,
+    MediaGalleryPrefId pref_id,
+    const base::Callback<void(base::File::Error result)>& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_NE(kInvalidMediaGalleryPrefId, pref_id);
+
+  Profile* profile =
+      Profile::FromBrowserContext(rvh->GetProcess()->GetBrowserContext());
+  MediaGalleriesPreferences* preferences = GetPreferences(profile);
+  MediaGalleriesPrefInfoMap::const_iterator gallery =
+      preferences->known_galleries().find(pref_id);
+  MediaGalleryPrefIdSet permitted_galleries =
+      preferences->GalleriesForExtension(*extension);
+
+  if (gallery == preferences->known_galleries().end() ||
+      !ContainsKey(permitted_galleries, pref_id)) {
+    BrowserThread::PostTask(
+        BrowserThread::IO, FROM_HERE,
+        base::Bind(callback, base::File::FILE_ERROR_NOT_FOUND));
+    return;
+  }
+
+  ExtensionGalleriesHost* extension_host =
+      GetExtensionGalleryHost(profile, preferences, extension->id());
+
+  // This must come before the GetMediaFileSystems call to make sure the
+  // RVH of the context is referenced before the filesystems are retrieved.
+  extension_host->ReferenceFromRVH(rvh);
+
+  extension_host->RegisterMediaFileSystem(gallery->second, callback);
+}
+
 MediaGalleriesPreferences* MediaFileSystemRegistry::GetPreferences(
     Profile* profile) {
   // Create an empty ExtensionHostMap for this profile on first initialization.
@@ -538,41 +625,49 @@
 class MediaFileSystemRegistry::MediaFileSystemContextImpl
     : public MediaFileSystemContext {
  public:
-  explicit MediaFileSystemContextImpl(MediaFileSystemRegistry* registry)
-      : registry_(registry) {
-    DCHECK(registry_);  // Suppresses unused warning on Android.
-  }
+  MediaFileSystemContextImpl() {}
   virtual ~MediaFileSystemContextImpl() {}
 
-  virtual std::string RegisterFileSystem(
-      const std::string& device_id, const base::FilePath& path) OVERRIDE {
+  virtual bool RegisterFileSystem(const std::string& device_id,
+                                  const std::string& fs_name,
+                                  const base::FilePath& path) OVERRIDE {
     if (StorageInfo::IsMassStorageDevice(device_id)) {
-      return RegisterFileSystemForMassStorage(device_id, path);
+      return RegisterFileSystemForMassStorage(device_id, fs_name, path);
     } else {
-      return RegisterFileSystemForMTPDevice(device_id, path);
+      return RegisterFileSystemForMTPDevice(device_id, fs_name, path);
     }
   }
 
-  virtual void RevokeFileSystem(const std::string& fsid) OVERRIDE {
+  virtual void RevokeFileSystem(const std::string& fs_name) OVERRIDE {
     ImportedMediaGalleryRegistry* imported_registry =
         ImportedMediaGalleryRegistry::GetInstance();
-    if (imported_registry->RevokeImportedFilesystemOnUIThread(fsid))
+    if (imported_registry->RevokeImportedFilesystemOnUIThread(fs_name))
       return;
 
-    IsolatedContext::GetInstance()->RevokeFileSystem(fsid);
+    ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(fs_name);
 
-    content::BrowserThread::PostTask(
-        content::BrowserThread::IO, FROM_HERE, base::Bind(
-            &MTPDeviceMapService::RevokeMTPFileSystem,
-            base::Unretained(MTPDeviceMapService::GetInstance()),
-            fsid));
+    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+        &MTPDeviceMapService::RevokeMTPFileSystem,
+        base::Unretained(MTPDeviceMapService::GetInstance()),
+        fs_name));
+  }
+
+  virtual base::FilePath GetRegisteredPath(
+      const std::string& fs_name) const OVERRIDE {
+    base::FilePath result;
+    if (!ExternalMountPoints::GetSystemInstance()->GetRegisteredPath(fs_name,
+                                                                     &result)) {
+      return base::FilePath();
+    }
+    return result;
   }
 
  private:
   // Registers and returns the file system id for the mass storage device
   // specified by |device_id| and |path|.
-  std::string RegisterFileSystemForMassStorage(
-      const std::string& device_id, const base::FilePath& path) {
+  bool RegisterFileSystemForMassStorage(const std::string& device_id,
+                                        const std::string& fs_name,
+                                        const base::FilePath& path) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     DCHECK(StorageInfo::IsMassStorageDevice(device_id));
 
@@ -584,57 +679,52 @@
     // call tree, probably by having it figure out by device id what
     // registration is needed, or having per-device-type handlers at the
     // next higher level.
-    std::string fsid;
+    bool result = false;
     if (StorageInfo::IsITunesDevice(device_id)) {
-      ImportedMediaGalleryRegistry* imported_registry =
+      ImportedMediaGalleryRegistry* registry =
           ImportedMediaGalleryRegistry::GetInstance();
-      fsid = imported_registry->RegisterITunesFilesystemOnUIThread(path);
+      result = registry->RegisterITunesFilesystemOnUIThread(fs_name, path);
     } else if (StorageInfo::IsPicasaDevice(device_id)) {
-      ImportedMediaGalleryRegistry* imported_registry =
+      ImportedMediaGalleryRegistry* registry =
           ImportedMediaGalleryRegistry::GetInstance();
-      fsid = imported_registry->RegisterPicasaFilesystemOnUIThread(
-          path);
+      result = registry->RegisterPicasaFilesystemOnUIThread(fs_name, path);
     } else if (StorageInfo::IsIPhotoDevice(device_id)) {
-      ImportedMediaGalleryRegistry* imported_registry =
+      ImportedMediaGalleryRegistry* registry =
           ImportedMediaGalleryRegistry::GetInstance();
-      fsid = imported_registry->RegisterIPhotoFilesystemOnUIThread(
-          path);
+      result = registry->RegisterIPhotoFilesystemOnUIThread(fs_name, path);
     } else {
-      std::string fs_name(extension_misc::kMediaFileSystemPathPart);
-      fsid = IsolatedContext::GetInstance()->RegisterFileSystemForPath(
-          fileapi::kFileSystemTypeNativeMedia, path, &fs_name);
+      result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+          fs_name, fileapi::kFileSystemTypeNativeMedia,
+          fileapi::FileSystemMountOption(), path);
     }
-    return fsid;
+    return result;
   }
 
-  std::string RegisterFileSystemForMTPDevice(
-      const std::string& device_id, const base::FilePath& path) {
+  bool RegisterFileSystemForMTPDevice(const std::string& device_id,
+                                      const std::string fs_name,
+                                      const base::FilePath& path) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     DCHECK(!StorageInfo::IsMassStorageDevice(device_id));
 
     // Sanity checks for |path|.
     CHECK(MediaStorageUtil::CanCreateFileSystem(device_id, path));
-    std::string fs_name(extension_misc::kMediaFileSystemPathPart);
-    const std::string fsid =
-        IsolatedContext::GetInstance()->RegisterFileSystemForPath(
-            fileapi::kFileSystemTypeDeviceMedia, path, &fs_name);
-    CHECK(!fsid.empty());
-    content::BrowserThread::PostTask(
-        content::BrowserThread::IO, FROM_HERE, base::Bind(
-            &MTPDeviceMapService::RegisterMTPFileSystem,
-            base::Unretained(MTPDeviceMapService::GetInstance()),
-            path.value(), fsid));
-    return fsid;
+    bool result = ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+        fs_name, fileapi::kFileSystemTypeDeviceMedia,
+        fileapi::FileSystemMountOption(), path);
+    CHECK(result);
+    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+        &MTPDeviceMapService::RegisterMTPFileSystem,
+        base::Unretained(MTPDeviceMapService::GetInstance()),
+        path.value(), fs_name));
+    return result;
   }
 
-  MediaFileSystemRegistry* registry_;
-
   DISALLOW_COPY_AND_ASSIGN(MediaFileSystemContextImpl);
 };
 
 // Constructor in 'private' section because depends on private class definition.
 MediaFileSystemRegistry::MediaFileSystemRegistry()
-    : file_system_context_(new MediaFileSystemContextImpl(this)) {
+    : file_system_context_(new MediaFileSystemContextImpl) {
   StorageMonitor::GetInstance()->AddObserver(this);
 }
 
@@ -698,6 +788,33 @@
   }
 }
 
+ExtensionGalleriesHost* MediaFileSystemRegistry::GetExtensionGalleryHost(
+    Profile* profile,
+    MediaGalleriesPreferences* preferences,
+    const std::string& extension_id) {
+  ExtensionGalleriesHostMap::iterator extension_hosts =
+      extension_hosts_map_.find(profile);
+  // GetPreferences(), which had to be called because preferences is an
+  // argument, ensures that profile is in the map.
+  DCHECK(extension_hosts != extension_hosts_map_.end());
+  if (extension_hosts->second.empty())
+    preferences->AddGalleryChangeObserver(this);
+
+  ExtensionGalleriesHost* result = extension_hosts->second[extension_id].get();
+  if (!result) {
+    result = new ExtensionGalleriesHost(
+        file_system_context_.get(),
+        profile->GetPath(),
+        extension_id,
+        base::Bind(&MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty,
+                   base::Unretained(this),
+                   profile,
+                   extension_id));
+    extension_hosts_map_[profile][extension_id] = result;
+  }
+  return result;
+}
+
 void MediaFileSystemRegistry::OnExtensionGalleriesHostEmpty(
     Profile* profile, const std::string& extension_id) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
diff --git a/chrome/browser/media_galleries/media_file_system_registry.h b/chrome/browser/media_galleries/media_file_system_registry.h
index 04065ff..9344698 100644
--- a/chrome/browser/media_galleries/media_file_system_registry.h
+++ b/chrome/browser/media_galleries/media_file_system_registry.h
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
@@ -80,6 +81,14 @@
       const extensions::Extension* extension,
       const MediaFileSystemsCallback& callback);
 
+  // Attempt to register the file system for |pref_id|. If |extension| does not
+  // have permission to |pref_id|, sends |callback| FILE_ERROR_NOT_FOUND.
+  void RegisterMediaFileSystemForExtension(
+      const content::RenderViewHost* rvh,
+      const extensions::Extension* extension,
+      MediaGalleryPrefId pref_id,
+      const base::Callback<void(base::File::Error result)>& callback);
+
   // Returns the media galleries preferences for the specified |profile|.
   // Caller is responsible for ensuring that the preferences are initialized
   // before use.
@@ -110,6 +119,12 @@
   virtual void OnGalleryRemoved(MediaGalleriesPreferences* pref,
                                 MediaGalleryPrefId pref_id) OVERRIDE;
 
+  // Look up or create the extension gallery host.
+  ExtensionGalleriesHost* GetExtensionGalleryHost(
+      Profile* profile,
+      MediaGalleriesPreferences* preferences,
+      const std::string& extension_id);
+
   void OnExtensionGalleriesHostEmpty(Profile* profile,
                                      const std::string& extension_id);
 
diff --git a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
index f771d6a..0bc622a 100644
--- a/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
+++ b/chrome/browser/media_galleries/media_file_system_registry_unittest.cc
@@ -65,47 +65,47 @@
   struct FSInfo {
     FSInfo() {}
     FSInfo(const std::string& device_id, const base::FilePath& path,
-           const std::string& fsid);
+           const std::string& fs_name);
 
     bool operator<(const FSInfo& other) const;
 
     std::string device_id;
     base::FilePath path;
-    std::string fsid;
+    std::string fs_name;
   };
 
   explicit TestMediaFileSystemContext(MediaFileSystemRegistry* registry);
   virtual ~TestMediaFileSystemContext() {}
 
   // MediaFileSystemContext implementation.
-  virtual std::string RegisterFileSystem(
-      const std::string& device_id, const base::FilePath& path) OVERRIDE;
+  virtual bool RegisterFileSystem(const std::string& device_id,
+                                  const std::string& fs_name,
+                                  const base::FilePath& path) OVERRIDE;
 
-  virtual void RevokeFileSystem(const std::string& fsid) OVERRIDE;
+  virtual void RevokeFileSystem(const std::string& fs_name) OVERRIDE;
 
-  base::FilePath GetPathForId(const std::string& fsid) const;
+  virtual base::FilePath GetRegisteredPath(
+      const std::string& fs_name) const OVERRIDE;
 
   MediaFileSystemRegistry* registry() { return registry_; }
 
  private:
-  std::string AddFSEntry(const std::string& device_id,
-                         const base::FilePath& path);
+  void AddFSEntry(const std::string& device_id,
+                  const base::FilePath& path,
+                  const std::string& fs_name);
 
   MediaFileSystemRegistry* registry_;
 
-  // A counter used to construct mock FSIDs.
-  int fsid_;
-
   // The currently allocated mock file systems.
-  std::map<std::string /*fsid*/, FSInfo> file_systems_by_id_;
+  std::map<std::string /*fs_name*/, FSInfo> file_systems_by_name_;
 };
 
 TestMediaFileSystemContext::FSInfo::FSInfo(const std::string& device_id,
                                            const base::FilePath& path,
-                                           const std::string& fsid)
+                                           const std::string& fs_name)
     : device_id(device_id),
       path(path),
-      fsid(fsid) {
+      fs_name(fs_name) {
 }
 
 bool TestMediaFileSystemContext::FSInfo::operator<(const FSInfo& other) const {
@@ -113,47 +113,47 @@
     return device_id < other.device_id;
   if (path.value() != other.path.value())
     return path.value() < other.path.value();
-  return fsid < other.fsid;
+  return fs_name < other.fs_name;
 }
 
 TestMediaFileSystemContext::TestMediaFileSystemContext(
     MediaFileSystemRegistry* registry)
-    : registry_(registry),
-      fsid_(0) {
+    : registry_(registry) {
   registry_->file_system_context_.reset(this);
 }
 
-std::string TestMediaFileSystemContext::RegisterFileSystem(
-    const std::string& device_id, const base::FilePath& path) {
-  std::string fsid = AddFSEntry(device_id, path);
-  return fsid;
+bool TestMediaFileSystemContext::RegisterFileSystem(
+    const std::string& device_id,
+    const std::string& fs_name,
+    const base::FilePath& path) {
+  AddFSEntry(device_id, path, fs_name);
+  return true;
 }
 
-void TestMediaFileSystemContext::RevokeFileSystem(const std::string& fsid) {
-  if (!ContainsKey(file_systems_by_id_, fsid))
+void TestMediaFileSystemContext::RevokeFileSystem(const std::string& fs_name) {
+  if (!ContainsKey(file_systems_by_name_, fs_name))
     return;
-  EXPECT_EQ(1U, file_systems_by_id_.erase(fsid));
+  EXPECT_EQ(1U, file_systems_by_name_.erase(fs_name));
 }
 
-base::FilePath TestMediaFileSystemContext::GetPathForId(
-    const std::string& fsid) const {
-  std::map<std::string /*fsid*/, FSInfo>::const_iterator it =
-      file_systems_by_id_.find(fsid);
-  if (it == file_systems_by_id_.end())
+base::FilePath TestMediaFileSystemContext::GetRegisteredPath(
+    const std::string& fs_name) const {
+  std::map<std::string /*fs_name*/, FSInfo>::const_iterator it =
+      file_systems_by_name_.find(fs_name);
+  if (it == file_systems_by_name_.end())
     return base::FilePath();
   return it->second.path;
 }
 
-std::string TestMediaFileSystemContext::AddFSEntry(const std::string& device_id,
-                                                   const base::FilePath& path) {
+void TestMediaFileSystemContext::AddFSEntry(const std::string& device_id,
+                                            const base::FilePath& path,
+                                            const std::string& fs_name) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(path.IsAbsolute());
   DCHECK(!path.ReferencesParent());
 
-  std::string fsid = base::StringPrintf("FSID:%d", ++fsid_);
-  FSInfo info(device_id, path, fsid);
-  file_systems_by_id_[fsid] = info;
-  return fsid;
+  FSInfo info(device_id, path, fs_name);
+  file_systems_by_name_[fs_name] = info;
 }
 
 namespace {
@@ -184,7 +184,7 @@
   else
     EXPECT_EQ(0UL, info.transient_device_id.size());
 
-  base::FilePath fsid_path = fs_context->GetPathForId(info.fsid);
+  base::FilePath fsid_path = fs_context->GetRegisteredPath(info.fsid);
   EXPECT_EQ(path, fsid_path);
 }
 
@@ -1067,7 +1067,7 @@
   FSInfoMap fs_info = profile_state->GetGalleriesInfo(
       profile_state->regular_permission_extension());
   ASSERT_EQ(1U, fs_info.size());
-  EXPECT_FALSE(test_file_system_context()->GetPathForId(
+  EXPECT_FALSE(test_file_system_context()->GetRegisteredPath(
       fs_info.begin()->second.fsid).empty());
 
   // Revoke permission and ensure that the file system is revoked.
@@ -1075,6 +1075,6 @@
                        profile_state->regular_permission_extension(),
                        device_id,
                        false /*has access*/);
-  EXPECT_TRUE(test_file_system_context()->GetPathForId(
+  EXPECT_TRUE(test_file_system_context()->GetRegisteredPath(
       fs_info.begin()->second.fsid).empty());
 }
diff --git a/chrome/browser/media_galleries/media_galleries_dialog_controller.cc b/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
index 033aa5e..1e9b5f7 100644
--- a/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
+++ b/chrome/browser/media_galleries/media_galleries_dialog_controller.cc
@@ -15,13 +15,13 @@
 #include "chrome/browser/media_galleries/media_gallery_context_menu.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_select_file_policy.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "components/storage_monitor/storage_info.h"
 #include "components/storage_monitor/storage_monitor.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc b/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
index a725f84..9dfc9bb 100644
--- a/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_dialog_controller_unittest.cc
@@ -13,11 +13,11 @@
 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h"
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/storage_monitor/storage_info.h"
 #include "components/storage_monitor/test_storage_monitor.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/media_galleries/media_galleries_preferences.cc b/chrome/browser/media_galleries/media_galleries_preferences.cc
index 070b464..9ab57f4 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences.cc
@@ -20,11 +20,11 @@
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/media_galleries/fileapi/iapps_finder.h"
 #include "chrome/browser/media_galleries/fileapi/picasa_finder.h"
+#include "chrome/browser/media_galleries/imported_media_gallery_registry.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
 #include "chrome/browser/media_galleries/media_galleries_histograms.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_paths.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "chrome/common/pref_names.h"
 #include "components/storage_monitor/media_storage_util.h"
 #include "components/storage_monitor/storage_monitor.h"
@@ -35,6 +35,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
 #include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -306,6 +307,11 @@
           device_name);
 }
 
+void InitializeImportedMediaGalleryRegistryOnFileThread() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+  ImportedMediaGalleryRegistry::GetInstance()->Initialize();
+}
+
 }  // namespace
 
 MediaGalleryPrefInfo::MediaGalleryPrefInfo()
@@ -575,7 +581,7 @@
 }
 
 void MediaGalleriesPreferences::OnFinderDeviceID(const std::string& device_id) {
-  if (!device_id.empty() && !UpdateDeviceIDForSingletonType(device_id)) {
+  if (!device_id.empty()) {
     std::string gallery_name;
     if (StorageInfo::IsIPhotoDevice(device_id))
       gallery_name = kIPhotoGalleryName;
@@ -583,13 +589,25 @@
       gallery_name = kITunesGalleryName;
     else if (StorageInfo::IsPicasaDevice(device_id))
       gallery_name = kPicasaGalleryName;
-    else
-      NOTREACHED();
 
-    AddGalleryInternal(device_id, base::ASCIIToUTF16(gallery_name),
-                       base::FilePath(), MediaGalleryPrefInfo::kAutoDetected,
-                       base::string16(), base::string16(), base::string16(), 0,
-                       base::Time(), false, 0, 0, 0, kCurrentPrefsVersion);
+    if (!gallery_name.empty()) {
+      pre_initialization_callbacks_waiting_++;
+      content::BrowserThread::PostTaskAndReply(
+          content::BrowserThread::FILE,
+          FROM_HERE,
+          base::Bind(&InitializeImportedMediaGalleryRegistryOnFileThread),
+          base::Bind(
+              &MediaGalleriesPreferences::OnInitializationCallbackReturned,
+              weak_factory_.GetWeakPtr()));
+    }
+
+    if (!UpdateDeviceIDForSingletonType(device_id)) {
+      DCHECK(!gallery_name.empty());
+      AddGalleryInternal(device_id, base::ASCIIToUTF16(gallery_name),
+                         base::FilePath(), MediaGalleryPrefInfo::kAutoDetected,
+                         base::string16(), base::string16(), base::string16(),
+                         0, base::Time(), false, 0, 0, 0, kCurrentPrefsVersion);
+    }
   }
 
   OnInitializationCallbackReturned();
diff --git a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
index 01602e9..b6be64a 100644
--- a/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_preferences_unittest.cc
@@ -15,7 +15,6 @@
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/media_galleries/media_file_system_registry.h"
 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/storage_monitor/media_storage_util.h"
 #include "components/storage_monitor/storage_monitor.h"
@@ -24,6 +23,7 @@
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_handlers/background_info.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "grit/generated_resources.h"
 #include "sync/api/string_ordinal.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller.cc b/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller.cc
index dc252c9..f047886 100644
--- a/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller.cc
+++ b/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller.cc
@@ -18,11 +18,11 @@
 #include "chrome/browser/media_galleries/media_gallery_context_menu.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "components/storage_monitor/storage_info.h"
 #include "components/storage_monitor/storage_monitor.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller_unittest.cc b/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller_unittest.cc
index 6e14ef8..6653030 100644
--- a/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller_unittest.cc
@@ -15,12 +15,12 @@
 #include "chrome/browser/media_galleries/media_galleries_preferences.h"
 #include "chrome/browser/media_galleries/media_galleries_scan_result_dialog_controller.h"
 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/storage_monitor/test_storage_monitor.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/media_galleries/media_galleries_test_util.cc b/chrome/browser/media_galleries/media_galleries_test_util.cc
index fe61ee6..bf39a18 100644
--- a/chrome/browser/media_galleries/media_galleries_test_util.cc
+++ b/chrome/browser/media_galleries/media_galleries_test_util.cc
@@ -77,7 +77,8 @@
       extension.get(),
       extensions::Extension::ENABLED,
       false,
-      syncer::StringOrdinal::CreateInitialOrdinal());
+      syncer::StringOrdinal::CreateInitialOrdinal(),
+      std::string());
   ExtensionService* extension_service =
       extensions::ExtensionSystem::Get(profile)->extension_service();
   extension_service->AddExtension(extension.get());
diff --git a/chrome/browser/media_galleries/media_scan_manager_unittest.cc b/chrome/browser/media_galleries/media_scan_manager_unittest.cc
index c582951..5ab0c4e 100644
--- a/chrome/browser/media_galleries/media_scan_manager_unittest.cc
+++ b/chrome/browser/media_galleries/media_scan_manager_unittest.cc
@@ -18,12 +18,12 @@
 #include "chrome/browser/media_galleries/media_galleries_test_util.h"
 #include "chrome/browser/media_galleries/media_scan_manager.h"
 #include "chrome/browser/media_galleries/media_scan_manager_observer.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/storage_monitor/test_storage_monitor.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/memory_details_android.cc b/chrome/browser/memory_details_android.cc
index fab8422..8257f8d 100644
--- a/chrome/browser/memory_details_android.cc
+++ b/chrome/browser/memory_details_android.cc
@@ -11,6 +11,7 @@
 #include "base/bind.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/process/process_iterator.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/common/chrome_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/process_type.h"
@@ -130,7 +131,7 @@
   GetProcessDataMemoryInformation(current_browser_processes, &current_browser);
   current_browser.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
   current_browser.process_name =
-      reinterpret_cast<unsigned int>(chrome::kBrowserProcessExecutableName);
+      base::ASCIIToUTF16(chrome::kBrowserProcessExecutableName);
   process_data_.push_back(current_browser);
 
   // Finally return to the browser thread.
diff --git a/chrome/browser/metrics/cloned_install_detector.cc b/chrome/browser/metrics/cloned_install_detector.cc
new file mode 100644
index 0000000..db52b84
--- /dev/null
+++ b/chrome/browser/metrics/cloned_install_detector.cc
@@ -0,0 +1,95 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/cloned_install_detector.h"
+
+#include "base/bind.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/metrics/cloned_install_detector.h"
+#include "chrome/browser/metrics/machine_id_provider.h"
+#include "chrome/common/pref_names.h"
+#include "components/metrics/metrics_hashes.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace metrics {
+
+namespace {
+
+uint32 HashRawId(const std::string& value) {
+  uint64 hash = metrics::HashMetricName(value);
+
+  // Only use 24 bits from the 64-bit hash.
+  return hash & ((1 << 24) - 1);
+}
+
+// State of the generated machine id in relation to the previously stored value.
+// Note: UMA histogram enum - don't re-order or remove entries
+enum MachineIdState {
+  ID_GENERATION_FAILED,
+  ID_NO_STORED_VALUE,
+  ID_CHANGED,
+  ID_UNCHANGED,
+  ID_ENUM_SIZE
+};
+
+// Logs the state of generating a machine id and comparing it to a stored value.
+void LogMachineIdState(MachineIdState state) {
+  UMA_HISTOGRAM_ENUMERATION("UMA.MachineIdState", state, ID_ENUM_SIZE);
+}
+
+}  // namespace
+
+ClonedInstallDetector::ClonedInstallDetector(MachineIdProvider* raw_id_provider)
+    : raw_id_provider_(raw_id_provider),
+      weak_ptr_factory_(this) {}
+
+ClonedInstallDetector::~ClonedInstallDetector() {}
+
+void ClonedInstallDetector::CheckForClonedInstall(PrefService* local_state) {
+  content::BrowserThread::PostTaskAndReplyWithResult(
+      content::BrowserThread::FILE,
+      FROM_HERE,
+      base::Bind(&metrics::MachineIdProvider::GetMachineId,
+                 raw_id_provider_),
+      base::Bind(&metrics::ClonedInstallDetector::SaveMachineId,
+                 weak_ptr_factory_.GetWeakPtr(),
+                 local_state));
+}
+
+void ClonedInstallDetector::SaveMachineId(
+    PrefService* local_state,
+    std::string raw_id) {
+  if (raw_id.empty()) {
+    LogMachineIdState(ID_GENERATION_FAILED);
+    local_state->ClearPref(prefs::kMetricsMachineId);
+    return;
+  }
+
+  int hashed_id = HashRawId(raw_id);
+
+  MachineIdState id_state = ID_NO_STORED_VALUE;
+  if (local_state->HasPrefPath(prefs::kMetricsMachineId)) {
+    if (local_state->GetInteger(prefs::kMetricsMachineId) != hashed_id) {
+      id_state = ID_CHANGED;
+      // TODO(jwd): Use a callback to set the reset pref. That way
+      // ClonedInstallDetector doesn't need to know about this pref.
+      local_state->SetBoolean(prefs::kMetricsResetIds, true);
+    } else {
+      id_state = ID_UNCHANGED;
+    }
+  }
+
+  LogMachineIdState(id_state);
+
+  local_state->SetInteger(prefs::kMetricsMachineId, hashed_id);
+}
+
+// static
+void ClonedInstallDetector::RegisterPrefs(PrefRegistrySimple* registry) {
+  registry->RegisterIntegerPref(prefs::kMetricsMachineId, 0);
+}
+
+}  // namespace metrics
diff --git a/chrome/browser/metrics/cloned_install_detector.h b/chrome/browser/metrics/cloned_install_detector.h
new file mode 100644
index 0000000..ced164d
--- /dev/null
+++ b/chrome/browser/metrics/cloned_install_detector.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_METRICS_CLONED_INSTALL_DETECTOR_H_
+#define CHROME_BROWSER_METRICS_CLONED_INSTALL_DETECTOR_H_
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+
+class PrefRegistrySimple;
+class PrefService;
+
+namespace metrics {
+
+class MachineIdProvider;
+
+// A class for detecting if an install is cloned. It does this by detecting
+// when the hardware running Chrome changes.
+class ClonedInstallDetector {
+ public:
+  explicit ClonedInstallDetector(MachineIdProvider* raw_id_provider);
+  virtual ~ClonedInstallDetector();
+
+  // Posts a task to generate a machine ID and store it to a local state pref.
+  // If the newly generated ID is different than the previously stored one, then
+  // the install is considered cloned. The ID is a 24-bit value based off of
+  // machine characteristics. This value should never be sent over the network.
+  // TODO(jwd): Implement change detection.
+  void CheckForClonedInstall(PrefService* local_state);
+
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(ClonedInstallDetectorTest, SaveId);
+  FRIEND_TEST_ALL_PREFIXES(ClonedInstallDetectorTest, DetectClone);
+
+  // Converts raw_id into a 24-bit hash and stores the hash in |local_state|.
+  // |raw_id| is not a const ref because it's passed from a cross-thread post
+  // task.
+  void SaveMachineId(PrefService* local_state, std::string raw_id);
+
+  scoped_refptr<MachineIdProvider> raw_id_provider_;
+  base::WeakPtrFactory<ClonedInstallDetector> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(ClonedInstallDetector);
+};
+
+}  // namespace metrics
+
+#endif  // CHROME_BROWSER_METRICS_CLONED_INSTALL_DETECTOR_H_
diff --git a/chrome/browser/metrics/cloned_install_detector_unittest.cc b/chrome/browser/metrics/cloned_install_detector_unittest.cc
new file mode 100644
index 0000000..dcc8bf6
--- /dev/null
+++ b/chrome/browser/metrics/cloned_install_detector_unittest.cc
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/cloned_install_detector.h"
+
+#include "base/prefs/testing_pref_service.h"
+#include "chrome/browser/metrics/machine_id_provider.h"
+#include "chrome/browser/metrics/metrics_service.h"
+#include "chrome/common/pref_names.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace metrics {
+
+namespace {
+
+const std::string kTestRawId = "test";
+// Hashed machine id for |kTestRawId|.
+const int kTestHashedId = 2216819;
+
+}  // namespace
+
+// TODO(jwd): Change these test to test the full flow and histogram outputs. It
+// should also remove the need to make the test a friend of
+// ClonedInstallDetector.
+TEST(ClonedInstallDetectorTest, SaveId) {
+  TestingPrefServiceSimple prefs;
+  ClonedInstallDetector::RegisterPrefs(prefs.registry());
+
+  scoped_ptr<ClonedInstallDetector> detector(
+      new ClonedInstallDetector(MachineIdProvider::CreateInstance()));
+
+  detector->SaveMachineId(&prefs, kTestRawId);
+
+  EXPECT_EQ(kTestHashedId, prefs.GetInteger(prefs::kMetricsMachineId));
+}
+
+TEST(ClonedInstallDetectorTest, DetectClone) {
+  TestingPrefServiceSimple prefs;
+  ClonedInstallDetector::RegisterPrefs(prefs.registry());
+  MetricsService::RegisterPrefs(prefs.registry());
+
+  // Save a machine id that will cause a clone to be detected.
+  prefs.SetInteger(prefs::kMetricsMachineId, kTestHashedId + 1);
+
+  scoped_ptr<ClonedInstallDetector> detector(
+      new ClonedInstallDetector(MachineIdProvider::CreateInstance()));
+
+  detector->SaveMachineId(&prefs, kTestRawId);
+
+  EXPECT_TRUE(prefs.GetBoolean(prefs::kMetricsResetIds));
+}
+
+}  // namespace metrics
diff --git a/chrome/browser/metrics/machine_id_provider.h b/chrome/browser/metrics/machine_id_provider.h
new file mode 100644
index 0000000..a154dad
--- /dev/null
+++ b/chrome/browser/metrics/machine_id_provider.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_METRICS_MACHINE_ID_PROVIDER_H_
+#define CHROME_BROWSER_METRICS_MACHINE_ID_PROVIDER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+
+namespace metrics {
+
+// Provides machine characteristics used as a machine id. The implementation is
+// platform specific with a default implementation that gives an empty id. The
+// class is ref-counted thread safe so it can be used to post to the FILE thread
+// and communicate back to the UI thread.
+// This raw machine id should not be stored or transmitted over the network.
+// TODO(jwd): Simplify implementation to get rid of the need for
+// RefCountedThreadSafe (crbug.com/354882).
+class MachineIdProvider : public base::RefCountedThreadSafe<MachineIdProvider> {
+ public:
+
+  // Get a string containing machine characteristics, to be used as a machine
+  // id. The implementation is platform specific, with a default implementation
+  // returning an empty string.
+  // The return value should not be stored to disk or transmitted.
+  std::string GetMachineId();
+
+  // Returns a pointer to a new MachineIdProvider or NULL if there is no
+  // provider implemented on a given platform. This is done to avoid posting a
+  // task to the FILE thread on platforms with no implementation.
+  static MachineIdProvider* CreateInstance();
+
+ private:
+  friend class base::RefCountedThreadSafe<MachineIdProvider>;
+
+  MachineIdProvider();
+  virtual ~MachineIdProvider();
+
+  DISALLOW_COPY_AND_ASSIGN(MachineIdProvider);
+};
+
+} //  namespace metrics
+
+#endif  // CHROME_BROWSER_METRICS_MACHINE_ID_PROVIDER_H_
diff --git a/chrome/browser/metrics/machine_id_provider_stub.cc b/chrome/browser/metrics/machine_id_provider_stub.cc
new file mode 100644
index 0000000..f9a188b
--- /dev/null
+++ b/chrome/browser/metrics/machine_id_provider_stub.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/machine_id_provider.h"
+
+namespace metrics {
+
+MachineIdProvider::MachineIdProvider() {}
+MachineIdProvider::~MachineIdProvider() {}
+
+// static
+MachineIdProvider* MachineIdProvider::CreateInstance() {
+  return NULL;
+}
+
+std::string MachineIdProvider::GetMachineId() {
+  return std::string();
+}
+
+} //  namespace metrics
diff --git a/chrome/browser/metrics/machine_id_provider_win.cc b/chrome/browser/metrics/machine_id_provider_win.cc
new file mode 100644
index 0000000..c3320bc
--- /dev/null
+++ b/chrome/browser/metrics/machine_id_provider_win.cc
@@ -0,0 +1,106 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/machine_id_provider.h"
+
+#include <windows.h>
+#include <winioctl.h>
+
+#include "base/base_paths.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/win/scoped_handle.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace metrics {
+
+MachineIdProvider::MachineIdProvider() {}
+MachineIdProvider::~MachineIdProvider() {}
+
+// On windows, the machine id is based on the serial number of the drive Chrome
+// is running from.
+std::string MachineIdProvider::GetMachineId() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+
+  // Use the program's path to get the drive used for the machine id. This means
+  // that whenever the underlying drive changes, it's considered a new machine.
+  // This is fine as we do not support migrating Chrome installs to new drives.
+  base::FilePath executable_path;
+
+  if (!PathService::Get(base::FILE_EXE, &executable_path)) {
+    NOTREACHED();
+    return std::string();
+  }
+
+  std::vector<base::FilePath::StringType> path_components;
+  executable_path.GetComponents(&path_components);
+  if (path_components.empty()) {
+    NOTREACHED();
+    return std::string();
+  }
+  base::FilePath::StringType drive_name = L"\\\\.\\" + path_components[0];
+
+  base::win::ScopedHandle drive_handle(CreateFile(
+      drive_name.c_str(),
+      0,
+      FILE_SHARE_READ | FILE_SHARE_WRITE,
+      NULL,
+      OPEN_EXISTING,
+      0,
+      NULL));
+
+  STORAGE_PROPERTY_QUERY query = {};
+  query.PropertyId = StorageDeviceProperty;
+  query.QueryType = PropertyStandardQuery;
+
+  // Perform an initial query to get the number of bytes being returned.
+  DWORD bytes_returned;
+  STORAGE_DESCRIPTOR_HEADER header = {};
+  BOOL status = DeviceIoControl(drive_handle, IOCTL_STORAGE_QUERY_PROPERTY,
+                                &query, sizeof(STORAGE_PROPERTY_QUERY),
+                                &header, sizeof(STORAGE_DESCRIPTOR_HEADER),
+                                &bytes_returned, NULL);
+
+  if (!status)
+    return std::string();
+
+  // Query for the actual serial number.
+  std::vector<int8> output_buf(header.Size);
+  status = DeviceIoControl(drive_handle, IOCTL_STORAGE_QUERY_PROPERTY,
+                           &query, sizeof(STORAGE_PROPERTY_QUERY),
+                           &output_buf[0], output_buf.size(),
+                           &bytes_returned, NULL);
+
+  if (!status)
+    return std::string();
+
+  const STORAGE_DEVICE_DESCRIPTOR* device_descriptor =
+      reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(&output_buf[0]);
+
+  // The serial number is stored in the |output_buf| as a null-terminated
+  // string starting at the specified offset.
+  const DWORD offset = device_descriptor->SerialNumberOffset;
+  if (offset >= output_buf.size())
+    return std::string();
+
+  // Make sure that the null-terminator exists.
+  const std::vector<int8>::iterator serial_number_begin =
+      output_buf.begin() + offset;
+  const std::vector<int8>::iterator null_location =
+      std::find(serial_number_begin, output_buf.end(), '\0');
+  if (null_location == output_buf.end())
+    return std::string();
+
+  const char* serial_number =
+      reinterpret_cast<const char*>(&output_buf[offset]);
+
+  return std::string(serial_number);
+}
+
+// static
+MachineIdProvider* MachineIdProvider::CreateInstance() {
+  return new MachineIdProvider();
+}
+
+} //  namespace metrics
diff --git a/chrome/browser/metrics/machine_id_provider_win_unittest.cc b/chrome/browser/metrics/machine_id_provider_win_unittest.cc
new file mode 100644
index 0000000..93a091d
--- /dev/null
+++ b/chrome/browser/metrics/machine_id_provider_win_unittest.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/metrics/machine_id_provider.h"
+
+#include "base/memory/ref_counted.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace metrics {
+
+TEST(MachineIdProviderTest, GetId) {
+  content::TestBrowserThreadBundle thread_bundle;
+
+  scoped_refptr<MachineIdProvider> provider(
+      MachineIdProvider::CreateInstance());
+  std::string id1 = provider->GetMachineId();
+
+  EXPECT_NE(std::string(), id1);
+
+  std::string id2 = provider->GetMachineId();
+  EXPECT_EQ(id1, id2);
+}
+
+}  // namespace metrics
diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc
index f9721f4..4fd74e7 100644
--- a/chrome/browser/metrics/metrics_log.cc
+++ b/chrome/browser/metrics/metrics_log.cc
@@ -84,7 +84,7 @@
     return "0";
   }
 
-  return pref->GetString(prefs::kMetricsClientIDTimestamp);
+  return pref->GetString(prefs::kMetricsReportingEnabledTimestamp);
 }
 
 OmniboxEventProto::InputType AsOmniboxEventInputType(
diff --git a/chrome/browser/metrics/metrics_log_unittest.cc b/chrome/browser/metrics/metrics_log_unittest.cc
index 9f3ca7c..eba9ed1 100644
--- a/chrome/browser/metrics/metrics_log_unittest.cc
+++ b/chrome/browser/metrics/metrics_log_unittest.cc
@@ -160,8 +160,8 @@
  private:
   void InitPrefs() {
     prefs_->SetInt64(prefs::kInstallDate, kInstallDate);
-    prefs_->SetString(prefs::kMetricsClientIDTimestamp,
-                     base::Int64ToString(kEnabledDate));
+    prefs_->SetString(prefs::kMetricsReportingEnabledTimestamp,
+                      base::Int64ToString(kEnabledDate));
 #if defined(OS_CHROMEOS)
     prefs_->SetInteger(prefs::kStabilityChildProcessCrashCount, 10);
     prefs_->SetInteger(prefs::kStabilityOtherUserCrashCount, 11);
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index 80fa396..ecd3114 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -188,7 +188,9 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/io_thread.h"
 #include "chrome/browser/memory_details.h"
+#include "chrome/browser/metrics/cloned_install_detector.h"
 #include "chrome/browser/metrics/compression_utils.h"
+#include "chrome/browser/metrics/machine_id_provider.h"
 #include "chrome/browser/metrics/metrics_log.h"
 #include "chrome/browser/metrics/metrics_log_serializer.h"
 #include "chrome/browser/metrics/metrics_reporting_scheduler.h"
@@ -233,6 +235,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/external_metrics.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chromeos/system/statistics_provider.h"
 #endif
 
@@ -432,10 +435,11 @@
 // static
 void MetricsService::RegisterPrefs(PrefRegistrySimple* registry) {
   DCHECK(IsSingleThreaded());
+  registry->RegisterBooleanPref(prefs::kMetricsResetIds, false);
   registry->RegisterStringPref(prefs::kMetricsClientID, std::string());
+  registry->RegisterInt64Pref(prefs::kMetricsReportingEnabledTimestamp, 0);
   registry->RegisterIntegerPref(prefs::kMetricsLowEntropySource,
                                 kLowEntropySourceNotSet);
-  registry->RegisterInt64Pref(prefs::kMetricsClientIDTimestamp, 0);
   registry->RegisterInt64Pref(prefs::kStabilityLaunchTimeSec, 0);
   registry->RegisterInt64Pref(prefs::kStabilityLastTimestampSec, 0);
   registry->RegisterStringPref(prefs::kStabilityStatsVersion, std::string());
@@ -480,6 +484,11 @@
   registry->RegisterInt64Pref(prefs::kUninstallLastLaunchTimeSec, 0);
   registry->RegisterInt64Pref(prefs::kUninstallLastObservedRunTimeSec, 0);
 
+  // TODO(asvitkine): Remove these once a couple of releases have passed.
+  // http://crbug.com/357704
+  registry->RegisterStringPref(prefs::kMetricsOldClientID, std::string());
+  registry->RegisterIntegerPref(prefs::kMetricsOldLowEntropySource, 0);
+
 #if defined(OS_ANDROID)
   RegisterPrefsAndroid(registry);
 #endif  // defined(OS_ANDROID)
@@ -518,7 +527,8 @@
 }
 
 MetricsService::MetricsService()
-    : recording_active_(false),
+    : metrics_ids_reset_check_performed_(false),
+      recording_active_(false),
       reporting_active_(false),
       test_mode_active_(false),
       state_(INITIALIZED),
@@ -630,6 +640,9 @@
 void MetricsService::ForceClientIdCreation() {
   if (!client_id_.empty())
     return;
+
+  ResetMetricsIDsIfNecessary();
+
   PrefService* pref = g_browser_process->local_state();
   client_id_ = pref->GetString(prefs::kMetricsClientID);
   if (!client_id_.empty())
@@ -638,9 +651,14 @@
   client_id_ = GenerateClientID();
   pref->SetString(prefs::kMetricsClientID, client_id_);
 
-  // Might as well make a note of how long this ID has existed
-  pref->SetString(prefs::kMetricsClientIDTimestamp,
-                  base::Int64ToString(Time::Now().ToTimeT()));
+  if (pref->GetString(prefs::kMetricsOldClientID).empty()) {
+    // Record the timestamp of when the user opted in to UMA.
+    pref->SetInt64(prefs::kMetricsReportingEnabledTimestamp,
+                   Time::Now().ToTimeT());
+  } else {
+    UMA_HISTOGRAM_BOOLEAN("UMA.ClientIdMigrated", true);
+  }
+  pref->ClearPref(prefs::kMetricsOldClientID);
 }
 
 void MetricsService::EnableRecording() {
@@ -1182,6 +1200,26 @@
   }
 }
 
+void MetricsService::ResetMetricsIDsIfNecessary() {
+  if (metrics_ids_reset_check_performed_)
+    return;
+
+  metrics_ids_reset_check_performed_ = true;
+
+  PrefService* local_state = g_browser_process->local_state();
+  if (!local_state->GetBoolean(prefs::kMetricsResetIds))
+    return;
+
+  UMA_HISTOGRAM_BOOLEAN("UMA.MetricsIDsReset", true);
+
+  DCHECK(client_id_.empty());
+  DCHECK_EQ(kLowEntropySourceNotSet, low_entropy_source_);
+
+  local_state->ClearPref(prefs::kMetricsClientID);
+  local_state->ClearPref(prefs::kMetricsLowEntropySource);
+  local_state->ClearPref(prefs::kMetricsResetIds);
+}
+
 int MetricsService::GetLowEntropySource() {
   // Note that the default value for the low entropy source and the default pref
   // value are both kLowEntropySourceNotSet, which is used to identify if the
@@ -1189,18 +1227,14 @@
   if (low_entropy_source_ != kLowEntropySourceNotSet)
     return low_entropy_source_;
 
+  ResetMetricsIDsIfNecessary();
+
   PrefService* local_state = g_browser_process->local_state();
   const CommandLine* command_line(CommandLine::ForCurrentProcess());
   // Only try to load the value from prefs if the user did not request a reset.
   // Otherwise, skip to generating a new value.
   if (!command_line->HasSwitch(switches::kResetVariationState)) {
     int value = local_state->GetInteger(prefs::kMetricsLowEntropySource);
-    // Old versions of the code would generate values in the range of [1, 8192],
-    // before the range was switched to [0, 8191] and then to [0, 7999]. Map
-    // 8192 to 0, so that the 0th bucket remains uniform, while re-generating
-    // the low entropy source for old values in the [8000, 8191] range.
-    if (value == 8192)
-      value = 0;
     // If the value is outside the [0, kMaxLowEntropySize) range, re-generate
     // it below.
     if (value >= 0 && value < kMaxLowEntropySize) {
@@ -1213,6 +1247,7 @@
   UMA_HISTOGRAM_BOOLEAN("UMA.GeneratedLowEntropySource", true);
   low_entropy_source_ = GenerateLowEntropySource();
   local_state->SetInteger(prefs::kMetricsLowEntropySource, low_entropy_source_);
+  local_state->ClearPref(prefs::kMetricsOldLowEntropySource);
   metrics::CachingPermutedEntropyProvider::ClearCache(local_state);
 
   return low_entropy_source_;
@@ -1858,6 +1893,21 @@
   synthetic_trial_groups_.push_back(trial_group);
 }
 
+void MetricsService::CheckForClonedInstall() {
+  DCHECK(!cloned_install_detector_);
+
+  metrics::MachineIdProvider* provider =
+      metrics::MachineIdProvider::CreateInstance();
+  if (!provider)
+    return;
+
+  cloned_install_detector_.reset(
+      new metrics::ClonedInstallDetector(provider));
+
+  PrefService* local_state = g_browser_process->local_state();
+  cloned_install_detector_->CheckForClonedInstall(local_state);
+}
+
 void MetricsService::GetCurrentSyntheticFieldTrials(
     std::vector<chrome_variations::ActiveGroupId>* synthetic_trials) {
   DCHECK(synthetic_trials);
@@ -2068,3 +2118,22 @@
   }
   return result;
 }
+
+bool MetricsServiceHelper::IsCrashReportingEnabled() {
+#if defined(GOOGLE_CHROME_BUILD)
+#if defined(OS_CHROMEOS)
+  bool reporting_enabled = false;
+  chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
+                                            &reporting_enabled);
+  return reporting_enabled;
+#elif defined(OS_ANDROID)
+  // Android has its own settings for metrics / crash uploading.
+  const PrefService* prefs = g_browser_process->local_state();
+  return prefs->GetBoolean(prefs::kCrashReportingEnabled);
+#else
+  return MetricsServiceHelper::IsMetricsReportingEnabled();
+#endif
+#else
+  return false;
+#endif
+}
diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h
index f1a2fb0..9ee89e2 100644
--- a/chrome/browser/metrics/metrics_service.h
+++ b/chrome/browser/metrics/metrics_service.h
@@ -42,6 +42,11 @@
 class Profile;
 class TemplateURLService;
 
+namespace {
+class CrashesDOMHandler;
+class FlashDOMHandler;
+}
+
 namespace base {
 class DictionaryValue;
 class MessageLoopProxy;
@@ -60,6 +65,11 @@
 namespace extensions {
 class ExtensionDownloader;
 class ManifestFetchData;
+class MetricsPrivateGetIsCrashReportingEnabledFunction;
+}
+
+namespace metrics {
+class ClonedInstallDetector;
 }
 
 namespace net {
@@ -70,6 +80,10 @@
 bool IsOmniboxEnabled(Profile* profile);
 }
 
+namespace system_logs {
+class ChromeInternalLogSource;
+}
+
 namespace tracked_objects {
 struct ProcessDataSnapshot;
 }
@@ -274,6 +288,11 @@
   // To use this method, SyntheticTrialGroup should friend your class.
   void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group);
 
+  // Check if this install was cloned or imaged from another machine. If a
+  // clone is detected, reset the client id and low entropy source. This
+  // should not be called more than once.
+  void CheckForClonedInstall();
+
  private:
   // The MetricsService has a lifecycle that is stored as a state.
   // See metrics_service.cc for description of this lifecycle.
@@ -349,6 +368,10 @@
                   base::TimeDelta* incremental_uptime,
                   base::TimeDelta* uptime);
 
+  // Reset the client id and low entropy source if the kMetricsResetMetricIDs
+  // pref is true.
+  void ResetMetricsIDsIfNecessary();
+
   // Returns the low entropy source for this client. This is a random value
   // that is non-identifying amongst browser clients. This method will
   // generate the entropy source value if it has not been called before.
@@ -504,6 +527,10 @@
 
   content::NotificationRegistrar registrar_;
 
+  // Set to true when |ResetMetricsIDsIfNecessary| is called for the first time.
+  // This prevents multiple resets within the same Chrome session.
+  bool metrics_ids_reset_check_performed_;
+
   // Indicate whether recording and reporting are currently happening.
   // These should not be set directly, but by calling SetRecording and
   // SetReporting.
@@ -612,12 +639,15 @@
   // Field trial groups that map to Chrome configuration states.
   SyntheticTrialGroups synthetic_trial_groups_;
 
+  scoped_ptr<metrics::ClonedInstallDetector> cloned_install_detector_;
+
   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, ClientIdCorrectlyFormatted);
   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, IsPluginProcess);
   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, LowEntropySource0NotReset);
   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest,
                            PermutedEntropyCacheClearedWhenLowEntropyReset);
   FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, RegisterSyntheticTrial);
+  FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, ResetMetricsIDs);
   FRIEND_TEST_ALL_PREFIXES(MetricsServiceBrowserTest,
                            CheckLowEntropySourceUsed);
   FRIEND_TEST_ALL_PREFIXES(MetricsServiceReportingTest,
@@ -626,18 +656,30 @@
   DISALLOW_COPY_AND_ASSIGN(MetricsService);
 };
 
-// This class limits and documents access to the IsMetricsReportingEnabled()
-// method. Since the method is private, each user has to be explicitly declared
-// as a 'friend' below.
+// This class limits and documents access to the IsMetricsReportingEnabled() and
+// IsCrashReportingEnabled() methods. Since these methods are private, each user
+// has to be explicitly declared as a 'friend' below.
 class MetricsServiceHelper {
  private:
   friend bool prerender::IsOmniboxEnabled(Profile* profile);
+  friend class ChromeRenderMessageFilter;
+  friend class ::CrashesDOMHandler;
   friend class extensions::ExtensionDownloader;
   friend class extensions::ManifestFetchData;
+  friend class extensions::MetricsPrivateGetIsCrashReportingEnabledFunction;
+  friend class ::FlashDOMHandler;
+  friend class system_logs::ChromeInternalLogSource;
+  FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, MetricsReportingEnabled);
+  FRIEND_TEST_ALL_PREFIXES(MetricsServiceTest, CrashReportingEnabled);
 
   // Returns true if prefs::kMetricsReportingEnabled is set.
   static bool IsMetricsReportingEnabled();
 
+  // Returns true if crash reporting is enabled.  This is set at the platform
+  // level for Android and ChromeOS, and otherwise is the same as
+  // IsMetricsReportingEnabled for desktop Chrome.
+  static bool IsCrashReportingEnabled();
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(MetricsServiceHelper);
 };
 
diff --git a/chrome/browser/metrics/metrics_service_unittest.cc b/chrome/browser/metrics/metrics_service_unittest.cc
index 2d38c44..ae110db 100644
--- a/chrome/browser/metrics/metrics_service_unittest.cc
+++ b/chrome/browser/metrics/metrics_service_unittest.cc
@@ -336,3 +336,80 @@
   EXPECT_TRUE(HasSyntheticTrial(synthetic_trials, "TestTrial3", "Group3"));
   service.log_manager_.FinishCurrentLog();
 }
+
+TEST_F(MetricsServiceTest, MetricsReportingEnabled) {
+#if !defined(OS_CHROMEOS)
+  GetLocalState()->SetBoolean(prefs::kMetricsReportingEnabled, false);
+  EXPECT_FALSE(MetricsServiceHelper::IsMetricsReportingEnabled());
+  GetLocalState()->SetBoolean(prefs::kMetricsReportingEnabled, true);
+  EXPECT_TRUE(MetricsServiceHelper::IsMetricsReportingEnabled());
+  GetLocalState()->ClearPref(prefs::kMetricsReportingEnabled);
+  EXPECT_FALSE(MetricsServiceHelper::IsMetricsReportingEnabled());
+#else
+  // ChromeOS does not register prefs::kMetricsReportingEnabled and uses
+  // device settings for metrics reporting.
+  EXPECT_FALSE(MetricsServiceHelper::IsMetricsReportingEnabled());
+#endif
+}
+
+
+TEST_F(MetricsServiceTest, CrashReportingEnabled) {
+#if defined(GOOGLE_CHROME_BUILD)
+// ChromeOS has different device settings for crash reporting.
+#if !defined(OS_CHROMEOS)
+#if defined(OS_ANDROID)
+  const char* crash_pref = prefs::kCrashReportingEnabled;
+#else
+  const char* crash_pref = prefs::kMetricsReportingEnabled;
+#endif
+  GetLocalState()->SetBoolean(crash_pref, false);
+  EXPECT_FALSE(MetricsServiceHelper::IsCrashReportingEnabled());
+  GetLocalState()->SetBoolean(crash_pref, true);
+  EXPECT_TRUE(MetricsServiceHelper::IsCrashReportingEnabled());
+  GetLocalState()->ClearPref(crash_pref);
+  EXPECT_FALSE(MetricsServiceHelper::IsCrashReportingEnabled());
+#endif // !defined(OS_CHROMEOS)
+#else // defined(GOOGLE_CHROME_BUILD)
+  // Chromium branded browsers never have crash reporting enabled.
+  EXPECT_FALSE(MetricsServiceHelper::IsCrashReportingEnabled());
+#endif // defined(GOOGLE_CHROME_BUILD)
+}
+
+// Check that setting the kMetricsResetIds pref to true causes the client id to
+// be reset. We do not check that the low entropy source is reset because we
+// cannot ensure that metrics service won't generate the same id again.
+TEST_F(MetricsServiceTest, ResetMetricsIDs) {
+  // Set an initial client id in prefs. It should not be possible for the
+  // metrics service to generate this id randomly.
+  const std::string kInitialClientId = "initial client id";
+  GetLocalState()->SetString(prefs::kMetricsClientID, kInitialClientId);
+
+  // Make sure the initial client id isn't reset by the metrics service.
+  {
+    MetricsService service;
+    service.ForceClientIdCreation();
+    EXPECT_TRUE(service.metrics_ids_reset_check_performed_);
+    EXPECT_EQ(kInitialClientId, service.client_id_);
+  }
+
+
+  // Set the reset pref to cause the IDs to be reset.
+  GetLocalState()->SetBoolean(prefs::kMetricsResetIds, true);
+
+  // Cause the actual reset to happen.
+  {
+    MetricsService service;
+    service.ForceClientIdCreation();
+    EXPECT_TRUE(service.metrics_ids_reset_check_performed_);
+    EXPECT_NE(kInitialClientId, service.client_id_);
+
+    service.GetLowEntropySource();
+
+    EXPECT_FALSE(GetLocalState()->GetBoolean(prefs::kMetricsResetIds));
+  }
+
+  std::string new_client_id =
+      GetLocalState()->GetString(prefs::kMetricsClientID);
+
+  EXPECT_NE(kInitialClientId, new_client_id);
+}
diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
index 3b030c4..30fd547 100644
--- a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
+++ b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc
@@ -57,12 +57,20 @@
     request.add_public_key_hash(i->ToString());
   }
 
-  const char* const* google_acceptable_certs =
-    net::TransportSecurityState::GooglePinsForDebugging();
-  for (size_t i = 0; google_acceptable_certs[i]; i++) {
-    net::HashValue hash_value(net::HASH_VALUE_SHA1);
-    memcpy(hash_value.data(), google_acceptable_certs[i], hash_value.size());
-    request.add_pin(hash_value.ToString());
+  const char* const* required_pins;
+  const char* const* excluded_pins;
+  if (net::TransportSecurityState::GetPinsForDebugging(
+          hostname, &required_pins, &excluded_pins)) {
+    for (size_t i = 0; required_pins[i]; i++) {
+      net::HashValue hash_value(net::HASH_VALUE_SHA1);
+      memcpy(hash_value.data(), required_pins[i], hash_value.size());
+      request.add_pin(hash_value.ToString());
+    }
+    for (size_t i = 0; excluded_pins[i]; i++) {
+      net::HashValue hash_value(net::HASH_VALUE_SHA1);
+      memcpy(hash_value.data(), excluded_pins[i], hash_value.size());
+      request.add_pin("!" + hash_value.ToString());
+    }
   }
 
   std::string out;
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc
index 2e9d3e7..b590367 100644
--- a/chrome/browser/net/chrome_network_delegate.cc
+++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -512,10 +512,16 @@
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     const net::HttpResponseHeaders* original_response_headers,
-    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   return ExtensionWebRequestEventRouter::GetInstance()->OnHeadersReceived(
-      profile_, extension_info_map_.get(), request, callback,
-      original_response_headers, override_response_headers);
+      profile_,
+      extension_info_map_.get(),
+      request,
+      callback,
+      original_response_headers,
+      override_response_headers,
+      allowed_unsafe_redirect_url);
 }
 
 void ChromeNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
diff --git a/chrome/browser/net/chrome_network_delegate.h b/chrome/browser/net/chrome_network_delegate.h
index 6adf283..d6ecc7e 100644
--- a/chrome/browser/net/chrome_network_delegate.h
+++ b/chrome/browser/net/chrome_network_delegate.h
@@ -151,8 +151,8 @@
       net::URLRequest* request,
       const net::CompletionCallback& callback,
       const net::HttpResponseHeaders* original_response_headers,
-      scoped_refptr<net::HttpResponseHeaders>* override_response_headers)
-      OVERRIDE;
+      scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE;
   virtual void OnBeforeRedirect(net::URLRequest* request,
                                 const GURL& new_location) OVERRIDE;
   virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
diff --git a/chrome/browser/net/disk_cache_dir_policy_handler.cc b/chrome/browser/net/disk_cache_dir_policy_handler.cc
index eaff244..737862a 100644
--- a/chrome/browser/net/disk_cache_dir_policy_handler.cc
+++ b/chrome/browser/net/disk_cache_dir_policy_handler.cc
@@ -27,7 +27,7 @@
     base::FilePath::StringType expanded_value =
         policy::path_parser::ExpandPathVariables(string_value);
     prefs->SetValue(prefs::kDiskCacheDir,
-                    base::Value::CreateStringValue(expanded_value));
+                    new base::StringValue(expanded_value));
   }
 }
 
diff --git a/chrome/browser/net/proxy_policy_handler_unittest.cc b/chrome/browser/net/proxy_policy_handler_unittest.cc
index 446d92c..c300d32 100644
--- a/chrome/browser/net/proxy_policy_handler_unittest.cc
+++ b/chrome/browser/net/proxy_policy_handler_unittest.cc
@@ -74,11 +74,16 @@
 
 TEST_F(ProxyPolicyHandlerTest, ManualOptions) {
   PolicyMap policy;
-  policy.Set(key::kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("http://chromium.org/override"),
+  policy.Set(key::kProxyBypassList,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("http://chromium.org/override"),
              NULL);
-  policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("chromium.org"), NULL);
+  policy.Set(key::kProxyServer,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("chromium.org"),
+             NULL);
   policy.Set(
       key::kProxyServerMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
       base::Value::CreateIntegerValue(
@@ -99,11 +104,16 @@
       base::Value::CreateIntegerValue(
           ProxyPolicyHandler::PROXY_MANUALLY_CONFIGURED_PROXY_SERVER_MODE),
       NULL);
-  policy.Set(key::kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("http://chromium.org/override"),
+  policy.Set(key::kProxyBypassList,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("http://chromium.org/override"),
              NULL);
-  policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("chromium.org"), NULL);
+  policy.Set(key::kProxyServer,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("chromium.org"),
+             NULL);
   UpdateProviderPolicy(policy);
 
   VerifyProxyPrefs("chromium.org",
@@ -138,8 +148,10 @@
 
 TEST_F(ProxyPolicyHandlerTest, NoProxyModeName) {
   PolicyMap policy;
-  policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(ProxyPrefs::kDirectProxyModeName),
+  policy.Set(key::kProxyMode,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue(ProxyPrefs::kDirectProxyModeName),
              NULL);
   UpdateProviderPolicy(policy);
   VerifyProxyPrefs(
@@ -162,9 +174,10 @@
 
 TEST_F(ProxyPolicyHandlerTest, AutoDetectProxyModeName) {
   PolicyMap policy;
-  policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(
-                 ProxyPrefs::kAutoDetectProxyModeName),
+  policy.Set(key::kProxyMode,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue(ProxyPrefs::kAutoDetectProxyModeName),
              NULL);
   UpdateProviderPolicy(policy);
   VerifyProxyPrefs(std::string(),
@@ -175,12 +188,15 @@
 
 TEST_F(ProxyPolicyHandlerTest, PacScriptProxyMode) {
   PolicyMap policy;
-  policy.Set(key::kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("http://short.org/proxy.pac"),
+  policy.Set(key::kProxyPacUrl,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("http://short.org/proxy.pac"),
              NULL);
-  policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(
-                 ProxyPrefs::kPacScriptProxyModeName),
+  policy.Set(key::kProxyMode,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue(ProxyPrefs::kPacScriptProxyModeName),
              NULL);
   UpdateProviderPolicy(policy);
   VerifyProxyPrefs(std::string(),
@@ -191,9 +207,10 @@
 
 TEST_F(ProxyPolicyHandlerTest, PacScriptProxyModeInvalid) {
   PolicyMap policy;
-  policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(
-                 ProxyPrefs::kPacScriptProxyModeName),
+  policy.Set(key::kProxyMode,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue(ProxyPrefs::kPacScriptProxyModeName),
              NULL);
   UpdateProviderPolicy(policy);
   const base::Value* value = NULL;
@@ -207,16 +224,17 @@
   policy.Set(key::kProxyServer,
              POLICY_LEVEL_MANDATORY,
              POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(std::string()),
+             new base::StringValue(std::string()),
              NULL);
   policy.Set(key::kProxyPacUrl,
              POLICY_LEVEL_MANDATORY,
              POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("http://short.org/proxy.pac"),
+             new base::StringValue("http://short.org/proxy.pac"),
              NULL);
-  policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(
-                 ProxyPrefs::kPacScriptProxyModeName),
+  policy.Set(key::kProxyMode,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue(ProxyPrefs::kPacScriptProxyModeName),
              NULL);
   UpdateProviderPolicy(policy);
   VerifyProxyPrefs(std::string(),
@@ -238,8 +256,10 @@
 
 TEST_F(ProxyPolicyHandlerTest, UseSystemProxyMode) {
   PolicyMap policy;
-  policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(ProxyPrefs::kSystemProxyModeName),
+  policy.Set(key::kProxyMode,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue(ProxyPrefs::kSystemProxyModeName),
              NULL);
   UpdateProviderPolicy(policy);
   VerifyProxyPrefs(
@@ -253,9 +273,10 @@
              base::Value::CreateIntegerValue(
                  ProxyPolicyHandler::PROXY_SERVER_MODE),
              NULL);
-  policy.Set(key::kProxyMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue(
-                 ProxyPrefs::kAutoDetectProxyModeName),
+  policy.Set(key::kProxyMode,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue(ProxyPrefs::kAutoDetectProxyModeName),
              NULL);
   UpdateProviderPolicy(policy);
   VerifyProxyPrefs(std::string(),
@@ -267,14 +288,21 @@
 TEST_F(ProxyPolicyHandlerTest, ProxyInvalid) {
   // No mode expects all three parameters being set.
   PolicyMap policy;
-  policy.Set(key::kProxyPacUrl, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("http://short.org/proxy.pac"),
+  policy.Set(key::kProxyPacUrl,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("http://short.org/proxy.pac"),
              NULL);
-  policy.Set(key::kProxyBypassList, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("http://chromium.org/override"),
+  policy.Set(key::kProxyBypassList,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("http://chromium.org/override"),
              NULL);
-  policy.Set(key::kProxyServer, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
-             base::Value::CreateStringValue("chromium.org"), NULL);
+  policy.Set(key::kProxyServer,
+             POLICY_LEVEL_MANDATORY,
+             POLICY_SCOPE_USER,
+             new base::StringValue("chromium.org"),
+             NULL);
   for (int i = 0; i < ProxyPolicyHandler::MODE_COUNT; ++i) {
     policy.Set(key::kProxyServerMode, POLICY_LEVEL_MANDATORY,
                POLICY_SCOPE_USER, base::Value::CreateIntegerValue(i), NULL);
diff --git a/chrome/browser/net/spdyproxy/data_saving_metrics.cc b/chrome/browser/net/spdyproxy/data_saving_metrics.cc
index ee26d4d..ed4ff02 100644
--- a/chrome/browser/net/spdyproxy/data_saving_metrics.cc
+++ b/chrome/browser/net/spdyproxy/data_saving_metrics.cc
@@ -43,8 +43,7 @@
     DCHECK(rv);
   }
   value += length;
-  list_update->Set(index,
-                   base::Value::CreateStringValue(base::Int64ToString(value)));
+  list_update->Set(index, new base::StringValue(base::Int64ToString(value)));
 }
 
 int64 ListPrefInt64Value(const base::ListValue& list_update, size_t index) {
diff --git a/chrome/browser/net/ssl_config_service_manager_pref.cc b/chrome/browser/net/ssl_config_service_manager_pref.cc
index 0aab9a6..36bc2aa 100644
--- a/chrome/browser/net/ssl_config_service_manager_pref.cc
+++ b/chrome/browser/net/ssl_config_service_manager_pref.cc
@@ -176,7 +176,6 @@
   StringPrefMember ssl_version_max_;
   BooleanPrefMember channel_id_enabled_;
   BooleanPrefMember ssl_record_splitting_disabled_;
-  BooleanPrefMember unrestricted_ssl3_fallback_enabled_;
 
   // The cached list of disabled SSL cipher suites.
   std::vector<uint16> disabled_cipher_suites_;
@@ -210,10 +209,6 @@
       prefs::kEnableOriginBoundCerts, local_state, local_state_callback);
   ssl_record_splitting_disabled_.Init(
       prefs::kDisableSSLRecordSplitting, local_state, local_state_callback);
-  unrestricted_ssl3_fallback_enabled_.Init(
-      prefs::kEnableUnrestrictedSSL3Fallback,
-      local_state,
-      local_state_callback);
 
   local_state_change_registrar_.Init(local_state);
   local_state_change_registrar_.Add(
@@ -244,8 +239,6 @@
                                 default_config.channel_id_enabled);
   registry->RegisterBooleanPref(prefs::kDisableSSLRecordSplitting,
                                 !default_config.false_start_enabled);
-  registry->RegisterBooleanPref(prefs::kEnableUnrestrictedSSL3Fallback,
-      default_config.unrestricted_ssl3_fallback_enabled);
   registry->RegisterListPref(prefs::kCipherSuiteBlacklist);
 }
 
@@ -282,8 +275,8 @@
       rev_checking_required_local_anchors_.GetValue();
   std::string version_min_str = ssl_version_min_.GetValue();
   std::string version_max_str = ssl_version_max_.GetValue();
-  config->version_min = net::SSLConfigService::default_version_min();
-  config->version_max = net::SSLConfigService::default_version_max();
+  config->version_min = net::kDefaultSSLVersionMin;
+  config->version_max = net::kDefaultSSLVersionMax;
   uint16 version_min = SSLProtocolVersionFromString(version_min_str);
   uint16 version_max = SSLProtocolVersionFromString(version_max_str);
   if (version_min) {
@@ -304,8 +297,6 @@
   config->channel_id_enabled = channel_id_enabled_.GetValue();
   // disabling False Start also happens to disable record splitting.
   config->false_start_enabled = !ssl_record_splitting_disabled_.GetValue();
-  config->unrestricted_ssl3_fallback_enabled =
-      unrestricted_ssl3_fallback_enabled_.GetValue();
 }
 
 void SSLConfigServiceManagerPref::OnDisabledCipherSuitesChange(
diff --git a/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc
index 2cbfc05..8ffe95d 100644
--- a/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc
+++ b/chrome/browser/net/ssl_config_service_manager_pref_unittest.cc
@@ -91,8 +91,8 @@
   EXPECT_TRUE(old_config.disabled_cipher_suites.empty());
 
   base::ListValue* list_value = new base::ListValue();
-  list_value->Append(base::Value::CreateStringValue("0x0004"));
-  list_value->Append(base::Value::CreateStringValue("0x0005"));
+  list_value->Append(new base::StringValue("0x0004"));
+  list_value->Append(new base::StringValue("0x0005"));
   local_state.SetUserPref(prefs::kCipherSuiteBlacklist, list_value);
 
   // Pump the message loop to notify the SSLConfigServiceManagerPref that the
@@ -126,11 +126,10 @@
   EXPECT_TRUE(old_config.disabled_cipher_suites.empty());
 
   base::ListValue* list_value = new base::ListValue();
-  list_value->Append(base::Value::CreateStringValue("0x0004"));
-  list_value->Append(
-      base::Value::CreateStringValue("TLS_NOT_WITH_A_CIPHER_SUITE"));
-  list_value->Append(base::Value::CreateStringValue("0x0005"));
-  list_value->Append(base::Value::CreateStringValue("0xBEEFY"));
+  list_value->Append(new base::StringValue("0x0004"));
+  list_value->Append(new base::StringValue("TLS_NOT_WITH_A_CIPHER_SUITE"));
+  list_value->Append(new base::StringValue("0x0005"));
+  list_value->Append(new base::StringValue("0xBEEFY"));
   local_state.SetUserPref(prefs::kCipherSuiteBlacklist, list_value);
 
   // Pump the message loop to notify the SSLConfigServiceManagerPref that the
@@ -146,11 +145,8 @@
   EXPECT_EQ(0x0005, config.disabled_cipher_suites[1]);
 }
 
-// Test that
-// * without command-line settings for minimum and maximum SSL versions,
-//   SSL 3.0 ~ default_version_max() are enabled;
-// * without --enable-unrestricted-ssl3-fallback,
-//   |unrestricted_ssl3_fallback_enabled| is false.
+// Test that without command-line settings for minimum and maximum SSL versions,
+// SSL 3.0 ~ kDefaultSSLVersionMax are enabled.
 TEST_F(SSLConfigServiceManagerPrefTest, NoCommandLinePrefs) {
   scoped_refptr<TestingPrefStore> local_state_store(new TestingPrefStore());
 
@@ -170,17 +166,13 @@
   SSLConfig ssl_config;
   config_service->GetSSLConfig(&ssl_config);
   // The default value in the absence of command-line options is that
-  // SSL 3.0 ~ default_version_max() are enabled.
+  // SSL 3.0 ~ kDefaultSSLVersionMax are enabled.
   EXPECT_EQ(net::SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_min);
-  EXPECT_EQ(net::SSLConfigService::default_version_max(),
-            ssl_config.version_max);
-  EXPECT_FALSE(ssl_config.unrestricted_ssl3_fallback_enabled);
+  EXPECT_EQ(net::kDefaultSSLVersionMax, ssl_config.version_max);
 
   // The settings should not be added to the local_state.
   EXPECT_FALSE(local_state->HasPrefPath(prefs::kSSLVersionMin));
   EXPECT_FALSE(local_state->HasPrefPath(prefs::kSSLVersionMax));
-  EXPECT_FALSE(local_state->HasPrefPath(
-      prefs::kEnableUnrestrictedSSL3Fallback));
 
   // Explicitly double-check the settings are not in the preference store.
   std::string version_min_str;
@@ -189,10 +181,6 @@
                                             &version_min_str));
   EXPECT_FALSE(local_state_store->GetString(prefs::kSSLVersionMax,
                                             &version_max_str));
-  bool unrestricted_ssl3_fallback_enabled;
-  EXPECT_FALSE(local_state_store->GetBoolean(
-      prefs::kEnableUnrestrictedSSL3Fallback,
-      &unrestricted_ssl3_fallback_enabled));
 }
 
 // Test that command-line settings for minimum and maximum SSL versions are
@@ -203,7 +191,6 @@
   CommandLine command_line(CommandLine::NO_PROGRAM);
   command_line.AppendSwitchASCII(switches::kSSLVersionMin, "tls1");
   command_line.AppendSwitchASCII(switches::kSSLVersionMax, "ssl3");
-  command_line.AppendSwitch(switches::kEnableUnrestrictedSSL3Fallback);
 
   PrefServiceMockFactory factory;
   factory.set_user_prefs(local_state_store);
@@ -224,7 +211,6 @@
   // Command-line flags should be respected.
   EXPECT_EQ(net::SSL_PROTOCOL_VERSION_TLS1, ssl_config.version_min);
   EXPECT_EQ(net::SSL_PROTOCOL_VERSION_SSL3, ssl_config.version_max);
-  EXPECT_TRUE(ssl_config.unrestricted_ssl3_fallback_enabled);
 
   // Explicitly double-check the settings are not in the preference store.
   const PrefService::Preference* version_min_pref =
@@ -235,18 +221,10 @@
       local_state->FindPreference(prefs::kSSLVersionMax);
   EXPECT_FALSE(version_max_pref->IsUserModifiable());
 
-  const PrefService::Preference* ssl3_fallback_pref =
-      local_state->FindPreference(prefs::kEnableUnrestrictedSSL3Fallback);
-  EXPECT_FALSE(ssl3_fallback_pref->IsUserModifiable());
-
   std::string version_min_str;
   std::string version_max_str;
   EXPECT_FALSE(local_state_store->GetString(prefs::kSSLVersionMin,
                                             &version_min_str));
   EXPECT_FALSE(local_state_store->GetString(prefs::kSSLVersionMax,
                                             &version_max_str));
-  bool unrestricted_ssl3_fallback_enabled;
-  EXPECT_FALSE(local_state_store->GetBoolean(
-      prefs::kEnableUnrestrictedSSL3Fallback,
-      &unrestricted_ssl3_fallback_enabled));
 }
diff --git a/chrome/browser/net/websocket_browsertest.cc b/chrome/browser/net/websocket_browsertest.cc
index 27bf3f9..58605de 100644
--- a/chrome/browser/net/websocket_browsertest.cc
+++ b/chrome/browser/net/websocket_browsertest.cc
@@ -60,15 +60,7 @@
   EXPECT_TRUE(EqualsASCII(result, "PASS"));
 }
 
-// Test that the browser can handle a WebSocket frame split into multiple SSL
-// records. This test is flaky on Linux; see http://crbug.com/176867.
-#if defined(OS_LINUX)
-#define MAYBE_SecureWebSocketSplitRecords DISABLED_SecureWebSocketSplitRecords
-#else
-#define MAYBE_SecureWebSocketSplitRecords SecureWebSocketSplitRecords
-#endif
-IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest,
-    MAYBE_SecureWebSocketSplitRecords) {
+IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, SecureWebSocketSplitRecords) {
   // Launch a secure WebSocket server.
   ASSERT_TRUE(wss_server_.Start());
 
diff --git a/chrome/browser/notifications/sync_notifier/OWNERS b/chrome/browser/notifications/sync_notifier/OWNERS
new file mode 100644
index 0000000..f11bada
--- /dev/null
+++ b/chrome/browser/notifications/sync_notifier/OWNERS
@@ -0,0 +1 @@
+petewil@chromium.org
\ No newline at end of file
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_unittest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_unittest.cc
index 07392f5..4200b51 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_delegate_unittest.cc
@@ -45,7 +45,7 @@
     // Set enough fields in sync_data, including specifics, for our tests
     // to pass.
     notifier::SyncedNotification* notification =
-        new notifier::SyncedNotification(sync_data);
+        new notifier::SyncedNotification(sync_data, this, NULL);
     // Retain ownership to avoid memory leaks in tests.
     owned_notifications_.push_back(notification);
     return notification;
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
index 4c296bb..f5f97ae 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.cc
@@ -24,6 +24,9 @@
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_delegate.h"
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_factory.h"
 #include "chrome/browser/notifications/sync_notifier/welcome_delegate.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/pref_names.h"
@@ -50,55 +53,6 @@
 const char kSyncedNotificationsWelcomeOrigin[] =
     "synced-notifications://welcome";
 
-// SyncedNotificationAppInfoTemp is a class that contains the information
-// necessary to produce a welcome notification and the app badges for all synced
-// notification.
-// TODO(dewittj): Convert this into a sync protobuf-backed data structure.
-class SyncedNotificationAppInfoTemp {
- public:
-  explicit SyncedNotificationAppInfoTemp(const std::string& app_id,
-                                         const base::string16& service_name);
-  ~SyncedNotificationAppInfoTemp();
-
-  const std::string& app_id() const { return app_id_; }
-  const base::string16& service_name() const { return service_name_; }
-  const base::string16& title() const { return title_; }
-
-  void set_icon(const gfx::Image& icon) { icon_ = icon; }
-  const gfx::Image& icon() const { return icon_; }
-
-  void set_small_icon(const gfx::Image& small_icon) {
-    small_icon_ = small_icon;
-  }
-  const gfx::Image& small_icon() const { return small_icon_; }
-
-  const message_center::NotifierId GetNotifierId() const;
-
- private:
-  std::string app_id_;
-  base::string16 service_name_;
-  gfx::Image icon_;
-  gfx::Image small_icon_;
-  base::string16 title_;
-  base::string16 message_;
-};
-
-SyncedNotificationAppInfoTemp::SyncedNotificationAppInfoTemp(
-    const std::string& app_id,
-    const base::string16& service_name)
-    : app_id_(app_id), service_name_(service_name) {
-  title_ =
-      l10n_util::GetStringFUTF16(IDS_NOTIFIER_WELCOME_TITLE, service_name_);
-}
-
-SyncedNotificationAppInfoTemp::~SyncedNotificationAppInfoTemp() {}
-
-const message_center::NotifierId SyncedNotificationAppInfoTemp::GetNotifierId()
-    const {
-  return message_center::NotifierId(
-      message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE, app_id());
-}
-
 bool ChromeNotifierService::avoid_bitmap_fetching_for_test_ = false;
 
 ChromeNotifierService::ChromeNotifierService(Profile* profile,
@@ -106,19 +60,24 @@
     : profile_(profile),
       notification_manager_(manager),
       synced_notification_first_run_(false) {
-  SyncedNotificationAppInfoTemp* temp_app_info =
-      new SyncedNotificationAppInfoTemp(
-      kFirstSyncedNotificationServiceId,
-      l10n_util::GetStringUTF16(IDS_FIRST_SYNCED_NOTIFICATION_SERVICE_NAME));
-  temp_app_info->set_small_icon(
-      ui::ResourceBundle::GetSharedInstance().GetImageNamed(
-          IDR_TEMPORARY_GOOGLE_PLUS_ICON));
-  app_info_data_.push_back(temp_app_info);
 
   InitializePrefs();
+
+  // Get a pointer to the app info service so we can get app info data.
+  synced_notification_app_info_service_ =
+      SyncedNotificationAppInfoServiceFactory::GetForProfile(
+          profile_, Profile::IMPLICIT_ACCESS);
+
+  DCHECK(synced_notification_app_info_service_ != NULL);
+
+  synced_notification_app_info_service_->set_chrome_notifier_service(this);
+
 }
 
-ChromeNotifierService::~ChromeNotifierService() {}
+ChromeNotifierService::~ChromeNotifierService() {
+  if (synced_notification_app_info_service_)
+    synced_notification_app_info_service_->set_chrome_notifier_service(NULL);
+}
 
 // Methods from KeyedService.
 void ChromeNotifierService::Shutdown() {}
@@ -148,9 +107,7 @@
     scoped_ptr<SyncedNotification> incoming(CreateNotificationFromSyncData(
         sync_data));
     if (!incoming) {
-      // TODO(petewil): Turn this into a NOTREACHED() call once we fix the
-      // underlying problem causing bad data.
-      LOG(WARNING) << "Badly formed sync data in incoming notification";
+      NOTREACHED();
       continue;
     }
 
@@ -311,7 +268,7 @@
       notification.GetEntitySpecifics());
 }
 
-// Static Method.  Convert from SyncData to our internal format.
+// Convert from SyncData to our internal format.
 scoped_ptr<SyncedNotification>
 ChromeNotifierService::CreateNotificationFromSyncData(
     const syncer::SyncData& sync_data) {
@@ -362,7 +319,7 @@
 
   // Create a new notification object based on the supplied sync_data.
   scoped_ptr<SyncedNotification> notification(
-      new SyncedNotification(sync_data));
+      new SyncedNotification(sync_data, this, notification_manager_));
 
   return notification.Pass();
 }
@@ -401,30 +358,84 @@
     std::vector<message_center::Notifier*>* notifiers) {
   // TODO(mukai|petewil): Check the profile's eligibility before adding the
   // sample app.
-  ScopedVector<SyncedNotificationAppInfoTemp>::iterator it =
-      app_info_data_.begin();
-  for (; it != app_info_data_.end(); ++it) {
-    SyncedNotificationAppInfoTemp* app_info = *it;
-    message_center::NotifierId notifier_id = app_info->GetNotifierId();
+  std::vector<SyncedNotificationSendingServiceSettingsData>
+      sending_service_settings_data;
 
-    // Enable or disable the sending service per saved settings.
+  if (synced_notification_app_info_service_ == NULL)
+    return;
+
+  sending_service_settings_data =
+      synced_notification_app_info_service_->GetAllSendingServiceSettingsData();
+
+  for (size_t ii = 0; ii < sending_service_settings_data.size(); ++ii) {
+
+    // Enable or disable the sending service per saved preferences.
     bool app_enabled = false;
     std::set<std::string>::iterator iter;
     iter = find(enabled_sending_services_.begin(),
                 enabled_sending_services_.end(),
-                notifier_id.id);
+                sending_service_settings_data[ii].notifier_id.id);
     app_enabled = iter != enabled_sending_services_.end();
 
     message_center::Notifier* app_info_notifier = new message_center::Notifier(
-        notifier_id, app_info->service_name(), app_enabled);
+        sending_service_settings_data[ii].notifier_id,
+        base::UTF8ToUTF16(
+            sending_service_settings_data[ii].settings_display_name),
+        app_enabled);
 
-    app_info_notifier->icon = app_info->small_icon();
+    app_info_notifier->icon = sending_service_settings_data[ii].settings_icon;
 
     // |notifiers| takes ownership of |app_info_notifier|.
     notifiers->push_back(app_info_notifier);
   }
 }
 
+void ChromeNotifierService::OnAddedAppIds(
+    std::vector<std::string> added_app_ids) {
+
+  std::vector<std::string>::const_iterator app_id_iter;
+  for (app_id_iter = added_app_ids.begin(); app_id_iter != added_app_ids.end();
+       ++app_id_iter) {
+    // Make sure this is not a dup, if it is, do nothing.
+    // TODO(petewil): consider a case insensitive compare.
+    std::set<std::string>::iterator sending_service_iter;
+    sending_service_iter = enabled_sending_services_.find(*app_id_iter);
+    if (sending_service_iter != enabled_sending_services_.end())
+      continue;
+
+    // Find any newly enabled notifications and call display on them.
+    // Show the welcome toast if required.
+    ScopedVector<SyncedNotification>::iterator notification_iter;
+    for (notification_iter = notification_data_.begin();
+         notification_iter != notification_data_.end();
+         ++notification_iter) {
+      (*notification_iter)->ShowAllForAppId(profile_, *app_id_iter);
+    }
+  }
+}
+
+void ChromeNotifierService::OnRemovedAppIds(
+    std::vector<std::string> removed_app_ids) {
+  // Remove from enabled sending services.
+  // Don't remove from initialized sending services. If it gets re-added later,
+  // we want to remember the user's decision, so we also leave prefs intact.
+
+  // Find any displayed notifications and remove them from the notification
+  // center.
+  std::vector<std::string>::const_iterator app_id_iter;
+  for (app_id_iter = removed_app_ids.begin();
+       app_id_iter != removed_app_ids.end();
+       ++app_id_iter) {
+    // Find any newly disabled notifications and remove them.
+    ScopedVector<SyncedNotification>::iterator notification_iter;
+    for (notification_iter = notification_data_.begin();
+         notification_iter != notification_data_.end();
+         ++notification_iter) {
+      (*notification_iter)->HideAllForAppId(*app_id_iter);
+    }
+  }
+}
+
 void ChromeNotifierService::MarkNotificationAsRead(
     const std::string& key) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -452,14 +463,14 @@
   notification_data_.push_back(notification.release());
 
   // If the user is not interested in this type of notification, ignore it.
-  std::set<std::string>::iterator iter =
-      find(enabled_sending_services_.begin(),
-           enabled_sending_services_.end(),
-           notification_copy->GetSendingServiceId());
+  std::string sending_service_id = GetSendingServiceId(notification_copy);
+  std::set<std::string>::iterator iter = find(enabled_sending_services_.begin(),
+                                              enabled_sending_services_.end(),
+                                              sending_service_id);
   if (iter == enabled_sending_services_.end()) {
     iter = find(initialized_sending_services_.begin(),
                 initialized_sending_services_.end(),
-                notification_copy->GetSendingServiceId());
+                sending_service_id);
     if (iter != initialized_sending_services_.end())
       return;
   }
@@ -467,11 +478,33 @@
   UpdateInMessageCenter(notification_copy);
 }
 
+std::string ChromeNotifierService::GetSendingServiceId(
+    const SyncedNotification* synced_notification) {
+  // Get the App Id from the notification, and look it up in the synced
+  // notification app info service.
+  std::string app_id = synced_notification->GetAppId();
+
+  DCHECK(synced_notification_app_info_service_ != NULL);
+
+  return synced_notification_app_info_service_->FindSendingServiceNameFromAppId(
+      app_id);
+}
+
 void ChromeNotifierService::AddForTest(
     scoped_ptr<notifier::SyncedNotification> notification) {
   notification_data_.push_back(notification.release());
 }
 
+void ChromeNotifierService::SetSyncedNotificationAppInfoServiceForTest(
+    SyncedNotificationAppInfoService* synced_notification_app_info_service) {
+  // If there already is a service attached, clear their reference to us.
+  if (synced_notification_app_info_service_)
+    synced_notification_app_info_service_->set_chrome_notifier_service(NULL);
+
+  synced_notification_app_info_service_ = synced_notification_app_info_service;
+  synced_notification_app_info_service_->set_chrome_notifier_service(this);
+}
+
 void ChromeNotifierService::UpdateInMessageCenter(
     SyncedNotification* notification) {
   // If the feature is disabled, exit now.
@@ -497,17 +530,17 @@
   // center.
   if (synced_notification_first_run_) {
     // Setting the toast state to false will prevent toasting the notification.
-    notification->SetToastState(false);
+    notification->set_toast_state(false);
   }
 
   // Our tests cannot use the network for reliability reasons.
   if (avoid_bitmap_fetching_for_test_) {
-    notification->Show(notification_manager_, this, profile_);
+    notification->Show(profile_);
     return;
   }
 
   // Set up to fetch the bitmaps.
-  notification->QueueBitmapFetchJobs(notification_manager_, this, profile_);
+  notification->QueueBitmapFetchJobs(this, profile_);
 
   // Start the bitmap fetching, Show() will be called when the last bitmap
   // either arrives or times out.
@@ -608,7 +641,7 @@
           notification_data_.begin();
        iter != notification_data_.end();
        ++iter) {
-    if ((*iter)->GetSendingServiceId() == notifier_id &&
+    if (GetSendingServiceId(*iter) == notifier_id &&
         (*iter)->GetReadState() == SyncedNotification::kUnread)
       Display(*iter);
   }
@@ -620,7 +653,7 @@
           notification_data_.begin();
        iter != notification_data_.end();
        ++iter) {
-    if ((*iter)->GetSendingServiceId() == notifier_id &&
+    if (GetSendingServiceId(*iter) == notifier_id &&
         (*iter)->GetReadState() == SyncedNotification::kUnread) {
       notification_manager_->CancelById((*iter)->GetKey());
     }
@@ -716,7 +749,7 @@
     const SyncedNotification* synced_notification,
     NotificationUIManager* notification_ui_manager) {
   const std::string& sending_service_id =
-      synced_notification->GetSendingServiceId();
+      GetSendingServiceId(synced_notification);
 
   std::set<std::string>::iterator iter;
   iter = find(initialized_sending_services_.begin(),
@@ -728,20 +761,17 @@
   if (iter != initialized_sending_services_.end())
     return;
 
-  // If there is no app info, we can't show a welcome toast.  Ideally all synced
+  // If there is no app info, we can't show a welcome toast.  All synced
   // notifications will be delayed until an app_info data structure can be
   // constructed for them.
-  // TODO(dewittj): Refactor when app_info is populated asynchronously.
-  SyncedNotificationAppInfoTemp* app_info = FindAppInfo(sending_service_id);
+  notifier::SyncedNotificationAppInfo* app_info =
+      FindAppInfoByAppId(synced_notification->GetAppId());
   if (!app_info)
     return;
 
-  // TODO(dewittj): Ensure that the app info icon is set before this point.
-  if (app_info->icon().IsEmpty()) {
+  if (app_info->settings_icon_url().is_empty()) {
     gfx::Image notification_app_icon = synced_notification->GetAppIcon();
-    if (!notification_app_icon.IsEmpty()) {
-      app_info->set_icon(notification_app_icon);
-    } else {
+    if (notification_app_icon.IsEmpty()) {
       // This block should only be reached in tests since the downloads are
       // already finished for |synced_notification|.
       DVLOG(1) << "Unable to find the app icon for the welcome notification. "
@@ -776,25 +806,21 @@
       initialized_sending_services);
 }
 
-SyncedNotificationAppInfoTemp* ChromeNotifierService::FindAppInfo(
+notifier::SyncedNotificationAppInfo* ChromeNotifierService::FindAppInfoByAppId(
     const std::string& app_id) const {
-  ScopedVector<SyncedNotificationAppInfoTemp>::const_iterator iter =
-      app_info_data_.begin();
-  while (iter != app_info_data_.end()) {
-    if ((*iter)->app_id() == app_id)
-      return (*iter);
+  if (NULL == synced_notification_app_info_service_)
+    return NULL;
 
-    ++iter;
-  }
-
-  return NULL;
+  return synced_notification_app_info_service_->
+      FindSyncedNotificationAppInfoByAppId(app_id);
 }
 
 const Notification ChromeNotifierService::CreateWelcomeNotificationForService(
-    SyncedNotificationAppInfoTemp* app_info) {
+    SyncedNotificationAppInfo* app_info) {
   std::string welcome_notification_id = base::GenerateGUID();
-  scoped_refptr<WelcomeDelegate> delegate(new WelcomeDelegate(
-      welcome_notification_id, profile_, app_info->GetNotifierId()));
+  message_center::NotifierId notifier_id = app_info->GetNotifierId();
+  scoped_refptr<WelcomeDelegate> delegate(
+      new WelcomeDelegate(welcome_notification_id, profile_, notifier_id));
 
   message_center::ButtonInfo button_info(
       l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BUTTON));
@@ -806,11 +832,11 @@
   return Notification(
       message_center::NOTIFICATION_TYPE_BASE_FORMAT,
       GURL(kSyncedNotificationsWelcomeOrigin),
-      app_info->title(),
+      base::UTF8ToUTF16(app_info->settings_display_name()),
       l10n_util::GetStringUTF16(IDS_NOTIFIER_WELCOME_BODY),
       app_info->icon(),
       blink::WebTextDirectionDefault,
-      app_info->GetNotifierId(),
+      notifier_id,
       l10n_util::GetStringUTF16(IDS_NOTIFICATION_WELCOME_DISPLAY_SOURCE),
       base::UTF8ToUTF16(welcome_notification_id),
       rich_notification_data,
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
index f1c1c43..f54ed11 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service.h
@@ -30,12 +30,12 @@
 }
 
 namespace notifier {
-class SyncedNotificationAppInfoTemp;
+class SyncedNotificationAppInfo;
+class SyncedNotificationAppInfoService;
 
 // The name of our first synced notification service.
-// TODO(petewil): remove this hardcoding once we have the synced notification
-// signalling sync data type set up to provide this.
-// crbug.com/248337
+// TODO(petewil): Remove this once we figure out how to do UMA for each sending
+// service name without knowing the name in advance.
 extern const char kFirstSyncedNotificationServiceId[];
 extern const char kServiceEnabledOnce[];
 extern const char kSyncedNotificationFirstRun[];
@@ -81,7 +81,7 @@
       const SyncedNotification& notification);
 
   // Convert from SyncData representation to internal representation.
-  static scoped_ptr<SyncedNotification> CreateNotificationFromSyncData(
+  scoped_ptr<SyncedNotification> CreateNotificationFromSyncData(
       const syncer::SyncData& sync_data);
 
   // Get a pointer to a notification.  ChromeNotifierService owns this pointer.
@@ -102,14 +102,25 @@
       const std::string& notifier_id,
       bool enabled);
 
+  // When app ids are added or removed, unblock or remove associated messages.
+  void OnAddedAppIds(std::vector<std::string> added_app_ids);
+  void OnRemovedAppIds(std::vector<std::string> removed_app_ids);
+
   // Register the preferences we use to save state.
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
   Profile* profile() const { return profile_; }
 
+  // Find and retun the sending service Id for this notification.
+  std::string GetSendingServiceId(
+      const SyncedNotification* synced_notification);
+
   // Functions for test.
   void AddForTest(scoped_ptr<notifier::SyncedNotification> notification);
 
+  void SetSyncedNotificationAppInfoServiceForTest(
+      SyncedNotificationAppInfoService* synced_notification_app_info_service);
+
   // If we allow the tests to do bitmap fetching, they will attempt to fetch
   // a URL from the web, which will fail.  We can already test the majority
   // of what we want without also trying to fetch bitmaps.  Other tests will
@@ -166,10 +177,13 @@
   void BuildServiceListValueInplace(
       std::set<std::string> services, base::ListValue* list_value);
 
-  SyncedNotificationAppInfoTemp* FindAppInfo(const std::string& app_id) const;
+  // Finds an app info by using the AppId
+  notifier::SyncedNotificationAppInfo* FindAppInfoByAppId(
+      const std::string& app_id) const;
 
+  // Builds a welcome notification for the listed sending service.
   const Notification CreateWelcomeNotificationForService(
-      SyncedNotificationAppInfoTemp* app_info);
+      SyncedNotificationAppInfo* app_info);
 
   // Preferences for storing which SyncedNotificationServices are enabled
   StringListPrefMember enabled_sending_services_prefs_;
@@ -187,8 +201,11 @@
   bool synced_notification_first_run_;
   static bool avoid_bitmap_fetching_for_test_;
   base::ThreadChecker thread_checker_;
+  // Unowned pointer to the App Info service.  The lifetime is managed by the
+  // profile service, this service depends on the App Info service, so it should
+  // always be in scope whenever our service is active.
+  SyncedNotificationAppInfoService* synced_notification_app_info_service_;
 
-  ScopedVector<SyncedNotificationAppInfoTemp> app_info_data_;
   // TODO(petewil): Consider whether a map would better suit our data.
   // If there are many entries, lookup time may trump locality of reference.
   ScopedVector<SyncedNotification> notification_data_;
@@ -202,6 +219,8 @@
   FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest,
                            GetEnabledSendingServicesFromPreferencesTest);
   FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, CheckFindAppInfo);
+  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, SetAddedAppIdsTest);
+  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, SetRemovedAppIdsTest);
 
   DISALLOW_COPY_AND_ASSIGN(ChromeNotifierService);
 };
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc
index a33a7d0..80411c3 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_factory.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -45,8 +46,13 @@
 
 ChromeNotifierServiceFactory::ChromeNotifierServiceFactory()
     : BrowserContextKeyedServiceFactory(
-        "ChromeNotifierService",
-        BrowserContextDependencyManager::GetInstance()) {}
+          "ChromeNotifierService",
+          BrowserContextDependencyManager::GetInstance()) {
+  // Mark this service as depending on the SyncedNotificationAppInfoService.
+  // Marking it provides a guarantee that the other service will alwasys be
+  // running whenever the ChromeNotifierServiceFactory is.
+  DependsOn(SyncedNotificationAppInfoServiceFactory::GetInstance());
+}
 
 ChromeNotifierServiceFactory::~ChromeNotifierServiceFactory() {
 }
diff --git a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
index 06650ae..bc237bd 100644
--- a/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc
@@ -16,6 +16,9 @@
 #include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
 #include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
 #include "chrome/browser/notifications/sync_notifier/synced_notification.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_factory.h"
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_switches.h"
@@ -124,6 +127,9 @@
 
     // Set up a profile for the unit tests to use.
     profile_.reset(new TestingProfile());
+
+    // Set up the testing SyncedNotificationAppInfoService with some test data.
+    AddTestingAppInfos();
   }
 
   virtual void TearDown() {
@@ -154,7 +160,7 @@
                                         app_id, key, read_state);
     // Set enough fields in sync_data, including specifics, for our tests
     // to pass.
-    return new SyncedNotification(sync_data);
+    return new SyncedNotification(sync_data, NULL, notification_manager_.get());
   }
 
   // Helper to create syncer::SyncChange.
@@ -170,6 +176,30 @@
         ChromeNotifierService::CreateSyncDataFromNotification(*notification));
   }
 
+  void AddTestingAppInfos() {
+    // Get the SyncedNotificationAppInfoService from the browser object.
+    SyncedNotificationAppInfoService* synced_notification_app_info_service =
+        SyncedNotificationAppInfoServiceFactory::GetForProfile(
+            profile_.get(), Profile::EXPLICIT_ACCESS);
+
+    // Create a notification to add.
+    // The sending_service_infos_ list will take ownership of this pointer.
+    scoped_ptr<SyncedNotificationAppInfo> test_service1(
+        new SyncedNotificationAppInfo(profile_.get(),
+                                      std::string(kSendingService1Name),
+                                      synced_notification_app_info_service));
+
+    // Add some App IDs.
+    test_service1->AddAppId(kAppId1);
+    test_service1->AddAppId(kAppId2);
+
+    // Set this icon's GURLs.
+    test_service1->SetSettingsURLs(GURL(kTestIconUrl), GURL());
+
+    // Call AddForTest.
+    synced_notification_app_info_service->AddForTest(test_service1.Pass());
+  }
+
  protected:
   scoped_ptr<TestingProfile> profile_;
 
@@ -182,18 +212,17 @@
   DISALLOW_COPY_AND_ASSIGN(ChromeNotifierServiceTest);
 };
 
-// TODO(petewil): Add more tests as I add functionalty.  Tests are based on
-// chrome/browser/extensions/app_notification_manager_sync_unittest.cc
-
 // Create a Notification, convert it to SyncData and convert it back.
 TEST_F(ChromeNotifierServiceTest, NotificationToSyncDataToNotification) {
+  ChromeNotifierService notifier(profile_.get(), notification_manager());
+
   scoped_ptr<SyncedNotification> notification1(
       CreateNotification(kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1,
                          kKey1, kUnread));
   SyncData sync_data =
       ChromeNotifierService::CreateSyncDataFromNotification(*notification1);
   scoped_ptr<SyncedNotification> notification2(
-      ChromeNotifierService::CreateNotificationFromSyncData(sync_data));
+      notifier.CreateNotificationFromSyncData(sync_data));
   EXPECT_TRUE(notification2.get());
   EXPECT_TRUE(notification1->EqualsIgnoringReadState(*notification2));
   EXPECT_EQ(notification1->GetReadState(), notification2->GetReadState());
@@ -394,7 +423,7 @@
   for (SyncDataList::const_iterator iter = initial_data.begin();
       iter != initial_data.end(); ++iter) {
     scoped_ptr<SyncedNotification> notification1(
-        ChromeNotifierService::CreateNotificationFromSyncData(*iter));
+        notifier.CreateNotificationFromSyncData(*iter));
     // TODO(petewil): Revisit this when we add version info to notifications.
     const std::string& key = notification1->GetKey();
     const SyncedNotification* notification2 =
@@ -532,8 +561,7 @@
 TEST_F(ChromeNotifierServiceTest, ServiceEnabledTest) {
   ChromeNotifierService notifier(profile_.get(), notification_manager());
   std::set<std::string>::iterator iter;
-  std::string first_synced_notification_service_id(
-      kFirstSyncedNotificationServiceId);
+  std::string first_synced_notification_service_id(kSendingService1Name);
 
   // Create some local fake data.
   scoped_ptr<SyncedNotification> n1(CreateNotification(
@@ -542,24 +570,23 @@
 
   // Enable the service and ensure the service is in the list.
   // Initially the service starts in the disabled state.
-  notifier.OnSyncedNotificationServiceEnabled(kFirstSyncedNotificationServiceId,
-                                              true);
+  notifier.OnSyncedNotificationServiceEnabled(kSendingService1Name, true);
   iter = find(notifier.enabled_sending_services_.begin(),
               notifier.enabled_sending_services_.end(),
               first_synced_notification_service_id);
-  EXPECT_NE(notifier.enabled_sending_services_.end(), iter);
-  // TODO(petewil): Verify Display gets called too.
 
+  EXPECT_NE(notifier.enabled_sending_services_.end(), iter);
+
+  // TODO(petewil): Verify Display gets called too.
   // Disable the service and ensure it is gone from the list and the
   // notification_manager.
-  notifier.OnSyncedNotificationServiceEnabled(kFirstSyncedNotificationServiceId,
-                                              false);
+  notifier.OnSyncedNotificationServiceEnabled(kSendingService1Name, false);
   iter = find(notifier.enabled_sending_services_.begin(),
               notifier.enabled_sending_services_.end(),
               first_synced_notification_service_id);
+
   EXPECT_EQ(notifier.enabled_sending_services_.end(), iter);
   EXPECT_EQ(notification_manager()->dismissed_id(), std::string(kKey1));
-
 }
 
 // http://crbug.com/341326
@@ -586,7 +613,7 @@
                                           kText1,
                                           kIconUrl1,
                                           kImageUrl1,
-                                          kFirstSyncedNotificationServiceId,
+                                          kAppId1,
                                           kKey1,
                                           kUnread)));
 
@@ -596,7 +623,7 @@
 
   // Verify that the first synced notification service is enabled in memory.
   std::set<std::string>::iterator iter;
-  std::string first_notification_service_id(kFirstSyncedNotificationServiceId);
+  std::string first_notification_service_id(kSendingService1Name);
   iter = find(notifier.enabled_sending_services_.begin(),
               notifier.enabled_sending_services_.end(),
               first_notification_service_id);
@@ -614,7 +641,7 @@
                                           kText2,
                                           kIconUrl2,
                                           kImageUrl2,
-                                          kFirstSyncedNotificationServiceId,
+                                          kAppId1,
                                           kKey2,
                                           kUnread)));
   notifier.ProcessSyncChanges(FROM_HERE, changes);
@@ -630,8 +657,7 @@
   notifier.set_avoid_bitmap_fetching_for_test(true);
 
   // Initialize but do not enable the sending service.
-  notifier.initialized_sending_services_.insert(
-      kFirstSyncedNotificationServiceId);
+  notifier.initialized_sending_services_.insert(kSendingService1Name);
   ASSERT_EQ(0U, notifier.enabled_sending_services_.size());
   ASSERT_EQ(1U, notifier.initialized_sending_services_.size());
 
@@ -640,8 +666,7 @@
   EXPECT_EQ(0U, notifier.GetAllSyncData(SYNCED_NOTIFICATIONS).size());
 
   // Set up an ADD.
-  std::string first_synced_notification_service_id(
-      kFirstSyncedNotificationServiceId);
+  std::string first_synced_notification_service_id(kSendingService1Name);
 
   SyncChangeList changes;
   changes.push_back(
@@ -650,7 +675,7 @@
                                           kText1,
                                           kIconUrl1,
                                           kImageUrl1,
-                                          kFirstSyncedNotificationServiceId,
+                                          kAppId1,
                                           kKey1,
                                           kUnread)));
 
@@ -663,13 +688,49 @@
   EXPECT_EQ(0U, notification_manager()->added_notifications());
 }
 
-TEST_F(ChromeNotifierServiceTest, CheckFindAppInfo) {
+TEST_F(ChromeNotifierServiceTest, SetAddedAppIdsTest) {
   ChromeNotifierService notifier(profile_.get(), notification_manager());
   notifier.set_avoid_bitmap_fetching_for_test(true);
 
-  SyncedNotificationAppInfoTemp* app_info =
-      notifier.FindAppInfo(kFirstSyncedNotificationServiceId);
-  EXPECT_TRUE(app_info != NULL);
+  // Add some notifications to our notification list.
+  scoped_ptr<SyncedNotification> n1(CreateNotification(
+      kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
+  n1->SetNotifierServiceForTest(&notifier);
+  notifier.AddForTest(n1.Pass());
+
+  EXPECT_EQ(static_cast<size_t>(0),
+            notification_manager()->added_notifications());
+
+  // Call SetAddedAppIds.
+  std::vector<std::string> added_app_ids;
+  added_app_ids.push_back(std::string(kAppId1));
+  notifier.OnAddedAppIds(added_app_ids);
+
+  // Verify the notification was added by the notification_manager.
+  // We see one welcome notification and one new notification.
+  EXPECT_EQ(static_cast<size_t>(2),
+            notification_manager()->added_notifications());
 }
 
+TEST_F(ChromeNotifierServiceTest, SetRemovedAppIdsTest) {
+  ChromeNotifierService notifier(profile_.get(), notification_manager());
+  notifier.set_avoid_bitmap_fetching_for_test(true);
+
+  // Add some notifications to our notification list.
+  scoped_ptr<SyncedNotification> n1(CreateNotification(
+      kTitle1, kText1, kIconUrl1, kImageUrl1, kAppId1, kKey1, kUnread));
+  notifier.AddForTest(n1.Pass());
+
+  // Call SetRemovedAppIds.
+  std::vector<std::string> removed_app_ids;
+  removed_app_ids.push_back(std::string(kAppId1));
+  notifier.OnRemovedAppIds(removed_app_ids);
+
+  // Verify the notification was "removed" in the notification manager.
+  EXPECT_EQ(std::string(kKey1), notification_manager()->dismissed_id());
+}
+
+// TODO(petewil): Add a test that we do *not* get a welcome dialog unless we
+// have a valid app info for the notification.
+
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/image_holder.cc b/chrome/browser/notifications/sync_notifier/image_holder.cc
new file mode 100644
index 0000000..7e82aa1
--- /dev/null
+++ b/chrome/browser/notifications/sync_notifier/image_holder.cc
@@ -0,0 +1,93 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This class holds the URL to an image and the bitmap for the fetched image,
+// and has code to fetch the bitmap from the URL.
+
+#include "chrome/browser/notifications/sync_notifier/image_holder.h"
+
+namespace notifier {
+
+ImageHolder::ImageHolder(const GURL& low_dpi_url,
+                         const GURL& high_dpi_url,
+                         Profile* profile,
+                         ImageHolderDelegate* delegate)
+    : low_dpi_url_(low_dpi_url),
+      high_dpi_url_(high_dpi_url),
+      low_dpi_fetched_(false),
+      high_dpi_fetched_(false),
+      delegate_(delegate),
+      profile_(profile) {
+
+  // If a URL is invalid, clear it so we don't try to fetch it.
+  if (!low_dpi_url_.is_valid()) {
+    low_dpi_url_ = GURL();
+  }
+  if (!high_dpi_url_.is_valid()) {
+    high_dpi_url_ = GURL();
+  }
+
+  // Create a featcher for each URL that is set.
+  if (!low_dpi_url_.is_empty()) {
+    CreateBitmapFetcher(low_dpi_url_);
+  }
+  if (!high_dpi_url_.is_empty()) {
+    CreateBitmapFetcher(high_dpi_url_);
+  }
+}
+
+ImageHolder::~ImageHolder() {}
+
+// This will let us know if we have tried to fetch once and the try completed.
+// Currently there is no logic for retries.
+bool ImageHolder::IsFetchingDone() const {
+  return ((low_dpi_url_.is_empty() || low_dpi_fetched_) &&
+           (high_dpi_url_.is_empty() || high_dpi_fetched_));
+}
+
+// If this bitmap has a valid GURL, create a fetcher for it.
+void ImageHolder::CreateBitmapFetcher(const GURL& url) {
+  // Check for dups, ignore any request for a dup.
+  ScopedVector<chrome::BitmapFetcher>::iterator iter;
+  for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
+    if ((*iter)->url() == url)
+      return;
+  }
+
+  if (url.is_valid()) {
+    fetchers_.push_back(new chrome::BitmapFetcher(url, this));
+    DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url;
+  }
+}
+
+void ImageHolder::StartFetch() {
+  // Now that we have queued them all, start the fetching.
+  ScopedVector<chrome::BitmapFetcher>::iterator iter;
+  for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
+    (*iter)->Start(profile_);
+  }
+}
+
+// Method inherited from BitmapFetcher delegate.
+void ImageHolder::OnFetchComplete(const GURL url, const SkBitmap* bitmap) {
+  // TODO(petewil): Should I retry if a fetch fails?
+  // Match the bitmap to the URL to put it into the image with the correct scale
+  // factor.
+  if (url == low_dpi_url_) {
+    low_dpi_fetched_ = true;
+    if (bitmap != NULL)
+      image_.AddRepresentation(gfx::ImageSkiaRep(*bitmap, 1.0));
+  } else if (url == high_dpi_url_) {
+    high_dpi_fetched_ = true;
+    if (bitmap != NULL)
+      image_.AddRepresentation(gfx::ImageSkiaRep(*bitmap, 2.0));
+  } else {
+    DVLOG(2) << __FUNCTION__ << "Unmatched bitmap arrived " << url;
+  }
+
+  // Notify callback of bitmap arrival.
+  delegate_->OnFetchComplete();
+}
+
+}  // namespace notifier.
diff --git a/chrome/browser/notifications/sync_notifier/image_holder.h b/chrome/browser/notifications/sync_notifier/image_holder.h
new file mode 100644
index 0000000..3d0c089
--- /dev/null
+++ b/chrome/browser/notifications/sync_notifier/image_holder.h
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_IMAGE_HOLDER_H_
+#define CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_IMAGE_HOLDER_H_
+
+#include "base/memory/scoped_vector.h"
+#include "chrome/browser/bitmap_fetcher.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
+#include "url/gurl.h"
+
+class Profile;
+
+namespace notifier {
+
+// This provides a callback so the ImageHolder can inform its parent when a
+// bitmap arrives.
+class ImageHolderDelegate {
+ public:
+  virtual void OnFetchComplete() = 0;
+};
+
+// This class encapsulates the action of fetching a bitmap, reporting when it is
+// fetched, and holding onto the bitmap until no longer needed.
+class ImageHolder : public chrome::BitmapFetcherDelegate {
+ public:
+  ImageHolder(const GURL& low_dpi_url,
+              const GURL& high_dpi_url,
+              Profile* profile,
+              ImageHolderDelegate* delegate);
+  virtual ~ImageHolder();
+
+  // Begin fetching of the URLs we have.
+  void StartFetch();
+
+  // Check whether we have a response from the server for these resources,
+  // even if the response is a failed fetch.
+  bool IsFetchingDone() const;
+
+  // Inherited from BitmapFetcherDelegate
+  virtual void OnFetchComplete(const GURL url, const SkBitmap* bitmap) OVERRIDE;
+
+  // Accessors:
+  GURL low_dpi_url() const { return low_dpi_url_; }
+  GURL high_dpi_url() const { return high_dpi_url_; }
+  gfx::Image low_dpi_image() { return gfx::Image(image_); }
+
+ private:
+  // Helper function to create a bitmap fetcher (but not start the fetch).
+  void CreateBitmapFetcher(const GURL& url);
+
+  GURL low_dpi_url_;
+  GURL high_dpi_url_;
+  bool low_dpi_fetched_;
+  bool high_dpi_fetched_;
+  gfx::ImageSkia image_;
+  ImageHolderDelegate* delegate_;
+  ScopedVector<chrome::BitmapFetcher> fetchers_;
+  Profile* profile_;
+
+  FRIEND_TEST_ALL_PREFIXES(ImageHolderTest, CreateBitmapFetcherTest);
+  FRIEND_TEST_ALL_PREFIXES(ImageHolderTest, OnFetchCompleteTest);
+  FRIEND_TEST_ALL_PREFIXES(ImageHolderTest, IsFetchingDoneTest);
+
+  DISALLOW_COPY_AND_ASSIGN(ImageHolder);
+};
+
+}  // namespace notifier.
+
+#endif  // CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_IMAGE_HOLDER_H_
diff --git a/chrome/browser/notifications/sync_notifier/image_holder_unittest.cc b/chrome/browser/notifications/sync_notifier/image_holder_unittest.cc
new file mode 100644
index 0000000..534228e
--- /dev/null
+++ b/chrome/browser/notifications/sync_notifier/image_holder_unittest.cc
@@ -0,0 +1,103 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "chrome/browser/notifications/sync_notifier/image_holder.h"
+#include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class TestDelegate : public notifier::ImageHolderDelegate {
+ public:
+  TestDelegate() : on_fetch_complete_called_(false) {}
+  virtual void OnFetchComplete() OVERRIDE {
+    on_fetch_complete_called_ = true;
+  }
+  bool on_fetch_complete_called_;
+};
+
+}  // namespace.
+
+namespace notifier {
+
+typedef testing::Test ImageHolderTest;
+
+TEST_F(ImageHolderTest, CreateBitmapFetcherTest) {
+  TestDelegate delegate;
+  ImageHolder image_holder(GURL(kIconUrl1), GURL(kIconUrl2), NULL, &delegate);
+
+  EXPECT_EQ(GURL(kIconUrl1), image_holder.fetchers_[0]->url());
+  EXPECT_EQ(GURL(kIconUrl2), image_holder.fetchers_[1]->url());
+  EXPECT_EQ(static_cast<unsigned int>(2), image_holder.fetchers_.size());
+
+  // Adding a dup of an existing URL shouldn't change anything.
+  image_holder.CreateBitmapFetcher(GURL(kIconUrl2));
+  EXPECT_EQ(GURL(kIconUrl1), image_holder.fetchers_[0]->url());
+  EXPECT_EQ(GURL(kIconUrl2), image_holder.fetchers_[1]->url());
+  EXPECT_EQ(static_cast<unsigned int>(2), image_holder.fetchers_.size());
+}
+
+TEST_F(ImageHolderTest, OnFetchCompleteTest) {
+  TestDelegate delegate;
+  ImageHolder image_holder(GURL(kIconUrl1), GURL(), NULL, &delegate);
+
+  // Put a real bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
+  SkBitmap bitmap;
+  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
+  bitmap.allocPixels();
+  bitmap.eraseColor(SK_ColorGREEN);
+
+  image_holder.OnFetchComplete(GURL(kIconUrl1), &bitmap);
+
+  // Expect that the app icon has some data in it.
+  EXPECT_FALSE(image_holder.low_dpi_image().IsEmpty());
+
+  // Expect that we reported the fetch done to the delegate.
+  EXPECT_TRUE(delegate.on_fetch_complete_called_);
+}
+
+TEST_F(ImageHolderTest, IsFetchingDoneTest) {
+  TestDelegate delegate;
+  ImageHolder image_holder1(GURL(kIconUrl1), GURL(kIconUrl2), NULL, &delegate);
+  ImageHolder image_holder2(GURL(kIconUrl1), GURL(), NULL, &delegate);
+  ImageHolder image_holder3(GURL(), GURL(kIconUrl2), NULL, &delegate);
+  ImageHolder image_holder4(GURL(), GURL(), NULL, &delegate);
+
+  // Initially, image holder 4 with no URLs should report done, but no others.
+  EXPECT_FALSE(image_holder1.IsFetchingDone());
+  EXPECT_FALSE(image_holder2.IsFetchingDone());
+  EXPECT_FALSE(image_holder3.IsFetchingDone());
+  EXPECT_TRUE(image_holder4.IsFetchingDone());
+
+  // Put a real bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
+  SkBitmap bitmap;
+  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
+  bitmap.allocPixels();
+  bitmap.eraseColor(SK_ColorGREEN);
+
+  // Add the first icon, and image holder 2 should now also report done.
+  image_holder1.OnFetchComplete(GURL(kIconUrl1), &bitmap);
+  image_holder2.OnFetchComplete(GURL(kIconUrl1), &bitmap);
+  image_holder3.OnFetchComplete(GURL(kIconUrl1), &bitmap);
+  image_holder4.OnFetchComplete(GURL(kIconUrl1), &bitmap);
+  EXPECT_FALSE(image_holder1.IsFetchingDone());
+  EXPECT_TRUE(image_holder2.IsFetchingDone());
+  EXPECT_FALSE(image_holder3.IsFetchingDone());
+  EXPECT_TRUE(image_holder4.IsFetchingDone());
+
+  // Add the second image, and now all 4 should report done.
+  image_holder1.OnFetchComplete(GURL(kIconUrl2), &bitmap);
+  image_holder2.OnFetchComplete(GURL(kIconUrl2), &bitmap);
+  image_holder3.OnFetchComplete(GURL(kIconUrl2), &bitmap);
+  image_holder4.OnFetchComplete(GURL(kIconUrl2), &bitmap);
+  EXPECT_TRUE(image_holder1.IsFetchingDone());
+  EXPECT_TRUE(image_holder2.IsFetchingDone());
+  EXPECT_TRUE(image_holder3.IsFetchingDone());
+  EXPECT_TRUE(image_holder4.IsFetchingDone());
+}
+
+}  // namespace notifier.
diff --git a/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc b/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc
index 23a11dc..ef9cda5 100644
--- a/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc
+++ b/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.cc
@@ -4,6 +4,12 @@
 
 #include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
 
+// Test data for App Info structures.
+const char kSendingService1Name[] = "TestService1";
+const char kSendingService2Name[] = "TestService2";
+const char kSendingService3Name[] = "TestService3";
+const char kTestIconUrl[] = "https://www.google.com/someicon.png";
+
 // Fake data for creating a SyncData object to use in creating a
 // SyncedNotification.
 const char kAppId1[] = "fboilmbenheemaomgaeehigklolhkhnf";
@@ -196,3 +202,87 @@
 
   return sync_data;
 }
+
+namespace notifier {
+
+StubSyncedNotificationAppInfoService::StubSyncedNotificationAppInfoService(
+    Profile* profile) : SyncedNotificationAppInfoService(profile) {
+  on_bitmap_fetches_done_called_ = false;
+}
+
+StubSyncedNotificationAppInfoService::~StubSyncedNotificationAppInfoService() {
+}
+
+syncer::SyncMergeResult
+StubSyncedNotificationAppInfoService::MergeDataAndStartSyncing(
+      syncer::ModelType type,
+      const syncer::SyncDataList& initial_sync_data,
+      scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
+      scoped_ptr<syncer::SyncErrorFactory> error_handler) {
+    return syncer::SyncMergeResult(syncer::SYNCED_NOTIFICATION_APP_INFO);
+}
+
+syncer::SyncError StubSyncedNotificationAppInfoService::ProcessSyncChanges(
+      const tracked_objects::Location& from_here,
+      const syncer::SyncChangeList& change_list) {
+    return syncer::SyncError();
+}
+
+syncer::SyncDataList StubSyncedNotificationAppInfoService::GetAllSyncData(
+    syncer::ModelType type) const {
+    return syncer::SyncDataList();
+}
+
+void StubSyncedNotificationAppInfoService::OnBitmapFetchesDone(
+    std::vector<std::string> added_app_ids,
+    std::vector<std::string> removed_app_ids) {
+    added_app_ids_ = added_app_ids;
+    removed_app_ids_ = removed_app_ids;
+    on_bitmap_fetches_done_called_ = true;
+}
+
+scoped_ptr<SyncedNotificationAppInfo>
+StubSyncedNotificationAppInfoService::
+    CreateSyncedNotificationAppInfoFromProtobuf(
+        const sync_pb::SyncedNotificationAppInfo& app_info) {
+  return scoped_ptr<SyncedNotificationAppInfo>();
+}
+
+SyncedNotificationAppInfo*
+StubSyncedNotificationAppInfoService::FindSyncedNotificationAppInfoByName(
+    const std::string& name) {
+  return NULL;
+}
+
+SyncedNotificationAppInfo*
+StubSyncedNotificationAppInfoService::FindSyncedNotificationAppInfoByAppId(
+    const std::string& app_id) {
+  return NULL;
+}
+
+std::string
+StubSyncedNotificationAppInfoService::FindSendingServiceNameFromAppId(
+    const std::string app_id) {
+  return std::string();
+}
+std::vector<SyncedNotificationSendingServiceSettingsData>
+StubSyncedNotificationAppInfoService::GetAllSendingServiceSettingsData() {
+  std::vector<SyncedNotificationSendingServiceSettingsData> empty;
+  return empty;
+}
+
+
+// Probe functions to return data.
+std::vector<std::string> StubSyncedNotificationAppInfoService::added_app_ids() {
+  return added_app_ids_;
+}
+
+std::vector<std::string>
+StubSyncedNotificationAppInfoService::removed_app_ids() {
+    return removed_app_ids_;
+}
+bool StubSyncedNotificationAppInfoService::on_bitmap_fetches_done_called() {
+  return on_bitmap_fetches_done_called_;
+}
+
+}  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h b/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h
index 4bd8897..9ff490d 100644
--- a/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h
+++ b/chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h
@@ -8,10 +8,17 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h"
 #include "sync/api/sync_data.h"
+#include "sync/api/sync_error_factory.h"
 #include "sync/protocol/sync.pb.h"
 #include "sync/protocol/synced_notification_specifics.pb.h"
 
+// Test data for App Info structures.
+extern const char kSendingService1Name[];
+extern const char kSendingService2Name[];
+extern const char kSendingService3Name[];
+extern const char kTestIconUrl[];
 
 // Fake data for creating a SyncedNotification.
 extern const char kAppId1[];
@@ -95,4 +102,63 @@
     const std::string& key,
       const sync_pb::CoalescedSyncedNotification_ReadState read_state);
 
+namespace notifier {
+
+// Stub out the SyncedNotificationAppInfoService.  This is used to
+// 1. Verify that when bitmaps are fetched, the OnFetchComplete causes a call to
+// OnBitmapFetchesDone.
+// 2. Provide the app info for our first sending service.
+class StubSyncedNotificationAppInfoService
+    : public SyncedNotificationAppInfoService {
+ public:
+  // Interface functions from SyncedNotificationAppInfoService
+    explicit StubSyncedNotificationAppInfoService(Profile* profile);
+  virtual ~StubSyncedNotificationAppInfoService();
+  virtual void Shutdown() OVERRIDE{}
+  virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
+      syncer::ModelType type,
+      const syncer::SyncDataList& initial_sync_data,
+      scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
+      scoped_ptr<syncer::SyncErrorFactory> error_handler) OVERRIDE;
+  virtual void StopSyncing(syncer::ModelType type) OVERRIDE{}
+  virtual syncer::SyncError ProcessSyncChanges(
+      const tracked_objects::Location& from_here,
+      const syncer::SyncChangeList& change_list) OVERRIDE;
+  virtual syncer::SyncDataList GetAllSyncData(syncer::ModelType type) const
+      OVERRIDE;
+  void ProcessIncomingAppInfoProtobuf(
+      const sync_pb::SyncedNotificationAppInfo& app_info) {}
+  void ProcessRemovedAppInfoProtobuf(
+      const sync_pb::SyncedNotificationAppInfo& app_info) {}
+  // Remember the arguments we saw in the most recent call.
+  virtual void OnBitmapFetchesDone(std::vector<std::string> added_app_ids,
+                                   std::vector<std::string> removed_app_ids)
+      OVERRIDE;
+  scoped_ptr<SyncedNotificationAppInfo>
+  CreateSyncedNotificationAppInfoFromProtobuf(
+      const sync_pb::SyncedNotificationAppInfo& app_info);
+  SyncedNotificationAppInfo* FindSyncedNotificationAppInfoByAppId(
+      const std::string& app_id);
+  std::string FindSendingServiceNameFromAppId(const std::string app_id);
+  std::vector<SyncedNotificationSendingServiceSettingsData>
+  GetAllSendingServiceSettingsData();
+  void AddForTest(
+      scoped_ptr<notifier::SyncedNotificationAppInfo> sending_service_info) {}
+  static void set_avoid_bitmap_fetching_for_test(bool avoid) {}
+
+  // Probe functions to return data.
+  std::vector<std::string> added_app_ids();
+  std::vector<std::string> removed_app_ids();
+  bool on_bitmap_fetches_done_called();
+
+ private:
+  SyncedNotificationAppInfo* FindSyncedNotificationAppInfoByName(
+      const std::string& name);
+  std::vector<std::string> added_app_ids_;
+  std::vector<std::string> removed_app_ids_;
+  bool on_bitmap_fetches_done_called_;
+};
+
+}  // namespace notifier
+
 #endif  // CHROME_BROWSER_NOTIFICATIONS_SYNC_NOTIFIER_SYNC_NOTIFIER_TEST_UTILS_H_
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.cc b/chrome/browser/notifications/sync_notifier/synced_notification.cc
index cddced0..a742563 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.cc
@@ -68,9 +68,12 @@
                sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED,
                local_enum_must_match_protobuf_enum);
 
-SyncedNotification::SyncedNotification(const syncer::SyncData& sync_data)
-    : notification_manager_(NULL),
-      notifier_service_(NULL),
+SyncedNotification::SyncedNotification(
+    const syncer::SyncData& sync_data,
+    ChromeNotifierService* notifier_service,
+    NotificationUIManager* notification_manager)
+    : notification_manager_(notification_manager),
+      notifier_service_(notifier_service),
       profile_(NULL),
       toast_state_(true),
       app_icon_bitmap_fetch_pending_(true),
@@ -86,166 +89,19 @@
   specifics_.CopyFrom(sync_data.GetSpecifics().synced_notification());
 }
 
-sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const {
-  sync_pb::EntitySpecifics entity_specifics;
-  entity_specifics.mutable_synced_notification()->CopyFrom(specifics_);
-  return entity_specifics;
-}
-
-// Check that we have either fetched or gotten an error on all the bitmaps we
-// asked for.
-bool SyncedNotification::AreAllBitmapsFetched() {
-  bool app_icon_ready = GetAppIconUrl().is_empty() ||
-      !app_icon_bitmap_.IsEmpty() || !app_icon_bitmap_fetch_pending_;
-  bool images_ready = GetImageUrl().is_empty() || !image_bitmap_.IsEmpty() ||
-      !image_bitmap_fetch_pending_;
-  bool sender_picture_ready = GetProfilePictureUrl(0).is_empty() ||
-      !sender_bitmap_.IsEmpty() || !sender_bitmap_fetch_pending_;
-  bool button_bitmaps_ready = true;
-  for (unsigned int j = 0; j < GetButtonCount(); ++j) {
-    if (!GetButtonIconUrl(j).is_empty()
-        && button_bitmaps_[j].IsEmpty()
-        && button_bitmaps_fetch_pending_[j]) {
-      button_bitmaps_ready = false;
-      break;
-    }
-  }
-
-  return app_icon_ready && images_ready && sender_picture_ready &&
-      button_bitmaps_ready;
-}
-
-// TODO(petewil): The fetch mechanism appears to be returning two bitmaps on the
-// mac - perhaps one is regular, one is high dpi?  If so, ensure we use the high
-// dpi bitmap when appropriate.
-void SyncedNotification::OnFetchComplete(const GURL url,
-                                         const SkBitmap* bitmap) {
-  // TODO(petewil): Add timeout mechanism in case bitmaps take too long.  Do we
-  // already have one built into URLFetcher?
-  // Make sure we are on the thread we expect.
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
-  gfx::Image downloaded_image;
-  if (bitmap != NULL)
-    downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap);
-
-  // Match the incoming bitmaps to URLs.  In case this is a dup, make sure to
-  // try all potentially matching urls.
-  if (GetAppIconUrl() == url) {
-    app_icon_bitmap_ = downloaded_image;
-    if (app_icon_bitmap_.IsEmpty())
-      app_icon_bitmap_fetch_pending_ = false;
-  }
-  if (GetImageUrl() == url) {
-    image_bitmap_ = downloaded_image;
-    if (image_bitmap_.IsEmpty())
-      image_bitmap_fetch_pending_ = false;
-  }
-  if (GetProfilePictureUrl(0) == url) {
-    sender_bitmap_ = downloaded_image;
-    if (sender_bitmap_.IsEmpty())
-      sender_bitmap_fetch_pending_ = false;
-  }
-
-  // If this URL matches one or more button bitmaps, save them off.
-  for (unsigned int i = 0; i < GetButtonCount(); ++i) {
-    if (GetButtonIconUrl(i) == url) {
-      if (bitmap != NULL) {
-        button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap);
-      }
-      button_bitmaps_fetch_pending_[i] = false;
-    }
-  }
-
-  DVLOG(2) << __FUNCTION__ << " popping bitmap " << url;
-
-  // See if all bitmaps are already accounted for, if so call Show.
-  if (AreAllBitmapsFetched()) {
-    Show(notification_manager_, notifier_service_, profile_);
-  }
-}
-
-void SyncedNotification::QueueBitmapFetchJobs(
-    NotificationUIManager* notification_manager,
-    ChromeNotifierService* notifier_service,
-    Profile* profile) {
-  // If we are not using the MessageCenter, call show now, and the existing
-  // code will handle the bitmap fetch for us.
-  if (!UseRichNotifications()) {
-    Show(notification_manager, notifier_service, profile);
-    return;
-  }
-
-  // Save off the arguments for the call to Show.
-  notification_manager_ = notification_manager;
-  notifier_service_ = notifier_service;
-  profile_ = profile;
-
-  // Ensure our bitmap vector has as many entries as there are buttons,
-  // so that when the bitmaps arrive the vector has a slot for them.
-  for (unsigned int i = 0; i < GetButtonCount(); ++i) {
-    button_bitmaps_.push_back(gfx::Image());
-    button_bitmaps_fetch_pending_.push_back(true);
-    AddBitmapToFetchQueue(GetButtonIconUrl(i));
-  }
-
-  // If there is a profile image bitmap, fetch it
-  if (GetProfilePictureCount() > 0) {
-    // TODO(petewil): When we have the capacity to display more than one bitmap,
-    // modify this code to fetch as many as we can display
-    AddBitmapToFetchQueue(GetProfilePictureUrl(0));
-  }
-
-  // If the URL is non-empty, add it to our queue of URLs to fetch.
-  AddBitmapToFetchQueue(GetAppIconUrl());
-  AddBitmapToFetchQueue(GetImageUrl());
-
-  // Check to see if we don't need to fetch images, either because we already
-  // did, or because the URLs are empty. If so, we can display the notification.
-
-  // See if all bitmaps are accounted for, if so call Show().
-  if (AreAllBitmapsFetched()) {
-    Show(notification_manager_, notifier_service_, profile_);
-  }
-}
-
-void SyncedNotification::StartBitmapFetch() {
-  // Now that we have queued and counted them all, start the fetching.
-  ScopedVector<chrome::BitmapFetcher>::iterator iter;
-  for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
-    (*iter)->Start(profile_);
-  }
-}
-
-void SyncedNotification::AddBitmapToFetchQueue(const GURL& url) {
-  // Check for dups, ignore any request for a dup.
-  ScopedVector<chrome::BitmapFetcher>::iterator iter;
-  for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
-    if ((*iter)->url() == url)
-      return;
-  }
-
-  if (url.is_valid()) {
-    fetchers_.push_back(new chrome::BitmapFetcher(url, this));
-    DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url;
-  }
-}
-
-void SyncedNotification::Show(NotificationUIManager* notification_manager,
-                              ChromeNotifierService* notifier_service,
-                              Profile* profile) {
+void SyncedNotification::Show(Profile* profile) {
   // Let NotificationUIManager know that the notification has been dismissed.
   if (SyncedNotification::kRead == GetReadState() ||
       SyncedNotification::kDismissed == GetReadState() ) {
-    notification_manager->CancelById(GetKey());
+    notification_manager_->CancelById(GetKey());
     DVLOG(2) << "Dismissed or read notification arrived"
              << GetHeading() << " " << GetText();
     return;
   }
 
   // |notifier_service| can be NULL in tests.
-  if (UseRichNotifications() && notifier_service) {
-    notifier_service->ShowWelcomeToastIfNecessary(this, notification_manager);
+  if (UseRichNotifications() && notifier_service_) {
+    notifier_service_->ShowWelcomeToastIfNecessary(this, notification_manager_);
   }
 
   // Set up the fields we need to send and create a Notification object.
@@ -264,7 +120,7 @@
   // The delegate will eventually catch calls that the notification
   // was read or deleted, and send the changes back to the server.
   scoped_refptr<NotificationDelegate> delegate =
-      new ChromeNotifierDelegate(GetKey(), notifier_service);
+      new ChromeNotifierDelegate(GetKey(), notifier_service_);
 
   // Some inputs and fields are only used if there is a notification center.
   if (UseRichNotifications()) {
@@ -364,7 +220,7 @@
     // has already been shown.
     ui_notification.set_shown_as_popup(!toast_state_);
 
-    notification_manager->Add(ui_notification, profile);
+    notification_manager_->Add(ui_notification, profile);
   } else {
     // In this case we have a Webkit Notification, not a Rich Notification.
     Notification ui_notification(GetOriginUrl(),
@@ -376,7 +232,7 @@
                                  replace_key,
                                  delegate.get());
 
-    notification_manager->Add(ui_notification, profile);
+    notification_manager_->Add(ui_notification, profile);
   }
 
   DVLOG(1) << "Showing Synced Notification! " << heading << " " << text
@@ -386,6 +242,76 @@
   return;
 }
 
+sync_pb::EntitySpecifics SyncedNotification::GetEntitySpecifics() const {
+  sync_pb::EntitySpecifics entity_specifics;
+  entity_specifics.mutable_synced_notification()->CopyFrom(specifics_);
+  return entity_specifics;
+}
+
+// Display the notification if it has the specified app_id_name.
+void SyncedNotification::ShowAllForAppId(Profile* profile,
+                                         std::string app_id_name) {
+  if (app_id_name == GetAppId())
+    Show(profile);
+}
+
+// Remove the notification if it has the specified app_id_name.
+void SyncedNotification::HideAllForAppId(std::string app_id_name) {
+  if (app_id_name == GetAppId()) {
+    notification_manager_->CancelById(GetKey());
+  }
+}
+
+void SyncedNotification::QueueBitmapFetchJobs(
+    ChromeNotifierService* notifier_service,
+    Profile* profile) {
+  // If we are not using the MessageCenter, call show now, and the existing
+  // code will handle the bitmap fetch for us.
+  if (!UseRichNotifications()) {
+    Show(profile);
+    return;
+  }
+
+  // Save off the arguments for the call to Show.
+  notifier_service_ = notifier_service;
+  profile_ = profile;
+
+  // Ensure our bitmap vector has as many entries as there are buttons,
+  // so that when the bitmaps arrive the vector has a slot for them.
+  for (unsigned int i = 0; i < GetButtonCount(); ++i) {
+    button_bitmaps_.push_back(gfx::Image());
+    button_bitmaps_fetch_pending_.push_back(true);
+    CreateBitmapFetcher(GetButtonIconUrl(i));
+  }
+
+  // If there is a profile image bitmap, fetch it
+  if (GetProfilePictureCount() > 0) {
+    // TODO(petewil): When we have the capacity to display more than one bitmap,
+    // modify this code to fetch as many as we can display
+    CreateBitmapFetcher(GetProfilePictureUrl(0));
+  }
+
+  // If the URL is non-empty, add it to our queue of URLs to fetch.
+  CreateBitmapFetcher(GetAppIconUrl());
+  CreateBitmapFetcher(GetImageUrl());
+
+  // Check to see if we don't need to fetch images, either because we already
+  // did, or because the URLs are empty. If so, we can display the notification.
+
+  // See if all bitmaps are accounted for, if so call Show().
+  if (AreAllBitmapsFetched()) {
+    Show(profile_);
+  }
+}
+
+void SyncedNotification::StartBitmapFetch() {
+  // Now that we have queued and counted them all, start the fetching.
+  ScopedVector<chrome::BitmapFetcher>::iterator iter;
+  for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
+    (*iter)->Start(profile_);
+  }
+}
+
 // This should detect even small changes in case the server updated the
 // notification.  We ignore the timestamp if other fields match.
 bool SyncedNotification::EqualsIgnoringReadState(
@@ -444,36 +370,6 @@
   return false;
 }
 
-void SyncedNotification::LogNotification() {
-  std::string readStateString("Unread");
-  if (SyncedNotification::kRead == GetReadState())
-    readStateString = "Read";
-  else if (SyncedNotification::kDismissed == GetReadState())
-    readStateString = "Dismissed";
-
-  DVLOG(2) << " Notification: Heading is " << GetHeading()
-           << " description is " << GetDescription()
-           << " key is " << GetKey()
-           << " read state is " << readStateString;
-}
-
-// Set the read state on the notification, returns true for success.
-void SyncedNotification::SetReadState(const ReadState& read_state) {
-
-  // Convert the read state to the protobuf type for read state.
-  if (kDismissed == read_state)
-    specifics_.mutable_coalesced_notification()->set_read_state(
-        sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED);
-  else if (kUnread == read_state)
-    specifics_.mutable_coalesced_notification()->set_read_state(
-        sync_pb::CoalescedSyncedNotification_ReadState_UNREAD);
-  else if (kRead == read_state)
-    specifics_.mutable_coalesced_notification()->set_read_state(
-        sync_pb::CoalescedSyncedNotification_ReadState_READ);
-  else
-    NOTREACHED();
-}
-
 void SyncedNotification::NotificationHasBeenRead() {
   SetReadState(kRead);
 }
@@ -627,33 +523,6 @@
   }
 }
 
-size_t SyncedNotification::GetNotificationCount() const {
-  return specifics_.coalesced_notification().render_info().
-      expanded_info().collapsed_info_size();
-}
-
-size_t SyncedNotification::GetButtonCount() const {
-  return specifics_.coalesced_notification().render_info().collapsed_info().
-      target_size();
-}
-
-size_t SyncedNotification::GetProfilePictureCount() const {
-  return specifics_.coalesced_notification().render_info().collapsed_info().
-      simple_collapsed_layout().profile_image_size();
-}
-
-GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const {
-  if (GetProfilePictureCount() <= which_url)
-    return GURL();
-
-  std::string url_spec = specifics_.coalesced_notification().render_info().
-      collapsed_info().simple_collapsed_layout().profile_image(which_url).
-      image_url();
-
-  return AddDefaultSchemaIfNeeded(url_spec);
-}
-
-
 std::string SyncedNotification::GetDefaultDestinationTitle() const {
   if (!specifics_.coalesced_notification().render_info().collapsed_info().
       default_destination().icon().has_alt_text()) {
@@ -726,6 +595,31 @@
   return AddDefaultSchemaIfNeeded(url_spec);
 }
 
+GURL SyncedNotification::GetProfilePictureUrl(unsigned int which_url) const {
+  if (GetProfilePictureCount() <= which_url)
+    return GURL();
+
+  std::string url_spec = specifics_.coalesced_notification().render_info().
+      collapsed_info().simple_collapsed_layout().profile_image(which_url).
+      image_url();
+
+  return AddDefaultSchemaIfNeeded(url_spec);
+}
+
+size_t SyncedNotification::GetProfilePictureCount() const {
+  return specifics_.coalesced_notification().render_info().collapsed_info().
+      simple_collapsed_layout().profile_image_size();
+}
+
+size_t SyncedNotification::GetNotificationCount() const {
+  return specifics_.coalesced_notification().render_info().
+      expanded_info().collapsed_info_size();
+}
+
+size_t SyncedNotification::GetButtonCount() const {
+  return specifics_.coalesced_notification().render_info().collapsed_info().
+      target_size();
+}
 std::string SyncedNotification::GetContainedNotificationTitle(
     int index) const {
   if (specifics_.coalesced_notification().render_info().expanded_info().
@@ -746,20 +640,127 @@
       collapsed_info(index).simple_collapsed_layout().description();
 }
 
-std::string SyncedNotification::GetSendingServiceId() const {
-  // TODO(petewil): We are building a new protocol (a new sync datatype) to send
-  // the service name and icon from the server.  For now this method is
-  // hardcoded to the name of our first service using synced notifications.
-  // Once the new protocol is built, remove this hardcoding.
-  return kFirstSyncedNotificationServiceId;
-}
-
 const gfx::Image& SyncedNotification::GetAppIcon() const {
   return app_icon_bitmap_;
 }
 
-void SyncedNotification::SetToastState(bool toast_state) {
+void SyncedNotification::set_toast_state(bool toast_state) {
   toast_state_ = toast_state;
 }
 
+void SyncedNotification::LogNotification() {
+  std::string readStateString("Unread");
+  if (SyncedNotification::kRead == GetReadState())
+    readStateString = "Read";
+  else if (SyncedNotification::kDismissed == GetReadState())
+    readStateString = "Dismissed";
+
+  DVLOG(2) << " Notification: Heading is " << GetHeading()
+           << " description is " << GetDescription()
+           << " key is " << GetKey()
+           << " read state is " << readStateString;
+}
+
+// TODO(petewil): The fetch mechanism appears to be returning two bitmaps on the
+// mac - perhaps one is regular, one is high dpi?  If so, ensure we use the high
+// dpi bitmap when appropriate.
+void SyncedNotification::OnFetchComplete(const GURL url,
+                                         const SkBitmap* bitmap) {
+  // Make sure we are on the thread we expect.
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  gfx::Image downloaded_image;
+  if (bitmap != NULL)
+    downloaded_image = gfx::Image::CreateFrom1xBitmap(*bitmap);
+
+  // Match the incoming bitmaps to URLs.  In case this is a dup, make sure to
+  // try all potentially matching urls.
+  if (GetAppIconUrl() == url) {
+    app_icon_bitmap_ = downloaded_image;
+    if (app_icon_bitmap_.IsEmpty())
+      app_icon_bitmap_fetch_pending_ = false;
+  }
+  if (GetImageUrl() == url) {
+    image_bitmap_ = downloaded_image;
+    if (image_bitmap_.IsEmpty())
+      image_bitmap_fetch_pending_ = false;
+  }
+  if (GetProfilePictureUrl(0) == url) {
+    sender_bitmap_ = downloaded_image;
+    if (sender_bitmap_.IsEmpty())
+      sender_bitmap_fetch_pending_ = false;
+  }
+
+  // If this URL matches one or more button bitmaps, save them off.
+  for (unsigned int i = 0; i < GetButtonCount(); ++i) {
+    if (GetButtonIconUrl(i) == url) {
+      if (bitmap != NULL) {
+        button_bitmaps_[i] = gfx::Image::CreateFrom1xBitmap(*bitmap);
+      }
+      button_bitmaps_fetch_pending_[i] = false;
+    }
+  }
+
+  DVLOG(2) << __FUNCTION__ << " popping bitmap " << url;
+
+  // See if all bitmaps are already accounted for, if so call Show.
+  if (AreAllBitmapsFetched()) {
+    Show(profile_);
+  }
+}
+
+void SyncedNotification::CreateBitmapFetcher(const GURL& url) {
+  // Check for dups, ignore any request for a dup.
+  ScopedVector<chrome::BitmapFetcher>::iterator iter;
+  for (iter = fetchers_.begin(); iter != fetchers_.end(); ++iter) {
+    if ((*iter)->url() == url)
+      return;
+  }
+
+  if (url.is_valid()) {
+    fetchers_.push_back(new chrome::BitmapFetcher(url, this));
+    DVLOG(2) << __FUNCTION__ << "Pushing bitmap " << url;
+  }
+}
+
+// Check that we have either fetched or gotten an error on all the bitmaps we
+// asked for.
+bool SyncedNotification::AreAllBitmapsFetched() {
+  bool app_icon_ready = GetAppIconUrl().is_empty() ||
+      !app_icon_bitmap_.IsEmpty() || !app_icon_bitmap_fetch_pending_;
+  bool images_ready = GetImageUrl().is_empty() || !image_bitmap_.IsEmpty() ||
+      !image_bitmap_fetch_pending_;
+  bool sender_picture_ready = GetProfilePictureUrl(0).is_empty() ||
+      !sender_bitmap_.IsEmpty() || !sender_bitmap_fetch_pending_;
+  bool button_bitmaps_ready = true;
+  for (unsigned int j = 0; j < GetButtonCount(); ++j) {
+    if (!GetButtonIconUrl(j).is_empty()
+        && button_bitmaps_[j].IsEmpty()
+        && button_bitmaps_fetch_pending_[j]) {
+      button_bitmaps_ready = false;
+      break;
+    }
+  }
+
+  return app_icon_ready && images_ready && sender_picture_ready &&
+      button_bitmaps_ready;
+}
+
+// Set the read state on the notification, returns true for success.
+void SyncedNotification::SetReadState(const ReadState& read_state) {
+
+  // Convert the read state to the protobuf type for read state.
+  if (kDismissed == read_state)
+    specifics_.mutable_coalesced_notification()->set_read_state(
+        sync_pb::CoalescedSyncedNotification_ReadState_DISMISSED);
+  else if (kUnread == read_state)
+    specifics_.mutable_coalesced_notification()->set_read_state(
+        sync_pb::CoalescedSyncedNotification_ReadState_UNREAD);
+  else if (kRead == read_state)
+    specifics_.mutable_coalesced_notification()->set_read_state(
+        sync_pb::CoalescedSyncedNotification_ReadState_READ);
+  else
+    NOTREACHED();
+}
+
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification.h b/chrome/browser/notifications/sync_notifier/synced_notification.h
index 429ecc6..293d4f6 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification.h
@@ -33,7 +33,9 @@
 
 class SyncedNotification : public chrome::BitmapFetcherDelegate {
  public:
-  explicit SyncedNotification(const syncer::SyncData& sync_data);
+  SyncedNotification(const syncer::SyncData& sync_data,
+                     ChromeNotifierService* notifier,
+                     NotificationUIManager* notification_manager);
 
   virtual ~SyncedNotification();
 
@@ -47,6 +49,38 @@
 
   void Update(const syncer::SyncData& sync_data);
 
+  // Display the notification in the notification center
+  void Show(Profile* profile);
+
+  // This gets a pointer to the SyncedNotificationSpecifics part
+  // of the sync data.
+  sync_pb::EntitySpecifics GetEntitySpecifics() const;
+
+  // Display the notification if it has the specified app_id_name.
+  void ShowAllForAppId(Profile* profile,
+                       std::string app_id_name);
+
+  // Remove the notification if it has the specified app_id_name.
+  void HideAllForAppId(std::string app_id_name);
+
+  // Fill up the queue of bitmaps to fetch.
+  void QueueBitmapFetchJobs(ChromeNotifierService* notifier_service,
+                            Profile* profile);
+
+  // Start the bitmap fetching.  When it is complete, the callback
+  // will call Show().
+  void StartBitmapFetch();
+
+  // Check against an incoming notification, see if only the read state is
+  // different.
+  bool EqualsIgnoringReadState(const SyncedNotification& other) const;
+
+  // Mark the notification as Read.
+  void NotificationHasBeenRead();
+
+  // Mark a notification as Dismissed (deleted).
+  void NotificationHasBeenDismissed();
+
   // Here are some helper functions to get individual data parts out of a
   // SyncedNotification.
   std::string GetTitle() const;
@@ -74,51 +108,31 @@
   size_t GetButtonCount() const;
   std::string GetContainedNotificationTitle(int index) const;
   std::string GetContainedNotificationMessage(int index) const;
-  std::string GetSendingServiceId() const;
   const gfx::Image& GetAppIcon() const;
 
   // Use this to prevent toasting a notification.
-  void SetToastState(bool toast_state);
-
-  bool EqualsIgnoringReadState(const SyncedNotification& other) const;
-
-  void NotificationHasBeenRead();
-  void NotificationHasBeenDismissed();
-
-  // Fill up the queue of bitmaps to fetch.
-  void QueueBitmapFetchJobs(NotificationUIManager* notification_manager,
-                            ChromeNotifierService* notifier_service,
-                            Profile* profile);
-
-  // Start the bitmap fetching.  When it is complete, the callback
-  // will call Show().
-  void StartBitmapFetch();
-
-  // Display the notification in the notification center
-  void Show(NotificationUIManager* notification_manager,
-            ChromeNotifierService* notifier_service,
-            Profile* profile);
-
-  // This gets a pointer to the SyncedNotificationSpecifics part
-  // of the sync data.
-  sync_pb::EntitySpecifics GetEntitySpecifics() const;
+  void set_toast_state(bool toast_state);
 
   // Write a notification to the console log.
   void LogNotification();
 
  private:
-  // Helper function to mark a notification as read or dismissed.
-  void SetReadState(const ReadState& read_state);
-
   // Method inherited from BitmapFetcher delegate.
   virtual void OnFetchComplete(const GURL url, const SkBitmap* bitmap) OVERRIDE;
 
   // If this bitmap has a valid GURL, create a fetcher for it.
-  void AddBitmapToFetchQueue(const GURL& gurl);
+  void CreateBitmapFetcher(const GURL& gurl);
 
   // Check to see if we have responses for all the bitmaps we need.
   bool AreAllBitmapsFetched();
 
+  // Helper function to mark a notification as read or dismissed.
+  void SetReadState(const ReadState& read_state);
+
+  void SetNotifierServiceForTest(ChromeNotifierService* notifier) {
+    notifier_service_ = notifier;
+  }
+
   sync_pb::SyncedNotificationSpecifics specifics_;
   NotificationUIManager* notification_manager_;
   ChromeNotifierService* notifier_service_;
@@ -134,13 +148,15 @@
   bool image_bitmap_fetch_pending_;
   std::vector<bool> button_bitmaps_fetch_pending_;
 
-
   friend class SyncedNotificationTest;
 
-  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationTest, AddBitmapToFetchQueueTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationTest, CreateBitmapFetcherTest);
   FRIEND_TEST_ALL_PREFIXES(SyncedNotificationTest, OnFetchCompleteTest);
   FRIEND_TEST_ALL_PREFIXES(SyncedNotificationTest, QueueBitmapFetchJobsTest);
   FRIEND_TEST_ALL_PREFIXES(SyncedNotificationTest, EmptyBitmapTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationTest, ShowIfNewlyEnabledTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationTest, HideIfNewlyRemovedTest);
+  FRIEND_TEST_ALL_PREFIXES(ChromeNotifierServiceTest, SetAddedAppIdsTest);
 
   DISALLOW_COPY_AND_ASSIGN(SyncedNotification);
 };
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_app_info.cc b/chrome/browser/notifications/sync_notifier/synced_notification_app_info.cc
index 1accb26..e3d4ac3 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_app_info.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_app_info.cc
@@ -4,17 +4,32 @@
 
 #include "chrome/browser/notifications/sync_notifier/synced_notification_app_info.h"
 
+#include "chrome/browser/notifications/sync_notifier/image_holder.h"
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "sync/api/sync_data.h"
 #include "sync/protocol/synced_notification_app_info_specifics.pb.h"
 
 namespace notifier {
 
 SyncedNotificationAppInfo::SyncedNotificationAppInfo(
-    const std::string& settings_display_name)
-    : settings_display_name_(settings_display_name) {}
+    Profile* const profile,
+    const std::string& settings_display_name,
+    SyncedNotificationAppInfoService* synced_notification_app_info_service)
+    : profile_(profile),
+      settings_display_name_(settings_display_name),
+      synced_notification_app_info_service_(
+          synced_notification_app_info_service) {}
 
 SyncedNotificationAppInfo::~SyncedNotificationAppInfo() {}
 
+GURL SyncedNotificationAppInfo::settings_icon_url() {
+  if (settings_holder_ != NULL)
+    return settings_holder_->low_dpi_url();
+  else
+    return GURL();
+}
+
 bool SyncedNotificationAppInfo::HasAppId(const std::string& app_id) {
   std::vector<std::string>::iterator it;
 
@@ -44,15 +59,96 @@
   }
 }
 
-void SyncedNotificationAppInfo::GetAppIdList(
-    std::vector<std::string>* app_id_list) {
-  if (app_id_list == NULL)
-    return;
+void SyncedNotificationAppInfo::SetSettingsURLs(
+    const GURL& settings_low_dpi, const GURL& settings_high_dpi) {
+  settings_holder_.reset(new ImageHolder(settings_low_dpi,
+                                         settings_high_dpi,
+                                         profile_,
+                                         this));
+}
 
+void SyncedNotificationAppInfo::SetMonochromeURLs(
+    const GURL& monochrome_low_dpi, const GURL& monochrome_high_dpi) {
+  monochrome_holder_.reset(new ImageHolder(monochrome_low_dpi,
+                                           monochrome_high_dpi,
+                                           profile_,
+                                           this));
+}
+
+void SyncedNotificationAppInfo::SetWelcomeURLs(
+    const GURL& welcome_low_dpi, const GURL& welcome_high_dpi) {
+  welcome_holder_.reset(new ImageHolder(welcome_low_dpi,
+                                        welcome_high_dpi,
+                                        profile_,
+                                        this));
+}
+
+gfx::Image SyncedNotificationAppInfo::icon() {
+  if (settings_holder_ != NULL)
+    return settings_holder_->low_dpi_image();
+  else
+    return gfx::Image();
+}
+
+std::vector<std::string> SyncedNotificationAppInfo::GetAppIdList() {
+  std::vector<std::string> app_id_list;
   std::vector<std::string>::iterator it;
   for (it = app_ids_.begin(); it != app_ids_.end(); ++it) {
-    app_id_list->push_back(*it);
+    app_id_list.push_back(*it);
   }
+
+  return app_id_list;
+}
+
+// TODO: rename, queing now happens elsewhere.
+// Fill up the queue of bitmaps to fetch.
+void SyncedNotificationAppInfo::QueueBitmapFetchJobs() {
+  // If there are no bitmaps to fetch, call OnBitmapFetchesDone.
+  if (AreAllBitmapsFetched()) {
+      synced_notification_app_info_service_->OnBitmapFetchesDone(
+          added_app_ids_, removed_app_ids_);
+    DVLOG(2) << "AppInfo object with no bitmaps, we should add some. "
+             << this->settings_display_name_;
+    return;
+  }
+}
+
+// Start the bitmap fetching.  When it is complete, the callback
+// will notify the ChromeNotifierService of the new app info availablity.
+void SyncedNotificationAppInfo::StartBitmapFetch() {
+  if (settings_holder_.get() != NULL)
+    settings_holder_->StartFetch();
+  if (monochrome_holder_.get() != NULL)
+    monochrome_holder_->StartFetch();
+  if (welcome_holder_.get() != NULL)
+    welcome_holder_->StartFetch();
+}
+
+// Method inherited from ImageHolderDelegate
+void SyncedNotificationAppInfo::OnFetchComplete() {
+  if (AreAllBitmapsFetched()) {
+    if (synced_notification_app_info_service_ != NULL) {
+      synced_notification_app_info_service_->OnBitmapFetchesDone(
+          added_app_ids_, removed_app_ids_);
+    }
+  }
+}
+
+// Check to see if we have responses for all the bitmaps we got a URL for.
+bool SyncedNotificationAppInfo::AreAllBitmapsFetched() {
+  bool done =
+      (settings_holder_.get() == NULL || settings_holder_->IsFetchingDone()) &&
+      (monochrome_holder_.get() == NULL ||
+       monochrome_holder_->IsFetchingDone()) &&
+      (welcome_holder_.get() == NULL || welcome_holder_->IsFetchingDone());
+
+  return done;
+}
+
+message_center::NotifierId SyncedNotificationAppInfo::GetNotifierId() {
+  return message_center::NotifierId(
+      message_center::NotifierId::SYNCED_NOTIFICATION_SERVICE,
+      settings_display_name_);
 }
 
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_app_info.h b/chrome/browser/notifications/sync_notifier/synced_notification_app_info.h
index e35d692..8e9cba5 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_app_info.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_app_info.h
@@ -11,14 +11,25 @@
 #include <string>
 #include <vector>
 
+#include "base/memory/scoped_vector.h"
+#include "chrome/browser/notifications/sync_notifier/image_holder.h"
+#include "ui/gfx/image/image.h"
+#include "ui/message_center/notifier_settings.h"
 #include "url/gurl.h"
 
+class Profile;
+
 namespace notifier {
 
-class SyncedNotificationAppInfo {
+class SyncedNotificationAppInfoService;
+
+class SyncedNotificationAppInfo : public notifier::ImageHolderDelegate {
  public:
-  explicit SyncedNotificationAppInfo(const std::string& settings_display_name);
-  ~SyncedNotificationAppInfo();
+  SyncedNotificationAppInfo(
+      Profile* const profile,
+      const std::string& settings_display_name,
+      SyncedNotificationAppInfoService* synced_notification_app_info_service);
+  virtual ~SyncedNotificationAppInfo();
 
   // Return true if the app id is present in this AppInfo protobuf.
   bool HasAppId(const std::string& app_id);
@@ -31,24 +42,88 @@
 
   std::string settings_display_name() const { return settings_display_name_; }
 
-  void SetSettingsIcon(const GURL& settings_icon) {
-    settings_icon_url_ = settings_icon;
+  // Set the URL for the low and high DPI bitmaps for the settings dialog.
+  void SetSettingsURLs(const GURL& settings_low_dpi,
+                       const GURL& settings_high_dpi);
+
+  // Set the URL for the low and high DPI bitmaps for indicating the sending
+  // service.
+  void SetMonochromeURLs(const GURL& monochrome_low_dpi,
+                         const GURL& monochrome_high_dpi);
+
+  // Set the URL for the low and high DPI bitmaps for use by the welcome dialog.
+  void SetWelcomeURLs(const GURL& welcome_low_dpi,
+                      const GURL& welcome_high_dpi);
+
+  GURL settings_icon_url();
+
+  // If an app info is updated, keep track of the newly added app ids so we can
+  // later inform the chrome_notifier_service to show any newly enabled
+  // notifications.
+  void set_added_app_ids(std::vector<std::string> added_app_ids) {
+    added_app_ids_ = added_app_ids;
   }
 
-  GURL settings_icon_url() { return settings_icon_url_; }
+  std::vector<std::string> added_app_ids() { return added_app_ids_; }
+
+  // If an app info is updated removing app ids, keep track of the removed app
+  // ids so we can later remove any affected notfications.
+  void set_removed_app_ids(std::vector<std::string> removed_app_ids) {
+    removed_app_ids_ = removed_app_ids;
+  }
+
+  std::vector<std::string> removed_app_ids() { return removed_app_ids_; }
+
+  // TODO(petewil): Check resolution of system and return the right icon.
+  gfx::Image icon();
 
   // Build a vector of app_ids that this app_info contains.
-  void GetAppIdList(std::vector<std::string>* app_id_list);
+  std::vector<std::string> GetAppIdList();
+
+  // Set up for fetching all the bitmaps in this AppInfo.
+  void QueueBitmapFetchJobs();
+
+  // Start the bitmap fetching.  When it is complete, the callback
+  // will notify the ChromeNotifierService of the new app info availablity.
+  void StartBitmapFetch();
+
+  // Method inherited from ImageHolderDelegate
+  virtual void OnFetchComplete() OVERRIDE;
+
+  // Check to see if we have responses for all the bitmaps we need.
+  bool AreAllBitmapsFetched();
+
+  // Construct a Message Center NotifierId from this synced notification app
+  // info object.
+  message_center::NotifierId GetNotifierId();
 
  private:
   // TODO(petewil): We need a unique id for a key.  We will use the settings
-  // display name for now, but it would be more robust with a unique id.
+  // display name, but it would be more robust with a unique id.
+  Profile* profile_;
   std::vector<std::string> app_ids_;
   std::string settings_display_name_;
-  // TODO(petewil): We should get 1x and 2x versions of all these images.
-  GURL settings_icon_url_;
-  // TODO(petewil): Add monochrome icons for app badging and welcome icons.
-  // TODO(petewil): Add a landing page link for settings/welcome toast.
+  // The 1x and 2x versions of the icon for settings, small.
+  scoped_ptr<ImageHolder> settings_holder_;
+  // Monochrome icons for app badging (1x and 2x), small.
+  scoped_ptr<ImageHolder> monochrome_holder_;
+  // Welcome dialog icon (1x and 2x), large.
+  scoped_ptr<ImageHolder> welcome_holder_;
+  // A landing page link for settings/welcome toast.
+  GURL welcome_landing_page_url_;
+  std::vector<std::string> added_app_ids_;
+  std::vector<std::string> removed_app_ids_;
+  SyncedNotificationAppInfoService* synced_notification_app_info_service_;
+
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoTest, AddRemoveTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoTest, GetAppIdListTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoTest,
+                           CreateBitmapFetcherTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoTest, OnFetchCompleteTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoTest,
+                           QueueBitmapFetchJobsTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoTest,
+                           AreAllBitmapsFetchedTest);
 
   DISALLOW_COPY_AND_ASSIGN(SyncedNotificationAppInfo);
 };
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.cc b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.cc
index befd34d..78abecc 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.cc
@@ -8,6 +8,8 @@
 #include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h"
 
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service.h"
+#include "chrome/browser/notifications/sync_notifier/chrome_notifier_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_change_processor.h"
@@ -18,9 +20,20 @@
 
 namespace notifier {
 
+SyncedNotificationSendingServiceSettingsData::
+    SyncedNotificationSendingServiceSettingsData(
+        std::string settings_display_name_param,
+        gfx::Image settings_icon_param,
+        message_center::NotifierId notifier_id_param)
+        : settings_display_name(settings_display_name_param),
+          settings_icon(settings_icon_param),
+          notifier_id(notifier_id_param) {}
+
+bool SyncedNotificationAppInfoService::avoid_bitmap_fetching_for_test_ = false;
+
 SyncedNotificationAppInfoService::SyncedNotificationAppInfoService(
     Profile* profile)
-    : profile_(profile) {}
+    : profile_(profile), chrome_notifier_service_(NULL) {}
 
 SyncedNotificationAppInfoService::~SyncedNotificationAppInfoService() {}
 
@@ -136,6 +149,13 @@
   return sync_data_list;
 }
 
+// When a new protobuf comes in, we will fetch all the bitmaps before reporting
+// the new protobufs to the ChromeNotifierService.  This helps insure that new
+// protobufs appear at the same time old ones disappear, and that no protobuf
+// appears before its bitmaps are present.
+// We also check for duplicate bitmap URLs when loading the bitmaps for a
+// protobuf, so we aren't left waiting for a second copy of the bitmap to be
+// fetched before we call the protobuf done.
 void SyncedNotificationAppInfoService::ProcessIncomingAppInfoProtobuf(
     const sync_pb::SyncedNotificationAppInfo& app_info) {
   // Build a local app_info object from the sync data.
@@ -153,19 +173,66 @@
 
   SyncedNotificationAppInfo* found = FindSyncedNotificationAppInfoByName(name);
 
-  if (NULL != found) {
+  std::vector<std::string> old_app_ids;
+  std::vector<std::string> new_app_ids;
+  std::vector<std::string> added_app_ids;
+  std::vector<std::string> removed_app_ids;
+
+  new_app_ids = incoming->GetAppIdList();
+
+  if (NULL == found) {
+    added_app_ids = new_app_ids;
+  } else {
     // When we have an update, some app id types may be added or removed.
     // Append to lists of added and removed types.
+    old_app_ids = found->GetAppIdList();
+    new_app_ids = incoming->GetAppIdList();
     FreeSyncedNotificationAppInfoByName(name);
+
+    // Set up for a set difference by sorting the lists.
+    std::sort(old_app_ids.begin(), old_app_ids.end());
+    std::sort(new_app_ids.begin(), new_app_ids.end());
+
+    // Calculate which app ids are removed (in old, but not in new app ids).
+    std::set_difference(old_app_ids.begin(),
+                        old_app_ids.end(),
+                        new_app_ids.begin(),
+                        new_app_ids.end(),
+                        std::back_inserter(removed_app_ids));
+
+    // Calculate which app_ids are added (in new, but not in old app ids).
+    std::set_difference(new_app_ids.begin(),
+                        new_app_ids.end(),
+                        old_app_ids.begin(),
+                        old_app_ids.end(),
+                        std::back_inserter(added_app_ids));
+  }
+
+  // Put these lists into the app_info object.
+  incoming->set_added_app_ids(added_app_ids);
+  incoming->set_removed_app_ids(removed_app_ids);
+
+  // Start bitmap fetch.
+  if (!avoid_bitmap_fetching_for_test_) {
+    incoming->QueueBitmapFetchJobs();
+    incoming->StartBitmapFetch();
+  } else {
+    OnBitmapFetchesDone(incoming->added_app_ids(), incoming->removed_app_ids());
   }
 
   sending_service_infos_.push_back(incoming.release());
+}
 
+void SyncedNotificationAppInfoService::OnBitmapFetchesDone(
+    std::vector<std::string> added_app_ids,
+    std::vector<std::string> removed_app_ids) {
   // Tell the Chrome Notifier Service so it can show any notifications that were
   // waiting for the app id to arrive, and to remave any notifications that are
   // no longer supported.
-  // TODO(petewil): Notify CNS of added ids
-  // TODO(petewil): Notify CNS of deleted ids.
+  if (chrome_notifier_service_ != NULL) {
+    chrome_notifier_service_->OnAddedAppIds(added_app_ids);
+    chrome_notifier_service_->OnRemovedAppIds(removed_app_ids);
+  }
 }
 
 // Static Method.  Convert from a server protobuf to our internal format.
@@ -183,14 +250,17 @@
     return app_info.Pass();
 
   // Create a new app info object based on the supplied protobuf.
-  app_info.reset(new SyncedNotificationAppInfo(display_name));
+  app_info.reset(new SyncedNotificationAppInfo(profile_, display_name, this));
 
   // TODO(petewil): Eventually we will add the monochrome icon here, and we may
   // need to fetch the correct url for the current DPI.
   // Add the icon URL, if any.
   if (server_app_info.has_icon()) {
     std::string icon_url = server_app_info.icon().url();
-    app_info->SetSettingsIcon(GURL(icon_url));
+    // Set the URLs for the low and high DPI images.
+    // TODO(petewil): Since the high DPI image is not available yet, we just
+    // pass an empty URL for now.  Fix this once the high DPI URL is available.
+    app_info->SetSettingsURLs(GURL(icon_url), GURL());
   }
 
   // Add all the AppIds from the protobuf.
@@ -219,6 +289,38 @@
   return NULL;
 }
 
+// This returns a pointer into a vector that we own.  Caller must not free it.
+// Returns NULL if no match is found.
+notifier::SyncedNotificationAppInfo*
+SyncedNotificationAppInfoService::FindSyncedNotificationAppInfoByAppId(
+    const std::string& app_id) {
+  for (ScopedVector<SyncedNotificationAppInfo>::const_iterator it =
+           sending_service_infos_.begin();
+       it != sending_service_infos_.end();
+       ++it) {
+    SyncedNotificationAppInfo* app_info = *it;
+    if (app_info->HasAppId(app_id))
+      return *it;
+  }
+
+  return NULL;
+}
+
+// Lookup the sending service name for a given app id.
+std::string SyncedNotificationAppInfoService::FindSendingServiceNameFromAppId(
+    const std::string app_id) {
+  for (ScopedVector<SyncedNotificationAppInfo>::const_iterator it =
+           sending_service_infos_.begin();
+       it != sending_service_infos_.end();
+       ++it) {
+    SyncedNotificationAppInfo* app_info = *it;
+    if (app_info->HasAppId(app_id))
+      return app_info->settings_display_name();
+  }
+
+  return std::string();
+}
+
 void SyncedNotificationAppInfoService::FreeSyncedNotificationAppInfoByName(
     const std::string& name) {
   ScopedVector<SyncedNotificationAppInfo>::iterator it =
@@ -232,6 +334,23 @@
   }
 }
 
+std::vector<SyncedNotificationSendingServiceSettingsData>
+SyncedNotificationAppInfoService::GetAllSendingServiceSettingsData() {
+  std::vector<SyncedNotificationSendingServiceSettingsData> settings_data;
+  ScopedVector<SyncedNotificationAppInfo>::iterator it =
+      sending_service_infos_.begin();
+
+  for (; it != sending_service_infos_.end(); ++it) {
+    SyncedNotificationSendingServiceSettingsData this_service(
+        (*it)->settings_display_name(),
+        (*it)->icon(),
+        (*it)->GetNotifierId());
+    settings_data.push_back(this_service);
+  }
+
+  return settings_data;
+}
+
 // Add a new app info to our data structure.  This takes ownership
 // of the passed in pointer.
 void SyncedNotificationAppInfoService::Add(
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h
index 17f036f..2ab3827 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h
@@ -24,6 +24,21 @@
 
 namespace notifier {
 
+// Information that the ChromeNotifierService needs from this app info to be
+// able to properly enable and disable the sending services.
+struct SyncedNotificationSendingServiceSettingsData {
+  SyncedNotificationSendingServiceSettingsData(
+      std::string settings_display_name,
+      gfx::Image settings_icon,
+      message_center::NotifierId notifier_id);
+  std::string settings_display_name;
+  gfx::Image settings_icon;
+  message_center::NotifierId notifier_id;
+};
+
+
+class ChromeNotifierService;
+
 // The SyncedNotificationAppInfoService contains and syncs AppInfo protobufs
 // from the server with metadata about the services sending synced
 // notifications.
@@ -65,26 +80,53 @@
   void ProcessRemovedAppInfoProtobuf(
       const sync_pb::SyncedNotificationAppInfo& app_info);
 
+  // When the bitmaps are all ready, tell ChromeNotifierService about changes.
+  virtual void OnBitmapFetchesDone(std::vector<std::string> added_app_ids,
+                                   std::vector<std::string> removed_app_ids);
+
   // Convert the protobuf to our internal format.
-  static scoped_ptr<SyncedNotificationAppInfo>
+  scoped_ptr<SyncedNotificationAppInfo>
       CreateSyncedNotificationAppInfoFromProtobuf(
           const sync_pb::SyncedNotificationAppInfo& app_info);
 
+  // Get the app info that contains this sending service name.
+  SyncedNotificationAppInfo* FindSyncedNotificationAppInfoByName(
+      const std::string& name);
+
+  // Get the app info that contains this app id.
+  SyncedNotificationAppInfo* FindSyncedNotificationAppInfoByAppId(
+      const std::string& app_id);
+
+  // Lookup the sending service name for a given app id.
+  std::string FindSendingServiceNameFromAppId(const std::string app_id);
+
+  // Return a list of all sending service names.
+  std::vector<SyncedNotificationSendingServiceSettingsData>
+  GetAllSendingServiceSettingsData();
+
+  void set_chrome_notifier_service(ChromeNotifierService* notifier) {
+    chrome_notifier_service_ = notifier;
+  }
+
   // Functions for test.
   void AddForTest(
       scoped_ptr<notifier::SyncedNotificationAppInfo> sending_service_info) {
     Add(sending_service_info.Pass());
   }
 
+  // If we allow the tests to do bitmap fetching, they will attempt to fetch
+  // a URL from the web, which will fail.  We can already test the majority
+  // of what we want without also trying to fetch bitmaps.  Other tests will
+  // cover bitmap fetching.
+  static void set_avoid_bitmap_fetching_for_test(bool avoid) {
+    avoid_bitmap_fetching_for_test_ = avoid;
+  }
+
  private:
   // Add an app_info object to our list.  This takes ownership of the pointer.
   void Add(
       scoped_ptr<notifier::SyncedNotificationAppInfo> sending_service_info);
 
-  // Get the app info that contains this ID.
-  SyncedNotificationAppInfo* FindSyncedNotificationAppInfoByName(
-      const std::string& name);
-
   // Remove this app info.
   void FreeSyncedNotificationAppInfoByName(const std::string& name);
 
@@ -102,6 +144,14 @@
   // Cache of the sync info.
   syncer::SyncData sync_data_;
 
+  // Don't let unit tests try to hit the network.
+  static bool avoid_bitmap_fetching_for_test_;
+
+  // Pointer to the ChromeNotifierService.  Its lifetime is controlled by the
+  // ChromeNotifierService itself, which will zero out the pointer when it is
+  // destroyed.
+  ChromeNotifierService* chrome_notifier_service_;
+
   friend class SyncedNotificationAppInfoServiceTest;
   FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoServiceTest,
                            MergeDataAndStartSyncingTest);
@@ -112,6 +162,8 @@
   FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoServiceTest,
                            FindSyncedNotificationAppInfoByNameTest);
   FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoServiceTest,
+                           FindSyncedNotificationAppInfoByNameTestTest);
+  FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoServiceTest,
                            FreeSyncedNotificationAppInfoByNameTest);
   FRIEND_TEST_ALL_PREFIXES(SyncedNotificationAppInfoServiceTest,
                            CreateSyncedNotificationAppInfoFromProtobufTest);
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_unittest.cc b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_unittest.cc
index ef9658e..9988229 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_service_unittest.cc
@@ -4,10 +4,11 @@
 
 #include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h"
 
+#include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/test_browser_thread.h"
 #include "sync/api/fake_sync_change_processor.h"
 #include "sync/api/sync_change.h"
 #include "sync/api/sync_change_processor.h"
@@ -26,18 +27,6 @@
 using notifier::SyncedNotificationAppInfoService;
 using sync_pb::SyncedNotificationAppInfoSpecifics;
 
-namespace {
-const char kSendingService1Name[] = "TestService1";
-const char kSendingService2Name[] = "TestService2";
-const char kSendingService3Name[] = "TestService3";
-const char kAppId1[] = "service1_appid1";
-const char kAppId2[] = "service1_appid2";
-const char kAppId3[] = "service1_appid3";
-const char kAppId4[] = "service2_appid1";
-const char kAppId5[] = "service2_appid2";
-const char kTestIconUrl[] = "https://www.google.com/someicon.png";
-}  // namespace
-
 namespace notifier {
 
 // Extract app_info id from syncer::SyncData.
@@ -114,29 +103,29 @@
     // Create the app_info struct, setting the settings display name.
 
     // The sending_service_infos_ list will take ownership of this pointer.
-    SyncedNotificationAppInfo* test_item1 =
-        new SyncedNotificationAppInfo(kSendingService1Name);
+    SyncedNotificationAppInfo* test_item1 = new SyncedNotificationAppInfo(
+        NULL, kSendingService1Name, app_info_service);
 
     // Add some App IDs.
     test_item1->AddAppId(kAppId1);
     test_item1->AddAppId(kAppId2);
 
     // Set this icon GURL.
-    test_item1->SetSettingsIcon(GURL(kTestIconUrl));
+    test_item1->SetSettingsURLs(GURL(kTestIconUrl), GURL());
 
     // Add to the list.
     app_info_service->sending_service_infos_.push_back(test_item1);
 
     // Add a second test item for another service.
-    SyncedNotificationAppInfo* test_item2 =
-        new SyncedNotificationAppInfo(kSendingService2Name);
+    SyncedNotificationAppInfo* test_item2 = new SyncedNotificationAppInfo(
+        NULL, kSendingService2Name, app_info_service);
 
     // Add some App IDs.
     test_item2->AddAppId(kAppId4);
     test_item2->AddAppId(kAppId5);
 
     // Set thi icon GURL.
-    test_item2->SetSettingsIcon(GURL(kTestIconUrl));
+    test_item2->SetSettingsURLs(GURL(kTestIconUrl), GURL());
 
     // Add to the list.
     app_info_service->sending_service_infos_.push_back(test_item2);
@@ -225,7 +214,6 @@
  private:
   scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
   scoped_ptr<syncer::SyncChangeProcessor> sync_processor_delegate_;
-  content::TestBrowserThreadBundle thread_bundle_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncedNotificationAppInfoServiceTest);
 };
@@ -248,6 +236,7 @@
 TEST_F(SyncedNotificationAppInfoServiceTest, ProcessSyncChangesEmptyModel) {
   // We initially have no data.
   SyncedNotificationAppInfoService app_info_service(profile_.get());
+  app_info_service.set_avoid_bitmap_fetching_for_test(true);
 
   // Set up an ADD.
   SyncChangeList changes;
@@ -274,6 +263,7 @@
 // Process sync changes when there is local data.
 TEST_F(SyncedNotificationAppInfoServiceTest, ProcessSyncChangesNonEmptyModel) {
     SyncedNotificationAppInfoService app_info_service(profile_.get());
+    app_info_service.set_avoid_bitmap_fetching_for_test(true);
 
   // Create some local fake data. We rely on the specific ids set up here.
   AddTestingAppInfosToList(&app_info_service);
@@ -306,6 +296,7 @@
        ProcessIncomingAppInfoProtobufAddTest) {
   // Get an app info service object.
   SyncedNotificationAppInfoService app_info_service(profile_.get());
+  app_info_service.set_avoid_bitmap_fetching_for_test(true);
 
   // Get an app info protobuf.
   sync_pb::SyncedNotificationAppInfo protobuf;
@@ -330,6 +321,7 @@
        ProcessIncomingAppInfoProtobufUpdateTest) {
   // Get an app info service object.
   SyncedNotificationAppInfoService app_info_service(profile_.get());
+  app_info_service.set_avoid_bitmap_fetching_for_test(true);
 
   // Make an app info with the same display name as the first one in the test
   // data.
@@ -368,13 +360,14 @@
 // Test our function that creates a synced notification from a protobuf.
 TEST_F(SyncedNotificationAppInfoServiceTest,
        CreateSyncedNotificationAppInfoFromProtobufTest) {
+  SyncedNotificationAppInfoService app_info_service(profile_.get());
   // Build a protobuf and fill it with data.
   sync_pb::SyncedNotificationAppInfo protobuf;
   FillProtobufWithTestData1(protobuf);
 
   scoped_ptr<SyncedNotificationAppInfo> app_info;
-  app_info = SyncedNotificationAppInfoService::
-      CreateSyncedNotificationAppInfoFromProtobuf(protobuf);
+  app_info =
+      app_info_service.CreateSyncedNotificationAppInfoFromProtobuf(protobuf);
 
   // Ensure the app info class has the fields we expect.
   EXPECT_EQ(std::string(kSendingService1Name),
@@ -384,7 +377,7 @@
   EXPECT_EQ(GURL(std::string(kTestIconUrl)), app_info->settings_icon_url());
 }
 
-// Test our find function.
+// Test our find by sending service name function.
 TEST_F(SyncedNotificationAppInfoServiceTest,
        FindSyncedNotificationAppInfoByNameTest) {
   SyncedNotificationAppInfoService app_info_service(profile_.get());
@@ -404,6 +397,41 @@
   EXPECT_EQ(NULL, found);
 }
 
+// Test our find by AppId function.
+TEST_F(SyncedNotificationAppInfoServiceTest,
+       FindSyncedNotificationAppInfoByAppIdTest) {
+  SyncedNotificationAppInfoService app_info_service(profile_.get());
+
+  AddTestingAppInfosToList(&app_info_service);
+
+  SyncedNotificationAppInfo* found;
+
+  found = app_info_service.FindSyncedNotificationAppInfoByAppId(kAppId1);
+
+  EXPECT_NE(static_cast<SyncedNotificationAppInfo*>(NULL), found);
+  EXPECT_EQ(std::string(kSendingService1Name), found->settings_display_name());
+
+  found = app_info_service.FindSyncedNotificationAppInfoByName(kAppId5);
+  EXPECT_EQ(NULL, found);
+}
+
+// Test our find sending service name by app id function.
+TEST_F(SyncedNotificationAppInfoServiceTest,
+       FindSendingServiceNameFromAppIdTest) {
+  SyncedNotificationAppInfoService app_info_service(profile_.get());
+
+  AddTestingAppInfosToList(&app_info_service);
+
+  std::string found_name;
+
+  found_name = app_info_service.FindSendingServiceNameFromAppId(kAppId1);
+
+  EXPECT_EQ(std::string(kSendingService1Name), found_name);
+
+  found_name = app_info_service.FindSendingServiceNameFromAppId(kAppId6);
+  EXPECT_TRUE(found_name.empty());
+}
+
 // Test our delete function.
 TEST_F(SyncedNotificationAppInfoServiceTest,
        FreeSyncedNotificationAppInfoByNameTest) {
@@ -419,4 +447,18 @@
   EXPECT_EQ(NULL, found);
 }
 
+TEST_F(SyncedNotificationAppInfoServiceTest,
+       GetAllSendingServiceSettingsDataTest) {
+  SyncedNotificationAppInfoService app_info_service(profile_.get());
+
+  AddTestingAppInfosToList(&app_info_service);
+
+  std::vector<SyncedNotificationSendingServiceSettingsData> data;
+  data = app_info_service.GetAllSendingServiceSettingsData();
+
+  EXPECT_EQ(static_cast<unsigned int>(2), data.size());
+  EXPECT_EQ(kSendingService1Name, data[0].settings_display_name);
+  EXPECT_EQ(kSendingService2Name, data[1].settings_display_name);
+}
+
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_unittest.cc b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_unittest.cc
index b648259..71f1553 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_app_info_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_app_info_unittest.cc
@@ -4,8 +4,10 @@
 
 #include <string>
 
+#include "chrome/browser/notifications/sync_notifier/sync_notifier_test_utils.h"
 #include "chrome/browser/notifications/sync_notifier/synced_notification_app_info.h"
-
+#include "chrome/browser/notifications/sync_notifier/synced_notification_app_info_service.h"
+#include "sync/api/sync_error_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
@@ -21,7 +23,7 @@
 typedef testing::Test SyncedNotificationAppInfoTest;
 
 TEST_F(SyncedNotificationAppInfoTest, AddRemoveTest) {
-  SyncedNotificationAppInfo app_info(kTestSendingServiceName);
+  SyncedNotificationAppInfo app_info(NULL, kTestSendingServiceName, NULL);
 
   app_info.AddAppId(kTestAppId1);
 
@@ -37,17 +39,57 @@
 }
 
 TEST_F(SyncedNotificationAppInfoTest, GetAppIdListTest) {
-  SyncedNotificationAppInfo app_info(kTestSendingServiceName);
+  SyncedNotificationAppInfo app_info(NULL, kTestSendingServiceName, NULL);
 
   // Add a few app infos.
   app_info.AddAppId(kTestAppId1);
   app_info.AddAppId(kTestAppId2);
 
-  std::vector<std::string> app_id_list;
-  app_info.GetAppIdList(&app_id_list);
+  std::vector<std::string> app_id_list = app_info.GetAppIdList();
 
   EXPECT_EQ(std::string(kTestAppId1), app_id_list[0]);
   EXPECT_EQ(std::string(kTestAppId2), app_id_list[1]);
 }
 
+TEST_F(SyncedNotificationAppInfoTest, OnFetchCompleteTest) {
+  StubSyncedNotificationAppInfoService
+      stub_synced_notification_app_info_service(NULL);
+  SyncedNotificationAppInfo app_info(
+      NULL,
+      kTestSendingServiceName,
+      &stub_synced_notification_app_info_service);
+
+  app_info.OnFetchComplete();
+
+  // Expect that we reported the fetches all done to the owning service.
+  EXPECT_TRUE(stub_synced_notification_app_info_service.
+              on_bitmap_fetches_done_called());
+
+}
+
+TEST_F(SyncedNotificationAppInfoTest, AreAllBitmapsFetchedTest) {
+  SyncedNotificationAppInfo app_info(NULL, kTestSendingServiceName, NULL);
+
+  // Before we have any images to fetch, we should report all fetching is done.
+  EXPECT_TRUE(app_info.AreAllBitmapsFetched());
+
+  // Add some bitmaps to fetch, we should report fetching is not done.
+  app_info.SetSettingsURLs(GURL(kIconUrl1), GURL(kIconUrl2));
+  EXPECT_FALSE(app_info.AreAllBitmapsFetched());
+
+  // Put a real bitmap into "bitmap".  2x2 bitmap of green 32 bit pixels.
+  SkBitmap bitmap;
+  bitmap.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
+  bitmap.allocPixels();
+  bitmap.eraseColor(SK_ColorGREEN);
+
+  // Now put in one bitmap, we are not done yet.
+  app_info.settings_holder_->OnFetchComplete(GURL(kIconUrl1), &bitmap);
+  EXPECT_FALSE(app_info.AreAllBitmapsFetched());
+
+  // Add a second bitmap, and now we should report done.
+  app_info.settings_holder_->OnFetchComplete(GURL(kIconUrl2), &bitmap);
+  EXPECT_TRUE(app_info.AreAllBitmapsFetched());
+}
+
 }  // namespace notifier
diff --git a/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc b/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc
index 6dd0990..f558fec 100644
--- a/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc
+++ b/chrome/browser/notifications/sync_notifier/synced_notification_unittest.cc
@@ -46,6 +46,9 @@
   // Methods from testing::Test.
 
   virtual void SetUp() OVERRIDE {
+    notification_manager_.reset(new StubNotificationUIManager(GURL(
+        kSyncedNotificationsWelcomeOrigin)));
+
     sync_data1_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
                                  kAppId1, kKey1, kUnread);
     sync_data2_ = CreateSyncData(kTitle2, kText2, kIconUrl2, kImageUrl2,
@@ -58,13 +61,15 @@
     sync_data4_ = CreateSyncData(kTitle1, kText1, kIconUrl1, kImageUrl1,
                                  kAppId1, kKey1, kDismissed);
 
-    notification1_.reset(new SyncedNotification(sync_data1_));
-    notification2_.reset(new SyncedNotification(sync_data2_));
-    notification3_.reset(new SyncedNotification(sync_data3_));
-    notification4_.reset(new SyncedNotification(sync_data4_));
+    notification1_.reset(new SyncedNotification(
+        sync_data1_, NULL, notification_manager_.get()));
+    notification2_.reset(new SyncedNotification(
+        sync_data2_, NULL, notification_manager_.get()));
+    notification3_.reset(new SyncedNotification(
+        sync_data3_, NULL, notification_manager_.get()));
+    notification4_.reset(new SyncedNotification(
+        sync_data4_, NULL, notification_manager_.get()));
 
-    notification_manager_.reset(new StubNotificationUIManager(GURL(
-        kSyncedNotificationsWelcomeOrigin)));
   }
 
   virtual void TearDown() OVERRIDE {
@@ -153,7 +158,6 @@
   EXPECT_EQ(expected_image_url, found_image_url);
 }
 
-// TODO(petewil): test with a multi-line message
 TEST_F(SyncedNotificationTest, GetTextTest) {
   std::string found_text = notification1_->GetText();
   std::string expected_text(kText1);
@@ -242,7 +246,8 @@
 
 TEST_F(SyncedNotificationTest, UpdateTest) {
   scoped_ptr<SyncedNotification> notification5;
-  notification5.reset(new SyncedNotification(sync_data1_));
+  notification5.reset(new SyncedNotification(
+      sync_data1_, NULL, notification_manager()));
 
   // update with the sync data from notification2, and ensure they are equal.
   notification5->Update(sync_data2_);
@@ -257,7 +262,7 @@
     return;
 
   // Call the method under test using the pre-populated data.
-  notification1_->Show(notification_manager(), NULL, NULL);
+  notification1_->Show(NULL);
 
   const Notification notification = notification_manager()->notification();
 
@@ -278,23 +283,24 @@
     return;
 
   // Call the method under test using a dismissed notification.
-  notification4_->Show(notification_manager(), NULL, NULL);
+  notification4_->Show(NULL);
 
   EXPECT_EQ(std::string(kKey1), notification_manager()->dismissed_id());
 }
 
-TEST_F(SyncedNotificationTest, AddBitmapToFetchQueueTest) {
+TEST_F(SyncedNotificationTest, CreateBitmapFetcherTest) {
   scoped_ptr<SyncedNotification> notification6;
-  notification6.reset(new SyncedNotification(sync_data1_));
+  notification6.reset(new SyncedNotification(
+      sync_data1_, NULL, notification_manager()));
 
   // Add two bitmaps to the queue.
-  notification6->AddBitmapToFetchQueue(GURL(kIconUrl1));
-  notification6->AddBitmapToFetchQueue(GURL(kIconUrl2));
+  notification6->CreateBitmapFetcher(GURL(kIconUrl1));
+  notification6->CreateBitmapFetcher(GURL(kIconUrl2));
 
   EXPECT_EQ(GURL(kIconUrl1), notification6->fetchers_[0]->url());
   EXPECT_EQ(GURL(kIconUrl2), notification6->fetchers_[1]->url());
 
-  notification6->AddBitmapToFetchQueue(GURL(kIconUrl2));
+  notification6->CreateBitmapFetcher(GURL(kIconUrl2));
 }
 
 TEST_F(SyncedNotificationTest, OnFetchCompleteTest) {
@@ -305,10 +311,10 @@
   notification1_->notification_manager_ = notification_manager();
 
   // Add the bitmaps to the queue for us to match up.
-  notification1_->AddBitmapToFetchQueue(GURL(kIconUrl1));
-  notification1_->AddBitmapToFetchQueue(GURL(kImageUrl1));
-  notification1_->AddBitmapToFetchQueue(GURL(kButtonOneIconUrl));
-  notification1_->AddBitmapToFetchQueue(GURL(kButtonTwoIconUrl));
+  notification1_->CreateBitmapFetcher(GURL(kIconUrl1));
+  notification1_->CreateBitmapFetcher(GURL(kImageUrl1));
+  notification1_->CreateBitmapFetcher(GURL(kButtonOneIconUrl));
+  notification1_->CreateBitmapFetcher(GURL(kButtonTwoIconUrl));
 
   // Put some realistic looking bitmap data into the url_fetcher.
   SkBitmap bitmap;
@@ -349,7 +355,7 @@
   //     image, notification1_->GetAppIconBitmap()));
 }
 
-
+// TODO(petewil): Empty bitmap should count as a successful fetch.
 TEST_F(SyncedNotificationTest, EmptyBitmapTest) {
   if (!UseRichNotifications())
     return;
@@ -358,10 +364,10 @@
   notification1_->notification_manager_ = notification_manager();
 
   // Add the bitmaps to the queue for us to match up.
-  notification1_->AddBitmapToFetchQueue(GURL(kIconUrl1));
-  notification1_->AddBitmapToFetchQueue(GURL(kImageUrl1));
-  notification1_->AddBitmapToFetchQueue(GURL(kButtonOneIconUrl));
-  notification1_->AddBitmapToFetchQueue(GURL(kButtonTwoIconUrl));
+  notification1_->CreateBitmapFetcher(GURL(kIconUrl1));
+  notification1_->CreateBitmapFetcher(GURL(kImageUrl1));
+  notification1_->CreateBitmapFetcher(GURL(kButtonOneIconUrl));
+  notification1_->CreateBitmapFetcher(GURL(kButtonTwoIconUrl));
 
   // Put some realistic looking bitmap data into the url_fetcher.
   SkBitmap bitmap;
@@ -399,6 +405,50 @@
       base::UTF16ToUTF8(notification_manager()->notification().message()));
 }
 
+TEST_F(SyncedNotificationTest, ShowIfNewlyEnabledTest) {
+  if (!UseRichNotifications())
+    return;
+
+  // Call the method using the wrong app id, nothing should get shown.
+  notification1_->ShowAllForAppId(NULL, kAppId2);
+
+  // Ensure no notification was generated and shown.
+  const Notification notification1 = notification_manager()->notification();
+  EXPECT_EQ(std::string(), base::UTF16ToUTF8(notification1.replace_id()));
+
+  // Call the method under test using the pre-populated data.
+  notification1_->ShowAllForAppId(NULL, kAppId1);
+
+  const Notification notification2 = notification_manager()->notification();
+
+  // Check the base fields of the notification.
+  EXPECT_EQ(message_center::NOTIFICATION_TYPE_IMAGE, notification2.type());
+  EXPECT_EQ(std::string(kTitle1), base::UTF16ToUTF8(notification2.title()));
+  EXPECT_EQ(std::string(kText1), base::UTF16ToUTF8(notification2.message()));
+  EXPECT_EQ(std::string(kExpectedOriginUrl), notification2.origin_url().spec());
+  EXPECT_EQ(std::string(kKey1), base::UTF16ToUTF8(notification2.replace_id()));
+
+  EXPECT_EQ(kFakeCreationTime, notification2.timestamp().ToDoubleT());
+  EXPECT_EQ(kNotificationPriority, notification2.priority());
+}
+
+TEST_F(SyncedNotificationTest, HideIfNewlyRemovedTest) {
+  if (!UseRichNotifications())
+    return;
+
+  // Add the notification to the notification manger, so it exists before we
+  // we remove it.
+  notification1_->Show(NULL);
+  const Notification* found1 = notification_manager()->FindById(kKey1);
+  EXPECT_NE(reinterpret_cast<Notification*>(NULL), found1);
+
+  // Call the method under test using the pre-populated data.
+  notification1_->HideAllForAppId(kAppId1);
+
+  // Ensure the notification was removed from the notification manager
+  EXPECT_EQ(std::string(kKey1), notification_manager()->dismissed_id());
+}
+
 // TODO(petewil): Add a test for a notification being read and or deleted.
 
 }  // namespace notifier
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.cc b/chrome/browser/password_manager/native_backend_gnome_x.cc
index b3becf1..ca3059b 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x.cc
@@ -495,19 +495,9 @@
 
 }  // namespace
 
-NativeBackendGnome::NativeBackendGnome(LocalProfileId id, PrefService* prefs)
-    : profile_id_(id), prefs_(prefs) {
-  // TODO(mdm): after a few more releases, remove the code which is now dead due
-  // to the true || here, and simplify this code. We don't do it yet to make it
-  // easier to revert if necessary.
-  if (true || PasswordStoreX::PasswordsUseLocalProfileId(prefs)) {
-    app_string_ = GetProfileSpecificAppString();
-    // We already did the migration previously. Don't try again.
-    migrate_tried_ = true;
-  } else {
-    app_string_ = kGnomeKeyringAppString;
-    migrate_tried_ = false;
-  }
+NativeBackendGnome::NativeBackendGnome(LocalProfileId id)
+    : profile_id_(id) {
+  app_string_ = GetProfileSpecificAppString();
 }
 
 NativeBackendGnome::~NativeBackendGnome() {
@@ -530,9 +520,6 @@
                << gnome_keyring_result_to_message(result);
     return false;
   }
-  // Successful write. Try migration if necessary.
-  if (!migrate_tried_)
-    MigrateToProfileSpecificLogins();
   return true;
 }
 
@@ -562,11 +549,6 @@
                    << " matching logins already! Will replace only the first.";
     }
 
-    // We try migration before updating the existing logins, since otherwise
-    // we'd do it after making some but not all of the changes below.
-    if (forms.size() > 0 && !migrate_tried_)
-      MigrateToProfileSpecificLogins();
-
     RemoveLogin(*forms[0]);
     for (size_t i = 0; i < forms.size(); ++i)
       delete forms[i];
@@ -595,11 +577,6 @@
     return false;
   }
 
-  // We try migration before updating the existing logins, since otherwise
-  // we'd do it after making some but not all of the changes below.
-  if (forms.size() > 0 && !migrate_tried_)
-    MigrateToProfileSpecificLogins();
-
   bool ok = true;
   for (size_t i = 0; i < forms.size(); ++i) {
     if (forms[i]->action != form.action ||
@@ -637,11 +614,6 @@
                  << gnome_keyring_result_to_message(result);
     return false;
   }
-  // Successful write. Try migration if necessary. Note that presumably if we've
-  // been asked to delete a login, it's because we returned it previously; thus,
-  // this will probably never happen since we'd have already tried migration.
-  if (!migrate_tried_)
-    MigrateToProfileSpecificLogins();
   return true;
 }
 
@@ -655,7 +627,6 @@
   PasswordFormList forms;
   if (!GetAllLogins(&forms))
     return false;
-  // No need to try migration here: GetAllLogins() does it.
 
   for (size_t i = 0; i < forms.size(); ++i) {
     if (delete_begin <= forms[i]->date_created &&
@@ -684,9 +655,6 @@
                << gnome_keyring_result_to_message(result);
     return false;
   }
-  // Successful read of actual data. Try migration if necessary.
-  if (!migrate_tried_)
-    MigrateToProfileSpecificLogins();
   return true;
 }
 
@@ -699,7 +667,6 @@
   PasswordFormList all_forms;
   if (!GetAllLogins(&all_forms))
     return false;
-  // No need to try migration here: GetAllLogins() does it.
 
   forms->reserve(forms->size() + all_forms.size());
   for (size_t i = 0; i < all_forms.size(); ++i) {
@@ -741,9 +708,6 @@
                << gnome_keyring_result_to_message(result);
     return false;
   }
-  // Successful read of actual data. Try migration if necessary.
-  if (!migrate_tried_)
-    MigrateToProfileSpecificLogins();
   return true;
 }
 
@@ -761,9 +725,6 @@
                << gnome_keyring_result_to_message(result);
     return false;
   }
-  // Successful read of actual data. Try migration if necessary.
-  if (!migrate_tried_)
-    MigrateToProfileSpecificLogins();
   return true;
 }
 
@@ -773,44 +734,3 @@
   // for nothing. Now we use it to distinguish passwords for different profiles.
   return base::StringPrintf("%s-%d", kGnomeKeyringAppString, profile_id_);
 }
-
-void NativeBackendGnome::MigrateToProfileSpecificLogins() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-
-  DCHECK(!migrate_tried_);
-  DCHECK_EQ(app_string_, kGnomeKeyringAppString);
-
-  // Record the fact that we've attempted migration already right away, so that
-  // we don't get recursive calls back to MigrateToProfileSpecificLogins().
-  migrate_tried_ = true;
-
-  // First get all the logins, using the old app string.
-  PasswordFormList forms;
-  if (!GetAllLogins(&forms))
-    return;
-
-  // Now switch to a profile-specific app string.
-  app_string_ = GetProfileSpecificAppString();
-
-  // Try to add all the logins with the new app string.
-  bool ok = true;
-  for (size_t i = 0; i < forms.size(); ++i) {
-    if (!RawAddLogin(*forms[i]))
-      ok = false;
-    delete forms[i];
-  }
-
-  if (ok) {
-    // All good! Keep the new app string and set a persistent pref.
-    // NOTE: We explicitly don't delete the old passwords yet. They are
-    // potentially shared with other profiles and other user data dirs!
-    // Each other profile must be able to migrate the shared data as well,
-    // so we must leave it alone. After a few releases, we'll add code to
-    // delete them, and eventually remove this migration code.
-    // TODO(mdm): follow through with the plan above.
-    PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_);
-  } else {
-    // We failed to migrate for some reason. Use the old app string.
-    app_string_ = kGnomeKeyringAppString;
-  }
-}
diff --git a/chrome/browser/password_manager/native_backend_gnome_x.h b/chrome/browser/password_manager/native_backend_gnome_x.h
index e115462..925eb09 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x.h
+++ b/chrome/browser/password_manager/native_backend_gnome_x.h
@@ -15,8 +15,6 @@
 #include "chrome/browser/password_manager/password_store_x.h"
 #include "chrome/browser/profiles/profile.h"
 
-class PrefService;
-
 namespace autofill {
 struct PasswordForm;
 }
@@ -76,7 +74,7 @@
 class NativeBackendGnome : public PasswordStoreX::NativeBackend,
                            public GnomeKeyringLoader {
  public:
-  NativeBackendGnome(LocalProfileId id, PrefService* prefs);
+  explicit NativeBackendGnome(LocalProfileId id);
 
   virtual ~NativeBackendGnome();
 
@@ -109,21 +107,12 @@
   // Generates a profile-specific app string based on profile_id_.
   std::string GetProfileSpecificAppString() const;
 
-  // Migrates non-profile-specific logins to be profile-specific.
-  void MigrateToProfileSpecificLogins();
-
   // The local profile id, used to generate the app string.
   const LocalProfileId profile_id_;
 
-  // The pref service to use for persistent migration settings.
-  PrefService* prefs_;
-
   // The app string, possibly based on the local profile id.
   std::string app_string_;
 
-  // True once MigrateToProfileSpecificLogins() has been attempted.
-  bool migrate_tried_;
-
   DISALLOW_COPY_AND_ASSIGN(NativeBackendGnome);
 };
 
diff --git a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
index 7bd8e13..bdc9dfa 100644
--- a/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_gnome_x_unittest.cc
@@ -406,7 +406,7 @@
     ASSERT_TRUE(helper.IsMatchingEnabled())
         << "PSL matching needs to be enabled.";
 
-    NativeBackendGnome backend(321, profile_.GetPrefs());
+    NativeBackendGnome backend(321);
     backend.Init();
 
     BrowserThread::PostTask(
@@ -445,8 +445,6 @@
   content::TestBrowserThread ui_thread_;
   content::TestBrowserThread db_thread_;
 
-  TestingProfile profile_;
-
   // Provide some test forms to avoid having to set them up in each test.
   PasswordForm form_google_;
   PasswordForm form_facebook_;
@@ -454,10 +452,7 @@
 };
 
 TEST_F(NativeBackendGnomeTest, BasicAddLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendGnome backend(42, profile_.GetPrefs());
+  NativeBackendGnome backend(42);
   backend.Init();
 
   BrowserThread::PostTask(
@@ -473,10 +468,7 @@
 }
 
 TEST_F(NativeBackendGnomeTest, BasicListLogins) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendGnome backend(42, profile_.GetPrefs());
+  NativeBackendGnome backend(42);
   backend.Init();
 
   BrowserThread::PostTask(
@@ -525,10 +517,7 @@
 }
 
 TEST_F(NativeBackendGnomeTest, BasicUpdateLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendGnome backend(42, profile_.GetPrefs());
+  NativeBackendGnome backend(42);
   backend.Init();
 
   // First add google login.
@@ -561,10 +550,7 @@
 }
 
 TEST_F(NativeBackendGnomeTest, BasicRemoveLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendGnome backend(42, profile_.GetPrefs());
+  NativeBackendGnome backend(42);
   backend.Init();
 
   BrowserThread::PostTask(
@@ -589,10 +575,7 @@
 }
 
 TEST_F(NativeBackendGnomeTest, RemoveNonexistentLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendGnome backend(42, profile_.GetPrefs());
+  NativeBackendGnome backend(42);
   backend.Init();
 
   // First add an unrelated login.
@@ -633,10 +616,7 @@
 }
 
 TEST_F(NativeBackendGnomeTest, AddDuplicateLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendGnome backend(42, profile_.GetPrefs());
+  NativeBackendGnome backend(42);
   backend.Init();
 
   BrowserThread::PostTask(
@@ -656,10 +636,7 @@
 }
 
 TEST_F(NativeBackendGnomeTest, ListLoginsAppends) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendGnome backend(42, profile_.GetPrefs());
+  NativeBackendGnome backend(42);
   backend.Init();
 
   BrowserThread::PostTask(
@@ -691,337 +668,4 @@
     CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome-42");
 }
 
-// TODO(mdm): add more basic (i.e. non-migration) tests here at some point.
-
-TEST_F(NativeBackendGnomeTest, DISABLED_MigrateOneLogin) {
-  // Reject attempts to migrate so we can populate the store.
-  mock_keyring_reject_local_ids = true;
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
-                   base::Unretained(&backend), form_google_));
-
-    // Make sure we can get the form back even when migration is failing.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  EXPECT_EQ(1u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-
-  // Now allow the migration.
-  mock_keyring_reject_local_ids = false;
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    // This should not trigger migration because there will be no results.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendGnome::GetBlacklistLogins),
-                   base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Check that we got nothing back.
-    EXPECT_EQ(0u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  // Check that the keyring is unmodified.
-  EXPECT_EQ(1u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-
-  // Check that we haven't set the persistent preference.
-  EXPECT_FALSE(
-      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  EXPECT_EQ(2u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-  if (mock_keyring_items.size() > 1)
-    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
-
-  // Check that we have set the persistent preference.
-  EXPECT_TRUE(
-      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
-}
-
-TEST_F(NativeBackendGnomeTest, DISABLED_MigrateToMultipleProfiles) {
-  // Reject attempts to migrate so we can populate the store.
-  mock_keyring_reject_local_ids = true;
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
-                   base::Unretained(&backend), form_google_));
-
-    RunBothThreads();
-  }
-
-  EXPECT_EQ(1u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-
-  // Now allow the migration.
-  mock_keyring_reject_local_ids = false;
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  EXPECT_EQ(2u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-  if (mock_keyring_items.size() > 1)
-    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
-
-  // Check that we have set the persistent preference.
-  EXPECT_TRUE(
-      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
-
-  // Normally we'd actually have a different profile. But in the test just reset
-  // the profile's persistent pref; we pass in the local profile id anyway.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false);
-
-  {
-    NativeBackendGnome backend(24, profile_.GetPrefs());
-    backend.Init();
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  EXPECT_EQ(3u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-  if (mock_keyring_items.size() > 1)
-    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
-  if (mock_keyring_items.size() > 2)
-    CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24");
-}
-
-TEST_F(NativeBackendGnomeTest, DISABLED_NoMigrationWithPrefSet) {
-  // Reject attempts to migrate so we can populate the store.
-  mock_keyring_reject_local_ids = true;
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
-                   base::Unretained(&backend), form_google_));
-
-    RunBothThreads();
-  }
-
-  EXPECT_EQ(1u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-
-  // Now allow migration, but also pretend that the it has already taken place.
-  mock_keyring_reject_local_ids = false;
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    // Trigger the migration by adding a new login.
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
-                   base::Unretained(&backend), form_isc_));
-
-    // Look up all logins; we expect only the one we added.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Quick check that we got the right thing back.
-    EXPECT_EQ(1u, form_list.size());
-    if (form_list.size() > 0)
-      EXPECT_EQ(form_isc_.signon_realm, form_list[0]->signon_realm);
-    STLDeleteElements(&form_list);
-  }
-
-  EXPECT_EQ(2u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-  if (mock_keyring_items.size() > 1)
-    CheckMockKeyringItem(&mock_keyring_items[1], form_isc_, "chrome-42");
-}
-
-TEST_F(NativeBackendGnomeTest, DISABLED_DeleteMigratedPasswordIsIsolated) {
-  // Reject attempts to migrate so we can populate the store.
-  mock_keyring_reject_local_ids = true;
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendGnome::AddLogin),
-                   base::Unretained(&backend), form_google_));
-
-    RunBothThreads();
-  }
-
-  EXPECT_EQ(1u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-
-  // Now allow the migration.
-  mock_keyring_reject_local_ids = false;
-
-  {
-    NativeBackendGnome backend(42, profile_.GetPrefs());
-    backend.Init();
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  EXPECT_EQ(2u, mock_keyring_items.size());
-  if (mock_keyring_items.size() > 0)
-    CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-  if (mock_keyring_items.size() > 1)
-    CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
-
-  // Check that we have set the persistent preference.
-  EXPECT_TRUE(
-      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
-
-  // Normally we'd actually have a different profile. But in the test just reset
-  // the profile's persistent pref; we pass in the local profile id anyway.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false);
-
-  {
-    NativeBackendGnome backend(24, profile_.GetPrefs());
-    backend.Init();
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendGnome::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunBothThreads();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-
-    // There should be three passwords now.
-    EXPECT_EQ(3u, mock_keyring_items.size());
-    if (mock_keyring_items.size() > 0)
-      CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-    if (mock_keyring_items.size() > 1)
-      CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
-    if (mock_keyring_items.size() > 2)
-      CheckMockKeyringItem(&mock_keyring_items[2], form_google_, "chrome-24");
-
-    // Now delete the password from this second profile.
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendGnome::RemoveLogin),
-                   base::Unretained(&backend), form_google_));
-
-    RunBothThreads();
-
-    // The other two copies of the password in different profiles should remain.
-    EXPECT_EQ(2u, mock_keyring_items.size());
-    if (mock_keyring_items.size() > 0)
-      CheckMockKeyringItem(&mock_keyring_items[0], form_google_, "chrome");
-    if (mock_keyring_items.size() > 1)
-      CheckMockKeyringItem(&mock_keyring_items[1], form_google_, "chrome-42");
-  }
-}
+// TODO(mdm): add more basic tests here at some point.
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.cc b/chrome/browser/password_manager/native_backend_kwallet_x.cc
index 79f4a42..03cecfe 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x.cc
+++ b/chrome/browser/password_manager/native_backend_kwallet_x.cc
@@ -102,23 +102,11 @@
 
 }  // namespace
 
-NativeBackendKWallet::NativeBackendKWallet(LocalProfileId id,
-                                           PrefService* prefs)
+NativeBackendKWallet::NativeBackendKWallet(LocalProfileId id)
     : profile_id_(id),
-      prefs_(prefs),
       kwallet_proxy_(NULL),
       app_name_(l10n_util::GetStringUTF8(IDS_PRODUCT_NAME)) {
-  // TODO(mdm): after a few more releases, remove the code which is now dead due
-  // to the true || here, and simplify this code. We don't do it yet to make it
-  // easier to revert if necessary.
-  if (true || PasswordStoreX::PasswordsUseLocalProfileId(prefs)) {
-    folder_name_ = GetProfileSpecificFolderName();
-    // We already did the migration previously. Don't try again.
-    migrate_tried_ = true;
-  } else {
-    folder_name_ = kKWalletFolder;
-    migrate_tried_ = false;
-  }
+  folder_name_ = GetProfileSpecificFolderName();
 }
 
 NativeBackendKWallet::~NativeBackendKWallet() {
@@ -926,10 +914,6 @@
     }
   }
 
-  // Successful initialization. Try migration if necessary.
-  if (!migrate_tried_)
-    MigrateToProfileSpecificLogins();
-
   return handle;
 }
 
@@ -938,59 +922,3 @@
   // Now we use it to distinguish passwords for different profiles.
   return base::StringPrintf("%s (%d)", kKWalletFolder, profile_id_);
 }
-
-void NativeBackendKWallet::MigrateToProfileSpecificLogins() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-
-  DCHECK(!migrate_tried_);
-  DCHECK_EQ(folder_name_, kKWalletFolder);
-
-  // Record the fact that we've attempted migration already right away, so that
-  // we don't get recursive calls back to MigrateToProfileSpecificLogins().
-  migrate_tried_ = true;
-
-  // First get all the logins, using the old folder name.
-  int wallet_handle = WalletHandle();
-  if (wallet_handle == kInvalidKWalletHandle)
-    return;
-  PasswordFormList forms;
-  if (!GetAllLogins(&forms, wallet_handle))
-    return;
-
-  // Now switch to a profile-specific folder name.
-  folder_name_ = GetProfileSpecificFolderName();
-
-  // Try to add all the logins with the new folder name.
-  // This could be done more efficiently by grouping by signon realm and using
-  // SetLoginsList(), but we do this for simplicity since it is only done once.
-  // Note, however, that we do need another call to WalletHandle() to create
-  // this folder if necessary.
-  bool ok = true;
-  for (size_t i = 0; i < forms.size(); ++i) {
-    if (!AddLogin(*forms[i]))
-      ok = false;
-    delete forms[i];
-  }
-  if (forms.empty()) {
-    // If there were no logins to migrate, we do an extra call to WalletHandle()
-    // for its side effect of attempting to create the profile-specific folder.
-    // This is not strictly necessary, but it's safe and helps in testing.
-    wallet_handle = WalletHandle();
-    if (wallet_handle == kInvalidKWalletHandle)
-      ok = false;
-  }
-
-  if (ok) {
-    // All good! Keep the new app string and set a persistent pref.
-    // NOTE: We explicitly don't delete the old passwords yet. They are
-    // potentially shared with other profiles and other user data dirs!
-    // Each other profile must be able to migrate the shared data as well,
-    // so we must leave it alone. After a few releases, we'll add code to
-    // delete them, and eventually remove this migration code.
-    // TODO(mdm): follow through with the plan above.
-    PasswordStoreX::SetPasswordsUseLocalProfileId(prefs_);
-  } else {
-    // We failed to migrate for some reason. Use the old folder name.
-    folder_name_ = kKWalletFolder;
-  }
-}
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x.h b/chrome/browser/password_manager/native_backend_kwallet_x.h
index b50f90e..e39ee04 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x.h
+++ b/chrome/browser/password_manager/native_backend_kwallet_x.h
@@ -16,7 +16,6 @@
 
 class Pickle;
 class PickleIterator;
-class PrefService;
 
 namespace autofill {
 struct PasswordForm;
@@ -34,7 +33,7 @@
 // NativeBackend implementation using KWallet.
 class NativeBackendKWallet : public PasswordStoreX::NativeBackend {
  public:
-  NativeBackendKWallet(LocalProfileId id, PrefService* prefs);
+  explicit NativeBackendKWallet(LocalProfileId id);
 
   virtual ~NativeBackendKWallet();
 
@@ -131,21 +130,12 @@
   // Generates a profile-specific folder name based on profile_id_.
   std::string GetProfileSpecificFolderName() const;
 
-  // Migrates non-profile-specific logins to be profile-specific.
-  void MigrateToProfileSpecificLogins();
-
   // The local profile id, used to generate the folder name.
   const LocalProfileId profile_id_;
 
-  // The pref service to use for persistent migration settings.
-  PrefService* prefs_;
-
   // The KWallet folder name, possibly based on the local profile id.
   std::string folder_name_;
 
-  // True once MigrateToProfileSpecificLogins() has been attempted.
-  bool migrate_tried_;
-
   // DBus handle for communication with klauncher and kwalletd.
   scoped_refptr<dbus::Bus> session_bus_;
   // Object proxy for kwalletd. We do not own this.
diff --git a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
index 650f628..4465094 100644
--- a/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
+++ b/chrome/browser/password_manager/native_backend_kwallet_x_unittest.cc
@@ -126,8 +126,8 @@
 // Subclass NativeBackendKWallet to promote some members to public for testing.
 class NativeBackendKWalletStub : public NativeBackendKWallet {
  public:
-  NativeBackendKWalletStub(LocalProfileId id, PrefService* pref_service)
-      :  NativeBackendKWallet(id, pref_service) {
+  explicit NativeBackendKWalletStub(LocalProfileId id)
+      :  NativeBackendKWallet(id) {
   }
   using NativeBackendKWallet::InitWithBus;
   using NativeBackendKWallet::kInvalidKWalletHandle;
@@ -226,7 +226,6 @@
   base::MessageLoopForUI message_loop_;
   content::TestBrowserThread ui_thread_;
   content::TestBrowserThread db_thread_;
-  TestingProfile profile_;
 
   scoped_refptr<dbus::MockBus> mock_session_bus_;
   scoped_refptr<dbus::MockObjectProxy> mock_klauncher_proxy_;
@@ -472,14 +471,14 @@
 }
 
 TEST_F(NativeBackendKWalletTest, NotEnabled) {
-  NativeBackendKWalletStub kwallet(42, profile_.GetPrefs());
+  NativeBackendKWalletStub kwallet(42);
   kwallet_enabled_ = false;
   EXPECT_FALSE(kwallet.InitWithBus(mock_session_bus_));
   EXPECT_FALSE(klauncher_contacted_);
 }
 
 TEST_F(NativeBackendKWalletTest, NotRunnable) {
-  NativeBackendKWalletStub kwallet(42, profile_.GetPrefs());
+  NativeBackendKWalletStub kwallet(42);
   kwallet_runnable_ = false;
   kwallet_running_ = false;
   EXPECT_FALSE(kwallet.InitWithBus(mock_session_bus_));
@@ -487,7 +486,7 @@
 }
 
 TEST_F(NativeBackendKWalletTest, NotRunningOrEnabled) {
-  NativeBackendKWalletStub kwallet(42, profile_.GetPrefs());
+  NativeBackendKWalletStub kwallet(42);
   kwallet_running_ = false;
   kwallet_enabled_ = false;
   EXPECT_FALSE(kwallet.InitWithBus(mock_session_bus_));
@@ -495,23 +494,20 @@
 }
 
 TEST_F(NativeBackendKWalletTest, NotRunning) {
-  NativeBackendKWalletStub kwallet(42, profile_.GetPrefs());
+  NativeBackendKWalletStub kwallet(42);
   kwallet_running_ = false;
   EXPECT_TRUE(kwallet.InitWithBus(mock_session_bus_));
   EXPECT_TRUE(klauncher_contacted_);
 }
 
 TEST_F(NativeBackendKWalletTest, BasicStartup) {
-  NativeBackendKWalletStub kwallet(42, profile_.GetPrefs());
+  NativeBackendKWalletStub kwallet(42);
   EXPECT_TRUE(kwallet.InitWithBus(mock_session_bus_));
   EXPECT_FALSE(klauncher_contacted_);
 }
 
 TEST_F(NativeBackendKWalletTest, BasicAddLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendKWalletStub backend(42, profile_.GetPrefs());
+  NativeBackendKWalletStub backend(42);
   EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
 
   BrowserThread::PostTask(
@@ -531,10 +527,7 @@
 }
 
 TEST_F(NativeBackendKWalletTest, BasicListLogins) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendKWalletStub backend(42, profile_.GetPrefs());
+  NativeBackendKWalletStub backend(42);
   EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
 
   BrowserThread::PostTask(
@@ -565,10 +558,7 @@
 }
 
 TEST_F(NativeBackendKWalletTest, BasicRemoveLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendKWalletStub backend(42, profile_.GetPrefs());
+  NativeBackendKWalletStub backend(42);
   EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
 
   BrowserThread::PostTask(
@@ -598,10 +588,7 @@
 }
 
 TEST_F(NativeBackendKWalletTest, RemoveNonexistentLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendKWalletStub backend(42, profile_.GetPrefs());
+  NativeBackendKWalletStub backend(42);
   EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
 
   // First add an unrelated login.
@@ -644,10 +631,7 @@
 }
 
 TEST_F(NativeBackendKWalletTest, AddDuplicateLogin) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendKWalletStub backend(42, profile_.GetPrefs());
+  NativeBackendKWalletStub backend(42);
   EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
 
   BrowserThread::PostTask(
@@ -671,10 +655,7 @@
 }
 
 TEST_F(NativeBackendKWalletTest, ListLoginsAppends) {
-  // Pretend that the migration has already taken place.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  NativeBackendKWalletStub backend(42, profile_.GetPrefs());
+  NativeBackendKWalletStub backend(42);
   EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
 
   BrowserThread::PostTask(
@@ -710,324 +691,9 @@
   CheckPasswordForms("Chrome Form Data (42)", expected);
 }
 
-// TODO(mdm): add more basic (i.e. non-migration) tests here at some point.
+// TODO(mdm): add more basic tests here at some point.
 // (For example tests for storing >1 password per realm pickle.)
 
-TEST_F(NativeBackendKWalletTest, DISABLED_MigrateOneLogin) {
-  // Reject attempts to migrate so we can populate the store.
-  wallet_.set_reject_local_folders(true);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin),
-                   base::Unretained(&backend), form_google_));
-
-    // Make sure we can get the form back even when migration is failing.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(
-                &NativeBackendKWalletStub::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunDBThread();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data (42)"));
-
-  std::vector<const PasswordForm*> forms;
-  forms.push_back(&form_google_);
-  ExpectationArray expected;
-  expected.push_back(make_pair(std::string(form_google_.signon_realm), forms));
-  CheckPasswordForms("Chrome Form Data", expected);
-
-  // Now allow the migration.
-  wallet_.set_reject_local_folders(false);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(
-                &NativeBackendKWalletStub::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunDBThread();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  CheckPasswordForms("Chrome Form Data", expected);
-  CheckPasswordForms("Chrome Form Data (42)", expected);
-
-  // Check that we have set the persistent preference.
-  EXPECT_TRUE(
-      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
-}
-
-TEST_F(NativeBackendKWalletTest, DISABLED_MigrateToMultipleProfiles) {
-  // Reject attempts to migrate so we can populate the store.
-  wallet_.set_reject_local_folders(true);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin),
-                   base::Unretained(&backend), form_google_));
-
-    RunDBThread();
-  }
-
-  EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data (42)"));
-
-  std::vector<const PasswordForm*> forms;
-  forms.push_back(&form_google_);
-  ExpectationArray expected;
-  expected.push_back(make_pair(std::string(form_google_.signon_realm), forms));
-  CheckPasswordForms("Chrome Form Data", expected);
-
-  // Now allow the migration.
-  wallet_.set_reject_local_folders(false);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(
-                &NativeBackendKWalletStub::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunDBThread();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  CheckPasswordForms("Chrome Form Data", expected);
-  CheckPasswordForms("Chrome Form Data (42)", expected);
-
-  // Check that we have set the persistent preference.
-  EXPECT_TRUE(
-      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
-
-  // Normally we'd actually have a different profile. But in the test just reset
-  // the profile's persistent pref; we pass in the local profile id anyway.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false);
-
-  {
-    NativeBackendKWalletStub backend(24, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(
-                &NativeBackendKWalletStub::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunDBThread();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  CheckPasswordForms("Chrome Form Data", expected);
-  CheckPasswordForms("Chrome Form Data (42)", expected);
-  CheckPasswordForms("Chrome Form Data (24)", expected);
-}
-
-TEST_F(NativeBackendKWalletTest, DISABLED_NoMigrationWithPrefSet) {
-  // Reject attempts to migrate so we can populate the store.
-  wallet_.set_reject_local_folders(true);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin),
-                   base::Unretained(&backend), form_google_));
-
-    RunDBThread();
-  }
-
-  EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data (42)"));
-
-  std::vector<const PasswordForm*> forms;
-  forms.push_back(&form_google_);
-  ExpectationArray expected;
-  expected.push_back(make_pair(std::string(form_google_.signon_realm), forms));
-  CheckPasswordForms("Chrome Form Data", expected);
-
-  // Now allow migration, but also pretend that the it has already taken place.
-  wallet_.set_reject_local_folders(false);
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    // Trigger the migration by adding a new login.
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(base::IgnoreResult(&NativeBackendKWalletStub::AddLogin),
-                   base::Unretained(&backend), form_isc_));
-
-    // Look up all logins; we expect only the one we added.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(
-                &NativeBackendKWalletStub::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunDBThread();
-
-    // Quick check that we got the right thing back.
-    EXPECT_EQ(1u, form_list.size());
-    if (form_list.size() > 0)
-      EXPECT_EQ(form_isc_.signon_realm, form_list[0]->signon_realm);
-    STLDeleteElements(&form_list);
-  }
-
-  CheckPasswordForms("Chrome Form Data", expected);
-
-  forms[0] = &form_isc_;
-  expected.clear();
-  expected.push_back(make_pair(std::string(form_isc_.signon_realm), forms));
-  CheckPasswordForms("Chrome Form Data (42)", expected);
-}
-
-TEST_F(NativeBackendKWalletTest, DISABLED_DeleteMigratedPasswordIsIsolated) {
-  // Reject attempts to migrate so we can populate the store.
-  wallet_.set_reject_local_folders(true);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendKWalletStub::AddLogin),
-            base::Unretained(&backend), form_google_));
-
-    RunDBThread();
-  }
-
-  EXPECT_FALSE(wallet_.hasFolder("Chrome Form Data (42)"));
-
-  std::vector<const PasswordForm*> forms;
-  forms.push_back(&form_google_);
-  ExpectationArray expected;
-  expected.push_back(make_pair(std::string(form_google_.signon_realm), forms));
-  CheckPasswordForms("Chrome Form Data", expected);
-
-  // Now allow the migration.
-  wallet_.set_reject_local_folders(false);
-
-  {
-    NativeBackendKWalletStub backend(42, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(
-                &NativeBackendKWalletStub::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunDBThread();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-  }
-
-  CheckPasswordForms("Chrome Form Data", expected);
-  CheckPasswordForms("Chrome Form Data (42)", expected);
-
-  // Check that we have set the persistent preference.
-  EXPECT_TRUE(
-      profile_.GetPrefs()->GetBoolean(prefs::kPasswordsUseLocalProfileId));
-
-  // Normally we'd actually have a different profile. But in the test just reset
-  // the profile's persistent pref; we pass in the local profile id anyway.
-  profile_.GetPrefs()->SetBoolean(prefs::kPasswordsUseLocalProfileId, false);
-
-  {
-    NativeBackendKWalletStub backend(24, profile_.GetPrefs());
-    EXPECT_TRUE(backend.InitWithBus(mock_session_bus_));
-
-    // Trigger the migration by looking something up.
-    std::vector<PasswordForm*> form_list;
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(
-                &NativeBackendKWalletStub::GetAutofillableLogins),
-            base::Unretained(&backend), &form_list));
-
-    RunDBThread();
-
-    // Quick check that we got something back.
-    EXPECT_EQ(1u, form_list.size());
-    STLDeleteElements(&form_list);
-
-    // There should be three passwords now.
-    CheckPasswordForms("Chrome Form Data", expected);
-    CheckPasswordForms("Chrome Form Data (42)", expected);
-    CheckPasswordForms("Chrome Form Data (24)", expected);
-
-    // Now delete the password from this second profile.
-    BrowserThread::PostTask(
-        BrowserThread::DB, FROM_HERE,
-        base::Bind(
-            base::IgnoreResult(&NativeBackendKWalletStub::RemoveLogin),
-            base::Unretained(&backend), form_google_));
-
-    RunDBThread();
-
-    // The other two copies of the password in different profiles should remain.
-    CheckPasswordForms("Chrome Form Data", expected);
-    CheckPasswordForms("Chrome Form Data (42)", expected);
-    expected.clear();
-    CheckPasswordForms("Chrome Form Data (24)", expected);
-  }
-}
-
 class NativeBackendKWalletPickleTest : public NativeBackendKWalletTestBase {
  protected:
   void CreateVersion1Pickle(const PasswordForm& form, Pickle* pickle);
diff --git a/chrome/browser/password_manager/password_store_factory.cc b/chrome/browser/password_manager/password_store_factory.cc
index 93ab2a1..7266546 100644
--- a/chrome/browser/password_manager/password_store_factory.cc
+++ b/chrome/browser/password_manager/password_store_factory.cc
@@ -187,7 +187,7 @@
   if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4) {
     // KDE3 didn't use DBus, which our KWallet store uses.
     VLOG(1) << "Trying KWallet for password storage.";
-    backend.reset(new NativeBackendKWallet(id, prefs));
+    backend.reset(new NativeBackendKWallet(id));
     if (backend->Init())
       VLOG(1) << "Using KWallet for password storage.";
     else
@@ -197,7 +197,7 @@
              desktop_env == base::nix::DESKTOP_ENVIRONMENT_XFCE) {
 #if defined(USE_GNOME_KEYRING)
     VLOG(1) << "Trying GNOME keyring for password storage.";
-    backend.reset(new NativeBackendGnome(id, prefs));
+    backend.reset(new NativeBackendGnome(id));
     if (backend->Init())
       VLOG(1) << "Using GNOME keyring for password storage.";
     else
@@ -233,14 +233,12 @@
 void PasswordStoreFactory::RegisterProfilePrefs(
     user_prefs::PrefRegistrySyncable* registry) {
 #if !defined(OS_CHROMEOS) && defined(USE_X11)
+  // Notice that the preprocessor conditions above are exactly those that will
+  // result in using PasswordStoreX in BuildServiceInstanceFor().
   registry->RegisterIntegerPref(
       prefs::kLocalProfileId,
       kInvalidLocalProfileId,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-
-  // Notice that the preprocessor conditions above are exactly those that will
-  // result in using PasswordStoreX in CreatePasswordStore() below.
-  PasswordStoreX::RegisterProfilePrefs(registry);
 #endif
 }
 
diff --git a/chrome/browser/password_manager/password_store_mac.cc b/chrome/browser/password_manager/password_store_mac.cc
index 4c3af35..80ba51d 100644
--- a/chrome/browser/password_manager/password_store_mac.cc
+++ b/chrome/browser/password_manager/password_store_mac.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/mac/security_wrappers.h"
 #include "components/password_manager/core/browser/login_database.h"
 #include "components/password_manager/core/browser/password_store_change.h"
+#include "content/public/browser/browser_thread.h"
 #include "crypto/apple_keychain.h"
 
 using autofill::PasswordForm;
@@ -840,6 +841,7 @@
 
 bool PasswordStoreMac::Init(
     const syncer::SyncableService::StartSyncFlare& flare) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
   thread_.reset(new base::Thread("Chrome_PasswordStore_Thread"));
 
   if (!thread_->Start()) {
@@ -849,6 +851,12 @@
   return PasswordStore::Init(flare);
 }
 
+void PasswordStoreMac::Shutdown() {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  PasswordStore::Shutdown();
+  thread_->Stop();
+}
+
 // Mac stores passwords in the system keychain, which can block for an
 // arbitrarily long time (most notably, it can block on user confirmation
 // from a dialog). Run tasks on a dedicated thread to avoid blocking the DB
diff --git a/chrome/browser/password_manager/password_store_mac.h b/chrome/browser/password_manager/password_store_mac.h
index 15b8005..52f74eb 100644
--- a/chrome/browser/password_manager/password_store_mac.h
+++ b/chrome/browser/password_manager/password_store_mac.h
@@ -36,6 +36,9 @@
   virtual bool Init(
       const syncer::SyncableService::StartSyncFlare& flare) OVERRIDE;
 
+  // Stops |thread_|.
+  virtual void Shutdown() OVERRIDE;
+
  protected:
   virtual ~PasswordStoreMac();
 
diff --git a/chrome/browser/password_manager/password_store_mac_unittest.cc b/chrome/browser/password_manager/password_store_mac_unittest.cc
index c07f635..64d0a3e 100644
--- a/chrome/browser/password_manager/password_store_mac_unittest.cc
+++ b/chrome/browser/password_manager/password_store_mac_unittest.cc
@@ -56,6 +56,27 @@
   base::MessageLoop::current()->Quit();
 }
 
+class TestPasswordStoreMac : public PasswordStoreMac {
+ public:
+  TestPasswordStoreMac(
+      scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner,
+      crypto::AppleKeychain* keychain,
+      LoginDatabase* login_db)
+      : PasswordStoreMac(main_thread_runner,
+                         db_thread_runner,
+                         keychain,
+                         login_db) {
+  }
+
+  using PasswordStoreMac::GetBackgroundTaskRunner;
+
+ private:
+  virtual ~TestPasswordStoreMac() {}
+
+  DISALLOW_COPY_AND_ASSIGN(TestPasswordStoreMac);
+};
+
 }  // namespace
 
 #pragma mark -
@@ -1038,7 +1059,7 @@
 
     keychain_ = new MockAppleKeychain();
 
-    store_ = new PasswordStoreMac(
+    store_ = new TestPasswordStoreMac(
         base::MessageLoopProxy::current(),
         base::MessageLoopProxy::current(),
         keychain_,
@@ -1048,16 +1069,12 @@
 
   virtual void TearDown() {
     store_->Shutdown();
-    base::MessageLoop::current()->PostTask(FROM_HERE,
-                                           base::MessageLoop::QuitClosure());
-    base::MessageLoop::current()->Run();
+    EXPECT_FALSE(store_->GetBackgroundTaskRunner());
   }
 
   void WaitForStoreUpdate() {
     // Do a store-level query to wait for all the operations above to be done.
     MockPasswordStoreConsumer consumer;
-    ON_CALL(consumer, OnGetPasswordStoreResults(_))
-        .WillByDefault(QuitUIMessageLoop());
     EXPECT_CALL(consumer, OnGetPasswordStoreResults(_))
         .WillOnce(DoAll(WithArg<0>(STLDeleteElements0()), QuitUIMessageLoop()));
     store_->GetLogins(PasswordForm(), PasswordStore::ALLOW_PROMPT, &consumer);
@@ -1070,7 +1087,7 @@
 
   MockAppleKeychain* keychain_;  // Owned by store_.
   LoginDatabase* login_db_;  // Owned by store_.
-  scoped_refptr<PasswordStoreMac> store_;
+  scoped_refptr<TestPasswordStoreMac> store_;
   base::ScopedTempDir db_dir_;
 };
 
@@ -1199,8 +1216,6 @@
   m_form.signon_realm = "http://m.facebook.com";
   m_form.origin = GURL("http://m.facebook.com/index.html");
   MockPasswordStoreConsumer consumer;
-  ON_CALL(consumer, OnGetPasswordStoreResults(_))
-      .WillByDefault(QuitUIMessageLoop());
   EXPECT_CALL(consumer, OnGetPasswordStoreResults(_)).WillOnce(DoAll(
       WithArg<0>(Invoke(&consumer, &MockPasswordStoreConsumer::CopyElements)),
       WithArg<0>(STLDeleteElements0()),
diff --git a/chrome/browser/password_manager/password_store_x.cc b/chrome/browser/password_manager/password_store_x.cc
index 40058df..ce44e1b 100644
--- a/chrome/browser/password_manager/password_store_x.cc
+++ b/chrome/browser/password_manager/password_store_x.cc
@@ -260,42 +260,3 @@
   STLDeleteElements(&forms);
   return result;
 }
-
-#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
-// static
-void PasswordStoreX::RegisterProfilePrefs(
-    user_prefs::PrefRegistrySyncable* registry) {
-  // Normally we should be on the UI thread here, but in tests we might not.
-  registry->RegisterBooleanPref(
-      prefs::kPasswordsUseLocalProfileId,
-      // default: passwords don't use local ids
-      false,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-}
-
-// static
-bool PasswordStoreX::PasswordsUseLocalProfileId(PrefService* prefs) {
-  // Normally we should be on the UI thread here, but in tests we might not.
-  return prefs->GetBoolean(prefs::kPasswordsUseLocalProfileId);
-}
-
-namespace {
-// This function is a hack to do something not entirely thread safe: the pref
-// service comes from the UI thread, but it's not ref counted. We keep a pointer
-// to it on the DB thread, and need to invoke a method on the UI thread. This
-// function does that for us without requiring ref counting the pref service.
-// TODO(mdm): Fix this if it becomes a problem. Given that this function will
-// be called once ever per profile, it probably will not cause a problem...
-void UISetPasswordsUseLocalProfileId(PrefService* prefs) {
-  prefs->SetBoolean(prefs::kPasswordsUseLocalProfileId, true);
-}
-}  // anonymous namespace
-
-// static
-void PasswordStoreX::SetPasswordsUseLocalProfileId(PrefService* prefs) {
-  // This method should work on any thread, but we expect the DB thread.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
-  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
-                          base::Bind(&UISetPasswordsUseLocalProfileId, prefs));
-}
-#endif  // !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
diff --git a/chrome/browser/password_manager/password_store_x.h b/chrome/browser/password_manager/password_store_x.h
index 7e5fadb..739a9ac 100644
--- a/chrome/browser/password_manager/password_store_x.h
+++ b/chrome/browser/password_manager/password_store_x.h
@@ -58,19 +58,6 @@
                  LoginDatabase* login_db,
                  NativeBackend* backend);
 
-#if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
-  // Registers the pref setting used for the methods below.
-  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
-
-  // Returns true if passwords have been tagged with the local profile id.
-  static bool PasswordsUseLocalProfileId(PrefService* prefs);
-
-  // Sets the persistent bit indicating that passwords have been tagged with the
-  // local profile id. This cannot be unset; passwords get migrated only once.
-  // The caller promises that |prefs| will not be deleted any time soon.
-  static void SetPasswordsUseLocalProfileId(PrefService* prefs);
-#endif  // !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
-
  private:
   friend class PasswordStoreXTest;
 
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
index 66e655d..d21b43f 100644
--- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -214,7 +214,8 @@
         em::DeviceRegisterRequest::BROWSER;
 #endif
     policy_manager->core()->client()->Register(
-        registration_type, "bogus", std::string(), false, std::string());
+        registration_type, "bogus", std::string(), false, std::string(),
+        std::string());
     run_loop.Run();
     Mock::VerifyAndClearExpectations(&observer);
     policy_manager->core()->client()->RemoveObserver(&observer);
diff --git a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
index 3cf4866..d04499c 100644
--- a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
+++ b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
@@ -129,7 +129,8 @@
         em::DeviceRegisterRequest::BROWSER;
 #endif
     policy_manager()->core()->client()->Register(
-        registration_type, "bogus", std::string(), false, std::string());
+        registration_type, "bogus", std::string(), false, std::string(),
+        std::string());
     run_loop.Run();
     Mock::VerifyAndClearExpectations(&observer);
     policy_manager()->core()->client()->RemoveObserver(&observer);
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
index 37da16f..157491a 100644
--- a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
+++ b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
@@ -266,7 +266,7 @@
       dm_protocol::kChromeExtensionPolicyType, kTestExtension2, kTestPolicy2));
 
   ExtensionTestMessageListener result_listener("ok", true);
-  result_listener.AlsoListenForFailureMessage("fail");
+  result_listener.set_failure_message("fail");
   scoped_refptr<const extensions::Extension> extension2 =
       LoadExtension(kTestExtension2Path);
   ASSERT_TRUE(extension2.get());
diff --git a/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc b/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc
index 0e1cdb4..5ab5a33 100644
--- a/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc
+++ b/chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.cc
@@ -4,12 +4,10 @@
 
 #include "chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.h"
 
-#include "base/command_line.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_invalidator.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/policy/core/common/policy_switches.h"
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h"
 #include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
@@ -42,11 +40,6 @@
 
 KeyedService* UserCloudPolicyInvalidatorFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-        switches::kDisableCloudPolicyPush)) {
-    return NULL;
-  }
-
   Profile* profile = static_cast<Profile*>(context);
 #if defined(OS_CHROMEOS)
   CloudPolicyManager* policy_manager =
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service.cc b/chrome/browser/policy/cloud/user_policy_signin_service.cc
index dd2baa1..95c8bf6 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/signin/signin_manager.h"
 #include "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "google_apis/gaia/gaia_constants.h"
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_android.cc b/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
index f7d27bd..2c98685 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_android.cc
@@ -19,7 +19,7 @@
 #include "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
 #include "components/policy/core/common/policy_switches.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "net/base/network_change_notifier.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "policy/proto/device_management_backend.pb.h"
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_base.cc b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
index db69d5a..1a754f0 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_base.cc
@@ -9,6 +9,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/chrome_content_client.h"
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_ios.mm b/chrome/browser/policy/cloud/user_policy_signin_service_ios.mm
index b5f7baa..08afe5c 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_ios.mm
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_ios.mm
@@ -19,7 +19,7 @@
 #include "components/policy/core/common/cloud/cloud_policy_client_registration_helper.h"
 #include "components/policy/core/common/cloud/user_cloud_policy_manager.h"
 #include "components/policy/core/common/policy_switches.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "net/base/network_change_notifier.h"
 #include "net/url_request/url_request_context_getter.h"
 #include "policy/proto/device_management_backend.pb.h"
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
index 2585b59..b5bc75d 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -15,7 +15,7 @@
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -176,7 +176,7 @@
     builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
                               SigninManagerFake::Build);
     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                              FakeProfileOAuth2TokenServiceWrapper::Build);
+                              BuildFakeProfileOAuth2TokenService);
 
     profile_ = builder.Build().Pass();
     url_factory_.set_remove_fetcher_on_delete(true);
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 3681ae2..20219a1 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -596,7 +596,7 @@
   handlers->AddHandler(make_scoped_ptr<ConfigurationPolicyHandler>(
       new ScreenMagnifierPolicyHandler()));
   handlers->AddHandler(make_scoped_ptr<ConfigurationPolicyHandler>(
-      new LoginScreenPowerManagementPolicyHandler));
+      new LoginScreenPowerManagementPolicyHandler(chrome_schema)));
 
   ScopedVector<ConfigurationPolicyHandler>
       power_management_idle_legacy_policies;
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 5426691..d1f49a3 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -2734,7 +2734,7 @@
 
   void FinishAudioTest() {
     content::MediaStreamRequest request(0, 0, 0,
-                                        request_url_.GetOrigin(),
+                                        request_url_.GetOrigin(), false,
                                         content::MEDIA_DEVICE_ACCESS,
                                         std::string(), std::string(),
                                         content::MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -2753,7 +2753,7 @@
     // TODO(raymes): Test MEDIA_DEVICE_OPEN (Pepper) which grants both webcam
     // and microphone permissions at the same time.
     content::MediaStreamRequest request(0, 0, 0,
-                                        request_url_.GetOrigin(),
+                                        request_url_.GetOrigin(), false,
                                         content::MEDIA_DEVICE_ACCESS,
                                         std::string(),
                                         std::string(),
diff --git a/chrome/browser/policy/policy_helpers.cc b/chrome/browser/policy/policy_helpers.cc
index e9b6983..3f840a0 100644
--- a/chrome/browser/policy/policy_helpers.cc
+++ b/chrome/browser/policy/policy_helpers.cc
@@ -6,6 +6,11 @@
 
 #include "url/gurl.h"
 
+#if defined(OS_CHROMEOS)
+#include "base/command_line.h"
+#include "chromeos/chromeos_switches.h"
+#endif
+
 #if !defined(OS_CHROMEOS) && !defined(OS_IOS)
 #include "chrome/browser/signin/signin_manager.h"
 #include "google_apis/gaia/gaia_urls.h"
@@ -14,7 +19,18 @@
 namespace policy {
 
 bool OverrideBlacklistForURL(const GURL& url, bool* block) {
-#if defined(OS_CHROMEOS) || defined(OS_IOS)
+#if defined(OS_CHROMEOS)
+  // On ChromeOS browsing is only allowed once OOBE has completed. Therefore all
+  // requests are blocked until this condition is met.
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          chromeos::switches::kOobeGuestSession)) {
+    if (!url.SchemeIs("chrome") && !url.SchemeIs("chrome-extension")) {
+      *block = true;
+      return true;
+    }
+  }
+  return false;
+#elif defined(OS_IOS)
   return false;
 #else
   static const char kServiceLoginAuth[] = "/ServiceLoginAuth";
diff --git a/chrome/browser/policy/test/policy_testserver.py b/chrome/browser/policy/test/policy_testserver.py
index a02942f..68c3936 100644
--- a/chrome/browser/policy/test/policy_testserver.py
+++ b/chrome/browser/policy/test/policy_testserver.py
@@ -1023,7 +1023,7 @@
     hashed_keys = map(lambda key: hashlib.sha256(key.decode('hex')).digest(),
                       set(state_keys))
     return filter(
-        lambda hash : int(hash.encode('hex'), 16) & modulus == remainder,
+        lambda hash : int(hash.encode('hex'), 16) % modulus == remainder,
         hashed_keys)
 
   def UnregisterDevice(self, dmtoken):
diff --git a/chrome/browser/policy/url_blacklist_manager_unittest.cc b/chrome/browser/policy/url_blacklist_manager_unittest.cc
index c6b928b..41bfe15 100644
--- a/chrome/browser/policy/url_blacklist_manager_unittest.cc
+++ b/chrome/browser/policy/url_blacklist_manager_unittest.cc
@@ -7,6 +7,7 @@
 #include <ostream>
 
 #include "base/basictypes.h"
+#include "base/callback.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/prefs/pref_registry_simple.h"
@@ -43,7 +44,7 @@
                             base::MessageLoopProxy::current(),
                             base::MessageLoopProxy::current(),
                             GetSegmentURLCallback(),
-                            OverrideBlacklistForURL),
+                            base::Bind(OverrideBlacklistForURL)),
         update_called_(0),
         set_blacklist_called_(false) {}
 
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 7e8d458..f9cf121 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -39,6 +39,7 @@
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/media/media_device_id_salt.h"
 #include "chrome/browser/media/media_stream_devices_controller.h"
+#include "chrome/browser/metrics/cloned_install_detector.h"
 #include "chrome/browser/metrics/metrics_log.h"
 #include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/browser/metrics/variations/variations_service.h"
@@ -242,6 +243,7 @@
   MetricsLog::RegisterPrefs(registry);
   MetricsService::RegisterPrefs(registry);
   metrics::CachingPermutedEntropyProvider::RegisterPrefs(registry);
+  metrics::ClonedInstallDetector::RegisterPrefs(registry);
   PrefProxyConfigTrackerImpl::RegisterPrefs(registry);
   ProfileInfoCache::RegisterPrefs(registry);
   profiles::RegisterPrefs(registry);
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc
index 59ed97b..55fef2f 100644
--- a/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -10,9 +10,7 @@
 #include "base/bind.h"
 #include "base/compiler_specific.h"
 #include "base/debug/trace_event.h"
-#include "base/file_util.h"
 #include "base/files/file_path.h"
-#include "base/json/json_file_value_serializer.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram.h"
 #include "base/prefs/default_pref_store.h"
@@ -26,16 +24,13 @@
 #include "base/prefs/pref_value_store.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/time/time.h"
-#include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/prefs/command_line_pref_store.h"
 #include "chrome/browser/prefs/pref_hash_filter.h"
-#include "chrome/browser/prefs/pref_hash_store.h"
-#include "chrome/browser/prefs/pref_hash_store_impl.h"
 #include "chrome/browser/prefs/pref_model_associator.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/prefs/pref_service_syncable_factory.h"
-#include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h"
+#include "chrome/browser/prefs/profile_pref_store_manager.h"
 #include "chrome/browser/profiles/file_path_verifier_win.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -73,16 +68,6 @@
 
 namespace {
 
-// TODO(erikwright): Enable this on Android when race condition is sorted out.
-// TODO(erikwright): Enable this on Chrome OS once MACs are moved out of Local
-// State.
-const bool kCanUsePrefHashStoreOnPlatform =
-#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
-    false;
-#else
-    true;
-#endif
-
 // Whether we are in testing mode; can be enabled via
 // DisableDelaysAndDomainCheckForTesting(). Forces startup checks to occur
 // with no delay and ignores the presence of a domain when determining the
@@ -284,24 +269,9 @@
   }
 }
 
-base::FilePath GetPrefFilePathFromProfilePath(
+scoped_ptr<ProfilePrefStoreManager> CreateProfilePrefStoreManager(
     const base::FilePath& profile_path) {
-  return profile_path.Append(chrome::kPreferencesFilename);
-}
-
-// Returns the PrefHashStoreImpl for the profile at |profile_path|; may be NULL
-// on some platforms.
-scoped_ptr<PrefHashStoreImpl> GetPrefHashStoreImpl(
-    const base::FilePath& profile_path) {
-  // TODO(erikwright): Remove this check and change this method's definition to
-  // never NULL once a pref hash store can be used on every platform.
-  if (!kCanUsePrefHashStoreOnPlatform)
-    return scoped_ptr<PrefHashStoreImpl>();
-
-  std::string seed = ResourceBundle::GetSharedInstance().GetRawDataResource(
-      IDR_PREF_HASH_SEED_BIN).as_string();
   std::string device_id;
-
 #if defined(OS_WIN) && defined(ENABLE_RLZ)
   // This is used by
   // chrome/browser/extensions/api/music_manager_private/device_id_win.cc
@@ -311,28 +281,22 @@
   // ways to defer preference loading until the device ID can be used.
   rlz_lib::GetMachineId(&device_id);
 #endif
-
-  return make_scoped_ptr(new PrefHashStoreImpl(
-      seed,
+  return make_scoped_ptr(new ProfilePrefStoreManager(
+      profile_path,
+      GetTrackingConfiguration(),
+      kTrackedPrefsReportingIDsCount,
+      ResourceBundle::GetSharedInstance()
+          .GetRawDataResource(IDR_PREF_HASH_SEED_BIN)
+          .as_string(),
       device_id,
-      scoped_ptr<HashStoreContents>(new PrefServiceHashStoreContents(
-          profile_path.AsUTF8Unsafe(), g_browser_process->local_state()))));
+      g_browser_process->local_state()));
 }
 
-scoped_ptr<PrefHashFilter> CreatePrefHashFilter(
-    scoped_ptr<PrefHashStore> pref_hash_store) {
-  return make_scoped_ptr(new PrefHashFilter(pref_hash_store.Pass(),
-                                            GetTrackingConfiguration(),
-                                            kTrackedPrefsReportingIDsCount));
-}
-
-void PrepareBuilder(
+void PrepareFactory(
     PrefServiceSyncableFactory* factory,
-    const base::FilePath& pref_filename,
-    base::SequencedTaskRunner* pref_io_task_runner,
     policy::PolicyService* policy_service,
     ManagedUserSettingsService* managed_user_settings,
-    scoped_ptr<PrefHashStore> pref_hash_store,
+    scoped_refptr<PersistentPrefStore> user_pref_store,
     const scoped_refptr<PrefStore>& extension_prefs,
     bool async) {
 #if defined(ENABLE_CONFIGURATION_POLICY)
@@ -362,134 +326,27 @@
       make_scoped_refptr(
           new CommandLinePrefStore(CommandLine::ForCurrentProcess())));
   factory->set_read_error_callback(base::Bind(&HandleReadError));
-  scoped_ptr<PrefFilter> pref_filter;
-  if (pref_hash_store)
-    pref_filter = CreatePrefHashFilter(pref_hash_store.Pass());
-  factory->set_user_prefs(
-      new JsonPrefStore(
-          pref_filename,
-          pref_io_task_runner,
-          pref_filter.Pass()));
-}
-
-// An in-memory PrefStore backed by an immutable DictionaryValue.
-class DictionaryPrefStore : public PrefStore {
- public:
-  explicit DictionaryPrefStore(const base::DictionaryValue* dictionary)
-      : dictionary_(dictionary) {}
-
-  virtual bool GetValue(const std::string& key,
-                        const base::Value** result) const OVERRIDE {
-    const base::Value* tmp = NULL;
-    if (!dictionary_->Get(key, &tmp))
-      return false;
-
-    if (result)
-      *result = tmp;
-    return true;
-  }
-
- private:
-  virtual ~DictionaryPrefStore() {}
-
-  const base::DictionaryValue* dictionary_;
-
-  DISALLOW_COPY_AND_ASSIGN(DictionaryPrefStore);
-};
-
-// Waits for a PrefStore to be initialized and then initializes the
-// corresponding PrefHashStore.
-// The observer deletes itself when its work is completed.
-class InitializeHashStoreObserver : public PrefStore::Observer {
- public:
-  // Creates an observer that will initialize |pref_hash_store| with the
-  // contents of |pref_store| when the latter is fully loaded.
-  InitializeHashStoreObserver(
-      const scoped_refptr<PrefStore>& pref_store,
-      scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl)
-      : pref_store_(pref_store),
-        pref_hash_store_impl_(pref_hash_store_impl.Pass()) {}
-
-  virtual ~InitializeHashStoreObserver();
-
-  // PrefStore::Observer implementation.
-  virtual void OnPrefValueChanged(const std::string& key) OVERRIDE;
-  virtual void OnInitializationCompleted(bool succeeded) OVERRIDE;
-
- private:
-  scoped_refptr<PrefStore> pref_store_;
-  scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl_;
-
-  DISALLOW_COPY_AND_ASSIGN(InitializeHashStoreObserver);
-};
-
-InitializeHashStoreObserver::~InitializeHashStoreObserver() {}
-
-void InitializeHashStoreObserver::OnPrefValueChanged(const std::string& key) {}
-
-void InitializeHashStoreObserver::OnInitializationCompleted(bool succeeded) {
-  // If we successfully loaded the preferences _and_ the PrefHashStoreImpl
-  // hasn't been initialized by someone else in the meantime, initialize it now.
-  const PrefHashStoreImpl::StoreVersion pre_update_version =
-      pref_hash_store_impl_->GetCurrentVersion();
-  if (succeeded && pre_update_version < PrefHashStoreImpl::VERSION_LATEST) {
-    CreatePrefHashFilter(pref_hash_store_impl_.PassAs<PrefHashStore>())->
-        Initialize(*pref_store_);
-    UMA_HISTOGRAM_ENUMERATION(
-        "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
-        pre_update_version,
-        PrefHashStoreImpl::VERSION_LATEST + 1);
-  }
-  pref_store_->RemoveObserver(this);
-  delete this;
-}
-
-// Initializes/updates the PrefHashStore for the profile preferences file under
-// |profile_path| without actually loading that profile. Also reports the
-// version of that PrefHashStore via UMA, whether it proceeds with initializing
-// it or not. This should only be called if |kCanUsePrefHashStoreOnPlatform|.
-void UpdatePrefHashStoreIfRequired(
-    const base::FilePath& profile_path) {
-  scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl(
-      GetPrefHashStoreImpl(profile_path));
-  DCHECK(pref_hash_store_impl);
-
-  const PrefHashStoreImpl::StoreVersion current_version =
-      pref_hash_store_impl->GetCurrentVersion();
-  UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferencesAlternateStoreVersion",
-                            current_version,
-                            PrefHashStoreImpl::VERSION_LATEST + 1);
-
-  // Update the pref hash store if it's not at the latest version and the
-  // SettingsEnforcement group allows seeding of unloaded profiles.
-  if (current_version != PrefHashStoreImpl::VERSION_LATEST &&
-      GetSettingsEnforcementGroup() < GROUP_ENFORCE_ALWAYS) {
-    const base::FilePath pref_file(
-        GetPrefFilePathFromProfilePath(profile_path));
-    scoped_refptr<JsonPrefStore> pref_store(
-        new JsonPrefStore(pref_file,
-                          JsonPrefStore::GetTaskRunnerForFile(
-                              pref_file, BrowserThread::GetBlockingPool()),
-                          scoped_ptr<PrefFilter>()));
-    pref_store->AddObserver(
-        new InitializeHashStoreObserver(pref_store,
-                                        pref_hash_store_impl.Pass()));
-    pref_store->ReadPrefsAsync(NULL);
-  }
+  factory->set_user_prefs(user_pref_store);
 }
 
 // Initialize/update preference hash stores for all profiles but the one whose
 // path matches |ignored_profile_path|.
 void UpdateAllPrefHashStoresIfRequired(
     const base::FilePath& ignored_profile_path) {
+  if (GetSettingsEnforcementGroup() >= GROUP_ENFORCE_ALWAYS)
+    return;
   const ProfileInfoCache& profile_info_cache =
       g_browser_process->profile_manager()->GetProfileInfoCache();
   const size_t n_profiles = profile_info_cache.GetNumberOfProfiles();
   for (size_t i = 0; i < n_profiles; ++i) {
     const base::FilePath profile_path =
         profile_info_cache.GetPathOfProfileAtIndex(i);
-    if (profile_path != ignored_profile_path)
-      UpdatePrefHashStoreIfRequired(profile_path);
+    if (profile_path != ignored_profile_path) {
+      CreateProfilePrefStoreManager(profile_path)
+          ->UpdateProfileHashStoreIfRequired(
+              JsonPrefStore::GetTaskRunnerForFile(
+                  profile_path, BrowserThread::GetBlockingPool()));
+    }
   }
 }
 
@@ -513,14 +370,14 @@
     const scoped_refptr<PrefRegistry>& pref_registry,
     bool async) {
   PrefServiceSyncableFactory factory;
-  PrepareBuilder(&factory,
-                 pref_filename,
-                 pref_io_task_runner,
-                 policy_service,
-                 NULL,
-                 scoped_ptr<PrefHashStore>(),
-                 NULL,
-                 async);
+  PrepareFactory(
+      &factory,
+      policy_service,
+      NULL,  // managed_user_settings
+      new JsonPrefStore(
+          pref_filename, pref_io_task_runner, scoped_ptr<PrefFilter>()),
+      NULL,  // extension_prefs
+      async);
   return factory.Create(pref_registry.get());
 }
 
@@ -534,12 +391,12 @@
     bool async) {
   TRACE_EVENT0("browser", "chrome_prefs::CreateProfilePrefs");
   PrefServiceSyncableFactory factory;
-  PrepareBuilder(&factory,
-                 GetPrefFilePathFromProfilePath(profile_path),
-                 pref_io_task_runner,
+  PrepareFactory(&factory,
                  policy_service,
                  managed_user_settings,
-                 GetPrefHashStoreImpl(profile_path).PassAs<PrefHashStore>(),
+                 scoped_refptr<PersistentPrefStore>(
+                     CreateProfilePrefStoreManager(profile_path)
+                         ->CreateProfilePrefStore(pref_io_task_runner)),
                  extension_prefs,
                  async);
   return factory.CreateSyncable(pref_registry.get());
@@ -550,12 +407,13 @@
   // Only do prefs file verification on Windows.
   const int kVerifyPrefsFileDelaySeconds = 60;
   BrowserThread::GetBlockingPool()->PostDelayedTask(
-        FROM_HERE,
-        base::Bind(&VerifyPreferencesFile,
-                   GetPrefFilePathFromProfilePath(profile_path)),
-        base::TimeDelta::FromSeconds(
-            g_disable_delays_and_domain_check_for_testing ?
-                0 : kVerifyPrefsFileDelaySeconds));
+      FROM_HERE,
+      base::Bind(&VerifyPreferencesFile,
+                 ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
+                     profile_path)),
+      base::TimeDelta::FromSeconds(g_disable_delays_and_domain_check_for_testing
+                                       ? 0
+                                       : kVerifyPrefsFileDelaySeconds));
 #endif
 }
 
@@ -565,8 +423,8 @@
 
 void SchedulePrefHashStoresUpdateCheck(
     const base::FilePath& initial_profile_path) {
-  if (!kCanUsePrefHashStoreOnPlatform) {
-    PrefServiceHashStoreContents::ResetAllPrefHashStores(
+  if (!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking) {
+    ProfilePrefStoreManager::ResetAllPrefHashStores(
         g_browser_process->local_state());
     return;
   }
@@ -583,53 +441,30 @@
 }
 
 void ResetPrefHashStore(const base::FilePath& profile_path) {
-  GetPrefHashStoreImpl(profile_path)->Reset();
+  CreateProfilePrefStoreManager(profile_path)->ResetPrefHashStore();
 }
 
 bool InitializePrefsFromMasterPrefs(
     const base::FilePath& profile_path,
     const base::DictionaryValue& master_prefs) {
-  // Create the profile directory if it doesn't exist yet (very possible on
-  // first run).
-  if (!base::CreateDirectory(profile_path))
-    return false;
-
-  JSONFileValueSerializer serializer(
-      GetPrefFilePathFromProfilePath(profile_path));
-
-  // Call Serialize (which does IO) on the main thread, which would _normally_
-  // be verboten. In this case however, we require this IO to synchronously
-  // complete before Chrome can start (as master preferences seed the Local
-  // State and Preferences files). This won't trip ThreadIORestrictions as they
-  // won't have kicked in yet on the main thread.
-  bool success = serializer.Serialize(master_prefs);
-
-  if (success) {
-    scoped_refptr<const PrefStore> pref_store(
-        new DictionaryPrefStore(&master_prefs));
-    CreatePrefHashFilter(
-        GetPrefHashStoreImpl(profile_path).PassAs<PrefHashStore>())->
-            Initialize(*pref_store);
-  }
-
-  UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success);
-  return success;
+  return CreateProfilePrefStoreManager(profile_path)
+      ->InitializePrefsFromMasterPrefs(master_prefs);
 }
 
 base::Time GetResetTime(Profile* profile) {
-  return PrefHashFilter::GetResetTime(profile->GetPrefs());
+  return ProfilePrefStoreManager::GetResetTime(profile->GetPrefs());
 }
 
 void ClearResetTime(Profile* profile) {
-  PrefHashFilter::ClearResetTime(profile->GetPrefs());
+  ProfilePrefStoreManager::ClearResetTime(profile->GetPrefs());
 }
 
 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
-  PrefHashFilter::RegisterProfilePrefs(registry);
+  ProfilePrefStoreManager::RegisterProfilePrefs(registry);
 }
 
 void RegisterPrefs(PrefRegistrySimple* registry) {
-  PrefServiceHashStoreContents::RegisterPrefs(registry);
+  ProfilePrefStoreManager::RegisterPrefs(registry);
 }
 
 }  // namespace chrome_prefs
diff --git a/chrome/browser/prefs/command_line_pref_store.cc b/chrome/browser/prefs/command_line_pref_store.cc
index 9cdbd4b..f2d6855 100644
--- a/chrome/browser/prefs/command_line_pref_store.cc
+++ b/chrome/browser/prefs/command_line_pref_store.cc
@@ -57,8 +57,6 @@
       { switches::kDisableTLSChannelID, prefs::kEnableOriginBoundCerts, false },
       { switches::kDisableSSLFalseStart, prefs::kDisableSSLRecordSplitting,
           true },
-      { switches::kEnableUnrestrictedSSL3Fallback,
-          prefs::kEnableUnrestrictedSSL3Fallback, true },
 #if defined(GOOGLE_CHROME_BUILD)
       { switches::kDisablePrintPreview, prefs::kPrintPreviewDisabled, true },
 #else
diff --git a/chrome/browser/prefs/incognito_mode_prefs_unittest.cc b/chrome/browser/prefs/incognito_mode_prefs_unittest.cc
index ea15b95..d2ba49c 100644
--- a/chrome/browser/prefs/incognito_mode_prefs_unittest.cc
+++ b/chrome/browser/prefs/incognito_mode_prefs_unittest.cc
@@ -58,15 +58,8 @@
 
 typedef IncognitoModePrefsTest IncognitoModePrefsDeathTest;
 
-// Takes too long to execute on Mac. http://crbug.com/101109
-#if defined(OS_MACOSX)
-#define MAYBE_GetAvailabilityBadValue DISABLED_GetAvailabilityBadValue
-#else
-#define MAYBE_GetAvailabilityBadValue GetAvailabilityBadValue
-#endif
-
 #if GTEST_HAS_DEATH_TEST
-TEST_F(IncognitoModePrefsDeathTest, MAYBE_GetAvailabilityBadValue) {
+TEST_F(IncognitoModePrefsDeathTest, GetAvailabilityBadValue) {
   prefs_.SetUserPref(prefs::kIncognitoModeAvailability,
                      base::Value::CreateIntegerValue(-1));
 #if defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
diff --git a/chrome/browser/prefs/pref_hash_browsertest.cc b/chrome/browser/prefs/pref_hash_browsertest.cc
index e954926..0259e6e 100644
--- a/chrome/browser/prefs/pref_hash_browsertest.cc
+++ b/chrome/browser/prefs/pref_hash_browsertest.cc
@@ -148,8 +148,19 @@
   }
 };
 
+#if defined(OS_CHROMEOS)
+// PrefHash service has been disabled on ChromeOS: crbug.com/343261
+#define MAYBE_PRE_PRE_InitializeUnloadedProfiles DISABLED_PRE_PRE_InitializeUnloadedProfiles
+#define MAYBE_PRE_InitializeUnloadedProfiles DISABLED_PRE_InitializeUnloadedProfiles
+#define MAYBE_InitializeUnloadedProfiles DISABLED_InitializeUnloadedProfiles
+#else
+#define MAYBE_PRE_PRE_InitializeUnloadedProfiles PRE_PRE_InitializeUnloadedProfiles
+#define MAYBE_PRE_InitializeUnloadedProfiles PRE_InitializeUnloadedProfiles
+#define MAYBE_InitializeUnloadedProfiles InitializeUnloadedProfiles
+#endif
+
 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
-                       PRE_PRE_InitializeUnloadedProfiles) {
+                       MAYBE_PRE_PRE_InitializeUnloadedProfiles) {
   if (!profiles::IsMultipleProfilesEnabled())
     return;
   ProfileManager* profile_manager = g_browser_process->profile_manager();
@@ -179,7 +190,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
-                       PRE_InitializeUnloadedProfiles) {
+                       MAYBE_PRE_InitializeUnloadedProfiles) {
   if (!profiles::IsMultipleProfilesEnabled())
     return;
 
@@ -216,7 +227,7 @@
 }
 
 IN_PROC_BROWSER_TEST_P(PrefHashBrowserTest,
-                       InitializeUnloadedProfiles) {
+                       MAYBE_InitializeUnloadedProfiles) {
   if (!profiles::IsMultipleProfilesEnabled())
     return;
 
diff --git a/chrome/browser/prefs/pref_hash_filter.cc b/chrome/browser/prefs/pref_hash_filter.cc
index b937c35..381fbac 100644
--- a/chrome/browser/prefs/pref_hash_filter.cc
+++ b/chrome/browser/prefs/pref_hash_filter.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
+#include "base/prefs/persistent_pref_store.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/pref_store.h"
 #include "base/strings/string_number_conversions.h"
@@ -91,6 +92,42 @@
   user_prefs->ClearPref(prefs::kPreferenceResetTime);
 }
 
+void PrefHashFilter::MigrateValues(PersistentPrefStore* source,
+                                   PersistentPrefStore* destination) {
+  scoped_ptr<PrefHashStoreTransaction> transaction =
+      pref_hash_store_->BeginTransaction();
+  for (TrackedPreferencesMap::const_iterator it = tracked_paths_.begin();
+       it != tracked_paths_.end();
+       ++it) {
+    const base::Value* source_value = NULL;
+    if (source->GetValue(it->first, &source_value) &&
+        !destination->GetValue(it->first, NULL)) {
+      base::DictionaryValue temp_dictionary;
+      // Copy the value from |source| into a suitable place for a
+      // TrackedPreference to act on it.
+      temp_dictionary.Set(it->first, source_value->DeepCopy());
+      // Check whether the value is correct according to our MAC. May remove the
+      //  value from |temp_dictionary|.
+      it->second->EnforceAndReport(&temp_dictionary, transaction.get());
+      // Now take the value as it appears in |temp_dictionary| and put it in
+      // |destination|.
+      scoped_ptr<base::Value> checked_value;
+      if (temp_dictionary.Remove(it->first, &checked_value))
+        destination->SetValue(it->first, checked_value.release());
+    }
+    source->RemoveValue(it->first);
+  }
+
+  // Order these such that a crash at any point is still recoverable. We assume
+  // that they are configured such that the writes will occur on worker threads
+  // in the order that we asked for them.
+  destination->CommitPendingWrite();
+  transaction.reset();
+  // If we crash here, we will just delete the values from |source| in a future
+  // invocation of MigrateValues.
+  source->CommitPendingWrite();
+}
+
 void PrefHashFilter::Initialize(const PrefStore& pref_store) {
   scoped_ptr<PrefHashStoreTransaction> hash_store_transaction(
       pref_hash_store_->BeginTransaction());
diff --git a/chrome/browser/prefs/pref_hash_filter.h b/chrome/browser/prefs/pref_hash_filter.h
index 753293c..c4353fa 100644
--- a/chrome/browser/prefs/pref_hash_filter.h
+++ b/chrome/browser/prefs/pref_hash_filter.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/prefs/pref_hash_store.h"
 #include "chrome/browser/prefs/tracked/tracked_preference.h"
 
+class PersistentPrefStore;
 class PrefService;
 class PrefStore;
 
@@ -83,6 +84,15 @@
   // |pref_store|.
   void Initialize(const PrefStore& pref_store);
 
+  // Migrates protected values from |source| to |destination|. Values are
+  // migrated if they are protected according to this filter's configuration,
+  // the corresponding key has no value in |destination|, and the value in
+  // |source| is trusted according to this filter's PrefHashStore. Regardless of
+  // the state of |destination| or the trust status, the protected values will
+  // be removed from |source|.
+  void MigrateValues(PersistentPrefStore* source,
+                     PersistentPrefStore* destination);
+
   // PrefFilter implementation.
   virtual void FilterOnLoad(base::DictionaryValue* pref_store_contents)
       OVERRIDE;
diff --git a/chrome/browser/prefs/pref_hash_filter_unittest.cc b/chrome/browser/prefs/pref_hash_filter_unittest.cc
index c212cfa..4fa0ab7 100644
--- a/chrome/browser/prefs/pref_hash_filter_unittest.cc
+++ b/chrome/browser/prefs/pref_hash_filter_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/prefs/testing_pref_store.h"
 #include "base/values.h"
 #include "chrome/browser/prefs/pref_hash_store.h"
 #include "chrome/browser/prefs/pref_hash_store_transaction.h"
@@ -68,12 +69,10 @@
   typedef std::pair<const void*, PrefHashFilter::PrefTrackingStrategy>
       ValuePtrStrategyPair;
 
-  MockPrefHashStore() : transactions_expected_(1),
-                        transactions_performed_(0),
+  MockPrefHashStore() : transactions_performed_(0),
                         transaction_active_(false) {}
 
   virtual ~MockPrefHashStore() {
-    EXPECT_EQ(transactions_expected_, transactions_performed_);
     EXPECT_FALSE(transaction_active_);
   }
 
@@ -89,9 +88,8 @@
       const std::string& path,
       const std::vector<std::string>& invalid_keys_result);
 
-  void set_transactions_expected(size_t transactions_expected) {
-    transactions_expected_ = transactions_expected;
-  }
+  // Returns the number of transactions that were performed.
+  size_t transactions_performed() { return transactions_performed_; }
 
   // Returns the number of paths checked.
   size_t checked_paths_count() const {
@@ -286,16 +284,8 @@
                           PrefHashFilter::TRACKING_STRATEGY_SPLIT);
 }
 
-// Creates a PrefHashFilter that uses a MockPrefHashStore. The
-// MockPrefHashStore (owned by the PrefHashFilter) is returned in
-// |mock_pref_hash_store|.
-scoped_ptr<PrefHashFilter> CreatePrefHashFilter(
-    PrefHashFilter::EnforcementLevel max_enforcement_level,
-    MockPrefHashStore** mock_pref_hash_store) {
-  scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
-      new MockPrefHashStore);
-  if (mock_pref_hash_store)
-    *mock_pref_hash_store = temp_mock_pref_hash_store.get();
+std::vector<PrefHashFilter::TrackedPreferenceMetadata> GetConfiguration(
+    PrefHashFilter::EnforcementLevel max_enforcement_level) {
   std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration(
       kTestTrackedPrefs, kTestTrackedPrefs + arraysize(kTestTrackedPrefs));
   for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
@@ -305,10 +295,7 @@
     if (it->enforcement_level > max_enforcement_level)
       it->enforcement_level = max_enforcement_level;
   }
-  return scoped_ptr<PrefHashFilter>(
-      new PrefHashFilter(temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
-                         configuration,
-                         arraysize(kTestTrackedPrefs)));
+  return configuration;
 }
 
 class PrefHashFilterTest
@@ -318,11 +305,24 @@
 
   virtual void SetUp() OVERRIDE {
     // Construct a PrefHashFilter and MockPrefHashStore for the test.
-    pref_hash_filter_ =
-        CreatePrefHashFilter(GetParam(), &mock_pref_hash_store_);
+    InitializePrefHashFilter(GetConfiguration(GetParam()));
   }
 
  protected:
+  // Creates a PrefHashFilter that uses a MockPrefHashStore. The
+  // MockPrefHashStore (owned by the PrefHashFilter) is returned in
+  // |mock_pref_hash_store|.
+  void InitializePrefHashFilter(const std::vector<
+      PrefHashFilter::TrackedPreferenceMetadata>& configuration) {
+    scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store(
+        new MockPrefHashStore);
+    mock_pref_hash_store_ = temp_mock_pref_hash_store.get();
+    pref_hash_filter_.reset(
+        new PrefHashFilter(temp_mock_pref_hash_store.PassAs<PrefHashStore>(),
+                           configuration,
+                           arraysize(kTestTrackedPrefs)));
+  }
+
   bool RecordedReset() {
     return pref_store_contents_.Get(prefs::kPreferenceResetTime, NULL);
   }
@@ -347,6 +347,7 @@
     ASSERT_EQ(NULL, mock_pref_hash_store_->checked_value(
                         kTestTrackedPrefs[i].name).first);
   }
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
   ASSERT_FALSE(RecordedReset());
 }
 
@@ -368,6 +369,7 @@
   ASSERT_EQ(string_value, stored_value.first);
   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, stored_value.second);
 
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
   ASSERT_FALSE(RecordedReset());
 }
 
@@ -391,14 +393,11 @@
   ASSERT_EQ(dict_value, stored_value.first);
   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value.second);
 
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
   ASSERT_FALSE(RecordedReset());
 }
 
 TEST_P(PrefHashFilterTest, FilterUntrackedPrefUpdate) {
-  // No transaction should even be started on FilterSerializeData() if there are
-  // no updates to perform.
-  mock_pref_hash_store_->set_transactions_expected(0);
-
   base::DictionaryValue root_dict;
   root_dict.Set("untracked", base::Value::CreateStringValue("some value"));
   pref_hash_filter_->FilterUpdate("untracked");
@@ -409,6 +408,10 @@
   // Nor on FilterSerializeData.
   pref_hash_filter_->FilterSerializeData(&root_dict);
   ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count());
+
+  // No transaction should even be started on FilterSerializeData() if there are
+  // no updates to perform.
+  ASSERT_EQ(0u, mock_pref_hash_store_->transactions_performed());
 }
 
 TEST_P(PrefHashFilterTest, MultiplePrefsFilterSerializeData) {
@@ -446,6 +449,7 @@
   ASSERT_EQ(int_value1, stored_value_atomic1.first);
   ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC,
             stored_value_atomic1.second);
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic3 =
       mock_pref_hash_store_->stored_value(kAtomicPref3);
@@ -471,6 +475,7 @@
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
        mock_pref_hash_store_->stored_value(kAtomicPref);
@@ -506,6 +511,7 @@
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
        mock_pref_hash_store_->stored_value(kAtomicPref);
@@ -563,6 +569,7 @@
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   // Seeding is always allowed for trusted unknown values.
   const base::Value* atomic_value_in_store;
@@ -613,6 +620,7 @@
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
        mock_pref_hash_store_->stored_value(kAtomicPref);
@@ -673,6 +681,7 @@
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   // Regardless of the enforcement level, the only thing that should be done is
   // to restore the hash for NULL. The value itself should still be NULL.
@@ -707,6 +716,7 @@
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
   ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value =
        mock_pref_hash_store_->stored_value(kAtomicPref);
@@ -751,6 +761,7 @@
   pref_hash_filter_->FilterOnLoad(&pref_store_contents_);
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   // Ensure that both the atomic and split hashes were restored.
   ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count());
@@ -810,6 +821,7 @@
   ASSERT_EQ(arraysize(kTestTrackedPrefs),
             mock_pref_hash_store_->checked_paths_count());
   ASSERT_EQ(4u, mock_pref_hash_store_->stored_paths_count());
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
 
   // No matter what the enforcement level is, the report only pref should never
   // be reset.
@@ -844,6 +856,80 @@
   }
 }
 
+TEST_P(PrefHashFilterTest, MigrateValuesTest) {
+  // Migration configuration should only contain the protected preferences.
+  std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration =
+      GetConfiguration(GetParam());
+  std::vector<PrefHashFilter::TrackedPreferenceMetadata>
+      migration_configuration;
+
+  for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it =
+           configuration.begin();
+       it != configuration.end();
+       ++it) {
+    if (it->enforcement_level >= PrefHashFilter::ENFORCE_ON_LOAD)
+      migration_configuration.push_back(*it);
+  }
+
+  // Discards the default created pref_hash_filter_.
+  InitializePrefHashFilter(migration_configuration);
+
+  scoped_refptr<TestingPrefStore> source(new TestingPrefStore);
+  scoped_refptr<TestingPrefStore> destination(new TestingPrefStore);
+
+  source->SetString(kAtomicPref, "foobar");
+  source->SetString(kAtomicPref2, "foobar2");
+  destination->SetString(kAtomicPref2, "foobar2 preexisting");
+  destination->SetString(kAtomicPref3, "foobar3");
+  source->SetString(kReportOnlyPref, "helloworld");
+
+  mock_pref_hash_store_->SetCheckResult(kAtomicPref,
+                                        PrefHashStoreTransaction::UNCHANGED);
+  mock_pref_hash_store_->SetCheckResult(kAtomicPref2,
+                                        PrefHashStoreTransaction::UNCHANGED);
+  mock_pref_hash_store_->SetCheckResult(kAtomicPref3,
+                                        PrefHashStoreTransaction::UNCHANGED);
+  mock_pref_hash_store_->SetCheckResult(kReportOnlyPref,
+                                        PrefHashStoreTransaction::UNCHANGED);
+
+  pref_hash_filter_->MigrateValues(source, destination);
+  ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed());
+
+  if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) {
+    std::string value;
+
+    ASSERT_FALSE(source->GetValue(kAtomicPref, NULL));
+    ASSERT_FALSE(source->GetValue(kAtomicPref2, NULL));
+    ASSERT_FALSE(source->GetValue(kAtomicPref3, NULL));
+    ASSERT_TRUE(source->GetString(kReportOnlyPref, &value));
+    ASSERT_EQ("helloworld", value);
+
+    ASSERT_TRUE(destination->GetString(kAtomicPref, &value));
+    ASSERT_EQ("foobar", value);
+    ASSERT_TRUE(destination->GetString(kAtomicPref2, &value));
+    ASSERT_EQ("foobar2 preexisting", value);
+    ASSERT_TRUE(destination->GetString(kAtomicPref3, &value));
+    ASSERT_EQ("foobar3", value);
+    ASSERT_FALSE(destination->GetValue(kReportOnlyPref, NULL));
+  } else {
+    std::string value;
+
+    ASSERT_TRUE(source->GetString(kAtomicPref, &value));
+    ASSERT_EQ("foobar", value);
+    ASSERT_TRUE(source->GetString(kAtomicPref2, &value));
+    ASSERT_EQ("foobar2", value);
+    ASSERT_FALSE(source->GetString(kAtomicPref3, &value));
+    ASSERT_TRUE(source->GetString(kReportOnlyPref, &value));
+    ASSERT_EQ("helloworld", value);
+
+    ASSERT_FALSE(destination->GetValue(kAtomicPref, NULL));
+    ASSERT_TRUE(destination->GetString(kAtomicPref2, &value));
+    ASSERT_EQ("foobar2 preexisting", value);
+    ASSERT_TRUE(destination->GetValue(kAtomicPref3, NULL));
+    ASSERT_FALSE(destination->GetValue(kReportOnlyPref, NULL));
+  }
+}
+
 INSTANTIATE_TEST_CASE_P(
     PrefHashFilterTestInstance, PrefHashFilterTest,
     testing::Values(PrefHashFilter::NO_ENFORCEMENT,
diff --git a/chrome/browser/prefs/profile_pref_store_manager.cc b/chrome/browser/prefs/profile_pref_store_manager.cc
new file mode 100644
index 0000000..fc350a0
--- /dev/null
+++ b/chrome/browser/prefs/profile_pref_store_manager.cc
@@ -0,0 +1,264 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/profile_pref_store_manager.h"
+
+#include "base/file_util.h"
+#include "base/json/json_file_value_serializer.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/json_pref_store.h"
+#include "base/prefs/persistent_pref_store.h"
+#include "base/prefs/pref_registry_simple.h"
+#include "chrome/browser/prefs/pref_hash_store_impl.h"
+#include "chrome/browser/prefs/tracked/pref_service_hash_store_contents.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/pref_names.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+
+namespace {
+
+// An in-memory PrefStore backed by an immutable DictionaryValue.
+class DictionaryPrefStore : public PrefStore {
+ public:
+  explicit DictionaryPrefStore(const base::DictionaryValue* dictionary)
+      : dictionary_(dictionary) {}
+
+  virtual bool GetValue(const std::string& key,
+                        const base::Value** result) const OVERRIDE {
+    const base::Value* tmp = NULL;
+    if (!dictionary_->Get(key, &tmp))
+      return false;
+
+    if (result)
+      *result = tmp;
+    return true;
+  }
+
+ private:
+  virtual ~DictionaryPrefStore() {}
+
+  const base::DictionaryValue* dictionary_;
+
+  DISALLOW_COPY_AND_ASSIGN(DictionaryPrefStore);
+};
+
+}  // namespace
+
+// TODO(erikwright): Enable this on Chrome OS and Android once MACs are moved
+// out of Local State. This will resolve a race condition on Android and a
+// privacy issue on ChromeOS. http://crbug.com/349158
+const bool ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking =
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+    false;
+#else
+    true;
+#endif
+
+// Waits for a PrefStore to be initialized and then initializes the
+// corresponding PrefHashStore.
+// The observer deletes itself when its work is completed.
+class ProfilePrefStoreManager::InitializeHashStoreObserver
+    : public PrefStore::Observer {
+ public:
+  // Creates an observer that will initialize |pref_hash_store| with the
+  // contents of |pref_store| when the latter is fully loaded.
+  InitializeHashStoreObserver(
+      const std::vector<PrefHashFilter::TrackedPreferenceMetadata>&
+          tracking_configuration,
+      size_t reporting_ids_count,
+      const scoped_refptr<PrefStore>& pref_store,
+      scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl)
+      : tracking_configuration_(tracking_configuration),
+        reporting_ids_count_(reporting_ids_count),
+        pref_store_(pref_store),
+        pref_hash_store_impl_(pref_hash_store_impl.Pass()) {}
+
+  virtual ~InitializeHashStoreObserver();
+
+  // PrefStore::Observer implementation.
+  virtual void OnPrefValueChanged(const std::string& key) OVERRIDE;
+  virtual void OnInitializationCompleted(bool succeeded) OVERRIDE;
+
+ private:
+  const std::vector<PrefHashFilter::TrackedPreferenceMetadata>
+      tracking_configuration_;
+  const size_t reporting_ids_count_;
+  scoped_refptr<PrefStore> pref_store_;
+  scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl_;
+
+  DISALLOW_COPY_AND_ASSIGN(InitializeHashStoreObserver);
+};
+
+ProfilePrefStoreManager::InitializeHashStoreObserver::
+    ~InitializeHashStoreObserver() {}
+
+void ProfilePrefStoreManager::InitializeHashStoreObserver::OnPrefValueChanged(
+    const std::string& key) {}
+
+void
+ProfilePrefStoreManager::InitializeHashStoreObserver::OnInitializationCompleted(
+    bool succeeded) {
+  // If we successfully loaded the preferences _and_ the PrefHashStoreImpl
+  // hasn't been initialized by someone else in the meantime, initialize it now.
+  const PrefHashStoreImpl::StoreVersion pre_update_version =
+      pref_hash_store_impl_->GetCurrentVersion();
+  if (succeeded && pre_update_version < PrefHashStoreImpl::VERSION_LATEST) {
+    PrefHashFilter(pref_hash_store_impl_.PassAs<PrefHashStore>(),
+                   tracking_configuration_,
+                   reporting_ids_count_).Initialize(*pref_store_);
+    UMA_HISTOGRAM_ENUMERATION(
+        "Settings.TrackedPreferencesAlternateStoreVersionUpdatedFrom",
+        pre_update_version,
+        PrefHashStoreImpl::VERSION_LATEST + 1);
+  }
+  pref_store_->RemoveObserver(this);
+  delete this;
+}
+
+ProfilePrefStoreManager::ProfilePrefStoreManager(
+    const base::FilePath& profile_path,
+    const std::vector<PrefHashFilter::TrackedPreferenceMetadata>&
+        tracking_configuration,
+    size_t reporting_ids_count,
+    const std::string& seed,
+    const std::string& device_id,
+    PrefService* local_state)
+    : profile_path_(profile_path),
+      tracking_configuration_(tracking_configuration),
+      reporting_ids_count_(reporting_ids_count),
+      seed_(seed),
+      device_id_(device_id),
+      local_state_(local_state) {}
+
+ProfilePrefStoreManager::~ProfilePrefStoreManager() {}
+
+// static
+void ProfilePrefStoreManager::RegisterPrefs(PrefRegistrySimple* registry) {
+  PrefServiceHashStoreContents::RegisterPrefs(registry);
+}
+
+// static
+void ProfilePrefStoreManager::RegisterProfilePrefs(
+    user_prefs::PrefRegistrySyncable* registry) {
+  PrefHashFilter::RegisterProfilePrefs(registry);
+}
+
+// static
+base::FilePath ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
+    const base::FilePath& profile_path) {
+  return profile_path.Append(chrome::kPreferencesFilename);
+}
+
+// static
+void ProfilePrefStoreManager::ResetAllPrefHashStores(PrefService* local_state) {
+  PrefServiceHashStoreContents::ResetAllPrefHashStores(local_state);
+}
+
+//  static
+base::Time ProfilePrefStoreManager::GetResetTime(PrefService* pref_service) {
+  // It's a bit of a coincidence that this (and ClearResetTime) work(s). The
+  // PrefHashFilter attached to the protected pref store will store the reset
+  // time directly in the protected pref store without going through the
+  // SegregatedPrefStore.
+
+  // PrefHashFilter::GetResetTime will read the value through the pref service,
+  // and thus through the SegregatedPrefStore. Even though it's not listed as
+  // "protected" it will be read from the protected store prefentially to the
+  // (NULL) value in the unprotected pref store.
+  return PrefHashFilter::GetResetTime(pref_service);
+}
+
+// static
+void ProfilePrefStoreManager::ClearResetTime(PrefService* pref_service) {
+  // PrefHashFilter::ClearResetTime will clear the value through the pref
+  // service, and thus through the SegregatedPrefStore. Since it's not listed as
+  // "protected" it will be migrated from the protected store to the unprotected
+  // pref store before being deleted from the latter.
+  PrefHashFilter::ClearResetTime(pref_service);
+}
+
+void ProfilePrefStoreManager::ResetPrefHashStore() {
+  if (kPlatformSupportsPreferenceTracking)
+    GetPrefHashStoreImpl()->Reset();
+}
+
+PersistentPrefStore* ProfilePrefStoreManager::CreateProfilePrefStore(
+    const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
+  scoped_ptr<PrefFilter> pref_filter;
+  if (kPlatformSupportsPreferenceTracking) {
+    pref_filter.reset(
+        new PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(),
+                           tracking_configuration_,
+                           reporting_ids_count_));
+  }
+  return new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_),
+                           io_task_runner,
+                           pref_filter.Pass());
+}
+
+void ProfilePrefStoreManager::UpdateProfileHashStoreIfRequired(
+    const scoped_refptr<base::SequencedTaskRunner>& io_task_runner) {
+  if (!kPlatformSupportsPreferenceTracking)
+    return;
+  scoped_ptr<PrefHashStoreImpl> pref_hash_store_impl(GetPrefHashStoreImpl());
+  const PrefHashStoreImpl::StoreVersion current_version =
+      pref_hash_store_impl->GetCurrentVersion();
+  UMA_HISTOGRAM_ENUMERATION("Settings.TrackedPreferencesAlternateStoreVersion",
+                            current_version,
+                            PrefHashStoreImpl::VERSION_LATEST + 1);
+
+  // Update the pref hash store if it's not at the latest version.
+  if (current_version != PrefHashStoreImpl::VERSION_LATEST) {
+    scoped_refptr<JsonPrefStore> pref_store =
+        new JsonPrefStore(GetPrefFilePathFromProfilePath(profile_path_),
+                          io_task_runner,
+                          scoped_ptr<PrefFilter>());
+    pref_store->AddObserver(
+        new InitializeHashStoreObserver(tracking_configuration_,
+                                        reporting_ids_count_,
+                                        pref_store,
+                                        pref_hash_store_impl.Pass()));
+    pref_store->ReadPrefsAsync(NULL);
+  }
+}
+
+bool ProfilePrefStoreManager::InitializePrefsFromMasterPrefs(
+    const base::DictionaryValue& master_prefs) {
+  // Create the profile directory if it doesn't exist yet (very possible on
+  // first run).
+  if (!base::CreateDirectory(profile_path_))
+    return false;
+
+  JSONFileValueSerializer serializer(
+      GetPrefFilePathFromProfilePath(profile_path_));
+
+  // Call Serialize (which does IO) on the main thread, which would _normally_
+  // be verboten. In this case however, we require this IO to synchronously
+  // complete before Chrome can start (as master preferences seed the Local
+  // State and Preferences files). This won't trip ThreadIORestrictions as they
+  // won't have kicked in yet on the main thread.
+  bool success = serializer.Serialize(master_prefs);
+
+  if (success && kPlatformSupportsPreferenceTracking) {
+    scoped_refptr<const PrefStore> pref_store(
+        new DictionaryPrefStore(&master_prefs));
+    PrefHashFilter(GetPrefHashStoreImpl().PassAs<PrefHashStore>(),
+                   tracking_configuration_,
+                   reporting_ids_count_).Initialize(*pref_store);
+  }
+
+  UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success);
+  return success;
+}
+
+scoped_ptr<PrefHashStoreImpl> ProfilePrefStoreManager::GetPrefHashStoreImpl() {
+  DCHECK(kPlatformSupportsPreferenceTracking);
+
+  return make_scoped_ptr(new PrefHashStoreImpl(
+      seed_,
+      device_id_,
+      scoped_ptr<HashStoreContents>(new PrefServiceHashStoreContents(
+          profile_path_.AsUTF8Unsafe(), local_state_))));
+}
diff --git a/chrome/browser/prefs/profile_pref_store_manager.h b/chrome/browser/prefs/profile_pref_store_manager.h
new file mode 100644
index 0000000..f75d3d0
--- /dev/null
+++ b/chrome/browser/prefs/profile_pref_store_manager.h
@@ -0,0 +1,119 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_PROFILE_PREF_STORE_MANAGER_H_
+#define CHROME_BROWSER_PREFS_PROFILE_PREF_STORE_MANAGER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/prefs/pref_hash_filter.h"
+
+class PersistentPrefStore;
+class PrefHashStoreImpl;
+class PrefService;
+
+namespace base {
+class DictionaryValue;
+class SequencedTaskRunner;
+}  // namespace base
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}  // namespace user_prefs
+
+class PrefRegistrySimple;
+
+// Provides a facade through which the user preference store may be accessed and
+// managed.
+class ProfilePrefStoreManager {
+ public:
+  // Instantiates a ProfilePrefStoreManager with the configuration required to
+  // manage the user preferences of the profile at |profile_path|.
+  // |tracking_configuration| is used for preference tracking.
+  // |reporting_ids_count| is the count of all possible tracked preference IDs
+  // (possibly greater than |tracking_configuration.size()|).
+  // |seed| and |device_id| are used to track preference value changes and must
+  // be the same on each launch in order to verify loaded preference values.
+  ProfilePrefStoreManager(
+      const base::FilePath& profile_path,
+      const std::vector<PrefHashFilter::TrackedPreferenceMetadata>&
+          tracking_configuration,
+      size_t reporting_ids_count,
+      const std::string& seed,
+      const std::string& device_id,
+      PrefService* local_state);
+
+  ~ProfilePrefStoreManager();
+
+  static const bool kPlatformSupportsPreferenceTracking;
+
+  // Register local state prefs used by the profile preferences system.
+  static void RegisterPrefs(PrefRegistrySimple* registry);
+
+  // Register user prefs used by the profile preferences system.
+  static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+  // Determines the user preferences filename for the profile at |profile_path|.
+  static base::FilePath GetPrefFilePathFromProfilePath(
+      const base::FilePath& profile_path);
+
+  // Deletes stored hashes for all profiles from |local_state|.
+  static void ResetAllPrefHashStores(PrefService* local_state);
+
+  // Retrieves the time of the last preference reset event, if any, for
+  // |pref_service|. Assumes that |pref_service| is backed by a PrefStore that
+  // was built by ProfilePrefStoreManager.
+  // If no reset has occurred, returns a null |Time|.
+  static base::Time GetResetTime(PrefService* pref_service);
+
+  // Clears the time of the last preference reset event, if any, for
+  // |pref_service|. Assumes that |pref_service| is backed by a PrefStore that
+  // was built by ProfilePrefStoreManager.
+  static void ClearResetTime(PrefService* pref_service);
+
+  // Deletes stored hashes for the managed profile.
+  void ResetPrefHashStore();
+
+  // Creates a PersistentPrefStore providing access to the user preferences of
+  // the managed profile.
+  PersistentPrefStore* CreateProfilePrefStore(
+      const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
+
+  // Checks the presence/version of the hash store for the managed profile and
+  // creates or updates it if necessary. Completes asynchronously and is safe if
+  // the preferences/hash store are concurrently loaded/manipulated by another
+  // task.
+  void UpdateProfileHashStoreIfRequired(
+      const scoped_refptr<base::SequencedTaskRunner>& io_task_runner);
+
+  // Initializes the preferences for the managed profile with the preference
+  // values in |master_prefs|. Acts synchronously, including blocking IO.
+  // Returns true on success.
+  bool InitializePrefsFromMasterPrefs(
+      const base::DictionaryValue& master_prefs);
+
+ private:
+  class InitializeHashStoreObserver;
+
+  // Returns a PrefHashStoreImpl for the managed profile. Should only be called
+  // if |kPlatformSupportsPreferenceTracking|.
+  scoped_ptr<PrefHashStoreImpl> GetPrefHashStoreImpl();
+
+  const base::FilePath profile_path_;
+  const std::vector<PrefHashFilter::TrackedPreferenceMetadata>
+      tracking_configuration_;
+  const size_t reporting_ids_count_;
+  const std::string seed_;
+  const std::string device_id_;
+  PrefService* local_state_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfilePrefStoreManager);
+};
+
+#endif  // CHROME_BROWSER_PREFS_PROFILE_PREF_STORE_MANAGER_H_
diff --git a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
new file mode 100644
index 0000000..c7bb745
--- /dev/null
+++ b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
@@ -0,0 +1,292 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/profile_pref_store_manager.h"
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/prefs/json_pref_store.h"
+#include "base/prefs/persistent_pref_store.h"
+#include "base/prefs/pref_service.h"
+#include "base/prefs/pref_store.h"
+#include "base/prefs/testing_pref_service.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/pref_hash_filter.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class FirstEqualsPredicate {
+ public:
+  explicit FirstEqualsPredicate(const std::string& expected)
+      : expected_(expected) {}
+  bool operator()(const std::pair<std::string, base::Value*>& pair) {
+    return pair.first == expected_;
+  }
+
+ private:
+  const std::string expected_;
+};
+
+// Observes changes to the PrefStore and verifies that only registered prefs are
+// written.
+class RegistryVerifier : public PrefStore::Observer {
+ public:
+  explicit RegistryVerifier(PrefRegistry* pref_registry)
+      : pref_registry_(pref_registry) {}
+
+  // PrefStore::Observer implementation
+  virtual void OnPrefValueChanged(const std::string& key) OVERRIDE {
+    EXPECT_TRUE(pref_registry_->end() !=
+                std::find_if(pref_registry_->begin(),
+                             pref_registry_->end(),
+                             FirstEqualsPredicate(key)))
+        << "Unregistered key " << key << " was changed.";
+  }
+
+  virtual void OnInitializationCompleted(bool succeeded) OVERRIDE {}
+
+ private:
+  scoped_refptr<PrefRegistry> pref_registry_;
+};
+
+const char kTrackedAtomic[] = "tracked_atomic";
+const char kProtectedAtomic[] = "protected_atomic";
+const char kProtectedSplit[] = "protected_split";
+
+const char kFoobar[] = "FOOBAR";
+const char kBarfoo[] = "BARFOO";
+const char kHelloWorld[] = "HELLOWORLD";
+const char kGoodbyeWorld[] = "GOODBYEWORLD";
+
+const PrefHashFilter::TrackedPreferenceMetadata kConfiguration[] = {
+    {0, kTrackedAtomic, PrefHashFilter::NO_ENFORCEMENT,
+     PrefHashFilter::TRACKING_STRATEGY_ATOMIC},
+    {1, kProtectedAtomic, PrefHashFilter::ENFORCE_ON_LOAD,
+     PrefHashFilter::TRACKING_STRATEGY_ATOMIC},
+    {2, kProtectedSplit, PrefHashFilter::ENFORCE_ON_LOAD,
+     PrefHashFilter::TRACKING_STRATEGY_SPLIT}};
+
+}  // namespace
+
+class ProfilePrefStoreManagerTest : public testing::Test {
+ public:
+  ProfilePrefStoreManagerTest()
+      : configuration_(kConfiguration,
+                       kConfiguration + arraysize(kConfiguration)),
+        profile_pref_registry_(new user_prefs::PrefRegistrySyncable),
+        registry_verifier_(profile_pref_registry_) {}
+
+  virtual void SetUp() OVERRIDE {
+    ProfilePrefStoreManager::RegisterPrefs(local_state_.registry());
+    ProfilePrefStoreManager::RegisterProfilePrefs(profile_pref_registry_);
+    for (const PrefHashFilter::TrackedPreferenceMetadata* it = kConfiguration;
+         it != kConfiguration + arraysize(kConfiguration);
+         ++it) {
+      if (it->strategy == PrefHashFilter::TRACKING_STRATEGY_ATOMIC) {
+        profile_pref_registry_->RegisterStringPref(
+            it->name, "", user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+      } else {
+        profile_pref_registry_->RegisterDictionaryPref(
+            it->name, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+      }
+    }
+    ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
+
+    manager_.reset(new ProfilePrefStoreManager(profile_dir_.path(),
+                                               configuration_,
+                                               configuration_.size(),
+                                               "seed",
+                                               "device_id",
+                                               &local_state_));
+  }
+
+  virtual void TearDown() OVERRIDE {
+    if (pref_store_) {
+      // Force everything to be written to disk, triggering the PrefHashFilter
+      // while our RegistryVerifier is watching.
+      pref_store_->CommitPendingWrite();
+      base::RunLoop().RunUntilIdle();
+
+      pref_store_->RemoveObserver(&registry_verifier_);
+      pref_store_ = NULL;
+      // Nothing should have to happen on the background threads, but just in
+      // case...
+      base::RunLoop().RunUntilIdle();
+    }
+  }
+
+ protected:
+  void InitializePrefs() {
+    scoped_refptr<PersistentPrefStore> pref_store =
+        manager_->CreateProfilePrefStore(
+            main_message_loop_.message_loop_proxy());
+    pref_store->AddObserver(&registry_verifier_);
+    PersistentPrefStore::PrefReadError error = pref_store->ReadPrefs();
+    ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE, error);
+    pref_store->SetValue(kTrackedAtomic, new base::StringValue(kFoobar));
+    pref_store->SetValue(kProtectedAtomic, new base::StringValue(kHelloWorld));
+    pref_store->RemoveObserver(&registry_verifier_);
+    pref_store = NULL;
+    base::RunLoop().RunUntilIdle();
+  }
+
+  void LoadExistingPrefs() {
+    pref_store_ = manager_->CreateProfilePrefStore(
+        main_message_loop_.message_loop_proxy());
+    pref_store_->AddObserver(&registry_verifier_);
+    EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+              pref_store_->ReadPrefs());
+  }
+
+  void ReplaceStringInPrefs(const std::string& find,
+                            const std::string& replace) {
+    // Tamper with the file's contents
+    base::FilePath pref_file_path =
+        ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
+            profile_dir_.path());
+    std::string pref_file_contents;
+    EXPECT_TRUE(base::ReadFileToString(pref_file_path, &pref_file_contents));
+    ReplaceSubstringsAfterOffset(&pref_file_contents, 0u, find, replace);
+    EXPECT_EQ(static_cast<int>(pref_file_contents.length()),
+              base::WriteFile(pref_file_path,
+                              pref_file_contents.c_str(),
+                              pref_file_contents.length()));
+  }
+
+  void ExpectStringValueEquals(const std::string& name,
+                               const std::string& expected) {
+    const base::Value* value = NULL;
+    std::string as_string;
+    if (!pref_store_->GetValue(name, &value)) {
+      ADD_FAILURE() << name << " is not a defined value.";
+    } else if (!value->GetAsString(&as_string)) {
+      ADD_FAILURE() << name << " could not be coerced to a string.";
+    } else {
+      EXPECT_EQ(expected, as_string);
+    }
+  }
+
+  base::MessageLoop main_message_loop_;
+  std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration_;
+  base::ScopedTempDir profile_dir_;
+  TestingPrefServiceSimple local_state_;
+  scoped_refptr<user_prefs::PrefRegistrySyncable> profile_pref_registry_;
+  RegistryVerifier registry_verifier_;
+  scoped_ptr<ProfilePrefStoreManager> manager_;
+  scoped_refptr<PersistentPrefStore> pref_store_;
+};
+
+TEST_F(ProfilePrefStoreManagerTest, StoreValues) {
+  InitializePrefs();
+
+  LoadExistingPrefs();
+
+  ExpectStringValueEquals(kTrackedAtomic, kFoobar);
+  ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
+}
+
+TEST_F(ProfilePrefStoreManagerTest, GetPrefFilePathFromProfilePath) {
+  base::FilePath pref_file_path =
+      ProfilePrefStoreManager::GetPrefFilePathFromProfilePath(
+          profile_dir_.path());
+
+  ASSERT_FALSE(base::PathExists(pref_file_path));
+
+  InitializePrefs();
+
+  ASSERT_TRUE(base::PathExists(pref_file_path));
+}
+
+TEST_F(ProfilePrefStoreManagerTest, ProtectValues) {
+  InitializePrefs();
+
+  ReplaceStringInPrefs(kFoobar, kBarfoo);
+  ReplaceStringInPrefs(kHelloWorld, kGoodbyeWorld);
+
+  LoadExistingPrefs();
+
+  // kTrackedAtomic is unprotected and thus will be loaded as it appears on
+  // disk.
+  ExpectStringValueEquals(kTrackedAtomic, kBarfoo);
+
+  // If preference tracking is supported, the tampered value of kProtectedAtomic
+  // will be discarded at load time, leaving this preference undefined.
+  EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
+            pref_store_->GetValue(kProtectedAtomic, NULL));
+}
+
+TEST_F(ProfilePrefStoreManagerTest, ResetPrefHashStore) {
+  InitializePrefs();
+
+  manager_->ResetPrefHashStore();
+
+  LoadExistingPrefs();
+
+  // kTrackedAtomic is loaded as it appears on disk.
+  ExpectStringValueEquals(kTrackedAtomic, kFoobar);
+  // If preference tracking is supported, the tampered value of kProtectedAtomic
+  // will be discarded at load time, leaving this preference undefined.
+  EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
+            pref_store_->GetValue(kProtectedAtomic, NULL));
+}
+
+TEST_F(ProfilePrefStoreManagerTest, ResetAllPrefHashStores) {
+  InitializePrefs();
+
+  ProfilePrefStoreManager::ResetAllPrefHashStores(&local_state_);
+
+  LoadExistingPrefs();
+
+  // kTrackedAtomic is loaded as it appears on disk.
+  ExpectStringValueEquals(kTrackedAtomic, kFoobar);
+  // If preference tracking is supported, kProtectedAtomic will be undefined
+  // because the value was discarded due to loss of the hash store contents.
+  EXPECT_EQ(!ProfilePrefStoreManager::kPlatformSupportsPreferenceTracking,
+            pref_store_->GetValue(kProtectedAtomic, NULL));
+}
+
+TEST_F(ProfilePrefStoreManagerTest, UpdateProfileHashStoreIfRequired) {
+  InitializePrefs();
+
+  manager_->ResetPrefHashStore();
+
+  // This is a no-op if !kPlatformSupportsPreferenceTracking.
+  manager_->UpdateProfileHashStoreIfRequired(
+      main_message_loop_.message_loop_proxy());
+  base::RunLoop().RunUntilIdle();
+
+  // At the moment, UpdateProfileHashStoreIfRequired will accept existing
+  // values.
+  LoadExistingPrefs();
+
+  // These expectations hold whether or not tracking is supported.
+  ExpectStringValueEquals(kTrackedAtomic, kFoobar);
+  ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
+}
+
+TEST_F(ProfilePrefStoreManagerTest, InitializePrefsFromMasterPrefs) {
+  scoped_ptr<base::DictionaryValue> master_prefs(
+      new base::DictionaryValue);
+  master_prefs->Set(kTrackedAtomic, new base::StringValue(kFoobar));
+  master_prefs->Set(kProtectedAtomic, new base::StringValue(kHelloWorld));
+  ASSERT_TRUE(
+      manager_->InitializePrefsFromMasterPrefs(*master_prefs));
+
+  LoadExistingPrefs();
+
+  // Verify that InitializePrefsFromMasterPrefs correctly applied the MACs
+  // necessary to authenticate these values.
+  ExpectStringValueEquals(kTrackedAtomic, kFoobar);
+  ExpectStringValueEquals(kProtectedAtomic, kHelloWorld);
+}
diff --git a/chrome/browser/prefs/tracked/hash_store_contents.h b/chrome/browser/prefs/tracked/hash_store_contents.h
index e07104b..388aad2 100644
--- a/chrome/browser/prefs/tracked/hash_store_contents.h
+++ b/chrome/browser/prefs/tracked/hash_store_contents.h
@@ -13,7 +13,14 @@
 class DictionaryValue;
 } // namespace base
 
-// Provides access to the contents of a preference hash store.
+// Provides access to the contents of a preference hash store. The store
+// contains the following data:
+// Contents: a client-defined dictionary that should map preference names to
+// MACs.
+// Version: a client-defined version number for the format of Contents.
+// Super MAC: a MAC that authenticates the entirety of Contents.
+// Legacy hash stores may have an ID that was incorporated into MAC
+// calculations. The ID, if any, is available via |hash_store_id()|.
 class HashStoreContents {
  public:
   // Used to modify a DictionaryValue stored in the preference hash store. The
diff --git a/chrome/browser/prefs/tracked/segregated_pref_store.cc b/chrome/browser/prefs/tracked/segregated_pref_store.cc
new file mode 100644
index 0000000..5c51da9
--- /dev/null
+++ b/chrome/browser/prefs/tracked/segregated_pref_store.cc
@@ -0,0 +1,182 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/tracked/segregated_pref_store.h"
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "base/values.h"
+
+SegregatedPrefStore::AggregatingObserver::AggregatingObserver(
+    SegregatedPrefStore* outer)
+    : outer_(outer),
+      failed_sub_initializations_(0),
+      successful_sub_initializations_(0) {}
+
+void SegregatedPrefStore::AggregatingObserver::OnPrefValueChanged(
+    const std::string& key) {
+  // There is no need to tell clients about changes if they have not yet been
+  // told about initialization.
+  if (failed_sub_initializations_ + successful_sub_initializations_ < 2)
+    return;
+
+  FOR_EACH_OBSERVER(
+      PrefStore::Observer, outer_->observers_, OnPrefValueChanged(key));
+}
+
+void SegregatedPrefStore::AggregatingObserver::OnInitializationCompleted(
+    bool succeeded) {
+  if (succeeded)
+    ++successful_sub_initializations_;
+  else
+    ++failed_sub_initializations_;
+
+  DCHECK_LE(failed_sub_initializations_ + successful_sub_initializations_, 2);
+
+  if (failed_sub_initializations_ + successful_sub_initializations_ == 2) {
+
+    if (!outer_->on_initialization_.is_null())
+      outer_->on_initialization_.Run();
+
+    if (successful_sub_initializations_ == 2 && outer_->read_error_delegate_) {
+      PersistentPrefStore::PrefReadError read_error = outer_->GetReadError();
+      if (read_error != PersistentPrefStore::PREF_READ_ERROR_NONE)
+        outer_->read_error_delegate_->OnError(read_error);
+    }
+
+    FOR_EACH_OBSERVER(
+        PrefStore::Observer,
+        outer_->observers_,
+        OnInitializationCompleted(successful_sub_initializations_ == 2));
+  }
+}
+
+SegregatedPrefStore::SegregatedPrefStore(
+    const scoped_refptr<PersistentPrefStore>& default_pref_store,
+    const scoped_refptr<PersistentPrefStore>& selected_pref_store,
+    const std::set<std::string>& selected_pref_names,
+    const base::Closure& on_initialization)
+    : default_pref_store_(default_pref_store),
+      selected_pref_store_(selected_pref_store),
+      selected_preference_names_(selected_pref_names),
+      on_initialization_(on_initialization),
+      aggregating_observer_(this) {
+
+  default_pref_store_->AddObserver(&aggregating_observer_);
+  selected_pref_store_->AddObserver(&aggregating_observer_);
+}
+
+void SegregatedPrefStore::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void SegregatedPrefStore::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+bool SegregatedPrefStore::HasObservers() const {
+  return observers_.might_have_observers();
+}
+
+bool SegregatedPrefStore::IsInitializationComplete() const {
+  return default_pref_store_->IsInitializationComplete() &&
+         selected_pref_store_->IsInitializationComplete();
+}
+
+bool SegregatedPrefStore::GetValue(const std::string& key,
+                                   const base::Value** result) const {
+  return StoreForKey(key)->GetValue(key, result);
+}
+
+void SegregatedPrefStore::SetValue(const std::string& key, base::Value* value) {
+  StoreForKey(key)->SetValue(key, value);
+}
+
+void SegregatedPrefStore::RemoveValue(const std::string& key) {
+  StoreForKey(key)->RemoveValue(key);
+}
+
+bool SegregatedPrefStore::GetMutableValue(const std::string& key,
+                                          base::Value** result) {
+  return StoreForKey(key)->GetMutableValue(key, result);
+}
+
+void SegregatedPrefStore::ReportValueChanged(const std::string& key) {
+  StoreForKey(key)->ReportValueChanged(key);
+}
+
+void SegregatedPrefStore::SetValueSilently(const std::string& key,
+                                           base::Value* value) {
+  StoreForKey(key)->SetValueSilently(key, value);
+}
+
+bool SegregatedPrefStore::ReadOnly() const {
+  return selected_pref_store_->ReadOnly() ||
+         default_pref_store_->ReadOnly();
+}
+
+PersistentPrefStore::PrefReadError SegregatedPrefStore::GetReadError() const {
+  PersistentPrefStore::PrefReadError read_error =
+      default_pref_store_->GetReadError();
+  return read_error != PersistentPrefStore::PREF_READ_ERROR_NONE
+             ? read_error
+             : selected_pref_store_->GetReadError();
+}
+
+PersistentPrefStore::PrefReadError SegregatedPrefStore::ReadPrefs() {
+  PersistentPrefStore::PrefReadError unselected_read_error =
+      default_pref_store_->ReadPrefs();
+  PersistentPrefStore::PrefReadError selected_read_error =
+      selected_pref_store_->ReadPrefs();
+
+  return unselected_read_error != PersistentPrefStore::PREF_READ_ERROR_NONE
+             ? unselected_read_error
+             : selected_read_error;
+}
+
+void SegregatedPrefStore::ReadPrefsAsync(ReadErrorDelegate* error_delegate) {
+  read_error_delegate_.reset(error_delegate);
+  default_pref_store_->ReadPrefsAsync(NULL);
+  selected_pref_store_->ReadPrefsAsync(NULL);
+}
+
+void SegregatedPrefStore::CommitPendingWrite() {
+  default_pref_store_->CommitPendingWrite();
+  selected_pref_store_->CommitPendingWrite();
+}
+
+SegregatedPrefStore::~SegregatedPrefStore() {
+  default_pref_store_->RemoveObserver(&aggregating_observer_);
+  selected_pref_store_->RemoveObserver(&aggregating_observer_);
+}
+
+const PersistentPrefStore*
+SegregatedPrefStore::StoreForKey(const std::string& key) const {
+  if (ContainsKey(selected_preference_names_, key) ||
+      selected_pref_store_->GetValue(key, NULL)) {
+    return selected_pref_store_.get();
+  }
+  return default_pref_store_.get();
+}
+
+PersistentPrefStore* SegregatedPrefStore::StoreForKey(const std::string& key) {
+  if (ContainsKey(selected_preference_names_, key))
+    return selected_pref_store_.get();
+
+  // Check if this unselected value was previously selected. If so, migrate it
+  // back to the unselected store.
+  // It's hard to do this in a single pass at startup because PrefStore does not
+  // permit us to enumerate its contents.
+  const base::Value* value = NULL;
+  if (selected_pref_store_->GetValue(key, &value)) {
+    scoped_ptr<base::Value> migrated_value(value->DeepCopy());
+    value = NULL;
+    default_pref_store_->SetValue(key, migrated_value.release());
+    default_pref_store_->CommitPendingWrite();
+    selected_pref_store_->RemoveValue(key);
+    selected_pref_store_->CommitPendingWrite();
+  }
+
+  return default_pref_store_.get();
+}
diff --git a/chrome/browser/prefs/tracked/segregated_pref_store.h b/chrome/browser/prefs/tracked/segregated_pref_store.h
new file mode 100644
index 0000000..b7bc6e9
--- /dev/null
+++ b/chrome/browser/prefs/tracked/segregated_pref_store.h
@@ -0,0 +1,104 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PREFS_TRACKED_SEGREGATED_PREF_STORE_H_
+#define CHROME_BROWSER_PREFS_TRACKED_SEGREGATED_PREF_STORE_H_
+
+#include <set>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "base/prefs/persistent_pref_store.h"
+
+// Provides a unified PersistentPrefStore implementation that splits its storage
+// and retrieval between two underlying PersistentPrefStore instances: a set of
+// preference names is used to partition the preferences.
+class SegregatedPrefStore : public PersistentPrefStore {
+ public:
+  // Creates an instance that delegates to |selected_pref_store| for the
+  // preferences named in |selected_pref_names| and to |default_pref_store|
+  // for all others. If an unselected preference is present in
+  // |selected_pref_store| (i.e. because it was previously selected) it will
+  // be migrated back to |default_pref_store| upon access via a non-const
+  // method.
+  // |on_initialization| will be invoked when both stores have been initialized,
+  // before observers of the combined store are notified.
+  SegregatedPrefStore(
+      const scoped_refptr<PersistentPrefStore>& default_pref_store,
+      const scoped_refptr<PersistentPrefStore>& selected_pref_store,
+      const std::set<std::string>& selected_pref_names,
+      const base::Closure& on_initialization);
+
+  // PrefStore implementation
+  virtual void AddObserver(Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(Observer* observer) OVERRIDE;
+  virtual bool HasObservers() const OVERRIDE;
+  virtual bool IsInitializationComplete() const OVERRIDE;
+  virtual bool GetValue(const std::string& key,
+                        const base::Value** result) const OVERRIDE;
+
+  // WriteablePrefStore implementation
+  virtual void SetValue(const std::string& key, base::Value* value) OVERRIDE;
+  virtual void RemoveValue(const std::string& key) OVERRIDE;
+
+  // PersistentPrefStore implementation
+  virtual bool GetMutableValue(const std::string& key,
+                               base::Value** result) OVERRIDE;
+  virtual void ReportValueChanged(const std::string& key) OVERRIDE;
+  virtual void SetValueSilently(const std::string& key,
+                                base::Value* value) OVERRIDE;
+  virtual bool ReadOnly() const OVERRIDE;
+  virtual PrefReadError GetReadError() const OVERRIDE;
+  virtual PrefReadError ReadPrefs() OVERRIDE;
+  virtual void ReadPrefsAsync(ReadErrorDelegate* error_delegate) OVERRIDE;
+  virtual void CommitPendingWrite() OVERRIDE;
+
+ private:
+  // Aggregates events from the underlying stores and synthesizes external
+  // events via |on_initialization|, |read_error_delegate_|, and |observers_|.
+  class AggregatingObserver : public PrefStore::Observer {
+   public:
+    explicit AggregatingObserver(SegregatedPrefStore* outer);
+
+    // PrefStore::Observer implementation
+    virtual void OnPrefValueChanged(const std::string& key) OVERRIDE;
+    virtual void OnInitializationCompleted(bool succeeded) OVERRIDE;
+
+   private:
+    SegregatedPrefStore* outer_;
+    int failed_sub_initializations_;
+    int successful_sub_initializations_;
+
+    DISALLOW_COPY_AND_ASSIGN(AggregatingObserver);
+  };
+
+  virtual ~SegregatedPrefStore();
+
+  // Returns |selected_pref_store| if |key| is selected or a value is present
+  // in |selected_pref_store|. This could happen if |key| was previously
+  // selected.
+  const PersistentPrefStore* StoreForKey(const std::string& key) const;
+
+  // Returns |selected_pref_store| if |key| is selected. If |key| is
+  // unselected but has a value in |selected_pref_store|, moves the value to
+  // |default_pref_store| before returning |default_pref_store|.
+  PersistentPrefStore* StoreForKey(const std::string& key);
+
+  scoped_refptr<PersistentPrefStore> default_pref_store_;
+  scoped_refptr<PersistentPrefStore> selected_pref_store_;
+  std::set<std::string> selected_preference_names_;
+  base::Closure on_initialization_;
+
+  scoped_ptr<PersistentPrefStore::ReadErrorDelegate> read_error_delegate_;
+  ObserverList<PrefStore::Observer, true> observers_;
+  AggregatingObserver aggregating_observer_;
+
+  DISALLOW_COPY_AND_ASSIGN(SegregatedPrefStore);
+};
+
+#endif  // CHROME_BROWSER_PREFS_TRACKED_SEGREGATED_PREF_STORE_H_
diff --git a/chrome/browser/prefs/tracked/segregated_pref_store_unittest.cc b/chrome/browser/prefs/tracked/segregated_pref_store_unittest.cc
new file mode 100644
index 0000000..ab91dfc
--- /dev/null
+++ b/chrome/browser/prefs/tracked/segregated_pref_store_unittest.cc
@@ -0,0 +1,255 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/prefs/tracked/segregated_pref_store.h"
+
+#include <set>
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/persistent_pref_store.h"
+#include "base/prefs/pref_store_observer_mock.h"
+#include "base/prefs/testing_pref_store.h"
+#include "base/values.h"
+#include "chrome/browser/prefs/tracked/segregated_pref_store.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+const char kSelectedPref[] = "selected_pref";
+const char kUnselectedPref[] = "unselected_pref";
+
+const char kValue1[] = "value1";
+const char kValue2[] = "value2";
+
+class MockReadErrorDelegate : public PersistentPrefStore::ReadErrorDelegate {
+ public:
+  struct Data {
+    Data(bool invoked_in, PersistentPrefStore::PrefReadError read_error_in)
+        : invoked(invoked_in), read_error(read_error_in) {}
+
+    bool invoked;
+    PersistentPrefStore::PrefReadError read_error;
+  };
+
+  explicit MockReadErrorDelegate(Data* data) : data_(data) {
+    DCHECK(data_);
+    EXPECT_FALSE(data_->invoked);
+  }
+
+  // PersistentPrefStore::ReadErrorDelegate implementation
+  virtual void OnError(PersistentPrefStore::PrefReadError read_error) OVERRIDE {
+    EXPECT_FALSE(data_->invoked);
+    data_->invoked = true;
+    data_->read_error = read_error;
+  }
+
+ private:
+  Data* data_;
+};
+
+}  // namespace
+
+class SegregatedPrefStoreTest : public testing::Test {
+ public:
+  SegregatedPrefStoreTest()
+      : initialization_callback_invoked_(false),
+        read_error_delegate_data_(false,
+                                  PersistentPrefStore::PREF_READ_ERROR_NONE),
+        read_error_delegate_(
+            new MockReadErrorDelegate(&read_error_delegate_data_)) {}
+
+  virtual void SetUp() OVERRIDE {
+    selected_store_ = new TestingPrefStore;
+    default_store_ = new TestingPrefStore;
+
+    std::set<std::string> selected_pref_names;
+    selected_pref_names.insert(kSelectedPref);
+
+    segregated_store_ = new SegregatedPrefStore(
+        default_store_,
+        selected_store_,
+        selected_pref_names,
+        base::Bind(&SegregatedPrefStoreTest::InitializationCallback,
+                   base::Unretained(this)));
+
+    segregated_store_->AddObserver(&observer_);
+  }
+
+  virtual void TearDown() OVERRIDE {
+    segregated_store_->RemoveObserver(&observer_);
+  }
+
+ protected:
+  scoped_ptr<PersistentPrefStore::ReadErrorDelegate> GetReadErrorDelegate() {
+    EXPECT_TRUE(read_error_delegate_);
+    return read_error_delegate_
+        .PassAs<PersistentPrefStore::ReadErrorDelegate>();
+  }
+
+  PrefStoreObserverMock observer_;
+  bool initialization_callback_invoked_;
+
+  scoped_refptr<TestingPrefStore> default_store_;
+  scoped_refptr<TestingPrefStore> selected_store_;
+  scoped_refptr<SegregatedPrefStore> segregated_store_;
+
+  MockReadErrorDelegate::Data read_error_delegate_data_;
+
+ private:
+  void InitializationCallback() {
+    EXPECT_FALSE(observer_.initialized);
+    EXPECT_FALSE(initialization_callback_invoked_);
+    initialization_callback_invoked_ = true;
+  }
+
+  scoped_ptr<MockReadErrorDelegate> read_error_delegate_;
+};
+
+TEST_F(SegregatedPrefStoreTest, StoreValues) {
+  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+            segregated_store_->ReadPrefs());
+
+  // Properly stores new values.
+  segregated_store_->SetValue(kSelectedPref, new base::StringValue(kValue1));
+  segregated_store_->SetValue(kUnselectedPref, new base::StringValue(kValue2));
+
+  ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
+  ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
+  ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
+  ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
+
+  ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
+  ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
+
+  ASSERT_FALSE(selected_store_->committed());
+  ASSERT_FALSE(default_store_->committed());
+
+  segregated_store_->CommitPendingWrite();
+
+  ASSERT_TRUE(selected_store_->committed());
+  ASSERT_TRUE(default_store_->committed());
+}
+
+TEST_F(SegregatedPrefStoreTest, ReadValues) {
+  selected_store_->SetValue(kSelectedPref, new base::StringValue(kValue1));
+  default_store_->SetValue(kUnselectedPref,
+                               new base::StringValue(kValue2));
+
+  // Works properly with values that are already there.
+  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+            segregated_store_->ReadPrefs());
+  ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+            segregated_store_->GetReadError());
+
+  ASSERT_TRUE(selected_store_->GetValue(kSelectedPref, NULL));
+  ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
+  ASSERT_FALSE(default_store_->GetValue(kSelectedPref, NULL));
+  ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
+
+  ASSERT_TRUE(segregated_store_->GetValue(kSelectedPref, NULL));
+  ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
+}
+
+TEST_F(SegregatedPrefStoreTest, PreviouslySelected) {
+  selected_store_->SetValue(kUnselectedPref, new base::StringValue(kValue1));
+  segregated_store_->ReadPrefs();
+  // It will read from the selected store.
+  ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
+  ASSERT_TRUE(selected_store_->GetValue(kUnselectedPref, NULL));
+  ASSERT_FALSE(default_store_->GetValue(kUnselectedPref, NULL));
+
+  // But when we update the value...
+  segregated_store_->SetValue(kUnselectedPref, new base::StringValue(kValue2));
+  // ...it will be migrated.
+  ASSERT_TRUE(segregated_store_->GetValue(kUnselectedPref, NULL));
+  ASSERT_FALSE(selected_store_->GetValue(kUnselectedPref, NULL));
+  ASSERT_TRUE(default_store_->GetValue(kUnselectedPref, NULL));
+}
+
+TEST_F(SegregatedPrefStoreTest, Observer) {
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE,
+            segregated_store_->ReadPrefs());
+  EXPECT_TRUE(initialization_callback_invoked_);
+  EXPECT_TRUE(observer_.initialized);
+  EXPECT_TRUE(observer_.initialization_success);
+  EXPECT_TRUE(observer_.changed_keys.empty());
+  segregated_store_->SetValue(kSelectedPref, new base::StringValue(kValue1));
+  observer_.VerifyAndResetChangedKey(kSelectedPref);
+  segregated_store_->SetValue(kUnselectedPref, new base::StringValue(kValue2));
+  observer_.VerifyAndResetChangedKey(kUnselectedPref);
+}
+
+TEST_F(SegregatedPrefStoreTest, SelectedPrefReadError) {
+  selected_store_->set_read_error(
+      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->ReadPrefs());
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, UnselectedPrefReadError) {
+  default_store_->set_read_error(
+      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->ReadPrefs());
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, BothPrefReadError) {
+  default_store_->set_read_error(
+      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+  selected_store_->set_read_error(
+      PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->ReadPrefs());
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, BothPrefReadErrorAsync) {
+  default_store_->set_read_error(
+      PersistentPrefStore::PREF_READ_ERROR_NO_FILE);
+  selected_store_->set_read_error(
+      PersistentPrefStore::PREF_READ_ERROR_ACCESS_DENIED);
+
+  selected_store_->SetBlockAsyncRead(true);
+
+  EXPECT_FALSE(read_error_delegate_data_.invoked);
+
+  segregated_store_->ReadPrefsAsync(GetReadErrorDelegate().release());
+
+  EXPECT_FALSE(read_error_delegate_data_.invoked);
+
+  selected_store_->SetBlockAsyncRead(false);
+
+  EXPECT_TRUE(read_error_delegate_data_.invoked);
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->GetReadError());
+  EXPECT_EQ(PersistentPrefStore::PREF_READ_ERROR_NO_FILE,
+            segregated_store_->GetReadError());
+}
+
+TEST_F(SegregatedPrefStoreTest, IsInitializationComplete) {
+  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+  segregated_store_->ReadPrefs();
+  EXPECT_TRUE(segregated_store_->IsInitializationComplete());
+}
+
+TEST_F(SegregatedPrefStoreTest, IsInitializationCompleteAsync) {
+  selected_store_->SetBlockAsyncRead(true);
+  default_store_->SetBlockAsyncRead(true);
+  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+  segregated_store_->ReadPrefsAsync(NULL);
+  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+  selected_store_->SetBlockAsyncRead(false);
+  EXPECT_FALSE(segregated_store_->IsInitializationComplete());
+  default_store_->SetBlockAsyncRead(false);
+  EXPECT_TRUE(segregated_store_->IsInitializationComplete());
+}
diff --git a/chrome/browser/prerender/prerender_histograms.cc b/chrome/browser/prerender/prerender_histograms.cc
index 25af32f..3208e8a 100644
--- a/chrome/browser/prerender/prerender_histograms.cc
+++ b/chrome/browser/prerender/prerender_histograms.cc
@@ -349,6 +349,19 @@
           50));
 }
 
+void PrerenderHistograms::RecordAbandonTimeUntilUsed(
+    Origin origin,
+    base::TimeDelta time_until_used) const {
+  PREFIXED_HISTOGRAM(
+      "AbandonTimeUntilUsed", origin,
+      UMA_HISTOGRAM_CUSTOM_TIMES(
+          name,
+          time_until_used,
+          base::TimeDelta::FromMilliseconds(10),
+          base::TimeDelta::FromSeconds(30),
+          50));
+}
+
 void PrerenderHistograms::RecordPerSessionCount(Origin origin,
                                                 int count) const {
   PREFIXED_HISTOGRAM(
diff --git a/chrome/browser/prerender/prerender_histograms.h b/chrome/browser/prerender/prerender_histograms.h
index eed97aa..4c965bb 100644
--- a/chrome/browser/prerender/prerender_histograms.h
+++ b/chrome/browser/prerender/prerender_histograms.h
@@ -65,6 +65,11 @@
   void RecordTimeUntilUsed(Origin origin,
                            base::TimeDelta time_until_used) const;
 
+  // Records the time from when a prerender is abandoned to when the user
+  // navigates to it. This must be called on the UI thread.
+  void RecordAbandonTimeUntilUsed(Origin origin,
+                                  base::TimeDelta time_until_used) const;
+
   // Record a PerSessionCount data point.
   void RecordPerSessionCount(Origin origin, int count) const;
 
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index 264f50b..2c5832a 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -578,6 +578,21 @@
   }
 
   // At this point, we've determined that we will use the prerender.
+  if (!prerender_data->contents()->load_start_time().is_null()) {
+    histograms_->RecordTimeUntilUsed(
+        prerender_data->contents()->origin(),
+        GetCurrentTimeTicks() - prerender_data->contents()->load_start_time());
+  }
+  histograms_->RecordAbandonTimeUntilUsed(
+      prerender_data->contents()->origin(),
+      prerender_data->abandon_time().is_null() ?
+          base::TimeDelta() :
+          GetCurrentTimeTicks() - prerender_data->abandon_time());
+
+  histograms_->RecordPerSessionCount(prerender_data->contents()->origin(),
+                                     ++prerenders_per_session_count_);
+  histograms_->RecordUsedPrerender(prerender_data->contents()->origin());
+
   if (prerender_data->pending_swap())
     prerender_data->pending_swap()->set_swap_successful(true);
   ScopedVector<PrerenderData>::iterator to_erase =
@@ -588,16 +603,6 @@
       prerender_contents(prerender_data->ReleaseContents());
   active_prerenders_.erase(to_erase);
 
-  if (!prerender_contents->load_start_time().is_null()) {
-    histograms_->RecordTimeUntilUsed(
-        prerender_contents->origin(),
-        GetCurrentTimeTicks() - prerender_contents->load_start_time());
-  }
-
-  histograms_->RecordPerSessionCount(prerender_contents->origin(),
-                                     ++prerenders_per_session_count_);
-  histograms_->RecordUsedPrerender(prerender_contents->origin());
-
   // Mark prerender as used.
   prerender_contents->PrepareForUse();
 
@@ -988,6 +993,8 @@
     PrerenderHandle* handle) {
   DCHECK_LT(0, handle_count_);
   DCHECK_NE(static_cast<PrerenderContents*>(NULL), contents_);
+  if (abandon_time_.is_null())
+    abandon_time_ = base::TimeTicks::Now();
   // We intentionally don't decrement the handle count here, so that the
   // prerender won't be canceled until it times out.
   manager_->SourceNavigatedAway(this);
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index a42df8d..87d8b11 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -396,6 +396,8 @@
 
     int handle_count() const { return handle_count_; }
 
+    base::TimeTicks abandon_time() const { return abandon_time_; }
+
     base::TimeTicks expiry_time() const { return expiry_time_; }
     void set_expiry_time(base::TimeTicks expiry_time) {
       expiry_time_ = expiry_time;
@@ -419,6 +421,9 @@
     // only merges handles of running prerenders.
     int handle_count_;
 
+    // The time when OnHandleNavigatedAway was called.
+    base::TimeTicks abandon_time_;
+
     // After this time, this prerender is no longer fresh, and should be
     // removed.
     base::TimeTicks expiry_time_;
diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
index 3c4a8c8..6947c3b 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
+++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.cc
@@ -45,6 +45,7 @@
 }
 
 void CloudPrintProxyService::Initialize() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
                             ServiceProcessControl::SERVICE_EVENT_INITIALIZE,
                             ServiceProcessControl::SERVICE_EVENT_MAX);
@@ -72,6 +73,7 @@
 }
 
 void CloudPrintProxyService::RefreshStatusFromService() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   InvokeServiceTask(
       base::Bind(&CloudPrintProxyService::RefreshCloudPrintProxyStatus,
                  weak_factory_.GetWeakPtr()));
@@ -90,6 +92,7 @@
     const std::string& robot_email,
     const std::string& user_email,
     const base::DictionaryValue& user_preferences) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
                             ServiceProcessControl::SERVICE_EVENT_ENABLE,
                             ServiceProcessControl::SERVICE_EVENT_MAX);
@@ -102,6 +105,7 @@
 }
 
 void CloudPrintProxyService::DisableForUser() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   UMA_HISTOGRAM_ENUMERATION("CloudPrint.ServiceEvents",
                             ServiceProcessControl::SERVICE_EVENT_DISABLE,
                             ServiceProcessControl::SERVICE_EVENT_MAX);
@@ -111,6 +115,7 @@
 }
 
 bool CloudPrintProxyService::ApplyCloudPrintConnectorPolicy() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled)) {
     std::string email =
         profile_->GetPrefs()->GetString(prefs::kCloudPrintEmail);
@@ -136,8 +141,11 @@
   return true;
 }
 
-void CloudPrintProxyService::GetPrintersAvalibleForRegistration(
-      std::vector<std::string>* printers) {
+void CloudPrintProxyService::GetPrinters(const PrintersCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!profile_->GetPrefs()->GetBoolean(prefs::kCloudPrintProxyEnabled))
+    return;
+
   base::FilePath list_path(
       CommandLine::ForCurrentProcess()->GetSwitchValuePath(
           switches::kCloudPrintSetupProxy));
@@ -146,36 +154,40 @@
     base::ReadFileToString(list_path, &printers_json);
     scoped_ptr<base::Value> value(base::JSONReader::Read(printers_json));
     base::ListValue* list = NULL;
+    std::vector<std::string> printers;
     if (value && value->GetAsList(&list) && list) {
       for (size_t i = 0; i < list->GetSize(); ++i) {
         std::string printer;
         if (list->GetString(i, &printer))
-          printers->push_back(printer);
+          printers.push_back(printer);
       }
     }
     UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrintersList",
-                               printers->size());
+                               printers.size());
+    base::MessageLoop::current()->PostTask(FROM_HERE,
+                                           base::Bind(callback, printers));
   } else {
-    printing::PrinterList printer_list;
-    scoped_refptr<printing::PrintBackend> backend(
-        printing::PrintBackend::CreateInstance(NULL));
-    if (backend.get())
-      backend->EnumeratePrinters(&printer_list);
-    for (size_t i = 0; i < printer_list.size(); ++i)
-      printers->push_back(printer_list[i].printer_name);
-    UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrinters",
-                               printers->size());
+    InvokeServiceTask(
+        base::Bind(&CloudPrintProxyService::GetCloudPrintProxyPrinters,
+                   weak_factory_.GetWeakPtr(),
+                   callback));
   }
 }
 
+void CloudPrintProxyService::GetCloudPrintProxyPrinters(
+    const PrintersCallback& callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  ServiceProcessControl* process_control = GetServiceProcessControl();
+  DCHECK(process_control->IsConnected());
+  process_control->GetPrinters(callback);
+}
+
 void CloudPrintProxyService::RefreshCloudPrintProxyStatus() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   ServiceProcessControl* process_control = GetServiceProcessControl();
   DCHECK(process_control->IsConnected());
-  ServiceProcessControl::CloudPrintProxyInfoHandler callback =
-       base::Bind(&CloudPrintProxyService::ProxyInfoCallback,
-                  base::Unretained(this));
-  // GetCloudPrintProxyInfo takes ownership of callback.
+  ServiceProcessControl::CloudPrintProxyInfoCallback callback = base::Bind(
+      &CloudPrintProxyService::ProxyInfoCallback, base::Unretained(this));
   process_control->GetCloudPrintProxyInfo(callback);
 }
 
diff --git a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h
index 3ccd5c2..7155015 100644
--- a/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h
+++ b/chrome/browser/printing/cloud_print/cloud_print_proxy_service.h
@@ -33,10 +33,16 @@
   explicit CloudPrintProxyService(Profile* profile);
   virtual ~CloudPrintProxyService();
 
+  typedef base::Callback<void(const std::vector<std::string>&)>
+      PrintersCallback;
+
   // Initializes the object. This should be called every time an object of this
   // class is constructed.
   void Initialize();
 
+  // Returns list of printer names available for registration.
+  void GetPrinters(const PrintersCallback& callback);
+
   // Enables/disables cloud printing for the user
   virtual void EnableForUserWithRobot(
       const std::string& robot_auth_code,
@@ -56,16 +62,13 @@
 
   std::string proxy_id() const { return proxy_id_; }
 
-  // Returns list of printer names available for registration.
-  static void GetPrintersAvalibleForRegistration(
-      std::vector<std::string>* printers);
-
  private:
   // NotificationDelegate implementation for the token expired notification.
   class TokenExpiredNotificationDelegate;
   friend class TokenExpiredNotificationDelegate;
 
   // Methods that send an IPC to the service.
+  void GetCloudPrintProxyPrinters(const PrintersCallback& callback);
   void RefreshCloudPrintProxyStatus();
   void EnableCloudPrintProxyWithRobot(
       const std::string& robot_auth_code,
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 74d8b68..aeb95df 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -187,12 +187,12 @@
   local_discovery::PrivetNotificationServiceFactory::GetInstance();
 #endif
 #if defined(ENABLE_MANAGED_USERS)
-  ManagedUserServiceFactory::GetInstance();
-  ManagedUserSyncServiceFactory::GetInstance();
 #if defined(OS_CHROMEOS)
-  ManagedUserPasswordServiceFactory::GetInstance();
+  chromeos::ManagedUserPasswordServiceFactory::GetInstance();
   chromeos::ManagerPasswordServiceFactory::GetInstance();
 #endif
+  ManagedUserServiceFactory::GetInstance();
+  ManagedUserSyncServiceFactory::GetInstance();
 #endif
 #if !defined(OS_ANDROID)
   MediaGalleriesPreferencesFactory::GetInstance();
diff --git a/chrome/browser/profiles/gaia_info_update_service.cc b/chrome/browser/profiles/gaia_info_update_service.cc
index 9733fe4..9585110 100644
--- a/chrome/browser/profiles/gaia_info_update_service.cc
+++ b/chrome/browser/profiles/gaia_info_update_service.cc
@@ -131,20 +131,12 @@
     cache.SetGAIAPictureOfProfileAtIndex(profile_index, NULL);
   }
 
-  // If this profile hasn't switched to using GAIA information for the profile
-  // name and picture then switch it now. Once the profile has switched this
-  // preference guards against clobbering the user's custom settings.
-  if (!cache.GetHasMigratedToGAIAInfoOfProfileAtIndex(profile_index)) {
-    cache.SetHasMigratedToGAIAInfoOfProfileAtIndex(profile_index, true);
-    // Order matters here for shortcut management, like in
-    // ProfileShortcutManagerWin::OnProfileAdded, as the picture update does not
-    // allow us to change the target, so we have to apply any renaming first. We
-    // also need to re-fetch the index, as SetIsUsingGAIANameOfProfileAtIndex
-    // may alter it.
-    cache.SetIsUsingGAIANameOfProfileAtIndex(profile_index, true);
-    profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
-    cache.SetIsUsingGAIAPictureOfProfileAtIndex(profile_index, true);
-  }
+  // Order matters here for shortcut management, like in
+  // ProfileShortcutManagerWin::OnProfileAdded, as the picture update does not
+  // allow us to change the target, so we have to apply any renaming first. We
+  // also need to re-fetch the index, as changing the profile name may alter it.
+  profile_index = cache.GetIndexOfProfileWithPath(profile_->GetPath());
+  cache.SetIsUsingGAIAPictureOfProfileAtIndex(profile_index, true);
 }
 
 void GAIAInfoUpdateService::OnProfileDownloadFailure(
diff --git a/chrome/browser/profiles/gaia_info_update_service_unittest.cc b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
index 5aa1d7e..1eacf5b 100644
--- a/chrome/browser/profiles/gaia_info_update_service_unittest.cc
+++ b/chrome/browser/profiles/gaia_info_update_service_unittest.cc
@@ -95,8 +95,6 @@
 
   // On success both the profile info and GAIA info should be updated.
   size_t index = GetCache()->GetIndexOfProfileWithPath(profile()->GetPath());
-  EXPECT_TRUE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(index));
-  EXPECT_TRUE(GetCache()->IsUsingGAIANameOfProfileAtIndex(index));
   EXPECT_EQ(name, GetCache()->GetNameOfProfileAtIndex(index));
   EXPECT_EQ(name, GetCache()->GetGAIANameOfProfileAtIndex(index));
   EXPECT_TRUE(gfx::test::IsEqual(
@@ -119,7 +117,6 @@
                                    ProfileDownloaderDelegate::SERVICE_ERROR);
 
   // On failure nothing should be updated.
-  EXPECT_FALSE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(index));
   EXPECT_EQ(old_name, GetCache()->GetNameOfProfileAtIndex(index));
   EXPECT_EQ(base::string16(), GetCache()->GetGAIANameOfProfileAtIndex(index));
   EXPECT_TRUE(gfx::test::IsEqual(
@@ -128,38 +125,6 @@
   EXPECT_EQ(std::string(), service.GetCachedPictureURL());
 }
 
-TEST_F(GAIAInfoUpdateServiceTest, NoMigration) {
-  size_t index = GetCache()->GetIndexOfProfileWithPath(profile()->GetPath());
-  base::string16 old_name = GetCache()->GetNameOfProfileAtIndex(index);
-  gfx::Image old_image = GetCache()->GetAvatarIconOfProfileAtIndex(index);
-
-  // Mark the profile as migrated.
-  GetCache()->SetHasMigratedToGAIAInfoOfProfileAtIndex(index, true);
-
-  GAIAInfoUpdateService service(profile());
-  NiceMock<ProfileDownloaderMock> downloader(&service);
-  base::string16 new_name = base::ASCIIToUTF16("Pat Smith");
-  EXPECT_CALL(downloader, GetProfileFullName()).WillOnce(Return(new_name));
-  gfx::Image new_image = gfx::test::CreateImage();
-  const SkBitmap* new_bmp = new_image.ToSkBitmap();
-  EXPECT_CALL(downloader, GetProfilePicture()).WillOnce(Return(*new_bmp));
-  EXPECT_CALL(downloader, GetProfilePictureStatus()).
-      WillOnce(Return(ProfileDownloader::PICTURE_SUCCESS));
-  EXPECT_CALL(downloader, GetProfilePictureURL()).WillOnce(Return(""));
-
-  service.OnProfileDownloadSuccess(&downloader);
-
-  // On success with no migration the profile info should not be updated but
-  // the GAIA info should be updated.
-  EXPECT_TRUE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(index));
-  EXPECT_EQ(old_name, GetCache()->GetNameOfProfileAtIndex(index));
-  EXPECT_EQ(new_name, GetCache()->GetGAIANameOfProfileAtIndex(index));
-  EXPECT_TRUE(gfx::test::IsEqual(
-      old_image, GetCache()->GetAvatarIconOfProfileAtIndex(index)));
-  EXPECT_TRUE(gfx::test::IsEqual(
-      new_image, *GetCache()->GetGAIAPictureOfProfileAtIndex(index)));
-}
-
 TEST_F(GAIAInfoUpdateServiceTest, ShouldUseGAIAProfileInfo) {
 #if defined(OS_CHROMEOS)
   // This feature should never be enabled on ChromeOS.
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.cc b/chrome/browser/profiles/off_the_record_profile_impl.cc
index b73a0ec..13c48be 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.cc
+++ b/chrome/browser/profiles/off_the_record_profile_impl.cc
@@ -321,6 +321,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) {
   ChromeMidiPermissionContext* context =
       ChromeMidiPermissionContextFactory::GetForProfile(this);
@@ -328,6 +329,7 @@
                                       render_view_id,
                                       bridge_id,
                                       requesting_frame,
+                                      user_gesture,
                                       callback);
 }
 
diff --git a/chrome/browser/profiles/off_the_record_profile_impl.h b/chrome/browser/profiles/off_the_record_profile_impl.h
index 41577b1..8a66045 100644
--- a/chrome/browser/profiles/off_the_record_profile_impl.h
+++ b/chrome/browser/profiles/off_the_record_profile_impl.h
@@ -105,6 +105,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) OVERRIDE;
   virtual void CancelMidiSysExPermissionRequest(
       int render_process_id,
diff --git a/chrome/browser/profiles/profile_browsertest.cc b/chrome/browser/profiles/profile_browsertest.cc
index fde3caf..aa5039d 100644
--- a/chrome/browser/profiles/profile_browsertest.cc
+++ b/chrome/browser/profiles/profile_browsertest.cc
@@ -6,7 +6,6 @@
 
 #include "base/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/platform_file.h"
 #include "base/prefs/pref_service.h"
 #include "base/version.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -33,10 +32,6 @@
 // Creates a prefs file in the given directory.
 void CreatePrefsFileInDirectory(const base::FilePath& directory_path) {
   base::FilePath pref_path(directory_path.Append(chrome::kPreferencesFilename));
-  base::PlatformFile file = base::CreatePlatformFile(pref_path,
-      base::PLATFORM_FILE_CREATE | base::PLATFORM_FILE_WRITE, NULL, NULL);
-  ASSERT_TRUE(file != base::kInvalidPlatformFileValue);
-  ASSERT_TRUE(base::ClosePlatformFile(file));
   std::string data("{}");
   ASSERT_TRUE(base::WriteFile(pref_path, data.c_str(), data.size()));
 }
diff --git a/chrome/browser/profiles/profile_downloader.cc b/chrome/browser/profiles/profile_downloader.cc
index deb3b01..b599122 100644
--- a/chrome/browser/profiles/profile_downloader.cc
+++ b/chrome/browser/profiles/profile_downloader.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index bd46756..4f434b9 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -939,6 +939,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) {
   ChromeMidiPermissionContext* context =
       ChromeMidiPermissionContextFactory::GetForProfile(this);
@@ -946,6 +947,7 @@
                                       render_view_id,
                                       bridge_id,
                                       requesting_frame,
+                                      user_gesture,
                                       callback);
 }
 
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index f923cad..ec314d9 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -80,6 +80,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) OVERRIDE;
   virtual void CancelMidiSysExPermissionRequest(
       int render_process_id,
diff --git a/chrome/browser/profiles/profile_impl_io_data.cc b/chrome/browser/profiles/profile_impl_io_data.cc
index dd51909..a48a6b1 100644
--- a/chrome/browser/profiles/profile_impl_io_data.cc
+++ b/chrome/browser/profiles/profile_impl_io_data.cc
@@ -55,6 +55,9 @@
 namespace {
 
 net::BackendType ChooseCacheBackendType() {
+#if defined(OS_ANDROID)
+  return net::CACHE_BACKEND_SIMPLE;
+#else
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
   if (command_line.HasSwitch(switches::kUseSimpleCacheBackend)) {
     const std::string opt_value =
@@ -66,13 +69,6 @@
   }
   const std::string experiment_name =
       base::FieldTrialList::FindFullName("SimpleCacheTrial");
-#if defined(OS_ANDROID)
-  if (experiment_name == "ExperimentNo" ||
-      experiment_name == "ExperimentControl") {
-    return net::CACHE_BACKEND_BLOCKFILE;
-  }
-  return net::CACHE_BACKEND_SIMPLE;
-#else
   if (experiment_name == "ExperimentYes" ||
       experiment_name == "ExperimentYes2") {
     return net::CACHE_BACKEND_SIMPLE;
@@ -507,7 +503,7 @@
 
   if (IsDomainReliabilityMonitoringEnabled()) {
     domain_reliability_monitor_.reset(
-        new domain_reliability::DomainReliabilityMonitor());
+        new domain_reliability::DomainReliabilityMonitor(main_context));
     network_delegate()->set_domain_reliability_monitor(
         domain_reliability_monitor_.get());
   }
diff --git a/chrome/browser/profiles/profile_info_cache.cc b/chrome/browser/profiles/profile_info_cache.cc
index 8055c96..8c35787 100644
--- a/chrome/browser/profiles/profile_info_cache.cc
+++ b/chrome/browser/profiles/profile_info_cache.cc
@@ -10,6 +10,7 @@
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
 #include "base/prefs/scoped_user_pref_update.h"
@@ -22,6 +23,7 @@
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/profile_management_switches.h"
 #include "content/public/browser/browser_thread.h"
@@ -42,14 +44,12 @@
 const char kShortcutNameKey[] = "shortcut_name";
 const char kGAIANameKey[] = "gaia_name";
 const char kGAIAGivenNameKey[] = "gaia_given_name";
-const char kUseGAIANameKey[] = "use_gaia_name";
 const char kUserNameKey[] = "user_name";
 const char kIsUsingDefaultName[] = "is_using_default_name";
 const char kAvatarIconKey[] = "avatar_icon";
 const char kAuthCredentialsKey[] = "local_auth_credentials";
 const char kUseGAIAPictureKey[] = "use_gaia_picture";
 const char kBackgroundAppsKey[] = "background_apps";
-const char kHasMigratedToGAIAInfoKey[] = "has_migrated_to_gaia_info";
 const char kGAIAPictureFileNameKey[] = "gaia_picture_file_name";
 const char kIsManagedKey[] = "is_managed";
 const char kIsOmittedFromProfileListKey[] = "is_omitted_from_profile_list";
@@ -60,6 +60,7 @@
 
 const char kDefaultUrlPrefix[] = "chrome://theme/IDR_PROFILE_AVATAR_";
 const char kGAIAPictureFileName[] = "Google Profile Picture.png";
+const char kHighResAvatarFolderName[] = "Avatars";
 
 const int kDefaultAvatarIconResources[] = {
   IDR_PROFILE_AVATAR_0,
@@ -90,6 +91,37 @@
   IDR_PROFILE_AVATAR_25,
 };
 
+// File names for the high-res avatar icon resources. In the same order as
+// the avatars in kDefaultAvatarIconResources.
+const char* kDefaultAvatarIconResourceFileNames[] = {
+  "avatar_generic.png",
+  "avatar_generic_aqua.png",
+  "avatar_generic_blue.png",
+  "avatar_generic_green.png",
+  "avatar_generic_orange.png",
+  "avatar_generic_purple.png",
+  "avatar_generic_red.png",
+  "avatar_generic_yellow.png",
+  "avatar_secret_agent.png",
+  "avatar_superhero.png",
+  "avatar_volley_ball.png",
+  "avatar_businessman.png",
+  "avatar_ninja.png",
+  "avatar_alien.png",
+  "avatar_smiley.png",
+  "avatar_flower.png",
+  "avatar_pizza.png",
+  "avatar_soccer.png",
+  "avatar_burger.png",
+  "avatar_cat.png",
+  "avatar_cupcake.png",
+  "avatar_dog.png",
+  "avatar_horse.png",
+  "avatar_margarita.png",
+  "avatar_note.png",
+  "avatar_sun_cloud.png",
+};
+
 const size_t kDefaultAvatarIconsCount = arraysize(kDefaultAvatarIconResources);
 
 // The first 8 icons are generic.
@@ -152,6 +184,10 @@
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   *out_image = NULL;
 
+  // If the path doesn't exist, don't even try reading it.
+  if (!base::PathExists(image_path))
+    return;
+
   std::string image_data;
   if (!base::ReadFileToString(image_path, &image_data)) {
     LOG(ERROR) << "Failed to read PNG file from disk.";
@@ -225,7 +261,7 @@
 
 ProfileInfoCache::~ProfileInfoCache() {
   STLDeleteContainerPairSecondPointers(
-      gaia_pictures_.begin(), gaia_pictures_.end());
+      cached_avatar_images_.begin(), cached_avatar_images_.end());
 }
 
 void ProfileInfoCache::AddProfileToCache(const base::FilePath& profile_path,
@@ -318,8 +354,7 @@
   base::string16 name;
   // Unless the user has customized the profile name, we should use the
   // profile's Gaia given name, if it's available.
-  if (IsUsingGAIANameOfProfileAtIndex(index) &&
-      ProfileIsUsingDefaultNameAtIndex(index)) {
+  if (ProfileIsUsingDefaultNameAtIndex(index)) {
     base::string16 given_name = GetGAIAGivenNameOfProfileAtIndex(index);
     name = given_name.empty() ? GetGAIANameOfProfileAtIndex(index) : given_name;
   }
@@ -364,6 +399,13 @@
       return *image;
   }
 
+  // Use the high resolution version of the avatar if it exists.
+  if (switches::IsNewProfileManagement()) {
+    const gfx::Image* image = GetHighResAvatarOfProfileAtIndex(index);
+    if (image)
+      return *image;
+  }
+
   int resource_id = GetDefaultAvatarIconResourceIDAtIndex(
       GetAvatarIconIndexOfProfileAtIndex(index));
   return ResourceBundle::GetSharedInstance().GetNativeImageNamed(resource_id);
@@ -400,41 +442,55 @@
   return name;
 }
 
-bool ProfileInfoCache::IsUsingGAIANameOfProfileAtIndex(size_t index) const {
-  bool value = false;
-  GetInfoForProfileAtIndex(index)->GetBoolean(kUseGAIANameKey, &value);
-  return value;
-}
-
 const gfx::Image* ProfileInfoCache::GetGAIAPictureOfProfileAtIndex(
     size_t index) const {
   base::FilePath path = GetPathOfProfileAtIndex(index);
   std::string key = CacheKeyFromProfilePath(path);
 
-  // If the picture is already loaded then use it.
-  if (gaia_pictures_.count(key)) {
-    if (gaia_pictures_[key]->IsEmpty())
-      return NULL;
-    return gaia_pictures_[key];
-  }
-
   std::string file_name;
   GetInfoForProfileAtIndex(index)->GetString(
       kGAIAPictureFileNameKey, &file_name);
 
-  // If the picture is not on disk or it is already being loaded then return
-  // NULL.
-  if (file_name.empty() || gaia_pictures_loading_[key])
+  // If the picture is not on disk then return NULL.
+  if (file_name.empty())
     return NULL;
 
-  gaia_pictures_loading_[key] = true;
   base::FilePath image_path = path.AppendASCII(file_name);
+  return LoadAvatarPictureFromPath(key, image_path);
+}
+
+const gfx::Image* ProfileInfoCache::GetHighResAvatarOfProfileAtIndex(
+    size_t index) const {
+  int avatar_index = GetAvatarIconIndexOfProfileAtIndex(index);
+  std::string key = kDefaultAvatarIconResourceFileNames[avatar_index];
+
+  base::FilePath user_data_dir;
+  PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
+  base::FilePath image_path =
+      user_data_dir.AppendASCII(kHighResAvatarFolderName).AppendASCII(key);
+  return LoadAvatarPictureFromPath(key, image_path);
+}
+
+const gfx::Image* ProfileInfoCache::LoadAvatarPictureFromPath(
+    const std::string& key,
+    const base::FilePath& image_path) const {
+  // If the picture is already loaded then use it.
+  if (cached_avatar_images_.count(key)) {
+    if (cached_avatar_images_[key]->IsEmpty())
+      return NULL;
+    return cached_avatar_images_[key];
+  }
+
+  // If the picture is already being loaded then don't try loading it again.
+  if (cached_avatar_images_loading_[key])
+    return NULL;
+  cached_avatar_images_loading_[key] = true;
+
   gfx::Image** image = new gfx::Image*;
   BrowserThread::PostTaskAndReply(BrowserThread::FILE, FROM_HERE,
       base::Bind(&ReadBitmap, image_path, image),
-      base::Bind(&ProfileInfoCache::OnGAIAPictureLoaded,
-          const_cast<ProfileInfoCache*>(this)->AsWeakPtr(), path, image));
-
+      base::Bind(&ProfileInfoCache::OnAvatarPictureLoaded,
+          const_cast<ProfileInfoCache*>(this)->AsWeakPtr(), key, image));
   return NULL;
 }
 
@@ -474,19 +530,18 @@
   return value;
 }
 
-void ProfileInfoCache::OnGAIAPictureLoaded(const base::FilePath& path,
-                                           gfx::Image** image) const {
+void ProfileInfoCache::OnAvatarPictureLoaded(const std::string& key,
+                                             gfx::Image** image) const {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
-  std::string key = CacheKeyFromProfilePath(path);
-  gaia_pictures_loading_[key] = false;
+  cached_avatar_images_loading_[key] = false;
 
+  delete cached_avatar_images_[key];
   if (*image) {
-    delete gaia_pictures_[key];
-    gaia_pictures_[key] = *image;
+    cached_avatar_images_[key] = *image;
   } else {
     // Place an empty image in the cache to avoid reloading it again.
-    gaia_pictures_[key] = new gfx::Image();
+    cached_avatar_images_[key] = new gfx::Image();
   }
   delete image;
 
@@ -677,38 +732,17 @@
   SetInfoForProfileAtIndex(index, info.release());
 }
 
-void ProfileInfoCache::SetIsUsingGAIANameOfProfileAtIndex(size_t index,
-                                                          bool value) {
-  if (value == IsUsingGAIANameOfProfileAtIndex(index))
-    return;
-
-  base::string16 old_display_name = GetNameOfProfileAtIndex(index);
-  scoped_ptr<base::DictionaryValue> info(
-      GetInfoForProfileAtIndex(index)->DeepCopy());
-  info->SetBoolean(kUseGAIANameKey, value);
-  // This takes ownership of |info|.
-  SetInfoForProfileAtIndex(index, info.release());
-  base::string16 new_display_name = GetNameOfProfileAtIndex(index);
-  base::FilePath profile_path = GetPathOfProfileAtIndex(index);
-  UpdateSortForProfileIndex(index);
-
-  if (old_display_name != new_display_name) {
-    FOR_EACH_OBSERVER(ProfileInfoCacheObserver,
-                      observer_list_,
-                      OnProfileNameChanged(profile_path, old_display_name));
-  }
-}
-
 void ProfileInfoCache::SetGAIAPictureOfProfileAtIndex(size_t index,
                                                       const gfx::Image* image) {
   base::FilePath path = GetPathOfProfileAtIndex(index);
   std::string key = CacheKeyFromProfilePath(path);
 
   // Delete the old bitmap from cache.
-  std::map<std::string, gfx::Image*>::iterator it = gaia_pictures_.find(key);
-  if (it != gaia_pictures_.end()) {
+  std::map<std::string, gfx::Image*>::iterator it =
+      cached_avatar_images_.find(key);
+  if (it != cached_avatar_images_.end()) {
     delete it->second;
-    gaia_pictures_.erase(it);
+    cached_avatar_images_.erase(it);
   }
 
   std::string old_file_name;
@@ -725,7 +759,7 @@
     }
   } else {
     // Save the new bitmap to disk.
-    gaia_pictures_[key] = new gfx::Image(*image);
+    cached_avatar_images_[key] = new gfx::Image(*image);
     scoped_ptr<ImageData> data(new ImageData);
     scoped_refptr<base::RefCountedMemory> png_data = image->As1xPNGBytes();
     data->assign(png_data->front(), png_data->front() + png_data->size());
@@ -839,23 +873,6 @@
   }
 }
 
-bool ProfileInfoCache::GetHasMigratedToGAIAInfoOfProfileAtIndex(
-      size_t index) const {
-  bool value = false;
-  GetInfoForProfileAtIndex(index)->GetBoolean(
-      kHasMigratedToGAIAInfoKey, &value);
-  return value;
-}
-
-void ProfileInfoCache::SetHasMigratedToGAIAInfoOfProfileAtIndex(
-    size_t index, bool value) {
-  scoped_ptr<base::DictionaryValue> info(
-      GetInfoForProfileAtIndex(index)->DeepCopy());
-  info->SetBoolean(kHasMigratedToGAIAInfoKey, value);
-  // This takes ownership of |info|.
-  SetInfoForProfileAtIndex(index, info.release());
-}
-
 bool ProfileInfoCache::IconIndexIsUnique(size_t icon_index) const {
   for (size_t i = 0; i < GetNumberOfProfiles(); ++i) {
     if (GetAvatarIconIndexOfProfileAtIndex(i) == icon_index)
diff --git a/chrome/browser/profiles/profile_info_cache.h b/chrome/browser/profiles/profile_info_cache.h
index 42a0222..07384f4 100644
--- a/chrome/browser/profiles/profile_info_cache.h
+++ b/chrome/browser/profiles/profile_info_cache.h
@@ -77,7 +77,6 @@
       size_t index) const OVERRIDE;
   virtual base::string16 GetGAIAGivenNameOfProfileAtIndex(
       size_t index) const OVERRIDE;
-  virtual bool IsUsingGAIANameOfProfileAtIndex(size_t index) const OVERRIDE;
   // Returns the GAIA picture for the given profile. This may return NULL
   // if the profile does not have a GAIA picture or if the picture must be
   // loaded from disk.
@@ -111,7 +110,6 @@
   void SetGAIANameOfProfileAtIndex(size_t index, const base::string16& name);
   void SetGAIAGivenNameOfProfileAtIndex(size_t index,
                                         const base::string16& name);
-  void SetIsUsingGAIANameOfProfileAtIndex(size_t index, bool value);
   void SetGAIAPictureOfProfileAtIndex(size_t index, const gfx::Image* image);
   void SetIsUsingGAIAPictureOfProfileAtIndex(size_t index, bool value);
   void SetProfileSigninRequiredAtIndex(size_t index, bool value);
@@ -121,16 +119,6 @@
   // Returns unique name that can be assigned to a newly created profile.
   base::string16 ChooseNameForNewProfile(size_t icon_index) const;
 
-  // Checks if the given profile has switched to using GAIA information
-  // for the profile name and picture. This pref is used to switch over
-  // to GAIA info the first time it is available. Afterwards this pref is
-  // checked to prevent clobbering the user's custom settings.
-  bool GetHasMigratedToGAIAInfoOfProfileAtIndex(size_t index) const;
-
-  // Marks the given profile as having switched to using GAIA information
-  // for the profile name and picture.
-  void SetHasMigratedToGAIAInfoOfProfileAtIndex(size_t index, bool value);
-
   // Returns an avatar icon index that can be assigned to a newly created
   // profile. Note that the icon may not be unique since there are a limited
   // set of default icons.
@@ -189,8 +177,15 @@
   // of profiles is still sorted.
   void UpdateSortForProfileIndex(size_t index);
 
-  void OnGAIAPictureLoaded(const base::FilePath& path,
-                           gfx::Image** image) const;
+  // Loads or uses an already loaded high resolution image of the
+  // generic profile avatar.
+  const gfx::Image* GetHighResAvatarOfProfileAtIndex(size_t index) const;
+
+  const gfx::Image* LoadAvatarPictureFromPath(
+      const std::string& key,
+      const base::FilePath& image_path) const;
+  void OnAvatarPictureLoaded(const std::string& key,
+                             gfx::Image** image) const;
   void OnGAIAPictureSaved(const base::FilePath& path, bool* success) const;
 
   PrefService* prefs_;
@@ -199,12 +194,12 @@
 
   ObserverList<ProfileInfoCacheObserver> observer_list_;
 
-  // A cache of gaia profile pictures. This cache is updated lazily so it needs
-  // to be mutable.
-  mutable std::map<std::string, gfx::Image*> gaia_pictures_;
-  // Marks a gaia profile picture as loading. This prevents a picture from
+  // A cache of gaia/high res avatar profile pictures. This cache is updated
+  // lazily so it needs to be mutable.
+  mutable std::map<std::string, gfx::Image*> cached_avatar_images_;
+  // Marks a profile picture as loading. This prevents a picture from
   // loading multiple times.
-  mutable std::map<std::string, bool> gaia_pictures_loading_;
+  mutable std::map<std::string, bool> cached_avatar_images_loading_;
 
   DISALLOW_COPY_AND_ASSIGN(ProfileInfoCache);
 };
diff --git a/chrome/browser/profiles/profile_info_cache_unittest.cc b/chrome/browser/profiles/profile_info_cache_unittest.cc
index 972d8ef..3f9b1e4 100644
--- a/chrome/browser/profiles/profile_info_cache_unittest.cc
+++ b/chrome/browser/profiles/profile_info_cache_unittest.cc
@@ -281,34 +281,6 @@
   EXPECT_FALSE(GetCache()->GetBackgroundStatusOfProfileAtIndex(1));
 }
 
-TEST_F(ProfileInfoCacheTest, HasMigrated) {
-  GetCache()->AddProfileToCache(
-      GetProfilePath("path_1"), ASCIIToUTF16("name_1"),
-      base::string16(), 0, std::string());
-  GetCache()->AddProfileToCache(
-      GetProfilePath("path_2"), ASCIIToUTF16("name_2"),
-      base::string16(), 0, std::string());
-
-  // Sanity check.
-  EXPECT_FALSE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(0));
-  EXPECT_FALSE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(1));
-
-  // Set migrated state for 2nd profile.
-  GetCache()->SetHasMigratedToGAIAInfoOfProfileAtIndex(1, true);
-  EXPECT_FALSE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(0));
-  EXPECT_TRUE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(1));
-
-  // Set migrated state for 1st profile.
-  GetCache()->SetHasMigratedToGAIAInfoOfProfileAtIndex(0, true);
-  EXPECT_TRUE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(0));
-  EXPECT_TRUE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(1));
-
-  // Unset migrated state for 2nd profile.
-  GetCache()->SetHasMigratedToGAIAInfoOfProfileAtIndex(1, false);
-  EXPECT_TRUE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(0));
-  EXPECT_FALSE(GetCache()->GetHasMigratedToGAIAInfoOfProfileAtIndex(1));
-}
-
 TEST_F(ProfileInfoCacheTest, ProfileActiveTime) {
   GetCache()->AddProfileToCache(
       GetProfilePath("path_1"), ASCIIToUTF16("name_1"),
@@ -342,31 +314,25 @@
   // Sanity check.
   EXPECT_TRUE(GetCache()->GetGAIANameOfProfileAtIndex(index1).empty());
   EXPECT_TRUE(GetCache()->GetGAIANameOfProfileAtIndex(index2).empty());
-  EXPECT_FALSE(GetCache()->IsUsingGAIANameOfProfileAtIndex(index1));
-  EXPECT_FALSE(GetCache()->IsUsingGAIANameOfProfileAtIndex(index2));
 
-  // Set GAIA name.
+  // Set GAIA name. This re-sorts the cache.
   base::string16 gaia_name(ASCIIToUTF16("Pat Smith"));
   GetCache()->SetGAIANameOfProfileAtIndex(index2, gaia_name);
+  index1 = GetCache()->GetIndexOfProfileWithPath(GetProfilePath("path_1"));
+  index2 = GetCache()->GetIndexOfProfileWithPath(GetProfilePath("path_2"));
+
+  // Since there is a GAIA name, we use that as a display name.
   EXPECT_TRUE(GetCache()->GetGAIANameOfProfileAtIndex(index1).empty());
   EXPECT_EQ(gaia_name, GetCache()->GetGAIANameOfProfileAtIndex(index2));
-  EXPECT_EQ(profile_name, GetCache()->GetNameOfProfileAtIndex(index2));
-
-  // Use GAIA name as profile name. This re-sorts the cache.
-  GetCache()->SetIsUsingGAIANameOfProfileAtIndex(index2, true);
-  index1 = GetCache()->GetIndexOfProfileWithPath(GetProfilePath("path_1"));
-  index2 = GetCache()->GetIndexOfProfileWithPath(GetProfilePath("path_2"));
-
-  EXPECT_EQ(GetCache()->IsUsingGAIANameOfProfileAtIndex(index2), true);
   EXPECT_EQ(gaia_name, GetCache()->GetNameOfProfileAtIndex(index2));
-  EXPECT_EQ(gaia_name, GetCache()->GetGAIANameOfProfileAtIndex(index2));
 
   // Don't use GAIA name as profile name. This re-sorts the cache.
-  GetCache()->SetIsUsingGAIANameOfProfileAtIndex(index2, false);
+  base::string16 custom_name(ASCIIToUTF16("Custom name"));
+  GetCache()->SetNameOfProfileAtIndex(index2, custom_name);
   index1 = GetCache()->GetIndexOfProfileWithPath(GetProfilePath("path_1"));
   index2 = GetCache()->GetIndexOfProfileWithPath(GetProfilePath("path_2"));
 
-  EXPECT_EQ(profile_name, GetCache()->GetNameOfProfileAtIndex(index2));
+  EXPECT_EQ(custom_name, GetCache()->GetNameOfProfileAtIndex(index2));
   EXPECT_EQ(gaia_name, GetCache()->GetGAIANameOfProfileAtIndex(index2));
 }
 
@@ -474,7 +440,6 @@
   // Set empty GAIA info.
   GetCache()->SetGAIANameOfProfileAtIndex(0, base::string16());
   GetCache()->SetGAIAPictureOfProfileAtIndex(0, NULL);
-  GetCache()->SetIsUsingGAIANameOfProfileAtIndex(0, true);
   GetCache()->SetIsUsingGAIAPictureOfProfileAtIndex(0, true);
 
   // Verify that the profile name and picture are not empty.
diff --git a/chrome/browser/profiles/profile_info_interface.h b/chrome/browser/profiles/profile_info_interface.h
index d369f6a..66f6741 100644
--- a/chrome/browser/profiles/profile_info_interface.h
+++ b/chrome/browser/profiles/profile_info_interface.h
@@ -53,9 +53,6 @@
   virtual base::string16 GetGAIAGivenNameOfProfileAtIndex(
       size_t index) const = 0;
 
-  // Checks if the GAIA name should be used as the profile's name.
-  virtual bool IsUsingGAIANameOfProfileAtIndex(size_t index) const = 0;
-
   virtual const gfx::Image* GetGAIAPictureOfProfileAtIndex(
       size_t index) const = 0;
 
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 0487c01..4aa1903 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -93,6 +93,7 @@
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/chromeos/drive/drive_protocol_handler.h"
+#include "chrome/browser/chromeos/login/startup_utils.h"
 #include "chrome/browser/chromeos/login/user.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
@@ -442,11 +443,12 @@
   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
       pool->GetSequencedTaskRunner(pool->GetSequenceToken());
   url_blacklist_manager_.reset(
-      new policy::URLBlacklistManager(pref_service,
-                                      background_task_runner,
-                                      io_message_loop_proxy,
-                                      callback,
-                                      policy::OverrideBlacklistForURL));
+      new policy::URLBlacklistManager(
+          pref_service,
+          background_task_runner,
+          io_message_loop_proxy,
+          callback,
+          base::Bind(policy::OverrideBlacklistForURL)));
 
   if (!IsOffTheRecord()) {
     // Add policy headers for non-incognito requests.
diff --git a/chrome/browser/profiles/profile_list_desktop_browsertest.cc b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
index 5668772..f7b6b1a 100644
--- a/chrome/browser/profiles/profile_list_desktop_browsertest.cc
+++ b/chrome/browser/profiles/profile_list_desktop_browsertest.cc
@@ -49,7 +49,13 @@
   DISALLOW_COPY_AND_ASSIGN(ProfileListDesktopBrowserTest);
 };
 
-IN_PROC_BROWSER_TEST_F(ProfileListDesktopBrowserTest, SignOut) {
+#if defined (OS_WIN)
+// SignOut is flaky. So far only observed on Windows. crbug.com/357329.
+#define MAYBE_SignOut DISABLED_SignOut
+#else
+#define MAYBE_SignOut SignOut
+#endif
+IN_PROC_BROWSER_TEST_F(ProfileListDesktopBrowserTest, MAYBE_SignOut) {
   if (!profiles::IsMultipleProfilesEnabled())
     return;
 
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 8c1291d..a6fcf75 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -48,6 +48,9 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/user_metrics.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension_set.h"
+#include "extensions/common/manifest.h"
 #include "grit/generated_resources.h"
 #include "net/http/http_transaction_factory.h"
 #include "net/url_request/url_request_context.h"
@@ -104,7 +107,7 @@
 }
 
 // Simple task to log the size of the current profile.
-void ProfileSizeTask(const base::FilePath& path, int extension_count) {
+void ProfileSizeTask(const base::FilePath& path, int enabled_app_count) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   const int64 kBytesInOneMB = 1024 * 1024;
 
@@ -152,9 +155,9 @@
   size_MB = static_cast<int>(size / kBytesInOneMB);
   UMA_HISTOGRAM_COUNTS_10000("Profile.PolicySize", size_MB);
 
-  // Count number of extensions in this profile, if we know.
-  if (extension_count != -1)
-    UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", extension_count);
+  // Count number of enabled apps in this profile, if we know.
+  if (enabled_app_count != -1)
+    UMA_HISTOGRAM_COUNTS_10000("Profile.AppCount", enabled_app_count);
 }
 
 void QueueProfileDirectoryForDeletion(const base::FilePath& path) {
@@ -188,6 +191,27 @@
 
 #endif
 
+#if defined(ENABLE_EXTENSIONS)
+
+// Returns the number of installed (and enabled) apps, excluding any component
+// apps.
+size_t GetEnabledAppCount(Profile* profile) {
+  size_t installed_apps = 0u;
+  const extensions::ExtensionSet& extensions =
+      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
+  for (extensions::ExtensionSet::const_iterator iter = extensions.begin();
+       iter != extensions.end();
+       ++iter) {
+    if ((*iter)->is_app() &&
+        (*iter)->location() != extensions::Manifest::COMPONENT) {
+      ++installed_apps;
+    }
+  }
+  return installed_apps;
+}
+
+#endif  // ENABLE_EXTENSIONS
+
 } // namespace
 
 ProfileManager::ProfileManager(const base::FilePath& user_data_dir)
@@ -264,7 +288,8 @@
 // static
 Profile* ProfileManager::GetLastUsedProfileAllowedByPolicy() {
   Profile* profile = GetLastUsedProfile();
-  if (IncognitoModePrefs::GetAvailability(profile->GetPrefs()) ==
+  if (profile->IsGuestSession() ||
+      IncognitoModePrefs::GetAvailability(profile->GetPrefs()) ==
       IncognitoModePrefs::FORCED) {
     return profile->GetOffTheRecordProfile();
   }
@@ -961,17 +986,15 @@
 
 void ProfileManager::DoFinalInitLogging(Profile* profile) {
   // Count number of extensions in this profile.
-  int extension_count = -1;
+  int enabled_app_count = -1;
 #if defined(ENABLE_EXTENSIONS)
-  ExtensionService* extension_service = profile->GetExtensionService();
-  if (extension_service)
-    extension_count = extension_service->GetAppIds().size();
+  enabled_app_count = GetEnabledAppCount(profile);
 #endif
 
   // Log the profile size after a reasonable startup delay.
   BrowserThread::PostDelayedTask(
       BrowserThread::FILE, FROM_HERE,
-      base::Bind(&ProfileSizeTask, profile->GetPath(), extension_count),
+      base::Bind(&ProfileSizeTask, profile->GetPath(), enabled_app_count),
       base::TimeDelta::FromSeconds(112));
 }
 
diff --git a/chrome/browser/profiles/profile_manager_unittest.cc b/chrome/browser/profiles/profile_manager_unittest.cc
index 579fd3d..803001c 100644
--- a/chrome/browser/profiles/profile_manager_unittest.cc
+++ b/chrome/browser/profiles/profile_manager_unittest.cc
@@ -360,7 +360,6 @@
   EXPECT_EQ(expected_path, guest_path);
 }
 
-#if defined(OS_CHROMEOS)
 class UnittestGuestProfileManager : public UnittestProfileManager {
  public:
   explicit UnittestGuestProfileManager(const base::FilePath& user_data_dir)
@@ -386,6 +385,7 @@
     TestingBrowserProcess::GetGlobal()->SetProfileManager(
         new UnittestGuestProfileManager(temp_dir_.path()));
 
+#if defined(OS_CHROMEOS)
     CommandLine* cl = CommandLine::ForCurrentProcess();
     if (GetParam())
       cl->AppendSwitch(switches::kMultiProfiles);
@@ -405,9 +405,24 @@
         chromeos::UserManager::kGuestUserName,
         chromeos::UserManager::kGuestUserName,
         false);
+#endif
   }
 };
 
+INSTANTIATE_TEST_CASE_P(ProfileManagerGuestTestInstantiation,
+                        ProfileManagerGuestTest,
+                        testing::Bool());
+
+TEST_P(ProfileManagerGuestTest, GetLastUsedProfileAllowedByPolicy) {
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  ASSERT_TRUE(profile_manager);
+
+  Profile* profile = profile_manager->GetLastUsedProfileAllowedByPolicy();
+  ASSERT_TRUE(profile);
+  EXPECT_TRUE(profile->IsOffTheRecord());
+}
+
+#if defined(OS_CHROMEOS)
 TEST_P(ProfileManagerGuestTest, GuestProfileIngonito) {
   Profile* primary_profile = ProfileManager::GetPrimaryUserProfile();
   EXPECT_TRUE(primary_profile->IsOffTheRecord());
@@ -422,10 +437,6 @@
 
   EXPECT_TRUE(last_used_profile->IsSameProfile(active_profile));
 }
-
-INSTANTIATE_TEST_CASE_P(ProfileManagerGuestTestInstantiation,
-                        ProfileManagerGuestTest,
-                        testing::Bool());
 #endif
 
 TEST_F(ProfileManagerTest, AutoloadProfilesWithBackgroundApps) {
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc
index 3eee013..282ffd3 100644
--- a/chrome/browser/profiles/profiles_state.cc
+++ b/chrome/browser/profiles/profiles_state.cc
@@ -16,7 +16,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -84,32 +84,11 @@
 
 void UpdateProfileName(Profile* profile,
                        const base::string16& new_profile_name) {
-  ProfileInfoCache& cache =
-        g_browser_process->profile_manager()->GetProfileInfoCache();
-  base::FilePath profile_file_path = profile->GetPath();
-  size_t profile_index = cache.GetIndexOfProfileWithPath(profile_file_path);
-
-  if ((new_profile_name ==
-          cache.GetGAIAGivenNameOfProfileAtIndex(profile_index)) ||
-      (new_profile_name == cache.GetGAIANameOfProfileAtIndex(profile_index))) {
-    // Set the profile to use the GAIA name as the profile name. Note, this
-    // is a little weird if the user typed their GAIA name manually but
-    // it's not a big deal.
-    cache.SetIsUsingGAIANameOfProfileAtIndex(profile_index, true);
-  } else {
-    PrefService* pref_service = profile->GetPrefs();
-    // Updating the profile preference will cause the cache to be updated for
-    // this preference.
-    pref_service->SetString(prefs::kProfileName,
-                            base::UTF16ToUTF8(new_profile_name));
-
-    // Changing the profile name can invalidate the profile index.
-    profile_index = cache.GetIndexOfProfileWithPath(profile_file_path);
-    if (profile_index == std::string::npos)
-      return;
-
-    cache.SetIsUsingGAIANameOfProfileAtIndex(profile_index, false);
-  }
+  PrefService* pref_service = profile->GetPrefs();
+  // Updating the profile preference will cause the cache to be updated for
+  // this preference.
+  pref_service->SetString(prefs::kProfileName,
+                          base::UTF16ToUTF8(new_profile_name));
 }
 
 std::vector<std::string> GetSecondaryAccountsForProfile(
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 8062f4f..807a1cc 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -56,6 +56,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/search_engines/search_engine_tab_helper.h"
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 #include "chrome/common/chrome_constants.h"
@@ -1495,9 +1496,7 @@
     OpenURL(
         handlers[handlerIndex].TranslateUrl(params_.link_url),
         params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
-        params_.frame_id,
-        disposition,
-        content::PAGE_TRANSITION_LINK);
+        disposition, content::PAGE_TRANSITION_LINK);
     return;
   }
 
@@ -1508,7 +1507,6 @@
       OpenURL(
           params_.link_url,
           params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
-          params_.frame_id,
           !browser || browser->is_app() ?
                   NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB,
           content::PAGE_TRANSITION_LINK);
@@ -1518,15 +1516,11 @@
       OpenURL(
           params_.link_url,
           params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
-          params_.frame_id,
           NEW_WINDOW, content::PAGE_TRANSITION_LINK);
       break;
 
     case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD:
-      OpenURL(params_.link_url,
-              GURL(),
-              params_.frame_id,
-              OFF_THE_RECORD,
+      OpenURL(params_.link_url, GURL(), OFF_THE_RECORD,
               content::PAGE_TRANSITION_LINK);
       break;
 
@@ -1595,7 +1589,6 @@
       OpenURL(
           params_.src_url,
           params_.frame_url.is_empty() ? params_.page_url : params_.frame_url,
-          params_.frame_id,
           NEW_BACKGROUND_TAB, content::PAGE_TRANSITION_LINK);
       break;
 
@@ -1802,11 +1795,13 @@
     }
 
     case IDC_CONTENT_CONTEXT_UNDO:
-      rvh->Undo();
+      if (render_frame_host)
+        render_frame_host->Undo();
       break;
 
     case IDC_CONTENT_CONTEXT_REDO:
-      rvh->Redo();
+      if (render_frame_host)
+        render_frame_host->Redo();
       break;
 
     case IDC_CONTENT_CONTEXT_CUT:
@@ -1825,34 +1820,33 @@
       break;
 
     case IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE:
-      rvh->PasteAndMatchStyle();
+      if (render_frame_host)
+        render_frame_host->PasteAndMatchStyle();
       break;
 
     case IDC_CONTENT_CONTEXT_DELETE:
-      rvh->Delete();
+      if (render_frame_host)
+        render_frame_host->Delete();
       break;
 
     case IDC_CONTENT_CONTEXT_SELECTALL:
-      rvh->SelectAll();
+      if (render_frame_host)
+        render_frame_host->SelectAll();
       break;
 
     case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
     case IDC_CONTENT_CONTEXT_GOTOURL: {
       WindowOpenDisposition disposition =
           ForceNewTabDispositionFromEventFlags(event_flags);
-      OpenURL(selection_navigation_url_,
-              GURL(),
-              params_.frame_id,
-              disposition,
+      OpenURL(selection_navigation_url_, GURL(), disposition,
               content::PAGE_TRANSITION_LINK);
       break;
     }
     case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS: {
       WindowOpenDisposition disposition =
           ForceNewTabDispositionFromEventFlags(event_flags);
-      std::string url = std::string(chrome::kChromeUISettingsURL) +
-          chrome::kLanguageOptionsSubPage;
-      OpenURL(GURL(url), GURL(), 0, disposition, content::PAGE_TRANSITION_LINK);
+      GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
+      OpenURL(url, GURL(), disposition, content::PAGE_TRANSITION_LINK);
       break;
     }
 
@@ -1861,9 +1855,8 @@
           UserMetricsAction("RegisterProtocolHandler.ContextMenu_Settings"));
       WindowOpenDisposition disposition =
           ForceNewTabDispositionFromEventFlags(event_flags);
-      std::string url = std::string(chrome::kChromeUISettingsURL) +
-          chrome::kHandlerSettingsSubPage;
-      OpenURL(GURL(url), GURL(), 0, disposition, content::PAGE_TRANSITION_LINK);
+      GURL url = chrome::GetSettingsUrl(chrome::kHandlerSettingsSubPage);
+      OpenURL(url, GURL(), disposition, content::PAGE_TRANSITION_LINK);
       break;
     }
 
@@ -1907,8 +1900,8 @@
       GURL url(chrome::kSpeechInputAboutURL);
       GURL localized_url = google_util::AppendGoogleLocaleParam(url);
       // Open URL with no referrer field (because user clicked on menu item).
-      OpenURL(localized_url, GURL(), 0, NEW_FOREGROUND_TAB,
-          content::PAGE_TRANSITION_LINK);
+      OpenURL(localized_url, GURL(), NEW_FOREGROUND_TAB,
+              content::PAGE_TRANSITION_LINK);
       break;
     }
 
@@ -1995,7 +1988,7 @@
 // Controller functions --------------------------------------------------------
 
 void RenderViewContextMenu::OpenURL(
-    const GURL& url, const GURL& referring_url, int64 frame_id,
+    const GURL& url, const GURL& referring_url,
     WindowOpenDisposition disposition,
     content::PageTransition transition) {
   content::Referrer referrer(referring_url.GetAsReferrer(),
@@ -2008,7 +2001,7 @@
 
   RetargetingDetails details;
   details.source_web_contents = source_web_contents_;
-  details.source_frame_id = frame_id;
+  details.source_render_frame_id = render_frame_id_;
   details.target_url = url;
   details.target_web_contents = new_contents;
   details.not_yet_in_tabstrip = false;
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.h b/chrome/browser/renderer_context_menu/render_view_context_menu.h
index c540bec..3de0070 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -228,10 +228,8 @@
   void AppendSpeechInputOptionsSubMenu();
   void AppendProtocolHandlerSubMenu();
 
-  // Opens the specified URL string in a new tab.  The |frame_id| specifies the
-  // frame in which the context menu was displayed, or 0 if the menu action is
-  // independent of that frame (e.g. protocol handler settings).
-  void OpenURL(const GURL& url, const GURL& referrer, int64 frame_id,
+  // Opens the specified URL string in a new tab.
+  void OpenURL(const GURL& url, const GURL& referrer,
                WindowOpenDisposition disposition,
                content::PageTransition transition);
 
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.cc b/chrome/browser/renderer_host/chrome_render_message_filter.cc
index a077fd9..a20b731 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.cc
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/extensions/activity_log/activity_log.h"
 #include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h"
 #include "chrome/browser/extensions/api/messaging/message_service.h"
+#include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/browser/net/chrome_url_request_context.h"
 #include "chrome/browser/net/predictor.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -133,6 +134,8 @@
                         OnCanTriggerClipboardRead)
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CanTriggerClipboardWrite,
                         OnCanTriggerClipboardWrite)
+    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_IsCrashReportingEnabled,
+                        OnIsCrashReportingEnabled)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -493,3 +496,7 @@
       extension_info_map_->SecurityOriginHasAPIPermission(
           origin, render_process_id_, APIPermission::kClipboardWrite));
 }
+
+void ChromeRenderMessageFilter::OnIsCrashReportingEnabled(bool* enabled) {
+  *enabled = MetricsServiceHelper::IsCrashReportingEnabled();
+}
diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h
index ffbb07c..1e8c527 100644
--- a/chrome/browser/renderer_host/chrome_render_message_filter.h
+++ b/chrome/browser/renderer_host/chrome_render_message_filter.h
@@ -166,6 +166,7 @@
                         bool* allowed);
   void OnCanTriggerClipboardRead(const GURL& origin, bool* allowed);
   void OnCanTriggerClipboardWrite(const GURL& origin, bool* allowed);
+  void OnIsCrashReportingEnabled(bool* enabled);
 
   int render_process_id_;
 
diff --git a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
index 5db0a03..c1c3126 100644
--- a/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
+++ b/chrome/browser/renderer_host/chrome_resource_dispatcher_host_delegate.cc
@@ -33,6 +33,7 @@
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/signin/signin_header_helper.h"
 #include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/browser/ui/auto_login_prompter.h"
 #include "chrome/browser/ui/login/login_prompt.h"
 #include "chrome/browser/ui/sync/one_click_signin_helper.h"
 #include "chrome/common/extensions/extension_constants.h"
@@ -74,7 +75,6 @@
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/android/intercept_download_resource_throttle.h"
-#include "chrome/browser/ui/android/infobars/auto_login_prompter.h"
 #include "components/navigation_interception/intercept_navigation_delegate.h"
 #else
 #include "chrome/browser/apps/app_url_redirector.h"
@@ -594,13 +594,11 @@
     IPC::Sender* sender) {
   const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request);
 
-#if defined(OS_ANDROID)
   // See if the response contains the X-Auto-Login header.  If so, this was
   // a request for a login page, and the server is allowing the browser to
   // suggest auto-login, if available.
   AutoLoginPrompter::ShowInfoBarIfPossible(request, info->GetChildID(),
                                            info->GetRouteID());
-#endif
 
   ProfileIOData* io_data = ProfileIOData::FromResourceContext(resource_context);
 
diff --git a/chrome/browser/renderer_host/web_cache_manager.cc b/chrome/browser/renderer_host/web_cache_manager.cc
index 274bb46..e4c7a58 100644
--- a/chrome/browser/renderer_host/web_cache_manager.cc
+++ b/chrome/browser/renderer_host/web_cache_manager.cc
@@ -328,7 +328,8 @@
       size_t max_dead_capacity = capacity / 2;
 #if defined(OS_ANDROID)
       if (base::android::SysUtils::IsLowEndDevice())
-        max_dead_capacity = std::min(512 * 1024U, max_dead_capacity);
+        max_dead_capacity = std::min(static_cast<size_t>(512 * 1024),
+                                     max_dead_capacity);
 #endif
 
       host->Send(new ChromeViewMsg_SetCacheCapacities(min_dead_capacity,
diff --git a/chrome/browser/resources/app_list/plugin_manager.js b/chrome/browser/resources/app_list/plugin_manager.js
index eeb3823..b6407b6 100644
--- a/chrome/browser/resources/app_list/plugin_manager.js
+++ b/chrome/browser/resources/app_list/plugin_manager.js
@@ -16,9 +16,8 @@
   var PluginState = {
     UNINITIALIZED: 0,
     LOADED: 1,
-    SAMPLING_RATE_READY: 2,
-    READY: 3,
-    RECOGNIZING: 4
+    READY: 2,
+    RECOGNIZING: 3
   };
 
   /**
@@ -35,7 +34,7 @@
   /**
    * The regexp pattern of the hotword recognition result.
    */
-  var recognitionPattern = /^HotwordFiredEvent:/;
+  var recognitionPattern = /^(HotwordFiredEvent:|hotword)/;
 
   /**
    * @constructor
@@ -67,17 +66,13 @@
    * @private
    */
   PluginManager.prototype.onMessage_ = function(messageEvent) {
-    if (this.state == PluginState.LOADED) {
-      if (messageEvent.data == 'stopped')
-        this.state = PluginState.SAMPLING_RATE_READY;
-      return;
-    }
-
     if (messageEvent.data == 'audio') {
-      if (this.state < PluginState.READY)
-        this.onReady_(this);
+      var wasNotReady = this.state < PluginState.READY;
       this.state = PluginState.RECOGNIZING;
-    } else if (messageEvent.data == 'stopped') {
+      if (wasNotReady)
+        this.onReady_(this);
+    } else if (messageEvent.data == 'stopped' &&
+               this.state == PluginState.RECOGNIZING) {
       this.state = PluginState.READY;
     } else if (recognitionPattern.exec(messageEvent.data)) {
       this.onRecognized_();
diff --git a/chrome/browser/resources/app_list/speech_manager.js b/chrome/browser/resources/app_list/speech_manager.js
index 30446e8..eb450f1 100644
--- a/chrome/browser/resources/app_list/speech_manager.js
+++ b/chrome/browser/resources/app_list/speech_manager.js
@@ -82,6 +82,7 @@
       this.audioManager_.start();
       this.setState_(SpeechState.HOTWORD_RECOGNIZING);
     } else {
+      this.pluginManager_.stopRecognizer();
       this.setState_(SpeechState.READY);
     }
     chrome.send('setHotwordRecognizerState', [true]);
diff --git a/chrome/browser/resources/bookmark_manager/css/bmm.css b/chrome/browser/resources/bookmark_manager/css/bmm.css
index 5c10770..5f1367d 100644
--- a/chrome/browser/resources/bookmark_manager/css/bmm.css
+++ b/chrome/browser/resources/bookmark_manager/css/bmm.css
@@ -55,9 +55,6 @@
   -webkit-flex: 1;
   direction: ltr; /* URLs always read LTR */
   display: none;
-  /* TODO(arv): Remove min-width once bug is fixed:
-   * https://bugs.webkit.org/show_bug.cgi?id=111790 */
-  min-width: 0;
 }
 
 list > :hover > .url,
@@ -204,9 +201,6 @@
 .main {
   -webkit-flex: 1;
   display: -webkit-flex;
-  /* TODO(arv): Remove min-height once bug is fixed:
-   * https://bugs.webkit.org/show_bug.cgi?id=111790 */
-  min-height: 0;
 }
 
 #tree-container {
@@ -240,9 +234,6 @@
   -webkit-flex: 1;
   -webkit-padding-end: 5px;
   box-sizing: border-box;
-  /* TODO(arv): Remove min-width once bug is fixed:
-   * https://bugs.webkit.org/show_bug.cgi?id=111790 */
-  min-width: 0;
   padding-bottom: 5px;
   padding-top: 5px;
 }
diff --git a/chrome/browser/resources/chromeos/certificate_manager_dialog.js b/chrome/browser/resources/chromeos/certificate_manager_dialog.js
index 5bc581c..4186497 100644
--- a/chrome/browser/resources/chromeos/certificate_manager_dialog.js
+++ b/chrome/browser/resources/chromeos/certificate_manager_dialog.js
@@ -38,7 +38,7 @@
   $('cert-manager-header').hidden = true;
 
   OptionsPage.isDialog = true;
-  CertificateManager.getInstance().initializePage();
+  CertificateManager.getInstance().initializePage(true);
   OptionsPage.registerOverlay(CertificateBackupOverlay.getInstance(),
     CertificateManager.getInstance());
   OptionsPage.registerOverlay(CertificateEditCaTrustOverlay.getInstance(),
diff --git a/chrome/browser/resources/chromeos/keyboard_overlay.css b/chrome/browser/resources/chromeos/keyboard_overlay.css
index 8ab73bd..ff291ac 100644
--- a/chrome/browser/resources/chromeos/keyboard_overlay.css
+++ b/chrome/browser/resources/chromeos/keyboard_overlay.css
@@ -15,7 +15,7 @@
   background: -webkit-linear-gradient(#484848, #252525) no-repeat;
   background-color: #252525;
   border-radius: 6px;
-  font-family: 'Droid Sans', Arial;
+  font-family: 'Noto Sans UI', ui-sans;
 }
 
 .keyboard-overlay-instructions {
diff --git a/chrome/browser/resources/chromeos/login/login_common.js b/chrome/browser/resources/chromeos/login/login_common.js
index 7716e01..dcb19eb 100644
--- a/chrome/browser/resources/chromeos/login/login_common.js
+++ b/chrome/browser/resources/chromeos/login/login_common.js
@@ -241,24 +241,50 @@
   };
 
   /**
-   * Login for autotests.
+   * Login for telemetry.
    * @param {string} username Login username.
    * @param {string} password Login password.
    */
   Oobe.loginForTesting = function(username, password) {
+    Oobe.disableSigninUI();
     chrome.send('skipToLoginForTesting', [username]);
     chrome.send('completeLogin', [username, password, false]);
   };
 
   /**
-   * Authenticate for autotests.
+   * Guest login for telemetry.
+   */
+  Oobe.guestLoginForTesting = function() {
+    Oobe.disableSigninUI();
+    chrome.send('skipToLoginForTesting');
+    chrome.send('launchIncognito');
+  };
+
+  /**
+   * Authenticate for telemetry - used for screenlocker.
    * @param {string} username Login username.
    * @param {string} password Login password.
    */
   Oobe.authenticateForTesting = function(username, password) {
+    Oobe.disableSigninUI();
     chrome.send('authenticateUser', [username, password]);
   };
 
+  /**
+   * Gaia login screen for telemetry.
+   */
+  Oobe.addUserForTesting = function() {
+    chrome.send('skipToLoginForTesting');
+    chrome.send('addUser');
+  };
+
+  /**
+   * Chromebox requisition for telemetry.
+   */
+  Oobe.chromeboxRequisitionForTesting = function() {
+    chrome.send('setDeviceRequisition', ['remora']);
+  };
+
   // Export
   return {
     Oobe: Oobe
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen.css b/chrome/browser/resources/chromeos/login/oobe_screen.css
index 0a7b6fa..52b2c7a 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen.css
@@ -138,10 +138,6 @@
 #oobe.eula #back-button,
 #oobe.kiosk-enable #kiosk-cancel-button,
 #oobe.kiosk-enable #kiosk-enable-button,
-#oobe.oauth-enrollment #oauth-enroll-cancel-button,
-#oobe.oauth-enrollment #oauth-enroll-done-button,
-#oobe.oauth-enrollment #oauth-enroll-explain-button,
-#oobe.oauth-enrollment #oauth-enroll-try-again-button,
 #oobe.reset #reset-button,
 #oobe.reset #reset-cancel-button,
 #oobe.signin #signin-button,
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_eula.html b/chrome/browser/resources/chromeos/login/oobe_screen_eula.html
index 1fc440c..3bf46f1 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_eula.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_eula.html
@@ -1,4 +1,5 @@
-<div class="step right hidden animated eula-loading" id="eula">
+<div class="step right hidden animated eula-loading" id="eula" role="group"
+     i18n-values="aria-label:eulaScreenAccessibleTitle">
   <div class="step-contents">
     <div id="eulas" class="eula-columns one-column">
       <div id="cros-eula" tabindex="0">
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_network.html b/chrome/browser/resources/chromeos/login/oobe_screen_network.html
index eacd6c6..f89acdc 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_network.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_network.html
@@ -1,4 +1,4 @@
-<div class="step hidden animated" id="connect">
+<div class="step hidden animated" id="connect" role="group">
   <div class="step-contents">
     <div id="welcome-message" i18n-content="networkScreenGreeting">
     </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
index e64728f..1a60f6a 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.css
@@ -9,40 +9,80 @@
   width: 722px;
 }
 
-#oauth-enroll-container {
+#oauth-enroll-step-contents {
+  -webkit-margin-after: 10px;
+  color: #666;
   display: -webkit-box;
 }
 
-#oauth-enroll-signin-frame {
-  height: 456px;
+#oauth-enroll-step-contents > div {
+  display: none;
 }
 
-#oauth-enroll-signin-frame {
-  border: 0 none;
+.oauth-enroll-state-working #oauth-enroll-step-working,
+.oauth-enroll-state-error #oauth-enroll-step-error,
+.oauth-enroll-state-explain #oauth-enroll-step-explain,
+.oauth-enroll-state-success #oauth-enroll-step-success {
+  display: table;
+  height: 480px;
+  margin: 0 auto;
+}
+
+.oauth-enroll-state-signin #oauth-enroll-step-signin {
+  display: -webkit-flex;
   width: 100%;
 }
 
 #oauth-enroll-signin-frame-container {
+  -webkit-flex: 1 1 auto;
   box-sizing: border-box;
   padding-bottom: 20px;
+}
+
+#oauth-enroll-signin-frame {
+  border: 0 none;
+  height: 456px;
   width: 100%;
 }
 
-#oauth-enroll-signin-link-container {
-  -webkit-box-pack: end;
-  display: -webkit-box;
-}
-#oauth-enroll-step-signin {
-  width: 100%;
+#oauth-enroll-signin-divider {
+  -webkit-flex: 0 0 auto;
+  background: linear-gradient(to bottom, #e3e3e3, #cacaca 50%, #e3e3e3);
+  border: none;
+  width: 1px;
 }
 
-.oauth-enroll-step-center {
-  height: 480px;
+#oauth-enroll-signin-right {
+  -webkit-flex: 0 0 auto;
+  -webkit-margin-before: 30px;
+  -webkit-margin-end: 20px;
+  -webkit-margin-start: 30px;
+  font-size: 12px;
+  width: 200px;
 }
 
-.oauth-enroll-step-center {
-  display: table;
-  margin: 0 auto;
+@media (pointer:coarse) {
+  #oauth-enroll-signin-right {
+    font-size: 14px;
+  }
+}
+
+#oauth-enroll-signin-right > div {
+  -webkit-margin-before: 20px;
+}
+
+#oauth-enroll-learn-more-link,
+.oauth-enroll-explain-link {
+  display: none;
+}
+
+#oauth-enrollment.mode-manual #oauth-enroll-learn-more-link,
+#oauth-enrollment.mode-forced #oauth-enroll-learn-more-link {
+  display: inline;
+}
+
+#oauth-enrollment.mode-auto .oauth-enroll-explain-link {
+  display: inline;
 }
 
 .oauth-enroll-step-content {
@@ -66,6 +106,10 @@
   width: 22px;
 }
 
+#oauth-enrollment.mode-auto #oauth-enroll-error-retry {
+  display: none;
+}
+
 .oauth-enroll-step-message {
   display: inline-block;
   max-width: 400px;
@@ -78,19 +122,31 @@
 }
 
 .oauth-enroll-link {
-  color: -webkit-link;
+  color: rgb(37, 79, 155);
   cursor: pointer;
-  text-decoration: underline;
+  text-decoration: none;
+}
+
+.oauth-enroll-button {
+  display: none;
+}
+
+.oauth-enroll-state-signin.mode-manual #oauth-enroll-cancel-button,
+.oauth-enroll-state-working.mode-manual #oauth-enroll-cancel-button,
+.oauth-enroll-state-signin.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-working.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-error.mode-manual #oauth-enroll-cancel-button,
+.oauth-enroll-state-error.mode-auto #oauth-enroll-retry-button,
+.oauth-enroll-state-error.mode-forced #oauth-enroll-back-button,
+.oauth-enroll-state-explain #oauth-enroll-explain-retry-button,
+.oauth-enroll-state-success #oauth-enroll-done-button {
+  display: inline;
 }
 
 #oobe.oauth-enrollment #header-oauth-enrollment {
   display: block;
 }
 
-#oauth-enrollment .step-contents {
-  -webkit-margin-after: 10px;
-}
-
 #oauth-saml-notice-container {
   left: 0;
   position: absolute;
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html
index 2514956..c0fee11 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.html
@@ -1,16 +1,21 @@
 <div id="oauth-enrollment" class="step hidden">
-  <div id="oauth-enroll-container" class="step-contents">
+  <div id="oauth-enroll-step-contents">
     <div id="oauth-enroll-step-signin">
       <div id="oauth-enroll-signin-frame-container">
         <iframe id="oauth-enroll-signin-frame" name="oauth-enroll-signin-frame" src="about:blank" marginwidth="0"
             marginheight="0" frameborder="0" scrolling="no"></iframe>
       </div>
-      <div id="oauth-enroll-signin-link-container">
-        <a class="oauth-enroll-explain-link oauth-enroll-link"
-            i18n-content="oauthEnrollExplainLink" hidden></a>
+      <div id="oauth-enroll-signin-divider"></div>
+      <div id="oauth-enroll-signin-right">
+        <div id="oauth-enroll-re-enrollment-text"></div>
+        <div i18n-content="oauthEnrollDescription"></div>
+        <div><a id="oauth-enroll-learn-more-link" class="oauth-enroll-link"
+              i18n-content="oauthEnrollExplainLink"></a></div>
+        <div><a class="oauth-enroll-explain-link oauth-enroll-link"
+              i18n-content="oauthEnrollExplainLink"></a></div>
       </div>
     </div>
-    <div id="oauth-enroll-step-working" class="oauth-enroll-step-center" hidden>
+    <div id="oauth-enroll-step-working">
       <div class="oauth-enroll-step-content">
         <span class="oauth-enroll-step-icon">
           <span class="spinner"></span>
@@ -20,7 +25,7 @@
         </span>
       </div>
     </div>
-    <div id="oauth-enroll-step-error" class="oauth-enroll-step-center" hidden>
+    <div id="oauth-enroll-step-error">
       <div class="oauth-enroll-step-content">
         <span class="oauth-enroll-step-icon">
           <img src="chrome://theme/IDR_ENROLL_FAILURE">
@@ -31,12 +36,12 @@
             <a id="oauth-enroll-error-retry" class="oauth-enroll-link" href="#"
                 i18n-content="oauthEnrollRetry"></a>
             <a class="oauth-enroll-explain-link oauth-enroll-link" href="#"
-                i18n-content="oauthEnrollExplainLink" hidden></a>
+                i18n-content="oauthEnrollExplainLink"></a>
           </p>
         </span>
       </div>
     </div>
-    <div id="oauth-enroll-step-explain" class="oauth-enroll-step-center" hidden>
+    <div id="oauth-enroll-step-explain">
       <div class="oauth-enroll-step-content">
         <span class="oauth-enroll-step-icon">
           <img src="chrome://theme/IDR_INFO">
@@ -47,7 +52,7 @@
         </span>
       </div>
     </div>
-    <div id="oauth-enroll-step-success" class="oauth-enroll-step-center" hidden>
+    <div id="oauth-enroll-step-success">
       <div class="oauth-enroll-step-content">
         <span class="oauth-enroll-step-icon">
           <img src="chrome://theme/IDR_ENROLL_SUCCESS">
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
index 01e82ca..38c7e8b 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_oauth_enrollment.js
@@ -9,9 +9,10 @@
   /** @const */ var STEP_EXPLAIN = 'explain';
   /** @const */ var STEP_SUCCESS = 'success';
 
+  /** @const */ var HELP_TOPIC_ENROLLMENT = 4631259;
+
   return {
     EXTERNAL_API: [
-      'setIsAutoEnrollment',
       'showStep',
       'showError',
       'showWorking',
@@ -24,21 +25,6 @@
     signInUrl_: null,
 
     /**
-     * Whether this is a manual or auto enrollment.
-     */
-    isAutoEnrollment_: false,
-
-    /**
-     * True if enrollment cancellation should be prevented.
-     */
-    preventCancellation_: false,
-
-    /**
-     * Enrollment steps with names and buttons to show.
-     */
-    steps_: null,
-
-    /**
      * Dialog to confirm that auto-enrollment should really be cancelled.
      * This is only created the first time it's used.
      */
@@ -61,11 +47,30 @@
                               this.onMessage_.bind(this), false);
       $('oauth-enroll-error-retry').addEventListener('click',
                                                      this.doRetry_.bind(this));
+      $('oauth-enroll-learn-more-link').addEventListener(
+          'click',
+          function() {
+            chrome.send('launchHelpApp', [HELP_TOPIC_ENROLLMENT]);
+          });
       var links = document.querySelectorAll('.oauth-enroll-explain-link');
       for (var i = 0; i < links.length; i++) {
         links[i].addEventListener('click',
                                   this.showStep.bind(this, STEP_EXPLAIN));
       }
+
+      this.updateLocalizedContent();
+    },
+
+    /**
+     * Updates localized strings.
+     */
+    updateLocalizedContent: function() {
+      $('oauth-enroll-re-enrollment-text').innerHTML =
+          loadTimeData.getStringF(
+              'oauthEnrollReEnrollmentText',
+              '<b id="oauth-enroll-management-domain"></b>');
+      $('oauth-enroll-management-domain').textContent = this.managementDomain_;
+      $('oauth-enroll-re-enrollment-text').hidden = !this.managementDomain_;
     },
 
     /**
@@ -82,89 +87,58 @@
      */
     get buttons() {
       var buttons = [];
+      var ownerDocument = this.ownerDocument;
 
-      var cancelButton = this.ownerDocument.createElement('button');
-      cancelButton.id = 'oauth-enroll-cancel-button';
-      cancelButton.textContent = loadTimeData.getString('oauthEnrollCancel');
+      function makeButton(id, classes, label, handler) {
+        var button = ownerDocument.createElement('button');
+        button.id = id;
+        button.classList.add('oauth-enroll-button');
+        button.classList.add.apply(button.classList, classes);
+        button.textContent = label;
+        button.addEventListener('click', handler);
+        buttons.push(button);
+      }
 
-      cancelButton.addEventListener('click', function(e) {
-        chrome.send('oauthEnrollClose', ['cancel']);
-      }.bind(this));
-      buttons.push(cancelButton);
+      makeButton(
+          'oauth-enroll-cancel-button',
+          ['oauth-enroll-focus-on-error'],
+          loadTimeData.getString('oauthEnrollCancel'),
+          function() {
+            chrome.send('oauthEnrollClose', ['cancel']);
+          });
 
-      var tryAgainButton = this.ownerDocument.createElement('button');
-      tryAgainButton.id = 'oauth-enroll-try-again-button';
-      tryAgainButton.hidden = true;
-      tryAgainButton.textContent =
-          loadTimeData.getString('oauthEnrollRetry');
-      tryAgainButton.addEventListener('click', this.doRetry_.bind(this));
-      buttons.push(tryAgainButton);
+      makeButton(
+          'oauth-enroll-back-button',
+          ['oauth-enroll-focus-on-error'],
+          loadTimeData.getString('oauthEnrollCancelAutoEnrollmentGoBack'),
+          function() {
+            chrome.send('oauthEnrollClose', ['cancel']);
+          });
 
-      var explainButton = this.ownerDocument.createElement('button');
-      explainButton.id = 'oauth-enroll-explain-button';
-      explainButton.hidden = true;
-      explainButton.textContent =
-          loadTimeData.getString('oauthEnrollExplainButton');
-      explainButton.addEventListener('click', this.doRetry_.bind(this));
-      buttons.push(explainButton);
+      makeButton(
+          'oauth-enroll-retry-button',
+          ['oauth-enroll-focus-on-error'],
+          loadTimeData.getString('oauthEnrollRetry'),
+          this.doRetry_.bind(this));
 
-      var doneButton = this.ownerDocument.createElement('button');
-      doneButton.id = 'oauth-enroll-done-button';
-      doneButton.hidden = true;
-      doneButton.textContent =
-          loadTimeData.getString('oauthEnrollDone');
-      doneButton.addEventListener('click', function(e) {
-        chrome.send('oauthEnrollClose', ['done']);
-      });
-      buttons.push(doneButton);
+      makeButton(
+          'oauth-enroll-explain-retry-button',
+          ['oauth-enroll-focus-on-explain'],
+          loadTimeData.getString('oauthEnrollExplainButton'),
+          this.doRetry_.bind(this));
+
+      makeButton(
+          'oauth-enroll-done-button',
+          ['oauth-enroll-focus-on-success'],
+          loadTimeData.getString('oauthEnrollDone'),
+          function() {
+            chrome.send('oauthEnrollClose', ['done']);
+          });
 
       return buttons;
     },
 
     /**
-     * Sets the |isAutoEnrollment| flag of the OAuthEnrollmentScreen class and
-     * updates the UI.
-     * @param {boolean} is_auto_enrollment the new value of the flag.
-     */
-    setIsAutoEnrollment: function(is_auto_enrollment) {
-      this.isAutoEnrollment_ = is_auto_enrollment;
-      // The cancel button is not available during auto-enrollment.
-      var cancel = this.isAutoEnrollment_ ? null : 'cancel';
-      // During auto-enrollment the user must try again from the error screen.
-      var errorCancel = this.isAutoEnrollment_ ? 'try-again' : 'cancel';
-      this.steps_ = [
-        {
-          name: STEP_SIGNIN,
-          button: cancel
-        },
-        {
-          name: STEP_WORKING,
-          button: cancel
-        },
-        {
-          name: STEP_ERROR,
-          button: errorCancel,
-          focusButton: this.isAutoEnrollment_
-        },
-        {
-          name: STEP_EXPLAIN,
-          button: 'explain',
-          focusButton: true
-        },
-        {
-          name: STEP_SUCCESS,
-          button: 'done',
-          focusButton: true
-        },
-      ];
-
-      var links = document.querySelectorAll('.oauth-enroll-explain-link');
-      for (var i = 0; i < links.length; i++) {
-        links[i].hidden = !this.isAutoEnrollment_;
-      }
-    },
-
-    /**
      * Event handler that is invoked just before the frame is shown.
      * @param {Object} data Screen init payload, contains the signin frame
      * URL.
@@ -173,15 +147,15 @@
       var url = data.signin_url;
       url += '?gaiaUrl=' + encodeURIComponent(data.gaiaUrl);
       this.signInUrl_ = url;
-      this.setIsAutoEnrollment(data.is_auto_enrollment);
-      this.preventCancellation_ = data.prevent_cancellation;
+      var modes = ['manual', 'forced', 'auto'];
+      for (var i = 0; i < modes.length; ++i) {
+        this.classList.toggle('mode-' + modes[i],
+                              data.enrollment_mode == modes[i]);
+      }
+      this.managementDomain_ = data.management_domain;
       $('oauth-enroll-signin-frame').contentWindow.location.href =
           this.signInUrl_;
-      if (this.preventCancellation_) {
-        $('oauth-enroll-cancel-button').textContent =
-            loadTimeData.getString('oauthEnrollCancelAutoEnrollmentGoBack');
-      }
-
+      this.updateLocalizedContent();
       this.showStep(STEP_SIGNIN);
     },
 
@@ -189,9 +163,6 @@
      * Cancels enrollment and drops the user back to the login screen.
      */
     cancel: function() {
-      if (this.isAutoEnrollment_)
-        return;
-
       chrome.send('oauthEnrollClose', ['cancel']);
     },
 
@@ -201,23 +172,17 @@
      * "error", "success".
      */
     showStep: function(step) {
-      this.currentStep_ = step;
-      this.classList.toggle('saml', false);
-      $('oauth-enroll-cancel-button').hidden = true;
-      $('oauth-enroll-try-again-button').hidden = true;
-      $('oauth-enroll-explain-button').hidden = true;
-      $('oauth-enroll-done-button').hidden = true;
-      for (var i = 0; i < this.steps_.length; i++) {
-        var theStep = this.steps_[i];
-        var active = (theStep.name == step);
-        $('oauth-enroll-step-' + theStep.name).hidden = !active;
-        if (active && theStep.button) {
-          var button = $('oauth-enroll-' + theStep.button + '-button');
-          button.hidden = false;
-          if (theStep.focusButton)
-            button.focus();
+      this.classList.toggle('oauth-enroll-state-' + this.currentStep_, false);
+      this.classList.toggle('oauth-enroll-state-' + step, true);
+      var focusElements =
+          this.querySelectorAll('.oauth-enroll-focus-on-' + step);
+      for (var i = 0; i < focusElements.length; ++i) {
+        if (getComputedStyle(focusElements[i])['display'] != 'none') {
+          focusElements[i].focus();
+          break;
         }
       }
+      this.currentStep_ = step;
     },
 
     /**
@@ -227,12 +192,12 @@
      */
     showError: function(message, retry) {
       $('oauth-enroll-error-message').textContent = message;
-      $('oauth-enroll-error-retry').hidden = !retry || this.isAutoEnrollment_;
+      $('oauth-enroll-error-retry').hidden = !retry;
       this.showStep(STEP_ERROR);
     },
 
     /**
-     * Sets a progressing message and switches to the working screen.
+     * Sets a progress message and switches to the working screen.
      * @param {string} message the progress message.
      */
     showWorking: function(message) {
@@ -249,7 +214,12 @@
      * @param {string} email The authenticated user's e-mail address.
      */
     setAuthenticatedUserEmail: function(attemptToken, email) {
-      if (this.attemptToken_ == attemptToken)
+      if (this.attemptToken_ != attemptToken)
+        return;
+
+      if (!email)
+        this.showError(loadTimeData.getString('fatalEnrollmentError'), false);
+      else
         chrome.send('oauthEnrollCompleteLogin', [email]);
     },
 
@@ -257,15 +227,10 @@
      * Handler for cancellations of an enforced auto-enrollment.
      */
     cancelAutoEnrollment: function() {
-      // Check if this is forced enrollment flow for a kiosk app.
-      if (this.preventCancellation_)
+      // Only to be activated for the explain step in auto-enrollment.
+      if (this.currentStep_ !== STEP_EXPLAIN)
         return;
 
-      // The dialog to confirm cancellation of auto-enrollment is only shown
-      // if this is an auto-enrollment, and if the user is currently in the
-      // 'explain' step.
-      if (!this.isAutoEnrollment_ || this.currentStep_ !== STEP_EXPLAIN)
-        return;
       if (!this.confirmDialog_) {
         this.confirmDialog_ = new cr.ui.dialogs.ConfirmDialog(document.body);
         this.confirmDialog_.setOkLabel(
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_reset.css b/chrome/browser/resources/chromeos/login/oobe_screen_reset.css
index c9fe92e..f2ecc92 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_reset.css
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_reset.css
@@ -3,7 +3,20 @@
  * found in the LICENSE file.
  */
 
+.norollback #rollback,
+.norestart #reset-warning-restart,
+#powerwash-help-link {
+  display: none;
+}
+
+.norollback #powerwash-help-link {
+  display: block;
+}
+
 #reset {
+  display: flex;
+  flex-flow: column;
+  font-size: 16px;
   min-height: 423px;
   padding: 40px 17px 80px;
   text-align: center;
@@ -12,7 +25,12 @@
 
 #reset #reset-controls {
   -webkit-box-pack: center;
-  bottom: 80px;
+  bottom: 40px;
+  margin-top: auto;
+}
+
+#reset-controls button {
+  margin: 0 10px;
 }
 
 #reset #reset-warning-msg {
@@ -21,8 +39,18 @@
   padding: 5px 45px 30px;
 }
 
-#reset #reset-warning-details {
+.reset-text {
   color: #606060;
-  font-size: 16px;
-  padding: 35px 40px 80px;
+}
+
+#reset #reset-warning-details {
+  padding: 20px 40px 0;
+}
+
+#reset #reset-warning-restart {
+  padding: 30px 40px 0;
+}
+
+#reset #rollback {
+  padding: 30px 40px 10px;
 }
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_reset.html b/chrome/browser/resources/chromeos/login/oobe_screen_reset.html
index 16fba2b..4a94819 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_reset.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_reset.html
@@ -1,8 +1,24 @@
 <div class="step hidden no-logo" id="reset">
   <div class="step-contents">
-    <div id="reset-warning-msg" i18n-content="resetWarningText"></div>
+    <div id="reset-warning-msg"></div>
     <img id="reset-warning-icon" src="chrome://theme/IDR_RESET_WARNING" alt="">
-    <div id="reset-warning-details" i18n-content="resetWarningDetails"></div>
+    <div id="reset-warning-details" class="reset-text"></div>
+    <div id="reset-warning-data-details" class="reset-text">
+    </div>
+    <a id="powerwash-help-link" href="#" i18n-content="learnMore"></a>
+    <div id="reset-warning-restart" i18n-content="resetRestartMessage"
+         class="reset-text">
+    </div>
+    <div id="rollback" class="reset-text">
+      <div>
+        <input id="reset-rollback-checkbox" type="checkbox">
+        <label for="reset-rollback-checkbox" i18n-content="resetRollbackOption">
+        </label>
+        <a id="reset-powerwash-help-link-on-rollback" href="#"
+           i18n-content="learnMore">
+        </a>
+      </div>
+    </div>
   </div>
   <div id="reset-controls" class="step-controls"></div>
 </div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_reset.js b/chrome/browser/resources/chromeos/login/oobe_screen_reset.js
index e37989d..decc38d 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_reset.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_reset.js
@@ -8,6 +8,14 @@
 
 login.createScreen('ResetScreen', 'reset', function() {
   return {
+    /** @override */
+    decorate: function() {
+      $('reset-powerwash-help-link-on-rollback').addEventListener(
+          'click', function(event) {
+        chrome.send('resetOnLearnMore');
+      });
+    },
+
     /**
      * Header text of the screen.
      * @type {string}
@@ -22,12 +30,15 @@
      */
     get buttons() {
       var buttons = [];
-
       var resetButton = this.ownerDocument.createElement('button');
       resetButton.id = 'reset-button';
-      resetButton.textContent = loadTimeData.getString('resetButton');
+      resetButton.textContent = '';
       resetButton.addEventListener('click', function(e) {
-        chrome.send('resetOnReset');
+        if ($('reset').needRestart)
+          chrome.send('restartOnReset', [$('reset-rollback-checkbox').checked]);
+        else
+          chrome.send('powerwashOnReset',
+                      [$('reset-rollback-checkbox').checked]);
         e.stopPropagation();
       });
       buttons.push(resetButton);
@@ -36,7 +47,7 @@
       cancelButton.id = 'reset-cancel-button';
       cancelButton.textContent = loadTimeData.getString('cancelButton');
       cancelButton.addEventListener('click', function(e) {
-        chrome.send('resetOnCancel');
+        chrome.send('cancelOnReset');
         e.stopPropagation();
       });
       buttons.push(cancelButton);
@@ -55,8 +66,77 @@
      * Cancels the reset and drops the user back to the login screen.
      */
     cancel: function() {
-      chrome.send('resetOnCancel');
-    }
+      chrome.send('cancelOnReset');
+    },
+
+    /**
+     * Event handler that is invoked just before the screen in shown.
+     * @param {Object} data Screen init payload.
+     */
+    onBeforeShow: function(data) {
+      if (data === undefined)
+        return;
+      if ('showRestartMsg' in data)
+        this.setRestartMsg_(data['showRestartMsg']);
+      if ('showRollbackOption' in data)
+        this.setRollbackAvailable_(data['showRollbackOption']);
+      if ('simpleConfirm' in data) {
+        this.isConfirmational = data['simpleConfirm'];
+        this.confirmRollback = false;
+      }
+      if ('rollbackConfirm' in data) {
+        this.isConfirmational = data['rollbackConfirm'];
+        this.confirmRollback = true;
+      }
+
+      if (this.isConfirmational) {
+        // Exec after reboot initiated by reset screen.
+        // Confirmational form of screen.
+        $('reset-button').textContent = loadTimeData.getString(
+            'resetButtonReset');
+        if (this.confirmRollback) {
+          $('reset-warning-msg').textContent = loadTimeData.getString(
+              'resetAndRollbackWarningTextConfirmational');
+          $('reset-warning-details').textContent = loadTimeData.getString(
+              'resetAndRollbackWarningDetailsConfirmational');
+        } else {
+          $('reset-warning-msg').textContent = loadTimeData.getString(
+              'resetWarningTextConfirmational');
+          $('reset-warning-details').textContent = loadTimeData.getString(
+              'resetWarningDetailsConfirmational');
+        }
+      } else {
+        $('reset-warning-msg').textContent = loadTimeData.getString(
+            'resetWarningTextInitial');
+        $('reset-warning-details').textContent = loadTimeData.getString(
+            'resetWarningDetailsInitial');
+        if (this.needRestart)
+          $('reset-button').textContent = loadTimeData.getString(
+              'resetButtonRelaunch');
+        else
+          $('reset-button').textContent = loadTimeData.getString(
+              'resetButtonPowerwash');
+      }
+    },
+
+    /**
+      * Sets restart necessity for the screen.
+      * @param {bool} need_restart. If restart required before reset.
+      * @private
+      */
+    setRestartMsg_: function(need_restart) {
+      this.classList.toggle('norestart', !need_restart);
+      this.needRestart = need_restart;
+    },
+
+    /**
+      * Sets rollback availability for the screen.
+      * @param {bool} can_rollback. If Rollback is available on reset screen.
+      * @private
+      */
+    setRollbackAvailable_: function(show_rollback) {
+      this.classList.toggle('norollback', !show_rollback);
+      this.showRollback = show_rollback;
+    },
   };
 });
-
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_update.html b/chrome/browser/resources/chromeos/login/oobe_screen_update.html
index 4d490b0..102caf0 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_update.html
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_update.html
@@ -1,4 +1,5 @@
-<div class="step right hidden animated" id="update">
+<div class="step right hidden animated" id="update" role="group"
+     i18n-values="aria-label:updateScreenAccessibleTitle">
   <div class="step-contents">
     <div id="update-cancel-hint" hidden>
       <p i18n-content="cancelUpdateHint"></p>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js
index 844437f..cb7d0a2 100644
--- a/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js
+++ b/chrome/browser/resources/chromeos/login/oobe_screen_user_image.js
@@ -166,6 +166,8 @@
       this.profileImageLoading_ = value;
       $('user-image-screen-main').classList[
           value ? 'add' : 'remove']('profile-image-loading');
+      if (value)
+        announceAccessibleMessage(loadTimeData.getString('syncingPreferences'));
       this.updateProfileImageCaption_();
     },
 
@@ -247,8 +249,7 @@
       imageGrid.flipPhoto = !imageGrid.flipPhoto;
       var flipMessageId = imageGrid.flipPhoto ?
          'photoFlippedAccessibleText' : 'photoFlippedBackAccessibleText';
-      this.announceAccessibleMessage_(
-          loadTimeData.getString(flipMessageId));
+      announceAccessibleMessage(loadTimeData.getString(flipMessageId));
     },
 
     /**
@@ -265,7 +266,7 @@
      */
     handlePhotoTaken_: function(e) {
       chrome.send('photoTaken', [e.dataURL]);
-      this.announceAccessibleMessage_(
+      announceAccessibleMessage(
           loadTimeData.getString('photoCaptureAccessibleText'));
     },
 
@@ -284,29 +285,11 @@
       var imageGrid = $('user-image-grid');
       imageGrid.discardPhoto();
       chrome.send('discardPhoto');
-      this.announceAccessibleMessage_(
+      announceAccessibleMessage(
           loadTimeData.getString('photoDiscardAccessibleText'));
     },
 
     /**
-     * Add an accessible message to the page that will be announced to
-     * users who have spoken feedback on, but will be invisible to all
-     * other users. It's removed right away so it doesn't clutter the DOM.
-     */
-    announceAccessibleMessage_: function(msg) {
-      var element = document.createElement('div');
-      element.setAttribute('aria-live', 'polite');
-      element.style.position = 'relative';
-      element.style.left = '-9999px';
-      element.style.height = '0px';
-      element.innerText = msg;
-      document.body.appendChild(element);
-      window.setTimeout(function() {
-        document.body.removeChild(element);
-      }, 0);
-    },
-
-    /**
      * Event handler that is invoked just before the screen is shown.
      * @param {object} data Screen init payload.
      */
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.css b/chrome/browser/resources/chromeos/login/screen_error_message.css
index 77472d3..3e88cd0 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.css
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.css
@@ -12,10 +12,12 @@
 .show-with-ui-state-locally-managed,
 .show-with-ui-state-kiosk-mode,
 .show-with-ui-state-local-state-error,
+.show-with-ui-state-auto-enrollment-error,
 .show-with-error-state-portal,
 .show-with-error-state-offline,
 .show-with-error-state-proxy,
 .show-with-error-state-auth-ext-timeout,
+.show-with-error-state-kiosk-online,
 .guest-signin,
 .offline-login,
 .connecting-indicator {
@@ -32,6 +34,7 @@
 .error-state-offline .show-with-error-state-offline,
 .error-state-proxy .show-with-error-state-proxy,
 .error-state-auth-ext-timeout .show-with-error-state-auth-ext-timeout,
+.error-state-kiosk-online .show-with-error-state-kiosk-online,
 .allow-guest-signin .guest-signin,
 .allow-offline-login .offline-login,
 .show-connecting-indicator .connecting-indicator {
@@ -98,6 +101,15 @@
   -webkit-box-flex: 1;
 }
 
+.ui-state-auto-enrollment-error .error-guest-signin {
+  display: none;
+}
+
+.ui-state-auto-enrollment-error.allow-guest-signin
+    .error-guest-signin-fix-network {
+  display: block;
+}
+
 @-webkit-keyframes connecting-indicator-ellipsis {
   0% {
     opacity: 0;
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.html b/chrome/browser/resources/chromeos/login/screen_error_message.html
index b7c0abc..3b93667 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.html
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.html
@@ -12,8 +12,17 @@
                  show-with-error-state-auth-ext-timeout
                  show-with-ui-state-local-state-error">
       </div>
+      <div id="kiosk-online-title" i18n-content="kioskOnlineTitle"
+          class="error-title
+                 show-with-error-state-kiosk-online"></div>
     </div>
     <div class="error-body">
+      <div id="kiosk-online-message-body"
+          class="error-message-paragraph
+                 show-with-error-state-kiosk-online">
+        <span i18n-content="kioskOnlineMessageBody"
+            class="show-with-error-state-kiosk-online"></span>
+      </div>
       <div id="offline-message-body"
           class="error-message-paragraph
                  show-with-error-state-offline
@@ -75,7 +84,8 @@
               class="offline-network-list-label
                      show-with-error-state-offline
                      show-with-error-state-proxy
-                     show-with-error-state-auth-timeout"></label>
+                     show-with-error-state-auth-timeout
+                     show-with-error-state-kiosk-online"></label>
           <label for="offline-networks-list-dropdown"
               i18n-content="selectAnotherNetwork"
               class="offline-network-list-label
@@ -95,7 +105,17 @@
             class="error-message-paragraph">
         </div>
       </div>
-      <div id="error-guest-signin" class="error-message-paragraph guest-signin">
+      <div class="show-with-ui-state-update
+                  show-with-ui-state-signin
+                  show-with-ui-state-locally-managed
+                  show-with-ui-state-kiosk-mode
+                  show-with-ui-local-state-error">
+        <span id="error-guest-signin"
+            class="error-message-paragraph guest-signin"></span>
+      </div>
+      <div class="show-with-ui-state-auto-enrollment-error">
+        <span id="error-guest-signin-fix-network"
+            class="error-message-paragraph guest-signin"></span>
       </div>
       <div id="error-offline-login"
           class="error-message-paragraph offline-login"></div>
diff --git a/chrome/browser/resources/chromeos/login/screen_error_message.js b/chrome/browser/resources/chromeos/login/screen_error_message.js
index bb68507..52fa33b 100644
--- a/chrome/browser/resources/chromeos/login/screen_error_message.js
+++ b/chrome/browser/resources/chromeos/login/screen_error_message.js
@@ -40,7 +40,8 @@
     PORTAL: 'error-state-portal',
     OFFLINE: 'error-state-offline',
     PROXY: 'error-state-proxy',
-    AUTH_EXT_TIMEOUT: 'error-state-auth-ext-timeout'
+    AUTH_EXT_TIMEOUT: 'error-state-auth-ext-timeout',
+    KIOSK_ONLINE: 'error-state-kiosk-online'
   };
 
   // Possible error states of the screen. Must be in the same order as
@@ -50,7 +51,8 @@
     ERROR_STATE.PORTAL,
     ERROR_STATE.OFFLINE,
     ERROR_STATE.PROXY,
-    ERROR_STATE.AUTH_EXT_TIMEOUT
+    ERROR_STATE.AUTH_EXT_TIMEOUT,
+    ERROR_STATE.KIOSK_ONLINE
   ];
 
   return {
@@ -135,9 +137,15 @@
           'guestSignin',
           '<a id="error-guest-signin-link" class="signin-link" href="#">',
           '</a>');
-      $('error-guest-signin-link').onclick = function() {
-        chrome.send('launchIncognito');
-      };
+      $('error-guest-signin-link').onclick = this.launchGuestSession_;
+
+      $('error-guest-signin-fix-network').innerHTML = loadTimeData.getStringF(
+          'guestSigninFixNetwork',
+          '<a id="error-guest-fix-network-signin-link" class="signin-link" ' +
+              'href="#">',
+          '</a>');
+      $('error-guest-fix-network-signin-link').onclick =
+          this.launchGuestSession_;
 
       $('error-offline-login').innerHTML = loadTimeData.getStringF(
           'offlineLogin',
@@ -220,6 +228,16 @@
       });
       buttons.push(certsButton);
 
+      var continueButton = this.ownerDocument.createElement('button');
+      continueButton.id = 'continue-network-config-btn';
+      continueButton.textContent = loadTimeData.getString('continueButton');
+      continueButton.classList.add('show-with-error-state-kiosk-online');
+      continueButton.addEventListener('click', function(e) {
+        chrome.send('continueAppLaunch');
+        e.stopPropagation();
+      });
+      buttons.push(continueButton);
+
       var spacer = this.ownerDocument.createElement('div');
       spacer.classList.add('button-spacer');
       spacer.classList.add('show-with-ui-state-kiosk-mode');
@@ -284,6 +302,15 @@
     },
 
     /**
+     * Event handler for guest session launch.
+     * @private
+     */
+    launchGuestSession_: function() {
+      chrome.send(Oobe.getInstance().isOobeUI() ?
+          'launchOobeGuestSession' : 'launchIncognito');
+    },
+
+    /**
      * Prepares error screen to show guest signin link.
      * @private
      */
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html
index 03945e9..740be55 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.html
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.html
@@ -1,6 +1,5 @@
-<div class="step right hidden" id="gaia-signin">
+<div class="step right hidden" id="gaia-signin" role="group" aria-live="polite">
   <div class="step-contents">
-    <div id="gaia-signin-aria-label" aria-live="polite"></div>
     <div id="gaia-signin-form-container">
         <div id="login-box"><!-- Aligned with the login box in iframe --></div>
         <iframe id="signin-frame" name="signin-frame" hidden
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
index 8656552..d4e243a 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -220,10 +220,6 @@
         chrome.send('loginVisible', ['gaia-loading']);
       });
 
-      // Announce the name of the screen, if accessibility is on.
-      $('gaia-signin-aria-label').setAttribute(
-          'aria-label', loadTimeData.getString('signinScreenTitle'));
-
       // Button header is always visible when sign in is presented.
       // Header is hidden once GAIA reports on successful sign in.
       Oobe.getInstance().headerHidden = false;
@@ -325,7 +321,10 @@
      * @param {string} email The authenticated user's e-mail address.
      */
     setAuthenticatedUserEmail: function(attemptToken, email) {
-      this.gaiaAuthHost_.setAuthenticatedUserEmail(attemptToken, email);
+      if (!email)
+        this.showFatalAuthError();
+      else
+        this.gaiaAuthHost_.setAuthenticatedUserEmail(attemptToken, email);
     },
 
     /**
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
index 31e817c..6e84b7b 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.html
@@ -25,7 +25,9 @@
         <div id="managed-user-creation-managers-pane"></div>
       </div>
     </div>
-    <div id="managed-user-creation-username" class="page-no-marketing" hidden>
+    <div id="managed-user-creation-username" class="page-no-marketing"
+        role="group"
+        i18n-values="aria-label:createManagedUserNameAccessibleTitle" hidden>
       <div class="logo-padded-text">
         <div class="hide-on-import">
           <div class="page-title inline"
@@ -34,7 +36,8 @@
               class="page-title-explanation inline"></div>
         </div>
         <div id="managed-user-creation-name-block" class="hide-on-import">
-          <input id="managed-user-creation-name" type="text" maxlength="50" />
+          <input id="managed-user-creation-name" type="text" maxlength="50"
+              i18n-values="placeholder:createManagedUserNameHint" />
           <span id="managed-user-creation-name-error" class="no-error">
           </span>
         </div>
diff --git a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
index eab470f..650c78b 100644
--- a/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
+++ b/chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js
@@ -1451,8 +1451,7 @@
       imageGrid.flipPhoto = !imageGrid.flipPhoto;
       var flipMessageId = imageGrid.flipPhoto ?
          'photoFlippedAccessibleText' : 'photoFlippedBackAccessibleText';
-      this.announceAccessibleMessage_(
-          loadTimeData.getString(flipMessageId));
+      announceAccessibleMessage(loadTimeData.getString(flipMessageId));
     },
 
     /**
@@ -1460,11 +1459,13 @@
      */
     handleTakePhoto_: function(e) {
       this.getScreenElement('image-grid').takePhoto();
-      chrome.send('takePhoto');
+      chrome.send('supervisedUserTakePhoto');
     },
 
     handlePhotoTaken_: function(e) {
       chrome.send('supervisedUserPhotoTaken', [e.dataURL]);
+      announceAccessibleMessage(
+          loadTimeData.getString('photoCaptureAccessibleText'));
     },
 
     /**
@@ -1481,28 +1482,11 @@
     handleDiscardPhoto_: function(e) {
       var imageGrid = this.getScreenElement('image-grid');
       imageGrid.discardPhoto();
-      chrome.send('discardPhoto');
+      chrome.send('supervisedUserDiscardPhoto');
+      announceAccessibleMessage(
+          loadTimeData.getString('photoDiscardAccessibleText'));
     },
 
-    /**
-     * Add an accessible message to the page that will be announced to
-     * users who have spoken feedback on, but will be invisible to all
-     * other users. It's removed right away so it doesn't clutter the DOM.
-     */
-    announceAccessibleMessage_: function(msg) {
-      var element = document.createElement('div');
-      element.setAttribute('aria-live', 'polite');
-      element.style.position = 'relative';
-      element.style.left = '-9999px';
-      element.style.height = '0px';
-      element.innerText = msg;
-      document.body.appendChild(element);
-      window.setTimeout(function() {
-        document.body.removeChild(element);
-      }, 0);
-    },
-
-
     setCameraPresent: function(present) {
       this.getScreenElement('image-grid').cameraPresent = present;
     },
diff --git a/chrome/browser/resources/chromeos/network.css b/chrome/browser/resources/chromeos/network.css
index 7822fe6..4996dda 100644
--- a/chrome/browser/resources/chromeos/network.css
+++ b/chrome/browser/resources/chromeos/network.css
@@ -45,6 +45,28 @@
   font-weight: bold;
 }
 
+.state-table-expand-button-cell {
+  text-align: center;
+}
+
+.state-table-expand-button {
+  background-color: #f0f0f0;
+  border: 1px solid;
+  border-color: #a0a0a0;
+  height: 12px;
+  margin: 4px;
+  padding: 0;
+  width: 12px;
+}
+
+.state-table-expand-button-expanded {
+  background-color: #b0b0b0;
+}
+
+.state-table-expanded-cell {
+  white-space: pre-wrap;
+}
+
 .network-level-tag {
   -webkit-margin-end: 5px;
   border: 1px solid;
diff --git a/chrome/browser/resources/chromeos/network.html b/chrome/browser/resources/chromeos/network.html
index 653651d..bc87812 100644
--- a/chrome/browser/resources/chromeos/network.html
+++ b/chrome/browser/resources/chromeos/network.html
@@ -33,6 +33,7 @@
   <h3>Networks: </h3>
   <table id="network-state-table" class="state-table">
     <tr class="state-table-header">
+      <td></td>
       <td>Path</td>
       <td>GUID</td>
       <td>Name</td>
@@ -53,6 +54,7 @@
   <h3>Favorites: </h3>
   <table id="favorite-state-table" class="state-table">
     <tr class="state-table-header">
+      <td></td>
       <td>Path</td>
       <td>GUID</td>
       <td>Name</td>
diff --git a/chrome/browser/resources/chromeos/network.js b/chrome/browser/resources/chromeos/network.js
index 24bbce5..4cfec58 100644
--- a/chrome/browser/resources/chromeos/network.js
+++ b/chrome/browser/resources/chromeos/network.js
@@ -95,15 +95,33 @@
   };
 
   /**
+   * Create a cell with a button for expanding a network state table row.
+   *
+   * @param {dictionary} state Property values for the network or favorite.
+   * @return {DOMElement} The created td element that displays the given value.
+   */
+  var createStateTableExpandButton = function(state) {
+    var cell = document.createElement('td');
+    cell.className = 'state-table-expand-button-cell';
+    var button = document.createElement('button');
+    button.addEventListener('click', function(event) {
+      toggleExpandRow(event.target, state);
+    });
+    button.className = 'state-table-expand-button';
+    cell.appendChild(button);
+    return cell;
+  };
+
+  /**
    * Create a cell in network state table.
    *
    * @param {string} value Content in the cell.
    * @return {DOMElement} The created td element that displays the given value.
    */
   var createStateTableCell = function(value) {
-    var col = document.createElement('td');
-    col.textContent = value || '';
-    return col;
+    var cell = document.createElement('td');
+    cell.textContent = value || '';
+    return cell;
   };
 
   /**
@@ -118,8 +136,12 @@
   var createStateTableRow = function(stateFields, path, state) {
     var row = document.createElement('tr');
     row.className = 'state-table-row';
+    row.appendChild(createStateTableExpandButton(state));
     row.appendChild(createStateTableCell(path));
-    row.appendChild(createStateTableCell(state['GUID'].slice(1, 9)));
+    var guid = state['GUID'];
+    if (guid)
+      guid = guid.slice(1, 9);
+    row.appendChild(createStateTableCell(guid));
     for (var i = 0; i < stateFields.length; ++i) {
       var field = stateFields[i];
       var value = '';
@@ -168,11 +190,52 @@
   };
 
   /**
+   * Toggle the button state and add or remove a row displaying the complete
+   * state information for a row.
+   *
+   * @param {DOMElement} btn The button that was clicked.
+   * @param {dictionary} state Property values for the network or favorite.
+   */
+  var toggleExpandRow = function(btn, state) {
+    var cell = btn.parentNode;
+    var row = cell.parentNode;
+    if (btn.classList.contains('state-table-expand-button-expanded')) {
+      btn.classList.remove('state-table-expand-button-expanded');
+      row.parentNode.removeChild(row.nextSibling);
+    } else {
+      btn.classList.add('state-table-expand-button-expanded');
+      var expandedRow = createExpandedRow(state, row);
+      row.parentNode.insertBefore(expandedRow, row.nextSibling);
+    }
+  };
+
+  /**
+   * Creates the expanded row for displaying the complete state as JSON.
+   *
+   * @param {dictionary} state Property values for the network or favorite.
+   * @param {DOMElement} baseRow The unexpanded row associated with the new row.
+   * @return {DOMElement} The created tr element for the expanded row.
+   */
+  var createExpandedRow = function(state, baseRow) {
+    var expandedRow = document.createElement('tr');
+    expandedRow.className = 'state-table-row';
+    var emptyCell = document.createElement('td');
+    emptyCell.style.border = 'none';
+    expandedRow.appendChild(emptyCell);
+    var detailCell = document.createElement('td');
+    detailCell.className = 'state-table-expanded-cell';
+    detailCell.colSpan = baseRow.childNodes.length - 1;
+    detailCell.innerHTML = JSON.stringify(state, null, '\t');
+    expandedRow.appendChild(detailCell);
+    return expandedRow;
+  };
+
+  /**
    * Sends a refresh request.
    */
   var sendRefresh = function() {
     chrome.send('requestNetworkInfo');
-  }
+  };
 
   /**
    * Sets refresh rate if the interval is found in the url.
diff --git a/chrome/browser/resources/chromeos/sounds/startup2.wav b/chrome/browser/resources/chromeos/sounds/startup2.wav
new file mode 100644
index 0000000..c42fc12
--- /dev/null
+++ b/chrome/browser/resources/chromeos/sounds/startup2.wav
Binary files differ
diff --git a/chrome/browser/resources/chromeos/user_images_grid.js b/chrome/browser/resources/chromeos/user_images_grid.js
index 0685791..b64b7ae 100644
--- a/chrome/browser/resources/chromeos/user_images_grid.js
+++ b/chrome/browser/resources/chromeos/user_images_grid.js
@@ -10,18 +10,6 @@
   /** @const */ var ListSingleSelectionModel = cr.ui.ListSingleSelectionModel;
 
   /**
-   * Interval between consecutive camera presence checks in msec.
-   * @const
-   */
-  var CAMERA_CHECK_INTERVAL_MS = 3000;
-
-  /**
-   * Interval between consecutive camera liveness checks in msec.
-   * @const
-   */
-  var CAMERA_LIVENESS_CHECK_MS = 3000;
-
-  /**
    * Number of frames recorded by takeVideo().
    * @const
    */
@@ -209,20 +197,6 @@
     },
 
     /**
-     * Start camera presence check.
-     * @private
-     */
-    checkCameraPresence_: function() {
-      if (this.cameraPresentCheckTimer_) {
-        window.clearTimeout(this.cameraPresentCheckTimer_);
-        this.cameraPresentCheckTimer_ = null;
-      }
-      if (!this.cameraVideo_)
-        return;
-      chrome.send('checkCameraPresence');
-    },
-
-    /**
      * Whether a camera is present or not.
      * @type {boolean}
      */
@@ -233,10 +207,6 @@
       this.cameraPresent_ = value;
       if (this.cameraLive)
         this.cameraImage = null;
-      // Repeat the check after some time.
-      this.cameraPresentCheckTimer_ = window.setTimeout(
-          this.checkCameraPresence_.bind(this),
-          CAMERA_CHECK_INTERVAL_MS);
     },
 
     /**
@@ -248,14 +218,7 @@
       return this.previewElement.classList.contains('online');
     },
     set cameraOnline(value) {
-      this.previewElement.classList[value ? 'add' : 'remove']('online');
-      if (value) {
-        this.cameraLiveCheckTimer_ = window.setInterval(
-            this.checkCameraLive_.bind(this), CAMERA_LIVENESS_CHECK_MS);
-      } else if (this.cameraLiveCheckTimer_) {
-        window.clearInterval(this.cameraLiveCheckTimer_);
-        this.cameraLiveCheckTimer_ = null;
-      }
+      this.previewElement.classList.toggle('online', value);
     },
 
     /**
@@ -333,18 +296,6 @@
     },
 
     /**
-     * Checks if camera is still live by comparing the timestamp of the last
-     * 'timeupdate' event with the current time.
-     * @private
-     */
-    checkCameraLive_: function() {
-      if (new Date().getTime() - this.lastFrameTime_ >
-          CAMERA_LIVENESS_CHECK_MS) {
-        this.cameraPresent = false;
-      }
-    },
-
-    /**
      * Type of the selected image (one of 'default', 'profile', 'camera').
      * Setting it will update class list of |previewElement|.
      * @type {string}
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index 6257793..a6a7bfc 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -72,15 +72,16 @@
         <include name="IDR_FILE_MANAGER_MAIN_JS" file="file_manager/foreground/js/main_scripts.js" flattenhtml="true" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_BKGND_JS" file="file_manager/background/js/background.js" type="BINDATA" />
 
-        <include name="IDR_FILE_MANAGER_MEDIAPLAYER" file="file_manager/mediaplayer.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_MEDIAPLAYER_JS" file="file_manager/foreground/js/media/mediaplayer_scripts.js" flattenhtml="true" type="BINDATA" />
-
+        <include name="IDR_VIDEO_PLAYER" file="video_player/video_player.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_VIDEO_PLAYER_JS" file="video_player/js/video_player_scripts.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_VIDEO_PLAYER_BKGND_JS" file="video_player/js/background.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_VIDEO_PLAYER_TEST_UTIL_JS" file="video_player/js/test_util.js" flattenhtml="false" type="BINDATA" />
+        <include name="IDR_VIDEO_PLAYER_ERROR_UTIL_JS" file="video_player/js/error_util.js" flattenhtml="false" type="BINDATA" />
+        <include name="IDR_VIDEO_PLAYER_ICON_16" file="video_player/images/100/icon.png" type="BINDATA" />
+        <include name="IDR_VIDEO_PLAYER_ICON_32" file="video_player/images/200/icon.png" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_AUDIO_PLAYER" file="file_manager/audio_player.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_AUDIO_PLAYER_SCRIPTS_JS" file="file_manager/audio_player/js/audio_player_scripts.js" flattenhtml="true" type="BINDATA" />
 
-        <include name="IDR_FILE_MANAGER_VIDEO_PLAYER" file="file_manager/video_player.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
-        <include name="IDR_FILE_MANAGER_VIDEO_PLAYER_JS" file="file_manager/foreground/js/media/video_player_scripts.js" flattenhtml="true" type="BINDATA" />
-
         <include name="IDR_FILE_MANAGER_GALLERY" file="file_manager/gallery.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
         <include name="IDR_FILE_MANAGER_GALLERY_JS" file="file_manager/foreground/js/photo/gallery_scripts.js" flattenhtml="true" type="BINDATA" />
 
diff --git a/chrome/browser/resources/extensions/extension_command_list.js b/chrome/browser/resources/extensions/extension_command_list.js
index c9370de..8b7ed57 100644
--- a/chrome/browser/resources/extensions/extension_command_list.js
+++ b/chrome/browser/resources/extensions/extension_command_list.js
@@ -475,9 +475,12 @@
 
         this.oldValue_ = keystroke;  // Forget what the old value was.
         var parsed = this.parseElementId_('command', node.id);
+
+        // Ending the capture must occur before calling
+        // setExtensionCommandShortcut to ensure the shortcut is set.
+        this.endCapture_(event);
         chrome.send('setExtensionCommandShortcut',
                     [parsed.extensionId, parsed.commandName, keystroke]);
-        this.endCapture_(event);
       }
 
       this.currentKeyEvent_ = event;
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_center.png b/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_center.png
index a3a4f7d..bb41a0b 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_left.png b/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_left.png
index b8feaf2..97305c2 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_left.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_right.png b/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_right.png
index 351ab54..52ffe90 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_right.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/bottom_base_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_next.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_next.png
index c65926e..f717fe8 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_next.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_next.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pause.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pause.png
index 49e62f6..709c215 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pause.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pause.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_play.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_play.png
index 814e474..298eadc 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_play.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_play.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist.png
index 77b4120..335703b 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist_active.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist_active.png
index 03d4729..39de0b2 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_playlist_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pressed.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pressed.png
index 66dd596..162bec4 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pressed.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_previous.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_previous.png
index 28534ce..373afd5 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_previous.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_previous.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat.png
index eb24d32..86b51ca 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat_active.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat_active.png
index 34d2054..bd1dd46 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_repeat_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle.png
index 7cffae7..0e13f1f 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle_active.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle_active.png
index 2e1ab22..f533c53 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_shuffle_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume.png
index d7ea3c1..175ee6d 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume_active.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume_active.png
index 03ffa5d..d958503 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_button_volume_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_center.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_center.png
index 7193693..f5dd2ac 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_left.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_left.png
index c68c02c..35ab5a4 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_left.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_right.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_right.png
index c68c02c..35ab5a4 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_right.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_base_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler.png
index 13b5d35..c59a529 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler_pressed.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler_pressed.png
index c8c1ae6..fa8526a 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler_pressed.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_handler_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_center.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_center.png
index d218645..b7ab78c 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_left.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_left.png
index 3ece2ec..9116014 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_left.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_right.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_right.png
index 3ece2ec..9116014 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_right.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_timeline_played_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_bottom.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_bottom.png
index 28ac9ad..70dac11 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_bottom.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_bottom.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_center.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_center.png
index 8fa73e7..0d74ad0 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_top.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_top.png
index 28ac9ad..70dac11 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_top.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_base_top.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_bottom.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_bottom.png
index 4004820..aeb0f62 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_bottom.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_bottom.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_center.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_center.png
index 93b4839..7b3b7ef 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_top.png b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_top.png
index 4004820..aeb0f62 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_top.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/100/player_volume_level_top.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_center.png b/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_center.png
index 88b4558..4d3e9fd 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_left.png b/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_left.png
index 319ea62..04fc369 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_left.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_right.png b/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_right.png
index f4289e8..e351ae1 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_right.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/bottom_base_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_next.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_next.png
index c3c2ea2..53a9252 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_next.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_next.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pause.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pause.png
index cf07c8c..2fc73a4 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pause.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pause.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_play.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_play.png
index fad7cb2..dd9d393 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_play.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_play.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist.png
index 550f10b..5740a25 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist_active.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist_active.png
index 4d42418..fc9714d 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_playlist_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pressed.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pressed.png
index 90539e2..c21edae 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pressed.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_previous.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_previous.png
index 8ad5f83..d09ec3b 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_previous.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_previous.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat.png
index 1965327..0f0679f 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat_active.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat_active.png
index 628699f..e73a8e9 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_repeat_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle.png
index 8a03887..cee7663 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle_active.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle_active.png
index 854e0cb..9dbf309 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_shuffle_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume.png
index 3c249c2..b08c9e5 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume_active.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume_active.png
index 480bffd..ece8ce9 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume_active.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_button_volume_active.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_center.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_center.png
index 194565f..2154855 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_left.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_left.png
index 3b6e4e1..4a11dd2 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_left.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_right.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_right.png
index c3ae07a..76279c4 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_right.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_base_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler.png
index f9bc0d0..8a54c4b 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler_pressed.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler_pressed.png
index 1fc1fe4..c27d948 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler_pressed.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_handler_pressed.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_center.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_center.png
index 9320d4c..f113bbd 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_left.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_left.png
index f99a816..9c63b73 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_left.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_left.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_right.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_right.png
index 6d51f1d..abcc959 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_right.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_timeline_played_right.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_bottom.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_bottom.png
index bfa2b66..beaa8aa 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_bottom.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_bottom.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_center.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_center.png
index 335f894..d4ed370 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_top.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_top.png
index ccf5a77..c6b68c2 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_top.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_base_top.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_bottom.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_bottom.png
index 59bbeab..b4707bd 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_bottom.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_bottom.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_center.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_center.png
index 9f12e25..1a1143b 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_center.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_center.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_top.png b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_top.png
index cd274d0..261037a 100644
--- a/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_top.png
+++ b/chrome/browser/resources/file_manager/audio_player/assets/200/player_volume_level_top.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/elements/track_list.css b/chrome/browser/resources/file_manager/audio_player/elements/track_list.css
index 2f0de8e..bc9500b 100644
--- a/chrome/browser/resources/file_manager/audio_player/elements/track_list.css
+++ b/chrome/browser/resources/file_manager/audio_player/elements/track_list.css
@@ -33,7 +33,7 @@
   width: 100%;
 }
 
-track-list:not([expanded]) > .track:not([active]) {
+:host(:not([expanded]):host) > .track:not([active]) {
   display: none;
 }
 
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-128.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-128.png
index 75d0b79..15b7772 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-128.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-128.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-256.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-256.png
index 738d228..e1202a8 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-256.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-256.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-32.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-32.png
index 9bcd22a..b22e5f6 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-32.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-32.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-48.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-48.png
index fbaeb36..305a3a9 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-48.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-48.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-64.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-64.png
index 9826ddd..724ee20 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-64.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-64.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-96.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-96.png
index b37c7b0..d866c35 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-96.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-96.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-16.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-16.png
index a04d890..90168b8 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-16.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-16.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-32.png b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-32.png
index 30ab220..50c7c87 100644
--- a/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-32.png
+++ b/chrome/browser/resources/file_manager/audio_player/icons/audio-player-favicon-32.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/background/js/background.js b/chrome/browser/resources/file_manager/background/js/background.js
index 386aa23..604c254 100644
--- a/chrome/browser/resources/file_manager/background/js/background.js
+++ b/chrome/browser/resources/file_manager/background/js/background.js
@@ -690,10 +690,6 @@
       launchAudioPlayer({items: urls, position: 0});
       break;
 
-    case 'watch':
-      launchVideoPlayer(urls[0]);
-      break;
-
     default:
       var launchEnable = null;
       var queue = new AsyncUtil.Queue();
@@ -803,21 +799,6 @@
   });
 }
 
-var videoPlayer = new SingletonAppWindowWrapper('video_player.html',
-                                                {hidden: true});
-
-/**
- * Launches the video player.
- * @param {string} url Video url.
- * @param {string=} opt_displayedId ProfileID of the desktop where the video
- *     player should show.
- */
-function launchVideoPlayer(url, opt_displayedId) {
-  videoPlayer.launch({url: url}, false, function(appWindow) {
-    AppWindowWrapper.focusOnDesktop(videoPlayer.rawAppWindow, opt_displayedId);
-  });
-}
-
 /**
  * Launches the app.
  * @private
@@ -871,9 +852,6 @@
     });
     callback();
   });
-
-  // Reopen video player.
-  videoPlayer.reopen();
 };
 
 /**
diff --git a/chrome/browser/resources/file_manager/background/js/test_util.js b/chrome/browser/resources/file_manager/background/js/test_util.js
index 75d45cb..e69b9d7 100644
--- a/chrome/browser/resources/file_manager/background/js/test_util.js
+++ b/chrome/browser/resources/file_manager/background/js/test_util.js
@@ -72,6 +72,21 @@
 };
 
 /**
+ * Closes the specified window.
+ *
+ * @param {string} appId AppId of window to be closed.
+ * @return {boolean} Result: True if success, false otherwise.
+ */
+test.util.sync.closeWindow = function(appId) {
+  if (appId in background.appWindows &&
+      background.appWindows[appId].contentWindow) {
+    background.appWindows[appId].close();
+    return true;
+  }
+  return false;
+};
+
+/**
  * Gets a document in the Files.app's window, including iframes.
  *
  * @param {Window} contentWindow Window to be used.
diff --git a/chrome/browser/resources/file_manager/foreground/css/common.css b/chrome/browser/resources/file_manager/foreground/css/common.css
index 12d18c1..ebb35bb 100644
--- a/chrome/browser/resources/file_manager/foreground/css/common.css
+++ b/chrome/browser/resources/file_manager/foreground/css/common.css
@@ -319,6 +319,8 @@
   color: rgb(150, 150, 150);
 }
 
+select:not([size]):hover,
+select[size='0']:hover,
 select[size='1']:hover {
   /* Original value is '5 fill', which hides the dropdown triangle. */
   border-image-slice: 5;
diff --git a/chrome/browser/resources/file_manager/foreground/css/file_manager.css b/chrome/browser/resources/file_manager/foreground/css/file_manager.css
index 9af65ec..95fc098 100644
--- a/chrome/browser/resources/file_manager/foreground/css/file_manager.css
+++ b/chrome/browser/resources/file_manager/foreground/css/file_manager.css
@@ -353,11 +353,9 @@
 }
 
 #navigation-list .root-item > div.root-eject {
-  background-image: -webkit-image-set(
-    url('../images/files/ui/eject.png') 1x,
-    url('../images/files/ui/2x/eject.png') 2x);
-  background-position: center center;
-  background-repeat: no-repeat;
+  background: -webkit-image-set(
+      url('../images/files/ui/eject.png') 1x,
+      url('../images/files/ui/2x/eject.png') 2x) no-repeat center;
   cursor: pointer;
   height: 20px;
   margin-right: 6px;
@@ -368,7 +366,9 @@
 }
 
 #navigation-list:focus .root-item[selected] > div.root-eject {
-  -webkit-filter: brightness(0) invert();
+  background: -webkit-image-set(
+      url('../images/files/ui/eject_white.png') 1x,
+      url('../images/files/ui/2x/eject_white.png') 2x) no-repeat center;
   opacity: 1;
 }
 
@@ -1633,15 +1633,15 @@
 
 list.autocomplete-suggestions > li > div[search-icon] {
   background: -webkit-image-set(
-    url('../images/files/ui/search_icon_active.png') 1x,
-    url('../images/files/ui/2x/search_icon_active.png') 2x);
-  background-position: center;
-  background-repeat: no-repeat;
+      url('../images/files/ui/search_icon_active.png') 1x,
+      url('../images/files/ui/2x/search_icon_active.png') 2x) center no-repeat;
 }
 
 list.autocomplete-suggestions > li[selected] > div[search-icon],
 list.autocomplete-suggestions > li[lead] > div[search-icon] {
-  -webkit-filter: brightness(0) invert();
+  background: -webkit-image-set(
+      url('../images/files/ui/search_icon_white.png') 1x,
+      url('../images/files/ui/2x/search_icon_white.png') 2x) center no-repeat;
 }
 
 list.autocomplete-suggestions > [selected],
@@ -1696,7 +1696,7 @@
   height: 48px;
   left: 64px;
   position: absolute;
-  right: 92px;
+  right: 134px;
   top: 0;
   width: auto;
   z-index: 101;
diff --git a/chrome/browser/resources/file_manager/foreground/css/gallery.css b/chrome/browser/resources/file_manager/foreground/css/gallery.css
index 7680f4d..1a62e4d 100644
--- a/chrome/browser/resources/file_manager/foreground/css/gallery.css
+++ b/chrome/browser/resources/file_manager/foreground/css/gallery.css
@@ -1359,6 +1359,13 @@
   width: 32px;
 }
 
+.gallery > .header > .minimize-button {
+  background: -webkit-image-set(
+    url('chrome://resources/images/apps/topbar_button_minimize.png') 1x,
+    url('chrome://resources/images/2x/apps/topbar_button_minimize.png') 2x)
+    center;
+}
+
 .gallery > .header > .maximize-button {
   background: -webkit-image-set(
     url('chrome://resources/images/apps/topbar_button_maximize.png') 1x,
diff --git a/chrome/browser/resources/file_manager/foreground/css/video_player.css b/chrome/browser/resources/file_manager/foreground/css/video_player.css
deleted file mode 100644
index decb63d..0000000
--- a/chrome/browser/resources/file_manager/foreground/css/video_player.css
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file. */
-
-body {
-  -webkit-user-select: none;
-  background: black;
-  font-family: Noto Sans UI,Droid Sans Fallback,sans-serif;
-  font-size: 84%;
-  margin: 0;
-  overflow: hidden;
-}
-
-#video-player {
-  height: 100%;
-  left: 0;
-  position: absolute;
-  top: 0;
-  width: 100%;
-}
-
-#video-container {
-  height: 100%;
-  left: 0;
-  position: absolute;
-  top: 0;
-  width: 100%;
-}
-
-video {
-  height: 100%;
-  left: 0;
-  pointer-events: none;
-  position: absolute;
-  top: 0;
-  width: 100%;
-}
-
-#controls-wrapper {
-  -webkit-box-align: center;
-  -webkit-box-orient: horizontal;
-  -webkit-box-pack: center;
-  bottom: 0;
-  display: -webkit-box;
-  left: 0;
-  position: absolute;
-  right: 0;
-}
-
-#controls {
-  -webkit-box-flex: 1;
-  display: -webkit-box;
-}
-
-#video-player:not([tools]) .tool {
-  opacity: 0;
-}
-
-#video-player:not([tools]) {
-  cursor: none;
-}
-
-#video-player[disabled] .tool {
-  display: none;
-}
-
-.tool {
-  transition: opacity 180ms linear;
-}
-
-#error-wrapper {
-  -webkit-box-align: center;
-  -webkit-box-orient: horizontal;
-  -webkit-box-pack: center;
-  display: -webkit-box;
-  height: 100%;
-  left: 0;
-  pointer-events: none;
-  position: absolute;
-  top: 0;
-  width: 100%;
-}
-
-#error {
-  -webkit-box-align: center;
-  -webkit-box-orient: horizontal;
-  -webkit-box-pack: center;
-  background-color: rgba(24, 24, 24, 1);
-  background-image: -webkit-image-set(
-    url('../images/media/error.png') 1x,
-    url('../images/media/2x/error.png') 2x);
-  background-position: 25px center;
-  background-repeat: no-repeat;
-  color: white;
-  display: -webkit-box;
-  height: 54px;
-  padding-left: 70px;
-  padding-right: 35px;
-}
-
-#error:not([visible]) {
-  display: none;
-}
diff --git a/chrome/browser/resources/file_manager/foreground/images/files/ui/2x/eject_white.png b/chrome/browser/resources/file_manager/foreground/images/files/ui/2x/eject_white.png
new file mode 100644
index 0000000..86ce5ec
--- /dev/null
+++ b/chrome/browser/resources/file_manager/foreground/images/files/ui/2x/eject_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/foreground/images/files/ui/2x/search_icon_white.png b/chrome/browser/resources/file_manager/foreground/images/files/ui/2x/search_icon_white.png
new file mode 100644
index 0000000..b49fc5f
--- /dev/null
+++ b/chrome/browser/resources/file_manager/foreground/images/files/ui/2x/search_icon_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/foreground/images/files/ui/eject_white.png b/chrome/browser/resources/file_manager/foreground/images/files/ui/eject_white.png
new file mode 100644
index 0000000..20f1fd2
--- /dev/null
+++ b/chrome/browser/resources/file_manager/foreground/images/files/ui/eject_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/foreground/images/files/ui/search_icon_white.png b/chrome/browser/resources/file_manager/foreground/images/files/ui/search_icon_white.png
new file mode 100644
index 0000000..dcc0f40
--- /dev/null
+++ b/chrome/browser/resources/file_manager/foreground/images/files/ui/search_icon_white.png
Binary files differ
diff --git a/chrome/browser/resources/file_manager/foreground/js/directory_contents.js b/chrome/browser/resources/file_manager/foreground/js/directory_contents.js
index 7c9cfa5..23581f2 100644
--- a/chrome/browser/resources/file_manager/foreground/js/directory_contents.js
+++ b/chrome/browser/resources/file_manager/foreground/js/directory_contents.js
@@ -528,12 +528,30 @@
  * 'scan-failed' event will be fired upon completion.
  */
 DirectoryContents.prototype.scan = function() {
+  /**
+   * Invoked when the scanning is completed successfully.
+   * @this {DirectoryContents}
+   */
+  function completionCallback() {
+    this.onScanFinished_();
+    this.onScanCompleted_();
+  }
+
+  /**
+   * Invoked when the scanning is finished but is not completed due to error.
+   * @this {DirectoryContents}
+   */
+  function errorCallback() {
+    this.onScanFinished_();
+    this.onScanError_();
+  }
+
   // TODO(hidehiko,mtomasz): this scan method must be called at most once.
   // Remove such a limitation.
   this.scanner_ = this.scannerFactory_();
   this.scanner_.scan(this.onNewEntries_.bind(this),
-                     this.onScanCompleted_.bind(this),
-                     this.onScanError_.bind(this));
+                     completionCallback.bind(this),
+                     errorCallback.bind(this));
 };
 
 /**
@@ -546,22 +564,49 @@
   if (this.scanner_)
     this.scanner_.cancel();
 
+  this.onScanFinished_();
+
   this.prefetchMetadataQueue_.cancel();
   cr.dispatchSimpleEvent(this, 'scan-cancelled');
 };
 
 /**
- * Called when the scanning by scanner_ is done.
+ * Called when the scanning by scanner_ is done, even when the scanning is
+ * succeeded or failed. This is called before completion (or error) callback.
+ *
+ * @private
+ */
+DirectoryContents.prototype.onScanFinished_ = function() {
+  this.scanner_ = null;
+
+  this.prefetchMetadataQueue_.run(function(callback) {
+    // TODO(yoshiki): Here we should fire the update event of changed
+    // items. Currently we have a method this.fileList_.updateIndex() to
+    // fire an event, but this method takes only 1 argument and invokes sort
+    // one by one. It is obviously time wasting. Instead, we call sort
+    // directory.
+    // In future, we should implement a good method like updateIndexes and
+    // use it here.
+    var status = this.fileList_.sortStatus;
+    if (status)
+      this.fileList_.sort(status.field, status.direction);
+
+    callback();
+  }.bind(this));
+};
+
+/**
+ * Called when the scanning by scanner_ is succeeded.
  * @private
  */
 DirectoryContents.prototype.onScanCompleted_ = function() {
-  this.scanner_ = null;
   if (this.scanCancelled_)
     return;
 
   this.prefetchMetadataQueue_.run(function(callback) {
     // Call callback first, so isScanning() returns false in the event handlers.
     callback();
+
     cr.dispatchSimpleEvent(this, 'scan-completed');
   }.bind(this));
 };
@@ -571,7 +616,6 @@
  * @private
  */
 DirectoryContents.prototype.onScanError_ = function() {
-  this.scanner_ = null;
   if (this.scanCancelled_)
     return;
 
@@ -614,16 +658,6 @@
           return;
         }
 
-        // TODO(yoshiki): Here we should fire the update event of changed
-        // items. Currently we have a method this.fileList_.updateIndex() to
-        // fire an event, but this method takes only 1 argument and invokes sort
-        // one by one. It is obviously time wasting. Instead, we call sort
-        // directory.
-        // In future, we should implement a good method like updateIndexes and
-        // use it here.
-        var status = this.fileList_.sortStatus;
-        this.fileList_.sort(status.field, status.direction);
-
         cr.dispatchSimpleEvent(this, 'scan-updated');
         callback();
       }.bind(this));
diff --git a/chrome/browser/resources/file_manager/foreground/js/file_manager.js b/chrome/browser/resources/file_manager/foreground/js/file_manager.js
index 6928430..a4ddac1 100644
--- a/chrome/browser/resources/file_manager/foreground/js/file_manager.js
+++ b/chrome/browser/resources/file_manager/foreground/js/file_manager.js
@@ -464,6 +464,10 @@
         event.preventDefault();
       };
 
+      var minimizeButton = this.dialogDom_.querySelector('#minimize-button');
+      minimizeButton.addEventListener('click', this.onMinimize.bind(this));
+      minimizeButton.addEventListener('mousedown', preventFocus);
+
       var maximizeButton = this.dialogDom_.querySelector('#maximize-button');
       maximizeButton.addEventListener('click', this.onMaximize.bind(this));
       maximizeButton.addEventListener('mousedown', preventFocus);
@@ -487,6 +491,10 @@
     }
   };
 
+  FileManager.prototype.onMinimize = function() {
+    chrome.app.window.current().minimize();
+  };
+
   FileManager.prototype.onMaximize = function() {
     var appWindow = chrome.app.window.current();
     if (appWindow.isMaximized())
@@ -1574,7 +1582,9 @@
       // Handle restoring after crash, or the gallery action.
       // TODO(mtomasz): Use the gallery action instead of just the gallery
       //     field.
-      if (this.params_.gallery || this.params_.action === 'gallery') {
+      if (this.params_.gallery ||
+          this.params_.action === 'gallery' ||
+          this.params_.action === 'gallery-video') {
         if (!opt_selectionEntry) {
           // Non-existent file or a directory.
           // Reloading while the Gallery is open with empty or multiple
@@ -2161,8 +2171,16 @@
 
   /**
    * Called when a dialog is shown or hidden.
-   * @param {boolean} flag True if a dialog is shown, false if hidden.   */
+   * @param {boolean} flag True if a dialog is shown, false if hidden.
+   */
   FileManager.prototype.onDialogShownOrHidden = function(show) {
+    if (show) {
+      // If a dialog is shown, activate the window.
+      var appWindow = chrome.app.window.current();
+      if (appWindow)
+        appWindow.focus();
+    }
+
     // Set/unset a flag to disable dragging on the title area.
     this.dialogContainer_.classList.toggle('disable-header-drag', show);
   };
@@ -2446,13 +2464,13 @@
       event.stopPropagation();
     }
 
-    switch (util.getKeyModifiers(event) + event.keyCode) {
-      case '27':  // Escape
+    switch (util.getKeyModifiers(event) + event.keyIdentifier) {
+      case 'U+001B':  // Escape
         this.cancelRename_();
         event.preventDefault();
         break;
 
-      case '13':  // Enter
+      case 'Enter':
         this.commitRename_();
         event.preventDefault();
         break;
diff --git a/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js b/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js
index 78202e1..1fe0266 100644
--- a/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js
+++ b/chrome/browser/resources/file_manager/foreground/js/file_manager_commands.js
@@ -101,13 +101,17 @@
 };
 
 /**
- * Checks if command should be visible on drive.
+ * Sets the command as visible only when the current volume is drive and it's
+ * running as a normal app, not as a modal dialog.
  * @param {Event} event Command event to mark.
  * @param {FileManager} fileManager FileManager to use.
  */
-CommandUtil.canExecuteVisibleOnDriveOnly = function(event, fileManager) {
-  event.canExecute = fileManager.isOnDrive();
-  event.command.setHidden(!fileManager.isOnDrive());
+CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly =
+    function(event, fileManager) {
+  var enabled = fileManager.isOnDrive() &&
+      !DialogType.isModal(fileManager.dialogType);
+  event.canExecute = enabled;
+  event.command.setHidden(!enabled);
 };
 
 /**
@@ -513,8 +517,7 @@
     var hideHelp = DialogType.isModal(fileManager.dialogType);
     event.canExecute = !hideHelp;
     event.command.setHidden(hideHelp);
-    fileManager.document_.getElementById('help-separator').hidden =
-        hideHelp && !fileManager.isOnDrive();
+    fileManager.document_.getElementById('help-separator').hidden = hideHelp;
   },
 };
 
@@ -526,7 +529,7 @@
   execute: function(event, fileManager) {
     util.visitURL(str('GOOGLE_DRIVE_BUY_STORAGE_URL'));
   },
-  canExecute: CommandUtil.canExecuteVisibleOnDriveOnly
+  canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
 };
 
 /**
@@ -537,7 +540,7 @@
   execute: function(event, fileManager) {
     util.visitURL(str('GOOGLE_DRIVE_ROOT_URL'));
   },
-  canExecute: CommandUtil.canExecuteVisibleOnDriveOnly
+  canExecute: CommandUtil.canExecuteVisibleOnDriveInNormalAppModeOnly
 };
 
 /**
diff --git a/chrome/browser/resources/file_manager/foreground/js/file_tasks.js b/chrome/browser/resources/file_manager/foreground/js/file_tasks.js
index ad8f6dd..8dd1473 100644
--- a/chrome/browser/resources/file_manager/foreground/js/file_tasks.js
+++ b/chrome/browser/resources/file_manager/foreground/js/file_tasks.js
@@ -46,6 +46,14 @@
 FileTasks.WEB_STORE_HANDLER_BASE_URL =
     'https://chrome.google.com/webstore/category/collection/file_handlers';
 
+
+/**
+ * The app ID of the video player app.
+ * @const
+ * @type {string}
+ */
+FileTasks.VIDEO_PLAYER_ID = 'jcgeabjmjgoblfofpppfkcoakmfobdko';
+
 /**
  * Returns URL of the Chrome Web Store which show apps supporting the given
  * file-extension and mime-type.
@@ -188,9 +196,9 @@
   return (appId === chrome.runtime.id &&
           taskType === 'file' &&
           (actionId === 'play' ||
-           actionId === 'watch' ||
            actionId === 'mount-archive' ||
-           actionId === 'gallery'));
+           actionId === 'gallery' ||
+           actionId === 'gallery-video'));
 };
 
 /**
@@ -232,12 +240,10 @@
       } else if (taskParts[2] === 'mount-archive') {
         task.iconType = 'archive';
         task.title = loadTimeData.getString('MOUNT_ARCHIVE');
-      } else if (taskParts[2] === 'gallery') {
+      } else if (taskParts[2] === 'gallery' ||
+                 taskParts[2] === 'gallery-video') {
         task.iconType = 'image';
         task.title = loadTimeData.getString('ACTION_OPEN');
-      } else if (taskParts[2] === 'watch') {
-        task.iconType = 'video';
-        task.title = loadTimeData.getString('ACTION_WATCH');
       } else if (taskParts[2] === 'open-hosted-generic') {
         if (this.entries_.length > 1)
           task.iconType = 'generic';
@@ -551,23 +557,12 @@
     return;
   }
 
-  if (id === 'watch') {
-    console.assert(entries.length === 1, 'Cannot open multiple videos');
-    // TODO(mtomasz): Pass an entry instead.
-    chrome.fileBrowserPrivate.getProfiles(function(profiles,
-                                                   currentId,
-                                                   displayedId) {
-      fm.backgroundPage.launchVideoPlayer(entries[0].toURL(), displayedId);
-    });
-    return;
-  }
-
   if (id === 'mount-archive') {
     this.mountArchivesInternal_(entries);
     return;
   }
 
-  if (id === 'gallery') {
+  if (id === 'gallery' || id === 'gallery-video') {
     this.openGalleryInternal_(entries);
     return;
   }
@@ -680,14 +675,6 @@
     document.title = savedTitle;
   };
 
-  var onClose = function() {
-    fm.onClose();
-  };
-
-  var onMaximize = function() {
-    fm.onMaximize();
-  };
-
   var onAppRegionChanged = function(visible) {
     fm.onFilePopupAppRegionChanged(visible);
   };
@@ -726,8 +713,9 @@
       pageState: this.params_,
       appWindow: chrome.app.window.current(),
       onBack: onBack,
-      onClose: onClose,
-      onMaximize: onMaximize,
+      onClose: fm.onClose.bind(fm),
+      onMaximize: fm.onMaximize.bind(fm),
+      onMinimize: fm.onMinimize.bind(fm),
       onAppRegionChanged: onAppRegionChanged,
       loadTimeData: fm.backgroundPage.background.stringData
     };
diff --git a/chrome/browser/resources/file_manager/foreground/js/media/media_controls.js b/chrome/browser/resources/file_manager/foreground/js/media/media_controls.js
index 174796c..f8c48b8 100644
--- a/chrome/browser/resources/file_manager/foreground/js/media/media_controls.js
+++ b/chrome/browser/resources/file_manager/foreground/js/media/media_controls.js
@@ -490,8 +490,10 @@
   if (!this.media_.duration)
     return;
 
-  window.appState.time = this.media_.currentTime;
-  util.saveAppState();
+  if (window.appState) {
+    window.appState.time = this.media_.currentTime;
+    util.saveAppState();
+  }
   return;
 };
 
@@ -500,11 +502,11 @@
  * @return {boolean} True if decode succeeded.
  */
 MediaControls.prototype.decodeState = function() {
-  if (!('time' in window.appState))
+  if (!window.appState || !('time' in window.appState))
     return false;
   // There is no page reload for apps v2, only app restart.
   // Always restart in paused state.
-  this.media_.currentTime = appState.time;
+  this.media_.currentTime = window.appState.time;
   this.pause();
   return true;
 };
@@ -513,6 +515,9 @@
  * Remove current state from the page URL or the app state.
  */
 MediaControls.prototype.clearState = function() {
+  if (!window.appState)
+    return;
+
   if ('time' in window.appState)
     delete window.appState.time;
   util.saveAppState();
diff --git a/chrome/browser/resources/file_manager/foreground/js/media/video_player.js b/chrome/browser/resources/file_manager/foreground/js/media/video_player.js
deleted file mode 100644
index a026bf7..0000000
--- a/chrome/browser/resources/file_manager/foreground/js/media/video_player.js
+++ /dev/null
@@ -1,289 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-/**
- * Display error message.
- * @param {string} message Message id.
- */
-function showErrorMessage(message) {
-  var errorBanner = document.querySelector('#error');
-  errorBanner.textContent =
-      loadTimeData.getString(message);
-  errorBanner.setAttribute('visible', 'true');
-
-  // The window is hidden if the video has not loaded yet.
-  chrome.app.window.current().show();
-}
-
-/**
- * Handles playback (decoder) errors.
- */
-function onPlaybackError() {
-  showErrorMessage('GALLERY_VIDEO_DECODING_ERROR');
-  decodeErrorOccured = true;
-
-  // Disable inactivity watcher, and disable the ui, by hiding tools manually.
-  controls.inactivityWatcher.disabled = true;
-  document.querySelector('#video-player').setAttribute('disabled', 'true');
-
-  // Detach the video element, since it may be unreliable and reset stored
-  // current playback time.
-  controls.cleanup();
-  controls.clearState();
-
-  // Avoid reusing a video element.
-  video.parentNode.removeChild(video);
-  video = null;
-}
-
-/**
- * @param {Element} playerContainer Main container.
- * @param {Element} videoContainer Container for the video element.
- * @param {Element} controlsContainer Container for video controls.
- * @constructor
- */
-function FullWindowVideoControls(
-    playerContainer, videoContainer, controlsContainer) {
-  VideoControls.call(this,
-      controlsContainer,
-      onPlaybackError,
-      loadTimeData.getString.bind(loadTimeData),
-      this.toggleFullScreen_.bind(this),
-      videoContainer);
-
-  this.playerContainer_ = playerContainer;
-
-  this.updateStyle();
-  window.addEventListener('resize', this.updateStyle.bind(this));
-
-  document.addEventListener('keydown', function(e) {
-    if (e.keyIdentifier == 'U+0020') {  // Space
-      this.togglePlayStateWithFeedback();
-      e.preventDefault();
-    }
-    if (e.keyIdentifier == 'U+001B') {  // Escape
-      util.toggleFullScreen(
-          chrome.app.window.current(),
-          false);  // Leave the full screen mode.
-      e.preventDefault();
-    }
-  }.bind(this));
-
-  // TODO(mtomasz): Simplify. crbug.com/254318.
-  videoContainer.addEventListener('click', function(e) {
-    if (e.ctrlKey) {
-      this.toggleLoopedModeWithFeedback(true);
-      if (!this.isPlaying())
-        this.togglePlayStateWithFeedback();
-    } else {
-      this.togglePlayStateWithFeedback();
-    }
-  }.bind(this));
-
-  this.inactivityWatcher_ = new MouseInactivityWatcher(playerContainer);
-  this.__defineGetter__('inactivityWatcher', function() {
-    return this.inactivityWatcher_;
-  });
-
-  this.inactivityWatcher_.check();
-}
-
-FullWindowVideoControls.prototype = { __proto__: VideoControls.prototype };
-
-/**
- * Save the current state so that it survives page/app reload.
- */
-FullWindowVideoControls.prototype.onPlayStateChanged = function() {
-  this.encodeState();
-};
-
-/**
- * Restore the state after the video is loaded.
- */
-FullWindowVideoControls.prototype.restorePlayState = function() {
-  if (!this.decodeState()) {
-    VideoControls.prototype.restorePlayState.apply(this, arguments);
-    this.play();
-  }
-};
-
-/**
- * Toggles the full screen mode.
- * @private
- */
-FullWindowVideoControls.prototype.toggleFullScreen_ = function() {
-  var appWindow = chrome.app.window.current();
-  util.toggleFullScreen(appWindow, !util.isFullScreen(appWindow));
-};
-
-// TODO(mtomasz): Convert it to class members: crbug.com/171191.
-var decodeErrorOccured;
-var video;
-var controls;
-var metadataCache;
-var volumeManager;
-var selectedEntry;
-
-/**
- * Initialize the video player window.
- */
-function loadVideoPlayer() {
-  document.ondragstart = function(e) { e.preventDefault() };
-
-  chrome.fileBrowserPrivate.getStrings(function(strings) {
-    loadTimeData.data = strings;
-
-    controls = new FullWindowVideoControls(
-        document.querySelector('#video-player'),
-        document.querySelector('#video-container'),
-        document.querySelector('#controls'));
-
-    volumeManager = new VolumeManagerWrapper(
-        VolumeManagerWrapper.DriveEnabledStatus.DRIVE_ENABLED);
-    volumeManager.addEventListener('externally-unmounted',
-                                   onExternallyUnmounted);
-    metadataCache = MetadataCache.createFull(volumeManager);
-
-    // If the video player is starting before the first instance of the File
-    // Manager then it does not have access to filesystem URLs.
-    // Request it now.
-    volumeManager.ensureInitialized(reload);
-    var reloadVideo = function(e) {
-      if (decodeErrorOccured &&
-          // Ignore shortcut keys
-          !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
-        reload();
-        e.preventDefault();
-      }
-    };
-
-    document.addEventListener('keydown', reloadVideo, true);
-    document.addEventListener('click', reloadVideo, true);
-  });
-}
-
-/**
- * Closes video player when a volume containing the played item is unmounted.
- * @param {Event} event The unmount event.
- */
-function onExternallyUnmounted(event) {
-  if (!selectedEntry)
-    return;
-
-  if (volumeManager.getVolumeInfo(selectedEntry) === event.volumeInfo)
-    window.close();
-}
-
-/**
- * Unload the player.
- */
-function unload() {
-  if (volumeManager)
-    volumeManager.dispose();
-
-  if (!controls.getMedia())
-    return;
-
-  controls.savePosition(true /* exiting */);
-  controls.cleanup();
-}
-
-/**
- * Reload the player.
- */
-function reload() {
-  // Re-enable ui and hide error message if already displayed.
-  document.querySelector('#video-player').removeAttribute('disabled');
-  document.querySelector('#error').removeAttribute('visible');
-  controls.inactivityWatcher.disabled = false;
-  decodeErrorOccured = false;
-
-  var url;
-  if (window.appState) {
-    util.saveAppState();
-    url = window.appState.url;
-  } else {
-    url = document.location.search.substr(1);
-  }
-
-  document.title = decodeURIComponent(url.split('/').pop());
-  var queue = new AsyncUtil.Queue();
-
-  queue.run(function(callback) {
-    webkitResolveLocalFileSystemURL(url,
-      function(entry) {
-        selectedEntry = entry;
-        callback();
-      }, function() {
-        console.warn('Failed to resolve entry for: ' + url);
-        callback();
-      });
-  });
-
-
-  queue.run(function(callback) {
-    if (!selectedEntry) {
-      showErrorMessage('GALLERY_VIDEO_ERROR');
-      return;
-    }
-    metadataCache.get(selectedEntry, 'streaming', function(streaming) {
-      if (streaming && !navigator.onLine) {
-        showErrorMessage('GALLERY_VIDEO_OFFLINE');
-        return;
-      }
-
-      // Detach the previous video element, if exists.
-      if (video)
-        video.parentNode.removeChild(video);
-
-      video = document.createElement('video');
-      document.querySelector('#video-container').appendChild(video);
-      controls.attachMedia(video);
-
-      video.src = selectedEntry.toURL();
-      video.load();
-      video.addEventListener('loadedmetadata', function() {
-        // TODO: chrome.app.window soon will be able to resize the content area.
-        // Until then use approximate title bar height.
-        var TITLE_HEIGHT = 33;
-
-        var aspect = video.videoWidth / video.videoHeight;
-        var newWidth = video.videoWidth;
-        var newHeight = video.videoHeight + TITLE_HEIGHT;
-
-        var shrinkX = newWidth / window.screen.availWidth;
-        var shrinkY = newHeight / window.screen.availHeight;
-        if (shrinkX > 1 || shrinkY > 1) {
-          if (shrinkY > shrinkX) {
-            newHeight = newHeight / shrinkY;
-            newWidth = (newHeight - TITLE_HEIGHT) * aspect;
-          } else {
-            newWidth = newWidth / shrinkX;
-            newHeight = newWidth / aspect + TITLE_HEIGHT;
-          }
-        }
-
-        var oldLeft = window.screenX;
-        var oldTop = window.screenY;
-        var oldWidth = window.outerWidth;
-        var oldHeight = window.outerHeight;
-
-        if (!oldWidth && !oldHeight) {
-          oldLeft = window.screen.availWidth / 2;
-          oldTop = window.screen.availHeight / 2;
-        }
-
-        var appWindow = chrome.app.window.current();
-        appWindow.resizeTo(newWidth, newHeight);
-        appWindow.moveTo(oldLeft - (newWidth - oldWidth) / 2,
-                         oldTop - (newHeight - oldHeight) / 2);
-        appWindow.show();
-      });
-    });
-  });
-}
-
-util.addPageLoadHandler(loadVideoPlayer);
diff --git a/chrome/browser/resources/file_manager/foreground/js/media/video_player_scripts.js b/chrome/browser/resources/file_manager/foreground/js/media/video_player_scripts.js
deleted file mode 100644
index 54ea178..0000000
--- a/chrome/browser/resources/file_manager/foreground/js/media/video_player_scripts.js
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The include directives are put into Javascript-style comments to prevent
-// parsing errors in non-flattened mode. The flattener still sees them.
-// Note that this makes the flattener to comment out the first line of the
-// included file but that's all right since any javascript file should start
-// with a copyright comment anyway.
-
-//<include src="../../../../../../../ui/webui/resources/js/cr.js"/>
-//<include src="../../../../../../../ui/webui/resources/js/cr/event_target.js"/>
-//<include src="../../../../../../../ui/webui/resources/js/cr/ui/array_data_model.js"/>
-//<include src="../../../../../../../ui/webui/resources/js/load_time_data.js"/>
-
-(function() {
-// 'strict mode' is invoked for this scope.
-
-//<include src="../../../common/js/async_util.js"/>
-//<include src="../../../common/js/util.js"/>
-//<include src="../../../common/js/path_util.js"/>
-//<include src="../file_type.js"/>
-//<include src="../volume_manager_wrapper.js">
-//<include src="../metadata/metadata_cache.js"/>
-
-//<include src="media_controls.js"/>
-//<include src="util.js"/>
-//<include src="video_player.js"/>
-//<include src="player_testapi.js"/>
-
-window.reload = reload;
-window.unload = unload;
-
-})();
diff --git a/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js b/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js
index 0a20c17..28e0a55 100644
--- a/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js
+++ b/chrome/browser/resources/file_manager/foreground/js/metadata/metadata_cache.js
@@ -581,7 +581,7 @@
   if (data === null) return;
   var properties = this.cache_[entry.toURL()].properties;
   for (var type in data) {
-    if (data.hasOwnProperty(type) && !properties.hasOwnProperty(type)) {
+    if (data.hasOwnProperty(type)) {
       properties[type] = data[type];
       this.notifyObservers_(entry, type);
     }
diff --git a/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js b/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js
index 6d4dbb1..9db9cd0 100644
--- a/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js
+++ b/chrome/browser/resources/file_manager/foreground/js/photo/gallery.js
@@ -26,6 +26,7 @@
  *     {function(string)} onBack
  *     {function()} onClose
  *     {function()} onMaximize
+ *     {function()} onMinimize
  *     {function(boolean)} onAppRegionChanged
  *     {MetadataCache} metadataCache
  *     {Array.<Object>} shareActions
@@ -182,6 +183,13 @@
 
   var preventDefault = function(event) { event.preventDefault(); };
 
+  var minimizeButton = util.createChild(this.header_,
+                                        'minimize-button tool dimmable',
+                                        'button');
+  minimizeButton.tabIndex = -1;
+  minimizeButton.addEventListener('click', this.onMinimize_.bind(this));
+  minimizeButton.addEventListener('mousedown', preventDefault);
+
   var maximizeButton = util.createChild(this.header_,
                                         'maximize-button tool dimmable',
                                         'button');
@@ -379,6 +387,14 @@
 };
 
 /**
+ * Handles user's 'Maximize' action (Escape or a click on the X icon).
+ * @private
+ */
+Gallery.prototype.onMinimize_ = function() {
+  this.executeWhenReady(this.context_.onMinimize);
+};
+
+/**
  * Executes a function when the editor is done with the modifications.
  * @param {function} callback Function to execute.
  */
diff --git a/chrome/browser/resources/file_manager/foreground/js/photo/gallery_item.js b/chrome/browser/resources/file_manager/foreground/js/photo/gallery_item.js
index 2ae80c9..5672143 100644
--- a/chrome/browser/resources/file_manager/foreground/js/photo/gallery_item.js
+++ b/chrome/browser/resources/file_manager/foreground/js/photo/gallery_item.js
@@ -198,10 +198,10 @@
  * @param {function()} onExists Called if the file with the new name exists.
  */
 Gallery.Item.prototype.rename = function(displayName, onSuccess, onExists) {
-  var fileName = this.entry_.name.replace(
+  var newFileName = this.entry_.name.replace(
       ImageUtil.getDisplayNameFromName(this.entry_.name), displayName);
 
-  if (name === this.entry_.name)
+  if (newFileName === this.entry_.name)
     return;
 
   var onRenamed = function(entry) {
@@ -210,16 +210,17 @@
   }.bind(this);
 
   var onError = function() {
-    console.error('Rename error: "' + oldName + '" to "' + newName + '"');
+    console.error(
+        'Rename error: "' + this.entry_.name + '" to "' + newFileName + '"');
   };
 
   var moveIfDoesNotExist = function(parentDir) {
     parentDir.getFile(
-        fileName,
+        newFileName,
         {create: false, exclusive: false},
         onExists,
         function() {
-          this.entry_.moveTo(parentDir, fileName, onRenamed, onError);
+          this.entry_.moveTo(parentDir, newFileName, onRenamed, onError);
         }.bind(this));
   }.bind(this);
 
diff --git a/chrome/browser/resources/file_manager/main.html b/chrome/browser/resources/file_manager/main.html
index cfe03fa..2602859 100644
--- a/chrome/browser/resources/file_manager/main.html
+++ b/chrome/browser/resources/file_manager/main.html
@@ -316,6 +316,9 @@
                     i18n-values="aria-label:GEAR_BUTTON_TOOLTIP"
                     aria-activedescendant="gear-menu">
             </button>
+            <button class="minimize-button" id="minimize-button"
+                    visibleif="full-page" tabindex="-1">
+            </button>
             <button class="maximize-button" id="maximize-button"
                     visibleif="full-page" tabindex="-1">
             </button>
diff --git a/chrome/browser/resources/file_manager/manifest.json b/chrome/browser/resources/file_manager/manifest.json
index 0ef6c24..2cce790 100644
--- a/chrome/browser/resources/file_manager/manifest.json
+++ b/chrome/browser/resources/file_manager/manifest.json
@@ -57,27 +57,6 @@
       ]
     },
     {
-      "id": "watch",
-      "default_title": "__MSG_PLAY_MEDIA__",
-      "default_icon": "common/images/file_types/200/video.png",
-      "file_filters": [
-        "filesystem:*.3gp",
-        "filesystem:*.avi",
-        "filesystem:*.m4v",
-        "filesystem:*.mkv",
-        "filesystem:*.mov",
-        "filesystem:*.mp4",
-        "filesystem:*.mpeg",
-        "filesystem:*.mpeg4",
-        "filesystem:*.mpg",
-        "filesystem:*.mpg4",
-        "filesystem:*.ogm",
-        "filesystem:*.ogv",
-        "filesystem:*.ogx",
-        "filesystem:*.webm"
-      ]
-    },
-    {
       "id": "mount-archive",
       "default_title": "__MSG_MOUNT_ARCHIVE__",
       "default_icon": "common/images/file_types/200/archive.png",
@@ -127,7 +106,14 @@
         "filesystem:*.jpg",
         "filesystem:*.jpeg",
         "filesystem:*.png",
-        "filesystem:*.webp",
+        "filesystem:*.webp"
+      ]
+    },
+    {
+      "id": "gallery-video",
+      "default_title": "__MSG_OPEN_ACTION__",
+      "default_icon": "common/images/file_types/200/image.png",
+      "file_filters": [
         // Video formats
         "filesystem:*.3gp",
         "filesystem:*.avi",
diff --git a/chrome/browser/resources/file_manager/video_player.html b/chrome/browser/resources/file_manager/video_player.html
deleted file mode 100644
index cb1ac0a..0000000
--- a/chrome/browser/resources/file_manager/video_player.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!--
-  -- Copyright (c) 2012 The Chromium Authors. All rights reserved.
-  -- Use of this source code is governed by a BSD-style license that can be
-  -- found in the LICENSE file.
-  -->
-<html>
-<head>
-  <!-- We have to set some default title, or chrome will use the page name.
-    -- As soon as the i18n'd strings are loaded we replace it with the correct
-    -- string. Until then, use an invisible non-whitespace character.
-    -->
-  <title>&#xFEFF;</title>
-  <link rel="icon" type="image/png" href="chrome://theme/IDR_FILE_MANAGER_IMG_FILETYPE_VIDEO">
-  <link rel="stylesheet" type="text/css" href="foreground/css/media_controls.css">
-  <link rel="stylesheet" type="text/css" href="foreground/css/video_player.css">
-
-  <!-- Don't load video_player_scripts.js when flattening is disabled -->
-  <if expr="False"><!-- </if>
-    <script src="foreground/js/media/video_player_scripts.js"></script>
-  <if expr="False"> --></if>
-
-  <if expr="False">
-    <!-- This section is used when the file manager is loaded with
-         'filemgr-ext-path' command-line flag. -->
-    <!-- Keep the list in sync with video_player_scripts.js. -->
-    <script src="chrome://resources/js/cr.js"></script>
-    <script src="chrome://resources/js/cr/event_target.js"></script>
-    <script src="chrome://resources/js/cr/ui/array_data_model.js"></script>
-    <script src="chrome://resources/js/load_time_data.js"></script>
-
-    <script src="common/js/async_util.js"></script>
-    <script src="common/js/util.js"></script>
-    <script src="common/js/path_util.js"></script>
-
-    <script src="foreground/js/file_type.js"></script>
-    <script src="foreground/js/volume_manager_wrapper.js"></script>
-    <script src="foreground/js/metadata/metadata_cache.js"></script>
-
-    <script src="foreground/js/media/media_controls.js"></script>
-    <script src="foreground/js/media/util.js"></script>
-    <script src="foreground/js/media/video_player.js"></script>
-    <script src="foreground/js/media/player_testapi.js"></script>
-  </if>
-</head>
-<body>
-  <div id="video-player" tools>
-    <div id="video-container">
-    </div>
-    <div id="controls-wrapper">
-      <div id="controls" class="tool"></div>
-    </div>
-    <div id="error-wrapper">
-      <div id="error"></div>
-    </div>
-  </div>
-</body>
-</html>
diff --git a/chrome/browser/resources/google_now/background.js b/chrome/browser/resources/google_now/background.js
index acc2aca..de13096 100644
--- a/chrome/browser/resources/google_now/background.js
+++ b/chrome/browser/resources/google_now/background.js
@@ -52,6 +52,19 @@
 var MAXIMUM_POLLING_PERIOD_SECONDS = 60 * 60;  // 1 hour
 
 /**
+ * Initial period for polling for Google Now optin notification after push
+ * messaging indicates Google Now is enabled.
+ */
+var INITIAL_OPTIN_POLLING_PERIOD_SECONDS = 60;  // 1 minute
+
+/**
+ * Maximum period for polling for Google Now optin notification after push
+ * messaging indicates Google Now is enabled. It is expected that the alarm
+ * will be stopped after this.
+ */
+var MAXIMUM_OPTIN_POLLING_PERIOD_SECONDS = 16 * 60;  // 16 minutes
+
+/**
  * Initial period for retrying the server request for dismissing cards.
  */
 var INITIAL_RETRY_DISMISS_PERIOD_SECONDS = 60;  // 1 minute
@@ -202,6 +215,11 @@
     requestCards,
     INITIAL_POLLING_PERIOD_SECONDS,
     MAXIMUM_POLLING_PERIOD_SECONDS);
+var optInCheckAttempts = buildAttemptManager(
+    'optin',
+    pollOptedIn,
+    INITIAL_OPTIN_POLLING_PERIOD_SECONDS,
+    MAXIMUM_OPTIN_POLLING_PERIOD_SECONDS);
 var dismissalAttempts = buildAttemptManager(
     'dismiss',
     retryPendingDismissals,
@@ -227,7 +245,10 @@
   DELETED_SHOW_WELCOME_TOAST: 8,
   STOPPED: 9,
   DELETED_USER_SUPPRESSED: 10,
-  EVENTS_TOTAL: 11  // EVENTS_TOTAL is not an event; all new events need to be
+  SIGNED_OUT: 11,
+  NOTIFICATION_DISABLED: 12,
+  GOOGLE_NOW_DISABLED: 13,
+  EVENTS_TOTAL: 14  // EVENTS_TOTAL is not an event; all new events need to be
                     // added before it.
 };
 
@@ -248,6 +269,29 @@
 }
 
 /**
+ * Records a notification clicked event.
+ * @param {number|undefined} cardTypeId Card type ID.
+ */
+function recordNotificationClick(cardTypeId) {
+  if (cardTypeId !== undefined) {
+    chrome.metricsPrivate.recordSparseValue(
+        'GoogleNow.Card.Clicked', cardTypeId);
+  }
+}
+
+/**
+ * Records a button clicked event.
+ * @param {number|undefined} cardTypeId Card type ID.
+ * @param {number} buttonIndex Button Index
+ */
+function recordButtonClick(cardTypeId, buttonIndex) {
+  if (cardTypeId !== undefined) {
+    chrome.metricsPrivate.recordSparseValue(
+        'GoogleNow.Card.Button.Clicked' + buttonIndex, cardTypeId);
+  }
+}
+
+/**
  * Checks the result of the HTTP Request and updates the authentication
  * manager on any failure.
  * @param {string} token Authentication token to validate against an
@@ -800,9 +844,9 @@
  * Opens URL corresponding to the clicked part of the notification.
  * @param {ChromeNotificationId} chromeNotificationId chrome.notifications ID of
  *     the card.
- * @param {function((ActionUrls|undefined)): (string|undefined)} selector
- *     Function that extracts the url for the clicked area from the button
- *     action URLs info.
+ * @param {function(NotificationDataEntry): (string|undefined)} selector
+ *     Function that extracts the url for the clicked area from the
+ *     notification data entry.
  */
 function onNotificationClicked(chromeNotificationId, selector) {
   fillFromChromeLocalStorage({
@@ -810,11 +854,11 @@
     notificationsData: {}
   }).then(function(items) {
     /** @type {(NotificationDataEntry|undefined)} */
-    var notificationData = items.notificationsData[chromeNotificationId];
-    if (!notificationData)
+    var notificationDataEntry = items.notificationsData[chromeNotificationId];
+    if (!notificationDataEntry)
       return;
 
-    var url = selector(notificationData.actionUrls);
+    var url = selector(notificationDataEntry);
     if (!url)
       return;
 
@@ -953,6 +997,24 @@
 }
 
 /**
+ * Record why this extension would not poll for cards.
+ * @param {boolean} signedIn true if the user is signed in.
+ * @param {boolean} notificationEnabled true if
+ *     Google Now for Chrome is allowed to show notifications.
+ * @param {boolean} googleNowEnabled true if
+ *     the Google Now is enabled for the user.
+ */
+function recordEventIfNoCards(signedIn, notificationEnabled, googleNowEnabled) {
+  if (!signedIn) {
+    recordEvent(GoogleNowEvent.SIGNED_OUT);
+  } else if (!notificationEnabled) {
+    recordEvent(GoogleNowEvent.NOTIFICATION_DISABLED);
+  } else if (!googleNowEnabled) {
+    recordEvent(GoogleNowEvent.GOOGLE_NOW_DISABLED);
+  }
+}
+
+/**
  * Does the actual work of deciding what Google Now should do
  * based off of the current state of Chrome.
  * @param {boolean} signedIn true if the user is signed in.
@@ -986,6 +1048,8 @@
     recordEvent(GoogleNowEvent.STOPPED);
   }
 
+  recordEventIfNoCards(signedIn, notificationEnabled, googleNowEnabled);
+
   console.log(
       'Requested Actions shouldSetBackground=' + shouldSetBackground + ' ' +
       'setShouldPollCards=' + shouldPollCards);
@@ -1050,6 +1114,48 @@
       });
 }
 
+/**
+ * Polls the optin state.
+ * Sometimes we get the response to the opted in result too soon during
+ * push messaging. We'll recheck the optin state a few times before giving up.
+ */
+function pollOptedIn() {
+  /**
+   * Cleans up any state used to recheck the opt-in poll.
+   */
+  function clearPollingState() {
+    localStorage.removeItem('optedInCheckCount');
+    optInCheckAttempts.stop();
+  }
+
+  /**
+   * Performs the actual work for checking the opt-in state and requesting cards
+   * on opted-in.
+   */
+  function checkOptedIn() {
+    // Limit retries to 5.
+    if (localStorage.optedInCheckCount < 5) {
+      console.log(new Date() +
+          ' checkOptedIn Attempt ' + localStorage.optedInCheckCount);
+      localStorage.optedInCheckCount++;
+      requestOptedIn(function() {
+        clearPollingState();
+        requestCards();
+      });
+    } else {
+      clearPollingState();
+    }
+  }
+
+  if (localStorage.optedInCheckCount === undefined) {
+    localStorage.optedInCheckCount = 0;
+    optInCheckAttempts.start();
+    checkOptedIn();
+  } else {
+    optInCheckAttempts.planForNext(checkOptedIn);
+  }
+}
+
 instrumented.runtime.onInstalled.addListener(function(details) {
   console.log('onInstalled ' + JSON.stringify(details));
   if (details.reason != 'chrome_update') {
@@ -1087,21 +1193,33 @@
 instrumented.notifications.onClicked.addListener(
     function(chromeNotificationId) {
       chrome.metricsPrivate.recordUserAction('GoogleNow.MessageClicked');
-      onNotificationClicked(chromeNotificationId, function(actionUrls) {
-        return actionUrls && actionUrls.messageUrl;
-      });
-    });
+      onNotificationClicked(chromeNotificationId,
+          function(notificationDataEntry) {
+            var actionUrls = notificationDataEntry.actionUrls;
+            var url = actionUrls && actionUrls.messageUrl;
+            if (url) {
+              recordNotificationClick(notificationDataEntry.cardTypeId);
+            }
+            return url;
+          });
+        });
 
 instrumented.notifications.onButtonClicked.addListener(
     function(chromeNotificationId, buttonIndex) {
       chrome.metricsPrivate.recordUserAction(
           'GoogleNow.ButtonClicked' + buttonIndex);
-      onNotificationClicked(chromeNotificationId, function(actionUrls) {
-        var url = actionUrls.buttonUrls[buttonIndex];
-        verify(url !== undefined, 'onButtonClicked: no url for a button');
-        return url;
-      });
-    });
+      onNotificationClicked(chromeNotificationId,
+          function(notificationDataEntry) {
+            var actionUrls = notificationDataEntry.actionUrls;
+            var url = actionUrls.buttonUrls[buttonIndex];
+            if (url) {
+              recordButtonClick(notificationDataEntry.cardTypeId, buttonIndex);
+            } else {
+              verify(false, 'onButtonClicked: no url for a button');
+            }
+            return url;
+          });
+        });
 
 instrumented.notifications.onClosed.addListener(onNotificationClosed);
 
@@ -1144,7 +1262,7 @@
             notificationGroups: items.notificationGroups
           });
 
-          requestCards();
+          pollOptedIn();
         }
       });
     });
diff --git a/chrome/browser/resources/google_now/background_unittest.gtestjs b/chrome/browser/resources/google_now/background_unittest.gtestjs
index 14d8e58..7cd66f5 100644
--- a/chrome/browser/resources/google_now/background_unittest.gtestjs
+++ b/chrome/browser/resources/google_now/background_unittest.gtestjs
@@ -279,6 +279,9 @@
       this.mockGlobals.expects(once()).recordEvent(
           GoogleNowEvent.STOPPED);
 
+      this.mockGlobals.expects(once()).recordEvent(
+          GoogleNowEvent.SIGNED_OUT);
+
       expectInitialization(this.mockApis);
 
       expectStateMachineCalls(
@@ -323,6 +326,104 @@
 });
 
 /**
+ * No Cards Event Recording Tests
+ */
+TEST_F('GoogleNowBackgroundUnitTest', 'NoCardsSignedOut', function() {
+  var signedIn = false;
+  var notificationEnabled = false;
+  var googleNowEnabled = false;
+  this.makeAndRegisterMockGlobals([
+      'recordEvent',
+      'setBackgroundEnable',
+      'setShouldPollCards']);
+
+  this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
+  this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
+
+  this.mockGlobals.expects(once()).recordEvent(
+      GoogleNowEvent.STOPPED);
+  this.mockGlobals.expects(once()).recordEvent(
+      GoogleNowEvent.SIGNED_OUT);
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.NOTIFICATION_DISABLED);
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.GOOGLE_NOW_DISABLED);
+  updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
+});
+
+TEST_F(
+    'GoogleNowBackgroundUnitTest',
+    'NoCardsNotificationsDisabled',
+    function() {
+      var signedIn = true;
+      var notificationEnabled = false;
+      var googleNowEnabled = false;
+      this.makeAndRegisterMockGlobals([
+          'recordEvent',
+          'setBackgroundEnable',
+          'setShouldPollCards']);
+
+      this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
+      this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
+
+      this.mockGlobals.expects(once()).recordEvent(
+          GoogleNowEvent.STOPPED);
+      this.mockGlobals.expects(never()).recordEvent(
+          GoogleNowEvent.SIGNED_OUT);
+      this.mockGlobals.expects(once()).recordEvent(
+          GoogleNowEvent.NOTIFICATION_DISABLED);
+      this.mockGlobals.expects(never()).recordEvent(
+          GoogleNowEvent.GOOGLE_NOW_DISABLED);
+      updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
+    });
+
+TEST_F('GoogleNowBackgroundUnitTest', 'NoCardsGoogleNowDisabled', function() {
+  var signedIn = true;
+  var notificationEnabled = true;
+  var googleNowEnabled = false;
+  this.makeAndRegisterMockGlobals([
+      'recordEvent',
+      'setBackgroundEnable',
+      'setShouldPollCards']);
+
+  this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
+  this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
+
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.STOPPED);
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.SIGNED_OUT);
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.NOTIFICATION_DISABLED);
+  this.mockGlobals.expects(once()).recordEvent(
+      GoogleNowEvent.GOOGLE_NOW_DISABLED);
+  updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
+});
+
+TEST_F('GoogleNowBackgroundUnitTest', 'NoCardsEverythingEnabled', function() {
+  var signedIn = true;
+  var notificationEnabled = true;
+  var googleNowEnabled = true;
+  this.makeAndRegisterMockGlobals([
+      'recordEvent',
+      'setBackgroundEnable',
+      'setShouldPollCards']);
+
+  this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
+  this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
+
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.STOPPED);
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.SIGNED_OUT);
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.NOTIFICATION_DISABLED);
+  this.mockGlobals.expects(never()).recordEvent(
+      GoogleNowEvent.GOOGLE_NOW_DISABLED);
+  updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
+});
+
+/**
  * Mocks global functions and APIs that onNotificationClicked() depends upon.
  * @param {Test} fixture Test fixture.
  */
@@ -379,8 +480,10 @@
       expectChromeLocalStorageGet(
           this, testNotificationDataRequest, testNotificationData);
 
-      this.mockLocalFunctions.expects(once()).selector(undefined).will(
-          returnValue(undefined));
+      this.mockLocalFunctions.expects(once())
+          .selector(eqJSON(
+              testNotificationData.notificationsData[testNotificationId]))
+          .will(returnValue(undefined));
 
       // Invoking the tested function.
       onNotificationClicked(
@@ -408,8 +511,10 @@
 
       expectChromeLocalStorageGet(
           this, testNotificationDataRequest, testNotificationData);
-      this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
-          returnValue(testActionUrl));
+      this.mockLocalFunctions.expects(once())
+          .selector(eqJSON(
+              testNotificationData.notificationsData[testNotificationId]))
+          .will(returnValue(testActionUrl));
       var chromeTabsCreateSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
           instrumented_tabs_create(
@@ -448,8 +553,10 @@
 
       expectChromeLocalStorageGet(
           this, testNotificationDataRequest, testNotificationData);
-      this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
-          returnValue(testActionUrl));
+      this.mockLocalFunctions.expects(once())
+          .selector(eqJSON(
+              testNotificationData.notificationsData[testNotificationId]))
+          .will(returnValue(testActionUrl));
       var chromeTabsCreateSavedArgs = new SaveMockArguments();
       this.mockApis.expects(once()).
           instrumented_tabs_create(
diff --git a/chrome/browser/resources/google_now/cards.js b/chrome/browser/resources/google_now/cards.js
index 81b89bf..00c9b5d 100644
--- a/chrome/browser/resources/google_now/cards.js
+++ b/chrome/browser/resources/google_now/cards.js
@@ -60,7 +60,8 @@
  *   actionUrls: (ActionUrls|undefined),
  *   dismissal: Object,
  *   locationBased: (boolean|undefined),
- *   groupName: string
+ *   groupName: string,
+ *   cardTypeId: (number|undefined)
  * }}
  */
 var ReceivedNotification;
@@ -91,12 +92,13 @@
  *
  * @typedef {{
  *   actionUrls: (ActionUrls|undefined),
+ *   cardTypeId: (number|undefined),
  *   timestamp: number,
  *   combinedCard: CombinedCard
  * }}
  *
  */
- var NotificationDataEntry;
+var NotificationDataEntry;
 
 /**
  * Names for tasks that can be created by the this file.
@@ -246,9 +248,11 @@
           winningCard.receivedNotification.actionUrls &&
           JSON.parse(JSON.stringify(
               winningCard.receivedNotification.actionUrls));
-
+      var winningCardTypeId = winningCard &&
+          winningCard.receivedNotification.cardTypeId;
       return {
         actionUrls: winningActionUrls,
+        cardTypeId: winningCardTypeId,
         timestamp: now,
         combinedCard: combinedCard
       };
diff --git a/chrome/browser/resources/google_now/utility.js b/chrome/browser/resources/google_now/utility.js
index d91bd68..c67a370 100644
--- a/chrome/browser/resources/google_now/utility.js
+++ b/chrome/browser/resources/google_now/utility.js
@@ -648,9 +648,22 @@
     defaultStorageObject,
     opt_allowPromiseRejection) {
   return new Promise(function(resolve, reject) {
-    instrumented.storage.local.get(defaultStorageObject, function(items) {
+    // We have to create a keys array because keys with a default value
+    // of undefined will cause that key to not be looked up!
+    var keysToGet = [];
+    for (var key in defaultStorageObject) {
+      keysToGet.push(key);
+    }
+    instrumented.storage.local.get(keysToGet, function(items) {
       if (items) {
-        resolve(items);
+        // Merge the result with the default storage object to ensure all keys
+        // requested have either the default value or the retrieved storage
+        // value.
+        var result = {};
+        for (var key in defaultStorageObject) {
+          result[key] = (key in items) ? items[key] : defaultStorageObject[key];
+        }
+        resolve(result);
       } else if (opt_allowPromiseRejection === PromiseRejection.ALLOW) {
         reject();
       } else {
diff --git a/chrome/browser/resources/hangout_services/OWNERS b/chrome/browser/resources/hangout_services/OWNERS
index 42702c2..22c4e82 100644
--- a/chrome/browser/resources/hangout_services/OWNERS
+++ b/chrome/browser/resources/hangout_services/OWNERS
@@ -1,3 +1,2 @@
 bemasc@chromium.org
-joi@chromium.org
 vrk@chrmium.org
diff --git a/chrome/browser/resources/history/history.js b/chrome/browser/resources/history/history.js
index 587e6c7..2e83107 100644
--- a/chrome/browser/resources/history/history.js
+++ b/chrome/browser/resources/history/history.js
@@ -237,8 +237,13 @@
     dropDown.addEventListener('mousedown', setActiveVisit);
     dropDown.addEventListener('focus', setActiveVisit);
 
-    // Prevent clicks on the drop down from affecting the checkbox.
-    dropDown.addEventListener('click', function(e) { e.preventDefault(); });
+    // Prevent clicks on the drop down from affecting the checkbox.  We need to
+    // call blur() explicitly because preventDefault() cancels any focus
+    // handling.
+    dropDown.addEventListener('click', function(e) {
+      e.preventDefault();
+      document.activeElement.blur();
+    });
     entryBox.appendChild(dropDown);
   }
 
diff --git a/chrome/browser/resources/hotword_helper/manager.js b/chrome/browser/resources/hotword_helper/manager.js
index ba0ee5c..07428fc 100644
--- a/chrome/browser/resources/hotword_helper/manager.js
+++ b/chrome/browser/resources/hotword_helper/manager.js
@@ -49,7 +49,11 @@
   // User has explicitly clicked 'no'.
   CLICKED_NO_OPTIN: 'hcno',
   // User has opted in.
-  CLICKED_OPTIN: 'hco'
+  CLICKED_OPTIN: 'hco',
+  // Audio logging is opted in.
+  AUDIO_LOGGING_ON: 'alon',
+  // Audio logging is opted out.
+  AUDIO_LOGGING_OFF: 'aloff',
 };
 
 
@@ -157,6 +161,25 @@
         chrome.hotwordPrivate.setEnabled(false);
       }
     }
+    // Information regarding the audio logging preference was sent.
+    if (request.type === OptInManager.CommandFromPage.AUDIO_LOGGING_ON) {
+      if (chrome.hotwordPrivate &&
+          chrome.hotwordPrivate.setAudioLoggingEnabled) {
+        chrome.hotwordPrivate.setAudioLoggingEnabled(true);
+        chrome.runtime.sendMessage(
+            OptInManager.HOTWORD_EXTENSION_ID_,
+            {'cmd': OptInManager.CommandFromHelper.AUDIO_LOGGING_ON});
+      }
+    }
+    if (request.type === OptInManager.CommandFromPage.AUDIO_LOGGING_OFF) {
+      if (chrome.hotwordPrivate &&
+          chrome.hotwordPrivate.setAudioLoggingEnabled) {
+        chrome.hotwordPrivate.setAudioLoggingEnabled(false);
+        chrome.runtime.sendMessage(
+            OptInManager.HOTWORD_EXTENSION_ID_,
+            {'cmd': OptInManager.CommandFromHelper.AUDIO_LOGGING_OFF});
+      }
+    }
   }
 };
 
diff --git a/chrome/browser/resources/hotword_helper/optin_client.js b/chrome/browser/resources/hotword_helper/optin_client.js
index a688df7..8ac22de 100644
--- a/chrome/browser/resources/hotword_helper/optin_client.js
+++ b/chrome/browser/resources/hotword_helper/optin_client.js
@@ -35,7 +35,11 @@
   // User has explicitly clicked 'no'.
   CLICKED_NO_OPTIN: 'hcno',
   // User has opted in.
-  CLICKED_OPTIN: 'hco'
+  CLICKED_OPTIN: 'hco',
+  // Audio logging is opted in.
+  AUDIO_LOGGING_ON: 'alon',
+  // Audio logging is opted out.
+  AUDIO_LOGGING_OFF: 'aloff',
 };
 
 
@@ -49,23 +53,15 @@
 
 /**
  * Handles the messages posted to the window, mainly listening for
- * the optin and no optin clicks.
+ * the optin and no optin clicks. Also listening for preference on
+ * audio logging.
  * @param {!MessageEvent} messageEvent Message event from the window.
  * @private
  */
 OptInClient.prototype.handleCommandFromPage_ = function(messageEvent) {
   if (messageEvent.source === window && messageEvent.data.type) {
     var command = messageEvent.data.type;
-    switch (command) {
-      case OptInClient.CommandFromPage.CLICKED_OPTIN:
-        chrome.runtime.sendMessage(
-            {'type': command});
-        break;
-      case OptInClient.CommandFromPage.CLICKED_NO_OPTIN:
-        chrome.runtime.sendMessage(
-            {'type': command});
-        break;
-    }
+    chrome.runtime.sendMessage({'type': command});
   }
 };
 
diff --git a/chrome/browser/resources/local_discovery/local_discovery.html b/chrome/browser/resources/local_discovery/local_discovery.html
index 358f366..1d5b763 100644
--- a/chrome/browser/resources/local_discovery/local_discovery.html
+++ b/chrome/browser/resources/local_discovery/local_discovery.html
@@ -98,7 +98,7 @@
 
       <div class="devices" id="register-device-list"></div>
 
-      <if expr="not chromeos and not is_macosx">
+      <if expr="not chromeos">
         <section id="cloud-print-connector-section">
           <h2 i18n-content="titleConnector"></h2>
           <div>
diff --git a/chrome/browser/resources/local_discovery/local_discovery.js b/chrome/browser/resources/local_discovery/local_discovery.js
index fccb04f..ab37a66 100644
--- a/chrome/browser/resources/local_discovery/local_discovery.js
+++ b/chrome/browser/resources/local_discovery/local_discovery.js
@@ -532,7 +532,7 @@
    * @private
    */
   function setupCloudPrintConnectorSection(disabled, label, allowed) {
-    if (!cr.isChromeOS && !cr.isMac) {
+    if (!cr.isChromeOS) {
       $('cloudPrintConnectorLabel').textContent = label;
       if (disabled || !allowed) {
         $('cloudPrintConnectorSetupButton').textContent =
@@ -561,7 +561,7 @@
   }
 
   function removeCloudPrintConnectorSection() {
-    if (!cr.isChromeOS && !cr.isMac) {
+    if (!cr.isChromeOS) {
        var connectorSectionElm = $('cloud-print-connector-section');
        if (connectorSectionElm)
           connectorSectionElm.parentNode.removeChild(connectorSectionElm);
diff --git a/chrome/browser/resources/login/display_manager.js b/chrome/browser/resources/login/display_manager.js
index 82ab279..836dc00 100644
--- a/chrome/browser/resources/login/display_manager.js
+++ b/chrome/browser/resources/login/display_manager.js
@@ -36,6 +36,8 @@
 /** @const */ var ACCELERATOR_DEVICE_REQUISITION_REMORA =
     'device_requisition_remora';
 /** @const */ var ACCELERATOR_APP_LAUNCH_BAILOUT = 'app_launch_bailout';
+/** @const */ var ACCELERATOR_APP_LAUNCH_NETWORK_CONFIG =
+    'app_launch_network_config';
 
 /* Signin UI state constants. Used to control header bar UI. */
 /** @const */ var SIGNIN_UI_STATE = {
@@ -255,6 +257,10 @@
         var currentStepId = this.screens_[this.currentStep_];
         if (currentStepId == SCREEN_APP_LAUNCH_SPLASH)
           chrome.send('cancelAppLaunch');
+      } else if (name == ACCELERATOR_APP_LAUNCH_NETWORK_CONFIG) {
+        var currentStepId = this.screens_[this.currentStep_];
+        if (currentStepId == SCREEN_APP_LAUNCH_SPLASH)
+          chrome.send('networkConfigRequest');
       }
 
       if (!this.forceKeyboardFlow_)
@@ -364,6 +370,20 @@
       if (newStep.onAfterShow)
         newStep.onAfterShow(screenData);
 
+      // Workaround for gaia and network screens.
+      // Due to other origin iframe and long ChromeVox focusing correspondingly
+      // passive aria-label title is not pronounced.
+      // Gaia hack can be removed on fixed crbug.com/316726.
+      if (nextStepId == SCREEN_GAIA_SIGNIN) {
+        newStep.setAttribute(
+            'aria-label',
+            loadTimeData.getString('signinScreenTitle'));
+      } else if (nextStepId == SCREEN_OOBE_NETWORK) {
+        newStep.setAttribute(
+            'aria-label',
+            loadTimeData.getString('networkScreenAccessibleTitle'));
+      }
+
       // Default control to be focused (if specified).
       var defaultControl = newStep.defaultControl;
 
diff --git a/chrome/browser/resources/login/screen.js b/chrome/browser/resources/login/screen.js
index dcab52a..fa03371 100644
--- a/chrome/browser/resources/login/screen.js
+++ b/chrome/browser/resources/login/screen.js
@@ -27,7 +27,7 @@
     /**
      * Called for currently active screen when screen size changed.
      */
-    onWindowResize: doNothing
+    onWindowResize: doNothing,
   };
 
   return {
diff --git a/chrome/browser/resources/login/user_pod_row.js b/chrome/browser/resources/login/user_pod_row.js
index 5246a7e..fa4db8f 100644
--- a/chrome/browser/resources/login/user_pod_row.js
+++ b/chrome/browser/resources/login/user_pod_row.js
@@ -2161,8 +2161,14 @@
           break;
         case 'Enter':
           if (this.focusedPod_) {
-            this.setActivatedPod(this.focusedPod_, e);
-            e.stopPropagation();
+            var targetTag = e.target.tagName;
+            if (e.target == this.focusedPod_.passwordElement ||
+                (targetTag != 'INPUT' &&
+                 targetTag != 'BUTTON' &&
+                 targetTag != 'A')) {
+              this.setActivatedPod(this.focusedPod_, e);
+              e.stopPropagation();
+            }
           }
           break;
         case 'U+001B':  // Esc
diff --git a/chrome/browser/resources/media/webrtc_logs.js b/chrome/browser/resources/media/webrtc_logs.js
index 508af7d..cb3d50d 100644
--- a/chrome/browser/resources/media/webrtc_logs.js
+++ b/chrome/browser/resources/media/webrtc_logs.js
@@ -27,49 +27,77 @@
     var upload = uploads[i];
 
     var logBlock = document.createElement('div');
+
     var title = document.createElement('h3');
-    title.textContent = loadTimeData.getStringF('webrtcLogHeaderFormat',
-                                                upload['id']);
+    title.textContent =
+        loadTimeData.getStringF('webrtcLogHeaderFormat',
+                                upload['capture_time'].length != 0 ?
+                                    upload['capture_time'] :
+                                    upload['upload_time']);
     logBlock.appendChild(title);
-    var date = document.createElement('p');
-    date.textContent = loadTimeData.getStringF('webrtcLogTimeFormat',
-                                               upload['time']);
-    logBlock.appendChild(date);
-    var linkBlock = document.createElement('p');
-    var link = document.createElement('a');
-    var commentLines = [
-      'Chrome Version: ' + version,
-      // TODO(tbreisacher): fill in the OS automatically?
-      'Operating System: e.g., "Windows 7", "Mac OSX 10.6"',
-      '',
-      'URL (if applicable) where the problem occurred:',
-      '',
-      'Can you reproduce this problem?',
-      '',
-      'What steps will reproduce this problem? (or if it\'s not ' +
-      'reproducible, what were you doing just before the problem)?',
-      '',
-      '1.', '2.', '3.',
-      '',
-      '*Please note that issues filed with no information filled in ' +
-      'above will be marked as WontFix*',
-      '',
-      '****DO NOT CHANGE BELOW THIS LINE****',
-      'report_id:' + upload.id
-    ];
-    var params = {
-      template: 'Defect report from user',
-      comment: commentLines.join('\n'),
-    };
-    var href = 'http://code.google.com/p/chromium/issues/entry';
-    for (var param in params) {
-      href = appendParam(href, param, params[param]);
+
+    var localFileLine = document.createElement('p');
+    if (upload['local_file'].length == 0) {
+      localFileLine.textContent =
+          loadTimeData.getString('noLocalLogFileMessage');
+    } else {
+      localFileLine.textContent =
+          loadTimeData.getString('webrtcLogLocalFileLabelFormat') + ' ';
+      var localFileLink = document.createElement('a');
+      localFileLink.href = 'file://' + upload['local_file'];
+      localFileLink.textContent =
+          loadTimeData.getStringF('webrtcLogLocalFileFormat',
+                                  upload['local_file']);
+      localFileLine.appendChild(localFileLink);
     }
-    link.href = href;
-    link.target = '_blank';
-    link.textContent = loadTimeData.getString('bugLinkText');
-    linkBlock.appendChild(link);
-    logBlock.appendChild(linkBlock);
+    logBlock.appendChild(localFileLine);
+
+    var uploadLine = document.createElement('p');
+    if (upload['id'].length == 0) {
+      uploadLine.textContent =
+          loadTimeData.getString('webrtcLogNotUploadedMessage');
+    } else {
+      uploadLine.textContent =
+          loadTimeData.getStringF('webrtcLogUploadTimeFormat',
+                                  upload['upload_time']) + '. ' +
+          loadTimeData.getStringF('webrtcLogReportIdFormat',
+                                  upload['id']) + '. ';
+      var link = document.createElement('a');
+      var commentLines = [
+          'Chrome Version: ' + version,
+          // TODO(tbreisacher): fill in the OS automatically?
+          'Operating System: e.g., "Windows 7", "Mac OSX 10.6"',
+          '',
+          'URL (if applicable) where the problem occurred:',
+          '',
+          'Can you reproduce this problem?',
+          '',
+          'What steps will reproduce this problem? (or if it\'s not ' +
+          'reproducible, what were you doing just before the problem)?',
+          '',
+          '1.', '2.', '3.',
+          '',
+          '*Please note that issues filed with no information filled in ' +
+          'above will be marked as WontFix*',
+          '',
+          '****DO NOT CHANGE BELOW THIS LINE****',
+          'report_id:' + upload.id
+      ];
+      var params = {
+        template: 'Defect report from user',
+        comment: commentLines.join('\n'),
+      };
+      var href = 'http://code.google.com/p/chromium/issues/entry';
+      for (var param in params) {
+        href = appendParam(href, param, params[param]);
+      }
+      link.href = href;
+      link.target = '_blank';
+      link.textContent = loadTimeData.getString('bugLinkText');
+      uploadLine.appendChild(link);
+    }
+    logBlock.appendChild(uploadLine);
+
     logSection.appendChild(logBlock);
   }
 
diff --git a/chrome/browser/resources/memory_internals/memory_internals.js b/chrome/browser/resources/memory_internals/memory_internals.js
index 5bb10c7..5a1d310 100644
--- a/chrome/browser/resources/memory_internals/memory_internals.js
+++ b/chrome/browser/resources/memory_internals/memory_internals.js
@@ -30,8 +30,8 @@
 
       $('os-value').textContent = browser['os'] + ' (' +
           browser['os_version'] + ')';
-      $('uptime-value').textContent = Math.floor(browser['uptime'] / 1000) +
-          ' sec';
+      $('uptime-value').textContent =
+          secondsToHMS(Math.floor(browser['uptime'] / 1000));
 
       this.updateSnapshot(browser['processes']);
       this.updateExtensions(browser['extensions']);
@@ -136,7 +136,7 @@
       var history = tab['history'][l];
       var title = (history['title'] == '') ? history['url'] : history['title'];
       var url = '<a href="' + history['url'] + '">' + HTMLEscape(title) +
-          '</a> (' + history['time'] + ' sec. ago)';
+          '</a> (' + secondsToHMS(history['time']) + ' ago)';
       if (l == tab['index']) {
         url = '<strong>' + url + '</strong>';
       }
@@ -145,6 +145,22 @@
     return line;
   };
 
+  /**
+   * Produces a readable string int the format '<HH> hours <MM> min. <SS> sec.'
+   * representing the amount of time provided as the number of seconds.
+   * @param {number} totalSeconds The total amount of seconds.
+   * @return {string} The formatted HH hours/hours MM min. SS sec. string
+   */
+  function secondsToHMS(totalSeconds) {
+    totalSeconds = Number(totalSeconds);
+    var hour = Math.floor(totalSeconds / 3600);
+    var min = Math.floor(totalSeconds % 3600 / 60);
+    var sec = Math.floor(totalSeconds % 60);
+    return (hour > 0 ? (hour + (hour > 1 ? ' hours ' : ' hour ')) : '') +
+           (min > 0 ? (min + ' min. ') : '') +
+           (sec + ' sec. ');
+  }
+
   return MainView;
 })();
 
diff --git a/chrome/browser/resources/net_internals/modules_view.js b/chrome/browser/resources/net_internals/modules_view.js
index 68d0dc3..0bf7b52 100644
--- a/chrome/browser/resources/net_internals/modules_view.js
+++ b/chrome/browser/resources/net_internals/modules_view.js
@@ -52,8 +52,9 @@
 
     onLoadLogFinish: function(data) {
       // Show the tab if there are either service providers or extension info.
-      return this.onExtensionInfoChanged(data.extensionInfo) ||
-          this.onServiceProvidersChanged(data.serviceProviders);
+      var hasExtensionInfo = this.onExtensionInfoChanged(data.extensionInfo);
+      var hasSpiInfo = this.onServiceProvidersChanged(data.serviceProviders);
+      return hasExtensionInfo || hasSpiInfo;
     },
 
     onExtensionInfoChanged: function(extensionInfo) {
diff --git a/chrome/browser/resources/options/browser_options.html b/chrome/browser/resources/options/browser_options.html
index 01c9713..b3043fb 100644
--- a/chrome/browser/resources/options/browser_options.html
+++ b/chrome/browser/resources/options/browser_options.html
@@ -382,7 +382,7 @@
               <label for="hotword-search-enable"
                   i18n-values=".innerHTML:hotwordSearchEnable">
               </label>
-              <span id="hotword-search-setting-indicator"
+              <span id="controlled-setting-indicator"
                   pref="hotword.search_enabled" dialog-pref>
               </span>
             </span>
diff --git a/chrome/browser/resources/options/browser_options.js b/chrome/browser/resources/options/browser_options.js
index 58b9753..c7c3b79 100644
--- a/chrome/browser/resources/options/browser_options.js
+++ b/chrome/browser/resources/options/browser_options.js
@@ -171,9 +171,6 @@
       };
 
       chrome.send('requestHotwordAvailable');
-      var hotwordIndicator = $('hotword-search-setting-indicator');
-      HotwordSearchSettingIndicator.decorate(hotwordIndicator);
-      hotwordIndicator.disabledOnErrorSection = $('hotword-search-enable');
 
       if ($('set-wallpaper')) {
         $('set-wallpaper').onclick = function(event) {
@@ -532,6 +529,7 @@
       if (cr.isChromeOS) {
         $('factory-reset-restart').onclick = function(event) {
           OptionsPage.navigateToPage('factoryResetData');
+          chrome.send('onPowerwashDialogShow');
         };
       }
 
@@ -858,7 +856,8 @@
       // Disable the "sign in" button if we're currently signing in, or if we're
       // already signed in and signout is not allowed.
       var signInButton = $('start-stop-sync');
-      signInButton.disabled = syncData.setupInProgress;
+      signInButton.disabled = syncData.setupInProgress ||
+                              !syncData.signoutAllowed;
       this.signoutAllowed_ = syncData.signoutAllowed;
       if (!syncData.signoutAllowed)
         $('start-stop-sync-indicator').setAttribute('controlled-by', 'policy');
@@ -915,6 +914,7 @@
         $('sync-general').insertBefore($('sync-status').nextSibling,
                                        $('enable-auto-login-checkbox'));
       }
+      $('enable-auto-login-checkbox').hidden = !syncData.autoLoginVisible;
     },
 
     /**
@@ -973,7 +973,6 @@
      */
     showHotwordSection_: function(opt_error) {
       $('hotword-search').hidden = false;
-      $('hotword-search-setting-indicator').errorText = opt_error;
     },
 
     /**
diff --git a/chrome/browser/resources/options/certificate_manager.js b/chrome/browser/resources/options/certificate_manager.js
index 943abdc..b2d46e9 100644
--- a/chrome/browser/resources/options/certificate_manager.js
+++ b/chrome/browser/resources/options/certificate_manager.js
@@ -11,8 +11,9 @@
   /**
    * blah
    * @param {!string} id The id of this tab.
+   * @param {boolean} isKiosk True if dialog is shown during CrOS kiosk launch.
    */
-  function CertificateManagerTab(id) {
+  function CertificateManagerTab(id, isKiosk) {
     this.tree = $(id + '-tree');
 
     options.CertificatesTree.decorate(this.tree);
@@ -44,24 +45,36 @@
 
     this.backupButton = $(id + '-backup');
     if (this.backupButton !== null) {
-      this.backupButton.onclick = function(e) {
-        var selected = tree.selectedItem;
-        chrome.send('exportPersonalCertificate', [selected.data.id]);
+      if (id == 'personalCertsTab' && isKiosk) {
+        this.backupButton.hidden = true;
+      } else {
+        this.backupButton.onclick = function(e) {
+          var selected = tree.selectedItem;
+          chrome.send('exportPersonalCertificate', [selected.data.id]);
+        }
       }
     }
 
     this.backupAllButton = $(id + '-backup-all');
     if (this.backupAllButton !== null) {
-      this.backupAllButton.onclick = function(e) {
-        chrome.send('exportAllPersonalCertificates');
+      if (id == 'personalCertsTab' && isKiosk) {
+        this.backupAllButton.hidden = true;
+      } else {
+        this.backupAllButton.onclick = function(e) {
+          chrome.send('exportAllPersonalCertificates');
+        }
       }
     }
 
     this.importButton = $(id + '-import');
     if (this.importButton !== null) {
       if (id == 'personalCertsTab') {
-        this.importButton.onclick = function(e) {
-          chrome.send('importPersonalCertificate', [false]);
+        if (isKiosk) {
+          this.importButton.hidden = true;
+        } else {
+          this.importButton.onclick = function(e) {
+            chrome.send('importPersonalCertificate', [false]);
+          }
         }
       } else if (id == 'serverCertsTab') {
         this.importButton.onclick = function(e) {
@@ -85,9 +98,13 @@
 
     this.exportButton = $(id + '-export');
     if (this.exportButton !== null) {
-      this.exportButton.onclick = function(e) {
-        var selected = tree.selectedItem;
-        chrome.send('exportCertificate', [selected.data.id]);
+      if (id == 'personalCertsTab' && isKiosk) {
+        this.exportButton.hidden = true;
+      } else {
+        this.exportButton.onclick = function(e) {
+          var selected = tree.selectedItem;
+          chrome.send('exportCertificate', [selected.data.id]);
+        }
       }
     }
 
@@ -164,13 +181,14 @@
   CertificateManager.prototype = {
     __proto__: OptionsPage.prototype,
 
-    initializePage: function() {
+    initializePage: function(isKiosk) {
       OptionsPage.prototype.initializePage.call(this);
 
-      this.personalTab = new CertificateManagerTab('personalCertsTab');
-      this.serverTab = new CertificateManagerTab('serverCertsTab');
-      this.caTab = new CertificateManagerTab('caCertsTab');
-      this.otherTab = new CertificateManagerTab('otherCertsTab');
+      this.personalTab = new CertificateManagerTab('personalCertsTab',
+                                                   !!isKiosk);
+      this.serverTab = new CertificateManagerTab('serverCertsTab', !!isKiosk);
+      this.caTab = new CertificateManagerTab('caCertsTab', !!isKiosk);
+      this.otherTab = new CertificateManagerTab('otherCertsTab', !!isKiosk);
 
       this.addEventListener('visibleChange', this.handleVisibleChange_);
 
diff --git a/chrome/browser/resources/options/chromeos/bluetooth.css b/chrome/browser/resources/options/chromeos/bluetooth.css
index 68c0e81..da6b5b0 100644
--- a/chrome/browser/resources/options/chromeos/bluetooth.css
+++ b/chrome/browser/resources/options/chromeos/bluetooth.css
@@ -23,12 +23,14 @@
   -webkit-box-pack: justify;
 }
 
-#bluetooth-options .button-strip #bluetooth-scanning-label {
+#bluetooth-options .button-strip #bluetooth-scanning-label,
+#bluetooth-options .button-strip #bluetooth-scan-stopped-label {
   -webkit-box-flex: 1;
   display: block;
 }
 
-#bluetooth-scanning-label {
+#bluetooth-scanning-label,
+#bluetooth-scan-stopped-label {
   -webkit-margin-start: 5px;
   color: #999;
 }
diff --git a/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.html b/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.html
index 534d963..dcb87ab 100644
--- a/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.html
+++ b/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.html
@@ -18,6 +18,9 @@
     <span id="bluetooth-scanning-label"
         i18n-content="bluetoothScanning">
     </span>
+    <span id="bluetooth-scan-stopped-label"
+        i18n-content="bluetoothScanStopped">
+    </span>
     <div id="bluetooth-scanning-icon" class="inline-spinner"></div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js b/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js
index 4bc7f6c..004cc6b 100644
--- a/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js
+++ b/chrome/browser/resources/options/chromeos/bluetooth_add_device_overlay.js
@@ -33,6 +33,8 @@
       OptionsPage.prototype.initializePage.call(this);
       this.createDeviceList_();
 
+      BluetoothOptions.updateDiscoveryState(true);
+
       $('bluetooth-add-device-cancel-button').onclick = function(event) {
         OptionsPage.closeOverlay();
       };
@@ -85,11 +87,30 @@
    * Automatically start the device discovery process if the
    * "Add device" dialog is visible.
    */
-  BluetoothOptions.updateDiscovery = function() {
+  BluetoothOptions.startDeviceDiscovery = function() {
     var page = BluetoothOptions.getInstance();
     if (page && page.visible)
       chrome.send('findBluetoothDevices');
-  }
+  };
+
+  /**
+   * Updates the dialog to show that device discovery has stopped. Updates the
+   * label text and hides/unhides the spinner. based on discovery state.
+   */
+  BluetoothOptions.updateDiscoveryState = function(discovering) {
+    $('bluetooth-scanning-label').hidden = !discovering;
+    $('bluetooth-scanning-icon').hidden = !discovering;
+    $('bluetooth-scan-stopped-label').hidden = discovering;
+  };
+
+  /**
+   * If the "Add device" dialog is visible, dismiss it.
+   */
+  BluetoothOptions.dismissOverlay = function() {
+    var page = BluetoothOptions.getInstance();
+    if (page && page.visible)
+      OptionsPage.closeOverlay();
+  };
 
   // Export
   return {
diff --git a/chrome/browser/resources/options/chromeos/change_picture_options.js b/chrome/browser/resources/options/chromeos/change_picture_options.js
index 60930ec..93982ea 100644
--- a/chrome/browser/resources/options/chromeos/change_picture_options.js
+++ b/chrome/browser/resources/options/chromeos/change_picture_options.js
@@ -130,6 +130,7 @@
         imageGrid.removeItem(this.oldImage_);
         this.oldImage_ = null;
       }
+      chrome.send('onChangePicturePageHidden');
     },
 
     /**
@@ -159,8 +160,7 @@
       imageGrid.flipPhoto = !imageGrid.flipPhoto;
       var flipMessageId = imageGrid.flipPhoto ?
          'photoFlippedAccessibleText' : 'photoFlippedBackAccessibleText';
-      this.announceAccessibleMessage_(
-          loadTimeData.getString(flipMessageId));
+      announceAccessibleMessage(loadTimeData.getString(flipMessageId));
     },
 
     /**
@@ -178,6 +178,8 @@
      */
     handlePhotoTaken_: function(e) {
       chrome.send('photoTaken', [e.dataURL]);
+      announceAccessibleMessage(
+          loadTimeData.getString('photoCaptureAccessibleText'));
     },
 
     /**
@@ -187,6 +189,8 @@
     handleDiscardPhoto_: function() {
       $('user-image-grid').discardPhoto();
       chrome.send('discardPhoto');
+      announceAccessibleMessage(
+          loadTimeData.getString('photoDiscardAccessibleText'));
     },
 
     /**
@@ -257,24 +261,6 @@
     },
 
     /**
-     * Add an accessible message to the page that will be announced to
-     * users who have spoken feedback on, but will be invisible to all
-     * other users. It's removed right away so it doesn't clutter the DOM.
-     */
-    announceAccessibleMessage_: function(msg) {
-      var element = document.createElement('div');
-      element.setAttribute('aria-live', 'polite');
-      element.style.position = 'relative';
-      element.style.left = '-9999px';
-      element.style.height = '0px';
-      element.innerText = msg;
-      document.body.appendChild(element);
-      window.setTimeout(function() {
-        document.body.removeChild(element);
-      }, 0);
-    },
-
-    /**
      * Adds or updates old user image taken from file/camera (neither a profile
      * image nor a default one).
      * @param {string} imageUrl Old user image, as data or internal URL.
diff --git a/chrome/browser/resources/options/chromeos/display_options.html b/chrome/browser/resources/options/chromeos/display_options.html
index 989e7ed..87d23de 100644
--- a/chrome/browser/resources/options/chromeos/display_options.html
+++ b/chrome/browser/resources/options/chromeos/display_options.html
@@ -46,6 +46,15 @@
               i18n-content="startCalibratingOverscan">
           </button>
         </div>
+        <div class="selected-display-option-row"
+            id="selected-display-color-profile-row">
+          <div class="selected-display-option-title"
+              i18n-content="selectedDisplayColorProfile">
+          </div>
+          <select id="display-options-color-profile-selection"
+              class="display-options-button">
+          </select>
+        </div>
       </div>
     </div>
     <!-- The arrow of display-configuration is achieved by a div
diff --git a/chrome/browser/resources/options/chromeos/display_options.js b/chrome/browser/resources/options/chromeos/display_options.js
index 3b000ca..da972e8 100644
--- a/chrome/browser/resources/options/chromeos/display_options.js
+++ b/chrome/browser/resources/options/chromeos/display_options.js
@@ -178,6 +178,10 @@
         chrome.send('setOrientation', [this.displays_[this.focusedIndex_].id,
                                        ev.target.value]);
       }.bind(this);
+      $('display-options-color-profile-selection').onchange = function(ev) {
+        chrome.send('setColorProfile', [this.displays_[this.focusedIndex_].id,
+                                        ev.target.value]);
+      }.bind(this);
       $('selected-display-start-calibrating-overscan').onclick = function() {
         // Passes the target display ID. Do not specify it through URL hash,
         // we do not care back/forward.
@@ -628,6 +632,23 @@
         }
         resolution.disabled = (display.resolutions.length <= 1);
       }
+
+      if (display.availableColorProfiles.length <= 1) {
+        $('selected-display-color-profile-row').hidden = true;
+      } else {
+        $('selected-display-color-profile-row').hidden = false;
+        var profiles = $('display-options-color-profile-selection');
+        profiles.innerHTML = '';
+        for (var i = 0; i < display.availableColorProfiles.length; i++) {
+          var option = document.createElement('option');
+          var colorProfile = display.availableColorProfiles[i];
+          option.value = colorProfile.profileId;
+          option.textContent = colorProfile.name;
+          option.selected = (
+              display.colorProfile == colorProfile.profileId);
+          profiles.appendChild(option);
+        }
+      }
     },
 
     /**
diff --git a/chrome/browser/resources/options/chromeos/internet_detail.js b/chrome/browser/resources/options/chromeos/internet_detail.js
index cbc07f2..7c9488b 100644
--- a/chrome/browser/resources/options/chromeos/internet_detail.js
+++ b/chrome/browser/resources/options/chromeos/internet_detail.js
@@ -810,6 +810,9 @@
           data.type == Constants.TYPE_WIMAX ||
           data.type == Constants.TYPE_VPN)) {
       $('details-internet-configure').hidden = false;
+    } else if (data.type == Constants.TYPE_ETHERNET) {
+      // Ethernet (802.1x) can be configured while connected.
+      $('details-internet-configure').hidden = false;
     } else {
       $('details-internet-configure').hidden = true;
     }
diff --git a/chrome/browser/resources/options/confirm_dialog.js b/chrome/browser/resources/options/confirm_dialog.js
index acf34e6..b7d235e 100644
--- a/chrome/browser/resources/options/confirm_dialog.js
+++ b/chrome/browser/resources/options/confirm_dialog.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 cr.define('options', function() {
-  /** @const */ var OptionsPage = options.OptionsPage;
+  /** @const */ var SettingsDialog = options.SettingsDialog;
 
   /**
    * A dialog that will pop up when the user attempts to set the value of the
@@ -22,13 +22,11 @@
    *     confirmed the dialog before. This ensures that the user is presented
    *     with the dialog only once. If left |undefined| or |null|, the dialog
    *     will pop up every time the user attempts to set |pref| to |true|.
-   * @extends {OptionsPage}
+   * @extends {SettingsDialog}
    */
   function ConfirmDialog(name, title, pageDivName, okButton, cancelButton, pref,
                          metric, confirmed_pref) {
-    OptionsPage.call(this, name, title, pageDivName);
-    this.okButton = okButton;
-    this.cancelButton = cancelButton;
+    SettingsDialog.call(this, name, title, pageDivName, okButton, cancelButton);
     this.pref = pref;
     this.metric = metric;
     this.confirmed_pref = confirmed_pref;
@@ -37,7 +35,7 @@
 
   ConfirmDialog.prototype = {
     // Set up the prototype chain
-    __proto__: OptionsPage.prototype,
+    __proto__: SettingsDialog.prototype,
 
     /**
      * Handle changes to |pref|. Only uncommitted changes are relevant as these
@@ -68,6 +66,8 @@
 
     /** @override */
     initializePage: function() {
+      SettingsDialog.prototype.initializePage.call(this);
+
       this.okButton.onclick = this.handleConfirm.bind(this);
       this.cancelButton.onclick = this.handleCancel.bind(this);
       Preferences.getInstance().addEventListener(
@@ -82,9 +82,10 @@
      * Handle the confirm button by committing the |pref| change. If
      * |confirmed_pref| has been specified, also remember that the dialog has
      * been confirmed to avoid bringing it up in the future.
+     * @override
      */
     handleConfirm: function() {
-      OptionsPage.closeOverlay();
+      SettingsDialog.prototype.handleConfirm.call(this);
 
       Preferences.getInstance().commitPref(this.pref, this.metric);
       if (this.confirmed_pref)
@@ -94,10 +95,10 @@
     /**
      * Handle the cancel button by rolling back the |pref| change without it
      * ever taking effect.
+     * @override
      */
     handleCancel: function() {
-      OptionsPage.closeOverlay();
-
+      SettingsDialog.prototype.handleCancel.call(this);
       Preferences.getInstance().rollbackPref(this.pref);
     },
 
diff --git a/chrome/browser/resources/options/handler_options.html b/chrome/browser/resources/options/handler_options.html
index 4f45f01..4b4e8e5 100644
--- a/chrome/browser/resources/options/handler_options.html
+++ b/chrome/browser/resources/options/handler_options.html
@@ -29,10 +29,16 @@
     </div>
   </div>
   <div class="action-area">
-    <div class="button-strip">
-      <button id="handler-options-overlay-confirm" class="default-button"
-          i18n-content="done">
-      </button>
+    <div class="hbox stretch">
+      <a target="_blank" i18n-content="learnMore"
+          i18n-values="href:handlers_learn_more_url"></a>
+    </div>
+    <div class="action-area-right">
+      <div class="button-strip">
+        <button id="handler-options-overlay-confirm" class="default-button"
+            i18n-content="done">
+        </button>
+      </div>
     </div>
   </div>
 </div>
diff --git a/chrome/browser/resources/options/hotword_confirm_overlay.css b/chrome/browser/resources/options/hotword_confirm_overlay.css
index ef7288f..9df27a8 100644
--- a/chrome/browser/resources/options/hotword_confirm_overlay.css
+++ b/chrome/browser/resources/options/hotword_confirm_overlay.css
@@ -6,3 +6,7 @@
 #hotword-confirm-overlay {
   width: 500px;
 }
+
+#feedback-bar input {
+  bottom: 6px;
+}
diff --git a/chrome/browser/resources/options/hotword_confirm_overlay.html b/chrome/browser/resources/options/hotword_confirm_overlay.html
index 8a25c12..366b85f 100644
--- a/chrome/browser/resources/options/hotword_confirm_overlay.html
+++ b/chrome/browser/resources/options/hotword_confirm_overlay.html
@@ -22,4 +22,17 @@
       </div>
     </div>
   </div>
+  <div id="feedback-bar" class="gray-bottom-bar checkbox">
+    <span class="controlled-setting-with-label">
+      <input id="hotword-audio-logging-enable"
+          pref="hotword.audio_logging_enabled"
+          metric="Options_Hotword_AudioLogging_Checkbox"
+          type="checkbox" dialog-pref checked>
+      <span>
+        <label for="hotword-audio-logging-enable"
+            i18n-content="hotwordAudioLoggingEnable">
+        </label>
+      </span>
+    </span>
+  </div>
 </div>
diff --git a/chrome/browser/resources/options/options.js b/chrome/browser/resources/options/options.js
index c8a96f0..60630a0 100644
--- a/chrome/browser/resources/options/options.js
+++ b/chrome/browser/resources/options/options.js
@@ -249,6 +249,7 @@
 
   window.setTimeout(function() {
     document.documentElement.classList.remove('loading');
+    chrome.send('onFinishedLoadingOptions');
   });
 }
 
diff --git a/chrome/browser/resources/options/pref_ui.js b/chrome/browser/resources/options/pref_ui.js
index 0775306..e8eb237 100644
--- a/chrome/browser/resources/options/pref_ui.js
+++ b/chrome/browser/resources/options/pref_ui.js
@@ -160,6 +160,9 @@
     decorate: function() {
       PrefInputElement.prototype.decorate.call(this);
       this.type = 'checkbox';
+
+      if (this.dialogPref)
+        this.updatePrefFromState_();
     },
 
     /**
diff --git a/chrome/browser/resources/options/preferences.js b/chrome/browser/resources/options/preferences.js
index 6f8cc82..ef1ed18 100644
--- a/chrome/browser/resources/options/preferences.js
+++ b/chrome/browser/resources/options/preferences.js
@@ -214,12 +214,11 @@
 
       var event = new Event(name);
       // Decorate pref value as CoreOptionsHandler::CreateValueForPref() does.
-      event.value = {
-        value: value,
-        recommendedValue: pref.orig.recommendedValue,
-        disabled: pref.orig.disabled,
-        uncommitted: true,
-      };
+      event.value = {value: value, uncommitted: true};
+      if (pref.orig) {
+        event.value.recommendedValue = pref.orig.recommendedValue;
+        event.value.disabled = pref.orig.disabled;
+      }
       this.dispatchEvent(event);
     },
 
diff --git a/chrome/browser/resources/options/sync_section.html b/chrome/browser/resources/options/sync_section.html
index 04f1a90..194d6e9 100644
--- a/chrome/browser/resources/options/sync_section.html
+++ b/chrome/browser/resources/options/sync_section.html
@@ -60,6 +60,13 @@
         i18n-content="manageAccountsButtonTitle">
     </button>
 </if>  <!-- chromeos -->
+    <div id="enable-auto-login-checkbox" class="checkbox" hidden>
+      <label>
+        <input id="enable-auto-login" pref="autologin.enabled"
+            metric="Options_Autologin" type="checkbox">
+        <span i18n-content="autologinEnabled"></span>
+      </label>
+    </div>
   </div>
 
 <if expr="not chromeos">
diff --git a/chrome/browser/resources/print_preview/data/local_parsers.js b/chrome/browser/resources/print_preview/data/local_parsers.js
index 91d5208..22cfded 100644
--- a/chrome/browser/resources/print_preview/data/local_parsers.js
+++ b/chrome/browser/resources/print_preview/data/local_parsers.js
@@ -15,13 +15,21 @@
    * @return {!print_preview.Destination} Parsed local print destination.
    */
   LocalDestinationParser.parse = function(destinationInfo) {
+    var options = {'description': destinationInfo.printerDescription};
+    if (destinationInfo.printerOptions) {
+      // Convert options into cloud print tags format.
+      options.tags = Object.keys(destinationInfo.printerOptions).map(
+          function(key) {return '__cp__' + key + '=' + this[key];},
+          destinationInfo.printerOptions);
+    }
     return new print_preview.Destination(
         destinationInfo.deviceName,
         print_preview.Destination.Type.LOCAL,
         print_preview.Destination.Origin.LOCAL,
         destinationInfo.printerName,
         false /*isRecent*/,
-        print_preview.Destination.ConnectionStatus.ONLINE);
+        print_preview.Destination.ConnectionStatus.ONLINE,
+        options);
   };
 
   /** Namespace that contains a method to parse local print capabilities. */
@@ -37,7 +45,7 @@
     var cdd = {
       version: '1.0',
       printer: {
-        collate: {default: true}
+        collate: {'default': true}
       }
     };
 
@@ -53,11 +61,11 @@
             is_default: !settingsInfo['setColorAsDefault']
           }
         ]
-      }
+      };
     }
 
     if (!settingsInfo['disableCopiesOption']) {
-      cdd.printer.copies = {default: 1};
+      cdd.printer.copies = {'default': 1};
     }
 
     if (settingsInfo['printerDefaultDuplexValue'] !=
@@ -105,7 +113,7 @@
 
     if (destinationInfo.isUnregistered) {
       returnedPrinters.push(new print_preview.Destination(
-        destinationInfo.serviceName,
+          destinationInfo.serviceName,
           print_preview.Destination.Type.GOOGLE,
           print_preview.Destination.Origin.PRIVET,
           destinationInfo.name,
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js
index 526e14f..c40ec86 100644
--- a/chrome/browser/resources/print_preview/native_layer.js
+++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -283,7 +283,7 @@
         'requestID': -1,
         'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
         'pageWidth': documentInfo.pageSize.width,
-        'pageHeight': documentInfo.pageSize.height,
+        'pageHeight': documentInfo.pageSize.height
       };
 
       if (!destination.isLocal) {
@@ -309,6 +309,7 @@
 
       if (destination.isPrivet) {
         ticket['ticket'] = printTicketStore.createPrintTicket(destination);
+        ticket['capabilities'] = JSON.stringify(destination.capabilities);
       }
 
       if (opt_isOpenPdfInPreview) {
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index a85ce2c..edf5c9f 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -884,6 +884,9 @@
       var selectedDest = this.destinationStore_.selectedDestination;
       setIsVisible($('cloud-print-dialog-link'),
                    !cr.isChromeOS && !selectedDest.isLocal);
+      if (this.isInKioskAutoPrintMode_) {
+        this.onPrintButtonClick_();
+      }
     },
 
     /**
diff --git a/chrome/browser/resources/sync_internals/about.css b/chrome/browser/resources/sync_internals/about.css
index b530cc6..29a2a62 100644
--- a/chrome/browser/resources/sync_internals/about.css
+++ b/chrome/browser/resources/sync_internals/about.css
@@ -3,33 +3,36 @@
  * found in the LICENSE file.
  */
 
-#aboutInfo {
-  -webkit-columns: 3;
+#about-info {
+  -webkit-column-width: 350px;
 }
 
-#aboutInfo h2 {
+#about-info > div {
+  -webkit-column-break-inside: avoid;
+  width: 350px;
+}
+
+#about-info h2 {
   color: rgb(74, 142, 230);
   font-size: 100%;
   margin-bottom: 0;
 }
 
-#aboutInfo .err {
+#about-info .err {
   color: red;
 }
 
-#aboutInfo .section {
-  -webkit-column-break-inside: avoid;
+#about-info .section {
   display: inline-block;
   margin-left: auto;
   margin-right: auto;
+}
+
+.about-details {
   width: 100%;
 }
 
-.aboutDetails {
-  width: 100%;
-}
-
-.aboutDetails tr:nth-child(odd) {
+.about-details tr:nth-child(odd) {
   background: rgb(239, 243, 255);
 }
 
@@ -45,37 +48,7 @@
  background: rgb(204, 255, 204);
 }
 
-@-webkit-keyframes highlight1 {
-  0% {
-    background: rgb(255, 255, 0);
-  }
-  100% {
-    background: #fff;
-  }
-}
-
-@-webkit-keyframes highlight2 {
-  0% {
-    background: rgb(155, 158, 166);
-  }
-  100% {
-    background: rgb(239, 243, 255);
-  }
-}
-
-.aboutDetails [highlighted] {
-  -webkit-animation-duration: 3s;
-  -webkit-animation-name: highlight1;
-  -webkit-animation-timing-function: linear;
-}
-
-.aboutDetails [highlighted]:nth-child(odd) {
-  -webkit-animation-duration: 3s;
-  -webkit-animation-name: highlight2;
-  -webkit-animation-timing-function: linear;
-}
-
-.aboutDetails .uninitialized {
+.about-details .uninitialized {
   color: #7f7f7f;
 }
 
@@ -85,3 +58,49 @@
   text-align: center;
   width: 300px;
 }
+
+#traffic-event-container {
+  border: 1px solid;
+  height: 500px;
+  max-width: 500px;
+  overflow-y: auto;
+}
+
+.traffic-event-entry {
+  border: 2px outset;
+  padding: 0.5em;
+}
+
+.traffic-event-entry:hover {
+  background-color: #eee;
+}
+
+.traffic-event-entry .time {
+  color: #222;
+  font-family: sans-serif;
+}
+
+.traffic-event-entry .type {
+  font-family: sans-serif;
+  font-weight: bold;
+  margin: 0.5em;
+  white-space: nowrap;
+}
+
+.traffic-event-entry .details {
+  margin: 0.5em;
+  overflow-x: auto;
+}
+
+.traffic-event-entry .proto {
+  display: none;
+}
+
+.traffic-event-entry-expanded .proto {
+  background-color: #fff;
+  border: 1px solid #222;
+  display: block;
+  max-height: 300px;
+  overflow-x: auto;
+  overflow-y: auto;
+}
diff --git a/chrome/browser/resources/sync_internals/about.html b/chrome/browser/resources/sync_internals/about.html
index 766e1bc..4aa8e34 100644
--- a/chrome/browser/resources/sync_internals/about.html
+++ b/chrome/browser/resources/sync_internals/about.html
@@ -14,19 +14,32 @@
   </div>
 </div>
 
-<div id='aboutInfo'>
+<div id='about-info'>
   <div class="section" jsselect="details">
     <h2 jscontent="title"></h2>
-    <table class="aboutDetails">
+    <table class="about-details">
       <tr jsselect="data"
-            jsvalues="class:$this.is_valid ? '' : 'uninitialized'"
-            jseval='highlightIfChanged(this, this.children[1].innerText, stat_value)'>
+            jsvalues="class:$this.is_valid ? '' : 'uninitialized'">
         <td class="detail" jscontent="stat_name" width=50%></td>
         <td class="value" jscontent="stat_value" width=50%></td>
       </tr>
     </table>
   </div>
 
+  <div id="traffic-event-container-wrapper" jsskip="true">
+    <h2>Sync Protocol Log</h2>
+    <div id="traffic-event-container">
+      <div class="traffic-event-entry"
+           jsselect="events"
+           jseval="chrome.sync.about_tab.addExpandListener(this)">
+        <span class="time" jscontent="(new Date(time)).toLocaleString()"></span>
+        <span class="type" jscontent="type"></span>
+        <pre class="details" jscontent="details"></pre>
+        <pre class="proto" jscontent="JSON.stringify(proto, null, 2)"></pre>
+      </div>
+    </div>
+  </div>
+
   <div class="section" style="overflow-x: auto">
     <h2>Type Info</h2>
     <table id="typeInfo">
diff --git a/chrome/browser/resources/sync_internals/about.js b/chrome/browser/resources/sync_internals/about.js
index 59f2847..172e690 100644
--- a/chrome/browser/resources/sync_internals/about.js
+++ b/chrome/browser/resources/sync_internals/about.js
@@ -2,89 +2,124 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function highlightIfChanged(node, oldVal, newVal) {
-  function clearHighlight() {
-    this.removeAttribute('highlighted');
+cr.define('chrome.sync.about_tab', function() {
+  // Contains the latest snapshot of sync about info.
+  chrome.sync.aboutInfo = {};
+
+  function refreshAboutInfo(aboutInfo) {
+    chrome.sync.aboutInfo = aboutInfo;
+    var aboutInfoDiv = $('about-info');
+    jstProcess(new JsEvalContext(aboutInfo), aboutInfoDiv);
   }
 
-  var oldStr = oldVal.toString();
-  var newStr = newVal.toString();
-  if (oldStr != '' && oldStr != newStr) {
-    // Note the addListener function does not end up creating duplicate
-    // listeners.  There can be only one listener per event at a time.
-    // Reference: https://developer.mozilla.org/en/DOM/element.addEventListener
-    node.addEventListener('webkitAnimationEnd', clearHighlight, false);
-    node.setAttribute('highlighted', '');
+  function onAboutInfoUpdatedEvent(e) {
+    refreshAboutInfo(e.details);
   }
-}
 
-(function() {
-// Contains the latest snapshot of sync about info.
-chrome.sync.aboutInfo = {};
+  /** Container for accumulated sync protocol events. */
+  var protocolEvents = [];
 
-function refreshAboutInfo(aboutInfo) {
-  chrome.sync.aboutInfo = aboutInfo;
-  var aboutInfoDiv = $('aboutInfo');
-  jstProcess(new JsEvalContext(aboutInfo), aboutInfoDiv);
-}
+  /**
+   * Callback for incoming protocol events.
+   * @param {Event} e The protocol event.
+   */
+  function onReceivedProtocolEvent(e) {
+    var details = e.details;
+    protocolEvents.push(details);
 
-function onAboutInfoUpdatedEvent(e) {
-  refreshAboutInfo(e.details);
-}
+    var context = new JsEvalContext({ events: protocolEvents });
+    jstProcess(context, $('traffic-event-container'));
+  }
 
-function onLoad() {
-  $('status-data').hidden = true;
+  /**
+   * Initializes state and callbacks for the protocol event log UI.
+   */
+  function initProtocolEventLog() {
+    chrome.sync.events.addEventListener(
+        'onProtocolEvent', onReceivedProtocolEvent);
 
-  chrome.sync.events.addEventListener(
-      'onAboutInfoUpdated',
-      onAboutInfoUpdatedEvent);
-  chrome.sync.requestUpdatedAboutInfo();
+    // Make the prototype jscontent element disappear.
+    jstProcess({}, $('traffic-event-container'));
+  }
 
-  var dumpStatusButton = $('dump-status');
-  dumpStatusButton.addEventListener('click', function(event) {
-    var aboutInfo = chrome.sync.aboutInfo;
-    if (!$('include-ids').checked) {
-      aboutInfo.details = chrome.sync.aboutInfo.details.filter(function(el) {
-        return !el.is_sensitive;
-      });
-    }
-    var data = '';
-    data += new Date().toString() + '\n';
-    data += '======\n';
-    data += 'Status\n';
-    data += '======\n';
-    data += JSON.stringify(aboutInfo, null, 2) + '\n';
+  /**
+   * Toggles the given traffic event entry div's "expanded" state.
+   * @param {HTMLElement} element the element to toggle.
+   */
+  function expandListener(element) {
+    element.target.classList.toggle('traffic-event-entry-expanded');
+  }
 
-    $('status-text').value = data;
-    $('status-data').hidden = false;
-  });
+  /**
+   * Attaches a listener to the given traffic event entry div.
+   * @param {HTMLElement} element the element to attach the listener to.
+   */
+  function addExpandListener(element) {
+    element.addEventListener('click', expandListener, false);
+  }
 
-  var importStatusButton = $('import-status');
-  importStatusButton.addEventListener('click', function(event) {
-    $('status-data').hidden = false;
-    if ($('status-text').value.length == 0) {
-      $('status-text').value = 'Paste sync status dump here then click import.';
-      return;
-    }
+  function onLoad() {
+    $('status-data').hidden = true;
 
-    // First remove any characters before the '{'.
-    var data = $('status-text').value;
-    var firstBrace = data.indexOf('{');
-    if (firstBrace < 0) {
-      $('status-text').value = 'Invalid sync status dump.';
-      return;
-    }
-    data = data.substr(firstBrace);
-
-    // Remove listeners to prevent sync events from overwriting imported data.
-    chrome.sync.events.removeEventListener(
+    chrome.sync.events.addEventListener(
         'onAboutInfoUpdated',
         onAboutInfoUpdatedEvent);
+    chrome.sync.requestUpdatedAboutInfo();
 
-    var aboutInfo = JSON.parse(data);
-    refreshAboutInfo(aboutInfo);
-  });
-}
+    var dumpStatusButton = $('dump-status');
+    dumpStatusButton.addEventListener('click', function(event) {
+      var aboutInfo = chrome.sync.aboutInfo;
+      if (!$('include-ids').checked) {
+        aboutInfo.details = chrome.sync.aboutInfo.details.filter(function(el) {
+          return !el.is_sensitive;
+        });
+      }
+      var data = '';
+      data += new Date().toString() + '\n';
+      data += '======\n';
+      data += 'Status\n';
+      data += '======\n';
+      data += JSON.stringify(aboutInfo, null, 2) + '\n';
 
-document.addEventListener('DOMContentLoaded', onLoad, false);
-})();
+      $('status-text').value = data;
+      $('status-data').hidden = false;
+    });
+
+    var importStatusButton = $('import-status');
+    importStatusButton.addEventListener('click', function(event) {
+      $('status-data').hidden = false;
+      if ($('status-text').value.length == 0) {
+        $('status-text').value =
+            'Paste sync status dump here then click import.';
+        return;
+      }
+
+      // First remove any characters before the '{'.
+      var data = $('status-text').value;
+      var firstBrace = data.indexOf('{');
+      if (firstBrace < 0) {
+        $('status-text').value = 'Invalid sync status dump.';
+        return;
+      }
+      data = data.substr(firstBrace);
+
+      // Remove listeners to prevent sync events from overwriting imported data.
+      chrome.sync.events.removeEventListener(
+          'onAboutInfoUpdated',
+          onAboutInfoUpdatedEvent);
+
+      var aboutInfo = JSON.parse(data);
+      refreshAboutInfo(aboutInfo);
+    });
+
+    initProtocolEventLog();
+  }
+
+  return {
+    onLoad: onLoad,
+    addExpandListener: addExpandListener
+  };
+});
+
+document.addEventListener(
+    'DOMContentLoaded', chrome.sync.about_tab.onLoad, false);
diff --git a/chrome/browser/resources/sync_internals/sync_log.js b/chrome/browser/resources/sync_internals/sync_log.js
index 44d1f25..296a04a 100644
--- a/chrome/browser/resources/sync_internals/sync_log.js
+++ b/chrome/browser/resources/sync_internals/sync_log.js
@@ -38,6 +38,10 @@
     transaction: [
       'onTransactionWrite',
     ],
+
+    protocol: [
+      'onProtocolEvent',
+    ]
   };
 
   /**
diff --git a/chrome/browser/resources/uber/uber.html b/chrome/browser/resources/uber/uber.html
index 0750dfc..1e81cf3 100644
--- a/chrome/browser/resources/uber/uber.html
+++ b/chrome/browser/resources/uber/uber.html
@@ -20,7 +20,7 @@
 
 <body>
 
-<div id="navigation"><iframe src="chrome://uber-frame/"></iframe></div>
+<div id="navigation"><iframe src="chrome://uber-frame/" name="chrome"></iframe></div>
 
 <div class="iframe-container"
     i18n-values="id:historyHost; data-url:historyFrameURL;"
diff --git a/chrome/browser/resources/uber/uber.js b/chrome/browser/resources/uber/uber.js
index 0fdb4ae..5793ce3 100644
--- a/chrome/browser/resources/uber/uber.js
+++ b/chrome/browser/resources/uber/uber.js
@@ -245,7 +245,7 @@
 
   /**
    * Selects a subpage. This is called from uber-frame.
-   * @param {string} pageId Should matche an id of one of the iframe containers.
+   * @param {string} pageId Should match an id of one of the iframe containers.
    * @param {integer} historyOption Indicates whether we should push or replace
    *     browser history.
    * @param {string} path A sub-page path.
@@ -259,6 +259,7 @@
     var frame = container.querySelector('iframe');
     if (!frame) {
       frame = container.ownerDocument.createElement('iframe');
+      frame.name = pageId;
       container.appendChild(frame);
       frame.src = sourceUrl;
     } else {
diff --git a/chrome/browser/resources/video_player/OWNERS b/chrome/browser/resources/video_player/OWNERS
new file mode 100644
index 0000000..f199533
--- /dev/null
+++ b/chrome/browser/resources/video_player/OWNERS
@@ -0,0 +1 @@
+yoshiki@chromium.org
\ No newline at end of file
diff --git a/chrome/browser/resources/video_player/css/video_player.css b/chrome/browser/resources/video_player/css/video_player.css
new file mode 100644
index 0000000..2c11c33
--- /dev/null
+++ b/chrome/browser/resources/video_player/css/video_player.css
@@ -0,0 +1,103 @@
+/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+body {
+  -webkit-user-select: none;
+  background: black;
+  font-family: Noto Sans UI,Droid Sans Fallback,sans-serif;
+  font-size: 84%;
+  margin: 0;
+  overflow: hidden;
+}
+
+#video-player {
+  height: 100%;
+  left: 0;
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+#video-container {
+  height: 100%;
+  left: 0;
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+video {
+  height: 100%;
+  left: 0;
+  pointer-events: none;
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+#controls-wrapper {
+  -webkit-box-align: center;
+  -webkit-box-orient: horizontal;
+  -webkit-box-pack: center;
+  bottom: 0;
+  display: -webkit-box;
+  left: 0;
+  position: absolute;
+  right: 0;
+}
+
+#controls {
+  -webkit-box-flex: 1;
+  display: -webkit-box;
+}
+
+#video-player:not([tools]) .tool {
+  opacity: 0;
+}
+
+#video-player:not([tools]) {
+  cursor: none;
+}
+
+#video-player[disabled] .tool {
+  display: none;
+}
+
+.tool {
+  transition: opacity 180ms linear;
+}
+
+#error-wrapper {
+  -webkit-box-align: center;
+  -webkit-box-orient: horizontal;
+  -webkit-box-pack: center;
+  display: -webkit-box;
+  height: 100%;
+  left: 0;
+  pointer-events: none;
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+#error {
+  -webkit-box-align: center;
+  -webkit-box-orient: horizontal;
+  -webkit-box-pack: center;
+  background-color: rgba(24, 24, 24, 1);
+  background-image: -webkit-image-set(
+      url('../images/100/error.png') 1x,
+      url('../images/200/error.png') 2x);
+  background-position: 25px center;
+  background-repeat: no-repeat;
+  color: white;
+  display: -webkit-box;
+  height: 54px;
+  padding-left: 70px;
+  padding-right: 35px;
+}
+
+#error:not([visible]) {
+  display: none;
+}
diff --git a/chrome/browser/resources/video_player/images/100/error.png b/chrome/browser/resources/video_player/images/100/error.png
new file mode 100644
index 0000000..125c0b7
--- /dev/null
+++ b/chrome/browser/resources/video_player/images/100/error.png
Binary files differ
diff --git a/chrome/browser/resources/video_player/images/100/icon.png b/chrome/browser/resources/video_player/images/100/icon.png
new file mode 100644
index 0000000..73b70f6
--- /dev/null
+++ b/chrome/browser/resources/video_player/images/100/icon.png
Binary files differ
diff --git a/chrome/browser/resources/video_player/images/200/error.png b/chrome/browser/resources/video_player/images/200/error.png
new file mode 100644
index 0000000..200baf5
--- /dev/null
+++ b/chrome/browser/resources/video_player/images/200/error.png
Binary files differ
diff --git a/chrome/browser/resources/video_player/images/200/icon.png b/chrome/browser/resources/video_player/images/200/icon.png
new file mode 100644
index 0000000..a8346a3
--- /dev/null
+++ b/chrome/browser/resources/video_player/images/200/icon.png
Binary files differ
diff --git a/chrome/browser/resources/video_player/js/background.js b/chrome/browser/resources/video_player/js/background.js
new file mode 100644
index 0000000..57ff169
--- /dev/null
+++ b/chrome/browser/resources/video_player/js/background.js
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+
+// Stores the app windows OLNY for test purpose.
+// We SHOULD NOT use it as it is except for test, since the files which have
+// the same name will be overridden each other.
+var appWindowsForTest = {};
+
+chrome.app.runtime.onLaunched.addListener(function(launchData) {
+  if (!launchData || !launchData.items || launchData.items.length == 0)
+    return;
+
+  var entry = launchData.items[0].entry;
+  entry.file(function(file) {
+    var url = window.URL.createObjectURL(file);
+    open(url, entry.name);
+  }.wrap(),
+  function() {
+    // TODO(yoshiki): handle error in a smarter way.
+    open('', 'error');  // Empty URL shows the error message.
+  }.wrap());
+}.wrap());
+
+function open(url, title) {
+  chrome.app.window.create('video_player.html', {
+    id: 'video',
+    singleton: false,
+    minWidth: 160,
+    minHeight: 100
+  },
+  function(createdWindow) {
+    // Stores the window for test purpose.
+    appWindowsForTest[title] = createdWindow;
+
+    createdWindow.setIcon('images/200/icon.png');
+    createdWindow.contentWindow.videoUrl = url;
+    createdWindow.contentWindow.videoTitle = title;
+  }.wrap());
+}
diff --git a/chrome/browser/resources/video_player/js/error_util.js b/chrome/browser/resources/video_player/js/error_util.js
new file mode 100644
index 0000000..fedf9f5
--- /dev/null
+++ b/chrome/browser/resources/video_player/js/error_util.js
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * This variable is checked in SelectFileDialogExtensionBrowserTest.
+ * @type {number}
+ */
+window.JSErrorCount = 0;
+
+/**
+ * Counts uncaught exceptions.
+ */
+window.onerror = function() { window.JSErrorCount++; };
+
+/**
+ * Wraps the function to use it as a callback.
+ * This does:
+ *  - Capture the stack trace in case of error.
+ *  - Bind this object
+ *
+ * @param {Object} thisObject Object to be used as this.
+ * @return {function} Wapped function.
+ */
+Function.prototype.wrap = function(thisObject) {
+  var func = this;
+  var liveStack = (new Error('Stack trace before async call')).stack;
+  if (thisObject === undefined)
+    thisObject = null;
+
+  return function wrappedCallback() {
+    try {
+      return func.apply(thisObject, arguments);
+    } catch (e) {
+      console.error('Exception happens in callback.', liveStack);
+
+      window.JSErrorCount++;
+      throw e;
+    }
+  }
+};
diff --git a/chrome/browser/resources/video_player/js/test_util.js b/chrome/browser/resources/video_player/js/test_util.js
new file mode 100644
index 0000000..c01df4a
--- /dev/null
+++ b/chrome/browser/resources/video_player/js/test_util.js
@@ -0,0 +1,121 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Namespace for test related things.
+ */
+var test = test || {};
+
+/**
+ * Namespace for test utility functions.
+ *
+ * Public functions in the test.util.sync and the test.util.async namespaces are
+ * published to test cases and can be called by using callRemoteTestUtil. The
+ * arguments are serialized as JSON internally. If application ID is passed to
+ * callRemoteTestUtil, the content window of the application is added as the
+ * first argument. The functions in the test.util.async namespace are passed the
+ * callback function as the last argument.
+ */
+test.util = {};
+
+/**
+ * Namespace for synchronous utility functions.
+ */
+test.util.sync = {};
+
+/**
+ * Namespace for asynchronous utility functions.
+ */
+test.util.async = {};
+
+/**
+ * Extension ID of the testing extension.
+ * @type {string}
+ * @const
+ */
+test.util.TESTING_EXTENSION_ID = 'oobinhbdbiehknkpbpejbbpdbkdjmoco';
+
+/**
+ * Opens the main Files.app's window and waits until it is ready.
+ *
+ * @param {Window} contentWindow Video player window to be chacked toOB.
+ * @return {boolean} True if the video is playing, false otherwise.
+ */
+test.util.sync.isPlaying = function(contentWindow) {
+  var selector = 'video[src]';
+  var element = contentWindow.document.querySelector(selector);
+  if (!element)
+    return false;
+
+  return !element.paused;
+};
+
+/**
+ * Gets total Javascript error count from each app window.
+ * @return {number} Error count.
+ */
+test.util.sync.getErrorCount = function() {
+  var totalCount = JSErrorCount;
+  for (var appId in appWindowsForTest) {
+    var contentWindow = appWindowsForTest[appId].contentWindow;
+    if (contentWindow.JSErrorCount)
+      totalCount += contentWindow.JSErrorCount;
+  }
+
+  // Errors in the background page.
+  totalCount += window.JSErrorCount;
+
+  return totalCount;
+};
+
+/**
+ * Registers message listener, which runs test utility functions.
+ */
+test.util.registerRemoteTestUtils = function() {
+  // Register the message listener.
+  var onMessage = chrome.runtime ? chrome.runtime.onMessageExternal :
+      chrome.extension.onMessageExternal;
+  // Return true for asynchronous functions and false for synchronous.
+  onMessage.addListener(function(request, sender, sendResponse) {
+    // Check the sender.
+    if (sender.id != test.util.TESTING_EXTENSION_ID) {
+      console.error('The testing extension must be white-listed.');
+      sendResponse(false);
+      return false;
+    }
+    if (!request.func || request.func[request.func.length - 1] == '_') {
+      request.func = '';
+    }
+    // Prepare arguments.
+    var args = request.args.slice();  // shallow copy
+    if (request.file) {
+      if (!appWindowsForTest[request.file]) {
+        console.error('Specified window not found: ' + request.file);
+        sendResponse(false);
+        return false;
+      }
+      args.unshift(appWindowsForTest[request.file].contentWindow);
+    }
+    // Call the test utility function and respond the result.
+    if (test.util.async[request.func]) {
+      args[test.util.async[request.func].length - 1] = function() {
+        console.debug('Received the result of ' + request.func);
+        sendResponse.apply(null, arguments);
+      };
+      console.debug('Waiting for the result of ' + request.func);
+      test.util.async[request.func].apply(null, args);
+      return true;
+    } else if (test.util.sync[request.func]) {
+      sendResponse(test.util.sync[request.func].apply(null, args));
+      return false;
+    } else {
+      console.error('Invalid function name.');
+      sendResponse(false);
+      return false;
+    }
+  }.wrap());
+};
+
+// Register the test utils.
+test.util.registerRemoteTestUtils();
diff --git a/chrome/browser/resources/video_player/js/video_player.js b/chrome/browser/resources/video_player/js/video_player.js
new file mode 100644
index 0000000..f472cdf
--- /dev/null
+++ b/chrome/browser/resources/video_player/js/video_player.js
@@ -0,0 +1,215 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+'use strict';
+
+/**
+ * Displays error message.
+ * @param {string} message Message id.
+ */
+function showErrorMessage(message) {
+  var errorBanner = document.querySelector('#error');
+  errorBanner.textContent =
+      loadTimeData.getString(message);
+  errorBanner.setAttribute('visible', 'true');
+
+  // The window is hidden if the video has not loaded yet.
+  chrome.app.window.current().show();
+}
+
+/**
+ * Handles playback (decoder) errors.
+ */
+function onPlaybackError() {
+  showErrorMessage('GALLERY_VIDEO_DECODING_ERROR');
+  decodeErrorOccured = true;
+
+  // Disable inactivity watcher, and disable the ui, by hiding tools manually.
+  controls.inactivityWatcher.disabled = true;
+  document.querySelector('#video-player').setAttribute('disabled', 'true');
+
+  // Detach the video element, since it may be unreliable and reset stored
+  // current playback time.
+  controls.cleanup();
+  controls.clearState();
+
+  // Avoid reusing a video element.
+  video.parentNode.removeChild(video);
+  video = null;
+}
+
+/**
+ * @param {Element} playerContainer Main container.
+ * @param {Element} videoContainer Container for the video element.
+ * @param {Element} controlsContainer Container for video controls.
+ * @constructor
+ */
+function FullWindowVideoControls(
+    playerContainer, videoContainer, controlsContainer) {
+  VideoControls.call(this,
+      controlsContainer,
+      onPlaybackError,
+      loadTimeData.getString.wrap(loadTimeData),
+      this.toggleFullScreen_.wrap(this),
+      videoContainer);
+
+  this.playerContainer_ = playerContainer;
+
+  this.updateStyle();
+  window.addEventListener('resize', this.updateStyle.wrap(this));
+
+  document.addEventListener('keydown', function(e) {
+    if (e.keyIdentifier == 'U+0020') {  // Space
+      this.togglePlayStateWithFeedback();
+      e.preventDefault();
+    }
+    if (e.keyIdentifier == 'U+001B') {  // Escape
+      util.toggleFullScreen(
+          chrome.app.window.current(),
+          false);  // Leave the full screen mode.
+      e.preventDefault();
+    }
+  }.wrap(this));
+
+  // TODO(mtomasz): Simplify. crbug.com/254318.
+  videoContainer.addEventListener('click', function(e) {
+    if (e.ctrlKey) {
+      this.toggleLoopedModeWithFeedback(true);
+      if (!this.isPlaying())
+        this.togglePlayStateWithFeedback();
+    } else {
+      this.togglePlayStateWithFeedback();
+    }
+  }.wrap(this));
+
+  this.inactivityWatcher_ = new MouseInactivityWatcher(playerContainer);
+  this.__defineGetter__('inactivityWatcher', function() {
+    return this.inactivityWatcher_;
+  });
+
+  this.inactivityWatcher_.check();
+}
+
+FullWindowVideoControls.prototype = { __proto__: VideoControls.prototype };
+
+/**
+ * Toggles the full screen mode.
+ * @private
+ */
+FullWindowVideoControls.prototype.toggleFullScreen_ = function() {
+  var appWindow = chrome.app.window.current();
+  util.toggleFullScreen(appWindow, !util.isFullScreen(appWindow));
+};
+
+// TODO(mtomasz): Convert it to class members: crbug.com/171191.
+var decodeErrorOccured;
+var video;
+var controls;
+
+/**
+ * Initializes the video player window.
+ */
+function loadVideoPlayer() {
+  document.ondragstart = function(e) { e.preventDefault() };
+
+  chrome.fileBrowserPrivate.getStrings(function(strings) {
+    loadTimeData.data = strings;
+
+    var url = window.videoUrl;
+    document.title = window.videoTitle;
+
+    controls = new FullWindowVideoControls(
+        document.querySelector('#video-player'),
+        document.querySelector('#video-container'),
+        document.querySelector('#controls'));
+
+    var reloadVideo = function(e) {
+      if (decodeErrorOccured &&
+          // Ignore shortcut keys
+          !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
+        loadVideo(url);
+        e.preventDefault();
+      }
+    };
+
+    loadVideo(url);
+    document.addEventListener('keydown', reloadVideo, true);
+    document.addEventListener('click', reloadVideo, true);
+  });
+}
+
+/**
+ * Unloads the player.
+ */
+function unload() {
+  if (!controls.getMedia())
+    return;
+
+  controls.savePosition(true /* exiting */);
+  controls.cleanup();
+}
+
+/**
+ * Reloads the player.
+ * @param {string} url URL of the video file.
+ */
+function loadVideo(url) {
+  // Re-enable ui and hide error message if already displayed.
+  document.querySelector('#video-player').removeAttribute('disabled');
+  document.querySelector('#error').removeAttribute('visible');
+  controls.inactivityWatcher.disabled = false;
+  decodeErrorOccured = false;
+
+  // Detach the previous video element, if exists.
+  if (video)
+    video.parentNode.removeChild(video);
+
+  video = document.createElement('video');
+  document.querySelector('#video-container').appendChild(video);
+  controls.attachMedia(video);
+
+  video.src = url;
+  video.load();
+  video.addEventListener('loadedmetadata', function() {
+    // TODO: chrome.app.window soon will be able to resize the content area.
+    // Until then use approximate title bar height.
+    var TITLE_HEIGHT = 33;
+
+    var aspect = video.videoWidth / video.videoHeight;
+    var newWidth = video.videoWidth;
+    var newHeight = video.videoHeight + TITLE_HEIGHT;
+
+    var shrinkX = newWidth / window.screen.availWidth;
+    var shrinkY = newHeight / window.screen.availHeight;
+    if (shrinkX > 1 || shrinkY > 1) {
+      if (shrinkY > shrinkX) {
+        newHeight = newHeight / shrinkY;
+        newWidth = (newHeight - TITLE_HEIGHT) * aspect;
+      } else {
+        newWidth = newWidth / shrinkX;
+        newHeight = newWidth / aspect + TITLE_HEIGHT;
+      }
+    }
+
+    var oldLeft = window.screenX;
+    var oldTop = window.screenY;
+    var oldWidth = window.outerWidth;
+    var oldHeight = window.outerHeight;
+
+    if (!oldWidth && !oldHeight) {
+      oldLeft = window.screen.availWidth / 2;
+      oldTop = window.screen.availHeight / 2;
+    }
+
+    var appWindow = chrome.app.window.current();
+    appWindow.resizeTo(newWidth, newHeight);
+    appWindow.moveTo(oldLeft - (newWidth - oldWidth) / 2,
+                     oldTop - (newHeight - oldHeight) / 2);
+    appWindow.show();
+
+    video.play();
+  });
+}
+
+util.addPageLoadHandler(loadVideoPlayer);
diff --git a/chrome/browser/resources/video_player/js/video_player_scripts.js b/chrome/browser/resources/video_player/js/video_player_scripts.js
new file mode 100644
index 0000000..802eff3
--- /dev/null
+++ b/chrome/browser/resources/video_player/js/video_player_scripts.js
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// The include directives are put into Javascript-style comments to prevent
+// parsing errors in non-flattened mode. The flattener still sees them.
+// Note that this makes the flattener to comment out the first line of the
+// included file but that's all right since any javascript file should start
+// with a copyright comment anyway.
+
+//<include src="error_util.js"/>
+
+//<include src="../../../../../ui/webui/resources/js/cr.js"/>
+//<include src="../../../../../ui/webui/resources/js/load_time_data.js"/>
+
+(function() {
+'use strict';
+
+//<include src="../../file_manager/common/js/util.js"/>
+//<include src="../../file_manager/foreground/js/media/media_controls.js"/>
+//<include src="../../file_manager/foreground/js/media/util.js"/>
+
+//<include src="video_player.js"/>
+
+window.unload = unload;
+
+})();
diff --git a/chrome/browser/resources/video_player/manifest.json b/chrome/browser/resources/video_player/manifest.json
new file mode 100644
index 0000000..5478a98
--- /dev/null
+++ b/chrome/browser/resources/video_player/manifest.json
@@ -0,0 +1,57 @@
+{
+  // chrome-extension://jcgeabjmjgoblfofpppfkcoakmfobdko/
+  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw0/gRbJc545iEGRZs20Rl/HtrSUp8H3gJd4Y6hCe0CG1xQiJhZ5nc8qZyxa96gMxRAKBq54S6sjVVtV6uS70oU6FvrvwItByYkkqr4ZE7eMJKwMqnGItxWbh6KBodf89lpKoIy6MtYTqubBhXB/IQBZsXah90tXwRzaaJNWw+2BBRIhcPsH3ng+wgN7rwFxo4HIv9ZpqkYlx90rwkfjOmKPPnSXyXFIBJfmqfdbd8PLtcxzzOTE+vxwoXZuYWrthKm4uKfNqXIYns74sSJlqyKfctuR+nQdNh8uePv0e+/Ul3wER1/jIXULLjfyoaklyDs+ak3SDf+xWScJ+0LJ0AwIDAQAB",
+  "manifest_version": 2,
+  "name": "Video Player",
+  "version": "1.0",
+  "description": "Video Player",
+  "display_in_launcher": false,
+  "incognito" : "split",
+  "icons": {
+    "16": "images/100/icon.png",
+    "32": "images/200/icon.png"
+  },
+  "permissions": [
+    "fileSystem",
+    "fileBrowserPrivate",
+    "fullscreen",
+    "mediaPlayerPrivate",
+    "storage",
+    "chrome://theme/"
+  ],
+  "file_handlers": {
+    "video": {
+      "types": [
+        "video/*"
+      ],
+      "extensions": [
+        "3gp",
+        "avi",
+        "m4v",
+        "mkv",
+        "mov",
+        "mp4",
+        "mpeg",
+        "mpeg4",
+        "mpg",
+        "mpg4",
+        "ogm",
+        "ogv",
+        "ogx",
+        "webm"
+      ],
+      // TODO(yoshiki): localize this.
+      "title": "Watch"
+    }
+  },
+  "app": {
+    "background": {
+      "scripts": [
+        "js/error_util.js",
+        "js/test_util.js",
+        "js/background.js"
+      ]
+    },
+    "content_security_policy": "default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' chrome://theme data:; media-src 'self'; object-src 'self'"
+  }
+}
diff --git a/chrome/browser/resources/video_player/video_player.html b/chrome/browser/resources/video_player/video_player.html
new file mode 100644
index 0000000..45ef353
--- /dev/null
+++ b/chrome/browser/resources/video_player/video_player.html
@@ -0,0 +1,28 @@
+<!--
+  -- Copyright 2014 The Chromium Authors. All rights reserved.
+  -- Use of this source code is governed by a BSD-style license that can be
+  -- found in the LICENSE file.
+  -->
+<html>
+<head>
+  <title>#xFEFF;</title>
+  <link rel="icon" type="image/png" href="images/200/icon.png">
+  <link rel="stylesheet" type="text/css"
+        href="../file_manager/foreground/css/media_controls.css">
+  <link rel="stylesheet" type="text/css" href="css/video_player.css">
+
+  <script src="js/video_player_scripts.js"></script>
+</head>
+<body>
+  <div id="video-player" tools>
+    <div id="video-container">
+    </div>
+    <div id="controls-wrapper">
+      <div id="controls" class="tool"></div>
+    </div>
+    <div id="error-wrapper">
+      <div id="error"></div>
+    </div>
+  </div>
+</body>
+</html>
diff --git a/chrome/browser/safe_browsing/binary_feature_extractor.h b/chrome/browser/safe_browsing/binary_feature_extractor.h
new file mode 100644
index 0000000..a06a242
--- /dev/null
+++ b/chrome/browser/safe_browsing/binary_feature_extractor.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Utility functions to extract file features for malicious binary detection.
+// Each platform has its own implementation of this class.
+
+#ifndef CHROME_BROWSER_SAFE_BROWSING_BINARY_FEATURE_EXTRACTOR_H_
+#define CHROME_BROWSER_SAFE_BROWSING_BINARY_FEATURE_EXTRACTOR_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace safe_browsing {
+class ClientDownloadRequest_ImageHeaders;
+class ClientDownloadRequest_SignatureInfo;
+
+class BinaryFeatureExtractor
+    : public base::RefCountedThreadSafe<BinaryFeatureExtractor> {
+ public:
+  BinaryFeatureExtractor();
+
+  // Fills in the DownloadRequest_SignatureInfo for the given file path.
+  // This method may be called on any thread.
+  virtual void CheckSignature(
+      const base::FilePath& file_path,
+      ClientDownloadRequest_SignatureInfo* signature_info);
+
+  // Populates |image_headers| with the PE image headers of |file_path|.
+  virtual void ExtractImageHeaders(
+      const base::FilePath& file_path,
+      ClientDownloadRequest_ImageHeaders* image_headers);
+
+ protected:
+  friend class base::RefCountedThreadSafe<BinaryFeatureExtractor>;
+  virtual ~BinaryFeatureExtractor();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BinaryFeatureExtractor);
+};
+}  // namespace safe_browsing
+
+#endif  // CHROME_BROWSER_SAFE_BROWSING_BINARY_FEATURE_EXTRACTOR_H_
diff --git a/chrome/browser/safe_browsing/binary_feature_extractor_posix.cc b/chrome/browser/safe_browsing/binary_feature_extractor_posix.cc
new file mode 100644
index 0000000..a7da722
--- /dev/null
+++ b/chrome/browser/safe_browsing/binary_feature_extractor_posix.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// This is a stub for the code signing utilities on Mac and Linux.
+// It should eventually be replaced with a real implementation.
+
+#include "chrome/browser/safe_browsing/binary_feature_extractor.h"
+
+namespace safe_browsing {
+
+BinaryFeatureExtractor::BinaryFeatureExtractor() {}
+
+BinaryFeatureExtractor::~BinaryFeatureExtractor() {}
+
+void BinaryFeatureExtractor::CheckSignature(
+    const base::FilePath& file_path,
+    ClientDownloadRequest_SignatureInfo* signature_info) {}
+
+void BinaryFeatureExtractor::ExtractImageHeaders(
+    const base::FilePath& file_path,
+    ClientDownloadRequest_ImageHeaders* image_headers) {}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/binary_feature_extractor_win.cc b/chrome/browser/safe_browsing/binary_feature_extractor_win.cc
new file mode 100644
index 0000000..76d8ed9
--- /dev/null
+++ b/chrome/browser/safe_browsing/binary_feature_extractor_win.cc
@@ -0,0 +1,147 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/binary_feature_extractor.h"
+
+#include <windows.h>
+#include <softpub.h>
+#include <wintrust.h>
+
+#include "base/files/file_path.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/logging.h"
+#include "chrome/browser/safe_browsing/pe_image_reader_win.h"
+#include "chrome/common/safe_browsing/csd.pb.h"
+
+#pragma comment(lib, "wintrust.lib")
+
+namespace safe_browsing {
+
+BinaryFeatureExtractor::BinaryFeatureExtractor() {}
+
+BinaryFeatureExtractor::~BinaryFeatureExtractor() {}
+
+void BinaryFeatureExtractor::CheckSignature(
+    const base::FilePath& file_path,
+    ClientDownloadRequest_SignatureInfo* signature_info) {
+  VLOG(2) << "Checking signature for " << file_path.value();
+
+  WINTRUST_FILE_INFO file_info = {0};
+  file_info.cbStruct = sizeof(file_info);
+  file_info.pcwszFilePath = file_path.value().c_str();
+  file_info.hFile = NULL;
+  file_info.pgKnownSubject = NULL;
+
+  WINTRUST_DATA wintrust_data = {0};
+  wintrust_data.cbStruct = sizeof(wintrust_data);
+  wintrust_data.pPolicyCallbackData = NULL;
+  wintrust_data.pSIPClientData = NULL;
+  wintrust_data.dwUIChoice = WTD_UI_NONE;
+  wintrust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
+  wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
+  wintrust_data.pFile = &file_info;
+  wintrust_data.dwStateAction = WTD_STATEACTION_VERIFY;
+  wintrust_data.hWVTStateData = NULL;
+  wintrust_data.pwszURLReference = NULL;
+  // Disallow revocation checks over the network.
+  wintrust_data.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
+  wintrust_data.dwUIContext = WTD_UICONTEXT_EXECUTE;
+
+  // The WINTRUST_ACTION_GENERIC_VERIFY_V2 policy verifies that the certificate
+  // chains up to a trusted root CA, and that it has appropriate permission to
+  // sign code.
+  GUID policy_guid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
+
+  LONG result = WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE),
+                               &policy_guid,
+                               &wintrust_data);
+
+  CRYPT_PROVIDER_DATA* prov_data = WTHelperProvDataFromStateData(
+      wintrust_data.hWVTStateData);
+  if (prov_data) {
+    if (prov_data->csSigners > 0) {
+      signature_info->set_trusted(result == ERROR_SUCCESS);
+    }
+    for (DWORD i = 0; i < prov_data->csSigners; ++i) {
+      const CERT_CHAIN_CONTEXT* cert_chain_context =
+          prov_data->pasSigners[i].pChainContext;
+      if (!cert_chain_context)
+        break;
+      for (DWORD j = 0; j < cert_chain_context->cChain; ++j) {
+        CERT_SIMPLE_CHAIN* simple_chain = cert_chain_context->rgpChain[j];
+        ClientDownloadRequest_CertificateChain* chain =
+            signature_info->add_certificate_chain();
+        if (!simple_chain)
+          break;
+        for (DWORD k = 0; k < simple_chain->cElement; ++k) {
+          CERT_CHAIN_ELEMENT* element = simple_chain->rgpElement[k];
+          chain->add_element()->set_certificate(
+              element->pCertContext->pbCertEncoded,
+              element->pCertContext->cbCertEncoded);
+        }
+      }
+    }
+
+    // Free the provider data.
+    wintrust_data.dwStateAction = WTD_STATEACTION_CLOSE;
+    WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE),
+                   &policy_guid, &wintrust_data);
+  }
+}
+
+void BinaryFeatureExtractor::ExtractImageHeaders(
+    const base::FilePath& file_path,
+    ClientDownloadRequest_ImageHeaders* image_headers) {
+  // Map the file into memory.
+  base::MemoryMappedFile file;
+  if (!file.Initialize(file_path))
+    return;
+
+  PeImageReader pe_image;
+  if (!pe_image.Initialize(file.data(), file.length()))
+    return;
+
+  // Copy the headers.
+  ClientDownloadRequest_PEImageHeaders* pe_headers =
+      image_headers->mutable_pe_headers();
+  pe_headers->set_dos_header(pe_image.GetDosHeader(), sizeof(IMAGE_DOS_HEADER));
+  pe_headers->set_file_header(pe_image.GetCoffFileHeader(),
+                              sizeof(IMAGE_FILE_HEADER));
+  size_t optional_header_size = 0;
+  const uint8_t* optional_header_data =
+      pe_image.GetOptionalHeaderData(&optional_header_size);
+  if (pe_image.GetWordSize() == PeImageReader::WORD_SIZE_32) {
+    pe_headers->set_optional_headers32(optional_header_data,
+                                       optional_header_size);
+  } else {
+    pe_headers->set_optional_headers64(optional_header_data,
+                                       optional_header_size);
+  }
+  const size_t number_of_sections = pe_image.GetNumberOfSections();
+  for (size_t i = 0; i != number_of_sections; ++i) {
+    pe_headers->add_section_header(pe_image.GetSectionHeaderAt(i),
+                                   sizeof(IMAGE_SECTION_HEADER));
+  }
+  size_t export_size = 0;
+  const uint8_t* export_section = pe_image.GetExportSection(&export_size);
+  if (export_section)
+    pe_headers->set_export_section_data(export_section, export_size);
+  size_t number_of_debug_entries = pe_image.GetNumberOfDebugEntries();
+  for (size_t i = 0; i != number_of_debug_entries; ++i) {
+    const uint8_t* raw_data = NULL;
+    size_t raw_data_size = 0;
+    const IMAGE_DEBUG_DIRECTORY* directory_entry =
+        pe_image.GetDebugEntry(i, &raw_data, &raw_data_size);
+    if (directory_entry) {
+      ClientDownloadRequest_PEImageHeaders_DebugData* debug_data =
+          pe_headers->add_debug_data();
+      debug_data->set_directory_entry(directory_entry,
+                                      sizeof(*directory_entry));
+      if (raw_data)
+        debug_data->set_raw_data(raw_data, raw_data_size);
+    }
+  }
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/binary_feature_extractor_win_unittest.cc b/chrome/browser/safe_browsing/binary_feature_extractor_win_unittest.cc
new file mode 100644
index 0000000..10481da
--- /dev/null
+++ b/chrome/browser/safe_browsing/binary_feature_extractor_win_unittest.cc
@@ -0,0 +1,161 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/binary_feature_extractor.h"
+
+#include <string>
+#include <vector>
+
+#include "base/base_paths.h"
+#include "base/files/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "base/path_service.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/safe_browsing/csd.pb.h"
+#include "net/cert/x509_cert_types.h"
+#include "net/cert/x509_certificate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace safe_browsing {
+
+class BinaryFeatureExtractorWinTest : public testing::Test {
+ protected:
+  virtual void SetUp() OVERRIDE {
+    base::FilePath source_path;
+    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &source_path));
+    testdata_path_ = source_path
+        .AppendASCII("safe_browsing")
+        .AppendASCII("download_protection");
+
+    binary_feature_extractor_ = new BinaryFeatureExtractor();
+  }
+
+  // Given a certificate chain protobuf, parse it into X509Certificates.
+  void ParseCertificateChain(
+      const ClientDownloadRequest_CertificateChain& chain,
+      std::vector<scoped_refptr<net::X509Certificate> >* certs) {
+    for (int i = 0; i < chain.element_size(); ++i) {
+      certs->push_back(
+          net::X509Certificate::CreateFromBytes(
+              chain.element(i).certificate().data(),
+              chain.element(i).certificate().size()));
+    }
+  }
+
+  base::FilePath testdata_path_;
+  scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_;
+};
+
+TEST_F(BinaryFeatureExtractorWinTest, UntrustedSignedBinary) {
+  // signed.exe is signed by an untrusted root CA.
+  ClientDownloadRequest_SignatureInfo signature_info;
+  binary_feature_extractor_->CheckSignature(
+      testdata_path_.Append(L"signed.exe"),
+      &signature_info);
+  ASSERT_EQ(1, signature_info.certificate_chain_size());
+  std::vector<scoped_refptr<net::X509Certificate> > certs;
+  ParseCertificateChain(signature_info.certificate_chain(0), &certs);
+  ASSERT_EQ(2, certs.size());
+  EXPECT_EQ("Joe's-Software-Emporium", certs[0]->subject().common_name);
+  EXPECT_EQ("Root Agency", certs[1]->subject().common_name);
+
+  EXPECT_TRUE(signature_info.has_trusted());
+  EXPECT_FALSE(signature_info.trusted());
+}
+
+TEST_F(BinaryFeatureExtractorWinTest, TrustedBinary) {
+  // wow_helper.exe is signed using Google's signing certifiacte.
+  ClientDownloadRequest_SignatureInfo signature_info;
+  binary_feature_extractor_->CheckSignature(
+      testdata_path_.Append(L"wow_helper.exe"),
+      &signature_info);
+  ASSERT_EQ(1, signature_info.certificate_chain_size());
+  std::vector<scoped_refptr<net::X509Certificate> > certs;
+  ParseCertificateChain(signature_info.certificate_chain(0), &certs);
+  ASSERT_EQ(3, certs.size());
+
+  EXPECT_EQ("Google Inc", certs[0]->subject().common_name);
+  EXPECT_EQ("VeriSign Class 3 Code Signing 2009-2 CA",
+            certs[1]->subject().common_name);
+  EXPECT_EQ("Class 3 Public Primary Certification Authority",
+            certs[2]->subject().organization_unit_names[0]);
+
+  EXPECT_TRUE(signature_info.trusted());
+}
+
+TEST_F(BinaryFeatureExtractorWinTest, UnsignedBinary) {
+  // unsigned.exe has no signature information.
+  ClientDownloadRequest_SignatureInfo signature_info;
+  binary_feature_extractor_->CheckSignature(
+      testdata_path_.Append(L"unsigned.exe"),
+      &signature_info);
+  EXPECT_EQ(0, signature_info.certificate_chain_size());
+  EXPECT_FALSE(signature_info.has_trusted());
+}
+
+TEST_F(BinaryFeatureExtractorWinTest, NonExistentBinary) {
+  // Test a file that doesn't exist.
+  ClientDownloadRequest_SignatureInfo signature_info;
+  binary_feature_extractor_->CheckSignature(
+      testdata_path_.Append(L"doesnotexist.exe"),
+      &signature_info);
+  EXPECT_EQ(0, signature_info.certificate_chain_size());
+  EXPECT_FALSE(signature_info.has_trusted());
+}
+
+TEST_F(BinaryFeatureExtractorWinTest, ExtractImageHeadersNoFile) {
+  // Test extracting headers from a file that doesn't exist.
+  ClientDownloadRequest_ImageHeaders image_headers;
+  binary_feature_extractor_->ExtractImageHeaders(
+      testdata_path_.AppendASCII("this_file_does_not_exist"),
+      &image_headers);
+  EXPECT_FALSE(image_headers.has_pe_headers());
+}
+
+TEST_F(BinaryFeatureExtractorWinTest, ExtractImageHeadersNonImage) {
+  // Test extracting headers from something that is not a PE image.
+  ClientDownloadRequest_ImageHeaders image_headers;
+  binary_feature_extractor_->ExtractImageHeaders(
+      testdata_path_.AppendASCII("simple_exe.cc"),
+      &image_headers);
+  EXPECT_FALSE(image_headers.has_pe_headers());
+}
+
+TEST_F(BinaryFeatureExtractorWinTest, ExtractImageHeaders) {
+  // Test extracting headers from something that is a PE image.
+  ClientDownloadRequest_ImageHeaders image_headers;
+  binary_feature_extractor_->ExtractImageHeaders(
+      testdata_path_.AppendASCII("unsigned.exe"),
+      &image_headers);
+  EXPECT_TRUE(image_headers.has_pe_headers());
+  const ClientDownloadRequest_PEImageHeaders& pe_headers =
+      image_headers.pe_headers();
+  EXPECT_TRUE(pe_headers.has_dos_header());
+  EXPECT_TRUE(pe_headers.has_file_header());
+  EXPECT_TRUE(pe_headers.has_optional_headers32());
+  EXPECT_FALSE(pe_headers.has_optional_headers64());
+  EXPECT_NE(0, pe_headers.section_header_size());
+  EXPECT_FALSE(pe_headers.has_export_section_data());
+  EXPECT_EQ(0, pe_headers.debug_data_size());
+}
+
+TEST_F(BinaryFeatureExtractorWinTest, ExtractImageHeadersWithDebugData) {
+  // Test extracting headers from something that is a PE image with debug data.
+  ClientDownloadRequest_ImageHeaders image_headers;
+  binary_feature_extractor_->ExtractImageHeaders(
+      testdata_path_.DirName().AppendASCII("module_with_exports_x86.dll"),
+      &image_headers);
+  EXPECT_TRUE(image_headers.has_pe_headers());
+  const ClientDownloadRequest_PEImageHeaders& pe_headers =
+      image_headers.pe_headers();
+  EXPECT_TRUE(pe_headers.has_dos_header());
+  EXPECT_TRUE(pe_headers.has_file_header());
+  EXPECT_TRUE(pe_headers.has_optional_headers32());
+  EXPECT_FALSE(pe_headers.has_optional_headers64());
+  EXPECT_NE(0, pe_headers.section_header_size());
+  EXPECT_TRUE(pe_headers.has_export_section_data());
+  EXPECT_EQ(1U, pe_headers.debug_data_size());
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.cc b/chrome/browser/safe_browsing/browser_feature_extractor.cc
index 522c3fc..8d0bd73 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor.cc
+++ b/chrome/browser/safe_browsing/browser_feature_extractor.cc
@@ -262,7 +262,6 @@
     ClientMalwareRequest* request,
     const MalwareDoneCallback& callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  DCHECK_EQ(0U, request->url().find("http:"));
   DCHECK(!callback.is_null());
 
   // Grab the IPs because they might go away before we're done
diff --git a/chrome/browser/safe_browsing/browser_feature_extractor.h b/chrome/browser/safe_browsing/browser_feature_extractor.h
index 82a4e0d..bdad206 100644
--- a/chrome/browser/safe_browsing/browser_feature_extractor.h
+++ b/chrome/browser/safe_browsing/browser_feature_extractor.h
@@ -58,6 +58,9 @@
 typedef std::map<std::string, std::vector<IPUrlInfo> > IPUrlMap;
 
 struct BrowseInfo {
+  // The URL we're currently browsing.
+  GURL url;
+
   // List of IPv4 and IPv6 addresses from which content was requested
   // together with the hosts on it, while browsing to the |url|.
   IPUrlMap ips;
@@ -78,6 +81,9 @@
   // The HTTP status code from this navigation.
   int http_status_code;
 
+  // The page ID of the navigation.  This comes from FrameNavigateParams.
+  int32 page_id;
+
   BrowseInfo();
   ~BrowseInfo();
 };
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index 130f0ca..c2830fc 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -19,8 +19,6 @@
 #include "chrome/browser/safe_browsing/client_side_detection_service.h"
 #include "chrome/browser/safe_browsing/database_manager.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/safe_browsing/csd.pb.h"
 #include "chrome/common/safe_browsing/safebrowsing_messages.h"
@@ -36,6 +34,7 @@
 #include "content/public/browser/resource_request_details.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/frame_navigate_params.h"
+#include "content/public/common/url_constants.h"
 #include "url/gurl.h"
 
 using content::BrowserThread;
@@ -50,28 +49,34 @@
 
 const char kSafeBrowsingMatchKey[] = "safe_browsing_match";
 
+typedef base::Callback<void(bool)> ShouldClassifyUrlCallback;
+
 // This class is instantiated each time a new toplevel URL loads, and
-// asynchronously checks whether the phishing classifier should run for this
-// URL.  If so, it notifies the renderer with a StartPhishingDetection IPC.
-// Objects of this class are ref-counted and will be destroyed once nobody
-// uses it anymore.  If |web_contents|, |csd_service| or |host| go away you need
-// to call Cancel().  We keep the |database_manager| alive in a ref pointer for
-// as long as it takes.
+// asynchronously checks whether the malware and phishing classifiers should run
+// for this URL.  If so, it notifies the host class by calling the provided
+// callback form the UI thread.  Objects of this class are ref-counted and will
+// be destroyed once nobody uses it anymore.  If |web_contents|, |csd_service|
+// or |host| go away you need to call Cancel().  We keep the |database_manager|
+// alive in a ref pointer for as long as it takes.
 class ClientSideDetectionHost::ShouldClassifyUrlRequest
     : public base::RefCountedThreadSafe<
           ClientSideDetectionHost::ShouldClassifyUrlRequest> {
  public:
-  ShouldClassifyUrlRequest(const content::FrameNavigateParams& params,
-                           WebContents* web_contents,
-                           ClientSideDetectionService* csd_service,
-                           SafeBrowsingDatabaseManager* database_manager,
-                           ClientSideDetectionHost* host)
-      : canceled_(false),
-        params_(params),
+  ShouldClassifyUrlRequest(
+      const content::FrameNavigateParams& params,
+      const ShouldClassifyUrlCallback& start_phishing_classification,
+      const ShouldClassifyUrlCallback& start_malware_classification,
+      WebContents* web_contents,
+      ClientSideDetectionService* csd_service,
+      SafeBrowsingDatabaseManager* database_manager,
+      ClientSideDetectionHost* host)
+      : params_(params),
         web_contents_(web_contents),
         csd_service_(csd_service),
         database_manager_(database_manager),
-        host_(host) {
+        host_(host),
+        start_phishing_classification_cb_(start_phishing_classification),
+        start_malware_classification_cb_(start_malware_classification) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     DCHECK(web_contents_);
     DCHECK(csd_service_);
@@ -83,7 +88,8 @@
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
     // We start by doing some simple checks that can run on the UI thread.
-    UMA_HISTOGRAM_COUNTS("SBClientPhishing.ClassificationStart", 1);
+    UMA_HISTOGRAM_BOOLEAN("SBClientPhishing.ClassificationStart", 1);
+    UMA_HISTOGRAM_BOOLEAN("SBClientMalware.ClassificationStart", 1);
 
     // Only classify [X]HTML documents.
     if (params_.contents_mime_type != "text/html" &&
@@ -91,50 +97,53 @@
       VLOG(1) << "Skipping phishing classification for URL: " << params_.url
               << " because it has an unsupported MIME type: "
               << params_.contents_mime_type;
-      UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail",
-                                NO_CLASSIFY_UNSUPPORTED_MIME_TYPE,
-                                NO_CLASSIFY_MAX);
-      return;
+      DontClassifyForPhishing(NO_CLASSIFY_UNSUPPORTED_MIME_TYPE);
     }
 
     if (csd_service_->IsPrivateIPAddress(params_.socket_address.host())) {
       VLOG(1) << "Skipping phishing classification for URL: " << params_.url
               << " because of hosting on private IP: "
               << params_.socket_address.host();
-      UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail",
-                                NO_CLASSIFY_PRIVATE_IP,
-                                NO_CLASSIFY_MAX);
-      return;
+      DontClassifyForPhishing(NO_CLASSIFY_PRIVATE_IP);
+      DontClassifyForMalware(NO_CLASSIFY_PRIVATE_IP);
     }
 
-    // Don't run the phishing classifier if the tab is incognito.
-    if (web_contents_->GetBrowserContext()->IsOffTheRecord()) {
+    // For phishing we only classify HTTP pages.
+    if (!params_.url.SchemeIs(content::kHttpScheme)) {
       VLOG(1) << "Skipping phishing classification for URL: " << params_.url
-              << " because we're browsing incognito.";
-      UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail",
-                                NO_CLASSIFY_OFF_THE_RECORD,
-                                NO_CLASSIFY_MAX);
+              << " because it is not HTTP: "
+              << params_.socket_address.host();
+      DontClassifyForPhishing(NO_CLASSIFY_NOT_HTTP_URL);
+    }
 
-      return;
+    // Don't run any classifier if the tab is incognito.
+    if (web_contents_->GetBrowserContext()->IsOffTheRecord()) {
+      VLOG(1) << "Skipping phishing and malware classification for URL: "
+              << params_.url << " because we're browsing incognito.";
+      DontClassifyForPhishing(NO_CLASSIFY_OFF_THE_RECORD);
+      DontClassifyForMalware(NO_CLASSIFY_OFF_THE_RECORD);
     }
 
     // We lookup the csd-whitelist before we lookup the cache because
     // a URL may have recently been whitelisted.  If the URL matches
-    // the csd-whitelist we won't start classification.  The
+    // the csd-whitelist we won't start phishing classification.  The
     // csd-whitelist check has to be done on the IO thread because it
     // uses the SafeBrowsing service class.
-    BrowserThread::PostTask(
-        BrowserThread::IO,
-        FROM_HERE,
-        base::Bind(&ShouldClassifyUrlRequest::CheckCsdWhitelist,
-                   this, params_.url));
+    if (ShouldClassifyForPhishing() || ShouldClassifyForMalware()) {
+      BrowserThread::PostTask(
+          BrowserThread::IO,
+          FROM_HERE,
+          base::Bind(&ShouldClassifyUrlRequest::CheckSafeBrowsingDatabase,
+                     this, params_.url));
+    }
   }
 
   void Cancel() {
-    canceled_ = true;
+    DontClassifyForPhishing(NO_CLASSIFY_CANCEL);
+    DontClassifyForMalware(NO_CLASSIFY_CANCEL);
     // Just to make sure we don't do anything stupid we reset all these
     // pointers except for the safebrowsing service class which may be
-    // accessed by CheckCsdWhitelist().
+    // accessed by CheckSafeBrowsingDatabase().
     web_contents_ = NULL;
     csd_service_ = NULL;
     host_ = NULL;
@@ -152,6 +161,11 @@
     NO_CLASSIFY_MATCH_CSD_WHITELIST,
     NO_CLASSIFY_TOO_MANY_REPORTS,
     NO_CLASSIFY_UNSUPPORTED_MIME_TYPE,
+    NO_CLASSIFY_NO_DATABASE_MANAGER,
+    NO_CLASSIFY_KILLSWITCH,
+    NO_CLASSIFY_CANCEL,
+    NO_CLASSIFY_RESULT_FROM_CACHE,
+    NO_CLASSIFY_NOT_HTTP_URL,
 
     NO_CLASSIFY_MAX  // Always add new values before this one.
   };
@@ -159,75 +173,120 @@
   // The destructor can be called either from the UI or the IO thread.
   virtual ~ShouldClassifyUrlRequest() { }
 
-  void CheckCsdWhitelist(const GURL& url) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-    if (!database_manager_.get() ||
-        database_manager_->MatchCsdWhitelistUrl(url)) {
-      // We're done.  There is no point in going back to the UI thread.
-      VLOG(1) << "Skipping phishing classification for URL: " << url
-              << " because it matches the csd whitelist";
+  bool ShouldClassifyForPhishing() const {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    return !start_phishing_classification_cb_.is_null();
+  }
+
+  bool ShouldClassifyForMalware() const {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    return !start_malware_classification_cb_.is_null();
+  }
+
+  void DontClassifyForPhishing(PreClassificationCheckFailures reason) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    if (ShouldClassifyForPhishing()) {
+      // Track the first reason why we stopped classifying for phishing.
       UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail",
-                                NO_CLASSIFY_MATCH_CSD_WHITELIST,
-                                NO_CLASSIFY_MAX);
-      return;
+                                reason, NO_CLASSIFY_MAX);
+      DVLOG(2) << "Failed phishing pre-classification checks.  Reason: "
+               << reason;
+      start_phishing_classification_cb_.Run(false);
     }
+    start_phishing_classification_cb_.Reset();
+  }
 
-    bool malware_killswitch_on = database_manager_->IsMalwareKillSwitchOn();
+  void DontClassifyForMalware(PreClassificationCheckFailures reason) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    if (ShouldClassifyForMalware()) {
+      // Track the first reason why we stopped classifying for malware.
+      UMA_HISTOGRAM_ENUMERATION("SBClientMalware.PreClassificationCheckFail",
+                                reason, NO_CLASSIFY_MAX);
+      DVLOG(2) << "Failed malware pre-classification checks.  Reason: "
+               << reason;
+      start_malware_classification_cb_.Run(false);
+    }
+    start_malware_classification_cb_.Reset();
+  }
 
+  void CheckSafeBrowsingDatabase(const GURL& url) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+    // We don't want to call the classification callbacks from the IO
+    // thread so we simply pass the results of this method to CheckCache()
+    // which is called on the UI thread;
+    PreClassificationCheckFailures phishing_reason = NO_CLASSIFY_MAX;
+    PreClassificationCheckFailures malware_reason = NO_CLASSIFY_MAX;
+    if (!database_manager_.get()) {
+      // We cannot check the Safe Browsing whitelists so we stop here
+      // for safety.
+      malware_reason = phishing_reason = NO_CLASSIFY_NO_DATABASE_MANAGER;
+    } else {
+      if (database_manager_->MatchCsdWhitelistUrl(url)) {
+        VLOG(1) << "Skipping phishing classification for URL: " << url
+                << " because it matches the csd whitelist";
+        phishing_reason = NO_CLASSIFY_MATCH_CSD_WHITELIST;
+      }
+      if (database_manager_->IsMalwareKillSwitchOn()) {
+        malware_reason = NO_CLASSIFY_KILLSWITCH;
+      }
+    }
     BrowserThread::PostTask(
         BrowserThread::UI,
         FROM_HERE,
-        base::Bind(&ShouldClassifyUrlRequest::CheckCache, this,
-                   malware_killswitch_on));
+        base::Bind(&ShouldClassifyUrlRequest::CheckCache,
+                   this,
+                   phishing_reason,
+                   malware_reason));
   }
 
-  void CheckCache(bool malware_killswitch_on) {
+  void CheckCache(PreClassificationCheckFailures phishing_reason,
+                  PreClassificationCheckFailures malware_reason) {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-    if (canceled_) {
-      return;
+    if (phishing_reason != NO_CLASSIFY_MAX)
+      DontClassifyForPhishing(phishing_reason);
+    if (malware_reason != NO_CLASSIFY_MAX)
+      DontClassifyForMalware(malware_reason);
+    if (!ShouldClassifyForMalware() && !ShouldClassifyForPhishing()) {
+      return;  // No point in doing anything else.
     }
-
-    host_->SetMalwareKillSwitch(malware_killswitch_on);
-    // If result is cached, we don't want to run classification again
+    // If result is cached, we don't want to run classification again.
+    // In that case we're just trying to show the warning.
     bool is_phishing;
     if (csd_service_->GetValidCachedResult(params_.url, &is_phishing)) {
       VLOG(1) << "Satisfying request for " << params_.url << " from cache";
-      UMA_HISTOGRAM_COUNTS("SBClientPhishing.RequestSatisfiedFromCache", 1);
+      UMA_HISTOGRAM_BOOLEAN("SBClientPhishing.RequestSatisfiedFromCache", 1);
       // Since we are already on the UI thread, this is safe.
       host_->MaybeShowPhishingWarning(params_.url, is_phishing);
-      return;
+      DontClassifyForPhishing(NO_CLASSIFY_RESULT_FROM_CACHE);
     }
 
     // We want to limit the number of requests, though we will ignore the
     // limit for urls in the cache.  We don't want to start classifying
     // too many pages as phishing, but for those that we already think are
-    // phishing we want to give ourselves a chance to fix false positives.
+    // phishing we want to send a request to the server to give ourselves
+    // a chance to fix misclassifications.
     if (csd_service_->IsInCache(params_.url)) {
       VLOG(1) << "Reporting limit skipped for " << params_.url
               << " as it was in the cache.";
-      UMA_HISTOGRAM_COUNTS("SBClientPhishing.ReportLimitSkipped", 1);
+      UMA_HISTOGRAM_BOOLEAN("SBClientPhishing.ReportLimitSkipped", 1);
     } else if (csd_service_->OverPhishingReportLimit()) {
       VLOG(1) << "Too many report phishing requests sent recently, "
               << "not running classification for " << params_.url;
-      UMA_HISTOGRAM_ENUMERATION("SBClientPhishing.PreClassificationCheckFail",
-                                NO_CLASSIFY_TOO_MANY_REPORTS,
-                                NO_CLASSIFY_MAX);
-      return;
+      DontClassifyForPhishing(NO_CLASSIFY_TOO_MANY_REPORTS);
+    }
+    if (csd_service_->OverMalwareReportLimit()) {
+      DontClassifyForMalware(NO_CLASSIFY_TOO_MANY_REPORTS);
     }
 
     // Everything checks out, so start classification.
     // |web_contents_| is safe to call as we will be destructed
     // before it is.
-    VLOG(1) << "Instruct renderer to start phishing detection for URL: "
-            << params_.url;
-    content::RenderViewHost* rvh = web_contents_->GetRenderViewHost();
-    rvh->Send(new SafeBrowsingMsg_StartPhishingDetection(
-        rvh->GetRoutingID(), params_.url));
+    if (ShouldClassifyForPhishing())
+      start_phishing_classification_cb_.Run(true);
+    if (ShouldClassifyForMalware())
+      start_malware_classification_cb_.Run(true);
   }
 
-  // No need to protect |canceled_| with a lock because it is only read and
-  // written by the UI thread.
-  bool canceled_;
   content::FrameNavigateParams params_;
   WebContents* web_contents_;
   ClientSideDetectionService* csd_service_;
@@ -236,6 +295,9 @@
   scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
   ClientSideDetectionHost* host_;
 
+  ShouldClassifyUrlCallback start_phishing_classification_cb_;
+  ShouldClassifyUrlCallback start_malware_classification_cb_;
+
   DISALLOW_COPY_AND_ASSIGN(ShouldClassifyUrlRequest);
 };
 
@@ -248,10 +310,12 @@
 ClientSideDetectionHost::ClientSideDetectionHost(WebContents* tab)
     : content::WebContentsObserver(tab),
       csd_service_(NULL),
+      classification_request_(NULL),
+      should_extract_malware_features_(true),
+      should_classify_for_malware_(false),
+      onload_complete_(false),
       weak_factory_(this),
-      unsafe_unique_page_id_(-1),
-      malware_killswitch_on_(false),
-      malware_report_enabled_(false) {
+      unsafe_unique_page_id_(-1) {
   DCHECK(tab);
   // Note: csd_service_ and sb_service will be NULL here in testing.
   csd_service_ = g_browser_process->safe_browsing_detection_service();
@@ -266,13 +330,6 @@
     database_manager_ = sb_service->database_manager();
     ui_manager_->AddObserver(this);
   }
-
-  // Only enable the malware bad IP matching and report feature for canary
-  // and dev channel.
-  chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
-  malware_report_enabled_ = (
-      channel == chrome::VersionInfo::CHANNEL_DEV ||
-      channel == chrome::VersionInfo::CHANNEL_CANARY);
 }
 
 ClientSideDetectionHost::~ClientSideDetectionHost() {
@@ -302,6 +359,10 @@
     // begin a new classification.
     return;
   }
+  // Cancel any pending classification request.
+  if (classification_request_.get()) {
+    classification_request_->Cancel();
+  }
   // If we navigate away and there currently is a pending phishing
   // report request we have to cancel it to make sure we don't display
   // an interstitial for the wrong page.  Note that this won't cancel
@@ -312,11 +373,6 @@
   if (!csd_service_) {
     return;
   }
-
-  // Cancel any pending classification request.
-  if (classification_request_.get()) {
-    classification_request_->Cancel();
-  }
   browse_info_.reset(new BrowseInfo);
 
   // Store redirect chain information.
@@ -324,14 +380,25 @@
     cur_host_ = params.url.host();
     cur_host_redirects_ = params.redirects;
   }
+  browse_info_->url = params.url;
   browse_info_->host_redirects = cur_host_redirects_;
   browse_info_->url_redirects = params.redirects;
   browse_info_->referrer = params.referrer.url;
   browse_info_->http_status_code = details.http_status_code;
+  browse_info_->page_id = params.page_id;
 
-  // Notify the renderer if it should classify this URL.
+  should_extract_malware_features_ = true;
+  should_classify_for_malware_ = false;
+  onload_complete_ = false;
+
+  // Check whether we can cassify the current URL for phishing or malware.
   classification_request_ = new ShouldClassifyUrlRequest(
-      params, web_contents(), csd_service_, database_manager_.get(), this);
+      params,
+      base::Bind(&ClientSideDetectionHost::OnPhishingPreClassificationDone,
+                 weak_factory_.GetWeakPtr()),
+      base::Bind(&ClientSideDetectionHost::OnMalwarePreClassificationDone,
+                 weak_factory_.GetWeakPtr()),
+      web_contents(), csd_service_, database_manager_.get(), this);
   classification_request_->Start();
 }
 
@@ -414,6 +481,70 @@
   feature_extractor_.reset();
 }
 
+void ClientSideDetectionHost::OnPhishingPreClassificationDone(
+    bool should_classify) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (browse_info_.get() && should_classify) {
+    VLOG(1) << "Instruct renderer to start phishing detection for URL: "
+            << browse_info_->url;
+    content::RenderViewHost* rvh = web_contents()->GetRenderViewHost();
+    rvh->Send(new SafeBrowsingMsg_StartPhishingDetection(
+        rvh->GetRoutingID(), browse_info_->url));
+  }
+}
+
+void ClientSideDetectionHost::OnMalwarePreClassificationDone(
+    bool should_classify) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  // If classification checks failed we should stop extracting malware features.
+  DVLOG(2) << "Malware pre-classification checks done. Should classify: "
+           << should_classify;
+  should_extract_malware_features_ = should_classify;
+  should_classify_for_malware_ = should_classify;
+  MaybeStartMalwareFeatureExtraction();
+}
+
+void ClientSideDetectionHost::DocumentOnLoadCompletedInMainFrame(
+    int32 page_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (!csd_service_ || !browse_info_.get())
+    return;
+  DVLOG(2) << "Main frame onload hander called.";
+  if (browse_info_->page_id != page_id) {
+    // Something weird is happening here.  The BrowseInfo page ID
+    // should always be the same as the most recent load.
+    UMA_HISTOGRAM_BOOLEAN("SBClientMalware.UnexpectedPageId", 1);
+    return;
+  }
+  onload_complete_ = true;
+  MaybeStartMalwareFeatureExtraction();
+}
+
+void ClientSideDetectionHost::MaybeStartMalwareFeatureExtraction() {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  if (csd_service_ && browse_info_.get() &&
+      should_classify_for_malware_ &&
+      onload_complete_) {
+    scoped_ptr<ClientMalwareRequest> malware_request(
+        new ClientMalwareRequest);
+    // Start browser-side malware feature extraction.  Once we're done it will
+    // send the malware client verdict request.
+    malware_request->set_url(browse_info_->url.spec());
+    const GURL& referrer = browse_info_->referrer;
+    if (referrer.SchemeIs("http")) {  // Only send http urls.
+      malware_request->set_referrer_url(referrer.spec());
+    }
+    // This function doesn't expect browse_info_ to stay around after this
+    // function returns.
+    feature_extractor_->ExtractMalwareFeatures(
+        browse_info_.get(),
+        malware_request.release(),
+        base::Bind(&ClientSideDetectionHost::MalwareFeatureExtractionDone,
+                   weak_factory_.GetWeakPtr()));
+    should_classify_for_malware_ = false;
+  }
+}
+
 void ClientSideDetectionHost::OnPhishingDetectionDone(
     const std::string& verdict_str) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -421,40 +552,15 @@
   // this method is called.  The renderer should not start phishing detection
   // if there isn't any service class in the browser.
   DCHECK(csd_service_);
-  // There shouldn't be any pending requests because we revoke them everytime
-  // we navigate away.
-  DCHECK(!weak_factory_.HasWeakPtrs());
   DCHECK(browse_info_.get());
 
   // We parse the protocol buffer here.  If we're unable to parse it we won't
   // send the verdict further.
   scoped_ptr<ClientPhishingRequest> verdict(new ClientPhishingRequest);
   if (csd_service_ &&
-      !weak_factory_.HasWeakPtrs() &&
       browse_info_.get() &&
       verdict->ParseFromString(verdict_str) &&
       verdict->IsInitialized()) {
-    // We do the malware IP matching and request sending if the feature
-    // is enabled.
-    if (malware_report_enabled_ && !MalwareKillSwitchIsOn()) {
-      scoped_ptr<ClientMalwareRequest> malware_verdict(
-          new ClientMalwareRequest);
-      // Start browser-side malware feature extraction.  Once we're done it will
-      // send the malware client verdict request.
-      malware_verdict->set_url(verdict->url());
-      const GURL& referrer = browse_info_->referrer;
-      if (referrer.SchemeIs("http")) {  // Only send http urls.
-          malware_verdict->set_referrer_url(referrer.spec());
-      }
-      // This function doesn't expect browse_info_ to stay around after this
-      // function returns.
-      feature_extractor_->ExtractMalwareFeatures(
-          browse_info_.get(),
-          malware_verdict.release(),
-          base::Bind(&ClientSideDetectionHost::MalwareFeatureExtractionDone,
-                     weak_factory_.GetWeakPtr()));
-    }
-
     // We only send phishing verdict to the server if the verdict is phishing or
     // if a SafeBrowsing interstitial was already shown for this site.  E.g., a
     // malware or phishing interstitial was shown but the user clicked
@@ -472,14 +578,13 @@
                      weak_factory_.GetWeakPtr()));
     }
   }
-  browse_info_.reset();
 }
 
 void ClientSideDetectionHost::MaybeShowPhishingWarning(GURL phishing_url,
                                                        bool is_phishing) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  VLOG(2) << "Received server phishing verdict for URL:" << phishing_url
-          << " is_phishing:" << is_phishing;
+  DVLOG(2) << "Received server phishing verdict for URL:" << phishing_url
+           << " is_phishing:" << is_phishing;
   if (is_phishing) {
     DCHECK(web_contents());
     if (ui_manager_.get()) {
@@ -509,8 +614,8 @@
                                                       GURL malware_url,
                                                       bool is_malware) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  VLOG(2) << "Received server malawre IP verdict for URL:" << malware_url
-          << " is_malware:" << is_malware;
+  DVLOG(2) << "Received server malawre IP verdict for URL:" << malware_url
+           << " is_malware:" << is_malware;
   if (is_malware && malware_url.is_valid() && original_url.is_valid()) {
     DCHECK(web_contents());
     if (ui_manager_.get()) {
@@ -540,8 +645,8 @@
     bool success,
     ClientPhishingRequest* request) {
   DCHECK(request);
-  VLOG(2) << "Feature extraction done (success:" << success << ") for URL: "
-          << request->url() << ". Start sending client phishing request.";
+  DVLOG(2) << "Feature extraction done (success:" << success << ") for URL: "
+           << request->url() << ". Start sending client phishing request.";
   ClientSideDetectionService::ClientReportPhishingRequestCallback callback;
   // If the client-side verdict isn't phishing we don't care about the server
   // response because we aren't going to display a warning.
@@ -559,8 +664,8 @@
     bool feature_extraction_success,
     scoped_ptr<ClientMalwareRequest> request) {
   DCHECK(request.get());
-  VLOG(2) << "Malware Feature extraction done for URL: " << request->url()
-          << ", with badip url count:" << request->bad_ip_url_info_size();
+  DVLOG(2) << "Malware Feature extraction done for URL: " << request->url()
+           << ", with badip url count:" << request->bad_ip_url_info_size();
 
   // Send ping if there is matching features.
   if (feature_extraction_success && request->bad_ip_url_info_size() > 0) {
@@ -601,15 +706,13 @@
   DCHECK_EQ(type, content::NOTIFICATION_RESOURCE_RESPONSE_STARTED);
   const ResourceRequestDetails* req = content::Details<ResourceRequestDetails>(
       details).ptr();
-  if (req && browse_info_.get() && malware_report_enabled_ &&
-      !MalwareKillSwitchIsOn()) {
-    if (req->url.is_valid()) {
-      UpdateIPUrlMap(req->socket_address.host() /* ip */,
-                     req->url.spec()  /* url */,
-                     req->method,
-                     req->referrer,
-                     req->resource_type);
-    }
+  if (req && browse_info_.get() &&
+      should_extract_malware_features_ && req->url.is_valid()) {
+    UpdateIPUrlMap(req->socket_address.host() /* ip */,
+                   req->url.spec()  /* url */,
+                   req->method,
+                   req->referrer,
+                   req->resource_type);
   }
 }
 
@@ -640,14 +743,4 @@
   database_manager_ = database_manager;
 }
 
-bool ClientSideDetectionHost::MalwareKillSwitchIsOn() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  return malware_killswitch_on_;
-}
-
-void ClientSideDetectionHost::SetMalwareKillSwitch(bool killswitch_on) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  malware_killswitch_on_ = killswitch_on;
-}
-
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.h b/chrome/browser/safe_browsing/client_side_detection_host.h
index c5cf95a..1492f13 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.h
+++ b/chrome/browser/safe_browsing/client_side_detection_host.h
@@ -79,6 +79,11 @@
   class ShouldClassifyUrlRequest;
   friend class ShouldClassifyUrlRequest;
 
+  // These methods are called when pre-classification checks are done for
+  // the phishing and malware clasifiers.
+  void OnPhishingPreClassificationDone(bool should_classify);
+  void OnMalwarePreClassificationDone(bool should_classify);
+
   // Verdict is an encoded ClientPhishingRequest protocol message.
   void OnPhishingDetectionDone(const std::string& verdict);
 
@@ -98,10 +103,14 @@
   // the UI thread.
   void FeatureExtractionDone(bool success, ClientPhishingRequest* request);
 
+  // Start malware classification once the onload handler was called and
+  // malware pre-classification checks are done and passed.
+  void MaybeStartMalwareFeatureExtraction();
+
   // Function to be called when the browser malware feature extractor is done.
   // Called on the UI thread.
-  void MalwareFeatureExtractionDone(bool success,
-                                    scoped_ptr<ClientMalwareRequest> request);
+  void MalwareFeatureExtractionDone(
+      bool success, scoped_ptr<ClientMalwareRequest> request);
 
   // Update the entries in browse_info_->ips map.
   void UpdateIPUrlMap(const std::string& ip,
@@ -116,6 +125,10 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+  // Inherited from WebContentsObserver.  This is called once the onload handler
+  // is called.
+  virtual void DocumentOnLoadCompletedInMainFrame(int32 page_id) OVERRIDE;
+
   // Returns true if the user has seen a regular SafeBrowsing
   // interstitial for the current page.  This is only true if the user has
   // actually clicked through the warning.  This method is called on the UI
@@ -126,10 +139,6 @@
   // class.
   void set_client_side_detection_service(ClientSideDetectionService* service);
 
-  // Get/Set malware_killswitch_on_ value. These methods called on UI thread.
-  bool MalwareKillSwitchIsOn();
-  void SetMalwareKillSwitch(bool killswitch_on);
-
   // This pointer may be NULL if client-side phishing detection is disabled.
   ClientSideDetectionService* csd_service_;
   // These pointers may be NULL if SafeBrowsing is disabled.
@@ -158,6 +167,10 @@
   // Max number of urls we report for each malware IP.
   static const int kMaxUrlsPerIP;
 
+  bool should_extract_malware_features_;
+  bool should_classify_for_malware_;
+  bool onload_complete_;
+
   base::WeakPtrFactory<ClientSideDetectionHost> weak_factory_;
 
   // Unique page ID of the most recent unsafe site that was loaded in this tab
@@ -165,14 +178,6 @@
   int unsafe_unique_page_id_;
   scoped_ptr<SafeBrowsingUIManager::UnsafeResource> unsafe_resource_;
 
-  // Whether the malware IP matching feature killswitch is on.
-  // This should be accessed from UI thread.
-  bool malware_killswitch_on_;
-
-  // Whether the malware bad ip matching and report feature is enabled.
-  // This should be accessed from UI thread.
-  bool malware_report_enabled_;
-
   DISALLOW_COPY_AND_ASSIGN(ClientSideDetectionHost);
 };
 
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index 3a66f8a..784182b 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -123,6 +123,7 @@
   MOCK_METHOD2(GetValidCachedResult, bool(const GURL&, bool*));
   MOCK_METHOD1(IsInCache, bool(const GURL&));
   MOCK_METHOD0(OverPhishingReportLimit, bool());
+  MOCK_METHOD0(OverMalwareReportLimit, bool());
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockClientSideDetectionService);
@@ -159,6 +160,7 @@
 
   MOCK_METHOD1(MatchCsdWhitelistUrl, bool(const GURL&));
   MOCK_METHOD1(MatchMalwareIP, bool(const std::string& ip_address));
+  MOCK_METHOD0(IsMalwareKillSwitchOn, bool());
 
  protected:
   virtual ~MockSafeBrowsingDatabaseManager() {}
@@ -219,10 +221,6 @@
     // We need to create this here since we don't call
     // DidNavigateMainFramePostCommit in this test.
     csd_host_->browse_info_.reset(new BrowseInfo);
-
-    // By default this is set to false. Turn it on as if we are in canary or
-    // dev channel
-    csd_host_->malware_report_enabled_ = true;
   }
 
   virtual void TearDown() {
@@ -248,6 +246,10 @@
     csd_host_->OnPhishingDetectionDone(verdict_str);
   }
 
+  void DocumentOnLoadCompletedInMainFrame(int32 page_id) {
+    csd_host_->DocumentOnLoadCompletedInMainFrame(page_id);
+  }
+
   void UpdateIPUrlMap(const std::string& ip, const std::string& host) {
     csd_host_->UpdateIPUrlMap(ip, host, "", "", ResourceType::OBJECT);
   }
@@ -260,9 +262,11 @@
                                      const bool* is_private,
                                      const bool* is_incognito,
                                      const bool* match_csd_whitelist,
+                                     const bool* malware_killswitch,
                                      const bool* get_valid_cached_result,
                                      const bool* is_in_cache,
-                                     const bool* over_report_limit) {
+                                     const bool* over_phishing_report_limit,
+                                     const bool* over_malware_report_limit) {
     if (is_private) {
       EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_))
           .WillOnce(Return(*is_private));
@@ -275,6 +279,10 @@
       EXPECT_CALL(*database_manager_.get(), MatchCsdWhitelistUrl(url))
           .WillOnce(Return(*match_csd_whitelist));
     }
+    if (malware_killswitch) {
+      EXPECT_CALL(*database_manager_.get(), IsMalwareKillSwitchOn())
+          .WillRepeatedly(Return(*malware_killswitch));
+    }
     if (get_valid_cached_result) {
       EXPECT_CALL(*csd_service_, GetValidCachedResult(url, NotNull()))
           .WillOnce(DoAll(SetArgumentPointee<1>(true),
@@ -283,9 +291,13 @@
     if (is_in_cache) {
       EXPECT_CALL(*csd_service_, IsInCache(url)).WillOnce(Return(*is_in_cache));
     }
-    if (over_report_limit) {
+    if (over_phishing_report_limit) {
       EXPECT_CALL(*csd_service_, OverPhishingReportLimit())
-          .WillOnce(Return(*over_report_limit));
+          .WillOnce(Return(*over_phishing_report_limit));
+    }
+    if (over_malware_report_limit) {
+      EXPECT_CALL(*csd_service_, OverMalwareReportLimit())
+          .WillOnce(Return(*over_malware_report_limit));
     }
   }
 
@@ -310,6 +322,25 @@
     csd_host_->browse_info_->referrer = referrer;
   }
 
+  void ExpectShouldClassifyForMalwareResult(bool should_classify) {
+    EXPECT_EQ(should_classify, csd_host_->should_classify_for_malware_);
+  }
+
+  void ExpectStartPhishingDetection(const GURL* url) {
+    const IPC::Message* msg = process()->sink().GetFirstMessageMatching(
+        SafeBrowsingMsg_StartPhishingDetection::ID);
+    if (url) {
+      ASSERT_TRUE(msg);
+      Tuple1<GURL> actual_url;
+      SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
+      EXPECT_EQ(*url, actual_url.a);
+      EXPECT_EQ(rvh()->GetRoutingID(), msg->routing_id());
+      process()->sink().ClearMessages();
+    } else {
+      ASSERT_FALSE(msg);
+    }
+  }
+
   void TestUnsafeResourceCopied(const UnsafeResource& resource) {
     ASSERT_TRUE(csd_host_->unsafe_resource_.get());
     // Test that the resource from OnSafeBrowsingHit notification was copied
@@ -450,13 +481,9 @@
   verdict.set_client_score(1.0f);
   verdict.set_is_phishing(true);
 
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
   EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _))
       .WillOnce(DoAll(DeleteArg<1>(),
                       InvokeCallbackArgument<2>(true, &verdict)));
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
                   Pointee(PartiallyEqualVerdict(verdict)), _))
@@ -494,14 +521,6 @@
               SendClientReportPhishingRequest(
                   Pointee(PartiallyEqualVerdict(verdict)), _))
       .WillOnce(SaveArg<1>(&cb));
-
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
-  EXPECT_CALL(*csd_service_,
-              SendClientReportMalwareRequest(_, _)).Times(0);
-
   OnPhishingDetectionDone(verdict.SerializeAsString());
   EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
   ASSERT_FALSE(cb.is_null());
@@ -529,14 +548,9 @@
   verdict.set_client_score(1.0f);
   verdict.set_is_phishing(true);
 
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
-
   EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _))
       .WillOnce(DoAll(DeleteArg<1>(),
                       InvokeCallbackArgument<2>(true, &verdict)));
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
                   Pointee(PartiallyEqualVerdict(verdict)), _))
@@ -589,14 +603,9 @@
   verdict.set_client_score(1.0f);
   verdict.set_is_phishing(true);
 
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
-
   EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _))
       .WillOnce(DoAll(DeleteArg<1>(),
                       InvokeCallbackArgument<2>(true, &verdict)));
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
   EXPECT_CALL(*csd_service_,
               SendClientReportPhishingRequest(
                   Pointee(PartiallyEqualVerdict(verdict)), _))
@@ -613,7 +622,7 @@
                                                   csd_host_.get()));
   GURL other_phishing_url("http://other_phishing_url.com/bla");
   ExpectPreClassificationChecks(other_phishing_url, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse, &kFalse);
+                                &kFalse, &kFalse, &kFalse, &kFalse, &kFalse);
   // We navigate away.  The callback cb should be revoked.
   NavigateAndCommit(other_phishing_url);
   // Wait for the pre-classification checks to finish for other_phishing_url.
@@ -679,12 +688,7 @@
   verdict.set_client_score(0.1f);
   verdict.set_is_phishing(false);
 
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
-
   EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _)).Times(0);
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
   OnPhishingDetectionDone(verdict.SerializeAsString());
   EXPECT_TRUE(Mock::VerifyAndClear(mock_extractor));
 }
@@ -701,7 +705,7 @@
 
   // First we have to navigate to the URL to set the unique page ID.
   ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse);
+                                &kFalse, &kFalse, &kFalse, &kFalse);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
   SetUnsafeSubResourceForCurrent();
@@ -727,7 +731,8 @@
   // Do an initial navigation to a safe host.
   GURL start_url("http://safe.example.com/");
   ExpectPreClassificationChecks(
-      start_url, &kFalse, &kFalse, &kFalse, &kFalse, &kFalse, &kFalse);
+      start_url, &kFalse, &kFalse, &kFalse, &kFalse, &kFalse, &kFalse, &kFalse,
+      &kFalse);
   NavigateAndCommit(start_url);
   WaitAndCheckPreClassificationChecks();
 
@@ -740,7 +745,7 @@
   verdict.set_is_phishing(false);
 
   ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse);
+                                &kFalse, &kFalse, &kFalse, &kFalse);
   NavigateWithSBHitAndCommit(url);
   WaitAndCheckPreClassificationChecks();
 
@@ -756,11 +761,72 @@
   EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
 
   ExpectPreClassificationChecks(start_url, &kFalse, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse);
+                                &kFalse, &kFalse, &kFalse, &kFalse);
   NavigateWithoutSBHitAndCommit(start_url);
   WaitAndCheckPreClassificationChecks();
 }
 
+TEST_F(ClientSideDetectionHostTest,
+       DocumentOnLoadCompletedInMainFrameShowMalwareInterstitial) {
+  // Case 9: client thinks the page match malware IP and so does the server.
+  // We show an sub-resource malware interstitial.
+  MockBrowserFeatureExtractor* mock_extractor =
+      new StrictMock<MockBrowserFeatureExtractor>(
+          web_contents(),
+          csd_host_.get());
+  SetFeatureExtractor(mock_extractor);  // The host class takes ownership.
+
+  GURL malware_landing_url("http://malware.com/");
+  GURL malware_ip_url("http://badip.com");
+  ClientMalwareRequest malware_verdict;
+  malware_verdict.set_url("http://malware.com/");
+  ClientMalwareRequest::UrlInfo* badipurl =
+      malware_verdict.add_bad_ip_url_info();
+  badipurl->set_ip("1.2.3.4");
+  badipurl->set_url("http://badip.com");
+
+  ExpectPreClassificationChecks(GURL(malware_verdict.url()), &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse);
+  NavigateAndCommit(GURL(malware_verdict.url()));
+  WaitAndCheckPreClassificationChecks();
+
+  ClientSideDetectionService::ClientReportMalwareRequestCallback cb;
+  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
+      .WillOnce(InvokeMalwareCallback(&malware_verdict));
+  EXPECT_CALL(*csd_service_,
+              SendClientReportMalwareRequest(
+                  Pointee(PartiallyEqualMalwareVerdict(malware_verdict)), _))
+      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb)));
+  DocumentOnLoadCompletedInMainFrame(GetBrowseInfo()->page_id);
+  EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
+  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
+  ASSERT_FALSE(cb.is_null());
+
+  UnsafeResource resource;
+  EXPECT_CALL(*ui_manager_.get(), DisplayBlockingPage(_))
+      .WillOnce(SaveArg<0>(&resource));
+  cb.Run(malware_landing_url, malware_ip_url, true);
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(Mock::VerifyAndClear(ui_manager_.get()));
+  EXPECT_EQ(malware_ip_url, resource.url);
+  EXPECT_EQ(malware_landing_url, resource.original_url);
+  EXPECT_TRUE(resource.is_subresource);
+  EXPECT_EQ(SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL, resource.threat_type);
+  EXPECT_EQ(web_contents()->GetRenderProcessHost()->GetID(),
+            resource.render_process_host_id);
+  EXPECT_EQ(web_contents()->GetRenderViewHost()->GetRoutingID(),
+            resource.render_view_id);
+
+  // Make sure the client object will be deleted.
+  BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
+                 ui_manager_, resource.callback));
+}
+
 TEST_F(ClientSideDetectionHostTest, UpdateIPUrlMap) {
   BrowseInfo* browse_info = GetBrowseInfo();
 
@@ -819,180 +885,6 @@
                   browse_info->ips["100.100.100.256"]);
 }
 
-TEST_F(ClientSideDetectionHostTest,
-       OnPhishingDetectionDoneVerdictNotPhishingNotMalwareIP) {
-  // Case 7: renderer sends a verdict string that isn't phishing and not matches
-  // malware bad IP list
-  MockBrowserFeatureExtractor* mock_extractor =
-      new StrictMock<MockBrowserFeatureExtractor>(
-          web_contents(),
-          csd_host_.get());
-  SetFeatureExtractor(mock_extractor);  // The host class takes ownership.
-
-  ClientPhishingRequest verdict;
-  verdict.set_url("http://not-phishing.com/");
-  verdict.set_client_score(0.1f);
-  verdict.set_is_phishing(false);
-
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
-
-  // That is a special case.  If there were no IP matches or if feature
-  // extraction failed the callback will delete the malware_verdict.
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
-  EXPECT_CALL(*csd_service_,
-              SendClientReportMalwareRequest(_, _)).Times(0);
-  EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _)).Times(0);
-
-  OnPhishingDetectionDone(verdict.SerializeAsString());
-  EXPECT_TRUE(Mock::VerifyAndClear(mock_extractor));
-}
-
-TEST_F(ClientSideDetectionHostTest,
-       OnPhishingDetectionDoneVerdictNotPhishingButMalwareIP) {
-  // Case 8: renderer sends a verdict string that isn't phishing but matches
-  // malware bad IP list
-  MockBrowserFeatureExtractor* mock_extractor =
-      new StrictMock<MockBrowserFeatureExtractor>(
-          web_contents(),
-          csd_host_.get());
-  SetFeatureExtractor(mock_extractor);  // The host class takes ownership.
-
-  ClientPhishingRequest verdict;
-  verdict.set_url("http://not-phishing.com/");
-  verdict.set_client_score(0.1f);
-  verdict.set_is_phishing(false);
-
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
-  malware_verdict.set_referrer_url("http://referrer.com/");
-  ClientMalwareRequest::UrlInfo* badipurl =
-      malware_verdict.add_bad_ip_url_info();
-  badipurl->set_ip("1.2.3.4");
-  badipurl->set_url("badip.com");
-
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
-  EXPECT_CALL(*csd_service_,
-              SendClientReportMalwareRequest(
-                  Pointee(PartiallyEqualMalwareVerdict(malware_verdict)), _))
-      .WillOnce(DeleteArg<0>());
-  EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _)).Times(0);
-
-  SetReferrer(GURL("http://referrer.com/"));
-  OnPhishingDetectionDone(verdict.SerializeAsString());
-  EXPECT_TRUE(Mock::VerifyAndClear(mock_extractor));
-}
-
-TEST_F(ClientSideDetectionHostTest,
-       OnPhishingDetectionDoneVerdictPhishingAndMalwareIP) {
-  // Case 9: renderer sends a verdict string that is phishing and matches
-  // malware bad IP list
-  MockBrowserFeatureExtractor* mock_extractor =
-      new StrictMock<MockBrowserFeatureExtractor>(
-          web_contents(),
-          csd_host_.get());
-  SetFeatureExtractor(mock_extractor);  // The host class takes ownership.
-
-  ClientSideDetectionService::ClientReportPhishingRequestCallback cb;
-  ClientPhishingRequest verdict;
-  verdict.set_url("http://not-phishing.com/");
-  verdict.set_client_score(0.1f);
-  verdict.set_is_phishing(true);
-
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url(verdict.url());
-  ClientMalwareRequest::UrlInfo* badipurl =
-      malware_verdict.add_bad_ip_url_info();
-  badipurl->set_ip("1.2.3.4");
-  badipurl->set_url("badip.com");
-
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
-  EXPECT_CALL(*csd_service_,
-              SendClientReportMalwareRequest(
-                  Pointee(PartiallyEqualMalwareVerdict(malware_verdict)), _))
-      .WillOnce(DeleteArg<0>());
-
-  EXPECT_CALL(*mock_extractor, ExtractFeatures(_, _, _))
-      .WillOnce(DoAll(DeleteArg<1>(),
-                      InvokeCallbackArgument<2>(true, &verdict)));
-
-  EXPECT_CALL(*csd_service_,
-              SendClientReportPhishingRequest(
-                  Pointee(PartiallyEqualVerdict(verdict)), _))
-      .WillOnce(SaveArg<1>(&cb));
-
-  // Referrer url using https won't be set and sent out.
-  SetReferrer(GURL("https://referrer.com/"));
-  OnPhishingDetectionDone(verdict.SerializeAsString());
-  EXPECT_TRUE(Mock::VerifyAndClear(mock_extractor));
-  EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
-  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
-  ASSERT_FALSE(cb.is_null());
-}
-
-TEST_F(ClientSideDetectionHostTest,
-       OnPhishingDetectionDoneShowMalwareInterstitial) {
-  // Case 10: client thinks the page match malware IP and so does the server.
-  // We show an sub-resource malware interstitial.
-  MockBrowserFeatureExtractor* mock_extractor =
-      new StrictMock<MockBrowserFeatureExtractor>(
-          web_contents(),
-          csd_host_.get());
-  SetFeatureExtractor(mock_extractor);  // The host class takes ownership.
-
-  ClientPhishingRequest verdict;
-  verdict.set_url("http://not-phishing.com/");
-  verdict.set_client_score(0.1f);
-  verdict.set_is_phishing(false);
-
-  ClientSideDetectionService::ClientReportMalwareRequestCallback cb;
-  GURL malware_landing_url("http://malware.com/");
-  GURL malware_ip_url("http://badip.com");
-  ClientMalwareRequest malware_verdict;
-  malware_verdict.set_url("http://malware.com/");
-  ClientMalwareRequest::UrlInfo* badipurl =
-      malware_verdict.add_bad_ip_url_info();
-  badipurl->set_ip("1.2.3.4");
-  badipurl->set_url("http://badip.com");
-
-  EXPECT_CALL(*mock_extractor, ExtractMalwareFeatures(_, _, _))
-      .WillOnce(InvokeMalwareCallback(&malware_verdict));
-  EXPECT_CALL(*csd_service_,
-              SendClientReportMalwareRequest(
-                  Pointee(PartiallyEqualMalwareVerdict(malware_verdict)), _))
-      .WillOnce(DoAll(DeleteArg<0>(), SaveArg<1>(&cb)));
-  OnPhishingDetectionDone(verdict.SerializeAsString());
-  EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
-  EXPECT_TRUE(Mock::VerifyAndClear(csd_service_.get()));
-  ASSERT_FALSE(cb.is_null());
-
-  UnsafeResource resource;
-  EXPECT_CALL(*ui_manager_.get(), DisplayBlockingPage(_))
-      .WillOnce(SaveArg<0>(&resource));
-  cb.Run(malware_landing_url, malware_ip_url, true);
-
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(Mock::VerifyAndClear(ui_manager_.get()));
-  EXPECT_EQ(malware_ip_url, resource.url);
-  EXPECT_EQ(malware_landing_url, resource.original_url);
-  EXPECT_TRUE(resource.is_subresource);
-  EXPECT_EQ(SB_THREAT_TYPE_CLIENT_SIDE_MALWARE_URL, resource.threat_type);
-  EXPECT_EQ(web_contents()->GetRenderProcessHost()->GetID(),
-            resource.render_process_host_id);
-  EXPECT_EQ(web_contents()->GetRenderViewHost()->GetRoutingID(),
-            resource.render_view_id);
-
-  // Make sure the client object will be deleted.
-  BrowserThread::PostTask(
-      BrowserThread::IO,
-      FROM_HERE,
-      base::Bind(&MockSafeBrowsingUIManager::InvokeOnBlockingPageComplete,
-                 ui_manager_, resource.callback));
-}
-
 TEST_F(ClientSideDetectionHostTest, NavigationCancelsShouldClassifyUrl) {
   // Test that canceling pending should classify requests works as expected.
 
@@ -1006,10 +898,10 @@
   EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_))
       .WillOnce(Return(false))
       .WillOnce(Return(false));
-  ExpectPreClassificationChecks(first_url, NULL, &kFalse, &kFalse, NULL,
-                                NULL, NULL);
+  ExpectPreClassificationChecks(first_url, NULL, &kFalse, &kFalse, &kFalse,
+                                NULL, NULL, NULL, NULL);
   ExpectPreClassificationChecks(second_url, NULL, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse);
+                                &kFalse, &kFalse, &kFalse, &kFalse);
 
   NavigateAndCommit(first_url);
   // Don't flush the message loop, as we want to navigate to a different
@@ -1018,156 +910,243 @@
   WaitAndCheckPreClassificationChecks();
 }
 
-TEST_F(ClientSideDetectionHostTest, ShouldClassifyUrl) {
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckPass) {
   // Navigate the tab to a page.  We should see a StartPhishingDetection IPC.
   GURL url("http://host.com/");
   ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse);
+                                &kFalse, &kFalse, &kFalse, &kFalse);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
 
-  const IPC::Message* msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_TRUE(msg);
-  Tuple1<GURL> actual_url;
-  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
-  EXPECT_EQ(url, actual_url.a);
-  EXPECT_EQ(rvh()->GetRoutingID(), msg->routing_id());
-  process()->sink().ClearMessages();
+  ExpectStartPhishingDetection(&url);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest,
+       TestPreClassificationCheckInPageNavigation) {
+  GURL url("http://host.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kFalse, &kFalse);
+  NavigateAndCommit(url);
+  WaitAndCheckPreClassificationChecks();
+
+  ExpectStartPhishingDetection(&url);
+  ExpectShouldClassifyForMalwareResult(true);
 
   // Now try an in-page navigation.  This should not trigger an IPC.
   EXPECT_CALL(*csd_service_, IsPrivateIPAddress(_)).Times(0);
-  url = GURL("http://host.com/#foo");
-  ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL);
-  NavigateAndCommit(url);
+  GURL inpage("http://host.com/#foo");
+  ExpectPreClassificationChecks(inpage, NULL, NULL, NULL, NULL, NULL, NULL,
+                                NULL, NULL);
+  NavigateAndCommit(inpage);
   WaitAndCheckPreClassificationChecks();
 
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_FALSE(msg);
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(true);
+}
 
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckXHTML) {
   // Check that XHTML is supported, in addition to the default HTML type.
-  // Note: for this test to work correctly, the new URL must be on the
-  // same domain as the previous URL, otherwise it will create a new
-  // RenderViewHost that won't have the mime type set.
-  url = GURL("http://host.com/xhtml");
+  GURL url("http://host.com/xhtml");
   rvh_tester()->SetContentsMimeType("application/xhtml+xml");
   ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse);
+                                &kFalse, &kFalse, &kFalse, &kFalse);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_TRUE(msg);
-  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
-  EXPECT_EQ(url, actual_url.a);
-  EXPECT_EQ(rvh()->GetRoutingID(), msg->routing_id());
-  process()->sink().ClearMessages();
 
-  // Navigate to a new host, which should cause another IPC.
-  url = GURL("http://host2.com/");
-  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kFalse);
-  NavigateAndCommit(url);
+  ExpectStartPhishingDetection(&url);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckTwoNavigations) {
+  // Navigate to two hosts, which should cause two IPCs.
+  GURL url1("http://host1.com/");
+  ExpectPreClassificationChecks(url1, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kFalse, &kFalse);
+  NavigateAndCommit(url1);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_TRUE(msg);
-  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
-  EXPECT_EQ(url, actual_url.a);
-  EXPECT_EQ(rvh()->GetRoutingID(), msg->routing_id());
-  process()->sink().ClearMessages();
 
-  // If the mime type is not one that we support, no IPC should be triggered.
+  ExpectStartPhishingDetection(&url1);
+  ExpectShouldClassifyForMalwareResult(true);
+
+  GURL url2("http://host2.com/");
+  ExpectPreClassificationChecks(url2, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kFalse, &kFalse);
+  NavigateAndCommit(url2);
+  WaitAndCheckPreClassificationChecks();
+
+  ExpectStartPhishingDetection(&url2);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckMimeType) {
+  // If the mime type is not one that we support, no IPC should be triggered
+  // but all pre-classification checks should run because we might classify
+  // other mime types for malware.
   // Note: for this test to work correctly, the new URL must be on the
   // same domain as the previous URL, otherwise it will create a new
   // RenderViewHost that won't have the mime type set.
-  url = GURL("http://host2.com/image.jpg");
+  GURL url("http://host2.com/image.jpg");
   rvh_tester()->SetContentsMimeType("image/jpeg");
-  ExpectPreClassificationChecks(url, NULL, NULL, NULL, NULL, NULL, NULL);
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kFalse,&kFalse, &kFalse);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_FALSE(msg);
 
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest,
+       TestPreClassificationCheckPrivateIpAddress) {
   // If IsPrivateIPAddress returns true, no IPC should be triggered.
-  url = GURL("http://host3.com/");
-  ExpectPreClassificationChecks(url, &kTrue, NULL, NULL, NULL, NULL, NULL);
+  GURL url("http://host3.com/");
+  ExpectPreClassificationChecks(url, &kTrue, &kFalse, NULL, NULL, NULL, NULL,
+                                NULL, NULL);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
+  const IPC::Message* msg = process()->sink().GetFirstMessageMatching(
       SafeBrowsingMsg_StartPhishingDetection::ID);
   ASSERT_FALSE(msg);
+  ExpectShouldClassifyForMalwareResult(false);
+}
 
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckIncognito) {
   // If the tab is incognito there should be no IPC.  Also, we shouldn't
   // even check the csd-whitelist.
-  url = GURL("http://host4.com/");
-  ExpectPreClassificationChecks(url, &kFalse, &kTrue, NULL, NULL, NULL, NULL);
+  GURL url("http://host4.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kTrue, NULL, NULL, NULL, NULL,
+                                NULL, NULL);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_FALSE(msg);
 
-  // If the URL is on the csd whitelist, no IPC should be triggered.
-  url = GURL("http://host5.com/");
-  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kTrue, NULL, NULL,
-                                NULL);
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(false);
+}
+
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckCsdWhitelist) {
+  // If the URL is on the csd whitelist no phishing IPC should be sent
+  // but we should classify the URL for malware.
+  GURL url("http://host5.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kTrue, &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kFalse);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_FALSE(msg);
 
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest,
+       TestPreClassificationCheckMalwareKillSwitch) {
+  // If the malware killswitch is on we shouldn't classify the page for malware.
+  GURL url("http://host5.com/kill-switch");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kTrue, &kFalse,
+                                &kFalse, &kFalse, &kFalse);
+  NavigateAndCommit(url);
+  WaitAndCheckPreClassificationChecks();
+
+  ExpectStartPhishingDetection(&url);
+  ExpectShouldClassifyForMalwareResult(false);
+}
+
+TEST_F(ClientSideDetectionHostTest,
+       TestPreClassificationCheckKillswitchAndCsdWhitelist) {
+  // If both the malware kill-swtich is on and the URL is on the csd whitelist,
+  // we will leave pre-classification checks early.
+  GURL url("http://host5.com/kill-switch-and-whitelisted");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kTrue, &kTrue, NULL,
+                                NULL, NULL, NULL);
+  NavigateAndCommit(url);
+  WaitAndCheckPreClassificationChecks();
+
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(false);
+}
+
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckInvalidCache) {
   // If item is in the cache but it isn't valid, we will classify regardless
   // of whether we are over the reporting limit.
-  url = GURL("http://host6.com/");
-  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, &kTrue,
-                                NULL);
+  GURL url("http://host6.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kTrue, NULL, &kFalse);
+
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_TRUE(msg);
-  SafeBrowsingMsg_StartPhishingDetection::Read(msg, &actual_url);
-  EXPECT_EQ(url, actual_url.a);
-  EXPECT_EQ(rvh()->GetRoutingID(), msg->routing_id());
-  process()->sink().ClearMessages();
 
+  ExpectStartPhishingDetection(&url);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest,
+       TestPreClassificationCheckOverPhishingReportingLimit) {
   // If the url isn't in the cache and we are over the reporting limit, we
   // don't do classification.
-  url = GURL("http://host7.com/");
+  GURL url("http://host7.com/");
   ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
-                                &kFalse, &kTrue);
+                                &kFalse, &kFalse, &kTrue, &kFalse);
   NavigateAndCommit(url);
   WaitAndCheckPreClassificationChecks();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_FALSE(msg);
 
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest,
+       TestPreClassificationCheckOverMalwareReportingLimit) {
+  GURL url("http://host.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kFalse, &kTrue);
+  NavigateAndCommit(url);
+  WaitAndCheckPreClassificationChecks();
+
+  ExpectStartPhishingDetection(&url);
+  ExpectShouldClassifyForMalwareResult(false);
+}
+
+TEST_F(ClientSideDetectionHostTest,
+       TestPreClassificationCheckOverBothReportingLimits) {
+  GURL url("http://host.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kTrue, &kTrue);
+  NavigateAndCommit(url);
+  WaitAndCheckPreClassificationChecks();
+
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(false);
+}
+
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckHttpsUrl) {
+  GURL url("https://host.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse,
+                                &kFalse, &kFalse, &kFalse, &kFalse);
+  NavigateAndCommit(url);
+  WaitAndCheckPreClassificationChecks();
+
+  ExpectStartPhishingDetection(NULL);
+  ExpectShouldClassifyForMalwareResult(true);
+}
+
+TEST_F(ClientSideDetectionHostTest, TestPreClassificationCheckValidCached) {
   // If result is cached, we will try and display the blocking page directly
   // with no start classification message.
-  url = GURL("http://host8.com/");
-  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kTrue, NULL,
-                                NULL);
+  GURL url("http://host8.com/");
+  ExpectPreClassificationChecks(url, &kFalse, &kFalse, &kFalse, &kFalse, &kTrue,
+                                &kFalse, &kFalse, &kFalse);
 
   UnsafeResource resource;
   EXPECT_CALL(*ui_manager_.get(), DisplayBlockingPage(_))
       .WillOnce(SaveArg<0>(&resource));
 
   NavigateAndCommit(url);
-  // Wait for CheckCsdWhitelist and CheckCache() to be called.
-  base::RunLoop().RunUntilIdle();
-  // Now we check that all expected functions were indeed called on the two
-  // service objects.
-  EXPECT_TRUE(Mock::VerifyAndClear(csd_host_.get()));
-  EXPECT_TRUE(Mock::VerifyAndClear(ui_manager_.get()));
+  WaitAndCheckPreClassificationChecks();
   EXPECT_EQ(url, resource.url);
   EXPECT_EQ(url, resource.original_url);
-  resource.callback.Reset();
-  msg = process()->sink().GetFirstMessageMatching(
-      SafeBrowsingMsg_StartPhishingDetection::ID);
-  ASSERT_FALSE(msg);
+
+  ExpectStartPhishingDetection(NULL);
+
+  // Showing a phishing warning will invalidate all the weak pointers which
+  // means we will not extract malware features.
+  ExpectShouldClassifyForMalwareResult(false);
 }
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc
index d63e45c..d045bd9 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -368,15 +368,6 @@
     return;
   }
 
-  if (OverMalwareReportLimit()) {
-    UpdateEnumUMAHistogram(REPORT_HIT_LIMIT);
-    DVLOG(1) << "Too many malware report requests sent recently."
-             << "Skip sending malware report for " << GURL(request->url());
-    if (!callback.is_null())
-      callback.Run(GURL(request->url()), GURL(request->url()), false);
-    return;
-  }
-
   std::string request_data;
   if (!request->SerializeToString(&request_data)) {
     UpdateEnumUMAHistogram(REPORT_FAILED_SERIALIZATION);
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
index b5f64d5..5762847 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
@@ -472,25 +472,22 @@
                                  net::URLRequestStatus::FAILED);
   EXPECT_FALSE(SendClientReportMalwareRequest(url));
 
-  // server blacklist decision is false, and response is succesful
+  // Server blacklist decision is false, and response is successful
   response.set_blacklist(false);
   SetClientReportMalwareResponse(response.SerializeAsString(), net::HTTP_OK,
                                  net::URLRequestStatus::SUCCESS);
   EXPECT_FALSE(SendClientReportMalwareRequest(url));
 
-  // Check that we have recorded all 4 requests within the correct time range.
+  // Check that we have recorded all 5 requests within the correct time range.
   base::Time after = base::Time::Now();
   std::queue<base::Time>& report_times = GetMalwareReportTimes();
-  EXPECT_EQ(4U, report_times.size());
+  EXPECT_EQ(5U, report_times.size());
 
-  // Another normal behavior will fail because of the limit is hit
-  response.set_blacklist(true);
-  SetClientReportMalwareResponse(response.SerializeAsString(), net::HTTP_OK,
-                                 net::URLRequestStatus::SUCCESS);
-  EXPECT_FALSE(SendClientReportMalwareRequest(url));
+  // Check that the malware report limit was reached.
+  EXPECT_TRUE(csd_service_->OverMalwareReportLimit());
 
   report_times = GetMalwareReportTimes();
-  EXPECT_EQ(4U, report_times.size());
+  EXPECT_EQ(5U, report_times.size());
   while (!report_times.empty()) {
     base::Time time = report_times.back();
     report_times.pop();
diff --git a/chrome/browser/safe_browsing/download_protection_service.cc b/chrome/browser/safe_browsing/download_protection_service.cc
index 8a9f6e1..abdcb0f 100644
--- a/chrome/browser/safe_browsing/download_protection_service.cc
+++ b/chrome/browser/safe_browsing/download_protection_service.cc
@@ -18,10 +18,12 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "base/time/time.h"
+#include "chrome/browser/history/history_service.h"
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/safe_browsing/binary_feature_extractor.h"
 #include "chrome/browser/safe_browsing/download_feedback_service.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
 #include "chrome/browser/safe_browsing/sandboxed_zip_analyzer.h"
-#include "chrome/browser/safe_browsing/signature_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/common/safe_browsing/csd.pb.h"
@@ -280,14 +282,16 @@
       const CheckDownloadCallback& callback,
       DownloadProtectionService* service,
       const scoped_refptr<SafeBrowsingDatabaseManager>& database_manager,
-      SignatureUtil* signature_util)
+      BinaryFeatureExtractor* binary_feature_extractor)
       : item_(item),
         url_chain_(item->GetUrlChain()),
         referrer_url_(item->GetReferrerUrl()),
+        tab_url_(item->GetTabUrl()),
+        tab_referrer_url_(item->GetTabReferrerUrl()),
         zipped_executable_(false),
         callback_(callback),
         service_(service),
-        signature_util_(signature_util),
+        binary_feature_extractor_(binary_feature_extractor),
         database_manager_(database_manager),
         pingback_enabled_(service_->enabled()),
         finished_(false),
@@ -335,7 +339,7 @@
     } else {
       DCHECK(!download_protection_util::IsArchiveFile(
           item_->GetTargetFilePath()));
-      StartExtractSignatureFeatures();
+      StartExtractFileFeatures();
     }
   }
 
@@ -496,21 +500,21 @@
         base::Bind(&CheckClientDownloadRequest::StartTimeout, this));
   }
 
-  void StartExtractSignatureFeatures() {
+  void StartExtractFileFeatures() {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     DCHECK(item_);  // Called directly from Start(), item should still exist.
     // Since we do blocking I/O, offload this to a worker thread.
     // The task does not need to block shutdown.
     BrowserThread::GetBlockingPool()->PostWorkerTaskWithShutdownBehavior(
         FROM_HERE,
-        base::Bind(&CheckClientDownloadRequest::ExtractSignatureFeatures,
+        base::Bind(&CheckClientDownloadRequest::ExtractFileFeatures,
                    this, item_->GetFullPath()),
         base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
   }
 
-  void ExtractSignatureFeatures(const base::FilePath& file_path) {
+  void ExtractFileFeatures(const base::FilePath& file_path) {
     base::TimeTicks start_time = base::TimeTicks::Now();
-    signature_util_->CheckSignature(file_path, &signature_info_);
+    binary_feature_extractor_->CheckSignature(file_path, &signature_info_);
     bool is_signed = (signature_info_.certificate_chain_size() > 0);
     if (is_signed) {
       VLOG(2) << "Downloaded a signed binary: " << file_path.value();
@@ -522,6 +526,11 @@
     UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractSignatureFeaturesTime",
                         base::TimeTicks::Now() - start_time);
 
+    start_time = base::TimeTicks::Now();
+    binary_feature_extractor_->ExtractImageHeaders(file_path, &image_headers_);
+    UMA_HISTOGRAM_TIMES("SBClientDownload.ExtractImageHeadersTime",
+                        base::TimeTicks::Now() - start_time);
+
     OnFileFeatureExtractionDone();
   }
 
@@ -602,13 +611,53 @@
       BrowserThread::PostTask(
           BrowserThread::UI,
           FROM_HERE,
-          base::Bind(&CheckClientDownloadRequest::SendRequest, this));
+          base::Bind(&CheckClientDownloadRequest::GetTabRedirects, this));
 #else
       PostFinishTask(SAFE, REASON_OS_NOT_SUPPORTED);
 #endif
     }
   }
 
+  void GetTabRedirects() {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    if (!tab_url_.is_valid()) {
+      SendRequest();
+      return;
+    }
+
+    Profile* profile = Profile::FromBrowserContext(item_->GetBrowserContext());
+    HistoryService* history =
+        HistoryServiceFactory::GetForProfile(profile, Profile::EXPLICIT_ACCESS);
+    if (!history) {
+      SendRequest();
+      return;
+    }
+
+    history->QueryRedirectsTo(
+        tab_url_,
+        &request_consumer_,
+        base::Bind(&CheckClientDownloadRequest::OnGotTabRedirects,
+                   base::Unretained(this)));
+  }
+
+  void OnGotTabRedirects(HistoryService::Handle handle,
+                         GURL url,
+                         bool success,
+                         history::RedirectList* redirect_list) {
+    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_EQ(url, tab_url_);
+
+    if (success && redirect_list->size() > 0) {
+      for (history::RedirectList::reverse_iterator i = redirect_list->rbegin();
+           i != redirect_list->rend();
+           ++i) {
+        tab_redirects_.push_back(*i);
+      }
+    }
+
+    SendRequest();
+  }
+
   void SendRequest() {
     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
 
@@ -628,19 +677,42 @@
         // The last URL in the chain is the download URL.
         resource->set_type(ClientDownloadRequest::DOWNLOAD_URL);
         resource->set_referrer(item_->GetReferrerUrl().spec());
+        DVLOG(2) << "dl url " << resource->url();
         if (!item_->GetRemoteAddress().empty()) {
           resource->set_remote_ip(item_->GetRemoteAddress());
+          DVLOG(2) << "  dl url remote addr: " << resource->remote_ip();
         }
+        DVLOG(2) << "dl referrer " << resource->referrer();
       } else {
+        DVLOG(2) << "dl redirect " << i << " " << resource->url();
         resource->set_type(ClientDownloadRequest::DOWNLOAD_REDIRECT);
       }
       // TODO(noelutz): fill out the remote IP addresses.
     }
+    // TODO(mattm): fill out the remote IP addresses for tab resources.
+    for (size_t i = 0; i < tab_redirects_.size(); ++i) {
+      ClientDownloadRequest::Resource* resource = request.add_resources();
+      DVLOG(2) << "tab redirect " << i << " " << tab_redirects_[i].spec();
+      resource->set_url(tab_redirects_[i].spec());
+      resource->set_type(ClientDownloadRequest::TAB_REDIRECT);
+    }
+    if (tab_url_.is_valid()) {
+      ClientDownloadRequest::Resource* resource = request.add_resources();
+      resource->set_url(tab_url_.spec());
+      DVLOG(2) << "tab url " << resource->url();
+      resource->set_type(ClientDownloadRequest::TAB_URL);
+      if (tab_referrer_url_.is_valid()) {
+        resource->set_referrer(tab_referrer_url_.spec());
+        DVLOG(2) << "tab referrer " << resource->referrer();
+      }
+    }
+
     request.set_user_initiated(item_->HasUserGesture());
     request.set_file_basename(
         item_->GetTargetFilePath().BaseName().AsUTF8Unsafe());
     request.set_download_type(type_);
     request.mutable_signature()->CopyFrom(signature_info_);
+    request.mutable_image_headers()->CopyFrom(image_headers_);
     if (!request.SerializeToString(&client_download_request_data_)) {
       FinishRequest(SAFE, REASON_INVALID_REQUEST_PROTO);
       return;
@@ -747,13 +819,19 @@
   // Copies of data from |item_| for access on other threads.
   std::vector<GURL> url_chain_;
   GURL referrer_url_;
+  // URL chain of redirects leading to (but not including) |tab_url|.
+  std::vector<GURL> tab_redirects_;
+  // URL and referrer of the window the download was started from.
+  GURL tab_url_;
+  GURL tab_referrer_url_;
 
   bool zipped_executable_;
   ClientDownloadRequest_SignatureInfo signature_info_;
+  ClientDownloadRequest_ImageHeaders image_headers_;
   CheckDownloadCallback callback_;
   // Will be NULL if the request has been canceled.
   DownloadProtectionService* service_;
-  scoped_refptr<SignatureUtil> signature_util_;
+  scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_;
   scoped_refptr<SafeBrowsingDatabaseManager> database_manager_;
   const bool pingback_enabled_;
   scoped_ptr<net::URLFetcher> fetcher_;
@@ -762,6 +840,7 @@
   bool finished_;
   ClientDownloadRequest::DownloadType type_;
   std::string client_download_request_data_;
+  CancelableRequestConsumer request_consumer_;  // For HistoryService lookup.
   base::WeakPtrFactory<CheckClientDownloadRequest> weakptr_factory_;
   base::TimeTicks start_time_;  // Used for stats.
 
@@ -773,7 +852,7 @@
     net::URLRequestContextGetter* request_context_getter)
     : request_context_getter_(request_context_getter),
       enabled_(false),
-      signature_util_(new SignatureUtil()),
+      binary_feature_extractor_(new BinaryFeatureExtractor()),
       download_request_timeout_ms_(kDownloadRequestTimeoutMs),
       feedback_service_(new DownloadFeedbackService(
           request_context_getter, BrowserThread::GetBlockingPool())) {
@@ -805,7 +884,8 @@
     const CheckDownloadCallback& callback) {
   scoped_refptr<CheckClientDownloadRequest> request(
       new CheckClientDownloadRequest(item, callback, this,
-                                     database_manager_, signature_util_.get()));
+                                     database_manager_,
+                                     binary_feature_extractor_.get()));
   download_requests_.insert(request);
   request->Start();
 }
diff --git a/chrome/browser/safe_browsing/download_protection_service.h b/chrome/browser/safe_browsing/download_protection_service.h
index 609fdcf..0b5f69f 100644
--- a/chrome/browser/safe_browsing/download_protection_service.h
+++ b/chrome/browser/safe_browsing/download_protection_service.h
@@ -34,7 +34,7 @@
 
 namespace safe_browsing {
 class DownloadFeedbackService;
-class SignatureUtil;
+class BinaryFeatureExtractor;
 
 // This class provides an asynchronous API to check whether a particular
 // client download is malicious or not.
@@ -190,8 +190,8 @@
   // Keeps track of the state of the service.
   bool enabled_;
 
-  // SignatureUtil object, may be overridden for testing.
-  scoped_refptr<SignatureUtil> signature_util_;
+  // BinaryFeatureExtractor object, may be overridden for testing.
+  scoped_refptr<BinaryFeatureExtractor> binary_feature_extractor_;
 
   int64 download_request_timeout_ms_;
 
diff --git a/chrome/browser/safe_browsing/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
index ee82e27..5692a10 100644
--- a/chrome/browser/safe_browsing/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection_service_unittest.cc
@@ -20,11 +20,14 @@
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/history/history_service.h"
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/safe_browsing/binary_feature_extractor.h"
 #include "chrome/browser/safe_browsing/database_manager.h"
 #include "chrome/browser/safe_browsing/download_feedback_service.h"
 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
-#include "chrome/browser/safe_browsing/signature_util.h"
 #include "chrome/common/safe_browsing/csd.pb.h"
+#include "chrome/test/base/testing_profile.h"
 #include "content/public/test/mock_download_item.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
@@ -95,17 +98,48 @@
   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingService);
 };
 
-class MockSignatureUtil : public SignatureUtil {
+class MockBinaryFeatureExtractor : public BinaryFeatureExtractor {
  public:
-  MockSignatureUtil() {}
+  MockBinaryFeatureExtractor() {}
   MOCK_METHOD2(CheckSignature, void (const base::FilePath&,
                                      ClientDownloadRequest_SignatureInfo*));
+  MOCK_METHOD2(ExtractImageHeaders, void (const base::FilePath&,
+                                          ClientDownloadRequest_ImageHeaders*));
 
  protected:
-  virtual ~MockSignatureUtil() {}
+  virtual ~MockBinaryFeatureExtractor() {}
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(MockSignatureUtil);
+  DISALLOW_COPY_AND_ASSIGN(MockBinaryFeatureExtractor);
+};
+
+class TestURLFetcherWatcher : public net::TestURLFetcherDelegateForTests {
+ public:
+  explicit TestURLFetcherWatcher(net::TestURLFetcherFactory* factory)
+      : factory_(factory), fetcher_id_(-1) {
+    factory_->SetDelegateForTests(this);
+  }
+  ~TestURLFetcherWatcher() {
+    factory_->SetDelegateForTests(NULL);
+  }
+
+  // TestURLFetcherDelegateForTests impl:
+  virtual void OnRequestStart(int fetcher_id) OVERRIDE {
+    fetcher_id_ = fetcher_id;
+    run_loop_.Quit();
+  }
+  virtual void OnChunkUpload(int fetcher_id) OVERRIDE {}
+  virtual void OnRequestEnd(int fetcher_id) OVERRIDE {}
+
+  int WaitForRequest() {
+    run_loop_.Run();
+    return fetcher_id_;
+  }
+
+ private:
+  net::TestURLFetcherFactory* factory_;
+  int fetcher_id_;
+  base::RunLoop run_loop_;
 };
 }  // namespace
 
@@ -113,6 +147,10 @@
   arg1->add_certificate_chain()->add_element()->set_certificate(contents);
 }
 
+ACTION_P(SetDosHeaderContents, contents) {
+  arg1->mutable_pe_headers()->set_dos_header(contents);
+}
+
 ACTION_P(TrustSignature, certificate_file) {
   arg1->set_trusted(true);
   // Add a certificate chain.  Note that we add the certificate twice so that
@@ -161,9 +199,9 @@
     // to test that we're on the correct thread work.
     sb_service_ = new StrictMock<FakeSafeBrowsingService>();
     sb_service_->Initialize();
-    signature_util_ = new StrictMock<MockSignatureUtil>();
+    binary_feature_extractor_ = new StrictMock<MockBinaryFeatureExtractor>();
     download_service_ = sb_service_->download_protection_service();
-    download_service_->signature_util_ = signature_util_;
+    download_service_->binary_feature_extractor_ = binary_feature_extractor_;
     download_service_->SetEnabled(true);
     base::RunLoop().RunUntilIdle();
     has_result_ = false;
@@ -311,7 +349,7 @@
 
  protected:
   scoped_refptr<FakeSafeBrowsingService> sb_service_;
-  scoped_refptr<MockSignatureUtil> signature_util_;
+  scoped_refptr<MockBinaryFeatureExtractor> binary_feature_extractor_;
   DownloadProtectionService* download_service_;
   DownloadProtectionService::DownloadCheckResult result_;
   bool has_result_;
@@ -333,6 +371,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   download_service_->CheckClientDownload(
       &item,
       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
@@ -348,6 +389,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   download_service_->CheckClientDownload(
       &item,
       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
@@ -379,11 +423,17 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
   EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(""));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(a_tmp, _)).Times(4);
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
+      .Times(4);
+  EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
+      .Times(4);
 
   // We should not get whilelist checks for other URLs than specified below.
   EXPECT_CALL(*sb_service_->mock_database_manager(),
@@ -465,6 +515,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -473,7 +526,8 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(a_tmp, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _));
 
   download_service_->CheckClientDownload(
       &item,
@@ -507,6 +561,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -515,7 +572,10 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(a_tmp, _)).Times(6);
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
+      .Times(6);
+  EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
+      .Times(6);
 
   download_service_->CheckClientDownload(
       &item,
@@ -651,6 +711,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_exe));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -659,7 +722,10 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(a_tmp, _)).Times(1);
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
+      .Times(1);
+  EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
+      .Times(1);
 
   download_service_->CheckClientDownload(
       &item,
@@ -700,6 +766,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -722,7 +791,7 @@
   MessageLoop::current()->Run();
   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
   Mock::VerifyAndClearExpectations(sb_service_.get());
-  Mock::VerifyAndClearExpectations(signature_util_.get());
+  Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
 
   // Now check with an executable in the zip file as well.
   ASSERT_EQ(static_cast<int>(file_contents.size()), base::WriteFile(
@@ -740,7 +809,7 @@
                  base::Unretained(this)));
   MessageLoop::current()->Run();
   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
-  Mock::VerifyAndClearExpectations(signature_util_.get());
+  Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
 
   // If the response is dangerous the result should also be marked as
   // dangerous.
@@ -760,7 +829,7 @@
 #else
   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
 #endif
-  Mock::VerifyAndClearExpectations(signature_util_.get());
+  Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
 }
 
 TEST_F(DownloadProtectionServiceTest, CheckClientDownloadCorruptZip) {
@@ -781,6 +850,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_zip));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -797,7 +869,7 @@
   MessageLoop::current()->Run();
   EXPECT_TRUE(IsResult(DownloadProtectionService::SAFE));
   Mock::VerifyAndClearExpectations(sb_service_.get());
-  Mock::VerifyAndClearExpectations(signature_util_.get());
+  Mock::VerifyAndClearExpectations(binary_feature_extractor_.get());
 }
 
 TEST_F(DownloadProtectionServiceTest, CheckClientCrxDownloadSuccess) {
@@ -827,6 +899,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(a_crx));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -835,7 +910,10 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(a_tmp, _)).Times(1);
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(a_tmp, _))
+      .Times(1);
+  EXPECT_CALL(*binary_feature_extractor_.get(), ExtractImageHeaders(a_tmp, _))
+      .Times(1);
 
   EXPECT_FALSE(download_service_->IsSupportedDownload(item, a_crx));
   download_service_->CheckClientDownload(
@@ -865,6 +943,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -873,8 +954,11 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(tmp_path, _))
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
       .WillOnce(SetCertificateContents("dummy cert data"));
+  EXPECT_CALL(*binary_feature_extractor_.get(),
+              ExtractImageHeaders(tmp_path, _))
+      .WillOnce(SetDosHeaderContents("dummy dos header"));
   download_service_->CheckClientDownload(
       &item,
       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
@@ -911,6 +995,12 @@
       request.signature().certificate_chain(0);
   ASSERT_EQ(1, chain.element_size());
   EXPECT_EQ("dummy cert data", chain.element(0).certificate());
+  EXPECT_TRUE(request.has_image_headers());
+  const ClientDownloadRequest_ImageHeaders& headers =
+      request.image_headers();
+  EXPECT_TRUE(headers.has_pe_headers());
+  EXPECT_TRUE(headers.pe_headers().has_dos_header());
+  EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
 
   // Simulate the request finishing.
   base::MessageLoop::current()->PostTask(
@@ -942,6 +1032,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -950,7 +1043,9 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(tmp_path, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(),
+              ExtractImageHeaders(tmp_path, _));
   download_service_->CheckClientDownload(
       &item,
       base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
@@ -992,6 +1087,191 @@
 #endif
 }
 
+// Similar to above, but with tab history.
+TEST_F(DownloadProtectionServiceTest,
+       CheckClientDownloadValidateRequestTabHistory) {
+  net::TestURLFetcherFactory factory;
+
+  base::ScopedTempDir profile_dir;
+  ASSERT_TRUE(profile_dir.CreateUniqueTempDir());
+  TestingProfile profile(profile_dir.path());
+  ASSERT_TRUE(
+      profile.CreateHistoryService(true /* delete_file */, false /* no_db */));
+
+  base::FilePath tmp_path(FILE_PATH_LITERAL("bla.tmp"));
+  base::FilePath final_path(FILE_PATH_LITERAL("bla.exe"));
+  std::vector<GURL> url_chain;
+  url_chain.push_back(GURL("http://www.google.com/"));
+  url_chain.push_back(GURL("http://www.google.com/bla.exe"));
+  GURL referrer("http://www.google.com/");
+  GURL tab_url("http://tab.com/final");
+  GURL tab_referrer("http://tab.com/referrer");
+  std::string hash = "hash";
+  std::string remote_address = "10.11.12.13";
+
+  content::MockDownloadItem item;
+  EXPECT_CALL(item, AddObserver(_)).Times(2);
+  EXPECT_CALL(item, RemoveObserver(_)).Times(2);
+  EXPECT_CALL(item, GetFullPath()).WillRepeatedly(ReturnRef(tmp_path));
+  EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
+  EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
+  EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(tab_url));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(tab_referrer));
+  EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
+  EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
+  EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
+  EXPECT_CALL(item, GetRemoteAddress()).WillRepeatedly(Return(remote_address));
+  EXPECT_CALL(item, GetBrowserContext()).WillRepeatedly(Return(&profile));
+  EXPECT_CALL(*sb_service_->mock_database_manager(),
+              MatchDownloadWhitelistUrl(_))
+      .WillRepeatedly(Return(false));
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _))
+      .WillRepeatedly(SetCertificateContents("dummy cert data"));
+  EXPECT_CALL(*binary_feature_extractor_.get(),
+              ExtractImageHeaders(tmp_path, _))
+      .WillRepeatedly(SetDosHeaderContents("dummy dos header"));
+
+  // First test with no history match for the tab URL.
+  {
+    TestURLFetcherWatcher fetcher_watcher(&factory);
+    download_service_->CheckClientDownload(
+        &item,
+        base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
+                   base::Unretained(this)));
+
+#if !defined(OS_WIN)
+    // SendRequest is not called.  Wait for FinishRequest to call our callback.
+    MessageLoop::current()->Run();
+    net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
+    EXPECT_EQ(NULL, fetcher);
+#else
+    EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
+    net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
+    ASSERT_TRUE(fetcher);
+    ClientDownloadRequest request;
+    EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
+    EXPECT_EQ("http://www.google.com/bla.exe", request.url());
+    EXPECT_EQ(hash, request.digests().sha256());
+    EXPECT_EQ(item.GetReceivedBytes(), request.length());
+    EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
+    EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
+    EXPECT_EQ(3, request.resources_size());
+    EXPECT_TRUE(
+        RequestContainsResource(request,
+                                ClientDownloadRequest::DOWNLOAD_REDIRECT,
+                                "http://www.google.com/",
+                                ""));
+    EXPECT_TRUE(RequestContainsResource(request,
+                                        ClientDownloadRequest::DOWNLOAD_URL,
+                                        "http://www.google.com/bla.exe",
+                                        referrer.spec()));
+    EXPECT_TRUE(RequestContainsResource(request,
+                                        ClientDownloadRequest::TAB_URL,
+                                        tab_url.spec(),
+                                        tab_referrer.spec()));
+    EXPECT_TRUE(request.has_signature());
+    ASSERT_EQ(1, request.signature().certificate_chain_size());
+    const ClientDownloadRequest_CertificateChain& chain =
+        request.signature().certificate_chain(0);
+    ASSERT_EQ(1, chain.element_size());
+    EXPECT_EQ("dummy cert data", chain.element(0).certificate());
+    EXPECT_TRUE(request.has_image_headers());
+    const ClientDownloadRequest_ImageHeaders& headers =
+        request.image_headers();
+    EXPECT_TRUE(headers.has_pe_headers());
+    EXPECT_TRUE(headers.pe_headers().has_dos_header());
+    EXPECT_EQ("dummy dos header", headers.pe_headers().dos_header());
+
+    // Simulate the request finishing.
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
+                   base::Unretained(this),
+                   fetcher));
+    MessageLoop::current()->Run();
+#endif
+  }
+
+  // Now try with a history match.
+  {
+    history::RedirectList redirects;
+    redirects.push_back(GURL("http://tab.com/ref1"));
+    redirects.push_back(GURL("http://tab.com/ref2"));
+    redirects.push_back(tab_url);
+    HistoryServiceFactory::GetForProfile(&profile, Profile::EXPLICIT_ACCESS)
+        ->AddPage(tab_url,
+                  base::Time::Now(),
+                  static_cast<void*>(this),
+                  0,
+                  GURL(),
+                  redirects,
+                  content::PAGE_TRANSITION_TYPED,
+                  history::SOURCE_BROWSED,
+                  false);
+
+    TestURLFetcherWatcher fetcher_watcher(&factory);
+    download_service_->CheckClientDownload(
+        &item,
+        base::Bind(&DownloadProtectionServiceTest::CheckDoneCallback,
+                   base::Unretained(this)));
+#if !defined(OS_WIN)
+    // SendRequest is not called.  Wait for FinishRequest to call our callback.
+    MessageLoop::current()->Run();
+    net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
+    EXPECT_EQ(NULL, fetcher);
+#else
+    EXPECT_EQ(0, fetcher_watcher.WaitForRequest());
+    net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
+    ASSERT_TRUE(fetcher);
+    ClientDownloadRequest request;
+    EXPECT_TRUE(request.ParseFromString(fetcher->upload_data()));
+    EXPECT_EQ("http://www.google.com/bla.exe", request.url());
+    EXPECT_EQ(hash, request.digests().sha256());
+    EXPECT_EQ(item.GetReceivedBytes(), request.length());
+    EXPECT_EQ(item.HasUserGesture(), request.user_initiated());
+    EXPECT_TRUE(RequestContainsServerIp(request, remote_address));
+    EXPECT_EQ(5, request.resources_size());
+    EXPECT_TRUE(
+        RequestContainsResource(request,
+                                ClientDownloadRequest::DOWNLOAD_REDIRECT,
+                                "http://www.google.com/",
+                                ""));
+    EXPECT_TRUE(RequestContainsResource(request,
+                                        ClientDownloadRequest::DOWNLOAD_URL,
+                                        "http://www.google.com/bla.exe",
+                                        referrer.spec()));
+    EXPECT_TRUE(RequestContainsResource(request,
+                                        ClientDownloadRequest::TAB_REDIRECT,
+                                        "http://tab.com/ref1",
+                                        ""));
+    EXPECT_TRUE(RequestContainsResource(request,
+                                        ClientDownloadRequest::TAB_REDIRECT,
+                                        "http://tab.com/ref2",
+                                        ""));
+    EXPECT_TRUE(RequestContainsResource(request,
+                                        ClientDownloadRequest::TAB_URL,
+                                        tab_url.spec(),
+                                        tab_referrer.spec()));
+    EXPECT_TRUE(request.has_signature());
+    ASSERT_EQ(1, request.signature().certificate_chain_size());
+    const ClientDownloadRequest_CertificateChain& chain =
+        request.signature().certificate_chain(0);
+    ASSERT_EQ(1, chain.element_size());
+    EXPECT_EQ("dummy cert data", chain.element(0).certificate());
+
+    // Simulate the request finishing.
+    base::MessageLoop::current()->PostTask(
+        FROM_HERE,
+        base::Bind(&DownloadProtectionServiceTest::SendURLFetchComplete,
+                   base::Unretained(this),
+                   fetcher));
+    MessageLoop::current()->Run();
+#endif
+  }
+}
+
 TEST_F(DownloadProtectionServiceTest, TestCheckDownloadUrl) {
   std::vector<GURL> url_chain;
   url_chain.push_back(GURL("http://www.google.com/"));
@@ -1074,6 +1354,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -1082,7 +1365,9 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(tmp_path, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(),
+              ExtractImageHeaders(tmp_path, _));
 
   download_service_->download_request_timeout_ms_ = 10;
   download_service_->CheckClientDownload(
@@ -1115,6 +1400,9 @@
   EXPECT_CALL(item, GetTargetFilePath()).WillRepeatedly(ReturnRef(final_path));
   EXPECT_CALL(item, GetUrlChain()).WillRepeatedly(ReturnRef(url_chain));
   EXPECT_CALL(item, GetReferrerUrl()).WillRepeatedly(ReturnRef(referrer));
+  EXPECT_CALL(item, GetTabUrl()).WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
+  EXPECT_CALL(item, GetTabReferrerUrl())
+      .WillRepeatedly(ReturnRef(GURL::EmptyGURL()));
   EXPECT_CALL(item, GetHash()).WillRepeatedly(ReturnRef(hash));
   EXPECT_CALL(item, GetReceivedBytes()).WillRepeatedly(Return(100));
   EXPECT_CALL(item, HasUserGesture()).WillRepeatedly(Return(true));
@@ -1123,7 +1411,9 @@
   EXPECT_CALL(*sb_service_->mock_database_manager(),
               MatchDownloadWhitelistUrl(_))
       .WillRepeatedly(Return(false));
-  EXPECT_CALL(*signature_util_.get(), CheckSignature(tmp_path, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(), CheckSignature(tmp_path, _));
+  EXPECT_CALL(*binary_feature_extractor_.get(),
+              ExtractImageHeaders(tmp_path, _));
 
   download_service_->CheckClientDownload(
       &item,
diff --git a/chrome/browser/safe_browsing/pe_image_reader_win.cc b/chrome/browser/safe_browsing/pe_image_reader_win.cc
new file mode 100644
index 0000000..70734fd
--- /dev/null
+++ b/chrome/browser/safe_browsing/pe_image_reader_win.cc
@@ -0,0 +1,327 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/pe_image_reader_win.h"
+
+#include "base/logging.h"
+
+namespace safe_browsing {
+
+// A class template of traits pertaining to IMAGE_OPTIONAL_HEADER{32,64}.
+template<class HEADER_TYPE>
+struct OptionalHeaderTraits {
+};
+
+template<>
+struct OptionalHeaderTraits<IMAGE_OPTIONAL_HEADER32> {
+  static const PeImageReader::WordSize word_size = PeImageReader::WORD_SIZE_32;
+};
+
+template<>
+struct OptionalHeaderTraits<IMAGE_OPTIONAL_HEADER64> {
+  static const PeImageReader::WordSize word_size = PeImageReader::WORD_SIZE_64;
+};
+
+// A template for type-specific optional header implementations. This, in
+// conjunction with the OptionalHeader interface, effectively erases the
+// underlying structure type from the point of view of the PeImageReader.
+template<class OPTIONAL_HEADER_TYPE>
+class PeImageReader::OptionalHeaderImpl : public PeImageReader::OptionalHeader {
+ public:
+  typedef OptionalHeaderTraits<OPTIONAL_HEADER_TYPE> TraitsType;
+
+  explicit OptionalHeaderImpl(const uint8_t* optional_header_start)
+      : optional_header_(reinterpret_cast<const OPTIONAL_HEADER_TYPE*>(
+                             optional_header_start)) {}
+
+  virtual WordSize GetWordSize() OVERRIDE {
+    return TraitsType::word_size;
+  }
+
+  virtual size_t GetDataDirectoryOffset() OVERRIDE {
+    return offsetof(OPTIONAL_HEADER_TYPE, DataDirectory);
+  }
+
+  virtual DWORD GetDataDirectorySize() OVERRIDE {
+    return optional_header_->NumberOfRvaAndSizes;
+  }
+
+  virtual const IMAGE_DATA_DIRECTORY* GetDataDirectoryEntries() OVERRIDE {
+    return &optional_header_->DataDirectory[0];
+  }
+
+ private:
+  const OPTIONAL_HEADER_TYPE* optional_header_;
+  DISALLOW_COPY_AND_ASSIGN(OptionalHeaderImpl);
+};
+
+PeImageReader::PeImageReader()
+    : image_data_(),
+      image_size_(),
+      validation_state_() {}
+
+PeImageReader::~PeImageReader() {
+  Clear();
+}
+
+bool PeImageReader::Initialize(const uint8_t* image_data, size_t image_size) {
+  image_data_ = image_data;
+  image_size_ = image_size;
+
+  if (!ValidateDosHeader() ||
+      !ValidatePeSignature() ||
+      !ValidateCoffFileHeader() ||
+      !ValidateOptionalHeader() ||
+      !ValidateSectionHeaders()) {
+    Clear();
+    return false;
+  }
+
+  return true;
+}
+
+PeImageReader::WordSize PeImageReader::GetWordSize() {
+  return optional_header_->GetWordSize();
+}
+
+const IMAGE_DOS_HEADER* PeImageReader::GetDosHeader() {
+  DCHECK_NE((validation_state_ & VALID_DOS_HEADER), 0U);
+  return reinterpret_cast<const IMAGE_DOS_HEADER*>(image_data_);
+}
+
+const IMAGE_FILE_HEADER* PeImageReader::GetCoffFileHeader() {
+  DCHECK_NE((validation_state_ & VALID_COFF_FILE_HEADER), 0U);
+  return reinterpret_cast<const IMAGE_FILE_HEADER*>(
+      image_data_ + GetDosHeader()->e_lfanew + sizeof(DWORD));
+}
+
+const uint8_t* PeImageReader::GetOptionalHeaderData(
+    size_t* optional_header_size) {
+  *optional_header_size = GetOptionalHeaderSize();
+  return GetOptionalHeaderStart();
+}
+
+size_t PeImageReader::GetNumberOfSections() {
+  return GetCoffFileHeader()->NumberOfSections;
+}
+
+const IMAGE_SECTION_HEADER* PeImageReader::GetSectionHeaderAt(size_t index) {
+  DCHECK_NE((validation_state_ & VALID_SECTION_HEADERS), 0U);
+  DCHECK_LT(index, GetNumberOfSections());
+  return reinterpret_cast<const IMAGE_SECTION_HEADER*>(
+      GetOptionalHeaderStart() +
+      GetOptionalHeaderSize() +
+      (sizeof(IMAGE_SECTION_HEADER) * index));
+}
+
+const uint8_t* PeImageReader::GetExportSection(size_t* section_size) {
+  size_t data_size = 0;
+  const uint8_t* data = GetImageData(IMAGE_DIRECTORY_ENTRY_EXPORT, &data_size);
+
+  // The export section data must be big enough for the export directory.
+  if (!data || data_size < sizeof(IMAGE_EXPORT_DIRECTORY))
+    return NULL;
+
+  *section_size = data_size;
+  return data;
+}
+
+size_t PeImageReader::GetNumberOfDebugEntries() {
+  size_t data_size = 0;
+  const uint8_t* data = GetImageData(IMAGE_DIRECTORY_ENTRY_DEBUG, &data_size);
+  return data ? (data_size / sizeof(IMAGE_DEBUG_DIRECTORY)) : 0;
+}
+
+const IMAGE_DEBUG_DIRECTORY* PeImageReader::GetDebugEntry(
+    size_t index,
+    const uint8_t** raw_data,
+    size_t* raw_data_size) {
+  DCHECK_LT(index, GetNumberOfDebugEntries());
+
+  // Get the debug directory.
+  size_t debug_directory_size = 0;
+  const IMAGE_DEBUG_DIRECTORY* entries =
+      reinterpret_cast<const IMAGE_DEBUG_DIRECTORY*>(
+          GetImageData(IMAGE_DIRECTORY_ENTRY_DEBUG, &debug_directory_size));
+  if (!entries)
+    return NULL;
+
+  const IMAGE_DEBUG_DIRECTORY& entry = entries[index];
+  const uint8_t* debug_data = NULL;
+  if (GetStructureAt(entry.PointerToRawData, entry.SizeOfData, &debug_data)) {
+    *raw_data = debug_data;
+    *raw_data_size = entry.SizeOfData;
+  }
+  return &entry;
+}
+
+void PeImageReader::Clear() {
+  image_data_ = NULL;
+  image_size_ = 0;
+  validation_state_ = 0;
+  optional_header_.reset();
+}
+
+bool PeImageReader::ValidateDosHeader() {
+  const IMAGE_DOS_HEADER* dos_header = NULL;
+  if (!GetStructureAt(0, &dos_header) ||
+      dos_header->e_magic != IMAGE_DOS_SIGNATURE ||
+      dos_header->e_lfanew < 0) {
+    return false;
+  }
+
+  validation_state_ |= VALID_DOS_HEADER;
+  return true;
+}
+
+bool PeImageReader::ValidatePeSignature() {
+  const DWORD* signature = NULL;
+  if (!GetStructureAt(GetDosHeader()->e_lfanew, &signature) ||
+      *signature != IMAGE_NT_SIGNATURE) {
+    return false;
+  }
+
+  validation_state_ |= VALID_PE_SIGNATURE;
+  return true;
+}
+
+bool PeImageReader::ValidateCoffFileHeader() {
+  DCHECK_NE((validation_state_ & VALID_PE_SIGNATURE), 0U);
+  const IMAGE_FILE_HEADER* file_header = NULL;
+  if (!GetStructureAt(GetDosHeader()->e_lfanew +
+                          offsetof(IMAGE_NT_HEADERS32, FileHeader),
+                      &file_header)) {
+    return false;
+  }
+
+  validation_state_ |= VALID_COFF_FILE_HEADER;
+  return true;
+}
+
+bool PeImageReader::ValidateOptionalHeader() {
+  const IMAGE_FILE_HEADER* file_header = GetCoffFileHeader();
+  const size_t optional_header_offset =
+      GetDosHeader()->e_lfanew + offsetof(IMAGE_NT_HEADERS32, OptionalHeader);
+  const size_t optional_header_size = file_header->SizeOfOptionalHeader;
+  const WORD* optional_header_magic = NULL;
+
+  if (optional_header_size < sizeof(*optional_header_magic) ||
+      !GetStructureAt(optional_header_offset, &optional_header_magic)) {
+    return false;
+  }
+
+  scoped_ptr<OptionalHeader> optional_header;
+  if (*optional_header_magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+    optional_header.reset(new OptionalHeaderImpl<IMAGE_OPTIONAL_HEADER32>(
+        image_data_ + optional_header_offset));
+  } else if (*optional_header_magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+    optional_header.reset(new OptionalHeaderImpl<IMAGE_OPTIONAL_HEADER64>(
+        image_data_ + optional_header_offset));
+  } else {
+    return false;
+  }
+
+  // Does all of the claimed optional header fit in the image?
+  if (optional_header_size > image_size_ - optional_header_offset)
+    return false;
+
+  // Is the claimed optional header big enough for everything but the dir?
+  if (optional_header->GetDataDirectoryOffset() > optional_header_size)
+    return false;
+
+  // Is there enough room for all of the claimed directory entries?
+  if (optional_header->GetDataDirectorySize() >
+      ((optional_header_size - optional_header->GetDataDirectoryOffset()) /
+       sizeof(IMAGE_DATA_DIRECTORY))) {
+    return false;
+  }
+
+  optional_header_.swap(optional_header);
+  validation_state_ |= VALID_OPTIONAL_HEADER;
+  return true;
+}
+
+bool PeImageReader::ValidateSectionHeaders() {
+  const uint8_t* first_section_header =
+      GetOptionalHeaderStart() + GetOptionalHeaderSize();
+  const size_t number_of_sections = GetNumberOfSections();
+
+  // Do all section headers fit in the image?
+  if (!GetStructureAt(first_section_header - image_data_,
+                      number_of_sections * sizeof(IMAGE_SECTION_HEADER),
+                      &first_section_header)) {
+    return false;
+  }
+
+  validation_state_ |= VALID_SECTION_HEADERS;
+  return true;
+}
+
+const uint8_t* PeImageReader::GetOptionalHeaderStart() {
+  DCHECK_NE((validation_state_ & VALID_OPTIONAL_HEADER), 0U);
+  return (image_data_ +
+          GetDosHeader()->e_lfanew +
+          offsetof(IMAGE_NT_HEADERS32, OptionalHeader));
+}
+
+size_t PeImageReader::GetOptionalHeaderSize() {
+  return GetCoffFileHeader()->SizeOfOptionalHeader;
+}
+
+const IMAGE_DATA_DIRECTORY* PeImageReader::GetDataDirectoryEntryAt(
+    size_t index) {
+  DCHECK_NE((validation_state_ & VALID_OPTIONAL_HEADER), 0U);
+  if (index >= optional_header_->GetDataDirectorySize())
+    return NULL;
+  return &optional_header_->GetDataDirectoryEntries()[index];
+}
+
+const IMAGE_SECTION_HEADER* PeImageReader::FindSectionFromRva(
+    uint32_t relative_address) {
+  const size_t number_of_sections = GetNumberOfSections();
+  for (size_t i = 0; i < number_of_sections; ++i) {
+    const IMAGE_SECTION_HEADER* section_header = GetSectionHeaderAt(i);
+    // Is the raw data present in the image? If no, optimistically keep looking.
+    const uint8_t* section_data = NULL;
+    if (!GetStructureAt(section_header->PointerToRawData,
+                        section_header->SizeOfRawData,
+                        &section_data)) {
+      continue;
+    }
+    // Does the RVA lie on or after this section's start when mapped? If no,
+    // bail.
+    if (section_header->VirtualAddress > relative_address)
+      break;
+    // Does the RVA lie within the section when mapped? If no, keep looking.
+    size_t address_offset = relative_address - section_header->VirtualAddress;
+    if (address_offset > section_header->Misc.VirtualSize)
+      continue;
+    // We have a winner.
+    return section_header;
+  }
+  return NULL;
+}
+
+const uint8_t* PeImageReader::GetImageData(size_t index, size_t* data_length) {
+  // Get the directory entry for the debug data.
+  const IMAGE_DATA_DIRECTORY* entry = GetDataDirectoryEntryAt(index);
+  if (!entry)
+    return NULL;
+
+  // Find the section containing the data.
+  const IMAGE_SECTION_HEADER* header =
+      FindSectionFromRva(entry->VirtualAddress);
+  if (!header)
+    return NULL;
+
+  // Does the data fit within the section when mapped?
+  size_t data_offset = entry->VirtualAddress - header->VirtualAddress;
+  if (entry->Size > (header->Misc.VirtualSize - data_offset))
+    return NULL;
+
+  *data_length = entry->Size;
+  return image_data_ + header->PointerToRawData + data_offset;
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/pe_image_reader_win.h b/chrome/browser/safe_browsing/pe_image_reader_win.h
new file mode 100644
index 0000000..6fa5349
--- /dev/null
+++ b/chrome/browser/safe_browsing/pe_image_reader_win.h
@@ -0,0 +1,133 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SAFE_BROWSING_PE_IMAGE_READER_WIN_H_
+#define CHROME_BROWSER_SAFE_BROWSING_PE_IMAGE_READER_WIN_H_
+
+#include <windows.h>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace safe_browsing {
+
+// Parses headers and various data from a PE image. This parser is safe for use
+// on untrusted data.
+class PeImageReader {
+ public:
+  enum WordSize {
+    WORD_SIZE_32,
+    WORD_SIZE_64,
+  };
+
+  PeImageReader();
+  ~PeImageReader();
+
+  // Returns false if the given data does not appear to be a valid PE image.
+  bool Initialize(const uint8_t* image_data, size_t image_size);
+
+  // Returns the machine word size for the image.
+  WordSize GetWordSize();
+
+  const IMAGE_DOS_HEADER* GetDosHeader();
+  const IMAGE_FILE_HEADER* GetCoffFileHeader();
+
+  // Returns a pointer to the optional header and its size.
+  const uint8_t* GetOptionalHeaderData(size_t* optional_data_size);
+  size_t GetNumberOfSections();
+  const IMAGE_SECTION_HEADER* GetSectionHeaderAt(size_t index);
+
+  // Returns a pointer to the image's export data (.edata) section and its size,
+  // or NULL if the section is not present.
+  const uint8_t* GetExportSection(size_t* section_size);
+
+  size_t GetNumberOfDebugEntries();
+  const IMAGE_DEBUG_DIRECTORY* GetDebugEntry(size_t index,
+                                             const uint8_t** raw_data,
+                                             size_t* raw_data_size);
+
+ private:
+  // Bits indicating what portions of the image have been validated.
+  enum ValidationStages {
+    VALID_DOS_HEADER = 1 << 0,
+    VALID_PE_SIGNATURE = 1 << 1,
+    VALID_COFF_FILE_HEADER = 1 << 2,
+    VALID_OPTIONAL_HEADER = 1 << 3,
+    VALID_SECTION_HEADERS = 1 << 4,
+  };
+
+  // An interface to an image's optional header.
+  class OptionalHeader {
+   public:
+    virtual WordSize GetWordSize() = 0;
+
+    // Returns the offset of the DataDirectory member relative to the start of
+    // the optional header.
+    virtual size_t GetDataDirectoryOffset() = 0;
+
+    // Returns the number of entries in the data directory.
+    virtual DWORD GetDataDirectorySize() = 0;
+
+    // Returns a pointer to the first data directory entry.
+    virtual const IMAGE_DATA_DIRECTORY* GetDataDirectoryEntries() = 0;
+  };
+
+  template<class OPTIONAL_HEADER_TYPE>
+  class OptionalHeaderImpl;
+
+  void Clear();
+  bool ValidateDosHeader();
+  bool ValidatePeSignature();
+  bool ValidateCoffFileHeader();
+  bool ValidateOptionalHeader();
+  bool ValidateSectionHeaders();
+
+  // Return a pointer to the first byte of the image's optional header.
+  const uint8_t* GetOptionalHeaderStart();
+  size_t GetOptionalHeaderSize();
+
+  // Returns the desired directory entry, or NULL if |index| is out of bounds.
+  const IMAGE_DATA_DIRECTORY* GetDataDirectoryEntryAt(size_t index);
+
+  // Returns the header for the section that contains the given address, or NULL
+  // if the address is out of bounds or the image does not contain the section.
+  const IMAGE_SECTION_HEADER* FindSectionFromRva(uint32_t relative_address);
+
+  // Returns a pointer to the |data_length| bytes referenced by the |index|'th
+  // data directory entry.
+  const uint8_t* GetImageData(size_t index, size_t* data_length);
+
+  // Populates |structure| with a pointer to a desired structure of type T at
+  // the given offset if the image is sufficiently large to contain it. Returns
+  // false if the structure does not fully fit within the image at the given
+  // offset.
+  template<typename T> bool GetStructureAt(size_t offset, const T** structure) {
+    return GetStructureAt(offset, sizeof(**structure), structure);
+  }
+
+  // Populates |structure| with a pointer to a desired structure of type T at
+  // the given offset if the image is sufficiently large to contain
+  // |structure_size| bytes. Returns false if the structure does not fully fit
+  // within the image at the given offset.
+  template<typename T> bool GetStructureAt(size_t offset,
+                                           size_t structure_size,
+                                           const T** structure) {
+    if (offset > image_size_)
+      return false;
+    if (structure_size > image_size_ - offset)
+      return false;
+    *structure = reinterpret_cast<const T*>(image_data_ + offset);
+    return true;
+  }
+
+  const uint8_t* image_data_;
+  size_t image_size_;
+  uint32_t validation_state_;
+  scoped_ptr<OptionalHeader> optional_header_;
+  DISALLOW_COPY_AND_ASSIGN(PeImageReader);
+};
+
+}  // namespace safe_browsing
+
+#endif  // CHROME_BROWSER_SAFE_BROWSING_PE_IMAGE_READER_WIN_H_
diff --git a/chrome/browser/safe_browsing/pe_image_reader_win_unittest.cc b/chrome/browser/safe_browsing/pe_image_reader_win_unittest.cc
new file mode 100644
index 0000000..63e6826
--- /dev/null
+++ b/chrome/browser/safe_browsing/pe_image_reader_win_unittest.cc
@@ -0,0 +1,157 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/file_path.h"
+#include "base/files/memory_mapped_file.h"
+#include "base/path_service.h"
+#include "chrome/browser/safe_browsing/pe_image_reader_win.h"
+#include "chrome/common/chrome_paths.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+struct TestData {
+  const char* filename;
+  safe_browsing::PeImageReader::WordSize word_size;
+  WORD machine_identifier;
+  WORD optional_header_size;
+  size_t number_of_sections;
+  size_t number_of_debug_entries;
+};
+
+// A test fixture parameterized on test data containing the name of a PE image
+// to parse and the expected values to be read from it. The file is read from
+// the src/chrome/test/data/safe_browsing directory.
+class PeImageReaderTest : public testing::TestWithParam<const TestData*> {
+ protected:
+  PeImageReaderTest() : expected_data_(GetParam()) {}
+
+  virtual void SetUp() OVERRIDE {
+    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_file_path_));
+    data_file_path_ = data_file_path_.AppendASCII("safe_browsing");
+    data_file_path_ = data_file_path_.AppendASCII(expected_data_->filename);
+
+    ASSERT_TRUE(data_file_.Initialize(data_file_path_));
+
+    ASSERT_TRUE(image_reader_.Initialize(data_file_.data(),
+                                         data_file_.length()));
+  }
+
+  const TestData* expected_data_;
+  base::FilePath data_file_path_;
+  base::MemoryMappedFile data_file_;
+  safe_browsing::PeImageReader image_reader_;
+};
+
+TEST_P(PeImageReaderTest, GetWordSize) {
+  EXPECT_EQ(expected_data_->word_size, image_reader_.GetWordSize());
+}
+
+TEST_P(PeImageReaderTest, GetDosHeader) {
+  const IMAGE_DOS_HEADER* dos_header = image_reader_.GetDosHeader();
+  ASSERT_NE(reinterpret_cast<const IMAGE_DOS_HEADER*>(NULL), dos_header);
+  EXPECT_EQ(IMAGE_DOS_SIGNATURE, dos_header->e_magic);
+}
+
+TEST_P(PeImageReaderTest, GetCoffFileHeader) {
+  const IMAGE_FILE_HEADER* file_header = image_reader_.GetCoffFileHeader();
+  ASSERT_NE(reinterpret_cast<const IMAGE_FILE_HEADER*>(NULL), file_header);
+  EXPECT_EQ(expected_data_->machine_identifier, file_header->Machine);
+  EXPECT_EQ(expected_data_->optional_header_size,
+            file_header->SizeOfOptionalHeader);
+}
+
+TEST_P(PeImageReaderTest, GetOptionalHeaderData) {
+  size_t optional_header_size = 0;
+  const uint8_t* optional_header_data =
+      image_reader_.GetOptionalHeaderData(&optional_header_size);
+  ASSERT_NE(reinterpret_cast<const uint8_t*>(NULL), optional_header_data);
+  EXPECT_EQ(expected_data_->optional_header_size, optional_header_size);
+}
+
+TEST_P(PeImageReaderTest, GetNumberOfSections) {
+  EXPECT_EQ(expected_data_->number_of_sections,
+            image_reader_.GetNumberOfSections());
+}
+
+TEST_P(PeImageReaderTest, GetSectionHeaderAt) {
+  size_t number_of_sections = image_reader_.GetNumberOfSections();
+  for (size_t i = 0; i < number_of_sections; ++i) {
+    const IMAGE_SECTION_HEADER* section_header =
+        image_reader_.GetSectionHeaderAt(i);
+    ASSERT_NE(reinterpret_cast<const IMAGE_SECTION_HEADER*>(NULL),
+              section_header);
+  }
+}
+
+TEST_P(PeImageReaderTest, InitializeFailTruncatedFile) {
+  // Compute the size of all headers through the section headers.
+  const IMAGE_SECTION_HEADER* last_section_header =
+      image_reader_.GetSectionHeaderAt(image_reader_.GetNumberOfSections() - 1);
+  const uint8_t* headers_end =
+      reinterpret_cast<const uint8_t*>(last_section_header) +
+      sizeof(*last_section_header);
+  size_t header_size = headers_end - data_file_.data();
+  safe_browsing::PeImageReader short_reader;
+
+  // Initialize should succeed when all headers are present.
+  EXPECT_TRUE(short_reader.Initialize(data_file_.data(), header_size));
+
+  // But fail if anything is missing.
+  for (size_t i = 0; i < header_size; ++i) {
+    EXPECT_FALSE(short_reader.Initialize(data_file_.data(), i));
+  }
+}
+
+TEST_P(PeImageReaderTest, GetExportSection) {
+  size_t section_size = 0;
+  const uint8_t* export_section = image_reader_.GetExportSection(&section_size);
+  ASSERT_NE(reinterpret_cast<const uint8_t*>(NULL), export_section);
+  EXPECT_NE(0U, section_size);
+}
+
+TEST_P(PeImageReaderTest, GetNumberOfDebugEntries) {
+  EXPECT_EQ(expected_data_->number_of_debug_entries,
+            image_reader_.GetNumberOfDebugEntries());
+}
+
+TEST_P(PeImageReaderTest, GetDebugEntry) {
+  size_t number_of_debug_entries = image_reader_.GetNumberOfDebugEntries();
+  for (size_t i = 0; i < number_of_debug_entries; ++i) {
+    const uint8_t* raw_data = NULL;
+    size_t raw_data_size = 0;
+    const IMAGE_DEBUG_DIRECTORY* entry =
+        image_reader_.GetDebugEntry(i, &raw_data, &raw_data_size);
+    EXPECT_NE(reinterpret_cast<const IMAGE_DEBUG_DIRECTORY*>(NULL), entry);
+    EXPECT_NE(reinterpret_cast<const uint8_t*>(NULL), raw_data);
+    EXPECT_NE(0U, raw_data_size);
+  }
+}
+
+namespace {
+
+const TestData kTestData[] = {
+  {
+    "module_with_exports_x86.dll",
+    safe_browsing::PeImageReader::WORD_SIZE_32,
+    IMAGE_FILE_MACHINE_I386,
+    sizeof(IMAGE_OPTIONAL_HEADER32),
+    4,
+    1,
+  }, {
+    "module_with_exports_x64.dll",
+    safe_browsing::PeImageReader::WORD_SIZE_64,
+    IMAGE_FILE_MACHINE_AMD64,
+    sizeof(IMAGE_OPTIONAL_HEADER64),
+    5,
+    1,
+  },
+};
+
+}  // namespace
+
+INSTANTIATE_TEST_CASE_P(WordSize32,
+                        PeImageReaderTest,
+                        testing::Values(&kTestData[0]));
+INSTANTIATE_TEST_CASE_P(WordSize64,
+                        PeImageReaderTest,
+                        testing::Values(&kTestData[1]));
diff --git a/chrome/browser/safe_browsing/safe_browsing_store.cc b/chrome/browser/safe_browsing/safe_browsing_store.cc
index 2638e58..a942b9a 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store.cc
@@ -10,6 +10,17 @@
 
 namespace {
 
+// Return |true| if the range is sorted by the given comparator.
+template <typename CTI, typename LESS>
+bool sorted(CTI beg, CTI end, LESS less) {
+  while ((end - beg) > 2) {
+    CTI n = beg++;
+    if (less(*beg, *n))
+      return false;
+  }
+  return true;
+}
+
 // Find items matching between |subs| and |adds|, and remove them,
 // recording the item from |adds| in |adds_removed|.  To minimize
 // copies, the inputs are processing in parallel, so |subs| and |adds|
@@ -133,15 +144,15 @@
   // to qualify things.  It becomes very arbitrary, though, and less
   // clear how things are working.
 
-  // Sort the inputs by the SBAddPrefix bits.
-  std::sort(add_prefixes->begin(), add_prefixes->end(),
-            SBAddPrefixLess<SBAddPrefix,SBAddPrefix>);
-  std::sort(sub_prefixes->begin(), sub_prefixes->end(),
-            SBAddPrefixLess<SBSubPrefix,SBSubPrefix>);
-  std::sort(add_full_hashes->begin(), add_full_hashes->end(),
-            SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>);
-  std::sort(sub_full_hashes->begin(), sub_full_hashes->end(),
-            SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>);
+  // Make sure things are sorted appropriately.
+  DCHECK(sorted(add_prefixes->begin(), add_prefixes->end(),
+                SBAddPrefixLess<SBAddPrefix,SBAddPrefix>));
+  DCHECK(sorted(sub_prefixes->begin(), sub_prefixes->end(),
+                SBAddPrefixLess<SBSubPrefix,SBSubPrefix>));
+  DCHECK(sorted(add_full_hashes->begin(), add_full_hashes->end(),
+                SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>));
+  DCHECK(sorted(sub_full_hashes->begin(), sub_full_hashes->end(),
+                SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>));
 
   // Factor out the prefix subs.
   SBAddPrefixes removed_adds;
diff --git a/chrome/browser/safe_browsing/safe_browsing_store.h b/chrome/browser/safe_browsing/safe_browsing_store.h
index 76cf28a..b381743 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store.h
+++ b/chrome/browser/safe_browsing/safe_browsing_store.h
@@ -53,6 +53,8 @@
   SBPrefix GetAddPrefix() const { return prefix; }
 };
 
+// TODO(shess): Measure the performance impact of switching this back to
+// std::vector<> once the v8 file format dominates.  Also SBSubPrefixes.
 typedef std::deque<SBAddPrefix> SBAddPrefixes;
 
 struct SBSubPrefix {
@@ -134,12 +136,7 @@
 // matched items from all vectors.  Additionally remove items from
 // deleted chunks.
 //
-// TODO(shess): Since the prefixes are uniformly-distributed hashes,
-// there aren't many ways to organize the inputs for efficient
-// processing.  For this reason, the vectors are sorted and processed
-// in parallel.  At this time this code does the sorting internally,
-// but it might make sense to make sorting an API requirement so that
-// the storage can optimize for it.
+// The inputs must be sorted by SBAddPrefixLess or SBAddPrefixHashLess.
 void SBProcessSubs(SBAddPrefixes* add_prefixes,
                    SBSubPrefixes* sub_prefixes,
                    std::vector<SBAddFullHash>* add_full_hashes,
@@ -147,10 +144,6 @@
                    const base::hash_set<int32>& add_chunks_deleted,
                    const base::hash_set<int32>& sub_chunks_deleted);
 
-// TODO(shess): This uses int32 rather than int because it's writing
-// specifically-sized items to files.  SBPrefix should likewise be
-// explicitly sized.
-
 // Abstract interface for storing data.
 class SafeBrowsingStore {
  public:
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file.cc b/chrome/browser/safe_browsing/safe_browsing_store_file.cc
index a879096..b58d961 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file.cc
@@ -14,22 +14,68 @@
 // NOTE(shess): kFileMagic should not be a byte-wise palindrome, so
 // that byte-order changes force corruption.
 const int32 kFileMagic = 0x600D71FE;
-const int32 kFileVersion = 7;  // SQLite storage was 6...
+
+// Version history:
+// Version 6: aad08754/r2814 by erikkay@google.com on 2008-10-02 (sqlite)
+// Version 7: 6afe28a5/r37435 by shess@chromium.org on 2010-01-28
+// Version 8: ????????/r????? by shess@chromium.org on 2014-03-??
+const int32 kFileVersion = 8;
+
+// ReadAndVerifyHeader() returns this in case of error.
+const int32 kInvalidVersion = -1;
 
 // Header at the front of the main database file.
-struct FileHeader {
+struct FileHeaderV7 {
   int32 magic, version;
   uint32 add_chunk_count, sub_chunk_count;
   uint32 add_prefix_count, sub_prefix_count;
   uint32 add_hash_count, sub_hash_count;
 };
 
+// Starting with version 8, the storage is sorted and can be sharded to allow
+// updates to be done with lower memory requirements.  Newly written files will
+// be sharded to need less than this amount of memory during update.  Larger
+// values are preferred to minimize looping overhead during processing.
+const int64 kUpdateStorageBytes = 100 * 1024;
+
+// Prevent excessive sharding by setting a lower limit on the shard stride.
+// Smaller values should work fine, but very small values will probably lead to
+// poor performance.  Shard stride is indirectly related to
+// |kUpdateStorageBytes|, setting that very small will bump against this.
+const uint32 kMinShardStride = 1 << 24;
+
+// Strides over the entire SBPrefix space.
+const uint64 kMaxShardStride = GG_LONGLONG(1u) << 32;
+
+// Maximum SBPrefix value.
+const SBPrefix kMaxSBPrefix = ~0;
+
+// Header at the front of the main database file.
+struct FileHeaderV8 {
+  int32 magic, version;
+  uint32 add_chunk_count, sub_chunk_count;
+  uint32 shard_stride;
+  // TODO(shess): Is this where 64-bit will bite me?  Perhaps write a
+  // specialized read/write?
+};
+
+union FileHeader {
+  struct FileHeaderV7 v7;
+  struct FileHeaderV8 v8;
+};
+
 // Header for each chunk in the chunk-accumulation file.
 struct ChunkHeader {
   uint32 add_prefix_count, sub_prefix_count;
   uint32 add_hash_count, sub_hash_count;
 };
 
+// Header for each shard of data in the main database file.
+struct ShardHeader {
+  uint32 add_prefix_count, sub_prefix_count;
+  uint32 add_hash_count, sub_hash_count;
+};
+
 // Rewind the file.  Using fseek(2) because rewind(3) errors are
 // weird.
 bool FileRewind(FILE* fp) {
@@ -38,18 +84,6 @@
   return rv == 0;
 }
 
-// Move file read pointer forward by |bytes| relative to current position.
-bool FileSkip(size_t bytes, FILE* fp) {
-  // Although fseek takes negative values, for this case, we only want
-  // to skip forward.
-  DCHECK(static_cast<long>(bytes) >= 0);
-  if (static_cast<long>(bytes) < 0)
-    return false;
-  int rv = fseek(fp, static_cast<long>(bytes), SEEK_CUR);
-  DCHECK_EQ(rv, 0);
-  return rv == 0;
-}
-
 // Read from |fp| into |item|, and fold the input data into the
 // checksum in |context|, if non-NULL.  Return true on success.
 template <class T>
@@ -104,22 +138,26 @@
   return true;
 }
 
-// Write all of |values| to |fp|, and fold the data into the checksum
-// in |context|, if non-NULL.  Returns true on succsess.
-template <typename CT>
-bool WriteContainer(const CT& values, FILE* fp,
-                    base::MD5Context* context) {
-  if (values.empty())
-    return true;
-
-  for (typename CT::const_iterator iter = values.begin();
-       iter != values.end(); ++iter) {
+// Write values between |beg| and |end| to |fp|, and fold the data into the
+// checksum in |context|, if non-NULL.  Returns true if all items successful.
+template <typename CTI>
+bool WriteRange(const CTI& beg, const CTI& end,
+                FILE* fp, base::MD5Context* context) {
+  for (CTI iter = beg; iter != end; ++iter) {
     if (!WriteItem(*iter, fp, context))
       return false;
   }
   return true;
 }
 
+// Write all of |values| to |fp|, and fold the data into the checksum
+// in |context|, if non-NULL.  Returns true if all items successful.
+template <typename CT>
+bool WriteContainer(const CT& values, FILE* fp,
+                    base::MD5Context* context) {
+  return WriteRange(values.begin(), values.end(), fp, context);
+}
+
 // Delete the chunks in |deleted| from |chunks|.
 void DeleteChunksFromSet(const base::hash_set<int32>& deleted,
                          std::set<int32>* chunks) {
@@ -131,16 +169,37 @@
   }
 }
 
+// base::MD5Final() modifies |context| in generating |digest|.  This wrapper
+// generates an intermediate digest without modifying the context.
+void MD5IntermediateDigest(base::MD5Digest* digest, base::MD5Context* context) {
+  base::MD5Context temp_context;
+  memcpy(&temp_context, context, sizeof(temp_context));
+  base::MD5Final(digest, &temp_context);
+}
+
+bool ReadAndVerifyChecksum(FILE* fp, base::MD5Context* context) {
+  base::MD5Digest calculated_digest;
+  MD5IntermediateDigest(&calculated_digest, context);
+
+  base::MD5Digest file_digest;
+  if (!ReadItem(&file_digest, fp, context))
+    return false;
+
+  return memcmp(&file_digest, &calculated_digest, sizeof(file_digest)) == 0;
+}
+
 // Sanity-check the header against the file's size to make sure our
 // vectors aren't gigantic.  This doubles as a cheap way to detect
 // corruption without having to checksum the entire file.
-bool FileHeaderSanityCheck(const base::FilePath& filename,
-                           const FileHeader& header) {
+bool FileHeaderV7SanityCheck(const base::FilePath& filename,
+                             const FileHeaderV7& header) {
+  DCHECK_EQ(header.version, 7);
+
   int64 size = 0;
   if (!base::GetFileSize(filename, &size))
     return false;
 
-  int64 expected_size = sizeof(FileHeader);
+  int64 expected_size = sizeof(FileHeaderV7);
   expected_size += header.add_chunk_count * sizeof(int32);
   expected_size += header.sub_chunk_count * sizeof(int32);
   expected_size += header.add_prefix_count * sizeof(SBAddPrefix);
@@ -154,21 +213,387 @@
   return true;
 }
 
-// This a helper function that reads header to |header|. Returns true if the
-// magic number is correct and santiy check passes.
-bool ReadAndVerifyHeader(const base::FilePath& filename,
-                         FILE* fp,
-                         FileHeader* header,
-                         base::MD5Context* context) {
-  if (!ReadItem(header, fp, context))
+// Helper function to read the file header and chunk TOC.  Rewinds |fp| and
+// initializes |context|.  The header is left in |header|, with the version
+// returned.  kInvalidVersion is returned for sanity check or checksum failure.
+int ReadAndVerifyHeader(const base::FilePath& filename,
+                        FileHeader* header,
+                        std::set<int32>* add_chunks,
+                        std::set<int32>* sub_chunks,
+                        FILE* fp,
+                        base::MD5Context* context) {
+  DCHECK(header);
+  DCHECK(add_chunks);
+  DCHECK(sub_chunks);
+  DCHECK(fp);
+  DCHECK(context);
+
+  int version = kInvalidVersion;
+
+  base::MD5Init(context);
+  if (!FileRewind(fp))
+    return kInvalidVersion;
+  if (!ReadItem(&header->v8, fp, context))
+    return kInvalidVersion;
+  if (header->v8.magic != kFileMagic)
+    return kInvalidVersion;
+
+  size_t add_chunks_count = 0;
+  size_t sub_chunks_count = 0;
+
+  if (header->v8.version == 7) {
+    version = 7;
+
+    // Reset the context and re-read the v7 header.
+    base::MD5Init(context);
+    if (!FileRewind(fp))
+      return kInvalidVersion;
+    if (!ReadItem(&header->v7, fp, context))
+      return kInvalidVersion;
+    if (header->v7.magic != kFileMagic || header->v7.version != 7)
+      return kInvalidVersion;
+    if (!FileHeaderV7SanityCheck(filename, header->v7))
+      return kInvalidVersion;
+
+    add_chunks_count = header->v7.add_chunk_count;
+    sub_chunks_count = header->v7.sub_chunk_count;
+  } else if (header->v8.version == kFileVersion) {
+    version = 8;
+    add_chunks_count = header->v8.add_chunk_count;
+    sub_chunks_count = header->v8.sub_chunk_count;
+  } else {
+    return kInvalidVersion;
+  }
+
+  if (!ReadToContainer(add_chunks, add_chunks_count, fp, context) ||
+      !ReadToContainer(sub_chunks, sub_chunks_count, fp, context)) {
+    return kInvalidVersion;
+  }
+
+  // v8 includes a checksum to validate the header.
+  if (version > 7 && !ReadAndVerifyChecksum(fp, context))
+    return kInvalidVersion;
+
+  return version;
+}
+
+// Helper function to write out the initial header and chunks-contained data.
+// Rewinds |fp|, initializes |context|, then writes a file header and
+// |add_chunks| and |sub_chunks|.
+bool WriteHeader(uint32 out_stride,
+                 const std::set<int32>& add_chunks,
+                 const std::set<int32>& sub_chunks,
+                 FILE* fp,
+                 base::MD5Context* context) {
+  if (!FileRewind(fp))
     return false;
-  if (header->magic != kFileMagic || header->version != kFileVersion)
+
+  base::MD5Init(context);
+  FileHeaderV8 header;
+  header.magic = kFileMagic;
+  header.version = kFileVersion;
+  header.add_chunk_count = add_chunks.size();
+  header.sub_chunk_count = sub_chunks.size();
+  header.shard_stride = out_stride;
+  if (!WriteItem(header, fp, context))
     return false;
-  if (!FileHeaderSanityCheck(filename, *header))
+
+  if (!WriteContainer(add_chunks, fp, context) ||
+      !WriteContainer(sub_chunks, fp, context))
     return false;
+
+  // Write out the header digest.
+  base::MD5Digest header_digest;
+  MD5IntermediateDigest(&header_digest, context);
+  if (!WriteItem(header_digest, fp, context))
+    return false;
+
   return true;
 }
 
+// Return |true| if the range is sorted by the given comparator.
+template <typename CTI, typename LESS>
+bool sorted(CTI beg, CTI end, LESS less) {
+  while ((end - beg) > 2) {
+    CTI n = beg++;
+    DCHECK(!less(*beg, *n));
+    if (less(*beg, *n))
+      return false;
+  }
+  return true;
+}
+
+// Merge |beg|..|end| into |container|.  Both should be sorted by the given
+// comparator, and the range iterators should not be derived from |container|.
+// Differs from std::inplace_merge() in that additional memory is not required
+// for linear performance.
+template <typename CT, typename CTI, typename COMP>
+void container_merge(CT* container, CTI beg, CTI end, const COMP& less) {
+  DCHECK(sorted(container->begin(), container->end(), less));
+  DCHECK(sorted(beg, end, less));
+
+  // Size the container to fit the results.
+  const size_t c_size = container->size();
+  container->resize(c_size + (end - beg));
+
+  // |c_end| points to the original endpoint, while |c_out| points to the
+  // endpoint that will scan from end to beginning while merging.
+  typename CT::iterator c_end = container->begin() + c_size;
+  typename CT::iterator c_out = container->end();
+
+  // While both inputs have data, move the greater to |c_out|.
+  while (c_end != container->begin() && end != beg) {
+    if (less(*(c_end - 1), *(end - 1))) {
+      *(--c_out) = *(--end);
+    } else {
+      *(--c_out) = *(--c_end);
+    }
+  }
+
+  // Copy any data remaining in the new range.
+  if (end != beg) {
+    // The original container data has been fully shifted.
+    DCHECK(c_end == container->begin());
+
+    // There is exactly the correct amount of space left.
+    DCHECK_EQ(c_out - c_end, end - beg);
+
+    std::copy(beg, end, container->begin());
+  }
+
+  DCHECK(sorted(container->begin(), container->end(), less));
+}
+
+// Collection of iterators used while stepping through StateInternal (see
+// below).
+class StateInternalPos {
+ public:
+  StateInternalPos(SBAddPrefixes::iterator add_prefixes_iter,
+                   SBSubPrefixes::iterator sub_prefixes_iter,
+                   std::vector<SBAddFullHash>::iterator add_hashes_iter,
+                   std::vector<SBSubFullHash>::iterator sub_hashes_iter)
+      : add_prefixes_iter_(add_prefixes_iter),
+        sub_prefixes_iter_(sub_prefixes_iter),
+        add_hashes_iter_(add_hashes_iter),
+        sub_hashes_iter_(sub_hashes_iter) {
+  }
+
+  SBAddPrefixes::iterator add_prefixes_iter_;
+  SBSubPrefixes::iterator sub_prefixes_iter_;
+  std::vector<SBAddFullHash>::iterator add_hashes_iter_;
+  std::vector<SBSubFullHash>::iterator sub_hashes_iter_;
+};
+
+// Helper to find the next shard boundary.
+template <class T>
+bool prefix_bounder(SBPrefix val, const T& elt) {
+  return val < elt.GetAddPrefix();
+}
+
+// Container for partial database state.  Includes add/sub prefixes/hashes, plus
+// aggregate operations on same.
+class StateInternal {
+ public:
+  explicit StateInternal(const std::vector<SBAddFullHash>& pending_adds)
+    : add_full_hashes_(pending_adds.begin(), pending_adds.end()) {
+  }
+
+  StateInternal() {}
+
+  // Append indicated amount of data from |fp|.
+  bool AppendData(size_t add_prefix_count, size_t sub_prefix_count,
+                  size_t add_hash_count, size_t sub_hash_count,
+                  FILE* fp, base::MD5Context* context) {
+    return
+        ReadToContainer(&add_prefixes_, add_prefix_count, fp, context) &&
+        ReadToContainer(&sub_prefixes_, sub_prefix_count, fp, context) &&
+        ReadToContainer(&add_full_hashes_, add_hash_count, fp, context) &&
+        ReadToContainer(&sub_full_hashes_, sub_hash_count, fp, context);
+  }
+
+  void ClearData() {
+    add_prefixes_.clear();
+    sub_prefixes_.clear();
+    add_full_hashes_.clear();
+    sub_full_hashes_.clear();
+  }
+
+  // Merge data from |beg|..|end| into receiver's state, then process the state.
+  // The current state and the range given should corrospond to the same sorted
+  // shard of data from different sources.  |add_del_cache| and |sub_del_cache|
+  // indicate the chunk ids which should be deleted during processing (see
+  // SBProcessSubs).
+  void MergeDataAndProcess(const StateInternalPos& beg,
+                           const StateInternalPos& end,
+                           const base::hash_set<int32>& add_del_cache,
+                           const base::hash_set<int32>& sub_del_cache) {
+    container_merge(&add_prefixes_,
+                    beg.add_prefixes_iter_,
+                    end.add_prefixes_iter_,
+                    SBAddPrefixLess<SBAddPrefix,SBAddPrefix>);
+
+    container_merge(&sub_prefixes_,
+                    beg.sub_prefixes_iter_,
+                    end.sub_prefixes_iter_,
+                    SBAddPrefixLess<SBSubPrefix,SBSubPrefix>);
+
+    container_merge(&add_full_hashes_,
+                    beg.add_hashes_iter_,
+                    end.add_hashes_iter_,
+                    SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>);
+
+    container_merge(&sub_full_hashes_,
+                    beg.sub_hashes_iter_,
+                    end.sub_hashes_iter_,
+                    SBAddPrefixHashLess<SBSubFullHash, SBSubFullHash>);
+
+    SBProcessSubs(&add_prefixes_, &sub_prefixes_,
+                  &add_full_hashes_, &sub_full_hashes_,
+                  add_del_cache, sub_del_cache);
+  }
+
+  // Sort the data appropriately for the sharding, merging, and processing
+  // operations.
+  void SortData() {
+    std::sort(add_prefixes_.begin(), add_prefixes_.end(),
+              SBAddPrefixLess<SBAddPrefix,SBAddPrefix>);
+    std::sort(sub_prefixes_.begin(), sub_prefixes_.end(),
+              SBAddPrefixLess<SBSubPrefix,SBSubPrefix>);
+    std::sort(add_full_hashes_.begin(), add_full_hashes_.end(),
+              SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>);
+    std::sort(sub_full_hashes_.begin(), sub_full_hashes_.end(),
+              SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>);
+  }
+
+  // Iterator from the beginning of the state's data.
+  StateInternalPos StateBegin() {
+    return StateInternalPos(add_prefixes_.begin(),
+                            sub_prefixes_.begin(),
+                            add_full_hashes_.begin(),
+                            sub_full_hashes_.begin());
+  }
+
+  // An iterator pointing just after the last possible element of the shard
+  // indicated by |shard_max|.  Used to step through the state by shard.
+  // TODO(shess): Verify whether binary search really improves over linear.
+  // Merging or writing will immediately touch all of these elements.
+  StateInternalPos ShardEnd(const StateInternalPos& beg, SBPrefix shard_max) {
+    return StateInternalPos(
+        std::upper_bound(beg.add_prefixes_iter_, add_prefixes_.end(),
+                         shard_max, prefix_bounder<SBAddPrefix>),
+        std::upper_bound(beg.sub_prefixes_iter_, sub_prefixes_.end(),
+                         shard_max, prefix_bounder<SBSubPrefix>),
+        std::upper_bound(beg.add_hashes_iter_, add_full_hashes_.end(),
+                         shard_max, prefix_bounder<SBAddFullHash>),
+        std::upper_bound(beg.sub_hashes_iter_, sub_full_hashes_.end(),
+                         shard_max, prefix_bounder<SBSubFullHash>));
+  }
+
+  // Write a shard header and data for the shard starting at |beg| and ending at
+  // the element before |end|.
+  bool WriteShard(const StateInternalPos& beg, const StateInternalPos& end,
+                  FILE* fp, base::MD5Context* context) {
+    ShardHeader shard_header;
+    shard_header.add_prefix_count =
+        end.add_prefixes_iter_ - beg.add_prefixes_iter_;
+    shard_header.sub_prefix_count =
+        end.sub_prefixes_iter_ - beg.sub_prefixes_iter_;
+    shard_header.add_hash_count =
+        end.add_hashes_iter_ - beg.add_hashes_iter_;
+    shard_header.sub_hash_count =
+        end.sub_hashes_iter_ - beg.sub_hashes_iter_;
+
+    return
+        WriteItem(shard_header, fp, context) &&
+        WriteRange(beg.add_prefixes_iter_, end.add_prefixes_iter_,
+                   fp, context) &&
+        WriteRange(beg.sub_prefixes_iter_, end.sub_prefixes_iter_,
+                   fp, context) &&
+        WriteRange(beg.add_hashes_iter_, end.add_hashes_iter_,
+                   fp, context) &&
+        WriteRange(beg.sub_hashes_iter_, end.sub_hashes_iter_,
+                   fp, context);
+  }
+
+  SBAddPrefixes add_prefixes_;
+  SBSubPrefixes sub_prefixes_;
+  std::vector<SBAddFullHash> add_full_hashes_;
+  std::vector<SBSubFullHash> sub_full_hashes_;
+};
+
+// True if |val| is an even power of two.
+template <typename T>
+bool IsPowerOfTwo(const T& val) {
+  return val && (val & (val - 1)) == 0;
+}
+
+// Helper to read the entire database state, used by GetAddPrefixes() and
+// GetAddFullHashes().  Those functions are generally used only for smaller
+// files.  Returns false in case of errors reading the data.
+bool ReadDbStateHelper(const base::FilePath& filename,
+                       StateInternal* db_state) {
+  file_util::ScopedFILE file(base::OpenFile(filename, "rb"));
+  if (file.get() == NULL)
+    return false;
+
+  std::set<int32> add_chunks;
+  std::set<int32> sub_chunks;
+
+  base::MD5Context context;
+  FileHeader header;
+  const int version =
+      ReadAndVerifyHeader(filename, &header, &add_chunks, &sub_chunks,
+                          file.get(), &context);
+  if (version == kInvalidVersion)
+    return false;
+
+  if (version == 7) {
+    if (!db_state->AppendData(header.v7.add_prefix_count,
+                              header.v7.sub_prefix_count,
+                              header.v7.add_hash_count,
+                              header.v7.sub_hash_count,
+                              file.get(), &context)) {
+      return false;
+    }
+
+    // v7 data was not stored sorted.
+    db_state->SortData();
+  } else {
+    // Read until the shard start overflows, always at least one pass.
+    uint64 in_min = 0;
+    uint64 in_stride = header.v8.shard_stride;
+    if (!in_stride)
+      in_stride = kMaxShardStride;
+    if (!IsPowerOfTwo(in_stride))
+      return false;
+
+    do {
+      ShardHeader shard_header;
+      if (!ReadItem(&shard_header, file.get(), &context))
+        return false;
+
+      if (!db_state->AppendData(shard_header.add_prefix_count,
+                                shard_header.sub_prefix_count,
+                                shard_header.add_hash_count,
+                                shard_header.sub_hash_count,
+                                file.get(), &context)) {
+        return false;
+      }
+
+      in_min += in_stride;
+    } while (in_min <= kMaxSBPrefix);
+  }
+
+  if (!ReadAndVerifyChecksum(file.get(), &context))
+    return false;
+
+  int64 size = 0;
+  if (!base::GetFileSize(filename, &size))
+    return false;
+
+  return static_cast<int64>(ftell(file.get())) == size;
+}
+
 }  // namespace
 
 // static
@@ -258,15 +683,7 @@
     bytes_left -= c;
   }
 
-  // Calculate the digest to this point.
-  base::MD5Digest calculated_digest;
-  base::MD5Final(&calculated_digest, &context);
-
-  // Read the stored digest and verify it.
-  base::MD5Digest file_digest;
-  if (!ReadItem(&file_digest, file_.get(), NULL))
-    return OnCorruptDatabase();
-  if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) {
+  if (!ReadAndVerifyChecksum(file_.get(), &context)) {
     RecordFormatEvent(FORMAT_EVENT_VALIDITY_CHECKSUM_FAILURE);
     return OnCorruptDatabase();
   }
@@ -293,48 +710,29 @@
 
 bool SafeBrowsingStoreFile::GetAddPrefixes(SBAddPrefixes* add_prefixes) {
   add_prefixes->clear();
+  if (!base::PathExists(filename_))
+    return true;
 
-  base::ScopedFILE file(base::OpenFile(filename_, "rb"));
-  if (file.get() == NULL) return false;
-
-  FileHeader header;
-  if (!ReadAndVerifyHeader(filename_, file.get(), &header, NULL))
+  StateInternal db_state;
+  if (!ReadDbStateHelper(filename_, &db_state))
     return OnCorruptDatabase();
 
-  size_t add_prefix_offset = header.add_chunk_count * sizeof(int32) +
-      header.sub_chunk_count * sizeof(int32);
-  if (!FileSkip(add_prefix_offset, file.get()))
-    return false;
-
-  if (!ReadToContainer(add_prefixes, header.add_prefix_count, file.get(), NULL))
-    return false;
-
+  add_prefixes->swap(db_state.add_prefixes_);
   return true;
 }
 
 bool SafeBrowsingStoreFile::GetAddFullHashes(
     std::vector<SBAddFullHash>* add_full_hashes) {
   add_full_hashes->clear();
+  if (!base::PathExists(filename_))
+    return true;
 
-  base::ScopedFILE file(base::OpenFile(filename_, "rb"));
-  if (file.get() == NULL) return false;
-
-  FileHeader header;
-  if (!ReadAndVerifyHeader(filename_, file.get(), &header, NULL))
+  StateInternal db_state;
+  if (!ReadDbStateHelper(filename_, &db_state))
     return OnCorruptDatabase();
 
-  size_t offset =
-      header.add_chunk_count * sizeof(int32) +
-      header.sub_chunk_count * sizeof(int32) +
-      header.add_prefix_count * sizeof(SBAddPrefix) +
-      header.sub_prefix_count * sizeof(SBSubPrefix);
-  if (!FileSkip(offset, file.get()))
-    return false;
-
-  return ReadToContainer(add_full_hashes,
-                         header.add_hash_count,
-                         file.get(),
-                         NULL);
+  add_full_hashes->swap(db_state.add_full_hashes_);
+  return true;
 }
 
 bool SafeBrowsingStoreFile::WriteAddHash(int32 chunk_id,
@@ -415,15 +813,26 @@
     return true;
   }
 
+  base::MD5Context context;
   FileHeader header;
-  if (!ReadItem(&header, file.get(), NULL))
-      return OnCorruptDatabase();
-
-  if (header.magic != kFileMagic || header.version != kFileVersion) {
-    if (!strcmp(reinterpret_cast<char*>(&header.magic), "SQLite format 3")) {
-      RecordFormatEvent(FORMAT_EVENT_FOUND_SQLITE);
-    } else {
-      RecordFormatEvent(FORMAT_EVENT_FOUND_UNKNOWN);
+  const int version =
+      ReadAndVerifyHeader(filename_, &header,
+                          &add_chunks_cache_, &sub_chunks_cache_,
+                          file.get(), &context);
+  if (version == kInvalidVersion) {
+    FileHeaderV8 retry_header;
+    if (FileRewind(file.get()) && ReadItem(&retry_header, file.get(), NULL) &&
+        (retry_header.magic != kFileMagic ||
+         (retry_header.version != 8 && retry_header.version != 7))) {
+      // TODO(shess): Think on whether these histograms are generating any
+      // actionable data.  I kid you not, SQLITE happens many thousands of times
+      // per day, UNKNOWN about 3x higher than that.
+      if (!strcmp(reinterpret_cast<char*>(&retry_header.magic),
+                  "SQLite format 3")) {
+        RecordFormatEvent(FORMAT_EVENT_FOUND_SQLITE);
+      } else {
+        RecordFormatEvent(FORMAT_EVENT_FOUND_UNKNOWN);
+      }
     }
 
     // Close the file so that it can be deleted.
@@ -432,20 +841,6 @@
     return OnCorruptDatabase();
   }
 
-  // TODO(shess): Under POSIX it is possible that this could size a
-  // file different from the file which was opened.
-  if (!FileHeaderSanityCheck(filename_, header))
-    return OnCorruptDatabase();
-
-  // Pull in the chunks-seen data for purposes of implementing
-  // |GetAddChunks()| and |GetSubChunks()|.  This data is sent up to
-  // the server at the beginning of an update.
-  if (!ReadToContainer(&add_chunks_cache_, header.add_chunk_count,
-                       file.get(), NULL) ||
-      !ReadToContainer(&sub_chunks_cache_, header.sub_chunk_count,
-                       file.get(), NULL))
-    return OnCorruptDatabase();
-
   file_.swap(file);
   new_file_.swap(new_file);
   return true;
@@ -485,80 +880,25 @@
   CHECK(builder);
   CHECK(add_full_hashes_result);
 
-  SBAddPrefixes add_prefixes;
-  SBSubPrefixes sub_prefixes;
-  std::vector<SBAddFullHash> add_full_hashes;
-  std::vector<SBSubFullHash> sub_full_hashes;
-
-  // Read original data into the vectors.
-  if (!empty_) {
-    DCHECK(file_.get());
-
-    if (!FileRewind(file_.get()))
-      return OnCorruptDatabase();
-
-    base::MD5Context context;
-    base::MD5Init(&context);
-
-    // Read the file header and make sure it looks right.
-    FileHeader header;
-    if (!ReadAndVerifyHeader(filename_, file_.get(), &header, &context))
-      return OnCorruptDatabase();
-
-    // Re-read the chunks-seen data to get to the later data in the
-    // file and calculate the checksum.  No new elements should be
-    // added to the sets.
-    if (!ReadToContainer(&add_chunks_cache_, header.add_chunk_count,
-                         file_.get(), &context) ||
-        !ReadToContainer(&sub_chunks_cache_, header.sub_chunk_count,
-                         file_.get(), &context))
-      return OnCorruptDatabase();
-
-    if (!ReadToContainer(&add_prefixes, header.add_prefix_count,
-                         file_.get(), &context) ||
-        !ReadToContainer(&sub_prefixes, header.sub_prefix_count,
-                         file_.get(), &context) ||
-        !ReadToContainer(&add_full_hashes, header.add_hash_count,
-                         file_.get(), &context) ||
-        !ReadToContainer(&sub_full_hashes, header.sub_hash_count,
-                         file_.get(), &context))
-      return OnCorruptDatabase();
-
-    // Calculate the digest to this point.
-    base::MD5Digest calculated_digest;
-    base::MD5Final(&calculated_digest, &context);
-
-    // Read the stored checksum and verify it.
-    base::MD5Digest file_digest;
-    if (!ReadItem(&file_digest, file_.get(), NULL))
-      return OnCorruptDatabase();
-
-    if (0 != memcmp(&file_digest, &calculated_digest, sizeof(file_digest))) {
-      RecordFormatEvent(FORMAT_EVENT_UPDATE_CHECKSUM_FAILURE);
-      return OnCorruptDatabase();
-    }
-
-    // Close the file so we can later rename over it.
-    file_.reset();
-  }
-  DCHECK(!file_.get());
-
   // Rewind the temporary storage.
   if (!FileRewind(new_file_.get()))
     return false;
 
   // Get chunk file's size for validating counts.
-  int64 size = 0;
-  if (!base::GetFileSize(TemporaryFileForFilename(filename_), &size))
+  int64 update_size = 0;
+  if (!base::GetFileSize(TemporaryFileForFilename(filename_), &update_size))
     return OnCorruptDatabase();
 
   // Track update size to answer questions at http://crbug.com/72216 .
   // Log small updates as 1k so that the 0 (underflow) bucket can be
   // used for "empty" in SafeBrowsingDatabase.
   UMA_HISTOGRAM_COUNTS("SB2.DatabaseUpdateKilobytes",
-                       std::max(static_cast<int>(size / 1024), 1));
+                       std::max(static_cast<int>(update_size / 1024), 1));
 
-  // Append the accumulated chunks onto the vectors read from |file_|.
+  // Chunk updates to integrate.
+  StateInternal new_state(pending_adds);
+
+  // Read update chunks.
   for (int i = 0; i < chunks_written_; ++i) {
     ChunkHeader header;
 
@@ -576,73 +916,202 @@
     expected_size += header.sub_prefix_count * sizeof(SBSubPrefix);
     expected_size += header.add_hash_count * sizeof(SBAddFullHash);
     expected_size += header.sub_hash_count * sizeof(SBSubFullHash);
-    if (expected_size > size)
+    if (expected_size > update_size)
       return false;
 
-    // TODO(shess): If the vectors were kept sorted, then this code
-    // could use std::inplace_merge() to merge everything together in
-    // sorted order.  That might still be slower than just sorting at
-    // the end if there were a large number of chunks.  In that case
-    // some sort of recursive binary merge might be in order (merge
-    // chunks pairwise, merge those chunks pairwise, and so on, then
-    // merge the result with the main list).
-    if (!ReadToContainer(&add_prefixes, header.add_prefix_count,
-                         new_file_.get(), NULL) ||
-        !ReadToContainer(&sub_prefixes, header.sub_prefix_count,
-                         new_file_.get(), NULL) ||
-        !ReadToContainer(&add_full_hashes, header.add_hash_count,
-                         new_file_.get(), NULL) ||
-        !ReadToContainer(&sub_full_hashes, header.sub_hash_count,
-                         new_file_.get(), NULL))
+    if (!new_state.AppendData(header.add_prefix_count, header.sub_prefix_count,
+                              header.add_hash_count, header.sub_hash_count,
+                              new_file_.get(), NULL)) {
       return false;
+    }
   }
 
-  // Append items from |pending_adds|.
-  add_full_hashes.insert(add_full_hashes.end(),
-                         pending_adds.begin(), pending_adds.end());
+  // The state was accumulated by chunk, sort by prefix.
+  new_state.SortData();
 
-  // Knock the subs from the adds and process deleted chunks.
-  SBProcessSubs(&add_prefixes, &sub_prefixes,
-                &add_full_hashes, &sub_full_hashes,
-                add_del_cache_, sub_del_cache_);
+  // These strides control how much data is loaded into memory per pass.
+  // Strides must be an even power of two.  |in_stride| will be derived from the
+  // input file.  |out_stride| will be derived from an estimate of the resulting
+  // file's size.  |process_stride| will be the max of both.
+  uint64 in_stride = kMaxShardStride;
+  uint64 out_stride = kMaxShardStride;
+  uint64 process_stride = 0;
+
+  // The header info is only used later if |!empty_|.  The v8 read loop only
+  // needs |in_stride|, while v7 needs to refer to header information.
+  base::MD5Context in_context;
+  int version = kInvalidVersion;
+  FileHeader header;
+
+  if (!empty_) {
+    DCHECK(file_.get());
+
+    version = ReadAndVerifyHeader(filename_, &header,
+                                  &add_chunks_cache_, &sub_chunks_cache_,
+                                  file_.get(), &in_context);
+    if (version == kInvalidVersion)
+      return OnCorruptDatabase();
+
+    if (version == 8 && header.v8.shard_stride)
+      in_stride = header.v8.shard_stride;
+
+    // The header checksum should have prevented this case, but the code will be
+    // broken if this is not correct.
+    if (!IsPowerOfTwo(in_stride))
+      return OnCorruptDatabase();
+  }
 
   // We no longer need to track deleted chunks.
   DeleteChunksFromSet(add_del_cache_, &add_chunks_cache_);
   DeleteChunksFromSet(sub_del_cache_, &sub_chunks_cache_);
 
-  // Write the new data to new_file_.
-  if (!FileRewind(new_file_.get()))
+  // Calculate |out_stride| to break the file down into reasonable shards.
+  {
+    int64 original_size = 0;
+    if (!empty_ && !base::GetFileSize(filename_, &original_size))
+      return OnCorruptDatabase();
+
+    // Approximate the final size as everything.  Subs and deletes will reduce
+    // the size, but modest over-sharding won't hurt much.
+    int64 shard_size = original_size + update_size;
+
+    // Keep splitting until a single stride of data fits the target.
+    size_t shifts = 0;
+    while (out_stride > kMinShardStride && shard_size > kUpdateStorageBytes) {
+      out_stride >>= 1;
+      shard_size >>= 1;
+      ++shifts;
+    }
+    UMA_HISTOGRAM_COUNTS("SB2.OutShardShifts", shifts);
+
+    DCHECK(IsPowerOfTwo(out_stride));
+  }
+
+  // Outer loop strides by the max of the input stride (to read integral shards)
+  // and the output stride (to write integral shards).
+  process_stride = std::max(in_stride, out_stride);
+  DCHECK(IsPowerOfTwo(process_stride));
+  DCHECK_EQ(0u, process_stride % in_stride);
+  DCHECK_EQ(0u, process_stride % out_stride);
+
+  // Start writing the new data to |new_file_|.
+  base::MD5Context out_context;
+  if (!WriteHeader(out_stride, add_chunks_cache_, sub_chunks_cache_,
+                   new_file_.get(), &out_context)) {
     return false;
+  }
 
-  base::MD5Context context;
-  base::MD5Init(&context);
+  // Start at the beginning of the SBPrefix space.
+  uint64 in_min = 0;
+  uint64 out_min = 0;
+  uint64 process_min = 0;
 
-  // Write a file header.
-  FileHeader header;
-  header.magic = kFileMagic;
-  header.version = kFileVersion;
-  header.add_chunk_count = add_chunks_cache_.size();
-  header.sub_chunk_count = sub_chunks_cache_.size();
-  header.add_prefix_count = add_prefixes.size();
-  header.sub_prefix_count = sub_prefixes.size();
-  header.add_hash_count = add_full_hashes.size();
-  header.sub_hash_count = sub_full_hashes.size();
-  if (!WriteItem(header, new_file_.get(), &context))
-    return false;
+  // Start at the beginning of the updates.
+  StateInternalPos new_pos = new_state.StateBegin();
 
-  // Write all the chunk data.
-  if (!WriteContainer(add_chunks_cache_, new_file_.get(), &context) ||
-      !WriteContainer(sub_chunks_cache_, new_file_.get(), &context) ||
-      !WriteContainer(add_prefixes, new_file_.get(), &context) ||
-      !WriteContainer(sub_prefixes, new_file_.get(), &context) ||
-      !WriteContainer(add_full_hashes, new_file_.get(), &context) ||
-      !WriteContainer(sub_full_hashes, new_file_.get(), &context))
-    return false;
+  // Re-usable container for shard processing.
+  StateInternal db_state;
 
-  // Write the checksum at the end.
-  base::MD5Digest digest;
-  base::MD5Final(&digest, &context);
-  if (!WriteItem(digest, new_file_.get(), NULL))
+  // Track aggregate counts for histograms.
+  size_t add_prefix_count = 0;
+  size_t sub_prefix_count = 0;
+
+  do {
+    // Maximum element in the current shard.
+    SBPrefix process_max =
+        static_cast<SBPrefix>(process_min + process_stride - 1);
+    DCHECK_GT(process_max, process_min);
+
+    // Drop the data from previous pass.
+    db_state.ClearData();
+
+    // Fill the processing shard with one or more input shards.
+    if (!empty_) {
+      if (version == 7) {
+        // Treat v7 as a single-shard file.
+        DCHECK_EQ(in_min, 0u);
+        DCHECK_EQ(in_stride, kMaxShardStride);
+        DCHECK_EQ(process_stride, kMaxShardStride);
+        if (!db_state.AppendData(header.v7.add_prefix_count,
+                                 header.v7.sub_prefix_count,
+                                 header.v7.add_hash_count,
+                                 header.v7.sub_hash_count,
+                                 file_.get(), &in_context))
+          return OnCorruptDatabase();
+
+        // v7 data is not sorted correctly.
+        db_state.SortData();
+      } else {
+        do {
+          ShardHeader shard_header;
+          if (!ReadItem(&shard_header, file_.get(), &in_context))
+            return OnCorruptDatabase();
+
+          if (!db_state.AppendData(shard_header.add_prefix_count,
+                                   shard_header.sub_prefix_count,
+                                   shard_header.add_hash_count,
+                                   shard_header.sub_hash_count,
+                                   file_.get(), &in_context))
+            return OnCorruptDatabase();
+
+          in_min += in_stride;
+        } while (in_min <= kMaxSBPrefix && in_min < process_max);
+      }
+    }
+
+    // Shard the update data to match the database data, then merge the update
+    // data and process the results.
+    {
+      StateInternalPos new_end = new_state.ShardEnd(new_pos, process_max);
+      db_state.MergeDataAndProcess(new_pos, new_end,
+                                   add_del_cache_, sub_del_cache_);
+      new_pos = new_end;
+    }
+
+    // Collect the processed data for return to caller.
+    for (size_t i = 0; i < db_state.add_prefixes_.size(); ++i) {
+      builder->AddPrefix(db_state.add_prefixes_[i].prefix);
+    }
+    add_full_hashes_result->insert(add_full_hashes_result->end(),
+                                   db_state.add_full_hashes_.begin(),
+                                   db_state.add_full_hashes_.end());
+    add_prefix_count += db_state.add_prefixes_.size();
+    sub_prefix_count += db_state.sub_prefixes_.size();
+
+    // Write one or more shards of processed output.
+    StateInternalPos out_pos = db_state.StateBegin();
+    do {
+      SBPrefix out_max = static_cast<SBPrefix>(out_min + out_stride - 1);
+      DCHECK_GT(out_max, out_min);
+
+      StateInternalPos out_end = db_state.ShardEnd(out_pos, out_max);
+      if (!db_state.WriteShard(out_pos, out_end, new_file_.get(), &out_context))
+        return false;
+      out_pos = out_end;
+
+      out_min += out_stride;
+    } while (out_min == static_cast<SBPrefix>(out_min) &&
+             out_min < process_max);
+
+    process_min += process_stride;
+  } while (process_min <= kMaxSBPrefix);
+
+  // Verify the overall checksum.
+  if (!empty_) {
+    if (!ReadAndVerifyChecksum(file_.get(), &in_context))
+      return OnCorruptDatabase();
+
+    // TODO(shess): Verify EOF?
+
+    // Close the input file so the new file can be renamed over it.
+    file_.reset();
+  }
+  DCHECK(!file_.get());
+
+  // Write the overall checksum.
+  base::MD5Digest out_digest;
+  base::MD5Final(&out_digest, &out_context);
+  if (!WriteItem(out_digest, new_file_.get(), NULL))
     return false;
 
   // Trim any excess left over from the temporary chunk data.
@@ -660,15 +1129,8 @@
     return false;
 
   // Record counts before swapping to caller.
-  UMA_HISTOGRAM_COUNTS("SB2.AddPrefixes", add_prefixes.size());
-  UMA_HISTOGRAM_COUNTS("SB2.SubPrefixes", sub_prefixes.size());
-
-  // Pass the resulting data off to the caller.
-  for (SBAddPrefixes::const_iterator iter = add_prefixes.begin();
-       iter != add_prefixes.end(); ++iter) {
-    builder->AddPrefix(iter->prefix);
-  }
-  add_full_hashes_result->swap(add_full_hashes);
+  UMA_HISTOGRAM_COUNTS("SB2.AddPrefixes", add_prefix_count);
+  UMA_HISTOGRAM_COUNTS("SB2.SubPrefixes", sub_prefix_count);
 
   return true;
 }
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file.h b/chrome/browser/safe_browsing/safe_browsing_store_file.h
index 6b821b0..c8a2429 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file.h
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file.h
@@ -21,38 +21,60 @@
 // int32 version;           // format version
 //
 // // Counts for the various data which follows the header.
-// uint32 add_chunk_count;   // Chunks seen, including empties.
-// uint32 sub_chunk_count;   // Ditto.
-// uint32 add_prefix_count;
-// uint32 sub_prefix_count;
-// uint32 add_hash_count;
-// uint32 sub_hash_count;
-//
+// uint32 add_chunk_count;  // Chunks seen, including empties.
+// uint32 sub_chunk_count;  // Ditto.
+// uint32 shard_stride;     // SBPrefix space covered per shard.
+//                          // 0==entire space in one shard.
+// // Sorted by chunk_id.
 // array[add_chunk_count] {
 //   int32 chunk_id;
 // }
+// // Sorted by chunk_id.
 // array[sub_chunk_count] {
 //   int32 chunk_id;
 // }
-// array[add_prefix_count] {
-//   int32 chunk_id;
-//   uint32 prefix;
+// MD5Digest header_checksum;  // Checksum over preceeding data.
+//
+// // Sorted by prefix, then add chunk_id, then hash, both within shards and
+// // overall.
+// array[from 0 to wraparound to 0 by shard_stride] {
+//   uint32 add_prefix_count;
+//   uint32 sub_prefix_count;
+//   uint32 add_hash_count;
+//   uint32 sub_hash_count;
+//   array[add_prefix_count] {
+//     int32 chunk_id;
+//     uint32 prefix;
+//   }
+//   array[sub_prefix_count] {
+//     int32 chunk_id;
+//     int32 add_chunk_id;
+//     uint32 add_prefix;
+//   }
+//   array[add_hash_count] {
+//     int32 chunk_id;
+//     int32 received_time;     // From base::Time::ToTimeT().
+//     char[32] full_hash;
+//   }
+//   array[sub_hash_count] {
+//     int32 chunk_id;
+//     int32 add_chunk_id;
+//     char[32] add_full_hash;
+//   }
 // }
-// array[sub_prefix_count] {
-//   int32 chunk_id;
-//   int32 add_chunk_id;
-//   uint32 add_prefix;
-// }
-// array[add_hash_count] {
-//   int32 chunk_id;
-//   int32 received_time;     // From base::Time::ToTimeT().
-//   char[32] full_hash;
-// array[sub_hash_count] {
-//   int32 chunk_id;
-//   int32 add_chunk_id;
-//   char[32] add_full_hash;
-// }
-// MD5Digest checksum;      // Checksum over preceeding data.
+// MD5Digest checksum;      // Checksum over entire file.
+//
+// The checksums are used to allow writing the file without doing an expensive
+// fsync().  Since the data can be re-fetched, failing the checksum is not
+// catastrophic.  Histograms indicate that file corruption here is pretty
+// uncommon.
+//
+// The |header_checksum| is present to guarantee valid header and chunk data for
+// updates.  Only that part of the file needs to be read to post the update.
+//
+// |shard_stride| breaks the file into approximately-equal portions, allowing
+// updates to stream from one file to another with modest memory usage.  It is
+// dynamic to adjust to different file sizes without adding excessive overhead.
 //
 // During the course of an update, uncommitted data is stored in a
 // temporary file (which is later re-used to commit).  This is an
@@ -91,19 +113,15 @@
 // - Open a temp file for storing new chunk info.
 // - Write new chunks to the temp file.
 // - When the transaction is finished:
-//   - Read the rest of the original file's data into buffers.
-//   - Rewind the temp file and merge the new data into buffers.
-//   - Process buffers for deletions and apply subs.
-//   - Rewind and write the buffers out to temp file.
+//   - Read the update data from the temp file into memory.
+//   - Overwrite the temp file with new header data.
+//   - Until done:
+//     - Read shards of the original file's data into memory.
+//     - Merge from the update data.
+//     - Write shards to the temp file.
 //   - Delete original file.
 //   - Rename temp file to original filename.
 
-// TODO(shess): By using a checksum, this code can avoid doing an
-// fsync(), at the possible cost of more frequently retrieving the
-// full dataset.  Measure how often this occurs, and if it occurs too
-// often, consider retaining the last known-good file for recovery
-// purposes, rather than deleting it.
-
 class SafeBrowsingStoreFile : public SafeBrowsingStore {
  public:
   SafeBrowsingStoreFile();
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
index 4f52241..e56b974 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_file_unittest.cc
@@ -9,6 +9,8 @@
 #include "base/files/scoped_file.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/md5.h"
+#include "base/path_service.h"
+#include "chrome/common/chrome_paths.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/platform_test.h"
 
@@ -28,6 +30,9 @@
 const SBFullHash kHash4 = SBFullHashForString("four");
 const SBFullHash kHash5 = SBFullHashForString("five");
 
+const SBPrefix kMinSBPrefix = 0u;
+const SBPrefix kMaxSBPrefix = ~kMinSBPrefix;
+
 class SafeBrowsingStoreFileTest : public PlatformTest {
  public:
   virtual void SetUp() {
@@ -58,7 +63,7 @@
 
   // Populate the store with some testing data.
   void PopulateStore(const base::Time& now) {
-    EXPECT_TRUE(store_->BeginUpdate());
+    ASSERT_TRUE(store_->BeginUpdate());
 
     EXPECT_TRUE(store_->BeginChunk());
     store_->SetAddChunk(kAddChunk1);
@@ -85,7 +90,17 @@
     EXPECT_TRUE(store_->FinishUpdate(pending_adds,
                                      &builder,
                                      &add_full_hashes_result));
-}
+  }
+
+  // Manually read the shard stride info from the file.
+  uint32 ReadStride() {
+    base::ScopedFILE file(base::OpenFile(filename_, "rb"));
+    const long kOffset = 4 * sizeof(uint32);
+    EXPECT_EQ(fseek(file.get(), kOffset, SEEK_SET), 0);
+    uint32 shard_stride = 0;
+    EXPECT_EQ(fread(&shard_stride, sizeof(shard_stride), 1, file.get()), 1U);
+    return shard_stride;
+  }
 
   base::ScopedTempDir temp_dir_;
   base::FilePath filename_;
@@ -95,7 +110,7 @@
 
 // Test that the empty store looks empty.
 TEST_F(SafeBrowsingStoreFileTest, Empty) {
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
 
   std::vector<int> chunks;
   store_->GetAddChunks(&chunks);
@@ -132,7 +147,7 @@
   const base::Time now = base::Time::Now();
   PopulateStore(now);
 
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
 
   std::vector<int> chunks;
   store_->GetAddChunks(&chunks);
@@ -164,7 +179,7 @@
     EXPECT_TRUE(SBFullHashEqual(kHash2, add_full_hashes_result[0].full_hash));
   }
 
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
 
   // Still has the chunks expected in the next update.
   store_->GetAddChunks(&chunks);
@@ -200,9 +215,63 @@
   }
 }
 
+// Verify that the min and max prefixes are stored and operated on.
+TEST_F(SafeBrowsingStoreFileTest, PrefixMinMax) {
+  const base::Time now = base::Time::Now();
+  PopulateStore(now);
+
+  ASSERT_TRUE(store_->BeginUpdate());
+
+  EXPECT_TRUE(store_->BeginChunk());
+  store_->SetAddChunk(kAddChunk2);
+  EXPECT_TRUE(store_->WriteAddPrefix(kAddChunk2, kMinSBPrefix));
+  EXPECT_TRUE(store_->WriteAddPrefix(kAddChunk2, kMaxSBPrefix));
+  EXPECT_TRUE(store_->FinishChunk());
+
+  {
+    std::vector<SBAddFullHash> pending_adds;
+    safe_browsing::PrefixSetBuilder builder;
+    std::vector<SBAddFullHash> add_full_hashes_result;
+    EXPECT_TRUE(store_->FinishUpdate(pending_adds,
+                                     &builder,
+                                     &add_full_hashes_result));
+
+    std::vector<SBPrefix> prefixes_result;
+    builder.GetPrefixSet()->GetPrefixes(&prefixes_result);
+    ASSERT_EQ(4U, prefixes_result.size());
+    EXPECT_EQ(kMinSBPrefix, prefixes_result[0]);
+    EXPECT_EQ(kHash1.prefix, prefixes_result[1]);
+    EXPECT_EQ(kHash2.prefix, prefixes_result[2]);
+    EXPECT_EQ(kMaxSBPrefix, prefixes_result[3]);
+  }
+
+  ASSERT_TRUE(store_->BeginUpdate());
+
+  EXPECT_TRUE(store_->BeginChunk());
+  store_->SetAddChunk(kSubChunk2);
+  EXPECT_TRUE(store_->WriteSubPrefix(kSubChunk2, kAddChunk2, kMinSBPrefix));
+  EXPECT_TRUE(store_->WriteSubPrefix(kSubChunk2, kAddChunk2, kMaxSBPrefix));
+  EXPECT_TRUE(store_->FinishChunk());
+
+  {
+    std::vector<SBAddFullHash> pending_adds;
+    safe_browsing::PrefixSetBuilder builder;
+    std::vector<SBAddFullHash> add_full_hashes_result;
+    EXPECT_TRUE(store_->FinishUpdate(pending_adds,
+                                     &builder,
+                                     &add_full_hashes_result));
+
+    std::vector<SBPrefix> prefixes_result;
+    builder.GetPrefixSet()->GetPrefixes(&prefixes_result);
+    ASSERT_EQ(2U, prefixes_result.size());
+    EXPECT_EQ(kHash1.prefix, prefixes_result[0]);
+    EXPECT_EQ(kHash2.prefix, prefixes_result[1]);
+  }
+}
+
 // Test that subs knockout adds.
 TEST_F(SafeBrowsingStoreFileTest, SubKnockout) {
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
 
   const base::Time now = base::Time::Now();
 
@@ -233,7 +302,7 @@
     EXPECT_TRUE(add_full_hashes_result.empty());
   }
 
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
 
   // This add should be knocked out by an existing sub.
   EXPECT_TRUE(store_->BeginChunk());
@@ -256,7 +325,7 @@
     EXPECT_TRUE(add_full_hashes_result.empty());
   }
 
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
 
   // But by here the sub should be gone, so it should stick this time.
   EXPECT_TRUE(store_->BeginChunk());
@@ -283,7 +352,7 @@
 
 // Test that deletes delete the chunk's data.
 TEST_F(SafeBrowsingStoreFileTest, DeleteChunks) {
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
 
   const base::Time now = base::Time::Now();
 
@@ -349,7 +418,7 @@
   }
 
   // Expected chunks are there in another update.
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
   EXPECT_FALSE(store_->CheckAddChunk(kAddChunk1));
   EXPECT_TRUE(store_->CheckAddChunk(kAddChunk2));
   EXPECT_FALSE(store_->CheckSubChunk(kSubChunk1));
@@ -369,7 +438,7 @@
   }
 
   // Expect no more chunks.
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
   EXPECT_FALSE(store_->CheckAddChunk(kAddChunk1));
   EXPECT_FALSE(store_->CheckAddChunk(kAddChunk2));
   EXPECT_FALSE(store_->CheckSubChunk(kSubChunk1));
@@ -413,7 +482,7 @@
   EXPECT_FALSE(base::PathExists(temp_file));
 
   // Starting a transaction creates a temporary file.
-  EXPECT_TRUE(store_->BeginUpdate());
+  ASSERT_TRUE(store_->BeginUpdate());
   EXPECT_TRUE(base::PathExists(temp_file));
 
   // Pull the rug out from under the existing store, simulating a
@@ -440,7 +509,7 @@
     std::vector<SBPrefix> orig_prefixes;
     std::vector<SBAddFullHash> orig_hashes;
     safe_browsing::PrefixSetBuilder builder;
-    EXPECT_TRUE(store_->BeginUpdate());
+    ASSERT_TRUE(store_->BeginUpdate());
     EXPECT_TRUE(store_->FinishUpdate(pending_adds, &builder, &orig_hashes));
     builder.GetPrefixSet()->GetPrefixes(&orig_prefixes);
     EXPECT_GT(orig_prefixes.size(), 0U);
@@ -466,7 +535,7 @@
   {
     std::vector<SBAddFullHash> pending_adds;
     safe_browsing::PrefixSetBuilder builder;
-    EXPECT_TRUE(store_->BeginUpdate());
+    ASSERT_TRUE(store_->BeginUpdate());
     EXPECT_FALSE(store_->FinishUpdate(pending_adds, &builder, &add_hashes));
     EXPECT_TRUE(corruption_detected_);
   }
@@ -505,15 +574,33 @@
   EXPECT_TRUE(store_->CancelUpdate());
 }
 
-// Corrupt the payload.
+// Corrupt the header.
+TEST_F(SafeBrowsingStoreFileTest, CheckValidityHeader) {
+  PopulateStore(base::Time::Now());
+  EXPECT_TRUE(base::PathExists(filename_));
+
+  // 37 is the most random prime number.  It's also past the initial header
+  // struct, somewhere in the chunk list.
+  const size_t kOffset = 37;
+
+  {
+    base::ScopedFILE file(base::OpenFile(filename_, "rb+"));
+    EXPECT_EQ(0, fseek(file.get(), kOffset, SEEK_SET));
+    EXPECT_GE(fputs("hello", file.get()), 0);
+  }
+  ASSERT_FALSE(store_->BeginUpdate());
+  EXPECT_TRUE(corruption_detected_);
+}
+
+// Corrupt the prefix payload.
 TEST_F(SafeBrowsingStoreFileTest, CheckValidityPayload) {
   PopulateStore(base::Time::Now());
   EXPECT_TRUE(base::PathExists(filename_));
 
-  // 37 is the most random prime number.  It's also past the header,
-  // as corrupting the header would fail BeginUpdate() in which case
-  // CheckValidity() cannot be called.
-  const size_t kOffset = 37;
+  // 137 is the second most random prime number.  It's also past the header and
+  // chunk-id area.  Corrupting the header would fail BeginUpdate() in which
+  // case CheckValidity() cannot be called.
+  const size_t kOffset = 137;
 
   {
     base::ScopedFILE file(base::OpenFile(filename_, "rb+"));
@@ -547,4 +634,210 @@
   EXPECT_TRUE(store_->CancelUpdate());
 }
 
+TEST_F(SafeBrowsingStoreFileTest, GetAddPrefixesAndHashes) {
+  ASSERT_TRUE(store_->BeginUpdate());
+
+  const base::Time now = base::Time::Now();
+
+  EXPECT_TRUE(store_->BeginChunk());
+  store_->SetAddChunk(kAddChunk1);
+  EXPECT_TRUE(store_->CheckAddChunk(kAddChunk1));
+  EXPECT_TRUE(store_->WriteAddPrefix(kAddChunk1, kHash1.prefix));
+  EXPECT_TRUE(store_->WriteAddPrefix(kAddChunk1, kHash2.prefix));
+  EXPECT_TRUE(store_->WriteAddHash(kAddChunk1, now, kHash2));
+
+  store_->SetSubChunk(kSubChunk1);
+  EXPECT_TRUE(store_->CheckSubChunk(kSubChunk1));
+  EXPECT_TRUE(store_->WriteSubPrefix(kSubChunk1, kAddChunk3, kHash3.prefix));
+  EXPECT_TRUE(store_->WriteSubHash(kSubChunk1, kAddChunk3, kHash3));
+  EXPECT_TRUE(store_->FinishChunk());
+
+  // Chunk numbers shouldn't leak over.
+  EXPECT_FALSE(store_->CheckAddChunk(kSubChunk1));
+  EXPECT_FALSE(store_->CheckAddChunk(kAddChunk3));
+  EXPECT_FALSE(store_->CheckSubChunk(kAddChunk1));
+
+  std::vector<int> chunks;
+  store_->GetAddChunks(&chunks);
+  ASSERT_EQ(1U, chunks.size());
+  EXPECT_EQ(kAddChunk1, chunks[0]);
+
+  store_->GetSubChunks(&chunks);
+  ASSERT_EQ(1U, chunks.size());
+  EXPECT_EQ(kSubChunk1, chunks[0]);
+
+  safe_browsing::PrefixSetBuilder builder;
+  std::vector<SBAddFullHash> add_full_hashes_result;
+  EXPECT_TRUE(store_->FinishUpdate(std::vector<SBAddFullHash>(),
+                                   &builder,
+                                   &add_full_hashes_result));
+
+  SBAddPrefixes add_prefixes;
+  EXPECT_TRUE(store_->GetAddPrefixes(&add_prefixes));
+  ASSERT_EQ(2U, add_prefixes.size());
+  EXPECT_EQ(kAddChunk1, add_prefixes[0].chunk_id);
+  EXPECT_EQ(kHash1.prefix, add_prefixes[0].prefix);
+  EXPECT_EQ(kAddChunk1, add_prefixes[1].chunk_id);
+  EXPECT_EQ(kHash2.prefix, add_prefixes[1].prefix);
+
+  std::vector<SBAddFullHash> add_hashes;
+  EXPECT_TRUE(store_->GetAddFullHashes(&add_hashes));
+  ASSERT_EQ(1U, add_hashes.size());
+  EXPECT_EQ(kAddChunk1, add_hashes[0].chunk_id);
+  EXPECT_TRUE(SBFullHashEqual(kHash2, add_hashes[0].full_hash));
+}
+
+// Test that the database handles resharding correctly, both when growing and
+// which shrinking.
+TEST_F(SafeBrowsingStoreFileTest, Resharding) {
+  // Loop through multiple stride boundaries (1<<32, 1<<31, 1<<30, 1<<29).
+  const uint32 kTargetStride = 1 << 29;
+
+  // Each chunk will require 8 bytes per prefix, plus 4 bytes for chunk
+  // information.  It should be less than |kTargetFootprint| in the
+  // implementation, but high enough to keep the number of rewrites modest (to
+  // keep the test fast).
+  const size_t kPrefixesPerChunk = 10000;
+
+  uint32 shard_stride = 0;
+  int chunk_id = 1;
+
+  // Add a series of chunks, tracking that the stride size changes in a
+  // direction appropriate to increasing file size.
+  do {
+    ASSERT_TRUE(store_->BeginUpdate());
+
+    EXPECT_TRUE(store_->BeginChunk());
+    store_->SetAddChunk(chunk_id);
+    EXPECT_TRUE(store_->CheckAddChunk(chunk_id));
+    for (size_t i = 0; i < kPrefixesPerChunk; ++i) {
+      EXPECT_TRUE(store_->WriteAddPrefix(chunk_id, static_cast<SBPrefix>(i)));
+    }
+    EXPECT_TRUE(store_->FinishChunk());
+
+    std::vector<SBAddFullHash> pending_adds;
+    safe_browsing::PrefixSetBuilder builder;
+    std::vector<SBAddFullHash> add_full_hashes_result;
+    EXPECT_TRUE(store_->FinishUpdate(pending_adds,
+                                     &builder,
+                                     &add_full_hashes_result));
+
+    SBAddPrefixes add_prefixes;
+    EXPECT_TRUE(store_->GetAddPrefixes(&add_prefixes));
+    ASSERT_EQ(chunk_id * kPrefixesPerChunk, add_prefixes.size());
+
+    // New stride should be the same, or shifted one right.
+    const uint32 new_shard_stride = ReadStride();
+    EXPECT_TRUE((new_shard_stride == shard_stride) ||
+                ((new_shard_stride << 1) == shard_stride));
+    shard_stride = new_shard_stride;
+    ++chunk_id;
+  } while (!shard_stride || shard_stride > kTargetStride);
+
+  // Guard against writing too many chunks.  If this gets too big, adjust
+  // |kPrefixesPerChunk|.
+  EXPECT_LT(chunk_id, 20);
+
+  // Remove each chunk and check that the stride goes back to 0.
+  while (--chunk_id) {
+    ASSERT_TRUE(store_->BeginUpdate());
+    EXPECT_TRUE(store_->CheckAddChunk(chunk_id));
+    EXPECT_FALSE(store_->CheckAddChunk(chunk_id + 1));
+    store_->DeleteAddChunk(chunk_id);
+
+    std::vector<SBAddFullHash> pending_adds;
+    safe_browsing::PrefixSetBuilder builder;
+    std::vector<SBAddFullHash> add_full_hashes_result;
+    EXPECT_TRUE(store_->FinishUpdate(pending_adds,
+                                     &builder,
+                                     &add_full_hashes_result));
+
+    // New stride should be the same, or shifted one left.
+    const uint32 new_shard_stride = ReadStride();
+    EXPECT_TRUE((new_shard_stride == shard_stride) ||
+                (new_shard_stride == (shard_stride << 1)));
+    shard_stride = new_shard_stride;
+  }
+  EXPECT_EQ(0u, shard_stride);
+}
+
+// Test that a golden v7 file can be read by the current code.  All platforms
+// generating v7 files are little-endian, so there is no point to testing this
+// transition if/when a big-endian port is added.
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+TEST_F(SafeBrowsingStoreFileTest, Version7) {
+  store_.reset();
+
+  // Copy the golden file into temporary storage.  The golden file contains:
+  // - Add chunk kAddChunk1 containing kHash1.prefix and kHash2.
+  // - Sub chunk kSubChunk1 containing kHash3.
+  const char kBasename[] = "FileStoreVersion7";
+  base::FilePath golden_path;
+  ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &golden_path));
+  golden_path = golden_path.AppendASCII("SafeBrowsing");
+  golden_path = golden_path.AppendASCII(kBasename);
+  ASSERT_TRUE(base::CopyFile(golden_path, filename_));
+
+  // Reset the store to make sure it re-reads the file.
+  store_.reset(new SafeBrowsingStoreFile());
+  store_->Init(filename_,
+               base::Bind(&SafeBrowsingStoreFileTest::OnCorruptionDetected,
+                          base::Unretained(this)));
+
+  // Check that the expected prefixes and hashes are in place.
+  SBAddPrefixes add_prefixes;
+  EXPECT_TRUE(store_->GetAddPrefixes(&add_prefixes));
+  ASSERT_EQ(2U, add_prefixes.size());
+  EXPECT_EQ(kAddChunk1, add_prefixes[0].chunk_id);
+  EXPECT_EQ(kHash1.prefix, add_prefixes[0].prefix);
+  EXPECT_EQ(kAddChunk1, add_prefixes[1].chunk_id);
+  EXPECT_EQ(kHash2.prefix, add_prefixes[1].prefix);
+
+  std::vector<SBAddFullHash> add_hashes;
+  EXPECT_TRUE(store_->GetAddFullHashes(&add_hashes));
+  ASSERT_EQ(1U, add_hashes.size());
+  EXPECT_EQ(kAddChunk1, add_hashes[0].chunk_id);
+  EXPECT_TRUE(SBFullHashEqual(kHash2, add_hashes[0].full_hash));
+
+  // Attempt an update to make sure things work end-to-end.
+  EXPECT_TRUE(store_->BeginUpdate());
+
+  // Still has the chunks expected in the next update.
+  std::vector<int> chunks;
+  store_->GetAddChunks(&chunks);
+  ASSERT_EQ(1U, chunks.size());
+  EXPECT_EQ(kAddChunk1, chunks[0]);
+
+  store_->GetSubChunks(&chunks);
+  ASSERT_EQ(1U, chunks.size());
+  EXPECT_EQ(kSubChunk1, chunks[0]);
+
+  EXPECT_TRUE(store_->CheckAddChunk(kAddChunk1));
+  EXPECT_TRUE(store_->CheckSubChunk(kSubChunk1));
+
+  // Sub chunk kAddChunk1 hash kHash2.
+  store_->SetSubChunk(kSubChunk2);
+  EXPECT_TRUE(store_->CheckSubChunk(kSubChunk1));
+  EXPECT_TRUE(store_->WriteSubPrefix(kSubChunk1, kAddChunk1, kHash2.prefix));
+  EXPECT_TRUE(store_->WriteSubHash(kSubChunk1, kAddChunk1, kHash2));
+  EXPECT_TRUE(store_->FinishChunk());
+
+  {
+    std::vector<SBAddFullHash> pending_adds;
+    safe_browsing::PrefixSetBuilder builder;
+    std::vector<SBAddFullHash> add_full_hashes_result;
+    EXPECT_TRUE(store_->FinishUpdate(pending_adds,
+                                     &builder,
+                                     &add_full_hashes_result));
+
+    // The sub'ed prefix and hash are gone.
+    std::vector<SBPrefix> prefixes_result;
+    builder.GetPrefixSet()->GetPrefixes(&prefixes_result);
+    ASSERT_EQ(1U, prefixes_result.size());
+    EXPECT_EQ(kHash1.prefix, prefixes_result[0]);
+    EXPECT_TRUE(add_full_hashes_result.empty());
+  }
+}
+#endif
+
 }  // namespace
diff --git a/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc b/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc
index 199138e..420ed1c 100644
--- a/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_store_unittest.cc
@@ -178,6 +178,15 @@
   add_hashes.push_back(SBAddFullHash(kAddChunk1, kNow, kHash4mod));
   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash4mod));
 
+  std::sort(add_prefixes.begin(), add_prefixes.end(),
+            SBAddPrefixLess<SBAddPrefix,SBAddPrefix>);
+  std::sort(sub_prefixes.begin(), sub_prefixes.end(),
+            SBAddPrefixLess<SBSubPrefix,SBSubPrefix>);
+  std::sort(add_hashes.begin(), add_hashes.end(),
+            SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>);
+  std::sort(sub_hashes.begin(), sub_hashes.end(),
+            SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>);
+
   const base::hash_set<int32> no_deletions;
   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
                 no_deletions, no_deletions);
@@ -249,6 +258,15 @@
   sub_hashes.push_back(SBSubFullHash(kSubChunk1, kAddChunk1, kHash3));
   sub_prefixes.push_back(SBSubPrefix(kSubChunk1, kAddChunk1, kHash3.prefix));
 
+  std::sort(add_prefixes.begin(), add_prefixes.end(),
+            SBAddPrefixLess<SBAddPrefix,SBAddPrefix>);
+  std::sort(sub_prefixes.begin(), sub_prefixes.end(),
+            SBAddPrefixLess<SBSubPrefix,SBSubPrefix>);
+  std::sort(add_hashes.begin(), add_hashes.end(),
+            SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>);
+  std::sort(sub_hashes.begin(), sub_hashes.end(),
+            SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>);
+
   const base::hash_set<int32> no_deletions;
   base::hash_set<int32> add_deletions;
   add_deletions.insert(kAddChunk1);
@@ -268,6 +286,15 @@
   EXPECT_EQ(kAddChunk1, sub_hashes[0].add_chunk_id);
   EXPECT_TRUE(SBFullHashEqual(kHash3, sub_hashes[0].full_hash));
 
+  std::sort(add_prefixes.begin(), add_prefixes.end(),
+            SBAddPrefixLess<SBAddPrefix,SBAddPrefix>);
+  std::sort(sub_prefixes.begin(), sub_prefixes.end(),
+            SBAddPrefixLess<SBSubPrefix,SBSubPrefix>);
+  std::sort(add_hashes.begin(), add_hashes.end(),
+            SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>);
+  std::sort(sub_hashes.begin(), sub_hashes.end(),
+            SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>);
+
   base::hash_set<int32> sub_deletions;
   sub_deletions.insert(kSubChunk1);
   SBProcessSubs(&add_prefixes, &sub_prefixes, &add_hashes, &sub_hashes,
diff --git a/chrome/browser/safe_browsing/signature_util.h b/chrome/browser/safe_browsing/signature_util.h
deleted file mode 100644
index 00aef61..0000000
--- a/chrome/browser/safe_browsing/signature_util.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Utility functions to check executable signatures for malicious binary
-// detection.  Each platform has its own implementation of this class.
-
-#ifndef CHROME_BROWSER_SAFE_BROWSING_SIGNATURE_UTIL_H_
-#define CHROME_BROWSER_SAFE_BROWSING_SIGNATURE_UTIL_H_
-
-#include "base/basictypes.h"
-#include "base/memory/ref_counted.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace safe_browsing {
-class ClientDownloadRequest_SignatureInfo;
-
-class SignatureUtil : public base::RefCountedThreadSafe<SignatureUtil> {
- public:
-  SignatureUtil();
-
-  // Fills in the DownloadRequest_SignatureInfo for the given file path.
-  // This method may be called on any thread.
-  virtual void CheckSignature(
-      const base::FilePath& file_path,
-      ClientDownloadRequest_SignatureInfo* signature_info);
-
- protected:
-  friend class base::RefCountedThreadSafe<SignatureUtil>;
-  virtual ~SignatureUtil();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SignatureUtil);
-};
-}  // namespace safe_browsing
-
-#endif  // CHROME_BROWSER_SAFE_BROWSING_SIGNATURE_UTIL_H_
diff --git a/chrome/browser/safe_browsing/signature_util_posix.cc b/chrome/browser/safe_browsing/signature_util_posix.cc
deleted file mode 100644
index 7a98a54..0000000
--- a/chrome/browser/safe_browsing/signature_util_posix.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This is a stub for the code signing utilities on Mac and Linux.
-// It should eventually be replaced with a real implementation.
-
-#include "chrome/browser/safe_browsing/signature_util.h"
-
-namespace safe_browsing {
-
-SignatureUtil::SignatureUtil() {}
-
-SignatureUtil::~SignatureUtil() {}
-
-void SignatureUtil::CheckSignature(
-    const base::FilePath& file_path,
-    ClientDownloadRequest_SignatureInfo* signature_info) {}
-
-}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/signature_util_win.cc b/chrome/browser/safe_browsing/signature_util_win.cc
deleted file mode 100644
index b512fca..0000000
--- a/chrome/browser/safe_browsing/signature_util_win.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/safe_browsing/signature_util.h"
-
-#include <windows.h>
-#include <softpub.h>
-#include <wintrust.h>
-
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "chrome/common/safe_browsing/csd.pb.h"
-
-#pragma comment(lib, "wintrust.lib")
-
-namespace safe_browsing {
-
-SignatureUtil::SignatureUtil() {}
-
-SignatureUtil::~SignatureUtil() {}
-
-void SignatureUtil::CheckSignature(
-    const base::FilePath& file_path,
-    ClientDownloadRequest_SignatureInfo* signature_info) {
-  VLOG(2) << "Checking signature for " << file_path.value();
-
-  WINTRUST_FILE_INFO file_info = {0};
-  file_info.cbStruct = sizeof(file_info);
-  file_info.pcwszFilePath = file_path.value().c_str();
-  file_info.hFile = NULL;
-  file_info.pgKnownSubject = NULL;
-
-  WINTRUST_DATA wintrust_data = {0};
-  wintrust_data.cbStruct = sizeof(wintrust_data);
-  wintrust_data.pPolicyCallbackData = NULL;
-  wintrust_data.pSIPClientData = NULL;
-  wintrust_data.dwUIChoice = WTD_UI_NONE;
-  wintrust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
-  wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
-  wintrust_data.pFile = &file_info;
-  wintrust_data.dwStateAction = WTD_STATEACTION_VERIFY;
-  wintrust_data.hWVTStateData = NULL;
-  wintrust_data.pwszURLReference = NULL;
-  // Disallow revocation checks over the network.
-  wintrust_data.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
-  wintrust_data.dwUIContext = WTD_UICONTEXT_EXECUTE;
-
-  // The WINTRUST_ACTION_GENERIC_VERIFY_V2 policy verifies that the certificate
-  // chains up to a trusted root CA, and that it has appropriate permission to
-  // sign code.
-  GUID policy_guid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
-
-  LONG result = WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE),
-                               &policy_guid,
-                               &wintrust_data);
-
-  CRYPT_PROVIDER_DATA* prov_data = WTHelperProvDataFromStateData(
-      wintrust_data.hWVTStateData);
-  if (prov_data) {
-    if (prov_data->csSigners > 0) {
-      signature_info->set_trusted(result == ERROR_SUCCESS);
-    }
-    for (DWORD i = 0; i < prov_data->csSigners; ++i) {
-      const CERT_CHAIN_CONTEXT* cert_chain_context =
-          prov_data->pasSigners[i].pChainContext;
-      if (!cert_chain_context)
-        break;
-      for (DWORD j = 0; j < cert_chain_context->cChain; ++j) {
-        CERT_SIMPLE_CHAIN* simple_chain = cert_chain_context->rgpChain[j];
-        ClientDownloadRequest_CertificateChain* chain =
-            signature_info->add_certificate_chain();
-        if (!simple_chain)
-          break;
-        for (DWORD k = 0; k < simple_chain->cElement; ++k) {
-          CERT_CHAIN_ELEMENT* element = simple_chain->rgpElement[k];
-          chain->add_element()->set_certificate(
-              element->pCertContext->pbCertEncoded,
-              element->pCertContext->cbCertEncoded);
-        }
-      }
-    }
-
-    // Free the provider data.
-    wintrust_data.dwStateAction = WTD_STATEACTION_CLOSE;
-    WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE),
-                   &policy_guid, &wintrust_data);
-  }
-}
-
-}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/signature_util_win_unittest.cc b/chrome/browser/safe_browsing/signature_util_win_unittest.cc
deleted file mode 100644
index 294a8e9..0000000
--- a/chrome/browser/safe_browsing/signature_util_win_unittest.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/safe_browsing/signature_util.h"
-
-#include <string>
-#include <vector>
-
-#include "base/base_paths.h"
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/path_service.h"
-#include "chrome/common/safe_browsing/csd.pb.h"
-#include "net/cert/x509_cert_types.h"
-#include "net/cert/x509_certificate.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace safe_browsing {
-
-class SignatureUtilWinTest : public testing::Test {
- protected:
-  virtual void SetUp() {
-    base::FilePath source_path;
-    ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &source_path));
-    testdata_path_ = source_path
-        .AppendASCII("chrome")
-        .AppendASCII("test")
-        .AppendASCII("data")
-        .AppendASCII("safe_browsing")
-        .AppendASCII("download_protection");
-  }
-
-  // Given a certificate chain protobuf, parse it into X509Certificates.
-  void ParseCertificateChain(
-      const ClientDownloadRequest_CertificateChain& chain,
-      std::vector<scoped_refptr<net::X509Certificate> >* certs) {
-    for (int i = 0; i < chain.element_size(); ++i) {
-      certs->push_back(
-          net::X509Certificate::CreateFromBytes(
-              chain.element(i).certificate().data(),
-              chain.element(i).certificate().size()));
-    }
-  }
-
-  base::FilePath testdata_path_;
-};
-
-TEST_F(SignatureUtilWinTest, UntrustedSignedBinary) {
-  // signed.exe is signed by an untrusted root CA.
-  scoped_refptr<SignatureUtil> signature_util(new SignatureUtil());
-  ClientDownloadRequest_SignatureInfo signature_info;
-  signature_util->CheckSignature(testdata_path_.Append(L"signed.exe"),
-                                 &signature_info);
-  ASSERT_EQ(1, signature_info.certificate_chain_size());
-  std::vector<scoped_refptr<net::X509Certificate> > certs;
-  ParseCertificateChain(signature_info.certificate_chain(0), &certs);
-  ASSERT_EQ(2, certs.size());
-  EXPECT_EQ("Joe's-Software-Emporium", certs[0]->subject().common_name);
-  EXPECT_EQ("Root Agency", certs[1]->subject().common_name);
-
-  EXPECT_TRUE(signature_info.has_trusted());
-  EXPECT_FALSE(signature_info.trusted());
-}
-
-TEST_F(SignatureUtilWinTest, TrustedBinary) {
-  // wow_helper.exe is signed using Google's signing certifiacte.
-  scoped_refptr<SignatureUtil> signature_util(new SignatureUtil());
-  ClientDownloadRequest_SignatureInfo signature_info;
-  signature_util->CheckSignature(testdata_path_.Append(L"wow_helper.exe"),
-                                 &signature_info);
-  ASSERT_EQ(1, signature_info.certificate_chain_size());
-  std::vector<scoped_refptr<net::X509Certificate> > certs;
-  ParseCertificateChain(signature_info.certificate_chain(0), &certs);
-  ASSERT_EQ(3, certs.size());
-
-  EXPECT_EQ("Google Inc", certs[0]->subject().common_name);
-  EXPECT_EQ("VeriSign Class 3 Code Signing 2009-2 CA",
-            certs[1]->subject().common_name);
-  EXPECT_EQ("Class 3 Public Primary Certification Authority",
-            certs[2]->subject().organization_unit_names[0]);
-
-  EXPECT_TRUE(signature_info.trusted());
-}
-
-TEST_F(SignatureUtilWinTest, UnsignedBinary) {
-  // unsigned.exe has no signature information.
-  scoped_refptr<SignatureUtil> signature_util(new SignatureUtil());
-  ClientDownloadRequest_SignatureInfo signature_info;
-  signature_util->CheckSignature(testdata_path_.Append(L"unsigned.exe"),
-                                 &signature_info);
-  EXPECT_EQ(0, signature_info.certificate_chain_size());
-  EXPECT_FALSE(signature_info.has_trusted());
-}
-
-TEST_F(SignatureUtilWinTest, NonExistentBinary) {
-  // Test a file that doesn't exist.
-  scoped_refptr<SignatureUtil> signature_util(new SignatureUtil());
-  ClientDownloadRequest_SignatureInfo signature_info;
-  signature_util->CheckSignature(testdata_path_.Append(L"doesnotexist.exe"),
-                                 &signature_info);
-  EXPECT_EQ(0, signature_info.certificate_chain_size());
-  EXPECT_FALSE(signature_info.has_trusted());
-}
-
-}  // namespace safe_browsing
diff --git a/chrome/browser/search/hotword_service.cc b/chrome/browser/search/hotword_service.cc
index b3d5cd3..044c86e 100644
--- a/chrome/browser/search/hotword_service.cc
+++ b/chrome/browser/search/hotword_service.cc
@@ -9,11 +9,13 @@
 #include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -21,6 +23,18 @@
 namespace {
 const int kMaxTimesToShowOptInPopup = 10;
 
+// Allowed languages for hotwording.
+static const char* kSupportedLocales[] = {
+  "en",
+  "en_us",
+  "en_gb",
+  "en_ca",
+  "en_au",
+  "fr_fr",
+  "de_de",
+  "ru_ru"
+};
+
 // Enum describing the state of the hotword preference.
 // This is used for UMA stats -- do not reorder or delete items; only add to
 // the end.
@@ -61,6 +75,17 @@
                             NUM_HOTWORD_EXTENSION_AVAILABILITY_METRICS);
 }
 
+void RecordLoggingMetrics(Profile* profile) {
+  // If the user is not opted in to hotword voice search, the audio logging
+  // metric is not valid so it is not recorded.
+  if (!profile->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled))
+    return;
+
+  UMA_HISTOGRAM_BOOLEAN(
+      "Hotword.HotwordAudioLogging",
+      profile->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled));
+}
+
 ExtensionService* GetExtensionService(Profile* profile) {
   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
@@ -88,10 +113,14 @@
 #else
       g_browser_process->GetApplicationLocale();
 #endif
-  // Only available for English now.
   std::string normalized_locale = l10n_util::NormalizeLocale(locale);
-  return normalized_locale == "en" || normalized_locale == "en_us" ||
-      normalized_locale =="en_US";
+  StringToLowerASCII(&normalized_locale);
+
+  for (size_t i = 0; i < arraysize(kSupportedLocales); i++) {
+    if (kSupportedLocales[i] == normalized_locale)
+      return true;
+  }
+  return false;
 }
 
 HotwordService::HotwordService(Profile* profile)
@@ -117,11 +146,35 @@
       prefs::kHotwordSearchEnabled,
       base::Bind(&HotwordService::OnHotwordSearchEnabledChanged,
                  base::Unretained(this)));
+
+  registrar_.Add(this,
+                 chrome::NOTIFICATION_EXTENSION_INSTALLED,
+                 content::Source<Profile>(profile_));
 }
 
 HotwordService::~HotwordService() {
 }
 
+void HotwordService::Observe(int type,
+                             const content::NotificationSource& source,
+                             const content::NotificationDetails& details) {
+  if (type == chrome::NOTIFICATION_EXTENSION_INSTALLED) {
+    const extensions::Extension* extension =
+        content::Details<const extensions::InstalledExtensionInfo>(details)
+              ->extension;
+    if (extension->id() == extension_misc::kHotwordExtensionId &&
+        !profile_->GetPrefs()->GetBoolean(prefs::kHotwordSearchEnabled)) {
+      DisableHotwordExtension(GetExtensionService(profile_));
+      // Once the extension is disabled, it will not be enabled until the
+      // user opts in at which point the pref registrar will take over
+      // enabling and disabling.
+      registrar_.Remove(this,
+                        chrome::NOTIFICATION_EXTENSION_INSTALLED,
+                        content::Source<Profile>(profile_));
+    }
+  }
+}
+
 bool HotwordService::ShouldShowOptInPopup() {
   if (profile_->IsOffTheRecord())
     return false;
@@ -157,6 +210,7 @@
       service->GetExtensionById(extension_misc::kHotwordExtensionId, true);
 
   RecordAvailabilityMetrics(service, extension);
+  RecordLoggingMetrics(profile_);
 
   return extension && IsHotwordAllowed();
 }
@@ -169,6 +223,13 @@
       DoesHotwordSupportLanguage(profile_);
 }
 
+bool HotwordService::IsOptedIntoAudioLogging() {
+  // Do not opt the user in if the preference has not been set.
+  return
+      profile_->GetPrefs()->HasPrefPath(prefs::kHotwordAudioLoggingEnabled) &&
+      profile_->GetPrefs()->GetBoolean(prefs::kHotwordAudioLoggingEnabled);
+}
+
 bool HotwordService::RetryHotwordExtension() {
   ExtensionService* extension_service = GetExtensionService(profile_);
   if (!extension_service)
diff --git a/chrome/browser/search/hotword_service.h b/chrome/browser/search/hotword_service.h
index 664a56a..def0df0 100644
--- a/chrome/browser/search/hotword_service.h
+++ b/chrome/browser/search/hotword_service.h
@@ -8,6 +8,8 @@
 #include "base/basictypes.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
 
 class ExtensionService;
 class Profile;
@@ -20,7 +22,8 @@
 
 // Provides an interface for the Hotword component that does voice triggered
 // search.
-class HotwordService : public KeyedService {
+class HotwordService : public content::NotificationObserver,
+                       public KeyedService {
  public:
   // Returns true if the hotword supports the current system language.
   static bool DoesHotwordSupportLanguage(Profile* profile);
@@ -28,6 +31,11 @@
   explicit HotwordService(Profile* profile);
   virtual ~HotwordService();
 
+  // Overridden from content::NotificationObserver:
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
   bool ShouldShowOptInPopup();
 
   // Used in testing to ensure that the popup is not shown more than this
@@ -46,6 +54,10 @@
   // and language.
   virtual bool IsHotwordAllowed();
 
+  // Checks if the user has opted into audio logging. Returns true if the user
+  // is opted in, false otherwise..
+  bool IsOptedIntoAudioLogging();
+
   // Used in the case of an error with the current hotword extension. Tries
   // to reload the extension or in the case of failure, tries to re-download it.
   // Returns true upon successful attempt at reload or if the extension has
@@ -65,6 +77,8 @@
 
   PrefChangeRegistrar pref_registrar_;
 
+  content::NotificationRegistrar registrar_;
+
   DISALLOW_COPY_AND_ASSIGN(HotwordService);
 };
 
diff --git a/chrome/browser/search/hotword_service_factory.cc b/chrome/browser/search/hotword_service_factory.cc
index 69ea28e..ba1d669 100644
--- a/chrome/browser/search/hotword_service_factory.cc
+++ b/chrome/browser/search/hotword_service_factory.cc
@@ -67,6 +67,12 @@
   prefs->RegisterIntegerPref(prefs::kHotwordOptInPopupTimesShown,
                              0,
                              user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+  // Although this is default true, users will not send back information to
+  // Google unless they have opted in to Hotwording at which point they must
+  // also confirm that they wish this preference to be true or opt out of it.
+  prefs->RegisterBooleanPref(prefs::kHotwordAudioLoggingEnabled,
+                             true,
+                             user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
 }
 
 KeyedService* HotwordServiceFactory::BuildServiceInstanceFor(
diff --git a/chrome/browser/search/hotword_service_unittest.cc b/chrome/browser/search/hotword_service_unittest.cc
index 4dca993..5da13fe 100644
--- a/chrome/browser/search/hotword_service_unittest.cc
+++ b/chrome/browser/search/hotword_service_unittest.cc
@@ -135,7 +135,7 @@
       hotword_internal::kHotwordFieldTrialName, "Good"));
 
   // Set the language to an invalid one.
-  SetApplicationLocale(static_cast<Profile*>(profile.get()), "non-english");
+  SetApplicationLocale(static_cast<Profile*>(profile.get()), "non-valid");
   EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(profile.get()));
 
   // Now with valid locales it should be fine.
@@ -145,9 +145,28 @@
   EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get()));
   SetApplicationLocale(static_cast<Profile*>(profile.get()), "en_us");
   EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get()));
+  SetApplicationLocale(static_cast<Profile*>(profile.get()), "de_DE");
+  EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get()));
+  SetApplicationLocale(static_cast<Profile*>(profile.get()), "fr_fr");
+  EXPECT_TRUE(HotwordServiceFactory::IsHotwordAllowed(profile.get()));
 
   // Test that incognito even with a valid locale and valid field trial
   // still returns false.
   SetApplicationLocale(static_cast<Profile*>(otr_profile.get()), "en");
   EXPECT_FALSE(HotwordServiceFactory::IsHotwordAllowed(otr_profile.get()));
 }
+
+TEST_F(HotwordServiceTest, AudioLoggingPrefSetCorrectly) {
+  TestingProfile::Builder profile_builder;
+  scoped_ptr<TestingProfile> profile = profile_builder.Build();
+
+  HotwordServiceFactory* hotword_service_factory =
+      HotwordServiceFactory::GetInstance();
+  HotwordService* hotword_service =
+      hotword_service_factory->GetForProfile(profile.get());
+  EXPECT_TRUE(hotword_service != NULL);
+
+  // If it's a fresh profile, although the default value is true,
+  // it should return false if the preference has never been set.
+  EXPECT_FALSE(hotword_service->IsOptedIntoAudioLogging());
+}
diff --git a/chrome/browser/search_engines/prepopulated_engines.json b/chrome/browser/search_engines/prepopulated_engines.json
index 9796452..4459da3 100644
--- a/chrome/browser/search_engines/prepopulated_engines.json
+++ b/chrome/browser/search_engines/prepopulated_engines.json
@@ -26,7 +26,7 @@
 
     // Increment this if you change the data in ways that mean users with
     // existing data should get a new version.
-    "kCurrentDataVersion": 69
+    "kCurrentDataVersion": 70
   },
 
   // The following engines are included in country lists and are added to the
@@ -1012,6 +1012,16 @@
       "id": 15
     },
 
+    "yandex_tr": {
+      "name": "Yandex",
+      "keyword": "yandex.com.tr",
+      "favicon_url": "http://yandex.st/islands-icons/_/6jyHGXR8-HAc8oJ1bU8qMUQQz_g.ico",
+      "search_url": "http://www.yandex.com.tr/yandsearch?text={searchTerms}",
+      "suggest_url": "http://suggest.yandex.com.tr/suggest-ff.cgi?part={searchTerms}",
+      "type": "SEARCH_ENGINE_YANDEX",
+      "id": 15
+    },
+
     "yandex_ua": {
       "name": "\u042f\u043d\u0434\u0435\u043a\u0441",
       "keyword": "yandex.ua",
@@ -1374,16 +1384,6 @@
       "id": 76
     },
 
-    "yandex_tr": {
-      "name": "Yandex",
-      "keyword": "yandex.com.tr",
-      "favicon_url": "http://yandex.st/islands-icons/_/6jyHGXR8-HAc8oJ1bU8qMUQQz_g.ico",
-      "search_url": "http://www.yandex.com.tr/yandsearch?text={searchTerms}",
-      "suggest_url": "http://suggest.yandex.com.tr/suggest-ff.cgi?part={searchTerms}",
-      "type": "SEARCH_ENGINE_YANDEX",
-      "id": 15
-    },
-
     "zoznam": {
       "name": "Zoznam",
       "keyword": "zoznam.sk",
diff --git a/chrome/browser/search_engines/search_terms_data.cc b/chrome/browser/search_engines/search_terms_data.cc
index 1d431b3..8e8d6f8 100644
--- a/chrome/browser/search_engines/search_terms_data.cc
+++ b/chrome/browser/search_engines/search_terms_data.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/search_engines/search_terms_data.h"
 
-#include "base/command_line.h"
 #include "base/logging.h"
 #include "base/metrics/field_trial.h"
 #include "base/prefs/pref_service.h"
@@ -16,7 +15,6 @@
 #include "chrome/browser/sync/glue/device_info.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
-#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
 #include "sync/protocol/sync.pb.h"
@@ -96,10 +94,9 @@
       BrowserThread::CurrentlyOn(BrowserThread::UI));
   if (google_base_url_)
     return *google_base_url_;
-  std::string base_url = CommandLine::ForCurrentProcess()->
-      GetSwitchValueASCII(switches::kGoogleBaseURL);
-  if (!base_url.empty())
-    return base_url;
+  GURL base_url(google_util::CommandLineGoogleBaseURL());
+  if (base_url.is_valid())
+    return base_url.spec();
   return profile_ ? GoogleURLTracker::GoogleURL(profile_).spec() :
       SearchTermsData::GoogleBaseURLValue();
 }
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index 22ea272..4ed0f89 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -436,7 +436,7 @@
 
 // Turkey
 const PrepopulatedEngine* engines_TR[] =
-    { &google, &bing_tr_TR, &yahoo_tr, };
+    { &google, &bing_tr_TR, &yahoo_tr, &yandex_tr, };
 
 // Trinidad and Tobago
 const PrepopulatedEngine* engines_TT[] =
@@ -504,7 +504,7 @@
   &yahoo_my,     &yahoo_nl,     &yahoo_nz,     &yahoo_pe,     &yahoo_ph,
   &yahoo_qc,     &yahoo_ro,     &yahoo_ru,     &yahoo_se,     &yahoo_sg,
   &yahoo_th,     &yahoo_tr,     &yahoo_tw,     &yahoo_uk,     &yahoo_ve,
-  &yahoo_vn,     &yahoo_za,     &yandex_ru,    &yandex_ua,
+  &yahoo_vn,     &yahoo_za,     &yandex_ru,    &yandex_tr,    &yandex_ua,
 
   // UMA-only engines:
   &atlas_cz,     &atlas_sk,     &avg,          &babylon,      &conduit,
@@ -513,7 +513,7 @@
   &neti,         &nigma,        &ok,           &rambler,      &sapo,
   &search_results, &searchnu,   &snapdo,       &softonic,     &sweetim,
   &terra_ar,     &terra_es,     &tut,          &walla,        &wp,
-  &yandex_tr,    &zoznam,
+  &zoznam,
 };
 
 const struct LogoURLs {
diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc
index 91704e0..bfdfe1c 100644
--- a/chrome/browser/search_engines/template_url_service.cc
+++ b/chrome/browser/search_engines/template_url_service.cc
@@ -2600,7 +2600,7 @@
     } else {
       // The value from the preferences takes over.
       default_search_provider = NULL;
-      if (default_from_prefs.get()) {
+      if (default_from_prefs) {
         TemplateURLData data(default_from_prefs->data());
         data.created_by_policy = true;
         data.id = kInvalidTemplateURLID;
@@ -2643,6 +2643,9 @@
     SetTemplateURLs(template_urls);
 
     if (default_search_provider) {
+      base::AutoReset<DefaultSearchChangeOrigin> change_origin(
+          &dsp_change_origin_, default_from_prefs ?
+              dsp_change_origin_ : DSP_CHANGE_NEW_ENGINE_NO_PREFS);
       // Note that this saves the default search provider to prefs.
       SetDefaultSearchProvider(default_search_provider);
     } else {
diff --git a/chrome/browser/search_engines/template_url_service.h b/chrome/browser/search_engines/template_url_service.h
index 6d919d6..bbd7f04 100644
--- a/chrome/browser/search_engines/template_url_service.h
+++ b/chrome/browser/search_engines/template_url_service.h
@@ -421,13 +421,17 @@
     // certain changes were intentionally from the system, or possibly some
     // unintentional change from when we were Syncing.
     DSP_CHANGE_SYNC_UNINTENTIONAL,
-    // All non-sync changes save PROFILE_RESET; we can't reorder the list for
-    // clarity as this would screw up stat collection.
+    // All changes that don't fall into another category; we can't reorder the
+    // list for clarity as this would screw up stat collection.
     DSP_CHANGE_OTHER,
     // Changed through "Profile Reset" feature.
     DSP_CHANGE_PROFILE_RESET,
     // Changed by an extension through the Override Settings API.
     DSP_CHANGE_OVERRIDE_SETTINGS_EXTENSION,
+    // New DSP during database/prepopulate data load, which was not previously
+    // in the known engine set, and with no previous value in prefs.  The
+    // typical time to see this is during first run.
+    DSP_CHANGE_NEW_ENGINE_NO_PREFS,
     // Boundary value.
     DSP_CHANGE_MAX,
   };
diff --git a/chrome/browser/service_process/service_process_control.cc b/chrome/browser/service_process/service_process_control.cc
index 15a902e..dbac06c 100644
--- a/chrome/browser/service_process/service_process_control.cc
+++ b/chrome/browser/service_process/service_process_control.cc
@@ -192,6 +192,7 @@
     IPC_MESSAGE_HANDLER(ServiceHostMsg_CloudPrintProxy_Info,
                         OnCloudPrintProxyInfo)
     IPC_MESSAGE_HANDLER(ServiceHostMsg_Histograms, OnHistograms)
+    IPC_MESSAGE_HANDLER(ServiceHostMsg_Printers, OnPrinters)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -272,8 +273,20 @@
   histograms_timeout_callback_.Cancel();
 }
 
+void ServiceProcessControl::OnPrinters(
+    const std::vector<std::string>& printers) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  UMA_HISTOGRAM_ENUMERATION(
+      "CloudPrint.ServiceEvents", SERVICE_PRINTERS_REPLY, SERVICE_EVENT_MAX);
+  UMA_HISTOGRAM_COUNTS_10000("CloudPrint.AvailablePrinters", printers.size());
+  if (!printers_callback_.is_null()) {
+    printers_callback_.Run(printers);
+    printers_callback_.Reset();
+  }
+}
+
 bool ServiceProcessControl::GetCloudPrintProxyInfo(
-    const CloudPrintProxyInfoHandler& cloud_print_info_callback) {
+    const CloudPrintProxyInfoCallback& cloud_print_info_callback) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   DCHECK(!cloud_print_info_callback.is_null());
   cloud_print_info_callback_.Reset();
@@ -316,6 +329,19 @@
   return true;
 }
 
+bool ServiceProcessControl::GetPrinters(
+    const PrintersCallback& printers_callback) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK(!printers_callback.is_null());
+  printers_callback_.Reset();
+  UMA_HISTOGRAM_ENUMERATION(
+      "CloudPrint.ServiceEvents", SERVICE_PRINTERS_REQUEST, SERVICE_EVENT_MAX);
+  if (!Send(new ServiceMsg_GetPrinters()))
+    return false;
+  printers_callback_ = printers_callback;
+  return true;
+}
+
 bool ServiceProcessControl::Shutdown() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   bool ret = Send(new ServiceMsg_Shutdown());
diff --git a/chrome/browser/service_process/service_process_control.h b/chrome/browser/service_process/service_process_control.h
index eedd4a3..9db9324 100644
--- a/chrome/browser/service_process/service_process_control.h
+++ b/chrome/browser/service_process/service_process_control.h
@@ -60,13 +60,17 @@
     SERVICE_EVENT_INFO_REPLY,
     SERVICE_EVENT_HISTOGRAMS_REQUEST,
     SERVICE_EVENT_HISTOGRAMS_REPLY,
+    SERVICE_PRINTERS_REQUEST,
+    SERVICE_PRINTERS_REPLY,
     SERVICE_EVENT_MAX,
   };
 
   typedef IDMap<ServiceProcessControl>::iterator iterator;
   typedef std::queue<IPC::Message> MessageQueue;
   typedef base::Callback<void(const cloud_print::CloudPrintProxyInfo&)>
-      CloudPrintProxyInfoHandler;
+      CloudPrintProxyInfoCallback;
+  typedef base::Callback<void(const std::vector<std::string>&)>
+      PrintersCallback;
 
   // Returns the singleton instance of this class.
   static ServiceProcessControl* GetInstance();
@@ -118,7 +122,7 @@
   // reply from service. The method resets any previous callback.
   // This call starts service if needed.
   bool GetCloudPrintProxyInfo(
-      const CloudPrintProxyInfoHandler& cloud_print_status_callback);
+      const CloudPrintProxyInfoCallback& cloud_print_status_callback);
 
   // Send request for histograms collected in service process.
   // Returns true if request was sent, and callback will be called in case of
@@ -128,6 +132,13 @@
   bool GetHistograms(const base::Closure& cloud_print_status_callback,
                      const base::TimeDelta& timeout);
 
+  // Send request for printers available for cloud print proxy.
+  // The callback gets the information when received.
+  // Returns true if request was sent. Callback will be called only in case of
+  // reply from service. The method resets any previous callback.
+  // This call starts service if needed.
+  bool GetPrinters(const PrintersCallback& enumerate_printers_callback);
+
  private:
   // This class is responsible for launching the service process on the
   // PROCESS_LAUNCHER thread.
@@ -175,6 +186,7 @@
   void OnCloudPrintProxyInfo(
       const cloud_print::CloudPrintProxyInfo& proxy_info);
   void OnHistograms(const std::vector<std::string>& pickled_histograms);
+  void OnPrinters(const std::vector<std::string>& printers);
 
   // Runs callback provided in |GetHistograms()|.
   void RunHistogramsCallback();
@@ -204,9 +216,13 @@
   // Callbacks that get invoked when there was a connection failure.
   TaskList connect_failure_tasks_;
 
+  // Callback that gets invoked when a printers is received from
+  // the cloud print proxy.
+  PrintersCallback printers_callback_;
+
   // Callback that gets invoked when a status message is received from
   // the cloud print proxy.
-  CloudPrintProxyInfoHandler cloud_print_info_callback_;
+  CloudPrintProxyInfoCallback cloud_print_info_callback_;
 
   // Callback that gets invoked when a message with histograms is received from
   // the service process.
diff --git a/chrome/browser/services/gcm/gcm_client_factory.cc b/chrome/browser/services/gcm/gcm_client_factory.cc
index ef78865..053b01c 100644
--- a/chrome/browser/services/gcm/gcm_client_factory.cc
+++ b/chrome/browser/services/gcm/gcm_client_factory.cc
@@ -9,7 +9,8 @@
 namespace gcm {
 
 scoped_ptr<GCMClient> GCMClientFactory::BuildInstance() {
-  return scoped_ptr<GCMClient>(new GCMClientImpl());
+  return scoped_ptr<GCMClient>(new GCMClientImpl(
+      make_scoped_ptr<GCMInternalsBuilder>(new GCMInternalsBuilder())));
 }
 
 GCMClientFactory::GCMClientFactory() {
diff --git a/chrome/browser/services/gcm/gcm_profile_service.cc b/chrome/browser/services/gcm/gcm_profile_service.cc
index 2f8fcc0..03cbb82 100644
--- a/chrome/browser/services/gcm/gcm_profile_service.cc
+++ b/chrome/browser/services/gcm/gcm_profile_service.cc
@@ -16,7 +16,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/state_store.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/services/gcm/gcm_app_handler.h"
 #include "chrome/browser/services/gcm/gcm_client_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
@@ -26,12 +26,11 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
-#include "extensions/browser/extension_system.h"
 #include "google_apis/gcm/protocol/android_checkin.pb.h"
 #include "net/url_request/url_request_context_getter.h"
 
@@ -39,15 +38,13 @@
 
 namespace {
 
-const char kRegistrationKey[] = "gcm.registration";
-const char kSendersKey[] = "senders";
-const char kRegistrationIDKey[] = "reg_id";
-
 checkin_proto::ChromeBuildProto_Platform GetPlatform() {
 #if defined(OS_WIN)
   return checkin_proto::ChromeBuildProto_Platform_PLATFORM_WIN;
 #elif defined(OS_MACOSX)
   return checkin_proto::ChromeBuildProto_Platform_PLATFORM_MAC;
+#elif defined(OS_IOS)
+  return checkin_proto::ChromeBuildProto_Platform_PLATFORM_IOS;
 #elif defined(OS_CHROMEOS)
   return checkin_proto::ChromeBuildProto_Platform_PLATFORM_CROS;
 #elif defined(OS_LINUX)
@@ -90,139 +87,51 @@
   DelayedTaskController();
   ~DelayedTaskController();
 
-  // Adds an app to the tracking list. It will be first marked as not ready.
-  // Tasks will be queued for delay execution until the app is marked as ready.
-  void AddApp(const std::string& app_id);
-
-  // Removes the app from the tracking list.
-  void RemoveApp(const std::string& app_id);
-
   // Adds a task that will be invoked once we're ready.
-  void AddTask(const std::string& app_id, base::Closure task);
+  void AddTask(base::Closure task);
 
-  // Sets GCM ready status. GCM is ready only when check-in is completed and
-  // the GCMClient is fully initialized. If it is set to ready for the first
-  // time, all the pending tasks for any ready apps will be run.
-  void SetGCMReady();
+  // Sets ready status. It is ready only when check-in is completed and
+  // the GCMClient is fully initialized.
+  void SetReady();
 
-  // Sets ready status for the app. If GCM is already ready, all the pending
-  // tasks for this app will be run.
-  void SetAppReady(const std::string& app_id);
-
-  // Returns true if it is ready to perform operations for an app.
-  bool CanRunTaskWithoutDelay(const std::string& app_id) const;
-
-  // Returns true if the app has been tracked for readiness.
-  bool IsAppTracked(const std::string& app_id) const;
+  // Returns true if it is ready to perform tasks.
+  bool CanRunTaskWithoutDelay() const;
 
  private:
-  struct AppTaskQueue {
-    AppTaskQueue();
-    ~AppTaskQueue();
+  void RunTasks();
 
-    // The flag that indicates if GCMClient is ready.
-    bool ready;
+  // Flag that indicates that GCM is ready.
+  bool ready_;
 
-    // Tasks to be invoked upon ready.
-    std::vector<base::Closure> tasks;
-  };
-
-  void RunTasks(AppTaskQueue* task_queue);
-
-  // Flag that indicates that GCM is done.
-  bool gcm_ready_;
-
-  // Map from app_id to AppTaskQueue storing the tasks that will be invoked
-  // when both GCM and the app get ready.
-  typedef std::map<std::string, AppTaskQueue*> DelayedTaskMap;
-  DelayedTaskMap delayed_task_map_;
+  std::vector<base::Closure> delayed_tasks_;
 };
 
-GCMProfileService::DelayedTaskController::AppTaskQueue::AppTaskQueue()
-    : ready(false) {
-}
-
-GCMProfileService::DelayedTaskController::AppTaskQueue::~AppTaskQueue() {
-}
-
 GCMProfileService::DelayedTaskController::DelayedTaskController()
-    : gcm_ready_(false) {
+    : ready_(false) {
 }
 
 GCMProfileService::DelayedTaskController::~DelayedTaskController() {
-  for (DelayedTaskMap::const_iterator iter = delayed_task_map_.begin();
-       iter != delayed_task_map_.end(); ++iter) {
-    delete iter->second;
-  }
 }
 
-void GCMProfileService::DelayedTaskController::AddApp(
-    const std::string& app_id) {
-  DCHECK(delayed_task_map_.find(app_id) == delayed_task_map_.end());
-  delayed_task_map_[app_id] = new AppTaskQueue;
+void GCMProfileService::DelayedTaskController::AddTask(base::Closure task) {
+  delayed_tasks_.push_back(task);
 }
 
-void GCMProfileService::DelayedTaskController::RemoveApp(
-    const std::string& app_id) {
-  DelayedTaskMap::iterator iter = delayed_task_map_.find(app_id);
-  if (iter == delayed_task_map_.end())
-    return;
-  delete iter->second;
-  delayed_task_map_.erase(iter);
+void GCMProfileService::DelayedTaskController::SetReady() {
+  ready_ = true;
+  RunTasks();
 }
 
-void GCMProfileService::DelayedTaskController::AddTask(
-    const std::string& app_id, base::Closure task) {
-  DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id);
-  DCHECK(iter != delayed_task_map_.end());
-  iter->second->tasks.push_back(task);
+bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay() const {
+  return ready_;
 }
 
-void GCMProfileService::DelayedTaskController::SetGCMReady() {
-  gcm_ready_ = true;
+void GCMProfileService::DelayedTaskController::RunTasks() {
+  DCHECK(ready_);
 
-  for (DelayedTaskMap::iterator iter = delayed_task_map_.begin();
-       iter != delayed_task_map_.end(); ++iter) {
-    if (iter->second->ready)
-      RunTasks(iter->second);
-  }
-}
-
-void GCMProfileService::DelayedTaskController::SetAppReady(
-    const std::string& app_id) {
-  DelayedTaskMap::iterator iter = delayed_task_map_.find(app_id);
-  DCHECK(iter != delayed_task_map_.end());
-
-  AppTaskQueue* task_queue = iter->second;
-  DCHECK(task_queue);
-  task_queue->ready = true;
-
-  if (gcm_ready_)
-    RunTasks(task_queue);
-}
-
-bool GCMProfileService::DelayedTaskController::CanRunTaskWithoutDelay(
-    const std::string& app_id) const {
-  if (!gcm_ready_)
-    return false;
-  DelayedTaskMap::const_iterator iter = delayed_task_map_.find(app_id);
-  if (iter == delayed_task_map_.end())
-    return true;
-  return iter->second->ready;
-}
-
-bool GCMProfileService::DelayedTaskController::IsAppTracked(
-    const std::string& app_id) const {
-  return delayed_task_map_.find(app_id) != delayed_task_map_.end();
-}
-
-void GCMProfileService::DelayedTaskController::RunTasks(
-    AppTaskQueue* task_queue) {
-  DCHECK(gcm_ready_ && task_queue->ready);
-
-  for (size_t i = 0; i < task_queue->tasks.size(); ++i)
-    task_queue->tasks[i].Run();
-  task_queue->tasks.clear();
+  for (size_t i = 0; i < delayed_tasks_.size(); ++i)
+    delayed_tasks_[i].Run();
+  delayed_tasks_.clear();
 }
 
 class GCMProfileService::IOWorker
@@ -494,16 +403,6 @@
   }
 }
 
-GCMProfileService::RegistrationInfo::RegistrationInfo() {
-}
-
-GCMProfileService::RegistrationInfo::~RegistrationInfo() {
-}
-
-bool GCMProfileService::RegistrationInfo::IsValid() const {
-  return !sender_ids.empty() && !registration_id.empty();
-}
-
 // static
 GCMProfileService::GCMEnabledState GCMProfileService::GetGCMEnabledState(
     Profile* profile) {
@@ -534,9 +433,6 @@
       prefs::kGCMChannelEnabled,
       on_by_default,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-  registry->RegisterListPref(
-      prefs::kGCMRegisteredAppIDs,
-      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
 }
 
 GCMProfileService::GCMProfileService(Profile* profile)
@@ -652,9 +548,8 @@
   register_callbacks_[app_id] = callback;
 
   // Delay the register operation until GCMClient is ready.
-  if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) {
+  if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
     delayed_task_controller_->AddTask(
-        app_id,
         base::Bind(&GCMProfileService::DoRegister,
                    weak_ptr_factory_.GetWeakPtr(),
                    app_id,
@@ -678,29 +573,6 @@
   std::vector<std::string> normalized_sender_ids = sender_ids;
   std::sort(normalized_sender_ids.begin(), normalized_sender_ids.end());
 
-  // If the same sender ids is provided, return the cached registration ID
-  // directly.
-  RegistrationInfoMap::const_iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  if (registration_info_iter != registration_info_map_.end() &&
-      registration_info_iter->second.sender_ids == normalized_sender_ids) {
-    RegisterCallback callback = callback_iter->second;
-    register_callbacks_.erase(callback_iter);
-    callback.Run(registration_info_iter->second.registration_id,
-                 GCMClient::SUCCESS);
-    return;
-  }
-
-  // Cache the sender IDs. The registration ID will be filled when the
-  // registration completes.
-  RegistrationInfo registration_info;
-  registration_info.sender_ids = normalized_sender_ids;
-  registration_info_map_[app_id] = registration_info;
-
-  // Save the IDs of all registered apps such that we know what to remove from
-  // the the app's state store when the profile is signed out.
-  WriteRegisteredAppIDs();
-
   content::BrowserThread::PostTask(
       content::BrowserThread::IO,
       FROM_HERE,
@@ -730,9 +602,8 @@
   unregister_callbacks_[app_id] = callback;
 
   // Delay the unregister operation until GCMClient is ready.
-  if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) {
+  if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
     delayed_task_controller_->AddTask(
-        app_id,
         base::Bind(&GCMProfileService::DoUnregister,
                    weak_ptr_factory_.GetWeakPtr(),
                    app_id));
@@ -745,23 +616,6 @@
 void GCMProfileService::DoUnregister(const std::string& app_id) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
 
-  // Unregister might be triggered in response to a message that is missing
-  // recipient and in that case there will not be an entry in the map.
-  RegistrationInfoMap::iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  if (registration_info_iter != registration_info_map_.end()) {
-    registration_info_map_.erase(registration_info_iter);
-
-    // Update the persisted IDs of registered apps.
-    WriteRegisteredAppIDs();
-
-    // Remove the persisted registration info.
-    DeleteRegistrationInfo(app_id);
-
-    // No need to track the app any more.
-    delayed_task_controller_->RemoveApp(app_id);
-  }
-
   // Ask the server to unregister it. There could be a small chance that the
   // unregister request fails. If this occurs, it does not bring any harm since
   // we simply reject the messages/events received from the server.
@@ -796,9 +650,8 @@
   send_callbacks_[key] = callback;
 
   // Delay the send operation until all GCMClient is ready.
-  if (!delayed_task_controller_->CanRunTaskWithoutDelay(app_id)) {
+  if (!delayed_task_controller_->CanRunTaskWithoutDelay()) {
     delayed_task_controller_->AddTask(
-        app_id,
         base::Bind(&GCMProfileService::DoSend,
                    weak_ptr_factory_.GetWeakPtr(),
                    app_id,
@@ -890,9 +743,6 @@
   DCHECK(!delayed_task_controller_);
   delayed_task_controller_.reset(new DelayedTaskController);
 
-  // Load all the registered apps.
-  ReadRegisteredAppIDs();
-
   // This will load the data from the gcm store and trigger the check-in if
   // the persisted check-in info is not found.
   // Note that we need to pass weak pointer again since the existing weak
@@ -915,19 +765,6 @@
   delayed_task_controller_.reset();
   register_callbacks_.clear();
   send_callbacks_.clear();
-  registration_info_map_.clear();
-}
-
-void GCMProfileService::RemovePersistedData() {
-  // Remove persisted data from app's state store.
-  for (RegistrationInfoMap::const_iterator iter =
-           registration_info_map_.begin();
-       iter != registration_info_map_.end(); ++iter) {
-    DeleteRegistrationInfo(iter->first);
-  }
-
-  // Remove persisted data from prefs store.
-  profile_->GetPrefs()->ClearPref(prefs::kGCMRegisteredAppIDs);
 }
 
 void GCMProfileService::CheckOut() {
@@ -937,10 +774,6 @@
   // initiated in the current session. This will make sure that all the
   // persisted data written previously will get purged.
 
-  // This has to be done before removing the cached data since we need to do
-  // the lookup based on the cached data.
-  RemovePersistedData();
-
   RemoveCachedData();
 
   content::BrowserThread::PostTask(
@@ -964,10 +797,6 @@
   if (username_.empty())
     return GCMClient::NOT_SIGNED_IN;
 
-  // Ensure that app registration information was read.
-  if (!delayed_task_controller_->IsAppTracked(app_id))
-    ReadRegistrationInfo(app_id);
-
   return GCMClient::SUCCESS;
 }
 
@@ -989,20 +818,6 @@
     return;
   }
 
-  // Cache the registration ID if the registration succeeds. Otherwise,
-  // removed the cached info.
-  RegistrationInfoMap::iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  // This is unlikely to happen because the app will not be uninstalled before
-  // the asynchronous extension function completes.
-  DCHECK(registration_info_iter != registration_info_map_.end());
-  if (result == GCMClient::SUCCESS) {
-    registration_info_iter->second.registration_id = registration_id;
-    WriteRegistrationInfo(app_id);
-  } else {
-    registration_info_map_.erase(registration_info_iter);
-  }
-
   RegisterCallback callback = callback_iter->second;
   register_callbacks_.erase(callback_iter);
   callback.Run(registration_id, result);
@@ -1048,16 +863,6 @@
   if (username_.empty())
     return;
 
-  // Dropping the message when application does not have a registration entry
-  // or the app is not registered for the sender of the message.
-  RegistrationInfoMap::iterator iter = registration_info_map_.find(app_id);
-  if (iter == registration_info_map_.end() ||
-      std::find(iter->second.sender_ids.begin(),
-                iter->second.sender_ids.end(),
-                message.sender_id) == iter->second.sender_ids.end()) {
-    return;
-  }
-
   GetAppHandler(app_id)->OnMessage(app_id, message);
 }
 
@@ -1090,7 +895,7 @@
     return;
   gcm_client_ready_ = true;
 
-  delayed_task_controller_->SetGCMReady();
+  delayed_task_controller_->SetReady();
 }
 
 GCMAppHandler* GCMProfileService::GetAppHandler(const std::string& app_id) {
@@ -1099,118 +904,6 @@
   return iter == app_handlers_.end() ? &default_app_handler_ : iter->second;
 }
 
-void GCMProfileService::ReadRegisteredAppIDs() {
-  const base::ListValue* app_id_list =
-      profile_->GetPrefs()->GetList(prefs::kGCMRegisteredAppIDs);
-  for (size_t i = 0; i < app_id_list->GetSize(); ++i) {
-    std::string app_id;
-    if (!app_id_list->GetString(i, &app_id))
-      continue;
-    ReadRegistrationInfo(app_id);
-  }
-}
-
-void GCMProfileService::WriteRegisteredAppIDs() {
-  base::ListValue apps;
-  for (RegistrationInfoMap::const_iterator iter =
-           registration_info_map_.begin();
-       iter != registration_info_map_.end(); ++iter) {
-    apps.Append(new base::StringValue(iter->first));
-  }
-  profile_->GetPrefs()->Set(prefs::kGCMRegisteredAppIDs, apps);
-}
-
-void GCMProfileService::DeleteRegistrationInfo(const std::string& app_id) {
-  extensions::StateStore* storage =
-      extensions::ExtensionSystem::Get(profile_)->state_store();
-  DCHECK(storage);
-
-  storage->RemoveExtensionValue(app_id, kRegistrationKey);
-}
-
-void GCMProfileService::WriteRegistrationInfo(const std::string& app_id) {
-  extensions::StateStore* storage =
-      extensions::ExtensionSystem::Get(profile_)->state_store();
-  DCHECK(storage);
-
-  RegistrationInfoMap::const_iterator registration_info_iter =
-      registration_info_map_.find(app_id);
-  if (registration_info_iter == registration_info_map_.end())
-    return;
-  const RegistrationInfo& registration_info = registration_info_iter->second;
-
-  scoped_ptr<base::ListValue> senders_list(new base::ListValue());
-  for (std::vector<std::string>::const_iterator senders_iter =
-           registration_info.sender_ids.begin();
-       senders_iter != registration_info.sender_ids.end();
-       ++senders_iter) {
-    senders_list->AppendString(*senders_iter);
-  }
-
-  scoped_ptr<base::DictionaryValue> registration_info_dict(
-      new base::DictionaryValue());
-  registration_info_dict->Set(kSendersKey, senders_list.release());
-  registration_info_dict->SetString(kRegistrationIDKey,
-                                    registration_info.registration_id);
-
-  storage->SetExtensionValue(
-      app_id, kRegistrationKey, registration_info_dict.PassAs<base::Value>());
-}
-
-void GCMProfileService::ReadRegistrationInfo(const std::string& app_id) {
-  delayed_task_controller_->AddApp(app_id);
-
-  extensions::StateStore* storage =
-      extensions::ExtensionSystem::Get(profile_)->state_store();
-  DCHECK(storage);
-  storage->GetExtensionValue(
-      app_id,
-      kRegistrationKey,
-      base::Bind(
-          &GCMProfileService::ReadRegistrationInfoFinished,
-          weak_ptr_factory_.GetWeakPtr(),
-          app_id));
-}
-
-void GCMProfileService::ReadRegistrationInfoFinished(
-    const std::string& app_id,
-    scoped_ptr<base::Value> value) {
-  RegistrationInfo registration_info;
-  if (value &&
-     !ParsePersistedRegistrationInfo(value.Pass(), &registration_info)) {
-    // Delete the persisted data if it is corrupted.
-    DeleteRegistrationInfo(app_id);
-  }
-
-  if (registration_info.IsValid())
-    registration_info_map_[app_id] = registration_info;
-
-  delayed_task_controller_->SetAppReady(app_id);
-}
-
-bool GCMProfileService::ParsePersistedRegistrationInfo(
-    scoped_ptr<base::Value> value,
-    RegistrationInfo* registration_info) {
-  base::DictionaryValue* dict = NULL;
-  if (!value.get() || !value->GetAsDictionary(&dict))
-    return false;
-
-  if (!dict->GetString(kRegistrationIDKey, &registration_info->registration_id))
-    return false;
-
-  const base::ListValue* senders_list = NULL;
-  if (!dict->GetList(kSendersKey, &senders_list) || !senders_list->GetSize())
-    return false;
-  for (size_t i = 0; i < senders_list->GetSize(); ++i) {
-    std::string sender;
-    if (!senders_list->GetString(i, &sender))
-      return false;
-    registration_info->sender_ids.push_back(sender);
-  }
-
-  return true;
-}
-
 void GCMProfileService::RequestGCMStatisticsFinished(
     GCMClient::GCMStatistics stats) {
   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
@@ -1218,9 +911,4 @@
   request_gcm_statistics_callback_.Run(stats);
 }
 
-// static
-const char* GCMProfileService::GetPersistentRegisterKeyForTesting() {
-  return kRegistrationKey;
-}
-
 }  // namespace gcm
diff --git a/chrome/browser/services/gcm/gcm_profile_service.h b/chrome/browser/services/gcm/gcm_profile_service.h
index 672fccc..39b7266 100644
--- a/chrome/browser/services/gcm/gcm_profile_service.h
+++ b/chrome/browser/services/gcm/gcm_profile_service.h
@@ -15,8 +15,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/services/gcm/default_gcm_app_handler.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "google_apis/gcm/gcm_client.h"
@@ -135,15 +135,6 @@
   class DelayedTaskController;
   class IOWorker;
 
-  struct RegistrationInfo {
-    RegistrationInfo();
-    ~RegistrationInfo();
-    bool IsValid() const;
-
-    std::vector<std::string> sender_ids;
-    std::string registration_id;
-  };
-
   typedef std::map<std::string, GCMAppHandler*> GCMAppHandlerMap;
 
   // Overridden from content::NotificationObserver:
@@ -160,9 +151,8 @@
   // the profile was signed in.
   void EnsureLoaded();
 
-  // Remove cached or persisted data when GCM service is stopped.
+  // Remove cached data when GCM service is stopped.
   void RemoveCachedData();
-  void RemovePersistedData();
 
   // Checks out of GCM when the profile has been signed out. This will erase
   // all the cached and persisted data.
@@ -204,24 +194,8 @@
   // Returns the handler for the given app.
   GCMAppHandler* GetAppHandler(const std::string& app_id);
 
-  // Used to persist the IDs of registered apps.
-  void ReadRegisteredAppIDs();
-  void WriteRegisteredAppIDs();
-
-  // Used to persist registration info into the app's state store.
-  void DeleteRegistrationInfo(const std::string& app_id);
-  void WriteRegistrationInfo(const std::string& app_id);
-  void ReadRegistrationInfo(const std::string& app_id);
-  void ReadRegistrationInfoFinished(const std::string& app_id,
-                                    scoped_ptr<base::Value> value);
-  bool ParsePersistedRegistrationInfo(scoped_ptr<base::Value> value,
-                                      RegistrationInfo* registration_info);
   void RequestGCMStatisticsFinished(GCMClient::GCMStatistics stats);
 
-  // Returns the key used to identify the registration info saved into the
-  // app's state store. Used for testing purpose.
-  static const char* GetPersistentRegisterKeyForTesting();
-
   // The profile which owns this object.
   Profile* profile_;
 
@@ -257,10 +231,6 @@
   // Callback for RequestGCMStatistics.
   RequestGCMStatisticsCallback request_gcm_statistics_callback_;
 
-  // Map from app_id to registration info (sender ids & registration ID).
-  typedef std::map<std::string, RegistrationInfo> RegistrationInfoMap;
-  RegistrationInfoMap registration_info_map_;
-
   // Used to pass a weak pointer to the IO worker.
   base::WeakPtrFactory<GCMProfileService> weak_ptr_factory_;
 
diff --git a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc
index 827368c..4bf894e 100644
--- a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc
+++ b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc
@@ -21,13 +21,15 @@
 #include "chrome/browser/services/gcm/gcm_client_mock.h"
 #include "chrome/browser/services/gcm/gcm_profile_service.h"
 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
-#include "chrome/browser/signin/signin_manager_base.h"
+#include "chrome/browser/signin/chrome_signin_client.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/os_crypt/os_crypt.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "extensions/browser/event_router.h"
@@ -40,6 +42,8 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/settings/device_settings_service.h"
+#else
+#include "chrome/browser/signin/signin_manager.h"
 #endif
 
 using namespace extensions;
@@ -129,7 +133,10 @@
 
 class FakeSigninManager : public SigninManagerBase {
  public:
-  explicit FakeSigninManager(Profile* profile) {
+  explicit FakeSigninManager(Profile* profile)
+      : SigninManagerBase(
+            ChromeSigninClientFactory::GetInstance()->GetForProfile(profile)),
+        profile_(profile) {
     Initialize(profile, NULL);
   }
 
@@ -146,9 +153,12 @@
   void SignOut() {
     std::string username = GetAuthenticatedUsername();
     clear_authenticated_username();
-    profile()->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
+    profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
     FOR_EACH_OBSERVER(Observer, observer_list_, GoogleSignedOut(username));
   }
+
+ private:
+  Profile* profile_;
 };
 
 }  // namespace
@@ -280,12 +290,15 @@
         has_persisted_registration_info_(false),
         send_result_(GCMClient::SUCCESS) {
     // Create a new profile.
-    profile_.reset(new TestingProfile);
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(
+        SigninManagerFactory::GetInstance(),
+        GCMProfileServiceTestConsumer::BuildFakeSigninManager);
+    profile_ = builder.Build();
 
-    // Use a fake version of SigninManager.
-    signin_manager_ = static_cast<FakeSigninManager*>(
-        SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-            profile(), &GCMProfileServiceTestConsumer::BuildFakeSigninManager));
+    SigninManagerBase* signin_manager =
+        SigninManagerFactory::GetInstance()->GetForProfile(profile_.get());
+    signin_manager_ = static_cast<FakeSigninManager*>(signin_manager);
 
     // Create extension service in order to uninstall the extension.
     extensions::TestExtensionSystem* extension_system(
@@ -395,26 +408,6 @@
     waiter_->SignalCompleted();
   }
 
-  bool HasPersistedRegistrationInfo(const std::string& app_id) {
-    StateStore* storage = ExtensionSystem::Get(profile())->state_store();
-    if (!storage)
-      return false;
-    has_persisted_registration_info_ = false;
-    storage->GetExtensionValue(
-        app_id,
-        GCMProfileService::GetPersistentRegisterKeyForTesting(),
-        base::Bind(
-            &GCMProfileServiceTestConsumer::ReadRegistrationInfoFinished,
-            base::Unretained(this)));
-    waiter_->WaitUntilCompleted();
-    return has_persisted_registration_info_;
-  }
-
-  void ReadRegistrationInfoFinished(scoped_ptr<base::Value> value) {
-    has_persisted_registration_info_ = value.get() != NULL;
-    waiter_->SignalCompleted();
-  }
-
   void Send(const std::string& app_id,
             const std::string& receiver_id,
             const GCMClient::OutgoingMessage& message) {
@@ -461,10 +454,6 @@
     return GetGCMProfileService()->gcm_client_ready_;
   }
 
-  bool ExistsCachedRegistrationInfo() const {
-    return !GetGCMProfileService()->registration_info_map_.empty();
-  }
-
   bool HasAppHandlers() const {
     return !GetGCMProfileService()->app_handlers_.empty();
   }
@@ -872,12 +861,13 @@
   consumer()->clear_registration_result();
 
   // Calling register 2nd time with the same set of sender IDs but different
-  // ordering will get back the same registration ID. There is no need to wait
-  // since register simply returns the cached registration ID.
+  // ordering will get back the same registration ID.
   std::vector<std::string> another_sender_ids;
   another_sender_ids.push_back("sender2");
   another_sender_ids.push_back("sender1");
   consumer()->Register(kTestingAppId, another_sender_ids);
+
+  WaitUntilCompleted();
   EXPECT_EQ(expected_registration_id, consumer()->registration_id());
   EXPECT_EQ(GCMClient::SUCCESS, consumer()->registration_result());
 }
@@ -907,40 +897,6 @@
   EXPECT_EQ(GCMClient::SUCCESS, consumer()->registration_result());
 }
 
-TEST_F(GCMProfileServiceSingleProfileTest, ReadRegistrationFromStateStore) {
-  scoped_refptr<Extension> extension(consumer()->CreateExtension());
-
-  std::vector<std::string> sender_ids;
-  sender_ids.push_back("sender1");
-  consumer()->Register(extension->id(), sender_ids);
-
-  WaitUntilCompleted();
-  EXPECT_FALSE(consumer()->registration_id().empty());
-  EXPECT_EQ(GCMClient::SUCCESS, consumer()->registration_result());
-  std::string old_registration_id = consumer()->registration_id();
-
-  // Clears the results that would be set by the Register callback in
-  // preparation to call register 2nd time.
-  consumer()->clear_registration_result();
-
-  // Register should not reach the server. Forcing GCMClient server error should
-  // help catch this.
-  consumer()->set_gcm_client_error_simulation(GCMClientMock::FORCE_ERROR);
-
-  // Simulate start-up by recreating GCMProfileService.
-  consumer()->CreateGCMProfileServiceInstance();
-
-  // Simulate start-up by reloading extension.
-  consumer()->ReloadExtension(extension);
-
-  // This should read the registration info from the extension's state store.
-  consumer()->Register(extension->id(), sender_ids);
-  PumpIOLoop();
-  PumpUILoop();
-  EXPECT_EQ(old_registration_id, consumer()->registration_id());
-  EXPECT_EQ(GCMClient::SUCCESS, consumer()->registration_result());
-}
-
 TEST_F(GCMProfileServiceSingleProfileTest,
        GCMClientReadyAfterReadingRegistration) {
   scoped_refptr<Extension> extension(consumer()->CreateExtension());
@@ -979,25 +935,6 @@
   EXPECT_EQ(GCMClient::SUCCESS, consumer()->registration_result());
 }
 
-TEST_F(GCMProfileServiceSingleProfileTest,
-       PersistedRegistrationInfoRemoveAfterSignOut) {
-  std::vector<std::string> sender_ids;
-  sender_ids.push_back("sender1");
-  consumer()->Register(kTestingAppId, sender_ids);
-  WaitUntilCompleted();
-
-  // The app id and registration info should be persisted.
-  EXPECT_TRUE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMRegisteredAppIDs));
-  EXPECT_TRUE(consumer()->HasPersistedRegistrationInfo(kTestingAppId));
-
-  consumer()->SignOut();
-  PumpUILoop();
-
-  // The app id and persisted registration info should be removed.
-  EXPECT_FALSE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMRegisteredAppIDs));
-  EXPECT_FALSE(consumer()->HasPersistedRegistrationInfo(kTestingAppId));
-}
-
 TEST_F(GCMProfileServiceSingleProfileTest, RegisterAfterSignOut) {
   // This will trigger check-out.
   consumer()->SignOut();
@@ -1021,21 +958,9 @@
   EXPECT_FALSE(consumer()->registration_id().empty());
   EXPECT_EQ(GCMClient::SUCCESS, consumer()->registration_result());
 
-  // The registration info should be cached.
-  EXPECT_TRUE(consumer()->ExistsCachedRegistrationInfo());
-
-  // The registration info should be persisted.
-  EXPECT_TRUE(consumer()->HasPersistedRegistrationInfo(extension->id()));
-
   // Uninstall the extension.
   consumer()->UninstallExtension(extension);
   base::MessageLoop::current()->RunUntilIdle();
-
-  // The cached registration info should be removed.
-  EXPECT_FALSE(consumer()->ExistsCachedRegistrationInfo());
-
-  // The persisted registration info should be removed.
-  EXPECT_FALSE(consumer()->HasPersistedRegistrationInfo(extension->id()));
 }
 
 TEST_F(GCMProfileServiceSingleProfileTest, UnregisterExplicitly) {
@@ -1047,22 +972,10 @@
   EXPECT_FALSE(consumer()->registration_id().empty());
   EXPECT_EQ(GCMClient::SUCCESS, consumer()->registration_result());
 
-  // The registration info should be cached.
-  EXPECT_TRUE(consumer()->ExistsCachedRegistrationInfo());
-
-  // The registration info should be persisted.
-  EXPECT_TRUE(consumer()->HasPersistedRegistrationInfo(kTestingAppId));
-
   consumer()->Unregister(kTestingAppId);
 
   WaitUntilCompleted();
   EXPECT_EQ(GCMClient::SUCCESS, consumer()->unregistration_result());
-
-  // The cached registration info should be removed.
-  EXPECT_FALSE(consumer()->ExistsCachedRegistrationInfo());
-
-  // The persisted registration info should be removed.
-  EXPECT_FALSE(consumer()->HasPersistedRegistrationInfo(kTestingAppId));
 }
 
 TEST_F(GCMProfileServiceSingleProfileTest,
@@ -1206,50 +1119,6 @@
             consumer()->gcm_app_handler()->message().sender_id);
 }
 
-// Flaky on all platforms: http://crbug.com/354803
-TEST_F(GCMProfileServiceSingleProfileTest,
-       DISABLED_MessageNotReceivedFromNotRegisteredSender) {
-  // Explicitly not registering the sender2 here, so that message gets dropped.
-  consumer()->Register(kTestingAppId, ToSenderList("sender1"));
-  WaitUntilCompleted();
-  GCMClient::IncomingMessage message;
-  message.data["key1"] = "value1";
-  message.data["key2"] = "value2";
-  message.sender_id = "sender2";
-  consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, message);
-  PumpUILoop();
-  EXPECT_EQ(FakeGCMAppHandler::NO_EVENT,
-            consumer()->gcm_app_handler()->received_event());
-  consumer()->gcm_app_handler()->clear_results();
-
-  // Register for sender2 and try to receive the message again, which should
-  // work with no problems.
-  consumer()->Register(kTestingAppId, ToSenderList("sender1,sender2"));
-  WaitUntilCompleted();
-  consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, message);
-  WaitUntilCompleted();
-  EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
-            consumer()->gcm_app_handler()->received_event());
-  consumer()->gcm_app_handler()->clear_results();
-
-  // Making sure that sender1 can receive the message as well.
-  message.sender_id = "sender1";
-  consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, message);
-  WaitUntilCompleted();
-  EXPECT_EQ(FakeGCMAppHandler::MESSAGE_EVENT,
-            consumer()->gcm_app_handler()->received_event());
-  consumer()->gcm_app_handler()->clear_results();
-
-  // Register for sender1 only and make sure it is not possible  to receive the
-  // message again from from sender1.
-  consumer()->Register(kTestingAppId, ToSenderList("sender2"));
-  WaitUntilCompleted();
-  consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, message);
-  PumpUILoop();
-  EXPECT_EQ(FakeGCMAppHandler::NO_EVENT,
-            consumer()->gcm_app_handler()->received_event());
-}
-
 TEST_F(GCMProfileServiceSingleProfileTest, MessageWithCollapseKeyReceived) {
   consumer()->Register(kTestingAppId, ToSenderList("sender"));
   WaitUntilCompleted();
diff --git a/chrome/browser/sessions/session_backend.cc b/chrome/browser/sessions/session_backend.cc
index e398d36..fa51c88 100644
--- a/chrome/browser/sessions/session_backend.cc
+++ b/chrome/browser/sessions/session_backend.cc
@@ -7,11 +7,10 @@
 #include <limits>
 
 #include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/memory/scoped_vector.h"
 #include "base/metrics/histogram.h"
 #include "base/threading/thread_restrictions.h"
-#include "net/base/file_stream.h"
-#include "net/base/net_errors.h"
 
 using base::TimeTicks;
 
@@ -46,10 +45,8 @@
         buffer_(SessionBackend::kFileReadBufferSize, 0),
         buffer_position_(0),
         available_count_(0) {
-    file_.reset(new net::FileStream(NULL));
-    if (base::PathExists(path))
-      file_->OpenSync(path,
-                      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
+    file_.reset(new base::File(
+        path, base::File::FLAG_OPEN | base::File::FLAG_READ));
   }
   // Reads the contents of the file specified in the constructor, returning
   // true on success. It is up to the caller to free all SessionCommands
@@ -77,7 +74,7 @@
   std::string buffer_;
 
   // The file.
-  scoped_ptr<net::FileStream> file_;
+  scoped_ptr<base::File> file_;
 
   // Position in buffer_ of the data.
   size_t buffer_position_;
@@ -90,13 +87,13 @@
 
 bool SessionFileReader::Read(BaseSessionService::SessionType type,
                              std::vector<SessionCommand*>* commands) {
-  if (!file_->IsOpen())
+  if (!file_->IsValid())
     return false;
   FileHeader header;
   int read_count;
   TimeTicks start_time = TimeTicks::Now();
-  read_count = file_->ReadUntilComplete(reinterpret_cast<char*>(&header),
-                                        sizeof(header));
+  read_count = file_->ReadAtCurrentPos(reinterpret_cast<char*>(&header),
+                                       sizeof(header));
   if (read_count != sizeof(header) || header.signature != kFileSignature ||
       header.version != kFileCurrentVersion)
     return false;
@@ -174,8 +171,8 @@
   buffer_position_ = 0;
   DCHECK(buffer_position_ + available_count_ < buffer_.size());
   int to_read = static_cast<int>(buffer_.size() - available_count_);
-  int read_count = file_->ReadUntilComplete(&(buffer_[available_count_]),
-                                            to_read);
+  int read_count = file_->ReadAtCurrentPos(&(buffer_[available_count_]),
+                                           to_read);
   if (read_count < 0) {
     errored_ = true;
     return false;
@@ -230,11 +227,11 @@
   // Make sure and check current_session_file_, if opening the file failed
   // current_session_file_ will be NULL.
   if ((reset_first && !empty_file_) || !current_session_file_.get() ||
-      !current_session_file_->IsOpen()) {
+      !current_session_file_->IsValid()) {
     ResetFile();
   }
   // Need to check current_session_file_ again, ResetFile may fail.
-  if (current_session_file_.get() && current_session_file_->IsOpen() &&
+  if (current_session_file_.get() && current_session_file_->IsValid() &&
       !AppendCommandsToFile(current_session_file_.get(), *commands)) {
     current_session_file_.reset(NULL);
   }
@@ -304,7 +301,7 @@
   return file_reader.Read(type_, commands);
 }
 
-bool SessionBackend::AppendCommandsToFile(net::FileStream* file,
+bool SessionBackend::AppendCommandsToFile(base::File* file,
     const std::vector<SessionCommand*>& commands) {
   for (std::vector<SessionCommand*>::const_iterator i = commands.begin();
        i != commands.end(); ++i) {
@@ -315,22 +312,22 @@
       UMA_HISTOGRAM_COUNTS("TabRestore.command_size", total_size);
     else
       UMA_HISTOGRAM_COUNTS("SessionRestore.command_size", total_size);
-    wrote = file->WriteSync(reinterpret_cast<const char*>(&total_size),
-                            sizeof(total_size));
+    wrote = file->WriteAtCurrentPos(reinterpret_cast<const char*>(&total_size),
+                                    sizeof(total_size));
     if (wrote != sizeof(total_size)) {
       NOTREACHED() << "error writing";
       return false;
     }
     id_type command_id = (*i)->id();
-    wrote = file->WriteSync(reinterpret_cast<char*>(&command_id),
-                            sizeof(command_id));
+    wrote = file->WriteAtCurrentPos(reinterpret_cast<char*>(&command_id),
+                                    sizeof(command_id));
     if (wrote != sizeof(command_id)) {
       NOTREACHED() << "error writing";
       return false;
     }
     if (content_size > 0) {
-      wrote = file->WriteSync(reinterpret_cast<char*>((*i)->contents()),
-                              content_size);
+      wrote = file->WriteAtCurrentPos(reinterpret_cast<char*>((*i)->contents()),
+                                      content_size);
       if (wrote != content_size) {
         NOTREACHED() << "error writing";
         return false;
@@ -339,7 +336,7 @@
 #if defined(OS_CHROMEOS)
     // TODO(gspencer): Remove this once we find a better place to do it.
     // See issue http://crbug.com/245015
-    file->FlushSync();
+    file->Flush();
 #endif
   }
   return true;
@@ -362,7 +359,9 @@
     // from under us once we close it. If truncation fails, we'll try to
     // recreate.
     const int header_size = static_cast<int>(sizeof(FileHeader));
-    if (current_session_file_->Truncate(header_size) != header_size)
+    if (current_session_file_->Seek(
+            base::File::FROM_BEGIN, header_size) != header_size ||
+        !current_session_file_->SetLength(header_size))
       current_session_file_.reset(NULL);
   }
   if (!current_session_file_.get())
@@ -370,19 +369,19 @@
   empty_file_ = true;
 }
 
-net::FileStream* SessionBackend::OpenAndWriteHeader(
-    const base::FilePath& path) {
+base::File* SessionBackend::OpenAndWriteHeader(const base::FilePath& path) {
   DCHECK(!path.empty());
-  scoped_ptr<net::FileStream> file(new net::FileStream(NULL));
-  if (file->OpenSync(path, base::PLATFORM_FILE_CREATE_ALWAYS |
-      base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_EXCLUSIVE_WRITE |
-      base::PLATFORM_FILE_EXCLUSIVE_READ) != net::OK)
+  scoped_ptr<base::File> file(new base::File(
+      path,
+      base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
+      base::File::FLAG_EXCLUSIVE_WRITE | base::File::FLAG_EXCLUSIVE_READ));
+  if (!file->IsValid())
     return NULL;
   FileHeader header;
   header.signature = kFileSignature;
   header.version = kFileCurrentVersion;
-  int wrote = file->WriteSync(reinterpret_cast<char*>(&header),
-                              sizeof(header));
+  int wrote = file->WriteAtCurrentPos(reinterpret_cast<char*>(&header),
+                                      sizeof(header));
   if (wrote != sizeof(header))
     return NULL;
   return file.release();
diff --git a/chrome/browser/sessions/session_backend.h b/chrome/browser/sessions/session_backend.h
index 70eb182..70c52f9 100644
--- a/chrome/browser/sessions/session_backend.h
+++ b/chrome/browser/sessions/session_backend.h
@@ -13,8 +13,8 @@
 #include "chrome/browser/sessions/base_session_service.h"
 #include "chrome/browser/sessions/session_command.h"
 
-namespace net {
-class FileStream;
+namespace base {
+class File;
 }
 
 // SessionBackend -------------------------------------------------------------
@@ -105,10 +105,10 @@
 
   // Opens the current file and writes the header. On success a handle to
   // the file is returned.
-  net::FileStream* OpenAndWriteHeader(const base::FilePath& path);
+  base::File* OpenAndWriteHeader(const base::FilePath& path);
 
   // Appends the specified commands to the specified file.
-  bool AppendCommandsToFile(net::FileStream* file,
+  bool AppendCommandsToFile(base::File* file,
                             const std::vector<SessionCommand*>& commands);
 
   const BaseSessionService::SessionType type_;
@@ -126,7 +126,7 @@
   bool last_session_valid_;
 
   // Handle to the target file.
-  scoped_ptr<net::FileStream> current_session_file_;
+  scoped_ptr<base::File> current_session_file_;
 
   // Whether we've inited. Remember, the constructor is run on the
   // Main thread, all others on the IO thread, hence lazy initialization.
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index 62b9389..25c306d 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -42,6 +42,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/page_transition_types.h"
 #include "content/public/test/test_navigation_observer.h"
@@ -54,6 +55,10 @@
 #include "base/mac/scoped_nsautorelease_pool.h"
 #endif
 
+#if defined(USE_AURA)
+#include "ui/aura/window.h"
+#endif
+
 class SessionRestoreTest : public InProcessBrowserTest {
  public:
   SessionRestoreTest() : active_browser_list_(NULL) {}
@@ -187,6 +192,35 @@
   const BrowserList* active_browser_list_;
 };
 
+#if defined(USE_AURA)
+// Verifies that restored tabs have a root window. This is important
+// otherwise the wrong information is communicated to the renderer.
+// (http://crbug.com/342672).
+IN_PROC_BROWSER_TEST_F(SessionRestoreTest, RestoredTabsShouldHaveRootWindow) {
+  // Create tabs.
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL(content::kAboutBlankURL), NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), GURL(content::kAboutBlankURL), NEW_BACKGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+  // Restart and session restore the tabs.
+  Browser* restored = QuitBrowserAndRestore(browser(), 3);
+  TabStripModel* tab_strip_model = restored->tab_strip_model();
+  const int tabs = tab_strip_model->count();
+  ASSERT_EQ(3, tabs);
+
+  // Check the restored tabs have a root window.
+  for (int i = 0; i < tabs; ++i) {
+    content::WebContents* contents = tab_strip_model->GetWebContentsAt(i);
+    gfx::NativeView window = contents->GetView()->GetNativeView();
+    bool tab_has_root_window = !!window->GetRootWindow();
+    EXPECT_TRUE(tab_has_root_window);
+  }
+}
+#endif  // USE_AURA
+
 #if defined(OS_CHROMEOS)
 // Verify that session restore does not occur when a user opens a browser window
 // when no other browser windows are open on ChromeOS.
diff --git a/chrome/browser/signin/OWNERS b/chrome/browser/signin/OWNERS
index 7300c05..ba261ed 100644
--- a/chrome/browser/signin/OWNERS
+++ b/chrome/browser/signin/OWNERS
@@ -1,3 +1,5 @@
 atwilson@chromium.org
 tim@chromium.org
-rogerta@chromium.org
\ No newline at end of file
+rogerta@chromium.org
+# Temporary, for refactoring purposes only.
+blundell@chromium.org
diff --git a/chrome/browser/signin/about_signin_internals.cc b/chrome/browser/signin/about_signin_internals.cc
index 838bba1..2943917 100644
--- a/chrome/browser/signin/about_signin_internals.cc
+++ b/chrome/browser/signin/about_signin_internals.cc
@@ -13,10 +13,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_internals_util.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/common/chrome_version_info.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_internals_util.h"
 #include "google_apis/gaia/gaia_constants.h"
 
 using base::Time;
diff --git a/chrome/browser/signin/about_signin_internals.h b/chrome/browser/signin/about_signin_internals.h
index 6207393..07cf96e 100644
--- a/chrome/browser/signin/about_signin_internals.h
+++ b/chrome/browser/signin/about_signin_internals.h
@@ -11,10 +11,10 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "base/values.h"
-#include "chrome/browser/signin/signin_internals_util.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/signin_internals_util.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 
 class Profile;
diff --git a/chrome/browser/signin/about_signin_internals_factory.cc b/chrome/browser/signin/about_signin_internals_factory.cc
index 462484c..453ee83 100644
--- a/chrome/browser/signin/about_signin_internals_factory.cc
+++ b/chrome/browser/signin/about_signin_internals_factory.cc
@@ -5,11 +5,12 @@
 #include "chrome/browser/signin/about_signin_internals_factory.h"
 
 #include "base/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/about_signin_internals.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_internals_util.h"
 #include "chrome/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/signin/core/browser/signin_internals_util.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "google_apis/gaia/gaia_constants.h"
 
diff --git a/chrome/browser/signin/account_reconcilor.cc b/chrome/browser/signin/account_reconcilor.cc
index e36c5a9..72faacf 100644
--- a/chrome/browser/signin/account_reconcilor.cc
+++ b/chrome/browser/signin/account_reconcilor.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/signin_oauth_helper.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
diff --git a/chrome/browser/signin/account_reconcilor_unittest.cc b/chrome/browser/signin/account_reconcilor_unittest.cc
index c524ef4..af64c00 100644
--- a/chrome/browser/signin/account_reconcilor_unittest.cc
+++ b/chrome/browser/signin/account_reconcilor_unittest.cc
@@ -8,13 +8,13 @@
 #include "chrome/browser/signin/account_reconcilor.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/url_request/test_url_fetcher_factory.h"
@@ -104,7 +104,7 @@
 void AccountReconcilorTest::SetUp() {
   TestingProfile::Builder builder;
   builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                            FakeProfileOAuth2TokenServiceWrapper::Build);
+                            BuildFakeProfileOAuth2TokenService);
   builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
                             FakeSigninManagerBase::Build);
   builder.AddTestingFactory(AccountReconcilorFactory::GetInstance(),
diff --git a/chrome/browser/signin/android_profile_oauth2_token_service.h b/chrome/browser/signin/android_profile_oauth2_token_service.h
index 98b0533..7d6a660 100644
--- a/chrome/browser/signin/android_profile_oauth2_token_service.h
+++ b/chrome/browser/signin/android_profile_oauth2_token_service.h
@@ -12,7 +12,7 @@
 #include "base/callback.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 
 // A specialization of ProfileOAuth2TokenService that will be returned by
@@ -68,7 +68,7 @@
   virtual void FireRefreshTokensLoadedFromJava(JNIEnv* env, jobject obj);
 
  protected:
-  friend class ProfileOAuth2TokenServiceWrapperImpl;
+  friend class ProfileOAuth2TokenServiceFactory;
   AndroidProfileOAuth2TokenService();
   virtual ~AndroidProfileOAuth2TokenService();
 
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 637f4bf..15c2fba 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -5,7 +5,11 @@
 #include "chrome/browser/signin/chrome_signin_client.h"
 
 #include "chrome/browser/content_settings/cookie_settings.h"
+#include "chrome/browser/signin/local_auth.h"
 #include "chrome/browser/webdata/web_data_service_factory.h"
+#include "chrome/common/profile_management_switches.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/child_process_host.h"
 #include "url/gurl.h"
 
 #if defined(ENABLE_MANAGED_USERS)
@@ -16,15 +20,25 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #endif
 
+using content::ChildProcessHost;
+using content::RenderProcessHost;
+
 namespace {
 
 const char kGoogleAccountsUrl[] = "https://accounts.google.com";
 
 }  // namespace
 
-ChromeSigninClient::ChromeSigninClient(Profile* profile) : profile_(profile) {}
+ChromeSigninClient::ChromeSigninClient(Profile* profile)
+    : profile_(profile), signin_host_id_(ChildProcessHost::kInvalidUniqueID) {}
 
-ChromeSigninClient::~ChromeSigninClient() {}
+ChromeSigninClient::~ChromeSigninClient() {
+  std::set<RenderProcessHost*>::iterator i;
+  for (i = signin_hosts_observed_.begin(); i != signin_hosts_observed_.end();
+       ++i) {
+    (*i)->RemoveObserver(this);
+  }
+}
 
 // static
 bool ChromeSigninClient::ProfileAllowsSigninCookies(Profile* profile) {
@@ -41,6 +55,42 @@
                                                  GURL(kGoogleAccountsUrl));
 }
 
+void ChromeSigninClient::SetSigninProcess(int process_id) {
+  if (process_id == signin_host_id_)
+    return;
+  DLOG_IF(WARNING, signin_host_id_ != ChildProcessHost::kInvalidUniqueID)
+      << "Replacing in-use signin process.";
+  signin_host_id_ = process_id;
+  RenderProcessHost* host = RenderProcessHost::FromID(process_id);
+  DCHECK(host);
+  host->AddObserver(this);
+  signin_hosts_observed_.insert(host);
+}
+
+void ChromeSigninClient::ClearSigninProcess() {
+  signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
+}
+
+bool ChromeSigninClient::IsSigninProcess(int process_id) const {
+  return process_id == signin_host_id_;
+}
+
+bool ChromeSigninClient::HasSigninProcess() const {
+  return signin_host_id_ != ChildProcessHost::kInvalidUniqueID;
+}
+
+void ChromeSigninClient::RenderProcessHostDestroyed(RenderProcessHost* host) {
+  // It's possible we're listening to a "stale" renderer because it was replaced
+  // with a new process by process-per-site. In either case, stop observing it,
+  // but only reset signin_host_id_ tracking if this was from the current signin
+  // process.
+  signin_hosts_observed_.erase(host);
+  if (signin_host_id_ == host->GetID())
+    signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
+}
+
+PrefService* ChromeSigninClient::GetPrefs() { return profile_->GetPrefs(); }
+
 scoped_refptr<TokenWebData> ChromeSigninClient::GetDatabase() {
   return WebDataServiceFactory::GetTokenWebDataForProfile(
       profile_, Profile::EXPLICIT_ACCESS);
@@ -72,3 +122,12 @@
 net::URLRequestContextGetter* ChromeSigninClient::GetURLRequestContext() {
   return profile_->GetRequestContext();
 }
+
+void ChromeSigninClient::GoogleSigninSucceeded(const std::string& username,
+                                               const std::string& password) {
+#if !defined(OS_ANDROID)
+  // Don't store password hash except for users of new profile features.
+  if (switches::IsNewProfileManagement())
+    chrome::SetLocalAuthCredentials(profile_, password);
+#endif
+}
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h
index 4bd7369..b51bcc0 100644
--- a/chrome/browser/signin/chrome_signin_client.h
+++ b/chrome/browser/signin/chrome_signin_client.h
@@ -8,12 +8,15 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/signin_client.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "content/public/browser/render_process_host_observer.h"
 
 class CookieSettings;
 class Profile;
 
-class ChromeSigninClient : public SigninClient, public KeyedService {
+class ChromeSigninClient : public SigninClient,
+                           public KeyedService,
+                           public content::RenderProcessHostObserver {
  public:
   explicit ChromeSigninClient(Profile* profile);
   virtual ~ChromeSigninClient();
@@ -22,14 +25,41 @@
   static bool ProfileAllowsSigninCookies(Profile* profile);
   static bool SettingsAllowSigninCookies(CookieSettings* cookie_settings);
 
+  // Tracks the privileged signin process identified by |host_id| so that we
+  // can later ask (via IsSigninProcess) if it is safe to sign the user in from
+  // the current context (see OneClickSigninHelper).  All of this tracking
+  // state is reset once the renderer process terminates.
+  //
+  // N.B. This is the id returned by RenderProcessHost::GetID().
+  // TODO(guohui): Eliminate these APIs once the web-based signin flow is
+  // replaced by a native flow. crbug.com/347247
+  void SetSigninProcess(int host_id);
+  void ClearSigninProcess();
+  bool IsSigninProcess(int host_id) const;
+  bool HasSigninProcess() const;
+
+  // content::RenderProcessHostObserver implementation.
+  virtual void RenderProcessHostDestroyed(content::RenderProcessHost* host)
+      OVERRIDE;
+
   // SigninClient implementation.
+  virtual PrefService* GetPrefs() OVERRIDE;
   virtual scoped_refptr<TokenWebData> GetDatabase() OVERRIDE;
   virtual bool CanRevokeCredentials() OVERRIDE;
   virtual net::URLRequestContextGetter* GetURLRequestContext() OVERRIDE;
+  virtual void GoogleSigninSucceeded(const std::string& username,
+                                     const std::string& password) OVERRIDE;
 
  private:
   Profile* profile_;
 
+  // See SetSigninProcess. Tracks the currently active signin process
+  // by ID, if there is one.
+  int signin_host_id_;
+
+  // The RenderProcessHosts being observed.
+  std::set<content::RenderProcessHost*> signin_hosts_observed_;
+
   DISALLOW_COPY_AND_ASSIGN(ChromeSigninClient);
 };
 
diff --git a/chrome/browser/signin/fake_auth_status_provider.cc b/chrome/browser/signin/fake_auth_status_provider.cc
deleted file mode 100644
index aacf600..0000000
--- a/chrome/browser/signin/fake_auth_status_provider.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/fake_auth_status_provider.h"
-
-FakeAuthStatusProvider::FakeAuthStatusProvider(SigninErrorController* error)
-  : error_provider_(error),
-    auth_error_(GoogleServiceAuthError::AuthErrorNone()) {
-  error_provider_->AddProvider(this);
-}
-
-FakeAuthStatusProvider::~FakeAuthStatusProvider() {
-  error_provider_->RemoveProvider(this);
-}
-
-std::string FakeAuthStatusProvider::GetAccountId() const {
-  return account_id_;
-}
-
-GoogleServiceAuthError FakeAuthStatusProvider::GetAuthStatus() const {
-  return auth_error_;
-}
-
-void FakeAuthStatusProvider::SetAuthError(const std::string& account_id,
-                                          const GoogleServiceAuthError& error) {
-  account_id_ = account_id;
-  auth_error_ = error;
-  error_provider_->AuthStatusChanged();
-}
diff --git a/chrome/browser/signin/fake_auth_status_provider.h b/chrome/browser/signin/fake_auth_status_provider.h
deleted file mode 100644
index 3552788..0000000
--- a/chrome/browser/signin/fake_auth_status_provider.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SIGNIN_FAKE_AUTH_STATUS_PROVIDER_H_
-#define CHROME_BROWSER_SIGNIN_FAKE_AUTH_STATUS_PROVIDER_H_
-
-#include "components/signin/core/signin_error_controller.h"
-
-// Helper class that reports auth errors to SigninErrorController. Automatically
-// registers and de-registers itself as an AuthStatusProvider in the
-// constructor and destructor.
-class FakeAuthStatusProvider
-    : public SigninErrorController::AuthStatusProvider {
- public:
-  explicit FakeAuthStatusProvider(SigninErrorController* error);
-  virtual ~FakeAuthStatusProvider();
-
-  // Sets the auth error that this provider reports to SigninErrorController.
-  // Also notifies SigninErrorController via AuthStatusChanged().
-  void SetAuthError(const std::string& account_id,
-                    const GoogleServiceAuthError& error);
-
-  void set_error_without_status_change(const GoogleServiceAuthError& error) {
-    auth_error_ = error;
-  }
-
-  // AuthStatusProvider implementation.
-  virtual std::string GetAccountId() const OVERRIDE;
-  virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
-
- private:
-  SigninErrorController* error_provider_;
-  std::string account_id_;
-  GoogleServiceAuthError auth_error_;
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_FAKE_AUTH_STATUS_PROVIDER_H_
diff --git a/chrome/browser/signin/fake_profile_oauth2_token_service.h b/chrome/browser/signin/fake_profile_oauth2_token_service.h
index 93933e5..205ef69 100644
--- a/chrome/browser/signin/fake_profile_oauth2_token_service.h
+++ b/chrome/browser/signin/fake_profile_oauth2_token_service.h
@@ -14,7 +14,7 @@
 #if defined(OS_ANDROID)
 #include "chrome/browser/signin/android_profile_oauth2_token_service.h"
 #else
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #endif
 
 // Helper class to simplify writing unittests that depend on an instance of
diff --git a/chrome/browser/signin/fake_profile_oauth2_token_service_builder.cc b/chrome/browser/signin/fake_profile_oauth2_token_service_builder.cc
new file mode 100644
index 0000000..8d54b31
--- /dev/null
+++ b/chrome/browser/signin/fake_profile_oauth2_token_service_builder.cc
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
+
+// TODO(blundell): Should these be namespaced?
+KeyedService* BuildFakeProfileOAuth2TokenService(
+    content::BrowserContext* context) {
+  Profile* profile = Profile::FromBrowserContext(context);
+  FakeProfileOAuth2TokenService* service = new FakeProfileOAuth2TokenService();
+  service->Initialize(
+      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile));
+  return service;
+}
+
+KeyedService* BuildAutoIssuingFakeProfileOAuth2TokenService(
+    content::BrowserContext* context) {
+  Profile* profile = Profile::FromBrowserContext(context);
+  FakeProfileOAuth2TokenService* service = new FakeProfileOAuth2TokenService();
+  service->set_auto_post_fetch_response_on_message_loop(true);
+  service->Initialize(
+      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile));
+  return service;
+}
diff --git a/chrome/browser/signin/fake_profile_oauth2_token_service_builder.h b/chrome/browser/signin/fake_profile_oauth2_token_service_builder.h
new file mode 100644
index 0000000..21672b6
--- /dev/null
+++ b/chrome/browser/signin/fake_profile_oauth2_token_service_builder.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_BUILDER_H_
+#define CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_BUILDER_H_
+
+class KeyedService;
+
+namespace content {
+class BrowserContext;
+}
+
+// Helper function to be used with
+// BrowserContextKeyedServiceFactory::SetTestingFactory() that returns a
+// FakeProfileOAuth2TokenService object.
+KeyedService* BuildFakeProfileOAuth2TokenService(
+    content::BrowserContext* context);
+
+// Helper function to be used with
+// BrowserContextKeyedServiceFactory::SetTestingFactory() that creates a
+// FakeProfileOAuth2TokenService object that posts fetch responses on the
+// current message loop.
+KeyedService* BuildAutoIssuingFakeProfileOAuth2TokenService(
+    content::BrowserContext* context);
+
+#endif  // CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_BUILDER_H_
diff --git a/chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.cc b/chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.cc
deleted file mode 100644
index 500d207..0000000
--- a/chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/chrome_signin_client_factory.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
-
-// static
-KeyedService* FakeProfileOAuth2TokenServiceWrapper::Build(
-    content::BrowserContext* context) {
-  Profile* profile = static_cast<Profile*>(context);
-  return new FakeProfileOAuth2TokenServiceWrapper(profile, false);
-}
-
-// static
-KeyedService*
-FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService(
-    content::BrowserContext* context) {
-  Profile* profile = static_cast<Profile*>(context);
-  return new FakeProfileOAuth2TokenServiceWrapper(profile, true);
-}
-
-FakeProfileOAuth2TokenServiceWrapper::FakeProfileOAuth2TokenServiceWrapper(
-    Profile* profile,
-    bool auto_issue_tokens) {
-  if (auto_issue_tokens)
-    service_.set_auto_post_fetch_response_on_message_loop(true);
-  service_.Initialize(
-      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile));
-}
-
-FakeProfileOAuth2TokenServiceWrapper::~FakeProfileOAuth2TokenServiceWrapper() {
-  service_.Shutdown();
-}
-
-ProfileOAuth2TokenService*
-FakeProfileOAuth2TokenServiceWrapper::GetProfileOAuth2TokenService() {
-  return &service_;
-}
diff --git a/chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h b/chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h
deleted file mode 100644
index 17fc7bf..0000000
--- a/chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_WRAPPER_H_
-#define CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_WRAPPER_H_
-
-#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-
-class Profile;
-
-// A wrapper around FakeProfileOAuth2TokenService to be able to use it as a
-// BCKS.
-class FakeProfileOAuth2TokenServiceWrapper
-    : public ProfileOAuth2TokenServiceWrapper {
- public:
-  // Helper function to be used with
-  // KeyedService::SetTestingFactory().
-  static KeyedService* Build(content::BrowserContext* context);
-
-  // Helper function to be used with
-  // KeyedService::SetTestingFactory() that creates a
-  // FakeProfileOAuth2TokenService object that posts fetch responses on the
-  // current message loop.
-  static KeyedService* BuildAutoIssuingTokenService(
-      content::BrowserContext* context);
-
-  FakeProfileOAuth2TokenServiceWrapper(Profile* profile,
-                                       bool auto_issue_tokens);
-  virtual ~FakeProfileOAuth2TokenServiceWrapper();
-
-  // ProfileOAuth2TokenServiceWrapper implementation:
-  virtual ProfileOAuth2TokenService* GetProfileOAuth2TokenService() OVERRIDE;
-
- private:
-  FakeProfileOAuth2TokenService service_;
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_FAKE_PROFILE_OAUTH2_TOKEN_SERVICE_WRAPPER_H_
diff --git a/chrome/browser/signin/fake_signin_manager.cc b/chrome/browser/signin/fake_signin_manager.cc
index f1affdf..c032105 100644
--- a/chrome/browser/signin/fake_signin_manager.cc
+++ b/chrome/browser/signin/fake_signin_manager.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_global_error.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/global_error/global_error_service.h"
@@ -16,8 +17,9 @@
 #include "chrome/common/pref_names.h"
 #include "content/public/browser/notification_service.h"
 
-FakeSigninManagerBase::FakeSigninManagerBase() {
-}
+FakeSigninManagerBase::FakeSigninManagerBase(Profile* profile)
+    : SigninManagerBase(
+          ChromeSigninClientFactory::GetInstance()->GetForProfile(profile)) {}
 
 FakeSigninManagerBase::~FakeSigninManagerBase() {
 }
@@ -27,7 +29,7 @@
   SigninManagerBase* manager;
   Profile* profile = static_cast<Profile*>(context);
 #if defined(OS_CHROMEOS)
-  manager = new FakeSigninManagerBase();
+  manager = new FakeSigninManagerBase(profile);
 #else
   manager = new FakeSigninManager(profile);
 #endif
@@ -41,7 +43,8 @@
 
 FakeSigninManager::FakeSigninManager(Profile* profile)
     : SigninManager(
-          ChromeSigninClientFactory::GetInstance()->GetForProfile(profile)) {}
+          ChromeSigninClientFactory::GetInstance()->GetForProfile(profile),
+          ProfileOAuth2TokenServiceFactory::GetForProfile(profile)) {}
 
 FakeSigninManager::~FakeSigninManager() {
 }
diff --git a/chrome/browser/signin/fake_signin_manager.h b/chrome/browser/signin/fake_signin_manager.h
index 0c8c8f1..f98b92e 100644
--- a/chrome/browser/signin/fake_signin_manager.h
+++ b/chrome/browser/signin/fake_signin_manager.h
@@ -10,6 +10,10 @@
 #include "base/compiler_specific.h"
 #include "chrome/browser/signin/signin_manager.h"
 
+namespace content {
+class BrowserContext;
+}
+
 class Profile;
 
 // SigninManager to use for testing. Tests should use the type
@@ -19,7 +23,7 @@
 // Overrides InitTokenService to do-nothing in tests.
 class FakeSigninManagerBase : public SigninManagerBase {
  public:
-  explicit FakeSigninManagerBase();
+  explicit FakeSigninManagerBase(Profile* profile);
   virtual ~FakeSigninManagerBase();
 
   // Helper function to be used with
diff --git a/chrome/browser/signin/mutable_profile_oauth2_token_service_unittest.cc b/chrome/browser/signin/mutable_profile_oauth2_token_service_unittest.cc
index e277f4c..4f7c3ee 100644
--- a/chrome/browser/signin/mutable_profile_oauth2_token_service_unittest.cc
+++ b/chrome/browser/signin/mutable_profile_oauth2_token_service_unittest.cc
@@ -6,10 +6,10 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/webdata/web_data_service_factory.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/mutable_profile_oauth2_token_service.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_error_controller.h"
-#include "components/signin/core/webdata/token_web_data.h"
+#include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
+#include "components/signin/core/browser/webdata/token_web_data.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
diff --git a/chrome/browser/signin/profile_oauth2_token_service_factory.cc b/chrome/browser/signin/profile_oauth2_token_service_factory.cc
index a7cb8bf..14c76ac 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_factory.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_factory.cc
@@ -9,50 +9,14 @@
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "chrome/browser/webdata/web_data_service_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 #if defined(OS_ANDROID)
 #include "chrome/browser/signin/android_profile_oauth2_token_service.h"
 #else
-#include "components/signin/core/mutable_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
 #endif
 
-class ProfileOAuth2TokenServiceWrapperImpl
-    : public ProfileOAuth2TokenServiceWrapper {
- public:
-  explicit ProfileOAuth2TokenServiceWrapperImpl(Profile* profile);
-  virtual ~ProfileOAuth2TokenServiceWrapperImpl();
-
-  // ProfileOAuth2TokenServiceWrapper:
-  virtual ProfileOAuth2TokenService* GetProfileOAuth2TokenService() OVERRIDE;
-
-  // KeyedService:
-  virtual void Shutdown() OVERRIDE;
-
- private:
-  scoped_ptr<ProfileOAuth2TokenService> profile_oauth2_token_service_;
-};
-
-ProfileOAuth2TokenServiceWrapperImpl::ProfileOAuth2TokenServiceWrapperImpl(
-    Profile* profile) {
-  profile_oauth2_token_service_.reset(new ProfileOAuth2TokenServiceFactory::
-                                          PlatformSpecificOAuth2TokenService());
-  ChromeSigninClient* client =
-      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile);
-  profile_oauth2_token_service_->Initialize(client);
-}
-
-ProfileOAuth2TokenServiceWrapperImpl::~ProfileOAuth2TokenServiceWrapperImpl() {}
-
-void ProfileOAuth2TokenServiceWrapperImpl::Shutdown() {
-  profile_oauth2_token_service_->Shutdown();
-}
-
-ProfileOAuth2TokenService*
-ProfileOAuth2TokenServiceWrapperImpl::GetProfileOAuth2TokenService() {
-  return profile_oauth2_token_service_.get();
-}
-
 ProfileOAuth2TokenServiceFactory::ProfileOAuth2TokenServiceFactory()
     : BrowserContextKeyedServiceFactory(
         "ProfileOAuth2TokenService",
@@ -65,24 +29,18 @@
 ProfileOAuth2TokenServiceFactory::~ProfileOAuth2TokenServiceFactory() {
 }
 
-// static
 ProfileOAuth2TokenService*
 ProfileOAuth2TokenServiceFactory::GetForProfile(Profile* profile) {
-  ProfileOAuth2TokenServiceWrapper* wrapper =
-      static_cast<ProfileOAuth2TokenServiceWrapper*>(
-          GetInstance()->GetServiceForBrowserContext(profile, true));
-  if (!wrapper)
-    return NULL;
-  return wrapper->GetProfileOAuth2TokenService();
+  return static_cast<ProfileOAuth2TokenService*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
 }
 
 // static
 ProfileOAuth2TokenServiceFactory::PlatformSpecificOAuth2TokenService*
 ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(
     Profile* profile) {
-  ProfileOAuth2TokenService* service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
-  return static_cast<PlatformSpecificOAuth2TokenService*>(service);
+  return static_cast<PlatformSpecificOAuth2TokenService*>(
+      GetForProfile(profile));
 }
 
 // static
@@ -94,5 +52,9 @@
 KeyedService* ProfileOAuth2TokenServiceFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
   Profile* profile = static_cast<Profile*>(context);
-  return new ProfileOAuth2TokenServiceWrapperImpl(profile);
+  PlatformSpecificOAuth2TokenService* service =
+      new PlatformSpecificOAuth2TokenService();
+  service->Initialize(
+      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile));
+  return service;
 }
diff --git a/chrome/browser/signin/profile_oauth2_token_service_factory.h b/chrome/browser/signin/profile_oauth2_token_service_factory.h
index c58626c..b0a1c28 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_factory.h
+++ b/chrome/browser/signin/profile_oauth2_token_service_factory.h
@@ -17,13 +17,7 @@
 class MutableProfileOAuth2TokenService;
 #endif
 
-// A wrapper of ProfileOAuth2TokenService so we can use it as a BCKS.
-class ProfileOAuth2TokenServiceWrapper : public KeyedService {
- public:
-  virtual ProfileOAuth2TokenService* GetProfileOAuth2TokenService() = 0;
-};
-
-/// Singleton that owns all ProfileOAuth2TokenServices and associates them with
+// Singleton that owns all ProfileOAuth2TokenServices and associates them with
 // Profiles. Listens for the Profile's destruction notification and cleans up
 // the associated ProfileOAuth2TokenService.
 class ProfileOAuth2TokenServiceFactory
@@ -52,7 +46,6 @@
 
  private:
   friend struct DefaultSingletonTraits<ProfileOAuth2TokenServiceFactory>;
-  friend class ProfileOAuth2TokenServiceWrapperImpl;
 
 #if defined(OS_ANDROID)
   typedef AndroidProfileOAuth2TokenService PlatformSpecificOAuth2TokenService;
diff --git a/chrome/browser/signin/profile_oauth2_token_service_request.cc b/chrome/browser/signin/profile_oauth2_token_service_request.cc
index 3e9ae24..c40beb1 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_request.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_request.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_access_token_consumer.h"
diff --git a/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc b/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc
index e2e2c44..0ada8e8 100644
--- a/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc
+++ b/chrome/browser/signin/profile_oauth2_token_service_request_unittest.cc
@@ -8,7 +8,7 @@
 #include <vector>
 #include "base/threading/thread.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread.h"
@@ -84,7 +84,7 @@
                                                   &ui_loop_));
   TestingProfile::Builder builder;
   builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                            &FakeProfileOAuth2TokenServiceWrapper::Build);
+                            &BuildFakeProfileOAuth2TokenService);
   profile_ = builder.Build();
 
   oauth2_service_ = (FakeProfileOAuth2TokenService*)
diff --git a/chrome/browser/signin/signin_account_id_helper.cc b/chrome/browser/signin/signin_account_id_helper.cc
index 44b03fe..610f88f 100644
--- a/chrome/browser/signin/signin_account_id_helper.cc
+++ b/chrome/browser/signin/signin_account_id_helper.cc
@@ -5,10 +5,9 @@
 #include "chrome/browser/signin/signin_account_id_helper.h"
 
 #include "base/prefs/pref_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/core/common/signin_pref_names.h"
 #include "google_apis/gaia/gaia_oauth_client.h"
 
 // TODO(guohui): this class should be moved to a more generic place for reuse.
@@ -16,7 +15,9 @@
     : public OAuth2TokenService::Consumer,
       public gaia::GaiaOAuthClient::Delegate {
  public:
-  GaiaIdFetcher(SigninManagerBase* signin_manager,
+  GaiaIdFetcher(SigninClient* client,
+                ProfileOAuth2TokenService* token_service,
+                SigninManagerBase* signin_manager,
                 SigninAccountIdHelper* signin_account_id_helper);
   virtual ~GaiaIdFetcher();
 
@@ -35,6 +36,8 @@
  private:
   void Start();
 
+  SigninClient* client_;
+  ProfileOAuth2TokenService* token_service_;
   SigninManagerBase* signin_manager_;
   SigninAccountIdHelper* signin_account_id_helper_;
 
@@ -45,9 +48,13 @@
 };
 
 SigninAccountIdHelper::GaiaIdFetcher::GaiaIdFetcher(
+    SigninClient* client,
+    ProfileOAuth2TokenService* token_service,
     SigninManagerBase* signin_manager,
     SigninAccountIdHelper* signin_account_id_helper)
     : OAuth2TokenService::Consumer("gaia_id_fetcher"),
+      client_(client),
+      token_service_(token_service),
       signin_manager_(signin_manager),
       signin_account_id_helper_(signin_account_id_helper) {
   Start();
@@ -56,12 +63,9 @@
 SigninAccountIdHelper::GaiaIdFetcher::~GaiaIdFetcher() {}
 
 void SigninAccountIdHelper::GaiaIdFetcher::Start() {
-  ProfileOAuth2TokenService* service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(
-          signin_manager_->profile());
   OAuth2TokenService::ScopeSet scopes;
   scopes.insert("https://www.googleapis.com/auth/userinfo.profile");
-  login_token_request_ = service->StartRequest(
+  login_token_request_ = token_service_->StartRequest(
       signin_manager_->GetAuthenticatedAccountId(), scopes, this);
 }
 
@@ -72,8 +76,7 @@
   DCHECK_EQ(request, login_token_request_.get());
 
   gaia_oauth_client_.reset(
-      new gaia::GaiaOAuthClient(
-          signin_manager_->profile()->GetRequestContext()));
+      new gaia::GaiaOAuthClient(client_->GetURLRequestContext()));
 
   const int kMaxGetUserIdRetries = 3;
   gaia_oauth_client_->GetUserId(access_token, kMaxGetUserIdRetries, this);
@@ -101,41 +104,44 @@
   VLOG(1) << "OnNetworkError " << response_code;
 }
 
-SigninAccountIdHelper::SigninAccountIdHelper(SigninManagerBase* signin_manager)
-    : signin_manager_(signin_manager) {
+SigninAccountIdHelper::SigninAccountIdHelper(
+    SigninClient* client,
+    ProfileOAuth2TokenService* token_service,
+    SigninManagerBase* signin_manager)
+    : client_(client),
+      token_service_(token_service),
+      signin_manager_(signin_manager) {
+  DCHECK(client_);
+  DCHECK(token_service_);
   DCHECK(signin_manager_);
   signin_manager_->AddObserver(this);
-  ProfileOAuth2TokenService* token_service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(
-          signin_manager_->profile());
   std::string primary_email = signin_manager_->GetAuthenticatedAccountId();
   if (!primary_email.empty() &&
-      token_service->RefreshTokenIsAvailable(primary_email) &&
+      token_service_->RefreshTokenIsAvailable(primary_email) &&
       !disable_for_test_) {
-    id_fetcher_.reset(new GaiaIdFetcher(signin_manager_, this));
+    id_fetcher_.reset(
+        new GaiaIdFetcher(client_, token_service_, signin_manager_, this));
   }
-  token_service->AddObserver(this);
+  token_service_->AddObserver(this);
 }
 
 SigninAccountIdHelper::~SigninAccountIdHelper() {
   signin_manager_->RemoveObserver(this);
-  ProfileOAuth2TokenServiceFactory::GetForProfile(signin_manager_->profile())->
-      RemoveObserver(this);
+  token_service_->RemoveObserver(this);
 }
 
 void SigninAccountIdHelper::GoogleSignedOut(const std::string& username) {
-  signin_manager_->profile()->GetPrefs()->ClearPref(
-      prefs::kGoogleServicesUserAccountId);
+  client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUserAccountId);
 }
 
 void SigninAccountIdHelper::OnRefreshTokenAvailable(
     const std::string& account_id) {
   if (account_id == signin_manager_->GetAuthenticatedAccountId()) {
     std::string current_gaia_id =
-      signin_manager_->profile()->GetPrefs()->
-          GetString(prefs::kGoogleServicesUserAccountId);
+        client_->GetPrefs()->GetString(prefs::kGoogleServicesUserAccountId);
     if (current_gaia_id.empty() && !disable_for_test_) {
-      id_fetcher_.reset(new GaiaIdFetcher(signin_manager_, this));
+      id_fetcher_.reset(
+          new GaiaIdFetcher(client_, token_service_, signin_manager_, this));
     }
   }
 }
@@ -143,8 +149,8 @@
 void SigninAccountIdHelper::OnPrimaryAccountIdFetched(
     const std::string& gaia_id) {
   if (!gaia_id.empty()) {
-    signin_manager_->profile()->GetPrefs()->SetString(
-        prefs::kGoogleServicesUserAccountId, gaia_id);
+    client_->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId,
+                                   gaia_id);
   }
 }
 
diff --git a/chrome/browser/signin/signin_account_id_helper.h b/chrome/browser/signin/signin_account_id_helper.h
index c3472e8..ad4b6dc 100644
--- a/chrome/browser/signin/signin_account_id_helper.h
+++ b/chrome/browser/signin/signin_account_id_helper.h
@@ -11,6 +11,8 @@
 
 class CookieSettings;
 class GaiaAuthFetcher;
+class ProfileOAuth2TokenService;
+class SigninClient;
 
 // The helper class for managing the obfuscated GAIA ID of the primary
 // account. It fetches the ID when user first signs into Chrome or when user
@@ -19,7 +21,9 @@
 class SigninAccountIdHelper : public SigninManagerBase::Observer,
                               public OAuth2TokenService::Observer {
  public:
-  explicit SigninAccountIdHelper(SigninManagerBase* signin_manager);
+  SigninAccountIdHelper(SigninClient* client,
+                        ProfileOAuth2TokenService* token_service,
+                        SigninManagerBase* signin_manager);
   virtual ~SigninAccountIdHelper();
 
   // SigninManagerBase::Observer:
@@ -42,6 +46,8 @@
 
   static bool disable_for_test_;
 
+  SigninClient* client_;
+  ProfileOAuth2TokenService* token_service_;
   SigninManagerBase* signin_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(SigninAccountIdHelper);
diff --git a/chrome/browser/signin/signin_browsertest.cc b/chrome/browser/signin/signin_browsertest.cc
index 1b98bc0..2f2d22d 100644
--- a/chrome/browser/signin/signin_browsertest.cc
+++ b/chrome/browser/signin/signin_browsertest.cc
@@ -6,8 +6,8 @@
 #define CHROME_BROWSER_SIGNIN_SIGNIN_BROWSERTEST_H_
 
 #include "base/command_line.h"
-#include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/signin/chrome_signin_client.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/singleton_tabs.h"
@@ -107,8 +107,8 @@
 #define MAYBE_ProcessIsolation ProcessIsolation
 #endif
 IN_PROC_BROWSER_TEST_F(SigninBrowserTest, MAYBE_ProcessIsolation) {
-  SigninManager* signin = SigninManagerFactory::GetForProfile(
-      browser()->profile());
+  ChromeSigninClient* signin =
+      ChromeSigninClientFactory::GetForProfile(browser()->profile());
   EXPECT_FALSE(signin->HasSigninProcess());
 
   ui_test_utils::NavigateToURL(browser(), signin::GetPromoURL(
@@ -149,8 +149,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(SigninBrowserTest, NotTrustedAfterRedirect) {
-  SigninManager* signin = SigninManagerFactory::GetForProfile(
-      browser()->profile());
+  ChromeSigninClient* signin =
+      ChromeSigninClientFactory::GetForProfile(browser()->profile());
   EXPECT_FALSE(signin->HasSigninProcess());
 
   GURL url = signin::GetPromoURL(signin::SOURCE_NTP_LINK, true);
@@ -206,8 +206,8 @@
   GURL start_url = signin::GetPromoURL(signin::SOURCE_START_PAGE, true);
   GURL skip_url = signin::GetLandingURL("ntp", 1);
 
-  SigninManager* signin = SigninManagerFactory::GetForProfile(
-      browser()->profile());
+  ChromeSigninClient* signin =
+      ChromeSigninClientFactory::GetForProfile(browser()->profile());
   EXPECT_FALSE(signin->HasSigninProcess());
 
   ui_test_utils::NavigateToURL(browser(), start_url);
diff --git a/chrome/browser/signin/signin_error_controller_unittest.cc b/chrome/browser/signin/signin_error_controller_unittest.cc
deleted file mode 100644
index f2146d2..0000000
--- a/chrome/browser/signin/signin_error_controller_unittest.cc
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/signin_error_controller.h"
-
-#include <functional>
-
-#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/signin/fake_auth_status_provider.h"
-#include "chrome/test/base/testing_profile.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-static const char kTestAccountId[] = "testuser@test.com";
-static const char kOtherTestAccountId[] = "otheruser@test.com";
-
-class SigninErrorControllerTest : public testing::Test {
- public:
-  virtual void SetUp() OVERRIDE {
-    error_controller_.reset(new SigninErrorController());
-  }
-
-  scoped_ptr<SigninErrorController> error_controller_;
-};
-
-TEST_F(SigninErrorControllerTest, NoErrorAuthStatusProviders) {
-  scoped_ptr<FakeAuthStatusProvider> provider;
-
-  // No providers.
-  ASSERT_FALSE(error_controller_->HasError());
-
-  // Add a provider.
-  provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
-  ASSERT_FALSE(error_controller_->HasError());
-
-  // Remove the provider.
-  provider.reset();
-  ASSERT_FALSE(error_controller_->HasError());
-}
-
-TEST_F(SigninErrorControllerTest, ErrorAuthStatusProvider) {
-  scoped_ptr<FakeAuthStatusProvider> provider;
-  scoped_ptr<FakeAuthStatusProvider> error_provider;
-
-  provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
-  ASSERT_FALSE(error_controller_->HasError());
-
-  error_provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
-  error_provider->SetAuthError(kTestAccountId, GoogleServiceAuthError(
-      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-  ASSERT_TRUE(error_controller_->HasError());
-
-  error_provider.reset();
-  ASSERT_FALSE(error_controller_->HasError());
-
-  provider.reset();
-  // All providers should be removed now.
-  ASSERT_FALSE(error_controller_->HasError());
-}
-
-TEST_F(SigninErrorControllerTest, AuthStatusProviderErrorTransition) {
-  scoped_ptr<FakeAuthStatusProvider> provider0(
-      new FakeAuthStatusProvider(error_controller_.get()));
-  scoped_ptr<FakeAuthStatusProvider> provider1(
-      new FakeAuthStatusProvider(error_controller_.get()));
-
-  ASSERT_FALSE(error_controller_->HasError());
-  provider0->SetAuthError(
-      kTestAccountId,
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-  ASSERT_TRUE(error_controller_->HasError());
-  provider1->SetAuthError(
-      kTestAccountId,
-      GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
-  ASSERT_TRUE(error_controller_->HasError());
-
-  // Now resolve the auth errors - the menu item should go away.
-  provider0->SetAuthError(kTestAccountId,
-                         GoogleServiceAuthError::AuthErrorNone());
-  ASSERT_TRUE(error_controller_->HasError());
-  provider1->SetAuthError(kTestAccountId,
-                         GoogleServiceAuthError::AuthErrorNone());
-  ASSERT_FALSE(error_controller_->HasError());
-
-  provider0.reset();
-  provider1.reset();
-  ASSERT_FALSE(error_controller_->HasError());
-}
-
-TEST_F(SigninErrorControllerTest, AuthStatusProviderAccountTransition) {
-  scoped_ptr<FakeAuthStatusProvider> provider0(
-      new FakeAuthStatusProvider(error_controller_.get()));
-  scoped_ptr<FakeAuthStatusProvider> provider1(
-      new FakeAuthStatusProvider(error_controller_.get()));
-
-  ASSERT_FALSE(error_controller_->HasError());
-
-  provider0->SetAuthError(
-      kTestAccountId,
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-  provider1->SetAuthError(
-      kOtherTestAccountId,
-      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
-  ASSERT_TRUE(error_controller_->HasError());
-  ASSERT_STREQ(kTestAccountId,
-               error_controller_->error_account_id().c_str());
-
-  // Swap providers reporting errors.
-  provider1->set_error_without_status_change(
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-  provider0->set_error_without_status_change(
-      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
-  error_controller_->AuthStatusChanged();
-  ASSERT_TRUE(error_controller_->HasError());
-  ASSERT_STREQ(kOtherTestAccountId,
-               error_controller_->error_account_id().c_str());
-
-  // Now resolve the auth errors - the menu item should go away.
-  provider0->set_error_without_status_change(
-      GoogleServiceAuthError::AuthErrorNone());
-  provider1->set_error_without_status_change(
-      GoogleServiceAuthError::AuthErrorNone());
-  error_controller_->AuthStatusChanged();
-  ASSERT_FALSE(error_controller_->HasError());
-
-  provider0.reset();
-  provider1.reset();
-  ASSERT_FALSE(error_controller_->HasError());
-}
-
-// Verify that SigninErrorController handles errors properly.
-TEST_F(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
-  typedef struct {
-    GoogleServiceAuthError::State error_state;
-    bool is_error;
-  } ErrorTableEntry;
-
-  ErrorTableEntry table[] = {
-    { GoogleServiceAuthError::NONE, false },
-    { GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, true },
-    { GoogleServiceAuthError::USER_NOT_SIGNED_UP, true },
-    { GoogleServiceAuthError::CONNECTION_FAILED, false },
-    { GoogleServiceAuthError::CAPTCHA_REQUIRED, true },
-    { GoogleServiceAuthError::ACCOUNT_DELETED, true },
-    { GoogleServiceAuthError::ACCOUNT_DISABLED, true },
-    { GoogleServiceAuthError::SERVICE_UNAVAILABLE, true },
-    { GoogleServiceAuthError::TWO_FACTOR, true },
-    { GoogleServiceAuthError::REQUEST_CANCELED, true },
-    { GoogleServiceAuthError::HOSTED_NOT_ALLOWED, true },
-    { GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, true },
-    { GoogleServiceAuthError::SERVICE_ERROR, true },
-  };
-  COMPILE_ASSERT(ARRAYSIZE_UNSAFE(table) == GoogleServiceAuthError::NUM_STATES,
-      kTable_size_does_not_match_number_of_auth_error_types);
-
-  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(table); ++i) {
-    FakeAuthStatusProvider provider(error_controller_.get());
-    provider.SetAuthError(kTestAccountId,
-                          GoogleServiceAuthError(table[i].error_state));
-
-    EXPECT_EQ(error_controller_->HasError(), table[i].is_error);
-
-    if (table[i].is_error) {
-      EXPECT_EQ(table[i].error_state,
-                error_controller_->auth_error().state());
-      EXPECT_STREQ(kTestAccountId,
-                   error_controller_->error_account_id().c_str());
-    } else {
-      EXPECT_EQ(GoogleServiceAuthError::NONE,
-                error_controller_->auth_error().state());
-      EXPECT_STREQ("",
-                   error_controller_->error_account_id().c_str());
-    }
-  }
-}
-
-// Verify that existing error is not replaced by new error.
-TEST_F(SigninErrorControllerTest, AuthStatusChange) {
-  scoped_ptr<FakeAuthStatusProvider> fake_provider0(
-      new FakeAuthStatusProvider(error_controller_.get()));
-  scoped_ptr<FakeAuthStatusProvider> fake_provider1(
-      new FakeAuthStatusProvider(error_controller_.get()));
-
-  // If there are multiple providers in the provider set...
-  //
-  // | provider0 |       provider1          | ...
-  // |   NONE    | INVALID_GAIA_CREDENTIALS | ...
-  //
-  // SigninErrorController picks the first error found when iterating through
-  // the set. But if another error crops up...
-  //
-  // |     provider0       |       provider1          | ...
-  // | SERVICE_UNAVAILABLE | INVALID_GAIA_CREDENTIALS | ...
-  //
-  // we want the controller to still use the original error.
-
-  // The provider pointers are stored in a set, which is sorted by std::less.
-  std::less<SigninErrorController::AuthStatusProvider*> compare;
-  FakeAuthStatusProvider* provider0 =
-      compare(fake_provider0.get(), fake_provider1.get()) ?
-          fake_provider0.get() : fake_provider1.get();
-  FakeAuthStatusProvider* provider1 =
-      provider0 == fake_provider0.get() ?
-          fake_provider1.get() : fake_provider0.get();
-
-  provider0->SetAuthError(
-      kTestAccountId,
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::NONE));
-  provider1->SetAuthError(
-      kOtherTestAccountId,
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-  ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
-            error_controller_->auth_error().state());
-  ASSERT_STREQ(kOtherTestAccountId,
-               error_controller_->error_account_id().c_str());
-
-  // Change the 1st provider's error.
-  provider1->SetAuthError(
-      kOtherTestAccountId,
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::SERVICE_UNAVAILABLE));
-  ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE,
-            error_controller_->auth_error().state());
-  ASSERT_STREQ(kOtherTestAccountId,
-               error_controller_->error_account_id().c_str());
-
-  // Set the 0th provider's error -- nothing should change.
-  provider0->SetAuthError(
-      kTestAccountId,
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE));
-  ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE,
-            error_controller_->auth_error().state());
-  ASSERT_STREQ(kOtherTestAccountId,
-               error_controller_->error_account_id().c_str());
-
-  // Clear the 1st provider's error, so the 0th provider's error is used.
-  provider1->SetAuthError(
-      kOtherTestAccountId,
-      GoogleServiceAuthError(
-          GoogleServiceAuthError::NONE));
-  ASSERT_EQ(GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE,
-            error_controller_->auth_error().state());
-  ASSERT_STREQ(kTestAccountId,
-               error_controller_->error_account_id().c_str());
-
-  fake_provider0.reset();
-  fake_provider1.reset();
-  ASSERT_FALSE(error_controller_->HasError());
-}
diff --git a/chrome/browser/signin/signin_error_notifier_ash.cc b/chrome/browser/signin/signin_error_notifier_ash.cc
index d40fd47..23b0a7c 100644
--- a/chrome/browser/signin/signin_error_notifier_ash.cc
+++ b/chrome/browser/signin/signin_error_notifier_ash.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/notifications/notification_delegate.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/chrome_pages.h"
@@ -163,17 +164,22 @@
   SigninNotificationDelegate* delegate =
       new SigninNotificationDelegate(notification_id_, profile_);
 
+  message_center::NotifierId notifier_id(
+      message_center::NotifierId::SYSTEM_COMPONENT,
+      kProfileSigninNotificationId);
+
+  // Set |profile_id| for multi-user notification blocker.
+  notifier_id.profile_id = multi_user_util::GetUserIDFromProfile(profile_);
+
   Notification notification(
       message_center::NOTIFICATION_TYPE_SIMPLE,
       GURL(notification_id_),
-      GetMessageTitle(),
+      l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE),
       GetMessageBody(),
       ui::ResourceBundle::GetSharedInstance().GetImageNamed(
           IDR_NOTIFICATION_ALERT),
       blink::WebTextDirectionDefault,
-      message_center::NotifierId(
-          message_center::NotifierId::SYSTEM_COMPONENT,
-          ash::system_notifier::kNotifierAuthError),
+      notifier_id,
       base::string16(),  // display_source
       base::ASCIIToUTF16(notification_id_),
       data,
@@ -186,19 +192,6 @@
     notification_ui_manager->Add(notification, profile_);
 }
 
-base::string16 SigninErrorNotifier::GetMessageTitle() const {
-  if (ash::Shell::HasInstance() &&
-      ash::Shell::GetInstance()->delegate()->IsMultiProfilesEnabled()) {
-    // Include the account id in the message text to differentiate between
-    // profiles.
-    return l10n_util::GetStringFUTF16(
-        IDS_SIGNIN_ERROR_NOTIFICATION_TITLE_MULTIPROFILE,
-        base::ASCIIToUTF16(error_controller_->error_account_id()));
-  }
-
-  return l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE);
-}
-
 base::string16 SigninErrorNotifier::GetMessageBody() const {
   switch (error_controller_->auth_error().state()) {
     // TODO(rogerta): use account id in error messages.
diff --git a/chrome/browser/signin/signin_error_notifier_ash.h b/chrome/browser/signin/signin_error_notifier_ash.h
index 34819b3..f450c3c 100644
--- a/chrome/browser/signin/signin_error_notifier_ash.h
+++ b/chrome/browser/signin/signin_error_notifier_ash.h
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/strings/string16.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 
 class Profile;
 
@@ -29,7 +29,6 @@
   virtual void OnErrorChanged() OVERRIDE;
 
  private:
-  base::string16 GetMessageTitle() const;
   base::string16 GetMessageBody() const;
 
   // The error controller to query for error details.
diff --git a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
index 4bc4400..841d3cf 100644
--- a/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
+++ b/chrome/browser/signin/signin_error_notifier_ash_unittest.cc
@@ -9,7 +9,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/notifications/notification.h"
 #include "chrome/browser/notifications/notification_ui_manager.h"
-#include "chrome/browser/signin/fake_auth_status_provider.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_error_notifier_factory_ash.h"
@@ -19,8 +18,9 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/message_center/notification.h"
@@ -66,12 +66,12 @@
     views::ViewsDelegate::views_delegate = &views_delegate_;
 
     // Create a signed-in profile.
-    profile_.reset(new TestingProfile());
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              FakeSigninManagerBase::Build);
+    profile_ = builder.Build();
     profile_->set_profile_name(kTestAccountId);
 
-    SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-            profile_.get(), FakeSigninManagerBase::Build);
-
     profile_manager_.reset(
         new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
     ASSERT_TRUE(profile_manager_->SetUp());
@@ -130,7 +130,6 @@
     ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId));
     {
       FakeAuthStatusProvider error_provider(error_controller_);
-      LOG(ERROR) << "Setting auth error";
       error_provider.SetAuthError(kTestAccountId, GoogleServiceAuthError(
           GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
       ASSERT_TRUE(notification_ui_manager_->FindById(kNotificationId));
diff --git a/chrome/browser/signin/signin_error_notifier_factory_ash.cc b/chrome/browser/signin/signin_error_notifier_factory_ash.cc
index 1c621d8..100df63 100644
--- a/chrome/browser/signin/signin_error_notifier_factory_ash.cc
+++ b/chrome/browser/signin/signin_error_notifier_factory_ash.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_error_notifier_ash.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 SigninErrorNotifierFactory::SigninErrorNotifierFactory()
     : BrowserContextKeyedServiceFactory(
diff --git a/chrome/browser/signin/signin_global_error.h b/chrome/browser/signin/signin_global_error.h
index 7723c83..dc0718c 100644
--- a/chrome/browser/signin/signin_global_error.h
+++ b/chrome/browser/signin/signin_global_error.h
@@ -10,7 +10,7 @@
 #include "base/compiler_specific.h"
 #include "chrome/browser/ui/global_error/global_error.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 
 class Profile;
 
diff --git a/chrome/browser/signin/signin_global_error_factory.cc b/chrome/browser/signin/signin_global_error_factory.cc
index 6dc46d0..47ecb90 100644
--- a/chrome/browser/signin/signin_global_error_factory.cc
+++ b/chrome/browser/signin/signin_global_error_factory.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/signin/signin_global_error.h"
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 #if defined(USE_ASH)
 #include "ash/shell.h"
diff --git a/chrome/browser/signin/signin_global_error_unittest.cc b/chrome/browser/signin/signin_global_error_unittest.cc
index 62e8863..54c7c8e 100644
--- a/chrome/browser/signin/signin_global_error_unittest.cc
+++ b/chrome/browser/signin/signin_global_error_unittest.cc
@@ -6,9 +6,8 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_service.h"
-#include "chrome/browser/signin/fake_auth_status_provider.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_global_error_factory.h"
@@ -18,7 +17,8 @@
 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -30,7 +30,7 @@
     // Create a signed-in profile.
     TestingProfile::Builder builder;
     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                              FakeProfileOAuth2TokenServiceWrapper::Build);
+                              BuildFakeProfileOAuth2TokenService);
     builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
                               FakeSigninManagerBase::Build);
     profile_ = builder.Build();
diff --git a/chrome/browser/signin/signin_header_helper.cc b/chrome/browser/signin/signin_header_helper.cc
index 78c6a4f..b43c4ba 100644
--- a/chrome/browser/signin/signin_header_helper.cc
+++ b/chrome/browser/signin/signin_header_helper.cc
@@ -36,9 +36,10 @@
 
 #if !defined(OS_ANDROID)
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
-  if (browser)
-    browser->window()->ShowAvatarBubbleFromAvatarButton();
-  // TODO(guohui): need to handle the case when avatar button is not available.
+  if (browser) {
+    browser->window()->ShowAvatarBubbleFromAvatarButton(
+        BrowserWindow::AVATAR_BUBBLE_MODE_ACCOUNT_MANAGEMENT);
+  }
 #else  // defined(OS_ANDROID)
   AccountManagementScreenHelper::OpenAccountManagementScreen(
       Profile::FromBrowserContext(web_contents->GetBrowserContext()));
diff --git a/chrome/browser/signin/signin_internals_util.cc b/chrome/browser/signin/signin_internals_util.cc
deleted file mode 100644
index cfb3ec5..0000000
--- a/chrome/browser/signin/signin_internals_util.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/signin_internals_util.h"
-
-#include <sstream>
-
-#include "base/logging.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/url_constants.h"
-#include "content/public/browser/web_contents.h"
-#include "crypto/sha2.h"
-#include "google_apis/gaia/gaia_constants.h"
-
-namespace signin_internals_util {
-
-const char kSigninPrefPrefix[] = "google.services.signin.";
-const char kTokenPrefPrefix[] = "google.services.signin.tokens.";
-
-#define ENUM_CASE(x) case x: return (std::string(kSigninPrefPrefix) + #x)
-std::string SigninStatusFieldToString(UntimedSigninStatusField field) {
-  switch (field) {
-    ENUM_CASE(USERNAME);
-    case UNTIMED_FIELDS_END:
-      NOTREACHED();
-      return std::string();
-  }
-
-  NOTREACHED();
-  return std::string();
-}
-
-std::string SigninStatusFieldToString(TimedSigninStatusField field) {
-  switch (field) {
-    ENUM_CASE(SIGNIN_TYPE);
-    ENUM_CASE(CLIENT_LOGIN_STATUS);
-    ENUM_CASE(OAUTH_LOGIN_STATUS);
-    ENUM_CASE(GET_USER_INFO_STATUS);
-    ENUM_CASE(UBER_TOKEN_STATUS);
-    ENUM_CASE(MERGE_SESSION_STATUS);
-    case TIMED_FIELDS_END:
-      NOTREACHED();
-      return std::string();
-  }
-
-  NOTREACHED();
-  return std::string();
-}
-
-std::string TokenPrefPath(const std::string& token_name) {
-  return std::string(kTokenPrefPrefix) + token_name;
-}
-
-// Gets the first few hex characters of the SHA256 hash of the passed in string.
-// These are enough to perform equality checks across a single users tokens,
-// while preventing outsiders from reverse-engineering the actual token from
-// the displayed value.
-// Note that for readability (in about:signin-internals), an empty string
-// is not hashed, but simply returned as an empty string.
-std::string GetTruncatedHash(const std::string& str) {
-  if (str.empty())
-    return str;
-
-  // Since each character in the hash string generates two hex charaters
-  // we only need half as many charaters in |hash_val| as hex characters
-  // returned.
-  const int kTruncateSize = kTruncateTokenStringLength / 2;
-  char hash_val[kTruncateSize];
-  crypto::SHA256HashString(str, &hash_val[0], kTruncateSize);
-  return StringToLowerASCII(base::HexEncode(&hash_val[0], kTruncateSize));
-}
-
-} //  namespace signin_internals_util
diff --git a/chrome/browser/signin/signin_internals_util.h b/chrome/browser/signin/signin_internals_util.h
deleted file mode 100644
index 82998ad..0000000
--- a/chrome/browser/signin/signin_internals_util.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_INTERNALS_UTIL_H_
-#define CHROME_BROWSER_SIGNIN_SIGNIN_INTERNALS_UTIL_H_
-
-#include <map>
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-
-namespace signin_internals_util {
-
-// Preference prefixes for signin and token values.
-extern const char kSigninPrefPrefix[];
-extern const char kTokenPrefPrefix[];
-
-// The length of strings returned by GetTruncatedHash() below.
-const size_t kTruncateTokenStringLength = 6;
-
-// Helper enums to access fields from SigninStatus (declared below).
-enum {
-  SIGNIN_FIELDS_BEGIN = 0,
-  UNTIMED_FIELDS_BEGIN = SIGNIN_FIELDS_BEGIN
-};
-
-enum UntimedSigninStatusField {
-  USERNAME = UNTIMED_FIELDS_BEGIN,
-  UNTIMED_FIELDS_END
-};
-
-enum {
-  UNTIMED_FIELDS_COUNT = UNTIMED_FIELDS_END - UNTIMED_FIELDS_BEGIN,
-  TIMED_FIELDS_BEGIN = UNTIMED_FIELDS_END
-};
-
-enum TimedSigninStatusField {
-  SIGNIN_TYPE = TIMED_FIELDS_BEGIN,
-  CLIENT_LOGIN_STATUS,
-  OAUTH_LOGIN_STATUS,
-  GET_USER_INFO_STATUS,
-  UBER_TOKEN_STATUS,
-  MERGE_SESSION_STATUS,
-  TIMED_FIELDS_END
-};
-
-enum {
-  TIMED_FIELDS_COUNT = TIMED_FIELDS_END - TIMED_FIELDS_BEGIN,
-  SIGNIN_FIELDS_END = TIMED_FIELDS_END,
-  SIGNIN_FIELDS_COUNT = SIGNIN_FIELDS_END - SIGNIN_FIELDS_BEGIN
-};
-
-// Returns the root preference path for the service. The path should be
-// qualified with one of .value, .status or .time to get the respective
-// full preference path names.
-std::string TokenPrefPath(const std::string& service_name);
-
-// Returns the name of a SigninStatus field.
-std::string SigninStatusFieldToString(UntimedSigninStatusField field);
-std::string SigninStatusFieldToString(TimedSigninStatusField field);
-
-// An Observer class for authentication and token diagnostic information.
-class SigninDiagnosticsObserver {
- public:
-  // Credentials and signin related changes.
-  virtual void NotifySigninValueChanged(const UntimedSigninStatusField& field,
-                                        const std::string& value) {}
-  virtual void NotifySigninValueChanged(const TimedSigninStatusField& field,
-                                        const std::string& value) {}
-  // OAuth tokens related changes.
-  virtual void NotifyTokenReceivedSuccess(const std::string& token_name,
-                                          const std::string& token,
-                                          bool update_time) {}
-  virtual void NotifyTokenReceivedFailure(const std::string& token_name,
-                                          const std::string& error) {}
-  virtual void NotifyClearStoredToken(const std::string& token_name) {}};
-
-// Gets the first 6 hex characters of the SHA256 hash of the passed in string.
-// These are enough to perform equality checks across a single users tokens,
-// while preventing outsiders from reverse-engineering the actual token from
-// the displayed value.
-// Note that for readability (in about:signin-internals), an empty string
-// is not hashed, but simply returned as an empty string.
-std::string GetTruncatedHash(const std::string& str);
-
-} // namespace signin_internals_util
-
-#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_INTERNALS_UTIL_H_
diff --git a/chrome/browser/signin/signin_manager.cc b/chrome/browser/signin/signin_manager.cc
index 6d09ce3..6ce8633 100644
--- a/chrome/browser/signin/signin_manager.cc
+++ b/chrome/browser/signin/signin_manager.cc
@@ -13,23 +13,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/profile_io_data.h"
-#include "chrome/browser/signin/about_signin_internals.h"
-#include "chrome/browser/signin/about_signin_internals_factory.h"
-#include "chrome/browser/signin/local_auth.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_account_id_helper.h"
-#include "chrome/browser/signin/signin_internals_util.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/profile_management_switches.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_client.h"
-#include "components/signin/core/signin_manager_cookie_helper.h"
-#include "content/public/browser/browser_thread.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/core/browser/signin_internals_util.h"
+#include "components/signin/core/browser/signin_manager_cookie_helper.h"
+#include "components/signin/core/common/signin_pref_names.h"
 #include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/child_process_host.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/escape.h"
@@ -37,10 +29,6 @@
 
 using namespace signin_internals_util;
 
-using content::BrowserThread;
-using content::ChildProcessHost;
-using content::RenderProcessHost;
-
 namespace {
 
 const char kChromiumSyncService[] = "service=chromiumsync";
@@ -72,37 +60,15 @@
           .find(kChromiumSyncService) != std::string::npos;
 }
 
-SigninManager::SigninManager(SigninClient* client)
-    : prohibit_signout_(false),
+SigninManager::SigninManager(SigninClient* client,
+                             ProfileOAuth2TokenService* token_service)
+    : SigninManagerBase(client),
+      profile_(NULL),
+      prohibit_signout_(false),
       type_(SIGNIN_TYPE_NONE),
       weak_pointer_factory_(this),
-      signin_host_id_(ChildProcessHost::kInvalidUniqueID),
-      client_(client) {}
-
-void SigninManager::SetSigninProcess(int process_id) {
-  if (process_id == signin_host_id_)
-    return;
-  DLOG_IF(WARNING,
-          signin_host_id_ != ChildProcessHost::kInvalidUniqueID)
-      << "Replacing in-use signin process.";
-  signin_host_id_ = process_id;
-  RenderProcessHost* host = RenderProcessHost::FromID(process_id);
-  DCHECK(host);
-  host->AddObserver(this);
-  signin_hosts_observed_.insert(host);
-}
-
-void SigninManager::ClearSigninProcess() {
-  signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
-}
-
-bool SigninManager::IsSigninProcess(int process_id) const {
-  return process_id == signin_host_id_;
-}
-
-bool SigninManager::HasSigninProcess() const {
-  return signin_host_id_ != ChildProcessHost::kInvalidUniqueID;
-}
+      client_(client),
+      token_service_(token_service) {}
 
 void SigninManager::AddMergeSessionObserver(
     MergeSessionHelper::Observer* observer) {
@@ -117,20 +83,12 @@
 }
 
 SigninManager::~SigninManager() {
-  std::set<RenderProcessHost*>::iterator i;
-  for (i = signin_hosts_observed_.begin();
-       i != signin_hosts_observed_.end();
-       ++i) {
-    (*i)->RemoveObserver(this);
-  }
 }
 
 void SigninManager::InitTokenService() {
-  ProfileOAuth2TokenService* token_service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
   const std::string& account_id = GetAuthenticatedUsername();
-  if (token_service && !account_id.empty())
-    token_service->LoadCredentials(account_id);
+  if (token_service_ && !account_id.empty())
+    token_service_->LoadCredentials(account_id);
 }
 
 std::string SigninManager::SigninTypeToString(
@@ -202,6 +160,7 @@
   DCHECK_NE(this, &source);
   possibly_invalid_username_ = source.possibly_invalid_username_;
   temp_refresh_token_ = source.temp_refresh_token_;
+  password_ = source.password_;
 }
 
 void SigninManager::ClearTransientSigninData() {
@@ -254,7 +213,7 @@
 
   const std::string& username = GetAuthenticatedUsername();
   clear_authenticated_username();
-  profile_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
+  client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
 
   // Erase (now) stale information from AboutSigninInternals.
   NotifyDiagnosticsObservers(USERNAME, "");
@@ -262,11 +221,9 @@
   // Revoke all tokens before sending signed_out notification, because there
   // may be components that don't listen for token service events when the
   // profile is not connected to an account.
-  ProfileOAuth2TokenService* token_service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
   LOG(WARNING) << "Revoking refresh token on server. Reason: sign out, "
                << "IsSigninAllowed: " << IsSigninAllowed();
-  token_service->RevokeAllCredentials();
+  token_service_->RevokeAllCredentials();
 
   // TODO(blundell): Eliminate this notification send once crbug.com/333997 is
   // fixed.
@@ -280,6 +237,7 @@
 }
 
 void SigninManager::Initialize(Profile* profile, PrefService* local_state) {
+  profile_ = profile;
   SigninManagerBase::Initialize(profile, local_state);
 
   // local_state can be null during unit tests.
@@ -290,12 +248,13 @@
         base::Bind(&SigninManager::OnGoogleServicesUsernamePatternChanged,
                    weak_pointer_factory_.GetWeakPtr()));
   }
-  signin_allowed_.Init(prefs::kSigninAllowed, profile_->GetPrefs(),
-      base::Bind(&SigninManager::OnSigninAllowedPrefChanged,
-                 base::Unretained(this)));
+  signin_allowed_.Init(prefs::kSigninAllowed,
+                       client_->GetPrefs(),
+                       base::Bind(&SigninManager::OnSigninAllowedPrefChanged,
+                                  base::Unretained(this)));
 
-  std::string user = profile_->GetPrefs()->GetString(
-      prefs::kGoogleServicesUsername);
+  std::string user =
+      client_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
   if ((!user.empty() && !IsAllowedUsername(user)) || !IsSigninAllowed()) {
     // User is signed in, but the username is invalid - the administrator must
     // have changed the policy since the last signin, so sign out the user.
@@ -303,7 +262,8 @@
   }
 
   InitTokenService();
-  account_id_helper_.reset(new SigninAccountIdHelper(this));
+  account_id_helper_.reset(
+      new SigninAccountIdHelper(client_, token_service_, this));
 }
 
 void SigninManager::Shutdown() {
@@ -328,12 +288,6 @@
   return signin_allowed_.GetValue();
 }
 
-// static
-bool SigninManager::IsSigninAllowedOnIOThread(ProfileIOData* io_data) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
-  return io_data->signin_allowed()->GetValue();
-}
-
 void SigninManager::OnSigninAllowedPrefChanged() {
   if (!IsSigninAllowed())
     SignOut();
@@ -390,18 +344,14 @@
   return possibly_invalid_username_;
 }
 
-void SigninManager::DisableOneClickSignIn(Profile* profile) {
-  PrefService* pref_service = profile->GetPrefs();
-  pref_service->SetBoolean(prefs::kReverseAutologinEnabled, false);
+void SigninManager::DisableOneClickSignIn(PrefService* prefs) {
+  prefs->SetBoolean(prefs::kReverseAutologinEnabled, false);
 }
 
 void SigninManager::CompletePendingSignin() {
   DCHECK(!possibly_invalid_username_.empty());
   OnSignedIn(possibly_invalid_username_);
 
-  ProfileOAuth2TokenService* token_service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
-
   // If inline sign in is enabled, but new profile management is not, perform a
   // merge session now to push the user's credentials into the cookie jar.
   bool do_merge_session_in_signin_manager =
@@ -410,13 +360,13 @@
 
   if (do_merge_session_in_signin_manager) {
     merge_session_helper_.reset(new MergeSessionHelper(
-        token_service, profile_->GetRequestContext(), NULL));
+        token_service_, client_->GetURLRequestContext(), NULL));
   }
 
   DCHECK(!temp_refresh_token_.empty());
   DCHECK(!GetAuthenticatedUsername().empty());
-  token_service->UpdateCredentials(GetAuthenticatedUsername(),
-                                   temp_refresh_token_);
+  token_service_->UpdateCredentials(GetAuthenticatedUsername(),
+                                    temp_refresh_token_);
   temp_refresh_token_.clear();
 
   if (do_merge_session_in_signin_manager)
@@ -444,24 +394,10 @@
                     GoogleSigninSucceeded(GetAuthenticatedUsername(),
                                           password_));
 
-#if !defined(OS_ANDROID)
-  // Don't store password hash except for users of new profile features.
-  if (switches::IsNewProfileManagement())
-    chrome::SetLocalAuthCredentials(profile_, password_);
-#endif
+  client_->GoogleSigninSucceeded(GetAuthenticatedUsername(), password_);
 
   password_.clear();  // Don't need it anymore.
-  DisableOneClickSignIn(profile_);  // Don't ever offer again.
-}
-
-void SigninManager::RenderProcessHostDestroyed(RenderProcessHost* host) {
-  // It's possible we're listening to a "stale" renderer because it was replaced
-  // with a new process by process-per-site. In either case, stop observing it,
-  // but only reset signin_host_id_ tracking if this was from the current signin
-  // process.
-  signin_hosts_observed_.erase(host);
-  if (signin_host_id_ == host->GetID())
-    signin_host_id_ = ChildProcessHost::kInvalidUniqueID;
+  DisableOneClickSignIn(client_->GetPrefs());  // Don't ever offer again.
 }
 
 void SigninManager::ProhibitSignout(bool prohibit_signout) {
diff --git a/chrome/browser/signin/signin_manager.h b/chrome/browser/signin/signin_manager.h
index b780d28..258c97c 100644
--- a/chrome/browser/signin/signin_manager.h
+++ b/chrome/browser/signin/signin_manager.h
@@ -17,7 +17,7 @@
 
 #if defined(OS_CHROMEOS)
 // On Chrome OS, SigninManagerBase is all that exists.
-#include "chrome/browser/signin/signin_manager_base.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 
 #else
 
@@ -31,23 +31,19 @@
 #include "base/observer_list.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "base/prefs/pref_member.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_internals_util.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "content/public/browser/render_process_host_observer.h"
+#include "components/signin/core/browser/signin_internals_util.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/merge_session_helper.h"
 #include "net/cookies/canonical_cookie.h"
 
-class CookieSettings;
-class ProfileIOData;
 class PrefService;
+class ProfileOAuth2TokenService;
 class SigninAccountIdHelper;
 class SigninClient;
 
-class SigninManager : public SigninManagerBase,
-                      public content::RenderProcessHostObserver {
+class SigninManager : public SigninManagerBase {
  public:
   // The callback invoked once the OAuth token has been fetched during signin,
   // but before the profile transitions to the "signed-in" state. This allows
@@ -66,7 +62,7 @@
   // OneClickSigninHelper.
   static const char kChromeSigninEffectiveSite[];
 
-  explicit SigninManager(SigninClient* client);
+  SigninManager(SigninClient* client, ProfileOAuth2TokenService* token_service);
   virtual ~SigninManager();
 
   // Returns true if the username is allowed based on the policy string.
@@ -119,13 +115,10 @@
   // authenticated. Returns an empty string if no auth is in progress.
   const std::string& GetUsernameForAuthInProgress() const;
 
-  // Set the profile preference to turn off one-click sign-in so that it won't
-  // ever show it again in this profile (even if the user tries a new account).
-  static void DisableOneClickSignIn(Profile* profile);
-
-  // content::RenderProcessHostObserver
-  virtual void RenderProcessHostDestroyed(
-      content::RenderProcessHost* host) OVERRIDE;
+  // Set the preference to turn off one-click sign-in so that it won't ever
+  // show it again for the user associated with |prefs| (even if the user tries
+  // a new account).
+  static void DisableOneClickSignIn(PrefService* prefs);
 
   // Tells the SigninManager whether to prohibit signout for this profile.
   // If |prohibit_signout| is true, then signout will be prohibited.
@@ -135,28 +128,15 @@
   // ignored).
   bool IsSignoutProhibited() const;
 
-  // Checks if signin is allowed for the profile that owns |io_data|. This must
-  // be invoked on the IO thread, and can be used to check if signin is enabled
-  // on that thread.
-  static bool IsSigninAllowedOnIOThread(ProfileIOData* io_data);
-
-  // Allows the SigninManager to track the privileged signin process
-  // identified by |host_id| so that we can later ask (via IsSigninProcess)
-  // if it is safe to sign the user in from the current context (see
-  // OneClickSigninHelper).  All of this tracking state is reset once the
-  // renderer process terminates.
-  //
-  // N.B. This is the id returned by RenderProcessHost::GetID().
-  void SetSigninProcess(int host_id);
-  void ClearSigninProcess();
-  bool IsSigninProcess(int host_id) const;
-  bool HasSigninProcess() const;
-
   // Add or remove observers for the merge session notification.
   void AddMergeSessionObserver(MergeSessionHelper::Observer* observer);
   void RemoveMergeSessionObserver(MergeSessionHelper::Observer* observer);
 
  protected:
+  // Pointer to parent profile (protected so FakeSigninManager can access
+  // it).
+  Profile* profile_;
+
   // Flag saying whether signing out is allowed.
   bool prohibit_signout_;
 
@@ -219,17 +199,14 @@
 
   base::WeakPtrFactory<SigninManager> weak_pointer_factory_;
 
-  // See SetSigninProcess.  Tracks the currently active signin process
-  // by ID, if there is one.
-  int signin_host_id_;
-
-  // The RenderProcessHosts being observed.
-  std::set<content::RenderProcessHost*> signin_hosts_observed_;
-
   // The SigninClient object associated with this object. Must outlive this
   // object.
   SigninClient* client_;
 
+  // The ProfileOAuth2TokenService instance associated with this object. Must
+  // outlive this object.
+  ProfileOAuth2TokenService* token_service_;
+
   // Helper object to listen for changes to signin preferences stored in non-
   // profile-specific local prefs (like kGoogleServicesUsernamePattern).
   PrefChangeRegistrar local_state_pref_registrar_;
diff --git a/chrome/browser/signin/signin_manager_base.cc b/chrome/browser/signin/signin_manager_base.cc
deleted file mode 100644
index e9504c9..0000000
--- a/chrome/browser/signin/signin_manager_base.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/signin/signin_manager_base.h"
-
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/memory/ref_counted.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/signin/about_signin_internals.h"
-#include "chrome/browser/signin/about_signin_internals_factory.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "components/sync_driver/sync_prefs.h"
-#include "content/public/browser/browser_thread.h"
-#include "google_apis/gaia/gaia_auth_util.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-
-using namespace signin_internals_util;
-
-using content::BrowserThread;
-
-SigninManagerBase::SigninManagerBase()
-    : profile_(NULL),
-      weak_pointer_factory_(this) {
-}
-
-SigninManagerBase::~SigninManagerBase() {
-}
-
-void SigninManagerBase::Initialize(Profile* profile, PrefService* local_state) {
-  // Should never call Initialize() twice.
-  DCHECK(!IsInitialized());
-  profile_ = profile;
-
-  // If the user is clearing the token service from the command line, then
-  // clear their login info also (not valid to be logged in without any
-  // tokens).
-  CommandLine* cmd_line = CommandLine::ForCurrentProcess();
-  if (cmd_line->HasSwitch(switches::kClearTokenService))
-    profile->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
-
-  std::string user = profile_->GetPrefs()->GetString(
-      prefs::kGoogleServicesUsername);
-  if (!user.empty())
-    SetAuthenticatedUsername(user);
-}
-
-bool SigninManagerBase::IsInitialized() const {
-  return profile_ != NULL;
-}
-
-bool SigninManagerBase::IsSigninAllowed() const {
-  return profile_->GetPrefs()->GetBoolean(prefs::kSigninAllowed);
-}
-
-const std::string& SigninManagerBase::GetAuthenticatedUsername() const {
-  return authenticated_username_;
-}
-
-const std::string& SigninManagerBase::GetAuthenticatedAccountId() const {
-  return GetAuthenticatedUsername();
-}
-
-void SigninManagerBase::SetAuthenticatedUsername(const std::string& username) {
-  if (!authenticated_username_.empty()) {
-    DLOG_IF(ERROR, !gaia::AreEmailsSame(username, authenticated_username_)) <<
-        "Tried to change the authenticated username to something different: " <<
-        "Current: " << authenticated_username_ << ", New: " << username;
-
-#if defined(OS_IOS)
-    // Prior to M26, chrome on iOS did not normalize the email before setting
-    // it in SigninManager.  If the emails are the same as given by
-    // gaia::AreEmailsSame() but not the same as given by std::string::op==(),
-    // make sure to set the authenticated name below.
-    if (!gaia::AreEmailsSame(username, authenticated_username_) ||
-        username == authenticated_username_) {
-      return;
-    }
-#else
-    return;
-#endif
-  }
-  std::string pref_username = profile_->GetPrefs()->GetString(
-      prefs::kGoogleServicesUsername);
-  DCHECK(pref_username.empty() ||
-      gaia::AreEmailsSame(username, pref_username))
-      << "username: " << username << "; pref_username: " << pref_username;
-  authenticated_username_ = username;
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username);
-  NotifyDiagnosticsObservers(USERNAME, username);
-
-  // Go ahead and update the last signed in username here as well. Once a
-  // user is signed in the two preferences should match. Doing it here as
-  // opposed to on signin allows us to catch the upgrade scenario.
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername, username);
-}
-
-void SigninManagerBase::clear_authenticated_username() {
-  authenticated_username_.clear();
-}
-
-bool SigninManagerBase::AuthInProgress() const {
-  // SigninManagerBase never kicks off auth processes itself.
-  return false;
-}
-
-void SigninManagerBase::Shutdown() {
-}
-
-void SigninManagerBase::AddObserver(Observer* observer) {
-  observer_list_.AddObserver(observer);
-}
-
-void SigninManagerBase::RemoveObserver(Observer* observer) {
-  observer_list_.RemoveObserver(observer);
-}
-
-void SigninManagerBase::AddSigninDiagnosticsObserver(
-    SigninDiagnosticsObserver* observer) {
-  signin_diagnostics_observers_.AddObserver(observer);
-}
-
-void SigninManagerBase::RemoveSigninDiagnosticsObserver(
-    SigninDiagnosticsObserver* observer) {
-  signin_diagnostics_observers_.RemoveObserver(observer);
-}
-
-void SigninManagerBase::NotifyDiagnosticsObservers(
-    const UntimedSigninStatusField& field,
-    const std::string& value) {
-  FOR_EACH_OBSERVER(SigninDiagnosticsObserver,
-                    signin_diagnostics_observers_,
-                    NotifySigninValueChanged(field, value));
-}
-
-void SigninManagerBase::NotifyDiagnosticsObservers(
-    const TimedSigninStatusField& field,
-    const std::string& value) {
-  FOR_EACH_OBSERVER(SigninDiagnosticsObserver,
-                    signin_diagnostics_observers_,
-                    NotifySigninValueChanged(field, value));
-}
diff --git a/chrome/browser/signin/signin_manager_base.h b/chrome/browser/signin/signin_manager_base.h
deleted file mode 100644
index 127bc13..0000000
--- a/chrome/browser/signin/signin_manager_base.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The signin manager encapsulates some functionality tracking
-// which user is signed in.
-//
-// **NOTE** on semantics of SigninManager:
-//
-// Once a signin is successful, the username becomes "established" and will not
-// be cleared until a SignOut operation is performed (persists across
-// restarts). Until that happens, the signin manager can still be used to
-// refresh credentials, but changing the username is not permitted.
-//
-// On Chrome OS, because of the existence of other components that handle login
-// and signin at a higher level, all that is needed from a SigninManager is
-// caching / handling of the "authenticated username" field, and TokenService
-// initialization, so that components that depend on these two things
-// (i.e on desktop) can continue using it / don't need to change. For this
-// reason, SigninManagerBase is all that exists on Chrome OS. For desktop,
-// see signin/signin_manager.h.
-
-#ifndef CHROME_BROWSER_SIGNIN_SIGNIN_MANAGER_BASE_H_
-#define CHROME_BROWSER_SIGNIN_SIGNIN_MANAGER_BASE_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/gtest_prod_util.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
-#include "base/prefs/pref_change_registrar.h"
-#include "base/prefs/pref_member.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/signin_internals_util.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-
-class CookieSettings;
-class ProfileIOData;
-class PrefService;
-
-// Details for the Notification type GOOGLE_SIGNIN_SUCCESSFUL.
-// TODO(blundell): Eliminate this struct once crbug.com/333997 is fixed.
-// A listener might use this to make note of a username / password
-// pair for encryption keys.
-struct GoogleServiceSigninSuccessDetails {
-  GoogleServiceSigninSuccessDetails(const std::string& in_username,
-                                    const std::string& in_password)
-      : username(in_username),
-        password(in_password) {}
-  std::string username;
-  std::string password;
-};
-
-// Details for the Notification type NOTIFICATION_GOOGLE_SIGNED_OUT.
-// TODO(blundell): Eliminate this struct once crbug.com/333997 is fixed.
-struct GoogleServiceSignoutDetails {
-  explicit GoogleServiceSignoutDetails(const std::string& in_username)
-      : username(in_username) {}
-  std::string username;
-};
-
-class SigninManagerBase : public KeyedService {
- public:
-  class Observer {
-   public:
-    // Called when a user fails to sign into Google services such as sync.
-    virtual void GoogleSigninFailed(const GoogleServiceAuthError& error) {}
-
-    // Called when a user signs into Google services such as sync.
-    virtual void GoogleSigninSucceeded(const std::string& username,
-                                       const std::string& password) {}
-
-    // Called when the currently signed-in user for a user has been signed out.
-    virtual void GoogleSignedOut(const std::string& username) {}
-
-   protected:
-    virtual ~Observer() {}
-  };
-
-  SigninManagerBase();
-  virtual ~SigninManagerBase();
-
-  // If user was signed in, load tokens from DB if available.
-  virtual void Initialize(Profile* profile, PrefService* local_state);
-  bool IsInitialized() const;
-
-  // Returns true if a signin to Chrome is allowed (by policy or pref).
-  // TODO(tim): kSigninAllowed is defined for all platforms in pref_names.h.
-  // If kSigninAllowed pref was non-Chrome OS-only, this method wouldn't be
-  // needed, but as is we provide this method to let all interested code
-  // code query the value in one way, versus half using PrefService directly
-  // and the other half using SigninManager.
-  virtual bool IsSigninAllowed() const;
-
-  // If a user has previously signed in (and has not signed out), this returns
-  // the normalized email address of the account. Otherwise, it returns an empty
-  // string.
-  const std::string& GetAuthenticatedUsername() const;
-
-  // If a user has previously signed in (and has not signed out), this returns
-  // the account id. Otherwise, it returns an empty string.  This id can be used
-  // to uniquely identify an account, so for example can be used as a key to
-  // map accounts to data.
-  //
-  // TODO(rogerta): eventually the account id should be an obfuscated gaia id.
-  // For now though, this function returns the same value as
-  // GetAuthenticatedUsername() since lots of code assumes the unique id for an
-  // account is the username.  For code that needs a unique id to represent the
-  // connected account, call this method. Example: the AccountInfoMap type
-  // in MutableProfileOAuth2TokenService.  For code that needs to know the
-  // normalized email address of the connected account, use
-  // GetAuthenticatedUsername().  Example: to show the string "Signed in as XXX"
-  // in the hotdog menu.
-  const std::string& GetAuthenticatedAccountId() const;
-
-  // Sets the user name.  Note: |username| should be already authenticated as
-  // this is a sticky operation (in contrast to StartSignIn).
-  // TODO(tim): Remove this in favor of passing username on construction by
-  // (by platform / depending on StartBehavior). Bug 88109.
-  void SetAuthenticatedUsername(const std::string& username);
-
-  // Returns true if there's a signin in progress.
-  virtual bool AuthInProgress() const;
-
-  // KeyedService implementation.
-  virtual void Shutdown() OVERRIDE;
-
-  // Methods to register or remove observers of signin.
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
-
-  // Methods to register or remove SigninDiagnosticObservers.
-  void AddSigninDiagnosticsObserver(
-      signin_internals_util::SigninDiagnosticsObserver* observer);
-  void RemoveSigninDiagnosticsObserver(
-      signin_internals_util::SigninDiagnosticsObserver* observer);
-
-  Profile* profile() { return profile_; }
-
- protected:
-  // Used by subclass to clear authenticated_username_ instead of using
-  // SetAuthenticatedUsername, which enforces special preconditions due
-  // to the fact that it is part of the public API and called by clients.
-  void clear_authenticated_username();
-
-  // Pointer to parent profile (protected so FakeSigninManager can access
-  // it).
-  Profile* profile_;
-
-  // List of observers to notify on signin events.
-  // Makes sure list is empty on destruction.
-  ObserverList<Observer, true> observer_list_;
-
-  // Helper methods to notify all registered diagnostics observers with.
-  void NotifyDiagnosticsObservers(
-      const signin_internals_util::UntimedSigninStatusField& field,
-      const std::string& value);
-  void NotifyDiagnosticsObservers(
-      const signin_internals_util::TimedSigninStatusField& field,
-      const std::string& value);
-
- private:
-  friend class FakeSigninManagerBase;
-  friend class FakeSigninManager;
-
-  // Actual username after successful authentication.
-  std::string authenticated_username_;
-
-  // The list of SigninDiagnosticObservers.
-  ObserverList<signin_internals_util::SigninDiagnosticsObserver, true>
-      signin_diagnostics_observers_;
-
-  base::WeakPtrFactory<SigninManagerBase> weak_pointer_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SigninManagerBase);
-};
-
-#endif  // CHROME_BROWSER_SIGNIN_SIGNIN_MANAGER_BASE_H_
diff --git a/chrome/browser/signin/signin_manager_factory.cc b/chrome/browser/signin/signin_manager_factory.cc
index 0c4d6d7c..dfc6bf5 100644
--- a/chrome/browser/signin/signin_manager_factory.cc
+++ b/chrome/browser/signin/signin_manager_factory.cc
@@ -6,6 +6,7 @@
 
 #include "base/prefs/pref_registry_simple.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/local_auth.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
@@ -124,11 +125,13 @@
     content::BrowserContext* context) const {
   SigninManagerBase* service = NULL;
   Profile* profile = static_cast<Profile*>(context);
+  SigninClient* client =
+      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile);
 #if defined(OS_CHROMEOS)
-  service = new SigninManagerBase();
+  service = new SigninManagerBase(client);
 #else
   service = new SigninManager(
-      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile));
+      client, ProfileOAuth2TokenServiceFactory::GetForProfile(profile));
 #endif
   service->Initialize(profile, g_browser_process->local_state());
   FOR_EACH_OBSERVER(Observer, observer_list_, SigninManagerCreated(service));
diff --git a/chrome/browser/signin/signin_manager_unittest.cc b/chrome/browser/signin/signin_manager_unittest.cc
index 0b9bed7..54d2bc6 100644
--- a/chrome/browser/signin/signin_manager_unittest.cc
+++ b/chrome/browser/signin/signin_manager_unittest.cc
@@ -18,14 +18,14 @@
 #include "chrome/browser/prefs/browser_prefs.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/notification_source.h"
 #include "content/public/test/test_browser_thread_bundle.h"
@@ -46,7 +46,8 @@
   SigninManager* service = NULL;
   Profile* profile = static_cast<Profile*>(context);
   service = new SigninManager(
-      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile));
+      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile),
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile));
   service->Initialize(profile, NULL);
   return service;
 }
@@ -97,7 +98,9 @@
         prefs_.get());
     TestingProfile::Builder builder;
     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                              FakeProfileOAuth2TokenServiceWrapper::Build);
+                              BuildFakeProfileOAuth2TokenService);
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              SigninManagerBuild);
     profile_ = builder.Build();
   }
 
@@ -122,14 +125,13 @@
 
   TestingProfile* profile() { return profile_.get(); }
 
-  // Create a signin manager as a service if other code will try to get it as
+  // Sets up the signin manager as a service if other code will try to get it as
   // a PKS.
-  void CreateSigninManagerAsService() {
+  void SetUpSigninManagerAsService() {
     DCHECK(!manager_);
     DCHECK(!naked_manager_);
     manager_ = static_cast<SigninManager*>(
-        SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-            profile(), SigninManagerBuild));
+        SigninManagerFactory::GetForProfile(profile()));
     manager_->AddObserver(&test_observer_);
   }
 
@@ -137,7 +139,8 @@
   void CreateNakedSigninManager() {
     DCHECK(!manager_);
     naked_manager_.reset(new SigninManager(
-        ChromeSigninClientFactory::GetInstance()->GetForProfile(profile())));
+        ChromeSigninClientFactory::GetInstance()->GetForProfile(profile()),
+        ProfileOAuth2TokenServiceFactory::GetForProfile(profile())));
 
     manager_ = naked_manager_.get();
     manager_->AddObserver(&test_observer_);
@@ -183,7 +186,7 @@
 };
 
 TEST_F(SigninManagerTest, SignInWithRefreshToken) {
-  CreateSigninManagerAsService();
+  SetUpSigninManagerAsService();
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->StartSignInWithRefreshToken(
@@ -202,7 +205,7 @@
 }
 
 TEST_F(SigninManagerTest, SignInWithRefreshTokenCallbackComplete) {
-  CreateSigninManagerAsService();
+  SetUpSigninManagerAsService();
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   // Since the password is empty, must verify the gaia cookies first.
@@ -221,7 +224,7 @@
 }
 
 TEST_F(SigninManagerTest, SignOut) {
-  CreateSigninManagerAsService();
+  SetUpSigninManagerAsService();
   manager_->StartSignInWithRefreshToken(
       "rt1",
       "user@gmail.com",
@@ -237,7 +240,7 @@
 }
 
 TEST_F(SigninManagerTest, SignOutWhileProhibited) {
-  CreateSigninManagerAsService();
+  SetUpSigninManagerAsService();
   EXPECT_TRUE(manager_->GetAuthenticatedUsername().empty());
 
   manager_->SetAuthenticatedUsername("user@gmail.com");
@@ -335,5 +338,5 @@
   std::string user("user@google.com");
   profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername, user);
   profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
-  CreateSigninManagerAsService();
+  SetUpSigninManagerAsService();
 }
diff --git a/chrome/browser/signin/signin_names_io_thread.h b/chrome/browser/signin/signin_names_io_thread.h
index e647864..8db31a4 100644
--- a/chrome/browser/signin/signin_names_io_thread.h
+++ b/chrome/browser/signin/signin_names_io_thread.h
@@ -11,8 +11,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 
 // This class provides access to a list of email addresses for all profiles
 // connected to a Google account, from the IO thread.  The main purpose of
diff --git a/chrome/browser/signin/signin_tracker.cc b/chrome/browser/signin/signin_tracker.cc
index 9e04a1a..2cac080 100644
--- a/chrome/browser/signin/signin_tracker.cc
+++ b/chrome/browser/signin/signin_tracker.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/profile_management_switches.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_constants.h"
 
 #if !defined(OS_CHROMEOS)
diff --git a/chrome/browser/signin/signin_tracker.h b/chrome/browser/signin/signin_tracker.h
index c88b441..224a127 100644
--- a/chrome/browser/signin/signin_tracker.h
+++ b/chrome/browser/signin/signin_tracker.h
@@ -6,7 +6,7 @@
 #define CHROME_BROWSER_SIGNIN_SIGNIN_TRACKER_H_
 
 #include "base/memory/scoped_ptr.h"
-#include "chrome/browser/signin/signin_manager_base.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/merge_session_helper.h"
 #include "google_apis/gaia/oauth2_token_service.h"
diff --git a/chrome/browser/signin/signin_tracker_unittest.cc b/chrome/browser/signin/signin_tracker_unittest.cc
index 9df79b4..9cb3390 100644
--- a/chrome/browser/signin/signin_tracker_unittest.cc
+++ b/chrome/browser/signin/signin_tracker_unittest.cc
@@ -9,9 +9,8 @@
 #include "base/compiler_specific.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/fake_auth_status_provider.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -19,7 +18,8 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_service_mock.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -53,8 +53,9 @@
   virtual void SetUp() OVERRIDE {
     TestingProfile::Builder builder;
     builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                              FakeProfileOAuth2TokenServiceWrapper::Build);
-
+                              BuildFakeProfileOAuth2TokenService);
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              FakeSigninManagerBase::Build);
     profile_ = builder.Build();
 
     fake_oauth2_token_service_ =
@@ -62,8 +63,7 @@
             ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get()));
 
     mock_signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
-        SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-            profile_.get(), FakeSigninManagerBase::Build));
+        SigninManagerFactory::GetForProfile(profile_.get()));
 
     tracker_.reset(new SigninTracker(profile_.get(), &observer_));
   }
diff --git a/chrome/browser/signin/signin_ui_util.cc b/chrome/browser/signin/signin_ui_util.cc
index dd48625..64b5a5e 100644
--- a/chrome/browser/signin/signin_ui_util.cc
+++ b/chrome/browser/signin/signin_ui_util.cc
@@ -15,7 +15,8 @@
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/sync_global_error.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "chrome/browser/sync/sync_global_error_factory.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -39,9 +40,8 @@
 
 std::vector<GlobalError*> GetSignedInServiceErrors(Profile* profile) {
   std::vector<GlobalError*> errors;
-
-  // On Chrome OS, we don't use SigninGlobalError. Other platforms use
-  // SigninGlobalError to show sign-in errors in the toolbar menu.
+  // Chrome OS doesn't use SigninGlobalError or SyncGlobalError. Other platforms
+  // may use these services to show auth and sync errors in the toolbar menu.
 #if !defined(OS_CHROMEOS)
   // Auth errors have the highest priority - after that, individual service
   // errors.
@@ -49,18 +49,16 @@
       SigninGlobalErrorFactory::GetForProfile(profile);
   if (signin_error && signin_error->HasMenuItem())
     errors.push_back(signin_error);
-#endif
 
   // No auth error - now try other services. Currently the list is just hard-
   // coded but in the future if we add more we can create some kind of
   // registration framework.
   if (profile->IsSyncAccessible()) {
-    ProfileSyncService* service =
-        ProfileSyncServiceFactory::GetForProfile(profile);
-    SyncGlobalError* error = service->sync_global_error();
+    SyncGlobalError* error = SyncGlobalErrorFactory::GetForProfile(profile);
     if (error && error->HasMenuItem())
       errors.push_back(error);
   }
+#endif
 
   return errors;
 }
diff --git a/chrome/browser/speech/tts_linux.cc b/chrome/browser/speech/tts_linux.cc
index 4d43a8e..44946ff 100644
--- a/chrome/browser/speech/tts_linux.cc
+++ b/chrome/browser/speech/tts_linux.cc
@@ -6,11 +6,13 @@
 
 #include <map>
 
+#include "base/command_line.h"
 #include "base/debug/leak_annotations.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
 #include "base/synchronization/lock.h"
 #include "chrome/browser/speech/tts_platform.h"
+#include "chrome/common/chrome_switches.h"
 #include "content/public/browser/browser_thread.h"
 
 #include "library_loaders/libspeechd.h"
@@ -93,6 +95,10 @@
 
 TtsPlatformImplLinux::TtsPlatformImplLinux()
     : utterance_id_(0) {
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  if (!command_line.HasSwitch(switches::kEnableSpeechDispatcher))
+    return;
+
   BrowserThread::PostTask(BrowserThread::FILE,
                           FROM_HERE,
                           base::Bind(&TtsPlatformImplLinux::Initialize,
diff --git a/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc b/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc
index 4766ac7..b4eb556 100644
--- a/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc
+++ b/chrome/browser/spellchecker/spellcheck_message_filter_mac.cc
@@ -103,7 +103,8 @@
   document_tag_ = document_tag;
   markers_ = markers;
 
-  // Send the remote query out.
+  // Send the remote query out. The barrier owns |this|, ensuring it is deleted
+  // after completion.
   completion_barrier_ =
       BarrierClosure(2,
                      base::Bind(&SpellingRequest::OnCheckCompleted,
@@ -155,6 +156,7 @@
   destination_->Release();
 
   // Object is self-managed - at this point, its life span is over.
+  // No need to delete, since the OnCheckCompleted callback owns |this|.
 }
 
 void SpellingRequest::OnRemoteCheckCompleted(
diff --git a/chrome/browser/spellchecker/spelling_service_client.cc b/chrome/browser/spellchecker/spelling_service_client.cc
index 8ef8bcf..a0506ba 100644
--- a/chrome/browser/spellchecker/spelling_service_client.cc
+++ b/chrome/browser/spellchecker/spelling_service_client.cc
@@ -254,8 +254,11 @@
     fetcher->GetResponseAsString(&data);
     success = ParseResponse(data, &results);
   }
-  callback_data->callback.Run(success, callback_data->text, results);
   spellcheck_fetchers_.erase(fetcher.get());
+
+  // The callback may release the last (transitive) dependency on |this|. It
+  // MUST be the last function called.
+  callback_data->callback.Run(success, callback_data->text, results);
 }
 
 net::URLFetcher* SpellingServiceClient::CreateURLFetcher(const GURL& url) {
diff --git a/chrome/browser/ssl/ssl_blocking_page.cc b/chrome/browser/ssl/ssl_blocking_page.cc
index fcab016..4f5a119 100644
--- a/chrome/browser/ssl/ssl_blocking_page.cc
+++ b/chrome/browser/ssl/ssl_blocking_page.cc
@@ -517,6 +517,10 @@
     const content::NotificationSource& source,
     const content::NotificationDetails& details) {
 #if defined(ENABLE_CAPTIVE_PORTAL_DETECTION)
+  // When detection is disabled, captive portal service always sends
+  // RESULT_INTERNET_CONNECTED. Ignore any probe results in that case.
+  if (!captive_portal_detection_enabled_)
+    return;
   if (type == chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT) {
     captive_portal_probe_completed_ = true;
     captive_portal::CaptivePortalService::Results* results =
diff --git a/chrome/browser/ssl/ssl_browser_tests.cc b/chrome/browser/ssl/ssl_browser_tests.cc
index 964191c..4993bb5 100644
--- a/chrome/browser/ssl/ssl_browser_tests.cc
+++ b/chrome/browser/ssl/ssl_browser_tests.cc
@@ -92,6 +92,76 @@
   bool seen_;
 };
 
+namespace AuthState {
+
+enum AuthStateFlags {
+  NONE = 0,
+  DISPLAYED_INSECURE_CONTENT = 1 << 0,
+  RAN_INSECURE_CONTENT = 1 << 1,
+  SHOWING_INTERSTITIAL = 1 << 2
+};
+
+void Check(const NavigationEntry& entry, int expected_authentication_state) {
+  EXPECT_EQ(!!(expected_authentication_state & AuthState::SHOWING_INTERSTITIAL)
+                ? content::PAGE_TYPE_INTERSTITIAL
+                : content::PAGE_TYPE_NORMAL,
+            entry.GetPageType());
+
+  bool displayed_insecure_content =
+      !!(entry.GetSSL().content_status & SSLStatus::DISPLAYED_INSECURE_CONTENT);
+  EXPECT_EQ(
+      !!(expected_authentication_state & AuthState::DISPLAYED_INSECURE_CONTENT),
+      displayed_insecure_content);
+
+  bool ran_insecure_content =
+      !!(entry.GetSSL().content_status & SSLStatus::RAN_INSECURE_CONTENT);
+  EXPECT_EQ(!!(expected_authentication_state & AuthState::RAN_INSECURE_CONTENT),
+            ran_insecure_content);
+}
+
+}  // namespace AuthState
+
+namespace SecurityStyle {
+
+void Check(const NavigationEntry& entry,
+           content::SecurityStyle expected_security_style) {
+  EXPECT_EQ(expected_security_style, entry.GetSSL().security_style);
+}
+
+}  // namespace SecurityStyle
+
+namespace CertError {
+
+enum CertErrorFlags {
+  NONE = 0
+};
+
+void Check(const NavigationEntry& entry, net::CertStatus error) {
+  if (error) {
+    EXPECT_EQ(error, entry.GetSSL().cert_status & error);
+    net::CertStatus extra_cert_errors =
+        error ^ (entry.GetSSL().cert_status & net::CERT_STATUS_ALL_ERRORS);
+    if (extra_cert_errors)
+      LOG(WARNING) << "Got unexpected cert error: " << extra_cert_errors;
+  } else {
+    EXPECT_EQ(0U, entry.GetSSL().cert_status & net::CERT_STATUS_ALL_ERRORS);
+  }
+}
+
+}  // namespace CertError
+
+void CheckSecurityState(WebContents* tab,
+                        net::CertStatus error,
+                        content::SecurityStyle expected_security_style,
+                        int expected_authentication_state) {
+  ASSERT_FALSE(tab->IsCrashed());
+  NavigationEntry* entry = tab->GetController().GetActiveEntry();
+  ASSERT_TRUE(entry);
+  CertError::Check(*entry, error);
+  SecurityStyle::Check(*entry, expected_security_style);
+  AuthState::Check(*entry, expected_authentication_state);
+}
+
 }  // namespace
 
 class SSLUITest : public InProcessBrowserTest {
@@ -118,62 +188,31 @@
     command_line->AppendSwitch(switches::kProcessPerSite);
   }
 
-  void CheckState(WebContents* tab,
-                  content::SecurityStyle expected_security_style,
-                  bool expected_displayed_insecure_content,
-                  bool expected_ran_insecure_content) {
-    ASSERT_FALSE(tab->IsCrashed());
-    NavigationEntry* entry = tab->GetController().GetActiveEntry();
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(content::PAGE_TYPE_NORMAL, entry->GetPageType());
-    EXPECT_EQ(expected_security_style, entry->GetSSL().security_style);
-    EXPECT_EQ(0U, entry->GetSSL().cert_status & net::CERT_STATUS_ALL_ERRORS);
-    bool displayed_insecure_content =
-        entry->GetSSL().content_status & SSLStatus::DISPLAYED_INSECURE_CONTENT;
-    EXPECT_EQ(expected_displayed_insecure_content, displayed_insecure_content);
-    bool ran_insecure_content =
-        entry->GetSSL().content_status & SSLStatus::RAN_INSECURE_CONTENT;
-    EXPECT_EQ(expected_ran_insecure_content, ran_insecure_content);
-  }
-
   void CheckAuthenticatedState(WebContents* tab,
-                               bool expected_displayed_insecure_content) {
-    CheckState(tab, content::SECURITY_STYLE_AUTHENTICATED,
-               expected_displayed_insecure_content, false);
+                               int expected_authentication_state) {
+    CheckSecurityState(tab,
+                       CertError::NONE,
+                       content::SECURITY_STYLE_AUTHENTICATED,
+                       expected_authentication_state);
   }
 
   void CheckUnauthenticatedState(WebContents* tab) {
-    CheckState(tab, content::SECURITY_STYLE_UNAUTHENTICATED, false, false);
-  }
-
-  void CheckBrokenAuthenticatedState(WebContents* tab) {
-    CheckState(tab, content::SECURITY_STYLE_AUTHENTICATION_BROKEN, false, true);
+    CheckSecurityState(tab,
+                       CertError::NONE,
+                       content::SECURITY_STYLE_UNAUTHENTICATED,
+                       AuthState::NONE);
   }
 
   void CheckAuthenticationBrokenState(WebContents* tab,
                                       net::CertStatus error,
-                                      bool ran_insecure_content,
-                                      bool interstitial) {
-    ASSERT_FALSE(tab->IsCrashed());
-    NavigationEntry* entry = tab->GetController().GetActiveEntry();
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(interstitial ?
-                  content::PAGE_TYPE_INTERSTITIAL : content::PAGE_TYPE_NORMAL,
-              entry->GetPageType());
-    EXPECT_EQ(content::SECURITY_STYLE_AUTHENTICATION_BROKEN,
-              entry->GetSSL().security_style);
+                                      int expected_authentication_state) {
+    CheckSecurityState(tab,
+                       error,
+                       content::SECURITY_STYLE_AUTHENTICATION_BROKEN,
+                       expected_authentication_state);
     // CERT_STATUS_UNABLE_TO_CHECK_REVOCATION doesn't lower the security style
     // to SECURITY_STYLE_AUTHENTICATION_BROKEN.
     ASSERT_NE(net::CERT_STATUS_UNABLE_TO_CHECK_REVOCATION, error);
-    EXPECT_EQ(error, entry->GetSSL().cert_status & error);
-    EXPECT_FALSE(!!(entry->GetSSL().content_status &
-                    SSLStatus::DISPLAYED_INSECURE_CONTENT));
-    EXPECT_EQ(ran_insecure_content,
-        !!(entry->GetSSL().content_status & SSLStatus::RAN_INSECURE_CONTENT));
-    net::CertStatus extra_cert_errors = error ^ (entry->GetSSL().cert_status &
-                                                 net::CERT_STATUS_ALL_ERRORS);
-    if (extra_cert_errors)
-      LOG(WARNING) << "Got unexpected cert error: " << extra_cert_errors;
   }
 
   void CheckWorkerLoadResult(WebContents* tab, bool expected_load) {
@@ -365,6 +404,30 @@
       browser()->tab_strip_model()->GetActiveWebContents());
 }
 
+IN_PROC_BROWSER_TEST_F(SSLUITest, TestBrokenHTTPSWithInsecureContent) {
+  ASSERT_TRUE(test_server()->Start());
+  ASSERT_TRUE(https_server_expired_.Start());
+
+  std::string replacement_path;
+  ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
+      "files/ssl/page_displays_insecure_content.html",
+      test_server()->host_port_pair(),
+      &replacement_path));
+
+  ui_test_utils::NavigateToURL(browser(),
+                               https_server_expired_.GetURL(replacement_path));
+
+  WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
+
+  ProceedThroughInterstitial(tab);
+
+  CheckAuthenticationBrokenState(tab,
+                                 net::CERT_STATUS_DATE_INVALID,
+                                 AuthState::DISPLAYED_INSECURE_CONTENT);
+}
+
 // http://crbug.com/91745
 #if defined(OS_CHROMEOS)
 #define MAYBE_TestOKHTTPS DISABLED_TestOKHTTPS
@@ -379,8 +442,8 @@
   ui_test_utils::NavigateToURL(browser(),
                                https_server_.GetURL("files/ssl/google.html"));
 
-  CheckAuthenticatedState(
-      browser()->tab_strip_model()->GetActiveWebContents(), false);
+  CheckAuthenticatedState(browser()->tab_strip_model()->GetActiveWebContents(),
+                          AuthState::NONE);
 }
 
 // Visits a page with https error and proceed:
@@ -391,13 +454,13 @@
       https_server_expired_.GetURL("files/ssl/google.html"));
 
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   ProceedThroughInterstitial(tab);
 
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 false);  // No interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
 }
 
 #ifndef NEDBUG
@@ -438,8 +501,9 @@
   ui_test_utils::NavigateToURL(browser(), cross_site_url);
 
   // An interstitial should be showing.
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
-                                 false, true);
+  CheckAuthenticationBrokenState(tab,
+                                 net::CERT_STATUS_COMMON_NAME_INVALID,
+                                 AuthState::SHOWING_INTERSTITIAL);
 
   // Simulate user clicking "Take me back".
   InterstitialPage* interstitial_page = tab->GetInterstitialPage();
@@ -447,7 +511,7 @@
   interstitial_page->DontProceed();
 
   // We should be back to the original good page.
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // Try to navigate to a new page. (to make sure bug 5800 is fixed).
   ui_test_utils::NavigateToURL(browser(),
@@ -471,8 +535,8 @@
   // Now go to a bad HTTPS page that shows an interstitial.
   ui_test_utils::NavigateToURL(browser(),
       https_server_expired_.GetURL("files/ssl/google.html"));
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   ProvisionalLoadWaiter load_failed_observer(tab);
 
@@ -508,8 +572,8 @@
   // Now go to a bad HTTPS page that shows an interstitial.
   ui_test_utils::NavigateToURL(browser(),
       https_server_expired_.GetURL("files/ssl/google.html"));
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   // Simulate user clicking and holding on back button (crbug.com/37215).
   tab->GetController().GoToOffset(-1);
@@ -551,8 +615,8 @@
   // Now go to a bad HTTPS page that shows an interstitial.
   ui_test_utils::NavigateToURL(browser(),
       https_server_expired_.GetURL("files/ssl/google.html"));
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   // Simulate user clicking and holding on forward button.
   {
@@ -641,8 +705,8 @@
       browser(),
       wss_server_expired_.GetURL(
           "connect_check.html").ReplaceComponents(replacements));
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   // Proceed anyway.
   ProceedThroughInterstitial(tab);
@@ -714,7 +778,7 @@
 
   // Visit a HTTPS page which requires client certs.
   ui_test_utils::NavigateToURL(browser(), url);
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // Test page runs a WebSocket wss connection test. The result will be shown
   // as page title.
@@ -837,8 +901,8 @@
   ui_test_utils::NavigateToURL(browser(),
                                https_server_.GetURL(replacement_path));
 
-  CheckAuthenticatedState(
-      browser()->tab_strip_model()->GetActiveWebContents(), true);
+  CheckAuthenticatedState(browser()->tab_strip_model()->GetActiveWebContents(),
+                          AuthState::DISPLAYED_INSECURE_CONTENT);
 }
 
 // Visits a page that runs insecure content and tries to suppress the insecure
@@ -853,7 +917,9 @@
       "files/ssl/page_runs_insecure_content.html"));
 
   CheckAuthenticationBrokenState(
-      browser()->tab_strip_model()->GetActiveWebContents(), 0, true, false);
+      browser()->tab_strip_model()->GetActiveWebContents(),
+      CertError::NONE,
+      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
 }
 
 // Visits a page with unsafe content and make sure that:
@@ -874,7 +940,7 @@
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
   // When the bad content is filtered, the state is expected to be
   // authenticated.
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // Because of cross-frame scripting restrictions, we cannot access the iframe
   // content.  So to know if the frame was loaded, we just check if a popup was
@@ -916,7 +982,7 @@
       replacement_path));
 
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // Load the insecure image.
   bool js_result = false;
@@ -927,7 +993,7 @@
   EXPECT_TRUE(js_result);
 
   // We should now have insecure content.
-  CheckAuthenticatedState(tab, true);
+  CheckAuthenticatedState(tab, AuthState::DISPLAYED_INSECURE_CONTENT);
 }
 
 // Visits two pages from the same origin: one that displays insecure content and
@@ -943,7 +1009,7 @@
   WebContents* tab1 = browser()->tab_strip_model()->GetActiveWebContents();
 
   // This tab should be fine.
-  CheckAuthenticatedState(tab1, false);
+  CheckAuthenticatedState(tab1, AuthState::NONE);
 
   // Create a new tab.
   std::string replacement_path;
@@ -965,10 +1031,10 @@
   observer.Wait();
 
   // The new tab has insecure content.
-  CheckAuthenticatedState(tab2, true);
+  CheckAuthenticatedState(tab2, AuthState::DISPLAYED_INSECURE_CONTENT);
 
   // The original tab should not be contaminated.
-  CheckAuthenticatedState(tab1, false);
+  CheckAuthenticatedState(tab1, AuthState::NONE);
 }
 
 // Visits two pages from the same origin: one that runs insecure content and one
@@ -984,7 +1050,7 @@
   WebContents* tab1 = browser()->tab_strip_model()->GetActiveWebContents();
 
   // This tab should be fine.
-  CheckAuthenticatedState(tab1, false);
+  CheckAuthenticatedState(tab1, AuthState::NONE);
 
   std::string replacement_path;
   ASSERT_TRUE(GetFilePathWithHostAndPortReplacement(
@@ -1010,11 +1076,15 @@
   EXPECT_EQ(tab1->GetRenderProcessHost(), tab2->GetRenderProcessHost());
 
   // The new tab has insecure content.
-  CheckAuthenticationBrokenState(tab2, 0, true, false);
+  CheckAuthenticationBrokenState(
+      tab2,
+      CertError::NONE,
+      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
 
   // Which means the origin for the first tab has also been contaminated with
   // insecure content.
-  CheckAuthenticationBrokenState(tab1, 0, true, false);
+  CheckAuthenticationBrokenState(
+      tab1, CertError::NONE, AuthState::RAN_INSECURE_CONTENT);
 }
 
 // Visits a page with an image over http.  Visits another page over https
@@ -1040,7 +1110,7 @@
   // content (even though the image comes from the WebCore memory cache).
   const GURL url_https = https_server_.GetURL(replacement_path);
   ui_test_utils::NavigateToURL(browser(), url_https);
-  CheckAuthenticatedState(tab, true);
+  CheckAuthenticatedState(tab, AuthState::DISPLAYED_INSECURE_CONTENT);
 }
 
 // http://crbug.com/84729
@@ -1074,7 +1144,10 @@
   // content (even though the image comes from the WebCore memory cache).
   const GURL url_https = https_server_.GetURL(replacement_path);
   ui_test_utils::NavigateToURL(browser(), url_https);
-  CheckAuthenticationBrokenState(tab, 0, true, false);
+  CheckAuthenticationBrokenState(
+      tab,
+      CertError::NONE,
+      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
 }
 
 // This test ensures the CN invalid status does not 'stick' to a certificate
@@ -1090,26 +1163,27 @@
 
   // We get an interstitial page as a result.
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
-                                 false, true);  // Interstitial showing.
+  CheckAuthenticationBrokenState(tab,
+                                 net::CERT_STATUS_COMMON_NAME_INVALID,
+                                 AuthState::SHOWING_INTERSTITIAL);
   ProceedThroughInterstitial(tab);
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
-                                 false, false);  // No interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_COMMON_NAME_INVALID, AuthState::NONE);
 
   // Now we try again with the right host name this time.
   GURL url(https_server_.GetURL("files/ssl/google.html"));
   ui_test_utils::NavigateToURL(browser(), url);
 
   // Security state should be OK.
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // Now try again the broken one to make sure it is still broken.
   ui_test_utils::NavigateToURL(browser(),
       https_server_mismatched_.GetURL("files/ssl/google.html"));
 
   // Since we OKed the interstitial last time, we get right to the page.
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_COMMON_NAME_INVALID,
-                                 false, false);  // No interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_COMMON_NAME_INVALID, AuthState::NONE);
 }
 
 #if defined(OS_CHROMEOS)
@@ -1128,21 +1202,20 @@
       https_server_expired_.GetURL("files/ssl/page_with_refs.html"));
 
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   ProceedThroughInterstitial(tab);
 
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 false);  // No interstitial showing.
-
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
   // Now navigate to a ref in the page, the security state should not have
   // changed.
   ui_test_utils::NavigateToURL(browser(),
       https_server_expired_.GetURL("files/ssl/page_with_refs.html#jp"));
 
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 false);  // No interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
 }
 
 // Tests that closing a page that has a unsafe pop-up does not crash the
@@ -1201,13 +1274,13 @@
 
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
 
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   ProceedThroughInterstitial(tab);
 
   // We have been redirected to the good page.
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 }
 
 // Visit a page over good https that is a redirect to a page with bad https.
@@ -1220,13 +1293,13 @@
   ui_test_utils::NavigateToURL(browser(), GURL(url1.spec() + url2.spec()));
 
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   ProceedThroughInterstitial(tab);
 
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 false);  // No interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
 }
 
 // Visit a page over http that is a redirect to a page with good HTTPS.
@@ -1243,7 +1316,7 @@
 
   ui_test_utils::NavigateToURL(browser(),
                                GURL(http_url.spec() + good_https_url.spec()));
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 }
 
 // Visit a page over http that is a redirect to a page with bad HTTPS.
@@ -1258,13 +1331,13 @@
       https_server_expired_.GetURL("files/ssl/google.html");
   ui_test_utils::NavigateToURL(browser(),
                                GURL(http_url.spec() + bad_https_url.spec()));
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   ProceedThroughInterstitial(tab);
 
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 false);  // No interstitial showing.
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
 }
 
 // Visit a page over https that is a redirect to a page with http (to make sure
@@ -1319,7 +1392,7 @@
   ui_test_utils::NavigateToURL(browser(),
                                https_server_.GetURL(top_frame_path));
 
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   bool success = false;
   // Now navigate inside the frame.
@@ -1336,7 +1409,7 @@
   }
 
   // We should still be fine.
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // Now let's hit a bad page.
   {
@@ -1352,7 +1425,7 @@
   }
 
   // The security style should still be secure.
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // And the frame should be blocked.
   bool is_content_evil = true;
@@ -1373,7 +1446,7 @@
     tab->GetController().GoBack();
     observer.Wait();
   }
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 
   // Navigate to a page served over HTTP.
   {
@@ -1389,7 +1462,10 @@
   }
 
   // Our state should be unathenticated (in the ran mixed script sense)
-  CheckBrokenAuthenticatedState(tab);
+  CheckAuthenticationBrokenState(
+      tab,
+      CertError::NONE,
+      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
 
   // Go back, our state should be unchanged.
   {
@@ -1400,7 +1476,10 @@
     observer.Wait();
   }
 
-  CheckBrokenAuthenticatedState(tab);
+  CheckAuthenticationBrokenState(
+      tab,
+      CertError::NONE,
+      AuthState::DISPLAYED_INSECURE_CONTENT | AuthState::RAN_INSECURE_CONTENT);
 }
 
 // From a bad HTTPS top frame:
@@ -1418,8 +1497,8 @@
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
   ui_test_utils::NavigateToURL(browser(),
                                https_server_expired_.GetURL(top_frame_path));
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   ProceedThroughInterstitial(tab);
 
@@ -1436,8 +1515,8 @@
   observer.Wait();
 
   // We should still be authentication broken.
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 false);
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
 }
 
 // From an HTTP top frame, navigate to good and bad HTTPS (security state should
@@ -1520,7 +1599,7 @@
   // Expect Worker not to load insecure content.
   CheckWorkerLoadResult(tab, false);
   // The bad content is filtered, expect the state to be authenticated.
-  CheckAuthenticatedState(tab, false);
+  CheckAuthenticatedState(tab, AuthState::NONE);
 }
 
 IN_PROC_BROWSER_TEST_F(SSLUITest, TestUnsafeContentsInWorker) {
@@ -1532,11 +1611,11 @@
   ui_test_utils::NavigateToURL(browser(),
       https_server_expired_.GetURL("files/ssl/blank_page.html"));
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
   ProceedThroughInterstitial(tab);
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 false);  // No Interstitial
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::NONE);
 
   // Navigate to safe page that has Worker loading unsafe content.
   // Expect content to load but be marked as auth broken due to running insecure
@@ -1547,7 +1626,8 @@
   ui_test_utils::NavigateToURL(browser(), https_server_.GetURL(
       page_with_unsafe_worker_path));
   CheckWorkerLoadResult(tab, true);  // Worker loads insecure content
-  CheckAuthenticationBrokenState(tab, 0, true, false);
+  CheckAuthenticationBrokenState(
+      tab, CertError::NONE, AuthState::RAN_INSECURE_CONTENT);
 }
 
 // Test that when the browser blocks displaying insecure content (images), the
@@ -1566,8 +1646,8 @@
   ui_test_utils::NavigateToURL(browser(),
                                https_server_.GetURL(replacement_path));
 
-  CheckAuthenticatedState(
-      browser()->tab_strip_model()->GetActiveWebContents(), false);
+  CheckAuthenticatedState(browser()->tab_strip_model()->GetActiveWebContents(),
+                          AuthState::NONE);
 }
 
 // Test that when the browser blocks displaying insecure content (iframes), the
@@ -1586,11 +1666,10 @@
   ui_test_utils::NavigateToURL(browser(),
                                https_server_.GetURL(replacement_path));
 
-  CheckAuthenticatedState(
-      browser()->tab_strip_model()->GetActiveWebContents(), false);
+  CheckAuthenticatedState(browser()->tab_strip_model()->GetActiveWebContents(),
+                          AuthState::NONE);
 }
 
-
 // Test that when the browser blocks running insecure content, the
 // indicator shows a secure page, because the blocking made the otherwise
 // unsafe page safe (the notification of this state is handled by other means).
@@ -1607,8 +1686,8 @@
   ui_test_utils::NavigateToURL(browser(),
                                https_server_.GetURL(replacement_path));
 
-  CheckAuthenticatedState(
-      browser()->tab_strip_model()->GetActiveWebContents(), false);
+  CheckAuthenticatedState(browser()->tab_strip_model()->GetActiveWebContents(),
+                          AuthState::NONE);
 }
 
 // Visit a page and establish a WebSocket connection over bad https with
@@ -1650,8 +1729,8 @@
   WebContents* tab = browser()->tab_strip_model()->GetActiveWebContents();
   ui_test_utils::NavigateToURL(browser(),
       https_server_expired_.GetURL("files/ssl/google.html"));
-  CheckAuthenticationBrokenState(tab, net::CERT_STATUS_DATE_INVALID, false,
-                                 true);  // Interstitial showing
+  CheckAuthenticationBrokenState(
+      tab, net::CERT_STATUS_DATE_INVALID, AuthState::SHOWING_INTERSTITIAL);
 
   InterstitialPage* interstitial_page = tab->GetInterstitialPage();
   content::RenderViewHost* interstitial_rvh =
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index 0ace414..a2861ef 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -192,6 +192,9 @@
   // Fetches the DeviceInfo tracker.
   virtual SyncedDeviceTracker* GetSyncedDeviceTracker() const = 0;
 
+  // Sets whether or not the frontend will be notified of network events.
+  virtual void SetForwardProtocolEvents(bool forward) = 0;
+
   virtual base::MessageLoop* GetSyncLoopForTesting() = 0;
 
   DISALLOW_COPY_AND_ASSIGN(SyncBackendHost);
diff --git a/chrome/browser/sync/glue/sync_backend_host_core.cc b/chrome/browser/sync/glue/sync_backend_host_core.cc
index b6249c9..c433b0b 100644
--- a/chrome/browser/sync/glue/sync_backend_host_core.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_core.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/sync/glue/synced_device_tracker.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
+#include "sync/internal_api/public/events/protocol_event.h"
 #include "sync/internal_api/public/http_post_provider_factory.h"
 #include "sync/internal_api/public/internal_components_factory.h"
 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
@@ -316,6 +317,18 @@
       types);
 }
 
+void SyncBackendHostCore::OnProtocolEvent(
+    const syncer::ProtocolEvent& event) {
+  // TODO(rlarocque): Find a way to pass event_clone as a scoped_ptr.
+  if (forward_protocol_events_) {
+    scoped_ptr<syncer::ProtocolEvent> event_clone(event.Clone());
+    host_.Call(
+        FROM_HERE,
+        &SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop,
+        event_clone.release());
+  }
+}
+
 void SyncBackendHostCore::DoOnInvalidatorStateChange(
     syncer::InvalidatorState state) {
   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
@@ -592,6 +605,11 @@
              retry_callback);
 }
 
+void SyncBackendHostCore::SetForwardProtocolEvents(bool enabled) {
+  DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
+  forward_protocol_events_ = enabled;
+}
+
 void SyncBackendHostCore::DeleteSyncDataFolder() {
   DCHECK_EQ(base::MessageLoop::current(), sync_loop_);
   if (base::DirectoryExists(sync_data_folder_path_)) {
diff --git a/chrome/browser/sync/glue/sync_backend_host_core.h b/chrome/browser/sync/glue/sync_backend_host_core.h
index d0b9793..d246255 100644
--- a/chrome/browser/sync/glue/sync_backend_host_core.h
+++ b/chrome/browser/sync/glue/sync_backend_host_core.h
@@ -102,6 +102,7 @@
   virtual void OnActionableError(
       const syncer::SyncProtocolError& sync_error) OVERRIDE;
   virtual void OnMigrationRequested(syncer::ModelTypeSet types) OVERRIDE;
+  virtual void OnProtocolEvent(const syncer::ProtocolEvent& event) OVERRIDE;
 
   // SyncEncryptionHandler::Observer implementation.
   virtual void OnPassphraseRequired(
@@ -208,6 +209,8 @@
     return synced_device_tracker_.get();
   }
 
+  void SetForwardProtocolEvents(bool forward);
+
   // Delete the sync data folder to cleanup backend data.  Happens the first
   // time sync is enabled for a user (to prevent accidentally reusing old
   // sync databases), as well as shutdown when you're no longer syncing.
@@ -285,6 +288,9 @@
   // Should not be used for anything except for UMAs and logging.
   const bool has_sync_setup_completed_;
 
+  // Set when we've been asked to forward sync protocol events to the frontend.
+  bool forward_protocol_events_;
+
   base::WeakPtrFactory<SyncBackendHostCore> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncBackendHostCore);
diff --git a/chrome/browser/sync/glue/sync_backend_host_impl.cc b/chrome/browser/sync/glue/sync_backend_host_impl.cc
index f5b2f6e..de87a49 100644
--- a/chrome/browser/sync/glue/sync_backend_host_impl.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_impl.cc
@@ -19,6 +19,7 @@
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
 #include "sync/internal_api/public/base_transaction.h"
+#include "sync/internal_api/public/events/protocol_event.h"
 #include "sync/internal_api/public/http_bridge.h"
 #include "sync/internal_api/public/internal_components_factory.h"
 #include "sync/internal_api/public/internal_components_factory_impl.h"
@@ -474,6 +475,14 @@
   return core_->synced_device_tracker();
 }
 
+void SyncBackendHostImpl::SetForwardProtocolEvents(bool forward) {
+  DCHECK(initialized());
+  registrar_->sync_thread()->message_loop()->PostTask(
+      FROM_HERE,
+      base::Bind(&SyncBackendHostCore::SetForwardProtocolEvents,
+                 core_, forward));
+}
+
 void SyncBackendHostImpl::InitCore(scoped_ptr<DoInitializeOptions> options) {
   registrar_->sync_thread()->message_loop()->PostTask(FROM_HERE,
       base::Bind(&SyncBackendHostCore::DoInitialize,
@@ -744,6 +753,14 @@
   frontend_->OnConnectionStatusChange(status);
 }
 
+void SyncBackendHostImpl::HandleProtocolEventOnFrontendLoop(
+    syncer::ProtocolEvent* event) {
+  scoped_ptr<syncer::ProtocolEvent> scoped_event(event);
+  if (!frontend_)
+    return;
+  frontend_->OnProtocolEvent(*scoped_event);
+}
+
 base::MessageLoop* SyncBackendHostImpl::GetSyncLoopForTesting() {
   return registrar_->sync_thread()->message_loop();
 }
diff --git a/chrome/browser/sync/glue/sync_backend_host_impl.h b/chrome/browser/sync/glue/sync_backend_host_impl.h
index b2ed962..24e6215 100644
--- a/chrome/browser/sync/glue/sync_backend_host_impl.h
+++ b/chrome/browser/sync/glue/sync_backend_host_impl.h
@@ -124,6 +124,7 @@
   virtual void GetModelSafeRoutingInfo(
       syncer::ModelSafeRoutingInfo* out) const OVERRIDE;
   virtual SyncedDeviceTracker* GetSyncedDeviceTracker() const OVERRIDE;
+  virtual void SetForwardProtocolEvents(bool forward) OVERRIDE;
   virtual base::MessageLoop* GetSyncLoopForTesting() OVERRIDE;
 
  protected:
@@ -166,6 +167,11 @@
   // frontend's sync configure retry method.
   void HandleControlTypesDownloadRetry();
 
+  // Forwards a ProtocolEvent to the frontend.  Will not be called unless a
+  // call to SetForwardProtocolEvents() explicitly requested that we start
+  // forwarding these events.
+  void HandleProtocolEventOnFrontendLoop(syncer::ProtocolEvent* event);
+
   SyncFrontend* frontend() { return frontend_; }
 
  private:
diff --git a/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc
index 62553d1..add3e2c 100644
--- a/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_impl_unittest.cc
@@ -82,6 +82,7 @@
                void(syncer::ModelTypeSet, bool));
   MOCK_METHOD0(OnEncryptionComplete, void());
   MOCK_METHOD1(OnMigrationNeededForTypes, void(syncer::ModelTypeSet));
+  MOCK_METHOD1(OnProtocolEvent, void(const syncer::ProtocolEvent&));
   MOCK_METHOD1(OnExperimentsChanged,
       void(const syncer::Experiments&));
   MOCK_METHOD1(OnActionableError,
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.cc b/chrome/browser/sync/glue/sync_backend_host_mock.cc
index 7f21935..f7629b2 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_mock.cc
@@ -110,6 +110,8 @@
   return NULL;
 }
 
+void SyncBackendHostMock::SetForwardProtocolEvents(bool enabled) {}
+
 void SyncBackendHostMock::set_fail_initial_download(bool should_fail) {
   fail_initial_download_ = should_fail;
 }
diff --git a/chrome/browser/sync/glue/sync_backend_host_mock.h b/chrome/browser/sync/glue/sync_backend_host_mock.h
index fb90c2b..b75a087 100644
--- a/chrome/browser/sync/glue/sync_backend_host_mock.h
+++ b/chrome/browser/sync/glue/sync_backend_host_mock.h
@@ -93,6 +93,8 @@
 
   virtual SyncedDeviceTracker* GetSyncedDeviceTracker() const OVERRIDE;
 
+  virtual void SetForwardProtocolEvents(bool enabled) OVERRIDE;
+
   virtual base::MessageLoop* GetSyncLoopForTesting() OVERRIDE;
 
   void set_fail_initial_download(bool should_fail);
diff --git a/chrome/browser/sync/managed_user_signin_manager_wrapper.cc b/chrome/browser/sync/managed_user_signin_manager_wrapper.cc
new file mode 100644
index 0000000..5fa2e17
--- /dev/null
+++ b/chrome/browser/sync/managed_user_signin_manager_wrapper.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "components/signin/core/browser/signin_manager_base.h"
+
+#if defined(ENABLE_MANAGED_USERS)
+#include "chrome/browser/managed_mode/managed_user_constants.h"
+#endif
+
+ManagedUserSigninManagerWrapper::ManagedUserSigninManagerWrapper(
+    Profile* profile,
+    SigninManagerBase* original)
+    : profile_(profile), original_(original) {}
+
+ManagedUserSigninManagerWrapper::~ManagedUserSigninManagerWrapper() {
+}
+
+SigninManagerBase* ManagedUserSigninManagerWrapper::GetOriginal() {
+  return original_;
+}
+
+std::string ManagedUserSigninManagerWrapper::GetEffectiveUsername() const {
+  if (profile_->IsManaged()) {
+#if defined(ENABLE_MANAGED_USERS)
+    DCHECK_EQ(std::string(), original_->GetAuthenticatedUsername());
+    return managed_users::kManagedUserPseudoEmail;
+#else
+    NOTREACHED();
+#endif
+  }
+
+  return original_->GetAuthenticatedUsername();
+}
+
+std::string ManagedUserSigninManagerWrapper::GetAccountIdToUse() const {
+  if (profile_->IsManaged()) {
+#if defined(ENABLE_MANAGED_USERS)
+    return managed_users::kManagedUserPseudoEmail;
+#else
+    NOTREACHED();
+#endif
+  }
+
+  return original_->GetAuthenticatedAccountId();
+}
diff --git a/chrome/browser/sync/managed_user_signin_manager_wrapper.h b/chrome/browser/sync/managed_user_signin_manager_wrapper.h
new file mode 100644
index 0000000..507754d
--- /dev/null
+++ b/chrome/browser/sync/managed_user_signin_manager_wrapper.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_MANAGED_USER_SIGNIN_MANAGER_WRAPPER_H_
+#define CHROME_BROWSER_SYNC_MANAGED_USER_SIGNIN_MANAGER_WRAPPER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+class Profile;
+class SigninManagerBase;
+
+// Some chrome cloud services support managed users as well as normally
+// authenticated users that sign in through SigninManager.  To facilitate
+// getting the "effective" username and account identifiers, services can
+// use this class to wrap the SigninManager and return managed user account
+// information when appropriate.
+class ManagedUserSigninManagerWrapper {
+ public:
+  ManagedUserSigninManagerWrapper(Profile* profile,
+                                  SigninManagerBase* original);
+  virtual ~ManagedUserSigninManagerWrapper();
+
+  virtual std::string GetEffectiveUsername() const;
+  virtual std::string GetAccountIdToUse() const;
+
+  SigninManagerBase* GetOriginal();
+
+ private:
+  Profile* profile_;
+  SigninManagerBase* original_;
+  DISALLOW_COPY_AND_ASSIGN(ManagedUserSigninManagerWrapper);
+};
+
+#endif  // CHROME_BROWSER_SYNC_MANAGED_USER_SIGNIN_MANAGER_WRAPPER_H_
diff --git a/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc b/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
index 2bf3e5e..430c311 100644
--- a/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
+++ b/chrome/browser/sync/profile_sync_components_factory_impl_unittest.cc
@@ -14,7 +14,7 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/data_type_controller.h"
 #include "content/public/test/test_browser_thread.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 616c2bb..9166d4f 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -26,7 +26,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/defaults.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/net/chrome_cookie_notification_details.h"
 #include "chrome/browser/prefs/pref_service_syncable.h"
 #include "chrome/browser/profiles/profile.h"
@@ -49,10 +48,11 @@
 #include "chrome/browser/sync/glue/sync_start_util.h"
 #include "chrome/browser/sync/glue/synced_device_tracker.h"
 #include "chrome/browser/sync/glue/typed_url_data_type_controller.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/sync/profile_sync_components_factory_impl.h"
 #include "chrome/browser/sync/sessions2/notification_service_sessions_router.h"
 #include "chrome/browser/sync/sessions2/sessions_sync_manager.h"
-#include "chrome/browser/sync/sync_global_error.h"
+#include "chrome/browser/sync/sync_error_controller.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
@@ -62,7 +62,7 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/data_type_controller.h"
 #include "components/sync_driver/pref_names.h"
 #include "components/sync_driver/system_encryptor.h"
@@ -274,20 +274,18 @@
   last_synced_time_ = sync_prefs_.GetLastSyncedTime();
 
 #if defined(OS_CHROMEOS)
-   std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken();
-   if (bootstrap_token.empty()) {
-     sync_prefs_.SetEncryptionBootstrapToken(
-         sync_prefs_.GetSpareBootstrapToken());
-   }
+  std::string bootstrap_token = sync_prefs_.GetEncryptionBootstrapToken();
+  if (bootstrap_token.empty()) {
+    sync_prefs_.SetEncryptionBootstrapToken(
+        sync_prefs_.GetSpareBootstrapToken());
+  }
 #endif
 
 #if !defined(OS_ANDROID)
-   if (!sync_global_error_) {
-     sync_global_error_.reset(new SyncGlobalError(this, signin()));
-     GlobalErrorServiceFactory::GetForProfile(profile_)->AddGlobalError(
-         sync_global_error_.get());
-     AddObserver(sync_global_error_.get());
-   }
+  DCHECK(sync_error_controller_ == NULL)
+      << "Initialize() called more than once.";
+  sync_error_controller_.reset(new SyncErrorController(this));
+  AddObserver(sync_error_controller_.get());
 #endif
 
   startup_controller_.Reset(GetRegisteredDataTypes());
@@ -334,18 +332,14 @@
 
 void ProfileSyncService::RegisterAuthNotifications() {
   oauth2_token_service_->AddObserver(this);
-
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-                 content::Source<Profile>(profile_));
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
-                 content::Source<Profile>(profile_));
+  if (signin())
+    signin()->AddObserver(this);
 }
 
 void ProfileSyncService::UnregisterAuthNotifications() {
+  if (signin())
+    signin()->RemoveObserver(this);
   oauth2_token_service_->RemoveObserver(this);
-  registrar_.RemoveAll();
 }
 
 void ProfileSyncService::RegisterDataTypeController(
@@ -562,6 +556,13 @@
   NotifyObservers();
 }
 
+void ProfileSyncService::OnProtocolEvent(
+    const syncer::ProtocolEvent& event) {
+  FOR_EACH_OBSERVER(browser_sync::ProtocolEventObserver,
+                    protocol_event_observers_,
+                    OnProtocolEvent(event));
+}
+
 void ProfileSyncService::OnDataTypeRequestsSyncStartup(
     syncer::ModelType type) {
   DCHECK(syncer::UserTypes().Has(type));
@@ -701,6 +702,11 @@
   UnregisterAuthNotifications();
 
   ShutdownImpl(browser_sync::SyncBackendHost::STOP);
+  if (sync_error_controller_) {
+    // Destroy the SyncErrorController when the service shuts down for good.
+    RemoveObserver(sync_error_controller_.get());
+    sync_error_controller_.reset();
+  }
 
   if (sync_thread_)
     sync_thread_->Stop();
@@ -708,13 +714,6 @@
 
 void ProfileSyncService::ShutdownImpl(
     browser_sync::SyncBackendHost::ShutdownOption option) {
-  if (sync_global_error_) {
-    GlobalErrorServiceFactory::GetForProfile(profile_)->RemoveGlobalError(
-        sync_global_error_.get());
-    RemoveObserver(sync_global_error_.get());
-    sync_global_error_.reset(NULL);
-  }
-
   if (!backend_)
     return;
 
@@ -936,6 +935,10 @@
   sync_js_controller_.AttachJsBackend(js_backend);
   debug_info_listener_ = debug_info_listener;
 
+  if (protocol_event_observers_.might_have_observers()) {
+    backend_->SetForwardProtocolEvents(true);
+  }
+
   // If we have a cached passphrase use it to decrypt/encrypt data now that the
   // backend is initialized. We want to call this before notifying observers in
   // case this operation affects the "passphrase required" status.
@@ -1011,6 +1014,9 @@
     profile()->GetPrefs()->ClearPref(prefs::kGCMChannelEnabled);
   }
 
+  profile()->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+                                    experiments.gcm_invalidations_enabled);
+
   int bookmarks_experiment_state_before = profile_->GetPrefs()->GetInteger(
       sync_driver::prefs::kEnhancedBookmarksExperimentEnabled);
   // kEnhancedBookmarksExperiment flag could have values "", "1" and "0".
@@ -2024,40 +2030,27 @@
   }
 }
 
-void ProfileSyncService::Observe(int type,
-                                 const content::NotificationSource& source,
-                                 const content::NotificationDetails& details) {
-  switch (type) {
-    case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: {
-      const GoogleServiceSigninSuccessDetails* successful =
-          content::Details<const GoogleServiceSigninSuccessDetails>(
-              details).ptr();
-      if (!sync_prefs_.IsStartSuppressed() &&
-          !successful->password.empty()) {
-        cached_passphrase_ = successful->password;
-        // Try to consume the passphrase we just cached. If the sync backend
-        // is not running yet, the passphrase will remain cached until the
-        // backend starts up.
-        ConsumeCachedPassphraseIfPossible();
-      }
-#if defined(OS_CHROMEOS)
-      RefreshSpareBootstrapToken(successful->password);
-#endif
-      if (!sync_initialized() ||
-          GetAuthError().state() != AuthError::NONE) {
-        // Track the fact that we're still waiting for auth to complete.
-        is_auth_in_progress_ = true;
-      }
-      break;
-    }
-    case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
-      sync_disabled_by_admin_ = false;
-      DisableForUser();
-      break;
-    default: {
-      NOTREACHED();
-    }
+void ProfileSyncService::GoogleSigninSucceeded(const std::string& username,
+                                               const std::string& password) {
+  if (!sync_prefs_.IsStartSuppressed() && !password.empty()) {
+    cached_passphrase_ = password;
+    // Try to consume the passphrase we just cached. If the sync backend
+    // is not running yet, the passphrase will remain cached until the
+    // backend starts up.
+    ConsumeCachedPassphraseIfPossible();
   }
+#if defined(OS_CHROMEOS)
+  RefreshSpareBootstrapToken(password);
+#endif
+  if (!sync_initialized() || GetAuthError().state() != AuthError::NONE) {
+    // Track the fact that we're still waiting for auth to complete.
+    is_auth_in_progress_ = true;
+  }
+}
+
+void ProfileSyncService::GoogleSignedOut(const std::string& username) {
+  sync_disabled_by_admin_ = false;
+  DisableForUser();
 }
 
 void ProfileSyncService::AddObserver(
@@ -2070,6 +2063,24 @@
   observers_.RemoveObserver(observer);
 }
 
+void ProfileSyncService::AddProtocolEventObserver(
+    browser_sync::ProtocolEventObserver* observer) {
+  protocol_event_observers_.AddObserver(observer);
+  if (backend_) {
+    backend_->SetForwardProtocolEvents(
+        protocol_event_observers_.might_have_observers());
+  }
+}
+
+void ProfileSyncService::RemoveProtocolEventObserver(
+    browser_sync::ProtocolEventObserver* observer) {
+  protocol_event_observers_.RemoveObserver(observer);
+  if (backend_) {
+    backend_->SetForwardProtocolEvents(
+        protocol_event_observers_.might_have_observers());
+  }
+}
+
 bool ProfileSyncService::HasObserver(
     ProfileSyncServiceBase::Observer* observer) const {
   return observers_.HasObserver(observer);
@@ -2120,6 +2131,8 @@
 }
 
 SigninManagerBase* ProfileSyncService::signin() const {
+  if (!signin_)
+    return NULL;
   return signin_->GetOriginal();
 }
 
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 0b3c439..79b2a52 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -25,9 +25,11 @@
 #include "chrome/browser/sync/glue/synced_device_tracker.h"
 #include "chrome/browser/sync/profile_sync_service_base.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
+#include "chrome/browser/sync/protocol_event_observer.h"
 #include "chrome/browser/sync/sessions2/sessions_sync_manager.h"
 #include "chrome/browser/sync/startup_controller.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "components/sync_driver/data_type_controller.h"
 #include "components/sync_driver/data_type_encryption_handler.h"
 #include "components/sync_driver/data_type_manager.h"
@@ -35,9 +37,6 @@
 #include "components/sync_driver/failed_data_types_handler.h"
 #include "components/sync_driver/sync_frontend.h"
 #include "components/sync_driver/sync_prefs.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_types.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "net/base/backoff_entry.h"
@@ -53,8 +52,7 @@
 class Profile;
 class ProfileOAuth2TokenService;
 class ProfileSyncComponentsFactory;
-class SigninManagerBase;
-class SyncGlobalError;
+class SyncErrorController;
 
 namespace browser_sync {
 class BackendMigrator;
@@ -172,12 +170,12 @@
                            public sync_driver::SyncPrefObserver,
                            public browser_sync::DataTypeManagerObserver,
                            public syncer::UnrecoverableErrorHandler,
-                           public content::NotificationObserver,
                            public KeyedService,
                            public browser_sync::DataTypeEncryptionHandler,
                            public OAuth2TokenService::Consumer,
                            public OAuth2TokenService::Observer,
-                           public SessionsSyncManager::SyncInternalApiDelegate {
+                           public SessionsSyncManager::SyncInternalApiDelegate,
+                           public SigninManagerBase::Observer {
  public:
   typedef browser_sync::SyncBackendHost::Status Status;
 
@@ -273,6 +271,11 @@
   virtual bool HasObserver(
       ProfileSyncServiceBase::Observer* observer) const OVERRIDE;
 
+
+  void AddProtocolEventObserver(browser_sync::ProtocolEventObserver* observer);
+  void RemoveProtocolEventObserver(
+      browser_sync::ProtocolEventObserver* observer);
+
   void RegisterAuthNotifications();
   void UnregisterAuthNotifications();
 
@@ -365,6 +368,7 @@
           debug_info_listener,
       bool success) OVERRIDE;
   virtual void OnSyncCycleCompleted() OVERRIDE;
+  virtual void OnProtocolEvent(const syncer::ProtocolEvent& event) OVERRIDE;
   virtual void OnSyncConfigureRetry() OVERRIDE;
   virtual void OnConnectionStatusChange(
       syncer::ConnectionStatus status) OVERRIDE;
@@ -393,6 +397,11 @@
   virtual bool IsPassphraseRequired() const OVERRIDE;
   virtual syncer::ModelTypeSet GetEncryptedDataTypes() const OVERRIDE;
 
+  // SigninManagerBase::Observer implementation.
+  virtual void GoogleSigninSucceeded(const std::string& username,
+                                     const std::string& password) OVERRIDE;
+  virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
+
   // Called when a user chooses which data types to sync as part of the sync
   // setup wizard.  |sync_everything| represents whether they chose the
   // "keep everything synced" option; if true, |chosen_types| will be ignored
@@ -558,11 +567,6 @@
   // SyncPrefObserver implementation.
   virtual void OnSyncManagedPrefChange(bool is_sync_managed) OVERRIDE;
 
-  // content::NotificationObserver implementation.
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
   // Changes which data types we're going to be syncing to |preferred_types|.
   // If it is running, the DataTypeManager will be instructed to reconfigure
   // the sync backend so that exactly these datatypes are actively synced.  See
@@ -649,7 +653,9 @@
   // the user about them any more.
   void AcknowledgeSyncedTypes();
 
-  SyncGlobalError* sync_global_error() { return sync_global_error_.get(); }
+  SyncErrorController* sync_error_controller() {
+    return sync_error_controller_.get();
+  }
 
   // TODO(sync): This is only used in tests.  Can we remove it?
   const browser_sync::FailedDataTypesHandler& failed_data_types_handler() const;
@@ -911,11 +917,10 @@
   scoped_ptr<browser_sync::DataTypeManager> data_type_manager_;
 
   ObserverList<ProfileSyncServiceBase::Observer> observers_;
+  ObserverList<browser_sync::ProtocolEventObserver> protocol_event_observers_;
 
   syncer::SyncJsController sync_js_controller_;
 
-  content::NotificationRegistrar registrar_;
-
   // This allows us to gracefully handle an ABORTED return code from the
   // DataTypeManager in the event that the server informed us to cease and
   // desist syncing immediately.
@@ -945,8 +950,8 @@
   // an action set on it.
   syncer::SyncProtocolError last_actionable_error_;
 
-  // This is used to show sync errors in the wrench menu.
-  scoped_ptr<SyncGlobalError> sync_global_error_;
+  // Exposes sync errors to the UI.
+  scoped_ptr<SyncErrorController> sync_error_controller_;
 
   // Tracks the set of failed data types (those that encounter an error
   // or must delay loading for some reason).
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 4aae06b..e249b7c 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -22,7 +22,7 @@
 #include "base/time/time.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -491,9 +491,8 @@
   virtual void SetUp() OVERRIDE {
     AbstractProfileSyncServiceTest::SetUp();
     TestingProfile::Builder builder;
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
+    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
+                              BuildAutoIssuingFakeProfileOAuth2TokenService);
     profile_ = builder.Build().Pass();
     web_database_.reset(new WebDatabaseFake(&autofill_table_));
     MockWebDataServiceWrapper* wrapper =
diff --git a/chrome/browser/sync/profile_sync_service_factory.cc b/chrome/browser/sync/profile_sync_service_factory.cc
index b92296a..76b6b5d 100644
--- a/chrome/browser/sync/profile_sync_service_factory.cc
+++ b/chrome/browser/sync/profile_sync_service_factory.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/password_manager/password_store_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -23,6 +22,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/sync/profile_sync_components_factory_impl.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/startup_controller.h"
@@ -31,7 +31,7 @@
 #include "chrome/browser/webdata/web_data_service_factory.h"
 #include "chrome/common/pref_names.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "extensions/browser/extension_system_provider.h"
 #include "extensions/browser/extensions_browser_client.h"
 
@@ -114,7 +114,7 @@
       new ProfileSyncComponentsFactoryImpl(profile,
                                            CommandLine::ForCurrentProcess()),
       profile,
-      new ManagedUserSigninManagerWrapper(signin),
+      new ManagedUserSigninManagerWrapper(profile, signin),
       ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
       behavior);
 
diff --git a/chrome/browser/sync/profile_sync_service_mock.cc b/chrome/browser/sync/profile_sync_service_mock.cc
index 7f9d981..1cfef8e 100644
--- a/chrome/browser/sync/profile_sync_service_mock.cc
+++ b/chrome/browser/sync/profile_sync_service_mock.cc
@@ -4,21 +4,22 @@
 
 #include "base/prefs/pref_service.h"
 #include "base/prefs/testing_pref_store.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/sync/profile_sync_service_mock.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 ProfileSyncServiceMock::ProfileSyncServiceMock(Profile* profile)
     : ProfileSyncService(
           NULL,
           profile,
           new ManagedUserSigninManagerWrapper(
+              profile,
               SigninManagerFactory::GetForProfile(profile)),
           ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
           browser_sync::MANUAL_START) {}
diff --git a/chrome/browser/sync/profile_sync_service_preference_unittest.cc b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
index d7eafb5..b85678e 100644
--- a/chrome/browser/sync/profile_sync_service_preference_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_preference_unittest.cc
@@ -19,7 +19,7 @@
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/prefs/pref_model_associator.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -127,9 +127,8 @@
   virtual void SetUp() {
     AbstractProfileSyncServiceTest::SetUp();
     TestingProfile::Builder builder;
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
+    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
+                              BuildAutoIssuingFakeProfileOAuth2TokenService);
     profile_ = builder.Build().Pass();
     invalidation::InvalidationServiceFactory::GetInstance()->SetTestingFactory(
         profile_.get(), invalidation::FakeInvalidationService::Build);
@@ -354,8 +353,8 @@
   {
     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
     base::ListValue* url_list = update.Get();
-    url_list->Append(base::Value::CreateStringValue(example_url0_));
-    url_list->Append(base::Value::CreateStringValue(example_url1_));
+    url_list->Append(new base::StringValue(example_url0_));
+    url_list->Append(new base::StringValue(example_url1_));
   }
   CreateRootHelper create_root(this, syncer::PREFERENCES);
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
@@ -375,19 +374,19 @@
   {
     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
     base::ListValue* url_list = update.Get();
-    url_list->Append(base::Value::CreateStringValue(example_url0_));
-    url_list->Append(base::Value::CreateStringValue(example_url1_));
+    url_list->Append(new base::StringValue(example_url0_));
+    url_list->Append(new base::StringValue(example_url1_));
   }
 
   PreferenceValues cloud_data;
   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
-  cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
+  cloud_data[prefs::kHomePage] = new base::StringValue(example_url1_);
   base::ListValue* urls_to_restore = new base::ListValue;
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
+  urls_to_restore->Append(new base::StringValue(example_url1_));
+  urls_to_restore->Append(new base::StringValue(example_url2_));
   cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore;
   cloud_data[prefs::kDefaultCharset] =
-      base::Value::CreateStringValue(non_default_charset_value_);
+      new base::StringValue(non_default_charset_value_);
 
   AddPreferenceEntriesHelper helper(this, cloud_data);
   ASSERT_TRUE(StartSyncService(helper.callback(), false));
@@ -401,9 +400,9 @@
   EXPECT_EQ(example_url1_, prefs_->GetString(prefs::kHomePage));
 
   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
-  expected_urls->Append(base::Value::CreateStringValue(example_url1_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url2_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url0_));
+  expected_urls->Append(new base::StringValue(example_url1_));
+  expected_urls->Append(new base::StringValue(example_url2_));
+  expected_urls->Append(new base::StringValue(example_url0_));
   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
   ASSERT_TRUE(value.get());
   EXPECT_TRUE(value->Equals(expected_urls.get()));
@@ -425,8 +424,8 @@
   PreferenceValues cloud_data;
   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
   base::ListValue* urls_to_restore = new base::ListValue;
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
+  urls_to_restore->Append(new base::StringValue(example_url1_));
+  urls_to_restore->Append(new base::StringValue(example_url2_));
   cloud_data[prefs::kURLsToRestoreOnStartupOld] = urls_to_restore;
 
   AddPreferenceEntriesHelper helper(this, cloud_data);
@@ -435,8 +434,8 @@
 
   // Expect that the new preference data contains the old pref's values.
   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
-  expected_urls->Append(base::Value::CreateStringValue(example_url1_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url2_));
+  expected_urls->Append(new base::StringValue(example_url1_));
+  expected_urls->Append(new base::StringValue(example_url2_));
 
   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
   scoped_ptr<const base::Value> value(
@@ -462,16 +461,16 @@
   {
     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
     base::ListValue* url_list = update.Get();
-    url_list->Append(base::Value::CreateStringValue(example_url0_));
-    url_list->Append(base::Value::CreateStringValue(example_url1_));
+    url_list->Append(new base::StringValue(example_url0_));
+    url_list->Append(new base::StringValue(example_url1_));
   }
 
   PreferenceValues cloud_data;
   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
-  cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
+  cloud_data[prefs::kHomePage] = new base::StringValue(example_url1_);
   base::ListValue* urls_to_restore = new base::ListValue;
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
+  urls_to_restore->Append(new base::StringValue(example_url1_));
+  urls_to_restore->Append(new base::StringValue(example_url2_));
   cloud_data[prefs::kURLsToRestoreOnStartupOld] = urls_to_restore;
 
   AddPreferenceEntriesHelper helper(this, cloud_data);
@@ -487,9 +486,9 @@
 
   // Expect that the new preference data contains the merged old prefs values.
   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
-  expected_urls->Append(base::Value::CreateStringValue(example_url1_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url2_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url0_));
+  expected_urls->Append(new base::StringValue(example_url1_));
+  expected_urls->Append(new base::StringValue(example_url2_));
+  expected_urls->Append(new base::StringValue(example_url0_));
 
   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
@@ -514,16 +513,16 @@
   {
     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartupOld);
     base::ListValue* url_list = update.Get();
-    url_list->Append(base::Value::CreateStringValue(example_url0_));
-    url_list->Append(base::Value::CreateStringValue(example_url1_));
+    url_list->Append(new base::StringValue(example_url0_));
+    url_list->Append(new base::StringValue(example_url1_));
   }
 
   PreferenceValues cloud_data;
   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
-  cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
+  cloud_data[prefs::kHomePage] = new base::StringValue(example_url1_);
   base::ListValue* urls_to_restore = new base::ListValue;
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
+  urls_to_restore->Append(new base::StringValue(example_url1_));
+  urls_to_restore->Append(new base::StringValue(example_url2_));
   cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore;
 
   AddPreferenceEntriesHelper helper(this, cloud_data);
@@ -539,8 +538,8 @@
 
   // Expect that the cloud data under the new migrated preference name sticks.
   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
-  expected_urls->Append(base::Value::CreateStringValue(example_url1_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url2_));
+  expected_urls->Append(new base::StringValue(example_url1_));
+  expected_urls->Append(new base::StringValue(example_url2_));
 
   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
@@ -551,8 +550,8 @@
 
   // The old preference data should still be here, though not synced.
   expected_urls.reset(new base::ListValue);
-  expected_urls->Append(base::Value::CreateStringValue(example_url0_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url1_));
+  expected_urls->Append(new base::StringValue(example_url0_));
+  expected_urls->Append(new base::StringValue(example_url1_));
 
   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartupOld));
   ASSERT_FALSE(value.get());
@@ -568,17 +567,17 @@
   {
     ListPrefUpdate update_old(prefs_, prefs::kURLsToRestoreOnStartupOld);
     base::ListValue* url_list_old = update_old.Get();
-    url_list_old->Append(base::Value::CreateStringValue(example_url0_));
-    url_list_old->Append(base::Value::CreateStringValue(example_url1_));
+    url_list_old->Append(new base::StringValue(example_url0_));
+    url_list_old->Append(new base::StringValue(example_url1_));
     ListPrefUpdate update(prefs_, prefs::kURLsToRestoreOnStartup);
     base::ListValue* url_list = update.Get();
-    url_list->Append(base::Value::CreateStringValue(example_url1_));
-    url_list->Append(base::Value::CreateStringValue(example_url2_));
+    url_list->Append(new base::StringValue(example_url1_));
+    url_list->Append(new base::StringValue(example_url2_));
   }
 
   PreferenceValues cloud_data;
   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
-  cloud_data[prefs::kHomePage] = base::Value::CreateStringValue(example_url1_);
+  cloud_data[prefs::kHomePage] = new base::StringValue(example_url1_);
 
   AddPreferenceEntriesHelper helper(this, cloud_data);
   ASSERT_TRUE(StartSyncService(helper.callback(), false));
@@ -593,8 +592,8 @@
 
   // Expect that the cloud data under the new migrated preference name sticks.
   scoped_ptr<base::ListValue> expected_urls(new base::ListValue);
-  expected_urls->Append(base::Value::CreateStringValue(example_url1_));
-  expected_urls->Append(base::Value::CreateStringValue(example_url2_));
+  expected_urls->Append(new base::StringValue(example_url1_));
+  expected_urls->Append(new base::StringValue(example_url2_));
 
   ASSERT_TRUE(HasSyncData(prefs::kURLsToRestoreOnStartup));
   value.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
@@ -624,13 +623,12 @@
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
-  scoped_ptr<base::Value> expected(
-      base::Value::CreateStringValue(example_url0_));
-  profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
+  base::StringValue expected(example_url0_);
+  profile_->GetPrefs()->Set(prefs::kHomePage, expected);
 
   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
   ASSERT_TRUE(actual.get());
-  EXPECT_TRUE(expected->Equals(actual.get()));
+  EXPECT_TRUE(expected.Equals(actual.get()));
 }
 
 TEST_F(ProfileSyncServicePreferenceTest, UpdatedPreferenceWithValue) {
@@ -639,13 +637,12 @@
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
-  scoped_ptr<base::Value> expected(
-      base::Value::CreateStringValue(example_url1_));
-  profile_->GetPrefs()->Set(prefs::kHomePage, *expected);
+  base::StringValue expected(example_url1_);
+  profile_->GetPrefs()->Set(prefs::kHomePage, expected);
 
   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
   ASSERT_TRUE(actual.get());
-  EXPECT_TRUE(expected->Equals(actual.get()));
+  EXPECT_TRUE(expected.Equals(actual.get()));
 }
 
 TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionUpdate) {
@@ -654,9 +651,8 @@
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
-  scoped_ptr<base::Value> expected(
-      base::Value::CreateStringValue(example_url1_));
-  int64 node_id = SetSyncedValue(prefs::kHomePage, *expected);
+  base::StringValue expected(example_url1_);
+  int64 node_id = SetSyncedValue(prefs::kHomePage, expected);
   ASSERT_NE(node_id, syncer::kInvalidId);
   {
     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
@@ -668,7 +664,7 @@
   change_processor_->CommitChangesFromSyncModel();
 
   const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
-  EXPECT_TRUE(expected->Equals(&actual));
+  EXPECT_TRUE(expected.Equals(&actual));
 }
 
 TEST_F(ProfileSyncServicePreferenceTest, UpdatedSyncNodeActionAdd) {
@@ -676,9 +672,8 @@
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
-  scoped_ptr<base::Value> expected(
-      base::Value::CreateStringValue(example_url0_));
-  int64 node_id = SetSyncedValue(prefs::kHomePage, *expected);
+  base::StringValue expected(example_url0_);
+  int64 node_id = SetSyncedValue(prefs::kHomePage, expected);
   ASSERT_NE(node_id, syncer::kInvalidId);
   {
     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
@@ -690,7 +685,7 @@
   change_processor_->CommitChangesFromSyncModel();
 
   const base::Value& actual = GetPreferenceValue(prefs::kHomePage);
-  EXPECT_TRUE(expected->Equals(&actual));
+  EXPECT_TRUE(expected.Equals(&actual));
   EXPECT_EQ(1U,
       pref_sync_service_->registered_preferences().count(prefs::kHomePage));
 }
@@ -700,9 +695,8 @@
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
-  scoped_ptr<base::Value> expected(
-      base::Value::CreateStringValue(example_url0_));
-  int64 node_id = SetSyncedValue("unknown preference", *expected);
+  base::StringValue expected(example_url0_);
+  int64 node_id = SetSyncedValue("unknown preference", expected);
   ASSERT_NE(node_id, syncer::kInvalidId);
   {
     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
@@ -719,25 +713,22 @@
 
 TEST_F(ProfileSyncServicePreferenceTest, ManagedPreferences) {
   // Make the homepage preference managed.
-  scoped_ptr<base::Value> managed_value(
-      base::Value::CreateStringValue("http://example.com"));
-  prefs_->SetManagedPref(prefs::kHomePage, managed_value->DeepCopy());
+  base::StringValue managed_value("http://example.com");
+  prefs_->SetManagedPref(prefs::kHomePage, managed_value.DeepCopy());
 
   CreateRootHelper create_root(this, syncer::PREFERENCES);
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
   // Changing the homepage preference should not sync anything.
-  scoped_ptr<base::Value> user_value(
-      base::Value::CreateStringValue("http://chromium..com"));
-  prefs_->SetUserPref(prefs::kHomePage, user_value->DeepCopy());
+  base::StringValue user_value("http://chromium..com");
+  prefs_->SetUserPref(prefs::kHomePage, user_value.DeepCopy());
   EXPECT_EQ(NULL, GetSyncedValue(prefs::kHomePage));
 
   // An incoming sync transaction should change the user value, not the managed
   // value.
-  scoped_ptr<base::Value> sync_value(
-      base::Value::CreateStringValue("http://crbug.com"));
-  int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value);
+  base::StringValue sync_value("http://crbug.com");
+  int64 node_id = SetSyncedValue(prefs::kHomePage, sync_value);
   ASSERT_NE(node_id, syncer::kInvalidId);
   {
     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
@@ -748,8 +739,8 @@
   }
   change_processor_->CommitChangesFromSyncModel();
 
-  EXPECT_TRUE(managed_value->Equals(prefs_->GetManagedPref(prefs::kHomePage)));
-  EXPECT_TRUE(sync_value->Equals(prefs_->GetUserPref(prefs::kHomePage)));
+  EXPECT_TRUE(managed_value.Equals(prefs_->GetManagedPref(prefs::kHomePage)));
+  EXPECT_TRUE(sync_value.Equals(prefs_->GetUserPref(prefs::kHomePage)));
 }
 
 // List preferences have special handling at association time due to our ability
@@ -758,8 +749,8 @@
 TEST_F(ProfileSyncServicePreferenceTest, ManagedListPreferences) {
   // Make the list of urls to restore on startup managed.
   base::ListValue managed_value;
-  managed_value.Append(base::Value::CreateStringValue(example_url0_));
-  managed_value.Append(base::Value::CreateStringValue(example_url1_));
+  managed_value.Append(new base::StringValue(example_url0_));
+  managed_value.Append(new base::StringValue(example_url1_));
   prefs_->SetManagedPref(prefs::kURLsToRestoreOnStartup,
                          managed_value.DeepCopy());
 
@@ -767,8 +758,8 @@
   PreferenceValues cloud_data;
   STLValueDeleter<PreferenceValues> cloud_data_deleter(&cloud_data);
   base::ListValue* urls_to_restore = new base::ListValue;
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url1_));
-  urls_to_restore->Append(base::Value::CreateStringValue(example_url2_));
+  urls_to_restore->Append(new base::StringValue(example_url1_));
+  urls_to_restore->Append(new base::StringValue(example_url2_));
   cloud_data[prefs::kURLsToRestoreOnStartup] = urls_to_restore;
 
   // Start sync and verify the synced value didn't get merged.
@@ -782,7 +773,7 @@
   // Changing the user's urls to restore on startup pref should not sync
   // anything.
   base::ListValue user_value;
-  user_value.Append(base::Value::CreateStringValue("http://chromium.org"));
+  user_value.Append(new base::StringValue("http://chromium.org"));
   prefs_->SetUserPref(prefs::kURLsToRestoreOnStartup, user_value.DeepCopy());
   actual.reset(GetSyncedValue(prefs::kURLsToRestoreOnStartup));
   EXPECT_TRUE(cloud_data[prefs::kURLsToRestoreOnStartup]->Equals(actual.get()));
@@ -790,7 +781,7 @@
   // An incoming sync transaction should change the user value, not the managed
   // value.
   base::ListValue sync_value;
-  sync_value.Append(base::Value::CreateStringValue("http://crbug.com"));
+  sync_value.Append(new base::StringValue("http://crbug.com"));
   int64 node_id = SetSyncedValue(prefs::kURLsToRestoreOnStartup, sync_value);
   ASSERT_NE(node_id, syncer::kInvalidId);
   {
@@ -813,27 +804,25 @@
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
-  scoped_ptr<base::Value> initial_value(
-      base::Value::CreateStringValue("http://example.com/initial"));
-  profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value);
+  base::StringValue initial_value("http://example.com/initial");
+  profile_->GetPrefs()->Set(prefs::kHomePage, initial_value);
   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
   ASSERT_TRUE(actual.get());
-  EXPECT_TRUE(initial_value->Equals(actual.get()));
+  EXPECT_TRUE(initial_value.Equals(actual.get()));
 
   // Switch kHomePage to managed and set a different value.
-  scoped_ptr<base::Value> managed_value(
-      base::Value::CreateStringValue("http://example.com/managed"));
-  profile_->GetTestingPrefService()->SetManagedPref(
-      prefs::kHomePage, managed_value->DeepCopy());
+  base::StringValue managed_value("http://example.com/managed");
+  profile_->GetTestingPrefService()->SetManagedPref(prefs::kHomePage,
+                                                    managed_value.DeepCopy());
 
   // The pref value should be the one dictated by policy.
-  EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
+  EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
 
   // Switch kHomePage back to unmanaged.
   profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
 
   // The original value should be picked up.
-  EXPECT_TRUE(initial_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
+  EXPECT_TRUE(initial_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
 }
 
 TEST_F(ProfileSyncServicePreferenceTest,
@@ -842,22 +831,19 @@
   ASSERT_TRUE(StartSyncService(create_root.callback(), false));
   ASSERT_TRUE(create_root.success());
 
-  scoped_ptr<base::Value> initial_value(
-      base::Value::CreateStringValue("http://example.com/initial"));
-  profile_->GetPrefs()->Set(prefs::kHomePage, *initial_value);
+  base::StringValue initial_value("http://example.com/initial");
+  profile_->GetPrefs()->Set(prefs::kHomePage, initial_value);
   scoped_ptr<const base::Value> actual(GetSyncedValue(prefs::kHomePage));
-  EXPECT_TRUE(initial_value->Equals(actual.get()));
+  EXPECT_TRUE(initial_value.Equals(actual.get()));
 
   // Switch kHomePage to managed and set a different value.
-  scoped_ptr<base::Value> managed_value(
-      base::Value::CreateStringValue("http://example.com/managed"));
-  profile_->GetTestingPrefService()->SetManagedPref(
-      prefs::kHomePage, managed_value->DeepCopy());
+  base::StringValue managed_value("http://example.com/managed");
+  profile_->GetTestingPrefService()->SetManagedPref(prefs::kHomePage,
+                                                    managed_value.DeepCopy());
 
   // Change the sync value.
-  scoped_ptr<base::Value> sync_value(
-      base::Value::CreateStringValue("http://example.com/sync"));
-  int64 node_id = SetSyncedValue(prefs::kHomePage, *sync_value);
+  base::StringValue sync_value("http://example.com/sync");
+  int64 node_id = SetSyncedValue(prefs::kHomePage, sync_value);
   ASSERT_NE(node_id, syncer::kInvalidId);
   {
     syncer::WriteTransaction trans(FROM_HERE, sync_service_->GetUserShare());
@@ -869,13 +855,13 @@
   change_processor_->CommitChangesFromSyncModel();
 
   // The pref value should still be the one dictated by policy.
-  EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
+  EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
 
   // Switch kHomePage back to unmanaged.
   profile_->GetTestingPrefService()->RemoveManagedPref(prefs::kHomePage);
 
   // Sync value should be picked up.
-  EXPECT_TRUE(sync_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
+  EXPECT_TRUE(sync_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
 }
 
 TEST_F(ProfileSyncServicePreferenceTest, DynamicManagedDefaultPreferences) {
@@ -889,12 +875,11 @@
   EXPECT_TRUE(pref->IsDefaultValue());
   EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL);
   // Switch kHomePage to managed and set a different value.
-  scoped_ptr<base::Value> managed_value(
-      base::Value::CreateStringValue("http://example.com/managed"));
-  profile_->GetTestingPrefService()->SetManagedPref(
-      prefs::kHomePage, managed_value->DeepCopy());
+  base::StringValue managed_value("http://example.com/managed");
+  profile_->GetTestingPrefService()->SetManagedPref(prefs::kHomePage,
+                                                    managed_value.DeepCopy());
   // The pref value should be the one dictated by policy.
-  EXPECT_TRUE(managed_value->Equals(&GetPreferenceValue(prefs::kHomePage)));
+  EXPECT_TRUE(managed_value.Equals(&GetPreferenceValue(prefs::kHomePage)));
   EXPECT_FALSE(pref->IsDefaultValue());
   // There should be no synced value.
   EXPECT_TRUE(GetSyncedValue(prefs::kHomePage) == NULL);
diff --git a/chrome/browser/sync/profile_sync_service_session_unittest.cc b/chrome/browser/sync/profile_sync_service_session_unittest.cc
index f78a5cc..6e17c9b 100644
--- a/chrome/browser/sync/profile_sync_service_session_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_session_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/callback.h"
+#include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/guid.h"
@@ -21,7 +22,7 @@
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/sessions/session_tab_helper.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -41,9 +42,10 @@
 #include "chrome/browser/sync/test_profile_sync_service.h"
 #include "chrome/browser/ui/sync/tab_contents_synced_tab_delegate.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/notification_observer.h"
@@ -137,9 +139,8 @@
  protected:
   virtual TestingProfile* CreateProfile() OVERRIDE {
     TestingProfile::Builder builder;
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
+    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
+                              BuildAutoIssuingFakeProfileOAuth2TokenService);
     // Don't want the profile to create a real ProfileSyncService.
     builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(), NULL);
     scoped_ptr<TestingProfile> profile(builder.Build());
@@ -156,6 +157,8 @@
         content::NotificationService::AllSources());
     registrar_.Add(this, chrome::NOTIFICATION_SYNC_REFRESH_LOCAL,
         content::NotificationService::AllSources());
+    CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+        switches::kSyncDeferredStartupTimeoutSeconds, "0");
   }
 
   virtual void Observe(int type,
diff --git a/chrome/browser/sync/profile_sync_service_startup_unittest.cc b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
index 58c2f4b..ecc49e8 100644
--- a/chrome/browser/sync/profile_sync_service_startup_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_startup_unittest.cc
@@ -5,27 +5,24 @@
 #include "base/file_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/prefs/pref_service.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "chrome/browser/sync/profile_sync_test_util.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/data_type_manager.h"
 #include "components/sync_driver/data_type_manager_mock.h"
 #include "components/sync_driver/pref_names.h"
 #include "components/sync_driver/sync_prefs.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_utils.h"
 #include "google_apis/gaia/gaia_auth_consumer.h"
@@ -78,9 +75,8 @@
     TestingProfile::Builder builder;
     builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
                               FakeSigninManagerBase::Build);
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
+    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
+                              BuildAutoIssuingFakeProfileOAuth2TokenService);
     builder.AddTestingFactory(ProfileSyncServiceFactory::GetInstance(),
                               BuildService);
     return builder.Build();
@@ -97,7 +93,7 @@
         new ProfileSyncComponentsFactoryMock(),
         profile,
         new ManagedUserSigninManagerWrapper(
-            SigninManagerFactory::GetForProfile(profile)),
+            profile, SigninManagerFactory::GetForProfile(profile)),
         ProfileOAuth2TokenServiceFactory::GetForProfile(profile),
         browser_sync::MANUAL_START);
   }
@@ -117,7 +113,22 @@
     return static_cast<ProfileSyncComponentsFactoryMock*>(sync_->factory());
   }
 
+  FakeSigninManagerForTesting* fake_signin() {
+    return static_cast<FakeSigninManagerForTesting*>(sync_->signin());
+  }
+
  protected:
+  void SimulateTestUserSignin() {
+    profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                    "test_user@gmail.com");
+#if !defined(OS_CHROMEOS)
+    fake_signin()->SignIn("test_user@gmail.com", "");
+#else
+    fake_signin()->SetAuthenticatedUsername("test_user@gmail.com");
+    sync_->GoogleSigninSucceeded("test_user@gmail.com", "");
+#endif
+  }
+
   DataTypeManagerMock* SetUpDataTypeManager() {
     DataTypeManagerMock* data_type_manager = new DataTypeManagerMock();
     EXPECT_CALL(*components_factory_mock(),
@@ -164,7 +175,7 @@
     return new ProfileSyncService(
         new ProfileSyncComponentsFactoryMock(),
         profile,
-        new ManagedUserSigninManagerWrapper(signin),
+        new ManagedUserSigninManagerWrapper(profile, signin),
         oauth2_token_service,
         browser_sync::AUTO_START);
   }
@@ -202,15 +213,7 @@
   sync_->SetSetupInProgress(true);
 
   // Simulate successful signin as test_user.
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                  "test_user@gmail.com");
-  sync_->signin()->SetAuthenticatedUsername("test_user@gmail.com");
-  GoogleServiceSigninSuccessDetails details("test_user@gmail.com", "");
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-      content::Source<Profile>(profile_.get()),
-      content::Details<const GoogleServiceSigninSuccessDetails>(&details));
-
+  SimulateTestUserSignin();
   // Create some tokens in the token service.
   IssueTestTokens();
 
@@ -243,14 +246,8 @@
   sync_->SetSetupInProgress(true);
 
   // Simulate successful signin as test_user.
-  profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
-                                  "test_user@gmail.com");
-  sync_->signin()->SetAuthenticatedUsername("test_user@gmail.com");
-  GoogleServiceSigninSuccessDetails details("test_user@gmail.com", "");
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-      content::Source<Profile>(profile_.get()),
-      content::Details<const GoogleServiceSigninSuccessDetails>(&details));
+  SimulateTestUserSignin();
+
   ProfileOAuth2TokenService* token_service =
     ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
   token_service->LoadCredentials("test_user@gmail.com");
@@ -292,12 +289,7 @@
   sync_->SetSetupInProgress(true);
 
   // Simulate successful signin.
-  GoogleServiceSigninSuccessDetails details("test_user@gmail.com",
-                                            std::string());
-  content::NotificationService::current()->Notify(
-        chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-        content::Source<Profile>(profile_.get()),
-        content::Details<const GoogleServiceSigninSuccessDetails>(&details));
+  SimulateTestUserSignin();
 
   sync_->SetSetupInProgress(false);
 
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index babf34c..ee820e9 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -25,7 +25,7 @@
 #include "chrome/browser/invalidation/fake_invalidation_service.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -187,9 +187,8 @@
   virtual void SetUp() {
     AbstractProfileSyncServiceTest::SetUp();
     TestingProfile::Builder builder;
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
+    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
+                              BuildAutoIssuingFakeProfileOAuth2TokenService);
     profile_ = builder.Build().Pass();
     invalidation::InvalidationServiceFactory::GetInstance()->SetTestingFactory(
         profile_.get(), invalidation::FakeInvalidationService::Build);
diff --git a/chrome/browser/sync/profile_sync_service_unittest.cc b/chrome/browser/sync/profile_sync_service_unittest.cc
index e07f250..11d4ebf 100644
--- a/chrome/browser/sync/profile_sync_service_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_unittest.cc
@@ -9,14 +9,14 @@
 #include "base/values.h"
 #include "chrome/browser/invalidation/fake_invalidation_service.h"
 #include "chrome/browser/invalidation/invalidation_service_factory.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/glue/data_type_manager_impl.h"
 #include "chrome/browser/sync/glue/sync_backend_host_mock.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_pref_service_syncable.h"
@@ -96,9 +96,8 @@
   virtual void SetUp() OVERRIDE {
     TestingProfile::Builder builder;
 
-    builder.AddTestingFactory(
-        ProfileOAuth2TokenServiceFactory::GetInstance(),
-        FakeProfileOAuth2TokenServiceWrapper::BuildAutoIssuingTokenService);
+    builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
+                              BuildAutoIssuingFakeProfileOAuth2TokenService);
     invalidation::InvalidationServiceFactory::GetInstance()->
         RegisterTestingFactory(invalidation::FakeInvalidationService::Build);
 
@@ -129,7 +128,7 @@
     service_.reset(new ProfileSyncService(
         components_factory_,
         profile_.get(),
-        new ManagedUserSigninManagerWrapper(signin),
+        new ManagedUserSigninManagerWrapper(profile_.get(), signin),
         oauth2_token_service,
         behavior));
   }
diff --git a/chrome/browser/sync/protocol_event_observer.cc b/chrome/browser/sync/protocol_event_observer.cc
new file mode 100644
index 0000000..b907907
--- /dev/null
+++ b/chrome/browser/sync/protocol_event_observer.cc
@@ -0,0 +1,13 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/protocol_event_observer.h"
+
+namespace browser_sync {
+
+ProtocolEventObserver::ProtocolEventObserver() {}
+
+ProtocolEventObserver::~ProtocolEventObserver() {}
+
+}  // namespace browser_sync
diff --git a/chrome/browser/sync/protocol_event_observer.h b/chrome/browser/sync/protocol_event_observer.h
new file mode 100644
index 0000000..3ed4095
--- /dev/null
+++ b/chrome/browser/sync/protocol_event_observer.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_PROTOCOL_EVENT_OBSERVER_H_
+#define CHROME_BROWSER_SYNC_PROTOCOL_EVENT_OBSERVER_H_
+
+namespace syncer {
+class ProtocolEvent;
+}
+
+namespace browser_sync {
+
+class ProtocolEventObserver {
+ public:
+  ProtocolEventObserver();
+  virtual ~ProtocolEventObserver();
+
+  virtual void OnProtocolEvent(const syncer::ProtocolEvent& event) = 0;
+};
+
+}  // namespace browser_sync
+
+#endif  // CHROME_BROWSER_SYNC_PROTOCOL_EVENT_OBSERVER_H_
diff --git a/chrome/browser/sync/sessions2/sessions_sync_manager.cc b/chrome/browser/sync/sessions2/sessions_sync_manager.cc
index 4de3ccb..58be186 100644
--- a/chrome/browser/sync/sessions2/sessions_sync_manager.cc
+++ b/chrome/browser/sync/sessions2/sessions_sync_manager.cc
@@ -774,6 +774,10 @@
         SyncData::CreateLocalDelete(TabNodePool2::TabIdToTag(tag, *it),
                                     syncer::SESSIONS)));
   }
+  content::NotificationService::current()->Notify(
+      chrome::NOTIFICATION_FOREIGN_SESSION_UPDATED,
+      content::Source<Profile>(profile_),
+      content::NotificationService::NoDetails());
 }
 
 bool SessionsSyncManager::DisassociateForeignSession(
diff --git a/chrome/browser/sync/sessions2/sessions_sync_manager_unittest.cc b/chrome/browser/sync/sessions2/sessions_sync_manager_unittest.cc
index 9529363..b990f1c 100644
--- a/chrome/browser/sync/sessions2/sessions_sync_manager_unittest.cc
+++ b/chrome/browser/sync/sessions2/sessions_sync_manager_unittest.cc
@@ -1650,7 +1650,8 @@
 };
 }  // namespace
 
-// Test that NOTIFICATION_FOREIGN_SESSION_UPDATED is sent.
+// Test that NOTIFICATION_FOREIGN_SESSION_UPDATED is sent when processing
+// sync changes.
 TEST_F(SessionsSyncManagerTest, NotifiedOfUpdates) {
   SessionNotificationObserver observer;
   ASSERT_FALSE(observer.notified_of_update());
@@ -1680,6 +1681,27 @@
   EXPECT_TRUE(observer.notified_of_update());
 }
 
+// Test that NOTIFICATION_FOREIGN_SESSION_UPDATED is sent when handling
+// local hide/removal of foreign session.
+TEST_F(SessionsSyncManagerTest, NotifiedOfLocalRemovalOfForeignSession) {
+  InitWithNoSyncData();
+  const std::string tag("tag1");
+  SessionID::id_type n[] = {5};
+  std::vector<sync_pb::SessionSpecifics> tabs1;
+  std::vector<SessionID::id_type> tab_list(n, n + arraysize(n));
+  sync_pb::SessionSpecifics meta(helper()->BuildForeignSession(
+      tag, tab_list, &tabs1));
+
+  syncer::SyncChangeList changes;
+  changes.push_back(MakeRemoteChange(1, meta, SyncChange::ACTION_ADD));
+  manager()->ProcessSyncChanges(FROM_HERE, changes);
+
+  SessionNotificationObserver observer;
+  ASSERT_FALSE(observer.notified_of_update());
+  manager()->DeleteForeignSession(tag);
+  ASSERT_TRUE(observer.notified_of_update());
+}
+
 #if defined(OS_ANDROID) || defined(OS_IOS)
 // Tests that opening the other devices page triggers a session sync refresh.
 // This page only exists on mobile platforms today; desktop has a
diff --git a/chrome/browser/sync/startup_controller.cc b/chrome/browser/sync/startup_controller.cc
index 3f84735..ca0fb44 100644
--- a/chrome/browser/sync/startup_controller.cc
+++ b/chrome/browser/sync/startup_controller.cc
@@ -8,9 +8,9 @@
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/strings/string_number_conversions.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/common/chrome_switches.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/sync_prefs.h"
 
 namespace browser_sync {
diff --git a/chrome/browser/sync/startup_controller_unittest.cc b/chrome/browser/sync/startup_controller_unittest.cc
index 5c0a4ef..fc96790 100644
--- a/chrome/browser/sync/startup_controller_unittest.cc
+++ b/chrome/browser/sync/startup_controller_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chrome/browser/defaults.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_profile.h"
 #include "components/sync_driver/sync_prefs.h"
@@ -35,7 +35,7 @@
     : public ManagedUserSigninManagerWrapper {
  public:
   FakeManagedUserSigninManagerWrapper()
-      : ManagedUserSigninManagerWrapper(NULL) {}
+      : ManagedUserSigninManagerWrapper(NULL, NULL) {}
   virtual std::string GetEffectiveUsername() const OVERRIDE {
     return account_;
   }
@@ -57,9 +57,8 @@
   virtual void SetUp() OVERRIDE {
     profile_.reset(new TestingProfile());
     sync_prefs_.reset(new sync_driver::SyncPrefs(profile_->GetPrefs()));
-    token_service_.reset(
-        static_cast<FakeProfileOAuth2TokenServiceWrapper*>(
-            FakeProfileOAuth2TokenServiceWrapper::Build(profile_.get())));
+    token_service_.reset(static_cast<FakeProfileOAuth2TokenService*>(
+        BuildFakeProfileOAuth2TokenService(profile_.get())));
     signin_.reset(new FakeManagedUserSigninManagerWrapper());
 
     ProfileSyncServiceStartBehavior behavior =
@@ -77,6 +76,7 @@
   virtual void TearDown() OVERRIDE {
     controller_.reset();
     signin_.reset();
+    token_service_->Shutdown();
     token_service_.reset();
     sync_prefs_.reset();
     started_ = false;
@@ -91,8 +91,7 @@
   StartupController* controller() { return controller_.get(); }
   FakeManagedUserSigninManagerWrapper* signin() { return signin_.get(); }
   FakeProfileOAuth2TokenService* token_service() {
-    return static_cast<FakeProfileOAuth2TokenService*>(
-        token_service_->GetProfileOAuth2TokenService());
+    return token_service_.get();
   }
   sync_driver::SyncPrefs* sync_prefs() { return sync_prefs_.get(); }
   Profile* profile() { return profile_.get(); }
@@ -102,7 +101,7 @@
   base::MessageLoop message_loop_;
   scoped_ptr<StartupController> controller_;
   scoped_ptr<FakeManagedUserSigninManagerWrapper> signin_;
-  scoped_ptr<FakeProfileOAuth2TokenServiceWrapper> token_service_;
+  scoped_ptr<FakeProfileOAuth2TokenService> token_service_;
   scoped_ptr<sync_driver::SyncPrefs> sync_prefs_;
   scoped_ptr<TestingProfile> profile_;
 };
diff --git a/chrome/browser/sync/sync_error_controller.cc b/chrome/browser/sync/sync_error_controller.cc
new file mode 100644
index 0000000..c6346d0
--- /dev/null
+++ b/chrome/browser/sync/sync_error_controller.cc
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/sync_error_controller.h"
+
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+
+SyncErrorController::SyncErrorController(ProfileSyncService* service)
+    : service_(service) {
+  DCHECK(service_);
+}
+
+SyncErrorController::~SyncErrorController() {
+}
+
+bool SyncErrorController::HasError() {
+  return service_->HasSyncSetupCompleted() &&
+      service_->IsPassphraseRequired() &&
+      service_->IsPassphraseRequiredForDecryption();
+}
+
+void SyncErrorController::AddObserver(Observer* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void SyncErrorController::RemoveObserver(Observer* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
+void SyncErrorController::OnStateChanged() {
+  FOR_EACH_OBSERVER(Observer,
+                    observer_list_,
+                    OnErrorChanged());
+}
diff --git a/chrome/browser/sync/sync_error_controller.h b/chrome/browser/sync/sync_error_controller.h
new file mode 100644
index 0000000..8b6722c
--- /dev/null
+++ b/chrome/browser/sync/sync_error_controller.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_SYNC_ERROR_CONTROLLER_H_
+#define CHROME_BROWSER_SYNC_SYNC_ERROR_CONTROLLER_H_
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/observer_list.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
+
+class Profile;
+class ProfileSyncService;
+
+// Keep track of sync errors and expose them to observers in the UI.
+class SyncErrorController : public ProfileSyncServiceObserver {
+ public:
+  // The observer class for SyncErrorController lets the controller notify
+  // observers when an error arises or changes.
+  class Observer {
+   public:
+    virtual ~Observer() {}
+    virtual void OnErrorChanged() = 0;
+  };
+
+  explicit SyncErrorController(ProfileSyncService* service);
+  virtual ~SyncErrorController();
+
+  // True if there exists an error worth elevating to the user.
+  bool HasError();
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  // ProfileSyncServiceObserver:
+  virtual void OnStateChanged() OVERRIDE;
+
+ private:
+  ProfileSyncService* service_;
+  ObserverList<Observer, true> observer_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncErrorController);
+};
+
+#endif  // CHROME_BROWSER_SYNC_SYNC_ERROR_CONTROLLER_H_
diff --git a/chrome/browser/sync/sync_error_notifier_ash.cc b/chrome/browser/sync/sync_error_notifier_ash.cc
new file mode 100644
index 0000000..f459075
--- /dev/null
+++ b/chrome/browser/sync/sync_error_notifier_ash.cc
@@ -0,0 +1,179 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/sync_error_notifier_ash.h"
+
+#include "ash/shell.h"
+#include "ash/shell_delegate.h"
+#include "ash/system/system_notifier.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
+#include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/webui/signin/login_ui_service.h"
+#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
+#include "chrome/common/url_constants.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "third_party/WebKit/public/web/WebTextDirection.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/message_center/notification.h"
+#include "ui/message_center/notification_delegate.h"
+
+namespace {
+
+const char kProfileSyncNotificationId[] = "chrome://settings/sync/";
+
+// A simple notification delegate for the sync setup button.
+class SyncNotificationDelegate : public NotificationDelegate {
+ public:
+  SyncNotificationDelegate(const std::string& id,
+                           Profile* profile);
+
+  // NotificationDelegate:
+  virtual void Display() OVERRIDE;
+  virtual void Error() OVERRIDE;
+  virtual void Close(bool by_user) OVERRIDE;
+  virtual bool HasClickedListener() OVERRIDE;
+  virtual void Click() OVERRIDE;
+  virtual void ButtonClick(int button_index) OVERRIDE;
+  virtual std::string id() const OVERRIDE;
+  virtual content::RenderViewHost* GetRenderViewHost() const OVERRIDE;
+
+ protected:
+  virtual ~SyncNotificationDelegate();
+
+ private:
+  // Unique id of the notification.
+  const std::string id_;
+
+  Profile* profile_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncNotificationDelegate);
+};
+
+SyncNotificationDelegate::SyncNotificationDelegate(
+    const std::string& id,
+    Profile* profile)
+    : id_(id),
+      profile_(profile) {
+}
+
+SyncNotificationDelegate::~SyncNotificationDelegate() {
+}
+
+void SyncNotificationDelegate::Display() {
+}
+
+void SyncNotificationDelegate::Error() {
+}
+
+void SyncNotificationDelegate::Close(bool by_user) {
+}
+
+bool SyncNotificationDelegate::HasClickedListener() {
+  return false;
+}
+
+void SyncNotificationDelegate::Click() {
+}
+
+std::string SyncNotificationDelegate::id() const {
+  return id_;
+}
+
+content::RenderViewHost* SyncNotificationDelegate::GetRenderViewHost() const {
+  return NULL;
+}
+
+void SyncNotificationDelegate::ButtonClick(int button_index) {
+  LoginUIService* login_ui = LoginUIServiceFactory::GetForProfile(profile_);
+  if (login_ui->current_login_ui()) {
+    // TODO(michaelpg): The LoginUI might be on an inactive desktop.
+    // See crbug.com/354280.
+    login_ui->current_login_ui()->FocusUI();
+    return;
+  }
+
+  chrome::ShowSettingsSubPageForProfile(profile_, chrome::kSyncSetupSubPage);
+}
+
+} // namespace
+
+SyncErrorNotifier::SyncErrorNotifier(SyncErrorController* controller,
+                                     Profile* profile)
+    : error_controller_(controller),
+      profile_(profile) {
+  // Create a unique notification ID for this profile.
+  notification_id_ = kProfileSyncNotificationId + profile_->GetProfileName();
+
+  error_controller_->AddObserver(this);
+  OnErrorChanged();
+}
+
+SyncErrorNotifier::~SyncErrorNotifier() {
+  DCHECK(!error_controller_)
+      << "SyncErrorNotifier::Shutdown() was not called";
+}
+
+void SyncErrorNotifier::Shutdown() {
+  error_controller_->RemoveObserver(this);
+  error_controller_ = NULL;
+}
+
+void SyncErrorNotifier::OnErrorChanged() {
+  NotificationUIManager* notification_ui_manager =
+      g_browser_process->notification_ui_manager();
+
+  // notification_ui_manager() may return NULL when shutting down.
+  if (!notification_ui_manager)
+    return;
+
+  if (!error_controller_->HasError()) {
+    g_browser_process->notification_ui_manager()->CancelById(notification_id_);
+    return;
+  }
+
+  // Keep the existing notification if there is one.
+  if (notification_ui_manager->FindById(notification_id_))
+    return;
+
+  // Add an accept button to launch the sync setup settings subpage.
+  message_center::RichNotificationData data;
+  data.buttons.push_back(message_center::ButtonInfo(
+      l10n_util::GetStringUTF16(IDS_SYNC_NOTIFICATION_ACCEPT)));
+
+  // Set the delegate for the notification's sync setup button.
+  SyncNotificationDelegate* delegate =
+      new SyncNotificationDelegate(notification_id_, profile_);
+
+  message_center::NotifierId notifier_id(
+      message_center::NotifierId::SYSTEM_COMPONENT,
+      kProfileSyncNotificationId);
+
+  // Set |profile_id| for multi-user notification blocker.
+  notifier_id.profile_id = multi_user_util::GetUserIDFromProfile(profile_);
+
+  // Add a new notification.
+  Notification notification(
+      message_center::NOTIFICATION_TYPE_SIMPLE,
+      GURL(notification_id_),
+      l10n_util::GetStringUTF16(IDS_SYNC_ERROR_BUBBLE_VIEW_TITLE),
+      l10n_util::GetStringUTF16(IDS_SYNC_PASSPHRASE_ERROR_BUBBLE_VIEW_MESSAGE),
+      ui::ResourceBundle::GetSharedInstance().GetImageNamed(
+          IDR_NOTIFICATION_ALERT),
+      blink::WebTextDirectionDefault,
+      notifier_id,
+      base::string16(),  // display_source
+      base::ASCIIToUTF16(notification_id_),
+      data,
+      delegate);
+  notification_ui_manager->Add(notification, profile_);
+}
diff --git a/chrome/browser/sync/sync_error_notifier_ash.h b/chrome/browser/sync/sync_error_notifier_ash.h
new file mode 100644
index 0000000..6457f73
--- /dev/null
+++ b/chrome/browser/sync/sync_error_notifier_ash.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_SYNC_ERROR_NOTIFIER_ASH_H_
+#define CHROME_BROWSER_SYNC_SYNC_ERROR_NOTIFIER_ASH_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/strings/string16.h"
+#include "chrome/browser/sync/sync_error_controller.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+class Profile;
+
+// Shows sync-related errors as notifications in Ash.
+class SyncErrorNotifier : public SyncErrorController::Observer,
+                          public KeyedService {
+ public:
+  SyncErrorNotifier(SyncErrorController* controller, Profile* profile);
+  virtual ~SyncErrorNotifier();
+
+  // KeyedService:
+  virtual void Shutdown() OVERRIDE;
+
+  // SyncErrorController::Observer:
+  virtual void OnErrorChanged() OVERRIDE;
+
+ private:
+  // The error controller to query for error details.
+  SyncErrorController* error_controller_;
+
+  // The Profile this service belongs to.
+  Profile* profile_;
+
+  // Used to keep track of the message center notification.
+  std::string notification_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifier);
+};
+
+#endif  // CHROME_BROWSER_SYNC_SYNC_ERROR_NOTIFIER_ASH_H_
diff --git a/chrome/browser/sync/sync_error_notifier_ash_unittest.cc b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
new file mode 100644
index 0000000..4f5bb65
--- /dev/null
+++ b/chrome/browser/sync/sync_error_notifier_ash_unittest.cc
@@ -0,0 +1,232 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/sync_error_notifier_ash.h"
+
+#include "ash/test/ash_test_base.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/notifications/notification_ui_manager.h"
+#include "chrome/browser/sync/profile_sync_service_mock.h"
+#include "chrome/browser/sync/sync_error_controller.h"
+#include "chrome/browser/ui/ash/test_views_delegate_with_parent.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/webui/signin/login_ui_service.h"
+#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/message_center/notification.h"
+
+#if !defined(OS_CHROMEOS)
+#include "chrome/browser/ui/ash/ash_util.h"
+#include "ui/aura/test/test_screen.h"
+#include "ui/gfx/screen.h"
+#include "ui/gfx/screen_type_delegate.h"
+#endif
+
+using ::testing::NiceMock;
+using ::testing::Return;
+using ::testing::ReturnRef;
+using ::testing::_;
+
+namespace ash {
+namespace test {
+
+namespace {
+
+static const char kTestAccountId[] = "testuser@test.com";
+
+// Notification ID corresponding to kProfileSyncNotificationId + kTestAccountId.
+static const std::string kNotificationId =
+    "chrome://settings/sync/testuser@test.com";
+
+#if !defined(OS_CHROMEOS)
+class ScreenTypeDelegateDesktop : public gfx::ScreenTypeDelegate {
+ public:
+  ScreenTypeDelegateDesktop() {}
+  virtual ~ScreenTypeDelegateDesktop() {}
+  virtual gfx::ScreenType GetScreenTypeForNativeView(
+      gfx::NativeView view) OVERRIDE {
+    return chrome::IsNativeViewInAsh(view) ?
+        gfx::SCREEN_TYPE_ALTERNATE :
+        gfx::SCREEN_TYPE_NATIVE;
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ScreenTypeDelegateDesktop);
+};
+#endif
+
+class FakeLoginUIService: public LoginUIService {
+ public:
+  FakeLoginUIService() : LoginUIService(NULL) {}
+  virtual ~FakeLoginUIService() {}
+};
+
+class FakeLoginUI : public LoginUIService::LoginUI {
+ public:
+  FakeLoginUI() : focus_ui_call_count_(0) {}
+
+  virtual ~FakeLoginUI() {}
+
+  int focus_ui_call_count() const { return focus_ui_call_count_; }
+
+ private:
+  // LoginUIService::LoginUI:
+  virtual void FocusUI() OVERRIDE {
+    ++focus_ui_call_count_;
+  }
+  virtual void CloseUI() OVERRIDE {}
+
+  int focus_ui_call_count_;
+};
+
+KeyedService* BuildMockLoginUIService(
+    content::BrowserContext* profile) {
+  return new FakeLoginUIService();
+}
+
+class SyncErrorNotifierTest : public AshTestBase  {
+ public:
+  SyncErrorNotifierTest() {}
+  virtual ~SyncErrorNotifierTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    views::ViewsDelegate::views_delegate = &views_delegate_;
+
+    profile_manager_.reset(
+        new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
+    ASSERT_TRUE(profile_manager_->SetUp());
+
+    profile_ = profile_manager_->CreateTestingProfile(kTestAccountId);
+
+    TestingBrowserProcess::GetGlobal();
+    AshTestBase::SetUp();
+
+    // Set up a desktop screen for Windows to hold native widgets, used when
+    // adding desktop widgets (i.e., message center notifications).
+#if defined(OS_WIN)
+    aura::TestScreen* test_screen = aura::TestScreen::Create();
+    gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, test_screen);
+    gfx::Screen::SetScreenTypeDelegate(new ScreenTypeDelegateDesktop);
+#endif
+
+    service_.reset(new NiceMock<ProfileSyncServiceMock>(profile_));
+
+    FakeLoginUIService* login_ui_service = static_cast<FakeLoginUIService*>(
+        LoginUIServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+            profile_, BuildMockLoginUIService));
+    login_ui_service->SetLoginUI(&login_ui_);
+
+    error_controller_.reset(new SyncErrorController(service_.get()));
+    error_notifier_.reset(new SyncErrorNotifier(error_controller_.get(),
+                                                profile_));
+
+    notification_ui_manager_ = g_browser_process->notification_ui_manager();
+  }
+
+  virtual void TearDown() OVERRIDE {
+    error_notifier_->Shutdown();
+    service_.reset();
+    profile_manager_.reset();
+
+    AshTestBase::TearDown();
+  }
+
+ protected:
+  // Utility function to test that SyncErrorNotifier behaves correctly for the
+  // given error condition.
+  void VerifySyncErrorNotifierResult(GoogleServiceAuthError::State error_state,
+                                     bool is_signed_in,
+                                     bool is_error) {
+    EXPECT_CALL(*service_, HasSyncSetupCompleted())
+                .WillRepeatedly(Return(is_signed_in));
+
+    GoogleServiceAuthError auth_error(error_state);
+    EXPECT_CALL(*service_, GetAuthError()).WillRepeatedly(
+        ReturnRef(auth_error));
+
+    error_controller_->OnStateChanged();
+    EXPECT_EQ(is_error, error_controller_->HasError());
+
+    // If there is an error we should see a notification.
+    const Notification* notification = notification_ui_manager_->
+        FindById(kNotificationId);
+    if (is_error) {
+      ASSERT_TRUE(notification);
+      ASSERT_FALSE(notification->title().empty());
+      ASSERT_FALSE(notification->title().empty());
+      ASSERT_EQ((size_t)1, notification->buttons().size());
+    } else {
+      ASSERT_FALSE(notification);
+    }
+  }
+
+  scoped_ptr<TestingProfileManager> profile_manager_;
+  scoped_ptr<SyncErrorController> error_controller_;
+  scoped_ptr<SyncErrorNotifier> error_notifier_;
+  scoped_ptr<NiceMock<ProfileSyncServiceMock> > service_;
+  TestingProfile* profile_;
+  FakeLoginUI login_ui_;
+  NotificationUIManager* notification_ui_manager_;
+  TestViewsDelegateWithParent views_delegate_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifierTest);
+};
+
+} // namespace
+
+// Test that SyncErrorNotifier shows an notification if a passphrase is
+// required.
+TEST_F(SyncErrorNotifierTest, PassphraseNotification) {
+  ASSERT_FALSE(notification_ui_manager_->FindById(kNotificationId));
+
+  browser_sync::SyncBackendHost::Status status;
+  EXPECT_CALL(*service_, QueryDetailedSyncStatus(_))
+              .WillRepeatedly(Return(false));
+
+  EXPECT_CALL(*service_, IsPassphraseRequired())
+              .WillRepeatedly(Return(true));
+  EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
+              .WillRepeatedly(Return(true));
+  {
+    SCOPED_TRACE("Expected a notification for passphrase error");
+    VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE,
+                                  true /* signed in */,
+                                  true /* error */);
+  }
+
+  // Check that no notification is shown if there is no error.
+  EXPECT_CALL(*service_, IsPassphraseRequired())
+              .WillRepeatedly(Return(false));
+  EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
+              .WillRepeatedly(Return(false));
+  {
+    SCOPED_TRACE("Not expecting notification since no error exists");
+    VerifySyncErrorNotifierResult(GoogleServiceAuthError::NONE,
+                                  true /* signed in */,
+                                  false /* no error */);
+  }
+
+  // Check that no notification is shown if sync setup is not completed.
+  EXPECT_CALL(*service_, IsPassphraseRequired())
+              .WillRepeatedly(Return(true));
+  EXPECT_CALL(*service_, IsPassphraseRequiredForDecryption())
+              .WillRepeatedly(Return(true));
+  {
+    SCOPED_TRACE("Not expecting notification since sync setup is incomplete");
+    VerifySyncErrorNotifierResult(
+        GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
+        false /* not signed in */,
+        false /* no error */);
+  }
+}
+
+}  // namespace test
+}  // namespace ash
diff --git a/chrome/browser/sync/sync_error_notifier_factory_ash.cc b/chrome/browser/sync/sync_error_notifier_factory_ash.cc
new file mode 100644
index 0000000..4548aca
--- /dev/null
+++ b/chrome/browser/sync/sync_error_notifier_factory_ash.cc
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/sync_error_notifier_factory_ash.h"
+
+#include "ash/shell.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/sync_error_notifier_ash.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+SyncErrorNotifierFactory::SyncErrorNotifierFactory()
+    : BrowserContextKeyedServiceFactory(
+        "SyncErrorNotifier",
+        BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(ProfileSyncServiceFactory::GetInstance());
+}
+
+SyncErrorNotifierFactory::~SyncErrorNotifierFactory() {}
+
+// static
+SyncErrorNotifier* SyncErrorNotifierFactory::GetForProfile(
+    Profile* profile) {
+  return static_cast<SyncErrorNotifier*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
+}
+
+// static
+SyncErrorNotifierFactory* SyncErrorNotifierFactory::GetInstance() {
+  return Singleton<SyncErrorNotifierFactory>::get();
+}
+
+KeyedService* SyncErrorNotifierFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  if (!ash::Shell::HasInstance())
+    return NULL;
+
+  Profile* profile = static_cast<Profile*>(context);
+  ProfileSyncService* profile_sync_service =
+      ProfileSyncServiceFactory::GetForProfile(profile);
+
+  if (!profile_sync_service)
+    return NULL;
+
+  SyncErrorController* sync_error_controller =
+      profile_sync_service->sync_error_controller();
+  if (!sync_error_controller)
+    return NULL;
+
+  return new SyncErrorNotifier(sync_error_controller, profile);
+}
diff --git a/chrome/browser/sync/sync_error_notifier_factory_ash.h b/chrome/browser/sync/sync_error_notifier_factory_ash.h
new file mode 100644
index 0000000..6149bc4
--- /dev/null
+++ b/chrome/browser/sync/sync_error_notifier_factory_ash.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_SYNC_ERROR_NOTIFIER_FACTORY_ASH_H_
+#define CHROME_BROWSER_SYNC_SYNC_ERROR_NOTIFIER_FACTORY_ASH_H_
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class SyncErrorNotifier;
+class Profile;
+
+// Singleton that owns all SyncErrorNotifiers and associates them with
+// Profiles. Listens for the Profile's destruction notification and cleans up
+// the associated SyncErrorNotifier.
+class SyncErrorNotifierFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  // Returns the instance of SyncErrorNotifier associated with this profile,
+  // creating one if none exists and the shell exists.
+  static SyncErrorNotifier* GetForProfile(Profile* profile);
+
+  // Returns an instance of the SyncErrorNotifierFactory singleton.
+  static SyncErrorNotifierFactory* GetInstance();
+
+ private:
+  friend struct DefaultSingletonTraits<SyncErrorNotifierFactory>;
+
+  SyncErrorNotifierFactory();
+  virtual ~SyncErrorNotifierFactory();
+
+  // BrowserContextKeyedServiceFactory:
+  virtual KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* profile) const OVERRIDE;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncErrorNotifierFactory);
+};
+
+#endif  // CHROME_BROWSER_SYNC_SYNC_ERROR_NOTIFIER_FACTORY_ASH_H_
diff --git a/chrome/browser/sync/sync_global_error.cc b/chrome/browser/sync/sync_global_error.cc
index d6da1fb..969cccf 100644
--- a/chrome/browser/sync/sync_global_error.cc
+++ b/chrome/browser/sync/sync_global_error.cc
@@ -6,7 +6,6 @@
 
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/browser/sync/sync_ui_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -21,16 +20,26 @@
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
-SyncGlobalError::SyncGlobalError(ProfileSyncService* service,
-                                 SigninManagerBase* signin)
-    : service_(service),
-      signin_(signin) {
+SyncGlobalError::SyncGlobalError(SyncErrorController* error_controller,
+                                 ProfileSyncService* profile_sync_service)
+    : error_controller_(error_controller),
+      service_(profile_sync_service) {
   DCHECK(service_);
-  DCHECK(signin_);
-  OnStateChanged();
+  error_controller_->AddObserver(this);
+  GlobalErrorServiceFactory::GetForProfile(service_->profile())->
+      AddGlobalError(this);
 }
 
 SyncGlobalError::~SyncGlobalError() {
+  DCHECK(!error_controller_)
+      << "SigninGlobalError::Shutdown() was not called";
+}
+
+void SyncGlobalError::Shutdown() {
+  GlobalErrorServiceFactory::GetForProfile(service_->profile())->
+      RemoveGlobalError(this);
+  error_controller_->RemoveObserver(this);
+  error_controller_ = NULL;
 }
 
 bool SyncGlobalError::HasMenuItem() {
@@ -87,12 +96,12 @@
   NOTREACHED();
 }
 
-void SyncGlobalError::OnStateChanged() {
+void SyncGlobalError::OnErrorChanged() {
   base::string16 menu_label;
   base::string16 bubble_message;
   base::string16 bubble_accept_label;
   sync_ui_util::GetStatusLabelsForSyncGlobalError(
-      service_, *signin_, &menu_label, &bubble_message, &bubble_accept_label);
+      service_, &menu_label, &bubble_message, &bubble_accept_label);
 
   // All the labels should be empty or all of them non-empty.
   DCHECK((menu_label.empty() && bubble_message.empty() &&
diff --git a/chrome/browser/sync/sync_global_error.h b/chrome/browser/sync/sync_global_error.h
index 5437e0f..b240869 100644
--- a/chrome/browser/sync/sync_global_error.h
+++ b/chrome/browser/sync/sync_global_error.h
@@ -7,25 +7,29 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "chrome/browser/sync/profile_sync_service_observer.h"
+#include "chrome/browser/sync/sync_error_controller.h"
 #include "chrome/browser/ui/global_error/global_error.h"
+#include "components/keyed_service/core/keyed_service.h"
 
 class ProfileSyncService;
-class SigninManagerBase;
 
-// Shows sync errors on the wrench menu using a bubble view and a
-// menu item.
+// Shows sync errors on the wrench menu using a bubble view and a menu item.
 class SyncGlobalError : public GlobalErrorWithStandardBubble,
-                        public ProfileSyncServiceObserver {
+                        public SyncErrorController::Observer,
+                        public KeyedService {
  public:
-  SyncGlobalError(ProfileSyncService* service, SigninManagerBase* signin);
+  SyncGlobalError(SyncErrorController* error_controller,
+                  ProfileSyncService* profile_sync_service);
   virtual ~SyncGlobalError();
 
+  // KeyedService:
+  virtual void Shutdown() OVERRIDE;
+
+  // GlobalErrorWithStandardBubble:
   virtual bool HasMenuItem() OVERRIDE;
   virtual int MenuItemCommandID() OVERRIDE;
   virtual base::string16 MenuItemLabel() OVERRIDE;
   virtual void ExecuteMenuItem(Browser* browser) OVERRIDE;
-
   virtual bool HasBubbleView() OVERRIDE;
   virtual base::string16 GetBubbleViewTitle() OVERRIDE;
   virtual std::vector<base::string16> GetBubbleViewMessages() OVERRIDE;
@@ -35,15 +39,19 @@
   virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE;
   virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE;
 
-  // ProfileSyncServiceObserver implementation.
-  virtual void OnStateChanged() OVERRIDE;
+  // SyncErrorController::Observer:
+  virtual void OnErrorChanged() OVERRIDE;
 
  private:
   base::string16 bubble_accept_label_;
   base::string16 bubble_message_;
   base::string16 menu_label_;
-  ProfileSyncService* service_;
-  SigninManagerBase* signin_;
+
+  // The error controller to query for error details. Owned by the
+  // ProfileSyncService this SyncGlobalError depends on.
+  SyncErrorController* error_controller_;
+
+  const ProfileSyncService* service_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncGlobalError);
 };
diff --git a/chrome/browser/sync/sync_global_error_factory.cc b/chrome/browser/sync/sync_global_error_factory.cc
new file mode 100644
index 0000000..0d0d571
--- /dev/null
+++ b/chrome/browser/sync/sync_global_error_factory.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/sync_global_error_factory.h"
+
+#include "ash/shell.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/sync_global_error.h"
+#include "chrome/browser/ui/global_error/global_error_service_factory.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+#if defined(USE_ASH)
+#include "ash/shell.h"
+#endif
+
+SyncGlobalErrorFactory::SyncGlobalErrorFactory()
+    : BrowserContextKeyedServiceFactory(
+        "SyncGlobalError",
+        BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(ProfileSyncServiceFactory::GetInstance());
+  DependsOn(GlobalErrorServiceFactory::GetInstance());
+}
+
+SyncGlobalErrorFactory::~SyncGlobalErrorFactory() {}
+
+// static
+SyncGlobalError* SyncGlobalErrorFactory::GetForProfile(
+    Profile* profile) {
+  return static_cast<SyncGlobalError*>(
+      GetInstance()->GetServiceForBrowserContext(profile, true));
+}
+
+// static
+SyncGlobalErrorFactory* SyncGlobalErrorFactory::GetInstance() {
+  return Singleton<SyncGlobalErrorFactory>::get();
+}
+
+KeyedService* SyncGlobalErrorFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+#if defined(USE_ASH)
+  if (ash::Shell::HasInstance())
+    return NULL;
+#endif
+
+  Profile* profile = static_cast<Profile*>(context);
+  ProfileSyncService* profile_sync_service =
+      ProfileSyncServiceFactory::GetForProfile(profile);
+
+  if (!profile_sync_service)
+    return NULL;
+
+  SyncErrorController* sync_error_controller =
+      profile_sync_service->sync_error_controller();
+  if (!sync_error_controller)
+    return NULL;
+
+  return new SyncGlobalError(sync_error_controller,
+                             profile_sync_service);
+}
diff --git a/chrome/browser/sync/sync_global_error_factory.h b/chrome/browser/sync/sync_global_error_factory.h
new file mode 100644
index 0000000..5a78683
--- /dev/null
+++ b/chrome/browser/sync/sync_global_error_factory.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_SYNC_GLOBAL_ERROR_FACTORY_H_
+#define CHROME_BROWSER_SYNC_SYNC_GLOBAL_ERROR_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class SyncGlobalError;
+class Profile;
+
+// Singleton that owns all SyncGlobalErrors and associates them with
+// Profiles. Listens for the Profile's destruction notification and cleans up
+// the associated SyncGlobalError.
+class SyncGlobalErrorFactory : public BrowserContextKeyedServiceFactory {
+ public:
+  // Returns the instance of SyncGlobalError associated with this profile,
+  // creating one if none exists. In Ash, this will return NULL.
+  static SyncGlobalError* GetForProfile(Profile* profile);
+
+  // Returns an instance of the SyncGlobalErrorFactory singleton.
+  static SyncGlobalErrorFactory* GetInstance();
+
+ private:
+  friend struct DefaultSingletonTraits<SyncGlobalErrorFactory>;
+
+  SyncGlobalErrorFactory();
+  virtual ~SyncGlobalErrorFactory();
+
+  // BrowserContextKeyedServiceFactory:
+  virtual KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* profile) const OVERRIDE;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncGlobalErrorFactory);
+};
+
+#endif  // CHROME_BROWSER_SYNC_SYNC_GLOBAL_ERROR_FACTORY_H_
diff --git a/chrome/browser/sync/sync_global_error_unittest.cc b/chrome/browser/sync/sync_global_error_unittest.cc
index b35399e..2d7498b 100644
--- a/chrome/browser/sync/sync_global_error_unittest.cc
+++ b/chrome/browser/sync/sync_global_error_unittest.cc
@@ -4,19 +4,18 @@
 
 #include "chrome/browser/sync/sync_global_error.h"
 
-#include "base/basictypes.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/app/chrome_command_ids.h"
-#include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/sync/profile_sync_service_mock.h"
+#include "chrome/browser/sync/sync_error_controller.h"
+#include "chrome/browser/sync/sync_global_error_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 #include "chrome/test/base/browser_with_test_window_test.h"
 #include "chrome/test/base/testing_profile.h"
-#include "content/public/test/test_browser_thread.h"
-#include "testing/gmock/include/gmock/gmock-actions.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_source.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -24,7 +23,6 @@
 using ::testing::Return;
 using ::testing::ReturnRef;
 using ::testing::_;
-using content::BrowserThread;
 
 namespace {
 
@@ -62,16 +60,27 @@
   SyncGlobalErrorTest() {}
   virtual ~SyncGlobalErrorTest() {}
 
+  virtual void SetUp() OVERRIDE {
+    profile_.reset(ProfileSyncServiceMock::MakeSignedInTestingProfile());
+
+    BrowserWithTestWindowTest::SetUp();
+  }
+
+  Profile* profile() { return profile_.get(); }
+
  private:
+  scoped_ptr<TestingProfile> profile_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncGlobalErrorTest);
 };
 
-// Utility function to test that SyncGlobalError behaves correct for the given
+// Utility function to test that SyncGlobalError behaves correctly for the given
 // error condition.
 void VerifySyncGlobalErrorResult(NiceMock<ProfileSyncServiceMock>* service,
                                  FakeLoginUIService* login_ui_service,
                                  Browser* browser,
-                                 SyncGlobalError* error,
+                                 SyncErrorController* error,
+                                 SyncGlobalError* global_error,
                                  GoogleServiceAuthError::State error_state,
                                  bool is_signed_in,
                                  bool is_error) {
@@ -82,54 +91,47 @@
   EXPECT_CALL(*service, GetAuthError()).WillRepeatedly(ReturnRef(auth_error));
 
   error->OnStateChanged();
+  EXPECT_EQ(is_error, error->HasError());
 
   // If there is an error then a menu item and bubble view should be shown.
-  EXPECT_EQ(error->HasMenuItem(), is_error);
-  EXPECT_EQ(error->HasBubbleView(), is_error);
+  EXPECT_EQ(is_error, global_error->HasMenuItem());
+  EXPECT_EQ(is_error, global_error->HasBubbleView());
 
   // If there is an error then labels should not be empty.
-  EXPECT_NE(error->MenuItemCommandID(), 0);
-  EXPECT_NE(error->MenuItemLabel().empty(), is_error);
-  EXPECT_NE(error->GetBubbleViewAcceptButtonLabel().empty(), is_error);
+  EXPECT_NE(0, global_error->MenuItemCommandID());
+  EXPECT_NE(is_error, global_error->MenuItemLabel().empty());
+  EXPECT_NE(is_error, global_error->GetBubbleViewAcceptButtonLabel().empty());
 
   // We never have a cancel button.
-  EXPECT_TRUE(error->GetBubbleViewCancelButtonLabel().empty());
+  EXPECT_TRUE(global_error->GetBubbleViewCancelButtonLabel().empty());
   // We always return a hardcoded title.
-  EXPECT_FALSE(error->GetBubbleViewTitle().empty());
+  EXPECT_FALSE(global_error->GetBubbleViewTitle().empty());
 
-  // TODO(altimofeev): Implement this for ChromeOS in a way that doesn't involve
-  //                   subclassing Browser or using GMock on browser/ui types
-  //                   which is banned. Consider observing
-  //                   NOTIFICATION_APP_TERMINATING instead.
-  //                   http://crbug.com/134675
-#if !defined(OS_CHROMEOS)
   // Test message handler.
   if (is_error) {
     FakeLoginUI* login_ui = static_cast<FakeLoginUI*>(
         login_ui_service->current_login_ui());
-    error->ExecuteMenuItem(browser);
+    global_error->ExecuteMenuItem(browser);
     ASSERT_GT(login_ui->focus_ui_call_count(), 0);
-    error->BubbleViewAcceptButtonPressed(browser);
-    error->BubbleViewDidClose(browser);
+    global_error->BubbleViewAcceptButtonPressed(browser);
+    global_error->BubbleViewDidClose(browser);
   }
-#endif
 }
 
 } // namespace
 
 // Test that SyncGlobalError shows an error if a passphrase is required.
 TEST_F(SyncGlobalErrorTest, PassphraseGlobalError) {
-  scoped_ptr<Profile> profile(
-      ProfileSyncServiceMock::MakeSignedInTestingProfile());
-  NiceMock<ProfileSyncServiceMock> service(profile.get());
-  SigninManagerBase* signin =
-      SigninManagerFactory::GetForProfile(profile.get());
+  NiceMock<ProfileSyncServiceMock> service(profile());
+
   FakeLoginUIService* login_ui_service = static_cast<FakeLoginUIService*>(
       LoginUIServiceFactory::GetInstance()->SetTestingFactoryAndUse(
-          profile.get(), BuildMockLoginUIService));
+          profile(), BuildMockLoginUIService));
   FakeLoginUI login_ui;
   login_ui_service->SetLoginUI(&login_ui);
-  SyncGlobalError error(&service, signin);
+
+  SyncErrorController error(&service);
+  SyncGlobalError global_error(&error, &service);
 
   browser_sync::SyncBackendHost::Status status;
   EXPECT_CALL(service, QueryDetailedSyncStatus(_))
@@ -140,6 +142,27 @@
   EXPECT_CALL(service, IsPassphraseRequiredForDecryption())
               .WillRepeatedly(Return(true));
   VerifySyncGlobalErrorResult(
-      &service, login_ui_service, browser(), &error,
-      GoogleServiceAuthError::NONE, true, true);
+      &service, login_ui_service, browser(), &error, &global_error,
+      GoogleServiceAuthError::NONE, true /* signed in*/, true /* error */);
+
+  // Check that no menu item is shown if there is no error.
+  EXPECT_CALL(service, IsPassphraseRequired())
+              .WillRepeatedly(Return(false));
+  EXPECT_CALL(service, IsPassphraseRequiredForDecryption())
+              .WillRepeatedly(Return(false));
+  VerifySyncGlobalErrorResult(
+      &service, login_ui_service, browser(), &error, &global_error,
+      GoogleServiceAuthError::NONE, true /* signed in */, false /* no error */);
+
+  // Check that no menu item is shown if sync setup is not completed.
+  EXPECT_CALL(service, IsPassphraseRequired())
+              .WillRepeatedly(Return(true));
+  EXPECT_CALL(service, IsPassphraseRequiredForDecryption())
+              .WillRepeatedly(Return(true));
+  VerifySyncGlobalErrorResult(
+      &service, login_ui_service, browser(), &error, &global_error,
+      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
+      false /* not signed in */, false /* no error */);
+
+  global_error.Shutdown();
 }
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc
index cf9400f..d84eab8 100644
--- a/chrome/browser/sync/sync_ui_util.cc
+++ b/chrome/browser/sync/sync_ui_util.cc
@@ -12,7 +12,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_ui_util.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -23,8 +22,9 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
@@ -341,8 +341,8 @@
       service, signin, status_label, link_label);
 }
 
-void GetStatusLabelsForSyncGlobalError(ProfileSyncService* service,
-                                       const SigninManagerBase& signin,
+#if !defined(OS_CHROMEOS)
+void GetStatusLabelsForSyncGlobalError(const ProfileSyncService* service,
                                        base::string16* menu_label,
                                        base::string16* bubble_message,
                                        base::string16* bubble_accept_label) {
@@ -370,6 +370,7 @@
     return;
   }
 }
+#endif
 
 MessageType GetStatus(
     ProfileSyncService* service, const SigninManagerBase& signin) {
diff --git a/chrome/browser/sync/sync_ui_util.h b/chrome/browser/sync/sync_ui_util.h
index b856024..696f333 100644
--- a/chrome/browser/sync/sync_ui_util.h
+++ b/chrome/browser/sync/sync_ui_util.h
@@ -48,12 +48,13 @@
 
 // Gets various labels for the sync global error based on the sync error state.
 // |menu_item_label|, |bubble_message|, and |bubble_accept_label| must not be
-// NULL.
-void GetStatusLabelsForSyncGlobalError(ProfileSyncService* service,
-                                       const SigninManagerBase& signin,
+// NULL. Note that we don't use SyncGlobalError on Chrome OS.
+#if !defined(OS_CHROMEOS)
+void GetStatusLabelsForSyncGlobalError(const ProfileSyncService* service,
                                        base::string16* menu_item_label,
                                        base::string16* bubble_message,
                                        base::string16* bubble_accept_label);
+#endif
 
 MessageType GetStatus(ProfileSyncService* service,
                       const SigninManagerBase& signin);
diff --git a/chrome/browser/sync/sync_ui_util_unittest.cc b/chrome/browser/sync/sync_ui_util_unittest.cc
index 97f85fd..06c872d 100644
--- a/chrome/browser/sync/sync_ui_util_unittest.cc
+++ b/chrome/browser/sync/sync_ui_util_unittest.cc
@@ -6,13 +6,13 @@
 #include "base/basictypes.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/fake_auth_status_provider.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/sync/profile_sync_service_mock.h"
 #include "chrome/browser/sync/sync_ui_util.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "grit/generated_resources.h"
@@ -47,10 +47,10 @@
 
 const char kTestUser[] = "test_user@test.com";
 
+#if !defined(OS_CHROMEOS)
 // Utility function to test that GetStatusLabelsForSyncGlobalError returns
 // the correct results for the given states.
 void VerifySyncGlobalErrorResult(NiceMock<ProfileSyncServiceMock>* service,
-                                 const SigninManagerBase& signin,
                                  GoogleServiceAuthError::State error_state,
                                  bool is_signed_in,
                                  bool is_error) {
@@ -62,11 +62,12 @@
 
   base::string16 label1, label2, label3;
   sync_ui_util::GetStatusLabelsForSyncGlobalError(
-      service, signin, &label1, &label2, &label3);
+      service, &label1, &label2, &label3);
   EXPECT_EQ(label1.empty(), !is_error);
   EXPECT_EQ(label2.empty(), !is_error);
   EXPECT_EQ(label3.empty(), !is_error);
 }
+#endif
 
 } // namespace
 
@@ -76,13 +77,13 @@
   content::TestBrowserThreadBundle thread_bundle_;
 };
 
+#if !defined(OS_CHROMEOS)
 // Test that GetStatusLabelsForSyncGlobalError returns an error if a
 // passphrase is required.
 TEST_F(SyncUIUtilTest, PassphraseGlobalError) {
   scoped_ptr<Profile> profile(
       ProfileSyncServiceMock::MakeSignedInTestingProfile());
   NiceMock<ProfileSyncServiceMock> service(profile.get());
-  FakeSigninManagerBase signin;
   browser_sync::SyncBackendHost::Status status;
   EXPECT_CALL(service, QueryDetailedSyncStatus(_))
               .WillRepeatedly(Return(false));
@@ -91,8 +92,10 @@
   EXPECT_CALL(service, IsPassphraseRequiredForDecryption())
               .WillRepeatedly(Return(true));
 
-  VerifySyncGlobalErrorResult(
-      &service, signin, GoogleServiceAuthError::NONE, true, true);
+  VerifySyncGlobalErrorResult(&service,
+                              GoogleServiceAuthError::NONE,
+                              true /* signed in */,
+                              true /* error */);
 }
 
 // Test that GetStatusLabelsForSyncGlobalError returns an error if a
@@ -101,7 +104,6 @@
   scoped_ptr<Profile> profile(
       ProfileSyncServiceMock::MakeSignedInTestingProfile());
   NiceMock<ProfileSyncServiceMock> service(profile.get());
-  FakeSigninManagerBase signin;
   browser_sync::SyncBackendHost::Status status;
   EXPECT_CALL(service, QueryDetailedSyncStatus(_))
               .WillRepeatedly(Return(false));
@@ -118,7 +120,7 @@
   EXPECT_CALL(service, GetAuthError()).WillRepeatedly(ReturnRef(auth_error));
   base::string16 menu_label, label2, label3;
   sync_ui_util::GetStatusLabelsForSyncGlobalError(
-      &service, signin, &menu_label, &label2, &label3);
+      &service, &menu_label, &label2, &label3);
   // Make sure we are still displaying the passphrase error badge (don't show
   // auth errors through SyncUIUtil).
   EXPECT_EQ(menu_label, l10n_util::GetStringUTF16(
@@ -150,12 +152,19 @@
     GoogleServiceAuthError::HOSTED_NOT_ALLOWED
   };
 
-  FakeSigninManagerBase signin;
+  FakeSigninManagerBase signin(profile.get());
   for (size_t i = 0; i < arraysize(table); ++i) {
-    VerifySyncGlobalErrorResult(&service, signin, table[i], true, false);
-    VerifySyncGlobalErrorResult(&service, signin, table[i], false, false);
+    VerifySyncGlobalErrorResult(&service,
+                                table[i],
+                                true /* signed in */,
+                                false /* no error */);
+    VerifySyncGlobalErrorResult(&service,
+                                table[i],
+                                false /* not signed in */,
+                                false /* no error */);
   }
 }
+#endif
 
 // TODO(tim): This shouldn't be required. r194857 removed the
 // AuthInProgress override from FakeSigninManager, which meant this test started
@@ -168,7 +177,7 @@
 class FakeSigninManagerForSyncUIUtilTest : public FakeSigninManagerBase {
  public:
   explicit FakeSigninManagerForSyncUIUtilTest(Profile* profile)
-      : auth_in_progress_(false) {
+      : FakeSigninManagerBase(profile), auth_in_progress_(false) {
     Initialize(profile, NULL);
   }
 
diff --git a/chrome/browser/sync/test/integration/cross_platform_sync_test.cc b/chrome/browser/sync/test/integration/cross_platform_sync_test.cc
index 432a90f..e46ce1a 100644
--- a/chrome/browser/sync/test/integration/cross_platform_sync_test.cc
+++ b/chrome/browser/sync/test/integration/cross_platform_sync_test.cc
@@ -5,10 +5,12 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
 using bookmarks_helper::AddURL;
 using bookmarks_helper::ModelMatchesVerifier;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 // These tests are run on the Chrome on iOS buildbots as part of cross-platform
 // sync integration tests, and are not meant to be run on the chromium
@@ -26,6 +28,6 @@
 IN_PROC_BROWSER_TEST_F(CrossPlatformSyncTest, DISABLED_AddBookmark) {
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
   ASSERT_TRUE(AddURL(0, L"Google", GURL("http://www.google.co.uk")));
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 }
diff --git a/chrome/browser/sync/test/integration/enable_disable_test.cc b/chrome/browser/sync/test/integration/enable_disable_test.cc
index 88f5583..2f8f925 100644
--- a/chrome/browser/sync/test/integration/enable_disable_test.cc
+++ b/chrome/browser/sync/test/integration/enable_disable_test.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "sync/internal_api/public/base/model_type.h"
@@ -13,17 +14,11 @@
 
 namespace {
 
-class EnableDisableTest : public SyncTest {
+class EnableDisableSingleClientTest : public SyncTest {
  public:
-  explicit EnableDisableTest(TestType test_type) : SyncTest(test_type) {}
-  virtual ~EnableDisableTest() {}
- private:
-  DISALLOW_COPY_AND_ASSIGN(EnableDisableTest);
-};
-
-class EnableDisableSingleClientTest : public EnableDisableTest {
- public:
-  EnableDisableSingleClientTest() : EnableDisableTest(SINGLE_CLIENT) {}
+  // TODO(pvalenzuela): Switch to SINGLE_CLIENT once FakeServer
+  // supports this scenario.
+  EnableDisableSingleClientTest() : SyncTest(SINGLE_CLIENT_LEGACY) {}
   virtual ~EnableDisableSingleClientTest() {}
  private:
   DISALLOW_COPY_AND_ASSIGN(EnableDisableSingleClientTest);
diff --git a/chrome/browser/sync/test/integration/migration_test.cc b/chrome/browser/sync/test/integration/migration_test.cc
index 58ca300..cd3372b 100644
--- a/chrome/browser/sync/test/integration/migration_test.cc
+++ b/chrome/browser/sync/test/integration/migration_test.cc
@@ -7,6 +7,7 @@
 #include "base/prefs/scoped_user_pref_update.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/backend_migrator.h"
+#include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/preferences_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
@@ -135,9 +136,9 @@
                << syncer::ModelTypeSetToString(migrated_types_);
     }
 
-    // Nudge ProfileSyncServiceHarness to inspect the exit condition provided by
-    // AwaitMigration.
-    harness_->OnStateChanged();
+    // Manually trigger a check of the exit condition.
+    if (!expected_types_.Empty())
+      OnStateChanged();
   }
 
  private:
@@ -237,8 +238,8 @@
     for (int i = 0; i < num_clients(); ++i) {
       MigrationChecker* checker = migration_checkers_[i];
       checker->set_expected_types(migrate_types);
-      if (!checker->IsExitConditionSatisfied())
-        ASSERT_TRUE(GetClient(i)->AwaitStatusChange(checker));
+      checker->Await();
+      ASSERT_FALSE(checker->TimedOut());
     }
   }
 
diff --git a/chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h b/chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h
index 43da601..8a29622 100644
--- a/chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h
+++ b/chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_P2P_INVALIDATION_FORWARDER_H_
 #define CHROME_BROWSER_SYNC_TEST_INTEGRATION_P2P_INVALIDATION_FORWARDER_H_
 
+#include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
 
@@ -35,6 +36,8 @@
  private:
   ProfileSyncService* sync_service_;
   invalidation::P2PInvalidationService* invalidation_service_;
+
+  DISALLOW_COPY_AND_ASSIGN(P2PInvalidationForwarder);
 };
 
 #endif  // CHROME_BROWSER_SYNC_TEST_INTEGRATION_P2P_INVALIDATION_FORWARDER_H_
diff --git a/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc b/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc
index 6993191..0ef29a9 100644
--- a/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc
+++ b/chrome/browser/sync/test/integration/performance/sync_timing_helper.cc
@@ -7,8 +7,11 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
+
 SyncTimingHelper::SyncTimingHelper() {}
 
 SyncTimingHelper::~SyncTimingHelper() {}
@@ -17,7 +20,7 @@
 base::TimeDelta SyncTimingHelper::TimeSyncCycle(
     ProfileSyncServiceHarness* client) {
   base::Time start = base::Time::Now();
-  EXPECT_TRUE(client->AwaitCommitActivityCompletion());
+  EXPECT_TRUE(AwaitCommitActivityCompletion(client->service()));
   return base::Time::Now() - start;
 }
 
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
index cd60324..2e953ec 100644
--- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
+++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -7,141 +7,99 @@
 #include <cstddef>
 #include <iterator>
 #include <ostream>
-#include <set>
 #include <sstream>
 #include <vector>
 
-#include "base/bind.h"
-#include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/json/json_writer.h"
-#include "base/location.h"
 #include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/prefs/pref_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/invalidation/p2p_invalidation_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/sync/about_sync_util.h"
-#include "chrome/browser/sync/backend_migrator.h"
+#include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
-#include "chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h"
 #include "chrome/browser/sync/test/integration/quiesce_status_change_checker.h"
 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
-#include "chrome/browser/sync/test/integration/status_change_checker.h"
-#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "components/sync_driver/data_type_controller.h"
-#include "content/public/browser/notification_service.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "sync/internal_api/public/base/progress_marker_map.h"
-#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
 #include "sync/internal_api/public/util/sync_string_conversions.h"
 
 #if defined(ENABLE_MANAGED_USERS)
 #include "chrome/browser/managed_mode/managed_user_constants.h"
 #endif
 
-using invalidation::P2PInvalidationService;
 using syncer::sessions::SyncSessionSnapshot;
 
-// The amount of time for which we wait for a sync operation to complete.
-// TODO(sync): This timeout must eventually be made less than the default 45
-// second timeout for integration tests so that in case a sync operation times
-// out, it is able to log a useful failure message before the test is killed.
-static const int kSyncOperationTimeoutMs = 45000;
-
 namespace {
 
-// Checks if a desired change in the state of the sync engine has taken place by
-// running the callback passed to it.
-class CallbackStatusChecker : public SingleClientStatusChangeChecker {
- public:
-  CallbackStatusChecker(ProfileSyncService* service,
-                        base::Callback<bool()> callback,
-                        const std::string& debug_message)
-      : SingleClientStatusChangeChecker(service),
-        callback_(callback),
-        debug_message_(debug_message) {
-  }
+bool HasAuthError(ProfileSyncService* service) {
+  return service->GetAuthError().state() ==
+             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
+         service->GetAuthError().state() ==
+             GoogleServiceAuthError::SERVICE_ERROR ||
+         service->GetAuthError().state() ==
+             GoogleServiceAuthError::REQUEST_CANCELED;
+}
 
-  virtual ~CallbackStatusChecker() {
-  }
+class BackendInitializeChecker : public SingleClientStatusChangeChecker {
+ public:
+  explicit BackendInitializeChecker(ProfileSyncService* service)
+      : SingleClientStatusChangeChecker(service) {}
 
   virtual bool IsExitConditionSatisfied() OVERRIDE {
-    return callback_.Run();
+    if (service()->sync_initialized())
+      return true;
+    // Backend initialization is blocked by an auth error.
+    if (HasAuthError(service()))
+      return true;
+    // Backend initialization is blocked by a failure to fetch Oauth2 tokens.
+    if (service()->IsRetryingAccessTokenFetchForTest())
+      return true;
+    // Still waiting on backend initialization.
+    return false;
   }
 
   virtual std::string GetDebugMessage() const OVERRIDE {
-    return debug_message_;
+    return "Backend Initialize";
   }
-
- private:
-  // Callback that evaluates whether the condition we are waiting on has been
-  // satisfied.
-  base::Callback<bool()> callback_;
-
-  const std::string debug_message_;
-
-  DISALLOW_COPY_AND_ASSIGN(CallbackStatusChecker);
 };
 
-// Helper function which returns true if the sync backend has been initialized,
-// or if backend initialization was blocked for some reason.
-bool DoneWaitingForBackendInitialization(
-    const ProfileSyncServiceHarness* harness) {
-  DCHECK(harness);
-  // Backend is initialized.
-  if (harness->service()->sync_initialized())
-    return true;
-  // Backend initialization is blocked by an auth error.
-  if (harness->HasAuthError())
-    return true;
-  // Backend initialization is blocked by a failure to fetch Oauth2 tokens.
-  if (harness->service()->IsRetryingAccessTokenFetchForTest())
-    return true;
-  // Still waiting on backend initialization.
-  return false;
-}
+class SyncSetupChecker : public SingleClientStatusChangeChecker {
+ public:
+  explicit SyncSetupChecker(ProfileSyncService* service)
+      : SingleClientStatusChangeChecker(service) {}
 
-// Helper function which returns true if sync setup is complete, or in case
-// it is blocked for some reason.
-bool DoneWaitingForSyncSetup(const ProfileSyncServiceHarness* harness) {
-  DCHECK(harness);
-  // Sync setup is complete, and the client is ready to sync new changes.
-  if (harness->ServiceIsPushingChanges())
-    return true;
-  // Sync is blocked because a custom passphrase is required.
-  if (harness->service()->passphrase_required_reason() ==
-      syncer::REASON_DECRYPTION) {
-    return true;
+  virtual bool IsExitConditionSatisfied() OVERRIDE {
+    // Sync setup is complete, and the client is ready to sync new changes.
+    if (service()->ShouldPushChanges())
+      return true;
+    // Sync is blocked because a custom passphrase is required.
+    if (service()->passphrase_required_reason() == syncer::REASON_DECRYPTION)
+      return true;
+    // Sync is blocked by an auth error.
+    if (HasAuthError(service()))
+      return true;
+    // Still waiting on sync setup.
+    return false;
   }
-  // Sync is blocked by an auth error.
-  if (harness->HasAuthError())
-    return true;
-  // Still waiting on sync setup.
-  return false;
-}
 
-// Helper function which returns true if the sync client requires a custom
-// passphrase to be entered for decryption.
-bool IsPassphraseRequired(const ProfileSyncServiceHarness* harness) {
-  DCHECK(harness);
-  return harness->service()->IsPassphraseRequired();
-}
+  virtual std::string GetDebugMessage() const OVERRIDE {
+    return "Sync Setup";
+  }
+};
 
-// Helper function which returns true if the custom passphrase entered was
-// accepted.
-bool IsPassphraseAccepted(const ProfileSyncServiceHarness* harness) {
-  DCHECK(harness);
-  return (!harness->service()->IsPassphraseRequired() &&
-          harness->service()->IsUsingSecondaryPassphrase());
+bool AwaitSyncSetupCompletion(ProfileSyncService* service) {
+  SyncSetupChecker checker(service);
+  checker.Await();
+  return !checker.TimedOut();
 }
 
 }  // namespace
@@ -151,36 +109,19 @@
     Profile* profile,
     const std::string& username,
     const std::string& password) {
-  return new ProfileSyncServiceHarness(profile, username, password, NULL);
-}
-
-// static
-ProfileSyncServiceHarness* ProfileSyncServiceHarness::CreateForIntegrationTest(
-    Profile* profile,
-    const std::string& username,
-    const std::string& password,
-    P2PInvalidationService* p2p_invalidation_service) {
-  return new ProfileSyncServiceHarness(profile,
-                                       username,
-                                       password,
-                                       p2p_invalidation_service);
+  return new ProfileSyncServiceHarness(profile, username, password);
 }
 
 ProfileSyncServiceHarness::ProfileSyncServiceHarness(
     Profile* profile,
     const std::string& username,
-    const std::string& password,
-    P2PInvalidationService* p2p_invalidation_service)
+    const std::string& password)
     : profile_(profile),
       service_(ProfileSyncServiceFactory::GetForProfile(profile)),
       username_(username),
       password_(password),
       oauth2_refesh_token_number_(0),
-      profile_debug_name_(profile->GetDebugName()),
-      status_change_checker_(NULL) {
-  // Start listening for and emitting notifications of commits.
-  p2p_invalidation_forwarder_.reset(
-      new P2PInvalidationForwarder(service_, p2p_invalidation_service));
+      profile_debug_name_(profile->GetDebugName()) {
 }
 
 ProfileSyncServiceHarness::~ProfileSyncServiceHarness() { }
@@ -217,11 +158,7 @@
 
   // Authenticate sync client using GAIA credentials.
   service()->signin()->SetAuthenticatedUsername(username_);
-  GoogleServiceSigninSuccessDetails details(username_, password_);
-  content::NotificationService::current()->Notify(
-      chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-      content::Source<Profile>(profile_),
-      content::Details<const GoogleServiceSigninSuccessDetails>(&details));
+  service()->GoogleSigninSucceeded(username_, password_);
 
 #if defined(ENABLE_MANAGED_USERS)
   std::string account_id = profile_->IsManaged() ?
@@ -234,10 +171,15 @@
       UpdateCredentials(account_id, GenerateFakeOAuth2RefreshTokenString());
 
   // Wait for the OnBackendInitialized() callback.
-  if (!AwaitBackendInitialized()) {
-    LOG(ERROR) << "OnBackendInitialized() not seen after "
-               << kSyncOperationTimeoutMs / 1000
-               << " seconds.";
+  BackendInitializeChecker checker(service());
+  checker.Await();
+
+  if (checker.TimedOut()) {
+    LOG(ERROR) << "OnBackendInitialized() timed out.";
+    return false;
+  }
+
+  if (!service()->sync_initialized()) {
     return false;
   }
 
@@ -249,7 +191,7 @@
   }
 
   // Make sure that initial sync wasn't blocked by rejected credentials.
-  if (HasAuthError()) {
+  if (HasAuthError(service())) {
     LOG(ERROR) << "Credentials were rejected. Sync cannot proceed.";
     return false;
   }
@@ -276,10 +218,8 @@
 
   // Wait for initial sync cycle to be completed.
   DCHECK(service()->sync_initialized());
-  if (!AwaitSyncSetupCompletion()) {
-    LOG(ERROR) << "Initial sync cycle did not complete after "
-               << kSyncOperationTimeoutMs / 1000
-               << " seconds.";
+  if (!AwaitSyncSetupCompletion(service())) {
+    LOG(ERROR) << "Initial sync cycle timed out.";
     return false;
   }
 
@@ -300,82 +240,6 @@
   return true;
 }
 
-void ProfileSyncServiceHarness::QuitMessageLoop() {
-  base::MessageLoop::current()->QuitWhenIdle();
-}
-
-void ProfileSyncServiceHarness::OnStateChanged() {
-  if (!status_change_checker_)
-    return;
-
-  DVLOG(1) << GetClientInfoString(status_change_checker_->GetDebugMessage());
-  if (status_change_checker_->IsExitConditionSatisfied())
-    QuitMessageLoop();
-}
-
-void ProfileSyncServiceHarness::OnSyncCycleCompleted() {
-  OnStateChanged();
-}
-
-bool ProfileSyncServiceHarness::AwaitPassphraseRequired() {
-  DVLOG(1) << GetClientInfoString("AwaitPassphraseRequired");
-  CallbackStatusChecker passphrase_required_checker(
-      service(),
-      base::Bind(&::IsPassphraseRequired, base::Unretained(this)),
-      "IsPassphraseRequired");
-  return AwaitStatusChange(&passphrase_required_checker);
-}
-
-bool ProfileSyncServiceHarness::AwaitPassphraseAccepted() {
-  CallbackStatusChecker passphrase_accepted_checker(
-      service(),
-      base::Bind(&::IsPassphraseAccepted, base::Unretained(this)),
-      "IsPassphraseAccepted");
-  bool return_value = AwaitStatusChange(&passphrase_accepted_checker);
-  if (return_value)
-    FinishSyncSetup();
-  return return_value;
-}
-
-bool ProfileSyncServiceHarness::AwaitBackendInitialized() {
-  DVLOG(1) << GetClientInfoString("AwaitBackendInitialized");
-  CallbackStatusChecker backend_initialized_checker(
-      service(),
-      base::Bind(&DoneWaitingForBackendInitialization,
-                 base::Unretained(this)),
-      "DoneWaitingForBackendInitialization");
-  AwaitStatusChange(&backend_initialized_checker);
-  return service()->sync_initialized();
-}
-
-// TODO(sync): As of today, we wait for a client to finish its commit activity
-// by checking if its progress markers are up to date. In future, once we have
-// an in-process C++ server, this function can be reimplemented without relying
-// on progress markers.
-bool ProfileSyncServiceHarness::AwaitCommitActivityCompletion() {
-  UpdatedProgressMarkerChecker progress_marker_checker(service());
-  return AwaitStatusChange(&progress_marker_checker);
-}
-
-bool ProfileSyncServiceHarness::AwaitSyncDisabled() {
-  DCHECK(service()->HasSyncSetupCompleted());
-  DCHECK(!IsSyncDisabled());
-  CallbackStatusChecker sync_disabled_checker(
-      service(),
-      base::Bind(&ProfileSyncServiceHarness::IsSyncDisabled,
-                 base::Unretained(this)),
-      "IsSyncDisabled");
-  return AwaitStatusChange(&sync_disabled_checker);
-}
-
-bool ProfileSyncServiceHarness::AwaitSyncSetupCompletion() {
-  CallbackStatusChecker sync_setup_complete_checker(
-      service(),
-      base::Bind(&DoneWaitingForSyncSetup, base::Unretained(this)),
-      "DoneWaitingForSyncSetup");
-  return AwaitStatusChange(&sync_setup_complete_checker);
-}
-
 bool ProfileSyncServiceHarness::AwaitMutualSyncCycleCompletion(
     ProfileSyncServiceHarness* partner) {
   std::vector<ProfileSyncServiceHarness*> harnesses;
@@ -402,48 +266,8 @@
     services.push_back((*it)->service());
   }
   QuiesceStatusChangeChecker checker(services);
-  return clients[0]->AwaitStatusChange(&checker);
-}
-
-bool ProfileSyncServiceHarness::AwaitStatusChange(
-    StatusChangeChecker* checker) {
-  DVLOG(1) << GetClientInfoString("AwaitStatusChange");
-
-  DCHECK(checker);
-  if (checker->IsExitConditionSatisfied()) {
-    DVLOG(1) << GetClientInfoString("AwaitStatusChange exiting early because "
-                                    "condition is already satisfied");
-    return true;
-  }
-
-  DCHECK(status_change_checker_ == NULL);
-  status_change_checker_ = checker;
-  status_change_checker_->InitObserver(this);
-
-  base::OneShotTimer<ProfileSyncServiceHarness> timer;
-  timer.Start(FROM_HERE,
-              base::TimeDelta::FromMilliseconds(kSyncOperationTimeoutMs),
-              base::Bind(&ProfileSyncServiceHarness::QuitMessageLoop,
-                         base::Unretained(this)));
-  {
-    base::MessageLoop* loop = base::MessageLoop::current();
-    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
-    loop->Run();
-  }
-
-  status_change_checker_->UninitObserver(this);
-  status_change_checker_ = NULL;
-
-  if (timer.IsRunning()) {
-    DVLOG(1) << GetClientInfoString("AwaitStatusChange succeeded");
-    return true;
-  } else {
-    LOG(ERROR) << GetClientInfoString(base::StringPrintf(
-        "AwaitStatusChange called from %s timed out",
-        checker->GetDebugMessage().c_str()));
-    CHECK(false) << "Ending test because of timeout.";
-    return false;
-  }
+  checker.Await();
+  return !checker.TimedOut();
 }
 
 std::string ProfileSyncServiceHarness::GenerateFakeOAuth2RefreshTokenString() {
@@ -451,36 +275,16 @@
                             ++oauth2_refesh_token_number_);
 }
 
-ProfileSyncService::Status ProfileSyncServiceHarness::GetStatus() const {
-  DCHECK(service() != NULL) << "GetStatus(): service() is NULL.";
-  ProfileSyncService::Status result;
-  service()->QueryDetailedSyncStatus(&result);
-  return result;
-}
-
 bool ProfileSyncServiceHarness::IsSyncDisabled() const {
   return !service()->setup_in_progress() &&
          !service()->HasSyncSetupCompleted();
 }
 
-bool ProfileSyncServiceHarness::HasAuthError() const {
-  return service()->GetAuthError().state() ==
-             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS ||
-         service()->GetAuthError().state() ==
-             GoogleServiceAuthError::SERVICE_ERROR ||
-         service()->GetAuthError().state() ==
-             GoogleServiceAuthError::REQUEST_CANCELED;
-}
-
 void ProfileSyncServiceHarness::FinishSyncSetup() {
   service()->SetSetupInProgress(false);
   service()->SetSyncSetupCompleted();
 }
 
-bool ProfileSyncServiceHarness::AutoStartEnabled() {
-  return service()->auto_start_enabled();
-}
-
 SyncSessionSnapshot ProfileSyncServiceHarness::GetLastSessionSnapshot() const {
   DCHECK(service() != NULL) << "Sync service has not yet been set up.";
   if (service()->sync_initialized()) {
@@ -513,7 +317,7 @@
 
   synced_datatypes.Put(syncer::ModelTypeFromInt(datatype));
   service()->OnUserChoseDatatypes(false, synced_datatypes);
-  if (AwaitSyncSetupCompletion()) {
+  if (AwaitSyncSetupCompletion(service())) {
     DVLOG(1) << "EnableSyncForDatatype(): Enabled sync for datatype "
              << syncer::ModelTypeToString(datatype)
              << " on " << profile_debug_name_ << ".";
@@ -546,7 +350,7 @@
   synced_datatypes.RetainAll(syncer::UserSelectableTypes());
   synced_datatypes.Remove(datatype);
   service()->OnUserChoseDatatypes(false, synced_datatypes);
-  if (AwaitSyncSetupCompletion()) {
+  if (AwaitSyncSetupCompletion(service())) {
     DVLOG(1) << "DisableSyncForDatatype(): Disabled sync for datatype "
              << syncer::ModelTypeToString(datatype)
              << " on " << profile_debug_name_ << ".";
@@ -569,7 +373,7 @@
   }
 
   service()->OnUserChoseDatatypes(true, syncer::ModelTypeSet::All());
-  if (AwaitSyncSetupCompletion()) {
+  if (AwaitSyncSetupCompletion(service())) {
     DVLOG(1) << "EnableSyncForAllDatatypes(): Enabled sync for all datatypes "
              << "on " << profile_debug_name_ << ".";
     return true;
@@ -594,17 +398,6 @@
   return true;
 }
 
-std::string ProfileSyncServiceHarness::GetSerializedProgressMarker(
-    syncer::ModelType model_type) const {
-  const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
-  const syncer::ProgressMarkerMap& markers_map =
-      snap.download_progress_markers();
-
-  syncer::ProgressMarkerMap::const_iterator it =
-      markers_map.find(model_type);
-  return (it != markers_map.end()) ? it->second : std::string();
-}
-
 // TODO(sync): Clean up this method in a separate CL. Remove all snapshot fields
 // and log shorter, more meaningful messages.
 std::string ProfileSyncServiceHarness::GetClientInfoString(
@@ -613,7 +406,8 @@
   os << profile_debug_name_ << ": " << message << ": ";
   if (service()) {
     const SyncSessionSnapshot& snap = GetLastSessionSnapshot();
-    const ProfileSyncService::Status& status = GetStatus();
+    ProfileSyncService::Status status;
+    service()->QueryDetailedSyncStatus(&status);
     // Capture select info from the sync session snapshot and syncer status.
     os << ", has_unsynced_items: "
        << (service()->sync_initialized() ? service()->HasUnsyncedItems() : 0)
@@ -634,61 +428,13 @@
        << ", notifications_enabled: "
        << status.notifications_enabled
        << ", service_is_pushing_changes: "
-       << ServiceIsPushingChanges();
+       << service()->ShouldPushChanges();
   } else {
     os << "Sync service not available";
   }
   return os.str();
 }
 
-bool ProfileSyncServiceHarness::EnableEncryption() {
-  if (IsEncryptionComplete())
-    return true;
-  service()->EnableEncryptEverything();
-
-  // In order to kick off the encryption we have to reconfigure. Just grab the
-  // currently synced types and use them.
-  const syncer::ModelTypeSet synced_datatypes =
-      service()->GetPreferredDataTypes();
-  bool sync_everything =
-      synced_datatypes.Equals(syncer::ModelTypeSet::All());
-  service()->OnUserChoseDatatypes(sync_everything, synced_datatypes);
-
-  // Wait some time to let the enryption finish.
-  return WaitForEncryption();
-}
-
-bool ProfileSyncServiceHarness::WaitForEncryption() {
-  if (IsEncryptionComplete()) {
-    // Encryption is already complete; do not wait.
-    return true;
-  }
-
-  CallbackStatusChecker encryption_complete_checker(
-      service(),
-      base::Bind(&ProfileSyncServiceHarness::IsEncryptionComplete,
-                 base::Unretained(this)),
-      "IsEncryptionComplete");
-  return AwaitStatusChange(&encryption_complete_checker);
-}
-
-bool ProfileSyncServiceHarness::IsEncryptionComplete() const {
-  bool is_encryption_complete = service()->EncryptEverythingEnabled() &&
-                                !service()->encryption_pending();
-  DVLOG(2) << "Encryption is "
-           << (is_encryption_complete ? "" : "not ")
-           << "complete; Encrypted types = "
-           << syncer::ModelTypeSetToString(service()->GetEncryptedDataTypes());
-  return is_encryption_complete;
-}
-
-bool ProfileSyncServiceHarness::IsTypeRunning(syncer::ModelType type) {
-  browser_sync::DataTypeController::StateMap state_map;
-  service()->GetDataTypeControllerStates(&state_map);
-  return (state_map.count(type) != 0 &&
-          state_map[type] == browser_sync::DataTypeController::RUNNING);
-}
-
 bool ProfileSyncServiceHarness::IsTypePreferred(syncer::ModelType type) {
   return service()->GetPreferredDataTypes().Has(type);
 }
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.h b/chrome/browser/sync/test/integration/profile_sync_service_harness.h
index de60336..6f2b755 100644
--- a/chrome/browser/sync/test/integration/profile_sync_service_harness.h
+++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.h
@@ -10,54 +10,28 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "sync/internal_api/public/base/model_type.h"
+#include "sync/internal_api/public/sessions/sync_session_snapshot.h"
 
 class Profile;
-class StatusChangeChecker;
-class P2PInvalidationForwarder;
-
-namespace invalidation {
-class P2PInvalidationService;
-}
-
-namespace browser_sync {
-namespace sessions {
-class SyncSessionSnapshot;
-}
-}
+class ProfileSyncService;
 
 // An instance of this class is basically our notion of a "sync client" for
 // automation purposes. It harnesses the ProfileSyncService member of the
 // profile passed to it on construction and automates certain things like setup
 // and authentication. It provides ways to "wait" adequate periods of time for
 // several clients to get to the same state.
-class ProfileSyncServiceHarness
-    : public ProfileSyncServiceObserver {
+class ProfileSyncServiceHarness {
  public:
   static ProfileSyncServiceHarness* Create(
       Profile* profile,
       const std::string& username,
       const std::string& password);
-
-  static ProfileSyncServiceHarness* CreateForIntegrationTest(
-      Profile* profile,
-      const std::string& username,
-      const std::string& password,
-      invalidation::P2PInvalidationService* invalidation_service);
-
   virtual ~ProfileSyncServiceHarness();
 
   // Sets the GAIA credentials with which to sign in to sync.
   void SetCredentials(const std::string& username, const std::string& password);
 
-  // Returns true if sync is disabled for this client.
-  bool IsSyncDisabled() const;
-
-  // Returns true if an auth error has been encountered.
-  bool HasAuthError() const;
-
   // Creates a ProfileSyncService for the profile passed at construction and
   // enables sync for all available datatypes. Returns true only after sync has
   // been fully initialized and authenticated, and we are ready to process
@@ -68,26 +42,6 @@
   // in |synced_datatypes|.
   bool SetupSync(syncer::ModelTypeSet synced_datatypes);
 
-  // ProfileSyncServiceObserver implementation.
-  virtual void OnStateChanged() OVERRIDE;
-  virtual void OnSyncCycleCompleted() OVERRIDE;
-
-  // Blocks the caller until the sync backend host associated with this harness
-  // has been initialized.  Returns true if the wait was successful.
-  bool AwaitBackendInitialized();
-
-  // Blocks the caller until the client has nothing left to commit and its
-  // progress markers are up to date. Returns true if successful.
-  bool AwaitCommitActivityCompletion();
-
-  // Blocks the caller until sync has been disabled for this client. Returns
-  // true if sync is disabled.
-  bool AwaitSyncDisabled();
-
-  // Blocks the caller until sync setup is complete for this client. Returns
-  // true if sync setup is complete.
-  bool AwaitSyncSetupCompletion();
-
   // Calling this acts as a barrier and blocks the caller until |this| and
   // |partner| have both completed a sync cycle.  When calling this method,
   // the |partner| should be the passive responder who responds to the actions
@@ -111,25 +65,12 @@
   static bool AwaitQuiescence(
       std::vector<ProfileSyncServiceHarness*>& clients);
 
-  // Blocks the caller until |service_| indicates that a passphrase is required.
-  bool AwaitPassphraseRequired();
-
-  // Blocks the caller until |service_| indicates that the passphrase set by
-  // calling SetDecryptionPassphrase has been accepted.
-  bool AwaitPassphraseAccepted();
-
   // Returns the ProfileSyncService member of the sync client.
   ProfileSyncService* service() const { return service_; }
 
   // Returns the debug name for this profile. Used for logging.
   const std::string& profile_debug_name() const { return profile_debug_name_; }
 
-  // Returns the status of the ProfileSyncService member of the sync client.
-  ProfileSyncService::Status GetStatus() const;
-
-  // See ProfileSyncService::ShouldPushChanges().
-  bool ServiceIsPushingChanges() const { return service_->ShouldPushChanges(); }
-
   // Enables sync for a particular sync datatype. Returns true on success.
   bool EnableSyncForDatatype(syncer::ModelType datatype);
 
@@ -145,35 +86,9 @@
   // Returns a snapshot of the current sync session.
   syncer::sessions::SyncSessionSnapshot GetLastSessionSnapshot() const;
 
-  // Encrypts all datatypes. This method will block while the sync backend host
-  // performs the encryption, or a timeout is reached. Returns true if
-  // encryption is complete and we are fully synced, and false if we timed out.
-  bool EnableEncryption();
-
-  // Waits until encryption is complete for all datatypes. Returns true if
-  // encryption is complete and we are fully synced, and false if we timed out.
-  bool WaitForEncryption();
-
-  // Returns true if encryption is complete for all datatypes, and false
-  // otherwise.
-  bool IsEncryptionComplete() const;
-
-  // Check if |type| is registered and the controller is running.
-  bool IsTypeRunning(syncer::ModelType type);
-
   // Check if |type| is being synced.
   bool IsTypePreferred(syncer::ModelType type);
 
-  // Gets the |auto_start_enabled_| variable from the |service_|.
-  bool AutoStartEnabled();
-
-  // Runs the UI message loop and waits until the Run() method of |checker|
-  // returns true, indicating that the status change we are waiting for has
-  // taken place. Caller retains ownership of |checker|, which must outlive this
-  // method. Returns true if the status change was observed. In case of a
-  // timeout, we CHECK(false).
-  bool AwaitStatusChange(StatusChangeChecker* checker);
-
   // Returns a string that can be used as the value of an oauth2 refresh token.
   // This function guarantees that a different string is returned each time
   // it is called.
@@ -187,33 +102,23 @@
   ProfileSyncServiceHarness(
       Profile* profile,
       const std::string& username,
-      const std::string& password,
-      invalidation::P2PInvalidationService* invalidation_service);
-
-  // Quits the current message loop. Called when the status change being waited
-  // on has occurred, or in the event of a timeout.
-  void QuitMessageLoop();
+      const std::string& password);
 
   // Signals that sync setup is complete, and that PSS may begin syncing.
   void FinishSyncSetup();
 
-  // Gets the current progress marker of the current sync session for a
-  // particular datatype. Returns an empty string if the progress marker isn't
-  // found.
-  std::string GetSerializedProgressMarker(syncer::ModelType model_type) const;
-
   // Gets detailed status from |service_| in pretty-printable form.
   std::string GetServiceStatus();
 
+  // Returns true if sync is disabled for this client.
+  bool IsSyncDisabled() const;
+
   // Sync profile associated with this sync client.
   Profile* profile_;
 
   // ProfileSyncService object associated with |profile_|.
   ProfileSyncService* service_;
 
-  // An bridge between the ProfileSyncService and P2PInvalidationService.
-  scoped_ptr<P2PInvalidationForwarder> p2p_invalidation_forwarder_;
-
   // Credentials used for GAIA authentication.
   std::string username_;
   std::string password_;
@@ -225,10 +130,6 @@
   // Used for logging.
   const std::string profile_debug_name_;
 
-  // Keeps track of the state change on which we are waiting. PSSHarness can
-  // wait on only one status change at a time.
-  StatusChangeChecker* status_change_checker_;
-
   DISALLOW_COPY_AND_ASSIGN(ProfileSyncServiceHarness);
 };
 
diff --git a/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc b/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc
index 92b8654..8c6d241 100644
--- a/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc
+++ b/chrome/browser/sync/test/integration/quiesce_status_change_checker.cc
@@ -9,7 +9,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
 
 namespace {
@@ -146,7 +145,7 @@
 
 QuiesceStatusChangeChecker::QuiesceStatusChangeChecker(
     std::vector<ProfileSyncService*> services)
-  : services_(services), harness_(NULL) {
+  : services_(services), timed_out_(false) {
   DCHECK_LE(1U, services_.size());
   for (size_t i = 0; i < services_.size(); ++i) {
     observers_.push_back(new ProgressMarkerWatcher(services[i], this));
@@ -155,6 +154,31 @@
 
 QuiesceStatusChangeChecker::~QuiesceStatusChangeChecker() {}
 
+base::TimeDelta QuiesceStatusChangeChecker::GetTimeoutDuration() {
+  return base::TimeDelta::FromSeconds(45);
+}
+
+void QuiesceStatusChangeChecker::Await() {
+  DVLOG(1) << "Await: " << GetDebugMessage();
+
+  if (IsExitConditionSatisfied()) {
+    DVLOG(1) << "Await -> Exit before waiting: " << GetDebugMessage();
+    return;
+  }
+
+  base::OneShotTimer<QuiesceStatusChangeChecker> timer;
+  timer.Start(FROM_HERE,
+              GetTimeoutDuration(),
+              base::Bind(&QuiesceStatusChangeChecker::OnTimeout,
+                         base::Unretained(this)));
+
+  {
+    base::MessageLoop* loop = base::MessageLoop::current();
+    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+    loop->Run();
+  }
+}
+
 bool QuiesceStatusChangeChecker::IsExitConditionSatisfied() {
   // Check that all progress markers are up to date.
   for (ScopedVector<ProgressMarkerWatcher>::const_iterator it =
@@ -206,18 +230,20 @@
                             services_.size());
 }
 
-
-void QuiesceStatusChangeChecker::InitObserver(
-    ProfileSyncServiceHarness* harness) {
-  harness_ = harness;
-}
-
-void QuiesceStatusChangeChecker::UninitObserver(
-    ProfileSyncServiceHarness* harness) {
-  harness_ = NULL;
-}
-
 void QuiesceStatusChangeChecker::OnServiceStateChanged(
     ProfileSyncService* service) {
-  harness_->OnStateChanged();
+  if (IsExitConditionSatisfied()) {
+    DVLOG(1) << "Await -> Condition met: " << GetDebugMessage();
+    base::MessageLoop::current()->QuitWhenIdle();
+  }
+}
+
+void QuiesceStatusChangeChecker::OnTimeout() {
+  DVLOG(1) << "Await -> Timed out: " << GetDebugMessage();
+  timed_out_ = true;
+  base::MessageLoop::current()->QuitWhenIdle();
+}
+
+bool QuiesceStatusChangeChecker::TimedOut() const {
+  return timed_out_;
 }
diff --git a/chrome/browser/sync/test/integration/quiesce_status_change_checker.h b/chrome/browser/sync/test/integration/quiesce_status_change_checker.h
index 37ec7e9..210f6c0 100644
--- a/chrome/browser/sync/test/integration/quiesce_status_change_checker.h
+++ b/chrome/browser/sync/test/integration/quiesce_status_change_checker.h
@@ -10,11 +10,11 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_vector.h"
+#include "base/time/time.h"
 #include "chrome/browser/sync/test/integration/status_change_checker.h"
 
 class ProfileSyncService;
 class ProgressMarkerWatcher;
-class ProfileSyncServiceHarness;
 
 // Waits until all provided clients have finished committing any unsynced items
 // and downloading each others' udpates.
@@ -34,17 +34,27 @@
       std::vector<ProfileSyncService*> services);
   virtual ~QuiesceStatusChangeChecker();
 
+  // Timeout length for this operation.  Default is 45s.
+  virtual base::TimeDelta GetTimeoutDuration();
+
+  // Blocks until all clients have quiesced or we time out.
+  void Await();
+
+  // A callback function for some helper objects.
+  void OnServiceStateChanged(ProfileSyncService* service);
+
+  // A callback for when the time limit is exceeded.
+  void OnTimeout();
+
   virtual bool IsExitConditionSatisfied() OVERRIDE;
   virtual std::string GetDebugMessage() const OVERRIDE;
-  virtual void InitObserver(ProfileSyncServiceHarness* harness) OVERRIDE;
-  virtual void UninitObserver(ProfileSyncServiceHarness* harness) OVERRIDE;
 
-  void OnServiceStateChanged(ProfileSyncService* service);
+  bool TimedOut() const;
 
  private:
   std::vector<ProfileSyncService*> services_;
   ScopedVector<ProgressMarkerWatcher> observers_;
-  ProfileSyncServiceHarness* harness_;
+  bool timed_out_;
 
   DISALLOW_COPY_AND_ASSIGN(QuiesceStatusChangeChecker);
 };
diff --git a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
index 51cf89c..1dbeb57 100644
--- a/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_app_list_sync_test.cc
@@ -7,12 +7,15 @@
 #include "chrome/browser/sync/test/integration/apps_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/sync_app_list_helper.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/common/chrome_switches.h"
 #include "ui/app_list/app_list_switches.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
+
 namespace {
 
 const size_t kNumDefaultApps = 2;
@@ -64,7 +67,7 @@
       app_list::AppListSyncableServiceFactory::GetForProfile(verifier());
   ASSERT_EQ(kNumApps + kNumDefaultApps, service->GetNumSyncItemsForTest());
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(AllProfilesHaveSameAppListAsVerifier());
 
 }
diff --git a/chrome/browser/sync/test/integration/single_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/single_client_apps_sync_test.cc
index ece1f81..34c1820 100644
--- a/chrome/browser/sync/test/integration/single_client_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_apps_sync_test.cc
@@ -5,11 +5,13 @@
 #include "base/basictypes.h"
 #include "chrome/browser/sync/test/integration/apps_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
 using apps_helper::AllProfilesHaveSameAppsAsVerifier;
 using apps_helper::InstallApp;
 using apps_helper::InstallPlatformApp;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class SingleClientAppsSyncTest : public SyncTest {
  public:
@@ -64,7 +66,7 @@
     InstallApp(verifier(), i);
   }
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier());
 }
@@ -78,7 +80,7 @@
     InstallPlatformApp(verifier(), i);
   }
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier());
 }
@@ -100,7 +102,7 @@
     InstallPlatformApp(verifier(), i);
   }
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_TRUE(AllProfilesHaveSameAppsAsVerifier());
 }
diff --git a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
index 57dca93..11c2287 100644
--- a/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_bookmarks_sync_test.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "ui/base/layout.h"
 
@@ -20,23 +21,18 @@
 using bookmarks_helper::RemoveAll;
 using bookmarks_helper::SetFavicon;
 using bookmarks_helper::SetTitle;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
-class SingleClientBookmarksSyncTest
-    : public SyncTest,
-      public testing::WithParamInterface<SyncTest::FakeServerExperiment> {
+class SingleClientBookmarksSyncTest : public SyncTest {
  public:
-  SingleClientBookmarksSyncTest() : SyncTest(SINGLE_CLIENT) {
-    if (GetParam() == USE_FAKE_SERVER) {
-      UseFakeServer();
-    }
-  }
+  SingleClientBookmarksSyncTest() : SyncTest(SINGLE_CLIENT) {}
   virtual ~SingleClientBookmarksSyncTest() {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(SingleClientBookmarksSyncTest);
 };
 
-IN_PROC_BROWSER_TEST_P(SingleClientBookmarksSyncTest, Sanity) {
+IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest, Sanity) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
 
   // Starting state:
@@ -62,7 +58,7 @@
 
   // Setup sync, wait for its completion, and make sure changes were synced.
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 
   //  Ultimately we want to end up with the following model; but this test is
@@ -93,7 +89,7 @@
   Move(0, tier1_a, bar, 1);
 
   // Wait for the bookmark position change to sync.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 
   const BookmarkNode* porsche = AddURL(0, bar, 2, L"Porsche",
@@ -105,7 +101,7 @@
   Move(0, tier1_a_url1, tier1_a, 2);
 
   // Wait for the rearranged hierarchy to sync.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 
   ASSERT_EQ(1, tier1_a_url0->parent()->GetIndexOf(tier1_a_url0));
@@ -128,7 +124,7 @@
   SetTitle(0, porsche, L"ICanHazPorsche?");
 
   // Wait for the title change to sync.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 
   ASSERT_EQ(tier1_a_url0->id(), top->GetChild(top->child_count() - 1)->id());
@@ -145,14 +141,14 @@
   Move(0, leafs, tier3_b, 0);
 
   // Wait for newly added bookmarks to sync.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 }
 
 // Test that a client doesn't mutate the favicon data in the process
 // of storing the favicon data from sync to the database or in the process
 // of requesting data from the database for sync.
-IN_PROC_BROWSER_TEST_P(SingleClientBookmarksSyncTest,
+IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest,
                        SetFaviconHiDPIDifferentCodec) {
   // Set the supported scale factors to 1x and 2x such that
   // BookmarkModel::GetFavicon() requests both 1x and 2x.
@@ -179,7 +175,7 @@
   SetFavicon(0, bookmark, icon_url, original_favicon,
              bookmarks_helper::FROM_SYNC);
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 
   scoped_refptr<base::RefCountedMemory> original_favicon_bytes =
@@ -193,7 +189,7 @@
   EXPECT_TRUE(original_favicon_bytes->Equals(final_favicon_bytes));
 }
 
-IN_PROC_BROWSER_TEST_P(SingleClientBookmarksSyncTest,
+IN_PROC_BROWSER_TEST_F(SingleClientBookmarksSyncTest,
                        BookmarkAllNodesRemovedEvent) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
   // Starting state:
@@ -229,20 +225,15 @@
 
   // Set up sync, wait for its completion and verify that changes propagated.
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 
   // Remove all bookmarks and wait for sync completion.
   RemoveAll(0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   // Verify other node has no children now.
   EXPECT_EQ(0, GetOtherNode(0)->child_count());
   EXPECT_EQ(0, GetBookmarkBarNode(0)->child_count());
   // Verify model matches verifier.
   ASSERT_TRUE(ModelMatchesVerifier(0));
 }
-
-INSTANTIATE_TEST_CASE_P(TestServerComparison,
-                        SingleClientBookmarksSyncTest,
-                        testing::Values(SyncTest::USE_DEFAULT_SERVER,
-                                        SyncTest::USE_FAKE_SERVER));
diff --git a/chrome/browser/sync/test/integration/single_client_dictionary_sync_test.cc b/chrome/browser/sync/test/integration/single_client_dictionary_sync_test.cc
index 30926ae..d6d29aa 100644
--- a/chrome/browser/sync/test/integration/single_client_dictionary_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_dictionary_sync_test.cc
@@ -4,8 +4,11 @@
 
 #include "chrome/browser/sync/test/integration/dictionary_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
+
 class SingleClientDictionarySyncTest : public SyncTest {
  public:
   SingleClientDictionarySyncTest() : SyncTest(SINGLE_CLIENT) {}
@@ -22,10 +25,10 @@
 
   std::string word = "foo";
   ASSERT_TRUE(dictionary_helper::AddWord(0, word));
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(dictionary_helper::DictionariesMatch());
 
   ASSERT_TRUE(dictionary_helper::RemoveWord(0, word));
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(dictionary_helper::DictionariesMatch());
 }
diff --git a/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc
index d19abab..e4f40cd 100644
--- a/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_extensions_sync_test.cc
@@ -5,10 +5,12 @@
 #include "base/basictypes.h"
 #include "chrome/browser/sync/test/integration/extensions_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
 using extensions_helper::AllProfilesHaveSameExtensionsAsVerifier;
 using extensions_helper::InstallExtension;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class SingleClientExtensionsSyncTest : public SyncTest {
  public:
@@ -50,7 +52,7 @@
     InstallExtension(verifier(), i);
   }
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_TRUE(AllProfilesHaveSameExtensionsAsVerifier());
 }
diff --git a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
index b658cb5..dcd4143 100644
--- a/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_passwords_sync_test.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/sync/test/integration/passwords_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "components/password_manager/core/browser/password_form_data.h"
 
@@ -14,6 +15,7 @@
 using passwords_helper::GetVerifierPasswordCount;
 using passwords_helper::GetVerifierPasswordStore;
 using passwords_helper::ProfileContainsSamePasswordFormsAsVerifier;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 using autofill::PasswordForm;
 
@@ -35,7 +37,7 @@
   AddLogin(GetPasswordStore(0), form);
   ASSERT_EQ(1, GetPasswordCount(0));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ProfileContainsSamePasswordFormsAsVerifier(0));
   ASSERT_EQ(1, GetPasswordCount(0));
 }
diff --git a/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc
index 2a03cb9..50ebf6f 100644
--- a/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_preferences_sync_test.cc
@@ -5,10 +5,12 @@
 #include "chrome/common/pref_names.h"
 #include "chrome/browser/sync/test/integration/preferences_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
 using preferences_helper::BooleanPrefMatches;
 using preferences_helper::ChangeBooleanPref;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class SingleClientPreferencesSyncTest : public SyncTest {
  public:
@@ -23,6 +25,6 @@
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
   ASSERT_TRUE(BooleanPrefMatches(prefs::kHomePageIsNewTabPage));
   ChangeBooleanPref(0, prefs::kHomePageIsNewTabPage);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(BooleanPrefMatches(prefs::kHomePageIsNewTabPage));
 }
diff --git a/chrome/browser/sync/test/integration/single_client_search_engines_sync_test.cc b/chrome/browser/sync/test/integration/single_client_search_engines_sync_test.cc
index 91fbbe4..8bf87ae 100644
--- a/chrome/browser/sync/test/integration/single_client_search_engines_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_search_engines_sync_test.cc
@@ -5,8 +5,11 @@
 #include "chrome/browser/search_engines/template_url_service.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/search_engines_helper.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
+
 class SingleClientSearchEnginesSyncTest : public SyncTest {
  public:
   SingleClientSearchEnginesSyncTest() : SyncTest(SINGLE_CLIENT) {}
@@ -22,6 +25,6 @@
 
   search_engines_helper::AddSearchEngine(0, 0);
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(search_engines_helper::ServiceMatchesVerifier(0));
 }
diff --git a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
index 0dfcf15..076baf9 100644
--- a/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_sessions_sync_test.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/sessions/session_types.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/sessions_helper.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/sync/test/integration/typed_urls_helper.h"
 #include "sync/util/time.h"
@@ -20,6 +21,7 @@
 using sessions_helper::SessionWindowMap;
 using sessions_helper::SyncedSessionVector;
 using sessions_helper::WindowsMatch;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 using typed_urls_helper::GetUrlFromClient;
 
 class SingleClientSessionsSyncTest : public SyncTest {
@@ -48,7 +50,7 @@
   ASSERT_TRUE(OpenTabAndGetLocalWindows(0,
                                         GURL("http://127.0.0.1/bubba"),
                                         old_windows.GetMutable()));
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   // Get foreign session data from client 0.
   SyncedSessionVector sessions;
diff --git a/chrome/browser/sync/test/integration/single_client_status_change_checker.cc b/chrome/browser/sync/test/integration/single_client_status_change_checker.cc
index fdd14ed..fcfe3c5 100644
--- a/chrome/browser/sync/test/integration/single_client_status_change_checker.cc
+++ b/chrome/browser/sync/test/integration/single_client_status_change_checker.cc
@@ -4,20 +4,57 @@
 
 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
 
+#include "base/logging.h"
+#include "base/scoped_observer.h"
 #include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 
 SingleClientStatusChangeChecker::SingleClientStatusChangeChecker(
-    ProfileSyncService* service) : service_(service) {}
+    ProfileSyncService* service) : service_(service), timed_out_(false) {}
 
 SingleClientStatusChangeChecker::~SingleClientStatusChangeChecker() {}
 
-void SingleClientStatusChangeChecker::InitObserver(
-    ProfileSyncServiceHarness* obs) {
-  service()->AddObserver(obs);
+base::TimeDelta SingleClientStatusChangeChecker::GetTimeoutDuration() {
+  return base::TimeDelta::FromSeconds(45);
+}
+void SingleClientStatusChangeChecker::OnTimeout() {
+  DVLOG(1) << "Await -> Timed out: " << GetDebugMessage();
+  timed_out_ = true;
+  base::MessageLoop::current()->QuitWhenIdle();
 }
 
-void SingleClientStatusChangeChecker::UninitObserver(
-    ProfileSyncServiceHarness* obs) {
-  service()->RemoveObserver(obs);
+void SingleClientStatusChangeChecker::Await() {
+  DVLOG(1) << "Await: " << GetDebugMessage();
+
+  if (IsExitConditionSatisfied()) {
+    DVLOG(1) << "Await -> Exit before waiting: " << GetDebugMessage();
+    return;
+  }
+
+  ScopedObserver<ProfileSyncService, SingleClientStatusChangeChecker> obs(this);
+  obs.Add(service());
+
+  base::OneShotTimer<SingleClientStatusChangeChecker> timer;
+  timer.Start(FROM_HERE,
+              GetTimeoutDuration(),
+              base::Bind(&SingleClientStatusChangeChecker::OnTimeout,
+                         base::Unretained(this)));
+
+  {
+    base::MessageLoop* loop = base::MessageLoop::current();
+    base::MessageLoop::ScopedNestableTaskAllower allow(loop);
+    loop->Run();
+  }
+}
+
+void SingleClientStatusChangeChecker::OnStateChanged() {
+  DVLOG(1) << "Await -> Checking Condition: " << GetDebugMessage();
+  if (IsExitConditionSatisfied()) {
+    DVLOG(1) << "Await -> Condition met: " << GetDebugMessage();
+    base::MessageLoop::current()->QuitWhenIdle();
+  }
+}
+
+bool SingleClientStatusChangeChecker::TimedOut() {
+  return timed_out_;
 }
diff --git a/chrome/browser/sync/test/integration/single_client_status_change_checker.h b/chrome/browser/sync/test/integration/single_client_status_change_checker.h
index c5f9a80..bca74f3 100644
--- a/chrome/browser/sync/test/integration/single_client_status_change_checker.h
+++ b/chrome/browser/sync/test/integration/single_client_status_change_checker.h
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_SYNC_TEST_INTEGRATION_SINGLE_CLIENT_STATUS_CHANGE_CHECKER_H_
 
 #include "base/compiler_specific.h"
+#include "base/time/time.h"
+#include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/browser/sync/test/integration/status_change_checker.h"
 
 class ProfileSyncService;
@@ -14,22 +16,38 @@
 // This class provides some common functionality for StatusChangeCheckers that
 // observe only one ProfileSyncService.  This class is abstract.  Its
 // descendants are expected to provide additional functionality.
-class SingleClientStatusChangeChecker : public StatusChangeChecker {
+class SingleClientStatusChangeChecker
+  : public StatusChangeChecker,
+    public ProfileSyncServiceObserver {
  public:
   explicit SingleClientStatusChangeChecker(ProfileSyncService* service);
   virtual ~SingleClientStatusChangeChecker();
 
+  // Timeout length for this operation.  Default is 45s.
+  virtual base::TimeDelta GetTimeoutDuration();
+
+  // Called when waiting times out.
+  void OnTimeout();
+
+  // Blocks until the exit condition is satisfied or a timeout occurs.
+  void Await();
+
+  // ProfileSyncServiceObserver implementation.
+  virtual void OnStateChanged() OVERRIDE;
+
+  // Returns true if the checker timed out.
+  bool TimedOut();
+
   // StatusChangeChecker implementations and stubs.
   virtual bool IsExitConditionSatisfied() = 0;
   virtual std::string GetDebugMessage() const = 0;
-  virtual void InitObserver(ProfileSyncServiceHarness* obs) OVERRIDE;
-  virtual void UninitObserver(ProfileSyncServiceHarness* obs) OVERRIDE;
 
  protected:
   ProfileSyncService* service() { return service_; }
 
  private:
   ProfileSyncService* service_;
+  bool timed_out_;
 };
 
 #endif  // CHROME_BROWSER_SYNC_TEST_INTEGRATION_SINGLE_CLIENT_STATUS_CHANGE_CHECKER_H_
diff --git a/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc b/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc
index 3508e9f..fc0c33d 100644
--- a/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_themes_sync_test.cc
@@ -4,9 +4,11 @@
 
 #include "base/basictypes.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/sync/test/integration/themes_helper.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 using themes_helper::GetCustomTheme;
 using themes_helper::GetThemeID;
 using themes_helper::UseCustomTheme;
@@ -40,7 +42,7 @@
   ASSERT_EQ(GetCustomTheme(0), GetThemeID(GetProfile(0)));
   ASSERT_EQ(GetCustomTheme(0), GetThemeID(verifier()));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_EQ(GetCustomTheme(0), GetThemeID(GetProfile(0)));
   ASSERT_EQ(GetCustomTheme(0), GetThemeID(verifier()));
@@ -59,14 +61,14 @@
   ASSERT_FALSE(UsingNativeTheme(GetProfile(0)));
   ASSERT_FALSE(UsingNativeTheme(verifier()));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   UseNativeTheme(GetProfile(0));
   UseNativeTheme(verifier());
   ASSERT_TRUE(UsingNativeTheme(GetProfile(0)));
   ASSERT_TRUE(UsingNativeTheme(verifier()));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_TRUE(UsingNativeTheme(GetProfile(0)));
   ASSERT_TRUE(UsingNativeTheme(verifier()));
@@ -80,14 +82,14 @@
   ASSERT_FALSE(UsingDefaultTheme(GetProfile(0)));
   ASSERT_FALSE(UsingDefaultTheme(verifier()));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   UseDefaultTheme(GetProfile(0));
   UseDefaultTheme(verifier());
   ASSERT_TRUE(UsingDefaultTheme(GetProfile(0)));
   ASSERT_TRUE(UsingDefaultTheme(verifier()));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_TRUE(UsingDefaultTheme(GetProfile(0)));
   ASSERT_TRUE(UsingDefaultTheme(verifier()));
diff --git a/chrome/browser/sync/test/integration/single_client_typed_urls_sync_test.cc b/chrome/browser/sync/test/integration/single_client_typed_urls_sync_test.cc
index 3a8f9cd..0362cd6 100644
--- a/chrome/browser/sync/test/integration/single_client_typed_urls_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_typed_urls_sync_test.cc
@@ -6,9 +6,11 @@
 #include "chrome/browser/history/history_types.h"
 #include "chrome/browser/sessions/session_service.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/sync/test/integration/typed_urls_helper.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 using typed_urls_helper::AddUrlToHistory;
 using typed_urls_helper::AddUrlToHistoryWithTransition;
 using typed_urls_helper::AssertAllProfilesHaveSameURLsAsVerifier;
@@ -40,7 +42,7 @@
   AssertAllProfilesHaveSameURLsAsVerifier();
 
   // Wait for sync and verify client did not change.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   AssertAllProfilesHaveSameURLsAsVerifier();
 }
 
@@ -60,7 +62,7 @@
   AssertAllProfilesHaveSameURLsAsVerifier();
 
   // Wait for sync and verify client did not change.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   AssertAllProfilesHaveSameURLsAsVerifier();
 }
 
@@ -80,12 +82,12 @@
   AssertAllProfilesHaveSameURLsAsVerifier();
 
   // Wait for sync and verify client did not change.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   AssertAllProfilesHaveSameURLsAsVerifier();
 
   // Now delete the URL we just added, wait for sync, and verify the deletion.
   DeleteUrlFromHistory(0, new_url);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   urls = GetTypedUrlsFromClient(0);
   ASSERT_EQ(0U, urls.size());
   AssertAllProfilesHaveSameURLsAsVerifier();
@@ -106,12 +108,12 @@
   AssertAllProfilesHaveSameURLsAsVerifier();
 
   // Wait for sync and verify client did not change.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   AssertAllProfilesHaveSameURLsAsVerifier();
 
   // Now delete the URL we just added, wait for sync and verify the deletion.
   DeleteUrlFromHistory(0, new_url);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   urls = GetTypedUrlsFromClient(0);
   ASSERT_EQ(0U, urls.size());
   AssertAllProfilesHaveSameURLsAsVerifier();
diff --git a/chrome/browser/sync/test/integration/status_change_checker.h b/chrome/browser/sync/test/integration/status_change_checker.h
index ae465f5..9f8c108 100644
--- a/chrome/browser/sync/test/integration/status_change_checker.h
+++ b/chrome/browser/sync/test/integration/status_change_checker.h
@@ -29,9 +29,6 @@
   // or "AwaitMigrationDone(BOOKMARKS)".
   virtual std::string GetDebugMessage() const = 0;
 
-  virtual void InitObserver(ProfileSyncServiceHarness*) = 0;
-  virtual void UninitObserver(ProfileSyncServiceHarness*) = 0;
-
  protected:
   virtual ~StatusChangeChecker();
 };
diff --git a/chrome/browser/sync/test/integration/sync_auth_test.cc b/chrome/browser/sync/test/integration/sync_auth_test.cc
index 79258f0..cee1732 100644
--- a/chrome/browser/sync/test/integration/sync_auth_test.cc
+++ b/chrome/browser/sync/test/integration/sync_auth_test.cc
@@ -10,13 +10,15 @@
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/url_request_status.h"
 
 using bookmarks_helper::AddURL;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 const char kShortLivedOAuth2Token[] =
     "{"
@@ -70,7 +72,9 @@
 
 class SyncAuthTest : public SyncTest {
  public:
-  SyncAuthTest() : SyncTest(SINGLE_CLIENT), bookmark_index_(0) {}
+  // TODO(pvalenzuela): Switch to SINGLE_CLIENT once FakeServer
+  // supports this scenario.
+  SyncAuthTest() : SyncTest(SINGLE_CLIENT_LEGACY), bookmark_index_(0) {}
   virtual ~SyncAuthTest() {}
 
   // Helper function that adds a bookmark and waits for either an auth error, or
@@ -84,7 +88,7 @@
 
     // Run until the bookmark is committed or an auth error is encountered.
     TestForAuthError checker_(GetClient(0)->service());
-    GetClient(0)->AwaitStatusChange(&checker_);
+    checker_.Await();
 
     GoogleServiceAuthError oauth_error =
         GetClient(0)->service()->GetSyncTokenStatus().last_get_token_error;
@@ -299,7 +303,7 @@
                                net::URLRequestStatus::SUCCESS);
 
   // Verify that the next sync cycle is successful, and uses the new auth token.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   std::string new_token = GetClient(0)->service()->GetAccessTokenForTest();
   ASSERT_NE(old_token, new_token);
 }
diff --git a/chrome/browser/sync/test/integration/sync_errors_test.cc b/chrome/browser/sync/test/integration/sync_errors_test.cc
index 5a434a0..687e18b 100644
--- a/chrome/browser/sync/test/integration/sync_errors_test.cc
+++ b/chrome/browser/sync/test/integration/sync_errors_test.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/sync/test/integration/passwords_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/common/pref_names.h"
 #include "google_apis/gaia/google_service_auth_error.h"
@@ -16,12 +17,36 @@
 
 using bookmarks_helper::AddFolder;
 using bookmarks_helper::SetTitle;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 namespace {
 
+class SyncDisabledChecker : public SingleClientStatusChangeChecker {
+ public:
+  explicit SyncDisabledChecker(ProfileSyncService* service)
+      : SingleClientStatusChangeChecker(service) {}
+
+  virtual bool IsExitConditionSatisfied() OVERRIDE {
+    return !service()->setup_in_progress() &&
+           !service()->HasSyncSetupCompleted();
+  }
+
+  virtual std::string GetDebugMessage() const OVERRIDE {
+    return "Sync Disabled";
+  }
+};
+
+bool AwaitSyncDisabled(ProfileSyncService* service) {
+  SyncDisabledChecker checker(service);
+  checker.Await();
+  return !checker.TimedOut();
+}
+
 class SyncErrorTest : public SyncTest {
  public:
-  SyncErrorTest() : SyncTest(SINGLE_CLIENT) {}
+  // TODO(pvalenzuela): Switch to SINGLE_CLIENT once FakeServer
+  // supports this scenario.
+  SyncErrorTest() : SyncTest(SINGLE_CLIENT_LEGACY) {}
   virtual ~SyncErrorTest() {}
 
  private:
@@ -59,13 +84,13 @@
   // Add an item, wait for sync, and trigger a birthday error on the server.
   const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
   SetTitle(0, node1, L"new_title1");
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   TriggerBirthdayError();
 
   // Now make one more change so we will do another sync.
   const BookmarkNode* node2 = AddFolder(0, 0, L"title2");
   SetTitle(0, node2, L"new_title2");
-  ASSERT_TRUE(GetClient(0)->AwaitSyncDisabled());
+  ASSERT_TRUE(AwaitSyncDisabled(GetClient(0)->service()));
 }
 
 IN_PROC_BROWSER_TEST_F(SyncErrorTest, ActionableErrorTest) {
@@ -73,7 +98,7 @@
 
   const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
   SetTitle(0, node1, L"new_title1");
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   syncer::SyncProtocolError protocol_error;
   protocol_error.error_type = syncer::TRANSIENT_ERROR;
@@ -88,9 +113,11 @@
 
   // Wait until an actionable error is encountered.
   ActionableErrorChecker actionable_error_checker(GetClient(0)->service());
-  ASSERT_TRUE(GetClient(0)->AwaitStatusChange(&actionable_error_checker));
+  actionable_error_checker.Await();
+  ASSERT_FALSE(actionable_error_checker.TimedOut());
 
-  ProfileSyncService::Status status = GetClient(0)->GetStatus();
+  ProfileSyncService::Status status;
+  GetClient(0)->service()->QueryDetailedSyncStatus(&status);
   ASSERT_EQ(status.sync_protocol_error.error_type, protocol_error.error_type);
   ASSERT_EQ(status.sync_protocol_error.action, protocol_error.action);
   ASSERT_EQ(status.sync_protocol_error.url, protocol_error.url);
@@ -107,7 +134,7 @@
   protocol_error.error_description = "Not My Fault";
   protocol_error.url = "www.google.com";
 
-  if (clients()[0]->AutoStartEnabled()) {
+  if (clients()[0]->service()->auto_start_enabled()) {
     // In auto start enabled platforms like chrome os we should be
     // able to set up even if the first sync while setting up fails.
     // Trigger error on every 2 out of 3 requests.
@@ -135,7 +162,7 @@
 
   const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
   SetTitle(0, node1, L"new_title1");
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   syncer::SyncProtocolError protocol_error;
   protocol_error.error_type = syncer::NOT_MY_BIRTHDAY;
@@ -147,8 +174,9 @@
   // Now make one more change so we will do another sync.
   const BookmarkNode* node2 = AddFolder(0, 0, L"title2");
   SetTitle(0, node2, L"new_title2");
-  ASSERT_TRUE(GetClient(0)->AwaitSyncDisabled());
-  ProfileSyncService::Status status = GetClient(0)->GetStatus();
+  ASSERT_TRUE(AwaitSyncDisabled(GetClient(0)->service()));
+  ProfileSyncService::Status status;
+  GetClient(0)->service()->QueryDetailedSyncStatus(&status);
   ASSERT_EQ(status.sync_protocol_error.error_type, protocol_error.error_type);
   ASSERT_EQ(status.sync_protocol_error.action, protocol_error.action);
   ASSERT_EQ(status.sync_protocol_error.url, protocol_error.url);
@@ -170,7 +198,7 @@
 
   const BookmarkNode* node1 = AddFolder(0, 0, L"title1");
   SetTitle(0, node1, L"new_title1");
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   // TODO(lipalani)" Verify initial sync ended for typed url is false.
 }
 
diff --git a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
index 47fa574..f0188cf 100644
--- a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
+++ b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
@@ -4,10 +4,12 @@
 
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/retry_verifier.h"
 #include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
 namespace {
@@ -15,10 +17,13 @@
 using bookmarks_helper::AddFolder;
 using bookmarks_helper::ModelMatchesVerifier;
 using syncer::sessions::SyncSessionSnapshot;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class SyncExponentialBackoffTest : public SyncTest {
  public:
-  SyncExponentialBackoffTest() : SyncTest(SINGLE_CLIENT) {}
+  // TODO(pvalenzuela): Switch to SINGLE_CLIENT once FakeServer
+  // supports this scenario.
+  SyncExponentialBackoffTest() : SyncTest(SINGLE_CLIENT_LEGACY) {}
   virtual ~SyncExponentialBackoffTest() {}
 
  private:
@@ -64,7 +69,7 @@
 
   // Add an item and ensure that sync is successful.
   ASSERT_TRUE(AddFolder(0, 0, L"folder1"));
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   // Trigger a network error at the client side.
   DisableNetwork(GetProfile(0));
@@ -76,13 +81,14 @@
   // reach the sync server.
   ExponentialBackoffChecker exponential_backoff_checker(
       GetClient(0)->service());
-  ASSERT_TRUE(GetClient(0)->AwaitStatusChange(&exponential_backoff_checker));
+  exponential_backoff_checker.Await();
+  ASSERT_FALSE(exponential_backoff_checker.TimedOut());
 
   // Recover from the network error.
   EnableNetwork(GetProfile(0));
 
   // Verify that sync was able to recover.
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ModelMatchesVerifier(0));
 }
 
@@ -91,7 +97,7 @@
 
   // Add an item and ensure that sync is successful.
   ASSERT_TRUE(AddFolder(0, 0, L"folder1"));
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   // Trigger a transient error on the server.
   TriggerTransientError();
@@ -103,7 +109,8 @@
   // reach the sync server.
   ExponentialBackoffChecker exponential_backoff_checker(
       GetClient(0)->service());
-  ASSERT_TRUE(GetClient(0)->AwaitStatusChange(&exponential_backoff_checker));
+  exponential_backoff_checker.Await();
+  ASSERT_FALSE(exponential_backoff_checker.TimedOut());
 }
 
 }  // namespace
diff --git a/chrome/browser/sync/test/integration/sync_integration_test_util.cc b/chrome/browser/sync/test/integration/sync_integration_test_util.cc
new file mode 100644
index 0000000..5a7b9e3
--- /dev/null
+++ b/chrome/browser/sync/test/integration/sync_integration_test_util.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
+
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
+#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
+
+namespace sync_integration_test_util {
+
+class PassphraseRequiredChecker : public SingleClientStatusChangeChecker {
+ public:
+  explicit PassphraseRequiredChecker(ProfileSyncService* service)
+      : SingleClientStatusChangeChecker(service) {}
+
+  virtual bool IsExitConditionSatisfied() OVERRIDE {
+    return service()->IsPassphraseRequired();
+  }
+
+  virtual std::string GetDebugMessage() const OVERRIDE {
+    return "Passhrase Required";
+  }
+};
+
+class PassphraseAcceptedChecker : public SingleClientStatusChangeChecker {
+ public:
+  explicit PassphraseAcceptedChecker(ProfileSyncService* service)
+      : SingleClientStatusChangeChecker(service) {}
+
+  virtual bool IsExitConditionSatisfied() OVERRIDE {
+    return !service()->IsPassphraseRequired() &&
+        service()->IsUsingSecondaryPassphrase();
+  }
+
+  virtual std::string GetDebugMessage() const OVERRIDE {
+    return "Passhrase Accepted";
+  }
+};
+
+bool AwaitPassphraseRequired(ProfileSyncService* service) {
+  PassphraseRequiredChecker checker(service);
+  checker.Await();
+  return !checker.TimedOut();
+}
+
+bool AwaitPassphraseAccepted(ProfileSyncService* service) {
+  PassphraseAcceptedChecker checker(service);
+  checker.Await();
+  return !checker.TimedOut();
+}
+
+bool AwaitCommitActivityCompletion(ProfileSyncService* service) {
+  UpdatedProgressMarkerChecker checker(service);
+  checker.Await();
+  return !checker.TimedOut();
+}
+
+}  // namespace sync_integration_test_util
diff --git a/chrome/browser/sync/test/integration/sync_integration_test_util.h b/chrome/browser/sync/test/integration/sync_integration_test_util.h
new file mode 100644
index 0000000..db43c96
--- /dev/null
+++ b/chrome/browser/sync/test/integration/sync_integration_test_util.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_INTEGRATION_TEST_UTIL_H_
+#define CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_INTEGRATION_TEST_UTIL_H_
+
+class ProfileSyncService;
+
+namespace sync_integration_test_util {
+
+// Wait until the provided |service| is blocked waiting for a passphrase.
+bool AwaitPassphraseRequired(ProfileSyncService* service);
+
+// Wait until the provided |service| has accepted the new passphrase.
+bool AwaitPassphraseAccepted(ProfileSyncService* service);
+
+// Wait until the |service| is fully synced.
+// This can be a bit flaky.  See UpdatedProgressMarkerChecker for details.
+bool AwaitCommitActivityCompletion(ProfileSyncService* service);
+
+}  // namespace sync_integration_test_util
+
+#endif  // CHROME_BROWSER_SYNC_TEST_INTEGRATION_SYNC_INTEGRATION_TEST_UTIL_H_
diff --git a/chrome/browser/sync/test/integration/sync_test.cc b/chrome/browser/sync/test/integration/sync_test.cc
index fb7953b..4a258f9 100644
--- a/chrome/browser/sync/test/integration/sync_test.cc
+++ b/chrome/browser/sync/test/integration/sync_test.cc
@@ -34,9 +34,13 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/test/integration/p2p_invalidation_forwarder.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h"
 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/host_desktop.h"
@@ -79,6 +83,8 @@
 const char kSyncServerCommandLine[] = "sync-server-command-line";
 }
 
+namespace {
+
 // Helper class that checks whether a sync test server is running or not.
 class SyncServerStatusChecker : public net::URLFetcherDelegate {
  public:
@@ -99,6 +105,25 @@
   bool running_;
 };
 
+bool IsEncryptionComplete(const ProfileSyncService* service) {
+  return service->EncryptEverythingEnabled() && !service->encryption_pending();
+}
+
+// Helper class to wait for encryption to complete.
+class EncryptionChecker : public SingleClientStatusChangeChecker {
+ public:
+  explicit EncryptionChecker(ProfileSyncService* service)
+      : SingleClientStatusChangeChecker(service) {}
+
+  virtual bool IsExitConditionSatisfied() OVERRIDE {
+    return IsEncryptionComplete(service());
+  }
+
+  virtual std::string GetDebugMessage() const OVERRIDE {
+    return "Encryption";
+  }
+};
+
 void SetProxyConfigCallback(
     base::WaitableEvent* done,
     net::URLRequestContextGetter* url_request_context_getter,
@@ -121,6 +146,8 @@
               LoginUIServiceFactory::GetForProfile(profile))));
 }
 
+}  // namespace
+
 SyncTest::SyncTest(TestType test_type)
     : test_type_(test_type),
       server_type_(SERVER_TYPE_UNDECIDED),
@@ -130,7 +157,8 @@
       test_server_handle_(base::kNullProcessHandle) {
   sync_datatype_helper::AssociateWithTest(this);
   switch (test_type_) {
-    case SINGLE_CLIENT: {
+    case SINGLE_CLIENT:
+    case SINGLE_CLIENT_LEGACY: {
       num_clients_ = 1;
       break;
     }
@@ -160,39 +188,12 @@
     password_ = "password";
   }
 
-  // Only set |server_type_| if it hasn't already been set. This allows for
-  // IN_PROCESS_FAKE_SERVER tests to set this value in each test class.
-  if (server_type_ == SERVER_TYPE_UNDECIDED) {
-    if (!cl->HasSwitch(switches::kSyncServiceURL) &&
-        !cl->HasSwitch(switches::kSyncServerCommandLine)) {
-      // If neither a sync server URL nor a sync server command line is
-      // provided, start up a local python sync test server and point Chrome
-      // to its URL.  This is the most common configuration, and the only
-      // one that makes sense for most developers.
-      server_type_ = LOCAL_PYTHON_SERVER;
-    } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
-               cl->HasSwitch(switches::kSyncServerCommandLine)) {
-      // If a sync server URL and a sync server command line are provided,
-      // start up a local sync server by running the command line. Chrome
-      // will connect to the server at the URL that was provided.
-      server_type_ = LOCAL_LIVE_SERVER;
-    } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
-               !cl->HasSwitch(switches::kSyncServerCommandLine)) {
-      // If a sync server URL is provided, but not a server command line,
-      // it is assumed that the server is already running. Chrome will
-      // automatically connect to it at the URL provided. There is nothing
-      // to do here.
-      server_type_ = EXTERNAL_LIVE_SERVER;
-    } else {
-      // If a sync server command line is provided, but not a server URL,
-      // we flag an error.
-      LOG(FATAL) << "Can't figure out how to run a server.";
-    }
-  }
-
   if (username_.empty() || password_.empty())
     LOG(FATAL) << "Cannot run sync tests without GAIA credentials.";
 
+  // Sets |server_type_| if it wasn't specified by the test.
+  DecideServerType();
+
   // Mock the Mac Keychain service.  The real Keychain can block on user input.
 #if defined(OS_MACOSX)
   OSCrypt::UseMockKeychain(true);
@@ -298,6 +299,7 @@
   profiles_.resize(num_clients_);
   browsers_.resize(num_clients_);
   clients_.resize(num_clients_);
+  invalidation_forwarders_.resize(num_clients_);
   for (int i = 0; i < num_clients_; ++i) {
     InitializeInstance(i);
   }
@@ -344,14 +346,18 @@
   }
 
   clients_[index] =
-      ProfileSyncServiceHarness::CreateForIntegrationTest(
+      ProfileSyncServiceHarness::Create(
           GetProfile(index),
           username_,
-          password_,
-          p2p_invalidation_service);
+          password_);
   EXPECT_FALSE(GetClient(index) == NULL) << "Could not create Client "
                                          << index << ".";
 
+  // Start listening for and emitting notificaitons of commits.
+  invalidation_forwarders_[index] =
+      new P2PInvalidationForwarder(clients_[index]->service(),
+                                   p2p_invalidation_service);
+
   test::WaitForBookmarkModelToLoad(
       BookmarkModelFactory::GetForProfile(GetProfile(index)));
   ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile(
@@ -396,6 +402,7 @@
   // All browsers should be closed at this point, or else we could see memory
   // corruption in QuitBrowser().
   CHECK_EQ(0U, chrome::GetTotalBrowserCount());
+  invalidation_forwarders_.clear();
   clients_.clear();
 }
 
@@ -512,6 +519,44 @@
   factory_.reset();
 }
 
+void SyncTest::DecideServerType() {
+  // Only set |server_type_| if it hasn't already been set. This allows for
+  // tests to explicitly set this value in each test class if needed.
+  if (server_type_ == SERVER_TYPE_UNDECIDED) {
+    base::CommandLine* cl = base::CommandLine::ForCurrentProcess();
+    if (!cl->HasSwitch(switches::kSyncServiceURL) &&
+        !cl->HasSwitch(switches::kSyncServerCommandLine)) {
+      // If neither a sync server URL nor a sync server command line is
+      // provided, start up a local sync test server and point Chrome
+      // to its URL.  This is the most common configuration, and the only
+      // one that makes sense for most developers. FakeServer is the
+      // current solution but some scenarios are only supported by the
+      // legacy python server.
+      // TODO(pvalenzuela): Make FAKE_SERVER the default and LOCAL_PYTHON
+      // the exception once more scenarios are supported.
+        server_type_ = test_type_ == SINGLE_CLIENT ?
+              IN_PROCESS_FAKE_SERVER : LOCAL_PYTHON_SERVER;
+    } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
+               cl->HasSwitch(switches::kSyncServerCommandLine)) {
+      // If a sync server URL and a sync server command line are provided,
+      // start up a local sync server by running the command line. Chrome
+      // will connect to the server at the URL that was provided.
+      server_type_ = LOCAL_LIVE_SERVER;
+    } else if (cl->HasSwitch(switches::kSyncServiceURL) &&
+               !cl->HasSwitch(switches::kSyncServerCommandLine)) {
+      // If a sync server URL is provided, but not a server command line,
+      // it is assumed that the server is already running. Chrome will
+      // automatically connect to it at the URL provided. There is nothing
+      // to do here.
+      server_type_ = EXTERNAL_LIVE_SERVER;
+    } else {
+      // If a sync server command line is provided, but not a server URL,
+      // we flag an error.
+      LOG(FATAL) << "Can't figure out how to run a server.";
+    }
+  }
+}
+
 // Start up a local sync server based on the value of server_type_, which
 // was determined from the command line parameters.
 void SyncTest::SetUpTestServerIfRequired() {
@@ -668,11 +713,29 @@
 }
 
 bool SyncTest::EnableEncryption(int index) {
-  return GetClient(index)->EnableEncryption();
+  ProfileSyncService* service = GetClient(index)->service();
+
+  if (::IsEncryptionComplete(service))
+    return true;
+
+  service->EnableEncryptEverything();
+
+  // In order to kick off the encryption we have to reconfigure. Just grab the
+  // currently synced types and use them.
+  const syncer::ModelTypeSet synced_datatypes =
+      service->GetPreferredDataTypes();
+  bool sync_everything = synced_datatypes.Equals(syncer::ModelTypeSet::All());
+  service->OnUserChoseDatatypes(sync_everything, synced_datatypes);
+
+  // Wait some time to let the enryption finish.
+  EncryptionChecker checker(service);
+  checker.Await();
+
+  return !checker.TimedOut();
 }
 
 bool SyncTest::IsEncryptionComplete(int index) {
-  return GetClient(index)->IsEncryptionComplete();
+  return ::IsEncryptionComplete(GetClient(index)->service());
 }
 
 bool SyncTest::AwaitQuiescence() {
@@ -886,8 +949,3 @@
                  make_scoped_refptr(context_getter), proxy_config));
   done.Wait();
 }
-
-void SyncTest::UseFakeServer() {
-  DCHECK_EQ(SERVER_TYPE_UNDECIDED, server_type_);
-  server_type_ = IN_PROCESS_FAKE_SERVER;
-}
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h
index 3e7d12b..d833d54 100644
--- a/chrome/browser/sync/test/integration/sync_test.h
+++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -23,6 +23,7 @@
 
 class Profile;
 class ProfileSyncServiceHarness;
+class P2PInvalidationForwarder;
 
 namespace base {
 class CommandLine;
@@ -44,9 +45,15 @@
   // The different types of live sync tests that can be implemented.
   enum TestType {
     // Tests where only one client profile is synced with the server. Typically
-    // sanity level tests.
+    // sanity level tests. Safe to run against the FakeServer, not just the
+    // older python test server.
     SINGLE_CLIENT,
 
+    // Tests where only one client profile is synced with the server. "Legacy"
+    // means that the scenario isn't yet supported by the FakeServer so they
+    // should be run against the python server instead.
+    SINGLE_CLIENT_LEGACY,
+
     // Tests where two client profiles are synced with the server. Typically
     // functionality level tests.
     TWO_CLIENT,
@@ -74,17 +81,6 @@
                             // LOCAL_PYTHON_SERVER.
   };
 
-  // This enum is used in conjunction with WithParamInterface to run tests with
-  // and without the fake server.
-  // TODO(pvalenzuela): Remove this when FakeServer is the default server.
-  enum FakeServerExperiment {
-    // The test should use the default logic for determining the test server.
-    USE_DEFAULT_SERVER,
-
-    // The test should use the fake server.
-    USE_FAKE_SERVER,
-  };
-
   // NOTE: IMPORTANT the enum here should match with
   // the enum defined on the chromiumsync.py test server impl.
   enum SyncErrorFrequency {
@@ -266,12 +262,6 @@
   void DisableNotificationsImpl();
   void EnableNotificationsImpl();
 
-  // Set up the test to use the in-process fake server. This must be called
-  // before SetUp().
-  // TODO(pvalenzuela): Remove this method when the C++ fake server becomes
-  // the default server type.
-  void UseFakeServer();
-
   // GAIA account used by the test case.
   std::string username_;
 
@@ -338,6 +328,10 @@
   // the default URLFetcher creation mechanism.
   void ClearMockGaiaResponses();
 
+  // Decide which sync server implementation to run against based on the type
+  // of test being run and command line args passed in.
+  void DecideServerType();
+
   // Python sync test server, started on demand.
   syncer::LocalSyncTestServer sync_server_;
 
@@ -370,6 +364,10 @@
   // profile with the server.
   ScopedVector<ProfileSyncServiceHarness> clients_;
 
+  // A set of objects to listen for commit activity and broadcast notifications
+  // of this activity to its peer sync clients.
+  ScopedVector<P2PInvalidationForwarder> invalidation_forwarders_;
+
   // Sync profile against which changes to individual profiles are verified. We
   // don't need a corresponding verifier sync client because the contents of the
   // verifier profile are strictly local, and are not meant to be synced.
diff --git a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
index 2495541..cfcd6b3 100644
--- a/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_app_list_sync_test.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/sync/test/integration/apps_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/sync_app_list_helper.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service.h"
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
@@ -28,6 +29,7 @@
 using apps_helper::InstallApp;
 using apps_helper::InstallAppsPendingForSync;
 using apps_helper::UninstallApp;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 namespace {
 
@@ -346,7 +348,7 @@
   ASSERT_TRUE(GetClient(1)->DisableSyncForDatatype(syncer::APP_LIST));
   InstallApp(GetProfile(0), 0);
   InstallApp(verifier(), 0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(HasSameAppsAsVerifier(0));
   ASSERT_FALSE(HasSameAppsAsVerifier(1));
 
@@ -368,7 +370,7 @@
   ASSERT_TRUE(GetClient(1)->DisableSyncForAllDatatypes());
   InstallApp(GetProfile(0), 0);
   InstallApp(verifier(), 0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(HasSameAppsAsVerifier(0));
   ASSERT_FALSE(HasSameAppsAsVerifier(1));
 
diff --git a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
index b99a9a9..23a0a76 100644
--- a/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_apps_sync_test.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/sync/test/integration/apps_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/sync_app_helper.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "extensions/browser/app_sorting.h"
@@ -30,6 +31,7 @@
 using apps_helper::SetAppLaunchOrdinalForApp;
 using apps_helper::SetPageOrdinalForApp;
 using apps_helper::UninstallApp;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class TwoClientAppsSyncTest : public SyncTest {
  public:
@@ -308,7 +310,7 @@
   ASSERT_TRUE(GetClient(1)->DisableSyncForDatatype(syncer::APPS));
   InstallApp(GetProfile(0), 0);
   InstallApp(verifier(), 0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(HasSameAppsAsVerifier(0));
   ASSERT_FALSE(HasSameAppsAsVerifier(1));
 
@@ -331,7 +333,7 @@
   ASSERT_TRUE(GetClient(1)->DisableSyncForAllDatatypes());
   InstallApp(GetProfile(0), 0);
   InstallApp(verifier(), 0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(HasSameAppsAsVerifier(0));
   ASSERT_FALSE(HasSameAppsAsVerifier(1));
 
diff --git a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
index 0791328..1d2f957 100644
--- a/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_autofill_sync_test.cc
@@ -6,6 +6,7 @@
 #include "chrome/browser/sync/test/integration/autofill_helper.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
@@ -39,6 +40,7 @@
 using bookmarks_helper::AddURL;
 using bookmarks_helper::IndexedURL;
 using bookmarks_helper::IndexedURLTitle;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class TwoClientAutofillSyncTest : public SyncTest {
  public:
@@ -382,7 +384,7 @@
   ASSERT_TRUE(GetClient(1)->DisableSyncForAllDatatypes());
   AddProfile(0, CreateAutofillProfile(PROFILE_FRASIER));
   MakeABookmarkChange(0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_FALSE(ProfilesMatch(0, 1));
   ASSERT_EQ(2U, GetAllProfiles(0).size());
   ASSERT_EQ(1U, GetAllProfiles(1).size());
diff --git a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
index 1491ff2..7e74189 100644
--- a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc
@@ -7,6 +7,7 @@
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/passwords_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
 #include "ui/base/layout.h"
@@ -38,6 +39,9 @@
 using bookmarks_helper::SortChildren;
 using passwords_helper::SetDecryptionPassphrase;
 using passwords_helper::SetEncryptionPassphrase;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
+using sync_integration_test_util::AwaitPassphraseAccepted;
+using sync_integration_test_util::AwaitPassphraseRequired;
 
 const std::string kGenericURL = "http://www.host.ext:1234/path/filename";
 const std::wstring kGenericURLTitle = L"URL Title";
@@ -1567,7 +1571,7 @@
 
   ASSERT_TRUE(GetClient(1)->DisableSyncForAllDatatypes());
   ASSERT_TRUE(AddFolder(0, IndexedFolderName(0)) != NULL);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_FALSE(AllModelsMatch());
 
   ASSERT_TRUE(AddFolder(1, IndexedFolderName(1)) != NULL);
@@ -1613,7 +1617,7 @@
   ASSERT_TRUE(AddURL(0, GetBookmarkBarNode(0), 0, L"bar", bar_url) != NULL);
   ASSERT_TRUE(AddURL(0, GetOtherNode(0), 0, L"other", other_url) != NULL);
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_TRUE(HasNodeWithURL(0, bar_url));
   ASSERT_TRUE(HasNodeWithURL(0, other_url));
@@ -1621,7 +1625,7 @@
   ASSERT_FALSE(HasNodeWithURL(1, other_url));
 
   Remove(0, GetBookmarkBarNode(0), 0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_FALSE(HasNodeWithURL(0, bar_url));
   ASSERT_TRUE(HasNodeWithURL(0, other_url));
@@ -1850,7 +1854,7 @@
   // Set a passphrase and enable encryption on Client 0. Client 1 will not
   // understand the bookmark updates.
   SetEncryptionPassphrase(0, kValidPassphrase, ProfileSyncService::EXPLICIT);
-  ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(0)->service()));
   ASSERT_TRUE(EnableEncryption(0));
   ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
   ASSERT_TRUE(IsEncryptionComplete(0));
@@ -1864,9 +1868,9 @@
   EXPECT_FALSE(AllModelsMatch());
 
   // Set the passphrase. Everything should resolve.
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired());
+  ASSERT_TRUE(AwaitPassphraseRequired(GetClient(1)->service()));
   ASSERT_TRUE(SetDecryptionPassphrase(1, kValidPassphrase));
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(1)->service()));
   ASSERT_TRUE(AwaitQuiescence());
   EXPECT_TRUE(AllModelsMatch());
   ASSERT_EQ(0,
diff --git a/chrome/browser/sync/test/integration/two_client_dictionary_sync_test.cc b/chrome/browser/sync/test/integration/two_client_dictionary_sync_test.cc
index 7d160d1..4566266 100644
--- a/chrome/browser/sync/test/integration/two_client_dictionary_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_dictionary_sync_test.cc
@@ -5,9 +5,12 @@
 #include "base/strings/string_number_conversions.h"
 #include "chrome/browser/sync/test/integration/dictionary_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/common/spellcheck_common.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
+
 class TwoClientDictionarySyncTest : public SyncTest {
  public:
   TwoClientDictionarySyncTest() : SyncTest(TWO_CLIENT) {}
@@ -106,7 +109,7 @@
 
   ASSERT_TRUE(GetClient(1)->DisableSyncForAllDatatypes());
   ASSERT_TRUE(dictionary_helper::AddWord(0, "foo"));
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(dictionary_helper::DictionaryMatchesVerifier(0));
   ASSERT_FALSE(dictionary_helper::DictionaryMatchesVerifier(1));
 }
diff --git a/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc b/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc
index 37b782f..b031f55 100644
--- a/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_extensions_sync_test.cc
@@ -5,6 +5,7 @@
 #include "base/basictypes.h"
 #include "chrome/browser/sync/test/integration/extensions_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
 using extensions_helper::AllProfilesHaveSameExtensionsAsVerifier;
@@ -16,6 +17,7 @@
 using extensions_helper::InstallExtension;
 using extensions_helper::InstallExtensionsPendingForSync;
 using extensions_helper::UninstallExtension;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class TwoClientExtensionsSyncTest : public SyncTest {
  public:
@@ -248,7 +250,7 @@
   InstallExtension(GetProfile(0), 1);
   InstallExtension(verifier(), 1);
   ASSERT_TRUE(
-      GetClient(0)->AwaitCommitActivityCompletion());
+      AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_FALSE(AllProfilesHaveSameExtensionsAsVerifier());
 
   ASSERT_TRUE(GetClient(1)->EnableSyncForDatatype(syncer::EXTENSIONS));
@@ -268,7 +270,7 @@
   InstallExtension(GetProfile(0), 0);
   InstallExtension(verifier(), 0);
   ASSERT_TRUE(
-      GetClient(0)->AwaitCommitActivityCompletion());
+      AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(HasSameExtensionsAsVerifier(0));
   ASSERT_FALSE(HasSameExtensionsAsVerifier(1));
 
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
index da167bf..ac8cb93 100644
--- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -5,6 +5,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/sync/test/integration/passwords_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "sync/internal_api/public/engine/model_safe_worker.h"
 #include "sync/internal_api/public/sessions/sync_session_snapshot.h"
@@ -23,6 +24,9 @@
 using passwords_helper::SetDecryptionPassphrase;
 using passwords_helper::SetEncryptionPassphrase;
 using passwords_helper::UpdateLogin;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
+using sync_integration_test_util::AwaitPassphraseAccepted;
+using sync_integration_test_util::AwaitPassphraseRequired;
 
 using autofill::PasswordForm;
 
@@ -80,7 +84,7 @@
   AddLogin(GetPasswordStore(0), form);
   ASSERT_EQ(1, GetPasswordCount(0));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ProfileContainsSamePasswordFormsAsVerifier(0));
   ASSERT_FALSE(ProfileContainsSamePasswordFormsAsVerifier(1));
 
@@ -102,7 +106,7 @@
   AddLogin(GetPasswordStore(0), form);
   ASSERT_EQ(1, GetPasswordCount(0));
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(ProfileContainsSamePasswordFormsAsVerifier(0));
   ASSERT_FALSE(ProfileContainsSamePasswordFormsAsVerifier(1));
 
@@ -116,13 +120,13 @@
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
 
   SetEncryptionPassphrase(0, kValidPassphrase, ProfileSyncService::EXPLICIT);
-  ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(0)->service()));
   ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
 
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired());
+  ASSERT_TRUE(AwaitPassphraseRequired(GetClient(1)->service()));
   ASSERT_TRUE(SetDecryptionPassphrase(1, kValidPassphrase));
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted());
-  ASSERT_TRUE(GetClient(1)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(1)->service()));
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(1)->service()));
 }
 
 IN_PROC_BROWSER_TEST_F(TwoClientPasswordsSyncTest,
@@ -130,12 +134,12 @@
   ASSERT_TRUE(SetupSync()) << "SetupSync() failed.";
 
   SetEncryptionPassphrase(0, kValidPassphrase, ProfileSyncService::EXPLICIT);
-  ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(0)->service()));
   ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
 
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired());
+  ASSERT_TRUE(AwaitPassphraseRequired(GetClient(1)->service()));
   ASSERT_TRUE(SetDecryptionPassphrase(1, kValidPassphrase));
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(1)->service()));
 
   PasswordForm form = CreateTestPasswordForm(0);
   AddLogin(GetPasswordStore(0), form);
@@ -235,14 +239,19 @@
 
   ASSERT_TRUE(GetClient(0)->SetupSync());
   SetEncryptionPassphrase(0, kValidPassphrase, ProfileSyncService::EXPLICIT);
-  ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted());
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(0)->service()));
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_FALSE(GetClient(1)->SetupSync());
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired());
+  ASSERT_TRUE(AwaitPassphraseRequired(GetClient(1)->service()));
   ASSERT_TRUE(SetDecryptionPassphrase(1, kValidPassphrase));
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted());
-  ASSERT_TRUE(GetClient(1)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(1)->service()));
+
+  // For some reason, the tests won't pass unless these flags are set.
+  GetClient(1)->service()->SetSetupInProgress(false);
+  GetClient(1)->service()->SetSyncSetupCompleted();
+
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(1)->service()));
 
   // Following ensures types are enabled and active (see bug 87572).
   syncer::ModelSafeRoutingInfo routes;
@@ -259,29 +268,33 @@
 
   ASSERT_TRUE(GetClient(0)->SetupSync());
   SetEncryptionPassphrase(0, kValidPassphrase, ProfileSyncService::EXPLICIT);
-  ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted());
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(0)->service()));
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   // Setup 1 with a different passphrase, so that it fails to sync.
   ASSERT_FALSE(GetClient(1)->SetupSync());
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired());
+  ASSERT_TRUE(AwaitPassphraseRequired(GetClient(1)->service()));
   ASSERT_FALSE(SetDecryptionPassphrase(1, kAnotherValidPassphrase));
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired());
+  ASSERT_TRUE(AwaitPassphraseRequired(GetClient(1)->service()));
 
   // Add a password on 0 while clients have different passphrases.
   PasswordForm form0 = CreateTestPasswordForm(0);
   AddLogin(GetVerifierPasswordStore(), form0);
   AddLogin(GetPasswordStore(0), form0);
 
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   // Password hasn't been synced to 1 yet.
   ASSERT_FALSE(AllProfilesContainSamePasswordFormsAsVerifier());
 
   // Update 1 with the correct passphrase, the password should now sync over.
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired());
+  ASSERT_TRUE(AwaitPassphraseRequired(GetClient(1)->service()));
   ASSERT_TRUE(SetDecryptionPassphrase(1, kValidPassphrase));
-  ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted());
+  ASSERT_TRUE(AwaitPassphraseAccepted(GetClient(1)->service()));
+
+  // For some reason, the tests won't pass unless these flags are set.
+  GetClient(1)->service()->SetSetupInProgress(false);
+  GetClient(1)->service()->SetSyncSetupCompleted();
 
   ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
   ASSERT_TRUE(AllProfilesContainSamePasswordFormsAsVerifier());
diff --git a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
index 3efadea..1811063 100644
--- a/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_preferences_sync_test.cc
@@ -5,6 +5,7 @@
 #include "base/values.h"
 #include "chrome/browser/sync/test/integration/preferences_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/translate/translate_tab_helper.h"
 #include "chrome/common/pref_names.h"
@@ -25,6 +26,7 @@
 using preferences_helper::Int64PrefMatches;
 using preferences_helper::ListPrefMatches;
 using preferences_helper::StringPrefMatches;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class TwoClientPreferencesSyncTest : public SyncTest {
  public:
@@ -95,7 +97,7 @@
 
   GetClient(1)->DisableSyncForDatatype(syncer::PREFERENCES);
   ChangeBooleanPref(0, prefs::kPasswordManagerEnabled);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_FALSE(BooleanPrefMatches(prefs::kPasswordManagerEnabled));
 
   GetClient(1)->EnableSyncForDatatype(syncer::PREFERENCES);
@@ -114,7 +116,7 @@
 
   GetClient(1)->DisableSyncForAllDatatypes();
   ChangeBooleanPref(0, prefs::kPasswordManagerEnabled);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_FALSE(BooleanPrefMatches(prefs::kPasswordManagerEnabled));
 
   ChangeBooleanPref(1, prefs::kShowHomeButton);
diff --git a/chrome/browser/sync/test/integration/two_client_search_engines_sync_test.cc b/chrome/browser/sync/test/integration/two_client_search_engines_sync_test.cc
index e25d5b6..dd567de 100644
--- a/chrome/browser/sync/test/integration/two_client_search_engines_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_search_engines_sync_test.cc
@@ -9,9 +9,11 @@
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
 #include "chrome/browser/sync/test/integration/search_engines_helper.h"
 #include "chrome/browser/sync/test/integration/sync_datatype_helper.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 
 using base::ASCIIToUTF16;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 
 class TwoClientSearchEnginesSyncTest : public SyncTest {
  public:
@@ -192,7 +194,7 @@
   ASSERT_TRUE(GetClient(1)->DisableSyncForAllDatatypes());
   search_engines_helper::AddSearchEngine(0, 0);
   ASSERT_TRUE(
-      GetClient(0)->AwaitCommitActivityCompletion());
+      AwaitCommitActivityCompletion(GetClient(0)->service()));
   ASSERT_TRUE(search_engines_helper::ServiceMatchesVerifier(0));
   ASSERT_FALSE(search_engines_helper::ServiceMatchesVerifier(1));
 
diff --git a/chrome/browser/sync/test/integration/two_client_themes_sync_test.cc b/chrome/browser/sync/test/integration/two_client_themes_sync_test.cc
index 22fb8b9..91d5354 100644
--- a/chrome/browser/sync/test/integration/two_client_themes_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_themes_sync_test.cc
@@ -4,9 +4,11 @@
 
 #include "base/basictypes.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/sync/test/integration/themes_helper.h"
 
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 using themes_helper::GetCustomTheme;
 using themes_helper::GetThemeID;
 using themes_helper::HasOrWillHaveCustomTheme;
@@ -204,7 +206,7 @@
   ASSERT_TRUE(GetClient(1)->DisableSyncForDatatype(syncer::THEMES));
   UseCustomTheme(GetProfile(0), 0);
   UseCustomTheme(verifier(), 0);
-  ASSERT_TRUE(GetClient(0)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_EQ(GetCustomTheme(0), GetThemeID(GetProfile(0)));
   ASSERT_FALSE(UsingCustomTheme(GetProfile(1)));
@@ -231,7 +233,7 @@
   UseCustomTheme(GetProfile(0), 0);
   UseCustomTheme(verifier(), 0);
   ASSERT_TRUE(
-      GetClient(0)->AwaitCommitActivityCompletion());
+      AwaitCommitActivityCompletion(GetClient(0)->service()));
 
   ASSERT_EQ(GetCustomTheme(0), GetThemeID(GetProfile(0)));
   ASSERT_FALSE(UsingCustomTheme(GetProfile(1)));
diff --git a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
index eff6a38..10812dc 100644
--- a/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_typed_urls_sync_test.cc
@@ -9,10 +9,12 @@
 #include "chrome/browser/sessions/session_service.h"
 #include "chrome/browser/sync/test/integration/bookmarks_helper.h"
 #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h"
+#include "chrome/browser/sync/test/integration/sync_integration_test_util.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/sync/test/integration/typed_urls_helper.h"
 
 using base::ASCIIToUTF16;
+using sync_integration_test_util::AwaitCommitActivityCompletion;
 using typed_urls_helper::AddUrlToHistory;
 using typed_urls_helper::AddUrlToHistoryWithTimestamp;
 using typed_urls_helper::AddUrlToHistoryWithTransition;
@@ -202,7 +204,7 @@
   GURL url2(kUrl2);
   AddUrlToHistory(0, url1);
   AddUrlToHistory(1, url2);
-  ASSERT_TRUE(GetClient(1)->AwaitCommitActivityCompletion());
+  ASSERT_TRUE(AwaitCommitActivityCompletion(GetClient(1)->service()));
 
   // Make sure that no data was exchanged.
   history::URLRows post_sync_urls = GetTypedUrlsFromClient(0);
@@ -313,7 +315,7 @@
   // before syncing client 0, so we have both of client 1's URLs in the sync DB
   // at the time that client 0 does model association.
   ASSERT_TRUE(GetClient(1)->SetupSync()) << "SetupSync() failed";
-  GetClient(1)->AwaitCommitActivityCompletion();
+  AwaitCommitActivityCompletion(GetClient(1)->service());
   ASSERT_TRUE(GetClient(0)->SetupSync()) << "SetupSync() failed";
   ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1)));
 
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index b1f8856..58f8164 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -5,12 +5,13 @@
 #include "chrome/browser/sync/test_profile_sync_service.h"
 
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/managed_mode/managed_user_signin_manager_wrapper.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/sync/glue/sync_backend_host.h"
 #include "chrome/browser/sync/glue/sync_backend_host_core.h"
+#include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
 #include "chrome/browser/sync/profile_sync_components_factory.h"
 #include "chrome/browser/sync/profile_sync_components_factory_mock.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -103,11 +104,11 @@
     SigninManagerBase* signin,
     ProfileOAuth2TokenService* oauth2_token_service,
     browser_sync::ProfileSyncServiceStartBehavior behavior)
-        : ProfileSyncService(factory,
-                             profile,
-                             new ManagedUserSigninManagerWrapper(signin),
-                             oauth2_token_service,
-                             behavior) {
+    : ProfileSyncService(factory,
+                         profile,
+                         new ManagedUserSigninManagerWrapper(profile, signin),
+                         oauth2_token_service,
+                         behavior) {
   SetSyncSetupCompleted();
 }
 
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index 245c51e..77936a0 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -13,7 +13,7 @@
 #include "chrome/browser/sync/glue/data_type_manager_impl.h"
 #include "chrome/browser/sync/glue/sync_backend_host_impl.h"
 #include "chrome/browser/sync/profile_sync_service.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/sync_prefs.h"
 #include "sync/test/engine/test_id_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/browser/sync_file_system/drive_backend/conflict_resolver.cc b/chrome/browser/sync_file_system/drive_backend/conflict_resolver.cc
index 726520f..a885772 100644
--- a/chrome/browser/sync_file_system/drive_backend/conflict_resolver.cc
+++ b/chrome/browser/sync_file_system/drive_backend/conflict_resolver.cc
@@ -23,11 +23,9 @@
 
 ConflictResolver::ConflictResolver(SyncEngineContext* sync_context)
     : sync_context_(sync_context),
-      weak_ptr_factory_(this) {
-}
+      weak_ptr_factory_(this) {}
 
-ConflictResolver::~ConflictResolver() {
-}
+ConflictResolver::~ConflictResolver() {}
 
 void ConflictResolver::RunSequential(const SyncStatusCallback& callback) {
   if (!IsContextReady()) {
diff --git a/chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc b/chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc
index 6f33490..8e2b25d 100644
--- a/chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/conflict_resolver_unittest.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
 #include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
@@ -43,8 +44,7 @@
 
 }  // namespace
 
-class ConflictResolverTest : public testing::Test,
-                             public SyncEngineContext {
+class ConflictResolverTest : public testing::Test {
  public:
   typedef FakeRemoteChangeProcessor::URLToFileChangesMap URLToFileChangesMap;
 
@@ -56,74 +56,78 @@
     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
 
-    fake_drive_service_.reset(new FakeDriveServiceWrapper);
-    ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
+    scoped_ptr<FakeDriveServiceWrapper>
+        fake_drive_service(new FakeDriveServiceWrapper);
+    ASSERT_TRUE(fake_drive_service->LoadAccountMetadataForWapi(
         "sync_file_system/account_metadata.json"));
-    ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
+    ASSERT_TRUE(fake_drive_service->LoadResourceListForWapi(
         "gdata/empty_feed.json"));
 
-    drive_uploader_.reset(new FakeDriveUploader(fake_drive_service_.get()));
+    scoped_ptr<drive::DriveUploaderInterface>
+        drive_uploader(new FakeDriveUploader(fake_drive_service.get()));
     fake_drive_helper_.reset(new FakeDriveServiceHelper(
-        fake_drive_service_.get(), drive_uploader_.get(),
-        kSyncRootFolderTitle));
+        fake_drive_service.get(), drive_uploader.get(), kSyncRootFolderTitle));
     fake_remote_change_processor_.reset(new FakeRemoteChangeProcessor);
 
+    context_.reset(new SyncEngineContext(
+        fake_drive_service.PassAs<drive::DriveServiceInterface>(),
+        drive_uploader.Pass(), base::MessageLoopProxy::current()));
+    context_->SetRemoteChangeProcessor(fake_remote_change_processor_.get());
+
     RegisterSyncableFileSystem();
+
+    sync_task_manager_.reset(new SyncTaskManager(
+        base::WeakPtr<SyncTaskManager::Client>(),
+        10 /* maximum_background_task */));
+    sync_task_manager_->Initialize(SYNC_STATUS_OK);
   }
 
   virtual void TearDown() OVERRIDE {
+    sync_task_manager_.reset();
+
     RevokeSyncableFileSystem();
 
     fake_remote_change_processor_.reset();
-    metadata_database_.reset();
     fake_drive_helper_.reset();
-    drive_uploader_.reset();
-    fake_drive_service_.reset();
+    context_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
   void InitializeMetadataDatabase() {
-    SyncEngineInitializer initializer(this,
-                                      base::MessageLoopProxy::current(),
-                                      fake_drive_service_.get(),
-                                      database_dir_.path(),
-                                      in_memory_env_.get());
+    SyncEngineInitializer* initializer =
+        new SyncEngineInitializer(context_.get(),
+                                  base::MessageLoopProxy::current(),
+                                  context_->GetDriveService(),
+                                  database_dir_.path(),
+                                  in_memory_env_.get());
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    initializer.RunSequential(CreateResultReceiver(&status));
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE,
+        scoped_ptr<SyncTask>(initializer),
+        SyncTaskManager::PRIORITY_MED,
+        base::Bind(&ConflictResolverTest::DidInitializeMetadataDatabase,
+                   base::Unretained(this), initializer, &status));
+
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(SYNC_STATUS_OK, status);
-    metadata_database_ = initializer.PassMetadataDatabase();
+  }
+
+  void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer,
+                                     SyncStatusCode* status_out,
+                                     SyncStatusCode status) {
+    context_->SetMetadataDatabase(initializer->PassMetadataDatabase());
+    *status_out = status;
   }
 
   void RegisterApp(const std::string& app_id,
                    const std::string& app_root_folder_id) {
     SyncStatusCode status = SYNC_STATUS_FAILED;
-    metadata_database_->RegisterApp(app_id, app_root_folder_id,
-                                    CreateResultReceiver(&status));
+    context_->GetMetadataDatabase()->RegisterApp(app_id, app_root_folder_id,
+                                                 CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(SYNC_STATUS_OK, status);
   }
 
-  virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
-    return fake_drive_service_.get();
-  }
-
-  virtual drive::DriveUploaderInterface* GetDriveUploader() OVERRIDE {
-    return drive_uploader_.get();
-  }
-
-  virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
-    return metadata_database_.get();
-  }
-
-  virtual RemoteChangeProcessor* GetRemoteChangeProcessor() OVERRIDE {
-    return fake_remote_change_processor_.get();
-  }
-
-  virtual base::SequencedTaskRunner* GetBlockingTaskRunner() OVERRIDE {
-    return base::MessageLoopProxy::current().get();
-  }
-
  protected:
   std::string CreateSyncRoot() {
     std::string sync_root_folder_id;
@@ -162,7 +166,7 @@
       const std::string& parent_folder_id,
       const std::string& file_id) {
     google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
-    fake_drive_service_->AddResourceToDirectory(
+    context_->GetDriveService()->AddResourceToDirectory(
         parent_folder_id, file_id,
         CreateResultReceiver(&error));
     base::RunLoop().RunUntilIdle();
@@ -185,7 +189,8 @@
 
   SyncStatusCode RunRemoteToLocalSyncer() {
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    scoped_ptr<RemoteToLocalSyncer> syncer(new RemoteToLocalSyncer(this));
+    scoped_ptr<RemoteToLocalSyncer> syncer(
+        new RemoteToLocalSyncer(context_.get()));
     syncer->RunSequential(CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
@@ -199,7 +204,8 @@
     if (file_change.IsAddOrUpdate())
       CreateTemporaryFileInDir(database_dir_.path(), &local_path);
     scoped_ptr<LocalToRemoteSyncer> syncer(new LocalToRemoteSyncer(
-        this, SyncFileMetadata(file_change.file_type(), 0, base::Time()),
+        context_.get(),
+        SyncFileMetadata(file_change.file_type(), 0, base::Time()),
         file_change, local_path, url));
     syncer->RunSequential(CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
@@ -216,16 +222,19 @@
 
   SyncStatusCode RunConflictResolver() {
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    ConflictResolver resolver(this);
+    ConflictResolver resolver(context_.get());
     resolver.RunSequential(CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
   }
 
   SyncStatusCode ListChanges() {
-    ListChangesTask list_changes(this);
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    list_changes.RunSequential(CreateResultReceiver(&status));
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE,
+        scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
+        SyncTaskManager::PRIORITY_MED,
+        CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
   }
@@ -263,12 +272,12 @@
   base::ScopedTempDir database_dir_;
   scoped_ptr<leveldb::Env> in_memory_env_;
 
-  scoped_ptr<FakeDriveServiceWrapper> fake_drive_service_;
-  scoped_ptr<FakeDriveUploader> drive_uploader_;
+  scoped_ptr<SyncEngineContext> context_;
   scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
-  scoped_ptr<MetadataDatabase> metadata_database_;
   scoped_ptr<FakeRemoteChangeProcessor> fake_remote_change_processor_;
 
+  scoped_ptr<SyncTaskManager> sync_task_manager_;
+
   DISALLOW_COPY_AND_ASSIGN(ConflictResolverTest);
 };
 
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc
index aee5b4b..a53b956 100644
--- a/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc
+++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc
@@ -68,11 +68,11 @@
     const google_apis::FileResource& file_resource,
     FileDetails* details) {
   details->clear_parent_folder_ids();
-  for (ScopedVector<google_apis::ParentReference>::const_iterator itr =
+  for (std::vector<google_apis::ParentReference>::const_iterator itr =
            file_resource.parents().begin();
        itr != file_resource.parents().end();
        ++itr) {
-    details->add_parent_folder_ids((*itr)->file_id());
+    details->add_parent_folder_ids(itr->file_id());
   }
   details->set_title(file_resource.title());
 
diff --git a/chrome/browser/sync_file_system/drive_backend/list_changes_task.cc b/chrome/browser/sync_file_system/drive_backend/list_changes_task.cc
index 404b1da..3899409 100644
--- a/chrome/browser/sync_file_system/drive_backend/list_changes_task.cc
+++ b/chrome/browser/sync_file_system/drive_backend/list_changes_task.cc
@@ -13,6 +13,8 @@
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
 #include "chrome/browser/sync_file_system/logger.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
 #include "google_apis/drive/drive_api_parser.h"
@@ -45,31 +47,34 @@
 ListChangesTask::~ListChangesTask() {
 }
 
-void ListChangesTask::RunSequential(const SyncStatusCallback& callback) {
+void ListChangesTask::Run(scoped_ptr<SyncTaskToken> token) {
   util::Log(logging::LOG_VERBOSE, FROM_HERE, "[Changes] Start.");
 
   if (!IsContextReady()) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
-              "[Changes] Failed to get required sercive.");
-    RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED));
+              "[Changes] Failed to get required service.");
+    RunSoon(FROM_HERE, base::Bind(&SyncTaskManager::NotifyTaskDone,
+                                  base::Passed(&token),
+                                  SYNC_STATUS_FAILED));
     return;
   }
 
   drive_service()->GetChangeList(
       metadata_database()->GetLargestFetchedChangeID() + 1,
       base::Bind(&ListChangesTask::DidListChanges,
-                 weak_ptr_factory_.GetWeakPtr(), callback));
+                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
 }
 
 void ListChangesTask::DidListChanges(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     google_apis::GDataErrorCode error,
     scoped_ptr<google_apis::ResourceList> resource_list) {
   SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Changes] Failed to fetch change list.");
-    callback.Run(SYNC_STATUS_NETWORK_ERROR);
+    SyncTaskManager::NotifyTaskDone(
+        token.Pass(), SYNC_STATUS_NETWORK_ERROR);
     return;
   }
 
@@ -77,7 +82,8 @@
     NOTREACHED();
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Changes] Got invalid change list.");
-    callback.Run(SYNC_STATUS_FAILED);
+    SyncTaskManager::NotifyTaskDone(
+        token.Pass(), SYNC_STATUS_FAILED);
     return;
   }
 
@@ -97,13 +103,14 @@
         base::Bind(
             &ListChangesTask::DidListChanges,
             weak_ptr_factory_.GetWeakPtr(),
-            callback));
+            base::Passed(&token)));
     return;
   }
 
   if (change_list_.empty()) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE, "[Changes] Got no change.");
-    callback.Run(SYNC_STATUS_NO_CHANGE_TO_SYNC);
+    SyncTaskManager::NotifyTaskDone(
+        token.Pass(), SYNC_STATUS_NO_CHANGE_TO_SYNC);
     return;
   }
 
@@ -112,7 +119,8 @@
             change_list_.size());
   metadata_database()->UpdateByChangeList(
       resource_list->largest_changestamp(),
-      change_list_.Pass(), callback);
+      change_list_.Pass(),
+      base::Bind(&SyncTaskManager::NotifyTaskDone, base::Passed(&token)));
 }
 
 bool ListChangesTask::IsContextReady() {
diff --git a/chrome/browser/sync_file_system/drive_backend/list_changes_task.h b/chrome/browser/sync_file_system/drive_backend/list_changes_task.h
index d45494e..f6b7832 100644
--- a/chrome/browser/sync_file_system/drive_backend/list_changes_task.h
+++ b/chrome/browser/sync_file_system/drive_backend/list_changes_task.h
@@ -9,7 +9,6 @@
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
-#include "chrome/browser/sync_file_system/sync_callbacks.h"
 #include "google_apis/drive/gdata_errorcode.h"
 
 namespace drive {
@@ -27,15 +26,15 @@
 class MetadataDatabase;
 class SyncEngineContext;
 
-class ListChangesTask : public SequentialSyncTask {
+class ListChangesTask : public SyncTask {
  public:
   explicit ListChangesTask(SyncEngineContext* sync_context);
   virtual ~ListChangesTask();
 
-  virtual void RunSequential(const SyncStatusCallback& callback) OVERRIDE;
+  virtual void Run(scoped_ptr<SyncTaskToken> token) OVERRIDE;
 
  private:
-  void DidListChanges(const SyncStatusCallback& callback,
+  void DidListChanges(scoped_ptr<SyncTaskToken> token,
                       google_apis::GDataErrorCode error,
                       scoped_ptr<google_apis::ResourceList> resource_list);
 
diff --git a/chrome/browser/sync_file_system/drive_backend/list_changes_task_unittest.cc b/chrome/browser/sync_file_system/drive_backend/list_changes_task_unittest.cc
index 1bde78e..38c430d 100644
--- a/chrome/browser/sync_file_system/drive_backend/list_changes_task_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/list_changes_task_unittest.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/drive/drive_api_parser.h"
@@ -32,8 +33,7 @@
 
 }  // namespace
 
-class ListChangesTaskTest : public testing::Test,
-                            public SyncEngineContext {
+class ListChangesTaskTest : public testing::Test {
  public:
   ListChangesTaskTest() {}
   virtual ~ListChangesTaskTest() {}
@@ -42,59 +42,54 @@
     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
 
-    fake_drive_service_.reset(new drive::FakeDriveService);
-    ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
+    scoped_ptr<drive::FakeDriveService>
+        fake_drive_service(new drive::FakeDriveService);
+    ASSERT_TRUE(fake_drive_service->LoadAccountMetadataForWapi(
         "sync_file_system/account_metadata.json"));
-    ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
+    ASSERT_TRUE(fake_drive_service->LoadResourceListForWapi(
         "gdata/empty_feed.json"));
 
-    drive_uploader_.reset(new drive::DriveUploader(
-        fake_drive_service_.get(), base::MessageLoopProxy::current()));
+    scoped_ptr<drive::DriveUploaderInterface>
+        drive_uploader(new drive::DriveUploader(
+            fake_drive_service.get(), base::MessageLoopProxy::current()));
 
     fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
-        fake_drive_service_.get(), drive_uploader_.get(),
-        kSyncRootFolderTitle));
+        fake_drive_service.get(), drive_uploader.get(), kSyncRootFolderTitle));
+
+    sync_task_manager_.reset(new SyncTaskManager(
+        base::WeakPtr<SyncTaskManager::Client>(),
+        10 /* maximum_background_task */));
+    sync_task_manager_->Initialize(SYNC_STATUS_OK);
+
+    context_.reset(new SyncEngineContext(
+        fake_drive_service.PassAs<drive::DriveServiceInterface>(),
+        drive_uploader.Pass(), base::MessageLoopProxy::current()));
 
     SetUpRemoteFolders();
+
     InitializeMetadataDatabase();
     RegisterApp(kAppID);
   }
 
   virtual void TearDown() OVERRIDE {
-    metadata_database_.reset();
+    sync_task_manager_.reset();
+    context_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
-  virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
-    return fake_drive_service_.get();
-  }
-
-  virtual drive::DriveUploader* GetDriveUploader() OVERRIDE {
-    return NULL;
-  }
-
-  virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
-    return metadata_database_.get();
-  }
-
-  virtual RemoteChangeProcessor* GetRemoteChangeProcessor() OVERRIDE {
-    return NULL;
-  }
-
-  virtual base::SequencedTaskRunner* GetBlockingTaskRunner() OVERRIDE {
-    return base::MessageLoopProxy::current();
-  }
-
  protected:
-  SyncStatusCode RunTask(SequentialSyncTask* sync_task) {
+  SyncStatusCode RunTask(scoped_ptr<SyncTask> sync_task) {
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    sync_task->RunSequential(CreateResultReceiver(&status));
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE, sync_task.Pass(),
+        SyncTaskManager::PRIORITY_MED,
+        CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
   }
 
   size_t CountDirtyTracker() {
-    return metadata_database_->CountDirtyTracker();
+    return context_->GetMetadataDatabase()->CountDirtyTracker();
   }
 
   FakeDriveServiceHelper* fake_drive_service_helper() {
@@ -137,7 +132,7 @@
   }
 
   std::string root_resource_id() {
-    return fake_drive_service_->GetRootResourceId();
+    return context_->GetDriveService()->GetRootResourceId();
   }
 
   std::string app_root_folder_id() {
@@ -148,6 +143,10 @@
     return unregistered_app_root_folder_id_;
   }
 
+  SyncEngineContext* GetSyncEngineContext() {
+    return context_.get();
+  }
+
  private:
   void SetUpRemoteFolders() {
     ASSERT_EQ(google_apis::HTTP_CREATED,
@@ -163,18 +162,36 @@
   }
 
   void InitializeMetadataDatabase() {
-    SyncEngineInitializer initializer(this,
-                                      base::MessageLoopProxy::current(),
-                                      fake_drive_service_.get(),
-                                      database_dir_.path(),
-                                      in_memory_env_.get());
-    EXPECT_EQ(SYNC_STATUS_OK, RunTask(&initializer));
-    metadata_database_ = initializer.PassMetadataDatabase();
+    SyncStatusCode status = SYNC_STATUS_UNKNOWN;
+    SyncEngineInitializer* initializer =
+        new SyncEngineInitializer(
+            context_.get(),
+            base::MessageLoopProxy::current(),
+            context_->GetDriveService(),
+            database_dir_.path(),
+            in_memory_env_.get());
+
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE, scoped_ptr<SyncTask>(initializer),
+        SyncTaskManager::PRIORITY_MED,
+        base::Bind(&ListChangesTaskTest::DidInitializeMetadataDatabase,
+                   base::Unretained(this), initializer, &status));
+
+    base::RunLoop().RunUntilIdle();
+
+    EXPECT_EQ(SYNC_STATUS_OK, status);
+  }
+
+  void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer,
+                                     SyncStatusCode* status_out,
+                                     SyncStatusCode status) {
+    context_->SetMetadataDatabase(initializer->PassMetadataDatabase());
+    *status_out = status;
   }
 
   void RegisterApp(const std::string& app_id) {
-    RegisterAppTask register_app(this, app_id);
-    EXPECT_EQ(SYNC_STATUS_OK, RunTask(&register_app));
+    EXPECT_EQ(SYNC_STATUS_OK, RunTask(scoped_ptr<SyncTask>(
+        new RegisterAppTask(context_.get(), app_id))));
   }
 
   scoped_ptr<leveldb::Env> in_memory_env_;
@@ -186,11 +203,10 @@
   content::TestBrowserThreadBundle browser_threads_;
   base::ScopedTempDir database_dir_;
 
-  scoped_ptr<drive::FakeDriveService> fake_drive_service_;
-  scoped_ptr<drive::DriveUploader> drive_uploader_;
+  scoped_ptr<SyncEngineContext> context_;
   scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
 
-  scoped_ptr<MetadataDatabase> metadata_database_;
+  scoped_ptr<SyncTaskManager> sync_task_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(ListChangesTaskTest);
 };
@@ -198,8 +214,8 @@
 TEST_F(ListChangesTaskTest, NoChange) {
   size_t num_dirty_trackers = CountDirtyTracker();
 
-  ListChangesTask list_changes(this);
-  EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC, RunTask(&list_changes));
+  EXPECT_EQ(SYNC_STATUS_NO_CHANGE_TO_SYNC, RunTask(
+      scoped_ptr<SyncTask>(new ListChangesTask(GetSyncEngineContext()))));
 
   EXPECT_EQ(num_dirty_trackers, CountDirtyTracker());
 }
@@ -210,8 +226,8 @@
   SetUpChangesInFolder(root_resource_id());
   SetUpChangesInFolder(unregistered_app_root_folder_id());
 
-  ListChangesTask list_changes(this);
-  EXPECT_EQ(SYNC_STATUS_OK, RunTask(&list_changes));
+  EXPECT_EQ(SYNC_STATUS_OK, RunTask(
+      scoped_ptr<SyncTask>(new ListChangesTask(GetSyncEngineContext()))));
 
   EXPECT_EQ(num_dirty_trackers, CountDirtyTracker());
 }
@@ -221,8 +237,8 @@
 
   SetUpChangesInFolder(app_root_folder_id());
 
-  ListChangesTask list_changes(this);
-  EXPECT_EQ(SYNC_STATUS_OK, RunTask(&list_changes));
+  EXPECT_EQ(SYNC_STATUS_OK, RunTask(
+      scoped_ptr<SyncTask>(new ListChangesTask(GetSyncEngineContext()))));
 
   EXPECT_EQ(num_dirty_trackers + 4, CountDirtyTracker());
 }
diff --git a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer_unittest.cc b/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer_unittest.cc
index 66a1aa3..f10debb 100644
--- a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer_unittest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
 #include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
@@ -45,8 +46,7 @@
 
 }  // namespace
 
-class LocalToRemoteSyncerTest : public testing::Test,
-                                public SyncEngineContext {
+class LocalToRemoteSyncerTest : public testing::Test {
  public:
   LocalToRemoteSyncerTest()
       : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP) {}
@@ -56,72 +56,81 @@
     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
 
-    fake_drive_service_.reset(new FakeDriveServiceWrapper);
-    ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
+    scoped_ptr<FakeDriveServiceWrapper>
+        fake_drive_service(new FakeDriveServiceWrapper);
+    ASSERT_TRUE(fake_drive_service->LoadAccountMetadataForWapi(
         "sync_file_system/account_metadata.json"));
-    ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
+    ASSERT_TRUE(fake_drive_service->LoadResourceListForWapi(
         "gdata/empty_feed.json"));
 
-    drive_uploader_.reset(new FakeDriveUploader(fake_drive_service_.get()));
+    scoped_ptr<drive::DriveUploaderInterface>
+        drive_uploader(new FakeDriveUploader(fake_drive_service.get()));
     fake_drive_helper_.reset(new FakeDriveServiceHelper(
-        fake_drive_service_.get(), drive_uploader_.get(),
-        kSyncRootFolderTitle));
+        fake_drive_service.get(), drive_uploader.get(), kSyncRootFolderTitle));
     fake_remote_change_processor_.reset(new FakeRemoteChangeProcessor);
 
+    context_.reset(new SyncEngineContext(
+        fake_drive_service.PassAs<drive::DriveServiceInterface>(),
+        drive_uploader.Pass(), base::MessageLoopProxy::current()));
+    context_->SetRemoteChangeProcessor(fake_remote_change_processor_.get());
+
     RegisterSyncableFileSystem();
+
+    sync_task_manager_.reset(new SyncTaskManager(
+        base::WeakPtr<SyncTaskManager::Client>(),
+        10 /* maximum_background_task */));
+    sync_task_manager_->Initialize(SYNC_STATUS_OK);
   }
 
   virtual void TearDown() OVERRIDE {
+    sync_task_manager_.reset();
+
     RevokeSyncableFileSystem();
 
     fake_remote_change_processor_.reset();
-    metadata_database_.reset();
     fake_drive_helper_.reset();
-    drive_uploader_.reset();
-    fake_drive_service_.reset();
+    context_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
   void InitializeMetadataDatabase() {
-    SyncEngineInitializer initializer(this,
-                                      base::MessageLoopProxy::current(),
-                                      fake_drive_service_.get(),
-                                      database_dir_.path(),
-                                      in_memory_env_.get());
+    SyncEngineInitializer* initializer =
+        new SyncEngineInitializer(context_.get(),
+                                  base::MessageLoopProxy::current(),
+                                  context_->GetDriveService(),
+                                  database_dir_.path(),
+                                  in_memory_env_.get());
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    initializer.RunSequential(CreateResultReceiver(&status));
+
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE,
+        scoped_ptr<SyncTask>(initializer),
+        SyncTaskManager::PRIORITY_MED,
+        base::Bind(&LocalToRemoteSyncerTest::DidInitializeMetadataDatabase,
+                   base::Unretained(this), initializer, &status));
+
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(SYNC_STATUS_OK, status);
-    metadata_database_ = initializer.PassMetadataDatabase();
+  }
+
+  void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer,
+                                     SyncStatusCode* status_out,
+                                     SyncStatusCode status) {
+    *status_out = status;
+    context_->SetMetadataDatabase(initializer->PassMetadataDatabase());
   }
 
   void RegisterApp(const std::string& app_id,
                    const std::string& app_root_folder_id) {
     SyncStatusCode status = SYNC_STATUS_FAILED;
-    metadata_database_->RegisterApp(app_id, app_root_folder_id,
-                                    CreateResultReceiver(&status));
+    context_->GetMetadataDatabase()->RegisterApp(
+        app_id, app_root_folder_id, CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(SYNC_STATUS_OK, status);
   }
 
-  virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
-    return fake_drive_service_.get();
-  }
-
-  virtual drive::DriveUploaderInterface* GetDriveUploader() OVERRIDE {
-    return drive_uploader_.get();
-  }
-
-  virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
-    return metadata_database_.get();
-  }
-
-  virtual RemoteChangeProcessor* GetRemoteChangeProcessor() OVERRIDE {
-    return fake_remote_change_processor_.get();
-  }
-
-  virtual base::SequencedTaskRunner* GetBlockingTaskRunner() OVERRIDE {
-    return base::MessageLoopProxy::current().get();
+  MetadataDatabase* GetMetadataDatabase() {
+    return context_->GetMetadataDatabase();
   }
 
  protected:
@@ -162,7 +171,8 @@
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
     base::FilePath local_path = base::FilePath::FromUTF8Unsafe("dummy");
     scoped_ptr<LocalToRemoteSyncer> syncer(new LocalToRemoteSyncer(
-        this, SyncFileMetadata(file_change.file_type(), 0, base::Time()),
+        context_.get(),
+        SyncFileMetadata(file_change.file_type(), 0, base::Time()),
         file_change, local_path, url));
     syncer->RunSequential(CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
@@ -170,16 +180,20 @@
   }
 
   SyncStatusCode ListChanges() {
-    ListChangesTask list_changes(this);
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    list_changes.RunSequential(CreateResultReceiver(&status));
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE,
+        scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
+        SyncTaskManager::PRIORITY_MED,
+        CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
   }
 
   SyncStatusCode RunRemoteToLocalSyncer() {
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    scoped_ptr<RemoteToLocalSyncer> syncer(new RemoteToLocalSyncer(this));
+    scoped_ptr<RemoteToLocalSyncer>
+        syncer(new RemoteToLocalSyncer(context_.get()));
     syncer->RunSequential(CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
@@ -229,11 +243,11 @@
   base::ScopedTempDir database_dir_;
   scoped_ptr<leveldb::Env> in_memory_env_;
 
-  scoped_ptr<FakeDriveServiceWrapper> fake_drive_service_;
-  scoped_ptr<FakeDriveUploader> drive_uploader_;
+  scoped_ptr<SyncEngineContext> context_;
   scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
   scoped_ptr<MetadataDatabase> metadata_database_;
   scoped_ptr<FakeRemoteChangeProcessor> fake_remote_change_processor_;
+  scoped_ptr<SyncTaskManager> sync_task_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(LocalToRemoteSyncerTest);
 };
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
index 81d919a..df703d1 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc
@@ -376,16 +376,13 @@
       const FileMetadata& file) {
     scoped_ptr<google_apis::FileResource> file_resource(
         new google_apis::FileResource);
-    ScopedVector<google_apis::ParentReference> parents;
     for (int i = 0; i < file.details().parent_folder_ids_size(); ++i) {
-      scoped_ptr<google_apis::ParentReference> parent(
-          new google_apis::ParentReference);
-      parent->set_file_id(file.details().parent_folder_ids(i));
-      parents.push_back(parent.release());
+      google_apis::ParentReference parent;
+      parent.set_file_id(file.details().parent_folder_ids(i));
+      file_resource->mutable_parents()->push_back(parent);
     }
 
     file_resource->set_file_id(file.file_id());
-    file_resource->set_parents(parents.Pass());
     file_resource->set_title(file.details().title());
     if (file.details().file_kind() == FILE_KIND_FOLDER)
       file_resource->set_mime_type("application/vnd.google-apps.folder");
diff --git a/chrome/browser/sync_file_system/drive_backend/register_app_task_unittest.cc b/chrome/browser/sync_file_system/drive_backend/register_app_task_unittest.cc
index fb9f80f..aea7e37 100644
--- a/chrome/browser/sync_file_system/drive_backend/register_app_task_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/register_app_task_unittest.cc
@@ -35,8 +35,7 @@
 const int64 kSyncRootTrackerID = 100;
 }  // namespace
 
-class RegisterAppTaskTest : public testing::Test,
-                            public SyncEngineContext {
+class RegisterAppTaskTest : public testing::Test {
  public:
   RegisterAppTaskTest()
       : next_file_id_(1000),
@@ -47,49 +46,35 @@
     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
 
-    fake_drive_service_.reset(new drive::FakeDriveService);
-    ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
+    scoped_ptr<drive::FakeDriveService>
+        fake_drive_service(new drive::FakeDriveService);
+    ASSERT_TRUE(fake_drive_service->LoadAccountMetadataForWapi(
         "sync_file_system/account_metadata.json"));
-    ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
+    ASSERT_TRUE(fake_drive_service->LoadResourceListForWapi(
         "gdata/empty_feed.json"));
 
-    drive_uploader_.reset(new drive::DriveUploader(
-        fake_drive_service_.get(), base::MessageLoopProxy::current()));
+    scoped_ptr<drive::DriveUploaderInterface>
+        drive_uploader(new drive::DriveUploader(
+            fake_drive_service.get(), base::MessageLoopProxy::current()));
 
     fake_drive_service_helper_.reset(new FakeDriveServiceHelper(
-        fake_drive_service_.get(), drive_uploader_.get(),
+        fake_drive_service.get(), drive_uploader.get(),
         kSyncRootFolderTitle));
 
+    context_.reset(new SyncEngineContext(
+        fake_drive_service.PassAs<drive::DriveServiceInterface>(),
+        drive_uploader.Pass(), base::MessageLoopProxy::current()));
+
     ASSERT_EQ(google_apis::HTTP_CREATED,
               fake_drive_service_helper_->AddOrphanedFolder(
                   kSyncRootFolderTitle, &sync_root_folder_id_));
   }
 
   virtual void TearDown() OVERRIDE {
-    metadata_database_.reset();
+    context_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
-  virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
-    return fake_drive_service_.get();
-  }
-
-  virtual drive::DriveUploaderInterface* GetDriveUploader() OVERRIDE {
-    return NULL;
-  }
-
-  virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
-    return metadata_database_.get();
-  }
-
-  virtual RemoteChangeProcessor* GetRemoteChangeProcessor() OVERRIDE {
-    return NULL;
-  }
-
-  virtual base::SequencedTaskRunner* GetBlockingTaskRunner() OVERRIDE {
-    return base::MessageLoopProxy::current();
-  }
-
  protected:
   scoped_ptr<leveldb::DB> OpenLevelDB() {
     leveldb::DB* db = NULL;
@@ -136,14 +121,16 @@
 
   void CreateMetadataDatabase(scoped_ptr<leveldb::DB> db) {
     ASSERT_TRUE(db);
-    ASSERT_FALSE(metadata_database_);
+    ASSERT_FALSE(context_->GetMetadataDatabase());
+    scoped_ptr<MetadataDatabase> metadata_db;
     ASSERT_EQ(SYNC_STATUS_OK,
               MetadataDatabase::CreateForTesting(
-                  db.Pass(), &metadata_database_));
+                  db.Pass(), &metadata_db));
+    context_->SetMetadataDatabase(metadata_db.Pass());
   }
 
   SyncStatusCode RunRegisterAppTask(const std::string& app_id) {
-    RegisterAppTask task(this, app_id);
+    RegisterAppTask task(context_.get(), app_id);
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
     task.RunSequential(CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
@@ -204,13 +191,13 @@
 
   size_t CountRegisteredAppRoot() {
     std::vector<std::string> app_ids;
-    metadata_database_->GetRegisteredAppIDs(&app_ids);
+    context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
     return app_ids.size();
   }
 
   bool IsAppRegistered(const std::string& app_id) {
     TrackerIDSet trackers;
-    if (!metadata_database_->FindTrackersByParentAndTitle(
+    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
             kSyncRootTrackerID, app_id, &trackers))
       return false;
     return trackers.has_active();
@@ -226,13 +213,13 @@
 
   bool HasRemoteAppRoot(const std::string& app_id) {
     TrackerIDSet files;
-    if (!metadata_database_->FindTrackersByParentAndTitle(
+    if (!context_->GetMetadataDatabase()->FindTrackersByParentAndTitle(
             kSyncRootTrackerID, app_id, &files) ||
         !files.has_active())
       return false;
 
     FileTracker app_root_tracker;
-    EXPECT_TRUE(metadata_database_->FindTrackerByTrackerID(
+    EXPECT_TRUE(context_->GetMetadataDatabase()->FindTrackerByTrackerID(
         files.active_tracker(), &app_root_tracker));
     std::string app_root_folder_id = app_root_tracker.file_id();
     scoped_ptr<google_apis::ResourceEntry> entry;
@@ -259,12 +246,9 @@
   content::TestBrowserThreadBundle browser_threads_;
   base::ScopedTempDir database_dir_;
 
-  scoped_ptr<drive::FakeDriveService> fake_drive_service_;
-  scoped_ptr<drive::DriveUploader> drive_uploader_;
+  scoped_ptr<SyncEngineContext> context_;
   scoped_ptr<FakeDriveServiceHelper> fake_drive_service_helper_;
 
-  scoped_ptr<MetadataDatabase> metadata_database_;
-
   DISALLOW_COPY_AND_ASSIGN(RegisterAppTaskTest);
 };
 
diff --git a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer_unittest.cc b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer_unittest.cc
index a416d05..49690ae 100644
--- a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer_unittest.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
 #include "chrome/browser/sync_file_system/fake_remote_change_processor.h"
 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
@@ -42,8 +43,7 @@
 
 }  // namespace
 
-class RemoteToLocalSyncerTest : public testing::Test,
-                                public SyncEngineContext {
+class RemoteToLocalSyncerTest : public testing::Test {
  public:
   typedef FakeRemoteChangeProcessor::URLToFileChangesMap URLToFileChangesMap;
 
@@ -55,73 +55,86 @@
     ASSERT_TRUE(database_dir_.CreateUniqueTempDir());
     in_memory_env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
 
-    fake_drive_service_.reset(new drive::FakeDriveService);
-    ASSERT_TRUE(fake_drive_service_->LoadAccountMetadataForWapi(
+    scoped_ptr<drive::FakeDriveService>
+        fake_drive_service(new drive::FakeDriveService);
+    ASSERT_TRUE(fake_drive_service->LoadAccountMetadataForWapi(
         "sync_file_system/account_metadata.json"));
-    ASSERT_TRUE(fake_drive_service_->LoadResourceListForWapi(
+    ASSERT_TRUE(fake_drive_service->LoadResourceListForWapi(
         "gdata/empty_feed.json"));
 
-    drive_uploader_.reset(new drive::DriveUploader(
-        fake_drive_service_.get(), base::MessageLoopProxy::current().get()));
+    scoped_ptr<drive::DriveUploaderInterface>
+        drive_uploader(new drive::DriveUploader(
+            fake_drive_service.get(),
+            base::MessageLoopProxy::current().get()));
     fake_drive_helper_.reset(new FakeDriveServiceHelper(
-        fake_drive_service_.get(), drive_uploader_.get(),
+        fake_drive_service.get(), drive_uploader.get(),
         kSyncRootFolderTitle));
     fake_remote_change_processor_.reset(new FakeRemoteChangeProcessor);
 
+    context_.reset(new SyncEngineContext(
+        fake_drive_service.PassAs<drive::DriveServiceInterface>(),
+        drive_uploader.Pass(), base::MessageLoopProxy::current()));
+    context_->SetRemoteChangeProcessor(fake_remote_change_processor_.get());
+
     RegisterSyncableFileSystem();
+
+    sync_task_manager_.reset(new SyncTaskManager(
+        base::WeakPtr<SyncTaskManager::Client>(),
+        10 /* max_parallel_task */));
+    sync_task_manager_->Initialize(SYNC_STATUS_OK);
   }
 
   virtual void TearDown() OVERRIDE {
+    sync_task_manager_.reset();
+
     RevokeSyncableFileSystem();
 
     fake_remote_change_processor_.reset();
-    metadata_database_.reset();
     fake_drive_helper_.reset();
-    drive_uploader_.reset();
-    fake_drive_service_.reset();
+    context_.reset();
     base::RunLoop().RunUntilIdle();
   }
 
   void InitializeMetadataDatabase() {
-    SyncEngineInitializer initializer(this,
-                                      base::MessageLoopProxy::current(),
-                                      fake_drive_service_.get(),
-                                      database_dir_.path(),
-                                      in_memory_env_.get());
+    SyncEngineInitializer* initializer =
+        new SyncEngineInitializer(
+            context_.get(),
+            base::MessageLoopProxy::current(),
+            context_->GetDriveService(),
+            database_dir_.path(),
+            in_memory_env_.get());
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    initializer.RunSequential(CreateResultReceiver(&status));
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE,
+        scoped_ptr<SyncTask>(initializer),
+        SyncTaskManager::PRIORITY_MED,
+        base::Bind(&RemoteToLocalSyncerTest::DidInitializeMetadataDatabase,
+                   base::Unretained(this),
+                   initializer, &status));
+
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(SYNC_STATUS_OK, status);
-    metadata_database_ = initializer.PassMetadataDatabase();
   }
 
+  void DidInitializeMetadataDatabase(SyncEngineInitializer* initializer,
+                                     SyncStatusCode* status_out,
+                                     SyncStatusCode status) {
+    *status_out = status;
+    context_->SetMetadataDatabase(initializer->PassMetadataDatabase());
+  }
+
+
   void RegisterApp(const std::string& app_id,
                    const std::string& app_root_folder_id) {
     SyncStatusCode status = SYNC_STATUS_FAILED;
-    metadata_database_->RegisterApp(app_id, app_root_folder_id,
-                                    CreateResultReceiver(&status));
+    context_->GetMetadataDatabase()->RegisterApp(app_id, app_root_folder_id,
+                                                 CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(SYNC_STATUS_OK, status);
   }
 
-  virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE {
-    return fake_drive_service_.get();
-  }
-
-  virtual drive::DriveUploaderInterface* GetDriveUploader() OVERRIDE {
-    return drive_uploader_.get();
-  }
-
-  virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE {
-    return metadata_database_.get();
-  }
-
-  virtual RemoteChangeProcessor* GetRemoteChangeProcessor() OVERRIDE {
-    return fake_remote_change_processor_.get();
-  }
-
-  virtual base::SequencedTaskRunner* GetBlockingTaskRunner() OVERRIDE {
-    return base::MessageLoopProxy::current().get();
+  MetadataDatabase* GetMetadataDatabase() {
+    return context_->GetMetadataDatabase();
   }
 
  protected:
@@ -171,7 +184,8 @@
 
   SyncStatusCode RunSyncer() {
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    scoped_ptr<RemoteToLocalSyncer> syncer(new RemoteToLocalSyncer(this));
+    scoped_ptr<RemoteToLocalSyncer>
+        syncer(new RemoteToLocalSyncer(context_.get()));
     syncer->RunSequential(CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
@@ -184,9 +198,12 @@
   }
 
   SyncStatusCode ListChanges() {
-    ListChangesTask list_changes(this);
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
-    list_changes.RunSequential(CreateResultReceiver(&status));
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE,
+        scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
+        SyncTaskManager::PRIORITY_MED,
+        CreateResultReceiver(&status));
     base::RunLoop().RunUntilIdle();
     return status;
   }
@@ -206,12 +223,12 @@
   base::ScopedTempDir database_dir_;
   scoped_ptr<leveldb::Env> in_memory_env_;
 
-  scoped_ptr<drive::FakeDriveService> fake_drive_service_;
-  scoped_ptr<drive::DriveUploader> drive_uploader_;
+  scoped_ptr<SyncEngineContext> context_;
   scoped_ptr<FakeDriveServiceHelper> fake_drive_helper_;
-  scoped_ptr<MetadataDatabase> metadata_database_;
   scoped_ptr<FakeRemoteChangeProcessor> fake_remote_change_processor_;
 
+  scoped_ptr<SyncTaskManager> sync_task_manager_;
+
   URLToFileChangesMap expected_changes_;
 
   DISALLOW_COPY_AND_ASSIGN(RemoteToLocalSyncerTest);
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
index 1c0fd5d..6b5f6ff 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -26,13 +26,14 @@
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
 #include "chrome/browser/sync_file_system/drive_backend/register_app_task.h"
 #include "chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_task.h"
 #include "chrome/browser/sync_file_system/drive_backend/uninstall_app_task.h"
 #include "chrome/browser/sync_file_system/file_status_observer.h"
 #include "chrome/browser/sync_file_system/logger.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/browser/extension_system_provider.h"
@@ -44,6 +45,9 @@
 #include "webkit/common/fileapi/file_system_util.h"
 
 namespace sync_file_system {
+
+class RemoteChangeProcessor;
+
 namespace drive_backend {
 
 namespace {
@@ -121,21 +125,23 @@
 
 SyncEngine::~SyncEngine() {
   net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-  drive_service_->RemoveObserver(this);
+  context_->GetDriveService()->RemoveObserver(this);
   if (notification_manager_)
     notification_manager_->RemoveObserver(this);
 }
 
 void SyncEngine::Initialize() {
   DCHECK(!task_manager_);
-  task_manager_.reset(new SyncTaskManager(weak_ptr_factory_.GetWeakPtr()));
+  task_manager_.reset(new SyncTaskManager(
+      weak_ptr_factory_.GetWeakPtr(),
+      0 /* maximum_background_task */));
   task_manager_->Initialize(SYNC_STATUS_OK);
 
   PostInitializeTask();
 
   if (notification_manager_)
     notification_manager_->AddObserver(this);
-  drive_service_->AddObserver(this);
+  context_->GetDriveService()->AddObserver(this);
   net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
 
   net::NetworkChangeNotifier::ConnectionType type =
@@ -155,10 +161,12 @@
 void SyncEngine::RegisterOrigin(
     const GURL& origin,
     const SyncStatusCallback& callback) {
-  if (!metadata_database_ && drive_service_->HasRefreshToken())
+  if (!context_->GetMetadataDatabase() &&
+      context_->GetDriveService()->HasRefreshToken())
     PostInitializeTask();
 
-  scoped_ptr<RegisterAppTask> task(new RegisterAppTask(this, origin.host()));
+  scoped_ptr<RegisterAppTask> task(
+      new RegisterAppTask(context_.get(), origin.host()));
   if (task->CanFinishImmediately()) {
     callback.Run(SYNC_STATUS_OK);
     return;
@@ -201,14 +209,15 @@
     const SyncStatusCallback& callback) {
   task_manager_->ScheduleSyncTask(
       FROM_HERE,
-      scoped_ptr<SyncTask>(new UninstallAppTask(this, origin.host(), flag)),
+      scoped_ptr<SyncTask>(
+          new UninstallAppTask(context_.get(), origin.host(), flag)),
       SyncTaskManager::PRIORITY_HIGH,
       callback);
 }
 
 void SyncEngine::ProcessRemoteChange(
     const SyncFileCallback& callback) {
-  RemoteToLocalSyncer* syncer = new RemoteToLocalSyncer(this);
+  RemoteToLocalSyncer* syncer = new RemoteToLocalSyncer(context_.get());
   task_manager_->ScheduleSyncTask(
       FROM_HERE,
       scoped_ptr<SyncTask>(syncer),
@@ -220,7 +229,7 @@
 
 void SyncEngine::SetRemoteChangeProcessor(
     RemoteChangeProcessor* processor) {
-  remote_change_processor_ = processor;
+  context_->SetRemoteChangeProcessor(processor);
 }
 
 LocalChangeProcessor* SyncEngine::GetLocalChangeProcessor() {
@@ -240,11 +249,11 @@
 
 void SyncEngine::GetOriginStatusMap(OriginStatusMap* status_map) {
   DCHECK(status_map);
-  if (!extension_service_ || !metadata_database_)
+  if (!extension_service_ || !context_->GetMetadataDatabase())
     return;
 
   std::vector<std::string> app_ids;
-  metadata_database_->GetRegisteredAppIDs(&app_ids);
+  context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
 
   for (std::vector<std::string>::const_iterator itr = app_ids.begin();
        itr != app_ids.end(); ++itr) {
@@ -252,20 +261,21 @@
     GURL origin =
         extensions::Extension::GetBaseURLFromExtensionId(app_id);
     (*status_map)[origin] =
-        metadata_database_->IsAppEnabled(app_id) ? "Enabled" : "Disabled";
+        context_->GetMetadataDatabase()->IsAppEnabled(app_id) ?
+        "Enabled" : "Disabled";
   }
 }
 
 scoped_ptr<base::ListValue> SyncEngine::DumpFiles(const GURL& origin) {
-  if (!metadata_database_)
+  if (!context_->GetMetadataDatabase())
     return scoped_ptr<base::ListValue>();
-  return metadata_database_->DumpFiles(origin.host());
+  return context_->GetMetadataDatabase()->DumpFiles(origin.host());
 }
 
 scoped_ptr<base::ListValue> SyncEngine::DumpDatabase() {
-  if (!metadata_database_)
+  if (!context_->GetMetadataDatabase())
     return scoped_ptr<base::ListValue>();
-  return metadata_database_->DumpDatabase();
+  return context_->GetMetadataDatabase()->DumpDatabase();
 }
 
 void SyncEngine::SetSyncEnabled(bool enabled) {
@@ -324,13 +334,14 @@
 }
 
 void SyncEngine::PromoteDemotedChanges() {
-  if (metadata_database_ && metadata_database_->HasLowPriorityDirtyTracker()) {
-    metadata_database_->PromoteLowerPriorityTrackersToNormal();
+  if (context_->GetMetadataDatabase() &&
+      context_->GetMetadataDatabase()->HasLowPriorityDirtyTracker()) {
+    context_->GetMetadataDatabase()->PromoteLowerPriorityTrackersToNormal();
     FOR_EACH_OBSERVER(
         Observer,
         service_observers_,
         OnRemoteChangeQueueUpdated(
-            metadata_database_->CountDirtyTracker()));
+            context_->GetMetadataDatabase()->CountDirtyTracker()));
   }
 }
 
@@ -341,7 +352,7 @@
     const fileapi::FileSystemURL& url,
     const SyncStatusCallback& callback) {
   LocalToRemoteSyncer* syncer = new LocalToRemoteSyncer(
-      this, local_metadata, local_change, local_path, url);
+      context_.get(), local_metadata, local_change, local_path, url);
   task_manager_->ScheduleSyncTask(
       FROM_HERE,
       scoped_ptr<SyncTask>(syncer),
@@ -366,12 +377,12 @@
     SyncStatusCode sync_status,
     bool used_network) {
   UpdateServiceStateFromSyncStatusCode(sync_status, used_network);
-  if (metadata_database_) {
+  if (context_->GetMetadataDatabase()) {
     FOR_EACH_OBSERVER(
         Observer,
         service_observers_,
         OnRemoteChangeQueueUpdated(
-            metadata_database_->CountDirtyTracker()));
+            context_->GetMetadataDatabase()->CountDirtyTracker()));
   }
 }
 
@@ -390,8 +401,9 @@
     return;
   UpdateServiceState(REMOTE_SERVICE_OK, "Authenticated");
 
-  if (!metadata_database_ && signin_manager_) {
-    drive_service_->Initialize(signin_manager_->GetAuthenticatedAccountId());
+  if (!context_->GetMetadataDatabase() && signin_manager_) {
+    context_->GetDriveService()->Initialize(
+        signin_manager_->GetAuthenticatedAccountId());
     PostInitializeTask();
     return;
   }
@@ -422,23 +434,23 @@
 }
 
 drive::DriveServiceInterface* SyncEngine::GetDriveService() {
-  return drive_service_.get();
+  return context_->GetDriveService();
 }
 
 drive::DriveUploaderInterface* SyncEngine::GetDriveUploader() {
-  return drive_uploader_.get();
+  return context_->GetDriveUploader();
 }
 
 MetadataDatabase* SyncEngine::GetMetadataDatabase() {
-  return metadata_database_.get();
+  return context_->GetMetadataDatabase();
 }
 
 RemoteChangeProcessor* SyncEngine::GetRemoteChangeProcessor() {
-  return remote_change_processor_;
+  return context_->GetRemoteChangeProcessor();
 }
 
 base::SequencedTaskRunner* SyncEngine::GetBlockingTaskRunner() {
-  return task_runner_.get();
+  return context_->GetBlockingTaskRunner();
 }
 
 SyncEngine::SyncEngine(const base::FilePath& base_dir,
@@ -450,14 +462,10 @@
                        SigninManagerBase* signin_manager,
                        leveldb::Env* env_override)
     : base_dir_(base_dir),
-      task_runner_(task_runner),
       env_override_(env_override),
-      drive_service_(drive_service.Pass()),
-      drive_uploader_(drive_uploader.Pass()),
       notification_manager_(notification_manager),
       extension_service_(extension_service),
       signin_manager_(signin_manager),
-      remote_change_processor_(NULL),
       service_state_(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE),
       should_check_conflict_(true),
       should_check_remote_change_(true),
@@ -466,33 +474,37 @@
       default_conflict_resolution_policy_(
           CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN),
       network_available_(false),
-      weak_ptr_factory_(this) {}
+      context_(new SyncEngineContext(drive_service.Pass(),
+                                     drive_uploader.Pass(),
+                                     task_runner)),
+      weak_ptr_factory_(this) {
+}
 
 void SyncEngine::DoDisableApp(const std::string& app_id,
                               const SyncStatusCallback& callback) {
-  if (metadata_database_)
-    metadata_database_->DisableApp(app_id, callback);
+  if (context_->GetMetadataDatabase())
+    context_->GetMetadataDatabase()->DisableApp(app_id, callback);
   else
     callback.Run(SYNC_STATUS_OK);
 }
 
 void SyncEngine::DoEnableApp(const std::string& app_id,
                              const SyncStatusCallback& callback) {
-  if (metadata_database_)
-    metadata_database_->EnableApp(app_id, callback);
+  if (context_->GetMetadataDatabase())
+    context_->GetMetadataDatabase()->EnableApp(app_id, callback);
   else
     callback.Run(SYNC_STATUS_OK);
 }
 
 void SyncEngine::PostInitializeTask() {
-  DCHECK(!metadata_database_);
+  DCHECK(!context_->GetMetadataDatabase());
 
-  // This initializer task may not run if metadata_database_ is already
-  // initialized when it runs.
+  // This initializer task may not run if MetadataDatabase in context_ is
+  // already initialized when it runs.
   SyncEngineInitializer* initializer =
-      new SyncEngineInitializer(this,
-                                task_runner_.get(),
-                                drive_service_.get(),
+      new SyncEngineInitializer(context_.get(),
+                                context_->GetBlockingTaskRunner(),
+                                context_->GetDriveService(),
                                 base_dir_.Append(kDatabaseName),
                                 env_override_);
   task_manager_->ScheduleSyncTask(
@@ -506,7 +518,7 @@
 void SyncEngine::DidInitialize(SyncEngineInitializer* initializer,
                                SyncStatusCode status) {
   if (status != SYNC_STATUS_OK) {
-    if (drive_service_->HasRefreshToken()) {
+    if (context_->GetDriveService()->HasRefreshToken()) {
       UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
                          "Could not initialize remote service");
     } else {
@@ -519,9 +531,8 @@
   scoped_ptr<MetadataDatabase> metadata_database =
       initializer->PassMetadataDatabase();
   if (metadata_database)
-    metadata_database_ = metadata_database.Pass();
+    context_->SetMetadataDatabase(metadata_database.Pass());
 
-  DCHECK(metadata_database_);
   UpdateRegisteredApps();
 }
 
@@ -529,7 +540,7 @@
                                         const SyncFileCallback& callback,
                                         SyncStatusCode status) {
   if (syncer->is_sync_root_deletion()) {
-    MetadataDatabase::ClearDatabase(metadata_database_.Pass());
+    MetadataDatabase::ClearDatabase(context_->PassMetadataDatabase());
     PostInitializeTask();
     callback.Run(status, syncer->url());
     return;
@@ -584,7 +595,7 @@
       !listing_remote_changes_) {
     task_manager_->ScheduleSyncTask(
         FROM_HERE,
-        scoped_ptr<SyncTask>(new ListChangesTask(this)),
+        scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
         SyncTaskManager::PRIORITY_HIGH,
         base::Bind(&SyncEngine::DidFetchChanges,
                    weak_ptr_factory_.GetWeakPtr()));
@@ -611,7 +622,7 @@
   if (GetCurrentState() == REMOTE_SERVICE_DISABLED)
     return;
 
-  if (!metadata_database_)
+  if (!context_->GetMetadataDatabase())
     return;
 
   if (listing_remote_changes_)
@@ -619,11 +630,12 @@
 
   base::TimeTicks now = base::TimeTicks::Now();
   if (!should_check_remote_change_ && now < time_to_check_changes_) {
-    if (!metadata_database_->HasDirtyTracker() && should_check_conflict_) {
+    if (!context_->GetMetadataDatabase()->HasDirtyTracker() &&
+        should_check_conflict_) {
       should_check_conflict_ = false;
       task_manager_->ScheduleSyncTaskIfIdle(
           FROM_HERE,
-          scoped_ptr<SyncTask>(new ConflictResolver(this)),
+          scoped_ptr<SyncTask>(new ConflictResolver(context_.get())),
           base::Bind(&SyncEngine::DidResolveConflict,
                      weak_ptr_factory_.GetWeakPtr()));
     }
@@ -632,7 +644,7 @@
 
   if (task_manager_->ScheduleSyncTaskIfIdle(
           FROM_HERE,
-          scoped_ptr<SyncTask>(new ListChangesTask(this)),
+          scoped_ptr<SyncTask>(new ListChangesTask(context_.get())),
           base::Bind(&SyncEngine::DidFetchChanges,
                      weak_ptr_factory_.GetWeakPtr()))) {
     should_check_remote_change_ = false;
@@ -679,7 +691,7 @@
     case SYNC_STATUS_NETWORK_ERROR:
     case SYNC_STATUS_ABORT:
     case SYNC_STATUS_FAILED:
-      if (drive_service_->HasRefreshToken()) {
+      if (context_->GetDriveService()->HasRefreshToken()) {
         UpdateServiceState(REMOTE_SERVICE_TEMPORARY_UNAVAILABLE,
                            "Network or temporary service error.");
       } else {
@@ -722,9 +734,9 @@
   if (!extension_service_)
     return;
 
-  DCHECK(metadata_database_);
+  DCHECK(context_->GetMetadataDatabase());
   std::vector<std::string> app_ids;
-  metadata_database_->GetRegisteredAppIDs(&app_ids);
+  context_->GetMetadataDatabase()->GetRegisteredAppIDs(&app_ids);
 
   // Update the status of every origin using status from ExtensionService.
   for (std::vector<std::string>::const_iterator itr = app_ids.begin();
@@ -742,7 +754,8 @@
       continue;
     }
     FileTracker tracker;
-    if (!metadata_database_->FindAppRootTracker(app_id, &tracker)) {
+    if (!context_->GetMetadataDatabase()->FindAppRootTracker(app_id,
+                                                             &tracker)) {
       // App will register itself on first run.
       continue;
     }
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.h b/chrome/browser/sync_file_system/drive_backend/sync_engine.h
index 892edd4..84799ff 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine.h
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.h
@@ -48,8 +48,7 @@
                    public SyncTaskManager::Client,
                    public drive::DriveNotificationObserver,
                    public drive::DriveServiceObserver,
-                   public net::NetworkChangeNotifier::NetworkChangeObserver,
-                   public SyncEngineContext {
+                   public net::NetworkChangeNotifier::NetworkChangeObserver {
  public:
   typedef Observer SyncServiceObserver;
 
@@ -131,12 +130,11 @@
   virtual void OnNetworkChanged(
       net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
 
-  // SyncEngineContext overrides.
-  virtual drive::DriveServiceInterface* GetDriveService() OVERRIDE;
-  virtual drive::DriveUploaderInterface* GetDriveUploader() OVERRIDE;
-  virtual MetadataDatabase* GetMetadataDatabase() OVERRIDE;
-  virtual RemoteChangeProcessor* GetRemoteChangeProcessor() OVERRIDE;
-  virtual base::SequencedTaskRunner* GetBlockingTaskRunner() OVERRIDE;
+  drive::DriveServiceInterface* GetDriveService();
+  drive::DriveUploaderInterface* GetDriveUploader();
+  MetadataDatabase* GetMetadataDatabase();
+  RemoteChangeProcessor* GetRemoteChangeProcessor();
+  base::SequencedTaskRunner* GetBlockingTaskRunner();
 
  private:
   friend class DriveBackendSyncTest;
@@ -179,13 +177,8 @@
   base::FilePath base_dir_;
   base::FilePath temporary_file_dir_;
 
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   leveldb::Env* env_override_;
 
-  scoped_ptr<drive::DriveServiceInterface> drive_service_;
-  scoped_ptr<drive::DriveUploaderInterface> drive_uploader_;
-  scoped_ptr<MetadataDatabase> metadata_database_;
-
   // These external services are not owned by SyncEngine.
   // The owner of the SyncEngine is responsible for their lifetime.
   // I.e. the owner should declare the dependency explicitly by calling
@@ -196,7 +189,6 @@
 
   ObserverList<SyncServiceObserver> service_observers_;
   ObserverList<FileStatusObserver> file_status_observers_;
-  RemoteChangeProcessor* remote_change_processor_;
 
   RemoteServiceState service_state_;
 
@@ -211,6 +203,7 @@
 
   scoped_ptr<SyncTaskManager> task_manager_;
 
+  scoped_ptr<SyncEngineContext> context_;
   base::WeakPtrFactory<SyncEngine> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncEngine);
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_context.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_context.cc
new file mode 100644
index 0000000..fd16882
--- /dev/null
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_context.cc
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "chrome/browser/drive/drive_service_interface.h"
+#include "chrome/browser/drive/drive_uploader.h"
+#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
+#include "chrome/browser/sync_file_system/remote_change_processor.h"
+
+namespace sync_file_system {
+namespace drive_backend {
+
+SyncEngineContext::SyncEngineContext(
+    scoped_ptr<drive::DriveServiceInterface> drive_service,
+    scoped_ptr<drive::DriveUploaderInterface> drive_uploader,
+    base::SequencedTaskRunner* task_runner)
+    : drive_service_(drive_service.Pass()),
+      drive_uploader_(drive_uploader.Pass()),
+      remote_change_processor_(NULL),
+      task_runner_(task_runner) {}
+
+SyncEngineContext::~SyncEngineContext() {}
+
+drive::DriveServiceInterface* SyncEngineContext::GetDriveService() {
+  return drive_service_.get();
+}
+
+drive::DriveUploaderInterface* SyncEngineContext::GetDriveUploader() {
+  return drive_uploader_.get();
+}
+
+MetadataDatabase* SyncEngineContext::GetMetadataDatabase() {
+  return metadata_database_.get();
+}
+
+scoped_ptr<MetadataDatabase> SyncEngineContext::PassMetadataDatabase() {
+  return metadata_database_.Pass();
+}
+
+RemoteChangeProcessor* SyncEngineContext::GetRemoteChangeProcessor() {
+  return remote_change_processor_;
+}
+
+base::SequencedTaskRunner* SyncEngineContext::GetBlockingTaskRunner() {
+  return task_runner_.get();
+}
+
+void SyncEngineContext::SetMetadataDatabase(
+    scoped_ptr<MetadataDatabase> metadata_database) {
+  if (metadata_database)
+    metadata_database_ = metadata_database.Pass();
+}
+
+void SyncEngineContext::SetRemoteChangeProcessor(
+    RemoteChangeProcessor* remote_change_processor) {
+  remote_change_processor_ = remote_change_processor;
+}
+
+}  // namespace drive_backend
+}  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_context.h b/chrome/browser/sync_file_system/drive_backend/sync_engine_context.h
index 2a90d84..be96406 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_context.h
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_context.h
@@ -6,6 +6,8 @@
 #define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_SYNC_ENGINE_CONTEXT_H_
 
 #include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -26,16 +28,29 @@
 
 class SyncEngineContext {
  public:
-  SyncEngineContext() {}
-  ~SyncEngineContext() {}
+  SyncEngineContext(scoped_ptr<drive::DriveServiceInterface> drive_service,
+                    scoped_ptr<drive::DriveUploaderInterface> drive_uploader,
+                    base::SequencedTaskRunner* task_runner);
+  ~SyncEngineContext();
 
-  virtual drive::DriveServiceInterface* GetDriveService() = 0;
-  virtual drive::DriveUploaderInterface* GetDriveUploader() = 0;
-  virtual MetadataDatabase* GetMetadataDatabase() = 0;
-  virtual RemoteChangeProcessor* GetRemoteChangeProcessor() = 0;
-  virtual base::SequencedTaskRunner* GetBlockingTaskRunner() = 0;
+  drive::DriveServiceInterface* GetDriveService();
+  drive::DriveUploaderInterface* GetDriveUploader();
+  MetadataDatabase* GetMetadataDatabase();
+  RemoteChangeProcessor* GetRemoteChangeProcessor();
+  base::SequencedTaskRunner* GetBlockingTaskRunner();
+
+  void SetMetadataDatabase(scoped_ptr<MetadataDatabase> metadata_database);
+  void SetRemoteChangeProcessor(RemoteChangeProcessor* remote_change_processor);
+
+  scoped_ptr<MetadataDatabase> PassMetadataDatabase();
 
  private:
+  scoped_ptr<drive::DriveServiceInterface> drive_service_;
+  scoped_ptr<drive::DriveUploaderInterface> drive_uploader_;
+  scoped_ptr<MetadataDatabase> metadata_database_;
+  RemoteChangeProcessor* remote_change_processor_;  // Do not own
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
+
   DISALLOW_COPY_AND_ASSIGN(SyncEngineContext);
 };
 
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc
index 5d3d995..89a0509 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.cc
@@ -13,6 +13,8 @@
 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
 #include "chrome/browser/sync_file_system/logger.h"
 #include "google_apis/drive/drive_api_parser.h"
 #include "google_apis/drive/gdata_wapi_parser.h"
@@ -25,10 +27,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Functions below are for wrapping the access to legacy GData WAPI classes.
 
-bool IsDeleted(const google_apis::ResourceEntry& entry) {
-  return entry.deleted();
-}
-
 bool HasNoParents(const google_apis::ResourceEntry& entry) {
   return !entry.GetLinkByType(google_apis::Link::LINK_PARENT);
 }
@@ -52,24 +50,10 @@
   return left.published_time() < right.published_time();
 }
 
-// Posts a request to continue listing.  Returns false if the list doesn't need
-// listing anymore.
-bool GetRemainingFileList(
-    google_apis::CancelCallback* cancel_callback,
-    drive::DriveServiceInterface* api_service,
-    const google_apis::ResourceList& resource_list,
-    const google_apis::GetResourceListCallback& callback) {
-  GURL next_url;
-  if (!resource_list.GetNextFeedURL(&next_url))
-    return false;
-
-  *cancel_callback = api_service->GetRemainingFileList(next_url, callback);
-  return true;
-}
-
-std::string GetID(const google_apis::ResourceEntry& entry) {
-  return entry.resource_id();
-}
+typedef base::Callback<void(scoped_ptr<SyncTaskToken> token,
+                            google_apis::GDataErrorCode error,
+                            scoped_ptr<google_apis::ResourceList> resources)>
+    TokenAndResourceListCallback;
 
 ScopedVector<google_apis::FileResource> ConvertResourceEntriesToFileResources(
     const ScopedVector<google_apis::ResourceEntry>& entries) {
@@ -113,21 +97,21 @@
     cancel_callback_.Run();
 }
 
-void SyncEngineInitializer::RunSequential(const SyncStatusCallback& callback) {
+void SyncEngineInitializer::Run(scoped_ptr<SyncTaskToken> token) {
   util::Log(logging::LOG_VERBOSE, FROM_HERE, "[Initialize] Start.");
 
   // The metadata seems to have been already initialized. Just return with OK.
   if (sync_context_ && sync_context_->GetMetadataDatabase()) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Already initialized.");
-    callback.Run(SYNC_STATUS_OK);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
     return;
   }
 
   MetadataDatabase::Create(
       task_runner_.get(), database_path_, env_override_,
       base::Bind(&SyncEngineInitializer::DidCreateMetadataDatabase,
-                 weak_ptr_factory_.GetWeakPtr(), callback));
+                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
 }
 
 scoped_ptr<MetadataDatabase> SyncEngineInitializer::PassMetadataDatabase() {
@@ -135,13 +119,13 @@
 }
 
 void SyncEngineInitializer::DidCreateMetadataDatabase(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     SyncStatusCode status,
     scoped_ptr<MetadataDatabase> instance) {
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Failed to initialize MetadataDatabase.");
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
@@ -150,23 +134,23 @@
   if (metadata_database_->HasSyncRoot()) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Found local cache of sync-root.");
-    callback.Run(SYNC_STATUS_OK);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
     return;
   }
 
-  GetAboutResource(callback);
+  GetAboutResource(token.Pass());
 }
 
 void SyncEngineInitializer::GetAboutResource(
-    const SyncStatusCallback& callback) {
+    scoped_ptr<SyncTaskToken> token) {
   set_used_network(true);
   drive_service_->GetAboutResource(
       base::Bind(&SyncEngineInitializer::DidGetAboutResource,
-                 weak_ptr_factory_.GetWeakPtr(), callback));
+                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
 }
 
 void SyncEngineInitializer::DidGetAboutResource(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     google_apis::GDataErrorCode error,
     scoped_ptr<google_apis::AboutResource> about_resource) {
   cancel_callback_.Reset();
@@ -175,7 +159,7 @@
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Failed to get AboutResource.");
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
@@ -184,14 +168,14 @@
   largest_change_id_ = about_resource->largest_change_id();
 
   DCHECK(!root_folder_id_.empty());
-  FindSyncRoot(callback);
+  FindSyncRoot(token.Pass());
 }
 
-void SyncEngineInitializer::FindSyncRoot(const SyncStatusCallback& callback) {
+void SyncEngineInitializer::FindSyncRoot(scoped_ptr<SyncTaskToken> token) {
   if (find_sync_root_retry_count_++ >= kMaxRetry) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Reached max retry count.");
-    callback.Run(SYNC_STATUS_FAILED);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     return;
   }
 
@@ -201,11 +185,11 @@
       std::string(),  // parent_folder_id
       base::Bind(&SyncEngineInitializer::DidFindSyncRoot,
                  weak_ptr_factory_.GetWeakPtr(),
-                 callback));
+                 base::Passed(&token)));
 }
 
 void SyncEngineInitializer::DidFindSyncRoot(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     google_apis::GDataErrorCode error,
     scoped_ptr<google_apis::ResourceList> resource_list) {
   cancel_callback_.Reset();
@@ -214,7 +198,7 @@
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Failed to find sync root.");
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
@@ -222,7 +206,7 @@
     NOTREACHED();
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Got invalid resource list.");
-    callback.Run(SYNC_STATUS_FAILED);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     return;
   }
 
@@ -234,7 +218,7 @@
     google_apis::ResourceEntry* entry = *itr;
 
     // Ignore deleted folder.
-    if (IsDeleted(*entry))
+    if (entry->deleted())
       continue;
 
     // Pick an orphaned folder or a direct child of the root folder and
@@ -251,28 +235,30 @@
 
   set_used_network(true);
   // If there are more results, retrieve them.
-  if (GetRemainingFileList(
-          &cancel_callback_,
-          drive_service_, *resource_list,
-          base::Bind(&SyncEngineInitializer::DidFindSyncRoot,
-                     weak_ptr_factory_.GetWeakPtr(),
-                     callback)))
+  GURL next_url;
+  if (resource_list->GetNextFeedURL(&next_url)) {
+    cancel_callback_ = drive_service_->GetRemainingFileList(
+        next_url,
+        base::Bind(&SyncEngineInitializer::DidFindSyncRoot,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   base::Passed(&token)));
     return;
+  }
 
   if (!sync_root_folder_) {
-    CreateSyncRoot(callback);
+    CreateSyncRoot(token.Pass());
     return;
   }
 
   if (!HasNoParents(*sync_root_folder_)) {
-    DetachSyncRoot(callback);
+    DetachSyncRoot(token.Pass());
     return;
   }
 
-  ListAppRootFolders(callback);
+  ListAppRootFolders(token.Pass());
 }
 
-void SyncEngineInitializer::CreateSyncRoot(const SyncStatusCallback& callback) {
+void SyncEngineInitializer::CreateSyncRoot(scoped_ptr<SyncTaskToken> token) {
   DCHECK(!sync_root_folder_);
   set_used_network(true);
   cancel_callback_ = drive_service_->AddNewDirectory(
@@ -280,11 +266,11 @@
       drive::DriveServiceInterface::AddNewDirectoryOptions(),
       base::Bind(&SyncEngineInitializer::DidCreateSyncRoot,
                  weak_ptr_factory_.GetWeakPtr(),
-                 callback));
+                 base::Passed(&token)));
 }
 
 void SyncEngineInitializer::DidCreateSyncRoot(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     google_apis::GDataErrorCode error,
     scoped_ptr<google_apis::ResourceEntry> entry) {
   DCHECK(!sync_root_folder_);
@@ -294,25 +280,25 @@
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Failed to create sync root.");
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
-  FindSyncRoot(callback);
+  FindSyncRoot(token.Pass());
 }
 
-void SyncEngineInitializer::DetachSyncRoot(const SyncStatusCallback& callback) {
+void SyncEngineInitializer::DetachSyncRoot(scoped_ptr<SyncTaskToken> token) {
   DCHECK(sync_root_folder_);
   set_used_network(true);
   cancel_callback_ = drive_service_->RemoveResourceFromDirectory(
-      root_folder_id_, GetID(*sync_root_folder_),
+      root_folder_id_, sync_root_folder_->resource_id(),
       base::Bind(&SyncEngineInitializer::DidDetachSyncRoot,
                  weak_ptr_factory_.GetWeakPtr(),
-                 callback));
+                 base::Passed(&token)));
 }
 
 void SyncEngineInitializer::DidDetachSyncRoot(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     google_apis::GDataErrorCode error) {
   cancel_callback_.Reset();
 
@@ -320,26 +306,26 @@
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Failed to detach sync root.");
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
-  ListAppRootFolders(callback);
+  ListAppRootFolders(token.Pass());
 }
 
 void SyncEngineInitializer::ListAppRootFolders(
-    const SyncStatusCallback& callback) {
+    scoped_ptr<SyncTaskToken> token) {
   DCHECK(sync_root_folder_);
   set_used_network(true);
   cancel_callback_ = drive_service_->GetResourceListInDirectory(
-      GetID(*sync_root_folder_),
+      sync_root_folder_->resource_id(),
       base::Bind(&SyncEngineInitializer::DidListAppRootFolders,
                  weak_ptr_factory_.GetWeakPtr(),
-                 callback));
+                 base::Passed(&token)));
 }
 
 void SyncEngineInitializer::DidListAppRootFolders(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     google_apis::GDataErrorCode error,
     scoped_ptr<google_apis::ResourceList> resource_list) {
   cancel_callback_.Reset();
@@ -348,7 +334,7 @@
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Failed to get initial app-root folders.");
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
@@ -356,7 +342,7 @@
     NOTREACHED();
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Got invalid initial app-root list.");
-    callback.Run(SYNC_STATUS_FAILED);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     return;
   }
 
@@ -367,19 +353,20 @@
   new_entries->weak_clear();
 
   set_used_network(true);
-  if (GetRemainingFileList(
-          &cancel_callback_,
-          drive_service_,
-          *resource_list,
-          base::Bind(&SyncEngineInitializer::DidListAppRootFolders,
-                     weak_ptr_factory_.GetWeakPtr(), callback)))
+  GURL next_url;
+  if (resource_list->GetNextFeedURL(&next_url)) {
+    cancel_callback_ = drive_service_->GetRemainingFileList(
+        next_url,
+        base::Bind(&SyncEngineInitializer::DidListAppRootFolders,
+                   weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
     return;
+  }
 
-  PopulateDatabase(callback);
+  PopulateDatabase(token.Pass());
 }
 
 void SyncEngineInitializer::PopulateDatabase(
-    const SyncStatusCallback& callback) {
+    scoped_ptr<SyncTaskToken> token) {
   DCHECK(sync_root_folder_);
   metadata_database_->PopulateInitialData(
       largest_change_id_,
@@ -387,24 +374,23 @@
           *sync_root_folder_),
       ConvertResourceEntriesToFileResources(app_root_folders_),
       base::Bind(&SyncEngineInitializer::DidPopulateDatabase,
-                 weak_ptr_factory_.GetWeakPtr(),
-                 callback));
+                 weak_ptr_factory_.GetWeakPtr(), base::Passed(&token)));
 }
 
 void SyncEngineInitializer::DidPopulateDatabase(
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     SyncStatusCode status) {
   if (status != SYNC_STATUS_OK) {
     util::Log(logging::LOG_VERBOSE, FROM_HERE,
               "[Initialize] Failed to populate initial data"
               " to MetadataDatabase.");
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
   util::Log(logging::LOG_VERBOSE, FROM_HERE,
             "[Initialize] Completed successfully.");
-  callback.Run(SYNC_STATUS_OK);
+  SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
 }
 
 }  // namespace drive_backend
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h
index 39e8f22..a1b86a4 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer.h
@@ -64,7 +64,7 @@
 //  - Populate database with the largest change ID, the sync-root folder and
 //    its contents.
 //
-class SyncEngineInitializer : public SequentialSyncTask {
+class SyncEngineInitializer : public SyncTask {
  public:
   SyncEngineInitializer(SyncEngineContext* sync_context,
                         base::SequencedTaskRunner* task_runner,
@@ -72,40 +72,40 @@
                         const base::FilePath& database_path,
                         leveldb::Env* env_override);
   virtual ~SyncEngineInitializer();
-  virtual void RunSequential(const SyncStatusCallback& callback) OVERRIDE;
+  virtual void Run(scoped_ptr<SyncTaskToken> token) OVERRIDE;
 
   scoped_ptr<MetadataDatabase> PassMetadataDatabase();
 
  private:
   typedef base::Callback<void(const SyncStatusCallback& callback)> Task;
 
-  void DidCreateMetadataDatabase(const SyncStatusCallback& callback,
+  void DidCreateMetadataDatabase(scoped_ptr<SyncTaskToken> token,
                                  SyncStatusCode status,
                                  scoped_ptr<MetadataDatabase> instance);
 
-  void GetAboutResource(const SyncStatusCallback& callback);
+  void GetAboutResource(scoped_ptr<SyncTaskToken> token);
   void DidGetAboutResource(
-      const SyncStatusCallback& callback,
+      scoped_ptr<SyncTaskToken> token,
       google_apis::GDataErrorCode error,
       scoped_ptr<google_apis::AboutResource> about_resource);
-  void FindSyncRoot(const SyncStatusCallback& callback);
-  void DidFindSyncRoot(const SyncStatusCallback& callback,
+  void FindSyncRoot(scoped_ptr<SyncTaskToken> token);
+  void DidFindSyncRoot(scoped_ptr<SyncTaskToken> token,
                        google_apis::GDataErrorCode error,
                        scoped_ptr<google_apis::ResourceList> resource_list);
-  void CreateSyncRoot(const SyncStatusCallback& callback);
-  void DidCreateSyncRoot(const SyncStatusCallback& callback,
+  void CreateSyncRoot(scoped_ptr<SyncTaskToken> token);
+  void DidCreateSyncRoot(scoped_ptr<SyncTaskToken> token,
                          google_apis::GDataErrorCode error,
                          scoped_ptr<google_apis::ResourceEntry> entry);
-  void DetachSyncRoot(const SyncStatusCallback& callback);
-  void DidDetachSyncRoot(const SyncStatusCallback& callback,
+  void DetachSyncRoot(scoped_ptr<SyncTaskToken> token);
+  void DidDetachSyncRoot(scoped_ptr<SyncTaskToken> token,
                          google_apis::GDataErrorCode error);
-  void ListAppRootFolders(const SyncStatusCallback& callback);
+  void ListAppRootFolders(scoped_ptr<SyncTaskToken> token);
   void DidListAppRootFolders(
-      const SyncStatusCallback& callback,
+      scoped_ptr<SyncTaskToken> token,
       google_apis::GDataErrorCode error,
       scoped_ptr<google_apis::ResourceList> resource_list);
-  void PopulateDatabase(const SyncStatusCallback& callback);
-  void DidPopulateDatabase(const SyncStatusCallback& callback,
+  void PopulateDatabase(scoped_ptr<SyncTaskToken> token);
+  void DidPopulateDatabase(scoped_ptr<SyncTaskToken> token,
                            SyncStatusCode status);
 
   SyncEngineContext* sync_context_;  // Not owned.
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc
index 5d1c4d8..58d8743 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_engine_initializer_unittest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_test_util.h"
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
 #include "chrome/browser/sync_file_system/sync_file_system_test_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "google_apis/drive/drive_api_parser.h"
@@ -48,10 +49,15 @@
         "sync_file_system/account_metadata.json"));
     ASSERT_TRUE(fake_drive_service_.LoadResourceListForWapi(
         "gdata/empty_feed.json"));
+
+    sync_task_manager_.reset(new SyncTaskManager(
+        base::WeakPtr<SyncTaskManager::Client>(),
+        1 /* maximum_parallel_task */));
+    sync_task_manager_->Initialize(SYNC_STATUS_OK);
   }
 
   virtual void TearDown() OVERRIDE {
-    initializer_.reset();
+    sync_task_manager_.reset();
     metadata_database_.reset();
     base::RunLoop().RunUntilIdle();
   }
@@ -61,21 +67,33 @@
   }
 
   SyncStatusCode RunInitializer() {
-    initializer_.reset(new SyncEngineInitializer(
-        NULL,
-        base::MessageLoopProxy::current(),
-        &fake_drive_service_,
-        database_path(),
-        in_memory_env_.get()));
+    SyncEngineInitializer* initializer =
+        new SyncEngineInitializer(
+            NULL,
+            base::MessageLoopProxy::current(),
+            &fake_drive_service_,
+            database_path(),
+            in_memory_env_.get());
     SyncStatusCode status = SYNC_STATUS_UNKNOWN;
 
-    initializer_->RunSequential(CreateResultReceiver(&status));
-    base::RunLoop().RunUntilIdle();
+    sync_task_manager_->ScheduleSyncTask(
+        FROM_HERE,
+        scoped_ptr<SyncTask>(initializer),
+        SyncTaskManager::PRIORITY_MED,
+        base::Bind(&SyncEngineInitializerTest::DidRunInitializer,
+                   base::Unretained(this), initializer, &status));
 
-    metadata_database_ = initializer_->PassMetadataDatabase();
+    base::RunLoop().RunUntilIdle();
     return status;
   }
 
+  void DidRunInitializer(SyncEngineInitializer* initializer,
+                         SyncStatusCode* status_out,
+                         SyncStatusCode status) {
+    *status_out = status;
+    metadata_database_ = initializer->PassMetadataDatabase();
+  }
+
   SyncStatusCode PopulateDatabase(
       const google_apis::FileResource& sync_root,
       const google_apis::FileResource** app_roots,
@@ -135,7 +153,7 @@
     for (size_t i = 0; i < sync_root->parents().size(); ++i) {
       google_apis::GDataErrorCode error = google_apis::GDATA_OTHER_ERROR;
       fake_drive_service_.RemoveResourceFromDirectory(
-          sync_root->parents()[i]->file_id(),
+          sync_root->parents()[i].file_id(),
           sync_root->file_id(),
           CreateResultReceiver(&error));
       base::RunLoop().RunUntilIdle();
@@ -201,8 +219,8 @@
   scoped_ptr<leveldb::Env> in_memory_env_;
   drive::FakeDriveService fake_drive_service_;
 
-  scoped_ptr<SyncEngineInitializer> initializer_;
   scoped_ptr<MetadataDatabase> metadata_database_;
+  scoped_ptr<SyncTaskManager> sync_task_manager_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncEngineInitializerTest);
 };
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc b/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc
index 6755932..fb273d6 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_task_manager.cc
@@ -51,8 +51,10 @@
 }
 
 SyncTaskManager::SyncTaskManager(
-    base::WeakPtr<Client> client)
+    base::WeakPtr<Client> client,
+    size_t maximum_background_task)
     : client_(client),
+      maximum_background_task_(maximum_background_task),
       pending_task_seq_(0),
       task_token_seq_(SyncTaskToken::kMinimumBackgroundTaskTokenID) {
 }
@@ -191,7 +193,13 @@
     scoped_ptr<SyncTaskToken> token,
     scoped_ptr<BlockingFactor> blocking_factor,
     const Continuation& continuation) {
-  if (!dependency_manager_.Insert(*blocking_factor)) {
+  if (!maximum_background_task_) {
+    continuation.Run(token.Pass());
+    return;
+  }
+
+  if (running_background_task_.size() >= maximum_background_task_ ||
+      !dependency_manager_.Insert(*blocking_factor)) {
     DCHECK(!running_background_task_.empty());
 
     // Wait for NotifyTaskDone to release a |blocking_factor|.
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_task_manager.h b/chrome/browser/sync_file_system/drive_backend/sync_task_manager.h
index 49e6bdc..7b29035 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_task_manager.h
+++ b/chrome/browser/sync_file_system/drive_backend/sync_task_manager.h
@@ -56,7 +56,10 @@
         bool last_operation_used_network) = 0;
   };
 
-  explicit SyncTaskManager(base::WeakPtr<Client> client);
+  // Runs at most |maximum_background_tasks| parallel as background tasks.
+  // If |maximum_background_tasks| is zero, all task runs as foreground task.
+  SyncTaskManager(base::WeakPtr<Client> client,
+                  size_t maximum_background_task);
   virtual ~SyncTaskManager();
 
   // This needs to be called to start task scheduling.
@@ -148,6 +151,8 @@
   // deletion.
   base::ScopedPtrHashMap<int64, SyncTask> running_background_task_;
 
+  size_t maximum_background_task_;
+
   // Holds pending continuation to move task to background.
   base::Closure pending_backgrounding_task_;
 
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc b/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
index a68df69..48a376b 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_task_manager_unittest.cc
@@ -49,12 +49,13 @@
     : public SyncTaskManager::Client,
       public base::SupportsWeakPtr<TaskManagerClient> {
  public:
-  TaskManagerClient()
+  explicit TaskManagerClient(int64 maximum_background_task)
       : maybe_schedule_next_task_count_(0),
         task_scheduled_count_(0),
         idle_task_scheduled_count_(0),
         last_operation_status_(SYNC_STATUS_OK) {
-    task_manager_.reset(new SyncTaskManager(AsWeakPtr()));
+    task_manager_.reset(new SyncTaskManager(
+        AsWeakPtr(), maximum_background_task));
     task_manager_->Initialize(SYNC_STATUS_OK);
     maybe_schedule_next_task_count_ = 0;
   }
@@ -230,7 +231,7 @@
 
 TEST(SyncTaskManagerTest, ScheduleTask) {
   base::MessageLoop message_loop;
-  TaskManagerClient client;
+  TaskManagerClient client(0 /* maximum_background_task */);
   int callback_count = 0;
   SyncStatusCode callback_status = SYNC_STATUS_OK;
 
@@ -250,7 +251,7 @@
 
 TEST(SyncTaskManagerTest, ScheduleTwoTasks) {
   base::MessageLoop message_loop;
-  TaskManagerClient client;
+  TaskManagerClient client(0 /* maximum_background_task */);
   int callback_count = 0;
   SyncStatusCode callback_status = SYNC_STATUS_OK;
 
@@ -273,7 +274,7 @@
 
 TEST(SyncTaskManagerTest, ScheduleIdleTask) {
   base::MessageLoop message_loop;
-  TaskManagerClient client;
+  TaskManagerClient client(0 /* maximum_background_task */);
 
   client.ScheduleTaskIfIdle(kStatus1);
   message_loop.RunUntilIdle();
@@ -287,7 +288,7 @@
 
 TEST(SyncTaskManagerTest, ScheduleIdleTaskWhileNotIdle) {
   base::MessageLoop message_loop;
-  TaskManagerClient client;
+  TaskManagerClient client(0 /* maximum_background_task */);
   int callback_count = 0;
   SyncStatusCode callback_status = SYNC_STATUS_OK;
 
@@ -317,7 +318,8 @@
   bool task_completed = false;
 
   {
-    SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
+    SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
+                                 0 /* maximum_background_task */);
     task_manager.Initialize(SYNC_STATUS_OK);
     task_manager.ScheduleSyncTask(
         FROM_HERE,
@@ -336,7 +338,8 @@
 
 TEST(SyncTaskManagerTest, ScheduleTaskAtPriority) {
   base::MessageLoop message_loop;
-  SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
+  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
+                               0 /* maximum_background_task */);
   task_manager.Initialize(SYNC_STATUS_OK);
 
   int callback_count = 0;
@@ -394,7 +397,8 @@
 
 TEST(SyncTaskManagerTest, BackgroundTask_Sequential) {
   base::MessageLoop message_loop;
-  SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
+  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
+                               10 /* maximum_background_task */);
   task_manager.Initialize(SYNC_STATUS_OK);
 
   SyncStatusCode status = SYNC_STATUS_FAILED;
@@ -433,7 +437,8 @@
 
 TEST(SyncTaskManagerTest, BackgroundTask_Parallel) {
   base::MessageLoop message_loop;
-  SyncTaskManager task_manager((base::WeakPtr<SyncTaskManager::Client>()));
+  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
+                               10 /* maximum_background_task */);
   task_manager.Initialize(SYNC_STATUS_OK);
 
   SyncStatusCode status = SYNC_STATUS_FAILED;
@@ -470,5 +475,45 @@
   EXPECT_EQ(3, stats.max_parallel_task);
 }
 
+TEST(SyncTaskManagerTest, BackgroundTask_Throttled) {
+  base::MessageLoop message_loop;
+  SyncTaskManager task_manager(base::WeakPtr<SyncTaskManager::Client>(),
+                               2 /* maximum_background_task */);
+  task_manager.Initialize(SYNC_STATUS_OK);
+
+  SyncStatusCode status = SYNC_STATUS_FAILED;
+  BackgroundTask::Stats stats;
+  task_manager.ScheduleSyncTask(
+      FROM_HERE,
+      scoped_ptr<SyncTask>(new BackgroundTask(
+          "app_id", MAKE_PATH("/hoge"),
+          &stats)),
+      SyncTaskManager::PRIORITY_MED,
+      CreateResultReceiver(&status));
+
+  task_manager.ScheduleSyncTask(
+      FROM_HERE,
+      scoped_ptr<SyncTask>(new BackgroundTask(
+          "app_id", MAKE_PATH("/fuga"),
+          &stats)),
+      SyncTaskManager::PRIORITY_MED,
+      CreateResultReceiver(&status));
+
+  task_manager.ScheduleSyncTask(
+      FROM_HERE,
+      scoped_ptr<SyncTask>(new BackgroundTask(
+          "app_id", MAKE_PATH("/piyo"),
+          &stats)),
+      SyncTaskManager::PRIORITY_MED,
+      CreateResultReceiver(&status));
+
+  message_loop.RunUntilIdle();
+
+  EXPECT_EQ(SYNC_STATUS_OK, status);
+  EXPECT_EQ(0, stats.running_background_task);
+  EXPECT_EQ(3, stats.finished_task);
+  EXPECT_EQ(2, stats.max_parallel_task);
+}
+
 }  // namespace drive_backend
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.cc b/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.cc
index cf2e51c..429d217 100644
--- a/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.cc
+++ b/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.cc
@@ -59,10 +59,11 @@
 
 }  // namespace
 
-BlockingFactor::BlockingFactor() {}
+BlockingFactor::BlockingFactor() : exclusive(false) {}
 BlockingFactor::~BlockingFactor() {}
 
-TaskDependencyManager::TaskDependencyManager() {}
+TaskDependencyManager::TaskDependencyManager()
+    : running_exclusive_task_(false) {}
 
 TaskDependencyManager::~TaskDependencyManager() {
   DCHECK(paths_by_app_id_.empty());
@@ -71,6 +72,18 @@
 }
 
 bool TaskDependencyManager::Insert(const BlockingFactor& blocking_factor) {
+  if (running_exclusive_task_)
+    return false;
+
+  if (blocking_factor.exclusive) {
+    if (!tracker_ids_.empty() ||
+        !file_ids_.empty() ||
+        !paths_by_app_id_.empty())
+      return false;
+    running_exclusive_task_ = true;
+    return true;
+  }
+
   if (!InsertAllOrNone(blocking_factor.tracker_ids, &tracker_ids_))
     goto fail_on_tracker_id_insertion;
 
@@ -97,6 +110,16 @@
 }
 
 void TaskDependencyManager::Erase(const BlockingFactor& blocking_factor) {
+  if (blocking_factor.exclusive) {
+    DCHECK(running_exclusive_task_);
+    DCHECK(paths_by_app_id_.empty());
+    DCHECK(file_ids_.empty());
+    DCHECK(tracker_ids_.empty());
+
+    running_exclusive_task_ = false;
+    return;
+  }
+
   if (!blocking_factor.app_id.empty()) {
     EraseContainer(blocking_factor.paths,
                    &paths_by_app_id_[blocking_factor.app_id]);
diff --git a/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.h b/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.h
index 68bd427..64e5a36 100644
--- a/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.h
+++ b/chrome/browser/sync_file_system/drive_backend/task_dependency_manager.h
@@ -18,6 +18,7 @@
 namespace drive_backend {
 
 struct BlockingFactor {
+  bool exclusive;
   std::string app_id;
   std::vector<base::FilePath> paths;
   std::vector<std::string> file_ids;
@@ -48,6 +49,7 @@
  private:
   friend class TaskDependencyManagerTest;
 
+  bool running_exclusive_task_;
   std::map<std::string, SubtreeSet> paths_by_app_id_;
   std::set<std::string> file_ids_;
   std::set<int64> tracker_ids_;
diff --git a/chrome/browser/sync_file_system/drive_backend/task_dependency_manager_unittest.cc b/chrome/browser/sync_file_system/drive_backend/task_dependency_manager_unittest.cc
index 6fe5317..4887932 100644
--- a/chrome/browser/sync_file_system/drive_backend/task_dependency_manager_unittest.cc
+++ b/chrome/browser/sync_file_system/drive_backend/task_dependency_manager_unittest.cc
@@ -36,6 +36,18 @@
   return manager->Erase(blocker);
 }
 
+bool InsertExclusiveTask(TaskDependencyManager* manager) {
+  BlockingFactor blocker;
+  blocker.exclusive = true;
+  return manager->Insert(blocker);
+}
+
+void EraseExclusiveTask(TaskDependencyManager* manager) {
+  BlockingFactor blocker;
+  blocker.exclusive = true;
+  manager->Erase(blocker);
+}
+
 }  // namespace
 
 TEST(TaskDependencyManagerTest, BasicTest) {
@@ -79,5 +91,20 @@
   ErasePath(&manager, "app_id", FPL("/ancestor/parent/self/child/descendant"));
 }
 
+TEST(TaskDependencyManagerTest, ExclusiveTask) {
+  TaskDependencyManager manager;
+
+  EXPECT_TRUE(InsertPath(&manager, "app_id", FPL("/foo/bar")));
+  EXPECT_FALSE(InsertExclusiveTask(&manager));
+  ErasePath(&manager, "app_id", FPL("/foo/bar"));
+
+  EXPECT_TRUE(InsertExclusiveTask(&manager));
+  EXPECT_FALSE(InsertPath(&manager, "app_id", FPL("/foo/bar")));
+  EraseExclusiveTask(&manager);
+
+  EXPECT_TRUE(InsertPath(&manager, "app_id", FPL("/foo/bar")));
+  ErasePath(&manager, "app_id", FPL("/foo/bar"));
+}
+
 }  // namespace drive_backend
 }  // namespace sync_file_system
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc b/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc
index 7fdb29b..316ec2c 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/api_util.cc
@@ -27,7 +27,7 @@
 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_util.h"
 #include "chrome/browser/sync_file_system/logger.h"
 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
diff --git a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc
index b737e4d..123a3df 100644
--- a/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc
+++ b/chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.cc
@@ -93,7 +93,8 @@
     Profile* profile) {
   scoped_ptr<DriveFileSyncService> service(new DriveFileSyncService(profile));
   scoped_ptr<drive_backend::SyncTaskManager> task_manager(
-      new drive_backend::SyncTaskManager(service->AsWeakPtr()));
+      new drive_backend::SyncTaskManager(service->AsWeakPtr(),
+                                         0 /* maximum_background_task */));
   SyncStatusCallback callback = base::Bind(
       &drive_backend::SyncTaskManager::Initialize, task_manager->AsWeakPtr());
   service->Initialize(task_manager.Pass(), callback);
@@ -116,7 +117,8 @@
     scoped_ptr<DriveMetadataStore> metadata_store) {
   scoped_ptr<DriveFileSyncService> service(new DriveFileSyncService(profile));
   scoped_ptr<drive_backend::SyncTaskManager> task_manager(
-      new drive_backend::SyncTaskManager(service->AsWeakPtr()));
+      new drive_backend::SyncTaskManager(service->AsWeakPtr(),
+                                         0 /* maximum_background_task */));
   SyncStatusCallback callback = base::Bind(
       &drive_backend::SyncTaskManager::Initialize, task_manager->AsWeakPtr());
   service->InitializeForTesting(task_manager.Pass(),
diff --git a/chrome/browser/tab_contents/retargeting_details.h b/chrome/browser/tab_contents/retargeting_details.h
index 108b6a6..c80a1ca 100644
--- a/chrome/browser/tab_contents/retargeting_details.h
+++ b/chrome/browser/tab_contents/retargeting_details.h
@@ -16,8 +16,9 @@
   // The source tab contents.
   content::WebContents* source_web_contents;
 
-  // The frame ID of the source tab from which the retargeting was triggered.
-  int64 source_frame_id;
+  // The routing id of the source render frame from which the retargeting was
+  // triggered.
+  int64 source_render_frame_id;
 
   // The target URL.
   GURL target_url;
diff --git a/chrome/browser/task_manager/background_information.cc b/chrome/browser/task_manager/background_information.cc
new file mode 100644
index 0000000..e6fcd89
--- /dev/null
+++ b/chrome/browser/task_manager/background_information.cc
@@ -0,0 +1,174 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_manager/background_information.h"
+
+#include "base/i18n/rtl.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/background/background_contents_service.h"
+#include "chrome/browser/background/background_contents_service_factory.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/tab_contents/background_contents.h"
+#include "chrome/browser/task_manager/renderer_resource.h"
+#include "chrome/browser/task_manager/resource_provider.h"
+#include "chrome/browser/task_manager/task_manager.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/view_type_utils.h"
+#include "extensions/common/extension.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/image/image_skia.h"
+
+using content::RenderProcessHost;
+using content::RenderViewHost;
+using content::WebContents;
+using extensions::Extension;
+
+namespace task_manager {
+
+class BackgroundContentsResource : public RendererResource {
+ public:
+  BackgroundContentsResource(BackgroundContents* background_contents,
+                             const base::string16& application_name);
+  virtual ~BackgroundContentsResource();
+
+  // Resource methods:
+  virtual base::string16 GetTitle() const OVERRIDE;
+  virtual gfx::ImageSkia GetIcon() const OVERRIDE;
+
+  const base::string16& application_name() const { return application_name_; }
+
+ private:
+  BackgroundContents* background_contents_;
+
+  base::string16 application_name_;
+
+  // The icon painted for BackgroundContents.
+  // TODO(atwilson): Use the favicon when there's a way to get the favicon for
+  // BackgroundContents.
+  static gfx::ImageSkia* default_icon_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundContentsResource);
+};
+
+gfx::ImageSkia* BackgroundContentsResource::default_icon_ = NULL;
+
+BackgroundContentsResource::BackgroundContentsResource(
+    BackgroundContents* background_contents,
+    const base::string16& application_name)
+    : RendererResource(
+          background_contents->web_contents()->GetRenderProcessHost()->
+              GetHandle(),
+          background_contents->web_contents()->GetRenderViewHost()),
+      background_contents_(background_contents),
+      application_name_(application_name) {
+  // Just use the same icon that other extension resources do.
+  // TODO(atwilson): Use the favicon when that's available.
+  if (!default_icon_) {
+    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+    default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON);
+  }
+  // Ensure that the string has the appropriate direction markers (see comment
+  // in TabContentsResource::GetTitle()).
+  base::i18n::AdjustStringForLocaleDirection(&application_name_);
+}
+
+BackgroundContentsResource::~BackgroundContentsResource() {}
+
+base::string16 BackgroundContentsResource::GetTitle() const {
+  base::string16 title = application_name_;
+
+  if (title.empty()) {
+    // No title (can't locate the parent app for some reason) so just display
+    // the URL (properly forced to be LTR).
+    title = base::i18n::GetDisplayStringInLTRDirectionality(
+        base::UTF8ToUTF16(background_contents_->GetURL().spec()));
+  }
+  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX, title);
+}
+
+gfx::ImageSkia BackgroundContentsResource::GetIcon() const {
+  return *default_icon_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BackgroundInformation class
+////////////////////////////////////////////////////////////////////////////////
+
+BackgroundInformation::BackgroundInformation() {}
+
+BackgroundInformation::~BackgroundInformation() {}
+
+bool BackgroundInformation::CheckOwnership(WebContents* web_contents) {
+  extensions::ViewType view_type = extensions::GetViewType(web_contents);
+  return view_type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS;
+}
+
+void BackgroundInformation::GetAll(const NewWebContentsCallback& callback) {
+  // Add all the existing BackgroundContents from every profile, including
+  // incognito profiles.
+  ProfileManager* profile_manager = g_browser_process->profile_manager();
+  std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
+  size_t num_default_profiles = profiles.size();
+  for (size_t i = 0; i < num_default_profiles; ++i) {
+    if (profiles[i]->HasOffTheRecordProfile()) {
+      profiles.push_back(profiles[i]->GetOffTheRecordProfile());
+    }
+  }
+  for (size_t i = 0; i < profiles.size(); ++i) {
+    BackgroundContentsService* background_contents_service =
+        BackgroundContentsServiceFactory::GetForProfile(profiles[i]);
+    std::vector<BackgroundContents*> contents =
+        background_contents_service->GetBackgroundContents();
+    for (std::vector<BackgroundContents*>::iterator iterator = contents.begin();
+         iterator != contents.end();
+         ++iterator) {
+      callback.Run((*iterator)->web_contents());
+    }
+  }
+}
+
+scoped_ptr<RendererResource> BackgroundInformation::MakeResource(
+    WebContents* web_contents) {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  ExtensionService* extension_service = profile->GetExtensionService();
+  BackgroundContentsService* background_contents_service =
+      BackgroundContentsServiceFactory::GetForProfile(profile);
+  std::vector<BackgroundContents*> contents =
+      background_contents_service->GetBackgroundContents();
+  for (std::vector<BackgroundContents*>::iterator iterator = contents.begin();
+       iterator != contents.end();
+       ++iterator) {
+    if ((*iterator)->web_contents() == web_contents) {
+      base::string16 application_name;
+      // Lookup the name from the parent extension.
+      if (extension_service) {
+        const base::string16& application_id =
+            background_contents_service->GetParentApplicationId(*iterator);
+        const Extension* extension = extension_service->GetExtensionById(
+            base::UTF16ToUTF8(application_id), false);
+        if (extension)
+          application_name = base::UTF8ToUTF16(extension->name());
+      }
+      return scoped_ptr<RendererResource>(
+          new BackgroundContentsResource(*iterator, application_name));
+    }
+  }
+  NOTREACHED();
+  return scoped_ptr<RendererResource>();
+}
+
+}  // namespace task_manager
diff --git a/chrome/browser/task_manager/background_information.h b/chrome/browser/task_manager/background_information.h
new file mode 100644
index 0000000..8bd7327
--- /dev/null
+++ b/chrome/browser/task_manager/background_information.h
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TASK_MANAGER_BACKGROUND_INFORMATION_H_
+#define CHROME_BROWSER_TASK_MANAGER_BACKGROUND_INFORMATION_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/task_manager/web_contents_information.h"
+
+namespace task_manager {
+
+// WebContentsInformation for BackgroundContents-owned WebContentses.
+class BackgroundInformation
+    : public NotificationObservingWebContentsInformation {
+ public:
+  BackgroundInformation();
+  virtual ~BackgroundInformation();
+
+  // WebContentsInformation implementation.
+  virtual bool CheckOwnership(content::WebContents* web_contents) OVERRIDE;
+  virtual void GetAll(const NewWebContentsCallback& callback) OVERRIDE;
+  virtual scoped_ptr<RendererResource> MakeResource(
+      content::WebContents* web_contents) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BackgroundInformation);
+};
+
+}  // namespace task_manager
+
+#endif  // CHROME_BROWSER_TASK_MANAGER_BACKGROUND_INFORMATION_H_
diff --git a/chrome/browser/task_manager/background_resource_provider.cc b/chrome/browser/task_manager/background_resource_provider.cc
deleted file mode 100644
index 345017a..0000000
--- a/chrome/browser/task_manager/background_resource_provider.cc
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/task_manager/background_resource_provider.h"
-
-#include "base/i18n/rtl.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/background/background_contents_service.h"
-#include "chrome/browser/background/background_contents_service_factory.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/tab_contents/background_contents.h"
-#include "chrome/browser/task_manager/renderer_resource.h"
-#include "chrome/browser/task_manager/resource_provider.h"
-#include "chrome/browser/task_manager/task_manager.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/common/extension.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/image/image_skia.h"
-
-using content::RenderProcessHost;
-using content::RenderViewHost;
-using content::WebContents;
-using extensions::Extension;
-
-namespace task_manager {
-
-class BackgroundContentsResource : public RendererResource {
- public:
-  BackgroundContentsResource(
-      BackgroundContents* background_contents,
-      const base::string16& application_name);
-  virtual ~BackgroundContentsResource();
-
-  // Resource methods:
-  virtual base::string16 GetTitle() const OVERRIDE;
-  virtual gfx::ImageSkia GetIcon() const OVERRIDE;
-
-  const base::string16& application_name() const { return application_name_; }
- private:
-  BackgroundContents* background_contents_;
-
-  base::string16 application_name_;
-
-  // The icon painted for BackgroundContents.
-  // TODO(atwilson): Use the favicon when there's a way to get the favicon for
-  // BackgroundContents.
-  static gfx::ImageSkia* default_icon_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackgroundContentsResource);
-};
-
-gfx::ImageSkia* BackgroundContentsResource::default_icon_ = NULL;
-
-// TODO(atwilson): http://crbug.com/116893
-// HACK: if the process handle is invalid, we use the current process's handle.
-// This preserves old behavior but is incorrect, and should be fixed.
-BackgroundContentsResource::BackgroundContentsResource(
-    BackgroundContents* background_contents,
-    const base::string16& application_name)
-    : RendererResource(
-          background_contents->web_contents()->GetRenderProcessHost()->
-              GetHandle() ?
-              background_contents->web_contents()->GetRenderProcessHost()->
-                  GetHandle() :
-              base::Process::Current().handle(),
-          background_contents->web_contents()->GetRenderViewHost()),
-      background_contents_(background_contents),
-      application_name_(application_name) {
-  // Just use the same icon that other extension resources do.
-  // TODO(atwilson): Use the favicon when that's available.
-  if (!default_icon_) {
-    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
-    default_icon_ = rb.GetImageSkiaNamed(IDR_PLUGINS_FAVICON);
-  }
-  // Ensure that the string has the appropriate direction markers (see comment
-  // in TabContentsResource::GetTitle()).
-  base::i18n::AdjustStringForLocaleDirection(&application_name_);
-}
-
-BackgroundContentsResource::~BackgroundContentsResource() {
-}
-
-base::string16 BackgroundContentsResource::GetTitle() const {
-  base::string16 title = application_name_;
-
-  if (title.empty()) {
-    // No title (can't locate the parent app for some reason) so just display
-    // the URL (properly forced to be LTR).
-    title = base::i18n::GetDisplayStringInLTRDirectionality(
-        base::UTF8ToUTF16(background_contents_->GetURL().spec()));
-  }
-  return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_BACKGROUND_PREFIX, title);
-}
-
-gfx::ImageSkia BackgroundContentsResource::GetIcon() const {
-  return *default_icon_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// BackgroundContentsResourceProvider class
-////////////////////////////////////////////////////////////////////////////////
-
-BackgroundContentsResourceProvider::
-    BackgroundContentsResourceProvider(TaskManager* task_manager)
-    : updating_(false),
-      task_manager_(task_manager) {
-}
-
-BackgroundContentsResourceProvider::~BackgroundContentsResourceProvider() {
-}
-
-Resource* BackgroundContentsResourceProvider::GetResource(
-    int origin_pid,
-    int child_id,
-    int route_id) {
-  // If an origin PID was specified, the request is from a plugin, not the
-  // render view host process
-  if (origin_pid)
-    return NULL;
-
-  content::RenderFrameHost* rfh =
-      content::RenderFrameHost::FromID(child_id, route_id);
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(rfh);
-
-  for (Resources::iterator i = resources_.begin(); i != resources_.end(); i++) {
-    if (web_contents == i->first->web_contents())
-      return i->second;
-  }
-
-  // Can happen if the page went away while a network request was being
-  // performed.
-  return NULL;
-}
-
-void BackgroundContentsResourceProvider::StartUpdating() {
-  DCHECK(!updating_);
-  updating_ = true;
-
-  // Add all the existing BackgroundContents from every profile, including
-  // incognito profiles.
-  ProfileManager* profile_manager = g_browser_process->profile_manager();
-  std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles());
-  size_t num_default_profiles = profiles.size();
-  for (size_t i = 0; i < num_default_profiles; ++i) {
-    if (profiles[i]->HasOffTheRecordProfile()) {
-      profiles.push_back(profiles[i]->GetOffTheRecordProfile());
-    }
-  }
-  for (size_t i = 0; i < profiles.size(); ++i) {
-    BackgroundContentsService* background_contents_service =
-        BackgroundContentsServiceFactory::GetForProfile(profiles[i]);
-    std::vector<BackgroundContents*> contents =
-        background_contents_service->GetBackgroundContents();
-    ExtensionService* extension_service = profiles[i]->GetExtensionService();
-    for (std::vector<BackgroundContents*>::iterator iterator = contents.begin();
-         iterator != contents.end(); ++iterator) {
-      base::string16 application_name;
-      // Lookup the name from the parent extension.
-      if (extension_service) {
-        const base::string16& application_id =
-            background_contents_service->GetParentApplicationId(*iterator);
-        const Extension* extension = extension_service->GetExtensionById(
-            base::UTF16ToUTF8(application_id), false);
-        if (extension)
-          application_name = base::UTF8ToUTF16(extension->name());
-      }
-      Add(*iterator, application_name);
-    }
-  }
-
-  // Then we register for notifications to get new BackgroundContents.
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED,
-                 content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
-                 content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Add(this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-                 content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Add(this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
-                 content::NotificationService::AllBrowserContextsAndSources());
-}
-
-void BackgroundContentsResourceProvider::StopUpdating() {
-  DCHECK(updating_);
-  updating_ = false;
-
-  // Unregister for notifications
-  registrar_.Remove(
-      this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED,
-      content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Remove(
-      this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED,
-      content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Remove(
-      this, chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED,
-      content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Remove(
-      this, content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED,
-      content::NotificationService::AllBrowserContextsAndSources());
-
-  // Delete all the resources.
-  STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
-
-  resources_.clear();
-}
-
-void BackgroundContentsResourceProvider::AddToTaskManager(
-    BackgroundContents* background_contents,
-    const base::string16& application_name) {
-  BackgroundContentsResource* resource =
-      new BackgroundContentsResource(background_contents, application_name);
-  resources_[background_contents] = resource;
-  task_manager_->AddResource(resource);
-}
-
-void BackgroundContentsResourceProvider::Add(
-    BackgroundContents* contents, const base::string16& application_name) {
-  if (!updating_)
-    return;
-
-  // TODO(atwilson): http://crbug.com/116893
-  // We should check that the process handle is valid here, but it won't
-  // be in the case of NOTIFICATION_BACKGROUND_CONTENTS_OPENED.
-
-  // Should never add the same BackgroundContents twice.
-  DCHECK(resources_.find(contents) == resources_.end());
-  AddToTaskManager(contents, application_name);
-}
-
-void BackgroundContentsResourceProvider::Remove(BackgroundContents* contents) {
-  if (!updating_)
-    return;
-  Resources::iterator iter = resources_.find(contents);
-  DCHECK(iter != resources_.end());
-
-  // Remove the resource from the Task Manager.
-  BackgroundContentsResource* resource = iter->second;
-  task_manager_->RemoveResource(resource);
-  // And from the provider.
-  resources_.erase(iter);
-  // Finally, delete the resource.
-  delete resource;
-}
-
-void BackgroundContentsResourceProvider::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  switch (type) {
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_OPENED: {
-      // Get the name from the parent application. If no parent application is
-      // found, just pass an empty string - BackgroundContentsResource::GetTitle
-      // will display the URL instead in this case. This should never happen
-      // except in rare cases when an extension is being unloaded or chrome is
-      // exiting while the task manager is displayed.
-      base::string16 application_name;
-      ExtensionService* service =
-          content::Source<Profile>(source)->GetExtensionService();
-      if (service) {
-        std::string application_id = base::UTF16ToUTF8(
-            content::Details<BackgroundContentsOpenedDetails>(details)->
-                application_id);
-        const Extension* extension =
-            service->GetExtensionById(application_id, false);
-        // Extension can be NULL when running unit tests.
-        if (extension)
-          application_name = base::UTF8ToUTF16(extension->name());
-      }
-      Add(content::Details<BackgroundContentsOpenedDetails>(details)->contents,
-          application_name);
-      // Opening a new BackgroundContents needs to force the display to refresh
-      // (applications may now be considered "background" that weren't before).
-      task_manager_->ModelChanged();
-      break;
-    }
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_NAVIGATED: {
-      BackgroundContents* contents =
-          content::Details<BackgroundContents>(details).ptr();
-      // Should never get a NAVIGATED before OPENED.
-      DCHECK(resources_.find(contents) != resources_.end());
-      // Preserve the application name.
-      base::string16 application_name(
-          resources_.find(contents)->second->application_name());
-      Remove(contents);
-      Add(contents, application_name);
-      break;
-    }
-    case chrome::NOTIFICATION_BACKGROUND_CONTENTS_DELETED:
-      Remove(content::Details<BackgroundContents>(details).ptr());
-      // Closing a BackgroundContents needs to force the display to refresh
-      // (applications may now be considered "foreground" that weren't before).
-      task_manager_->ModelChanged();
-      break;
-    case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: {
-      WebContents* web_contents = content::Source<WebContents>(source).ptr();
-      for (Resources::iterator i = resources_.begin(); i != resources_.end();
-           i++) {
-        if (i->first->web_contents() == web_contents) {
-          base::string16 application_name = i->second->application_name();
-          BackgroundContents* contents = i->first;
-          Remove(contents);
-          Add(contents, application_name);
-          return;
-        }
-      }
-      break;
-    }
-    default:
-      NOTREACHED() << "Unexpected notification.";
-      return;
-  }
-}
-
-}  // namespace task_manager
diff --git a/chrome/browser/task_manager/background_resource_provider.h b/chrome/browser/task_manager/background_resource_provider.h
deleted file mode 100644
index c4b0ec3..0000000
--- a/chrome/browser/task_manager/background_resource_provider.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_TASK_MANAGER_BACKGROUND_RESOURCE_PROVIDER_H_
-#define CHROME_BROWSER_TASK_MANAGER_BACKGROUND_RESOURCE_PROVIDER_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/strings/string16.h"
-#include "chrome/browser/task_manager/resource_provider.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-
-class BackgroundContents;
-class TaskManager;
-
-namespace task_manager {
-
-class BackgroundContentsResource;
-
-class BackgroundContentsResourceProvider
-    : public ResourceProvider,
-      public content::NotificationObserver {
- public:
-  explicit BackgroundContentsResourceProvider(TaskManager* task_manager);
-
-  virtual Resource* GetResource(int origin_pid,
-                                int child_id,
-                                int route_id) OVERRIDE;
-  virtual void StartUpdating() OVERRIDE;
-  virtual void StopUpdating() OVERRIDE;
-
-  // content::NotificationObserver method:
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
- private:
-  virtual ~BackgroundContentsResourceProvider();
-
-  void Add(BackgroundContents* background_contents,
-           const base::string16& title);
-  void Remove(BackgroundContents* background_contents);
-
-  void AddToTaskManager(BackgroundContents* background_contents,
-                        const base::string16& title);
-
-  // Whether we are currently reporting to the task manager. Used to ignore
-  // notifications sent after StopUpdating().
-  bool updating_;
-
-  TaskManager* task_manager_;
-
-  // Maps the actual resources (the BackgroundContents) to the Task Manager
-  // resources.
-  typedef std::map<BackgroundContents*, BackgroundContentsResource*>
-      Resources;
-  Resources resources_;
-
-  // A scoped container for notification registries.
-  content::NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackgroundContentsResourceProvider);
-};
-
-}  // namespace task_manager
-
-#endif  // CHROME_BROWSER_TASK_MANAGER_BACKGROUND_RESOURCE_PROVIDER_H_
diff --git a/chrome/browser/task_manager/extension_process_resource_provider.cc b/chrome/browser/task_manager/extension_process_resource_provider.cc
index d14ba08..3505150 100644
--- a/chrome/browser/task_manager/extension_process_resource_provider.cc
+++ b/chrome/browser/task_manager/extension_process_resource_provider.cc
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -245,15 +245,13 @@
     IsHandledByThisProvider(content::RenderViewHost* render_view_host) {
   WebContents* web_contents = WebContents::FromRenderViewHost(render_view_host);
   // Don't add WebContents that belong to a guest (those are handled by
-  // GuestResourceProvider). Otherwise they will be added twice, and
-  // in this case they will have the app's name as a title (due to the
-  // ExtensionProcessResource constructor).
+  // GuestInformation). Otherwise they will be added twice.
   if (web_contents->GetRenderProcessHost()->IsGuest())
     return false;
   extensions::ViewType view_type = extensions::GetViewType(web_contents);
   // Don't add tab contents (those are handled by TabContentsResourceProvider)
-  // or background contents (handled by BackgroundResourceProvider) or panels
-  // (handled by PanelResourceProvider)
+  // or background contents (handled by BackgroundInformation) or panels
+  // (handled by PanelInformation)
   return (view_type != extensions::VIEW_TYPE_TAB_CONTENTS &&
           view_type != extensions::VIEW_TYPE_BACKGROUND_CONTENTS &&
           view_type != extensions::VIEW_TYPE_PANEL);
diff --git a/chrome/browser/task_manager/extension_process_resource_provider.h b/chrome/browser/task_manager/extension_process_resource_provider.h
index 9c6e634..e2d0e7b 100644
--- a/chrome/browser/task_manager/extension_process_resource_provider.h
+++ b/chrome/browser/task_manager/extension_process_resource_provider.h
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
diff --git a/chrome/browser/task_manager/guest_information.cc b/chrome/browser/task_manager/guest_information.cc
new file mode 100644
index 0000000..e0926f2
--- /dev/null
+++ b/chrome/browser/task_manager/guest_information.cc
@@ -0,0 +1,118 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_manager/guest_information.h"
+
+#include "base/strings/string16.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/favicon/favicon_tab_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/task_manager/renderer_resource.h"
+#include "chrome/browser/task_manager/resource_provider.h"
+#include "chrome/browser/task_manager/task_manager.h"
+#include "chrome/browser/task_manager/task_manager_util.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_iterator.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/browser/web_contents.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_skia.h"
+
+using content::RenderProcessHost;
+using content::RenderViewHost;
+using content::RenderWidgetHost;
+using content::WebContents;
+using extensions::Extension;
+
+namespace task_manager {
+
+class GuestResource : public RendererResource {
+ public:
+  explicit GuestResource(content::RenderViewHost* render_view_host);
+  virtual ~GuestResource();
+
+  // Resource methods:
+  virtual Type GetType() const OVERRIDE;
+  virtual base::string16 GetTitle() const OVERRIDE;
+  virtual gfx::ImageSkia GetIcon() const OVERRIDE;
+  virtual content::WebContents* GetWebContents() const OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GuestResource);
+};
+
+GuestResource::GuestResource(RenderViewHost* render_view_host)
+    : RendererResource(
+          render_view_host->GetSiteInstance()->GetProcess()->GetHandle(),
+          render_view_host) {
+}
+
+GuestResource::~GuestResource() {
+}
+
+Resource::Type GuestResource::GetType() const {
+  return GUEST;
+}
+
+base::string16 GuestResource::GetTitle() const {
+  WebContents* web_contents = GetWebContents();
+  const int message_id = IDS_TASK_MANAGER_WEBVIEW_TAG_PREFIX;
+  if (web_contents) {
+    base::string16 title = util::GetTitleFromWebContents(web_contents);
+    return l10n_util::GetStringFUTF16(message_id, title);
+  }
+  return l10n_util::GetStringFUTF16(message_id, base::string16());
+}
+
+gfx::ImageSkia GuestResource::GetIcon() const {
+  WebContents* web_contents = GetWebContents();
+  if (web_contents && FaviconTabHelper::FromWebContents(web_contents)) {
+    return FaviconTabHelper::FromWebContents(web_contents)->
+        GetFavicon().AsImageSkia();
+  }
+  return gfx::ImageSkia();
+}
+
+WebContents* GuestResource::GetWebContents() const {
+  return WebContents::FromRenderViewHost(render_view_host());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// GuestInformation class
+////////////////////////////////////////////////////////////////////////////////
+
+GuestInformation::GuestInformation() {}
+
+GuestInformation::~GuestInformation() {}
+
+bool GuestInformation::CheckOwnership(WebContents* web_contents) {
+  // Guest WebContentses are created and owned internally by the content layer.
+  return web_contents->IsSubframe();
+}
+
+void GuestInformation::GetAll(const NewWebContentsCallback& callback) {
+  scoped_ptr<content::RenderWidgetHostIterator> widgets(
+      content::RenderWidgetHost::GetRenderWidgetHosts());
+  while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
+    if (widget->IsRenderView()) {
+      content::RenderViewHost* rvh = content::RenderViewHost::From(widget);
+      WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
+      if (web_contents && web_contents->IsSubframe())
+        callback.Run(web_contents);
+    }
+  }
+}
+
+scoped_ptr<RendererResource> GuestInformation::MakeResource(
+    WebContents* web_contents) {
+  return scoped_ptr<RendererResource>(
+      new GuestResource(web_contents->GetRenderViewHost()));
+}
+
+}  // namespace task_manager
diff --git a/chrome/browser/task_manager/guest_information.h b/chrome/browser/task_manager/guest_information.h
new file mode 100644
index 0000000..36e8062
--- /dev/null
+++ b/chrome/browser/task_manager/guest_information.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TASK_MANAGER_GUEST_INFORMATION_H_
+#define CHROME_BROWSER_TASK_MANAGER_GUEST_INFORMATION_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/task_manager/web_contents_information.h"
+
+namespace task_manager {
+
+class GuestResource;
+
+// WebContentsInformation for WebContentses that are browser plugin guests.
+class GuestInformation : public NotificationObservingWebContentsInformation {
+ public:
+  GuestInformation();
+  virtual ~GuestInformation();
+
+  // WebContentsInformation implementation.
+  virtual bool CheckOwnership(content::WebContents* web_contents) OVERRIDE;
+  virtual void GetAll(const NewWebContentsCallback& callback) OVERRIDE;
+  virtual scoped_ptr<RendererResource> MakeResource(
+      content::WebContents* web_contents) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GuestInformation);
+};
+
+}  // namespace task_manager
+
+#endif  // CHROME_BROWSER_TASK_MANAGER_GUEST_INFORMATION_H_
diff --git a/chrome/browser/task_manager/guest_resource_provider.cc b/chrome/browser/task_manager/guest_resource_provider.cc
deleted file mode 100644
index e01455e..0000000
--- a/chrome/browser/task_manager/guest_resource_provider.cc
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/task_manager/guest_resource_provider.h"
-
-#include "base/strings/string16.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/favicon/favicon_tab_helper.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/task_manager/renderer_resource.h"
-#include "chrome/browser/task_manager/resource_provider.h"
-#include "chrome/browser/task_manager/task_manager.h"
-#include "chrome/browser/task_manager/task_manager_util.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/render_widget_host_iterator.h"
-#include "content/public/browser/site_instance.h"
-#include "content/public/browser/web_contents.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_skia.h"
-
-using content::RenderProcessHost;
-using content::RenderViewHost;
-using content::RenderWidgetHost;
-using content::WebContents;
-using extensions::Extension;
-
-namespace task_manager {
-
-class GuestResource : public RendererResource {
- public:
-  explicit GuestResource(content::RenderViewHost* render_view_host);
-  virtual ~GuestResource();
-
-  // Resource methods:
-  virtual Type GetType() const OVERRIDE;
-  virtual base::string16 GetTitle() const OVERRIDE;
-  virtual gfx::ImageSkia GetIcon() const OVERRIDE;
-  virtual content::WebContents* GetWebContents() const OVERRIDE;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GuestResource);
-};
-
-GuestResource::GuestResource(RenderViewHost* render_view_host)
-    : RendererResource(
-          render_view_host->GetSiteInstance()->GetProcess()->GetHandle(),
-          render_view_host) {
-}
-
-GuestResource::~GuestResource() {
-}
-
-Resource::Type GuestResource::GetType() const {
-  return GUEST;
-}
-
-base::string16 GuestResource::GetTitle() const {
-  WebContents* web_contents = GetWebContents();
-  const int message_id = IDS_TASK_MANAGER_WEBVIEW_TAG_PREFIX;
-  if (web_contents) {
-    base::string16 title = util::GetTitleFromWebContents(web_contents);
-    return l10n_util::GetStringFUTF16(message_id, title);
-  }
-  return l10n_util::GetStringFUTF16(message_id, base::string16());
-}
-
-gfx::ImageSkia GuestResource::GetIcon() const {
-  WebContents* web_contents = GetWebContents();
-  if (web_contents && FaviconTabHelper::FromWebContents(web_contents)) {
-    return FaviconTabHelper::FromWebContents(web_contents)->
-        GetFavicon().AsImageSkia();
-  }
-  return gfx::ImageSkia();
-}
-
-WebContents* GuestResource::GetWebContents() const {
-  return WebContents::FromRenderViewHost(render_view_host());
-}
-
-GuestResourceProvider::GuestResourceProvider(TaskManager* task_manager)
-    :  updating_(false),
-       task_manager_(task_manager) {
-}
-
-GuestResourceProvider::~GuestResourceProvider() {
-}
-
-Resource* GuestResourceProvider::GetResource(
-    int origin_pid,
-    int child_id,
-    int route_id) {
-  // If an origin PID was specified then the request originated in a plugin
-  // working on the WebContents's behalf, so ignore it.
-  if (origin_pid)
-    return NULL;
-
-  content::RenderFrameHost* rfh =
-      content::RenderFrameHost::FromID(child_id, route_id);
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(rfh);
-
-  for (GuestResourceMap::iterator i = resources_.begin();
-       i != resources_.end(); ++i) {
-    WebContents* guest_contents = WebContents::FromRenderViewHost(i->first);
-    if (web_contents == guest_contents)
-      return i->second;
-  }
-
-  return NULL;
-}
-
-void GuestResourceProvider::StartUpdating() {
-  DCHECK(!updating_);
-  updating_ = true;
-
-  // Add all the existing guest WebContents.
-  scoped_ptr<content::RenderWidgetHostIterator> widgets(
-      RenderWidgetHost::GetRenderWidgetHosts());
-  while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
-    if (widget->IsRenderView()) {
-      RenderViewHost* rvh = RenderViewHost::From(widget);
-      WebContents* web_contents = WebContents::FromRenderViewHost(rvh);
-      if (web_contents && web_contents->IsSubframe())
-        Add(rvh);
-    }
-  }
-
-  // Then we register for notifications to get new guests.
-  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
-      content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
-      content::NotificationService::AllBrowserContextsAndSources());
-}
-
-void GuestResourceProvider::StopUpdating() {
-  DCHECK(updating_);
-  updating_ = false;
-
-  // Unregister for notifications.
-  registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
-      content::NotificationService::AllBrowserContextsAndSources());
-  registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
-      content::NotificationService::AllBrowserContextsAndSources());
-
-  // Delete all the resources.
-  STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
-
-  resources_.clear();
-}
-
-void GuestResourceProvider::Add(RenderViewHost* render_view_host) {
-  GuestResource* resource = new GuestResource(render_view_host);
-  resources_[render_view_host] = resource;
-  task_manager_->AddResource(resource);
-}
-
-void GuestResourceProvider::Remove(RenderViewHost* render_view_host) {
-  if (!updating_)
-    return;
-
-  GuestResourceMap::iterator iter = resources_.find(render_view_host);
-  if (iter == resources_.end())
-    return;
-
-  GuestResource* resource = iter->second;
-  task_manager_->RemoveResource(resource);
-  resources_.erase(iter);
-  delete resource;
-}
-
-void GuestResourceProvider::Observe(int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  WebContents* web_contents = content::Source<WebContents>(source).ptr();
-  if (!web_contents || !web_contents->IsSubframe())
-    return;
-
-  switch (type) {
-    case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
-      Add(web_contents->GetRenderViewHost());
-      break;
-    case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
-      Remove(web_contents->GetRenderViewHost());
-      break;
-    default:
-      NOTREACHED() << "Unexpected notification.";
-  }
-}
-
-}  // namespace task_manager
diff --git a/chrome/browser/task_manager/guest_resource_provider.h b/chrome/browser/task_manager/guest_resource_provider.h
deleted file mode 100644
index 17d390a..0000000
--- a/chrome/browser/task_manager/guest_resource_provider.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_TASK_MANAGER_GUEST_RESOURCE_PROVIDER_H_
-#define CHROME_BROWSER_TASK_MANAGER_GUEST_RESOURCE_PROVIDER_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "chrome/browser/task_manager/resource_provider.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-
-class TaskManager;
-
-namespace content {
-class RenderViewHost;
-}
-
-namespace task_manager {
-
-class GuestResource;
-
-class GuestResourceProvider : public ResourceProvider,
-                              public content::NotificationObserver {
- public:
-  explicit GuestResourceProvider(TaskManager* task_manager);
-
-  // ResourceProvider methods:
-  virtual Resource* GetResource(int origin_pid,
-                                int child_id,
-                                int route_id) OVERRIDE;
-  virtual void StartUpdating() OVERRIDE;
-  virtual void StopUpdating() OVERRIDE;
-
-  // content::NotificationObserver method:
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
- private:
-  virtual ~GuestResourceProvider();
-
-  void Add(content::RenderViewHost* render_view_host);
-  void Remove(content::RenderViewHost* render_view_host);
-
-  // Whether we are currently reporting to the task manager. Used to ignore
-  // notifications sent after StopUpdating().
-  bool updating_;
-
-  TaskManager* task_manager_;
-
-  typedef std::map<content::RenderViewHost*, GuestResource*> GuestResourceMap;
-  GuestResourceMap resources_;
-
-  // A scoped container for notification registries.
-  content::NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(GuestResourceProvider);
-};
-
-}  // namespace task_manager
-
-#endif  // CHROME_BROWSER_TASK_MANAGER_GUEST_RESOURCE_PROVIDER_H_
diff --git a/chrome/browser/task_manager/panel_information.cc b/chrome/browser/task_manager/panel_information.cc
new file mode 100644
index 0000000..aabb0c0
--- /dev/null
+++ b/chrome/browser/task_manager/panel_information.cc
@@ -0,0 +1,133 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_manager/panel_information.h"
+
+#include "base/i18n/rtl.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/task_manager/renderer_resource.h"
+#include "chrome/browser/task_manager/task_manager_util.h"
+#include "chrome/browser/ui/panels/panel.h"
+#include "chrome/browser/ui/panels/panel_manager.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/view_type_utils.h"
+#include "extensions/common/extension.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image_skia.h"
+
+using content::RenderProcessHost;
+using content::RenderViewHost;
+using content::WebContents;
+using extensions::Extension;
+
+namespace task_manager {
+
+class PanelResource : public RendererResource {
+ public:
+  explicit PanelResource(Panel* panel);
+  virtual ~PanelResource();
+
+  // Resource methods:
+  virtual Type GetType() const OVERRIDE;
+  virtual base::string16 GetTitle() const OVERRIDE;
+  virtual gfx::ImageSkia GetIcon() const OVERRIDE;
+  virtual content::WebContents* GetWebContents() const OVERRIDE;
+
+ private:
+  Panel* panel_;
+  // Determines prefix for title reflecting whether extensions are apps
+  // or in incognito mode.
+  int message_prefix_id_;
+
+  DISALLOW_COPY_AND_ASSIGN(PanelResource);
+};
+
+PanelResource::PanelResource(Panel* panel)
+    : RendererResource(
+        panel->GetWebContents()->GetRenderProcessHost()->GetHandle(),
+        panel->GetWebContents()->GetRenderViewHost()),
+      panel_(panel) {
+  ExtensionService* service = panel_->profile()->GetExtensionService();
+  message_prefix_id_ = util::GetMessagePrefixID(
+      service->extensions()->GetByID(panel_->extension_id())->is_app(),
+      true,  // is_extension
+      panel_->profile()->IsOffTheRecord(),
+      false,   // is_prerender
+      false);  // is_background
+}
+
+PanelResource::~PanelResource() {
+}
+
+Resource::Type PanelResource::GetType() const {
+  return EXTENSION;
+}
+
+base::string16 PanelResource::GetTitle() const {
+  base::string16 title = panel_->GetWindowTitle();
+  // Since the title will be concatenated with an IDS_TASK_MANAGER_* prefix
+  // we need to explicitly set the title to be LTR format if there is no
+  // strong RTL charater in it. Otherwise, if the task manager prefix is an
+  // RTL word, the concatenated result might be wrong. For example,
+  // a page whose title is "Yahoo! Mail: The best web-based Email!", without
+  // setting it explicitly as LTR format, the concatenated result will be
+  // "!Yahoo! Mail: The best web-based Email :PPA", in which the capital
+  // letters "PPA" stands for the Hebrew word for "app".
+  base::i18n::AdjustStringForLocaleDirection(&title);
+
+  return l10n_util::GetStringFUTF16(message_prefix_id_, title);
+}
+
+gfx::ImageSkia PanelResource::GetIcon() const {
+  gfx::Image icon = panel_->GetCurrentPageIcon();
+  return icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia();
+}
+
+WebContents* PanelResource::GetWebContents() const {
+  return panel_->GetWebContents();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// PanelInformation class
+////////////////////////////////////////////////////////////////////////////////
+
+PanelInformation::PanelInformation() {}
+
+PanelInformation::~PanelInformation() {}
+
+bool PanelInformation::CheckOwnership(WebContents* web_contents) {
+  std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
+  for (size_t i = 0; i < panels.size(); ++i) {
+    if (panels[i]->GetWebContents() == web_contents) {
+      return true;
+    }
+  }
+  return false;
+}
+
+void PanelInformation::GetAll(const NewWebContentsCallback& callback) {
+  // Add all the Panels.
+  std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
+  for (size_t i = 0; i < panels.size(); ++i)
+    callback.Run(panels[i]->GetWebContents());
+}
+
+scoped_ptr<RendererResource> PanelInformation::MakeResource(
+    WebContents* web_contents) {
+  std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
+  for (size_t i = 0; i < panels.size(); ++i) {
+    if (panels[i]->GetWebContents() == web_contents) {
+      return scoped_ptr<RendererResource>(new PanelResource(panels[i]));
+    }
+  }
+  NOTREACHED();
+  return scoped_ptr<RendererResource>();
+}
+
+}  // namespace task_manager
diff --git a/chrome/browser/task_manager/panel_information.h b/chrome/browser/task_manager/panel_information.h
new file mode 100644
index 0000000..5c84bfd
--- /dev/null
+++ b/chrome/browser/task_manager/panel_information.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TASK_MANAGER_PANEL_INFORMATION_H_
+#define CHROME_BROWSER_TASK_MANAGER_PANEL_INFORMATION_H_
+
+#include "base/basictypes.h"
+#include "chrome/browser/task_manager/web_contents_information.h"
+
+namespace task_manager {
+
+class PanelResource;
+
+// WebContentsInformation for WebContents instances owned by the PanelManager.
+class PanelInformation : public NotificationObservingWebContentsInformation {
+ public:
+  PanelInformation();
+  virtual ~PanelInformation();
+
+  // WebContentsInformation implementation.
+  virtual bool CheckOwnership(content::WebContents* web_contents) OVERRIDE;
+  virtual void GetAll(const NewWebContentsCallback& callback) OVERRIDE;
+  virtual scoped_ptr<RendererResource> MakeResource(
+      content::WebContents* web_contents) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(PanelInformation);
+};
+
+}  // namespace task_manager
+
+#endif  // CHROME_BROWSER_TASK_MANAGER_PANEL_INFORMATION_H_
diff --git a/chrome/browser/task_manager/panel_resource_provider.cc b/chrome/browser/task_manager/panel_resource_provider.cc
deleted file mode 100644
index 96e3d58..0000000
--- a/chrome/browser/task_manager/panel_resource_provider.cc
+++ /dev/null
@@ -1,231 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/task_manager/panel_resource_provider.h"
-
-#include "base/i18n/rtl.h"
-#include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/extensions/extension_service.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/task_manager/renderer_resource.h"
-#include "chrome/browser/task_manager/resource_provider.h"
-#include "chrome/browser/task_manager/task_manager.h"
-#include "chrome/browser/task_manager/task_manager_util.h"
-#include "chrome/browser/ui/panels/panel.h"
-#include "chrome/browser/ui/panels/panel_manager.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/browser/view_type_utils.h"
-#include "extensions/common/extension.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using content::RenderProcessHost;
-using content::RenderViewHost;
-using content::WebContents;
-using extensions::Extension;
-
-namespace task_manager {
-
-class PanelResource : public RendererResource {
- public:
-  explicit PanelResource(Panel* panel);
-  virtual ~PanelResource();
-
-  // Resource methods:
-  virtual Type GetType() const OVERRIDE;
-  virtual base::string16 GetTitle() const OVERRIDE;
-  virtual gfx::ImageSkia GetIcon() const OVERRIDE;
-  virtual content::WebContents* GetWebContents() const OVERRIDE;
-
- private:
-  Panel* panel_;
-  // Determines prefix for title reflecting whether extensions are apps
-  // or in incognito mode.
-  int message_prefix_id_;
-
-  DISALLOW_COPY_AND_ASSIGN(PanelResource);
-};
-
-PanelResource::PanelResource(Panel* panel)
-    : RendererResource(
-        panel->GetWebContents()->GetRenderProcessHost()->GetHandle(),
-        panel->GetWebContents()->GetRenderViewHost()),
-      panel_(panel) {
-  ExtensionService* service = panel_->profile()->GetExtensionService();
-  message_prefix_id_ = util::GetMessagePrefixID(
-      service->extensions()->GetByID(panel_->extension_id())->is_app(),
-      true,  // is_extension
-      panel_->profile()->IsOffTheRecord(),
-      false,   // is_prerender
-      false);  // is_background
-}
-
-PanelResource::~PanelResource() {
-}
-
-Resource::Type PanelResource::GetType() const {
-  return EXTENSION;
-}
-
-base::string16 PanelResource::GetTitle() const {
-  base::string16 title = panel_->GetWindowTitle();
-  // Since the title will be concatenated with an IDS_TASK_MANAGER_* prefix
-  // we need to explicitly set the title to be LTR format if there is no
-  // strong RTL charater in it. Otherwise, if the task manager prefix is an
-  // RTL word, the concatenated result might be wrong. For example,
-  // a page whose title is "Yahoo! Mail: The best web-based Email!", without
-  // setting it explicitly as LTR format, the concatenated result will be
-  // "!Yahoo! Mail: The best web-based Email :PPA", in which the capital
-  // letters "PPA" stands for the Hebrew word for "app".
-  base::i18n::AdjustStringForLocaleDirection(&title);
-
-  return l10n_util::GetStringFUTF16(message_prefix_id_, title);
-}
-
-gfx::ImageSkia PanelResource::GetIcon() const {
-  gfx::Image icon = panel_->GetCurrentPageIcon();
-  return icon.IsEmpty() ? gfx::ImageSkia() : *icon.ToImageSkia();
-}
-
-WebContents* PanelResource::GetWebContents() const {
-  return panel_->GetWebContents();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// PanelResourceProvider class
-////////////////////////////////////////////////////////////////////////////////
-
-PanelResourceProvider::PanelResourceProvider(TaskManager* task_manager)
-    : updating_(false),
-      task_manager_(task_manager) {
-}
-
-PanelResourceProvider::~PanelResourceProvider() {
-}
-
-Resource* PanelResourceProvider::GetResource(
-    int origin_pid,
-    int child_id,
-    int route_id) {
-  // If an origin PID was specified, the request is from a plugin, not the
-  // render view host process
-  if (origin_pid)
-    return NULL;
-
-  content::RenderFrameHost* rfh =
-      content::RenderFrameHost::FromID(child_id, route_id);
-  content::WebContents* web_contents =
-      content::WebContents::FromRenderFrameHost(rfh);
-
-  for (PanelResourceMap::iterator i = resources_.begin();
-       i != resources_.end(); ++i) {
-    if (web_contents == i->first->GetWebContents())
-      return i->second;
-  }
-
-  // Can happen if the panel went away while a network request was being
-  // performed.
-  return NULL;
-}
-
-void PanelResourceProvider::StartUpdating() {
-  DCHECK(!updating_);
-  updating_ = true;
-
-  // Add all the Panels.
-  std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
-  for (size_t i = 0; i < panels.size(); ++i)
-    Add(panels[i]);
-
-  // Then we register for notifications to get new and remove closed panels.
-  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
-                 content::NotificationService::AllSources());
-  registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
-                 content::NotificationService::AllSources());
-}
-
-void PanelResourceProvider::StopUpdating() {
-  DCHECK(updating_);
-  updating_ = false;
-
-  // Unregister for notifications about new/removed panels.
-  registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
-                    content::NotificationService::AllSources());
-  registrar_.Remove(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
-                    content::NotificationService::AllSources());
-
-  // Delete all the resources.
-  STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end());
-  resources_.clear();
-}
-
-void PanelResourceProvider::Add(Panel* panel) {
-  if (!updating_)
-    return;
-
-  PanelResourceMap::const_iterator iter = resources_.find(panel);
-  if (iter != resources_.end())
-    return;
-
-  PanelResource* resource = new PanelResource(panel);
-  resources_[panel] = resource;
-  task_manager_->AddResource(resource);
-}
-
-void PanelResourceProvider::Remove(Panel* panel) {
-  if (!updating_)
-    return;
-
-  PanelResourceMap::iterator iter = resources_.find(panel);
-  if (iter == resources_.end())
-    return;
-
-  PanelResource* resource = iter->second;
-  task_manager_->RemoveResource(resource);
-  resources_.erase(iter);
-  delete resource;
-}
-
-void PanelResourceProvider::Observe(int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  WebContents* web_contents = content::Source<WebContents>(source).ptr();
-  if (extensions::GetViewType(web_contents) != extensions::VIEW_TYPE_PANEL)
-    return;
-
-  switch (type) {
-    case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
-    {
-      std::vector<Panel*>panels = PanelManager::GetInstance()->panels();
-      for (size_t i = 0; i < panels.size(); ++i) {
-        if (panels[i]->GetWebContents() == web_contents) {
-          Add(panels[i]);
-          break;
-        }
-      }
-      break;
-    }
-    case content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED:
-    {
-      for (PanelResourceMap::iterator iter = resources_.begin();
-           iter != resources_.end(); ++iter) {
-        Panel* panel = iter->first;
-        WebContents* panel_contents = panel->GetWebContents();
-        if (!panel_contents || panel_contents == web_contents) {
-          Remove(panel);
-          break;
-        }
-      }
-      break;
-    }
-    default:
-      NOTREACHED() << "Unexpected notificiation.";
-      break;
-  }
-}
-
-}  // namespace task_manager
diff --git a/chrome/browser/task_manager/panel_resource_provider.h b/chrome/browser/task_manager/panel_resource_provider.h
deleted file mode 100644
index 2c7a669..0000000
--- a/chrome/browser/task_manager/panel_resource_provider.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_TASK_MANAGER_PANEL_RESOURCE_PROVIDER_H_
-#define CHROME_BROWSER_TASK_MANAGER_PANEL_RESOURCE_PROVIDER_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/strings/string16.h"
-#include "chrome/browser/task_manager/resource_provider.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "ui/gfx/image/image_skia.h"
-
-class Panel;
-class TaskManager;
-
-namespace task_manager {
-
-class PanelResource;
-
-class PanelResourceProvider : public ResourceProvider,
-                              public content::NotificationObserver {
- public:
-  explicit PanelResourceProvider(TaskManager* task_manager);
-
-  // ResourceProvider methods:
-  virtual Resource* GetResource(int origin_pid,
-                                int child_id,
-                                int route_id) OVERRIDE;
-  virtual void StartUpdating() OVERRIDE;
-  virtual void StopUpdating() OVERRIDE;
-
-  // content::NotificationObserver method:
-  virtual void Observe(int type,
-                       const content::NotificationSource& source,
-                       const content::NotificationDetails& details) OVERRIDE;
-
- private:
-  virtual ~PanelResourceProvider();
-
-  void Add(Panel* panel);
-  void Remove(Panel* panel);
-
-  // Whether we are currently reporting to the task manager. Used to ignore
-  // notifications sent after StopUpdating().
-  bool updating_;
-
-  TaskManager* task_manager_;
-
-  // Maps the actual resources (the Panels) to the Task Manager resources.
-  typedef std::map<Panel*, PanelResource*> PanelResourceMap;
-  PanelResourceMap resources_;
-
-  // A scoped container for notification registries.
-  content::NotificationRegistrar registrar_;
-
-  DISALLOW_COPY_AND_ASSIGN(PanelResourceProvider);
-};
-
-}  // namespace task_manager
-
-#endif  // CHROME_BROWSER_TASK_MANAGER_PANEL_RESOURCE_PROVIDER_H_
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index e876bcf..a66851b 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -17,14 +17,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/task_manager/background_resource_provider.h"
+#include "chrome/browser/task_manager/background_information.h"
 #include "chrome/browser/task_manager/browser_process_resource_provider.h"
 #include "chrome/browser/task_manager/child_process_resource_provider.h"
 #include "chrome/browser/task_manager/extension_process_resource_provider.h"
-#include "chrome/browser/task_manager/guest_resource_provider.h"
-#include "chrome/browser/task_manager/panel_resource_provider.h"
+#include "chrome/browser/task_manager/guest_information.h"
+#include "chrome/browser/task_manager/panel_information.h"
 #include "chrome/browser/task_manager/resource_provider.h"
 #include "chrome/browser/task_manager/tab_contents_resource_provider.h"
+#include "chrome/browser/task_manager/web_contents_resource_provider.h"
 #include "chrome/browser/task_manager/worker_resource_provider.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/common/pref_names.h"
@@ -58,6 +59,7 @@
 using content::WebContents;
 using task_manager::Resource;
 using task_manager::ResourceProvider;
+using task_manager::WebContentsInformation;
 
 class Profile;
 
@@ -246,16 +248,24 @@
       goat_salt_(base::RandUint64()) {
   AddResourceProvider(
       new task_manager::BrowserProcessResourceProvider(task_manager));
-  AddResourceProvider(
-      new task_manager::BackgroundContentsResourceProvider(task_manager));
+  AddResourceProvider(new task_manager::WebContentsResourceProvider(
+      task_manager,
+      scoped_ptr<WebContentsInformation>(
+          new task_manager::BackgroundInformation())));
   AddResourceProvider(
       new task_manager::TabContentsResourceProvider(task_manager));
-  AddResourceProvider(new task_manager::PanelResourceProvider(task_manager));
+  AddResourceProvider(new task_manager::WebContentsResourceProvider(
+      task_manager,
+      scoped_ptr<WebContentsInformation>(
+          new task_manager::PanelInformation())));
   AddResourceProvider(
       new task_manager::ChildProcessResourceProvider(task_manager));
   AddResourceProvider(
       new task_manager::ExtensionProcessResourceProvider(task_manager));
-  AddResourceProvider(new task_manager::GuestResourceProvider(task_manager));
+  AddResourceProvider(new task_manager::WebContentsResourceProvider(
+      task_manager,
+      scoped_ptr<WebContentsInformation>(
+          new task_manager::GuestInformation())));
 
 #if !defined(OS_CHROMEOS) && defined(ENABLE_NOTIFICATIONS)
   ResourceProvider* provider =
@@ -890,6 +900,10 @@
       return ValueCompare(current1, current2);
     }
 
+    case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN:
+      return ValueCompare(GetIdleWakeupsPerSecond(row1),
+                          GetIdleWakeupsPerSecond(row2));
+
     case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
     case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
     case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: {
diff --git a/chrome/browser/task_manager/task_manager_notification_browsertest.cc b/chrome/browser/task_manager/task_manager_notification_browsertest.cc
index 89ad198..d9d1217 100644
--- a/chrome/browser/task_manager/task_manager_notification_browsertest.cc
+++ b/chrome/browser/task_manager/task_manager_notification_browsertest.cc
@@ -43,6 +43,9 @@
 // TODO(linux_aura) http://crbug.com/163931
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA)
 #define MAYBE_NoticeNotificationChanges DISABLED_NoticeNotificationChanges
+// Broken on gtk, see http://crbug.com/355442
+#elif defined(TOOLKIT_GTK)
+#define MAYBE_NoticeNotificationChanges DISABLED_NoticeNotificationChanges
 #else
 #define MAYBE_NoticeNotificationChanges NoticeNotificationChanges
 #endif
diff --git a/chrome/browser/task_manager/web_contents_information.cc b/chrome/browser/task_manager/web_contents_information.cc
new file mode 100644
index 0000000..c82cd16
--- /dev/null
+++ b/chrome/browser/task_manager/web_contents_information.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_manager/web_contents_information.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+
+namespace task_manager {
+
+WebContentsInformation::WebContentsInformation() {}
+
+WebContentsInformation::~WebContentsInformation() {}
+
+NotificationObservingWebContentsInformation::
+    NotificationObservingWebContentsInformation() {}
+
+NotificationObservingWebContentsInformation::
+    ~NotificationObservingWebContentsInformation() {}
+
+void NotificationObservingWebContentsInformation::StartObservingCreation(
+    const NewWebContentsCallback& callback) {
+  observer_callback_ = callback;
+  registrar_.Add(this,
+                 content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
+                 content::NotificationService::AllBrowserContextsAndSources());
+}
+
+void NotificationObservingWebContentsInformation::StopObservingCreation() {
+  registrar_.Remove(
+      this,
+      content::NOTIFICATION_WEB_CONTENTS_CONNECTED,
+      content::NotificationService::AllBrowserContextsAndSources());
+  observer_callback_.Reset();
+}
+
+void NotificationObservingWebContentsInformation::Observe(
+    int type,
+    const content::NotificationSource& source,
+    const content::NotificationDetails& details) {
+  content::WebContents* web_contents =
+      content::Source<content::WebContents>(source).ptr();
+
+  switch (type) {
+    case content::NOTIFICATION_WEB_CONTENTS_CONNECTED:
+      if (CheckOwnership(web_contents))
+        observer_callback_.Run(web_contents);
+      break;
+  }
+}
+
+}  // namespace task_manager
diff --git a/chrome/browser/task_manager/web_contents_information.h b/chrome/browser/task_manager/web_contents_information.h
new file mode 100644
index 0000000..bce0551
--- /dev/null
+++ b/chrome/browser/task_manager/web_contents_information.h
@@ -0,0 +1,84 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_INFORMATION_H_
+#define CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_INFORMATION_H_
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace task_manager {
+
+class RendererResource;
+
+// This interface gives a WebContentsResourceProvider information about a
+// category of WebContentses owned by some service. The instances are expected
+// to be owned by their WebContentsResourceProvider, which will track and adapt
+// the WebContentses into TaskManager resources.
+class WebContentsInformation {
+ public:
+  typedef base::Callback<void(content::WebContents*)> NewWebContentsCallback;
+
+  WebContentsInformation();
+  virtual ~WebContentsInformation();
+
+  // Retrieve all known WebContents instances from the service we're tracking.
+  // Invoke |callback| on each one.
+  virtual void GetAll(const NewWebContentsCallback& callback) = 0;
+
+  // Return true if |web_contents| is from the service we're tracking.
+  virtual bool CheckOwnership(content::WebContents* web_contents) = 0;
+
+  // Start listening to the creation of new WebContents instances from
+  // the service. While listening, invoke |callback| on each new instance.
+  virtual void StartObservingCreation(
+      const NewWebContentsCallback& callback) = 0;
+
+  // Stop listening to creation of new WebContents instances.
+  virtual void StopObservingCreation() = 0;
+
+  // Create a new task manager resource for the given WebContents instance.
+  virtual scoped_ptr<RendererResource> MakeResource(
+      content::WebContents* web_contents) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(WebContentsInformation);
+};
+
+// Implements the observer methods (StartObservingCreation() /
+// StopObservingCreation()) of WebContentsInformation using
+// NOTIFICATION_WEB_CONTENTS_CONNECTED.
+class NotificationObservingWebContentsInformation
+    : public WebContentsInformation,
+      public content::NotificationObserver {
+ public:
+  NotificationObservingWebContentsInformation();
+  virtual ~NotificationObservingWebContentsInformation();
+
+  // WebContentsInformation partial implementation.
+  virtual void StartObservingCreation(const NewWebContentsCallback& callback)
+      OVERRIDE;
+  virtual void StopObservingCreation() OVERRIDE;
+
+  // content::NotificationObserver implementation.
+  virtual void Observe(int type,
+                       const content::NotificationSource& source,
+                       const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+  content::NotificationRegistrar registrar_;
+  NewWebContentsCallback observer_callback_;
+  DISALLOW_COPY_AND_ASSIGN(NotificationObservingWebContentsInformation);
+};
+
+}  // namespace task_manager
+
+#endif  // CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_INFORMATION_H_
diff --git a/chrome/browser/task_manager/web_contents_resource_provider.cc b/chrome/browser/task_manager/web_contents_resource_provider.cc
new file mode 100644
index 0000000..4b19090
--- /dev/null
+++ b/chrome/browser/task_manager/web_contents_resource_provider.cc
@@ -0,0 +1,186 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/task_manager/web_contents_resource_provider.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/prerender/prerender_manager.h"
+#include "chrome/browser/prerender/prerender_manager_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/task_manager/renderer_resource.h"
+#include "chrome/browser/task_manager/task_manager.h"
+#include "chrome/browser/task_manager/task_manager_util.h"
+#include "chrome/browser/task_manager/web_contents_information.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_iterator.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+
+using content::WebContents;
+using content::RenderViewHost;
+
+namespace task_manager {
+
+// A WebContentsObserver that tracks changes to a WebContents on behalf of
+// a WebContentsResourceProvider.
+class TaskManagerWebContentsObserver : public content::WebContentsObserver {
+ public:
+  TaskManagerWebContentsObserver(WebContents* web_contents,
+                                 WebContentsResourceProvider* provider)
+      : content::WebContentsObserver(web_contents), provider_(provider) {}
+
+  // content::WebContentsObserver implementation.
+  virtual void RenderViewHostChanged(RenderViewHost* old_host,
+                                     RenderViewHost* new_host) OVERRIDE {
+    provider_->RemoveFromTaskManager(web_contents());
+    provider_->AddToTaskManager(web_contents());
+  }
+
+  virtual void WebContentsDestroyed(WebContents* web_contents) OVERRIDE {
+    provider_->RemoveFromTaskManager(web_contents);
+    provider_->DeleteObserver(this);  // Deletes |this|.
+  }
+
+ private:
+  WebContentsResourceProvider* provider_;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// WebContentsResourceProvider class
+////////////////////////////////////////////////////////////////////////////////
+
+WebContentsResourceProvider::WebContentsResourceProvider(
+    TaskManager* task_manager,
+    scoped_ptr<WebContentsInformation> info)
+    : updating_(false), task_manager_(task_manager), info_(info.Pass()) {}
+
+WebContentsResourceProvider::~WebContentsResourceProvider() {}
+
+RendererResource* WebContentsResourceProvider::GetResource(int origin_pid,
+                                                           int child_id,
+                                                           int route_id) {
+  content::RenderFrameHost* rfh =
+      content::RenderFrameHost::FromID(child_id, route_id);
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(rfh);
+
+  // If an origin PID was specified then the request originated in a plugin
+  // working on the WebContents's behalf, so ignore it.
+  if (origin_pid)
+    return NULL;
+
+  std::map<WebContents*, RendererResource*>::iterator res_iter =
+      resources_.find(web_contents);
+
+  if (res_iter == resources_.end()) {
+    // Can happen if the tab was closed while a network request was being
+    // performed.
+    return NULL;
+  }
+  return res_iter->second;
+}
+
+void WebContentsResourceProvider::StartUpdating() {
+  DCHECK(!updating_);
+  updating_ = true;
+
+  WebContentsInformation::NewWebContentsCallback new_web_contents_callback =
+      base::Bind(&WebContentsResourceProvider::OnWebContentsCreated, this);
+  info_->GetAll(new_web_contents_callback);
+  info_->StartObservingCreation(new_web_contents_callback);
+}
+
+void WebContentsResourceProvider::StopUpdating() {
+  DCHECK(updating_);
+  updating_ = false;
+
+  info_->StopObservingCreation();
+
+  // Delete all observers; this dissassociates them from the WebContents too.
+  STLDeleteElements(&web_contents_observers_);
+  web_contents_observers_.clear();
+
+  // Delete all resources. We don't need to remove them from the TaskManager,
+  // because it's the TaskManager that's asking us to StopUpdating().
+  STLDeleteValues(&resources_);
+  resources_.clear();
+}
+
+void WebContentsResourceProvider::OnWebContentsCreated(
+    WebContents* web_contents) {
+  // Don't add dead tabs or tabs that haven't yet connected.
+  if (!web_contents->GetRenderProcessHost()->GetHandle() ||
+      !web_contents->WillNotifyDisconnection()) {
+    return;
+  }
+
+  DCHECK(info_->CheckOwnership(web_contents));
+  if (AddToTaskManager(web_contents)) {
+    web_contents_observers_.insert(
+        new TaskManagerWebContentsObserver(web_contents, this));
+  }
+}
+
+bool WebContentsResourceProvider::AddToTaskManager(WebContents* web_contents) {
+  if (!updating_)
+    return false;
+
+  if (resources_.count(web_contents)) {
+    // The case may happen that we have added a WebContents as part of the
+    // iteration performed during StartUpdating() call but the notification that
+    // it has connected was not fired yet. So when the notification happens, we
+    // are already observing this WebContents and just ignore it.
+    return false;
+  }
+
+  // TODO(nick): If the RenderView is not live, then do we still want to install
+  // the WebContentsObserver? Only some of the original ResourceProviders
+  // had that check.
+  scoped_ptr<RendererResource> resource = info_->MakeResource(web_contents);
+  if (!resource)
+    return false;
+
+  task_manager_->AddResource(resource.get());
+  resources_[web_contents] = resource.release();
+  return true;
+}
+
+void WebContentsResourceProvider::RemoveFromTaskManager(
+    WebContents* web_contents) {
+  if (!updating_)
+    return;
+
+  std::map<WebContents*, RendererResource*>::iterator resource_iter =
+      resources_.find(web_contents);
+
+  if (resource_iter == resources_.end()) {
+    return;
+  }
+
+  RendererResource* resource = resource_iter->second;
+  task_manager_->RemoveResource(resource);
+
+  // Remove the resource from the Task Manager.
+  // And from the provider.
+  resources_.erase(resource_iter);
+
+  // Finally, delete the resource.
+  delete resource;
+}
+
+void WebContentsResourceProvider::DeleteObserver(
+    TaskManagerWebContentsObserver* observer) {
+  if (!web_contents_observers_.erase(observer)) {
+    NOTREACHED();
+    return;
+  }
+  delete observer;  // Typically, this is our caller. Deletion is okay.
+}
+
+}  // namespace task_manager
diff --git a/chrome/browser/task_manager/web_contents_resource_provider.h b/chrome/browser/task_manager/web_contents_resource_provider.h
new file mode 100644
index 0000000..b07e211
--- /dev/null
+++ b/chrome/browser/task_manager/web_contents_resource_provider.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_RESOURCE_PROVIDER_H_
+#define CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_RESOURCE_PROVIDER_H_
+
+#include <map>
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/task_manager/renderer_resource.h"
+#include "chrome/browser/task_manager/resource_provider.h"
+
+class TaskManager;
+
+namespace content {
+class WebContents;
+}
+
+namespace task_manager {
+
+class RendererResource;
+class TaskManagerWebContentsObserver;
+class WebContentsInformation;
+
+// Provides resources to the task manager on behalf of a chrome service that
+// owns WebContentses. The chrome service is parameterized as a
+// WebContentsInformation, which provides a list of WebContentses to track.
+//
+// This ResourceProvider is instantiated several times by the task manager, each
+// with a different implementation of WebContentsInformation.
+class WebContentsResourceProvider : public ResourceProvider {
+ public:
+  WebContentsResourceProvider(TaskManager* task_manager,
+                              scoped_ptr<WebContentsInformation> info);
+
+  // ResourceProvider implementation.
+  virtual RendererResource* GetResource(int origin_pid,
+                                        int child_id,
+                                        int route_id) OVERRIDE;
+  virtual void StartUpdating() OVERRIDE;
+  virtual void StopUpdating() OVERRIDE;
+
+  // Start observing |web_contents| for changes via WebContentsObserver, and
+  // add it to the task manager.
+  void OnWebContentsCreated(content::WebContents* web_contents);
+
+  // Create TaskManager resources for |web_contents|, and add them to the
+  // TaskManager.
+  bool AddToTaskManager(content::WebContents* web_contents);
+
+  // Remove the task manager resources associated with |web_contents|.
+  void RemoveFromTaskManager(content::WebContents* web_contents);
+
+  // Remove a WebContentsObserver from our tracking list, and delete it.
+  void DeleteObserver(TaskManagerWebContentsObserver* observer);
+
+ protected:
+  virtual ~WebContentsResourceProvider();
+
+ private:
+  // Whether we are currently reporting to the task manager. Used to ignore
+  // notifications sent after StopUpdating().
+  bool updating_;
+
+  TaskManager* task_manager_;
+
+  // Maps the actual resources (the WebContentses) to the TaskManager
+  // resources. The RendererResources are owned by us and registered with
+  // the TaskManager.
+  std::map<content::WebContents*, RendererResource*> resources_;
+
+  // Set of current active WebContentsObserver instances owned by this class.
+  std::set<TaskManagerWebContentsObserver*> web_contents_observers_;
+
+  // The WebContentsInformation that informs us when a new WebContents* is
+  // created, and which serves as a RendererResource factory for our type.
+  scoped_ptr<WebContentsInformation> info_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebContentsResourceProvider);
+};
+
+}  // namespace task_manager
+
+#endif  // CHROME_BROWSER_TASK_MANAGER_WEB_CONTENTS_RESOURCE_PROVIDER_H_
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 82f24b3..2603efa 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -6,6 +6,7 @@
 
 #include <limits>
 
+#include "base/files/file.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/stl_util.h"
@@ -21,8 +22,6 @@
 #include "extensions/common/id_util.h"
 #include "grit/theme_resources.h"
 #include "grit/ui_resources.h"
-#include "net/base/file_stream.h"
-#include "net/base/net_errors.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/base/resource/data_pack.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -418,16 +417,15 @@
 // Returns a piece of memory with the contents of the file |path|.
 base::RefCountedMemory* ReadFileData(const base::FilePath& path) {
   if (!path.empty()) {
-    net::FileStream file(NULL);
-    int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
-    if (file.OpenSync(path, flags) == net::OK) {
-      int64 avail = file.Available();
-      if (avail > 0 && avail < INT_MAX) {
-        size_t size = static_cast<size_t>(avail);
+    base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+    if (file.IsValid()) {
+      int64 length = file.GetLength();
+      if (length > 0 && length < INT_MAX) {
+        int size = static_cast<int>(length);
         std::vector<unsigned char> raw_data;
         raw_data.resize(size);
         char* data = reinterpret_cast<char*>(&(raw_data.front()));
-        if (file.ReadUntilComplete(data, size) == avail)
+        if (file.ReadAtCurrentPos(data, size) == length)
           return base::RefCountedBytes::TakeVector(&raw_data);
       }
     }
diff --git a/chrome/browser/three_d_api_observer.cc b/chrome/browser/three_d_api_observer.cc
index 582da93..94d3b38 100644
--- a/chrome/browser/three_d_api_observer.cc
+++ b/chrome/browser/three_d_api_observer.cc
@@ -11,6 +11,7 @@
 #include "chrome/browser/tab_contents/tab_util.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
 
@@ -37,7 +38,7 @@
 
   // ConfirmInfoBarDelegate:
   virtual bool EqualsDelegate(InfoBarDelegate* delegate) const OVERRIDE;
-  virtual ThreeDAPIInfoBarDelegate* AsThreeDAPIInfoBarDelegate() OVERRIDE;
+  virtual int GetIconID() const OVERRIDE;
   virtual base::string16 GetMessageText() const OVERRIDE;
   virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
   virtual bool Accept() OVERRIDE;
@@ -88,12 +89,11 @@
   // WebGL and Pepper 3D and both APIs are blocked, just leave the
   // first infobar up. If the user selects "try again", both APIs will
   // be unblocked and the web page reload will succeed.
-  return (delegate->AsThreeDAPIInfoBarDelegate() != NULL);
+  return delegate->GetIconID() == GetIconID();
 }
 
-ThreeDAPIInfoBarDelegate*
-    ThreeDAPIInfoBarDelegate::AsThreeDAPIInfoBarDelegate() {
-  return this;
+int ThreeDAPIInfoBarDelegate::GetIconID() const {
+  return IDR_INFOBAR_3D_BLOCKED;
 }
 
 base::string16 ThreeDAPIInfoBarDelegate::GetMessageText() const {
diff --git a/chrome/browser/translate/translate_manager.cc b/chrome/browser/translate/translate_manager.cc
index b5b11f4..9442f10 100644
--- a/chrome/browser/translate/translate_manager.cc
+++ b/chrome/browser/translate/translate_manager.cc
@@ -13,7 +13,6 @@
 #include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/translate/translate_tab_helper.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -25,6 +24,7 @@
 #include "components/translate/core/browser/page_translated_details.h"
 #include "components/translate/core/browser/translate_accept_languages.h"
 #include "components/translate/core/browser/translate_browser_metrics.h"
+#include "components/translate/core/browser/translate_client.h"
 #include "components/translate/core/browser/translate_download_manager.h"
 #include "components/translate/core/browser/translate_driver.h"
 #include "components/translate/core/browser/translate_error_details.h"
@@ -216,7 +216,8 @@
     : max_reload_check_attempts_(kMaxTranslateLoadCheckAttempts),
       accept_languages_pref_name_(accept_languages_pref_name),
       translate_tab_helper_(helper),
-      translate_driver_(helper->GetTranslateDriver()),
+      translate_client_(helper),
+      translate_driver_(translate_client_->GetTranslateDriver()),
       weak_method_factory_(this) {
 
   WebContents* web_contents = translate_tab_helper_->GetWebContents();
@@ -233,12 +234,7 @@
 }
 
 void TranslateManager::InitiateTranslation(const std::string& page_lang) {
-  WebContents* web_contents = translate_tab_helper_->GetWebContents();
-  DCHECK(web_contents);
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  Profile* original_profile = profile->GetOriginalProfile();
-  PrefService* prefs = original_profile->GetPrefs();
+  PrefService* prefs = translate_client_->GetPrefs();
   if (!prefs->GetBoolean(prefs::kEnableTranslate)) {
     TranslateBrowserMetrics::ReportInitiationStatus(
         TranslateBrowserMetrics::INITIATION_STATUS_DISABLED_BY_PREFS);
@@ -259,6 +255,7 @@
 
   // MHTML pages currently cannot be translated.
   // See bug: 217945.
+  WebContents* web_contents = translate_tab_helper_->GetWebContents();
   if (web_contents->GetContentsMimeType() == "multipart/related") {
     TranslateBrowserMetrics::ReportInitiationStatus(
         TranslateBrowserMetrics::INITIATION_STATUS_MIME_TYPE_IS_NOT_SUPPORTED);
@@ -302,10 +299,10 @@
   }
 
   scoped_ptr<TranslatePrefs> translate_prefs(
-      TranslateTabHelper::CreateTranslatePrefs(profile->GetPrefs()));
+      translate_client_->GetTranslatePrefs());
 
   TranslateAcceptLanguages* accept_languages =
-      TranslateTabHelper::GetTranslateAcceptLanguages(profile);
+      translate_client_->GetTranslateAcceptLanguages();
   // Don't translate any user black-listed languages.
   if (!translate_prefs->CanTranslateLanguage(accept_languages,
                                              language_code)) {
diff --git a/chrome/browser/translate/translate_manager.h b/chrome/browser/translate/translate_manager.h
index f77d9f4..fc57637 100644
--- a/chrome/browser/translate/translate_manager.h
+++ b/chrome/browser/translate/translate_manager.h
@@ -19,6 +19,7 @@
 class GURL;
 struct PageTranslatedDetails;
 class PrefService;
+class TranslateClient;
 class TranslateDriver;
 struct TranslateErrorDetails;
 class TranslateTabHelper;
@@ -129,6 +130,7 @@
   // TODO(droger): Remove all uses of |translate_tab_helper_|, use
   // TranslateClient and TranslateDriver instead.
   TranslateTabHelper* translate_tab_helper_;  // Weak.
+  TranslateClient* translate_client_;         // Weak.
   TranslateDriver* translate_driver_;  // Weak.
 
   base::WeakPtrFactory<TranslateManager> weak_method_factory_;
diff --git a/chrome/browser/translate/translate_tab_helper.cc b/chrome/browser/translate/translate_tab_helper.cc
index 8cf93f3..0e5bd18 100644
--- a/chrome/browser/translate/translate_tab_helper.cc
+++ b/chrome/browser/translate/translate_tab_helper.cc
@@ -4,7 +4,17 @@
 
 #include "chrome/browser/translate/translate_tab_helper.h"
 
+#if defined(CLD2_DYNAMIC_MODE)
+#include "base/basictypes.h"
+#include "base/lazy_instance.h"
+#endif
 #include "base/logging.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "base/path_service.h"
+#include "base/platform_file.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
+#endif
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/translate/translate_accept_languages_factory.h"
@@ -16,19 +26,42 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/translate/translate_bubble_factory.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "chrome/common/chrome_paths.h"
+#endif
 #include "chrome/common/pref_names.h"
 #include "chrome/common/render_messages.h"
 #include "components/translate/core/browser/page_translated_details.h"
 #include "components/translate/core/browser/translate_accept_languages.h"
 #include "components/translate/core/browser/translate_prefs.h"
 #include "components/translate/core/common/language_detection_details.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "content/public/browser/browser_thread.h"
+#endif
 #include "content/public/browser/notification_service.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
+#endif
 #include "content/public/browser/web_contents.h"
 
 DEFINE_WEB_CONTENTS_USER_DATA_KEY(TranslateTabHelper);
 
+#if defined(CLD2_DYNAMIC_MODE)
+// Statics defined in the .h file:
+base::PlatformFile TranslateTabHelper::s_cached_platform_file_ =
+    base::kInvalidPlatformFileValue;
+uint64 TranslateTabHelper::s_cached_data_offset_ = 0;
+uint64 TranslateTabHelper::s_cached_data_length_ = 0;
+base::LazyInstance<base::Lock> TranslateTabHelper::s_file_lock_ =
+    LAZY_INSTANCE_INITIALIZER;
+#endif
+
 TranslateTabHelper::TranslateTabHelper(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
+#if defined(CLD2_DYNAMIC_MODE)
+      weak_pointer_factory_(this),
+#endif
       translate_driver_(&web_contents->GetController()),
       translate_manager_(new TranslateManager(this, prefs::kAcceptLanguages)) {}
 
@@ -113,12 +146,34 @@
   return &translate_driver_;
 }
 
+PrefService* TranslateTabHelper::GetPrefs() {
+  DCHECK(web_contents());
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+  return profile->GetOriginalProfile()->GetPrefs();
+}
+
+scoped_ptr<TranslatePrefs> TranslateTabHelper::GetTranslatePrefs() {
+  DCHECK(web_contents());
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+  return CreateTranslatePrefs(profile->GetPrefs());
+}
+
+TranslateAcceptLanguages* TranslateTabHelper::GetTranslateAcceptLanguages() {
+  DCHECK(web_contents());
+  return GetTranslateAcceptLanguages(web_contents()->GetBrowserContext());
+}
+
 bool TranslateTabHelper::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(TranslateTabHelper, message)
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_TranslateLanguageDetermined,
                         OnLanguageDetermined)
     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_PageTranslated, OnPageTranslated)
+#if defined(CLD2_DYNAMIC_MODE)
+    IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NeedCLDData, OnCLDDataRequested)
+#endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -140,6 +195,145 @@
   translate_manager_.reset();
 }
 
+#if defined(CLD2_DYNAMIC_MODE)
+void TranslateTabHelper::OnCLDDataRequested() {
+  // Quickly try to read s_cached_platform_file_. If valid, the file handle is
+  // cached and can be used immediately. Else, queue the caching task to the
+  // blocking pool.
+  base::PlatformFile handle = base::kInvalidPlatformFileValue;
+  uint64 data_offset = 0;
+  uint64 data_length = 0;
+  {
+    base::AutoLock lock(s_file_lock_.Get());
+    handle = s_cached_platform_file_;
+    data_offset = s_cached_data_offset_;
+    data_length = s_cached_data_length_;
+  }
+
+  if (handle != base::kInvalidPlatformFileValue) {
+    // Cached data available. Respond to the request.
+    SendCLDDataAvailable(handle, data_offset, data_length);
+    return;
+  }
+
+  // Else, we don't have the data file yet. Queue a caching attempt.
+  // The caching attempt happens in the blocking pool because it may involve
+  // arbitrary filesystem access.
+  // After the caching attempt is made, we call MaybeSendCLDDataAvailable
+  // to pass the file handle to the renderer. This only results in an IPC
+  // message if the caching attempt was successful.
+  content::BrowserThread::PostBlockingPoolTaskAndReply(
+      FROM_HERE,
+      base::Bind(&TranslateTabHelper::HandleCLDDataRequest),
+      base::Bind(&TranslateTabHelper::MaybeSendCLDDataAvailable,
+                 weak_pointer_factory_.GetWeakPtr()));
+}
+
+void TranslateTabHelper::MaybeSendCLDDataAvailable() {
+  base::PlatformFile handle = base::kInvalidPlatformFileValue;
+  uint64 data_offset = 0;
+  uint64 data_length = 0;
+  {
+    base::AutoLock lock(s_file_lock_.Get());
+    handle = s_cached_platform_file_;
+    data_offset = s_cached_data_offset_;
+    data_length = s_cached_data_length_;
+  }
+
+  if (handle != base::kInvalidPlatformFileValue)
+    SendCLDDataAvailable(handle, data_offset, data_length);
+}
+
+void TranslateTabHelper::SendCLDDataAvailable(const base::PlatformFile handle,
+                                              const uint64 data_offset,
+                                              const uint64 data_length) {
+  // Data available, respond to the request.
+  IPC::PlatformFileForTransit ipc_platform_file =
+      IPC::GetFileHandleForProcess(
+          handle,
+          GetWebContents()->GetRenderViewHost()->GetProcess()->GetHandle(),
+          false);
+  // In general, sending a response from within the code path that is processing
+  // a request is discouraged because there is potential for deadlock (if the
+  // methods are sent synchronously) or loops (if the response can trigger a
+  // new request). Neither of these concerns is relevant in this code, so
+  // sending the response from within the code path of the request handler is
+  // safe.
+  Send(new ChromeViewMsg_CLDDataAvailable(
+      GetWebContents()->GetRenderViewHost()->GetRoutingID(),
+      ipc_platform_file, data_offset, data_length));
+}
+
+void TranslateTabHelper::HandleCLDDataRequest() {
+  // Because this function involves arbitrary file system access, it must run
+  // on the blocking pool.
+  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
+  DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  {
+    base::AutoLock lock(s_file_lock_.Get());
+    if (s_cached_platform_file_ != base::kInvalidPlatformFileValue)
+      return; // Already done, duplicate request
+  }
+
+  base::FilePath path;
+  if (!PathService::Get(chrome::DIR_USER_DATA, &path)) {
+    LOG(WARNING) << "Unable to locate user data directory";
+    return; // Chrome isn't properly installed.
+  }
+
+  // If the file exists, we can send an IPC-safe construct back to the
+  // renderer process immediately.
+  path = path.Append(chrome::kCLDDataFilename);
+  if (!base::PathExists(path))
+    return;
+
+  // Attempt to open the file for reading.
+  bool created = false;
+  base::PlatformFileError error;
+  const base::PlatformFile file = base::CreatePlatformFile(
+      path,
+      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
+      &created, &error);
+  DCHECK(!created);
+  if (error != base::PLATFORM_FILE_OK) {
+    LOG(WARNING) << "CLD data file exists but cannot be opened";
+    return;
+  }
+
+  base::PlatformFileInfo file_info;
+  if (!base::GetPlatformFileInfo(file, &file_info)) {
+    LOG(WARNING) << "CLD data file exists but cannot be inspected";
+    return;
+  }
+
+  // For now, our offset and length are simply 0 and the length of the file,
+  // respectively. If we later decide to include the CLD2 data file inside of
+  // a larger binary context, these params can be twiddled appropriately.
+  const uint64 data_offset = 0;
+  const uint64 data_length = file_info.size;
+
+  bool racing = false;
+  {
+    base::AutoLock lock(s_file_lock_.Get());
+    if (s_cached_platform_file_ != base::kInvalidPlatformFileValue) {
+      // Idempotence: Racing another request on the blocking pool, abort.
+      racing = true;
+    } else {
+      // Else, this request has taken care of it all. Cache all info.
+      s_cached_platform_file_ = file;
+      s_cached_data_offset_ = data_offset;
+      s_cached_data_length_ = data_length;
+    }
+  }
+
+  if (racing) {
+    // Other thread wins, give up the redundant file handle.
+    base::ClosePlatformFile(file);
+  }
+}
+#endif // defined(CLD2_DYNAMIC_MODE)
+
 void TranslateTabHelper::OnLanguageDetermined(
     const LanguageDetectionDetails& details,
     bool page_needs_translation) {
diff --git a/chrome/browser/translate/translate_tab_helper.h b/chrome/browser/translate/translate_tab_helper.h
index c5dd0ff..ae23754 100644
--- a/chrome/browser/translate/translate_tab_helper.h
+++ b/chrome/browser/translate/translate_tab_helper.h
@@ -7,7 +7,17 @@
 
 #include <string>
 
+#if defined(CLD2_DYNAMIC_MODE)
+#include "base/basictypes.h"
+#include "base/lazy_instance.h"
+#endif
 #include "base/memory/scoped_ptr.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "base/memory/weak_ptr.h"
+#include "base/platform_file.h"
+#include "base/synchronization/lock.h"
+#include "base/task_runner.h"
+#endif
 #include "chrome/browser/ui/translate/translate_bubble_model.h"
 #include "components/translate/content/browser/content_translate_driver.h"
 #include "components/translate/core/browser/translate_client.h"
@@ -78,6 +88,9 @@
 
   // TranslateClient implementation.
   virtual TranslateDriver* GetTranslateDriver() OVERRIDE;
+  virtual PrefService* GetPrefs() OVERRIDE;
+  virtual scoped_ptr<TranslatePrefs> GetTranslatePrefs() OVERRIDE;
+  virtual TranslateAcceptLanguages* GetTranslateAcceptLanguages() OVERRIDE;
 
  private:
   explicit TranslateTabHelper(content::WebContents* web_contents);
@@ -98,6 +111,45 @@
                         const std::string& translated_lang,
                         TranslateErrors::Type error_type);
 
+#if defined(CLD2_DYNAMIC_MODE)
+  // Called when we receive ChromeViewHostMsg_NeedCLDData from a renderer.
+  // If we have already cached the data, responds immediately; else, enqueues
+  // a HandleCLDDataRequest on the blocking pool to cache the data.
+  // Acquires and releases s_file_lock_ in a non-blocking manner; queries
+  // handled while the file is being cached will gracefully and immediately
+  // fail.
+  // It is up to the originator of the message to poll again later if required;
+  // no "negative response" will be generated.
+  void OnCLDDataRequested();
+
+  // Invoked on the blocking pool in order to cache the data. When successful,
+  // immediately responds to the request that initiated OnCLDDataRequested.
+  // Holds s_file_lock_ while the file is being cached.
+  static void HandleCLDDataRequest();
+
+  // If the CLD data is ready, send it to the renderer. Briefly checks the lock.
+  void MaybeSendCLDDataAvailable();
+
+  // Sends the renderer a response containing the data file handle. No locking.
+  void SendCLDDataAvailable(const base::PlatformFile handle,
+                            const uint64 data_offset,
+                            const uint64 data_length);
+
+  // Necessary for binding the callback to HandleCLDDataRequest on the blocking
+  // pool.
+  base::WeakPtrFactory<TranslateTabHelper> weak_pointer_factory_;
+
+  // The data file,  cached as long as the process stays alive.
+  // We also track the offset at which the data starts, and its length.
+  static base::PlatformFile s_cached_platform_file_; // guarded by file_lock_
+  static uint64 s_cached_data_offset_; // guarded by file_lock_
+  static uint64 s_cached_data_length_; // guarded by file_lock_
+
+  // Guards s_cached_platform_file_
+  static base::LazyInstance<base::Lock> s_file_lock_;
+
+#endif
+
   // Shows the translate bubble.
   void ShowBubble(TranslateStep step, TranslateErrors::Type error_type);
 
diff --git a/chrome/browser/ui/android/infobars/auto_login_infobar_delegate.cc b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate.cc
deleted file mode 100644
index 8d575c0..0000000
--- a/chrome/browser/ui/android/infobars/auto_login_infobar_delegate.cc
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_helper.h"
-#include "base/android/jni_string.h"
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/histogram.h"
-#include "base/prefs/pref_service.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/google/google_util.h"
-#include "chrome/browser/infobars/infobar.h"
-#include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/infobars/simple_alert_infobar_delegate.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/ui/sync/sync_promo_ui.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "chrome/common/url_constants.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/page_navigator.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/common/referrer.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "google_apis/gaia/ubertoken_fetcher.h"
-#include "grit/chromium_strings.h"
-#include "grit/generated_resources.h"
-#include "grit/theme_resources.h"
-#include "jni/AutoLoginDelegate_jni.h"
-#include "net/base/escape.h"
-#include "net/url_request/url_request.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using base::android::ConvertUTF8ToJavaString;
-using base::android::ScopedJavaLocalRef;
-
-
-// AutoLoginRedirector --------------------------------------------------------
-
-namespace {
-
-// This class is created by the AutoLoginInfoBarDelegate when the user wishes to
-// auto-login.  It holds context information needed while re-issuing service
-// tokens using the OAuth2TokenService, gets the browser cookies with the
-// TokenAuth API, and finally redirects the user to the correct page.
-class AutoLoginRedirector : public UbertokenConsumer,
-                            public content::WebContentsObserver {
- public:
-  AutoLoginRedirector(content::WebContents* web_contents,
-                      const std::string& args);
-  virtual ~AutoLoginRedirector();
-
- private:
-  // Overriden from UbertokenConsumer:
-  virtual void OnUbertokenSuccess(const std::string& token) OVERRIDE;
-  virtual void OnUbertokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
-
-  // Implementation of content::WebContentsObserver
-  virtual void WebContentsDestroyed(
-      content::WebContents* web_contents) OVERRIDE;
-
-  // Redirect tab to MergeSession URL, logging the user in and navigating
-  // to the desired page.
-  void RedirectToMergeSession(const std::string& token);
-
-  const std::string args_;
-  scoped_ptr<UbertokenFetcher> ubertoken_fetcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutoLoginRedirector);
-};
-
-AutoLoginRedirector::AutoLoginRedirector(
-    content::WebContents* web_contents,
-    const std::string& args)
-    : content::WebContentsObserver(web_contents),
-      args_(args) {
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  ProfileOAuth2TokenService* token_service =
-      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
-  SigninManagerBase* signin_manager =
-      SigninManagerFactory::GetInstance()->GetForProfile(profile);
-  ubertoken_fetcher_.reset(new UbertokenFetcher(token_service,
-                                                this,
-                                                profile->GetRequestContext()));
-  ubertoken_fetcher_->StartFetchingToken(
-      signin_manager->GetAuthenticatedAccountId());
-}
-
-AutoLoginRedirector::~AutoLoginRedirector() {
-}
-
-void AutoLoginRedirector::WebContentsDestroyed(
-    content::WebContents* web_contents) {
-  // The WebContents that started this has been destroyed. The request must be
-  // cancelled and this object must be deleted.
-  ubertoken_fetcher_.reset();
-  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void AutoLoginRedirector::OnUbertokenSuccess(const std::string& token) {
-  RedirectToMergeSession(token);
-  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void AutoLoginRedirector::OnUbertokenFailure(
-    const GoogleServiceAuthError& error) {
-  LOG(WARNING) << "AutoLoginRedirector: token request failed";
-  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-void AutoLoginRedirector::RedirectToMergeSession(const std::string& token) {
-  // TODO(rogerta): what is the correct page transition?
-  web_contents()->GetController().LoadURL(
-      GaiaUrls::GetInstance()->merge_session_url().Resolve(
-          "?source=chrome&uberauth=" + token + "&" + args_),
-      content::Referrer(), content::PAGE_TRANSITION_AUTO_BOOKMARK,
-      std::string());
-}
-
-}  // namespace
-
-
-// AutoLoginInfoBarDelegate ---------------------------------------------------
-
-// static
-bool AutoLoginInfoBarDelegate::Create(content::WebContents* web_contents,
-                                      const Params& params) {
-  // If |web_contents| is hosted in a WebDialog, there may be no infobar
-  // service.
-  InfoBarService* infobar_service =
-    InfoBarService::FromWebContents(web_contents);
-  if (!infobar_service)
-    return false;
-
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  return !!infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
-      scoped_ptr<ConfirmInfoBarDelegate>(
-          new AutoLoginInfoBarDelegate(params, profile))));
-}
-
-AutoLoginInfoBarDelegate::AutoLoginInfoBarDelegate(const Params& params,
-                                                   Profile* profile)
-    : ConfirmInfoBarDelegate(),
-      params_(params),
-      profile_(profile),
-      button_pressed_(false) {
-  RecordHistogramAction(SHOWN);
-  SigninManagerFactory::GetInstance()->GetForProfile(profile_)->AddObserver(
-      this);
-}
-
-AutoLoginInfoBarDelegate::~AutoLoginInfoBarDelegate() {
-  // The SigninManagerFactory is scoped to the lifetime of the app and the
-  // SigninManager is scoped to the lifetime of the Profile, both of which are
-  // longer than the lifetime of the WebContents that this object cannot
-  // outlive. Therefore, it's safe to call RemoveObserver() unconditionally.
-  SigninManagerFactory::GetInstance()->GetForProfile(profile_)->RemoveObserver(
-      this);
-
-  if (!button_pressed_)
-    RecordHistogramAction(IGNORED);
-}
-
-bool AutoLoginInfoBarDelegate::AttachAccount(
-    JavaObjectWeakGlobalRef weak_java_auto_login_delegate) {
-  weak_java_auto_login_delegate_ = weak_java_auto_login_delegate;
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm());
-  ScopedJavaLocalRef<jstring> jaccount =
-      ConvertUTF8ToJavaString(env, account());
-  ScopedJavaLocalRef<jstring> jargs = ConvertUTF8ToJavaString(env, args());
-  DCHECK(!jrealm.is_null());
-  DCHECK(!jaccount.is_null());
-  DCHECK(!jargs.is_null());
-
-  ScopedJavaLocalRef<jobject> delegate =
-      weak_java_auto_login_delegate_.get(env);
-  DCHECK(delegate.obj());
-  user_ = base::android::ConvertJavaStringToUTF8(
-      Java_AutoLoginDelegate_initializeAccount(
-          env, delegate.obj(), reinterpret_cast<intptr_t>(this), jrealm.obj(),
-          jaccount.obj(), jargs.obj()));
-  return !user_.empty();
-}
-
-void AutoLoginInfoBarDelegate::LoginSuccess(JNIEnv* env,
-                                                   jobject obj,
-                                                   jstring result) {
-  if (!infobar()->owner())
-     return;  // We're closing; don't call anything, it might access the owner.
-
-  // TODO(miguelg): Test whether the Stop() and RemoveInfoBar() calls here are
-  // necessary, or whether OpenURL() will do this for us.
-  content::WebContents* contents = web_contents();
-  contents->Stop();
-  infobar()->RemoveSelf();
-  // WARNING: |this| may be deleted at this point!  Do not access any members!
-  contents->OpenURL(content::OpenURLParams(
-      GURL(base::android::ConvertJavaStringToUTF8(env, result)),
-      content::Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_AUTO_BOOKMARK,
-      false));
-}
-
-void AutoLoginInfoBarDelegate::LoginFailed(JNIEnv* env, jobject obj) {
-  if (!infobar()->owner())
-     return;  // We're closing; don't call anything, it might access the owner.
-
-  // TODO(miguelg): Using SimpleAlertInfoBarDelegate::Create() animates in a new
-  // infobar while we animate the current one closed.  It would be better to use
-  // ReplaceInfoBar().
-  SimpleAlertInfoBarDelegate::Create(
-      infobar()->owner(), IDR_INFOBAR_WARNING,
-      l10n_util::GetStringUTF16(IDS_AUTO_LOGIN_FAILED), false);
-  infobar()->RemoveSelf();
-}
-
-void AutoLoginInfoBarDelegate::LoginDismiss(JNIEnv* env, jobject obj) {
-  infobar()->RemoveSelf();
-}
-
-bool AutoLoginInfoBarDelegate::Register(JNIEnv* env) {
-  return RegisterNativesImpl(env);
-}
-
-void AutoLoginInfoBarDelegate::InfoBarDismissed() {
-  RecordHistogramAction(DISMISSED);
-  button_pressed_ = true;
-}
-
-int AutoLoginInfoBarDelegate::GetIconID() const {
-  return IDR_INFOBAR_AUTOLOGIN;
-}
-
-InfoBarDelegate::Type AutoLoginInfoBarDelegate::GetInfoBarType() const {
-  return PAGE_ACTION_TYPE;
-}
-
-AutoLoginInfoBarDelegate*
-    AutoLoginInfoBarDelegate::AsAutoLoginInfoBarDelegate() {
-  return this;
-}
-
-base::string16 AutoLoginInfoBarDelegate::GetMessageText() const {
-  return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE,
-                                    base::UTF8ToUTF16(user_));
-}
-
-base::string16 AutoLoginInfoBarDelegate::GetButtonLabel(
-    InfoBarButton button) const {
-  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
-      IDS_AUTOLOGIN_INFOBAR_OK_BUTTON : IDS_AUTOLOGIN_INFOBAR_CANCEL_BUTTON);
-}
-
-bool AutoLoginInfoBarDelegate::Accept() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> delegate =
-      weak_java_auto_login_delegate_.get(env);
-  DCHECK(delegate.obj());
-  Java_AutoLoginDelegate_logIn(env, delegate.obj(),
-                               reinterpret_cast<intptr_t>(this));
-  // Do not close the infobar on accept, it will be closed as part
-  // of the log in callback.
-  return false;
-}
-
-bool AutoLoginInfoBarDelegate::Cancel() {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  ScopedJavaLocalRef<jobject> delegate =
-      weak_java_auto_login_delegate_.get(env);
-  DCHECK(delegate.obj());
-  Java_AutoLoginDelegate_cancelLogIn(env, delegate.obj(),
-                                     reinterpret_cast<intptr_t>(this));
-  return true;
-}
-
-void AutoLoginInfoBarDelegate::GoogleSignedOut(const std::string& username) {
-  infobar()->RemoveSelf();
-}
-
-void AutoLoginInfoBarDelegate::RecordHistogramAction(Actions action) {
-  UMA_HISTOGRAM_ENUMERATION("AutoLogin.Regular", action,
-                            HISTOGRAM_BOUNDING_VALUE);
-}
diff --git a/chrome/browser/ui/android/infobars/auto_login_infobar_delegate.h b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate.h
deleted file mode 100644
index 45585dc..0000000
--- a/chrome/browser/ui/android/infobars/auto_login_infobar_delegate.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_H_
-#define CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_H_
-
-#include <string>
-#include "base/android/jni_helper.h"
-#include "base/android/scoped_java_ref.h"
-#include "chrome/browser/infobars/confirm_infobar_delegate.h"
-#include "chrome/browser/signin/signin_manager.h"
-#include "components/auto_login_parser/auto_login_parser.h"
-
-class PrefService;
-class Profile;
-
-namespace content {
-class NavigationController;
-}
-
-// This is the actual infobar displayed to prompt the user to auto-login.
-class AutoLoginInfoBarDelegate : public ConfirmInfoBarDelegate,
-                                 public SigninManagerBase::Observer {
- public:
-  struct Params {
-    // Information from a parsed header.
-    auto_login_parser::HeaderData header;
-
-    // Username to display in the infobar indicating user to be logged in as.
-    // This is initially fetched from sign-in on non-Android platforms. Note
-    // that on Android this field is not used.
-    std::string username;
-  };
-
-  // Creates an autologin infobar and delegate and adds the infobar to the
-  // infobar service for |web_contents|.  Returns whether the infobar was
-  // successfully added.
-  static bool Create(content::WebContents* web_contents, const Params& params);
-
-  // These methods are defined in downstream code.
-  bool AttachAccount(JavaObjectWeakGlobalRef weak_java_translate_helper);
-  void LoginSuccess(JNIEnv* env, jobject obj, jstring result);
-  void LoginFailed(JNIEnv* env, jobject obj);
-  void LoginDismiss(JNIEnv* env, jobject obj);
-
-  // Register Android JNI bindings.
-  static bool Register(JNIEnv* env);
-
- protected:
-  AutoLoginInfoBarDelegate(const Params& params, Profile* profile);
-  virtual ~AutoLoginInfoBarDelegate();
-
- private:
-  // Enum values used for UMA histograms.
-  enum Actions {
-    SHOWN,       // The infobar was shown to the user.
-    ACCEPTED,    // The user pressed the accept button.
-    REJECTED,    // The user pressed the reject button.
-    DISMISSED,   // The user pressed the close button.
-    IGNORED,     // The user ignored the infobar.
-    LEARN_MORE,  // The user clicked on the learn more link.
-    HISTOGRAM_BOUNDING_VALUE
-  };
-
-  const std::string& realm() const { return params_.header.realm; }
-  const std::string& account() const { return params_.header.account; }
-  const std::string& args() const { return params_.header.args; }
-
-  // ConfirmInfoBarDelegate:
-  virtual void InfoBarDismissed() OVERRIDE;
-  virtual int GetIconID() const OVERRIDE;
-  virtual Type GetInfoBarType() const OVERRIDE;
-  virtual AutoLoginInfoBarDelegate* AsAutoLoginInfoBarDelegate() OVERRIDE;
-  virtual base::string16 GetMessageText() const OVERRIDE;
-  virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
-  virtual bool Accept() OVERRIDE;
-  virtual bool Cancel() OVERRIDE;
-
-  // SigninManagerBase::Observer:
-  virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
-
-  void RecordHistogramAction(Actions action);
-
-  JavaObjectWeakGlobalRef weak_java_auto_login_delegate_;
-  std::string user_;
-  const Params params_;
-
-  Profile* profile_;
-
-  // Whether any UI controls in the infobar were pressed or not.
-  bool button_pressed_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutoLoginInfoBarDelegate);
-};
-
-#endif  // CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.cc b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.cc
new file mode 100644
index 0000000..3ae87b3
--- /dev/null
+++ b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.cc
@@ -0,0 +1,120 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_helper.h"
+#include "base/android/jni_string.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/infobars/infobar.h"
+#include "chrome/browser/infobars/simple_alert_infobar_delegate.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate.h"
+#include "content/public/browser/web_contents.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "jni/AutoLoginDelegate_jni.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaLocalRef;
+
+
+AutoLoginInfoBarDelegateAndroid::AutoLoginInfoBarDelegateAndroid(
+    const Params& params,
+    Profile* profile)
+    : AutoLoginInfoBarDelegate(params, profile),
+      params_(params) {
+}
+
+AutoLoginInfoBarDelegateAndroid::~AutoLoginInfoBarDelegateAndroid() {
+}
+
+bool AutoLoginInfoBarDelegateAndroid::AttachAccount(
+    JavaObjectWeakGlobalRef weak_java_auto_login_delegate) {
+  weak_java_auto_login_delegate_ = weak_java_auto_login_delegate;
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> jrealm = ConvertUTF8ToJavaString(env, realm());
+  ScopedJavaLocalRef<jstring> jaccount =
+      ConvertUTF8ToJavaString(env, account());
+  ScopedJavaLocalRef<jstring> jargs = ConvertUTF8ToJavaString(env, args());
+  DCHECK(!jrealm.is_null());
+  DCHECK(!jaccount.is_null());
+  DCHECK(!jargs.is_null());
+
+  ScopedJavaLocalRef<jobject> delegate =
+      weak_java_auto_login_delegate_.get(env);
+  DCHECK(delegate.obj());
+  user_ = base::android::ConvertJavaStringToUTF8(
+      Java_AutoLoginDelegate_initializeAccount(
+          env, delegate.obj(), reinterpret_cast<intptr_t>(this), jrealm.obj(),
+          jaccount.obj(), jargs.obj()));
+  return !user_.empty();
+}
+
+base::string16 AutoLoginInfoBarDelegateAndroid::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE,
+                                    base::UTF8ToUTF16(user_));
+}
+
+bool AutoLoginInfoBarDelegateAndroid::Accept() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> delegate =
+      weak_java_auto_login_delegate_.get(env);
+  DCHECK(delegate.obj());
+  Java_AutoLoginDelegate_logIn(env, delegate.obj(),
+                               reinterpret_cast<intptr_t>(this));
+  // Do not close the infobar on accept, it will be closed as part
+  // of the log in callback.
+  return false;
+}
+
+bool AutoLoginInfoBarDelegateAndroid::Cancel() {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  ScopedJavaLocalRef<jobject> delegate =
+      weak_java_auto_login_delegate_.get(env);
+  DCHECK(delegate.obj());
+  Java_AutoLoginDelegate_cancelLogIn(env, delegate.obj(),
+                                     reinterpret_cast<intptr_t>(this));
+  return true;
+}
+
+void AutoLoginInfoBarDelegateAndroid::LoginSuccess(JNIEnv* env,
+                                                   jobject obj,
+                                                   jstring result) {
+  if (!infobar()->owner())
+     return;  // We're closing; don't call anything, it might access the owner.
+
+  // TODO(miguelg): Test whether the Stop() and RemoveInfoBar() calls here are
+  // necessary, or whether OpenURL() will do this for us.
+  content::WebContents* contents = web_contents();
+  contents->Stop();
+  infobar()->RemoveSelf();
+  // WARNING: |this| may be deleted at this point!  Do not access any members!
+  contents->OpenURL(content::OpenURLParams(
+      GURL(base::android::ConvertJavaStringToUTF8(env, result)),
+      content::Referrer(), CURRENT_TAB, content::PAGE_TRANSITION_AUTO_BOOKMARK,
+      false));
+}
+
+void AutoLoginInfoBarDelegateAndroid::LoginFailed(JNIEnv* env, jobject obj) {
+  if (!infobar()->owner())
+     return;  // We're closing; don't call anything, it might access the owner.
+
+  // TODO(miguelg): Using SimpleAlertInfoBarDelegate::Create() animates in a new
+  // infobar while we animate the current one closed.  It would be better to use
+  // ReplaceInfoBar().
+  SimpleAlertInfoBarDelegate::Create(
+      infobar()->owner(), IDR_INFOBAR_WARNING,
+      l10n_util::GetStringUTF16(IDS_AUTO_LOGIN_FAILED), false);
+  infobar()->RemoveSelf();
+}
+
+void AutoLoginInfoBarDelegateAndroid::LoginDismiss(JNIEnv* env, jobject obj) {
+  infobar()->RemoveSelf();
+}
+
+bool AutoLoginInfoBarDelegateAndroid::Register(JNIEnv* env) {
+  return RegisterNativesImpl(env);
+}
diff --git a/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h
new file mode 100644
index 0000000..b977c94
--- /dev/null
+++ b/chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+#define CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+
+#include "base/android/jni_helper.h"
+#include "base/android/scoped_java_ref.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate.h"
+
+class AutoLoginInfoBarDelegateAndroid : public AutoLoginInfoBarDelegate {
+ public:
+  AutoLoginInfoBarDelegateAndroid(const Params& params, Profile* profile);
+  virtual ~AutoLoginInfoBarDelegateAndroid();
+
+  // AutoLoginInfoBarDelegate:
+  virtual bool Accept() OVERRIDE;
+  virtual bool Cancel() OVERRIDE;
+  virtual base::string16 GetMessageText() const OVERRIDE;
+
+  // These methods are defined in downstream code.
+  bool AttachAccount(JavaObjectWeakGlobalRef weak_java_translate_helper);
+  void LoginSuccess(JNIEnv* env, jobject obj, jstring result);
+  void LoginFailed(JNIEnv* env, jobject obj);
+  void LoginDismiss(JNIEnv* env, jobject obj);
+
+  // Register Android JNI bindings.
+  static bool Register(JNIEnv* env);
+
+ private:
+  const std::string& realm() const { return params_.header.realm; }
+  const std::string& account() const { return params_.header.account; }
+  const std::string& args() const { return params_.header.args; }
+
+  JavaObjectWeakGlobalRef weak_java_auto_login_delegate_;
+  std::string user_;
+  const Params params_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoLoginInfoBarDelegateAndroid);
+};
+
+#endif  // CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_INFOBAR_DELEGATE_ANDROID_H_
+
diff --git a/chrome/browser/ui/android/infobars/auto_login_prompter.cc b/chrome/browser/ui/android/infobars/auto_login_prompter.cc
deleted file mode 100644
index ef13339..0000000
--- a/chrome/browser/ui/android/infobars/auto_login_prompter.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/android/infobars/auto_login_prompter.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/prefs/pref_service.h"
-#include "chrome/browser/google/google_url_tracker.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_factory.h"
-#include "chrome/browser/tab_contents/tab_util.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "components/auto_login_parser/auto_login_parser.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/web_contents.h"
-#include "net/url_request/url_request.h"
-#include "url/gurl.h"
-
-using content::BrowserThread;
-using content::WebContents;
-
-AutoLoginPrompter::AutoLoginPrompter(WebContents* web_contents,
-                                     const Params& params,
-                                     const GURL& url)
-    : WebContentsObserver(web_contents),
-      params_(params),
-      url_(url),
-      infobar_shown_(false) {
-  if (!web_contents->IsLoading()) {
-    // If the WebContents isn't loading a page, the load notification will never
-    // be triggered.  Try adding the InfoBar now.
-    AddInfoBarToWebContents();
-  }
-}
-
-AutoLoginPrompter::~AutoLoginPrompter() {
-}
-
-// static
-void AutoLoginPrompter::ShowInfoBarIfPossible(net::URLRequest* request,
-                                              int child_id,
-                                              int route_id) {
-  // See if the response contains the X-Auto-Login header.  If so, this was
-  // a request for a login page, and the server is allowing the browser to
-  // suggest auto-login, if available.
-  Params params;
-  // Currently we only accept GAIA credentials in Chrome.
-  if (!auto_login_parser::ParserHeaderInResponse(
-          request, auto_login_parser::ONLY_GOOGLE_COM, &params.header))
-    return;
-
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&ShowInfoBarUIThread,
-                 params, request->url(), child_id, route_id));
-}
-
-
-// static
-void AutoLoginPrompter::ShowInfoBarUIThread(Params params,
-                                            const GURL& url,
-                                            int child_id,
-                                            int route_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-  WebContents* web_contents = tab_util::GetWebContentsByID(child_id, route_id);
-  if (!web_contents)
-    return;
-
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
-
-  if (!profile->GetPrefs()->GetBoolean(prefs::kAutologinEnabled))
-    return;
-
-  // Make sure that |account|, if specified, matches the logged in user.
-  // However, |account| is usually empty.
-  if (!params.username.empty() && !params.header.account.empty() &&
-      params.username != params.header.account)
-    return;
-  // We can't add the infobar just yet, since we need to wait for the tab to
-  // finish loading.  If we don't, the info bar appears and then disappears
-  // immediately.  Create an AutoLoginPrompter instance to listen for the
-  // relevant notifications; it will delete itself.
-  new AutoLoginPrompter(web_contents, params, url);
-}
-
-void AutoLoginPrompter::DidStopLoading(
-    content::RenderViewHost* render_view_host) {
-  AddInfoBarToWebContents();
-  delete this;
-}
-
-void AutoLoginPrompter::WebContentsDestroyed(WebContents* web_contents) {
-  // The WebContents was destroyed before the navigation completed.
-  delete this;
-}
-
-void AutoLoginPrompter::AddInfoBarToWebContents() {
-  if (!infobar_shown_)
-    infobar_shown_ = AutoLoginInfoBarDelegate::Create(web_contents(), params_);
-}
diff --git a/chrome/browser/ui/android/infobars/auto_login_prompter.h b/chrome/browser/ui/android/infobars/auto_login_prompter.h
deleted file mode 100644
index d4d5801..0000000
--- a/chrome/browser/ui/android/infobars/auto_login_prompter.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_PROMPTER_H_
-#define CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_PROMPTER_H_
-
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "url/gurl.h"
-
-namespace content {
-class RenderViewHost;
-class WebContents;
-}
-
-namespace net {
-class URLRequest;
-}
-
-// This class displays an infobar that allows the user to automatically login to
-// the currently loaded page with one click.  This is used when the browser
-// detects that the user has navigated to a login page and that there are stored
-// tokens that would allow a one-click login.
-class AutoLoginPrompter : public content::WebContentsObserver {
- public:
-  typedef AutoLoginInfoBarDelegate::Params Params;
-
-  // Looks for the X-Auto-Login response header in the request, and if found,
-  // tries to display an infobar in the tab contents identified by the
-  // child/route id.
-  static void ShowInfoBarIfPossible(net::URLRequest* request,
-                                    int child_id,
-                                    int route_id);
-
- private:
-  friend class AutoLoginPrompterTest;
-
-  AutoLoginPrompter(content::WebContents* web_contents,
-                    const Params& params,
-                    const GURL& url);
-
-  virtual ~AutoLoginPrompter();
-
-  static void ShowInfoBarUIThread(Params params,
-                                  const GURL& url,
-                                  int child_id,
-                                  int route_id);
-
-  virtual void DidStopLoading(
-      content::RenderViewHost* render_view_host) OVERRIDE;
-
-  virtual void WebContentsDestroyed(
-      content::WebContents* web_contents) OVERRIDE;
-
-  // Add the infobar to the WebContents, if it's still needed.
-  void AddInfoBarToWebContents();
-
-  const Params params_;
-  const GURL url_;
-  bool infobar_shown_;
-
-  DISALLOW_COPY_AND_ASSIGN(AutoLoginPrompter);
-};
-
-#endif  // CHROME_BROWSER_UI_ANDROID_INFOBARS_AUTO_LOGIN_PROMPTER_H_
diff --git a/chrome/browser/ui/android/infobars/infobar_container_android.cc b/chrome/browser/ui/android/infobars/infobar_container_android.cc
index 8e1039a..6a89bc3 100644
--- a/chrome/browser/ui/android/infobars/infobar_container_android.cc
+++ b/chrome/browser/ui/android/infobars/infobar_container_android.cc
@@ -10,7 +10,7 @@
 #include "chrome/browser/infobars/infobar.h"
 #include "chrome/browser/infobars/infobar_delegate.h"
 #include "chrome/browser/infobars/infobar_service.h"
-#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate.h"
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
 #include "chrome/browser/ui/android/infobars/infobar_android.h"
 #include "content/public/browser/web_contents.h"
 #include "jni/InfoBarContainer_jni.h"
@@ -48,8 +48,8 @@
   }
 
   if (infobar->delegate()->AsAutoLoginInfoBarDelegate()) {
-    AutoLoginInfoBarDelegate* auto_login_delegate =
-        static_cast<AutoLoginInfoBarDelegate*>(
+    AutoLoginInfoBarDelegateAndroid* auto_login_delegate =
+        static_cast<AutoLoginInfoBarDelegateAndroid*>(
             infobar->delegate()->AsAutoLoginInfoBarDelegate());
     if (!auto_login_delegate->AttachAccount(weak_java_auto_login_delegate_))
       return;
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.cc b/chrome/browser/ui/app_list/app_list_syncable_service.cc
index aa78b46..54a141e 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.cc
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.cc
@@ -102,13 +102,6 @@
                         ->WasInstalledByDefault(id);
 }
 
-bool AppIsOem(ExtensionService* service, const std::string& id) {
-  if (!service)
-    return false;
-  const extensions::Extension* extension = service->GetExtensionById(id, true);
-  return extension && extension->was_installed_by_oem();
-}
-
 void UninstallExtension(ExtensionService* service, const std::string& id) {
   if (service && service->GetInstalledExtension(id))
     service->UninstallExtension(id, false, NULL);
@@ -269,11 +262,14 @@
   if (!sync_item)
     return;  // Item is not valid.
 
-  DVLOG(1) << this << ": AddItem: " << sync_item->ToString();
-  std::string folder_id = sync_item->parent_id;
-  if (folder_id.empty()) {
-    if (AppIsOem(extension_system_->extension_service(), app_item->id()))
-      folder_id = FindOrCreateOemFolder();
+  std::string folder_id;
+  if (AppIsOem(app_item->id())) {
+    folder_id = FindOrCreateOemFolder();
+    DVLOG(1) << this << ": AddItem to OEM folder: " << sync_item->ToString();
+  } else {
+    folder_id = sync_item->parent_id;
+    DVLOG(1) << this << ": AddItem: " << sync_item->ToString()
+             << " Folder: '" << folder_id << "'";
   }
   model_->AddItemToFolder(app_item.Pass(), folder_id);
 }
@@ -381,8 +377,7 @@
 
 void AppListSyncableService::UpdateItem(AppListItem* app_item) {
   // Check to see if the item needs to be moved to/from the OEM folder.
-  bool is_oem =
-      AppIsOem(extension_system_->extension_service(), app_item->id());
+  bool is_oem = AppIsOem(app_item->id());
   if (!is_oem && app_item->folder_id() == kOemFolderId)
     model_->MoveItemToFolder(app_item, "");
   else if (is_oem && app_item->folder_id() != kOemFolderId)
@@ -666,7 +661,8 @@
   }
   // This is the only place where sync can cause an item to change folders.
   if (app_list::switches::IsFolderUIEnabled() &&
-      app_item->folder_id() != sync_item->parent_id) {
+      app_item->folder_id() != sync_item->parent_id &&
+      !AppIsOem(app_item->id())) {
     DVLOG(2) << " Moving Item To Folder: " << sync_item->parent_id;
     model_->MoveItemToFolder(app_item, sync_item->parent_id);
   }
@@ -768,6 +764,14 @@
   return oem_folder->id();
 }
 
+bool AppListSyncableService::AppIsOem(const std::string& id) {
+  if (!extension_system_->extension_service())
+    return false;
+  const extensions::Extension* extension =
+      extension_system_->extension_service()->GetExtensionById(id, true);
+  return extension && extension->was_installed_by_oem();
+}
+
 std::string AppListSyncableService::SyncItem::ToString() const {
   std::string res = item_id.substr(0, 8);
   if (item_type == sync_pb::AppListSpecifics::TYPE_REMOVE_DEFAULT_APP) {
diff --git a/chrome/browser/ui/app_list/app_list_syncable_service.h b/chrome/browser/ui/app_list/app_list_syncable_service.h
index 949b49f..aa7ba06 100644
--- a/chrome/browser/ui/app_list/app_list_syncable_service.h
+++ b/chrome/browser/ui/app_list/app_list_syncable_service.h
@@ -79,7 +79,10 @@
 
   Profile* profile() { return profile_; }
   AppListModel* model() { return model_.get(); }
-  size_t GetNumSyncItemsForTest() { return sync_items_.size(); }
+  size_t GetNumSyncItemsForTest() const { return sync_items_.size(); }
+  const std::string& GetOemFolderNameForTest() const {
+    return oem_folder_name_;
+  }
 
   // syncer::SyncableService
   virtual syncer::SyncMergeResult MergeDataAndStartSyncing(
@@ -176,6 +179,10 @@
   // folder id.
   std::string FindOrCreateOemFolder();
 
+  // Returns true if an extension matching |id| exists and was installed by
+  // an OEM (extension->was_installed_by_oem() is true).
+  bool AppIsOem(const std::string& id);
+
   Profile* profile_;
   extensions::ExtensionSystem* extension_system_;
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.cc b/chrome/browser/ui/app_list/app_list_view_delegate.cc
index 3a92ba8..1c696d2 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.cc
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.cc
@@ -79,6 +79,7 @@
     user.name = profile_info.GetNameOfProfileAtIndex(i);
     user.email = profile_info.GetUserNameOfProfileAtIndex(i);
     user.profile_path = profile_info.GetPathOfProfileAtIndex(i);
+    user.signin_required = profile_info.ProfileIsSigninRequiredAtIndex(i);
     user.active = active_profile_path == user.profile_path;
     users->push_back(user);
   }
@@ -244,7 +245,7 @@
                                       GURL()));
 
   web_app::UpdateShortcutInfoAndIconForApp(
-      *extension,
+      extension,
       profile_,
       base::Bind(CreateShortcutInWebAppDir, app_data_dir, callback));
 #else
diff --git a/chrome/browser/ui/app_list/app_list_view_delegate.h b/chrome/browser/ui/app_list/app_list_view_delegate.h
index 85625ec..945baab 100644
--- a/chrome/browser/ui/app_list/app_list_view_delegate.h
+++ b/chrome/browser/ui/app_list/app_list_view_delegate.h
@@ -14,10 +14,10 @@
 #include "base/observer_list.h"
 #include "base/scoped_observer.h"
 #include "chrome/browser/profiles/profile_info_cache_observer.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/app_list/chrome_signin_delegate.h"
 #include "chrome/browser/ui/app_list/start_page_observer.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "ui/app_list/app_list_view_delegate.h"
 
 class AppListControllerDelegate;
diff --git a/chrome/browser/ui/app_list/search/people/people_provider.cc b/chrome/browser/ui/app_list/search/people/people_provider.cc
index 2cfc80c..1d99aff 100644
--- a/chrome/browser/ui/app_list/search/people/people_provider.cc
+++ b/chrome/browser/ui/app_list/search/people/people_provider.cc
@@ -20,7 +20,7 @@
 #include "chrome/browser/ui/app_list/search/common/json_response_fetcher.h"
 #include "chrome/browser/ui/app_list/search/people/people_result.h"
 #include "chrome/browser/ui/app_list/search/people/person.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "net/base/url_util.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/ui/app_list/search/people/people_result.cc b/chrome/browser/ui/app_list/search/people/people_result.cc
index 1613dd5..5df2d29 100644
--- a/chrome/browser/ui/app_list/search/people/people_result.cc
+++ b/chrome/browser/ui/app_list/search/people/people_result.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/ui/app_list/search/people/person.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/common/extensions/api/hangouts_private.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/user_metrics.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_system.h"
diff --git a/chrome/browser/ui/app_list/start_page_service.cc b/chrome/browser/ui/app_list/start_page_service.cc
index 641c66b..9e689a6 100644
--- a/chrome/browser/ui/app_list/start_page_service.cc
+++ b/chrome/browser/ui/app_list/start_page_service.cc
@@ -145,8 +145,8 @@
 }
 
 content::WebContents* StartPageService::GetStartPageContents() {
-  return CommandLine::ForCurrentProcess()->HasSwitch(
-      ::switches::kShowAppListStartPage) ? contents_.get() : NULL;
+  return app_list::switches::IsExperimentalAppListEnabled() ? contents_.get()
+                                                            : NULL;
 }
 
 content::WebContents* StartPageService::GetSpeechRecognitionContents() {
diff --git a/chrome/browser/ui/app_list/start_page_service_factory.cc b/chrome/browser/ui/app_list/start_page_service_factory.cc
index a5141e2..ff6e6e4 100644
--- a/chrome/browser/ui/app_list/start_page_service_factory.cc
+++ b/chrome/browser/ui/app_list/start_page_service_factory.cc
@@ -18,8 +18,7 @@
 
 // static
 StartPageService* StartPageServiceFactory::GetForProfile(Profile* profile) {
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          ::switches::kShowAppListStartPage) &&
+  if (!app_list::switches::IsExperimentalAppListEnabled() &&
       !app_list::switches::IsVoiceSearchEnabled()) {
       return NULL;
     }
diff --git a/chrome/browser/ui/app_list/test/fake_profile.cc b/chrome/browser/ui/app_list/test/fake_profile.cc
index 36277cd..41ebb25 100644
--- a/chrome/browser/ui/app_list/test/fake_profile.cc
+++ b/chrome/browser/ui/app_list/test/fake_profile.cc
@@ -61,6 +61,7 @@
     int render_view_id,
     int bridge_id,
     const GURL& requesting_frame,
+    bool user_gesture,
     const MidiSysExPermissionCallback& callback) {
 }
 
diff --git a/chrome/browser/ui/app_list/test/fake_profile.h b/chrome/browser/ui/app_list/test/fake_profile.h
index eee7499..12ba769 100644
--- a/chrome/browser/ui/app_list/test/fake_profile.h
+++ b/chrome/browser/ui/app_list/test/fake_profile.h
@@ -49,6 +49,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) OVERRIDE;
   virtual void CancelMidiSysExPermissionRequest(
         int render_process_id,
diff --git a/chrome/browser/ui/apps/chrome_app_window_delegate.cc b/chrome/browser/ui/apps/chrome_app_window_delegate.cc
index 3bbd9a3..7f0e066 100644
--- a/chrome/browser/ui/apps/chrome_app_window_delegate.cc
+++ b/chrome/browser/ui/apps/chrome_app_window_delegate.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/apps/chrome_app_window_delegate.h"
 
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/favicon/favicon_tab_helper.h"
 #include "chrome/browser/file_select_helper.h"
@@ -20,6 +21,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
 #include "content/public/browser/web_contents_view.h"
 
 #if defined(USE_ASH)
@@ -42,7 +44,6 @@
 // Opens a URL with Chromium (not external browser) with the right profile.
 content::WebContents* OpenURLFromTabInternal(
     content::BrowserContext* context,
-    content::WebContents* source,
     const content::OpenURLParams& params) {
   // Force all links to open in a new tab, even if they were trying to open a
   // window.
@@ -67,9 +68,9 @@
 class OpenURLFromTabBasedOnBrowserDefault
     : public ShellIntegration::DefaultWebClientObserver {
  public:
-  OpenURLFromTabBasedOnBrowserDefault(content::WebContents* source,
+  OpenURLFromTabBasedOnBrowserDefault(scoped_ptr<content::WebContents> source,
                                       const content::OpenURLParams& params)
-      : source_(source), params_(params) {}
+      : source_(source.Pass()), params_(params) {}
 
   // Opens a URL when called with the result of if this is the default system
   // browser or not.
@@ -84,7 +85,7 @@
       case ShellIntegration::STATE_PROCESSING:
         break;
       case ShellIntegration::STATE_IS_DEFAULT:
-        OpenURLFromTabInternal(profile, source_, params_);
+        OpenURLFromTabInternal(profile, params_);
         break;
       case ShellIntegration::STATE_NOT_DEFAULT:
       case ShellIntegration::STATE_UNKNOWN:
@@ -96,26 +97,42 @@
   virtual bool IsOwnedByWorker() OVERRIDE { return true; }
 
  private:
-  content::WebContents* source_;
+  scoped_ptr<content::WebContents> source_;
   const content::OpenURLParams params_;
 };
 
 }  // namespace
 
-AppWindowLinkDelegate::AppWindowLinkDelegate() {}
+class ChromeAppWindowDelegate::NewWindowContentsDelegate
+    : public content::WebContentsDelegate {
+ public:
+  NewWindowContentsDelegate() {}
+  virtual ~NewWindowContentsDelegate() {}
 
-AppWindowLinkDelegate::~AppWindowLinkDelegate() {}
+  virtual content::WebContents* OpenURLFromTab(
+      content::WebContents* source,
+      const content::OpenURLParams& params) OVERRIDE;
 
-// TODO(rockot): Add a test that exercises this code. See
-// http://crbug.com/254260.
-content::WebContents* AppWindowLinkDelegate::OpenURLFromTab(
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NewWindowContentsDelegate);
+};
+
+content::WebContents*
+ChromeAppWindowDelegate::NewWindowContentsDelegate::OpenURLFromTab(
     content::WebContents* source,
     const content::OpenURLParams& params) {
   if (source) {
+    // This NewWindowContentsDelegate was given ownership of the incoming
+    // WebContents by being assigned as its delegate within
+    // ChromeAppWindowDelegate::AddNewContents, but this is the first time
+    // NewWindowContentsDelegate actually sees the WebContents.
+    // Here it is captured for deletion.
+    scoped_ptr<content::WebContents> owned_source(source);
     scoped_refptr<ShellIntegration::DefaultWebClientWorker>
         check_if_default_browser_worker =
             new ShellIntegration::DefaultBrowserWorker(
-                new OpenURLFromTabBasedOnBrowserDefault(source, params));
+                new OpenURLFromTabBasedOnBrowserDefault(owned_source.Pass(),
+                                                        params));
     // Object lifetime notes: The OpenURLFromTabBasedOnBrowserDefault is owned
     // by check_if_default_browser_worker. StartCheckIsDefault() takes lifetime
     // ownership of check_if_default_browser_worker and will clean up after
@@ -125,7 +142,8 @@
   return NULL;
 }
 
-ChromeAppWindowDelegate::ChromeAppWindowDelegate() {}
+ChromeAppWindowDelegate::ChromeAppWindowDelegate()
+    : new_window_contents_delegate_(new NewWindowContentsDelegate()) {}
 
 ChromeAppWindowDelegate::~ChromeAppWindowDelegate() {}
 
@@ -157,7 +175,7 @@
     content::BrowserContext* context,
     content::WebContents* source,
     const content::OpenURLParams& params) {
-  return OpenURLFromTabInternal(context, source, params);
+  return OpenURLFromTabInternal(context, params);
 }
 
 void ChromeAppWindowDelegate::AddNewContents(content::BrowserContext* context,
@@ -167,9 +185,11 @@
                                              bool user_gesture,
                                              bool* was_blocked) {
   if (!disable_external_open_for_testing_) {
-    if (!app_window_link_delegate_.get())
-      app_window_link_delegate_.reset(new AppWindowLinkDelegate());
-    new_contents->SetDelegate(app_window_link_delegate_.get());
+    // We don't really want to open a window for |new_contents|, but we need to
+    // capture its intended navigation. Here we give ownership to the
+    // NewWindowContentsDelegate, which will dispose of the contents once
+    // a navigation is captured.
+    new_contents->SetDelegate(new_window_contents_delegate_.get());
     return;
   }
   chrome::ScopedTabbedBrowserDisplayer displayer(
diff --git a/chrome/browser/ui/apps/chrome_app_window_delegate.h b/chrome/browser/ui/apps/chrome_app_window_delegate.h
index b801739..600e3c3 100644
--- a/chrome/browser/ui/apps/chrome_app_window_delegate.h
+++ b/chrome/browser/ui/apps/chrome_app_window_delegate.h
@@ -7,28 +7,14 @@
 
 #include "apps/app_window.h"
 #include "base/memory/scoped_ptr.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_delegate.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/gfx/rect.h"
 
 namespace content {
 class BrowserContext;
+class WebContents;
 }
 
-class AppWindowLinkDelegate : public content::WebContentsDelegate {
- public:
-  AppWindowLinkDelegate();
-  virtual ~AppWindowLinkDelegate();
-
- private:
-  virtual content::WebContents* OpenURLFromTab(
-      content::WebContents* source,
-      const content::OpenURLParams& params) OVERRIDE;
-
-  DISALLOW_COPY_AND_ASSIGN(AppWindowLinkDelegate);
-};
-
 class ChromeAppWindowDelegate : public apps::AppWindow::Delegate {
  public:
   ChromeAppWindowDelegate();
@@ -37,6 +23,8 @@
   static void DisableExternalOpenForTesting();
 
  private:
+  class NewWindowContentsDelegate;
+
   // apps::AppWindow::Delegate:
   virtual void InitWebContents(content::WebContents* web_contents) OVERRIDE;
   virtual apps::NativeAppWindow* CreateNativeAppWindow(
@@ -74,7 +62,7 @@
       apps::AppWindow* window,
       const apps::AppWindow::CreateParams& params);
 
-  scoped_ptr<AppWindowLinkDelegate> app_window_link_delegate_;
+  scoped_ptr<NewWindowContentsDelegate> new_window_contents_delegate_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeAppWindowDelegate);
 };
diff --git a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
index 6d1d00c..8af22d5 100644
--- a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
+++ b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
@@ -96,7 +96,12 @@
       public InProcessBrowserTest {
  public:
   AcceleratorCommandsFullscreenBrowserTest()
-      : initial_show_state_(GetParam()) {
+#if defined(OS_CHROMEOS)
+      : put_window_in_immersive_(true),
+#else
+      : put_window_in_immersive_(false),
+#endif
+        initial_show_state_(GetParam()) {
   }
   virtual ~AcceleratorCommandsFullscreenBrowserTest() {
   }
@@ -117,7 +122,12 @@
       return window_state->IsNormalStateType();
   }
 
+  bool put_window_in_immersive() const {
+    return put_window_in_immersive_;
+  }
+
  private:
+  bool put_window_in_immersive_;
   ui::WindowShowState initial_show_state_;
 
   DISALLOW_COPY_AND_ASSIGN(AcceleratorCommandsFullscreenBrowserTest);
@@ -144,7 +154,7 @@
 
   ash::accelerators::ToggleFullscreen();
   EXPECT_TRUE(window_state->IsFullscreen());
-  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
+  EXPECT_EQ(put_window_in_immersive(), IsInImmersiveFullscreen(window_state));
 
   ash::accelerators::ToggleFullscreen();
   EXPECT_TRUE(IsInitialShowState(window_state));
@@ -171,7 +181,7 @@
 
   ash::accelerators::ToggleFullscreen();
   EXPECT_TRUE(window_state->IsFullscreen());
-  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
+  EXPECT_EQ(put_window_in_immersive(), IsInImmersiveFullscreen(window_state));
 
   ash::accelerators::ToggleFullscreen();
   EXPECT_TRUE(IsInitialShowState(window_state));
@@ -190,7 +200,7 @@
 
   ash::accelerators::ToggleFullscreen();
   EXPECT_TRUE(window_state->IsFullscreen());
-  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
+  EXPECT_EQ(put_window_in_immersive(), IsInImmersiveFullscreen(window_state));
 
   ash::accelerators::ToggleFullscreen();
   EXPECT_TRUE(IsInitialShowState(window_state));
@@ -210,7 +220,7 @@
 
   ash::accelerators::ToggleFullscreen();
   EXPECT_TRUE(window_state->IsFullscreen());
-  EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
+  EXPECT_EQ(put_window_in_immersive(), IsInImmersiveFullscreen(window_state));
 
   // TODO(pkotwicz|oshima): Make toggling fullscreen restore the window to its
   // show state prior to entering fullscreen.
@@ -230,7 +240,12 @@
       public extensions::PlatformAppBrowserTest {
  public:
   AcceleratorCommandsPlatformAppFullscreenBrowserTest()
-      : initial_show_state_(GetParam()) {
+#if defined(OS_CHROMEOS)
+      : put_window_in_immersive_(true),
+#else
+      : put_window_in_immersive_(false),
+#endif
+        initial_show_state_(GetParam()) {
   }
   virtual ~AcceleratorCommandsPlatformAppFullscreenBrowserTest() {
   }
@@ -251,7 +266,12 @@
       return ui::BaseWindow::IsRestored(*app_window->GetBaseWindow());
   }
 
+  bool put_window_in_immersive() const {
+    return put_window_in_immersive_;
+  }
+
  private:
+  bool put_window_in_immersive_;
   ui::WindowShowState initial_show_state_;
 
   DISALLOW_COPY_AND_ASSIGN(AcceleratorCommandsPlatformAppFullscreenBrowserTest);
@@ -285,7 +305,8 @@
     EXPECT_TRUE(native_app_window->IsFullscreen());
     ash::wm::WindowState* window_state =
         ash::wm::GetWindowState(native_app_window->GetNativeWindow());
-    EXPECT_TRUE(IsInImmersiveFullscreen(window_state));
+    EXPECT_EQ(put_window_in_immersive(),
+              IsInImmersiveFullscreen(window_state));
 
     ash::accelerators::ToggleFullscreen();
     EXPECT_TRUE(IsInitialShowState(app_window));
diff --git a/chrome/browser/ui/ash/ash_init.cc b/chrome/browser/ui/ash/ash_init.cc
index 8cfd74d..2af2f8a 100644
--- a/chrome/browser/ui/ash/ash_init.cc
+++ b/chrome/browser/ui/ash/ash_init.cc
@@ -12,8 +12,6 @@
 #include "ash/shell.h"
 #include "base/command_line.h"
 #include "chrome/browser/browser_shutdown.h"
-#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 #include "chrome/browser/ui/ash/screenshot_taker.h"
@@ -23,6 +21,8 @@
 
 #if defined(OS_CHROMEOS)
 #include "base/sys_info.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
+#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
 #include "chrome/browser/ui/ash/ime_controller_chromeos.h"
 #include "chrome/browser/ui/ash/volume_controller_chromeos.h"
 #include "chromeos/chromeos_switches.h"
@@ -83,12 +83,8 @@
 }
 
 void CloseAsh() {
-  // If shutdown is initiated by |BrowserX11IOErrorHandler|, don't
-  // try to cleanup resources.
-  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers() &&
-      ash::Shell::HasInstance()) {
+  if (ash::Shell::HasInstance())
     ash::Shell::DeleteInstance();
-  }
 }
 
 }  // namespace chrome
diff --git a/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc b/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc
index 860ea48..4a71cd4 100644
--- a/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc
+++ b/chrome/browser/ui/ash/ash_keyboard_controller_proxy.cc
@@ -7,7 +7,6 @@
 #include "ash/display/display_controller.h"
 #include "ash/shell.h"
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
-#include "chrome/browser/extensions/event_names.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h
index c436b04..c1d52a4 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate.h
+++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -51,7 +51,7 @@
   virtual bool IsIncognitoAllowed() const OVERRIDE;
   virtual bool IsRunningInForcedAppMode() const OVERRIDE;
   virtual void PreInit() OVERRIDE;
-  virtual void Shutdown() OVERRIDE;
+  virtual void PreShutdown() OVERRIDE;
   virtual void Exit() OVERRIDE;
   virtual keyboard::KeyboardControllerProxy*
       CreateKeyboardControllerProxy() OVERRIDE;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
index 39ba0d3..2a481af 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
@@ -27,6 +27,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/signin_error_notifier_factory_ash.h"
 #include "chrome/browser/speech/tts_controller.h"
+#include "chrome/browser/sync/sync_error_notifier_factory_ash.h"
 #include "chrome/browser/ui/ash/chrome_new_window_delegate_chromeos.h"
 #include "chrome/browser/ui/ash/session_state_delegate_chromeos.h"
 #include "chrome/browser/ui/ash/system_tray_delegate_chromeos.h"
@@ -35,8 +36,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/chromeos_switches.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
-#include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/ime/input_method_manager.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/user_metrics.h"
@@ -148,6 +147,11 @@
         ShouldShowAccessibilityMenu();
   }
 
+  virtual bool IsBrailleDisplayConnected() const OVERRIDE {
+    DCHECK(chromeos::AccessibilityManager::Get());
+    return chromeos::AccessibilityManager::Get()->IsBrailleDisplayConnected();
+  }
+
   virtual void SilenceSpokenFeedback() const OVERRIDE {
     TtsController::GetInstance()->Stop();
   }
@@ -237,10 +241,8 @@
       new chromeos::DisplayConfigurationObserver());
 }
 
-void ChromeShellDelegate::Shutdown() {
-  content::RecordAction(base::UserMetricsAction("Shutdown"));
-  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
-      RequestShutdown();
+void ChromeShellDelegate::PreShutdown() {
+  display_configuration_observer_.reset();
 }
 
 ash::SessionStateDelegate* ChromeShellDelegate::CreateSessionStateDelegate() {
@@ -275,8 +277,9 @@
       Profile* profile = content::Details<Profile>(details).ptr();
       if (!chromeos::ProfileHelper::IsSigninProfile(profile) &&
           !profile->IsGuestSession() && !profile->IsManaged()) {
-        // Start the error notifier service to show auth notifications.
+        // Start the error notifier services to show auth/sync notifications.
         SigninErrorNotifierFactory::GetForProfile(profile);
+        SyncErrorNotifierFactory::GetForProfile(profile);
       }
       ash::Shell::GetInstance()->OnLoginUserProfilePrepared();
       break;
@@ -285,11 +288,6 @@
       InitAfterSessionStart();
       ash::Shell::GetInstance()->ShowShelf();
       break;
-    case chrome::NOTIFICATION_APP_TERMINATING:
-      // Let classes unregister themselves as observers of the
-      // ash::Shell singleton before the shell is destroyed.
-      display_configuration_observer_.reset();
-      break;
     default:
       NOTREACHED() << "Unexpected notification " << type;
   }
@@ -302,7 +300,4 @@
   registrar_.Add(this,
                  chrome::NOTIFICATION_SESSION_STARTED,
                  content::NotificationService::AllSources());
-  registrar_.Add(this,
-                 chrome::NOTIFICATION_APP_TERMINATING,
-                 content::NotificationService::AllSources());
 }
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_views.cc b/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
index be2e38d..1ce1cc0 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/ash/chrome_shell_delegate.h"
 
+#include <vector>
+
 #include "ash/accessibility_delegate.h"
 #include "ash/magnifier/magnifier_constants.h"
 #include "ash/media_delegate.h"
@@ -11,11 +13,13 @@
 #include "ash/wm/window_util.h"
 #include "base/command_line.h"
 #include "chrome/browser/accessibility/accessibility_events.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/signin_error_notifier_factory_ash.h"
+#include "chrome/browser/sync/sync_error_notifier_factory_ash.h"
 #include "chrome/browser/ui/ash/chrome_new_window_delegate.h"
 #include "chrome/browser/ui/ash/session_state_delegate_views.h"
 #include "chrome/browser/ui/browser.h"
@@ -121,6 +125,8 @@
     return false;
   }
 
+  virtual bool IsBrailleDisplayConnected() const OVERRIDE { return false; }
+
   virtual void SilenceSpokenFeedback() const OVERRIDE {
   }
 
@@ -156,7 +162,7 @@
 void ChromeShellDelegate::PreInit() {
 }
 
-void ChromeShellDelegate::Shutdown() {
+void ChromeShellDelegate::PreShutdown() {
 }
 
 ash::NewWindowDelegate* ChromeShellDelegate::CreateNewWindowDelegate() {
@@ -195,10 +201,22 @@
                                   const content::NotificationSource& source,
                                   const content::NotificationDetails& details) {
   switch (type) {
-    case chrome::NOTIFICATION_ASH_SESSION_STARTED: {
-      Profile* profile = ProfileManager::GetActiveUserProfile();
-      // Start the error notifier service to show auth notifications.
+    case chrome::NOTIFICATION_PROFILE_ADDED: {
+      // Start the error notifier services to show sync/auth notifications.
+      Profile* profile = content::Source<Profile>(source).ptr();
       SigninErrorNotifierFactory::GetForProfile(profile);
+      SyncErrorNotifierFactory::GetForProfile(profile);
+      break;
+    }
+    case chrome::NOTIFICATION_ASH_SESSION_STARTED: {
+      // Start the error notifier services for the already loaded profiles.
+      const std::vector<Profile*> profiles =
+          g_browser_process->profile_manager()->GetLoadedProfiles();
+      for (std::vector<Profile*>::const_iterator it = profiles.begin();
+           it != profiles.end(); ++it) {
+        SigninErrorNotifierFactory::GetForProfile(*it);
+        SyncErrorNotifierFactory::GetForProfile(*it);
+      }
 
 #if defined(OS_WIN)
       // If we are launched to service a windows 8 search request then let the
@@ -225,7 +243,7 @@
             dummy,
             chrome::startup::IS_NOT_FIRST_RUN);
         startup_impl.Launch(
-            profile,
+            ProfileManager::GetActiveUserProfile(),
             std::vector<GURL>(),
             true,
             chrome::HOST_DESKTOP_TYPE_ASH);
@@ -238,7 +256,7 @@
         }
 
         chrome::ScopedTabbedBrowserDisplayer displayer(
-            profile,
+            ProfileManager::GetActiveUserProfile(),
             chrome::HOST_DESKTOP_TYPE_ASH);
         chrome::AddTabAt(displayer.browser(), GURL(), -1, true);
       }
@@ -254,6 +272,9 @@
 void ChromeShellDelegate::PlatformInit() {
 #if defined(OS_WIN)
   registrar_.Add(this,
+                 chrome::NOTIFICATION_PROFILE_ADDED,
+                 content::NotificationService::AllSources());
+  registrar_.Add(this,
                  chrome::NOTIFICATION_ASH_SESSION_STARTED,
                  content::NotificationService::AllSources());
   registrar_.Add(this,
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/app_window_launcher_controller.cc
index e323e45..e12e8bb 100644
--- a/chrome/browser/ui/ash/launcher/app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/app_window_launcher_controller.cc
@@ -15,8 +15,8 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "extensions/common/extension.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window_event_dispatcher.h"
+#include "ui/wm/public/activation_client.h"
 
 using apps::AppWindow;
 
diff --git a/chrome/browser/ui/ash/launcher/app_window_launcher_controller.h b/chrome/browser/ui/ash/launcher/app_window_launcher_controller.h
index 6b258b1..5f51a62 100644
--- a/chrome/browser/ui/ash/launcher/app_window_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/app_window_launcher_controller.h
@@ -10,8 +10,8 @@
 #include <string>
 
 #include "apps/app_window_registry.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace apps {
 class AppWindow;
diff --git a/chrome/browser/ui/ash/launcher/browser_status_monitor.cc b/chrome/browser/ui/ash/launcher/browser_status_monitor.cc
index ad34095..285d0fc 100644
--- a/chrome/browser/ui/ash/launcher/browser_status_monitor.cc
+++ b/chrome/browser/ui/ash/launcher/browser_status_monitor.cc
@@ -17,10 +17,10 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "content/public/browser/web_contents.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/gfx/screen.h"
+#include "ui/wm/public/activation_client.h"
 
 BrowserStatusMonitor::LocalWebContentsObserver::LocalWebContentsObserver(
     content::WebContents* contents,
diff --git a/chrome/browser/ui/ash/launcher/browser_status_monitor.h b/chrome/browser/ui/ash/launcher/browser_status_monitor.h
index dd73bc1..6e54ac2 100644
--- a/chrome/browser/ui/ash/launcher/browser_status_monitor.h
+++ b/chrome/browser/ui/ash/launcher/browser_status_monitor.h
@@ -16,9 +16,9 @@
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
 #include "content/public/browser/web_contents_observer.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/display_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class Window;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index 8cba80d..25f83d9 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -905,8 +905,9 @@
 
 bool ChromeLauncherController::CanUserModifyShelfAutoHideBehavior(
     aura::Window* root_window) const {
-  return profile_->GetPrefs()->
-      FindPreference(prefs::kShelfAutoHideBehaviorLocal)->IsUserModifiable();
+  return !ash::Shell::GetInstance()->IsMaximizeModeWindowManagerEnabled() &&
+      profile_->GetPrefs()->FindPreference(
+          prefs::kShelfAutoHideBehaviorLocal)->IsUserModifiable();
 }
 
 void ChromeLauncherController::ToggleShelfAutoHideBehavior(
@@ -919,31 +920,6 @@
   return;
 }
 
-void ChromeLauncherController::RemoveTabFromRunningApp(
-    WebContents* tab,
-    const std::string& app_id) {
-  web_contents_to_app_id_.erase(tab);
-  // BrowserShortcutLauncherItemController::UpdateBrowserItemState() will update
-  // the state when no application is associated with the tab.
-  if (app_id.empty())
-    return;
-
-  AppIDToWebContentsListMap::iterator i_app_id =
-      app_id_to_web_contents_list_.find(app_id);
-  if (i_app_id != app_id_to_web_contents_list_.end()) {
-    WebContentsList* tab_list = &i_app_id->second;
-    tab_list->remove(tab);
-    ash::ShelfItemStatus status = ash::STATUS_RUNNING;
-    if (tab_list->empty()) {
-      app_id_to_web_contents_list_.erase(i_app_id);
-      status = ash::STATUS_CLOSED;
-    }
-    ash::ShelfID id = GetShelfIDForAppID(app_id);
-    if (id)
-      SetItemStatus(id, status);
-  }
-}
-
 void ChromeLauncherController::UpdateAppState(content::WebContents* contents,
                                               AppState app_state) {
   std::string app_id = app_tab_helper_->GetAppID(contents);
@@ -957,42 +933,27 @@
   // remove it from the previous app.
   if (web_contents_to_app_id_.find(contents) != web_contents_to_app_id_.end()) {
     std::string last_app_id = web_contents_to_app_id_[contents];
-    if (last_app_id != app_id)
-      RemoveTabFromRunningApp(contents, last_app_id);
-  }
-
-  web_contents_to_app_id_[contents] = app_id;
-
-  if (app_state == APP_STATE_REMOVED) {
-    // The tab has gone away.
-    RemoveTabFromRunningApp(contents, app_id);
-  } else if (!app_id.empty()) {
-    WebContentsList& tab_list(app_id_to_web_contents_list_[app_id]);
-    WebContentsList::const_iterator i_tab =
-        std::find(tab_list.begin(), tab_list.end(), contents);
-
-    if (i_tab == tab_list.end())
-      tab_list.push_back(contents);
-
-    if (app_state == APP_STATE_INACTIVE || app_state == APP_STATE_ACTIVE) {
-      if (i_tab != tab_list.begin()) {
-        // Going to running state, but wasn't the front tab, indicating that a
-        // new tab has already become active.
-        return;
+    if (last_app_id != app_id) {
+      ash::ShelfID id = GetShelfIDForAppID(last_app_id);
+      if (id) {
+        // Since GetAppState() will use |web_contents_to_app_id_| we remove
+        // the connection before calling it.
+        web_contents_to_app_id_.erase(contents);
+        SetItemStatus(id, GetAppState(last_app_id));
       }
     }
+  }
 
-    if (app_state == APP_STATE_ACTIVE || app_state == APP_STATE_WINDOW_ACTIVE) {
-      tab_list.remove(contents);
-      tab_list.push_front(contents);
-    }
+  if (app_state == APP_STATE_REMOVED)
+    web_contents_to_app_id_.erase(contents);
+  else
+    web_contents_to_app_id_[contents] = app_id;
 
-    ash::ShelfID id = GetShelfIDForAppID(app_id);
-    if (id) {
-      // If the window is active, mark the app as active.
-      SetItemStatus(id, app_state == APP_STATE_WINDOW_ACTIVE ?
-          ash::STATUS_ACTIVE : ash::STATUS_RUNNING);
-    }
+  ash::ShelfID id = GetShelfIDForAppID(app_id);
+  if (id) {
+    SetItemStatus(id, (app_state == APP_STATE_WINDOW_ACTIVE ||
+                       app_state == APP_STATE_ACTIVE) ? ash::STATUS_ACTIVE :
+                                                        GetAppState(app_id));
   }
 }
 
@@ -1718,35 +1679,27 @@
   SetShelfAlignmentFromPrefs();
 }
 
-WebContents* ChromeLauncherController::GetLastActiveWebContents(
-    const std::string& app_id) {
-  AppIDToWebContentsListMap::iterator i =
-      app_id_to_web_contents_list_.find(app_id);
-  if (i == app_id_to_web_contents_list_.end())
-    return NULL;
-
-  // There are many crash records (crbug.com/341250) which indicate that the
-  // app_id_to_web_contents_list_ contains deleted content entries - so there
-  // must be a way that the content does not get properly updated. To fix
-  // M33 and M34 we filter out the invalid items here, but this should be
-  // addressed by a later patch correctly. Looking at the code however, the
-  // real culprit is possibly BrowserStatusMonitor::UpdateAppItemState which
-  // does not call "UpdateAppState(.., APP_STATE_REMOVED)" because due to a
-  // Browser::SwapTabContent operation it isn't able to get the browser. I
-  // think that the real patch is to call anyway when APP_STATE_REMOVED is
-  // requested, but for a backport that seems risky.
-  WebContentsList* list = &i->second;
-  while (!list->empty()) {
-    WebContents* contents = *list->begin();
-    if (chrome::FindBrowserWithWebContents(contents))
-      return contents;
-    list->erase(list->begin());
-    // This might not be necessary, but since we do not know why the lists
-    // diverged we also erase it since it cannot be correct either.
-    web_contents_to_app_id_.erase(contents);
+ash::ShelfItemStatus ChromeLauncherController::GetAppState(
+    const::std::string& app_id) {
+  ash::ShelfItemStatus status = ash::STATUS_CLOSED;
+  for (WebContentsToAppIDMap::iterator it = web_contents_to_app_id_.begin();
+       it != web_contents_to_app_id_.end();
+       ++it) {
+    if (it->second == app_id) {
+      Browser* browser = chrome::FindBrowserWithWebContents(it->first);
+      // There should never be an item in our |web_contents_to_app_id_| list
+      // which got deleted already. If it is, it is likely that
+      // BrowserStatusMonitor forgot to inform us of that change.
+      DCHECK(browser);
+      if (browser->window()->IsActive()) {
+        return browser->tab_strip_model()->GetActiveWebContents() == it->first ?
+            ash::STATUS_ACTIVE : ash::STATUS_RUNNING;
+      } else {
+        status = ash::STATUS_RUNNING;
+      }
+    }
   }
-  app_id_to_web_contents_list_.erase(app_id);
-  return NULL;
+  return status;
 }
 
 ash::ShelfID ChromeLauncherController::InsertAppLauncherItem(
@@ -1765,15 +1718,10 @@
   item.type = shelf_item_type;
   item.image = extensions::IconsInfo::GetDefaultAppIcon();
 
-  WebContents* active_tab = GetLastActiveWebContents(app_id);
-  if (active_tab) {
-    Browser* browser = chrome::FindBrowserWithWebContents(active_tab);
-    DCHECK(browser);
-    if (browser->window()->IsActive())
-      status = ash::STATUS_ACTIVE;
-    else
-      status = ash::STATUS_RUNNING;
-  }
+  ash::ShelfItemStatus new_state = GetAppState(app_id);
+  if (new_state != ash::STATUS_CLOSED)
+    status = new_state;
+
   item.status = status;
 
   model_->AddAt(index, item);
@@ -1880,9 +1828,9 @@
     ash::ShelfItemType type = model_->items()[i].type;
     if (type == ash::TYPE_APP_SHORTCUT ||
         ((is_app_list || alternate) && type == ash::TYPE_APP_LIST) ||
-        type == ash::TYPE_BROWSER_SHORTCUT ||
-        type == ash::TYPE_WINDOWED_APP)
+        type == ash::TYPE_BROWSER_SHORTCUT) {
       return i;
+    }
   }
   return 0;
 }
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
index 78fd95f..e0bdadc 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.h
@@ -263,10 +263,6 @@
   // user is not allowed to modify the auto-hide behavior.
   void ToggleShelfAutoHideBehavior(aura::Window* root_window);
 
-  // The tab no longer represents its previously identified application.
-  void RemoveTabFromRunningApp(content::WebContents* tab,
-                               const std::string& app_id);
-
   // Notify the controller that the state of an non platform app's tabs
   // have changed,
   void UpdateAppState(content::WebContents* contents, AppState app_state);
@@ -414,8 +410,6 @@
   friend class LauncherPlatformAppBrowserTest;
 
   typedef std::map<ash::ShelfID, LauncherItemController*> IDToItemControllerMap;
-  typedef std::list<content::WebContents*> WebContentsList;
-  typedef std::map<std::string, WebContentsList> AppIDToWebContentsListMap;
   typedef std::map<content::WebContents*, std::string> WebContentsToAppIDMap;
 
   // Remembers / restores list of running applications.
@@ -464,8 +458,10 @@
   // Sets both of auto-hide behavior and alignment from prefs.
   void SetShelfBehaviorsFromPrefs();
 
-  // Returns the most recently active web contents for an app.
-  content::WebContents* GetLastActiveWebContents(const std::string& app_id);
+  // Returns the shelf item status for the given |app_id|, which can be either
+  // STATUS_ACTIVE (if the app is active), STATUS_RUNNING (if there is such an
+  // app) or STATUS_CLOSED.
+  ash::ShelfItemStatus GetAppState(const::std::string& app_id);
 
   // Creates an app launcher to insert at |index|. Note that |index| may be
   // adjusted by the model to meet ordering constraints.
@@ -548,9 +544,6 @@
 
   IDToItemControllerMap id_to_item_controller_map_;
 
-  // Maintains activation order of web contents for each app.
-  AppIDToWebContentsListMap app_id_to_web_contents_list_;
-
   // Direct access to app_id for a web contents.
   WebContentsToAppIDMap web_contents_to_app_id_;
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
index a17509e..208337a 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -44,6 +44,7 @@
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/aura/client/window_tree_client.h"
 #include "ui/base/models/menu_model.h"
 
 #if defined(OS_CHROMEOS)
@@ -58,6 +59,7 @@
 #include "chrome/browser/ui/ash/launcher/browser_status_monitor.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
 #include "chrome/common/chrome_constants.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -722,7 +724,9 @@
     native_window_->SetType(ui::wm::WINDOW_TYPE_POPUP);
     native_window_->Init(aura::WINDOW_LAYER_TEXTURED);
     native_window_->Show();
-
+    aura::client::ParentWindowWithContext(native_window_.get(),
+                                          ash::Shell::GetPrimaryRootWindow(),
+                                          gfx::Rect(10, 10, 20, 30));
     Browser::CreateParams params = Browser::CreateParams::CreateForApp(
         Browser::TYPE_POPUP,
         kCrxAppPrefix + app_name,
@@ -774,6 +778,8 @@
     destroyed_watcher.Wait();
   }
 
+  apps::AppWindow* window() { return window_; }
+
  private:
   // The app window which represents the application. Note that the window
   // deletes itself asynchronously after window_->GetBaseWindow()->Close() gets
@@ -860,6 +866,10 @@
     EXPECT_TRUE(profile);
     // Remember the profile name so that we can destroy it upon destruction.
     created_profiles_[profile] = profile_name;
+    if (chrome::MultiUserWindowManager::GetInstance())
+      chrome::MultiUserWindowManager::GetInstance()->AddUser(profile);
+    if (launcher_controller_)
+      launcher_controller_->AdditionalUserAddedToSession(profile);
     return profile;
   }
 
@@ -867,6 +877,11 @@
   void SwitchActiveUser(const std::string& name) {
     session_delegate()->SwitchActiveUser(name);
     GetFakeUserManager()->SwitchActiveUser(name);
+    chrome::MultiUserWindowManagerChromeOS* manager =
+        static_cast<chrome::MultiUserWindowManagerChromeOS*>(
+            chrome::MultiUserWindowManager::GetInstance());
+    manager->SetAnimationsForTest(true);
+    manager->ActiveUserChanged(name);
     launcher_controller_->browser_status_monitor_for_test()->
         ActiveUserChanged(name);
     launcher_controller_->app_window_controller_for_test()->
@@ -2445,6 +2460,63 @@
   SwitchActiveUser(profile()->GetProfileName());
   EXPECT_EQ(2, model_->item_count());
 }
+
+// Check that V2 applications will be made visible on the target desktop if
+// another window of the same type got previously teleported there.
+TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
+       V2AppFollowsTeleportedWindow) {
+  InitLauncherController();
+  chrome::MultiUserWindowManager* manager =
+      chrome::MultiUserWindowManager::GetInstance();
+
+  // Create and add three users / profiles, and go to #1's desktop.
+  TestingProfile* profile1 = CreateMultiUserProfile("user-1");
+  TestingProfile* profile2 = CreateMultiUserProfile("user-2");
+  TestingProfile* profile3 = CreateMultiUserProfile("user-3");
+  SwitchActiveUser(profile1->GetProfileName());
+
+  // A v2 app for user #1 should be shown first and get hidden when switching to
+  // desktop #2.
+  V2App v2_app_1(profile1, extension1_);
+  EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
+  SwitchActiveUser(profile2->GetProfileName());
+  EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
+
+  // Add a v2 app for user #1 while on desktop #2 should not be shown.
+  V2App v2_app_2(profile1, extension1_);
+  EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
+  EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
+
+  // Teleport the app from user #1 to the desktop #2 should show it.
+  manager->ShowWindowForUser(v2_app_1.window()->GetNativeWindow(),
+                             profile2->GetProfileName());
+  EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
+  EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
+
+  // Creating a new application for user #1 on desktop #2 should teleport it
+  // there automatically.
+  V2App v2_app_3(profile1, extension1_);
+  EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
+  EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
+  EXPECT_TRUE(v2_app_3.window()->GetNativeWindow()->IsVisible());
+
+  // Switching back to desktop#1 and creating an app for user #1 should move
+  // the app on desktop #1.
+  SwitchActiveUser(profile1->GetProfileName());
+  V2App v2_app_4(profile1, extension1_);
+  EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
+  EXPECT_TRUE(v2_app_2.window()->GetNativeWindow()->IsVisible());
+  EXPECT_FALSE(v2_app_3.window()->GetNativeWindow()->IsVisible());
+  EXPECT_TRUE(v2_app_4.window()->GetNativeWindow()->IsVisible());
+
+  // Switching to desktop #3 and create an app for user #1 there should land on
+  // his own desktop (#1).
+  SwitchActiveUser(profile3->GetProfileName());
+  V2App v2_app_5(profile1, extension1_);
+  EXPECT_FALSE(v2_app_5.window()->GetNativeWindow()->IsVisible());
+  SwitchActiveUser(profile1->GetProfileName());
+  EXPECT_TRUE(v2_app_5.window()->GetNativeWindow()->IsVisible());
+}
 #endif  // defined(OS_CHROMEOS)
 
 // Checks that the generated menu list properly activates items.
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
index 92cb916..4369c3d 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -171,9 +171,9 @@
   // fullscreen because it is confusing when the preference appears not to
   // apply.
   if (!IsFullScreenMode() &&
-        controller_->CanUserModifyShelfAutoHideBehavior(root_window_)) {
+      controller_->CanUserModifyShelfAutoHideBehavior(root_window_)) {
     AddCheckItemWithStringId(MENU_AUTO_HIDE,
-                              IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE);
+                             IDS_ASH_SHELF_CONTEXT_MENU_AUTO_HIDE);
   }
   if (ash::ShelfWidget::ShelfAlignmentAllowed()) {
     AddSubMenuWithStringId(MENU_ALIGNMENT_MENU,
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.h b/chrome/browser/ui/ash/launcher/launcher_context_menu.h
index f2d29f6..429b6eb 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu.h
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.h
@@ -69,6 +69,9 @@
   FRIEND_TEST_ALL_PREFIXES(
       LauncherContextMenuTest,
       NewWindowMenuIsDisabledWhenIncognitoModeForced);
+  FRIEND_TEST_ALL_PREFIXES(
+      LauncherContextMenuTest,
+      NoAutoHideOptionInMaximizedMode);
 
   enum MenuItem {
     MENU_OPEN_NEW,
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
index 6c885e0..4250223 100644
--- a/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/launcher_context_menu_unittest.cc
@@ -7,6 +7,7 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_item_types.h"
 #include "ash/shelf/shelf_model.h"
+#include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "base/prefs/pref_service.h"
 #include "chrome/app/chrome_command_ids.h"
@@ -108,3 +109,28 @@
       menu.get(), LauncherContextMenu::MENU_NEW_WINDOW));
   EXPECT_FALSE(menu->IsCommandIdEnabled(LauncherContextMenu::MENU_NEW_WINDOW));
 }
+
+// Verifies that the "auto hide" menu items are not present in maximized mode.
+TEST_F(LauncherContextMenuTest, NoAutoHideOptionInMaximizedMode) {
+  {
+    scoped_ptr<LauncherContextMenu> menu(
+        CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT));
+    ASSERT_TRUE(IsItemPresentInMenu(
+        menu.get(), LauncherContextMenu::MENU_AUTO_HIDE));
+  }
+  ash::Shell::GetInstance()->EnableMaximizeModeWindowManager(true);
+  {
+    scoped_ptr<LauncherContextMenu> menu(
+        CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT));
+    ASSERT_FALSE(IsItemPresentInMenu(
+        menu.get(), LauncherContextMenu::MENU_AUTO_HIDE));
+  }
+  ash::Shell::GetInstance()->EnableMaximizeModeWindowManager(false);
+  {
+    scoped_ptr<LauncherContextMenu> menu(
+        CreateLauncherContextMenu(ash::TYPE_BROWSER_SHORTCUT));
+    ASSERT_TRUE(IsItemPresentInMenu(
+        menu.get(), LauncherContextMenu::MENU_AUTO_HIDE));
+  }
+}
+
diff --git a/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.cc
index 1af5ce5..4f44d57 100644
--- a/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.cc
@@ -8,7 +8,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
+#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
 #include "chrome/browser/ui/host_desktop.h"
+#include "ui/aura/window.h"
 
 namespace {
 
@@ -74,8 +76,24 @@
     return;
   app_window_list_.push_back(app_window);
   Profile* profile = Profile::FromBrowserContext(app_window->browser_context());
-  if (multi_user_util::IsProfileFromActiveUser(profile))
+  if (multi_user_util::IsProfileFromActiveUser(profile)) {
     RegisterApp(app_window);
+  } else {
+    // If the window got created for a non active user but the user allowed to
+    // teleport to the current user's desktop, we teleport it now.
+    if (UserHasAppOnActiveDesktop(app_window)) {
+      chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
+          app_window->GetNativeWindow(),
+          multi_user_util::GetCurrentUserId());
+      if (app_window->GetNativeWindow()->type() == ui::wm::WINDOW_TYPE_PANEL &&
+          !app_window->GetNativeWindow()->layer()->GetTargetOpacity()) {
+        // The panel layout manager only manages windows which are anchored.
+        // Since this window did never had an anchor, it would stay hidden. We
+        // therefore make it visible now.
+        app_window->GetNativeWindow()->layer()->SetOpacity(1.0f);
+      }
+    }
+  }
 }
 
 void MultiProfileAppWindowLauncherController::OnAppWindowRemoved(
@@ -93,3 +111,26 @@
   DCHECK(it != app_window_list_.end());
   app_window_list_.erase(it);
 }
+
+bool MultiProfileAppWindowLauncherController::UserHasAppOnActiveDesktop(
+    apps::AppWindow* app_window) {
+  const std::string& app_id = app_window->extension_id();
+  content::BrowserContext* app_context = app_window->browser_context();
+  DCHECK(!app_context->IsOffTheRecord());
+  const std::string& current_user = multi_user_util::GetCurrentUserId();
+  chrome::MultiUserWindowManager* manager =
+      chrome::MultiUserWindowManager::GetInstance();
+  for (AppWindowList::iterator it = app_window_list_.begin();
+       it != app_window_list_.end();
+       ++it) {
+    apps::AppWindow* other_window = *it;
+    DCHECK(!other_window->browser_context()->IsOffTheRecord());
+    if (manager->IsWindowOnDesktopOfUser(other_window->GetNativeWindow(),
+                                         current_user) &&
+        app_id == other_window->extension_id() &&
+        app_context == other_window->browser_context()) {
+      return true;
+    }
+  }
+  return false;
+}
diff --git a/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.h b/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.h
index e1b9325..c31862c 100644
--- a/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.h
+++ b/chrome/browser/ui/ash/launcher/multi_profile_app_window_launcher_controller.h
@@ -28,6 +28,10 @@
   typedef std::vector<apps::AppWindow*> AppWindowList;
   typedef std::vector<apps::AppWindowRegistry*> AppWindowRegistryList;
 
+  // Returns true if the owner of the given |app_window| has a window teleported
+  // of the |app_window|'s application type to the current desktop.
+  bool UserHasAppOnActiveDesktop(apps::AppWindow* app_window);
+
   // A list of all app windows for all users.
   AppWindowList app_window_list_;
 
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
index 5a9ea72..d85677d 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "content/public/browser/notification_service.h"
 #include "google_apis/gaia/gaia_auth_util.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -47,6 +46,7 @@
 #include "ui/wm/core/transient_window_manager.h"
 #include "ui/wm/core/window_animations.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace {
 
diff --git a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
index e59c2ce..bc8aea5 100644
--- a/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos_unittest.cc
@@ -17,11 +17,11 @@
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_profile.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/ui_base_types.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace ash {
 namespace test {
diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
index 4dd49cc..2341781 100644
--- a/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.cc
@@ -38,6 +38,16 @@
   return chromeos::UserManager::Get()->GetProfileByUser(user);
 }
 
+content::BrowserContext*
+SessionStateDelegateChromeos::GetBrowserContextForWindow(
+    aura::Window* window) {
+  const std::string& user_id =
+      chrome::MultiUserWindowManager::GetInstance()->GetWindowOwner(window);
+  const chromeos::User* user = chromeos::UserManager::Get()->FindUser(user_id);
+  DCHECK(user);
+  return chromeos::UserManager::Get()->GetProfileByUser(user);
+}
+
 int SessionStateDelegateChromeos::GetMaximumNumberOfLoggedInUsers() const {
   // We limit list of logged in users to 10 due to memory constraints.
   // Note that 10 seems excessive, but we want to test how many users are
diff --git a/chrome/browser/ui/ash/session_state_delegate_chromeos.h b/chrome/browser/ui/ash/session_state_delegate_chromeos.h
index 89a7d95..b6dc922 100644
--- a/chrome/browser/ui/ash/session_state_delegate_chromeos.h
+++ b/chrome/browser/ui/ash/session_state_delegate_chromeos.h
@@ -25,6 +25,8 @@
   // ash::SessionStateDelegate:
   virtual content::BrowserContext* GetBrowserContextByIndex(
       ash::MultiProfileIndex index) OVERRIDE;
+  virtual content::BrowserContext* GetBrowserContextForWindow(
+      aura::Window* window) OVERRIDE;
   virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE;
   virtual int NumberOfLoggedInUsers() const OVERRIDE;
   virtual bool IsActiveUserSessionStarted() const OVERRIDE;
diff --git a/chrome/browser/ui/ash/session_state_delegate_views.cc b/chrome/browser/ui/ash/session_state_delegate_views.cc
index cac69f9..c8c1033 100644
--- a/chrome/browser/ui/ash/session_state_delegate_views.cc
+++ b/chrome/browser/ui/ash/session_state_delegate_views.cc
@@ -26,6 +26,12 @@
   return NULL;
 }
 
+content::BrowserContext* SessionStateDelegate::GetBrowserContextForWindow(
+    aura::Window* window) {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
 int SessionStateDelegate::GetMaximumNumberOfLoggedInUsers() const {
   return 3;
 }
diff --git a/chrome/browser/ui/ash/session_state_delegate_views.h b/chrome/browser/ui/ash/session_state_delegate_views.h
index c9a4f08..549326f 100644
--- a/chrome/browser/ui/ash/session_state_delegate_views.h
+++ b/chrome/browser/ui/ash/session_state_delegate_views.h
@@ -22,6 +22,8 @@
   // ash::SessionStateDelegate:
   virtual content::BrowserContext* GetBrowserContextByIndex(
       ash::MultiProfileIndex index) OVERRIDE;
+  virtual content::BrowserContext* GetBrowserContextForWindow(
+      aura::Window* window) OVERRIDE;
   virtual int GetMaximumNumberOfLoggedInUsers() const OVERRIDE;
   virtual int NumberOfLoggedInUsers() const OVERRIDE;
   virtual bool IsActiveUserSessionStarted() const OVERRIDE;
diff --git a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
index 2c4c359..f39af56 100644
--- a/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/system_tray_delegate_chromeos.cc
@@ -89,6 +89,7 @@
 #include "chrome/browser/ui/webui/chromeos/charger_replacement_handler.h"
 #include "chrome/browser/ui/webui/chromeos/mobile_setup_dialog.h"
 #include "chrome/browser/upgrade_detector.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
@@ -218,21 +219,16 @@
   // TODO(sad): Do something?
 }
 
-// Shows the settings sub page in the last active browser. If there is no such
-// browser, creates a new browser with the settings sub page.
-void ShowSettingsSubPageForAppropriateBrowser(const std::string& sub_page,
-                                              Profile* profile) {
-  chrome::ScopedTabbedBrowserDisplayer displayer(profile,
-                                                 chrome::HOST_DESKTOP_TYPE_ASH);
-  chrome::ShowSettingsSubPage(displayer.browser(), sub_page);
+void ShowSettingsSubPageForActiveUser(const std::string& sub_page) {
+  chrome::ShowSettingsSubPageForProfile(
+      ProfileManager::GetActiveUserProfile(), sub_page);
 }
 
 void ShowNetworkSettingsPage(const std::string& service_path) {
   std::string page = chrome::kInternetOptionsSubPage;
   page += "?servicePath=" + net::EscapeUrlEncodedData(service_path, true);
   content::RecordAction(base::UserMetricsAction("OpenInternetOptionsDialog"));
-  ShowSettingsSubPageForAppropriateBrowser(
-      page, ProfileManager::GetPrimaryUserProfile());
+  ShowSettingsSubPageForActiveUser(page);
 }
 
 void OnAcceptMultiprofilesIntro(bool no_show_again) {
@@ -428,9 +424,7 @@
 void SystemTrayDelegateChromeOS::ChangeProfilePicture() {
   content::RecordAction(
       base::UserMetricsAction("OpenChangeProfilePictureDialog"));
-  ShowSettingsSubPageForAppropriateBrowser(
-      chrome::kChangeProfilePictureSubPage,
-      ProfileManager::GetActiveUserProfile());
+  ShowSettingsSubPageForActiveUser(chrome::kChangeProfilePictureSubPage);
 }
 
 const std::string SystemTrayDelegateChromeOS::GetEnterpriseDomain() const {
@@ -478,9 +472,7 @@
 }
 
 void SystemTrayDelegateChromeOS::ShowSettings() {
-  chrome::ScopedTabbedBrowserDisplayer displayer(
-      ProfileManager::GetActiveUserProfile(), chrome::HOST_DESKTOP_TYPE_ASH);
-  chrome::ShowSettings(displayer.browser());
+  ShowSettingsSubPageForActiveUser("");
 }
 
 bool SystemTrayDelegateChromeOS::ShouldShowSettings() {
@@ -493,8 +485,7 @@
       std::string(chrome::kSearchSubPage) + "#" +
       l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_DATETIME);
   // Everybody can change the time zone (even though it is a device setting).
-  ShowSettingsSubPageForAppropriateBrowser(
-      sub_page, ProfileManager::GetActiveUserProfile());
+  ShowSettingsSubPageForActiveUser(sub_page);
 }
 
 void SystemTrayDelegateChromeOS::ShowNetworkSettings(
@@ -510,8 +501,7 @@
 
 void SystemTrayDelegateChromeOS::ShowDisplaySettings() {
   content::RecordAction(base::UserMetricsAction("ShowDisplayOptions"));
-  ShowSettingsSubPageForAppropriateBrowser(
-      kDisplaySettingsSubPageName, ProfileManager::GetActiveUserProfile());
+  ShowSettingsSubPageForActiveUser(kDisplaySettingsSubPageName);
 }
 
 void SystemTrayDelegateChromeOS::ShowChromeSlow() {
@@ -535,12 +525,12 @@
     return true;
 
   GURL visible_url = active_contents->GetLastCommittedURL();
-  std::string display_settings_url =
-      std::string(chrome::kChromeUISettingsURL) + kDisplaySettingsSubPageName;
-  std::string display_overscan_url = std::string(chrome::kChromeUISettingsURL) +
-                                     kDisplayOverscanSettingsSubPageName;
-  return (visible_url.spec() != display_settings_url) &&
-         (visible_url.spec() != display_overscan_url);
+  GURL display_settings_url =
+      chrome::GetSettingsUrl(kDisplaySettingsSubPageName);
+  GURL display_overscan_url =
+      chrome::GetSettingsUrl(kDisplayOverscanSettingsSubPageName);
+  return (visible_url != display_settings_url &&
+          visible_url != display_overscan_url);
 }
 
 void SystemTrayDelegateChromeOS::ShowDriveSettings() {
@@ -556,8 +546,7 @@
 
 void SystemTrayDelegateChromeOS::ShowIMESettings() {
   content::RecordAction(base::UserMetricsAction("OpenLanguageOptionsDialog"));
-  ShowSettingsSubPageForAppropriateBrowser(
-      chrome::kLanguageOptionsSubPage, ProfileManager::GetActiveUserProfile());
+  ShowSettingsSubPageForActiveUser(chrome::kLanguageOptionsSubPage);
 }
 
 void SystemTrayDelegateChromeOS::ShowHelp() {
@@ -577,8 +566,7 @@
   std::string sub_page = std::string(chrome::kSearchSubPage) + "#" +
                          l10n_util::GetStringUTF8(
                              IDS_OPTIONS_SETTINGS_SECTION_TITLE_ACCESSIBILITY);
-  ShowSettingsSubPageForAppropriateBrowser(
-      sub_page, ProfileManager::GetActiveUserProfile());
+  ShowSettingsSubPageForActiveUser(sub_page);
 }
 
 void SystemTrayDelegateChromeOS::ShowPublicAccountInfo() {
@@ -840,8 +828,7 @@
   std::string sub_page =
       std::string(chrome::kSearchSubPage) + "#" +
       l10n_util::GetStringUTF8(IDS_OPTIONS_SETTINGS_SECTION_TITLE_BLUETOOTH);
-  ShowSettingsSubPageForAppropriateBrowser(
-      sub_page, ProfileManager::GetPrimaryUserProfile());
+  ShowSettingsSubPageForActiveUser(sub_page);
 }
 
 void SystemTrayDelegateChromeOS::ToggleBluetooth() {
diff --git a/chrome/browser/ui/ash/volume_controller_browsertest_chromeos.cc b/chrome/browser/ui/ash/volume_controller_browsertest_chromeos.cc
index ed9b5ed..40004c2 100644
--- a/chrome/browser/ui/ash/volume_controller_browsertest_chromeos.cc
+++ b/chrome/browser/ui/ash/volume_controller_browsertest_chromeos.cc
@@ -4,10 +4,12 @@
 
 #include <vector>
 
+#include "ash/accessibility_delegate.h"
 #include "ash/ash_switches.h"
 #include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
 #include "chrome/browser/ui/ash/volume_controller_chromeos.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/audio/chromeos_sounds.h"
@@ -166,14 +168,14 @@
     media::SoundsManager::InitializeForTesting(sounds_manager_);
   }
 
-  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
-    VolumeControllerTest::SetUpCommandLine(command_line);
-    command_line->AppendSwitch(ash::switches::kAshEnableSystemSounds);
+  void EnableSpokenFeedback(bool enabled) {
+    chromeos::AccessibilityManager* manager =
+        chromeos::AccessibilityManager::Get();
+    manager->EnableSpokenFeedback(enabled, ash::A11Y_NOTIFICATION_NONE);
   }
 
   bool is_sound_initialized() const {
-    return sounds_manager_->is_sound_initialized(
-        chromeos::SOUND_VOLUME_ADJUST);
+    return sounds_manager_->is_sound_initialized(chromeos::SOUND_VOLUME_ADJUST);
   }
 
   int num_play_requests() const {
@@ -186,8 +188,23 @@
   DISALLOW_COPY_AND_ASSIGN(VolumeControllerSoundsTest);
 };
 
-IN_PROC_BROWSER_TEST_F(VolumeControllerSoundsTest, VolumeAdjustSounds) {
+IN_PROC_BROWSER_TEST_F(VolumeControllerSoundsTest, Simple) {
+  audio_handler_->SetOutputVolumePercent(50);
+
+  EnableSpokenFeedback(false /* enabled */);
+  VolumeUp();
+  VolumeDown();
+  EXPECT_EQ(0, num_play_requests());
+
+  EnableSpokenFeedback(true /* enabled */);
+  VolumeUp();
+  VolumeDown();
+  EXPECT_EQ(2, num_play_requests());
+}
+
+IN_PROC_BROWSER_TEST_F(VolumeControllerSoundsTest, EdgeCases) {
   EXPECT_TRUE(is_sound_initialized());
+  EnableSpokenFeedback(true /* enabled */);
 
   // Check that sound is played on volume up and volume down.
   audio_handler_->SetOutputVolumePercent(50);
diff --git a/chrome/browser/ui/ash/volume_controller_chromeos.cc b/chrome/browser/ui/ash/volume_controller_chromeos.cc
index b8bd9bb..8acade0 100644
--- a/chrome/browser/ui/ash/volume_controller_chromeos.cc
+++ b/chrome/browser/ui/ash/volume_controller_chromeos.cc
@@ -30,7 +30,7 @@
 
 void PlayVolumeAdjustSound() {
   if (VolumeAdjustSoundEnabled())
-    ash::PlaySystemSoundAlways(chromeos::SOUND_VOLUME_ADJUST);
+    ash::PlaySystemSoundIfSpokenFeedback(chromeos::SOUND_VOLUME_ADJUST);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc b/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc
index b72fd14..dba4955 100644
--- a/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc
+++ b/chrome/browser/ui/aura/chrome_browser_main_extra_parts_aura.cc
@@ -16,7 +16,6 @@
 #include "ui/aura/env.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/screen.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #include "ui/views/widget/native_widget_aura.h"
 
 #if defined(OS_LINUX)
@@ -33,6 +32,10 @@
 #endif  // defined(OS_WIN)
 #endif  // defined(USE_ASH)
 
+#if !defined(OS_CHROMEOS)
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
+#endif
+
 namespace {
 
 #if !defined(OS_CHROMEOS) && defined(USE_ASH)
diff --git a/chrome/browser/ui/auto_login_infobar_delegate.cc b/chrome/browser/ui/auto_login_infobar_delegate.cc
new file mode 100644
index 0000000..6e5bb74
--- /dev/null
+++ b/chrome/browser/ui/auto_login_infobar_delegate.cc
@@ -0,0 +1,235 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/auto_login_infobar_delegate.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/google/google_util.h"
+#include "chrome/browser/infobars/infobar.h"
+#include "chrome/browser/infobars/infobar_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/ui/sync/sync_promo_ui.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/url_constants.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/common/referrer.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/ubertoken_fetcher.h"
+#include "grit/chromium_strings.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources.h"
+#include "net/base/escape.h"
+#include "net/url_request/url_request.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if defined(OS_ANDROID)
+#include "chrome/browser/ui/android/infobars/auto_login_infobar_delegate_android.h"
+#endif
+
+
+// AutoLoginRedirector --------------------------------------------------------
+
+namespace {
+
+// This class is created by the AutoLoginInfoBarDelegate when the user wishes to
+// auto-login.  It holds context information needed while re-issuing service
+// tokens using the OAuth2TokenService, gets the browser cookies with the
+// TokenAuth API, and finally redirects the user to the correct page.
+class AutoLoginRedirector : public UbertokenConsumer,
+                            public content::WebContentsObserver {
+ public:
+  AutoLoginRedirector(content::WebContents* web_contents,
+                      const std::string& args);
+  virtual ~AutoLoginRedirector();
+
+ private:
+  // Overriden from UbertokenConsumer:
+  virtual void OnUbertokenSuccess(const std::string& token) OVERRIDE;
+  virtual void OnUbertokenFailure(const GoogleServiceAuthError& error) OVERRIDE;
+
+  // Implementation of content::WebContentsObserver
+  virtual void WebContentsDestroyed(
+      content::WebContents* web_contents) OVERRIDE;
+
+  // Redirect tab to MergeSession URL, logging the user in and navigating
+  // to the desired page.
+  void RedirectToMergeSession(const std::string& token);
+
+  const std::string args_;
+  scoped_ptr<UbertokenFetcher> ubertoken_fetcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoLoginRedirector);
+};
+
+AutoLoginRedirector::AutoLoginRedirector(
+    content::WebContents* web_contents,
+    const std::string& args)
+    : content::WebContentsObserver(web_contents),
+      args_(args) {
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+  ProfileOAuth2TokenService* token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+  SigninManagerBase* signin_manager =
+      SigninManagerFactory::GetInstance()->GetForProfile(profile);
+  ubertoken_fetcher_.reset(new UbertokenFetcher(token_service,
+                                                this,
+                                                profile->GetRequestContext()));
+  ubertoken_fetcher_->StartFetchingToken(
+      signin_manager->GetAuthenticatedAccountId());
+}
+
+AutoLoginRedirector::~AutoLoginRedirector() {
+}
+
+void AutoLoginRedirector::WebContentsDestroyed(
+    content::WebContents* web_contents) {
+  // The WebContents that started this has been destroyed. The request must be
+  // cancelled and this object must be deleted.
+  ubertoken_fetcher_.reset();
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void AutoLoginRedirector::OnUbertokenSuccess(const std::string& token) {
+  RedirectToMergeSession(token);
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void AutoLoginRedirector::OnUbertokenFailure(
+    const GoogleServiceAuthError& error) {
+  LOG(WARNING) << "AutoLoginRedirector: token request failed";
+  base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
+void AutoLoginRedirector::RedirectToMergeSession(const std::string& token) {
+  // TODO(rogerta): what is the correct page transition?
+  web_contents()->GetController().LoadURL(
+      GaiaUrls::GetInstance()->merge_session_url().Resolve(
+          "?source=chrome&uberauth=" + token + "&" + args_),
+      content::Referrer(), content::PAGE_TRANSITION_AUTO_BOOKMARK,
+      std::string());
+}
+
+}  // namespace
+
+
+// AutoLoginInfoBarDelegate ---------------------------------------------------
+
+// static
+bool AutoLoginInfoBarDelegate::Create(content::WebContents* web_contents,
+                                      const Params& params) {
+  // If |web_contents| is hosted in a WebDialog, there may be no infobar
+  // service.
+  InfoBarService* infobar_service =
+    InfoBarService::FromWebContents(web_contents);
+  if (!infobar_service)
+    return false;
+
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+#if defined(OS_ANDROID)
+  typedef AutoLoginInfoBarDelegateAndroid Delegate;
+#else
+  typedef AutoLoginInfoBarDelegate Delegate;
+#endif
+  return !!infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
+      scoped_ptr<ConfirmInfoBarDelegate>(new Delegate(params, profile))));
+}
+
+AutoLoginInfoBarDelegate::AutoLoginInfoBarDelegate(const Params& params,
+                                                   Profile* profile)
+    : ConfirmInfoBarDelegate(),
+      params_(params),
+      profile_(profile),
+      button_pressed_(false) {
+  RecordHistogramAction(SHOWN);
+
+  // The AutoLogin infobar is shown in incognito mode on Android, so a
+  // SigninManager isn't guaranteed to exist for |profile_|.
+  SigninManagerBase* signin_manager =
+      SigninManagerFactory::GetInstance()->GetForProfile(profile_);
+  if (signin_manager)
+    signin_manager->AddObserver(this);
+}
+
+AutoLoginInfoBarDelegate::~AutoLoginInfoBarDelegate() {
+  // The AutoLogin infobar is shown in incognito mode on Android, so a
+  // SigninManager isn't guaranteed to exist for |profile_|.
+  SigninManagerBase* signin_manager =
+      SigninManagerFactory::GetInstance()->GetForProfile(profile_);
+  if (signin_manager)
+    signin_manager->RemoveObserver(this);
+
+  if (!button_pressed_)
+    RecordHistogramAction(IGNORED);
+}
+
+void AutoLoginInfoBarDelegate::InfoBarDismissed() {
+  RecordHistogramAction(DISMISSED);
+  button_pressed_ = true;
+}
+
+int AutoLoginInfoBarDelegate::GetIconID() const {
+  return IDR_INFOBAR_AUTOLOGIN;
+}
+
+InfoBarDelegate::Type AutoLoginInfoBarDelegate::GetInfoBarType() const {
+  return PAGE_ACTION_TYPE;
+}
+
+AutoLoginInfoBarDelegate*
+    AutoLoginInfoBarDelegate::AsAutoLoginInfoBarDelegate() {
+  return this;
+}
+
+base::string16 AutoLoginInfoBarDelegate::GetMessageText() const {
+  return l10n_util::GetStringFUTF16(IDS_AUTOLOGIN_INFOBAR_MESSAGE,
+                                    base::UTF8ToUTF16(params_.username));
+}
+
+base::string16 AutoLoginInfoBarDelegate::GetButtonLabel(
+    InfoBarButton button) const {
+  return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
+      IDS_AUTOLOGIN_INFOBAR_OK_BUTTON : IDS_AUTOLOGIN_INFOBAR_CANCEL_BUTTON);
+}
+
+bool AutoLoginInfoBarDelegate::Accept() {
+  // AutoLoginRedirector deletes itself.
+  new AutoLoginRedirector(web_contents(), params_.header.args);
+  RecordHistogramAction(ACCEPTED);
+  button_pressed_ = true;
+  return true;
+}
+
+bool AutoLoginInfoBarDelegate::Cancel() {
+  PrefService* pref_service = Profile::FromBrowserContext(
+      web_contents()->GetBrowserContext())->GetPrefs();
+  pref_service->SetBoolean(prefs::kAutologinEnabled, false);
+  RecordHistogramAction(REJECTED);
+  button_pressed_ = true;
+  return true;
+}
+
+void AutoLoginInfoBarDelegate::GoogleSignedOut(const std::string& username) {
+  infobar()->RemoveSelf();
+}
+
+void AutoLoginInfoBarDelegate::RecordHistogramAction(Actions action) {
+  UMA_HISTOGRAM_ENUMERATION("AutoLogin.Regular", action,
+                            HISTOGRAM_BOUNDING_VALUE);
+}
diff --git a/chrome/browser/ui/auto_login_infobar_delegate.h b/chrome/browser/ui/auto_login_infobar_delegate.h
new file mode 100644
index 0000000..ce084b4
--- /dev/null
+++ b/chrome/browser/ui/auto_login_infobar_delegate.h
@@ -0,0 +1,80 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_H_
+#define CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_H_
+
+#include <string>
+#include "chrome/browser/infobars/confirm_infobar_delegate.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "components/auto_login_parser/auto_login_parser.h"
+
+class PrefService;
+class Profile;
+
+namespace content {
+class NavigationController;
+}
+
+// This is the actual infobar displayed to prompt the user to auto-login.
+class AutoLoginInfoBarDelegate : public ConfirmInfoBarDelegate,
+                                 public SigninManagerBase::Observer {
+ public:
+  struct Params {
+    // Information from a parsed header.
+    auto_login_parser::HeaderData header;
+
+    // Username to display in the infobar indicating user to be logged in as.
+    // This is initially fetched from sign-in on non-Android platforms. Note
+    // that on Android this field is not used.
+    std::string username;
+  };
+
+  // Creates an autologin infobar and delegate and adds the infobar to the
+  // infobar service for |web_contents|.  Returns whether the infobar was
+  // successfully added.
+  static bool Create(content::WebContents* web_contents, const Params& params);
+
+ protected:
+  AutoLoginInfoBarDelegate(const Params& params, Profile* profile);
+  virtual ~AutoLoginInfoBarDelegate();
+
+ private:
+  // Enum values used for UMA histograms.
+  enum Actions {
+    SHOWN,       // The infobar was shown to the user.
+    ACCEPTED,    // The user pressed the accept button.
+    REJECTED,    // The user pressed the reject button.
+    DISMISSED,   // The user pressed the close button.
+    IGNORED,     // The user ignored the infobar.
+    LEARN_MORE,  // The user clicked on the learn more link.
+    HISTOGRAM_BOUNDING_VALUE
+  };
+
+  // ConfirmInfoBarDelegate:
+  virtual void InfoBarDismissed() OVERRIDE;
+  virtual int GetIconID() const OVERRIDE;
+  virtual Type GetInfoBarType() const OVERRIDE;
+  virtual AutoLoginInfoBarDelegate* AsAutoLoginInfoBarDelegate() OVERRIDE;
+  virtual base::string16 GetMessageText() const OVERRIDE;
+  virtual base::string16 GetButtonLabel(InfoBarButton button) const OVERRIDE;
+  virtual bool Accept() OVERRIDE;
+  virtual bool Cancel() OVERRIDE;
+
+  // SigninManagerBase::Observer:
+  virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
+
+  void RecordHistogramAction(Actions action);
+
+  const Params params_;
+
+  Profile* profile_;
+
+  // Whether any UI controls in the infobar were pressed or not.
+  bool button_pressed_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoLoginInfoBarDelegate);
+};
+
+#endif  // CHROME_BROWSER_UI_AUTO_LOGIN_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/ui/auto_login_prompter.cc b/chrome/browser/ui/auto_login_prompter.cc
new file mode 100644
index 0000000..745b1aa
--- /dev/null
+++ b/chrome/browser/ui/auto_login_prompter.cc
@@ -0,0 +1,142 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/auto_login_prompter.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/google/google_url_tracker.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/signin_manager.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/tab_contents/tab_util.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "components/auto_login_parser/auto_login_parser.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/web_contents.h"
+#include "net/url_request/url_request.h"
+#include "url/gurl.h"
+
+using content::BrowserThread;
+using content::WebContents;
+
+namespace {
+
+#if !defined(OS_ANDROID)
+bool FetchUsernameThroughSigninManager(Profile* profile, std::string* output) {
+  // In an incognito window these services are not available.
+  SigninManagerBase* signin_manager =
+      SigninManagerFactory::GetInstance()->GetForProfile(profile);
+  if (!signin_manager)
+    return false;
+
+  ProfileOAuth2TokenService* token_service =
+      ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+  if (!token_service || !token_service->RefreshTokenIsAvailable(
+      signin_manager->GetAuthenticatedAccountId())) {
+    return false;
+  }
+
+  *output = signin_manager->GetAuthenticatedUsername();
+  return true;
+}
+#endif  // !defined(OS_ANDROID)
+
+}  // namespace
+
+AutoLoginPrompter::AutoLoginPrompter(WebContents* web_contents,
+                                     const Params& params,
+                                     const GURL& url)
+    : WebContentsObserver(web_contents),
+      params_(params),
+      url_(url),
+      infobar_shown_(false) {
+  if (!web_contents->IsLoading()) {
+    // If the WebContents isn't loading a page, the load notification will never
+    // be triggered.  Try adding the InfoBar now.
+    AddInfoBarToWebContents();
+  }
+}
+
+AutoLoginPrompter::~AutoLoginPrompter() {
+}
+
+// static
+void AutoLoginPrompter::ShowInfoBarIfPossible(net::URLRequest* request,
+                                              int child_id,
+                                              int route_id) {
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin))
+      return;
+
+  // See if the response contains the X-Auto-Login header.  If so, this was
+  // a request for a login page, and the server is allowing the browser to
+  // suggest auto-login, if available.
+  Params params;
+  // Currently we only accept GAIA credentials in Chrome.
+  if (!auto_login_parser::ParserHeaderInResponse(
+          request, auto_login_parser::ONLY_GOOGLE_COM, &params.header))
+    return;
+
+  BrowserThread::PostTask(
+      BrowserThread::UI, FROM_HERE,
+      base::Bind(&ShowInfoBarUIThread,
+                 params, request->url(), child_id, route_id));
+}
+
+
+// static
+void AutoLoginPrompter::ShowInfoBarUIThread(Params params,
+                                            const GURL& url,
+                                            int child_id,
+                                            int route_id) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  WebContents* web_contents = tab_util::GetWebContentsByID(child_id, route_id);
+  if (!web_contents)
+    return;
+
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
+
+  if (!profile->GetPrefs()->GetBoolean(prefs::kAutologinEnabled))
+    return;
+
+#if !defined(OS_ANDROID)
+  // On Android, the username is fetched on the Java side from the
+  // AccountManager provided by the platform.
+  if (!FetchUsernameThroughSigninManager(profile, &params.username))
+    return;
+#endif
+
+  // Make sure that |account|, if specified, matches the logged in user.
+  // However, |account| is usually empty.
+  if (!params.username.empty() && !params.header.account.empty() &&
+      params.username != params.header.account)
+    return;
+  // We can't add the infobar just yet, since we need to wait for the tab to
+  // finish loading.  If we don't, the info bar appears and then disappears
+  // immediately.  Create an AutoLoginPrompter instance to listen for the
+  // relevant notifications; it will delete itself.
+  new AutoLoginPrompter(web_contents, params, url);
+}
+
+void AutoLoginPrompter::DidStopLoading(
+    content::RenderViewHost* render_view_host) {
+  AddInfoBarToWebContents();
+  delete this;
+}
+
+void AutoLoginPrompter::WebContentsDestroyed(WebContents* web_contents) {
+  // The WebContents was destroyed before the navigation completed.
+  delete this;
+}
+
+void AutoLoginPrompter::AddInfoBarToWebContents() {
+  if (!infobar_shown_)
+    infobar_shown_ = AutoLoginInfoBarDelegate::Create(web_contents(), params_);
+}
diff --git a/chrome/browser/ui/auto_login_prompter.h b/chrome/browser/ui/auto_login_prompter.h
new file mode 100644
index 0000000..55607b4
--- /dev/null
+++ b/chrome/browser/ui/auto_login_prompter.h
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_AUTO_LOGIN_PROMPTER_H_
+#define CHROME_BROWSER_UI_AUTO_LOGIN_PROMPTER_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "chrome/browser/ui/auto_login_infobar_delegate.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "url/gurl.h"
+
+namespace content {
+class RenderViewHost;
+class WebContents;
+}
+
+namespace net {
+class URLRequest;
+}
+
+// This class displays an infobar that allows the user to automatically login to
+// the currently loaded page with one click.  This is used when the browser
+// detects that the user has navigated to a login page and that there are stored
+// tokens that would allow a one-click login.
+class AutoLoginPrompter : public content::WebContentsObserver {
+ public:
+  typedef AutoLoginInfoBarDelegate::Params Params;
+
+  // Looks for the X-Auto-Login response header in the request, and if found,
+  // tries to display an infobar in the tab contents identified by the
+  // child/route id.
+  static void ShowInfoBarIfPossible(net::URLRequest* request,
+                                    int child_id,
+                                    int route_id);
+
+ private:
+  friend class AutoLoginPrompterTest;
+
+  AutoLoginPrompter(content::WebContents* web_contents,
+                    const Params& params,
+                    const GURL& url);
+
+  virtual ~AutoLoginPrompter();
+
+  static void ShowInfoBarUIThread(Params params,
+                                  const GURL& url,
+                                  int child_id,
+                                  int route_id);
+
+  virtual void DidStopLoading(
+      content::RenderViewHost* render_view_host) OVERRIDE;
+
+  virtual void WebContentsDestroyed(
+      content::WebContents* web_contents) OVERRIDE;
+
+  // Add the infobar to the WebContents, if it's still needed.
+  void AddInfoBarToWebContents();
+
+  const Params params_;
+  const GURL url_;
+  bool infobar_shown_;
+
+  DISALLOW_COPY_AND_ASSIGN(AutoLoginPrompter);
+};
+
+#endif  // CHROME_BROWSER_UI_AUTO_LOGIN_PROMPTER_H_
diff --git a/chrome/browser/ui/autofill/autofill_dialog_common.cc b/chrome/browser/ui/autofill/autofill_dialog_common.cc
index 1570815..5c3b801 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_common.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_common.cc
@@ -23,9 +23,8 @@
 namespace autofill {
 namespace common {
 
-// Returns true if |input| should be shown when |field_type| has been requested.
-bool ServerTypeMatchesFieldType(ServerFieldType type,
-                                const AutofillType& field_type) {
+bool ServerTypeEncompassesFieldType(ServerFieldType type,
+                                    const AutofillType& field_type) {
   // If any credit card expiration info is asked for, show both month and year
   // inputs.
   ServerFieldType server_type = field_type.GetStorableType();
@@ -46,15 +45,20 @@
   if (autofill_type.group() != field_type.group())
     return false;
 
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
   // Street address (all lines) is matched to the first input address line.
   if (server_type == ADDRESS_HOME_STREET_ADDRESS)
     return autofill_type.GetStorableType() == ADDRESS_HOME_LINE1;
+#else
+  // The page may ask for individual address lines; this roughly matches the
+  // street address blob.
+  if (server_type == ADDRESS_HOME_LINE1 || server_type == ADDRESS_HOME_LINE2)
+    return autofill_type.GetStorableType() == ADDRESS_HOME_STREET_ADDRESS;
+#endif
 
   return autofill_type.GetStorableType() == server_type;
 }
 
-// Returns true if |input| in the given |section| should be used for a
-// site-requested |field|.
 bool ServerTypeMatchesField(DialogSection section,
                             ServerFieldType type,
                             const AutofillField& field) {
@@ -66,14 +70,13 @@
     return type == NAME_BILLING_FULL;
   }
 
-  return ServerTypeMatchesFieldType(type, field_type);
+  return ServerTypeEncompassesFieldType(type, field_type);
 }
 
 bool IsCreditCardType(ServerFieldType type) {
   return AutofillType(type).group() == CREDIT_CARD;
 }
 
-// Constructs |inputs| from template data.
 void BuildInputs(const DetailInput* input_template,
                  size_t template_size,
                  DetailInputs* inputs) {
diff --git a/chrome/browser/ui/autofill/autofill_dialog_common.h b/chrome/browser/ui/autofill/autofill_dialog_common.h
index 34bc1eb..f4195f8 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_common.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_common.h
@@ -27,8 +27,12 @@
 };
 
 // Returns true if |type| should be shown when |field_type| has been requested.
-bool ServerTypeMatchesFieldType(ServerFieldType type,
-                                const AutofillType& field_type);
+// This filters the types that we fill into the page to match the ones the
+// dialog actually cares about, preventing rAc from giving away data that an
+// AutofillProfile or other data source might know about the user which isn't
+// represented in the dialog.
+bool ServerTypeEncompassesFieldType(ServerFieldType type,
+                                    const AutofillType& field_type);
 
 // Returns true if |type| in the given |section| should be used for a
 // site-requested |field|.
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
index 947ccab..188f72c 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.cc
@@ -189,7 +189,7 @@
                                     const AutofillField& field) {
   // Equivalent billing field type is used to support UseBillingAsShipping
   // usecase.
-  return common::ServerTypeMatchesFieldType(
+  return common::ServerTypeEncompassesFieldType(
       type,
       AutofillType(AutofillType::GetEquivalentBillingFieldType(
           field.Type().GetStorableType())));
@@ -1959,7 +1959,7 @@
   ScopedViewUpdates updates(view_.get());
 
   if (type == ADDRESS_BILLING_COUNTRY || type == ADDRESS_HOME_COUNTRY) {
-    const FieldValueMap snapshot = TakeUserInputSnapshot();
+    const FieldValueMap& snapshot = TakeUserInputSnapshot();
 
     // Clobber the inputs because the view's already been updated.
     RebuildInputsForCountry(section, field_contents, true);
@@ -2008,6 +2008,9 @@
         &popup_labels,
         &popup_icons,
         &popup_guids_);
+
+    GetI18nValidatorSuggestions(section, type, &popup_values, &popup_labels,
+                                &popup_icons);
   }
 
   if (popup_values.empty()) {
@@ -2021,7 +2024,7 @@
   // TODO(estade): do we need separators and control rows like 'Clear
   // Form'?
   std::vector<int> popup_ids;
-  for (size_t i = 0; i < popup_guids_.size(); ++i) {
+  for (size_t i = 0; i < popup_values.size(); ++i) {
     popup_ids.push_back(i);
   }
 
@@ -2271,17 +2274,22 @@
   const ServerFieldType popup_input_type = popup_input_type_;
 
   ScopedViewUpdates updates(view_.get());
-  const PersonalDataManager::GUIDPair& pair = popup_guids_[identifier];
-
   scoped_ptr<DataModelWrapper> wrapper;
-  if (common::IsCreditCardType(popup_input_type)) {
-    wrapper.reset(new AutofillCreditCardWrapper(
-        GetManager()->GetCreditCardByGUID(pair.first)));
+
+  if (static_cast<size_t>(identifier) < popup_guids_.size()) {
+    const PersonalDataManager::GUIDPair& pair = popup_guids_[identifier];
+    if (common::IsCreditCardType(popup_input_type)) {
+      wrapper.reset(new AutofillCreditCardWrapper(
+          GetManager()->GetCreditCardByGUID(pair.first)));
+    } else {
+      wrapper.reset(new AutofillProfileWrapper(
+          GetManager()->GetProfileByGUID(pair.first),
+          AutofillType(popup_input_type),
+          pair.second));
+    }
   } else {
-    wrapper.reset(new AutofillProfileWrapper(
-        GetManager()->GetProfileByGUID(pair.first),
-        AutofillType(popup_input_type),
-        pair.second));
+    wrapper.reset(new I18nAddressDataWrapper(
+        &i18n_validator_suggestions_[identifier - popup_guids_.size()]));
   }
 
   // If the user hasn't switched away from the default country and |wrapper|'s
@@ -3232,6 +3240,57 @@
   return NULL;
 }
 
+void AutofillDialogControllerImpl::GetI18nValidatorSuggestions(
+    DialogSection section,
+    ServerFieldType type,
+    std::vector<base::string16>* popup_values,
+    std::vector<base::string16>* popup_labels,
+    std::vector<base::string16>* popup_icons) {
+  AddressField focused_field;
+  if (!i18ninput::FieldForType(type, &focused_field))
+    return;
+
+  FieldValueMap inputs;
+  view_->GetUserInput(section, &inputs);
+
+  AutofillProfile profile;
+  FillFormGroupFromOutputs(inputs, &profile);
+
+  AddressData user_input;
+  i18ninput::CreateAddressData(
+      base::Bind(&GetInfoFromProfile, profile), &user_input);
+
+  static const size_t kSuggestionsLimit = 10;
+  AddressValidator::Status status = GetValidator()->GetSuggestions(
+      user_input, focused_field, kSuggestionsLimit,
+      &i18n_validator_suggestions_);
+
+  if (status != AddressValidator::SUCCESS)
+    return;
+
+  for (size_t i = 0; i < i18n_validator_suggestions_.size(); ++i) {
+    popup_values->push_back(base::UTF8ToUTF16(
+        i18n_validator_suggestions_[i].GetFieldValue(focused_field)));
+
+    // Disambiguate the suggestion by showing the smallest administrative
+    // region of the suggested address:
+    //    ADMIN_AREA > LOCALITY > DEPENDENT_LOCALITY
+    popup_labels->push_back(base::string16());
+    for (int field = ::i18n::addressinput::DEPENDENT_LOCALITY;
+         field >= ::i18n::addressinput::ADMIN_AREA;
+         --field) {
+      const std::string& field_value =
+          i18n_validator_suggestions_[i].GetFieldValue(
+              static_cast<AddressField>(field));
+      if (focused_field != field && !field_value.empty()) {
+        popup_labels->back().assign(base::UTF8ToUTF16(field_value));
+        break;
+      }
+    }
+  }
+  popup_icons->resize(popup_values->size());
+}
+
 DetailInputs* AutofillDialogControllerImpl::MutableRequestedFieldsForSection(
     DialogSection section) {
   return const_cast<DetailInputs*>(&RequestedFieldsForSection(section));
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
index 7eb07e5..2585289 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_impl.h
@@ -468,17 +468,13 @@
   base::string16 ExtraSuggestionTextForSection(DialogSection section) const;
   gfx::Image ExtraSuggestionIconForSection(DialogSection section);
 
-  // Loads profiles that can suggest data for |type|. |field_contents| is the
-  // part the user has already typed. |inputs| is the rest of section.
-  // Identifying info is loaded into the last three outparams as well as
-  // |popup_guids_|.
-  void GetProfileSuggestions(
-      ServerFieldType type,
-      const base::string16& field_contents,
-      const DetailInputs& inputs,
-      std::vector<base::string16>* popup_values,
-      std::vector<base::string16>* popup_labels,
-      std::vector<base::string16>* popup_icons);
+  // Suggests address completions using the downloaded i18n validation rules.
+  // Stores the suggestions in |i18n_validator_suggestions_|.
+  void GetI18nValidatorSuggestions(DialogSection section,
+                                   ServerFieldType type,
+                                   std::vector<base::string16>* popup_values,
+                                   std::vector<base::string16>* popup_labels,
+                                   std::vector<base::string16>* popup_icons);
 
   // Like RequestedFieldsForSection, but returns a pointer.
   DetailInputs* MutableRequestedFieldsForSection(DialogSection section);
@@ -727,6 +723,9 @@
   // The GUIDs for the currently showing unverified profiles popup.
   std::vector<PersonalDataManager::GUIDPair> popup_guids_;
 
+  // The autofill suggestions based on downloaded i18n validation rules.
+  std::vector< ::i18n::addressinput::AddressData> i18n_validator_suggestions_;
+
   // The controller for the currently showing popup (which helps users when
   // they're manually filling the dialog).
   base::WeakPtr<AutofillPopupControllerImpl> popup_controller_;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
index e5c40e9..c6cc695 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_controller_unittest.cc
@@ -1801,7 +1801,11 @@
   CreditCard full_card(test::GetCreditCard());
   for (size_t i = 0; i < inputs.size(); ++i) {
     const ServerFieldType type = inputs[i].type;
+#if defined(OS_MACOSX)
     if (type == ADDRESS_BILLING_LINE1)
+#else
+    if (type == ADDRESS_BILLING_STREET_ADDRESS)
+#endif
       outputs[type] = ASCIIToUTF16(kEditedBillingAddress);
     else
       outputs[type] = full_profile.GetInfo(AutofillType(type), "en-US");
@@ -3348,6 +3352,10 @@
 TEST_F(AutofillDialogControllerTest, DontSuggestHiddenCountries) {
   SwitchToAutofill();
 
+  FieldValueMap outputs;
+  outputs[ADDRESS_HOME_COUNTRY] = ASCIIToUTF16("US");
+  controller()->GetView()->SetUserInput(SECTION_SHIPPING, outputs);
+
   AutofillProfile cn_profile(test::GetVerifiedProfile());
   cn_profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("Chinese User"));
   cn_profile.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("CN"));
@@ -3381,6 +3389,10 @@
 TEST_F(AutofillDialogControllerTest, SuggestCountrylessProfiles) {
   SwitchToAutofill();
 
+  FieldValueMap outputs;
+  outputs[ADDRESS_HOME_COUNTRY] = ASCIIToUTF16("US");
+  controller()->GetView()->SetUserInput(SECTION_SHIPPING, outputs);
+
   AutofillProfile profile(test::GetVerifiedProfile());
   profile.SetRawInfo(NAME_FULL, ASCIIToUTF16("The Man Without a Country"));
   profile.SetRawInfo(ADDRESS_HOME_COUNTRY, base::string16());
diff --git a/chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc b/chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc
index c3a3900..c079e3d 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_i18n_input.cc
@@ -6,6 +6,7 @@
 
 #include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/credit_card.h"
 #include "components/autofill/core/browser/field_types.h"
@@ -38,8 +39,11 @@
 void BuildAddressInputs(common::AddressType address_type,
                         const std::string& country_code,
                         DetailInputs* inputs) {
+  // TODO(rouslan): Store the language code for the autofill profile.
+  // http://crbug.com/354955
   std::vector<AddressUiComponent> components(
-      ::i18n::addressinput::BuildComponents(country_code));
+      ::i18n::addressinput::BuildComponents(
+          country_code, g_browser_process->GetApplicationLocale(), NULL));
 
   const bool billing = address_type == common::ADDRESS_TYPE_BILLING;
 
@@ -56,6 +60,7 @@
     DetailInput input = { length, server_type, placeholder };
     inputs->push_back(input);
 
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
     if (component.field == ::i18n::addressinput::STREET_ADDRESS &&
         component.length_hint == AddressUiComponent::HINT_LONG) {
       // TODO(dbeam): support more than 2 address lines. http://crbug.com/324889
@@ -65,6 +70,7 @@
       DetailInput input = { length, server_type, placeholder };
       inputs->push_back(input);
     }
+#endif
   }
 
   ServerFieldType server_type =
@@ -141,8 +147,14 @@
       return billing ? ADDRESS_BILLING_ZIP : ADDRESS_HOME_ZIP;
     case ::i18n::addressinput::SORTING_CODE:
       return billing ? ADDRESS_BILLING_SORTING_CODE : ADDRESS_HOME_SORTING_CODE;
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
     case ::i18n::addressinput::STREET_ADDRESS:
       return billing ? ADDRESS_BILLING_LINE1 : ADDRESS_HOME_LINE1;
+#else
+    case ::i18n::addressinput::STREET_ADDRESS:
+      return billing ? ADDRESS_BILLING_STREET_ADDRESS :
+                       ADDRESS_HOME_STREET_ADDRESS;
+#endif
     case ::i18n::addressinput::RECIPIENT:
       return billing ? NAME_BILLING_FULL : NAME_FULL;
     case ::i18n::addressinput::ORGANIZATION:
@@ -152,6 +164,62 @@
   return UNKNOWN_TYPE;
 }
 
+bool FieldForType(ServerFieldType server_type,
+                  ::i18n::addressinput::AddressField* field) {
+  switch (server_type) {
+    case ADDRESS_BILLING_COUNTRY:
+    case ADDRESS_HOME_COUNTRY:
+      if (field)
+        *field = ::i18n::addressinput::COUNTRY;
+      return true;
+    case ADDRESS_BILLING_STATE:
+    case ADDRESS_HOME_STATE:
+      if (field)
+        *field = ::i18n::addressinput::ADMIN_AREA;
+      return true;
+    case ADDRESS_BILLING_CITY:
+    case ADDRESS_HOME_CITY:
+      if (field)
+        *field = ::i18n::addressinput::LOCALITY;
+      return true;
+    case ADDRESS_BILLING_DEPENDENT_LOCALITY:
+    case ADDRESS_HOME_DEPENDENT_LOCALITY:
+      if (field)
+        *field = ::i18n::addressinput::DEPENDENT_LOCALITY;
+      return true;
+    case ADDRESS_BILLING_SORTING_CODE:
+    case ADDRESS_HOME_SORTING_CODE:
+      if (field)
+        *field = ::i18n::addressinput::SORTING_CODE;
+      return true;
+    case ADDRESS_BILLING_ZIP:
+    case ADDRESS_HOME_ZIP:
+      if (field)
+        *field = ::i18n::addressinput::POSTAL_CODE;
+      return true;
+    case ADDRESS_BILLING_STREET_ADDRESS:
+    case ADDRESS_BILLING_LINE1:
+    case ADDRESS_BILLING_LINE2:
+    case ADDRESS_HOME_STREET_ADDRESS:
+    case ADDRESS_HOME_LINE1:
+    case ADDRESS_HOME_LINE2:
+      if (field)
+        *field = ::i18n::addressinput::STREET_ADDRESS;
+      return true;
+    case COMPANY_NAME:
+      if (field)
+        *field = ::i18n::addressinput::ORGANIZATION;
+      return true;
+    case NAME_BILLING_FULL:
+    case NAME_FULL:
+      if (field)
+        *field = ::i18n::addressinput::RECIPIENT;
+      return true;
+    default:
+      return false;
+  }
+}
+
 void CreateAddressData(
     const base::Callback<base::string16(const AutofillType&)>& get_info,
     AddressData* address_data) {
@@ -178,7 +246,8 @@
 bool CountryIsFullySupported(const std::string& country_code) {
   DCHECK_EQ(2U, country_code.size());
   std::vector< ::i18n::addressinput::AddressUiComponent> components =
-      ::i18n::addressinput::BuildComponents(country_code);
+      ::i18n::addressinput::BuildComponents(
+          country_code, g_browser_process->GetApplicationLocale(), NULL);
   for (size_t i = 0; i < components.size(); ++i) {
     if (components[i].field == ::i18n::addressinput::DEPENDENT_LOCALITY)
       return false;
diff --git a/chrome/browser/ui/autofill/autofill_dialog_i18n_input.h b/chrome/browser/ui/autofill/autofill_dialog_i18n_input.h
index d32ccb9..0384e1b 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_i18n_input.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_i18n_input.h
@@ -46,6 +46,12 @@
 ServerFieldType TypeForField(::i18n::addressinput::AddressField field,
                              common::AddressType address_type);
 
+// Sets |field| to the corresponding address field for the Autofill
+// |server_type|. Returns |true| if |server_type| can be represented as an
+// address field. The |field| parameter can be NULL.
+bool FieldForType(ServerFieldType server_type,
+                  ::i18n::addressinput::AddressField* field);
+
 // Creates an AddressData object for internationalized address display or
 // validation using |get_info| for field values.
 void CreateAddressData(
diff --git a/chrome/browser/ui/autofill/autofill_dialog_i18n_input_unittest.cc b/chrome/browser/ui/autofill/autofill_dialog_i18n_input_unittest.cc
index 87a7faf..a78db23 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_i18n_input_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_i18n_input_unittest.cc
@@ -13,7 +13,11 @@
 
 namespace {
 
+#if defined(OS_MACOSX)
 const size_t kNumberOfAddressLinesUS = 7;
+#else
+const size_t kNumberOfAddressLinesUS = 6;
+#endif
 
 }  // namespace
 
@@ -40,22 +44,28 @@
   BuildAddressInputs(common::ADDRESS_TYPE_SHIPPING, "US", &inputs);
   ASSERT_EQ(kNumberOfAddressLinesUS, inputs.size());
 
-  // Inputs before or after [ City ] [ State ] [ Zip ] should be on other lines.
-  EXPECT_NE(inputs[2].length, DetailInput::SHORT);
+#if defined(OS_MACOSX)
+  int input_index = 3;
+#else
+  int input_index = 2;
+#endif
 
-  const DetailInput& city = inputs[3];
-  ASSERT_EQ(ADDRESS_HOME_CITY, city.type);
+  // Inputs before or after [ City ] [ State ] [ Zip ] should be on other lines.
+  EXPECT_NE(inputs[input_index - 1].length, DetailInput::SHORT);
+
+  const DetailInput& city = inputs[input_index++];
+  EXPECT_EQ(ADDRESS_HOME_CITY, city.type);
   EXPECT_EQ(city.length, DetailInput::SHORT);
 
-  const DetailInput& state = inputs[4];
-  ASSERT_EQ(ADDRESS_HOME_STATE, state.type);
+  const DetailInput& state = inputs[input_index++];
+  EXPECT_EQ(ADDRESS_HOME_STATE, state.type);
   EXPECT_EQ(state.length, DetailInput::SHORT);
 
-  const DetailInput& zip = inputs[5];
-  ASSERT_EQ(ADDRESS_HOME_ZIP, zip.type);
+  const DetailInput& zip = inputs[input_index++];
+  EXPECT_EQ(ADDRESS_HOME_ZIP, zip.type);
   EXPECT_EQ(zip.length, DetailInput::SHORT);
 
-  EXPECT_NE(inputs[6].length, DetailInput::SHORT);
+  EXPECT_NE(inputs[input_index].length, DetailInput::SHORT);
 }
 
 TEST(AutofillDialogI18nInput, IvoryCoastNoStreetLine2) {
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.cc b/chrome/browser/ui/autofill/autofill_dialog_types.cc
index 597cea5..c1a33dc 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.cc
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.cc
@@ -22,6 +22,14 @@
 
 static const base::char16 kRangeSeparator = '|';
 
+// Street address is multi-line, except in countries where it shares a line
+// with other inputs (such as Coite d'Ivoire).
+bool DetailInput::IsMultiline() const {
+  return (type == ADDRESS_HOME_STREET_ADDRESS ||
+          type == ADDRESS_BILLING_STREET_ADDRESS) &&
+      length == DetailInput::LONG;
+}
+
 DialogNotification::DialogNotification() : type_(NONE) {}
 
 DialogNotification::DialogNotification(Type type,
diff --git a/chrome/browser/ui/autofill/autofill_dialog_types.h b/chrome/browser/ui/autofill/autofill_dialog_types.h
index c7ebcea..97926f2 100644
--- a/chrome/browser/ui/autofill/autofill_dialog_types.h
+++ b/chrome/browser/ui/autofill/autofill_dialog_types.h
@@ -28,13 +28,16 @@
 // dialog.
 struct DetailInput {
   enum Length {
-    SHORT,     // Shares a line with other short inputs, like display: inline.
-    SHORT_EOL, // Like SHORT but starts a new line directly afterward. Used to
-               // separate groups of short inputs into different lines.
-    LONG,      // Will be given its own full line, like display: block.
-    NONE,      // Input will not be shown.
+    SHORT,      // Shares a line with other short inputs, like display: inline.
+    SHORT_EOL,  // Like SHORT but starts a new line directly afterward. Used to
+                // separate groups of short inputs into different lines.
+    LONG,       // Will be given its own full line, like display: block.
+    NONE,       // Input will not be shown.
   };
 
+  // Returns whether this input can spread across multiple lines.
+  bool IsMultiline() const;
+
   // Used to determine which inputs share lines when laying out.
   Length length;
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index 36576c9..4e6c6a0 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -302,10 +302,18 @@
   SetSelectedLine(LineFromY(point.y()));
 }
 
-void AutofillPopupControllerImpl::AcceptSelectionAtPoint(
-    const gfx::Point& point) {
-  SetSelectionAtPoint(point);
-  AcceptSelectedLine();
+bool AutofillPopupControllerImpl::AcceptSelectedLine() {
+  if (selected_line_ == kNoSelection)
+    return false;
+
+  DCHECK_GE(selected_line_, 0);
+  DCHECK_LT(selected_line_, static_cast<int>(names_.size()));
+
+  if (!CanAccept(identifiers_[selected_line_]))
+    return false;
+
+  AcceptSuggestion(selected_line_);
+  return true;
 }
 
 void AutofillPopupControllerImpl::SelectionCleared() {
@@ -476,20 +484,6 @@
   SetSelectedLine(new_selected_line);
 }
 
-bool AutofillPopupControllerImpl::AcceptSelectedLine() {
-  if (selected_line_ == kNoSelection)
-    return false;
-
-  DCHECK_GE(selected_line_, 0);
-  DCHECK_LT(selected_line_, static_cast<int>(names_.size()));
-
-  if (!CanAccept(identifiers_[selected_line_]))
-    return false;
-
-  AcceptSuggestion(selected_line_);
-  return true;
-}
-
 bool AutofillPopupControllerImpl::RemoveSelectedLine() {
   if (selected_line_ == kNoSelection)
     return false;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
index 0852ef6..899c50b 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.h
@@ -75,7 +75,7 @@
   // AutofillPopupController implementation.
   virtual void UpdateBoundsAndRedrawPopup() OVERRIDE;
   virtual void SetSelectionAtPoint(const gfx::Point& point) OVERRIDE;
-  virtual void AcceptSelectionAtPoint(const gfx::Point& point) OVERRIDE;
+  virtual bool AcceptSelectedLine() OVERRIDE;
   virtual void SelectionCleared() OVERRIDE;
   virtual bool ShouldRepostEvent(const ui::MouseEvent& event) OVERRIDE;
   virtual bool ShouldHideOnOutsideClick() const OVERRIDE;
@@ -113,9 +113,6 @@
   // Decrease the selected line by 1, properly handling wrapping.
   void SelectPreviousLine();
 
-  // The user has choosen the selected line.
-  bool AcceptSelectedLine();
-
   // The user has removed a suggestion.
   bool RemoveSelectedLine();
 
diff --git a/chrome/browser/ui/autofill/autofill_popup_view_delegate.h b/chrome/browser/ui/autofill/autofill_popup_view_delegate.h
index 3b85496..15836cb 100644
--- a/chrome/browser/ui/autofill/autofill_popup_view_delegate.h
+++ b/chrome/browser/ui/autofill/autofill_popup_view_delegate.h
@@ -33,9 +33,9 @@
   // must be in popup coordinates.
   virtual void SetSelectionAtPoint(const gfx::Point& point) = 0;
 
-  // The user has accpeted the selection at |point|, e.g. by clicking on it
-  // using the mouse. |point| must be in popup coordinates.
-  virtual void AcceptSelectionAtPoint(const gfx::Point& point) = 0;
+  // The user has accepted the currently selected line. Returns whether there
+  // was a selection to accept.
+  virtual bool AcceptSelectedLine() = 0;
 
   // The user cleared the current selection, e.g. by moving the mouse cursor
   // out of the popup bounds.
diff --git a/chrome/browser/ui/autofill/country_combobox_model_unittest.cc b/chrome/browser/ui/autofill/country_combobox_model_unittest.cc
index 1514b7a..56ebd85 100644
--- a/chrome/browser/ui/autofill/country_combobox_model_unittest.cc
+++ b/chrome/browser/ui/autofill/country_combobox_model_unittest.cc
@@ -50,7 +50,8 @@
 
     std::string country_code = model()->countries()[i]->country_code();
     std::vector< ::i18n::addressinput::AddressUiComponent> components =
-        ::i18n::addressinput::BuildComponents(country_code);
+        ::i18n::addressinput::BuildComponents(
+            country_code, std::string(), NULL);
     EXPECT_FALSE(components.empty());
   }
 }
diff --git a/chrome/browser/ui/autofill/data_model_wrapper.cc b/chrome/browser/ui/autofill/data_model_wrapper.cc
index 25e1673..7c0b9df 100644
--- a/chrome/browser/ui/autofill/data_model_wrapper.cc
+++ b/chrome/browser/ui/autofill/data_model_wrapper.cc
@@ -14,6 +14,7 @@
 #include "components/autofill/content/browser/wallet/full_wallet.h"
 #include "components/autofill/content/browser/wallet/wallet_address.h"
 #include "components/autofill/content/browser/wallet/wallet_items.h"
+#include "components/autofill/core/browser/autofill_country.h"
 #include "components/autofill/core/browser/autofill_data_model.h"
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_profile.h"
@@ -339,4 +340,26 @@
       type, g_browser_process->GetApplicationLocale());
 }
 
+I18nAddressDataWrapper::I18nAddressDataWrapper(
+    const ::i18n::addressinput::AddressData* address)
+    : address_(address) {}
+
+I18nAddressDataWrapper::~I18nAddressDataWrapper() {}
+
+base::string16 I18nAddressDataWrapper::GetInfo(const AutofillType& type) const {
+  ::i18n::addressinput::AddressField field;
+  if (!i18ninput::FieldForType(type.GetStorableType(), &field))
+    return base::string16();
+
+  if (field == ::i18n::addressinput::STREET_ADDRESS)
+    return base::string16();
+
+  if (field == ::i18n::addressinput::COUNTRY) {
+    return AutofillCountry(address_->country_code,
+                           g_browser_process->GetApplicationLocale()).name();
+  }
+
+  return base::UTF8ToUTF16(address_->GetFieldValue(field));
+}
+
 }  // namespace autofill
diff --git a/chrome/browser/ui/autofill/data_model_wrapper.h b/chrome/browser/ui/autofill/data_model_wrapper.h
index 6f79c84..3ff868c 100644
--- a/chrome/browser/ui/autofill/data_model_wrapper.h
+++ b/chrome/browser/ui/autofill/data_model_wrapper.h
@@ -18,6 +18,12 @@
 class Image;
 }
 
+namespace i18n {
+namespace addressinput {
+struct AddressData;
+}
+}
+
 namespace autofill {
 
 class AutofillDataModel;
@@ -205,6 +211,21 @@
   DISALLOW_COPY_AND_ASSIGN(FullWalletShippingWrapper);
 };
 
+// A DataModelWrapper for ::i18n::addressinput::AddressData objects.
+class I18nAddressDataWrapper : public DataModelWrapper {
+ public:
+  explicit I18nAddressDataWrapper(
+      const ::i18n::addressinput::AddressData* address);
+  virtual ~I18nAddressDataWrapper();
+
+  virtual base::string16 GetInfo(const AutofillType& type) const OVERRIDE;
+
+ private:
+  const ::i18n::addressinput::AddressData* address_;
+
+  DISALLOW_COPY_AND_ASSIGN(I18nAddressDataWrapper);
+};
+
 }  // namespace autofill
 
 #endif  // CHROME_BROWSER_UI_AUTOFILL_DATA_MODEL_WRAPPER_H_
diff --git a/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
index e408068..8933a21 100644
--- a/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
+++ b/chrome/browser/ui/autofill/new_credit_card_bubble_controller.cc
@@ -62,11 +62,7 @@
 }
 
 void NewCreditCardBubbleController::OnLinkClicked() {
-  Browser* browser = chrome::FindTabbedBrowser(profile_, false,
-                                               chrome::GetActiveDesktop());
-  if (browser)
-    chrome::ShowSettingsSubPage(browser, chrome::kAutofillSubPage);
-
+  chrome::ShowSettingsSubPageForProfile(profile_, chrome::kAutofillSubPage);
   Hide();
 }
 
diff --git a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
index b711cb2..64c40b1 100644
--- a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.cc
@@ -291,10 +291,12 @@
     PasswordSelected(true);
 }
 
-void PasswordGenerationPopupControllerImpl::AcceptSelectionAtPoint(
-    const gfx::Point& point) {
-  if (password_bounds_.Contains(point))
-    PasswordAccepted();
+bool PasswordGenerationPopupControllerImpl::AcceptSelectedLine() {
+  if (!password_selected_)
+    return false;
+
+  PasswordAccepted();
+  return true;
 }
 
 void PasswordGenerationPopupControllerImpl::SelectionCleared() {
diff --git a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h
index c368376..f20287b 100644
--- a/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h
+++ b/chrome/browser/ui/autofill/password_generation_popup_controller_impl.h
@@ -87,7 +87,7 @@
   virtual void Hide() OVERRIDE;
   virtual void ViewDestroyed() OVERRIDE;
   virtual void SetSelectionAtPoint(const gfx::Point& point) OVERRIDE;
-  virtual void AcceptSelectionAtPoint(const gfx::Point& point) OVERRIDE;
+  virtual bool AcceptSelectedLine() OVERRIDE;
   virtual void SelectionCleared() OVERRIDE;
   virtual bool ShouldRepostEvent(const ui::MouseEvent& event) OVERRIDE;
   virtual bool ShouldHideOnOutsideClick() const OVERRIDE;
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils.cc b/chrome/browser/ui/bookmarks/bookmark_utils.cc
index d577df6..54e6f50 100644
--- a/chrome/browser/ui/bookmarks/bookmark_utils.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_utils.cc
@@ -342,4 +342,23 @@
          BOOKMARK_SHORTCUT_DISPOSITION_REMOVED;
 }
 
+bool ShouldRemoveBookmarkOpenPagesUI(Profile* profile) {
+  extensions::ExtensionRegistry* registry =
+      extensions::ExtensionRegistry::Get(profile);
+  if (!registry)
+    return false;
+
+  const extensions::ExtensionSet& extension_set =
+      registry->enabled_extensions();
+
+  for (extensions::ExtensionSet::const_iterator i = extension_set.begin();
+       i != extension_set.end();
+       ++i) {
+    if (extensions::CommandService::RemovesBookmarkOpenPagesShortcut(*i))
+      return true;
+  }
+
+  return false;
+}
+
 }  // namespace chrome
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils.h b/chrome/browser/ui/bookmarks/bookmark_utils.h
index 99007ed..f321b26 100644
--- a/chrome/browser/ui/bookmarks/bookmark_utils.h
+++ b/chrome/browser/ui/bookmarks/bookmark_utils.h
@@ -110,6 +110,10 @@
 // the user interface.
 bool ShouldRemoveBookmarkThisPageUI(Profile* profile);
 
+// Whether the menu item and shortcut to bookmark open pages should be removed
+// from the user interface.
+bool ShouldRemoveBookmarkOpenPagesUI(Profile* profile);
+
 }  // namespace chrome
 
 #endif  // CHROME_BROWSER_UI_BOOKMARKS_BOOKMARK_UTILS_H_
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index b04508d..85824f4 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -447,9 +447,7 @@
 
 Browser::~Browser() {
   // The tab strip should not have any tabs at this point.
-  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
-    DCHECK(tab_strip_model_->empty());
-
+  DCHECK(tab_strip_model_->empty());
   tab_strip_model_->RemoveObserver(this);
 
   // Destroy the BrowserCommandController before removing the browser, so that
@@ -916,7 +914,7 @@
 
   // Make sure the loading state is updated correctly, otherwise the throbber
   // won't start if the page is loading.
-  LoadingStateChanged(contents);
+  LoadingStateChanged(contents, true);
 
   interstitial_observers_.push_back(new InterstitialObserver(this, contents));
 
@@ -1341,13 +1339,14 @@
   window_->Deactivate();
 }
 
-void Browser::LoadingStateChanged(WebContents* source) {
+void Browser::LoadingStateChanged(WebContents* source,
+    bool to_different_document) {
   window_->UpdateLoadingAnimations(tab_strip_model_->TabsAreLoading());
   window_->UpdateTitleBar();
 
   WebContents* selected_contents = tab_strip_model_->GetActiveWebContents();
   if (source == selected_contents) {
-    bool is_loading = source->IsLoading();
+    bool is_loading = source->IsLoading() && to_different_document;
     command_controller_->LoadingStateChanged(is_loading, false);
     if (GetStatusBubble()) {
       GetStatusBubble()->SetStatus(CoreTabHelper::FromWebContents(
@@ -1510,7 +1509,7 @@
 }
 
 void Browser::WebContentsCreated(WebContents* source_contents,
-                                 int64 source_frame_id,
+                                 int opener_render_frame_id,
                                  const base::string16& frame_name,
                                  const GURL& target_url,
                                  WebContents* new_contents) {
@@ -1523,7 +1522,7 @@
   // Notify.
   RetargetingDetails details;
   details.source_web_contents = source_contents;
-  details.source_frame_id = source_frame_id;
+  details.source_render_frame_id = opener_render_frame_id;
   details.target_url = target_url;
   details.target_web_contents = new_contents;
   details.not_yet_in_tabstrip = true;
@@ -1834,6 +1833,10 @@
           this,
           IDC_BOOKMARK_PAGE,
           !chrome::ShouldRemoveBookmarkThisPageUI(profile_));
+      chrome::UpdateCommandEnabled(
+          this,
+          IDC_BOOKMARK_ALL_TABS,
+          !chrome::ShouldRemoveBookmarkOpenPagesUI(profile_));
 
       if (window()->GetLocationBar())
         window()->GetLocationBar()->UpdatePageActions();
@@ -1878,6 +1881,10 @@
           this,
           IDC_BOOKMARK_PAGE,
           !chrome::ShouldRemoveBookmarkThisPageUI(profile_));
+      chrome::UpdateCommandEnabled(
+          this,
+          IDC_BOOKMARK_ALL_TABS,
+          !chrome::ShouldRemoveBookmarkOpenPagesUI(profile_));
     // fallthrough
     case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
       // During window creation on Windows we may end up calling into
@@ -2179,6 +2186,35 @@
   }
 }
 
+bool Browser::ShouldShowLocationBar() const {
+  if (!is_app()) {
+    // Hide the URL for singleton settings windows.
+    // TODO(stevenjb): We could avoid this check by setting a Browser
+    // property for "system" windows, possibly shared with hosted app windows.
+    // crbug.com/350128.
+    if (chrome::IsSettingsWindow(this))
+      return false;
+    return true;
+  }
+
+  // Normally apps do not show a location bar.
+  if (app_type() != APP_TYPE_HOST ||
+      app_name() == DevToolsWindow::kDevToolsApp ||
+      !CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableStreamlinedHostedApps))
+    return false;
+
+  // If kEnableStreamlinedHostedApps is true, show the locaiton bar for non
+  // legacy packaged apps.
+  ExtensionService* service =
+      extensions::ExtensionSystem::Get(profile_)->extension_service();
+  const extensions::Extension* extension =
+      service ? service->GetInstalledExtension(
+                    web_app::GetExtensionIdFromApplicationName(app_name()))
+              : NULL;
+  return (!extension || !extension->is_legacy_packaged_app());
+}
+
 bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
                                         bool check_fullscreen) const {
   bool hide_ui_for_fullscreen = check_fullscreen && ShouldHideUIForFullscreen();
@@ -2198,20 +2234,8 @@
     if (is_type_tabbed())
       features |= FEATURE_TOOLBAR;
 
-    ExtensionService* service =
-        extensions::ExtensionSystem::Get(profile_)->extension_service();
-    const extensions::Extension* extension =
-        service ? service->GetInstalledExtension(
-                      web_app::GetExtensionIdFromApplicationName(app_name()))
-                : NULL;
-
-    if (!is_app() || (app_type() == APP_TYPE_HOST &&
-                      app_name() != DevToolsWindow::kDevToolsApp &&
-                      (!extension || !extension->is_legacy_packaged_app()) &&
-                      CommandLine::ForCurrentProcess()->HasSwitch(
-                          switches::kEnableStreamlinedHostedApps))) {
+    if (ShouldShowLocationBar())
       features |= FEATURE_LOCATIONBAR;
-    }
   }
   return !!(features & feature);
 }
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
index 72bdcb8..0e6d0bb 100644
--- a/chrome/browser/ui/browser.h
+++ b/chrome/browser/ui/browser.h
@@ -549,7 +549,8 @@
                               bool* was_blocked) OVERRIDE;
   virtual void ActivateContents(content::WebContents* contents) OVERRIDE;
   virtual void DeactivateContents(content::WebContents* contents) OVERRIDE;
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
   virtual void CloseContents(content::WebContents* source) OVERRIDE;
   virtual void MoveContents(content::WebContents* source,
                             const gfx::Rect& pos) OVERRIDE;
@@ -588,7 +589,7 @@
       const std::string& partition_id,
       content::SessionStorageNamespace* session_storage_namespace) OVERRIDE;
   virtual void WebContentsCreated(content::WebContents* source_contents,
-                                  int64 source_frame_id,
+                                  int opener_render_frame_id,
                                   const base::string16& frame_name,
                                   const GURL& target_url,
                                   content::WebContents* new_contents) OVERRIDE;
@@ -769,6 +770,9 @@
   // Shared code between Reload() and ReloadIgnoringCache().
   void ReloadInternal(WindowOpenDisposition disposition, bool ignore_cache);
 
+  // Returns true if the Browser window should show the location bar.
+  bool ShouldShowLocationBar() const;
+
   // Implementation of SupportsWindowFeature and CanSupportWindowFeature. If
   // |check_fullscreen| is true, the set of features reflect the actual state of
   // the browser, otherwise the set of features reflect the possible state of
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc
index c76ba26..94d132e 100644
--- a/chrome/browser/ui/browser_commands.cc
+++ b/chrome/browser/ui/browser_commands.cc
@@ -769,6 +769,7 @@
 
 bool CanBookmarkAllTabs(const Browser* browser) {
   return browser->tab_strip_model()->count() > 1 &&
+             !chrome::ShouldRemoveBookmarkOpenPagesUI(browser->profile()) &&
              CanBookmarkCurrentPageInternal(browser, false);
 }
 
@@ -1013,17 +1014,25 @@
 }
 
 bool CanOpenTaskManager() {
+#if defined(ENABLE_TASK_MANAGER)
 #if defined(OS_WIN)
   // In metro we can't display the task manager, as it is a native window.
   return !win8::IsSingleWindowMetroMode();
 #else
   return true;
 #endif
+#else
+  return false;
+#endif
 }
 
 void OpenTaskManager(Browser* browser) {
+#if defined(ENABLE_TASK_MANAGER)
   content::RecordAction(UserMetricsAction("TaskManager"));
   chrome::ShowTaskManager(browser);
+#else
+  NOTREACHED();
+#endif
 }
 
 void OpenFeedbackDialog(Browser* browser) {
@@ -1042,7 +1051,8 @@
 }
 
 void ShowAvatarMenu(Browser* browser) {
-  browser->window()->ShowAvatarBubbleFromAvatarButton();
+  browser->window()->ShowAvatarBubbleFromAvatarButton(
+      BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT);
 }
 
 void OpenUpdateChromeDialog(Browser* browser) {
@@ -1051,6 +1061,11 @@
         chrome::NOTIFICATION_OUTDATED_INSTALL,
         content::NotificationService::AllSources(),
         content::NotificationService::NoDetails());
+  } else if (UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
+    content::NotificationService::current()->Notify(
+        chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+        content::NotificationService::AllSources(),
+        content::NotificationService::NoDetails());
   } else {
     content::RecordAction(UserMetricsAction("UpdateChrome"));
     browser->window()->ShowUpdateChromeDialog();
diff --git a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
index 5f5ff7c..eeb0e7d 100644
--- a/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
+++ b/chrome/browser/ui/browser_navigator_browsertest_chromeos.cc
@@ -157,6 +157,7 @@
     command_line_copy.AppendSwitchASCII(
         chromeos::switches::kLoginProfile, "user");
     chromeos::GetOffTheRecordCommandLine(GetGoogleURL(),
+                                         true,
                                          command_line_copy,
                                          command_line);
   }
diff --git a/chrome/browser/ui/browser_tab_strip_model_delegate.cc b/chrome/browser/ui/browser_tab_strip_model_delegate.cc
index ab08564..730a2ad 100644
--- a/chrome/browser/ui/browser_tab_strip_model_delegate.cc
+++ b/chrome/browser/ui/browser_tab_strip_model_delegate.cc
@@ -77,7 +77,7 @@
     // won't start if the page is loading.
     // TODO(beng): find a better way of doing this.
     static_cast<content::WebContentsDelegate*>(browser)->
-        LoadingStateChanged(item.web_contents);
+        LoadingStateChanged(item.web_contents, true);
   }
 
   return browser;
diff --git a/chrome/browser/ui/browser_window.h b/chrome/browser/ui/browser_window.h
index 2577304..226033b 100644
--- a/chrome/browser/ui/browser_window.h
+++ b/chrome/browser/ui/browser_window.h
@@ -367,8 +367,13 @@
   virtual void ShowAvatarBubble(content::WebContents* web_contents,
                                 const gfx::Rect& rect) = 0;
 
-  // Shows the avatar bubble on the window frame off of the avatar button.
-  virtual void ShowAvatarBubbleFromAvatarButton() = 0;
+  // Shows the avatar bubble on the window frame off of the avatar button with
+  // the given mode.
+  enum AvatarBubbleMode {
+    AVATAR_BUBBLE_MODE_DEFAULT,
+    AVATAR_BUBBLE_MODE_ACCOUNT_MANAGEMENT
+  };
+  virtual void ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode) = 0;
 
   // Show bubble for password generation positioned relative to |rect|. The
   // subclasses implementing this interface do not own the |password_generator|
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index acdb1f1..9b481ea 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -15,18 +15,22 @@
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/extensions/application_launch.h"
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
+#include "chrome/browser/ui/settings_window_manager.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/options/content_settings_handler.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/user_metrics.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/url_util.h"
-#include "url/gurl.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/enumerate_modules_model_win.h"
@@ -51,9 +55,8 @@
   content::RecordAction(UserMetricsAction("ShowBookmarks"));
   NavigateParams params(GetSingletonTabNavigateParams(
       browser,
-      GURL(kChromeUIBookmarksURL).Resolve(
-          base::StringPrintf("/#%s%s", action.c_str(),
-              base::Int64ToString(node_id).c_str()))));
+      GURL(kChromeUIBookmarksURL).Resolve(base::StringPrintf(
+          "/#%s%s", action.c_str(), base::Int64ToString(node_id).c_str()))));
   params.path_behavior = NavigateParams::IGNORE_AND_NAVIGATE;
   ShowSingletonTabOverwritingNTP(browser, params);
 }
@@ -76,10 +79,10 @@
 #if defined(OS_CHROMEOS) && defined(OFFICIAL_BUILD)
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
   if (!command_line->HasSwitch(chromeos::switches::kDisableGeniusApp)) {
-    const extensions::Extension* extension = profile->GetExtensionService()->
-        GetInstalledExtension(genius_app::kGeniusAppId);
-    OpenApplication(
-        AppLaunchParams(profile, extension, 0, host_desktop_type));
+    const extensions::Extension* extension =
+        profile->GetExtensionService()->GetInstalledExtension(
+            genius_app::kGeniusAppId);
+    OpenApplication(AppLaunchParams(profile, extension, 0, host_desktop_type));
     return;
   }
 #endif
@@ -176,8 +179,8 @@
 }
 
 void ShowHelp(Browser* browser, HelpSource source) {
-  ShowHelpImpl(browser, browser->profile(), browser->host_desktop_type(),
-      source);
+  ShowHelpImpl(
+      browser, browser->profile(), browser->host_desktop_type(), source);
 }
 
 void ShowHelpForProfile(Profile* profile,
@@ -196,22 +199,69 @@
 #endif
 }
 
-void ShowSettings(Browser* browser) {
-  content::RecordAction(UserMetricsAction("ShowOptions"));
-  ShowSettingsSubPage(browser, std::string());
-}
-
-void ShowSettingsSubPage(Browser* browser, const std::string& sub_page) {
+GURL GetSettingsUrl(const std::string& sub_page) {
   std::string url = std::string(kChromeUISettingsURL) + sub_page;
 #if defined(OS_CHROMEOS)
   if (sub_page.find(kInternetOptionsSubPage, 0) != std::string::npos) {
     std::string::size_type loc = sub_page.find("?", 0);
-    std::string network_page = loc != std::string::npos ?
-        sub_page.substr(loc) : std::string();
+    std::string network_page =
+        loc != std::string::npos ? sub_page.substr(loc) : std::string();
     url = std::string(kChromeUISettingsURL) + network_page;
   }
 #endif
-  NavigateParams params(GetSingletonTabNavigateParams(browser, GURL(url)));
+  return GURL(url);
+}
+
+bool IsSettingsWindow(const Browser* browser) {
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableSettingsWindow))
+    return false;
+  if (browser->is_type_tabbed())
+    return false;
+  const content::WebContents* web_contents =
+      browser->tab_strip_model()->GetWebContentsAt(0);
+  if (!web_contents)
+    return false;
+  GURL url(web_contents->GetURL());
+  return (url.SchemeIs(content::kChromeUIScheme) &&
+          url.spec().find(chrome::kChromeUISettingsURL) == 0);
+}
+
+void ShowSettings(Browser* browser) {
+  ShowSettingsSubPage(browser, std::string());
+}
+
+void ShowSettingsSubPage(Browser* browser, const std::string& sub_page) {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          ::switches::kEnableSettingsWindow)) {
+    SettingsWindowManager::GetInstance()->ShowForProfile(browser->profile(),
+                                                         sub_page);
+    return;
+  }
+  ShowSettingsSubPageInTabbedBrowser(browser, sub_page);
+}
+
+void ShowSettingsSubPageForProfile(Profile* profile,
+                                   const std::string& sub_page) {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          ::switches::kEnableSettingsWindow)) {
+    SettingsWindowManager::GetInstance()->ShowForProfile(profile, sub_page);
+    return;
+  }
+  Browser* browser =
+      chrome::FindTabbedBrowser(profile, false, HOST_DESKTOP_TYPE_NATIVE);
+  if (!browser) {
+    browser = new Browser(
+        Browser::CreateParams(profile, chrome::HOST_DESKTOP_TYPE_NATIVE));
+  }
+  ShowSettingsSubPageInTabbedBrowser(browser, sub_page);
+}
+
+void ShowSettingsSubPageInTabbedBrowser(Browser* browser,
+                                        const std::string& sub_page) {
+  content::RecordAction(UserMetricsAction("ShowOptions"));
+  GURL gurl = GetSettingsUrl(sub_page);
+  NavigateParams params(GetSingletonTabNavigateParams(browser, gurl));
   params.path_behavior = NavigateParams::IGNORE_AND_NAVIGATE;
   ShowSingletonTabOverwritingNTP(browser, params);
 }
@@ -221,8 +271,8 @@
   ShowSettingsSubPage(
       browser,
       kContentSettingsExceptionsSubPage + std::string(kHashMark) +
-      options::ContentSettingsHandler::ContentSettingsTypeToGroupName(
-          content_settings_type));
+          options::ContentSettingsHandler::ContentSettingsTypeToGroupName(
+              content_settings_type));
 }
 
 void ShowClearBrowsingDataDialog(Browser* browser) {
@@ -272,8 +322,7 @@
       browser = displayer->browser();
     }
 
-    NavigateToSingletonTab(browser,
-                           GURL(signin::GetPromoURL(source, false)));
+    NavigateToSingletonTab(browser, GURL(signin::GetPromoURL(source, false)));
     DCHECK_GT(browser->tab_strip_model()->count(), 0);
   }
 }
diff --git a/chrome/browser/ui/chrome_pages.h b/chrome/browser/ui/chrome_pages.h
index 29bee22..d780520 100644
--- a/chrome/browser/ui/chrome_pages.h
+++ b/chrome/browser/ui/chrome_pages.h
@@ -10,9 +10,9 @@
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/common/content_settings_types.h"
+#include "url/gurl.h"
 
 class Browser;
-class GURL;
 
 namespace content {
 class WebContents;
@@ -54,11 +54,21 @@
 void ShowPolicy(Browser* browser);
 void ShowSlow(Browser* browser);
 
+// Constructs a settings GURL for the specified |sub_page|.
+GURL GetSettingsUrl(const std::string& sub_page);
+
+// Returns true if |browser| is a popup window containing a settings page.
+bool IsSettingsWindow(const Browser* browser);
+
 // Various things that open in a settings UI.
 void ShowSettings(Browser* browser);
 void ShowSettingsSubPage(Browser* browser, const std::string& sub_page);
+void ShowSettingsSubPageForProfile(Profile* profile,
+                                   const std::string& sub_page);
 void ShowContentSettings(Browser* browser,
                          ContentSettingsType content_settings_type);
+void ShowSettingsSubPageInTabbedBrowser(Browser* browser,
+                                        const std::string& sub_page);
 void ShowClearBrowsingDataDialog(Browser* browser);
 void ShowPasswordManager(Browser* browser);
 void ShowImportDialog(Browser* browser);
diff --git a/chrome/browser/ui/cocoa/applescript/tab_applescript.mm b/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
index 8039244..3cce6a1 100644
--- a/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
+++ b/chrome/browser/ui/cocoa/applescript/tab_applescript.mm
@@ -166,23 +166,23 @@
 }
 
 - (void)handlesUndoScriptCommand:(NSScriptCommand*)command {
-  RenderViewHost* view = webContents_->GetRenderViewHost();
-  if (!view) {
+  RenderFrameHost* frame = webContents_->GetFocusedFrame();
+  if (!frame) {
     NOTREACHED();
     return;
   }
 
-  view->Undo();
+  frame->Undo();
 }
 
 - (void)handlesRedoScriptCommand:(NSScriptCommand*)command {
-  RenderViewHost* view = webContents_->GetRenderViewHost();
-  if (!view) {
+  RenderFrameHost* frame = webContents_->GetFocusedFrame();
+  if (!frame) {
     NOTREACHED();
     return;
   }
 
-  view->Redo();
+  frame->Redo();
 }
 
 - (void)handlesCutScriptCommand:(NSScriptCommand*)command {
@@ -216,13 +216,13 @@
 }
 
 - (void)handlesSelectAllScriptCommand:(NSScriptCommand*)command {
-  RenderViewHost* view = webContents_->GetRenderViewHost();
-  if (!view) {
+  RenderFrameHost* frame = webContents_->GetFocusedFrame();
+  if (!frame) {
     NOTREACHED();
     return;
   }
 
-  view->SelectAll();
+  frame->SelectAll();
 }
 
 - (void)handlesGoBackScriptCommand:(NSScriptCommand*)command {
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
index 6e925d1..de6dd55 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.h
@@ -101,15 +101,11 @@
   // Called to handle a key event.
   bool HandledByExtensionCommand(NSEvent* event);
 
-  // Called to handle a mouse event.
-  void HandleMouseEvent(NSEvent* event);
-
   // Returns true if |point| in local Cocoa coordinate system falls within
   // the draggable region.
   bool IsWithinDraggableRegion(NSPoint point) const;
 
   NSRect restored_bounds() const { return restored_bounds_; }
-  bool use_system_drag() const { return use_system_drag_; }
 
  protected:
   // NativeAppWindow implementation.
@@ -176,11 +172,6 @@
   void InstallView();
   void UninstallView();
   void InstallDraggableRegionViews();
-  void UpdateDraggableRegionsForSystemDrag(
-      const std::vector<extensions::DraggableRegion>& regions,
-      const extensions::DraggableRegion* draggable_area);
-  void UpdateDraggableRegionsForCustomDrag(
-      const std::vector<extensions::DraggableRegion>& regions);
 
   // Cache |restored_bounds_| only if the window is currently restored.
   void UpdateRestoredBounds();
@@ -212,22 +203,10 @@
   base::scoped_nsobject<NativeAppWindowController> window_controller_;
   NSInteger attention_request_id_;  // identifier from requestUserAttention
 
-  // Indicates whether system drag or custom drag should be used, depending on
-  // the complexity of draggable regions.
-  bool use_system_drag_;
-
   // For system drag, the whole window is draggable and the non-draggable areas
   // have to been explicitly excluded.
   std::vector<gfx::Rect> system_drag_exclude_areas_;
 
-  // For custom drag, the whole window is non-draggable and the draggable region
-  // has to been explicitly provided.
-  scoped_ptr<SkRegion> draggable_region_;  // used in custom drag.
-
-  // Mouse location since the last mouse event, in screen coordinates. This is
-  // used in custom drag to compute the window movement.
-  NSPoint last_mouse_location_;
-
   // The Extension Command Registry used to determine which keyboard events to
   // handle.
   scoped_ptr<ExtensionKeybindingRegistryCocoa> extension_keybinding_registry_;
diff --git a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
index 7f842a8..2d949c0 100644
--- a/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/apps/native_app_window_cocoa.mm
@@ -13,6 +13,7 @@
 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
 #include "chrome/browser/ui/cocoa/extensions/extension_keybinding_registry_cocoa.h"
 #include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h"
+#import "chrome/browser/ui/cocoa/nsview_additions.h"
 #include "chrome/common/chrome_switches.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/render_widget_host_view.h"
@@ -20,6 +21,7 @@
 #include "content/public/browser/web_contents_view.h"
 #include "extensions/common/extension.h"
 #include "third_party/skia/include/core/SkRegion.h"
+#include "ui/gfx/skia_util.h"
 
 // NOTE: State Before Update.
 //
@@ -104,6 +106,25 @@
   return cocoa_bounds;
 }
 
+// Return a vector of non-draggable regions that fill a window of size
+// |width| by |height|, but leave gaps where the window should be draggable.
+std::vector<gfx::Rect> CalculateNonDraggableRegions(
+    const std::vector<extensions::DraggableRegion>& regions,
+    int width,
+    int height) {
+  scoped_ptr<SkRegion> draggable(
+      AppWindow::RawDraggableRegionsToSkRegion(regions));
+  scoped_ptr<SkRegion> non_draggable(new SkRegion);
+  non_draggable->op(0, 0, width, height, SkRegion::kUnion_Op);
+  non_draggable->op(*draggable, SkRegion::kDifference_Op);
+
+  std::vector<gfx::Rect> result;
+  for (SkRegion::Iterator it(*non_draggable); !it.done(); it.next()) {
+    result.push_back(gfx::SkIRectToRect(it.rect()));
+  }
+  return result;
+}
+
 }  // namespace
 
 @implementation NativeAppWindowController
@@ -251,39 +272,17 @@
 
 @end
 
-@interface ControlRegionView : NSView {
- @private
-  NativeAppWindowCocoa* appWindow_;  // Weak; owns self.
-}
-
+@interface ControlRegionView : NSView
 @end
 
 @implementation ControlRegionView
 
-- (id)initWithAppWindow:(NativeAppWindowCocoa*)appWindow {
-  if ((self = [super init]))
-    appWindow_ = appWindow;
-  return self;
-}
-
 - (BOOL)mouseDownCanMoveWindow {
   return NO;
 }
 
 - (NSView*)hitTest:(NSPoint)aPoint {
-  if (appWindow_->use_system_drag() ||
-      !appWindow_->IsWithinDraggableRegion(aPoint)) {
-    return nil;
-  }
-  return self;
-}
-
-- (void)mouseDown:(NSEvent*)event {
-  appWindow_->HandleMouseEvent(event);
-}
-
-- (void)mouseDragged:(NSEvent*)event {
-  appWindow_->HandleMouseEvent(event);
+  return nil;
 }
 
 @end
@@ -304,8 +303,7 @@
       is_resizable_(params.resizable),
       shows_resize_controls_(true),
       shows_fullscreen_controls_(true),
-      attention_request_id_(0),
-      use_system_drag_(true) {
+      attention_request_id_(0) {
   Observe(web_contents());
 
   base::scoped_nsobject<NSWindow> window;
@@ -330,6 +328,7 @@
                   backing:NSBackingStoreBuffered
                     defer:NO]);
   [window setTitle:base::SysUTF8ToNSString(extension()->name())];
+  [[window contentView] cr_setWantsLayer:YES];
 
   if (base::mac::IsOSSnowLeopard() &&
       [window respondsToSelector:@selector(setBottomCornerRounded:)])
@@ -642,127 +641,17 @@
   if (has_frame_)
     return;
 
-  // To use system drag, the window has to be marked as draggable with
-  // non-draggable areas being excluded via overlapping views.
-  // 1) If no draggable area is provided, the window is not draggable at all.
-  // 2) If only one draggable area is given, as this is the most common
-  //    case, use the system drag. The non-draggable areas that are opposite of
-  //    the draggable area are computed.
-  // 3) Otherwise, use the custom drag. As such, we lose the capability to
-  //    support some features like snapping into other space.
-
-  // Determine how to perform the drag by counting the number of draggable
-  // areas.
-  const extensions::DraggableRegion* draggable_area = NULL;
-  use_system_drag_ = true;
-  for (std::vector<extensions::DraggableRegion>::const_iterator iter =
-           regions.begin();
-       iter != regions.end();
-       ++iter) {
-    if (iter->draggable) {
-      // If more than one draggable area is found, use custom drag.
-      if (draggable_area) {
-        use_system_drag_ = false;
-        break;
-      }
-      draggable_area = &(*iter);
-    }
-  }
-
-  if (use_system_drag_)
-    UpdateDraggableRegionsForSystemDrag(regions, draggable_area);
-  else
-    UpdateDraggableRegionsForCustomDrag(regions);
+  // Draggable regions is implemented by having the whole web view draggable
+  // (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
+  NSView* web_view = web_contents()->GetView()->GetNativeView();
+  system_drag_exclude_areas_ = CalculateNonDraggableRegions(
+      regions, NSWidth([web_view bounds]), NSHeight([web_view bounds]));
 
   InstallDraggableRegionViews();
 }
 
 SkRegion* NativeAppWindowCocoa::GetDraggableRegion() {
-  return draggable_region_.get();
-}
-
-void NativeAppWindowCocoa::UpdateDraggableRegionsForSystemDrag(
-    const std::vector<extensions::DraggableRegion>& regions,
-    const extensions::DraggableRegion* draggable_area) {
-  NSView* web_view = web_contents()->GetView()->GetNativeView();
-  NSInteger web_view_width = NSWidth([web_view bounds]);
-  NSInteger web_view_height = NSHeight([web_view bounds]);
-
-  system_drag_exclude_areas_.clear();
-
-  // The whole window is not draggable if no draggable area is given.
-  if (!draggable_area) {
-    gfx::Rect window_bounds(0, 0, web_view_width, web_view_height);
-    system_drag_exclude_areas_.push_back(window_bounds);
-    return;
-  }
-
-  // Otherwise, there is only one draggable area. Compute non-draggable areas
-  // that are the opposite of the given draggable area, combined with the
-  // remaining provided non-draggable areas.
-
-  // Copy all given non-draggable areas.
-  for (std::vector<extensions::DraggableRegion>::const_iterator iter =
-           regions.begin();
-       iter != regions.end();
-       ++iter) {
-    if (!iter->draggable)
-      system_drag_exclude_areas_.push_back(iter->bounds);
-  }
-
-  gfx::Rect draggable_bounds = draggable_area->bounds;
-  gfx::Rect non_draggable_bounds;
-
-  // Add the non-draggable area above the given draggable area.
-  if (draggable_bounds.y() > 0) {
-    non_draggable_bounds.SetRect(0,
-                                 0,
-                                 web_view_width,
-                                 draggable_bounds.y() - 1);
-    system_drag_exclude_areas_.push_back(non_draggable_bounds);
-  }
-
-  // Add the non-draggable area below the given draggable area.
-  if (draggable_bounds.bottom() < web_view_height) {
-    non_draggable_bounds.SetRect(0,
-                                 draggable_bounds.bottom() + 1,
-                                 web_view_width,
-                                 web_view_height - draggable_bounds.bottom());
-    system_drag_exclude_areas_.push_back(non_draggable_bounds);
-  }
-
-  // Add the non-draggable area to the left of the given draggable area.
-  if (draggable_bounds.x() > 0) {
-    non_draggable_bounds.SetRect(0,
-                                 draggable_bounds.y(),
-                                 draggable_bounds.x() - 1,
-                                 draggable_bounds.height());
-    system_drag_exclude_areas_.push_back(non_draggable_bounds);
-  }
-
-  // Add the non-draggable area to the right of the given draggable area.
-  if (draggable_bounds.right() < web_view_width) {
-    non_draggable_bounds.SetRect(draggable_bounds.right() + 1,
-                                 draggable_bounds.y(),
-                                 web_view_width - draggable_bounds.right(),
-                                 draggable_bounds.height());
-    system_drag_exclude_areas_.push_back(non_draggable_bounds);
-  }
-}
-
-void NativeAppWindowCocoa::UpdateDraggableRegionsForCustomDrag(
-    const std::vector<extensions::DraggableRegion>& regions) {
-  // We still need one ControlRegionView to cover the whole window such that
-  // mouse events could be captured.
-  NSView* web_view = web_contents()->GetView()->GetNativeView();
-  gfx::Rect window_bounds(
-      0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds]));
-  system_drag_exclude_areas_.clear();
-  system_drag_exclude_areas_.push_back(window_bounds);
-
-  // Aggregate the draggable areas and non-draggable areas such that hit test
-  // could be performed easily.
-  draggable_region_.reset(AppWindow::RawDraggableRegionsToSkRegion(regions));
+  return NULL;
 }
 
 void NativeAppWindowCocoa::HandleKeyboardEvent(
@@ -799,7 +688,7 @@
        iter != system_drag_exclude_areas_.end();
        ++iter) {
     base::scoped_nsobject<NSView> controlRegion(
-        [[ControlRegionView alloc] initWithAppWindow:this]);
+        [[ControlRegionView alloc] initWithFrame:NSZeroRect]);
     [controlRegion setFrame:NSMakeRect(iter->x(),
                                        webViewHeight - iter->bottom(),
                                        iter->width(),
@@ -969,32 +858,6 @@
       content::NativeWebKeyboardEvent(event));
 }
 
-void NativeAppWindowCocoa::HandleMouseEvent(NSEvent* event) {
-  if ([event type] == NSLeftMouseDown) {
-    last_mouse_location_ =
-        [window() convertBaseToScreen:[event locationInWindow]];
-  } else if ([event type] == NSLeftMouseDragged) {
-    NSPoint current_mouse_location =
-        [window() convertBaseToScreen:[event locationInWindow]];
-    NSPoint frame_origin = [window() frame].origin;
-    frame_origin.x += current_mouse_location.x - last_mouse_location_.x;
-    frame_origin.y += current_mouse_location.y - last_mouse_location_.y;
-    [window() setFrameOrigin:frame_origin];
-    last_mouse_location_ = current_mouse_location;
-  }
-}
-
-bool NativeAppWindowCocoa::IsWithinDraggableRegion(NSPoint point) const {
-  if (!draggable_region_)
-    return false;
-  NSView* webView = web_contents()->GetView()->GetNativeView();
-  NSInteger webViewHeight = NSHeight([webView bounds]);
-  // |draggable_region_| is stored in local platform-indepdent coordiate system
-  // while |point| is in local Cocoa coordinate system. Do the conversion
-  // to match these two.
-  return draggable_region_->contains(point.x, webViewHeight - point.y);
-}
-
 void NativeAppWindowCocoa::ShowWithApp() {
   is_hidden_with_app_ = false;
   if (!is_hidden_)
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
index 4ee0bba..356f795 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_popup_view_cocoa.mm
@@ -159,7 +159,8 @@
                                fromView:nil];
 
   if (NSPointInRect(location, [self bounds])) {
-    controller_->AcceptSelectionAtPoint(gfx::Point(NSPointToCGPoint(location)));
+    controller_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location)));
+    controller_->AcceptSelectedLine();
   }
 }
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm b/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm
index 1cf70c8..500e392 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_container.mm
@@ -324,6 +324,7 @@
 
 - (void)update {
   [self updateAndClobber:YES];
+  [view_ updateHoverState];
 }
 
 - (void)fillForType:(const autofill::ServerFieldType)type {
@@ -437,12 +438,14 @@
                                                              type,
                                                              fieldValue);
     [textfield setValidityMessage:base::SysUTF16ToNSString(message)];
-    [validationDelegate_ updateMessageForField:textfield];
 
     // If the field transitioned from invalid to valid, re-validate the group,
     // since inter-field checks become meaningful with valid fields.
     if (![textfield invalid])
       [self validateFor:autofill::VALIDATE_EDIT];
+
+    // The validity message has potentially changed - notify the error bubble.
+    [validationDelegate_ updateMessageForField:textfield];
   }
 
   // Update the icon if necessary.
@@ -639,9 +642,12 @@
       base::scoped_nsobject<AutofillPopUpButton> popup(
           [[AutofillPopUpButton alloc] initWithFrame:NSZeroRect pullsDown:NO]);
       for (int i = 0; i < inputModel->GetItemCount(); ++i) {
-        if (inputModel->IsItemSeparatorAt(i)) {
-          [[popup menu] addItem:[NSMenuItem separatorItem]];
-        } else {
+        if (!inputModel->IsItemSeparatorAt(i)) {
+          // Currently, the first item in |inputModel| is duplicated later in
+          // the list. The second item is a separator. Because NSPopUpButton
+          // de-duplicates, the menu's just left with a separator on the top of
+          // the list (with nothing it's separating). For that reason,
+          // separators are ignored on Mac for now. http://crbug.com/347653
           [popup addItemWithTitle:
               base::SysUTF16ToNSString(inputModel->GetItemAt(i))];
         }
@@ -656,6 +662,12 @@
           l10n_util::FixUpWindowsStyleLabel(input.placeholder_text)];
       NSString* tooltipText =
           base::SysUTF16ToNSString(delegate_->TooltipForField(input.type));
+      // VoiceOver onlys seems to pick up the help message on [field cell]
+      // (rather than just field).
+      BOOL success = [[field cell]
+          accessibilitySetOverrideValue:tooltipText
+                           forAttribute:NSAccessibilityHelpAttribute];
+      DCHECK(success);
       if ([tooltipText length] > 0) {
         if (!tooltipController_) {
           tooltipController_.reset(
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_view.h b/chrome/browser/ui/cocoa/autofill/autofill_section_view.h
index 1f3156d..a85bb1b 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_view.h
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_view.h
@@ -18,6 +18,10 @@
   BOOL shouldHighlightOnHover_;  // Indicates if view should highlight on hover
 }
 
+// Resets tracking info. Useful if e.g. the mouse has changed inside/outside
+// status during a popup menu's runloop.
+- (void)updateHoverState;
+
 // Target for any mouse click.
 @property(assign, nonatomic) NSControl* clickTarget;
 
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_section_view.mm b/chrome/browser/ui/cocoa/autofill/autofill_section_view.mm
index 4d77362..e10435a 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_section_view.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_section_view.mm
@@ -20,6 +20,12 @@
 @synthesize shouldHighlightOnHover = shouldHighlightOnHover_;
 @synthesize isHighlighted = isHighlighted_;
 
+- (void)updateHoverState {
+  NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
+  mouseLoc = [self convertPoint:mouseLoc fromView:nil];
+  [self setIsHighlighted:NSPointInRect(mouseLoc, [self bounds])];
+}
+
 - (void)mouseEvent:(NSEvent*)event {
   if ([event type] == NSMouseExited)
     [self setIsHighlighted:NO];
diff --git a/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.mm b/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.mm
index 6af255b..b2a66dc 100644
--- a/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.mm
+++ b/chrome/browser/ui/cocoa/autofill/autofill_tooltip_controller.mm
@@ -62,6 +62,10 @@
   [tooltipController_ updateTooltipDisplayState];
 }
 
+- (BOOL)acceptsFirstResponder {
+  return NO;
+}
+
 @end
 
 #pragma mark AutofillTrackingView
diff --git a/chrome/browser/ui/cocoa/browser/avatar_base_controller.h b/chrome/browser/ui/cocoa/browser/avatar_base_controller.h
index e670fbd..4c8c108 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_base_controller.h
+++ b/chrome/browser/ui/cocoa/browser/avatar_base_controller.h
@@ -9,6 +9,7 @@
 
 #import "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/browser_window.h"
 
 @class BaseBubbleController;
 class Browser;
@@ -38,8 +39,9 @@
 // Designated initializer.
 - (id)initWithBrowser:(Browser*)browser;
 
-// Shows the avatar bubble.
-- (void)showAvatarBubble:(NSView*)anchor;
+// Shows the avatar bubble in the given mode.
+- (void)showAvatarBubble:(NSView*)anchor
+                withMode:(BrowserWindow::AvatarBubbleMode)mode;
 
 @end
 
diff --git a/chrome/browser/ui/cocoa/browser/avatar_base_controller.mm b/chrome/browser/ui/cocoa/browser/avatar_base_controller.mm
index 85fa8b4..9f5b6a5 100644
--- a/chrome/browser/ui/cocoa/browser/avatar_base_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/avatar_base_controller.mm
@@ -97,7 +97,8 @@
   return button_.get();
 }
 
-- (void)showAvatarBubble:(NSView*)anchor {
+- (void)showAvatarBubble:(NSView*)anchor
+                withMode:(BrowserWindow::AvatarBubbleMode)mode {
   if (menuController_)
     return;
 
@@ -110,16 +111,25 @@
         lockBarVisibilityForOwner:self withAnimation:NO delay:NO];
   }
 
-  NSPoint point = NSMakePoint(NSMidX([anchor bounds]),
+  // The new avatar bubble does not have an arrow, and it should be anchored
+  // to the edge of the avatar button.
+  int anchorX = switches::IsNewProfileManagement() ? NSMaxX([anchor bounds]) :
+                                                     NSMidX([anchor bounds]);
+  NSPoint point = NSMakePoint(anchorX,
                               NSMaxY([anchor bounds]) - kMenuYOffsetAdjust);
   point = [anchor convertPoint:point toView:nil];
   point = [[anchor window] convertBaseToScreen:point];
 
   // |menuController_| will automatically release itself on close.
   if (switches::IsNewProfileManagement()) {
+    BubbleViewMode viewMode =
+        mode == BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT ?
+        PROFILE_CHOOSER_VIEW :
+        ACCOUNT_MANAGEMENT_VIEW;
     menuController_ =
-      [[ProfileChooserController alloc] initWithBrowser:browser_
-                                             anchoredAt:point];
+        [[ProfileChooserController alloc] initWithBrowser:browser_
+                                               anchoredAt:point
+                                                 withMode:viewMode];
   } else {
     menuController_ =
       [[AvatarMenuBubbleController alloc] initWithBrowser:browser_
@@ -138,7 +148,8 @@
 
 - (IBAction)buttonClicked:(id)sender {
   DCHECK_EQ(sender, button_.get());
-  [self showAvatarBubble:button_];
+  [self showAvatarBubble:button_
+                withMode:BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT];
 }
 
 - (void)bubbleWillClose:(NSNotification*)notif {
@@ -160,4 +171,3 @@
 }
 
 @end
-
diff --git a/chrome/browser/ui/cocoa/browser/profile_chooser_controller.h b/chrome/browser/ui/cocoa/browser/profile_chooser_controller.h
index 0157405..3391193 100644
--- a/chrome/browser/ui/cocoa/browser/profile_chooser_controller.h
+++ b/chrome/browser/ui/cocoa/browser/profile_chooser_controller.h
@@ -23,7 +23,7 @@
 // This window controller manages the bubble that displays a "menu" of profiles.
 // It is brought open by clicking on the avatar icon in the window frame.
 @interface ProfileChooserController : BaseBubbleController {
- @private
+ @public
   // Different views that can be displayed in the bubble.
   enum BubbleViewMode {
     PROFILE_CHOOSER_VIEW,     // Shows a "fast profile switcher" view.
@@ -32,6 +32,7 @@
     GAIA_ADD_ACCOUNT_VIEW     // Shows a web view for adding secondary accounts.
   };
 
+ @private
   // The menu that contains the data from the backend.
   scoped_ptr<AvatarMenu> avatarMenu_;
 
@@ -60,7 +61,9 @@
   BOOL isGuestSession_;
 }
 
-- (id)initWithBrowser:(Browser*)browser anchoredAt:(NSPoint)point;
+- (id)initWithBrowser:(Browser*)browser
+           anchoredAt:(NSPoint)point
+             withMode:(BubbleViewMode)mode;
 
 // Creates all the subviews of the avatar bubble for |viewToDisplay|.
 - (void)initMenuContentsWithView:(BubbleViewMode)viewToDisplay;
@@ -68,21 +71,12 @@
 // Returns the view currently displayed by the bubble.
 - (BubbleViewMode)viewMode;
 
-// Creates a new profile.
-- (IBAction)addNewProfile:(id)sender;
-
 // Switches to a given profile. |sender| is an ProfileChooserItemController.
 - (IBAction)switchToProfile:(id)sender;
 
 // Shows the User Manager.
 - (IBAction)showUserManager:(id)sender;
 
-// Starts a guest browser window.
-- (IBAction)switchToGuestProfile:(id)sender;
-
-// Closes all guest browser windows.
-- (IBAction)exitGuestProfile:(id)sender;
-
 // Shows the account management view.
 - (IBAction)showAccountManagement:(id)sender;
 
@@ -105,7 +99,9 @@
 // Testing API /////////////////////////////////////////////////////////////////
 
 @interface ProfileChooserController (ExposedForTesting)
-- (id)initWithBrowser:(Browser*)browser anchoredAt:(NSPoint)point;
+- (id)initWithBrowser:(Browser*)browser
+           anchoredAt:(NSPoint)point
+             withMode:(BubbleViewMode)mode;
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_BROWSER_PROFILE_CHOOSER_CONTROLLER_H_
diff --git a/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm b/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm
index 69e4eca..7b09c5e 100644
--- a/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm
+++ b/chrome/browser/ui/cocoa/browser/profile_chooser_controller.mm
@@ -33,9 +33,10 @@
 #import "chrome/browser/ui/cocoa/user_manager_mac.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/profile_management_switches.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/mutable_profile_oauth2_token_service.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
@@ -492,24 +493,10 @@
 
   NSColor* backgroundColor = gfx::SkColorToCalibratedNSColor(
       ui::NativeTheme::instance()->GetSystemColor(isHighlighted?
-          ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor :
-          ui::NativeTheme::kColorId_MenuBackgroundColor));
+          ui::NativeTheme::kColorId_MenuSeparatorColor :
+          ui::NativeTheme::kColorId_DialogBackground));
 
   [[self cell] setBackgroundColor:backgroundColor];
-
-  // When hovered, the button text should be white.
-  NSColor* textColor =
-      isHighlighted ? [NSColor whiteColor] : [NSColor blackColor];
-  base::scoped_nsobject<NSMutableParagraphStyle> textStyle(
-      [[NSMutableParagraphStyle alloc] init]);
-  [textStyle setAlignment:NSLeftTextAlignment];
-
-  base::scoped_nsobject<NSAttributedString> attributedTitle(
-      [[NSAttributedString alloc]
-          initWithString:[self title]
-              attributes:@{ NSParagraphStyleAttributeName : textStyle,
-                            NSForegroundColorAttributeName : textColor }]);
-  [self setAttributedTitle:attributedTitle];
 }
 
 @end
@@ -534,8 +521,9 @@
 // switcher in the middle of the bubble.
 - (NSButton*)createOtherProfileView:(int)itemIndex;
 
-// Creates the Guest / Add person / View all persons buttons.
-- (NSView*)createOptionsViewWithRect:(NSRect)rect;
+// Creates the "Not you" and Lock option buttons.
+- (NSView*)createOptionsViewWithRect:(NSRect)rect
+                          enableLock:(BOOL)enableLock;
 
 // Creates the account management view for the active profile.
 - (NSView*)createCurrentProfileAccountsView:(NSRect)rect;
@@ -546,11 +534,11 @@
 // Creates the Gaia sign-in/add account view.
 - (NSView*)createGaiaEmbeddedView;
 
-// Creates a button with text given by |textResourceId|, an icon given by
-// |imageResourceId| and with |action|. The icon |alternateImageResourceId| is
-// displayed in the button's hovered and pressed states.
+// Creates a button with |text|, an icon given by |imageResourceId| and with
+// |action|. The icon |alternateImageResourceId| is displayed in the button's
+// hovered and pressed states.
 - (NSButton*)hoverButtonWithRect:(NSRect)rect
-                  textResourceId:(int)textResourceId
+                            text:(NSString*)text
                  imageResourceId:(int)imageResourceId
         alternateImageResourceId:(int)alternateImageResourceId
                           action:(SEL)action;
@@ -577,13 +565,6 @@
   return viewMode_;
 }
 
-- (IBAction)addNewProfile:(id)sender {
-  profiles::CreateAndSwitchToNewProfile(
-      browser_->host_desktop_type(),
-      profiles::ProfileSwitchingDoneCallback(),
-      ProfileMetrics::ADD_NEW_USER_ICON);
-}
-
 - (IBAction)switchToProfile:(id)sender {
   // Check the event flags to see if a new window should be created.
   bool alwaysCreate = ui::WindowOpenDispositionFromNSEvent(
@@ -598,15 +579,6 @@
       isGuestSession_ ? NULL : browser_->profile());
 }
 
-- (IBAction)switchToGuestProfile:(id)sender {
-  profiles::SwitchToGuestProfile(browser_->host_desktop_type(),
-                                 profiles::ProfileSwitchingDoneCallback());
-}
-
-- (IBAction)exitGuestProfile:(id)sender {
-  profiles::CloseGuestProfileWindows();
-}
-
 - (IBAction)showAccountManagement:(id)sender {
   [self initMenuContentsWithView:ACCOUNT_MANAGEMENT_VIEW];
 }
@@ -655,7 +627,9 @@
   webContents_.reset();
 }
 
-- (id)initWithBrowser:(Browser*)browser anchoredAt:(NSPoint)point {
+- (id)initWithBrowser:(Browser*)browser
+           anchoredAt:(NSPoint)point
+             withMode:(BubbleViewMode)mode {
   base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
       initWithContentRect:ui::kWindowSizeDeterminedLater
                 styleMask:NSBorderlessWindowMask
@@ -666,7 +640,7 @@
                        parentWindow:browser->window()->GetNativeWindow()
                          anchoredAt:point])) {
     browser_ = browser;
-    viewMode_ = PROFILE_CHOOSER_VIEW;
+    viewMode_ = mode;
     tutorialShowing_ = false;
     observer_.reset(new ActiveProfileObserverBridge(self, browser_));
 
@@ -679,7 +653,12 @@
     // Guest profiles do not have a token service.
     isGuestSession_ = browser_->profile()->IsGuestSession();
 
-    [[self bubble] setArrowLocation:info_bubble::kTopRight];
+    ui::NativeTheme* nativeTheme = ui::NativeTheme::instance();
+    [[self bubble] setAlignment:info_bubble::kAlignRightEdgeToAnchorEdge];
+    [[self bubble] setArrowLocation:info_bubble::kNoArrow];
+    [[self bubble] setBackgroundColor:
+        gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor(
+            ui::NativeTheme::kColorId_DialogBackground))];
     [self initMenuContentsWithView:viewMode_];
   }
 
@@ -702,6 +681,8 @@
   NSView* currentProfileView = nil;
   base::scoped_nsobject<NSMutableArray> otherProfiles(
       [[NSMutableArray alloc] init]);
+  // Local and guest profiles cannot lock their profile.
+  bool enableLock = false;
 
   // Loop over the profiles in reverse, so that they are sorted by their
   // y-coordinate, and separate them into active and "other" profiles.
@@ -711,6 +692,7 @@
       if (viewMode_ == PROFILE_CHOOSER_VIEW)
         tutorialView = [self createTutorialViewIfNeeded:item];
       currentProfileView = [self createCurrentProfileView:item];
+      enableLock = item.signed_in;
     } else {
       [otherProfiles addObject:[self createOtherProfileView:i]];
     }
@@ -722,9 +704,10 @@
   // coordinates.
   CGFloat yOffset = kSmallVerticalSpacing;
 
-  // Guest / Add Person / View All Persons buttons.
+  // Option buttons.
   NSView* optionsView = [self createOptionsViewWithRect:
-      NSMakeRect(0, yOffset, kFixedMenuWidth, 0)];
+      NSMakeRect(0, yOffset, kFixedMenuWidth, 0)
+                                        enableLock:enableLock];
   [contentView addSubview:optionsView];
   yOffset = NSMaxY([optionsView frame]) + kSmallVerticalSpacing;
 
@@ -733,7 +716,8 @@
   [contentView addSubview:separator];
   yOffset = NSMaxY([separator frame]) + kVerticalSpacing;
 
-  if (viewToDisplay == PROFILE_CHOOSER_VIEW) {
+  if (viewToDisplay == PROFILE_CHOOSER_VIEW &&
+      switches::IsFastUserSwitching()) {
     // Other profiles switcher. The profiles have already been sorted
     // by their y-coordinate, so they can be added in the existing order.
     for (NSView *otherProfileView in otherProfiles.get()) {
@@ -920,48 +904,26 @@
                                 withXOffset:(CGFloat)xOffset {
   base::scoped_nsobject<NSView> container([[NSView alloc]
       initWithFrame:NSZeroRect]);
-  CGFloat maxX = 0;  // Ensure the container is wide enough for all the links.
-  CGFloat yOffset;
 
+  NSButton* link;
+  NSPoint frameOrigin = NSMakePoint(xOffset, kSmallVerticalSpacing);
   // The available links depend on the type of profile that is active.
   if (item.signed_in) {
-    yOffset = 0;
-    // We need to display 2 links instead of 1, so make the padding in between
-    // the links even smaller to fit.
-    const CGFloat kLinkSpacing = kSmallVerticalSpacing / 2;
-    NSButton* manageAccountsLink =
-        [self linkButtonWithTitle:l10n_util::GetNSString(
-            IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON)
-                      frameOrigin:NSMakePoint(xOffset, yOffset)
-                           action:@selector(showAccountManagement:)];
-    yOffset = NSMaxY([manageAccountsLink frame]) + kLinkSpacing;
-
-    NSButton* signOutLink =
-        [self linkButtonWithTitle:l10n_util::GetNSString(
-            IDS_PROFILES_PROFILE_SIGNOUT_BUTTON)
-                      frameOrigin:NSMakePoint(xOffset, yOffset)
-                           action:@selector(lockProfile:)];
-    yOffset = NSMaxY([signOutLink frame]);
-
-    maxX = std::max(NSMaxX([manageAccountsLink frame]),
-                                 NSMaxX([signOutLink frame]));
-    [container addSubview:manageAccountsLink];
-    [container addSubview:signOutLink];
+    link = [self linkButtonWithTitle:l10n_util::GetNSString(
+        IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON)
+                         frameOrigin:frameOrigin
+                              action:@selector(showAccountManagement:)];
   } else {
-    yOffset = kSmallVerticalSpacing;
-    NSButton* signInLink =
-        [self linkButtonWithTitle:l10n_util::GetNSStringFWithFixup(
-            IDS_SYNC_START_SYNC_BUTTON_LABEL,
-            l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME))
-                      frameOrigin:NSMakePoint(xOffset, yOffset)
-                           action:@selector(showSigninPage:)];
-    yOffset = NSMaxY([signInLink frame]) + kSmallVerticalSpacing;
-    maxX = NSMaxX([signInLink frame]);
-
-    [container addSubview:signInLink];
+    link = [self linkButtonWithTitle:l10n_util::GetNSStringFWithFixup(
+        IDS_SYNC_START_SYNC_BUTTON_LABEL,
+        l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME))
+                         frameOrigin:frameOrigin
+                              action:@selector(showSigninPage:)];
   }
 
-  [container setFrameSize:NSMakeSize(maxX, yOffset)];
+  [container addSubview:link];
+  [container setFrameSize:NSMakeSize(
+      NSMaxX([link frame]), NSMaxY([link frame]) + kSmallVerticalSpacing)];
   return container.autorelease();
 }
 
@@ -1011,38 +973,38 @@
   return profileButton.autorelease();
 }
 
-- (NSView*)createOptionsViewWithRect:(NSRect)rect {
-  NSRect viewRect = NSMakeRect(0, 0, rect.size.width, kBlueButtonHeight);
-  NSButton* allUsersButton =
+- (NSView*)createOptionsViewWithRect:(NSRect)rect
+                          enableLock:(BOOL)enableLock {
+  int widthOfLockButton = enableLock? 2 * kHorizontalSpacing + 12 : 0;
+  NSRect viewRect = NSMakeRect(0, 0,
+                               rect.size.width - widthOfLockButton,
+                               kBlueButtonHeight);
+  NSButton* notYouButton =
       [self hoverButtonWithRect:viewRect
-                 textResourceId:IDS_PROFILES_ALL_PEOPLE_BUTTON
-                imageResourceId:IDR_ICON_PROFILES_ADD_USER
-       alternateImageResourceId:IDR_ICON_PROFILES_ADD_USER_WHITE
+                           text:l10n_util::GetNSStringF(
+          IDS_PROFILES_NOT_YOU_BUTTON,
+          profiles::GetAvatarNameForProfile(browser_->profile()))
+                imageResourceId:IDR_ICON_PROFILES_MENU_AVATAR
+       alternateImageResourceId:IDR_ICON_PROFILES_MENU_AVATAR
                          action:@selector(showUserManager:)];
-  viewRect.origin.y = NSMaxY([allUsersButton frame]);
 
-  NSButton* addUserButton =
-      [self hoverButtonWithRect:viewRect
-                 textResourceId:IDS_PROFILES_ADD_PERSON_BUTTON
-                imageResourceId:IDR_ICON_PROFILES_ADD_USER
-       alternateImageResourceId:IDR_ICON_PROFILES_ADD_USER_WHITE
-                         action:@selector(addNewProfile:)];
-  viewRect.origin.y = NSMaxY([addUserButton frame]);
-
-  int guestButtonText = isGuestSession_ ? IDS_PROFILES_EXIT_GUEST_BUTTON :
-                                          IDS_PROFILES_GUEST_BUTTON;
-  SEL guestButtonAction = isGuestSession_ ? @selector(exitGuestProfile:) :
-                                            @selector(switchToGuestProfile:);
-  NSButton* guestButton =
-      [self hoverButtonWithRect:viewRect
-                 textResourceId:guestButtonText
-                imageResourceId:IDR_ICON_PROFILES_BROWSE_GUEST
-       alternateImageResourceId:IDR_ICON_PROFILES_BROWSE_GUEST_WHITE
-                         action:guestButtonAction];
-  rect.size.height = NSMaxY([guestButton frame]);
+  rect.size.height = NSMaxY([notYouButton frame]);
   base::scoped_nsobject<NSView> container([[NSView alloc]
       initWithFrame:rect]);
-  [container setSubviews:@[allUsersButton, addUserButton, guestButton]];
+  [container addSubview:notYouButton];
+
+  if (enableLock) {
+    viewRect.origin.x = NSMaxX([notYouButton frame]);
+    viewRect.size.width = widthOfLockButton;
+    NSButton* lockButton =
+        [self hoverButtonWithRect:viewRect
+                             text:@""
+                  imageResourceId:IDR_ICON_PROFILES_MENU_LOCK
+         alternateImageResourceId:IDR_ICON_PROFILES_MENU_LOCK
+                           action:@selector(lockProfile:)];
+    [container addSubview:lockButton];
+  }
+
   return container.autorelease();
 }
 
@@ -1143,14 +1105,14 @@
 }
 
 - (NSButton*)hoverButtonWithRect:(NSRect)rect
-                  textResourceId:(int)textResourceId
+                            text:(NSString*)text
                  imageResourceId:(int)imageResourceId
         alternateImageResourceId:(int)alternateImageResourceId
                           action:(SEL)action  {
   base::scoped_nsobject<BackgroundColorHoverButton> button(
       [[BackgroundColorHoverButton alloc] initWithFrame:rect]);
 
-  [button setTitle:l10n_util::GetNSString(textResourceId)];
+  [button setTitle:text];
   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
   NSImage* alternateImage = rb->GetNativeImageNamed(
       alternateImageResourceId).ToNSImage();
diff --git a/chrome/browser/ui/cocoa/browser/profile_chooser_controller_unittest.mm b/chrome/browser/ui/cocoa/browser/profile_chooser_controller_unittest.mm
index 89617b7..2866637 100644
--- a/chrome/browser/ui/cocoa/browser/profile_chooser_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser/profile_chooser_controller_unittest.mm
@@ -4,6 +4,7 @@
 
 #import "chrome/browser/ui/cocoa/browser/profile_chooser_controller.h"
 
+#include "base/command_line.h"
 #include "base/mac/scoped_nsobject.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/sys_string_conversions.h"
@@ -12,13 +13,14 @@
 #include "chrome/browser/profiles/avatar_menu.h"
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "chrome/common/chrome_switches.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 
 const std::string kEmail = "user@gmail.com";
 const std::string kSecondaryEmail = "user2@gmail.com";
@@ -36,7 +38,7 @@
     TestingProfile::TestingFactories factories;
     factories.push_back(
         std::make_pair(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                       FakeProfileOAuth2TokenServiceWrapper::Build));
+                       BuildFakeProfileOAuth2TokenService));
     testing_profile_manager()->
         CreateTestingProfile("test1", scoped_ptr<PrefServiceSyncable>(),
                              base::ASCIIToUTF16("Test 1"), 0, std::string(),
@@ -63,9 +65,10 @@
   void StartProfileChooserController() {
     NSRect frame = [test_window() frame];
     NSPoint point = NSMakePoint(NSMidX(frame), NSMidY(frame));
-    controller_.reset(
-        [[ProfileChooserController alloc] initWithBrowser:browser()
-                                               anchoredAt:point]);
+    controller_.reset([[ProfileChooserController alloc]
+        initWithBrowser:browser()
+             anchoredAt:point
+               withMode:PROFILE_CHOOSER_VIEW]);
     [controller_ showWindow:nil];
   }
 
@@ -85,21 +88,53 @@
   StartProfileChooserController();
   NSArray* subviews = [[[controller() window] contentView] subviews];
 
+  // Three profiles means we should have one active card, one separator and
+  // one option buttons view.
+  EXPECT_EQ(3U, [subviews count]);
+
+  // For a local profile, there should be one button in the option buttons view.
+  NSArray* buttonSubviews = [[subviews objectAtIndex:0] subviews];
+  EXPECT_EQ(1U, [buttonSubviews count]);
+  NSButton* button = static_cast<NSButton*>([buttonSubviews objectAtIndex:0]);
+  EXPECT_EQ(@selector(showUserManager:), [button action]);
+  EXPECT_EQ(controller(), [button target]);
+
+  // There should be a separator.
+  EXPECT_TRUE([[subviews objectAtIndex:1] isKindOfClass:[NSBox class]]);
+
+  // There should be the profile avatar, name and links container in the active
+  // card view. The links displayed in the container are checked separately.
+  NSArray* activeCardSubviews = [[subviews objectAtIndex:2] subviews];
+  EXPECT_EQ(3U, [activeCardSubviews count]);
+
+  NSView* activeProfileImage = [activeCardSubviews objectAtIndex:0];
+  EXPECT_TRUE([activeProfileImage isKindOfClass:[NSImageView class]]);
+
+  // There are some links in between. The profile name is added last.
+  CGFloat index = [activeCardSubviews count] - 1;
+  NSView* activeProfileName = [activeCardSubviews objectAtIndex:index];
+  EXPECT_TRUE([activeProfileName isKindOfClass:[NSButton class]]);
+  EXPECT_EQ(menu()->GetItemAt(0).name, base::SysNSStringToUTF16(
+      [static_cast<NSButton*>(activeProfileName) title]));
+}
+
+TEST_F(ProfileChooserControllerTest, InitialLayoutWithFastUserSwitcher) {
+  // The fast user switcher is only availbale behind a flag.
+  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kFastUserSwitching);
+
+  StartProfileChooserController();
+  NSArray* subviews = [[[controller() window] contentView] subviews];
+
   // Three profiles means we should have one active card, two "other" profiles,
   // one separator and one option buttons view.
   EXPECT_EQ(5U, [subviews count]);
 
-  // There should be three buttons in the option buttons view.
+  // For a local profile, there should be one button in the option buttons view.
   NSArray* buttonSubviews = [[subviews objectAtIndex:0] subviews];
-  const SEL buttonSelectors[] = { @selector(showUserManager:),
-                                  @selector(addNewProfile:),
-                                  @selector(switchToGuestProfile:) };
-  EXPECT_EQ(3U, [buttonSubviews count]);
-  for (NSUInteger i = 0; i < [buttonSubviews count]; ++i) {
-    NSButton* button = static_cast<NSButton*>([buttonSubviews objectAtIndex:i]);
-    EXPECT_EQ(buttonSelectors[i], [button action]);
-    EXPECT_EQ(controller(), [button target]);
-  }
+  EXPECT_EQ(1U, [buttonSubviews count]);
+  NSButton* button = static_cast<NSButton*>([buttonSubviews objectAtIndex:0]);
+  EXPECT_EQ(@selector(showUserManager:), [button action]);
+  EXPECT_EQ(controller(), [button target]);
 
   // There should be a separator.
   EXPECT_TRUE([[subviews objectAtIndex:1] isKindOfClass:[NSBox class]]);
@@ -134,6 +169,9 @@
 }
 
 TEST_F(ProfileChooserControllerTest, OtherProfilesSortedAlphabetically) {
+  // The fast user switcher is only availbale behind a flag.
+  CommandLine::ForCurrentProcess()->AppendSwitch(switches::kFastUserSwitching);
+
   // Add two extra profiles, to make sure sorting is alphabetical and not
   // by order of creation.
   testing_profile_manager()->
@@ -166,7 +204,7 @@
 TEST_F(ProfileChooserControllerTest, LocalProfileActiveCardLinks) {
   StartProfileChooserController();
   NSArray* subviews = [[[controller() window] contentView] subviews];
-  NSArray* activeCardSubviews = [[subviews objectAtIndex:4] subviews];
+  NSArray* activeCardSubviews = [[subviews objectAtIndex:2] subviews];
   NSArray* activeCardLinks = [[activeCardSubviews objectAtIndex:1] subviews];
 
   // There should be one "sign in" link.
@@ -184,20 +222,15 @@
 
   StartProfileChooserController();
   NSArray* subviews = [[[controller() window] contentView] subviews];
-  NSArray* activeCardSubviews = [[subviews objectAtIndex:4] subviews];
+  NSArray* activeCardSubviews = [[subviews objectAtIndex:2] subviews];
   NSArray* activeCardLinks = [[activeCardSubviews objectAtIndex:1] subviews];
 
-  // There are two links: lock and manage accounts.
-  EXPECT_EQ(2U, [activeCardLinks count]);
+  // There is one link: manage accounts.
+  EXPECT_EQ(1U, [activeCardLinks count]);
   NSButton* manageAccountsLink =
       static_cast<NSButton*>([activeCardLinks objectAtIndex:0]);
   EXPECT_EQ(@selector(showAccountManagement:), [manageAccountsLink action]);
   EXPECT_EQ(controller(), [manageAccountsLink target]);
-
-  NSButton* lockLink =
-      static_cast<NSButton*>([activeCardLinks objectAtIndex:1]);
-  EXPECT_EQ(@selector(lockProfile:), [lockLink action]);
-  EXPECT_EQ(controller(), [lockLink target]);
 }
 
 TEST_F(ProfileChooserControllerTest, AccountManagementLayout) {
@@ -223,12 +256,11 @@
   // and one option buttons view.
   EXPECT_EQ(5U, [subviews count]);
 
-  // There should be three buttons in the option buttons view.
+  // There should be two buttons in the option buttons view.
   NSArray* buttonSubviews = [[subviews objectAtIndex:0] subviews];
   const SEL buttonSelectors[] = { @selector(showUserManager:),
-                                  @selector(addNewProfile:),
-                                  @selector(switchToGuestProfile:) };
-  EXPECT_EQ(3U, [buttonSubviews count]);
+                                  @selector(lockProfile:) };
+  EXPECT_EQ(2U, [buttonSubviews count]);
   for (NSUInteger i = 0; i < [buttonSubviews count]; ++i) {
     NSButton* button = static_cast<NSButton*>([buttonSubviews objectAtIndex:i]);
     EXPECT_EQ(buttonSelectors[i], [button action]);
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.h b/chrome/browser/ui/cocoa/browser_window_cocoa.h
index 2a6f784..f8bb00b 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.h
@@ -148,7 +148,7 @@
       GetWebContentsModalDialogHost() OVERRIDE;
   virtual void ShowAvatarBubble(content::WebContents* web_contents,
                                 const gfx::Rect& rect) OVERRIDE;
-  virtual void ShowAvatarBubbleFromAvatarButton() OVERRIDE;
+  virtual void ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode) OVERRIDE;
   virtual void ShowPasswordGenerationBubble(
       const gfx::Rect& rect,
       const autofill::PasswordForm& form,
diff --git a/chrome/browser/ui/cocoa/browser_window_cocoa.mm b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
index c1e1854..63731fe 100644
--- a/chrome/browser/ui/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/ui/cocoa/browser_window_cocoa.mm
@@ -646,8 +646,8 @@
 
 WindowOpenDisposition BrowserWindowCocoa::GetDispositionForPopupBounds(
     const gfx::Rect& bounds) {
-  // In Lion fullscreen mode, convert popups into tabs.
-  if (chrome::mac::SupportsSystemFullscreen() && IsFullscreen())
+  // When using Cocoa's System Fullscreen mode, convert popups into tabs.
+  if ([controller_ isInSystemFullscreen])
     return NEW_FOREGROUND_TAB;
   return NEW_POPUP;
 }
@@ -705,9 +705,10 @@
   [menu showWindow:nil];
 }
 
-void BrowserWindowCocoa::ShowAvatarBubbleFromAvatarButton() {
+void BrowserWindowCocoa::ShowAvatarBubbleFromAvatarButton(
+    AvatarBubbleMode mode) {
   AvatarBaseController* controller = [controller_ avatarButtonController];
-  [controller showAvatarBubble:[controller buttonView]];
+  [controller showAvatarBubble:[controller buttonView] withMode:mode];
 }
 
 void BrowserWindowCocoa::ShowPasswordGenerationBubble(
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.h b/chrome/browser/ui/cocoa/browser_window_controller.h
index aed9187..d16649f 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller.h
@@ -108,11 +108,6 @@
   // NO on growth.
   BOOL isShrinkingFromZoomed_;
 
-  // The raw accumulated zoom value and the actual zoom increments made for an
-  // an in-progress pinch gesture.
-  CGFloat totalMagnifyGestureAmount_;
-  NSInteger currentZoomStepDelta_;
-
   // The view controller that manages the incognito badge or the multi-profile
   // avatar button. Depending on whether the --new-profile-management flag is
   // used, the multi-profile button can either be the avatar's icon badge or a
@@ -127,24 +122,21 @@
   // nil for those which don't).
   base::scoped_nsobject<NSView> floatingBarBackingView_;
 
-  // The borderless window used in fullscreen mode.  Lion reuses the original
-  // window in fullscreen mode, so this is always nil on Lion.
+  // The borderless window used in fullscreen mode when Cocoa's System
+  // Fullscreen API is not being used (or not available, before OS 10.7).
   base::scoped_nsobject<NSWindow> fullscreenWindow_;
 
   // The Cocoa implementation of the PermissionBubbleView.
   scoped_ptr<PermissionBubbleCocoa> permissionBubbleCocoa_;
 
-  // Tracks whether presentation mode was entered from fullscreen mode or
-  // directly from normal windowed mode.  Used to determine what to do when
-  // exiting presentation mode.
-  BOOL enteredPresentationModeFromFullscreen_;
-
-  // True between -windowWillEnterFullScreen and -windowDidEnterFullScreen.
-  // Only used on Lion and higher.
+  // True between |-windowWillEnterFullScreen:| and |-windowDidEnterFullScreen:|
+  // to indicate that the window is in the process of transitioning into
+  // fullscreen mode.
   BOOL enteringFullscreen_;
 
   // True between |-setPresentationMode:url:bubbleType:| and
-  // -windowDidEnterFullScreen. Only used on Lion and higher.
+  // |-windowDidEnterFullScreen:| to indicate that the window is in the process
+  // of transitioning into fullscreen presentation mode.
   BOOL enteringPresentationMode_;
 
   // The size of the original (non-fullscreen) window.  This is saved just
@@ -438,9 +430,18 @@
 - (void)updateFullscreenExitBubbleURL:(const GURL&)url
                            bubbleType:(FullscreenExitBubbleType)bubbleType;
 
-// Returns fullscreen state.  This method is safe to call on all OS versions.
+// Returns fullscreen state: YES when the window is in fullscreen or is
+// animating into fullscreen.
 - (BOOL)isFullscreen;
 
+// Returns YES if the browser window is currently in fullscreen via the built-in
+// immersive mechanism.
+- (BOOL)isInImmersiveFullscreen;
+
+// Returns YES if the browser window is currently in fullscreen via the Cocoa
+// System Fullscreen API.
+- (BOOL)isInSystemFullscreen;
+
 // Enters (or exits) presentation mode.  Also enters fullscreen mode if this
 // window is not already fullscreen.  This method is safe to call on all OS
 // versions.
diff --git a/chrome/browser/ui/cocoa/browser_window_controller.mm b/chrome/browser/ui/cocoa/browser_window_controller.mm
index 761683f..b7de006 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller.mm
@@ -1147,6 +1147,17 @@
           [menuItem setHidden:shouldHide];
           break;
         }
+        case IDC_BOOKMARK_ALL_TABS: {
+          // Extensions have the ability to hide the bookmark all tabs menu
+          // item.  This only affects the bookmark page menu item under the main
+          // menu.  The bookmark page menu item under the wrench menu has its
+          // visibility controlled by WrenchMenuModel.
+          bool shouldHide =
+              chrome::ShouldRemoveBookmarkOpenPagesUI(browser_->profile());
+          NSMenuItem* menuItem = base::mac::ObjCCast<NSMenuItem>(item);
+          [menuItem setHidden:shouldHide];
+          break;
+        }
         default:
           // Special handling for the contents of the Text Encoding submenu. On
           // Mac OS, instead of enabling/disabling the top-level menu item, we
@@ -1857,41 +1868,6 @@
   }
 }
 
-// Called repeatedly during a pinch gesture, with incremental change values.
-- (void)magnifyWithEvent:(NSEvent*)event {
-  // The deltaZ difference necessary to trigger a zoom action. Derived from
-  // experimentation to find a value that feels reasonable.
-  const float kZoomStepValue = 0.6;
-
-  // Find the (absolute) thresholds on either side of the current zoom factor,
-  // then convert those to actual numbers to trigger a zoom in or out.
-  // This logic deliberately makes the range around the starting zoom value for
-  // the gesture twice as large as the other ranges (i.e., the notches are at
-  // ..., -3*step, -2*step, -step, step, 2*step, 3*step, ... but not at 0)
-  // so that it's easier to get back to your starting point than it is to
-  // overshoot.
-  float nextStep = (abs(currentZoomStepDelta_) + 1) * kZoomStepValue;
-  float backStep = abs(currentZoomStepDelta_) * kZoomStepValue;
-  float zoomInThreshold = (currentZoomStepDelta_ >= 0) ? nextStep : -backStep;
-  float zoomOutThreshold = (currentZoomStepDelta_ <= 0) ? -nextStep : backStep;
-
-  unsigned int command = 0;
-  totalMagnifyGestureAmount_ += [event magnification];
-  if (totalMagnifyGestureAmount_ > zoomInThreshold) {
-    command = IDC_ZOOM_PLUS;
-  } else if (totalMagnifyGestureAmount_ < zoomOutThreshold) {
-    command = IDC_ZOOM_MINUS;
-  }
-
-  if (command && chrome::IsCommandEnabled(browser_.get(), command)) {
-    currentZoomStepDelta_ += (command == IDC_ZOOM_PLUS) ? 1 : -1;
-    chrome::ExecuteCommandWithDisposition(
-        browser_.get(),
-        command,
-        ui::WindowOpenDispositionFromNSEvent(event));
-  }
-}
-
 // Delegate method called when window is resized.
 - (void)windowDidResize:(NSNotification*)notification {
   [self saveWindowPositionIfNeeded];
@@ -2095,10 +2071,10 @@
   chrome::ExecuteCommand(browser_.get(), IDC_FULLSCREEN);
 }
 
-// On Lion, this method is called by either the Lion fullscreen button or the
-// "Enter Full Screen" menu item.  On Snow Leopard, this function is never
-// called by the UI directly, but it provides the implementation for
-// |-setPresentationMode:|.
+// Called to transition into or out of fullscreen mode. Only use System
+// Fullscreen mode if the system supports it and we aren't trying to go
+// fullscreen for the renderer-initiated use cases.
+// Discussion: http://crbug.com/179181 and http:/crbug.com/351252
 - (void)setFullscreen:(BOOL)fullscreen {
   if (fullscreen == [self isFullscreen])
     return;
@@ -2106,17 +2082,28 @@
   if (!chrome::IsCommandEnabled(browser_.get(), IDC_FULLSCREEN))
     return;
 
-  if (chrome::mac::SupportsSystemFullscreen() && !fullscreenWindow_) {
-    enteredPresentationModeFromFullscreen_ = YES;
-    if (FramedBrowserWindow* framedBrowserWindow =
-            base::mac::ObjCCast<FramedBrowserWindow>([self window])) {
-      [framedBrowserWindow toggleSystemFullScreen];
+  if (fullscreen) {
+    const BOOL shouldUseSystemFullscreen =
+        chrome::mac::SupportsSystemFullscreen() && !fullscreenWindow_ &&
+        !browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending();
+    if (shouldUseSystemFullscreen) {
+      if (FramedBrowserWindow* framedBrowserWindow =
+          base::mac::ObjCCast<FramedBrowserWindow>([self window])) {
+        [framedBrowserWindow toggleSystemFullScreen];
+      }
+    } else {
+      [self enterImmersiveFullscreen];
     }
   } else {
-    if (fullscreen)
-      [self enterFullscreenForSnowLeopard];
-    else
-      [self exitFullscreenForSnowLeopard];
+    if ([self isInSystemFullscreen]) {
+      if (FramedBrowserWindow* framedBrowserWindow =
+          base::mac::ObjCCast<FramedBrowserWindow>([self window])) {
+        [framedBrowserWindow toggleSystemFullScreen];
+      }
+    } else {
+      DCHECK(fullscreenWindow_.get());
+      [self exitImmersiveFullscreen];
+    }
   }
 }
 
@@ -2137,11 +2124,20 @@
 }
 
 - (BOOL)isFullscreen {
-  return (fullscreenWindow_.get() != nil) ||
-         ([[self window] styleMask] & NSFullScreenWindowMask) ||
+  return [self isInImmersiveFullscreen] ||
+         [self isInSystemFullscreen] ||
          enteringFullscreen_;
 }
 
+- (BOOL)isInImmersiveFullscreen {
+  return fullscreenWindow_.get() != nil;
+}
+
+- (BOOL)isInSystemFullscreen {
+  return ([[self window] styleMask] & NSFullScreenWindowMask) ==
+      NSFullScreenWindowMask;
+}
+
 // On Lion, this function is called by either the presentation mode toggle
 // button or the "Enter Presentation Mode" menu item.  In the latter case, this
 // function also triggers the Lion machinery to enter fullscreen mode as well as
@@ -2163,7 +2159,6 @@
 
   if (presentationMode) {
     BOOL fullscreen = [self isFullscreen];
-    enteredPresentationModeFromFullscreen_ = fullscreen;
     enteringPresentationMode_ = YES;
 
     if (fullscreen) {
@@ -2183,13 +2178,9 @@
       [self showFullscreenExitBubbleIfNecessary];
       browser_->WindowFullscreenStateChanged();
     } else {
-      // If not in fullscreen mode, trigger the Lion fullscreen mode machinery.
-      // Presentation mode will automatically be enabled in
-      // |-windowWillEnterFullScreen:|.
-      if (FramedBrowserWindow* window =
-              base::mac::ObjCCast<FramedBrowserWindow>([self window])) {
-        [window toggleSystemFullScreen];
-      }
+      // Need to transition into fullscreen mode.  Presentation mode will
+      // automatically be enabled in |-windowWillEnterFullScreen:|.
+      [self setFullscreen:YES];
     }
   } else {
     // Exiting presentation mode does not exit system fullscreen; it merely
@@ -2221,7 +2212,7 @@
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
   DCHECK(command_line->HasSwitch(switches::kEnableSimplifiedFullscreen));
 
-  [self enterFullscreenForSnowLeopard];
+  [self enterImmersiveFullscreen];
   [self updateFullscreenExitBubbleURL:url bubbleType:bubbleType];
 }
 
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.h b/chrome/browser/ui/cocoa/browser_window_controller_private.h
index 558da46..f0a4a3d 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.h
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.h
@@ -96,19 +96,13 @@
 // keep the total height of the two views constant.
 - (void)adjustToolbarAndBookmarkBarForCompression:(CGFloat)compression;
 
-// Whether to show the presentation mode toggle button in the UI.  Returns YES
-// if in fullscreen mode on Lion or later.  This method is safe to call on all
-// OS versions.
-- (BOOL)shouldShowPresentationModeToggle;
-
-// Moves views between windows in preparation for fullscreen mode on Snow
-// Leopard.  (Lion and later reuses the original window for
-// fullscreen mode, so there is no need to move views around.)  This method does
-// not position views; callers must also call |-layoutSubviews|.  This method
-// must not be called on Lion or later.
-- (void)moveViewsForFullscreenForSnowLeopard:(BOOL)fullscreen
-                               regularWindow:(NSWindow*)regularWindow
-                            fullscreenWindow:(NSWindow*)fullscreenWindow;
+// Moves views between windows in preparation for fullscreen mode when not using
+// Cocoa's System Fullscreen API.  (System Fullscreen reuses the original window
+// for fullscreen mode, so there is no need to move views around.)  This method
+// does not position views; callers must also call |-layoutSubviews:|.
+- (void)moveViewsForImmersiveFullscreen:(BOOL)fullscreen
+                          regularWindow:(NSWindow*)regularWindow
+                       fullscreenWindow:(NSWindow*)fullscreenWindow;
 
 // Sets presentation mode, creating the PresentationModeController if needed and
 // forcing a relayout.  If |forceDropdown| is YES, this method will always
@@ -118,15 +112,14 @@
 - (void)setPresentationModeInternal:(BOOL)presentationMode
                       forceDropdown:(BOOL)forceDropdown;
 
-// Called on Snow Leopard or earlier to enter or exit fullscreen.  These methods
-// are internal implementations of |-setFullscreen:|.  These methods must not be
-// called on Lion or later.
-- (void)enterFullscreenForSnowLeopard;
-- (void)exitFullscreenForSnowLeopard;
+// Enter or exit fullscreen without using Cocoa's System Fullscreen API.  These
+// methods are internal implementations of |-setFullscreen:|.
+- (void)enterImmersiveFullscreen;
+- (void)exitImmersiveFullscreen;
 
 // Register or deregister for content view resize notifications.  These
-// notifications are used while transitioning to fullscreen mode in Lion or
-// later.  This method is safe to call on all OS versions.
+// notifications are used while transitioning into fullscreen mode using Cocoa's
+// System Fullscreen API.
 - (void)registerForContentViewResizeNotifications;
 - (void)deregisterForContentViewResizeNotifications;
 
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_private.mm b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
index bf9167b..a6ff42d 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_private.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_private.mm
@@ -526,16 +526,9 @@
 
 // Fullscreen and presentation mode methods
 
-- (BOOL)shouldShowPresentationModeToggle {
-  return chrome::mac::SupportsSystemFullscreen() && [self isFullscreen];
-}
-
-- (void)moveViewsForFullscreenForSnowLeopard:(BOOL)fullscreen
-    regularWindow:(NSWindow*)regularWindow
-    fullscreenWindow:(NSWindow*)fullscreenWindow {
-  // This method is only for systems without fullscreen support.
-  DCHECK(!chrome::mac::SupportsSystemFullscreen());
-
+- (void)moveViewsForImmersiveFullscreen:(BOOL)fullscreen
+                          regularWindow:(NSWindow*)regularWindow
+                       fullscreenWindow:(NSWindow*)fullscreenWindow {
   NSWindow* sourceWindow = fullscreen ? regularWindow : fullscreenWindow;
   NSWindow* destWindow = fullscreen ? fullscreenWindow : regularWindow;
 
@@ -648,9 +641,10 @@
   [self layoutSubviews];
 }
 
-// TODO(rohitrao): This method is misnamed now, since there is a flag that
-// enables 10.6-style fullscreen on newer OSes.
-- (void)enterFullscreenForSnowLeopard {
+- (void)enterImmersiveFullscreen {
+  // |-isFullscreen:| will return YES from here onwards.
+  enteringFullscreen_ = YES;  // Set to NO by |-windowDidEnterFullScreen:|.
+
   // Fade to black.
   const CGDisplayReservationInterval kFadeDurationSeconds = 0.6;
   Boolean didFadeOut = NO;
@@ -662,15 +656,14 @@
         kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, /*synchronous=*/true);
   }
 
-  // Create the fullscreen window.  After this line, isFullscreen will return
-  // YES.
+  // Create the fullscreen window.
   fullscreenWindow_.reset([[self createFullscreenWindow] retain]);
   savedRegularWindow_ = [[self window] retain];
   savedRegularWindowFrame_ = [savedRegularWindow_ frame];
 
-  [self moveViewsForFullscreenForSnowLeopard:YES
-                               regularWindow:[self window]
-                            fullscreenWindow:fullscreenWindow_.get()];
+  [self moveViewsForImmersiveFullscreen:YES
+                          regularWindow:[self window]
+                       fullscreenWindow:fullscreenWindow_.get()];
 
   // When simplified fullscreen is enabled, do not enter presentation mode.
   const CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -693,11 +686,7 @@
   }
 }
 
-- (void)exitFullscreenForSnowLeopard {
-  // TODO(rohitrao): This method is misnamed now, since there is a flag that
-  // enables 10.6-style fullscreen on newer OSes.
-  DCHECK(!chrome::mac::SupportsSystemFullscreen());
-
+- (void)exitImmersiveFullscreen {
   // Fade to black.
   const CGDisplayReservationInterval kFadeDurationSeconds = 0.6;
   Boolean didFadeOut = NO;
@@ -718,9 +707,9 @@
 
   [self windowWillExitFullScreen:nil];
 
-  [self moveViewsForFullscreenForSnowLeopard:NO
-                                        regularWindow:savedRegularWindow_
-                                     fullscreenWindow:fullscreenWindow_.get()];
+  [self moveViewsForImmersiveFullscreen:NO
+                          regularWindow:savedRegularWindow_
+                       fullscreenWindow:fullscreenWindow_.get()];
 
   // When exiting fullscreen mode, we need to call layoutSubviews manually.
   [savedRegularWindow_ autorelease];
@@ -759,9 +748,10 @@
 
 - (void)showFullscreenExitBubbleIfNecessary {
   // This method is called in response to
-  // |-updateFullscreenExitBubbleURL:bubbleType:|. If on Lion the system is
-  // transitioning, do not show the bubble because it will cause visual jank
-  // <http://crbug.com/130649>. This will be called again as part of
+  // |-updateFullscreenExitBubbleURL:bubbleType:|. If we're in the middle of the
+  // transition into fullscreen (i.e., using the System Fullscreen API), do not
+  // show the bubble because it will cause visual jank
+  // (http://crbug.com/130649). This will be called again as part of
   // |-windowDidEnterFullScreen:|, so arrange to do that work then instead.
   if (enteringFullscreen_)
     return;
@@ -821,7 +811,8 @@
 }
 
 - (void)windowWillEnterFullScreen:(NSNotification*)notification {
-  [self registerForContentViewResizeNotifications];
+  if (notification)  // For System Fullscreen when non-nil.
+    [self registerForContentViewResizeNotifications];
 
   NSWindow* window = [self window];
   savedRegularWindowFrame_ = [window frame];
@@ -832,7 +823,7 @@
 }
 
 - (void)windowDidEnterFullScreen:(NSNotification*)notification {
-  if (chrome::mac::SupportsSystemFullscreen())
+  if (notification)  // For System Fullscreen when non-nil.
     [self deregisterForContentViewResizeNotifications];
   enteringFullscreen_ = NO;
   enteringPresentationMode_ = NO;
@@ -849,7 +840,7 @@
 }
 
 - (void)windowWillExitFullScreen:(NSNotification*)notification {
-  if (chrome::mac::SupportsSystemFullscreen())
+  if (notification)  // For System Fullscreen when non-nil.
     [self registerForContentViewResizeNotifications];
   fullscreenModeController_.reset();
   [self destroyFullscreenExitBubbleIfNecessary];
@@ -857,7 +848,7 @@
 }
 
 - (void)windowDidExitFullScreen:(NSNotification*)notification {
-  if (chrome::mac::SupportsSystemFullscreen())
+  if (notification)  // For System Fullscreen when non-nil.
     [self deregisterForContentViewResizeNotifications];
   browser_->WindowFullscreenStateChanged();
 }
diff --git a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
index b50c651..3a23530 100644
--- a/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
+++ b/chrome/browser/ui/cocoa/browser_window_controller_unittest.mm
@@ -11,7 +11,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/signin/fake_auth_status_provider.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -28,8 +27,9 @@
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
 #include "grit/chromium_strings.h"
diff --git a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
index 6879d92..7cd63fe 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_action_button.mm
@@ -149,14 +149,16 @@
     [self setButtonType:NSMomentaryChangeButton];
     [self setShowsBorderOnlyWhileMouseInside:YES];
 
-    contextMenuController_.reset([[ExtensionActionContextMenuController alloc]
-        initWithExtension:extension
-                  browser:browser
-          extensionAction:browser_action]);
-    base::scoped_nsobject<NSMenu> contextMenu(
-        [[NSMenu alloc] initWithTitle:@""]);
-    [contextMenu setDelegate:self];
-    [self setMenu:contextMenu];
+    if (extension->ShowConfigureContextMenus()) {
+      contextMenuController_.reset([[ExtensionActionContextMenuController alloc]
+          initWithExtension:extension
+                    browser:browser
+            extensionAction:browser_action]);
+      base::scoped_nsobject<NSMenu> contextMenu(
+          [[NSMenu alloc] initWithTitle:@""]);
+      [contextMenu setDelegate:self];
+      [self setMenu:contextMenu];
+    }
 
     tabId_ = tabId;
     extension_ = extension;
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h
index 81002ed..edb3471 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.h
@@ -14,13 +14,13 @@
 @class BrowserActionButton;
 @class BrowserActionsContainerView;
 @class ExtensionPopupController;
-class ExtensionToolbarModel;
 class ExtensionServiceObserverBridge;
 @class MenuButton;
 class Profile;
 
 namespace extensions {
 class Extension;
+class ExtensionToolbarModel;
 }
 
 // Sent when the visibility of the Browser Actions changes.
@@ -40,7 +40,7 @@
   Profile* profile_;
 
   // The model that tracks the order of the toolbar icons. Weak.
-  ExtensionToolbarModel* toolbarModel_;
+  extensions::ExtensionToolbarModel* toolbarModel_;
 
   // The observer for the ExtensionService we're getting events from.
   scoped_ptr<ExtensionServiceObserverBridge> observer_;
diff --git a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
index 7e53734..cc758af 100644
--- a/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
+++ b/chrome/browser/ui/cocoa/extensions/browser_actions_controller.mm
@@ -178,8 +178,9 @@
 
 // A helper class to proxy extension notifications to the view controller's
 // appropriate methods.
-class ExtensionServiceObserverBridge : public content::NotificationObserver,
-                                       public ExtensionToolbarModel::Observer {
+class ExtensionServiceObserverBridge
+    : public content::NotificationObserver,
+      public extensions::ExtensionToolbarModel::Observer {
  public:
   ExtensionServiceObserverBridge(BrowserActionsController* owner,
                                  Browser* browser)
@@ -220,7 +221,7 @@
     }
   }
 
-  // ExtensionToolbarModel::Observer implementation.
+  // extensions::ExtensionToolbarModel::Observer implementation.
   virtual void BrowserActionAdded(
       const Extension* extension,
       int index) OVERRIDE {
@@ -273,7 +274,7 @@
     profile_ = browser->profile();
 
     observer_.reset(new ExtensionServiceObserverBridge(self, browser_));
-    toolbarModel_ = ExtensionToolbarModel::Get(profile_);
+    toolbarModel_ = extensions::ExtensionToolbarModel::Get(profile_);
     if (toolbarModel_)
       toolbarModel_->AddObserver(observer_.get());
 
@@ -763,9 +764,9 @@
   GURL popupUrl;
   switch (toolbarModel_->ExecuteBrowserAction(extension, browser_, &popupUrl,
                                               shouldGrant)) {
-    case ExtensionToolbarModel::ACTION_NONE:
+    case extensions::ExtensionToolbarModel::ACTION_NONE:
       break;
-    case ExtensionToolbarModel::ACTION_SHOW_POPUP: {
+    case extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP: {
       NSPoint arrowPoint = [self popupPointForBrowserAction:extension];
       [ExtensionPopupController showURL:popupUrl
                               inBrowser:browser_
diff --git a/chrome/browser/ui/cocoa/fast_resize_view.mm b/chrome/browser/ui/cocoa/fast_resize_view.mm
index 93438f4..f4ea8d3 100644
--- a/chrome/browser/ui/cocoa/fast_resize_view.mm
+++ b/chrome/browser/ui/cocoa/fast_resize_view.mm
@@ -23,8 +23,8 @@
 
 - (id)initWithFrame:(NSRect)frameRect {
   if ((self = [super initWithFrame:frameRect])) {
-    if (CommandLine::ForCurrentProcess()->HasSwitch(
-            switches::kEnableCoreAnimation)) {
+    if (!CommandLine::ForCurrentProcess()->HasSwitch(
+            switches::kDisableCoreAnimation)) {
       ScopedCAActionDisabler disabler;
       base::scoped_nsobject<CALayer> layer([[CALayer alloc] init]);
       [layer setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
index 3dc2a28..521ec5e 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.h
@@ -12,6 +12,7 @@
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 
 @class AutocompleteTextFieldCell;
+class LocationBarDecoration;
 
 // AutocompleteTextField intercepts UI actions for forwarding to
 // OmniboxViewMac (*), and provides a custom look.  It works
@@ -162,6 +163,9 @@
 - (NSString*)suggestText;
 - (NSColor*)suggestColor;
 
+// Obtain the bubble anchor point for |decoration|. In window coordinates.
+- (NSPoint)bubblePointForDecoration:(LocationBarDecoration*)decoration;
+
 @end
 
 namespace autocomplete_text_field {
diff --git a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
index adbfc96..bb920d5 100644
--- a/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
+++ b/chrome/browser/ui/cocoa/location_bar/autocomplete_text_field.mm
@@ -8,6 +8,7 @@
 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
 #import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
+#import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h"
 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
 #import "chrome/browser/ui/cocoa/url_drop_target.h"
 #import "chrome/browser/ui/cocoa/view_id_util.h"
@@ -252,6 +253,13 @@
   return suggestColor_;
 }
 
+- (NSPoint)bubblePointForDecoration:(LocationBarDecoration*)decoration {
+  const NSRect frame =
+      [[self cell] frameForDecoration:decoration inFrame:[self bounds]];
+  const NSPoint point = decoration->GetBubblePointInFrame(frame);
+  return [self convertPoint:point toView:nil];
+}
+
 // TODO(shess): -resetFieldEditorFrameIfNeeded is the place where
 // changes to the cell layout should be flushed.  LocationBarViewMac
 // and ToolbarController are calling this routine directly, and I
diff --git a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
index 5c0048d..340ed9a 100644
--- a/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/content_setting_decoration.h
@@ -38,16 +38,13 @@
   virtual NSString* GetToolTip() OVERRIDE;
   virtual CGFloat GetWidthForSpace(CGFloat width) OVERRIDE;
   virtual void DrawInFrame(NSRect frame, NSView* control_view) OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
   // Called from internal animator. Only public because ObjC objects can't
   // be friends.
   virtual void AnimationTimerFired();
 
  private:
-  // Helper to get where the bubble point should land.  Similar to
-  // |PageActionDecoration| or |StarDecoration| (|LocationBarViewMac|
-  // calls those).
-  NSPoint GetBubblePointInFrame(NSRect frame);
 
   void SetToolTip(NSString* tooltip);
 
diff --git a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
index 2e52c37..0e1ca95 100644
--- a/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/ev_bubble_decoration.h
@@ -29,9 +29,6 @@
   // fits, else it will set an elided version.
   void SetFullLabel(NSString* full_label);
 
-  // Get the point where the page info bubble should point within the
-  // decoration's frame, in the cell's coordinates.
-  NSPoint GetBubblePointInFrame(NSRect frame);
 
   // Implement |LocationBarDecoration|.
   virtual CGFloat GetWidthForSpace(CGFloat width) OVERRIDE;
@@ -41,6 +38,7 @@
   virtual NSRect GetDragImageFrame(NSRect frame) OVERRIDE;
   virtual bool OnMousePressed(NSRect frame) OVERRIDE;
   virtual bool AcceptsMousePress() OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
   // Implement |BubbleDecoration|.
   virtual ui::NinePartImageIds GetBubbleImageIds() OVERRIDE;
diff --git a/chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h b/chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h
index 808677b..7c43d4e 100644
--- a/chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/generated_credit_card_decoration.h
@@ -27,15 +27,12 @@
   // Called when this decoration should update its visible status.
   void Update();
 
-  // Get the point where the bookmark bubble should point within the
-  // decoration's frame.
-  NSPoint GetBubblePointInFrame(NSRect frame);
-
   // Implement |LocationBarDecoration|.
   // N.B. - this is identical to LocationBarDecorationView's OnClick
   // and canHandleClick.
   virtual bool AcceptsMousePress() OVERRIDE;
   virtual bool OnMousePressed(NSRect frame) OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
  private:
   // Helper to get the GeneratedCreditCardBubbleController associated with the
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h
index 1daf01f..f3c708e 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h
@@ -85,6 +85,11 @@
   // Gets the font used to draw text in the decoration.
   virtual NSFont* GetFont() const;
 
+  // Helper to get where the bubble point should land. |frame| specifies the
+  // decorations' image rectangle. Defaults to |frame.origin| if not overriden.
+  // The return value is in the same coordinate system as |frame|.
+  virtual NSPoint GetBubblePointInFrame(NSRect frame);
+
   static void DrawLabel(NSString* label,
                         NSDictionary* attributes,
                         const NSRect& frame);
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm
index e645cc7..0b6d940 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_decoration.mm
@@ -72,6 +72,14 @@
   return OmniboxViewMac::GetFieldFont(gfx::Font::NORMAL);
 }
 
+NSPoint LocationBarDecoration::GetBubblePointInFrame(NSRect frame) {
+  // Clients that use a bubble should implement this. Can't be abstract
+  // because too many LocationBarDecoration subclasses don't use a bubble.
+  // Can't live on subclasses only because it needs to be on a shared API.
+  NOTREACHED();
+  return frame.origin;
+}
+
 // static
 void LocationBarDecoration::DrawLabel(NSString* label,
                                       NSDictionary* attributes,
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
index f50b1bf..6130583 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h
@@ -150,6 +150,7 @@
   virtual void Update(const content::WebContents* contents) OVERRIDE;
   virtual void OnChanged() OVERRIDE;
   virtual void OnSetFocus() OVERRIDE;
+  virtual void ShowURL() OVERRIDE;
   virtual InstantController* GetInstant() OVERRIDE;
   virtual content::WebContents* GetWebContents() OVERRIDE;
   virtual ToolbarModel* GetToolbarModel() OVERRIDE;
@@ -174,6 +175,10 @@
   // Activates the page action for the extension that has the given id.
   void ActivatePageAction(const std::string& extension_id);
 
+ protected:
+  // OmniboxEditController:
+  virtual void HideURL() OVERRIDE;
+
  private:
   friend ZoomDecorationTest;
 
diff --git a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
index 13e2a17..ba5ad5f 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
+++ b/chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.mm
@@ -352,47 +352,24 @@
 
 NSPoint LocationBarViewMac::GetBookmarkBubblePoint() const {
   DCHECK(IsStarEnabled());
-
-  AutocompleteTextFieldCell* cell = [field_ cell];
-  const NSRect frame = [cell frameForDecoration:star_decoration_.get()
-                                        inFrame:[field_ bounds]];
-  const NSPoint point = star_decoration_->GetBubblePointInFrame(frame);
-  return [field_ convertPoint:point toView:nil];
+  return [field_ bubblePointForDecoration:star_decoration_.get()];
 }
 
 NSPoint LocationBarViewMac::GetTranslateBubblePoint() const {
-  AutocompleteTextFieldCell* cell = [field_ cell];
-  const NSRect frame = [cell frameForDecoration:translate_decoration_.get()
-                                        inFrame:[field_ bounds]];
-  const NSPoint point = translate_decoration_->GetBubblePointInFrame(frame);
-  return [field_ convertPoint:point toView:nil];
+  return [field_ bubblePointForDecoration:translate_decoration_.get()];
 }
 
 NSPoint LocationBarViewMac::GetPageInfoBubblePoint() const {
-  AutocompleteTextFieldCell* cell = [field_ cell];
   if (ev_bubble_decoration_->IsVisible()) {
-    const NSRect frame = [cell frameForDecoration:ev_bubble_decoration_.get()
-                                          inFrame:[field_ bounds]];
-    const NSPoint point = ev_bubble_decoration_->GetBubblePointInFrame(frame);
-    return [field_ convertPoint:point toView:nil];
+    return [field_ bubblePointForDecoration:ev_bubble_decoration_.get()];
   } else {
-    const NSRect frame =
-        [cell frameForDecoration:location_icon_decoration_.get()
-                         inFrame:[field_ bounds]];
-    const NSPoint point =
-        location_icon_decoration_->GetBubblePointInFrame(frame);
-    return [field_ convertPoint:point toView:nil];
+    return [field_ bubblePointForDecoration:location_icon_decoration_.get()];
   }
 }
 
 NSPoint LocationBarViewMac::GetGeneratedCreditCardBubblePoint() const {
-  AutocompleteTextFieldCell* cell = [field_ cell];
-  const NSRect frame =
-      [cell frameForDecoration:generated_credit_card_decoration_.get()
-                       inFrame:[field_ bounds]];
-  const NSPoint point =
-      generated_credit_card_decoration_->GetBubblePointInFrame(frame);
-  return [field_ convertPoint:point toView:nil];
+  return
+      [field_ bubblePointForDecoration:generated_credit_card_decoration_.get()];
 }
 
 void LocationBarViewMac::OnDecorationsChanged() {
@@ -593,6 +570,14 @@
   OnChanged();
 }
 
+void LocationBarViewMac::ShowURL() {
+  omnibox_view_->ShowURL();
+}
+
+void LocationBarViewMac::HideURL() {
+  omnibox_view_->HideURL();
+}
+
 InstantController* LocationBarViewMac::GetInstant() {
   return browser_->instant_controller() ?
       browser_->instant_controller()->instant() : NULL;
diff --git a/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h b/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h
index 582d251..8915ecf 100644
--- a/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/location_icon_decoration.h
@@ -25,14 +25,11 @@
   virtual NSImage* GetDragImage() OVERRIDE;
   virtual NSRect GetDragImageFrame(NSRect frame) OVERRIDE;
 
-  // Get the point where the page info bubble should point within the
-  // decoration's frame, in the |owner_|'s coordinates.
-  NSPoint GetBubblePointInFrame(NSRect frame);
-
   // Show the page info panel on click.
   virtual bool OnMousePressed(NSRect frame) OVERRIDE;
   virtual bool AcceptsMousePress() OVERRIDE;
   virtual NSString* GetToolTip() OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
  private:
   NSRect drag_frame_;
diff --git a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h
index 3096a01..f68c0b0 100644
--- a/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/page_action_decoration.h
@@ -49,16 +49,13 @@
   void SetToolTip(NSString* tooltip);
   void SetToolTip(std::string tooltip);
 
-  // Get the point where extension info bubbles should point within
-  // the given decoration frame.
-  NSPoint GetBubblePointInFrame(NSRect frame);
-
   // Overridden from |LocationBarDecoration|
   virtual CGFloat GetWidthForSpace(CGFloat width) OVERRIDE;
   virtual bool AcceptsMousePress() OVERRIDE;
   virtual bool OnMousePressed(NSRect frame) OVERRIDE;
   virtual NSString* GetToolTip() OVERRIDE;
   virtual NSMenu* GetMenu() OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
   // Activate the page action in its default frame.
   void ActivatePageAction();
diff --git a/chrome/browser/ui/cocoa/location_bar/star_decoration.h b/chrome/browser/ui/cocoa/location_bar/star_decoration.h
index 691f52e..461cb33 100644
--- a/chrome/browser/ui/cocoa/location_bar/star_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/star_decoration.h
@@ -24,14 +24,11 @@
   // Returns true if the star is lit.
   bool starred() const { return starred_; }
 
-  // Get the point where the bookmark bubble should point within the
-  // decoration's frame.
-  NSPoint GetBubblePointInFrame(NSRect frame);
-
   // Implement |LocationBarDecoration|.
   virtual bool AcceptsMousePress() OVERRIDE;
   virtual bool OnMousePressed(NSRect frame) OVERRIDE;
   virtual NSString* GetToolTip() OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
  private:
   // For bringing up bookmark bar.
diff --git a/chrome/browser/ui/cocoa/location_bar/translate_decoration.h b/chrome/browser/ui/cocoa/location_bar/translate_decoration.h
index 77ce6cd..2a30157 100644
--- a/chrome/browser/ui/cocoa/location_bar/translate_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/translate_decoration.h
@@ -23,16 +23,13 @@
   // Toggles the icon on or off.
   void SetLit(bool on);
 
-  // Get the point where the translate bubble should point within the
-  // decoration's frame.
-  NSPoint GetBubblePointInFrame(NSRect frame);
-
- private:
   // Implement |LocationBarDecoration|
   virtual bool AcceptsMousePress() OVERRIDE;
   virtual bool OnMousePressed(NSRect frame) OVERRIDE;
   virtual NSString* GetToolTip() OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
+ private:
   // For showing the translate bubble up.
   CommandUpdater* command_updater_;  // Weak, owned by Browser.
 
diff --git a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h
index b1cbe19..07d02a0 100644
--- a/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h
+++ b/chrome/browser/ui/cocoa/location_bar/zoom_decoration.h
@@ -38,7 +38,6 @@
  private:
   friend ZoomDecorationTest;
 
-  NSPoint GetBubblePointInFrame(NSRect frame);
   bool IsAtDefaultZoom() const;
   bool ShouldShowDecoration() const;
 
@@ -46,6 +45,7 @@
   virtual bool AcceptsMousePress() OVERRIDE;
   virtual bool OnMousePressed(NSRect frame) OVERRIDE;
   virtual NSString* GetToolTip() OVERRIDE;
+  virtual NSPoint GetBubblePointInFrame(NSRect frame) OVERRIDE;
 
   // ZoomBubbleControllerDelegate implementation.
   virtual content::WebContents* GetWebContents() OVERRIDE;
diff --git a/chrome/browser/ui/cocoa/nsview_additions.mm b/chrome/browser/ui/cocoa/nsview_additions.mm
index df85353..6d8ed4b 100644
--- a/chrome/browser/ui/cocoa/nsview_additions.mm
+++ b/chrome/browser/ui/cocoa/nsview_additions.mm
@@ -91,8 +91,8 @@
 }
 
 - (void)cr_setWantsLayer:(BOOL)wantsLayer {
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableCoreAnimation))
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableCoreAnimation))
     return;
 
   // Dynamically removing layers on SnowLeopard will sometimes result in
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
index 48a0a82..7f306ca 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.h
@@ -10,20 +10,50 @@
 #include "base/mac/scoped_nsobject.h"
 #include "chrome/browser/autocomplete/autocomplete_match.h"
 
+class OmniboxPopupViewMac;
+
 // OmniboxPopupCell overrides how backgrounds are displayed to
 // handle hover versus selected.  So long as we're in there, it also
 // provides some default initialization.
 @interface OmniboxPopupCell : NSButtonCell {
  @private
+  // The popup view parent of this cell.
+  OmniboxPopupViewMac* parent_;
+
   // The match which will be rendered for this row in omnibox dropdown.
   AutocompleteMatch match_;
 
+  // NSAttributedString instances for various match components.
   base::scoped_nsobject<NSAttributedString> separator_;
   base::scoped_nsobject<NSAttributedString> description_;
+
+  // NOTE: While |prefix_| is used only for postfix suggestions, it still needs
+  // to be a member of the class. This allows the |NSAttributedString| instance
+  // to stay alive between the call to |drawTitle| and the actual paint event
+  // which accesses the |NSAttributedString| instance.
+  base::scoped_nsobject<NSAttributedString> prefix_;
+
+  // The width of widest match contents in a set of infinite suggestions.
+  CGFloat maxMatchContentsWidth_;
+
+  // The offset at which the infinite suggesiton contents should be displayed.
+  CGFloat contentsOffset_;
 }
 
 - (void)setMatch:(const AutocompleteMatch&)match;
 
+- (void)setMaxMatchContentsWidth:(CGFloat)maxMatchContentsWidth;
+
+- (void)setContentsOffset:(CGFloat)contentsOffset;
+
+// Returns the width of the match contents.
+- (CGFloat)getMatchContentsWidth;
+
+// Returns the offset of the start of the contents in the input text for the
+// given match. It is costly to compute this offset, so it is computed once and
+// shared by all OmniboxPopupCell instances through OmniboxPopupViewMac parent.
++ (CGFloat)computeContentsOffset:(const AutocompleteMatch&)match;
+
 @end
 
 #endif  // CHROME_BROWSER_UI_COCOA_OMNIBOX_OMNIBOX_POPUP_CELL_H_
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
index 2fd6079..1c83402 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_cell.mm
@@ -9,8 +9,12 @@
 
 #include "base/i18n/rtl.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/cocoa/omnibox/omnibox_view_mac.h"
+#include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
 #include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -22,13 +26,15 @@
 const CGFloat kImageXOffset = 5.0;
 
 // How far to offset the text column from the left.
-const CGFloat kTextXOffset = 28.0;
+const CGFloat kTextStartOffset = 28.0;
 
 // Rounding radius of selection and hover background on popup items.
 const CGFloat kCellRoundingRadius = 2.0;
 
 // Flips the given |rect| in context of the given |frame|.
 NSRect FlipIfRTL(NSRect rect, NSRect frame) {
+  DCHECK_LE(NSMinX(frame), NSMinX(rect));
+  DCHECK_GE(NSMaxX(frame), NSMaxX(rect));
   if (base::i18n::IsRTL()) {
     NSRect result = rect;
     result.origin.x = NSMinX(frame) + (NSMaxX(frame) - NSMaxX(rect));
@@ -39,6 +45,7 @@
 
 // Shifts the left edge of the given |rect| by |dX|
 NSRect ShiftRect(NSRect rect, CGFloat dX) {
+  DCHECK_LE(dX, NSWidth(rect));
   NSRect result = rect;
   result.origin.x += dX;
   result.size.width -= dX;
@@ -69,9 +76,14 @@
   return OmniboxViewMac::GetFieldFont(gfx::Font::BOLD);
 }
 
+CGFloat GetContentAreaWidth(NSRect cellFrame) {
+  return NSWidth(cellFrame) - kTextStartOffset;
+}
+
 NSMutableAttributedString* CreateAttributedString(
     const base::string16& text,
-    NSColor* text_color) {
+    NSColor* text_color,
+    NSTextAlignment textAlignment) {
   // Start out with a string using the default style info.
   NSString* s = base::SysUTF16ToNSString(text);
   NSDictionary* attributes = @{
@@ -87,6 +99,7 @@
       [[[NSMutableParagraphStyle alloc] init] autorelease];
   [style setLineBreakMode:NSLineBreakByTruncatingTail];
   [style setTighteningFactorForTruncation:0.0];
+  [style setAlignment:textAlignment];
   [as addAttribute:NSParagraphStyleAttributeName
              value:style
              range:NSMakeRange(0, [as length])];
@@ -94,6 +107,12 @@
   return as;
 }
 
+NSMutableAttributedString* CreateAttributedString(
+    const base::string16& text,
+    NSColor* text_color) {
+  return CreateAttributedString(text, text_color, NSNaturalTextAlignment);
+}
+
 NSAttributedString* CreateClassifiedAttributedString(
     const base::string16& text,
     NSColor* text_color,
@@ -169,6 +188,14 @@
   }
 }
 
+- (void)setMaxMatchContentsWidth:(CGFloat)maxMatchContentsWidth {
+  maxMatchContentsWidth_ = maxMatchContentsWidth;
+}
+
+- (void)setContentsOffset:(CGFloat)contentsOffset {
+  contentsOffset_ = contentsOffset;
+}
+
 // The default NSButtonCell drawing leaves the image flush left and
 // the title next to the image.  This spaces things out to line up
 // with the star button and autocomplete field.
@@ -207,7 +234,8 @@
 - (void)drawMatchWithFrame:(NSRect)cellFrame inView:(NSView*)controlView {
   NSAttributedString* contents = [self attributedTitle];
 
-  CGFloat contentsWidth = [contents size].width;
+  CGFloat remainingWidth = GetContentAreaWidth(cellFrame);
+  CGFloat contentsWidth = [self getMatchContentsWidth];
   CGFloat separatorWidth = [separator_ size].width;
   CGFloat descriptionWidth = description_.get() ? [description_ size].width : 0;
   int contentsMaxWidth, descriptionMaxWidth;
@@ -215,12 +243,19 @@
       ceilf(contentsWidth),
       ceilf(separatorWidth),
       ceilf(descriptionWidth),
-      ceilf(cellFrame.size.width - kTextXOffset),
+      ceilf(remainingWidth),
       !AutocompleteMatch::IsSearchType(match_.type),
       &contentsMaxWidth,
       &descriptionMaxWidth);
 
-  CGFloat offset = kTextXOffset;
+  CGFloat offset = kTextStartOffset;
+  if (match_.type == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE) {
+    // Infinite suggestions are rendered with a prefix (usually ellipsis), which
+    // appear vertically stacked.
+    offset += [self drawMatchPrefixWithFrame:cellFrame
+                                      inView:controlView
+                        withContentsMaxWidth:&contentsMaxWidth];
+  }
   offset += [self drawMatchPart:contents
                       withFrame:cellFrame
                        atOffset:offset
@@ -241,11 +276,63 @@
   }
 }
 
+- (CGFloat)drawMatchPrefixWithFrame:(NSRect)cellFrame
+                             inView:(NSView*)controlView
+               withContentsMaxWidth:(int*)contentsMaxWidth {
+  CGFloat offset = 0.0f;
+  CGFloat remainingWidth = GetContentAreaWidth(cellFrame);
+  bool isRTL = base::i18n::IsRTL();
+  bool isContentsRTL = (base::i18n::RIGHT_TO_LEFT ==
+      base::i18n::GetFirstStrongCharacterDirection(match_.contents));
+  // Prefix may not have any characters with strong directionality, and may take
+  // the UI directionality. But prefix needs to appear in continuation of the
+  // contents so we force the directionality.
+  NSTextAlignment textAlignment = isContentsRTL ?
+      NSRightTextAlignment : NSLeftTextAlignment;
+  prefix_.reset([CreateAttributedString(base::UTF8ToUTF16(
+      match_.GetAdditionalInfo(kACMatchPropertyContentsPrefix)),
+      ContentTextColor(), textAlignment) retain]);
+  CGFloat prefixWidth = [prefix_ size].width;
+
+  CGFloat prefixOffset = 0.0f;
+  if (isRTL != isContentsRTL) {
+    // The contents is rendered between the contents offset extending towards
+    // the start edge, while prefix is rendered in opposite direction. Ideally
+    // the prefix should be rendered at |contentsOffset_|. If that is not
+    // sufficient to render the widest suggestion, we increase it to
+    // |maxMatchContentsWidth_|.  If |remainingWidth| is not sufficient to
+    // accomodate that, we reduce the offset so that the prefix gets rendered.
+    prefixOffset = std::min(
+        remainingWidth - prefixWidth, std::max(contentsOffset_,
+                                               maxMatchContentsWidth_));
+    offset = std::max<CGFloat>(0.0, prefixOffset - *contentsMaxWidth);
+  } else { // The direction of contents is same as UI direction.
+    // Ideally the offset should be |contentsOffset_|. If the max total width
+    // (|prefixWidth| + |maxMatchContentsWidth_|) from offset will exceed the
+    // |remainingWidth|, then we shift the offset to the left , so that all
+    // postfix suggestions are visible.
+    // We have to render the prefix, so offset has to be at least |prefixWidth|.
+    offset = std::max(prefixWidth,
+        std::min(remainingWidth - maxMatchContentsWidth_, contentsOffset_));
+    prefixOffset = offset - prefixWidth;
+  }
+  *contentsMaxWidth = std::min((int)ceilf(remainingWidth - prefixWidth),
+                               *contentsMaxWidth);
+  [self drawMatchPart:prefix_
+            withFrame:cellFrame
+             atOffset:prefixOffset + kTextStartOffset
+         withMaxWidth:prefixWidth
+               inView:controlView];
+  return offset;
+}
+
 - (CGFloat)drawMatchPart:(NSAttributedString*)as
                withFrame:(NSRect)cellFrame
                 atOffset:(CGFloat)offset
             withMaxWidth:(int)maxWidth
                   inView:(NSView*)controlView {
+  if (offset > NSWidth(cellFrame))
+    return 0.0f;
   NSRect renderRect = ShiftRect(cellFrame, offset);
   renderRect.size.width =
       std::min(NSWidth(renderRect), static_cast<CGFloat>(maxWidth));
@@ -257,4 +344,76 @@
   return NSWidth(renderRect);
 }
 
+- (CGFloat)getMatchContentsWidth {
+  NSAttributedString* contents = [self attributedTitle];
+  return contents ? [contents size].width : 0;
+}
+
+
++ (CGFloat)computeContentsOffset:(const AutocompleteMatch&)match {
+  const base::string16& inputText = base::UTF8ToUTF16(
+      match.GetAdditionalInfo(kACMatchPropertyInputText));
+  int contentsStartIndex = 0;
+  base::StringToInt(
+      match.GetAdditionalInfo(kACMatchPropertyContentsStartIndex),
+      &contentsStartIndex);
+  // Ignore invalid state.
+  if (!StartsWith(match.fill_into_edit, inputText, true)
+      || !EndsWith(match.fill_into_edit, match.contents, true)
+      || ((size_t)contentsStartIndex >= inputText.length())) {
+    return 0;
+  }
+  bool isRTL = base::i18n::IsRTL();
+  bool isContentsRTL = (base::i18n::RIGHT_TO_LEFT ==
+      base::i18n::GetFirstStrongCharacterDirection(match.contents));
+
+  // Color does not matter.
+  NSAttributedString* as = CreateAttributedString(inputText, DimTextColor());
+  base::scoped_nsobject<NSTextStorage> textStorage([[NSTextStorage alloc]
+      initWithAttributedString:as]);
+  base::scoped_nsobject<NSLayoutManager> layoutManager(
+      [[NSLayoutManager alloc] init]);
+  base::scoped_nsobject<NSTextContainer> textContainer(
+      [[NSTextContainer alloc] init]);
+  [layoutManager addTextContainer:textContainer];
+  [textStorage addLayoutManager:layoutManager];
+
+  NSUInteger charIndex = static_cast<NSUInteger>(contentsStartIndex);
+  NSUInteger glyphIndex =
+      [layoutManager glyphIndexForCharacterAtIndex:charIndex];
+
+  // This offset is computed from the left edge of the glyph always from the
+  // left edge of the string, irrespective of the directionality of UI or text.
+  CGFloat glyphOffset = [layoutManager locationForGlyphAtIndex:glyphIndex].x;
+
+  CGFloat inputWidth = [as size].width;
+
+  // The offset obtained above may need to be corrected because the left-most
+  // glyph may not have 0 offset. So we find the offset of left-most glyph, and
+  // subtract it from the offset of the glyph we obtained above.
+  CGFloat minOffset = glyphOffset;
+
+  // If content is RTL, we are interested in the right-edge of the glyph.
+  // Unfortunately the bounding rect computation methods from NSLayoutManager or
+  // NSFont don't work correctly with bidirectional text. So we compute the
+  // glyph width by finding the closest glyph offset to the right of the glyph
+  // we are looking for.
+  CGFloat glyphWidth = inputWidth;
+
+  for (NSUInteger i = 0; i < [as length]; i++) {
+    if (i == charIndex) continue;
+    glyphIndex = [layoutManager glyphIndexForCharacterAtIndex:i];
+    CGFloat offset = [layoutManager locationForGlyphAtIndex:glyphIndex].x;
+    minOffset = std::min(minOffset, offset);
+    if (offset > glyphOffset)
+      glyphWidth = std::min(glyphWidth, offset - glyphOffset);
+  }
+  glyphOffset -= minOffset;
+  if (glyphWidth == 0)
+    glyphWidth = inputWidth - glyphOffset;
+  if (isContentsRTL)
+    glyphOffset += glyphWidth;
+  return isRTL ? (inputWidth - glyphOffset) : glyphOffset;
+}
+
 @end
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
index af30630..accddf9 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.mm
@@ -104,11 +104,26 @@
   // Load the results into the popup's matrix.
   DCHECK_GT(rows, 0U);
   [matrix_ renewRows:rows columns:1];
+  CGFloat max_match_contents_width = 0.0f;
+  CGFloat contents_offset = -1.0f;
   for (size_t ii = 0; ii < rows; ++ii) {
     OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0];
     const AutocompleteMatch& match = GetResult().match_at(ii + start_match);
     [cell setImage:ImageForMatch(match)];
     [cell setMatch:match];
+    if (match.type == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE) {
+      max_match_contents_width = std::max(max_match_contents_width,
+                                           [cell getMatchContentsWidth]);
+      if (contents_offset < 0.0f) {
+        contents_offset = [OmniboxPopupCell computeContentsOffset:match];
+      }
+      [cell setContentsOffset:contents_offset];
+    }
+  }
+
+  for (size_t ii = 0; ii < rows; ++ii) {
+    OmniboxPopupCell* cell = [matrix_ cellAtRow:ii column:0];
+    [cell setMaxMatchContentsWidth:max_match_contents_width];
   }
 
   // Set the cell size to fit a line of text in the cell's font.  All
diff --git a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
index 3a3b8d7..6b1416f 100644
--- a/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
+++ b/chrome/browser/ui/cocoa/omnibox/omnibox_view_mac_unittest.mm
@@ -89,10 +89,13 @@
   }
   virtual ~TestingOmniboxEditController() {}
 
+ protected:
   // Overridden from OmniboxEditController:
   virtual void Update(const content::WebContents* contents) OVERRIDE {}
   virtual void OnChanged() OVERRIDE {}
   virtual void OnSetFocus() OVERRIDE {}
+  virtual void ShowURL() OVERRIDE {}
+  virtual void HideURL() OVERRIDE {}
   virtual InstantController* GetInstant() OVERRIDE { return NULL; }
   virtual content::WebContents* GetWebContents() OVERRIDE { return NULL; }
   virtual ToolbarModel* GetToolbarModel() OVERRIDE { return toolbar_model_; }
diff --git a/chrome/browser/ui/cocoa/presentation_mode_controller.mm b/chrome/browser/ui/cocoa/presentation_mode_controller.mm
index e114467..649145b 100644
--- a/chrome/browser/ui/cocoa/presentation_mode_controller.mm
+++ b/chrome/browser/ui/cocoa/presentation_mode_controller.mm
@@ -335,17 +335,23 @@
   return [browserController_ floatingBarShownFraction];
 }
 
+- (void)setSystemFullscreenModeTo:(base::mac::FullScreenMode)mode {
+  if (mode == systemFullscreenMode_)
+    return;
+  if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal)
+    base::mac::RequestFullScreen(mode);
+  else if (mode == base::mac::kFullScreenModeNormal)
+    base::mac::ReleaseFullScreen(systemFullscreenMode_);
+  else
+    base::mac::SwitchFullScreenModes(systemFullscreenMode_, mode);
+  systemFullscreenMode_ = mode;
+}
+
 - (void)changeFloatingBarShownFraction:(CGFloat)fraction {
   [browserController_ setFloatingBarShownFraction:fraction];
 
-  base::mac::FullScreenMode desiredMode = [self desiredSystemFullscreenMode];
-  if (desiredMode != systemFullscreenMode_ && [self shouldToggleMenuBar]) {
-    if (systemFullscreenMode_ == base::mac::kFullScreenModeNormal)
-      base::mac::RequestFullScreen(desiredMode);
-    else
-      base::mac::SwitchFullScreenModes(systemFullscreenMode_, desiredMode);
-    systemFullscreenMode_ = desiredMode;
-  }
+  if ([self shouldToggleMenuBar])
+    [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]];
 }
 
 // Used to activate the floating bar in presentation mode.
@@ -424,7 +430,7 @@
 }
 
 - (BOOL)shouldToggleMenuBar {
-  return !chrome::mac::SupportsSystemFullscreen() &&
+  return [browserController_ isInImmersiveFullscreen] &&
          [self isWindowOnPrimaryScreen] &&
          [[browserController_ window] isMainWindow];
 }
@@ -636,20 +642,15 @@
   if (systemFullscreenMode_ != base::mac::kFullScreenModeNormal)
     return;
 
-  if ([self shouldToggleMenuBar]) {
-    base::mac::FullScreenMode desiredMode = [self desiredSystemFullscreenMode];
-    base::mac::RequestFullScreen(desiredMode);
-    systemFullscreenMode_ = desiredMode;
-  }
+  if ([self shouldToggleMenuBar])
+    [self setSystemFullscreenModeTo:[self desiredSystemFullscreenMode]];
 
   // TODO(rohitrao): Insert the Exit Fullscreen button.  http://crbug.com/35956
 }
 
 - (void)hideActiveWindowUI {
-  if (systemFullscreenMode_ != base::mac::kFullScreenModeNormal) {
-    base::mac::ReleaseFullScreen(systemFullscreenMode_);
-    systemFullscreenMode_ = base::mac::kFullScreenModeNormal;
-  }
+  if ([self shouldToggleMenuBar])
+    [self setSystemFullscreenModeTo:base::mac::kFullScreenModeNormal];
 
   // TODO(rohitrao): Remove the Exit Fullscreen button.  http://crbug.com/35956
 }
diff --git a/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.h b/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.h
index 9193da3..e096cea 100644
--- a/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.h
+++ b/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.h
@@ -35,7 +35,8 @@
   virtual ~ScreenCaptureNotificationUICocoa();
 
   // ScreenCaptureNotificationUI interface.
-  virtual void OnStarted(const base::Closure& stop_callback) OVERRIDE;
+  virtual gfx::NativeViewId OnStarted(const base::Closure& stop_callback)
+      OVERRIDE;
 
  private:
   friend class ScreenCaptureNotificationUICocoaTest;
diff --git a/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.mm b/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.mm
index 8a80703..29d1151 100644
--- a/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.mm
+++ b/chrome/browser/ui/cocoa/screen_capture_notification_ui_cocoa.mm
@@ -29,9 +29,10 @@
 const CGFloat kMinimumWidth = 460;
 const CGFloat kMaximumWidth = 1000;
 const CGFloat kHorizontalMargin = 10;
-const CGFloat kPadding = 5;
-const CGFloat kPaddingLeft = 10;
+const CGFloat kPaddingVertical = 5;
+const CGFloat kPaddingHorizontal = 10;
 const CGFloat kWindowCornerRadius = 2;
+const CGFloat kWindowAlphaValue = 0.85;
 
 @interface ScreenCaptureNotificationController()
 - (void)hide;
@@ -53,7 +54,7 @@
 
 ScreenCaptureNotificationUICocoa::~ScreenCaptureNotificationUICocoa() {}
 
-void ScreenCaptureNotificationUICocoa::OnStarted(
+gfx::NativeViewId ScreenCaptureNotificationUICocoa::OnStarted(
     const base::Closure& stop_callback) {
   DCHECK(!stop_callback.is_null());
   DCHECK(!windowController_);
@@ -62,6 +63,7 @@
       initWithCallback:stop_callback
                   text:text_]);
   [windowController_ showWindow:nil];
+  return [[windowController_ window] windowNumber];
 }
 
 scoped_ptr<ScreenCaptureNotificationUI> ScreenCaptureNotificationUI::Create(
@@ -79,6 +81,7 @@
                                     backing:NSBackingStoreBuffered
                                       defer:NO]);
   [window setReleasedWhenClosed:NO];
+  [window setAlphaValue:kWindowAlphaValue];
   [window setBackgroundColor:[NSColor clearColor]];
   [window setOpaque:NO];
   [window setHasShadow:YES];
@@ -137,9 +140,14 @@
   [stopButton_ sizeToFit];
   [content addSubview:stopButton_];
 
-  minimizeButton_.reset(
-      [[HyperlinkButtonCell buttonWithString:l10n_util::GetNSString(
-          IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON)] retain]);
+  base::scoped_nsobject<HyperlinkButtonCell> cell(
+      [[HyperlinkButtonCell alloc]
+       initTextCell:l10n_util::GetNSString(
+                        IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON)]);
+  [cell setShouldUnderline:NO];
+
+  minimizeButton_.reset([[NSButton alloc] initWithFrame:NSZeroRect]);
+  [minimizeButton_ setCell:cell.get()];
   [minimizeButton_ sizeToFit];
   [minimizeButton_ setTarget:self];
   [minimizeButton_ setAction:@selector(minimize:)];
@@ -147,20 +155,21 @@
 
   CGFloat buttonsWidth = NSWidth([stopButton_ frame]) + kHorizontalMargin +
       NSWidth([minimizeButton_ frame]);
-  CGFloat totalHeight = kPadding + NSHeight([stopButton_ frame]) + kPadding;
+  CGFloat totalHeight =
+      kPaddingVertical + NSHeight([stopButton_ frame]) + kPaddingVertical;
 
   // Create grip icon.
   base::scoped_nsobject<WindowGripView> gripView([[WindowGripView alloc] init]);
   [content addSubview:gripView];
   CGFloat gripWidth = NSWidth([gripView frame]);
   CGFloat gripHeight = NSHeight([gripView frame]);
-  [gripView
-      setFrameOrigin:NSMakePoint(kPaddingLeft, (totalHeight - gripHeight) / 2)];
+  [gripView setFrameOrigin:NSMakePoint(kPaddingHorizontal,
+                                       (totalHeight - gripHeight) / 2)];
 
   // Create text label.
   int maximumWidth =
       std::min(kMaximumWidth, NSWidth([[NSScreen mainScreen] visibleFrame]));
-  int maxLabelWidth = maximumWidth - kPaddingLeft - kPadding -
+  int maxLabelWidth = maximumWidth - kPaddingHorizontal * 2 -
                       kHorizontalMargin * 2 - gripWidth - buttonsWidth;
   gfx::FontList font_list;
   base::string16 elidedText =
@@ -176,26 +185,26 @@
   [statusTextField setFont:font_list.GetPrimaryFont().GetNativeFont()];
   [statusTextField sizeToFit];
   [statusTextField setFrameOrigin:NSMakePoint(
-                       kPaddingLeft + kHorizontalMargin + gripWidth,
+                       kPaddingHorizontal + kHorizontalMargin + gripWidth,
                        (totalHeight - NSHeight([statusTextField frame])) / 2)];
   [content addSubview:statusTextField];
 
   // Resize content view to fit controls.
-  CGFloat minimumLableWidth = kMinimumWidth - kPaddingLeft - kPadding -
+  CGFloat minimumLableWidth = kMinimumWidth - kPaddingHorizontal * 2 -
                               kHorizontalMargin * 2 - gripWidth - buttonsWidth;
   CGFloat lableWidth =
       std::max(NSWidth([statusTextField frame]), minimumLableWidth);
-  CGFloat totalWidth = kPaddingLeft + kPadding + kHorizontalMargin * 2 +
+  CGFloat totalWidth = kPaddingHorizontal * 2 + kHorizontalMargin * 2 +
                        gripWidth + lableWidth + buttonsWidth;
   [content setFrame:NSMakeRect(0, 0, totalWidth, totalHeight)];
 
   // Move the buttons to the right place.
-  NSPoint buttonOrigin =
-      NSMakePoint(totalWidth - kPadding - buttonsWidth, kPadding);
+  NSPoint buttonOrigin = NSMakePoint(
+      totalWidth - kPaddingHorizontal - buttonsWidth, kPaddingVertical);
   [stopButton_ setFrameOrigin:buttonOrigin];
 
   [minimizeButton_ setFrameOrigin:NSMakePoint(
-      totalWidth - kPadding - NSWidth([minimizeButton_ frame]),
+      totalWidth - kPaddingHorizontal - NSWidth([minimizeButton_ frame]),
       (totalHeight - NSHeight([minimizeButton_ frame])) / 2)];
 
   if (base::i18n::IsRTL()) {
diff --git a/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm b/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm
index 193d8bf..4bab57e 100644
--- a/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm
+++ b/chrome/browser/ui/cocoa/tabs/tab_strip_drag_controller.mm
@@ -9,6 +9,7 @@
 #import "base/mac/sdk_forward_declarations.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_controller.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_controller_target.h"
+#import "chrome/browser/ui/cocoa/tabs/tab_strip_view.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_view.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
@@ -16,6 +17,15 @@
 const CGFloat kTearDistance = 36.0;
 const NSTimeInterval kTearDuration = 0.333;
 
+// Returns whether |screenPoint| is inside the bounds of |view|.
+static BOOL PointIsInsideView(NSPoint screenPoint, NSView* view) {
+  if ([view window] == nil)
+    return NO;
+  NSPoint windowPoint = [[view window] convertScreenToBase:screenPoint];
+  NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil];
+  return [view mouse:viewPoint inRect:[view bounds]];
+}
+
 @interface TabStripDragController (Private)
 - (void)resetDragControllers;
 - (NSArray*)dropTargetsForController:(TabWindowController*)dragController;
@@ -187,8 +197,6 @@
     }
   }
 
-  // Do not start dragging until the user has "torn" the tab off by
-  // moving more than 3 pixels.
   NSPoint thisPoint = [NSEvent mouseLocation];
 
   // Iterate over possible targets checking for the one the mouse is in.
@@ -202,10 +210,7 @@
     NSRect windowFrame = [[target window] frame];
     if (NSPointInRect(thisPoint, windowFrame)) {
       [[target window] orderFront:self];
-      NSRect tabStripFrame = [[target tabStripView] frame];
-      tabStripFrame.origin = [[target window]
-                              convertBaseToScreen:tabStripFrame.origin];
-      if (NSPointInRect(thisPoint, tabStripFrame)) {
+      if (PointIsInsideView(thisPoint, [target tabStripView])) {
         newTarget = target;
       }
       break;
@@ -225,9 +230,6 @@
 
   // Create or identify the dragged controller.
   if (!draggedController_) {
-    // Get rid of any placeholder remaining in the original source window.
-    [sourceController_ removePlaceholder];
-
     // Detach from the current window and put it in a new window. If there are
     // no more tabs remaining after detaching, the source window is about to
     // go away (it's been autoreleased) so we need to ensure we don't reference
@@ -241,7 +243,19 @@
 
     dragWindow_ = [draggedController_ window];
     [dragWindow_ setAlphaValue:0.0];
-    if (![sourceController_ hasLiveTabs]) {
+    if ([sourceController_ hasLiveTabs]) {
+      if (PointIsInsideView(thisPoint, [sourceController_ tabStripView])) {
+        // We don't want to remove the source window's placeholder here because
+        // the new tab button may briefly flash in and out if we remove and add
+        // back the placeholder.
+        // Instead, we will remove the placeholder later when the target window
+        // actually changes.
+        targetController_ = sourceController_;
+      } else {
+        [sourceController_ removePlaceholder];
+      }
+    } else {
+      [sourceController_ removePlaceholder];
       sourceController_ = draggedController_;
       sourceWindow_ = dragWindow_;
     }
diff --git a/chrome/browser/ui/cocoa/web_dialog_window_controller.mm b/chrome/browser/ui/cocoa/web_dialog_window_controller.mm
index 3e61033..db0be89 100644
--- a/chrome/browser/ui/cocoa/web_dialog_window_controller.mm
+++ b/chrome/browser/ui/cocoa/web_dialog_window_controller.mm
@@ -73,7 +73,8 @@
                               const gfx::Rect& initial_pos,
                               bool user_gesture,
                               bool* was_blocked) OVERRIDE;
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
 
 private:
   WebDialogWindowController* controller_;  // weak
@@ -240,7 +241,7 @@
 }
 
 void WebDialogWindowDelegateBridge::LoadingStateChanged(
-    content::WebContents* source) {
+    content::WebContents* source, bool to_different_document) {
   if (delegate_)
     delegate_->OnLoadingStateChanged(source);
 }
diff --git a/chrome/browser/ui/extensions/application_launch.cc b/chrome/browser/ui/extensions/application_launch.cc
index d391d8f..458805e 100644
--- a/chrome/browser/ui/extensions/application_launch.cc
+++ b/chrome/browser/ui/extensions/application_launch.cc
@@ -468,7 +468,8 @@
   ExtensionService* service =
       extensions::ExtensionSystem::Get(profile)->extension_service();
   if (!service->IsExtensionEnabled(extension->id()) ||
-      service->GetTerminatedExtension(extension->id())) {
+      extensions::ExtensionRegistry::Get(profile)->GetExtensionById(
+          extension->id(), extensions::ExtensionRegistry::TERMINATED)) {
     (new EnableViaAppListFlow(
         service, profile, params.desktop_type, extension->id(),
         base::Bind(base::IgnoreResult(OpenEnabledApplication), params)))->Run();
diff --git a/chrome/browser/ui/extensions/extension_enable_flow.cc b/chrome/browser/ui/extensions/extension_enable_flow.cc
index 4586331..b89155f 100644
--- a/chrome/browser/ui/extensions/extension_enable_flow.cc
+++ b/chrome/browser/ui/extensions/extension_enable_flow.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
 #include "content/public/browser/notification_details.h"
 #include "content/public/browser/notification_source.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 
 using extensions::Extension;
@@ -54,7 +55,8 @@
       extensions::ExtensionSystem::Get(profile_)->extension_service();
   const Extension* extension = service->GetExtensionById(extension_id_, true);
   if (!extension) {
-    extension = service->GetTerminatedExtension(extension_id_);
+    extension = extensions::ExtensionRegistry::Get(profile_)->GetExtensionById(
+        extension_id_, extensions::ExtensionRegistry::TERMINATED);
     // It's possible (though unlikely) the app could have been uninstalled since
     // the user clicked on it.
     if (!extension)
diff --git a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
index 158c801..bd425d2 100644
--- a/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
+++ b/chrome/browser/ui/gtk/autofill/autofill_popup_view_gtk.cc
@@ -118,7 +118,8 @@
   if (event->button != 1)
     return FALSE;
 
-  controller_->AcceptSelectionAtPoint(gfx::Point(event->x, event->y));
+  controller_->SetSelectionAtPoint(gfx::Point(event->x, event->y));
+  controller_->AcceptSelectedLine();
   return TRUE;
 }
 
diff --git a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
index 6f65c60..6612538 100644
--- a/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
+++ b/chrome/browser/ui/gtk/bookmarks/bookmark_bar_gtk.cc
@@ -16,7 +16,6 @@
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/bookmarks/bookmark_node_data.h"
 #include "chrome/browser/bookmarks/bookmark_stats.h"
-#include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -893,8 +892,7 @@
 void BookmarkBarGtk::BookmarkModelBeingDeleted(BookmarkModel* model) {
   // The bookmark model should never be deleted before us. This code exists
   // to check for regressions in shutdown code and not crash.
-  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
-    NOTREACHED();
+  NOTREACHED();
 
   // Do minimal cleanup, presumably we'll be deleted shortly.
   model_->RemoveObserver(this);
diff --git a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
index 660e590..9091988 100644
--- a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.cc
@@ -259,16 +259,16 @@
   // popup will grant tab permissions if |should_grant| is true. Popup's shown
   // via an API should not grant permissions.
   bool Activate(GtkWidget* widget, bool should_grant) {
-    ExtensionToolbarModel* model = toolbar_->model();
+    extensions::ExtensionToolbarModel* model = toolbar_->model();
     const Extension* extension = extension_;
     Browser* browser = toolbar_->browser();
     GURL popup_url;
 
     switch (model->ExecuteBrowserAction(
         extension, browser, &popup_url, should_grant)) {
-      case ExtensionToolbarModel::ACTION_NONE:
+      case extensions::ExtensionToolbarModel::ACTION_NONE:
         break;
-      case ExtensionToolbarModel::ACTION_SHOW_POPUP:
+      case extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP:
         ExtensionPopupGtk::Show(popup_url, browser, widget,
                                 ExtensionPopupGtk::SHOW);
         return true;
@@ -503,7 +503,7 @@
       desired_width_(0),
       start_width_(0),
       weak_factory_(this) {
-  model_ = ExtensionToolbarModel::Get(profile_);
+  model_ = extensions::ExtensionToolbarModel::Get(profile_);
   if (!model_)
     return;
 
@@ -834,9 +834,9 @@
 
   switch (model_->ExecuteBrowserAction(
       extension, browser(), &popup_url, true)) {
-    case ExtensionToolbarModel::ACTION_NONE:
+    case extensions::ExtensionToolbarModel::ACTION_NONE:
       break;
-    case ExtensionToolbarModel::ACTION_SHOW_POPUP:
+    case extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP:
       ExtensionPopupGtk::Show(popup_url, browser(), chevron(),
                               ExtensionPopupGtk::SHOW);
       break;
diff --git a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h
index 83acdfd..25d11ee 100644
--- a/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h
+++ b/chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h
@@ -36,11 +36,12 @@
 typedef struct _GdkDragContext GdkDragContext;
 typedef struct _GtkWidget GtkWidget;
 
-class BrowserActionsToolbarGtk : public ExtensionToolbarModel::Observer,
-                                 public gfx::AnimationDelegate,
-                                 public MenuGtk::Delegate,
-                                 public ui::SimpleMenuModel::Delegate,
-                                 public content::NotificationObserver {
+class BrowserActionsToolbarGtk
+    : public extensions::ExtensionToolbarModel::Observer,
+      public gfx::AnimationDelegate,
+      public MenuGtk::Delegate,
+      public ui::SimpleMenuModel::Delegate,
+      public content::NotificationObserver {
  public:
   explicit BrowserActionsToolbarGtk(Browser* browser);
   virtual ~BrowserActionsToolbarGtk();
@@ -59,7 +60,7 @@
 
   Browser* browser() { return browser_; }
 
-  ExtensionToolbarModel* model() { return model_; }
+  extensions::ExtensionToolbarModel* model() { return model_; }
 
   // Returns the currently selected tab ID, or -1 if there is none.
   int GetCurrentTabId() const;
@@ -113,7 +114,7 @@
   // for incognito.
   bool ShouldDisplayBrowserAction(const extensions::Extension* extension);
 
-  // ExtensionToolbarModel::Observer implementation.
+  // extensions::ExtensionToolbarModel::Observer implementation.
   virtual void BrowserActionAdded(const extensions::Extension* extension,
                                   int index) OVERRIDE;
   virtual void BrowserActionRemoved(
@@ -185,7 +186,7 @@
   Profile* profile_;
   GtkThemeService* theme_service_;
 
-  ExtensionToolbarModel* model_;
+  extensions::ExtensionToolbarModel* model_;
 
   // Contains the drag gripper, browser action buttons, and overflow chevron.
   ui::OwnedWidgetGtk hbox_;
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
index e1fc0ce..5828897 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -1219,7 +1219,7 @@
                           &rect);
 }
 
-void BrowserWindowGtk::ShowAvatarBubbleFromAvatarButton() {
+void BrowserWindowGtk::ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode) {
   if (titlebar_->avatar_button())
     titlebar_->avatar_button()->ShowAvatarBubble();
 }
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.h b/chrome/browser/ui/gtk/browser_window_gtk.h
index d95d47c..529c38a 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.h
+++ b/chrome/browser/ui/gtk/browser_window_gtk.h
@@ -180,7 +180,7 @@
       GetWebContentsModalDialogHost() OVERRIDE;
   virtual void ShowAvatarBubble(content::WebContents* web_contents,
                                 const gfx::Rect& rect) OVERRIDE;
-  virtual void ShowAvatarBubbleFromAvatarButton() OVERRIDE;
+  virtual void ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode) OVERRIDE;
   virtual void ShowPasswordGenerationBubble(
       const gfx::Rect& rect,
       const autofill::PasswordForm& form,
diff --git a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
index c95a5fa..a9d721d 100644
--- a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
+++ b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc
@@ -331,7 +331,7 @@
 
   // Get shortcut information and icon now; they are needed for our UI.
   web_app::UpdateShortcutInfoAndIconForApp(
-      *app, profile,
+      app, profile,
       base::Bind(
           &CreateChromeApplicationShortcutsDialogGtk::OnShortcutInfoLoaded,
           this));
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.cc b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
index dde1ff7..e8fa487 100644
--- a/chrome/browser/ui/gtk/location_bar_view_gtk.cc
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.cc
@@ -635,6 +635,10 @@
   OnChanged();
 }
 
+void LocationBarViewGtk::ShowURL() {
+  omnibox_view_->ShowURL();
+}
+
 InstantController* LocationBarViewGtk::GetInstant() {
   return browser_->instant_controller() ?
       browser_->instant_controller()->instant() : NULL;
@@ -1571,6 +1575,10 @@
   return !browser_->is_type_tabbed();
 }
 
+void LocationBarViewGtk::HideURL() {
+  omnibox_view_->HideURL();
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // LocationBarViewGtk::PageToolViewGtk
 
diff --git a/chrome/browser/ui/gtk/location_bar_view_gtk.h b/chrome/browser/ui/gtk/location_bar_view_gtk.h
index 6150409..0de4e02 100644
--- a/chrome/browser/ui/gtk/location_bar_view_gtk.h
+++ b/chrome/browser/ui/gtk/location_bar_view_gtk.h
@@ -112,6 +112,7 @@
   virtual void Update(const content::WebContents* contents) OVERRIDE;
   virtual void OnChanged() OVERRIDE;
   virtual void OnSetFocus() OVERRIDE;
+  virtual void ShowURL() OVERRIDE;
   virtual InstantController* GetInstant() OVERRIDE;
   virtual content::WebContents* GetWebContents() OVERRIDE;
   virtual ToolbarModel* GetToolbarModel() OVERRIDE;
@@ -211,6 +212,9 @@
   };
 
  private:
+  // OmniboxEditController:
+  virtual void HideURL() OVERRIDE;
+
   class PageActionViewGtk :
        public ExtensionActionIconFactory::Observer,
        public content::NotificationObserver,
diff --git a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
index 11a2a25..1b2bd5e 100644
--- a/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
+++ b/chrome/browser/ui/gtk/omnibox/omnibox_view_gtk_unittest.cc
@@ -26,10 +26,12 @@
   MOCK_METHOD1(Update, void(const content::WebContents* contents));
   MOCK_METHOD0(OnChanged, void());
   MOCK_METHOD0(OnSetFocus, void());
+  MOCK_METHOD0(ShowURL, void());
   MOCK_METHOD0(GetInstant, InstantController*());
   MOCK_METHOD0(GetWebContents, content::WebContents*());
   MOCK_METHOD0(GetToolbarModel, ToolbarModel*());
   MOCK_CONST_METHOD0(GetToolbarModel, ToolbarModel*());
+  MOCK_METHOD0(HideURL, void());
 };
 }  // namespace
 
diff --git a/chrome/browser/ui/gtk/screen_capture_notification_ui_gtk.cc b/chrome/browser/ui/gtk/screen_capture_notification_ui_gtk.cc
index e4842f5..bfdf8b4 100644
--- a/chrome/browser/ui/gtk/screen_capture_notification_ui_gtk.cc
+++ b/chrome/browser/ui/gtk/screen_capture_notification_ui_gtk.cc
@@ -21,7 +21,8 @@
   virtual ~ScreenCaptureNotificationUIGtk();
 
   // ScreenCaptureNotificationUI interface
-  virtual void OnStarted(const base::Closure& stop_callback) OVERRIDE;
+  virtual gfx::NativeViewId OnStarted(const base::Closure& stop_callback)
+      OVERRIDE;
 
  private:
   CHROMEGTK_CALLBACK_1(ScreenCaptureNotificationUIGtk, gboolean, OnDelete,
@@ -135,7 +136,7 @@
   gtk_window_present(GTK_WINDOW(window_));
 }
 
-void ScreenCaptureNotificationUIGtk::OnStarted(
+gfx::NativeViewId ScreenCaptureNotificationUIGtk::OnStarted(
     const base::Closure& stop_callback) {
   DCHECK(stop_callback_.is_null());
   DCHECK(!stop_callback.is_null());
@@ -143,6 +144,8 @@
 
   stop_callback_ = stop_callback;
   CreateWindow();
+
+  return 0;
 }
 
 void ScreenCaptureNotificationUIGtk::HideWindow() {
diff --git a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
index 4a5acff..5b345ac 100644
--- a/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
+++ b/chrome/browser/ui/libgtk2ui/gtk2_ui.cc
@@ -77,6 +77,9 @@
 // Number of app indicators used (used as part of app-indicator id).
 int indicators_count;
 
+// The unknown content type.
+const char* kUnknownContentType = "application/octet-stream";
+
 // The size of the rendered toolbar image.
 const int kToolbarImageWidth = 64;
 const int kToolbarImageHeight = 128;
@@ -498,23 +501,30 @@
   // This call doesn't take a reference.
   GtkIconTheme* theme = gtk_icon_theme_get_default();
 
-  ScopedGIcon icon(g_content_type_get_icon(content_type.c_str()));
-  ScopedGtkIconInfo icon_info(
-      gtk_icon_theme_lookup_by_gicon(
-          theme, icon.get(), size,
-          static_cast<GtkIconLookupFlags>(GTK_ICON_LOOKUP_FORCE_SIZE)));
-  if (!icon_info)
-    return gfx::Image();
-  ScopedGdkPixbuf pixbuf(gtk_icon_info_load_icon(icon_info.get(), NULL));
-  if (!pixbuf)
-    return gfx::Image();
+  std::string content_types[] = {
+    content_type, kUnknownContentType
+  };
 
-  SkBitmap bitmap = GdkPixbufToImageSkia(pixbuf.get());
-  DCHECK_EQ(size, bitmap.width());
-  DCHECK_EQ(size, bitmap.height());
-  gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
-  image_skia.MakeThreadSafe();
-  return gfx::Image(image_skia);
+  for (size_t i = 0; i < arraysize(content_types); ++i) {
+    ScopedGIcon icon(g_content_type_get_icon(content_types[i].c_str()));
+    ScopedGtkIconInfo icon_info(
+        gtk_icon_theme_lookup_by_gicon(
+            theme, icon.get(), size,
+            static_cast<GtkIconLookupFlags>(GTK_ICON_LOOKUP_FORCE_SIZE)));
+    if (!icon_info)
+      continue;
+    ScopedGdkPixbuf pixbuf(gtk_icon_info_load_icon(icon_info.get(), NULL));
+    if (!pixbuf)
+      continue;
+
+    SkBitmap bitmap = GdkPixbufToImageSkia(pixbuf.get());
+    DCHECK_EQ(size, bitmap.width());
+    DCHECK_EQ(size, bitmap.height());
+    gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+    image_skia.MakeThreadSafe();
+    return gfx::Image(image_skia);
+  }
+  return gfx::Image();
 }
 
 scoped_ptr<views::Border> Gtk2UI::CreateNativeBorder(
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_controller.cc b/chrome/browser/ui/omnibox/omnibox_edit_controller.cc
index 43987fc..05d01bb 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_controller.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_controller.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/command_updater.h"
+#include "chrome/browser/ui/toolbar/toolbar_model.h"
 
 void OmniboxEditController::OnAutocompleteAccept(
     const GURL& destination_url,
@@ -26,5 +27,21 @@
           content::PAGE_TRANSITION_FROM_ADDRESS_BAR)) {
 }
 
+void OmniboxEditController::HideOriginChip() {
+  GetToolbarModel()->set_origin_chip_enabled(false);
+  OnChanged();
+}
+
+void OmniboxEditController::ShowOriginChip() {
+  // If URL replacement is still enabled, we can simply show the chip.  If it
+  // was disabled by an action to show the URL then the URL needs to be hidden.
+  if (GetToolbarModel()->url_replacement_enabled()) {
+    GetToolbarModel()->set_origin_chip_enabled(true);
+    OnChanged();
+  } else {
+    HideURL();
+  }
+}
+
 OmniboxEditController::~OmniboxEditController() {
 }
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_controller.h b/chrome/browser/ui/omnibox/omnibox_edit_controller.h
index 2757210..9b9f08e 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_controller.h
+++ b/chrome/browser/ui/omnibox/omnibox_edit_controller.h
@@ -44,6 +44,16 @@
   // Called whenever the autocomplete edit gets focused.
   virtual void OnSetFocus() = 0;
 
+  // Hides the origin chip and shows the URL.
+  virtual void ShowURL() = 0;
+
+  // Hides the origin chip while leaving the Omnibox empty.
+  void HideOriginChip();
+
+  // Shows the origin chip.  Hides the URL if it was previously shown by a call
+  // to ShowURL().
+  void ShowOriginChip();
+
   // Returns the InstantController, or NULL if instant is not enabled.
   virtual InstantController* GetInstant() = 0;
 
@@ -57,6 +67,9 @@
   explicit OmniboxEditController(CommandUpdater* command_updater);
   virtual ~OmniboxEditController();
 
+  // Hides the URL and shows the origin chip.
+  virtual void HideURL() = 0;
+
   CommandUpdater* command_updater() { return command_updater_; }
   GURL destination_url() const { return destination_url_; }
   WindowOpenDisposition disposition() const { return disposition_; }
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_model.cc b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
index 7b05193..592a0f5 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_model.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_model.cc
@@ -501,24 +501,15 @@
     time_user_first_modified_omnibox_ = base::TimeTicks::Now();
     content::RecordAction(base::UserMetricsAction("OmniboxInputInProgress"));
     autocomplete_controller()->ResetSession();
-    // Once the user starts editing, re-enable URL replacement, so that it will
-    // kick in if applicable once the edit is committed or reverted. (While the
-    // edit is in progress, this won't have a visible effect.)
-    controller_->GetToolbarModel()->set_url_replacement_enabled(true);
   }
 
-  // The following code handles three cases:
+  // The following code handles two cases:
   // * For HIDE_ON_USER_INPUT, it hides the chip when user input begins.
   // * For HIDE_ON_MOUSE_RELEASE, which only hides the chip on mouse release if
   //   the omnibox is empty, it handles the "omnibox was not empty" case by
-  //   acting like HIDE_ON_USER_INPUT.  (If the omnibox was empty, it
-  //   effectively no-ops.)
-  // * For both hide behaviors, it allows the chip to be reshown once input
-  //   ends.  (The chip won't actually be re-shown until there's no pending
-  //   typed navigation; see OriginChipView::ShouldShow() and
-  //   OriginChipDecoration::ShouldShow().)
-  if (chrome::ShouldDisplayOriginChipV2())
-    controller()->GetToolbarModel()->set_origin_chip_enabled(!in_progress);
+  //   acting like HIDE_ON_USER_INPUT.
+  if (chrome::ShouldDisplayOriginChipV2() && in_progress)
+    controller()->GetToolbarModel()->set_origin_chip_enabled(false);
 
   controller_->GetToolbarModel()->set_input_in_progress(in_progress);
   controller_->Update(NULL);
@@ -924,9 +915,10 @@
     // that we avoid PermanentURL() here because it's not guaranteed to give us
     // the actual underlying current URL, e.g. if we're on the NTP and the
     // |permanent_text_| is empty.
-    autocomplete_controller()->StartZeroSuggest(delegate_->GetURL(),
-                                                ClassifyPage(),
-                                                permanent_text_);
+    autocomplete_controller()->StartZeroSuggest(AutocompleteInput(
+        permanent_text_, base::string16::npos, base::string16(),
+        delegate_->GetURL(), ClassifyPage(), false, false, true,
+        AutocompleteInput::ALL_MATCHES));
   }
 
   if (user_input_in_progress_ || !in_revert_)
@@ -942,9 +934,6 @@
 }
 
 void OmniboxEditModel::OnWillKillFocus(gfx::NativeView view_gaining_focus) {
-  // TODO(jered): Rip this out along with StartZeroSuggest.
-  autocomplete_controller()->StopZeroSuggest();
-
   if (user_input_in_progress_ || !in_revert_)
     delegate_->OnInputStateChanged();
 }
@@ -972,6 +961,15 @@
     view_->Update();
   }
 
+  // When using the origin chip, hitting escape to revert all should either
+  // display the URL (when search term replacement would not be performed for
+  // this page) or the search terms (when it would).  To accomplish this,
+  // we'll need to disable URL replacement iff it's currently enabled and
+  // search term replacement wouldn't normally happen.
+  bool should_disable_url_replacement =
+      controller_->GetToolbarModel()->url_replacement_enabled() &&
+      !controller_->GetToolbarModel()->WouldPerformSearchTermReplacement(true);
+
   // If the user wasn't editing, but merely had focus in the edit, allow <esc>
   // to be processed as an accelerator, so it can still be used to stop a load.
   // When the permanent text isn't all selected we still fall through to the
@@ -979,8 +977,8 @@
   // <esc> to quickly replace all the text; this matches IE.
   const bool has_zero_suggest_match = match.provider &&
       (match.provider->type() == AutocompleteProvider::TYPE_ZERO_SUGGEST);
-  if (!has_zero_suggest_match && !user_input_in_progress_ &&
-      view_->IsSelectAll())
+  if (!has_zero_suggest_match && !should_disable_url_replacement &&
+      !user_input_in_progress_ && view_->IsSelectAll())
     return false;
 
   if (!user_text_.empty()) {
@@ -988,7 +986,12 @@
                               OMNIBOX_USER_TEXT_CLEARED_WITH_ESCAPE,
                               OMNIBOX_USER_TEXT_CLEARED_NUM_OF_ITEMS);
   }
-  view_->RevertAll();
+
+  if (should_disable_url_replacement) {
+    controller_->GetToolbarModel()->set_url_replacement_enabled(false);
+    UpdatePermanentText();
+  }
+  view_->RevertWithoutResettingSearchTermReplacement();
   view_->SelectAll(true);
   return true;
 }
diff --git a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
index 6115ad7..7d27472 100644
--- a/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_edit_unittest.cc
@@ -105,10 +105,13 @@
         toolbar_model_(toolbar_model) {
   }
 
+ protected:
   // OmniboxEditController:
   virtual void Update(const content::WebContents* contents) OVERRIDE {}
   virtual void OnChanged() OVERRIDE {}
   virtual void OnSetFocus() OVERRIDE {}
+  virtual void ShowURL() OVERRIDE {}
+  virtual void HideURL() OVERRIDE {}
   virtual InstantController* GetInstant() OVERRIDE { return NULL; }
   virtual WebContents* GetWebContents() OVERRIDE { return NULL; }
   virtual ToolbarModel* GetToolbarModel() OVERRIDE { return toolbar_model_; }
diff --git a/chrome/browser/ui/omnibox/omnibox_view.cc b/chrome/browser/ui/omnibox/omnibox_view.cc
index d5c6847..ecd98b3 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view.cc
@@ -93,23 +93,14 @@
   if ((chrome::GetOriginChipV2HideTrigger() ==
        chrome::ORIGIN_CHIP_V2_HIDE_ON_MOUSE_RELEASE) &&
       controller()->GetToolbarModel()->GetText().empty()) {
-    controller()->GetToolbarModel()->set_origin_chip_enabled(false);
-    controller()->OnChanged();
+    controller()->HideOriginChip();
   }
 }
 
 void OmniboxView::OnDidKillFocus() {
-  // If user input is not in progress, re-enable the origin chip and URL
-  // replacement.  This addresses the case where the URL was shown by a call
-  // to ShowURL().  If the Omnibox achieved focus by other means, the calls to
-  // set_url_replacement_enabled, UpdatePermanentText and RevertAll are not
-  // required (a call to OnChanged would be sufficient) but do no harm.
   if (chrome::ShouldDisplayOriginChipV2() &&
       !model()->user_input_in_progress()) {
-    controller()->GetToolbarModel()->set_origin_chip_enabled(true);
-    controller()->GetToolbarModel()->set_url_replacement_enabled(true);
-    model()->UpdatePermanentText();
-    RevertAll();
+    controller()->ShowOriginChip();
   }
 }
 
@@ -119,10 +110,11 @@
                             const base::string16& pasted_text,
                             size_t selected_line) {
   // Invalid URLs such as chrome://history can end up here.
-  if (match.destination_url.is_valid() && model_) {
-    model_->OpenMatch(match, disposition, alternate_nav_url, pasted_text,
-                      selected_line);
-  }
+  if (!match.destination_url.is_valid() || !model_)
+    return;
+  model_->OpenMatch(
+      match, disposition, alternate_nav_url, pasted_text, selected_line);
+  OnMatchOpened(match, model_->profile(), controller_->GetWebContents());
 }
 
 bool OmniboxView::IsEditingOrEmpty() const {
@@ -178,6 +170,13 @@
   SelectAll(true);
 }
 
+void OmniboxView::HideURL() {
+  controller_->GetToolbarModel()->set_origin_chip_enabled(true);
+  controller_->GetToolbarModel()->set_url_replacement_enabled(true);
+  model_->UpdatePermanentText();
+  RevertWithoutResettingSearchTermReplacement();
+}
+
 void OmniboxView::RevertAll() {
   controller_->GetToolbarModel()->set_url_replacement_enabled(true);
   RevertWithoutResettingSearchTermReplacement();
@@ -211,6 +210,10 @@
   return false;
 }
 
+void OmniboxView::OnMatchOpened(const AutocompleteMatch& match,
+                                Profile* profile,
+                                content::WebContents* web_contents) const {}
+
 OmniboxView::OmniboxView(Profile* profile,
                          OmniboxEditController* controller,
                          CommandUpdater* command_updater)
diff --git a/chrome/browser/ui/omnibox/omnibox_view.h b/chrome/browser/ui/omnibox/omnibox_view.h
index d88125c..3463440 100644
--- a/chrome/browser/ui/omnibox/omnibox_view.h
+++ b/chrome/browser/ui/omnibox/omnibox_view.h
@@ -137,6 +137,9 @@
   // selects all.
   void ShowURL();
 
+  // Enables search term replacement and reverts the omnibox.
+  void HideURL();
+
   // Re-enables search term replacement on the ToolbarModel, and reverts the
   // edit and popup back to their unedited state (permanent text showing, popup
   // closed, no user input in progress).
@@ -232,6 +235,12 @@
   // only ever return true on mobile ports.
   virtual bool IsIndicatingQueryRefinement() const;
 
+  // Called after a |match| has been opened for the given |profile| and
+  // |web_contents|.
+  virtual void OnMatchOpened(const AutocompleteMatch& match,
+                             Profile* profile,
+                             content::WebContents* web_contents) const;
+
   // Returns |text| with any leading javascript schemas stripped.
   static base::string16 StripJavascriptSchemas(const base::string16& text);
 
diff --git a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
index c51bb2a..b92a358 100644
--- a/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
+++ b/chrome/browser/ui/omnibox/omnibox_view_browsertest.cc
@@ -1462,7 +1462,9 @@
 }
 #endif  // defined(TOOLKIT_GTK) || defined(TOOLKIT_VIEWS)
 
-IN_PROC_BROWSER_TEST_F(OmniboxViewTest, DoesNotUpdateAutocompleteOnBlur) {
+// Flaky test. crbug.com/356850
+IN_PROC_BROWSER_TEST_F(OmniboxViewTest,
+                       DISABLED_DoesNotUpdateAutocompleteOnBlur) {
   OmniboxView* omnibox_view = NULL;
   ASSERT_NO_FATAL_FAILURE(GetOmniboxView(&omnibox_view));
   OmniboxPopupModel* popup_model = omnibox_view->model()->popup_model();
@@ -1830,9 +1832,9 @@
   EXPECT_EQ(url_c, omnibox_view->GetText());
 }
 
-IN_PROC_BROWSER_TEST_F(OmniboxViewTest, InputResetsSearchTermReplacement) {
-  browser()->toolbar_model()->set_url_replacement_enabled(false);
+IN_PROC_BROWSER_TEST_F(OmniboxViewTest, EscDisablesSearchTermReplacement) {
+  browser()->toolbar_model()->set_url_replacement_enabled(true);
   chrome::FocusLocationBar(browser());
-  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_A, 0));
-  EXPECT_TRUE(browser()->toolbar_model()->url_replacement_enabled());
+  ASSERT_NO_FATAL_FAILURE(SendKey(ui::VKEY_ESCAPE, 0));
+  EXPECT_FALSE(browser()->toolbar_model()->url_replacement_enabled());
 }
diff --git a/chrome/browser/ui/panels/panel_host.cc b/chrome/browser/ui/panels/panel_host.cc
index 89c1863..9d8bbd3 100644
--- a/chrome/browser/ui/panels/panel_host.cc
+++ b/chrome/browser/ui/panels/panel_host.cc
@@ -160,8 +160,9 @@
   panel_->Deactivate();
 }
 
-void PanelHost::LoadingStateChanged(content::WebContents* source) {
-  bool is_loading = source->IsLoading();
+void PanelHost::LoadingStateChanged(content::WebContents* source,
+    bool to_different_document) {
+  bool is_loading = source->IsLoading() && to_different_document;
   panel_->LoadingStateChanged(is_loading);
 }
 
diff --git a/chrome/browser/ui/panels/panel_host.h b/chrome/browser/ui/panels/panel_host.h
index 37ab05b..d383f63 100644
--- a/chrome/browser/ui/panels/panel_host.h
+++ b/chrome/browser/ui/panels/panel_host.h
@@ -61,7 +61,8 @@
                               bool* was_blocked) OVERRIDE;
   virtual void ActivateContents(content::WebContents* contents) OVERRIDE;
   virtual void DeactivateContents(content::WebContents* contents) OVERRIDE;
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
   virtual void CloseContents(content::WebContents* source) OVERRIDE;
   virtual void MoveContents(content::WebContents* source,
                             const gfx::Rect& pos) OVERRIDE;
diff --git a/chrome/browser/ui/screen_capture_notification_ui_stub.cc b/chrome/browser/ui/screen_capture_notification_ui_stub.cc
index 5dfb1a8..d33ad4a 100644
--- a/chrome/browser/ui/screen_capture_notification_ui_stub.cc
+++ b/chrome/browser/ui/screen_capture_notification_ui_stub.cc
@@ -12,8 +12,10 @@
   ScreenCaptureNotificationUIStub() {}
   virtual ~ScreenCaptureNotificationUIStub() {}
 
-  virtual void OnStarted(const base::Closure& stop_callback) OVERRIDE {
+  virtual gfx::NativeViewId OnStarted(const base::Closure& stop_callback)
+      OVERRIDE {
     NOTIMPLEMENTED();
+    return 0;
   }
 };
 
diff --git a/chrome/browser/ui/search/search_tab_helper_unittest.cc b/chrome/browser/ui/search/search_tab_helper_unittest.cc
index 0cdc1bb..cd04921 100644
--- a/chrome/browser/ui/search/search_tab_helper_unittest.cc
+++ b/chrome/browser/ui/search/search_tab_helper_unittest.cc
@@ -67,12 +67,18 @@
     SearchTabHelper::CreateForWebContents(web_contents());
   }
 
+  virtual content::BrowserContext* CreateBrowserContext() OVERRIDE {
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              FakeSigninManagerBase::Build);
+    return builder.Build().release();
+  }
+
   // Creates a sign-in manager for tests.  If |username| is not empty, the
   // testing profile of the WebContents will be connected to the given account.
   void CreateSigninManager(const std::string& username) {
     SigninManagerBase* signin_manager = static_cast<SigninManagerBase*>(
-        SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-            profile(), FakeSigninManagerBase::Build));
+        SigninManagerFactory::GetForProfile(profile()));
 
     if (!username.empty()) {
       ASSERT_TRUE(signin_manager);
diff --git a/chrome/browser/ui/settings_window_manager.cc b/chrome/browser/ui/settings_window_manager.cc
new file mode 100644
index 0000000..f2a93ad
--- /dev/null
+++ b/chrome/browser/ui/settings_window_manager.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/settings_window_manager.h"
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/chrome_pages.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "content/public/browser/user_metrics.h"
+#include "content/public/browser/web_contents.h"
+
+namespace chrome {
+
+// static
+SettingsWindowManager* SettingsWindowManager::GetInstance() {
+  return Singleton<SettingsWindowManager>::get();
+}
+
+void SettingsWindowManager::ShowForProfile(Profile* profile,
+                                           const std::string& sub_page) {
+  content::RecordAction(base::UserMetricsAction("ShowOptions"));
+  GURL gurl = chrome::GetSettingsUrl(sub_page);
+  // Look for an existing browser window.
+  ProfileSessionMap::iterator iter = settings_session_map_.find(profile);
+  if (iter != settings_session_map_.end()) {
+    Browser* browser = chrome::FindBrowserWithID(iter->second);
+    if (browser) {
+      DCHECK(browser->profile() == profile);
+      const content::WebContents* web_contents =
+          browser->tab_strip_model()->GetWebContentsAt(0);
+      if (web_contents && web_contents->GetURL() == gurl) {
+        browser->window()->Show();
+        return;
+      }
+      NavigateParams params(browser, gurl,
+                            content::PAGE_TRANSITION_AUTO_BOOKMARK);
+      params.window_action = NavigateParams::SHOW_WINDOW;
+      params.user_gesture = true;
+      chrome::Navigate(&params);
+      return;
+    }
+  }
+  // No existing browser window, create one.
+  NavigateParams params(profile, gurl, content::PAGE_TRANSITION_AUTO_BOOKMARK);
+  params.disposition = NEW_POPUP;
+  params.window_action = NavigateParams::SHOW_WINDOW;
+  params.user_gesture = true;
+  params.path_behavior = NavigateParams::IGNORE_AND_NAVIGATE;
+  chrome::Navigate(&params);
+  settings_session_map_[profile] = params.browser->session_id().id();
+}
+
+SettingsWindowManager::SettingsWindowManager() {
+}
+
+SettingsWindowManager::~SettingsWindowManager() {
+}
+
+}  // namespace chrome
diff --git a/chrome/browser/ui/settings_window_manager.h b/chrome/browser/ui/settings_window_manager.h
new file mode 100644
index 0000000..fc96bcd
--- /dev/null
+++ b/chrome/browser/ui/settings_window_manager.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_SETTINGS_WINDOW_MANAGER_H_
+#define CHROME_BROWSER_UI_SETTINGS_WINDOW_MANAGER_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/singleton.h"
+#include "chrome/browser/sessions/session_id.h"
+
+class Profile;
+
+namespace chrome {
+
+// Class for managing settings windows when --enable-settings-window is enabled.
+// TODO(stevenjb): Remove flag comment if enabled by default.
+
+class SettingsWindowManager {
+ public:
+  static SettingsWindowManager* GetInstance();
+
+  // Show an existing settings window for |profile| or create a new one, and
+  // navigate to |sub_page|.
+  void ShowForProfile(Profile* profile, const std::string& sub_page);
+
+ private:
+  friend struct DefaultSingletonTraits<SettingsWindowManager>;
+  typedef std::map<Profile*, SessionID::id_type> ProfileSessionMap;
+
+  SettingsWindowManager();
+  ~SettingsWindowManager();
+
+  ProfileSessionMap settings_session_map_;
+
+  DISALLOW_COPY_AND_ASSIGN(SettingsWindowManager);
+};
+
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_UI_SETTINGS_WINDOW_MANAGER_H_
diff --git a/chrome/browser/ui/startup/bad_flags_prompt.cc b/chrome/browser/ui/startup/bad_flags_prompt.cc
index 5779c99..4236f62 100644
--- a/chrome/browser/ui/startup/bad_flags_prompt.cc
+++ b/chrome/browser/ui/startup/bad_flags_prompt.cc
@@ -51,9 +51,9 @@
 
     // These flags undermine HTTPS / connection security.
     switches::kDisableUserMediaSecurity,
-  #if defined(ENABLE_WEBRTC)
+#if defined(ENABLE_WEBRTC)
     switches::kDisableWebRtcEncryption,
-  #endif
+#endif
     switches::kIgnoreCertificateErrors,
     switches::kReduceSecurityForTesting,
     switches::kSyncAllowInsecureXmppConnection,
@@ -65,6 +65,12 @@
 
     // This flag gives extensions more powers.
     extensions::switches::kExtensionsOnChromeURLs,
+
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+    // Speech dispatcher is buggy, it can crash and it can make Chrome freeze.
+    // http://crbug.com/327295
+    switches::kEnableSpeechDispatcher,
+#endif
     NULL
   };
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index 3041b1d..bcf713a 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -88,6 +88,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_view.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/constants.h"
 #include "grit/locale_settings.h"
@@ -285,13 +286,12 @@
   DISALLOW_COPY_AND_ASSIGN(WebContentsCloseObserver);
 };
 
-const Extension* GetDisabledOrTerminatedPlatformApp(Profile* profile,
-                                        const std::string& extension_id) {
-  ExtensionService* service =
-      extensions::ExtensionSystem::Get(profile)->extension_service();
-  const Extension* extension = service->GetExtensionById(extension_id, true);
-  if (!extension)
-    extension = service->GetTerminatedExtension(extension_id);
+// TODO(koz): Consolidate this function and remove the special casing.
+const Extension* GetPlatformApp(Profile* profile,
+                                const std::string& extension_id) {
+  const Extension* extension =
+      extensions::ExtensionRegistry::Get(profile)->GetExtensionById(
+          extension_id, extensions::ExtensionRegistry::EVERYTHING);
   return extension && extension->is_platform_app() ? extension : NULL;
 }
 
@@ -349,8 +349,7 @@
   AppListService::InitAll(profile);
   if (command_line_.HasSwitch(switches::kAppId)) {
     std::string app_id = command_line_.GetSwitchValueASCII(switches::kAppId);
-    const Extension* extension =
-        GetDisabledOrTerminatedPlatformApp(profile, app_id);
+    const Extension* extension = GetPlatformApp(profile, app_id);
     // If |app_id| is a disabled or terminated platform app we handle it
     // specially here, otherwise it will be handled below.
     if (extension) {
diff --git a/chrome/browser/ui/sync/one_click_signin_helper.cc b/chrome/browser/ui/sync/one_click_signin_helper.cc
index 6539a9a..62752b0 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/signin/chrome_signin_client.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
@@ -61,10 +62,10 @@
 #include "chrome/common/url_constants.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/password_manager/core/browser/password_manager.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_client.h"
-#include "components/signin/core/signin_error_controller.h"
-#include "components/signin/core/signin_manager_cookie_helper.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/core/browser/signin_error_controller.h"
+#include "components/signin/core/browser/signin_manager_cookie_helper.h"
 #include "components/sync_driver/sync_prefs.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_entry.h"
@@ -903,7 +904,7 @@
   if (io_data->IsOffTheRecord())
     return DONT_OFFER;
 
-  if (!SigninManager::IsSigninAllowedOnIOThread(io_data))
+  if (!io_data->signin_allowed()->GetValue())
     return DONT_OFFER;
 
   if (!io_data->reverse_autologin_enabled()->GetValue())
@@ -1112,10 +1113,10 @@
   // show a modal dialog asking the user to confirm.
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  SigninManager* manager = profile ?
-      SigninManagerFactory::GetForProfile(profile) : NULL;
+  ChromeSigninClient* signin_client =
+      profile ? ChromeSigninClientFactory::GetForProfile(profile) : NULL;
   helper->untrusted_confirmation_required_ |=
-      (manager && !manager->IsSigninProcess(child_id));
+      (signin_client && !signin_client->IsSigninProcess(child_id));
 
   if (continue_url.is_valid()) {
     // Set |original_continue_url_| if it is currently empty. |continue_url|
@@ -1307,11 +1308,11 @@
     // sign-in process when a navigation to a non-sign-in URL occurs.
     Profile* profile =
         Profile::FromBrowserContext(web_contents()->GetBrowserContext());
-    SigninManager* manager = profile ?
-        SigninManagerFactory::GetForProfile(profile) : NULL;
+    ChromeSigninClient* signin_client =
+        profile ? ChromeSigninClientFactory::GetForProfile(profile) : NULL;
     int process_id = web_contents()->GetRenderProcessHost()->GetID();
-    if (manager && manager->IsSigninProcess(process_id))
-      manager->ClearSigninProcess();
+    if (signin_client && signin_client->IsSigninProcess(process_id))
+      signin_client->ClearSigninProcess();
 
     // If the navigation to a non-sign-in URL hasn't been triggered by the web
     // contents, the sign in flow has been aborted and the state must be
@@ -1474,7 +1475,7 @@
     case AUTO_ACCEPT_ACCEPTED:
       LogOneClickHistogramValue(one_click_signin::HISTOGRAM_ACCEPTED);
       LogOneClickHistogramValue(one_click_signin::HISTOGRAM_WITH_DEFAULTS);
-      SigninManager::DisableOneClickSignIn(profile);
+      SigninManager::DisableOneClickSignIn(profile->GetPrefs());
       // Start syncing with the default settings - prompt the user to sign in
       // first.
       if (!do_not_start_sync_for_testing_) {
@@ -1490,7 +1491,7 @@
     case AUTO_ACCEPT_CONFIGURE:
       LogOneClickHistogramValue(one_click_signin::HISTOGRAM_ACCEPTED);
       LogOneClickHistogramValue(one_click_signin::HISTOGRAM_WITH_ADVANCED);
-      SigninManager::DisableOneClickSignIn(profile);
+      SigninManager::DisableOneClickSignIn(profile->GetPrefs());
       // Display the extra confirmation (even in the SAML case) in case this
       // was an untrusted renderer.
       if (!do_not_start_sync_for_testing_) {
diff --git a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
index 8848f84..73dd4bb 100644
--- a/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_helper_unittest.cc
@@ -14,8 +14,10 @@
 #include "chrome/browser/profiles/profile_info_cache.h"
 #include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/signin/chrome_signin_client.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_wrapper.h"
+#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -35,7 +37,7 @@
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
 #include "components/autofill/core/common/password_form.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/pref_names.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_details.h"
@@ -202,10 +204,10 @@
   virtual void SetUp() OVERRIDE;
   virtual void TearDown() OVERRIDE;
 
-  // Creates the sign-in manager for tests.  If |username| is
+  // Sets up the sign-in manager for tests.  If |username| is
   // is not empty, the profile of the mock WebContents will be connected to
   // the given account.
-  void CreateSigninManager(const std::string& username);
+  void SetUpSigninManager(const std::string& username);
 
   // Set the ID of the signin process that the test will assume to be the
   // only process allowed to sign the user in to Chrome.
@@ -258,14 +260,14 @@
   trusted_signin_process_id_ = id;
 }
 
-void OneClickSigninHelperTest::CreateSigninManager(
-    const std::string& username) {
-  signin_manager_ = static_cast<SigninManagerMock*>(
-      SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-          profile(), BuildSigninManagerMock));
-  if (signin_manager_)
-    signin_manager_->SetSigninProcess(trusted_signin_process_id_);
+void OneClickSigninHelperTest::SetUpSigninManager(const std::string& username) {
+  ChromeSigninClient* signin_client =
+      ChromeSigninClientFactory::GetForProfile(profile());
+  if (signin_client)
+    signin_client->SetSigninProcess(trusted_signin_process_id_);
 
+  signin_manager_ = static_cast<SigninManagerMock*>(
+      SigninManagerFactory::GetForProfile(profile()));
   if (!username.empty()) {
     ASSERT_TRUE(signin_manager_);
     signin_manager_->SetAuthenticatedUsername(username);
@@ -328,7 +330,9 @@
 content::BrowserContext* OneClickSigninHelperTest::CreateBrowserContext() {
   TestingProfile::Builder builder;
   builder.AddTestingFactory(ProfileOAuth2TokenServiceFactory::GetInstance(),
-                            FakeProfileOAuth2TokenServiceWrapper::Build);
+                            BuildFakeProfileOAuth2TokenService);
+  builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                            BuildSigninManagerMock);
   scoped_ptr<TestingProfile> profile = builder.Build();
 
   fake_oauth2_token_service_ =
@@ -411,7 +415,7 @@
 }
 
 TEST_F(OneClickSigninHelperTest, CanOffer) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
 
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
         WillRepeatedly(Return(true));
@@ -449,7 +453,7 @@
 }
 
 TEST_F(OneClickSigninHelperTest, CanOfferFirstSetup) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
 
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
         WillRepeatedly(Return(true));
@@ -479,7 +483,7 @@
 }
 
 TEST_F(OneClickSigninHelperTest, CanOfferProfileConnected) {
-  CreateSigninManager("foo@gmail.com");
+  SetUpSigninManager("foo@gmail.com");
 
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
       WillRepeatedly(Return(true));
@@ -519,7 +523,7 @@
 }
 
 TEST_F(OneClickSigninHelperTest, CanOfferUsernameNotAllowed) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
 
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
       WillRepeatedly(Return(false));
@@ -543,7 +547,7 @@
 }
 
 TEST_F(OneClickSigninHelperTest, CanOfferWithRejectedEmail) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
 
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
         WillRepeatedly(Return(true));
@@ -572,7 +576,7 @@
 }
 
 TEST_F(OneClickSigninHelperIncognitoTest, CanOfferIncognito) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
 
   std::string error_message;
   EXPECT_FALSE(OneClickSigninHelper::CanOffer(
@@ -592,7 +596,7 @@
 }
 
 TEST_F(OneClickSigninHelperTest, CanOfferNoSigninCookies) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
   AllowSigninCookies(false);
 
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
@@ -616,7 +620,7 @@
 }
 
 TEST_F(OneClickSigninHelperTest, CanOfferDisabledByPolicy) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
 
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_)).
         WillRepeatedly(Return(true));
@@ -651,7 +655,7 @@
 // Should not crash if a helper instance is not associated with an incognito
 // web contents.
 TEST_F(OneClickSigninHelperIncognitoTest, ShowInfoBarUIThreadIncognito) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
   OneClickSigninHelper* helper =
       OneClickSigninHelper::FromWebContents(web_contents());
   EXPECT_EQ(NULL, helper);
@@ -666,7 +670,7 @@
 // config sync, then Chrome should redirect immediately to sync settings page,
 // and upon successful setup, redirect back to webstore.
 TEST_F(OneClickSigninHelperTest, SigninFromWebstoreWithConfigSyncfirst) {
-  CreateSigninManager(std::string());
+  SetUpSigninManager(std::string());
   EXPECT_CALL(*signin_manager_, IsAllowedUsername(_))
       .WillRepeatedly(Return(true));
 
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
index 395b966..84a4420 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter.cc
@@ -508,8 +508,8 @@
 void OneClickSigninSyncStarter::ShowSettingsPageInWebContents(
     content::WebContents* contents,
     const std::string& sub_page) {
-  std::string url = std::string(chrome::kChromeUISettingsURL) + sub_page;
-  content::OpenURLParams params(GURL(url),
+  GURL url = chrome::GetSettingsUrl(sub_page);
+  content::OpenURLParams params(url,
                                 content::Referrer(),
                                 CURRENT_TAB,
                                 content::PAGE_TRANSITION_AUTO_TOPLEVEL,
diff --git a/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc b/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
index 7637286..2a8cb58 100644
--- a/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
+++ b/chrome/browser/ui/sync/one_click_signin_sync_starter_unittest.cc
@@ -29,17 +29,20 @@
   // testing::Test:
   virtual void SetUp() OVERRIDE {
     testing::Test::SetUp();
-    profile_.reset(new TestingProfile());
+
+    // Create the sign in manager required by OneClickSigninSyncStarter.
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(
+        SigninManagerFactory::GetInstance(),
+        &OneClickSigninSyncStarterTest::BuildSigninManager);
+    profile_ = builder.Build();
+
+    SigninManagerBase* signin_manager = static_cast<FakeSigninManager*>(
+        SigninManagerFactory::GetForProfile(profile_.get()));
 
     // Disable sync to simplify the creation of a OneClickSigninSyncStarter.
     CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableSync);
 
-    // Create the sign in manager required by OneClickSigninSyncStarter.
-    SigninManagerBase* signin_manager =
-        static_cast<FakeSigninManager*>(
-            SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-                profile_.get(),
-                &OneClickSigninSyncStarterTest::BuildSigninManager));
     signin_manager->Initialize(profile_.get(), NULL);
     signin_manager->SetAuthenticatedUsername(kTestingUsername);
   }
diff --git a/chrome/browser/ui/sync/sync_promo_ui_unittest.cc b/chrome/browser/ui/sync/sync_promo_ui_unittest.cc
index 05e4b5c..f4ea003 100644
--- a/chrome/browser/ui/sync/sync_promo_ui_unittest.cc
+++ b/chrome/browser/ui/sync/sync_promo_ui_unittest.cc
@@ -21,23 +21,13 @@
   // testing::Test:
   virtual void SetUp() OVERRIDE {
     testing::Test::SetUp();
-    profile_.reset(new TestingProfile());
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              FakeSigninManagerBase::Build);
+    profile_ = builder.Build();
   }
 
  protected:
-  void CreateSigninManager(const std::string& username) {
-    FakeSigninManagerForTesting* signin_manager =
-        static_cast<FakeSigninManagerForTesting*>(
-            SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-                profile_.get(),
-                &FakeSigninManagerBase::Build));
-
-    if (!username.empty()) {
-      ASSERT_TRUE(signin_manager);
-      signin_manager->SetAuthenticatedUsername(username);
-    }
-  }
-
   void DisableSync() {
     CommandLine::ForCurrentProcess()->AppendSwitch(switches::kDisableSync);
   }
@@ -51,7 +41,6 @@
 // Verifies that ShouldShowSyncPromo returns false if sync is disabled by
 // policy.
 TEST_F(SyncPromoUITest, ShouldShowSyncPromoSyncDisabled) {
-  CreateSigninManager("");
   DisableSync();
   EXPECT_FALSE(SyncPromoUI::ShouldShowSyncPromo(profile_.get()));
 }
@@ -59,7 +48,6 @@
 // Verifies that ShouldShowSyncPromo returns true if all conditions to
 // show the promo are met.
 TEST_F(SyncPromoUITest, ShouldShowSyncPromoSyncEnabled) {
-  CreateSigninManager("");
 #if defined(OS_CHROMEOS)
   // No sync promo on CrOS.
   EXPECT_FALSE(SyncPromoUI::ShouldShowSyncPromo(profile_.get()));
diff --git a/chrome/browser/ui/tab_contents/OWNERS b/chrome/browser/ui/tab_contents/OWNERS
index d60eba2..37b4544 100644
--- a/chrome/browser/ui/tab_contents/OWNERS
+++ b/chrome/browser/ui/tab_contents/OWNERS
@@ -1,3 +1,2 @@
 avi@chromium.org
-joi@chromium.org
 jam@chromium.org
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index fc586cf..5fd4fef 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -109,9 +109,6 @@
 
   // Create all the tab helpers.
 
-  Profile* profile =
-      Profile::FromBrowserContext(web_contents->GetBrowserContext());
-
   // SessionTabHelper comes first because it sets up the tab ID, and other
   // helpers may rely on that.
   SessionTabHelper::CreateForWebContents(web_contents);
@@ -183,6 +180,8 @@
 #endif
 
 #if defined(ENABLE_MANAGED_USERS)
+  Profile* profile =
+      Profile::FromBrowserContext(web_contents->GetBrowserContext());
   if (profile->IsManaged()) {
     ManagedModeNavigationObserver::CreateForWebContents(web_contents);
   }
diff --git a/chrome/browser/ui/toolbar/bookmark_sub_menu_model.cc b/chrome/browser/ui/toolbar/bookmark_sub_menu_model.cc
index 21f4a1c..0a3382e 100644
--- a/chrome/browser/ui/toolbar/bookmark_sub_menu_model.cc
+++ b/chrome/browser/ui/toolbar/bookmark_sub_menu_model.cc
@@ -30,12 +30,16 @@
 #if !defined(OS_CHROMEOS)
   AddItemWithStringId(IDC_IMPORT_SETTINGS, IDS_IMPORT_SETTINGS_MENU_LABEL);
 #endif
-  AddSeparator(ui::NORMAL_SEPARATOR);
+  if (delegate()->IsCommandIdVisible(IDC_BOOKMARK_PAGE) ||
+      delegate()->IsCommandIdVisible(IDC_BOOKMARK_ALL_TABS) ||
+      delegate()->IsCommandIdVisible(IDC_PIN_TO_START_SCREEN)) {
+    AddSeparator(ui::NORMAL_SEPARATOR);
 
-  AddItemWithStringId(IDC_BOOKMARK_PAGE, IDS_BOOKMARK_THIS_PAGE);
-  AddItemWithStringId(IDC_BOOKMARK_ALL_TABS, IDS_BOOKMARK_OPEN_PAGES);
+    AddItemWithStringId(IDC_BOOKMARK_PAGE, IDS_BOOKMARK_THIS_PAGE);
+    AddItemWithStringId(IDC_BOOKMARK_ALL_TABS, IDS_BOOKMARK_OPEN_PAGES);
 
-  AddItemWithStringId(IDC_PIN_TO_START_SCREEN, IDS_PIN_TO_START_SCREEN);
+    AddItemWithStringId(IDC_PIN_TO_START_SCREEN, IDS_PIN_TO_START_SCREEN);
+  }
 #if defined(OS_MACOSX)
   AddSeparator(ui::NORMAL_SEPARATOR);
 #endif
diff --git a/chrome/browser/ui/toolbar/test_toolbar_model.cc b/chrome/browser/ui/toolbar/test_toolbar_model.cc
index 1d11263..f086bcb 100644
--- a/chrome/browser/ui/toolbar/test_toolbar_model.cc
+++ b/chrome/browser/ui/toolbar/test_toolbar_model.cc
@@ -20,6 +20,10 @@
   return text_;
 }
 
+base::string16 TestToolbarModel::GetFormattedURL() const {
+  return text_;
+}
+
 base::string16 TestToolbarModel::GetCorpusNameForMobile() const {
   return base::string16();
 }
diff --git a/chrome/browser/ui/toolbar/test_toolbar_model.h b/chrome/browser/ui/toolbar/test_toolbar_model.h
index dd3a539..f426056 100644
--- a/chrome/browser/ui/toolbar/test_toolbar_model.h
+++ b/chrome/browser/ui/toolbar/test_toolbar_model.h
@@ -17,6 +17,7 @@
   TestToolbarModel();
   virtual ~TestToolbarModel();
   virtual base::string16 GetText() const OVERRIDE;
+  virtual base::string16 GetFormattedURL() const OVERRIDE;
   virtual base::string16 GetCorpusNameForMobile() const OVERRIDE;
   virtual GURL GetURL() const OVERRIDE;
   virtual bool WouldPerformSearchTermReplacement(
diff --git a/chrome/browser/ui/toolbar/toolbar_model.h b/chrome/browser/ui/toolbar/toolbar_model.h
index 4f1abc6..f4ecb74 100644
--- a/chrome/browser/ui/toolbar/toolbar_model.h
+++ b/chrome/browser/ui/toolbar/toolbar_model.h
@@ -31,15 +31,21 @@
 
   virtual ~ToolbarModel();
 
-  // Returns the text for the current page's URL. This will have been formatted
-  // for display to the user:
-  //   - Some characters may be unescaped.
-  //   - The scheme and/or trailing slash may be dropped.
+  // Returns the text to be displayed in the toolbar for the current page.
+  // The text is formatted in various ways:
   //   - If the current page's URL is a search URL for the user's default search
   //     engine, the query will be extracted and returned for display instead
   //     of the URL.
+  //   - If the origin chip is enabled and visible, the text will be empty.
+  //   - Otherwise, the text will contain the URL returned by GetFormattedURL().
   virtual base::string16 GetText() const = 0;
 
+  // Returns a formatted URL for display in the toolbar. The formatting
+  // includes:
+  //   - Some characters may be unescaped.
+  //   - The scheme and/or trailing slash may be dropped.
+  virtual base::string16 GetFormattedURL() const = 0;
+
   // Some search URLs bundle a special "corpus" param that we can extract and
   // display next to users' search terms in cases where we'd show the search
   // terms instead of the URL anyway.  For example, a Google image search might
diff --git a/chrome/browser/ui/toolbar/toolbar_model_impl.cc b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
index eac4909..1a36ba2 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_impl.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_impl.cc
@@ -103,6 +103,10 @@
   if (WouldOmitURLDueToOriginChip())
     return base::string16();
 
+  return GetFormattedURL();
+}
+
+base::string16 ToolbarModelImpl::GetFormattedURL() const {
   std::string languages;  // Empty if we don't have a |navigation_controller|.
   Profile* profile = GetProfile();
   if (profile)
diff --git a/chrome/browser/ui/toolbar/toolbar_model_impl.h b/chrome/browser/ui/toolbar/toolbar_model_impl.h
index 35e1434..7cec706 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_impl.h
+++ b/chrome/browser/ui/toolbar/toolbar_model_impl.h
@@ -42,6 +42,7 @@
  private:
   // ToolbarModel:
   virtual base::string16 GetText() const OVERRIDE;
+  virtual base::string16 GetFormattedURL() const OVERRIDE;
   virtual base::string16 GetCorpusNameForMobile() const OVERRIDE;
   virtual GURL GetURL() const OVERRIDE;
   virtual bool WouldOmitURLDueToOriginChip() const OVERRIDE;
diff --git a/chrome/browser/ui/toolbar/wrench_menu_model.cc b/chrome/browser/ui/toolbar/wrench_menu_model.cc
index b7cc878..08c7c35 100644
--- a/chrome/browser/ui/toolbar/wrench_menu_model.cc
+++ b/chrome/browser/ui/toolbar/wrench_menu_model.cc
@@ -81,10 +81,9 @@
 // Conditionally return the update app menu item title based on upgrade detector
 // state.
 base::string16 GetUpgradeDialogMenuItemName() {
-  if (UpgradeDetector::GetInstance()->is_outdated_install()) {
-    return l10n_util::GetStringFUTF16(
-        IDS_UPGRADE_BUBBLE_MENU_ITEM,
-        l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
+  if (UpgradeDetector::GetInstance()->is_outdated_install() ||
+      UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
+    return l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_MENU_ITEM);
   } else {
     return l10n_util::GetStringUTF16(IDS_UPDATE_NOW);
   }
@@ -427,6 +426,8 @@
 #if !defined(OS_LINUX) || defined(USE_AURA)
     case IDC_BOOKMARK_PAGE:
       return !chrome::ShouldRemoveBookmarkThisPageUI(browser_->profile());
+    case IDC_BOOKMARK_ALL_TABS:
+      return !chrome::ShouldRemoveBookmarkOpenPagesUI(browser_->profile());
 #endif
     default:
       return true;
diff --git a/chrome/browser/ui/views/accessibility/accessibility_event_router_views.cc b/chrome/browser/ui/views/accessibility/accessibility_event_router_views.cc
index f3bd9c9..8d82915 100644
--- a/chrome/browser/ui/views/accessibility/accessibility_event_router_views.cc
+++ b/chrome/browser/ui/views/accessibility/accessibility_event_router_views.cc
@@ -343,8 +343,7 @@
   view->GetAccessibleState(&state);
   std::string name = base::UTF16ToUTF8(state.name);
   std::string context = GetViewContext(view);
-  bool password =
-      (state.state & ui::AX_STATE_PROTECTED) != 0;
+  bool password = state.HasStateFlag(ui::AX_STATE_PROTECTED);
   AccessibilityTextBoxInfo info(profile, name, context, password);
   std::string value = base::UTF16ToUTF8(state.value);
   info.SetValue(value, state.selection_start, state.selection_end);
@@ -379,7 +378,7 @@
       profile,
       name,
       context,
-      state.state == ui::AX_STATE_CHECKED);
+      state.HasStateFlag(ui::AX_STATE_CHECKED));
   SendControlAccessibilityNotification(event, &info);
 }
 
diff --git a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
index 55d816b..07b7f26 100644
--- a/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
+++ b/chrome/browser/ui/views/accessibility/invert_bubble_view.cc
@@ -31,7 +31,6 @@
     "https://chrome.google.com/webstore/search-themes/dark";
 const char kLearnMoreUrl[] =
     "https://groups.google.com/a/googleproductforums.com/d/topic/chrome/Xrco2HsXS-8/discussion";
-const int kBubbleWidth = 500;
 
 class InvertBubbleView : public views::BubbleDelegateView,
                          public views::LinkListener {
@@ -75,10 +74,8 @@
       rb.GetFontList(ui::ResourceBundle::MediumFont);
 
   views::Label* title = new views::Label(
-      l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_NOTIFICATION),
-      original_font_list.Derive(2, gfx::Font::BOLD));
+      base::string16(), original_font_list.Derive(2, gfx::Font::BOLD));
   title->SetMultiLine(true);
-  title->SizeToFit(kBubbleWidth);
 
   learn_more_ = new views::Link(l10n_util::GetStringUTF16(IDS_LEARN_MORE));
   learn_more_->SetFontList(original_font_list);
@@ -89,8 +86,7 @@
   high_contrast_->SetFontList(original_font_list);
   high_contrast_->set_listener(this);
 
-  dark_theme_ =
-      new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME));
+  dark_theme_ = new views::Link(l10n_util::GetStringUTF16(IDS_DARK_THEME));
   dark_theme_->SetFontList(original_font_list);
   dark_theme_->set_listener(this);
 
@@ -117,6 +113,11 @@
   layout->AddView(learn_more_);
   layout->AddView(close_);
 
+  // Fit the message to the width of the links in the bubble.
+  const gfx::Size size(GetPreferredSize());
+  title->SetText(l10n_util::GetStringUTF16(IDS_HIGH_CONTRAST_NOTIFICATION));
+  title->SizeToFit(size.width());
+
   // Switching to high-contrast mode has a nasty habit of causing Chrome
   // top-level windows to lose focus, so closing the bubble on deactivate
   // makes it disappear before the user has even seen it. This forces the
diff --git a/chrome/browser/ui/views/app_list/linux/app_list_service_linux.cc b/chrome/browser/ui/views/app_list/linux/app_list_service_linux.cc
index c19e9e4..37af4f0 100644
--- a/chrome/browser/ui/views/app_list/linux/app_list_service_linux.cc
+++ b/chrome/browser/ui/views/app_list/linux/app_list_service_linux.cc
@@ -100,8 +100,6 @@
 
   ScopedKeepAlive show_app_list_keepalive;
 
-  // TODO(mgiuca): Call SetDidRunForNDayActiveStats.
-
   InvalidatePendingProfileLoads();
   SetProfilePath(requested_profile->GetPath());
   shower_->ShowForProfile(requested_profile);
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_tab.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_tab.cc
index 5e006b3..e8d6d31 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_tab.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_permissions_tab.cc
@@ -9,13 +9,14 @@
 #include "extensions/common/permissions/permission_set.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
-#include "ui/message_center/views/bounded_scroll_view.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/layout/layout_constants.h"
 
 // A scrollable list of permissions for the given app.
-class PermissionsScrollView : public message_center::BoundedScrollView {
+class PermissionsScrollView : public views::ScrollView {
  public:
   PermissionsScrollView(int min_height,
                         int max_height,
@@ -27,8 +28,10 @@
 
 PermissionsScrollView::PermissionsScrollView(int min_height,
                                              int max_height,
-                                             const extensions::Extension* app)
-    : message_center::BoundedScrollView(min_height, max_height) {
+                                             const extensions::Extension* app) {
+  ClipHeightTo(min_height, max_height);
+  SetVerticalScrollBar(new views::OverlayScrollBar(false));
+
   views::View* inner_scrollable_view = new views::View();
   this->SetContents(inner_scrollable_view);
 
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc
index 2cf7207..c494a2c 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.cc
@@ -4,15 +4,22 @@
 
 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.h"
 
+#include <vector>
+
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/image_loader.h"
+#include "chrome/browser/extensions/launch_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/common/chrome_switches.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/extension_icon_set.h"
 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
 #include "chrome/common/extensions/manifest_url_handler.h"
+#include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "grit/generated_resources.h"
 #include "net/base/url_util.h"
@@ -20,6 +27,7 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image.h"
 #include "ui/gfx/image/image_skia.h"
+#include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/link.h"
@@ -30,12 +38,106 @@
 // Size of extension icon in top left of dialog.
 const int kIconSize = 64;
 
+// A model for a combobox selecting the launch options for a hosted app.
+// Displays different options depending on the host OS.
+class LaunchOptionsComboboxModel : public ui::ComboboxModel {
+ public:
+  LaunchOptionsComboboxModel();
+  virtual ~LaunchOptionsComboboxModel();
+
+  extensions::LaunchType GetLaunchTypeAtIndex(int index) const;
+  int GetIndexForLaunchType(extensions::LaunchType launch_type) const;
+
+  // Overridden from ui::ComboboxModel:
+  virtual int GetItemCount() const OVERRIDE;
+  virtual base::string16 GetItemAt(int index) OVERRIDE;
+
+ private:
+  // A list of the launch types available in the combobox, in order.
+  std::vector<extensions::LaunchType> launch_types_;
+
+  // A list of the messages to display in the combobox, in order. The indexes in
+  // this list correspond to the indexes in launch_types_.
+  std::vector<base::string16> launch_type_messages_;
+};
+
+LaunchOptionsComboboxModel::LaunchOptionsComboboxModel() {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableStreamlinedHostedApps)) {
+    // Streamlined hosted apps can only toggle between LAUNCH_TYPE_WINDOW and
+    // LAUNCH_TYPE_REGULAR.
+    // TODO(sashab): Use a checkbox for this choice instead of combobox.
+    launch_types_.push_back(extensions::LAUNCH_TYPE_REGULAR);
+    launch_type_messages_.push_back(
+        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_TAB));
+
+    // Although LAUNCH_TYPE_WINDOW doesn't work on Mac, the streamlined hosted
+    // apps flag isn't available on Mac, so we must be on a non-Mac OS.
+    launch_types_.push_back(extensions::LAUNCH_TYPE_WINDOW);
+    launch_type_messages_.push_back(
+        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW));
+  } else {
+    launch_types_.push_back(extensions::LAUNCH_TYPE_REGULAR);
+    launch_type_messages_.push_back(
+        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_REGULAR));
+
+    launch_types_.push_back(extensions::LAUNCH_TYPE_PINNED);
+    launch_type_messages_.push_back(
+        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_PINNED));
+
+#if defined(OS_MACOSX)
+    // Mac does not support standalone web app browser windows or maximize.
+    launch_types_.push_back(extensions::LAUNCH_TYPE_FULLSCREEN);
+    launch_type_messages_.push_back(
+        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_FULLSCREEN));
+#else
+    launch_types_.push_back(extensions::LAUNCH_TYPE_WINDOW);
+    launch_type_messages_.push_back(
+        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_WINDOW));
+
+    // Even though the launch type is Full Screen, it is more accurately
+    // described as Maximized in non-Mac OSs.
+    launch_types_.push_back(extensions::LAUNCH_TYPE_FULLSCREEN);
+    launch_type_messages_.push_back(
+        l10n_util::GetStringUTF16(IDS_APP_CONTEXT_MENU_OPEN_MAXIMIZED));
+#endif
+  }
+}
+
+LaunchOptionsComboboxModel::~LaunchOptionsComboboxModel() {}
+
+extensions::LaunchType LaunchOptionsComboboxModel::GetLaunchTypeAtIndex(
+    int index) const {
+  return launch_types_[index];
+}
+
+int LaunchOptionsComboboxModel::GetIndexForLaunchType(
+    extensions::LaunchType launch_type) const {
+  for (size_t i = 0; i < launch_types_.size(); i++) {
+    if (launch_types_[i] == launch_type) {
+      return i;
+    }
+  }
+  // If the requested launch type is not available, just select the first one.
+  LOG(WARNING) << "Unavailable launch type " << launch_type << " selected.";
+  return 0;
+}
+
+int LaunchOptionsComboboxModel::GetItemCount() const {
+  return launch_types_.size();
+};
+
+base::string16 LaunchOptionsComboboxModel::GetItemAt(int index) {
+  return launch_type_messages_[index];
+};
+
 AppInfoSummaryTab::AppInfoSummaryTab(gfx::NativeWindow parent_window,
                                      Profile* profile,
                                      const extensions::Extension* app,
                                      const base::Closure& close_callback)
     : AppInfoTab(parent_window, profile, app, close_callback),
       app_icon_(NULL),
+      launch_options_combobox_(NULL),
       weak_ptr_factory_(this) {
   // Create UI elements.
   views::Label* app_name_label =
@@ -112,9 +214,36 @@
     layout->StartRow(0, kMainColumnSetId);
     layout->AddView(view_in_store_link_);
   }
+
+  // Add hosted app launch options for non-platform apps.
+  if (CanSetLaunchType()) {
+    launch_options_combobox_model_.reset(new LaunchOptionsComboboxModel());
+    launch_options_combobox_ =
+        new views::Combobox(launch_options_combobox_model_.get());
+
+    launch_options_combobox_->set_listener(this);
+    launch_options_combobox_->SetSelectedIndex(
+        launch_options_combobox_model_->GetIndexForLaunchType(GetLaunchType()));
+
+    layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
+    layout->StartRow(0, kMainColumnSetId);
+    layout->AddView(launch_options_combobox_);
+  }
 }
 
-AppInfoSummaryTab::~AppInfoSummaryTab() {}
+AppInfoSummaryTab::~AppInfoSummaryTab() {
+  // Destroy view children before their models.
+  RemoveAllChildViews(true);
+}
+
+void AppInfoSummaryTab::OnPerformAction(views::Combobox* combobox) {
+  if (combobox == launch_options_combobox_) {
+    SetLaunchType(launch_options_combobox_model_->GetLaunchTypeAtIndex(
+        launch_options_combobox_->selected_index()));
+  } else {
+    NOTREACHED();
+  }
+}
 
 void AppInfoSummaryTab::LinkClicked(views::Link* source, int event_flags) {
   if (source == view_in_store_link_) {
@@ -151,6 +280,23 @@
   app_icon_->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(*bitmap));
 }
 
+extensions::LaunchType AppInfoSummaryTab::GetLaunchType() const {
+  return extensions::GetLaunchType(extensions::ExtensionPrefs::Get(profile_),
+                                   app_);
+}
+
+void AppInfoSummaryTab::SetLaunchType(extensions::LaunchType launch_type) {
+  DCHECK(CanSetLaunchType());
+  ExtensionService* service =
+      extensions::ExtensionSystem::Get(profile_)->extension_service();
+  extensions::SetLaunchType(service, app_->id(), launch_type);
+}
+
+bool AppInfoSummaryTab::CanSetLaunchType() {
+  // V2 apps don't have a launch type.
+  return !app_->is_platform_app();
+}
+
 bool AppInfoSummaryTab::CanShowAppInWebStore() const {
   return app_->from_webstore();
 }
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.h
index 80ec0c6..8e06858 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.h
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_tab.h
@@ -6,7 +6,10 @@
 #define CHROME_BROWSER_UI_VIEWS_APPS_APP_INFO_DIALOG_APP_INFO_SUMMARY_TAB_H_
 
 #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_tab.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "ui/base/models/combobox_model.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/views/controls/combobox/combobox_listener.h"
 #include "ui/views/controls/link_listener.h"
 
 class Profile;
@@ -18,13 +21,17 @@
 class Image;
 }
 namespace views {
+class Combobox;
 class ImageView;
 }
 
+class LaunchOptionsComboboxModel;
+
 // The Summary tab of the app info dialog, which provides basic information and
 // controls related to the app.
 class AppInfoSummaryTab : public AppInfoTab,
                           public views::LinkListener,
+                          public views::ComboboxListener,
                           public base::SupportsWeakPtr<AppInfoSummaryTab> {
  public:
   AppInfoSummaryTab(gfx::NativeWindow parent_window,
@@ -38,10 +45,20 @@
   virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
 
  private:
+  // Overridden from views::ComboboxListener:
+  virtual void OnPerformAction(views::Combobox* combobox) OVERRIDE;
+
   // Load the app icon asynchronously. For the response, check OnAppImageLoaded.
-  virtual void LoadAppImageAsync();
+  void LoadAppImageAsync();
   // Called when the app's icon is loaded.
-  virtual void OnAppImageLoaded(const gfx::Image& image);
+  void OnAppImageLoaded(const gfx::Image& image);
+
+  // Returns the launch type of the app (e.g. pinned tab, fullscreen, etc).
+  extensions::LaunchType GetLaunchType() const;
+  // Sets the launch type of the app to the given type. Must only be called if
+  // CanSetLaunchType() returns true.
+  void SetLaunchType(extensions::LaunchType);
+  bool CanSetLaunchType();
 
   // Opens the app in the web store. Only call if CanShowAppInWebStore() returns
   // true.
@@ -52,6 +69,9 @@
   views::ImageView* app_icon_;
   views::Link* view_in_store_link_;
 
+  scoped_ptr<LaunchOptionsComboboxModel> launch_options_combobox_model_;
+  views::Combobox* launch_options_combobox_;
+
   base::WeakPtrFactory<AppInfoSummaryTab> weak_ptr_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(AppInfoSummaryTab);
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
index a43320d..fa942ef 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.cc
@@ -210,13 +210,7 @@
 
   views::Widget::InitParams init_params(views::Widget::InitParams::TYPE_WINDOW);
   init_params.delegate = this;
-  init_params.remove_standard_frame = !ShouldUseNativeFrame();
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-  // On Linux, remove the standard frame. Instead, we will use CustomFrameView
-  // to draw a native-like frame.
-  // TODO(mgiuca): Remove this during fix for http://crbug.com/322256.
-  init_params.remove_standard_frame = true;
-#endif
+  init_params.remove_standard_frame = IsFrameless() || has_frame_color_;
   init_params.use_system_default_icon = true;
   // TODO(erg): Conceptually, these are toplevel windows, but we theoretically
   // could plumb context through to here in some cases.
@@ -337,10 +331,6 @@
 #endif
 }
 
-bool ChromeNativeAppWindowViews::ShouldUseNativeFrame() const {
-  return !IsFrameless() && !has_frame_color_;
-}
-
 void ChromeNativeAppWindowViews::InstallEasyResizeTargeterOnContainer() const {
   aura::Window* root_window = widget()->GetNativeWindow()->GetRootWindow();
   gfx::Insets inset(kResizeInsideBoundsSize, kResizeInsideBoundsSize,
@@ -366,9 +356,11 @@
     resize_area_corner_size = ash::kResizeAreaCornerSize;
   }
 #endif
-  apps::AppWindowFrameView* frame_view = new apps::AppWindowFrameView(this);
+  apps::AppWindowFrameView* frame_view = new apps::AppWindowFrameView();
   frame_view->Init(widget(),
+                   has_frame_color_,
                    frame_color_,
+                   GetDraggableRegion(),
                    resize_inside_bounds_size,
                    resize_outside_bounds_size,
                    resize_outside_scale_for_touch,
@@ -503,18 +495,26 @@
     if (!IsFrameless()) {
       ash::CustomFrameViewAsh* custom_frame_view =
           new ash::CustomFrameViewAsh(widget);
+#if defined(OS_CHROMEOS)
       // Non-frameless app windows can be put into immersive fullscreen.
+      // TODO(pkotwicz): Investigate if immersive fullscreen can be enabled for
+      // Windows Ash.
       immersive_fullscreen_controller_.reset(
           new ash::ImmersiveFullscreenController());
       custom_frame_view->InitImmersiveFullscreenControllerForView(
           immersive_fullscreen_controller_.get());
+#endif
       custom_frame_view->GetHeaderView()->set_context_menu_controller(this);
       return custom_frame_view;
     }
   }
 #endif
-  if (!ShouldUseNativeFrame())
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  return CreateAppWindowFrameView();
+#else
+  if (IsFrameless() || has_frame_color_)
     return CreateAppWindowFrameView();
+#endif
   return views::WidgetDelegateView::CreateNonClientFrameView(widget);
 }
 
@@ -672,7 +672,7 @@
       NULL));
 
 #if defined(OS_WIN)
-  if (!ShouldUseNativeFrame() &&
+  if ((IsFrameless() || has_frame_color_) &&
       chrome::GetHostDesktopTypeForNativeWindow(widget()->GetNativeWindow()) !=
           chrome::HOST_DESKTOP_TYPE_ASH) {
     InstallEasyResizeTargeterOnContainer();
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h
index 9350252..ceaca21 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views.h
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views.h
@@ -44,8 +44,6 @@
   FRIEND_TEST_ALL_PREFIXES(ShapedAppWindowTargeterTest,
                            ResizeInsetsWithinBounds);
 
-  bool ShouldUseNativeFrame() const;
-
   // Installs an EasyResizeWindowTargeter on the containing window, which
   // allows the window to be resized from within |kResizeInsideBoundsSize|
   // pixels inside the window bounds.
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.cc b/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.cc
index 586b873..44bc4d8 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.cc
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.cc
@@ -8,6 +8,7 @@
 #include "apps/app_window_registry.h"
 #include "ash/shell.h"
 #include "base/command_line.h"
+#include "base/file_util.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_worker_pool.h"
@@ -16,10 +17,12 @@
 #include "chrome/browser/jumplist_updater_win.h"
 #include "chrome/browser/metro_utils/metro_chrome_win.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/ui/web_applications/web_app_ui.h"
 #include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_win.h"
 #include "chrome/common/chrome_icon_resources_win.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/common/extension.h"
 #include "grit/generated_resources.h"
@@ -29,6 +32,42 @@
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
 #include "ui/views/win/hwnd_util.h"
 
+namespace {
+
+void CreateIconAndSetRelaunchDetails(
+    const base::FilePath& web_app_path,
+    const base::FilePath& icon_file,
+    const ShellIntegration::ShortcutInfo& shortcut_info,
+    const HWND hwnd) {
+  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
+
+  // Set the relaunch data so "Pin this program to taskbar" has the app's
+  // information.
+  CommandLine command_line = ShellIntegration::CommandLineArgsForLauncher(
+      shortcut_info.url,
+      shortcut_info.extension_id,
+      shortcut_info.profile_path);
+
+  base::FilePath chrome_exe;
+  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
+    NOTREACHED();
+    return;
+  }
+  command_line.SetProgram(chrome_exe);
+  ui::win::SetRelaunchDetailsForWindow(command_line.GetCommandLineString(),
+      shortcut_info.title, hwnd);
+
+  if (!base::PathExists(web_app_path) &&
+      !base::CreateDirectory(web_app_path)) {
+    return;
+  }
+
+  ui::win::SetAppIconForWindow(icon_file.value(), hwnd);
+  web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info.favicon);
+}
+
+}  // namespace
+
 ChromeNativeAppWindowViewsWin::ChromeNativeAppWindowViewsWin()
     : weak_ptr_factory_(this) {}
 
@@ -49,6 +88,27 @@
   }
 }
 
+void ChromeNativeAppWindowViewsWin::OnShortcutInfoLoaded(
+    const ShellIntegration::ShortcutInfo& shortcut_info) {
+  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+  HWND hwnd = GetNativeAppWindowHWND();
+
+  // Set window's icon to the one we're about to create/update in the web app
+  // path. The icon cache will refresh on icon creation.
+  base::FilePath web_app_path = web_app::GetWebAppDataDirectory(
+      shortcut_info.profile_path, shortcut_info.extension_id,
+      shortcut_info.url);
+  base::FilePath icon_file = web_app_path
+      .Append(web_app::internals::GetSanitizedFileName(shortcut_info.title))
+      .ReplaceExtension(FILE_PATH_LITERAL(".ico"));
+
+  content::BrowserThread::PostBlockingPoolTask(
+      FROM_HERE,
+      base::Bind(&CreateIconAndSetRelaunchDetails,
+                 web_app_path, icon_file, shortcut_info, hwnd));
+}
+
 HWND ChromeNativeAppWindowViewsWin::GetNativeAppWindowHWND() const {
   return views::HWNDForWidget(widget()->GetTopLevelWidget());
 }
@@ -86,11 +146,25 @@
 
 void ChromeNativeAppWindowViewsWin::InitializeDefaultWindow(
     const apps::AppWindow::CreateParams& create_params) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
-
   ChromeNativeAppWindowViews::InitializeDefaultWindow(create_params);
 
-  SetAppDetailsForWindow();
+  const extensions::Extension* extension = app_window()->extension();
+  std::string app_name =
+      web_app::GenerateApplicationNameFromExtensionId(extension->id());
+  base::string16 app_name_wide = base::UTF8ToWide(app_name);
+  HWND hwnd = GetNativeAppWindowHWND();
+  Profile* profile =
+      Profile::FromBrowserContext(app_window()->browser_context());
+  app_model_id_ =
+      ShellIntegration::GetAppModelIdForProfile(app_name_wide,
+                                                profile->GetPath());
+  ui::win::SetAppIdForWindow(app_model_id_, hwnd);
+
+  web_app::UpdateShortcutInfoAndIconForApp(
+      extension,
+      profile,
+      base::Bind(&ChromeNativeAppWindowViewsWin::OnShortcutInfoLoaded,
+                 weak_ptr_factory_.GetWeakPtr()));
 
   UpdateShelfMenu();
 }
@@ -145,46 +219,3 @@
 
   jumplist_updater.CommitUpdate();
 }
-
-void ChromeNativeAppWindowViewsWin::SetAppDetailsForWindow() {
-  // Set the Application Model ID so that windows are grouped correctly.
-  const extensions::Extension* app = app_window()->extension();
-  std::string app_name =
-      web_app::GenerateApplicationNameFromExtensionId(app->id());
-  base::string16 app_name_wide = base::UTF8ToWide(app_name);
-  HWND hwnd = GetNativeAppWindowHWND();
-  Profile* profile =
-      Profile::FromBrowserContext(app_window()->browser_context());
-  app_model_id_ =
-      ShellIntegration::GetAppModelIdForProfile(app_name_wide,
-                                                profile->GetPath());
-
-  // Set the relaunch data so "Pin this program to taskbar" has the app's
-  // information.
-  base::FilePath chrome_exe;
-  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
-    NOTREACHED();
-    return;
-  }
-
-  GURL url = extensions::AppLaunchInfo::GetLaunchWebURL(app);
-  CommandLine command_line = ShellIntegration::CommandLineArgsForLauncher(
-      url, app->id(), profile->GetPath());
-  command_line.SetProgram(chrome_exe);
-
-  // Set window's icon to the one in the web app path. This was created when the
-  // app was installed. The icon cache would have been refreshed at that time.
-  base::string16 title = base::UTF8ToUTF16(app->name());
-  base::FilePath web_app_path = web_app::GetWebAppDataDirectory(
-      profile->GetPath(), app->id(), url);
-  base::FilePath icon_file = web_app_path
-      .Append(web_app::internals::GetSanitizedFileName(title))
-      .ReplaceExtension(FILE_PATH_LITERAL(".ico"));
-
-  ui::win::SetAppDetailsForWindow(
-      app_model_id_,
-      icon_file.value(),
-      command_line.GetCommandLineString(),
-      title,
-      hwnd);
-}
diff --git a/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h b/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h
index 9841c96..d665eda 100644
--- a/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h
+++ b/chrome/browser/ui/views/apps/chrome_native_app_window_views_win.h
@@ -17,6 +17,9 @@
  private:
   void ActivateParentDesktopIfNecessary();
 
+  void OnShortcutInfoLoaded(
+      const ShellIntegration::ShortcutInfo& shortcut_info);
+
   HWND GetNativeAppWindowHWND() const;
 
   // Overridden from ChromeNativeAppWindowViews:
@@ -32,9 +35,6 @@
   // Overridden from apps::NativeAppWindow:
   virtual void UpdateShelfMenu() OVERRIDE;
 
-  // Calls ui::win::SetAppDetailsForWindow with the required strings.
-  void SetAppDetailsForWindow();
-
   base::WeakPtrFactory<ChromeNativeAppWindowViewsWin> weak_ptr_factory_;
 
   // The Windows Application User Model ID identifying the app.
diff --git a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
index 6c6d1c4..62c95e7 100644
--- a/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/views/ash/chrome_browser_main_extra_parts_ash.cc
@@ -19,7 +19,6 @@
 #include "ui/gfx/screen_type_delegate.h"
 #include "ui/keyboard/keyboard.h"
 #include "ui/keyboard/keyboard_util.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
 
 #if defined(OS_CHROMEOS)
 #include "chrome/browser/ui/views/select_file_dialog_extension.h"
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_view_tester_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_view_tester_views.cc
index 135b151..1508425 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_view_tester_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_view_tester_views.cc
@@ -6,7 +6,7 @@
 
 #include "base/logging.h"
 #include "chrome/browser/ui/views/autofill/autofill_dialog_views.h"
-#include "chrome/browser/ui/views/autofill/decorated_textfield.h"
+#include "chrome/browser/ui/views/autofill/expanding_textfield.h"
 #include "ui/base/models/combobox_model.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/textfield/textfield.h"
@@ -38,9 +38,9 @@
 
 base::string16 AutofillDialogViewTesterViews::GetTextContentsOfInput(
     ServerFieldType type) {
-  views::Textfield* textfield = view_->TextfieldForType(type);
+  ExpandingTextfield* textfield = view_->TextfieldForType(type);
   if (textfield)
-    return textfield->text();
+    return textfield->GetText();
 
   views::Combobox* combobox = view_->ComboboxForType(type);
   if (combobox)
@@ -53,7 +53,7 @@
 void AutofillDialogViewTesterViews::SetTextContentsOfInput(
     ServerFieldType type,
     const base::string16& contents) {
-  views::Textfield* textfield = view_->TextfieldForType(type);
+  ExpandingTextfield* textfield = view_->TextfieldForType(type);
   if (textfield) {
     textfield->SetText(contents);
     return;
@@ -72,8 +72,7 @@
 void AutofillDialogViewTesterViews::SetTextContentsOfSuggestionInput(
     DialogSection section,
     const base::string16& text) {
-  view_->GroupForSection(section)->suggested_info->decorated_textfield()->
-      SetText(text);
+  view_->GroupForSection(section)->suggested_info->textfield()->SetText(text);
 }
 
 void AutofillDialogViewTesterViews::ActivateInput(ServerFieldType type) {
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
index 5d549a0..62cbe07 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.cc
@@ -13,7 +13,7 @@
 #include "chrome/browser/ui/autofill/autofill_dialog_sign_in_delegate.h"
 #include "chrome/browser/ui/autofill/autofill_dialog_view_delegate.h"
 #include "chrome/browser/ui/autofill/loading_animation.h"
-#include "chrome/browser/ui/views/autofill/decorated_textfield.h"
+#include "chrome/browser/ui/views/autofill/expanding_textfield.h"
 #include "chrome/browser/ui/views/autofill/info_bubble.h"
 #include "chrome/browser/ui/views/autofill/tooltip_icon.h"
 #include "chrome/browser/ui/views/constrained_window_views.h"
@@ -147,12 +147,6 @@
   }
 }
 
-// Returns whether |view| is an input (e.g. textfield, combobox).
-bool IsInput(views::View* view) {
-  return view->GetClassName() == DecoratedTextfield::kViewClassName ||
-         view->GetClassName() == views::Combobox::kViewClassName;
-}
-
 void SelectComboboxValueOrSetToDefault(views::Combobox* combobox,
                                        const base::string16& value) {
   if (!combobox->SelectValue(value))
@@ -204,12 +198,12 @@
 
     // Textfield is right aligned.
     int end_x = bounds.width();
-    views::View* decorated = child_at(2);
-    if (decorated->visible()) {
-      const int preferred_width = decorated->GetPreferredSize().width();
-      decorated->SetBounds(bounds.width() - preferred_width, bounds.y(),
+    views::View* textfield = child_at(2);
+    if (textfield->visible()) {
+      const int preferred_width = textfield->GetPreferredSize().width();
+      textfield->SetBounds(bounds.width() - preferred_width, bounds.y(),
                            preferred_width, bounds.height());
-      end_x = decorated->bounds().x() - kAroundTextPadding;
+      end_x = textfield->bounds().x() - kAroundTextPadding;
     }
 
     // Label takes up all the space in between.
@@ -454,6 +448,15 @@
   DISALLOW_COPY_AND_ASSIGN(LoadingAnimationView);
 };
 
+// Gets either the Combobox or ExpandingTextfield that is an ancestor (including
+// self) of |view|.
+views::View* GetAncestralInputView(views::View* view) {
+  if (view->GetClassName() == views::Combobox::kViewClassName)
+    return view;
+
+  return view->GetAncestorWithClassName(ExpandingTextfield::kViewClassName);
+}
+
 }  // namespace
 
 // AutofillDialogViews::AccountChooser -----------------------------------------
@@ -920,7 +923,7 @@
 
   // Special case for (CVC) inputs in the suggestion view.
   if (forward_mouse_events_ &&
-      handler->GetAncestorWithClassName(DecoratedTextfield::kViewClassName)) {
+      handler->GetAncestorWithClassName(ExpandingTextfield::kViewClassName)) {
     return handler;
   }
 
@@ -1025,9 +1028,10 @@
     : label_(new views::Label()),
       label_line_2_(new views::Label()),
       icon_(new views::ImageView()),
-      decorated_(
-          new DecoratedTextfield(base::string16(),
+      textfield_(
+          new ExpandingTextfield(base::string16(),
                                  base::string16(),
+                                 false,
                                  autofill_dialog)) {
   // TODO(estade): Make this the correct color.
   SetBorder(views::Border::CreateSolidSidedBorder(1, 0, 0, 0, SK_ColorLTGRAY));
@@ -1041,9 +1045,9 @@
   label_container->AddChildView(label_);
 
   // TODO(estade): get the sizing and spacing right on this textfield.
-  decorated_->SetVisible(false);
-  decorated_->set_default_width_in_chars(15);
-  label_container->AddChildView(decorated_);
+  textfield_->SetVisible(false);
+  textfield_->SetDefaultWidthInCharacters(15);
+  label_container->AddChildView(textfield_);
 
   label_line_2_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   label_line_2_->SetVisible(false);
@@ -1143,9 +1147,9 @@
 void AutofillDialogViews::SuggestionView::SetTextfield(
     const base::string16& placeholder_text,
     const gfx::Image& icon) {
-  decorated_->set_placeholder_text(placeholder_text);
-  decorated_->SetIcon(icon);
-  decorated_->SetVisible(!placeholder_text.empty());
+  textfield_->SetPlaceholderText(placeholder_text);
+  textfield_->SetIcon(icon);
+  textfield_->SetVisible(!placeholder_text.empty());
 }
 
 void AutofillDialogViews::SuggestionView::UpdateLabelText() {
@@ -1359,7 +1363,7 @@
   DetailsGroup* group = GroupForSection(section);
   for (TextfieldMap::const_iterator it = group->textfields.begin();
        it != group->textfields.end(); ++it) {
-    output->insert(std::make_pair(it->first, it->second->text()));
+    output->insert(std::make_pair(it->first, it->second->GetText()));
   }
   for (ComboboxMap::const_iterator it = group->comboboxes.begin();
        it != group->comboboxes.end(); ++it) {
@@ -1370,7 +1374,7 @@
 
 base::string16 AutofillDialogViews::GetCvc() {
   return GroupForSection(GetCreditCardSection())->suggested_info->
-      decorated_textfield()->text();
+      textfield()->GetText();
 }
 
 bool AutofillDialogViews::HitTestInput(ServerFieldType type,
@@ -1573,13 +1577,14 @@
   for (views::View* next = scrollable_area_;
        next;
        next = manager->GetNextFocusableView(next, window_, false, true)) {
-    if (!IsInput(next))
+    views::View* input_view = GetAncestralInputView(next);
+    if (!input_view)
       continue;
 
     // If there are no invalid inputs, return the first input found. Otherwise,
     // return the first invalid input found.
     if (validity_map_.empty() ||
-        validity_map_.find(next) != validity_map_.end()) {
+        validity_map_.find(input_view) != validity_map_.end()) {
       return next;
     }
   }
@@ -1640,6 +1645,11 @@
   InputEditedOrActivated(TypeForTextfield(sender),
                          sender->GetBoundsInScreen(),
                          true);
+
+  const ExpandingTextfield* expanding = static_cast<ExpandingTextfield*>(
+      sender->GetAncestorWithClassName(ExpandingTextfield::kViewClassName));
+  if (expanding && expanding->needs_layout())
+    ContentsPreferredSizeChanged();
 }
 
 bool AutofillDialogViews::HandleKeyEvent(views::Textfield* sender,
@@ -1932,8 +1942,9 @@
       SelectComboboxValueOrSetToDefault(combobox, input.initial_value);
       view_to_add.reset(combobox);
     } else {
-      DecoratedTextfield* field = new DecoratedTextfield(input.initial_value,
+      ExpandingTextfield* field = new ExpandingTextfield(input.initial_value,
                                                          input.placeholder_text,
+                                                         input.IsMultiline(),
                                                          this);
       textfields->insert(std::make_pair(input.type, field));
       view_to_add.reset(field);
@@ -2004,8 +2015,8 @@
     views::View* focused = GetFocusManager()->GetFocusedView();
     if (focused && group->container->Contains(focused)) {
       // Remember which view was focused before the inputs are clobbered.
-      if (focused->GetClassName() == DecoratedTextfield::kViewClassName)
-        type = TypeForTextfield(static_cast<DecoratedTextfield*>(focused));
+      if (focused->GetClassName() == ExpandingTextfield::kViewClassName)
+        type = TypeForTextfield(focused);
       else if (focused->GetClassName() == views::Combobox::kViewClassName)
         type = TypeForCombobox(static_cast<views::Combobox*>(focused));
     }
@@ -2029,9 +2040,9 @@
 
       TextfieldMap::iterator text_mapping = group->textfields.find(input.type);
       if (text_mapping != group->textfields.end()) {
-        DecoratedTextfield* decorated = text_mapping->second;
-        if (decorated->text().empty())
-          decorated->SetText(input.initial_value);
+        ExpandingTextfield* textfield = text_mapping->second;
+        if (textfield->GetText().empty())
+          textfield->SetText(input.initial_value);
       }
 
       ComboboxMap::iterator combo_mapping = group->comboboxes.find(input.type);
@@ -2091,7 +2102,9 @@
   } else {
     validity_map_.erase(input);
 
-    if (error_bubble_ && error_bubble_->anchor() == input) {
+    if (error_bubble_ &&
+        error_bubble_->anchor()->GetAncestorWithClassName(
+            input->GetClassName()) == input) {
       validity_map_.erase(input);
       HideErrorBubble();
     }
@@ -2107,10 +2120,16 @@
     return;
   }
 
+  if (view->GetClassName() == DecoratedTextfield::kViewClassName &&
+      !static_cast<DecoratedTextfield*>(view)->invalid()) {
+    return;
+  }
+
+  views::View* input_view = GetAncestralInputView(view);
   std::map<views::View*, base::string16>::iterator error_message =
-      validity_map_.find(view);
+      validity_map_.find(input_view);
   if (error_message != validity_map_.end()) {
-    view->ScrollRectToVisible(view->GetLocalBounds());
+    input_view->ScrollRectToVisible(input_view->GetLocalBounds());
 
     if (!error_bubble_ || error_bubble_->anchor() != view) {
       HideErrorBubble();
@@ -2161,8 +2180,7 @@
       const ValidityMessage& message =
           messages.GetMessageOrDefault(CREDIT_CARD_VERIFICATION_CODE);
       if (overwrite_unsure || message.sure) {
-        SetValidityForInput(group->suggested_info->decorated_textfield(),
-                            message.text);
+        SetValidityForInput(group->suggested_info->textfield(), message.text);
       }
     }
   }
@@ -2180,7 +2198,7 @@
       if (!iter->second->editable())
         continue;
 
-      detail_outputs[iter->first] = iter->second->text();
+      detail_outputs[iter->first] = iter->second->GetText();
     }
     for (ComboboxMap::const_iterator iter = group.comboboxes.begin();
          iter != group.comboboxes.end(); ++iter) {
@@ -2193,10 +2211,9 @@
       detail_outputs[iter->first] = item;
     }
   } else if (group.section == GetCreditCardSection()) {
-    DecoratedTextfield* decorated_cvc =
-        group.suggested_info->decorated_textfield();
-    if (decorated_cvc->visible())
-      detail_outputs[CREDIT_CARD_VERIFICATION_CODE] = decorated_cvc->text();
+    ExpandingTextfield* cvc = group.suggested_info->textfield();
+    if (cvc->visible())
+      detail_outputs[CREDIT_CARD_VERIFICATION_CODE] = cvc->GetText();
   }
 
   ValidityMessages validity = delegate_->InputsAreValid(group.section,
@@ -2229,19 +2246,19 @@
                                                  bool was_edit) {
   DCHECK_NE(UNKNOWN_TYPE, type);
 
-  DecoratedTextfield* decorated = TextfieldForType(type);
+  ExpandingTextfield* textfield = TextfieldForType(type);
   views::Combobox* combobox = ComboboxForType(type);
 
   // Both views may be NULL if the event comes from an inactive section, which
   // may occur when using an IME.
-  if (!combobox && !decorated)
+  if (!combobox && !textfield)
     return;
 
-  DCHECK_NE(!!combobox, !!decorated);
-  DetailsGroup* group = decorated ? GroupForView(decorated) :
+  DCHECK_NE(!!combobox, !!textfield);
+  DetailsGroup* group = textfield ? GroupForView(textfield) :
                                     GroupForView(combobox);
-  base::string16 text = decorated ?
-      decorated->text() :
+  base::string16 text = textfield ?
+      textfield->GetText() :
       combobox->model()->GetItemAt(combobox->selected_index());
   DCHECK(group);
 
@@ -2257,15 +2274,15 @@
   // so flagging them as invalid prematurely is not helpful. However,
   // correcting a minor mistake (i.e. a wrong CC digit) should immediately
   // result in validation - positive user feedback.
-  if (decorated && decorated->invalid() && was_edit) {
+  if (textfield && textfield->invalid() && was_edit) {
     SetValidityForInput(
-        decorated,
+        textfield,
         delegate_->InputValidityMessage(
-            group->section, type, decorated->text()));
+            group->section, type, textfield->GetText()));
 
     // If the field transitioned from invalid to valid, re-validate the group,
     // since inter-field checks become meaningful with valid fields.
-    if (!decorated->invalid())
+    if (!textfield->invalid())
       ValidateGroup(*group, VALIDATE_EDIT);
   }
 
@@ -2311,20 +2328,20 @@
     views::View* view) {
   DCHECK(view);
 
+  views::View* input_view = GetAncestralInputView(view);
+  if (!input_view)
+    return NULL;
+
   for (DetailGroupMap::iterator iter = detail_groups_.begin();
        iter != detail_groups_.end(); ++iter) {
     DetailsGroup* group = &iter->second;
-    if (view->parent() == group->manual_input)
+    if (input_view->parent() == group->manual_input)
       return group;
 
-    views::View* decorated =
-        view->GetAncestorWithClassName(DecoratedTextfield::kViewClassName);
-
     // Textfields need to check a second case, since they can be suggested
     // inputs instead of directly editable inputs. Those are accessed via
     // |suggested_info|.
-    if (decorated &&
-        decorated == group->suggested_info->decorated_textfield()) {
+    if (input_view == group->suggested_info->textfield()) {
       return group;
     }
   }
@@ -2342,12 +2359,12 @@
   }
 }
 
-DecoratedTextfield* AutofillDialogViews::TextfieldForType(
+ExpandingTextfield* AutofillDialogViews::TextfieldForType(
     ServerFieldType type) {
   if (type == CREDIT_CARD_VERIFICATION_CODE) {
     DetailsGroup* group = GroupForSection(GetCreditCardSection());
     if (!group->manual_input->visible())
-      return group->suggested_info->decorated_textfield();
+      return group->suggested_info->textfield();
   }
 
   for (DetailGroupMap::iterator iter = detail_groups_.begin();
@@ -2365,9 +2382,12 @@
 }
 
 ServerFieldType AutofillDialogViews::TypeForTextfield(
-    const views::Textfield* textfield) {
+    const views::View* textfield) {
+  const views::View* expanding =
+      textfield->GetAncestorWithClassName(ExpandingTextfield::kViewClassName);
+
   DetailsGroup* cc_group = GroupForSection(GetCreditCardSection());
-  if (textfield == cc_group->suggested_info->decorated_textfield())
+  if (expanding == cc_group->suggested_info->textfield())
     return CREDIT_CARD_VERIFICATION_CODE;
 
   for (DetailGroupMap::const_iterator it = detail_groups_.begin();
@@ -2377,7 +2397,7 @@
 
     for (TextfieldMap::const_iterator text_it = it->second.textfields.begin();
          text_it != it->second.textfields.end(); ++text_it) {
-      if (textfield == text_it->second)
+      if (expanding == text_it->second)
         return text_it->first;
     }
   }
@@ -2434,7 +2454,7 @@
        ++textfield_it) {
     ServerFieldType field_type = textfield_it->first;
     FieldIconMap::const_iterator field_icon_it = field_icons.find(field_type);
-    DecoratedTextfield* textfield = textfield_it->second;
+    ExpandingTextfield* textfield = textfield_it->second;
     if (field_icon_it != field_icons.end())
       textfield->SetIcon(field_icon_it->second);
     else
@@ -2454,8 +2474,8 @@
 
     TextfieldMap::iterator text_mapping = group->textfields.find(input.type);
     if (text_mapping != group->textfields.end()) {
-      DecoratedTextfield* decorated = text_mapping->second;
-      decorated->SetEditable(editable);
+      ExpandingTextfield* textfield= text_mapping->second;
+      textfield->SetEditable(editable);
       continue;
     }
 
diff --git a/chrome/browser/ui/views/autofill/autofill_dialog_views.h b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
index 0c6270c..5b0d8e3 100644
--- a/chrome/browser/ui/views/autofill/autofill_dialog_views.h
+++ b/chrome/browser/ui/views/autofill/autofill_dialog_views.h
@@ -54,7 +54,7 @@
 namespace autofill {
 
 class AutofillDialogSignInDelegate;
-class DecoratedTextfield;
+class ExpandingTextfield;
 class InfoBubble;
 
 // Views toolkit implementation of the Autofill dialog that handles the
@@ -286,7 +286,7 @@
     DISALLOW_COPY_AND_ASSIGN(NotificationArea);
   };
 
-  typedef std::map<ServerFieldType, DecoratedTextfield*> TextfieldMap;
+  typedef std::map<ServerFieldType, ExpandingTextfield*> TextfieldMap;
   typedef std::map<ServerFieldType, views::Combobox*> ComboboxMap;
 
   // A view that packs a label on the left and some related controls
@@ -389,7 +389,7 @@
     virtual int GetHeightForWidth(int width) OVERRIDE;
     virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
 
-    DecoratedTextfield* decorated_textfield() { return decorated_; }
+    ExpandingTextfield* textfield() { return textfield_; }
 
    private:
     // Returns whether there's room to display |state_.vertically_compact_text|
@@ -428,7 +428,7 @@
     // The icon that comes just before |label_|.
     views::ImageView* icon_;
     // The input set by ShowTextfield.
-    DecoratedTextfield* decorated_;
+    ExpandingTextfield* textfield_;
     // An "Edit" link that flips to editable inputs rather than suggestion text.
     views::Link* edit_link_;
 
@@ -522,7 +522,7 @@
   void FocusInitialView();
 
   // Sets the visual state for an input to be either valid or invalid. This
-  // should work on Comboboxes or DecoratedTextfields. If |message| is empty,
+  // should work on Comboboxes or ExpandingTextfields. If |message| is empty,
   // the input is valid.
   template<class T>
   void SetValidityForInput(T* input, const base::string16& message);
@@ -564,10 +564,10 @@
   void DoContentsPreferredSizeChanged();
 
   // Gets the textfield view that is shown for the given |type| or NULL.
-  DecoratedTextfield* TextfieldForType(ServerFieldType type);
+  ExpandingTextfield* TextfieldForType(ServerFieldType type);
 
   // Returns the associated ServerFieldType for |textfield|.
-  ServerFieldType TypeForTextfield(const views::Textfield* textfield);
+  ServerFieldType TypeForTextfield(const views::View* textfield);
 
   // Gets the combobox view that is shown for the given |type|, or NULL.
   views::Combobox* ComboboxForType(ServerFieldType type);
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
index 6d98744..bff5e7a 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/ui/views/autofill/autofill_popup_base_view.h"
 
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop.h"
 #include "chrome/browser/ui/autofill/popup_constants.h"
 #include "ui/gfx/point.h"
 #include "ui/gfx/screen.h"
@@ -34,7 +37,9 @@
     AutofillPopupViewDelegate* delegate,
     views::Widget* observing_widget)
     : delegate_(delegate),
-      observing_widget_(observing_widget) {}
+      observing_widget_(observing_widget),
+      weak_ptr_factory_(this) {}
+
 AutofillPopupBaseView::~AutofillPopupBaseView() {
   if (delegate_) {
     delegate_->ViewDestroyed();
@@ -47,6 +52,16 @@
   if (!GetWidget()) {
     observing_widget_->AddObserver(this);
 
+    views::FocusManager* focus_manager = observing_widget_->GetFocusManager();
+    focus_manager->RegisterAccelerator(
+        ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE),
+        ui::AcceleratorManager::kNormalPriority,
+        this);
+    focus_manager->RegisterAccelerator(
+        ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE),
+        ui::AcceleratorManager::kNormalPriority,
+        this);
+
     // The widget is destroyed by the corresponding NativeWidget, so we use
     // a weak pointer to hold the reference and don't have to worry about
     // deletion.
@@ -91,6 +106,7 @@
 }
 
 void AutofillPopupBaseView::RemoveObserver() {
+  observing_widget_->GetFocusManager()->UnregisterAccelerators(this);
   observing_widget_->RemoveObserver(this);
 }
 
@@ -124,7 +140,13 @@
 }
 
 void AutofillPopupBaseView::OnMouseExited(const ui::MouseEvent& event) {
-  ClearSelection();
+  // Pressing return causes the cursor to hide, which will generate an
+  // OnMouseExited event. Pressing return should activate the current selection
+  // via AcceleratorPressed, so we need to let that run first.
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&AutofillPopupBaseView::ClearSelection,
+                 weak_ptr_factory_.GetWeakPtr()));
 }
 
 void AutofillPopupBaseView::OnMouseMoved(const ui::MouseEvent& event) {
@@ -200,14 +222,33 @@
   event->SetHandled();
 }
 
+bool AutofillPopupBaseView::AcceleratorPressed(
+    const ui::Accelerator& accelerator) {
+  DCHECK_EQ(accelerator.modifiers(), ui::EF_NONE);
+
+  if (accelerator.key_code() == ui::VKEY_ESCAPE) {
+    HideController();
+    return true;
+  }
+
+  if (accelerator.key_code() == ui::VKEY_RETURN)
+    return delegate_->AcceptSelectedLine();
+
+  NOTREACHED();
+  return false;
+}
+
 void AutofillPopupBaseView::SetSelection(const gfx::Point& point) {
   if (delegate_)
     delegate_->SetSelectionAtPoint(point);
 }
 
 void AutofillPopupBaseView::AcceptSelection(const gfx::Point& point) {
-  if (delegate_)
-    delegate_->AcceptSelectionAtPoint(point);
+  if (!delegate_)
+    return;
+
+  delegate_->SetSelectionAtPoint(point);
+  delegate_->AcceptSelectedLine();
 }
 
 void AutofillPopupBaseView::ClearSelection() {
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view.h b/chrome/browser/ui/views/autofill/autofill_popup_base_view.h
index 4a6309d..a64e002 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_base_view.h
+++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_POPUP_BASE_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_AUTOFILL_AUTOFILL_POPUP_BASE_VIEW_H_
 
+#include "base/memory/weak_ptr.h"
 #include "chrome/browser/ui/autofill/autofill_popup_view_delegate.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/widget/widget_observer.h"
@@ -55,6 +56,7 @@
   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
+  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
 
   // views::WidgetObserver implementation.
   virtual void OnWidgetBoundsChanged(views::Widget* widget,
@@ -86,6 +88,8 @@
   // The widget that |this| observes. Weak reference.
   views::Widget* observing_widget_;
 
+  base::WeakPtrFactory<AutofillPopupBaseView> weak_ptr_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(AutofillPopupBaseView);
 };
 
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc b/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc
index d15571b..fa1b6a0 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc
@@ -26,7 +26,7 @@
   MOCK_METHOD0(Hide, void());
   MOCK_METHOD0(ViewDestroyed, void());
   MOCK_METHOD1(SetSelectionAtPoint, void(const gfx::Point&));
-  MOCK_METHOD1(AcceptSelectionAtPoint, void(const gfx::Point&));
+  MOCK_METHOD0(AcceptSelectedLine, bool());
   MOCK_METHOD0(SelectionCleared, void());
   // TODO(jdduke): Mock this method upon resolution of crbug.com/352463.
   bool ShouldRepostEvent(const ui::MouseEvent&) { return false; }
@@ -48,7 +48,7 @@
         .WillRepeatedly(Return(window));
     EXPECT_CALL(mock_delegate_, ShouldHideOnOutsideClick())
         .WillRepeatedly(Return(false));
-    EXPECT_CALL(mock_delegate_, ViewDestroyed()).Times(1);
+    EXPECT_CALL(mock_delegate_, ViewDestroyed());
 
     view_ = new AutofillPopupBaseView(
         &mock_delegate_,
@@ -88,9 +88,9 @@
   // Expectations.
   {
     testing::InSequence dummy;
-    EXPECT_CALL(mock_delegate_, SetSelectionAtPoint(point)).Times(1);
-    EXPECT_CALL(mock_delegate_, AcceptSelectionAtPoint(point)).Times(1);
-    EXPECT_CALL(mock_delegate_, SelectionCleared()).Times(1);
+    EXPECT_CALL(mock_delegate_, SetSelectionAtPoint(point)).Times(2);
+    EXPECT_CALL(mock_delegate_, AcceptSelectedLine());
+    EXPECT_CALL(mock_delegate_, SelectionCleared());
   }
 
   // Tap down will select an element.
diff --git a/chrome/browser/ui/views/autofill/expanding_textfield.cc b/chrome/browser/ui/views/autofill/expanding_textfield.cc
new file mode 100644
index 0000000..147742b
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/expanding_textfield.cc
@@ -0,0 +1,146 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/autofill/expanding_textfield.h"
+
+#include "base/bind.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ui/views/autofill/decorated_textfield.h"
+#include "ui/views/layout/box_layout.h"
+
+namespace autofill {
+
+namespace {
+
+// The vertical padding between textfields.
+const int kManualInputRowPadding = 10;
+
+}  // namespace
+
+// static
+const char ExpandingTextfield::kViewClassName[] = "autofill/ExpandingTextfield";
+
+ExpandingTextfield::ExpandingTextfield(
+    const base::string16& default_value,
+    const base::string16& placeholder,
+    bool multiline,
+    views::TextfieldController* controller)
+    : controller_(controller) {
+  textfields_.push_back(
+      new DecoratedTextfield(base::string16(), placeholder, this));
+  if (multiline) {
+    textfields_.push_back(
+        new DecoratedTextfield(base::string16(), placeholder, this));
+  }
+  SetText(default_value);
+
+  for (std::list<DecoratedTextfield*>::iterator iter = textfields_.begin();
+       iter != textfields_.end(); ++iter) {
+    AddChildView(*iter);
+  }
+
+  SetLayoutManager(new views::BoxLayout(views::BoxLayout::kVertical, 0, 0,
+                                        kManualInputRowPadding));
+}
+
+ExpandingTextfield::~ExpandingTextfield() {}
+
+void ExpandingTextfield::SetText(const base::string16& text) {
+  textfields_.front()->SetText(text);
+  std::vector<base::string16> strings;
+  base::SplitStringDontTrim(text, '\n', &strings);
+
+  size_t i = 0;
+  for (std::list<DecoratedTextfield*>::iterator iter = textfields_.begin();
+       iter != textfields_.end(); ++iter) {
+    (*iter)->SetText(i < strings.size() ? strings[i++] : base::string16());
+  }
+
+  for (; i < strings.size(); ++i) {
+    textfields_.push_back(new DecoratedTextfield(
+        strings[i],
+        textfields_.front()->GetPlaceholderText(),
+        this));
+    AddChildView(textfields_.back());
+    PreferredSizeChanged();
+  }
+}
+
+base::string16 ExpandingTextfield::GetText() {
+  base::string16 text = textfields_.front()->text();
+  std::list<DecoratedTextfield*>::const_iterator iter = ++textfields_.begin();
+  while (iter != textfields_.end()) {
+    text += base::ASCIIToUTF16("\n") + (*iter++)->text();
+  }
+  base::TrimWhitespace(text, base::TRIM_ALL, &text);
+  return text;
+}
+
+void ExpandingTextfield::SetInvalid(bool invalid) {
+  textfields_.front()->SetInvalid(invalid);
+}
+
+void ExpandingTextfield::SetDefaultWidthInCharacters(int chars) {
+  ForEachTextfield(&DecoratedTextfield::set_default_width_in_chars, chars);
+}
+
+void ExpandingTextfield::SetPlaceholderText(const base::string16& placeholder) {
+  ForEachTextfield<views::Textfield, const base::string16&>(
+      &DecoratedTextfield::set_placeholder_text, placeholder);
+}
+
+void ExpandingTextfield::SetIcon(const gfx::Image& icon) {
+  textfields_.front()->SetIcon(icon);
+}
+
+void ExpandingTextfield::SetTooltipIcon(const base::string16& text) {
+  textfields_.front()->SetTooltipIcon(text);
+}
+
+void ExpandingTextfield::SetEditable(bool editable) {
+  ForEachTextfield(&DecoratedTextfield::SetEditable, editable);
+}
+
+const char* ExpandingTextfield::GetClassName() const {
+  return kViewClassName;
+}
+
+void ExpandingTextfield::ContentsChanged(views::Textfield* sender,
+                                         const base::string16& new_contents) {
+  if (textfields_.size() > 1 && sender == textfields_.back() &&
+      !new_contents.empty()) {
+    textfields_.push_back(
+        new DecoratedTextfield(base::string16(),
+                               sender->GetPlaceholderText(),
+                               this));
+    AddChildView(textfields_.back());
+    PreferredSizeChanged();
+  }
+
+  controller_->ContentsChanged(sender, new_contents);
+}
+
+bool ExpandingTextfield::HandleKeyEvent(views::Textfield* sender,
+                                        const ui::KeyEvent& key_event) {
+  return controller_->HandleKeyEvent(sender, key_event);
+}
+
+bool ExpandingTextfield::HandleMouseEvent(views::Textfield* sender,
+                                          const ui::MouseEvent& mouse_event) {
+  return controller_->HandleMouseEvent(sender, mouse_event);
+}
+
+template <typename BaseType, typename Param>
+void ExpandingTextfield::ForEachTextfield(
+    void (BaseType::* f)(Param), Param p) const {
+  for (std::list<DecoratedTextfield*>::const_iterator iter =
+           textfields_.begin();
+       iter != textfields_.end(); ++iter) {
+    base::Bind(f, base::Unretained(*iter), p).Run();
+  }
+}
+
+}  // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/expanding_textfield.h b/chrome/browser/ui/views/autofill/expanding_textfield.h
new file mode 100644
index 0000000..c34bf76
--- /dev/null
+++ b/chrome/browser/ui/views/autofill/expanding_textfield.h
@@ -0,0 +1,88 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_EXPANDING_TEXTFIELD_H_
+#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_EXPANDING_TEXTFIELD_H_
+
+#include <list>
+
+#include "base/strings/string16.h"
+#include "chrome/browser/ui/views/autofill/decorated_textfield.h"
+#include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/view.h"
+
+namespace gfx {
+class Image;
+}
+
+namespace autofill {
+
+// A view that houses a stack of textfields. The stack grows as needed.
+class ExpandingTextfield : public views::View,
+                           public views::TextfieldController {
+ public:
+  static const char kViewClassName[];
+
+  // When |multiline| is false, the view acts pretty much like a normal
+  // DecoratedTextfield.
+  ExpandingTextfield(const base::string16& default_value,
+                     const base::string16& placeholder,
+                     bool multiline,
+                     views::TextfieldController* controller);
+  virtual ~ExpandingTextfield();
+
+  // Sets the contents of the textfields. Textfield n is set to the nth line
+  // of |text|, as separated by line returns.
+  void SetText(const base::string16& text);
+  // Concatenates text contents of all textfields (with line returns as the
+  // joining character) and returns it.
+  base::string16 GetText();
+
+  // Sets whether to indicate the first textfield has invalid content. Latter
+  // textfields are always valid.
+  void SetInvalid(bool invalid);
+  bool invalid() {
+    return textfields_.front()->invalid();
+  }
+
+  // Like validity, this only cares about the first textfield.
+  void SetEditable(bool editable);
+  bool editable() {
+    return textfields_.front()->editable();
+  }
+
+  // DecoratedTextfield pass-throughs.
+  void SetDefaultWidthInCharacters(int chars);
+  void SetPlaceholderText(const base::string16& placeholder);
+  void SetIcon(const gfx::Image& icon);
+  void SetTooltipIcon(const base::string16& text);
+
+  // View implementation.
+  virtual const char* GetClassName() const OVERRIDE;
+  using views::View::needs_layout;
+
+  // TextfieldController implementation.
+  virtual void ContentsChanged(views::Textfield* sender,
+                               const base::string16& new_contents) OVERRIDE;
+  virtual bool HandleKeyEvent(views::Textfield* sender,
+                              const ui::KeyEvent& key_event) OVERRIDE;
+  virtual bool HandleMouseEvent(views::Textfield* sender,
+                                const ui::MouseEvent& mouse_event) OVERRIDE;
+
+ private:
+  // Calls a given function on every textfield.
+  template <typename BaseType, typename Param>
+  void ForEachTextfield(void (BaseType::* f)(Param), Param p) const;
+
+  // The list of textfields. Owned as child views.
+  std::list<DecoratedTextfield*> textfields_;
+
+  TextfieldController* controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExpandingTextfield);
+};
+
+}  // namespace autofill
+
+#endif  // CHROME_BROWSER_UI_VIEWS_AUTOFILL_EXPANDING_TEXTFIELD_H_
diff --git a/chrome/browser/ui/views/avatar_label.cc b/chrome/browser/ui/views/avatar_label.cc
index 65ae8fc..6f77339 100644
--- a/chrome/browser/ui/views/avatar_label.cc
+++ b/chrome/browser/ui/views/avatar_label.cc
@@ -104,7 +104,8 @@
   if (!LabelButton::OnMousePressed(event))
     return false;
 
-  browser_view_->ShowAvatarBubbleFromAvatarButton();
+  browser_view_->ShowAvatarBubbleFromAvatarButton(
+      BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT);
   return true;
 }
 
diff --git a/chrome/browser/ui/views/avatar_menu_button.cc b/chrome/browser/ui/views/avatar_menu_button.cc
index e9942f5..c4268bb 100644
--- a/chrome/browser/ui/views/avatar_menu_button.cc
+++ b/chrome/browser/ui/views/avatar_menu_button.cc
@@ -107,6 +107,7 @@
       views::BubbleBorder::TOP_RIGHT : views::BubbleBorder::TOP_LEFT;
   if (switches::IsNewProfileManagement()) {
     ProfileChooserView::ShowBubble(
+        ProfileChooserView::BUBBLE_VIEW_MODE_PROFILE_CHOOSER,
         this, arrow, views::BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR, bounds,
         browser_);
   } else {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
index ebaf328..aa4a15b 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/bookmarks/bookmark_model.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/browser_shutdown.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/defaults.h"
 #include "chrome/browser/extensions/extension_service.h"
@@ -995,12 +994,7 @@
 }
 
 void BookmarkBarView::BookmarkModelBeingDeleted(BookmarkModel* model) {
-  // In normal shutdown The bookmark model should never be deleted before us.
-  // When X exits suddenly though, it can happen, This code exists
-  // to check for regressions in shutdown code and not crash.
-  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
-    NOTREACHED();
-
+  NOTREACHED();
   // Do minimal cleanup, presumably we'll be deleted shortly.
   model_->RemoveObserver(this);
   model_ = NULL;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view_unittest.cc
index d119d4d..7263bcd 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bubble_view_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bubble_view_unittest.cc
@@ -44,6 +44,14 @@
     BrowserWithTestWindowTest::TearDown();
   }
 
+  // BrowserWithTestWindowTest:
+  virtual TestingProfile* CreateProfile() OVERRIDE {
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              FakeSigninManagerBase::Build);
+    return builder.Build().release();
+  }
+
  protected:
   // Creates a bookmark bubble view.
   void CreateBubbleView() {
@@ -56,38 +64,24 @@
                                          true));
   }
 
-  void CreateSigninManager(const std::string& username) {
-    SigninManagerBase* signin_manager =
-        static_cast<SigninManagerBase*>(
-            SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-                profile(),
-                &BookmarkBubbleViewTest::BuildFakeSignInManager));
-    signin_manager->Initialize(profile(), NULL);
-
-    if (!username.empty()) {
-      ASSERT_TRUE(signin_manager);
-      signin_manager->SetAuthenticatedUsername(username);
-    }
+  void SetUpSigninManager(const std::string& username) {
+    if (username.empty())
+      return;
+    SigninManagerBase* signin_manager = static_cast<SigninManagerBase*>(
+        SigninManagerFactory::GetForProfile(profile()));
+    ASSERT_TRUE(signin_manager);
+    signin_manager->SetAuthenticatedUsername(username);
   }
 
   scoped_ptr<BookmarkBubbleView> bubble_;
 
  private:
-  static KeyedService* BuildFakeSignInManager(
-      content::BrowserContext* profile) {
-#if defined(OS_CHROMEOS)
-    return new FakeSigninManagerBase();
-#else  // !defined(OS_CHROMEOS)
-    return new FakeSigninManager(static_cast<Profile*>(profile));
-#endif
-  }
-
   DISALLOW_COPY_AND_ASSIGN(BookmarkBubbleViewTest);
 };
 
 // Verifies that the sync promo is not displayed for a signed in user.
 TEST_F(BookmarkBubbleViewTest, SyncPromoSignedIn) {
-  CreateSigninManager("fake_username");
+  SetUpSigninManager("fake_username");
   CreateBubbleView();
   bubble_->Init();
   EXPECT_FALSE(bubble_->sync_promo_view_);
diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc
index fca0654..d2d90a7 100644
--- a/chrome/browser/ui/views/create_application_shortcut_view.cc
+++ b/chrome/browser/ui/views/create_application_shortcut_view.cc
@@ -533,7 +533,7 @@
 
   // Get shortcut information and icon now; they are needed for our UI.
   web_app::UpdateShortcutInfoAndIconForApp(
-      *app, profile,
+      app, profile,
       base::Bind(&CreateChromeApplicationShortcutView::OnShortcutInfoLoaded,
                  weak_ptr_factory_.GetWeakPtr()));
 }
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 3daa584..a1b6098 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -421,11 +421,9 @@
       IconManager* im = g_browser_process->icon_manager();
       gfx::Image* icon = im->LookupIconFromFilepath(
           download()->GetTargetFilePath(), IconLoader::SMALL);
-      if (icon) {
-        views::Widget* widget = GetWidget();
-        DragDownloadItem(
-            download(), icon, widget ? widget->GetNativeView() : NULL);
-      }
+      views::Widget* widget = GetWidget();
+      DragDownloadItem(
+          download(), icon, widget ? widget->GetNativeView() : NULL);
     }
   } else if (ExceededDragThreshold(event.location() - drag_start_point_)) {
     dragging_ = true;
@@ -496,11 +494,10 @@
 void DownloadItemView::GetAccessibleState(ui::AXViewState* state) {
   state->name = accessible_name_;
   state->role = ui::AX_ROLE_BUTTON;
-  if (model_.IsDangerous()) {
-    state->state = ui::AX_STATE_DISABLED;
-  } else {
-    state->state = ui::AX_STATE_HASPOPUP;
-  }
+  if (model_.IsDangerous())
+    state->AddStateFlag(ui::AX_STATE_DISABLED);
+  else
+    state->AddStateFlag(ui::AX_STATE_HASPOPUP);
 }
 
 void DownloadItemView::OnThemeChanged() {
diff --git a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
index 5e2dc87..05aaaf9 100644
--- a/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
+++ b/chrome/browser/ui/views/extensions/extension_message_bubble_view.cc
@@ -9,12 +9,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/extensions/dev_mode_bubble_controller.h"
 #include "chrome/browser/extensions/extension_action_manager.h"
+#include "chrome/browser/extensions/extension_message_bubble_controller.h"
 #include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/settings_api_bubble_controller.h"
 #include "chrome/browser/extensions/suspicious_extension_bubble_controller.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/settings_api_bubble_helper_views.h"
 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
+#include "chrome/browser/ui/views/toolbar/browser_actions_container_observer.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_system.h"
@@ -30,6 +33,9 @@
 
 namespace {
 
+base::LazyInstance<std::set<Profile*> > g_profiles_evaluated =
+    LAZY_INSTANCE_INITIALIZER;
+
 // Layout constants.
 const int kExtensionListPadding = 10;
 const int kInsetBottomRight = 13;
@@ -47,15 +53,13 @@
 
 }  // namespace
 
-////////////////////////////////////////////////////////////////////////////////
-// ExtensionMessageBubbleView
-
 namespace extensions {
 
 ExtensionMessageBubbleView::ExtensionMessageBubbleView(
     views::View* anchor_view,
-    scoped_ptr<ExtensionMessageBubbleController> controller)
-    : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
+    views::BubbleBorder::Arrow arrow_location,
+    scoped_ptr<extensions::ExtensionMessageBubbleController> controller)
+    : BubbleDelegateView(anchor_view, arrow_location),
       weak_factory_(this),
       controller_(controller.Pass()),
       headline_(NULL),
@@ -64,7 +68,7 @@
       link_clicked_(false),
       action_taken_(false) {
   DCHECK(anchor_view->GetWidget());
-  set_close_on_deactivate(false);
+  set_close_on_deactivate(controller_->CloseOnDeactivate());
   set_move_with_anchor(true);
   set_close_on_esc(true);
 
@@ -72,75 +76,6 @@
   set_anchor_view_insets(gfx::Insets(5, 0, 5, 0));
 }
 
-// static
-void ExtensionMessageBubbleView::MaybeShow(
-    Browser* browser,
-    ToolbarView* toolbar_view,
-    views::View* anchor_view) {
-#if defined(OS_WIN)
-  // The list of suspicious extensions takes priority over the dev mode bubble,
-  // since that needs to be shown as soon as we disable something. The dev mode
-  // bubble is not as time sensitive so we'll catch the dev mode extensions on
-  // the next startup/next window that opens. That way, we're not too spammy
-  // with the bubbles.
-  scoped_ptr<SuspiciousExtensionBubbleController> suspicious_extensions(
-      new SuspiciousExtensionBubbleController(browser->profile()));
-  if (suspicious_extensions->ShouldShow()) {
-    SuspiciousExtensionBubbleController* controller =
-        suspicious_extensions.get();
-    ExtensionMessageBubbleView* bubble_delegate =
-        new ExtensionMessageBubbleView(anchor_view,
-                                       suspicious_extensions.Pass());
-    views::BubbleDelegateView::CreateBubble(bubble_delegate);
-    controller->Show(bubble_delegate);
-    return;
-  }
-
-  scoped_ptr<DevModeBubbleController> dev_mode_extensions(
-      new DevModeBubbleController(browser->profile()));
-  if (dev_mode_extensions->ShouldShow()) {
-    views::View* reference_view = NULL;
-    BrowserActionsContainer* container = toolbar_view->browser_actions();
-    if (container->animating())
-      return;
-
-    ExtensionService* service = extensions::ExtensionSystem::Get(
-        browser->profile())->extension_service();
-    extensions::ExtensionActionManager* extension_action_manager =
-        extensions::ExtensionActionManager::Get(browser->profile());
-
-    const ExtensionIdList extension_list =
-        dev_mode_extensions->GetExtensionIdList();
-    ExtensionToolbarModel::Get(
-        browser->profile())->EnsureVisibility(extension_list);
-    for (size_t i = 0; i < extension_list.size(); ++i) {
-      const Extension* extension =
-          service->GetExtensionById(extension_list[i], false);
-      if (!extension)
-        continue;
-      reference_view = container->GetBrowserActionView(
-          extension_action_manager->GetBrowserAction(*extension));
-      if (reference_view && reference_view->visible())
-        break;  // Found a good candidate.
-    }
-    if (reference_view) {
-      // If we have a view, it means we found a browser action and we want to
-      // point to the chevron, not the hotdog menu.
-      if (!reference_view->visible())
-        reference_view = container->chevron();  // It's hidden, use the chevron.
-    }
-    if (reference_view && reference_view->visible())
-      anchor_view = reference_view;  // Catch-all is the hotdog menu.
-
-    DevModeBubbleController* controller = dev_mode_extensions.get();
-    ExtensionMessageBubbleView* bubble_delegate =
-        new ExtensionMessageBubbleView(anchor_view, dev_mode_extensions.Pass());
-    views::BubbleDelegateView::CreateBubble(bubble_delegate);
-    controller->Show(bubble_delegate);
-  }
-#endif
-}
-
 void ExtensionMessageBubbleView::OnActionButtonClicked(
     const base::Closure& callback) {
   action_callback_ = callback;
@@ -182,8 +117,7 @@
 ////////////////////////////////////////////////////////////////////////////////
 // ExtensionMessageBubbleView - private.
 
-ExtensionMessageBubbleView::~ExtensionMessageBubbleView() {
-}
+ExtensionMessageBubbleView::~ExtensionMessageBubbleView() {}
 
 void ExtensionMessageBubbleView::ShowBubble() {
   GetWidget()->Show();
@@ -329,4 +263,218 @@
     NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// ExtensionMessageBubbleFactory
+
+ExtensionMessageBubbleFactory::ExtensionMessageBubbleFactory(
+    Profile* profile,
+    ToolbarView* toolbar_view)
+    : profile_(profile),
+      toolbar_view_(toolbar_view),
+      shown_suspicious_extensions_bubble_(false),
+      shown_startup_override_extensions_bubble_(false),
+      shown_dev_mode_extensions_bubble_(false),
+      is_observing_(false),
+      stage_(STAGE_START),
+      container_(NULL),
+      anchor_view_(NULL) {}
+
+ExtensionMessageBubbleFactory::~ExtensionMessageBubbleFactory() {
+  MaybeStopObserving();
+}
+
+void ExtensionMessageBubbleFactory::MaybeShow(views::View* anchor_view) {
+#if defined(OS_WIN)
+  // The list of suspicious extensions takes priority over the dev mode bubble
+  // and the settings API bubble, since that needs to be shown as soon as we
+  // disable something. The settings API bubble is shown on first startup after
+  // an extension has changed the startup pages and it is acceptable if that
+  // waits until the next startup because of the suspicious extension bubble.
+  // The dev mode bubble is not time sensitive like the other two so we'll catch
+  // the dev mode extensions on the next startup/next window that opens. That
+  // way, we're not too spammy with the bubbles.
+  if (!shown_suspicious_extensions_bubble_) {
+    if (MaybeShowSuspiciousExtensionsBubble(anchor_view))
+      return;
+  }
+
+  if (!shown_startup_override_extensions_bubble_ &&
+      IsInitialProfileCheck(profile_->GetOriginalProfile()) &&
+      MaybeShowStartupOverrideExtensionsBubble(anchor_view))
+    return;
+
+  if (!shown_dev_mode_extensions_bubble_)
+    MaybeShowDevModeExtensionsBubble(anchor_view);
+
+  RecordProfileCheck(profile_->GetOriginalProfile());
+#endif  // OS_WIN
+}
+
+bool ExtensionMessageBubbleFactory::MaybeShowSuspiciousExtensionsBubble(
+    views::View* anchor_view) {
+  DCHECK(!shown_suspicious_extensions_bubble_);
+
+  scoped_ptr<SuspiciousExtensionBubbleController> suspicious_extensions(
+      new SuspiciousExtensionBubbleController(profile_));
+  if (!suspicious_extensions->ShouldShow())
+    return false;
+
+  shown_suspicious_extensions_bubble_ = true;
+  SuspiciousExtensionBubbleController* weak_controller =
+      suspicious_extensions.get();
+  ExtensionMessageBubbleView* bubble_delegate = new ExtensionMessageBubbleView(
+      anchor_view,
+      views::BubbleBorder::TOP_RIGHT,
+      suspicious_extensions.PassAs<ExtensionMessageBubbleController>());
+
+  views::BubbleDelegateView::CreateBubble(bubble_delegate);
+  weak_controller->Show(bubble_delegate);
+
+  return true;
+}
+
+bool ExtensionMessageBubbleFactory::MaybeShowStartupOverrideExtensionsBubble(
+    views::View* anchor_view) {
+#if !defined(OS_WIN)
+  return false;
+#endif
+
+  DCHECK(!shown_startup_override_extensions_bubble_);
+
+  const Extension* extension = OverridesStartupPages(profile_, NULL);
+  if (!extension)
+    return false;
+
+  scoped_ptr<SettingsApiBubbleController> settings_api_bubble(
+      new SettingsApiBubbleController(profile_,
+                                      BUBBLE_TYPE_STARTUP_PAGES));
+  if (!settings_api_bubble->ShouldShow(extension->id()))
+    return false;
+
+  shown_startup_override_extensions_bubble_ = true;
+  SettingsApiBubbleController* weak_controller = settings_api_bubble.get();
+  ExtensionMessageBubbleView* bubble_delegate = new ExtensionMessageBubbleView(
+      anchor_view,
+      views::BubbleBorder::TOP_RIGHT,
+      settings_api_bubble.PassAs<ExtensionMessageBubbleController>());
+  views::BubbleDelegateView::CreateBubble(bubble_delegate);
+  weak_controller->Show(bubble_delegate);
+
+  return true;
+}
+
+bool ExtensionMessageBubbleFactory::MaybeShowDevModeExtensionsBubble(
+    views::View* anchor_view) {
+  DCHECK(!shown_dev_mode_extensions_bubble_);
+
+  // Check the Developer Mode extensions.
+  scoped_ptr<DevModeBubbleController> dev_mode_extensions(
+      new DevModeBubbleController(profile_));
+
+  // Return early if we have none to show.
+  if (!dev_mode_extensions->ShouldShow())
+    return false;
+
+  shown_dev_mode_extensions_bubble_ = true;
+
+  // We should be in the start stage (i.e., should not have a pending attempt to
+  // show a bubble).
+  DCHECK_EQ(stage_, STAGE_START);
+
+  // Prepare to display and highlight the developer mode extensions before
+  // showing the bubble. Since this is an asynchronous process, set member
+  // variables for later use.
+  controller_ = dev_mode_extensions.Pass();
+  anchor_view_ = anchor_view;
+  container_ = toolbar_view_->browser_actions();
+
+  if (container_->animating())
+    MaybeObserve();
+  else
+    HighlightDevModeExtensions();
+
+  return true;
+}
+
+void ExtensionMessageBubbleFactory::MaybeObserve() {
+  if (!is_observing_) {
+    is_observing_ = true;
+    container_->AddObserver(this);
+  }
+}
+
+void ExtensionMessageBubbleFactory::MaybeStopObserving() {
+  if (is_observing_) {
+    is_observing_ = false;
+    container_->RemoveObserver(this);
+  }
+}
+
+void ExtensionMessageBubbleFactory::RecordProfileCheck(Profile* profile) {
+  g_profiles_evaluated.Get().insert(profile);
+}
+
+bool ExtensionMessageBubbleFactory::IsInitialProfileCheck(Profile* profile) {
+  return g_profiles_evaluated.Get().count(profile) == 0;
+}
+
+void ExtensionMessageBubbleFactory::OnBrowserActionsContainerAnimationEnded() {
+  MaybeStopObserving();
+  if (stage_ == STAGE_START) {
+    HighlightDevModeExtensions();
+  } else if (stage_ == STAGE_HIGHLIGHTED) {
+    ShowDevModeBubble();
+  } else {  // We shouldn't be observing if we've completed the process.
+    NOTREACHED();
+    Finish();
+  }
+}
+
+void ExtensionMessageBubbleFactory::OnBrowserActionsContainerDestroyed() {
+  // If the container associated with the bubble is destroyed, abandon the
+  // process.
+  Finish();
+}
+
+void ExtensionMessageBubbleFactory::HighlightDevModeExtensions() {
+  DCHECK_EQ(STAGE_START, stage_);
+  stage_ = STAGE_HIGHLIGHTED;
+
+  const ExtensionIdList extension_list = controller_->GetExtensionIdList();
+  DCHECK(!extension_list.empty());
+  ExtensionToolbarModel::Get(profile_)->HighlightExtensions(extension_list);
+  if (container_->animating())
+    MaybeObserve();
+  else
+    ShowDevModeBubble();
+}
+
+void ExtensionMessageBubbleFactory::ShowDevModeBubble() {
+  DCHECK_EQ(stage_, STAGE_HIGHLIGHTED);
+  stage_ = STAGE_COMPLETE;
+
+  views::View* reference_view = NULL;
+  if (container_->num_browser_actions() > 0)
+    reference_view = container_->GetBrowserActionViewAt(0);
+  if (reference_view && reference_view->visible())
+    anchor_view_ = reference_view;
+
+  DevModeBubbleController* weak_controller = controller_.get();
+  ExtensionMessageBubbleView* bubble_delegate = new ExtensionMessageBubbleView(
+      anchor_view_,
+      views::BubbleBorder::TOP_RIGHT,
+      scoped_ptr<ExtensionMessageBubbleController>(controller_.release()));
+  views::BubbleDelegateView::CreateBubble(bubble_delegate);
+  weak_controller->Show(bubble_delegate);
+
+  Finish();
+}
+
+void ExtensionMessageBubbleFactory::Finish() {
+  MaybeStopObserving();
+  controller_.reset();
+  anchor_view_ = NULL;
+  container_ = NULL;
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/ui/views/extensions/extension_message_bubble_view.h b/chrome/browser/ui/views/extensions/extension_message_bubble_view.h
index a388a97..c615c18 100644
--- a/chrome/browser/ui/views/extensions/extension_message_bubble_view.h
+++ b/chrome/browser/ui/views/extensions/extension_message_bubble_view.h
@@ -5,24 +5,127 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_MESSAGE_BUBBLE_VIEW_H_
 #define CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSION_MESSAGE_BUBBLE_VIEW_H_
 
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
 #include "chrome/browser/extensions/extension_message_bubble.h"
-#include "chrome/browser/extensions/extension_message_bubble_controller.h"
+#include "chrome/browser/ui/views/toolbar/browser_actions_container_observer.h"
 #include "ui/views/bubble/bubble_delegate.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/link_listener.h"
 
-class Browser;
+class Profile;
+class BrowserActionsContainer;
 class ToolbarView;
 
 namespace views {
 class Label;
 class LabelButton;
-class Link;
-class Widget;
+class View;
 }
 
 namespace extensions {
 
+class DevModeBubbleController;
+class ExtensionMessageBubbleController;
+
+// Create and show ExtensionMessageBubbles for either extensions that look
+// suspicious and have therefore been disabled, or for extensions that are
+// running in developer mode that we want to warn the user about.
+// Calling MaybeShow() will show one of the bubbles, if there is cause to (we
+// don't show both in order to avoid spamminess). The suspicious extensions
+// bubble takes priority over the developer mode extensions bubble.
+class ExtensionMessageBubbleFactory : public BrowserActionsContainerObserver {
+ public:
+  ExtensionMessageBubbleFactory(Profile* profile, ToolbarView* toolbar_view);
+  virtual ~ExtensionMessageBubbleFactory();
+
+  void MaybeShow(views::View* anchor_view);
+
+ private:
+  // The stage of showing the developer mode extensions bubble. STAGE_START
+  // corresponds to the beginning of the process, when nothing has been done.
+  // STAGE_HIGHLIGHTED indicates that the toolbar should be highlighting
+  // dangerous extensions. STAGE_COMPLETE means that the process should be
+  // ended.
+  enum Stage { STAGE_START, STAGE_HIGHLIGHTED, STAGE_COMPLETE };
+
+  // Shows the suspicious extensions bubble, if there are suspicious extensions
+  // and we have not done so already.
+  // Returns true if we have show the view.
+  bool MaybeShowSuspiciousExtensionsBubble(views::View* anchor_view);
+
+  // Shows the settings API extensions bubble, if there are extensions
+  // overriding the startup pages and we have not done so already.
+  // Returns true if we show the view (or start the process).
+  bool MaybeShowStartupOverrideExtensionsBubble(views::View* anchor_view);
+
+  // Shows the developer mode extensions bubble, if there are extensions running
+  // in developer mode and we have not done so already.
+  // Returns true if we show the view (or start the process).
+  bool MaybeShowDevModeExtensionsBubble(views::View* anchor_view);
+
+  // Starts or stops observing the BrowserActionsContainer, if necessary.
+  void MaybeObserve();
+  void MaybeStopObserving();
+
+  // Adds |profile| to the list of profiles that have been evaluated for showing
+  // a bubble. Handy for things that only want to check once per profile.
+  void RecordProfileCheck(Profile* profile);
+  // Returns false if this profile has been evaluated before.
+  bool IsInitialProfileCheck(Profile* profile);
+
+  // BrowserActionsContainer::Observer implementation.
+  virtual void OnBrowserActionsContainerAnimationEnded() OVERRIDE;
+  virtual void OnBrowserActionsContainerDestroyed() OVERRIDE;
+
+  // Inform the ExtensionToolbarModel to highlight the appropriate extensions.
+  void HighlightDevModeExtensions();
+
+  // Shows the developer mode bubble, after highlighting the extensions.
+  void ShowDevModeBubble();
+
+  // Finishes the process of showing the developer mode bubble.
+  void Finish();
+
+  // The associated profile.
+  Profile* profile_;
+
+  // The toolbar view that the ExtensionMessageBubbleViews will attach to.
+  ToolbarView* toolbar_view_;
+
+  // Whether or not we have shown the suspicious extensions bubble.
+  bool shown_suspicious_extensions_bubble_;
+
+  // Whether or not we have shown the Settings API extensions bubble notifying
+  // the user about the startup pages being overridden.
+  bool shown_startup_override_extensions_bubble_;
+
+  // Whether or not we have shown the developer mode extensions bubble.
+  bool shown_dev_mode_extensions_bubble_;
+
+  // Whether or not we are already observing the BrowserActionsContainer (so
+  // we don't add ourselves twice).
+  bool is_observing_;
+
+  // The current stage of showing the bubble.
+  Stage stage_;
+
+  // The BrowserActionsContainer for the profile. This will be NULL if the
+  // factory is not currently in the process of showing a bubble.
+  BrowserActionsContainer* container_;
+
+  // The default view to anchor the bubble to. This will be NULL if the factory
+  // is not currently in the process of showing a bubble.
+  views::View* anchor_view_;
+
+  // The DevModeBubbleController to use. This will be NULL if the factory is not
+  // currently in the process of showing a bubble.
+  scoped_ptr<DevModeBubbleController> controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(ExtensionMessageBubbleFactory);
+};
+
 // This is a class that implements the UI for the bubble showing which
 // extensions look suspicious and have therefore been automatically disabled.
 class ExtensionMessageBubbleView : public ExtensionMessageBubble,
@@ -30,9 +133,10 @@
                                    public views::ButtonListener,
                                    public views::LinkListener {
  public:
-  // Show the Disabled Extension bubble, if needed.
-  static void MaybeShow(
-      Browser* browser, ToolbarView* toolbar_view, views::View* anchor_view);
+  ExtensionMessageBubbleView(
+      views::View* anchor_view,
+      views::BubbleBorder::Arrow arrow_location,
+      scoped_ptr<ExtensionMessageBubbleController> controller);
 
   // ExtensionMessageBubble methods.
   virtual void OnActionButtonClicked(const base::Closure& callback) OVERRIDE;
@@ -44,12 +148,8 @@
   virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
 
  private:
-  ExtensionMessageBubbleView(
-      views::View* anchor_view,
-      scoped_ptr<ExtensionMessageBubbleController> controller);
   virtual ~ExtensionMessageBubbleView();
 
-  // Shows the bubble and updates the counter for how often it has been shown.
   void ShowBubble();
 
   // views::BubbleDelegateView overrides:
@@ -64,8 +164,8 @@
 
   // views::View implementation.
   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
-  virtual void ViewHierarchyChanged(
-      const ViewHierarchyChangedDetails& details) OVERRIDE;
+  virtual void ViewHierarchyChanged(const ViewHierarchyChangedDetails& details)
+      OVERRIDE;
 
   base::WeakPtrFactory<ExtensionMessageBubbleView> weak_factory_;
 
diff --git a/chrome/browser/ui/views/extensions/extension_popup.cc b/chrome/browser/ui/views/extensions/extension_popup.cc
index e8a31ab..dcacc5a 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.cc
+++ b/chrome/browser/ui/views/extensions/extension_popup.cc
@@ -29,10 +29,10 @@
 #include "ui/views/widget/widget.h"
 
 #if defined(USE_AURA)
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/wm/core/window_animations.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 #endif
 
 #if defined(OS_WIN)
diff --git a/chrome/browser/ui/views/extensions/extension_popup.h b/chrome/browser/ui/views/extensions/extension_popup.h
index aa4be8f..172198c 100644
--- a/chrome/browser/ui/views/extensions/extension_popup.h
+++ b/chrome/browser/ui/views/extensions/extension_popup.h
@@ -16,7 +16,7 @@
 #include "url/gurl.h"
 
 #if defined(USE_AURA)
-#include "ui/aura/client/activation_change_observer.h"
+#include "ui/wm/public/activation_change_observer.h"
 #endif
 
 class Browser;
diff --git a/chrome/browser/ui/views/first_run_dialog.cc b/chrome/browser/ui/views/first_run_dialog.cc
index 4825735..15a1169 100644
--- a/chrome/browser/ui/views/first_run_dialog.cc
+++ b/chrome/browser/ui/views/first_run_dialog.cc
@@ -15,7 +15,6 @@
 #include "grit/generated_resources.h"
 #include "grit/locale_settings.h"
 #include "grit/theme_resources.h"
-#include "ui/aura/client/dispatcher_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -26,6 +25,7 @@
 #include "ui/views/layout/layout_constants.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
+#include "ui/wm/public/dispatcher_client.h"
 
 #if defined(GOOGLE_CHROME_BUILD)
 #include "base/prefs/pref_service.h"
diff --git a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
index 34ee202..1467bd7 100644
--- a/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
+++ b/chrome/browser/ui/views/frame/browser_header_painter_ash.cc
@@ -248,7 +248,7 @@
   if (window_icon_) {
     // Vertically center the window icon with respect to the caption button
     // container.
-    int icon_size = ash::HeaderPainterUtil::GetIconSize();
+    int icon_size = ash::HeaderPainterUtil::GetDefaultIconSize();
     int icon_offset_y = (caption_button_container_->height() - icon_size) / 2;
     window_icon_->SetBounds(ash::HeaderPainterUtil::GetIconXOffset(),
         icon_offset_y, icon_size, icon_size);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index 624ff44..9f3fcda 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -95,7 +95,7 @@
   EXPECT_TRUE(frame_view->caption_button_container_->visible());
 }
 
-// TODO(zturner): Change this to USE_ASH after fixing the test on Windows.
+// Immersive fullscreen is CrOS only for now.
 #if defined(OS_CHROMEOS)
 IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewAshTest, ImmersiveFullscreen) {
   // We know we're using Views, so static cast.
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 5d332a5..75ee610 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -144,6 +144,7 @@
 #endif
 
 #if defined(USE_AURA)
+#include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/gfx/screen.h"
@@ -916,14 +917,14 @@
   if (IsFullscreen())
     return;  // Nothing to do.
 
-  ProcessFullscreen(true, NORMAL_FULLSCREEN, url, bubble_type);
+  ProcessFullscreen(true, FOR_DESKTOP, url, bubble_type);
 }
 
 void BrowserView::ExitFullscreen() {
   if (!IsFullscreen())
     return;  // Nothing to do.
 
-  ProcessFullscreen(false, NORMAL_FULLSCREEN, GURL(), FEB_TYPE_NONE);
+  ProcessFullscreen(false, FOR_DESKTOP, GURL(), FEB_TYPE_NONE);
 }
 
 void BrowserView::UpdateFullscreenExitBubbleContent(
@@ -962,7 +963,7 @@
 #if defined(OS_WIN)
 void BrowserView::SetMetroSnapMode(bool enable) {
   HISTOGRAM_COUNTS("Metro.SnapModeToggle", enable);
-  ProcessFullscreen(enable, METRO_SNAP_FULLSCREEN, GURL(), FEB_TYPE_NONE);
+  ProcessFullscreen(enable, FOR_METRO, GURL(), FEB_TYPE_NONE);
 }
 
 bool BrowserView::IsInMetroSnapMode() const {
@@ -984,7 +985,7 @@
 
 void BrowserView::FullscreenStateChanged() {
   CHECK(!IsFullscreen());
-  ProcessFullscreen(false, NORMAL_FULLSCREEN, GURL(), FEB_TYPE_NONE);
+  ProcessFullscreen(false, FOR_DESKTOP, GURL(), FEB_TYPE_NONE);
 }
 
 void BrowserView::ToolbarSizeChanged(bool is_animating) {
@@ -1056,7 +1057,7 @@
     // origin chip is enabled, show it now to support the same functionality.
     if (select_all &&
         location_bar->GetToolbarModel()->WouldOmitURLDueToOriginChip())
-      location_bar->omnibox_view()->ShowURL();
+      location_bar->ShowURL();
     else
       location_bar->FocusLocation(select_all);
   } else {
@@ -1461,6 +1462,22 @@
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserView, TabStripModelObserver implementation:
 
+void BrowserView::TabInsertedAt(WebContents* contents,
+                                int index,
+                                bool foreground) {
+  // WebContents inserted in tabs might not have been added to the root
+  // window yet. Per http://crbug/342672 add them now since drawing the
+  // WebContents requires root window specific data - information about
+  // the screen the WebContents is drawn on, for example.
+  if (!contents->GetView()->GetNativeView()->GetRootWindow()) {
+    aura::Window* window = contents->GetView()->GetNativeView();
+    aura::Window* root_window = GetNativeWindow()->GetRootWindow();
+    aura::client::ParentWindowWithContext(
+        window, root_window, root_window->GetBoundsInScreen());
+    DCHECK(contents->GetView()->GetNativeView()->GetRootWindow());
+  }
+}
+
 void BrowserView::TabDetachedAt(WebContents* contents, int index) {
   if (PermissionBubbleManager::FromWebContents(contents))
     PermissionBubbleManager::FromWebContents(contents)->SetView(NULL);
@@ -2177,7 +2194,7 @@
 }
 
 void BrowserView::ProcessFullscreen(bool fullscreen,
-                                    FullscreenMode mode,
+                                    FullscreenType type,
                                     const GURL& url,
                                     FullscreenExitBubbleType bubble_type) {
   if (in_process_fullscreen_)
@@ -2190,7 +2207,7 @@
   //     thus are slow and look ugly (enforced via |in_process_fullscreen_|).
   LocationBarView* location_bar = GetLocationBarView();
 
-  if (mode == METRO_SNAP_FULLSCREEN || !fullscreen) {
+  if (type == FOR_METRO || !fullscreen) {
     // Hide the fullscreen bubble as soon as possible, since the mode toggle can
     // take enough time for the user to notice.
     fullscreen_bubble_.reset();
@@ -2209,15 +2226,13 @@
   frame_->SetFullscreen(fullscreen);
 
   // Enable immersive before the browser refreshes its list of enabled commands.
-  if (mode != METRO_SNAP_FULLSCREEN && ShouldUseImmersiveFullscreenForUrl(url))
+  if (ShouldUseImmersiveFullscreenForUrl(url))
     immersive_mode_controller_->SetEnabled(fullscreen);
 
   browser_->WindowFullscreenStateChanged();
 
-  if (fullscreen && !chrome::IsRunningInAppMode() &&
-      mode != METRO_SNAP_FULLSCREEN) {
+  if (fullscreen && !chrome::IsRunningInAppMode() && type != FOR_METRO)
     UpdateFullscreenExitBubbleContent(url, bubble_type);
-  }
 
   // Undo our anti-jankiness hacks and force a re-layout. We also need to
   // recompute the height of the infobar top arrow because toggling in and out
@@ -2230,14 +2245,15 @@
 }
 
 bool BrowserView::ShouldUseImmersiveFullscreenForUrl(const GURL& url) const {
-  // Kiosk mode needs the whole screen, and if we're not in an Ash desktop
-  // immersive fullscreen doesn't exist.
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode) ||
-      browser()->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH) {
+#if defined(OS_CHROMEOS)
+  // Kiosk mode needs the whole screen.
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
     return false;
-  }
-
-  return url.is_empty();
+  bool is_browser_fullscreen = url.is_empty();
+  return is_browser_fullscreen;
+#else
+  return false;
+#endif
 }
 
 void BrowserView::LoadAccelerators() {
@@ -2413,7 +2429,7 @@
       views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, bounds, browser_.get());
 }
 
-void BrowserView::ShowAvatarBubbleFromAvatarButton() {
+void BrowserView::ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode) {
   if (switches::IsNewProfileManagement()) {
     NewAvatarButton* button = frame_->GetNewAvatarMenuButton();
     if (button) {
@@ -2421,8 +2437,12 @@
       views::View::ConvertPointToScreen(button, &origin);
       gfx::Rect bounds(origin, size());
 
+      ProfileChooserView::BubbleViewMode view_mode =
+          mode == BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT ?
+          ProfileChooserView::BUBBLE_VIEW_MODE_PROFILE_CHOOSER :
+          ProfileChooserView::BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT;
       ProfileChooserView::ShowBubble(
-          button, views::BubbleBorder::TOP_RIGHT,
+          view_mode, button, views::BubbleBorder::TOP_RIGHT,
           views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE, bounds, browser());
     }
   } else {
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index bc44061..3d709e4 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -123,7 +123,6 @@
 
   // Returns a Browser instance of this view.
   Browser* browser() { return browser_.get(); }
-  const Browser* browser() const { return browser_.get(); }
 
   // Initializes (or re-initializes) the status bubble.  We try to only create
   // the bubble once and re-use it for the life of the browser, but certain
@@ -376,7 +375,7 @@
       GetWebContentsModalDialogHost() OVERRIDE;
   virtual void ShowAvatarBubble(content::WebContents* web_contents,
                                 const gfx::Rect& rect) OVERRIDE;
-  virtual void ShowAvatarBubbleFromAvatarButton() OVERRIDE;
+  virtual void ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode) OVERRIDE;
   virtual void ShowPasswordGenerationBubble(
       const gfx::Rect& rect,
       const autofill::PasswordForm& form,
@@ -398,6 +397,9 @@
   virtual ToolbarView* GetToolbarView() const OVERRIDE;
 
   // Overridden from TabStripModelObserver:
+  virtual void TabInsertedAt(content::WebContents* contents,
+                             int index,
+                             bool foreground) OVERRIDE;
   virtual void TabDetachedAt(content::WebContents* contents,
                              int index) OVERRIDE;
   virtual void TabDeactivated(content::WebContents* contents) OVERRIDE;
@@ -479,9 +481,9 @@
   FRIEND_TEST_ALL_PREFIXES(BrowserViewsAccessibilityTest,
                            TestAboutChromeViewAccObj);
 
-  enum FullscreenMode {
-    NORMAL_FULLSCREEN,
-    METRO_SNAP_FULLSCREEN
+  enum FullscreenType {
+    FOR_DESKTOP,
+    FOR_METRO
   };
 
   // Appends to |toolbars| a pointer to each AccessiblePaneView that
@@ -546,7 +548,7 @@
   // |bubble_type| determines what should be shown in the fullscreen exit
   // bubble.
   void ProcessFullscreen(bool fullscreen,
-                         FullscreenMode mode,
+                         FullscreenType fullscreen_type,
                          const GURL& url,
                          FullscreenExitBubbleType bubble_type);
 
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
index 472dcad..0b154a3 100644
--- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -285,8 +285,10 @@
 // GlassBrowserFrameView, views::ButtonListener overrides:
 void GlassBrowserFrameView::ButtonPressed(views::Button* sender,
                                           const ui::Event& event) {
-  if (sender == new_avatar_button())
-    browser_view()->ShowAvatarBubbleFromAvatarButton();
+  if (sender == new_avatar_button()) {
+    browser_view()->ShowAvatarBubbleFromAvatarButton(
+        BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT);
+  }
 }
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
index aeb8549..010c9bb 100644
--- a/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
+++ b/chrome/browser/ui/views/frame/global_menu_bar_x11.cc
@@ -670,12 +670,12 @@
       HistoryItem* item = new HistoryItem();
       item->session_id = entry_win->id;
 
-      std::string title = item->tabs.size() == 1 ?
+      std::string title = tabs.size() == 1 ?
           l10n_util::GetStringUTF8(
               IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_SINGLE) :
           l10n_util::GetStringFUTF8(
               IDS_NEW_TAB_RECENTLY_CLOSED_WINDOW_MULTIPLE,
-              base::IntToString16(item->tabs.size()));
+              base::IntToString16(tabs.size()));
       DbusmenuMenuitem* parent_item = BuildMenuItem(
           title, TAG_RECENTLY_CLOSED);
       menuitem_child_add_position(history_menu_, parent_item, index++);
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_factory.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_factory.cc
index f69b9eb..ad89c60 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_factory.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_factory.cc
@@ -2,16 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#if defined(USE_ASH)
-#include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
-#else
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
+
 #include "chrome/browser/ui/views/frame/immersive_mode_controller_stub.h"
-#endif
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/ui/views/frame/immersive_mode_controller_ash.h"
+#endif  // defined(OS_CHROMEOS)
 
 namespace chrome {
 
 ImmersiveModeController* CreateImmersiveModeController() {
-#if defined(USE_ASH)
+#if defined(OS_CHROMEOS)
   return new ImmersiveModeControllerAsh();
 #else
   return new ImmersiveModeControllerStub();
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
index 36d1896..00f6469 100644
--- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
+++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -362,16 +362,18 @@
 
 void OpaqueBrowserFrameView::ButtonPressed(views::Button* sender,
                                            const ui::Event& event) {
-  if (sender == minimize_button_)
+  if (sender == minimize_button_) {
     frame()->Minimize();
-  else if (sender == maximize_button_)
+  } else if (sender == maximize_button_) {
     frame()->Maximize();
-  else if (sender == restore_button_)
+  } else if (sender == restore_button_) {
     frame()->Restore();
-  else if (sender == close_button_)
+  } else if (sender == close_button_) {
     frame()->Close();
-  else if (sender == new_avatar_button())
-    browser_view()->ShowAvatarBubbleFromAvatarButton();
+  } else if (sender == new_avatar_button()) {
+    browser_view()->ShowAvatarBubbleFromAvatarButton(
+        BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT);
+  }
 }
 
 void OpaqueBrowserFrameView::OnMenuButtonClicked(views::View* source,
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index 177ba02..9e6a0fb 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -11,6 +11,7 @@
 #include "base/i18n/rtl.h"
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
+#include "base/strings/string_split.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/chrome_notification_types.h"
@@ -39,6 +40,7 @@
 #include "chrome/browser/ui/omnibox/omnibox_popup_view.h"
 #include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/toolbar/origin_chip_info.h"
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/bookmarks/bookmark_prompt_view.h"
 #include "chrome/browser/ui/views/browser_dialogs.h"
@@ -78,6 +80,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/theme_provider.h"
 #include "ui/events/event.h"
+#include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/color_utils.h"
 #include "ui/gfx/image/image.h"
@@ -219,7 +222,8 @@
       is_popup_mode_(is_popup_mode),
       show_focus_rect_(false),
       template_url_service_(NULL),
-      animation_offset_(0),
+      dropdown_animation_offset_(0),
+      animated_host_label_(NULL),
       weak_ptr_factory_(this) {
   edit_bookmarks_enabled_.Init(
       prefs::kEditBookmarksEnabled, profile->GetPrefs(),
@@ -317,8 +321,11 @@
   ime_inline_autocomplete_view_->SetVisible(false);
   AddChildView(ime_inline_autocomplete_view_);
 
+  animated_host_label_ = new views::Label(base::string16(), font_list);
+  animated_host_label_->SetVisible(false);
+  AddChildView(animated_host_label_);
+
   origin_chip_view_ = new OriginChipView(this, profile(), font_list);
-  origin_chip_view_->Init();
   origin_chip_view_->SetFocusable(false);
   origin_chip_view_->set_drag_controller(this);
   AddChildView(origin_chip_view_);
@@ -423,6 +430,14 @@
   search_button_->SetVisible(false);
   AddChildView(search_button_);
 
+  show_url_animation_.reset(new gfx::SlideAnimation(this));
+  show_url_animation_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
+  show_url_animation_->SetSlideDuration(200);
+
+  hide_url_animation_.reset(new gfx::SlideAnimation(this));
+  hide_url_animation_->SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN);
+  hide_url_animation_->SetSlideDuration(200);
+
   content::Source<Profile> profile_source = content::Source<Profile>(profile());
   registrar_.Add(this,
                  chrome::NOTIFICATION_EXTENSION_LOCATION_BAR_UPDATED,
@@ -532,7 +547,7 @@
 }
 
 void LocationBarView::SetAnimationOffset(int offset) {
-  animation_offset_ = offset;
+  dropdown_animation_offset_ = offset;
 }
 
 void LocationBarView::UpdateContentSettingsIcons() {
@@ -708,6 +723,7 @@
   if (!IsInitialized())
     return;
 
+  animated_host_label_->SetVisible(false);
   origin_chip_view_->SetVisible(origin_chip_view_->ShouldShow());
   selected_keyword_view_->SetVisible(false);
   location_icon_view_->SetVisible(false);
@@ -723,6 +739,46 @@
   LocationBarLayout trailing_decorations(LocationBarLayout::RIGHT_EDGE,
                                          item_padding);
 
+  // Show and position the animated host label used in the show and hide URL
+  // animations.
+  if (show_url_animation_->is_animating() ||
+      hide_url_animation_->is_animating()) {
+    const GURL url = GetWebContents()->GetURL();
+    const base::string16 host =
+        OriginChip::LabelFromURLForProfile(url, profile());
+    animated_host_label_->SetText(host);
+
+    const base::string16 formatted_url = GetToolbarModel()->GetFormattedURL();
+
+    // Split the formatted URL on the host name in order to determine the size
+    // of the text leading up to it.
+    std::vector<base::string16> substrings;
+    base::SplitStringUsingSubstr(formatted_url, host, &substrings);
+    const base::string16 text_leading_host = substrings[0];
+    const int leading_text_width =
+        gfx::Canvas::GetStringWidth(text_leading_host,
+                                    origin_chip_view_->GetFontList());
+
+    const int position_of_host_name_in_chip = origin_chip_view_->host_label_x();
+    const int position_of_host_name_in_url =
+        position_of_host_name_in_chip + leading_text_width;
+
+    int host_label_x = position_of_host_name_in_chip;
+    if (show_url_animation_->is_animating()) {
+      host_label_x = show_url_animation_->
+          CurrentValueBetween(position_of_host_name_in_chip,
+                              position_of_host_name_in_url);
+    } else if (hide_url_animation_->is_animating()) {
+      host_label_x = hide_url_animation_->
+          CurrentValueBetween(position_of_host_name_in_url,
+                              position_of_host_name_in_chip);
+    }
+    animated_host_label_->SetBounds(
+        host_label_x, 0,
+        animated_host_label_->GetPreferredSize().width(), height());
+    animated_host_label_->SetVisible(true);
+  }
+
   const int origin_chip_width = origin_chip_view_->visible() ?
       origin_chip_view_->GetPreferredSize().width() : 0;
   origin_chip_view_->SetBounds(0, 0, origin_chip_width, height());
@@ -1101,6 +1157,59 @@
   GetFocusManager()->SetFocusedView(this);
 }
 
+void LocationBarView::ShowURL() {
+  if (chrome::ShouldDisplayOriginChipV2()) {
+    omnibox_view_->SetVisible(false);
+    omnibox_view_->ShowURL();
+    show_url_animation_->Show();
+  } else {
+    omnibox_view_->ShowURL();
+  }
+}
+
+void LocationBarView::OnShowURLAnimationEnded() {
+  animated_host_label_->SetVisible(false);
+  omnibox_view_->SetVisible(true);
+  omnibox_view_->FadeIn();
+  omnibox_view_->SetFocus();
+
+  // Sometimes the selection established by OmniboxView::ShowURL() is lost at
+  // the call to SetFocus() above.  Select all again to be sure.
+  // TODO(jdonnelly): Figure out why the selection is sometimes lost and
+  // implement a more principled fix.
+  omnibox_view_->SelectAll(true);
+}
+
+void LocationBarView::HideURL() {
+  omnibox_view_->SetVisible(false);
+  hide_url_animation_->Show();
+}
+
+void LocationBarView::OnHideURLAnimationEnded() {
+  animated_host_label_->SetVisible(false);
+  omnibox_view_->HideURL();
+  omnibox_view_->SetVisible(true);
+  origin_chip_view_->FadeIn();
+}
+
+void LocationBarView::AnimationProgressed(const gfx::Animation* animation) {
+  if (animation == show_url_animation_.get() ||
+      animation == hide_url_animation_.get()) {
+    Layout();
+    SchedulePaint();
+  }
+}
+
+void LocationBarView::AnimationEnded(const gfx::Animation* animation) {
+  if (animation == show_url_animation_.get()) {
+    show_url_animation_->Reset();
+    OnShowURLAnimationEnded();
+  } else if (animation == hide_url_animation_.get()) {
+    hide_url_animation_->Reset();
+    OnHideURLAnimationEnded();
+  }
+}
+
 InstantController* LocationBarView::GetInstant() {
   return delegate_->GetInstant();
 }
@@ -1140,7 +1249,7 @@
   state->selection_end = entry_end;
 
   if (is_popup_mode_) {
-    state->state |= ui::AX_STATE_READ_ONLY;
+    state->AddStateFlag(ui::AX_STATE_READ_ONLY);
   } else {
     state->set_value_callback =
         base::Bind(&LocationBarView::AccessibilitySetValue,
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.h b/chrome/browser/ui/views/location_bar/location_bar_view.h
index 51489ba..cd7d8e7 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.h
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.h
@@ -23,6 +23,7 @@
 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
+#include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/font.h"
 #include "ui/gfx/rect.h"
 #include "ui/views/controls/button/button.h"
@@ -56,6 +57,10 @@
 struct SSLStatus;
 }
 
+namespace gfx {
+class SlideAnimation;
+}
+
 namespace views {
 class BubbleDelegateView;
 class ImageButton;
@@ -80,6 +85,7 @@
                         public views::DragController,
                         public OmniboxEditController,
                         public DropdownBarHostDelegate,
+                        public gfx::AnimationDelegate,
                         public TemplateURLServiceObserver,
                         public content::NotificationObserver,
                         public SearchModelObserver {
@@ -91,8 +97,8 @@
   virtual void SetFocusAndSelection(bool select_all) OVERRIDE;
   virtual void SetAnimationOffset(int offset) OVERRIDE;
 
-  // Returns the offset used while animating.
-  int animation_offset() const { return animation_offset_; }
+  // Returns the offset used during dropdown animation.
+  int dropdown_animation_offset() const { return dropdown_animation_offset_; }
 
   class Delegate {
    public:
@@ -255,6 +261,7 @@
   virtual void Update(const content::WebContents* contents) OVERRIDE;
   virtual void OnChanged() OVERRIDE;
   virtual void OnSetFocus() OVERRIDE;
+  virtual void ShowURL() OVERRIDE;
   virtual InstantController* GetInstant() OVERRIDE;
   virtual content::WebContents* GetWebContents() OVERRIDE;
   virtual ToolbarModel* GetToolbarModel() OVERRIDE;
@@ -352,10 +359,17 @@
   // Space between the edge and a bubble.
   static const int kBubblePadding;
 
- protected:
+ private:
+  // views::View:
   virtual void OnFocus() OVERRIDE;
 
- private:
+  // OmniboxEditController:
+  virtual void HideURL() OVERRIDE;
+
+  // gfx::AnimationDelegate:
+  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
+  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
+
   typedef std::vector<ContentSettingImageView*> ContentSettingViews;
 
   friend class PageActionImageView;
@@ -416,6 +430,10 @@
   // don't normally use this). Sets the value and clears the selection.
   void AccessibilitySetValue(const base::string16& new_value);
 
+  // Origin chip animation control methods.
+  void OnShowURLAnimationEnded();
+  void OnHideURLAnimationEnded();
+
   // The Browser this LocationBarView is in.  Note that at least
   // chromeos::SimpleWebViewDialog uses a LocationBarView outside any browser
   // window, so this may be NULL.
@@ -511,11 +529,18 @@
   // Tracks this preference to determine whether bookmark editing is allowed.
   BooleanPrefMember edit_bookmarks_enabled_;
 
-  // While animating, the host clips the widget and draws only the bottom
-  // part of it. The view needs to know the pixel offset at which we are drawing
-  // the widget so that we can draw the curved edges that attach to the toolbar
-  // in the right location.
-  int animation_offset_;
+  // During dropdown animation, the host clips the widget and draws only the
+  // bottom part of it. The view needs to know the pixel offset at which we are
+  // drawing the widget so that we can draw the curved edges that attach to the
+  // toolbar in the right location.
+  int dropdown_animation_offset_;
+
+  // Origin chip animations.
+  scoped_ptr<gfx::SlideAnimation> show_url_animation_;
+  scoped_ptr<gfx::SlideAnimation> hide_url_animation_;
+
+  // Text label shown only during origin chip animations.
+  views::Label* animated_host_label_;
 
   // Used to register for notifications received by NotificationObserver.
   content::NotificationRegistrar registrar_;
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.cc b/chrome/browser/ui/views/location_bar/location_icon_view.cc
index 009c85d..5fbe9d2 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.cc
@@ -37,19 +37,28 @@
 }
 
 void LocationIconView::OnMouseReleased(const ui::MouseEvent& event) {
-  if (!event.IsOnlyMiddleMouseButton() &&
-      !chrome::ShouldDisplayOriginChip() &&
-      !chrome::ShouldDisplayOriginChipV2())
-    page_info_helper_.ProcessEvent(event);
+  if (event.IsOnlyMiddleMouseButton())
+    return;
+  OnClickOrTap(event);
 }
 
 void LocationIconView::OnGestureEvent(ui::GestureEvent* event) {
-  if (!chrome::ShouldDisplayOriginChip() &&
-      !chrome::ShouldDisplayOriginChipV2() &&
-      (event->type() == ui::ET_GESTURE_TAP)) {
-    page_info_helper_.ProcessEvent(*event);
-    event->SetHandled();
-  }
+  if (event->type() != ui::ET_GESTURE_TAP)
+    return;
+  OnClickOrTap(*event);
+  event->SetHandled();
+}
+
+void LocationIconView::OnClickOrTap(const ui::LocatedEvent& event) {
+  // Do not show page info if the user has been editing the location bar or the
+  // location bar is at the NTP.  Also skip showing the page info if the
+  // toolbar-based origin chip is being shown because it is responsible for
+  // showing the page info instead.
+  if (page_info_helper_.location_bar()->omnibox_view()->IsEditingOrEmpty() ||
+      chrome::ShouldDisplayOriginChip())
+    return;
+
+  page_info_helper_.ProcessEvent(event);
 }
 
 void LocationIconView::ShowTooltip(bool show) {
diff --git a/chrome/browser/ui/views/location_bar/location_icon_view.h b/chrome/browser/ui/views/location_bar/location_icon_view.h
index 22c4470..c1a1964 100644
--- a/chrome/browser/ui/views/location_bar/location_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/location_icon_view.h
@@ -31,6 +31,10 @@
   PageInfoHelper* page_info_helper() { return &page_info_helper_; }
 
  private:
+  // Handles both click and gesture events by delegating to the page info
+  // helper in the appropriate circumstances.
+  void OnClickOrTap(const ui::LocatedEvent& event);
+
   PageInfoHelper page_info_helper_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(LocationIconView);
diff --git a/chrome/browser/ui/views/location_bar/origin_chip_view.cc b/chrome/browser/ui/views/location_bar/origin_chip_view.cc
index 09e3853..1da7a95 100644
--- a/chrome/browser/ui/views/location_bar/origin_chip_view.cc
+++ b/chrome/browser/ui/views/location_bar/origin_chip_view.cc
@@ -25,8 +25,6 @@
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
@@ -37,6 +35,8 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/theme_provider.h"
+#include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/canvas.h"
 #include "ui/gfx/font_list.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/label_button.h"
@@ -143,16 +143,7 @@
     sb_service->ui_manager()->AddObserver(this);
 
   SetFontList(font_list);
-}
 
-OriginChipView::~OriginChipView() {
-  scoped_refptr<SafeBrowsingService> sb_service =
-      g_browser_process->safe_browsing_service();
-  if (sb_service.get() && sb_service->ui_manager())
-    sb_service->ui_manager()->RemoveObserver(this);
-}
-
-void OriginChipView::Init() {
   image()->EnableCanvasFlippingForRTLUI(false);
 
   // TODO(gbillock): Would be nice to just use stock LabelButton stuff here.
@@ -164,6 +155,17 @@
 
   host_label_ = new views::Label(base::string16(), GetFontList());
   AddChildView(host_label_);
+
+  fade_in_animation_.reset(new gfx::SlideAnimation(this));
+  fade_in_animation_->SetTweenType(gfx::Tween::LINEAR);
+  fade_in_animation_->SetSlideDuration(300);
+}
+
+OriginChipView::~OriginChipView() {
+  scoped_refptr<SafeBrowsingService> sb_service =
+      g_browser_process->safe_browsing_service();
+  if (sb_service.get() && sb_service->ui_manager())
+    sb_service->ui_manager()->RemoveObserver(this);
 }
 
 bool OriginChipView::ShouldShow() {
@@ -280,6 +282,24 @@
   // arrows are pointing to the right spot. Only needed for some edge cases.
 }
 
+void OriginChipView::FadeIn() {
+  fade_in_animation_->Show();
+}
+
+void OriginChipView::AnimationProgressed(const gfx::Animation* animation) {
+  if (animation == fade_in_animation_.get())
+    SchedulePaint();
+  else
+    views::LabelButton::AnimationProgressed(animation);
+}
+
+void OriginChipView::AnimationEnded(const gfx::Animation* animation) {
+  if (animation == fade_in_animation_.get())
+    fade_in_animation_->Reset();
+  else
+    views::LabelButton::AnimationEnded(animation);
+}
+
 gfx::Size OriginChipView::GetPreferredSize() {
   gfx::Size label_size = host_label_->GetPreferredSize();
   gfx::Size icon_size = location_icon_view_->GetPreferredSize();
@@ -312,6 +332,17 @@
                          height() - 2 * LocationBarView::kNormalEdgeThickness);
 }
 
+void OriginChipView::OnPaintBorder(gfx::Canvas* canvas) {
+  if (fade_in_animation_->is_animating()) {
+    canvas->SaveLayerAlpha(static_cast<uint8>(
+        fade_in_animation_->CurrentValueBetween(0, 255)));
+    views::LabelButton::OnPaintBorder(canvas);
+    canvas->Restore();
+  } else {
+    views::LabelButton::OnPaintBorder(canvas);
+  }
+}
+
 int OriginChipView::ElideDomainTarget(int target_max_width) {
   base::string16 host =
       OriginChip::LabelFromURLForProfile(url_displayed_, profile_);
@@ -350,7 +381,7 @@
   UMA_HISTOGRAM_COUNTS("OriginChip.Pressed", 1);
   content::RecordAction(base::UserMetricsAction("OriginChipPress"));
 
-  location_bar_view_->GetOmniboxView()->ShowURL();
+  location_bar_view_->ShowURL();
 }
 
 // Note: When OnSafeBrowsingHit would be called, OnSafeBrowsingMatch will
diff --git a/chrome/browser/ui/views/location_bar/origin_chip_view.h b/chrome/browser/ui/views/location_bar/origin_chip_view.h
index bb2d19d..644283e 100644
--- a/chrome/browser/ui/views/location_bar/origin_chip_view.h
+++ b/chrome/browser/ui/views/location_bar/origin_chip_view.h
@@ -22,6 +22,7 @@
 namespace gfx {
 class Canvas;
 class FontList;
+class SlideAnimation;
 }
 
 namespace views {
@@ -38,8 +39,6 @@
                  const gfx::FontList& font_list);
   virtual ~OriginChipView();
 
-  void Init();
-
   // Returns true if the origin chip should be visible.  This will always be
   // true if the original origin chip experiment is enabled.  If the V2
   // experiment is enabled this is true if the chip hasn't been hidden by
@@ -65,9 +64,18 @@
   // width, since the hostname will not be elided past the TLD+1.
   int ElideDomainTarget(int target_max_width);
 
+  // Starts an animation that fades in the border.
+  void FadeIn();
+
+  // Returns the current X position of the host label.
+  int host_label_x() const { return host_label_->x(); }
+
   // views::LabelButton:
+  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
+  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
   virtual gfx::Size GetPreferredSize() OVERRIDE;
   virtual void Layout() OVERRIDE;
+  virtual void OnPaintBorder(gfx::Canvas* canvas) OVERRIDE;
 
   // views::ButtonListener:
   virtual void ButtonPressed(views::Button* sender,
@@ -92,6 +100,7 @@
   GURL url_displayed_;
   ToolbarModel::SecurityLevel security_level_;
   bool url_malware_;
+  scoped_ptr<gfx::SlideAnimation> fade_in_animation_;
 
   DISALLOW_COPY_AND_ASSIGN(OriginChipView);
 };
diff --git a/chrome/browser/ui/views/location_bar/page_info_helper.cc b/chrome/browser/ui/views/location_bar/page_info_helper.cc
index 98c596a..e92f809 100644
--- a/chrome/browser/ui/views/location_bar/page_info_helper.cc
+++ b/chrome/browser/ui/views/location_bar/page_info_helper.cc
@@ -26,24 +26,13 @@
   if (!owner_->HitTestPoint(event.location()))
     return;
 
-  // Do not show page info if the user has been editing the location
-  // bar, or the location bar is at the NTP.
-  if (location_bar_->GetOmniboxView()->IsEditingOrEmpty() &&
-      !chrome::ShouldDisplayOriginChip() &&
-      !chrome::ShouldDisplayOriginChipV2())
-    return;
-
   WebContents* tab = location_bar_->GetWebContents();
   if (!tab)
     return;
   const NavigationController& controller = tab->GetController();
   // Important to use GetVisibleEntry to match what's showing in the omnibox.
   NavigationEntry* nav_entry = controller.GetVisibleEntry();
-  if (!nav_entry) {
-    NOTREACHED();
-    return;
-  }
-
+  DCHECK(nav_entry);
   location_bar_->delegate()->ShowWebsiteSettings(
       tab, nav_entry->GetURL(), nav_entry->GetSSL());
 }
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
index c8135e1..dc43622 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -62,7 +62,7 @@
   }
 }
 
-// TODO(zturner): Change this to USE_ASH after fixing the test on Windows.
+// Immersive fullscreen is CrOS only for now.
 #if defined(OS_CHROMEOS)
 // Test whether the zoom bubble is anchored and whether it is visible when in
 // immersive fullscreen.
diff --git a/chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc b/chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc
index 497402b..54a6c7f 100644
--- a/chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc
+++ b/chrome/browser/ui/views/new_avatar_menu_button_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "content/public/test/test_utils.h"
 #include "grit/generated_resources.h"
+#include "ui/views/controls/button/label_button.h"
 
 class NewAvatarMenuButtonTest : public InProcessBrowserTest {
  public:
@@ -121,10 +122,10 @@
       menu->GetItemAt(menu->GetActiveProfileIndex());
   EXPECT_FALSE(menu_item_before.signin_required);
 
-  ProfileChooserView::profile_bubble_->LinkClicked(
-      static_cast<views::Link*>(
-          ProfileChooserView::profile_bubble_->signout_current_profile_link_),
-      0);
+  ui::MouseEvent mouse_ev(
+      ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0, 0);
+  ProfileChooserView::profile_bubble_->ButtonPressed(
+      ProfileChooserView::profile_bubble_->lock_button_, mouse_ev);
 
   EXPECT_TRUE(menu->GetItemAt(menu->GetActiveProfileIndex()).signin_required);
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index 1a095c6..ebfd9f6 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -261,9 +261,8 @@
     int max_width) const {
   DCHECK(!render_text->text().empty());
 
-  const int remaining_width =
-      std::min(mirroring_context_->remaining_width(x), max_width);
-  int right_x = x + remaining_width;
+  const int remaining_width = mirroring_context_->remaining_width(x);
+  int right_x = x + max_width;
 
   // Infinite suggestions should appear with the leading ellipses vertically
   // stacked.
@@ -279,7 +278,7 @@
 
     scoped_ptr<gfx::RenderText> prefix_render_text(
         CreateRenderText(base::UTF8ToUTF16(
-            match.GetAdditionalInfo("match contents prefix"))));
+            match.GetAdditionalInfo(kACMatchPropertyContentsPrefix))));
     const int prefix_width = prefix_render_text->GetContentWidth();
     int prefix_x = x;
 
@@ -306,8 +305,7 @@
       // the ellipsis such that the widest suggestion reaches the end of the
       // dropdown.
       const int start_offset = std::max(prefix_width,
-          std::min(remaining_width - (prefix_width + max_match_contents_width),
-                   offset));
+          std::min(remaining_width - max_match_contents_width, offset));
       right_x = x + std::min(remaining_width, start_offset + max_width);
       x += start_offset;
       prefix_x = x - prefix_width;
@@ -400,9 +398,9 @@
     return 0;
 
   const base::string16& input_text =
-      base::UTF8ToUTF16(match.GetAdditionalInfo("input text"));
+      base::UTF8ToUTF16(match.GetAdditionalInfo(kACMatchPropertyInputText));
   int contents_start_index = 0;
-  base::StringToInt(match.GetAdditionalInfo("match contents start index"),
+  base::StringToInt(match.GetAdditionalInfo(kACMatchPropertyContentsStartIndex),
                     &contents_start_index);
 
   scoped_ptr<gfx::RenderText> input_render_text(CreateRenderText(input_text));
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index f01cfb8..aa42419 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -21,6 +21,8 @@
 #include "chrome/browser/ui/view_ids.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h"
+#include "chrome/browser/ui/views/settings_api_bubble_helper_views.h"
+#include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h"
 #include "chrome/common/chrome_switches.h"
 #include "content/public/browser/web_contents.h"
 #include "extensions/common/constants.h"
@@ -39,6 +41,7 @@
 #include "ui/base/models/simple_menu_model.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/events/event.h"
+#include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/selection_model.h"
@@ -178,6 +181,14 @@
   chromeos::input_method::InputMethodManager::Get()->
       AddCandidateWindowObserver(this);
 #endif
+
+  fade_in_animation_.reset(new gfx::SlideAnimation(this));
+  fade_in_animation_->SetTweenType(gfx::Tween::LINEAR);
+  fade_in_animation_->SetSlideDuration(300);
+}
+
+void OmniboxViewViews::FadeIn() {
+  fade_in_animation_->Show();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -187,6 +198,17 @@
   return kViewClassName;
 }
 
+void OmniboxViewViews::OnPaint(gfx::Canvas* canvas) {
+  if (fade_in_animation_->is_animating()) {
+    canvas->SaveLayerAlpha(static_cast<uint8>(
+        fade_in_animation_->CurrentValueBetween(0, 255)));
+    views::Textfield::OnPaint(canvas);
+    canvas->Restore();
+  } else {
+    views::Textfield::OnPaint(canvas);
+  }
+}
+
 bool OmniboxViewViews::OnMousePressed(const ui::MouseEvent& event) {
   select_all_on_mouse_release_ =
       (event.IsOnlyLeftMouseButton() || event.IsOnlyRightMouseButton()) &&
@@ -406,7 +428,10 @@
   // Tell the model to reset itself.
   model()->OnKillFocus();
 
-  OnDidKillFocus();
+  // Ignore loss of focus if we lost focus because the website settings popup
+  // is open. When the popup is destroyed, focus will return to the Omnibox.
+  if (!WebsiteSettingsPopupView::IsPopupShowing())
+    OnDidKillFocus();
 
   // Make sure the beginning of the text is visible.
   SelectRange(gfx::Range(0));
@@ -716,6 +741,13 @@
   GetInputMethod()->ShowImeIfNeeded();
 }
 
+void OmniboxViewViews::OnMatchOpened(const AutocompleteMatch& match,
+                                     Profile* profile,
+                                     content::WebContents* web_contents) const {
+  extensions::MaybeShowExtensionControlledSearchNotification(
+      profile, web_contents, match);
+}
+
 bool OmniboxViewViews::IsCommandIdEnabled(int command_id) const {
   if (command_id == IDS_APP_PASTE)
     return !read_only() && !GetClipboardText().empty();
@@ -745,7 +777,7 @@
       model()->PasteAndGo(GetClipboardText());
       break;
     case IDS_SHOW_URL:
-      ShowURL();
+      controller()->ShowURL();
       break;
     case IDC_EDIT_SEARCH_ENGINES:
       command_updater()->ExecuteCommand(command_id);
@@ -765,6 +797,17 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// OmniboxViewViews, gfx::AnimationDelegate implementation:
+
+void OmniboxViewViews::AnimationProgressed(const gfx::Animation* animation) {
+  SchedulePaint();
+}
+
+void OmniboxViewViews::AnimationEnded(const gfx::Animation* animation) {
+  fade_in_animation_->Reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // OmniboxViewViews, views::TextfieldController implementation:
 
 void OmniboxViewViews::ContentsChanged(views::Textfield* sender,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index 350c7cf..c7e19df 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -12,6 +12,7 @@
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
 #include "chrome/browser/ui/toolbar/toolbar_model.h"
 #include "ui/base/window_open_disposition.h"
+#include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/range/range.h"
 #include "ui/views/controls/textfield/textfield.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
@@ -24,6 +25,10 @@
 class OmniboxPopupView;
 class Profile;
 
+namespace gfx {
+class SlideAnimation;
+}
+
 namespace ui {
 class OSExchangeData;
 }  // namespace ui
@@ -32,6 +37,7 @@
 class OmniboxViewViews
     : public views::Textfield,
       public OmniboxView,
+      public gfx::AnimationDelegate,
 #if defined(OS_CHROMEOS)
       public
           chromeos::input_method::InputMethodManager::CandidateWindowObserver,
@@ -52,8 +58,12 @@
   // Initialize, create the underlying views, etc;
   void Init();
 
+  // Starts an animation that fades in the entire OmniboxView.
+  void FadeIn();
+
   // views::Textfield:
   virtual const char* GetClassName() const OVERRIDE;
+  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
   virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE;
   virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
@@ -110,11 +120,18 @@
   virtual bool IsImeComposing() const OVERRIDE;
   virtual bool IsImeShowingPopup() const OVERRIDE;
   virtual void ShowImeIfNeeded() OVERRIDE;
+  virtual void OnMatchOpened(const AutocompleteMatch& match,
+                             Profile* profile,
+                             content::WebContents* web_contents) const OVERRIDE;
   virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
   virtual bool IsItemForCommandIdDynamic(int command_id) const OVERRIDE;
   virtual base::string16 GetLabelForCommandId(int command_id) const OVERRIDE;
   virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
 
+  // gfx::AnimationDelegate:
+  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
+  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
+
   // views::TextfieldController:
   virtual void ContentsChanged(views::Textfield* sender,
                                const base::string16& new_contents) OVERRIDE;
@@ -204,6 +221,8 @@
   // and gets a tap. So we use this variable to remember focus state before tap.
   bool select_all_on_gesture_tap_;
 
+  scoped_ptr<gfx::SlideAnimation> fade_in_animation_;
+
   DISALLOW_COPY_AND_ASSIGN(OmniboxViewViews);
 };
 
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
index 5c741b9..4c90173 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
@@ -4,8 +4,17 @@
 
 #include "chrome/browser/ui/views/outdated_upgrade_bubble_view.h"
 
+#if defined(OS_WIN)
+#include <shellapi.h>
+#endif
+
 #include "base/metrics/histogram.h"
+#include "base/path_service.h"
+#include "base/prefs/pref_service.h"
+#include "chrome/browser/browser_process.h"
 #include "chrome/browser/upgrade_detector.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/page_navigator.h"
 #include "content/public/browser/user_metrics.h"
 #include "grit/chromium_strings.h"
@@ -21,6 +30,15 @@
 #include "ui/views/widget/widget.h"
 #include "url/gurl.h"
 
+#if defined(OS_WIN)
+#include "base/win/win_util.h"
+#include "base/win/windows_version.h"
+#include "chrome/installer/util/google_update_util.h"
+#include "chrome/installer/util/install_util.h"
+#include "ui/gfx/icon_util.h"
+#endif
+
+using content::BrowserThread;
 using views::GridLayout;
 
 namespace {
@@ -44,6 +62,36 @@
 // The number of buckets we want the NumLaterPerReinstall histogram to use.
 const int kNumIgnoredBuckets = 5;
 
+// Adds an elevation icon to |button| when running a system level install.
+void AddElevationIconIfNeeded(views::LabelButton* button) {
+#if defined(OS_WIN)
+  if ((base::win::GetVersion() >= base::win::VERSION_VISTA) &&
+      base::win::UserAccountControlIsEnabled()) {
+    // This code was lifted from chrome/browser/ui/views/infobars/infobar_view.
+    // TODO(mad): Investigate the possibility of moving it to a common place.
+    SHSTOCKICONINFO icon_info = { sizeof(SHSTOCKICONINFO) };
+    // Even with the runtime guard above, we have to use GetProcAddress() here,
+    // because otherwise the loader will try to resolve the function address on
+    // startup, which will break on XP.
+    typedef HRESULT (STDAPICALLTYPE *GetStockIconInfo)(SHSTOCKICONID, UINT,
+                                                       SHSTOCKICONINFO*);
+    GetStockIconInfo func = reinterpret_cast<GetStockIconInfo>(
+        GetProcAddress(GetModuleHandle(L"shell32.dll"), "SHGetStockIconInfo"));
+    if (SUCCEEDED((*func)(SIID_SHIELD, SHGSI_ICON | SHGSI_SMALLICON,
+                          &icon_info))) {
+      scoped_ptr<SkBitmap> icon(IconUtil::CreateSkBitmapFromHICON(
+          icon_info.hIcon, gfx::Size(GetSystemMetrics(SM_CXSMICON),
+                                     GetSystemMetrics(SM_CYSMICON))));
+      if (icon.get()) {
+        button->SetImage(views::Button::STATE_NORMAL,
+                         gfx::ImageSkia::CreateFrom1xBitmap(*icon));
+      }
+      DestroyIcon(icon_info.hIcon);
+    }
+  }
+#endif
+}
+
 }  // namespace
 
 // OutdatedUpgradeBubbleView ---------------------------------------------------
@@ -53,13 +101,16 @@
 
 // static
 void OutdatedUpgradeBubbleView::ShowBubble(views::View* anchor_view,
-                                           content::PageNavigator* navigator) {
+                                           content::PageNavigator* navigator,
+                                           bool auto_update_enabled) {
   if (IsShowing())
     return;
-  upgrade_bubble_ = new OutdatedUpgradeBubbleView(anchor_view, navigator);
+  upgrade_bubble_ = new OutdatedUpgradeBubbleView(
+      anchor_view, navigator, auto_update_enabled);
   views::BubbleDelegateView::CreateBubble(upgrade_bubble_)->Show();
-  content::RecordAction(
-      base::UserMetricsAction("OutdatedUpgradeBubble.Show"));
+  content::RecordAction(base::UserMetricsAction(
+      auto_update_enabled ? "OutdatedUpgradeBubble.Show"
+                          : "OutdatedUpgradeBubble.ShowNoAU"));
 }
 
 bool OutdatedUpgradeBubbleView::IsAvailable() {
@@ -73,12 +124,12 @@
 }
 
 OutdatedUpgradeBubbleView::~OutdatedUpgradeBubbleView() {
-  if (!chose_to_reinstall_ && num_ignored_bubbles_ < kMaxIgnored)
+  if (!accepted_ && num_ignored_bubbles_ < kMaxIgnored)
     ++num_ignored_bubbles_;
 }
 
 views::View* OutdatedUpgradeBubbleView::GetInitiallyFocusedView() {
-  return reinstall_button_;
+  return accept_button_;
 }
 
 void OutdatedUpgradeBubbleView::WindowClosing() {
@@ -90,26 +141,27 @@
 }
 
 void OutdatedUpgradeBubbleView::Init() {
-  base::string16 product_name(
-      l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME));
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  reinstall_button_ = new views::LabelButton(
-      this, l10n_util::GetStringFUTF16(IDS_REINSTALL_APP, product_name));
-  reinstall_button_->SetStyle(views::Button::STYLE_BUTTON);
-  reinstall_button_->SetIsDefault(true);
-  reinstall_button_->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont));
+  accept_button_ = new views::LabelButton(
+      this, l10n_util::GetStringUTF16(
+          auto_update_enabled_ ? IDS_REINSTALL_APP : IDS_REENABLE_UPDATES));
+  accept_button_->SetStyle(views::Button::STYLE_BUTTON);
+  accept_button_->SetIsDefault(true);
+  accept_button_->SetFontList(rb.GetFontList(ui::ResourceBundle::BoldFont));
+  AddElevationIconIfNeeded(accept_button_);
 
   later_button_ = new views::LabelButton(
       this, l10n_util::GetStringUTF16(IDS_LATER));
   later_button_->SetStyle(views::Button::STYLE_BUTTON);
 
   views::Label* title_label = new views::Label(
-      l10n_util::GetStringFUTF16(IDS_UPGRADE_BUBBLE_TITLE, product_name));
+      l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TITLE));
   title_label->SetFontList(rb.GetFontList(ui::ResourceBundle::MediumFont));
   title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
 
-  views::Label* text_label = new views::Label(
-      l10n_util::GetStringFUTF16(IDS_UPGRADE_BUBBLE_TEXT, product_name));
+  views::Label* text_label = new views::Label(l10n_util::GetStringUTF16(
+      auto_update_enabled_ ? IDS_UPGRADE_BUBBLE_TEXT
+                           : IDS_UPGRADE_BUBBLE_REENABLE_TEXT));
   text_label->SetMultiLine(true);
   text_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
 
@@ -157,17 +209,20 @@
   layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
 
   layout->StartRow(0, kButtonsColumnSetId);
-  layout->AddView(reinstall_button_);
+  layout->AddView(accept_button_);
   layout->AddView(later_button_);
 
   AddAccelerator(ui::Accelerator(ui::VKEY_RETURN, ui::EF_NONE));
 }
 
 OutdatedUpgradeBubbleView::OutdatedUpgradeBubbleView(
-    views::View* anchor_view, content::PageNavigator* navigator)
+    views::View* anchor_view,
+    content::PageNavigator* navigator,
+    bool auto_update_enabled)
     : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
-      chose_to_reinstall_(false),
-      reinstall_button_(NULL),
+      auto_update_enabled_(auto_update_enabled),
+      accepted_(false),
+      accept_button_(NULL),
       later_button_(NULL),
       navigator_(navigator) {
   // Compensate for built-in vertical padding in the anchor view's image.
@@ -184,19 +239,39 @@
 }
 
 void OutdatedUpgradeBubbleView::HandleButtonPressed(views::Button* sender) {
-  if (sender == reinstall_button_) {
-    DCHECK(UpgradeDetector::GetInstance()->is_outdated_install());
-    chose_to_reinstall_ = true;
-    UMA_HISTOGRAM_CUSTOM_COUNTS(
-        "OutdatedUpgradeBubble.NumLaterPerReinstall", num_ignored_bubbles_,
-        0, kMaxIgnored, kNumIgnoredBuckets);
-    content::RecordAction(
-        base::UserMetricsAction("OutdatedUpgradeBubble.Reinstall"));
-    navigator_->OpenURL(content::OpenURLParams(GURL(kDownloadChromeUrl),
-                                               content::Referrer(),
-                                               NEW_FOREGROUND_TAB,
-                                               content::PAGE_TRANSITION_LINK,
-                                               false));
+  if (sender == accept_button_) {
+    accepted_ = true;
+    if (auto_update_enabled_) {
+      DCHECK(UpgradeDetector::GetInstance()->is_outdated_install());
+      UMA_HISTOGRAM_CUSTOM_COUNTS(
+          "OutdatedUpgradeBubble.NumLaterPerReinstall", num_ignored_bubbles_,
+          0, kMaxIgnored, kNumIgnoredBuckets);
+      content::RecordAction(
+          base::UserMetricsAction("OutdatedUpgradeBubble.Reinstall"));
+      navigator_->OpenURL(content::OpenURLParams(GURL(kDownloadChromeUrl),
+                                                 content::Referrer(),
+                                                 NEW_FOREGROUND_TAB,
+                                                 content::PAGE_TRANSITION_LINK,
+                                                 false));
+#if defined(OS_WIN)
+    } else {
+      DCHECK(UpgradeDetector::GetInstance()->is_outdated_install_no_au());
+      UMA_HISTOGRAM_CUSTOM_COUNTS(
+          "OutdatedUpgradeBubble.NumLaterPerEnableAU", num_ignored_bubbles_,
+          0, kMaxIgnored, kNumIgnoredBuckets);
+      content::RecordAction(
+          base::UserMetricsAction("OutdatedUpgradeBubble.EnableAU"));
+      // Record that the autoupdate flavour of the dialog has been shown.
+      if (g_browser_process->local_state()) {
+        g_browser_process->local_state()->SetBoolean(
+            prefs::kAttemptedToEnableAutoupdate, true);
+      }
+
+      // Re-enable updates by shelling out to setup.exe in the blocking pool.
+      BrowserThread::PostBlockingPoolTask(FROM_HERE,
+          base::Bind(&google_update::ElevateIfNeededToReenableUpdates));
+#endif  // defined(OS_WIN)
+    }
   } else {
     DCHECK_EQ(later_button_, sender);
     content::RecordAction(
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.h b/chrome/browser/ui/views/outdated_upgrade_bubble_view.h
index 7a66a69..8c410c8 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.h
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.h
@@ -24,7 +24,8 @@
                                   public views::ButtonListener {
  public:
   static void ShowBubble(views::View* anchor_view,
-                         content::PageNavigator* navigator);
+                         content::PageNavigator* navigator,
+                         bool auto_update_enabled);
 
   // Identifies if we are running a build that supports the
   // outdated upgrade bubble view.
@@ -38,7 +39,8 @@
 
  private:
   OutdatedUpgradeBubbleView(views::View* anchor_view,
-                            content::PageNavigator* navigator);
+                            content::PageNavigator* navigator,
+                            bool auto_update_enabled);
   virtual ~OutdatedUpgradeBubbleView();
 
   static bool IsShowing() { return upgrade_bubble_ != NULL; }
@@ -60,11 +62,16 @@
   // reinstall.
   static int num_ignored_bubbles_;
 
-  // Identifies if the reinstall button was hit before closing the bubble.
-  bool chose_to_reinstall_;
+  // Identifies if auto-update is enabled or not.
+  bool auto_update_enabled_;
 
-  // Button that takes the user to the Chrome download page.
-  views::LabelButton* reinstall_button_;
+  // Identifies if the accept button was hit before closing the bubble.
+  bool accepted_;
+
+  // Button that lets the user accept the proposal, which is to navigate to a
+  // Chrome download page when |auto_update_enabled_| is true, or attempt to
+  // re-enable auto-update otherwise.
+  views::LabelButton* accept_button_;
 
   // Button for the user to be reminded later about the outdated upgrade.
   views::LabelButton* later_button_;
diff --git a/chrome/browser/ui/views/panels/panel_frame_view.cc b/chrome/browser/ui/views/panels/panel_frame_view.cc
index 30667d9..8bc56a8 100644
--- a/chrome/browser/ui/views/panels/panel_frame_view.cc
+++ b/chrome/browser/ui/views/panels/panel_frame_view.cc
@@ -18,6 +18,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/path.h"
+#include "ui/gfx/screen.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/widget/widget.h"
@@ -578,10 +579,18 @@
 }
 
 bool PanelFrameView::OnMouseDragged(const ui::MouseEvent& event) {
+#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+  // Converting the mouse location to screen coordinates returns an incorrect
+  // location while the panel is moving. See crbug.com/353393 for more details.
+  // TODO(pkotwicz): Fix conversion to screen coordinates
+  gfx::Screen* screen = gfx::Screen::GetNativeScreen();
+  gfx::Point mouse_location = screen->GetCursorScreenPoint();
+#else
   // |event.location| is in the view's coordinate system. Convert it to the
   // screen coordinate system.
   gfx::Point mouse_location = event.location();
   views::View::ConvertPointToScreen(this, &mouse_location);
+#endif
 
   if (panel_view_->OnTitlebarMouseDragged(mouse_location))
     return true;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
index 58f4d83..7de7836 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_bubble_view.cc
@@ -324,6 +324,7 @@
 
     manage_link_ =
         new views::Link(manage_passwords_bubble_model_->manage_link());
+    manage_link_->SetUnderline(false);
     manage_link_->set_listener(this);
     layout->StartRowWithPadding(0, kSingleButtonSetId,
                                 0, views::kRelatedControlVerticalSpacing);
diff --git a/chrome/browser/ui/views/profile_chooser_view.cc b/chrome/browser/ui/views/profile_chooser_view.cc
index 259503d..f1f11dd 100644
--- a/chrome/browser/ui/views/profile_chooser_view.cc
+++ b/chrome/browser/ui/views/profile_chooser_view.cc
@@ -7,6 +7,7 @@
 #include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/lifetime/application_lifetime.h"
 #include "chrome/browser/profiles/profile_info_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_window.h"
@@ -20,9 +21,10 @@
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/views/user_manager_view.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/profile_management_switches.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/mutable_profile_oauth2_token_service.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
@@ -35,6 +37,7 @@
 #include "ui/gfx/text_elider.h"
 #include "ui/native_theme/native_theme.h"
 #include "ui/views/controls/button/blue_button.h"
+#include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/controls/button/menu_button.h"
 #include "ui/views/controls/label.h"
@@ -53,6 +56,9 @@
 const int kFixedMenuWidth = 250;
 const int kButtonHeight = 29;
 const int kProfileAvatarTutorialShowMax = 5;
+const int kFixedGaiaViewHeight = 400;
+const int kFixedGaiaViewWidth = 360;
+const int kFixedAccountRemovalViewWidth = 280;
 
 // Creates a GridLayout with a single column. This ensures that all the child
 // views added get auto-expanded to fill the full width of the bubble.
@@ -120,8 +126,6 @@
   SetImage(STATE_NORMAL, normal_icon);
   SetImage(STATE_HOVERED, hover_icon);
   SetImage(STATE_PRESSED, hover_icon);
-  SetTextColor(STATE_HOVERED, GetNativeTheme()->GetSystemColor(
-      ui::NativeTheme::kColorId_SelectedMenuItemForegroundColor));
 }
 
 BackgroundColorHoverButton::~BackgroundColorHoverButton() {}
@@ -129,7 +133,7 @@
 void BackgroundColorHoverButton::OnPaint(gfx::Canvas* canvas) {
   if ((state() == STATE_PRESSED) || (state() == STATE_HOVERED) || HasFocus()) {
     canvas->DrawColor(GetNativeTheme()->GetSystemColor(
-        ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor));
+        ui::NativeTheme::kColorId_MenuSeparatorColor));
   }
   LabelButton::OnPaint(canvas);
 }
@@ -283,6 +287,53 @@
   DISALLOW_COPY_AND_ASSIGN(EditableProfileName);
 };
 
+// A title card with one back button right aligned and one label center aligned.
+class TitleCard : public views::View {
+ public:
+   TitleCard(int message_id, views::ButtonListener* listener,
+             views::ImageButton** back_button) {
+    back_button_ = new views::ImageButton(listener);
+    back_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT,
+                                    views::ImageButton::ALIGN_MIDDLE);
+    ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
+    back_button_->SetImage(views::ImageButton::STATE_NORMAL,
+                           rb->GetImageSkiaNamed(IDR_BACK));
+    back_button_->SetImage(views::ImageButton::STATE_HOVERED,
+                           rb->GetImageSkiaNamed(IDR_BACK_H));
+    back_button_->SetImage(views::ImageButton::STATE_PRESSED,
+                           rb->GetImageSkiaNamed(IDR_BACK_P));
+    back_button_->SetImage(views::ImageButton::STATE_DISABLED,
+                           rb->GetImageSkiaNamed(IDR_BACK_D));
+    *back_button = back_button_;
+
+    title_label_ = new views::Label(l10n_util::GetStringUTF16(message_id));
+    title_label_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+    const gfx::FontList& medium_font_list =
+        rb->GetFontList(ui::ResourceBundle::MediumFont);
+    title_label_->SetFontList(medium_font_list);
+
+    AddChildView(back_button_);
+    AddChildView(title_label_);
+  }
+
+ private:
+  virtual void Layout() OVERRIDE{
+    back_button_->SetBoundsRect(GetContentsBounds());
+    title_label_->SetBoundsRect(GetContentsBounds());
+  }
+
+  virtual gfx::Size GetPreferredSize() OVERRIDE{
+    int height = profiles::kAvatarIconPadding * 2 +
+        std::max(title_label_->GetPreferredSize().height(),
+                 back_button_->GetPreferredSize().height());
+    return gfx::Size(width(), height);
+  }
+
+  views::ImageButton* back_button_;
+  views::Label* title_label_;
+
+  DISALLOW_COPY_AND_ASSIGN(TitleCard);
+};
 
 // ProfileChooserView ---------------------------------------------------------
 
@@ -292,15 +343,12 @@
 
 // static
 void ProfileChooserView::ShowBubble(
+    BubbleViewMode view_mode,
     views::View* anchor_view,
     views::BubbleBorder::Arrow arrow,
     views::BubbleBorder::BubbleAlignment border_alignment,
     const gfx::Rect& anchor_rect,
     Browser* browser) {
-  if (IsShowing())
-    // TODO(bcwhite): handle case where we should show on different window
-    return;
-
   profile_bubble_ = new ProfileChooserView(
       anchor_view, arrow, anchor_rect, browser);
   views::BubbleDelegateView::CreateBubble(profile_bubble_);
@@ -308,6 +356,9 @@
   profile_bubble_->SetAlignment(border_alignment);
   profile_bubble_->GetWidget()->Show();
   profile_bubble_->SetArrowPaintType(views::BubbleBorder::PAINT_NONE);
+
+  if (view_mode != BUBBLE_VIEW_MODE_PROFILE_CHOOSER)
+    profile_bubble_->ShowView(view_mode, profile_bubble_->avatar_menu_.get());
 }
 
 // static
@@ -327,13 +378,17 @@
                                        Browser* browser)
     : BubbleDelegateView(anchor_view, arrow),
       browser_(browser),
-      view_mode_(PROFILE_CHOOSER_VIEW),
+      view_mode_(BUBBLE_VIEW_MODE_PROFILE_CHOOSER),
       tutorial_showing_(false) {
   // Reset the default margins inherited from the BubbleDelegateView.
   set_margins(gfx::Insets());
 
   ResetView();
 
+  set_background(views::Background::CreateSolidBackground(
+      GetNativeTheme()->GetSystemColor(
+          ui::NativeTheme::kColorId_DialogBackground)));
+
   avatar_menu_.reset(new AvatarMenu(
       &g_browser_process->profile_manager()->GetProfileInfoCache(),
       this,
@@ -355,24 +410,23 @@
 
 void ProfileChooserView::ResetView() {
   manage_accounts_link_ = NULL;
-  signout_current_profile_link_ = NULL;
   signin_current_profile_link_ = NULL;
-  guest_button_ = NULL;
-  end_guest_button_ = NULL;
   users_button_ = NULL;
-  add_user_button_ = NULL;
+  lock_button_ = NULL;
   add_account_button_ = NULL;
   current_profile_photo_ = NULL;
   current_profile_name_ = NULL;
   tutorial_ok_button_ = NULL;
   tutorial_learn_more_link_ = NULL;
+  account_removal_cancel_button_ = NULL;
+  gaia_signin_cancel_button_ = NULL;
   open_other_profile_indexes_map_.clear();
   current_profile_accounts_map_.clear();
   tutorial_showing_ = false;
 }
 
 void ProfileChooserView::Init() {
-  ShowView(PROFILE_CHOOSER_VIEW, avatar_menu_.get());
+  ShowView(BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu_.get());
 }
 
 void ProfileChooserView::OnAvatarMenuChanged(
@@ -380,32 +434,32 @@
   // Refresh the view with the new menu. We can't just update the local copy
   // as this may have been triggered by a sign out action, in which case
   // the view is being destroyed.
-  ShowView(PROFILE_CHOOSER_VIEW, avatar_menu);
+  ShowView(BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu);
 }
 
 void ProfileChooserView::OnRefreshTokenAvailable(
     const std::string& account_id) {
   // Refresh the account management view when a new account is added to the
   // profile.
-  if (view_mode_ == ACCOUNT_MANAGEMENT_VIEW ||
-      view_mode_ == GAIA_SIGNIN_VIEW ||
-      view_mode_ == GAIA_ADD_ACCOUNT_VIEW) {
-    ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_.get());
+  if (view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT ||
+      view_mode_ == BUBBLE_VIEW_MODE_GAIA_SIGNIN ||
+      view_mode_ == BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT) {
+    ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
   }
 }
 
 void ProfileChooserView::OnRefreshTokenRevoked(const std::string& account_id) {
   // Refresh the account management view when an account is removed from the
   // profile.
-  if (view_mode_ == ACCOUNT_MANAGEMENT_VIEW)
-    ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_.get());
+  if (view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT)
+    ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
 }
 
 void ProfileChooserView::ShowView(BubbleViewMode view_to_display,
                                   AvatarMenu* avatar_menu) {
   // The account management view should only be displayed if the active profile
   // is signed in.
-  if (view_to_display == ACCOUNT_MANAGEMENT_VIEW) {
+  if (view_to_display == BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT) {
     const AvatarMenu::Item& active_item = avatar_menu->GetItemAt(
         avatar_menu->GetActiveProfileIndex());
     DCHECK(active_item.signed_in);
@@ -417,25 +471,15 @@
   RemoveAllChildViews(true);
   view_mode_ = view_to_display;
 
-  if (view_to_display == GAIA_SIGNIN_VIEW ||
-      view_to_display == GAIA_ADD_ACCOUNT_VIEW) {
-    // Minimum size for embedded sign in pages as defined in Gaia.
-    const int kMinGaiaViewWidth = 320;
-    const int kMinGaiaViewHeight = 440;
-    Profile* profile = browser_->profile();
-    views::WebView* web_view = new views::WebView(profile);
-    signin::Source source = (view_to_display == GAIA_SIGNIN_VIEW) ?
-        signin::SOURCE_AVATAR_BUBBLE_SIGN_IN :
-        signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT;
-    GURL url(signin::GetPromoURL(
-        source, false /* auto_close */, true /* is_constrained */));
-    web_view->LoadInitialURL(url);
-    views::GridLayout* layout =
-        CreateSingleColumnLayout(this, kMinGaiaViewWidth);
+  if (view_mode_ == BUBBLE_VIEW_MODE_GAIA_SIGNIN ||
+      view_mode_ == BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT ||
+      view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL) {
+    bool is_removal_view = view_mode_ == BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL;
+    views::GridLayout* layout = CreateSingleColumnLayout(this,
+        is_removal_view ? kFixedAccountRemovalViewWidth : kFixedGaiaViewWidth);
     layout->StartRow(1, 0);
-    layout->AddView(web_view);
-    layout->set_minimum_size(
-        gfx::Size(kMinGaiaViewWidth, kMinGaiaViewHeight));
+    layout->AddView(is_removal_view ? CreateAccountRemovalView():
+        CreateGaiaSigninView(view_mode_ == BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT));
     Layout();
     if (GetBubbleFrameView())
       SizeToContents();
@@ -445,21 +489,21 @@
   views::GridLayout* layout = CreateSingleColumnLayout(this, kFixedMenuWidth);
   // Separate items into active and alternatives.
   Indexes other_profiles;
-  bool is_guest_view = true;
   views::View* tutorial_view = NULL;
   views::View* current_profile_view = NULL;
   views::View* current_profile_accounts = NULL;
+  views::View* option_buttons_view = NULL;
   for (size_t i = 0; i < avatar_menu->GetNumberOfItems(); ++i) {
     const AvatarMenu::Item& item = avatar_menu->GetItemAt(i);
     if (item.active) {
-      if (view_to_display == PROFILE_CHOOSER_VIEW) {
+      option_buttons_view = CreateOptionsView(item.signed_in);
+      if (view_to_display == BUBBLE_VIEW_MODE_PROFILE_CHOOSER) {
         tutorial_view = CreateTutorialView(item, tutorial_shown);
         current_profile_view = CreateCurrentProfileView(item, false);
       } else {
         current_profile_view = CreateCurrentProfileEditableView(item);
         current_profile_accounts = CreateCurrentProfileAccountsView(item);
       }
-      is_guest_view = false;
     } else {
       other_profiles.push_back(i);
     }
@@ -472,15 +516,19 @@
     layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
   }
 
-  if (!current_profile_view)  // Guest windows don't have an active profile.
+  if (!current_profile_view) {
+    // Guest windows don't have an active profile.
     current_profile_view = CreateGuestProfileView();
+    option_buttons_view = CreateOptionsView(false);
+  }
 
   layout->StartRow(1, 0);
   layout->AddView(current_profile_view);
 
-  if (view_to_display == PROFILE_CHOOSER_VIEW) {
+  if (view_to_display == BUBBLE_VIEW_MODE_PROFILE_CHOOSER) {
     layout->StartRow(1, 0);
-    layout->AddView(CreateOtherProfilesView(other_profiles));
+    if (switches::IsFastUserSwitching())
+      layout->AddView(CreateOtherProfilesView(other_profiles));
   } else {
     DCHECK(current_profile_accounts);
     layout->StartRow(0, 0);
@@ -493,7 +541,6 @@
   layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
 
   // Action buttons.
-  views::View* option_buttons_view = CreateOptionsView(is_guest_view);
   layout->StartRow(0, 0);
   layout->AddView(option_buttons_view);
 
@@ -515,24 +562,12 @@
   if (sender->parent())
     sender->SetEnabled(false);
 
-  if (sender == guest_button_) {
-    profiles::SwitchToGuestProfile(browser_->host_desktop_type(),
-                                   profiles::ProfileSwitchingDoneCallback());
-  } else if (sender == end_guest_button_) {
-    profiles::CloseGuestProfileWindows();
-  } else if (sender == users_button_) {
-    // Guest users cannot appear in the User Manager, nor display a tutorial.
-    profiles::ShowUserManagerMaybeWithTutorial(
-        end_guest_button_ ? NULL : browser_->profile());
-  } else if (sender == add_user_button_) {
-    profiles::CreateAndSwitchToNewProfile(
-        browser_->host_desktop_type(),
-        profiles::ProfileSwitchingDoneCallback(),
-        ProfileMetrics::ADD_NEW_USER_ICON);
+  if (sender == users_button_) {
+    chrome::ShowUserManager(base::FilePath());
+  } else if (sender == lock_button_) {
+    profiles::LockProfile(browser_->profile());
   } else if (sender == add_account_button_) {
-    ShowView(GAIA_ADD_ACCOUNT_VIEW, avatar_menu_.get());
-  } else if (sender == current_profile_photo_->change_photo_button()) {
-    avatar_menu_->EditProfile(avatar_menu_->GetActiveProfileIndex());
+    ShowView(BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT, avatar_menu_.get());
   } else if (sender == tutorial_ok_button_) {
     // If the user manually dismissed the tutorial, never show it again by
     // setting the number of times shown to the maximum plus 1, so that later we
@@ -540,7 +575,22 @@
     // is indeed shown for the maximum number of times.
     browser_->profile()->GetPrefs()->SetInteger(
         prefs::kProfileAvatarTutorialShown, kProfileAvatarTutorialShowMax + 1);
-    ShowView(PROFILE_CHOOSER_VIEW, avatar_menu_.get());
+    ShowView(BUBBLE_VIEW_MODE_PROFILE_CHOOSER, avatar_menu_.get());
+  } else if (sender == remove_account_and_relaunch_button_) {
+    RemoveAccount();
+  } else if (sender == account_removal_cancel_button_) {
+    account_id_to_remove_.clear();
+    ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
+  } else if (sender == gaia_signin_cancel_button_) {
+    std::string primary_account =
+        SigninManagerFactory::GetForProfile(browser_->profile())->
+        GetAuthenticatedUsername();
+    ShowView(primary_account.empty() ? BUBBLE_VIEW_MODE_PROFILE_CHOOSER :
+                                       BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT,
+             avatar_menu_.get());
+  } else if (current_profile_photo_ &&
+             sender == current_profile_photo_->change_photo_button()) {
+    avatar_menu_->EditProfile(avatar_menu_->GetActiveProfileIndex());
   } else {
     // One of the "other profiles" buttons was pressed.
     ButtonIndexes::const_iterator match =
@@ -558,20 +608,26 @@
   AccountButtonIndexes::const_iterator match =
       current_profile_accounts_map_.find(source);
   DCHECK(match != current_profile_accounts_map_.end());
+  account_id_to_remove_ = match->second;
+  ShowView(BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL, avatar_menu_.get());
+}
 
+void ProfileChooserView::RemoveAccount() {
+  DCHECK(!account_id_to_remove_.empty());
   MutableProfileOAuth2TokenService* oauth2_token_service =
       ProfileOAuth2TokenServiceFactory::GetPlatformSpecificForProfile(
-          browser_->profile());
+      browser_->profile());
   if (oauth2_token_service)
-    oauth2_token_service->RevokeCredentials(match->second);
+    oauth2_token_service->RevokeCredentials(account_id_to_remove_);
+  account_id_to_remove_.clear();
+
+  chrome::AttemptRestart();
 }
 
 void ProfileChooserView::LinkClicked(views::Link* sender, int event_flags) {
   if (sender == manage_accounts_link_) {
     // ShowView() will DCHECK if this view is displayed for non signed-in users.
-    ShowView(ACCOUNT_MANAGEMENT_VIEW, avatar_menu_.get());
-  } else if (sender == signout_current_profile_link_) {
-    profiles::LockProfile(browser_->profile());
+    ShowView(BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT, avatar_menu_.get());
   } else if (sender == tutorial_learn_more_link_) {
     // TODO(guohui): update |learn_more_url| once it is decided.
     const GURL lear_more_url("https://support.google.com/chrome/?hl=en#to");
@@ -583,7 +639,7 @@
     chrome::Navigate(&params);
   } else {
     DCHECK(sender == signin_current_profile_link_);
-    ShowView(GAIA_SIGNIN_VIEW, avatar_menu_.get());
+    ShowView(BUBBLE_VIEW_MODE_GAIA_SIGNIN, avatar_menu_.get());
   }
 }
 
@@ -749,14 +805,11 @@
     manage_accounts_link_ = CreateLink(
         l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_MANAGE_ACCOUNTS_BUTTON),
         this);
-    signout_current_profile_link_ = CreateLink(
-        l10n_util::GetStringUTF16(IDS_PROFILES_PROFILE_SIGNOUT_BUTTON), this);
-    layout->StartRow(1, 0);
-    layout->SkipColumns(1);
-    layout->AddView(signout_current_profile_link_);
     layout->StartRow(1, 0);
     layout->SkipColumns(1);
     layout->AddView(manage_accounts_link_);
+    layout->StartRow(1, 0);
+    layout->SkipColumns(1);
   } else {
     signin_current_profile_link_ = CreateLink(
         l10n_util::GetStringFUTF16(
@@ -849,49 +902,52 @@
   return view;
 }
 
-views::View* ProfileChooserView::CreateOptionsView(bool is_guest_view) {
+views::View* ProfileChooserView::CreateOptionsView(bool enable_lock) {
   views::View* view = new views::View();
-  views::GridLayout* layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
+  views::GridLayout* layout;
+
+  // Only signed-in users have the ability to lock.
+  if (enable_lock) {
+    layout = new views::GridLayout(view);
+    views::ColumnSet* columns = layout->AddColumnSet(0);
+    int width_of_lock_button =
+        2 * views::kUnrelatedControlLargeHorizontalSpacing + 12;
+    int width_of_users_button = kFixedMenuWidth - width_of_lock_button;
+    columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
+                       views::GridLayout::FIXED, width_of_users_button,
+                       width_of_users_button);
+    columns->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 0,
+                       views::GridLayout::FIXED, width_of_lock_button,
+                       width_of_lock_button);
+    view->SetLayoutManager(layout);
+  } else {
+    layout = CreateSingleColumnLayout(view, kFixedMenuWidth);
+  }
+
   // The horizontal padding will be set by each button individually, so that
   // in the hovered state the button spans the entire parent view.
   layout->SetInsets(views::kRelatedControlVerticalSpacing, 0,
                     views::kRelatedControlVerticalSpacing, 0);
 
   ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
-
-  layout->StartRow(1, 0);
-  if (is_guest_view) {
-    end_guest_button_ = new BackgroundColorHoverButton(
-        this,
-        l10n_util::GetStringUTF16(IDS_PROFILES_EXIT_GUEST_BUTTON),
-        *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST),
-        *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST_WHITE));
-    layout->AddView(end_guest_button_);
-  } else {
-    guest_button_ = new BackgroundColorHoverButton(
-        this,
-        l10n_util::GetStringUTF16(IDS_PROFILES_GUEST_BUTTON),
-        *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST),
-        *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_BROWSE_GUEST_WHITE));
-    layout->AddView(guest_button_);
-  }
-
-  add_user_button_ = new BackgroundColorHoverButton(
-      this,
-      l10n_util::GetStringUTF16(IDS_PROFILES_ADD_PERSON_BUTTON),
-      *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER),
-      *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER_WHITE));
-  layout->StartRow(1, 0);
-  layout->AddView(add_user_button_);
-
   users_button_ = new BackgroundColorHoverButton(
       this,
-      l10n_util::GetStringUTF16(IDS_PROFILES_ALL_PEOPLE_BUTTON),
-      *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER),
-      *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_ADD_USER_WHITE));
+      l10n_util::GetStringFUTF16(IDS_PROFILES_NOT_YOU_BUTTON,
+          profiles::GetAvatarNameForProfile(browser_->profile())),
+      *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_AVATAR),
+      *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_AVATAR));
+
   layout->StartRow(1, 0);
   layout->AddView(users_button_);
 
+  if (enable_lock) {
+    lock_button_ = new BackgroundColorHoverButton(
+        this,
+        base::string16(),
+        *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_LOCK),
+        *rb->GetImageSkiaNamed(IDR_ICON_PROFILES_MENU_LOCK));
+    layout->AddView(lock_button_);
+  }
   return view;
 }
 
@@ -946,16 +1002,110 @@
       gfx::ElideEmail(base::UTF8ToUTF16(account),
                       rb->GetFontList(ui::ResourceBundle::BaseFont),
                       width - menu_marker->width()),
-      is_primary_account ? NULL : this,  // Cannot delete the primary account.
-      !is_primary_account);
+      this,
+      true /* show_menu_marker */);
   email_button->SetBorder(views::Border::CreateEmptyBorder(0, 0, 0, 0));
-  if (!is_primary_account) {
-    email_button->set_menu_marker(menu_marker);
+  email_button->set_menu_marker(menu_marker);
+  if (!is_primary_account)
     layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
-  }
   layout->StartRow(1, 0);
   layout->AddView(email_button);
 
   // Save the original email address, as the button text could be elided.
   current_profile_accounts_map_[email_button] = account;
 }
+
+views::View* ProfileChooserView::CreateGaiaSigninView(
+    bool add_secondary_account) {
+  views::View* view = new views::View();
+  views::GridLayout* layout =
+      CreateSingleColumnLayout(view, kFixedGaiaViewWidth);
+
+  // Adds title.
+  views::View* padded_title = new views::View();
+  int available_width = kFixedGaiaViewWidth - 2 * views::kButtonHEdgeMarginNew;
+  views::GridLayout* padded_layout = CreateSingleColumnLayout(
+      padded_title, available_width);
+  padded_layout->SetInsets(views::kButtonVEdgeMarginNew,
+                           views::kButtonHEdgeMarginNew,
+                           views::kButtonVEdgeMarginNew,
+                           views::kButtonHEdgeMarginNew);
+  padded_layout->StartRow(1, 0);
+  padded_layout->AddView(new TitleCard(
+      add_secondary_account ? IDS_PROFILES_GAIA_ADD_ACCOUNT_TITLE :
+                              IDS_PROFILES_GAIA_SIGNIN_TITLE,
+      this, &gaia_signin_cancel_button_));
+
+  layout->StartRow(1, 0);
+  layout->AddView(padded_title);
+  layout->StartRow(1, 0);
+  layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
+
+  // Adds Gaia signin webview
+  Profile* profile = browser_->profile();
+  views::WebView* web_view = new views::WebView(profile);
+  signin::Source source = add_secondary_account ?
+      signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT :
+      signin::SOURCE_AVATAR_BUBBLE_SIGN_IN;
+  GURL url(signin::GetPromoURL(
+      source, false /* auto_close */, true /* is_constrained */));
+  web_view->LoadInitialURL(url);
+  web_view->SetPreferredSize(
+      gfx::Size(kFixedGaiaViewWidth, kFixedGaiaViewHeight));
+
+  layout->StartRow(1, 0);
+  layout->AddView(web_view);
+
+  return view;
+}
+
+views::View* ProfileChooserView::CreateAccountRemovalView() {
+  views::View* view = new views::View();
+  views::GridLayout* layout = CreateSingleColumnLayout(
+      view, kFixedAccountRemovalViewWidth - 2 * views::kButtonHEdgeMarginNew);
+  layout->SetInsets(views::kButtonVEdgeMarginNew,
+                    views::kButtonHEdgeMarginNew,
+                    views::kButtonVEdgeMarginNew,
+                    views::kButtonHEdgeMarginNew);
+
+  // Adds title.
+  layout->StartRow(1, 0);
+  layout->AddView(new TitleCard(IDS_PROFILES_ACCOUNT_REMOVAL_TITLE, this,
+                                &account_removal_cancel_button_));
+  layout->StartRowWithPadding(1, 0, 0, views::kRelatedControlVerticalSpacing);
+  layout->AddView(new views::Separator(views::Separator::HORIZONTAL));
+
+  const std::string& primary_account = SigninManagerFactory::GetForProfile(
+      browser_->profile())->GetAuthenticatedUsername();
+  bool is_primary_account = primary_account == account_id_to_remove_;
+
+  // Adds main text.
+  views::Label* content_label = new views::Label(is_primary_account ?
+      l10n_util::GetStringFUTF16(IDS_PROFILES_PRIMARY_ACCOUNT_REMOVAL_TEXT,
+                                 base::UTF8ToUTF16(account_id_to_remove_)) :
+      l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_TEXT));
+
+  content_label->SetMultiLine(true);
+  content_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+  ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
+  const gfx::FontList& small_font_list =
+      rb->GetFontList(ui::ResourceBundle::SmallFont);
+  content_label->SetFontList(small_font_list);
+  layout->StartRowWithPadding(1, 0, 0, views::kUnrelatedControlVerticalSpacing);
+  layout->AddView(content_label);
+
+  // Adds button.
+  if (!is_primary_account) {
+    remove_account_and_relaunch_button_ = new views::BlueButton(
+        this, l10n_util::GetStringUTF16(IDS_PROFILES_ACCOUNT_REMOVAL_BUTTON));
+    remove_account_and_relaunch_button_->SetHorizontalAlignment(
+        gfx::ALIGN_CENTER);
+    layout->StartRowWithPadding(
+        1, 0, 0, views::kUnrelatedControlVerticalSpacing);
+    layout->AddView(remove_account_and_relaunch_button_);
+  } else {
+    layout->AddPaddingRow(0, views::kUnrelatedControlVerticalSpacing);
+  }
+
+  return view;
+}
diff --git a/chrome/browser/ui/views/profile_chooser_view.h b/chrome/browser/ui/views/profile_chooser_view.h
index 3cfb113..b697d0d 100644
--- a/chrome/browser/ui/views/profile_chooser_view.h
+++ b/chrome/browser/ui/views/profile_chooser_view.h
@@ -10,6 +10,7 @@
 
 #include "chrome/browser/profiles/avatar_menu.h"
 #include "chrome/browser/profiles/avatar_menu_observer.h"
+#include "chrome/browser/ui/browser_window.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "ui/views/bubble/bubble_delegate.h"
 #include "ui/views/controls/button/button.h"
@@ -27,6 +28,7 @@
 
 namespace views {
 class GridLayout;
+class ImageButton;
 class Link;
 class LabelButton;
 }
@@ -43,12 +45,27 @@
                            public AvatarMenuObserver,
                            public OAuth2TokenService::Observer {
  public:
+  // Different views that can be displayed in the bubble.
+  enum BubbleViewMode {
+    // Shows a "fast profile switcher" view.
+    BUBBLE_VIEW_MODE_PROFILE_CHOOSER,
+    // Shows a list of accounts for the active user.
+    BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT,
+    // Shows a web view for primary sign in.
+    BUBBLE_VIEW_MODE_GAIA_SIGNIN,
+    // Shows a web view for adding secondary accounts.
+    BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT,
+    // Shows a view for confirming account removal.
+    BUBBLE_VIEW_MODE_ACCOUNT_REMOVAL
+  };
+
   // Shows the bubble if one is not already showing.  This allows us to easily
   // make a button toggle the bubble on and off when clicked: we unconditionally
   // call this function when the button is clicked and if the bubble isn't
   // showing it will appear while if it is showing, nothing will happen here and
   // the existing bubble will auto-close due to focus loss.
-  static void ShowBubble(views::View* anchor_view,
+  static void ShowBubble(BubbleViewMode view_mode,
+                         views::View* anchor_view,
                          views::BubbleBorder::Arrow arrow,
                          views::BubbleBorder::BubbleAlignment border_alignment,
                          const gfx::Rect& anchor_rect,
@@ -71,14 +88,6 @@
   typedef std::map<views::Button*, int> ButtonIndexes;
   typedef std::map<views::View*, std::string> AccountButtonIndexes;
 
-  // Different views that can be displayed in the bubble.
-  enum BubbleViewMode {
-    PROFILE_CHOOSER_VIEW,     // Shows a "fast profile switcher" view.
-    ACCOUNT_MANAGEMENT_VIEW,  // Shows a list of accounts for the active user.
-    GAIA_SIGNIN_VIEW,         // Shows a web view for primary sign in.
-    GAIA_ADD_ACCOUNT_VIEW     // Shows a web view for adding secondary accounts.
-  };
-
   ProfileChooserView(views::View* anchor_view,
                      views::BubbleBorder::Arrow arrow,
                      const gfx::Rect& anchor_rect,
@@ -132,7 +141,7 @@
       bool is_guest);
   views::View* CreateGuestProfileView();
   views::View* CreateOtherProfilesView(const Indexes& avatars_to_show);
-  views::View* CreateOptionsView(bool is_guest_view);
+  views::View* CreateOptionsView(bool enable_lock);
 
   // Account Management view for the profile |avatar_item|.
   views::View* CreateCurrentProfileEditableView(
@@ -144,6 +153,14 @@
                            bool is_primary_account,
                            int width);
 
+  // Creates a webview showing the gaia signin page.
+  views::View* CreateGaiaSigninView(bool add_secondary_account);
+
+  // Creates a view to confirm account removal for |account_id_to_remove_|.
+  views::View* CreateAccountRemovalView();
+
+  void RemoveAccount();
+
   scoped_ptr<AvatarMenu> avatar_menu_;
   Browser* browser_;
 
@@ -159,7 +176,6 @@
 
   // Links displayed in the active profile card.
   views::Link* manage_accounts_link_;
-  views::Link* signout_current_profile_link_;
   views::Link* signin_current_profile_link_;
 
   // The profile name and photo in the active profile card. Owned by the
@@ -168,12 +184,20 @@
   EditableProfileName* current_profile_name_;
 
   // Action buttons.
-  views::LabelButton* guest_button_;
-  views::LabelButton* end_guest_button_;
-  views::LabelButton* add_user_button_;
   views::LabelButton* users_button_;
+  views::LabelButton* lock_button_;
   views::LabelButton* add_account_button_;
 
+  // Buttons displayed in the gaia signin view.
+  views::ImageButton* gaia_signin_cancel_button_;
+
+  // Links and buttons displayed in the account removal view.
+  views::LabelButton* remove_account_and_relaunch_button_;
+  views::ImageButton* account_removal_cancel_button_;
+
+  // Records the account id to remove.
+  std::string account_id_to_remove_;
+
   // Active view mode.
   BubbleViewMode view_mode_;
 
diff --git a/chrome/browser/ui/views/screen_capture_notification_ui_views.cc b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
index 94819e3..1001736 100644
--- a/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
+++ b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
@@ -24,13 +24,18 @@
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/wm/core/shadow_types.h"
 
+#if defined(OS_WIN)
+#include "ui/views/win/hwnd_util.h"
+#endif
+
 namespace {
 
 const int kMinimumWidth = 460;
 const int kMaximumWidth = 1000;
 const int kHorizontalMargin = 10;
-const int kPadding = 5;
-const int kPaddingLeft = 10;
+const float kWindowAlphaValue = 0.85f;
+const int kPaddingVertical = 5;
+const int kPaddingHorizontal = 10;
 
 namespace {
 
@@ -79,7 +84,8 @@
   virtual ~ScreenCaptureNotificationUIViews();
 
   // ScreenCaptureNotificationUI interface.
-  virtual void OnStarted(const base::Closure& stop_callback) OVERRIDE;
+  virtual gfx::NativeViewId OnStarted(const base::Closure& stop_callback)
+      OVERRIDE;
 
   // views::View overrides.
   virtual gfx::Size GetPreferredSize() OVERRIDE;
@@ -150,6 +156,7 @@
   hide_link_ = new views::Link(
       l10n_util::GetStringUTF16(IDS_PASSWORDS_PAGE_VIEW_HIDE_BUTTON));
   hide_link_->set_listener(this);
+  hide_link_->SetUnderline(false);
   AddChildView(hide_link_);
 }
 
@@ -158,7 +165,7 @@
   delete GetWidget();
 }
 
-void ScreenCaptureNotificationUIViews::OnStarted(
+gfx::NativeViewId ScreenCaptureNotificationUIViews::OnStarted(
     const base::Closure& stop_callback) {
   stop_callback_ = stop_callback;
 
@@ -202,8 +209,14 @@
       work_area.y() + work_area.height() - size.height(),
       size.width(), size.height());
   widget->SetBounds(bounds);
-
+  widget->SetOpacity(0xFF * kWindowAlphaValue);
   widget->Show();
+
+#if defined(OS_WIN)
+  return gfx::NativeViewId(views::HWNDForWidget(widget));
+#else
+  return 0;
+#endif
 }
 
 gfx::Size ScreenCaptureNotificationUIViews::GetPreferredSize() {
@@ -268,7 +281,10 @@
 ScreenCaptureNotificationUIViews::CreateNonClientFrameView(
     views::Widget* widget) {
   views::BubbleFrameView* frame = new views::BubbleFrameView(
-      gfx::Insets(kPadding, kPaddingLeft, kPadding, kPadding));
+      gfx::Insets(kPaddingVertical,
+                  kPaddingHorizontal,
+                  kPaddingVertical,
+                  kPaddingHorizontal));
   SkColor color = widget->GetNativeTheme()->GetSystemColor(
       ui::NativeTheme::kColorId_DialogBackground);
   frame->SetBubbleBorder(scoped_ptr<views::BubbleBorder>(
diff --git a/chrome/browser/ui/views/settings_api_bubble_helper_views.cc b/chrome/browser/ui/views/settings_api_bubble_helper_views.cc
new file mode 100644
index 0000000..5a91d26
--- /dev/null
+++ b/chrome/browser/ui/views/settings_api_bubble_helper_views.cc
@@ -0,0 +1,157 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/settings_api_bubble_helper_views.h"
+
+#include "chrome/browser/extensions/settings_api_bubble_controller.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/views/extensions/extension_message_bubble_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/settings_api_bubble_helper_views.h"
+#include "chrome/browser/ui/views/toolbar/home_button.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
+#include "content/public/browser/browser_context.h"
+#include "extensions/browser/extension_registry.h"
+
+namespace {
+
+void ShowSettingsApiBubble(extensions::SettingsApiOverrideType type,
+                           const std::string& extension_id,
+                           Profile* profile,
+                           views::View* anchor_view,
+                           views::BubbleBorder::Arrow arrow) {
+  scoped_ptr<extensions::SettingsApiBubbleController> settings_api_bubble(
+      new extensions::SettingsApiBubbleController(profile, type));
+  if (!settings_api_bubble->ShouldShow(extension_id))
+    return;
+
+  extensions::SettingsApiBubbleController* controller =
+      settings_api_bubble.get();
+  extensions::ExtensionMessageBubbleView* bubble_delegate =
+      new extensions::ExtensionMessageBubbleView(
+          anchor_view,
+          arrow,
+          settings_api_bubble.PassAs<
+              extensions::ExtensionMessageBubbleController>());
+  views::BubbleDelegateView::CreateBubble(bubble_delegate);
+  controller->Show(bubble_delegate);
+}
+
+}  // namespace
+
+namespace extensions {
+
+void MaybeShowExtensionControlledHomeNotification(Browser* browser) {
+#if !defined(OS_WIN)
+  return;
+#endif
+
+  const Extension* extension = OverridesHomepage(browser->profile(), NULL);
+  if (extension) {
+    // The bubble will try to anchor itself against the home button
+    views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser)->
+        toolbar()->home_button();
+    ShowSettingsApiBubble(BUBBLE_TYPE_HOME_PAGE,
+                          extension->id(),
+                          browser->profile(),
+                          anchor_view,
+                          views::BubbleBorder::TOP_LEFT);
+  }
+}
+
+void MaybeShowExtensionControlledSearchNotification(
+    Profile* profile,
+    content::WebContents* web_contents,
+    const AutocompleteMatch& match) {
+#if !defined(OS_WIN)
+  return;
+#endif
+
+  if (match.provider &&
+      match.provider->type() == AutocompleteProvider::TYPE_SEARCH) {
+    const extensions::Extension* extension =
+        OverridesSearchEngine(profile, NULL);
+    if (extension) {
+      ToolbarView* toolbar =
+          BrowserView::GetBrowserViewForBrowser(
+              chrome::FindBrowserWithWebContents(web_contents))->toolbar();
+      ShowSettingsApiBubble(BUBBLE_TYPE_SEARCH_ENGINE,
+                            extension->id(),
+                            profile,
+                            toolbar->app_menu(),
+                            views::BubbleBorder::TOP_RIGHT);
+    }
+  }
+}
+
+const extensions::SettingsOverrides* FindOverridingExtension(
+    content::BrowserContext* browser_context,
+    SettingsApiOverrideType type,
+    const Extension** extension) {
+  const extensions::ExtensionSet& extensions =
+      extensions::ExtensionRegistry::Get(browser_context)->enabled_extensions();
+
+  for (extensions::ExtensionSet::const_iterator it = extensions.begin();
+       it != extensions.end();
+       ++it) {
+    const extensions::SettingsOverrides* settings =
+        extensions::SettingsOverrides::Get(*it);
+    if (settings) {
+      if ((type == BUBBLE_TYPE_HOME_PAGE && settings->homepage) ||
+          (type == BUBBLE_TYPE_STARTUP_PAGES &&
+              !settings->startup_pages.empty()) ||
+          (type == BUBBLE_TYPE_SEARCH_ENGINE && settings->search_engine)) {
+        *extension = *it;
+        return settings;
+      }
+    }
+  }
+
+  return NULL;
+}
+
+const Extension* OverridesHomepage(content::BrowserContext* browser_context,
+                                   GURL* home_page_url) {
+  const extensions::Extension* extension = NULL;
+  const extensions::SettingsOverrides* settings =
+      FindOverridingExtension(
+          browser_context, BUBBLE_TYPE_HOME_PAGE, &extension);
+  if (settings && home_page_url)
+    *home_page_url = *settings->homepage;
+  return extension;
+}
+
+const Extension* OverridesStartupPages(content::BrowserContext* browser_context,
+                                       std::vector<GURL>* startup_pages) {
+  const extensions::Extension* extension = NULL;
+  const extensions::SettingsOverrides* settings =
+      FindOverridingExtension(
+          browser_context, BUBBLE_TYPE_STARTUP_PAGES, &extension);
+  if (settings && startup_pages) {
+    startup_pages->clear();
+    for (std::vector<GURL>::const_iterator it = settings->startup_pages.begin();
+         it != settings->startup_pages.end();
+         ++it)
+      startup_pages->push_back(GURL(*it));
+  }
+  return extension;
+}
+
+const Extension* OverridesSearchEngine(
+    content::BrowserContext* browser_context,
+    api::manifest_types::ChromeSettingsOverrides::Search_provider*
+        search_provider) {
+  const extensions::Extension* extension = NULL;
+  const extensions::SettingsOverrides* settings =
+      FindOverridingExtension(
+          browser_context, BUBBLE_TYPE_SEARCH_ENGINE, &extension);
+  if (settings && search_provider)
+    search_provider = settings->search_engine.get();
+  return extension;
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/ui/views/settings_api_bubble_helper_views.h b/chrome/browser/ui/views/settings_api_bubble_helper_views.h
new file mode 100644
index 0000000..a36a806
--- /dev/null
+++ b/chrome/browser/ui/views/settings_api_bubble_helper_views.h
@@ -0,0 +1,64 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_SETTINGS_API_BUBBLE_HELPER_VIEWS_H_
+#define CHROME_BROWSER_UI_VIEWS_SETTINGS_API_BUBBLE_HELPER_VIEWS_H_
+
+#include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
+
+struct AutocompleteMatch;
+class Browser;
+class Profile;
+
+namespace content {
+class BrowserContext;
+class WebContents;
+}
+
+namespace extensions {
+
+// Shows a bubble notifying the user that the homepage is controlled by an
+// extension. This bubble is shown only on the first use of the Home button
+// after the controlling extension takes effect.
+void MaybeShowExtensionControlledHomeNotification(Browser* browser);
+
+// Shows a bubble notifying the user that the search engine is controlled by an
+// extension. This bubble is shown only on the first search after the
+// controlling extension takes effect.
+void MaybeShowExtensionControlledSearchNotification(
+    Profile* profile,
+    content::WebContents* web_contents,
+    const AutocompleteMatch& match);
+
+// Find which |extension| is overriding a particular |type| of setting. Returns
+// the SettingsOverride object, or NULL if no |extension| is overriding that
+// particular setting.
+const extensions::SettingsOverrides* FindOverridingExtension(
+    content::BrowserContext* browser_context,
+    SettingsApiOverrideType type,
+    const Extension** extension);
+
+// Returns which extension is overriding the homepage in a given
+// |browser_context|. |home_page_url|, if non-NULL, will contain the home_page
+// value the extension has set.
+const Extension* OverridesHomepage(content::BrowserContext* browser_context,
+                                   GURL* home_page_url);
+
+// Returns which extension is overriding the homepage in a given
+// |browser_context|. |startup_pages|, if non-NULL, will contain the vector of
+// startup page URLs the extension has set.
+const Extension* OverridesStartupPages(content::BrowserContext* browser_context,
+                                       std::vector<GURL>* startup_pages);
+
+// Returns which extension is overriding the search engine in a given
+// |browser_context|. |search_provider|, if non-NULL, will contain the search
+// provider the extension has set.
+const Extension* OverridesSearchEngine(
+    content::BrowserContext* browser_context,
+    api::manifest_types::ChromeSettingsOverrides::Search_provider*
+        search_provider);
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_UI_VIEWS_SETTINGS_API_BUBBLE_HELPER_VIEWS_H_
diff --git a/chrome/browser/ui/views/simple_message_box_views.cc b/chrome/browser/ui/views/simple_message_box_views.cc
index c5f1a93..4203532 100644
--- a/chrome/browser/ui/views/simple_message_box_views.cc
+++ b/chrome/browser/ui/views/simple_message_box_views.cc
@@ -6,22 +6,16 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
-#include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_pump_dispatcher.h"
-#include "base/run_loop.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/views/constrained_window_views.h"
 #include "grit/generated_resources.h"
-#include "ui/aura/client/dispatcher_client.h"
-#include "ui/aura/env.h"
 #include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/views/controls/message_box_view.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
+#include "ui/wm/public/dispatcher_client.h"
 
 #if defined(OS_WIN)
 #include "ui/base/win/message_box_win.h"
@@ -32,21 +26,15 @@
 
 namespace {
 
-// Multiple SimpleMessageBoxViews can show up at the same time. Each of these
-// start a nested message-loop. However, these SimpleMessageBoxViews can be
-// deleted in any order. This creates problems if a box in an inner-loop gets
-// destroyed before a box in an outer-loop. So to avoid this, ref-counting is
-// used so that the SimpleMessageBoxViews gets deleted at the right time.
-class SimpleMessageBoxViews : public views::DialogDelegate,
-                              public base::RefCounted<SimpleMessageBoxViews> {
+class SimpleMessageBoxViews : public views::DialogDelegate {
  public:
   SimpleMessageBoxViews(const base::string16& title,
                         const base::string16& message,
                         MessageBoxType type,
                         const base::string16& yes_text,
-                        const base::string16& no_text);
-
-  MessageBoxResult result() const { return result_; }
+                        const base::string16& no_text,
+                        MessageBoxResult* result);
+  virtual ~SimpleMessageBoxViews();
 
   // Overridden from views::DialogDelegate:
   virtual int GetDialogButtons() const OVERRIDE;
@@ -64,8 +52,6 @@
   virtual const views::Widget* GetWidget() const OVERRIDE;
 
  private:
-  friend class base::RefCounted<SimpleMessageBoxViews>;
-  virtual ~SimpleMessageBoxViews();
 
   // This terminates the nested message-loop.
   void Done();
@@ -74,7 +60,7 @@
   const MessageBoxType type_;
   base::string16 yes_text_;
   base::string16 no_text_;
-  MessageBoxResult result_;
+  MessageBoxResult* result_;
   views::MessageBoxView* message_box_view_;
 
   DISALLOW_COPY_AND_ASSIGN(SimpleMessageBoxViews);
@@ -87,16 +73,16 @@
                                              const base::string16& message,
                                              MessageBoxType type,
                                              const base::string16& yes_text,
-                                             const base::string16& no_text)
+                                             const base::string16& no_text,
+                                             MessageBoxResult* result)
     : window_title_(title),
       type_(type),
       yes_text_(yes_text),
       no_text_(no_text),
-      result_(MESSAGE_BOX_RESULT_NO),
+      result_(result),
       message_box_view_(new views::MessageBoxView(
           views::MessageBoxView::InitParams(message))) {
-  AddRef();
-
+  CHECK(result_);
   if (yes_text_.empty()) {
     if (type_ == MESSAGE_BOX_TYPE_QUESTION)
       yes_text_ =
@@ -116,6 +102,9 @@
   }
 }
 
+SimpleMessageBoxViews::~SimpleMessageBoxViews() {
+}
+
 int SimpleMessageBoxViews::GetDialogButtons() const {
   if (type_ == MESSAGE_BOX_TYPE_QUESTION ||
       type_ == MESSAGE_BOX_TYPE_OK_CANCEL) {
@@ -133,13 +122,13 @@
 }
 
 bool SimpleMessageBoxViews::Cancel() {
-  result_ = MESSAGE_BOX_RESULT_NO;
+  *result_ = MESSAGE_BOX_RESULT_NO;
   Done();
   return true;
 }
 
 bool SimpleMessageBoxViews::Accept() {
-  result_ = MESSAGE_BOX_RESULT_YES;
+  *result_ = MESSAGE_BOX_RESULT_YES;
   Done();
   return true;
 }
@@ -149,7 +138,7 @@
 }
 
 void SimpleMessageBoxViews::DeleteDelegate() {
-  Release();
+  delete this;
 }
 
 ui::ModalType SimpleMessageBoxViews::GetModalType() const {
@@ -171,9 +160,6 @@
 ////////////////////////////////////////////////////////////////////////////////
 // SimpleMessageBoxViews, private:
 
-SimpleMessageBoxViews::~SimpleMessageBoxViews() {
-}
-
 void SimpleMessageBoxViews::Done() {
   aura::Window* window = GetWidget()->GetNativeView();
   aura::client::DispatcherClient* client =
@@ -207,7 +193,7 @@
                                     const base::string16& no_text) {
 #if defined(OS_WIN)
   // GPU-based dialogs can't be used early on; fallback to a Windows MessageBox.
-  if (!ui::ContextFactory::GetInstance()) {
+  if (!base::MessageLoop::current()->is_running()) {
     int result = ui::MessageBox(views::HWNDForNativeWindow(parent), message,
                                 title, GetMessageBoxFlagsFromType(type));
     return (result == IDYES || result == IDOK) ?
@@ -215,9 +201,10 @@
   }
 #endif
 
-  scoped_refptr<SimpleMessageBoxViews> dialog(
-      new SimpleMessageBoxViews(title, message, type, yes_text, no_text));
-  CreateBrowserModalDialogViews(dialog.get(), parent)->Show();
+  MessageBoxResult result = MESSAGE_BOX_RESULT_NO;
+  SimpleMessageBoxViews* dialog = new SimpleMessageBoxViews(
+      title, message, type, yes_text, no_text, &result);
+  CreateBrowserModalDialogViews(dialog, parent)->Show();
 
   // Use the widget's window itself so that the message loop
   // exists when the dialog is closed by some other means than
@@ -226,7 +213,9 @@
   aura::client::DispatcherClient* client =
       aura::client::GetDispatcherClient(anchor->GetRootWindow());
   client->RunWithDispatcher(NULL);
-  return dialog->result();
+  // NOTE: |dialog| will have been deleted by the time control returns here.
+
+  return result;
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
index d5c9678..77a682c 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -1783,8 +1783,7 @@
   EXPECT_FALSE(browser2->window()->IsMaximized());
 }
 
-// Immersive fullscreen is Ash only.  However, Windows Ash does not support
-// multiple displays.
+// Immersive fullscreen is ChromeOS only.
 #if defined(OS_CHROMEOS)
 // TODO(sky,sad): Disabled as it fails due to resize locks with a real
 // compositor. crbug.com/331924
diff --git a/chrome/browser/ui/views/toolbar/browser_action_view.cc b/chrome/browser/ui/views/toolbar/browser_action_view.cc
index a33e8ee..059fb7e 100644
--- a/chrome/browser/ui/views/toolbar/browser_action_view.cc
+++ b/chrome/browser/ui/views/toolbar/browser_action_view.cc
@@ -7,7 +7,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/api/commands/command_service.h"
-#include "chrome/browser/extensions/dev_mode_bubble_controller.h"
 #include "chrome/browser/extensions/extension_action.h"
 #include "chrome/browser/extensions/extension_action_manager.h"
 #include "chrome/browser/extensions/extension_context_menu_model.h"
@@ -67,16 +66,7 @@
 }
 
 void BrowserActionView::Layout() {
-  // We can't rely on button_->GetPreferredSize() here because that's not set
-  // correctly until the first call to
-  // BrowserActionsContainer::RefreshBrowserActionViews(), whereas this can be
-  // called before that when the initial bounds are set (and then not after,
-  // since the bounds don't change).  So instead of setting the height from the
-  // button's preferred size, we use IconHeight(), since that's how big the
-  // button should be regardless of what it's displaying.
-  gfx::Point offset = delegate_->GetViewContentOffset();
-  button_->SetBounds(offset.x(), offset.y(), width() - offset.x(),
-                     BrowserActionsContainer::IconHeight());
+  button_->SetBounds(0, y(), width(), height());
 }
 
 void BrowserActionView::GetAccessibleState(ui::AXViewState* state) {
@@ -232,11 +222,7 @@
     ThemeService* theme =
         ThemeServiceFactory::GetForProfile(browser_->profile());
 
-    int background_id = IDR_BROWSER_ACTION;
-    if (extensions::DevModeBubbleController::IsDevModeExtension(extension_))
-      background_id = IDR_BROWSER_ACTION_HIGHLIGHT;
-
-    gfx::ImageSkia bg = *theme->GetImageSkiaNamed(background_id);
+    gfx::ImageSkia bg = *theme->GetImageSkiaNamed(IDR_BROWSER_ACTION);
     SetIcon(gfx::ImageSkiaOperations::CreateSuperimposedImage(bg, icon));
 
     gfx::ImageSkia bg_h = *theme->GetImageSkiaNamed(IDR_BROWSER_ACTION_H);
diff --git a/chrome/browser/ui/views/toolbar/browser_action_view.h b/chrome/browser/ui/views/toolbar/browser_action_view.h
index f1743e0..eb5aa87 100644
--- a/chrome/browser/ui/views/toolbar/browser_action_view.h
+++ b/chrome/browser/ui/views/toolbar/browser_action_view.h
@@ -54,9 +54,6 @@
     // Called when a browser action becomes visible/hidden.
     virtual void OnBrowserActionVisibilityChanged() = 0;
 
-    // Returns relative position of a button inside BrowserActionView.
-    virtual gfx::Point GetViewContentOffset() const = 0;
-
     virtual bool NeedToShowMultipleIconStates() const;
     virtual bool NeedToShowTooltip() const;
 
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.cc b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
index b774a5d..6e24af6 100644
--- a/chrome/browser/ui/views/toolbar/browser_actions_container.cc
+++ b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
@@ -30,15 +30,19 @@
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
 #include "grit/ui_resources.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/accessibility/ax_view_state.h"
 #include "ui/base/dragdrop/drag_utils.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/base/nine_image_painter_factory.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/theme_provider.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/rect.h"
 #include "ui/views/controls/resize_area.h"
 #include "ui/views/metrics.h"
+#include "ui/views/painter.h"
 #include "ui/views/widget/widget.h"
 
 using extensions::Extension;
@@ -79,7 +83,7 @@
       show_menu_task_factory_(this) {
   set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR);
 
-  model_ = ExtensionToolbarModel::Get(browser->profile());
+  model_ = extensions::ExtensionToolbarModel::Get(browser->profile());
   if (model_)
     model_->AddObserver(this);
 
@@ -103,6 +107,10 @@
 }
 
 BrowserActionsContainer::~BrowserActionsContainer() {
+  FOR_EACH_OBSERVER(BrowserActionsContainerObserver,
+                    observers_,
+                    OnBrowserActionsContainerDestroyed());
+
   if (overflow_menu_)
     overflow_menu_->set_observer(NULL);
   if (model_)
@@ -189,6 +197,16 @@
                                                  command.accelerator());
 }
 
+void BrowserActionsContainer::AddObserver(
+    BrowserActionsContainerObserver* observer) {
+  observers_.AddObserver(observer);
+}
+
+void BrowserActionsContainer::RemoveObserver(
+    BrowserActionsContainerObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
 gfx::Size BrowserActionsContainer::GetPreferredSize() {
   if (browser_action_views_.empty())
     return gfx::Size(ToolbarView::kStandardSpacing, 0);
@@ -212,8 +230,7 @@
   }
 
   SetVisible(true);
-  resize_area_->SetBounds(0, ToolbarView::kVertSpacing, kItemSpacing,
-                          IconHeight());
+  resize_area_->SetBounds(0, 0, kItemSpacing, height());
 
   // If the icons don't all fit, show the chevron (unless suppressed).
   int max_x = GetPreferredSize().width();
@@ -224,7 +241,9 @@
         ToolbarView::kStandardSpacing + chevron_size.width() + kChevronSpacing;
     chevron_->SetBounds(
         width() - ToolbarView::kStandardSpacing - chevron_size.width(),
-        ToolbarView::kVertSpacing, chevron_size.width(), chevron_size.height());
+        0,
+        chevron_size.width(),
+        chevron_size.height());
   } else {
     chevron_->SetVisible(false);
   }
@@ -418,7 +437,8 @@
 bool BrowserActionsContainer::CanStartDragForView(View* sender,
                                                   const gfx::Point& press_pt,
                                                   const gfx::Point& p) {
-  return true;
+  // We don't allow dragging while we're highlighting.
+  return !model_->is_highlighting();
 }
 
 void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) {
@@ -452,6 +472,10 @@
   resize_amount_ = 0;
   suppress_chevron_ = false;
   OnBrowserActionVisibilityChanged();
+
+  FOR_EACH_OBSERVER(BrowserActionsContainerObserver,
+                    observers_,
+                    OnBrowserActionsContainerAnimationEnded());
 }
 
 void BrowserActionsContainer::NotifyMenuDeleted(
@@ -496,10 +520,6 @@
   owner_view_->SchedulePaint();
 }
 
-gfx::Point BrowserActionsContainer::GetViewContentOffset() const {
-  return gfx::Point(0, ToolbarView::kVertSpacing);
-}
-
 extensions::ActiveTabPermissionGranter*
     BrowserActionsContainer::GetActiveTabPermissionGranter() {
   content::WebContents* web_contents =
@@ -570,6 +590,13 @@
 }
 
 void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) {
+  // If the views haven't been initialized yet, wait for the next call to
+  // paint (one will be triggered by entering highlight mode).
+  if (model_->is_highlighting() && !browser_action_views_.empty()) {
+    views::Painter::PaintPainterAt(
+        canvas, highlight_painter_.get(), GetLocalBounds());
+  }
+
   // TODO(sky/glen): Instead of using a drop indicator, animate the icons while
   // dragging (like we do for tab dragging).
   if (drop_indicator_position_ > -1) {
@@ -577,7 +604,9 @@
     static const int kDropIndicatorWidth = 2;
     gfx::Rect indicator_bounds(
         drop_indicator_position_ - (kDropIndicatorWidth / 2),
-        ToolbarView::kVertSpacing, kDropIndicatorWidth, IconHeight());
+        0,
+        kDropIndicatorWidth,
+        height());
 
     // Color of the drop indicator.
     static const SkColor kDropIndicatorColor = SK_ColorBLACK;
@@ -730,6 +759,16 @@
   SetContainerWidth();
 }
 
+void BrowserActionsContainer::HighlightModeChanged(bool is_highlighting) {
+  // The visual highlighting is done in OnPaint(). It's a bit of a pain that
+  // we delete and recreate everything here, but that's how it's done in
+  // BrowserActionMoved(), too. If we want to optimize it, we could move the
+  // existing icons, instead of deleting it all.
+  DeleteBrowserActionViews();
+  CreateBrowserActionViews();
+  SaveDesiredSizeAndAnimate(gfx::Tween::LINEAR, browser_action_views_.size());
+}
+
 void BrowserActionsContainer::LoadImages() {
   ui::ThemeProvider* tp = GetThemeProvider();
   chevron_->SetIcon(*tp->GetImageSkiaNamed(IDR_BROWSER_ACTIONS_OVERFLOW));
@@ -737,6 +776,9 @@
       IDR_BROWSER_ACTIONS_OVERFLOW_H));
   chevron_->SetPushedIcon(*tp->GetImageSkiaNamed(
       IDR_BROWSER_ACTIONS_OVERFLOW_P));
+
+  const int kImages[] = IMAGE_GRID(IDR_DEVELOPER_MODE_HIGHLIGHT);
+  highlight_painter_.reset(views::Painter::CreateImageGridPainter(kImages));
 }
 
 void BrowserActionsContainer::SetContainerWidth() {
@@ -858,7 +900,7 @@
   GURL popup_url;
   if (model_->ExecuteBrowserAction(
           extension, browser_, &popup_url, should_grant) !=
-      ExtensionToolbarModel::ACTION_SHOW_POPUP) {
+      extensions::ExtensionToolbarModel::ACTION_SHOW_POPUP) {
     return false;
   }
 
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.h b/chrome/browser/ui/views/toolbar/browser_actions_container.h
index 7ca1d75..5c84871 100644
--- a/chrome/browser/ui/views/toolbar/browser_actions_container.h
+++ b/chrome/browser/ui/views/toolbar/browser_actions_container.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_H_
 #define CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_H_
 
+#include "base/observer_list.h"
 #include "chrome/browser/extensions/extension_keybinding_registry.h"
 #include "chrome/browser/extensions/extension_toolbar_model.h"
 #include "chrome/browser/ui/views/chrome_views_export.h"
@@ -12,6 +13,7 @@
 #include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views.h"
 #include "chrome/browser/ui/views/extensions/extension_popup.h"
 #include "chrome/browser/ui/views/toolbar/browser_action_view.h"
+#include "chrome/browser/ui/views/toolbar/browser_actions_container_observer.h"
 #include "content/public/browser/notification_observer.h"
 #include "ui/gfx/animation/animation_delegate.h"
 #include "ui/gfx/animation/tween.h"
@@ -117,7 +119,7 @@
       public views::MenuButtonListener,
       public views::ResizeAreaDelegate,
       public gfx::AnimationDelegate,
-      public ExtensionToolbarModel::Observer,
+      public extensions::ExtensionToolbarModel::Observer,
       public BrowserActionOverflowMenuController::Observer,
       public views::WidgetObserver,
       public BrowserActionView::Delegate,
@@ -165,6 +167,10 @@
   void ExecuteExtensionCommand(const extensions::Extension* extension,
                                const extensions::Command& command);
 
+  // Add or remove an observer.
+  void AddObserver(BrowserActionsContainerObserver* observer);
+  void RemoveObserver(BrowserActionsContainerObserver* observer);
+
   // Overridden from views::View:
   virtual gfx::Size GetPreferredSize() OVERRIDE;
   virtual void Layout() OVERRIDE;
@@ -211,7 +217,6 @@
   virtual int GetCurrentTabId() const OVERRIDE;
   virtual void OnBrowserActionExecuted(BrowserActionButton* button) OVERRIDE;
   virtual void OnBrowserActionVisibilityChanged() OVERRIDE;
-  virtual gfx::Point GetViewContentOffset() const OVERRIDE;
 
   // Overridden from extension::ExtensionKeybindingRegistry::Delegate:
   virtual extensions::ActiveTabPermissionGranter*
@@ -254,7 +259,7 @@
   virtual void OnThemeChanged() OVERRIDE;
 
  private:
-  friend class BrowserActionView;  // So it can access IconHeight().
+  friend class BrowserActionView;  // So it can access IconWidth().
   friend class ShowFolderMenuTask;
 
   typedef std::vector<BrowserActionView*> BrowserActionViews;
@@ -265,7 +270,7 @@
   // Returns the height of an icon.
   static int IconHeight();
 
-  // ExtensionToolbarModel::Observer implementation.
+  // extensions::ExtensionToolbarModel::Observer implementation.
   virtual void BrowserActionAdded(const extensions::Extension* extension,
                                   int index) OVERRIDE;
   virtual void BrowserActionRemoved(
@@ -275,6 +280,7 @@
   virtual bool BrowserActionShowPopup(
       const extensions::Extension* extension) OVERRIDE;
   virtual void VisibleCountChanged() OVERRIDE;
+  virtual void HighlightModeChanged(bool is_highlighting) OVERRIDE;
 
   void LoadImages();
 
@@ -353,7 +359,7 @@
   BrowserActionButton* popup_button_;
 
   // The model that tracks the order of the toolbar icons.
-  ExtensionToolbarModel* model_;
+  extensions::ExtensionToolbarModel* model_;
 
   // The current width of the container.
   int container_width_;
@@ -364,6 +370,9 @@
   // The chevron for accessing the overflow items.
   views::MenuButton* chevron_;
 
+  // The painter used when we are highlighting a subset of extensions.
+  scoped_ptr<views::Painter> highlight_painter_;
+
   // The menu to show for the overflow button (chevron). This class manages its
   // own lifetime so that it can stay alive during drag and drop operations.
   BrowserActionOverflowMenuController* overflow_menu_;
@@ -394,6 +403,8 @@
   // Handles delayed showing of the overflow menu when hovering.
   base::WeakPtrFactory<BrowserActionsContainer> show_menu_task_factory_;
 
+  ObserverList<BrowserActionsContainerObserver> observers_;
+
   DISALLOW_COPY_AND_ASSIGN(BrowserActionsContainer);
 };
 
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc b/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc
index a707bb7..799d10d 100644
--- a/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc
+++ b/chrome/browser/ui/views/toolbar/browser_actions_container_browsertest.cc
@@ -8,10 +8,15 @@
 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
 #include "chrome/browser/extensions/browser_action_test_util.h"
 #include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/extension_toolbar_model.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/views/toolbar/browser_action_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_prefs.h"
-
-using extensions::Extension;
+#include "extensions/common/extension.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/views/view.h"
 
 class BrowserActionsContainerTest : public ExtensionBrowserTest {
  public:
@@ -184,3 +189,62 @@
       extensions::ExtensionPrefs::Get(browser()->profile()), idA, false);
   EXPECT_EQ(0, browser_actions_bar()->VisibleBrowserActions());
 }
+
+// Test that the BrowserActionsContainer responds correctly when the underlying
+// model enters highlight mode, and that browser actions are undraggable in
+// highlight mode. (Highlight mode itself it tested more thoroughly in the
+// ExtensionToolbarModel browsertests).
+IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, HighlightMode) {
+  BrowserActionsContainer::disable_animations_during_testing_ = true;
+
+  // Load three extensions with browser actions.
+  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
+                                          .AppendASCII("browser_action")
+                                          .AppendASCII("basics")));
+  std::string id_a = browser_actions_bar()->GetExtensionId(0);
+  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
+                                          .AppendASCII("browser_action")
+                                          .AppendASCII("add_popup")));
+  std::string id_b = browser_actions_bar()->GetExtensionId(1);
+  ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
+                                          .AppendASCII("browser_action")
+                                          .AppendASCII("remove_popup")));
+
+  EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
+  EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
+
+  BrowserActionsContainer* container = browser()
+                                           ->window()
+                                           ->GetBrowserWindowTesting()
+                                           ->GetToolbarView()
+                                           ->browser_actions();
+
+  // Currently, dragging should be enabled.
+  BrowserActionView* action_view = container->GetBrowserActionViewAt(0);
+  ASSERT_TRUE(action_view);
+  gfx::Point point(action_view->x(), action_view->y());
+  EXPECT_TRUE(container->CanStartDragForView(action_view, point, point));
+
+  extensions::ExtensionToolbarModel* model =
+      extensions::ExtensionToolbarModel::Get(profile());
+
+  extensions::ExtensionIdList extension_ids;
+  extension_ids.push_back(id_a);
+  extension_ids.push_back(id_b);
+  model->HighlightExtensions(extension_ids);
+
+  // Only two browser actions should be visible.
+  EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
+  EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
+
+  // We shouldn't be able to drag in highlight mode.
+  action_view = container->GetBrowserActionViewAt(0);
+  EXPECT_FALSE(container->CanStartDragForView(action_view, point, point));
+
+  // We should go back to normal after leaving highlight mode.
+  model->StopHighlighting();
+  EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
+  EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
+  action_view = container->GetBrowserActionViewAt(0);
+  EXPECT_TRUE(container->CanStartDragForView(action_view, point, point));
+}
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container_observer.h b/chrome/browser/ui/views/toolbar/browser_actions_container_observer.h
new file mode 100644
index 0000000..383937e
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/browser_actions_container_observer.h
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_OBSERVER_H_
+#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_OBSERVER_H_
+
+class BrowserActionsContainerObserver {
+ public:
+  virtual void OnBrowserActionsContainerAnimationEnded() {}
+  virtual void OnBrowserActionsContainerDestroyed() {}
+
+ protected:
+  virtual ~BrowserActionsContainerObserver() {}
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_OBSERVER_H_
diff --git a/chrome/browser/ui/views/toolbar/home_button.cc b/chrome/browser/ui/views/toolbar/home_button.cc
index d3768ca..2c56077 100644
--- a/chrome/browser/ui/views/toolbar/home_button.cc
+++ b/chrome/browser/ui/views/toolbar/home_button.cc
@@ -7,6 +7,7 @@
 #include "base/prefs/pref_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/views/settings_api_bubble_helper_views.h"
 #include "chrome/common/pref_names.h"
 #include "components/user_prefs/user_prefs.h"
 #include "grit/generated_resources.h"
@@ -178,3 +179,8 @@
   }
   return ui::DragDropTypes::DRAG_NONE;
 }
+
+void HomeButton::NotifyClick(const ui::Event& event) {
+  ToolbarButton::NotifyClick(event);
+  extensions::MaybeShowExtensionControlledHomeNotification(browser_);
+}
diff --git a/chrome/browser/ui/views/toolbar/home_button.h b/chrome/browser/ui/views/toolbar/home_button.h
index b532182..014ab3b 100644
--- a/chrome/browser/ui/views/toolbar/home_button.h
+++ b/chrome/browser/ui/views/toolbar/home_button.h
@@ -16,7 +16,7 @@
   HomeButton(views::ButtonListener* listener, Browser* browser);
   virtual ~HomeButton();
 
-  // views::ImageButton:
+  // ToolbarButton:
   virtual bool GetDropFormats(
       int* formats,
       std::set<OSExchangeData::CustomFormat>* custom_formats) OVERRIDE;
@@ -25,6 +25,9 @@
   virtual int OnPerformDrop(const ui::DropTargetEvent& event) OVERRIDE;
 
  private:
+  // ToolbarButton:
+  virtual void NotifyClick(const ui::Event& event) OVERRIDE;
+
   Browser* browser_;
 
   DISALLOW_COPY_AND_ASSIGN(HomeButton);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_button.cc b/chrome/browser/ui/views/toolbar/toolbar_button.cc
index fb97d1c..fd8d239 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_button.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_button.cc
@@ -125,7 +125,7 @@
   CustomButton::GetAccessibleState(state);
   state->role = ui::AX_ROLE_BUTTON_DROP_DOWN;
   state->default_action = l10n_util::GetStringUTF16(IDS_APP_ACCACTION_PRESS);
-  state->state = ui::AX_STATE_HASPOPUP;
+  state->AddStateFlag(ui::AX_STATE_HASPOPUP);
 }
 
 void ToolbarButton::ShowContextMenuForView(View* source,
diff --git a/chrome/browser/ui/views/toolbar/toolbar_origin_chip_view.cc b/chrome/browser/ui/views/toolbar/toolbar_origin_chip_view.cc
index 136807a..7fb18d0 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_origin_chip_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_origin_chip_view.cc
@@ -341,7 +341,7 @@
   UMA_HISTOGRAM_COUNTS("OriginChip.Pressed", 1);
   content::RecordAction(base::UserMetricsAction("OriginChipPress"));
 
-  toolbar_view_->location_bar()->GetOmniboxView()->ShowURL();
+  toolbar_view_->location_bar()->ShowURL();
 }
 
 void ToolbarOriginChipView::WriteDragDataForView(View* sender,
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc
index 6bf12da..4556ad0 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -86,6 +86,7 @@
 
 #if !defined(OS_CHROMEOS)
 #include "chrome/browser/signin/signin_global_error_factory.h"
+#include "chrome/browser/sync/sync_global_error_factory.h"
 #endif
 
 #if defined(USE_ASH)
@@ -145,7 +146,10 @@
       origin_chip_view_(NULL),
       browser_actions_(NULL),
       app_menu_(NULL),
-      browser_(browser) {
+      browser_(browser),
+      extension_message_bubble_factory_(
+          new extensions::ExtensionMessageBubbleFactory(browser->profile(),
+                                                        this)) {
   set_id(VIEW_ID_TOOLBAR);
 
   chrome::AddCommandObserver(browser_, IDC_BACK, this);
@@ -164,6 +168,8 @@
   if (OutdatedUpgradeBubbleView::IsAvailable()) {
     registrar_.Add(this, chrome::NOTIFICATION_OUTDATED_INSTALL,
                    content::NotificationService::AllSources());
+    registrar_.Add(this, chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+                   content::NotificationService::AllSources());
   }
 #if defined(OS_WIN)
   registrar_.Add(this, chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED,
@@ -263,11 +269,14 @@
 
   LoadImages();
 
-  // Start signin global error service now so we badge the menu correctly
-  // in non-Ash.
+  // Start global error services now so we badge the menu correctly in non-Ash.
 #if !defined(OS_CHROMEOS)
-  if (!HasAshShell())
+  if (!HasAshShell()) {
     SigninGlobalErrorFactory::GetForProfile(browser_->profile());
+#if !defined(OS_ANDROID)
+    SyncGlobalErrorFactory::GetForProfile(browser_->profile());
+#endif
+  }
 #endif  // OS_CHROMEOS
 
   // Add any necessary badges to the menu item based on the system state.
@@ -300,11 +309,9 @@
 
 void ToolbarView::OnWidgetVisibilityChanged(views::Widget* widget,
                                             bool visible) {
-  if (visible) {
-    extensions::ExtensionMessageBubbleView::MaybeShow(
-        browser_, this, app_menu_);
-    GetWidget()->RemoveObserver(this);
-  }
+  // Safe to call multiple times; the bubble will only appear once.
+  if (visible)
+    extension_message_bubble_factory_->MaybeShow(app_menu_);
 }
 
 void ToolbarView::Update(WebContents* tab) {
@@ -513,7 +520,10 @@
       UpdateAppMenuState();
       break;
     case chrome::NOTIFICATION_OUTDATED_INSTALL:
-      ShowOutdatedInstallNotification();
+      ShowOutdatedInstallNotification(true);
+      break;
+    case chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU:
+      ShowOutdatedInstallNotification(false);
       break;
 #if defined(OS_WIN)
     case chrome::NOTIFICATION_CRITICAL_UPGRADE_INSTALLED:
@@ -657,8 +667,8 @@
     next_element_x = origin_chip_view_->bounds().right();
   }
 
-  browser_actions_->SetBounds(next_element_x, 0,
-                              browser_actions_width, height());
+  browser_actions_->SetBounds(
+      next_element_x, child_y, browser_actions_width, child_height);
   next_element_x = browser_actions_->bounds().right();
 
   // The browser actions need to do a layout explicitly, because when an
@@ -812,9 +822,11 @@
 #endif
 }
 
-void ToolbarView::ShowOutdatedInstallNotification() {
-  if (OutdatedUpgradeBubbleView::IsAvailable())
-    OutdatedUpgradeBubbleView::ShowBubble(app_menu_, browser_);
+void ToolbarView::ShowOutdatedInstallNotification(bool auto_update_enabled) {
+  if (OutdatedUpgradeBubbleView::IsAvailable()) {
+    OutdatedUpgradeBubbleView::ShowBubble(
+        app_menu_, browser_, auto_update_enabled);
+  }
 }
 
 void ToolbarView::UpdateAppMenuState() {
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h
index 188fe0d..6a02f5a 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_view.h
+++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -34,6 +34,7 @@
 namespace extensions {
 class Command;
 class Extension;
+class ExtensionMessageBubbleFactory;
 }
 
 namespace views {
@@ -104,6 +105,7 @@
   LocationBarView* location_bar() const { return location_bar_; }
   ToolbarOriginChipView* origin_chip() const { return origin_chip_view_; }
   views::MenuButton* app_menu() const;
+  HomeButton* home_button() const { return home_; }
 
   // Overridden from AccessiblePaneView
   virtual bool SetPaneFocus(View* initial_focus) OVERRIDE;
@@ -210,7 +212,8 @@
   void ShowCriticalNotification();
 
   // Shows the outdated install notification bubble against the wrench menu.
-  void ShowOutdatedInstallNotification();
+  // |auto_update_enabled| is set to true when auto-upate is on.
+  void ShowOutdatedInstallNotification(bool auto_update_enabled);
 
   // Updates the badge and the accessible name of the app menu (Wrench).
   void UpdateAppMenuState();
@@ -245,6 +248,11 @@
   scoped_ptr<WrenchMenuModel> wrench_menu_model_;
   scoped_ptr<WrenchMenu> wrench_menu_;
 
+  // The factory to create bubbles to warn about dangerous/suspicious
+  // extensions.
+  scoped_ptr<extensions::ExtensionMessageBubbleFactory>
+      extension_message_bubble_factory_;
+
   // A list of listeners to call when the menu opens.
   ObserverList<views::MenuListener> menu_listeners_;
 
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc
index 19eb05c..4f5ad81 100644
--- a/chrome/browser/ui/views/translate/translate_bubble_view.cc
+++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/translate/translate_service.h"
 #include "chrome/browser/translate/translate_tab_helper.h"
 #include "chrome/browser/translate/translate_ui_delegate.h"
+#include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/translate/translate_bubble_model_impl.h"
 #include "chrome/common/url_constants.h"
 #include "components/translate/core/browser/translate_download_manager.h"
@@ -398,10 +399,9 @@
       break;
     }
     case LINK_ID_LANGUAGE_SETTINGS: {
-      std::string url = std::string(chrome::kChromeUISettingsURL) +
-          chrome::kLanguageOptionsSubPage;
+      GURL url = chrome::GetSettingsUrl(chrome::kLanguageOptionsSubPage);
       web_contents()->OpenURL(content::OpenURLParams(
-          GURL(url),
+          url,
           content::Referrer(),
           NEW_FOREGROUND_TAB,
           content::PAGE_TRANSITION_LINK,
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
index 4d6e5e6..eb679bd 100644
--- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
+++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.cc
@@ -52,6 +52,14 @@
 
 namespace {
 
+// NOTE(jdonnelly): This use of this process-wide variable assumes that there's
+// never more than one website settings popup shown and that it's associated
+// with the current window. If this assumption fails in the future, we'll need
+// to return a weak pointer from ShowPopup so callers can associate it with the
+// current window (or other context) and check if the popup they care about is
+// showing.
+bool is_popup_showing = false;
+
 // Padding values for sections on the connection tab.
 const int kConnectionSectionPaddingBottom = 16;
 const int kConnectionSectionPaddingLeft = 18;
@@ -140,6 +148,9 @@
   explicit InternalPageInfoPopupView(views::View* anchor_view);
   virtual ~InternalPageInfoPopupView();
 
+  // views::BubbleDelegateView:
+  virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView);
 };
@@ -248,6 +259,10 @@
 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
 }
 
+void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) {
+  is_popup_showing = false;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WebsiteSettingsPopupView
 ////////////////////////////////////////////////////////////////////////////////
@@ -262,6 +277,7 @@
                                          const GURL& url,
                                          const content::SSLStatus& ssl,
                                          Browser* browser) {
+  is_popup_showing = true;
   if (InternalChromePage(url)) {
     new InternalPageInfoPopupView(anchor_view);
   } else {
@@ -270,6 +286,11 @@
   }
 }
 
+// static
+bool WebsiteSettingsPopupView::IsPopupShowing() {
+  return is_popup_showing;
+}
+
 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
     views::View* anchor_view,
     Profile* profile,
@@ -355,6 +376,7 @@
 }
 
 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
+  is_popup_showing = false;
   presenter_->OnUIClosing();
 }
 
diff --git a/chrome/browser/ui/views/website_settings/website_settings_popup_view.h b/chrome/browser/ui/views/website_settings/website_settings_popup_view.h
index 35fefd1..894e297 100644
--- a/chrome/browser/ui/views/website_settings/website_settings_popup_view.h
+++ b/chrome/browser/ui/views/website_settings/website_settings_popup_view.h
@@ -53,6 +53,8 @@
                         const content::SSLStatus& ssl,
                         Browser* browser);
 
+  static bool IsPopupShowing();
+
  private:
   WebsiteSettingsPopupView(views::View* anchor_view,
                            Profile* profile,
@@ -65,7 +67,7 @@
   virtual void OnPermissionChanged(
       PermissionSelectorView* selector) OVERRIDE;
 
-  // views::BubbleDelegate implementation.
+  // views::BubbleDelegateView implementation.
   virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
 
   // views::ButtonListener implementation.
diff --git a/chrome/browser/ui/web_applications/web_app_ui.cc b/chrome/browser/ui/web_applications/web_app_ui.cc
index 4a6adb3..04ab5ac 100644
--- a/chrome/browser/ui/web_applications/web_app_ui.cc
+++ b/chrome/browser/ui/web_applications/web_app_ui.cc
@@ -291,8 +291,8 @@
     return;
   }
 
-  base::FilePath icon_file = web_app_path.Append(file_name_).ReplaceExtension(
-      FILE_PATH_LITERAL(".ico"));
+  base::FilePath icon_file =
+      web_app::internals::GetIconFilePath(web_app_path, shortcut_info_.title);
   web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info_.favicon);
 
   // Update existing shortcuts' description, icon and app id.
@@ -425,18 +425,18 @@
 }
 
 void UpdateShortcutInfoAndIconForApp(
-    const extensions::Extension& extension,
+    const extensions::Extension* extension,
     Profile* profile,
     const web_app::ShortcutInfoCallback& callback) {
   ShellIntegration::ShortcutInfo shortcut_info =
-      ShortcutInfoForExtensionAndProfile(&extension, profile);
+      ShortcutInfoForExtensionAndProfile(extension, profile);
 
   std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
   for (size_t i = 0; i < kNumDesiredSizes; ++i) {
     int size = kDesiredSizes[i];
     extensions::ExtensionResource resource =
         extensions::IconsInfo::GetIconResource(
-            &extension, size, ExtensionIconSet::MATCH_EXACTLY);
+            extension, size, ExtensionIconSet::MATCH_EXACTLY);
     if (!resource.empty()) {
       info_list.push_back(extensions::ImageLoader::ImageRepresentation(
           resource,
@@ -455,10 +455,10 @@
     // so look for a larger icon first:
     extensions::ExtensionResource resource =
         extensions::IconsInfo::GetIconResource(
-            &extension, size, ExtensionIconSet::MATCH_BIGGER);
+            extension, size, ExtensionIconSet::MATCH_BIGGER);
     if (resource.empty()) {
       resource = extensions::IconsInfo::GetIconResource(
-          &extension, size, ExtensionIconSet::MATCH_SMALLER);
+          extension, size, ExtensionIconSet::MATCH_SMALLER);
     }
     info_list.push_back(extensions::ImageLoader::ImageRepresentation(
         resource,
@@ -471,7 +471,7 @@
   // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty
   // image and exit immediately.
   extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync(
-      &extension,
+      extension,
       info_list,
       base::Bind(&OnImageLoaded, shortcut_info, callback));
 }
diff --git a/chrome/browser/ui/web_applications/web_app_ui.h b/chrome/browser/ui/web_applications/web_app_ui.h
index 19ee0ce..6496974 100644
--- a/chrome/browser/ui/web_applications/web_app_ui.h
+++ b/chrome/browser/ui/web_applications/web_app_ui.h
@@ -47,7 +47,7 @@
 // Fetches the icon for |extension| and calls |callback| with shortcut info
 // filled out as by UpdateShortcutInfoForApp.
 void UpdateShortcutInfoAndIconForApp(
-    const extensions::Extension& extension,
+    const extensions::Extension* extension,
     Profile* profile,
     const ShortcutInfoCallback& callback);
 
diff --git a/chrome/browser/ui/webui/DEPS b/chrome/browser/ui/webui/DEPS
index f154c9a..7d9e166 100644
--- a/chrome/browser/ui/webui/DEPS
+++ b/chrome/browser/ui/webui/DEPS
@@ -4,6 +4,7 @@
 
   "+sync/js",
   "+sync/internal_api/public/util/weak_handle.h",
+  "+sync/internal_api/public/events",
 
   # Other libraries.
   "+device/bluetooth",
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 6328745..abf539f 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -127,8 +127,6 @@
 
 #if defined(USE_AURA)
 #include "chrome/browser/ui/webui/gesture_config_ui.h"
-#include "ui/keyboard/keyboard_constants.h"
-#include "ui/keyboard/keyboard_ui_controller.h"
 #endif
 
 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
@@ -459,8 +457,6 @@
 #if defined(USE_AURA)
   if (url.host() == chrome::kChromeUIGestureConfigHost)
     return &NewWebUI<GestureConfigUI>;
-  if (url.host() == keyboard::kKeyboardWebUIHost)
-    return &NewWebUI<keyboard::KeyboardUIController>;
 #endif
 
 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) && !defined(OS_IOS)
diff --git a/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc b/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
index 47c1b3f..e0ab916 100644
--- a/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/first_run/first_run_ui.cc
@@ -14,6 +14,7 @@
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "grit/browser_resources.h"
+#include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
@@ -41,8 +42,11 @@
       "trayText", l10n_util::GetStringUTF16(IDS_FIRST_RUN_TRAY_STEP_TEXT));
   localized_strings->SetString(
       "helpHeader", l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_HEADER));
+  base::string16 product_name =
+      l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
   localized_strings->SetString(
-      "helpText1", l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_TEXT_1));
+      "helpText1", l10n_util::GetStringFUTF16(IDS_FIRST_RUN_HELP_STEP_TEXT_1,
+                                              product_name));
   localized_strings->SetString(
       "helpText2", l10n_util::GetStringUTF16(IDS_FIRST_RUN_HELP_STEP_TEXT_2));
   localized_strings->SetString(
diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
index 1068d19..016c94a 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.cc
@@ -43,7 +43,10 @@
       show_on_init_(false),
       state_(APP_LAUNCH_STATE_LOADING_AUTH_FILE),
       network_state_informer_(network_state_informer),
-      error_screen_actor_(error_screen_actor) {
+      error_screen_actor_(error_screen_actor),
+      online_state_(false),
+      network_config_done_(false),
+      network_config_requested_(false) {
   network_state_informer_->AddObserver(this);
 }
 
@@ -101,6 +104,10 @@
               &AppLaunchSplashScreenHandler::HandleConfigureNetwork);
   AddCallback("cancelAppLaunch",
               &AppLaunchSplashScreenHandler::HandleCancelAppLaunch);
+  AddCallback("continueAppLaunch",
+              &AppLaunchSplashScreenHandler::HandleContinueAppLaunch);
+  AddCallback("networkConfigRequest",
+              &AppLaunchSplashScreenHandler::HandleNetworkConfigRequested);
 }
 
 void AppLaunchSplashScreenHandler::PrepareToShow() {
@@ -133,8 +140,11 @@
 void AppLaunchSplashScreenHandler::ShowNetworkConfigureUI() {
   NetworkStateInformer::State state = network_state_informer_->state();
   if (state == NetworkStateInformer::ONLINE) {
-    delegate_->OnNetworkStateChanged(true);
-    return;
+    online_state_ = true;
+    if (!network_config_requested_) {
+      delegate_->OnNetworkStateChanged(true);
+      return;
+    }
   }
 
   const std::string network_path = network_state_informer_->network_path();
@@ -162,6 +172,11 @@
           ErrorScreen::ERROR_STATE_OFFLINE, network_name);
       break;
     }
+    case NetworkStateInformer::ONLINE: {
+      error_screen_actor_->SetErrorState(
+          ErrorScreen::ERROR_STATE_KIOSK_ONLINE, network_name);
+      break;
+    }
     default:
       error_screen_actor_->SetErrorState(
           ErrorScreen::ERROR_STATE_OFFLINE, network_name);
@@ -195,8 +210,11 @@
     return;
   }
 
-  NetworkStateInformer::State state = network_state_informer_->state();
-  delegate_->OnNetworkStateChanged(state == NetworkStateInformer::ONLINE);
+  bool new_online_state =
+      network_state_informer_->state() == NetworkStateInformer::ONLINE;
+  delegate_->OnNetworkStateChanged(new_online_state);
+
+  online_state_ = new_online_state;
 }
 
 void AppLaunchSplashScreenHandler::PopulateAppInfo(
@@ -253,4 +271,22 @@
     LOG(WARNING) << "No delegate set to handle cancel app launch";
 }
 
+void AppLaunchSplashScreenHandler::HandleNetworkConfigRequested() {
+  if (!delegate_ || network_config_done_)
+    return;
+
+  network_config_requested_ = true;
+  delegate_->OnNetworkConfigRequested(true);
+}
+
+void AppLaunchSplashScreenHandler::HandleContinueAppLaunch() {
+  DCHECK(online_state_);
+  if (delegate_ && online_state_) {
+    network_config_requested_ = false;
+    network_config_done_ = true;
+    delegate_->OnNetworkConfigRequested(false);
+    Show(app_id_);
+  }
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
index 50c3e33..9238638 100644
--- a/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/app_launch_splash_screen_handler.h
@@ -55,6 +55,8 @@
   int GetProgressMessageFromState(AppLaunchState state);
   void HandleConfigureNetwork();
   void HandleCancelAppLaunch();
+  void HandleContinueAppLaunch();
+  void HandleNetworkConfigRequested();
 
   AppLaunchSplashScreenHandler::Delegate* delegate_;
   bool show_on_init_;
@@ -63,6 +65,12 @@
 
   scoped_refptr<NetworkStateInformer> network_state_informer_;
   ErrorScreenActor* error_screen_actor_;
+  // True if we are online.
+  bool online_state_;
+  // True if we have network config screen was already shown before.
+  bool network_config_done_;
+  // True if we have manually requested network config screen.
+  bool network_config_requested_;
 
   DISALLOW_COPY_AND_ASSIGN(AppLaunchSplashScreenHandler);
 };
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
index 865f324..6af9d52 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -30,6 +30,7 @@
 #include "net/url_request/url_request_context_getter.h"
 #include "ui/base/l10n/l10n_util.h"
 
+namespace chromeos {
 namespace {
 
 const char kJsScreenPath[] = "login.OAuthEnrollmentScreen";
@@ -42,6 +43,25 @@
 const char kEnrollmentStepSignin[] = "signin";
 const char kEnrollmentStepSuccess[] = "success";
 
+// Enrollment mode strings.
+const char kEnrollmentModeManual[] = "manual";
+const char kEnrollmentModeForced[] = "forced";
+const char kEnrollmentModeAuto[] = "auto";
+
+std::string EnrollmentModeToString(EnrollmentScreenActor::EnrollmentMode mode) {
+  switch (mode) {
+    case EnrollmentScreenActor::ENROLLMENT_MODE_MANUAL:
+      return kEnrollmentModeManual;
+    case EnrollmentScreenActor::ENROLLMENT_MODE_FORCED:
+      return kEnrollmentModeForced;
+    case EnrollmentScreenActor::ENROLLMENT_MODE_AUTO:
+      return kEnrollmentModeAuto;
+  }
+
+  NOTREACHED() << "Bad enrollment mode " << mode;
+  return kEnrollmentModeManual;
+}
+
 // A helper class that takes care of asynchronously revoking a given token.
 class TokenRevoker : public GaiaAuthConsumer {
  public:
@@ -68,16 +88,13 @@
 
 }  // namespace
 
-namespace chromeos {
-
 // EnrollmentScreenHandler, public ------------------------------
 
 EnrollmentScreenHandler::EnrollmentScreenHandler()
     : BaseScreenHandler(kJsScreenPath),
       controller_(NULL),
       show_on_init_(false),
-      is_auto_enrollment_(false),
-      can_exit_enrollment_(true),
+      enrollment_mode_(ENROLLMENT_MODE_MANUAL),
       browsing_data_remover_(NULL) {
   set_async_assets_load_id(OobeUI::kScreenOobeEnrollment);
 }
@@ -103,15 +120,13 @@
 // EnrollmentScreenHandler
 //      EnrollmentScreenActor implementation -----------------------------------
 
-void EnrollmentScreenHandler::SetParameters(Controller* controller,
-                                            bool is_auto_enrollment,
-                                            bool can_exit_enrollment,
-                                            const std::string& user) {
+void EnrollmentScreenHandler::SetParameters(
+    Controller* controller,
+    EnrollmentMode enrollment_mode,
+    const std::string& management_domain) {
   controller_ = controller;
-  is_auto_enrollment_ = is_auto_enrollment;
-  can_exit_enrollment_ = can_exit_enrollment;
-  if (is_auto_enrollment_)
-    user_ = user;
+  enrollment_mode_ = enrollment_mode;
+  management_domain_ = management_domain;
 }
 
 void EnrollmentScreenHandler::PrepareToShow() {
@@ -224,14 +239,17 @@
     case policy::EnrollmentStatus::STATUS_REGISTRATION_FAILED:
       // Some special cases for generating a nicer message that's more helpful.
       switch (status.client_status()) {
+        case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
+          ShowError(IDS_ENTERPRISE_ENROLLMENT_ACCOUNT_ERROR, true);
+          break;
         case policy::DM_STATUS_SERVICE_MISSING_LICENSES:
           ShowError(IDS_ENTERPRISE_ENROLLMENT_MISSING_LICENSES_ERROR, true);
           break;
         case policy::DM_STATUS_SERVICE_DEPROVISIONED:
           ShowError(IDS_ENTERPRISE_ENROLLMENT_DEPROVISIONED_ERROR, true);
           break;
-        case policy::DM_STATUS_SERVICE_MANAGEMENT_NOT_SUPPORTED:
-          ShowError(IDS_ENTERPRISE_ENROLLMENT_ACCOUNT_ERROR, true);
+        case policy::DM_STATUS_SERVICE_DOMAIN_MISMATCH:
+          ShowError(IDS_ENTERPRISE_ENROLLMENT_DOMAIN_MISMATCH_ERROR, true);
           break;
         default:
           ShowErrorMessage(
@@ -301,6 +319,9 @@
     LocalizedValuesBuilder* builder) {
   builder->Add("oauthEnrollScreenTitle",
                IDS_ENTERPRISE_ENROLLMENT_SCREEN_TITLE);
+  builder->Add("oauthEnrollDescription", IDS_ENTERPRISE_ENROLLMENT_DESCRIPTION);
+  builder->Add("oauthEnrollReEnrollmentText",
+               IDS_ENTERPRISE_ENROLLMENT_RE_ENROLLMENT_TEXT);
   builder->Add("oauthEnrollRetry", IDS_ENTERPRISE_ENROLLMENT_RETRY);
   builder->Add("oauthEnrollCancel", IDS_ENTERPRISE_ENROLLMENT_CANCEL);
   builder->Add("oauthEnrollDone", IDS_ENTERPRISE_ENROLLMENT_DONE);
@@ -405,8 +426,9 @@
   base::DictionaryValue screen_data;
   screen_data.SetString("signin_url", kGaiaExtStartPage);
   screen_data.SetString("gaiaUrl", GaiaUrls::GetInstance()->gaia_url().spec());
-  screen_data.SetBoolean("is_auto_enrollment", is_auto_enrollment_);
-  screen_data.SetBoolean("prevent_cancellation", !can_exit_enrollment_);
+  screen_data.SetString("enrollment_mode",
+                        EnrollmentModeToString(enrollment_mode_));
+  screen_data.SetString("management_domain", management_domain_);
 
   ShowScreen(OobeUI::kScreenOobeEnrollment, &screen_data);
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
index ad64736..e5e7ffd 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
@@ -39,9 +39,8 @@
 
   // Implements EnrollmentScreenActor:
   virtual void SetParameters(Controller* controller,
-                             bool is_auto_enrollment,
-                             bool can_exit_enrollment,
-                             const std::string& user) OVERRIDE;
+                             EnrollmentMode enrollment_mode,
+                             const std::string& management_domain) OVERRIDE;
   virtual void PrepareToShow() OVERRIDE;
   virtual void Show() OVERRIDE;
   virtual void Hide() OVERRIDE;
@@ -92,18 +91,15 @@
 
   bool show_on_init_;
 
-  // Whether this is an auto-enrollment screen.
-  bool is_auto_enrollment_;
+  // The enrollment mode.
+  EnrollmentMode enrollment_mode_;
 
-  // True of we can exit enrollment and return back to the regular login flow.
-  bool can_exit_enrollment_;
+  // The management domain, if applicable.
+  std::string management_domain_;
 
   // Whether an enrollment attempt has failed.
   bool enrollment_failed_once_;
 
-  // Username of the user signing in.
-  std::string user_;
-
   // This intentionally lives here and not in the controller, since it needs to
   // execute requests in the context of the profile that displays the webui.
   scoped_ptr<policy::PolicyOAuth2TokenFetcher> oauth_fetcher_;
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
index 03ade16..c5641ca 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.cc
@@ -195,6 +195,11 @@
   dialog->Show();
 }
 
+void ErrorScreenHandler::HandleLaunchOobeGuestSession() {
+  if (delegate_)
+    delegate_->OnLaunchOobeGuestSession();
+}
+
 void ErrorScreenHandler::RegisterMessages() {
   AddCallback("showCaptivePortal",
               &ErrorScreenHandler::HandleShowCaptivePortal);
@@ -208,6 +213,8 @@
               &ErrorScreenHandler::HandleDiagnoseButtonClicked);
   AddCallback("configureCertsClicked",
               &ErrorScreenHandler::HandleConfigureCerts);
+  AddCallback("launchOobeGuestSession",
+              &ErrorScreenHandler::HandleLaunchOobeGuestSession);
 }
 
 void ErrorScreenHandler::DeclareLocalizedValues(
@@ -215,6 +222,8 @@
   builder->Add("loginErrorTitle", IDS_LOGIN_ERROR_TITLE);
   builder->Add("signinOfflineMessageBody", IDS_LOGIN_OFFLINE_MESSAGE);
   builder->Add("kioskOfflineMessageBody", IDS_KIOSK_OFFLINE_MESSAGE);
+  builder->Add("kioskOnlineTitle", IDS_LOGIN_NETWORK_RESTORED_TITLE);
+  builder->Add("kioskOnlineMessageBody", IDS_KIOSK_ONLINE_MESSAGE);
   builder->Add("autoEnrollmentOfflineMessageBody",
                IDS_LOGIN_AUTO_ENROLLMENT_OFFLINE_MESSAGE);
   builder->Add("captivePortalTitle", IDS_LOGIN_MAYBE_CAPTIVE_PORTAL_TITLE);
@@ -232,9 +241,11 @@
   builder->Add("localStateErrorPowerwashButton",
                IDS_LOCAL_STATE_ERROR_POWERWASH_BUTTON);
   builder->Add("connectingIndicatorText", IDS_LOGIN_CONNECTING_INDICATOR_TEXT);
+  builder->Add("guestSigninFixNetwork", IDS_LOGIN_GUEST_SIGNIN_FIX_NETWORK);
   builder->Add("rebootButton", IDS_RELAUNCH_BUTTON);
   builder->Add("diagnoseButton", IDS_DIAGNOSE_BUTTON);
   builder->Add("configureCertsButton", IDS_MANAGE_CERTIFICATES);
+  builder->Add("continueButton", IDS_NETWORK_SELECTION_CONTINUE_BUTTON);
 }
 
 void ErrorScreenHandler::Initialize() {
diff --git a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
index 8badf89..94014de 100644
--- a/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/error_screen_handler.h
@@ -58,6 +58,7 @@
   void HandleRebootButtonClicked();
   void HandleDiagnoseButtonClicked();
   void HandleConfigureCerts();
+  void HandleLaunchOobeGuestSession();
 
   // WebUIMessageHandler implementation:
   virtual void RegisterMessages() OVERRIDE;
diff --git a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
index 3c12fda..8e37a38 100644
--- a/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc
@@ -59,6 +59,9 @@
 void EulaScreenHandler::DeclareLocalizedValues(
     LocalizedValuesBuilder* builder) {
   builder->Add("eulaScreenTitle", IDS_EULA_SCREEN_TITLE);
+  builder->AddF("eulaScreenAccessibleTitle",
+                IDS_EULA_SCREEN_ACCESSIBLE_TITLE,
+                IDS_PRODUCT_OS_NAME);
   builder->Add("checkboxLogging", IDS_EULA_CHECKBOX_ENABLE_LOGGING);
   builder->Add("back", IDS_EULA_BACK_BUTTON);
   builder->Add("acceptAgreement", IDS_EULA_ACCEPT_AND_CONTINUE_BUTTON);
diff --git a/chrome/browser/ui/webui/chromeos/login/inline_login_handler_chromeos.cc b/chrome/browser/ui/webui/chromeos/login/inline_login_handler_chromeos.cc
index c5753c7..fb8a231 100644
--- a/chrome/browser/ui/webui/chromeos/login/inline_login_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/chromeos/login/inline_login_handler_chromeos.cc
@@ -9,7 +9,7 @@
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "content/public/browser/web_ui.h"
 
 namespace chromeos {
diff --git a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
index f9f45d5..69c9fa9 100644
--- a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.cc
@@ -7,6 +7,7 @@
 #include "ash/audio/sounds.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
+#include "chrome/browser/chromeos/camera_presence_notifier.h"
 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_flow.h"
 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
@@ -42,8 +43,10 @@
 
 LocallyManagedUserCreationScreenHandler::
     ~LocallyManagedUserCreationScreenHandler() {
-  if (delegate_)
+  if (delegate_) {
+    CameraPresenceNotifier::GetInstance()->RemoveObserver(delegate_);
     delegate_->OnActorDestroyed(this);
+  }
 }
 
 void LocallyManagedUserCreationScreenHandler::DeclareLocalizedValues(
@@ -88,8 +91,12 @@
 
   builder->Add("createManagedUserNameTitle",
                IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_TITLE);
+  builder->Add("createManagedUserNameAccessibleTitle",
+               IDS_CREATE_LOCALLY_MANAGED_USER_SETUP_ACCESSIBLE_TITLE);
   builder->Add("createManagedUserNameExplanation",
                IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_EXPLANATION);
+  builder->Add("createManagedUserNameHint",
+               IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_ACCOUNT_NAME_HINT);
   builder->Add("createManagedUserPasswordTitle",
                IDS_CREATE_LOCALLY_MANAGED_USER_CREATE_PASSWORD_TITLE);
   builder->Add("createManagedUserPasswordExplanation",
@@ -144,7 +151,10 @@
                IDS_OPTIONS_PHOTO_FLIP_ACCESSIBLE_TEXT);
   builder->Add("photoFlippedBackAccessibleText",
                IDS_OPTIONS_PHOTO_FLIPBACK_ACCESSIBLE_TEXT);
-
+  builder->Add("photoCaptureAccessibleText",
+               IDS_OPTIONS_PHOTO_CAPTURE_ACCESSIBLE_TEXT);
+  builder->Add("photoDiscardAccessibleText",
+               IDS_OPTIONS_PHOTO_DISCARD_ACCESSIBLE_TEXT);
 }
 
 void LocallyManagedUserCreationScreenHandler::Initialize() {}
@@ -187,15 +197,12 @@
 
   AddCallback("supervisedUserPhotoTaken",
               &LocallyManagedUserCreationScreenHandler::HandlePhotoTaken);
-  AddCallback("supervisedUserPhotoTaken",
+  AddCallback("supervisedUserTakePhoto",
               &LocallyManagedUserCreationScreenHandler::HandleTakePhoto);
-  AddCallback("supervisedUserPhotoTaken",
+  AddCallback("supervisedUserDiscardPhoto",
               &LocallyManagedUserCreationScreenHandler::HandleDiscardPhoto);
   AddCallback("supervisedUserSelectImage",
               &LocallyManagedUserCreationScreenHandler::HandleSelectImage);
-  AddCallback("supervisedUserCheckCameraPresence",
-              &LocallyManagedUserCreationScreenHandler::
-                  HandleCheckCameraPresence);
   AddCallback("currentSupervisedUserPage",
               &LocallyManagedUserCreationScreenHandler::
                   HandleCurrentSupervisedUserPage);
@@ -227,10 +234,13 @@
 
   if (!delegate_)
     return;
-  delegate_->CheckCameraPresence();
+  CameraPresenceNotifier::GetInstance()->AddObserver(delegate_);
 }
 
-void LocallyManagedUserCreationScreenHandler::Hide() {}
+void LocallyManagedUserCreationScreenHandler::Hide() {
+  if (delegate_)
+    CameraPresenceNotifier::GetInstance()->RemoveObserver(delegate_);
+}
 
 void LocallyManagedUserCreationScreenHandler::ShowIntroPage() {
   CallJS("showIntroPage");
@@ -418,12 +428,6 @@
   ash::PlaySystemSoundIfSpokenFeedback(SOUND_OBJECT_DELETE);
 }
 
-void LocallyManagedUserCreationScreenHandler::HandleCheckCameraPresence() {
-  if (!delegate_)
-    return;
-  delegate_->CheckCameraPresence();
-}
-
 void LocallyManagedUserCreationScreenHandler::HandleSelectImage(
     const std::string& image_url,
     const std::string& image_type) {
diff --git a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h
index 7d7a073..4a35394 100644
--- a/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/locally_managed_user_creation_screen_handler.h
@@ -9,6 +9,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/strings/string16.h"
+#include "chrome/browser/chromeos/camera_presence_notifier.h"
 #include "chrome/browser/chromeos/login/default_user_images.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "content/public/browser/web_ui.h"
@@ -21,10 +22,13 @@
 
 class LocallyManagedUserCreationScreenHandler : public BaseScreenHandler {
  public:
-  class Delegate {
+  class Delegate : public CameraPresenceNotifier::Observer {
    public:
     virtual ~Delegate() {}
 
+    // CameraPresenceNotifier::Observer implementation:
+    virtual void OnCameraPresenceCheckDone(bool is_camera_present) = 0;
+
     // This method is called, when actor is being destroyed. Note, if Delegate
     // is destroyed earlier then it has to call SetDelegate(NULL).
     virtual void OnActorDestroyed(
@@ -57,7 +61,6 @@
     virtual void AbortFlow() = 0;
     virtual void FinishFlow() = 0;
 
-    virtual void CheckCameraPresence() = 0;
     virtual void OnPhotoTaken(const std::string& raw_data) = 0;
     virtual void OnImageSelected(const std::string& image_url,
                                  const std::string& image_type) = 0;
@@ -126,7 +129,6 @@
   void HandlePhotoTaken(const std::string& image_url);
   void HandleTakePhoto();
   void HandleDiscardPhoto();
-  void HandleCheckCameraPresence();
   void HandleSelectImage(const std::string& image_url,
                          const std::string& image_type);
 
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
index 3f1f341..30d2e1f 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.cc
@@ -9,6 +9,7 @@
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/command_line.h"
+#include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/prefs/pref_registry_simple.h"
 #include "base/prefs/pref_service.h"
@@ -18,11 +19,11 @@
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
-#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/chromeos/base/locale_util.h"
 #include "chrome/browser/chromeos/idle_detector.h"
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/login/input_events_blocker.h"
+#include "chrome/browser/chromeos/login/login_display_host.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/screens/core_oobe_actor.h"
 #include "chrome/browser/chromeos/system/input_device_settings.h"
@@ -52,9 +53,9 @@
 
 const char kUSLayout[] = "xkb:us::eng";
 
-const int kDerelectDetectionTimeoutSeconds = 8 * 60 * 60; // 8 hours.
-const int kDerelectIdleTimeoutSeconds = 5 * 60; // 5 minutes.
-const int kOobeTimerUpdateIntervalSeconds = 5 * 60; // 5 minutes.
+const int kDerelectDetectionTimeoutSeconds = 8 * 60 * 60;  // 8 hours.
+const int kDerelectIdleTimeoutSeconds = 5 * 60;  // 5 minutes.
+const int kOobeTimerUpdateIntervalSeconds = 5 * 60;  // 5 minutes.
 
 // Returns true if element was inserted.
 bool InsertString(const std::string& str, std::set<std::string>& to) {
@@ -168,6 +169,8 @@
     builder->Add("networkScreenGreeting", IDS_WELCOME_SCREEN_GREETING);
 
   builder->Add("networkScreenTitle", IDS_WELCOME_SCREEN_TITLE);
+  builder->Add("networkScreenAccessibleTitle",
+               IDS_NETWORK_SCREEN_ACCESSIBLE_TITLE);
   builder->Add("selectLanguage", IDS_LANGUAGE_SELECTION_SELECT);
   builder->Add("selectKeyboard", IDS_KEYBOARD_SELECTION_SELECT);
   builder->Add("selectNetwork", IDS_NETWORK_SELECTION_SELECT);
@@ -218,7 +221,7 @@
 // NetworkScreenHandler, private: ----------------------------------------------
 
 void NetworkScreenHandler::HandleOnExit() {
-  detector_.reset();
+  idle_detector_.reset();
   ClearErrors();
   if (screen_)
     screen_->OnContinuePressed();
@@ -297,13 +300,13 @@
 }
 
 void NetworkScreenHandler::StartIdleDetection() {
-  if (!detector_.get()) {
-    detector_.reset(
+  if (!idle_detector_.get()) {
+    idle_detector_.reset(
         new IdleDetector(base::Closure(),
                          base::Bind(&NetworkScreenHandler::OnIdle,
                                     weak_ptr_factory_.GetWeakPtr())));
   }
-  detector_->Start(derelict_idle_timeout_);
+  idle_detector_->Start(derelict_idle_timeout_);
 }
 
 void NetworkScreenHandler::StartOobeTimer() {
diff --git a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
index 627af65..d163df7 100644
--- a/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/network_screen_handler.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/screens/network_screen_actor.h"
@@ -117,13 +118,13 @@
 
   scoped_ptr<CrosSettings::ObserverSubscription> timezone_subscription_;
 
-  scoped_ptr<IdleDetector> detector_;
+  scoped_ptr<IdleDetector> idle_detector_;
 
   base::RepeatingTimer<NetworkScreenHandler> oobe_timer_;
 
   // Timeout to detect if the machine is in a derelict state.
   base::TimeDelta derelict_detection_timeout_;
-  // Timeout before showing our demo up if the machine is in a derelict state.
+  // Timeout before showing our demo app if the machine is in a derelict state.
   base::TimeDelta derelict_idle_timeout_;
   // Time between updating our total time on oobe.
   base::TimeDelta oobe_timer_update_interval_;
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index d22350d..643603f 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -135,6 +135,7 @@
 const char OobeUI::kScreenOobeEula[]        = "eula";
 const char OobeUI::kScreenOobeUpdate[]      = "update";
 const char OobeUI::kScreenOobeEnrollment[]  = "oauth-enrollment";
+const char OobeUI::kScreenOobeReset[]       = "reset";
 const char OobeUI::kScreenGaiaSignin[]      = "gaia-signin";
 const char OobeUI::kScreenAccountPicker[]   = "account-picker";
 const char OobeUI::kScreenKioskAutolaunch[] = "autolaunch";
@@ -390,6 +391,7 @@
   screen_names_[SCREEN_OOBE_EULA] = kScreenOobeEula;
   screen_names_[SCREEN_OOBE_UPDATE] = kScreenOobeUpdate;
   screen_names_[SCREEN_OOBE_ENROLLMENT] = kScreenOobeEnrollment;
+  screen_names_[SCREEN_OOBE_RESET] = kScreenOobeReset;
   screen_names_[SCREEN_GAIA_SIGNIN] = kScreenGaiaSignin;
   screen_names_[SCREEN_ACCOUNT_PICKER] = kScreenAccountPicker;
   screen_names_[SCREEN_KIOSK_AUTOLAUNCH] = kScreenKioskAutolaunch;
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
index 08d66e8..caa7976 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.h
@@ -56,6 +56,7 @@
   static const char kScreenOobeEula[];
   static const char kScreenOobeUpdate[];
   static const char kScreenOobeEnrollment[];
+  static const char kScreenOobeReset[];
   static const char kScreenGaiaSignin[];
   static const char kScreenAccountPicker[];
   static const char kScreenKioskAutolaunch[];
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
index fb40ab3..8312326 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.cc
@@ -7,14 +7,18 @@
 #include <string>
 
 #include "base/command_line.h"
+#include "base/metrics/histogram.h"
 #include "base/prefs/pref_service.h"
+#include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/common/chrome_switches.h"
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
+#include "chrome/browser/chromeos/reset/metrics.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/chromeos_switches.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "chromeos/dbus/session_manager_client.h"
+#include "chromeos/dbus/update_engine_client.h"
 #include "grit/browser_resources.h"
 #include "grit/chromium_strings.h"
 #include "grit/generated_resources.h"
@@ -33,7 +37,11 @@
 ResetScreenHandler::ResetScreenHandler()
     : BaseScreenHandler(kJsScreenPath),
       delegate_(NULL),
-      show_on_init_(false) {
+      show_on_init_(false),
+      restart_required_(true),
+      reboot_was_requested_(false),
+      rollback_available_(false),
+      weak_factory_(this) {
 }
 
 ResetScreenHandler::~ResetScreenHandler() {
@@ -44,12 +52,63 @@
 void ResetScreenHandler::PrepareToShow() {
 }
 
+void ResetScreenHandler::ShowWithParams() {
+  int dialog_type;
+  if (reboot_was_requested_) {
+    dialog_type = rollback_available_ ?
+        reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_AND_ROLLBACK :
+        reset::DIALOG_SHORTCUT_CONFIRMING_POWERWASH_ONLY;
+  } else {
+    dialog_type = rollback_available_ ?
+      reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_AVAILABLE :
+      reset::DIALOG_SHORTCUT_OFFERING_ROLLBACK_UNAVAILABLE;
+  }
+  UMA_HISTOGRAM_ENUMERATION("Reset.ChromeOS.PowerwashDialogShown",
+                            dialog_type,
+                            reset::DIALOG_VIEW_TYPE_SIZE);
+
+  base::DictionaryValue reset_screen_params;
+  reset_screen_params.SetBoolean("showRestartMsg", restart_required_);
+  reset_screen_params.SetBoolean(
+      "showRollbackOption", rollback_available_ && !reboot_was_requested_);
+  reset_screen_params.SetBoolean(
+      "simpleConfirm", reboot_was_requested_ && !rollback_available_);
+  reset_screen_params.SetBoolean(
+      "rollbackConfirm", reboot_was_requested_ && rollback_available_);
+
+  PrefService* prefs = g_browser_process->local_state();
+  prefs->SetBoolean(prefs::kFactoryResetRequested, false);
+  prefs->SetBoolean(prefs::kRollbackRequested, false);
+  prefs->CommitPendingWrite();
+  ShowScreen(kResetScreen, &reset_screen_params);
+}
+
 void ResetScreenHandler::Show() {
   if (!page_is_ready()) {
     show_on_init_ = true;
     return;
   }
-  ShowScreen(kResetScreen, NULL);
+
+  PrefService* prefs = g_browser_process->local_state();
+  restart_required_ = !CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kFirstExecAfterBoot);
+  reboot_was_requested_ = false;
+  rollback_available_ = false;
+  if (!restart_required_)  // First exec after boot.
+    reboot_was_requested_ = prefs->GetBoolean(prefs::kFactoryResetRequested);
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kEnableRollbackOption)) {
+    rollback_available_ = false;
+    ShowWithParams();
+  } else if (!restart_required_ && reboot_was_requested_) {
+    // First exec after boot.
+    rollback_available_ = prefs->GetBoolean(prefs::kRollbackRequested);
+    ShowWithParams();
+  } else {
+    chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->
+        CanRollbackCheck(base::Bind(&ResetScreenHandler::OnRollbackCheck,
+        weak_factory_.GetWeakPtr()));
+  }
 }
 
 void ResetScreenHandler::Hide() {
@@ -66,22 +125,46 @@
   builder->Add("resetScreenTitle", IDS_RESET_SCREEN_TITLE);
   builder->Add("cancelButton", IDS_CANCEL);
 
-  builder->AddF("resetWarningText",
+  builder->Add("resetWarningDataDetails",
+               IDS_RESET_SCREEN_WARNING_DETAILS_DATA);
+  builder->Add("resetRestartMessage", IDS_RESET_SCREEN_RESTART_MSG);
+  builder->AddF("resetRollbackOption",
+                IDS_RESET_SCREEN_ROLLBACK_OPTION,
+                IDS_SHORT_PRODUCT_NAME);
+
+  // Different variants of the same UI elements for all dialog cases.
+  builder->Add("resetButtonReset", IDS_RESET_SCREEN_RESET);
+  builder->Add("resetButtonRelaunch", IDS_RELAUNCH_BUTTON);
+  builder->Add("resetButtonPowerwash", IDS_RESET_SCREEN_POWERWASH);
+
+  builder->AddF(
+      "resetAndRollbackWarningTextConfirmational",
+      IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_AND_ROLLBACK_MSG,
+      IDS_SHORT_PRODUCT_NAME);
+  builder->AddF("resetWarningTextConfirmational",
+                IDS_RESET_SCREEN_CONFIRMATION_WARNING_POWERWASH_MSG,
+                IDS_SHORT_PRODUCT_NAME);
+  builder->AddF("resetWarningTextInitial",
                 IDS_RESET_SCREEN_WARNING_MSG,
                 IDS_SHORT_PRODUCT_NAME);
 
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kFirstExecAfterBoot)) {
-    builder->AddF("resetWarningDetails",
-                  IDS_RESET_SCREEN_WARNING_DETAILS,
-                  IDS_SHORT_PRODUCT_NAME);
-    builder->Add("resetButton", IDS_RESET_SCREEN_RESET);
-  } else {
-    builder->AddF("resetWarningDetails",
-                  IDS_RESET_SCREEN_WARNING_DETAILS_RESTART,
-                  IDS_SHORT_PRODUCT_NAME);
-    builder->Add("resetButton", IDS_RELAUNCH_BUTTON);
-  }
+  builder->AddF(
+      "resetAndRollbackWarningDetailsConfirmational",
+      IDS_RESET_SCREEN_CONFIRMATION_WARNING_ROLLBACK_DETAILS,
+      IDS_SHORT_PRODUCT_NAME);
+  builder->AddF("resetWarningDetailsConfirmational",
+                IDS_RESET_SCREEN_CONFIRMATION_WARNING_DETAILS,
+                IDS_SHORT_PRODUCT_NAME);
+  builder->AddF("resetWarningDetailsInitial",
+                IDS_RESET_SCREEN_WARNING_DETAILS,
+                IDS_SHORT_PRODUCT_NAME);
+}
+
+// Invoked from call to CanRollbackCheck upon completion of the DBus call.
+void ResetScreenHandler::OnRollbackCheck(bool can_rollback) {
+  VLOG(1) << "Callback from CanRollbackCheck, result " << can_rollback;
+  rollback_available_ = can_rollback;
+  ShowWithParams();
 }
 
 void ResetScreenHandler::Initialize() {
@@ -95,8 +178,10 @@
 }
 
 void ResetScreenHandler::RegisterMessages() {
-  AddCallback("resetOnCancel", &ResetScreenHandler::HandleOnCancel);
-  AddCallback("resetOnReset", &ResetScreenHandler::HandleOnReset);
+  AddCallback("cancelOnReset", &ResetScreenHandler::HandleOnCancel);
+  AddCallback("restartOnReset", &ResetScreenHandler::HandleOnRestart);
+  AddCallback("powerwashOnReset", &ResetScreenHandler::HandleOnPowerwash);
+  AddCallback("resetOnLearnMore", &ResetScreenHandler::HandleOnLearnMore);
 }
 
 void ResetScreenHandler::HandleOnCancel() {
@@ -104,19 +189,31 @@
     delegate_->OnExit();
 }
 
-void ResetScreenHandler::HandleOnReset() {
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kFirstExecAfterBoot)) {
+void ResetScreenHandler::HandleOnRestart(bool should_rollback) {
+  PrefService* prefs = g_browser_process->local_state();
+  prefs->SetBoolean(prefs::kFactoryResetRequested, true);
+  prefs->SetBoolean(prefs::kRollbackRequested, should_rollback);
+  prefs->CommitPendingWrite();
+
+  chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->RequestRestart();
+}
+
+void ResetScreenHandler::HandleOnPowerwash(bool rollback_checked) {
+  if (rollback_checked && rollback_available_) {
+      chromeos::DBusThreadManager::Get()->GetUpdateEngineClient()->Rollback();
+  } else {
+    if (rollback_checked)
+      NOTREACHED() <<
+          "Rollback was checked but not available. Starting powerwash.";
     chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
         StartDeviceWipe();
-  } else {
-    PrefService* prefs = g_browser_process->local_state();
-    prefs->SetBoolean(prefs::kFactoryResetRequested, true);
-    prefs->CommitPendingWrite();
-
-    chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
-        RequestRestart();
   }
 }
 
+void ResetScreenHandler::HandleOnLearnMore() {
+  if (!help_app_.get())
+    help_app_ = new HelpAppLauncher(GetNativeWindow());
+  help_app_->ShowHelpTopic(HelpAppLauncher::HELP_POWERWASH);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
index dd1ddb5..6836e38 100644
--- a/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/reset_screen_handler.h
@@ -6,6 +6,9 @@
 #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_RESET_SCREEN_HANDLER_H_
 
 #include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/screens/reset_screen_actor.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "content/public/browser/web_ui.h"
@@ -32,16 +35,38 @@
   // WebUIMessageHandler implementation:
   virtual void RegisterMessages() OVERRIDE;
 
+  void OnRollbackCheck(bool can_rollback);
+
  private:
   // JS messages handlers.
   void HandleOnCancel();
-  void HandleOnReset();
+  void HandleOnRestart(bool should_rollback);
+  void HandleOnPowerwash(bool rollback_checked);
+  void HandleOnLearnMore();
+
+  void ShowWithParams();
 
   Delegate* delegate_;
 
+  // Help application used for help dialogs.
+  scoped_refptr<HelpAppLauncher> help_app_;
+
   // Keeps whether screen should be shown right after initialization.
   bool show_on_init_;
 
+  // Keeps whether restart is required before reset.
+  // False if first exec after boot.
+  bool restart_required_;
+
+  // Keeps whether previous reboot was requested from reset screen. Makes sense
+  // for first exec after boot situation.
+  bool reboot_was_requested_;
+
+  // Keeps whether rollback option is available fo.
+  bool rollback_available_;
+
+  base::WeakPtrFactory<ResetScreenHandler> weak_factory_;
+
   DISALLOW_COPY_AND_ASSIGN(ResetScreenHandler);
 };
 
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
index 6dd02b0..e6b546a 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc
@@ -29,6 +29,7 @@
 #include "chrome/browser/chromeos/input_method/input_method_util.h"
 #include "chrome/browser/chromeos/kiosk_mode/kiosk_mode_settings.h"
 #include "chrome/browser/chromeos/login/hwid_checker.h"
+#include "chrome/browser/chromeos/login/login_display_host.h"
 #include "chrome/browser/chromeos/login/login_display_host_impl.h"
 #include "chrome/browser/chromeos/login/multi_profile_user_controller.h"
 #include "chrome/browser/chromeos/login/screen_locker.h"
@@ -310,7 +311,6 @@
       offline_login_active_(false),
       last_network_state_(NetworkStateInformer::UNKNOWN),
       has_pending_auth_ui_(false),
-      wait_for_auto_enrollment_check_(false),
       caps_lock_enabled_(false),
       gaia_screen_handler_(gaia_screen_handler) {
   DCHECK(network_state_informer_.get());
@@ -434,6 +434,9 @@
   builder->Add("easyUnlockTooltip",
                IDS_LOGIN_EASY_UNLOCK_TOOLTIP);
 
+  builder->Add("fatalEnrollmentError",
+               IDS_ENTERPRISE_ENROLLMENT_AUTH_FATAL_ERROR);
+
   if (chromeos::KioskModeSettings::Get()->IsKioskModeEnabled())
     builder->Add("demoLoginMessage", IDS_KIOSK_MODE_LOGIN_MESSAGE);
 
@@ -869,7 +872,12 @@
 
   // TODO(tengs): Move this code once we move unlocking to native code.
   if (ScreenLocker::default_screen_locker()) {
-    PrefService* profile_prefs = Profile::FromWebUI(web_ui())->GetPrefs();
+    UserManager* user_manager = UserManager::Get();
+    const User* user = user_manager->FindUser(username);
+    if (!user)
+      return;
+    PrefService* profile_prefs =
+        user_manager->GetProfileByUser(user)->GetPrefs();
     if (profile_prefs->GetBoolean(prefs::kEasyUnlockShowTutorial)) {
       CallJS("login.AccountPickerScreen.showEasyUnlockBubble");
       profile_prefs->SetBoolean(prefs::kEasyUnlockShowTutorial, false);
@@ -1255,11 +1263,13 @@
       !auto_enrollment_progress_subscription_ &&
       !connector->IsEnterpriseManaged() &&
       LoginDisplayHostImpl::default_host()) {
+    AutoEnrollmentController* auto_enrollment_controller =
+        LoginDisplayHostImpl::default_host()->GetAutoEnrollmentController();
     auto_enrollment_progress_subscription_ =
-        LoginDisplayHostImpl::default_host()
-            ->RegisterAutoEnrollmentProgressHandler(
-                base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
-                           weak_factory_.GetWeakPtr()));
+        auto_enrollment_controller->RegisterProgressCallback(
+            base::Bind(&SigninScreenHandler::ContinueKioskEnableFlow,
+                       weak_factory_.GetWeakPtr()));
+    ContinueKioskEnableFlow(auto_enrollment_controller->state());
   }
 }
 
@@ -1406,8 +1416,6 @@
 
   PrefService* prefs = g_browser_process->local_state();
   if (prefs->GetBoolean(prefs::kFactoryResetRequested)) {
-    prefs->SetBoolean(prefs::kFactoryResetRequested, false);
-    prefs->CommitPendingWrite();
     HandleToggleResetScreen();
     return;
   }
@@ -1716,23 +1724,24 @@
 }
 
 void SigninScreenHandler::ContinueKioskEnableFlow(
-    policy::AutoEnrollmentClient::State state) {
+    policy::AutoEnrollmentState state) {
   // Do not proceed with kiosk enable when auto enroll will be enforced.
   // TODO(xiyuan): Add an error UI feedkback so user knows what happens.
   switch (state) {
-    case policy::AutoEnrollmentClient::STATE_PENDING:
-    case policy::AutoEnrollmentClient::STATE_CONNECTION_ERROR:
+    case policy::AUTO_ENROLLMENT_STATE_IDLE:
+    case policy::AUTO_ENROLLMENT_STATE_PENDING:
+    case policy::AUTO_ENROLLMENT_STATE_CONNECTION_ERROR:
       // Wait for the next callback.
       return;
-    case policy::AutoEnrollmentClient::STATE_TRIGGER_ENROLLMENT:
+    case policy::AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT:
       // Auto-enrollment is on.
       LOG(WARNING) << "Kiosk enable flow aborted because auto enrollment is "
                       "going to be enforced.";
       if (!kiosk_enable_flow_aborted_callback_for_test_.is_null())
         kiosk_enable_flow_aborted_callback_for_test_.Run();
       break;
-    case policy::AutoEnrollmentClient::STATE_SERVER_ERROR:
-    case policy::AutoEnrollmentClient::STATE_NO_ENROLLMENT:
+    case policy::AUTO_ENROLLMENT_STATE_SERVER_ERROR:
+    case policy::AUTO_ENROLLMENT_STATE_NO_ENROLLMENT:
       // Auto-enrollment not applicable.
       if (delegate_)
         delegate_->ShowKioskEnableScreen();
diff --git a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
index 0af9107..d2967a3 100644
--- a/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h
@@ -15,12 +15,11 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/login/enrollment/auto_enrollment_controller.h"
 #include "chrome/browser/chromeos/login/login_display.h"
-#include "chrome/browser/chromeos/login/login_display_host.h"
 #include "chrome/browser/chromeos/login/screens/error_screen_actor.h"
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/net/network_portal_detector.h"
-#include "chrome/browser/chromeos/policy/auto_enrollment_client.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
@@ -438,7 +437,7 @@
   // Invoked when auto enrollment check progresses to decide whether to
   // continue kiosk enable flow. Kiosk enable flow is resumed when
   // |state| indicates that enrollment is not applicable.
-  void ContinueKioskEnableFlow(policy::AutoEnrollmentClient::State state);
+  void ContinueKioskEnableFlow(policy::AutoEnrollmentState state);
 
   // Shows signin screen for |email|.
   void OnShowAddUser(const std::string& email);
@@ -525,11 +524,9 @@
 
   scoped_ptr<CrosSettings::ObserverSubscription> allow_new_user_subscription_;
   scoped_ptr<CrosSettings::ObserverSubscription> allow_guest_subscription_;
-  scoped_ptr<LoginDisplayHost::AutoEnrollmentProgressCallbackSubscription>
+  scoped_ptr<AutoEnrollmentController::ProgressCallbackList::Subscription>
       auto_enrollment_progress_subscription_;
 
-  bool wait_for_auto_enrollment_check_;
-
   bool caps_lock_enabled_;
 
   base::Closure kiosk_enable_flow_aborted_callback_for_test_;
diff --git a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc
index 96e93ba..38b756f 100644
--- a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.cc
@@ -38,6 +38,8 @@
                 IDS_UPDATE_MSG, IDS_SHORT_PRODUCT_NAME);
 
   builder->Add("updateScreenTitle", IDS_UPDATE_SCREEN_TITLE);
+  builder->Add("updateScreenAccessibleTitle",
+               IDS_UPDATE_SCREEN_ACCESSIBLE_TITLE);
   builder->Add("checkingForUpdates", IDS_CHECKING_FOR_UPDATES);
   builder->Add("downloading", IDS_DOWNLOADING);
   builder->Add("downloadingTimeLeftLong", IDS_DOWNLOADING_TIME_LEFT_LONG);
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
index ed1136d..bb048c5 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.cc
@@ -9,6 +9,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
 #include "base/values.h"
+#include "chrome/browser/chromeos/camera_presence_notifier.h"
 #include "chrome/browser/chromeos/login/default_user_images.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
 #include "chrome/browser/chromeos/login/user.h"
@@ -46,8 +47,10 @@
 }
 
 UserImageScreenHandler::~UserImageScreenHandler() {
-  if (screen_)
+  if (screen_) {
+    CameraPresenceNotifier::GetInstance()->RemoveObserver(screen_);
     screen_->OnActorDestroyed(this);
+  }
 }
 
 void UserImageScreenHandler::Initialize() {
@@ -73,12 +76,13 @@
   // When shown, query camera presence.
   if (!screen_)
     return;
-  screen_->CheckCameraPresence();
+  CameraPresenceNotifier::GetInstance()->AddObserver(screen_);
   if (is_ready_)
     screen_->OnScreenReady();
 }
 
 void UserImageScreenHandler::Hide() {
+  CameraPresenceNotifier::GetInstance()->RemoveObserver(screen_);
 }
 
 void UserImageScreenHandler::PrepareToShow() {
@@ -86,9 +90,7 @@
 
 void UserImageScreenHandler::DeclareLocalizedValues(
     LocalizedValuesBuilder* builder) {
-  // TODO(ivankr): string should be renamed to something like
-  // IDS_USER_IMAGE_SCREEN_TITLE (currently used for Take Photo dialog).
-  builder->Add("userImageScreenTitle", IDS_OOBE_PICTURE);
+  builder->Add("userImageScreenTitle", IDS_USER_IMAGE_SCREEN_TITLE);
   builder->Add("userImageScreenDescription",
                IDS_OPTIONS_CHANGE_PICTURE_DIALOG_TEXT);
   builder->Add("takePhoto", IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO);
@@ -118,8 +120,6 @@
   AddCallback("discardPhoto", &UserImageScreenHandler::HandleDiscardPhoto);
   AddCallback("photoTaken", &UserImageScreenHandler::HandlePhotoTaken);
   AddCallback("selectImage", &UserImageScreenHandler::HandleSelectImage);
-  AddCallback("checkCameraPresence",
-              &UserImageScreenHandler::HandleCheckCameraPresence);
   AddCallback("onUserImageAccepted",
               &UserImageScreenHandler::HandleImageAccepted);
   AddCallback("onUserImageScreenShown",
@@ -192,12 +192,6 @@
   ash::PlaySystemSoundIfSpokenFeedback(SOUND_OBJECT_DELETE);
 }
 
-void UserImageScreenHandler::HandleCheckCameraPresence() {
-  if (!screen_)
-    return;
-  screen_->CheckCameraPresence();
-}
-
 void UserImageScreenHandler::HandleSelectImage(const std::string& image_url,
                                                const std::string& image_type,
                                                bool is_user_selection) {
diff --git a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h
index c8a8105..68e3236 100644
--- a/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/user_image_screen_handler.h
@@ -66,9 +66,6 @@
   // Handles 'discard-photo' button click.
   void HandleDiscardPhoto();
 
-  // Handles camera presence check request.
-  void HandleCheckCameraPresence();
-
   // Handles clicking on default user image.
   void HandleSelectImage(const std::string& image_url,
                          const std::string& image_type,
diff --git a/chrome/browser/ui/webui/chromeos/network_ui.cc b/chrome/browser/ui/webui/chromeos/network_ui.cc
index c8d16c7..8f4433d 100644
--- a/chrome/browser/ui/webui/chromeos/network_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/network_ui.cc
@@ -120,9 +120,9 @@
            favorite_list.begin();
        it != favorite_list.end();
        ++it) {
-    base::DictionaryValue* properties = new base::DictionaryValue;
-    (*it)->GetProperties(properties);
-    output->Set((*it)->path(), properties);
+    // Get the complete dictionary of FavoriteState properties.
+    const base::DictionaryValue& properties = (*it)->properties();
+    output->Set((*it)->path(), properties.DeepCopy());
   }
 }
 
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc
index 64fbfff..a2f1c61 100644
--- a/chrome/browser/ui/webui/crashes_ui.cc
+++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -10,14 +10,12 @@
 #include "base/bind_helpers.h"
 #include "base/i18n/time_formatting.h"
 #include "base/memory/ref_counted_memory.h"
-#include "base/prefs/pref_service.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/crash_upload_list.h"
+#include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/chrome_version_info.h"
-#include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -30,10 +28,6 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/settings/cros_settings.h"
-#endif
-
 using content::WebContents;
 using content::WebUIMessageHandler;
 
@@ -128,7 +122,8 @@
 }
 
 void CrashesDOMHandler::UpdateUI() {
-  bool crash_reporting_enabled = CrashesUI::CrashReportingUIEnabled();
+  bool crash_reporting_enabled =
+      MetricsServiceHelper::IsCrashReportingEnabled();
   base::ListValue crash_list;
 
   if (crash_reporting_enabled) {
@@ -175,24 +170,3 @@
   return ResourceBundle::GetSharedInstance().
       LoadDataResourceBytesForScale(IDR_SAD_FAVICON, scale_factor);
 }
-
-// static
-bool CrashesUI::CrashReportingUIEnabled() {
-#if defined(GOOGLE_CHROME_BUILD)
-#if defined(OS_CHROMEOS)
-  bool reporting_enabled = false;
-  chromeos::CrosSettings::Get()->GetBoolean(chromeos::kStatsReportingPref,
-                                            &reporting_enabled);
-  return reporting_enabled;
-#elif defined(OS_ANDROID)
-  // Android has it's own setings for metrics / crash uploading.
-  PrefService* prefs = g_browser_process->local_state();
-  return prefs->GetBoolean(prefs::kCrashReportingEnabled);
-#else
-  PrefService* prefs = g_browser_process->local_state();
-  return prefs->GetBoolean(prefs::kMetricsReportingEnabled);
-#endif
-#else
-  return false;
-#endif
-}
diff --git a/chrome/browser/ui/webui/crashes_ui.h b/chrome/browser/ui/webui/crashes_ui.h
index 47b1290..99a678c 100644
--- a/chrome/browser/ui/webui/crashes_ui.h
+++ b/chrome/browser/ui/webui/crashes_ui.h
@@ -19,9 +19,6 @@
   static base::RefCountedMemory* GetFaviconResourceBytes(
       ui::ScaleFactor scale_factor);
 
-  // Whether crash reporting UI has been enabled.
-  static bool CrashReportingUIEnabled();
-
  private:
   DISALLOW_COPY_AND_ASSIGN(CrashesUI);
 };
diff --git a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
index 15c0cb2..c03ee31 100644
--- a/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
+++ b/chrome/browser/ui/webui/extensions/chromeos/kiosk_apps_handler.cc
@@ -193,6 +193,8 @@
   base::StringValue app_id_value(app_id);
   web_ui()->CallJavascriptFunction("extensions.KioskAppsOverlay.showError",
                                    app_id_value);
+
+  kiosk_app_manager_->RemoveApp(app_id);
 }
 
 
diff --git a/chrome/browser/ui/webui/extensions/command_handler.cc b/chrome/browser/ui/webui/extensions/command_handler.cc
index a8b525f..6a51761 100644
--- a/chrome/browser/ui/webui/extensions/command_handler.cc
+++ b/chrome/browser/ui/webui/extensions/command_handler.cc
@@ -8,6 +8,7 @@
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/api/commands/command_service.h"
+#include "chrome/browser/extensions/extension_commands_global_registry.h"
 #include "chrome/browser/extensions/extension_keybinding_registry.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -124,8 +125,13 @@
 void CommandHandler::HandleSetShortcutHandlingSuspended(
     const base::ListValue* args) {
   bool suspended;
-  if (args->GetBoolean(0, &suspended))
+  if (args->GetBoolean(0, &suspended)) {
+    // Suspend/Resume normal shortcut handling.
     ExtensionKeybindingRegistry::SetShortcutHandlingSuspended(suspended);
+
+    // Suspend/Resume global shortcut handling.
+    ExtensionCommandsGlobalRegistry::SetShortcutHandlingSuspended(suspended);
+  }
 }
 
 void CommandHandler::GetAllCommands(base::DictionaryValue* commands) {
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
index 5581bba..bdb8b95 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.cc
@@ -38,6 +38,7 @@
 #include "chrome/browser/extensions/extension_tab_util.h"
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/extension_warning_set.h"
+#include "chrome/browser/extensions/install_verifier.h"
 #include "chrome/browser/extensions/unpacked_installer.h"
 #include "chrome/browser/extensions/updater/extension_updater.h"
 #include "chrome/browser/google/google_util.h"
@@ -157,6 +158,7 @@
       registered_for_notifications_(false),
       warning_service_observer_(this),
       error_console_observer_(this),
+      extension_prefs_observer_(this),
       should_do_verification_check_(false) {
 }
 
@@ -178,6 +180,7 @@
       registered_for_notifications_(false),
       warning_service_observer_(this),
       error_console_observer_(this),
+      extension_prefs_observer_(this),
       should_do_verification_check_(false) {
 }
 
@@ -552,11 +555,51 @@
                  AsWeakPtr()));
 }
 
+void ExtensionSettingsHandler::LoadUnpackedExtension(
+    const base::FilePath& path) {
+  UnpackedInstaller::Create(extension_service_)->Load(path);
+}
+
+int ExtensionSettingsHandler::IndexOfLoadingPath(const base::FilePath& path) {
+  for (size_t i = 0; i < loading_extension_directories_.size(); ++i) {
+    if (path == loading_extension_directories_[i])
+      return i;
+  }
+  return -1;
+}
+
+void ExtensionSettingsHandler::AddLoadingPath(const base::FilePath& path) {
+  DCHECK(IndexOfLoadingPath(path) == -1);
+
+  if (loading_extension_directories_.empty()) {
+    Profile* profile = Profile::FromWebUI(web_ui());
+    registrar_.Add(this,
+                   chrome::NOTIFICATION_EXTENSION_LOAD_RETRY,
+                   content::Source<Profile>(profile));
+  }
+  loading_extension_directories_.push_back(path);
+}
+
+void ExtensionSettingsHandler::RemoveLoadingPath(const base::FilePath& path) {
+  int index = IndexOfLoadingPath(path);
+  DCHECK(index != -1);
+
+  loading_extension_directories_.erase(loading_extension_directories_.begin() +
+                                       index);
+  if (loading_extension_directories_.empty()) {
+    Profile* profile = Profile::FromWebUI(web_ui());
+    registrar_.Remove(this,
+                      chrome::NOTIFICATION_EXTENSION_LOAD_RETRY,
+                      content::Source<Profile>(profile));
+  }
+}
+
 void ExtensionSettingsHandler::FileSelected(const base::FilePath& path,
                                             int index,
                                             void* params) {
   last_unpacked_directory_ = base::FilePath(path);
-  UnpackedInstaller::Create(extension_service_)->Load(path);
+  AddLoadingPath(last_unpacked_directory_);
+  LoadUnpackedExtension(path);
 }
 
 void ExtensionSettingsHandler::MultiFilesSelected(
@@ -595,7 +638,7 @@
     case chrome::NOTIFICATION_EXTENSION_HOST_CREATED:
       source_profile = content::Source<Profile>(source).ptr();
       if (!profile->IsSameProfile(source_profile))
-          return;
+        return;
       MaybeUpdateAfterNotification();
       break;
     case content::NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED: {
@@ -606,7 +649,20 @@
       MaybeUpdateAfterNotification();
       break;
     }
-    case chrome::NOTIFICATION_EXTENSION_LOADED:
+    case chrome::NOTIFICATION_EXTENSION_LOAD_RETRY: {
+      std::pair<bool, const base::FilePath&>* retry_and_path =
+          content::Details<std::pair<bool, const base::FilePath&> >(details)
+              .ptr();
+      HandleLoadRetryMessage(retry_and_path->first, retry_and_path->second);
+      break;
+    }
+    case chrome::NOTIFICATION_EXTENSION_LOADED: {
+      const base::FilePath& path =
+          content::Details<const Extension>(details).ptr()->path();
+      if (IndexOfLoadingPath(path) != -1)
+        RemoveLoadingPath(path);
+      // Fall through.
+    }
     case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED:
     case chrome::NOTIFICATION_EXTENSION_UNINSTALLED:
     case chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED:
@@ -627,6 +683,12 @@
   }
 }
 
+void ExtensionSettingsHandler::OnExtensionDisableReasonsChanged(
+    const std::string& extension_id,
+    int disable_reasons) {
+  MaybeUpdateAfterNotification();
+}
+
 void ExtensionSettingsHandler::ExtensionUninstallAccepted() {
   DCHECK(!extension_id_prompting_.empty());
 
@@ -637,8 +699,9 @@
   const Extension* extension =
       extension_service_->GetExtensionById(extension_id_prompting_, true);
   if (!extension) {
-    extension = extension_service_->GetTerminatedExtension(
-        extension_id_prompting_);
+    extension =
+        ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))->GetExtensionById(
+            extension_id_prompting_, ExtensionRegistry::TERMINATED);
     was_terminated = true;
   }
   if (!extension)
@@ -691,6 +754,7 @@
 
   for (std::vector<const Extension*>::iterator iter =
        unpacked_extensions.begin(); iter != unpacked_extensions.end(); ++iter) {
+    AddLoadingPath((*iter)->path());
     extension_service_->ReloadExtension((*iter)->id());
   }
 }
@@ -760,7 +824,9 @@
                         should_do_verification_check_);
   if (should_do_verification_check_) {
     should_do_verification_check_ = false;
-    extension_service_->VerifyAllExtensions(false);  // bootstrap=false.
+    ExtensionSystem::Get(Profile::FromWebUI(web_ui()))
+        ->install_verifier()
+        ->VerifyAllExtensions();
   }
 }
 
@@ -830,6 +896,10 @@
     const base::ListValue* args) {
   std::string extension_id = base::UTF16ToUTF8(ExtractStringValue(args));
   CHECK(!extension_id.empty());
+  const Extension* extension =
+      extension_service_->GetInstalledExtension(extension_id);
+  if (extension)
+    AddLoadingPath(extension->path());
   extension_service_->ReloadExtension(extension_id);
 }
 
@@ -966,9 +1036,8 @@
   std::string extension_id(base::UTF16ToUTF8(ExtractStringValue(args)));
   CHECK(!extension_id.empty());
   const Extension* extension =
-      extension_service_->GetExtensionById(extension_id, true);
-  if (!extension)
-    extension = extension_service_->GetTerminatedExtension(extension_id);
+      ExtensionRegistry::Get(Profile::FromWebUI(web_ui()))
+          ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
   if (!extension)
     return;
 
@@ -1249,9 +1318,21 @@
   } else {
     ExtensionErrorReporter::GetInstance()->ReportError(
         base::UTF8ToUTF16(JoinString(requirement_errors, ' ')),
-        true /* be noisy */);
+        true,   // Be noisy.
+        NULL);  // Caller expects no response.
   }
   requirements_checker_.reset();
 }
 
+void ExtensionSettingsHandler::HandleLoadRetryMessage(
+    bool retry,
+    const base::FilePath& path) {
+  if (IndexOfLoadingPath(path) == -1)
+    return;  // Not an extension we're tracking.
+  if (retry)
+    LoadUnpackedExtension(path);
+  else
+    RemoveLoadingPath(path);
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/ui/webui/extensions/extension_settings_handler.h b/chrome/browser/ui/webui/extensions/extension_settings_handler.h
index 5c48818..4eea56b 100644
--- a/chrome/browser/ui/webui/extensions/extension_settings_handler.h
+++ b/chrome/browser/ui/webui/extensions/extension_settings_handler.h
@@ -23,6 +23,7 @@
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_ui_message_handler.h"
+#include "extensions/browser/extension_prefs.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 #include "url/gurl.h"
 
@@ -69,6 +70,7 @@
       public ui::SelectFileDialog::Listener,
       public ErrorConsole::Observer,
       public ExtensionInstallPrompt::Delegate,
+      public ExtensionPrefs::Observer,
       public ExtensionUninstallDialog::Delegate,
       public ExtensionWarningService::Observer,
       public base::SupportsWeakPtr<ExtensionSettingsHandler> {
@@ -106,6 +108,21 @@
   // WebUIMessageHandler implementation.
   virtual void RegisterMessages() OVERRIDE;
 
+  // Loads an unpacked extension from |path|.
+  void LoadUnpackedExtension(const base::FilePath& path);
+
+  // Returns the index of the given FilePath in the vector of currently loading
+  // extensions. Returns -1 if not found.
+  int IndexOfLoadingPath(const base::FilePath& path);
+
+  // Adds |path| to the vector of currently loading extensions. Registers
+  // for the load retry notification if vector is empty before call.
+  void AddLoadingPath(const base::FilePath& path);
+
+  // Removes |path| from the vector of currently loading extensions. Unregisters
+  // for the load retry notification if vector is empty after call.
+  void RemoveLoadingPath(const base::FilePath& path);
+
   // SelectFileDialog::Listener implementation.
   virtual void FileSelected(const base::FilePath& path,
                             int index,
@@ -122,6 +139,10 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
+  // ExtensionPrefs::Observer implementation.
+  virtual void OnExtensionDisableReasonsChanged(const std::string& extension_id,
+                                                int disable_reasons) OVERRIDE;
+
   // ExtensionUninstallDialog::Delegate implementation, used for receiving
   // notification about uninstall confirmation dialog selections.
   virtual void ExtensionUninstallAccepted() OVERRIDE;
@@ -211,6 +232,15 @@
   void OnRequirementsChecked(std::string extension_id,
                              std::vector<std::string> requirement_errors);
 
+  // Handles the load retry notification sent from
+  // ExtensionService::ReportExtensionLoadError. Attempts to retry loading
+  // extension from |path| if retry is true, otherwise removes |path| from the
+  // vector of currently loading extensions.
+  //
+  // Does nothing if |path| is not a currently loading extension this object is
+  // tracking.
+  void HandleLoadRetryMessage(bool retry, const base::FilePath& path);
+
   // Our model.  Outlives us since it's owned by our containing profile.
   ExtensionService* extension_service_;
 
@@ -224,6 +254,10 @@
   // loaded.
   base::FilePath last_unpacked_directory_;
 
+  // Used to keep track of FilePaths for all extensions in the process of
+  // loading for the purpose of retrying on load failure.
+  std::vector<base::FilePath> loading_extension_directories_;
+
   // Used to show confirmation UI for uninstalling extensions in incognito mode.
   scoped_ptr<ExtensionUninstallDialog> extension_uninstall_dialog_;
 
@@ -269,6 +303,11 @@
   // An observer to listen for when Extension errors are reported.
   ScopedObserver<ErrorConsole, ErrorConsole::Observer> error_console_observer_;
 
+  // An observer to listen for notable changes in the ExtensionPrefs, like
+  // a change in Disable Reasons.
+  ScopedObserver<ExtensionPrefs, ExtensionPrefs::Observer>
+      extension_prefs_observer_;
+
   // Whether we found any DISABLE_NOT_VERIFIED extensions and want to kick off
   // a verification check to try and rescue them.
   bool should_do_verification_check_;
diff --git a/chrome/browser/ui/webui/extensions/install_extension_handler.cc b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
index 3463c09..a87d439 100644
--- a/chrome/browser/ui/webui/extensions/install_extension_handler.cc
+++ b/chrome/browser/ui/webui/extensions/install_extension_handler.cc
@@ -74,13 +74,15 @@
     return;
   }
 
-  const content::DropData::FileInfo& file_info = drop_data->filenames.front();
+  const ui::FileInfo& file_info = drop_data->filenames.front();
 
-  file_to_install_ = base::FilePath::FromUTF16Unsafe(file_info.path);
+  file_to_install_ = file_info.path;
   // Use the display name if provided, for checking file names
   // (.path is likely a random hash value in that case).
-  file_display_name_ =
-      file_info.display_name.empty() ? file_info.path : file_info.display_name;
+  // TODO(dcheng): It would be nice to make this a FilePath too.
+  file_display_name_ = file_info.display_name.empty()
+                           ? file_info.path.AsUTF16Unsafe()
+                           : file_info.display_name.AsUTF16Unsafe();
 }
 
 void InstallExtensionHandler::HandleStopDragMessage(
diff --git a/chrome/browser/ui/webui/flash_ui.cc b/chrome/browser/ui/webui/flash_ui.cc
index 7809614..e9f1222 100644
--- a/chrome/browser/ui/webui/flash_ui.cc
+++ b/chrome/browser/ui/webui/flash_ui.cc
@@ -20,9 +20,9 @@
 #include "base/timer/timer.h"
 #include "base/values.h"
 #include "chrome/browser/crash_upload_list.h"
+#include "chrome/browser/metrics/metrics_service.h"
 #include "chrome/browser/plugins/plugin_prefs.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/crashes_ui.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/url_constants.h"
 #include "content/public/browser/gpu_data_manager.h"
@@ -298,7 +298,8 @@
 
   // Crash information.
   AddPair(list, base::string16(), "--- Crash data ---");
-  bool crash_reporting_enabled = CrashesUI::CrashReportingUIEnabled();
+  bool crash_reporting_enabled =
+      MetricsServiceHelper::IsCrashReportingEnabled();
   if (crash_reporting_enabled) {
     std::vector<CrashUploadList::UploadInfo> crashes;
     upload_list_->GetUploads(10, &crashes);
diff --git a/chrome/browser/ui/webui/inspect_ui_browsertest.cc b/chrome/browser/ui/webui/inspect_ui_browsertest.cc
index 3028744..454898f 100644
--- a/chrome/browser/ui/webui/inspect_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/inspect_ui_browsertest.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "chrome/browser/devtools/devtools_adb_bridge.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/url_constants.h"
-#include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/base/web_ui_browsertest.h"
 #include "content/public/browser/navigation_details.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
@@ -20,17 +21,29 @@
 const char kSharedWorkerJs[] =
     "files/workers/workers_ui_shared_worker.js";
 
-class InspectUITest : public InProcessBrowserTest {
+class InspectUITest : public WebUIBrowserTest {
  public:
   InspectUITest() {}
 
+  virtual void SetUpOnMainThread() OVERRIDE {
+    WebUIBrowserTest::SetUpOnMainThread();
+    AddLibrary(base::FilePath(FILE_PATH_LITERAL("inspect_ui_test.js")));
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(InspectUITest);
 };
 
-// The test fails on Mac OS X and Windows, see crbug.com/89583
-// Intermittently fails on Linux.
-IN_PROC_BROWSER_TEST_F(InspectUITest, DISABLED_SharedWorkersList) {
+IN_PROC_BROWSER_TEST_F(InspectUITest, InspectUIPage) {
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIInspectURL));
+  ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
+      "testTargetListed",
+      new base::StringValue("#pages"),
+      new base::StringValue("populateWebContentsTargets"),
+      new base::StringValue(chrome::kChromeUIInspectURL)));
+}
+
+IN_PROC_BROWSER_TEST_F(InspectUITest, SharedWorker) {
   ASSERT_TRUE(test_server()->Start());
   GURL url = test_server()->GetURL(kSharedWorkerTestPage);
   ui_test_utils::NavigateToURL(browser(), url);
@@ -41,25 +54,32 @@
       NEW_FOREGROUND_TAB,
       ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
 
-  WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_TRUE(web_contents != NULL);
+  ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
+      "testTargetListed",
+      new base::StringValue("#workers"),
+      new base::StringValue("populateWorkerTargets"),
+      new base::StringValue(kSharedWorkerJs)));
 
-  std::string result;
-  ASSERT_TRUE(
-      content::ExecuteScriptAndExtractString(
-          web_contents,
-          "window.domAutomationController.send("
-          "    '' + document.body.textContent);",
-          &result));
-  ASSERT_TRUE(result.find(kSharedWorkerJs) != std::string::npos);
-  ASSERT_TRUE(result.find(kSharedWorkerTestPage) != std::string::npos);
+  ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest(
+      "testTargetListed",
+      new base::StringValue("#pages"),
+      new base::StringValue("populateWebContentsTargets"),
+      new base::StringValue(kSharedWorkerTestPage)));
+}
+
+IN_PROC_BROWSER_TEST_F(InspectUITest, AdbTargets) {
+  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIInspectURL));
+
+  scoped_refptr<DevToolsAdbBridge> adb_bridge =
+      DevToolsAdbBridge::Factory::GetForProfile(browser()->profile());
+  adb_bridge->set_device_provider_for_test(
+      AndroidDeviceProvider::GetMockDeviceProviderForTest());
+
+  ASSERT_TRUE(WebUIBrowserTest::RunJavascriptAsyncTest("testAdbTargetsListed"));
 }
 
 IN_PROC_BROWSER_TEST_F(InspectUITest, ReloadCrash) {
   ASSERT_TRUE(test_server()->Start());
-  // Make sure that loading the inspect UI twice in the same tab
-  // connects/disconnects listeners without crashing.
   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIInspectURL));
   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIInspectURL));
 }
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
index 27caf50..cb8a3e4 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -10,9 +10,9 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/local_discovery/test_service_discovery_client.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h"
@@ -20,7 +20,8 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chrome/test/base/web_ui_browsertest.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/http/http_status_code.h"
 #include "net/url_request/test_url_fetcher_factory.h"
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
index e791a32..5bd0e91 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.cc
@@ -24,14 +24,14 @@
 #include "chrome/browser/printing/cloud_print/cloud_print_url.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/user_metrics.h"
 #include "content/public/browser/web_ui.h"
@@ -42,8 +42,7 @@
 #include "net/http/http_status_code.h"
 #include "ui/base/l10n/l10n_util.h"
 
-#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS) && \
-  !defined(OS_MACOSX)
+#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS)
 #define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE
 #endif
 
@@ -64,12 +63,12 @@
   cloud_print_connector_ui_enabled_ =
       CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kEnableCloudPrintProxy);
-#elif !defined(OS_CHROMEOS)
+#else
   // Always enabled for Linux and Google Chrome Windows builds.
   // Never enabled for Chrome OS, we don't even need to indicate it.
   cloud_print_connector_ui_enabled_ = true;
 #endif
-#endif  // !defined(OS_MACOSX)
+#endif  // defined(CLOUD_PRINT_CONNECTOR_UI_AVAILABLE)
 }
 
 LocalDiscoveryUIHandler::~LocalDiscoveryUIHandler() {
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
index 3f898ae..119ce00 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_handler.h
@@ -17,8 +17,7 @@
 #include "chrome/browser/signin/signin_manager.h"
 #include "content/public/browser/web_ui_message_handler.h"
 
-#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS) && \
-  !defined(OS_MACOSX)
+#if defined(ENABLE_FULL_PRINTING) && !defined(OS_CHROMEOS)
 #define CLOUD_PRINT_CONNECTOR_UI_AVAILABLE
 #endif
 
diff --git a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
index fdd528c..10d68a7 100644
--- a/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
+++ b/chrome/browser/ui/webui/media/webrtc_logs_ui.cc
@@ -11,11 +11,13 @@
 #include "base/i18n/time_formatting.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/prefs/pref_service.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/media/webrtc_log_upload_list.h"
+#include "chrome/browser/media/webrtc_log_list.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/upload_list.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
@@ -49,9 +51,19 @@
                              IDS_WEBRTC_LOGS_LOG_COUNT_BANNER_FORMAT);
   source->AddLocalizedString("webrtcLogHeaderFormat",
                              IDS_WEBRTC_LOGS_LOG_HEADER_FORMAT);
-  source->AddLocalizedString("webrtcLogTimeFormat",
-                             IDS_WEBRTC_LOGS_LOG_TIME_FORMAT);
+  source->AddLocalizedString("webrtcLogLocalFileLabelFormat",
+                             IDS_WEBRTC_LOGS_LOG_LOCAL_FILE_LABEL_FORMAT);
+  source->AddLocalizedString("webrtcLogLocalFileFormat",
+                             IDS_WEBRTC_LOGS_LOG_LOCAL_FILE_FORMAT);
+  source->AddLocalizedString("noLocalLogFileMessage",
+                             IDS_WEBRTC_LOGS_NO_LOCAL_LOG_FILE_MESSAGE);
+  source->AddLocalizedString("webrtcLogUploadTimeFormat",
+                             IDS_WEBRTC_LOGS_LOG_UPLOAD_TIME_FORMAT);
+  source->AddLocalizedString("webrtcLogReportIdFormat",
+                             IDS_WEBRTC_LOGS_LOG_REPORT_ID_FORMAT);
   source->AddLocalizedString("bugLinkText", IDS_WEBRTC_LOGS_BUG_LINK_LABEL);
+  source->AddLocalizedString("webrtcLogNotUploadedMessage",
+                             IDS_WEBRTC_LOGS_LOG_NOT_UPLOADED_MESSAGE);
   source->AddLocalizedString("noLogsMessage",
                              IDS_WEBRTC_LOGS_NO_LOGS_MESSAGE);
   source->SetJsonPath("strings.js");
@@ -68,7 +80,7 @@
 
 // The handler for Javascript messages for the chrome://webrtc-logs/ page.
 class WebRtcLogsDOMHandler : public WebUIMessageHandler,
-                             public WebRtcLogUploadList::Delegate {
+                             public UploadList::Delegate {
  public:
   explicit WebRtcLogsDOMHandler(Profile* profile);
   virtual ~WebRtcLogsDOMHandler();
@@ -76,7 +88,7 @@
   // WebUIMessageHandler implementation.
   virtual void RegisterMessages() OVERRIDE;
 
-  // WebRtcLogUploadList::Delegate implemenation.
+  // UploadList::Delegate implemenation.
   virtual void OnUploadListAvailable() OVERRIDE;
 
  private:
@@ -87,7 +99,10 @@
   void UpdateUI();
 
   // Loads, parses and stores the list of uploaded WebRTC logs.
-  scoped_refptr<WebRtcLogUploadList> upload_list_;
+  scoped_refptr<UploadList> upload_list_;
+
+  // The directory where the logs are stored.
+  base::FilePath log_dir_;
 
   // Set when |upload_list_| has finished populating the list of logs.
   bool list_available_;
@@ -100,8 +115,11 @@
 };
 
 WebRtcLogsDOMHandler::WebRtcLogsDOMHandler(Profile* profile)
-    : list_available_(false), js_request_pending_(false) {
-  upload_list_ = WebRtcLogUploadList::Create(this, profile);
+    : log_dir_(
+          WebRtcLogList::GetWebRtcLogDirectoryForProfile(profile->GetPath())),
+      list_available_(false),
+      js_request_pending_(false) {
+  upload_list_ = WebRtcLogList::CreateWebRtcLogList(this, profile);
 }
 
 WebRtcLogsDOMHandler::~WebRtcLogsDOMHandler() {
@@ -131,15 +149,35 @@
 }
 
 void WebRtcLogsDOMHandler::UpdateUI() {
-  std::vector<WebRtcLogUploadList::UploadInfo> uploads;
+  std::vector<UploadList::UploadInfo> uploads;
   upload_list_->GetUploads(50, &uploads);
 
   base::ListValue upload_list;
-  for (std::vector<WebRtcLogUploadList::UploadInfo>::iterator i =
-       uploads.begin(); i != uploads.end(); ++i) {
+  for (std::vector<UploadList::UploadInfo>::iterator i = uploads.begin();
+       i != uploads.end();
+       ++i) {
     base::DictionaryValue* upload = new base::DictionaryValue();
     upload->SetString("id", i->id);
-    upload->SetString("time", base::TimeFormatFriendlyDateAndTime(i->time));
+
+    base::string16 value_w;
+    if (!i->time.is_null())
+      value_w = base::TimeFormatFriendlyDateAndTime(i->time);
+    upload->SetString("upload_time", value_w);
+
+    value_w.clear();
+    double seconds_since_epoch;
+    if (base::StringToDouble(i->local_id, &seconds_since_epoch)) {
+      base::Time capture_time = base::Time::FromDoubleT(seconds_since_epoch);
+      value_w = base::TimeFormatFriendlyDateAndTime(capture_time);
+    }
+    upload->SetString("capture_time", value_w);
+
+    base::FilePath::StringType value;
+    if (!i->local_id.empty())
+      value = log_dir_.AppendASCII(i->local_id)
+          .AddExtension(FILE_PATH_LITERAL(".gz")).value();
+    upload->SetString("local_file", value);
+
     upload_list.Append(upload);
   }
 
diff --git a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
index 46b8da3..fdfdcad 100644
--- a/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
+++ b/chrome/browser/ui/webui/ntp/app_launcher_handler.cc
@@ -130,8 +130,11 @@
   base::i18n::UnadjustStringForLocaleDirection(&name);
   NewTabUI::SetFullNameAndDirection(name, value);
 
-  bool enabled = service->IsExtensionEnabled(extension->id()) &&
-      !service->GetTerminatedExtension(extension->id());
+  bool enabled =
+      service->IsExtensionEnabled(extension->id()) &&
+      !extensions::ExtensionRegistry::Get(service->GetBrowserContext())
+           ->GetExtensionById(extension->id(),
+                              extensions::ExtensionRegistry::TERMINATED);
   extensions::GetExtensionBasicInfo(extension, enabled, value);
 
   value->SetBoolean("mayDisable", extensions::ExtensionSystem::Get(
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.cc b/chrome/browser/ui/webui/options/browser_options_handler.cc
index 6437885..b4a87c6 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.cc
+++ b/chrome/browser/ui/webui/options/browser_options_handler.cc
@@ -107,6 +107,7 @@
 #include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/chromeos/login/wallpaper_manager.h"
 #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
+#include "chrome/browser/chromeos/reset/metrics.h"
 #include "chrome/browser/chromeos/settings/cros_settings.h"
 #include "chrome/browser/chromeos/system/timezone_util.h"
 #include "chrome/browser/policy/profile_policy_connector.h"
@@ -142,6 +143,7 @@
     : page_initialized_(false),
       template_url_service_(NULL),
       cloud_print_mdns_ui_enabled_(false),
+      signin_observer_(this),
       weak_ptr_factory_(this) {
 #if !defined(OS_MACOSX)
   default_browser_worker_ = new ShellIntegration::DefaultBrowserWorker(this);
@@ -257,6 +259,7 @@
     { "hotwordConfirmDisable", IDS_HOTWORD_CONFIRM_BUBBLE_DISABLE },
     { "hotwordConfirmMessage", IDS_HOTWORD_SEARCH_PREF_DESCRIPTION },
     { "hotwordRetryDownloadButton", IDS_HOTWORD_RETRY_DOWNLOAD_BUTTON },
+    { "hotwordAudioLoggingEnable", IDS_HOTWORD_AUDIO_LOGGING_ENABLE },
     { "importData", IDS_OPTIONS_IMPORT_DATA_BUTTON },
     { "improveBrowsingExperience", IDS_OPTIONS_IMPROVE_BROWSING_EXPERIENCE },
     { "languageAndSpellCheckSettingsButton",
@@ -478,7 +481,7 @@
       l10n_util::GetStringFUTF16(IDS_SEARCH_PREF_EXPLANATION, omnibox_url));
   values->SetString("hotwordLearnMoreURL", chrome::kHotwordLearnMoreURL);
   RegisterTitle(values, "hotwordConfirmOverlay",
-                IDS_HOTWORD_SEARCH_PREF_CHKBOX);
+                IDS_HOTWORD_CONFIRM_BUBBLE_TITLE);
 
 #if defined(OS_CHROMEOS)
   Profile* profile = Profile::FromWebUI(web_ui());
@@ -686,6 +689,10 @@
       base::Bind(&BrowserOptionsHandler::VirtualKeyboardChangeCallback,
                  base::Unretained(this)));
   web_ui()->RegisterMessageCallback(
+       "onPowerwashDialogShow",
+       base::Bind(&BrowserOptionsHandler::OnPowerwashDialogShow,
+                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "performFactoryResetRestart",
       base::Bind(&BrowserOptionsHandler::PerformFactoryResetRestart,
                  base::Unretained(this)));
@@ -744,6 +751,15 @@
   UpdateSyncState();
 }
 
+void BrowserOptionsHandler::GoogleSigninSucceeded(const std::string& username,
+                                                  const std::string& password) {
+  OnStateChanged();
+}
+
+void BrowserOptionsHandler::GoogleSignedOut(const std::string& username) {
+  OnStateChanged();
+}
+
 void BrowserOptionsHandler::PageLoadStarted() {
   page_initialized_ = false;
 }
@@ -754,9 +770,16 @@
 
   ProfileSyncService* sync_service(
       ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile));
+  // TODO(blundell): Use a ScopedObserver to observe the PSS so that cleanup on
+  // destruction is automatic.
   if (sync_service)
     sync_service->AddObserver(this);
 
+  SigninManagerBase* signin_manager(
+      SigninManagerFactory::GetInstance()->GetForProfile(profile));
+  if (signin_manager)
+    signin_observer_.Add(signin_manager);
+
   // Create our favicon data source.
   content::URLDataSource::Add(
       profile, new FaviconSource(profile, FaviconSource::FAVICON));
@@ -778,10 +801,6 @@
                      ThemeServiceFactory::GetForProfile(profile)));
   registrar_.Add(this, chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED,
                  content::Source<Profile>(profile));
-  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL,
-                 content::Source<Profile>(profile));
-  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
-                 content::Source<Profile>(profile));
   AddTemplateUrlServiceObserver();
 
 #if defined(OS_WIN)
@@ -1152,8 +1171,6 @@
     SendProfilesInfo();
       break;
     case chrome::NOTIFICATION_GLOBAL_ERRORS_CHANGED:
-    case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL:
-    case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT:
       // Update our sync/signin status display.
       OnStateChanged();
       break;
@@ -1351,6 +1368,11 @@
                           !signin->GetAuthenticatedUsername().empty());
   sync_status->SetBoolean("hasUnrecoverableError",
                           service && service->HasUnrecoverableError());
+  sync_status->SetBoolean(
+      "autoLoginVisible",
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableAutologin) &&
+      service && service->IsSyncEnabledAndLoggedIn() &&
+      service->IsOAuthRefreshTokenAvailable());
 
   return sync_status.Pass();
 }
@@ -1410,6 +1432,14 @@
     OnWallpaperManagedChanged(has_policy);
 }
 
+void BrowserOptionsHandler::OnPowerwashDialogShow(
+     const base::ListValue* args) {
+  UMA_HISTOGRAM_ENUMERATION(
+      "Reset.ChromeOS.PowerwashDialogShown",
+      chromeos::reset::DIALOG_FROM_OPTIONS,
+      chromeos::reset::DIALOG_VIEW_TYPE_SIZE);
+}
+
 #endif  // defined(OS_CHROMEOS)
 
 void BrowserOptionsHandler::UpdateSyncState() {
@@ -1593,14 +1623,8 @@
   Profile* profile = Profile::FromWebUI(web_ui());
   std::string group = base::FieldTrialList::FindFullName("VoiceTrigger");
   if (group != "" && group != "Disabled") {
-    if (HotwordServiceFactory::IsServiceAvailable(profile)) {
+    if (HotwordServiceFactory::IsServiceAvailable(profile))
       web_ui()->CallJavascriptFunction("BrowserOptions.showHotwordSection");
-    } else if (HotwordServiceFactory::IsHotwordAllowed(profile)) {
-      base::StringValue error_message(l10n_util::GetStringUTF16(
-          IDS_HOTWORD_GENERIC_ERROR_MESSAGE));
-      web_ui()->CallJavascriptFunction("BrowserOptions.showHotwordSection",
-                                       error_message);
-    }
   }
 }
 
diff --git a/chrome/browser/ui/webui/options/browser_options_handler.h b/chrome/browser/ui/webui/options/browser_options_handler.h
index 49f55c2..00685d4 100644
--- a/chrome/browser/ui/webui/options/browser_options_handler.h
+++ b/chrome/browser/ui/webui/options/browser_options_handler.h
@@ -14,12 +14,14 @@
 #include "base/memory/weak_ptr.h"
 #include "base/prefs/pref_change_registrar.h"
 #include "base/prefs/pref_member.h"
+#include "base/scoped_observer.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_observer.h"
 #include "chrome/browser/shell_integration.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/browser/notification_observer.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "ui/base/models/table_model_observer.h"
@@ -48,6 +50,7 @@
 class BrowserOptionsHandler
     : public OptionsPageUIHandler,
       public ProfileSyncServiceObserver,
+      public SigninManagerBase::Observer,
       public ui::SelectFileDialog::Listener,
       public ShellIntegration::DefaultWebClientObserver,
 #if defined(OS_CHROMEOS)
@@ -70,6 +73,11 @@
   // ProfileSyncServiceObserver implementation.
   virtual void OnStateChanged() OVERRIDE;
 
+  // SigninManagerBase::Observer implementation.
+  virtual void GoogleSigninSucceeded(const std::string& username,
+                                     const std::string& password) OVERRIDE;
+  virtual void GoogleSignedOut(const std::string& username) OVERRIDE;
+
   // ShellIntegration::DefaultWebClientObserver implementation.
   virtual void SetDefaultWebClientUIState(
       ShellIntegration::DefaultWebClientUIState state) OVERRIDE;
@@ -105,6 +113,9 @@
   // Will be called when the policy::key::kWallpaperImage policy changes.
   void OnWallpaperPolicyChanged(const base::Value* previous_policy,
                                 const base::Value* current_policy);
+
+  // Will be called when powerwash dialog is shown.
+  void OnPowerwashDialogShow(const base::ListValue* args);
 #endif
 
   void UpdateSyncState();
@@ -355,6 +366,9 @@
   scoped_ptr<policy::PolicyChangeRegistrar> policy_registrar_;
 #endif
 
+  ScopedObserver<SigninManagerBase, SigninManagerBase::Observer>
+      signin_observer_;
+
   // Used to get WeakPtr to self for use on the UI thread.
   base::WeakPtrFactory<BrowserOptionsHandler> weak_ptr_factory_;
 
diff --git a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
index cd8c46b..959c432 100644
--- a/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
+++ b/chrome/browser/ui/webui/options/certificate_manager_browsertest.cc
@@ -8,11 +8,13 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/webui/options/options_ui_browsertest.h"
+#include "chrome/common/url_constants.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/policy/core/common/external_data_fetcher.h"
 #include "components/policy/core/common/mock_configuration_policy_provider.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
+#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_utils.h"
@@ -142,18 +144,31 @@
   }
 #endif
 
-  void ClickElement(const std::string& selector) {
-    EXPECT_TRUE(content::ExecuteScriptInFrame(
+  static bool FrameHasSettingsSourceHost(content::RenderFrameHost* frame) {
+    return frame->GetLastCommittedURL().DomainIs(
+        chrome::kChromeUISettingsFrameHost);
+  }
+
+  content::RenderFrameHost* SettingsFrame() {
+    // NB: The utility function content::FrameHasSourceUrl can't be used because
+    // the settings frame navigates itself to chrome://settings-frame/settings
+    // to indicate that it's showing the top-level settings. Therefore, just
+    // match the host.
+    return content::FrameMatchingPredicate(
         browser()->tab_strip_model()->GetActiveWebContents(),
-        "//div[@id='settings']/iframe",
+        base::Bind(&CertificateManagerBrowserTest::FrameHasSettingsSourceHost));
+  }
+
+  void ClickElement(const std::string& selector) {
+    EXPECT_TRUE(content::ExecuteScript(
+        SettingsFrame(),
         "document.querySelector(\"" + selector + "\").click()"));
   }
 
   bool HasElement(const std::string& selector) {
     bool result;
-    EXPECT_TRUE(content::ExecuteScriptInFrameAndExtractBool(
-        browser()->tab_strip_model()->GetActiveWebContents(),
-        "//div[@id='settings']/iframe",
+    EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
+        SettingsFrame(),
         "window.domAutomationController.send("
         "    !!document.querySelector('" + selector + "'));",
         &result));
diff --git a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc
index c079127..beb4d44 100644
--- a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.cc
@@ -85,6 +85,7 @@
     { "bluetoothNoDevicesFound",
         IDS_OPTIONS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND },
     { "bluetoothScanning", IDS_OPTIONS_SETTINGS_BLUETOOTH_SCANNING },
+    { "bluetoothScanStopped", IDS_OPTIONS_SETTINGS_BLUETOOTH_SCAN_STOPPED },
     { "bluetoothDeviceConnecting", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECTING },
     { "bluetoothConnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_CONNECT },
     { "bluetoothDisconnectDevice", IDS_OPTIONS_SETTINGS_BLUETOOTH_DISCONNECT },
@@ -168,6 +169,21 @@
   base::FundamentalValue checked(powered);
   web_ui()->CallJavascriptFunction(
       "options.BrowserOptions.setBluetoothState", checked);
+
+  // If the "Add device" overlay is visible, dismiss it.
+  if (!powered) {
+    web_ui()->CallJavascriptFunction(
+        "options.BluetoothOptions.dismissOverlay");
+  }
+}
+
+void BluetoothOptionsHandler::AdapterDiscoveringChanged(
+    device::BluetoothAdapter* adapter,
+    bool discovering) {
+  DCHECK(adapter == adapter_.get());
+  base::FundamentalValue discovering_value(discovering);
+  web_ui()->CallJavascriptFunction(
+      "options.BluetoothOptions.updateDiscoveryState", discovering_value);
 }
 
 void BluetoothOptionsHandler::RegisterMessages() {
@@ -198,10 +214,11 @@
   // Show or hide the bluetooth settings and update the checkbox based
   // on the current present/powered state.
   AdapterPresentChanged(adapter_.get(), adapter_->IsPresent());
+
   // Automatically start device discovery if the "Add Bluetooth Device"
   // overlay is visible.
   web_ui()->CallJavascriptFunction(
-      "options.BluetoothOptions.updateDiscovery");
+      "options.BluetoothOptions.startDeviceDiscovery");
 }
 
 void BluetoothOptionsHandler::InitializeAdapter(
@@ -254,6 +271,11 @@
 void BluetoothOptionsHandler::FindDevicesError() {
   VLOG(1) << "Failed to start discovery.";
   ReportError("bluetoothStartDiscoveryFailed", std::string());
+  if (!adapter_.get())
+    return;
+  base::FundamentalValue discovering(adapter_->IsDiscovering());
+  web_ui()->CallJavascriptFunction(
+      "options.BluetoothOptions.updateDiscoveryState", discovering);
 }
 
 void BluetoothOptionsHandler::UpdateDeviceCallback(
diff --git a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h
index 0c4ae95..fcfcd1e 100644
--- a/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h
+++ b/chrome/browser/ui/webui/options/chromeos/bluetooth_options_handler.h
@@ -140,6 +140,8 @@
                                      bool present) OVERRIDE;
   virtual void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
                                      bool powered) OVERRIDE;
+  virtual void AdapterDiscoveringChanged(device::BluetoothAdapter* adapter,
+                                         bool discovering) OVERRIDE;
   virtual void DeviceAdded(device::BluetoothAdapter* adapter,
                            device::BluetoothDevice* device) OVERRIDE;
   virtual void DeviceChanged(device::BluetoothAdapter* adapter,
diff --git a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc
index d8c0765..014c86f 100644
--- a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.cc
@@ -14,7 +14,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
-#include "chrome/browser/chromeos/camera_detector.h"
+#include "chrome/browser/chromeos/camera_presence_notifier.h"
 #include "chrome/browser/chromeos/login/default_user_images.h"
 #include "chrome/browser/chromeos/login/user_image.h"
 #include "chrome/browser/chromeos/login/user_image_manager.h"
@@ -76,9 +76,7 @@
 
 ChangePictureOptionsHandler::ChangePictureOptionsHandler()
     : previous_image_url_(content::kAboutBlankURL),
-      previous_image_index_(User::kInvalidImageIndex),
-      weak_factory_(this),
-      was_camera_present_(false) {
+      previous_image_index_(User::kInvalidImageIndex) {
   registrar_.Add(this, chrome::NOTIFICATION_PROFILE_IMAGE_UPDATED,
       content::NotificationService::AllSources());
   registrar_.Add(this, chrome::NOTIFICATION_PROFILE_IMAGE_UPDATE_FAILED,
@@ -95,6 +93,7 @@
 }
 
 ChangePictureOptionsHandler::~ChangePictureOptionsHandler() {
+  CameraPresenceNotifier::GetInstance()->RemoveObserver(this);
   if (select_file_dialog_.get())
     select_file_dialog_->ListenerDestroyed();
   if (image_decoder_.get())
@@ -150,12 +149,12 @@
   web_ui()->RegisterMessageCallback("discardPhoto",
       base::Bind(&ChangePictureOptionsHandler::HandleDiscardPhoto,
                  base::Unretained(this)));
-  web_ui()->RegisterMessageCallback("checkCameraPresence",
-      base::Bind(&ChangePictureOptionsHandler::HandleCheckCameraPresence,
-                 base::Unretained(this)));
   web_ui()->RegisterMessageCallback("onChangePicturePageShown",
       base::Bind(&ChangePictureOptionsHandler::HandlePageShown,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("onChangePicturePageHidden",
+      base::Bind(&ChangePictureOptionsHandler::HandlePageHidden,
+                 base::Unretained(this)));
   web_ui()->RegisterMessageCallback("onChangePicturePageInitialized",
       base::Bind(&ChangePictureOptionsHandler::HandlePageInitialized,
                  base::Unretained(this)));
@@ -244,12 +243,6 @@
   image_decoder_->Start(task_runner);
 }
 
-void ChangePictureOptionsHandler::HandleCheckCameraPresence(
-    const base::ListValue* args) {
-  DCHECK(args->empty());
-  CheckCameraPresence();
-}
-
 void ChangePictureOptionsHandler::HandlePageInitialized(
     const base::ListValue* args) {
   DCHECK(args && args->empty());
@@ -258,9 +251,14 @@
 
 void ChangePictureOptionsHandler::HandlePageShown(const base::ListValue* args) {
   DCHECK(args && args->empty());
-  CheckCameraPresence();
   SendSelectedImage();
   UpdateProfileImage();
+  CameraPresenceNotifier::GetInstance()->AddObserver(this);
+}
+
+void ChangePictureOptionsHandler::HandlePageHidden(
+    const base::ListValue* args) {
+  CameraPresenceNotifier::GetInstance()->RemoveObserver(this);
 }
 
 void ChangePictureOptionsHandler::SendSelectedImage() {
@@ -416,25 +414,16 @@
   VLOG(1) << "Selected camera photo";
 }
 
-void ChangePictureOptionsHandler::CheckCameraPresence() {
-  CameraDetector::StartPresenceCheck(
-      base::Bind(&ChangePictureOptionsHandler::OnCameraPresenceCheckDone,
-                 weak_factory_.GetWeakPtr()));
-}
-
 void ChangePictureOptionsHandler::SetCameraPresent(bool present) {
   base::FundamentalValue present_value(present);
+
   web_ui()->CallJavascriptFunction("ChangePictureOptions.setCameraPresent",
                                    present_value);
 }
 
-void ChangePictureOptionsHandler::OnCameraPresenceCheckDone() {
-  bool is_camera_present = CameraDetector::camera_presence() ==
-                           CameraDetector::kCameraPresent;
-  if (is_camera_present != was_camera_present_) {
-    SetCameraPresent(is_camera_present);
-    was_camera_present_ = is_camera_present;
-  }
+void ChangePictureOptionsHandler::OnCameraPresenceCheckDone(
+    bool is_camera_present) {
+  SetCameraPresent(is_camera_present);
 }
 
 void ChangePictureOptionsHandler::Observe(
diff --git a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h
index 30006db..0330677 100644
--- a/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h
+++ b/chrome/browser/ui/webui/options/chromeos/change_picture_options_handler.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_OPTIONS_CHROMEOS_CHANGE_PICTURE_OPTIONS_HANDLER_H_
 #define CHROME_BROWSER_UI_WEBUI_OPTIONS_CHROMEOS_CHANGE_PICTURE_OPTIONS_HANDLER_H_
 
-#include "base/memory/weak_ptr.h"
+#include "chrome/browser/chromeos/camera_presence_notifier.h"
 #include "chrome/browser/image_decoder.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
 #include "content/public/browser/notification_observer.h"
@@ -29,7 +29,8 @@
 class ChangePictureOptionsHandler : public ::options::OptionsPageUIHandler,
                                     public ui::SelectFileDialog::Listener,
                                     public content::NotificationObserver,
-                                    public ImageDecoder::Delegate {
+                                    public ImageDecoder::Delegate,
+                                    public CameraPresenceNotifier::Observer {
  public:
   ChangePictureOptionsHandler();
   virtual ~ChangePictureOptionsHandler();
@@ -41,6 +42,9 @@
   // WebUIMessageHandler implementation.
   virtual void RegisterMessages() OVERRIDE;
 
+  // CameraPresenceNotifier::Observer implementation:
+  virtual void OnCameraPresenceCheckDone(bool is_camera_present) OVERRIDE;
+
  private:
   // Sends list of available default images to the page.
   void SendDefaultImages();
@@ -77,9 +81,6 @@
   // Handles 'discard-photo' button click.
   void HandleDiscardPhoto(const base::ListValue* args);
 
-  // Handles camera presence check request.
-  void HandleCheckCameraPresence(const base::ListValue* args);
-
   // Gets the list of available user images and sends it to the page.
   void HandleGetAvailableImages(const base::ListValue* args);
 
@@ -89,6 +90,9 @@
   // Handles page shown event.
   void HandlePageShown(const base::ListValue* args);
 
+  // Handles page hidden event.
+  void HandlePageHidden(const base::ListValue* args);
+
   // Selects one of the available images as user's.
   void HandleSelectImage(const base::ListValue* args);
 
@@ -102,9 +106,6 @@
                        const content::NotificationSource& source,
                        const content::NotificationDetails& details) OVERRIDE;
 
-  // Called when the camera presence check has been completed.
-  void OnCameraPresenceCheckDone();
-
   // Sets user image to photo taken from camera.
   void SetImageFromCamera(const gfx::ImageSkia& photo);
 
@@ -137,16 +138,10 @@
 
   content::NotificationRegistrar registrar_;
 
-  base::WeakPtrFactory<ChangePictureOptionsHandler> weak_factory_;
-
   // Last ImageDecoder instance used to decode an image blob received by
   // HandlePhotoTaken.
   scoped_refptr<ImageDecoder> image_decoder_;
 
- private:
-  // Last known state of the camera.
-  bool was_camera_present_;
-
   DISALLOW_COPY_AND_ASSIGN(ChangePictureOptionsHandler);
 };
 
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
index cbbfb71..023843f 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.cc
@@ -60,6 +60,28 @@
   return d1.size.GetArea() < d2.size.GetArea();
 }
 
+base::string16 GetColorProfileName(ui::ColorCalibrationProfile profile) {
+  switch (profile) {
+    case ui::COLOR_PROFILE_STANDARD:
+      return l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_STANDARD);
+    case ui::COLOR_PROFILE_DYNAMIC:
+      return l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_DYNAMIC);
+    case ui::COLOR_PROFILE_MOVIE:
+      return l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_MOVIE);
+    case ui::COLOR_PROFILE_READING:
+      return l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_READING);
+    case ui::NUM_COLOR_PROFILES:
+      break;
+  }
+
+  NOTREACHED();
+  return base::string16();
+}
+
 }  // namespace
 
 DisplayOptionsHandler::DisplayOptionsHandler() {
@@ -110,6 +132,9 @@
   localized_strings->SetString(
       "startCalibratingOverscan", l10n_util::GetStringUTF16(
           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
+  localized_strings->SetString(
+      "selectedDisplayColorProfile", l10n_util::GetStringUTF16(
+          IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE));
 }
 
 void DisplayOptionsHandler::InitializePage() {
@@ -145,6 +170,10 @@
       "setOrientation",
       base::Bind(&DisplayOptionsHandler::HandleSetOrientation,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "setColorProfile",
+      base::Bind(&DisplayOptionsHandler::HandleSetColorProfile,
+                 base::Unretained(this)));
 }
 
 void DisplayOptionsHandler::OnDisplayConfigurationChanging() {
@@ -242,6 +271,19 @@
       js_resolutions->Append(resolution_info);
     }
     js_display->Set("resolutions", js_resolutions);
+
+    js_display->SetInteger("colorProfile", display_info.color_profile());
+    base::ListValue* available_color_profiles = new base::ListValue();
+    for (size_t i = 0;
+         i < display_info.available_color_profiles().size(); ++i) {
+      base::DictionaryValue* color_profile_dict = new base::DictionaryValue();
+      ui::ColorCalibrationProfile color_profile =
+          display_info.available_color_profiles()[i];
+      color_profile_dict->SetInteger("profileId", color_profile);
+      color_profile_dict->SetString("name", GetColorProfileName(color_profile));
+      available_color_profiles->Append(color_profile_dict);
+    }
+    js_display->Set("availableColorProfiles", available_color_profiles);
     js_displays.Append(js_display);
   }
 
@@ -406,5 +448,34 @@
   GetDisplayManager()->SetDisplayRotation(display_id, new_rotation);
 }
 
+void DisplayOptionsHandler::HandleSetColorProfile(const base::ListValue* args) {
+  DCHECK(!args->empty());
+  int64 display_id = GetDisplayId(args);
+  if (display_id == gfx::Display::kInvalidDisplayID)
+    return;
+
+  std::string profile_value;
+  if (!args->GetString(1, &profile_value)) {
+    LOG(ERROR) << "Invalid profile_value";
+    return;
+  }
+
+  int profile_id;
+  if (!base::StringToInt(profile_value, &profile_id)) {
+    LOG(ERROR) << "Invalid profile: " << profile_value;
+    return;
+  }
+
+  if (profile_id < ui::COLOR_PROFILE_STANDARD ||
+      profile_id > ui::COLOR_PROFILE_READING) {
+    LOG(ERROR) << "Invalid profile_id: " << profile_id;
+    return;
+  }
+
+  GetDisplayManager()->SetColorCalibrationProfile(
+      display_id, static_cast<ui::ColorCalibrationProfile>(profile_id));
+  SendAllDisplayInfo();
+}
+
 }  // namespace options
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/options/chromeos/display_options_handler.h b/chrome/browser/ui/webui/options/chromeos/display_options_handler.h
index 1606c72..3cb55fd 100644
--- a/chrome/browser/ui/webui/options/chromeos/display_options_handler.h
+++ b/chrome/browser/ui/webui/options/chromeos/display_options_handler.h
@@ -61,6 +61,7 @@
   void HandleSetUIScale(const base::ListValue* args);
   void HandleSetResolution(const base::ListValue* args);
   void HandleSetOrientation(const base::ListValue* args);
+  void HandleSetColorProfile(const base::ListValue* args);
 
   DISALLOW_COPY_AND_ASSIGN(DisplayOptionsHandler);
 };
diff --git a/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc b/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc
index fe5d060..92cd2a8 100644
--- a/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/options/chromeos/guest_mode_options_ui_browsertest.cc
@@ -3,8 +3,10 @@
 // found in the LICENSE file.
 
 #include "base/command_line.h"
+#include "chrome/browser/chromeos/login/user_manager.h"
 #include "chrome/browser/ui/webui/options/options_ui_browsertest.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/test/base/testing_profile.h"
 #include "chromeos/chromeos_switches.h"
 
 namespace {
@@ -17,11 +19,15 @@
 
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     command_line->AppendSwitch(chromeos::switches::kGuestSession);
+    command_line->AppendSwitchASCII(chromeos::switches::kLoginUser,
+                                    chromeos::UserManager::kGuestUserName);
+    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
+                                    TestingProfile::kTestUserProfileDir);
     command_line->AppendSwitch(switches::kIncognito);
   }
 };
 
-IN_PROC_BROWSER_TEST_F(GuestModeOptionsBrowserTest, DISABLED_LoadOptionsByURL) {
+IN_PROC_BROWSER_TEST_F(GuestModeOptionsBrowserTest, LoadOptionsByURL) {
   NavigateToSettings();
   VerifyTitle();
   VerifyNavbar();
diff --git a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
index a145093..9437ed9 100644
--- a/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
+++ b/chrome/browser/ui/webui/options/clear_browser_data_handler.cc
@@ -148,7 +148,9 @@
 
 void ClearBrowserDataHandler::HandleClearBrowserData(
     const base::ListValue* value) {
-  DCHECK(!remover_);
+  // TODO(engedy): change this back to a DCHECK once we have updated the UI.
+  if (remover_)
+    return;
 
   Profile* profile = Profile::FromWebUI(web_ui());
   PrefService* prefs = profile->GetPrefs();
diff --git a/chrome/browser/ui/webui/options/core_options_handler.cc b/chrome/browser/ui/webui/options/core_options_handler.cc
index e11526f..d676de6 100644
--- a/chrome/browser/ui/webui/options/core_options_handler.cc
+++ b/chrome/browser/ui/webui/options/core_options_handler.cc
@@ -182,6 +182,9 @@
   web_ui()->RegisterMessageCallback("coreOptionsInitialize",
       base::Bind(&CoreOptionsHandler::HandleInitialize,
                  base::Unretained(this)));
+  web_ui()->RegisterMessageCallback("onFinishedLoadingOptions",
+      base::Bind(&CoreOptionsHandler::OnFinishedLoading,
+                 base::Unretained(this)));
   web_ui()->RegisterMessageCallback("fetchPrefs",
       base::Bind(&CoreOptionsHandler::HandleFetchPrefs,
                  base::Unretained(this)));
@@ -222,6 +225,11 @@
   handlers_host_->InitializeHandlers();
 }
 
+void CoreOptionsHandler::OnFinishedLoading(const base::ListValue* args) {
+  DCHECK(handlers_host_);
+  handlers_host_->OnFinishedLoading();
+}
+
 base::Value* CoreOptionsHandler::FetchPref(const std::string& pref_name) {
   return CreateValueForPref(pref_name, std::string());
 }
diff --git a/chrome/browser/ui/webui/options/core_options_handler.h b/chrome/browser/ui/webui/options/core_options_handler.h
index 369be28..5976d49 100644
--- a/chrome/browser/ui/webui/options/core_options_handler.h
+++ b/chrome/browser/ui/webui/options/core_options_handler.h
@@ -116,6 +116,11 @@
   // setup can be performed before the page is shown.
   void HandleInitialize(const base::ListValue* args);
 
+  // Callback for the "onFinishedLoadingOptions" message. This message is sent
+  // when the load() handler for the options frame, along with all asynchronous
+  // calls it has spawned, have finished running.
+  void OnFinishedLoading(const base::ListValue* args);
+
   // Callback for the "fetchPrefs" message. This message accepts the list of
   // preference names passed as the |args| parameter (ListValue). It passes
   // results dictionary of preference values by calling prefsFetched() JS method
diff --git a/chrome/browser/ui/webui/options/handler_options_handler.cc b/chrome/browser/ui/webui/options/handler_options_handler.cc
index bb76b44..4c8dfc7 100644
--- a/chrome/browser/ui/webui/options/handler_options_handler.cc
+++ b/chrome/browser/ui/webui/options/handler_options_handler.cc
@@ -13,6 +13,7 @@
 #include "base/values.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
+#include "chrome/browser/google/google_util.h"
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/web_ui.h"
 #include "grit/generated_resources.h"
@@ -20,6 +21,13 @@
 
 namespace options {
 
+namespace {
+
+const char kHandlersLearnMoreUrl[] =
+    "https://support.google.com/chromebook/answer/1382847";
+
+}  // namespace
+
 HandlerOptionsHandler::HandlerOptionsHandler() {
 }
 
@@ -44,6 +52,10 @@
   RegisterTitle(localized_strings, "handlersPage",
                 IDS_HANDLER_OPTIONS_WINDOW_TITLE);
   RegisterStrings(localized_strings, resources, arraysize(resources));
+
+  localized_strings->SetString(
+      "handlers_learn_more_url",
+      google_util::StringAppendGoogleLocaleParam(kHandlersLearnMoreUrl));
 }
 
 void HandlerOptionsHandler::InitializeHandler() {
diff --git a/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc b/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc
index 5ee6ea7..2c8a843 100644
--- a/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc
+++ b/chrome/browser/ui/webui/options/managed_user_create_confirm_handler.cc
@@ -13,11 +13,11 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profile_window.h"
 #include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/host_desktop.h"
 #include "chrome/browser/ui/startup/startup_types.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/browser/web_ui.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ui/webui/options/managed_user_import_handler.cc b/chrome/browser/ui/webui/options/managed_user_import_handler.cc
index fe2ae05..64ab13b 100644
--- a/chrome/browser/ui/webui/options/managed_user_import_handler.cc
+++ b/chrome/browser/ui/webui/options/managed_user_import_handler.cc
@@ -23,8 +23,8 @@
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "content/public/browser/web_ui.h"
 #include "grit/generated_resources.h"
 #include "grit/theme_resources.h"
diff --git a/chrome/browser/ui/webui/options/managed_user_import_handler.h b/chrome/browser/ui/webui/options/managed_user_import_handler.h
index 21a4932..2128a41 100644
--- a/chrome/browser/ui/webui/options/managed_user_import_handler.h
+++ b/chrome/browser/ui/webui/options/managed_user_import_handler.h
@@ -10,7 +10,7 @@
 #include "base/scoped_observer.h"
 #include "chrome/browser/managed_mode/managed_user_sync_service_observer.h"
 #include "chrome/browser/ui/webui/options/options_ui.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 
 namespace base {
 class DictionaryValue;
diff --git a/chrome/browser/ui/webui/options/options_ui.cc b/chrome/browser/ui/webui/options/options_ui.cc
index c7c11cd..8c5b1e0 100644
--- a/chrome/browser/ui/webui/options/options_ui.cc
+++ b/chrome/browser/ui/webui/options/options_ui.cc
@@ -360,6 +360,11 @@
     handlers_[i]->Uninitialize();
 }
 
+scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
+OptionsUI::RegisterOnFinishedLoadingCallback(const base::Closure& callback) {
+  return on_finished_loading_callbacks_.Add(callback);
+}
+
 // static
 void OptionsUI::ProcessAutocompleteSuggestions(
     const AutocompleteResult& result,
@@ -432,6 +437,10 @@
       "BrowserOptions.notifyInitializationComplete");
 }
 
+void OptionsUI::OnFinishedLoading() {
+  on_finished_loading_callbacks_.Notify();
+}
+
 void OptionsUI::AddOptionsPageUIHandler(
     base::DictionaryValue* localized_strings,
     OptionsPageUIHandler* handler_raw) {
diff --git a/chrome/browser/ui/webui/options/options_ui.h b/chrome/browser/ui/webui/options/options_ui.h
index 609eb33..b6ecda5 100644
--- a/chrome/browser/ui/webui/options/options_ui.h
+++ b/chrome/browser/ui/webui/options/options_ui.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback_list.h"
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "content/public/browser/notification_registrar.h"
@@ -100,6 +101,7 @@
 class OptionsPageUIHandlerHost {
  public:
   virtual void InitializeHandlers() = 0;
+  virtual void OnFinishedLoading() {}
 
  protected:
   virtual ~OptionsPageUIHandlerHost() {}
@@ -110,9 +112,16 @@
                   public content::WebContentsObserver,
                   public OptionsPageUIHandlerHost {
  public:
+  typedef base::CallbackList<void()> OnFinishedLoadingCallbackList;
+
   explicit OptionsUI(content::WebUI* web_ui);
   virtual ~OptionsUI();
 
+  // Registers a callback to be called once the settings frame has finished
+  // loading on the HTML/JS side.
+  scoped_ptr<OnFinishedLoadingCallbackList::Subscription>
+      RegisterOnFinishedLoadingCallback(const base::Closure& callback);
+
   // Takes the suggestions from |result| and adds them to |suggestions| so that
   // they can be passed to a JavaScript function.
   static void ProcessAutocompleteSuggestions(
@@ -134,6 +143,7 @@
 
   // Overridden from OptionsPageUIHandlerHost:
   virtual void InitializeHandlers() OVERRIDE;
+  virtual void OnFinishedLoading() OVERRIDE;
 
  private:
   // Adds OptionsPageUiHandler to the handlers list if handler is enabled.
@@ -143,6 +153,7 @@
   bool initialized_handlers_;
 
   std::vector<OptionsPageUIHandler*> handlers_;
+  OnFinishedLoadingCallbackList on_finished_loading_callbacks_;
 
 #if defined(OS_CHROMEOS)
   scoped_ptr<chromeos::system::PointerDeviceObserver>
diff --git a/chrome/browser/ui/webui/options/options_ui_browsertest.cc b/chrome/browser/ui/webui/options/options_ui_browsertest.cc
index a5ebc36..4f7e4b8 100644
--- a/chrome/browser/ui/webui/options/options_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/options/options_ui_browsertest.cc
@@ -5,19 +5,21 @@
 #include "chrome/browser/ui/webui/options/options_ui_browsertest.h"
 
 #include "base/prefs/pref_service.h"
+#include "base/scoped_observer.h"
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/webui/options/options_ui.h"
+#include "chrome/browser/ui/webui/uber/uber_ui.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/ui_test_utils.h"
-#include "content/public/browser/notification_service.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
 #include "grit/generated_resources.h"
 #include "ui/base/l10n/l10n_util.h"
 
@@ -38,10 +40,46 @@
 #include "url/gurl.h"
 #endif
 
+using content::MessageLoopRunner;
+
 namespace options {
 
 namespace {
 
+class SignOutWaiter : public SigninManagerBase::Observer {
+ public:
+  SignOutWaiter(SigninManagerBase* signin_manager)
+      : seen_(false), running_(false), scoped_observer_(this) {
+    scoped_observer_.Add(signin_manager);
+  }
+  virtual ~SignOutWaiter() {}
+
+  void Wait() {
+    if (seen_)
+      return;
+
+    running_ = true;
+    message_loop_runner_ = new MessageLoopRunner;
+    message_loop_runner_->Run();
+    EXPECT_TRUE(seen_);
+  }
+
+  virtual void GoogleSignedOut(const std::string& username) OVERRIDE {
+    seen_ = true;
+    if (!running_)
+      return;
+
+    message_loop_runner_->Quit();
+    running_ = false;
+  }
+
+ private:
+  bool seen_;
+  bool running_;
+  ScopedObserver<SigninManagerBase, SignOutWaiter> scoped_observer_;
+  scoped_refptr<MessageLoopRunner> message_loop_runner_;
+};
+
 #if !defined(OS_CHROMEOS)
 void RunClosureWhenProfileInitialized(const base::Closure& closure,
                                       Profile* profile,
@@ -58,6 +96,30 @@
 
 void OptionsUIBrowserTest::NavigateToSettings() {
   const GURL& url = GURL(chrome::kChromeUISettingsURL);
+  ui_test_utils::NavigateToURLWithDisposition(browser(), url, CURRENT_TAB, 0);
+
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+  ASSERT_TRUE(web_contents);
+  ASSERT_TRUE(web_contents->GetWebUI());
+  UberUI* uber_ui = static_cast<UberUI*>(
+      web_contents->GetWebUI()->GetController());
+  OptionsUI* options_ui = static_cast<OptionsUI*>(
+      uber_ui->GetSubpage(chrome::kChromeUISettingsFrameURL)->GetController());
+
+  // It is not possible to subscribe to the OnFinishedLoading event before the
+  // call to NavigateToURL(), because the WebUI does not yet exist at that time.
+  // However, it is safe to subscribe afterwards, because the event will always
+  // be posted asynchronously to the message loop.
+  scoped_refptr<MessageLoopRunner> message_loop_runner(new MessageLoopRunner);
+  scoped_ptr<OptionsUI::OnFinishedLoadingCallbackList::Subscription>
+      subscription = options_ui->RegisterOnFinishedLoadingCallback(
+          message_loop_runner->QuitClosure());
+  message_loop_runner->Run();
+}
+
+void OptionsUIBrowserTest::NavigateToSettingsFrame() {
+  const GURL& url = GURL(chrome::kChromeUISettingsFrameURL);
   ui_test_utils::NavigateToURL(browser(), url);
 }
 
@@ -78,88 +140,20 @@
   EXPECT_NE(title.find(expected_title), base::string16::npos);
 }
 
-// Flaky, see http://crbug.com/119671.
-IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, DISABLED_LoadOptionsByURL) {
+IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, LoadOptionsByURL) {
   NavigateToSettings();
   VerifyTitle();
   VerifyNavbar();
 }
 
-// Flaky on win_rel http://crbug.com/352546
-#if defined(OS_WIN)
-#define MAYBE_VerifyManagedSignout DISABLED_VerifyManagedSignout
-#else
-#define MAYBE_VerifyManagedSignout VerifyManagedSignout
-#endif
-
 #if !defined(OS_CHROMEOS)
-IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, MAYBE_VerifyManagedSignout) {
-  SigninManager* signin =
-      SigninManagerFactory::GetForProfile(browser()->profile());
-  signin->OnExternalSigninCompleted("test@example.com");
-  signin->ProhibitSignout(true);
-
-  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
-      browser(), GURL(chrome::kChromeUISettingsFrameURL), 1);
-
-  // This script simulates a click on the "Disconnect your Google Account"
-  // button and returns true if the hidden flag of the appropriate dialog gets
-  // flipped.
-  bool result = false;
-  ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
-      browser()->tab_strip_model()->GetActiveWebContents(),
-      "var dialog = $('manage-profile-overlay-disconnect-managed');"
-      "var original_status = dialog.hidden;"
-      "$('start-stop-sync').click();"
-      "domAutomationController.send(original_status && !dialog.hidden);",
-      &result));
-
-  EXPECT_TRUE(result);
-
-  base::FilePath profile_dir = browser()->profile()->GetPath();
-  ProfileInfoCache& profile_info_cache =
-      g_browser_process->profile_manager()->GetProfileInfoCache();
-
-  EXPECT_TRUE(DirectoryExists(profile_dir));
-  EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) !=
-              std::string::npos);
-
-  content::WindowedNotificationObserver wait_for_profile_deletion(
-      chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED,
-      content::NotificationService::AllSources());
-
-#if defined(OS_MACOSX)
-  // TODO(kaliamoorthi): Get the macos problem fixed and remove this code.
-  // Deleting the Profile also destroys all browser windows of that Profile.
-  // Wait for the current browser to close before resuming, otherwise
-  // the browser_tests shutdown code will be confused on the Mac.
-  content::WindowedNotificationObserver wait_for_browser_closed(
-      chrome::NOTIFICATION_BROWSER_CLOSED,
-      content::NotificationService::AllSources());
-#endif
-
-  ASSERT_TRUE(content::ExecuteScript(
-      browser()->tab_strip_model()->GetActiveWebContents(),
-      "$('disconnect-managed-profile-ok').click();"));
-
-  wait_for_profile_deletion.Wait();
-
-  EXPECT_TRUE(profile_info_cache.GetIndexOfProfileWithPath(profile_dir) ==
-              std::string::npos);
-
-#if defined(OS_MACOSX)
-  wait_for_browser_closed.Wait();
-#endif
-}
-
 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, VerifyUnmanagedSignout) {
   SigninManager* signin =
       SigninManagerFactory::GetForProfile(browser()->profile());
   const std::string user = "test@example.com";
   signin->OnExternalSigninCompleted(user);
 
-  ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(
-      browser(), GURL(chrome::kChromeUISettingsFrameURL), 1);
+  NavigateToSettingsFrame();
 
   // This script simulates a click on the "Disconnect your Google Account"
   // button and returns true if the hidden flag of the appropriate dialog gets
@@ -175,15 +169,13 @@
 
   EXPECT_TRUE(result);
 
-  content::WindowedNotificationObserver wait_for_signout(
-      chrome::NOTIFICATION_GOOGLE_SIGNED_OUT,
-      content::NotificationService::AllSources());
+  SignOutWaiter sign_out_waiter(signin);
 
   ASSERT_TRUE(content::ExecuteScript(
       browser()->tab_strip_model()->GetActiveWebContents(),
       "$('stop-syncing-ok').click();"));
 
-  wait_for_signout.Wait();
+  sign_out_waiter.Wait();
 
   EXPECT_TRUE(browser()->profile()->GetProfileName() != user);
   EXPECT_TRUE(signin->GetAuthenticatedUsername().empty());
@@ -192,8 +184,7 @@
 // Regression test for http://crbug.com/301436, excluded on Chrome OS because
 // profile management in the settings UI exists on desktop platforms only.
 IN_PROC_BROWSER_TEST_F(OptionsUIBrowserTest, NavigateBackFromOverlayDialog) {
-  // Navigate to the settings page.
-  ui_test_utils::NavigateToURL(browser(), GURL("chrome://settings-frame"));
+  NavigateToSettingsFrame();
 
   // Click a button that opens an overlay dialog.
   content::WebContents* contents =
diff --git a/chrome/browser/ui/webui/options/options_ui_browsertest.h b/chrome/browser/ui/webui/options/options_ui_browsertest.h
index aed9a6b..85ca83c 100644
--- a/chrome/browser/ui/webui/options/options_ui_browsertest.h
+++ b/chrome/browser/ui/webui/options/options_ui_browsertest.h
@@ -14,9 +14,12 @@
  public:
   OptionsUIBrowserTest();
 
-  // Navigate to the settings tab and block until complete.
+  // Navigate to the Uber/Settings page and block until it has loaded.
   void NavigateToSettings();
 
+  // Navigate to the Settings frame and block until complete.
+  void NavigateToSettingsFrame();
+
   // Check navbar's existence.
   void VerifyNavbar();
 
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
index 28d5eb3..4ee6c2f 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
-#include "chrome/browser/signin/signin_manager_base.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
@@ -51,7 +50,8 @@
 #include "chrome/common/crash_keys.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/print_messages.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_controller.h"
@@ -62,6 +62,7 @@
 #include "content/public/browser/web_ui.h"
 #include "google_apis/gaia/oauth2_token_service.h"
 #include "printing/backend/print_backend.h"
+#include "printing/backend/print_backend_consts.h"
 #include "printing/metafile.h"
 #include "printing/metafile_impl.h"
 #include "printing/pdf_render_settings.h"
@@ -286,19 +287,36 @@
   for (printing::PrinterList::iterator it = printer_list.begin();
        it != printer_list.end(); ++it) {
     base::DictionaryValue* printer_info = new base::DictionaryValue;
+    printers->Append(printer_info);
     std::string printer_name;
+    std::string printer_description;
 #if defined(OS_MACOSX)
     // On Mac, |it->printer_description| specifies the printer name and
     // |it->printer_name| specifies the device name / printer queue name.
     printer_name = it->printer_description;
+    if (!it->options[kDriverNameTagName].empty())
+      printer_description = it->options[kDriverNameTagName];
 #else
     printer_name = it->printer_name;
+    printer_description = it->printer_description;
 #endif
-    printer_info->SetString(printing::kSettingPrinterName, printer_name);
     printer_info->SetString(printing::kSettingDeviceName, it->printer_name);
+    printer_info->SetString(printing::kSettingPrinterDescription,
+                            printer_description);
+    printer_info->SetString(printing::kSettingPrinterName, printer_name);
     VLOG(1) << "Found printer " << printer_name
             << " with device name " << it->printer_name;
-    printers->Append(printer_info);
+
+    base::DictionaryValue* options = new base::DictionaryValue;
+    printer_info->Set(printing::kSettingPrinterOptions, options);
+    for (std::map<std::string, std::string>::iterator opt = it->options.begin();
+         opt != it->options.end();
+         ++opt) {
+      options->SetString(opt->first, opt->second);
+    }
+
+    VLOG(1) << "Found printer " << printer_name << " with device name "
+            << it->printer_name;
   }
   VLOG(1) << "Enumerate printers finished, found " << printers->GetSize()
           << " printers";
@@ -722,6 +740,7 @@
   if (print_with_privet && PrivetPrintingEnabled()) {
     std::string printer_name;
     std::string print_ticket;
+    std::string capabilities;
     UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintWithPrivet", page_count);
     ReportUserActionHistogram(PRINT_WITH_PRIVET);
 
@@ -729,16 +748,18 @@
     int height = 0;
     if (!settings->GetString(printing::kSettingDeviceName, &printer_name) ||
         !settings->GetString(printing::kSettingTicket, &print_ticket) ||
+        !settings->GetString(printing::kSettingCapabilities, &capabilities) ||
         !settings->GetInteger(printing::kSettingPageWidth, &width) ||
         !settings->GetInteger(printing::kSettingPageHeight, &height) ||
-        width <= 0 || height <=0) {
+        width <= 0 || height <= 0) {
       NOTREACHED();
       base::FundamentalValue http_code_value(-1);
       web_ui()->CallJavascriptFunction("onPrivetPrintFailed", http_code_value);
       return;
     }
 
-    PrintToPrivetPrinter(printer_name, print_ticket, gfx::Size(width, height));
+    PrintToPrivetPrinter(
+        printer_name, print_ticket, capabilities, gfx::Size(width, height));
     return;
   }
 #endif
@@ -1402,21 +1423,23 @@
 
 void PrintPreviewHandler::PrivetLocalPrintUpdateClient(
     std::string print_ticket,
+    std::string capabilities,
     gfx::Size page_size,
     scoped_ptr<local_discovery::PrivetHTTPClient> http_client) {
   if (!PrivetUpdateClient(http_client.Pass()))
     return;
 
-  StartPrivetLocalPrint(print_ticket, page_size);
+  StartPrivetLocalPrint(print_ticket, capabilities, page_size);
 }
 
-void PrintPreviewHandler::StartPrivetLocalPrint(
-    const std::string& print_ticket,
-    const gfx::Size& page_size) {
+void PrintPreviewHandler::StartPrivetLocalPrint(const std::string& print_ticket,
+                                                const std::string& capabilities,
+                                                const gfx::Size& page_size) {
   privet_local_print_operation_ =
       privet_http_client_->CreateLocalPrintOperation(this);
 
   privet_local_print_operation_->SetTicket(print_ticket);
+  privet_local_print_operation_->SetCapabilities(capabilities);
 
   scoped_refptr<base::RefCountedBytes> data;
   base::string16 title;
@@ -1480,14 +1503,17 @@
       name_value);
 }
 
-void PrintPreviewHandler::PrintToPrivetPrinter(
-    const std::string& device_name,
-    const std::string& ticket,
-    const gfx::Size& page_size) {
+void PrintPreviewHandler::PrintToPrivetPrinter(const std::string& device_name,
+                                               const std::string& ticket,
+                                               const std::string& capabilities,
+                                               const gfx::Size& page_size) {
   CreatePrivetHTTP(
       device_name,
       base::Bind(&PrintPreviewHandler::PrivetLocalPrintUpdateClient,
-                 base::Unretained(this), ticket, page_size));
+                 base::Unretained(this),
+                 ticket,
+                 capabilities,
+                 page_size));
 }
 
 bool PrintPreviewHandler::CreatePrivetHTTP(
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
index cf33a0b..5ff8fb4 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -253,15 +253,18 @@
       scoped_ptr<local_discovery::PrivetHTTPClient> http_client);
   void PrivetLocalPrintUpdateClient(
       std::string print_ticket,
+      std::string capabilities,
       gfx::Size page_size,
       scoped_ptr<local_discovery::PrivetHTTPClient> http_client);
   bool PrivetUpdateClient(
       scoped_ptr<local_discovery::PrivetHTTPClient> http_client);
   void StartPrivetLocalPrint(const std::string& print_ticket,
+                             const std::string& capabilities,
                              const gfx::Size& page_size);
   void SendPrivetCapabilitiesError(const std::string& id);
   void PrintToPrivetPrinter(const std::string& printer_name,
                             const std::string& print_ticket,
+                            const std::string& capabilities,
                             const gfx::Size& page_size);
   bool CreatePrivetHTTP(
       const std::string& name,
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
index 0d2e2ad..db7cddc 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc
@@ -24,12 +24,13 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/gaia_auth_util.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/url_util.h"
@@ -299,7 +300,7 @@
       net::GetValueForKeyInQuery(current_url, "validateEmail",
                                  &validate_email) &&
       validate_email == "1") {
-    if (email_ != default_email) {
+    if (!gaia::AreEmailsSame(email_, default_email)) {
       SyncStarterCallback(OneClickSigninSyncStarter::SYNC_SETUP_FAILURE);
       return;
     }
diff --git a/chrome/browser/ui/webui/signin/login_ui_service_factory.cc b/chrome/browser/ui/webui/signin/login_ui_service_factory.cc
index cd8f7cd..82cf510 100644
--- a/chrome/browser/ui/webui/signin/login_ui_service_factory.cc
+++ b/chrome/browser/ui/webui/signin/login_ui_service_factory.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
 
 #include "base/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/signin_manager.h"
 #include "chrome/browser/ui/webui/signin/login_ui_service.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc
index e5fb406..2bfe34b 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/dump_database_handler.cc
@@ -26,8 +26,11 @@
 }
 
 void DumpDatabaseHandler::GetDatabaseDump(const base::ListValue* args) {
-  scoped_ptr<base::ListValue> list =
-      SyncFileSystemServiceFactory::GetForProfile(profile_)->DumpDatabase();
+  scoped_ptr<base::ListValue> list;
+  sync_file_system::SyncFileSystemService* sync_service =
+      SyncFileSystemServiceFactory::GetForProfile(profile_);
+  if (sync_service)
+    list = sync_service->DumpDatabase();
   if (!list)
     list.reset(new base::ListValue);
   web_ui()->CallJavascriptFunction("DumpDatabase.onGetDatabaseDump",
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
index 88147f1..061dc83 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/extension_statuses_handler.cc
@@ -42,14 +42,15 @@
     base::ListValue* values) {
   DCHECK(profile);
   DCHECK(values);
-  std::map<GURL, std::string> status_map;
-  SyncFileSystemServiceFactory::GetForProfile(profile)->GetExtensionStatusMap(
-      &status_map);
-
+  sync_file_system::SyncFileSystemService* sync_service =
+      SyncFileSystemServiceFactory::GetForProfile(profile);
   ExtensionService* extension_service =
       extensions::ExtensionSystem::Get(profile)->extension_service();
-  if (!extension_service)
+  if (!sync_service || !extension_service)
     return;
+
+  std::map<GURL, std::string> status_map;
+  sync_service->GetExtensionStatusMap(&status_map);
   for (std::map<GURL, std::string>::const_iterator itr = status_map.begin();
        itr != status_map.end();
        ++itr) {
diff --git a/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc b/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
index b8af67a..96ce60e 100644
--- a/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
+++ b/chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_handler.cc
@@ -30,14 +30,14 @@
     : profile_(profile) {
   sync_file_system::SyncFileSystemService* sync_service =
       SyncFileSystemServiceFactory::GetForProfile(profile);
-  DCHECK(sync_service);
-  sync_service->AddSyncEventObserver(this);
+  if (sync_service)
+    sync_service->AddSyncEventObserver(this);
 }
 
 SyncFileSystemInternalsHandler::~SyncFileSystemInternalsHandler() {
   sync_file_system::SyncFileSystemService* sync_service =
       SyncFileSystemServiceFactory::GetForProfile(profile_);
-  if (sync_service != NULL)
+  if (sync_service)
     sync_service->RemoveSyncEventObserver(this);
 }
 
@@ -83,9 +83,12 @@
 
 void SyncFileSystemInternalsHandler::GetServiceStatus(
     const base::ListValue* args) {
-  SyncServiceState state_enum = SyncFileSystemServiceFactory::GetForProfile(
-      profile_)->GetSyncServiceState();
-  std::string state_string = extensions::api::sync_file_system::ToString(
+  SyncServiceState state_enum = sync_file_system::SYNC_SERVICE_DISABLED;
+  sync_file_system::SyncFileSystemService* sync_service =
+      SyncFileSystemServiceFactory::GetForProfile(profile_);
+  if (sync_service)
+    state_enum = sync_service->GetSyncServiceState();
+  const std::string state_string = extensions::api::sync_file_system::ToString(
       extensions::SyncServiceStateToExtensionEnum(state_enum));
   web_ui()->CallJavascriptFunction("SyncService.onGetServiceStatus",
                                    base::StringValue(state_string));
@@ -95,6 +98,8 @@
     const base::ListValue* args) {
   drive::DriveNotificationManager* drive_notification_manager =
       drive::DriveNotificationManagerFactory::GetForBrowserContext(profile_);
+  if (!drive_notification_manager)
+    return;
   bool xmpp_enabled = drive_notification_manager->push_notification_enabled();
   std::string notification_source = xmpp_enabled ? "XMPP" : "Polling";
   web_ui()->CallJavascriptFunction("SyncService.onGetNotificationSource",
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.cc b/chrome/browser/ui/webui/sync_internals_message_handler.cc
index 28edb86..e0b64f9 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/sync/profile_sync_service_factory.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_ui.h"
+#include "sync/internal_api/public/events/protocol_event.h"
 #include "sync/internal_api/public/util/weak_handle.h"
 #include "sync/js/js_arg_list.h"
 #include "sync/js/js_event_details.h"
@@ -24,12 +25,17 @@
 using syncer::WeakHandle;
 
 SyncInternalsMessageHandler::SyncInternalsMessageHandler()
-    : scoped_observer_(this),
-      weak_ptr_factory_(this) {}
+    : weak_ptr_factory_(this) {}
 
 SyncInternalsMessageHandler::~SyncInternalsMessageHandler() {
   if (js_controller_)
     js_controller_->RemoveJsEventHandler(this);
+
+  ProfileSyncService* service = GetProfileSyncService();
+  if (service && service->HasObserver(this)) {
+    service->RemoveObserver(this);
+    service->RemoveProtocolEventObserver(this);
+  }
 }
 
 void SyncInternalsMessageHandler::RegisterMessages() {
@@ -38,7 +44,8 @@
   // Register for ProfileSyncService events.
   ProfileSyncService* service = GetProfileSyncService();
   if (service) {
-    scoped_observer_.Add(service);
+    service->AddObserver(this);
+    service->AddProtocolEventObserver(this);
     js_controller_ = service->GetJsController();
     js_controller_->AddJsEventHandler(this);
   }
@@ -53,8 +60,6 @@
       base::Bind(&SyncInternalsMessageHandler::HandleRequestListOfTypes,
                  base::Unretained(this)));
 
-  RegisterJsControllerCallback("getNotificationState");
-  RegisterJsControllerCallback("getNotificationInfo");
   RegisterJsControllerCallback("getAllNodes");
   RegisterJsControllerCallback("getClientServerTraffic");
 }
@@ -96,6 +101,16 @@
   SendAboutInfo();
 }
 
+void SyncInternalsMessageHandler::OnProtocolEvent(
+    const syncer::ProtocolEvent& event) {
+  scoped_ptr<base::DictionaryValue> value(
+      syncer::ProtocolEvent::ToValue(event));
+  web_ui()->CallJavascriptFunction(
+      "chrome.sync.dispatchEvent",
+      base::StringValue("onProtocolEvent"),
+      *value);
+}
+
 void SyncInternalsMessageHandler::HandleJsEvent(
     const std::string& name,
     const JsEventDetails& details) {
diff --git a/chrome/browser/ui/webui/sync_internals_message_handler.h b/chrome/browser/ui/webui/sync_internals_message_handler.h
index 902c1d6..806e25d 100644
--- a/chrome/browser/ui/webui/sync_internals_message_handler.h
+++ b/chrome/browser/ui/webui/sync_internals_message_handler.h
@@ -13,6 +13,7 @@
 #include "base/scoped_observer.h"
 #include "base/values.h"
 #include "chrome/browser/sync/profile_sync_service_observer.h"
+#include "chrome/browser/sync/protocol_event_observer.h"
 #include "content/public/browser/web_ui_message_handler.h"
 #include "sync/js/js_controller.h"
 #include "sync/js/js_event_handler.h"
@@ -25,7 +26,8 @@
     : public content::WebUIMessageHandler,
       public syncer::JsEventHandler,
       public syncer::JsReplyHandler,
-      public ProfileSyncServiceObserver {
+      public ProfileSyncServiceObserver,
+      public browser_sync::ProtocolEventObserver {
  public:
   SyncInternalsMessageHandler();
   virtual ~SyncInternalsMessageHandler();
@@ -54,6 +56,9 @@
   // ProfileSyncServiceObserver implementation.
   virtual void OnStateChanged() OVERRIDE;
 
+  // ProtocolEventObserver implementation.
+  virtual void OnProtocolEvent(const syncer::ProtocolEvent& e) OVERRIDE;
+
  private:
   // Helper function to register JsController function callbacks.
   void RegisterJsControllerCallback(const std::string& name);
@@ -64,9 +69,6 @@
 
   ProfileSyncService* GetProfileSyncService();
 
-  ScopedObserver<ProfileSyncService, SyncInternalsMessageHandler>
-      scoped_observer_;
-
   base::WeakPtr<syncer::JsController> js_controller_;
   base::WeakPtrFactory<SyncInternalsMessageHandler> weak_ptr_factory_;
 
diff --git a/chrome/browser/ui/webui/sync_setup_handler.cc b/chrome/browser/ui/webui/sync_setup_handler.cc
index 3c73742..dc20992 100644
--- a/chrome/browser/ui/webui/sync_setup_handler.cc
+++ b/chrome/browser/ui/webui/sync_setup_handler.cc
@@ -37,8 +37,8 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/signin/core/signin_error_controller.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
 #include "components/sync_driver/sync_prefs.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
@@ -52,7 +52,7 @@
 #include "ui/base/l10n/l10n_util.h"
 
 #if defined(OS_CHROMEOS)
-#include "chrome/browser/signin/signin_manager_base.h"
+#include "components/signin/core/browser/signin_manager_base.h"
 #else
 #include "chrome/browser/signin/signin_manager.h"
 #endif
diff --git a/chrome/browser/ui/webui/sync_setup_handler_unittest.cc b/chrome/browser/ui/webui/sync_setup_handler_unittest.cc
index a8e4687..503a206 100644
--- a/chrome/browser/ui/webui/sync_setup_handler_unittest.cc
+++ b/chrome/browser/ui/webui/sync_setup_handler_unittest.cc
@@ -12,7 +12,6 @@
 #include "base/prefs/pref_service.h"
 #include "base/stl_util.h"
 #include "base/values.h"
-#include "chrome/browser/signin/fake_auth_status_provider.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_manager.h"
@@ -26,7 +25,8 @@
 #include "chrome/test/base/scoped_testing_local_state.h"
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
 #include "components/sync_driver/sync_prefs.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/test/test_browser_thread.h"
@@ -209,7 +209,8 @@
     return 0;
   }
   virtual void SetBindings(int bindings) OVERRIDE {}
-  virtual void SetFrameXPath(const std::string& xpath) OVERRIDE {}
+  virtual void OverrideJavaScriptFrame(
+      const std::string& frame_name) OVERRIDE {}
   virtual void AddMessageHandler(
       content::WebUIMessageHandler* handler) OVERRIDE {}
   virtual void RegisterMessageCallback(
@@ -279,13 +280,19 @@
   SyncSetupHandlerTest() : error_(GoogleServiceAuthError::NONE) {}
   virtual void SetUp() OVERRIDE {
     error_ = GoogleServiceAuthError::AuthErrorNone();
-    profile_.reset(ProfileSyncServiceMock::MakeSignedInTestingProfile());
 
+    TestingProfile::Builder builder;
+    builder.AddTestingFactory(SigninManagerFactory::GetInstance(),
+                              FakeSigninManagerBase::Build);
+    profile_ = builder.Build();
+
+    // Sign in the user.
     mock_signin_ = static_cast<SigninManagerBase*>(
-        SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
-            profile_.get(), FakeSigninManagerBase::Build));
-    profile_->GetPrefs()->SetString(
-        prefs::kGoogleServicesUsername, GetTestUser());
+        SigninManagerFactory::GetForProfile(profile_.get()));
+    mock_signin_->SetAuthenticatedUsername(GetTestUser());
+    profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
+                                    GetTestUser());
+
     mock_pss_ = static_cast<ProfileSyncServiceMock*>(
         ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
             profile_.get(),
diff --git a/chrome/browser/ui/webui/uber/uber_ui.cc b/chrome/browser/ui/webui/uber/uber_ui.cc
index d200923..4393e5f 100644
--- a/chrome/browser/ui/webui/uber/uber_ui.cc
+++ b/chrome/browser/ui/webui/uber/uber_ui.cc
@@ -131,25 +131,37 @@
   Profile* profile = Profile::FromWebUI(web_ui);
   content::WebUIDataSource::Add(profile, CreateUberHTMLSource());
 
-  RegisterSubpage(chrome::kChromeUIExtensionsFrameURL);
-  RegisterSubpage(chrome::kChromeUIHelpFrameURL);
-  RegisterSubpage(chrome::kChromeUIHistoryFrameURL);
-  RegisterSubpage(chrome::kChromeUISettingsFrameURL);
-  RegisterSubpage(chrome::kChromeUIUberFrameURL);
+  RegisterSubpage(chrome::kChromeUIExtensionsFrameURL,
+                  chrome::kChromeUIExtensionsHost);
+  RegisterSubpage(chrome::kChromeUIHelpFrameURL,
+                  chrome::kChromeUIHelpHost);
+  RegisterSubpage(chrome::kChromeUIHistoryFrameURL,
+                  chrome::kChromeUIHistoryHost);
+  RegisterSubpage(chrome::kChromeUISettingsFrameURL,
+                  chrome::kChromeUISettingsHost);
+  RegisterSubpage(chrome::kChromeUIUberFrameURL,
+                  chrome::kChromeUIUberHost);
 }
 
 UberUI::~UberUI() {
   STLDeleteValues(&sub_uis_);
 }
 
-void UberUI::RegisterSubpage(const std::string& page_url) {
-  content::WebUI* webui =
-      web_ui()->GetWebContents()->CreateWebUI(GURL(page_url));
+void UberUI::RegisterSubpage(const std::string& page_url,
+                             const std::string& page_host) {
+  GURL page_gurl(page_url);
+  content::WebUI* webui = web_ui()->GetWebContents()->CreateWebUI(page_gurl);
 
-  webui->SetFrameXPath("//iframe[starts-with(@src,'" + page_url + "')]");
+  webui->OverrideJavaScriptFrame(page_host);
   sub_uis_[page_url] = webui;
 }
 
+content::WebUI* UberUI::GetSubpage(const std::string& page_url) {
+  if (!sub_uis_.count(page_url))
+    return NULL;
+  return sub_uis_[page_url];
+}
+
 void UberUI::RenderViewCreated(RenderViewHost* render_view_host) {
   for (SubpageMap::iterator iter = sub_uis_.begin(); iter != sub_uis_.end();
        ++iter) {
diff --git a/chrome/browser/ui/webui/uber/uber_ui.h b/chrome/browser/ui/webui/uber/uber_ui.h
index e8e7f38..7183b03 100644
--- a/chrome/browser/ui/webui/uber/uber_ui.h
+++ b/chrome/browser/ui/webui/uber/uber_ui.h
@@ -22,6 +22,8 @@
   explicit UberUI(content::WebUI* web_ui);
   virtual ~UberUI();
 
+  content::WebUI* GetSubpage(const std::string& page_url);
+
   // WebUIController implementation.
   virtual bool OverrideHandleWebUIMessage(const GURL& source_url,
                                           const std::string& message,
@@ -38,7 +40,8 @@
   typedef std::map<std::string, content::WebUI*> SubpageMap;
 
   // Creates and stores a WebUI for the given URL.
-  void RegisterSubpage(const std::string& page_url);
+  void RegisterSubpage(const std::string& page_url,
+                       const std::string& page_host);
 
   // The WebUI*s in this map are owned.
   SubpageMap sub_uis_;
diff --git a/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc b/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc
index 2caef65..767db59 100644
--- a/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc
+++ b/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc
@@ -69,7 +69,7 @@
           content::PAGE_TRANSITION_TYPED, history::SOURCE_SYNCED, false);
   test_web_contents_delegate_->NavigationStateChanged(NULL, 0);
   test_web_contents_delegate_->ActivateContents(NULL);
-  test_web_contents_delegate_->LoadingStateChanged(NULL);
+  test_web_contents_delegate_->LoadingStateChanged(NULL, true);
   test_web_contents_delegate_->CloseContents(NULL);
   test_web_contents_delegate_->UpdateTargetURL(NULL, 0, GURL());
   test_web_contents_delegate_->MoveContents(NULL, gfx::Rect());
diff --git a/chrome/browser/ui/webui/web_ui_test_handler.cc b/chrome/browser/ui/webui/web_ui_test_handler.cc
index 8f1d7b7..0f7a8f7 100644
--- a/chrome/browser/ui/webui/web_ui_test_handler.cc
+++ b/chrome/browser/ui/webui/web_ui_test_handler.cc
@@ -32,8 +32,7 @@
                                          RenderViewHost* preload_host) {
   DCHECK(preload_host);
   preload_host->Send(new ChromeViewMsg_WebUIJavaScript(
-      preload_host->GetRoutingID(), base::string16(), js_text, 0,
-      false));
+      preload_host->GetRoutingID(), js_text));
 }
 
 void WebUITestHandler::RunJavaScript(const base::string16& js_text) {
diff --git a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
index 8150107..3418e69 100644
--- a/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
+++ b/chrome/browser/ui/window_sizer/window_sizer_ash_unittest.cc
@@ -18,12 +18,12 @@
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/render_view_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/gfx/screen.h"
+#include "ui/wm/public/activation_client.h"
 
 typedef ash::test::AshTestBase WindowSizerAshTest;
 
diff --git a/chrome/browser/upgrade_detector.cc b/chrome/browser/upgrade_detector.cc
index f6b68bc..55327bd 100644
--- a/chrome/browser/upgrade_detector.cc
+++ b/chrome/browser/upgrade_detector.cc
@@ -35,6 +35,7 @@
 void UpgradeDetector::RegisterPrefs(PrefRegistrySimple* registry) {
   registry->RegisterBooleanPref(prefs::kRestartLastSessionOnShutdown, false);
   registry->RegisterBooleanPref(prefs::kWasRestarted, false);
+  registry->RegisterBooleanPref(prefs::kAttemptedToEnableAutoupdate, false);
 }
 
 int UpgradeDetector::GetIconResourceID(UpgradeNotificationIconType type) {
@@ -109,6 +110,13 @@
           content::NotificationService::NoDetails());
       break;
     }
+    case UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU: {
+      content::NotificationService::current()->Notify(
+          chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
+          content::Source<UpgradeDetector>(this),
+          content::NotificationService::NoDetails());
+      break;
+    }
     case UPGRADE_AVAILABLE_CRITICAL: {
       int idle_timer = UseTestingIntervals() ?
           kIdleRepeatingTimerWait :
diff --git a/chrome/browser/upgrade_detector.h b/chrome/browser/upgrade_detector.h
index 9c1826e..cd84b27 100644
--- a/chrome/browser/upgrade_detector.h
+++ b/chrome/browser/upgrade_detector.h
@@ -54,6 +54,12 @@
     return upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL;
   }
 
+  // Whether the upgrade recommendation is due to Chrome being outdated AND
+  // auto-update is turned off.
+  bool is_outdated_install_no_au() const {
+    return upgrade_available_ == UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU;
+  }
+
   // Notifify this object that the user has acknowledged the critical update
   // so we don't need to complain about it for now.
   void acknowledge_critical_update() {
@@ -105,6 +111,9 @@
     // If no update to Chrome has been installed for more than the recommended
     // time.
     UPGRADE_NEEDED_OUTDATED_INSTALL,
+    // If no update to Chrome has been installed for more than the recommended
+    // time AND auto-update is turned off.
+    UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU,
   } upgrade_available_;
 
   // Whether the user has acknowledged the critical update.
diff --git a/chrome/browser/upgrade_detector_impl.cc b/chrome/browser/upgrade_detector_impl.cc
index f293453..cf56ba7 100644
--- a/chrome/browser/upgrade_detector_impl.cc
+++ b/chrome/browser/upgrade_detector_impl.cc
@@ -13,6 +13,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/singleton.h"
 #include "base/path_service.h"
+#include "base/prefs/pref_service.h"
 #include "base/process/launch.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -23,18 +24,18 @@
 #include "chrome/browser/google/google_util.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
+#include "chrome/common/pref_names.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_WIN)
+#include "base/win/win_util.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/google_update_settings.h"
 #include "chrome/installer/util/helper.h"
 #include "chrome/installer/util/install_util.h"
 #elif defined(OS_MACOSX)
 #include "chrome/browser/mac/keystone_glue.h"
-#elif defined(OS_POSIX)
-#include "base/process/launch.h"
 #endif
 
 using content::BrowserThread;
@@ -55,17 +56,28 @@
 // The number of days after which we identify a build/install as outdated.
 const uint64 kOutdatedBuildAgeInDays = 12 * 7;
 
+// Return the string that was passed as a value for the
+// kCheckForUpdateIntervalSec switch.
 std::string CmdLineInterval() {
   const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
   return cmd_line.GetSwitchValueASCII(switches::kCheckForUpdateIntervalSec);
 }
 
+// Check if one of the outdated simulation switches was present on the command
+// line.
+bool SimulatingOutdated() {
+  const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
+  return cmd_line.HasSwitch(switches::kSimulateOutdated) ||
+      cmd_line.HasSwitch(switches::kSimulateOutdatedNoAU);
+}
+
+// Check if any of the testing switches was present on the command line.
 bool IsTesting() {
   const CommandLine& cmd_line = *CommandLine::ForCurrentProcess();
   return cmd_line.HasSwitch(switches::kSimulateUpgrade) ||
       cmd_line.HasSwitch(switches::kCheckForUpdateIntervalSec) ||
       cmd_line.HasSwitch(switches::kSimulateCriticalUpdate) ||
-      cmd_line.HasSwitch(switches::kSimulateOutdated);
+      SimulatingOutdated();
 }
 
 // How often to check for an upgrade.
@@ -79,6 +91,7 @@
   return kCheckForUpgradeMs;
 }
 
+// Return true if the current build is one of the unstable channels.
 bool IsUnstableChannel() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
   chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel();
@@ -96,6 +109,7 @@
 }
 
 #if defined(OS_WIN)
+// Return true if the currently running Chrome is a system install.
 bool IsSystemInstall() {
   // Get the version of the currently *installed* instance of Chrome,
   // which might be newer than the *running* instance if we have been
@@ -109,19 +123,25 @@
   return !InstallUtil::IsPerUserInstall(exe_path.value().c_str());
 }
 
-// This task checks the update policy and calls back the task only if automatic
-// updates are allowed. It also identifies whether we are running an unstable
-// channel.
+// This task checks the update policy and calls back the task only if the
+// system is not enrolled in a domain (i.e., not in an enterprise environment).
+// It also identifies if autoupdate is enabled and whether we are running an
+// unstable channel. |is_auto_update_enabled| can be NULL.
 void DetectUpdatability(const base::Closure& callback_task,
-                        bool* is_unstable_channel) {
+                        bool* is_unstable_channel,
+                        bool* is_auto_update_enabled) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
 
   base::string16 app_guid = installer::GetAppGuidForUpdates(IsSystemInstall());
   DCHECK(!app_guid.empty());
-  if (GoogleUpdateSettings::AUTOMATIC_UPDATES ==
-      GoogleUpdateSettings::GetAppUpdatePolicy(app_guid, NULL)) {
-    CheckForUnstableChannel(callback_task, is_unstable_channel);
+  // Don't try to turn on autoupdate when we failed previously.
+  if (is_auto_update_enabled) {
+    *is_auto_update_enabled =
+        GoogleUpdateSettings::AreAutoupdatesEnabled(app_guid);
   }
+  // Don't show the update bubbles to entreprise users (i.e., on a domain).
+  if (!base::win::IsEnrolledToDomain())
+    CheckForUnstableChannel(callback_task, is_unstable_channel);
 }
 #endif  // defined(OS_WIN)
 
@@ -130,6 +150,7 @@
 UpgradeDetectorImpl::UpgradeDetectorImpl()
     : weak_factory_(this),
       is_unstable_channel_(false),
+      is_auto_update_enabled_(true),
       build_date_(base::GetBuildTime()) {
   CommandLine command_line(*CommandLine::ForCurrentProcess());
   // The different command line switches that affect testing can't be used
@@ -139,7 +160,8 @@
   //   switch from being taken into account.
   // - kSimulateUpgrade supersedes critical or outdated upgrade switches.
   // - kSimulateCriticalUpdate has precedence over kSimulateOutdated.
-  // - kSimulateOutdated can work on its own, or with a specified date.
+  // - kSimulateOutdatedNoAU has precedence over kSimulateOutdated.
+  // - kSimulateOutdated[NoAu] can work on its own, or with a specified date.
   if (command_line.HasSwitch(switches::kDisableBackgroundNetworking))
     return;
   if (command_line.HasSwitch(switches::kSimulateUpgrade)) {
@@ -150,7 +172,7 @@
     UpgradeDetected(UPGRADE_AVAILABLE_CRITICAL);
     return;
   }
-  if (command_line.HasSwitch(switches::kSimulateOutdated)) {
+  if (SimulatingOutdated()) {
     // The outdated simulation can work without a value, which means outdated
     // now, or with a value that must be a well formed date/time string that
     // overrides the build date.
@@ -158,8 +180,14 @@
     // tracking moves off of the VariationsService, the "variations-server-url"
     // command line switch must also be specified for the service to be
     // available on non GOOGLE_CHROME_BUILD.
-    std::string build_date = command_line.GetSwitchValueASCII(
-        switches::kSimulateOutdated);
+    std::string switch_name;
+    if (command_line.HasSwitch(switches::kSimulateOutdatedNoAU)) {
+      is_auto_update_enabled_ = false;
+      switch_name = switches::kSimulateOutdatedNoAU;
+    } else {
+      switch_name = switches::kSimulateOutdated;
+    }
+    std::string build_date = command_line.GetSwitchValueASCII(switch_name);
     base::Time maybe_build_time;
     bool result = base::Time::FromString(build_date.c_str(), &maybe_build_time);
     if (result && !maybe_build_time.is_null()) {
@@ -168,7 +196,9 @@
       StartTimerForUpgradeCheck();
     } else {
       // Without a valid date, we simulate that we are already outdated...
-      UpgradeDetected(UPGRADE_NEEDED_OUTDATED_INSTALL);
+      UpgradeDetected(
+          is_auto_update_enabled_ ? UPGRADE_NEEDED_OUTDATED_INSTALL
+                                  : UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU);
     }
     return;
   }
@@ -181,18 +211,27 @@
   // Only enable upgrade notifications for official builds.  Chromium has no
   // upgrade channel.
 #if defined(GOOGLE_CHROME_BUILD)
-  // On Windows, there might be a policy preventing updates, so validate
-  // updatability, and then call StartTimerForUpgradeCheck appropriately.
+  // On Windows, there might be a policy/enterprise environment preventing
+  // updates, so validate updatability, and then call StartTimerForUpgradeCheck
+  // appropriately. And don't check for autoupdate if we already attempted to
+  // enable it in the past.
+  bool attempted_enabling_autoupdate = g_browser_process->local_state() &&
+      g_browser_process->local_state()->GetBoolean(
+          prefs::kAttemptedToEnableAutoupdate);
   BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
                           base::Bind(&DetectUpdatability,
                                      start_upgrade_check_timer_task,
-                                     &is_unstable_channel_));
+                                     &is_unstable_channel_,
+                                     attempted_enabling_autoupdate ?
+                                         NULL : &is_auto_update_enabled_));
 #endif
 #else
 #if defined(OS_MACOSX)
   // Only enable upgrade notifications if the updater (Keystone) is present.
-  if (!keystone_glue::KeystoneEnabled())
+  if (!keystone_glue::KeystoneEnabled()) {
+    is_auto_update_enabled_ = false;
     return;
+  }
 #elif defined(OS_POSIX)
   // Always enable upgrade notifications regardless of branding.
 #else
@@ -203,10 +242,9 @@
                           base::Bind(&CheckForUnstableChannel,
                                      start_upgrade_check_timer_task,
                                      &is_unstable_channel_));
-
+#endif
   // Start tracking network time updates.
   network_time_tracker_.Start();
-#endif
 }
 
 UpgradeDetectorImpl::~UpgradeDetectorImpl() {
@@ -315,12 +353,10 @@
 }
 
 bool UpgradeDetectorImpl::DetectOutdatedInstall() {
-  // Only enable the outdated install check if we are running the trial for it,
-  // unless we are simulating an outdated isntall.
-  static bool simulate_outdated = CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kSimulateOutdated);
+  // Don't show the bubble if we have a brand code that is NOT organic, unless
+  // an outdated build is being simulated by command line switches.
+  static bool simulate_outdated = SimulatingOutdated();
   if (!simulate_outdated) {
-    // Also don't show the bubble if we have a brand code that is NOT organic.
     std::string brand;
     if (google_util::GetBrand(&brand) && !google_util::IsOrganic(brand))
       return false;
@@ -331,7 +367,9 @@
   if (!network_time_tracker_.GetNetworkTime(base::TimeTicks::Now(),
                                             &network_time,
                                             &uncertainty)) {
-    return false;
+    // When network time has not been initialized yet, simply rely on the
+    // machine's current time.
+    network_time = base::Time::Now();
   }
 
   if (network_time.is_null() || build_date_.is_null() ||
@@ -342,7 +380,9 @@
 
   if (network_time - build_date_ >
       base::TimeDelta::FromDays(kOutdatedBuildAgeInDays)) {
-    UpgradeDetected(UPGRADE_NEEDED_OUTDATED_INSTALL);
+    UpgradeDetected(is_auto_update_enabled_ ?
+        UPGRADE_NEEDED_OUTDATED_INSTALL :
+        UPGRADE_NEEDED_OUTDATED_INSTALL_NO_AU);
     return true;
   }
   // If we simlated an outdated install with a date, we don't want to keep
diff --git a/chrome/browser/upgrade_detector_impl.h b/chrome/browser/upgrade_detector_impl.h
index d0eef53..30bf7b0 100644
--- a/chrome/browser/upgrade_detector_impl.h
+++ b/chrome/browser/upgrade_detector_impl.h
@@ -66,6 +66,9 @@
   // True if this build is a dev or canary channel build.
   bool is_unstable_channel_;
 
+  // True if auto update is turned on.
+  bool is_auto_update_enabled_;
+
   // The date the binaries were built.
   base::Time build_date_;
 
diff --git a/chrome/browser/upload_list.cc b/chrome/browser/upload_list.cc
index 2f96005..cd236c6 100644
--- a/chrome/browser/upload_list.cc
+++ b/chrome/browser/upload_list.cc
@@ -15,8 +15,13 @@
 
 using content::BrowserThread;
 
-UploadList::UploadInfo::UploadInfo(const std::string& c, const base::Time& t)
-    : id(c), time(t) {}
+UploadList::UploadInfo::UploadInfo(const std::string& id,
+                                   const base::Time& t,
+                                   const std::string& local_id)
+    : id(id), time(t), local_id(local_id) {}
+
+UploadList::UploadInfo::UploadInfo(const std::string& id, const base::Time& t)
+    : id(id), time(t) {}
 
 UploadList::UploadInfo::~UploadInfo() {}
 
@@ -74,13 +79,18 @@
     std::vector<std::string> components;
     base::SplitString(*i, ',', &components);
     // Skip any blank (or corrupted) lines.
-    if (components.size() != 2)
+    if (components.size() != 2 && components.size() != 3)
       continue;
+    base::Time upload_time;
     double seconds_since_epoch;
-    if (!base::StringToDouble(components[0], &seconds_since_epoch))
-      continue;
-    UploadInfo info(components[1],
-                    base::Time::FromDoubleT(seconds_since_epoch));
+    if (!components[0].empty()) {
+      if (!base::StringToDouble(components[0], &seconds_since_epoch))
+        continue;
+      upload_time = base::Time::FromDoubleT(seconds_since_epoch);
+    }
+    UploadInfo info(components[1], upload_time);
+    if (components.size() == 3)
+      info.local_id = components[2];
     uploads_.push_back(info);
   }
 }
diff --git a/chrome/browser/upload_list.h b/chrome/browser/upload_list.h
index e62288d..9561193 100644
--- a/chrome/browser/upload_list.h
+++ b/chrome/browser/upload_list.h
@@ -14,20 +14,25 @@
 #include "base/time/time.h"
 
 // Loads and parses an upload list text file of the format
-// time,id
-// time,id
+// time,id[,local_id]
+// time,id[,local_id]
 // etc.
 // where each line represents an upload and "time" is Unix time. Must be used
 // from the UI thread. The loading and parsing is done on a blocking pool task
-// runner.
+// runner. A line may or may not contain "local_id".
 class UploadList : public base::RefCountedThreadSafe<UploadList> {
  public:
   struct UploadInfo {
-    UploadInfo(const std::string& c, const base::Time& t);
+    UploadInfo(const std::string& id,
+               const base::Time& t,
+               const std::string& local_id);
+    UploadInfo(const std::string& id, const base::Time& t);
     ~UploadInfo();
 
     std::string id;
     base::Time time;
+    // ID for a locally stored object that may or may not be uploaded.
+    std::string local_id;
   };
 
   class Delegate {
@@ -71,6 +76,7 @@
  private:
   friend class base::RefCountedThreadSafe<UploadList>;
   FRIEND_TEST_ALL_PREFIXES(UploadListTest, ParseLogEntries);
+  FRIEND_TEST_ALL_PREFIXES(UploadListTest, ParseLogEntriesWithLocalId);
 
   // Manages the background thread work for LoadUploadListAsynchronously().
   void LoadUploadListAndInformDelegateOfCompletion();
diff --git a/chrome/browser/upload_list_unittest.cc b/chrome/browser/upload_list_unittest.cc
index 153f9db..9dfa9eb 100644
--- a/chrome/browser/upload_list_unittest.cc
+++ b/chrome/browser/upload_list_unittest.cc
@@ -32,6 +32,7 @@
   double time_double = upload_list->uploads_[0].time.ToDoubleT();
   EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
   EXPECT_STREQ(kTestID, upload_list->uploads_[0].id.c_str());
+  EXPECT_STREQ("", upload_list->uploads_[0].local_id.c_str());
 
   // Add 3 more entries.
   log_entries.push_back(test_entry);
@@ -41,4 +42,39 @@
   time_double = upload_list->uploads_[3].time.ToDoubleT();
   EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
   EXPECT_STREQ(kTestID, upload_list->uploads_[3].id.c_str());
+  EXPECT_STREQ("", upload_list->uploads_[3].local_id.c_str());
+}
+
+TEST(UploadListTest, ParseLogEntriesWithLocalId) {
+  const char kTestTime[] = "1234567890";
+  const char kTestID[] = "0123456789abcdef";
+  const char kTestLocalID[] = "fedcba9876543210";
+  std::string test_entry = kTestTime;
+  test_entry += ",";
+  test_entry.append(kTestID, sizeof(kTestID));
+  test_entry += ",";
+  test_entry.append(kTestLocalID, sizeof(kTestLocalID));
+
+  scoped_refptr<UploadList> upload_list =
+      new UploadList(NULL, base::FilePath());
+
+  // 1 entry.
+  std::vector<std::string> log_entries;
+  log_entries.push_back(test_entry);
+  upload_list->ParseLogEntries(log_entries);
+  EXPECT_EQ(1u, upload_list->uploads_.size());
+  double time_double = upload_list->uploads_[0].time.ToDoubleT();
+  EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
+  EXPECT_STREQ(kTestID, upload_list->uploads_[0].id.c_str());
+  EXPECT_STREQ(kTestLocalID, upload_list->uploads_[0].local_id.c_str());
+
+  // Add 3 more entries.
+  log_entries.push_back(test_entry);
+  log_entries.push_back(test_entry);
+  upload_list->ParseLogEntries(log_entries);
+  EXPECT_EQ(4u, upload_list->uploads_.size());
+  time_double = upload_list->uploads_[3].time.ToDoubleT();
+  EXPECT_STREQ(kTestTime, base::DoubleToString(time_double).c_str());
+  EXPECT_STREQ(kTestID, upload_list->uploads_[3].id.c_str());
+  EXPECT_STREQ(kTestLocalID, upload_list->uploads_[3].local_id.c_str());
 }
diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm
index ba8e4f6..3edfc4e 100644
--- a/chrome/browser/web_applications/web_app_mac.mm
+++ b/chrome/browser/web_applications/web_app_mac.mm
@@ -440,7 +440,7 @@
   // Normally we would show a dialog, but since we always create the app
   // shortcut in /Applications there are no options for the user to choose.
   web_app::UpdateShortcutInfoAndIconForApp(
-      *app, profile,
+      app, profile,
       base::Bind(&CreateShortcutsAndRunCallback, close_callback));
 }
 
diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc
index cef73df..3178d67 100644
--- a/chrome/browser/web_applications/web_app_win.cc
+++ b/chrome/browser/web_applications/web_app_win.cc
@@ -32,8 +32,6 @@
 const base::FilePath::CharType kIconChecksumFileExt[] =
     FILE_PATH_LITERAL(".ico.md5");
 
-// Width and height of icons exported to .ico files.
-
 // Calculates checksum of an icon family using MD5.
 // The checksum is derived from all of the icons in the family.
 void GetImageCheckSum(const gfx::ImageFamily& image, base::MD5Digest* digest) {
@@ -173,12 +171,8 @@
   }
 
   // Generates file name to use with persisted ico and shortcut file.
-  base::FilePath file_name =
-      web_app::internals::GetSanitizedFileName(shortcut_info.title);
-
-  // Creates an ico file to use with shortcut.
-  base::FilePath icon_file = web_app_path.Append(file_name).AddExtension(
-      FILE_PATH_LITERAL(".ico"));
+  base::FilePath icon_file =
+      web_app::internals::GetIconFilePath(web_app_path, shortcut_info.title);
   if (!web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info.favicon)) {
     return false;
   }
@@ -214,8 +208,11 @@
 
   bool success = true;
   for (size_t i = 0; i < shortcut_paths.size(); ++i) {
-    base::FilePath shortcut_file = shortcut_paths[i].Append(file_name).
-        AddExtension(installer::kLnkExt);
+    base::FilePath shortcut_file =
+        shortcut_paths[i]
+            .Append(
+                 web_app::internals::GetSanitizedFileName(shortcut_info.title))
+            .AddExtension(installer::kLnkExt);
     if (creation_reason == web_app::SHORTCUT_CREATION_AUTOMATED) {
       // Check whether there is an existing shortcut to this app.
       std::vector<base::FilePath> shortcut_files =
@@ -336,10 +333,23 @@
   std::vector<base::FilePath> paths;
   paths.push_back(web_app_dir);
   std::vector<base::FilePath> out_filenames;
-  CreateShortcutsInPaths(web_app_dir, shortcut_info, paths,
-                         SHORTCUT_CREATION_BY_USER, &out_filenames);
-  DCHECK_EQ(out_filenames.size(), 1u);
-  return out_filenames[0];
+  base::FilePath web_app_dir_shortcut =
+      web_app_dir.Append(internals::GetSanitizedFileName(shortcut_info.title))
+          .AddExtension(installer::kLnkExt);
+  if (!PathExists(web_app_dir_shortcut)) {
+    CreateShortcutsInPaths(web_app_dir,
+                           shortcut_info,
+                           paths,
+                           SHORTCUT_CREATION_BY_USER,
+                           &out_filenames);
+    DCHECK_EQ(out_filenames.size(), 1u);
+    DCHECK_EQ(out_filenames[0].value(), web_app_dir_shortcut.value());
+  } else {
+    internals::CheckAndSaveIcon(
+        internals::GetIconFilePath(web_app_dir, shortcut_info.title),
+        shortcut_info.favicon);
+  }
+  return web_app_dir_shortcut;
 }
 
 namespace internals {
@@ -393,8 +403,7 @@
     return false;
 
   if (pin_to_taskbar) {
-    base::FilePath file_name =
-        web_app::internals::GetSanitizedFileName(shortcut_info.title);
+    base::FilePath file_name = GetSanitizedFileName(shortcut_info.title);
     // Use the web app path shortcut for pinning to avoid having unique numbers
     // in the application name.
     base::FilePath shortcut_to_pin = web_app_path.Append(file_name).
@@ -431,8 +440,7 @@
     // GetShortcutLocationsAndDeleteShortcuts will have deleted it. In that
     // case, re-pin it.
     if (was_pinned_to_taskbar) {
-      base::FilePath file_name =
-          web_app::internals::GetSanitizedFileName(shortcut_info.title);
+      base::FilePath file_name = GetSanitizedFileName(shortcut_info.title);
       // Use the web app path shortcut for pinning to avoid having unique
       // numbers in the application name.
       base::FilePath shortcut_to_pin = web_app_path.Append(file_name).
@@ -442,9 +450,8 @@
   }
 
   // Update the icon if necessary.
-  base::FilePath icon_file = web_app_path.Append(file_name).AddExtension(
-      FILE_PATH_LITERAL(".ico"));
-  web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info.favicon);
+  base::FilePath icon_file = GetIconFilePath(web_app_path, shortcut_info.title);
+  CheckAndSaveIcon(icon_file, shortcut_info.favicon);
 }
 
 void DeletePlatformShortcuts(
@@ -533,6 +540,12 @@
   return shortcut_paths;
 }
 
+base::FilePath GetIconFilePath(const base::FilePath& web_app_path,
+                               const base::string16& title) {
+  return web_app_path.Append(GetSanitizedFileName(title))
+      .AddExtension(FILE_PATH_LITERAL(".ico"));
+}
+
 }  // namespace internals
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_win.h b/chrome/browser/web_applications/web_app_win.h
index 6b2cf5b..3c0dafe 100644
--- a/chrome/browser/web_applications/web_app_win.h
+++ b/chrome/browser/web_applications/web_app_win.h
@@ -25,6 +25,9 @@
 bool CheckAndSaveIcon(const base::FilePath& icon_file,
                       const gfx::ImageFamily& image);
 
+base::FilePath GetIconFilePath(const base::FilePath& web_app_path,
+                               const base::string16& title);
+
 }  // namespace internals
 
 }  // namespace web_app
diff --git a/chrome/browser/webdata/OWNERS b/chrome/browser/webdata/OWNERS
index c2e0b66..edd7941 100644
--- a/chrome/browser/webdata/OWNERS
+++ b/chrome/browser/webdata/OWNERS
@@ -1,5 +1,3 @@
-joi@chromium.org
-
 # For sqlite stuff:
 shess@chromium.org
 
diff --git a/chrome/browser/webdata/keyword_table.cc b/chrome/browser/webdata/keyword_table.cc
index 585c629..7cc01f6 100644
--- a/chrome/browser/webdata/keyword_table.cc
+++ b/chrome/browser/webdata/keyword_table.cc
@@ -156,8 +156,7 @@
   return GetKey();
 }
 
-bool KeywordTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
-  WebDatabaseTable::Init(db, meta_table);
+bool KeywordTable::CreateTablesIfNecessary() {
   return db_->DoesTableExist("keywords") ||
       db_->Execute("CREATE TABLE keywords ("
                    "id INTEGER PRIMARY KEY,"
diff --git a/chrome/browser/webdata/keyword_table.h b/chrome/browser/webdata/keyword_table.h
index 477721b..913578f 100644
--- a/chrome/browser/webdata/keyword_table.h
+++ b/chrome/browser/webdata/keyword_table.h
@@ -90,7 +90,7 @@
   static KeywordTable* FromWebDatabase(WebDatabase* db);
 
   virtual WebDatabaseTable::TypeKey GetTypeKey() const OVERRIDE;
-  virtual bool Init(sql::Connection* db, sql::MetaTable* meta_table) OVERRIDE;
+  virtual bool CreateTablesIfNecessary() OVERRIDE;
   virtual bool IsSyncable() OVERRIDE;
   virtual bool MigrateToVersion(int version,
                                 bool* update_compatible_version) OVERRIDE;
diff --git a/chrome/browser/webdata/logins_table.cc b/chrome/browser/webdata/logins_table.cc
index cfb24ab..ff14bcb 100644
--- a/chrome/browser/webdata/logins_table.cc
+++ b/chrome/browser/webdata/logins_table.cc
@@ -29,9 +29,7 @@
   return GetKey();
 }
 
-bool LoginsTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
-  WebDatabaseTable::Init(db, meta_table);
-
+bool LoginsTable::CreateTablesIfNecessary() {
   if (db_->DoesTableExist("logins")) {
     // We don't check for success. It doesn't matter that much.
     // If we fail we'll just try again later anyway.
diff --git a/chrome/browser/webdata/logins_table.h b/chrome/browser/webdata/logins_table.h
index 2b200eb..f9628ff 100644
--- a/chrome/browser/webdata/logins_table.h
+++ b/chrome/browser/webdata/logins_table.h
@@ -29,7 +29,7 @@
   static LoginsTable* FromWebDatabase(WebDatabase* db);
 
   virtual WebDatabaseTable::TypeKey GetTypeKey() const OVERRIDE;
-  virtual bool Init(sql::Connection* db, sql::MetaTable* meta_table) OVERRIDE;
+  virtual bool CreateTablesIfNecessary() OVERRIDE;
   virtual bool IsSyncable() OVERRIDE;
   virtual bool MigrateToVersion(int version,
                                 bool* update_compatible_version) OVERRIDE;
diff --git a/chrome/browser/webdata/web_apps_table.cc b/chrome/browser/webdata/web_apps_table.cc
index 16d498b..c30562e 100644
--- a/chrome/browser/webdata/web_apps_table.cc
+++ b/chrome/browser/webdata/web_apps_table.cc
@@ -31,9 +31,7 @@
   return GetKey();
 }
 
-bool WebAppsTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
-  WebDatabaseTable::Init(db, meta_table);
-
+bool WebAppsTable::CreateTablesIfNecessary() {
   return (InitWebAppIconsTable() && InitWebAppsTable());
 }
 
diff --git a/chrome/browser/webdata/web_apps_table.h b/chrome/browser/webdata/web_apps_table.h
index 20d8ac8..82a19b2 100644
--- a/chrome/browser/webdata/web_apps_table.h
+++ b/chrome/browser/webdata/web_apps_table.h
@@ -38,7 +38,7 @@
   static WebAppsTable* FromWebDatabase(WebDatabase* database);
 
   virtual WebDatabaseTable::TypeKey GetTypeKey() const OVERRIDE;
-  virtual bool Init(sql::Connection* db, sql::MetaTable* meta_table) OVERRIDE;
+  virtual bool CreateTablesIfNecessary() OVERRIDE;
   virtual bool IsSyncable() OVERRIDE;
   virtual bool MigrateToVersion(int version,
                                 bool* update_compatible_version) OVERRIDE;
diff --git a/chrome/browser/webdata/web_data_service.cc b/chrome/browser/webdata/web_data_service.cc
index 65e391f..1d2ebec 100644
--- a/chrome/browser/webdata/web_data_service.cc
+++ b/chrome/browser/webdata/web_data_service.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/webdata/logins_table.h"
 #include "chrome/browser/webdata/web_apps_table.h"
 #include "chrome/browser/webdata/web_intents_table.h"
-#include "components/signin/core/webdata/token_service_table.h"
+#include "components/signin/core/browser/webdata/token_service_table.h"
 #include "components/webdata/common/web_database_service.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/notification_details.h"
diff --git a/chrome/browser/webdata/web_data_service_factory.cc b/chrome/browser/webdata/web_data_service_factory.cc
index ac077c5..e49c6b2 100644
--- a/chrome/browser/webdata/web_data_service_factory.cc
+++ b/chrome/browser/webdata/web_data_service_factory.cc
@@ -21,8 +21,8 @@
 #include "components/autofill/core/browser/webdata/autofill_table.h"
 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/signin/core/webdata/token_service_table.h"
-#include "components/signin/core/webdata/token_web_data.h"
+#include "components/signin/core/browser/webdata/token_service_table.h"
+#include "components/signin/core/browser/webdata/token_web_data.h"
 #include "components/webdata/common/webdata_constants.h"
 #include "content/public/browser/browser_thread.h"
 #include "grit/chromium_strings.h"
diff --git a/chrome/browser/webdata/web_intents_table.cc b/chrome/browser/webdata/web_intents_table.cc
index bb57097..0f97d08 100644
--- a/chrome/browser/webdata/web_intents_table.cc
+++ b/chrome/browser/webdata/web_intents_table.cc
@@ -41,9 +41,7 @@
   return GetKey();
 }
 
-bool WebIntentsTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
-  WebDatabaseTable::Init(db, meta_table);
-
+bool WebIntentsTable::CreateTablesIfNecessary() {
   if (!db_->DoesTableExist("web_intents")) {
     if (!db_->Execute("CREATE TABLE web_intents ("
                       " service_url LONGVARCHAR,"
@@ -105,19 +103,19 @@
 // Updates the table by way of renaming the old tables, rerunning
 // the Init method, then selecting old values into the new tables.
 bool WebIntentsTable::MigrateToVersion46AddSchemeColumn() {
+  // If the old table doesn't exist, there's nothing to migrate.
+  if (!db_->DoesTableExist("web_intents"))
+    return true;
 
-  if (!db_->Execute("ALTER TABLE web_intents RENAME TO old_web_intents")) {
-    DLOG(WARNING) << "Could not backup web_intents table.";
+  if (!db_->Execute("ALTER TABLE web_intents RENAME TO old_web_intents"))
     return false;
-  }
 
   if (!db_->Execute("ALTER TABLE web_intents_defaults"
-                    " RENAME TO old_web_intents_defaults")) {
-    DLOG(WARNING) << "Could not backup web_intents_defaults table.";
+                    " RENAME TO old_web_intents_defaults"))
     return false;
-  }
 
-  if (!Init(db_, meta_table_)) return false;
+  if (!CreateTablesIfNecessary())
+    return false;
 
   int error = db_->ExecuteAndReturnErrorCode(
       "INSERT INTO web_intents"
diff --git a/chrome/browser/webdata/web_intents_table.h b/chrome/browser/webdata/web_intents_table.h
index d8c2041..e2b7efa 100644
--- a/chrome/browser/webdata/web_intents_table.h
+++ b/chrome/browser/webdata/web_intents_table.h
@@ -59,7 +59,7 @@
 
   // WebDatabaseTable implementation.
   virtual WebDatabaseTable::TypeKey GetTypeKey() const OVERRIDE;
-  virtual bool Init(sql::Connection* db, sql::MetaTable* meta_table) OVERRIDE;
+  virtual bool CreateTablesIfNecessary() OVERRIDE;
   virtual bool IsSyncable() OVERRIDE;
   virtual bool MigrateToVersion(int version,
                                 bool* update_compatible_version) OVERRIDE;
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 602e752..97a3b4c 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -22,7 +22,6 @@
     'allocator_target': '../base/allocator/allocator.gyp:allocator',
     'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome',
     'protoc_out_dir': '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
-    'repack_locales_cmd': ['python', 'tools/build/repack_locales.py'],
     'conditions': [
       ['OS!="ios"', {
         'chromium_browser_dependencies': [
@@ -313,6 +312,9 @@
             '..',
             '<(grit_out_dir)',
           ],
+          'export_dependent_settings': [
+            'common/extensions/api/api.gyp:chrome_api',
+          ],
           'conditions': [
             ['toolkit_uses_gtk == 1', {
               'dependencies': [
@@ -913,8 +915,10 @@
             'safe_browsing_proto',
           ],
           'sources': [
-            'browser/safe_browsing/signature_util.h',
-            'browser/safe_browsing/signature_util_win.cc',
+            'browser/safe_browsing/binary_feature_extractor.h',
+            'browser/safe_browsing/binary_feature_extractor_win.cc',
+            'browser/safe_browsing/pe_image_reader_win.cc',
+            'browser/safe_browsing/pe_image_reader_win.h',
             'tools/safe_browsing/sb_sigutil.cc',
           ],
         },
diff --git a/chrome/chrome_android.gypi b/chrome/chrome_android.gypi
index 1109343..48e8cdb 100644
--- a/chrome/chrome_android.gypi
+++ b/chrome/chrome_android.gypi
@@ -39,7 +39,8 @@
             }],
           ],
         }],
-        [ 'android_use_tcmalloc==1', {
+        # TODO(dmikurube): Kill android_use_tcmalloc. http://crbug.com/345554
+        [ '(use_allocator!="none" and use_allocator!="see_use_tcmalloc") or (use_allocator=="see_use_tcmalloc" and android_use_tcmalloc==1)', {
           'dependencies': [
             '../base/allocator/allocator.gyp:allocator', ],
         }],
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 6ed95e1..f629e66 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -37,7 +37,7 @@
         '../components/components.gyp:policy_component',
         '../components/components.gyp:precache_core',
         '../components/components.gyp:rappor',
-        '../components/components.gyp:signin_core',
+        '../components/components.gyp:signin_core_browser',
         '../components/components.gyp:startup_metric_utils',
         '../components/components.gyp:sync_driver',
         '../components/components.gyp:translate_core_browser',
@@ -51,6 +51,7 @@
         '../components/components.gyp:webdata_common',
         '../content/content.gyp:content_browser',
         '../content/content.gyp:content_common',
+        '../courgette/courgette.gyp:courgette_lib',
         '../crypto/crypto.gyp:crypto',
         '../google_apis/gcm/gcm.gyp:gcm',
         '../google_apis/google_apis.gyp:google_apis',
@@ -147,6 +148,8 @@
         'browser/android/meta_tag_observer.h',
         'browser/android/new_tab_page_prefs.cc',
         'browser/android/new_tab_page_prefs.h',
+        'browser/android/new_tab_page_url_handler.cc',
+        'browser/android/new_tab_page_url_handler.h',
         'browser/android/google_location_settings_helper.h',
         'browser/android/intent_helper.cc',
         'browser/android/intent_helper.h',
@@ -396,8 +399,6 @@
         'browser/browsing_data/browsing_data_cookie_helper.h',
         'browser/browsing_data/cookies_tree_model.cc',
         'browser/browsing_data/cookies_tree_model.h',
-        'browser/feedback/feedback_common.cc',
-        'browser/feedback/feedback_common.h',
         'browser/feedback/feedback_data.cc',
         'browser/feedback/feedback_data.h',
         'browser/feedback/feedback_profile_observer.cc',
@@ -494,8 +495,6 @@
         'browser/component_updater/component_patcher.h',
         'browser/component_updater/component_patcher_operation.cc',
         'browser/component_updater/component_patcher_operation.h',
-        'browser/component_updater/component_patcher_win.cc',
-        'browser/component_updater/component_patcher_win.h',
         'browser/component_updater/component_updater_configurator.cc',
         'browser/component_updater/component_updater_configurator.h',
         'browser/component_updater/component_unpacker.cc',
@@ -1117,8 +1116,6 @@
         'browser/managed_mode/managed_user_shared_settings_service_factory.h',
         'browser/managed_mode/managed_user_shared_settings_update.cc',
         'browser/managed_mode/managed_user_shared_settings_update.h',
-        'browser/managed_mode/managed_user_signin_manager_wrapper.cc',
-        'browser/managed_mode/managed_user_signin_manager_wrapper.h',
         'browser/managed_mode/managed_user_sync_service.cc',
         'browser/managed_mode/managed_user_sync_service.h',
         'browser/managed_mode/managed_user_sync_service_factory.cc',
@@ -1163,10 +1160,12 @@
         'browser/media/midi_permission_infobar_delegate.h',
         'browser/media/native_desktop_media_list.cc',
         'browser/media/native_desktop_media_list.h',
-        'browser/media/webrtc_log_upload_list.cc',
-        'browser/media/webrtc_log_upload_list.h',
+        'browser/media/webrtc_log_list.cc',
+        'browser/media/webrtc_log_list.h',
         'browser/media/webrtc_log_uploader.cc',
         'browser/media/webrtc_log_uploader.h',
+        'browser/media/webrtc_log_util.cc',
+        'browser/media/webrtc_log_util.h',
         'browser/media/webrtc_logging_handler_host.cc',
         'browser/media/webrtc_logging_handler_host.h',
         'browser/media_galleries/fileapi/av_scanning_file_validator.cc',
@@ -1262,12 +1261,17 @@
         'browser/memory_details_win.cc',
         'browser/metrics/chrome_browser_main_extra_parts_metrics.cc',
         'browser/metrics/chrome_browser_main_extra_parts_metrics.h',
+        'browser/metrics/cloned_install_detector.cc',
+        'browser/metrics/cloned_install_detector.h',
         'browser/metrics/compression_utils.cc',
         'browser/metrics/compression_utils.h',
         'browser/metrics/extension_metrics.cc',
         'browser/metrics/extension_metrics.h',
         'browser/metrics/field_trial_synchronizer.cc',
         'browser/metrics/field_trial_synchronizer.h',
+        'browser/metrics/machine_id_provider.h',
+        'browser/metrics/machine_id_provider_stub.cc',
+        'browser/metrics/machine_id_provider_win.cc',
         'browser/metrics/metric_event_duration_details.h',
         'browser/metrics/metrics_log.cc',
         'browser/metrics/metrics_log.h',
@@ -1464,6 +1468,8 @@
         'browser/notifications/sync_notifier/chrome_notifier_service.h',
         'browser/notifications/sync_notifier/chrome_notifier_service_factory.cc',
         'browser/notifications/sync_notifier/chrome_notifier_service_factory.h',
+        'browser/notifications/sync_notifier/image_holder.cc',
+        'browser/notifications/sync_notifier/image_holder.h',
         'browser/notifications/sync_notifier/synced_notification.cc',
         'browser/notifications/sync_notifier/synced_notification.h',
         'browser/notifications/sync_notifier/synced_notification_app_info.cc',
@@ -1657,6 +1663,8 @@
         'browser/prefs/pref_service_syncable_factory.cc',
         'browser/prefs/pref_service_syncable_factory.h',
         'browser/prefs/pref_service_syncable_observer.h',
+        'browser/prefs/profile_pref_store_manager.cc',
+        'browser/prefs/profile_pref_store_manager.h',
         'browser/prefs/proxy_config_dictionary.cc',
         'browser/prefs/proxy_config_dictionary.h',
         'browser/prefs/proxy_prefs.cc',
@@ -1672,6 +1680,8 @@
         'browser/prefs/tracked/pref_hash_calculator_helper_win.cc',
         'browser/prefs/tracked/pref_service_hash_store_contents.cc',
         'browser/prefs/tracked/pref_service_hash_store_contents.h',
+        'browser/prefs/tracked/segregated_pref_store.cc',
+        'browser/prefs/tracked/segregated_pref_store.h',
         'browser/prefs/tracked/tracked_atomic_preference.cc',
         'browser/prefs/tracked/tracked_atomic_preference.h',
         'browser/prefs/tracked/tracked_preference.h',
@@ -1942,6 +1952,9 @@
         'browser/resources_util.h',
         'browser/rlz/rlz.cc',
         'browser/rlz/rlz.h',
+        'browser/safe_browsing/binary_feature_extractor_posix.cc',
+        'browser/safe_browsing/binary_feature_extractor_win.cc',
+        'browser/safe_browsing/binary_feature_extractor.h',
         'browser/safe_browsing/browser_feature_extractor.cc',
         'browser/safe_browsing/browser_feature_extractor.h',
         'browser/safe_browsing/browser_features.cc',
@@ -1966,6 +1979,8 @@
         'browser/safe_browsing/malware_details_cache.h',
         'browser/safe_browsing/malware_details_history.cc',
         'browser/safe_browsing/malware_details_history.h',
+        'browser/safe_browsing/pe_image_reader_win.cc',
+        'browser/safe_browsing/pe_image_reader_win.h',
         'browser/safe_browsing/ping_manager.cc',
         'browser/safe_browsing/ping_manager.h',
         'browser/safe_browsing/prefix_set.cc',
@@ -1992,9 +2007,6 @@
         'browser/safe_browsing/safe_browsing_util.h',
         'browser/safe_browsing/sandboxed_zip_analyzer.cc',
         'browser/safe_browsing/sandboxed_zip_analyzer.h',
-        'browser/safe_browsing/signature_util_posix.cc',
-        'browser/safe_browsing/signature_util_win.cc',
-        'browser/safe_browsing/signature_util.h',
         'browser/safe_browsing/two_phase_uploader.cc',
         'browser/safe_browsing/two_phase_uploader.h',
         'browser/safe_browsing/ui_manager.cc',
@@ -2148,12 +2160,8 @@
         'browser/signin/signin_global_error.h',
         'browser/signin/signin_global_error_factory.cc',
         'browser/signin/signin_global_error_factory.h',
-        'browser/signin/signin_internals_util.cc',
-        'browser/signin/signin_internals_util.h',
         'browser/signin/signin_manager.cc',
         'browser/signin/signin_manager.h',
-        'browser/signin/signin_manager_base.cc',
-        'browser/signin/signin_manager_base.h',
         'browser/signin/signin_manager_factory.cc',
         'browser/signin/signin_manager_factory.h',
         'browser/signin/signin_names_io_thread.cc',
@@ -2346,6 +2354,8 @@
         'browser/sync/glue/ui_data_type_controller.h',
         'browser/sync/glue/ui_model_worker.cc',
         'browser/sync/glue/ui_model_worker.h',
+        'browser/sync/managed_user_signin_manager_wrapper.cc',
+        'browser/sync/managed_user_signin_manager_wrapper.h',
         'browser/sync/profile_sync_components_factory.h',
         'browser/sync/profile_sync_components_factory_impl.cc',
         'browser/sync/profile_sync_components_factory_impl.h',
@@ -2360,6 +2370,8 @@
         'browser/sync/profile_sync_service_model_type_selection_android.h',
         'browser/sync/profile_sync_service_observer.cc',
         'browser/sync/profile_sync_service_observer.h',
+        'browser/sync/protocol_event_observer.cc',
+        'browser/sync/protocol_event_observer.h',
         'browser/sync/sessions2/notification_service_sessions_router.cc',
         'browser/sync/sessions2/notification_service_sessions_router.h',
         'browser/sync/sessions2/session_data_type_controller2.cc',
@@ -2374,8 +2386,16 @@
         'browser/sync/sessions2/tab_node_pool2.h',
         'browser/sync/startup_controller.cc',
         'browser/sync/startup_controller.h',
+        'browser/sync/sync_error_controller.cc',
+        'browser/sync/sync_error_controller.h',
+        'browser/sync/sync_error_notifier_ash.cc',
+        'browser/sync/sync_error_notifier_ash.h',
+        'browser/sync/sync_error_notifier_factory_ash.cc',
+        'browser/sync/sync_error_notifier_factory_ash.h',
         'browser/sync/sync_global_error.cc',
         'browser/sync/sync_global_error.h',
+        'browser/sync/sync_global_error_factory.cc',
+        'browser/sync/sync_global_error_factory.h',
         'browser/sync/sync_policy_handler.cc',
         'browser/sync/sync_policy_handler.h',
         'browser/sync/sync_startup_tracker.cc',
@@ -2409,6 +2429,7 @@
         'browser/sync_file_system/drive_backend/remote_to_local_syncer.h',
         'browser/sync_file_system/drive_backend/sync_engine.cc',
         'browser/sync_file_system/drive_backend/sync_engine.h',
+        'browser/sync_file_system/drive_backend/sync_engine_context.cc',
         'browser/sync_file_system/drive_backend/sync_engine_context.h',
         'browser/sync_file_system/drive_backend/sync_engine_initializer.cc',
         'browser/sync_file_system/drive_backend/sync_engine_initializer.h',
@@ -2502,20 +2523,20 @@
         'browser/tab_contents/retargeting_details.h',
         'browser/tab_contents/tab_util.cc',
         'browser/tab_contents/tab_util.h',
-        'browser/task_manager/background_resource_provider.cc',
-        'browser/task_manager/background_resource_provider.h',
+        'browser/task_manager/background_information.cc',
+        'browser/task_manager/background_information.h',
         'browser/task_manager/browser_process_resource_provider.cc',
         'browser/task_manager/browser_process_resource_provider.h',
         'browser/task_manager/child_process_resource_provider.cc',
         'browser/task_manager/child_process_resource_provider.h',
         'browser/task_manager/extension_process_resource_provider.cc',
         'browser/task_manager/extension_process_resource_provider.h',
-        'browser/task_manager/guest_resource_provider.cc',
-        'browser/task_manager/guest_resource_provider.h',
+        'browser/task_manager/guest_information.cc',
+        'browser/task_manager/guest_information.h',
         'browser/task_manager/notification_resource_provider.cc',
         'browser/task_manager/notification_resource_provider.h',
-        'browser/task_manager/panel_resource_provider.cc',
-        'browser/task_manager/panel_resource_provider.h',
+        'browser/task_manager/panel_information.cc',
+        'browser/task_manager/panel_information.h',
         'browser/task_manager/renderer_resource.cc',
         'browser/task_manager/renderer_resource.h',
         'browser/task_manager/resource_provider.cc',
@@ -2526,6 +2547,10 @@
         'browser/task_manager/task_manager.h',
         'browser/task_manager/task_manager_util.cc',
         'browser/task_manager/task_manager_util.h',
+        'browser/task_manager/web_contents_information.cc',
+        'browser/task_manager/web_contents_information.h',
+        'browser/task_manager/web_contents_resource_provider.cc',
+        'browser/task_manager/web_contents_resource_provider.h',
         'browser/task_manager/worker_resource_provider.cc',
         'browser/task_manager/worker_resource_provider.h',
         'browser/task_profiler/auto_tracking.cc',
@@ -3073,6 +3098,10 @@
             'browser/speech/tts_linux.cc',
             'browser/sxs_linux.cc',
             'browser/sxs_linux.h',
+            'browser/sync/sync_global_error.cc',
+            'browser/sync/sync_global_error.h',
+            'browser/sync/sync_global_error_factory.cc',
+            'browser/sync/sync_global_error_factory.h',
             'browser/task_manager/notification_resource_provider.cc',
             'browser/task_manager/notification_resource_provider.h',
             'browser/themes/theme_service_aurax11.cc',
@@ -3480,6 +3509,7 @@
           'sources!': [
             'browser/first_run/first_run_dialog.h',
             'browser/lifetime/application_lifetime_stub.cc',
+            'browser/metrics/machine_id_provider_stub.cc',
             'browser/prefs/tracked/pref_hash_calculator_helper_stub.cc',
             'browser/profiles/profile_shortcut_manager_stub.cc',
           ],
@@ -3575,6 +3605,8 @@
             'browser/media/webrtc_log_upload_list.h',
             'browser/media/webrtc_log_uploader.cc',
             'browser/media/webrtc_log_uploader.h',
+            'browser/media/webrtc_log_util.cc',
+            'browser/media/webrtc_log_util.h',
             'browser/media/webrtc_logging_handler_host.cc',
             'browser/media/webrtc_logging_handler_host.h',
           ]
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index b69ca80..d70e02d 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -41,11 +41,12 @@
         'installer_util',
         'safe_browsing_proto',
         'safe_browsing_report_proto',
-        '../third_party/re2/re2.gyp:re2',
         '../breakpad/breakpad.gyp:breakpad_client',
         '../build/linux/system.gyp:dbus',
         '../chromeos/chromeos.gyp:chromeos',
         '../chromeos/chromeos.gyp:chromeos_memory',
+        # browser_chromeos #includes signed_secret.pb.h directly.
+        '../chromeos/chromeos.gyp:cryptohome_signkey_proto',
         # browser_chromeos #includes power_supply_properties.pb.h directly.
         '../chromeos/chromeos.gyp:power_manager_proto',
         '../chromeos/ime/input_method.gyp:gencode',
@@ -82,6 +83,7 @@
         '../third_party/npapi/npapi.gyp:npapi',
         '../third_party/protobuf/protobuf.gyp:protobuf_lite',
         '../third_party/protobuf/protobuf.gyp:protoc#host',
+        '../third_party/re2/re2.gyp:re2',
         '../third_party/zlib/zlib.gyp:zlib',
         '../ui/base/strings/ui_strings.gyp:ui_strings',
         '../ui/base/ui_base.gyp:ui_base',
@@ -108,6 +110,7 @@
         ],
       },
       'export_dependent_settings': [
+        'common/extensions/api/api.gyp:chrome_api',
         '../sync/sync.gyp:sync',
       ],
       'include_dirs': [
@@ -168,6 +171,8 @@
         'browser/chromeos/boot_times_loader.h',
         'browser/chromeos/camera_detector.cc',
         'browser/chromeos/camera_detector.h',
+        'browser/chromeos/camera_presence_notifier.cc',
+        'browser/chromeos/camera_presence_notifier.h',
         'browser/chromeos/charger_replace/charger_link_dialog.cc',
         'browser/chromeos/charger_replace/charger_link_dialog.h',
         'browser/chromeos/charger_replace/charger_replacement_dialog.cc',
@@ -365,6 +370,13 @@
         'browser/chromeos/file_manager/volume_manager_observer.h',
         'browser/chromeos/file_manager/zip_file_creator.cc',
         'browser/chromeos/file_manager/zip_file_creator.h',
+        'browser/chromeos/file_system_provider/observer.h',
+        'browser/chromeos/file_system_provider/provided_file_system.cc',
+        'browser/chromeos/file_system_provider/provided_file_system.h',
+        'browser/chromeos/file_system_provider/service.cc',
+        'browser/chromeos/file_system_provider/service.h',
+        'browser/chromeos/file_system_provider/service_factory.cc',
+        'browser/chromeos/file_system_provider/service_factory.h',
         'browser/chromeos/fileapi/file_access_permissions.cc',
         'browser/chromeos/fileapi/file_access_permissions.h',
         'browser/chromeos/fileapi/file_system_backend.cc',
@@ -462,6 +474,10 @@
         'browser/chromeos/login/default_user_images.h',
         'browser/chromeos/login/demo_mode/demo_app_launcher.cc',
         'browser/chromeos/login/demo_mode/demo_app_launcher.h',
+        'browser/chromeos/login/enrollment/auto_enrollment_check_step.cc',
+        'browser/chromeos/login/enrollment/auto_enrollment_check_step.h',
+        'browser/chromeos/login/enrollment/auto_enrollment_controller.cc',
+        'browser/chromeos/login/enrollment/auto_enrollment_controller.h',
         'browser/chromeos/login/enrollment/enrollment_screen.cc',
         'browser/chromeos/login/enrollment/enrollment_screen.h',
         'browser/chromeos/login/enrollment/enrollment_screen_actor.h',
@@ -490,6 +506,8 @@
         'browser/chromeos/login/login_display_host.h',
         'browser/chromeos/login/login_display_host_impl.cc',
         'browser/chromeos/login/login_display_host_impl.h',
+        'browser/chromeos/login/login_location_monitor.cc',
+        'browser/chromeos/login/login_location_monitor.h',
         'browser/chromeos/login/login_performer.cc',
         'browser/chromeos/login/login_performer.h',
         'browser/chromeos/login/login_status_consumer.cc',
@@ -654,6 +672,8 @@
         'browser/chromeos/mobile_config.h',
         'browser/chromeos/net/cert_verify_proc_chromeos.cc',
         'browser/chromeos/net/cert_verify_proc_chromeos.h',
+        'browser/chromeos/net/delay_network_call.cc',
+        'browser/chromeos/net/delay_network_call.h',
         'browser/chromeos/net/network_portal_detector.cc',
         'browser/chromeos/net/network_portal_detector.h',
         'browser/chromeos/net/network_portal_detector_impl.cc',
@@ -730,8 +750,6 @@
         'browser/chromeos/policy/enterprise_install_attributes.h',
         'browser/chromeos/policy/login_profile_policy_provider.cc',
         'browser/chromeos/policy/login_profile_policy_provider.h',
-        'browser/chromeos/policy/login_screen_power_management_policy.cc',
-        'browser/chromeos/policy/login_screen_power_management_policy.h',
         'browser/chromeos/policy/network_configuration_updater.cc',
         'browser/chromeos/policy/network_configuration_updater.h',
         'browser/chromeos/policy/policy_cert_service.cc',
@@ -807,6 +825,7 @@
         'browser/chromeos/proxy_config_service_impl.h',
         'browser/chromeos/proxy_cros_settings_parser.cc',
         'browser/chromeos/proxy_cros_settings_parser.h',
+        'browser/chromeos/reset/metrics.h',
         'browser/chromeos/session_length_limiter.cc',
         'browser/chromeos/session_length_limiter.h',
         'browser/chromeos/settings/cros_settings.cc',
@@ -864,6 +883,10 @@
         'browser/chromeos/system_logs/network_event_log_source.h',
         'browser/chromeos/system_logs/touch_log_source.cc',
         'browser/chromeos/system_logs/touch_log_source.h',
+        'browser/chromeos/timezone/timezone_provider.h',
+        'browser/chromeos/timezone/timezone_provider.cc',
+        'browser/chromeos/timezone/timezone_request.cc',
+        'browser/chromeos/timezone/timezone_request.h',
         'browser/chromeos/ui/echo_dialog_listener.h',
         'browser/chromeos/ui/echo_dialog_view.cc',
         'browser/chromeos/ui/echo_dialog_view.h',
@@ -985,7 +1008,6 @@
           'dependencies': [
             '../build/linux/system.gyp:dbus',
             '../build/linux/system.gyp:fontconfig',
-            '../build/linux/system.gyp:x11',
             '../ui/views/views.gyp:views',
           ],
           'include_dirs': [
@@ -997,6 +1019,11 @@
             ['include', '^browser/chromeos/status/memory_menu_button.h'],
           ],
         }],
+        ['use_aura==1 and use_x11==1', {
+          'dependencies': [
+            '../build/linux/system.gyp:x11',
+          ],
+        }],
         ['enable_printing != 0', {
           'dependencies': [
             '../printing/printing.gyp:printing',
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index a0b5081..6b36a4c 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -39,6 +39,7 @@
         '../device/bluetooth/bluetooth.gyp:device_bluetooth',
         '../device/hid/hid.gyp:device_hid',
         '../device/serial/serial.gyp:device_serial',
+        '../extensions/common/api/api.gyp:extensions_api',
         '../extensions/extensions.gyp:extensions_browser',
         '../net/net.gyp:net',
         '../skia/skia.gyp:skia',
@@ -65,6 +66,7 @@
         '<(INTERMEDIATE_DIR)',
       ],
       'export_dependent_settings': [
+        'common/extensions/api/api.gyp:chrome_api',
         '../content/content.gyp:content_browser',
       ],
       'sources': [
@@ -254,10 +256,6 @@
         'browser/extensions/api/dial/dial_registry.h',
         'browser/extensions/api/dial/dial_service.cc',
         'browser/extensions/api/dial/dial_service.h',
-        'browser/extensions/api/dns/dns_api.cc',
-        'browser/extensions/api/dns/dns_api.h',
-        'browser/extensions/api/dns/host_resolver_wrapper.cc',
-        'browser/extensions/api/dns/host_resolver_wrapper.h',
         'browser/extensions/api/downloads/downloads_api.cc',
         'browser/extensions/api/downloads/downloads_api.h',
         'browser/extensions/api/extension_action/extension_action_api.cc',
@@ -336,6 +334,7 @@
         'browser/extensions/api/image_writer_private/image_writer_private_api.h',
         'browser/extensions/api/image_writer_private/removable_storage_provider.h',
         'browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc',
+        'browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc',
         'browser/extensions/api/image_writer_private/removable_storage_provider_mac.cc',
         'browser/extensions/api/image_writer_private/removable_storage_provider_win.cc',
         'browser/extensions/api/image_writer_private/write_from_file_operation.cc',
@@ -594,6 +593,8 @@
         'browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h',
         'browser/extensions/api/webstore_private/webstore_private_api.cc',
         'browser/extensions/api/webstore_private/webstore_private_api.h',
+        'browser/extensions/api/webstore/webstore_api.cc',
+        'browser/extensions/api/webstore/webstore_api.h',
         'browser/extensions/api/webview/webview_api.cc',
         'browser/extensions/api/webview/webview_api.h',
         'browser/extensions/app_icon_loader.h',
@@ -609,6 +610,8 @@
         'browser/extensions/blacklist_state_fetcher.h',
         'browser/extensions/blob_reader.cc',
         'browser/extensions/blob_reader.h',
+        'browser/extensions/bookmark_app_helper.cc',
+        'browser/extensions/bookmark_app_helper.h',
         'browser/extensions/browser_action_test_util.h',
         'browser/extensions/browser_context_keyed_service_factories.cc',
         'browser/extensions/browser_context_keyed_service_factories.h',
@@ -651,8 +654,6 @@
         'browser/extensions/devtools_util.cc',
         'browser/extensions/error_console/error_console.cc',
         'browser/extensions/error_console/error_console.h',
-        'browser/extensions/event_names.cc',
-        'browser/extensions/event_names.h',
         'browser/extensions/event_router_forwarder.cc',
         'browser/extensions/event_router_forwarder.h',
         'browser/extensions/extension_action.cc',
@@ -822,6 +823,8 @@
         'browser/extensions/sandboxed_unpacker.h',
         'browser/extensions/script_executor.cc',
         'browser/extensions/script_executor.h',
+        'browser/extensions/settings_api_bubble_controller.cc',
+        'browser/extensions/settings_api_bubble_controller.h',
         'browser/extensions/standard_management_policy_provider.cc',
         'browser/extensions/standard_management_policy_provider.h',
         'browser/extensions/startup_helper.cc',
@@ -890,6 +893,7 @@
             'browser/extensions/api/audio/audio_service.cc',
             'browser/extensions/api/feedback_private/feedback_service_nonchromeos.cc',
             'browser/extensions/api/image_writer_private/operation_nonchromeos.cc',
+            'browser/extensions/api/image_writer_private/removable_storage_provider_linux.cc',
             'browser/extensions/api/system_display/display_info_provider_aura.cc',
             'browser/extensions/default_apps.cc',
             'browser/extensions/default_apps.h',
diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi
index 2cd7b4b..efc84fe 100644
--- a/chrome/chrome_browser_ui.gypi
+++ b/chrome/chrome_browser_ui.gypi
@@ -85,10 +85,8 @@
         'browser/ui/android/autofill/autofill_popup_view_android.h',
         'browser/ui/android/content_settings/popup_blocked_infobar_delegate.cc',
         'browser/ui/android/content_settings/popup_blocked_infobar_delegate.h',
-        'browser/ui/android/infobars/auto_login_infobar_delegate.cc',
-        'browser/ui/android/infobars/auto_login_infobar_delegate.h',
-        'browser/ui/android/infobars/auto_login_prompter.cc',
-        'browser/ui/android/infobars/auto_login_prompter.h',
+        'browser/ui/android/infobars/auto_login_infobar_delegate_android.cc',
+        'browser/ui/android/infobars/auto_login_infobar_delegate_android.h',
         'browser/ui/android/infobars/confirm_infobar.cc',
         'browser/ui/android/infobars/confirm_infobar.h',
         'browser/ui/android/infobars/infobar_android.cc',
@@ -413,6 +411,10 @@
         'browser/ui/autofill/popup_controller_common.h',
         'browser/ui/autofill/tab_autofill_manager_delegate.cc',
         'browser/ui/autofill/tab_autofill_manager_delegate.h',
+        'browser/ui/auto_login_infobar_delegate.cc',
+        'browser/ui/auto_login_infobar_delegate.h',
+        'browser/ui/auto_login_prompter.cc',
+        'browser/ui/auto_login_prompter.h',
         'browser/ui/blocked_content/blocked_window_params.cc',
         'browser/ui/blocked_content/blocked_window_params.h',
         'browser/ui/blocked_content/popup_blocker_tab_helper.cc',
@@ -1569,6 +1571,8 @@
         'browser/ui/search_engines/template_url_fetcher_ui_callbacks.h',
         'browser/ui/search_engines/template_url_table_model.cc',
         'browser/ui/search_engines/template_url_table_model.h',
+        'browser/ui/settings_window_manager.cc',
+        'browser/ui/settings_window_manager.h',
         'browser/ui/profile_reset_bubble.h',
         'browser/ui/profile_reset_bubble_stub.cc',
         'browser/ui/simple_message_box.h',
@@ -1748,6 +1752,8 @@
         'browser/ui/views/autofill/new_credit_card_bubble_views.h',
         'browser/ui/views/autofill/decorated_textfield.cc',
         'browser/ui/views/autofill/decorated_textfield.h',
+        'browser/ui/views/autofill/expanding_textfield.cc',
+        'browser/ui/views/autofill/expanding_textfield.h',
         'browser/ui/views/autofill/info_bubble.cc',
         'browser/ui/views/autofill/info_bubble.h',
         'browser/ui/views/autofill/password_generation_popup_view_views.cc',
@@ -2107,6 +2113,8 @@
         'browser/ui/views/select_file_dialog_extension.h',
         'browser/ui/views/select_file_dialog_extension_factory.cc',
         'browser/ui/views/select_file_dialog_extension_factory.h',
+        'browser/ui/views/settings_api_bubble_helper_views.cc',
+        'browser/ui/views/settings_api_bubble_helper_views.h',
         'browser/ui/views/signed_certificate_timestamps_views.cc',
         'browser/ui/views/signed_certificate_timestamps_views.h',
         'browser/ui/views/signed_certificate_timestamp_info_view.cc',
@@ -2164,6 +2172,7 @@
         'browser/ui/views/toolbar/browser_action_view.h',
         'browser/ui/views/toolbar/browser_actions_container.cc',
         'browser/ui/views/toolbar/browser_actions_container.h',
+        'browser/ui/views/toolbar/browser_actions_container_observer.h',
         'browser/ui/views/toolbar/home_button.cc',
         'browser/ui/views/toolbar/home_button.h',
         'browser/ui/views/toolbar/toolbar_origin_chip_view.cc',
@@ -2848,6 +2857,8 @@
             'browser/ui/ash/chrome_shell_delegate_views.cc',
             'browser/ui/ash/multi_user/multi_user_context_menu.cc',
             'browser/ui/ash/session_state_delegate_views.cc',
+            'browser/ui/aura/active_desktop_monitor.cc',
+            'browser/ui/aura/active_desktop_monitor.h',
             'browser/ui/startup/default_browser_prompt.cc',
             'browser/ui/startup/default_browser_prompt.h',
             'browser/ui/external_protocol_dialog_delegate.cc',
@@ -2871,6 +2882,7 @@
             'browser/ui/views/notifications/balloon_view_views.cc',
             'browser/ui/views/notifications/balloon_view_views.h',
             'browser/ui/views/screen_capture_notification_ui_views.cc',
+            'browser/ui/views/tabs/window_finder_x11.cc',
             'browser/ui/webui/help/version_updater_basic.cc',
             'browser/ui/webui/help/version_updater_basic.h',
             'browser/ui/webui/signin/inline_login_handler_impl.cc',
diff --git a/chrome/chrome_common.gypi b/chrome/chrome_common.gypi
index 8d8c7f1..a8e1d43 100644
--- a/chrome/chrome_common.gypi
+++ b/chrome/chrome_common.gypi
@@ -141,7 +141,6 @@
         'common/extensions/api/managed_mode_private/managed_mode_handler.h',
         'common/extensions/api/media_galleries_private/media_galleries_handler.h',
         'common/extensions/api/media_galleries_private/media_galleries_handler.cc',
-        'common/extensions/api/messaging/message.h',
         'common/extensions/api/omnibox/omnibox_handler.cc',
         'common/extensions/api/omnibox/omnibox_handler.h',
         'common/extensions/api/plugins/plugins_handler.cc',
@@ -162,6 +161,8 @@
         'common/extensions/api/system_indicator/system_indicator_handler.h',
         'common/extensions/api/url_handlers/url_handlers_parser.cc',
         'common/extensions/api/url_handlers/url_handlers_parser.h',
+        'common/extensions/api/webstore/webstore_api_constants.cc',
+        'common/extensions/api/webstore/webstore_api_constants.h',
         'common/extensions/chrome_extension_messages.h',
         'common/extensions/chrome_extensions_client.cc',
         'common/extensions/chrome_extensions_client.h',
@@ -226,25 +227,6 @@
         'common/extensions/permissions/chrome_api_permissions.h',
         'common/extensions/permissions/chrome_permission_message_provider.cc',
         'common/extensions/permissions/chrome_permission_message_provider.h',
-        'common/extensions/permissions/media_galleries_permission.cc',
-        'common/extensions/permissions/media_galleries_permission.h',
-        'common/extensions/permissions/media_galleries_permission_data.cc',
-        'common/extensions/permissions/media_galleries_permission_data.h',
-        'common/extensions/permissions/permission_message_util.cc',
-        'common/extensions/permissions/permission_message_util.h',
-        'common/extensions/permissions/set_disjunction_permission.h',
-        'common/extensions/permissions/settings_override_permission.cc',
-        'common/extensions/permissions/settings_override_permission.h',
-        'common/extensions/permissions/socket_permission.cc',
-        'common/extensions/permissions/socket_permission.h',
-        'common/extensions/permissions/socket_permission_data.cc',
-        'common/extensions/permissions/socket_permission_data.h',
-        'common/extensions/permissions/socket_permission_entry.cc',
-        'common/extensions/permissions/socket_permission_entry.h',
-        'common/extensions/permissions/usb_device_permission.cc',
-        'common/extensions/permissions/usb_device_permission.h',
-        'common/extensions/permissions/usb_device_permission_data.cc',
-        'common/extensions/permissions/usb_device_permission_data.h',
         'common/extensions/sync_helper.cc',
         'common/extensions/sync_helper.h',
         'common/extensions/update_manifest.cc',
@@ -421,13 +403,18 @@
             '<(DEPTH)/components/components.gyp:autofill_core_common',
             '<(DEPTH)/components/components.gyp:autofill_content_common',
             '<(DEPTH)/components/components.gyp:password_manager_core_common',
+            '<(DEPTH)/components/components.gyp:signin_core_common',
             '<(DEPTH)/components/nacl.gyp:nacl_common',
             '<(DEPTH)/components/components.gyp:visitedlink_common',
+            '<(DEPTH)/extensions/common/api/api.gyp:extensions_api',
             '<(DEPTH)/extensions/extensions.gyp:extensions_common',
             '<(DEPTH)/ipc/ipc.gyp:ipc',
             '<(DEPTH)/third_party/adobe/flash/flash_player.gyp:flapper_version_h',
             '<(DEPTH)/third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
           ],
+          'export_dependent_settings': [
+            '<(DEPTH)/chrome/common/extensions/api/api.gyp:chrome_api',
+          ],
         }, {  # OS == ios
           'sources/': [
             ['exclude', '^common/child_process_'],
diff --git a/chrome/chrome_dll.gypi b/chrome/chrome_dll.gypi
index 63887c6..e99c437 100644
--- a/chrome/chrome_dll.gypi
+++ b/chrome/chrome_dll.gypi
@@ -104,6 +104,7 @@
               'dependencies': [
                 # On Windows, link the dependencies (libraries) that make
                 # up actual Chromium functionality into this .dll.
+                'chrome_dll_pdb_workaround',
                 'chrome_version_resources',
                 '../chrome/chrome_resources.gyp:chrome_unscaled_resources',
                 '../crypto/crypto.gyp:crypto',
@@ -215,11 +216,6 @@
                     '../printing/printing.gyp:printing',
                   ],
                 }],
-                ['component!="shared_library"', {  # http://crbug.com/339215
-                  'dependencies': [
-                    'chrome_dll_pdb_workaround',
-                   ],
-                }],
                 ['chrome_pgo_phase==1', {
                   'msvs_settings': {
                     'VCLinkerTool': {
diff --git a/chrome/chrome_dll_bundle.gypi b/chrome/chrome_dll_bundle.gypi
index a4b6d6c..33aeb42 100644
--- a/chrome/chrome_dll_bundle.gypi
+++ b/chrome/chrome_dll_bundle.gypi
@@ -108,7 +108,6 @@
       }],
     ],
     'libpeer_target_type%': 'static_library',
-    'repack_path': '../tools/grit/grit/format/repack.py',
   },
   'postbuilds': [
     {
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi
index 6f92d5a..293e5fb 100644
--- a/chrome/chrome_renderer.gypi
+++ b/chrome/chrome_renderer.gypi
@@ -182,6 +182,8 @@
         'renderer/media/chrome_webrtc_log_message_delegate.h',
         'renderer/media/webrtc_logging_message_filter.cc',
         'renderer/media/webrtc_logging_message_filter.h',
+	'renderer/net/error_cache_load.cc',
+	'renderer/net/error_cache_load.h',
         'renderer/net/net_error_helper.cc',
         'renderer/net/net_error_helper.h',
         'renderer/net/net_error_helper_core.cc',
diff --git a/chrome/chrome_repack_chrome_100_percent.gypi b/chrome/chrome_repack_chrome_100_percent.gypi
index c07e38a..b644df6 100644
--- a/chrome/chrome_repack_chrome_100_percent.gypi
+++ b/chrome/chrome_repack_chrome_100_percent.gypi
@@ -10,6 +10,7 @@
       '<(grit_out_dir)/renderer_resources_100_percent.pak',
       '<(grit_out_dir)/theme_resources_100_percent.pak',
     ],
+    'pak_output': '<(SHARED_INTERMEDIATE_DIR)/repack/chrome_100_percent.pak',
     'conditions': [
       ['OS != "ios"', {
         'pak_inputs': [
@@ -23,12 +24,5 @@
       }],
     ],
   },
-  'inputs': [
-    '<(repack_path)',
-    '<@(pak_inputs)',
-  ],
-  'outputs': [
-    '<(SHARED_INTERMEDIATE_DIR)/repack/chrome_100_percent.pak',
-  ],
-  'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'],
+  'includes': [ '../build/repack_action.gypi' ],
 }
diff --git a/chrome/chrome_repack_chrome_200_percent.gypi b/chrome/chrome_repack_chrome_200_percent.gypi
index c9d7e58..ccd1de2 100644
--- a/chrome/chrome_repack_chrome_200_percent.gypi
+++ b/chrome/chrome_repack_chrome_200_percent.gypi
@@ -10,6 +10,7 @@
       '<(grit_out_dir)/renderer_resources_200_percent.pak',
       '<(grit_out_dir)/theme_resources_200_percent.pak',
     ],
+    'pak_output': '<(SHARED_INTERMEDIATE_DIR)/repack/chrome_200_percent.pak',
     'conditions': [
       ['OS != "ios"', {
         'pak_inputs': [
@@ -23,12 +24,5 @@
       }],
     ],
   },
-  'inputs': [
-    '<(repack_path)',
-    '<@(pak_inputs)',
-  ],
-  'outputs': [
-    '<(SHARED_INTERMEDIATE_DIR)/repack/chrome_200_percent.pak',
-  ],
-  'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'],
+  'includes': [ '../build/repack_action.gypi' ],
 }
diff --git a/chrome/chrome_repack_locales.gypi b/chrome/chrome_repack_locales.gypi
index c80c125..0e24ee2 100644
--- a/chrome/chrome_repack_locales.gypi
+++ b/chrome/chrome_repack_locales.gypi
@@ -1,9 +1,12 @@
 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
+
+# To use this the following variables need to be defined:
+#   pak_locales: string: the list of all the locales that need repacking
 {
-  'action_name': 'repack_locales',
   'variables': {
+    'repack_locales_path': 'tools/build/repack_locales.py',
     'conditions': [
       ['branding=="Chrome"', {
         'branding_flag': ['-b', 'google_chrome',],
@@ -11,25 +14,23 @@
         'branding_flag': ['-b', 'chromium',],
       }],
     ],
-    'repack_extra_flags%': [],
-    'repack_output_dir%': '<(SHARED_INTERMEDIATE_DIR)',
   },
   'inputs': [
-    'tools/build/repack_locales.py',
-    '<!@pymod_do_main(repack_locales -i -p <(OS) <(branding_flag) -g <(grit_out_dir) -s <(SHARED_INTERMEDIATE_DIR) -x <(repack_output_dir) --use-ash <(use_ash) <(repack_extra_flags) <(locales))'
+    '<(repack_locales_path)',
+    '<!@pymod_do_main(repack_locales -i -p <(OS) <(branding_flag) -g <(grit_out_dir) -s <(SHARED_INTERMEDIATE_DIR) -x <(SHARED_INTERMEDIATE_DIR) --use-ash <(use_ash) <(pak_locales))'
   ],
   'outputs': [
-    '<!@pymod_do_main(repack_locales -o -p <(OS) -g <(grit_out_dir) -s <(SHARED_INTERMEDIATE_DIR) -x <(repack_output_dir) <(locales))'
+    '<!@pymod_do_main(repack_locales -o -p <(OS) -g <(grit_out_dir) -s <(SHARED_INTERMEDIATE_DIR) -x <(SHARED_INTERMEDIATE_DIR) <(pak_locales))'
   ],
   'action': [
-    '<@(repack_locales_cmd)',
+    'python',
+    '<(repack_locales_path)',
     '<@(branding_flag)',
     '-p', '<(OS)',
     '-g', '<(grit_out_dir)',
     '-s', '<(SHARED_INTERMEDIATE_DIR)',
-    '-x', '<(repack_output_dir)/.',
+    '-x', '<(SHARED_INTERMEDIATE_DIR)/.',
     '--use-ash', '<(use_ash)',
-    '<@(repack_extra_flags)',
-    '<@(locales)',
+    '<@(pak_locales)',
   ],
 }
diff --git a/chrome/chrome_repack_pseudo_locales.gypi b/chrome/chrome_repack_pseudo_locales.gypi
deleted file mode 100644
index 3fd0e76..0000000
--- a/chrome/chrome_repack_pseudo_locales.gypi
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-{
-  'action_name': 'repack_pseudo_locales',
-  'variables': {
-    'conditions': [
-      ['branding=="Chrome"', {
-        'branding_flag': ['-b', 'google_chrome',],
-      }, {  # else: branding!="Chrome"
-        'branding_flag': ['-b', 'chromium',],
-      }],
-    ],
-  },
-  'inputs': [
-    'tools/build/repack_locales.py',
-    '<!@pymod_do_main(repack_locales -i -p <(OS) <(branding_flag) -g <(grit_out_dir) -s <(SHARED_INTERMEDIATE_DIR) -x <(INTERMEDIATE_DIR) --use-ash <(use_ash) <(pseudo_locales))'
-  ],
-  'conditions': [
-    ['OS == "mac" or OS == "ios"', {
-      'outputs': [
-        '<!@pymod_do_main(repack_locales -o -p <(OS) -g <(grit_out_dir) -s <(SHARED_INTERMEDIATE_DIR) -x <(SHARED_INTERMEDIATE_DIR) <(pseudo_locales))'
-      ],
-    }, { # else 'OS != "mac"'
-      'outputs': [
-        '<(SHARED_INTERMEDIATE_DIR)/<(pseudo_locales).pak'
-      ],
-    }],
-  ],
-  'action': [
-    '<@(repack_locales_cmd)',
-    '<@(branding_flag)',
-    '-p', '<(OS)',
-    '-g', '<(grit_out_dir)',
-    '-s', '<(SHARED_INTERMEDIATE_DIR)',
-    '-x', '<(SHARED_INTERMEDIATE_DIR)/.',
-    '--use-ash', '<(use_ash)',
-    '<@(pseudo_locales)',
-  ],
-}
diff --git a/chrome/chrome_repack_resources.gypi b/chrome/chrome_repack_resources.gypi
index 17bbca5..dcc2d7e 100644
--- a/chrome/chrome_repack_resources.gypi
+++ b/chrome/chrome_repack_resources.gypi
@@ -19,6 +19,7 @@
       '<(grit_out_dir)/sync_internals_resources.pak',
       '<(grit_out_dir)/translate_internals_resources.pak',
     ],
+    'pak_output': '<(SHARED_INTERMEDIATE_DIR)/repack/resources.pak',
     'conditions': [
       ['OS != "ios"', {
         'pak_inputs': [
@@ -44,12 +45,5 @@
       }],
     ],
   },
-  'inputs': [
-    '<(repack_path)',
-    '<@(pak_inputs)',
-  ],
-  'outputs': [
-    '<(SHARED_INTERMEDIATE_DIR)/repack/resources.pak',
-  ],
-  'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'],
+  'includes': [ '../build/repack_action.gypi' ],
 }
diff --git a/chrome/chrome_resources.gyp b/chrome/chrome_resources.gyp
index f67bfb4..6b1d8d8 100644
--- a/chrome/chrome_resources.gyp
+++ b/chrome/chrome_resources.gyp
@@ -6,7 +6,6 @@
     'grit_out_dir': '<(SHARED_INTERMEDIATE_DIR)/chrome',
     'about_credits_file': '<(SHARED_INTERMEDIATE_DIR)/about_credits.html',
     'additional_modules_list_file': '<(SHARED_INTERMEDIATE_DIR)/chrome/browser/internal/additional_modules_list.txt',
-    'repack_locales_cmd': ['python', 'tools/build/repack_locales.py'],
   },
   'targets': [
     {
@@ -320,9 +319,6 @@
     {
       'target_name': 'packed_extra_resources',
       'type': 'none',
-      'variables': {
-        'repack_path': '../tools/grit/grit/format/repack.py',
-      },
       'dependencies': [
         'chrome_extra_resources',
         'packed_resources',
@@ -350,9 +346,6 @@
     {
       'target_name': 'packed_resources',
       'type': 'none',
-      'variables': {
-        'repack_path': '../tools/grit/grit/format/repack.py',
-      },
       'dependencies': [
         # MSVS needs the dependencies explictly named, Make is able to
         # derive the dependencies from the output files.
@@ -367,10 +360,18 @@
       ],
       'actions': [
         {
+          'action_name': 'repack_locales_pack',
+          'variables': {
+            'pak_locales': '<(locales)',
+          },
           'includes': ['chrome_repack_locales.gypi']
         },
         {
-          'includes': ['chrome_repack_pseudo_locales.gypi']
+          'action_name': 'repack_pseudo_locales_pack',
+          'variables': {
+            'pak_locales': '<(pseudo_locales)',
+          },
+          'includes': ['chrome_repack_locales.gypi']
         },
         {
           'includes': ['chrome_repack_chrome_100_percent.gypi']
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index a4ec6a4..61b6c1b 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -88,7 +88,6 @@
         'chrome_resources.gyp:chrome_strings',
         'chrome_resources.gyp:packed_extra_resources',
         'chrome_resources.gyp:packed_resources',
-        'common/extensions/api/api.gyp:chrome_api',
         'debugger',
         'renderer',
         'test_support_common',
@@ -144,8 +143,6 @@
         'browser/extensions/extension_function_test_utils.cc',
         'browser/extensions/extension_commands_global_registry_apitest.cc',
         'browser/extensions/extension_keybinding_apitest.cc',
-        'browser/extensions/extension_test_message_listener.cc',
-        'browser/extensions/extension_test_message_listener.h',
         'browser/extensions/notifications_apitest.cc',
         'browser/extensions/updater/extension_cache_fake.h',
         'browser/extensions/updater/extension_cache_fake.cc',
@@ -572,12 +569,6 @@
         'test/chromedriver/chrome/web_view.h',
         'test/chromedriver/chrome/web_view_impl.cc',
         'test/chromedriver/chrome/web_view_impl.h',
-        'test/chromedriver/chrome/zip.cc',
-        'test/chromedriver/chrome/zip.h',
-        'test/chromedriver/chrome/zip_internal.cc',
-        'test/chromedriver/chrome/zip_internal.h',
-        'test/chromedriver/chrome/zip_reader.cc',
-        'test/chromedriver/chrome/zip_reader.h',
         'test/chromedriver/net/adb_client_socket.cc',
         'test/chromedriver/net/adb_client_socket.h',
         'test/chromedriver/net/net_util.cc',
@@ -683,6 +674,7 @@
         '../crypto/crypto.gyp:crypto',
         '../net/net.gyp:http_server',
         '../net/net.gyp:net',
+        '../third_party/zlib/google/zip.gyp:zip',
         '../ui/base/ui_base.gyp:ui_base',
         '../ui/events/events.gyp:events_base',
         '../ui/gfx/gfx.gyp:gfx',
@@ -912,8 +904,8 @@
         '../third_party/libjingle/libjingle.gyp:peerconnection_server',
         '../third_party/safe_browsing/safe_browsing.gyp:safe_browsing',
         '../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
-        '../ui/base/ui_base.gyp:webui_test_support',
         '../ui/compositor/compositor.gyp:compositor_test_support',
+        '../ui/resources/ui_resources.gyp:ui_resources',
         '../ui/web_dialogs/web_dialogs.gyp:web_dialogs_test_support',
         '../v8/tools/gyp/v8.gyp:v8',
         # Runtime dependencies
@@ -990,6 +982,7 @@
         'browser/chromeos/drive/drive_integration_service_browsertest.cc',
         'browser/chromeos/drive/test_util.cc',
         'browser/chromeos/drive/test_util.h',
+        'browser/chromeos/extensions/accessibility_features_apitest.cc',
         'browser/chromeos/extensions/screenlock_private_apitest.cc',
         'browser/chromeos/extensions/echo_private_apitest.cc',
         'browser/chromeos/extensions/file_manager/file_browser_handler_api_test.cc',
@@ -1014,6 +1007,7 @@
         'browser/chromeos/kiosk_mode/mock_kiosk_mode_settings.h',
         'browser/chromeos/login/captive_portal_window_browsertest.cc',
         'browser/chromeos/login/crash_restore_browsertest.cc',
+        'browser/chromeos/login/demo_mode/demo_app_launcher_browsertest.cc',
         'browser/chromeos/login/enrollment/enrollment_screen_browsertest.cc',
         'browser/chromeos/login/enrollment/mock_enrollment_screen.cc',
         'browser/chromeos/login/enrollment/mock_enrollment_screen.h',
@@ -1047,6 +1041,8 @@
         'browser/chromeos/login/screens/network_screen_browsertest.cc',
         'browser/chromeos/login/screens/update_screen_browsertest.cc',
         'browser/chromeos/login/simple_web_view_dialog_browsertest.cc',
+        'browser/chromeos/login/test/app_window_waiter.cc',
+        'browser/chromeos/login/test/app_window_waiter.h',
         'browser/chromeos/login/test/https_forwarder.cc',
         'browser/chromeos/login/test/https_forwarder.h',
         'browser/chromeos/login/test_login_utils.cc',
@@ -1055,6 +1051,7 @@
         'browser/chromeos/login/user_image_manager_browsertest.cc',
         'browser/chromeos/login/user_image_manager_test_util.cc',
         'browser/chromeos/login/user_image_manager_test_util.h',
+        'browser/chromeos/login/wallpaper_manager_policy_browsertest.cc',
         'browser/chromeos/login/wizard_controller_browsertest.cc',
         'browser/chromeos/login/wizard_in_process_browser_test.cc',
         'browser/chromeos/login/wizard_in_process_browser_test.h',
@@ -1103,6 +1100,8 @@
         'browser/extensions/api/bluetooth/bluetooth_apitest.cc',
         'browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc',
         'browser/extensions/api/braille_display_private/braille_display_private_apitest.cc',
+        'browser/extensions/api/braille_display_private/mock_braille_controller.cc',
+        'browser/extensions/api/braille_display_private/mock_braille_controller.h',
         'browser/extensions/api/bookmarks/bookmark_apitest.cc',
         'browser/extensions/api/browsing_data/browsing_data_test.cc',
         'browser/extensions/api/cast_channel/cast_channel_apitest.cc',
@@ -1145,7 +1144,6 @@
         'browser/extensions/api/management/management_browsertest.cc',
         'browser/extensions/api/mdns/mdns_apitest.cc',
         'browser/extensions/api/media_galleries/media_galleries_apitest.cc',
-        'browser/extensions/api/media_galleries_private/media_galleries_private_apitest.cc',
         'browser/extensions/api/media_galleries_private/media_galleries_watch_apitest.cc',
         'browser/extensions/api/messaging/native_messaging_apitest.cc',
         'browser/extensions/api/metrics_private/metrics_apitest.cc',
@@ -1242,8 +1240,6 @@
         'browser/extensions/extension_startup_browsertest.cc',
         'browser/extensions/extension_storage_apitest.cc',
         'browser/extensions/extension_tabs_apitest.cc',
-        'browser/extensions/extension_test_message_listener.cc',
-        'browser/extensions/extension_test_message_listener.h',
         'browser/extensions/extension_toolbar_model_browsertest.cc',
         'browser/extensions/extension_url_rewrite_browsertest.cc',
         'browser/extensions/extension_view_host_factory_browsertest.cc',
@@ -1681,6 +1677,11 @@
             'browser/ui/sync/one_click_signin_bubble_links_delegate_browsertest.cc',
           ]
         }],
+        [ 'OS == "android"', {
+          'sources!': [
+            'browser/autofill/risk/fingerprint_browsertest.cc',
+          ]
+        }],
         ['enable_autofill_dialog==0', {
           'sources!': [
             'browser/ui/autofill/autofill_dialog_controller_browsertest.cc',
@@ -1718,6 +1719,7 @@
                     '../third_party/liblouis/nacl_wrapper/liblouis_wrapper_browsertest.cc',
                   ],
                   'dependencies': [
+                    'browser_chromeos',
                     '../third_party/liblouis/liblouis_nacl.gyp:liblouis_test_data',
                   ],
                 }],
@@ -1882,7 +1884,6 @@
             # for win aura builds.
             # TODO: enable these for win_ash browser tests.
             'browser/chromeos/system/tray_accessibility_browsertest.cc',
-            'browser/ui/ash/accelerator_commands_browsertest.cc',
             'browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc',
             'browser/ui/ash/launcher/launcher_favicon_loader_browsertest.cc',
             'browser/ui/ash/shelf_browsertest.cc',
@@ -2123,6 +2124,7 @@
         'test/base/chrome_render_view_test.h',
         'test/perf/browser_perf_test.cc',
         'test/perf/browser_perf_test.h',
+        'test/perf/mach_ports_performancetest.cc',
       ],
       'rules': [
         {
@@ -2220,6 +2222,10 @@
             'chrome',
             '../components/components.gyp:breakpad_stubs',
           ],
+        }, {  # OS!="mac"
+          'sources!': [
+            'test/perf/mach_ports_performancetest.cc',
+          ],
         }],
         ['os_posix == 1 and OS != "mac" and OS != "android"', {
           'conditions': [
@@ -2401,6 +2407,8 @@
         'browser/sync/test/integration/sync_datatype_helper.h',
         'browser/sync/test/integration/sync_extension_helper.cc',
         'browser/sync/test/integration/sync_extension_helper.h',
+        'browser/sync/test/integration/sync_integration_test_util.cc',
+        'browser/sync/test/integration/sync_integration_test_util.h',
         'browser/sync/test/integration/sync_test.cc',
         'browser/sync/test/integration/sync_test.h',
         'browser/sync/test/integration/themes_helper.cc',
@@ -2437,7 +2445,6 @@
         'chrome_resources.gyp:packed_extra_resources',
         'chrome_resources.gyp:packed_resources',
         'common',
-        'common/extensions/api/api.gyp:chrome_api',
         'renderer',
         'test_support_sync_integration',
         '../sync/sync.gyp:sync',
@@ -2590,7 +2597,6 @@
       'target_name': 'sync_performance_tests',
       'type': 'executable',
       'dependencies': [
-        'common/extensions/api/api.gyp:chrome_api',
         'test/perf/perf_test.gyp:*',
         'test_support_sync_integration',
         '../sync/sync.gyp:sync',
@@ -3238,6 +3244,13 @@
             'tools/service_discovery_sniffer/service_discovery_sniffer.h',
             'tools/service_discovery_sniffer/service_discovery_sniffer.cc',
           ],
+          'conditions': [
+            ['enable_webrtc==1', {
+              'dependencies': [
+                '../third_party/libjingle/libjingle.gyp:libjingle_webrtc'
+              ]
+            }],
+          ],
         }]
     }],
   ],  # 'conditions'
diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi
index 025cbe1..2c11c1e 100644
--- a/chrome/chrome_tests_unit.gypi
+++ b/chrome/chrome_tests_unit.gypi
@@ -19,6 +19,8 @@
         '../base/base.gyp:base_prefs_test_support',
         '../base/base.gyp:test_support_base',
         '../components/components.gyp:password_manager_core_browser_test_support',
+        '../components/components.gyp:signin_core_browser_test_support',
+        '../components/components.gyp:sync_driver_test_support',
         '../components/components.gyp:sync_driver_test_support',
         '../content/content.gyp:content_app_both',
         '../content/content_shell_and_tests.gyp:test_support_content',
@@ -100,6 +102,8 @@
         'browser/chromeos/login/test/oobe_screen_waiter.h',
         'browser/chromeos/login/test/js_checker.cc',
         'browser/chromeos/login/test/js_checker.h',
+        'browser/chromeos/net/network_portal_detector_test_utils.cc',
+        'browser/chromeos/net/network_portal_detector_test_utils.h',
         'browser/chromeos/policy/cloud_external_data_manager_base_test_util.cc',
         'browser/chromeos/policy/cloud_external_data_manager_base_test_util.h',
         'browser/chromeos/policy/device_policy_builder.cc',
@@ -125,6 +129,8 @@
         'browser/extensions/api/messaging/native_messaging_test_util.h',
         'browser/extensions/extension_notification_observer.cc',
         'browser/extensions/extension_notification_observer.h',
+        'browser/extensions/extension_test_message_listener.cc',
+        'browser/extensions/extension_test_message_listener.h',
         'browser/extensions/fake_safe_browsing_database_manager.cc',
         'browser/extensions/fake_safe_browsing_database_manager.h',
         'browser/extensions/mock_extension_special_storage_policy.cc',
@@ -173,8 +179,8 @@
         'browser/sessions/session_service_test_helper.h',
         'browser/signin/fake_profile_oauth2_token_service.cc',
         'browser/signin/fake_profile_oauth2_token_service.h',
-        'browser/signin/fake_profile_oauth2_token_service_wrapper.cc',
-        'browser/signin/fake_profile_oauth2_token_service_wrapper.h',
+        'browser/signin/fake_profile_oauth2_token_service_builder.cc',
+        'browser/signin/fake_profile_oauth2_token_service_builder.h',
         'browser/signin/fake_signin_manager.cc',
         'browser/signin/fake_signin_manager.h',
         'browser/ssl/ssl_client_auth_requestor_mock.cc',
@@ -661,6 +667,7 @@
         'browser/chromeos/drive/drive_file_stream_reader_unittest.cc',
         'browser/chromeos/drive/drive_integration_service_unittest.cc',
         'browser/chromeos/drive/drive_url_request_job_unittest.cc',
+        'browser/chromeos/drive/dummy_file_system.cc',
         'browser/chromeos/drive/dummy_file_system.h',
         'browser/chromeos/drive/fake_file_system.cc',
         'browser/chromeos/drive/fake_file_system.h',
@@ -716,6 +723,7 @@
         'browser/chromeos/file_manager/path_util_unittest.cc',
         'browser/chromeos/file_manager/url_util_unittest.cc',
         'browser/chromeos/file_manager/volume_manager_unittest.cc',
+        'browser/chromeos/file_system_provider/service_unittest.cc',
         'browser/chromeos/extensions/device_local_account_management_policy_provider_unittest.cc',
         'browser/chromeos/extensions/wallpaper_private_api_unittest.cc',
         'browser/chromeos/external_metrics_unittest.cc',
@@ -760,7 +768,6 @@
         'browser/chromeos/policy/device_cloud_policy_store_chromeos_unittest.cc',
         'browser/chromeos/policy/device_local_account_policy_service_unittest.cc',
         'browser/chromeos/policy/enterprise_install_attributes_unittest.cc',
-        'browser/chromeos/policy/login_screen_power_management_policy_unittest.cc',
         'browser/chromeos/policy/network_configuration_updater_unittest.cc',
         'browser/chromeos/policy/recommendation_restorer_unittest.cc',
         'browser/chromeos/policy/user_cloud_policy_manager_chromeos_unittest.cc',
@@ -783,7 +790,6 @@
         'browser/chromeos/version_loader_unittest.cc',
         'browser/command_updater_unittest.cc',
         'browser/component_updater/test/component_installers_unittest.cc',
-        'browser/component_updater/test/component_patcher_mock.h',
         'browser/component_updater/test/component_patcher_unittest.cc',
         'browser/component_updater/test/component_updater_ping_manager_unittest.cc',
         'browser/component_updater/test/component_updater_service_unittest.cc',
@@ -877,6 +883,7 @@
         'browser/extensions/api/image_writer_private/destroy_partitions_operation_unittest.cc',
         'browser/extensions/api/image_writer_private/operation_manager_unittest.cc',
         'browser/extensions/api/image_writer_private/operation_unittest.cc',
+        'browser/extensions/api/image_writer_private/removable_storage_provider_chromeos_unittest.cc',
         'browser/extensions/api/image_writer_private/test_utils.cc',
         'browser/extensions/api/image_writer_private/write_from_file_operation_unittest.cc',
         'browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc',
@@ -914,6 +921,7 @@
         'browser/extensions/app_sync_data_unittest.cc',
         'browser/extensions/blacklist_unittest.cc',
         'browser/extensions/blacklist_state_fetcher_unittest.cc',
+        'browser/extensions/bookmark_app_helper_unittest.cc',
         'browser/extensions/browser_permissions_policy_delegate_unittest.cc',
         'browser/extensions/chrome_app_sorting_unittest.cc',
         'browser/extensions/component_loader_unittest.cc',
@@ -940,6 +948,7 @@
         'browser/extensions/extension_service_unittest.h',
         'browser/extensions/extension_special_storage_policy_unittest.cc',
         'browser/extensions/extension_sync_data_unittest.cc',
+        'browser/extensions/extension_test_message_listener_unittest.cc',
         'browser/extensions/extension_ui_unittest.cc',
         'browser/extensions/extension_warning_badge_service_unittest.cc',
         'browser/extensions/extension_warning_service_unittest.cc',
@@ -956,7 +965,6 @@
         'browser/extensions/policy_handlers_unittest.cc',
         'browser/extensions/sandboxed_unpacker_unittest.cc',
         'browser/extensions/standard_management_policy_provider_unittest.cc',
-        'browser/extensions/tab_helper_unittest.cc',
         'browser/extensions/token_cache/token_cache_service_unittest.cc',
         'browser/extensions/updater/extension_cache_fake.h',
         'browser/extensions/updater/extension_cache_fake.cc',
@@ -967,7 +975,6 @@
         'browser/extensions/webstore_installer_unittest.cc',
         'browser/external_protocol/external_protocol_handler_unittest.cc',
         'browser/favicon/favicon_handler_unittest.cc',
-        'browser/feedback/feedback_common_unittest.cc',
         'browser/feedback/feedback_uploader_unittest.cc',
         'browser/file_select_helper_unittest.cc',
         'browser/first_run/first_run_unittest.cc',
@@ -1053,6 +1060,7 @@
         'browser/media/desktop_media_list_ash_unittest.cc',
         'browser/media/native_desktop_media_list_unittest.cc',
         'browser/media/webrtc_log_uploader_unittest.cc',
+        'browser/media/webrtc_log_util_unittest.cc',
         'browser/media_galleries/fileapi/native_media_file_util_unittest.cc',
         'browser/media_galleries/linux/mtp_device_object_enumerator_unittest.cc',
         'browser/media_galleries/mac/mtp_device_delegate_impl_mac_unittest.mm',
@@ -1067,8 +1075,10 @@
         'browser/media_galleries/media_galleries_scan_result_dialog_controller_unittest.cc',
         'browser/media_galleries/media_scan_manager_unittest.cc',
         'browser/media_galleries/win/mtp_device_object_enumerator_unittest.cc',
+        'browser/metrics/cloned_install_detector_unittest.cc',
         'browser/metrics/compression_utils_unittest.cc',
         'browser/metrics/extension_metrics_unittest.cc',
+        'browser/metrics/machine_id_provider_win_unittest.cc',
         'browser/metrics/metrics_log_unittest.cc',
         'browser/metrics/metrics_log_serializer_unittest.cc',
         'browser/metrics/metrics_reporting_scheduler_unittest.cc',
@@ -1115,6 +1125,7 @@
         'browser/notifications/message_center_settings_controller_unittest.cc',
         'browser/notifications/sync_notifier/chrome_notifier_delegate_unittest.cc',
         'browser/notifications/sync_notifier/chrome_notifier_service_unittest.cc',
+        'browser/notifications/sync_notifier/image_holder_unittest.cc',
         'browser/notifications/sync_notifier/synced_notification_unittest.cc',
         'browser/notifications/sync_notifier/synced_notification_app_info_unittest.cc',
         'browser/notifications/sync_notifier/synced_notification_app_info_service_unittest.cc',
@@ -1150,12 +1161,14 @@
         'browser/prefs/pref_hash_filter_unittest.cc',
         'browser/prefs/pref_hash_store_impl_unittest.cc',
         'browser/prefs/pref_model_associator_unittest.cc',
+        'browser/prefs/profile_pref_store_manager_unittest.cc',
         'browser/prefs/proxy_config_dictionary_unittest.cc',
         'browser/prefs/proxy_policy_unittest.cc',
         'browser/prefs/proxy_prefs_unittest.cc',
         'browser/prefs/session_startup_pref_unittest.cc',
         'browser/prefs/tracked/pref_hash_calculator_helper_win_unittest.cc',
         'browser/prefs/tracked/pref_service_hash_store_contents_unittest.cc',
+        'browser/prefs/tracked/segregated_pref_store_unittest.cc',
         'browser/prerender/prerender_history_unittest.cc',
         'browser/prerender/prerender_tracker_unittest.cc',
         'browser/prerender/prerender_unittest.cc',
@@ -1206,6 +1219,7 @@
         'browser/resources/print_preview/print_preview_utils_unittest.gtestjs',
         'browser/resources_util_unittest.cc',
         'browser/rlz/rlz_unittest.cc',
+        'browser/safe_browsing/binary_feature_extractor_win_unittest.cc',
         'browser/safe_browsing/browser_feature_extractor_unittest.cc',
         'browser/safe_browsing/chunk_range_unittest.cc',
         'browser/safe_browsing/client_side_detection_host_unittest.cc',
@@ -1216,6 +1230,7 @@
         'browser/safe_browsing/download_protection_service_unittest.cc',
         'browser/safe_browsing/local_two_phase_testserver.cc',
         'browser/safe_browsing/malware_details_unittest.cc',
+        'browser/safe_browsing/pe_image_reader_win_unittest.cc',
         'browser/safe_browsing/ping_manager_unittest.cc',
         'browser/safe_browsing/prefix_set_unittest.cc',
         'browser/safe_browsing/protocol_manager_unittest.cc',
@@ -1225,7 +1240,6 @@
         'browser/safe_browsing/safe_browsing_store_file_unittest.cc',
         'browser/safe_browsing/safe_browsing_store_unittest.cc',
         'browser/safe_browsing/safe_browsing_util_unittest.cc',
-        'browser/safe_browsing/signature_util_win_unittest.cc',
         'browser/safe_browsing/two_phase_uploader_unittest.cc',
         'browser/search/hotword_service_unittest.cc',
         'browser/search/iframe_source_unittest.cc',
@@ -1257,12 +1271,9 @@
         'browser/shell_integration_linux_unittest.cc',
         'browser/shell_integration_win_unittest.cc',
         'browser/signin/account_reconcilor_unittest.cc',
-        'browser/signin/fake_auth_status_provider.cc',
-        'browser/signin/fake_auth_status_provider.h',
         'browser/signin/local_auth_unittest.cc',
         'browser/signin/mutable_profile_oauth2_token_service_unittest.cc',
         'browser/signin/profile_oauth2_token_service_request_unittest.cc',
-        'browser/signin/signin_error_controller_unittest.cc',
         'browser/signin/signin_error_notifier_ash_unittest.cc',
         'browser/signin/signin_global_error_unittest.cc',
         'browser/signin/signin_manager_unittest.cc',
@@ -1340,6 +1351,7 @@
         'browser/sync/sessions2/sessions_sync_manager_unittest.cc',
         'browser/sync/sessions2/tab_node_pool2_unittest.cc',
         'browser/sync/startup_controller_unittest.cc',
+        'browser/sync/sync_error_notifier_ash_unittest.cc',
         'browser/sync/sync_global_error_unittest.cc',
         'browser/sync/sync_policy_handler_unittest.cc',
         'browser/sync/sync_startup_tracker_unittest.cc',
@@ -1943,11 +1955,6 @@
         # unit_tests than in base_unittests.
         '../base/path_service_unittest.cc',
 
-        # TODO(joi): Move to //components/components_tests.gypi once
-        # remaining dependencies back to //chrome are eliminated.
-        '../components/autofill/content/browser/content_autofill_driver_unittest.cc',
-        '../components/autofill/content/browser/request_autocomplete_manager_unittest.cc',
-
         # TODO(yael): Move to //components/components_tests.gypi once
         # nacl_defines is moved out of chrome.gyp into a common place.
         '../components/nacl/loader/nacl_ipc_adapter_unittest.cc',
@@ -2164,9 +2171,6 @@
         }],
         ['chromeos==0', {
           'sources!': [
-            # TODO(zturner): Enable this on Windows.  See
-            # BrowserWithTestWindowTest::SetUp() for a comment explaining why
-            # this is broken.
             'browser/ui/views/frame/immersive_mode_controller_ash_unittest.cc',
             'browser/ui/views/select_file_dialog_extension_unittest.cc',
           ],
@@ -2267,6 +2271,7 @@
         ['enable_webrtc==0', {
           'sources!': [
             'browser/media/webrtc_log_uploader_unittest.cc',
+            'browser/media/webrtc_log_util_unittest.cc',
             'renderer/media/chrome_webrtc_log_message_delegate_unittest.cc',
           ],
         }],
@@ -2284,6 +2289,7 @@
             'browser/signin/signin_global_error_unittest.cc',
             'browser/signin/signin_manager_unittest.cc',
             'browser/signin/signin_names_io_thread_unittest.cc',
+            'browser/sync/sync_global_error_unittest.cc',
             'browser/ui/sync/one_click_signin_helper_unittest.cc',
             'browser/ui/sync/one_click_signin_sync_starter_unittest.cc',
             'browser/ui/views/frame/opaque_browser_frame_view_layout_unittest.cc',
@@ -2523,6 +2529,7 @@
             'browser/browser_commands_unittest.cc',
             'browser/download/download_shelf_unittest.cc',
             'browser/extensions/extension_message_bubble_controller_unittest.cc',
+            'browser/extensions/extension_test_message_listener_unittest.cc',
             'browser/policy/policy_path_parser_unittest.cc',
             'browser/profiles/off_the_record_profile_impl_unittest.cc',
             'browser/profiles/profile_list_desktop_unittest.cc',
diff --git a/chrome/common/DEPS b/chrome/common/DEPS
index 2c0d962..8609f1d 100644
--- a/chrome/common/DEPS
+++ b/chrome/common/DEPS
@@ -7,6 +7,7 @@
   "+components/nacl/common",
   "+components/password_manager/core/common",
   "+components/policy/core/common",
+  "+components/signin/core/common",
   "+components/translate/core/common",
   "+extensions/common",
   "+grit",  # For generated headers
diff --git a/chrome/common/badge_util.cc b/chrome/common/badge_util.cc
index 349443d..7ef0b5a 100644
--- a/chrome/common/badge_util.cc
+++ b/chrome/common/badge_util.cc
@@ -26,7 +26,7 @@
 const int kTopTextPadding = 0;
 #elif defined(OS_LINUX) && defined(TOOLKIT_VIEWS)
 const float kTextSize = 8.0;
-const int kBottomMarginBrowserAction = 5;
+const int kBottomMarginBrowserAction = 0;
 const int kBottomMarginPageAction = 2;
 const int kPadding = 2;
 const int kTopTextPadding = 1;
@@ -38,7 +38,7 @@
 const int kTopTextPadding = 0;
 #else
 const float kTextSize = 10;
-const int kBottomMarginBrowserAction = 5;
+const int kBottomMarginBrowserAction = 0;
 const int kBottomMarginPageAction = 2;
 const int kPadding = 2;
 // The padding between the top of the badge and the top of the text.
diff --git a/chrome/common/cast_messages.h b/chrome/common/cast_messages.h
index 0462234..5b91f59 100644
--- a/chrome/common/cast_messages.h
+++ b/chrome/common/cast_messages.h
@@ -103,11 +103,6 @@
   IPC_STRUCT_TRAITS_MEMBER(type)
 IPC_STRUCT_TRAITS_END()
 
-IPC_STRUCT_TRAITS_BEGIN(media::cast::CastLoggingConfig)
-  IPC_STRUCT_TRAITS_MEMBER(enable_raw_data_collection)
-  IPC_STRUCT_TRAITS_MEMBER(enable_stats_data_collection)
-IPC_STRUCT_TRAITS_END()
-
 // Cast messages sent from the browser to the renderer.
 
 IPC_MESSAGE_CONTROL2(CastMsg_ReceivedPacket,
@@ -169,11 +164,10 @@
     bool /* is_audio */,
     media::cast::MissingFramesAndPacketsMap /* missing_packets */)
 
-IPC_MESSAGE_CONTROL3(
+IPC_MESSAGE_CONTROL2(
     CastHostMsg_New,
     int32 /* channel_id */,
-    net::IPEndPoint /*remote_end_point*/,
-    media::cast::CastLoggingConfig /* logging_config */);
+    net::IPEndPoint /*remote_end_point*/);
 
 IPC_MESSAGE_CONTROL1(
     CastHostMsg_Delete,
diff --git a/chrome/common/chrome_constants.cc b/chrome/common/chrome_constants.cc
index 31e7f11..53a35eb 100644
--- a/chrome/common/chrome_constants.cc
+++ b/chrome/common/chrome_constants.cc
@@ -156,6 +156,8 @@
 const base::FilePath::CharType kCookieFilename[] = FPL("Cookies");
 const base::FilePath::CharType kCRLSetFilename[] =
     FPL("Certificate Revocation Lists");
+const base::FilePath::CharType kCLDDataFilename[] =
+    FPL("cld2_data.bin");
 const base::FilePath::CharType kCustomDictionaryFileName[] =
     FPL("Custom Dictionary.txt");
 const base::FilePath::CharType kExtensionActivityLogFilename[] =
diff --git a/chrome/common/chrome_constants.h b/chrome/common/chrome_constants.h
index bebfdd6..e3c5111 100644
--- a/chrome/common/chrome_constants.h
+++ b/chrome/common/chrome_constants.h
@@ -60,6 +60,7 @@
 extern const base::FilePath::CharType kCacheDirname[];
 extern const base::FilePath::CharType kCookieFilename[];
 extern const base::FilePath::CharType kCRLSetFilename[];
+extern const base::FilePath::CharType kCLDDataFilename[];
 extern const base::FilePath::CharType kCustomDictionaryFileName[];
 extern const base::FilePath::CharType kExtensionActivityLogFilename[];
 extern const base::FilePath::CharType kExtensionsCookieFilename[];
diff --git a/chrome/common/chrome_content_client.cc b/chrome/common/chrome_content_client.cc
index 9a43d15..e245a0e 100644
--- a/chrome/common/chrome_content_client.cc
+++ b/chrome/common/chrome_content_client.cc
@@ -479,6 +479,7 @@
     std::vector<std::string>* savable_schemes) {
   standard_schemes->push_back(extensions::kExtensionScheme);
   savable_schemes->push_back(extensions::kExtensionScheme);
+  standard_schemes->push_back(chrome::kChromeNativeScheme);
   standard_schemes->push_back(extensions::kExtensionResourceScheme);
   savable_schemes->push_back(extensions::kExtensionResourceScheme);
   standard_schemes->push_back(chrome::kChromeSearchScheme);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 8badaa8..2d6ec19 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -84,6 +84,12 @@
 // confirmation dialog. A value of 'accept' means to always act as if the dialog
 // was accepted, and 'cancel' means to always act as if the dialog was
 // cancelled.
+//
+// TODO (rdevlin.cronin): Remove this.
+// This is not a good use of a command-line flag, as it would be equally
+// effective as a global boolean. Additionally, this opens up a dangerous way
+// for attackers to append a commandline flag and circumvent all user action for
+// installing an extension.
 const char kAppsGalleryInstallAutoConfirmForTests[] =
     "apps-gallery-install-auto-confirm-for-tests";
 
@@ -156,10 +162,6 @@
 // Comma-separated list of SSL cipher suites to disable.
 const char kCipherSuiteBlacklist[]          = "cipher-suite-blacklist";
 
-// Clears the token service before using it. This allows simulating the
-// expiration of credentials during testing.
-const char kClearTokenService[]             = "clear-token-service";
-
 // Tells chrome to display the cloud print dialog and upload the specified file
 // for printing.
 const char kCloudPrintFile[]                = "cloud-print-file";
@@ -486,6 +488,11 @@
 // HttpAuthHandlerNegotiate::CreateSPN for more background.
 const char kEnableAuthNegotiatePort[]       = "enable-auth-negotiate-port";
 
+// Enables the pre- and auto-login features. When a user signs in to sync, the
+// browser's cookie jar is pre-filled with GAIA cookies. When the user visits a
+// GAIA login page, an info bar can help the user login.
+const char kEnableAutologin[]               = "enable-autologin";
+
 // Enables the Automation extension API.
 // TODO(dtseng): Remove once API enabled for stable channel.
 const char kEnableAutomationAPI[]           = "enable-automation-api";
@@ -673,6 +680,9 @@
 const char kEnableSearchButtonInOmniboxForStrOrIip[] =
     "enable-search-button-in-omnibox-for-str-or-iip";
 
+// Enable settings in a separate browser window per profile.
+const char kEnableSettingsWindow[]          = "enable-settings-window";
+
 // Enable SPDY/4 alpha 2. This is a temporary testing flag.
 const char kEnableSpdy4a2[]                 = "enable-spdy4a2";
 
@@ -704,13 +714,6 @@
 // Enables Translate experimental new UX which replaces the infobar.
 const char kEnableTranslateNewUX[]         = "enable-translate-new-ux";
 
-// Enables unrestricted SSL 3.0 fallback.
-// With this switch, SSL 3.0 fallback will be enabled for all sites.
-// Without this switch, SSL 3.0 fallback will be disabled for a site
-// pinned to the Google pin list (indicating that it is a Google site).
-const char kEnableUnrestrictedSSL3Fallback[] =
-    "enable-unrestricted-ssl3-fallback";
-
 // Enables Alternate-Protocol when the port is user controlled (> 1024).
 const char kEnableUserAlternateProtocolPorts[] =
     "enable-user-controlled-alternate-protocol-ports";
@@ -756,6 +759,10 @@
 // loaded. It is useful to tell the difference for tracking purposes.
 const char kFastStart[]            = "fast-start";
 
+// Allows displaying the list of existing profiles in the avatar bubble for
+// fast switching between profiles.
+const char kFastUserSwitching[]             = "fast-user-switching";
+
 // These two flags are added around the switches about:flags adds to the
 // command line. This is useful to see which switches were added by about:flags
 // on about:version. They don't have any effect.
@@ -851,6 +858,10 @@
 // Causes the browser to launch directly in incognito mode.
 const char kIncognito[]                     = "incognito";
 
+// Invalidation service should use GCM network channel even if experiment is not
+// enabled.
+const char kInvalidationUseGCMChannel[]     = "invalidation-use-gcm-channel";
+
 // Causes Chrome to attempt to get metadata from the webstore for the
 // app/extension ID given, and then prompt the user to download and install it.
 const char kInstallFromWebstore[]           = "install-from-webstore";
@@ -920,11 +931,6 @@
 // Enables multiprofile Chrome.
 const char kMultiProfiles[]                 = "multi-profiles";
 
-// List of native messaging hosts outside of the default location. Used for
-// tests. The value must be comma-separate lists of key-value pairs separated
-// equal sign. E.g. "host1=/path/to/host1/manifest.json,host2=/path/host2.json".
-const char kNativeMessagingHosts[]          = "native-messaging-hosts";
-
 // Sets the base logging level for the net log. Log 0 logs the most data.
 // Intended primarily for use with --log-net-log.
 const char kNetLogLevel[]                   = "net-log-level";
@@ -1190,9 +1196,6 @@
 // If true the app list will be shown.
 const char kShowAppList[]                   = "show-app-list";
 
-// If true the app list will show the start page webui.
-const char kShowAppListStartPage[]          = "show-app-list-start-page";
-
 // See kHideIcons.
 const char kShowIcons[]                     = "show-icons";
 
@@ -1220,6 +1223,9 @@
 // Simulates that current version is outdated.
 const char kSimulateOutdated[]               = "simulate-outdated";
 
+// Simulates that current version is outdated and auto-update is off.
+const char kSimulateOutdatedNoAU[]           = "simulate-outdated-no-au";
+
 // Replaces the buffered data source for <audio> and <video> with a simplified
 // resource loader that downloads the entire resource into memory.
 
@@ -1434,6 +1440,9 @@
 const char kEnableZeroSuggestPersonalized[] =
     "enable-zero-suggest-personalized";
 
+// Enables instant search clicks feature.
+const char kEnableInstantSearchClicks[] = "enable-instant-search-clicks";
+
 #endif
 
 #if defined(USE_ASH)
@@ -1451,6 +1460,11 @@
 // and sanity checks are made to avoid corrupting the profile.
 // The browser exits after migration is complete.
 const char kMigrateDataDirForSxS[]          = "migrate-data-dir-for-sxs";
+
+// Allows sending text-to-speech requests to speech-dispatcher, a common
+// Linux speech service. Because it's buggy, the user must explicitly
+// enable it so that visiting a random webpage can't cause instability.
+const char kEnableSpeechDispatcher[] = "enable-speech-dispatcher";
 #endif  // defined(OS_LINUX) && !defined(OS_CHROMEOS)
 
 #if defined(OS_MACOSX)
@@ -1475,9 +1489,6 @@
 const char kEnablePermissionsBubbles[]      = "enable-permissions-bubbles";
 
 #if defined(OS_WIN)
-// Enables support to debug printing subsystem.
-const char kDebugPrint[]                    = "debug-print";
-
 // Fallback to XPS. By default connector uses CDD.
 const char kEnableCloudPrintXps[]           = "enable-cloud-print-xps";
 
@@ -1512,6 +1523,11 @@
 const char kWindows8Search[]           = "windows8-search";
 #endif
 
+#if defined(ENABLE_FULL_PRINTING) && !defined(OFFICIAL_BUILD)
+// Enables support to debug printing subsystem.
+const char kDebugPrint[] = "debug-print";
+#endif
+
 #ifndef NDEBUG
 // Enables overriding the path of file manager extension.
 const char kFileManagerExtensionPath[]      = "filemgr-ext-path";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 0002c9d..8f4001b 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -12,6 +12,7 @@
 #include "base/base_switches.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/password_manager/core/common/password_manager_switches.h"
+#include "components/signin/core/common/signin_switches.h"
 #include "content/public/common/content_switches.h"
 
 namespace switches {
@@ -57,7 +58,6 @@
 extern const char kCheckForUpdateIntervalSec[];
 extern const char kCheckCloudPrintConnectorPolicy[];
 extern const char kCipherSuiteBlacklist[];
-extern const char kClearTokenService[];
 extern const char kCloudPrintFile[];
 extern const char kCloudPrintJobTitle[];
 extern const char kCloudPrintFileType[];
@@ -141,6 +141,7 @@
 extern const char kEnableAppsShowOnFirstPaint[];
 extern const char kEnableAsyncDns[];
 extern const char kEnableAuthNegotiatePort[];
+extern const char kEnableAutologin[];
 extern const char kEnableAutomationAPI[];
 extern const char kEnableBenchmarking[];
 extern const char kEnableClientHints[];
@@ -193,6 +194,7 @@
 extern const char kEnableSearchButtonInOmniboxAlways[];
 extern const char kEnableSearchButtonInOmniboxForStr[];
 extern const char kEnableSearchButtonInOmniboxForStrOrIip[];
+extern const char kEnableSettingsWindow[];
 extern const char kEnableSpdy4a2[];
 extern const char kEnableSpellingAutoCorrect[];
 extern const char kEnableSpellingFeedbackFieldTrial[];
@@ -202,7 +204,6 @@
 extern const char kEnableSyncSyncedNotifications[];
 extern const char kEnableThumbnailRetargeting[];
 extern const char kEnableTranslateNewUX[];
-extern const char kEnableUnrestrictedSSL3Fallback[];
 extern const char kEnableUserAlternateProtocolPorts[];
 extern const char kEnableWatchdog[];
 extern const char kEnableWebSocketOverSpdy[];
@@ -214,6 +215,7 @@
 extern const char kExtraSearchQueryParams[];
 extern const char kFakeVariationsChannel[];
 extern const char kFastStart[];
+extern const char kFastUserSwitching[];
 extern const char kFlagSwitchesBegin[];
 extern const char kFlagSwitchesEnd[];
 extern const char kFeedbackServer[];
@@ -236,6 +238,7 @@
 extern const char kHostResolverRetryAttempts[];
 extern const char kIgnoreUrlFetcherCertRequests[];
 extern const char kIncognito[];
+extern const char kInvalidationUseGCMChannel[];
 extern const char kInstallFromWebstore[];
 extern const char kInstantProcess[];
 extern const char kIpcFuzzerTestcase[];
@@ -255,7 +258,6 @@
 extern const char kMessageLoopHistogrammer[];
 extern const char kMetricsRecordingOnly[];
 extern const char kMultiProfiles[];
-extern const char kNativeMessagingHosts[];
 extern const char kNetLogLevel[];
 extern const char kNewProfileManagement[];
 extern const char kNoDefaultBrowserCheck[];
@@ -324,13 +326,13 @@
 extern const char kSilentLaunch[];
 extern const char kSetToken[];
 extern const char kShowAppList[];
-extern const char kShowAppListStartPage[];
 extern const char kShowIcons[];
 extern const char kSigninProcess[];
 extern const char kSilentDumpOnDCHECK[];
 extern const char kSimulateUpgrade[];
 extern const char kSimulateCriticalUpdate[];
 extern const char kSimulateOutdated[];
+extern const char kSimulateOutdatedNoAU[];
 extern const char kSpdyProxyAuthFallback[];
 extern const char kSpdyProxyAuthOrigin[];
 extern const char kSpdyProxyAuthValue[];
@@ -395,6 +397,7 @@
 extern const char kEnableZeroSuggestEtherNoSerp[];
 extern const char kEnableZeroSuggestMostVisited[];
 extern const char kEnableZeroSuggestPersonalized[];
+extern const char kEnableInstantSearchClicks[];
 #endif
 
 #if defined(USE_ASH)
@@ -406,6 +409,7 @@
 #endif
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+extern const char kEnableSpeechDispatcher[];
 extern const char kMigrateDataDirForSxS[];
 #endif
 
@@ -417,7 +421,6 @@
 #endif
 
 #if defined(OS_WIN)
-extern const char kDebugPrint[];
 extern const char kEnableCloudPrintXps[];
 extern const char kEnableProfileShortcutManager[];
 extern const char kForceDesktop[];
@@ -429,6 +432,10 @@
 extern const char kWindows8Search[];
 #endif
 
+#if defined(ENABLE_FULL_PRINTING) && !defined(OFFICIAL_BUILD)
+extern const char kDebugPrint[];
+#endif
+
 #ifndef NDEBUG
 extern const char kFileManagerExtensionPath[];
 extern const char kImageLoaderExtensionPath[];
diff --git a/chrome/common/chrome_utility_messages.h b/chrome/common/chrome_utility_messages.h
index 2c2acbc..c375565 100644
--- a/chrome/common/chrome_utility_messages.h
+++ b/chrome/common/chrome_utility_messages.h
@@ -23,6 +23,7 @@
 #include "printing/backend/print_backend.h"
 #include "printing/page_range.h"
 #include "printing/pdf_render_settings.h"
+#include "printing/pwg_raster_settings.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
 #define IPC_MESSAGE_START ChromeUtilityMsgStart
@@ -75,6 +76,14 @@
   IPC_STRUCT_TRAITS_MEMBER(duplex_default)
 IPC_STRUCT_TRAITS_END()
 
+IPC_ENUM_TRAITS(printing::PwgRasterTransformType);
+
+IPC_STRUCT_TRAITS_BEGIN(printing::PwgRasterSettings)
+  IPC_STRUCT_TRAITS_MEMBER(odd_page_transform)
+  IPC_STRUCT_TRAITS_MEMBER(rotate_all_pages)
+  IPC_STRUCT_TRAITS_MEMBER(reverse_page_order)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(UpdateManifest::Result)
   IPC_STRUCT_TRAITS_MEMBER(extension_id)
   IPC_STRUCT_TRAITS_MEMBER(version)
@@ -142,7 +151,7 @@
 // Utility process messages:
 // These are messages from the browser to the utility process.
 
-// Tell the utility process to unpack the given extension file in its
+// Tells the utility process to unpack the given extension file in its
 // directory and verify that it is valid.
 IPC_MESSAGE_CONTROL4(ChromeUtilityMsg_UnpackExtension,
                      base::FilePath /* extension_filename */,
@@ -177,10 +186,12 @@
                      std::vector<printing::PageRange>)
 
 // Tell the utility process to render the given PDF into a PWGRaster.
-IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_RenderPDFPagesToPWGRaster,
-                     IPC::PlatformFileForTransit,  /* Input PDF file */
-                     printing::PdfRenderSettings,  /* PDF render settings */
-                     IPC::PlatformFileForTransit   /* Output PWG file */)
+IPC_MESSAGE_CONTROL4(ChromeUtilityMsg_RenderPDFPagesToPWGRaster,
+                     IPC::PlatformFileForTransit, /* Input PDF file */
+                     printing::PdfRenderSettings, /* PDF render settings */
+                     // PWG transform settings.
+                     printing::PwgRasterSettings,
+                     IPC::PlatformFileForTransit /* Output PWG file */)
 
 // Tell the utility process to decode the given JPEG image data with a robust
 // libjpeg codec.
@@ -205,6 +216,22 @@
 IPC_MESSAGE_CONTROL1(ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults,
                      std::string /* printer name */)
 
+// Tell the utility process to patch the given |input_file| using |patch_file|
+// and place the output in |output_file|. The patch should use the bsdiff
+// algorithm (Courgette's version).
+IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_PatchFileBsdiff,
+                     base::FilePath /* input_file */,
+                     base::FilePath /* patch_file */,
+                     base::FilePath /* output_file */)
+
+// Tell the utility process to patch the given |input_file| using |patch_file|
+// and place the output in |output_file|. The patch should use the Courgette
+// algorithm.
+IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_PatchFileCourgette,
+                     base::FilePath /* input_file */,
+                     base::FilePath /* patch_file */,
+                     base::FilePath /* output_file */)
+
 #if defined(OS_CHROMEOS)
 // Tell the utility process to create a zip file on the given list of files.
 IPC_MESSAGE_CONTROL3(ChromeUtilityMsg_CreateZipFile,
@@ -379,6 +406,13 @@
     printing::PrinterSemanticCapsAndDefaults)
 #endif
 
+// Reply when a file has been patched successfully.
+IPC_MESSAGE_CONTROL0(ChromeUtilityHostMsg_PatchFile_Succeeded)
+
+// Reply when patching a file failed.
+IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_PatchFile_Failed,
+                     int /* error code */)
+
 // Reply when the utility process has failed to obtain the printer
 // capabilities and defaults.
 IPC_MESSAGE_CONTROL1(ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed,
diff --git a/chrome/common/chrome_version_info_win.cc b/chrome/common/chrome_version_info_win.cc
index e540c2d..b52e51e 100644
--- a/chrome/common/chrome_version_info_win.cc
+++ b/chrome/common/chrome_version_info_win.cc
@@ -27,7 +27,7 @@
     GoogleUpdateSettings::GetChromeChannelAndModifiers(is_system_install,
                                                        &channel);
   }
-#if defined(ADDRESS_SANITIZER)
+#if defined(SYZYASAN)
   if (base::debug::IsBinaryInstrumented())
     channel += L" SyzyASan";
 #endif
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index 6515a26..dbe950e 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -9,6 +9,15 @@
 // type will require manually updating chrome/renderer/resources/dispatcher.cc.
 
 {
+  "accessibilityFeatures": [{
+    "platforms": ["chromeos"],
+    "dependencies": ["permission:accessibilityFeatures.modify"],
+    "contexts": ["blessed_extension"]
+  }, {
+    "platforms": ["chromeos"],
+    "dependencies": ["permission:accessibilityFeatures.read"],
+    "contexts": ["blessed_extension"]
+  }],
   "activityLogPrivate": {
     "dependencies": ["permission:activityLogPrivate"],
     "contexts": ["blessed_extension"]
@@ -464,26 +473,6 @@
     "dependencies": ["permission:mediaGalleries"],
     "contexts": ["blessed_extension"]
   },
-  "mediaGalleries.startMediaScan": {
-    "channel": "dev",
-    "dependencies": ["permission:mediaGalleries"],
-    "contexts": ["blessed_extension"]
-  },
-  "mediaGalleries.cancelMediaScan": {
-    "channel": "dev",
-    "dependencies": ["permission:mediaGalleries"],
-    "contexts": ["blessed_extension"]
-  },
-  "mediaGalleries.addScanResults": {
-    "channel": "dev",
-    "dependencies": ["permission:mediaGalleries"],
-    "contexts": ["blessed_extension"]
-  },
-  "mediaGalleries.onScanProgress": {
-    "channel": "dev",
-    "dependencies": ["permission:mediaGalleries"],
-    "contexts": ["blessed_extension"]
-  },
   "mediaGalleriesPrivate": {
     "dependencies": ["permission:mediaGalleriesPrivate"],
     "contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_manifest_features.json b/chrome/common/extensions/api/_manifest_features.json
index 4a7e7e1..670bed0 100644
--- a/chrome/common/extensions/api/_manifest_features.json
+++ b/chrome/common/extensions/api/_manifest_features.json
@@ -43,7 +43,7 @@
     "extension_types": ["legacy_packaged_app", "hosted_app"]
   },
   "app.service_worker": {
-    "channel": "trunk",
+    "channel": "trunk",  // When changing update tests: http://crbug.com/353209
     "extension_types": ["platform_app"]
   },
   "author": {
@@ -83,7 +83,7 @@
     "channel": "dev",
     "extension_types": ["extension"],
     "platforms": ["win"]
-  }, {  // TODO(wittman): remove this section for M36.
+  }, {  // TODO(wittman): remove this section for M37.
     "channel": "stable",
     "extension_types": ["extension"],
     "whitelist": [
@@ -198,7 +198,12 @@
       "extension_types": ["shared_module"],
       "whitelist": [
         "6EAED1924DB611B6EEF2A664BD077BE7EAD33B8F",
-        "4EB74897CB187C7633357C2FE832E0AD6A44883A"
+        "4EB74897CB187C7633357C2FE832E0AD6A44883A",
+        // Next four: http://crbug.com/357213
+        "mafeflapfdfljijmlienjedomfjfmhpd",
+        "ajchadodoajkaojdidnbblnfcdipbple",
+        "47F838F58D2A3B585DE50F29E3585D94999921D1",
+        "8EBAFB8DEB647EA2FC887A5E01EBD9BDC0FDC536"
       ]
     },
     {
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index a6224d4..751b945 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -15,6 +15,14 @@
 // hashes back to ids.
 
 {
+  "accessibilityFeatures.modify": {
+    "channel": "dev",
+    "extension_types": ["extension", "platform_app"]
+  },
+  "accessibilityFeatures.read": {
+    "channel": "dev",
+    "extension_types": ["extension", "platform_app"]
+  },
   "activeTab": {
     "channel": "stable",
     "extension_types": ["extension", "legacy_packaged_app"],
@@ -553,7 +561,7 @@
     "channel": "stable",
     "extension_types": [ "platform_app" ]
   },
-  // TODO(thestig) Remove this as part of http://crbug.com/144496
+  // TODO(thestig) Remove this as part of http://crbug.com/166950
   "mediaGalleriesPrivate": {
     "channel": "stable",
     "extension_types": [ "platform_app" ],
diff --git a/chrome/common/extensions/api/accessibility_features.json b/chrome/common/extensions/api/accessibility_features.json
new file mode 100644
index 0000000..495a0fb
--- /dev/null
+++ b/chrome/common/extensions/api/accessibility_features.json
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+[
+  {
+    "namespace": "accessibilityFeatures",
+    "platforms": ["chromeos"],
+    "description": "Use the <code>chrome.accessibilityFeatures</code> API to manage Chrome's accessibility features. This API relies on the <a href='types.html#ChromeSetting'>ChromeSetting prototype of the type API</a> for getting and setting individual accessibility features. In order to get feature states the extension must request <code>accessibilityFeatures.read</code> permission. For modifying feature state, the extension needs <code>accessibilityFeatures.modify</code> permission. Note that <code>accessibilityFeatures.modify</code> does not imply <code>accessibilityFeatures.read</code> permission.",
+    "properties": {
+      "spokenFeedback": {
+        "$ref": "types.ChromeSetting",
+        "description": "Spoken feedback (text-to-speech). The value indicates whether the feature is enabled or not. <code>get()</code> requires <code>accessibilityFeatures.read</code> permission. <code>set()</code> and <code>clear()</code> require <code>accessibilityFeatures.modify</code> permission.",
+        "value": ["spokenFeedback", {"type": "boolean"}]
+      },
+      "largeCursor": {
+        "$ref": "types.ChromeSetting",
+        "description": "Enlarged cursor. The value indicates whether the feature is enabled or not. <code>get()</code> requires <code>accessibilityFeatures.read</code> permission. <code>set()</code> and <code>clear()</code> require <code>accessibilityFeatures.modify</code> permission.",
+        "value": ["largeCursor", {"type": "boolean"}]
+      },
+      "stickyKeys": {
+        "$ref": "types.ChromeSetting",
+        "description": "Sticky modifier keys (like shift or alt). The value indicates whether the feature is enabled or not. <code>get()</code> requires <code>accessibilityFeatures.read</code> permission. <code>set()</code> and <code>clear()</code> require <code>accessibilityFeatures.modify</code> permission.",
+        "value": ["stickyKeys", {"type": "boolean"}]
+      },
+      "highContrast": {
+        "$ref": "types.ChromeSetting",
+        "description": "High contrast rendering mode. The value indicates whether the feature is enabled or not. <code>get()</code> requires <code>accessibilityFeatures.read</code> permission. <code>set()</code> and <code>clear()</code> require <code>accessibilityFeatures.modify</code> permission.",
+        "value": ["highContrast", {"type": "boolean"}]
+      },
+      "screenMagnifier": {
+        "$ref": "types.ChromeSetting",
+        "description": "Full screen magnification. The value indicates whether the feature is enabled or not. <code>get()</code> requires <code>accessibilityFeatures.read</code> permission. <code>set()</code> and <code>clear()</code> require <code>accessibilityFeatures.modify</code> permission.",
+        "value": ["screenMagnifier", {"type": "boolean"}]
+      },
+      "autoclick": {
+        "$ref": "types.ChromeSetting",
+        "description":"Auto mouse click after mouse stops moving. The value indicates whether the feature is enabled or not. <code>get()</code> requires <code>accessibilityFeatures.read</code> permission. <code>set()</code> and <code>clear()</code> require <code>accessibilityFeatures.modify</code> permission.",
+        "value": ["autoclick", {"type": "boolean"}]
+      },
+      "virtualKeyboard": {
+        "$ref": "types.ChromeSetting",
+        "description": "Virtual on-screen keyboard. The value indicates whether the feature is enabled or not. <code>get()</code> requires <code>accessibilityFeatures.read</code> permission. <code>set()</code> and <code>clear()</code> require <code>accessibilityFeatures.modify</code> permission.",
+        "value": ["virtualKeyboard", {"type": "boolean"}]
+      }
+    }
+  }
+]
diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp
index 3e1233f..fdfc3e7 100644
--- a/chrome/common/extensions/api/api.gyp
+++ b/chrome/common/extensions/api/api.gyp
@@ -59,7 +59,6 @@
               'desktop_capture.json',
               'developer_private.idl',
               'dial.idl',
-              'dns.idl',
               'downloads.idl',
               'downloads_internal.idl',
               'echo_private.json',
@@ -157,6 +156,7 @@
           }],
           ['chromeos==1', {
             'schema_files': [
+              'accessibility_features.json',
               'diagnostics.idl',
               'file_browser_handler_internal.json',
               'first_run_private.json',
diff --git a/chrome/common/extensions/api/browser_action.json b/chrome/common/extensions/api/browser_action.json
index e08851b..d7ff743 100644
--- a/chrome/common/extensions/api/browser_action.json
+++ b/chrome/common/extensions/api/browser_action.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "browserAction",
-    "description": "Use browser actions to put icons in the main Google Chrome toolbar, to the right of the address bar. In addition to its <a href='#icon'>icon</a>, a browser action can also have a <a href='#tooltip'>tooltip</a>, a <a href='#badge'>badge</a>, and a <a href = '#popups'>popup</a>.",
+    "description": "Use browser actions to put icons in the main Google Chrome toolbar, to the right of the address bar. In addition to its <a href='browserAction#icon'>icon</a>, a browser action can also have a <a href='browserAction#tooltip'>tooltip</a>, a <a href='browserAction#badge'>badge</a>, and a <a href='browserAction#popups'>popup</a>.",
     "types": [
       {
         "id": "ColorArray",
diff --git a/chrome/common/extensions/api/cast_streaming_rtp_stream.idl b/chrome/common/extensions/api/cast_streaming_rtp_stream.idl
index 2098bd3..0443b32 100644
--- a/chrome/common/extensions/api/cast_streaming_rtp_stream.idl
+++ b/chrome/common/extensions/api/cast_streaming_rtp_stream.idl
@@ -25,8 +25,10 @@
 
     long? clockRate;
 
+    // Minimum bitrate in kilobits per second.
     long? minBitrate;
 
+    // Maximum bitrate in kilobits per second.
     long? maxBitrate;
 
     // The number of channels.
diff --git a/chrome/common/extensions/api/dns.idl b/chrome/common/extensions/api/dns.idl
deleted file mode 100644
index f2da6b3..0000000
--- a/chrome/common/extensions/api/dns.idl
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Use the <code>chrome.dns</code> API for dns resolution.
-namespace dns {
-
-  dictionary ResolveCallbackResolveInfo {
-    // The result code. Zero indicates success.
-    long resultCode;
-
-    // A string representing the IP address literal. Supplied only if resultCode
-    // indicates success. Note that we presently return only IPv4 addresses.
-    DOMString? address;
-  };
-
-  callback ResolveCallback = void (ResolveCallbackResolveInfo resolveInfo);
-
-  interface Functions {
-    // Resolves the given hostname or IP address literal.
-    // |hostname| : The hostname to resolve.
-    // |callback| : Called when the resolution operation completes.
-    static void resolve(DOMString hostname,
-                        ResolveCallback callback);
-  };
-
-};
diff --git a/chrome/common/extensions/api/file_browser_private.idl b/chrome/common/extensions/api/file_browser_private.idl
index 4c1e7a8..ebd5e38 100644
--- a/chrome/common/extensions/api/file_browser_private.idl
+++ b/chrome/common/extensions/api/file_browser_private.idl
@@ -8,7 +8,8 @@
  implemented_in="chrome/browser/chromeos/extensions/file_manager/file_browser_private_api_functions.h"]
 namespace fileBrowserPrivate {
 // Type of the mounted volume.
-enum VolumeType { drive, downloads, removable, archive, cloud_device, testing };
+enum VolumeType { drive, downloads, removable, archive, cloud_device, provided,
+                  testing };
 
 // Device type. Available if this is removable volume.
 enum DeviceType { usb, sd, optical, mobile, unknown };
diff --git a/chrome/common/extensions/api/file_system_provider.idl b/chrome/common/extensions/api/file_system_provider.idl
index a3385aa..173a1c8 100644
--- a/chrome/common/extensions/api/file_system_provider.idl
+++ b/chrome/common/extensions/api/file_system_provider.idl
@@ -11,7 +11,7 @@
   // <code>fileSystemID</code> will be a unique ID for the file system just
   // mounted. The ID is used to distinguish multiple file systems mounted
   // from a single File System Provider.
-  callback MountCallback = void(DOMString fileSystemId,
+  callback MountCallback = void(long fileSystemId,
                                 [nodoc, instanceOf=DOMError] object error);
 
   // Callback to handle an error raised from the browser.
diff --git a/chrome/common/extensions/api/hotword_private.idl b/chrome/common/extensions/api/hotword_private.idl
index 1fa7bd13..7e1a60b 100644
--- a/chrome/common/extensions/api/hotword_private.idl
+++ b/chrome/common/extensions/api/hotword_private.idl
@@ -22,6 +22,10 @@
 
     // Whether the hotword extension is available to be enabled
     boolean available;
+
+    // Whether the sound of "Ok, Google" plus a few seconds before is sent
+    // back to Google.
+    boolean audioLoggingEnabled;
   };
 
   callback GenericDoneCallback = void ();
@@ -35,6 +39,10 @@
     // Retrieves the current state of hotword search.
     // The result is put into a StatusDetails object.
     static void getStatus(StatusDetailsCallback callback);
+
+    // Sets the current enabled state of audio logging in the extension.
+    // True: logging enabled. False: no logging.
+    static void setAudioLoggingEnabled(boolean state, optional GenericDoneCallback callback);
   };
 
   interface Events {
diff --git a/chrome/common/extensions/api/input_ime.json b/chrome/common/extensions/api/input_ime.json
index ab8c164..e682d40 100644
--- a/chrome/common/extensions/api/input_ime.json
+++ b/chrome/common/extensions/api/input_ime.json
@@ -195,7 +195,7 @@
             "type": "object",
             "properties": {
               "contextID": {
-                "description": "ID of the context where the key events will be sent",
+                "description": "ID of the context where the key events will be sent, or zero to send key events to non-input field.",
                 "type": "integer"
               },
               "keyData": {
diff --git a/chrome/common/extensions/api/manifest_types.json b/chrome/common/extensions/api/manifest_types.json
index b7767f4..d2e1af6 100644
--- a/chrome/common/extensions/api/manifest_types.json
+++ b/chrome/common/extensions/api/manifest_types.json
@@ -43,7 +43,7 @@
         "type": "object",
         "description": "Chrome settings which can be overriden by an extension.",
         "properties": {
-          // TODO(wittman): Remove for M36.
+          // TODO(wittman): Remove for M37.
           "bookmarks_ui": {
             "type": "object",
             "description": "Settings to permit bookmarks user interface customization by extensions.",
@@ -60,6 +60,12 @@
                 "description": "If <code>true</code>, the built-in \"Bookmark this page...\" shortcut key is removed and the extension is permitted to override the shortcut by binding it in the commands section of the manifest. The corresponding menu item is also removed or overridden as well.",
                 "optional": true
               },
+              "remove_bookmark_open_pages_shortcut": {
+                "type": "boolean",
+                "nodoc": true,
+                "description": "[Private] If <code>true</code>, the built-in \"Bookmark open pages...\" shortcut key and corresponding menu item is removed.",
+                "optional": true
+              },
               "hide_bookmark_button": {
                 "type": "boolean",
                 "description": "Deprecated. Use remove_button instead.",
@@ -171,6 +177,12 @@
                 "type": "boolean",
                 "description": "If <code>true</code>, the built-in \"Bookmark this page...\" shortcut key is removed and the extension is permitted to override the shortcut by binding it in the commands section of the manifest.",
                 "optional": true
+              },
+              "remove_bookmark_open_pages_shortcut": {
+                "type": "boolean",
+                "nodoc": true,
+                "description": "[Private] If <code>true</code>, the built-in \"Bookmark open pages...\" shortcut key and corresponding menu item is removed.",
+                "optional": true
               }
             }
           }
diff --git a/chrome/common/extensions/api/media_galleries_private.idl b/chrome/common/extensions/api/media_galleries_private.idl
index e04df52..64312a5 100644
--- a/chrome/common/extensions/api/media_galleries_private.idl
+++ b/chrome/common/extensions/api/media_galleries_private.idl
@@ -2,25 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// This is a private API since M23. This will be superceded by the
-// systeminfo.storage API in the future.
-// See http://crbug.com/166950 and http://crbug.com/177605.
+// This is a private API since M23. Gallery watching needs to be implemented
+// on platforms others than Windows and then moved to the public API.
+// See http://crbug.com/166950.
 namespace mediaGalleriesPrivate {
-  // A dictionary that describes an attached device.
-  [inline_doc] dictionary DeviceAttachmentDetails {
-    // The name of the device.
-    DOMString deviceName;
-
-    // A transient id that unique identifies the device.
-    DOMString deviceId;
-  };
-
-  // A dictionary that describes a detached device.
-  [inline_doc] dictionary DeviceDetachmentDetails {
-    // A transient id that unique identifies the device.
-    DOMString deviceId;
-  };
-
   // A dictionary that describes the modified gallery.
   [inline_doc] dictionary GalleryChangeDetails {
     // Gallery identifier.
@@ -28,12 +13,6 @@
   };
 
   interface Events {
-    // Fired when a media device gets attached.
-    static void onDeviceAttached(DeviceAttachmentDetails details);
-
-    // Fired when a media device gets detached.
-    static void onDeviceDetached(DeviceDetachmentDetails details);
-
     // Fired when a media gallery is changed.
     static void onGalleryChanged(GalleryChangeDetails details);
   };
diff --git a/chrome/common/extensions/api/messaging/message.h b/chrome/common/extensions/api/messaging/message.h
deleted file mode 100644
index 5a03224..0000000
--- a/chrome/common/extensions/api/messaging/message.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_API_MESSAGING_MESSAGE_H_
-#define CHROME_COMMON_EXTENSIONS_API_MESSAGING_MESSAGE_H_
-
-namespace extensions {
-
-// A message consists of both the data itself as well as a user  gestur e state.
-struct Message {
-  std::string data;
-  bool user_gesture;
-
-  Message() : data(), user_gesture(false) {}
-  Message(const std::string& data, bool user_gesture)
-      : data(data), user_gesture(user_gesture) {}
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_API_MESSAGING_MESSAGE_H_
diff --git a/chrome/common/extensions/api/metrics_private.json b/chrome/common/extensions/api/metrics_private.json
index d1ee679..28edefe 100644
--- a/chrome/common/extensions/api/metrics_private.json
+++ b/chrome/common/extensions/api/metrics_private.json
@@ -148,6 +148,15 @@
         ]
       },
       {
+        "name": "recordSparseValue",
+        "type": "function",
+        "description": "Increments the count associated with |value| in the sparse histogram defined by the |metricName|.",
+        "parameters": [
+          {"name": "metricName", "type": "string"},
+          {"name": "value", "type": "integer"}
+        ]
+      },
+      {
         "name": "recordValue",
         "type": "function",
         "description": "Adds a value to the given metric.",
diff --git a/chrome/common/extensions/api/permissions.json b/chrome/common/extensions/api/permissions.json
index e5a408f..a504746 100644
--- a/chrome/common/extensions/api/permissions.json
+++ b/chrome/common/extensions/api/permissions.json
@@ -5,7 +5,7 @@
 [
   {
     "namespace": "permissions",
-    "description": "Use the <code>chrome.permissions</code> API to request <a href=\"#manifest\">declared optional permissions</a> at run time rather than install time, so users understand why the permissions are needed and grant only those that are necessary.",
+    "description": "Use the <code>chrome.permissions</code> API to request <a href='permissions#manifest'>declared optional permissions</a> at run time rather than install time, so users understand why the permissions are needed and grant only those that are necessary.",
     "types": [
       {
         "id": "Permissions",
diff --git a/chrome/common/extensions/api/runtime.json b/chrome/common/extensions/api/runtime.json
index 00a8012..55704f1 100644
--- a/chrome/common/extensions/api/runtime.json
+++ b/chrome/common/extensions/api/runtime.json
@@ -113,7 +113,6 @@
       {
         "name": "setUninstallURL",
         "type": "function",
-        "unpriviledged": true,
         "description": "Sets the URL to be visited upon uninstallation. This may be used to clean up server-side data, do analytics, and implement surveys. Maximum 255 characters.",
         "parameters": [
           {
@@ -127,7 +126,6 @@
         "name": "reload",
         "description": "Reloads the app or extension.",
         "type": "function",
-        "nocompile": true,
         "parameters": []
       },
       {
@@ -165,7 +163,6 @@
         "name": "restart",
         "description": "Restart the ChromeOS device when the app runs in kiosk mode. Otherwise, it's no-op.",
         "type": "function",
-        "nocompile": true,
         "parameters": []
       },
       {
diff --git a/chrome/common/extensions/api/sockets/sockets_manifest_permission.h b/chrome/common/extensions/api/sockets/sockets_manifest_permission.h
index 92112c0..625cbeb 100644
--- a/chrome/common/extensions/api/sockets/sockets_manifest_permission.h
+++ b/chrome/common/extensions/api/sockets/sockets_manifest_permission.h
@@ -8,9 +8,9 @@
 #include <set>
 #include <vector>
 
-#include "chrome/common/extensions/permissions/socket_permission_entry.h"
 #include "extensions/common/install_warning.h"
 #include "extensions/common/permissions/manifest_permission.h"
+#include "extensions/common/permissions/socket_permission_entry.h"
 
 namespace content {
 struct SocketPermissionRequest;
diff --git a/chrome/common/extensions/api/streams_private.idl b/chrome/common/extensions/api/streams_private.idl
index e566def..2d3bada 100644
--- a/chrome/common/extensions/api/streams_private.idl
+++ b/chrome/common/extensions/api/streams_private.idl
@@ -22,8 +22,11 @@
     // information on the size it will be -1.
     long expectedContentSize;
 
-    // The HTTP response headers of the intercepted request.
-    DOMString responseHeaders;
+    // The HTTP response headers of the intercepted request stored as a
+    // dictionary mapping header name to header value. If a header name appears
+    // multiple times, the header values are merged in the dictionary and
+    // separated by a ", ".
+    object responseHeaders;
   };
 
   interface Events {
diff --git a/chrome/common/extensions/api/web_request.json b/chrome/common/extensions/api/web_request.json
index 51a161e..5d279c7 100644
--- a/chrome/common/extensions/api/web_request.json
+++ b/chrome/common/extensions/api/web_request.json
@@ -66,7 +66,7 @@
           "redirectUrl": {
             "type": "string",
             "optional": true,
-            "description": "Only used as a response to the onBeforeRequest event. If set, the original request is prevented from being sent and is instead redirected to the given URL."
+            "description": "Only used as a response to the onBeforeRequest and onHeadersReceived events. If set, the original request is prevented from being sent/completed and is instead redirected to the given URL. Redirections to non-HTTP schemes such as data: are allowed. Redirects initiated by a redirect action use the original request method for the redirect, with one exception: If the redirect is initiated at the onHeadersReceived stage, then the redirect will be issued using the GET method."
           },
           "requestHeaders": {
             "$ref": "HttpHeaders",
diff --git a/chrome/common/extensions/api/webstore.json b/chrome/common/extensions/api/webstore.json
index 31cbd2d..38d6de3 100644
--- a/chrome/common/extensions/api/webstore.json
+++ b/chrome/common/extensions/api/webstore.json
@@ -6,6 +6,40 @@
   {
     "namespace": "webstore",
     "description": "Use the <code>chrome.webstore</code> API to initiate app and extension installations \"inline\" from your site.",
+    "types": [
+      {
+        "id": "InstallStage",
+        "type": "string",
+        "enum": ["installing", "downloading"],
+        "description": "Enum used to indicate the stage of the installation process. 'downloading' indicates that the necessary files are being downloaded, and 'installing' indicates that the files are downloaded and are being actively installed."
+      }
+    ],  // types
+    "events": [
+      {
+        "name": "onInstallStageChanged",
+        "description": "Fired when an inline installation enters a new InstallStage. In order to receive notifications about this event, listeners must be registered before the inline installation begins.",
+        "type": "function",
+        "parameters": [
+          {
+            "name": "stage",
+            "$ref": "InstallStage",
+            "description": "The InstallStage that just began."
+          }
+        ]
+      },  // onInstallStageChanged
+      {
+        "name": "onDownloadProgress",
+        "description": "Fired periodically with the download progress of an inline install. In order to receive notifications about this event, listeners must be registered before the inline installation begins.",
+        "type": "function",
+        "parameters": [
+          {
+            "name": "percentDownloaded",
+            "type": "number",
+            "description": "The progress of the download, between 0 and 1. 0 indicates no progress; 1.0 indicates complete."
+          }
+        ]
+      }  // onDownloadProgress
+    ],  // events
     "functions": [
       {
         "name": "install",
@@ -39,6 +73,6 @@
           }
         ]
       }  // install
-    ]
+    ]  // functions
   }  // webstore
 ]
diff --git a/chrome/common/extensions/api/webstore/webstore_api_constants.cc b/chrome/common/extensions/api/webstore/webstore_api_constants.cc
new file mode 100644
index 0000000..e766bce
--- /dev/null
+++ b/chrome/common/extensions/api/webstore/webstore_api_constants.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/extensions/api/webstore/webstore_api_constants.h"
+
+namespace extensions {
+namespace api {
+namespace webstore {
+
+// The "downloading" stage begins when the installer starts downloading modules
+// for the extension.
+const char kInstallStageDownloading[] = "downloading";
+
+// The "installing" stage begins once all downloads are complete, and the
+// CrxInstaller begins.
+const char kInstallStageInstalling[] = "installing";
+
+// The method in custom_webstore_bindings.js triggered when we enter a new
+// install stage ("downloading" or "installing").
+const char kOnInstallStageChangedMethodName[] = "onInstallStageChanged";
+
+// The method in custom_webstore_bindings.js triggered when we update
+// download progress.
+const char kOnDownloadProgressMethodName[] = "onDownloadProgress";
+
+}  // namespace webstore
+}  // namespace api
+}  // namespace extensions
diff --git a/chrome/common/extensions/api/webstore/webstore_api_constants.h b/chrome/common/extensions/api/webstore/webstore_api_constants.h
new file mode 100644
index 0000000..445a57b
--- /dev/null
+++ b/chrome/common/extensions/api/webstore/webstore_api_constants.h
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_EXTENSIONS_API_WEBSTORE_WEBSTORE_API_CONSTANTS_H_
+#define CHROME_COMMON_EXTENSIONS_API_WEBSTORE_WEBSTORE_API_CONSTANTS_H_
+
+namespace extensions {
+namespace api {
+namespace webstore {
+
+// An enum for listener types. This is used when creating/reading the mask for
+// IPC messages.
+enum ListenerType {
+  INSTALL_STAGE_LISTENER = 1,
+  DOWNLOAD_PROGRESS_LISTENER = 1 << 1
+};
+
+// An enum to represent which stage the installation is in.
+enum InstallStage {
+  INSTALL_STAGE_DOWNLOADING = 0,
+  INSTALL_STAGE_INSTALLING,
+};
+
+extern const char kInstallStageDownloading[];
+extern const char kInstallStageInstalling[];
+extern const char kOnInstallStageChangedMethodName[];
+extern const char kOnDownloadProgressMethodName[];
+
+}  // namespace webstore
+}  // namespace api
+}  // namespace extensions
+
+#endif  // CHROME_COMMON_EXTENSIONS_API_WEBSTORE_WEBSTORE_API_CONSTANTS_H_
diff --git a/chrome/common/extensions/api/webview_tag.json b/chrome/common/extensions/api/webview_tag.json
index 1802e10..1b09cd9 100644
--- a/chrome/common/extensions/api/webview_tag.json
+++ b/chrome/common/extensions/api/webview_tag.json
@@ -8,7 +8,8 @@
     "description": "Use the <code>webview</code> tag to actively load live content from the web over the network and embed it in your Chrome App. Your app can control the appearance of the <code>webview</code> and interact with the web content, initiate navigations in an embedded web page, react to error events that happen within it, and more (see <a href=\"#usage\">Usage</a>).",
     "documentation_options": {
       "title": "<webview> Tag",
-      "namespace": "<webview>"
+      "namespace": "<webview>",
+      "documented_in": "tags/webview"
     },
     "types": [
       {
diff --git a/chrome/common/extensions/chrome_extension_messages.h b/chrome/common/extensions/chrome_extension_messages.h
index e25e901..2372412 100644
--- a/chrome/common/extensions/chrome_extension_messages.h
+++ b/chrome/common/extensions/chrome_extension_messages.h
@@ -8,11 +8,15 @@
 //
 // Multiply-included message file, hence no include guard.
 
+#include "chrome/common/extensions/api/webstore/webstore_api_constants.h"
 #include "chrome/common/web_application_info.h"
 #include "ipc/ipc_message_macros.h"
 
 #define IPC_MESSAGE_START ChromeExtensionMsgStart
 
+IPC_ENUM_TRAITS_MAX_VALUE(extensions::api::webstore::InstallStage,
+                          extensions::api::webstore::INSTALL_STAGE_INSTALLING)
+
 IPC_STRUCT_TRAITS_BEGIN(WebApplicationInfo::IconInfo)
   IPC_STRUCT_TRAITS_MEMBER(url)
   IPC_STRUCT_TRAITS_MEMBER(width)
@@ -34,6 +38,31 @@
 IPC_MESSAGE_ROUTED1(ChromeExtensionMsg_GetApplicationInfo,
                     int32 /* page_id */)
 
+// Sent by the renderer to implement chrome.webstore.install().
+IPC_MESSAGE_ROUTED5(ExtensionHostMsg_InlineWebstoreInstall,
+                    int32 /* install id */,
+                    int32 /* return route id */,
+                    std::string /* Web Store item ID */,
+                    GURL /* requestor URL */,
+                    int /* listeners_mask */)
+
+// Sent to the renderer if install stage updates were requested for an inline
+// install.
+IPC_MESSAGE_ROUTED1(ExtensionMsg_InlineInstallStageChanged,
+                    extensions::api::webstore::InstallStage /* stage */)
+
+// Sent to the renderer if download progress updates were requested for an
+// inline install.
+IPC_MESSAGE_ROUTED1(ExtensionMsg_InlineInstallDownloadProgress,
+                    int /* percent_downloaded */)
+
+// Send to renderer once the installation mentioned on
+// ExtensionHostMsg_InlineWebstoreInstall is complete.
+IPC_MESSAGE_ROUTED3(ExtensionMsg_InlineWebstoreInstallResponse,
+                    int32 /* install id */,
+                    bool /* whether the install was successful */,
+                    std::string /* error */)
+
 // Messages sent from the renderer to the browser.
 
 IPC_MESSAGE_ROUTED2(ChromeExtensionHostMsg_DidGetApplicationInfo,
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc
index c9b7c19..5d82845 100644
--- a/chrome/common/extensions/chrome_extensions_client.cc
+++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -144,10 +144,6 @@
   // TODO(erikkay): This seems like the wrong test.  Shouldn't we we testing
   // against the store app extent?
   GURL store_url(extension_urls::GetWebstoreLaunchURL());
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kAllowScriptingGallery)) {
-    return true;
-  }
   if (url.host() == store_url.host()) {
     if (error)
       *error = manifest_errors::kCannotScriptGallery;
diff --git a/chrome/common/extensions/command.cc b/chrome/common/extensions/command.cc
index 5ebf3fc..f3ddfb4 100644
--- a/chrome/common/extensions/command.cc
+++ b/chrome/common/extensions/command.cc
@@ -9,7 +9,6 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "base/values.h"
-#include "chrome/common/chrome_version_info.h"  // TODO(finnur): Remove.
 #include "extensions/common/error_utils.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/feature_switch.h"
@@ -448,8 +447,7 @@
 
   // Check if this is a global or a regular shortcut.
   bool global = false;
-  if (FeatureSwitch::global_commands()->IsEnabled() &&
-      chrome::VersionInfo::GetChannel() <= chrome::VersionInfo::CHANNEL_DEV)
+  if (FeatureSwitch::global_commands()->IsEnabled())
     command->GetBoolean(keys::kGlobal, &global);
 
   // Normalize the suggestions.
@@ -542,13 +540,8 @@
   extension_data->SetBoolean("global", global());
   extension_data->SetBoolean("extension_action", extension_action);
 
-  if (FeatureSwitch::global_commands()->IsEnabled()) {
-    // TODO(finnur): This is to make sure we don't show the config UI beyond
-    // dev and will be removed when we launch.
-    static bool stable_or_beta =
-        chrome::VersionInfo::GetChannel() >= chrome::VersionInfo::CHANNEL_BETA;
-    extension_data->SetBoolean("scope_ui_visible", !stable_or_beta);
-  }
+  if (FeatureSwitch::global_commands()->IsEnabled())
+    extension_data->SetBoolean("scope_ui_visible", true);
 
   return extension_data;
 }
diff --git a/chrome/common/extensions/docs/server2/api_data_source.py b/chrome/common/extensions/docs/server2/api_data_source.py
index 2f557d4..04a6eac 100644
--- a/chrome/common/extensions/docs/server2/api_data_source.py
+++ b/chrome/common/extensions/docs/server2/api_data_source.py
@@ -8,8 +8,7 @@
 import posixpath
 
 from environment import IsPreviewServer
-from extensions_paths import (
-    API_FEATURES, JSON_TEMPLATES, PRIVATE_TEMPLATES)
+from extensions_paths import JSON_TEMPLATES, PRIVATE_TEMPLATES
 import third_party.json_schema_compiler.json_parse as json_parse
 import third_party.json_schema_compiler.model as model
 from environment import IsPreviewServer
@@ -69,35 +68,26 @@
   def __init__(self,
                api_name,
                api_models,
-               ref_resolver,
                disable_refs,
                availability_finder,
                json_cache,
                template_cache,
+               features_bundle,
                event_byname_function):
-    self._ref_resolver = ref_resolver
     self._disable_refs = disable_refs
     self._availability_finder = availability_finder
     self._api_availabilities = json_cache.GetFromFile(
         posixpath.join(JSON_TEMPLATES, 'api_availabilities.json'))
     self._intro_tables = json_cache.GetFromFile(
         posixpath.join(JSON_TEMPLATES, 'intro_tables.json'))
-    self._api_features = json_cache.GetFromFile(API_FEATURES)
+    self._api_features = features_bundle.GetAPIFeatures()
     self._template_cache = template_cache
     self._event_byname_function = event_byname_function
     self._namespace = api_models.GetModel(api_name).Get()
 
-  def _FormatDescription(self, description):
-    if self._disable_refs:
-      return description
-    return self._ref_resolver.ResolveAllLinks(description,
-                                              namespace=self._namespace.name)
-
   def _GetLink(self, link):
-    if self._disable_refs:
-      type_name = link.split('.', 1)[-1]
-      return { 'href': '#type-%s' % type_name, 'text': link, 'name': link }
-    return self._ref_resolver.SafeGetLink(link, namespace=self._namespace.name)
+    ref = link if '.' in link else (self._namespace.name + '.' + link)
+    return { 'ref': ref, 'text': link, 'name': link }
 
   def ToDict(self):
     if self._namespace is None:
@@ -145,7 +135,7 @@
   def _GenerateType(self, type_):
     type_dict = {
       'name': type_.simple_name,
-      'description': self._FormatDescription(type_.description),
+      'description': type_.description,
       'properties': self._GenerateProperties(type_.properties),
       'functions': self._GenerateFunctions(type_.functions),
       'events': self._GenerateEvents(type_.events),
@@ -160,7 +150,7 @@
   def _GenerateFunction(self, function):
     function_dict = {
       'name': function.simple_name,
-      'description': self._FormatDescription(function.description),
+      'description': function.description,
       'callback': self._GenerateCallback(function.callback),
       'parameters': [],
       'returns': None,
@@ -190,7 +180,7 @@
   def _GenerateEvent(self, event):
     event_dict = {
       'name': event.simple_name,
-      'description': self._FormatDescription(event.description),
+      'description': event.description,
       'filters': [self._GenerateProperty(f) for f in event.filters],
       'conditions': [self._GetLink(condition)
                      for condition in event.conditions],
@@ -267,7 +257,7 @@
     property_dict = {
       'name': property_.simple_name,
       'optional': property_.optional,
-      'description': self._FormatDescription(property_.description),
+      'description': property_.description,
       'properties': self._GenerateProperties(type_.properties),
       'functions': self._GenerateFunctions(type_.functions),
       'parameters': [],
@@ -297,7 +287,7 @@
   def _GenerateCallbackProperty(self, callback):
     property_dict = {
       'name': callback.simple_name,
-      'description': self._FormatDescription(callback.description),
+      'description': callback.description,
       'optional': callback.optional,
       'is_callback': True,
       'id': _CreateId(callback, 'property'),
@@ -357,7 +347,7 @@
     return {
       'title': 'Description',
       'content': [
-        { 'text': self._FormatDescription(self._namespace.description) }
+        { 'text': self._namespace.description }
       ]
     }
 
@@ -386,21 +376,20 @@
     # Devtools aren't in _api_features. If we're dealing with devtools, bail.
     if 'devtools' in self._namespace.name:
       return []
-    feature = self._api_features.Get().get(self._namespace.name)
-    assert feature, ('"%s" not found in _api_features.json.'
-                     % self._namespace.name)
 
-    dependencies = feature.get('dependencies')
-    if dependencies is None:
+    api_feature = self._api_features.Get().get(self._namespace.name)
+    if not api_feature:
+      logging.error('"%s" not found in _api_features.json' %
+                    self._namespace.name)
       return []
 
-    def make_code_node(text):
-      return { 'class': 'code', 'text': text }
-
     permissions_content = []
     manifest_content = []
 
     def categorize_dependency(dependency):
+      def make_code_node(text):
+        return { 'class': 'code', 'text': text }
+
       context, name = dependency.split(':', 1)
       if context == 'permission':
         permissions_content.append(make_code_node('"%s"' % name))
@@ -412,10 +401,10 @@
         for transitive_dependency in transitive_dependencies:
           categorize_dependency(transitive_dependency)
       else:
-        raise ValueError('Unrecognized dependency for %s: %s' % (
-            self._namespace.name, context))
+        logging.error('Unrecognized dependency for %s: %s' %
+                      (self._namespace.name, context))
 
-    for dependency in dependencies:
+    for dependency in api_feature.get('dependencies', ()):
       categorize_dependency(dependency)
 
     dependency_rows = []
@@ -456,8 +445,7 @@
 
   def _AddCommonProperties(self, target, src):
     if src.deprecated is not None:
-      target['deprecated'] = self._FormatDescription(
-          src.deprecated)
+      target['deprecated'] = src.deprecated
     if (src.parent is not None and
         not isinstance(src.parent, model.Namespace)):
       target['parentName'] = src.parent.simple_name
@@ -487,18 +475,19 @@
                  file_system,
                  availability_finder,
                  api_models,
+                 features_bundle,
                  object_store_creator):
       self._json_cache = compiled_fs_factory.ForJson(file_system)
       self._template_cache = compiled_fs_factory.ForTemplates(file_system)
       self._availability_finder = availability_finder
       self._api_models = api_models
+      self._features_bundle = features_bundle
       self._model_cache_refs = object_store_creator.Create(
           APIDataSource, 'model-cache-refs')
       self._model_cache_no_refs = object_store_creator.Create(
           APIDataSource, 'model-cache-no-refs')
 
       # These must be set later via the SetFooDataSourceFactory methods.
-      self._ref_resolver_factory = None
       self._samples_data_source_factory = None
 
       # This caches the result of _LoadEventByName.
@@ -507,9 +496,6 @@
     def SetSamplesDataSourceFactory(self, samples_data_source_factory):
       self._samples_data_source_factory = samples_data_source_factory
 
-    def SetReferenceResolverFactory(self, ref_resolver_factory):
-      self._ref_resolver_factory = ref_resolver_factory
-
     def Create(self, request):
       '''Creates an APIDataSource.
       '''
@@ -546,11 +532,11 @@
       jsc_model = _JSCModel(
           api_name,
           self._api_models,
-          self._ref_resolver_factory.Create() if not disable_refs else None,
           disable_refs,
           self._availability_finder,
           self._json_cache,
           self._template_cache,
+          self._features_bundle,
           self._LoadEventByName).ToDict()
 
       self._GetModelCache(disable_refs).Set(api_name, jsc_model)
diff --git a/chrome/common/extensions/docs/server2/api_data_source_test.py b/chrome/common/extensions/docs/server2/api_data_source_test.py
index 47c4992b..9d0a537 100755
--- a/chrome/common/extensions/docs/server2/api_data_source_test.py
+++ b/chrome/common/extensions/docs/server2/api_data_source_test.py
@@ -13,10 +13,11 @@
                              _GetEventByNameFromEvents)
 from branch_utility import ChannelInfo
 from extensions_paths import CHROME_EXTENSIONS
+from fake_host_file_system_provider import FakeHostFileSystemProvider
+from features_bundle import FeaturesBundle
 from file_system import FileNotFoundError
 from future import Future
 from object_store_creator import ObjectStoreCreator
-from reference_resolver import ReferenceResolver
 from server_instance import ServerInstance
 from test_data.canned_data import (CANNED_API_FILE_SYSTEM_DATA, CANNED_BRANCHES)
 from test_data.api_data_source.canned_trunk_fs import CANNED_TRUNK_FS_DATA
@@ -41,19 +42,6 @@
     return ChannelInfo('stable', '396', 5)
 
 
-class _FakeHostFileSystemProvider(object):
-
-  def __init__(self, file_system_data):
-    self._file_system_data = file_system_data
-
-  def GetTrunk(self):
-    return self.GetBranch('trunk')
-
-  @memoize
-  def GetBranch(self, branch):
-    return TestFileSystem(self._file_system_data[str(branch)])
-
-
 class _FakeSamplesDataSource(object):
 
   def Create(self, request):
@@ -75,6 +63,12 @@
     return self._json[key]
 
 
+class _FakeNamespace(object):
+
+  def __init__(self):
+    self.documentation_options = {}
+
+
 class _FakeAPIModels(object):
 
   def __init__(self, names):
@@ -83,6 +77,9 @@
   def GetNames(self):
     return self._names
 
+  def GetModel(self, name):
+    return Future(value=_FakeNamespace())
+
 
 class _FakeTemplateCache(object):
 
@@ -97,13 +94,16 @@
 
     server_instance = ServerInstance.ForTest(
         TestFileSystem(CANNED_TRUNK_FS_DATA, relative_to=CHROME_EXTENSIONS))
-    self._json_cache = server_instance.compiled_fs_factory.ForJson(
-        server_instance.host_file_system_provider.GetTrunk())
+    file_system = server_instance.host_file_system_provider.GetTrunk()
+    self._json_cache = server_instance.compiled_fs_factory.ForJson(file_system)
+    self._features_bundle = FeaturesBundle(file_system,
+                                           server_instance.compiled_fs_factory,
+                                           server_instance.object_store_creator)
     self._api_models = server_instance.api_models
 
     # Used for testGetApiAvailability() so that valid-ish data is processed.
     server_instance = ServerInstance.ForTest(
-        file_system_provider=_FakeHostFileSystemProvider(
+        file_system_provider=FakeHostFileSystemProvider(
             CANNED_API_FILE_SYSTEM_DATA))
     self._avail_api_models = server_instance.api_models
     self._avail_json_cache = server_instance.compiled_fs_factory.ForJson(
@@ -114,23 +114,17 @@
     with open(os.path.join(self._base_path, filename), 'r') as f:
       return f.read()
 
-  def _CreateRefResolver(self, filename):
-    test_data = self._LoadJSON(filename)
-    return ReferenceResolver.Factory(_FakeAPIDataSource(test_data),
-                                     _FakeAPIModels(test_data),
-                                     ObjectStoreCreator.ForTest()).Create()
-
   def _LoadJSON(self, filename):
     return json.loads(self._ReadLocalFile(filename))
 
   def testCreateId(self):
     dict_ = _JSCModel('tester',
                       self._api_models,
-                      self._CreateRefResolver('test_file_data_source.json'),
                       False,
                       _FakeAvailabilityFinder(),
                       self._json_cache,
                       _FakeTemplateCache(),
+                      self._features_bundle,
                       None).ToDict()
     self.assertEquals('type-TypeA', dict_['types'][0]['id'])
     self.assertEquals('property-TypeA-b',
@@ -144,10 +138,10 @@
     dict_ = _JSCModel('tester',
                       self._api_models,
                       False,
-                      self._CreateRefResolver('test_file_data_source.json'),
                       _FakeAvailabilityFinder(),
                       self._json_cache,
                       _FakeTemplateCache(),
+                      self._features_bundle,
                       None).ToDict()
     self.assertEquals(expected_json, dict_)
 
@@ -156,27 +150,6 @@
     self.assertEquals('67', _FormatValue(67))
     self.assertEquals('234,567', _FormatValue(234567))
 
-  def testFormatDescription(self):
-    dict_ = _JSCModel('ref_test',
-                      self._api_models,
-                      self._CreateRefResolver('ref_test_data_source.json'),
-                      False,
-                      _FakeAvailabilityFinder(),
-                      self._json_cache,
-                      _FakeTemplateCache(),
-                      None).ToDict()
-    self.assertEquals(_MakeLink('ref_test.html#type-type2', 'type2'),
-                      _GetType(dict_, 'type1')['description'])
-    self.assertEquals(
-        'A %s, or %s' % (_MakeLink('ref_test.html#type-type3', 'type3'),
-                         _MakeLink('ref_test.html#type-type2', 'type2')),
-        _GetType(dict_, 'type2')['description'])
-    self.assertEquals(
-        '%s != %s' % (_MakeLink('other.html#type-type2', 'other.type2'),
-                      _MakeLink('ref_test.html#type-type2', 'type2')),
-        _GetType(dict_, 'type3')['description'])
-
-
   def testGetApiAvailability(self):
     api_availabilities = {
       'bluetooth': ChannelInfo('dev', CANNED_BRANCHES[28], 28),
@@ -189,22 +162,22 @@
     for api_name, availability in api_availabilities.iteritems():
       model = _JSCModel(api_name,
                         self._avail_api_models,
-                        None,
                         True,
                         self._avail_finder,
                         self._avail_json_cache,
                         _FakeTemplateCache(),
+                        self._features_bundle,
                         None)
       self.assertEquals(availability, model._GetApiAvailability())
 
   def testGetIntroList(self):
     model = _JSCModel('tester',
                       self._api_models,
-                      self._CreateRefResolver('test_file_data_source.json'),
                       False,
                       _FakeAvailabilityFinder(),
                       self._json_cache,
                       _FakeTemplateCache(),
+                      self._features_bundle,
                       None)
     expected_list = [
       { 'title': 'Description',
@@ -272,11 +245,11 @@
   def testAddRules(self):
     dict_ = _JSCModel('add_rules_tester',
                       self._api_models,
-                      self._CreateRefResolver('test_file_data_source.json'),
                       False,
                       _FakeAvailabilityFinder(),
                       self._json_cache,
                       _FakeTemplateCache(),
+                      self._features_bundle,
                       self._FakeLoadAddRulesSchema).ToDict()
 
     # Check that the first event has the addRulesFunction defined.
diff --git a/chrome/common/extensions/docs/server2/api_list_data_source.py b/chrome/common/extensions/docs/server2/api_list_data_source.py
index 22f4f33..04c4b35 100644
--- a/chrome/common/extensions/docs/server2/api_list_data_source.py
+++ b/chrome/common/extensions/docs/server2/api_list_data_source.py
@@ -2,11 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from data_source import DataSource
+from future import Future
 from operator import itemgetter
 
 import docs_server_utils as utils
 
-class APIListDataSource(object):
+class APIListDataSource(DataSource):
   """ This class creates a list of chrome.* APIs and chrome.experimental.* APIs
   for extensions and apps that are used in the api_index.html,
   experimental.html, and private_apis.html pages.
@@ -21,92 +23,82 @@
       "extension_types" property where either/both "extension"/"platform_app"
       values are present.
   """
-  class Factory(object):
-    def __init__(self,
-                 compiled_fs_factory,
-                 file_system,
-                 features_bundle,
-                 object_store_creator,
-                 api_models,
-                 availability_finder,
-                 api_categorizer):
-      self._file_system = file_system
-      self._features_bundle = features_bundle
-      self._api_categorizer = api_categorizer
-      self._object_store_creator = object_store_creator
-      self._api_models = api_models
-      self._availability_finder = availability_finder
+  def __init__(self, server_instance, _):
+    self._features_bundle = server_instance.features_bundle
+    self._object_store = server_instance.object_store_creator.Create(
+        APIListDataSource)
+    self._api_models = server_instance.api_models
+    self._api_categorizer = server_instance.api_categorizer
+    self._availability_finder = server_instance.availability_finder
 
-    def _GenerateAPIDict(self):
+  def _GenerateAPIDict(self):
+    def get_channel_info(api_name):
+      return self._availability_finder.GetApiAvailability(api_name)
 
-      def _GetChannelInfo(api_name):
-        return self._availability_finder.GetApiAvailability(api_name)
+    def get_api_platform(api_name):
+      feature = self._features_bundle.GetAPIFeatures().Get()[api_name]
+      return feature['platforms']
 
-      def _GetApiPlatform(api_name):
-        feature = self._features_bundle.GetAPIFeatures().Get()[api_name]
-        return feature['platforms']
-
-      def _MakeDictForPlatform(platform):
-        platform_dict = {
-          'chrome': {'stable': [], 'beta': [], 'dev': [], 'trunk': []},
-        }
-        private_apis = []
-        experimental_apis = []
-        all_apis = []
-        for api_name, api_model in self._api_models.IterModels():
-          if not self._api_categorizer.IsDocumented(platform, api_name):
-            continue
-          api = {
-            'name': api_name,
-            'description': api_model.description,
-            'platforms': _GetApiPlatform(api_name),
-          }
-          category = self._api_categorizer.GetCategory(platform, api_name)
-          if category == 'chrome':
-            channel_info = _GetChannelInfo(api_name)
-            channel = channel_info.channel
-            if channel == 'stable':
-              version = channel_info.version
-              api['version'] = version
-            platform_dict[category][channel].append(api)
-            all_apis.append(api)
-          elif category == 'experimental':
-            experimental_apis.append(api)
-            all_apis.append(api)
-          elif category == 'private':
-            private_apis.append(api)
-
-        for channel, apis_by_channel in platform_dict['chrome'].iteritems():
-          apis_by_channel.sort(key=itemgetter('name'))
-          utils.MarkLast(apis_by_channel)
-          platform_dict['chrome'][channel] = apis_by_channel
-
-        for key, apis in (('all', all_apis),
-                          ('private', private_apis),
-                          ('experimental', experimental_apis)):
-          apis.sort(key=itemgetter('name'))
-          utils.MarkLast(apis)
-          platform_dict[key] = apis
-
-        return platform_dict
-      return {
-        'apps': _MakeDictForPlatform('apps'),
-        'extensions': _MakeDictForPlatform('extensions'),
+    def make_dict_for_platform(platform):
+      platform_dict = {
+        'chrome': {'stable': [], 'beta': [], 'dev': [], 'trunk': []},
       }
+      private_apis = []
+      experimental_apis = []
+      all_apis = []
+      for api_name, api_model in self._api_models.IterModels():
+        if not self._api_categorizer.IsDocumented(platform, api_name):
+          continue
+        api = {
+          'name': api_name,
+          'description': api_model.description,
+          'platforms': get_api_platform(api_name),
+        }
+        category = self._api_categorizer.GetCategory(platform, api_name)
+        if category == 'chrome':
+          channel_info = get_channel_info(api_name)
+          channel = channel_info.channel
+          if channel == 'stable':
+            version = channel_info.version
+            api['version'] = version
+          platform_dict[category][channel].append(api)
+          all_apis.append(api)
+        elif category == 'experimental':
+          experimental_apis.append(api)
+          all_apis.append(api)
+        elif category == 'private':
+          private_apis.append(api)
 
-    def Create(self):
-      return APIListDataSource(self, self._object_store_creator)
+      for channel, apis_by_channel in platform_dict['chrome'].iteritems():
+        apis_by_channel.sort(key=itemgetter('name'))
+        utils.MarkLast(apis_by_channel)
+        platform_dict['chrome'][channel] = apis_by_channel
 
-  def __init__(self, factory, object_store_creator):
-    self._factory = factory
-    self._object_store = object_store_creator.Create(APIListDataSource)
+      for key, apis in (('all', all_apis),
+                        ('private', private_apis),
+                        ('experimental', experimental_apis)):
+        apis.sort(key=itemgetter('name'))
+        utils.MarkLast(apis)
+        platform_dict[key] = apis
+
+      return platform_dict
+    return {
+      'apps': make_dict_for_platform('apps'),
+      'extensions': make_dict_for_platform('extensions'),
+    }
 
   def _GetCachedAPIData(self):
-    data = self._object_store.Get('api_data').Get()
-    if data is None:
-      data = self._factory._GenerateAPIDict()
-      self._object_store.Set('api_data', data)
-    return data
+    data_future = self._object_store.Get('api_data')
+    def resolve():
+      data = data_future.Get()
+      if data is None:
+        data = self._GenerateAPIDict()
+        self._object_store.Set('api_data', data)
+      return data
+    return Future(callback=resolve)
 
   def get(self, key):
-    return self._GetCachedAPIData().get(key)
+    return self._GetCachedAPIData().Get().get(key)
+
+  def Cron(self):
+    return self._GetCachedAPIData()
diff --git a/chrome/common/extensions/docs/server2/api_list_data_source_test.py b/chrome/common/extensions/docs/server2/api_list_data_source_test.py
index 8964d50..44523a5 100755
--- a/chrome/common/extensions/docs/server2/api_list_data_source_test.py
+++ b/chrome/common/extensions/docs/server2/api_list_data_source_test.py
@@ -131,18 +131,12 @@
   def setUp(self):
     server_instance = ServerInstance.ForTest(
         TestFileSystem(_TEST_DATA, relative_to=CHROME_EXTENSIONS))
-    self._factory = APIListDataSource.Factory(
-        server_instance.compiled_fs_factory,
-        server_instance.host_file_system_provider.GetTrunk(),
-        server_instance.features_bundle,
-        server_instance.object_store_creator,
-        server_instance.api_models,
-        server_instance.availability_finder,
-        server_instance.api_categorizer)
+    # APIListDataSource takes a request but doesn't use it,
+    # so put None
+    self._api_list = APIListDataSource(server_instance, None)
     self.maxDiff = None
 
   def testApps(self):
-    api_list = self._factory.Create()
     self.assertEqual({
         'stable': [
           {
@@ -176,10 +170,9 @@
           }],
         'beta': [],
         'trunk': []
-        }, api_list.get('apps').get('chrome'))
+        }, self._api_list.get('apps').get('chrome'))
 
   def testExperimentalApps(self):
-    api_list = self._factory.Create()
     self.assertEqual([
         {
           'name': 'experimental.bluetooth',
@@ -191,10 +184,9 @@
           'platforms': ['apps', 'extensions'],
           'last': True,
           'description': u'<code>experimental.power</code>'
-        }], api_list.get('apps').get('experimental'))
+        }], self._api_list.get('apps').get('experimental'))
 
   def testExtensions(self):
-    api_list = self._factory.Create()
     self.assertEqual({
         'stable': [
           {
@@ -232,10 +224,9 @@
           }],
         'beta': [],
         'trunk': []
-        }, api_list.get('extensions').get('chrome'))
+        }, self._api_list.get('extensions').get('chrome'))
 
   def testExperimentalExtensions(self):
-    api_list = self._factory.Create()
     self.assertEqual([
         {
           'name': 'experimental.history',
@@ -247,7 +238,7 @@
           'platforms': ['apps', 'extensions'],
           'description': u'<code>experimental.power</code>',
           'last': True
-        }], api_list.get('extensions').get('experimental'))
+        }], self._api_list.get('extensions').get('experimental'))
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/chrome/common/extensions/docs/server2/api_models.py b/chrome/common/extensions/docs/server2/api_models.py
index 2f06d75..d7cacc4 100644
--- a/chrome/common/extensions/docs/server2/api_models.py
+++ b/chrome/common/extensions/docs/server2/api_models.py
@@ -5,9 +5,9 @@
 import posixpath
 
 from compiled_file_system import SingleFile, Unicode
-from extensions_paths import API, CHROME_API
+from extensions_paths import API_PATHS
 from file_system import FileNotFoundError
-from future import Gettable, Future
+from future import Future
 from schema_util import ProcessSchema
 from third_party.json_schema_compiler.model import Namespace, UnixName
 
@@ -44,7 +44,7 @@
     # By default |api_name| is assumed to be given without a path or extension,
     # so combinations of known paths and extension types will be searched.
     api_extensions = ('.json', '.idl')
-    api_paths = (API, CHROME_API)
+    api_paths = API_PATHS
 
     # Callers sometimes include a file extension and/or prefix path with the
     # |api_name| argument. We believe them and narrow the search space
@@ -81,7 +81,7 @@
         except FileNotFoundError: pass
       # Propagate the first FileNotFoundError if neither were found.
       futures[0].Get()
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def IterModels(self):
     future_models = [(name, self.GetModel(name)) for name in self.GetNames()]
diff --git a/chrome/common/extensions/docs/server2/api_models_test.py b/chrome/common/extensions/docs/server2/api_models_test.py
index 1d2a4c1..305f4e7 100755
--- a/chrome/common/extensions/docs/server2/api_models_test.py
+++ b/chrome/common/extensions/docs/server2/api_models_test.py
@@ -8,7 +8,7 @@
 
 from api_models import APIModels
 from compiled_file_system import CompiledFileSystem
-from extensions_paths import CHROME_API, CHROME_EXTENSIONS
+from extensions_paths import API_PATHS, CHROME_API, CHROME_EXTENSIONS
 from features_bundle import FeaturesBundle
 from file_system import FileNotFoundError
 from mock_file_system import MockFileSystem
@@ -128,11 +128,11 @@
                                                 'storage.idl').Get)
 
   def testSingleFile(self):
-    # 4 stats (1 for JSON and 1 for IDL, in both possible API path),
+    # 2 stats (1 for JSON and 1 for IDL) for each available API path.
     # 1 read (for IDL file which existed).
     future = self._api_models.GetModel('alarms')
     self.assertTrue(*self._mock_file_system.CheckAndReset(
-        read_count=1, stat_count=4))
+        read_count=1, stat_count=len(API_PATHS)*2))
 
     # 1 read-resolve (for the IDL file).
     #
@@ -143,10 +143,11 @@
     self.assertTrue(*self._mock_file_system.CheckAndReset(
         read_resolve_count=1))
 
-    # 4 stats (1 for JSON and 1 for IDL, in both possible API paths)
-    # no reads (still cached).
+    # 2 stats (1 for JSON and 1 for IDL) for each available API path.
+    # No reads (still cached).
     future = self._api_models.GetModel('alarms')
-    self.assertTrue(*self._mock_file_system.CheckAndReset(stat_count=4))
+    self.assertTrue(*self._mock_file_system.CheckAndReset(
+        stat_count=len(API_PATHS)*2))
     future.Get()
     self.assertTrue(*self._mock_file_system.CheckAndReset())
 
diff --git a/chrome/common/extensions/docs/server2/app.yaml b/chrome/common/extensions/docs/server2/app.yaml
index fc83781..db123ac 100644
--- a/chrome/common/extensions/docs/server2/app.yaml
+++ b/chrome/common/extensions/docs/server2/app.yaml
@@ -1,5 +1,5 @@
 application: chrome-apps-doc
-version: 3-14-0
+version: 3-16-0
 runtime: python27
 api_version: 1
 threadsafe: false
diff --git a/chrome/common/extensions/docs/server2/appengine_url_fetcher.py b/chrome/common/extensions/docs/server2/appengine_url_fetcher.py
index 9949678..12894f5 100644
--- a/chrome/common/extensions/docs/server2/appengine_url_fetcher.py
+++ b/chrome/common/extensions/docs/server2/appengine_url_fetcher.py
@@ -9,14 +9,6 @@
 from future import Future
 
 
-class _AsyncFetchDelegate(object):
-  def __init__(self, rpc):
-    self._rpc = rpc
-
-  def Get(self):
-    return self._rpc.get_result()
-
-
 def _MakeHeaders(username, password):
   headers = {
     'User-Agent': 'Chromium docserver %s' % GetAppVersion(),
@@ -49,7 +41,7 @@
     urlfetch.make_fetch_call(rpc,
                              self._FromBasePath(url),
                              headers=_MakeHeaders(username, password))
-    return Future(delegate=_AsyncFetchDelegate(rpc))
+    return Future(callback=lambda: rpc.get_result())
 
   def _FromBasePath(self, url):
     assert not url.startswith('/'), url
diff --git a/chrome/common/extensions/docs/server2/availability_finder.py b/chrome/common/extensions/docs/server2/availability_finder.py
index 24d594b..a2d2fa9 100644
--- a/chrome/common/extensions/docs/server2/availability_finder.py
+++ b/chrome/common/extensions/docs/server2/availability_finder.py
@@ -7,10 +7,11 @@
 
 from api_schema_graph import APISchemaGraph
 from branch_utility import BranchUtility
-from extensions_paths import (
-    API, CHROME_API, JSON_TEMPLATES, API_FEATURES, MANIFEST_FEATURES,
-    PERMISSION_FEATURES)
+from extensions_paths import API_PATHS, JSON_TEMPLATES
+from features_bundle import FeaturesBundle
+import features_utility
 from file_system import FileNotFoundError
+from third_party.json_schema_compiler.memoize import memoize
 from third_party.json_schema_compiler.model import UnixName
 
 
@@ -27,34 +28,12 @@
 _SVN_MIN_VERSION = 5
 
 
-def _GetChannelFromFeatures(api_name, json_fs, filename):
-  '''Finds API channel information from the features |filename| within the the
-  given |json_fs|. Returns None if channel information for the API cannot be
-  located.
+def _GetChannelFromFeatures(api_name, features):
+  '''Finds API channel information for |api_name| from |features|.
+  Returns None if channel information for the API cannot be located.
   '''
-  feature = json_fs.GetFromFile(filename).Get().get(api_name)
-  if feature is None:
-    return None
-  if isinstance(feature, Mapping):
-    # The channel information exists as a solitary dict.
-    return feature.get('channel')
-  # The channel information dict is nested within a list for whitelisting
-  # purposes. Take the newest channel out of all of the entries.
-  return BranchUtility.NewestChannel(entry.get('channel') for entry in feature)
-
-
-def _GetChannelFromApiFeatures(api_name, json_fs):
-  return _GetChannelFromFeatures(api_name, json_fs, API_FEATURES)
-
-
-def _GetChannelFromManifestFeatures(api_name, json_fs):
-  # _manifest_features.json uses unix_style API names.
-  api_name = UnixName(api_name)
-  return _GetChannelFromFeatures(api_name, json_fs, MANIFEST_FEATURES)
-
-
-def _GetChannelFromPermissionFeatures(api_name, json_fs):
-  return _GetChannelFromFeatures(api_name, json_fs, PERMISSION_FEATURES)
+  feature = features.Get().get(api_name)
+  return feature.get('channel') if feature else None
 
 
 class AvailabilityFinder(object):
@@ -103,7 +82,7 @@
       api_name = UnixName(api_name)
 
     futures = [(path, file_system.ReadSingle(path))
-               for path in (API, CHROME_API)]
+               for path in API_PATHS]
     for path, future in futures:
       try:
         filenames = future.Get()
@@ -154,19 +133,21 @@
     if version < _SVN_MIN_VERSION:
       # SVN data isn't available below this version.
       return False
+    features_bundle = self._CreateFeaturesBundle(file_system)
     available_channel = None
-    json_fs = self._compiled_fs_factory.ForJson(file_system)
     if version >= _API_FEATURES_MIN_VERSION:
       # The _api_features.json file first appears in version 28 and should be
       # the most reliable for finding API availability.
-      available_channel = _GetChannelFromApiFeatures(api_name, json_fs)
+      available_channel = self._GetChannelFromApiFeatures(api_name,
+                                                          features_bundle)
     if version >= _ORIGINAL_FEATURES_MIN_VERSION:
       # The _permission_features.json and _manifest_features.json files are
       # present in Chrome 20 and onwards. Use these if no information could be
       # found using _api_features.json.
-      available_channel = available_channel or (
-          _GetChannelFromPermissionFeatures(api_name, json_fs)
-          or _GetChannelFromManifestFeatures(api_name, json_fs))
+      available_channel = (
+          available_channel or
+          self._GetChannelFromPermissionFeatures(api_name, features_bundle) or
+          self._GetChannelFromManifestFeatures(api_name, features_bundle))
       if available_channel is not None:
         return available_channel == 'stable'
     if version >= _SVN_MIN_VERSION:
@@ -180,10 +161,11 @@
     back to checking the file system for API schema existence, to determine
     whether or not an API is available on the given channel, |channel_info|.
     '''
-    json_fs = self._compiled_fs_factory.ForJson(file_system)
-    available_channel = (_GetChannelFromApiFeatures(api_name, json_fs)
-        or _GetChannelFromPermissionFeatures(api_name, json_fs)
-        or _GetChannelFromManifestFeatures(api_name, json_fs))
+    features_bundle = self._CreateFeaturesBundle(file_system)
+    available_channel = (
+        self._GetChannelFromApiFeatures(api_name, features_bundle) or
+        self._GetChannelFromPermissionFeatures(api_name, features_bundle) or
+        self._GetChannelFromManifestFeatures(api_name, features_bundle))
     if (available_channel is None and
         self._HasApiSchema(api_name, file_system, channel_info.version)):
       # If an API is not represented in any of the _features files, but exists
@@ -196,6 +178,25 @@
                                           channel_info.channel))
     return available_channel is not None and newest == channel_info.channel
 
+  @memoize
+  def _CreateFeaturesBundle(self, file_system):
+    return FeaturesBundle(file_system,
+                          self._compiled_fs_factory,
+                          self._object_store_creator)
+
+  def _GetChannelFromApiFeatures(self, api_name, features_bundle):
+    return _GetChannelFromFeatures(api_name, features_bundle.GetAPIFeatures())
+
+  def _GetChannelFromManifestFeatures(self, api_name, features_bundle):
+    # _manifest_features.json uses unix_style API names.
+    api_name = UnixName(api_name)
+    return _GetChannelFromFeatures(api_name,
+                                   features_bundle.GetManifestFeatures())
+
+  def _GetChannelFromPermissionFeatures(self, api_name, features_bundle):
+    return _GetChannelFromFeatures(api_name,
+                                   features_bundle.GetPermissionFeatures())
+
   def _CheckApiAvailability(self, api_name, file_system, channel_info):
     '''Determines the availability for an API at a certain version of Chrome.
     Two branches of logic are used depending on whether or not the API is
diff --git a/chrome/common/extensions/docs/server2/cache_chain_object_store.py b/chrome/common/extensions/docs/server2/cache_chain_object_store.py
index 5f0a379..6741d5f 100644
--- a/chrome/common/extensions/docs/server2/cache_chain_object_store.py
+++ b/chrome/common/extensions/docs/server2/cache_chain_object_store.py
@@ -5,55 +5,6 @@
 from future import Future
 from object_store import ObjectStore
 
-class _GetMultiFuture(object):
-  '''A Future for GetMulti.
-
-  Params:
-  - |toplevel_cache| CacheChainObjectStore's cache.
-  - |object_store_futures| a list of (object store, future) pairs, where future
-    is the result of calling GetMulti on the missing keys for the object store.
-  - |cached_items| a mapping of cache items already in memory.
-  - |missing_keys| the keys that were missing from the GetMulti call
-  '''
-  def __init__(self,
-               toplevel_cache,
-               object_store_futures,
-               cached_items,
-               missing_keys):
-    self._toplevel_cache = toplevel_cache
-    self._object_store_futures = object_store_futures
-    self._results_so_far = cached_items
-    self._missing_keys = missing_keys
-
-  def Get(self):
-    # Approach:
-    #
-    # Try each object store in order, until there are no more missing keys.
-    # Don't realise the Future value of an object store that we don't need to;
-    # this is important e.g. to avoid querying data store constantly.
-    #
-    # When a value is found, cache it in all object stores further up the
-    # chain, including the object-based cache on CacheChainObjectStore.
-    object_store_updates = []
-    for object_store, object_store_future in self._object_store_futures:
-      if len(self._missing_keys) == 0:
-        break
-      result = object_store_future.Get()
-      for k, v in result.items():  # use items(); changes during iteration
-        if v is None or k not in self._missing_keys:
-          del result[k]
-          continue
-        self._toplevel_cache[k] = v
-        self._results_so_far[k] = v
-        self._missing_keys.remove(k)
-      for _, updates in object_store_updates:
-        updates.update(result)
-      object_store_updates.append((object_store, {}))
-    # Update the caches of all object stores that need it.
-    for object_store, updates in object_store_updates:
-      if updates:
-        object_store.SetMulti(updates)
-    return self._results_so_far
 
 class CacheChainObjectStore(ObjectStore):
   '''Maintains an in-memory cache along with a chain of other object stores to
@@ -92,8 +43,36 @@
       return Future(value=cached_items)
     object_store_futures = [(object_store, object_store.GetMulti(missing_keys))
                             for object_store in self._object_stores]
-    return Future(delegate=_GetMultiFuture(
-        self._cache, object_store_futures, cached_items, missing_keys))
+    def resolve():
+      # Approach:
+      #
+      # Try each object store in order, until there are no more missing keys.
+      # Don't realise the Future value of an object store that we don't need to;
+      # this is important e.g. to avoid querying data store constantly.
+      #
+      # When a value is found, cache it in all object stores further up the
+      # chain, including the object-based cache on CacheChainObjectStore.
+      object_store_updates = []
+      for object_store, object_store_future in object_store_futures:
+        if len(missing_keys) == 0:
+          break
+        result = object_store_future.Get()
+        for k, v in result.items():  # use items(); changes during iteration
+          if v is None or k not in missing_keys:
+            del result[k]
+            continue
+          self._cache[k] = v
+          cached_items[k] = v
+          missing_keys.remove(k)
+        for _, updates in object_store_updates:
+          updates.update(result)
+        object_store_updates.append((object_store, {}))
+      # Update the caches of all object stores that need it.
+      for object_store, updates in object_store_updates:
+        if updates:
+          object_store.SetMulti(updates)
+      return cached_items
+    return Future(callback=resolve)
 
   def DelMulti(self, keys):
     for k in keys:
diff --git a/chrome/common/extensions/docs/server2/caching_file_system.py b/chrome/common/extensions/docs/server2/caching_file_system.py
index 3c082f5..18217a4 100644
--- a/chrome/common/extensions/docs/server2/caching_file_system.py
+++ b/chrome/common/extensions/docs/server2/caching_file_system.py
@@ -9,29 +9,6 @@
 from future import Future
 
 
-class _AsyncUncachedFuture(object):
-  def __init__(self,
-               uncached_read_futures,
-               stats_for_uncached,
-               current_results,
-               file_system,
-               object_store):
-    self._uncached_read_futures = uncached_read_futures
-    self._stats_for_uncached = stats_for_uncached
-    self._current_results = current_results
-    self._file_system = file_system
-    self._object_store = object_store
-
-  def Get(self):
-    new_results = self._uncached_read_futures.Get()
-    # Update the cached data in the object store. This is a path -> (read,
-    # version) mapping.
-    self._object_store.SetMulti(dict(
-        (path, (new_result, self._stats_for_uncached[path].version))
-        for path, new_result in new_results.iteritems()))
-    new_results.update(self._current_results)
-    return new_results
-
 class CachingFileSystem(FileSystem):
   '''FileSystem which implements a caching layer on top of |file_system|. It's
   smart, using Stat() to decided whether to skip Read()ing from |file_system|,
@@ -111,12 +88,17 @@
     if not uncached:
       return Future(value=results)
 
-    return Future(delegate=_AsyncUncachedFuture(
-        self._file_system.Read(uncached.keys()),
-        uncached,
-        results,
-        self,
-        self._read_object_store))
+    uncached_read_futures = self._file_system.Read(uncached.keys())
+    def resolve():
+      new_results = uncached_read_futures.Get()
+      # Update the cached data in the object store. This is a path -> (read,
+      # version) mapping.
+      self._read_object_store.SetMulti(dict(
+          (path, (new_result, uncached[path].version))
+          for path, new_result in new_results.iteritems()))
+      new_results.update(results)
+      return new_results
+    return Future(callback=resolve)
 
   def GetIdentity(self):
     return self._file_system.GetIdentity()
diff --git a/chrome/common/extensions/docs/server2/chained_compiled_file_system.py b/chrome/common/extensions/docs/server2/chained_compiled_file_system.py
index be87de9..c8b3f1c 100644
--- a/chrome/common/extensions/docs/server2/chained_compiled_file_system.py
+++ b/chrome/common/extensions/docs/server2/chained_compiled_file_system.py
@@ -4,7 +4,7 @@
 
 from compiled_file_system import CompiledFileSystem
 from file_system import FileNotFoundError
-from future import Gettable, Future
+from future import Future
 
 
 class ChainedCompiledFileSystem(object):
@@ -82,4 +82,4 @@
       # Try an arbitrary operation again to generate a realistic stack trace.
       return read_futures[0][0].Get()
 
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
diff --git a/chrome/common/extensions/docs/server2/chroot_file_system.py b/chrome/common/extensions/docs/server2/chroot_file_system.py
index 950aa39..2feae00 100644
--- a/chrome/common/extensions/docs/server2/chroot_file_system.py
+++ b/chrome/common/extensions/docs/server2/chroot_file_system.py
@@ -6,7 +6,7 @@
 
 from docs_server_utils import StringIdentity
 from file_system import FileSystem
-from future import Gettable, Future
+from future import Future
 
 
 class ChrootFileSystem(FileSystem):
@@ -37,7 +37,7 @@
     def resolve():
       return dict((prefixed_paths[path], content)
                   for path, content in future_result.Get().iteritems())
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Refresh(self):
     return self._file_system.Refresh()
diff --git a/chrome/common/extensions/docs/server2/compiled_file_system.py b/chrome/common/extensions/docs/server2/compiled_file_system.py
index e80882a..beba804 100644
--- a/chrome/common/extensions/docs/server2/compiled_file_system.py
+++ b/chrome/common/extensions/docs/server2/compiled_file_system.py
@@ -7,7 +7,7 @@
 import schema_util
 from docs_server_utils import ToUnicode
 from file_system import FileNotFoundError
-from future import Gettable, Future
+from future import Future
 from path_util import AssertIsDirectory, AssertIsFile
 from third_party.handlebar import Handlebar
 from third_party.json_schema_compiler import json_parse
@@ -198,7 +198,7 @@
 
       return first_layer_files + get_from_future_listing(second_layer_listing)
 
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def GetFromFile(self, path):
     '''Calls |compilation_function| on the contents of the file at |path|.  If
@@ -222,7 +222,7 @@
       cache_data = self._compilation_function(path, future_files.Get())
       self._file_object_store.Set(path, _CacheEntry(cache_data, version))
       return cache_data
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def GetFromFileListing(self, path):
     '''Calls |compilation_function| on the listing of the files at |path|.
@@ -244,7 +244,7 @@
       cache_data = self._compilation_function(path, recursive_list_future.Get())
       self._list_object_store.Set(path, _CacheEntry(cache_data, version))
       return cache_data
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def GetFileVersion(self, path):
     cache_entry = self._file_object_store.Get(path).Get()
diff --git a/chrome/common/extensions/docs/server2/content_provider.py b/chrome/common/extensions/docs/server2/content_provider.py
index 22d60b9..2a6de2a 100644
--- a/chrome/common/extensions/docs/server2/content_provider.py
+++ b/chrome/common/extensions/docs/server2/content_provider.py
@@ -9,7 +9,7 @@
 from directory_zipper import DirectoryZipper
 from docs_server_utils import ToUnicode
 from file_system import FileNotFoundError
-from future import Gettable, Future
+from future import Future
 from path_canonicalizer import PathCanonicalizer
 from path_util import AssertIsValid, Join, ToDirectory
 from special_paths import SITE_VERIFICATION_FILE
@@ -132,8 +132,8 @@
     # Check for a zip file first, if zip is enabled.
     if self._directory_zipper and ext == '.zip':
       zip_future = self._directory_zipper.Zip(ToDirectory(base))
-      return Future(delegate=Gettable(
-          lambda: ContentAndType(zip_future.Get(), 'application/zip')))
+      return Future(callback=
+          lambda: ContentAndType(zip_future.Get(), 'application/zip'))
 
     # If there is no file extension, look for a file with one of the default
     # extensions.
@@ -159,7 +159,7 @@
         if f != SITE_VERIFICATION_FILE and ext in self._default_extensions:
           futures.append(self.GetContentAndType(Join(root, base)))
       # TODO(kalman): Cache .zip files for each directory (if supported).
-    return Future(delegate=Gettable(lambda: [f.Get() for f in futures]))
+    return Future(callback=lambda: [f.Get() for f in futures])
 
   def __repr__(self):
     return 'ContentProvider of <%s>' % repr(self.file_system)
diff --git a/chrome/common/extensions/docs/server2/content_providers.py b/chrome/common/extensions/docs/server2/content_providers.py
index 31be9b5..e9cfaca 100644
--- a/chrome/common/extensions/docs/server2/content_providers.py
+++ b/chrome/common/extensions/docs/server2/content_providers.py
@@ -10,7 +10,7 @@
 from content_provider import ContentProvider
 import environment
 from extensions_paths import CONTENT_PROVIDERS, LOCAL_DEBUG_DIR
-from future import Gettable, Future
+from future import Future
 from local_file_system import LocalFileSystem
 from third_party.json_schema_compiler.memoize import memoize
 
@@ -177,5 +177,5 @@
                            'initializing',
                            self._CreateContentProvider(name, config).Cron))
                for name, config in self._GetConfig().iteritems()]
-    return Future(delegate=Gettable(
-        lambda: [safe(name, 'resolving', f.Get) for name, f in futures if f]))
+    return Future(callback=
+        lambda: [safe(name, 'resolving', f.Get) for name, f in futures if f])
diff --git a/chrome/common/extensions/docs/server2/cron.yaml b/chrome/common/extensions/docs/server2/cron.yaml
index c7f5d95..c5cc566 100644
--- a/chrome/common/extensions/docs/server2/cron.yaml
+++ b/chrome/common/extensions/docs/server2/cron.yaml
@@ -2,4 +2,4 @@
 - description: Repopulates all cached data.
   url: /_cron
   schedule: every 5 minutes
-  target: 3-14-0
+  target: 3-16-0
diff --git a/chrome/common/extensions/docs/server2/cron_servlet.py b/chrome/common/extensions/docs/server2/cron_servlet.py
index 8bfb528..31c7143 100644
--- a/chrome/common/extensions/docs/server2/cron_servlet.py
+++ b/chrome/common/extensions/docs/server2/cron_servlet.py
@@ -15,7 +15,7 @@
 from environment import IsDevServer
 from extensions_paths import EXAMPLES, PUBLIC_TEMPLATES, STATIC_DOCS
 from file_system_util import CreateURLsFromPaths
-from future import Gettable, Future
+from future import Future
 from gcs_file_system_provider import CloudStorageFileSystemProvider
 from github_file_system_provider import GithubFileSystemProvider
 from host_file_system_provider import HostFileSystemProvider
@@ -187,7 +187,7 @@
                  init_timer.With(resolve_timer).FormatElapsed(),
                  init_timer.FormatElapsed(),
                  resolve_timer.FormatElapsed()))
-        return Future(delegate=Gettable(resolve))
+        return Future(callback=resolve)
 
       targets = (CreateDataSources(server_instance).values() +
                  [server_instance.content_providers])
@@ -211,22 +211,15 @@
 
       # Samples are too expensive to run on the dev server, where there is no
       # parallel fetch.
-      if not IsDevServer():
+      #
+      # XXX(kalman): Currently samples are *always* too expensive to fetch, so
+      # disabling them for now. It won't break anything so long as we're still
+      # not enforcing that everything gets cached for normal instances.
+      if False:  # should be "not IsDevServer()":
         # Fetch each individual sample file.
         results.append(request_files_in_dir(EXAMPLES,
                                             prefix='extensions/examples'))
 
-        # Fetch the zip file of each example (contains all the individual
-        # files).
-        example_zips = []
-        for root, _, files in trunk_fs.Walk(EXAMPLES):
-          example_zips.extend(
-              root + '.zip' for name in files if name == 'manifest.json')
-        results.append(_RequestEachItem(
-            'example zips',
-            example_zips,
-            lambda path: render('extensions/examples/' + path)))
-
       # Resolve the hand-written Cron method futures.
       title = 'resolving %s parallel Cron targets' % len(targets)
       _cronlog.info(title)
diff --git a/chrome/common/extensions/docs/server2/cron_servlet_test.py b/chrome/common/extensions/docs/server2/cron_servlet_test.py
index 303f548..0847c56 100755
--- a/chrome/common/extensions/docs/server2/cron_servlet_test.py
+++ b/chrome/common/extensions/docs/server2/cron_servlet_test.py
@@ -109,6 +109,12 @@
           'static.txt': 'static.txt contents'
         },
         'templates': {
+          'articles': {
+            'activeTab.html': 'activeTab.html contents'
+          },
+          'intros': {
+            'browserAction.html': 'activeTab.html contents'
+          },
           'private': {
             'table_of_contents.html': 'table_of_contents.html contents',
           },
diff --git a/chrome/common/extensions/docs/server2/data_source_registry.py b/chrome/common/extensions/docs/server2/data_source_registry.py
index 8249a23..7588811 100644
--- a/chrome/common/extensions/docs/server2/data_source_registry.py
+++ b/chrome/common/extensions/docs/server2/data_source_registry.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from api_list_data_source import APIListDataSource
 from data_source import DataSource
 from manifest_data_source import ManifestDataSource
 from permissions_data_source import PermissionsDataSource
@@ -13,6 +14,7 @@
 
 
 _all_data_sources = {
+  'api_list': APIListDataSource,
   'articles': ArticleDataSource,
   'intros': IntroDataSource,
   'manifest_source': ManifestDataSource,
diff --git a/chrome/common/extensions/docs/server2/document_renderer.py b/chrome/common/extensions/docs/server2/document_renderer.py
index 8aa7380..e254908 100644
--- a/chrome/common/extensions/docs/server2/document_renderer.py
+++ b/chrome/common/extensions/docs/server2/document_renderer.py
@@ -30,7 +30,7 @@
     '''
     START_REF = '$(ref:'
     END_REF = ')'
-    MAX_REF_LENGTH = 100
+    MAX_REF_LENGTH = 256
 
     new_document = []
 
@@ -52,7 +52,7 @@
         new_document.append(document[cursor_index:end_ref_index + 1])
       else:
         ref = document[start_ref_index:end_ref_index]
-        ref_parts = ref[len(START_REF):].split(' ', 1)
+        ref_parts = ref[len(START_REF):].split(None, 1)
 
         # Guess the api name from the html name, replacing '_' with '.' (e.g.
         # if the page is app_window.html, guess the api name is app.window)
diff --git a/chrome/common/extensions/docs/server2/document_renderer_test.py b/chrome/common/extensions/docs/server2/document_renderer_test.py
index 7f7ff1f..0c5862f 100755
--- a/chrome/common/extensions/docs/server2/document_renderer_test.py
+++ b/chrome/common/extensions/docs/server2/document_renderer_test.py
@@ -100,15 +100,36 @@
     self.assertEqual(expected_document, text)
     self.assertEqual([], warnings)
 
+  def testRefSplitAcrossLines(self):
+    document = 'Hello, $(ref:baz.baz_e1 world). A $(ref:foo.foo_t3\n link)'
+    expected_document = ('Hello, <a href=#type-baz_e1>world</a>. A <a href='
+                         '#type-foo_t3>link</a>')
+
+    path = 'some/path/to/document.html'
+
+    text, warnings = self._renderer.Render(document, path)
+    self.assertEqual(expected_document, text)
+    self.assertEqual([], warnings)
+
+    text, warnings = self._renderer.Render(document, path, render_title=True)
+    self.assertEqual(expected_document, text)
+    self.assertEqual(['Expected a title'], warnings)
+
   def testInvalidRef(self):
-    # There needs to be more than 100 characters between the invalid ref
-    # and the next ref
-    document = ('An invalid $(ref:foo.foo_t3 a title with some long '
-                'text containing a valid reference pointing to '
+    # DocumentRenderer attempts to detect unclosed $(ref:...) tags by limiting
+    # how far it looks ahead. Lorem Ipsum should be long enough to trigger that.
+    _LOREM_IPSUM = (
+        'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do '
+        'eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim '
+        'ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut '
+        'aliquip ex ea commodo consequat. Duis aute irure dolor in '
+        'reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla '
+        'pariatur. Excepteur sint occaecat cupidatat non proident, sunt in '
+        'culpa qui officia deserunt mollit anim id est laborum.')
+    document = ('An invalid $(ref:foo.foo_t3 a title ' + _LOREM_IPSUM +
                 '$(ref:baz.baz_e1) here')
-    expected_document = ('An invalid $(ref:foo.foo_t3 a title with some long '
-                         'text containing a valid reference pointing to <a'
-                         ' href=#type-baz_e1>baz.baz_e1</a> here')
+    expected_document = ('An invalid $(ref:foo.foo_t3 a title ' + _LOREM_IPSUM +
+                         '<a href=#type-baz_e1>baz.baz_e1</a> here')
     path = 'some/path/to/document_api.html'
 
     text, warnings = self._renderer.Render(document, path)
diff --git a/chrome/common/extensions/docs/server2/extensions_paths.py b/chrome/common/extensions/docs/server2/extensions_paths.py
index 682f1c0..3bb6342 100644
--- a/chrome/common/extensions/docs/server2/extensions_paths.py
+++ b/chrome/common/extensions/docs/server2/extensions_paths.py
@@ -7,12 +7,21 @@
 
 # Extensions-related paths within the Chromium repository.
 
+APPS = 'apps/common/'
 EXTENSIONS = 'extensions/common/'
 CHROME_EXTENSIONS = 'chrome/common/extensions/'
 
-API = join(EXTENSIONS, 'api/')
+APPS_API = join(APPS, 'api/')
+EXTENSIONS_API = join(EXTENSIONS, 'api/')
 CHROME_API = join(CHROME_EXTENSIONS, 'api/')
 
+# Note: This determines search order when APIs are resolved in the filesystem.
+API_PATHS = (
+  CHROME_API,
+  EXTENSIONS_API,
+  APPS_API,
+)
+
 DOCS = join(CHROME_EXTENSIONS, 'docs/')
 
 API_FEATURES = join(CHROME_API, '_api_features.json')
diff --git a/chrome/common/extensions/docs/server2/fake_url_fetcher.py b/chrome/common/extensions/docs/server2/fake_url_fetcher.py
index c4dd71c..a9ae53e3 100644
--- a/chrome/common/extensions/docs/server2/fake_url_fetcher.py
+++ b/chrome/common/extensions/docs/server2/fake_url_fetcher.py
@@ -5,7 +5,7 @@
 import os
 import posixpath
 
-from future import Gettable, Future
+from future import Future
 from path_util import AssertIsDirectory, IsDirectory
 
 
@@ -51,7 +51,7 @@
     def resolve():
       self._async_resolve_count += 1
       return self._DoFetch(url)
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Fetch(self, url):
     self._sync_count += 1
@@ -128,7 +128,7 @@
     def resolve():
       self._fetch_resolve_count += 1
       return future.Get()
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def CheckAndReset(self,
                     fetch_count=0,
diff --git a/chrome/common/extensions/docs/server2/features_bundle.py b/chrome/common/extensions/docs/server2/features_bundle.py
index a813214..e58c650 100644
--- a/chrome/common/extensions/docs/server2/features_bundle.py
+++ b/chrome/common/extensions/docs/server2/features_bundle.py
@@ -4,11 +4,12 @@
 
 import posixpath
 
-from compiled_file_system import Unicode
+from compiled_file_system import SingleFile, Unicode
 from extensions_paths import (
     API_FEATURES, JSON_TEMPLATES, MANIFEST_FEATURES, PERMISSION_FEATURES)
 import features_utility
-from future import Gettable, Future
+from file_system import FileNotFoundError
+from future import Future
 from third_party.json_schema_compiler.json_parse import Parse
 
 
@@ -39,8 +40,11 @@
 
 class _FeaturesCache(object):
   def __init__(self, file_system, compiled_fs_factory, *json_paths):
-    self._cache = compiled_fs_factory.Create(
-        file_system, self._CreateCache, type(self))
+    populate = self._CreateCache
+    if len(json_paths) == 1:
+      populate = SingleFile(populate)
+
+    self._cache = compiled_fs_factory.Create(file_system, populate, type(self))
     self._text_cache = compiled_fs_factory.ForUnicode(file_system)
     self._json_path = json_paths[0]
     self._extra_paths = json_paths[1:]
@@ -51,7 +55,11 @@
                           for path in self._extra_paths]
     features = features_utility.Parse(Parse(features_json))
     for path_future in extra_path_futures:
-      extra_json = path_future.Get()
+      try:
+        extra_json = path_future.Get()
+      except FileNotFoundError:
+        # Not all file system configurations have the extra files.
+        continue
       features = features_utility.MergedWith(
           features_utility.Parse(Parse(extra_json)), features)
     return features
@@ -80,7 +88,11 @@
         compiled_fs_factory,
         PERMISSION_FEATURES,
         posixpath.join(JSON_TEMPLATES, 'permissions.json'))
-    self._object_store = object_store_creator.Create(_FeaturesCache, 'features')
+    # Namespace the object store by the file system ID because this class is
+    # used by the availability finder cross-channel.
+    # TODO(kalman): Configure this at the ObjectStore level.
+    self._object_store = object_store_creator.Create(
+        _FeaturesCache, category=file_system.GetIdentity())
 
   def GetPermissionFeatures(self):
     return self._permission_cache.GetFeatures()
@@ -109,4 +121,4 @@
             feature, api_features, manifest_features, permission_features)
       self._object_store.Set('api_features', api_features)
       return api_features
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
diff --git a/chrome/common/extensions/docs/server2/features_utility.py b/chrome/common/extensions/docs/server2/features_utility.py
index 5781b71..b965db5 100644
--- a/chrome/common/extensions/docs/server2/features_utility.py
+++ b/chrome/common/extensions/docs/server2/features_utility.py
@@ -13,6 +13,7 @@
 a whitelist are ignored as they are only useful to specific apps or extensions.
 '''
 
+from branch_utility import BranchUtility
 from copy import deepcopy
 
 def _GetPlatformsForExtensionTypes(extension_types):
@@ -65,9 +66,14 @@
         # See http://crbug.com/316194.
         extension_types = set()
         for value in available_values:
-          extension_types.update(value['extension_types'])
-        value = [subvalue for subvalue in available_values
-                 if subvalue['channel'] == 'stable'][0]
+          extension_types.update(value.get('extension_types', ()))
+
+        # For the base value, select the one with the most recent availability.
+        channel_names = BranchUtility.GetAllChannelNames()
+        available_values.sort(
+            key=lambda v: channel_names.index(v.get('channel', 'stable')))
+        value = available_values[0]
+
         value['extension_types'] = list(extension_types)
 
     if ignore_feature(name, value):
diff --git a/chrome/common/extensions/docs/server2/features_utility_test.py b/chrome/common/extensions/docs/server2/features_utility_test.py
index 5dcfdd8..6a75173 100755
--- a/chrome/common/extensions/docs/server2/features_utility_test.py
+++ b/chrome/common/extensions/docs/server2/features_utility_test.py
@@ -56,6 +56,50 @@
 
     self.assertEqual(expected, Parse(raw_features_json))
 
+  def testFeatureList(self):
+    raw_features_json = {
+      'doc1': [
+        { 'extension_types': ['extension'] },
+        { 'extension_types': ['platform_app'] }
+      ],
+      'doc2': [
+        { 'channel': 'dev', 'extension_types': ['extension', 'platform_app'] },
+        { 'channel': 'stable' }
+      ],
+      'doc3': [
+        { 'channel': 'beta' },
+        { 'channel': 'dev' }
+      ],
+      'doc4': [
+        { 'channel': 'beta' },
+        { 'dependencies': ['permission:perm1'] }
+      ]
+    }
+
+    expected = {
+      'doc1': {
+        'platforms': ['apps', 'extensions'],
+        'name': 'doc1'
+      },
+      'doc2': {
+        'channel': 'stable',
+        'platforms': ['apps', 'extensions'],
+        'name': 'doc2'
+      },
+      'doc3': {
+        'platforms': [],
+        'channel': 'beta',
+        'name': 'doc3'
+      },
+      'doc4': {
+        'platforms': [],
+        'dependencies': ['permission:perm1'],
+        'name': 'doc4'
+      }
+    }
+
+    self.assertEqual(expected, Parse(raw_features_json))
+
   def testFilter(self):
     unfiltered = {
       'doc1': { 'platforms': ['apps'] },
diff --git a/chrome/common/extensions/docs/server2/file_system.py b/chrome/common/extensions/docs/server2/file_system.py
index c2da419..e21ff1e 100644
--- a/chrome/common/extensions/docs/server2/file_system.py
+++ b/chrome/common/extensions/docs/server2/file_system.py
@@ -5,7 +5,7 @@
 import posixpath
 import traceback
 
-from future import Gettable, Future
+from future import Future
 from path_util import (
     AssertIsDirectory, AssertIsValid, IsDirectory, IsValid, SplitParent,
     ToDirectory)
@@ -19,7 +19,7 @@
   def RaiseInFuture(cls, message):
     stack = traceback.format_stack()
     def boom(): raise cls('%s. Creation stack:\n%s' % (message, ''.join(stack)))
-    return Future(delegate=Gettable(boom))
+    return Future(callback=boom)
 
 
 class FileNotFoundError(_BaseFileSystemException):
@@ -86,7 +86,7 @@
     '''
     AssertIsValid(path)
     read_single = self.Read([path])
-    return Future(delegate=Gettable(lambda: read_single.Get()[path]))
+    return Future(callback=lambda: read_single.Get()[path])
 
   def Exists(self, path):
     '''Returns a Future to the existence of |path|; True if |path| exists,
@@ -108,7 +108,7 @@
         return base in list_future.Get()
       except FileNotFoundError:
         return False
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Refresh(self):
     '''Asynchronously refreshes the content of the FileSystem, returning a
@@ -171,6 +171,13 @@
     for walkinfo in walk(root):
       yield walkinfo
 
+  def __eq__(self, other):
+    return (isinstance(other, FileSystem) and
+            self.GetIdentity() == other.GetIdentity())
+
+  def __ne__(self, other):
+    return not (self == other)
+
   def __repr__(self):
     return '<%s>' % type(self).__name__
 
diff --git a/chrome/common/extensions/docs/server2/future.py b/chrome/common/extensions/docs/server2/future.py
index 4a90344..2f60099 100644
--- a/chrome/common/extensions/docs/server2/future.py
+++ b/chrome/common/extensions/docs/server2/future.py
@@ -11,40 +11,30 @@
   '''Creates a Future which returns a list of results from each Future in
   |futures|.
   '''
-  return Future(delegate=Gettable(lambda: [f.Get() for f in futures]))
-
-
-class Gettable(object):
-  '''Allows a Future to accept a callable as a delegate. Wraps |f| in a .Get
-  interface required by Future.
-  '''
-  def __init__(self, f, *args):
-    self._g = lambda: f(*args)
-  def Get(self):
-    return self._g()
+  return Future(callback=lambda: [f.Get() for f in futures])
 
 
 class Future(object):
-  '''Stores a value, error, or delegate to be used later.
+  '''Stores a value, error, or callback to be used later.
   '''
-  def __init__(self, value=_no_value, delegate=None, exc_info=None):
+  def __init__(self, value=_no_value, callback=None, exc_info=None):
     self._value = value
-    self._delegate = delegate
+    self._callback = callback
     self._exc_info = exc_info
     if (self._value is _no_value and
-        self._delegate is None and
+        self._callback is None and
         self._exc_info is None):
-      raise ValueError('Must have either a value, error, or delegate.')
+      raise ValueError('Must have either a value, error, or callback.')
 
   def Get(self):
-    '''Gets the stored value, error, or delegate contents.
+    '''Gets the stored value, error, or callback contents.
     '''
     if self._value is not _no_value:
       return self._value
     if self._exc_info is not None:
       self._Raise()
     try:
-      self._value = self._delegate.Get()
+      self._value = self._callback()
       return self._value
     except:
       self._exc_info = sys.exc_info()
diff --git a/chrome/common/extensions/docs/server2/future_test.py b/chrome/common/extensions/docs/server2/future_test.py
index 3b31a0c..94352fe 100755
--- a/chrome/common/extensions/docs/server2/future_test.py
+++ b/chrome/common/extensions/docs/server2/future_test.py
@@ -6,8 +6,10 @@
 import traceback
 import unittest
 
+
 from future import Future
 
+
 class FutureTest(unittest.TestCase):
   def testNoValueOrDelegate(self):
     self.assertRaises(ValueError, Future)
@@ -18,16 +20,12 @@
     self.assertEqual(42, future.Get())
 
   def testDelegateValue(self):
-    assertFalse = self.assertFalse
-    class delegate(object):
-      def __init__(self):
-        self._get_called = False
-      def Get(self):
-        assertFalse(self._get_called)
-        self._get_called = True
-        return 42
-
-    future = Future(delegate=delegate())
+    called = [False,]
+    def callback():
+      self.assertFalse(called[0])
+      called[0] = True
+      return 42
+    future = Future(callback=callback)
     self.assertEqual(42, future.Get())
     self.assertEqual(42, future.Get())
 
@@ -46,14 +44,11 @@
       return bar()
     chain = [foo, bar, baz, qux]
 
-    assertFalse = self.assertFalse
-    class delegate(object):
-      def __init__(self):
-        self._get_called = False
-      def Get(self):
-        assertFalse(self._get_called)
-        self._get_called = True
-        return foo()
+    called = [False,]
+    def callback():
+      self.assertFalse(called[0])
+      called[0] = True
+      return foo()
 
     fail = self.fail
     assertTrue = self.assertTrue
@@ -66,9 +61,10 @@
         stack = traceback.format_exc()
         assertTrue(all(stack.find(fn.__name__) != -1 for fn in chain))
 
-    future = Future(delegate=delegate())
+    future = Future(callback=callback)
     assert_raises_full_stack(future, FunkyException)
     assert_raises_full_stack(future, FunkyException)
 
+
 if __name__ == '__main__':
   unittest.main()
diff --git a/chrome/common/extensions/docs/server2/gcs_file_system.py b/chrome/common/extensions/docs/server2/gcs_file_system.py
index e43a85d..9a16537 100644
--- a/chrome/common/extensions/docs/server2/gcs_file_system.py
+++ b/chrome/common/extensions/docs/server2/gcs_file_system.py
@@ -8,7 +8,7 @@
 
 from docs_server_utils import StringIdentity
 from file_system import FileSystem, FileNotFoundError, StatInfo
-from future import Gettable, Future
+from future import Future
 from path_util import (
     AssertIsDirectory, AssertIsFile, AssertIsValid, IsDirectory, Join)
 
@@ -96,7 +96,7 @@
         self._warnAboutAuthError()
         raise
 
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Refresh(self):
     return Future(value=())
diff --git a/chrome/common/extensions/docs/server2/github_file_system.py b/chrome/common/extensions/docs/server2/github_file_system.py
index df10edaa..57cd698 100644
--- a/chrome/common/extensions/docs/server2/github_file_system.py
+++ b/chrome/common/extensions/docs/server2/github_file_system.py
@@ -21,52 +21,46 @@
 USERNAME = None
 PASSWORD = None
 
+
 def _MakeBlobstoreKey(version):
   return ZIP_KEY + '.' + str(version)
 
-class _AsyncFetchFutureZip(object):
-  def __init__(self,
-               fetcher,
-               username,
-               password,
-               blobstore,
-               key_to_set,
-               key_to_delete=None):
-    self._fetcher = fetcher
-    self._fetch = fetcher.FetchAsync(ZIP_KEY,
-                                     username=username,
-                                     password=password)
-    self._blobstore = blobstore
-    self._key_to_set = key_to_set
-    self._key_to_delete = key_to_delete
 
-  def Get(self):
+def _GetAsyncFetchCallback(fetcher,
+                           username,
+                           password,
+                           blobstore,
+                           key_to_set,
+                           key_to_delete=None):
+  fetch = fetcher.FetchAsync(ZIP_KEY, username=username, password=password)
+
+  def resolve():
     try:
-      result = self._fetch.Get()
+      result = fetch.Get()
       # Check if Github authentication failed.
       if result.status_code == 401:
         logging.error('Github authentication failed for %s, falling back to '
                       'unauthenticated.' % USERNAME)
-        blob = self._fetcher.Fetch(ZIP_KEY).content
+        blob = fetcher.Fetch(ZIP_KEY).content
       else:
         blob = result.content
     except urlfetch.DownloadError as e:
       logging.error('Bad github zip file: %s' % e)
       return None
-    if self._key_to_delete is not None:
-      self._blobstore.Delete(_MakeBlobstoreKey(self._key_to_delete),
-                             BLOBSTORE_GITHUB)
+    if key_to_delete is not None:
+      blobstore.Delete(_MakeBlobstoreKey(key_to_delete, BLOBSTORE_GITHUB))
     try:
       return_zip = ZipFile(StringIO(blob))
     except BadZipfile as e:
       logging.error('Bad github zip file: %s' % e)
       return None
 
-    self._blobstore.Set(_MakeBlobstoreKey(self._key_to_set),
-                        blob,
-                        BLOBSTORE_GITHUB)
+    blobstore.Set(_MakeBlobstoreKey(key_to_set), blob, BLOBSTORE_GITHUB)
     return return_zip
 
+  return resolve
+
+
 class GithubFileSystem(FileSystem):
   @staticmethod
   def CreateChromeAppsSamples(object_store_creator):
@@ -114,12 +108,12 @@
         self._zip_file = Future(value=None)
     else:
       self._zip_file = Future(
-          delegate=_AsyncFetchFutureZip(self._fetcher,
-                                        self._username,
-                                        self._password,
-                                        self._blobstore,
-                                        version,
-                                        key_to_delete=self._version))
+          callback=_GetAsyncFetchCallback(self._fetcher,
+                                          self._username,
+                                          self._password,
+                                          self._blobstore,
+                                          version,
+                                          key_to_delete=self._version))
     self._version = version
 
   def _ReadFile(self, path):
diff --git a/chrome/common/extensions/docs/server2/local_file_system.py b/chrome/common/extensions/docs/server2/local_file_system.py
index c9d13f8..fff30a2 100644
--- a/chrome/common/extensions/docs/server2/local_file_system.py
+++ b/chrome/common/extensions/docs/server2/local_file_system.py
@@ -7,7 +7,7 @@
 
 from docs_server_utils import StringIdentity
 from file_system import FileSystem, FileNotFoundError, StatInfo
-from future import Gettable, Future
+from future import Future
 from path_util import AssertIsDirectory, AssertIsValid
 from test_util import ChromiumPath
 
@@ -88,7 +88,7 @@
         else:
           result[path] = _ReadFile(full_path)
       return result
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Refresh(self):
     return Future(value=())
diff --git a/chrome/common/extensions/docs/server2/manifest_data_source.py b/chrome/common/extensions/docs/server2/manifest_data_source.py
index 6495ccb..414c21a 100644
--- a/chrome/common/extensions/docs/server2/manifest_data_source.py
+++ b/chrome/common/extensions/docs/server2/manifest_data_source.py
@@ -6,7 +6,7 @@
 
 from data_source import DataSource
 import features_utility
-from future import Gettable, Future
+from future import Future
 from manifest_features import ConvertDottedKeysToNested
 
 def _ListifyAndSortDocs(features, app_name):
@@ -121,7 +121,7 @@
         'apps': for_templates(manifest_features, 'app'),
         'extensions': for_templates(manifest_features, 'extension')
       }
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def _GetCachedManifestData(self):
     data = self._object_store.Get('manifest_data').Get()
diff --git a/chrome/common/extensions/docs/server2/mock_file_system.py b/chrome/common/extensions/docs/server2/mock_file_system.py
index 7346beb..9f04cd1 100644
--- a/chrome/common/extensions/docs/server2/mock_file_system.py
+++ b/chrome/common/extensions/docs/server2/mock_file_system.py
@@ -5,7 +5,7 @@
 import posixpath
 
 from file_system import FileSystem, FileNotFoundError
-from future import Gettable, Future
+from future import Future
 from test_file_system import _List, _StatTracker, TestFileSystem
 from path_util import IsDirectory
 
@@ -51,7 +51,7 @@
         if update is not None:
           result[path] = update
       return result
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Refresh(self):
     return self._file_system.Refresh()
diff --git a/chrome/common/extensions/docs/server2/new_github_file_system.py b/chrome/common/extensions/docs/server2/new_github_file_system.py
index eb31311..e9307b7 100644
--- a/chrome/common/extensions/docs/server2/new_github_file_system.py
+++ b/chrome/common/extensions/docs/server2/new_github_file_system.py
@@ -14,7 +14,7 @@
 from appengine_wrappers import urlfetch
 from docs_server_utils import StringIdentity
 from file_system import FileNotFoundError, FileSystem, FileSystemError, StatInfo
-from future import Future, Gettable
+from future import Future
 from object_store_creator import ObjectStoreCreator
 from path_util import AssertIsDirectory, IsDirectory
 import url_constants
@@ -194,7 +194,7 @@
         self._up_to_date_cache.Set(repo_key, True)
         self._stat_cache.Set(repo_key, version)
         return repo_zip
-      return Future(delegate=Gettable(resolve))
+      return Future(callback=resolve)
 
     # To decide whether we need to re-stat, and from there whether to re-fetch,
     # make use of ObjectStore's start-empty configuration. If
@@ -257,7 +257,7 @@
         else:
           reads[path] = repo_zip.Read(path)
       return reads
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Stat(self, path):
     '''Stats |path| returning its version as as StatInfo object. If |path| ends
diff --git a/chrome/common/extensions/docs/server2/object_store.py b/chrome/common/extensions/docs/server2/object_store.py
index f33aa91..9eb624a 100644
--- a/chrome/common/extensions/docs/server2/object_store.py
+++ b/chrome/common/extensions/docs/server2/object_store.py
@@ -4,13 +4,6 @@
 
 from future import Future
 
-class _SingleGetFuture(object):
-  def __init__(self, multi_get, key):
-    self._future = multi_get
-    self._key = key
-
-  def Get(self):
-    return self._future.Get().get(self._key)
 
 class ObjectStore(object):
   '''A class for caching picklable objects.
@@ -19,7 +12,8 @@
     '''Gets a |Future| with the value of |key| in the object store, or None
     if |key| is not in the object store.
     '''
-    return Future(delegate=_SingleGetFuture(self.GetMulti([key]), key))
+    multi_get_future = self.GetMulti((key,))
+    return Future(callback=lambda: multi_get_future.Get().get(key))
 
   def GetMulti(self, keys):
     '''Gets a |Future| with values mapped to |keys| from the object store, with
diff --git a/chrome/common/extensions/docs/server2/offline_file_system.py b/chrome/common/extensions/docs/server2/offline_file_system.py
index a020113..2096de7 100644
--- a/chrome/common/extensions/docs/server2/offline_file_system.py
+++ b/chrome/common/extensions/docs/server2/offline_file_system.py
@@ -3,7 +3,7 @@
 # found in the LICENSE file.
 
 from file_system import FileSystem, FileNotFoundError
-from future import Gettable, Future
+from future import Future
 
 
 class OfflineFileSystem(FileSystem):
@@ -16,7 +16,7 @@
   def Read(self, paths):
     def raise_file_not_found():
       raise FileNotFoundError('File system is offline, cannot read %s' % paths)
-    return Future(delegate=Gettable(raise_file_not_found))
+    return Future(callback=raise_file_not_found)
 
   def Stat(self, path):
     raise FileNotFoundError('File system is offline, cannot read %s' % path)
diff --git a/chrome/common/extensions/docs/server2/patched_file_system.py b/chrome/common/extensions/docs/server2/patched_file_system.py
index ed335cd..02fa27c 100644
--- a/chrome/common/extensions/docs/server2/patched_file_system.py
+++ b/chrome/common/extensions/docs/server2/patched_file_system.py
@@ -5,36 +5,33 @@
 from copy import deepcopy
 
 from file_system import FileSystem, StatInfo, FileNotFoundError
-from future import Gettable, Future
+from future import Future
 
-class _AsyncFetchFuture(object):
-  def __init__(self,
-               unpatched_files_future,
-               patched_files_future,
-               dirs_value,
-               patched_file_system):
-    self._unpatched_files_future = unpatched_files_future
-    self._patched_files_future = patched_files_future
-    self._dirs_value  = dirs_value
-    self._patched_file_system = patched_file_system
 
-  def Get(self):
-    files = self._unpatched_files_future.Get()
-    files.update(self._patched_files_future.Get())
-    files.update(
-        dict((path, self._PatchDirectoryListing(path, self._dirs_value[path]))
-             for path in self._dirs_value))
-    return files
-
-  def _PatchDirectoryListing(self, path, original_listing):
+def _GetAsyncFetchCallback(unpatched_files_future,
+                           patched_files_future,
+                           dirs_value,
+                           patched_file_system):
+  def patch_directory_listing(path, original_listing):
     added, deleted, modified = (
-        self._patched_file_system._GetDirectoryListingFromPatch(path))
+        patched_file_system._GetDirectoryListingFromPatch(path))
     if original_listing is None:
       if len(added) == 0:
         raise FileNotFoundError('Directory %s not found in the patch.' % path)
       return added
     return list((set(original_listing) | set(added)) - set(deleted))
 
+  def resolve():
+    files = unpatched_files_future.Get()
+    files.update(patched_files_future.Get())
+    files.update(
+        dict((path, patch_directory_listing(path, dirs_value[path]))
+             for path in dirs_value))
+    return files
+
+  return resolve
+
+
 class PatchedFileSystem(FileSystem):
   ''' Class to fetch resources with a patch applied.
   '''
@@ -48,13 +45,13 @@
     if set(paths) & set(deleted):
       def raise_file_not_found():
         raise FileNotFoundError('Files are removed from the patch.')
-      return Future(delegate=Gettable(raise_file_not_found))
+      return Future(callback=raise_file_not_found)
     patched_files |= (set(added) | set(modified))
     dir_paths = set(path for path in paths if path.endswith('/'))
     file_paths = set(paths) - dir_paths
     patched_paths = file_paths & patched_files
     unpatched_paths = file_paths - patched_files
-    return Future(delegate=_AsyncFetchFuture(
+    return Future(callback=_GetAsyncFetchCallback(
         self._base_file_system.Read(unpatched_paths),
         self._patcher.Apply(patched_paths, self._base_file_system),
         self._TryReadDirectory(dir_paths),
diff --git a/chrome/common/extensions/docs/server2/path_canonicalizer.py b/chrome/common/extensions/docs/server2/path_canonicalizer.py
index 1d8e3fc..23da9e1 100644
--- a/chrome/common/extensions/docs/server2/path_canonicalizer.py
+++ b/chrome/common/extensions/docs/server2/path_canonicalizer.py
@@ -5,7 +5,7 @@
 from collections import defaultdict
 import posixpath
 
-from future import Gettable, Future
+from future import Future
 from path_util import SplitParent
 from special_paths import SITE_VERIFICATION_FILE
 
@@ -74,7 +74,7 @@
 
       return canonical_paths, simplified_paths_map
 
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def Canonicalize(self, path):
     '''Returns the canonical path for |path|.
diff --git a/chrome/common/extensions/docs/server2/permissions_data_source.py b/chrome/common/extensions/docs/server2/permissions_data_source.py
index f757c25..77287eb 100644
--- a/chrome/common/extensions/docs/server2/permissions_data_source.py
+++ b/chrome/common/extensions/docs/server2/permissions_data_source.py
@@ -8,7 +8,7 @@
 from data_source import DataSource
 from extensions_paths import PRIVATE_TEMPLATES
 import features_utility as features
-from future import Gettable, Future
+from future import Future
 
 
 def _ListifyPermissions(permissions):
@@ -74,7 +74,7 @@
         'declare_extensions': filter_for_platform(
             permission_features, 'extensions')
       }
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def _GetCachedPermissionsData(self):
     data = self._object_store.Get('permissions_data').Get()
diff --git a/chrome/common/extensions/docs/server2/persistent_object_store.py b/chrome/common/extensions/docs/server2/persistent_object_store.py
index d94b78f..0feb6d8 100644
--- a/chrome/common/extensions/docs/server2/persistent_object_store.py
+++ b/chrome/common/extensions/docs/server2/persistent_object_store.py
@@ -8,17 +8,6 @@
 from future import Future
 from object_store import ObjectStore
 
-class _AsyncGetFuture(object):
-  def __init__(self, object_store, keys):
-    self._futures = dict(
-        (k, db.get_async(
-            PersistentObjectStoreItem.CreateKey(object_store._namespace, k)))
-         for k in keys)
-
-  def Get(self):
-    return dict((key, future.get_result().GetValue())
-                for key, future in self._futures.iteritems()
-                if future.get_result() is not None)
 
 class PersistentObjectStore(ObjectStore):
   '''Stores data persistently using the AppEngine Datastore API.
@@ -37,7 +26,15 @@
       [future.wait() for future in futures]
 
   def GetMulti(self, keys):
-    return Future(delegate=_AsyncGetFuture(self, keys))
+    db_futures = dict(
+        (k, db.get_async(
+            PersistentObjectStoreItem.CreateKey(self._namespace, k)))
+        for k in keys)
+    def resolve():
+      return dict((key, future.get_result().GetValue())
+                  for key, future in db_futures.iteritems()
+                  if future.get_result() is not None)
+    return Future(callback=resolve)
 
   def DelMulti(self, keys):
     futures = []
diff --git a/chrome/common/extensions/docs/server2/redirector.py b/chrome/common/extensions/docs/server2/redirector.py
index cd54d75..3e28427 100644
--- a/chrome/common/extensions/docs/server2/redirector.py
+++ b/chrome/common/extensions/docs/server2/redirector.py
@@ -6,7 +6,7 @@
 from urlparse import urlsplit
 
 from file_system import FileNotFoundError
-from future import Gettable, Future
+from future import Future
 
 class Redirector(object):
   def __init__(self, compiled_fs_factory, file_system):
@@ -66,4 +66,4 @@
       if 'redirects.json' in files:
         futures.append(
             self._cache.GetFromFile(posixpath.join(root, 'redirects.json')))
-    return Future(delegate=Gettable(lambda: [f.Get() for f in futures]))
+    return Future(callback=lambda: [f.Get() for f in futures])
diff --git a/chrome/common/extensions/docs/server2/reference_resolver.py b/chrome/common/extensions/docs/server2/reference_resolver.py
index 8ab7393..32d2eea 100644
--- a/chrome/common/extensions/docs/server2/reference_resolver.py
+++ b/chrome/common/extensions/docs/server2/reference_resolver.py
@@ -60,21 +60,6 @@
   # Matches after a $ref: that doesn't have []s.
   _bare_ref = re.compile('\w+(\.\w+)*')
 
-  class Factory(object):
-    def __init__(self,
-                 api_data_source_factory,
-                 api_models,
-                 object_store_creator):
-      self._api_data_source_factory = api_data_source_factory
-      self._api_models = api_models
-      self._object_store_creator = object_store_creator
-
-    def Create(self):
-      return ReferenceResolver(
-          self._api_data_source_factory.Create(None),
-          self._api_models,
-          self._object_store_creator.Create(ReferenceResolver))
-
   def __init__(self, api_data_source, api_models, object_store):
     self._api_data_source = api_data_source
     self._api_models = api_models
@@ -114,8 +99,10 @@
       category, node_name = node_info
       if namespace is not None and text.startswith('%s.' % namespace):
         text = text[len('%s.' % namespace):]
+      api_model = self._api_models.GetModel(api_name).Get()
+      filename = api_model.documentation_options.get('documented_in', api_name)
       return {
-        'href': '%s.html#%s-%s' % (api_name, category, name.replace('.', '-')),
+        'href': '%s#%s-%s' % (filename, category, name.replace('.', '-')),
         'text': text,
         'name': node_name
       }
@@ -125,7 +112,7 @@
     # to other APIs.
     if ref in api_list:
       return {
-        'href': '%s.html' % ref,
+        'href': '%s' % ref,
         'text': ref,
         'name': ref
       }
diff --git a/chrome/common/extensions/docs/server2/reference_resolver_test.py b/chrome/common/extensions/docs/server2/reference_resolver_test.py
index ce46ef4..fcb8842 100755
--- a/chrome/common/extensions/docs/server2/reference_resolver_test.py
+++ b/chrome/common/extensions/docs/server2/reference_resolver_test.py
@@ -9,12 +9,13 @@
 import unittest
 
 from file_system import FileNotFoundError
+from future import Future
 from reference_resolver import ReferenceResolver
 from test_object_store import TestObjectStore
 from test_util import Server2Path
 
 
-class FakeAPIDataSource(object):
+class _FakeAPIDataSource(object):
   def __init__(self, json_data):
     self._json = json_data
 
@@ -25,15 +26,23 @@
     return self._json[key]
 
 
-class FakeAPIModels(object):
+class _FakeNamespace(object):
+  def __init__(self):
+    self.documentation_options = {}
+
+
+class _FakeAPIModels(object):
   def __init__(self, names):
     self._names = names
 
   def GetNames(self):
     return self._names
 
+  def GetModel(self, name):
+    return Future(value=_FakeNamespace())
 
-class APIDataSourceTest(unittest.TestCase):
+
+class ReferenceResolverTest(unittest.TestCase):
   def setUp(self):
     self._base_path = Server2Path('test_data', 'test_json')
 
@@ -43,86 +52,86 @@
 
   def testGetLink(self):
     test_data = json.loads(self._ReadLocalFile('fake_data_source.json'))
-    resolver = ReferenceResolver(FakeAPIDataSource(test_data),
-                                 FakeAPIModels(test_data.keys()),
+    resolver = ReferenceResolver(_FakeAPIDataSource(test_data),
+                                 _FakeAPIModels(test_data.keys()),
                                  TestObjectStore('test'))
     self.assertEqual({
-      'href': 'foo.html',
+      'href': 'foo',
       'text': 'foo',
       'name': 'foo'
     }, resolver.GetLink('foo', namespace='baz'))
     self.assertEqual({
-      'href': 'foo.html#type-foo_t1',
+      'href': 'foo#type-foo_t1',
       'text': 'foo.foo_t1',
       'name': 'foo_t1'
     }, resolver.GetLink('foo.foo_t1', namespace='baz'))
     self.assertEqual({
-      'href': 'baz.html#event-baz_e1',
+      'href': 'baz#event-baz_e1',
       'text': 'baz_e1',
       'name': 'baz_e1'
     }, resolver.GetLink('baz.baz_e1', namespace='baz'))
     self.assertEqual({
-      'href': 'baz.html#event-baz_e1',
+      'href': 'baz#event-baz_e1',
       'text': 'baz_e1',
       'name': 'baz_e1'
     }, resolver.GetLink('baz_e1', namespace='baz'))
     self.assertEqual({
-      'href': 'foo.html#method-foo_f1',
+      'href': 'foo#method-foo_f1',
       'text': 'foo.foo_f1',
       'name': 'foo_f1'
     }, resolver.GetLink('foo.foo_f1', namespace='baz'))
     self.assertEqual({
-      'href': 'foo.html#property-foo_p3',
+      'href': 'foo#property-foo_p3',
       'text': 'foo.foo_p3',
       'name': 'foo_p3'
     }, resolver.GetLink('foo.foo_p3', namespace='baz'))
     self.assertEqual({
-      'href': 'bar.bon.html#type-bar_bon_t3',
+      'href': 'bar.bon#type-bar_bon_t3',
       'text': 'bar.bon.bar_bon_t3',
       'name': 'bar_bon_t3'
     }, resolver.GetLink('bar.bon.bar_bon_t3', namespace='baz'))
     self.assertEqual({
-      'href': 'bar.bon.html#property-bar_bon_p3',
+      'href': 'bar.bon#property-bar_bon_p3',
       'text': 'bar_bon_p3',
       'name': 'bar_bon_p3'
     }, resolver.GetLink('bar_bon_p3', namespace='bar.bon'))
     self.assertEqual({
-      'href': 'bar.bon.html#property-bar_bon_p3',
+      'href': 'bar.bon#property-bar_bon_p3',
       'text': 'bar_bon_p3',
       'name': 'bar_bon_p3'
     }, resolver.GetLink('bar.bon.bar_bon_p3', namespace='bar.bon'))
     self.assertEqual({
-      'href': 'bar.html#event-bar_e2',
+      'href': 'bar#event-bar_e2',
       'text': 'bar_e2',
       'name': 'bar_e2'
     }, resolver.GetLink('bar.bar_e2', namespace='bar'))
     self.assertEqual({
-      'href': 'bar.html#type-bon',
+      'href': 'bar#type-bon',
       'text': 'bon',
       'name': 'bon'
     }, resolver.GetLink('bar.bon', namespace='bar'))
     self.assertEqual({
-      'href': 'foo.html#event-foo_t3-foo_t3_e1',
+      'href': 'foo#event-foo_t3-foo_t3_e1',
       'text': 'foo_t3.foo_t3_e1',
       'name': 'foo_t3_e1'
     }, resolver.GetLink('foo_t3.foo_t3_e1', namespace='foo'))
     self.assertEqual({
-      'href': 'foo.html#event-foo_t3-foo_t3_e1',
+      'href': 'foo#event-foo_t3-foo_t3_e1',
       'text': 'foo_t3.foo_t3_e1',
       'name': 'foo_t3_e1'
     }, resolver.GetLink('foo.foo_t3.foo_t3_e1', namespace='foo'))
     self.assertEqual({
-      'href': 'foo.html#event-foo_t3-foo_t3_e1',
+      'href': 'foo#event-foo_t3-foo_t3_e1',
       'text': 'foo_t3.foo_t3_e1',
       'name': 'foo_t3_e1'
     }, resolver.GetLink('foo.foo_p1.foo_t3_e1', namespace='foo'))
     self.assertEqual({
-      'href': 'bar.html#property-bar_t1-bar_t1_p1',
+      'href': 'bar#property-bar_t1-bar_t1_p1',
       'text': 'bar.bar_t1.bar_t1_p1',
       'name': 'bar_t1_p1'
     }, resolver.GetLink('bar.bar_p3.bar_t1_p1', namespace='foo'))
     self.assertEqual({
-      'href': 'bar.html#property-bar_t1-bar_t1_p1',
+      'href': 'bar#property-bar_t1-bar_t1_p1',
       'text': 'bar_t1.bar_t1_p1',
       'name': 'bar_t1_p1'
     }, resolver.GetLink('bar_p3.bar_t1_p1', namespace='bar'))
@@ -142,72 +151,72 @@
         None,
         resolver.GetLink('bar_p3', namespace='foo'))
     self.assertEqual(
-        'Hello <a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">Bon Bon</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>',
+        'Hello <a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">Bon Bon</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>',
         resolver.ResolveAllLinks(
             'Hello $ref:bar_bon_p3, $ref:[bar_bon_p3 Bon Bon], $ref:bar_bon_p3',
             namespace='bar.bon'))
     self.assertEqual(
-        'I like <a href="bar.html#property-bar_t1-bar_t1_p1">food</a>.',
+        'I like <a href="bar#property-bar_t1-bar_t1_p1">food</a>.',
         resolver.ResolveAllLinks('I like $ref:[bar.bar_p3.bar_t1_p1 food].',
                                  namespace='foo'))
     self.assertEqual(
-        'Ref <a href="foo.html">It\'s foo!</a>',
+        'Ref <a href="foo">It\'s foo!</a>',
         resolver.ResolveAllLinks('Ref $ref:[foo It\'s foo!]', namespace='bar'))
     self.assertEqual(
-        'Ref <a href="bar.html#type-bon">Bon</a>',
+        'Ref <a href="bar#type-bon">Bon</a>',
         resolver.ResolveAllLinks('Ref $ref:[bar.bon Bon]', namespace='bar'))
 
     # Different kinds of whitespace can be significant inside <pre> tags.
     self.assertEqual(
-        '<pre><a href="bar.html#type-bon">bar.bon</a>({\nkey: value})',
+        '<pre><a href="bar#type-bon">bar.bon</a>({\nkey: value})',
         resolver.ResolveAllLinks('<pre>$ref:[bar.bon]({\nkey: value})',
                                  namespace='baz'))
 
     # Allow bare "$ref:foo.bar." at the end of a string.
     self.assertEqual(
-        '<a href="bar.html#type-bon">bar.bon</a>.',
+        '<a href="bar#type-bon">bar.bon</a>.',
         resolver.ResolveAllLinks('$ref:bar.bon.',
                                  namespace='baz'))
 
     # If a request is provided it should construct an appropriate relative link.
     self.assertEqual(
-        'Hi <a href="../../bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>, '
-            '<a href="../../bar.bon.html#property-bar_bon_p3">Bon Bon</a>, '
-            '<a href="../../bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>',
+        'Hi <a href="../../bar.bon#property-bar_bon_p3">bar_bon_p3</a>, '
+            '<a href="../../bar.bon#property-bar_bon_p3">Bon Bon</a>, '
+            '<a href="../../bar.bon#property-bar_bon_p3">bar_bon_p3</a>',
         resolver.ResolveAllLinks(
             'Hi $ref:bar_bon_p3, $ref:[bar_bon_p3 Bon Bon], $ref:bar_bon_p3',
             relative_to='big/long/path/bar.html',
             namespace='bar.bon'))
     self.assertEqual(
-        'Hi <a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">Bon Bon</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>',
+        'Hi <a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">Bon Bon</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>',
         resolver.ResolveAllLinks(
             'Hi $ref:bar_bon_p3, $ref:[bar_bon_p3 Bon Bon], $ref:bar_bon_p3',
             relative_to='',
             namespace='bar.bon'))
     self.assertEqual(
-        'Hi <a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">Bon Bon</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>',
+        'Hi <a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">Bon Bon</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>',
         resolver.ResolveAllLinks(
             'Hi $ref:bar_bon_p3, $ref:[bar_bon_p3 Bon Bon], $ref:bar_bon_p3',
             relative_to='bar.html',
             namespace='bar.bon'))
     self.assertEqual(
-        'Hi <a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">Bon Bon</a>, '
-            '<a href="bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>',
+        'Hi <a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">Bon Bon</a>, '
+            '<a href="bar.bon#property-bar_bon_p3">bar_bon_p3</a>',
         resolver.ResolveAllLinks(
             'Hi $ref:bar_bon_p3, $ref:[bar_bon_p3 Bon Bon], $ref:bar_bon_p3',
             relative_to='foo/bar.html',
             namespace='bar.bon'))
     self.assertEqual(
-        'Hi <a href="../bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>, '
-            '<a href="../bar.bon.html#property-bar_bon_p3">Bon Bon</a>, '
-            '<a href="../bar.bon.html#property-bar_bon_p3">bar_bon_p3</a>',
+        'Hi <a href="../bar.bon#property-bar_bon_p3">bar_bon_p3</a>, '
+            '<a href="../bar.bon#property-bar_bon_p3">Bon Bon</a>, '
+            '<a href="../bar.bon#property-bar_bon_p3">bar_bon_p3</a>',
         resolver.ResolveAllLinks(
             'Hi $ref:bar_bon_p3, $ref:[bar_bon_p3 Bon Bon], $ref:bar_bon_p3',
             relative_to='foo/baz/bar.html',
diff --git a/chrome/common/extensions/docs/server2/rietveld_patcher.py b/chrome/common/extensions/docs/server2/rietveld_patcher.py
index 0743138..dd085fc 100644
--- a/chrome/common/extensions/docs/server2/rietveld_patcher.py
+++ b/chrome/common/extensions/docs/server2/rietveld_patcher.py
@@ -24,33 +24,25 @@
   def __init__(self, message):
     self.message = message
 
-class _AsyncFetchFuture(object):
-  def __init__(self,
-               issue,
-               patchset,
-               files,
-               fetcher):
-    self._issue = issue
-    self._patchset = patchset
-    self._files = files
-    self._tarball = fetcher.FetchAsync('tarball/%s/%s' % (issue, patchset))
 
-  def Get(self):
-    tarball_result = self._tarball.Get()
+def _GetAsyncFetchCallback(issue, patchset, files, fetcher):
+  tarball = fetcher.FetchAsync('tarball/%s/%s' % (issue, patchset))
+
+  def resolve():
+    tarball_result = tarball.Get()
     if tarball_result.status_code != 200:
       raise RietveldPatcherError(
           'Failed to download tarball for issue %s patchset %s. Status: %s' %
-          (self._issue, self._patchset, tarball_result.status_code))
+          (issue, patchset, tarball_result.status_code))
 
     try:
       tar = tarfile.open(fileobj=StringIO(tarball_result.content))
     except tarfile.TarError as e:
       raise RietveldPatcherError(
-          'Error loading tarball for issue %s patchset %s.' % (self._issue,
-                                                               self._patchset))
+          'Error loading tarball for issue %s patchset %s.' % (issue, patchset))
 
-    self._value = {}
-    for path in self._files:
+    value = {}
+    for path in files:
       tar_path = 'b/%s' % path
 
       patched_file = None
@@ -62,18 +54,21 @@
         # is corrupted.
         raise RietveldPatcherError(
             'Error extracting tarball for issue %s patchset %s file %s.' %
-            (self._issue, self._patchset, tar_path))
+            (issue, patchset, tar_path))
       except KeyError as e:
         raise FileNotFoundError(
             'File %s not found in the tarball for issue %s patchset %s' %
-            (tar_path, self._issue, self._patchset))
+            (tar_path, issue, patchset))
       finally:
         if patched_file:
           patched_file.close()
 
-      self._value[path] = data
+      value[path] = data
 
-    return self._value
+    return value
+
+  return resolve
+
 
 class RietveldPatcher(Patcher):
   ''' Class to fetch resources from a patchset in Rietveld.
@@ -146,10 +141,10 @@
   def Apply(self, paths, file_system, version=None):
     if version is None:
       version = self.GetVersion()
-    return Future(delegate=_AsyncFetchFuture(self._issue,
-                                             version,
-                                             paths,
-                                             self._fetcher))
+    return Future(callback=_GetAsyncFetchCallback(self._issue,
+                                                  version,
+                                                  paths,
+                                                  self._fetcher))
 
   def GetIdentity(self):
     return self._issue
diff --git a/chrome/common/extensions/docs/server2/samples_data_source.py b/chrome/common/extensions/docs/server2/samples_data_source.py
index 591993f..203f2c5 100644
--- a/chrome/common/extensions/docs/server2/samples_data_source.py
+++ b/chrome/common/extensions/docs/server2/samples_data_source.py
@@ -27,11 +27,11 @@
                  host_file_system,
                  app_samples_file_system,
                  compiled_fs_factory,
-                 ref_resolver_factory,
+                 ref_resolver,
                  base_path):
       self._host_file_system = host_file_system
       self._app_samples_file_system = app_samples_file_system
-      self._ref_resolver = ref_resolver_factory.Create()
+      self._ref_resolver = ref_resolver
       self._base_path = base_path
       self._extensions_cache = compiled_fs_factory.Create(
           host_file_system,
diff --git a/chrome/common/extensions/docs/server2/server_instance.py b/chrome/common/extensions/docs/server2/server_instance.py
index cfcb691..95cb56b 100644
--- a/chrome/common/extensions/docs/server2/server_instance.py
+++ b/chrome/common/extensions/docs/server2/server_instance.py
@@ -98,24 +98,13 @@
         host_fs_at_trunk,
         self.availability_finder,
         self.api_models,
+        self.features_bundle,
         self.object_store_creator)
 
-    self.api_list_data_source_factory = APIListDataSource.Factory(
-        self.compiled_fs_factory,
-        host_fs_at_trunk,
-        self.features_bundle,
-        self.object_store_creator,
+    self.ref_resolver = ReferenceResolver(
+        self.api_data_source_factory.Create(None),
         self.api_models,
-        self.availability_finder,
-        self.api_categorizer)
-
-    self.ref_resolver_factory = ReferenceResolver.Factory(
-        self.api_data_source_factory,
-        self.api_models,
-        object_store_creator)
-
-    self.api_data_source_factory.SetReferenceResolverFactory(
-        self.ref_resolver_factory)
+        self.object_store_creator.Create(ReferenceResolver))
 
     # Note: samples are super slow in the dev server because it doesn't support
     # async fetch, so disable them.
@@ -132,7 +121,7 @@
         extension_samples_fs,
         app_samples_fs,
         CompiledFileSystem.Factory(object_store_creator),
-        self.ref_resolver_factory,
+        self.ref_resolver,
         base_path)
 
     self.api_data_source_factory.SetSamplesDataSourceFactory(
@@ -157,7 +146,7 @@
         TableOfContentsRenderer(host_fs_at_trunk,
                                 compiled_fs_factory,
                                 self.template_renderer),
-        self.ref_resolver_factory.Create())
+        self.ref_resolver)
 
   @staticmethod
   def ForTest(file_system=None, file_system_provider=None, base_path='/'):
diff --git a/chrome/common/extensions/docs/server2/sidenav_data_source.py b/chrome/common/extensions/docs/server2/sidenav_data_source.py
index 967a46d..1a7bae9 100644
--- a/chrome/common/extensions/docs/server2/sidenav_data_source.py
+++ b/chrome/common/extensions/docs/server2/sidenav_data_source.py
@@ -9,7 +9,7 @@
 from compiled_file_system import SingleFile, Unicode
 from data_source import DataSource
 from extensions_paths import JSON_TEMPLATES
-from future import Gettable, Future
+from future import Future
 from third_party.json_schema_compiler.json_parse import Parse
 
 
diff --git a/chrome/common/extensions/docs/server2/subversion_file_system.py b/chrome/common/extensions/docs/server2/subversion_file_system.py
index 9e860e9..21d1165 100644
--- a/chrome/common/extensions/docs/server2/subversion_file_system.py
+++ b/chrome/common/extensions/docs/server2/subversion_file_system.py
@@ -95,46 +95,42 @@
 
   return StatInfo(parent_version, child_versions)
 
-class _AsyncFetchFuture(object):
-  def __init__(self, paths, fetcher, args=None):
-    def apply_args(path):
-      return path if args is None else '%s?%s' % (path, args)
-    # A list of tuples of the form (path, Future).
-    self._fetches = [(path, fetcher.FetchAsync(apply_args(path)))
-                     for path in paths]
-    self._value = {}
-    self._error = None
+def _GetAsyncFetchCallback(paths, fetcher, args=None):
+  def apply_args(path):
+    return path if args is None else '%s?%s' % (path, args)
 
-  def _ListDir(self, directory):
+  def list_dir(directory):
     dom = xml.parseString(directory)
     files = [elem.childNodes[0].data for elem in dom.getElementsByTagName('a')]
     if '..' in files:
       files.remove('..')
     return files
 
-  def Get(self):
-    for path, future in self._fetches:
+  # A list of tuples of the form (path, Future).
+  fetches = [(path, fetcher.FetchAsync(apply_args(path))) for path in paths]
+
+  def resolve():
+    value = {}
+    for path, future in fetches:
       try:
         result = future.Get()
       except Exception as e:
         exc_type = FileNotFoundError if IsDownloadError(e) else FileSystemError
         raise exc_type('%s fetching %s for Get: %s' %
                        (type(e).__name__, path, traceback.format_exc()))
-
       if result.status_code == 404:
         raise FileNotFoundError('Got 404 when fetching %s for Get, content %s' %
             (path, result.content))
       if result.status_code != 200:
         raise FileSystemError('Got %s when fetching %s for Get, content %s' %
             (result.status_code, path, result.content))
-
       if path.endswith('/'):
-        self._value[path] = self._ListDir(result.content)
+        value[path] = list_dir(result.content)
       else:
-        self._value[path] = result.content
-    if self._error is not None:
-      raise self._error
-    return self._value
+        value[path] = result.content
+    return value
+
+  return resolve
 
 class SubversionFileSystem(FileSystem):
   '''Class to fetch resources from src.chromium.org.
@@ -162,9 +158,9 @@
     if self._revision is not None:
       # |fetcher| gets from svn.chromium.org which uses p= for version.
       args = 'p=%s' % self._revision
-    return Future(delegate=_AsyncFetchFuture(paths,
-                                             self._file_fetcher,
-                                             args=args))
+    return Future(callback=_GetAsyncFetchCallback(paths,
+                                                  self._file_fetcher,
+                                                  args=args))
 
   def Refresh(self):
     return Future(value=())
diff --git a/chrome/common/extensions/docs/server2/template_renderer.py b/chrome/common/extensions/docs/server2/template_renderer.py
index a6b8d65..3316ec7 100644
--- a/chrome/common/extensions/docs/server2/template_renderer.py
+++ b/chrome/common/extensions/docs/server2/template_renderer.py
@@ -51,7 +51,6 @@
     server_instance = self._server_instance
     data_sources = CreateDataSources(server_instance, request=request)
     data_sources.update({
-      'api_list': server_instance.api_list_data_source_factory.Create(),
       'apis': server_instance.api_data_source_factory.Create(request),
       'samples': server_instance.samples_data_source_factory.Create(request),
     })
diff --git a/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py b/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py
index e47e927..27d45f5 100644
--- a/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py
+++ b/chrome/common/extensions/docs/server2/test_data/api_data_source/canned_trunk_fs.py
@@ -182,7 +182,9 @@
               }
             ]
           }
-        })
+        }),
+        'manifest.json': '{}',
+        'permissions.json': '{}'
       },
       'private': {
         'intro_tables': {
diff --git a/chrome/common/extensions/docs/server2/test_data/canned_data.py b/chrome/common/extensions/docs/server2/test_data/canned_data.py
index 143da00..fabbf99 100644
--- a/chrome/common/extensions/docs/server2/test_data/canned_data.py
+++ b/chrome/common/extensions/docs/server2/test_data/canned_data.py
@@ -205,9 +205,9 @@
           { 'channel': 'beta',
             'extension_types': ['extension']
           },
-          # whitelist
           { 'channel': 'stable',
-            'extension_types': ['extension']
+            'extension_types': ['extension'],
+            'whitelist': ['aaa']
           },
         ],
         'falseBetaAPI': {
@@ -370,8 +370,7 @@
         },
         'declarativeWebRequest': [
           { 'channel': 'beta' },
-          # whitelist
-          { 'channel': 'stable'}
+          { 'channel': 'stable', 'whitelist': ['aaa'] }
         ],
         'downloads': {
           'channel': 'beta'
@@ -500,8 +499,7 @@
         },
         'declarativeWebRequest': [
           { 'channel': 'beta' },
-          # whitelist
-          { 'channel': 'stable'}
+          { 'channel': 'stable', 'whitelist': ['aaa'] }
         ],
         'downloads': {
           'channel': 'dev'
@@ -614,8 +612,7 @@
         },
         'declarativeWebRequest': [
           { 'channel': 'beta' },
-          # whitelist
-          { 'channel': 'stable'}
+          { 'channel': 'stable', 'whitelist': ['aaa'] }
         ],
         'systemInfo.display': {
           'channel': 'stable'
diff --git a/chrome/common/extensions/docs/server2/test_object_store.py b/chrome/common/extensions/docs/server2/test_object_store.py
index c0db64d..65f6249 100644
--- a/chrome/common/extensions/docs/server2/test_object_store.py
+++ b/chrome/common/extensions/docs/server2/test_object_store.py
@@ -26,11 +26,10 @@
   #
 
   def GetMulti(self, keys):
-    class FutureImpl(object):
-      def Get(self2):
-        self._get_count += 1
-        return dict((k, self._store.get(k)) for k in keys if k in self._store)
-    return Future(delegate=FutureImpl())
+    def callback():
+      self._get_count += 1
+      return dict((k, self._store.get(k)) for k in keys if k in self._store)
+    return Future(callback=callback)
 
   def SetMulti(self, mapping):
     self._set_count += 1
diff --git a/chrome/common/extensions/docs/server2/whats_new_data_source.py b/chrome/common/extensions/docs/server2/whats_new_data_source.py
index 05bf875..7d67a20 100644
--- a/chrome/common/extensions/docs/server2/whats_new_data_source.py
+++ b/chrome/common/extensions/docs/server2/whats_new_data_source.py
@@ -8,7 +8,7 @@
 
 from data_source import DataSource
 from extensions_paths import JSON_TEMPLATES, PUBLIC_TEMPLATES
-from future import Gettable, Future
+from future import Future
 
 
 class WhatsNewDataSource(DataSource):
@@ -84,7 +84,7 @@
         'apps': _MakeDictByPlatform('apps'),
         'extensions': _MakeDictByPlatform('extensions')
       }
-    return Future(delegate=Gettable(resolve))
+    return Future(callback=resolve)
 
   def _GetCachedWhatsNewData(self):
     data = self._object_store.Get('whats_new_data').Get()
diff --git a/chrome/common/extensions/docs/templates/articles/cloudMessagingV2.html b/chrome/common/extensions/docs/templates/articles/cloudMessagingV2.html
index eea9671..65f420d 100644
--- a/chrome/common/extensions/docs/templates/articles/cloudMessagingV2.html
+++ b/chrome/common/extensions/docs/templates/articles/cloudMessagingV2.html
@@ -21,6 +21,10 @@
 <p>Please note that GCM Chrome API is experimental. It is only available to Chrome
 users on the dev channel.</p>
 
+<p class="note"><strong>API Samples</strong>: Want to play with the code? Check out the
+<a href="https://github.com/GoogleChrome/chrome-app-samples/tree/master/gcm-notifications">gcm-notifications</a>
+sample.</p>
+
 <h2 id="enable_gcm">Enable GCM</h2>
 
 <p>To use GCM for your app or extension, do the following:</p>
@@ -176,8 +180,25 @@
 <p>If your app or extension is installed in different profiles and/or in different
 Chrome instances, each of them will receive a different registration ID.</p>
 
+<p>Your app or extension could call $(ref:gcm.unregister) to revoke the registration ID.
+The unregistration should only be done in rare cases, such as if your app or
+extension does not want to receive further messages, or the registration ID is
+suspected to be compromised.</p>
+
+<pre data-filename="background.js"><code>
+function unregisterCallback() {
+  if (chrome.runtime.lastError) {
+    // When the unregistration fails, handle the error and retry
+    // the unregistration later.
+    return;
+  }
+}
+
+chrome.gcm.unregister(unregisterCallback);
+</code></pre>
+
 <p>Your app or extension is automatically unregistered from the GCM service when a
-user uninstalls it. You can't unregister using the GCM API.</p>
+user uninstalls it.</p>
 
 <h3 id="receive_messages">Receive messages</h3>
 
@@ -353,6 +374,6 @@
 <h2 id="feedback">Feedback</h2>
 
 <p>You can provide feedback about Google Cloud Messaging and the gcm API through
-the Google Group <a href="https://groups.google.com/forum/#!forum/gcm-for-chrome-v2-feedback">GCM for Chrome V2
+the Google Group <a href="https://groups.google.com/forum/#!forum/gcm-for-chrome-feedback">GCM for Chrome
 Feedback</a>.
 Use this group to ask for help, file bug reports, and request features.</p>
diff --git a/chrome/common/extensions/docs/templates/intros/commands.html b/chrome/common/extensions/docs/templates/intros/commands.html
index 65c3b7c..6d9503b 100644
--- a/chrome/common/extensions/docs/templates/intros/commands.html
+++ b/chrome/common/extensions/docs/templates/intros/commands.html
@@ -1,8 +1,10 @@
 <h2 id="manifest">Manifest</h2>
 <p>
-You must set manifest_version to (at least) 2 to use this API.
+You must have a <code>"manifest_version"</code> of at least <code>2</code> to use this API.
 </p>
 
+{{?is_apps +partials.warning_dev /}}
+
 <h2 id="usage">Usage</h2>
 <p>The commands API allows you to define specific commands, and bind them to a
 default key combination. Each command your extension accepts must be listed in
@@ -74,3 +76,35 @@
 popup opening, consider listening for an 'onDomReady' event inside your popup's
 code.
 </p>
+
+<h2 id="usage">Scope</h2>
+<p>By default, Commands are scoped to the Chrome browser, which means that while
+the browser does not have focus, the shortcut will be inactive. On desktop
+Chrome, Commands can instead have global scope and will then also work while
+Chrome does *not* have focus. NOTE: The exception here is ChromeOS, where global
+commands are not allowed at the moment.</p>
+
+<p>The user is free to designate any shortcut as global using the UI in
+chrome://extensions \ Keyboard Shortcuts, but the extension developer is limited
+to specifying only Ctrl+Shift+[0..9] as global shortcuts. This is to minimize
+the risk of overriding shortcuts in other applications since if, for example,
+Alt+P were to be allowed as global, the printing shortcut might not work in
+other applications.</p>
+
+<p>Example:</p>
+
+<pre data-filename="manifest.json">
+{
+  "name": "My extension",
+  ...
+  "commands": {
+    "toggle-feature-foo": {
+      "suggested_key": {
+        "default": "Ctrl+Shift+5"
+      },
+      "description": "Toggle feature foo",
+      <b>"global": true</b>
+    }
+  },
+  ...
+}</pre>
diff --git a/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html b/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html
index 505c6be..7de1ce8 100644
--- a/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html
+++ b/chrome/common/extensions/docs/templates/intros/declarativeWebRequest.html
@@ -180,10 +180,10 @@
   <tr><td>EditRequestCookie<td><td>✓<td><td>
   <tr><td>EditResponseCookie<td><td><td>✓<td>
   <tr><td>IgnoreRules<td>✓<td>✓<td>✓<td>✓
-  <tr><td>RedirectByRegEx<td>✓<td><td><td>
-  <tr><td>RedirectRequest<td>✓<td><td><td>
-  <tr><td>RedirectToEmptyDocument<td>✓<td><td><td>
-  <tr><td>RedirectToTransparentImage<td>✓<td><td><td>
+  <tr><td>RedirectByRegEx<td>✓<td><td>✓<td>
+  <tr><td>RedirectRequest<td>✓<td><td>✓<td>
+  <tr><td>RedirectToEmptyDocument<td>✓<td><td>✓<td>
+  <tr><td>RedirectToTransparentImage<td>✓<td><td>✓<td>
   <tr><td>RemoveRequestCookie<td><td>✓<td><td>
   <tr><td>RemoveRequestHeader<td><td>✓<td><td>
   <tr><td>RemoveResponseCookie<td><td><td>✓<td>
@@ -198,14 +198,19 @@
 "stages" attribute.
 </p>
 <p>
+<strong>Note:</strong> Redirects initiated by a redirect action use the original
+request method for the redirect, with one exception: If the redirect is
+initiated at the onHeadersReceived stage, then the redirect will be issued using
+the GET method.
+</p>
+<p>
 <strong>Example:</strong> It is possible to combine a
 <code>new chrome.declarativeWebRequest.RequestMatcher({contentType: ["image/jpeg"]})</code>
 condition with a <code>new chrome.declarativeWebRequest.CancelRequest()</code>
 action because both of them can be evaluated in the onHeadersReceived stage.
 It is, however, impossible to combine the request matcher with a
-<code>new chrome.declarativeWebRequest.RedirectToTransparentImage()</code>
-because redirects cannot be executed any more by the time the content
-type has been determined.
+<code>new chrome.declarativeWebRequest.SetRequestHeader()</code>
+because request headers cannot be set any more by the time the content type has been terminated.
 </p>
 
 <h2 id="precedences">Using priorities to override rules</h2>
diff --git a/chrome/common/extensions/docs/templates/intros/mediaGalleries.html b/chrome/common/extensions/docs/templates/intros/mediaGalleries.html
index d5729ea..194ac22 100644
--- a/chrome/common/extensions/docs/templates/intros/mediaGalleries.html
+++ b/chrome/common/extensions/docs/templates/intros/mediaGalleries.html
@@ -110,21 +110,42 @@
 
 <p>If present, the user's iTunes library can be accessed as a media gallery.
 In addition to the media files in the library, the "iTunes Music Library.xml"
-file is also presented. Regardless of where the music files are actually on the
-disk (and where the xml file says they are), they are mapping into an
-Artist/Album/Track hierarchy like iTunes does by default.  This mapping doesn't
-always work perfectly, so there are two things to note for Apps trying to match
-the xml file with files in the gallery. If the filenames for tracks within an
-album are not unique, they will be uniquified by adding the track id in
-parentheses before the extension, and if there is a colon or a slash in the
-artist, album, or track name, they are turned into underscore characters.</p>
+file is also presented.</p>
+<p>Regardless of where the music files are actually on the disk (and where
+the xml file says they are), they are mapped into an Artist/Album/Track
+hierarchy like iTunes does by default.  This mapping doesn't always work
+perfectly, so there are two things to note for Apps trying to match the
+xml file with files in the gallery.</p>
+<p>If the filenames for tracks within an album are not unique, they will be
+uniquified by adding the track id in parentheses before the extension, and
+if there is a colon or a slash in the artist, album, or track name, they are
+turned into underscore characters.</p>
 
 <h2 id="Picasa">Picasa</h2>
 
 <p>If present, the user's Picasa library can also be accessed as a media
 gallery. Directories on the filesystem scanned by Picasa are presented under
-folders/. Picasa Albums are presented under albums/. Albums and Folders that
-have duplicate names and dates will be uniquified using an incrementing
-integer in parenthesis before the extension. Duplicate filenames within the
-same Album will also be uniquified using an incrementing integer in parenthesis
-before the extension.</p>
+folders/. Picasa Albums are presented under albums/.</p>
+<p>Albums and Folders that have duplicate names and dates will be uniquified
+using an incrementing integer in parenthesis before the extension.</p>
+<p>Duplicate filenames within the same Album will also be uniquified using an
+incrementing integer in parenthesis before the extension.</p>
+
+<h2 id="iPhoto">iPhoto</h2>
+
+<p>If present, the user's iPhoto library can be accessed as a media gallery.
+The files are structured within a subdirectory called "Albums/". Within that
+subdirectory, each album in the user's iPhoto library will appear as a
+subdirectory by name, and contain file entries for the photos in that album.
+</p>
+<p>Duplicate album names or image filenames with albums will get a
+disambiguating suffix like "(NN)" where NN is a unique number.</p>
+<p>Any items appearing in multiple albums in iPhoto will appear in all those
+albums in the gallery.</p>
+<p>If the user has modified any images within an album, there will be an
+additional subdirectory called "originals/" within the album directory, which
+will then contain the original image, which will have the same filename as
+the file in the album itself. The file as it appears in the album directory,
+though, will be the one the user has invested time cropping, rotating, or
+otherwise editing.</p>
+
diff --git a/chrome/common/extensions/docs/templates/intros/webRequest.html b/chrome/common/extensions/docs/templates/intros/webRequest.html
index 44b542d..b0a4930 100644
--- a/chrome/common/extensions/docs/templates/intros/webRequest.html
+++ b/chrome/common/extensions/docs/templates/intros/webRequest.html
@@ -58,7 +58,8 @@
   <dd>Fires each time that an HTTP(S) response header is received. Due
   to redirects and authentication requests this can happen multiple times per
   request. This event is intended to allow extensions to add, modify, and delete
-  response headers, such as incoming Set-Cookie headers.</dd>
+  response headers, such as incoming Set-Cookie headers. It also allows you to
+  redirect the request.</dd>
   <dt><code>onAuthRequired</code> (optionally synchronous)</dt>
   <dd>Fires when a request requires authentication of the user. This event can
   be handled synchronously to provide authentication credentials. Note that
diff --git a/chrome/common/extensions/docs/templates/private/ref_link.html b/chrome/common/extensions/docs/templates/private/ref_link.html
index 98408be..bd3817f 100644
--- a/chrome/common/extensions/docs/templates/private/ref_link.html
+++ b/chrome/common/extensions/docs/templates/private/ref_link.html
@@ -1 +1 @@
-<a href="{{link.href}}">{{link.text}}</a>
+$(ref:{{link.ref}} {{link.text}})
diff --git a/chrome/common/extensions/docs/templates/public/apps/accessibilityFeatures.html b/chrome/common/extensions/docs/templates/public/apps/accessibilityFeatures.html
new file mode 100644
index 0000000..f1d58dd
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/apps/accessibilityFeatures.html
@@ -0,0 +1 @@
+{{+partials.standard_apps_api api:apis.accessibility_features/}}
diff --git a/chrome/common/extensions/docs/templates/public/extensions/accessibilityFeatures.html b/chrome/common/extensions/docs/templates/public/extensions/accessibilityFeatures.html
new file mode 100644
index 0000000..f1d58dd
--- /dev/null
+++ b/chrome/common/extensions/docs/templates/public/extensions/accessibilityFeatures.html
@@ -0,0 +1 @@
+{{+partials.standard_apps_api api:apis.accessibility_features/}}
diff --git a/chrome/common/extensions/extension_l10n_util.cc b/chrome/common/extensions/extension_l10n_util.cc
index bc3c229..38891ba 100644
--- a/chrome/common/extensions/extension_l10n_util.cc
+++ b/chrome/common/extensions/extension_l10n_util.cc
@@ -240,12 +240,13 @@
 
   // Initialize search_provider fields.
   base::DictionaryValue* search_provider = NULL;
-  if (manifest->GetDictionary(keys::kSearchProvider, &search_provider)) {
+  if (manifest->GetDictionary(keys::kOverrideSearchProvider,
+                              &search_provider)) {
     for (base::DictionaryValue::Iterator iter(*search_provider);
          !iter.IsAtEnd();
          iter.Advance()) {
-      key.assign(base::StringPrintf("%s.%s", keys::kSearchProvider,
-                                    iter.key().c_str()));
+      key.assign(base::StringPrintf(
+          "%s.%s", keys::kOverrideSearchProvider, iter.key().c_str()));
       bool success = (key == keys::kSettingsOverrideAlternateUrls) ?
           LocalizeManifestListValue(key, messages, manifest, error) :
           LocalizeManifestValue(key, messages, manifest, error);
@@ -254,6 +255,16 @@
     }
   }
 
+  // Initialize chrome_settings_overrides.homepage.
+  if (!LocalizeManifestValue(
+          keys::kOverrideHomepage, messages, manifest, error))
+    return false;
+
+  // Initialize chrome_settings_overrides.startup_pages.
+  if (!LocalizeManifestListValue(
+          keys::kOverrideStartupPage, messages, manifest, error))
+    return false;
+
   // Add current locale key to the manifest, so we can overwrite prefs
   // with new manifest when chrome locale changes.
   manifest->SetString(keys::kCurrentLocale, CurrentLocaleOrDefault());
diff --git a/chrome/common/extensions/extension_l10n_util_unittest.cc b/chrome/common/extensions/extension_l10n_util_unittest.cc
index c5ed18a..442fec0 100644
--- a/chrome/common/extensions/extension_l10n_util_unittest.cc
+++ b/chrome/common/extensions/extension_l10n_util_unittest.cc
@@ -575,7 +575,13 @@
   search_provider->SetString("search_url", "http://www.foo.__MSG_country__");
   search_provider->SetString("favicon_url", "http://www.foo.__MSG_country__");
   search_provider->SetString("suggest_url", "http://www.foo.__MSG_country__");
-  manifest.Set(keys::kSearchProvider, search_provider);
+  manifest.Set(keys::kOverrideSearchProvider, search_provider);
+
+  manifest.SetString(keys::kOverrideHomepage, "http://www.foo.__MSG_country__");
+
+  base::ListValue* startup_pages = new base::ListValue;
+  startup_pages->AppendString("http://www.foo.__MSG_country__");
+  manifest.Set(keys::kOverrideStartupPage, startup_pages);
 
   std::string error;
   scoped_ptr<MessageBundle> messages(CreateManifestBundle());
@@ -590,7 +596,7 @@
   ASSERT_TRUE(manifest.GetString(keys::kDescription, &result));
   EXPECT_EQ("description", result);
 
-  std::string key_prefix(keys::kSearchProvider);
+  std::string key_prefix(keys::kOverrideSearchProvider);
   key_prefix += '.';
   ASSERT_TRUE(manifest.GetString(key_prefix + "name", &result));
   EXPECT_EQ("de", result);
@@ -607,6 +613,13 @@
   ASSERT_TRUE(manifest.GetString(key_prefix + "suggest_url", &result));
   EXPECT_EQ("http://www.foo.de", result);
 
+  ASSERT_TRUE(manifest.GetString(keys::kOverrideHomepage, &result));
+  EXPECT_EQ("http://www.foo.de", result);
+
+  ASSERT_TRUE(manifest.GetList(keys::kOverrideStartupPage, &startup_pages));
+  ASSERT_TRUE(startup_pages->GetString(0, &result));
+  EXPECT_EQ("http://www.foo.de", result);
+
   EXPECT_TRUE(error.empty());
 }
 
diff --git a/chrome/common/extensions/manifest_handlers/settings_overrides_handler.cc b/chrome/common/extensions/manifest_handlers/settings_overrides_handler.cc
index 772c6e2..b36b40a 100644
--- a/chrome/common/extensions/manifest_handlers/settings_overrides_handler.cc
+++ b/chrome/common/extensions/manifest_handlers/settings_overrides_handler.cc
@@ -9,17 +9,18 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/common/extensions/permissions/settings_override_permission.h"
 #include "extensions/common/error_utils.h"
-#include "extensions/common/extension_messages.h"
+#include "extensions/common/extension_set.h"
 #include "extensions/common/feature_switch.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/permissions/api_permission_set.h"
 #include "extensions/common/permissions/manifest_permission.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/settings_override_permission.h"
 #include "grit/generated_resources.h"
 #include "ipc/ipc_message.h"
+#include "ipc/ipc_message_utils.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
@@ -214,12 +215,14 @@
 
 SettingsOverrides::~SettingsOverrides() {}
 
+// static
 const SettingsOverrides* SettingsOverrides::Get(
     const Extension* extension) {
   return static_cast<SettingsOverrides*>(
       extension->GetManifestData(manifest_keys::kSettingsOverride));
 }
 
+// static
 bool SettingsOverrides::RemovesBookmarkButton(
     const SettingsOverrides& settings_overrides) {
   return settings_overrides.bookmarks_ui &&
@@ -227,6 +230,7 @@
       *settings_overrides.bookmarks_ui->remove_button;
 }
 
+// static
 bool SettingsOverrides::RemovesBookmarkShortcut(
     const SettingsOverrides& settings_overrides) {
   return settings_overrides.bookmarks_ui &&
@@ -234,6 +238,13 @@
       *settings_overrides.bookmarks_ui->remove_bookmark_shortcut;
 }
 
+bool SettingsOverrides::RemovesBookmarkOpenPagesShortcut(
+    const SettingsOverrides& settings_overrides) {
+  return settings_overrides.bookmarks_ui &&
+      settings_overrides.bookmarks_ui->remove_bookmark_open_pages_shortcut &&
+      *settings_overrides.bookmarks_ui->remove_bookmark_open_pages_shortcut;
+}
+
 SettingsOverridesHandler::SettingsOverridesHandler() {}
 
 SettingsOverridesHandler::~SettingsOverridesHandler() {}
@@ -306,8 +317,9 @@
     if (!FeatureSwitch::enable_override_bookmarks_ui()->IsEnabled()) {
       warnings->push_back(InstallWarning(
           ErrorUtils::FormatErrorMessage(
-              manifest_errors::kUnrecognizedManifestKey,
-              manifest_keys::kBookmarkUI)));
+              manifest_errors::kUnrecognizedManifestProperty,
+              manifest_keys::kBookmarkUI,
+              manifest_keys::kSettingsOverride)));
     } else if (settings_overrides->bookmarks_ui->hide_bookmark_button) {
       warnings->push_back(InstallWarning(
             ErrorUtils::FormatErrorMessage(
diff --git a/chrome/common/extensions/manifest_handlers/settings_overrides_handler.h b/chrome/common/extensions/manifest_handlers/settings_overrides_handler.h
index 8f7490a..b819a88 100644
--- a/chrome/common/extensions/manifest_handlers/settings_overrides_handler.h
+++ b/chrome/common/extensions/manifest_handlers/settings_overrides_handler.h
@@ -11,6 +11,12 @@
 
 namespace extensions {
 
+enum SettingsApiOverrideType {
+  BUBBLE_TYPE_HOME_PAGE = 0,
+  BUBBLE_TYPE_SEARCH_ENGINE,
+  BUBBLE_TYPE_STARTUP_PAGES,
+};
+
 class ManifestPermission;
 
 // SettingsOverride is associated with "chrome_settings_overrides" manifest key.
@@ -26,6 +32,8 @@
       const SettingsOverrides& settings_overrides);
   static bool RemovesBookmarkShortcut(
       const SettingsOverrides& settings_overrides);
+  static bool RemovesBookmarkOpenPagesShortcut(
+      const SettingsOverrides& settings_overrides);
 
   scoped_ptr<api::manifest_types::ChromeSettingsOverrides::Bookmarks_ui>
       bookmarks_ui;
diff --git a/chrome/common/extensions/manifest_handlers/ui_overrides_handler.cc b/chrome/common/extensions/manifest_handlers/ui_overrides_handler.cc
index 095fe4a..9fd33b5 100644
--- a/chrome/common/extensions/manifest_handlers/ui_overrides_handler.cc
+++ b/chrome/common/extensions/manifest_handlers/ui_overrides_handler.cc
@@ -152,6 +152,13 @@
       *ui_overrides.bookmarks_ui->remove_bookmark_shortcut;
 }
 
+bool UIOverrides::RemovesBookmarkOpenPagesShortcut(
+    const UIOverrides& ui_overrides) {
+  return ui_overrides.bookmarks_ui &&
+      ui_overrides.bookmarks_ui->remove_bookmark_open_pages_shortcut &&
+      *ui_overrides.bookmarks_ui->remove_bookmark_open_pages_shortcut;
+}
+
 UIOverridesHandler::UIOverridesHandler() {}
 
 UIOverridesHandler::~UIOverridesHandler() {}
@@ -187,8 +194,9 @@
     if (!FeatureSwitch::enable_override_bookmarks_ui()->IsEnabled()) {
       warnings->push_back(InstallWarning(
           ErrorUtils::FormatErrorMessage(
-              manifest_errors::kUnrecognizedManifestKey,
-              manifest_keys::kBookmarkUI)));
+              manifest_errors::kUnrecognizedManifestProperty,
+              manifest_keys::kBookmarkUI,
+              manifest_keys::kUIOverride)));
     }
   }
 
diff --git a/chrome/common/extensions/manifest_handlers/ui_overrides_handler.h b/chrome/common/extensions/manifest_handlers/ui_overrides_handler.h
index 7d9ca34..4846757 100644
--- a/chrome/common/extensions/manifest_handlers/ui_overrides_handler.h
+++ b/chrome/common/extensions/manifest_handlers/ui_overrides_handler.h
@@ -24,6 +24,7 @@
 
   static bool RemovesBookmarkButton(const UIOverrides& ui_overrides);
   static bool RemovesBookmarkShortcut(const UIOverrides& ui_overrides);
+  static bool RemovesBookmarkOpenPagesShortcut(const UIOverrides& ui_overrides);
 
   scoped_ptr<api::manifest_types::ChromeUIOverrides::Bookmarks_ui> bookmarks_ui;
 
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_service_worker_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_service_worker_unittest.cc
index 414619f..10f4de8 100644
--- a/chrome/common/extensions/manifest_tests/extension_manifests_service_worker_unittest.cc
+++ b/chrome/common/extensions/manifest_tests/extension_manifests_service_worker_unittest.cc
@@ -20,12 +20,18 @@
 
 class ExtensionManifestServiceWorkerTest : public ExtensionManifestTest {
  public:
+  ExtensionManifestServiceWorkerTest()
+      : trunk_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {}
+
   void AddServiceWorkerCommandLineSwitch() {
     CHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
         switches::kEnableServiceWorker));
     CommandLine::ForCurrentProcess()->AppendSwitch(
         switches::kEnableServiceWorker);
   }
+
+  // "app.service_worker" is restricted to trunk in _manifest_features.json.
+  extensions::ScopedCurrentChannel trunk_channel_;
 };
 
 // Checks that a service_worker key is ignored without enable-service-worker
@@ -91,6 +97,8 @@
       "  }"
       "}"));
   ASSERT_TRUE(extension.get());
+  // "app.service_worker" key exists and access is permitted.
+  EXPECT_TRUE(extension->manifest()->HasPath("app.service_worker"));
   EXPECT_EQ("service_worker.js",
             BackgroundInfo::GetServiceWorkerScript(extension.get()));
 
diff --git a/chrome/common/extensions/manifest_url_handler.cc b/chrome/common/extensions/manifest_url_handler.cc
index 08bed8b..557c1c2 100644
--- a/chrome/common/extensions/manifest_url_handler.cc
+++ b/chrome/common/extensions/manifest_url_handler.cc
@@ -292,7 +292,7 @@
                    page != chrome::kChromeUIActivationMessageHost);
 #endif
 #if defined(OS_CHROMEOS)
-    is_override = (is_override && page != keyboard::kKeyboardWebUIHost);
+    is_override = (is_override && page != keyboard::kKeyboardHost);
 #endif
 
     if (is_override || !iter.value().GetAsString(&val)) {
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index f05dc67..bf7c7ec 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/common/extensions/permissions/chrome_api_permissions.h"
 
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
-#include "chrome/common/extensions/permissions/usb_device_permission.h"
 #include "extensions/common/permissions/api_permission.h"
 #include "extensions/common/permissions/api_permission_set.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
 #include "extensions/common/permissions/permission_message.h"
 #include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/socket_permission.h"
+#include "extensions/common/permissions/usb_device_permission.h"
 #include "grit/generated_resources.h"
 
 namespace extensions {
@@ -84,6 +84,14 @@
         {APIPermission::kGcm, "gcm"},
 
         // Register extension permissions.
+        {APIPermission::kAccessibilityFeaturesModify,
+         "accessibilityFeatures.modify", APIPermissionInfo::kFlagNone,
+         IDS_EXTENSION_PROMPT_WARNING_ACCESSIBILITY_FEATURES_MODIFY,
+         PermissionMessage::kAccessibilityFeaturesModify},
+        {APIPermission::kAccessibilityFeaturesRead,
+         "accessibilityFeatures.read", APIPermissionInfo::kFlagNone,
+         IDS_EXTENSION_PROMPT_WARNING_ACCESSIBILITY_FEATURES_READ,
+         PermissionMessage::kAccessibilityFeaturesRead},
         {APIPermission::kActiveTab, "activeTab"},
         {APIPermission::kAdView, "adview"},
         {APIPermission::kAlarms, "alarms"},
diff --git a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
index 94cb2c4..69236b8 100644
--- a/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
+++ b/chrome/common/extensions/permissions/chrome_permission_message_provider.cc
@@ -5,9 +5,9 @@
 #include "chrome/common/extensions/permissions/chrome_permission_message_provider.h"
 
 #include "base/stl_util.h"
-#include "chrome/common/extensions/permissions/permission_message_util.h"
 #include "extensions/common/extensions_client.h"
 #include "extensions/common/permissions/permission_message.h"
+#include "extensions/common/permissions/permission_message_util.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/url_pattern_set.h"
 #include "grit/generated_resources.h"
diff --git a/chrome/common/extensions/permissions/media_galleries_permission.cc b/chrome/common/extensions/permissions/media_galleries_permission.cc
deleted file mode 100644
index 8c87bf3..0000000
--- a/chrome/common/extensions/permissions/media_galleries_permission.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
-
-#include <set>
-#include <string>
-
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "extensions/common/permissions/permissions_info.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace {
-
-// copyTo permission requires delete permission as a prerequisite.
-// delete permission requires read permission as a prerequisite.
-bool IsValidPermissionSet(bool has_read, bool has_copy_to, bool has_delete,
-                          std::string* error) {
-  if (has_copy_to) {
-    if (has_read && has_delete)
-      return true;
-    if (error)
-      *error = "copyTo permission requires read and delete permissions";
-    return false;
-  }
-  if (has_delete) {
-    if (has_read)
-      return true;
-    if (error)
-      *error = "delete permission requires read permission";
-    return false;
-  }
-  return true;
-}
-
-}  // namespace
-
-namespace extensions {
-
-const char MediaGalleriesPermission::kAllAutoDetectedPermission[] =
-    "allAutoDetected";
-const char MediaGalleriesPermission::kScanPermission[] = "scan";
-const char MediaGalleriesPermission::kReadPermission[] = "read";
-const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo";
-const char MediaGalleriesPermission::kDeletePermission[] = "delete";
-
-MediaGalleriesPermission::MediaGalleriesPermission(
-    const APIPermissionInfo* info)
-  : SetDisjunctionPermission<MediaGalleriesPermissionData,
-                             MediaGalleriesPermission>(info) {
-}
-
-MediaGalleriesPermission::~MediaGalleriesPermission() {
-}
-
-bool MediaGalleriesPermission::FromValue(const base::Value* value,
-                                         std::string* error) {
-  if (!SetDisjunctionPermission<MediaGalleriesPermissionData,
-                                MediaGalleriesPermission>::FromValue(value,
-                                                                     error)) {
-    return false;
-  }
-
-  bool has_read = false;
-  bool has_copy_to = false;
-  bool has_delete = false;
-  for (std::set<MediaGalleriesPermissionData>::const_iterator it =
-      data_set_.begin(); it != data_set_.end(); ++it) {
-    if (it->permission() == kAllAutoDetectedPermission ||
-        it->permission() == kScanPermission) {
-      continue;
-    }
-    if (it->permission() == kReadPermission) {
-      has_read = true;
-      continue;
-    }
-    if (it->permission() == kCopyToPermission) {
-      has_copy_to = true;
-      continue;
-    }
-    if (it->permission() == kDeletePermission) {
-      has_delete = true;
-      continue;
-    }
-
-    // No other permissions, so reaching this means
-    // MediaGalleriesPermissionData is probably out of sync in some way.
-    // Fail so developers notice this.
-    NOTREACHED();
-    return false;
-  }
-
-  return IsValidPermissionSet(has_read, has_copy_to, has_delete, error);
-}
-
-PermissionMessages MediaGalleriesPermission::GetMessages() const {
-  DCHECK(HasMessages());
-  PermissionMessages result;
-
-  bool has_all_auto_detected = false;
-  bool has_read = false;
-  bool has_copy_to = false;
-  bool has_delete = false;
-
-  for (std::set<MediaGalleriesPermissionData>::const_iterator it =
-      data_set_.begin(); it != data_set_.end(); ++it) {
-    if (it->permission() == kAllAutoDetectedPermission)
-      has_all_auto_detected = true;
-    else if (it->permission() == kReadPermission)
-      has_read = true;
-    else if (it->permission() == kCopyToPermission)
-      has_copy_to = true;
-    else if (it->permission() == kDeletePermission)
-      has_delete = true;
-  }
-
-  if (!IsValidPermissionSet(has_read, has_copy_to, has_delete, NULL)) {
-    NOTREACHED();
-    return result;
-  }
-
-  // If |has_all_auto_detected| is false, then Chrome will prompt the user at
-  // runtime when the extension call the getMediaGalleries API.
-  if (!has_all_auto_detected)
-    return result;
-  // No access permission case.
-  if (!has_read)
-    return result;
-
-  // Separate PermissionMessage IDs for read, copyTo, and delete. Otherwise an
-  // extension can silently gain new access capabilities.
-  result.push_back(PermissionMessage(
-      PermissionMessage::kMediaGalleriesAllGalleriesRead,
-      l10n_util::GetStringUTF16(
-          IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ)));
-
-  // For copyTo and delete, the proper combined permission message will be
-  // derived in ChromePermissionMessageProvider::GetWarningMessages(), such
-  // that the user get 1 entry for all media galleries access permissions,
-  // rather than several separate entries.
-  if (has_copy_to) {
-    result.push_back(PermissionMessage(
-        PermissionMessage::kMediaGalleriesAllGalleriesCopyTo,
-        base::string16()));
-  }
-  if (has_delete) {
-    result.push_back(PermissionMessage(
-        PermissionMessage::kMediaGalleriesAllGalleriesDelete,
-        base::string16()));
-  }
-  return result;
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/media_galleries_permission.h b/chrome/common/extensions/permissions/media_galleries_permission.h
deleted file mode 100644
index 33e6d0f..0000000
--- a/chrome/common/extensions/permissions/media_galleries_permission.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
-
-#include "base/basictypes.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission_data.h"
-#include "chrome/common/extensions/permissions/set_disjunction_permission.h"
-#include "extensions/common/permissions/api_permission.h"
-
-namespace extensions {
-
-// Media Galleries permissions are as follows:
-//   <media-galleries-permission-pattern>
-//             := <access> | <access> 'allAutoDetected' | 'allAutoDetected' |
-//                <access> 'scan' | 'scan'
-//   <access>  := 'read' | 'read' <access> | 'read' <secondary-access>
-//   <secondary-access>
-//             := 'delete' | 'delete' <secondary-access> |
-//                'delete' <tertiary-access>
-//   <tertiary-access>
-//             := 'copyTo' | 'copyTo' <tertiary-access>
-class MediaGalleriesPermission
-  : public SetDisjunctionPermission<MediaGalleriesPermissionData,
-                                    MediaGalleriesPermission> {
- public:
-  struct CheckParam : public APIPermission::CheckParam {
-    explicit CheckParam(const std::string& permission)
-      : permission(permission) {}
-    const std::string permission;
-  };
-
-  explicit MediaGalleriesPermission(const APIPermissionInfo* info);
-  virtual ~MediaGalleriesPermission();
-
-  // SetDisjunctionPermission overrides.
-  // MediaGalleriesPermission does additional checks to make sure the
-  // permissions do not contain unknown values.
-  virtual bool FromValue(const base::Value* value, std::string* error) OVERRIDE;
-
-  // APIPermission overrides.
-  virtual PermissionMessages GetMessages() const OVERRIDE;
-
-  // Permission strings.
-  static const char kAllAutoDetectedPermission[];
-  static const char kScanPermission[];
-  static const char kReadPermission[];
-  static const char kCopyToPermission[];
-  static const char kDeletePermission[];
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
diff --git a/chrome/common/extensions/permissions/media_galleries_permission_data.cc b/chrome/common/extensions/permissions/media_galleries_permission_data.cc
deleted file mode 100644
index fd8a9da..0000000
--- a/chrome/common/extensions/permissions/media_galleries_permission_data.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/media_galleries_permission_data.h"
-
-#include "base/strings/string_util.h"
-#include "base/values.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
-
-namespace extensions {
-
-MediaGalleriesPermissionData::MediaGalleriesPermissionData() {
-}
-
-bool MediaGalleriesPermissionData::Check(
-    const APIPermission::CheckParam* param) const {
-  if (!param)
-    return false;
-
-  const MediaGalleriesPermission::CheckParam& specific_param =
-      *static_cast<const MediaGalleriesPermission::CheckParam*>(param);
-  return permission_ == specific_param.permission;
-}
-
-scoped_ptr<base::Value> MediaGalleriesPermissionData::ToValue() const {
-  return scoped_ptr<base::Value>(new base::StringValue(permission_));
-}
-
-bool MediaGalleriesPermissionData::FromValue(const base::Value* value) {
-  if (!value)
-    return false;
-
-  std::string raw_permission;
-  if (!value->GetAsString(&raw_permission))
-    return false;
-
-  std::string permission;
-  base::TrimWhitespaceASCII(raw_permission, base::TRIM_ALL, &permission);
-
-  if (permission == MediaGalleriesPermission::kAllAutoDetectedPermission ||
-      permission == MediaGalleriesPermission::kScanPermission ||
-      permission == MediaGalleriesPermission::kReadPermission ||
-      permission == MediaGalleriesPermission::kCopyToPermission ||
-      permission == MediaGalleriesPermission::kDeletePermission) {
-    permission_ = permission;
-    return true;
-  }
-  return false;
-}
-
-bool MediaGalleriesPermissionData::operator<(
-    const MediaGalleriesPermissionData& rhs) const {
-  return permission_ < rhs.permission_;
-}
-
-bool MediaGalleriesPermissionData::operator==(
-    const MediaGalleriesPermissionData& rhs) const {
-  return permission_ == rhs.permission_;
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/media_galleries_permission_data.h b/chrome/common/extensions/permissions/media_galleries_permission_data.h
deleted file mode 100644
index 9d13eae..0000000
--- a/chrome/common/extensions/permissions/media_galleries_permission_data.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "extensions/common/permissions/api_permission.h"
-
-namespace base {
-class Value;
-}
-
-namespace extensions {
-
-// A MediaGalleriesPermissionData instance represents a single part of the
-// MediaGalleriesPermission. e.g. "read" or "allAutoDetected".
-class MediaGalleriesPermissionData {
- public:
-  MediaGalleriesPermissionData();
-
-  // Check if |param| (which must be a MediaGalleriesPermission::CheckParam)
-  // matches the encapsulated attribute.
-  bool Check(const APIPermission::CheckParam* param) const;
-
-  // Convert |this| into a base::Value.
-  scoped_ptr<base::Value> ToValue() const;
-
-  // Populate |this| from a base::Value.
-  bool FromValue(const base::Value* value);
-
-  bool operator<(const MediaGalleriesPermissionData& rhs) const;
-  bool operator==(const MediaGalleriesPermissionData& rhs) const;
-
-  std::string permission() const { return permission_; }
-
-  // This accessor is provided for IPC_STRUCT_TRAITS_MEMBER.  Please think
-  // twice before using it for anything else.
-  std::string& permission() { return permission_; }
-
- private:
-  std::string permission_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
diff --git a/chrome/common/extensions/permissions/media_galleries_permission_unittest.cc b/chrome/common/extensions/permissions/media_galleries_permission_unittest.cc
index 1006d3c..8540376 100644
--- a/chrome/common/extensions/permissions/media_galleries_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/media_galleries_permission_unittest.cc
@@ -5,9 +5,9 @@
 // These tests make sure MediaGalleriesPermission values are parsed correctly.
 
 #include "base/values.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission_data.h"
 #include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
+#include "extensions/common/permissions/media_galleries_permission_data.h"
 #include "extensions/common/permissions/permissions_info.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/common/extensions/permissions/permission_message_util.cc b/chrome/common/extensions/permissions/permission_message_util.cc
deleted file mode 100644
index f881eed..0000000
--- a/chrome/common/extensions/permissions/permission_message_util.cc
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/permission_message_util.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/public/common/url_constants.h"
-#include "extensions/common/permissions/permission_message.h"
-#include "extensions/common/permissions/permission_set.h"
-#include "extensions/common/url_pattern_set.h"
-#include "grit/generated_resources.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using extensions::PermissionMessage;
-using extensions::PermissionSet;
-using extensions::URLPatternSet;
-
-namespace {
-
-// Helper for GetDistinctHosts(): com > net > org > everything else.
-bool RcdBetterThan(const std::string& a, const std::string& b) {
-  if (a == b)
-    return false;
-  if (a == "com")
-    return true;
-  if (a == "net")
-    return b != "com";
-  if (a == "org")
-    return b != "com" && b != "net";
-  return false;
-}
-
-}  // namespace
-
-namespace permission_message_util {
-
-PermissionMessage CreateFromHostList(const std::set<std::string>& hosts) {
-  std::vector<std::string> host_list(hosts.begin(), hosts.end());
-  DCHECK(host_list.size());
-  PermissionMessage::ID message_id;
-  base::string16 message;
-  base::string16 details;
-
-  switch (host_list.size()) {
-    case 1:
-      message_id = PermissionMessage::kHosts1;
-      message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
-                                           base::UTF8ToUTF16(host_list[0]));
-      break;
-    case 2:
-      message_id = PermissionMessage::kHosts2;
-      message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
-                                           base::UTF8ToUTF16(host_list[0]),
-                                           base::UTF8ToUTF16(host_list[1]));
-      break;
-    case 3:
-      message_id = PermissionMessage::kHosts3;
-      message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
-                                           base::UTF8ToUTF16(host_list[0]),
-                                           base::UTF8ToUTF16(host_list[1]),
-                                           base::UTF8ToUTF16(host_list[2]));
-      break;
-    default:
-      message_id = PermissionMessage::kHosts4OrMore;
-
-      const int kRetainedFilesMessageIDs[6] = {
-          IDS_EXTENSION_PROMPT_WARNING_HOSTS_DEFAULT,
-          IDS_EXTENSION_PROMPT_WARNING_HOST_SINGULAR,
-          IDS_EXTENSION_PROMPT_WARNING_HOSTS_ZERO,
-          IDS_EXTENSION_PROMPT_WARNING_HOSTS_TWO,
-          IDS_EXTENSION_PROMPT_WARNING_HOSTS_FEW,
-          IDS_EXTENSION_PROMPT_WARNING_HOSTS_MANY,
-      };
-      std::vector<int> message_ids;
-      for (size_t i = 0; i < arraysize(kRetainedFilesMessageIDs); i++) {
-        message_ids.push_back(kRetainedFilesMessageIDs[i]);
-      }
-      message = l10n_util::GetPluralStringFUTF16(message_ids, host_list.size());
-
-      for (size_t i = 0; i < host_list.size(); ++i) {
-        if (i > 0)
-          details += base::ASCIIToUTF16("\n");
-        details += l10n_util::GetStringFUTF16(
-            IDS_EXTENSION_PROMPT_WARNING_HOST_LIST_ENTRY,
-            base::UTF8ToUTF16(host_list[i]));
-      }
-  }
-
-  return PermissionMessage(message_id, message, details);
-}
-
-std::set<std::string> GetDistinctHosts(
-    const URLPatternSet& host_patterns,
-    bool include_rcd,
-    bool exclude_file_scheme) {
-  // Use a vector to preserve order (also faster than a map on small sets).
-  // Each item is a host split into two parts: host without RCDs and
-  // current best RCD.
-  typedef std::vector<std::pair<std::string, std::string> > HostVector;
-  HostVector hosts_best_rcd;
-  for (URLPatternSet::const_iterator i = host_patterns.begin();
-       i != host_patterns.end(); ++i) {
-    if (exclude_file_scheme && i->scheme() == content::kFileScheme)
-      continue;
-
-    std::string host = i->host();
-
-    // Add the subdomain wildcard back to the host, if necessary.
-    if (i->match_subdomains())
-      host = "*." + host;
-
-    // If the host has an RCD, split it off so we can detect duplicates.
-    std::string rcd;
-    size_t reg_len = net::registry_controlled_domains::GetRegistryLength(
-        host,
-        net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
-        net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
-    if (reg_len && reg_len != std::string::npos) {
-      if (include_rcd)  // else leave rcd empty
-        rcd = host.substr(host.size() - reg_len);
-      host = host.substr(0, host.size() - reg_len);
-    }
-
-    // Check if we've already seen this host.
-    HostVector::iterator it = hosts_best_rcd.begin();
-    for (; it != hosts_best_rcd.end(); ++it) {
-      if (it->first == host)
-        break;
-    }
-    // If this host was found, replace the RCD if this one is better.
-    if (it != hosts_best_rcd.end()) {
-      if (include_rcd && RcdBetterThan(rcd, it->second))
-        it->second = rcd;
-    } else {  // Previously unseen host, append it.
-      hosts_best_rcd.push_back(std::make_pair(host, rcd));
-    }
-  }
-
-  // Build up the final vector by concatenating hosts and RCDs.
-  std::set<std::string> distinct_hosts;
-  for (HostVector::iterator it = hosts_best_rcd.begin();
-       it != hosts_best_rcd.end(); ++it)
-    distinct_hosts.insert(it->first + it->second);
-  return distinct_hosts;
-}
-
-}  // namespace permission_message_util
diff --git a/chrome/common/extensions/permissions/permission_message_util.h b/chrome/common/extensions/permissions/permission_message_util.h
deleted file mode 100644
index 13b41c1..0000000
--- a/chrome/common/extensions/permissions/permission_message_util.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
-
-#include <set>
-#include <string>
-
-namespace extensions {
-class PermissionMessage;
-class PermissionSet;
-class URLPatternSet;
-}
-
-namespace permission_message_util {
-
-// Creates the corresponding permission message for a list of hosts.
-// The messages change depending on what hosts are present.
-extensions::PermissionMessage CreateFromHostList(
-    const std::set<std::string>& hosts);
-
-std::set<std::string> GetDistinctHosts(
-    const extensions::URLPatternSet& host_patterns,
-    bool include_rcd,
-    bool exclude_file_scheme);
-
-}  // namespace permission_message_util
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index b42fb5e..77baf5f 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -12,14 +12,14 @@
 #include "chrome/common/extensions/extension_test_util.h"
 #include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/permissions/chrome_permission_message_provider.h"
-#include "chrome/common/extensions/permissions/permission_message_util.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
 #include "extensions/common/error_utils.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/permissions/permission_message_provider.h"
+#include "extensions/common/permissions/permission_message_util.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/socket_permission.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using extension_test_util::LoadManifest;
diff --git a/chrome/common/extensions/permissions/set_disjunction_permission.h b/chrome/common/extensions/permissions/set_disjunction_permission.h
deleted file mode 100644
index b05917f..0000000
--- a/chrome/common/extensions/permissions/set_disjunction_permission.h
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
-
-#include <algorithm>
-#include <set>
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "extensions/common/extension_messages.h"
-#include "extensions/common/permissions/api_permission.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_message_utils.h"
-
-namespace extensions {
-
-// An abstract base class for permissions that are represented by the
-// disjunction of a set of conditions.  Each condition is represented by a
-// |PermissionDataType| (e.g. SocketPermissionData).  If an
-// APIPermission::CheckParam matches any of the conditions in the set, the
-// permission is granted.
-//
-// For an example of how to use this class, see SocketPermission.
-template <class PermissionDataType, class DerivedType>
-class SetDisjunctionPermission : public APIPermission {
- public:
-  explicit SetDisjunctionPermission(const APIPermissionInfo* info)
-    : APIPermission(info) {
-  }
-
-  ~SetDisjunctionPermission() {
-  }
-
-  // APIPermission overrides
-  virtual bool HasMessages() const OVERRIDE {
-    return !data_set_.empty();
-  }
-
-  virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE {
-    for (typename std::set<PermissionDataType>::const_iterator i =
-        data_set_.begin(); i != data_set_.end(); ++i) {
-      if (i->Check(param))
-        return true;
-    }
-    return false;
-  }
-
-  virtual bool Contains(const APIPermission* rhs) const OVERRIDE {
-    CHECK(rhs->info() == info());
-    const SetDisjunctionPermission* perm =
-        static_cast<const SetDisjunctionPermission*>(rhs);
-    return std::includes(
-        data_set_.begin(), data_set_.end(),
-        perm->data_set_.begin(), perm->data_set_.end());
-  }
-
-  virtual bool Equal(const APIPermission* rhs) const OVERRIDE {
-    CHECK(rhs->info() == info());
-    const SetDisjunctionPermission* perm =
-        static_cast<const SetDisjunctionPermission*>(rhs);
-    return data_set_ == perm->data_set_;
-  }
-
-  virtual APIPermission* Clone() const OVERRIDE {
-    SetDisjunctionPermission* result = new DerivedType(info());
-    result->data_set_ = data_set_;
-    return result;
-  }
-
-  virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE {
-    CHECK(rhs->info() == info());
-    const SetDisjunctionPermission* perm =
-        static_cast<const SetDisjunctionPermission*>(rhs);
-    scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
-    std::set_difference(
-        data_set_.begin(), data_set_.end(),
-        perm->data_set_.begin(), perm->data_set_.end(),
-        std::inserter<std::set<PermissionDataType> >(
-            result->data_set_, result->data_set_.begin()));
-    return result->data_set_.empty() ? NULL : result.release();
-  }
-
-  virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE {
-    CHECK(rhs->info() == info());
-    const SetDisjunctionPermission* perm =
-        static_cast<const SetDisjunctionPermission*>(rhs);
-    scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
-    std::set_union(
-        data_set_.begin(), data_set_.end(),
-        perm->data_set_.begin(), perm->data_set_.end(),
-        std::inserter<std::set<PermissionDataType> >(
-            result->data_set_, result->data_set_.begin()));
-    return result.release();
-  }
-
-  virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE {
-    CHECK(rhs->info() == info());
-    const SetDisjunctionPermission* perm =
-        static_cast<const SetDisjunctionPermission*>(rhs);
-    scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
-    std::set_intersection(
-        data_set_.begin(), data_set_.end(),
-        perm->data_set_.begin(), perm->data_set_.end(),
-        std::inserter<std::set<PermissionDataType> >(
-            result->data_set_, result->data_set_.begin()));
-    return result->data_set_.empty() ? NULL : result.release();
-  }
-
-  virtual bool FromValue(const base::Value* value,
-                         std::string* error) OVERRIDE {
-    data_set_.clear();
-    const base::ListValue* list = NULL;
-
-    if (!value || !value->GetAsList(&list) || list->GetSize() == 0) {
-      if (error)
-        *error = "NULL or empty permission list";
-      return false;
-    }
-
-    for (size_t i = 0; i < list->GetSize(); ++i) {
-      const base::Value* item_value = NULL;
-      bool got_item = list->Get(i, &item_value);
-      DCHECK(got_item);
-      DCHECK(item_value);
-
-      PermissionDataType data;
-      if (!data.FromValue(item_value)) {
-        if (error)
-          *error = "Cannot parse an item from the permission list";
-        return false;
-      }
-
-      data_set_.insert(data);
-    }
-    return true;
-  }
-
-  virtual scoped_ptr<base::Value> ToValue() const OVERRIDE {
-    base::ListValue* list = new base::ListValue();
-    typename std::set<PermissionDataType>::const_iterator i;
-    for (i = data_set_.begin(); i != data_set_.end(); ++i) {
-      scoped_ptr<base::Value> item_value(i->ToValue());
-      list->Append(item_value.release());
-    }
-    return scoped_ptr<base::Value>(list);
-  }
-
-  virtual void Write(IPC::Message* m) const OVERRIDE {
-    IPC::WriteParam(m, data_set_);
-  }
-
-  virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE {
-    return IPC::ReadParam(m, iter, &data_set_);
-  }
-
-  virtual void Log(std::string* log) const OVERRIDE {
-    IPC::LogParam(data_set_, log);
-  }
-
- protected:
-  std::set<PermissionDataType> data_set_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
diff --git a/chrome/common/extensions/permissions/settings_override_permission.cc b/chrome/common/extensions/permissions/settings_override_permission.cc
deleted file mode 100644
index 934bf98..0000000
--- a/chrome/common/extensions/permissions/settings_override_permission.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/settings_override_permission.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace extensions {
-
-SettingsOverrideAPIPermission::SettingsOverrideAPIPermission(
-    const APIPermissionInfo* permission, const std::string& setting_value)
-    : APIPermission(permission),
-      setting_value_(setting_value) {
-}
-
-SettingsOverrideAPIPermission::~SettingsOverrideAPIPermission() {
-}
-
-bool SettingsOverrideAPIPermission::HasMessages() const {
-  return info()->message_id() > PermissionMessage::kNone;
-}
-
-PermissionMessages SettingsOverrideAPIPermission::GetMessages() const {
-  DCHECK(HasMessages());
-  int string_id = -1;
-  switch (id()) {
-    case kHomepage: {
-      string_id = IDS_EXTENSION_PROMPT_WARNING_HOME_PAGE_SETTING_OVERRIDE;
-      break;
-    }
-    case kStartupPages: {
-      string_id = IDS_EXTENSION_PROMPT_WARNING_START_PAGE_SETTING_OVERRIDE;
-      break;
-    }
-    case kSearchProvider: {
-      string_id = IDS_EXTENSION_PROMPT_WARNING_SEARCH_SETTINGS_OVERRIDE;
-      break;
-    }
-    default:
-      NOTREACHED();
-  }
-  PermissionMessages result;
-  result.push_back(PermissionMessage(
-      info()->message_id(),
-      l10n_util::GetStringFUTF16(string_id,
-                                 base::UTF8ToUTF16(setting_value_))));
-  return result;
-}
-
-bool SettingsOverrideAPIPermission::Check(
-    const APIPermission::CheckParam* param) const {
-  return (param == NULL);
-}
-
-bool SettingsOverrideAPIPermission::Contains(const APIPermission* rhs) const {
-  CHECK_EQ(info(), rhs->info());
-  return true;
-}
-
-bool SettingsOverrideAPIPermission::Equal(const APIPermission* rhs) const {
-  if (this != rhs)
-    CHECK_EQ(info(), rhs->info());
-  return true;
-}
-
-bool SettingsOverrideAPIPermission::FromValue(const base::Value* value,
-                                              std::string* /*error*/) {
-  return (value == NULL);
-}
-
-scoped_ptr<base::Value> SettingsOverrideAPIPermission::ToValue() const {
-  return scoped_ptr<base::Value>();
-}
-
-APIPermission* SettingsOverrideAPIPermission::Clone() const {
-  return new SettingsOverrideAPIPermission(info(), setting_value_);
-}
-
-APIPermission* SettingsOverrideAPIPermission::Diff(
-    const APIPermission* rhs) const {
-  CHECK_EQ(info(), rhs->info());
-  return NULL;
-}
-
-APIPermission* SettingsOverrideAPIPermission::Union(
-    const APIPermission* rhs) const {
-  CHECK_EQ(info(), rhs->info());
-  return new SettingsOverrideAPIPermission(info(), setting_value_);
-}
-
-APIPermission* SettingsOverrideAPIPermission::Intersect(
-    const APIPermission* rhs) const {
-  CHECK_EQ(info(), rhs->info());
-  return new SettingsOverrideAPIPermission(info(), setting_value_);
-}
-
-void SettingsOverrideAPIPermission::Write(IPC::Message* m) const {
-}
-
-bool SettingsOverrideAPIPermission::Read(
-    const IPC::Message* m, PickleIterator* iter) {
-  return true;
-}
-
-void SettingsOverrideAPIPermission::Log(std::string* log) const {
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/settings_override_permission.h b/chrome/common/extensions/permissions/settings_override_permission.h
deleted file mode 100644
index d123f83..0000000
--- a/chrome/common/extensions/permissions/settings_override_permission.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
-
-#include <string>
-
-#include "extensions/common/permissions/api_permission.h"
-
-namespace extensions {
-
-// Takes care of creating custom permission messages for extensions that
-// override settings.
-class SettingsOverrideAPIPermission : public APIPermission {
- public:
-  SettingsOverrideAPIPermission(
-      const APIPermissionInfo* permission, const std::string& setting_value);
-  virtual ~SettingsOverrideAPIPermission();
-
-  // APIPermission overrides.
-  virtual bool HasMessages() const OVERRIDE;
-  virtual PermissionMessages GetMessages() const OVERRIDE;
-  virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE;
-  virtual bool Contains(const APIPermission* rhs) const OVERRIDE;
-  virtual bool Equal(const APIPermission* rhs) const OVERRIDE;
-  virtual bool FromValue(const base::Value* value, std::string* error) OVERRIDE;
-  virtual scoped_ptr<base::Value> ToValue() const OVERRIDE;
-  virtual APIPermission* Clone() const OVERRIDE;
-  virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE;
-  virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE;
-  virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE;
-  virtual void Write(IPC::Message* m) const OVERRIDE;
-  virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE;
-  virtual void Log(std::string* log) const OVERRIDE;
-
- private:
-  std::string setting_value_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
diff --git a/chrome/common/extensions/permissions/settings_override_permission_unittest.cc b/chrome/common/extensions/permissions/settings_override_permission_unittest.cc
index c290a78..d5b9a04 100644
--- a/chrome/common/extensions/permissions/settings_override_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/settings_override_permission_unittest.cc
@@ -8,10 +8,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "chrome/common/extensions/manifest_tests/extension_manifest_test.h"
-#include "chrome/common/extensions/permissions/settings_override_permission.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/settings_override_permission.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
diff --git a/chrome/common/extensions/permissions/socket_permission.cc b/chrome/common/extensions/permissions/socket_permission.cc
deleted file mode 100644
index 6c08127..0000000
--- a/chrome/common/extensions/permissions/socket_permission.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/socket_permission.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/common/extensions/permissions/set_disjunction_permission.h"
-#include "extensions/common/permissions/permissions_info.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-namespace extensions {
-
-SocketPermission::SocketPermission(const APIPermissionInfo* info)
-  : SetDisjunctionPermission<SocketPermissionData, SocketPermission>(info) {
-}
-
-SocketPermission::~SocketPermission() {
-}
-
-PermissionMessages SocketPermission::GetMessages() const {
-  DCHECK(HasMessages());
-  PermissionMessages result;
-  if (!AddAnyHostMessage(result)) {
-    AddSpecificHostMessage(result);
-    AddSubdomainHostMessage(result);
-  }
-  AddNetworkListMessage(result);
-  return result;
-}
-
-bool SocketPermission::AddAnyHostMessage(PermissionMessages& messages) const {
-  std::set<SocketPermissionData>::const_iterator i;
-  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
-    if (i->entry().IsAddressBoundType() &&
-        i->entry().GetHostType() == SocketPermissionEntry::ANY_HOST) {
-      messages.push_back(PermissionMessage(
-          PermissionMessage::kSocketAnyHost,
-          l10n_util::GetStringUTF16(
-              IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
-      return true;
-    }
-  }
-  return false;
-}
-
-void SocketPermission::AddSubdomainHostMessage(
-    PermissionMessages& messages) const {
-  std::set<base::string16> domains;
-  std::set<SocketPermissionData>::const_iterator i;
-  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
-    if (i->entry().GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
-      domains.insert(base::UTF8ToUTF16(i->entry().pattern().host));
-  }
-  if (!domains.empty()) {
-    int id = (domains.size() == 1) ?
-             IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN :
-             IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
-    messages.push_back(PermissionMessage(
-        PermissionMessage::kSocketDomainHosts,
-        l10n_util::GetStringFUTF16(
-            id,
-            JoinString(
-                std::vector<base::string16>(
-                    domains.begin(), domains.end()), ' '))));
-  }
-}
-
-void SocketPermission::AddSpecificHostMessage(
-    PermissionMessages& messages) const {
-  std::set<base::string16> hostnames;
-  std::set<SocketPermissionData>::const_iterator i;
-  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
-    if (i->entry().GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
-      hostnames.insert(base::UTF8ToUTF16(i->entry().pattern().host));
-  }
-  if (!hostnames.empty()) {
-    int id = (hostnames.size() == 1) ?
-             IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST :
-             IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
-    messages.push_back(PermissionMessage(
-        PermissionMessage::kSocketSpecificHosts,
-        l10n_util::GetStringFUTF16(
-            id,
-            JoinString(
-                std::vector<base::string16>(
-                    hostnames.begin(), hostnames.end()), ' '))));
-  }
-}
-
-void SocketPermission::AddNetworkListMessage(
-    PermissionMessages& messages) const {
-  std::set<SocketPermissionData>::const_iterator i;
-  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
-    if (i->entry().pattern().type ==
-        content::SocketPermissionRequest::NETWORK_STATE) {
-      messages.push_back(PermissionMessage(
-          PermissionMessage::kNetworkState,
-          l10n_util::GetStringUTF16(
-              IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
-    }
-  }
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/socket_permission.h b/chrome/common/extensions/permissions/socket_permission.h
deleted file mode 100644
index 5f3373e..0000000
--- a/chrome/common/extensions/permissions/socket_permission.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_H_
-
-#include <string>
-
-#include "chrome/common/extensions/permissions/set_disjunction_permission.h"
-#include "chrome/common/extensions/permissions/socket_permission_data.h"
-#include "extensions/common/permissions/api_permission.h"
-
-namespace extensions {
-
-class SocketPermission : public SetDisjunctionPermission<SocketPermissionData,
-                                                         SocketPermission> {
- public:
-  struct CheckParam : APIPermission::CheckParam {
-    CheckParam(content::SocketPermissionRequest::OperationType type,
-        const std::string& host,
-        int port)
-      : request(type, host, port) { }
-    content::SocketPermissionRequest request;
-  };
-
-  explicit SocketPermission(const APIPermissionInfo* info);
-
-  virtual ~SocketPermission();
-
-  // Returns the localized permission messages of this permission.
-  virtual PermissionMessages GetMessages() const OVERRIDE;
-
- private:
-  bool AddAnyHostMessage(PermissionMessages& messages) const;
-  void AddSubdomainHostMessage(PermissionMessages& messages) const;
-  void AddSpecificHostMessage(PermissionMessages& messages) const;
-  void AddNetworkListMessage(PermissionMessages& messages) const;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_H_
diff --git a/chrome/common/extensions/permissions/socket_permission_data.cc b/chrome/common/extensions/permissions/socket_permission_data.cc
deleted file mode 100644
index b110cb5..0000000
--- a/chrome/common/extensions/permissions/socket_permission_data.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/socket_permission_data.h"
-
-#include <cstdlib>
-#include <sstream>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
-#include "extensions/common/permissions/api_permission.h"
-#include "url/url_canon.h"
-
-namespace {
-
-using content::SocketPermissionRequest;
-using extensions::SocketPermissionData;
-
-const char kColon = ':';
-const char kInvalid[] = "invalid";
-const char kTCPConnect[] = "tcp-connect";
-const char kTCPListen[] = "tcp-listen";
-const char kUDPBind[] = "udp-bind";
-const char kUDPSendTo[] = "udp-send-to";
-const char kUDPMulticastMembership[] = "udp-multicast-membership";
-const char kResolveHost[] = "resolve-host";
-const char kResolveProxy[] = "resolve-proxy";
-const char kNetworkState[] = "network-state";
-
-SocketPermissionRequest::OperationType StringToType(const std::string& s) {
-  if (s == kTCPConnect)
-    return SocketPermissionRequest::TCP_CONNECT;
-  if (s == kTCPListen)
-    return SocketPermissionRequest::TCP_LISTEN;
-  if (s == kUDPBind)
-    return SocketPermissionRequest::UDP_BIND;
-  if (s == kUDPSendTo)
-    return SocketPermissionRequest::UDP_SEND_TO;
-  if (s == kUDPMulticastMembership)
-    return SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP;
-  if (s == kResolveHost)
-    return SocketPermissionRequest::RESOLVE_HOST;
-  if (s == kResolveProxy)
-    return SocketPermissionRequest::RESOLVE_PROXY;
-  if (s == kNetworkState)
-    return SocketPermissionRequest::NETWORK_STATE;
-  return SocketPermissionRequest::NONE;
-}
-
-const char* TypeToString(SocketPermissionRequest::OperationType type) {
-  switch (type) {
-    case SocketPermissionRequest::TCP_CONNECT:
-      return kTCPConnect;
-    case SocketPermissionRequest::TCP_LISTEN:
-      return kTCPListen;
-    case SocketPermissionRequest::UDP_BIND:
-      return kUDPBind;
-    case SocketPermissionRequest::UDP_SEND_TO:
-      return kUDPSendTo;
-    case SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP:
-      return kUDPMulticastMembership;
-    case SocketPermissionRequest::RESOLVE_HOST:
-      return kResolveHost;
-    case SocketPermissionRequest::RESOLVE_PROXY:
-      return kResolveProxy;
-    case SocketPermissionRequest::NETWORK_STATE:
-      return kNetworkState;
-    default:
-      return kInvalid;
-  }
-}
-
-}  // namespace
-
-namespace extensions {
-
-SocketPermissionData::SocketPermissionData() { }
-
-SocketPermissionData::~SocketPermissionData() { }
-
-bool SocketPermissionData::operator<(const SocketPermissionData& rhs) const {
-  return entry_ < rhs.entry_;
-}
-
-bool SocketPermissionData::operator==(const SocketPermissionData& rhs) const {
-  return entry_ == rhs.entry_;
-}
-
-bool SocketPermissionData::Check(
-    const APIPermission::CheckParam* param) const {
-  if (!param)
-    return false;
-  const SocketPermission::CheckParam& specific_param =
-      *static_cast<const SocketPermission::CheckParam*>(param);
-  const SocketPermissionRequest &request = specific_param.request;
-
-  return entry_.Check(request);
-}
-
-scoped_ptr<base::Value> SocketPermissionData::ToValue() const {
-  return scoped_ptr<base::Value>(new base::StringValue(GetAsString()));
-}
-
-bool SocketPermissionData::FromValue(const base::Value* value) {
-  std::string spec;
-  if (!value->GetAsString(&spec))
-    return false;
-
-  return Parse(spec);
-}
-
-SocketPermissionEntry& SocketPermissionData::entry() {
-   // Clear the spec because the caller could mutate |this|.
-   spec_.clear();
-  return entry_;
-}
-
-// TODO(ikarienator): Rewrite this method to support IPv6.
-bool SocketPermissionData::Parse(const std::string& permission) {
-  Reset();
-
-  std::vector<std::string> tokens;
-  base::SplitStringDontTrim(permission, kColon, &tokens);
-  if (tokens.empty())
-    return false;
-
-  SocketPermissionRequest::OperationType type = StringToType(tokens[0]);
-  if (type == SocketPermissionRequest::NONE)
-    return false;
-
-  tokens.erase(tokens.begin());
-  return SocketPermissionEntry::ParseHostPattern(type, tokens, &entry_);
-}
-
-const std::string& SocketPermissionData::GetAsString() const {
-  if (!spec_.empty())
-    return spec_;
-
-  spec_.reserve(64);
-  spec_.append(TypeToString(entry_.pattern().type));
-  std::string pattern = entry_.GetHostPatternAsString();
-  if (!pattern.empty()) {
-    spec_.append(1, kColon).append(pattern);
-  }
-  return spec_;
-}
-
-void SocketPermissionData::Reset() {
-  entry_ = SocketPermissionEntry();
-  spec_.clear();
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/socket_permission_data.h b/chrome/common/extensions/permissions/socket_permission_data.h
deleted file mode 100644
index eaeb119..0000000
--- a/chrome/common/extensions/permissions/socket_permission_data.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
-
-#include <string>
-
-#include "chrome/common/extensions/permissions/socket_permission_entry.h"
-#include "extensions/common/permissions/api_permission.h"
-#include "ipc/ipc_param_traits.h"
-
-namespace ipc_fuzzer {
-template <class T> struct FuzzTraits;
-template <class T> struct GenerateTraits;
-}  // namespace ipc_fuzzer
-
-namespace extensions {
-
-// A pattern that can be used to match socket permission.
-//   <socket-permission-pattern>
-//          := <op> |
-//             <op> ':' <host> |
-//             <op> ':' ':' <port> |
-//             <op> ':' <host> ':' <port> |
-//             'udp-multicast-membership'
-//   <op>   := 'tcp-connect' |
-//             'tcp-listen' |
-//             'udp-bind' |
-//             'udp-send-to' |
-//             'udp-multicast-membership' |
-//             'resolve-host' |
-//             'resolve-proxy' |
-//             'network-state'
-//   <host> := '*' |
-//             '*.' <anychar except '/' and '*'>+ |
-//             <anychar except '/' and '*'>+
-//   <port> := '*' |
-//             <port number between 0 and 65535>)
-// The multicast membership permission implies a permission to any address.
-class SocketPermissionData {
- public:
-  SocketPermissionData();
-  ~SocketPermissionData();
-
-  // operators <, == are needed by container std::set and algorithms
-  // std::set_includes and std::set_differences.
-  bool operator<(const SocketPermissionData& rhs) const;
-  bool operator==(const SocketPermissionData& rhs) const;
-
-  // Check if |param| (which must be a SocketPermissionData::CheckParam)
-  // matches the spec of |this|.
-  bool Check(const APIPermission::CheckParam* param) const;
-
-  // Convert |this| into a base::Value.
-  scoped_ptr<base::Value> ToValue() const;
-
-  // Populate |this| from a base::Value.
-  bool FromValue(const base::Value* value);
-
-  // TODO(bryeung): SocketPermissionData should be encoded as a base::Value
-  // instead of a string.  Until that is done, expose these methods for
-  // testing.
-  bool ParseForTest(const std::string& permission) { return Parse(permission); }
-  const std::string& GetAsStringForTest() const { return GetAsString(); }
-
-  const SocketPermissionEntry& entry() const { return entry_; }
-
- private:
-  // Friend so ParamTraits can serialize us.
-  friend struct IPC::ParamTraits<SocketPermissionData>;
-  friend struct ipc_fuzzer::FuzzTraits<SocketPermissionData>;
-  friend struct ipc_fuzzer::GenerateTraits<SocketPermissionData>;
-
-  SocketPermissionEntry& entry();
-
-  bool Parse(const std::string& permission);
-  const std::string& GetAsString() const;
-  void Reset();
-
-  SocketPermissionEntry entry_;
-  mutable std::string spec_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
diff --git a/chrome/common/extensions/permissions/socket_permission_entry.cc b/chrome/common/extensions/permissions/socket_permission_entry.cc
deleted file mode 100644
index be426ea..0000000
--- a/chrome/common/extensions/permissions/socket_permission_entry.cc
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/socket_permission_entry.h"
-
-#include <cstdlib>
-#include <sstream>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
-#include "extensions/common/permissions/api_permission.h"
-#include "url/url_canon.h"
-
-namespace {
-
-using content::SocketPermissionRequest;
-
-const char kColon = ':';
-const char kDot = '.';
-const char kWildcard[] = "*";
-const int kWildcardPortNumber = 0;
-const int kInvalidPort = -1;
-
-bool StartsOrEndsWithWhitespace(const std::string& str) {
-  if (str.find_first_not_of(base::kWhitespaceASCII) != 0)
-    return true;
-  if (str.find_last_not_of(base::kWhitespaceASCII) != str.length() - 1)
-    return true;
-  return false;
-}
-
-}  // namespace
-
-namespace extensions {
-
-SocketPermissionEntry::SocketPermissionEntry()
-  : pattern_(SocketPermissionRequest::NONE, std::string(), kInvalidPort),
-    match_subdomains_(false) {
-}
-
-SocketPermissionEntry::~SocketPermissionEntry() {}
-
-bool SocketPermissionEntry::operator<(const SocketPermissionEntry& rhs) const {
-  if (pattern_.type < rhs.pattern_.type)
-    return true;
-  if (pattern_.type > rhs.pattern_.type)
-    return false;
-
-  if (pattern_.host < rhs.pattern_.host)
-    return true;
-  if (pattern_.host > rhs.pattern_.host)
-    return false;
-
-  if (match_subdomains_ < rhs.match_subdomains_)
-    return true;
-  if (match_subdomains_ > rhs.match_subdomains_)
-    return false;
-
-  if (pattern_.port < rhs.pattern_.port)
-    return true;
-  return false;
-}
-
-bool SocketPermissionEntry::operator==(const SocketPermissionEntry& rhs) const {
-  return (pattern_.type == rhs.pattern_.type) &&
-         (pattern_.host == rhs.pattern_.host) &&
-         (match_subdomains_ == rhs.match_subdomains_) &&
-         (pattern_.port == rhs.pattern_.port);
-}
-
-bool SocketPermissionEntry::Check(
-    const content::SocketPermissionRequest& request) const {
-  if (pattern_.type != request.type)
-    return false;
-
-  std::string lhost = StringToLowerASCII(request.host);
-  if (pattern_.host != lhost) {
-    if (!match_subdomains_)
-      return false;
-
-    if (!pattern_.host.empty()) {
-      // Do not wildcard part of IP address.
-      url_parse::Component component(0, lhost.length());
-      url_canon::RawCanonOutputT<char, 128> ignored_output;
-      url_canon::CanonHostInfo host_info;
-      url_canon::CanonicalizeIPAddress(lhost.c_str(), component,
-                                       &ignored_output, &host_info);
-      if (host_info.IsIPAddress())
-        return false;
-
-      // host should equal one or more chars + "." +  host_.
-      int i = lhost.length() - pattern_.host.length();
-      if (i < 2)
-        return false;
-
-      if (lhost.compare(i, pattern_.host.length(), pattern_.host) != 0)
-        return false;
-
-      if (lhost[i - 1] != kDot)
-        return false;
-    }
-  }
-
-  if (pattern_.port != request.port && pattern_.port != kWildcardPortNumber)
-    return false;
-
-  return true;
-}
-
-SocketPermissionEntry::HostType SocketPermissionEntry::GetHostType() const {
-  return pattern_.host.empty() ? SocketPermissionEntry::ANY_HOST :
-         match_subdomains_     ? SocketPermissionEntry::HOSTS_IN_DOMAINS :
-                                 SocketPermissionEntry::SPECIFIC_HOSTS;
-}
-
-bool SocketPermissionEntry::IsAddressBoundType() const {
-  return pattern_.type == SocketPermissionRequest::TCP_CONNECT ||
-      pattern_.type == SocketPermissionRequest::TCP_LISTEN ||
-      pattern_.type == SocketPermissionRequest::UDP_BIND ||
-      pattern_.type == SocketPermissionRequest::UDP_SEND_TO;
-}
-
-// static
-bool SocketPermissionEntry::ParseHostPattern(
-    SocketPermissionRequest::OperationType type,
-    const std::string& pattern,
-    SocketPermissionEntry* entry) {
-  std::vector<std::string> tokens;
-  base::SplitStringDontTrim(pattern, kColon, &tokens);
-  return ParseHostPattern(type, tokens, entry);
-}
-
-// static
-bool SocketPermissionEntry::ParseHostPattern(
-    SocketPermissionRequest::OperationType type,
-    const std::vector<std::string>& pattern_tokens,
-    SocketPermissionEntry* entry) {
-
-  SocketPermissionEntry result;
-
-  if (type == SocketPermissionRequest::NONE)
-    return false;
-
-  if (pattern_tokens.size() > 2)
-    return false;
-
-  result.pattern_.type = type;
-  result.pattern_.port = kWildcardPortNumber;
-  result.match_subdomains_ = true;
-
-  if (pattern_tokens.size() == 0) {
-    *entry = result;
-    return true;
-  }
-
-    // Return an error if address is specified for permissions that don't
-    // need it (such as 'resolve-host').
-    if (!result.IsAddressBoundType())
-      return false;
-
-  result.pattern_.host = pattern_tokens[0];
-  if (!result.pattern_.host.empty()) {
-    if (StartsOrEndsWithWhitespace(result.pattern_.host))
-      return false;
-    result.pattern_.host = StringToLowerASCII(result.pattern_.host);
-
-    // The first component can optionally be '*' to match all subdomains.
-    std::vector<std::string> host_components;
-    base::SplitString(result.pattern_.host, kDot, &host_components);
-    DCHECK(!host_components.empty());
-
-    if (host_components[0] == kWildcard || host_components[0].empty()) {
-      host_components.erase(host_components.begin(),
-                            host_components.begin() + 1);
-    } else {
-      result.match_subdomains_ = false;
-    }
-    result.pattern_.host = JoinString(host_components, kDot);
-  }
-
-  if (pattern_tokens.size() == 1 ||
-      pattern_tokens[1].empty() ||
-      pattern_tokens[1] == kWildcard) {
-    *entry = result;
-    return true;
-  }
-
-  if (StartsOrEndsWithWhitespace(pattern_tokens[1]))
-    return false;
-
-  if (!base::StringToInt(pattern_tokens[1], &result.pattern_.port) ||
-      result.pattern_.port < 1 || result.pattern_.port > 65535)
-    return false;
-
-  *entry = result;
-  return true;
-}
-
-std::string SocketPermissionEntry::GetHostPatternAsString() const {
-  std::string result;
-
-  if (!IsAddressBoundType())
-    return result;
-
-  if (match_subdomains()) {
-    result.append(kWildcard);
-    if (!pattern_.host.empty())
-      result.append(1, kDot).append(pattern_.host);
-  } else {
-     result.append(pattern_.host);
-  }
-
-  if (pattern_.port == kWildcardPortNumber)
-    result.append(1, kColon).append(kWildcard);
-  else
-    result.append(1, kColon).append(base::IntToString(pattern_.port));
-
-  return result;
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/socket_permission_entry.h b/chrome/common/extensions/permissions/socket_permission_entry.h
deleted file mode 100644
index 5d2eb9b..0000000
--- a/chrome/common/extensions/permissions/socket_permission_entry.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
-
-#include <string>
-#include <vector>
-
-#include "content/public/common/socket_permission_request.h"
-#include "ipc/ipc_param_traits.h"
-
-namespace ipc_fuzzer {
-template <class T> struct FuzzTraits;
-template <class T> struct GenerateTraits;
-}  // namespace ipc_fuzzer
-
-namespace extensions {
-
-// Internal representation of a socket permission for a specific operation, such
-// as UDP "bind", host 127.0.0.1, port *.
-class SocketPermissionEntry {
- public:
-  enum HostType {
-    ANY_HOST,
-    HOSTS_IN_DOMAINS,
-    SPECIFIC_HOSTS,
-  };
-
-  SocketPermissionEntry();
-  ~SocketPermissionEntry();
-
-  // operators <, == are needed by container std::set and algorithms
-  // std::set_includes and std::set_differences.
-  bool operator<(const SocketPermissionEntry& rhs) const;
-  bool operator==(const SocketPermissionEntry& rhs) const;
-
-  bool Check(const content::SocketPermissionRequest& request) const;
-
-  // Parse a host:port pattern for a given operation type.
-  //   <pattern> := '' |
-  //                <host> |
-  //                ':' <port> |
-  //                <host> ':' <port> |
-  //
-  //   <host> := '*' |
-  //             '*.' <anychar except '/' and '*'>+ |
-  //             <anychar except '/' and '*'>+
-  //
-  //   <port> := '*' |
-  //             <port number between 0 and 65535>)
-  static bool ParseHostPattern(
-      content::SocketPermissionRequest::OperationType type,
-      const std::string& pattern,
-      SocketPermissionEntry* entry);
-
-  static bool ParseHostPattern(
-      content::SocketPermissionRequest::OperationType type,
-      const std::vector<std::string>& pattern_tokens,
-      SocketPermissionEntry* entry);
-
-  // Returns true if the permission type can be bound to a host or port.
-  bool IsAddressBoundType() const;
-
-  std::string GetHostPatternAsString() const;
-  HostType GetHostType() const;
-
-  const content::SocketPermissionRequest& pattern() const { return pattern_; }
-  bool match_subdomains() const { return match_subdomains_; }
-
- private:
-  // Friend so ParamTraits can serialize us.
-  friend struct IPC::ParamTraits<SocketPermissionEntry>;
-  friend struct ipc_fuzzer::FuzzTraits<SocketPermissionEntry>;
-  friend struct ipc_fuzzer::GenerateTraits<SocketPermissionEntry>;
-
-  // The permission type, host and port.
-  content::SocketPermissionRequest pattern_;
-
-  // True if there was a wildcard in the host name.
-  bool match_subdomains_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
diff --git a/chrome/common/extensions/permissions/socket_permission_unittest.cc b/chrome/common/extensions/permissions/socket_permission_unittest.cc
index a968c46..7cb1b9f 100644
--- a/chrome/common/extensions/permissions/socket_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/socket_permission_unittest.cc
@@ -6,9 +6,9 @@
 
 #include "base/pickle.h"
 #include "base/values.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
-#include "chrome/common/extensions/permissions/socket_permission_data.h"
 #include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/socket_permission.h"
+#include "extensions/common/permissions/socket_permission_data.h"
 #include "ipc/ipc_message.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/common/extensions/permissions/usb_device_permission.cc b/chrome/common/extensions/permissions/usb_device_permission.cc
deleted file mode 100644
index ee010ac..0000000
--- a/chrome/common/extensions/permissions/usb_device_permission.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/usb_device_permission.h"
-
-#include <set>
-#include <string>
-
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "extensions/common/permissions/permissions_info.h"
-#include "grit/generated_resources.h"
-#include "ui/base/l10n/l10n_util.h"
-
-#if defined(ENABLE_EXTENSIONS)
-#include "device/usb/usb_ids.h"
-#endif
-
-namespace extensions {
-
-UsbDevicePermission::UsbDevicePermission(
-    const APIPermissionInfo* info)
-  : SetDisjunctionPermission<UsbDevicePermissionData,
-                             UsbDevicePermission>(info) {
-}
-
-UsbDevicePermission::~UsbDevicePermission() {
-}
-
-PermissionMessages UsbDevicePermission::GetMessages() const {
-  DCHECK(HasMessages());
-  PermissionMessages result;
-
-#if defined(ENABLE_EXTENSIONS)
-  // //device/usb/usb.gyp:device_usb is not available when extensions are
-  // disabled.
-  for (std::set<UsbDevicePermissionData>::const_iterator i =
-      data_set_.begin(); i != data_set_.end(); ++i) {
-    const char* vendor = device::UsbIds::GetVendorName(i->vendor_id());
-
-    if (vendor) {
-      const char* product =
-          device::UsbIds::GetProductName(i->vendor_id(), i->product_id());
-      if (product) {
-        result.push_back(PermissionMessage(
-            PermissionMessage::kUsbDevice,
-            l10n_util::GetStringFUTF16(
-                IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE,
-                base::ASCIIToUTF16(product),
-                base::ASCIIToUTF16(vendor))));
-      } else {
-        result.push_back(PermissionMessage(
-            PermissionMessage::kUsbDevice,
-            l10n_util::GetStringFUTF16(
-                IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_MISSING_PRODUCT,
-                base::ASCIIToUTF16(vendor))));
-      }
-    } else {
-      result.push_back(PermissionMessage(
-          PermissionMessage::kUsbDevice,
-          l10n_util::GetStringUTF16(
-              IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_MISSING_VENDOR)));
-    }
-  }
-#else
-  NOTREACHED();
-#endif  // defined(ENABLE_EXTENSIONS)
-
-  return result;
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/usb_device_permission.h b/chrome/common/extensions/permissions/usb_device_permission.h
deleted file mode 100644
index 3e599f0..0000000
--- a/chrome/common/extensions/permissions/usb_device_permission.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_H_
-
-#include "base/basictypes.h"
-#include "chrome/common/extensions/permissions/set_disjunction_permission.h"
-#include "chrome/common/extensions/permissions/usb_device_permission_data.h"
-#include "extensions/common/permissions/api_permission.h"
-
-namespace extensions {
-
-class UsbDevicePermission
-  : public SetDisjunctionPermission<UsbDevicePermissionData,
-                                    UsbDevicePermission> {
- public:
-  struct CheckParam : public APIPermission::CheckParam {
-    CheckParam(uint16 vendor_id, uint16 product_id, int interface_id)
-      : vendor_id(vendor_id),
-        product_id(product_id),
-        interface_id(interface_id) {}
-    const uint16 vendor_id;
-    const uint16 product_id;
-    const int interface_id;
-  };
-
-  explicit UsbDevicePermission(const APIPermissionInfo* info);
-  virtual ~UsbDevicePermission();
-
-  // APIPermission overrides
-  virtual PermissionMessages GetMessages() const OVERRIDE;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_H_
diff --git a/chrome/common/extensions/permissions/usb_device_permission_data.cc b/chrome/common/extensions/permissions/usb_device_permission_data.cc
deleted file mode 100644
index 9cf32ba..0000000
--- a/chrome/common/extensions/permissions/usb_device_permission_data.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/extensions/permissions/usb_device_permission_data.h"
-
-#include <string>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/values.h"
-#include "chrome/common/extensions/permissions/usb_device_permission.h"
-#include "extensions/common/permissions/api_permission.h"
-
-namespace {
-
-const char* kProductIdKey = "productId";
-const char* kVendorIdKey = "vendorId";
-const char* kInterfaceIdKey = "interfaceId";
-
-}  // namespace
-
-namespace extensions {
-
-UsbDevicePermissionData::UsbDevicePermissionData()
-  : vendor_id_(0), product_id_(0), interface_id_(ANY_INTERFACE) {
-}
-
-UsbDevicePermissionData::UsbDevicePermissionData(uint16 vendor_id,
-                                                 uint16 product_id,
-                                                 int interface_id)
-  : vendor_id_(vendor_id),
-    product_id_(product_id),
-    interface_id_(interface_id) {
-}
-
-bool UsbDevicePermissionData::Check(
-    const APIPermission::CheckParam* param) const {
-  if (!param)
-    return false;
-  const UsbDevicePermission::CheckParam& specific_param =
-      *static_cast<const UsbDevicePermission::CheckParam*>(param);
-  return vendor_id_ == specific_param.vendor_id &&
-         product_id_ == specific_param.product_id &&
-         (specific_param.interface_id == UNSPECIFIED_INTERFACE ||
-          interface_id_ == specific_param.interface_id);
-}
-
-scoped_ptr<base::Value> UsbDevicePermissionData::ToValue() const {
-  base::DictionaryValue* result = new base::DictionaryValue();
-  result->SetInteger(kVendorIdKey, vendor_id_);
-  result->SetInteger(kProductIdKey, product_id_);
-  result->SetInteger(kInterfaceIdKey, interface_id_);
-  return scoped_ptr<base::Value>(result);
-}
-
-bool UsbDevicePermissionData::FromValue(const base::Value* value) {
-  if (!value)
-    return false;
-
-  const base::DictionaryValue* dict_value;
-  if (!value->GetAsDictionary(&dict_value))
-    return false;
-
-  int temp;
-  if (!dict_value->GetInteger(kVendorIdKey, &temp))
-    return false;
-  if (temp < 0 || temp > kuint16max)
-    return false;
-  vendor_id_ = temp;
-
-  if (!dict_value->GetInteger(kProductIdKey, &temp))
-    return false;
-  if (temp < 0 || temp > kuint16max)
-    return false;
-  product_id_ = temp;
-
-  if (!dict_value->GetInteger(kInterfaceIdKey, &temp))
-    interface_id_ = ANY_INTERFACE;
-  else if (temp < ANY_INTERFACE || temp > kuint8max)
-    return false;
-  else
-    interface_id_ = temp;
-
-  return true;
-}
-
-bool UsbDevicePermissionData::operator<(
-    const UsbDevicePermissionData& rhs) const {
-  if (vendor_id_ == rhs.vendor_id_) {
-    if (product_id_ == rhs.product_id_)
-      return interface_id_ < rhs.interface_id_;
-
-    return product_id_ < rhs.product_id_;
-  }
-  return vendor_id_ < rhs.vendor_id_;
-}
-
-bool UsbDevicePermissionData::operator==(
-    const UsbDevicePermissionData& rhs) const {
-  return vendor_id_ == rhs.vendor_id_ &&
-      product_id_ == rhs.product_id_ &&
-      interface_id_ == rhs.interface_id_;
-}
-
-}  // namespace extensions
diff --git a/chrome/common/extensions/permissions/usb_device_permission_data.h b/chrome/common/extensions/permissions/usb_device_permission_data.h
deleted file mode 100644
index c326371..0000000
--- a/chrome/common/extensions/permissions/usb_device_permission_data.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#ifndef CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
-#define CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "extensions/common/permissions/api_permission.h"
-
-namespace base {
-
-class Value;
-
-}  // namespace base
-
-namespace extensions {
-
-// A pattern that can be used to match a USB device permission.
-// Should be of the format: vendorId:productId, where both vendorId and
-// productId are decimal strings representing uint16 values.
-class UsbDevicePermissionData {
- public:
-  enum SpecialInterfaces {
-    // A special interface id for stating permissions for an entire USB device,
-    // no specific interface. This value must match value of Rule::ANY_INTERFACE
-    // from ChromeOS permission_broker project.
-    ANY_INTERFACE = -1,
-
-    // A special interface id for |Check| to indicate that interface field is
-    // not to be checked. Not used in manifest file.
-    UNSPECIFIED_INTERFACE = -2
-  };
-
-  UsbDevicePermissionData();
-  UsbDevicePermissionData(uint16 vendor_id,
-                          uint16 product_id,
-                          int interface_id);
-
-  // Check if |param| (which must be a UsbDevicePermissionData::CheckParam)
-  // matches the vendor and product IDs associated with |this|.
-  bool Check(const APIPermission::CheckParam* param) const;
-
-  // Convert |this| into a base::Value.
-  scoped_ptr<base::Value> ToValue() const;
-
-  // Populate |this| from a base::Value.
-  bool FromValue(const base::Value* value);
-
-  bool operator<(const UsbDevicePermissionData& rhs) const;
-  bool operator==(const UsbDevicePermissionData& rhs) const;
-
-  const uint16& vendor_id() const { return vendor_id_; }
-  const uint16& product_id() const { return product_id_; }
-
-  // These accessors are provided for IPC_STRUCT_TRAITS_MEMBER.  Please
-  // think twice before using them for anything else.
-  uint16& vendor_id() { return vendor_id_; }
-  uint16& product_id() { return product_id_; }
-
- private:
-  uint16 vendor_id_;
-  uint16 product_id_;
-  int interface_id_;
-};
-
-}  // namespace extensions
-
-#endif  // CHROME_COMMON_EXTENSIONS_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
diff --git a/chrome/common/extensions/permissions/usb_device_permission_unittest.cc b/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
index 2aa47f1..e64d429 100644
--- a/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
+++ b/chrome/common/extensions/permissions/usb_device_permission_unittest.cc
@@ -9,10 +9,10 @@
 #include "base/pickle.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
-#include "chrome/common/extensions/permissions/usb_device_permission.h"
-#include "chrome/common/extensions/permissions/usb_device_permission_data.h"
 #include "extensions/common/permissions/api_permission.h"
 #include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/usb_device_permission.h"
+#include "extensions/common/permissions/usb_device_permission_data.h"
 #include "ipc/ipc_message.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/chrome/common/extensions_api_resources.grd b/chrome/common/extensions_api_resources.grd
index 631f989..07518d3 100644
--- a/chrome/common/extensions_api_resources.grd
+++ b/chrome/common/extensions_api_resources.grd
@@ -10,12 +10,9 @@
     <includes>
       <include name="IDR_EXTENSION_API_JSON_APP" file="extensions\api\app.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_BROWSERACTION" file="extensions\api\browser_action.json" type="BINDATA" />
-      <include name="IDR_EXTENSION_API_JSON_BROWSINGDATA" file="extensions\api\browsing_data.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_COMMANDS" file="extensions\api\commands.json" type="BINDATA" />
-      <include name="IDR_EXTENSION_API_JSON_CONTEXTMENUSINTERNAL" file="extensions\api\context_menus_internal.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT" file="extensions\api\declarative_content.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_DECLARATIVE_WEBREQUEST" file="extensions\api\declarative_web_request.json" type="BINDATA" />
-      <include name="IDR_EXTENSION_API_JSON_ECHOPRIVATE" file="extensions\api\echo_private.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER" file="extensions\api\file_browser_handler.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE" file="extensions\api\input_method_private.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_PAGEACTION" file="extensions\api\page_action.json" type="BINDATA" />
@@ -23,16 +20,13 @@
       <include name="IDR_EXTENSION_API_JSON_PRIVACY" file="extensions\api\privacy.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_PROCESSES" file="extensions\api\processes.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_PROXY" file="extensions\api\proxy.json" type="BINDATA" />
-      <include name="IDR_EXTENSION_API_JSON_RUNTIME" file="extensions\api\runtime.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_SCRIPTBADGE" file="extensions\api\script_badge.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_TTS" file="extensions\api\tts.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_TTSENGINE" file="extensions\api\tts_engine.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_TYPES" file="extensions\api\types.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_TYPES_PRIVATE" file="extensions\api\types_private.json" type="BINDATA" />
-      <include name="IDR_EXTENSION_API_JSON_VIRTUALKEYBOARDPRIVATE" file="extensions\api\virtual_keyboard_private.json" type="BINDATA" /> 
       <include name="IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL" file="extensions\api\web_request_internal.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_WEBSTORE" file="extensions\api\webstore.json" type="BINDATA" />
-      <include name="IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE" file="extensions\api\webstore_private.json" type="BINDATA" />
       <include name="IDR_EXTENSION_API_JSON_WEBVIEW_REQUEST" file="extensions\api\webview_request.json" type="BINDATA" />
     </includes>
   </release>
diff --git a/chrome/common/metrics/variations/variation_ids.h b/chrome/common/metrics/variations/variation_ids.h
index 1d9ed01..bbd8f76 100644
--- a/chrome/common/metrics/variations/variation_ids.h
+++ b/chrome/common/metrics/variations/variation_ids.h
@@ -318,10 +318,14 @@
   AUTOCOMPLETE_DYNAMIC_FIELD_TRIAL_RANGE3_ID_MIN = 3312122,
   AUTOCOMPLETE_DYNAMIC_FIELD_TRIAL_RANGE3_ID_MAX = 3312321,
 
+  // Instant search clicks field trial.
+  INSTANT_SEARCH_CLICKS_FIELD_TRIAL_ID_MIN = 3312322,
+  INSTANT_SEARCH_CLICKS_FIELD_TRIAL_ID_MAX = 3312371,
+
   // NEXT ID: When adding new IDs, please add them above this section, starting
   // with the value of NEXT_ID, and updating NEXT_ID to (end of your reserved
   // range) + 1.
-  NEXT_ID = 3312322,
+  NEXT_ID = 3312372,
 
   // USABLE IDs END HERE.
   //
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index c269458..e957ceb 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1309,9 +1309,6 @@
 // The GCM channel's enabled state.
 const char kGCMChannelEnabled[] = "gcm.channel_enabled";
 
-// Registered GCM application ids.
-const char kGCMRegisteredAppIDs[] = "gcm.register_app_ids";
-
 // Whether Easy Unlock is enabled.
 extern const char kEasyUnlockEnabled[] = "easy_unlock.enabled";
 
@@ -1360,29 +1357,45 @@
 const char kCipherSuiteBlacklist[] = "ssl.cipher_suites.blacklist";
 const char kEnableOriginBoundCerts[] = "ssl.origin_bound_certs.enabled";
 const char kDisableSSLRecordSplitting[] = "ssl.ssl_record_splitting.disabled";
-const char kEnableUnrestrictedSSL3Fallback[] =
-    "ssl.unrestricted_ssl3_fallback.enabled";
 
 // A boolean pref of the EULA accepted flag.
 const char kEulaAccepted[] = "EulaAccepted";
 
 // The metrics client GUID, entropy source and session ID.
-const char kMetricsClientID[] = "user_experience_metrics.client_id";
+// Note: The names client_id2 and low_entropy_source2 are a result of creating
+// new prefs to do a one-time reset of the previous values.
+const char kMetricsClientID[] = "user_experience_metrics.client_id2";
 const char kMetricsSessionID[] = "user_experience_metrics.session_id";
 const char kMetricsLowEntropySource[] =
-    "user_experience_metrics.low_entropy_source";
+    "user_experience_metrics.low_entropy_source2";
 const char kMetricsPermutedEntropyCache[] =
     "user_experience_metrics.permuted_entropy_cache";
 
-// Date/time when the current metrics profile ID was created
-// (which hopefully corresponds to first run).
-const char kMetricsClientIDTimestamp[] =
-    "user_experience_metrics.client_id_timestamp";
+// Old client id and low entropy source values, cleared the first time this
+// version is launched.
+// TODO(asvitkine): Delete these after a few releases have gone by and old
+// values have been cleaned up. http://crbug.com/357704
+const char kMetricsOldClientID[] = "user_experience_metrics.client_id";
+const char kMetricsOldLowEntropySource[] =
+    "user_experience_metrics.low_entropy_source";
 
 // Boolean that specifies whether or not crash reporting and metrics reporting
 // are sent over the network for analysis.
 const char kMetricsReportingEnabled[] =
     "user_experience_metrics.reporting_enabled";
+// Date/time when the user opted in to UMA and generated the client id for the
+// very first time (local machine time, stored as a 64-bit time_t value).
+const char kMetricsReportingEnabledTimestamp[] =
+    "user_experience_metrics.client_id_timestamp";
+
+// A machine ID used to detect when underlying hardware changes. It is only
+// stored locally and never transmitted in metrics reports.
+const char kMetricsMachineId[] = "user_experience_metrics.machine_id";
+
+// Boolean that indicates a cloned install has been detected and the metrics
+// client id and low entropy source should be reset.
+const char kMetricsResetIds[] =
+    "user_experience_metrics.reset_metrics_ids";
 
 // Boolean that specifies whether or not crash reports are sent
 // over the network for analysis.
@@ -1821,9 +1834,6 @@
 const char kSpdyProxyAuthWasEnabledBefore[] = "spdy_proxy.was_enabled_before";
 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
 
-// Boolean which stores if the user is allowed to signin to chrome.
-const char kSigninAllowed[] = "signin.allowed";
-
 // An ID to uniquely identify this client to the invalidator service.
 const char kInvalidatorClientId[] = "invalidator.client_id";
 
@@ -1835,25 +1845,10 @@
 // yet.  Used to keep invalidation clients in sync in case of a restart.
 const char kInvalidatorSavedInvalidations[] = "invalidator.saved_invalidations";
 
-// String the identifies the last user that logged into sync and other
-// google services. As opposed to kGoogleServicesUsername, this value is not
-// cleared on signout, but while the user is signed in the two values will
-// be the same.
-const char kGoogleServicesLastUsername[] = "google.services.last_username";
-
-// Obfuscated account ID that identifies the current user logged into sync and
-// other google services.
-const char kGoogleServicesUserAccountId[] = "google.services.user_account_id";
-
-// String that identifies the current user logged into sync and other google
-// services.
-const char kGoogleServicesUsername[] = "google.services.username";
-
-// Local state pref containing a string regex that restricts which accounts
-// can be used to log in to chrome (e.g. "*@google.com"). If missing or blank,
-// all accounts are allowed (no restrictions).
-const char kGoogleServicesUsernamePattern[] =
-    "google.services.username_pattern";
+// Boolean indicating that TiclInvalidationService should use GCM channel.
+// False or lack of settings means XMPPPushClient channel.
+const char kInvalidationServiceUseGCMChannel[] =
+    "invalidation_service.use_gcm_channel";
 
 // Local hash of authentication password, used for off-line authentication
 // when on-line authentication is not available.
@@ -2070,6 +2065,10 @@
 // longer shown.
 const char kHotwordOptInPopupTimesShown[] = "hotword.opt_in_popup_times_shown";
 
+// A boolean pref that controls whether the sound of "Ok, Google" plus a few
+// seconds of audio data before is sent back to improve voice search.
+const char kHotwordAudioLoggingEnabled[] = "hotword.audio_logging_enabled";
+
 #if defined(OS_ANDROID)
 // Boolean that controls the global enabled-state of protected media identifier.
 const char kProtectedMediaIdentifierEnabled[] =
@@ -2210,9 +2209,13 @@
 // Value of the enums in TabStrip::LayoutType as an int.
 const char kTabStripLayoutType[] = "tab_strip_layout_type";
 
-// Indicates that factory reset was requested from options page.
+// Indicates that factory reset was requested from options page or reset screen.
 const char kFactoryResetRequested[] = "FactoryResetRequested";
 
+// Indicates that rollback was requested alongside with factory reset.
+// Makes sense only if kFactoryResetRequested is true.
+const char kRollbackRequested[] = "RollbackRequested";
+
 // Boolean recording whether we have showed a balloon that calls out the message
 // center for desktop notifications.
 const char kMessageCenterShowedFirstRunBalloon[] =
@@ -2362,6 +2365,13 @@
 // troubleshooting.
 const char kComponentUpdaterState[] = "component_updater.state";
 
+// A boolean where true means that the browser has previously attempted to
+// enable autoupdate and failed, so the next out-of-date browser start should
+// not prompt the user to enable autoupdate, it should offer to reinstall Chrome
+// instead.
+const char kAttemptedToEnableAutoupdate[] =
+    "browser.attempted_to_enable_autoupdate";
+
 // The next media gallery ID to assign.
 const char kMediaGalleriesUniqueId[] = "media_galleries.gallery_id";
 
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 207e8a0..1f69037 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -12,6 +12,7 @@
 #include "build/build_config.h"
 
 #include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/signin/core/common/signin_pref_names.h"
 
 namespace prefs {
 
@@ -410,7 +411,6 @@
 extern const char kProfileResetPromptMemento[];
 
 extern const char kGCMChannelEnabled[];
-extern const char kGCMRegisteredAppIDs[];
 
 extern const char kEasyUnlockEnabled[];
 extern const char kEasyUnlockShowTutorial[];
@@ -424,7 +424,6 @@
 extern const char kCipherSuiteBlacklist[];
 extern const char kEnableOriginBoundCerts[];
 extern const char kDisableSSLRecordSplitting[];
-extern const char kEnableUnrestrictedSSL3Fallback[];
 
 extern const char kGLVendorString[];
 extern const char kGLRendererString[];
@@ -436,8 +435,12 @@
 extern const char kMetricsSessionID[];
 extern const char kMetricsLowEntropySource[];
 extern const char kMetricsPermutedEntropyCache[];
-extern const char kMetricsClientIDTimestamp[];
+extern const char kMetricsOldClientID[];
+extern const char kMetricsOldLowEntropySource[];
 extern const char kMetricsReportingEnabled[];
+extern const char kMetricsReportingEnabledTimestamp[];
+extern const char kMetricsMachineId[];
+extern const char kMetricsResetIds[];
 // Android has it's own metric / crash reporting implemented in Android
 // Java code so kMetricsReportingEnabled doesn't make sense. We use this
 // to inform crashes_ui that we have enabled crash reporting.
@@ -601,17 +604,13 @@
 extern const char kSpdyProxyAuthEnabled[];
 extern const char kSpdyProxyAuthWasEnabledBefore[];
 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
-extern const char kSigninAllowed[];
 
-extern const char kGoogleServicesLastUsername[];
-extern const char kGoogleServicesUserAccountId[];
-extern const char kGoogleServicesUsername[];
-extern const char kGoogleServicesUsernamePattern[];
 extern const char kGoogleServicesPasswordHash[];
 
 extern const char kInvalidatorClientId[];
 extern const char kInvalidatorInvalidationState[];
 extern const char kInvalidatorSavedInvalidations[];
+extern const char kInvalidationServiceUseGCMChannel[];
 
 extern const char kSignInPromoStartupCount[];
 extern const char kSignInPromoUserSkipped[];
@@ -701,6 +700,7 @@
 
 extern const char kHotwordSearchEnabled[];
 extern const char kHotwordOptInPopupTimesShown[];
+extern const char kHotwordAudioLoggingEnabled[];
 
 #if defined(OS_ANDROID)
 extern const char kProtectedMediaIdentifierEnabled[];
@@ -795,11 +795,13 @@
 extern const char kDevicePolicyRefreshRate[];
 
 extern const char kFactoryResetRequested[];
+extern const char kRollbackRequested[];
 
 extern const char kMessageCenterShowedFirstRunBalloon[];
 
 extern const char kRecoveryComponentVersion[];
 extern const char kComponentUpdaterState[];
+extern const char kAttemptedToEnableAutoupdate[];
 
 extern const char kMediaGalleriesUniqueId[];
 extern const char kMediaGalleriesRememberedGalleries[];
diff --git a/chrome/common/profile_management_switches.cc b/chrome/common/profile_management_switches.cc
index a33d62a..e6af279 100644
--- a/chrome/common/profile_management_switches.cc
+++ b/chrome/common/profile_management_switches.cc
@@ -53,4 +53,9 @@
   return CheckProfileManagementFlag(switches::kNewProfileManagement, true);
 }
 
+bool IsFastUserSwitching() {
+  return CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kFastUserSwitching);
+}
+
 }  // namespace switches
diff --git a/chrome/common/profile_management_switches.h b/chrome/common/profile_management_switches.h
index e26cb41..5c9db49 100644
--- a/chrome/common/profile_management_switches.h
+++ b/chrome/common/profile_management_switches.h
@@ -21,6 +21,9 @@
 // choosers.
 bool IsNewProfileManagement();
 
+// Checks whether the flag for fast user switching is enabled.
+bool IsFastUserSwitching();
+
 }  // namespace switches
 
 #endif  // CHROME_COMMON_PROFILE_MANAGEMENT_SWITCHES_H_
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index d8e4d18..11813ce 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -3,12 +3,12 @@
 // found in the LICENSE file.
 
 // Multiply-included file, no traditional include guard.
+#include <stdint.h>
 #include <map>
 #include <set>
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/files/file_path.h"
 #include "base/memory/shared_memory.h"
 #include "base/process/process.h"
@@ -262,14 +262,11 @@
 IPC_MESSAGE_CONTROL1(ChromeViewMsg_ClearCache,
                      bool /* on_navigation */)
 
-// For WebUI testing, this message stores parameters to do ScriptEvalRequest at
-// a time which is late enough to not be thrown out, and early enough to be
-// before onload events are fired.
-IPC_MESSAGE_ROUTED4(ChromeViewMsg_WebUIJavaScript,
-                    base::string16,  /* frame_xpath */
-                    base::string16,  /* jscript_url */
-                    int,  /* ID */
-                    bool  /* If true, result is sent back. */)
+// For WebUI testing, this message requests JavaScript to be executed at a time
+// which is late enough to not be thrown out, and early enough to be before
+// onload events are fired.
+IPC_MESSAGE_ROUTED1(ChromeViewMsg_WebUIJavaScript,
+                    base::string16  /* javascript */)
 
 // Set the content setting rules stored by the renderer.
 IPC_MESSAGE_CONTROL1(ChromeViewMsg_SetContentSettingRules,
@@ -404,6 +401,17 @@
                     std::string /* tag_name */ )
 #endif  // defined(OS_ANDROID)
 
+#if defined(CLD2_DYNAMIC_MODE)
+// Informs the renderer process that Compact Language Detector (CLD) data is
+// available and provides an IPC::PlatformFileForTransit obtained from
+// IPC::GetFileHandleForProcess(...)
+// See also: ChromeViewHostMsg_NeedCLDData
+IPC_MESSAGE_ROUTED3(ChromeViewMsg_CLDDataAvailable,
+                    IPC::PlatformFileForTransit /* ipc_file_handle */,
+                    uint64 /* data_offset */,
+                    uint64 /* data_length */)
+#endif
+
 // chrome.principals messages ------------------------------------------------
 
 // Message sent from the renderer to the browser to get the list of browser
@@ -777,3 +785,16 @@
                     base::string16 /* source */,
                     extensions::StackTrace /* stack trace */,
                     int32 /* severity level */)
+
+// Sent by the renderer to check if crash reporting is enabled.
+IPC_SYNC_MESSAGE_CONTROL0_1(ChromeViewHostMsg_IsCrashReportingEnabled,
+                            bool /* enabled */)
+
+#if defined(CLD2_DYNAMIC_MODE)
+// Informs the browser process that Compact Language Detector (CLD) data is
+// required by the originating renderer. The browser process should respond
+// with a ChromeViewMsg_CLDDataAvailable if the data is available, else it
+// should go unanswered (the renderer will ask again later).
+// See also: ChromeViewMsg_CLDDataAvailable
+IPC_MESSAGE_ROUTED0(ChromeViewHostMsg_NeedCLDData)
+#endif
diff --git a/chrome/common/safe_browsing/csd.proto b/chrome/common/safe_browsing/csd.proto
index a7ef9d3..6b5f6c6 100644
--- a/chrome/common/safe_browsing/csd.proto
+++ b/chrome/common/safe_browsing/csd.proto
@@ -220,7 +220,38 @@
   // Locale of the device, eg en, en_US.
   optional string locale = 11;
 
-  // Field 12 is only used on the server.
+  message PEImageHeaders {
+    // IMAGE_DOS_HEADER.
+    optional bytes dos_header = 1;
+    // IMAGE_FILE_HEADER.
+    optional bytes file_header = 2;
+    // IMAGE_OPTIONAL_HEADER32. Present only for 32-bit PE images.
+    optional bytes optional_headers32 = 3;
+    // IMAGE_OPTIONAL_HEADER64. Present only for 64-bit PE images.
+    optional bytes optional_headers64 = 4;
+    // IMAGE_SECTION_HEADER.
+    repeated bytes section_header = 5;
+    // Contents of the .edata section.
+    optional bytes export_section_data = 6;
+
+    message DebugData {
+      // IMAGE_DEBUG_DIRECTORY.
+      optional bytes directory_entry = 1;
+      optional bytes raw_data = 2;
+    }
+
+    repeated DebugData debug_data = 7;
+  }
+
+  message ImageHeaders {
+    // Windows Portable Executable image headers.
+    optional PEImageHeaders pe_headers = 1;
+  };
+
+  // Fields 12-17 are reserved for server-side use and are never sent by the
+  // client.
+
+  optional ImageHeaders image_headers = 18;
 }
 
 message ClientDownloadResponse {
diff --git a/chrome/common/service_messages.h b/chrome/common/service_messages.h
index 1f05e63..c1b598b 100644
--- a/chrome/common/service_messages.h
+++ b/chrome/common/service_messages.h
@@ -37,6 +37,9 @@
 // Requests a message back with serialized UMA histograms.
 IPC_MESSAGE_CONTROL0(ServiceMsg_GetHistograms)
 
+// Requests a message back with all available printers.
+IPC_MESSAGE_CONTROL0(ServiceMsg_GetPrinters)
+
 // Tell the service process to shutdown.
 IPC_MESSAGE_CONTROL0(ServiceMsg_Shutdown)
 
@@ -53,3 +56,7 @@
 // Sent as a response to ServiceMsg_GetHistograms.
 IPC_MESSAGE_CONTROL1(ServiceHostMsg_Histograms,
                      std::vector<std::string> /* pickled_histograms */)
+
+// Sent as a response to ServiceMsg_GetPrinters.
+IPC_MESSAGE_CONTROL1(ServiceHostMsg_Printers,
+                     std::vector<std::string> /* printers */)
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index 3e103bd..6f8a339 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -93,6 +93,8 @@
 
 #if defined(OS_ANDROID)
 const char kChromeUINativeNewTabURL[] = "chrome-native://newtab/";
+const char kChromeUINativeBookmarksURL[] = "chrome-native://bookmarks/";
+const char kChromeUINativeRecentTabsURL[] = "chrome-native://recent-tabs/";
 const char kChromeUIWelcomeURL[] = "chrome://welcome/";
 #endif
 
@@ -343,7 +345,6 @@
 const char kAutoPasswordGenerationLearnMoreURL[] =
     "https://support.google.com/chrome/?p=ui_generate_password";
 
-
 const char kPasswordManagerLearnMoreURL[] =
 #if defined(OS_CHROMEOS)
     "https://support.google.com/chromeos/?p=settings_password";
@@ -351,6 +352,9 @@
     "https://support.google.com/chrome/?p=settings_password";
 #endif
 
+const char kSettingsApiLearnMoreURL[] =
+    "https://support.google.com/chrome/?p=ui_settings_api_extension";
+
 const char kChromeHelpViaKeyboardURL[] =
 #if defined(OS_CHROMEOS)
 #if defined(OFFICIAL_BUILD)
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 861f993..f12ea11 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -88,6 +88,8 @@
 
 #if defined(OS_ANDROID)
 extern const char kChromeUINativeNewTabURL[];
+extern const char kChromeUINativeBookmarksURL[];
+extern const char kChromeUINativeRecentTabsURL[];
 extern const char kChromeUIWelcomeURL[];
 #endif
 
@@ -333,6 +335,9 @@
 
 extern const char kPasswordManagerLearnMoreURL[];
 
+// "Learn more" URL for the Settings API bubble.
+extern const char kSettingsApiLearnMoreURL[];
+
 // General help links for Chrome, opened using various actions.
 extern const char kChromeHelpViaKeyboardURL[];
 extern const char kChromeHelpViaMenuURL[];
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include
index 616c3c4..2be82db 100644
--- a/chrome/installer/linux/common/installer.include
+++ b/chrome/installer/linux/common/installer.include
@@ -222,6 +222,10 @@
   process_template "${BUILDDIR}/installer/common/wrapper" \
     "${STAGEDIR}/${INSTALLDIR}/${PACKAGE}"
   chmod 755 "${STAGEDIR}/${INSTALLDIR}/${PACKAGE}"
+  if [ ! -f "${STAGEDIR}/${INSTALLDIR}/google-chrome" ]; then
+    ln -sn "${INSTALLDIR}/${PACKAGE}" \
+      "${STAGEDIR}/${INSTALLDIR}/google-chrome"
+  fi
   ln -snf "${INSTALLDIR}/${PACKAGE}" \
     "${STAGEDIR}/usr/bin/${USR_BIN_SYMLINK_NAME}"
 
diff --git a/chrome/installer/linux/common/postinst.include b/chrome/installer/linux/common/postinst.include
index 9d10185..194e9a4 100644
--- a/chrome/installer/linux/common/postinst.include
+++ b/chrome/installer/linux/common/postinst.include
@@ -15,7 +15,7 @@
 fi
 
 # Update cache of .desktop file MIME types. Non-fatal since it's just a cache.
-update-desktop-database || true
+update-desktop-database > /dev/null 2>&1 || true
 
 # Updates defaults.list file if present.
 update_defaults_list() {
diff --git a/chrome/installer/linux/common/prerm.include b/chrome/installer/linux/common/prerm.include
index 721f525..5bb2c40 100644
--- a/chrome/installer/linux/common/prerm.include
+++ b/chrome/installer/linux/common/prerm.include
@@ -15,4 +15,4 @@
 fi
 
 # Update cache of .desktop file MIME types. Non-fatal since it's just a cache.
-update-desktop-database || true
+update-desktop-database > /dev/null 2>&1 || true
diff --git a/chrome/installer/linux/rpm/build.sh b/chrome/installer/linux/rpm/build.sh
index 52cb1b8..ae4008b 100755
--- a/chrome/installer/linux/rpm/build.sh
+++ b/chrome/installer/linux/rpm/build.sh
@@ -105,10 +105,11 @@
   fi
 
   # Use find-requires script to make sure the dependencies are complete
-  # (especially libc and libstdc++ versions). Filter out udev to avoid
-  # libudev.so.0 vs. libudev.so.1 mismatches.
+  # (especially libc and libstdc++ versions).
+  # - Filter out udev to avoid libudev.so.0 vs. libudev.so.1 mismatches.
+  # - Filter out libmojo_system since that a library that we provide.
   DETECTED_DEPENDS="$(echo "${BUILDDIR}/chrome" | /usr/lib/rpm/find-requires |
-      grep -v udev)"
+      grep -v 'udev\|libmojo_system')"
 
   # Compare the expected dependency list to the generated list.
   BAD_DIFF=0
diff --git a/chrome/installer/linux/rpm/expected_deps_i386 b/chrome/installer/linux/rpm/expected_deps_i386
index 5683fe9..52fd504 100644
--- a/chrome/installer/linux/rpm/expected_deps_i386
+++ b/chrome/installer/linux/rpm/expected_deps_i386
@@ -39,7 +39,6 @@
 libglib-2.0.so.0
 libgobject-2.0.so.0
 libgtk-x11-2.0.so.0
-libmojo_system.so
 libm.so.6
 libm.so.6(GLIBC_2.0)
 libm.so.6(GLIBC_2.1)
diff --git a/chrome/installer/linux/rpm/expected_deps_x86_64 b/chrome/installer/linux/rpm/expected_deps_x86_64
index 59ca7cb..1435e39 100644
--- a/chrome/installer/linux/rpm/expected_deps_x86_64
+++ b/chrome/installer/linux/rpm/expected_deps_x86_64
@@ -33,7 +33,6 @@
 libglib-2.0.so.0()(64bit)
 libgobject-2.0.so.0()(64bit)
 libgtk-x11-2.0.so.0()(64bit)
-libmojo_system.so()(64bit)
 libm.so.6()(64bit)
 libm.so.6(GLIBC_2.2.5)(64bit)
 libnspr4.so()(64bit)
diff --git a/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py b/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py
index 0f3d74f..4010668 100755
--- a/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py
+++ b/chrome/installer/linux/sysroot_scripts/install-debian.wheezy.sysroot.py
@@ -27,7 +27,7 @@
 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
 URL_PREFIX = 'https://commondatastorage.googleapis.com'
 URL_PATH = 'chrome-linux-sysroot/toolchain'
-REVISION = 232685
+REVISION = 259398
 TARBALL_AMD64 = 'debian_wheezy_amd64_sysroot.tgz'
 TARBALL_I386 = 'debian_wheezy_i386_sysroot.tgz'
 SYSROOT_DIR_AMD64 = 'debian_wheezy_amd64-sysroot'
diff --git a/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.amd64 b/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.amd64
index b014e5d..c93eccb 100644
--- a/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.amd64
+++ b/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.amd64
@@ -15,12 +15,12 @@
 main/d/dbus/libdbus-1-dev_1.6.8-1+deb7u1_amd64.deb
 main/e/e2fsprogs/comerr-dev_2.1-1.42.5-1.1_amd64.deb
 main/e/e2fsprogs/libcomerr2_1.42.5-1.1_amd64.deb
-main/e/eglibc/libc6_2.13-38_amd64.deb
-main/e/eglibc/libc6-dev_2.13-38_amd64.deb
+main/e/eglibc/libc6_2.13-38+deb7u1_amd64.deb
+main/e/eglibc/libc6-dev_2.13-38+deb7u1_amd64.deb
 main/e/elfutils/libelf1_0.152-1+wheezy1_amd64.deb
 main/e/elfutils/libelf-dev_0.152-1+wheezy1_amd64.deb
-main/e/expat/libexpat1_2.1.0-1_amd64.deb
-main/e/expat/libexpat1-dev_2.1.0-1_amd64.deb
+main/e/expat/libexpat1_2.1.0-1+deb7u1_amd64.deb
+main/e/expat/libexpat1-dev_2.1.0-1+deb7u1_amd64.deb
 main/f/fontconfig/libfontconfig1_2.9.0-7.1_amd64.deb
 main/f/fontconfig/libfontconfig1-dev_2.9.0-7.1_amd64.deb
 main/f/freetype/libfreetype6_2.4.9-1.1_amd64.deb
@@ -58,6 +58,8 @@
 main/k/krb5/libkrb5support0_1.10.1+dfsg-5+deb7u1_amd64.deb
 main/libc/libcap2/libcap2_2.22-1.2_amd64.deb
 main/libc/libcap2/libcap-dev_2.22-1.2_amd64.deb
+main/libe/libexif/libexif12_0.6.20-3_amd64.deb
+main/libe/libexif/libexif-dev_0.6.20-3_amd64.deb
 main/libf/libffi/libffi5_3.0.10-3_amd64.deb
 main/libg/libgcrypt11/libgcrypt11_1.5.0-5+deb7u1_amd64.deb
 main/libg/libgcrypt11/libgcrypt11-dev_1.5.0-5+deb7u1_amd64.deb
@@ -106,13 +108,13 @@
 main/libx/libxt/libxt-dev_1.1.3-1+deb7u1_amd64.deb
 main/libx/libxtst/libxtst6_1.2.1-1+deb7u1_amd64.deb
 main/libx/libxtst/libxtst-dev_1.2.1-1+deb7u1_amd64.deb
-main/l/linux/linux-libc-dev_3.2.51-1_amd64.deb
-main/n/nspr/libnspr4_4.9.2-1_amd64.deb
-main/n/nspr/libnspr4-dev_4.9.2-1_amd64.deb
-main/n/nss/libnss3_3.14.3-1_amd64.deb
-main/n/nss/libnss3-dev_3.14.3-1_amd64.deb
-main/o/openssl/libssl1.0.0_1.0.1e-2_amd64.deb
-main/o/openssl/libssl-dev_1.0.1e-2_amd64.deb
+main/l/linux/linux-libc-dev_3.2.54-2_amd64.deb
+main/n/nspr/libnspr4_4.9.2-1+deb7u1_amd64.deb
+main/n/nspr/libnspr4-dev_4.9.2-1+deb7u1_amd64.deb
+main/n/nss/libnss3_3.14.5-1_amd64.deb
+main/n/nss/libnss3-dev_3.14.5-1_amd64.deb
+main/o/openssl/libssl1.0.0_1.0.1e-2+deb7u4_amd64.deb
+main/o/openssl/libssl-dev_1.0.1e-2+deb7u4_amd64.deb
 main/o/orbit2/liborbit2_2.14.19-0.1_amd64.deb
 main/p/p11-kit/libp11-kit0_0.12-3_amd64.deb
 main/p/pam/libpam0g_1.1.3-7.1_amd64.deb
@@ -124,8 +126,8 @@
 main/p/pcre3/libpcre3_8.30-5_amd64.deb
 main/p/pcre3/libpcre3-dev_8.30-5_amd64.deb
 main/p/pcre3/libpcrecpp0_8.30-5_amd64.deb
-main/p/pixman/libpixman-1-0_0.26.0-4_amd64.deb
-main/p/pixman/libpixman-1-dev_0.26.0-4_amd64.deb
+main/p/pixman/libpixman-1-0_0.26.0-4+deb7u1_amd64.deb
+main/p/pixman/libpixman-1-dev_0.26.0-4+deb7u1_amd64.deb
 main/p/pulseaudio/libpulse0_2.0-6.1_amd64.deb
 main/p/pulseaudio/libpulse-dev_2.0-6.1_amd64.deb
 main/p/pulseaudio/libpulse-mainloop-glib0_2.0-6.1_amd64.deb
diff --git a/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.i386 b/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.i386
index f38c297..ab63a1e 100644
--- a/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.i386
+++ b/chrome/installer/linux/sysroot_scripts/packagelist.debian.wheezy.i386
@@ -15,12 +15,12 @@
 main/d/dbus/libdbus-1-dev_1.6.8-1+deb7u1_i386.deb
 main/e/e2fsprogs/comerr-dev_2.1-1.42.5-1.1_i386.deb
 main/e/e2fsprogs/libcomerr2_1.42.5-1.1_i386.deb
-main/e/eglibc/libc6_2.13-38_i386.deb
-main/e/eglibc/libc6-dev_2.13-38_i386.deb
+main/e/eglibc/libc6_2.13-38+deb7u1_i386.deb
+main/e/eglibc/libc6-dev_2.13-38+deb7u1_i386.deb
 main/e/elfutils/libelf1_0.152-1+wheezy1_i386.deb
 main/e/elfutils/libelf-dev_0.152-1+wheezy1_i386.deb
-main/e/expat/libexpat1_2.1.0-1_i386.deb
-main/e/expat/libexpat1-dev_2.1.0-1_i386.deb
+main/e/expat/libexpat1_2.1.0-1+deb7u1_i386.deb
+main/e/expat/libexpat1-dev_2.1.0-1+deb7u1_i386.deb
 main/f/fontconfig/libfontconfig1_2.9.0-7.1_i386.deb
 main/f/fontconfig/libfontconfig1-dev_2.9.0-7.1_i386.deb
 main/f/freetype/libfreetype6_2.4.9-1.1_i386.deb
@@ -58,6 +58,8 @@
 main/k/krb5/libkrb5support0_1.10.1+dfsg-5+deb7u1_i386.deb
 main/libc/libcap2/libcap2_2.22-1.2_i386.deb
 main/libc/libcap2/libcap-dev_2.22-1.2_i386.deb
+main/libe/libexif/libexif12_0.6.20-3_i386.deb
+main/libe/libexif/libexif-dev_0.6.20-3_i386.deb
 main/libf/libffi/libffi5_3.0.10-3_i386.deb
 main/libg/libgcrypt11/libgcrypt11_1.5.0-5+deb7u1_i386.deb
 main/libg/libgcrypt11/libgcrypt11-dev_1.5.0-5+deb7u1_i386.deb
@@ -106,13 +108,13 @@
 main/libx/libxt/libxt-dev_1.1.3-1+deb7u1_i386.deb
 main/libx/libxtst/libxtst6_1.2.1-1+deb7u1_i386.deb
 main/libx/libxtst/libxtst-dev_1.2.1-1+deb7u1_i386.deb
-main/l/linux/linux-libc-dev_3.2.51-1_i386.deb
-main/n/nspr/libnspr4_4.9.2-1_i386.deb
-main/n/nspr/libnspr4-dev_4.9.2-1_i386.deb
-main/n/nss/libnss3_3.14.3-1_i386.deb
-main/n/nss/libnss3-dev_3.14.3-1_i386.deb
-main/o/openssl/libssl1.0.0_1.0.1e-2_i386.deb
-main/o/openssl/libssl-dev_1.0.1e-2_i386.deb
+main/l/linux/linux-libc-dev_3.2.54-2_i386.deb
+main/n/nspr/libnspr4_4.9.2-1+deb7u1_i386.deb
+main/n/nspr/libnspr4-dev_4.9.2-1+deb7u1_i386.deb
+main/n/nss/libnss3_3.14.5-1_i386.deb
+main/n/nss/libnss3-dev_3.14.5-1_i386.deb
+main/o/openssl/libssl1.0.0_1.0.1e-2+deb7u4_i386.deb
+main/o/openssl/libssl-dev_1.0.1e-2+deb7u4_i386.deb
 main/o/orbit2/liborbit2_2.14.19-0.1_i386.deb
 main/p/p11-kit/libp11-kit0_0.12-3_i386.deb
 main/p/pam/libpam0g_1.1.3-7.1_i386.deb
@@ -124,8 +126,8 @@
 main/p/pcre3/libpcre3_8.30-5_i386.deb
 main/p/pcre3/libpcre3-dev_8.30-5_i386.deb
 main/p/pcre3/libpcrecpp0_8.30-5_i386.deb
-main/p/pixman/libpixman-1-0_0.26.0-4_i386.deb
-main/p/pixman/libpixman-1-dev_0.26.0-4_i386.deb
+main/p/pixman/libpixman-1-0_0.26.0-4+deb7u1_i386.deb
+main/p/pixman/libpixman-1-dev_0.26.0-4+deb7u1_i386.deb
 main/p/pulseaudio/libpulse0_2.0-6.1_i386.deb
 main/p/pulseaudio/libpulse-dev_2.0-6.1_i386.deb
 main/p/pulseaudio/libpulse-mainloop-glib0_2.0-6.1_i386.deb
diff --git a/chrome/installer/linux/sysroot_scripts/sysroot-creator-debian.wheezy.sh b/chrome/installer/linux/sysroot_scripts/sysroot-creator-debian.wheezy.sh
index 530865a..7eabe61 100755
--- a/chrome/installer/linux/sysroot_scripts/sysroot-creator-debian.wheezy.sh
+++ b/chrome/installer/linux/sysroot_scripts/sysroot-creator-debian.wheezy.sh
@@ -31,7 +31,7 @@
 # Package Config
 ######################################################################
 
-# this is where we get all the debian packages from
+# This is where we get all the debian packages from.
 readonly DEBIAN_REPO=http://http.us.debian.org/debian
 readonly REPO_BASEDIR="${DEBIAN_REPO}/dists/wheezy"
 
@@ -73,6 +73,8 @@
   libdbus-glib-1-2 \
   libelf1 \
   libelf-dev \
+  libexif12 \
+  libexif-dev \
   libexpat1 \
   libexpat1-dev \
   libffi5 \
@@ -319,6 +321,18 @@
   tar zcf ${tarball} -C ${INSTALL_ROOT} .
 }
 
+CheckBuildSysrootArgs() {
+  if [ "$#" -ne "1" ]; then
+    echo "ERROR: BuildSysroot commands only take 1 argument"
+    exit 1
+  fi
+
+  if [ -z "$1" ]; then
+    echo "ERROR: tarball name required"
+    exit 1
+  fi
+}
+
 ######################################################################
 #
 ######################################################################
@@ -437,11 +451,12 @@
 #@
 #@    Build everything and package it
 BuildSysrootAmd64() {
+  CheckBuildSysrootArgs $@
   ClearInstallDir
   InstallIntoSysroot ${DEBIAN_DEP_FILES_AMD64}
   CleanupJailSymlinks
   HacksAndPatchesAmd64
-  CreateTarBall $1
+  CreateTarBall "$1"
 }
 
 #@
@@ -449,11 +464,12 @@
 #@
 #@    Build everything and package it
 BuildSysrootI386() {
+  CheckBuildSysrootArgs $@
   ClearInstallDir
   InstallIntoSysroot ${DEBIAN_DEP_FILES_I386}
   CleanupJailSymlinks
   HacksAndPatchesI386
-  CreateTarBall $1
+  CreateTarBall "$1"
 }
 
 #
diff --git a/chrome/installer/setup/install.cc b/chrome/installer/setup/install.cc
index 078a9ac..e7cc375 100644
--- a/chrome/installer/setup/install.cc
+++ b/chrome/installer/setup/install.cc
@@ -676,14 +676,11 @@
   // present for this user (as some shortcuts used to be installed on first
   // run and this could otherwise re-install shortcuts for users that have
   // already deleted them in the past).
-  base::FilePath first_run_sentinel;
-  InstallUtil::GetSentinelFilePath(
-      chrome::kFirstRunSentinel, chrome.distribution(), &first_run_sentinel);
   // Decide whether to create the shortcuts or simply replace existing
   // shortcuts; if the decision is to create them, only shortcuts whose matching
   // all-users shortcut isn't present on the system will be created.
   InstallShortcutOperation install_operation =
-      (!force && base::PathExists(first_run_sentinel) ?
+      (!force && InstallUtil::IsFirstRunSentinelPresent() ?
            INSTALL_SHORTCUT_REPLACE_EXISTING :
            INSTALL_SHORTCUT_CREATE_EACH_IF_NO_SYSTEM_LEVEL);
 
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc
index 2562be0..9847c32 100644
--- a/chrome/installer/setup/setup_main.cc
+++ b/chrome/installer/setup/setup_main.cc
@@ -1199,6 +1199,20 @@
     } else {
       *exit_code = installer::PATCH_INVALID_ARGUMENTS;
     }
+  } else if (cmd_line.HasSwitch(installer::switches::kReenableAutoupdates)) {
+    // setup.exe has been asked to attempt to reenable updates for Chrome.
+    // Figure out whether we should do so for the multi binaries or the main
+    // Chrome product.
+    BrowserDistribution::Type dist_type = BrowserDistribution::CHROME_BROWSER;
+    if (installer_state->is_multi_install())
+      dist_type = BrowserDistribution::CHROME_BINARIES;
+
+    BrowserDistribution* dist =
+        BrowserDistribution::GetSpecificDistribution(dist_type);
+    bool updates_enabled =
+        GoogleUpdateSettings::ReenableAutoupdatesForApp(dist->GetAppGuid());
+    *exit_code = updates_enabled ? installer::REENABLE_UPDATES_SUCCEEDED :
+                                   installer::REENABLE_UPDATES_FAILED;
   } else {
     handled = false;
   }
diff --git a/chrome/installer/util/eula_util.cc b/chrome/installer/util/eula_util.cc
index 9bbf502..e1051e4 100644
--- a/chrome/installer/util/eula_util.cc
+++ b/chrome/installer/util/eula_util.cc
@@ -6,7 +6,6 @@
 
 #include "base/file_util.h"
 #include "base/memory/scoped_ptr.h"
-#include "chrome/common/chrome_constants.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/install_util.h"
 #include "chrome/installer/util/installation_state.h"
@@ -18,16 +17,6 @@
 
 namespace {
 
-bool IsChromeFirstRunPending(BrowserDistribution* dist) {
-  // Chrome creates the first run sentinel after the user has gone through the
-  // first-run flow. Assume Chrome has been run if the path to the sentinel
-  // cannot be determined.
-  base::FilePath first_run_sentinel;
-  return InstallUtil::GetSentinelFilePath(chrome::kFirstRunSentinel, dist,
-                                          &first_run_sentinel) &&
-      !base::PathExists(first_run_sentinel);
-}
-
 bool IsEULAAcceptanceFlagged(BrowserDistribution* dist) {
   // Chrome creates the EULA sentinel after the EULA has been accepted when
   // doing so is required by master_preferences. Assume the EULA has not been
@@ -88,7 +77,7 @@
   if (prod_state.GetEulaAccepted(&eula_accepted) && !eula_accepted)
     return QUERY_EULA_NOT_ACCEPTED;
 
-  if (!IsChromeFirstRunPending(dist) || IsEULAAcceptanceFlagged(dist))
+  if (InstallUtil::IsFirstRunSentinelPresent() || IsEULAAcceptanceFlagged(dist))
     return QUERY_EULA_ACCEPTED;
 
   // EULA acceptance not flagged. Now see if it is required.
diff --git a/chrome/installer/util/google_update_settings.cc b/chrome/installer/util/google_update_settings.cc
index e29f987..c6cba00 100644
--- a/chrome/installer/util/google_update_settings.cc
+++ b/chrome/installer/util/google_update_settings.cc
@@ -31,19 +31,27 @@
 using base::win::RegKey;
 using installer::InstallationState;
 
-namespace {
-
-const wchar_t kGoogleUpdatePoliciesKey[] =
+const wchar_t GoogleUpdateSettings::kPoliciesKey[] =
     L"SOFTWARE\\Policies\\Google\\Update";
-const wchar_t kGoogleUpdateUpdatePolicyValue[] = L"UpdateDefault";
-const wchar_t kGoogleUpdateUpdateOverrideValuePrefix[] = L"Update";
-const GoogleUpdateSettings::UpdatePolicy kGoogleUpdateDefaultUpdatePolicy =
+const wchar_t GoogleUpdateSettings::kUpdatePolicyValue[] = L"UpdateDefault";
+const wchar_t GoogleUpdateSettings::kUpdateOverrideValuePrefix[] = L"Update";
+const wchar_t GoogleUpdateSettings::kCheckPeriodOverrideMinutes[] =
+    L"AutoUpdateCheckPeriodMinutes";
+
+// Don't allow update periods longer than six weeks.
+const int GoogleUpdateSettings::kCheckPeriodOverrideMinutesMax =
+    60 * 24 * 7 * 6;
+
+const GoogleUpdateSettings::UpdatePolicy
+GoogleUpdateSettings::kDefaultUpdatePolicy =
 #if defined(GOOGLE_CHROME_BUILD)
     GoogleUpdateSettings::AUTOMATIC_UPDATES;
 #else
     GoogleUpdateSettings::UPDATES_DISABLED;
 #endif
 
+namespace {
+
 bool ReadGoogleUpdateStrKey(const wchar_t* const name, std::wstring* value) {
   BrowserDistribution* dist = BrowserDistribution::GetDistribution();
   std::wstring reg_path = dist->GetStateKey();
@@ -537,22 +545,17 @@
     const std::wstring& app_guid,
     bool* is_overridden) {
   bool found_override = false;
-  UpdatePolicy update_policy = kGoogleUpdateDefaultUpdatePolicy;
+  UpdatePolicy update_policy = kDefaultUpdatePolicy;
 
 #if defined(GOOGLE_CHROME_BUILD)
   DCHECK(!app_guid.empty());
   RegKey policy_key;
 
   // Google Update Group Policy settings are always in HKLM.
-  if (policy_key.Open(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                      KEY_QUERY_VALUE) == ERROR_SUCCESS) {
-    static const size_t kPrefixLen =
-        arraysize(kGoogleUpdateUpdateOverrideValuePrefix) - 1;
-    DWORD value;
-    std::wstring app_update_override;
-    app_update_override.reserve(kPrefixLen + app_guid.size());
-    app_update_override.append(kGoogleUpdateUpdateOverrideValuePrefix,
-                               kPrefixLen);
+  if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey, KEY_QUERY_VALUE) ==
+          ERROR_SUCCESS) {
+    DWORD value = 0;
+    base::string16 app_update_override(kUpdateOverrideValuePrefix);
     app_update_override.append(app_guid);
     // First try to read and comprehend the app-specific override.
     found_override = (policy_key.ReadValueDW(app_update_override.c_str(),
@@ -561,8 +564,7 @@
 
     // Failing that, try to read and comprehend the default override.
     if (!found_override &&
-        policy_key.ReadValueDW(kGoogleUpdateUpdatePolicyValue,
-                               &value) == ERROR_SUCCESS) {
+        policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS) {
       GetUpdatePolicyFromDword(value, &update_policy);
     }
   }
@@ -574,6 +576,96 @@
   return update_policy;
 }
 
+// static
+bool GoogleUpdateSettings::AreAutoupdatesEnabled(
+    const base::string16& app_guid) {
+  // Check the auto-update check period override. If it is 0 or exceeds the
+  // maximum timeout, then for all intents and purposes auto updates are
+  // disabled.
+  RegKey policy_key;
+  DWORD value = 0;
+  if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey,
+                      KEY_QUERY_VALUE) == ERROR_SUCCESS &&
+      policy_key.ReadValueDW(kCheckPeriodOverrideMinutes,
+                             &value) == ERROR_SUCCESS &&
+      (value == 0 || value > kCheckPeriodOverrideMinutesMax)) {
+    return false;
+  }
+
+  UpdatePolicy policy = GetAppUpdatePolicy(app_guid, NULL);
+  return (policy == AUTOMATIC_UPDATES || policy == AUTO_UPDATES_ONLY);
+}
+
+// static
+bool GoogleUpdateSettings::ReenableAutoupdatesForApp(
+    const base::string16& app_guid) {
+#if defined(GOOGLE_CHROME_BUILD)
+  int needs_reset_count = 0;
+  int did_reset_count = 0;
+
+  UpdatePolicy update_policy = kDefaultUpdatePolicy;
+  RegKey policy_key;
+  if (policy_key.Open(HKEY_LOCAL_MACHINE, kPoliciesKey,
+                      KEY_SET_VALUE | KEY_QUERY_VALUE) == ERROR_SUCCESS) {
+    // First check the app-specific override value and reset that if needed.
+    // Note that this intentionally sets the override to AUTOMATIC_UPDATES
+    // even if it was previously AUTO_UPDATES_ONLY. The thinking is that
+    // AUTOMATIC_UPDATES is marginally more likely to let a user update and this
+    // code is only called when a stuck user asks for updates.
+    base::string16 app_update_override(kUpdateOverrideValuePrefix);
+    app_update_override.append(app_guid);
+    DWORD value = 0;
+    bool has_app_update_override =
+        policy_key.ReadValueDW(app_update_override.c_str(),
+                               &value) == ERROR_SUCCESS;
+    if (has_app_update_override &&
+        (!GetUpdatePolicyFromDword(value, &update_policy) ||
+         update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) {
+      ++needs_reset_count;
+      if (policy_key.WriteValue(
+              app_update_override.c_str(),
+              static_cast<DWORD>(GoogleUpdateSettings::AUTOMATIC_UPDATES)) ==
+                  ERROR_SUCCESS) {
+        ++did_reset_count;
+      }
+    }
+
+    // If there was no app-specific override policy see if there's a global
+    // policy preventing updates and delete it if so.
+    if (!has_app_update_override &&
+        policy_key.ReadValueDW(kUpdatePolicyValue, &value) == ERROR_SUCCESS &&
+        (!GetUpdatePolicyFromDword(value, &update_policy) ||
+         update_policy != GoogleUpdateSettings::AUTOMATIC_UPDATES)) {
+      ++needs_reset_count;
+      if (policy_key.DeleteValue(kUpdatePolicyValue) == ERROR_SUCCESS)
+        ++did_reset_count;
+    }
+
+    // Check the auto-update check period override. If it is 0 or exceeds
+    // the maximum timeout, delete the override value.
+    if (policy_key.ReadValueDW(kCheckPeriodOverrideMinutes,
+                               &value) == ERROR_SUCCESS &&
+        (value == 0 || value > kCheckPeriodOverrideMinutesMax)) {
+      ++needs_reset_count;
+      if (policy_key.DeleteValue(kCheckPeriodOverrideMinutes) == ERROR_SUCCESS)
+        ++did_reset_count;
+    }
+
+    // Return whether the number of successful resets is the same as the
+    // number of things that appeared to need resetting.
+    return (needs_reset_count == did_reset_count);
+  } else {
+    // For some reason we couldn't open the policy key with the desired
+    // permissions to make changes (the most likely reason is that there is no
+    // policy set). Simply return whether or not we think updates are enabled.
+    return AreAutoupdatesEnabled(app_guid);
+  }
+
+#endif
+  // Non Google Chrome isn't going to autoupdate.
+  return true;
+}
+
 void GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms() {
   const bool is_multi_install = InstallUtil::IsMultiInstall(
       BrowserDistribution::GetDistribution(), IsSystemInstall());
diff --git a/chrome/installer/util/google_update_settings.h b/chrome/installer/util/google_update_settings.h
index dfd948c..093f8bd 100644
--- a/chrome/installer/util/google_update_settings.h
+++ b/chrome/installer/util/google_update_settings.h
@@ -34,6 +34,14 @@
     UPDATE_POLICIES_COUNT
   };
 
+  static const wchar_t kPoliciesKey[];
+  static const wchar_t kUpdatePolicyValue[];
+  static const wchar_t kUpdateOverrideValuePrefix[];
+  static const wchar_t kCheckPeriodOverrideMinutes[];
+  static const int kCheckPeriodOverrideMinutesDefault;
+  static const int kCheckPeriodOverrideMinutesMax;
+  static const GoogleUpdateSettings::UpdatePolicy kDefaultUpdatePolicy;
+
   // Defines product data that is tracked/used by Google Update.
   struct ProductData {
     // The currently installed version.
@@ -228,6 +236,23 @@
   static UpdatePolicy GetAppUpdatePolicy(const std::wstring& app_guid,
                                          bool* is_overridden);
 
+  // Returns true if the app indicated by |app_guid| should be updated
+  // automatically by Google Update based on current autoupdate settings. This
+  // is distinct from GetApUpdatePolicy which checks only a subset of things
+  // that can cause an app not to update.
+  static bool AreAutoupdatesEnabled(const base::string16& app_guid);
+
+  // Attempts to reenable auto-updates for |app_guid| by removing
+  // any group policy settings that would block updates from occurring. This is
+  // a superset of the things checked by GetAppUpdatePolicy() as
+  // GetAppUpdatePolicy() does not check Omaha's AutoUpdateCheckPeriodMinutes
+  // setting which will be reset by this method. Will need to be called from an
+  // elevated process since those settings live in HKLM. Returns true if there
+  // is a reasonable belief that updates are not disabled by policy when this
+  // method returns, false otherwise. Note that for Chromium builds, this
+  // returns true since Chromium is assumed not to autoupdate.
+  static bool ReenableAutoupdatesForApp(const base::string16& app_guid);
+
   // Records UMA stats about Chrome's update policy.
   static void RecordChromeUpdatePolicyHistograms();
 
diff --git a/chrome/installer/util/google_update_settings_unittest.cc b/chrome/installer/util/google_update_settings_unittest.cc
index 536b6f3..9eef4e5 100644
--- a/chrome/installer/util/google_update_settings_unittest.cc
+++ b/chrome/installer/util/google_update_settings_unittest.cc
@@ -25,17 +25,6 @@
 
 namespace {
 
-const wchar_t kGoogleUpdatePoliciesKey[] =
-    L"SOFTWARE\\Policies\\Google\\Update";
-const wchar_t kGoogleUpdateUpdateDefault[] = L"UpdateDefault";
-const wchar_t kGoogleUpdateUpdatePrefix[] = L"Update";
-const GoogleUpdateSettings::UpdatePolicy kDefaultUpdatePolicy =
-#if defined(GOOGLE_CHROME_BUILD)
-    GoogleUpdateSettings::AUTOMATIC_UPDATES;
-#else
-    GoogleUpdateSettings::UPDATES_DISABLED;
-#endif
-
 const wchar_t kTestProductGuid[] = L"{89F1B351-B15D-48D4-8F10-1298721CF13D}";
 const wchar_t kTestExperimentLabel[] = L"test_label_value";
 
@@ -206,6 +195,68 @@
     return ap_key_value;
   }
 
+  bool SetUpdatePolicyForAppGuid(const base::string16& app_guid,
+                                 GoogleUpdateSettings::UpdatePolicy policy) {
+    RegKey policy_key;
+    if (policy_key.Create(HKEY_LOCAL_MACHINE,
+                          GoogleUpdateSettings::kPoliciesKey,
+                          KEY_SET_VALUE) == ERROR_SUCCESS) {
+      base::string16 app_update_override(
+          GoogleUpdateSettings::kUpdateOverrideValuePrefix);
+      app_update_override.append(app_guid);
+      return policy_key.WriteValue(app_update_override.c_str(),
+                                   static_cast<DWORD>(policy)) == ERROR_SUCCESS;
+    }
+    return false;
+  }
+
+  DWORD GetUpdatePolicyForAppGuid(const base::string16& app_guid) {
+    RegKey policy_key;
+    if (policy_key.Create(HKEY_LOCAL_MACHINE,
+                          GoogleUpdateSettings::kPoliciesKey,
+                          KEY_QUERY_VALUE) == ERROR_SUCCESS) {
+      base::string16 app_update_override(
+          GoogleUpdateSettings::kUpdateOverrideValuePrefix);
+      app_update_override.append(app_guid);
+
+      DWORD value = -1;
+      if (policy_key.ReadValueDW(app_update_override.c_str(),
+                                 &value) == ERROR_SUCCESS) {
+        return value;
+      }
+    }
+    return -1;
+  }
+
+  bool SetGlobalUpdatePolicy(GoogleUpdateSettings::UpdatePolicy policy) {
+    RegKey policy_key;
+    return policy_key.Create(HKEY_LOCAL_MACHINE,
+                             GoogleUpdateSettings::kPoliciesKey,
+                             KEY_SET_VALUE) == ERROR_SUCCESS &&
+           policy_key.WriteValue(GoogleUpdateSettings::kUpdatePolicyValue,
+                                 static_cast<DWORD>(policy)) == ERROR_SUCCESS;
+  }
+
+  DWORD GetGlobalUpdatePolicy() {
+    RegKey policy_key;
+    DWORD value = -1;
+    return (policy_key.Create(HKEY_LOCAL_MACHINE,
+                              GoogleUpdateSettings::kPoliciesKey,
+                              KEY_QUERY_VALUE) == ERROR_SUCCESS &&
+            policy_key.ReadValueDW(GoogleUpdateSettings::kUpdatePolicyValue,
+                                   &value) == ERROR_SUCCESS) ? value : -1;
+  }
+
+  bool SetUpdateTimeoutOverride(DWORD time_in_minutes) {
+    RegKey policy_key;
+    return policy_key.Create(HKEY_LOCAL_MACHINE,
+                             GoogleUpdateSettings::kPoliciesKey,
+                             KEY_SET_VALUE) == ERROR_SUCCESS &&
+           policy_key.WriteValue(
+               GoogleUpdateSettings::kCheckPeriodOverrideMinutes,
+               time_in_minutes) == ERROR_SUCCESS;
+  }
+
   registry_util::RegistryOverrideManager registry_overrides_;
 };
 
@@ -488,23 +539,26 @@
 TEST_F(GoogleUpdateSettingsTest, GetAppUpdatePolicyNoOverride) {
   // There are no policies at all.
   EXPECT_EQ(ERROR_FILE_NOT_FOUND,
-            RegKey().Open(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey().Open(HKEY_LOCAL_MACHINE,
+                          GoogleUpdateSettings::kPoliciesKey,
                           KEY_QUERY_VALUE));
   bool is_overridden = true;
-  EXPECT_EQ(kDefaultUpdatePolicy,
+  EXPECT_EQ(GoogleUpdateSettings::kDefaultUpdatePolicy,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
                                                      &is_overridden));
   EXPECT_FALSE(is_overridden);
 
   // The policy key exists, but there are no values of interest present.
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey().Create(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey().Create(HKEY_LOCAL_MACHINE,
+                            GoogleUpdateSettings::kPoliciesKey,
                             KEY_SET_VALUE));
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey().Open(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey().Open(HKEY_LOCAL_MACHINE,
+                          GoogleUpdateSettings::kPoliciesKey,
                           KEY_QUERY_VALUE));
   is_overridden = true;
-  EXPECT_EQ(kDefaultUpdatePolicy,
+  EXPECT_EQ(GoogleUpdateSettings::kDefaultUpdatePolicy,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
                                                      &is_overridden));
   EXPECT_FALSE(is_overridden);
@@ -516,9 +570,10 @@
 // present.
 TEST_F(GoogleUpdateSettingsTest, GetAppUpdatePolicyDefaultOverride) {
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
-                                             static_cast<DWORD>(0)));
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
+                   KEY_SET_VALUE).WriteValue(
+                       GoogleUpdateSettings::kUpdatePolicyValue,
+                       static_cast<DWORD>(0)));
   bool is_overridden = true;
   EXPECT_EQ(GoogleUpdateSettings::UPDATES_DISABLED,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
@@ -526,9 +581,10 @@
   EXPECT_FALSE(is_overridden);
 
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
-                                             static_cast<DWORD>(1)));
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
+                   KEY_SET_VALUE).WriteValue(
+                       GoogleUpdateSettings::kUpdatePolicyValue,
+                       static_cast<DWORD>(1)));
   is_overridden = true;
   EXPECT_EQ(GoogleUpdateSettings::AUTOMATIC_UPDATES,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
@@ -536,9 +592,10 @@
   EXPECT_FALSE(is_overridden);
 
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
-                                             static_cast<DWORD>(2)));
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
+                   KEY_SET_VALUE).WriteValue(
+                       GoogleUpdateSettings::kUpdatePolicyValue,
+                       static_cast<DWORD>(2)));
   is_overridden = true;
   EXPECT_EQ(GoogleUpdateSettings::MANUAL_UPDATES_ONLY,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
@@ -546,9 +603,10 @@
   EXPECT_FALSE(is_overridden);
 
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
-                                             static_cast<DWORD>(3)));
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
+                   KEY_SET_VALUE).WriteValue(
+                       GoogleUpdateSettings::kUpdatePolicyValue,
+                       static_cast<DWORD>(3)));
   is_overridden = true;
   EXPECT_EQ(GoogleUpdateSettings::AUTO_UPDATES_ONLY,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
@@ -557,11 +615,12 @@
 
   // The default policy should be in force for bogus values.
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
-                                             static_cast<DWORD>(4)));
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
+                   KEY_SET_VALUE).WriteValue(
+                       GoogleUpdateSettings::kUpdatePolicyValue,
+                       static_cast<DWORD>(4)));
   is_overridden = true;
-  EXPECT_EQ(kDefaultUpdatePolicy,
+  EXPECT_EQ(GoogleUpdateSettings::kDefaultUpdatePolicy,
             GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
                                                      &is_overridden));
   EXPECT_FALSE(is_overridden);
@@ -569,15 +628,17 @@
 
 // Test that an app-specific override is used if present.
 TEST_F(GoogleUpdateSettingsTest, GetAppUpdatePolicyAppOverride) {
-  std::wstring app_policy_value(kGoogleUpdateUpdatePrefix);
+  std::wstring app_policy_value(
+      GoogleUpdateSettings::kUpdateOverrideValuePrefix);
   app_policy_value.append(kTestProductGuid);
 
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
-                                             static_cast<DWORD>(1)));
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
+                   KEY_SET_VALUE).WriteValue(
+                       GoogleUpdateSettings::kUpdatePolicyValue,
+                       static_cast<DWORD>(1)));
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
                    KEY_SET_VALUE).WriteValue(app_policy_value.c_str(),
                                              static_cast<DWORD>(0)));
   bool is_overridden = false;
@@ -587,11 +648,12 @@
   EXPECT_TRUE(is_overridden);
 
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
-                   KEY_SET_VALUE).WriteValue(kGoogleUpdateUpdateDefault,
-                                             static_cast<DWORD>(0)));
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
+                   KEY_SET_VALUE).WriteValue(
+                       GoogleUpdateSettings::kUpdatePolicyValue,
+                       static_cast<DWORD>(0)));
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
                    KEY_SET_VALUE).WriteValue(app_policy_value.c_str(),
                                              static_cast<DWORD>(1)));
   is_overridden = false;
@@ -601,7 +663,7 @@
   EXPECT_TRUE(is_overridden);
 
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
                    KEY_SET_VALUE).WriteValue(app_policy_value.c_str(),
                                              static_cast<DWORD>(2)));
   is_overridden = false;
@@ -611,7 +673,7 @@
   EXPECT_TRUE(is_overridden);
 
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
                    KEY_SET_VALUE).WriteValue(app_policy_value.c_str(),
                                              static_cast<DWORD>(3)));
   is_overridden = false;
@@ -622,7 +684,7 @@
 
   // The default policy should be in force for bogus values.
   EXPECT_EQ(ERROR_SUCCESS,
-            RegKey(HKEY_LOCAL_MACHINE, kGoogleUpdatePoliciesKey,
+            RegKey(HKEY_LOCAL_MACHINE, GoogleUpdateSettings::kPoliciesKey,
                    KEY_SET_VALUE).WriteValue(app_policy_value.c_str(),
                                              static_cast<DWORD>(4)));
   is_overridden = true;
@@ -632,6 +694,90 @@
   EXPECT_FALSE(is_overridden);
 }
 
+TEST_F(GoogleUpdateSettingsTest, PerAppUpdatesDisabledByPolicy) {
+  EXPECT_TRUE(
+      SetUpdatePolicyForAppGuid(kTestProductGuid,
+                                GoogleUpdateSettings::UPDATES_DISABLED));
+  bool is_overridden = false;
+  GoogleUpdateSettings::UpdatePolicy update_policy =
+      GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
+                                               &is_overridden);
+  EXPECT_TRUE(is_overridden);
+  EXPECT_EQ(GoogleUpdateSettings::UPDATES_DISABLED, update_policy);
+  EXPECT_FALSE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+
+  EXPECT_TRUE(
+      GoogleUpdateSettings::ReenableAutoupdatesForApp(kTestProductGuid));
+  update_policy = GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
+                                                           &is_overridden);
+  // Should still have a policy but now that policy should explicitly enable
+  // updates.
+  EXPECT_TRUE(is_overridden);
+  EXPECT_EQ(GoogleUpdateSettings::AUTOMATIC_UPDATES, update_policy);
+  EXPECT_TRUE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+}
+
+TEST_F(GoogleUpdateSettingsTest, PerAppUpdatesEnabledWithGlobalDisabled) {
+  // Disable updates globally but enable them for our specific app (the app-
+  // specific setting should take precedence).
+  EXPECT_TRUE(
+      SetUpdatePolicyForAppGuid(kTestProductGuid,
+                                GoogleUpdateSettings::AUTOMATIC_UPDATES));
+  EXPECT_TRUE(SetGlobalUpdatePolicy(GoogleUpdateSettings::UPDATES_DISABLED));
+
+  // Make sure we read this as still having updates enabled.
+  EXPECT_TRUE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+
+  // Make sure that the reset action returns true and is a no-op.
+  EXPECT_TRUE(
+      GoogleUpdateSettings::ReenableAutoupdatesForApp(kTestProductGuid));
+  EXPECT_EQ(static_cast<DWORD>(GoogleUpdateSettings::AUTOMATIC_UPDATES),
+            GetUpdatePolicyForAppGuid(kTestProductGuid));
+  EXPECT_EQ(static_cast<DWORD>(GoogleUpdateSettings::UPDATES_DISABLED),
+            GetGlobalUpdatePolicy());
+}
+
+TEST_F(GoogleUpdateSettingsTest, GlobalUpdatesDisabledByPolicy) {
+  EXPECT_TRUE(SetGlobalUpdatePolicy(GoogleUpdateSettings::UPDATES_DISABLED));
+  bool is_overridden = false;
+
+  // The contract for GetAppUpdatePolicy states that |is_overridden| should be
+  // set to false when updates are disabled on a non-app-specific basis.
+  GoogleUpdateSettings::UpdatePolicy update_policy =
+      GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
+                                               &is_overridden);
+  EXPECT_FALSE(is_overridden);
+  EXPECT_EQ(GoogleUpdateSettings::UPDATES_DISABLED, update_policy);
+  EXPECT_FALSE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+
+  EXPECT_TRUE(
+      GoogleUpdateSettings::ReenableAutoupdatesForApp(kTestProductGuid));
+  update_policy = GoogleUpdateSettings::GetAppUpdatePolicy(kTestProductGuid,
+                                                           &is_overridden);
+  // Policy should now be to enable updates, |is_overridden| should still be
+  // false.
+  EXPECT_FALSE(is_overridden);
+  EXPECT_EQ(GoogleUpdateSettings::AUTOMATIC_UPDATES, update_policy);
+  EXPECT_TRUE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+}
+
+TEST_F(GoogleUpdateSettingsTest, UpdatesDisabledByTimeout) {
+  // Disable updates altogether.
+  EXPECT_TRUE(SetUpdateTimeoutOverride(0));
+  EXPECT_FALSE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+  EXPECT_TRUE(
+      GoogleUpdateSettings::ReenableAutoupdatesForApp(kTestProductGuid));
+  EXPECT_TRUE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+
+  // Set the update period to something unreasonable.
+  EXPECT_TRUE(SetUpdateTimeoutOverride(
+      GoogleUpdateSettings::kCheckPeriodOverrideMinutesMax + 1));
+  EXPECT_FALSE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+  EXPECT_TRUE(
+      GoogleUpdateSettings::ReenableAutoupdatesForApp(kTestProductGuid));
+  EXPECT_TRUE(GoogleUpdateSettings::AreAutoupdatesEnabled(kTestProductGuid));
+}
+
 TEST_F(GoogleUpdateSettingsTest, ExperimentsLabelHelperSystem) {
   TestExperimentsLabelHelper(SYSTEM_INSTALL);
 }
@@ -809,6 +955,7 @@
         (state_medium_value_ == TRUE_SETTING) :
         (state_value_ == TRUE_SETTING);
   }
+
  private:
   bool system_level_;
   bool multi_install_;
diff --git a/chrome/installer/util/google_update_util.cc b/chrome/installer/util/google_update_util.cc
index 18ea762..c7de7a5 100644
--- a/chrome/installer/util/google_update_util.cc
+++ b/chrome/installer/util/google_update_util.cc
@@ -11,9 +11,11 @@
 
 #include "base/command_line.h"
 #include "base/environment.h"
+#include "base/file_util.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/path_service.h"
 #include "base/process/kill.h"
 #include "base/process/launch.h"
 #include "base/strings/string16.h"
@@ -21,9 +23,15 @@
 #include "base/time/time.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_handle.h"
+#include "base/win/win_util.h"
+#include "base/win/windows_version.h"
 #include "chrome/installer/launcher_support/chrome_launcher_support.h"
+#include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/google_update_constants.h"
 #include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/installation_state.h"
+#include "chrome/installer/util/product.h"
 
 using base::win::RegKey;
 
@@ -217,6 +225,47 @@
   return success;
 }
 
+void ElevateIfNeededToReenableUpdates() {
+  base::FilePath chrome_exe;
+  if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
+    NOTREACHED();
+    return;
+  }
+  installer::ProductState product_state;
+  BrowserDistribution* dist = BrowserDistribution::GetDistribution();
+  const bool system_install = !InstallUtil::IsPerUserInstall(
+      chrome_exe.value().c_str());
+  if (!product_state.Initialize(system_install, dist))
+    return;
+  base::FilePath exe_path(product_state.GetSetupPath());
+  if (exe_path.empty() || !base::PathExists(exe_path)) {
+    LOG(ERROR) << "Could not find setup.exe to reenable updates.";
+    return;
+  }
+
+  CommandLine cmd(exe_path);
+  cmd.AppendSwitch(installer::switches::kReenableAutoupdates);
+  installer::Product product(dist);
+  product.InitializeFromUninstallCommand(product_state.uninstall_command());
+  product.AppendProductFlags(&cmd);
+  if (system_install)
+    cmd.AppendSwitch(installer::switches::kSystemLevel);
+  if (product_state.uninstall_command().HasSwitch(
+          installer::switches::kVerboseLogging)) {
+    cmd.AppendSwitch(installer::switches::kVerboseLogging);
+  }
+
+  base::LaunchOptions launch_options;
+  launch_options.force_breakaway_from_job_ = true;
+
+  if (base::win::GetVersion() >= base::win::VERSION_VISTA &&
+      base::win::UserAccountControlIsEnabled()) {
+    base::LaunchElevatedProcess(cmd, launch_options, NULL);
+  } else {
+    base::LaunchProcess(cmd, launch_options, NULL);
+  }
+}
+
 std::string GetUntrustedDataValue(const std::string& key) {
   std::map<std::string, std::string> untrusted_data;
   if (GetGoogleUpdateUntrustedData(&untrusted_data)) {
diff --git a/chrome/installer/util/google_update_util.h b/chrome/installer/util/google_update_util.h
index 8ef2b9a..4f240af 100644
--- a/chrome/installer/util/google_update_util.h
+++ b/chrome/installer/util/google_update_util.h
@@ -22,6 +22,11 @@
 // Returns false if Google Update could not be executed, or times out.
 bool UninstallGoogleUpdate(bool system_install);
 
+// Run setup.exe to attempt to reenable updates for for Chrome while elevating
+// if needed. Setup.exe will call into
+// GoogleUpdateSettings::ReenableAutoupdatesForApp() to do the work.
+void ElevateIfNeededToReenableUpdates();
+
 // Returns the value corresponding to |key| in untrusted data passed from
 // Google Update.  Returns an empty string if |key| is absent or if its value
 // contains non-printable characters.
diff --git a/chrome/installer/util/install_util.cc b/chrome/installer/util/install_util.cc
index 570386e..11196c4 100644
--- a/chrome/installer/util/install_util.cc
+++ b/chrome/installer/util/install_util.cc
@@ -28,6 +28,8 @@
 #include "base/win/metro.h"
 #include "base/win/registry.h"
 #include "base/win/windows_version.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
 #include "chrome/installer/util/browser_distribution.h"
 #include "chrome/installer/util/google_update_constants.h"
 #include "chrome/installer/util/helper.h"
@@ -399,10 +401,19 @@
   return sxs;
 }
 
-bool InstallUtil::GetSentinelFilePath(
-    const base::FilePath::CharType* file,
-    BrowserDistribution* dist,
-    base::FilePath* path) {
+// static
+bool InstallUtil::IsFirstRunSentinelPresent() {
+  // TODO(msw): Consolidate with first_run::internal::IsFirstRunSentinelPresent.
+  base::FilePath user_data_dir;
+  return !PathService::Get(chrome::DIR_USER_DATA, &user_data_dir) ||
+         base::PathExists(user_data_dir.Append(chrome::kFirstRunSentinel));
+}
+
+// static
+bool InstallUtil::GetSentinelFilePath(const base::FilePath::CharType* file,
+                                      BrowserDistribution* dist,
+                                      base::FilePath* path) {
+  // TODO(msw): Use PathService to obtain the correct DIR_USER_DATA.
   std::vector<base::FilePath> user_data_dir_paths;
   installer::GetChromeUserDataPaths(dist, &user_data_dir_paths);
 
diff --git a/chrome/installer/util/install_util.h b/chrome/installer/util/install_util.h
index 5bc6b91..53d389f 100644
--- a/chrome/installer/util/install_util.h
+++ b/chrome/installer/util/install_util.h
@@ -106,6 +106,9 @@
   // by either --chrome-sxs or the executable path).
   static bool IsChromeSxSProcess();
 
+  // Returns true if the sentinel file exists (or the path cannot be obtained).
+  static bool IsFirstRunSentinelPresent();
+
   // Populates |path| with the path to |file| in the sentinel directory for
   // |dist|. Returns false on error.
   static bool GetSentinelFilePath(const base::FilePath::CharType* file,
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc
index f19bc0a..b4639e5 100644
--- a/chrome/installer/util/util_constants.cc
+++ b/chrome/installer/util/util_constants.cc
@@ -112,7 +112,10 @@
 // exit code: 0 if EULA not accepted, 1 if EULA accepted, and E_FAIL on error.
 const char kQueryEULAAcceptance[] = "query-eula-acceptance";
 
-// Register Chrome as a valid browser on the current sytem. This option
+// Requests that setup attempt to reenable autoupdates for Chrome.
+const char kReenableAutoupdates[] = "reenable-autoupdates";
+
+// Register Chrome as a valid browser on the current system. This option
 // requires that setup.exe is running as admin. If this option is specified,
 // options kInstallArchive and kUninstall are ignored.
 const char kRegisterChromeBrowser[] = "register-chrome-browser";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h
index d8ab60a..d5d6281 100644
--- a/chrome/installer/util/util_constants.h
+++ b/chrome/installer/util/util_constants.h
@@ -90,12 +90,15 @@
   UNUSED_BINARIES_UNINSTALLED,  // 52. The binaries were uninstalled.
   UNSUPPORTED_OPTION,          // 53. An unsupported legacy option was given.
   CPU_NOT_SUPPORTED,           // 54. Current OS not supported
+  REENABLE_UPDATES_SUCCEEDED,  // 55. Autoupdates are now enabled.
+  REENABLE_UPDATES_FAILED,     // 56. Autoupdates could not be enabled.
+
   // Friendly reminder: note the COMPILE_ASSERT below.
 };
 
 
 // Existing InstallStatus values must not change.  Always add to the end.
-COMPILE_ASSERT(installer::CPU_NOT_SUPPORTED == 54,
+COMPILE_ASSERT(installer::REENABLE_UPDATES_FAILED == 56,
                dont_change_enum);
 
 // The type of an update archive.
@@ -167,6 +170,7 @@
 extern const char kNewSetupExe[];
 extern const char kOnOsUpgrade[];
 extern const char kQueryEULAAcceptance[];
+extern const char kReenableAutoupdates[];
 extern const char kRegisterChromeBrowser[];
 extern const char kRegisterChromeBrowserSuffix[];
 extern const char kRegisterDevChrome[];
diff --git a/chrome/plugin/chrome_content_plugin_client.cc b/chrome/plugin/chrome_content_plugin_client.cc
index 4e1dee7..1abe0a3 100644
--- a/chrome/plugin/chrome_content_plugin_client.cc
+++ b/chrome/plugin/chrome_content_plugin_client.cc
@@ -30,9 +30,9 @@
   crypto::EnsureNSSInit();
 #elif defined(OS_WIN)
   // crypt32.dll is used to decode X509 certificates for Chromoting.
-  std::string error;
+  base::NativeLibraryLoadError error;
   if (base::LoadNativeLibrary(base::FilePath(L"crypt32.dll"), &error) == NULL)
-    LOG(ERROR) << "Failed to load crypto32.dll: " << error;
+    LOG(ERROR) << "Failed to load crypto32.dll: " << error.ToString();
 #endif // defined(OS_WIN)
 
   // Load media libraries for the Chromoting client plugin.
diff --git a/chrome/renderer/DEPS b/chrome/renderer/DEPS
index bf9a831..729cb68 100644
--- a/chrome/renderer/DEPS
+++ b/chrome/renderer/DEPS
@@ -21,5 +21,6 @@
   "+webkit/glue",
   "+webkit/renderer",
 
+  "+third_party/cld_2",
   "+third_party/sqlite",
 ]
diff --git a/chrome/renderer/autofill/autofill_renderer_browsertest.cc b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
index ba2d19b..85c2c66 100644
--- a/chrome/renderer/autofill/autofill_renderer_browsertest.cc
+++ b/chrome/renderer/autofill/autofill_renderer_browsertest.cc
@@ -148,7 +148,7 @@
   // Simulate attempting to Autofill the form from the first element, which
   // specifies autocomplete="off".  This should still trigger an IPC which
   // shouldn't display warnings.
-  autofill_agent_->InputElementClicked(firstname, true, true);
+  autofill_agent_->FormControlElementClicked(firstname, true);
   const IPC::Message* message1 = render_thread_->sink().GetFirstMessageMatching(
       AutofillHostMsg_QueryFormFieldAutofill::ID);
   EXPECT_NE(static_cast<IPC::Message*>(NULL), message1);
@@ -162,7 +162,7 @@
   // does not specify autocomplete="off".  This should trigger an IPC that will
   // show warnings, as we *do* show warnings for elements that don't themselves
   // set autocomplete="off", but for which the form does.
-  autofill_agent_->InputElementClicked(middlename, true, true);
+  autofill_agent_->FormControlElementClicked(middlename, true);
   const IPC::Message* message2 = render_thread_->sink().GetFirstMessageMatching(
       AutofillHostMsg_QueryFormFieldAutofill::ID);
   ASSERT_NE(static_cast<IPC::Message*>(NULL), message2);
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
index 419545d..7581c36 100644
--- a/chrome/renderer/autofill/form_autofill_browsertest.cc
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -159,7 +159,7 @@
   }
 
   typedef void (*FillFormFunction)(const FormData& form,
-                                   const WebInputElement& element);
+                                   const WebFormControlElement& element);
 
   typedef WebString (*GetValueFunction)(WebFormControlElement element);
 
@@ -187,10 +187,10 @@
     FormData form_data;
     FormFieldData field;
     EXPECT_TRUE(
-        FindFormAndFieldForInputElement(input_element,
-                                        &form_data,
-                                        &field,
-                                        autofill::REQUIRE_AUTOCOMPLETE));
+        FindFormAndFieldForFormControlElement(input_element,
+                                              &form_data,
+                                              &field,
+                                              autofill::REQUIRE_AUTOCOMPLETE));
     EXPECT_EQ(ASCIIToUTF16("TestForm"), form_data.name);
     EXPECT_EQ(GURL(web_frame->document().url()), form_data.origin);
     EXPECT_EQ(GURL("http://buh.com"), form_data.action);
@@ -232,9 +232,8 @@
     WebString value;
     WebFormControlElement element = GetMainFrame()->document().getElementById(
         ASCIIToUTF16(field_case.name)).to<WebFormControlElement>();
-    if (element.formControlType() == "select-one") {
-      value = element.to<WebSelectElement>().value();
-    } else if (element.formControlType() == "textarea") {
+    if ((element.formControlType() == "select-one") ||
+        (element.formControlType() == "textarea")) {
       value = get_value_function(element);
     } else {
       ASSERT_TRUE(element.formControlType() == "text" ||
@@ -258,7 +257,7 @@
 
   static void FillFormIncludingNonFocusableElementsWrapper(
       const FormData& form,
-      const WebInputElement& element) {
+      const WebFormControlElement& element) {
     FillFormIncludingNonFocusableElements(form, element.form());
   }
 
@@ -266,6 +265,9 @@
     if (element.formControlType() == "textarea")
       return element.to<WebTextAreaElement>().value();
 
+    if (element.formControlType() == "select-one")
+      return element.to<WebSelectElement>().value();
+
     return element.to<WebInputElement>().value();
   }
 
@@ -273,6 +275,9 @@
     if (element.formControlType() == "textarea")
       return element.to<WebTextAreaElement>().suggestedValue();
 
+    if (element.formControlType() == "select-one")
+      return element.to<WebSelectElement>().suggestedValue();
+
     return element.to<WebInputElement>().suggestedValue();
   }
 
@@ -1002,7 +1007,7 @@
   }
 }
 
-TEST_F(FormAutofillTest, FindForm) {
+TEST_F(FormAutofillTest, FindFormForInputElement) {
   LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
            "  <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
            "  <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
@@ -1027,8 +1032,10 @@
   // Find the form and verify it's the correct form.
   FormData form;
   FormFieldData field;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form,
+                                                    &field,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
   EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -1062,8 +1069,11 @@
   // Try again, but require autocomplete.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form2, &field2,
-                                              autofill::REQUIRE_AUTOCOMPLETE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(
+      input_element,
+      &form2,
+      &field2,
+      autofill::REQUIRE_AUTOCOMPLETE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
   EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -1088,6 +1098,109 @@
   EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]);
 }
 
+TEST_F(FormAutofillTest, FindFormForTextAreaElement) {
+  LoadHTML("<FORM name=\"TestForm\" action=\"http://buh.com\" method=\"post\">"
+           "  <INPUT type=\"text\" id=\"firstname\" value=\"John\"/>"
+           "  <INPUT type=\"text\" id=\"lastname\" value=\"Smith\"/>"
+           "  <INPUT type=\"text\" id=\"email\" value=\"john@example.com\""
+                     "autocomplete=\"off\" />"
+           "  <TEXTAREA id=\"street-address\">"
+               "123 Fantasy Ln.&#10;"
+               "Apt. 42"
+             "</TEXTAREA>"
+           "  <INPUT type=\"submit\" name=\"reply-send\" value=\"Send\"/>"
+           "</FORM>");
+
+  WebFrame* web_frame = GetMainFrame();
+  ASSERT_NE(static_cast<WebFrame*>(NULL), web_frame);
+
+  FormCache form_cache;
+  std::vector<FormData> forms;
+  form_cache.ExtractForms(*web_frame, &forms);
+  ASSERT_EQ(1U, forms.size());
+
+  // Get the textarea element we want to find.
+  WebElement element = web_frame->document().getElementById("street-address");
+  WebTextAreaElement textarea_element = element.to<WebTextAreaElement>();
+
+  // Find the form and verify it's the correct form.
+  FormData form;
+  FormFieldData field;
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(textarea_element,
+                                                    &form,
+                                                    &field,
+                                                    autofill::REQUIRE_NONE));
+  EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
+  EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
+  EXPECT_EQ(GURL("http://buh.com"), form.action);
+
+  const std::vector<FormFieldData>& fields = form.fields;
+  ASSERT_EQ(4U, fields.size());
+
+  FormFieldData expected;
+
+  expected.name = ASCIIToUTF16("firstname");
+  expected.value = ASCIIToUTF16("John");
+  expected.form_control_type = "text";
+  expected.max_length = WebInputElement::defaultMaxLength();
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[0]);
+
+  expected.name = ASCIIToUTF16("lastname");
+  expected.value = ASCIIToUTF16("Smith");
+  expected.form_control_type = "text";
+  expected.max_length = WebInputElement::defaultMaxLength();
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[1]);
+
+  expected.name = ASCIIToUTF16("email");
+  expected.value = ASCIIToUTF16("john@example.com");
+  expected.autocomplete_attribute = "off";
+  expected.form_control_type = "text";
+  expected.max_length = WebInputElement::defaultMaxLength();
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[2]);
+  expected.autocomplete_attribute = std::string();  // reset
+
+  expected.name = ASCIIToUTF16("street-address");
+  expected.value = ASCIIToUTF16("123 Fantasy Ln.\nApt. 42");
+  expected.form_control_type = "textarea";
+  expected.max_length = 0;
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields[3]);
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, field);
+
+  // Try again, but require autocomplete.
+  FormData form2;
+  FormFieldData field2;
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(
+      textarea_element,
+      &form2,
+      &field2,
+      autofill::REQUIRE_AUTOCOMPLETE));
+  EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
+  EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
+  EXPECT_EQ(GURL("http://buh.com"), form2.action);
+
+  const std::vector<FormFieldData>& fields2 = form2.fields;
+  ASSERT_EQ(3U, fields2.size());
+
+  expected.name = ASCIIToUTF16("firstname");
+  expected.value = ASCIIToUTF16("John");
+  expected.form_control_type = "text";
+  expected.max_length = WebInputElement::defaultMaxLength();
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[0]);
+
+  expected.name = ASCIIToUTF16("lastname");
+  expected.value = ASCIIToUTF16("Smith");
+  expected.form_control_type = "text";
+  expected.max_length = WebInputElement::defaultMaxLength();
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[1]);
+
+  expected.name = ASCIIToUTF16("street-address");
+  expected.value = ASCIIToUTF16("123 Fantasy Ln.\nApt. 42");
+  expected.form_control_type = "textarea";
+  expected.max_length = 0;
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, fields2[2]);
+  EXPECT_FORM_FIELD_DATA_EQUALS(expected, field);
+}
+
 // Test regular FillForm function.
 TEST_F(FormAutofillTest, FillForm) {
   static const AutofillFieldCase field_cases[] = {
@@ -1205,10 +1318,11 @@
       {"month", "month", "", "", true, "2017-11", "2017-11"},
       // Non-empty <input type="month"> should not be previewed.
       {"month", "month-nonempty", "2011-12", "", false, "2017-11", ""},
-      // Regular select fields preview is not yet supported
-      {"select-one", "select", "", "", false, "TX", ""},
-      // Select fields preview is not yet supported
-      {"select-one", "select-nonempty", "CA", "", false, "TX", "CA"},
+      // Regular select fields should be previewed.
+      {"select-one", "select", "", "", true, "TX", "TX"},
+      // Select fields should be previewed even if they already have a
+      // non-empty value.
+      {"select-one", "select-nonempty", "CA", "", true, "TX", "TX"},
       // Normal textarea elements should be previewed.
       {"textarea", "textarea", "", "", true, "suggested multi-\nline value",
        "suggested multi-\nline value"},
@@ -2109,8 +2223,10 @@
   // Find the form that contains the input element.
   FormData form;
   FormFieldData field;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form,
+                                                    &field,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
   EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -2145,8 +2261,10 @@
   // Find the newly-filled form that contains the input element.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form2, &field2,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form2,
+                                                    &field2,
+                                                    autofill::REQUIRE_NONE));
 
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
@@ -2202,8 +2320,10 @@
   // Find the form that contains the input element.
   FormData form;
   FormFieldData field;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form,
+                                                    &field,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
   EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -2233,8 +2353,10 @@
   // Find the newly-filled form that contains the input element.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form2, &field2,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form2,
+                                                    &field2,
+                                                    autofill::REQUIRE_NONE));
 
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
@@ -2279,8 +2401,10 @@
   // Find the form that contains the input element.
   FormData form;
   FormFieldData field;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form,
+                                                    &field,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
   EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -2310,8 +2434,10 @@
   // Find the newly-filled form that contains the input element.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form2, &field2,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form2,
+                                                    &field2,
+                                                    autofill::REQUIRE_NONE));
 
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
@@ -2365,8 +2491,10 @@
   // Find the form that contains the input element.
   FormData form;
   FormFieldData field;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form,
+                                                    &field,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(base::string16(), form.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
   EXPECT_EQ(GURL("http://abc.com"), form.action);
@@ -2399,8 +2527,10 @@
   // Find the newly-filled form that contains the input element.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form2, &field2,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form2,
+                                                    &field2,
+                                                    autofill::REQUIRE_NONE));
 
   EXPECT_EQ(base::string16(), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
@@ -2584,8 +2714,10 @@
   // Find the form that contains the input element.
   FormData form;
   FormFieldData field;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form, &field,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form,
+                                                    &field,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form.origin);
   EXPECT_EQ(GURL("http://buh.com"), form.action);
@@ -2626,8 +2758,10 @@
   // Find the newly-filled form that contains the input element.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(input_element, &form2, &field2,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(input_element,
+                                                    &form2,
+                                                    &field2,
+                                                    autofill::REQUIRE_NONE));
 
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
@@ -2701,8 +2835,10 @@
   // Verify the form is cleared.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(firstname, &form2, &field2,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(firstname,
+                                                    &form2,
+                                                    &field2,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
   EXPECT_EQ(GURL("http://buh.com"), form2.action);
@@ -2803,8 +2939,10 @@
   // Verify the form is cleared.
   FormData form2;
   FormFieldData field2;
-  EXPECT_TRUE(FindFormAndFieldForInputElement(firstname, &form2, &field2,
-                                              autofill::REQUIRE_NONE));
+  EXPECT_TRUE(FindFormAndFieldForFormControlElement(firstname,
+                                                    &form2,
+                                                    &field2,
+                                                    autofill::REQUIRE_NONE));
   EXPECT_EQ(ASCIIToUTF16("TestForm"), form2.name);
   EXPECT_EQ(GURL(web_frame->document().url()), form2.origin);
   EXPECT_EQ(GURL("http://buh.com"), form2.action);
diff --git a/chrome/renderer/autofill/page_click_tracker_browsertest.cc b/chrome/renderer/autofill/page_click_tracker_browsertest.cc
index b549615..4c5c818 100644
--- a/chrome/renderer/autofill/page_click_tracker_browsertest.cc
+++ b/chrome/renderer/autofill/page_click_tracker_browsertest.cc
@@ -10,6 +10,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebInputElement.h"
+#include "third_party/WebKit/public/web/WebTextAreaElement.h"
 #include "third_party/WebKit/public/web/WebView.h"
 #include "third_party/WebKit/public/platform/WebSize.h"
 #include "ui/events/keycodes/keyboard_codes.h"
@@ -19,38 +20,34 @@
 class TestPageClickListener : public PageClickListener {
  public:
   TestPageClickListener()
-      : input_element_clicked_called_(false),
-        input_element_lost_focus_called_(false),
-        was_focused_(false),
-        is_focused_(false) {
+      : form_control_element_clicked_called_(false),
+        form_control_element_lost_focus_called_(false),
+        was_focused_(false) {
   }
 
-  virtual void InputElementClicked(const blink::WebInputElement& element,
-                                   bool was_focused,
-                                   bool is_focused) OVERRIDE {
-    input_element_clicked_called_ = true;
-    element_clicked_ = element;
+  virtual void FormControlElementClicked(
+      const blink::WebFormControlElement& element,
+      bool was_focused)  OVERRIDE {
+    form_control_element_clicked_called_ = true;
+    form_control_element_clicked_ = element;
     was_focused_ = was_focused;
-    is_focused_ = is_focused;
   }
 
-  virtual void InputElementLostFocus() OVERRIDE {
-    input_element_lost_focus_called_ = true;
+  virtual void FormControlElementLostFocus() OVERRIDE {
+    form_control_element_lost_focus_called_ = true;
   }
 
   void ClearResults() {
-    input_element_clicked_called_ = false;
-    input_element_lost_focus_called_ = false;
-    element_clicked_.reset();
+    form_control_element_clicked_called_ = false;
+    form_control_element_lost_focus_called_ = false;
+    form_control_element_clicked_.reset();
     was_focused_ = false;
-    is_focused_ = false;
   }
 
-  bool input_element_clicked_called_;
-  bool input_element_lost_focus_called_;
-  blink::WebInputElement element_clicked_;
+  bool form_control_element_clicked_called_;
+  bool form_control_element_lost_focus_called_;
+  blink::WebFormControlElement form_control_element_clicked_;
   bool was_focused_;
-  bool is_focused_;
 };
 
 class PageClickTrackerTest : public content::RenderViewTest {
@@ -65,17 +62,22 @@
     LoadHTML("<form>"
              "  <input type='text' id='text_1'></input><br>"
              "  <input type='text' id='text_2'></input><br>"
+             "  <textarea  id='textarea_1'></textarea><br>"
+             "  <textarea  id='textarea_2'></textarea><br>"
              "  <input type='button' id='button'></input><br>"
              "</form>");
     GetWebWidget()->resize(blink::WebSize(500, 500));
     GetWebWidget()->setFocus(true);
     blink::WebDocument document = view_->GetWebView()->mainFrame()->document();
     text_ = document.getElementById("text_1");
+    textarea_ = document.getElementById("textarea_1");
     ASSERT_FALSE(text_.isNull());
+    ASSERT_FALSE(textarea_.isNull());
   }
 
   virtual void TearDown() OVERRIDE {
     text_.reset();
+    textarea_.reset();
     test_listener_.ClearResults();
     page_click_tracker_.reset();
     content::RenderViewTest::TearDown();
@@ -100,29 +102,51 @@
   scoped_ptr<PageClickTracker> page_click_tracker_;
   TestPageClickListener test_listener_;
   blink::WebElement text_;
+  blink::WebElement textarea_;
 };
 
-// Tests that PageClickTracker does notify correctly when a node is clicked.
+// Tests that PageClickTracker does notify correctly when an input
+// node is clicked.
 TEST_F(PageClickTrackerTest, PageClickTrackerInputClicked) {
   // Click the text field once.
   EXPECT_TRUE(SimulateElementClick("text_1"));
-  EXPECT_TRUE(test_listener_.input_element_clicked_called_);
+  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
   EXPECT_FALSE(test_listener_.was_focused_);
-  EXPECT_TRUE(test_listener_.is_focused_);
-  EXPECT_TRUE(text_ == test_listener_.element_clicked_);
+  EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_);
   test_listener_.ClearResults();
 
   // Click the text field again to test that was_focused_ is set correctly.
   EXPECT_TRUE(SimulateElementClick("text_1"));
-  EXPECT_TRUE(test_listener_.input_element_clicked_called_);
+  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
   EXPECT_TRUE(test_listener_.was_focused_);
-  EXPECT_TRUE(test_listener_.is_focused_);
-  EXPECT_TRUE(text_ == test_listener_.element_clicked_);
+  EXPECT_TRUE(text_ == test_listener_.form_control_element_clicked_);
   test_listener_.ClearResults();
 
   // Click the button, no notification should happen (this is not a text-input).
   EXPECT_TRUE(SimulateElementClick("button"));
-  EXPECT_FALSE(test_listener_.input_element_clicked_called_);
+  EXPECT_FALSE(test_listener_.form_control_element_clicked_called_);
+}
+
+// Tests that PageClickTracker does notify correctly when a textarea
+// node is clicked.
+TEST_F(PageClickTrackerTest, PageClickTrackerTextAreaClicked) {
+  // Click the textarea field once.
+  EXPECT_TRUE(SimulateElementClick("textarea_1"));
+  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
+  EXPECT_FALSE(test_listener_.was_focused_);
+  EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_);
+  test_listener_.ClearResults();
+
+  // Click the textarea field again to test that was_focused_ is set correctly.
+  EXPECT_TRUE(SimulateElementClick("textarea_1"));
+  EXPECT_TRUE(test_listener_.form_control_element_clicked_called_);
+  EXPECT_TRUE(test_listener_.was_focused_);
+  EXPECT_TRUE(textarea_ == test_listener_.form_control_element_clicked_);
+  test_listener_.ClearResults();
+
+  // Click the button, no notification should happen (this is not a text-input).
+  EXPECT_TRUE(SimulateElementClick("button"));
+  EXPECT_FALSE(test_listener_.form_control_element_clicked_called_);
 }
 
 TEST_F(PageClickTrackerTest, PageClickTrackerInputFocusLost) {
@@ -130,35 +154,73 @@
   EXPECT_NE(text_, text_.document().focusedElement());
   SendKeyPress(ui::VKEY_TAB);
   EXPECT_EQ(text_, text_.document().focusedElement());
-  EXPECT_FALSE(test_listener_.input_element_lost_focus_called_);
+  EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_);
 
   // Click a button and ensure that the lost focus notification was sent,
   // even though focus was gained without the mouse.
   EXPECT_TRUE(SimulateElementClick("button"));
-  EXPECT_TRUE(test_listener_.input_element_lost_focus_called_);
+  EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_);
   test_listener_.ClearResults();
 
   // Click a text field and test that no lost focus notifications are sent.
   EXPECT_TRUE(SimulateElementClick("text_1"));
-  EXPECT_FALSE(test_listener_.input_element_lost_focus_called_);
+  EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_);
   test_listener_.ClearResults();
 
   // Select another text field to test that the notifcation for the
   // first text field losing focus is sent.
   EXPECT_TRUE(SimulateElementClick("text_2"));
-  EXPECT_TRUE(test_listener_.input_element_lost_focus_called_);
+  EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_);
   test_listener_.ClearResults();
 
   // Click the button, a notification should happen since a text field has
   // lost focus.
   EXPECT_TRUE(SimulateElementClick("button"));
-  EXPECT_TRUE(test_listener_.input_element_lost_focus_called_);
+  EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_);
   test_listener_.ClearResults();
 
   // Click on a text field while the button has focus and ensure no lost focus
   // notification is sent.
   EXPECT_TRUE(SimulateElementClick("text_1"));
-  EXPECT_FALSE(test_listener_.input_element_lost_focus_called_);
+  EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_);
+}
+
+TEST_F(PageClickTrackerTest, PageClickTrackerTextAreaFocusLost) {
+  // Gain focus on the textare field by using tab.
+  EXPECT_NE(textarea_, textarea_.document().focusedElement());
+  SendKeyPress(ui::VKEY_TAB);
+  SendKeyPress(ui::VKEY_TAB);
+  SendKeyPress(ui::VKEY_TAB);
+  EXPECT_EQ(textarea_, textarea_.document().focusedElement());
+  EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_);
+
+  // Click a button and ensure that the lost focus notification was sent,
+  // even though focus was gained without the mouse.
+  EXPECT_TRUE(SimulateElementClick("button"));
+  EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_);
+  test_listener_.ClearResults();
+
+  // Click a textarea field and test that no lost focus notifications are sent.
+  EXPECT_TRUE(SimulateElementClick("textarea_1"));
+  EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_);
+  test_listener_.ClearResults();
+
+  // Select another textarea field to test that the notifcation for the
+  // first textarea field losing focus is sent.
+  EXPECT_TRUE(SimulateElementClick("textarea_2"));
+  EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_);
+  test_listener_.ClearResults();
+
+  // Click the button, a notification should happen since a textarea field has
+  // lost focus.
+  EXPECT_TRUE(SimulateElementClick("button"));
+  EXPECT_TRUE(test_listener_.form_control_element_lost_focus_called_);
+  test_listener_.ClearResults();
+
+  // Click on a textarea field while the button has focus and ensure no lost
+  // focus notification is sent.
+  EXPECT_TRUE(SimulateElementClick("textarea_1"));
+  EXPECT_FALSE(test_listener_.form_control_element_lost_focus_called_);
 }
 
 }  // namespace autofill
diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc
index e4f6d4b..450f1cd 100644
--- a/chrome/renderer/chrome_render_process_observer.cc
+++ b/chrome/renderer/chrome_render_process_observer.cc
@@ -294,8 +294,7 @@
 #elif defined(OS_WIN)
   // crypt32.dll is used to decode X509 certificates for Chromoting.
   // Only load this library when the feature is enabled.
-  std::string error;
-  base::LoadNativeLibrary(base::FilePath(L"crypt32.dll"), &error);
+  base::LoadNativeLibrary(base::FilePath(L"crypt32.dll"), NULL);
 #endif
   // Setup initial set of crash dump data for Field Trials in this renderer.
   chrome_variations::SetChildProcessLoggingVariationList();
diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc
index af98718..8a39f35 100644
--- a/chrome/renderer/chrome_render_view_observer.cc
+++ b/chrome/renderer/chrome_render_view_observer.cc
@@ -255,15 +255,8 @@
 }
 
 void ChromeRenderViewObserver::OnWebUIJavaScript(
-    const base::string16& frame_xpath,
-    const base::string16& jscript,
-    int id,
-    bool notify_result) {
-  webui_javascript_.reset(new WebUIJavaScript());
-  webui_javascript_->frame_xpath = frame_xpath;
-  webui_javascript_->jscript = jscript;
-  webui_javascript_->id = id;
-  webui_javascript_->notify_result = notify_result;
+    const base::string16& javascript) {
+  webui_javascript_ = javascript;
 }
 
 void ChromeRenderViewObserver::OnJavaScriptStressTestControl(int cmd,
@@ -360,6 +353,9 @@
   // event (including tab reload).
   if (chrome_render_process_observer_)
     chrome_render_process_observer_->ExecutePendingClearCache();
+  // Let translate_helper do any preparatory work for loading a URL.
+  if (translate_helper_)
+    translate_helper_->PrepareForUrl(url);
 }
 
 void ChromeRenderViewObserver::OnSetClientSidePhishingDetection(
@@ -395,12 +391,9 @@
 
 void ChromeRenderViewObserver::DidStartLoading() {
   if ((render_view()->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) &&
-      webui_javascript_.get()) {
-    render_view()->EvaluateScript(webui_javascript_->frame_xpath,
-                                  webui_javascript_->jscript,
-                                  webui_javascript_->id,
-                                  webui_javascript_->notify_result);
-    webui_javascript_.reset();
+      !webui_javascript_.empty()) {
+    render_view()->GetMainRenderFrame()->ExecuteJavaScript(webui_javascript_);
+    webui_javascript_.clear();
   }
 }
 
diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h
index 117a3cb..5462cf5 100644
--- a/chrome/renderer/chrome_render_view_observer.h
+++ b/chrome/renderer/chrome_render_view_observer.h
@@ -45,15 +45,6 @@
   virtual ~ChromeRenderViewObserver();
 
  private:
-  // Holds the information received in OnWebUIJavaScript for later use
-  // to call EvaluateScript() to preload javascript for WebUI tests.
-  struct WebUIJavaScript {
-    base::string16 frame_xpath;
-    base::string16 jscript;
-    int id;
-    bool notify_result;
-  };
-
   // RenderViewObserver implementation.
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
   virtual void DidStartLoading() OVERRIDE;
@@ -67,10 +58,7 @@
                                            int32 severity_level) OVERRIDE;
   virtual void Navigate(const GURL& url) OVERRIDE;
 
-  void OnWebUIJavaScript(const base::string16& frame_xpath,
-                         const base::string16& jscript,
-                         int id,
-                         bool notify_result);
+  void OnWebUIJavaScript(const base::string16& javascript);
   void OnJavaScriptStressTestControl(int cmd, int param);
   void OnSetClientSidePhishingDetection(bool enable_phishing_detection);
   void OnSetVisuallyDeemphasized(bool deemphasized);
@@ -104,7 +92,7 @@
   bool HasRefreshMetaTag(blink::WebFrame* frame);
 
   // Save the JavaScript to preload if a ViewMsg_WebUIJavaScript is received.
-  scoped_ptr<WebUIJavaScript> webui_javascript_;
+  base::string16 webui_javascript_;
 
   // Owned by ChromeContentRendererClient and outlive us.
   ChromeRenderProcessObserver* chrome_render_process_observer_;
diff --git a/chrome/renderer/extensions/dispatcher.cc b/chrome/renderer/extensions/dispatcher.cc
index 8fb700f..8d83596 100644
--- a/chrome/renderer/extensions/dispatcher.cc
+++ b/chrome/renderer/extensions/dispatcher.cc
@@ -18,7 +18,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/crash_keys.h"
-#include "chrome/common/extensions/api/messaging/message.h"
 #include "chrome/common/extensions/features/feature_channel.h"
 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
 #include "chrome/common/extensions/message_bundle.h"
@@ -70,6 +69,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/v8_value_converter.h"
+#include "extensions/common/api/messaging/message.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_api.h"
diff --git a/chrome/renderer/extensions/extension_helper.cc b/chrome/renderer/extensions/extension_helper.cc
index 6d9cf1f..ccaf8cf 100644
--- a/chrome/renderer/extensions/extension_helper.cc
+++ b/chrome/renderer/extensions/extension_helper.cc
@@ -12,7 +12,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/api/messaging/message.h"
 #include "chrome/common/extensions/chrome_extension_messages.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/common/render_messages.h"
@@ -26,6 +25,7 @@
 #include "chrome/renderer/web_apps.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/render_view_visitor.h"
+#include "extensions/common/api/messaging/message.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_messages.h"
 #include "third_party/WebKit/public/platform/WebURLRequest.h"
diff --git a/chrome/renderer/extensions/media_galleries_custom_bindings.cc b/chrome/renderer/extensions/media_galleries_custom_bindings.cc
index 1b4a0e1..78a4e27 100644
--- a/chrome/renderer/extensions/media_galleries_custom_bindings.cc
+++ b/chrome/renderer/extensions/media_galleries_custom_bindings.cc
@@ -23,21 +23,22 @@
   CHECK_EQ(1, args.Length());
   CHECK(args[0]->IsString());
 
-  std::string fsid(*v8::String::Utf8Value(args[0]));
-  CHECK(!fsid.empty());
+  std::string fs_mount(*v8::String::Utf8Value(args[0]));
+  CHECK(!fs_mount.empty());
 
   blink::WebFrame* webframe = blink::WebFrame::frameForCurrentContext();
   const GURL origin = GURL(webframe->document().securityOrigin().toString());
-  const std::string fs_name = fileapi::GetIsolatedFileSystemName(origin, fsid);
+  std::string fs_name =
+      fileapi::GetFileSystemName(origin, fileapi::kFileSystemTypeExternal);
+  fs_name.append("_");
+  fs_name.append(fs_mount);
   const GURL root_url(
-      fileapi::GetIsolatedFileSystemRootURIString(
-          origin, fsid, extension_misc::kMediaFileSystemPathPart));
+      fileapi::GetExternalFileSystemRootURIString(origin, fs_mount));
   args.GetReturnValue().Set(
-      blink::WebDOMFileSystem::create(
-          webframe,
-          blink::WebFileSystemTypeIsolated,
-          blink::WebString::fromUTF8(fs_name),
-          root_url).toV8Value());
+      blink::WebDOMFileSystem::create(webframe,
+                                      blink::WebFileSystemTypeExternal,
+                                      blink::WebString::fromUTF8(fs_name),
+                                      root_url).toV8Value());
 }
 
 }  // namespace
diff --git a/chrome/renderer/extensions/messaging_bindings.cc b/chrome/renderer/extensions/messaging_bindings.cc
index c7524ae..af0422b 100644
--- a/chrome/renderer/extensions/messaging_bindings.cc
+++ b/chrome/renderer/extensions/messaging_bindings.cc
@@ -13,7 +13,6 @@
 #include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
 #include "base/values.h"
-#include "chrome/common/extensions/api/messaging/message.h"
 #include "chrome/common/extensions/manifest_handlers/externally_connectable.h"
 #include "chrome/common/extensions/message_bundle.h"
 #include "chrome/common/url_constants.h"
@@ -26,6 +25,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/v8_value_converter.h"
+#include "extensions/common/api/messaging/message.h"
 #include "extensions/common/extension_messages.h"
 #include "grit/renderer_resources.h"
 #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h"
diff --git a/chrome/renderer/extensions/renderer_permissions_policy_delegate.cc b/chrome/renderer/extensions/renderer_permissions_policy_delegate.cc
index 73a1c73..2774064 100644
--- a/chrome/renderer/extensions/renderer_permissions_policy_delegate.cc
+++ b/chrome/renderer/extensions/renderer_permissions_policy_delegate.cc
@@ -46,8 +46,7 @@
     return false;
   }
 
-  if (dispatcher_->IsExtensionActive(extension_misc::kWebStoreAppId) &&
-      !command_line->HasSwitch(switches::kAllowScriptingGallery)) {
+  if (dispatcher_->IsExtensionActive(extension_misc::kWebStoreAppId)) {
     if (error)
       *error = errors::kCannotScriptGallery;
     return false;
diff --git a/chrome/renderer/extensions/webstore_bindings.cc b/chrome/renderer/extensions/webstore_bindings.cc
index 21f3b22..08e9d9a 100644
--- a/chrome/renderer/extensions/webstore_bindings.cc
+++ b/chrome/renderer/extensions/webstore_bindings.cc
@@ -5,11 +5,12 @@
 #include "chrome/renderer/extensions/webstore_bindings.h"
 
 #include "base/strings/string_util.h"
+#include "chrome/common/extensions/api/webstore/webstore_api_constants.h"
+#include "chrome/common/extensions/chrome_extension_messages.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "chrome/renderer/extensions/chrome_v8_context.h"
 #include "content/public/renderer/render_view.h"
 #include "extensions/common/extension.h"
-#include "extensions/common/extension_messages.h"
 #include "grit/renderer_resources.h"
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebElement.h"
@@ -32,12 +33,6 @@
 
 const char kWebstoreLinkRelation[] = "chrome-webstore-item";
 
-const char kPreferredStoreLinkUrlNotAString[] =
-    "The Chrome Web Store item link URL parameter must be a string.";
-const char kSuccessCallbackNotAFunctionError[] =
-    "The success callback parameter must be a function.";
-const char kFailureCallbackNotAFunctionError[] =
-    "The failure callback parameter must be a function.";
 const char kNotInTopFrameError[] =
     "Chrome Web Store installations can only be started by the top frame.";
 const char kNotUserGestureError[] =
@@ -64,28 +59,30 @@
 
 void WebstoreBindings::Install(
     const v8::FunctionCallbackInfo<v8::Value>& args) {
-  WebFrame* frame = WebFrame::frameForContext(context()->v8_context());
-  if (!frame || !frame->view())
-    return;
-
-  content::RenderView* render_view =
-      content::RenderView::FromWebView(frame->view());
+  content::RenderView* render_view = GetRenderView();
   if (!render_view)
     return;
 
+  // The first two arguments indicate whether or not there are install stage
+  // or download progress listeners.
+  int listener_mask = 0;
+  CHECK(args[0]->IsBoolean());
+  if (args[0]->BooleanValue())
+    listener_mask |= api::webstore::INSTALL_STAGE_LISTENER;
+  CHECK(args[1]->IsBoolean());
+  if (args[1]->BooleanValue())
+    listener_mask |= api::webstore::DOWNLOAD_PROGRESS_LISTENER;
+
   std::string preferred_store_link_url;
-  if (!args[0]->IsUndefined()) {
-    if (args[0]->IsString()) {
-      preferred_store_link_url = std::string(*v8::String::Utf8Value(args[0]));
-    } else {
-      args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
-          args.GetIsolate(), kPreferredStoreLinkUrlNotAString));
-      return;
-    }
+  if (!args[2]->IsUndefined()) {
+    CHECK(args[2]->IsString());
+    preferred_store_link_url = std::string(*v8::String::Utf8Value(args[2]));
   }
 
   std::string webstore_item_id;
   std::string error;
+  WebFrame* frame = context()->web_frame();
+
   if (!GetWebstoreItemIdFromFrame(
       frame, preferred_store_link_url, &webstore_item_id, &error)) {
     args.GetIsolate()->ThrowException(
@@ -94,24 +91,13 @@
   }
 
   int install_id = g_next_install_id++;
-  if (!args[1]->IsUndefined() && !args[1]->IsFunction()) {
-    args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
-        args.GetIsolate(), kSuccessCallbackNotAFunctionError));
-    return;
-  }
 
-  if (!args[2]->IsUndefined() && !args[2]->IsFunction()) {
-    args.GetIsolate()->ThrowException(v8::String::NewFromUtf8(
-        args.GetIsolate(), kFailureCallbackNotAFunctionError));
-    return;
-  }
-
-  Send(new ExtensionHostMsg_InlineWebstoreInstall(
-      render_view->GetRoutingID(),
-      install_id,
-      GetRoutingID(),
-      webstore_item_id,
-      frame->document().url()));
+  Send(new ExtensionHostMsg_InlineWebstoreInstall(render_view->GetRoutingID(),
+                                                  install_id,
+                                                  GetRoutingID(),
+                                                  webstore_item_id,
+                                                  frame->document().url(),
+                                                  listener_mask));
 
   args.GetReturnValue().Set(static_cast<int32_t>(install_id));
 }
@@ -207,6 +193,10 @@
   IPC_BEGIN_MESSAGE_MAP(WebstoreBindings, message)
     IPC_MESSAGE_HANDLER(ExtensionMsg_InlineWebstoreInstallResponse,
                         OnInlineWebstoreInstallResponse)
+    IPC_MESSAGE_HANDLER(ExtensionMsg_InlineInstallStageChanged,
+                        OnInlineInstallStageChanged)
+    IPC_MESSAGE_HANDLER(ExtensionMsg_InlineInstallDownloadProgress,
+                        OnInlineInstallDownloadProgress)
     IPC_MESSAGE_UNHANDLED(CHECK(false) << "Unhandled IPC message")
   IPC_END_MESSAGE_MAP()
   return true;
@@ -228,4 +218,35 @@
       "webstore", "onInstallResponse", arraysize(argv), argv);
 }
 
+void WebstoreBindings::OnInlineInstallStageChanged(int stage) {
+  const char* stage_string = NULL;
+  api::webstore::InstallStage install_stage =
+      static_cast<api::webstore::InstallStage>(stage);
+  switch (install_stage) {
+    case api::webstore::INSTALL_STAGE_DOWNLOADING:
+      stage_string = api::webstore::kInstallStageDownloading;
+      break;
+    case api::webstore::INSTALL_STAGE_INSTALLING:
+      stage_string = api::webstore::kInstallStageInstalling;
+      break;
+  }
+  v8::Isolate* isolate = context()->isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Context::Scope context_scope(context()->v8_context());
+  v8::Handle<v8::Value> argv[] = {
+      v8::String::NewFromUtf8(isolate, stage_string)};
+  context()->module_system()->CallModuleMethod(
+      "webstore", "onInstallStageChanged", arraysize(argv), argv);
+}
+
+void WebstoreBindings::OnInlineInstallDownloadProgress(int percent_downloaded) {
+  v8::Isolate* isolate = context()->isolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Context::Scope context_scope(context()->v8_context());
+  v8::Handle<v8::Value> argv[] = {
+      v8::Number::New(isolate, percent_downloaded / 100.0)};
+  context()->module_system()->CallModuleMethod(
+      "webstore", "onDownloadProgress", arraysize(argv), argv);
+}
+
 }  // namespace extensions
diff --git a/chrome/renderer/extensions/webstore_bindings.h b/chrome/renderer/extensions/webstore_bindings.h
index b729150..5df521a 100644
--- a/chrome/renderer/extensions/webstore_bindings.h
+++ b/chrome/renderer/extensions/webstore_bindings.h
@@ -30,6 +30,10 @@
   void OnInlineWebstoreInstallResponse(
       int install_id, bool success, const std::string& error);
 
+  void OnInlineInstallStageChanged(int stage);
+
+  void OnInlineInstallDownloadProgress(int percent_downloaded);
+
   // Extracts a Web Store item ID from a <link rel="chrome-webstore-item"
   // href="https://chrome.google.com/webstore/detail/id"> node found in the
   // frame. On success, true will be returned and the |webstore_item_id|
diff --git a/chrome/renderer/media/cast_rtp_stream.cc b/chrome/renderer/media/cast_rtp_stream.cc
index de71a43..68c99c4 100644
--- a/chrome/renderer/media/cast_rtp_stream.cc
+++ b/chrome/renderer/media/cast_rtp_stream.cc
@@ -18,11 +18,13 @@
 #include "media/base/audio_fifo.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/multi_channel_resampler.h"
+#include "media/base/video_frame.h"
 #include "media/cast/cast_config.h"
 #include "media/cast/cast_defines.h"
 #include "media/cast/cast_sender.h"
 #include "media/cast/transport/cast_transport_config.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "ui/gfx/geometry/size.h"
 
 using media::cast::AudioSenderConfig;
 using media::cast::VideoSenderConfig;
@@ -32,6 +34,9 @@
 const char kCodecNameOpus[] = "OPUS";
 const char kCodecNameVp8[] = "VP8";
 
+// To convert from kilobits per second to bits to per second.
+const int kBitrateMultiplier = 1000;
+
 // This constant defines the number of sets of audio data to buffer
 // in the FIFO. If input audio and output data have different resampling
 // rates then buffer is necessary to avoid audio glitches.
@@ -47,6 +52,7 @@
   payload.codec_name = kCodecNameOpus;
   payload.clock_rate = 48000;
   payload.channels = 2;
+  // The value is 0 which means VBR.
   payload.min_bitrate = payload.max_bitrate =
       media::cast::kDefaultAudioEncoderBitrate;
   return payload;
@@ -61,8 +67,8 @@
   payload.clock_rate = 90000;
   payload.width = 1280;
   payload.height = 720;
-  payload.min_bitrate = 50 * 1000;
-  payload.max_bitrate = 2000 * 1000;
+  payload.min_bitrate = 50;
+  payload.max_bitrate = 2000;
   return payload;
 }
 
@@ -88,7 +94,7 @@
   config->use_external_encoder = false;
   config->frequency = params.payload.clock_rate;
   config->channels = params.payload.channels;
-  config->bitrate = params.payload.max_bitrate;
+  config->bitrate = params.payload.max_bitrate * kBitrateMultiplier;
   config->codec = media::cast::transport::kPcm16;
   if (params.payload.codec_name == kCodecNameOpus)
     config->codec = media::cast::transport::kOpus;
@@ -105,8 +111,9 @@
   config->use_external_encoder = false;
   config->width = params.payload.width;
   config->height = params.payload.height;
-  config->min_bitrate = config->start_bitrate = params.payload.min_bitrate;
-  config->max_bitrate = params.payload.max_bitrate;
+  config->min_bitrate = config->start_bitrate =
+      params.payload.min_bitrate * kBitrateMultiplier;
+  config->max_bitrate = params.payload.max_bitrate * kBitrateMultiplier;
   if (params.payload.codec_name == kCodecNameVp8)
     config->codec = media::cast::transport::kVp8;
   else
diff --git a/chrome/renderer/media/cast_rtp_stream.h b/chrome/renderer/media/cast_rtp_stream.h
index f727f6e..c5e1102 100644
--- a/chrome/renderer/media/cast_rtp_stream.h
+++ b/chrome/renderer/media/cast_rtp_stream.h
@@ -47,10 +47,10 @@
   // Update frequency of payload sample.
   int clock_rate;
 
-  // Maximum bitrate.
+  // Maximum bitrate in kilobits per second.
   int max_bitrate;
 
-  // Minimum bitrate.
+  // Minimum bitrate in kilobits per second.
   int min_bitrate;
 
   // Number of audio channels.
diff --git a/chrome/renderer/media/cast_session.cc b/chrome/renderer/media/cast_session.cc
index 940c6b4..7a89d00 100644
--- a/chrome/renderer/media/cast_session.cc
+++ b/chrome/renderer/media/cast_session.cc
@@ -7,12 +7,39 @@
 #include "base/message_loop/message_loop_proxy.h"
 #include "chrome/renderer/media/cast_session_delegate.h"
 #include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/video_encode_accelerator.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/video_frame.h"
 #include "media/cast/cast_config.h"
 #include "media/cast/cast_sender.h"
 #include "media/cast/logging/logging_defines.h"
 
+namespace {
+
+void CreateVideoEncodeAccelerator(
+    const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback) {
+  DCHECK(content::RenderThread::Get());
+
+  // Delegate the call to content API on the render thread.
+  content::CreateVideoEncodeAccelerator(callback);
+}
+
+void CreateVideoEncodeMemory(
+    size_t size,
+    const media::cast::ReceiveVideoEncodeMemoryCallback& callback) {
+  DCHECK(content::RenderThread::Get());
+
+  scoped_ptr<base::SharedMemory> shm =
+      content::RenderThread::Get()->HostAllocateSharedMemoryBuffer(size);
+  DCHECK(shm) << "Failed to allocate shared memory";
+  if (!shm->Map(size)) {
+    NOTREACHED() << "Map failed";
+  }
+  callback.Run(shm.Pass());
+}
+
+}  // namespace
+
 CastSession::CastSession()
     : delegate_(new CastSessionDelegate()),
       io_message_loop_proxy_(
@@ -54,7 +81,11 @@
                  base::Unretained(delegate_.get()),
                  config,
                  media::BindToCurrentLoop(callback),
-                 media::BindToCurrentLoop(error_callback)));
+                 media::BindToCurrentLoop(error_callback),
+                 media::BindToCurrentLoop(
+                     base::Bind(&CreateVideoEncodeAccelerator)),
+                 media::BindToCurrentLoop(
+                     base::Bind(&CreateVideoEncodeMemory))));
 }
 
 void CastSession::StartUDP(const net::IPEndPoint& remote_endpoint) {
diff --git a/chrome/renderer/media/cast_session_delegate.cc b/chrome/renderer/media/cast_session_delegate.cc
index 66ec865..9c99965 100644
--- a/chrome/renderer/media/cast_session_delegate.cc
+++ b/chrome/renderer/media/cast_session_delegate.cc
@@ -16,6 +16,8 @@
 #include "media/cast/logging/encoding_event_subscriber.h"
 #include "media/cast/logging/log_serializer.h"
 #include "media/cast/logging/logging_defines.h"
+#include "media/cast/logging/stats_event_subscriber.h"
+#include "media/cast/logging/stats_util.h"
 #include "media/cast/transport/cast_transport_config.h"
 #include "media/cast/transport/cast_transport_sender.h"
 
@@ -88,7 +90,10 @@
 void CastSessionDelegate::StartVideo(
     const VideoSenderConfig& config,
     const VideoFrameInputAvailableCallback& callback,
-    const ErrorCallback& error_callback) {
+    const ErrorCallback& error_callback,
+    const media::cast::CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+    const media::cast::CreateVideoEncodeMemoryCallback&
+        create_video_encode_mem_cb) {
   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
 
   if (!cast_transport_ || !cast_sender_) {
@@ -103,34 +108,24 @@
   transport_config.codec = config.codec;
   transport_config.base.rtp_config = config.rtp_config;
   cast_transport_->InitializeVideo(transport_config);
-  // TODO(mikhal): Pass in a valid GpuVideoAcceleratorFactories to support
-  // hardware video encoding.
   cast_sender_->InitializeVideo(
       config,
       base::Bind(&CastSessionDelegate::InitializationResultCB,
                  weak_factory_.GetWeakPtr()),
-      NULL /* GPU*/);
+      create_vea_cb,
+      create_video_encode_mem_cb);
 }
 
 void CastSessionDelegate::StartUDP(const net::IPEndPoint& remote_endpoint) {
   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
 
-  // Logging: enable raw events and stats collection.
-  media::cast::CastLoggingConfig logging_config =
-      media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled();
-
   // CastSender uses the renderer's IO thread as the main thread. This reduces
   // thread hopping for incoming video frames and outgoing network packets.
-  // There's no need to decode so no thread assigned for decoding.
   cast_environment_ = new CastEnvironment(
       scoped_ptr<base::TickClock>(new base::DefaultTickClock()).Pass(),
       base::MessageLoopProxy::current(),
       g_cast_threads.Get().GetAudioEncodeMessageLoopProxy(),
-      NULL,
-      g_cast_threads.Get().GetVideoEncodeMessageLoopProxy(),
-      NULL,
-      base::MessageLoopProxy::current(),
-      logging_config);
+      g_cast_threads.Get().GetVideoEncodeMessageLoopProxy());
 
   // Rationale for using unretained: The callback cannot be called after the
   // destruction of CastTransportSenderIPC, and they both share the same thread.
@@ -138,7 +133,6 @@
       remote_endpoint,
       base::Bind(&CastSessionDelegate::StatusNotificationCB,
                  base::Unretained(this)),
-      logging_config,
       base::Bind(&CastSessionDelegate::LogRawEvents, base::Unretained(this))));
 
   cast_sender_ = CastSender::Create(cast_environment_, cast_transport_.get());
@@ -149,33 +143,55 @@
   DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
   if (enable) {
     if (is_audio) {
-      if (audio_event_subscriber_.get())
-        return;
-      audio_event_subscriber_.reset(new media::cast::EncodingEventSubscriber(
-          media::cast::AUDIO_EVENT, kMaxAudioEventEntries));
-      cast_environment_->Logging()->AddRawEventSubscriber(
-          audio_event_subscriber_.get());
+      if (!audio_event_subscriber_.get()) {
+        audio_event_subscriber_.reset(new media::cast::EncodingEventSubscriber(
+            media::cast::AUDIO_EVENT, kMaxAudioEventEntries));
+        cast_environment_->Logging()->AddRawEventSubscriber(
+            audio_event_subscriber_.get());
+      }
+      if (!audio_stats_subscriber_.get()) {
+        audio_stats_subscriber_.reset(
+            new media::cast::StatsEventSubscriber(media::cast::AUDIO_EVENT));
+        cast_environment_->Logging()->AddRawEventSubscriber(
+            audio_stats_subscriber_.get());
+      }
     } else {
-      if (video_event_subscriber_.get())
-        return;
-      video_event_subscriber_.reset(new media::cast::EncodingEventSubscriber(
-          media::cast::VIDEO_EVENT, kMaxVideoEventEntries));
-      cast_environment_->Logging()->AddRawEventSubscriber(
-          video_event_subscriber_.get());
+      if (!video_event_subscriber_.get()) {
+        video_event_subscriber_.reset(new media::cast::EncodingEventSubscriber(
+            media::cast::VIDEO_EVENT, kMaxVideoEventEntries));
+        cast_environment_->Logging()->AddRawEventSubscriber(
+            video_event_subscriber_.get());
+      }
+      if (!video_stats_subscriber_.get()) {
+        video_stats_subscriber_.reset(
+            new media::cast::StatsEventSubscriber(media::cast::VIDEO_EVENT));
+        cast_environment_->Logging()->AddRawEventSubscriber(
+            video_stats_subscriber_.get());
+      }
     }
   } else {
     if (is_audio) {
-      if (!audio_event_subscriber_.get())
-        return;
-      cast_environment_->Logging()->RemoveRawEventSubscriber(
-          audio_event_subscriber_.get());
-      audio_event_subscriber_.reset();
+      if (audio_event_subscriber_.get()) {
+        cast_environment_->Logging()->RemoveRawEventSubscriber(
+            audio_event_subscriber_.get());
+        audio_event_subscriber_.reset();
+      }
+      if (audio_stats_subscriber_.get()) {
+        cast_environment_->Logging()->RemoveRawEventSubscriber(
+            audio_stats_subscriber_.get());
+        audio_stats_subscriber_.reset();
+      }
     } else {
-      if (!video_event_subscriber_.get())
-        return;
-      cast_environment_->Logging()->RemoveRawEventSubscriber(
-          video_event_subscriber_.get());
-      video_event_subscriber_.reset();
+      if (video_event_subscriber_.get()) {
+        cast_environment_->Logging()->RemoveRawEventSubscriber(
+            video_event_subscriber_.get());
+        video_event_subscriber_.reset();
+      }
+      if (video_stats_subscriber_.get()) {
+        cast_environment_->Logging()->RemoveRawEventSubscriber(
+            video_stats_subscriber_.get());
+        video_stats_subscriber_.reset();
+      }
     }
   }
 }
@@ -223,12 +239,18 @@
 
 void CastSessionDelegate::GetStatsAndReset(bool is_audio,
                                            const StatsCallback& callback) {
-  media::cast::FrameStatsMap frame_stats =
-      cast_environment_->Logging()->GetFrameStatsData(
-          is_audio ? media::cast::AUDIO_EVENT : media::cast::VIDEO_EVENT);
-  media::cast::PacketStatsMap packet_stats =
-      cast_environment_->Logging()->GetPacketStatsData(
-          is_audio ? media::cast::AUDIO_EVENT : media::cast::VIDEO_EVENT);
+  media::cast::StatsEventSubscriber* subscriber =
+      is_audio ? audio_stats_subscriber_.get() : video_stats_subscriber_.get();
+  if (!subscriber) {
+    callback.Run(make_scoped_ptr(new base::DictionaryValue).Pass());
+    return;
+  }
+
+  media::cast::FrameStatsMap frame_stats;
+  subscriber->GetFrameStats(&frame_stats);
+  media::cast::PacketStatsMap packet_stats;
+  subscriber->GetPacketStats(&packet_stats);
+  subscriber->Reset();
 
   scoped_ptr<base::DictionaryValue> stats = media::cast::ConvertStats(
       frame_stats, packet_stats);
diff --git a/chrome/renderer/media/cast_session_delegate.h b/chrome/renderer/media/cast_session_delegate.h
index 9243826..008c327 100644
--- a/chrome/renderer/media/cast_session_delegate.h
+++ b/chrome/renderer/media/cast_session_delegate.h
@@ -32,6 +32,7 @@
 class CastEnvironment;
 class EncodingEventSubscriber;
 class FrameInput;
+class StatsEventSubscriber;
 
 namespace transport {
 class CastTransportSender;
@@ -73,7 +74,11 @@
 
   void StartVideo(const media::cast::VideoSenderConfig& config,
                   const VideoFrameInputAvailableCallback& callback,
-                  const ErrorCallback& error_callback);
+                  const ErrorCallback& error_callback,
+                  const media::cast::CreateVideoEncodeAcceleratorCallback&
+                      create_vea_cb,
+                  const media::cast::CreateVideoEncodeMemoryCallback&
+                      create_video_encode_mem_cb);
 
   void ToggleLogging(bool is_audio, bool enable);
   void GetEventLogsAndReset(bool is_audio, const EventLogsCallback& callback);
@@ -104,6 +109,9 @@
   scoped_ptr<media::cast::EncodingEventSubscriber> audio_event_subscriber_;
   scoped_ptr<media::cast::EncodingEventSubscriber> video_event_subscriber_;
 
+  scoped_ptr<media::cast::StatsEventSubscriber> audio_stats_subscriber_;
+  scoped_ptr<media::cast::StatsEventSubscriber> video_stats_subscriber_;
+
   // Proxy to the IO message loop.
   scoped_refptr<base::MessageLoopProxy> io_message_loop_proxy_;
   base::WeakPtrFactory<CastSessionDelegate> weak_factory_;
diff --git a/chrome/renderer/media/cast_transport_sender_ipc.cc b/chrome/renderer/media/cast_transport_sender_ipc.cc
index dd76411..8199402 100644
--- a/chrome/renderer/media/cast_transport_sender_ipc.cc
+++ b/chrome/renderer/media/cast_transport_sender_ipc.cc
@@ -15,13 +15,12 @@
 CastTransportSenderIPC::CastTransportSenderIPC(
     const net::IPEndPoint& remote_end_point,
     const media::cast::transport::CastTransportStatusCallback& status_cb,
-    const media::cast::CastLoggingConfig& logging_config,
     const media::cast::transport::BulkRawEventsCallback& raw_events_cb)
     : status_callback_(status_cb), raw_events_callback_(raw_events_cb) {
   if (CastIPCDispatcher::Get()) {
     channel_id_ = CastIPCDispatcher::Get()->AddSender(this);
   }
-  Send(new CastHostMsg_New(channel_id_, remote_end_point, logging_config));
+  Send(new CastHostMsg_New(channel_id_, remote_end_point));
 }
 
 CastTransportSenderIPC::~CastTransportSenderIPC() {
diff --git a/chrome/renderer/media/cast_transport_sender_ipc.h b/chrome/renderer/media/cast_transport_sender_ipc.h
index 11b34e8..5c7b258 100644
--- a/chrome/renderer/media/cast_transport_sender_ipc.h
+++ b/chrome/renderer/media/cast_transport_sender_ipc.h
@@ -21,7 +21,6 @@
   CastTransportSenderIPC(
       const net::IPEndPoint& remote_end_point,
       const media::cast::transport::CastTransportStatusCallback& status_cb,
-      const media::cast::CastLoggingConfig& logging_config,
       const media::cast::transport::BulkRawEventsCallback& raw_events_cb);
 
   virtual ~CastTransportSenderIPC();
diff --git a/chrome/renderer/net/DEPS b/chrome/renderer/net/DEPS
new file mode 100644
index 0000000..b462077
--- /dev/null
+++ b/chrome/renderer/net/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+gin",
+]
diff --git a/chrome/renderer/net/error_cache_load.cc b/chrome/renderer/net/error_cache_load.cc
new file mode 100644
index 0000000..e866917
--- /dev/null
+++ b/chrome/renderer/net/error_cache_load.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "error_cache_load.h"
+
+#include "content/public/renderer/render_frame.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebKit.h"
+
+gin::WrapperInfo ErrorCacheLoad::kWrapperInfo = {gin::kEmbedderNativeGin};
+
+// static
+void ErrorCacheLoad::Install(content::RenderFrame* render_frame,
+                             const GURL& page_url) {
+  v8::Isolate* isolate = blink::mainThreadIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::Context> context =
+      render_frame->GetWebFrame()->mainWorldScriptContext();
+  if (context.IsEmpty())
+    return;
+
+  v8::Context::Scope context_scope(context);
+
+  gin::Handle<ErrorCacheLoad> controller =
+      gin::CreateHandle(isolate, new ErrorCacheLoad(render_frame, page_url));
+  v8::Handle<v8::Object> global = context->Global();
+  global->Set(gin::StringToV8(isolate, "errorCacheLoad"), controller.ToV8());
+}
+
+bool ErrorCacheLoad::ReloadStaleInstance() {
+  if (!render_frame_)
+    return false;
+
+  blink::WebURLRequest request(page_url_);
+  request.setCachePolicy(blink::WebURLRequest::ReturnCacheDataDontLoad);
+
+  render_frame_->GetWebFrame()->loadRequest(request);
+
+  return true;
+}
+
+ErrorCacheLoad::ErrorCacheLoad(content::RenderFrame* render_frame,
+                               const GURL& page_url)
+    : RenderFrameObserver(render_frame),
+      render_frame_(render_frame),
+      page_url_(page_url) {}
+
+ErrorCacheLoad::~ErrorCacheLoad() {}
+
+gin::ObjectTemplateBuilder ErrorCacheLoad::GetObjectTemplateBuilder(
+    v8::Isolate* isolate) {
+  return gin::Wrappable<ErrorCacheLoad>::GetObjectTemplateBuilder(isolate)
+      .SetMethod("reloadStaleInstance", &ErrorCacheLoad::ReloadStaleInstance);
+}
+
+void ErrorCacheLoad::OnDestruct() { render_frame_ = NULL; }
diff --git a/chrome/renderer/net/error_cache_load.h b/chrome/renderer/net/error_cache_load.h
new file mode 100644
index 0000000..1bb60c2
--- /dev/null
+++ b/chrome/renderer/net/error_cache_load.h
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_NET_ERROR_CACHE_LOAD_H_
+#define CHROME_RENDERER_NET_ERROR_CACHE_LOAD_H_
+
+#include "base/basictypes.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "gin/wrappable.h"
+#include "url/gurl.h"
+
+// ErrorCacheLoad class:
+//
+// This class makes cache loading operations available to the
+// error page loaded by NetErrorHelper.  It is bound to the javascript
+// window.errorCacheLoad object.
+
+class GURL;
+
+namespace content {
+class RenderFrame;
+}
+
+class ErrorCacheLoad : public gin::Wrappable<ErrorCacheLoad>,
+                       public content::RenderFrameObserver {
+ public:
+  static gin::WrapperInfo kWrapperInfo;
+
+  static void Install(content::RenderFrame* render_frame, const GURL& page_url);
+
+ private:
+  ErrorCacheLoad(content::RenderFrame* render_frame, const GURL& page_url);
+  virtual ~ErrorCacheLoad();
+
+  // Loads the original URL associated with the frame, with the blink
+  // ReturnCacheDataDontLoad flag set to make sure that the value is
+  // only gotten from cache.
+  bool ReloadStaleInstance();
+
+  // gin::WrappableBase
+  virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+      v8::Isolate* isolate) OVERRIDE;
+
+  // RenderFrameObserver.  Overridden to avoid being destroyed when RenderFrame
+  // goes away; ErrorCacheLoad objects are owned by the JS garbage collector.
+  virtual void OnDestruct() OVERRIDE;
+
+  // We'll be torn down by V8 when the page goes away, so it's safe to hold
+  // a naked pointer to the render frame.
+  content::RenderFrame* render_frame_;
+
+  const GURL page_url_;
+
+  bool render_frame_destroyed_;
+
+  DISALLOW_COPY_AND_ASSIGN(ErrorCacheLoad);
+};
+
+#endif  // CHROME_RENDERER_NET_ERROR_CACHE_LOAD_H_
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index 1084d2f..1d9529a 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -16,6 +16,7 @@
 #include "chrome/common/localized_error.h"
 #include "chrome/common/net/net_error_info.h"
 #include "chrome/common/render_messages.h"
+#include "chrome/renderer/net/error_cache_load.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/renderer/content_renderer_client.h"
@@ -178,6 +179,10 @@
   frame->loadHTMLString(html, GURL(kUnreachableWebDataURL), failed_url, true);
 }
 
+void NetErrorHelper::EnableStaleLoadBindings(const GURL& page_url) {
+  ErrorCacheLoad::Install(render_frame(), page_url);
+}
+
 void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error,
                                      bool is_failed_post) {
   base::DictionaryValue error_strings;
@@ -203,8 +208,7 @@
     return;
   }
 
-  base::string16 frame_xpath;
-  render_frame()->GetRenderView()->EvaluateScript(frame_xpath, js16, 0, false);
+  render_frame()->ExecuteJavaScript(js16);
 }
 
 void NetErrorHelper::FetchNavigationCorrections(
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h
index 3dafeae..5369e19 100644
--- a/chrome/renderer/net/net_error_helper.h
+++ b/chrome/renderer/net/net_error_helper.h
@@ -78,6 +78,7 @@
       std::string* html) const OVERRIDE;
   virtual void LoadErrorPageInMainFrame(const std::string& html,
                                         const GURL& failed_url) OVERRIDE;
+  virtual void EnableStaleLoadBindings(const GURL& page_url) OVERRIDE;
   virtual void UpdateErrorPage(const blink::WebURLError& error,
                                bool is_failed_post) OVERRIDE;
   virtual void FetchNavigationCorrections(
diff --git a/chrome/renderer/net/net_error_helper_core.cc b/chrome/renderer/net/net_error_helper_core.cc
index 105d391..d888a1a 100644
--- a/chrome/renderer/net/net_error_helper_core.cc
+++ b/chrome/renderer/net/net_error_helper_core.cc
@@ -384,6 +384,12 @@
 
   committed_error_page_info_->is_finished_loading = true;
 
+  // Only enable stale cache JS bindings if this wasn't a post.
+  if (!committed_error_page_info_->was_failed_post) {
+    delegate_->EnableStaleLoadBindings(
+        committed_error_page_info_->error.unreachableURL);
+  }
+
   if (committed_error_page_info_->navigation_correction_url.is_valid()) {
     // If there is another pending error page load, |fix_url| should have been
     // cleared.
diff --git a/chrome/renderer/net/net_error_helper_core.h b/chrome/renderer/net/net_error_helper_core.h
index e52a3a4..bd5297c 100644
--- a/chrome/renderer/net/net_error_helper_core.h
+++ b/chrome/renderer/net/net_error_helper_core.h
@@ -54,6 +54,9 @@
     virtual void LoadErrorPageInMainFrame(const std::string& html,
                                           const GURL& failed_url) = 0;
 
+    // Create extra Javascript bindings in the error page.
+    virtual void EnableStaleLoadBindings(const GURL& page_url) = 0;
+
     // Updates the currently displayed error page with a new error code.  The
     // currently displayed error page must have finished loading, and must have
     // been generated by a call to GenerateLocalizedErrorPage.
diff --git a/chrome/renderer/net/net_error_helper_core_unittest.cc b/chrome/renderer/net/net_error_helper_core_unittest.cc
index 67eb65e..f41da62 100644
--- a/chrome/renderer/net/net_error_helper_core_unittest.cc
+++ b/chrome/renderer/net/net_error_helper_core_unittest.cc
@@ -118,7 +118,8 @@
                              core_(this),
                              update_count_(0),
                              error_html_update_count_(0),
-                             reload_count_(0) {
+                             reload_count_(0),
+                             enable_stale_load_bindings_count_(0) {
     core_.set_auto_reload_enabled(false);
     core_.set_timer_for_testing(scoped_ptr<base::Timer>(timer_));
   }
@@ -137,6 +138,10 @@
     return reload_count_;
   }
 
+  int enable_stale_load_bindings_count() const {
+    return enable_stale_load_bindings_count_;
+  }
+
   const std::string& last_update_string() const { return last_update_string_; }
   int update_count() const { return update_count_;  }
 
@@ -231,6 +236,10 @@
     last_error_html_ = html;
   }
 
+  virtual void EnableStaleLoadBindings(const GURL& page_url) OVERRIDE {
+    enable_stale_load_bindings_count_++;
+  }
+
   virtual void UpdateErrorPage(const WebURLError& error,
                                bool is_failed_post) OVERRIDE {
     update_count_++;
@@ -280,6 +289,8 @@
   mutable scoped_ptr<LocalizedError::ErrorPageParams> last_error_page_params_;
 
   int reload_count_;
+
+  int enable_stale_load_bindings_count_;
 };
 
 //------------------------------------------------------------------------------
@@ -323,12 +334,14 @@
   EXPECT_EQ(NetErrorString(net::ERR_CONNECTION_RESET), html);
 
   // Error page loads.
+  EXPECT_EQ(0, enable_stale_load_bindings_count());
   core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
                      NetErrorHelperCore::ERROR_PAGE);
   core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
   core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
   EXPECT_EQ(0, update_count());
   EXPECT_EQ(0, error_html_update_count());
+  EXPECT_EQ(1, enable_stale_load_bindings_count());
 }
 
 TEST_F(NetErrorHelperCoreTest, MainFrameNonDnsErrorWithCorrections) {
@@ -726,11 +739,13 @@
             html);
 
   // Error page loads.
+  EXPECT_EQ(0, enable_stale_load_bindings_count());
   core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
                      NetErrorHelperCore::ERROR_PAGE);
   core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
   core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
   EXPECT_EQ(0, update_count());
+  EXPECT_EQ(0, enable_stale_load_bindings_count());
 
   core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
   EXPECT_EQ(1, update_count());
diff --git a/chrome/renderer/pepper/pepper_uma_host.cc b/chrome/renderer/pepper/pepper_uma_host.cc
index 7ecdcf9..c165928 100644
--- a/chrome/renderer/pepper/pepper_uma_host.cc
+++ b/chrome/renderer/pepper/pepper_uma_host.cc
@@ -8,7 +8,9 @@
 #include "base/sha1.h"
 #include "base/strings/string_number_conversions.h"
 #include "chrome/common/chrome_switches.h"
+#include "chrome/common/render_messages.h"
 #include "chrome/renderer/chrome_content_renderer_client.h"
+#include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/renderer_ppapi_host.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
@@ -65,19 +67,23 @@
         OnHistogramCustomCounts);
     PPAPI_DISPATCH_HOST_RESOURCE_CALL(PpapiHostMsg_UMA_HistogramEnumeration,
         OnHistogramEnumeration);
+    PPAPI_DISPATCH_HOST_RESOURCE_CALL_0(
+        PpapiHostMsg_UMA_IsCrashReportingEnabled, OnIsCrashReportingEnabled);
   IPC_END_MESSAGE_MAP()
   return PP_ERROR_FAILED;
 }
 
+bool PepperUMAHost::IsPluginWhitelisted() {
+  return ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
+      document_url_, allowed_origins_);
+}
+
 bool PepperUMAHost::IsHistogramAllowed(const std::string& histogram) {
   if (is_plugin_in_process_ && histogram.find("NaCl.") == 0) {
     return true;
   }
 
-  bool is_whitelisted =
-      ChromeContentRendererClient::IsExtensionOrSharedModuleWhitelisted(
-          document_url_, allowed_origins_);
-  if (is_whitelisted &&
+  if (IsPluginWhitelisted() &&
       allowed_histogram_prefixes_.find(HashPrefix(histogram)) !=
           allowed_histogram_prefixes_.end()) {
     return true;
@@ -169,3 +175,15 @@
   return PP_OK;
 }
 
+int32_t PepperUMAHost::OnIsCrashReportingEnabled(
+    ppapi::host::HostMessageContext* context) {
+  if (!IsPluginWhitelisted())
+    return PP_ERROR_NOACCESS;
+  bool enabled = false;
+  content::RenderThread::Get()->Send(
+      new ChromeViewHostMsg_IsCrashReportingEnabled(&enabled));
+  if (enabled)
+    return PP_OK;
+  return PP_ERROR_FAILED;
+}
+
diff --git a/chrome/renderer/pepper/pepper_uma_host.h b/chrome/renderer/pepper/pepper_uma_host.h
index 7039cce..a998128 100644
--- a/chrome/renderer/pepper/pepper_uma_host.h
+++ b/chrome/renderer/pepper/pepper_uma_host.h
@@ -37,6 +37,7 @@
       ppapi::host::HostMessageContext* context) OVERRIDE;
 
  private:
+  bool IsPluginWhitelisted();
   bool IsHistogramAllowed(const std::string& histogram);
 
   int32_t OnHistogramCustomTimes(
@@ -61,6 +62,9 @@
       int32_t sample,
       int32_t boundary_value);
 
+  int32_t OnIsCrashReportingEnabled(
+      ppapi::host::HostMessageContext* context);
+
   const GURL document_url_;
   bool is_plugin_in_process_;
 
diff --git a/chrome/renderer/printing/print_web_view_helper.cc b/chrome/renderer/printing/print_web_view_helper.cc
index 5d39437..13c69ef 100644
--- a/chrome/renderer/printing/print_web_view_helper.cc
+++ b/chrome/renderer/printing/print_web_view_helper.cc
@@ -412,7 +412,7 @@
 
 }  // namespace
 
-FrameReference::FrameReference(const blink::WebFrame* frame) {
+FrameReference::FrameReference(blink::WebFrame* frame) {
   Reset(frame);
 }
 
@@ -423,18 +423,25 @@
 FrameReference::~FrameReference() {
 }
 
-void FrameReference::Reset(const blink::WebFrame* frame) {
+void FrameReference::Reset(blink::WebFrame* frame) {
   if (frame) {
     view_ = frame->view();
-    frame_name_ = frame->uniqueName();
+    frame_ = frame;
   } else {
     view_ = NULL;
-    frame_name_.reset();
+    frame_ = NULL;
   }
 }
 
 blink::WebFrame* FrameReference::GetFrame() {
-  return view_ ? view_->findFrameByName(frame_name_) : NULL;
+  if (view_ == NULL || frame_ == NULL)
+    return NULL;
+  for (blink::WebFrame* frame = view_->mainFrame(); frame != NULL;
+           frame = frame->traverseNext(false)) {
+    if (frame == frame_)
+      return frame;
+  }
+  return NULL;
 }
 
 blink::WebView* FrameReference::view() {
@@ -971,12 +978,20 @@
 
   UMA_HISTOGRAM_ENUMERATION("PrintPreview.PreviewEvent",
                             PREVIEW_EVENT_REQUESTED, PREVIEW_EVENT_MAX);
-  if (!print_preview_context_.source_frame() ||
-      !UpdatePrintSettings(print_preview_context_.source_frame(),
+
+  if (!print_preview_context_.source_frame()) {
+    DidFinishPrinting(FAIL_PREVIEW);
+    return;
+  }
+
+  if (!UpdatePrintSettings(print_preview_context_.source_frame(),
                            print_preview_context_.source_node(), settings)) {
     if (print_preview_context_.last_error() != PREVIEW_ERROR_BAD_SETTING) {
       Send(new PrintHostMsg_PrintPreviewInvalidPrinterSettings(
-          routing_id(), print_pages_params_->params.document_cookie));
+          routing_id(),
+          print_pages_params_.get()
+              ? print_pages_params_->params.document_cookie
+              : 0));
       notify_browser_of_print_failure_ = false;  // Already sent.
     }
     DidFinishPrinting(FAIL_PREVIEW);
diff --git a/chrome/renderer/printing/print_web_view_helper.h b/chrome/renderer/printing/print_web_view_helper.h
index 6bf5d36..368ed08 100644
--- a/chrome/renderer/printing/print_web_view_helper.h
+++ b/chrome/renderer/printing/print_web_view_helper.h
@@ -40,20 +40,21 @@
 
 // Stores reference to frame using WebVew and unique name.
 // Workaround to modal dialog issue on Linux. crbug.com/236147.
+// If WebFrame someday supports WeakPtr, we should use it here.
 class FrameReference {
  public:
-  explicit FrameReference(const blink::WebFrame* frame);
+  explicit FrameReference(blink::WebFrame* frame);
   FrameReference();
   ~FrameReference();
 
-  void Reset(const blink::WebFrame* frame);
+  void Reset(blink::WebFrame* frame);
 
   blink::WebFrame* GetFrame();
   blink::WebView* view();
 
  private:
   blink::WebView* view_;
-  blink::WebString frame_name_;
+  blink::WebFrame* frame_;
 };
 
 // PrintWebViewHelper handles most of the printing grunt work for RenderView.
diff --git a/chrome/renderer/resources/extensions/ad_view.js b/chrome/renderer/resources/extensions/ad_view.js
index 81d6e92..1f094e6 100644
--- a/chrome/renderer/resources/extensions/ad_view.js
+++ b/chrome/renderer/resources/extensions/ad_view.js
@@ -101,7 +101,7 @@
 function AdView(adviewNode) {
   this.adviewNode_ = adviewNode;
   this.browserPluginNode_ = this.createBrowserPluginNode_();
-  var shadowRoot = this.adviewNode_.webkitCreateShadowRoot();
+  var shadowRoot = this.adviewNode_.createShadowRoot();
   shadowRoot.appendChild(this.browserPluginNode_);
 
   this.setupCustomAttributes_();
diff --git a/chrome/renderer/resources/extensions/inject_app_titlebar.js b/chrome/renderer/resources/extensions/inject_app_titlebar.js
index aa785c9..9f2ba37 100644
--- a/chrome/renderer/resources/extensions/inject_app_titlebar.js
+++ b/chrome/renderer/resources/extensions/inject_app_titlebar.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 exports.didCreateDocumentElement = function() {
-  var root = document.documentElement.webkitCreateShadowRoot();
+  var root = document.documentElement.createShadowRoot();
   root.appendChild(document.createElement('style')).innerText =
       // TODO(jeremya): switch this to use automatic inlining once grit
       // supports inlining into JS. See http://crbug.com/146319.
diff --git a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js
index 7e514ab..789df03 100644
--- a/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/web_request_internal_custom_bindings.js
@@ -90,7 +90,7 @@
             eventName, subEventName, requestId, result);
       } catch (e) {
         webRequestInternal.eventHandled(
-            eventName, subEventName, requestId, {cancel: true});
+            eventName, subEventName, requestId);
         throw e;
       }
     };
diff --git a/chrome/renderer/resources/extensions/web_view.js b/chrome/renderer/resources/extensions/web_view.js
index 7253695..34ab004 100644
--- a/chrome/renderer/resources/extensions/web_view.js
+++ b/chrome/renderer/resources/extensions/web_view.js
@@ -166,7 +166,7 @@
   privates(webviewNode).internal = this;
   this.webviewNode = webviewNode;
   this.browserPluginNode = this.createBrowserPluginNode();
-  var shadowRoot = this.webviewNode.webkitCreateShadowRoot();
+  var shadowRoot = this.webviewNode.createShadowRoot();
   shadowRoot.appendChild(this.browserPluginNode);
 
   this.setupWebviewNodeAttributes();
diff --git a/chrome/renderer/resources/extensions/webstore_custom_bindings.js b/chrome/renderer/resources/extensions/webstore_custom_bindings.js
index 963adaa..c31f40f 100644
--- a/chrome/renderer/resources/extensions/webstore_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/webstore_custom_bindings.js
@@ -5,15 +5,38 @@
 // Custom binding for the webstore API.
 
 var webstoreNatives = requireNative('webstore');
+var Event = require('event_bindings').Event;
 
 function Installer() {
   this._pendingInstall = null;
+  this.onInstallStageChanged =
+      new Event(null, [{name: 'stage', type: 'string'}], {unmanaged: true});
+  this.onDownloadProgress =
+      new Event(null, [{name: 'progress', type: 'number'}], {unmanaged: true});
 }
 
 Installer.prototype.install = function(url, onSuccess, onFailure) {
   if (this._pendingInstall)
-    throw 'A Chrome Web Store installation is already pending.';
-  var installId = webstoreNatives.Install(url, onSuccess, onFailure);
+    throw new Error('A Chrome Web Store installation is already pending.');
+  if (url !== undefined && typeof(url) !== 'string') {
+    throw new Error(
+        'The Chrome Web Store item link URL parameter must be a string.');
+  }
+  if (onSuccess !== undefined && typeof(onSuccess) !== 'function')
+    throw new Error('The success callback parameter must be a function.');
+  if (onFailure !== undefined && typeof(onFailure) !== 'function')
+    throw new Error('The failure callback parameter must be a function.');
+
+  // Since we call Install() with a bool for if we have listeners, listeners
+  // must be set prior to the inline installation starting (this is also
+  // noted in the Event documentation in
+  // chrome/common/extensions/api/webstore.json).
+  var installId = webstoreNatives.Install(
+      this.onInstallStageChanged.hasListeners(),
+      this.onDownloadProgress.hasListeners(),
+      url,
+      onSuccess,
+      onFailure);
   if (installId !== undefined) {
     this._pendingInstall = {
       installId: installId,
@@ -43,20 +66,32 @@
   }
 };
 
+Installer.prototype.onInstallStageChanged = function(installStage) {
+  this.onInstallStageChanged.dispatch(installStage);
+};
+
+Installer.prototype.onDownloadProgress = function(progress) {
+  this.onDownloadProgress.dispatch(progress);
+};
+
 var installer = new Installer();
 
 var chromeWebstore = {
-  install: function install(url, onSuccess, onFailure) {
+  install: function (url, onSuccess, onFailure) {
     installer.install(url, onSuccess, onFailure);
-  }
+  },
+  onInstallStageChanged: installer.onInstallStageChanged,
+  onDownloadProgress: installer.onDownloadProgress
 };
 
-// Called by webstore_binding.cc.
-function onInstallResponse(installId, success, error) {
-  installer.onInstallResponse(installId, success, error);
-}
-
-// These must match the names in InstallWebstorebinding in
+// This must match the name in InstallWebstoreBindings in
 // chrome/renderer/extensions/dispatcher.cc.
 exports.chromeWebstore = chromeWebstore;
-exports.onInstallResponse = onInstallResponse;
+
+// Called by webstore_bindings.cc.
+exports.onInstallResponse =
+    Installer.prototype.onInstallResponse.bind(installer);
+exports.onInstallStageChanged =
+    Installer.prototype.onInstallStageChanged.bind(installer);
+exports.onDownloadProgress =
+    Installer.prototype.onDownloadProgress.bind(installer);
diff --git a/chrome/renderer/resources/extensions/window_controls.js b/chrome/renderer/resources/extensions/window_controls.js
index e57271d..75c88e6 100644
--- a/chrome/renderer/resources/extensions/window_controls.js
+++ b/chrome/renderer/resources/extensions/window_controls.js
@@ -40,7 +40,7 @@
     template = WindowControls.prototype.template_element;
   }
   // Create shadow root element with template clone as first child.
-  var shadowRoot = node.webkitCreateShadowRoot();
+  var shadowRoot = node.createShadowRoot();
   shadowRoot.appendChild(template.content.cloneNode(true));
   return shadowRoot;
 }
diff --git a/chrome/renderer/resources/neterror.html b/chrome/renderer/resources/neterror.html
index ff197b8..63c6a69 100644
--- a/chrome/renderer/resources/neterror.html
+++ b/chrome/renderer/resources/neterror.html
@@ -45,7 +45,7 @@
               jsdisplay="diagnose"></button>
           <div id="diagnose-frame" class="hidden"></div>
           <form class="suggestions" jsdisplay="searchUrl"
-              jsvalues=".url:searchUrl" onclick="return search(this.url)">
+              jsvalues=".url:searchUrl" onsubmit="return search(this.url)">
             <div class="suggestion-header" jscontent="searchHeader"></div>
             <div id="search-container">
               <input type="text" name="q" id="search-box"
diff --git a/chrome/renderer/security_filter_peer.h b/chrome/renderer/security_filter_peer.h
index f67de71..a4c0027 100644
--- a/chrome/renderer/security_filter_peer.h
+++ b/chrome/renderer/security_filter_peer.h
@@ -6,6 +6,7 @@
 #define CHROME_RENDERER_SECURITY_FILTER_PEER_H_
 
 #include "webkit/child/resource_loader_bridge.h"
+#include "webkit/common/resource_type.h"
 
 // The SecurityFilterPeer is a proxy to a
 // webkit_glue::ResourceLoaderBridge::Peer instance.  It is used to pre-process
diff --git a/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.cc b/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.cc
index ca14fab..b71e652 100644
--- a/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.cc
+++ b/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.cc
@@ -13,8 +13,8 @@
   return new CocoaSpellingEngine();
 }
 
-void CocoaSpellingEngine::Init(base::PlatformFile bdict_file) {
-  DCHECK(bdict_file == base::kInvalidPlatformFileValue);
+void CocoaSpellingEngine::Init(base::File bdict_file) {
+  DCHECK(!bdict_file.IsValid());
 }
 
 bool CocoaSpellingEngine::InitializeIfNeeded() {
diff --git a/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.h b/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.h
index 53b5cb7..a0f01e2 100644
--- a/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.h
+++ b/chrome/renderer/spellchecker/cocoa_spelling_engine_mac.h
@@ -10,7 +10,7 @@
 
 class CocoaSpellingEngine : public SpellingEngine {
  public:
-  virtual void Init(base::PlatformFile bdict_file) OVERRIDE;
+  virtual void Init(base::File bdict_file) OVERRIDE;
   virtual bool InitializeIfNeeded() OVERRIDE;
   virtual bool IsEnabled() OVERRIDE;
   virtual bool CheckSpelling(const base::string16& word_to_check,
diff --git a/chrome/renderer/spellchecker/hunspell_engine.cc b/chrome/renderer/spellchecker/hunspell_engine.cc
index c2cdd29..f8071ef 100644
--- a/chrome/renderer/spellchecker/hunspell_engine.cc
+++ b/chrome/renderer/spellchecker/hunspell_engine.cc
@@ -29,7 +29,7 @@
 
   COMPILE_ASSERT(kMaxCheckedLen <= size_t(MAXWORDLEN), MaxCheckedLen_too_long);
   COMPILE_ASSERT(kMaxSuggestLen <= kMaxCheckedLen, MaxSuggestLen_too_long);
-}
+}  // namespace
 
 #if !defined(OS_MACOSX)
 SpellingEngine* CreateNativeSpellingEngine() {
@@ -38,7 +38,7 @@
 #endif
 
 HunspellEngine::HunspellEngine()
-    : file_(base::kInvalidPlatformFileValue),
+    : hunspell_enabled_(false),
       initialized_(false),
       dictionary_requested_(false) {
   // Wait till we check the first word before doing any initializing.
@@ -47,11 +47,12 @@
 HunspellEngine::~HunspellEngine() {
 }
 
-void HunspellEngine::Init(base::PlatformFile file) {
+void HunspellEngine::Init(base::File file) {
   initialized_ = true;
   hunspell_.reset();
   bdict_file_.reset();
-  file_ = file;
+  file_ = file.Pass();
+  hunspell_enabled_ = file_.IsValid();
   // Delay the actual initialization of hunspell until it is needed.
 }
 
@@ -61,13 +62,10 @@
 
   bdict_file_.reset(new base::MemoryMappedFile);
 
-  // TODO(rvargas): This object should not keep file_ after passing it to
-  // bdict_file_.
-  if (bdict_file_->Initialize(base::File(file_))) {
+  if (bdict_file_->Initialize(file_.Pass())) {
     TimeTicks debug_start_time = base::Histogram::DebugNow();
 
-    hunspell_.reset(
-        new Hunspell(bdict_file_->data(), bdict_file_->length()));
+    hunspell_.reset(new Hunspell(bdict_file_->data(), bdict_file_->length()));
 
     DHISTOGRAM_TIMES("Spellcheck.InitTime",
                      base::Histogram::DebugNow() - debug_start_time);
@@ -134,12 +132,12 @@
   }
 
   // Don't initialize if hunspell is disabled.
-  if (file_ != base::kInvalidPlatformFileValue)
+  if (file_.IsValid())
     InitializeHunspell();
 
   return !initialized_;
 }
 
 bool HunspellEngine::IsEnabled() {
-  return file_ != base::kInvalidPlatformFileValue;
+  return hunspell_enabled_;
 }
diff --git a/chrome/renderer/spellchecker/hunspell_engine.h b/chrome/renderer/spellchecker/hunspell_engine.h
index fbd8ac8..534eb87 100644
--- a/chrome/renderer/spellchecker/hunspell_engine.h
+++ b/chrome/renderer/spellchecker/hunspell_engine.h
@@ -25,7 +25,7 @@
   HunspellEngine();
   virtual ~HunspellEngine();
 
-  virtual void Init(base::PlatformFile file) OVERRIDE;
+  virtual void Init(base::File file) OVERRIDE;
 
   virtual bool InitializeIfNeeded() OVERRIDE;
   virtual bool IsEnabled() OVERRIDE;
@@ -46,15 +46,18 @@
   // The hunspell dictionary in use.
   scoped_ptr<Hunspell> hunspell_;
 
-  base::PlatformFile file_;
+  base::File file_;
 
-  // This flags is true if we have been initialized.
+  // This flag is true if hunspell is enabled.
+  bool hunspell_enabled_;
+
+  // This flag is true if we have been initialized.
   // The value indicates whether we should request a
   // dictionary from the browser when the render view asks us to check the
   // spelling of a word.
   bool initialized_;
 
-  // This flags is true if we have requested dictionary.
+  // This flag is true if we have requested dictionary.
   bool dictionary_requested_;
 };
 
diff --git a/chrome/renderer/spellchecker/spellcheck.cc b/chrome/renderer/spellchecker/spellcheck.cc
index 51c0ba9..2150dd2 100644
--- a/chrome/renderer/spellchecker/spellcheck.cc
+++ b/chrome/renderer/spellchecker/spellcheck.cc
@@ -134,7 +134,7 @@
                         const std::set<std::string>& custom_words,
                         const std::string& language,
                         bool auto_spell_correct) {
-  Init(IPC::PlatformFileForTransitToPlatformFile(bdict_file),
+  Init(IPC::PlatformFileForTransitToFile(bdict_file),
        custom_words, language);
   auto_spell_correct_turned_on_ = auto_spell_correct;
 #if !defined(OS_MACOSX)
@@ -167,10 +167,10 @@
 
 // TODO(groby): Make sure we always have a spelling engine, even before Init()
 // is called.
-void SpellCheck::Init(base::PlatformFile file,
+void SpellCheck::Init(base::File file,
                       const std::set<std::string>& custom_words,
                       const std::string& language) {
-  spellcheck_.Init(file, language);
+  spellcheck_.Init(file.Pass(), language);
   custom_dictionary_.Init(custom_words);
 }
 
diff --git a/chrome/renderer/spellchecker/spellcheck.h b/chrome/renderer/spellchecker/spellcheck.h
index 95779c0..7c74bdb 100644
--- a/chrome/renderer/spellchecker/spellcheck.h
+++ b/chrome/renderer/spellchecker/spellcheck.h
@@ -8,10 +8,10 @@
 #include <string>
 #include <vector>
 
+#include "base/files/file.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/platform_file.h"
 #include "base/strings/string16.h"
 #include "chrome/renderer/spellchecker/custom_dictionary_engine.h"
 #include "chrome/renderer/spellchecker/spellcheck_language.h"
@@ -44,7 +44,7 @@
   virtual ~SpellCheck();
 
   // TODO: Try to move that all to SpellcheckLanguage.
-  void Init(base::PlatformFile file,
+  void Init(base::File file,
             const std::set<std::string>& custom_words,
             const std::string& language);
 
diff --git a/chrome/renderer/spellchecker/spellcheck_language.cc b/chrome/renderer/spellchecker/spellcheck_language.cc
index e9d1015..c7ad42d 100644
--- a/chrome/renderer/spellchecker/spellcheck_language.cc
+++ b/chrome/renderer/spellchecker/spellcheck_language.cc
@@ -16,11 +16,9 @@
 SpellcheckLanguage::~SpellcheckLanguage() {
 }
 
-void SpellcheckLanguage::Init(
-    base::PlatformFile file,
-    const std::string& language) {
+void SpellcheckLanguage::Init(base::File file, const std::string& language) {
   DCHECK(platform_spelling_engine_.get());
-  platform_spelling_engine_->Init(file);
+  platform_spelling_engine_->Init(file.Pass());
 
   character_attributes_.SetDefaultLanguage(language);
   text_iterator_.Reset();
diff --git a/chrome/renderer/spellchecker/spellcheck_language.h b/chrome/renderer/spellchecker/spellcheck_language.h
index 0cd2bba..43fbf5b 100644
--- a/chrome/renderer/spellchecker/spellcheck_language.h
+++ b/chrome/renderer/spellchecker/spellcheck_language.h
@@ -9,8 +9,8 @@
 #include <string>
 #include <vector>
 
+#include "base/files/file.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/platform_file.h"
 #include "base/strings/string16.h"
 #include "chrome/renderer/spellchecker/spellcheck_worditerator.h"
 
@@ -21,7 +21,7 @@
   SpellcheckLanguage();
   ~SpellcheckLanguage();
 
-  void Init(base::PlatformFile file, const std::string& language);
+  void Init(base::File file, const std::string& language);
 
   // SpellCheck a word.
   // Returns true if spelled correctly, false otherwise.
diff --git a/chrome/renderer/spellchecker/spellcheck_unittest.cc b/chrome/renderer/spellchecker/spellcheck_unittest.cc
index f17f770..7369f56 100644
--- a/chrome/renderer/spellchecker/spellcheck_unittest.cc
+++ b/chrome/renderer/spellchecker/spellcheck_unittest.cc
@@ -55,17 +55,17 @@
   void InitializeSpellCheck(const std::string& language) {
     base::FilePath hunspell_directory = GetHunspellDirectory();
     EXPECT_FALSE(hunspell_directory.empty());
-    base::PlatformFile file = base::CreatePlatformFile(
+    base::File file(
         chrome::spellcheck_common::GetVersionedFileName(language,
-            hunspell_directory),
-        base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL, NULL);
+                                                        hunspell_directory),
+        base::File::FLAG_OPEN | base::File::FLAG_READ);
 #if defined(OS_MACOSX)
     // TODO(groby): Forcing spellcheck to use hunspell, even on OSX.
     // Instead, tests should exercise individual spelling engines.
     spell_check_->spellcheck_.platform_spelling_engine_.reset(
         new HunspellEngine);
 #endif
-    spell_check_->Init(file, std::set<std::string>(), language);
+    spell_check_->Init(file.Pass(), std::set<std::string>(), language);
   }
 
   void EnableAutoCorrect(bool enable_autocorrect) {
diff --git a/chrome/renderer/spellchecker/spelling_engine.h b/chrome/renderer/spellchecker/spelling_engine.h
index f6e6bff..12e502d 100644
--- a/chrome/renderer/spellchecker/spelling_engine.h
+++ b/chrome/renderer/spellchecker/spelling_engine.h
@@ -8,7 +8,7 @@
 #include <string>
 #include <vector>
 
-#include "base/platform_file.h"
+#include "base/files/file.h"
 #include "base/strings/string16.h"
 
 // Creates the platform's "native" spelling engine.
@@ -21,7 +21,7 @@
 
   // Initialize spelling engine with browser-side info. Must be called before
   // any other functions are called.
-  virtual void Init(base::PlatformFile bdict_file) = 0;
+  virtual void Init(base::File bdict_file) = 0;
   virtual bool InitializeIfNeeded() = 0;
   virtual bool IsEnabled() = 0;
   virtual bool CheckSpelling(const base::string16& word_to_check, int tag) = 0;
diff --git a/chrome/renderer/translate/translate_helper.cc b/chrome/renderer/translate/translate_helper.cc
index ccd2279..fb95cbf 100644
--- a/chrome/renderer/translate/translate_helper.cc
+++ b/chrome/renderer/translate/translate_helper.cc
@@ -4,8 +4,15 @@
 
 #include "chrome/renderer/translate/translate_helper.h"
 
+#if defined(CLD2_DYNAMIC_MODE)
+#include <stdint.h>
+#endif
+
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "base/files/memory_mapped_file.h"
+#endif
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string16.h"
@@ -19,6 +26,12 @@
 #include "components/translate/core/common/translate_util.h"
 #include "components/translate/language_detection/language_detection_util.h"
 #include "content/public/renderer/render_view.h"
+#include "extensions/common/constants.h"
+#include "ipc/ipc_platform_file.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "content/public/common/url_constants.h"
+#include "third_party/cld_2/src/public/compact_lang_det.h"
+#endif
 #include "third_party/WebKit/public/web/WebDocument.h"
 #include "third_party/WebKit/public/web/WebElement.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
@@ -64,6 +77,13 @@
 
 }  // namespace
 
+#if defined(CLD2_DYNAMIC_MODE)
+// The mmap for the CLD2 data must be held forever once it is available in the
+// process. This is declared static in the translate_helper.h.
+base::LazyInstance<TranslateHelper::CLDMmapWrapper>::Leaky
+  TranslateHelper::s_cld_mmap_ = LAZY_INSTANCE_INITIALIZER;
+#endif
+
 ////////////////////////////////////////////////////////////////////////////////
 // TranslateHelper, public:
 //
@@ -71,13 +91,64 @@
     : content::RenderViewObserver(render_view),
       page_id_(-1),
       translation_pending_(false),
-      weak_method_factory_(this) {
+      weak_method_factory_(this)
+#if defined(CLD2_DYNAMIC_MODE)
+      ,cld2_data_file_polling_started_(false),
+      cld2_data_file_polling_canceled_(false),
+      deferred_page_capture_(false),
+      deferred_page_id_(-1),
+      deferred_contents_(ASCIIToUTF16(""))
+#endif
+  {
 }
 
 TranslateHelper::~TranslateHelper() {
   CancelPendingTranslation();
+#if defined(CLD2_DYNAMIC_MODE)
+  CancelCLD2DataFilePolling();
+#endif
 }
 
+void TranslateHelper::PrepareForUrl(const GURL& url) {
+#if defined(CLD2_DYNAMIC_MODE)
+  deferred_page_capture_ = false;
+  deferred_contents_.clear();
+  if (cld2_data_file_polling_started_)
+    return;
+
+  // TODO(andrewhayden): Refactor translate_manager.cc's IsTranslatableURL to
+  // components/translate/core/common/translate_util.cc, and ignore any URL
+  // that fails that check. This will require moving unit tests and rewiring
+  // other function calls as well, so for now replicate the logic here.
+  if (url.is_empty())
+    return;
+  if (url.SchemeIs(content::kChromeUIScheme))
+    return;
+  if (url.SchemeIs(content::kChromeDevToolsScheme))
+    return;
+  if (url.SchemeIs(content::kFtpScheme))
+    return;
+#if defined(OS_CHROMEOS)
+  if (url.SchemeIs(extensions::kExtensionScheme) &&
+      url.DomainIs(file_manager::kFileManagerAppId))
+    return;
+#endif
+
+  // Start polling for CLD data.
+  cld2_data_file_polling_started_ = true;
+  TranslateHelper::SendCLD2DataFileRequest(0, 1000);
+#endif
+}
+
+#if defined(CLD2_DYNAMIC_MODE)
+void TranslateHelper::DeferPageCaptured(const int page_id,
+                                        const base::string16& contents) {
+  deferred_page_capture_ = true;
+  deferred_page_id_ = page_id;
+  deferred_contents_ = contents;
+}
+#endif
+
 void TranslateHelper::PageCaptured(int page_id,
                                    const base::string16& contents) {
   // Get the document language as set by WebKit from the http-equiv
@@ -92,6 +163,17 @@
   WebFrame* main_frame = GetMainFrame();
   if (!main_frame || render_view()->GetPageId() != page_id)
     return;
+
+  // TODO(andrewhayden): UMA insertion point here: Track if data is available.
+  // TODO(andrewhayden): Retry insertion point here, retry till data available.
+#if defined(CLD2_DYNAMIC_MODE)
+  if (!CLD2::isDataLoaded()) {
+    // We're in dynamic mode and CLD data isn't loaded. Retry when CLD data
+    // is loaded, if ever.
+    TranslateHelper::DeferPageCaptured(page_id, contents);
+    return;
+  }
+#endif
   page_id_ = page_id;
   WebDocument document = main_frame->document();
   std::string content_language = document.contentLanguage().utf8();
@@ -136,6 +218,9 @@
   translation_pending_ = false;
   source_lang_.clear();
   target_lang_.clear();
+#if defined(CLD2_DYNAMIC_MODE)
+  CancelCLD2DataFilePolling();
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -310,6 +395,9 @@
   IPC_BEGIN_MESSAGE_MAP(TranslateHelper, message)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_TranslatePage, OnTranslatePage)
     IPC_MESSAGE_HANDLER(ChromeViewMsg_RevertTranslation, OnRevertTranslation)
+#if defined(CLD2_DYNAMIC_MODE)
+    IPC_MESSAGE_HANDLER(ChromeViewMsg_CLDDataAvailable, OnCLDDataAvailable);
+#endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
@@ -499,3 +587,100 @@
 
   return web_view->mainFrame();
 }
+
+#if defined(CLD2_DYNAMIC_MODE)
+void TranslateHelper::CancelCLD2DataFilePolling() {
+  cld2_data_file_polling_canceled_ = true;
+}
+
+void TranslateHelper::SendCLD2DataFileRequest(const int delay_millis,
+                                              const int next_delay_millis) {
+  // Terminate immediately if told to stop polling.
+  if (cld2_data_file_polling_canceled_)
+    return;
+
+  // Terminate immediately if data is already loaded.
+  if (CLD2::isDataLoaded())
+    return;
+
+  // Else, send the IPC message to the browser process requesting the data...
+  Send(new ChromeViewHostMsg_NeedCLDData(routing_id()));
+
+  // ... and enqueue another delayed task to call again. This will start a
+  // chain of polling that will last until the pointer stops being NULL,
+  // which is the right thing to do.
+  // NB: In the great majority of cases, the data file will be available and
+  // the very first delayed task will be a no-op that terminates the chain.
+  // It's only while downloading the file that this will chain for a
+  // nontrivial amount of time.
+  // Use a weak pointer to avoid keeping this helper object around forever.
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&TranslateHelper::SendCLD2DataFileRequest,
+                 weak_method_factory_.GetWeakPtr(),
+                 next_delay_millis, next_delay_millis),
+      base::TimeDelta::FromMilliseconds(delay_millis));
+}
+
+void TranslateHelper::OnCLDDataAvailable(
+    const IPC::PlatformFileForTransit ipc_file_handle,
+    const uint64 data_offset,
+    const uint64 data_length) {
+  LoadCLDDData(ipc_file_handle, data_offset, data_length);
+  if (deferred_page_capture_ && CLD2::isDataLoaded()) {
+    deferred_page_capture_ = false; // Don't do this a second time.
+    PageCaptured(deferred_page_id_, deferred_contents_);
+    deferred_page_id_ = -1; // Clean up for sanity
+    deferred_contents_.clear(); // Clean up for sanity
+  }
+}
+
+void TranslateHelper::LoadCLDDData(
+    const IPC::PlatformFileForTransit ipc_file_handle,
+    const uint64 data_offset,
+    const uint64 data_length) {
+  // Terminate immediately if told to stop polling.
+  if (cld2_data_file_polling_canceled_)
+    return;
+
+  // Terminate immediately if data is already loaded.
+  if (CLD2::isDataLoaded())
+    return;
+
+  // Grab the file handle
+  base::PlatformFile platform_file =
+      IPC::PlatformFileForTransitToPlatformFile(ipc_file_handle);
+  if (platform_file == base::kInvalidPlatformFileValue) {
+    LOG(ERROR) << "Can't find the CLD data file.";
+    return;
+  }
+  base::File basic_file(platform_file);
+
+  // mmap the file
+  s_cld_mmap_.Get().value = new base::MemoryMappedFile();
+  bool initialized = s_cld_mmap_.Get().value->Initialize(basic_file.Pass());
+  if (!initialized) {
+    LOG(ERROR) << "mmap initialization failed";
+    delete s_cld_mmap_.Get().value;
+    s_cld_mmap_.Get().value = NULL;
+    return;
+  }
+
+  // Sanity checks
+  uint64 max_int32 = std::numeric_limits<int32>::max();
+  if (data_length + data_offset > s_cld_mmap_.Get().value->length()
+      || data_length > max_int32) { // max signed 32 bit integer
+    LOG(ERROR) << "Illegal mmap config: data_offset="
+        << data_offset << ", data_length=" << data_length
+        << ", mmap->length()=" << s_cld_mmap_.Get().value->length();
+    delete s_cld_mmap_.Get().value;
+    s_cld_mmap_.Get().value = NULL;
+    return;
+  }
+
+  // Initialize the CLD subsystem... and it's all done!
+  const uint8* data_ptr = s_cld_mmap_.Get().value->data() + data_offset;
+  CLD2::loadDataFromRawAddress(data_ptr, data_length);
+  DCHECK(CLD2::isDataLoaded()) << "Failed to load CLD data from mmap";
+}
+#endif
diff --git a/chrome/renderer/translate/translate_helper.h b/chrome/renderer/translate/translate_helper.h
index 88dd518..b66e399 100644
--- a/chrome/renderer/translate/translate_helper.h
+++ b/chrome/renderer/translate/translate_helper.h
@@ -7,11 +7,21 @@
 
 #include <string>
 
+#if defined(CLD2_DYNAMIC_MODE)
+#include "base/files/memory_mapped_file.h"
+#endif
 #include "base/gtest_prod_util.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "base/lazy_instance.h"
+#endif
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "components/translate/core/common/translate_errors.h"
 #include "content/public/renderer/render_view_observer.h"
+#if defined(CLD2_DYNAMIC_MODE)
+#include "ipc/ipc_platform_file.h"
+#include "url/gurl.h"
+#endif
 
 namespace blink {
 class WebDocument;
@@ -29,6 +39,11 @@
   // Informs us that the page's text has been extracted.
   void PageCaptured(int page_id, const base::string16& contents);
 
+  // Lets the translation system know that we are preparing to navigate to
+  // the specified URL. If there is anything that can or should be done before
+  // this URL loads, this is the time to prepare for it.
+  void PrepareForUrl(const GURL& url);
+
  protected:
   // The following methods are protected so they can be overridden in
   // unit-tests.
@@ -148,6 +163,73 @@
   // Method factory used to make calls to TranslatePageImpl.
   base::WeakPtrFactory<TranslateHelper> weak_method_factory_;
 
+#if defined(CLD2_DYNAMIC_MODE)
+  // Do not ask for CLD data any more.
+  void CancelCLD2DataFilePolling();
+
+  // Invoked when PageCaptured is called prior to obtaining CLD data. This
+  // method stores the page ID into deferred_page_id_ and COPIES the contents
+  // of the page, then sets deferred_page_capture_ to true. When CLD data is
+  // eventually received (in OnCLDDataAvailable), any deferred request will be
+  // "resurrected" and allowed to proceed automatically, assuming that the
+  // page ID has not changed.
+  void DeferPageCaptured(const int page_id, const base::string16& contents);
+
+  // Immediately send an IPC request to the browser process to get the CLD
+  // data file. In most cases, the file will already exist and we will only
+  // poll once; but since the file might need to be downloaded first, poll
+  // indefinitely until a ChromeViewMsg_CLDDataAvailable message is received
+  // from the browser process.
+  // Polling will automatically halt as soon as the renderer obtains a
+  // reference to the data file.
+  void SendCLD2DataFileRequest(const int delay_millis,
+                               const int next_delay_millis);
+
+  // Invoked when a ChromeViewMsg_CLDDataAvailable message is received from
+  // the browser process, providing a file handle for the CLD data file. If a
+  // PageCaptured request was previously deferred with DeferPageCaptured and
+  // the page ID has not yet changed, the PageCaptured is reinvoked to
+  // "resurrect" the language detection pathway.
+  void OnCLDDataAvailable(const IPC::PlatformFileForTransit ipc_file_handle,
+                          const uint64 data_offset,
+                          const uint64 data_length);
+
+  // After receiving data in OnCLDDataAvailable, loads the data into CLD2.
+  void LoadCLDDData(const IPC::PlatformFileForTransit ipc_file_handle,
+                    const uint64 data_offset,
+                    const uint64 data_length);
+
+  // A struct that contains the pointer to the CLD mmap. Used so that we can
+  // leverage LazyInstance:Leaky to properly scope the lifetime of the mmap.
+  struct CLDMmapWrapper {
+    CLDMmapWrapper() {
+      value = NULL;
+    }
+    base::MemoryMappedFile* value;
+  };
+  static base::LazyInstance<CLDMmapWrapper>::Leaky s_cld_mmap_;
+
+  // Whether or not polling for CLD2 data has started.
+  bool cld2_data_file_polling_started_;
+
+  // Whether or not CancelCLD2DataFilePolling has been called.
+  bool cld2_data_file_polling_canceled_;
+
+  // Whether or not a PageCaptured event arrived prior to CLD data becoming
+  // available. If true, deferred_page_id_ contains the most recent page ID
+  // and deferred_contents_ contains the most recent contents.
+  bool deferred_page_capture_;
+
+  // The ID of the page most recently reported to PageCaptured if
+  // deferred_page_capture_ is true.
+  int deferred_page_id_;
+
+  // The contents of the page most recently reported to PageCaptured if
+  // deferred_page_capture_ is true.
+  base::string16 deferred_contents_;
+
+#endif
+
   DISALLOW_COPY_AND_ASSIGN(TranslateHelper);
 };
 
diff --git a/chrome/service/cloud_print/cloud_print_proxy.cc b/chrome/service/cloud_print/cloud_print_proxy.cc
index 9e07db9..6834eb9 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.cc
+++ b/chrome/service/cloud_print/cloud_print_proxy.cc
@@ -143,7 +143,8 @@
   if (backend_.get())
     return false;
 
-  settings_.InitFrom(service_prefs_);
+  ConnectorSettings settings;
+  settings.InitFrom(service_prefs_);
 
   // By default we don't poll for jobs when we lose XMPP connection. But this
   // behavior can be overridden by a preference.
@@ -156,8 +157,8 @@
   oauth_client_info.client_secret =
     google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_CLOUD_PRINT);
   oauth_client_info.redirect_uri = "oob";
-  backend_.reset(new CloudPrintProxyBackend(this, settings_, oauth_client_info,
-                                            enable_job_poll));
+  backend_.reset(new CloudPrintProxyBackend(
+      this, settings, oauth_client_info, enable_job_poll));
   return true;
 }
 
@@ -188,12 +189,25 @@
   info->email.clear();
   if (enabled_)
     info->email = user_email();
-  info->proxy_id = settings_.proxy_id();
-  // If the Cloud Print service is not enabled, we may need to read the old
-  // value of proxy_id from prefs.
-  if (info->proxy_id.empty())
-    info->proxy_id =
-        service_prefs_->GetString(prefs::kCloudPrintProxyId, std::string());
+  ConnectorSettings settings;
+  settings.InitFrom(service_prefs_);
+  info->proxy_id = settings.proxy_id();
+}
+
+void CloudPrintProxy::GetPrinters(std::vector<std::string>* printers) {
+  ConnectorSettings settings;
+  settings.InitFrom(service_prefs_);
+  scoped_refptr<PrintSystem> print_system =
+      PrintSystem::CreateInstance(settings.print_system_settings());
+  if (!print_system)
+    return;
+  PrintSystem::PrintSystemResult result = print_system->Init();
+  if (!result.succeeded())
+    return;
+  printing::PrinterList printer_list;
+  print_system->EnumeratePrinters(&printer_list);
+  for (size_t i = 0; i < printer_list.size(); ++i)
+    printers->push_back(printer_list[i].printer_name);
 }
 
 void CloudPrintProxy::CheckCloudPrintProxyPolicy() {
@@ -253,7 +267,9 @@
   UMA_HISTOGRAM_COUNTS_10000("CloudPrint.UnregisterPrinters",
                              printer_ids.size());
   ShutdownBackend();
-  wipeout_.reset(new CloudPrintWipeout(this, settings_.server_url()));
+  ConnectorSettings settings;
+  settings.InitFrom(service_prefs_);
+  wipeout_.reset(new CloudPrintWipeout(this, settings.server_url()));
   wipeout_->UnregisterPrinters(auth_token, printer_ids);
 }
 
diff --git a/chrome/service/cloud_print/cloud_print_proxy.h b/chrome/service/cloud_print/cloud_print_proxy.h
index 71c2d66..3c6ddbb 100644
--- a/chrome/service/cloud_print/cloud_print_proxy.h
+++ b/chrome/service/cloud_print/cloud_print_proxy.h
@@ -51,6 +51,8 @@
   void DisableForUser();
   // Returns the proxy info.
   void GetProxyInfo(CloudPrintProxyInfo* info);
+  // Return accessible printers.
+  void GetPrinters(std::vector<std::string>* printers);
 
   // Launches a browser to see if the proxy policy has been set.
   void CheckCloudPrintProxyPolicy();
@@ -92,8 +94,6 @@
   // This is set to true when the Cloud Print proxy is enabled and after
   // successful authentication with the Cloud Print service.
   bool enabled_;
-  // Connector settings.
-  ConnectorSettings settings_;
   // This is a cleanup class for unregistering printers on proxy disable.
   scoped_ptr<CloudPrintWipeout> wipeout_;
 
diff --git a/chrome/service/service_ipc_server.cc b/chrome/service/service_ipc_server.cc
index b700c57..987f806 100644
--- a/chrome/service/service_ipc_server.cc
+++ b/chrome/service/service_ipc_server.cc
@@ -100,6 +100,7 @@
     IPC_MESSAGE_HANDLER(ServiceMsg_GetCloudPrintProxyInfo,
                         OnGetCloudPrintProxyInfo)
     IPC_MESSAGE_HANDLER(ServiceMsg_GetHistograms, OnGetHistograms)
+    IPC_MESSAGE_HANDLER(ServiceMsg_GetPrinters, OnGetPrinters)
     IPC_MESSAGE_HANDLER(ServiceMsg_Shutdown, OnShutdown);
     IPC_MESSAGE_HANDLER(ServiceMsg_UpdateAvailable, OnUpdateAvailable);
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -132,6 +133,12 @@
   channel_->Send(new ServiceHostMsg_Histograms(deltas));
 }
 
+void ServiceIPCServer::OnGetPrinters() {
+  std::vector<std::string> printers;
+  g_service_process->GetCloudPrintProxy()->GetPrinters(&printers);
+  channel_->Send(new ServiceHostMsg_Printers(printers));
+}
+
 void ServiceIPCServer::OnDisableCloudPrintProxy() {
   // User disabled CloudPrint proxy explicitly. Delete printers
   // registered from this proxy and disable proxy.
diff --git a/chrome/service/service_ipc_server.h b/chrome/service/service_ipc_server.h
index c265a98..0708f35 100644
--- a/chrome/service/service_ipc_server.h
+++ b/chrome/service/service_ipc_server.h
@@ -60,6 +60,7 @@
       const base::DictionaryValue& user_settings);
   void OnGetCloudPrintProxyInfo();
   void OnGetHistograms();
+  void OnGetPrinters();
   void OnDisableCloudPrintProxy();
 
   void OnShutdown();
diff --git a/chrome/test/base/chrome_render_view_host_test_harness.cc b/chrome/test/base/chrome_render_view_host_test_harness.cc
index 68c10c4..a18ff6e 100644
--- a/chrome/test/base/chrome_render_view_host_test_harness.cc
+++ b/chrome/test/base/chrome_render_view_host_test_harness.cc
@@ -5,6 +5,7 @@
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/fake_signin_manager.h"
 #include "chrome/browser/signin/signin_manager_factory.h"
 #include "chrome/test/base/testing_profile.h"
@@ -38,7 +39,8 @@
 static KeyedService* BuildSigninManagerFake(content::BrowserContext* context) {
   Profile* profile = static_cast<Profile*>(context);
 #if defined (OS_CHROMEOS)
-  SigninManagerBase* signin = new SigninManagerBase();
+  SigninManagerBase* signin = new SigninManagerBase(
+      ChromeSigninClientFactory::GetInstance()->GetForProfile(profile));
   signin->Initialize(profile, NULL);
   return signin;
 #else
diff --git a/chrome/test/base/test_browser_window.h b/chrome/test/base/test_browser_window.h
index 80a90c9..90569d0 100644
--- a/chrome/test/base/test_browser_window.h
+++ b/chrome/test/base/test_browser_window.h
@@ -145,7 +145,8 @@
       GetWebContentsModalDialogHost() OVERRIDE;
   virtual void ShowAvatarBubble(content::WebContents* web_contents,
                                 const gfx::Rect& rect) OVERRIDE {}
-  virtual void ShowAvatarBubbleFromAvatarButton() OVERRIDE {}
+  virtual void ShowAvatarBubbleFromAvatarButton(AvatarBubbleMode mode)
+      OVERRIDE {}
   virtual void ShowPasswordGenerationBubble(
       const gfx::Rect& rect,
       const autofill::PasswordForm& form,
diff --git a/chrome/test/base/testing_profile.cc b/chrome/test/base/testing_profile.cc
index 6352262..11886bb 100644
--- a/chrome/test/base/testing_profile.cc
+++ b/chrome/test/base/testing_profile.cc
@@ -739,6 +739,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) {
   // Always reject requests for testing.
   callback.Run(false);
diff --git a/chrome/test/base/testing_profile.h b/chrome/test/base/testing_profile.h
index 497247d..10f6088 100644
--- a/chrome/test/base/testing_profile.h
+++ b/chrome/test/base/testing_profile.h
@@ -281,6 +281,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) OVERRIDE;
   virtual void CancelMidiSysExPermissionRequest(
         int render_process_id,
diff --git a/chrome/test/base/view_event_test_base.cc b/chrome/test/base/view_event_test_base.cc
index faf6fe4..d8604c9 100644
--- a/chrome/test/base/view_event_test_base.cc
+++ b/chrome/test/base/view_event_test_base.cc
@@ -17,7 +17,6 @@
 #include "ui/compositor/test/context_factories_for_test.h"
 #include "ui/message_center/message_center.h"
 #include "ui/views/view.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #include "ui/views/widget/widget.h"
 
 #if defined(USE_ASH)
@@ -40,6 +39,8 @@
 #include "chromeos/audio/cras_audio_handler.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_handler.h"
+#else  // !defined(OS_CHROMEOS)
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #endif
 
 namespace {
diff --git a/chrome/test/chromedriver/chrome/zip.cc b/chrome/test/chromedriver/chrome/zip.cc
deleted file mode 100644
index 16924e3..0000000
--- a/chrome/test/chromedriver/chrome/zip.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/chromedriver/chrome/zip.h"
-
-#include "base/bind.h"
-#include "base/file_util.h"
-#include "base/files/file_enumerator.h"
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_util.h"
-#include "chrome/test/chromedriver/chrome/zip_internal.h"
-#include "chrome/test/chromedriver/chrome/zip_reader.h"
-#include "net/base/file_stream.h"
-
-#if defined(USE_SYSTEM_MINIZIP)
-#include <minizip/unzip.h>
-#include <minizip/zip.h>
-#else
-#include "third_party/zlib/contrib/minizip/unzip.h"
-#include "third_party/zlib/contrib/minizip/zip.h"
-#endif
-
-namespace {
-
-bool AddFileToZip(zipFile zip_file, const base::FilePath& src_dir) {
-  net::FileStream stream(NULL);
-  int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
-  if (stream.OpenSync(src_dir, flags) != 0) {
-    DLOG(ERROR) << "Could not open stream for path "
-                << src_dir.value();
-    return false;
-  }
-
-  int num_bytes;
-  char buf[zip::internal::kZipBufSize];
-  do {
-    num_bytes = stream.ReadSync(buf, zip::internal::kZipBufSize);
-    if (num_bytes > 0) {
-      if (ZIP_OK != zipWriteInFileInZip(zip_file, buf, num_bytes)) {
-        DLOG(ERROR) << "Could not write data to zip for path "
-                    << src_dir.value();
-        return false;
-      }
-    }
-  } while (num_bytes > 0);
-
-  return true;
-}
-
-bool AddEntryToZip(zipFile zip_file, const base::FilePath& path,
-                   const base::FilePath& root_path) {
-  std::string str_path =
-      path.AsUTF8Unsafe().substr(root_path.value().length() + 1);
-#if defined(OS_WIN)
-  ReplaceSubstringsAfterOffset(&str_path, 0u, "\\", "/");
-#endif
-
-  bool is_directory = base::DirectoryExists(path);
-  if (is_directory)
-    str_path += "/";
-
-  if (ZIP_OK != zipOpenNewFileInZip(
-      zip_file, str_path.c_str(),
-      NULL, NULL, 0u, NULL, 0u, NULL,  // file info, extrafield local, length,
-                                       // extrafield global, length, comment
-      Z_DEFLATED, Z_DEFAULT_COMPRESSION)) {
-    DLOG(ERROR) << "Could not open zip file entry " << str_path;
-    return false;
-  }
-
-  bool success = true;
-  if (!is_directory) {
-    success = AddFileToZip(zip_file, path);
-  }
-
-  if (ZIP_OK != zipCloseFileInZip(zip_file)) {
-    DLOG(ERROR) << "Could not close zip file entry " << str_path;
-    return false;
-  }
-
-  return success;
-}
-
-bool ExcludeNoFilesFilter(const base::FilePath& file_path) {
-  return true;
-}
-
-bool ExcludeHiddenFilesFilter(const base::FilePath& file_path) {
-  return file_path.BaseName().value()[0] != '.';
-}
-
-}  // namespace
-
-namespace zip {
-
-bool Unzip(const base::FilePath& src_file, const base::FilePath& dest_dir) {
-  ZipReader reader;
-  if (!reader.Open(src_file)) {
-    DLOG(WARNING) << "Failed to open " << src_file.value();
-    return false;
-  }
-  while (reader.HasMore()) {
-    if (!reader.OpenCurrentEntryInZip()) {
-      DLOG(WARNING) << "Failed to open the current file in zip";
-      return false;
-    }
-    if (reader.current_entry_info()->is_unsafe()) {
-      DLOG(WARNING) << "Found an unsafe file in zip "
-                    << reader.current_entry_info()->file_path().value();
-      return false;
-    }
-    if (!reader.ExtractCurrentEntryIntoDirectory(dest_dir)) {
-      DLOG(WARNING) << "Failed to extract "
-                    << reader.current_entry_info()->file_path().value();
-      return false;
-    }
-    if (!reader.AdvanceToNextEntry()) {
-      DLOG(WARNING) << "Failed to advance to the next file";
-      return false;
-    }
-  }
-  return true;
-}
-
-bool ZipWithFilterCallback(const base::FilePath& src_dir,
-                           const base::FilePath& dest_file,
-                           const FilterCallback& filter_cb) {
-  DCHECK(base::DirectoryExists(src_dir));
-
-  zipFile zip_file = internal::OpenForZipping(dest_file.AsUTF8Unsafe(),
-                                              APPEND_STATUS_CREATE);
-
-  if (!zip_file) {
-    DLOG(WARNING) << "couldn't create file " << dest_file.value();
-    return false;
-  }
-
-  bool success = true;
-  base::FileEnumerator file_enumerator(src_dir, true /* recursive */,
-      base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES);
-  for (base::FilePath path = file_enumerator.Next(); !path.value().empty();
-       path = file_enumerator.Next()) {
-    if (!filter_cb.Run(path)) {
-      continue;
-    }
-
-    if (!AddEntryToZip(zip_file, path, src_dir)) {
-      success = false;
-      return false;
-    }
-  }
-
-  if (ZIP_OK != zipClose(zip_file, NULL)) {
-    DLOG(ERROR) << "Error closing zip file " << dest_file.value();
-    return false;
-  }
-
-  return success;
-}
-
-bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
-         bool include_hidden_files) {
-  if (include_hidden_files) {
-    return ZipWithFilterCallback(
-        src_dir, dest_file, base::Bind(&ExcludeNoFilesFilter));
-  } else {
-    return ZipWithFilterCallback(
-        src_dir, dest_file, base::Bind(&ExcludeHiddenFilesFilter));
-  }
-}
-
-#if defined(OS_POSIX)
-bool ZipFiles(const base::FilePath& src_dir,
-              const std::vector<base::FilePath>& src_relative_paths,
-              int dest_fd) {
-  DCHECK(base::DirectoryExists(src_dir));
-  zipFile zip_file = internal::OpenFdForZipping(dest_fd, APPEND_STATUS_CREATE);
-
-  if (!zip_file) {
-    DLOG(ERROR) << "couldn't create file for fd " << dest_fd;
-    return false;
-  }
-
-  bool success = true;
-  for (std::vector<base::FilePath>::const_iterator iter =
-           src_relative_paths.begin();
-      iter != src_relative_paths.end(); ++iter) {
-    const base::FilePath& path = src_dir.Append(*iter);
-    if (!AddEntryToZip(zip_file, path, src_dir)) {
-      // TODO(hshi): clean up the partial zip file when error occurs.
-      success = false;
-      break;
-    }
-  }
-
-  if (ZIP_OK != zipClose(zip_file, NULL)) {
-    DLOG(ERROR) << "Error closing zip file for fd " << dest_fd;
-    success = false;
-  }
-
-  return success;
-}
-#endif  // defined(OS_POSIX)
-
-}  // namespace zip
diff --git a/chrome/test/chromedriver/chrome/zip.h b/chrome/test/chromedriver/chrome/zip.h
deleted file mode 100644
index 744509b..0000000
--- a/chrome/test/chromedriver/chrome/zip.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_H_
-#define CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_H_
-
-#include "base/callback.h"
-#include "base/files/file_path.h"
-
-namespace zip {
-
-// Zip the contents of src_dir into dest_file. src_path must be a directory.
-// An entry will *not* be created in the zip for the root folder -- children
-// of src_dir will be at the root level of the created zip. For each file in
-// src_dir, include it only if the callback |filter_cb| returns true. Otherwise
-// omit it.
-typedef base::Callback<bool(const base::FilePath&)> FilterCallback;
-bool ZipWithFilterCallback(const base::FilePath& src_dir,
-                           const base::FilePath& dest_file,
-                           const FilterCallback& filter_cb);
-
-// Convenience method for callers who don't need to set up the filter callback.
-// If |include_hidden_files| is true, files starting with "." are included.
-// Otherwise they are omitted.
-bool Zip(const base::FilePath& src_dir, const base::FilePath& dest_file,
-         bool include_hidden_files);
-
-#if defined(OS_POSIX)
-// Zips files listed in |src_relative_paths| to destination specified by file
-// descriptor |dest_fd|. The paths listed in |src_relative_paths| are relative
-// to the |src_dir| and will be used as the file names in the created zip file.
-// All source paths must be under |src_dir| in the file system hierarchy.
-bool ZipFiles(const base::FilePath& src_dir,
-              const std::vector<base::FilePath>& src_relative_paths,
-              int dest_fd);
-#endif  // defined(OS_POSIX)
-
-// Unzip the contents of zip_file into dest_dir.
-bool Unzip(const base::FilePath& zip_file, const base::FilePath& dest_dir);
-
-}  // namespace zip
-
-#endif  // CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_H_
diff --git a/chrome/test/chromedriver/chrome/zip_internal.cc b/chrome/test/chromedriver/chrome/zip_internal.cc
deleted file mode 100644
index 18b1cce..0000000
--- a/chrome/test/chromedriver/chrome/zip_internal.cc
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/chromedriver/chrome/zip.h"
-
-#include <algorithm>
-
-#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-
-#if defined(USE_SYSTEM_MINIZIP)
-#include <minizip/unzip.h>
-#include <minizip/zip.h>
-#include <minizip/ioapi.h>
-#else
-#include "third_party/zlib/contrib/minizip/unzip.h"
-#include "third_party/zlib/contrib/minizip/zip.h"
-#if defined(OS_WIN)
-#include "third_party/zlib/contrib/minizip/iowin32.h"
-#elif defined(OS_POSIX)
-#include "third_party/zlib/contrib/minizip/ioapi.h"
-#endif  // defined(OS_POSIX)
-#endif  // defined(USE_SYSTEM_MINIZIP)
-
-namespace {
-
-#if defined(OS_WIN)
-typedef struct {
-  HANDLE hf;
-  int error;
-} WIN32FILE_IOWIN;
-
-// This function is derived from third_party/minizip/iowin32.c.
-// Its only difference is that it treats the char* as UTF8 and
-// uses the Unicode version of CreateFile.
-void* ZipOpenFunc(void *opaque, const char* filename, int mode) {
-  DWORD desired_access, creation_disposition;
-  DWORD share_mode, flags_and_attributes;
-  HANDLE file = 0;
-  void* ret = NULL;
-
-  desired_access = share_mode = flags_and_attributes = 0;
-
-  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ) {
-    desired_access = GENERIC_READ;
-    creation_disposition = OPEN_EXISTING;
-    share_mode = FILE_SHARE_READ;
-  } else if (mode & ZLIB_FILEFUNC_MODE_EXISTING) {
-    desired_access = GENERIC_WRITE | GENERIC_READ;
-    creation_disposition = OPEN_EXISTING;
-  } else if (mode & ZLIB_FILEFUNC_MODE_CREATE) {
-    desired_access = GENERIC_WRITE | GENERIC_READ;
-    creation_disposition = CREATE_ALWAYS;
-  }
-
-  base::string16 filename16 = base::UTF8ToUTF16(filename);
-  if ((filename != NULL) && (desired_access != 0)) {
-    file = CreateFile(filename16.c_str(), desired_access, share_mode,
-        NULL, creation_disposition, flags_and_attributes, NULL);
-  }
-
-  if (file == INVALID_HANDLE_VALUE)
-    file = NULL;
-
-  if (file != NULL) {
-    WIN32FILE_IOWIN file_ret;
-    file_ret.hf = file;
-    file_ret.error = 0;
-    ret = malloc(sizeof(WIN32FILE_IOWIN));
-    if (ret == NULL)
-      CloseHandle(file);
-    else
-      *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret;
-  }
-  return ret;
-}
-#endif
-
-#if defined(OS_POSIX)
-// Callback function for zlib that opens a file stream from a file descriptor.
-void* FdOpenFileFunc(void* opaque, const char* filename, int mode) {
-  FILE* file = NULL;
-  const char* mode_fopen = NULL;
-
-  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
-    mode_fopen = "rb";
-  else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
-    mode_fopen = "r+b";
-  else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
-    mode_fopen = "wb";
-
-  if ((filename != NULL) && (mode_fopen != NULL))
-    file = fdopen(*static_cast<int*>(opaque), mode_fopen);
-
-  return file;
-}
-
-// We don't actually close the file stream since that would close
-// the underlying file descriptor, and we don't own it. However we do need to
-// flush buffers and free |opaque| since we malloc'ed it in FillFdOpenFileFunc.
-int CloseFileFunc(void* opaque, void* stream) {
-  fflush(static_cast<FILE*>(stream));
-  free(opaque);
-  return 0;
-}
-
-// Fills |pzlib_filecunc_def| appropriately to handle the zip file
-// referred to by |fd|.
-void FillFdOpenFileFunc(zlib_filefunc_def* pzlib_filefunc_def, int fd) {
-  fill_fopen_filefunc(pzlib_filefunc_def);
-  pzlib_filefunc_def->zopen_file = FdOpenFileFunc;
-  pzlib_filefunc_def->zclose_file = CloseFileFunc;
-  int* ptr_fd = static_cast<int*>(malloc(sizeof(fd)));
-  *ptr_fd = fd;
-  pzlib_filefunc_def->opaque = ptr_fd;
-}
-#endif  // defined(OS_POSIX)
-
-#if defined(OS_WIN)
-// Callback function for zlib that opens a file stream from a Windows handle.
-void* HandleOpenFileFunc(void* opaque, const char* filename, int mode) {
-  WIN32FILE_IOWIN file_ret;
-  file_ret.hf = static_cast<HANDLE>(opaque);
-  file_ret.error = 0;
-  if (file_ret.hf == INVALID_HANDLE_VALUE)
-    return NULL;
-
-  void* ret = malloc(sizeof(WIN32FILE_IOWIN));
-  if (ret != NULL)
-    *(static_cast<WIN32FILE_IOWIN*>(ret)) = file_ret;
-  return ret;
-}
-#endif
-
-// A struct that contains data required for zlib functions to extract files from
-// a zip archive stored in memory directly. The following I/O API functions
-// expect their opaque parameters refer to this struct.
-struct ZipBuffer {
-  const char* data;  // weak
-  size_t length;
-  size_t offset;
-};
-
-// Opens the specified file. When this function returns a non-NULL pointer, zlib
-// uses this pointer as a stream parameter while compressing or uncompressing
-// data. (Returning NULL represents an error.) This function initializes the
-// given opaque parameter and returns it because this parameter stores all
-// information needed for uncompressing data. (This function does not support
-// writing compressed data and it returns NULL for this case.)
-void* OpenZipBuffer(void* opaque, const char* /*filename*/, int mode) {
-  if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) != ZLIB_FILEFUNC_MODE_READ) {
-    NOTREACHED();
-    return NULL;
-  }
-  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
-  if (!buffer || !buffer->data || !buffer->length)
-    return NULL;
-  buffer->offset = 0;
-  return opaque;
-}
-
-// Reads compressed data from the specified stream. This function copies data
-// referred by the opaque parameter and returns the size actually copied.
-uLong ReadZipBuffer(void* opaque, void* /*stream*/, void* buf, uLong size) {
-  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
-  if (!buffer)
-    return 0;
-  DCHECK_LE(buffer->offset, buffer->length);
-  size_t remaining_bytes = buffer->length - buffer->offset;
-  if (!buffer->data || !remaining_bytes)
-    return 0;
-  size = std::min(size, static_cast<uLong>(remaining_bytes));
-  memcpy(buf, &buffer->data[buffer->offset], size);
-  buffer->offset += size;
-  return size;
-}
-
-// Writes compressed data to the stream. This function always returns zero
-// because this implementation is only for reading compressed data.
-uLong WriteZipBuffer(void* /*opaque*/,
-                     void* /*stream*/,
-                     const void* /*buf*/,
-                     uLong /*size*/) {
-  NOTREACHED();
-  return 0;
-}
-
-// Returns the offset from the beginning of the data.
-long GetOffsetOfZipBuffer(void* opaque, void* /*stream*/) {
-  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
-  if (!buffer)
-    return -1;
-  return static_cast<long>(buffer->offset);
-}
-
-// Moves the current offset to the specified position.
-long SeekZipBuffer(void* opaque, void* /*stream*/, uLong offset, int origin) {
-  ZipBuffer* buffer = static_cast<ZipBuffer*>(opaque);
-  if (!buffer)
-    return -1;
-  if (origin == ZLIB_FILEFUNC_SEEK_CUR) {
-    buffer->offset = std::min(buffer->offset + static_cast<size_t>(offset),
-                              buffer->length);
-    return 0;
-  }
-  if (origin == ZLIB_FILEFUNC_SEEK_END) {
-    buffer->offset = (buffer->length > offset) ? buffer->length - offset : 0;
-    return 0;
-  }
-  if (origin == ZLIB_FILEFUNC_SEEK_SET) {
-    buffer->offset = std::min(buffer->length, static_cast<size_t>(offset));
-    return 0;
-  }
-  NOTREACHED();
-  return -1;
-}
-
-// Closes the input offset and deletes all resources used for compressing or
-// uncompressing data. This function deletes the ZipBuffer object referred by
-// the opaque parameter since zlib deletes the unzFile object and it does not
-// use this object any longer.
-int CloseZipBuffer(void* opaque, void* /*stream*/) {
-  if (opaque)
-    free(opaque);
-  return 0;
-}
-
-// Returns the last error happened when reading or writing data. This function
-// always returns zero, which means there are not any errors.
-int GetErrorOfZipBuffer(void* /*opaque*/, void* /*stream*/) {
-  return 0;
-}
-
-}  // namespace
-
-namespace zip {
-namespace internal {
-
-unzFile OpenForUnzipping(const std::string& file_name_utf8) {
-  zlib_filefunc_def* zip_func_ptrs = NULL;
-#if defined(OS_WIN)
-  zlib_filefunc_def zip_funcs;
-  fill_win32_filefunc(&zip_funcs);
-  zip_funcs.zopen_file = ZipOpenFunc;
-  zip_func_ptrs = &zip_funcs;
-#endif
-  return unzOpen2(file_name_utf8.c_str(), zip_func_ptrs);
-}
-
-#if defined(OS_POSIX)
-unzFile OpenFdForUnzipping(int zip_fd) {
-  zlib_filefunc_def zip_funcs;
-  FillFdOpenFileFunc(&zip_funcs, zip_fd);
-  // Passing dummy "fd" filename to zlib.
-  return unzOpen2("fd", &zip_funcs);
-}
-#endif
-
-#if defined(OS_WIN)
-unzFile OpenHandleForUnzipping(HANDLE zip_handle) {
-  zlib_filefunc_def zip_funcs;
-  fill_win32_filefunc(&zip_funcs);
-  zip_funcs.zopen_file = HandleOpenFileFunc;
-  zip_funcs.opaque = zip_handle;
-  return unzOpen2("fd", &zip_funcs);
-}
-#endif
-
-// static
-unzFile PreprareMemoryForUnzipping(const std::string& data) {
-  if (data.empty())
-    return NULL;
-
-  ZipBuffer* buffer = static_cast<ZipBuffer*>(malloc(sizeof(ZipBuffer)));
-  if (!buffer)
-    return NULL;
-  buffer->data = data.data();
-  buffer->length = data.length();
-  buffer->offset = 0;
-
-  zlib_filefunc_def zip_functions;
-  zip_functions.zopen_file = OpenZipBuffer;
-  zip_functions.zread_file = ReadZipBuffer;
-  zip_functions.zwrite_file = WriteZipBuffer;
-  zip_functions.ztell_file = GetOffsetOfZipBuffer;
-  zip_functions.zseek_file = SeekZipBuffer;
-  zip_functions.zclose_file = CloseZipBuffer;
-  zip_functions.zerror_file = GetErrorOfZipBuffer;
-  zip_functions.opaque = static_cast<void*>(buffer);
-  return unzOpen2(NULL, &zip_functions);
-}
-
-zipFile OpenForZipping(const std::string& file_name_utf8, int append_flag) {
-  zlib_filefunc_def* zip_func_ptrs = NULL;
-#if defined(OS_WIN)
-  zlib_filefunc_def zip_funcs;
-  fill_win32_filefunc(&zip_funcs);
-  zip_funcs.zopen_file = ZipOpenFunc;
-  zip_func_ptrs = &zip_funcs;
-#endif
-  return zipOpen2(file_name_utf8.c_str(),
-                  append_flag,
-                  NULL,  // global comment
-                  zip_func_ptrs);
-}
-
-#if defined(OS_POSIX)
-zipFile OpenFdForZipping(int zip_fd, int append_flag) {
-  zlib_filefunc_def zip_funcs;
-  FillFdOpenFileFunc(&zip_funcs, zip_fd);
-  // Passing dummy "fd" filename to zlib.
-  return zipOpen2("fd", append_flag, NULL, &zip_funcs);
-}
-#endif
-
-}  // namespace internal
-}  // namespace zip
diff --git a/chrome/test/chromedriver/chrome/zip_internal.h b/chrome/test/chromedriver/chrome/zip_internal.h
deleted file mode 100644
index 8a1f703..0000000
--- a/chrome/test/chromedriver/chrome/zip_internal.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_INTERNAL_H_
-#define CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_INTERNAL_H_
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#include <string>
-
-#if defined(USE_SYSTEM_MINIZIP)
-#include <minizip/unzip.h>
-#include <minizip/zip.h>
-#else
-#include "third_party/zlib/contrib/minizip/unzip.h"
-#include "third_party/zlib/contrib/minizip/zip.h"
-#endif
-
-// Utility functions and constants used internally for the zip file
-// library in the directory. Don't use them outside of the library.
-namespace zip {
-namespace internal {
-
-// Opens the given file name in UTF-8 for unzipping, with some setup for
-// Windows.
-unzFile OpenForUnzipping(const std::string& file_name_utf8);
-
-#if defined(OS_POSIX)
-// Opens the file referred to by |zip_fd| for unzipping.
-unzFile OpenFdForUnzipping(int zip_fd);
-#endif
-
-#if defined(OS_WIN)
-// Opens the file referred to by |zip_handle| for unzipping.
-unzFile OpenHandleForUnzipping(HANDLE zip_handle);
-#endif
-
-// Creates a custom unzFile object which reads data from the specified string.
-// This custom unzFile object overrides the I/O API functions of zlib so it can
-// read data from the specified string.
-unzFile PreprareMemoryForUnzipping(const std::string& data);
-
-// Opens the given file name in UTF-8 for zipping, with some setup for
-// Windows. |append_flag| will be passed to zipOpen2().
-zipFile OpenForZipping(const std::string& file_name_utf8, int append_flag);
-
-#if defined(OS_POSIX)
-// Opens the file referred to by |zip_fd| for zipping. |append_flag| will be
-// passed to zipOpen2().
-zipFile OpenFdForZipping(int zip_fd, int append_flag);
-#endif
-
-const int kZipMaxPath = 256;
-const int kZipBufSize = 8192;
-
-}  // namespace internal
-}  // namespace zip
-
-#endif  // CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_INTERNAL_H_
diff --git a/chrome/test/chromedriver/chrome/zip_reader.cc b/chrome/test/chromedriver/chrome/zip_reader.cc
deleted file mode 100644
index 718aea5..0000000
--- a/chrome/test/chromedriver/chrome/zip_reader.cc
+++ /dev/null
@@ -1,310 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/test/chromedriver/chrome/zip_reader.h"
-
-#include "base/file_util.h"
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/test/chromedriver/chrome/zip_internal.h"
-#include "net/base/file_stream.h"
-
-#if defined(USE_SYSTEM_MINIZIP)
-#include <minizip/unzip.h>
-#else
-#include "third_party/zlib/contrib/minizip/unzip.h"
-#if defined(OS_WIN)
-#include "third_party/zlib/contrib/minizip/iowin32.h"
-#endif  // defined(OS_WIN)
-#endif  // defined(USE_SYSTEM_MINIZIP)
-
-namespace zip {
-
-// TODO(satorux): The implementation assumes that file names in zip files
-// are encoded in UTF-8. This is true for zip files created by Zip()
-// function in zip.h, but not true for user-supplied random zip files.
-ZipReader::EntryInfo::EntryInfo(const std::string& file_name_in_zip,
-                                const unz_file_info& raw_file_info)
-    : file_path_(base::FilePath::FromUTF8Unsafe(file_name_in_zip)),
-      is_directory_(false) {
-  original_size_ = raw_file_info.uncompressed_size;
-
-  // Directory entries in zip files end with "/".
-  is_directory_ = EndsWith(file_name_in_zip, "/", false);
-
-  // Check the file name here for directory traversal issues. In the name of
-  // simplicity and security, we might reject a valid file name such as "a..b".
-  is_unsafe_ = file_name_in_zip.find("..") != std::string::npos;
-
-  // We also consider that the file name is unsafe, if it's invalid UTF-8.
-  base::string16 file_name_utf16;
-  if (!base::UTF8ToUTF16(file_name_in_zip.data(), file_name_in_zip.size(),
-                         &file_name_utf16)) {
-    is_unsafe_ = true;
-  }
-
-  // We also consider that the file name is unsafe, if it's absolute.
-  // On Windows, IsAbsolute() returns false for paths starting with "/".
-  if (file_path_.IsAbsolute() || StartsWithASCII(file_name_in_zip, "/", false))
-    is_unsafe_ = true;
-
-  // Construct the last modified time. The timezone info is not present in
-  // zip files, so we construct the time as local time.
-  base::Time::Exploded exploded_time = {};  // Zero-clear.
-  exploded_time.year = raw_file_info.tmu_date.tm_year;
-  // The month in zip file is 0-based, whereas ours is 1-based.
-  exploded_time.month = raw_file_info.tmu_date.tm_mon + 1;
-  exploded_time.day_of_month = raw_file_info.tmu_date.tm_mday;
-  exploded_time.hour = raw_file_info.tmu_date.tm_hour;
-  exploded_time.minute = raw_file_info.tmu_date.tm_min;
-  exploded_time.second = raw_file_info.tmu_date.tm_sec;
-  exploded_time.millisecond = 0;
-  if (exploded_time.HasValidValues()) {
-    last_modified_ = base::Time::FromLocalExploded(exploded_time);
-  } else {
-    // Use Unix time epoch if the time stamp data is invalid.
-    last_modified_ = base::Time::UnixEpoch();
-  }
-}
-
-ZipReader::ZipReader() {
-  Reset();
-}
-
-ZipReader::~ZipReader() {
-  Close();
-}
-
-bool ZipReader::Open(const base::FilePath& zip_file_path) {
-  DCHECK(!zip_file_);
-
-  // Use of "Unsafe" function does not look good, but there is no way to do
-  // this safely on Linux. See file_util.h for details.
-  zip_file_ = internal::OpenForUnzipping(zip_file_path.AsUTF8Unsafe());
-  if (!zip_file_) {
-    return false;
-  }
-
-  return OpenInternal();
-}
-
-bool ZipReader::OpenFromPlatformFile(base::PlatformFile zip_fd) {
-  DCHECK(!zip_file_);
-
-#if defined(OS_POSIX)
-  zip_file_ = internal::OpenFdForUnzipping(zip_fd);
-#elif defined(OS_WIN)
-  zip_file_ = internal::OpenHandleForUnzipping(zip_fd);
-#endif
-  if (!zip_file_) {
-    return false;
-  }
-
-  return OpenInternal();
-}
-
-bool ZipReader::OpenFromString(const std::string& data) {
-  zip_file_ = internal::PreprareMemoryForUnzipping(data);
-  if (!zip_file_)
-    return false;
-  return OpenInternal();
-}
-
-void ZipReader::Close() {
-  if (zip_file_) {
-    unzClose(zip_file_);
-  }
-  Reset();
-}
-
-bool ZipReader::HasMore() {
-  return !reached_end_;
-}
-
-bool ZipReader::AdvanceToNextEntry() {
-  DCHECK(zip_file_);
-
-  // Should not go further if we already reached the end.
-  if (reached_end_)
-    return false;
-
-  unz_file_pos position = {};
-  if (unzGetFilePos(zip_file_, &position) != UNZ_OK)
-    return false;
-  const int current_entry_index = position.num_of_file;
-  // If we are currently at the last entry, then the next position is the
-  // end of the zip file, so mark that we reached the end.
-  if (current_entry_index + 1 == num_entries_) {
-    reached_end_ = true;
-  } else {
-    DCHECK_LT(current_entry_index + 1, num_entries_);
-    if (unzGoToNextFile(zip_file_) != UNZ_OK) {
-      return false;
-    }
-  }
-  current_entry_info_.reset();
-  return true;
-}
-
-bool ZipReader::OpenCurrentEntryInZip() {
-  DCHECK(zip_file_);
-
-  unz_file_info raw_file_info = {};
-  char raw_file_name_in_zip[internal::kZipMaxPath] = {};
-  const int result = unzGetCurrentFileInfo(zip_file_,
-                                           &raw_file_info,
-                                           raw_file_name_in_zip,
-                                           sizeof(raw_file_name_in_zip) - 1,
-                                           NULL,  // extraField.
-                                           0,  // extraFieldBufferSize.
-                                           NULL,  // szComment.
-                                           0);  // commentBufferSize.
-  if (result != UNZ_OK)
-    return false;
-  if (raw_file_name_in_zip[0] == '\0')
-    return false;
-  current_entry_info_.reset(
-      new EntryInfo(raw_file_name_in_zip, raw_file_info));
-  return true;
-}
-
-bool ZipReader::LocateAndOpenEntry(const base::FilePath& path_in_zip) {
-  DCHECK(zip_file_);
-
-  current_entry_info_.reset();
-  reached_end_ = false;
-  const int kDefaultCaseSensivityOfOS = 0;
-  const int result = unzLocateFile(zip_file_,
-                                   path_in_zip.AsUTF8Unsafe().c_str(),
-                                   kDefaultCaseSensivityOfOS);
-  if (result != UNZ_OK)
-    return false;
-
-  // Then Open the entry.
-  return OpenCurrentEntryInZip();
-}
-
-bool ZipReader::ExtractCurrentEntryToFilePath(
-    const base::FilePath& output_file_path) {
-  DCHECK(zip_file_);
-
-  // If this is a directory, just create it and return.
-  if (current_entry_info()->is_directory())
-    return base::CreateDirectory(output_file_path);
-
-  const int open_result = unzOpenCurrentFile(zip_file_);
-  if (open_result != UNZ_OK)
-    return false;
-
-  // We can't rely on parent directory entries being specified in the
-  // zip, so we make sure they are created.
-  base::FilePath output_dir_path = output_file_path.DirName();
-  if (!base::CreateDirectory(output_dir_path))
-    return false;
-
-  net::FileStream stream(NULL);
-  const int flags = (base::PLATFORM_FILE_CREATE_ALWAYS |
-                     base::PLATFORM_FILE_WRITE);
-  if (stream.OpenSync(output_file_path, flags) != 0)
-    return false;
-
-  bool success = true;  // This becomes false when something bad happens.
-  while (true) {
-    char buf[internal::kZipBufSize];
-    const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
-                                                  internal::kZipBufSize);
-    if (num_bytes_read == 0) {
-      // Reached the end of the file.
-      break;
-    } else if (num_bytes_read < 0) {
-      // If num_bytes_read < 0, then it's a specific UNZ_* error code.
-      success = false;
-      break;
-    } else if (num_bytes_read > 0) {
-      // Some data is read. Write it to the output file.
-      if (num_bytes_read != stream.WriteSync(buf, num_bytes_read)) {
-        success = false;
-        break;
-      }
-    }
-  }
-
-  unzCloseCurrentFile(zip_file_);
-  return success;
-}
-
-bool ZipReader::ExtractCurrentEntryIntoDirectory(
-    const base::FilePath& output_directory_path) {
-  DCHECK(current_entry_info_.get());
-
-  base::FilePath output_file_path = output_directory_path.Append(
-      current_entry_info()->file_path());
-  return ExtractCurrentEntryToFilePath(output_file_path);
-}
-
-#if defined(OS_POSIX)
-bool ZipReader::ExtractCurrentEntryToFd(const int fd) {
-  DCHECK(zip_file_);
-
-  // If this is a directory, there's nothing to extract to the file descriptor,
-  // so return false.
-  if (current_entry_info()->is_directory())
-    return false;
-
-  const int open_result = unzOpenCurrentFile(zip_file_);
-  if (open_result != UNZ_OK)
-    return false;
-
-  bool success = true;  // This becomes false when something bad happens.
-  while (true) {
-    char buf[internal::kZipBufSize];
-    const int num_bytes_read = unzReadCurrentFile(zip_file_, buf,
-                                                  internal::kZipBufSize);
-    if (num_bytes_read == 0) {
-      // Reached the end of the file.
-      break;
-    } else if (num_bytes_read < 0) {
-      // If num_bytes_read < 0, then it's a specific UNZ_* error code.
-      success = false;
-      break;
-    } else if (num_bytes_read > 0) {
-      // Some data is read. Write it to the output file descriptor.
-      if (num_bytes_read !=
-          base::WriteFileDescriptor(fd, buf, num_bytes_read)) {
-        success = false;
-        break;
-      }
-    }
-  }
-
-  unzCloseCurrentFile(zip_file_);
-  return success;
-}
-#endif  // defined(OS_POSIX)
-
-bool ZipReader::OpenInternal() {
-  DCHECK(zip_file_);
-
-  unz_global_info zip_info = {};  // Zero-clear.
-  if (unzGetGlobalInfo(zip_file_, &zip_info) != UNZ_OK) {
-    return false;
-  }
-  num_entries_ = zip_info.number_entry;
-  if (num_entries_ < 0)
-    return false;
-
-  // We are already at the end if the zip file is empty.
-  reached_end_ = (num_entries_ == 0);
-  return true;
-}
-
-void ZipReader::Reset() {
-  zip_file_ = NULL;
-  num_entries_ = 0;
-  reached_end_ = false;
-  current_entry_info_.reset();
-}
-
-}  // namespace zip
diff --git a/chrome/test/chromedriver/chrome/zip_reader.h b/chrome/test/chromedriver/chrome/zip_reader.h
deleted file mode 100644
index 451968e..0000000
--- a/chrome/test/chromedriver/chrome/zip_reader.h
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_READER_H_
-#define CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_READER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/platform_file.h"
-#include "base/time/time.h"
-
-#if defined(USE_SYSTEM_MINIZIP)
-#include <minizip/unzip.h>
-#else
-#include "third_party/zlib/contrib/minizip/unzip.h"
-#endif
-
-namespace zip {
-
-// This class is used for reading zip files. A typical use case of this
-// class is to scan entries in a zip file and extract them. The code will
-// look like:
-//
-//   ZipReader reader;
-//   reader.Open(zip_file_path);
-//   while (reader.HasMore()) {
-//     reader.OpenCurrentEntryInZip();
-//     reader.ExtractCurrentEntryToDirectory(output_directory_path);
-//     reader.AdvanceToNextEntry();
-//   }
-//
-// For simplicty, error checking is omitted in the example code above. The
-// production code should check return values from all of these functions.
-//
-// This calls can also be used for random access of contents in a zip file
-// using LocateAndOpenEntry().
-//
-class ZipReader {
- public:
-  // This class represents information of an entry (file or directory) in
-  // a zip file.
-  class EntryInfo {
-   public:
-    EntryInfo(const std::string& filename_in_zip,
-              const unz_file_info& raw_file_info);
-
-    // Returns the file path. The path is usually relative like
-    // "foo/bar.txt", but if it's absolute, is_unsafe() returns true.
-    const base::FilePath& file_path() const { return file_path_; }
-
-    // Returns the size of the original file (i.e. after uncompressed).
-    // Returns 0 if the entry is a directory.
-    int64 original_size() const { return original_size_; }
-
-    // Returns the last modified time.
-    base::Time last_modified() const { return last_modified_; }
-
-    // Returns true if the entry is a directory.
-    bool is_directory() const { return is_directory_; }
-
-    // Returns true if the entry is unsafe, like having ".." or invalid
-    // UTF-8 characters in its file name, or the file path is absolute.
-    bool is_unsafe() const { return is_unsafe_; }
-
-   private:
-    const base::FilePath file_path_;
-    int64 original_size_;
-    base::Time last_modified_;
-    bool is_directory_;
-    bool is_unsafe_;
-    DISALLOW_COPY_AND_ASSIGN(EntryInfo);
-  };
-
-  ZipReader();
-  ~ZipReader();
-
-  // Opens the zip file specified by |zip_file_path|. Returns true on
-  // success.
-  bool Open(const base::FilePath& zip_file_path);
-
-  // Opens the zip file referred to by the platform file |zip_fd|.
-  // Returns true on success.
-  bool OpenFromPlatformFile(base::PlatformFile zip_fd);
-
-  // Opens the zip data stored in |data|. This class uses a weak reference to
-  // the given sring while extracting files, i.e. the caller should keep the
-  // string until it finishes extracting files.
-  bool OpenFromString(const std::string& data);
-
-  // Closes the currently opened zip file. This function is called in the
-  // destructor of the class, so you usually don't need to call this.
-  void Close();
-
-  // Returns true if there is at least one entry to read. This function is
-  // used to scan entries with AdvanceToNextEntry(), like:
-  //
-  // while (reader.HasMore()) {
-  //   // Do something with the current file here.
-  //   reader.AdvanceToNextEntry();
-  // }
-  bool HasMore();
-
-  // Advances the next entry. Returns true on success.
-  bool AdvanceToNextEntry();
-
-  // Opens the current entry in the zip file. On success, returns true and
-  // updates the the current entry state (i.e. current_entry_info() is
-  // updated). This function should be called before operations over the
-  // current entry like ExtractCurrentEntryToFile().
-  //
-  // Note that there is no CloseCurrentEntryInZip(). The the current entry
-  // state is reset automatically as needed.
-  bool OpenCurrentEntryInZip();
-
-  // Locates an entry in the zip file and opens it. Returns true on
-  // success. This function internally calls OpenCurrentEntryInZip() on
-  // success. On failure, current_entry_info() becomes NULL.
-  bool LocateAndOpenEntry(const base::FilePath& path_in_zip);
-
-  // Extracts the current entry to the given output file path. If the
-  // current file is a directory, just creates a directory
-  // instead. Returns true on success. OpenCurrentEntryInZip() must be
-  // called beforehand.
-  //
-  // This function does not preserve the timestamp of the original entry.
-  bool ExtractCurrentEntryToFilePath(const base::FilePath& output_file_path);
-
-  // Extracts the current entry to the given output directory path using
-  // ExtractCurrentEntryToFilePath(). Sub directories are created as needed
-  // based on the file path of the current entry. For example, if the file
-  // path in zip is "foo/bar.txt", and the output directory is "output",
-  // "output/foo/bar.txt" will be created.
-  //
-  // Returns true on success. OpenCurrentEntryInZip() must be called
-  // beforehand.
-  bool ExtractCurrentEntryIntoDirectory(
-      const base::FilePath& output_directory_path);
-
-#if defined(OS_POSIX)
-  // Extracts the current entry by writing directly to a file descriptor.
-  // Does not close the file descriptor. Returns true on success.
-  bool ExtractCurrentEntryToFd(int fd);
-#endif
-
-  // Returns the current entry info. Returns NULL if the current entry is
-  // not yet opened. OpenCurrentEntryInZip() must be called beforehand.
-  EntryInfo* current_entry_info() const {
-    return current_entry_info_.get();
-  }
-
-  // Returns the number of entries in the zip file.
-  // Open() must be called beforehand.
-  int num_entries() const { return num_entries_; }
-
- private:
-  // Common code used both in Open and OpenFromFd.
-  bool OpenInternal();
-
-  // Resets the internal state.
-  void Reset();
-
-  unzFile zip_file_;
-  int num_entries_;
-  bool reached_end_;
-  scoped_ptr<EntryInfo> current_entry_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(ZipReader);
-};
-
-}  // namespace zip
-
-#endif  // CHROME_TEST_CHROMEDRIVER_CHROME_ZIP_READER_H_
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc
index 1ca47c3..75d05d3 100644
--- a/chrome/test/chromedriver/chrome_launcher.cc
+++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -38,10 +38,10 @@
 #include "chrome/test/chromedriver/chrome/user_data_dir.h"
 #include "chrome/test/chromedriver/chrome/version.h"
 #include "chrome/test/chromedriver/chrome/web_view.h"
-#include "chrome/test/chromedriver/chrome/zip.h"
 #include "chrome/test/chromedriver/net/port_server.h"
 #include "chrome/test/chromedriver/net/url_request_context_getter.h"
 #include "crypto/sha2.h"
+#include "third_party/zlib/google/zip.h"
 
 #if defined(OS_POSIX)
 #include <fcntl.h>
@@ -255,7 +255,7 @@
   if (!CommandLine::ForCurrentProcess()->HasSwitch("verbose")) {
     // Redirect stderr to /dev/null, so that Chrome log spew doesn't confuse
     // users.
-    devnull.reset(open("/dev/null", O_WRONLY));
+    devnull.reset(HANDLE_EINTR(open("/dev/null", O_WRONLY)));
     if (!devnull.is_valid())
       return Status(kUnknownError, "couldn't open /dev/null");
     no_stderr.push_back(std::make_pair(devnull.get(), STDERR_FILENO));
diff --git a/chrome/test/chromedriver/js/call_function_test.html b/chrome/test/chromedriver/js/call_function_test.html
index 7c0a2df..3c99a08 100644
--- a/chrome/test/chromedriver/js/call_function_test.html
+++ b/chrome/test/chromedriver/js/call_function_test.html
@@ -165,7 +165,7 @@
 
   // Set up something in the shadow DOM.
   var host = document.body.appendChild(document.createElement('div'));
-  var root = host.webkitCreateShadowRoot();
+  var root = host.createShadowRoot();
   var shadowDiv = root.appendChild(document.createElement('div'));
 
   function func(element) {
@@ -187,7 +187,7 @@
 
   // Set up something in the shadow DOM.
   var host = document.body.appendChild(document.createElement('div'));
-  var root = host.webkitCreateShadowRoot();
+  var root = host.createShadowRoot();
   var shadowDiv = root.appendChild(document.createElement('div'));
 
   function func(element) {
@@ -215,7 +215,7 @@
   
   // Set up something in the shadow DOM.
   var host = document.body.appendChild(document.createElement('div'));
-  var root = host.webkitCreateShadowRoot();
+  var root = host.createShadowRoot();
   var shadowDiv = root.appendChild(document.createElement('div'));
   
   // Test with attached element in shadow DOM.
@@ -241,7 +241,7 @@
 
   // Set up something in the shadow DOM.
   var host = document.body.appendChild(document.createElement('div'));
-  var root = host.webkitCreateShadowRoot();
+  var root = host.createShadowRoot();
   var shadowDiv = root.appendChild(document.createElement('div'));
 
   // Test with detached element in shadow DOM.
diff --git a/chrome/test/chromedriver/test/test_expectations b/chrome/test/chromedriver/test/test_expectations
index 1e2803f..2589bf2 100644
--- a/chrome/test/chromedriver/test/test_expectations
+++ b/chrome/test/chromedriver/test/test_expectations
@@ -115,6 +115,8 @@
     'AlertsTest.testShouldAllowUsersToAcceptAnAlertInAFrame',
     # Flaky: https://code.google.com/p/chromedriver/issues/detail?id=375
     'PageLoadingTest.testShouldBeAbleToNavigateBackInTheBrowserHistoryInPresenceOfIframes',
+    # Flaky: https://code.google.com/p/chromedriver/issues/detail?id=416
+    'TakesScreenshotTest.testShouldCaptureScreenshotAtFramePage',
 ]
 _OS_NEGATIVE_FILTER['android:chrome'] = [
     'ChromeOptionsFunctionalTest.canStartChromeWithCustomOptions',
diff --git a/chrome/test/chromedriver/util.cc b/chrome/test/chromedriver/util.cc
index f1fac34..e91689d 100644
--- a/chrome/test/chromedriver/util.cc
+++ b/chrome/test/chromedriver/util.cc
@@ -18,8 +18,8 @@
 #include "chrome/test/chromedriver/chrome/status.h"
 #include "chrome/test/chromedriver/chrome/ui_events.h"
 #include "chrome/test/chromedriver/chrome/web_view.h"
-#include "chrome/test/chromedriver/chrome/zip.h"
 #include "chrome/test/chromedriver/key_converter.h"
+#include "third_party/zlib/google/zip.h"
 
 std::string GenerateId() {
   uint64 msb = base::RandUint64();
diff --git a/chrome/test/functional/chromoting/chromoting_base.py b/chrome/test/functional/chromoting/chromoting_base.py
index 64eb59b..b7dafb6 100644
--- a/chrome/test/functional/chromoting/chromoting_base.py
+++ b/chrome/test/functional/chromoting/chromoting_base.py
@@ -39,14 +39,9 @@
     self.client_tab_index = 2 if self.client_local else 1
 
   def ExtraChromeFlags(self):
-    """Add extra flags for chromoting testing
+    """Add extra flags for chromoting testing.
 
     Add --allow-nacl-socket-api to connect chromoting successfully.
-    Add --allow-legacy-extension-manifests so that chrome can load
-    chromoting webapp in v1 format.
     """
-    extra_chrome_flags = [
-        '--allow-nacl-socket-api=*',
-        '--allow-legacy-extension-manifests'
-        ]
-    return pyauto.PyUITest.ExtraChromeFlags(self) + extra_chrome_flags
\ No newline at end of file
+    extra_chrome_flags = ['--allow-nacl-socket-api=*']
+    return pyauto.PyUITest.ExtraChromeFlags(self) + extra_chrome_flags
diff --git a/chrome/test/functional/perf.py b/chrome/test/functional/perf.py
index 0bc8f44..77b2eb5 100755
--- a/chrome/test/functional/perf.py
+++ b/chrome/test/functional/perf.py
@@ -765,7 +765,7 @@
     # Window size impacts a variety of perf tests, ensure consistency.
     flags.append('--window-size=1024,768')
     if self._IsPGOMode():
-      flags = flags + ['--child-clean-exit', '--no-sandbox']
+      flags = flags + ['--no-sandbox']
     return flags
 
 
diff --git a/chrome/test/functional/test_clean_exit.py b/chrome/test/functional/test_clean_exit.py
deleted file mode 100755
index c0e1834..0000000
--- a/chrome/test/functional/test_clean_exit.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import logging
-import os
-import signal
-import subprocess
-import tempfile
-import unittest
-
-import pyauto_functional
-import pyauto
-import test_utils
-
-
-class SimpleTest(pyauto.PyUITest):
-
-  def ExtraChromeFlags(self):
-    """Ensures Chrome is launched with custom flags.
-
-    Returns:
-      A list of extra flags to pass to Chrome when it is launched.
-    """
-    fd, self._strace_log = tempfile.mkstemp()
-    os.close(fd)
-    extra_flags = ['--no-sandbox', '--child-clean-exit',
-                   '--renderer-cmd-prefix=/usr/bin/strace -o %s' %
-                    self._strace_log]
-    logging.debug('Strace file is: %s' % self._strace_log)
-    return pyauto.PyUITest.ExtraChromeFlags(self) + extra_flags
-
-
-  def testCleanExit(self):
-    """Ensures the renderer process cleanly exits."""
-    url = self.GetHttpURLForDataPath('title2.html')
-    self.NavigateToURL(url)
-    os.kill(self.GetBrowserInfo()['browser_pid'], signal.SIGINT)
-    self.WaitUntil(lambda: self._IsFileOpen(self._strace_log))
-    strace_contents = open(self._strace_log).read()
-    self.assertTrue('exit_group' in strace_contents)
-    os.remove(self._strace_log)
-
-  def _IsFileOpen(self, filename):
-    p = subprocess.Popen(['lsof', filename])
-    return p.communicate()[0] == ''
-
-
-if __name__ == '__main__':
-  pyauto_functional.Main()
diff --git a/chrome/test/gpu/webgl_infobar_browsertest.cc b/chrome/test/gpu/webgl_infobar_browsertest.cc
index bbe9f45..8040cae 100644
--- a/chrome/test/gpu/webgl_infobar_browsertest.cc
+++ b/chrome/test/gpu/webgl_infobar_browsertest.cc
@@ -27,6 +27,7 @@
 #include "content/public/common/page_transition_types.h"
 #include "content/public/test/browser_test_utils.h"
 #include "gpu/config/gpu_test_config.h"
+#include "grit/theme_resources.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gl/gl_implementation.h"
 
@@ -132,7 +133,7 @@
       browser()->tab_strip_model()->GetActiveWebContents());
   ASSERT_EQ(1u, infobar_service->infobar_count());
   InfoBarDelegate* delegate = infobar_service->infobar_at(0)->delegate();
-  ASSERT_TRUE(delegate->AsThreeDAPIInfoBarDelegate());
+  ASSERT_EQ(IDR_INFOBAR_3D_BLOCKED, delegate->GetIconID());
   delegate->AsConfirmInfoBarDelegate()->Cancel();
 
   // The page should reload and another message sent to the
diff --git a/chrome/test/nacl/nacl_browsertest.cc b/chrome/test/nacl/nacl_browsertest.cc
index 46a12b5..6f4c03f 100644
--- a/chrome/test/nacl/nacl_browsertest.cc
+++ b/chrome/test/nacl/nacl_browsertest.cc
@@ -14,9 +14,13 @@
 #include "base/command_line.h"
 #include "base/environment.h"
 #include "base/path_service.h"
+#include "base/process/kill.h"
+#include "base/process/launch.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/win/windows_version.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/nacl/nacl_browsertest_util.h"
+#include "components/nacl/browser/nacl_browser.h"
 #include "components/nacl/common/nacl_switches.h"
 #include "content/public/common/content_switches.h"
 
@@ -35,6 +39,17 @@
   RunLoadTest(FILE_PATH_LITERAL("nacl_load_test.html"));
 })
 
+// ASan does not work with libc-free context, so disable the test.
+#if defined(OS_LINUX) && !defined(ADDRESS_SANITIZER)
+#  define MAYBE_NonSfiMessaging NonSfiMessaging
+#else
+#  define MAYBE_NonSfiMessaging DISABLED_NonSfiMessaging
+#endif
+
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestNonSfiMode, MAYBE_NonSfiMessaging) {
+  RunLoadTest(FILE_PATH_LITERAL("libc_free.html"));
+}
+
 NACL_BROWSER_TEST_F(NaClBrowserTest, ExitStatus0, {
   RunNaClIntegrationTest(FILE_PATH_LITERAL(
       "pm_exit_status_test.html?trigger=exit0&expected_exit=0"));
@@ -190,7 +205,8 @@
   RunLoadTest(FILE_PATH_LITERAL("manifest/relative_manifest.html"));
 }
 
-class NaClBrowserTestPnaclDebugURL : public NaClBrowserTestPnacl {
+// Test with the NaCl debug flag turned on.
+class NaClBrowserTestPnaclDebug : public NaClBrowserTestPnacl {
  public:
   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
     NaClBrowserTestPnacl::SetUpCommandLine(command_line);
@@ -201,40 +217,89 @@
 #if defined(OS_WIN)
     command_line->AppendSwitch(switches::kNoSandbox);
 #endif
-    // Don't actually debug the app though.
+  }
+
+  // On some platforms this test does not work.
+  bool TestIsBroken() {
+    // TODO(jvoung): Make this test work on Windows 32-bit. When --no-sandbox
+    // is used, the required 1GB sandbox address space is not reserved.
+    // (see note in chrome/browser/nacl_host/test/nacl_gdb_browsertest.cc)
+#if defined(OS_WIN)
+    if (base::win::OSInfo::GetInstance()->wow64_status() ==
+        base::win::OSInfo::WOW64_DISABLED &&
+        base::win::OSInfo::GetInstance()->architecture() ==
+        base::win::OSInfo::X86_ARCHITECTURE) {
+      return true;
+    }
+#endif
+    return false;
+  }
+
+  void StartTestScript(base::ProcessHandle* test_process,
+                       int debug_stub_port) {
+    // We call a python script that speaks to the debug stub, and
+    // lets the app continue, so that the load progress event completes.
+    CommandLine cmd(base::FilePath(FILE_PATH_LITERAL("python")));
+    base::FilePath script;
+    PathService::Get(base::DIR_SOURCE_ROOT, &script);
+    script = script.AppendASCII(
+        "chrome/browser/nacl_host/test/debug_stub_browser_tests.py");
+    cmd.AppendArgPath(script);
+    cmd.AppendArg(base::IntToString(debug_stub_port));
+    cmd.AppendArg("continue");
+    LOG(INFO) << cmd.GetCommandLineString();
+    base::LaunchProcess(cmd, base::LaunchOptions(), test_process);
+  }
+
+  void RunWithTestDebugger(const base::FilePath::StringType& test_url) {
+    base::ProcessHandle test_script;
+    scoped_ptr<base::Environment> env(base::Environment::Create());
+    nacl::NaClBrowser::GetInstance()->SetGdbDebugStubPortListener(
+        base::Bind(&NaClBrowserTestPnaclDebug::StartTestScript,
+                   base::Unretained(this), &test_script));
+    // Turn on debug stub logging.
+    env->SetVar("NACLVERBOSITY", "1");
+    RunLoadTest(test_url);
+    env->UnSetVar("NACLVERBOSITY");
+    nacl::NaClBrowser::GetInstance()->ClearGdbDebugStubPortListener();
+    int exit_code;
+    LOG(INFO) << "Waiting for script to exit (which waits for embed to die).";
+    base::WaitForExitCode(test_script, &exit_code);
+    EXPECT_EQ(0, exit_code);
+  }
+};
+
+// Test with the NaCl debug flag turned on, but mask off every URL
+// so that nothing is actually debugged.
+class NaClBrowserTestPnaclDebugMasked : public NaClBrowserTestPnaclDebug {
+ public:
+  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
+    NaClBrowserTestPnaclDebug::SetUpCommandLine(command_line);
     command_line->AppendSwitchASCII(switches::kNaClDebugMask,
                                     "!<all_urls>");
   }
 };
 
-IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclDebugURL,
-                       MAYBE_PNACL(PnaclDebugURLFlagAndURL)) {
-  // TODO(jvoung): Make this test work on Windows 32-bit. When --no-sandbox
-  // is used, the required 1GB sandbox address space is not reserved.
-  // (see note in chrome/browser/nacl_host/test/nacl_gdb_browsertest.cc)
+// The tests which actually start a debug session must use the debug stub
+// to continue the app startup. However, NaCl on windows can't open the
+// debug stub socket in the browser process as needed by the test.
+// See http://crbug.com/157312.
 #if defined(OS_WIN)
-  if (base::win::OSInfo::GetInstance()->wow64_status() ==
-      base::win::OSInfo::WOW64_DISABLED &&
-      base::win::OSInfo::GetInstance()->architecture() ==
-      base::win::OSInfo::X86_ARCHITECTURE) {
-    return;
-  }
+#define MAYBE_PnaclDebugURLFlagAndURL DISABLED_PnaclDebugURLFlagAndURL
+#define MAYBE_PnaclDebugURLFlagNoURL DISABLED_PnaclDebugURLFlagNoURL
+#else
+#define MAYBE_PnaclDebugURLFlagAndURL PnaclDebugURLFlagAndURL
+#define MAYBE_PnaclDebugURLFlagNoURL PnaclDebugURLFlagNoURL
 #endif
-  RunLoadTest(FILE_PATH_LITERAL(
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclDebug,
+                       MAYBE_PnaclDebugURLFlagAndURL) {
+  RunWithTestDebugger(FILE_PATH_LITERAL(
       "pnacl_debug_url.html?nmf_file=pnacl_has_debug.nmf"));
 }
 
-IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclDebugURL,
-                       MAYBE_PNACL(PnaclDebugURLFlagNoURL)) {
-#if defined(OS_WIN)
-  if (base::win::OSInfo::GetInstance()->wow64_status() ==
-      base::win::OSInfo::WOW64_DISABLED &&
-      base::win::OSInfo::GetInstance()->architecture() ==
-      base::win::OSInfo::X86_ARCHITECTURE) {
-    return;
-  }
-#endif
-  RunLoadTest(FILE_PATH_LITERAL(
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclDebug,
+                       MAYBE_PnaclDebugURLFlagNoURL) {
+  RunWithTestDebugger(FILE_PATH_LITERAL(
       "pnacl_debug_url.html?nmf_file=pnacl_no_debug.nmf"));
 }
 
@@ -244,6 +309,16 @@
       "pnacl_debug_url.html?nmf_file=pnacl_has_debug_flag_off.nmf"));
 }
 
+IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnaclDebugMasked,
+                       MAYBE_PNACL(PnaclDebugURLFlagMaskedOff)) {
+  if (TestIsBroken()) {
+    return;
+  }
+  // If the mask excludes debugging, it's as if the flag was off.
+  RunLoadTest(FILE_PATH_LITERAL(
+      "pnacl_debug_url.html?nmf_file=pnacl_has_debug_flag_off.nmf"));
+}
+
 IN_PROC_BROWSER_TEST_F(NaClBrowserTestPnacl,
                        MAYBE_PNACL(PnaclErrorHandling)) {
   RunNaClIntegrationTest(FILE_PATH_LITERAL("pnacl_error_handling.html"));
diff --git a/chrome/test/nacl/nacl_browsertest_util.cc b/chrome/test/nacl/nacl_browsertest_util.cc
index 2d92ea9..97058b8 100644
--- a/chrome/test/nacl/nacl_browsertest_util.cc
+++ b/chrome/test/nacl/nacl_browsertest_util.cc
@@ -14,6 +14,7 @@
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/ui_test_utils.h"
+#include "components/nacl/common/nacl_switches.h"
 #include "content/public/browser/plugin_service.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/webplugininfo.h"
@@ -201,7 +202,7 @@
 NaClBrowserTestBase::~NaClBrowserTestBase() {
 }
 
-void NaClBrowserTestBase::SetUpCommandLine(CommandLine* command_line) {
+void NaClBrowserTestBase::SetUpCommandLine(base::CommandLine* command_line) {
   command_line->AppendSwitch(switches::kEnableNaCl);
 }
 
@@ -313,11 +314,22 @@
 bool NaClBrowserTestPnaclDisabled::IsPnaclDisabled() {
   return true;
 }
-void NaClBrowserTestPnaclDisabled::SetUpCommandLine(CommandLine* command_line) {
+void NaClBrowserTestPnaclDisabled::SetUpCommandLine(
+    base::CommandLine* command_line) {
   NaClBrowserTestBase::SetUpCommandLine(command_line);
   command_line->AppendSwitch(switches::kDisablePnacl);
 }
 
+base::FilePath::StringType NaClBrowserTestNonSfiMode::Variant() {
+  return FILE_PATH_LITERAL("libc-free");
+}
+
+void NaClBrowserTestNonSfiMode::SetUpCommandLine(
+    base::CommandLine* command_line) {
+  NaClBrowserTestBase::SetUpCommandLine(command_line);
+  command_line->AppendSwitch(switches::kEnableNaClNonSfiMode);
+}
+
 base::FilePath::StringType NaClBrowserTestStatic::Variant() {
   return FILE_PATH_LITERAL("static");
 }
diff --git a/chrome/test/nacl/nacl_browsertest_util.h b/chrome/test/nacl/nacl_browsertest_util.h
index 2f2d73d..fa50192 100644
--- a/chrome/test/nacl/nacl_browsertest_util.h
+++ b/chrome/test/nacl/nacl_browsertest_util.h
@@ -136,6 +136,12 @@
   virtual bool IsPnaclDisabled() OVERRIDE;
 };
 
+class NaClBrowserTestNonSfiMode : public NaClBrowserTestBase {
+ public:
+  virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE;
+  virtual base::FilePath::StringType Variant() OVERRIDE;
+};
+
 // A NaCl browser test only using static files.
 class NaClBrowserTestStatic : public NaClBrowserTestBase {
  public:
diff --git a/chrome/test/perf/mach_ports_performancetest.cc b/chrome/test/perf/mach_ports_performancetest.cc
new file mode 100644
index 0000000..8208a4f
--- /dev/null
+++ b/chrome/test/perf/mach_ports_performancetest.cc
@@ -0,0 +1,115 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <mach/mach.h>
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "net/test/spawned_test_server/spawned_test_server.h"
+#include "testing/perf/perf_test.h"
+
+namespace {
+
+// This test spawns a new browser and counts the number of open Mach ports in
+// the browser process. It navigates tabs and closes them, repeatedly measuring
+// the number of open ports. This is used to protect against leaking Mach ports,
+// which was the source of <http://crbug.com/105513>.
+class MachPortsTest : public InProcessBrowserTest {
+ public:
+  MachPortsTest()
+      : server_(net::SpawnedTestServer::TYPE_HTTP,
+                net::SpawnedTestServer::kLocalhost,
+                base::FilePath(FILE_PATH_LITERAL("data/mach_ports/moz"))) {
+  }
+
+  virtual void SetUp() OVERRIDE {
+    InProcessBrowserTest::SetUp();
+
+    ASSERT_TRUE(server_.Start());
+  }
+
+  virtual void TearDown() OVERRIDE {
+    std::string ports;
+    for (std::vector<int>::iterator it = port_counts_.begin();
+         it != port_counts_.end(); ++it) {
+      base::StringAppendF(&ports, "%d,", *it);
+    }
+    perf_test::PrintResultList("mach_ports", "", "", ports, "ports", true);
+
+    InProcessBrowserTest::TearDown();
+  }
+
+  // Gets the browser's current number of Mach ports and records it.
+  void RecordPortCount() {
+    mach_port_name_array_t names;
+    mach_msg_type_number_t names_count = 0;
+    mach_port_type_array_t types;
+    mach_msg_type_number_t types_count = 0;
+
+    mach_port_t self = mach_task_self();
+
+    // A friendlier interface would allow NULL buffers to only get the counts.
+    kern_return_t kr = mach_port_names(self,
+                                       &names, &names_count,
+                                       &types, &types_count);
+    ASSERT_EQ(KERN_SUCCESS, kr) << "Failed to get mach_port_names(): "
+                                << mach_error_string(kr);
+    ASSERT_EQ(names_count, types_count);  // Documented kernel invariant.
+
+    port_counts_.push_back(names_count);
+
+    vm_deallocate(self, reinterpret_cast<vm_address_t>(names),
+        names_count * sizeof(mach_port_name_array_t));
+    vm_deallocate(self, reinterpret_cast<vm_address_t>(types),
+        types_count * sizeof(mach_port_type_array_t));
+  }
+
+  // Adds a tab from the page cycler data at the specified domain.
+  void AddTab(const std::string& domain) {
+    GURL url = server_.GetURL("files/" + domain + "/").Resolve("?skip");
+    AddTabAtIndex(0, url, content::PageTransition::PAGE_TRANSITION_TYPED);
+  }
+
+ private:
+  net::SpawnedTestServer server_;
+  std::vector<int> port_counts_;
+};
+
+IN_PROC_BROWSER_TEST_F(MachPortsTest, GetCounts) {
+  browser()->window()->Show();
+
+  // Record startup number.
+  RecordPortCount();
+
+  // Create a browser and open a few tabs.
+  AddTab("www.google.com");
+  RecordPortCount();
+
+  AddTab("www.cnn.com");
+  RecordPortCount();
+
+  AddTab("www.nytimes.com");
+  RecordPortCount();
+
+  TabStripModel* tab_strip_model = browser()->tab_strip_model();
+  int tab_count = tab_strip_model->count();
+  ASSERT_EQ(4, tab_count);  // Also count about:blank.
+
+  // Close each tab, recording the number of ports after each. Do not close the
+  // last tab, which is about:blank.
+  for (int i = 0; i < tab_count - 1; ++i) {
+    EXPECT_TRUE(
+        tab_strip_model->CloseWebContentsAt(0, TabStripModel::CLOSE_NONE));
+    RecordPortCount();
+  }
+}
+
+}  // namespace
diff --git a/chrome/test/ppapi/ppapi_browsertest.cc b/chrome/test/ppapi/ppapi_browsertest.cc
index 0a344a8..b71421f 100644
--- a/chrome/test/ppapi/ppapi_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_browsertest.cc
@@ -780,6 +780,7 @@
   RunTestViaHTTP(
       LIST_TEST(PostMessage_SendInInit)
       LIST_TEST(PostMessage_SendingData)
+      LIST_TEST(PostMessage_SendingString)
       LIST_TEST(PostMessage_SendingArrayBuffer)
       LIST_TEST(DISABLED_PostMessage_SendingArray)
       LIST_TEST(DISABLED_PostMessage_SendingDictionary)
@@ -801,6 +802,7 @@
   RunTestViaHTTP(
       LIST_TEST(PostMessage_SendInInit)
       LIST_TEST(PostMessage_SendingData)
+      LIST_TEST(PostMessage_SendingString)
       LIST_TEST(PostMessage_SendingArrayBuffer)
       LIST_TEST(PostMessage_SendingArray)
       LIST_TEST(PostMessage_SendingDictionary)
@@ -816,6 +818,7 @@
   RunTestViaHTTP(
       LIST_TEST(PostMessage_SendInInit)
       LIST_TEST(PostMessage_SendingData)
+      LIST_TEST(PostMessage_SendingString)
       LIST_TEST(PostMessage_SendingArrayBuffer)
       LIST_TEST(PostMessage_SendingArray)
       LIST_TEST(PostMessage_SendingDictionary)
@@ -831,6 +834,7 @@
   RunTestViaHTTP(
       LIST_TEST(PostMessage_SendInInit)
       LIST_TEST(PostMessage_SendingData)
+      LIST_TEST(PostMessage_SendingString)
       LIST_TEST(PostMessage_SendingArrayBuffer)
       LIST_TEST(PostMessage_SendingArray)
       LIST_TEST(PostMessage_SendingDictionary)
@@ -846,6 +850,7 @@
   RunTestViaHTTP(
       LIST_TEST(PostMessage_SendInInit)
       LIST_TEST(PostMessage_SendingData)
+      LIST_TEST(PostMessage_SendingString)
       LIST_TEST(PostMessage_SendingArrayBuffer)
       LIST_TEST(PostMessage_SendingArray)
       LIST_TEST(PostMessage_SendingDictionary)
diff --git a/chrome/test/ppapi/ppapi_interactive_browsertest.cc b/chrome/test/ppapi/ppapi_interactive_browsertest.cc
index cb6a5fd..0552a8b 100644
--- a/chrome/test/ppapi/ppapi_interactive_browsertest.cc
+++ b/chrome/test/ppapi/ppapi_interactive_browsertest.cc
@@ -16,7 +16,7 @@
 // Disable tests under ASAN.  http://crbug.com/104832.
 // This is a bit heavy handed, but the majority of these tests fail under ASAN.
 // See bug for history.
-#if !defined(ADDRESS_SANITIZER)
+#if !defined(ADDRESS_SANITIZER) && !defined(SYZYASAN)
 
 // Disabled due to timeouts: http://crbug.com/136548
 IN_PROC_BROWSER_TEST_F(
diff --git a/chrome/test/ppapi/ppapi_test.cc b/chrome/test/ppapi/ppapi_test.cc
index 117c974..96a27ad 100644
--- a/chrome/test/ppapi/ppapi_test.cc
+++ b/chrome/test/ppapi/ppapi_test.cc
@@ -31,14 +31,6 @@
 using content::DomOperationNotificationDetails;
 using content::RenderViewHost;
 
-#if defined(DISABLE_NACL)
-#define RETURN_IF_NO_NACL() do { \
-  LOG(WARNING) << "This test always passes with disable_nacl=1."; \
-  return; } while (0)
-#else
-#define RETURN_IF_NO_NACL() do { } while (0)
-#endif
-
 namespace {
 
 // Platform-specific filename relative to the chrome executable.
@@ -357,7 +349,7 @@
 }
 
 void PPAPINaClTest::SetUpCommandLine(base::CommandLine* command_line) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::SetUpCommandLine(command_line);
 
   // Enable running (non-portable) NaCl outside of the Chrome web store.
@@ -365,6 +357,7 @@
   command_line->AppendSwitchASCII(switches::kAllowNaClSocketAPI, "127.0.0.1");
   command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream);
   command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
+#endif
 }
 
 void PPAPINaClTest::SetUpOnMainThread() {
@@ -374,40 +367,47 @@
 }
 
 void PPAPINaClTest::RunTest(const std::string& test_case) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::RunTest(test_case);
+#endif
 }
 
 void PPAPINaClTest::RunTestAndReload(const std::string& test_case) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::RunTestAndReload(test_case);
+#endif
 }
 
 void PPAPINaClTest::RunTestViaHTTP(const std::string& test_case) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::RunTestViaHTTP(test_case);
+#endif
 }
 
 void PPAPINaClTest::RunTestWithSSLServer(const std::string& test_case) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::RunTestWithSSLServer(test_case);
+#endif
 }
 
 void PPAPINaClTest::RunTestWithWebSocketServer(const std::string& test_case) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::RunTestWithWebSocketServer(test_case);
+#endif
 }
 
 void PPAPINaClTest::RunTestIfAudioOutputAvailable(
     const std::string& test_case) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::RunTestIfAudioOutputAvailable(test_case);
+#endif
 }
 
 void PPAPINaClTest::RunTestViaHTTPIfAudioOutputAvailable(
     const std::string& test_case) {
-  RETURN_IF_NO_NACL();
+#if !defined(DISABLE_NACL)
   PPAPITestBase::RunTestViaHTTPIfAudioOutputAvailable(test_case);
+#endif
 }
 
 // Append the correct mode and testcase string
diff --git a/chrome/test/pyautolib/chromoting_helper.py b/chrome/test/pyautolib/chromoting_helper.py
index 9b06b4b..1c14bb5 100644
--- a/chrome/test/pyautolib/chromoting_helper.py
+++ b/chrome/test/pyautolib/chromoting_helper.py
@@ -124,7 +124,7 @@
 
     mock_pref_pane = os.path.join(pref_pane_dir, 'mock_pref_pane')
     pref_pane = os.path.join(pref_pane_dir,
-                             'org.chromium.chromoting.prefPane')
+                             'ChromeRemoteDesktop.prefPane')
     mock_pref_pane_python = os.path.join(
         os.path.dirname(os.path.abspath(__file__)),
         'mock_pref_pane.py')
@@ -197,4 +197,4 @@
 
 
 if __name__ == '__main__':
-  Main()
\ No newline at end of file
+  Main()
diff --git a/chrome/tools/build/win/FILES.cfg b/chrome/tools/build/win/FILES.cfg
index 6883f45..24cfa0c 100644
--- a/chrome/tools/build/win/FILES.cfg
+++ b/chrome/tools/build/win/FILES.cfg
@@ -527,7 +527,9 @@
     'buildtype': ['official'],
     'archive': 'cloud_print.zip',
   },
-  # syzygy files:
+  # Syzygy modified binaries and related files. Only add to this section if you
+  # know what you're doing! The build configuration has to be modified to run
+  # Syzygy on the target in question before adding a staging dependency here!
   {
     'filename': 'chrome.dll-order.json',
     'arch': ['32bit'],
@@ -572,14 +574,6 @@
     'optional': ['dev'],
   },
   {
-    'filename': 'syzygy/mojo_system.dll',
-    'arch': ['32bit'],
-    'buildtype': ['dev', 'official'],
-    'archive': 'syzygy/mojo_system.dll',
-    'filegroup': ['symsrc'],
-    'optional': ['dev'],
-  },
-  {
     'filename': 'syzygy/syzyasan_rtl.dll',
     'arch': ['32bit'],
     'buildtype': ['dev', 'official'],
@@ -708,6 +702,9 @@
     'buildtype': ['dev', 'official'],
     'archive': 'chrome-win32-syms.zip',
   },
+  # PDB files for Syzygy modified binaries. Only add to this section if you
+  # know what you're doing! The build configuration has to be modified to run
+  # Syzygy on the target in question before adding a staging dependency here!
   {
     'filename': 'syzygy/chrome.dll.pdb',
     'arch': ['32bit'],
@@ -730,13 +727,6 @@
     'optional': ['dev'],
   },
   {
-    'filename': 'syzygy/mojo_system.dll.pdb',
-    'arch': ['32bit'],
-    'buildtype': ['dev', 'official'],
-    'archive': 'chrome-win32-syms.zip',
-    'optional': ['dev'],
-  },
-  {
     'filename': 'syzygy/syzyasan_rtl.dll.pdb',
     'arch': ['32bit'],
     'buildtype': ['dev', 'official'],
diff --git a/chrome/tools/mac_helpers/infoplist_strings_util.mm b/chrome/tools/mac_helpers/infoplist_strings_util.mm
index 6531342..1655e0d 100644
--- a/chrome/tools/mac_helpers/infoplist_strings_util.mm
+++ b/chrome/tools/mac_helpers/infoplist_strings_util.mm
@@ -253,6 +253,10 @@
         LoadStringFromDataPack(branded_data_pack.get(), cur_lang,
                                IDS_ABOUT_VERSION_COPYRIGHT,
                                "IDS_ABOUT_VERSION_COPYRIGHT");
+    NSString* address_book_prompt_description =
+        LoadStringFromDataPack(branded_data_pack.get(), cur_lang,
+                               IDS_AUTOFILL_ADDRESS_BOOK_PROMPT_DESCRIPTION,
+                               "IDS_AUTOFILL_ADDRESS_BOOK_PROMPT_DESCRIPTION");
 
     base::Time::Exploded exploded_time;
     base::Time::Now().LocalExplode(&exploded_time);
@@ -274,10 +278,12 @@
           @"CFBundleDisplayName = \"%@\";\n"
           @"CFBundleGetInfoString = \"%@\";\n"
           @"CFBundleName = \"%@\";\n"
+          @"NSContactsUsageDescription = \"%@\";\n"
           @"NSHumanReadableCopyright = \"%@\";\n",
           EscapeForStringsFileValue(name),
           EscapeForStringsFileValue(get_info),
           EscapeForStringsFileValue(short_name),
+          EscapeForStringsFileValue(address_book_prompt_description),
           EscapeForStringsFileValue(copyright)];
 
     // We set up Xcode projects expecting strings files to be UTF8, so make
diff --git a/chrome/tools/safe_browsing/sb_sigutil.cc b/chrome/tools/safe_browsing/sb_sigutil.cc
index 4d2f75b..34b19ef 100644
--- a/chrome/tools/safe_browsing/sb_sigutil.cc
+++ b/chrome/tools/safe_browsing/sb_sigutil.cc
@@ -15,7 +15,7 @@
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
-#include "chrome/browser/safe_browsing/signature_util.h"
+#include "chrome/browser/safe_browsing/binary_feature_extractor.h"
 #include "chrome/common/safe_browsing/csd.pb.h"
 
 // Command-line switch for the executable to extract a signature from.
@@ -37,11 +37,11 @@
     return 1;
   }
 
-  scoped_refptr<safe_browsing::SignatureUtil> sig_util(
-      new safe_browsing::SignatureUtil());
+  scoped_refptr<safe_browsing::BinaryFeatureExtractor> extractor(
+      new safe_browsing::BinaryFeatureExtractor());
   safe_browsing::ClientDownloadRequest_SignatureInfo signature_info;
-  sig_util->CheckSignature(cmd_line->GetSwitchValuePath(kExecutable),
-                           &signature_info);
+  extractor->CheckSignature(cmd_line->GetSwitchValuePath(kExecutable),
+                            &signature_info);
 
   std::string serialized_info = signature_info.SerializeAsString();
   int bytes_written = base::WriteFile(
diff --git a/chrome/utility/DEPS b/chrome/utility/DEPS
index c3d40c3..0a3ce26 100644
--- a/chrome/utility/DEPS
+++ b/chrome/utility/DEPS
@@ -2,6 +2,7 @@
   "+content/public/child",
   "+content/public/utility",
   "+components/wifi",
+  "+courgette",
   "+extensions/common",
 
   # For generated headers.
diff --git a/chrome/utility/chrome_content_utility_client.cc b/chrome/utility/chrome_content_utility_client.cc
index f4569b2..f7274ed 100644
--- a/chrome/utility/chrome_content_utility_client.cc
+++ b/chrome/utility/chrome_content_utility_client.cc
@@ -31,6 +31,8 @@
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/utility/utility_thread.h"
+#include "courgette/courgette.h"
+#include "courgette/third_party/bsdiff.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/manifest.h"
 #include "media/base/media.h"
@@ -371,6 +373,10 @@
                         OnGetPrinterCapsAndDefaults)
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults,
                         OnGetPrinterSemanticCapsAndDefaults)
+    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileBsdiff,
+                        OnPatchFileBsdiff)
+    IPC_MESSAGE_HANDLER(ChromeUtilityMsg_PatchFileCourgette,
+                        OnPatchFileCourgette)
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_StartupPing, OnStartupPing)
     IPC_MESSAGE_HANDLER(ChromeUtilityMsg_AnalyzeZipFileForDownloadProtection,
                         OnAnalyzeZipFileForDownloadProtection)
@@ -581,12 +587,13 @@
 void ChromeContentUtilityClient::OnRenderPDFPagesToPWGRaster(
     IPC::PlatformFileForTransit pdf_transit,
     const printing::PdfRenderSettings& settings,
+    const printing::PwgRasterSettings& bitmap_settings,
     IPC::PlatformFileForTransit bitmap_transit) {
   base::PlatformFile pdf =
       IPC::PlatformFileForTransitToPlatformFile(pdf_transit);
   base::PlatformFile bitmap =
       IPC::PlatformFileForTransitToPlatformFile(bitmap_transit);
-  if (RenderPDFPagesToPWGRaster(pdf, settings, bitmap)) {
+  if (RenderPDFPagesToPWGRaster(pdf, settings, bitmap_settings, bitmap)) {
     Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded());
   } else {
     Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed());
@@ -674,6 +681,7 @@
 bool ChromeContentUtilityClient::RenderPDFPagesToPWGRaster(
     base::PlatformFile pdf_file,
     const printing::PdfRenderSettings& settings,
+    const printing::PwgRasterSettings& bitmap_settings,
     base::PlatformFile bitmap_file) {
   bool autoupdate = true;
   if (!g_pdf_lib.Get().IsValid())
@@ -706,10 +714,21 @@
   cloud_print::BitmapImage image(settings.area().size(),
                                  cloud_print::BitmapImage::BGRA);
   for (int i = 0; i < total_page_count; ++i) {
-    if (!g_pdf_lib.Get().RenderPDFPageToBitmap(
-             data.data(), data.size(), i, image.pixel_data(),
-             image.size().width(), image.size().height(), settings.dpi(),
-             settings.dpi(), autoupdate)) {
+    int page_number = i;
+
+    if (bitmap_settings.reverse_page_order) {
+      page_number = total_page_count - 1 - page_number;
+    }
+
+    if (!g_pdf_lib.Get().RenderPDFPageToBitmap(data.data(),
+                                               data.size(),
+                                               page_number,
+                                               image.pixel_data(),
+                                               image.size().width(),
+                                               image.size().height(),
+                                               settings.dpi(),
+                                               settings.dpi(),
+                                               autoupdate)) {
       return false;
     }
     std::string pwg_page;
@@ -801,6 +820,43 @@
   ReleaseProcessIfNeeded();
 }
 
+void ChromeContentUtilityClient::OnPatchFileBsdiff(
+    const base::FilePath& input_file,
+    const base::FilePath& patch_file,
+    const base::FilePath& output_file) {
+  if (input_file.empty() || patch_file.empty() || output_file.empty()) {
+    Send(new ChromeUtilityHostMsg_PatchFile_Failed(-1));
+  } else {
+    const int patch_status = courgette::ApplyBinaryPatch(input_file,
+                                                         patch_file,
+                                                         output_file);
+    if (patch_status != courgette::OK)
+      Send(new ChromeUtilityHostMsg_PatchFile_Failed(patch_status));
+    else
+      Send(new ChromeUtilityHostMsg_PatchFile_Succeeded());
+  }
+  ReleaseProcessIfNeeded();
+}
+
+void ChromeContentUtilityClient::OnPatchFileCourgette(
+    const base::FilePath& input_file,
+    const base::FilePath& patch_file,
+    const base::FilePath& output_file) {
+  if (input_file.empty() || patch_file.empty() || output_file.empty()) {
+    Send(new ChromeUtilityHostMsg_PatchFile_Failed(-1));
+  } else {
+    const int patch_status = courgette::ApplyEnsemblePatch(
+        input_file.value().c_str(),
+        patch_file.value().c_str(),
+        output_file.value().c_str());
+    if (patch_status != courgette::C_OK)
+      Send(new ChromeUtilityHostMsg_PatchFile_Failed(patch_status));
+    else
+      Send(new ChromeUtilityHostMsg_PatchFile_Succeeded());
+  }
+  ReleaseProcessIfNeeded();
+}
+
 void ChromeContentUtilityClient::OnStartupPing() {
   Send(new ChromeUtilityHostMsg_ProcessStarted);
   // Don't release the process, we assume further messages are on the way.
diff --git a/chrome/utility/chrome_content_utility_client.h b/chrome/utility/chrome_content_utility_client.h
index 4f6b33f..c9e2d0e 100644
--- a/chrome/utility/chrome_content_utility_client.h
+++ b/chrome/utility/chrome_content_utility_client.h
@@ -28,6 +28,7 @@
 
 namespace printing {
 class PdfRenderSettings;
+struct PwgRasterSettings;
 struct PageRange;
 }
 
@@ -62,6 +63,7 @@
   void OnRenderPDFPagesToPWGRaster(
       IPC::PlatformFileForTransit pdf_transit,
       const printing::PdfRenderSettings& settings,
+      const printing::PwgRasterSettings& bitmap_settings,
       IPC::PlatformFileForTransit bitmap_transit);
   void OnRobustJPEGDecodeImage(
       const std::vector<unsigned char>& encoded_data);
@@ -88,10 +90,17 @@
   bool RenderPDFPagesToPWGRaster(
       base::PlatformFile pdf_file,
       const printing::PdfRenderSettings& settings,
+      const printing::PwgRasterSettings& bitmap_settings,
       base::PlatformFile bitmap_file);
 
   void OnGetPrinterCapsAndDefaults(const std::string& printer_name);
   void OnGetPrinterSemanticCapsAndDefaults(const std::string& printer_name);
+  void OnPatchFileBsdiff(const base::FilePath& input_file,
+                         const base::FilePath& patch_file,
+                         const base::FilePath& output_file);
+  void OnPatchFileCourgette(const base::FilePath& input_file,
+                            const base::FilePath& patch_file,
+                            const base::FilePath& output_file);
   void OnStartupPing();
   void OnAnalyzeZipFileForDownloadProtection(
       const IPC::PlatformFileForTransit& zip_file);
diff --git a/chrome/utility/image_writer/image_writer.cc b/chrome/utility/image_writer/image_writer.cc
index b913175..de2caeb 100644
--- a/chrome/utility/image_writer/image_writer.cc
+++ b/chrome/utility/image_writer/image_writer.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/platform_file.h"
-#include "chrome/utility/image_writer/error_messages.h"
 #include "chrome/utility/image_writer/image_writer.h"
+
+#include "chrome/utility/image_writer/error_messages.h"
 #include "chrome/utility/image_writer/image_writer_handler.h"
 #include "content/public/utility/utility_thread.h"
 
@@ -15,12 +15,12 @@
 const int kBurningBlockSize = 1 << 20;
 
 ImageWriter::ImageWriter(ImageWriterHandler* handler)
-    : image_file_(base::kInvalidPlatformFileValue),
-      device_file_(base::kInvalidPlatformFileValue),
-      bytes_processed_(0),
+    : bytes_processed_(0),
       handler_(handler) {}
 
-ImageWriter::~ImageWriter() { CleanUp(); }
+ImageWriter::~ImageWriter() {
+  CleanUp();
+}
 
 void ImageWriter::Write(const base::FilePath& image_path,
                         const base::FilePath& device_path) {
@@ -33,15 +33,10 @@
   device_path_ = device_path;
   bytes_processed_ = 0;
 
-  base::PlatformFileError error;
+  image_file_.Initialize(image_path_,
+                         base::File::FLAG_OPEN | base::File::FLAG_READ);
 
-  image_file_ = base::CreatePlatformFile(
-      image_path_,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
-      NULL,
-      &error);
-
-  if (error != base::PLATFORM_FILE_OK) {
+  if (!image_file_.IsValid()) {
     DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
     Error(error::kOpenImage);
     return;
@@ -49,30 +44,28 @@
 
 #if defined(OS_WIN)
   // Windows requires that device files be opened with FILE_FLAG_NO_BUFFERING
-  // and FILE_FLAG_WRITE_THROUGH.  These two flags are not part of
-  // PlatformFile::CreatePlatformFile.
-  device_file_ = CreateFile(device_path.value().c_str(),
+  // and FILE_FLAG_WRITE_THROUGH.  These two flags are not part of base::File.
+  device_file_ =
+      base::File(CreateFile(device_path.value().c_str(),
                             GENERIC_WRITE,
                             FILE_SHARE_WRITE,
                             NULL,
                             OPEN_EXISTING,
                             FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
-                            INVALID_HANDLE_VALUE);
+                            NULL));
 
-  if (device_file_ == base::kInvalidPlatformFileValue) {
+  if (!device_file_.IsValid()) {
     Error(error::kOpenDevice);
     return;
   }
 #else
-  device_file_ = base::CreatePlatformFile(
-      device_path_,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE,
-      NULL,
-      &error);
+  device_file_.Initialize(device_path_,
+                          base::File::FLAG_OPEN | base::File::FLAG_WRITE);
 
-  if (error != base::PLATFORM_FILE_OK) {
-    DLOG(ERROR) << "Unable to open file for write(" << error
-                << "): " << device_path_.value();
+  if (!device_file_.IsValid()) {
+    DLOG(ERROR) << "Unable to open file for write(" <<
+                   device_file_.error_details() << "): " <<
+                   device_path_.value();
     Error(error::kOpenDevice);
     return;
   }
@@ -94,27 +87,19 @@
   device_path_ = device_path;
   bytes_processed_ = 0;
 
-  base::PlatformFileError error;
+  image_file_.Initialize(image_path_,
+                         base::File::FLAG_OPEN | base::File::FLAG_READ);
 
-  image_file_ = base::CreatePlatformFile(
-      image_path_,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
-      NULL,
-      &error);
-
-  if (error != base::PLATFORM_FILE_OK) {
+  if (!image_file_.IsValid()) {
     DLOG(ERROR) << "Unable to open file for read: " << image_path_.value();
     Error(error::kOpenImage);
     return;
   }
 
-  device_file_ = base::CreatePlatformFile(
-      device_path_,
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
-      NULL,
-      &error);
+  device_file_.Initialize(device_path_,
+                          base::File::FLAG_OPEN | base::File::FLAG_READ);
 
-  if (error != base::PLATFORM_FILE_OK) {
+  if (!device_file_.IsValid()) {
     DLOG(ERROR) << "Unable to open file for read: " << device_path_.value();
     Error(error::kOpenDevice);
     return;
@@ -131,8 +116,7 @@
 }
 
 bool ImageWriter::IsRunning() const {
-  return image_file_ != base::kInvalidPlatformFileValue ||
-         device_file_ != base::kInvalidPlatformFileValue;
+  return image_file_.IsValid() || device_file_.IsValid();
 }
 
 void ImageWriter::PostTask(const base::Closure& task) {
@@ -155,16 +139,15 @@
 
   scoped_ptr<char[]> buffer(new char[kBurningBlockSize]);
   memset(buffer.get(), 0, kBurningBlockSize);
-  base::PlatformFileInfo info;
 
-  int bytes_read = base::ReadPlatformFile(
-      image_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
+  int bytes_read = image_file_.Read(bytes_processed_, buffer.get(),
+                                    kBurningBlockSize);
 
   if (bytes_read > 0) {
     // Always attempt to write a whole block, as Windows requires 512-byte
     // aligned writes to devices.
-    int bytes_written = base::WritePlatformFile(
-        device_file_, bytes_processed_, buffer.get(), kBurningBlockSize);
+    int bytes_written = device_file_.Write(bytes_processed_, buffer.get(),
+                                           kBurningBlockSize);
 
     if (bytes_written < bytes_read) {
       Error(error::kWriteImage);
@@ -177,7 +160,7 @@
     PostTask(base::Bind(&ImageWriter::WriteChunk, AsWeakPtr()));
   } else if (bytes_read == 0) {
     // End of file.
-    base::FlushPlatformFile(device_file_);
+    device_file_.Flush();
     CleanUp();
     handler_->SendSucceeded();
   } else {
@@ -194,14 +177,13 @@
   scoped_ptr<char[]> image_buffer(new char[kBurningBlockSize]);
   scoped_ptr<char[]> device_buffer(new char[kBurningBlockSize]);
 
-  int bytes_read = base::ReadPlatformFile(
-      image_file_, bytes_processed_, image_buffer.get(), kBurningBlockSize);
+  int bytes_read = image_file_.Read(bytes_processed_, image_buffer.get(),
+                                    kBurningBlockSize);
 
   if (bytes_read > 0) {
-    if (base::ReadPlatformFile(device_file_,
-                               bytes_processed_,
-                               device_buffer.get(),
-                               kBurningBlockSize) < bytes_read) {
+    if (device_file_.Read(bytes_processed_,
+                          device_buffer.get(),
+                          kBurningBlockSize) < bytes_read) {
       LOG(ERROR) << "Failed to read " << kBurningBlockSize << " bytes of "
                  << "device at offset " << bytes_processed_;
       Error(error::kReadDevice);
@@ -232,14 +214,8 @@
 }
 
 void ImageWriter::CleanUp() {
-  if (image_file_ != base::kInvalidPlatformFileValue) {
-    base::ClosePlatformFile(image_file_);
-    image_file_ = base::kInvalidPlatformFileValue;
-  }
-  if (device_file_ != base::kInvalidPlatformFileValue) {
-    base::ClosePlatformFile(device_file_);
-    device_file_ = base::kInvalidPlatformFileValue;
-  }
+  image_file_.Close();
+  device_file_.Close();
 }
 
 }  // namespace image_writer
diff --git a/chrome/utility/image_writer/image_writer.h b/chrome/utility/image_writer/image_writer.h
index 8a9fd5b..70633e7 100644
--- a/chrome/utility/image_writer/image_writer.h
+++ b/chrome/utility/image_writer/image_writer.h
@@ -7,6 +7,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 
@@ -51,8 +52,8 @@
   base::FilePath image_path_;
   base::FilePath device_path_;
 
-  base::PlatformFile image_file_;
-  base::PlatformFile device_file_;
+  base::File image_file_;
+  base::File device_file_;
   int64 bytes_processed_;
 
   ImageWriterHandler* handler_;
diff --git a/chrome_elf/blacklist/blacklist.cc b/chrome_elf/blacklist/blacklist.cc
index 19c7641..705cc60 100644
--- a/chrome_elf/blacklist/blacklist.cc
+++ b/chrome_elf/blacklist/blacklist.cc
@@ -244,8 +244,9 @@
   if (!force && !LeaveSetupBeacon())
     return false;
 
-  // Tells the resolver to patch already patched functions.
-  const bool kRelaxed = true;
+  // It is possible for other dlls to have already patched code by now and
+  // attempting to patch their code might result in crashes.
+  const bool kRelaxed = false;
 
   // Create a thunk via the appropriate ServiceResolver instance.
   sandbox::ServiceResolverThunk* thunk = GetThunk(kRelaxed);
diff --git a/chrome_elf/breakpad.cc b/chrome_elf/breakpad.cc
index d2189b6..17ddc8f 100644
--- a/chrome_elf/breakpad.cc
+++ b/chrome_elf/breakpad.cc
@@ -18,7 +18,7 @@
 
 namespace {
 
-const wchar_t kBreakpadProductName[] = L"ChromeElf";
+const wchar_t kBreakpadProductName[] = L"Chrome";
 const wchar_t kBreakpadVersionEntry[] = L"ver";
 const wchar_t kBreakpadProdEntry[] = L"prod";
 const wchar_t kBreakpadPlatformEntry[] = L"plat";
diff --git a/chrome_elf/elf_imports_unittest.cc b/chrome_elf/elf_imports_unittest.cc
index c4b9dd4..136912b 100644
--- a/chrome_elf/elf_imports_unittest.cc
+++ b/chrome_elf/elf_imports_unittest.cc
@@ -61,12 +61,13 @@
   std::vector<std::string>::iterator it(elf_imports.begin());
 
   static const char* const kValidFilePatterns[] = {
-      "KERNEL32.dll",
-      "MSVC*",
-#if defined(ADDRESS_SANITIZER)
-      "syzyasan_rtl.dll",
+    "KERNEL32.dll",
+    "MSVC*",
+#if defined(SYZYASAN)
+    "syzyasan_rtl.dll",
 #endif
-      "ADVAPI32.dll"};
+    "ADVAPI32.dll"
+  };
 
   // Make sure all of ELF's imports are in the valid imports list.
   for (; it != elf_imports.end(); it++) {
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 6d1b733..2e33b4c 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-5661.0.0
\ No newline at end of file
+5687.0.0
\ No newline at end of file
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index f633b58..3115014 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -116,6 +116,12 @@
         'dbus/fake_bluetooth_agent_service_provider.h',
         'dbus/fake_bluetooth_device_client.cc',
         'dbus/fake_bluetooth_device_client.h',
+        'dbus/fake_bluetooth_gatt_characteristic_client.cc',
+        'dbus/fake_bluetooth_gatt_characteristic_client.h',
+        'dbus/fake_bluetooth_gatt_descriptor_client.cc',
+        'dbus/fake_bluetooth_gatt_descriptor_client.h',
+        'dbus/fake_bluetooth_gatt_service_client.cc',
+        'dbus/fake_bluetooth_gatt_service_client.h',
         'dbus/fake_bluetooth_input_client.cc',
         'dbus/fake_bluetooth_input_client.h',
         'dbus/fake_bluetooth_profile_manager_client.cc',
@@ -553,5 +559,19 @@
       },
       'includes': ['../build/protoc.gypi'],
     },
+    {
+      # Protobuf compiler/generator for cryptohome key signing protocol buffer.
+      'target_name': 'cryptohome_signkey_proto',
+      'type': 'static_library',
+      'sources': [
+        '../third_party/cros_system_api/dbus/cryptohome/signed_secret.proto',
+      ],
+      'variables': {
+        'proto_in_dir': '../third_party/cros_system_api/dbus/cryptohome',
+        'proto_out_dir': 'chromeos/cryptohome',
+      },
+      'includes': ['../build/protoc.gypi'],
+    },
+
   ],
 }
diff --git a/chromeos/chromeos_switches.cc b/chromeos/chromeos_switches.cc
index 1e0c2c1..200b9a6 100644
--- a/chromeos/chromeos_switches.cc
+++ b/chromeos/chromeos_switches.cc
@@ -15,13 +15,10 @@
 // Possible values: parallel|postpone. Default: parallel.
 const char kAshWebUIInit[]                  = "ash-webui-init";
 
-// Enables overriding the path for the default authentication extension.
-const char kAuthExtensionPath[]             = "auth-ext-path";
-
 // Forces the stub implementation of dbus clients.
 const char kDbusStub[] = "dbus-stub";
 
-// Time before a machine at OOBE is considered derelict
+// Time before a machine at OOBE is considered derelict.
 const char kDerelictDetectionTimeout[] = "derelict-detection-timeout";
 
 // Time before a derelict machines starts demo mode.
@@ -61,11 +58,6 @@
 const char kDisableNetworkPortalNotification[] =
     "disable-network-portal-notification";
 
-// Disables portal detection and network error handling before auto
-// update.
-const char kDisableOOBEBlockingUpdate[] =
-    "disable-oobe-blocking-update";
-
 // Enables overriding the path for the default echo component extension.
 // Useful for testing.
 const char kEchoExtensionPath[]             = "echo-ext-path";
@@ -85,6 +77,9 @@
 // than the kiosk app mode.
 const char kEnableKioskMode[]               = "enable-kiosk-mode";
 
+// Enables rollback option for resetting ChromeOS.
+const char kEnableRollbackOption[]          = "enable-rollback-option";
+
 // Enables request of tablet site (via user agent override).
 const char kEnableRequestTabletSite[]       = "enable-request-tablet-site";
 
@@ -157,6 +152,9 @@
 // Interval at which we check for total time on OOBE.
 const char kOobeTimerInterval[]             = "oobe-timer-interval";
 
+// Indicates that a guest session has been started before OOBE completion.
+const char kOobeGuestSession[]              = "oobe-guest-session";
+
 // Specifies power stub behavior:
 //  'cycle=2' - Cycles power states every 2 seconds.
 // See FakeDBusThreadManager::ParsePowerCommandLineSwitch for full details.
diff --git a/chromeos/chromeos_switches.h b/chromeos/chromeos_switches.h
index 077f5e4..3beffec 100644
--- a/chromeos/chromeos_switches.h
+++ b/chromeos/chromeos_switches.h
@@ -22,7 +22,6 @@
 // Please keep alphabetized.
 CHROMEOS_EXPORT extern const char kAppOemManifestFile[];
 CHROMEOS_EXPORT extern const char kAshWebUIInit[];
-CHROMEOS_EXPORT extern const char kAuthExtensionPath[];
 CHROMEOS_EXPORT extern const char kDbusStub[];
 CHROMEOS_EXPORT extern const char kDerelictDetectionTimeout[];
 CHROMEOS_EXPORT extern const char kDerelictIdleTimeout[];
@@ -34,13 +33,13 @@
 CHROMEOS_EXPORT extern const char kDisableNetworkPortalNotification[];
 CHROMEOS_EXPORT extern const char kDisableNewChannelSwitcherUI[];
 CHROMEOS_EXPORT extern const char kDisableNewKioskUI[];
-CHROMEOS_EXPORT extern const char kDisableOOBEBlockingUpdate[];
 CHROMEOS_EXPORT extern const char kDisableQuickofficeComponentApp[];
 CHROMEOS_EXPORT extern const char kDisableVolumeAdjustSound[];
 CHROMEOS_EXPORT extern const char kEchoExtensionPath[];
 CHROMEOS_EXPORT extern const char kEnableCarrierSwitching[];
 CHROMEOS_EXPORT extern const char kEnableKioskMode[];
 CHROMEOS_EXPORT extern const char kEnableNetworkPortalNotification[];
+CHROMEOS_EXPORT extern const char kEnableRollbackOption[];
 CHROMEOS_EXPORT extern const char kEnableRequestTabletSite[];
 CHROMEOS_EXPORT extern const char kEnableTouchpadThreeFingerClick[];
 CHROMEOS_EXPORT extern const char kEnterpriseEnableForcedReEnrollment[];
@@ -62,6 +61,7 @@
 CHROMEOS_EXPORT extern const char kNaturalScrollDefault[];
 CHROMEOS_EXPORT extern const char kOobeSkipPostLogin[];
 CHROMEOS_EXPORT extern const char kOobeTimerInterval[];
+CHROMEOS_EXPORT extern const char kOobeGuestSession[];
 CHROMEOS_EXPORT extern const char kPowerStub[];
 CHROMEOS_EXPORT extern const char kShillStub[];
 CHROMEOS_EXPORT extern const char kSkipHWIDCheck[];
diff --git a/chromeos/cryptohome/homedir_methods.cc b/chromeos/cryptohome/homedir_methods.cc
index ae1faa4..d1a1cf4 100644
--- a/chromeos/cryptohome/homedir_methods.cc
+++ b/chromeos/cryptohome/homedir_methods.cc
@@ -175,6 +175,27 @@
                    callback));
   }
 
+  virtual void RemoveKeyEx(const Identification& id,
+                           const Authorization& auth,
+                           const std::string& label,
+                           const Callback& callback) OVERRIDE {
+    cryptohome::AccountIdentifier id_proto;
+    cryptohome::AuthorizationRequest auth_proto;
+    cryptohome::RemoveKeyRequest request;
+
+    FillIdentificationProtobuf(id, &id_proto);
+    FillAuthorizationProtobuf(auth, &auth_proto);
+    request.mutable_key()->mutable_data()->set_label(label);
+
+    DBusThreadManager::Get()->GetCryptohomeClient()->RemoveKeyEx(
+        id_proto,
+        auth_proto,
+        request,
+        base::Bind(&HomedirMethodsImpl::OnBaseReplyCallback,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   callback));
+  }
+
   virtual void UpdateKeyEx(const Identification& id,
                            const Authorization& auth,
                            const KeyDefinition& new_key,
diff --git a/chromeos/cryptohome/homedir_methods.h b/chromeos/cryptohome/homedir_methods.h
index d765678..0276f1b 100644
--- a/chromeos/cryptohome/homedir_methods.h
+++ b/chromeos/cryptohome/homedir_methods.h
@@ -70,6 +70,13 @@
                            const std::string& signature,
                            const Callback& callback) = 0;
 
+  // Asks cryptohomed to remove specific key labeled with |label| for user
+  // identified by |id| using |auth|.
+  virtual void RemoveKeyEx(const Identification& id,
+                           const Authorization& auth,
+                           const std::string& label,
+                           const Callback& callback) = 0;
+
   // Creates the global HomedirMethods instance.
   static void Initialize();
 
diff --git a/chromeos/dbus/cryptohome_client.cc b/chromeos/dbus/cryptohome_client.cc
index e5b7db5..4bf3c78 100644
--- a/chromeos/dbus/cryptohome_client.cc
+++ b/chromeos/dbus/cryptohome_client.cc
@@ -438,7 +438,7 @@
       const AsyncMethodCallback& callback) OVERRIDE {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
-        cryptohome::kCryptohomeAsyncTpmAttestationCreateEnrollRequestNew);
+        cryptohome::kCryptohomeAsyncTpmAttestationCreateEnrollRequest);
     dbus::MessageWriter writer(&method_call);
     writer.AppendInt32(pca_type);
     proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
@@ -454,7 +454,7 @@
       const AsyncMethodCallback& callback) OVERRIDE {
     dbus::MethodCall method_call(
         cryptohome::kCryptohomeInterface,
-        cryptohome::kCryptohomeAsyncTpmAttestationEnrollNew);
+        cryptohome::kCryptohomeAsyncTpmAttestationEnroll);
     dbus::MessageWriter writer(&method_call);
     writer.AppendInt32(pca_type);
     writer.AppendArrayOfBytes(
@@ -774,7 +774,27 @@
     writer.AppendProtoAsArrayOfBytes(auth);
     writer.AppendProtoAsArrayOfBytes(request);
 
-    proxy_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+    proxy_->CallMethod(&method_call,
+                       dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+                       base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
+                                  weak_ptr_factory_.GetWeakPtr(),
+                                  callback));
+  }
+
+  virtual void RemoveKeyEx(const cryptohome::AccountIdentifier& id,
+                           const cryptohome::AuthorizationRequest& auth,
+                           const cryptohome::RemoveKeyRequest& request,
+                           const ProtobufMethodCallback& callback) OVERRIDE {
+    const char* method_name = cryptohome::kCryptohomeRemoveKeyEx;
+    dbus::MethodCall method_call(cryptohome::kCryptohomeInterface, method_name);
+
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendProtoAsArrayOfBytes(id);
+    writer.AppendProtoAsArrayOfBytes(auth);
+    writer.AppendProtoAsArrayOfBytes(request);
+
+    proxy_->CallMethod(&method_call,
+                       dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
                        base::Bind(&CryptohomeClientImpl::OnBaseReplyMethod,
                                   weak_ptr_factory_.GetWeakPtr(),
                                   callback));
diff --git a/chromeos/dbus/cryptohome_client.h b/chromeos/dbus/cryptohome_client.h
index a532e9f..de9fd89 100644
--- a/chromeos/dbus/cryptohome_client.h
+++ b/chromeos/dbus/cryptohome_client.h
@@ -24,6 +24,7 @@
 class CheckKeyRequest;
 class MountRequest;
 class UpdateKeyRequest;
+class RemoveKeyRequest;
 
 } // namespace cryptohome
 
@@ -490,6 +491,14 @@
       const cryptohome::UpdateKeyRequest& request,
       const ProtobufMethodCallback& callback) = 0;
 
+  // Asynchronously calls RemoveKeyEx method. |callback| is called after method
+  // call, and with reply protobuf.
+  // RemoveKeyEx removes key from the given key set.
+  virtual void RemoveKeyEx(const cryptohome::AccountIdentifier& id,
+                           const cryptohome::AuthorizationRequest& auth,
+                           const cryptohome::RemoveKeyRequest& request,
+                           const ProtobufMethodCallback& callback) = 0;
+
  protected:
   // Create() should be used instead.
   CryptohomeClient();
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index 1d84074..c76c93e 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -14,6 +14,9 @@
 #include "chromeos/dbus/bluetooth_adapter_client.h"
 #include "chromeos/dbus/bluetooth_agent_manager_client.h"
 #include "chromeos/dbus/bluetooth_device_client.h"
+#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
+#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
+#include "chromeos/dbus/bluetooth_gatt_service_client.h"
 #include "chromeos/dbus/bluetooth_input_client.h"
 #include "chromeos/dbus/bluetooth_profile_manager_client.h"
 #include "chromeos/dbus/cras_audio_client.h"
@@ -71,6 +74,11 @@
     bluetooth_agent_manager_client_.reset(
         BluetoothAgentManagerClient::Create());
     bluetooth_device_client_.reset(BluetoothDeviceClient::Create());
+    bluetooth_gatt_characteristic_client_.reset(
+        BluetoothGattCharacteristicClient::Create());
+    bluetooth_gatt_descriptor_client_.reset(
+        BluetoothGattDescriptorClient::Create());
+    bluetooth_gatt_service_client_.reset(BluetoothGattServiceClient::Create());
     bluetooth_input_client_.reset(BluetoothInputClient::Create());
     bluetooth_profile_manager_client_.reset(
         BluetoothProfileManagerClient::Create());
@@ -114,6 +122,15 @@
   BluetoothDeviceClient* bluetooth_device_client() {
     return bluetooth_device_client_.get();
   }
+  BluetoothGattCharacteristicClient* bluetooth_gatt_characteristic_client() {
+    return bluetooth_gatt_characteristic_client_.get();
+  }
+  BluetoothGattDescriptorClient* bluetooth_gatt_descriptor_client() {
+    return bluetooth_gatt_descriptor_client_.get();
+  }
+  BluetoothGattServiceClient* bluetooth_gatt_service_client() {
+    return bluetooth_gatt_service_client_.get();
+  }
   BluetoothInputClient* bluetooth_input_client() {
     return bluetooth_input_client_.get();
   }
@@ -197,6 +214,10 @@
   scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_;
   scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_;
   scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_;
+  scoped_ptr<BluetoothGattCharacteristicClient>
+      bluetooth_gatt_characteristic_client_;
+  scoped_ptr<BluetoothGattDescriptorClient> bluetooth_gatt_descriptor_client_;
+  scoped_ptr<BluetoothGattServiceClient> bluetooth_gatt_service_client_;
   scoped_ptr<BluetoothInputClient> bluetooth_input_client_;
   scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_;
   scoped_ptr<CrasAudioClient> cras_audio_client_;
@@ -295,6 +316,20 @@
     return client_bundle_->bluetooth_device_client();
   }
 
+  virtual BluetoothGattCharacteristicClient*
+      GetBluetoothGattCharacteristicClient() OVERRIDE {
+    return client_bundle_->bluetooth_gatt_characteristic_client();
+  }
+
+  virtual BluetoothGattDescriptorClient* GetBluetoothGattDescriptorClient()
+      OVERRIDE {
+    return client_bundle_->bluetooth_gatt_descriptor_client();
+  }
+
+  virtual BluetoothGattServiceClient* GetBluetoothGattServiceClient() OVERRIDE {
+    return client_bundle_->bluetooth_gatt_service_client();
+  }
+
   virtual BluetoothInputClient* GetBluetoothInputClient() OVERRIDE {
     return client_bundle_->bluetooth_input_client();
   }
@@ -520,6 +555,9 @@
   InitClient(g_dbus_thread_manager->GetBluetoothAdapterClient());
   InitClient(g_dbus_thread_manager->GetBluetoothAgentManagerClient());
   InitClient(g_dbus_thread_manager->GetBluetoothDeviceClient());
+  InitClient(g_dbus_thread_manager->GetBluetoothGattCharacteristicClient());
+  InitClient(g_dbus_thread_manager->GetBluetoothGattDescriptorClient());
+  InitClient(g_dbus_thread_manager->GetBluetoothGattServiceClient());
   InitClient(g_dbus_thread_manager->GetBluetoothInputClient());
   InitClient(g_dbus_thread_manager->GetBluetoothProfileManagerClient());
   InitClient(g_dbus_thread_manager->GetCrasAudioClient());
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index 513a59f..5f6e290 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -29,6 +29,9 @@
 class BluetoothAdapterClient;
 class BluetoothAgentManagerClient;
 class BluetoothDeviceClient;
+class BluetoothGattCharacteristicClient;
+class BluetoothGattDescriptorClient;
+class BluetoothGattServiceClient;
 class BluetoothInputClient;
 class BluetoothProfileManagerClient;
 class CrasAudioClient;
@@ -124,6 +127,10 @@
   virtual BluetoothAdapterClient* GetBluetoothAdapterClient() = 0;
   virtual BluetoothAgentManagerClient* GetBluetoothAgentManagerClient() = 0;
   virtual BluetoothDeviceClient* GetBluetoothDeviceClient() = 0;
+  virtual BluetoothGattCharacteristicClient*
+      GetBluetoothGattCharacteristicClient() = 0;
+  virtual BluetoothGattDescriptorClient* GetBluetoothGattDescriptorClient() = 0;
+  virtual BluetoothGattServiceClient* GetBluetoothGattServiceClient() = 0;
   virtual BluetoothInputClient* GetBluetoothInputClient() = 0;
   virtual BluetoothProfileManagerClient* GetBluetoothProfileManagerClient() = 0;
   virtual CrasAudioClient* GetCrasAudioClient() = 0;
diff --git a/chromeos/dbus/fake_bluetooth_device_client.cc b/chromeos/dbus/fake_bluetooth_device_client.cc
index 64df07f..44b9a0b 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.cc
+++ b/chromeos/dbus/fake_bluetooth_device_client.cc
@@ -19,6 +19,7 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/rand_util.h"
 #include "base/stl_util.h"
 #include "base/threading/worker_pool.h"
 #include "base/time/time.h"
@@ -26,6 +27,7 @@
 #include "chromeos/dbus/fake_bluetooth_adapter_client.h"
 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
 #include "chromeos/dbus/fake_bluetooth_agent_service_provider.h"
+#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
 #include "chromeos/dbus/fake_bluetooth_input_client.h"
 #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
 #include "chromeos/dbus/fake_bluetooth_profile_service_provider.h"
@@ -38,6 +40,10 @@
 // Default interval between simulated events.
 const int kSimulationIntervalMs = 750;
 
+// Minimum and maximum bounds for randomly generated RSSI values.
+const int kMinRSSI = -90;
+const int kMaxRSSI = -30;
+
 
 void SimulatedProfileSocket(int fd) {
   // Simulate a server-side socket of a profile; read data from the socket,
@@ -167,6 +173,15 @@
     "Just-Works Device";
 const uint32 FakeBluetoothDeviceClient::kJustWorksClass = 0x240428;
 
+const char FakeBluetoothDeviceClient::kLowEnergyPath[] =
+    "/fake/hci0/devC";
+const char FakeBluetoothDeviceClient::kLowEnergyAddress[] =
+    "00:1A:11:00:15:30";
+const char FakeBluetoothDeviceClient::kLowEnergyName[] =
+    "Bluetooth 4.0 Heart Rate Monitor";
+const uint32 FakeBluetoothDeviceClient::kLowEnergyClass =
+    0x000918;  // Major class "Health", Minor class "Heart/Pulse Rate Monitor."
+
 FakeBluetoothDeviceClient::Properties::Properties(
     const PropertyChangedCallback& callback)
     : BluetoothDeviceClient::Properties(
@@ -293,6 +308,15 @@
   properties->connected.ReplaceValue(true);
   callback.Run();
 
+  // Expose GATT services if connected to LE device.
+  if (object_path == dbus::ObjectPath(kLowEnergyPath)) {
+    FakeBluetoothGattServiceClient* gatt_service_client =
+        static_cast<FakeBluetoothGattServiceClient*>(
+            DBusThreadManager::Get()->GetBluetoothGattServiceClient());
+    gatt_service_client->ExposeHeartRateService(
+        dbus::ObjectPath(kLowEnergyPath));
+  }
+
   AddInputDeviceIfNeeded(object_path, properties);
 }
 
@@ -303,12 +327,21 @@
   VLOG(1) << "Disconnect: " << object_path.value();
   Properties* properties = GetProperties(object_path);
 
-  if (properties->connected.value() == true) {
-    callback.Run();
-    properties->connected.ReplaceValue(false);
-  } else {
+  if (!properties->connected.value()) {
     error_callback.Run("org.bluez.Error.NotConnected", "Not Connected");
+    return;
   }
+
+  // Hide the Heart Rate Service if disconnected from LE device.
+  if (object_path == dbus::ObjectPath(kLowEnergyPath)) {
+    FakeBluetoothGattServiceClient* gatt_service_client =
+        static_cast<FakeBluetoothGattServiceClient*>(
+            DBusThreadManager::Get()->GetBluetoothGattServiceClient());
+    gatt_service_client->HideHeartRateService();
+  }
+
+  callback.Run();
+  properties->connected.ReplaceValue(false);
 }
 
 void FakeBluetoothDeviceClient::ConnectProfile(
@@ -564,6 +597,16 @@
     properties->name.ReplaceValue("JustWorks");
     properties->alias.ReplaceValue(kJustWorksName);
 
+  } else if (device_path == dbus::ObjectPath(kLowEnergyPath)) {
+    properties->address.ReplaceValue(kLowEnergyAddress);
+    properties->bluetooth_class.ReplaceValue(kLowEnergyClass);
+    properties->name.ReplaceValue("Heart Rate Monitor");
+    properties->alias.ReplaceValue(kLowEnergyName);
+
+    std::vector<std::string> uuids;
+    uuids.push_back(FakeBluetoothGattServiceClient::kHeartRateServiceUUID);
+    properties->uuids.ReplaceValue(uuids);
+
   } else {
     NOTREACHED();
 
@@ -597,6 +640,13 @@
           DBusThreadManager::Get()->GetBluetoothInputClient());
   fake_bluetooth_input_client->RemoveInputDevice(device_path);
 
+  if (device_path == dbus::ObjectPath(kLowEnergyPath)) {
+    FakeBluetoothGattServiceClient* gatt_service_client =
+        static_cast<FakeBluetoothGattServiceClient*>(
+            DBusThreadManager::Get()->GetBluetoothGattServiceClient());
+    gatt_service_client->HideHeartRateService();
+  }
+
   FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                     DeviceRemoved(device_path));
 
@@ -607,6 +657,8 @@
 void FakeBluetoothDeviceClient::OnPropertyChanged(
     const dbus::ObjectPath& object_path,
     const std::string& property_name) {
+  VLOG(2) << "Fake Bluetooth device property changed: " << object_path.value()
+          << ": " << property_name;
   FOR_EACH_OBSERVER(BluetoothDeviceClient::Observer, observers_,
                     DevicePropertyChanged(object_path, property_name));
 }
@@ -621,22 +673,30 @@
   if (discovery_simulation_step_ == 2) {
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kLegacyAutopairPath));
+    CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
+                 dbus::ObjectPath(kLowEnergyPath));
 
   } else if (discovery_simulation_step_ == 4) {
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kDisplayPinCodePath));
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kVanishingDevicePath));
+    UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
+                     base::RandInt(kMinRSSI, kMaxRSSI));
 
   } else if (discovery_simulation_step_ == 7) {
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kConnectUnpairablePath));
+    UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
+                     base::RandInt(kMinRSSI, kMaxRSSI));
 
   } else if (discovery_simulation_step_ == 8) {
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kDisplayPasskeyPath));
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kRequestPinCodePath));
+    UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
+                     base::RandInt(kMinRSSI, kMaxRSSI));
 
   } else if (discovery_simulation_step_ == 10) {
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
@@ -649,12 +709,18 @@
                  dbus::ObjectPath(kUnpairableDevicePath));
     CreateDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kJustWorksPath));
+    UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
+                     base::RandInt(kMinRSSI, kMaxRSSI));
 
   } else if (discovery_simulation_step_ == 13) {
     RemoveDevice(dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath),
                  dbus::ObjectPath(kVanishingDevicePath));
+    UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
+                     base::RandInt(kMinRSSI, kMaxRSSI));
 
   } else if (discovery_simulation_step_ == 14) {
+    UpdateDeviceRSSI(dbus::ObjectPath(kLowEnergyPath),
+                     base::RandInt(kMinRSSI, kMaxRSSI));
     return;
 
   }
@@ -744,7 +810,8 @@
 
   if (object_path == dbus::ObjectPath(kLegacyAutopairPath) ||
       object_path == dbus::ObjectPath(kConnectUnpairablePath) ||
-      object_path == dbus::ObjectPath(kUnconnectableDevicePath)) {
+      object_path == dbus::ObjectPath(kUnconnectableDevicePath) ||
+      object_path == dbus::ObjectPath(kLowEnergyPath)) {
     // No need to call anything on the pairing delegate, just wait 3 times
     // the interval before acting as if the other end accepted it.
     base::MessageLoop::current()->PostDelayedTask(
@@ -921,6 +988,19 @@
     fake_bluetooth_input_client->AddInputDevice(object_path);
 }
 
+void FakeBluetoothDeviceClient::UpdateDeviceRSSI(
+    const dbus::ObjectPath& object_path,
+    int16 rssi) {
+  PropertiesMap::iterator iter = properties_map_.find(object_path);
+  if (iter == properties_map_.end()) {
+    VLOG(2) << "Fake device does not exist: " << object_path.value();
+    return;
+  }
+  Properties* properties = iter->second;
+  DCHECK(properties);
+  properties->rssi.ReplaceValue(rssi);
+}
+
 void FakeBluetoothDeviceClient::PinCodeCallback(
     const dbus::ObjectPath& object_path,
     const base::Closure& callback,
diff --git a/chromeos/dbus/fake_bluetooth_device_client.h b/chromeos/dbus/fake_bluetooth_device_client.h
index c1699be..827fdcb 100644
--- a/chromeos/dbus/fake_bluetooth_device_client.h
+++ b/chromeos/dbus/fake_bluetooth_device_client.h
@@ -159,6 +159,11 @@
   static const char kJustWorksAddress[];
   static const uint32 kJustWorksClass;
 
+  static const char kLowEnergyPath[];
+  static const char kLowEnergyName[];
+  static const char kLowEnergyAddress[];
+  static const uint32 kLowEnergyClass;
+
  private:
   // Property callback passed when we create Properties* structures.
   void OnPropertyChanged(const dbus::ObjectPath& object_path,
@@ -187,6 +192,10 @@
       const dbus::ObjectPath& object_path,
       Properties* properties);
 
+  // Updates the RSSI property of fake device with object path |object_path|
+  // to |rssi|, if the fake device exists.
+  void UpdateDeviceRSSI(const dbus::ObjectPath& object_path, int16 rssi);
+
   void PinCodeCallback(
       const dbus::ObjectPath& object_path,
       const base::Closure& callback,
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc
new file mode 100644
index 0000000..85408b8
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc
@@ -0,0 +1,342 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/rand_util.h"
+#include "base/time/time.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+namespace {
+
+const int kHeartRateMeasurementNotificationIntervalMs = 2000;
+
+}  // namespace
+
+// static
+const char FakeBluetoothGattCharacteristicClient::
+    kHeartRateMeasurementPathComponent[] = "char0000";
+const char FakeBluetoothGattCharacteristicClient::
+    kBodySensorLocationPathComponent[] = "char0001";
+const char FakeBluetoothGattCharacteristicClient::
+    kHeartRateControlPointPathComponent[] = "char0002";
+
+// static
+const char FakeBluetoothGattCharacteristicClient::kHeartRateMeasurementUUID[] =
+    "00002a37-0000-1000-8000-00805f9b34fb";
+const char FakeBluetoothGattCharacteristicClient::kBodySensorLocationUUID[] =
+    "00002a38-0000-1000-8000-00805f9b34fb";
+const char FakeBluetoothGattCharacteristicClient::kHeartRateControlPointUUID[] =
+    "00002a39-0000-1000-8000-00805f9b34fb";
+
+FakeBluetoothGattCharacteristicClient::Properties::Properties(
+    const PropertyChangedCallback& callback)
+    : BluetoothGattCharacteristicClient::Properties(
+          NULL,
+          bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
+          callback) {
+}
+
+FakeBluetoothGattCharacteristicClient::Properties::~Properties() {
+}
+
+void FakeBluetoothGattCharacteristicClient::Properties::Get(
+    dbus::PropertyBase* property,
+    dbus::PropertySet::GetCallback callback) {
+  VLOG(1) << "Get " << property->name();
+  callback.Run(false);
+}
+
+void FakeBluetoothGattCharacteristicClient::Properties::GetAll() {
+  VLOG(1) << "GetAll";
+}
+
+void FakeBluetoothGattCharacteristicClient::Properties::Set(
+    dbus::PropertyBase* property,
+    dbus::PropertySet::SetCallback callback) {
+  VLOG(1) << "Set " << property->name();
+  if (property->name() != value.name()) {
+    callback.Run(false);
+    return;
+  }
+  // Allow writing to only certain characteristics that are defined with the
+  // write permission.
+  // TODO(armansito): Actually check against the permissions property instead of
+  // UUID, once that property is fully defined in the API.
+  if (uuid.value() != kHeartRateControlPointUUID) {
+    callback.Run(false);
+    return;
+  }
+  callback.Run(true);
+  property->ReplaceValueWithSetValue();
+}
+
+FakeBluetoothGattCharacteristicClient::FakeBluetoothGattCharacteristicClient()
+    : heart_rate_visible_(false),
+      calories_burned_(0),
+      weak_ptr_factory_(this) {
+}
+
+FakeBluetoothGattCharacteristicClient::
+    ~FakeBluetoothGattCharacteristicClient() {
+}
+
+void FakeBluetoothGattCharacteristicClient::Init(dbus::Bus* bus) {
+}
+
+void FakeBluetoothGattCharacteristicClient::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void FakeBluetoothGattCharacteristicClient::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+std::vector<dbus::ObjectPath>
+FakeBluetoothGattCharacteristicClient::GetCharacteristics() {
+  std::vector<dbus::ObjectPath> paths;
+  if (IsHeartRateVisible()) {
+    paths.push_back(dbus::ObjectPath(heart_rate_measurement_path_));
+    paths.push_back(dbus::ObjectPath(body_sensor_location_path_));
+    paths.push_back(dbus::ObjectPath(heart_rate_control_point_path_));
+  }
+  return paths;
+}
+
+FakeBluetoothGattCharacteristicClient::Properties*
+FakeBluetoothGattCharacteristicClient::GetProperties(
+    const dbus::ObjectPath& object_path) {
+  if (object_path.value() == heart_rate_measurement_path_) {
+    DCHECK(heart_rate_measurement_properties_.get());
+    return heart_rate_measurement_properties_.get();
+  }
+  if (object_path.value() == body_sensor_location_path_) {
+    DCHECK(heart_rate_measurement_properties_.get());
+    return heart_rate_measurement_properties_.get();
+  }
+  if (object_path.value() == heart_rate_control_point_path_) {
+    DCHECK(heart_rate_control_point_properties_.get());
+    return heart_rate_control_point_properties_.get();
+  }
+  return NULL;
+}
+
+void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics(
+    const dbus::ObjectPath& service_path) {
+  if (IsHeartRateVisible()) {
+    VLOG(2) << "Fake Heart Rate characteristics are already visible.";
+    return;
+  }
+
+  VLOG(2) << "Exposing fake Heart Rate characteristics.";
+
+  // ==== Heart Rate Measurement Characteristic ====
+  heart_rate_measurement_path_ =
+      service_path.value() + "/" + kHeartRateMeasurementPathComponent;
+  heart_rate_measurement_properties_.reset(new Properties(base::Bind(
+      &FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
+      weak_ptr_factory_.GetWeakPtr(),
+      dbus::ObjectPath(heart_rate_measurement_path_))));
+  heart_rate_measurement_properties_->uuid.ReplaceValue(
+      kHeartRateMeasurementUUID);
+  heart_rate_measurement_properties_->service.ReplaceValue(service_path);
+
+  // TODO(armansito): Fill out the flags field once bindings for the values have
+  // been added. For now, leave it empty.
+
+  std::vector<uint8> measurement_value = GetHeartRateMeasurementValue();
+  heart_rate_measurement_properties_->value.ReplaceValue(measurement_value);
+
+  // ==== Body Sensor Location Characteristic ====
+  body_sensor_location_path_ =
+      service_path.value() + "/" + kBodySensorLocationPathComponent;
+  body_sensor_location_properties_.reset(new Properties(base::Bind(
+      &FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
+      weak_ptr_factory_.GetWeakPtr(),
+      dbus::ObjectPath(body_sensor_location_path_))));
+  body_sensor_location_properties_->uuid.ReplaceValue(kBodySensorLocationUUID);
+  body_sensor_location_properties_->service.ReplaceValue(service_path);
+
+  // TODO(armansito): Fill out the flags field once bindings for the values have
+  // been added. For now, leave it empty.
+
+  // The sensor is in the "Other" location.
+  std::vector<uint8> body_sensor_location_value;
+  body_sensor_location_value.push_back(0);
+  body_sensor_location_properties_->value.ReplaceValue(
+      body_sensor_location_value);
+
+  // ==== Heart Rate Control Point Characteristic ====
+  heart_rate_control_point_path_ =
+      service_path.value() + "/" + kHeartRateControlPointPathComponent;
+  heart_rate_control_point_properties_.reset(new Properties(base::Bind(
+      &FakeBluetoothGattCharacteristicClient::OnPropertyChanged,
+      weak_ptr_factory_.GetWeakPtr(),
+      dbus::ObjectPath(heart_rate_control_point_path_))));
+  heart_rate_control_point_properties_->uuid.ReplaceValue(
+      kHeartRateControlPointUUID);
+  heart_rate_control_point_properties_->service.ReplaceValue(service_path);
+
+  // TODO(armansito): Fill out the flags field once bindings for the values have
+  // been added. For now, leave it empty.
+
+  // Set the initial value to 0. Whenever this gets set to 1, we will reset the
+  // total calories burned and change the value back to 0.
+  std::vector<uint8> heart_rate_control_point_value;
+  heart_rate_control_point_value.push_back(0);
+  heart_rate_control_point_properties_->value.ReplaceValue(
+      heart_rate_control_point_value);
+
+  heart_rate_visible_ = true;
+
+  NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_measurement_path_));
+  NotifyCharacteristicAdded(dbus::ObjectPath(body_sensor_location_path_));
+  NotifyCharacteristicAdded(dbus::ObjectPath(heart_rate_control_point_path_));
+
+  // Set up notifications for heart rate measurement.
+  // TODO(armansito): Do this based on the value of the "client characteristic
+  // configuration" descriptor. Since it's still unclear how descriptors will
+  // be handled by BlueZ, automatically set up notifications for now.
+  ScheduleHeartRateMeasurementValueChange();
+
+  // TODO(armansito): Add descriptors.
+}
+
+void FakeBluetoothGattCharacteristicClient::HideHeartRateCharacteristics() {
+  VLOG(2) << "Hiding fake Heart Rate characteristics.";
+  heart_rate_measurement_properties_.reset();
+  body_sensor_location_properties_.reset();
+  heart_rate_control_point_properties_.reset();
+
+  std::string hrm_path = heart_rate_measurement_path_;
+  heart_rate_measurement_path_.clear();
+  std::string bsl_path =  body_sensor_location_path_;
+  body_sensor_location_path_.clear();
+  std::string hrcp_path = heart_rate_control_point_path_;
+  heart_rate_control_point_path_.clear();
+  heart_rate_visible_ = false;
+
+  NotifyCharacteristicRemoved(dbus::ObjectPath(hrm_path));
+  NotifyCharacteristicRemoved(dbus::ObjectPath(bsl_path));
+  NotifyCharacteristicRemoved(dbus::ObjectPath(hrcp_path));
+}
+
+void FakeBluetoothGattCharacteristicClient::OnPropertyChanged(
+    const dbus::ObjectPath& object_path,
+    const std::string& property_name) {
+  VLOG(2) << "Characteristic property changed: " << object_path.value()
+          << ": " << property_name;
+
+  FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
+                    GattCharacteristicPropertyChanged(
+                        object_path, property_name));
+
+  // If the heart rate control point was set, reset the calories burned.
+  if (object_path.value() != heart_rate_control_point_path_)
+    return;
+  DCHECK(heart_rate_control_point_properties_.get());
+  dbus::Property<std::vector<uint8> >* value_prop =
+      &heart_rate_control_point_properties_->value;
+  if (property_name != value_prop->name())
+    return;
+
+  std::vector<uint8> value = value_prop->value();
+  DCHECK(value.size() == 1);
+  if (value[0] == 0)
+    return;
+
+  DCHECK(value[0] == 1);
+  calories_burned_ = 0;
+  value[0] = 0;
+  value_prop->ReplaceValue(value);
+}
+
+void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicAdded(
+    const dbus::ObjectPath& object_path) {
+  VLOG(2) << "GATT characteristic added: " << object_path.value();
+  FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
+                    GattCharacteristicAdded(object_path));
+}
+
+void FakeBluetoothGattCharacteristicClient::NotifyCharacteristicRemoved(
+    const dbus::ObjectPath& object_path) {
+  VLOG(2) << "GATT characteristic removed: " << object_path.value();
+  FOR_EACH_OBSERVER(BluetoothGattCharacteristicClient::Observer, observers_,
+                    GattCharacteristicRemoved(object_path));
+}
+
+void FakeBluetoothGattCharacteristicClient::
+    ScheduleHeartRateMeasurementValueChange() {
+  if (!IsHeartRateVisible())
+    return;
+  VLOG(2) << "Updating heart rate value.";
+  std::vector<uint8> measurement = GetHeartRateMeasurementValue();
+  heart_rate_measurement_properties_->value.ReplaceValue(measurement);
+
+  base::MessageLoop::current()->PostDelayedTask(
+      FROM_HERE,
+      base::Bind(&FakeBluetoothGattCharacteristicClient::
+                     ScheduleHeartRateMeasurementValueChange,
+                 weak_ptr_factory_.GetWeakPtr()),
+                 base::TimeDelta::FromMilliseconds(
+                     kHeartRateMeasurementNotificationIntervalMs));
+}
+
+std::vector<uint8>
+FakeBluetoothGattCharacteristicClient::GetHeartRateMeasurementValue() {
+  // TODO(armansito): We should make sure to properly pack this struct to ensure
+  // correct byte alignment and endianness. It doesn't matter too much right now
+  // as this is a fake and GCC on Linux seems to do the right thing.
+  struct {
+    uint8 flags;
+    uint8 bpm;
+    uint16 energy_expanded;
+    uint16 rr_interval;
+  } value;
+
+  // Flags in LSB:     0       11   1 1 000
+  //                   |       |    | | |
+  // 8-bit bpm format --       |    | | |
+  // Sensor contact supported --    | | |
+  // Energy expanded field present -- | |
+  // RR-Interval values present ------- |
+  // Reserved for future use ------------
+  value.flags = 0x0;
+  value.flags |= (0x03 << 1);
+  value.flags |= (0x01 << 3);
+  value.flags |= (0x01 << 4);
+
+  // Pick a value between 117 bpm and 153 bpm for heart rate.
+  value.bpm = static_cast<uint8>(base::RandInt(117, 153));
+
+  // Total calories burned in kJoules since the last reset. Increment this by 1
+  // every time. It's fine if it overflows: it becomes 0 when the user resets
+  // the heart rate monitor (or pretend that he had a lot of cheeseburgers).
+  value.energy_expanded = calories_burned_++;
+
+  // Include one RR-Interval value, in seconds.
+  value.rr_interval = 60/value.bpm;
+
+  // Return the bytes in an array.
+  uint8* bytes = reinterpret_cast<uint8*>(&value);
+  std::vector<uint8> return_value;
+  return_value.assign(bytes, bytes + sizeof(value));
+  return return_value;
+}
+
+bool FakeBluetoothGattCharacteristicClient::IsHeartRateVisible() const {
+  DCHECK(heart_rate_visible_ != heart_rate_measurement_path_.empty());
+  DCHECK(heart_rate_visible_ != body_sensor_location_path_.empty());
+  DCHECK(heart_rate_visible_ != heart_rate_control_point_path_.empty());
+  DCHECK(heart_rate_visible_ == !!heart_rate_measurement_properties_.get());
+  DCHECK(heart_rate_visible_ == !!body_sensor_location_properties_.get());
+  DCHECK(heart_rate_visible_ == !!heart_rate_control_point_properties_.get());
+  return heart_rate_visible_;
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h
new file mode 100644
index 0000000..69eb23d
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h
@@ -0,0 +1,125 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
+#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/bluetooth_gatt_characteristic_client.h"
+#include "dbus/object_path.h"
+#include "dbus/property.h"
+
+namespace chromeos {
+
+// FakeBluetoothGattCharacteristicClient simulates the behavior of the
+// Bluetooth Daemon GATT characteristic objects and is used in test cases in
+// place of a mock and on the Linux desktop.
+class CHROMEOS_EXPORT FakeBluetoothGattCharacteristicClient
+    : public BluetoothGattCharacteristicClient {
+ public:
+  struct Properties : public BluetoothGattCharacteristicClient::Properties {
+    explicit Properties(const PropertyChangedCallback& callback);
+    virtual ~Properties();
+
+    // dbus::PropertySet override
+    virtual void Get(dbus::PropertyBase* property,
+                     dbus::PropertySet::GetCallback callback) OVERRIDE;
+    virtual void GetAll() OVERRIDE;
+    virtual void Set(dbus::PropertyBase* property,
+                     dbus::PropertySet::SetCallback callback) OVERRIDE;
+  };
+
+  FakeBluetoothGattCharacteristicClient();
+  virtual ~FakeBluetoothGattCharacteristicClient();
+
+  // DBusClient override.
+  virtual void Init(dbus::Bus* bus) OVERRIDE;
+
+  // BluetoothGattCharacteristicClient overrides.
+  virtual void AddObserver(Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(Observer* observer) OVERRIDE;
+  virtual std::vector<dbus::ObjectPath> GetCharacteristics() OVERRIDE;
+  virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
+      OVERRIDE;
+
+  // Makes the group of characteristics belonging to a particular GATT based
+  // profile available under the GATT service with object path |service_path|.
+  // Characteristic paths are hierarchical to service paths.
+  void ExposeHeartRateCharacteristics(const dbus::ObjectPath& service_path);
+  void HideHeartRateCharacteristics();
+
+  // Object path components and UUIDs of GATT characteristics.
+  // Heart Rate Service:
+  static const char kHeartRateMeasurementPathComponent[];
+  static const char kHeartRateMeasurementUUID[];
+  static const char kBodySensorLocationPathComponent[];
+  static const char kBodySensorLocationUUID[];
+  static const char kHeartRateControlPointPathComponent[];
+  static const char kHeartRateControlPointUUID[];
+
+ private:
+  // Property callback passed when we create Properties structures.
+  void OnPropertyChanged(const dbus::ObjectPath& object_path,
+                         const std::string& property_name);
+
+  // Notifies observers.
+  void NotifyCharacteristicAdded(const dbus::ObjectPath& object_path);
+  void NotifyCharacteristicRemoved(const dbus::ObjectPath& object_path);
+
+  // Schedules a heart rate measurement value change, if the heart rate
+  // characteristics are visible.
+  void ScheduleHeartRateMeasurementValueChange();
+
+  // Returns a random Heart Rate Measurement value. All the fields of the value
+  // are populated according to the the fake behavior. The measurement value
+  // is a random value within a reasonable range.
+  std::vector<uint8> GetHeartRateMeasurementValue();
+
+  // Returns whether or not the heart rate characteristics are visible and
+  // performs the appropriate assertions.
+  bool IsHeartRateVisible() const;
+
+  // If true, characteristics of the Heart Rate Service are visible. Use
+  // IsHeartRateVisible() to check the value.
+  bool heart_rate_visible_;
+
+  // Total calories burned, used for the Heart Rate Measurement characteristic.
+  uint16 calories_burned_;
+
+  // Static properties returned for simulated characteristics for the Heart
+  // Rate Service. These pointers are not NULL only if the characteristics are
+  // actually exposed.
+  scoped_ptr<Properties> heart_rate_measurement_properties_;
+  scoped_ptr<Properties> body_sensor_location_properties_;
+  scoped_ptr<Properties> heart_rate_control_point_properties_;
+
+  // Object paths of the exposed characteristics. If a characteristic is not
+  // exposed, these will be empty.
+  std::string heart_rate_measurement_path_;
+  std::string body_sensor_location_path_;
+  std::string heart_rate_control_point_path_;
+
+  // List of observers interested in event notifications from us.
+  ObserverList<Observer> observers_;
+
+  // Weak pointer factory for generating 'this' pointers that might live longer
+  // than we do.
+  // Note: This should remain the last member so it'll be destroyed and
+  // invalidate its weak pointers before any other members are destroyed.
+  base::WeakPtrFactory<FakeBluetoothGattCharacteristicClient>
+      weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattCharacteristicClient);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_CHARACTERISTIC_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc b/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc
new file mode 100644
index 0000000..f0846a8
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.cc
@@ -0,0 +1,71 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
+
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+FakeBluetoothGattDescriptorClient::Properties::Properties(
+    const PropertyChangedCallback& callback)
+    : BluetoothGattDescriptorClient::Properties(
+          NULL,
+          bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
+          callback) {
+}
+
+FakeBluetoothGattDescriptorClient::Properties::~Properties() {
+}
+
+void FakeBluetoothGattDescriptorClient::Properties::Get(
+    dbus::PropertyBase* property,
+    dbus::PropertySet::GetCallback callback) {
+  VLOG(1) << "Get " << property->name();
+  callback.Run(false);
+}
+
+void FakeBluetoothGattDescriptorClient::Properties::GetAll() {
+  VLOG(1) << "GetAll";
+}
+
+void FakeBluetoothGattDescriptorClient::Properties::Set(
+    dbus::PropertyBase* property,
+    dbus::PropertySet::SetCallback callback) {
+  VLOG(1) << "Get " << property->name();
+  callback.Run(false);
+
+  // TODO(armansito): Setting the "Value" property should be allowed based
+  // on permissions.
+}
+
+FakeBluetoothGattDescriptorClient::FakeBluetoothGattDescriptorClient() {
+}
+
+FakeBluetoothGattDescriptorClient::~FakeBluetoothGattDescriptorClient() {
+}
+
+void FakeBluetoothGattDescriptorClient::Init(dbus::Bus* bus) {
+}
+
+void FakeBluetoothGattDescriptorClient::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void FakeBluetoothGattDescriptorClient::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+std::vector<dbus::ObjectPath>
+FakeBluetoothGattDescriptorClient::GetDescriptors() {
+  return std::vector<dbus::ObjectPath>();
+}
+
+FakeBluetoothGattDescriptorClient::Properties*
+FakeBluetoothGattDescriptorClient::GetProperties(
+    const dbus::ObjectPath& object_path) {
+  return NULL;
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h b/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h
new file mode 100644
index 0000000..dd9f7af
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h
@@ -0,0 +1,57 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
+#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
+
+#include "base/observer_list.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/bluetooth_gatt_descriptor_client.h"
+
+namespace chromeos {
+
+// FakeBluetoothGattDescriptorClient simulates the behavior of the Bluetooth
+// Daemon GATT characteristic descriptor objects and is used in test cases in
+// place of a mock and on the Linux desktop.
+class CHROMEOS_EXPORT FakeBluetoothGattDescriptorClient
+    : public BluetoothGattDescriptorClient {
+ public:
+  struct Properties : public BluetoothGattDescriptorClient::Properties {
+    explicit Properties(const PropertyChangedCallback& callback);
+    virtual ~Properties();
+
+    // dbus::PropertySet override
+    virtual void Get(dbus::PropertyBase* property,
+                     dbus::PropertySet::GetCallback callback) OVERRIDE;
+    virtual void GetAll() OVERRIDE;
+    virtual void Set(dbus::PropertyBase* property,
+                     dbus::PropertySet::SetCallback callback) OVERRIDE;
+  };
+
+  FakeBluetoothGattDescriptorClient();
+  virtual ~FakeBluetoothGattDescriptorClient();
+
+  // DBusClient override.
+  virtual void Init(dbus::Bus* bus) OVERRIDE;
+
+  // BluetoothGattDescriptorClient overrides.
+  virtual void AddObserver(Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(Observer* observer) OVERRIDE;
+  virtual std::vector<dbus::ObjectPath> GetDescriptors() OVERRIDE;
+  virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
+      OVERRIDE;
+
+ private:
+  // TODO(armansito): Add simulated descriptors, once BlueZ's behavior is
+  // better defined.
+
+  // List of observers interested in event notifications from us.
+  ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattDescriptorClient);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_DESCRIPTOR_CLIENT_H_
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_client.cc b/chromeos/dbus/fake_bluetooth_gatt_service_client.cc
new file mode 100644
index 0000000..d579a26
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_gatt_service_client.cc
@@ -0,0 +1,152 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
+
+#include "base/bind.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+// static
+const char FakeBluetoothGattServiceClient::kHeartRateServicePathComponent[] =
+    "service0000";
+const char FakeBluetoothGattServiceClient::kHeartRateServiceUUID[] =
+    "0000180d-0000-1000-8000-00805f9b34fb";
+
+FakeBluetoothGattServiceClient::Properties::Properties(
+    const PropertyChangedCallback& callback)
+    : BluetoothGattServiceClient::Properties(
+        NULL,
+        bluetooth_gatt_service::kBluetoothGattServiceInterface,
+        callback) {
+}
+
+FakeBluetoothGattServiceClient::Properties::~Properties() {
+}
+
+void FakeBluetoothGattServiceClient::Properties::Get(
+    dbus::PropertyBase* property,
+    dbus::PropertySet::GetCallback callback) {
+  VLOG(1) << "Get " << property->name();
+  callback.Run(false);
+}
+
+void FakeBluetoothGattServiceClient::Properties::GetAll() {
+  VLOG(1) << "GetAll";
+}
+
+void FakeBluetoothGattServiceClient::Properties::Set(
+    dbus::PropertyBase* property,
+    dbus::PropertySet::GetCallback callback) {
+  VLOG(1) << "Set " << property->name();
+  callback.Run(false);
+}
+
+FakeBluetoothGattServiceClient::FakeBluetoothGattServiceClient() {
+}
+
+FakeBluetoothGattServiceClient::~FakeBluetoothGattServiceClient() {
+}
+
+void FakeBluetoothGattServiceClient::Init(dbus::Bus* bus) {
+}
+
+void FakeBluetoothGattServiceClient::AddObserver(Observer* observer) {
+  observers_.AddObserver(observer);
+}
+
+void FakeBluetoothGattServiceClient::RemoveObserver(Observer* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+std::vector<dbus::ObjectPath> FakeBluetoothGattServiceClient::GetServices() {
+  std::vector<dbus::ObjectPath> paths;
+  if (heart_rate_service_properties_.get()) {
+    DCHECK(!heart_rate_service_path_.empty());
+    paths.push_back(dbus::ObjectPath(heart_rate_service_path_));
+  }
+  return paths;
+}
+
+FakeBluetoothGattServiceClient::Properties*
+FakeBluetoothGattServiceClient::GetProperties(
+    const dbus::ObjectPath& object_path) {
+  if (object_path.value() == heart_rate_service_path_)
+    return heart_rate_service_properties_.get();
+  return NULL;
+}
+
+void FakeBluetoothGattServiceClient::ExposeHeartRateService(
+    const dbus::ObjectPath& device_path) {
+  if (heart_rate_service_properties_.get()) {
+    DCHECK(!heart_rate_service_path_.empty());
+    VLOG(1) << "Fake Heart Rate Service already exposed.";
+    return;
+  }
+  VLOG(2) << "Exposing fake Heart Rate Service.";
+  heart_rate_service_path_ =
+      device_path.value() + "/" + kHeartRateServicePathComponent;
+  heart_rate_service_properties_.reset(new Properties(base::Bind(
+      &FakeBluetoothGattServiceClient::OnPropertyChanged,
+      base::Unretained(this),
+      dbus::ObjectPath(heart_rate_service_path_))));
+  heart_rate_service_properties_->uuid.ReplaceValue(heart_rate_service_path_);
+
+  NotifyServiceAdded(dbus::ObjectPath(heart_rate_service_path_));
+
+  FakeBluetoothGattCharacteristicClient* char_client =
+      static_cast<FakeBluetoothGattCharacteristicClient*>(
+          DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient());
+  char_client->ExposeHeartRateCharacteristics(
+      dbus::ObjectPath(heart_rate_service_path_));
+}
+
+void FakeBluetoothGattServiceClient::HideHeartRateService() {
+  if (!heart_rate_service_properties_.get()) {
+    DCHECK(heart_rate_service_path_.empty());
+    VLOG(1) << "Fake Heart Rate Service already hidden.";
+    return;
+  }
+  VLOG(2) << "Hiding fake Heart Rate Service.";
+  FakeBluetoothGattCharacteristicClient* char_client =
+      static_cast<FakeBluetoothGattCharacteristicClient*>(
+          DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient());
+  char_client->HideHeartRateCharacteristics();
+
+  heart_rate_service_properties_.reset();
+  std::string hrs_path = heart_rate_service_path_;
+  heart_rate_service_path_.clear();
+
+  NotifyServiceRemoved(dbus::ObjectPath(hrs_path));
+}
+
+void FakeBluetoothGattServiceClient::OnPropertyChanged(
+    const dbus::ObjectPath& object_path,
+    const std::string& property_name) {
+  VLOG(2) << "Fake GATT Service property changed: " << object_path.value()
+          << ": " << property_name;
+  FOR_EACH_OBSERVER(BluetoothGattServiceClient::Observer, observers_,
+                    GattServicePropertyChanged(object_path, property_name));
+}
+
+void FakeBluetoothGattServiceClient::NotifyServiceAdded(
+    const dbus::ObjectPath& object_path) {
+  VLOG(2) << "GATT service added: " << object_path.value();
+  FOR_EACH_OBSERVER(
+      BluetoothGattServiceClient::Observer, observers_,
+      GattServiceAdded(object_path));
+}
+
+void FakeBluetoothGattServiceClient::NotifyServiceRemoved(
+    const dbus::ObjectPath& object_path) {
+  VLOG(2) << "GATT service removed: " << object_path.value();
+  FOR_EACH_OBSERVER(
+      BluetoothGattServiceClient::Observer, observers_,
+      GattServiceRemoved(object_path));
+}
+
+}  // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_client.h b/chromeos/dbus/fake_bluetooth_gatt_service_client.h
new file mode 100644
index 0000000..35b05d4
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_gatt_service_client.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_
+#define CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/bluetooth_gatt_service_client.h"
+#include "dbus/object_path.h"
+#include "dbus/property.h"
+
+namespace chromeos {
+
+// FakeBluetoothGattServiceClient simulates the behavior of the Bluetooth Daemon
+// GATT service objects and is used in test cases in place of a mock and on the
+// Linux desktop.
+class CHROMEOS_EXPORT FakeBluetoothGattServiceClient
+    : public BluetoothGattServiceClient {
+ public:
+  struct Properties : public BluetoothGattServiceClient::Properties {
+    explicit Properties(const PropertyChangedCallback& callback);
+    virtual ~Properties();
+
+    // dbus::PropertySet override
+    virtual void Get(dbus::PropertyBase* property,
+                     dbus::PropertySet::GetCallback callback) OVERRIDE;
+    virtual void GetAll() OVERRIDE;
+    virtual void Set(dbus::PropertyBase* property,
+                     dbus::PropertySet::SetCallback callback) OVERRIDE;
+  };
+
+  FakeBluetoothGattServiceClient();
+  virtual ~FakeBluetoothGattServiceClient();
+
+  // DBusClient override.
+  virtual void Init(dbus::Bus* bus) OVERRIDE;
+
+  // BluetoothGattServiceClient overrides.
+  virtual void AddObserver(Observer* observer) OVERRIDE;
+  virtual void RemoveObserver(Observer* observer) OVERRIDE;
+  virtual std::vector<dbus::ObjectPath> GetServices() OVERRIDE;
+  virtual Properties* GetProperties(const dbus::ObjectPath& object_path)
+      OVERRIDE;
+
+  // Makes a service visible for device with object path |device_path|. Note
+  // that only one instance of a specific service is simulated at a time. Hence,
+  // this method will fail, if the service is already visible.
+  void ExposeHeartRateService(const dbus::ObjectPath& device_path);
+  void HideHeartRateService();
+
+  // Final object path components and the corresponding UUIDs of the GATT
+  // services that we emulate. Service paths are hierarchical to Bluetooth
+  // device paths, so if the path component is "service0000", and the device
+  // path is "/org/foo/device0", the service path is
+  // "/org/foo/device0/service0000".
+  static const char kHeartRateServicePathComponent[];
+  static const char kHeartRateServiceUUID[];
+
+ private:
+  // Property callback passed when we create Properties structures.
+  void OnPropertyChanged(const dbus::ObjectPath& object_path,
+                         const std::string& property_name);
+
+  // Notifies observers.
+  void NotifyServiceAdded(const dbus::ObjectPath& object_path);
+  void NotifyServiceRemoved(const dbus::ObjectPath& object_path);
+
+  // Static properties we return. As long as a service is exposed, this will be
+  // non-null. Otherwise it will be null.
+  scoped_ptr<Properties> heart_rate_service_properties_;
+  std::string heart_rate_service_path_;
+
+  // List of observers interested in event notifications from us.
+  ObserverList<Observer> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeBluetoothGattServiceClient);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_DBUS_FAKE_BLUETOOTH_GATT_SERVICE_CLIENT_H_
diff --git a/chromeos/dbus/fake_cryptohome_client.cc b/chromeos/dbus/fake_cryptohome_client.cc
index df33138..0a54ff0 100644
--- a/chromeos/dbus/fake_cryptohome_client.cc
+++ b/chromeos/dbus/fake_cryptohome_client.cc
@@ -420,6 +420,14 @@
   ReturnProtobufMethodCallback(id.email(), callback);
 }
 
+void FakeCryptohomeClient::RemoveKeyEx(
+    const cryptohome::AccountIdentifier& id,
+    const cryptohome::AuthorizationRequest& auth,
+    const cryptohome::RemoveKeyRequest& request,
+    const ProtobufMethodCallback& callback) {
+  ReturnProtobufMethodCallback(id.email(), callback);
+}
+
 void FakeCryptohomeClient::UpdateKeyEx(
     const cryptohome::AccountIdentifier& id,
     const cryptohome::AuthorizationRequest& auth,
diff --git a/chromeos/dbus/fake_cryptohome_client.h b/chromeos/dbus/fake_cryptohome_client.h
index f1b6538..6c1ea8e 100644
--- a/chromeos/dbus/fake_cryptohome_client.h
+++ b/chromeos/dbus/fake_cryptohome_client.h
@@ -180,6 +180,10 @@
       const cryptohome::AuthorizationRequest& auth,
       const cryptohome::UpdateKeyRequest& request,
       const ProtobufMethodCallback& callback) OVERRIDE;
+  virtual void RemoveKeyEx(const cryptohome::AccountIdentifier& id,
+                           const cryptohome::AuthorizationRequest& auth,
+                           const cryptohome::RemoveKeyRequest& request,
+                           const ProtobufMethodCallback& callback) OVERRIDE;
 
   // Changes the behavior of WaitForServiceToBeAvailable(). This method runs
   // pending callbacks if is_available is true.
diff --git a/chromeos/dbus/fake_dbus_thread_manager.cc b/chromeos/dbus/fake_dbus_thread_manager.cc
index b5bb787..467178b 100644
--- a/chromeos/dbus/fake_dbus_thread_manager.cc
+++ b/chromeos/dbus/fake_dbus_thread_manager.cc
@@ -14,6 +14,9 @@
 #include "chromeos/dbus/fake_bluetooth_adapter_client.h"
 #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h"
 #include "chromeos/dbus/fake_bluetooth_device_client.h"
+#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h"
+#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h"
+#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
 #include "chromeos/dbus/fake_bluetooth_input_client.h"
 #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
 #include "chromeos/dbus/fake_cryptohome_client.h"
@@ -59,6 +62,13 @@
       new FakeBluetoothAgentManagerClient));
   SetBluetoothDeviceClient(
       scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient));
+  SetBluetoothGattCharacteristicClient(
+      scoped_ptr<BluetoothGattCharacteristicClient>(
+          new FakeBluetoothGattCharacteristicClient));
+  SetBluetoothGattDescriptorClient(scoped_ptr<BluetoothGattDescriptorClient>(
+      new FakeBluetoothGattDescriptorClient));
+  SetBluetoothGattServiceClient(scoped_ptr<BluetoothGattServiceClient>(
+      new FakeBluetoothGattServiceClient));
   SetBluetoothInputClient(
       scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient));
   SetBluetoothProfileManagerClient(scoped_ptr<BluetoothProfileManagerClient>(
@@ -139,6 +149,21 @@
   bluetooth_device_client_ = client.Pass();
 }
 
+void FakeDBusThreadManager::SetBluetoothGattCharacteristicClient(
+    scoped_ptr<BluetoothGattCharacteristicClient> client) {
+  bluetooth_gatt_characteristic_client_ = client.Pass();
+}
+
+void FakeDBusThreadManager::SetBluetoothGattDescriptorClient(
+    scoped_ptr<BluetoothGattDescriptorClient> client) {
+  bluetooth_gatt_descriptor_client_ = client.Pass();
+}
+
+void FakeDBusThreadManager::SetBluetoothGattServiceClient(
+    scoped_ptr<BluetoothGattServiceClient> client) {
+  bluetooth_gatt_service_client_ = client.Pass();
+}
+
 void FakeDBusThreadManager::SetBluetoothInputClient(
     scoped_ptr<BluetoothInputClient> client) {
   bluetooth_input_client_ = client.Pass();
@@ -304,6 +329,21 @@
   return bluetooth_device_client_.get();
 }
 
+BluetoothGattCharacteristicClient*
+    FakeDBusThreadManager::GetBluetoothGattCharacteristicClient() {
+  return bluetooth_gatt_characteristic_client_.get();
+}
+
+BluetoothGattDescriptorClient*
+    FakeDBusThreadManager::GetBluetoothGattDescriptorClient() {
+  return bluetooth_gatt_descriptor_client_.get();
+}
+
+BluetoothGattServiceClient*
+    FakeDBusThreadManager::GetBluetoothGattServiceClient() {
+  return bluetooth_gatt_service_client_.get();
+}
+
 BluetoothInputClient*
     FakeDBusThreadManager::GetBluetoothInputClient() {
   return bluetooth_input_client_.get();
diff --git a/chromeos/dbus/fake_dbus_thread_manager.h b/chromeos/dbus/fake_dbus_thread_manager.h
index 74ab40d..7a3ae7a 100644
--- a/chromeos/dbus/fake_dbus_thread_manager.h
+++ b/chromeos/dbus/fake_dbus_thread_manager.h
@@ -41,6 +41,12 @@
   void SetBluetoothAgentManagerClient(
       scoped_ptr<BluetoothAgentManagerClient> client);
   void SetBluetoothDeviceClient(scoped_ptr<BluetoothDeviceClient> client);
+  void SetBluetoothGattCharacteristicClient(
+      scoped_ptr<BluetoothGattCharacteristicClient> client);
+  void SetBluetoothGattDescriptorClient(
+      scoped_ptr<BluetoothGattDescriptorClient> client);
+  void SetBluetoothGattServiceClient(
+      scoped_ptr<BluetoothGattServiceClient> client);
   void SetBluetoothInputClient(scoped_ptr<BluetoothInputClient> client);
   void SetBluetoothProfileManagerClient(
       scoped_ptr<BluetoothProfileManagerClient> client);
@@ -78,6 +84,11 @@
   virtual BluetoothAgentManagerClient*
       GetBluetoothAgentManagerClient() OVERRIDE;
   virtual BluetoothDeviceClient* GetBluetoothDeviceClient() OVERRIDE;
+  virtual BluetoothGattCharacteristicClient*
+      GetBluetoothGattCharacteristicClient() OVERRIDE;
+  virtual BluetoothGattDescriptorClient*
+      GetBluetoothGattDescriptorClient() OVERRIDE;
+  virtual BluetoothGattServiceClient* GetBluetoothGattServiceClient() OVERRIDE;
   virtual BluetoothInputClient* GetBluetoothInputClient() OVERRIDE;
   virtual BluetoothProfileManagerClient*
       GetBluetoothProfileManagerClient() OVERRIDE;
@@ -115,6 +126,11 @@
   scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_;
   scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_;
   scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_;
+  scoped_ptr<BluetoothGattCharacteristicClient>
+      bluetooth_gatt_characteristic_client_;
+  scoped_ptr<BluetoothGattDescriptorClient>
+      bluetooth_gatt_descriptor_client_;
+  scoped_ptr<BluetoothGattServiceClient> bluetooth_gatt_service_client_;
   scoped_ptr<BluetoothInputClient> bluetooth_input_client_;
   scoped_ptr<BluetoothProfileManagerClient> bluetooth_profile_manager_client_;
   scoped_ptr<CrasAudioClient> cras_audio_client_;
diff --git a/chromeos/dbus/fake_update_engine_client.cc b/chromeos/dbus/fake_update_engine_client.cc
index a246c41..b87b798 100644
--- a/chromeos/dbus/fake_update_engine_client.cc
+++ b/chromeos/dbus/fake_update_engine_client.cc
@@ -32,6 +32,13 @@
   callback.Run(update_check_result_);
 }
 
+void FakeUpdateEngineClient::Rollback() {
+}
+
+void FakeUpdateEngineClient::CanRollbackCheck(
+    const RollbackCheckCallback& callback) {
+}
+
 void FakeUpdateEngineClient::RebootAfterUpdate() {
   reboot_after_update_call_count_++;
 }
diff --git a/chromeos/dbus/fake_update_engine_client.h b/chromeos/dbus/fake_update_engine_client.h
index c5afe18..8768e31 100644
--- a/chromeos/dbus/fake_update_engine_client.h
+++ b/chromeos/dbus/fake_update_engine_client.h
@@ -28,6 +28,9 @@
   virtual bool HasObserver(Observer* observer) OVERRIDE;
   virtual void RequestUpdateCheck(const UpdateCheckCallback& callback) OVERRIDE;
   virtual void RebootAfterUpdate() OVERRIDE;
+  virtual void Rollback() OVERRIDE;
+  virtual void CanRollbackCheck(
+      const RollbackCheckCallback& callback) OVERRIDE;
   virtual Status GetLastStatus() OVERRIDE;
   virtual void SetChannel(const std::string& target_channel,
                           bool is_powerwash_allowed) OVERRIDE;
diff --git a/chromeos/dbus/mock_cryptohome_client.h b/chromeos/dbus/mock_cryptohome_client.h
index f36bbb5..5eb251d 100644
--- a/chromeos/dbus/mock_cryptohome_client.h
+++ b/chromeos/dbus/mock_cryptohome_client.h
@@ -185,6 +185,11 @@
            const cryptohome::AuthorizationRequest& auth,
            const cryptohome::UpdateKeyRequest& request,
            const ProtobufMethodCallback& callback));
+  MOCK_METHOD4(RemoveKeyEx,
+               void(const cryptohome::AccountIdentifier& id,
+                    const cryptohome::AuthorizationRequest& auth,
+                    const cryptohome::RemoveKeyRequest& request,
+                    const ProtobufMethodCallback& callback));
 };
 
 }  // namespace chromeos
diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc
index bd2ec59..be8fb6d 100644
--- a/chromeos/dbus/power_manager_client.cc
+++ b/chromeos/dbus/power_manager_client.cc
@@ -81,7 +81,7 @@
   virtual void DecreaseScreenBrightness(bool allow_off) OVERRIDE {
     dbus::MethodCall method_call(
         power_manager::kPowerManagerInterface,
-        power_manager::kDecreaseScreenBrightness);
+        power_manager::kDecreaseScreenBrightnessMethod);
     dbus::MessageWriter writer(&method_call);
     writer.AppendBool(allow_off);
     power_manager_proxy_->CallMethod(
@@ -91,22 +91,25 @@
   }
 
   virtual void IncreaseScreenBrightness() OVERRIDE {
-    SimpleMethodCallToPowerManager(power_manager::kIncreaseScreenBrightness);
+    SimpleMethodCallToPowerManager(
+        power_manager::kIncreaseScreenBrightnessMethod);
   }
 
   virtual void DecreaseKeyboardBrightness() OVERRIDE {
-    SimpleMethodCallToPowerManager(power_manager::kDecreaseKeyboardBrightness);
+    SimpleMethodCallToPowerManager(
+        power_manager::kDecreaseKeyboardBrightnessMethod);
   }
 
   virtual void IncreaseKeyboardBrightness() OVERRIDE {
-    SimpleMethodCallToPowerManager(power_manager::kIncreaseKeyboardBrightness);
+    SimpleMethodCallToPowerManager(
+        power_manager::kIncreaseKeyboardBrightnessMethod);
   }
 
   virtual void SetScreenBrightnessPercent(double percent,
                                           bool gradual) OVERRIDE {
     dbus::MethodCall method_call(
         power_manager::kPowerManagerInterface,
-        power_manager::kSetScreenBrightnessPercent);
+        power_manager::kSetScreenBrightnessPercentMethod);
     dbus::MessageWriter writer(&method_call);
     writer.AppendDouble(percent);
     writer.AppendInt32(
@@ -121,8 +124,9 @@
 
   virtual void GetScreenBrightnessPercent(
       const GetScreenBrightnessPercentCallback& callback) OVERRIDE {
-    dbus::MethodCall method_call(power_manager::kPowerManagerInterface,
-                                 power_manager::kGetScreenBrightnessPercent);
+    dbus::MethodCall method_call(
+        power_manager::kPowerManagerInterface,
+        power_manager::kGetScreenBrightnessPercentMethod);
     power_manager_proxy_->CallMethod(
         &method_call,
         dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
@@ -409,7 +413,7 @@
       dbus::Response* response) {
     if (!response) {
       LOG(ERROR) << "Error calling "
-                 << power_manager::kGetScreenBrightnessPercent;
+                 << power_manager::kGetScreenBrightnessPercentMethod;
       return;
     }
     dbus::MessageReader reader(response);
diff --git a/chromeos/dbus/update_engine_client.cc b/chromeos/dbus/update_engine_client.cc
index 4c3fb99..e9f68f8 100644
--- a/chromeos/dbus/update_engine_client.cc
+++ b/chromeos/dbus/update_engine_client.cc
@@ -27,7 +27,7 @@
 // Delay between successive state transitions during AU.
 const int kStateTransitionDefaultDelayMs = 3000;
 
-// Delay between successive notificatioins about downloading progress
+// Delay between successive notifications about downloading progress
 // during fake AU.
 const int kStateTransitionDownloadingDelayMs = 250;
 
@@ -123,6 +123,37 @@
                    weak_ptr_factory_.GetWeakPtr()));
   }
 
+  virtual void Rollback() OVERRIDE {
+    VLOG(1) << "Requesting a rollback";
+     dbus::MethodCall method_call(
+        update_engine::kUpdateEngineInterface,
+        update_engine::kAttemptRollback);
+    dbus::MessageWriter writer(&method_call);
+    writer.AppendBool(true /* powerwash */);
+
+    update_engine_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::Bind(&UpdateEngineClientImpl::OnRollback,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+
+
+  virtual void CanRollbackCheck(
+      const RollbackCheckCallback& callback) OVERRIDE {
+    dbus::MethodCall method_call(
+        update_engine::kUpdateEngineInterface,
+        update_engine::kCanRollback);
+
+    VLOG(1) << "Requesting to get rollback availability status";
+    update_engine_proxy_->CallMethod(
+        &method_call,
+        dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+        base::Bind(&UpdateEngineClientImpl::OnCanRollbackCheck,
+                   weak_ptr_factory_.GetWeakPtr(),
+                   callback));
+  }
+
   virtual Status GetLastStatus() OVERRIDE {
     return last_status_;
   }
@@ -226,6 +257,33 @@
     }
   }
 
+  // Called when a response for Rollback() is received.
+  void OnRollback(dbus::Response* response) {
+    if (!response) {
+      LOG(ERROR) << "Failed to rollback";
+      return;
+    }
+  }
+
+  // Called when a response for CanRollbackCheck() is received.
+  void OnCanRollbackCheck(const RollbackCheckCallback& callback,
+                          dbus::Response* response) {
+    if (!response) {
+      LOG(ERROR) << "Failed to request rollback availability status";
+      callback.Run(false);
+      return;
+    }
+    dbus::MessageReader reader(response);
+    bool can_rollback;
+    if (!reader.PopBool(&can_rollback)) {
+      LOG(ERROR) << "Incorrect response: " << response->ToString();
+      callback.Run(false);
+      return;
+    }
+    VLOG(1) << "Rollback availability status received: " << can_rollback;
+    callback.Run(can_rollback);
+  }
+
   // Called when a response for GetStatus is received.
   void OnGetStatus(dbus::Response* response) {
     if (!response) {
@@ -346,17 +404,22 @@
     callback.Run(UPDATE_RESULT_NOTIMPLEMENTED);
   }
   virtual void RebootAfterUpdate() OVERRIDE {}
+  virtual void Rollback() OVERRIDE {}
+  virtual void CanRollbackCheck(
+      const RollbackCheckCallback& callback) OVERRIDE {
+    callback.Run(true);
+  }
   virtual Status GetLastStatus() OVERRIDE { return Status(); }
   virtual void SetChannel(const std::string& target_channel,
                           bool is_powerwash_allowed) OVERRIDE {
-    LOG(INFO) << "Requesting to set channel: "
-              << "target_channel=" << target_channel << ", "
-              << "is_powerwash_allowed=" << is_powerwash_allowed;
+    VLOG(1) << "Requesting to set channel: "
+            << "target_channel=" << target_channel << ", "
+            << "is_powerwash_allowed=" << is_powerwash_allowed;
   }
   virtual void GetChannel(bool get_current_channel,
                           const GetChannelCallback& callback) OVERRIDE {
-    LOG(INFO) << "Requesting to get channel, get_current_channel="
-              << get_current_channel;
+    VLOG(1) << "Requesting to get channel, get_current_channel="
+            << get_current_channel;
     callback.Run(kReleaseChannelBeta);
   }
 };
diff --git a/chromeos/dbus/update_engine_client.h b/chromeos/dbus/update_engine_client.h
index 2923c6b..31af616 100644
--- a/chromeos/dbus/update_engine_client.h
+++ b/chromeos/dbus/update_engine_client.h
@@ -84,6 +84,17 @@
   // Reboots if update has been performed.
   virtual void RebootAfterUpdate() = 0;
 
+  // Starts Rollback.
+  virtual void Rollback() = 0;
+
+  // Called once CanRollbackCheck() is complete. Takes one parameter:
+  // - bool: the result of the rollback availability check.
+  typedef base::Callback<void(bool can_rollback)> RollbackCheckCallback;
+
+  // Checks if Rollback is available and calls |callback| when completed.
+  virtual void CanRollbackCheck(
+      const RollbackCheckCallback& callback) = 0;
+
   // Called once GetChannel() is complete. Takes one parameter;
   // - string: the channel name like "beta-channel".
   typedef base::Callback<void(const std::string& channel_name)>
diff --git a/chromeos/disks/mock_disk_mount_manager.cc b/chromeos/disks/mock_disk_mount_manager.cc
index 6e21d75..c1665b7 100644
--- a/chromeos/disks/mock_disk_mount_manager.cc
+++ b/chromeos/disks/mock_disk_mount_manager.cc
@@ -181,25 +181,28 @@
     const std::string& vendor_name,
     const std::string& product_name,
     DeviceType device_type,
-    uint64 total_size_in_bytes) {
-  Disk* disk = new DiskMountManager::Disk(std::string(mount_info.source_path),
-                                          std::string(mount_info.mount_path),
+    uint64 total_size_in_bytes,
+    bool is_parent,
+    bool has_media,
+    bool on_boot_device) {
+  Disk* disk = new DiskMountManager::Disk(mount_info.source_path,
+                                          mount_info.mount_path,
                                           std::string(),  // system_path
-                                          std::string(),  // file_path
-                                          device_label,  // device_label
+                                          mount_info.source_path,
+                                          device_label,
                                           std::string(),  // drive_label
                                           std::string(),  // vendor_id
                                           vendor_name,
                                           std::string(),  // product_id
                                           product_name,
-                                          device_id,  // fs_uuid
+                                          device_id,      // fs_uuid
                                           std::string(),  // system_path_prefix
                                           device_type,
                                           total_size_in_bytes,
-                                          false,  // is_parent
+                                          is_parent,
                                           false,  // is_read_only
-                                          true,  // has_media
-                                          false,  // on_boot_device
+                                          has_media,
+                                          on_boot_device,
                                           false);  // is_hidden
   DiskMountManager::DiskMap::iterator it = disks_.find(mount_info.source_path);
   if (it == disks_.end()) {
diff --git a/chromeos/disks/mock_disk_mount_manager.h b/chromeos/disks/mock_disk_mount_manager.h
index ef3967b..f7baa8e 100644
--- a/chromeos/disks/mock_disk_mount_manager.h
+++ b/chromeos/disks/mock_disk_mount_manager.h
@@ -16,6 +16,8 @@
 namespace chromeos {
 namespace disks {
 
+// TODO(tbarzic): Replace this mock with a fake implementation
+// (http://crbug.com/355757)
 class MockDiskMountManager : public DiskMountManager {
  public:
   MockDiskMountManager();
@@ -60,7 +62,10 @@
       const std::string& vendor_name,
       const std::string& product_name,
       DeviceType device_type,
-      uint64 total_size_in_bytes);
+      uint64 total_size_in_bytes,
+      bool is_parent,
+      bool has_media,
+      bool on_boot_device);
 
   // Removes the fake disk entry associated with the mounted device. This
   // function is primarily for StorageMonitorTest.
diff --git a/chromeos/ime/OWNERS b/chromeos/ime/OWNERS
index 7a78757..631c968 100644
--- a/chromeos/ime/OWNERS
+++ b/chromeos/ime/OWNERS
@@ -1,3 +1,7 @@
+# primary reviewer
+yukishiino@chromium.org
+
+# backup reviewers
 komatsu@chromium.org
 nona@chromium.org
 satorux@chromium.org
diff --git a/chromeos/ime/component_extension_ime_manager.cc b/chromeos/ime/component_extension_ime_manager.cc
index e39537a..d34ef19 100644
--- a/chromeos/ime/component_extension_ime_manager.cc
+++ b/chromeos/ime/component_extension_ime_manager.cc
@@ -203,8 +203,8 @@
               // Enables extension based xkb keyboards on login screen.
               extension_ime_util::IsKeyboardLayoutExtension(
                   input_method_id) && IsInLoginLayoutWhitelist(layouts),
-              component_extension_imes_[i].options_page_url,
-              component_extension_imes_[i].input_view_url));
+              component_extension_imes_[i].engines[j].options_page_url,
+              component_extension_imes_[i].engines[j].input_view_url));
     }
   }
   return result;
diff --git a/chromeos/ime/component_extension_ime_manager.h b/chromeos/ime/component_extension_ime_manager.h
index bc26ec6..11f113f 100644
--- a/chromeos/ime/component_extension_ime_manager.h
+++ b/chromeos/ime/component_extension_ime_manager.h
@@ -24,6 +24,8 @@
   std::vector<std::string> language_codes;  // The engine's language(ex. "en").
   std::string description;  // The engine description.
   std::vector<std::string> layouts;  // The list of keyboard layout of engine.
+  GURL options_page_url; // an URL to option page.
+  GURL input_view_url; // an URL to input view page.
 };
 
 // Represents a component extension IME.
@@ -34,7 +36,6 @@
   std::string manifest;  // the contents of manifest.json
   std::string description;  // description of extension.
   GURL options_page_url; // an URL to option page.
-  GURL input_view_url; // an URL to input view page.
   base::FilePath path;
   std::vector<ComponentExtensionEngine> engines;
 };
diff --git a/chromeos/ime/fake_xkeyboard.cc b/chromeos/ime/fake_xkeyboard.cc
index 45bd5bf..6a7d7a4 100644
--- a/chromeos/ime/fake_xkeyboard.cc
+++ b/chromeos/ime/fake_xkeyboard.cc
@@ -38,6 +38,14 @@
   return caps_lock_is_enabled_;
 }
 
+bool FakeXKeyboard::IsISOLevel5ShiftAvailable() const {
+  return false;
+}
+
+bool FakeXKeyboard::IsAltGrAvailable() const {
+  return false;
+}
+
 bool FakeXKeyboard::SetAutoRepeatEnabled(bool enabled) {
   auto_repeat_is_enabled_ = enabled;
   return true;
diff --git a/chromeos/ime/fake_xkeyboard.h b/chromeos/ime/fake_xkeyboard.h
index c25b39f..df531ae 100644
--- a/chromeos/ime/fake_xkeyboard.h
+++ b/chromeos/ime/fake_xkeyboard.h
@@ -27,6 +27,8 @@
   virtual void DisableNumLock() OVERRIDE;
   virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE;
   virtual bool CapsLockIsEnabled() OVERRIDE;
+  virtual bool IsISOLevel5ShiftAvailable() const OVERRIDE;
+  virtual bool IsAltGrAvailable() const OVERRIDE;
   virtual bool SetAutoRepeatEnabled(bool enabled) OVERRIDE;
   virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) OVERRIDE;
 
diff --git a/chromeos/ime/input_method_manager.h b/chromeos/ime/input_method_manager.h
index e344770..dbbed38 100644
--- a/chromeos/ime/input_method_manager.h
+++ b/chromeos/ime/input_method_manager.h
@@ -157,6 +157,10 @@
   // Gets the descriptor of the input method which is currently selected.
   virtual InputMethodDescriptor GetCurrentInputMethod() const = 0;
 
+  virtual bool IsISOLevel5ShiftUsedByCurrentInputMethod() const = 0;
+
+  virtual bool IsAltGrUsedByCurrentInputMethod() const = 0;
+
   // Returns an X keyboard object which could be used to change the current XKB
   // layout, change the caps lock status, and set the auto repeat rate/interval.
   virtual XKeyboard* GetXKeyboard() = 0;
diff --git a/chromeos/ime/input_methods.txt b/chromeos/ime/input_methods.txt
index a570da7..d053d12 100644
--- a/chromeos/ime/input_methods.txt
+++ b/chromeos/ime/input_methods.txt
@@ -34,10 +34,12 @@
 #    * chrome/browser/resources/chromeos/keyboard_overlay_data.js
 #    * chrome/browser/ui/webui/chromeos/keyboard_overlay_ui.cc
 #
-#   If you add an XKB layout which depends on X11's Mod3Mask (e.g. Germany Neo2
-#   XKB layout), you should also update IsMod3UsedByCurrentInputMethod() method
-#   in chrome/browser/ui/ash/event_rewriter.cc. Otherwise, Mod3Mask might be
-#   removed unexpectedly by the rewriter.
+#   If you add an XKB layout which depends on AltGr or X11's Mod3Mask
+#   (e.g. Germany Neo2 XKB layout), you should also update kAltGrLayoutIds or
+#   kMod3LayoutIds in
+#   chrome/browser/chromeos/input_method/input_method_manager_impl.cc
+#   Otherwise, Mod3Mask might be removed unexpectedly by the rewriter, and
+#   sticky keys will not work.
 #
 
 # U.S. English
diff --git a/chromeos/ime/xkeyboard.cc b/chromeos/ime/xkeyboard.cc
index e0e69cf..b2f55f1 100644
--- a/chromeos/ime/xkeyboard.cc
+++ b/chromeos/ime/xkeyboard.cc
@@ -45,6 +45,54 @@
 // A string for obtaining a mask value for Num Lock.
 const char kNumLockVirtualModifierString[] = "NumLock";
 
+const char *kISOLevel5ShiftLayoutIds[] = {
+  "ca(multix)",
+  "de(neo)",
+};
+
+const char *kAltGrLayoutIds[] = {
+  "be",
+  "be",
+  "be",
+  "bg",
+  "bg(phonetic)",
+  "br",
+  "ca",
+  "ca(eng)",
+  "ca(multix)",
+  "ch",
+  "ch(fr)",
+  "cz",
+  "de",
+  "de(neo)",
+  "dk",
+  "ee",
+  "es",
+  "es(cat)",
+  "fi",
+  "fr",
+  "gb(dvorak)",
+  "gb(extd)",
+  "gr",
+  "hr",
+  "il",
+  "it",
+  "latam",
+  "lt",
+  "no",
+  "pl",
+  "pt",
+  "ro",
+  "se",
+  "si",
+  "sk",
+  "tr",
+  "ua",
+  "us(altgr-intl)",
+  "us(intl)",
+};
+
+
 // Returns false if |layout_name| contains a bad character.
 bool CheckLayoutName(const std::string& layout_name) {
   static const char kValidLayoutNameCharacters[] =
@@ -77,6 +125,8 @@
   virtual void DisableNumLock() OVERRIDE;
   virtual void SetCapsLockEnabled(bool enable_caps_lock) OVERRIDE;
   virtual bool CapsLockIsEnabled() OVERRIDE;
+  virtual bool IsISOLevel5ShiftAvailable() const OVERRIDE;
+  virtual bool IsAltGrAvailable() const OVERRIDE;
   virtual bool SetAutoRepeatEnabled(bool enabled) OVERRIDE;
   virtual bool SetAutoRepeatRate(const AutoRepeatRate& rate) OVERRIDE;
 
@@ -288,6 +338,23 @@
   return (status.locked_mods & LockMask);
 }
 
+bool XKeyboardImpl::IsISOLevel5ShiftAvailable() const {
+  for (size_t i = 0; i < arraysize(kISOLevel5ShiftLayoutIds); ++i) {
+    if (current_layout_name_ == kISOLevel5ShiftLayoutIds[i])
+      return true;
+  }
+  return false;
+}
+
+bool XKeyboardImpl::IsAltGrAvailable() const {
+  for (size_t i = 0; i < arraysize(kAltGrLayoutIds); ++i) {
+    if (current_layout_name_ == kAltGrLayoutIds[i])
+      return true;
+  }
+  return false;
+}
+
+
 bool XKeyboardImpl::SetAutoRepeatEnabled(bool enabled) {
   if (enabled)
     XAutoRepeatOn(GetXDisplay());
diff --git a/chromeos/ime/xkeyboard.h b/chromeos/ime/xkeyboard.h
index eae5e7c..b07e4f4 100644
--- a/chromeos/ime/xkeyboard.h
+++ b/chromeos/ime/xkeyboard.h
@@ -70,6 +70,12 @@
   // threads.
   virtual bool CapsLockIsEnabled() = 0;
 
+  // Returns true if the current layout supports ISO Level 5 shift.
+  virtual bool IsISOLevel5ShiftAvailable() const = 0;
+
+  // Returns true if the current layout supports alt gr.
+  virtual bool IsAltGrAvailable() const = 0;
+
   // Turns on and off the auto-repeat of the keyboard. Returns true on success.
   // Do not call the function from non-UI threads.
   virtual bool SetAutoRepeatEnabled(bool enabled) = 0;
diff --git a/chromeos/network/favorite_state.cc b/chromeos/network/favorite_state.cc
index 0ba576f..8ad9d3f 100644
--- a/chromeos/network/favorite_state.cc
+++ b/chromeos/network/favorite_state.cc
@@ -25,6 +25,13 @@
 
 bool FavoriteState::PropertyChanged(const std::string& key,
                                     const base::Value& value) {
+  // All property values except UIData (which may contain a lengthy
+  // certificate pattern) and passphrase entries get stored in |properties_|.
+  if (key != shill::kUIDataProperty &&
+      !shill_property_util::IsPassphraseKey(key)) {
+    properties_.SetWithoutPathExpansion(key, value.DeepCopy());
+  }
+
   if (ManagedStatePropertyChanged(key, value))
     return true;
   if (key == shill::kProfileProperty) {
@@ -37,6 +44,15 @@
       return false;
     }
     ui_data_ = *new_ui_data;
+
+    // Add ONCSource to |properties_| for debugging.
+    scoped_ptr<base::DictionaryValue> onc_dict(new base::DictionaryValue);
+    ui_data_.FillDictionary(onc_dict.get());
+    std::string onc_source;
+    onc_dict->GetStringWithoutPathExpansion(NetworkUIData::kKeyONCSource,
+                                            &onc_source);
+    properties_.SetStringWithoutPathExpansion(NetworkUIData::kKeyONCSource,
+                                              onc_source);
     return true;
   } else if (key == shill::kGuidProperty) {
     return GetStringValue(key, value, &guid_);
@@ -67,26 +83,16 @@
   return false;
 }
 
+bool FavoriteState::IsFavorite() const {
+  // kTypeEthernetEap is always a favorite. We need this check because it does
+  // not show up in the visible list, but its properties may not be available
+  // when it first shows up in ServiceCompleteList. See crbug.com/355117.
+  return !profile_path_.empty() || type() == shill::kTypeEthernetEap;
+}
+
 bool FavoriteState::IsPrivate() const {
   return !profile_path_.empty() &&
       profile_path_ != NetworkProfileHandler::GetSharedProfilePath();
 }
 
-void FavoriteState::GetProperties(base::DictionaryValue* dictionary) const {
-  dictionary->SetStringWithoutPathExpansion(shill::kNameProperty, name());
-  dictionary->SetStringWithoutPathExpansion(shill::kTypeProperty, type());
-  dictionary->SetStringWithoutPathExpansion(shill::kProfileProperty,
-                                            profile_path_);
-  dictionary->SetStringWithoutPathExpansion(shill::kGuidProperty, guid_);
-
-  // ONCSource is used for debugging in chrome://network.
-  scoped_ptr<base::DictionaryValue> onc_dict(new base::DictionaryValue);
-  ui_data_.FillDictionary(onc_dict.get());
-  std::string onc_source;
-  onc_dict->GetStringWithoutPathExpansion(NetworkUIData::kKeyONCSource,
-                                          &onc_source);
-  dictionary->SetStringWithoutPathExpansion(NetworkUIData::kKeyONCSource,
-                                            onc_source);
-}
-
 }  // namespace chromeos
diff --git a/chromeos/network/favorite_state.h b/chromeos/network/favorite_state.h
index e1d8e11..bb468a7 100644
--- a/chromeos/network/favorite_state.h
+++ b/chromeos/network/favorite_state.h
@@ -20,7 +20,7 @@
 // Note: NetworkStateHandler will store an entry for each member of
 // Manager.ServiceCompleteList, even for visible entries that are not
 // favorites. This is necessary to avoid unnecessarily re-requesting entries,
-// and to limit the code complexity. The is_favorite() accessor is used to skip
+// and to limit the code complexity. The IsFavorite() accessor is used to skip
 // entries that are not actually favorites.
 class CHROMEOS_EXPORT FavoriteState : public ManagedState {
  public:
@@ -33,19 +33,17 @@
 
   // Accessors
   const std::string& profile_path() const { return profile_path_; }
-  bool is_favorite() const { return !profile_path_.empty(); }
   const NetworkUIData& ui_data() const { return ui_data_; }
   const base::DictionaryValue& proxy_config() const { return proxy_config_; }
   const std::string& guid() const { return guid_; }
+  const base::DictionaryValue& properties() const { return properties_; }
+
+  // Returns true if this is a favorite stored in a profile (see note above).
+  bool IsFavorite() const;
 
   // Returns true if the network properties are stored in a user profile.
   bool IsPrivate() const;
 
-  // Fills |dictionary| with the state properties. Only properties that are
-  // parsed by PropertyChanged are stored in |dictionary|. The dictionary
-  // includes the 'onc_source' property from |ui_data_|.
-  void GetProperties(base::DictionaryValue* dictionary) const;
-
  private:
   std::string profile_path_;
   NetworkUIData ui_data_;
@@ -55,6 +53,11 @@
   // provides proxy configuration. crbug.com/241775
   base::DictionaryValue proxy_config_;
 
+  // Keep all Favorite properties in a dictionary so that all configured
+  // properties can be examined for debugging. Since the Favorite list is
+  // mostly fixed, the overhead should be reasonable.
+  base::DictionaryValue properties_;
+
   DISALLOW_COPY_AND_ASSIGN(FavoriteState);
 };
 
diff --git a/chromeos/network/managed_network_configuration_handler_impl.cc b/chromeos/network/managed_network_configuration_handler_impl.cc
index 67ab01f..f233147 100644
--- a/chromeos/network/managed_network_configuration_handler_impl.cc
+++ b/chromeos/network/managed_network_configuration_handler_impl.cc
@@ -69,7 +69,10 @@
 void LogErrorWithDict(const tracked_objects::Location& from_where,
                       const std::string& error_name,
                       scoped_ptr<base::DictionaryValue> error_data) {
-  LOG(ERROR) << from_where.ToString() << ": " << error_name;
+  network_event_log::internal::AddEntry(
+       from_where.file_name(), from_where.line_number(),
+       network_event_log::LOG_LEVEL_ERROR,
+       error_name, "");
 }
 
 const base::DictionaryValue* GetByGUID(const GuidToPolicyMap& policies,
@@ -143,10 +146,8 @@
                                                  &profile_path);
   const NetworkProfile* profile =
       network_profile_handler_->GetProfileForPath(profile_path);
-  if (!profile) {
-    LOG(ERROR) << "No or no known profile received for service "
-            << service_path << ".";
-  }
+  if (!profile)
+    NET_LOG_ERROR("No profile for service: " + profile_path, service_path);
 
   scoped_ptr<NetworkUIData> ui_data =
       shill_property_util::GetUIDataFromProperties(shill_properties);
@@ -162,8 +163,7 @@
     else
       NOTREACHED();
   } else if (profile) {
-    LOG(WARNING) << "Service " << service_path << " of profile "
-                 << profile_path << " contains no or no valid UIData.";
+    NET_LOG_ERROR("Service contains empty or invalid UIData", service_path);
     // TODO(pneubeck): add a conversion of user configured entries of old
     // ChromeOS versions. We will have to use a heuristic to determine which
     // properties _might_ be user configured.
@@ -377,9 +377,8 @@
     DCHECK(!guid.empty());
 
     if (policies->per_network_config.count(guid) > 0) {
-      LOG(ERROR) << "ONC from " << ToDebugString(onc_source, userhash)
-                 << " contains several entries for the same GUID "
-                 << guid << ".";
+      NET_LOG_ERROR("ONC from " + ToDebugString(onc_source, userhash) +
+                    " contains several entries for the same GUID ", guid);
       delete policies->per_network_config[guid];
     }
     const base::DictionaryValue* new_entry = network->DeepCopy();
@@ -461,7 +460,9 @@
   existing_properties.GetStringWithoutPathExpansion(shill::kProfileProperty,
                                                     &profile);
   if (profile.empty()) {
-    LOG(ERROR) << "Missing profile property.";
+    NET_LOG_ERROR("Missing profile property",
+                  shill_property_util::GetNetworkIdFromProperties(
+                      existing_properties));
     return;
   }
   shill_properties.SetStringWithoutPathExpansion(shill::kProfileProperty,
@@ -469,7 +470,9 @@
 
   if (!shill_property_util::CopyIdentifyingProperties(existing_properties,
                                                       &shill_properties)) {
-    LOG(ERROR) << "Missing identifying properties.";
+    NET_LOG_ERROR("Missing identifying properties",
+                  shill_property_util::GetNetworkIdFromProperties(
+                      existing_properties));
   }
 
   shill_properties.MergeDictionary(&new_properties);
@@ -536,7 +539,7 @@
   const NetworkProfile* profile =
       network_profile_handler_->GetProfileForPath(profile_path);
   if (!profile) {
-    LOG(ERROR) << "Profile path unknown: " << profile_path;
+    NET_LOG_ERROR("Profile path unknown:" + profile_path, guid);
     return NULL;
   }
 
diff --git a/chromeos/network/managed_state.cc b/chromeos/network/managed_state.cc
index b4f77fb..62e9db4 100644
--- a/chromeos/network/managed_state.cc
+++ b/chromeos/network/managed_state.cc
@@ -19,6 +19,19 @@
   return pattern.MatchesType(type());
 }
 
+// static
+std::string ManagedState::TypeToString(ManagedType type) {
+  switch (type) {
+    case MANAGED_TYPE_NETWORK:
+      return "Network";
+    case MANAGED_TYPE_FAVORITE:
+      return "Favorite";
+    case MANAGED_TYPE_DEVICE:
+      return "Device";
+  }
+  return "Unknown";
+}
+
 ManagedState::ManagedState(ManagedType type, const std::string& path)
     : managed_type_(type),
       path_(path),
@@ -107,7 +120,7 @@
                                   std::string* out_value) {
   std::string new_value;
   if (!value.GetAsString(&new_value)) {
-    NET_LOG_ERROR("Error parsing state value", path() + "." + key);
+    NET_LOG_ERROR("Error parsing state: " + key, path());
     return false;
   }
   if (*out_value == new_value)
diff --git a/chromeos/network/managed_state.h b/chromeos/network/managed_state.h
index 2cab509..4e7b9fa 100644
--- a/chromeos/network/managed_state.h
+++ b/chromeos/network/managed_state.h
@@ -77,6 +77,8 @@
 
   bool Matches(const NetworkTypePattern& pattern) const;
 
+  static std::string TypeToString(ManagedType type);
+
  protected:
   ManagedState(ManagedType type, const std::string& path);
 
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc
index ff81dee..ea81a75 100644
--- a/chromeos/network/network_configuration_handler.cc
+++ b/chromeos/network/network_configuration_handler.cc
@@ -53,13 +53,6 @@
     const std::string& service_path,
     DBusMethodCallStatus call_status,
     const base::DictionaryValue& properties) {
-  // Get the correct name from WifiHex if necessary.
-  scoped_ptr<base::DictionaryValue> properties_copy(properties.DeepCopy());
-  std::string name =
-      shill_property_util::GetNameFromProperties(service_path, properties);
-  if (!name.empty()) {
-    properties_copy->SetStringWithoutPathExpansion(shill::kNameProperty, name);
-  }
   if (call_status != DBUS_METHOD_CALL_SUCCESS) {
     // Because network services are added and removed frequently, we will see
     // failures regularly, so don't log these.
@@ -67,9 +60,18 @@
                                       service_path,
                                       network_handler::kDBusFailedError,
                                       network_handler::kDBusFailedErrorMessage);
-  } else if (!callback.is_null()) {
-    callback.Run(service_path, *properties_copy.get());
+    return;
   }
+  if (callback.is_null())
+    return;
+
+  // Get the correct name from WifiHex if necessary.
+  scoped_ptr<base::DictionaryValue> properties_copy(properties.DeepCopy());
+  std::string name =
+      shill_property_util::GetNameFromProperties(service_path, properties);
+  if (!name.empty())
+    properties_copy->SetStringWithoutPathExpansion(shill::kNameProperty, name);
+  callback.Run(service_path, *properties_copy.get());
 }
 
 void SetNetworkProfileErrorCallback(
@@ -84,25 +86,13 @@
       dbus_error_name, dbus_error_message);
 }
 
-bool IsPassphrase(const std::string& key) {
-  return key == shill::kEapPrivateKeyPasswordProperty ||
-      key == shill::kEapPasswordProperty ||
-      key == shill::kL2tpIpsecPasswordProperty ||
-      key == shill::kOpenVPNPasswordProperty ||
-      key == shill::kPassphraseProperty ||
-      key == shill::kOpenVPNOTPProperty ||
-      key == shill::kEapPrivateKeyProperty ||
-      key == shill::kEapPinProperty ||
-      key == shill::kApnPasswordProperty;
-}
-
 void LogConfigProperties(const std::string& desc,
                          const std::string& path,
                          const base::DictionaryValue& properties) {
   for (base::DictionaryValue::Iterator iter(properties);
        !iter.IsAtEnd(); iter.Advance()) {
     std::string v = "******";
-    if (!IsPassphrase(iter.key()))
+    if (!shill_property_util::IsPassphraseKey(iter.key()))
       base::JSONWriter::Write(&iter.value(), &v);
     NET_LOG_DEBUG(desc,  path + "." + iter.key() + "=" + v);
   }
@@ -279,15 +269,17 @@
       DBusThreadManager::Get()->GetShillManagerClient();
   std::string type;
   properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
+  DCHECK(!type.empty());
   if (NetworkTypePattern::Ethernet().MatchesType(type)) {
     InvokeErrorCallback(
-        "" /* no service path */,
+        shill_property_util::GetNetworkIdFromProperties(properties),
         error_callback,
-        "ConfigureServiceForProfile is not implemented for Ethernet");
+        "ConfigureServiceForProfile: Invalid type: " + type);
     return;
   }
 
-  NET_LOG_USER("CreateConfiguration", type);
+  NET_LOG_USER("CreateConfiguration: " + type,
+               shill_property_util::GetNetworkIdFromProperties(properties));
   LogConfigProperties("Configure", type, properties);
 
   std::string profile;
diff --git a/chromeos/network/network_configuration_handler_unittest.cc b/chromeos/network/network_configuration_handler_unittest.cc
index 03fabc4..f181848 100644
--- a/chromeos/network/network_configuration_handler_unittest.cc
+++ b/chromeos/network/network_configuration_handler_unittest.cc
@@ -346,9 +346,12 @@
 TEST_F(NetworkConfigurationHandlerTest, CreateConfiguration) {
   std::string networkName = "MyNetwork";
   std::string key = "SSID";
+  std::string type = "wifi";
   std::string profile = "profile path";
   base::DictionaryValue value;
   shill_property_util::SetSSID(networkName, &value);
+  value.SetWithoutPathExpansion(shill::kTypeProperty,
+                                base::Value::CreateStringValue(type));
   value.SetWithoutPathExpansion(shill::kProfileProperty,
                                 base::Value::CreateStringValue(profile));
 
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index e6f344d..5b2a85d 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -85,11 +85,10 @@
   } else if (key == shill::kErrorProperty) {
     if (!GetStringValue(key, value, &error_))
       return false;
-    // Shill uses "Unknown" to indicate an unset error state.
-    if (error_ == kErrorUnknown)
-      error_.clear();
-    if (!error_.empty())
+    if (ErrorIsValid(error_))
       last_error_ = error_;
+    else
+      error_.clear();
     return true;
   } else if (key == IPConfigProperty(shill::kAddressProperty)) {
     return GetStringValue(key, value, &ip_address_);
@@ -158,7 +157,13 @@
 bool NetworkState::InitialPropertiesReceived(
     const base::DictionaryValue& properties) {
   NET_LOG_DEBUG("InitialPropertiesReceived", path());
-  bool changed = UpdateName(properties);
+  bool changed = false;
+  if (!properties.HasKey(shill::kTypeProperty)) {
+    NET_LOG_ERROR("NetworkState has no type",
+                  shill_property_util::GetNetworkIdFromProperties(properties));
+  } else {
+    changed |= UpdateName(properties);
+  }
   bool had_ca_cert_nss = has_ca_cert_nss_;
   has_ca_cert_nss_ = IsCaCertNssSet(properties);
   changed |= had_ca_cert_nss != has_ca_cert_nss_;
@@ -278,6 +283,12 @@
 }
 
 // static
+bool NetworkState::ErrorIsValid(const std::string& error) {
+  // Shill uses "Unknown" to indicate an unset or cleared error state.
+  return !error.empty() && error != kErrorUnknown;
+}
+
+// static
 std::string NetworkState::IPConfigProperty(const char* key) {
   return base::StringPrintf("%s.%s", shill::kIPConfigProperty, key);
 }
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index c9b6dcb..8a74bcd 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -97,9 +97,10 @@
   // Converts the prefix length to a netmask string.
   std::string GetNetmask() const;
 
-  // Helpers (used e.g. when a state is cached)
+  // Helpers (used e.g. when a state or error is cached)
   static bool StateIsConnected(const std::string& connection_state);
   static bool StateIsConnecting(const std::string& connection_state);
+  static bool ErrorIsValid(const std::string& error);
 
   // Helper to return a full prefixed version of an IPConfig property key.
   static std::string IPConfigProperty(const char* key);
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index 42902d3..d754bbb 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -304,7 +304,7 @@
        iter != favorite_list_.end(); ++iter) {
     const FavoriteState* favorite = (*iter)->AsFavoriteState();
     DCHECK(favorite);
-    if (favorite->update_received() && favorite->is_favorite() &&
+    if (favorite->update_received() && favorite->IsFavorite() &&
         favorite->Matches(type)) {
       list->push_back(favorite);
     }
@@ -319,7 +319,7 @@
     return NULL;
   const FavoriteState* favorite = managed->AsFavoriteState();
   DCHECK(favorite);
-  if (!favorite->update_received() || !favorite->is_favorite())
+  if (!favorite->update_received() || !favorite->IsFavorite())
     return NULL;
   return favorite;
 }
@@ -353,17 +353,6 @@
       ManagedState::MANAGED_TYPE_NETWORK, service_path);
 }
 
-void NetworkStateHandler::RequestUpdateForAllNetworks() {
-  NET_LOG_EVENT("RequestUpdateForAllNetworks", "");
-  for (ManagedStateList::iterator iter = network_list_.begin();
-       iter != network_list_.end(); ++iter) {
-    ManagedState* network = *iter;
-    network->set_update_requested(true);
-    shill_property_handler_->RequestProperties(
-        ManagedState::MANAGED_TYPE_NETWORK, network->path());
-  }
-}
-
 void NetworkStateHandler::ClearLastErrorForNetwork(
     const std::string& service_path) {
   NetworkState* network = GetModifiableNetworkState(service_path);
@@ -483,8 +472,8 @@
 
 void NetworkStateHandler::ProfileListChanged() {
   NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties");
-  for (ManagedStateList::iterator iter = network_list_.begin();
-       iter != network_list_.end(); ++iter) {
+  for (ManagedStateList::iterator iter = favorite_list_.begin();
+       iter != favorite_list_.end(); ++iter) {
     shill_property_handler_->RequestProperties(
         ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path());
   }
@@ -510,7 +499,7 @@
   }
   managed->set_update_received();
 
-  std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived";
+  std::string desc = GetManagedStateLogType(managed) + " Properties Received";
   NET_LOG_DEBUG(desc, GetManagedStateLogName(managed));
 
   if (type == ManagedState::MANAGED_TYPE_NETWORK) {
@@ -679,7 +668,7 @@
     for (ManagedStateList::iterator iter = favorite_list_.begin();
          iter != favorite_list_.end(); ++iter) {
       FavoriteState* favorite = (*iter)->AsFavoriteState();
-      if (!favorite->is_favorite())
+      if (!favorite->IsFavorite())
         continue;
       if (favorite->IsPrivate())
         ++unshared;
diff --git a/chromeos/network/network_state_handler.h b/chromeos/network/network_state_handler.h
index 6e05ffc..2c4e621 100644
--- a/chromeos/network/network_state_handler.h
+++ b/chromeos/network/network_state_handler.h
@@ -203,11 +203,6 @@
   // properties actually changed.
   void RequestUpdateForNetwork(const std::string& service_path);
 
-  // Request an update for all existing NetworkState entries, e.g. after
-  // loading an ONC configuration file that may have updated one or more
-  // existing networks.
-  void RequestUpdateForAllNetworks();
-
   // Clear the last_error value for the NetworkState for |service_path|.
   void ClearLastErrorForNetwork(const std::string& service_path);
 
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index 8530935..c0d6325 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -476,20 +476,6 @@
   message_loop_.RunUntilIdle();
   EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
       kShillManagerClientStubDefaultWireless));
-
-  // Request an update for all networks.
-  network_state_handler_->RequestUpdateForAllNetworks();
-  message_loop_.RunUntilIdle();
-  // kShillManagerClientStubDefaultWireless should now have 3 updates
-  EXPECT_EQ(3, test_observer_->PropertyUpdatesForService(
-      kShillManagerClientStubDefaultWireless));
-  // Other networks should have 2 updates (inital + request).
-  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
-      kShillManagerClientStubDefaultService));
-  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
-      kShillManagerClientStubWireless2));
-  EXPECT_EQ(2, test_observer_->PropertyUpdatesForService(
-      kShillManagerClientStubCellular));
 }
 
 }  // namespace chromeos
diff --git a/chromeos/network/shill_property_handler.cc b/chromeos/network/shill_property_handler.cc
index 5a4bca0..8ae24fb 100644
--- a/chromeos/network/shill_property_handler.cc
+++ b/chromeos/network/shill_property_handler.cc
@@ -201,10 +201,10 @@
 
 void ShillPropertyHandler::RequestProperties(ManagedState::ManagedType type,
                                              const std::string& path) {
-  VLOG(2) << "Request Properties: " << type << " : " << path;
   if (pending_updates_[type].find(path) != pending_updates_[type].end())
     return;  // Update already requested.
 
+  NET_LOG_DEBUG("Request Properties", path);
   pending_updates_[type].insert(path);
   if (type == ManagedState::MANAGED_TYPE_NETWORK ||
       type == ManagedState::MANAGED_TYPE_FAVORITE) {
@@ -344,7 +344,9 @@
   std::set<std::string>& requested_service_updates =
       requested_updates_[ManagedState::MANAGED_TYPE_NETWORK];  // For favorites
   std::set<std::string> new_requested_updates;
-  VLOG(2) << "Update Properties: " << type << " Entries: " << entries.GetSize();
+  NET_LOG_DEBUG(
+      base::StringPrintf("UpdateProperties: %" PRIuS, entries.GetSize()),
+      ManagedState::TypeToString(type));
   for (base::ListValue::const_iterator iter = entries.begin();
        iter != entries.end(); ++iter) {
     std::string path;
@@ -465,7 +467,8 @@
     const std::string& path,
     DBusMethodCallStatus call_status,
     const base::DictionaryValue& properties) {
-  VLOG(2) << "GetPropertiesCallback: " << type << " : " << path;
+  NET_LOG_DEBUG("GetPropertiesCallback: " + ManagedState::TypeToString(type),
+                path);
   pending_updates_[type].erase(path);
   if (call_status != DBUS_METHOD_CALL_SUCCESS) {
     // The shill service no longer exists.  This can happen when a network
diff --git a/chromeos/network/shill_property_util.cc b/chromeos/network/shill_property_util.cc
index d0d33d3..35e4bb1 100644
--- a/chromeos/network/shill_property_util.cc
+++ b/chromeos/network/shill_property_util.cc
@@ -120,6 +120,22 @@
   return ssid;
 }
 
+std::string GetNetworkIdFromProperties(
+    const base::DictionaryValue& properties) {
+  if (properties.empty())
+    return "EmptyProperties";
+  std::string result;
+  if (properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &result))
+    return result;
+  if (properties.GetStringWithoutPathExpansion(shill::kSSIDProperty, &result))
+    return result;
+  if (properties.GetStringWithoutPathExpansion(shill::kNameProperty, &result))
+    return result;
+  std::string type = "UnknownType";
+  properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
+  return "Unidentified " + type;
+}
+
 std::string GetNameFromProperties(const std::string& service_path,
                                   const base::DictionaryValue& properties) {
   std::string name;
@@ -135,6 +151,10 @@
 
   std::string type;
   properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
+  if (type.empty()) {
+    NET_LOG_ERROR("GetNameFromProperties: No type", service_path);
+    return validated_name;
+  }
   if (!NetworkTypePattern::WiFi().MatchesType(type))
     return validated_name;
 
@@ -222,8 +242,9 @@
     // with the keys "Provider.Type" and "Provider.Host".
     const base::DictionaryValue* provider_properties = NULL;
     if (!service_properties.GetDictionaryWithoutPathExpansion(
-             shill::kProviderProperty, &provider_properties)) {
-      NET_LOG_ERROR("CopyIdentifyingProperties", "Missing VPN provider dict");
+            shill::kProviderProperty, &provider_properties)) {
+      NET_LOG_ERROR("Missing VPN provider dict",
+                    GetNetworkIdFromProperties(service_properties));
       return false;
     }
     std::string vpn_provider_type;
@@ -246,8 +267,10 @@
     NOTREACHED() << "Unsupported network type " << type;
     success = false;
   }
-  if (!success)
-    NET_LOG_ERROR("CopyIdentifyingProperties", "Missing required properties");
+  if (!success) {
+    NET_LOG_ERROR("Missing required properties",
+                  GetNetworkIdFromProperties(service_properties));
+  }
   return success;
 }
 
@@ -263,6 +286,20 @@
   return identifying_a.Equals(&identifying_b);
 }
 
+bool IsPassphraseKey(const std::string& key) {
+  return key == shill::kEapPrivateKeyPasswordProperty ||
+      key == shill::kEapPasswordProperty ||
+      key == shill::kL2tpIpsecPasswordProperty ||
+      key == shill::kOpenVPNPasswordProperty ||
+      key == shill::kOpenVPNAuthUserPassProperty ||
+      key == shill::kOpenVPNTLSAuthContentsProperty ||
+      key == shill::kPassphraseProperty ||
+      key == shill::kOpenVPNOTPProperty ||
+      key == shill::kEapPrivateKeyProperty ||
+      key == shill::kEapPinProperty ||
+      key == shill::kApnPasswordProperty;
+}
+
 }  // namespace shill_property_util
 
 namespace {
diff --git a/chromeos/network/shill_property_util.h b/chromeos/network/shill_property_util.h
index 466b967..4ae1df5 100644
--- a/chromeos/network/shill_property_util.h
+++ b/chromeos/network/shill_property_util.h
@@ -31,7 +31,12 @@
     const base::DictionaryValue& properties,
     bool* unknown_encoding);
 
-// Returns the name for the network represented by the Shill |properties|. For
+// Returns the GUID (if available), SSID, or Name from |properties|. Only used
+// for logging and debugging.
+CHROMEOS_EXPORT std::string GetNetworkIdFromProperties(
+    const base::DictionaryValue& properties);
+
+  // Returns the name for the network represented by the Shill |properties|. For
 // WiFi it refers to the HexSSID.
 CHROMEOS_EXPORT std::string GetNameFromProperties(
     const std::string& service_path,
@@ -66,6 +71,9 @@
 bool DoIdentifyingPropertiesMatch(const base::DictionaryValue& properties_a,
                                   const base::DictionaryValue& properties_b);
 
+// Returns true if |key| corresponds to a passphrase property.
+bool IsPassphraseKey(const std::string& key);
+
 }  // namespace shill_property_util
 
 class CHROMEOS_EXPORT NetworkTypePattern {
diff --git a/chromeos/system/name_value_pairs_parser.cc b/chromeos/system/name_value_pairs_parser.cc
index efa5779..39b852b 100644
--- a/chromeos/system/name_value_pairs_parser.cc
+++ b/chromeos/system/name_value_pairs_parser.cc
@@ -12,6 +12,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_tokenizer.h"
 #include "base/strings/string_util.h"
+#include "base/sys_info.h"
 
 namespace chromeos {  // NOLINT
 namespace system {
@@ -126,7 +127,8 @@
   if (base::ReadFileToString(file_path, &contents)) {
     return ParseNameValuePairs(contents, eq, delim);
   } else {
-    LOG(WARNING) << "Unable to read statistics file: " << file_path.value();
+    if (base::SysInfo::IsRunningOnChromeOS())
+      LOG(WARNING) << "Unable to read statistics file: " << file_path.value();
     return false;
   }
 }
diff --git a/chromeos/system/statistics_provider.cc b/chromeos/system/statistics_provider.cc
index 9beff02..93557b9 100644
--- a/chromeos/system/statistics_provider.cc
+++ b/chromeos/system/statistics_provider.cc
@@ -72,6 +72,7 @@
 const char kOffersCouponCodeKey[] = "ubind_attribute";
 const char kOffersGroupCodeKey[] = "gbind_attribute";
 const char kRlzBrandCodeKey[] = "rlz_brand_code";
+const char kDiskSerialNumber[] = "root_disk_serial_number";
 
 // OEM specific statistics. Must be prefixed with "oem_".
 const char kOemCanExitEnterpriseEnrollmentKey[] = "oem_can_exit_enrollment";
@@ -226,9 +227,9 @@
   if (cancellation_flag_.IsSet())
     return;
 
+  NameValuePairsParser parser(&machine_info_);
   if (base::SysInfo::IsRunningOnChromeOS()) {
     // Parse all of the key/value pairs from the crossystem tool.
-    NameValuePairsParser parser(&machine_info_);
     if (!parser.ParseNameValuePairsFromTool(arraysize(kCrosSystemTool),
                                             kCrosSystemTool,
                                             kCrosSystemEq,
@@ -236,18 +237,18 @@
                                             kCrosSystemCommentDelim)) {
       LOG(ERROR) << "Errors parsing output from: " << kCrosSystemTool;
     }
-
-    parser.GetNameValuePairsFromFile(base::FilePath(kMachineHardwareInfoFile),
-                                     kMachineHardwareInfoEq,
-                                     kMachineHardwareInfoDelim);
-    parser.GetNameValuePairsFromFile(base::FilePath(kEchoCouponFile),
-                                     kEchoCouponEq,
-                                     kEchoCouponDelim);
-    parser.GetNameValuePairsFromFile(base::FilePath(kVpdFile),
-                                     kVpdEq,
-                                     kVpdDelim);
   }
 
+  parser.GetNameValuePairsFromFile(base::FilePath(kMachineHardwareInfoFile),
+                                   kMachineHardwareInfoEq,
+                                   kMachineHardwareInfoDelim);
+  parser.GetNameValuePairsFromFile(base::FilePath(kEchoCouponFile),
+                                   kEchoCouponEq,
+                                   kEchoCouponDelim);
+  parser.GetNameValuePairsFromFile(base::FilePath(kVpdFile),
+                                   kVpdEq,
+                                   kVpdDelim);
+
   // Ensure that the hardware class key is present with the expected
   // key name, and if it couldn't be retrieved, that the value is "unknown".
   std::string hardware_class = machine_info_[kHardwareClassCrosSystemKey];
diff --git a/chromeos/system/statistics_provider.h b/chromeos/system/statistics_provider.h
index d1dd22c..ed6699d 100644
--- a/chromeos/system/statistics_provider.h
+++ b/chromeos/system/statistics_provider.h
@@ -49,6 +49,9 @@
 // Release Brand Code key.
 CHROMEOS_EXPORT extern const char kRlzBrandCodeKey[];
 
+// The serial number of the disk the root device is on.
+CHROMEOS_EXPORT extern const char kDiskSerialNumber[];
+
 // This interface provides access to Chrome OS statistics.
 class CHROMEOS_EXPORT StatisticsProvider {
  public:
diff --git a/components/OWNERS b/components/OWNERS
index 80e220a..3434a73 100644
--- a/components/OWNERS
+++ b/components/OWNERS
@@ -1,6 +1,5 @@
 blundell@chromium.org
 jochen@chromium.org
-joi@chromium.org
 
 per-file autofill*=dhollowa@chromium.org
 per-file autofill*=isherman@chromium.org
diff --git a/components/auto_login_parser.target.darwin-arm.mk b/components/auto_login_parser.target.darwin-arm.mk
index 5114189..3d6852f 100644
--- a/components/auto_login_parser.target.darwin-arm.mk
+++ b/components/auto_login_parser.target.darwin-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/auto_login_parser.target.darwin-mips.mk b/components/auto_login_parser.target.darwin-mips.mk
index 0fddb71..ecc4a1b 100644
--- a/components/auto_login_parser.target.darwin-mips.mk
+++ b/components/auto_login_parser.target.darwin-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/auto_login_parser.target.darwin-x86.mk b/components/auto_login_parser.target.darwin-x86.mk
index c963a40..61f8ee9 100644
--- a/components/auto_login_parser.target.darwin-x86.mk
+++ b/components/auto_login_parser.target.darwin-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/auto_login_parser.target.darwin-x86_64.mk b/components/auto_login_parser.target.darwin-x86_64.mk
new file mode 100644
index 0000000..485a986
--- /dev/null
+++ b/components/auto_login_parser.target.darwin-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_auto_login_parser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/auto_login_parser/auto_login_parser.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_auto_login_parser_gyp
+
+# Alias gyp target name.
+.PHONY: auto_login_parser
+auto_login_parser: components_auto_login_parser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/auto_login_parser.target.linux-arm.mk b/components/auto_login_parser.target.linux-arm.mk
index 5114189..3d6852f 100644
--- a/components/auto_login_parser.target.linux-arm.mk
+++ b/components/auto_login_parser.target.linux-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/auto_login_parser.target.linux-mips.mk b/components/auto_login_parser.target.linux-mips.mk
index 0fddb71..ecc4a1b 100644
--- a/components/auto_login_parser.target.linux-mips.mk
+++ b/components/auto_login_parser.target.linux-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/auto_login_parser.target.linux-x86.mk b/components/auto_login_parser.target.linux-x86.mk
index c963a40..61f8ee9 100644
--- a/components/auto_login_parser.target.linux-x86.mk
+++ b/components/auto_login_parser.target.linux-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/auto_login_parser.target.linux-x86_64.mk b/components/auto_login_parser.target.linux-x86_64.mk
new file mode 100644
index 0000000..485a986
--- /dev/null
+++ b/components/auto_login_parser.target.linux-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_auto_login_parser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/auto_login_parser/auto_login_parser.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_auto_login_parser_gyp
+
+# Alias gyp target name.
+.PHONY: auto_login_parser
+auto_login_parser: components_auto_login_parser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill.gypi b/components/autofill.gypi
index 9227b76..dd2d78a 100644
--- a/components/autofill.gypi
+++ b/components/autofill.gypi
@@ -383,6 +383,15 @@
 
           # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
           'msvs_disabled_warnings': [4267, ],
+
+          'conditions': [
+            [ 'OS == "android"', {
+              'sources!': [
+                'autofill/content/browser/risk/fingerprint.cc',
+                'autofill/content/browser/risk/fingerprint.h',
+              ],
+            }],
+          ],
         },
 
         {
diff --git a/components/autofill/OWNERS b/components/autofill/OWNERS
index af7b445..3883338 100644
--- a/components/autofill/OWNERS
+++ b/components/autofill/OWNERS
@@ -3,6 +3,3 @@
 
 # Owner for password autofill/generation only.
 gcasto@chromium.org
-
-# Temporary owner, for refactoring changes only.
-joi@chromium.org
diff --git a/components/autofill/content/browser/DEPS b/components/autofill/content/browser/DEPS
index 1e0ab98..e0b7448 100644
--- a/components/autofill/content/browser/DEPS
+++ b/components/autofill/content/browser/DEPS
@@ -15,20 +15,4 @@
   '.*_[a-z]*test\.cc': [
     "+content/public/test",
   ],
-
-  # TODO(joi): Removing these dependencies needs to wait until some
-  # other things (AutofillWebData::FromBrowserContext and a few other
-  # things) move out of being built in //chrome. If we break the
-  # dependency on ChromeRenderViewHostTestHarness now (by switching to
-  # content::RenderViewHostTestHarness) but leave the test running in
-  # the 'unit_tests' target, it will fail at runtime trying to cast a
-  # plain BrowserContext to a Profile. If on the other hand we move it
-  # to the 'components_unittests' target, it will at this point fail
-  # to build due to a few link-time dependencies.
-  'content_autofill_driver_unittest.cc': [
-    "!chrome/test/base/chrome_render_view_host_test_harness.h",
-  ],
-  'request_autocomplete_manager_unittest.cc': [
-    "!chrome/test/base/chrome_render_view_host_test_harness.h",
-  ],
 }
diff --git a/components/autofill/content/browser/content_autofill_driver_unittest.cc b/components/autofill/content/browser/content_autofill_driver_unittest.cc
index edb4aa0..c116cfc 100644
--- a/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -8,7 +8,6 @@
 #include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
 #include "components/autofill/content/common/autofill_messages.h"
 #include "components/autofill/core/browser/autofill_external_delegate.h"
@@ -22,6 +21,7 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/frame_navigate_params.h"
 #include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_renderer_host.h"
 #include "ipc/ipc_test_sink.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -63,10 +63,10 @@
   using ContentAutofillDriver::DidNavigateMainFrame;
 };
 
-class ContentAutofillDriverTest : public ChromeRenderViewHostTestHarness {
+class ContentAutofillDriverTest : public content::RenderViewHostTestHarness {
  public:
   virtual void SetUp() OVERRIDE {
-    ChromeRenderViewHostTestHarness::SetUp();
+    content::RenderViewHostTestHarness::SetUp();
 
     test_manager_delegate_.reset(new TestAutofillManagerDelegate());
     driver_.reset(new TestContentAutofillDriver(web_contents(),
@@ -77,7 +77,7 @@
     // Reset the driver now to cause all pref observers to be removed and avoid
     // crashes that otherwise occur in the destructor.
     driver_.reset();
-    ChromeRenderViewHostTestHarness::TearDown();
+    content::RenderViewHostTestHarness::TearDown();
   }
 
  protected:
diff --git a/components/autofill/content/browser/request_autocomplete_manager_unittest.cc b/components/autofill/content/browser/request_autocomplete_manager_unittest.cc
index 4906172..cbe3c5d 100644
--- a/components/autofill/content/browser/request_autocomplete_manager_unittest.cc
+++ b/components/autofill/content/browser/request_autocomplete_manager_unittest.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/autofill/content/browser/content_autofill_driver.h"
 #include "components/autofill/content/browser/request_autocomplete_manager.h"
 #include "components/autofill/content/common/autofill_messages.h"
 #include "components/autofill/core/browser/test_autofill_manager_delegate.h"
 #include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_renderer_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace autofill {
@@ -90,12 +90,13 @@
 
 }  // namespace
 
-class RequestAutocompleteManagerTest : public ChromeRenderViewHostTestHarness {
+class RequestAutocompleteManagerTest :
+    public content::RenderViewHostTestHarness {
  public:
   RequestAutocompleteManagerTest() {}
 
   virtual void SetUp() OVERRIDE {
-    ChromeRenderViewHostTestHarness::SetUp();
+    content::RenderViewHostTestHarness::SetUp();
 
     driver_.reset(
         new TestContentAutofillDriver(web_contents(), &manager_delegate_));
@@ -107,7 +108,7 @@
     // Reset the driver now to cause all pref observers to be removed and avoid
     // crashes that otherwise occur in the destructor.
     driver_.reset();
-    ChromeRenderViewHostTestHarness::TearDown();
+    content::RenderViewHostTestHarness::TearDown();
   }
 
   // Searches for an |AutofillMsg_RequestAutocompleteResult| message in the
diff --git a/components/autofill/content/browser/risk/fingerprint.cc b/components/autofill/content/browser/risk/fingerprint.cc
index 62b0b24..1f412c5 100644
--- a/components/autofill/content/browser/risk/fingerprint.cc
+++ b/components/autofill/content/browser/risk/fingerprint.cc
@@ -360,7 +360,8 @@
                                   weak_ptr_factory_.GetWeakPtr()));
 
   // Load GPU data if needed.
-  if (!gpu_data_manager_->IsCompleteGpuInfoAvailable()) {
+  if (gpu_data_manager_->GpuAccessAllowed(NULL) &&
+      !gpu_data_manager_->IsCompleteGpuInfoAvailable()) {
     gpu_observer_.Add(gpu_data_manager_);
     gpu_data_manager_->RequestCompleteGpuInfoIfNeeded();
   }
@@ -425,7 +426,8 @@
   // If all of the data has been loaded, or if the |timeout_timer_| has expired,
   // fill the fingerprint and clean up.
   if (!timeout_timer_.IsRunning() ||
-      (gpu_data_manager_->IsCompleteGpuInfoAvailable() &&
+      ((!gpu_data_manager_->GpuAccessAllowed(NULL) ||
+        gpu_data_manager_->IsCompleteGpuInfoAvailable()) &&
        fonts_ &&
        !waiting_on_plugins_ &&
        (geoposition_.Validate() ||
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index 5f3b030..d6dbfa1 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -41,6 +41,7 @@
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "third_party/WebKit/public/web/WebNode.h"
 #include "third_party/WebKit/public/web/WebOptionElement.h"
+#include "third_party/WebKit/public/web/WebTextAreaElement.h"
 #include "third_party/WebKit/public/web/WebView.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/events/keycodes/keyboard_codes.h"
@@ -56,6 +57,7 @@
 using blink::WebNode;
 using blink::WebOptionElement;
 using blink::WebString;
+using blink::WebTextAreaElement;
 using blink::WebVector;
 
 namespace autofill {
@@ -296,14 +298,18 @@
   ignore_text_changes_ = ignore;
 }
 
-void AutofillAgent::InputElementClicked(const WebInputElement& element,
-                                        bool was_focused,
-                                        bool is_focused) {
+void AutofillAgent::FormControlElementClicked(
+    const WebFormControlElement& element,
+    bool was_focused) {
+  const WebInputElement* input_element = toWebInputElement(&element);
+  if (!input_element && !IsTextAreaElement(element))
+    return;
+
   if (was_focused)
     ShowSuggestions(element, true, false, true, false);
 }
 
-void AutofillAgent::InputElementLostFocus() {
+void AutofillAgent::FormControlElementLostFocus() {
   HidePopup();
 }
 
@@ -313,10 +319,12 @@
   Send(new AutofillHostMsg_DidEndTextFieldEditing(routing_id()));
 }
 
-void AutofillAgent::textFieldDidChange(const WebInputElement& element) {
+void AutofillAgent::textFieldDidChange(const WebFormControlElement& element) {
   if (ignore_text_changes_)
     return;
 
+  DCHECK(toWebInputElement(&element) || IsTextAreaElement(element));
+
   if (did_set_node_text_) {
     did_set_node_text_ = false;
     return;
@@ -333,27 +341,34 @@
                  element));
 }
 
-void AutofillAgent::TextFieldDidChangeImpl(const WebInputElement& element) {
+void AutofillAgent::TextFieldDidChangeImpl(
+    const WebFormControlElement& element) {
   // If the element isn't focused then the changes don't matter. This check is
   // required to properly handle IME interactions.
   if (!element.focused())
     return;
 
-  if (password_generation_agent_ &&
-      password_generation_agent_->TextDidChangeInTextField(element)) {
-    return;
-  }
+  const WebInputElement* input_element = toWebInputElement(&element);
+  if (input_element) {
+    if (password_generation_agent_ &&
+        password_generation_agent_->TextDidChangeInTextField(*input_element)) {
+      return;
+    }
 
-  if (password_autofill_agent_->TextDidChangeInTextField(element)) {
-    element_ = element;
-    return;
+    if (password_autofill_agent_->TextDidChangeInTextField(*input_element)) {
+      element_ = element;
+      return;
+    }
   }
 
   ShowSuggestions(element, false, true, false, false);
 
   FormData form;
   FormFieldData field;
-  if (FindFormAndFieldForInputElement(element, &form, &field, REQUIRE_NONE)) {
+  if (FindFormAndFieldForFormControlElement(element,
+                                            &form,
+                                            &field,
+                                            REQUIRE_NONE)) {
     Send(new AutofillHostMsg_TextFieldDidChange(routing_id(), form, field,
                                                 base::TimeTicks::Now()));
   }
@@ -377,14 +392,16 @@
 
 void AutofillAgent::AcceptDataListSuggestion(
     const base::string16& suggested_value) {
+  WebInputElement* input_element = toWebInputElement(&element_);
+  DCHECK(input_element);
   base::string16 new_value = suggested_value;
   // If this element takes multiple values then replace the last part with
   // the suggestion.
-  if (element_.isMultiple() &&
-      element_.formControlType() == WebString::fromUTF8("email")) {
+  if (input_element->isMultiple() &&
+      input_element->formControlType() == WebString::fromUTF8("email")) {
     std::vector<base::string16> parts;
 
-    base::SplitStringDontTrim(element_.editingValue(), ',', &parts);
+    base::SplitStringDontTrim(input_element->editingValue(), ',', &parts);
     if (parts.size() == 0)
       parts.push_back(base::string16());
 
@@ -401,7 +418,7 @@
 
     new_value = JoinString(parts, ',');
   }
-  FillFieldWithValue(new_value, &element_);
+  FillFieldWithValue(new_value, input_element);
 }
 
 void AutofillAgent::OnFieldTypePredictionsAvailable(
@@ -451,11 +468,15 @@
 }
 
 void AutofillAgent::OnFillFieldWithValue(const base::string16& value) {
-  FillFieldWithValue(value, &element_);
+  WebInputElement* input_element = toWebInputElement(&element_);
+  if (input_element)
+    FillFieldWithValue(value, input_element);
 }
 
 void AutofillAgent::OnPreviewFieldWithValue(const base::string16& value) {
-  PreviewFieldWithValue(value, &element_);
+  WebInputElement* input_element = toWebInputElement(&element_);
+  if (input_element)
+    PreviewFieldWithValue(value, input_element);
 }
 
 void AutofillAgent::OnAcceptDataListSuggestion(const base::string16& value) {
@@ -489,16 +510,25 @@
   in_flight_request_form_.reset();
 }
 
-void AutofillAgent::ShowSuggestions(const WebInputElement& element,
+void AutofillAgent::ShowSuggestions(const WebFormControlElement& element,
                                     bool autofill_on_empty_values,
                                     bool requires_caret_at_end,
                                     bool display_warning_if_disabled,
                                     bool datalist_only) {
-  if (!element.isEnabled() || element.isReadOnly() || !element.isTextField() ||
-      element.isPasswordField())
+  if (!element.isEnabled() || element.isReadOnly())
     return;
-  if (!datalist_only && !element.suggestedValue().isEmpty())
-    return;
+
+  const WebInputElement* input_element = toWebInputElement(&element);
+  if (input_element) {
+    if (!input_element->isTextField() || input_element->isPasswordField())
+      return;
+    if (!datalist_only && !input_element->suggestedValue().isEmpty())
+      return;
+  } else {
+    DCHECK(IsTextAreaElement(element));
+    if (!element.toConst<WebTextAreaElement>().suggestedValue().isEmpty())
+      return;
+  }
 
   // Don't attempt to autofill with values that are too large or if filling
   // criteria are not met.
@@ -515,7 +545,8 @@
   }
 
   element_ = element;
-  if (password_autofill_agent_->ShowSuggestions(element)) {
+  if (input_element &&
+      password_autofill_agent_->ShowSuggestions(*input_element)) {
     is_popup_possibly_visible_ = true;
     return;
   }
@@ -535,12 +566,15 @@
                            datalist_only);
 }
 
-void AutofillAgent::QueryAutofillSuggestions(const WebInputElement& element,
-                                             bool display_warning_if_disabled,
-                                             bool datalist_only) {
+void AutofillAgent::QueryAutofillSuggestions(
+    const WebFormControlElement& element,
+    bool display_warning_if_disabled,
+    bool datalist_only) {
   if (!element.document().frame())
     return;
 
+  DCHECK(toWebInputElement(&element) || IsTextAreaElement(element));
+
   static int query_counter = 0;
   autofill_query_id_ = query_counter++;
   display_warning_if_disabled_ = display_warning_if_disabled;
@@ -555,7 +589,8 @@
 
   FormData form;
   FormFieldData field;
-  if (!FindFormAndFieldForInputElement(element, &form, &field, requirements)) {
+  if (!FindFormAndFieldForFormControlElement(element, &form, &field,
+                                             requirements)) {
     // If we didn't find the cached form, at least let autocomplete have a shot
     // at providing suggestions.
     WebFormControlElementToFormField(element, EXTRACT_VALUE, &field);
@@ -566,21 +601,24 @@
   gfx::RectF bounding_box_scaled =
       GetScaledBoundingBox(web_view_->pageScaleFactor(), &element_);
 
-  // Find the datalist values and send them to the browser process.
-  std::vector<base::string16> data_list_values;
-  std::vector<base::string16> data_list_labels;
-  GetDataListSuggestions(element_,
-                         datalist_only,
-                         &data_list_values,
-                         &data_list_labels);
-  TrimStringVectorForIPC(&data_list_values);
-  TrimStringVectorForIPC(&data_list_labels);
+  const WebInputElement* input_element = toWebInputElement(&element);
+  if (input_element) {
+    // Find the datalist values and send them to the browser process.
+    std::vector<base::string16> data_list_values;
+    std::vector<base::string16> data_list_labels;
+    GetDataListSuggestions(*input_element,
+                           datalist_only,
+                           &data_list_values,
+                           &data_list_labels);
+    TrimStringVectorForIPC(&data_list_values);
+    TrimStringVectorForIPC(&data_list_labels);
+
+    Send(new AutofillHostMsg_SetDataList(routing_id(),
+                                         data_list_values,
+                                         data_list_labels));
+  }
 
   is_popup_possibly_visible_ = true;
-  Send(new AutofillHostMsg_SetDataList(routing_id(),
-                                       data_list_values,
-                                       data_list_labels));
-
   Send(new AutofillHostMsg_QueryFormFieldAutofill(routing_id(),
                                                   autofill_query_id_,
                                                   form,
@@ -601,6 +639,8 @@
   was_query_node_autofilled_ = element_.isAutofilled();
   node->setSuggestedValue(value.substr(0, node->maxLength()));
   node->setAutofilled(true);
+  node->setSelectionRange(node->value().length(),
+                          node->suggestedValue().length());
 }
 
 void AutofillAgent::HidePopup() {
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h
index 5c327db..ba01c7b 100644
--- a/components/autofill/content/renderer/autofill_agent.h
+++ b/components/autofill/content/renderer/autofill_agent.h
@@ -18,6 +18,7 @@
 #include "components/autofill/core/common/forms_seen_state.h"
 #include "content/public/renderer/render_view_observer.h"
 #include "third_party/WebKit/public/web/WebAutofillClient.h"
+#include "third_party/WebKit/public/web/WebFormControlElement.h"
 #include "third_party/WebKit/public/web/WebFormElement.h"
 #include "third_party/WebKit/public/web/WebInputElement.h"
 
@@ -68,16 +69,16 @@
   virtual void OrientationChangeEvent(int orientation) OVERRIDE;
 
   // PageClickListener:
-  virtual void InputElementClicked(const blink::WebInputElement& element,
-                                   bool was_focused,
-                                   bool is_focused) OVERRIDE;
-  virtual void InputElementLostFocus() OVERRIDE;
+  virtual void FormControlElementClicked(
+      const blink::WebFormControlElement& element,
+      bool was_focused) OVERRIDE;
+  virtual void FormControlElementLostFocus() OVERRIDE;
 
   // blink::WebAutofillClient:
   virtual void textFieldDidEndEditing(
       const blink::WebInputElement& element) OVERRIDE;
   virtual void textFieldDidChange(
-      const blink::WebInputElement& element) OVERRIDE;
+      const blink::WebFormControlElement& element);
   virtual void textFieldDidReceiveKeyDown(
       const blink::WebInputElement& element,
       const blink::WebKeyboardEvent& event) OVERRIDE;
@@ -113,7 +114,7 @@
 
   // Called in a posted task by textFieldDidChange() to work-around a WebKit bug
   // http://bugs.webkit.org/show_bug.cgi?id=16976
-  void TextFieldDidChangeImpl(const blink::WebInputElement& element);
+  void TextFieldDidChangeImpl(const blink::WebFormControlElement& element);
 
   // Shows the autofill suggestions for |element|.
   // This call is asynchronous and may or may not lead to the showing of a
@@ -129,7 +130,7 @@
   // |datalist_only| specifies whether all of <datalist> suggestions and no
   // autofill suggestions are shown. |autofill_on_empty_values| and
   // |requires_caret_at_end| are ignored if |datalist_only| is true.
-  void ShowSuggestions(const blink::WebInputElement& element,
+  void ShowSuggestions(const blink::WebFormControlElement& element,
                        bool autofill_on_empty_values,
                        bool requires_caret_at_end,
                        bool display_warning_if_disabled,
@@ -137,7 +138,7 @@
 
   // Queries the browser for Autocomplete and Autofill suggestions for the given
   // |element|.
-  void QueryAutofillSuggestions(const blink::WebInputElement& element,
+  void QueryAutofillSuggestions(const blink::WebFormControlElement& element,
                                 bool display_warning_if_disabled,
                                 bool datalist_only);
 
@@ -174,7 +175,7 @@
   int autofill_query_id_;
 
   // The element corresponding to the last request sent for form field Autofill.
-  blink::WebInputElement element_;
+  blink::WebFormControlElement element_;
 
   // The form element currently requesting an interactive autocomplete.
   blink::WebFormElement in_flight_request_form_;
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index c9c6f87..995bb06 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -507,10 +507,9 @@
     // i.e. the field the user is currently editing and interacting with.
     const WebInputElement* input_element = toWebInputElement(element);
     if (!force_override && !is_initiating_element &&
-        ((IsAutofillableInputElement(input_element) &&
-          !input_element->value().isEmpty()) ||
-         (IsTextAreaElement(*element) &&
-          !element->toConst<WebTextAreaElement>().value().isEmpty())))
+        ((IsAutofillableInputElement(input_element) ||
+          IsTextAreaElement(*element)) &&
+         !element->value().isEmpty()))
       continue;
 
     if (((filters & FILTER_DISABLED_ELEMENTS) && !element->isEnabled()) ||
@@ -539,28 +538,24 @@
     // returns the default maxlength value.
     input_element->setValue(
         data.value.substr(0, input_element->maxLength()), true);
-    if (is_initiating_node) {
-      int length = input_element->value().length();
-      input_element->setSelectionRange(length, length);
-      // Clear the current IME composition (the underline), if there is one.
-      input_element->document().frame()->unmarkText();
-    }
-  } else if (IsTextAreaElement(*field)) {
-    WebTextAreaElement text_area = field->to<WebTextAreaElement>();
-    if (text_area.value() != data.value) {
-      text_area.setValue(data.value);
-      text_area.dispatchFormControlChangeEvent();
-    }
-  } else if (IsSelectElement(*field)) {
-    WebSelectElement select_element = field->to<WebSelectElement>();
-    if (select_element.value() != data.value) {
-      select_element.setValue(data.value);
-      select_element.dispatchFormControlChangeEvent();
+  } else if (IsTextAreaElement(*field) || IsSelectElement(*field)) {
+    if (field->value() != data.value) {
+      field->setValue(data.value);
+      field->dispatchFormControlChangeEvent();
     }
   } else {
     DCHECK(IsCheckableElement(input_element));
     input_element->setChecked(data.is_checked, true);
   }
+
+  if (is_initiating_node &&
+      ((IsTextInput(input_element) || IsMonthInput(input_element)) ||
+       IsTextAreaElement(*field))) {
+    int length = field->value().length();
+    field->setSelectionRange(length, length);
+    // Clear the current IME composition (the underline), if there is one.
+    field->document().frame()->unmarkText();
+  }
 }
 
 // Sets the |field|'s "suggested" (non JS visible) value to the value in |data|.
@@ -572,9 +567,9 @@
   if (data.value.empty())
     return;
 
-  // Preview input and textarea fields. For input fields, excludes checkboxes
-  // and radio buttons, as there is no provision for setSuggestedCheckedValue
-  // in WebInputElement.
+  // Preview input, textarea and select fields. For input fields, excludes
+  // checkboxes and radio buttons, as there is no provision for
+  // setSuggestedCheckedValue in WebInputElement.
   WebInputElement* input_element = toWebInputElement(field);
   if (IsTextInput(input_element) || IsMonthInput(input_element)) {
     // If the maxlength attribute contains a negative value, maxLength()
@@ -582,17 +577,18 @@
     input_element->setSuggestedValue(
       data.value.substr(0, input_element->maxLength()));
     input_element->setAutofilled(true);
-    if (is_initiating_node) {
-      // Select the part of the text that the user didn't type.
-      input_element->setSelectionRange(
-          input_element->value().length(),
-          input_element->suggestedValue().length());
-    }
-  } else if (IsTextAreaElement(*field)) {
-    WebTextAreaElement textarea = field->to<WebTextAreaElement>();
-    textarea.setSuggestedValue(data.value);
+  } else if (IsTextAreaElement(*field) || IsSelectElement(*field)) {
+    field->setSuggestedValue(data.value);
     field->setAutofilled(true);
   }
+
+  if (is_initiating_node &&
+      (IsTextInput(input_element) || IsTextAreaElement(*field))) {
+    // Select the part of the text that the user didn't type.
+    int start = field->value().length();
+    int end = field->suggestedValue().length();
+    field->setSelectionRange(start, end);
+  }
 }
 
 std::string RetrievalMethodToString(
@@ -772,17 +768,21 @@
     return;
 
   const WebInputElement* input_element = toWebInputElement(&element);
+  if (IsAutofillableInputElement(input_element) ||
+      IsTextAreaElement(element)) {
+    field->is_autofilled = element.isAutofilled();
+    field->is_focusable = element.isFocusable();
+    field->should_autocomplete = element.autoComplete();
+    field->text_direction = element.directionForFormData() ==
+        "rtl" ? base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
+  }
+
   if (IsAutofillableInputElement(input_element)) {
     if (IsTextInput(input_element))
       field->max_length = input_element->maxLength();
 
-    field->is_autofilled = input_element->isAutofilled();
-    field->is_focusable = input_element->isFocusable();
     field->is_checkable = IsCheckableElement(input_element);
     field->is_checked = input_element->isChecked();
-    field->should_autocomplete = input_element->autoComplete();
-    field->text_direction = input_element->directionForFormData() == "rtl" ?
-        base::i18n::RIGHT_TO_LEFT : base::i18n::LEFT_TO_RIGHT;
   } else if (IsTextAreaElement(element)) {
     // Nothing more to do in this case.
   } else if (extract_mask & EXTRACT_OPTIONS) {
@@ -797,16 +797,10 @@
   if (!(extract_mask & EXTRACT_VALUE))
     return;
 
-  base::string16 value;
-  if (IsAutofillableInputElement(input_element)) {
-    value = input_element->value();
-  } else if (IsTextAreaElement(element)) {
-    value = element.toConst<WebTextAreaElement>().value();
-  } else {
-    DCHECK(IsSelectElement(element));
-    const WebSelectElement select_element = element.toConst<WebSelectElement>();
-    value = select_element.value();
+  base::string16 value = element.value();
 
+  if (IsSelectElement(element)) {
+    const WebSelectElement select_element = element.toConst<WebSelectElement>();
     // Convert the |select_element| value to text if requested.
     if (extract_mask & EXTRACT_OPTION_TEXT) {
       WebVector<WebElement> list_items = select_element.listItems();
@@ -971,10 +965,10 @@
   return true;
 }
 
-bool FindFormAndFieldForInputElement(const WebInputElement& element,
-                                     FormData* form,
-                                     FormFieldData* field,
-                                     RequirementsMask requirements) {
+bool FindFormAndFieldForFormControlElement(const WebFormControlElement& element,
+                                           FormData* form,
+                                           FormFieldData* field,
+                                           RequirementsMask requirements) {
   if (!IsAutofillableElement(element))
     return false;
 
@@ -992,7 +986,7 @@
                                   field);
 }
 
-void FillForm(const FormData& form, const WebInputElement& element) {
+void FillForm(const FormData& form, const WebFormControlElement& element) {
   WebFormElement form_element = element.form();
   if (form_element.isNull())
     return;
@@ -1033,7 +1027,7 @@
                            &FillFormField);
 }
 
-void PreviewForm(const FormData& form, const WebInputElement& element) {
+void PreviewForm(const FormData& form, const WebFormControlElement& element) {
   WebFormElement form_element = element.form();
   if (form_element.isNull())
     return;
@@ -1046,7 +1040,7 @@
                            &PreviewFormField);
 }
 
-bool ClearPreviewedFormWithElement(const WebInputElement& element,
+bool ClearPreviewedFormWithElement(const WebFormControlElement& element,
                                    bool was_autofilled) {
   WebFormElement form_element = element.form();
   if (form_element.isNull())
@@ -1062,11 +1056,12 @@
     // want to reset the auto-filled status for fields that were previewed.
     WebFormControlElement control_element = control_elements[i];
 
-    // Only text input and textarea elements can be previewed.
+    // Only text input, textarea and select elements can be previewed.
     WebInputElement* input_element = toWebInputElement(&control_element);
     if (!IsTextInput(input_element) &&
         !IsMonthInput(input_element) &&
-        !IsTextAreaElement(control_element))
+        !IsTextAreaElement(control_element) &&
+        !IsSelectElement(control_element))
       continue;
 
     // If the element is not auto-filled, we did not preview it,
@@ -1074,39 +1069,32 @@
     if(!control_element.isAutofilled())
       continue;
 
-    if ((IsTextInput(input_element) &&
-         input_element->suggestedValue().isEmpty()) ||
-        (IsMonthInput(input_element) &&
-         input_element->suggestedValue().isEmpty()) ||
-        (IsTextAreaElement(control_element) &&
-         control_element.to<WebTextAreaElement>().suggestedValue().isEmpty()))
+    if ((IsTextInput(input_element) ||
+         IsMonthInput(input_element) ||
+         IsTextAreaElement(control_element) ||
+         IsSelectElement(control_element)) &&
+        control_element.suggestedValue().isEmpty())
       continue;
 
     // Clear the suggested value. For the initiating node, also restore the
     // original value.
-    if (IsTextInput(input_element) || IsMonthInput(input_element)) {
-      input_element->setSuggestedValue(WebString());
-      bool is_initiating_node = (element == *input_element);
-      if (is_initiating_node)
-        input_element->setAutofilled(was_autofilled);
-      else
-        input_element->setAutofilled(false);
-
-      // Clearing the suggested value in the focused node (above) can cause
-      // selection to be lost. We force selection range to restore the text
-      // cursor.
+    if (IsTextInput(input_element) || IsMonthInput(input_element) ||
+        IsTextAreaElement(control_element)) {
+      control_element.setSuggestedValue(WebString());
+      bool is_initiating_node = (element == control_element);
       if (is_initiating_node) {
-        int length = input_element->value().length();
-        input_element->setSelectionRange(length, length);
-      }
-    } else if (IsTextAreaElement(control_element)) {
-      WebTextAreaElement text_area = control_element.to<WebTextAreaElement>();
-      text_area.setSuggestedValue(WebString());
-      bool is_initiating_node = (element == text_area);
-      if (is_initiating_node)
         control_element.setAutofilled(was_autofilled);
-      else
+        // Clearing the suggested value in the focused node (above) can cause
+        // selection to be lost. We force selection range to restore the text
+        // cursor.
+        int length = control_element.value().length();
+        control_element.setSelectionRange(length, length);
+      } else {
         control_element.setAutofilled(false);
+      }
+    } else if (IsSelectElement(control_element)) {
+      control_element.setSuggestedValue(WebString());
+      control_element.setAutofilled(false);
     }
   }
 
@@ -1184,7 +1172,7 @@
   return true;
 }
 
-gfx::RectF GetScaledBoundingBox(float scale, WebInputElement* element) {
+gfx::RectF GetScaledBoundingBox(float scale, WebFormControlElement* element) {
   gfx::Rect bounding_box(element->boundsInViewportSpace());
   return gfx::RectF(bounding_box.x() * scale,
                     bounding_box.y() * scale,
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index f3384f1..0f0f6c2 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -116,15 +116,16 @@
 // Finds the form that contains |element| and returns it in |form|.  Fills
 // |field| with the |FormField| representation for element.
 // Returns false if the form is not found or cannot be serialized.
-bool FindFormAndFieldForInputElement(const blink::WebInputElement& element,
-                                     FormData* form,
-                                     FormFieldData* field,
-                                     RequirementsMask requirements);
+bool FindFormAndFieldForFormControlElement(
+    const blink::WebFormControlElement& element,
+    FormData* form,
+    FormFieldData* field,
+    RequirementsMask requirements);
 
 // Fills the form represented by |form|.  |element| is the input element that
 // initiated the auto-fill process.
 void FillForm(const FormData& form,
-              const blink::WebInputElement& element);
+              const blink::WebFormControlElement& element);
 
 // Fills focusable and non-focusable form control elements within |form_element|
 // with field data from |form_data|.
@@ -141,13 +142,13 @@
 // Previews the form represented by |form|.  |element| is the input element that
 // initiated the preview process.
 void PreviewForm(const FormData& form,
-                 const blink::WebInputElement& element);
+                 const blink::WebFormControlElement& element);
 
 // Clears the placeholder values and the auto-filled background for any fields
 // in the form containing |node| that have been previewed.  Resets the
 // autofilled state of |node| to |was_autofilled|.  Returns false if the form is
 // not found.
-bool ClearPreviewedFormWithElement(const blink::WebInputElement& element,
+bool ClearPreviewedFormWithElement(const blink::WebFormControlElement& element,
                                    bool was_autofilled);
 
 // Returns true if |form| has any auto-filled fields.
@@ -169,7 +170,8 @@
 bool IsWebElementEmpty(const blink::WebElement& element);
 
 // Return a gfx::RectF that is the bounding box for |element| scaled by |scale|.
-gfx::RectF GetScaledBoundingBox(float scale, blink::WebInputElement* element);
+gfx::RectF GetScaledBoundingBox(float scale,
+                                blink::WebFormControlElement* element);
 
 }  // namespace autofill
 
diff --git a/components/autofill/content/renderer/form_cache.cc b/components/autofill/content/renderer/form_cache.cc
index 431979e..d9acf37 100644
--- a/components/autofill/content/renderer/form_cache.cc
+++ b/components/autofill/content/renderer/form_cache.cc
@@ -179,7 +179,7 @@
   RemoveOldElements(frame, &initial_checked_state_);
 }
 
-bool FormCache::ClearFormWithElement(const WebInputElement& element) {
+bool FormCache::ClearFormWithElement(const WebFormControlElement& element) {
   WebFormElement form_element = element.form();
   if (form_element.isNull())
     return false;
diff --git a/components/autofill/content/renderer/form_cache.h b/components/autofill/content/renderer/form_cache.h
index 3cb2525..1f97d07 100644
--- a/components/autofill/content/renderer/form_cache.h
+++ b/components/autofill/content/renderer/form_cache.h
@@ -13,6 +13,7 @@
 
 namespace blink {
 class WebDocument;
+class WebFormControlElement;
 class WebFormElement;
 class WebFrame;
 class WebInputElement;
@@ -50,7 +51,7 @@
 
   // Clears the values of all input elements in the form that contains
   // |element|.  Returns false if the form is not found.
-  bool ClearFormWithElement(const blink::WebInputElement& element);
+  bool ClearFormWithElement(const blink::WebFormControlElement& element);
 
   // For each field in the |form|, sets the field's placeholder text to the
   // field's overall predicted type.  Also sets the title to include the field's
diff --git a/components/autofill/content/renderer/page_click_listener.h b/components/autofill/content/renderer/page_click_listener.h
index 1fc7862..4582ea5 100644
--- a/components/autofill/content/renderer/page_click_listener.h
+++ b/components/autofill/content/renderer/page_click_listener.h
@@ -6,7 +6,7 @@
 #define COMPONENTS_AUTOFILL_CONTENT_RENDERER_PAGE_CLICK_LISTENER_H_
 
 namespace blink {
-class WebInputElement;
+class WebFormControlElement;
 }
 
 namespace autofill {
@@ -19,13 +19,13 @@
   // Notification that |element| was clicked.
   // |was_focused| is true if |element| had focus BEFORE the click.
   // |is_focused| is true if |element| has focus AFTER the click was processed.
-  virtual void InputElementClicked(const blink::WebInputElement& element,
-                                   bool was_focused,
-                                   bool is_focused) = 0;
+  virtual void FormControlElementClicked(
+      const blink::WebFormControlElement& element,
+      bool was_focused) = 0;
 
-  // If the previously focused element was an input field, listeners are
-  // informed that the text field has lost its focus.
-  virtual void InputElementLostFocus() = 0;
+  // If the previously focused element was an input field or a textarea,
+  // listeners are informed that the text field has lost its focus.
+  virtual void FormControlElementLostFocus() = 0;
 
  protected:
   virtual ~PageClickListener() {}
diff --git a/components/autofill/content/renderer/page_click_tracker.cc b/components/autofill/content/renderer/page_click_tracker.cc
index 59adae1..8938826 100644
--- a/components/autofill/content/renderer/page_click_tracker.cc
+++ b/components/autofill/content/renderer/page_click_tracker.cc
@@ -13,6 +13,7 @@
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebInputElement.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebTextAreaElement.h"
 #include "third_party/WebKit/public/web/WebView.h"
 
 using blink::WebDOMEvent;
@@ -25,6 +26,7 @@
 using blink::WebMouseEvent;
 using blink::WebNode;
 using blink::WebString;
+using blink::WebTextAreaElement;
 using blink::WebView;
 
 namespace {
@@ -43,6 +45,18 @@
   return *input;
 }
 
+// Casts |node| to a WebTextAreaElement.
+// Returns an empty (isNull()) WebTextAreaElement if |node| is not a
+// textarea field.
+const WebTextAreaElement GetTextWebTextAreaElement(const WebNode& node) {
+  if (!node.isElementNode())
+    return WebTextAreaElement();
+  const WebElement element = node.toConst<WebElement>();
+  if (!element.hasTagName("textarea"))
+    return WebTextAreaElement();
+  return element.toConst<WebTextAreaElement>();
+}
+
 // Checks to see if a text field was the previously selected node and is now
 // losing its focus.
 bool DidSelectedTextFieldLoseFocus(const WebNode& newly_clicked_node) {
@@ -50,7 +64,8 @@
     newly_clicked_node.document().focusedElement();
 
   if (focused_element.isNull() ||
-      GetTextWebInputElement(focused_element).isNull())
+      (GetTextWebInputElement(focused_element).isNull() &&
+       GetTextWebTextAreaElement(focused_element).isNull()))
     return false;
 
   return focused_element != newly_clicked_node;
@@ -82,14 +97,18 @@
     return;
   }
 
-  // We are only interested in text field clicks.
+  // We are only interested in text field and textarea field clicks.
   const WebInputElement input_element =
       GetTextWebInputElement(last_node_clicked_);
-  if (input_element.isNull())
+  const WebTextAreaElement textarea_element =
+      GetTextWebTextAreaElement(last_node_clicked_);
+  if (input_element.isNull() && textarea_element.isNull())
     return;
 
-  bool is_focused = (last_node_clicked_ == render_view()->GetFocusedElement());
-  listener_->InputElementClicked(input_element, was_focused_, is_focused);
+  if (!input_element.isNull())
+    listener_->FormControlElementClicked(input_element, was_focused_);
+  else if (!textarea_element.isNull())
+    listener_->FormControlElementClicked(textarea_element, was_focused_);
 }
 
 void PageClickTracker::DidFinishDocumentLoad(blink::WebFrame* frame) {
@@ -132,7 +151,8 @@
   HandleTextFieldMaybeLosingFocus(node);
 
   // We are only interested in text field clicks.
-  if (GetTextWebInputElement(node).isNull())
+  if (GetTextWebInputElement(node).isNull() &&
+      GetTextWebTextAreaElement(node).isNull())
     return;
 
   last_node_clicked_ = node;
@@ -142,7 +162,7 @@
 void PageClickTracker::HandleTextFieldMaybeLosingFocus(
     const WebNode& newly_clicked_node) {
   if (DidSelectedTextFieldLoseFocus(newly_clicked_node))
-    listener_->InputElementLostFocus();
+    listener_->FormControlElementLostFocus();
 }
 
 }  // namespace autofill
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index df80562..6a3c2b4 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -542,7 +542,7 @@
     // keep just the first frame found, it might be a good idea to add a UMA
     // statistic or a similar check on how many frames are here to choose from.
     if (current_frame == form_frame ||
-        current_frame->findChildByName(form_frame->uniqueName())) {
+        current_frame->findChildByName(form_frame->assignedName())) {
       return form_frame;
     }
   }
@@ -637,7 +637,7 @@
 
     FormData form;
     FormFieldData field;
-    FindFormAndFieldForInputElement(
+    FindFormAndFieldForFormControlElement(
         username_element, &form, &field, REQUIRE_NONE);
     Send(new AutofillHostMsg_AddPasswordFormMapping(
         routing_id(),
@@ -699,7 +699,7 @@
 
   FormData form;
   FormFieldData field;
-  FindFormAndFieldForInputElement(
+  FindFormAndFieldForFormControlElement(
       user_input, &form, &field, REQUIRE_NONE);
 
   blink::WebInputElement selected_element = user_input;
diff --git a/components/autofill/core/browser/autocomplete_history_manager.cc b/components/autofill/core/browser/autocomplete_history_manager.cc
index 6562157..d473763 100644
--- a/components/autofill/core/browser/autocomplete_history_manager.cc
+++ b/components/autofill/core/browser/autocomplete_history_manager.cc
@@ -81,6 +81,7 @@
     int query_id,
     const base::string16& name,
     const base::string16& prefix,
+    const std::string form_control_type,
     const std::vector<base::string16>& autofill_values,
     const std::vector<base::string16>& autofill_labels,
     const std::vector<base::string16>& autofill_icons,
@@ -92,7 +93,8 @@
   autofill_labels_ = autofill_labels;
   autofill_icons_ = autofill_icons;
   autofill_unique_ids_ = autofill_unique_ids;
-  if (!manager_delegate_->IsAutocompleteEnabled()) {
+  if (!manager_delegate_->IsAutocompleteEnabled() ||
+      form_control_type == "textarea") {
     SendSuggestions(NULL);
     return;
   }
diff --git a/components/autofill/core/browser/autocomplete_history_manager.h b/components/autofill/core/browser/autocomplete_history_manager.h
index cb234db..50ad599 100644
--- a/components/autofill/core/browser/autocomplete_history_manager.h
+++ b/components/autofill/core/browser/autocomplete_history_manager.h
@@ -39,6 +39,7 @@
       int query_id,
       const base::string16& name,
       const base::string16& prefix,
+      const std::string form_control_type,
       const std::vector<base::string16>& autofill_values,
       const std::vector<base::string16>& autofill_labels,
       const std::vector<base::string16>& autofill_icons,
diff --git a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
index c26c5f5..6379f07 100644
--- a/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
+++ b/components/autofill/core/browser/autocomplete_history_manager_unittest.cc
@@ -225,4 +225,46 @@
   autocomplete_history_manager.SendSuggestions(NULL);
 }
 
+// Verify that no autocomplete suggestion is returned for textarea.
+TEST_F(AutocompleteHistoryManagerTest, NoAutocompleteSuggestionsForTextarea) {
+  TestAutocompleteHistoryManager autocomplete_history_manager(
+      autofill_driver_.get(), manager_delegate_.get());
+
+  scoped_ptr<AutofillManager> autofill_manager(new AutofillManager(
+      autofill_driver_.get(),
+      manager_delegate_.get(),
+      "en-US",
+      AutofillManager::ENABLE_AUTOFILL_DOWNLOAD_MANAGER));
+
+  MockAutofillExternalDelegate external_delegate(autofill_manager.get(),
+                                                 autofill_driver_.get());
+  autocomplete_history_manager.SetExternalDelegate(&external_delegate);
+
+  FormData form;
+  form.name = ASCIIToUTF16("MyForm");
+  form.method = ASCIIToUTF16("POST");
+  form.origin = GURL("http://myform.com/form.html");
+  form.action = GURL("http://myform.com/submit.html");
+  form.user_submitted = true;
+
+  FormFieldData field;
+  test::CreateTestFormField("Address", "address", "", "textarea", &field);
+
+  EXPECT_CALL(external_delegate,
+              OnSuggestionsReturned(0,
+                                    std::vector<base::string16>(),
+                                    std::vector<base::string16>(),
+                                    std::vector<base::string16>(),
+                                    std::vector<int>()));
+  autocomplete_history_manager.OnGetAutocompleteSuggestions(
+      0,
+      field.name,
+      field.value,
+      field.form_control_type,
+      std::vector<base::string16>(),
+      std::vector<base::string16>(),
+      std::vector<base::string16>(),
+      std::vector<int>());
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_field.cc b/components/autofill/core/browser/autofill_field.cc
index a548c25..ffd6145 100644
--- a/components/autofill/core/browser/autofill_field.cc
+++ b/components/autofill/core/browser/autofill_field.cc
@@ -224,7 +224,7 @@
 
 // Fills in the select control |field| with |value|.  If an exact match is not
 // found, falls back to alternate filling strategies based on the |type|.
-void FillSelectControl(const AutofillType& type,
+bool FillSelectControl(const AutofillType& type,
                        const base::string16& value,
                        const std::string& app_locale,
                        FormFieldData* field) {
@@ -232,29 +232,31 @@
 
   // Guard against corrupted values passed over IPC.
   if (field->option_values.size() != field->option_contents.size())
-    return;
+    return false;
 
   if (value.empty())
-    return;
+    return false;
 
   // First, search for exact matches.
   if (SetSelectControlValue(value, field))
-    return;
+    return true;
 
   // If that fails, try specific fallbacks based on the field type.
   ServerFieldType storable_type = type.GetStorableType();
   if (storable_type == ADDRESS_HOME_STATE) {
-    FillStateSelectControl(value, field);
+    return FillStateSelectControl(value, field);
   } else if (storable_type == ADDRESS_HOME_COUNTRY) {
-    FillCountrySelectControl(value, app_locale, field);
+    return FillCountrySelectControl(value, app_locale, field);
   } else if (storable_type == CREDIT_CARD_EXP_MONTH) {
-    FillExpirationMonthSelectControl(value, field);
+    return FillExpirationMonthSelectControl(value, field);
   } else if (storable_type == CREDIT_CARD_EXP_2_DIGIT_YEAR ||
              storable_type == CREDIT_CARD_EXP_4_DIGIT_YEAR) {
-    FillYearSelectControl(value, field);
+    return FillYearSelectControl(value, field);
   } else if (storable_type == CREDIT_CARD_TYPE) {
-    FillCreditCardTypeSelectControl(value, field);
+    return FillCreditCardTypeSelectControl(value, field);
   }
+
+  return false;
 }
 
 // Fills in the month control |field| with |value|.  |value| should be a date
@@ -389,22 +391,26 @@
 }
 
 // static
-void AutofillField::FillFormField(const AutofillField& field,
+bool AutofillField::FillFormField(const AutofillField& field,
                                   const base::string16& value,
                                   const std::string& app_locale,
                                   FormFieldData* field_data) {
   AutofillType type = field.Type();
 
-  if (type.GetStorableType() == PHONE_HOME_NUMBER)
+  if (type.GetStorableType() == PHONE_HOME_NUMBER) {
     FillPhoneNumberField(field, value, field_data);
-  else if (field_data->form_control_type == "select-one")
-    FillSelectControl(type, value, app_locale, field_data);
-  else if (field_data->form_control_type == "month")
-    FillMonthControl(value, field_data);
-  else if (type.GetStorableType() == ADDRESS_HOME_STREET_ADDRESS)
+    return true;
+  } else if (field_data->form_control_type == "select-one") {
+    return FillSelectControl(type, value, app_locale, field_data);
+  } else if (field_data->form_control_type == "month") {
+    return FillMonthControl(value, field_data);
+  } else if (type.GetStorableType() == ADDRESS_HOME_STREET_ADDRESS) {
     FillStreetAddress(value, field_data);
-  else
-    field_data->value = value;
+    return true;
+  }
+
+  field_data->value = value;
+  return true;
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_field.h b/components/autofill/core/browser/autofill_field.h
index 38aeaea..f0b1e7e 100644
--- a/components/autofill/core/browser/autofill_field.h
+++ b/components/autofill/core/browser/autofill_field.h
@@ -67,8 +67,8 @@
 
   // Set |field_data|'s value to |value|.  Uses |field| and |app_locale| as
   // hints when filling exceptional cases like phone number values and <select>
-  // fields.
-  static void FillFormField(const AutofillField& field,
+  // fields. Returns |true| if the field has been filled, |false| otherwise.
+  static bool FillFormField(const AutofillField& field,
                             const base::string16& value,
                             const std::string& app_locale,
                             FormFieldData* field_data);
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 96f7eb2..95126de 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -206,12 +206,18 @@
       prefs::kAutofillAuxiliaryProfilesEnabled,
       true,
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
-#else
+#else  // defined(OS_MACOSX) || defined(OS_ANDROID)
   registry->RegisterBooleanPref(
       prefs::kAutofillAuxiliaryProfilesEnabled,
       false,
       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
-#endif
+#endif  // defined(OS_MACOSX) || defined(OS_ANDROID)
+#if defined(OS_MACOSX)
+  registry->RegisterBooleanPref(
+      prefs::kAutofillAuxiliaryProfilesQueried,
+      false,
+      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+#endif  // defined(OS_MACOSX)
   registry->RegisterDoublePref(
       prefs::kAutofillPositiveUploadRate,
       kAutofillPositiveUploadRateDefaultValue,
@@ -450,7 +456,8 @@
   // hand off what we generated and they will send the results back to the
   // renderer.
   autocomplete_history_manager_->OnGetAutocompleteSuggestions(
-      query_id, field.name, field.value, values, labels, icons, unique_ids);
+      query_id, field.name, field.value, field.form_control_type, values,
+      labels, icons, unique_ids);
 }
 
 void AutofillManager::FillOrPreviewForm(
@@ -496,14 +503,15 @@
       if ((*iter) == field) {
         base::string16 value = data_model->GetInfoForVariant(
             autofill_field->Type(), variant, app_locale_);
-        AutofillField::FillFormField(*autofill_field, value, app_locale_,
-                                     &(*iter));
-        // Mark the cached field as autofilled, so that we can detect when a
-        // user edits an autofilled field (for metrics).
-        autofill_field->is_autofilled = true;
+        if (AutofillField::FillFormField(
+            *autofill_field, value, app_locale_, &(*iter))) {
+          // Mark the cached field as autofilled, so that we can detect when a
+          // user edits an autofilled field (for metrics).
+          autofill_field->is_autofilled = true;
 
-        if (!is_credit_card && !value.empty())
-          manager_delegate_->DidFillOrPreviewField(value, profile_full_name);
+          if (!is_credit_card && !value.empty())
+            manager_delegate_->DidFillOrPreviewField(value, profile_full_name);
+        }
         break;
       }
     }
@@ -547,14 +555,15 @@
           (result.fields[i] == field ||
            result.fields[i].form_control_type == "select-one" ||
            result.fields[i].value.empty());
-      AutofillField::FillFormField(*cached_field, value, app_locale_,
-                                   &result.fields[i]);
-      // Mark the cached field as autofilled, so that we can detect when a user
-      // edits an autofilled field (for metrics).
-      form_structure->field(i)->is_autofilled = true;
+      if (AutofillField::FillFormField(
+          *cached_field, value, app_locale_, &result.fields[i])) {
+        // Mark the cached field as autofilled, so that we can detect when a
+        // user edits an autofilled field (for metrics).
+        form_structure->field(i)->is_autofilled = true;
 
-      if (should_notify)
-        manager_delegate_->DidFillOrPreviewField(value, profile_full_name);
+        if (should_notify)
+          manager_delegate_->DidFillOrPreviewField(value, profile_full_name);
+      }
     }
   }
 
diff --git a/components/autofill/core/browser/personal_data_manager_mac.mm b/components/autofill/core/browser/personal_data_manager_mac.mm
index 834a115..745a60e 100644
--- a/components/autofill/core/browser/personal_data_manager_mac.mm
+++ b/components/autofill/core/browser/personal_data_manager_mac.mm
@@ -14,12 +14,15 @@
 #import "base/mac/scoped_nsexception_enabler.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/autofill/core/browser/autofill_country.h"
 #include "components/autofill/core/browser/autofill_profile.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/phone_number.h"
+#include "components/autofill/core/common/autofill_pref_names.h"
 #include "grit/component_strings.h"
 #include "ui/base/l10n/l10n_util_mac.h"
 
@@ -46,7 +49,8 @@
   virtual ~AuxiliaryProfilesImpl() {}
 
   // Import the "me" card from the Mac Address Book and fill in |profiles_|.
-  void GetAddressBookMeCard(const std::string& app_locale);
+  void GetAddressBookMeCard(const std::string& app_locale,
+                            PrefService* pref_service);
 
  private:
   void GetAddressBookNames(ABPerson* me,
@@ -73,8 +77,8 @@
 // from the active user's address book.  It looks for the user address
 // information and translates it to the internal list of |AutofillProfile| data
 // structures.
-void AuxiliaryProfilesImpl::GetAddressBookMeCard(
-    const std::string& app_locale) {
+void AuxiliaryProfilesImpl::GetAddressBookMeCard(const std::string& app_locale,
+                                                 PrefService* pref_service) {
   profiles_.clear();
 
   // +[ABAddressBook sharedAddressBook] throws an exception internally in
@@ -85,6 +89,13 @@
   ABAddressBook* addressBook = base::mac::RunBlockIgnoringExceptions(^{
       return [ABAddressBook sharedAddressBook];
   });
+  UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailable", addressBook != nil);
+  if (!pref_service->GetBoolean(prefs::kAutofillAuxiliaryProfilesQueried)) {
+    pref_service->SetBoolean(prefs::kAutofillAuxiliaryProfilesQueried, true);
+    UMA_HISTOGRAM_BOOLEAN("Autofill.AddressBookAvailableOnFirstAttempt",
+                          addressBook != nil);
+  }
+
   ABPerson* me = [addressBook me];
   if (!me)
     return;
@@ -267,7 +278,7 @@
 // Populate |auxiliary_profiles_| with the Address Book data.
 void PersonalDataManager::LoadAuxiliaryProfiles() const {
   AuxiliaryProfilesImpl impl(&auxiliary_profiles_);
-  impl.GetAddressBookMeCard(app_locale_);
+  impl.GetAddressBookMeCard(app_locale_, pref_service_);
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/webdata/autofill_table.cc b/components/autofill/core/browser/webdata/autofill_table.cc
index 6866cda..ce7cebe 100644
--- a/components/autofill/core/browser/webdata/autofill_table.cc
+++ b/components/autofill/core/browser/webdata/autofill_table.cc
@@ -380,8 +380,7 @@
   return GetKey();
 }
 
-bool AutofillTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
-  WebDatabaseTable::Init(db, meta_table);
+bool AutofillTable::CreateTablesIfNecessary() {
   return (InitMainTable() && InitCreditCardsTable() && InitProfilesTable() &&
           InitProfileNamesTable() && InitProfileEmailsTable() &&
           InitProfilePhonesTable() && InitProfileTrashTable());
@@ -1330,6 +1329,24 @@
 }
 
 bool AutofillTable::MigrateToVersion22ClearAutofillEmptyValueElements() {
+  if (!db_->DoesTableExist("autofill") &&
+      (!db_->Execute("CREATE TABLE autofill ("
+                     "  name VARCHAR,"
+                     "  value VARCHAR,"
+                     "  value_lower VARCHAR,"
+                     "  pair_id INTEGER PRIMARY KEY,"
+                     "  count INTEGER DEFAULT 1)") ||
+       !db_->Execute("CREATE INDEX autofill_name ON autofill (name)") ||
+       !db_->Execute("CREATE INDEX autofill_name_value_lower ON"
+                     "  autofill (name, value_lower)") ||
+       !db_->Execute("CREATE TABLE autofill_dates ("
+                     "  pair_id INTEGER DEFAULT 0,"
+                     "  date_created INTEGER DEFAULT 0)") ||
+       !db_->Execute("CREATE INDEX autofill_dates_pair_id ON"
+                     "  autofill (pair_id)")))
+    return false;
+
+
   sql::Statement s(db_->GetUniqueStatement(
       "SELECT pair_id FROM autofill WHERE TRIM(value) = \"\""));
   if (!s.is_valid())
@@ -1386,11 +1403,46 @@
 // the existence of the columns only AFTER we've executed the commands
 // to add them.
 bool AutofillTable::MigrateToVersion23AddCardNumberEncryptedColumn() {
+  if (!db_->DoesTableExist("autofill_profiles") &&
+      (!db_->Execute("CREATE TABLE autofill_profiles ( "
+                     "label VARCHAR, "
+                     "unique_id INTEGER PRIMARY KEY, "
+                     "first_name VARCHAR, "
+                     "middle_name VARCHAR, "
+                     "last_name VARCHAR, "
+                     "email VARCHAR, "
+                     "company_name VARCHAR, "
+                     "address_line_1 VARCHAR, "
+                     "address_line_2 VARCHAR, "
+                     "city VARCHAR, "
+                     "state VARCHAR, "
+                     "zipcode VARCHAR, "
+                     "country VARCHAR, "
+                     "phone VARCHAR, "
+                     "fax VARCHAR)") ||
+       !db_->Execute("CREATE INDEX autofill_profiles_label_index"
+                     "  ON autofill_profiles (label)")))
+    return false;
+
+  if (!db_->DoesTableExist("credit_cards") &&
+      (!db_->Execute("CREATE TABLE credit_cards ( "
+                     "label VARCHAR, "
+                     "unique_id INTEGER PRIMARY KEY, "
+                     "name_on_card VARCHAR, "
+                     "type VARCHAR, "
+                     "card_number VARCHAR, "
+                     "expiration_month INTEGER, "
+                     "expiration_year INTEGER, "
+                     "verification_code VARCHAR, "
+                     "billing_address VARCHAR, "
+                     "shipping_address VARCHAR)") ||
+       !db_->Execute("CREATE INDEX credit_cards_label_index"
+                     "  ON credit_cards (label)")))
+    return false;
+
   if (!db_->DoesColumnExist("credit_cards", "card_number_encrypted")) {
     if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
                       "card_number_encrypted BLOB DEFAULT NULL")) {
-      LOG(WARNING) << "Could not add card_number_encrypted to "
-                      "credit_cards table.";
       return false;
     }
   }
@@ -1398,8 +1450,6 @@
   if (!db_->DoesColumnExist("credit_cards", "verification_code_encrypted")) {
     if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
                       "verification_code_encrypted BLOB DEFAULT NULL")) {
-      LOG(WARNING) << "Could not add verification_code_encrypted to "
-                      "credit_cards table.";
       return false;
     }
   }
@@ -1723,6 +1773,27 @@
 // schema is in place because the table was newly created when migrating
 // from a pre-version-22 database.
 bool AutofillTable::MigrateToVersion33ProfilesBasedOnFirstName() {
+  if (!db_->DoesTableExist("autofill_profile_names") &&
+      !db_->Execute("CREATE TABLE autofill_profile_names ( "
+                    "guid VARCHAR, "
+                    "first_name VARCHAR, "
+                    "middle_name VARCHAR, "
+                    "last_name VARCHAR)"))
+    return false;
+
+  if (!db_->DoesTableExist("autofill_profile_emails") &&
+      !db_->Execute("CREATE TABLE autofill_profile_emails ( "
+                    "guid VARCHAR, "
+                    "email VARCHAR)"))
+    return false;
+
+  if (!db_->DoesTableExist("autofill_profile_phones") &&
+      !db_->Execute("CREATE TABLE autofill_profile_phones ( "
+                    "guid VARCHAR, "
+                    "type INTEGER DEFAULT 0, "
+                    "number VARCHAR)"))
+    return false;
+
   if (db_->DoesColumnExist("autofill_profiles", "first_name")) {
     // Create autofill_profiles_temp table that will receive the data.
     if (!db_->DoesTableExist("autofill_profiles_temp")) {
@@ -1880,6 +1951,10 @@
 
 // Merge and cull older profiles where possible.
 bool AutofillTable::MigrateToVersion37MergeAndCullOlderProfiles() {
+  if (!db_->DoesTableExist("autofill_profiles_trash") &&
+      !db_->Execute("CREATE TABLE autofill_profiles_trash (guid VARCHAR)"))
+    return false;
+
   sql::Statement s(db_->GetUniqueStatement(
       "SELECT guid, date_modified FROM autofill_profiles"));
 
diff --git a/components/autofill/core/browser/webdata/autofill_table.h b/components/autofill/core/browser/webdata/autofill_table.h
index 5041243..0a72e81 100644
--- a/components/autofill/core/browser/webdata/autofill_table.h
+++ b/components/autofill/core/browser/webdata/autofill_table.h
@@ -128,7 +128,7 @@
   static AutofillTable* FromWebDatabase(WebDatabase* db);
 
   virtual WebDatabaseTable::TypeKey GetTypeKey() const OVERRIDE;
-  virtual bool Init(sql::Connection* db, sql::MetaTable* meta_table) OVERRIDE;
+  virtual bool CreateTablesIfNecessary() OVERRIDE;
   virtual bool IsSyncable() OVERRIDE;
   virtual bool MigrateToVersion(int version,
                                 bool* update_compatible_version) OVERRIDE;
diff --git a/components/autofill/core/common/autofill_pref_names.cc b/components/autofill/core/common/autofill_pref_names.cc
index 622783c..d7385bb 100644
--- a/components/autofill/core/common/autofill_pref_names.cc
+++ b/components/autofill/core/common/autofill_pref_names.cc
@@ -12,6 +12,12 @@
 const char kAutofillAuxiliaryProfilesEnabled[] =
     "autofill.auxiliary_profiles_enabled";
 
+// Boolean that is true when at least one read request for auxiliary Autofill
+// profiles has been issued.  Currently applies only to auxiliary profiles on
+// Mac.
+const char kAutofillAuxiliaryProfilesQueried[] =
+    "autofill.auxiliary_profiles_queried";
+
 // Boolean that is true if Autofill is enabled and allowed to save profile data.
 const char kAutofillEnabled[] = "autofill.enabled";
 
diff --git a/components/autofill/core/common/autofill_pref_names.h b/components/autofill/core/common/autofill_pref_names.h
index e52cc72..50af375 100644
--- a/components/autofill/core/common/autofill_pref_names.h
+++ b/components/autofill/core/common/autofill_pref_names.h
@@ -11,6 +11,7 @@
 // Alphabetical list of preference names specific to the Autofill
 // component. Keep alphabetized, and document each in the .cc file.
 extern const char kAutofillAuxiliaryProfilesEnabled[];
+extern const char kAutofillAuxiliaryProfilesQueried[];
 extern const char kAutofillEnabled[];
 extern const char kAutofillNegativeUploadRate[];
 extern const char kAutofillPositiveUploadRate[];
diff --git a/components/autofill_content_browser.target.darwin-arm.mk b/components/autofill_content_browser.target.darwin-arm.mk
index 6523012..9ad08ee 100644
--- a/components/autofill_content_browser.target.darwin-arm.mk
+++ b/components/autofill_content_browser.target.darwin-arm.mk
@@ -36,7 +36,6 @@
 LOCAL_SRC_FILES := \
 	components/autofill/content/browser/content_autofill_driver.cc \
 	components/autofill/content/browser/request_autocomplete_manager.cc \
-	components/autofill/content/browser/risk/fingerprint.cc \
 	components/autofill/content/browser/wallet/form_field_error.cc \
 	components/autofill/content/browser/wallet/full_wallet.cc \
 	components/autofill/content/browser/wallet/gaia_account.cc \
@@ -108,9 +107,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -132,6 +129,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -256,9 +254,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -280,6 +276,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_content_browser.target.darwin-mips.mk b/components/autofill_content_browser.target.darwin-mips.mk
index 445222d..530d51b 100644
--- a/components/autofill_content_browser.target.darwin-mips.mk
+++ b/components/autofill_content_browser.target.darwin-mips.mk
@@ -36,7 +36,6 @@
 LOCAL_SRC_FILES := \
 	components/autofill/content/browser/content_autofill_driver.cc \
 	components/autofill/content/browser/request_autocomplete_manager.cc \
-	components/autofill/content/browser/risk/fingerprint.cc \
 	components/autofill/content/browser/wallet/form_field_error.cc \
 	components/autofill/content/browser/wallet/full_wallet.cc \
 	components/autofill/content/browser/wallet/gaia_account.cc \
@@ -107,9 +106,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -131,6 +128,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -254,9 +252,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -278,6 +274,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_content_browser.target.darwin-x86.mk b/components/autofill_content_browser.target.darwin-x86.mk
index c2cd02c..7aa6247 100644
--- a/components/autofill_content_browser.target.darwin-x86.mk
+++ b/components/autofill_content_browser.target.darwin-x86.mk
@@ -36,7 +36,6 @@
 LOCAL_SRC_FILES := \
 	components/autofill/content/browser/content_autofill_driver.cc \
 	components/autofill/content/browser/request_autocomplete_manager.cc \
-	components/autofill/content/browser/risk/fingerprint.cc \
 	components/autofill/content/browser/wallet/form_field_error.cc \
 	components/autofill/content/browser/wallet/full_wallet.cc \
 	components/autofill/content/browser/wallet/gaia_account.cc \
@@ -109,9 +108,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -132,6 +129,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -256,9 +254,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -279,6 +275,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_content_browser.target.darwin-x86_64.mk b/components/autofill_content_browser.target.darwin-x86_64.mk
new file mode 100644
index 0000000..513923d
--- /dev/null
+++ b/components/autofill_content_browser.target.darwin-x86_64.mk
@@ -0,0 +1,410 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_risk_proto_gyp)/components_autofill_content_risk_proto_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_regexes_gyp)/autofill_regexes.stamp \
+	$(call intermediates-dir-for,GYP,components_components_resources_gyp)/components_resources.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/content/browser/content_autofill_driver.cc \
+	components/autofill/content/browser/request_autocomplete_manager.cc \
+	components/autofill/content/browser/wallet/form_field_error.cc \
+	components/autofill/content/browser/wallet/full_wallet.cc \
+	components/autofill/content/browser/wallet/gaia_account.cc \
+	components/autofill/content/browser/wallet/instrument.cc \
+	components/autofill/content/browser/wallet/required_action.cc \
+	components/autofill/content/browser/wallet/wallet_address.cc \
+	components/autofill/content/browser/wallet/wallet_client.cc \
+	components/autofill/content/browser/wallet/wallet_items.cc \
+	components/autofill/content/browser/wallet/wallet_service_url.cc \
+	components/autofill/content/browser/wallet/wallet_signin_helper.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp \
+	skia_skia_library_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp \
+	ui_base_ui_base_gyp \
+	components_autofill_content_risk_proto_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_browser_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_browser
+autofill_content_browser: components_autofill_content_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_content_browser.target.linux-arm.mk b/components/autofill_content_browser.target.linux-arm.mk
index 6523012..9ad08ee 100644
--- a/components/autofill_content_browser.target.linux-arm.mk
+++ b/components/autofill_content_browser.target.linux-arm.mk
@@ -36,7 +36,6 @@
 LOCAL_SRC_FILES := \
 	components/autofill/content/browser/content_autofill_driver.cc \
 	components/autofill/content/browser/request_autocomplete_manager.cc \
-	components/autofill/content/browser/risk/fingerprint.cc \
 	components/autofill/content/browser/wallet/form_field_error.cc \
 	components/autofill/content/browser/wallet/full_wallet.cc \
 	components/autofill/content/browser/wallet/gaia_account.cc \
@@ -108,9 +107,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -132,6 +129,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -256,9 +254,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -280,6 +276,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_content_browser.target.linux-mips.mk b/components/autofill_content_browser.target.linux-mips.mk
index 445222d..530d51b 100644
--- a/components/autofill_content_browser.target.linux-mips.mk
+++ b/components/autofill_content_browser.target.linux-mips.mk
@@ -36,7 +36,6 @@
 LOCAL_SRC_FILES := \
 	components/autofill/content/browser/content_autofill_driver.cc \
 	components/autofill/content/browser/request_autocomplete_manager.cc \
-	components/autofill/content/browser/risk/fingerprint.cc \
 	components/autofill/content/browser/wallet/form_field_error.cc \
 	components/autofill/content/browser/wallet/full_wallet.cc \
 	components/autofill/content/browser/wallet/gaia_account.cc \
@@ -107,9 +106,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -131,6 +128,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -254,9 +252,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -278,6 +274,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_content_browser.target.linux-x86.mk b/components/autofill_content_browser.target.linux-x86.mk
index c2cd02c..7aa6247 100644
--- a/components/autofill_content_browser.target.linux-x86.mk
+++ b/components/autofill_content_browser.target.linux-x86.mk
@@ -36,7 +36,6 @@
 LOCAL_SRC_FILES := \
 	components/autofill/content/browser/content_autofill_driver.cc \
 	components/autofill/content/browser/request_autocomplete_manager.cc \
-	components/autofill/content/browser/risk/fingerprint.cc \
 	components/autofill/content/browser/wallet/form_field_error.cc \
 	components/autofill/content/browser/wallet/full_wallet.cc \
 	components/autofill/content/browser/wallet/gaia_account.cc \
@@ -109,9 +108,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -132,6 +129,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -256,9 +254,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -279,6 +275,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_content_browser.target.linux-x86_64.mk b/components/autofill_content_browser.target.linux-x86_64.mk
new file mode 100644
index 0000000..513923d
--- /dev/null
+++ b/components/autofill_content_browser.target.linux-x86_64.mk
@@ -0,0 +1,410 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,components_autofill_content_risk_proto_gyp)/components_autofill_content_risk_proto_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_regexes_gyp)/autofill_regexes.stamp \
+	$(call intermediates-dir-for,GYP,components_components_resources_gyp)/components_resources.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/content/browser/content_autofill_driver.cc \
+	components/autofill/content/browser/request_autocomplete_manager.cc \
+	components/autofill/content/browser/wallet/form_field_error.cc \
+	components/autofill/content/browser/wallet/full_wallet.cc \
+	components/autofill/content/browser/wallet/gaia_account.cc \
+	components/autofill/content/browser/wallet/instrument.cc \
+	components/autofill/content/browser/wallet/required_action.cc \
+	components/autofill/content/browser/wallet/wallet_address.cc \
+	components/autofill/content/browser/wallet/wallet_client.cc \
+	components/autofill/content/browser/wallet/wallet_items.cc \
+	components/autofill/content/browser/wallet/wallet_service_url.cc \
+	components/autofill/content/browser/wallet/wallet_signin_helper.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp \
+	skia_skia_library_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp \
+	ui_base_ui_base_gyp \
+	components_autofill_content_risk_proto_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_browser_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_browser
+autofill_content_browser: components_autofill_content_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_content_common.target.darwin-arm.mk b/components/autofill_content_common.target.darwin-arm.mk
index 8809528..f47b382 100644
--- a/components/autofill_content_common.target.darwin-arm.mk
+++ b/components/autofill_content_common.target.darwin-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -98,6 +96,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -209,9 +208,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -220,6 +217,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_common.target.darwin-mips.mk b/components/autofill_content_common.target.darwin-mips.mk
index 85909eb..eaffa71 100644
--- a/components/autofill_content_common.target.darwin-mips.mk
+++ b/components/autofill_content_common.target.darwin-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -97,6 +95,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -207,9 +206,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -218,6 +215,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_common.target.darwin-x86.mk b/components/autofill_content_common.target.darwin-x86.mk
index 31b3564..011a80b 100644
--- a/components/autofill_content_common.target.darwin-x86.mk
+++ b/components/autofill_content_common.target.darwin-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -99,6 +97,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,9 +209,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -221,6 +218,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_common.target.darwin-x86_64.mk b/components/autofill_content_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..fde0bbd
--- /dev/null
+++ b/components/autofill_content_common.target.darwin-x86_64.mk
@@ -0,0 +1,334 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_minimal_gyp)/blink_minimal.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/content/common/autofill_message_generator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_common_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_common
+autofill_content_common: components_autofill_content_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_content_common.target.linux-arm.mk b/components/autofill_content_common.target.linux-arm.mk
index 8809528..f47b382 100644
--- a/components/autofill_content_common.target.linux-arm.mk
+++ b/components/autofill_content_common.target.linux-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -98,6 +96,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -209,9 +208,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -220,6 +217,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_common.target.linux-mips.mk b/components/autofill_content_common.target.linux-mips.mk
index 85909eb..eaffa71 100644
--- a/components/autofill_content_common.target.linux-mips.mk
+++ b/components/autofill_content_common.target.linux-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -97,6 +95,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -207,9 +206,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -218,6 +215,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_common.target.linux-x86.mk b/components/autofill_content_common.target.linux-x86.mk
index 31b3564..011a80b 100644
--- a/components/autofill_content_common.target.linux-x86.mk
+++ b/components/autofill_content_common.target.linux-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -99,6 +97,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,9 +209,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -221,6 +218,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_common.target.linux-x86_64.mk b/components/autofill_content_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..fde0bbd
--- /dev/null
+++ b/components/autofill_content_common.target.linux-x86_64.mk
@@ -0,0 +1,334 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_minimal_gyp)/blink_minimal.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/content/common/autofill_message_generator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_common_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_common
+autofill_content_common: components_autofill_content_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_content_renderer.target.darwin-arm.mk b/components/autofill_content_renderer.target.darwin-arm.mk
index 2c71c7d..ecb59f5 100644
--- a/components/autofill_content_renderer.target.darwin-arm.mk
+++ b/components/autofill_content_renderer.target.darwin-arm.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -233,9 +232,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -248,6 +245,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.darwin-mips.mk b/components/autofill_content_renderer.target.darwin-mips.mk
index 658503c..92a9487 100644
--- a/components/autofill_content_renderer.target.darwin-mips.mk
+++ b/components/autofill_content_renderer.target.darwin-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -231,9 +230,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -246,6 +243,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.darwin-x86.mk b/components/autofill_content_renderer.target.darwin-x86.mk
index ea41ac6..2a76f73 100644
--- a/components/autofill_content_renderer.target.darwin-x86.mk
+++ b/components/autofill_content_renderer.target.darwin-x86.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +109,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -234,9 +233,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +246,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.darwin-x86_64.mk b/components/autofill_content_renderer.target.darwin-x86_64.mk
new file mode 100644
index 0000000..3554380
--- /dev/null
+++ b/components/autofill_content_renderer.target.darwin-x86_64.mk
@@ -0,0 +1,374 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/content/renderer/autofill_agent.cc \
+	components/autofill/content/renderer/form_autofill_util.cc \
+	components/autofill/content/renderer/form_cache.cc \
+	components/autofill/content/renderer/page_click_tracker.cc \
+	components/autofill/content/renderer/password_autofill_agent.cc \
+	components/autofill/content/renderer/password_form_conversion_utils.cc \
+	components/autofill/content/renderer/password_generation_agent.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_renderer
+autofill_content_renderer: components_autofill_content_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_content_renderer.target.linux-arm.mk b/components/autofill_content_renderer.target.linux-arm.mk
index 2c71c7d..ecb59f5 100644
--- a/components/autofill_content_renderer.target.linux-arm.mk
+++ b/components/autofill_content_renderer.target.linux-arm.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -233,9 +232,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -248,6 +245,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.linux-mips.mk b/components/autofill_content_renderer.target.linux-mips.mk
index 658503c..92a9487 100644
--- a/components/autofill_content_renderer.target.linux-mips.mk
+++ b/components/autofill_content_renderer.target.linux-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -231,9 +230,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -246,6 +243,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.linux-x86.mk b/components/autofill_content_renderer.target.linux-x86.mk
index ea41ac6..2a76f73 100644
--- a/components/autofill_content_renderer.target.linux-x86.mk
+++ b/components/autofill_content_renderer.target.linux-x86.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +109,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -234,9 +233,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +246,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_renderer.target.linux-x86_64.mk b/components/autofill_content_renderer.target.linux-x86_64.mk
new file mode 100644
index 0000000..3554380
--- /dev/null
+++ b/components/autofill_content_renderer.target.linux-x86_64.mk
@@ -0,0 +1,374 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/content/renderer/autofill_agent.cc \
+	components/autofill/content/renderer/form_autofill_util.cc \
+	components/autofill/content/renderer/form_cache.cc \
+	components/autofill/content/renderer/page_click_tracker.cc \
+	components/autofill/content/renderer/password_autofill_agent.cc \
+	components/autofill/content/renderer/password_form_conversion_utils.cc \
+	components/autofill/content/renderer/password_generation_agent.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_renderer
+autofill_content_renderer: components_autofill_content_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_content_risk_proto.target.darwin-arm.mk b/components/autofill_content_risk_proto.target.darwin-arm.mk
index 1f04198..c9277bb 100644
--- a/components/autofill_content_risk_proto.target.darwin-arm.mk
+++ b/components/autofill_content_risk_proto.target.darwin-arm.mk
@@ -108,6 +108,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -197,6 +198,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_risk_proto.target.darwin-mips.mk b/components/autofill_content_risk_proto.target.darwin-mips.mk
index 92a6e13..5c42329 100644
--- a/components/autofill_content_risk_proto.target.darwin-mips.mk
+++ b/components/autofill_content_risk_proto.target.darwin-mips.mk
@@ -107,6 +107,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -195,6 +196,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_risk_proto.target.darwin-x86.mk b/components/autofill_content_risk_proto.target.darwin-x86.mk
index 3a45c52..3719944 100644
--- a/components/autofill_content_risk_proto.target.darwin-x86.mk
+++ b/components/autofill_content_risk_proto.target.darwin-x86.mk
@@ -109,6 +109,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -198,6 +199,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_risk_proto.target.darwin-x86_64.mk b/components/autofill_content_risk_proto.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d91a852
--- /dev/null
+++ b/components/autofill_content_risk_proto.target.darwin-x86_64.mk
@@ -0,0 +1,296 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_risk_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "components_components_gyp_autofill_content_risk_proto_target_genproto":
+# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['autofill/content/browser/risk/proto/fingerprint.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'autofill/content/browser/risk/proto', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: $(LOCAL_PATH)/components/autofill/content/browser/risk/proto/fingerprint.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto; cd $(gyp_local_path)/components; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h" --proto-in-dir autofill/content/browser/risk/proto --proto-in-file "fingerprint$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto" --python_out "$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto"
+
+$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h: $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py ;
+.PHONY: components_autofill_content_risk_proto_gyp_rule_trigger
+components_autofill_content_risk_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/fingerprint.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/fingerprint.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h \
+	components_autofill_content_risk_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_risk_proto_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_risk_proto
+autofill_content_risk_proto: components_autofill_content_risk_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_content_risk_proto.target.linux-arm.mk b/components/autofill_content_risk_proto.target.linux-arm.mk
index 1f04198..c9277bb 100644
--- a/components/autofill_content_risk_proto.target.linux-arm.mk
+++ b/components/autofill_content_risk_proto.target.linux-arm.mk
@@ -108,6 +108,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -197,6 +198,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_risk_proto.target.linux-mips.mk b/components/autofill_content_risk_proto.target.linux-mips.mk
index 92a6e13..5c42329 100644
--- a/components/autofill_content_risk_proto.target.linux-mips.mk
+++ b/components/autofill_content_risk_proto.target.linux-mips.mk
@@ -107,6 +107,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -195,6 +196,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_risk_proto.target.linux-x86.mk b/components/autofill_content_risk_proto.target.linux-x86.mk
index 3a45c52..3719944 100644
--- a/components/autofill_content_risk_proto.target.linux-x86.mk
+++ b/components/autofill_content_risk_proto.target.linux-x86.mk
@@ -109,6 +109,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -198,6 +199,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_content_risk_proto.target.linux-x86_64.mk b/components/autofill_content_risk_proto.target.linux-x86_64.mk
new file mode 100644
index 0000000..d91a852
--- /dev/null
+++ b/components/autofill_content_risk_proto.target.linux-x86_64.mk
@@ -0,0 +1,296 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_content_risk_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "components_components_gyp_autofill_content_risk_proto_target_genproto":
+# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['autofill/content/browser/risk/proto/fingerprint.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'autofill/content/browser/risk/proto', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py: $(LOCAL_PATH)/components/autofill/content/browser/risk/proto/fingerprint.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto; cd $(gyp_local_path)/components; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h" --proto-in-dir autofill/content/browser/risk/proto --proto-in-file "fingerprint$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto" --python_out "$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto"
+
+$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h: $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py ;
+.PHONY: components_autofill_content_risk_proto_gyp_rule_trigger
+components_autofill_content_risk_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/fingerprint.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/fingerprint.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/components/autofill/content/browser/risk/proto/fingerprint_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto/fingerprint.pb.h \
+	components_autofill_content_risk_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/components/autofill/content/browser/risk/proto
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_content_risk_proto_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_content_risk_proto
+autofill_content_risk_proto: components_autofill_content_risk_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_core_browser.target.darwin-arm.mk b/components/autofill_core_browser.target.darwin-arm.mk
index 3337c90..aa4de29 100644
--- a/components/autofill_core_browser.target.darwin-arm.mk
+++ b/components/autofill_core_browser.target.darwin-arm.mk
@@ -133,9 +133,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -157,6 +155,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -279,9 +278,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -303,6 +300,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_core_browser.target.darwin-mips.mk b/components/autofill_core_browser.target.darwin-mips.mk
index c62ff39..40ace50 100644
--- a/components/autofill_core_browser.target.darwin-mips.mk
+++ b/components/autofill_core_browser.target.darwin-mips.mk
@@ -132,9 +132,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -156,6 +154,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -277,9 +276,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -301,6 +298,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_core_browser.target.darwin-x86.mk b/components/autofill_core_browser.target.darwin-x86.mk
index 23ee512..aadf885 100644
--- a/components/autofill_core_browser.target.darwin-x86.mk
+++ b/components/autofill_core_browser.target.darwin-x86.mk
@@ -134,9 +134,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -157,6 +155,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -279,9 +278,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -302,6 +299,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_core_browser.target.darwin-x86_64.mk b/components/autofill_core_browser.target.darwin-x86_64.mk
new file mode 100644
index 0000000..be2b268
--- /dev/null
+++ b/components/autofill_core_browser.target.darwin-x86_64.mk
@@ -0,0 +1,430 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_core_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_regexes_gyp)/autofill_regexes.stamp \
+	$(call intermediates-dir-for,GYP,components_components_resources_gyp)/components_resources.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/autofill_regex_constants.cc: $(gyp_shared_intermediate_dir)/autofill_regex_constants.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/autofill_regex_constants.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)
+
+LOCAL_SRC_FILES := \
+	components/autofill/core/browser/address.cc \
+	components/autofill/core/browser/address_field.cc \
+	components/autofill/core/browser/autocomplete_history_manager.cc \
+	components/autofill/core/browser/autofill_country.cc \
+	components/autofill/core/browser/autofill_data_model.cc \
+	components/autofill/core/browser/autofill_download.cc \
+	components/autofill/core/browser/autofill_external_delegate.cc \
+	components/autofill/core/browser/autofill_field.cc \
+	components/autofill/core/browser/autofill_manager.cc \
+	components/autofill/core/browser/autofill_metrics.cc \
+	components/autofill/core/browser/autofill_profile.cc \
+	components/autofill/core/browser/autofill_regexes.cc \
+	components/autofill/core/browser/autofill_scanner.cc \
+	components/autofill/core/browser/autofill_type.cc \
+	components/autofill/core/browser/autofill_xml_parser.cc \
+	components/autofill/core/browser/contact_info.cc \
+	components/autofill/core/browser/credit_card.cc \
+	components/autofill/core/browser/credit_card_field.cc \
+	components/autofill/core/browser/email_field.cc \
+	components/autofill/core/browser/form_field.cc \
+	components/autofill/core/browser/form_group.cc \
+	components/autofill/core/browser/form_structure.cc \
+	components/autofill/core/browser/name_field.cc \
+	components/autofill/core/browser/password_autofill_manager.cc \
+	components/autofill/core/browser/password_generator.cc \
+	components/autofill/core/browser/personal_data_manager.cc \
+	components/autofill/core/browser/phone_field.cc \
+	components/autofill/core/browser/phone_number.cc \
+	components/autofill/core/browser/phone_number_i18n.cc \
+	components/autofill/core/browser/state_names.cc \
+	components/autofill/core/browser/validation.cc \
+	components/autofill/core/browser/webdata/autofill_change.cc \
+	components/autofill/core/browser/webdata/autofill_entry.cc \
+	components/autofill/core/browser/webdata/autofill_table.cc \
+	components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc \
+	components/autofill/core/browser/webdata/autofill_webdata_service.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_core_browser_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_core_browser
+autofill_core_browser: components_autofill_core_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_core_browser.target.linux-arm.mk b/components/autofill_core_browser.target.linux-arm.mk
index 3337c90..aa4de29 100644
--- a/components/autofill_core_browser.target.linux-arm.mk
+++ b/components/autofill_core_browser.target.linux-arm.mk
@@ -133,9 +133,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -157,6 +155,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -279,9 +278,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -303,6 +300,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_core_browser.target.linux-mips.mk b/components/autofill_core_browser.target.linux-mips.mk
index c62ff39..40ace50 100644
--- a/components/autofill_core_browser.target.linux-mips.mk
+++ b/components/autofill_core_browser.target.linux-mips.mk
@@ -132,9 +132,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -156,6 +154,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -277,9 +276,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -301,6 +298,7 @@
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_core_browser.target.linux-x86.mk b/components/autofill_core_browser.target.linux-x86.mk
index 23ee512..aadf885 100644
--- a/components/autofill_core_browser.target.linux-x86.mk
+++ b/components/autofill_core_browser.target.linux-x86.mk
@@ -134,9 +134,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -157,6 +155,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -279,9 +278,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -302,6 +299,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/components/autofill_core_browser.target.linux-x86_64.mk b/components/autofill_core_browser.target.linux-x86_64.mk
new file mode 100644
index 0000000..be2b268
--- /dev/null
+++ b/components/autofill_core_browser.target.linux-x86_64.mk
@@ -0,0 +1,430 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_core_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_regexes_gyp)/autofill_regexes.stamp \
+	$(call intermediates-dir-for,GYP,components_components_resources_gyp)/components_resources.stamp \
+	$(call intermediates-dir-for,GYP,components_components_strings_gyp)/components_strings.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/autofill_regex_constants.cc: $(gyp_shared_intermediate_dir)/autofill_regex_constants.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/autofill_regex_constants.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)
+
+LOCAL_SRC_FILES := \
+	components/autofill/core/browser/address.cc \
+	components/autofill/core/browser/address_field.cc \
+	components/autofill/core/browser/autocomplete_history_manager.cc \
+	components/autofill/core/browser/autofill_country.cc \
+	components/autofill/core/browser/autofill_data_model.cc \
+	components/autofill/core/browser/autofill_download.cc \
+	components/autofill/core/browser/autofill_external_delegate.cc \
+	components/autofill/core/browser/autofill_field.cc \
+	components/autofill/core/browser/autofill_manager.cc \
+	components/autofill/core/browser/autofill_metrics.cc \
+	components/autofill/core/browser/autofill_profile.cc \
+	components/autofill/core/browser/autofill_regexes.cc \
+	components/autofill/core/browser/autofill_scanner.cc \
+	components/autofill/core/browser/autofill_type.cc \
+	components/autofill/core/browser/autofill_xml_parser.cc \
+	components/autofill/core/browser/contact_info.cc \
+	components/autofill/core/browser/credit_card.cc \
+	components/autofill/core/browser/credit_card_field.cc \
+	components/autofill/core/browser/email_field.cc \
+	components/autofill/core/browser/form_field.cc \
+	components/autofill/core/browser/form_group.cc \
+	components/autofill/core/browser/form_structure.cc \
+	components/autofill/core/browser/name_field.cc \
+	components/autofill/core/browser/password_autofill_manager.cc \
+	components/autofill/core/browser/password_generator.cc \
+	components/autofill/core/browser/personal_data_manager.cc \
+	components/autofill/core/browser/phone_field.cc \
+	components/autofill/core/browser/phone_number.cc \
+	components/autofill/core/browser/phone_number_i18n.cc \
+	components/autofill/core/browser/state_names.cc \
+	components/autofill/core/browser/validation.cc \
+	components/autofill/core/browser/webdata/autofill_change.cc \
+	components/autofill/core/browser/webdata/autofill_entry.cc \
+	components/autofill/core/browser/webdata/autofill_table.cc \
+	components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc \
+	components/autofill/core/browser/webdata/autofill_webdata_service.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/components \
+	$(gyp_shared_intermediate_dir)/components/strings \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_core_browser_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_core_browser
+autofill_core_browser: components_autofill_core_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_core_common.target.darwin-arm.mk b/components/autofill_core_common.target.darwin-arm.mk
index 2abf1f7..0649967 100644
--- a/components/autofill_core_common.target.darwin-arm.mk
+++ b/components/autofill_core_common.target.darwin-arm.mk
@@ -105,9 +105,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -116,6 +114,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_core_common.target.darwin-mips.mk b/components/autofill_core_common.target.darwin-mips.mk
index 7d17a9a..5028877 100644
--- a/components/autofill_core_common.target.darwin-mips.mk
+++ b/components/autofill_core_common.target.darwin-mips.mk
@@ -104,9 +104,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -115,6 +113,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -223,9 +222,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -234,6 +231,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_core_common.target.darwin-x86.mk b/components/autofill_core_common.target.darwin-x86.mk
index 915a2dd..2a9e10d 100644
--- a/components/autofill_core_common.target.darwin-x86.mk
+++ b/components/autofill_core_common.target.darwin-x86.mk
@@ -105,9 +105,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -116,6 +114,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -235,6 +232,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_core_common.target.darwin-x86_64.mk b/components/autofill_core_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..bba6236
--- /dev/null
+++ b/components/autofill_core_common.target.darwin-x86_64.mk
@@ -0,0 +1,348 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_core_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_jni_headers_gyp)/autofill_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/core/browser/android/auxiliary_profile_loader_android.cc \
+	components/autofill/core/browser/android/auxiliary_profiles_android.cc \
+	components/autofill/core/browser/android/component_jni_registrar.cc \
+	components/autofill/core/browser/android/personal_data_manager_android.cc \
+	components/autofill/core/common/autofill_constants.cc \
+	components/autofill/core/common/autofill_data_validation.cc \
+	components/autofill/core/common/autofill_pref_names.cc \
+	components/autofill/core/common/autofill_switches.cc \
+	components/autofill/core/common/form_data.cc \
+	components/autofill/core/common/form_data_predictions.cc \
+	components/autofill/core/common/form_field_data.cc \
+	components/autofill/core/common/form_field_data_predictions.cc \
+	components/autofill/core/common/password_autofill_util.cc \
+	components/autofill/core/common/password_form.cc \
+	components/autofill/core/common/password_form_fill_data.cc \
+	components/autofill/core/common/password_generation_util.cc \
+	components/autofill/core/common/web_element_descriptor.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/autofill \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/autofill \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_base_ui_base_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_core_common_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_core_common
+autofill_core_common: components_autofill_core_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_core_common.target.linux-arm.mk b/components/autofill_core_common.target.linux-arm.mk
index 2abf1f7..0649967 100644
--- a/components/autofill_core_common.target.linux-arm.mk
+++ b/components/autofill_core_common.target.linux-arm.mk
@@ -105,9 +105,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -116,6 +114,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_core_common.target.linux-mips.mk b/components/autofill_core_common.target.linux-mips.mk
index 7d17a9a..5028877 100644
--- a/components/autofill_core_common.target.linux-mips.mk
+++ b/components/autofill_core_common.target.linux-mips.mk
@@ -104,9 +104,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -115,6 +113,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -223,9 +222,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -234,6 +231,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_core_common.target.linux-x86.mk b/components/autofill_core_common.target.linux-x86.mk
index 915a2dd..2a9e10d 100644
--- a/components/autofill_core_common.target.linux-x86.mk
+++ b/components/autofill_core_common.target.linux-x86.mk
@@ -105,9 +105,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -116,6 +114,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -235,6 +232,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_core_common.target.linux-x86_64.mk b/components/autofill_core_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..bba6236
--- /dev/null
+++ b/components/autofill_core_common.target.linux-x86_64.mk
@@ -0,0 +1,348 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_autofill_core_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,components_autofill_jni_headers_gyp)/autofill_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/autofill/core/browser/android/auxiliary_profile_loader_android.cc \
+	components/autofill/core/browser/android/auxiliary_profiles_android.cc \
+	components/autofill/core/browser/android/component_jni_registrar.cc \
+	components/autofill/core/browser/android/personal_data_manager_android.cc \
+	components/autofill/core/common/autofill_constants.cc \
+	components/autofill/core/common/autofill_data_validation.cc \
+	components/autofill/core/common/autofill_pref_names.cc \
+	components/autofill/core/common/autofill_switches.cc \
+	components/autofill/core/common/form_data.cc \
+	components/autofill/core/common/form_data_predictions.cc \
+	components/autofill/core/common/form_field_data.cc \
+	components/autofill/core/common/form_field_data_predictions.cc \
+	components/autofill/core/common/password_autofill_util.cc \
+	components/autofill/core/common/password_form.cc \
+	components/autofill/core/common/password_form_fill_data.cc \
+	components/autofill/core/common/password_generation_util.cc \
+	components/autofill/core/common/web_element_descriptor.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/autofill \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/autofill \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_base_ui_base_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_core_common_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_core_common
+autofill_core_common: components_autofill_core_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/autofill_jni_headers.target.darwin-arm.mk b/components/autofill_jni_headers.target.darwin-arm.mk
index 9a2f55b..b1f21c5 100644
--- a/components/autofill_jni_headers.target.darwin-arm.mk
+++ b/components/autofill_jni_headers.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_jni_headers.target.darwin-mips.mk b/components/autofill_jni_headers.target.darwin-mips.mk
index 443b6a6..cb927d7 100644
--- a/components/autofill_jni_headers.target.darwin-mips.mk
+++ b/components/autofill_jni_headers.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_jni_headers.target.darwin-x86.mk b/components/autofill_jni_headers.target.darwin-x86.mk
index 11c90bd..97720ce 100644
--- a/components/autofill_jni_headers.target.darwin-x86.mk
+++ b/components/autofill_jni_headers.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_jni_headers.target.darwin-x86_64.mk b/components/autofill_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4edd3a3
--- /dev/null
+++ b/components/autofill_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,234 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_autofill_jni_headers_gyp
+LOCAL_MODULE_STEM := autofill_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "components_components_gyp_autofill_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/autofill/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['autofill/core/browser/android/java/src/org/chromium/components/browser/autofill/PersonalAutofillPopulator.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/autofill/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: $(LOCAL_PATH)/components/autofill/core/browser/android/java/src/org/chromium/components/browser/autofill/PersonalAutofillPopulator.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/autofill/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file autofill/core/browser/android/java/src/org/chromium/components/browser/autofill/PersonalAutofillPopulator.java --output_dir "$(gyp_shared_intermediate_dir)/autofill/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_autofill_jni_headers_gyp_rule_trigger
+components_autofill_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h \
+	components_autofill_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_jni_headers
+autofill_jni_headers: components_autofill_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/autofill_jni_headers.target.linux-arm.mk b/components/autofill_jni_headers.target.linux-arm.mk
index 9a2f55b..b1f21c5 100644
--- a/components/autofill_jni_headers.target.linux-arm.mk
+++ b/components/autofill_jni_headers.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_jni_headers.target.linux-mips.mk b/components/autofill_jni_headers.target.linux-mips.mk
index 443b6a6..cb927d7 100644
--- a/components/autofill_jni_headers.target.linux-mips.mk
+++ b/components/autofill_jni_headers.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_jni_headers.target.linux-x86.mk b/components/autofill_jni_headers.target.linux-x86.mk
index 11c90bd..97720ce 100644
--- a/components/autofill_jni_headers.target.linux-x86.mk
+++ b/components/autofill_jni_headers.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/autofill_jni_headers.target.linux-x86_64.mk b/components/autofill_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..4edd3a3
--- /dev/null
+++ b/components/autofill_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,234 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_autofill_jni_headers_gyp
+LOCAL_MODULE_STEM := autofill_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "components_components_gyp_autofill_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/autofill/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['autofill/core/browser/android/java/src/org/chromium/components/browser/autofill/PersonalAutofillPopulator.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/autofill/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h: $(LOCAL_PATH)/components/autofill/core/browser/android/java/src/org/chromium/components/browser/autofill/PersonalAutofillPopulator.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/autofill/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file autofill/core/browser/android/java/src/org/chromium/components/browser/autofill/PersonalAutofillPopulator.java --output_dir "$(gyp_shared_intermediate_dir)/autofill/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_autofill_jni_headers_gyp_rule_trigger
+components_autofill_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/autofill/jni/PersonalAutofillPopulator_jni.h \
+	components_autofill_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_jni_headers
+autofill_jni_headers: components_autofill_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/autofill_regexes.target.darwin-x86_64.mk b/components/autofill_regexes.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4ef4652
--- /dev/null
+++ b/components/autofill_regexes.target.darwin-x86_64.mk
@@ -0,0 +1,50 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_autofill_regexes_gyp
+LOCAL_MODULE_STEM := autofill_regexes
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "autofill_regexes":
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: $(LOCAL_PATH)/build/escape_unicode.py $(LOCAL_PATH)/components/autofill/core/browser/autofill_regex_constants.cc.utf8 $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: components_components_gyp_autofill_regexes_target_autofill_regexes ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir); python ../build/escape_unicode.py -o "$(gyp_shared_intermediate_dir)" autofill/core/browser/autofill_regex_constants.cc.utf8
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_regexes_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_regexes
+autofill_regexes: components_autofill_regexes_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/autofill_regexes.target.linux-x86_64.mk b/components/autofill_regexes.target.linux-x86_64.mk
new file mode 100644
index 0000000..4ef4652
--- /dev/null
+++ b/components/autofill_regexes.target.linux-x86_64.mk
@@ -0,0 +1,50 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_autofill_regexes_gyp
+LOCAL_MODULE_STEM := autofill_regexes
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "autofill_regexes":
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc: $(LOCAL_PATH)/build/escape_unicode.py $(LOCAL_PATH)/components/autofill/core/browser/autofill_regex_constants.cc.utf8 $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: components_components_gyp_autofill_regexes_target_autofill_regexes ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir); python ../build/escape_unicode.py -o "$(gyp_shared_intermediate_dir)" autofill/core/browser/autofill_regex_constants.cc.utf8
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/autofill_regex_constants.cc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_autofill_regexes_gyp
+
+# Alias gyp target name.
+.PHONY: autofill_regexes
+autofill_regexes: components_autofill_regexes_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/cloud_devices/description_items.h b/components/cloud_devices/description_items.h
index 9fd2de7..383aa55 100644
--- a/components/cloud_devices/description_items.h
+++ b/components/cloud_devices/description_items.h
@@ -193,6 +193,33 @@
   DISALLOW_COPY_AND_ASSIGN(EmptyCapability);
 };
 
+// Represents an item that is of a specific value type.
+// Ex: "<CAPABILITY_NAME>": {<VALUE>}
+// Option specifies data type for <VALUE>.
+// Traits specifies how <VALUE> is stored in JSON and semantic validation.
+template <class Option, class Traits>
+class ValueCapability {
+ public:
+  ValueCapability();
+  ~ValueCapability();
+
+  bool LoadFrom(const CloudDeviceDescription& description);
+  void SaveTo(CloudDeviceDescription* description) const;
+
+  void Reset() { value_ = Option(); }
+
+  bool IsValid() const;
+
+  const Option& value() const { return value_; }
+
+  void set_value(const Option& value) { value_ = value; }
+
+ private:
+  Option value_;
+
+  DISALLOW_COPY_AND_ASSIGN(ValueCapability);
+};
+
 // Represents CJT items.
 // Ex: "<CAPABILITY_NAME>": {<VALUE>}
 // Option specifies data type for <VALUE>.
diff --git a/components/cloud_devices/description_items_inl.h b/components/cloud_devices/description_items_inl.h
index 5866807..6254890 100644
--- a/components/cloud_devices/description_items_inl.h
+++ b/components/cloud_devices/description_items_inl.h
@@ -174,6 +174,41 @@
 }
 
 template <class Option, class Traits>
+ValueCapability<Option, Traits>::ValueCapability() {
+  Reset();
+}
+
+template <class Option, class Traits>
+ValueCapability<Option, Traits>::~ValueCapability() {}
+
+template <class Option, class Traits>
+bool ValueCapability<Option, Traits>::IsValid() const {
+  return Traits::IsValid(value());
+}
+
+template <class Option, class Traits>
+bool ValueCapability<Option, Traits>::LoadFrom(
+    const CloudDeviceDescription& description) {
+  Reset();
+  const base::DictionaryValue* option_value =
+      description.GetItem(Traits::GetCapabilityPath());
+  if (!option_value)
+    return false;
+  Option option;
+  if (!Traits::Load(*option_value, &option))
+    return false;
+  set_value(option);
+  return IsValid();
+}
+
+template <class Option, class Traits>
+void ValueCapability<Option, Traits>::SaveTo(
+    CloudDeviceDescription* description) const {
+  DCHECK(IsValid());
+  Traits::Save(value(), description->CreateItem(Traits::GetCapabilityPath()));
+}
+
+template <class Option, class Traits>
 TicketItem<Option, Traits>::TicketItem() {
   Reset();
 }
diff --git a/components/cloud_devices/printer_description.cc b/components/cloud_devices/printer_description.cc
index 1d42962..8efb576 100644
--- a/components/cloud_devices/printer_description.cc
+++ b/components/cloud_devices/printer_description.cc
@@ -43,6 +43,7 @@
 extern const char kOptionPageOrientation[] = "page_orientation";
 extern const char kOptionPageRange[] = "page_range";
 extern const char kOptionReverse[] = "reverse_order";
+extern const char kOptionPwgRasterConfig[] = "pwg_raster_config";
 
 const char kMargineBottom[] = "bottom_microns";
 const char kMargineLeft[] = "left_microns";
@@ -60,6 +61,10 @@
 const char kPageRangeEnd[] = "end";
 const char kPageRangeStart[] = "start";
 
+const char kPwgRasterDocumentSheetBack[] = "document_sheet_back";
+const char kPwgRasterReverseOrderStreaming[] = "reverse_order_streaming";
+const char kPwgRasterRotateAllPages[] = "rotate_all_pages";
+
 const char kTypeColorColor[] = "STANDARD_COLOR";
 const char kTypeColorMonochrome[] = "STANDARD_MONOCHROME";
 const char kTypeColorCustomColor[] = "CUSTOM_COLOR";
@@ -84,6 +89,11 @@
 const char kTypeOrientationLandscape[] = "LANDSCAPE";
 const char kTypeOrientationPortrait[] = "PORTRAIT";
 
+const char kTypeDocumentSheetBackNormal[] = "NORMAL";
+const char kTypeDocumentSheetBackRotated[] = "ROTATED";
+const char kTypeDocumentSheetBackManualTumble[] = "MANUAL_TUMBLE";
+const char kTypeDocumentSheetBackFlipped[] = "FLIPPED";
+
 const struct ColorNames {
   ColorType id;
   const char* const json_name;
@@ -133,6 +143,15 @@
   { FILL_PAGE, kTypeFitToPageFillPage },
 };
 
+const struct DocumentSheetBackNames {
+  DocumentSheetBack id;
+  const char* const json_name;
+} kDocumentSheetBackNames[] = {
+      {NORMAL, kTypeDocumentSheetBackNormal},
+      {ROTATED, kTypeDocumentSheetBackRotated},
+      {MANUAL_TUMBLE, kTypeDocumentSheetBackManualTumble},
+      {FLIPPED, kTypeDocumentSheetBackFlipped}};
+
 const int32 kInchToUm = 25400;
 const int32 kMmToUm = 1000;
 const int32 kSizeTrasholdUm = 1000;
@@ -350,6 +369,11 @@
 
 }  // namespace
 
+PwgRasterConfig::PwgRasterConfig()
+    : document_sheet_back(ROTATED),
+      reverse_order_streaming(false),
+      rotate_all_pages(false) {}
+
 Color::Color() : type(AUTO_COLOR) {}
 
 Color::Color(ColorType type) : type(type) {}
@@ -506,6 +530,40 @@
   }
 };
 
+class PwgRasterConfigTraits : public NoValueValidation,
+                              public ItemsTraits<kOptionPwgRasterConfig> {
+ public:
+  static bool Load(const base::DictionaryValue& dict, PwgRasterConfig* option) {
+    std::string document_sheet_back;
+    PwgRasterConfig option_out;
+    if (dict.GetString(kPwgRasterDocumentSheetBack, &document_sheet_back)) {
+      if (!TypeFromString(kDocumentSheetBackNames,
+                          document_sheet_back,
+                          &option_out.document_sheet_back)) {
+        return false;
+      }
+    }
+
+    dict.GetBoolean(kPwgRasterReverseOrderStreaming,
+                    &option_out.reverse_order_streaming);
+    dict.GetBoolean(kPwgRasterRotateAllPages, &option_out.rotate_all_pages);
+    *option = option_out;
+    return true;
+  }
+
+  static void Save(const PwgRasterConfig& option, base::DictionaryValue* dict) {
+    dict->SetString(
+        kPwgRasterDocumentSheetBack,
+        TypeToString(kDocumentSheetBackNames, option.document_sheet_back));
+    if (option.reverse_order_streaming)
+      dict->SetBoolean(kPwgRasterReverseOrderStreaming,
+                       option.reverse_order_streaming);
+
+    if (option.rotate_all_pages)
+      dict->SetBoolean(kPwgRasterRotateAllPages, option.rotate_all_pages);
+  }
+};
+
 class ColorTraits : public ItemsTraits<kOptionColor> {
  public:
   static bool IsValid(const Color& option) {
@@ -743,6 +801,7 @@
 using namespace printer;
 
 template class ListCapability<ContentType, ContentTypeTraits>;
+template class ValueCapability<PwgRasterConfig, PwgRasterConfigTraits>;
 template class SelectionCapability<Color, ColorTraits>;
 template class SelectionCapability<DuplexType, DuplexTraits>;
 template class SelectionCapability<OrientationType, OrientationTraits>;
@@ -755,6 +814,7 @@
 template class BooleanCapability<class CollateTraits>;
 template class BooleanCapability<class ReverseTraits>;
 
+template class TicketItem<PwgRasterConfig, PwgRasterConfigTraits>;
 template class TicketItem<Color, ColorTraits>;
 template class TicketItem<DuplexType, DuplexTraits>;
 template class TicketItem<OrientationType, OrientationTraits>;
diff --git a/components/cloud_devices/printer_description.h b/components/cloud_devices/printer_description.h
index 2251355..cdfd20e 100644
--- a/components/cloud_devices/printer_description.h
+++ b/components/cloud_devices/printer_description.h
@@ -19,6 +19,21 @@
 
 typedef std::string ContentType;
 
+enum DocumentSheetBack {
+  NORMAL,
+  ROTATED,
+  MANUAL_TUMBLE,
+  FLIPPED
+};
+
+struct PwgRasterConfig {
+  PwgRasterConfig();
+
+  DocumentSheetBack document_sheet_back;
+  bool reverse_order_streaming;
+  bool rotate_all_pages;
+};
+
 enum ColorType {
   STANDARD_COLOR,
   STANDARD_MONOCHROME,
@@ -320,6 +335,7 @@
 typedef std::vector<Interval> PageRange;
 
 class ContentTypeTraits;
+class PwgRasterConfigTraits;
 class ColorTraits;
 class DuplexTraits;
 class OrientationTraits;
@@ -330,9 +346,10 @@
 class CopiesTraits;
 class PageRangeTraits;
 class CollateTraits;
-class ReverseTraits;
 
 typedef ListCapability<ContentType, ContentTypeTraits> ContentTypesCapability;
+typedef ValueCapability<PwgRasterConfig, PwgRasterConfigTraits>
+    PwgRasterConfigCapability;
 typedef SelectionCapability<Color, ColorTraits> ColorCapability;
 typedef SelectionCapability<DuplexType, DuplexTraits> DuplexCapability;
 typedef SelectionCapability<OrientationType,
@@ -346,6 +363,8 @@
 typedef BooleanCapability<class CollateTraits> CollateCapability;
 typedef BooleanCapability<class ReverseTraits> ReverseCapability;
 
+typedef TicketItem<PwgRasterConfig, PwgRasterConfigTraits>
+    PwgRasterConfigTicketItem;
 typedef TicketItem<Color, ColorTraits> ColorTicketItem;
 typedef TicketItem<DuplexType, DuplexTraits> DuplexTicketItem;
 typedef TicketItem<OrientationType, OrientationTraits> OrientationTicketItem;
diff --git a/components/cloud_devices/printer_description_unittest.cc b/components/cloud_devices/printer_description_unittest.cc
index a7f3abc..41923ea 100644
--- a/components/cloud_devices/printer_description_unittest.cc
+++ b/components/cloud_devices/printer_description_unittest.cc
@@ -35,6 +35,10 @@
 "    }, {"
 "      'content_type': 'image/jpeg'"
 "    } ],"
+"    'pwg_raster_config' : {"
+"      'document_sheet_back' : 'MANUAL_TUMBLE',"
+"      'reverse_order_streaming': true"
+"    },"
 "    'color': {"
 "      'option': [ {"
 "        'is_default': true,"
@@ -193,6 +197,10 @@
 "{"
 "  'version': '1.0',"
 "  'print': {"
+"    'pwg_raster_config' : {"
+"      'document_sheet_back' : 'MANUAL_TUMBLE',"
+"      'reverse_order_streaming': true"
+"    },"
 "    'color': {"
 "      'type': 'STANDARD_MONOCHROME'"
 "    },"
@@ -258,6 +266,7 @@
   EXPECT_EQ(NormalizeJson(kDefaultCdd), NormalizeJson(description.ToString()));
 
   ContentTypesCapability content_types;
+  PwgRasterConfigCapability pwg_raster;
   ColorCapability color;
   DuplexCapability duplex;
   OrientationCapability orientation;
@@ -271,6 +280,7 @@
   ReverseCapability reverse;
 
   EXPECT_FALSE(content_types.LoadFrom(description));
+  EXPECT_FALSE(pwg_raster.LoadFrom(description));
   EXPECT_FALSE(color.LoadFrom(description));
   EXPECT_FALSE(duplex.LoadFrom(description));
   EXPECT_FALSE(orientation.LoadFrom(description));
@@ -302,6 +312,7 @@
   CloudDeviceDescription description;
 
   ContentTypesCapability content_types;
+  PwgRasterConfigCapability pwg_raster_config;
   ColorCapability color;
   DuplexCapability duplex;
   OrientationCapability orientation;
@@ -317,6 +328,12 @@
   content_types.AddOption("image/pwg-raster");
   content_types.AddOption("image/jpeg");
 
+  PwgRasterConfig custom_raster;
+  custom_raster.document_sheet_back = MANUAL_TUMBLE;
+  custom_raster.reverse_order_streaming = true;
+  custom_raster.rotate_all_pages = false;
+  pwg_raster_config.set_value(custom_raster);
+
   color.AddDefaultOption(Color(STANDARD_COLOR), true);
   color.AddOption(Color(STANDARD_MONOCHROME));
   Color custom(CUSTOM_MONOCHROME);
@@ -365,6 +382,7 @@
   media.SaveTo(&description);
   collate.SaveTo(&description);
   reverse.SaveTo(&description);
+  pwg_raster_config.SaveTo(&description);
 
   EXPECT_EQ(NormalizeJson(kCdd), NormalizeJson(description.ToString()));
 }
@@ -374,6 +392,7 @@
   ASSERT_TRUE(description.InitFromString(NormalizeJson(kCdd)));
 
   ContentTypesCapability content_types;
+  PwgRasterConfigCapability pwg_raster_config;
   ColorCapability color;
   DuplexCapability duplex;
   OrientationCapability orientation;
@@ -399,10 +418,15 @@
   EXPECT_TRUE(collate.LoadFrom(description));
   EXPECT_TRUE(reverse.LoadFrom(description));
   EXPECT_TRUE(media.LoadFrom(description));
+  EXPECT_TRUE(pwg_raster_config.LoadFrom(description));
 
   EXPECT_TRUE(content_types.Contains("image/pwg-raster"));
   EXPECT_TRUE(content_types.Contains("image/jpeg"));
 
+  EXPECT_EQ(MANUAL_TUMBLE, pwg_raster_config.value().document_sheet_back);
+  EXPECT_TRUE(pwg_raster_config.value().reverse_order_streaming);
+  EXPECT_FALSE(pwg_raster_config.value().rotate_all_pages);
+
   EXPECT_TRUE(color.Contains(Color(STANDARD_COLOR)));
   EXPECT_TRUE(color.Contains(Color(STANDARD_MONOCHROME)));
   Color custom(CUSTOM_MONOCHROME);
@@ -453,6 +477,7 @@
   CloudDeviceDescription description;
   EXPECT_EQ(NormalizeJson(kDefaultCjt), NormalizeJson(description.ToString()));
 
+  PwgRasterConfigTicketItem pwg_raster_config;
   ColorTicketItem color;
   DuplexTicketItem duplex;
   OrientationTicketItem orientation;
@@ -465,6 +490,7 @@
   CollateTicketItem collate;
   ReverseTicketItem reverse;
 
+  EXPECT_FALSE(pwg_raster_config.LoadFrom(description));
   EXPECT_FALSE(color.LoadFrom(description));
   EXPECT_FALSE(duplex.LoadFrom(description));
   EXPECT_FALSE(orientation.LoadFrom(description));
@@ -487,6 +513,7 @@
 TEST(PrinterDescriptionTest, CjtSetAll) {
   CloudDeviceDescription description;
 
+  PwgRasterConfigTicketItem pwg_raster_config;
   ColorTicketItem color;
   DuplexTicketItem duplex;
   OrientationTicketItem orientation;
@@ -499,6 +526,11 @@
   CollateTicketItem collate;
   ReverseTicketItem reverse;
 
+  PwgRasterConfig custom_raster;
+  custom_raster.document_sheet_back = MANUAL_TUMBLE;
+  custom_raster.reverse_order_streaming = true;
+  custom_raster.rotate_all_pages = false;
+  pwg_raster_config.set_value(custom_raster);
   color.set_value(Color(STANDARD_MONOCHROME));
   duplex.set_value(NO_DUPLEX);
   orientation.set_value(LANDSCAPE);
@@ -514,6 +546,7 @@
   collate.set_value(false);
   reverse.set_value(true);
 
+  pwg_raster_config.SaveTo(&description);
   color.SaveTo(&description);
   duplex.SaveTo(&description);
   orientation.SaveTo(&description);
@@ -544,7 +577,9 @@
   PageRangeTicketItem page_range;
   CollateTicketItem collate;
   ReverseTicketItem reverse;
+  PwgRasterConfigTicketItem pwg_raster_config;
 
+  EXPECT_TRUE(pwg_raster_config.LoadFrom(description));
   EXPECT_TRUE(color.LoadFrom(description));
   EXPECT_TRUE(duplex.LoadFrom(description));
   EXPECT_TRUE(orientation.LoadFrom(description));
@@ -558,6 +593,9 @@
   EXPECT_TRUE(reverse.LoadFrom(description));
   EXPECT_TRUE(media.LoadFrom(description));
 
+  EXPECT_EQ(MANUAL_TUMBLE, pwg_raster_config.value().document_sheet_back);
+  EXPECT_TRUE(pwg_raster_config.value().reverse_order_streaming);
+  EXPECT_FALSE(pwg_raster_config.value().rotate_all_pages);
   EXPECT_EQ(color.value(), Color(STANDARD_MONOCHROME));
   EXPECT_EQ(duplex.value(), NO_DUPLEX);
   EXPECT_EQ(orientation.value(), LANDSCAPE);
diff --git a/components/components_resources.target.darwin-arm.mk b/components/components_resources.target.darwin-arm.mk
index 386b3bb..57f9ed8 100644
--- a/components/components_resources.target.darwin-arm.mk
+++ b/components/components_resources.target.darwin-arm.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/third_party/readability/css/readability.css $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/components/components_resources.target.darwin-mips.mk b/components/components_resources.target.darwin-mips.mk
index 386b3bb..57f9ed8 100644
--- a/components/components_resources.target.darwin-mips.mk
+++ b/components/components_resources.target.darwin-mips.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/third_party/readability/css/readability.css $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/components/components_resources.target.darwin-x86.mk b/components/components_resources.target.darwin-x86.mk
index 28fe8bf..57f9ed8 100644
--- a/components/components_resources.target.darwin-x86.mk
+++ b/components/components_resources.target.darwin-x86.mk
@@ -18,9 +18,9 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/third_party/readability/css/readability.css $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/components/component_resources.pak: $(gyp_shared_intermediate_dir)/components/grit/component_resources.h ;
 
@@ -31,7 +31,7 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/resources/components_scaled_resources.grd $(LOCAL_PATH)/components/resources/autofill_scaled_resources.grdp $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/cc-generic.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/diners.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/jcb.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/visa.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/visa.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_scaled_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_scaled_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_scaled_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/components/component_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
 $(gyp_shared_intermediate_dir)/components/component_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
diff --git a/components/components_resources.target.darwin-x86_64.mk b/components/components_resources.target.darwin-x86_64.mk
new file mode 100644
index 0000000..57f9ed8
--- /dev/null
+++ b/components/components_resources.target.darwin-x86_64.mk
@@ -0,0 +1,67 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_components_resources_gyp
+LOCAL_MODULE_STEM := components_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_components_resources":
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/components/component_resources.pak: $(gyp_shared_intermediate_dir)/components/grit/component_resources.h ;
+
+### Rules for action "generate_components_scaled_resources":
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/resources/components_scaled_resources.grd $(LOCAL_PATH)/components/resources/autofill_scaled_resources.grdp $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/cc-generic.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/diners.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/jcb.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/visa.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/visa.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from resources/components_scaled_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_scaled_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/components/component_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
+$(gyp_shared_intermediate_dir)/components/component_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/components/grit/component_resources.h \
+	$(gyp_shared_intermediate_dir)/components/component_resources.pak \
+	$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h \
+	$(gyp_shared_intermediate_dir)/components/component_resources_100_percent.pak \
+	$(gyp_shared_intermediate_dir)/components/component_resources_200_percent.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_components_resources_gyp
+
+# Alias gyp target name.
+.PHONY: components_resources
+components_resources: components_components_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/components_resources.target.linux-arm.mk b/components/components_resources.target.linux-arm.mk
index 386b3bb..57f9ed8 100644
--- a/components/components_resources.target.linux-arm.mk
+++ b/components/components_resources.target.linux-arm.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/third_party/readability/css/readability.css $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/components/components_resources.target.linux-mips.mk b/components/components_resources.target.linux-mips.mk
index 386b3bb..57f9ed8 100644
--- a/components/components_resources.target.linux-mips.mk
+++ b/components/components_resources.target.linux-mips.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/third_party/readability/css/readability.css $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/components/components_resources.target.linux-x86.mk b/components/components_resources.target.linux-x86.mk
index 28fe8bf..57f9ed8 100644
--- a/components/components_resources.target.linux-x86.mk
+++ b/components/components_resources.target.linux-x86.mk
@@ -18,9 +18,9 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/third_party/readability/css/readability.css $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/components/component_resources.pak: $(gyp_shared_intermediate_dir)/components/grit/component_resources.h ;
 
@@ -31,7 +31,7 @@
 $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/resources/components_scaled_resources.grd $(LOCAL_PATH)/components/resources/autofill_scaled_resources.grdp $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/cc-generic.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/diners.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/jcb.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/visa.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/visa.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from resources/components_scaled_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_scaled_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_scaled_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/components/component_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
 $(gyp_shared_intermediate_dir)/components/component_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
diff --git a/components/components_resources.target.linux-x86_64.mk b/components/components_resources.target.linux-x86_64.mk
new file mode 100644
index 0000000..57f9ed8
--- /dev/null
+++ b/components/components_resources.target.linux-x86_64.mk
@@ -0,0 +1,67 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_components_resources_gyp
+LOCAL_MODULE_STEM := components_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_components_resources":
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/components/grit/component_resources.h: $(LOCAL_PATH)/third_party/dom_distiller_js/js/domdistiller.js $(LOCAL_PATH)/components/resources/components_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/dom_distiller/content/resources/dom_distiller_viewer.html $(LOCAL_PATH)/components/dom_distiller/core/css/distilledpage.css $(LOCAL_PATH)/components/dom_distiller/core/javascript/domdistiller.js $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.css $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.html $(LOCAL_PATH)/components/dom_distiller/webui/resources/about_dom_distiller.js $(LOCAL_PATH)/components/resources/dom_distiller_resources.grdp $(LOCAL_PATH)/components/resources/translate_resources.grdp $(LOCAL_PATH)/components/translate/core/browser/resources/translate.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from resources/components_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/components/component_resources.pak: $(gyp_shared_intermediate_dir)/components/grit/component_resources.h ;
+
+### Rules for action "generate_components_scaled_resources":
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/resources/components_scaled_resources.grd $(LOCAL_PATH)/components/resources/autofill_scaled_resources.grdp $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/cc-generic.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/diners.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/jcb.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_100_percent/common/autofill/visa.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/amex.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/discover.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/mastercard.png $(LOCAL_PATH)/components/resources/default_200_percent/common/autofill/visa.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from resources/components_scaled_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/grit $(gyp_shared_intermediate_dir)/components; python ../tools/grit/grit.py -i resources/components_scaled_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/components/component_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
+$(gyp_shared_intermediate_dir)/components/component_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/components/grit/component_resources.h \
+	$(gyp_shared_intermediate_dir)/components/component_resources.pak \
+	$(gyp_shared_intermediate_dir)/components/grit/component_scaled_resources.h \
+	$(gyp_shared_intermediate_dir)/components/component_resources_100_percent.pak \
+	$(gyp_shared_intermediate_dir)/components/component_resources_200_percent.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_components_resources_gyp
+
+# Alias gyp target name.
+.PHONY: components_resources
+components_resources: components_components_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/components_strings.target.darwin-x86.mk b/components/components_strings.target.darwin-x86.mk
index 8919c7e..7dbcbbc 100644
--- a/components/components_strings.target.darwin-x86.mk
+++ b/components/components_strings.target.darwin-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/components_strings.grd $(LOCAL_PATH)/components/autofill_strings.grdp $(LOCAL_PATH)/components/dom_distiller_strings.grdp $(LOCAL_PATH)/components/policy_strings.grdp $(LOCAL_PATH)/components/strings/component_strings_am.xtb $(LOCAL_PATH)/components/strings/component_strings_ar.xtb $(LOCAL_PATH)/components/strings/component_strings_bg.xtb $(LOCAL_PATH)/components/strings/component_strings_bn.xtb $(LOCAL_PATH)/components/strings/component_strings_ca.xtb $(LOCAL_PATH)/components/strings/component_strings_cs.xtb $(LOCAL_PATH)/components/strings/component_strings_da.xtb $(LOCAL_PATH)/components/strings/component_strings_de.xtb $(LOCAL_PATH)/components/strings/component_strings_el.xtb $(LOCAL_PATH)/components/strings/component_strings_en-GB.xtb $(LOCAL_PATH)/components/strings/component_strings_es-419.xtb $(LOCAL_PATH)/components/strings/component_strings_es.xtb $(LOCAL_PATH)/components/strings/component_strings_et.xtb $(LOCAL_PATH)/components/strings/component_strings_fa.xtb $(LOCAL_PATH)/components/strings/component_strings_fi.xtb $(LOCAL_PATH)/components/strings/component_strings_fil.xtb $(LOCAL_PATH)/components/strings/component_strings_fr.xtb $(LOCAL_PATH)/components/strings/component_strings_gu.xtb $(LOCAL_PATH)/components/strings/component_strings_hi.xtb $(LOCAL_PATH)/components/strings/component_strings_hr.xtb $(LOCAL_PATH)/components/strings/component_strings_hu.xtb $(LOCAL_PATH)/components/strings/component_strings_id.xtb $(LOCAL_PATH)/components/strings/component_strings_it.xtb $(LOCAL_PATH)/components/strings/component_strings_iw.xtb $(LOCAL_PATH)/components/strings/component_strings_ja.xtb $(LOCAL_PATH)/components/strings/component_strings_kn.xtb $(LOCAL_PATH)/components/strings/component_strings_ko.xtb $(LOCAL_PATH)/components/strings/component_strings_lt.xtb $(LOCAL_PATH)/components/strings/component_strings_lv.xtb $(LOCAL_PATH)/components/strings/component_strings_ml.xtb $(LOCAL_PATH)/components/strings/component_strings_mr.xtb $(LOCAL_PATH)/components/strings/component_strings_ms.xtb $(LOCAL_PATH)/components/strings/component_strings_nl.xtb $(LOCAL_PATH)/components/strings/component_strings_no.xtb $(LOCAL_PATH)/components/strings/component_strings_pl.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-BR.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-PT.xtb $(LOCAL_PATH)/components/strings/component_strings_ro.xtb $(LOCAL_PATH)/components/strings/component_strings_ru.xtb $(LOCAL_PATH)/components/strings/component_strings_sk.xtb $(LOCAL_PATH)/components/strings/component_strings_sl.xtb $(LOCAL_PATH)/components/strings/component_strings_sr.xtb $(LOCAL_PATH)/components/strings/component_strings_sv.xtb $(LOCAL_PATH)/components/strings/component_strings_sw.xtb $(LOCAL_PATH)/components/strings/component_strings_ta.xtb $(LOCAL_PATH)/components/strings/component_strings_te.xtb $(LOCAL_PATH)/components/strings/component_strings_th.xtb $(LOCAL_PATH)/components/strings/component_strings_tr.xtb $(LOCAL_PATH)/components/strings/component_strings_uk.xtb $(LOCAL_PATH)/components/strings/component_strings_vi.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-CN.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from components_strings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/strings/grit $(gyp_shared_intermediate_dir)/components/strings; python ../tools/grit/grit.py -i components_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components/strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/strings/grit $(gyp_shared_intermediate_dir)/components/strings; python ../tools/grit/grit.py -i components_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components/strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/components/strings/component_strings_am.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
 $(gyp_shared_intermediate_dir)/components/strings/component_strings_ar.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
diff --git a/components/components_strings.target.darwin-x86_64.mk b/components/components_strings.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7dbcbbc
--- /dev/null
+++ b/components/components_strings.target.darwin-x86_64.mk
@@ -0,0 +1,158 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_components_strings_gyp
+LOCAL_MODULE_STEM := components_strings
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_components_strings":
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/components_strings.grd $(LOCAL_PATH)/components/autofill_strings.grdp $(LOCAL_PATH)/components/dom_distiller_strings.grdp $(LOCAL_PATH)/components/policy_strings.grdp $(LOCAL_PATH)/components/strings/component_strings_am.xtb $(LOCAL_PATH)/components/strings/component_strings_ar.xtb $(LOCAL_PATH)/components/strings/component_strings_bg.xtb $(LOCAL_PATH)/components/strings/component_strings_bn.xtb $(LOCAL_PATH)/components/strings/component_strings_ca.xtb $(LOCAL_PATH)/components/strings/component_strings_cs.xtb $(LOCAL_PATH)/components/strings/component_strings_da.xtb $(LOCAL_PATH)/components/strings/component_strings_de.xtb $(LOCAL_PATH)/components/strings/component_strings_el.xtb $(LOCAL_PATH)/components/strings/component_strings_en-GB.xtb $(LOCAL_PATH)/components/strings/component_strings_es-419.xtb $(LOCAL_PATH)/components/strings/component_strings_es.xtb $(LOCAL_PATH)/components/strings/component_strings_et.xtb $(LOCAL_PATH)/components/strings/component_strings_fa.xtb $(LOCAL_PATH)/components/strings/component_strings_fi.xtb $(LOCAL_PATH)/components/strings/component_strings_fil.xtb $(LOCAL_PATH)/components/strings/component_strings_fr.xtb $(LOCAL_PATH)/components/strings/component_strings_gu.xtb $(LOCAL_PATH)/components/strings/component_strings_hi.xtb $(LOCAL_PATH)/components/strings/component_strings_hr.xtb $(LOCAL_PATH)/components/strings/component_strings_hu.xtb $(LOCAL_PATH)/components/strings/component_strings_id.xtb $(LOCAL_PATH)/components/strings/component_strings_it.xtb $(LOCAL_PATH)/components/strings/component_strings_iw.xtb $(LOCAL_PATH)/components/strings/component_strings_ja.xtb $(LOCAL_PATH)/components/strings/component_strings_kn.xtb $(LOCAL_PATH)/components/strings/component_strings_ko.xtb $(LOCAL_PATH)/components/strings/component_strings_lt.xtb $(LOCAL_PATH)/components/strings/component_strings_lv.xtb $(LOCAL_PATH)/components/strings/component_strings_ml.xtb $(LOCAL_PATH)/components/strings/component_strings_mr.xtb $(LOCAL_PATH)/components/strings/component_strings_ms.xtb $(LOCAL_PATH)/components/strings/component_strings_nl.xtb $(LOCAL_PATH)/components/strings/component_strings_no.xtb $(LOCAL_PATH)/components/strings/component_strings_pl.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-BR.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-PT.xtb $(LOCAL_PATH)/components/strings/component_strings_ro.xtb $(LOCAL_PATH)/components/strings/component_strings_ru.xtb $(LOCAL_PATH)/components/strings/component_strings_sk.xtb $(LOCAL_PATH)/components/strings/component_strings_sl.xtb $(LOCAL_PATH)/components/strings/component_strings_sr.xtb $(LOCAL_PATH)/components/strings/component_strings_sv.xtb $(LOCAL_PATH)/components/strings/component_strings_sw.xtb $(LOCAL_PATH)/components/strings/component_strings_ta.xtb $(LOCAL_PATH)/components/strings/component_strings_te.xtb $(LOCAL_PATH)/components/strings/component_strings_th.xtb $(LOCAL_PATH)/components/strings/component_strings_tr.xtb $(LOCAL_PATH)/components/strings/component_strings_uk.xtb $(LOCAL_PATH)/components/strings/component_strings_vi.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-CN.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from components_strings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/strings/grit $(gyp_shared_intermediate_dir)/components/strings; python ../tools/grit/grit.py -i components_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components/strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_am.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ar.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_bg.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_bn.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ca.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_cs.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_da.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_de.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_el.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-GB.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-US.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_es.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_es-419.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_et.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fa.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fil.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_gu.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_he.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_hi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_hr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_hu.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_id.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_it.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ja.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_kn.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ko.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_lt.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_lv.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ml.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_mr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ms.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_nl.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_nb.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_pl.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-BR.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-PT.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ro.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ru.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sk.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sl.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sv.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sw.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ta.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_te.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_th.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_tr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_uk.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_vi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-CN.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-TW.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_am.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ar.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_bg.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_bn.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ca.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_cs.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_da.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_de.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_el.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_es.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_et.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fa.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fil.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_gu.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_he.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_hi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_hr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_hu.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_id.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_it.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ja.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_kn.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ko.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_lt.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_lv.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ml.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_mr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ms.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_nl.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_nb.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_pl.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ro.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ru.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sk.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sl.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sv.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sw.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ta.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_te.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_th.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_tr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_uk.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_vi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-TW.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_components_strings_gyp
+
+# Alias gyp target name.
+.PHONY: components_strings
+components_strings: components_components_strings_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/components_strings.target.linux-x86.mk b/components/components_strings.target.linux-x86.mk
index 8919c7e..7dbcbbc 100644
--- a/components/components_strings.target.linux-x86.mk
+++ b/components/components_strings.target.linux-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/components_strings.grd $(LOCAL_PATH)/components/autofill_strings.grdp $(LOCAL_PATH)/components/dom_distiller_strings.grdp $(LOCAL_PATH)/components/policy_strings.grdp $(LOCAL_PATH)/components/strings/component_strings_am.xtb $(LOCAL_PATH)/components/strings/component_strings_ar.xtb $(LOCAL_PATH)/components/strings/component_strings_bg.xtb $(LOCAL_PATH)/components/strings/component_strings_bn.xtb $(LOCAL_PATH)/components/strings/component_strings_ca.xtb $(LOCAL_PATH)/components/strings/component_strings_cs.xtb $(LOCAL_PATH)/components/strings/component_strings_da.xtb $(LOCAL_PATH)/components/strings/component_strings_de.xtb $(LOCAL_PATH)/components/strings/component_strings_el.xtb $(LOCAL_PATH)/components/strings/component_strings_en-GB.xtb $(LOCAL_PATH)/components/strings/component_strings_es-419.xtb $(LOCAL_PATH)/components/strings/component_strings_es.xtb $(LOCAL_PATH)/components/strings/component_strings_et.xtb $(LOCAL_PATH)/components/strings/component_strings_fa.xtb $(LOCAL_PATH)/components/strings/component_strings_fi.xtb $(LOCAL_PATH)/components/strings/component_strings_fil.xtb $(LOCAL_PATH)/components/strings/component_strings_fr.xtb $(LOCAL_PATH)/components/strings/component_strings_gu.xtb $(LOCAL_PATH)/components/strings/component_strings_hi.xtb $(LOCAL_PATH)/components/strings/component_strings_hr.xtb $(LOCAL_PATH)/components/strings/component_strings_hu.xtb $(LOCAL_PATH)/components/strings/component_strings_id.xtb $(LOCAL_PATH)/components/strings/component_strings_it.xtb $(LOCAL_PATH)/components/strings/component_strings_iw.xtb $(LOCAL_PATH)/components/strings/component_strings_ja.xtb $(LOCAL_PATH)/components/strings/component_strings_kn.xtb $(LOCAL_PATH)/components/strings/component_strings_ko.xtb $(LOCAL_PATH)/components/strings/component_strings_lt.xtb $(LOCAL_PATH)/components/strings/component_strings_lv.xtb $(LOCAL_PATH)/components/strings/component_strings_ml.xtb $(LOCAL_PATH)/components/strings/component_strings_mr.xtb $(LOCAL_PATH)/components/strings/component_strings_ms.xtb $(LOCAL_PATH)/components/strings/component_strings_nl.xtb $(LOCAL_PATH)/components/strings/component_strings_no.xtb $(LOCAL_PATH)/components/strings/component_strings_pl.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-BR.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-PT.xtb $(LOCAL_PATH)/components/strings/component_strings_ro.xtb $(LOCAL_PATH)/components/strings/component_strings_ru.xtb $(LOCAL_PATH)/components/strings/component_strings_sk.xtb $(LOCAL_PATH)/components/strings/component_strings_sl.xtb $(LOCAL_PATH)/components/strings/component_strings_sr.xtb $(LOCAL_PATH)/components/strings/component_strings_sv.xtb $(LOCAL_PATH)/components/strings/component_strings_sw.xtb $(LOCAL_PATH)/components/strings/component_strings_ta.xtb $(LOCAL_PATH)/components/strings/component_strings_te.xtb $(LOCAL_PATH)/components/strings/component_strings_th.xtb $(LOCAL_PATH)/components/strings/component_strings_tr.xtb $(LOCAL_PATH)/components/strings/component_strings_uk.xtb $(LOCAL_PATH)/components/strings/component_strings_vi.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-CN.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from components_strings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/strings/grit $(gyp_shared_intermediate_dir)/components/strings; python ../tools/grit/grit.py -i components_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components/strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/strings/grit $(gyp_shared_intermediate_dir)/components/strings; python ../tools/grit/grit.py -i components_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components/strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/components/strings/component_strings_am.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
 $(gyp_shared_intermediate_dir)/components/strings/component_strings_ar.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
diff --git a/components/components_strings.target.linux-x86_64.mk b/components/components_strings.target.linux-x86_64.mk
new file mode 100644
index 0000000..7dbcbbc
--- /dev/null
+++ b/components/components_strings.target.linux-x86_64.mk
@@ -0,0 +1,158 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_components_strings_gyp
+LOCAL_MODULE_STEM := components_strings
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_components_strings":
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/components/components_strings.grd $(LOCAL_PATH)/components/autofill_strings.grdp $(LOCAL_PATH)/components/dom_distiller_strings.grdp $(LOCAL_PATH)/components/policy_strings.grdp $(LOCAL_PATH)/components/strings/component_strings_am.xtb $(LOCAL_PATH)/components/strings/component_strings_ar.xtb $(LOCAL_PATH)/components/strings/component_strings_bg.xtb $(LOCAL_PATH)/components/strings/component_strings_bn.xtb $(LOCAL_PATH)/components/strings/component_strings_ca.xtb $(LOCAL_PATH)/components/strings/component_strings_cs.xtb $(LOCAL_PATH)/components/strings/component_strings_da.xtb $(LOCAL_PATH)/components/strings/component_strings_de.xtb $(LOCAL_PATH)/components/strings/component_strings_el.xtb $(LOCAL_PATH)/components/strings/component_strings_en-GB.xtb $(LOCAL_PATH)/components/strings/component_strings_es-419.xtb $(LOCAL_PATH)/components/strings/component_strings_es.xtb $(LOCAL_PATH)/components/strings/component_strings_et.xtb $(LOCAL_PATH)/components/strings/component_strings_fa.xtb $(LOCAL_PATH)/components/strings/component_strings_fi.xtb $(LOCAL_PATH)/components/strings/component_strings_fil.xtb $(LOCAL_PATH)/components/strings/component_strings_fr.xtb $(LOCAL_PATH)/components/strings/component_strings_gu.xtb $(LOCAL_PATH)/components/strings/component_strings_hi.xtb $(LOCAL_PATH)/components/strings/component_strings_hr.xtb $(LOCAL_PATH)/components/strings/component_strings_hu.xtb $(LOCAL_PATH)/components/strings/component_strings_id.xtb $(LOCAL_PATH)/components/strings/component_strings_it.xtb $(LOCAL_PATH)/components/strings/component_strings_iw.xtb $(LOCAL_PATH)/components/strings/component_strings_ja.xtb $(LOCAL_PATH)/components/strings/component_strings_kn.xtb $(LOCAL_PATH)/components/strings/component_strings_ko.xtb $(LOCAL_PATH)/components/strings/component_strings_lt.xtb $(LOCAL_PATH)/components/strings/component_strings_lv.xtb $(LOCAL_PATH)/components/strings/component_strings_ml.xtb $(LOCAL_PATH)/components/strings/component_strings_mr.xtb $(LOCAL_PATH)/components/strings/component_strings_ms.xtb $(LOCAL_PATH)/components/strings/component_strings_nl.xtb $(LOCAL_PATH)/components/strings/component_strings_no.xtb $(LOCAL_PATH)/components/strings/component_strings_pl.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-BR.xtb $(LOCAL_PATH)/components/strings/component_strings_pt-PT.xtb $(LOCAL_PATH)/components/strings/component_strings_ro.xtb $(LOCAL_PATH)/components/strings/component_strings_ru.xtb $(LOCAL_PATH)/components/strings/component_strings_sk.xtb $(LOCAL_PATH)/components/strings/component_strings_sl.xtb $(LOCAL_PATH)/components/strings/component_strings_sr.xtb $(LOCAL_PATH)/components/strings/component_strings_sv.xtb $(LOCAL_PATH)/components/strings/component_strings_sw.xtb $(LOCAL_PATH)/components/strings/component_strings_ta.xtb $(LOCAL_PATH)/components/strings/component_strings_te.xtb $(LOCAL_PATH)/components/strings/component_strings_th.xtb $(LOCAL_PATH)/components/strings/component_strings_tr.xtb $(LOCAL_PATH)/components/strings/component_strings_uk.xtb $(LOCAL_PATH)/components/strings/component_strings_vi.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-CN.xtb $(LOCAL_PATH)/components/strings/component_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from components_strings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/components; mkdir -p $(gyp_shared_intermediate_dir)/components/strings/grit $(gyp_shared_intermediate_dir)/components/strings; python ../tools/grit/grit.py -i components_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/components/strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_am.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ar.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_bg.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_bn.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ca.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_cs.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_da.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_de.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_el.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-GB.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-US.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_es.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_es-419.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_et.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fa.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fil.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_fr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_gu.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_he.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_hi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_hr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_hu.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_id.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_it.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ja.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_kn.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ko.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_lt.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_lv.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ml.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_mr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ms.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_nl.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_nb.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_pl.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-BR.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-PT.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ro.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ru.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sk.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sl.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sv.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_sw.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_ta.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_te.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_th.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_tr.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_uk.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_vi.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-CN.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-TW.pak: $(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/components/strings/grit/component_strings.h \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_am.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ar.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_bg.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_bn.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ca.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_cs.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_da.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_de.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_el.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_es.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_et.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fa.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fil.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_fr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_gu.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_he.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_hi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_hr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_hu.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_id.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_it.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ja.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_kn.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ko.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_lt.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_lv.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ml.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_mr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ms.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_nl.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_nb.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_pl.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ro.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ru.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sk.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sl.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sv.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_sw.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_ta.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_te.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_th.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_tr.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_uk.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_vi.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/components/strings/component_strings_zh-TW.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_components_strings_gyp
+
+# Alias gyp target name.
+.PHONY: components_strings
+components_strings: components_components_strings_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/components_tests.gyp b/components/components_tests.gyp
index e59d0d0..b3d6fec 100644
--- a/components/components_tests.gyp
+++ b/components/components_tests.gyp
@@ -18,6 +18,8 @@
           'type': '<(gtest_target_type)',
           'sources': [
             'auto_login_parser/auto_login_parser_unittest.cc',
+            'autofill/content/browser/content_autofill_driver_unittest.cc',
+            'autofill/content/browser/request_autocomplete_manager_unittest.cc',
             'autofill/content/browser/wallet/full_wallet_unittest.cc',
             'autofill/content/browser/wallet/instrument_unittest.cc',
             'autofill/content/browser/wallet/wallet_address_unittest.cc',
@@ -72,9 +74,12 @@
             'dom_distiller/core/task_tracker_unittest.cc',
             'dom_distiller/core/url_utils_unittest.cc',
             'domain_reliability/context_unittest.cc',
+            'domain_reliability/dispatcher_unittest.cc',
             'domain_reliability/monitor_unittest.cc',
+            'domain_reliability/scheduler_unittest.cc',
             'domain_reliability/test_util.cc',
             'domain_reliability/test_util.h',
+            'domain_reliability/uploader_unittest.cc',
             'domain_reliability/util_unittest.cc',
             'json_schema/json_schema_validator_unittest.cc',
             'json_schema/json_schema_validator_unittest_base.cc',
@@ -105,7 +110,8 @@
             'rappor/rappor_metric_unittest.cc',
             'rappor/rappor_service_unittest.cc',
             'sessions/serialized_navigation_entry_unittest.cc',
-            'signin/core/webdata/token_service_table_unittest.cc',
+            'signin/core/browser/signin_error_controller_unittest.cc',
+            'signin/core/browser/webdata/token_service_table_unittest.cc',
             'storage_monitor/image_capture_device_manager_unittest.mm',
             'storage_monitor/media_storage_util_unittest.cc',
             'storage_monitor/media_transfer_protocol_device_observer_linux_unittest.cc',
@@ -205,7 +211,8 @@
             'components.gyp:rappor',
 
             # Dependencies of signin
-            'components.gyp:signin_core',
+            'components.gyp:signin_core_browser',
+            'components.gyp:signin_core_browser_test_support',
 
             # Dependencies of sync_driver
             'components.gyp:sync_driver_test_support',
@@ -544,7 +551,6 @@
             'HAS_OUT_OF_PROC_TEST_RUNNER',
           ],
           'sources': [
-            '../content/test/content_test_launcher.cc',
             'dom_distiller/content/distiller_page_web_contents_browsertest.cc',
 
             # content_extractor is a standalone content extraction tool built as
@@ -555,21 +561,13 @@
             {
               'action_name': 'repack_components_pack',
               'variables': {
-                'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
                 'pak_inputs': [
                   '<(SHARED_INTERMEDIATE_DIR)/components/component_resources.pak',
                   '<(SHARED_INTERMEDIATE_DIR)/components/strings/component_strings_en-US.pak',
                 ],
+                'pak_output': '<(PRODUCT_DIR)/components_resources.pak',
               },
-              'inputs': [
-                '<(repack_path)',
-                '<@(pak_inputs)',
-              ],
-              'outputs': [
-                '<(PRODUCT_DIR)/components_resources.pak',
-              ],
-              'action': ['python', '<(repack_path)', '<@(_outputs)',
-                         '<@(pak_inputs)'],
+              'includes': [ '../build/repack_action.gypi' ],
             },
           ],
           'conditions': [
diff --git a/components/dom_distiller/content/DEPS b/components/dom_distiller/content/DEPS
index 58162ae..d6b816f 100644
--- a/components/dom_distiller/content/DEPS
+++ b/components/dom_distiller/content/DEPS
@@ -2,7 +2,6 @@
   "+components/keyed_service",
   "+content/public",
   "+content/shell",
-  "+content/test",
   "+net/base",
   "+net/test",
   "+ui/base/l10n",
diff --git a/components/dom_distiller/content/distiller_page_web_contents.cc b/components/dom_distiller/content/distiller_page_web_contents.cc
index 2333d03..9cf8388 100644
--- a/components/dom_distiller/content/distiller_page_web_contents.cc
+++ b/components/dom_distiller/content/distiller_page_web_contents.cc
@@ -35,9 +35,9 @@
 
 void DistillerPageWebContents::InitImpl() {
   DCHECK(browser_context_);
-  web_contents_.reset(
-      content::WebContents::Create(
-          content::WebContents::CreateParams(browser_context_)));
+  content::WebContents::CreateParams create_params(browser_context_);
+  create_params.initially_hidden = true;
+  web_contents_.reset(content::WebContents::Create(create_params));
 }
 
 void DistillerPageWebContents::LoadURLImpl(const GURL& gurl) {
@@ -57,14 +57,12 @@
                                       web_contents_->GetLastCommittedURL()));
 }
 
-void DistillerPageWebContents::DidFinishLoad(int64 frame_id,
-                                             const GURL& validated_url,
-                                             bool is_main_frame,
-                                             RenderViewHost* render_view_host) {
-  // TODO(shashishekhar): Find a better way to detect when it is safe to run the
-  // distillation script. Waiting for the entire page to load is really slow.
-  if (is_main_frame) {
+void DistillerPageWebContents::DocumentLoadedInFrame(
+    int64 frame_id,
+    RenderViewHost* render_view_host) {
+  if (frame_id == web_contents_->GetMainFrame()->GetRoutingID()) {
     content::WebContentsObserver::Observe(NULL);
+    web_contents_->Stop();
     OnLoadURLDone();
   }
 }
diff --git a/components/dom_distiller/content/distiller_page_web_contents.h b/components/dom_distiller/content/distiller_page_web_contents.h
index 8d8bf3e..c6b94fc 100644
--- a/components/dom_distiller/content/distiller_page_web_contents.h
+++ b/components/dom_distiller/content/distiller_page_web_contents.h
@@ -46,10 +46,8 @@
   virtual ~DistillerPageWebContents();
 
   // content::WebContentsObserver implementation.
-  virtual void DidFinishLoad(int64 frame_id,
-                             const GURL& validated_url,
-                             bool is_main_frame,
-                             RenderViewHost* render_view_host) OVERRIDE;
+  virtual void DocumentLoadedInFrame(int64 frame_id,
+                                     RenderViewHost* render_view_host) OVERRIDE;
 
   virtual void DidFailLoad(int64 frame_id,
                            const GURL& validated_url,
diff --git a/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc b/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc
index 4c72eb7..5a240c2 100644
--- a/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc
+++ b/components/dom_distiller/content/distiller_page_web_contents_browsertest.cc
@@ -8,8 +8,8 @@
 #include "components/dom_distiller/content/distiller_page_web_contents.h"
 #include "components/dom_distiller/core/distiller_page.h"
 #include "content/public/browser/browser_context.h"
+#include "content/public/test/content_browser_test.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
 using content::ContentBrowserTest;
diff --git a/components/dom_distiller/core/css/distilledpage.css b/components/dom_distiller/core/css/distilledpage.css
new file mode 100644
index 0000000..a71a814
--- /dev/null
+++ b/components/dom_distiller/core/css/distilledpage.css
@@ -0,0 +1,16 @@
+/* Copyright 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+@charset "utf-8";
+/* Document */
+body{font-family:'Open Sans',sans-serif;font-size:18px;line-height:1.4;}
+/* Don't let images bleed out of viewport. */
+img{max-width:100%;}
+/* Margin */
+.margin-x-narrow{width:95%;}
+.margin-narrow{width:85%;}
+.margin-medium{width:75%;}
+.margin-wide{width:55%;}
+.margin-x-wide{width:35%;}
+/* Override html styling attributes */
+table,tr,td{background-color:transparent!important;}
diff --git a/components/dom_distiller/core/page_distiller.cc b/components/dom_distiller/core/page_distiller.cc
index 9116b47..db941ab 100644
--- a/components/dom_distiller/core/page_distiller.cc
+++ b/components/dom_distiller/core/page_distiller.cc
@@ -40,11 +40,15 @@
   LoadURL(url);
 }
 
-void PageDistiller::LoadURL(const GURL& url) { distiller_page_->LoadURL(url); }
+void PageDistiller::LoadURL(const GURL& url) {
+  DVLOG(1) << "Loading for distillation: " << url.spec();
+  distiller_page_->LoadURL(url);
+}
 
 void PageDistiller::OnLoadURLDone() { GetDistilledContent(); }
 
 void PageDistiller::GetDistilledContent() {
+  DVLOG(1) << "Beginning distillation";
   std::string script = ResourceBundle::GetSharedInstance()
                            .GetRawDataResource(IDR_DISTILLER_JS)
                            .as_string();
@@ -53,6 +57,9 @@
 
 void PageDistiller::OnExecuteJavaScriptDone(const GURL& page_url,
                                             const base::Value* value) {
+  DVLOG(1) << "Distillation complete; extracting resources for "
+      << page_url.spec();
+
   scoped_ptr<DistilledPageInfo> page_info(new DistilledPageInfo());
   std::string result;
   const base::ListValue* result_list = NULL;
diff --git a/components/dom_distiller/standalone/DEPS b/components/dom_distiller/standalone/DEPS
index d56a447..5fa9138 100644
--- a/components/dom_distiller/standalone/DEPS
+++ b/components/dom_distiller/standalone/DEPS
@@ -2,7 +2,6 @@
   "+components/dom_distiller/content",
   "+content/public",
   "+content/shell",
-  "+content/test",
   "+net",
   "+ui",
 ]
diff --git a/components/dom_distiller/standalone/content_extractor.cc b/components/dom_distiller/standalone/content_extractor.cc
index a3b37e8..6f16b01 100644
--- a/components/dom_distiller/standalone/content_extractor.cc
+++ b/components/dom_distiller/standalone/content_extractor.cc
@@ -19,8 +19,8 @@
 #include "components/dom_distiller/core/task_tracker.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/test/content_browser_test.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
 #include "net/dns/mock_host_resolver.h"
 #include "ui/base/resource/resource_bundle.h"
 
diff --git a/components/domain_reliability.gypi b/components/domain_reliability.gypi
index 0c5052f..447f35a 100644
--- a/components/domain_reliability.gypi
+++ b/components/domain_reliability.gypi
@@ -26,9 +26,15 @@
         'domain_reliability/config.h',
         'domain_reliability/context.cc',
         'domain_reliability/context.h',
+        'domain_reliability/dispatcher.cc',
+        'domain_reliability/dispatcher.h',
         'domain_reliability/domain_reliability_export.h',
         'domain_reliability/monitor.cc',
         'domain_reliability/monitor.h',
+        'domain_reliability/scheduler.cc',
+        'domain_reliability/scheduler.h',
+        'domain_reliability/uploader.cc',
+        'domain_reliability/uploader.h',
         'domain_reliability/util.cc',
         'domain_reliability/util.h',
       ],
diff --git a/components/domain_reliability/context.cc b/components/domain_reliability/context.cc
index 5a69689..88b28b8 100644
--- a/components/domain_reliability/context.cc
+++ b/components/domain_reliability/context.cc
@@ -10,6 +10,7 @@
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/values.h"
+#include "components/domain_reliability/dispatcher.h"
 #include "net/url_request/url_request_context_getter.h"
 
 using base::DictionaryValue;
@@ -29,9 +30,17 @@
 
 DomainReliabilityContext::DomainReliabilityContext(
     MockableTime* time,
+    const DomainReliabilityScheduler::Params& scheduler_params,
+    DomainReliabilityDispatcher* dispatcher,
+    DomainReliabilityUploader* uploader,
     scoped_ptr<const DomainReliabilityConfig> config)
     : config_(config.Pass()),
       time_(time),
+      scheduler_(time, config_->collectors.size(), scheduler_params,
+                 base::Bind(&DomainReliabilityContext::ScheduleUpload,
+                            base::Unretained(this))),
+      dispatcher_(dispatcher),
+      uploader_(uploader),
       beacon_count_(0),
       weak_factory_(this) {
   InitializeResourceStates();
@@ -68,6 +77,7 @@
     ++beacon_count_;
     if (beacon_count_ > kMaxQueuedBeacons)
       RemoveOldestBeacon();
+    scheduler_.OnBeaconAdded();
   }
 }
 
@@ -152,6 +162,43 @@
     states_.push_back(new ResourceState(this, *it));
 }
 
+void DomainReliabilityContext::ScheduleUpload(
+    base::TimeDelta min_delay,
+    base::TimeDelta max_delay) {
+  dispatcher_->ScheduleTask(
+      base::Bind(
+          &DomainReliabilityContext::StartUpload,
+          weak_factory_.GetWeakPtr()),
+      min_delay,
+      max_delay);
+}
+
+void DomainReliabilityContext::StartUpload() {
+  MarkUpload();
+
+  base::TimeTicks upload_time = time_->Now();
+  std::string report_json;
+  scoped_ptr<const Value> report_value(CreateReport(upload_time));
+  base::JSONWriter::Write(report_value.get(), &report_json);
+  report_value.reset();
+
+  int collector_index;
+  scheduler_.OnUploadStart(&collector_index);
+
+  uploader_->UploadReport(
+      report_json,
+      config_->collectors[collector_index]->upload_url,
+      base::Bind(
+          &DomainReliabilityContext::OnUploadComplete,
+          weak_factory_.GetWeakPtr()));
+}
+
+void DomainReliabilityContext::OnUploadComplete(bool success) {
+  if (success)
+    CommitUpload();
+  scheduler_.OnUploadComplete(success);
+}
+
 scoped_ptr<const Value> DomainReliabilityContext::CreateReport(
     base::TimeTicks upload_time) const {
   ListValue* resources_value = new ListValue();
diff --git a/components/domain_reliability/context.h b/components/domain_reliability/context.h
index bb6099d..428d639 100644
--- a/components/domain_reliability/context.h
+++ b/components/domain_reliability/context.h
@@ -15,19 +15,26 @@
 #include "components/domain_reliability/beacon.h"
 #include "components/domain_reliability/config.h"
 #include "components/domain_reliability/domain_reliability_export.h"
+#include "components/domain_reliability/scheduler.h"
+#include "components/domain_reliability/uploader.h"
 #include "components/domain_reliability/util.h"
 
 class GURL;
-class MockableTime;
 
 namespace domain_reliability {
 
+class DomainReliabilityDispatcher;
+class MockableTime;
+
 // The per-domain context for the Domain Reliability client; includes the
 // domain's config and per-resource beacon queues.
 class DOMAIN_RELIABILITY_EXPORT DomainReliabilityContext {
  public:
   DomainReliabilityContext(
       MockableTime* time,
+      const DomainReliabilityScheduler::Params& scheduler_params,
+      DomainReliabilityDispatcher* dispatcher,
+      DomainReliabilityUploader* uploader,
       scoped_ptr<const DomainReliabilityConfig> config);
   virtual ~DomainReliabilityContext();
 
@@ -89,6 +96,9 @@
   typedef ResourceStateVector::const_iterator ResourceStateIterator;
 
   void InitializeResourceStates();
+  void ScheduleUpload(base::TimeDelta min_delay, base::TimeDelta max_delay);
+  void StartUpload();
+  void OnUploadComplete(bool success);
 
   scoped_ptr<const base::Value> CreateReport(base::TimeTicks upload_time) const;
 
@@ -105,6 +115,9 @@
 
   scoped_ptr<const DomainReliabilityConfig> config_;
   MockableTime* time_;
+  DomainReliabilityScheduler scheduler_;
+  DomainReliabilityDispatcher* dispatcher_;
+  DomainReliabilityUploader* uploader_;
 
   // Each ResourceState in |states_| corresponds to the Resource of the same
   // index in the config.
diff --git a/components/domain_reliability/context_unittest.cc b/components/domain_reliability/context_unittest.cc
index 323f448..ee45229 100644
--- a/components/domain_reliability/context_unittest.cc
+++ b/components/domain_reliability/context_unittest.cc
@@ -10,6 +10,8 @@
 #include "base/bind.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "components/domain_reliability/dispatcher.h"
+#include "components/domain_reliability/scheduler.h"
 #include "components/domain_reliability/test_util.h"
 #include "net/base/net_errors.h"
 #include "net/url_request/url_request_test_util.h"
@@ -37,8 +39,39 @@
 class DomainReliabilityContextTest : public testing::Test {
  protected:
   DomainReliabilityContextTest()
-      : context_(&time_,
-                 CreateConfig().Pass()) {}
+      : dispatcher_(&time_),
+        params_(CreateParams()),
+        uploader_(base::Bind(&DomainReliabilityContextTest::OnUploadRequest,
+                             base::Unretained(this))),
+        context_(&time_,
+                 params_,
+                 &dispatcher_,
+                 &uploader_,
+                 CreateConfig().Pass()),
+        upload_pending_(false) {}
+
+  TimeDelta min_delay() const { return params_.minimum_upload_delay; }
+  TimeDelta max_delay() const { return params_.maximum_upload_delay; }
+  TimeDelta retry_interval() const { return params_.upload_retry_interval; }
+  TimeDelta zero_delta() const { return TimeDelta::FromMicroseconds(0); }
+
+  bool upload_pending() { return upload_pending_; }
+
+  const std::string& upload_report() {
+    DCHECK(upload_pending_);
+    return upload_report_;
+  }
+
+  const GURL& upload_url() {
+    DCHECK(upload_pending_);
+    return upload_url_;
+  }
+
+  void CallUploadCallback(bool success) {
+    DCHECK(upload_pending_);
+    upload_callback_.Run(success);
+    upload_pending_ = false;
+  }
 
   bool CheckNoBeacons(int index) {
     BeaconVector beacons;
@@ -53,9 +86,31 @@
   }
 
   MockTime time_;
+  DomainReliabilityDispatcher dispatcher_;
+  DomainReliabilityScheduler::Params params_;
+  MockUploader uploader_;
   DomainReliabilityContext context_;
 
  private:
+  void OnUploadRequest(
+      const std::string& report_json,
+      const GURL& upload_url,
+      const DomainReliabilityUploader::UploadCallback& callback) {
+    DCHECK(!upload_pending_);
+    upload_report_ = report_json;
+    upload_url_ = upload_url;
+    upload_callback_ = callback;
+    upload_pending_ = true;
+  }
+
+  static DomainReliabilityScheduler::Params CreateParams() {
+    DomainReliabilityScheduler::Params params;
+    params.minimum_upload_delay = base::TimeDelta::FromSeconds(60);
+    params.maximum_upload_delay = base::TimeDelta::FromSeconds(300);
+    params.upload_retry_interval = base::TimeDelta::FromSeconds(15);
+    return params;
+  }
+
   static scoped_ptr<const DomainReliabilityConfig> CreateConfig() {
     DomainReliabilityConfig* config = new DomainReliabilityConfig();
     DomainReliabilityConfig::Resource* resource;
@@ -83,6 +138,11 @@
 
     return scoped_ptr<const DomainReliabilityConfig>(config);
   }
+
+  bool upload_pending_;
+  std::string upload_report_;
+  GURL upload_url_;
+  DomainReliabilityUploader::UploadCallback upload_callback_;
 };
 
 TEST_F(DomainReliabilityContextTest, Create) {
@@ -124,4 +184,23 @@
   EXPECT_TRUE(CheckCounts(1, 0, 0));
 }
 
+TEST_F(DomainReliabilityContextTest, ReportUpload) {
+  DomainReliabilityBeacon beacon = MakeBeacon(&time_);
+  context_.AddBeacon(beacon, GURL("http://example/always_report"));
+
+  const char* kExpectedReport = "{\"reporter\":\"chrome\","
+      "\"resource_reports\":[{\"beacons\":[{\"http_response_code\":200,"
+      "\"request_age_ms\":300250,\"request_elapsed_ms\":250,\"server_ip\":"
+      "\"127.0.0.1\",\"status\":\"ok\"}],\"failed_requests\":0,"
+      "\"resource_name\":\"always_report\",\"successful_requests\":1},"
+      "{\"beacons\":[],\"failed_requests\":0,\"resource_name\":"
+      "\"never_report\",\"successful_requests\":0}]}";
+
+  time_.Advance(max_delay());
+  EXPECT_TRUE(upload_pending());
+  EXPECT_EQ(kExpectedReport, upload_report());
+  EXPECT_EQ(GURL("https://example/upload"), upload_url());
+  CallUploadCallback(true);
+}
+
 }  // namespace domain_reliability
diff --git a/components/domain_reliability/dispatcher.cc b/components/domain_reliability/dispatcher.cc
new file mode 100644
index 0000000..ceb4da0
--- /dev/null
+++ b/components/domain_reliability/dispatcher.cc
@@ -0,0 +1,109 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/domain_reliability/dispatcher.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/stl_util.h"
+#include "base/timer/timer.h"
+#include "components/domain_reliability/util.h"
+
+namespace domain_reliability {
+
+DomainReliabilityDispatcher::DomainReliabilityDispatcher(MockableTime* time)
+    : time_(time) {}
+
+DomainReliabilityDispatcher::~DomainReliabilityDispatcher() {
+  // TODO(ttuttle): STLElementDeleter?
+  STLDeleteElements(&tasks_);
+}
+
+void DomainReliabilityDispatcher::ScheduleTask(
+    const base::Closure& closure,
+    base::TimeDelta min_delay,
+    base::TimeDelta max_delay) {
+  DCHECK(!closure.is_null());
+  // Would be DCHECK_LE, but you can't << a TimeDelta.
+  DCHECK(min_delay <= max_delay);
+
+  Task* task = new Task(closure, time_->CreateTimer(), min_delay, max_delay);
+  tasks_.insert(task);
+  if (max_delay.InMicroseconds() < 0)
+    RunAndDeleteTask(task);
+  else if (min_delay.InMicroseconds() < 0)
+    MakeTaskEligible(task);
+  else
+    MakeTaskWaiting(task);
+}
+
+void DomainReliabilityDispatcher::RunEligibleTasks() {
+  // Move all eligible tasks to a separate set so that eligible_tasks_.erase in
+  // RunAndDeleteTask won't erase elements out from under the iterator.  (Also
+  // keeps RunEligibleTasks from running forever if a task adds a new, already-
+  // eligible task that does the same, and so on.)
+  std::set<Task*> tasks;
+  tasks.swap(eligible_tasks_);
+
+  for (std::set<Task*>::const_iterator it = tasks.begin();
+       it != tasks.end();
+       ++it) {
+    Task* task = *it;
+    DCHECK(task);
+    DCHECK(task->eligible);
+    RunAndDeleteTask(task);
+  }
+}
+
+DomainReliabilityDispatcher::Task::Task(const base::Closure& closure,
+                                        scoped_ptr<MockableTime::Timer> timer,
+                                        base::TimeDelta min_delay,
+                                        base::TimeDelta max_delay)
+    : closure(closure),
+      timer(timer.Pass()),
+      min_delay(min_delay),
+      max_delay(max_delay),
+      eligible(false) {}
+
+DomainReliabilityDispatcher::Task::~Task() {}
+
+void DomainReliabilityDispatcher::MakeTaskWaiting(Task* task) {
+  DCHECK(task);
+  DCHECK(!task->eligible);
+  DCHECK(!task->timer->IsRunning());
+  task->timer->Start(
+      FROM_HERE,
+      task->min_delay,
+      base::Bind(
+          &DomainReliabilityDispatcher::MakeTaskEligible,
+          base::Unretained(this),
+          task));
+}
+
+void
+DomainReliabilityDispatcher::MakeTaskEligible(Task* task) {
+  DCHECK(task);
+  DCHECK(!task->eligible);
+  task->eligible = true;
+  eligible_tasks_.insert(task);
+  task->timer->Start(
+      FROM_HERE,
+      task->max_delay - task->min_delay,
+      base::Bind(
+          &DomainReliabilityDispatcher::RunAndDeleteTask,
+          base::Unretained(this),
+          task));
+}
+
+void DomainReliabilityDispatcher::RunAndDeleteTask(Task* task) {
+  DCHECK(task);
+  DCHECK(!task->closure.is_null());
+  task->closure.Run();
+  if (task->eligible)
+    eligible_tasks_.erase(task);
+  tasks_.erase(task);
+  delete task;
+}
+
+}  // namespace domain_reliability
diff --git a/components/domain_reliability/dispatcher.h b/components/domain_reliability/dispatcher.h
new file mode 100644
index 0000000..52309e7
--- /dev/null
+++ b/components/domain_reliability/dispatcher.h
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOMAIN_RELIABILITY_DISPATCHER_H_
+#define COMPONENTS_DOMAIN_RELIABILITY_DISPATCHER_H_
+
+#include <set>
+
+#include "base/callback.h"
+#include "base/memory/scoped_vector.h"
+#include "base/time/time.h"
+#include "components/domain_reliability/domain_reliability_export.h"
+#include "components/domain_reliability/util.h"
+
+namespace tracked_objects {
+class Location;
+}  // namespace tracked_objects
+
+namespace domain_reliability {
+
+// Runs tasks during a specified interval. Calling |RunEligibleTasks| gives any
+// task a chance to run early (if the minimum delay has already passed); tasks
+// that aren't run early will be run once their maximum delay has passed.
+//
+// (See scheduler.h for an explanation of how the intervals are chosen.)
+class DOMAIN_RELIABILITY_EXPORT DomainReliabilityDispatcher {
+ public:
+  DomainReliabilityDispatcher(MockableTime* time);
+  ~DomainReliabilityDispatcher();
+
+  void ScheduleTask(
+      const base::Closure& task,
+      base::TimeDelta min_delay,
+      base::TimeDelta max_delay);
+
+  void RunEligibleTasks();
+
+ private:
+  struct Task {
+    Task(const base::Closure& closure_p,
+         scoped_ptr<MockableTime::Timer> timer_p,
+         base::TimeDelta min_delay_p,
+         base::TimeDelta max_delay_p);
+    ~Task();
+
+    base::Closure closure;
+    scoped_ptr<MockableTime::Timer> timer;
+    base::TimeDelta min_delay;
+    base::TimeDelta max_delay;
+    bool eligible;
+  };
+
+  void MakeTaskWaiting(Task* task);
+  void MakeTaskEligible(Task* task);
+  void RunAndDeleteTask(Task* task);
+
+  MockableTime* time_;
+  std::set<Task*> tasks_;
+  std::set<Task*> eligible_tasks_;
+};
+
+}  // namespace domain_reliability
+
+#endif
diff --git a/components/domain_reliability/dispatcher_unittest.cc b/components/domain_reliability/dispatcher_unittest.cc
new file mode 100644
index 0000000..f19883d
--- /dev/null
+++ b/components/domain_reliability/dispatcher_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/domain_reliability/dispatcher.h"
+
+#include "base/bind.h"
+#include "components/domain_reliability/test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace domain_reliability {
+
+class DomainReliabilityDispatcherTest : public testing::Test {
+ public:
+  DomainReliabilityDispatcherTest() : dispatcher_(&time_) {}
+
+ protected:
+  MockTime time_;
+  DomainReliabilityDispatcher dispatcher_;
+};
+
+TEST_F(DomainReliabilityDispatcherTest, Create) {
+}
+
+TEST_F(DomainReliabilityDispatcherTest, TaskDoesntRunEarly) {
+  TimeDelta delay = TimeDelta::FromSeconds(1);
+  TestCallback callback;
+
+  dispatcher_.ScheduleTask(callback.callback(), 2 * delay, 3 * delay);
+  time_.Advance(delay);
+  dispatcher_.RunEligibleTasks();
+  EXPECT_FALSE(callback.called());
+}
+
+TEST_F(DomainReliabilityDispatcherTest, TaskRunsWhenEligible) {
+  TimeDelta delay = TimeDelta::FromSeconds(1);
+  TestCallback callback;
+
+  dispatcher_.ScheduleTask(callback.callback(), 2 * delay, 3 * delay);
+  time_.Advance(2 * delay);
+  EXPECT_FALSE(callback.called());
+  dispatcher_.RunEligibleTasks();
+  EXPECT_TRUE(callback.called());
+  time_.Advance(delay);
+}
+
+TEST_F(DomainReliabilityDispatcherTest, TaskRunsAtDeadline) {
+  TimeDelta delay = TimeDelta::FromSeconds(1);
+  TestCallback callback;
+
+  dispatcher_.ScheduleTask(callback.callback(), 2 * delay, 3 * delay);
+  time_.Advance(2 * delay);
+  EXPECT_FALSE(callback.called());
+  time_.Advance(delay);
+  EXPECT_TRUE(callback.called());
+}
+
+}  // namespace domain_reliability
diff --git a/components/domain_reliability/monitor.cc b/components/domain_reliability/monitor.cc
index 09f122f..8f0b8cd 100644
--- a/components/domain_reliability/monitor.cc
+++ b/components/domain_reliability/monitor.cc
@@ -18,18 +18,67 @@
   return content::BrowserThread::CurrentlyOn(content::BrowserThread::IO);
 }
 
+// Shamelessly stolen from net/tools/get_server_time/get_server_time.cc.
+// TODO(ttuttle): Merge them, if possible.
+class TrivialURLRequestContextGetter : public net::URLRequestContextGetter {
+ public:
+  TrivialURLRequestContextGetter(
+      net::URLRequestContext* context,
+      const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
+      : context_(context),
+        main_task_runner_(main_task_runner) {}
+
+  // net::URLRequestContextGEtter implementation:
+  virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
+    return context_;
+  }
+
+  virtual scoped_refptr<base::SingleThreadTaskRunner>
+  GetNetworkTaskRunner() const OVERRIDE {
+    return main_task_runner_;
+  }
+
+ private:
+  virtual ~TrivialURLRequestContextGetter() {}
+
+  net::URLRequestContext* context_;
+  const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+};
+
 }  // namespace
 
 namespace domain_reliability {
 
-DomainReliabilityMonitor::DomainReliabilityMonitor()
-    : time_(new ActualTime()) {
+DomainReliabilityMonitor::DomainReliabilityMonitor(
+    net::URLRequestContext* url_request_context)
+    : time_(new ActualTime()),
+      url_request_context_getter_(scoped_refptr<net::URLRequestContextGetter>(
+          new TrivialURLRequestContextGetter(
+              url_request_context,
+              content::BrowserThread::GetMessageLoopProxyForThread(
+                  content::BrowserThread::IO)))),
+      scheduler_params_(
+          DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
+      dispatcher_(time_.get()),
+      uploader_(
+          DomainReliabilityUploader::Create(url_request_context_getter_)) {
   DCHECK(OnIOThread());
 }
 
 DomainReliabilityMonitor::DomainReliabilityMonitor(
+    net::URLRequestContext* url_request_context,
     scoped_ptr<MockableTime> time)
-    : time_(time.Pass()) {
+    : time_(time.Pass()),
+      url_request_context_getter_(scoped_refptr<net::URLRequestContextGetter>(
+          new TrivialURLRequestContextGetter(
+              url_request_context,
+              content::BrowserThread::GetMessageLoopProxyForThread(
+                  content::BrowserThread::IO)))),
+      scheduler_params_(
+          DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()),
+      dispatcher_(time_.get()),
+      uploader_(
+          DomainReliabilityUploader::Create(url_request_context_getter_)) {
   DCHECK(OnIOThread());
 }
 
@@ -59,7 +108,12 @@
     scoped_ptr<const DomainReliabilityConfig> config) {
   DomainReliabilityContext*& context_ref = contexts_[config->domain];
   DCHECK(!context_ref);
-  context_ref = new DomainReliabilityContext(time_.get(), config.Pass());
+  context_ref = new DomainReliabilityContext(
+      time_.get(),
+      scheduler_params_,
+      &dispatcher_,
+      uploader_.get(),
+      config.Pass());
   return context_ref;
 }
 
diff --git a/components/domain_reliability/monitor.h b/components/domain_reliability/monitor.h
index 5d189dc..da989cd 100644
--- a/components/domain_reliability/monitor.h
+++ b/components/domain_reliability/monitor.h
@@ -12,7 +12,10 @@
 #include "components/domain_reliability/beacon.h"
 #include "components/domain_reliability/config.h"
 #include "components/domain_reliability/context.h"
+#include "components/domain_reliability/dispatcher.h"
 #include "components/domain_reliability/domain_reliability_export.h"
+#include "components/domain_reliability/scheduler.h"
+#include "components/domain_reliability/uploader.h"
 #include "components/domain_reliability/util.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/load_timing_info.h"
@@ -20,6 +23,8 @@
 
 namespace net {
 class URLRequest;
+class URLRequestContext;
+class URLRequestContextGetter;
 }
 
 namespace domain_reliability {
@@ -31,8 +36,11 @@
  public:
   // NB: We don't take a URLRequestContextGetter because we already live on the
   // I/O thread.
-  DomainReliabilityMonitor();
-  explicit DomainReliabilityMonitor(scoped_ptr<MockableTime> time);
+  explicit DomainReliabilityMonitor(
+      net::URLRequestContext* url_request_context);
+  DomainReliabilityMonitor(
+      net::URLRequestContext* url_request_context,
+      scoped_ptr<MockableTime> time);
   ~DomainReliabilityMonitor();
 
   // Should be called from the profile's NetworkDelegate on the corresponding
@@ -64,6 +72,10 @@
   void OnRequestLegComplete(const RequestInfo& info);
 
   scoped_ptr<MockableTime> time_;
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+  DomainReliabilityScheduler::Params scheduler_params_;
+  DomainReliabilityDispatcher dispatcher_;
+  scoped_ptr<DomainReliabilityUploader> uploader_;
   std::map<std::string, DomainReliabilityContext*> contexts_;
 
   DISALLOW_COPY_AND_ASSIGN(DomainReliabilityMonitor);
diff --git a/components/domain_reliability/monitor_unittest.cc b/components/domain_reliability/monitor_unittest.cc
index 9d15114..59da34b 100644
--- a/components/domain_reliability/monitor_unittest.cc
+++ b/components/domain_reliability/monitor_unittest.cc
@@ -15,7 +15,9 @@
 #include "components/domain_reliability/config.h"
 #include "components/domain_reliability/test_util.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "net/url_request/url_request_context_getter.h"
 #include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace domain_reliability {
@@ -28,8 +30,11 @@
 
   DomainReliabilityMonitorTest()
       : bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+        url_request_context_getter_(new net::TestURLRequestContextGetter(
+            base::MessageLoopProxy::current())),
         time_(new MockTime()),
-        monitor_(scoped_ptr<MockableTime>(time_)),
+        monitor_(url_request_context_getter_->GetURLRequestContext(),
+                 scoped_ptr<MockableTime>(time_)),
         context_(monitor_.AddContextForTesting(CreateConfig())) {}
 
   static scoped_ptr<const DomainReliabilityConfig> CreateConfig() {
@@ -81,6 +86,7 @@
   }
 
   content::TestBrowserThreadBundle bundle_;
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
   MockTime* time_;
   DomainReliabilityMonitor monitor_;
   DomainReliabilityContext* context_;
diff --git a/components/domain_reliability/scheduler.cc b/components/domain_reliability/scheduler.cc
new file mode 100644
index 0000000..20da4fc
--- /dev/null
+++ b/components/domain_reliability/scheduler.cc
@@ -0,0 +1,210 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/domain_reliability/scheduler.h"
+
+#include <algorithm>
+
+#include "base/metrics/field_trial.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/domain_reliability/config.h"
+#include "components/domain_reliability/util.h"
+
+namespace {
+
+const int kInvalidCollectorIndex = -1;
+
+const int kDefaultMinimumUploadDelaySec = 60;
+const int kDefaultMaximumUploadDelaySec = 300;
+const int kDefaultUploadRetryIntervalSec = 60;
+
+const char* kMinimumUploadDelayFieldTrialName = "DomRel-MinimumUploadDelay";
+const char* kMaximumUploadDelayFieldTrialName = "DomRel-MaximumUploadDelay";
+const char* kUploadRetryIntervalFieldTrialName = "DomRel-UploadRetryInterval";
+
+int GetIntegerFieldTrialValueOrDefault(
+    std::string field_trial_name,
+    int default_value) {
+  if (!base::FieldTrialList::TrialExists(field_trial_name))
+    return default_value;
+
+  std::string group_name = base::FieldTrialList::FindFullName(field_trial_name);
+  int value;
+  if (!base::StringToInt(group_name, &value)) {
+    LOG(ERROR) << "Expected integer for field trial " << field_trial_name
+               << " group name, but got \"" << group_name << "\".";
+    return default_value;
+  }
+
+  return value;
+}
+
+}  // namespace
+
+namespace domain_reliability {
+
+// static
+DomainReliabilityScheduler::Params
+DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults() {
+  DomainReliabilityScheduler::Params params;
+
+  params.minimum_upload_delay = base::TimeDelta::FromSeconds(
+      GetIntegerFieldTrialValueOrDefault(kMinimumUploadDelayFieldTrialName,
+                                         kDefaultMinimumUploadDelaySec));
+  params.maximum_upload_delay = base::TimeDelta::FromSeconds(
+      GetIntegerFieldTrialValueOrDefault(kMaximumUploadDelayFieldTrialName,
+                                         kDefaultMaximumUploadDelaySec));
+  params.upload_retry_interval = base::TimeDelta::FromSeconds(
+      GetIntegerFieldTrialValueOrDefault(kUploadRetryIntervalFieldTrialName,
+                                         kDefaultUploadRetryIntervalSec));
+
+  return params;
+}
+
+DomainReliabilityScheduler::DomainReliabilityScheduler(
+    MockableTime* time,
+    size_t num_collectors,
+    const Params& params,
+    const ScheduleUploadCallback& callback)
+    : time_(time),
+      collectors_(num_collectors),
+      params_(params),
+      callback_(callback),
+      upload_pending_(false),
+      upload_scheduled_(false),
+      upload_running_(false),
+      collector_index_(kInvalidCollectorIndex) {
+}
+
+DomainReliabilityScheduler::~DomainReliabilityScheduler() {}
+
+void DomainReliabilityScheduler::OnBeaconAdded() {
+  if (!upload_pending_)
+    first_beacon_time_ = time_->Now();
+  upload_pending_ = true;
+  VLOG(2) << "OnBeaconAdded";
+  MaybeScheduleUpload();
+}
+
+void DomainReliabilityScheduler::OnUploadStart(int* collector_index_out) {
+  DCHECK(collector_index_out);
+  DCHECK(upload_scheduled_);
+  DCHECK_EQ(kInvalidCollectorIndex, collector_index_);
+  upload_scheduled_ = false;
+  upload_running_ = true;
+
+  base::TimeTicks now = time_->Now();
+  base::TimeTicks min_upload_time;
+  GetNextUploadTimeAndCollector(now, &min_upload_time, &collector_index_);
+  DCHECK(min_upload_time <= now);
+
+  *collector_index_out = collector_index_;
+
+  VLOG(1) << "Starting upload to collector " << collector_index_ << ".";
+}
+
+void DomainReliabilityScheduler::OnUploadComplete(bool success) {
+  DCHECK(upload_running_);
+  DCHECK_NE(kInvalidCollectorIndex, collector_index_);
+  upload_running_ = false;
+
+  VLOG(1) << "Upload to collector " << collector_index_
+          << (success ? " succeeded." : " failed.");
+
+  CollectorState* collector = &collectors_[collector_index_];
+  collector_index_ = kInvalidCollectorIndex;
+
+  if (success) {
+    collector->failures = 0;
+  } else {
+    // Restore upload_pending_ and first_beacon_time_ to pre-upload state,
+    // since upload failed.
+    upload_pending_ = true;
+    first_beacon_time_ = old_first_beacon_time_;
+
+    ++collector->failures;
+  }
+
+  base::TimeDelta retry_interval = GetUploadRetryInterval(collector->failures);
+  collector->next_upload = time_->Now() + retry_interval;
+
+  VLOG(1) << "Next upload to collector at least "
+          << retry_interval.InSeconds() << " seconds from now.";
+
+  MaybeScheduleUpload();
+}
+
+DomainReliabilityScheduler::CollectorState::CollectorState() : failures(0) {}
+
+void DomainReliabilityScheduler::MaybeScheduleUpload() {
+  if (!upload_pending_ || upload_scheduled_ || upload_running_)
+    return;
+
+  upload_pending_ = false;
+  upload_scheduled_ = true;
+  old_first_beacon_time_ = first_beacon_time_;
+
+  base::TimeTicks now = time_->Now();
+
+  base::TimeTicks min_by_deadline, max_by_deadline;
+  min_by_deadline = first_beacon_time_ + params_.minimum_upload_delay;
+  max_by_deadline = first_beacon_time_ + params_.maximum_upload_delay;
+  DCHECK(min_by_deadline <= max_by_deadline);
+
+  base::TimeTicks min_by_backoff;
+  int collector_index;
+  GetNextUploadTimeAndCollector(now, &min_by_backoff, &collector_index);
+
+  base::TimeDelta min_delay = std::max(min_by_deadline, min_by_backoff) - now;
+  base::TimeDelta max_delay = std::max(max_by_deadline, min_by_backoff) - now;
+
+  VLOG(1) << "Scheduling upload for between " << min_delay.InSeconds()
+          << " and " << max_delay.InSeconds() << " seconds from now.";
+
+  callback_.Run(min_delay, max_delay);
+}
+
+// TODO(ttuttle): Add min and max interval to config, use that instead.
+// TODO(ttuttle): Cap min and max intervals received from config.
+
+void DomainReliabilityScheduler::GetNextUploadTimeAndCollector(
+    base::TimeTicks now,
+    base::TimeTicks* upload_time_out,
+    int* collector_index_out) {
+  DCHECK(upload_time_out);
+  DCHECK(collector_index_out);
+
+  base::TimeTicks min_time;
+  int min_index = kInvalidCollectorIndex;
+
+  for (unsigned i = 0; i < collectors_.size(); ++i) {
+    CollectorState* collector = &collectors_[i];
+    // If a collector is usable, use the first one in the list.
+    if (collector->failures == 0 || collector->next_upload <= now) {
+      min_time = now;
+      min_index = i;
+      break;
+    // If not, keep track of which will be usable soonest:
+    } else if (min_index == kInvalidCollectorIndex ||
+        collector->next_upload < min_time) {
+      min_time = collector->next_upload;
+      min_index = i;
+    }
+  }
+
+  DCHECK_NE(kInvalidCollectorIndex, min_index);
+  *upload_time_out = min_time;
+  *collector_index_out = min_index;
+}
+
+base::TimeDelta DomainReliabilityScheduler::GetUploadRetryInterval(
+    int failures) {
+  if (failures == 0)
+    return base::TimeDelta::FromSeconds(0);
+  else {
+    return params_.upload_retry_interval * (1 << std::min(failures - 1, 5));
+  }
+}
+
+}  // namespace domain_reliability
diff --git a/components/domain_reliability/scheduler.h b/components/domain_reliability/scheduler.h
new file mode 100644
index 0000000..ee924d7
--- /dev/null
+++ b/components/domain_reliability/scheduler.h
@@ -0,0 +1,113 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOMAIN_RELIABILITY_SCHEDULER_H_
+#define COMPONENTS_DOMAIN_RELIABILITY_SCHEDULER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/time/time.h"
+#include "components/domain_reliability/domain_reliability_export.h"
+
+namespace domain_reliability {
+
+class DomainReliabilityConfig;
+class MockableTime;
+
+// Determines when an upload should be scheduled. A domain's config will
+// specify minimum and maximum upload delays; the minimum upload delay ensures
+// that Chrome will not send too many upload requests to a site by waiting at
+// least that long after the first beacon, while the maximum upload delay makes
+// sure the server receives the reports while they are still fresh.
+//
+// When everything is working fine, the scheduler will return precisely that
+// interval. If all uploaders have failed, then the beginning or ending points
+// of the interval may be pushed later to accomodate the retry with exponential
+// backoff.
+//
+// See dispatcher.h for an explanation of what happens with the scheduled
+// interval.
+class DOMAIN_RELIABILITY_EXPORT DomainReliabilityScheduler {
+ public:
+  typedef base::Callback<void(base::TimeDelta, base::TimeDelta)>
+      ScheduleUploadCallback;
+
+  struct Params {
+   public:
+    base::TimeDelta minimum_upload_delay;
+    base::TimeDelta maximum_upload_delay;
+    base::TimeDelta upload_retry_interval;
+
+    static Params GetFromFieldTrialsOrDefaults();
+  };
+
+  DomainReliabilityScheduler(MockableTime* time,
+                             size_t num_collectors,
+                             const Params& params,
+                             const ScheduleUploadCallback& callback);
+  ~DomainReliabilityScheduler();
+
+  // Called when a beacon is added to the context. May call the provided
+  // ScheduleUploadCallback (if all previous beacons have been uploaded).
+  void OnBeaconAdded();
+
+  // Called when an upload is about to start.
+  void OnUploadStart(int* collector_index_out);
+
+  // Called when an upload has finished. May call the provided
+  // ScheduleUploadCallback (if the upload failed, or if beacons arrived
+  // during the upload).
+  void OnUploadComplete(bool success);
+
+ private:
+  struct CollectorState {
+    CollectorState();
+
+    // The number of consecutive failures to upload to this collector, or 0 if
+    // the most recent upload succeeded.
+    int failures;
+    base::TimeTicks next_upload;
+  };
+
+  void MaybeScheduleUpload();
+
+  void GetNextUploadTimeAndCollector(base::TimeTicks now,
+                                     base::TimeTicks* upload_time_out,
+                                     int* collector_index_out);
+  base::TimeDelta GetUploadRetryInterval(int failures);
+
+  MockableTime* time_;
+  std::vector<CollectorState> collectors_;
+  Params params_;
+  ScheduleUploadCallback callback_;
+
+  // Whether there are beacons that have not yet been uploaded. Set when a
+  // beacon arrives or an upload fails, and cleared when an upload starts.
+  bool upload_pending_;
+
+  // Whether the scheduler has called the ScheduleUploadCallback to schedule
+  // the next upload. Set when an upload is scheduled and cleared when the
+  // upload starts.
+  bool upload_scheduled_;
+
+  // Whether the last scheduled upload is in progress. Set when the upload
+  // starts and cleared when the upload completes (successfully or not).
+  bool upload_running_;
+
+  // Index of the collector selected for the next upload.  (Set in
+  // |OnUploadStart| and cleared in |OnUploadComplete|.)
+  int collector_index_;
+
+  // Time of the first beacon that was not included in the last successful
+  // upload.
+  base::TimeTicks first_beacon_time_;
+
+  // first_beacon_time_ saved during uploads.  Restored if upload fails.
+  base::TimeTicks old_first_beacon_time_;
+};
+
+}  // namespace domain_reliability
+
+#endif  // COMPONENTS_DOMAIN_RELIABILITY_SCHEDULER_H_
diff --git a/components/domain_reliability/scheduler_unittest.cc b/components/domain_reliability/scheduler_unittest.cc
new file mode 100644
index 0000000..1d4ef7b
--- /dev/null
+++ b/components/domain_reliability/scheduler_unittest.cc
@@ -0,0 +1,215 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/domain_reliability/scheduler.h"
+
+#include "base/bind.h"
+#include "base/time/time.h"
+#include "components/domain_reliability/test_util.h"
+#include "components/domain_reliability/util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+namespace domain_reliability {
+
+class DomainReliabilitySchedulerTest : public testing::Test {
+ public:
+  DomainReliabilitySchedulerTest() :
+      num_collectors_(0),
+      params_(CreateDefaultParams()),
+      callback_called_(false) {
+  }
+
+  void CreateScheduler(int num_collectors) {
+    DCHECK_LT(0, num_collectors);
+    DCHECK(!scheduler_);
+
+    num_collectors_ = num_collectors;
+    scheduler_.reset(new DomainReliabilityScheduler(
+        &time_,
+        num_collectors_,
+        params_,
+        base::Bind(&DomainReliabilitySchedulerTest::ScheduleUploadCallback,
+                   base::Unretained(this))));
+  }
+
+  static DomainReliabilityScheduler::Params CreateDefaultParams() {
+    DomainReliabilityScheduler::Params params;
+    params.minimum_upload_delay = base::TimeDelta::FromSeconds(60);
+    params.maximum_upload_delay = base::TimeDelta::FromSeconds(300);
+    params.upload_retry_interval = base::TimeDelta::FromSeconds(15);
+    return params;
+  }
+
+  ::testing::AssertionResult CheckNoPendingUpload() {
+    DCHECK(scheduler_);
+
+    if (!callback_called_)
+      return ::testing::AssertionSuccess();
+
+    return ::testing::AssertionFailure()
+           << "expected no upload, got upload between "
+           << callback_min_.InSeconds() << " and "
+           << callback_max_.InSeconds() << " seconds from now";
+  }
+
+  ::testing::AssertionResult CheckPendingUpload(TimeDelta expected_min,
+                                                TimeDelta expected_max) {
+    DCHECK(scheduler_);
+    DCHECK_LE(expected_min.InMicroseconds(), expected_max.InMicroseconds());
+
+    if (callback_called_ && expected_min == callback_min_
+                         && expected_max == callback_max_) {
+      return ::testing::AssertionSuccess();
+    }
+
+    if (callback_called_) {
+      return ::testing::AssertionFailure()
+             << "expected upload between " << expected_min.InSeconds()
+             << " and " << expected_max.InSeconds() << " seconds from now, "
+             << "got upload between " << callback_min_.InSeconds()
+             << " and " << callback_max_.InSeconds() << " seconds from now";
+    } else {
+      return ::testing::AssertionFailure()
+             << "expected upload between " << expected_min.InSeconds()
+             << " and " << expected_max.InSeconds() << " seconds from now, "
+             << "got no upload";
+    }
+  }
+
+  ::testing::AssertionResult CheckStartingUpload(int expected_collector) {
+    DCHECK(scheduler_);
+    DCHECK_LE(0, expected_collector);
+    DCHECK_GT(num_collectors_, expected_collector);
+
+    int collector;
+    scheduler_->OnUploadStart(&collector);
+    if (collector == expected_collector)
+      return ::testing::AssertionSuccess();
+
+    return ::testing::AssertionFailure()
+           << "expected upload to collector " << expected_collector
+           << ", got upload to collector " << collector;
+  }
+
+  TimeDelta min_delay() const { return params_.minimum_upload_delay; }
+  TimeDelta max_delay() const { return params_.maximum_upload_delay; }
+  TimeDelta retry_interval() const { return params_.upload_retry_interval; }
+  TimeDelta zero_delta() const { return base::TimeDelta::FromMicroseconds(0); }
+
+ protected:
+  void ScheduleUploadCallback(TimeDelta min, TimeDelta max) {
+    callback_called_ = true;
+    callback_min_ = min;
+    callback_max_ = max;
+  }
+
+  MockTime time_;
+  int num_collectors_;
+  DomainReliabilityScheduler::Params params_;
+  scoped_ptr<DomainReliabilityScheduler> scheduler_;
+
+  bool callback_called_;
+  TimeDelta callback_min_;
+  TimeDelta callback_max_;
+};
+
+TEST_F(DomainReliabilitySchedulerTest, Create) {
+  CreateScheduler(1);
+}
+
+TEST_F(DomainReliabilitySchedulerTest, UploadNotPendingWithoutBeacon) {
+  CreateScheduler(1);
+
+  ASSERT_TRUE(CheckNoPendingUpload());
+}
+
+TEST_F(DomainReliabilitySchedulerTest, SuccessfulUploads) {
+  CreateScheduler(1);
+
+  scheduler_->OnBeaconAdded();
+  ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
+  time_.Advance(min_delay());
+  ASSERT_TRUE(CheckStartingUpload(0));
+  scheduler_->OnUploadComplete(true);
+
+  scheduler_->OnBeaconAdded();
+  ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
+  time_.Advance(min_delay());
+  ASSERT_TRUE(CheckStartingUpload(0));
+  scheduler_->OnUploadComplete(true);
+}
+
+TEST_F(DomainReliabilitySchedulerTest, Failover) {
+  CreateScheduler(2);
+
+  scheduler_->OnBeaconAdded();
+  ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
+  time_.Advance(min_delay());
+  ASSERT_TRUE(CheckStartingUpload(0));
+  scheduler_->OnUploadComplete(false);
+
+  scheduler_->OnBeaconAdded();
+  ASSERT_TRUE(CheckPendingUpload(zero_delta(), max_delay() - min_delay()));
+  // Don't need to advance; should retry immediately.
+  ASSERT_TRUE(CheckStartingUpload(1));
+  scheduler_->OnUploadComplete(true);
+}
+
+TEST_F(DomainReliabilitySchedulerTest, FailedAllCollectors) {
+  CreateScheduler(2);
+
+  // T = 0
+  scheduler_->OnBeaconAdded();
+  ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
+  time_.Advance(min_delay());
+
+  // T = min_delay
+  ASSERT_TRUE(CheckStartingUpload(0));
+  scheduler_->OnUploadComplete(false);
+
+  ASSERT_TRUE(CheckPendingUpload(zero_delta(), max_delay() - min_delay()));
+  // Don't need to advance; should retry immediately.
+  ASSERT_TRUE(CheckStartingUpload(1));
+  scheduler_->OnUploadComplete(false);
+
+  ASSERT_TRUE(CheckPendingUpload(retry_interval(), max_delay() - min_delay()));
+  time_.Advance(retry_interval());
+
+  // T = min_delay + retry_interval
+  ASSERT_TRUE(CheckStartingUpload(0));
+  scheduler_->OnUploadComplete(false);
+
+  ASSERT_TRUE(CheckPendingUpload(
+      zero_delta(),
+      max_delay() - min_delay() - retry_interval()));
+  ASSERT_TRUE(CheckStartingUpload(1));
+  scheduler_->OnUploadComplete(false);
+}
+
+// Make sure that the scheduler uses the first available collector at upload
+// time, even if it wasn't available at scheduling time.
+TEST_F(DomainReliabilitySchedulerTest, DetermineCollectorAtUpload) {
+  CreateScheduler(2);
+
+  // T = 0
+  scheduler_->OnBeaconAdded();
+  ASSERT_TRUE(CheckPendingUpload(min_delay(), max_delay()));
+  time_.Advance(min_delay());
+
+  // T = min_delay
+  ASSERT_TRUE(CheckStartingUpload(0));
+  scheduler_->OnUploadComplete(false);
+
+  ASSERT_TRUE(CheckPendingUpload(zero_delta(), max_delay() - min_delay()));
+  time_.Advance(retry_interval());
+
+  // T = min_delay + retry_interval; collector 0 should be active again.
+  ASSERT_TRUE(CheckStartingUpload(0));
+  scheduler_->OnUploadComplete(true);
+}
+
+}  // namespace domain_reliability
diff --git a/components/domain_reliability/test_util.cc b/components/domain_reliability/test_util.cc
index 08ddd04..cfb1f31 100644
--- a/components/domain_reliability/test_util.cc
+++ b/components/domain_reliability/test_util.cc
@@ -23,6 +23,7 @@
   }
   virtual ~MockTimer() {}
 
+  // MockableTime::Timer implementation:
   virtual void Start(const tracked_objects::Location& posted_from,
                      base::TimeDelta delay,
                      const base::Closure& user_task) OVERRIDE {
@@ -82,6 +83,17 @@
   called_ = true;
 }
 
+MockUploader::MockUploader(const UploadRequestCallback& callback)
+    : callback_(callback) {}
+
+MockUploader::~MockUploader() {}
+
+void MockUploader::UploadReport(const std::string& report_json,
+                                const GURL& upload_url,
+                                const UploadCallback& callback) {
+  callback_.Run(report_json, upload_url, callback);
+}
+
 MockTime::MockTime()
     : now_(base::TimeTicks::Now()),
       epoch_(now_),
diff --git a/components/domain_reliability/test_util.h b/components/domain_reliability/test_util.h
index c7a1f2d..a123073 100644
--- a/components/domain_reliability/test_util.h
+++ b/components/domain_reliability/test_util.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "components/domain_reliability/monitor.h"
+#include "components/domain_reliability/uploader.h"
 #include "components/domain_reliability/util.h"
 #include "net/base/host_port_pair.h"
 
@@ -34,6 +35,25 @@
   bool called_;
 };
 
+class MockUploader : public DomainReliabilityUploader {
+ public:
+  typedef base::Callback<void(const std::string& report_json,
+                              const GURL& upload_url,
+                              const UploadCallback& upload_callback)>
+      UploadRequestCallback;
+
+  MockUploader(const UploadRequestCallback& callback);
+  virtual ~MockUploader();
+
+  // DomainREliabilityUploader implementation:
+  virtual void UploadReport(const std::string& report_json,
+                            const GURL& upload_url,
+                            const UploadCallback& callback) OVERRIDE;
+
+ private:
+  UploadRequestCallback callback_;
+};
+
 class MockTime : public MockableTime {
  public:
   MockTime();
@@ -42,6 +62,7 @@
   // to their scheduled time.
   virtual ~MockTime();
 
+  // MockableTime implementation:
   virtual base::TimeTicks Now() OVERRIDE;
   virtual scoped_ptr<MockableTime::Timer> CreateTimer() OVERRIDE;
 
diff --git a/components/domain_reliability/uploader.cc b/components/domain_reliability/uploader.cc
new file mode 100644
index 0000000..58d9749
--- /dev/null
+++ b/components/domain_reliability/uploader.cc
@@ -0,0 +1,89 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/domain_reliability/uploader.h"
+
+#include "base/bind.h"
+#include "base/stl_util.h"
+#include "net/base/load_flags.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace domain_reliability {
+
+namespace {
+
+class DomainReliabilityUploaderImpl
+    : public DomainReliabilityUploader, net::URLFetcherDelegate {
+ public:
+  DomainReliabilityUploaderImpl(
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter)
+      : url_request_context_getter_(url_request_context_getter) {}
+
+  virtual ~DomainReliabilityUploaderImpl() {
+    // Delete any in-flight URLFetchers.
+    STLDeleteContainerPairFirstPointers(
+        upload_callbacks_.begin(), upload_callbacks_.end());
+  }
+
+  // DomainReliabilityUploader implementation:
+  virtual void UploadReport(
+      const std::string& report_json,
+      const GURL& upload_url,
+      const DomainReliabilityUploader::UploadCallback& callback) OVERRIDE {
+    VLOG(1) << "Uploading report to " << upload_url;
+    VLOG(2) << "Report JSON: " << report_json;
+
+    net::URLFetcher* fetcher =
+        net::URLFetcher::Create(0, upload_url, net::URLFetcher::POST, this);
+    fetcher->SetRequestContext(url_request_context_getter_);
+    fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
+                          net::LOAD_DO_NOT_SAVE_COOKIES);
+    fetcher->SetUploadData("text/json", report_json);
+    fetcher->SetAutomaticallyRetryOn5xx(false);
+    fetcher->Start();
+
+    upload_callbacks_[fetcher] = callback;
+  }
+
+  // net::URLFetcherDelegate implementation:
+  virtual void OnURLFetchComplete(
+      const net::URLFetcher* fetcher) OVERRIDE {
+    DCHECK(fetcher);
+
+    UploadCallbackMap::iterator callback_it = upload_callbacks_.find(fetcher);
+    DCHECK(callback_it != upload_callbacks_.end());
+
+    VLOG(1) << "Upload finished with " << fetcher->GetResponseCode();
+
+    bool success = fetcher->GetResponseCode() == 200;
+    callback_it->second.Run(success);
+
+    delete callback_it->first;
+    upload_callbacks_.erase(callback_it);
+  }
+
+ private:
+  using DomainReliabilityUploader::UploadCallback;
+  typedef std::map<const net::URLFetcher*, UploadCallback> UploadCallbackMap;
+
+  scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
+  UploadCallbackMap upload_callbacks_;
+};
+
+}  // namespace
+
+DomainReliabilityUploader::DomainReliabilityUploader() {}
+
+DomainReliabilityUploader::~DomainReliabilityUploader() {}
+
+// static
+scoped_ptr<DomainReliabilityUploader> DomainReliabilityUploader::Create(
+    scoped_refptr<net::URLRequestContextGetter> url_request_context_getter) {
+  return scoped_ptr<DomainReliabilityUploader>(
+      new DomainReliabilityUploaderImpl(url_request_context_getter));
+}
+
+}  // namespace domain_reliability
diff --git a/components/domain_reliability/uploader.h b/components/domain_reliability/uploader.h
new file mode 100644
index 0000000..c99cb62
--- /dev/null
+++ b/components/domain_reliability/uploader.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DOMAIN_RELIABILITY_UPLOADER_H_
+#define COMPONENTS_DOMAIN_RELIABILITY_UPLOADER_H_
+
+#include <map>
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "components/domain_reliability/domain_reliability_export.h"
+#include "url/gurl.h"
+
+namespace net {
+class URLFetcher;
+class URLRequestContextGetter;
+}  // namespace net
+
+namespace domain_reliability {
+
+class DOMAIN_RELIABILITY_EXPORT DomainReliabilityUploader {
+ public:
+  typedef base::Callback<void(bool success)> UploadCallback;
+
+  DomainReliabilityUploader();
+  virtual ~DomainReliabilityUploader();
+
+  static scoped_ptr<DomainReliabilityUploader> Create(
+      scoped_refptr<net::URLRequestContextGetter> url_request_context_getter);
+
+  virtual void UploadReport(const std::string& report_json,
+                            const GURL& upload_url,
+                            const UploadCallback& callback) = 0;
+};
+
+}  // namespace domain_reliability
+
+#endif  // COMPONENTS_DOMAIN_RELIABILITY_UPLOADER_H_
diff --git a/components/domain_reliability/uploader_unittest.cc b/components/domain_reliability/uploader_unittest.cc
new file mode 100644
index 0000000..e9614a4
--- /dev/null
+++ b/components/domain_reliability/uploader_unittest.cc
@@ -0,0 +1,106 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/domain_reliability/uploader.h"
+
+#include <map>
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "components/domain_reliability/test_util.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/url_request/test_url_fetcher_factory.h"
+#include "net/url_request/url_fetcher_delegate.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace domain_reliability {
+
+class DomainReliabilityUploaderTest : public testing::Test {
+ protected:
+  DomainReliabilityUploaderTest()
+      : test_browser_thread_bundle_(
+            content::TestBrowserThreadBundle::IO_MAINLOOP),
+        url_request_context_getter_(new net::TestURLRequestContextGetter(
+            base::MessageLoopProxy::current())),
+        uploader_(DomainReliabilityUploader::Create(
+            url_request_context_getter_)) {}
+
+  DomainReliabilityUploader::UploadCallback MakeUploadCallback(int index) {
+    return base::Bind(&DomainReliabilityUploaderTest::OnUploadComplete,
+                      base::Unretained(this),
+                      index);
+  }
+
+  void OnUploadComplete(int index, bool success) {
+    EXPECT_FALSE(upload_complete_[index]);
+    upload_complete_[index] = true;
+    upload_successful_[index] = success;
+  }
+
+  content::TestBrowserThreadBundle test_browser_thread_bundle_;
+  net::TestURLFetcherFactory url_fetcher_factory_;
+  scoped_refptr<net::TestURLRequestContextGetter> url_request_context_getter_;
+  scoped_ptr<DomainReliabilityUploader> uploader_;
+
+  std::map<int, bool> upload_complete_;
+  std::map<int, bool> upload_successful_;
+};
+
+TEST_F(DomainReliabilityUploaderTest, Create) {
+  net::TestURLFetcher* fetcher;
+
+  fetcher = url_fetcher_factory_.GetFetcherByID(0);
+  EXPECT_FALSE(fetcher);
+}
+
+TEST_F(DomainReliabilityUploaderTest, SuccessfulUpload) {
+  net::TestURLFetcher* fetcher;
+
+  std::string report_json = "{}";
+  GURL upload_url = GURL("https://test.example/upload");
+  uploader_->UploadReport(report_json, upload_url, MakeUploadCallback(0));
+
+  fetcher = url_fetcher_factory_.GetFetcherByID(0);
+  EXPECT_TRUE(fetcher);
+  EXPECT_EQ(report_json, fetcher->upload_data());
+  EXPECT_EQ(upload_url, fetcher->GetOriginalURL());
+
+  fetcher->set_url(upload_url);
+  fetcher->set_status(net::URLRequestStatus());
+  fetcher->set_response_code(200);
+  fetcher->SetResponseString("");
+
+  EXPECT_FALSE(upload_complete_[0]);
+  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  EXPECT_TRUE(upload_complete_[0]);
+  EXPECT_TRUE(upload_successful_[0]);
+}
+
+TEST_F(DomainReliabilityUploaderTest, FailedUpload) {
+  net::TestURLFetcher* fetcher;
+
+  std::string report_json = "{}";
+  GURL upload_url = GURL("https://test.example/upload");
+  uploader_->UploadReport(report_json, upload_url, MakeUploadCallback(0));
+
+  fetcher = url_fetcher_factory_.GetFetcherByID(0);
+  EXPECT_TRUE(fetcher);
+  EXPECT_EQ(report_json, fetcher->upload_data());
+  EXPECT_EQ(upload_url, fetcher->GetOriginalURL());
+
+  fetcher->set_url(upload_url);
+  fetcher->set_status(net::URLRequestStatus());
+  fetcher->set_response_code(500);
+  fetcher->SetResponseString("");
+
+  EXPECT_FALSE(upload_complete_[0]);
+  fetcher->delegate()->OnURLFetchComplete(fetcher);
+  EXPECT_TRUE(upload_complete_[0]);
+  EXPECT_FALSE(upload_successful_[0]);
+}
+
+}  // namespace domain_reliability
diff --git a/components/domain_reliability/util.cc b/components/domain_reliability/util.cc
index 75164d5..c88031f 100644
--- a/components/domain_reliability/util.cc
+++ b/components/domain_reliability/util.cc
@@ -22,6 +22,7 @@
   ActualTimer() : base_timer_(false, false) {}
   virtual ~ActualTimer() {}
 
+  // MockableTime::Timer implementation:
   virtual void Start(const tracked_objects::Location& posted_from,
                      base::TimeDelta delay,
                      const base::Closure& user_task) OVERRIDE {
diff --git a/components/domain_reliability/util.h b/components/domain_reliability/util.h
index 2603d8d..7ac84d9 100644
--- a/components/domain_reliability/util.h
+++ b/components/domain_reliability/util.h
@@ -65,6 +65,7 @@
   ActualTime();
   virtual ~ActualTime();
 
+  // MockableTime implementation:
   virtual base::TimeTicks Now() OVERRIDE;
   virtual scoped_ptr<MockableTime::Timer> CreateTimer() OVERRIDE;
 };
diff --git a/components/json_schema.gypi b/components/json_schema.gypi
index fd1675d..fdafc98 100644
--- a/components/json_schema.gypi
+++ b/components/json_schema.gypi
@@ -9,6 +9,7 @@
       'type': 'static_library',
       'dependencies': [
         '../base/base.gyp:base',
+        '../third_party/re2/re2.gyp:re2'
       ],
       'include_dirs': [
         '..',
diff --git a/components/json_schema/DEPS b/components/json_schema/DEPS
index e7cf2c6..62035fb 100644
--- a/components/json_schema/DEPS
+++ b/components/json_schema/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  "+third_party/re2",
   "+ui/base",
 ]
diff --git a/components/json_schema/json_schema_validator.cc b/components/json_schema/json_schema_validator.cc
index 18558d0..1899ad6 100644
--- a/components/json_schema/json_schema_validator.cc
+++ b/components/json_schema/json_schema_validator.cc
@@ -7,13 +7,17 @@
 #include <algorithm>
 #include <cfloat>
 #include <cmath>
+#include <vector>
 
 #include "base/json/json_reader.h"
+#include "base/logging.h"
+#include "base/memory/scoped_vector.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
 #include "components/json_schema/json_schema_constants.h"
+#include "third_party/re2/re2/re2.h"
 
 namespace schema = json_schema_constants;
 
@@ -86,6 +90,8 @@
     { schema::kMinLength,               base::Value::TYPE_INTEGER     },
     { schema::kMinimum,                 base::Value::TYPE_DOUBLE      },
     { schema::kOptional,                base::Value::TYPE_BOOLEAN     },
+    { schema::kPattern,                 base::Value::TYPE_STRING      },
+    { schema::kPatternProperties,       base::Value::TYPE_DICTIONARY  },
     { schema::kProperties,              base::Value::TYPE_DICTIONARY  },
     { schema::kTitle,                   base::Value::TYPE_STRING      },
   };
@@ -186,10 +192,29 @@
     // Validate the "properties" attribute. Each entry maps a key to a schema.
     if (it.key() == schema::kProperties) {
       it.value().GetAsDictionary(&dictionary_value);
-      for (base::DictionaryValue::Iterator it(*dictionary_value);
-           !it.IsAtEnd(); it.Advance()) {
-        if (!it.value().GetAsDictionary(&dictionary_value)) {
-          *error = "Invalid value for properties attribute";
+      for (base::DictionaryValue::Iterator iter(*dictionary_value);
+           !iter.IsAtEnd(); iter.Advance()) {
+        if (!iter.value().GetAsDictionary(&dictionary_value)) {
+          *error = "properties must be a dictionary";
+          return false;
+        }
+        if (!IsValidSchema(dictionary_value, options, error)) {
+          DCHECK(!error->empty());
+          return false;
+        }
+      }
+    }
+
+    // Validate the "patternProperties" attribute. Each entry maps a regular
+    // expression to a schema. The validity of the regular expression expression
+    // won't be checked here for performance reasons. Instead, invalid regular
+    // expressions will be caught as validation errors in Validate().
+    if (it.key() == schema::kPatternProperties) {
+      it.value().GetAsDictionary(&dictionary_value);
+      for (base::DictionaryValue::Iterator iter(*dictionary_value);
+           !iter.IsAtEnd(); iter.Advance()) {
+        if (!iter.value().GetAsDictionary(&dictionary_value)) {
+          *error = "patternProperties must be a dictionary";
           return false;
         }
         if (!IsValidSchema(dictionary_value, options, error)) {
@@ -308,6 +333,8 @@
     "Expected '*' but got '*'.";
 const char JSONSchemaValidator::kInvalidTypeIntegerNumber[] =
     "Expected 'integer' but got 'number', consider using Math.round().";
+const char JSONSchemaValidator::kInvalidRegex[] =
+    "Regular expression /*/ is invalid: *";
 
 
 // static
@@ -551,8 +578,7 @@
                                          const base::DictionaryValue* schema,
                                          const std::string& path) {
   const base::DictionaryValue* properties = NULL;
-  schema->GetDictionary(schema::kProperties, &properties);
-  if (properties) {
+  if (schema->GetDictionary(schema::kProperties, &properties)) {
     for (base::DictionaryValue::Iterator it(*properties); !it.IsAtEnd();
          it.Advance()) {
       std::string prop_path = path.empty() ? it.key() : (path + "." + it.key());
@@ -575,16 +601,52 @@
   }
 
   const base::DictionaryValue* additional_properties_schema = NULL;
-  if (SchemaAllowsAnyAdditionalItems(schema, &additional_properties_schema))
-    return;
+  bool allow_any_additional_properties =
+      SchemaAllowsAnyAdditionalItems(schema, &additional_properties_schema);
 
-  // Validate additional properties.
+  const base::DictionaryValue* pattern_properties = NULL;
+  ScopedVector<re2::RE2> pattern_properties_pattern;
+  std::vector<const base::DictionaryValue*> pattern_properties_schema;
+
+  if (schema->GetDictionary(schema::kPatternProperties, &pattern_properties)) {
+    for (base::DictionaryValue::Iterator it(*pattern_properties); !it.IsAtEnd();
+         it.Advance()) {
+      re2::RE2* prop_pattern = new re2::RE2(it.key());
+      if (!prop_pattern->ok()) {
+        LOG(WARNING) << "Regular expression /" << it.key()
+                     << "/ is invalid: " << prop_pattern->error() << ".";
+        errors_.push_back(
+            Error(path,
+                  FormatErrorMessage(
+                      kInvalidRegex, it.key(), prop_pattern->error())));
+        continue;
+      }
+      const base::DictionaryValue* prop_schema = NULL;
+      CHECK(it.value().GetAsDictionary(&prop_schema));
+      pattern_properties_pattern.push_back(prop_pattern);
+      pattern_properties_schema.push_back(prop_schema);
+    }
+  }
+
+  // Validate pattern properties and additional properties.
   for (base::DictionaryValue::Iterator it(*instance); !it.IsAtEnd();
        it.Advance()) {
-    if (properties && properties->HasKey(it.key()))
+    std::string prop_path = path.empty() ? it.key() : path + "." + it.key();
+
+    bool found_matching_pattern = false;
+    for (size_t index = 0; index < pattern_properties_pattern.size(); ++index) {
+      if (re2::RE2::PartialMatch(it.key(),
+                                 *pattern_properties_pattern[index])) {
+        found_matching_pattern = true;
+        Validate(&it.value(), pattern_properties_schema[index], prop_path);
+        break;
+      }
+    }
+
+    if (found_matching_pattern || allow_any_additional_properties ||
+        (properties && properties->HasKey(it.key())))
       continue;
 
-    std::string prop_path = path.empty() ? it.key() : path + "." + it.key();
     if (!additional_properties_schema) {
       errors_.push_back(Error(prop_path, kUnexpectedProperty));
     } else {
@@ -707,7 +769,20 @@
     }
   }
 
-  CHECK(!schema->HasKey(schema::kPattern)) << "Pattern is not supported.";
+  std::string pattern;
+  if (schema->GetString(schema::kPattern, &pattern)) {
+    re2::RE2 compiled_regex(pattern);
+    if (!compiled_regex.ok()) {
+      LOG(WARNING) << "Regular expression /" << pattern
+                   << "/ is invalid: " << compiled_regex.error() << ".";
+      errors_.push_back(Error(
+          path,
+          FormatErrorMessage(kInvalidRegex, pattern, compiled_regex.error())));
+    } else if (!re2::RE2::PartialMatch(value, compiled_regex)) {
+      errors_.push_back(
+          Error(path, FormatErrorMessage(kStringPattern, pattern)));
+    }
+  }
 }
 
 void JSONSchemaValidator::ValidateNumber(const base::Value* instance,
diff --git a/components/json_schema/json_schema_validator.h b/components/json_schema/json_schema_validator.h
index 4e8acad..ad429ef 100644
--- a/components/json_schema/json_schema_validator.h
+++ b/components/json_schema/json_schema_validator.h
@@ -32,7 +32,6 @@
 // - disallow
 // - union types (but replaced with 'choices')
 // - number.maxDecimal
-// - string.pattern
 //
 // The following properties are not applicable to the interface exposed by
 // this class:
@@ -52,6 +51,8 @@
 // - by default an "object" typed schema does not allow additional properties.
 //   if present, "additionalProperties" is to be a schema against which all
 //   additional properties will be validated.
+// - regular expression supports all syntaxes that re2 accepts.
+//   See https://code.google.com/p/re2/wiki/Syntax for details.
 //==============================================================================
 class JSONSchemaValidator {
  public:
@@ -92,6 +93,7 @@
   static const char kNumberMaximum[];
   static const char kInvalidType[];
   static const char kInvalidTypeIntegerNumber[];
+  static const char kInvalidRegex[];
 
   // Classifies a Value as one of the JSON schema primitive types.
   static std::string GetJSONSchemaType(const base::Value* value);
@@ -110,6 +112,10 @@
   // and that DictionaryValue can be used to build a JSONSchemaValidator.
   // Returns the parsed DictionaryValue when |schema| validated, otherwise
   // returns NULL. In that case, |error| contains an error description.
+  // For performance reasons, currently IsValidSchema() won't check the
+  // correctness of regular expressions used in "pattern" and
+  // "patternProperties" and in Validate() invalid regular expression don't
+  // accept any strings.
   static scoped_ptr<base::DictionaryValue> IsValidSchema(
       const std::string& schema,
       std::string* error);
diff --git a/components/json_schema/json_schema_validator_unittest.cc b/components/json_schema/json_schema_validator_unittest.cc
index 73809de..aaa2555 100644
--- a/components/json_schema/json_schema_validator_unittest.cc
+++ b/components/json_schema/json_schema_validator_unittest.cc
@@ -9,9 +9,7 @@
 
 class JSONSchemaValidatorCPPTest : public JSONSchemaValidatorTestBase {
  public:
-  JSONSchemaValidatorCPPTest()
-      : JSONSchemaValidatorTestBase(JSONSchemaValidatorTestBase::CPP) {
-  }
+  JSONSchemaValidatorCPPTest() : JSONSchemaValidatorTestBase() {}
 
  protected:
   virtual void ExpectValid(const std::string& test_source,
@@ -134,6 +132,19 @@
   EXPECT_TRUE(JSONSchemaValidator::IsValidSchema(
       "{"
       "  \"type\": \"object\","
+      "  \"patternProperties\": {"
+      "    \".\": { \"type\": \"any\" },"
+      "    \"foo\": { \"type\": \"any\" },"
+      "    \"^foo$\": { \"type\": \"any\" },"
+      "    \"foo+\": { \"type\": \"any\" },"
+      "    \"foo?\": { \"type\": \"any\" },"
+      "    \"fo{2,4}\": { \"type\": \"any\" },"
+      "    \"(left)|(right)\": { \"type\": \"any\" }"
+      "  }"
+      "}", &error)) << error;
+  EXPECT_TRUE(JSONSchemaValidator::IsValidSchema(
+      "{"
+      "  \"type\": \"object\","
       "  \"unknown attribute\": \"that should just be ignored\""
       "}",
       JSONSchemaValidator::OPTIONS_IGNORE_UNKNOWN_ATTRIBUTES,
diff --git a/components/json_schema/json_schema_validator_unittest_base.cc b/components/json_schema/json_schema_validator_unittest_base.cc
index 2e936a2..5c9f1a5 100644
--- a/components/json_schema/json_schema_validator_unittest_base.cc
+++ b/components/json_schema/json_schema_validator_unittest_base.cc
@@ -67,9 +67,7 @@
 }  // namespace
 
 
-JSONSchemaValidatorTestBase::JSONSchemaValidatorTestBase(
-    JSONSchemaValidatorTestBase::ValidatorType type)
-    : type_(type) {
+JSONSchemaValidatorTestBase::JSONSchemaValidatorTestBase() {
 }
 
 void JSONSchemaValidatorTestBase::RunTests() {
@@ -118,10 +116,6 @@
 }
 
 void JSONSchemaValidatorTestBase::TestStringPattern() {
-  // Regex patterns not supported in CPP validator.
-  if (type_ == CPP)
-    return;
-
   scoped_ptr<base::DictionaryValue> schema(new base::DictionaryValue());
   schema->SetString(schema::kType, schema::kString);
   schema->SetString(schema::kPattern, "foo+");
@@ -224,8 +218,8 @@
   instance->SetBoolean("extra", true);
   ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL,
                  "extra", JSONSchemaValidator::kUnexpectedProperty);
-
   instance->Remove("extra", NULL);
+
   instance->Remove("bar", NULL);
   ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, "bar",
                  JSONSchemaValidator::kObjectPropertyIsRequired);
@@ -236,12 +230,47 @@
                      JSONSchemaValidator::kInvalidType,
                      schema::kInteger,
                      schema::kString));
+  instance->SetInteger("bar", 42);
 
+  // Test "patternProperties".
+  instance->SetInteger("extra", 42);
+  ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL,
+                 "extra", JSONSchemaValidator::kUnexpectedProperty);
+  schema->SetString("patternProperties.extra+.type",
+                    schema::kInteger);
+  ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
+  instance->Remove("extra", NULL);
+  instance->SetInteger("extraaa", 42);
+  ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
+  instance->Remove("extraaa", NULL);
+  instance->SetInteger("extr", 42);
+  ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL,
+                 "extr", JSONSchemaValidator::kUnexpectedProperty);
+  instance->Remove("extr", NULL);
+  schema->Remove(schema::kPatternProperties, NULL);
+
+  // Test "patternProperties" and "properties" schemas are both checked if
+  // applicable.
+  schema->SetString("patternProperties.fo+.type", schema::kInteger);
+  ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, "foo",
+                 JSONSchemaValidator::FormatErrorMessage(
+                     JSONSchemaValidator::kInvalidType,
+                     schema::kInteger,
+                     schema::kString));
+  instance->SetInteger("foo", 123);
+  ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL, "foo",
+                 JSONSchemaValidator::FormatErrorMessage(
+                     JSONSchemaValidator::kInvalidType,
+                     schema::kString,
+                     schema::kInteger));
+  instance->SetString("foo", "foo");
+  schema->Remove(schema::kPatternProperties, NULL);
+
+  // Test additional properties.
   base::DictionaryValue* additional_properties = new base::DictionaryValue();
   additional_properties->SetString(schema::kType, schema::kAny);
   schema->Set(schema::kAdditionalProperties, additional_properties);
 
-  instance->SetInteger("bar", 42);
   instance->SetBoolean("extra", true);
   ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
 
@@ -258,6 +287,7 @@
                      JSONSchemaValidator::kInvalidType,
                      schema::kBoolean,
                      schema::kString));
+  instance->Remove("extra", NULL);
 
   base::DictionaryValue* properties = NULL;
   base::DictionaryValue* bar_property = NULL;
@@ -265,7 +295,6 @@
   ASSERT_TRUE(properties->GetDictionary("bar", &bar_property));
 
   bar_property->SetBoolean(schema::kOptional, true);
-  instance->Remove("extra", NULL);
   ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
   instance->Remove("bar", NULL);
   ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
@@ -281,6 +310,18 @@
                      JSONSchemaValidator::kInvalidType,
                      schema::kInteger,
                      schema::kString));
+
+  // Verify that JSON parser handles dot in "patternProperties" well.
+  schema.reset(LoadDictionary("pattern_properties_dot.json"));
+  ASSERT_TRUE(schema->GetDictionary(schema::kPatternProperties, &properties));
+  ASSERT_TRUE(properties->HasKey("^.$"));
+
+  instance.reset(new base::DictionaryValue());
+  instance->SetString("a", "whatever");
+  ExpectValid(TEST_SOURCE, instance.get(), schema.get(), NULL);
+  instance->SetString("foo", "bar");
+  ExpectNotValid(TEST_SOURCE, instance.get(), schema.get(), NULL,
+                 "foo", JSONSchemaValidator::kUnexpectedProperty);
 }
 
 void JSONSchemaValidatorTestBase::TestTypeReference() {
diff --git a/components/json_schema/json_schema_validator_unittest_base.h b/components/json_schema/json_schema_validator_unittest_base.h
index 7b4854e..4edb994 100644
--- a/components/json_schema/json_schema_validator_unittest_base.h
+++ b/components/json_schema/json_schema_validator_unittest_base.h
@@ -20,12 +20,7 @@
 // JSONSchemaValidatorJSTest that inherits from this.
 class JSONSchemaValidatorTestBase : public testing::Test {
  public:
-  enum ValidatorType {
-    CPP = 1,
-    JS = 2
-  };
-
-  explicit JSONSchemaValidatorTestBase(ValidatorType type);
+  JSONSchemaValidatorTestBase();
 
   void RunTests();
 
@@ -56,8 +51,6 @@
   void TestNumber();
   void TestTypeClassifier();
   void TestTypes();
-
-  ValidatorType type_;
 };
 
 #endif  // COMPONENTS_JSON_SCHEMA_JSON_SCHEMA_VALIDATOR_UNITTEST_BASE_H_
diff --git a/components/nacl.gyp b/components/nacl.gyp
index 9cf8d92..3194b0a 100644
--- a/components/nacl.gyp
+++ b/components/nacl.gyp
@@ -142,6 +142,8 @@
           'target_name': 'nacl_renderer',
           'type': 'static_library',
           'sources': [
+            'nacl/renderer/nexe_load_manager.cc',
+            'nacl/renderer/nexe_load_manager.h',
             'nacl/renderer/pnacl_translation_resource_host.cc',
             'nacl/renderer/pnacl_translation_resource_host.h',
             'nacl/renderer/ppb_nacl_private_impl.cc',
diff --git a/components/nacl/browser/nacl_host_message_filter.cc b/components/nacl/browser/nacl_host_message_filter.cc
index 9e85266..9389b70 100644
--- a/components/nacl/browser/nacl_host_message_filter.cc
+++ b/components/nacl/browser/nacl_host_message_filter.cc
@@ -57,6 +57,8 @@
                                     OnOpenNaClExecutable)
     IPC_MESSAGE_HANDLER(NaClHostMsg_NaClGetNumProcessors,
                         OnNaClGetNumProcessors)
+    IPC_MESSAGE_HANDLER(NaClHostMsg_NaClDebugEnabledForURL,
+                        OnNaClDebugEnabledForURL)
 #endif
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
@@ -181,4 +183,10 @@
                                      reply_msg);
 }
 
+void NaClHostMessageFilter::OnNaClDebugEnabledForURL(const GURL& nmf_url,
+                                                     bool* should_debug) {
+  *should_debug =
+      nacl::NaClBrowser::GetDelegate()->URLMatchesDebugPatterns(nmf_url);
+}
+
 }  // namespace nacl
diff --git a/components/nacl/browser/nacl_host_message_filter.h b/components/nacl/browser/nacl_host_message_filter.h
index c7bf900..3dc4b45 100644
--- a/components/nacl/browser/nacl_host_message_filter.h
+++ b/components/nacl/browser/nacl_host_message_filter.h
@@ -67,6 +67,8 @@
   void AsyncReturnTemporaryFile(int pp_instance,
                                 base::PlatformFile fd,
                                 bool is_hit);
+  void OnNaClDebugEnabledForURL(const GURL& nmf_url, bool* should_debug);
+
   int render_process_id_;
 
   // off_the_record_ is copied from the profile partly so that it can be
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index 23a76b5..1316974 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -49,10 +49,11 @@
 #include "ppapi/host/host_factory.h"
 #include "ppapi/host/ppapi_host.h"
 #include "ppapi/proxy/ppapi_messages.h"
+#include "ppapi/shared_impl/ppapi_constants.h"
 #include "ppapi/shared_impl/ppapi_nacl_plugin_args.h"
-#include "ppapi/shared_impl/ppapi_switches.h"
 
 #if defined(OS_POSIX)
+
 #include <fcntl.h>
 
 #include "ipc/ipc_channel_posix.h"
@@ -251,6 +252,9 @@
 
 // -----------------------------------------------------------------------------
 
+unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ =
+    ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds;
+
 NaClProcessHost::NaClProcessHost(const GURL& manifest_url,
                                  int render_view_id,
                                  uint32 permission_bits,
@@ -372,6 +376,12 @@
   NaClBrowser::GetDelegate()->SetDebugPatterns(nacl_debug_mask);
 }
 
+// static
+void NaClProcessHost::SetPpapiKeepAliveThrottleForTesting(
+    unsigned milliseconds) {
+  keepalive_throttle_interval_milliseconds_ = milliseconds;
+}
+
 void NaClProcessHost::Launch(
     NaClHostMessageFilter* nacl_host_message_filter,
     IPC::Message* reply_msg,
@@ -871,10 +881,11 @@
     ppapi::PpapiNaClPluginArgs args;
     args.off_the_record = nacl_host_message_filter_->off_the_record();
     args.permissions = permissions_;
+    args.keepalive_throttle_interval_milliseconds =
+        keepalive_throttle_interval_milliseconds_;
     CommandLine* cmdline = CommandLine::ForCurrentProcess();
     DCHECK(cmdline);
     std::string flag_whitelist[] = {
-      switches::kPpapiKeepAliveThrottle,
       switches::kV,
       switches::kVModule,
     };
diff --git a/components/nacl/browser/nacl_process_host.h b/components/nacl/browser/nacl_process_host.h
index 758f708..370599d 100644
--- a/components/nacl/browser/nacl_process_host.h
+++ b/components/nacl/browser/nacl_process_host.h
@@ -76,6 +76,9 @@
   // Do any minimal work that must be done at browser startup.
   static void EarlyStartup();
 
+  // Specifies throttling time in milliseconds for PpapiHostMsg_Keepalive IPCs.
+  static void SetPpapiKeepAliveThrottleForTesting(unsigned milliseconds);
+
   // Initialize the new NaCl process. Result is returned by sending ipc
   // message reply_msg.
   void Launch(NaClHostMessageFilter* nacl_host_message_filter,
@@ -218,6 +221,9 @@
 
   int render_view_id_;
 
+  // Throttling time in milliseconds for PpapiHostMsg_Keepalive IPCs.
+  static unsigned keepalive_throttle_interval_milliseconds_;
+
   DISALLOW_COPY_AND_ASSIGN(NaClProcessHost);
 };
 
diff --git a/components/nacl/common/nacl_host_messages.h b/components/nacl/common/nacl_host_messages.h
index 3a1e447..da7478b 100644
--- a/components/nacl/common/nacl_host_messages.h
+++ b/components/nacl/common/nacl_host_messages.h
@@ -104,5 +104,14 @@
                             uint64 /* file_token_lo */,
                             uint64 /* file_token_hi */)
 
+// A renderer sends this to the browser process to determine how many
+// processors are online.
 IPC_SYNC_MESSAGE_CONTROL0_1(NaClHostMsg_NaClGetNumProcessors,
                             int /* Number of processors */)
+
+// A renderer sends this to the browser process to determine if the
+// NaCl application started from the given NMF URL will be debugged.
+// If not (filtered out by commandline flags), it sets should_debug to false.
+IPC_SYNC_MESSAGE_CONTROL1_1(NaClHostMsg_NaClDebugEnabledForURL,
+                            GURL /* alleged URL of NMF file */,
+                            bool /* should debug */)
diff --git a/components/nacl/renderer/nexe_load_manager.cc b/components/nacl/renderer/nexe_load_manager.cc
new file mode 100644
index 0000000..2fc7c53
--- /dev/null
+++ b/components/nacl/renderer/nexe_load_manager.cc
@@ -0,0 +1,215 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/nacl/renderer/nexe_load_manager.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "components/nacl/common/nacl_host_messages.h"
+#include "components/nacl/common/nacl_types.h"
+#include "components/nacl/renderer/pnacl_translation_resource_host.h"
+#include "components/nacl/renderer/trusted_plugin_channel.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/sandbox_init.h"
+#include "content/public/renderer/pepper_plugin_instance.h"
+#include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/private/pp_file_handle.h"
+#include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/ppapi_permissions.h"
+#include "ppapi/shared_impl/ppapi_preferences.h"
+#include "ppapi/shared_impl/var.h"
+#include "ppapi/thunk/enter.h"
+#include "third_party/WebKit/public/web/WebDOMResourceProgressEvent.h"
+#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebPluginContainer.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "v8/include/v8.h"
+
+namespace {
+
+void HistogramEnumerate(const std::string& name,
+                        int32_t sample,
+                        int32_t boundary_value) {
+  base::HistogramBase* counter =
+      base::LinearHistogram::FactoryGet(
+          name,
+          1,
+          boundary_value,
+          boundary_value + 1,
+          base::HistogramBase::kUmaTargetedHistogramFlag);
+  counter->Add(sample);
+}
+
+blink::WebString EventTypeToString(PP_NaClEventType event_type) {
+  switch (event_type) {
+    case PP_NACL_EVENT_LOADSTART:
+      return blink::WebString::fromUTF8("loadstart");
+    case PP_NACL_EVENT_PROGRESS:
+      return blink::WebString::fromUTF8("progress");
+    case PP_NACL_EVENT_ERROR:
+      return blink::WebString::fromUTF8("error");
+    case PP_NACL_EVENT_ABORT:
+      return blink::WebString::fromUTF8("abort");
+    case PP_NACL_EVENT_LOAD:
+      return blink::WebString::fromUTF8("load");
+    case PP_NACL_EVENT_LOADEND:
+      return blink::WebString::fromUTF8("loadend");
+    case PP_NACL_EVENT_CRASH:
+      return blink::WebString::fromUTF8("crash");
+  }
+  NOTIMPLEMENTED();
+  return blink::WebString();
+}
+
+static int GetRoutingID(PP_Instance instance) {
+  // Check that we are on the main renderer thread.
+  DCHECK(content::RenderThread::Get());
+  content::RendererPpapiHost *host =
+      content::RendererPpapiHost::GetForPPInstance(instance);
+  if (!host)
+    return 0;
+  return host->GetRoutingIDForWidget(instance);
+}
+
+}  // namespace
+
+namespace nacl {
+
+NexeLoadManager::NexeLoadManager(
+    PP_Instance pp_instance)
+    : pp_instance_(pp_instance),
+      nacl_ready_state_(PP_NACL_READY_STATE_UNSENT),
+      nexe_error_reported_(false),
+      plugin_instance_(content::PepperPluginInstance::Get(pp_instance)),
+      weak_factory_(this) {
+}
+
+NexeLoadManager::~NexeLoadManager() {
+}
+
+void NexeLoadManager::ReportLoadError(PP_NaClError error,
+                                      const std::string& error_message,
+                                      const std::string& console_message) {
+  // Check that we are on the main renderer thread.
+  DCHECK(content::RenderThread::Get());
+
+  if (error == PP_NACL_ERROR_MANIFEST_PROGRAM_MISSING_ARCH) {
+    // A special case: the manifest may otherwise be valid but is missing
+    // a program/file compatible with the user's sandbox.
+    IPC::Sender* sender = content::RenderThread::Get();
+    sender->Send(
+        new NaClHostMsg_MissingArchError(GetRoutingID(pp_instance_)));
+  }
+  set_nacl_ready_state(PP_NACL_READY_STATE_DONE);
+  nexe_error_reported_ = true;
+
+  // We must set all properties before calling DispatchEvent so that when an
+  // event handler runs, the properties reflect the current load state.
+  std::string error_string = std::string("NaCl module load failed: ") +
+      std::string(error_message);
+  plugin_instance_->SetEmbedProperty(
+      ppapi::StringVar::StringToPPVar("lastError"),
+      ppapi::StringVar::StringToPPVar(error_string));
+
+  // Inform JavaScript that loading encountered an error and is complete.
+  ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
+      FROM_HERE,
+      base::Bind(&NexeLoadManager::DispatchEvent,
+                 weak_factory_.GetWeakPtr(),
+                 ProgressEvent(PP_NACL_EVENT_ERROR)));
+
+  ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
+      FROM_HERE,
+      base::Bind(&NexeLoadManager::DispatchEvent,
+                 weak_factory_.GetWeakPtr(),
+                 ProgressEvent(PP_NACL_EVENT_LOADEND)));
+
+  HistogramEnumerate("NaCl.LoadStatus.Plugin", error,
+                     PP_NACL_ERROR_MAX);
+  std::string uma_name = is_installed_ ?
+                         "NaCl.LoadStatus.Plugin.InstalledApp" :
+                         "NaCl.LoadStatus.Plugin.NotInstalledApp";
+  HistogramEnumerate(uma_name, error, PP_NACL_ERROR_MAX);
+
+  LogToConsole(console_message);
+}
+
+void NexeLoadManager::DispatchEvent(const ProgressEvent &event) {
+  blink::WebPluginContainer* container = plugin_instance_->GetContainer();
+  // It's possible that container() is NULL if the plugin has been removed from
+  // the DOM (but the PluginInstance is not destroyed yet).
+  if (!container)
+    return;
+  blink::WebFrame* frame = container->element().document().frame();
+  if (!frame)
+    return;
+  v8::HandleScope handle_scope(plugin_instance_->GetIsolate());
+  v8::Local<v8::Context> context(
+      plugin_instance_->GetIsolate()->GetCurrentContext());
+  if (context.IsEmpty()) {
+    // If there's no JavaScript on the stack, we have to make a new Context.
+    context = v8::Context::New(plugin_instance_->GetIsolate());
+  }
+  v8::Context::Scope context_scope(context);
+
+  if (!event.resource_url.empty()) {
+    blink::WebString url_string = blink::WebString::fromUTF8(
+        event.resource_url.data(), event.resource_url.size());
+    blink::WebDOMResourceProgressEvent blink_event(
+        EventTypeToString(event.event_type),
+        event.length_is_computable,
+        event.loaded_bytes,
+        event.total_bytes,
+        url_string);
+    container->element().dispatchEvent(blink_event);
+  } else {
+    blink::WebDOMProgressEvent blink_event(EventTypeToString(event.event_type),
+                                           event.length_is_computable,
+                                           event.loaded_bytes,
+                                           event.total_bytes);
+    container->element().dispatchEvent(blink_event);
+  }
+}
+
+void NexeLoadManager::set_trusted_plugin_channel(
+    scoped_ptr<TrustedPluginChannel> channel) {
+  trusted_plugin_channel_ = channel.Pass();
+}
+
+bool NexeLoadManager::nexe_error_reported() {
+  return nexe_error_reported_;
+}
+
+void NexeLoadManager::set_nexe_error_reported(bool error_reported) {
+  nexe_error_reported_ = error_reported;
+}
+
+PP_NaClReadyState NexeLoadManager::nacl_ready_state() {
+  return nacl_ready_state_;
+}
+
+void NexeLoadManager::set_nacl_ready_state(PP_NaClReadyState ready_state) {
+  nacl_ready_state_ = ready_state;
+  SetReadOnlyProperty(ppapi::StringVar::StringToPPVar("readyState"),
+                      PP_MakeInt32(ready_state));
+}
+
+void NexeLoadManager::SetReadOnlyProperty(PP_Var key, PP_Var value) {
+  plugin_instance_->SetEmbedProperty(key, value);
+}
+
+void NexeLoadManager::LogToConsole(const std::string& message) {
+  ppapi::PpapiGlobals::Get()->LogWithSource(
+      pp_instance_, PP_LOGLEVEL_LOG, std::string("NativeClient"), message);
+}
+
+}  // namespace nacl
diff --git a/components/nacl/renderer/nexe_load_manager.h b/components/nacl/renderer/nexe_load_manager.h
new file mode 100644
index 0000000..a82c51b
--- /dev/null
+++ b/components/nacl/renderer/nexe_load_manager.h
@@ -0,0 +1,96 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_NACL_RENDERER_NEXE_LOAD_MANAGER_H_
+#define COMPONENTS_NACL_RENDERER_NEXE_LOAD_MANAGER_H_
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+
+#include "ppapi/c/private/ppb_nacl_private.h"
+
+namespace content {
+class PepperPluginInstance;
+}
+
+namespace nacl {
+
+class TrustedPluginChannel;
+
+// NexeLoadManager provides methods for reporting the progress of loading a
+// nexe.
+class NexeLoadManager {
+ public:
+  explicit NexeLoadManager(PP_Instance instance);
+  ~NexeLoadManager();
+
+  void ReportLoadError(PP_NaClError error,
+                       const std::string& error_message,
+                       const std::string& console_message);
+
+  // TODO(dmichael): Everything below this comment should eventually be made
+  // private, when ppb_nacl_private_impl.cc is no longer using them directly.
+  // The intent is for this class to only expose functions for reporting a
+  // load state transition (e.g., ReportLoadError, ReportProgress,
+  // ReportLoadAbort, etc.)
+  struct ProgressEvent {
+    explicit ProgressEvent(PP_NaClEventType event_type_param)
+        : event_type(event_type_param),
+          length_is_computable(false),
+          loaded_bytes(0),
+          total_bytes(0) {
+    }
+    PP_Instance instance;
+    PP_NaClEventType event_type;
+    std::string resource_url;
+    bool length_is_computable;
+    uint64_t loaded_bytes;
+    uint64_t total_bytes;
+  };
+  void DispatchEvent(const ProgressEvent &event);
+  void set_trusted_plugin_channel(scoped_ptr<TrustedPluginChannel> channel);
+
+  bool nexe_error_reported();
+  void set_nexe_error_reported(bool error_reported);
+
+  PP_NaClReadyState nacl_ready_state();
+  void set_nacl_ready_state(PP_NaClReadyState ready_state);
+
+  void SetReadOnlyProperty(PP_Var key, PP_Var value);
+  void LogToConsole(const std::string& message);
+
+  bool is_installed() { return is_installed_; }
+  void set_is_installed(bool installed) { is_installed_ = installed; }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NexeLoadManager);
+
+  PP_Instance pp_instance_;
+  PP_NaClReadyState nacl_ready_state_;
+  bool nexe_error_reported_;
+
+  // A flag indicating if the NaCl executable is being loaded from an installed
+  // application.  This flag is used to bucket UMA statistics more precisely to
+  // help determine whether nexe loading problems are caused by networking
+  // issues.  (Installed applications will be loaded from disk.)
+  // Unfortunately, the definition of what it means to be part of an installed
+  // application is a little murky - for example an installed application can
+  // register a mime handler that loads NaCl executables into an arbitrary web
+  // page.  As such, the flag actually means "our best guess, based on the URLs
+  // for NaCl resources that we have seen so far".
+  bool is_installed_;
+
+  // Non-owning.
+  content::PepperPluginInstance* plugin_instance_;
+
+  scoped_ptr<TrustedPluginChannel> trusted_plugin_channel_;
+  base::WeakPtrFactory<NexeLoadManager> weak_factory_;
+};
+
+}  // namespace nacl
+
+#endif  // COMPONENTS_NACL_RENDERER_NEXE_LOAD_MANAGER_H_
diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc
index 0875886..0e771b8 100644
--- a/components/nacl/renderer/ppb_nacl_private_impl.cc
+++ b/components/nacl/renderer/ppb_nacl_private_impl.cc
@@ -5,14 +5,15 @@
 #include "components/nacl/renderer/ppb_nacl_private_impl.h"
 
 #include "base/command_line.h"
+#include "base/containers/scoped_ptr_hash_map.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
-#include "base/metrics/histogram.h"
 #include "base/rand_util.h"
 #include "components/nacl/common/nacl_host_messages.h"
 #include "components/nacl/common/nacl_messages.h"
 #include "components/nacl/common/nacl_switches.h"
 #include "components/nacl/common/nacl_types.h"
+#include "components/nacl/renderer/nexe_load_manager.h"
 #include "components/nacl/renderer/pnacl_translation_resource_host.h"
 #include "components/nacl/renderer/sandbox_arch.h"
 #include "components/nacl/renderer/trusted_plugin_channel.h"
@@ -31,20 +32,9 @@
 #include "ppapi/shared_impl/ppapi_preferences.h"
 #include "ppapi/shared_impl/var.h"
 #include "ppapi/thunk/enter.h"
-#include "third_party/WebKit/public/web/WebDOMResourceProgressEvent.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebElement.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "url/gurl.h"
-#include "v8/include/v8.h"
 
 namespace {
 
-// Forward declare LogToConsole() we can use it in other functions here.
-void LogToConsole(PP_Instance instance, const char* message);
-
 base::LazyInstance<scoped_refptr<PnaclTranslationResourceHost> >
     g_pnacl_resource_host = LAZY_INSTANCE_INITIALIZER;
 
@@ -75,23 +65,18 @@
 base::LazyInstance<InstanceInfoMap> g_instance_info =
     LAZY_INSTANCE_INITIALIZER;
 
-typedef std::map<PP_Instance, nacl::TrustedPluginChannel*>
-    InstanceTrustedChannelMap;
+typedef base::ScopedPtrHashMap<PP_Instance, nacl::NexeLoadManager>
+    NexeLoadManagerMap;
 
-base::LazyInstance<InstanceTrustedChannelMap> g_channel_map =
+base::LazyInstance<NexeLoadManagerMap> g_load_manager_map =
     LAZY_INSTANCE_INITIALIZER;
 
-void HistogramEnumerate(const std::string& name,
-                        int32_t sample,
-                        int32_t boundary_value) {
-  base::HistogramBase* counter =
-      base::LinearHistogram::FactoryGet(
-          name,
-          1,
-          boundary_value,
-          boundary_value + 1,
-          base::HistogramBase::kUmaTargetedHistogramFlag);
-  counter->Add(sample);
+nacl::NexeLoadManager* GetNexeLoadManager(PP_Instance instance) {
+  NexeLoadManagerMap& map = g_load_manager_map.Get();
+  NexeLoadManagerMap::iterator iter = map.find(instance);
+  if (iter != map.end())
+    return iter->second;
+  return NULL;
 }
 
 static int GetRoutingID(PP_Instance instance) {
@@ -199,9 +184,16 @@
     invalid_handle = (launch_result.trusted_ipc_channel_handle.socket.fd == -1);
 #endif
   if (!invalid_handle) {
-    g_channel_map.Get()[instance] = new nacl::TrustedPluginChannel(
-        launch_result.trusted_ipc_channel_handle, callback,
-        content::RenderThread::Get()->GetShutdownEvent());
+    nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+    DCHECK(load_manager);
+    if (load_manager) {
+      scoped_ptr<nacl::TrustedPluginChannel> trusted_plugin_channel(
+          new nacl::TrustedPluginChannel(
+              launch_result.trusted_ipc_channel_handle,
+              callback,
+              content::RenderThread::Get()->GetShutdownEvent()));
+      load_manager->set_trusted_plugin_channel(trusted_plugin_channel.Pass());
+    }
   }
 
   *(static_cast<NaClHandle*>(imc_handle)) =
@@ -396,45 +388,12 @@
   return handle;
 }
 
-blink::WebString EventTypeToString(PP_NaClEventType event_type) {
-  switch (event_type) {
-    case PP_NACL_EVENT_LOADSTART:
-      return blink::WebString::fromUTF8("loadstart");
-    case PP_NACL_EVENT_PROGRESS:
-      return blink::WebString::fromUTF8("progress");
-    case PP_NACL_EVENT_ERROR:
-      return blink::WebString::fromUTF8("error");
-    case PP_NACL_EVENT_ABORT:
-      return blink::WebString::fromUTF8("abort");
-    case PP_NACL_EVENT_LOAD:
-      return blink::WebString::fromUTF8("load");
-    case PP_NACL_EVENT_LOADEND:
-      return blink::WebString::fromUTF8("loadend");
-    case PP_NACL_EVENT_CRASH:
-      return blink::WebString::fromUTF8("crash");
-  }
-  NOTIMPLEMENTED();
-  return blink::WebString();
-}
-
-struct ProgressEvent {
-  explicit ProgressEvent(PP_Instance instance_param,
-                         PP_NaClEventType event_type_param)
-      : instance(instance_param),
-        event_type(event_type_param),
-        length_is_computable(false),
-        loaded_bytes(0),
-        total_bytes(0) {
-  }
-  PP_Instance instance;
-  PP_NaClEventType event_type;
-  std::string resource_url;
-  bool length_is_computable;
-  uint64_t loaded_bytes;
-  uint64_t total_bytes;
-};
-
-void DispatchEventOnMainThread(const ProgressEvent &event);
+void DispatchEventOnMainThread(PP_Instance instance,
+                               PP_NaClEventType event_type,
+                               const std::string& resource_url,
+                               PP_Bool length_is_computable,
+                               uint64_t loaded_bytes,
+                               uint64_t total_bytes);
 
 void DispatchEvent(PP_Instance instance,
                    PP_NaClEventType event_type,
@@ -442,131 +401,80 @@
                    PP_Bool length_is_computable,
                    uint64_t loaded_bytes,
                    uint64_t total_bytes) {
-  ProgressEvent p(instance, event_type);
-  p.length_is_computable = PP_ToBool(length_is_computable);
-  p.loaded_bytes = loaded_bytes;
-  p.total_bytes = total_bytes;
-
-  // We have to copy resource_url into our struct manually since we don't have
-  // guarantees about the PP_Var lifetime.
-  p.resource_url = std::string();
-  if (resource_url)
-    p.resource_url = std::string(resource_url);
-
   ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask(
       FROM_HERE,
-      base::Bind(&DispatchEventOnMainThread, p));
+      base::Bind(&DispatchEventOnMainThread,
+                 instance,
+                 event_type,
+                 std::string(resource_url),
+                 length_is_computable,
+                 loaded_bytes,
+                 total_bytes));
 }
 
-void DispatchEventOnMainThread(const ProgressEvent &event) {
-  content::PepperPluginInstance* plugin_instance =
-      content::PepperPluginInstance::Get(event.instance);
-  // The instance may have been destroyed after we were scheduled, so just
-  // return if it's gone.
-  if (!plugin_instance)
-    return;
-
-  blink::WebPluginContainer* container = plugin_instance->GetContainer();
-  // It's possible that container() is NULL if the plugin has been removed from
-  // the DOM (but the PluginInstance is not destroyed yet).
-  if (!container)
-    return;
-  blink::WebFrame* frame = container->element().document().frame();
-  if (!frame)
-    return;
-  v8::HandleScope handle_scope(plugin_instance->GetIsolate());
-  v8::Local<v8::Context> context(
-      plugin_instance->GetIsolate()->GetCurrentContext());
-  if (context.IsEmpty()) {
-    // If there's no JavaScript on the stack, we have to make a new Context.
-    context = v8::Context::New(plugin_instance->GetIsolate());
-  }
-  v8::Context::Scope context_scope(context);
-
-  if (!event.resource_url.empty()) {
-    blink::WebString url_string = blink::WebString::fromUTF8(
-        event.resource_url.data(), event.resource_url.size());
-    blink::WebDOMResourceProgressEvent blink_event(
-        EventTypeToString(event.event_type),
-        event.length_is_computable,
-        event.loaded_bytes,
-        event.total_bytes,
-        url_string);
-    container->element().dispatchEvent(blink_event);
-  } else {
-    blink::WebDOMProgressEvent blink_event(EventTypeToString(event.event_type),
-                                           event.length_is_computable,
-                                           event.loaded_bytes,
-                                           event.total_bytes);
-    container->element().dispatchEvent(blink_event);
+void DispatchEventOnMainThread(PP_Instance instance,
+                               PP_NaClEventType event_type,
+                               const std::string& resource_url,
+                               PP_Bool length_is_computable,
+                               uint64_t loaded_bytes,
+                               uint64_t total_bytes) {
+  nacl::NexeLoadManager* load_manager =
+      GetNexeLoadManager(instance);
+  // The instance may have been destroyed after we were scheduled, so do
+  // nothing if it's gone.
+  if (load_manager) {
+    nacl::NexeLoadManager::ProgressEvent event(event_type);
+    event.resource_url = resource_url;
+    event.length_is_computable = PP_ToBool(length_is_computable);
+    event.loaded_bytes = loaded_bytes;
+    event.total_bytes = total_bytes;
+    load_manager->DispatchEvent(event);
   }
 }
 
 void SetReadOnlyProperty(PP_Instance instance,
                          struct PP_Var key,
                          struct PP_Var value) {
-  content::PepperPluginInstance* plugin_instance =
-      content::PepperPluginInstance::Get(instance);
-  plugin_instance->SetEmbedProperty(key, value);
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  if (load_manager)
+    load_manager->SetReadOnlyProperty(key, value);
 }
 
 void ReportLoadError(PP_Instance instance,
                      PP_NaClError error,
                      const char* error_message,
-                     const char* console_message,
-                     PP_Bool is_installed) {
-  // Check that we are on the main renderer thread.
-  DCHECK(content::RenderThread::Get());
+                     const char* console_message) {
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  if (load_manager)
+    load_manager->ReportLoadError(error, error_message, console_message);
+}
 
-  if (error == PP_NACL_ERROR_MANIFEST_PROGRAM_MISSING_ARCH) {
-    // A special case: the manifest may otherwise be valid but is missing
-    // a program/file compatible with the user's sandbox.
-    IPC::Sender* sender = content::RenderThread::Get();
-    sender->Send(
-        new NaClHostMsg_MissingArchError(GetRoutingID(instance)));
-  }
-  // TODO(dmichael): Move the following actions here:
-  // - Set ready state to DONE.
-
-  // Inform JavaScript that loading encountered an error and is complete.
-  DispatchEvent(instance, PP_NACL_EVENT_ERROR, NULL, PP_FALSE, 0, 0);
-  DispatchEvent(instance, PP_NACL_EVENT_LOADEND, NULL, PP_FALSE, 0, 0);
-
-  HistogramEnumerate("NaCl.LoadStatus.Plugin", error,
-                     PP_NACL_ERROR_MAX);
-  std::string uma_name = (is_installed == PP_TRUE) ?
-                         "NaCl.LoadStatus.Plugin.InstalledApp" :
-                         "NaCl.LoadStatus.Plugin.NotInstalledApp";
-  HistogramEnumerate(uma_name, error, PP_NACL_ERROR_MAX);
-
-  std::string error_string = std::string("NaCl module load failed: ") +
-      std::string(error_message);
-  content::PepperPluginInstance* plugin_instance =
-      content::PepperPluginInstance::Get(instance);
-  plugin_instance->SetEmbedProperty(
-      ppapi::StringVar::StringToPPVar("lastError"),
-      ppapi::StringVar::StringToPPVar(error_string));
-
-  std::string console_string = std::string("NaCl module load failed: ") +
-      std::string(console_message);
-  LogToConsole(instance, console_string.c_str());
+void InstanceCreated(PP_Instance instance) {
+  scoped_ptr<nacl::NexeLoadManager> new_load_manager(
+      new nacl::NexeLoadManager(instance));
+  NexeLoadManagerMap& map = g_load_manager_map.Get();
+  DLOG_IF(ERROR, map.count(instance) != 0) << "Instance count should be 0";
+  map.add(instance, new_load_manager.Pass());
 }
 
 void InstanceDestroyed(PP_Instance instance) {
-  InstanceTrustedChannelMap& map = g_channel_map.Get();
-  InstanceTrustedChannelMap::iterator it = map.find(instance);
-  if (it == map.end()) {
-    DLOG(ERROR) << "Could not find instance ID";
-    return;
-  }
-  nacl::TrustedPluginChannel* instance_info = it->second;
-  map.erase(it);
-  delete instance_info;
+  NexeLoadManagerMap& map = g_load_manager_map.Get();
+  DLOG_IF(ERROR, map.count(instance) == 0) << "Could not find instance ID";
+  map.erase(instance);
 }
 
-PP_Bool NaClDebugStubEnabled() {
-  return PP_FromBool(CommandLine::ForCurrentProcess()->HasSwitch(
-                         switches::kEnableNaClDebug));
+PP_Bool NaClDebugEnabledForURL(const char* alleged_nmf_url) {
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaClDebug))
+    return PP_FALSE;
+  bool should_debug;
+  IPC::Sender* sender = content::RenderThread::Get();
+  DCHECK(sender);
+  if(!sender->Send(new NaClHostMsg_NaClDebugEnabledForURL(
+         GURL(alleged_nmf_url),
+         &should_debug))) {
+    return PP_FALSE;
+  }
+  return PP_FromBool(should_debug);
 }
 
 const char* GetSandboxArch() {
@@ -587,11 +495,55 @@
 }
 
 void LogToConsole(PP_Instance instance, const char* message) {
-  std::string source("NativeClient");
-  ppapi::PpapiGlobals::Get()->LogWithSource(instance,
-                                            PP_LOGLEVEL_LOG,
-                                            source,
-                                            std::string(message));
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  DCHECK(load_manager);
+  if (load_manager)
+    load_manager->LogToConsole(std::string(message));
+}
+
+PP_Bool GetNexeErrorReported(PP_Instance instance) {
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  DCHECK(load_manager);
+  if (load_manager)
+    return PP_FromBool(load_manager->nexe_error_reported());
+  return PP_FALSE;
+}
+
+void SetNexeErrorReported(PP_Instance instance, PP_Bool error_reported) {
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  DCHECK(load_manager);
+  if (load_manager)
+    load_manager->set_nexe_error_reported(PP_ToBool(error_reported));
+}
+
+PP_NaClReadyState GetNaClReadyState(PP_Instance instance) {
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  DCHECK(load_manager);
+  if (load_manager)
+    return load_manager->nacl_ready_state();
+  return PP_NACL_READY_STATE_UNSENT;
+}
+
+void SetNaClReadyState(PP_Instance instance, PP_NaClReadyState ready_state) {
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  DCHECK(load_manager);
+  if (load_manager)
+    load_manager->set_nacl_ready_state(ready_state);
+}
+
+PP_Bool GetIsInstalled(PP_Instance instance) {
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  DCHECK(load_manager);
+  if (load_manager)
+    return PP_FromBool(load_manager->is_installed());
+  return PP_FALSE;
+}
+
+void SetIsInstalled(PP_Instance instance, PP_Bool installed) {
+  nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
+  DCHECK(load_manager);
+  if (load_manager)
+    load_manager->set_is_installed(PP_ToBool(installed));
 }
 
 const PPB_NaCl_Private nacl_interface = {
@@ -610,11 +562,18 @@
   &DispatchEvent,
   &SetReadOnlyProperty,
   &ReportLoadError,
+  &InstanceCreated,
   &InstanceDestroyed,
-  &NaClDebugStubEnabled,
+  &NaClDebugEnabledForURL,
   &GetSandboxArch,
   &GetUrlScheme,
-  &LogToConsole
+  &LogToConsole,
+  &GetNexeErrorReported,
+  &SetNexeErrorReported,
+  &GetNaClReadyState,
+  &SetNaClReadyState,
+  &GetIsInstalled,
+  &SetIsInstalled
 };
 
 }  // namespace
diff --git a/components/navigation_interception.target.darwin-arm.mk b/components/navigation_interception.target.darwin-arm.mk
index 9332888..d8278a5 100644
--- a/components/navigation_interception.target.darwin-arm.mk
+++ b/components/navigation_interception.target.darwin-arm.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception.target.darwin-mips.mk b/components/navigation_interception.target.darwin-mips.mk
index 8fc1ed1..c07b811 100644
--- a/components/navigation_interception.target.darwin-mips.mk
+++ b/components/navigation_interception.target.darwin-mips.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception.target.darwin-x86.mk b/components/navigation_interception.target.darwin-x86.mk
index 1a5814e..e0b6756 100644
--- a/components/navigation_interception.target.darwin-x86.mk
+++ b/components/navigation_interception.target.darwin-x86.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception.target.darwin-x86_64.mk b/components/navigation_interception.target.darwin-x86_64.mk
new file mode 100644
index 0000000..9bfed14
--- /dev/null
+++ b/components/navigation_interception.target.darwin-x86_64.mk
@@ -0,0 +1,286 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_navigation_interception_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,components_navigation_interception_jni_headers_gyp)/navigation_interception_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/navigation_interception/intercept_navigation_resource_throttle.cc \
+	components/navigation_interception/navigation_params.cc \
+	components/navigation_interception/component_jni_registrar.cc \
+	components/navigation_interception/intercept_navigation_delegate.cc \
+	components/navigation_interception/navigation_params_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/navigation_interception \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/navigation_interception \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_navigation_interception_gyp
+
+# Alias gyp target name.
+.PHONY: navigation_interception
+navigation_interception: components_navigation_interception_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/navigation_interception.target.linux-arm.mk b/components/navigation_interception.target.linux-arm.mk
index 9332888..d8278a5 100644
--- a/components/navigation_interception.target.linux-arm.mk
+++ b/components/navigation_interception.target.linux-arm.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception.target.linux-mips.mk b/components/navigation_interception.target.linux-mips.mk
index 8fc1ed1..c07b811 100644
--- a/components/navigation_interception.target.linux-mips.mk
+++ b/components/navigation_interception.target.linux-mips.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception.target.linux-x86.mk b/components/navigation_interception.target.linux-x86.mk
index 1a5814e..e0b6756 100644
--- a/components/navigation_interception.target.linux-x86.mk
+++ b/components/navigation_interception.target.linux-x86.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception.target.linux-x86_64.mk b/components/navigation_interception.target.linux-x86_64.mk
new file mode 100644
index 0000000..9bfed14
--- /dev/null
+++ b/components/navigation_interception.target.linux-x86_64.mk
@@ -0,0 +1,286 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_navigation_interception_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,components_navigation_interception_jni_headers_gyp)/navigation_interception_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/navigation_interception/intercept_navigation_resource_throttle.cc \
+	components/navigation_interception/navigation_params.cc \
+	components/navigation_interception/component_jni_registrar.cc \
+	components/navigation_interception/intercept_navigation_delegate.cc \
+	components/navigation_interception/navigation_params_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/navigation_interception \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/navigation_interception \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_navigation_interception_gyp
+
+# Alias gyp target name.
+.PHONY: navigation_interception
+navigation_interception: components_navigation_interception_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/navigation_interception_jni_headers.target.darwin-arm.mk b/components/navigation_interception_jni_headers.target.darwin-arm.mk
index 7b749b7..e4d6f2c 100644
--- a/components/navigation_interception_jni_headers.target.darwin-arm.mk
+++ b/components/navigation_interception_jni_headers.target.darwin-arm.mk
@@ -107,6 +107,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -189,6 +190,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception_jni_headers.target.darwin-mips.mk b/components/navigation_interception_jni_headers.target.darwin-mips.mk
index d9996e7..630dc47 100644
--- a/components/navigation_interception_jni_headers.target.darwin-mips.mk
+++ b/components/navigation_interception_jni_headers.target.darwin-mips.mk
@@ -106,6 +106,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception_jni_headers.target.darwin-x86.mk b/components/navigation_interception_jni_headers.target.darwin-x86.mk
index e12fe2a..c171ffe 100644
--- a/components/navigation_interception_jni_headers.target.darwin-x86.mk
+++ b/components/navigation_interception_jni_headers.target.darwin-x86.mk
@@ -108,6 +108,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception_jni_headers.target.darwin-x86_64.mk b/components/navigation_interception_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a9da622
--- /dev/null
+++ b/components/navigation_interception_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,246 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_navigation_interception_jni_headers_gyp
+LOCAL_MODULE_STEM := navigation_interception_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "components_components_gyp_navigation_interception_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/navigation_interception/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java', 'navigation_interception/android/java/src/org/chromium/components/navigation_interception/NavigationParams.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/navigation_interception/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: $(LOCAL_PATH)/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/navigation_interception/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java --output_dir "$(gyp_shared_intermediate_dir)/navigation_interception/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_navigation_interception_jni_headers_gyp_rule_trigger
+components_navigation_interception_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h
+
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: $(LOCAL_PATH)/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/NavigationParams.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/navigation_interception/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file navigation_interception/android/java/src/org/chromium/components/navigation_interception/NavigationParams.java --output_dir "$(gyp_shared_intermediate_dir)/navigation_interception/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_navigation_interception_jni_headers_gyp_rule_trigger
+components_navigation_interception_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h \
+	components_navigation_interception_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_navigation_interception_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: navigation_interception_jni_headers
+navigation_interception_jni_headers: components_navigation_interception_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/navigation_interception_jni_headers.target.linux-arm.mk b/components/navigation_interception_jni_headers.target.linux-arm.mk
index 7b749b7..e4d6f2c 100644
--- a/components/navigation_interception_jni_headers.target.linux-arm.mk
+++ b/components/navigation_interception_jni_headers.target.linux-arm.mk
@@ -107,6 +107,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -189,6 +190,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception_jni_headers.target.linux-mips.mk b/components/navigation_interception_jni_headers.target.linux-mips.mk
index d9996e7..630dc47 100644
--- a/components/navigation_interception_jni_headers.target.linux-mips.mk
+++ b/components/navigation_interception_jni_headers.target.linux-mips.mk
@@ -106,6 +106,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception_jni_headers.target.linux-x86.mk b/components/navigation_interception_jni_headers.target.linux-x86.mk
index e12fe2a..c171ffe 100644
--- a/components/navigation_interception_jni_headers.target.linux-x86.mk
+++ b/components/navigation_interception_jni_headers.target.linux-x86.mk
@@ -108,6 +108,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/navigation_interception_jni_headers.target.linux-x86_64.mk b/components/navigation_interception_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..a9da622
--- /dev/null
+++ b/components/navigation_interception_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,246 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_navigation_interception_jni_headers_gyp
+LOCAL_MODULE_STEM := navigation_interception_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "components_components_gyp_navigation_interception_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/navigation_interception/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java', 'navigation_interception/android/java/src/org/chromium/components/navigation_interception/NavigationParams.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/navigation_interception/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h: $(LOCAL_PATH)/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/navigation_interception/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file navigation_interception/android/java/src/org/chromium/components/navigation_interception/InterceptNavigationDelegate.java --output_dir "$(gyp_shared_intermediate_dir)/navigation_interception/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_navigation_interception_jni_headers_gyp_rule_trigger
+components_navigation_interception_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h
+
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h: $(LOCAL_PATH)/components/navigation_interception/android/java/src/org/chromium/components/navigation_interception/NavigationParams.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/navigation_interception/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file navigation_interception/android/java/src/org/chromium/components/navigation_interception/NavigationParams.java --output_dir "$(gyp_shared_intermediate_dir)/navigation_interception/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_navigation_interception_jni_headers_gyp_rule_trigger
+components_navigation_interception_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/InterceptNavigationDelegate_jni.h \
+	$(gyp_shared_intermediate_dir)/navigation_interception/jni/NavigationParams_jni.h \
+	components_navigation_interception_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_navigation_interception_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: navigation_interception_jni_headers
+navigation_interception_jni_headers: components_navigation_interception_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/os_crypt.target.darwin-arm.mk b/components/os_crypt.target.darwin-arm.mk
index 24a4726..34ee03d 100644
--- a/components/os_crypt.target.darwin-arm.mk
+++ b/components/os_crypt.target.darwin-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/os_crypt.target.darwin-mips.mk b/components/os_crypt.target.darwin-mips.mk
index 474bc11..a74408f 100644
--- a/components/os_crypt.target.darwin-mips.mk
+++ b/components/os_crypt.target.darwin-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/os_crypt.target.darwin-x86.mk b/components/os_crypt.target.darwin-x86.mk
index f66058d..d317ace 100644
--- a/components/os_crypt.target.darwin-x86.mk
+++ b/components/os_crypt.target.darwin-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/os_crypt.target.darwin-x86_64.mk b/components/os_crypt.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4548799
--- /dev/null
+++ b/components/os_crypt.target.darwin-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_os_crypt_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/os_crypt/os_crypt_posix.cc \
+	components/os_crypt/os_crypt_switches.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_os_crypt_gyp
+
+# Alias gyp target name.
+.PHONY: os_crypt
+os_crypt: components_os_crypt_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/os_crypt.target.linux-arm.mk b/components/os_crypt.target.linux-arm.mk
index 24a4726..34ee03d 100644
--- a/components/os_crypt.target.linux-arm.mk
+++ b/components/os_crypt.target.linux-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/os_crypt.target.linux-mips.mk b/components/os_crypt.target.linux-mips.mk
index 474bc11..a74408f 100644
--- a/components/os_crypt.target.linux-mips.mk
+++ b/components/os_crypt.target.linux-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/os_crypt.target.linux-x86.mk b/components/os_crypt.target.linux-x86.mk
index f66058d..d317ace 100644
--- a/components/os_crypt.target.linux-x86.mk
+++ b/components/os_crypt.target.linux-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/os_crypt.target.linux-x86_64.mk b/components/os_crypt.target.linux-x86_64.mk
new file mode 100644
index 0000000..4548799
--- /dev/null
+++ b/components/os_crypt.target.linux-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_os_crypt_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/os_crypt/os_crypt_posix.cc \
+	components/os_crypt/os_crypt_switches.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_os_crypt_gyp
+
+# Alias gyp target name.
+.PHONY: os_crypt
+os_crypt: components_os_crypt_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index 115fd65..8ce07fa 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -76,9 +76,8 @@
 }
 
 PasswordFormManager::~PasswordFormManager() {
-  UMA_HISTOGRAM_ENUMERATION("PasswordManager.ActionsTakenWithPsl",
-                            GetActionsTaken(),
-                            kMaxNumActionsTaken);
+  UMA_HISTOGRAM_ENUMERATION(
+      "PasswordManager.ActionsTakenV3", GetActionsTaken(), kMaxNumActionsTaken);
   if (has_generated_password_ && submit_result_ == kSubmitResultNotSubmitted)
     LogPasswordGenerationSubmissionEvent(PASSWORD_NOT_SUBMITTED);
 }
@@ -244,7 +243,7 @@
 
     // Check to see if we're using a known username but a new password.
     if (pending_credentials_.password_value != credentials.password_value)
-      user_action_ = kUserActionOverride;
+      user_action_ = kUserActionOverridePassword;
   } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES &&
              UpdatePendingCredentialsIfOtherPossibleUsername(
                  credentials.username_value)) {
@@ -256,7 +255,7 @@
     is_new_login_ = false;
   } else {
     // User typed in a new, unknown username.
-    user_action_ = kUserActionOverride;
+    user_action_ = kUserActionOverrideUsernameAndPassword;
     pending_credentials_ = observed_form_;
     pending_credentials_.username_value = credentials.username_value;
     pending_credentials_.other_possible_usernames =
@@ -280,7 +279,7 @@
   pending_credentials_.password_value = credentials.password_value;
   pending_credentials_.preferred = credentials.preferred;
 
-  if (user_action_ == kUserActionOverride &&
+  if (user_action_ == kUserActionOverridePassword &&
       pending_credentials_.type == PasswordForm::TYPE_GENERATED &&
       !has_generated_password_) {
     LogPasswordGenerationSubmissionEvent(PASSWORD_OVERRIDDEN);
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index d2dcbc3..a1d0595 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -175,13 +175,16 @@
   // by simply (not typing anything at all), you get None. If there were
   // multiple choices and the user selects one other than the default,
   // you get Choose, if user selects an entry from matching against the Public
-  // Suffix List you get ChoosePslMatch, and if the user types in a new value,
-  // you get Override.
+  // Suffix List you get ChoosePslMatch, if the user types in a new value
+  // for just the password you get OverridePassword, and if the user types in a
+  // new value for the username and password you get
+  // OverrideUsernameAndPassword.
   enum UserAction {
     kUserActionNone = 0,
     kUserActionChoose,
     kUserActionChoosePslMatch,
-    kUserActionOverride,
+    kUserActionOverridePassword,
+    kUserActionOverrideUsernameAndPassword,
     kUserActionMax
   };
 
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h
index ca0c39c..6c62963 100644
--- a/components/password_manager/core/browser/password_store.h
+++ b/components/password_manager/core/browser/password_store.h
@@ -123,11 +123,11 @@
   virtual void UpdateLogin(const autofill::PasswordForm& form);
 
   // Removes the matching PasswordForm from the secure password store (async).
-  void RemoveLogin(const autofill::PasswordForm& form);
+  virtual void RemoveLogin(const autofill::PasswordForm& form);
 
   // Removes all logins created in the given date range.
-  void RemoveLoginsCreatedBetween(const base::Time& delete_begin,
-                                  const base::Time& delete_end);
+  virtual void RemoveLoginsCreatedBetween(const base::Time& delete_begin,
+                                          const base::Time& delete_end);
 
   // Searches for a matching PasswordForm, and notifies |consumer| on
   // completion. The request will be cancelled if the consumer is destroyed.
@@ -144,15 +144,15 @@
   // Gets the complete list of PasswordForms that are not blacklist entries--and
   // are thus auto-fillable. |consumer| will be notified on completion.
   // The request will be cancelled if the consumer is destroyed.
-  void GetAutofillableLogins(PasswordStoreConsumer* consumer);
+  virtual void GetAutofillableLogins(PasswordStoreConsumer* consumer);
 
   // Gets the complete list of PasswordForms that are blacklist entries,
   // and notify |consumer| on completion. The request will be cancelled if the
   // consumer is destroyed.
-  void GetBlacklistLogins(PasswordStoreConsumer* consumer);
+  virtual void GetBlacklistLogins(PasswordStoreConsumer* consumer);
 
   // Reports usage metrics for the database.
-  void ReportMetrics();
+  virtual void ReportMetrics();
 
   // Adds an observer to be notified when the password store data changes.
   void AddObserver(Observer* observer);
diff --git a/components/password_manager/core/common/password_manager_pref_names.cc b/components/password_manager/core/common/password_manager_pref_names.cc
index 65b074c..dc42c90 100644
--- a/components/password_manager/core/common/password_manager_pref_names.cc
+++ b/components/password_manager/core/common/password_manager_pref_names.cc
@@ -35,11 +35,6 @@
 #if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
 // The local profile id for this profile.
 const char kLocalProfileId[] = "profile.local_profile_id";
-
-// Whether passwords in external services (e.g. GNOME Keyring) have been tagged
-// with the local profile id yet. (Used for migrating to tagged passwords.)
-const char kPasswordsUseLocalProfileId[] =
-    "profile.passwords_use_local_profile_id";
 #endif
 
 }  // namespace prefs
diff --git a/components/password_manager/core/common/password_manager_pref_names.h b/components/password_manager/core/common/password_manager_pref_names.h
index 1837ec0..e21234b 100644
--- a/components/password_manager/core/common/password_manager_pref_names.h
+++ b/components/password_manager/core/common/password_manager_pref_names.h
@@ -21,7 +21,6 @@
 
 #if !defined(OS_MACOSX) && !defined(OS_CHROMEOS) && defined(OS_POSIX)
 extern const char kLocalProfileId[];
-extern const char kPasswordsUseLocalProfileId[];
 #endif
 
 }  // namespace prefs
diff --git a/components/policy/core/browser/cloud/message_util.cc b/components/policy/core/browser/cloud/message_util.cc
index f394762..ea9f65e 100644
--- a/components/policy/core/browser/cloud/message_util.cc
+++ b/components/policy/core/browser/cloud/message_util.cc
@@ -42,6 +42,8 @@
       return IDS_POLICY_DM_STATUS_SERVICE_MISSING_LICENSES;
     case DM_STATUS_SERVICE_DEPROVISIONED:
       return IDS_POLICY_DM_STATUS_SERVICE_DEPROVISIONED;
+    case DM_STATUS_SERVICE_DOMAIN_MISMATCH:
+      return IDS_POLICY_DM_STATUS_SERVICE_DOMAIN_MISMATCH;
     case DM_STATUS_SERVICE_POLICY_NOT_FOUND:
       return IDS_POLICY_DM_STATUS_SERVICE_POLICY_NOT_FOUND;
   }
diff --git a/components/policy/core/browser/configuration_policy_pref_store_unittest.cc b/components/policy/core/browser/configuration_policy_pref_store_unittest.cc
index c277253..4b67420 100644
--- a/components/policy/core/browser/configuration_policy_pref_store_unittest.cc
+++ b/components/policy/core/browser/configuration_policy_pref_store_unittest.cc
@@ -176,7 +176,6 @@
   const base::Value* value = NULL;
   EXPECT_FALSE(store_->GetValue(kTestPolicy, NULL));
 
-  EXPECT_CALL(observer_, OnPrefValueChanged(kTestPref)).Times(1);
   PolicyMap policy;
   policy.Set(kTestPolicy,
              POLICY_LEVEL_MANDATORY,
@@ -184,18 +183,16 @@
              base::Value::CreateStringValue("http://www.chromium.org"),
              NULL);
   UpdateProviderPolicy(policy);
-  Mock::VerifyAndClearExpectations(&observer_);
+  observer_.VerifyAndResetChangedKey(kTestPref);
   EXPECT_TRUE(store_->GetValue(kTestPref, &value));
   EXPECT_TRUE(base::StringValue("http://www.chromium.org").Equals(value));
 
-  EXPECT_CALL(observer_, OnPrefValueChanged(_)).Times(0);
   UpdateProviderPolicy(policy);
-  Mock::VerifyAndClearExpectations(&observer_);
+  EXPECT_TRUE(observer_.changed_keys.empty());
 
-  EXPECT_CALL(observer_, OnPrefValueChanged(kTestPref)).Times(1);
   policy.Erase(kTestPolicy);
   UpdateProviderPolicy(policy);
-  Mock::VerifyAndClearExpectations(&observer_);
+  observer_.VerifyAndResetChangedKey(kTestPref);
   EXPECT_FALSE(store_->GetValue(kTestPref, NULL));
 }
 
@@ -203,9 +200,10 @@
   EXPECT_FALSE(store_->IsInitializationComplete());
   EXPECT_CALL(provider_, IsInitializationComplete(POLICY_DOMAIN_CHROME))
       .WillRepeatedly(Return(true));
-  EXPECT_CALL(observer_, OnInitializationCompleted(true)).Times(1);
   PolicyMap policy;
   UpdateProviderPolicy(policy);
+  EXPECT_TRUE(observer_.initialized);
+  EXPECT_TRUE(observer_.initialization_success);
   Mock::VerifyAndClearExpectations(&observer_);
   EXPECT_TRUE(store_->IsInitializationComplete());
 }
diff --git a/components/policy/core/browser/url_blacklist_manager.cc b/components/policy/core/browser/url_blacklist_manager.cc
index c5489bb..b6fd7a7 100644
--- a/components/policy/core/browser/url_blacklist_manager.cc
+++ b/components/policy/core/browser/url_blacklist_manager.cc
@@ -369,7 +369,7 @@
 #endif
 
   bool block = false;
-  if (override_blacklist_(request.url(), &block))
+  if (override_blacklist_.Run(request.url(), &block))
     return block;
 
   return IsURLBlocked(request.url());
diff --git a/components/policy/core/browser/url_blacklist_manager.h b/components/policy/core/browser/url_blacklist_manager.h
index ea8f41d..e875461 100644
--- a/components/policy/core/browser/url_blacklist_manager.h
+++ b/components/policy/core/browser/url_blacklist_manager.h
@@ -133,8 +133,7 @@
  public:
   // Returns true if the blacklist should be overridden for |url| and sets
   // |block| to true if it should be blocked and false otherwise.
-  typedef bool (*OverrideBlacklistCallback)(const GURL& url,
-                                            bool* block);
+  typedef base::Callback<bool(const GURL&, bool*)> OverrideBlacklistCallback;
 
   // Must be constructed on the UI thread.
   // |background_task_runner| is used to build the blacklist in a background
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc
index 8a5ee78..3014fd7 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -93,7 +93,8 @@
                                  const std::string& auth_token,
                                  const std::string& client_id,
                                  bool is_auto_enrollement,
-                                 const std::string& requisition) {
+                                 const std::string& requisition,
+                                 const std::string& current_state_key) {
   DCHECK(service_);
   DCHECK(!auth_token.empty());
   DCHECK(!is_registered());
@@ -126,6 +127,8 @@
     request->set_auto_enrolled(true);
   if (!requisition.empty())
     request->set_requisition(requisition);
+  if (!current_state_key.empty())
+    request->set_server_backed_state_key(current_state_key);
 
   request_job_->SetRetryCallback(
       base::Bind(&CloudPolicyClient::OnRetryRegister, base::Unretained(this)));
diff --git a/components/policy/core/common/cloud/cloud_policy_client.h b/components/policy/core/common/cloud/cloud_policy_client.h
index 3aa12f7..bcf4353 100644
--- a/components/policy/core/common/cloud/cloud_policy_client.h
+++ b/components/policy/core/common/cloud/cloud_policy_client.h
@@ -113,7 +113,8 @@
       const std::string& auth_token,
       const std::string& client_id,
       bool is_auto_enrollment,
-      const std::string& requisition);
+      const std::string& requisition,
+      const std::string& current_state_key);
 
   // Sets information about a policy invalidation. Subsequent fetch operations
   // will use the given info, and callers can use fetched_invalidation_version
diff --git a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc
index 0123443..5c49e18 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_registration_helper.cc
@@ -263,7 +263,7 @@
   // Kick off registration of the CloudPolicyClient with our newly minted
   // oauth_access_token_.
   client_->Register(registration_type_, oauth_access_token_,
-                    std::string(), false, std::string());
+                    std::string(), false, std::string(), std::string());
 }
 
 void CloudPolicyClientRegistrationHelper::OnPolicyFetched(
diff --git a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
index 8502c38..e997604 100644
--- a/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
+++ b/components/policy/core/common/cloud/cloud_policy_client_unittest.cc
@@ -38,6 +38,7 @@
 const char kDMToken[] = "fake-dm-token";
 const char kDeviceCertificate[] = "fake-device-certificate";
 const char kRequisition[] = "fake-requisition";
+const char kStateKey[] = "fake-state-key";
 
 class MockStatusProvider : public CloudPolicyClient::StatusProvider {
  public:
@@ -232,8 +233,8 @@
 TEST_F(CloudPolicyClientTest, RegistrationAndPolicyFetch) {
   ExpectRegistration(kOAuthToken);
   EXPECT_CALL(observer_, OnRegistrationStateChanged(_));
-  client_->Register(em::DeviceRegisterRequest::USER,
-                    kOAuthToken, std::string(), false, std::string());
+  client_->Register(em::DeviceRegisterRequest::USER, kOAuthToken, std::string(),
+                    false, std::string(), std::string());
   EXPECT_TRUE(client_->is_registered());
   EXPECT_FALSE(client_->GetPolicyFor(policy_ns_key_));
   EXPECT_EQ(DM_STATUS_SUCCESS, client_->status());
@@ -251,10 +252,12 @@
   registration_request_.mutable_register_request()->set_auto_enrolled(true);
   registration_request_.mutable_register_request()->set_requisition(
       kRequisition);
+  registration_request_.mutable_register_request()->set_server_backed_state_key(
+      kStateKey);
   ExpectRegistration(kOAuthToken);
   EXPECT_CALL(observer_, OnRegistrationStateChanged(_));
-  client_->Register(em::DeviceRegisterRequest::USER,
-                    kOAuthToken, kClientID, true, kRequisition);
+  client_->Register(em::DeviceRegisterRequest::USER, kOAuthToken, kClientID,
+                    true, kRequisition, kStateKey);
   EXPECT_EQ(kClientID, client_id_);
 }
 
@@ -263,8 +266,8 @@
       clear_device_management_token();
   ExpectRegistration(kOAuthToken);
   EXPECT_CALL(observer_, OnClientError(_));
-  client_->Register(em::DeviceRegisterRequest::USER,
-                    kOAuthToken, std::string(), false, std::string());
+  client_->Register(em::DeviceRegisterRequest::USER, kOAuthToken, std::string(),
+                    false, std::string(), std::string());
   EXPECT_FALSE(client_->is_registered());
   EXPECT_FALSE(client_->GetPolicyFor(policy_ns_key_));
   EXPECT_EQ(DM_STATUS_RESPONSE_DECODING_ERROR, client_->status());
@@ -277,8 +280,8 @@
       .WillOnce(service_.FailJob(DM_STATUS_REQUEST_FAILED));
   EXPECT_CALL(service_, StartJob(_, _, _, _, _, _, _));
   EXPECT_CALL(observer_, OnClientError(_));
-  client_->Register(em::DeviceRegisterRequest::USER,
-                    kOAuthToken, std::string(), false, std::string());
+  client_->Register(em::DeviceRegisterRequest::USER, kOAuthToken, std::string(),
+                    false, std::string(), std::string());
   EXPECT_FALSE(client_->is_registered());
   EXPECT_FALSE(client_->GetPolicyFor(policy_ns_key_));
   EXPECT_EQ(DM_STATUS_REQUEST_FAILED, client_->status());
@@ -296,8 +299,8 @@
   EXPECT_CALL(service_, StartJob(dm_protocol::kValueRequestRegister,
                                  "", kOAuthToken, "", "", _,
                                  MatchProto(registration_request_)));
-  client_->Register(em::DeviceRegisterRequest::USER,
-                    kOAuthToken, std::string(), false, std::string());
+  client_->Register(em::DeviceRegisterRequest::USER, kOAuthToken, std::string(),
+                    false, std::string(), std::string());
   EXPECT_FALSE(client_->is_registered());
   Mock::VerifyAndClearExpectations(&service_);
 
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.h b/components/policy/core/common/cloud/cloud_policy_constants.h
index 4f67f45..350cb42 100644
--- a/components/policy/core/common/cloud/cloud_policy_constants.h
+++ b/components/policy/core/common/cloud/cloud_policy_constants.h
@@ -95,6 +95,8 @@
   DM_STATUS_SERVICE_MISSING_LICENSES,
   // Service error: The administrator has deprovisioned this client.
   DM_STATUS_SERVICE_DEPROVISIONED,
+  // Service error: Device registration for the wrong domain.
+  DM_STATUS_SERVICE_DOMAIN_MISMATCH,
   // Service error: Policy not found. Error code defined by the DM folks.
   DM_STATUS_SERVICE_POLICY_NOT_FOUND = 902,
 };
diff --git a/components/policy/core/common/cloud/cloud_policy_refresh_scheduler.cc b/components/policy/core/common/cloud/cloud_policy_refresh_scheduler.cc
index c8d4109..9bc4a32 100644
--- a/components/policy/core/common/cloud/cloud_policy_refresh_scheduler.cc
+++ b/components/policy/core/common/cloud/cloud_policy_refresh_scheduler.cc
@@ -8,14 +8,12 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
-#include "base/command_line.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/histogram.h"
 #include "base/sequenced_task_runner.h"
 #include "base/time/default_tick_clock.h"
 #include "base/time/tick_clock.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
-#include "components/policy/core/common/policy_switches.h"
 
 namespace policy {
 
@@ -306,6 +304,7 @@
     case DM_STATUS_SERVICE_DEVICE_ID_CONFLICT:
     case DM_STATUS_SERVICE_MISSING_LICENSES:
     case DM_STATUS_SERVICE_DEPROVISIONED:
+    case DM_STATUS_SERVICE_DOMAIN_MISMATCH:
       // Need a re-registration, no use in retrying.
       refresh_callback_.Cancel();
       return;
@@ -353,11 +352,6 @@
           base::Unretained(this)));
   base::TimeDelta delay =
       base::TimeDelta::FromSeconds(kWaitForInvalidationsTimeoutSeconds);
-  // Do not wait for the invalidation service if the feature is disabled.
-  if (CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kDisableCloudPolicyPush)) {
-    delay = base::TimeDelta();
-  }
   task_runner_->PostDelayedTask(
       FROM_HERE,
       wait_for_invalidations_timeout_callback_.callback(),
diff --git a/components/policy/core/common/cloud/device_management_service.cc b/components/policy/core/common/cloud/device_management_service.cc
index 95b9c3c..5d01ff8 100644
--- a/components/policy/core/common/cloud/device_management_service.cc
+++ b/components/policy/core/common/cloud/device_management_service.cc
@@ -41,6 +41,7 @@
 const int kDeviceManagementNotAllowed = 403;
 const int kInvalidURL = 404;  // This error is not coming from the GFE.
 const int kInvalidSerialNumber = 405;
+const int kDomainMismatch = 406;
 const int kDeviceIdConflict = 409;
 const int kDeviceNotFound = 410;
 const int kPendingApproval = 412;
@@ -259,6 +260,9 @@
     case kInvalidSerialNumber:
       ReportError(DM_STATUS_SERVICE_INVALID_SERIAL_NUMBER);
       return;
+    case kDomainMismatch:
+      ReportError(DM_STATUS_SERVICE_DOMAIN_MISMATCH);
+      return;
     case kDeprovisioned:
       ReportError(DM_STATUS_SERVICE_DEPROVISIONED);
       return;
diff --git a/components/policy/core/common/cloud/enterprise_metrics.h b/components/policy/core/common/cloud/enterprise_metrics.h
index 7d5108e..f3af080 100644
--- a/components/policy/core/common/cloud/enterprise_metrics.h
+++ b/components/policy/core/common/cloud/enterprise_metrics.h
@@ -165,6 +165,8 @@
   kMetricEnrollmentRobotRefreshTokenStoreFailed,
   // Enrollment failed because the administrator has deprovisioned the device.
   kMetricEnrollmentDeprovisioned,
+  // Enrollment failed because the device doesn't belong to the domain.
+  kMetricEnrollmentDomainMismatch,
 
   kMetricEnrollmentSize  // Must be the last.
 };
diff --git a/components/policy/core/common/cloud/mock_cloud_policy_client.h b/components/policy/core/common/cloud/mock_cloud_policy_client.h
index 434d2d8..3d4b2bb 100644
--- a/components/policy/core/common/cloud/mock_cloud_policy_client.h
+++ b/components/policy/core/common/cloud/mock_cloud_policy_client.h
@@ -20,9 +20,10 @@
   virtual ~MockCloudPolicyClient();
 
   MOCK_METHOD2(SetupRegistration, void(const std::string&, const std::string&));
-  MOCK_METHOD5(Register, void(
+  MOCK_METHOD6(Register, void(
       enterprise_management::DeviceRegisterRequest::Type type,
-      const std::string&, const std::string&, bool, const std::string&));
+      const std::string&, const std::string&, bool, const std::string&,
+      const std::string&));
   MOCK_METHOD0(FetchPolicy, void(void));
   MOCK_METHOD0(Unregister, void(void));
   MOCK_METHOD2(UploadCertificate,
diff --git a/components/policy/core/common/policy_loader_ios.h b/components/policy/core/common/policy_loader_ios.h
index d3c9771..90f37eb 100644
--- a/components/policy/core/common/policy_loader_ios.h
+++ b/components/policy/core/common/policy_loader_ios.h
@@ -30,6 +30,10 @@
  private:
   void UserDefaultsChanged();
 
+  // Loads the Chrome policies in |dictionary| into the given |bundle|.
+  static void LoadNSDictionaryToPolicyBundle(NSDictionary* dictionary,
+                                             PolicyBundle* bundle);
+
   // Used to manage the registration for NSNotificationCenter notifications.
   base::scoped_nsobject<id> notification_observer_;
 
diff --git a/components/policy/core/common/policy_loader_ios.mm b/components/policy/core/common/policy_loader_ios.mm
index 19718ea..edf91a1 100644
--- a/components/policy/core/common/policy_loader_ios.mm
+++ b/components/policy/core/common/policy_loader_ios.mm
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/mac/scoped_nsobject.h"
 #include "base/sequenced_task_runner.h"
 #include "components/policy/core/common/mac_util.h"
 #include "components/policy/core/common/policy_bundle.h"
@@ -32,6 +33,10 @@
 // Key in the managed app configuration that contains the Chrome policy.
 NSString* const kChromePolicyKey = @"ChromePolicy";
 
+// Key in the managed app configuration that contains the encoded Chrome policy.
+// This is a serialized Property List, encoded in base 64.
+NSString* const kEncodedChromePolicyKey = @"EncodedChromePolicy";
+
 }  // namespace
 
 // Helper that observes notifications for NSUserDefaults and triggers an update
@@ -107,15 +112,37 @@
   NSDictionary* configuration = [[NSUserDefaults standardUserDefaults]
       dictionaryForKey:kConfigurationKey];
   id chromePolicy = configuration[kChromePolicyKey];
+  id encodedChromePolicy = configuration[kEncodedChromePolicyKey];
+
   if (chromePolicy && [chromePolicy isKindOfClass:[NSDictionary class]]) {
-    // NSDictionary is toll-free bridged to CFDictionaryRef, which is a
-    // CFPropertyListRef.
-    scoped_ptr<base::Value> value =
-        PropertyToValue(static_cast<CFPropertyListRef>(chromePolicy));
-    base::DictionaryValue* dict = NULL;
-    if (value && value->GetAsDictionary(&dict)) {
-      PolicyMap& map = bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, ""));
-      map.LoadFrom(dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
+    LoadNSDictionaryToPolicyBundle(chromePolicy, bundle.get());
+
+    if (encodedChromePolicy)
+      NSLog(@"Ignoring EncodedChromePolicy because ChromePolicy is present.");
+  } else if (encodedChromePolicy &&
+             [encodedChromePolicy isKindOfClass:[NSString class]]) {
+    base::scoped_nsobject<NSData> data(
+        [[NSData alloc] initWithBase64EncodedString:encodedChromePolicy
+                                            options:0]);
+    if (!data) {
+      NSLog(@"Invalid Base64 encoding of EncodedChromePolicy");
+    } else {
+      NSError* error = nil;
+      NSDictionary* properties = [NSPropertyListSerialization
+          propertyListWithData:data.get()
+                       options:NSPropertyListImmutable
+                        format:NULL
+                         error:&error];
+      if (error) {
+        NSLog(@"Invalid property list in EncodedChromePolicy: %@", error);
+      } else if (!properties) {
+        NSLog(@"Failed to deserialize a valid Property List");
+      } else if (![properties isKindOfClass:[NSDictionary class]]) {
+        NSLog(@"Invalid property list in EncodedChromePolicy: expected an "
+               "NSDictionary but found %@", [properties class]);
+      } else {
+        LoadNSDictionaryToPolicyBundle(properties, bundle.get());
+      }
     }
   }
 
@@ -135,4 +162,18 @@
   Reload(false);
 }
 
+// static
+void PolicyLoaderIOS::LoadNSDictionaryToPolicyBundle(NSDictionary* dictionary,
+                                                     PolicyBundle* bundle) {
+  // NSDictionary is toll-free bridged to CFDictionaryRef, which is a
+  // CFPropertyListRef.
+  scoped_ptr<base::Value> value =
+      PropertyToValue(static_cast<CFPropertyListRef>(dictionary));
+  base::DictionaryValue* dict = NULL;
+  if (value && value->GetAsDictionary(&dict)) {
+    PolicyMap& map = bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, ""));
+    map.LoadFrom(dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
+  }
+}
+
 }  // namespace policy
diff --git a/components/policy/core/common/policy_loader_ios_unittest.mm b/components/policy/core/common/policy_loader_ios_unittest.mm
index e0c6e4c..7b85dc8 100644
--- a/components/policy/core/common/policy_loader_ios_unittest.mm
+++ b/components/policy/core/common/policy_loader_ios_unittest.mm
@@ -8,6 +8,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/strings/sys_string_conversions.h"
+#include "base/test/test_simple_task_runner.h"
 #include "base/values.h"
 #include "components/policy/core/common/async_policy_provider.h"
 #include "components/policy/core/common/configuration_policy_provider_test.h"
@@ -26,7 +27,9 @@
 
 class TestHarness : public PolicyProviderTestHarness {
  public:
-  TestHarness();
+  // If |use_encoded_key| is true then AddPolicies() serializes and encodes
+  // the policies, and publishes them under the EncodedChromePolicy key.
+  explicit TestHarness(bool use_encoded_key);
   virtual ~TestHarness();
 
   virtual void SetUp() OVERRIDE;
@@ -50,18 +53,24 @@
       const base::DictionaryValue* policy_value) OVERRIDE;
 
   static PolicyProviderTestHarness* Create();
+  static PolicyProviderTestHarness* CreateWithEncodedKey();
 
  private:
   // Merges the policies in |policy| into the current policy dictionary
   // in NSUserDefaults, after making sure that the policy dictionary
   // exists.
   void AddPolicies(NSDictionary* policy);
+  void AddChromePolicy(NSDictionary* policy);
+  void AddEncodedChromePolicy(NSDictionary* policy);
+
+  bool use_encoded_key_;
 
   DISALLOW_COPY_AND_ASSIGN(TestHarness);
 };
 
-TestHarness::TestHarness()
-    : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE) {}
+TestHarness::TestHarness(bool use_encoded_key)
+    : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE),
+      use_encoded_key_(use_encoded_key) {}
 
 TestHarness::~TestHarness() {
   // Cleanup any policies left from the test.
@@ -130,10 +139,22 @@
 
 // static
 PolicyProviderTestHarness* TestHarness::Create() {
-  return new TestHarness();
+  return new TestHarness(false);
+}
+
+// static
+PolicyProviderTestHarness* TestHarness::CreateWithEncodedKey() {
+  return new TestHarness(true);
 }
 
 void TestHarness::AddPolicies(NSDictionary* policy) {
+  if (use_encoded_key_)
+    AddEncodedChromePolicy(policy);
+  else
+    AddChromePolicy(policy);
+}
+
+void TestHarness::AddChromePolicy(NSDictionary* policy) {
   NSString* key = @"ChromePolicy";
   NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
   base::scoped_nsobject<NSMutableDictionary> chromePolicy(
@@ -152,12 +173,95 @@
                                             forKey:kConfigurationKey];
 }
 
+void TestHarness::AddEncodedChromePolicy(NSDictionary* policy) {
+  NSString* key = @"EncodedChromePolicy";
+  NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
+
+  base::scoped_nsobject<NSMutableDictionary> chromePolicy(
+      [[NSMutableDictionary alloc] init]);
+
+  NSString* previous = [defaults stringForKey:key];
+  if (previous) {
+    base::scoped_nsobject<NSData> data(
+        [[NSData alloc] initWithBase64EncodedString:previous options:0]);
+    NSDictionary* properties = [NSPropertyListSerialization
+        propertyListWithData:data.get()
+                     options:NSPropertyListImmutable
+                      format:NULL
+                       error:NULL];
+    [chromePolicy addEntriesFromDictionary:properties];
+  }
+
+  [chromePolicy addEntriesFromDictionary:policy];
+
+  NSData* data = [NSPropertyListSerialization
+      dataWithPropertyList:chromePolicy
+                    format:NSPropertyListXMLFormat_v1_0
+                   options:0
+                     error:NULL];
+  NSString* encoded = [data base64EncodedStringWithOptions:0];
+
+  NSDictionary* wrapper = @{
+      key: encoded
+  };
+  [[NSUserDefaults standardUserDefaults] setObject:wrapper
+                                            forKey:kConfigurationKey];
+}
+
 }  // namespace
 
-// Instantiate abstract test case for basic policy reading tests.
 INSTANTIATE_TEST_CASE_P(
-    PolicyProviderIOSTest,
+    PolicyProviderIOSChromePolicyTest,
     ConfigurationPolicyProviderTest,
     testing::Values(TestHarness::Create));
 
+INSTANTIATE_TEST_CASE_P(
+    PolicyProviderIOSEncodedChromePolicyTest,
+    ConfigurationPolicyProviderTest,
+    testing::Values(TestHarness::CreateWithEncodedKey));
+
+TEST(PolicyProviderIOSTest, ChromePolicyOverEncodedChromePolicy) {
+  // This test verifies that if the "ChromePolicy" key is present then the
+  // "EncodedChromePolicy" key is ignored.
+
+  NSDictionary* policy = @{
+    @"shared": @"wrong",
+    @"key1": @"value1",
+  };
+  NSData* data = [NSPropertyListSerialization
+      dataWithPropertyList:policy
+                    format:NSPropertyListXMLFormat_v1_0
+                   options:0
+                     error:NULL];
+  NSString* encodedChromePolicy = [data base64EncodedStringWithOptions:0];
+
+  NSDictionary* chromePolicy = @{
+    @"shared": @"right",
+    @"key2": @"value2",
+  };
+
+  NSDictionary* wrapper = @{
+    @"ChromePolicy": chromePolicy,
+    @"EncodedChromePolicy": encodedChromePolicy,
+  };
+
+  [[NSUserDefaults standardUserDefaults] setObject:wrapper
+                                            forKey:kConfigurationKey];
+
+  PolicyBundle expected;
+  PolicyMap& expectedMap =
+      expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, ""));
+  expectedMap.Set("shared", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
+                  new base::StringValue("right"), NULL);
+  expectedMap.Set("key2", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
+                  new base::StringValue("value2"), NULL);
+
+  scoped_refptr<base::TestSimpleTaskRunner> taskRunner =
+      new base::TestSimpleTaskRunner();
+  PolicyLoaderIOS loader(taskRunner);
+  scoped_ptr<PolicyBundle> bundle = loader.Load();
+  ASSERT_TRUE(bundle);
+  EXPECT_TRUE(bundle->Equals(expected));
+}
+
 }  // namespace policy
diff --git a/components/policy/core/common/policy_switches.cc b/components/policy/core/common/policy_switches.cc
index 5a7878f..682ae56 100644
--- a/components/policy/core/common/policy_switches.cc
+++ b/components/policy/core/common/policy_switches.cc
@@ -18,9 +18,6 @@
 // device management backend.
 const char kDeviceManagementUrl[]           = "device-management-url";
 
-// Disables pushing cloud policy to Chrome using an invalidation service.
-const char kDisableCloudPolicyPush[]        = "disable-cloud-policy-push";
-
 // Enables fetching and storing cloud policy for components.
 const char kEnableComponentCloudPolicy[]    = "enable-component-cloud-policy";
 
diff --git a/components/policy/core/common/policy_switches.h b/components/policy/core/common/policy_switches.h
index 6880ecd..43c366c 100644
--- a/components/policy/core/common/policy_switches.h
+++ b/components/policy/core/common/policy_switches.h
@@ -14,7 +14,6 @@
 
 POLICY_EXPORT extern const char kCloudPolicyInvalidationDelay[];
 POLICY_EXPORT extern const char kDeviceManagementUrl[];
-POLICY_EXPORT extern const char kDisableCloudPolicyPush[];
 POLICY_EXPORT extern const char kEnableComponentCloudPolicy[];
 POLICY_EXPORT extern const char kDisablePolicyKeyVerification[];
 
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index fe5ab19..5f2f0f4 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -51,6 +51,11 @@
   // upon. This allows clients to pass hints e.g. at device enrollment time
   // about the intended use of the device.
   optional string requisition = 6;
+
+  // The current server-backed state key for the client, if applicable. This can
+  // be used by the server to link the registration request to an existing
+  // device record for re-enrollment.
+  optional bytes server_backed_state_key = 7;
 }
 
 // Response from server to device register request.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index a371fa0..8e7b1fb 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -325,7 +325,7 @@
       Setting this to enabled causes Chrome to wait for a shorter interval for DNS-based WPAD servers.
 
       If this policy is left not set, this will be enabled and the user will not
-      be able to change it..''',
+      be able to change it.''',
     },
     {
       'name': 'DisableSpdy',
@@ -5445,17 +5445,98 @@
       ],
     },
     {
-      # TODO(bartfab): Change the policy type to 'dict' once this is fully
-      # supported. http://crbug.com/258339
       'name': 'DeviceLoginScreenPowerManagement',
-      'type': 'string',
-      'schema': { 'type': 'string' },
+      'type': 'dict',
+      'schema': {
+        'type': 'object',
+        'properties': {
+          'AC': {
+            'description': 'Power management settings applicable only when running on AC power',
+            'type': 'object',
+            'properties': {
+              'Delays': {
+                'type': 'object',
+                'properties': {
+                  'ScreenDim': {
+                    'description': 'The length of time without user input after which the screen is dimmed, in milliseconds',
+                    'type': 'integer',
+                    'minimum': 0
+                  },
+                  'ScreenOff': {
+                    'description': 'The length of time without user input after which the screen is turned off, in milliseconds',
+                    'type': 'integer',
+                    'minimum': 0
+                  },
+                  'Idle': {
+                    'description': 'The length of time without user input after which the idle action is taken, in milliseconds',
+                    'type': 'integer',
+                    'minimum': 0
+                  }
+                }
+              },
+              'IdleAction': {
+                'description': 'Action to take when the idle delay is reached',
+                'type': 'string',
+                'enum': [ 'Suspend', 'Shutdown', 'DoNothing' ]
+              }
+            }
+          },
+          'Battery': {
+            'description': 'Power management settings applicable only when running on battery power',
+            'type': 'object',
+            'properties': {
+              'Delays': {
+                'type': 'object',
+                'properties': {
+                  'ScreenDim': {
+                    'description': 'The length of time without user input after which the screen is dimmed, in milliseconds',
+                    'type': 'integer',
+                    'minimum': 0
+                  },
+                  'ScreenOff': {
+                    'description': 'The length of time without user input after which the screen is turned off, in milliseconds',
+                    'type': 'integer',
+                    'minimum': 0
+                  },
+                  'Idle': {
+                    'description': 'The length of time without user input after which the idle action is taken, in milliseconds',
+                    'type': 'integer',
+                    'minimum': 0
+                  }
+                }
+              },
+              'IdleAction': {
+                'description': 'Action to take when the idle delay is reached',
+                'type': 'string',
+                'enum': [ 'Suspend', 'Shutdown', 'DoNothing' ]
+              }
+            }
+          },
+          'LidCloseAction': {
+            'description': 'Action to take when the lid is closed',
+            'type': 'string',
+            'enum': [ 'Suspend', 'Shutdown', 'DoNothing' ]
+          },
+          'UserActivityScreenDimDelayScale': {
+            'description': 'Percentage by which the screen dim delay is scaled when user activity is observed while the screen is dimmed or soon after the screen has been turned off',
+            'type': 'integer',
+            'minimum': 100
+          }
+        }
+      },
       'supported_on': ['chrome_os:30-'],
       'device_only': True,
       'features': {
         'dynamic_refresh': True,
       },
-      'example_value': '{ "AC": { "IdleAction": "DoNothing" }, "Battery": { "IdleAction": "DoNothing" } }',
+      'example_value': {
+        'AC': {
+          'IdleAction': 'DoNothing'
+        },
+        'Battery': {
+          'IdleAction': 'DoNothing'
+        }
+      },
       'id': 225,
       'caption': '''Power management on the login screen''',
       'desc': '''Configure power management on the login screen in <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph>.
@@ -5464,82 +5545,6 @@
       * The actions to take on idle or lid close cannot be to end the session.
       * The default action taken on idle when running on AC power is to shut down.
 
-      The policy should be specified as a string that expresses the individual settings in JSON format, conforming to the following schema:
-      {
-        "type": "object",
-        "properties": {
-          "AC": {
-            "description": "Power management settings applicable only when running on AC power",
-            "type": "object",
-            "properties": {
-              "Delays": {
-                "type": "object",
-                "properties": {
-                  "ScreenDim": {
-                    "description": "The length of time without user input after which the screen is dimmed, in milliseconds",
-                    "type": "integer",
-                    "minimum": 0
-                  },
-                  "ScreenOff": {
-                    "description": "The length of time without user input after which the screen is turned off, in milliseconds",
-                    "type": "integer",
-                    "minimum": 0
-                  },
-                  "Idle": {
-                    "description": "The length of time without user input after which the idle action is taken, in milliseconds",
-                    "type": "integer",
-                    "minimum": 0
-                  }
-                }
-              },
-              "IdleAction": {
-                "description": "Action to take when the idle delay is reached",
-                "enum": [ "Suspend", "Shutdown", "DoNothing" ]
-              }
-            }
-          },
-          "Battery": {
-            "description": "Power management settings applicable only when running on battery power",
-            "type": "object",
-            "properties": {
-              "Delays": {
-                "type": "object",
-                "properties": {
-                  "ScreenDim": {
-                    "description": "The length of time without user input after which the screen is dimmed, in milliseconds",
-                    "type": "integer",
-                    "minimum": 0
-                  },
-                  "ScreenOff": {
-                    "description": "The length of time without user input after which the screen is turned off, in milliseconds",
-                    "type": "integer",
-                    "minimum": 0
-                  },
-                  "Idle": {
-                    "description": "The length of time without user input after which the idle action is taken, in milliseconds",
-                    "type": "integer",
-                    "minimum": 0
-                  }
-                }
-              },
-              "IdleAction": {
-                "description": "Action to take when the idle delay is reached",
-                "enum": [ "Suspend", "Shutdown", "DoNothing" ]
-              }
-            }
-          },
-          "LidCloseAction": {
-            "description": "Action to take when the lid is closed",
-            "enum": [ "Suspend", "Shutdown", "DoNothing" ]
-          },
-          "UserActivityScreenDimDelayScale": {
-            "description": "Percentage by which the screen dim delay is scaled when user activity is observed while the screen is dimmed or soon after the screen has been turned off",
-            "type": "integer",
-            "minimum": 100
-          }
-        }
-      }
-
       If a setting is left unspecified, a default value is used.
 
       If this policy is unset, defaults are used for all settings.''',
diff --git a/components/policy/resources/policy_templates_am.xtb b/components/policy/resources/policy_templates_am.xtb
index 4a1a9ec..28eeaf3 100644
--- a/components/policy/resources/policy_templates_am.xtb
+++ b/components/policy/resources/policy_templates_am.xtb
@@ -951,7 +951,7 @@
 <translation id="7880891067740158163">ጣቢያው የእውቅና ማረጋገጫ ከጠየቀ <ph name="PRODUCT_NAME"/> በራስ-ሰር የደንበኛ እውቅና ማረጋገጫ ሊጠይቅላቸው የሚገባ የዩ አር ኤል ስርዓተ ጥለቶች ዝርዝር እንዲገልጹ ያስችልዎታል።
 
           ይህ መምሪያ እንዳልተዋቀረ ከተተወ ለማንኛውም ጣቢያ ምንም ራስ-ምርጫ አይቀመጥለትም።</translation>
-<translation id="3866249974567520381">ገለጻ</translation>
+<translation id="3866249974567520381">ማብራሪያ</translation>
 <translation id="5192837635164433517">በ<ph name="PRODUCT_NAME"/> ውስጥ የተሰሩ ተለዋጭ የስህተት ገጾች (እንደ «ገጹ አልተገኘም» ያሉ) ስራ ላይ እንዲውሉ የሚያነቃ እና ተጠቃሚዎች ይህን ቅንብር እንዳይቀይሩት የሚያግድ ነው።
 
       ይህን ቅንብር ካነቁ ተለዋጭ የስህተት ገጾች ስራ ላይ ይውላሉ።
diff --git a/components/policy/resources/policy_templates_de.xtb b/components/policy/resources/policy_templates_de.xtb
index 1b74dbd..20e8a5d 100644
--- a/components/policy/resources/policy_templates_de.xtb
+++ b/components/policy/resources/policy_templates_de.xtb
@@ -325,7 +325,7 @@
 <translation id="6598235178374410284">Nutzer-Avatarbild</translation>
 <translation id="1675391920437889033">Legt fest, welche Typen von Apps bzw. Erweiterungen installiert werden können.
 
-          Diese Einstellung erstellt eine weiße Liste der Typen von Erweiterungen bzw. Apps, die in <ph name="PRODUCT_NAME"/> installiert werden können. Der Wert besteht aus einer Liste von Zeichenfolgen, die jeweils einer der folgenden Zeichenfolgen entsprechen: &quot;extension&quot;, &quot;theme&quot;, &quot;user_script&quot;, &quot;hosted_app&quot;, &quot;legacy_packaged_app&quot;, &quot;platform_app&quot;. Weitere Informationen zu diesen Typen finden Sie in der Dokumentation zu Chrome-Erweiterungen.
+          Diese Einstellung erstellt eine Whitelist der Typen von Erweiterungen bzw. Apps, die in <ph name="PRODUCT_NAME"/> installiert werden können. Der Wert besteht aus einer Liste von Zeichenfolgen, die jeweils einer der folgenden Zeichenfolgen entsprechen: &quot;extension&quot;, &quot;theme&quot;, &quot;user_script&quot;, &quot;hosted_app&quot;, &quot;legacy_packaged_app&quot;, &quot;platform_app&quot;. Weitere Informationen zu diesen Typen finden Sie in der Dokumentation zu Chrome-Erweiterungen.
 
           Diese Richtlinie betrifft auch Erweiterungen und Apps, deren Installation mit ExtensionInstallForcelist erzwungen wurde.
 
@@ -552,7 +552,7 @@
 
           So installiert <ph name="EXTENSION_POLICY_EXAMPLE"/> beispielsweise die Erweiterung <ph name="EXTENSION_POLICY_EXAMPLE_EXTENSION_NAME"/> über die standardmäßige Update-URL des Chrome Web Stores. Weitere Informationen zum Hosten von Erweiterungen finden Sie unter <ph name="LINK_TO_EXTENSION_DOC2"/>.
 
-          Nutzer können die von dieser Richtlinie festgelegten Erweiterungen nicht deinstallieren. Wenn Sie eine Erweiterung aus dieser Liste entfernen, wird diese automatisch von <ph name="PRODUCT_NAME"/> deinstalliert. Die in dieser Liste aufgeführten Erweiterungen werden zudem automatisch in die weiße Liste für die Installation aufgenommen. Die &quot;ExtensionsInstallBlacklist&quot; hat auf sie keinen Einfluss.
+          Nutzer können die von dieser Richtlinie festgelegten Erweiterungen nicht deinstallieren. Wenn Sie eine Erweiterung aus dieser Liste entfernen, wird diese automatisch von <ph name="PRODUCT_NAME"/> deinstalliert. Die in dieser Liste aufgeführten Erweiterungen werden zudem automatisch in die Whitelist für die Installation aufgenommen. Die &quot;ExtensionsInstallBlacklist&quot; hat auf sie keinen Einfluss.
 
           Bleibt diese Richtlinie unkonfiguriert, kann der Nutzer jede Erweiterung in <ph name="PRODUCT_NAME"/> deinstallieren.</translation>
 <translation id="6899705656741990703">Proxy-Einstellungen automatisch erkennen</translation>
@@ -693,7 +693,7 @@
 
       Mithilfe dieser Richtlinie können Ausnahmen von restriktiven schwarzen Listen geöffnet werden. So können beispielsweise mit &quot;*&quot; alle Anfragen blockiert werden, während mit dieser Richtlinie der Zugriff auf eine eingeschränkte Liste von URLs erlaubt werden kann. Hiermit können Ausnahmen von bestimmten Schemata, Sub-Domains anderer Domains, Ports oder bestimmten Pfaden geöffnet werden.
 
-      Der spezifischste Filter bestimmt, ob eine URL blockiert oder erlaubt ist. Die weiße Liste hat Vorrang vor der schwarzen Liste.
+      Der spezifischste Filter bestimmt, ob eine URL blockiert oder erlaubt ist. Die Whitelist hat Vorrang vor der schwarzen Liste.
 
       Diese Richtlinie ist auf 1000 Einträge beschränkt. Alle weiteren Einträge werden ignoriert.
 
@@ -913,7 +913,7 @@
 
       Wird diese Richtlinie nicht festgelegt, wird die Standardgröße verwendet und der Nutzer kann diese mit dem Parameter &quot;--disk-cache-size&quot; überschreiben.</translation>
 <translation id="5475361623548884387">Drucken aktivieren</translation>
-<translation id="7287359148642300270">Hiermit legen Sie fest, welche Server auf die weiße Liste für integrierte Authentifizierung gesetzt werden. Integrierte Authentifizierung ist nur möglich, wenn <ph name="PRODUCT_NAME"/> eine Authentifizierungsanfrage von einem Proxy oder einem anderen Server erhält, der in dieser Liste erlaubter Server enthalten ist.
+<translation id="7287359148642300270">Hiermit legen Sie fest, welche Server auf die Whitelist für integrierte Authentifizierung gesetzt werden. Integrierte Authentifizierung ist nur möglich, wenn <ph name="PRODUCT_NAME"/> eine Authentifizierungsanfrage von einem Proxy oder einem anderen Server erhält, der in dieser Liste erlaubter Server enthalten ist.
 
           Fügen Sie zwischen den verschiedenen Servernamen ein Komma als Trennzeichen ein. Platzhalter (*) sind zulässig.
 
diff --git a/components/policy/resources/policy_templates_lt.xtb b/components/policy/resources/policy_templates_lt.xtb
index e7707b4..e6944d8 100644
--- a/components/policy/resources/policy_templates_lt.xtb
+++ b/components/policy/resources/policy_templates_lt.xtb
@@ -644,7 +644,7 @@
 <translation id="6417861582779909667">Leidžiama nustatyti URL šablonų, nurodančių svetaines, kuriose neleidžiama nustatyti slapukų, sąrašą.
 
           Nenustačius šios politikos, visose svetainėse bus naudojama visuotinė numatytoji vertė iš politikos „Numatytasis slapukų nustatymas“ (jei nustatyta) ar naudotojo asmeninės konfigūracijos.</translation>
-<translation id="5457296720557564923">Leidžiama puslapiams pasiekti „JavaScript“ atminties naudojimo statistiką. Dėl šio nustatymo tinklalapis gali pasiekti kūrėjo įrankių profilių skydo atminties statistiką.</translation>
+<translation id="5457296720557564923">Leidžiama puslapiams pasiekti „JavaScript“ atminties naudojimo statistiką. Dėl šio nustatymo tinklalapis gali pasiekti kūrėjo įrankių profilių skydelio atminties statistiką.</translation>
 <translation id="5776485039795852974">Paklausti kaskart, kai svetainėje norima rodyti darbalaukio pranešimus</translation>
 <translation id="5047604665028708335">Leisti pasiekti svetaines, nesančias turinio paketuose</translation>
 <translation id="5052081091120171147">Pagal šią politiką naršymo istorija priverstinai importuojama iš esamos numatytosios naršyklės (jei įgalinta). Be to, jei įgalinta, ši politika turi įtakos importavimo dialogo langui.
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp
index c7a667c..bca17e8 100644
--- a/components/policy_strings.grdp
+++ b/components/policy_strings.grdp
@@ -309,4 +309,12 @@
     </message>
   </if>
 
+  <!-- TODO(mnissler): Move this message up to the other IDS_POLICY_DM_STATUS
+       messages in the file. It's here because there's a problem with the
+       Android build failing component_unittests due to string constant
+       mismatches between the code and the resources. -->
+  <message name="IDS_POLICY_DM_STATUS_SERVICE_DOMAIN_MISMATCH" desc="Message indicating this client cannot be registered with the specified domain.">
+    Domain mismatch
+  </message>
+
 </grit-part>
diff --git a/components/rappor/bloom_filter.h b/components/rappor/bloom_filter.h
index 0bb9a57..d9acfa4 100644
--- a/components/rappor/bloom_filter.h
+++ b/components/rappor/bloom_filter.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "base/macros.h"
 #include "components/rappor/byte_vector_utils.h"
 
 namespace rappor {
diff --git a/components/rappor/byte_vector_utils.h b/components/rappor/byte_vector_utils.h
index 9154cab..0e33041 100644
--- a/components/rappor/byte_vector_utils.h
+++ b/components/rappor/byte_vector_utils.h
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/basictypes.h"
+#include "base/macros.h"
 #include "components/rappor/rappor_parameters.h"
 #include "crypto/hmac.h"
 
diff --git a/components/rappor/log_uploader.cc b/components/rappor/log_uploader.cc
index 4837ba1..ead1a97 100644
--- a/components/rappor/log_uploader.cc
+++ b/components/rappor/log_uploader.cc
@@ -102,12 +102,12 @@
   DCHECK_EQ(current_fetch_.get(), source);
   scoped_ptr<net::URLFetcher> fetch(current_fetch_.Pass());
 
-  int response_code = source->GetResponseCode();
+  const int response_code = source->GetResponseCode();
 
   // Log a histogram to track response success vs. failure rates.
   UMA_HISTOGRAM_SPARSE_SLOWLY("Rappor.UploadResponseCode", response_code);
 
-  bool upload_succeeded = response_code == 200;
+  const bool upload_succeeded = response_code == 200;
 
   // Determine whether this log should be retransmitted.
   DiscardReason reason = NUM_DISCARD_REASONS;
@@ -128,7 +128,7 @@
 
   // Error 400 indicates a problem with the log, not with the server, so
   // don't consider that a sign that the server is in trouble.
-  bool server_is_healthy = upload_succeeded || response_code == 400;
+  const bool server_is_healthy = upload_succeeded || response_code == 400;
   OnUploadFinished(server_is_healthy, !queued_logs_.empty());
 }
 
diff --git a/components/rappor/log_uploader.h b/components/rappor/log_uploader.h
index 30a129a..a446a34 100644
--- a/components/rappor/log_uploader.h
+++ b/components/rappor/log_uploader.h
@@ -8,6 +8,8 @@
 #include <queue>
 #include <string>
 
+#include "base/compiler_specific.h"
+#include "base/macros.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
@@ -21,16 +23,22 @@
 
 namespace rappor {
 
-// Handles uploading logs to an external server.
+// Uploads logs from RapporService.  Logs are passed in via QueueLog(), stored
+// internally, and uploaded one at a time.  A queued log will be uploaded at a
+// fixed interval after the successful upload of the previous logs.  If an
+// upload fails, the uploader will keep retrying the upload with an exponential
+// backoff interval.
 class LogUploader : public net::URLFetcherDelegate {
  public:
-  // Constructor takes the server_url that logs should be uploaded to, the
-  // mime_type of the uploaded data, and request_context to create uploads
+  // Constructor takes the |server_url| that logs should be uploaded to, the
+  // |mime_type| of the uploaded data, and |request_context| to create uploads
   // with.
   LogUploader(const GURL& server_url,
               const std::string& mime_type,
               net::URLRequestContextGetter* request_context);
 
+  // If the object is destroyed (or the program terminates) while logs are
+  // queued, the logs are lost.
   virtual ~LogUploader();
 
   // Adds an entry to the queue of logs to be uploaded to the server.  The
@@ -39,7 +47,7 @@
   void QueueLog(const std::string& log);
 
  protected:
-  // Check if an upload has been scheduled.
+  // Checks if an upload has been scheduled.
   virtual bool IsUploadScheduled() const;
 
   // Schedules a future call to StartScheduledUpload if one isn't already
@@ -54,8 +62,8 @@
   static base::TimeDelta BackOffUploadInterval(base::TimeDelta);
 
  private:
-  // Implementation of net::URLFetcherDelegate. Called after transmission
-  // completes (either successfully or with failure).
+  // Implements net::URLFetcherDelegate. Called after transmission completes
+  // (whether successful or not).
   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
 
   // Called when the upload is completed.
diff --git a/components/rappor/log_uploader_unittest.cc b/components/rappor/log_uploader_unittest.cc
index 46db7db..8c175b4 100644
--- a/components/rappor/log_uploader_unittest.cc
+++ b/components/rappor/log_uploader_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/rappor/log_uploader.h"
 
+#include "base/compiler_specific.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "net/url_request/test_url_fetcher_factory.h"
 #include "net/url_request/url_request_test_util.h"
diff --git a/components/rappor/rappor_metric.cc b/components/rappor/rappor_metric.cc
index 2da3b31..f8ff162 100644
--- a/components/rappor/rappor_metric.cc
+++ b/components/rappor/rappor_metric.cc
@@ -30,7 +30,7 @@
   // client's secret key + real data as a seed.  The inclusion of the secret
   // in the seed avoids correlations between real and fake data.
   // The seed isn't a human-readable string.
-  std::string personalization_string = metric_name_ +
+  const std::string personalization_string = metric_name_ +
       std::string(bytes().begin(), bytes().end());
   HmacByteVectorGenerator hmac_generator(bytes().size(), secret,
                                          personalization_string);
diff --git a/components/rappor/rappor_metric.h b/components/rappor/rappor_metric.h
index 30147c4..07f422d 100644
--- a/components/rappor/rappor_metric.h
+++ b/components/rappor/rappor_metric.h
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_RAPPOR_RAPPOR_H_
-#define COMPONENTS_RAPPOR_RAPPOR_H_
+#ifndef COMPONENTS_RAPPOR_RAPPOR_METRIC_H_
+#define COMPONENTS_RAPPOR_RAPPOR_METRIC_H_
 
 #include <string>
 
+#include "base/basictypes.h"
+#include "base/macros.h"
 #include "components/rappor/bloom_filter.h"
 #include "components/rappor/byte_vector_utils.h"
 #include "components/rappor/rappor_parameters.h"
@@ -16,17 +18,20 @@
 // A RapporMetric is an object that collects string samples into a Bloom filter,
 // and generates randomized reports about the collected data.
 //
+// This class should not be used directly by metrics clients.  Record metrics
+// using RapporService::RecordSample instead.
+//
 // For a full description of the rappor metrics, see
 // http://www.chromium.org/developers/design-documents/rappor
 class RapporMetric {
  public:
   // Takes the |metric_name| that this will be reported to the server with,
-  // a |parameters| describing size and probability weights to be used in
-  // recording this metric, and cohort value, which modifies the hash
-  // functions and used in the bloom filter.
-  explicit RapporMetric(const std::string& metric_name,
-                        const RapporParameters& parameters,
-                        int32_t cohort);
+  // a |parameters| describing size and probability weights used in recording
+  // this metric, and a |cohort| value, which determines the hash functions
+  // used in the Bloom filter.
+  RapporMetric(const std::string& metric_name,
+               const RapporParameters& parameters,
+               int32_t cohort);
   ~RapporMetric();
 
   // Records an additional sample in the Bloom filter.
@@ -53,4 +58,4 @@
 
 }  // namespace rappor
 
-#endif  // COMPONENTS_RAPPOR_RAPPOR_H_
+#endif  // COMPONENTS_RAPPOR_RAPPOR_METRIC_H_
diff --git a/components/rappor/rappor_metric_unittest.cc b/components/rappor/rappor_metric_unittest.cc
index bbcb1ab..7c50fd4 100644
--- a/components/rappor/rappor_metric_unittest.cc
+++ b/components/rappor/rappor_metric_unittest.cc
@@ -18,8 +18,7 @@
     PROBABILITY_75 /* Fake data probability */,
     PROBABILITY_50 /* Fake one probability */,
     PROBABILITY_75 /* One coin probability */,
-    PROBABILITY_50 /* Zero coin probability */
-};
+    PROBABILITY_50 /* Zero coin probability */};
 
 const RapporParameters kTestStatsRapporParameters = {
     50 /* Bloom filter size bytes */,
@@ -27,8 +26,7 @@
     PROBABILITY_75 /* Fake data probability */,
     PROBABILITY_50 /* Fake one probability */,
     PROBABILITY_75 /* One coin probability */,
-    PROBABILITY_50 /* Zero coin probability */
-};
+    PROBABILITY_50 /* Zero coin probability */};
 
 // Check for basic syntax and use.
 TEST(RapporMetricTest, BasicMetric) {
@@ -41,7 +39,7 @@
 TEST(RapporMetricTest, GetReport) {
   RapporMetric metric("MyRappor", kTestRapporParameters, 0);
 
-  ByteVector report = metric.GetReport(
+  const ByteVector report = metric.GetReport(
       HmacByteVectorGenerator::GenerateEntropyInput());
   EXPECT_EQ(16u, report.size());
 }
@@ -52,25 +50,26 @@
   for (char i = 0; i < 50; i++) {
     metric.AddSample(base::StringPrintf("%d", i));
   }
-  ByteVector real_bits = metric.bytes();
-  int real_bit_count = CountBits(real_bits);
+  const ByteVector real_bits = metric.bytes();
+  const int real_bit_count = CountBits(real_bits);
   EXPECT_EQ(real_bit_count, 152);
 
-  std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
-  ByteVector report = metric.GetReport(secret);
+  const std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
+  const ByteVector report = metric.GetReport(secret);
 
-  // For the bits we actually set in the bloom filter, get a count of how
+  // For the bits we actually set in the Bloom filter, get a count of how
   // many of them reported true.
   ByteVector from_true_reports = report;
   // Real bits AND report bits.
   ByteVectorMerge(real_bits, real_bits, &from_true_reports);
-  int true_from_true_count = CountBits(from_true_reports);
+  const int true_from_true_count = CountBits(from_true_reports);
 
-  // For the bits we didn't set in the bloom filter, get a count of how
+  // For the bits we didn't set in the Bloom filter, get a count of how
   // many of them reported true.
   ByteVector from_false_reports = report;
   ByteVectorOr(real_bits, &from_false_reports);
-  int true_from_false_count = CountBits(from_false_reports) - real_bit_count;
+  const int true_from_false_count =
+      CountBits(from_false_reports) - real_bit_count;
 
   // The probability of a true bit being true after redaction =
   //   [fake_prob]*[fake_true_prob] + (1-[fake_prob]) =
diff --git a/components/rappor/rappor_service.cc b/components/rappor/rappor_service.cc
index 493e7b9..01e6ab0 100644
--- a/components/rappor/rappor_service.cc
+++ b/components/rappor/rappor_service.cc
@@ -10,8 +10,11 @@
 #include "base/prefs/pref_service.h"
 #include "base/rand_util.h"
 #include "base/stl_util.h"
+#include "base/time/time.h"
 #include "components/metrics/metrics_hashes.h"
+#include "components/rappor/log_uploader.h"
 #include "components/rappor/proto/rappor_metric.pb.h"
+#include "components/rappor/rappor_metric.h"
 #include "components/rappor/rappor_pref_names.h"
 #include "components/variations/variations_associated_data.h"
 
@@ -42,14 +45,13 @@
 }
 
 const RapporParameters kRapporParametersForType[NUM_RAPPOR_TYPES] = {
-    {  // ETLD_PLUS_ONE_RAPPOR_TYPE
-        16 /* Bloom filter size bytes */,
-        2 /* Bloom filter hash count */,
-        rappor::PROBABILITY_75 /* Fake data probability */,
-        rappor::PROBABILITY_50 /* Fake one probability */,
-        rappor::PROBABILITY_75 /* One coin probability */,
-        rappor::PROBABILITY_50 /* Zero coin probability */
-    },
+    // ETLD_PLUS_ONE_RAPPOR_TYPE
+    {16 /* Bloom filter size bytes */,
+     2 /* Bloom filter hash count */,
+     rappor::PROBABILITY_75 /* Fake data probability */,
+     rappor::PROBABILITY_50 /* Fake one probability */,
+     rappor::PROBABILITY_75 /* One coin probability */,
+     rappor::PROBABILITY_50 /* Zero coin probability */},
 };
 
 }  // namespace
@@ -62,7 +64,7 @@
 
 void RapporService::Start(PrefService* pref_service,
                           net::URLRequestContextGetter* request_context) {
-  GURL server_url = GetServerUrl();
+  const GURL server_url = GetServerUrl();
   if (!server_url.is_valid())
     return;
   DCHECK(!uploader_);
@@ -98,19 +100,21 @@
 }
 
 void RapporService::LoadCohort(PrefService* pref_service) {
-  DCHECK_EQ(cohort_, -1);
+  DCHECK(!IsInitialized());
   cohort_ = pref_service->GetInteger(prefs::kRapporCohort);
+  // If the user is already assigned to a valid cohort, we're done.
   if (cohort_ >= 0 && cohort_ < kNumCohorts)
     return;
 
+  // This is the first time the client has started the service (or their
+  // preferences were corrupted).  Randomly assign them to a cohort.
   cohort_ = base::RandGenerator(kNumCohorts);
   pref_service->SetInteger(prefs::kRapporCohort, cohort_);
 }
 
 void RapporService::LoadSecret(PrefService* pref_service) {
   DCHECK(secret_.empty());
-  std::string secret_base64 =
-      pref_service->GetString(prefs::kRapporSecret);
+  std::string secret_base64 = pref_service->GetString(prefs::kRapporSecret);
   if (!secret_base64.empty()) {
     bool decoded = base::Base64Decode(secret_base64, &secret_);
     if (decoded && secret_.size() == HmacByteVectorGenerator::kEntropyInputSize)
@@ -132,8 +136,9 @@
   DCHECK_GE(cohort_, 0);
   reports->set_cohort(cohort_);
 
-  for (std::map<std::string, RapporMetric*>::iterator it = metrics_map_.begin();
-       metrics_map_.end() != it;
+  for (std::map<std::string, RapporMetric*>::const_iterator it =
+           metrics_map_.begin();
+       it != metrics_map_.end();
        ++it) {
     const RapporMetric* metric = it->second;
     RapporReports::Report* report = reports->add_report();
@@ -163,7 +168,6 @@
                                          const RapporParameters& parameters,
                                          const std::string& sample) {
   DCHECK(IsInitialized());
-
   RapporMetric* metric = LookUpMetric(metric_name, parameters);
   metric->AddSample(sample);
 }
@@ -171,9 +175,9 @@
 RapporMetric* RapporService::LookUpMetric(const std::string& metric_name,
                                           const RapporParameters& parameters) {
   DCHECK(IsInitialized());
-  std::map<std::string, RapporMetric*>::iterator it =
+  std::map<std::string, RapporMetric*>::const_iterator it =
       metrics_map_.find(metric_name);
-  if (metrics_map_.end() != it) {
+  if (it != metrics_map_.end()) {
     RapporMetric* metric = it->second;
     DCHECK_EQ(parameters.ToString(), metric->parameters().ToString());
     return metric;
diff --git a/components/rappor/rappor_service.h b/components/rappor/rappor_service.h
index 9e2cd9b..323e9ba 100644
--- a/components/rappor/rappor_service.h
+++ b/components/rappor/rappor_service.h
@@ -5,22 +5,31 @@
 #ifndef COMPONENTS_RAPPOR_RAPPOR_SERVICE_H_
 #define COMPONENTS_RAPPOR_RAPPOR_SERVICE_H_
 
+#include <map>
 #include <string>
 
 #include "base/basictypes.h"
-#include "base/prefs/pref_service.h"
-#include "base/time/time.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/timer/timer.h"
-#include "components/rappor/log_uploader.h"
-#include "components/rappor/proto/rappor_metric.pb.h"
-#include "components/rappor/rappor_metric.h"
 
 class PrefRegistrySimple;
+class PrefService;
+
+namespace net {
+class URLRequestContextGetter;
+}
 
 namespace rappor {
 
+class LogUploader;
+class RapporMetric;
+class RapporReports;
+struct RapporParameters;
+
 // The type of data stored in a metric.
 enum RapporType {
+  // For sampling the eTLD+1 of a URL.
   ETLD_PLUS_ONE_RAPPOR_TYPE = 0,
   NUM_RAPPOR_TYPES
 };
@@ -52,8 +61,9 @@
   static void RegisterPrefs(PrefRegistrySimple* registry);
 
  protected:
-  // Logs all of the collected metrics to the reports proto message.  Exposed
-  // for tests.  Returns true if any metrics were recorded.
+  // Logs all of the collected metrics to the reports proto message and clears
+  // the internal map.  Exposed for tests.  Returns true if any metrics were
+  // recorded.
   bool ExportMetrics(RapporReports* reports);
 
   // Records a sample of the rappor metric specified by |parameters|.
@@ -91,7 +101,7 @@
   // The cohort this client is assigned to. -1 is uninitialized.
   int32_t cohort_;
 
-  // Timer which schedules calls to OnLogInterval()
+  // Timer which schedules calls to OnLogInterval().
   base::OneShotTimer<RapporService> log_rotation_timer_;
 
   // A private LogUploader instance for sending reports to the server.
diff --git a/components/rappor/rappor_service_unittest.cc b/components/rappor/rappor_service_unittest.cc
index 790eae7..a36e960 100644
--- a/components/rappor/rappor_service_unittest.cc
+++ b/components/rappor/rappor_service_unittest.cc
@@ -4,6 +4,9 @@
 
 #include "components/rappor/rappor_service.h"
 
+#include "components/rappor/byte_vector_utils.h"
+#include "components/rappor/proto/rappor_metric.pb.h"
+#include "components/rappor/rappor_parameters.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace rappor {
@@ -27,8 +30,7 @@
       PROBABILITY_75 /* Fake data probability */,
       PROBABILITY_50 /* Fake one probability */,
       PROBABILITY_75 /* One coin probability */,
-      PROBABILITY_50 /* Zero coin probability */
-  };
+      PROBABILITY_50 /* Zero coin probability */};
 
   TestRapporService rappor_service;
   rappor_service.SetCohortForTesting(0);
diff --git a/components/resources/dom_distiller_resources.grdp b/components/resources/dom_distiller_resources.grdp
index 1ef1ac5..edb3489 100644
--- a/components/resources/dom_distiller_resources.grdp
+++ b/components/resources/dom_distiller_resources.grdp
@@ -5,5 +5,5 @@
   <include name="IDR_ABOUT_DOM_DISTILLER_JS" file="../dom_distiller/webui/resources/about_dom_distiller.js" type="BINDATA" />
   <include name="IDR_DOM_DISTILLER_VIEWER_HTML" file="../dom_distiller/content/resources/dom_distiller_viewer.html" type="BINDATA" />
   <include name="IDR_DISTILLER_JS" file="../dom_distiller/core/javascript/domdistiller.js" flattenhtml="true" type="BINDATA" />
-  <include name="IDR_DISTILLER_CSS" file="../../third_party/readability/css/readability.css" type="BINDATA" />
+  <include name="IDR_DISTILLER_CSS" file="../dom_distiller/core/css/distilledpage.css" type="BINDATA" />
 </grit-part>
diff --git a/components/signin.gypi b/components/signin.gypi
index 2b83a0c..01c64af 100644
--- a/components/signin.gypi
+++ b/components/signin.gypi
@@ -5,44 +5,77 @@
 {
   'targets': [
     {
-      'target_name': 'signin_core',
+      'target_name': 'signin_core_common',
+      'type': 'static_library',
+      'include_dirs': [
+        '..',
+      ],
+      'sources': [
+        'signin/core/common/signin_pref_names.cc',
+        'signin/core/common/signin_pref_names.h',
+        'signin/core/common/signin_switches.cc',
+        'signin/core/common/signin_switches.h',
+      ],
+    },
+    {
+      'target_name': 'signin_core_browser',
       'type': 'static_library',
       'dependencies': [
         '../base/base.gyp:base',
+        '../crypto/crypto.gyp:crypto',
         '../google_apis/google_apis.gyp:google_apis',
         '../net/net.gyp:net',
         '../sql/sql.gyp:sql',
         'keyed_service_core',
         'os_crypt',
+        'signin_core_common',
         'webdata_common',
       ],
       'include_dirs': [
         '..',
       ],
       'sources': [
-        'signin/core/mutable_profile_oauth2_token_service.cc',
-        'signin/core/mutable_profile_oauth2_token_service.h',
-        'signin/core/profile_oauth2_token_service.cc',
-        'signin/core/profile_oauth2_token_service.h',
-        'signin/core/signin_client.h',
-        'signin/core/signin_error_controller.cc',
-        'signin/core/signin_error_controller.h',
-        'signin/core/signin_manager_cookie_helper.cc',
-        'signin/core/signin_manager_cookie_helper.h',
-        'signin/core/webdata/token_service_table.cc',
-        'signin/core/webdata/token_service_table.h',
-        'signin/core/webdata/token_web_data.cc',
-        'signin/core/webdata/token_web_data.h',
+        'signin/core/browser/mutable_profile_oauth2_token_service.cc',
+        'signin/core/browser/mutable_profile_oauth2_token_service.h',
+        'signin/core/browser/profile_oauth2_token_service.cc',
+        'signin/core/browser/profile_oauth2_token_service.h',
+        'signin/core/browser/signin_client.h',
+        'signin/core/browser/signin_error_controller.cc',
+        'signin/core/browser/signin_error_controller.h',
+        'signin/core/browser/signin_internals_util.cc',
+        'signin/core/browser/signin_internals_util.h',
+        'signin/core/browser/signin_manager_base.cc',
+        'signin/core/browser/signin_manager_base.h',
+        'signin/core/browser/signin_manager_cookie_helper.cc',
+        'signin/core/browser/signin_manager_cookie_helper.h',
+        'signin/core/browser/webdata/token_service_table.cc',
+        'signin/core/browser/webdata/token_service_table.h',
+        'signin/core/browser/webdata/token_web_data.cc',
+        'signin/core/browser/webdata/token_web_data.h',
+      ],
+      'conditions': [
+        ['OS=="android"', {
+          'sources!': [
+            # Not used on Android.
+            'signin/core/browser/mutable_profile_oauth2_token_service.cc',
+            'signin/core/browser/mutable_profile_oauth2_token_service.h',
+          ],
+        }],
       ],
     },
-  ],
-  'conditions': [
-    ['OS=="android"', {
-      'sources!': [
-        # Not used on Android.
-        'signin/core/mutable_profile_oauth2_token_service.cc',
-        'signin/core/mutable_profile_oauth2_token_service.h',
+    {
+      'target_name': 'signin_core_browser_test_support',
+      'type': 'static_library',
+      'dependencies': [
+        'signin_core_browser',
       ],
-    }],
+      'include_dirs': [
+        '..',
+      ],
+      'sources': [
+        'signin/core/browser/fake_auth_status_provider.cc',
+        'signin/core/browser/fake_auth_status_provider.h',
+      ],
+    },
   ],
 }
diff --git a/components/signin/DEPS b/components/signin/DEPS
index 046e713..6aef403 100644
--- a/components/signin/DEPS
+++ b/components/signin/DEPS
@@ -2,6 +2,7 @@
   "+components/keyed_service/core",
   "+components/os_crypt",
   "+components/webdata/common",
+  "+crypto",
   "+google_apis/gaia",
   "+grit",  # For generated headers
   "+net",
diff --git a/components/signin/OWNERS b/components/signin/OWNERS
index 7300c05..21253b0 100644
--- a/components/signin/OWNERS
+++ b/components/signin/OWNERS
@@ -1,3 +1,5 @@
 atwilson@chromium.org
 tim@chromium.org
-rogerta@chromium.org
\ No newline at end of file
+rogerta@chromium.org
+# Temporary, for refactoring purposes only
+blundell@chromium.org
diff --git a/components/signin/core/browser/fake_auth_status_provider.cc b/components/signin/core/browser/fake_auth_status_provider.cc
new file mode 100644
index 0000000..77e10db
--- /dev/null
+++ b/components/signin/core/browser/fake_auth_status_provider.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+
+FakeAuthStatusProvider::FakeAuthStatusProvider(SigninErrorController* error)
+  : error_provider_(error),
+    auth_error_(GoogleServiceAuthError::AuthErrorNone()) {
+  error_provider_->AddProvider(this);
+}
+
+FakeAuthStatusProvider::~FakeAuthStatusProvider() {
+  error_provider_->RemoveProvider(this);
+}
+
+std::string FakeAuthStatusProvider::GetAccountId() const {
+  return account_id_;
+}
+
+GoogleServiceAuthError FakeAuthStatusProvider::GetAuthStatus() const {
+  return auth_error_;
+}
+
+void FakeAuthStatusProvider::SetAuthError(const std::string& account_id,
+                                          const GoogleServiceAuthError& error) {
+  account_id_ = account_id;
+  auth_error_ = error;
+  error_provider_->AuthStatusChanged();
+}
diff --git a/components/signin/core/browser/fake_auth_status_provider.h b/components/signin/core/browser/fake_auth_status_provider.h
new file mode 100644
index 0000000..91f1024
--- /dev/null
+++ b/components/signin/core/browser/fake_auth_status_provider.h
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_FAKE_AUTH_STATUS_PROVIDER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_FAKE_AUTH_STATUS_PROVIDER_H_
+
+#include "components/signin/core/browser/signin_error_controller.h"
+
+// Helper class that reports auth errors to SigninErrorController. Automatically
+// registers and de-registers itself as an AuthStatusProvider in the
+// constructor and destructor.
+class FakeAuthStatusProvider
+    : public SigninErrorController::AuthStatusProvider {
+ public:
+  explicit FakeAuthStatusProvider(SigninErrorController* error);
+  virtual ~FakeAuthStatusProvider();
+
+  // Sets the auth error that this provider reports to SigninErrorController.
+  // Also notifies SigninErrorController via AuthStatusChanged().
+  void SetAuthError(const std::string& account_id,
+                    const GoogleServiceAuthError& error);
+
+  void set_error_without_status_change(const GoogleServiceAuthError& error) {
+    auth_error_ = error;
+  }
+
+  // AuthStatusProvider implementation.
+  virtual std::string GetAccountId() const OVERRIDE;
+  virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
+
+ private:
+  SigninErrorController* error_provider_;
+  std::string account_id_;
+  GoogleServiceAuthError auth_error_;
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_FAKE_AUTH_STATUS_PROVIDER_H_
diff --git a/components/signin/core/browser/mutable_profile_oauth2_token_service.cc b/components/signin/core/browser/mutable_profile_oauth2_token_service.cc
new file mode 100644
index 0000000..a0acd23
--- /dev/null
+++ b/components/signin/core/browser/mutable_profile_oauth2_token_service.cc
@@ -0,0 +1,384 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/mutable_profile_oauth2_token_service.h"
+
+#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/core/browser/webdata/token_web_data.h"
+#include "components/webdata/common/web_data_service_base.h"
+#include "google_apis/gaia/gaia_auth_fetcher.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace {
+
+const char kAccountIdPrefix[] = "AccountId-";
+const size_t kAccountIdPrefixLength = 10;
+
+std::string ApplyAccountIdPrefix(const std::string& account_id) {
+  return kAccountIdPrefix + account_id;
+}
+
+bool IsLegacyRefreshTokenId(const std::string& service_id) {
+  return service_id == GaiaConstants::kGaiaOAuth2LoginRefreshToken;
+}
+
+bool IsLegacyServiceId(const std::string& account_id) {
+  return account_id.compare(0u, kAccountIdPrefixLength, kAccountIdPrefix) != 0;
+}
+
+std::string RemoveAccountIdPrefix(const std::string& prefixed_account_id) {
+  return prefixed_account_id.substr(kAccountIdPrefixLength);
+}
+
+}  // namespace
+
+// This class sends a request to GAIA to revoke the given refresh token from
+// the server.  This is a best effort attempt only.  This class deletes itself
+// when done sucessfully or otherwise.
+class MutableProfileOAuth2TokenService::RevokeServerRefreshToken
+    : public GaiaAuthConsumer {
+ public:
+  RevokeServerRefreshToken(MutableProfileOAuth2TokenService* token_service,
+                           const std::string& account_id);
+  virtual ~RevokeServerRefreshToken();
+
+ private:
+  // GaiaAuthConsumer overrides:
+  virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE;
+
+  MutableProfileOAuth2TokenService* token_service_;
+  GaiaAuthFetcher fetcher_;
+
+  DISALLOW_COPY_AND_ASSIGN(RevokeServerRefreshToken);
+};
+
+MutableProfileOAuth2TokenService::
+    RevokeServerRefreshToken::RevokeServerRefreshToken(
+    MutableProfileOAuth2TokenService* token_service,
+    const std::string& refresh_token)
+    : token_service_(token_service),
+      fetcher_(this, GaiaConstants::kChromeSource,
+               token_service_->GetRequestContext()) {
+  fetcher_.StartRevokeOAuth2Token(refresh_token);
+}
+
+MutableProfileOAuth2TokenService::
+    RevokeServerRefreshToken::~RevokeServerRefreshToken() {}
+
+void MutableProfileOAuth2TokenService::
+    RevokeServerRefreshToken::OnOAuth2RevokeTokenCompleted() {
+  // |this| pointer will be deleted when removed from the vector, so don't
+  // access any members after call to erase().
+  token_service_->server_revokes_.erase(
+      std::find(token_service_->server_revokes_.begin(),
+                token_service_->server_revokes_.end(),
+                this));
+}
+
+MutableProfileOAuth2TokenService::AccountInfo::AccountInfo(
+    ProfileOAuth2TokenService* token_service,
+    const std::string& account_id,
+    const std::string& refresh_token)
+  : token_service_(token_service),
+    account_id_(account_id),
+    refresh_token_(refresh_token),
+    last_auth_error_(GoogleServiceAuthError::NONE) {
+  DCHECK(token_service_);
+  DCHECK(!account_id_.empty());
+  token_service_->signin_error_controller()->AddProvider(this);
+}
+
+MutableProfileOAuth2TokenService::AccountInfo::~AccountInfo() {
+  token_service_->signin_error_controller()->RemoveProvider(this);
+}
+
+void MutableProfileOAuth2TokenService::AccountInfo::SetLastAuthError(
+    const GoogleServiceAuthError& error) {
+  if (error.state() != last_auth_error_.state()) {
+    last_auth_error_ = error;
+    token_service_->signin_error_controller()->AuthStatusChanged();
+  }
+}
+
+std::string
+MutableProfileOAuth2TokenService::AccountInfo::GetAccountId() const {
+  return account_id_;
+}
+
+GoogleServiceAuthError
+MutableProfileOAuth2TokenService::AccountInfo::GetAuthStatus() const {
+  return last_auth_error_;
+}
+
+MutableProfileOAuth2TokenService::MutableProfileOAuth2TokenService()
+    : web_data_service_request_(0)  {
+}
+
+MutableProfileOAuth2TokenService::~MutableProfileOAuth2TokenService() {
+  DCHECK(server_revokes_.empty());
+}
+
+void MutableProfileOAuth2TokenService::Shutdown() {
+  server_revokes_.clear();
+  CancelWebTokenFetch();
+  CancelAllRequests();
+  refresh_tokens_.clear();
+
+  ProfileOAuth2TokenService::Shutdown();
+}
+
+bool MutableProfileOAuth2TokenService::RefreshTokenIsAvailable(
+    const std::string& account_id) const {
+  return !GetRefreshToken(account_id).empty();
+}
+
+std::string MutableProfileOAuth2TokenService::GetRefreshToken(
+    const std::string& account_id) const {
+  AccountInfoMap::const_iterator iter = refresh_tokens_.find(account_id);
+  if (iter != refresh_tokens_.end())
+    return iter->second->refresh_token();
+  return std::string();
+}
+
+OAuth2AccessTokenFetcher*
+MutableProfileOAuth2TokenService::CreateAccessTokenFetcher(
+    const std::string& account_id,
+    net::URLRequestContextGetter* getter,
+    OAuth2AccessTokenConsumer* consumer) {
+  std::string refresh_token = GetRefreshToken(account_id);
+  DCHECK(!refresh_token.empty());
+  return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token);
+}
+
+net::URLRequestContextGetter*
+MutableProfileOAuth2TokenService::GetRequestContext() {
+  return client()->GetURLRequestContext();
+}
+
+void MutableProfileOAuth2TokenService::LoadCredentials(
+    const std::string& primary_account_id) {
+  DCHECK(!primary_account_id.empty());
+  DCHECK(loading_primary_account_id_.empty());
+  DCHECK_EQ(0, web_data_service_request_);
+
+  CancelAllRequests();
+  refresh_tokens().clear();
+  loading_primary_account_id_ = primary_account_id;
+  scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
+  if (token_web_data.get())
+    web_data_service_request_ = token_web_data->GetAllTokens(this);
+}
+
+void MutableProfileOAuth2TokenService::OnWebDataServiceRequestDone(
+    WebDataServiceBase::Handle handle,
+    const WDTypedResult* result) {
+  DCHECK_EQ(web_data_service_request_, handle);
+  web_data_service_request_ = 0;
+
+  if (result) {
+    DCHECK(result->GetType() == TOKEN_RESULT);
+    const WDResult<std::map<std::string, std::string> > * token_result =
+        static_cast<const WDResult<std::map<std::string, std::string> > * > (
+            result);
+    LoadAllCredentialsIntoMemory(token_result->GetValue());
+  }
+
+  // Make sure that we have an entry for |loading_primary_account_id_| in the
+  // map.  The entry could be missing if there is a corruption in the token DB
+  // while this profile is connected to an account.
+  DCHECK(!loading_primary_account_id_.empty());
+  if (refresh_tokens().count(loading_primary_account_id_) == 0) {
+    refresh_tokens()[loading_primary_account_id_].reset(
+        new AccountInfo(this, loading_primary_account_id_, std::string()));
+  }
+
+  // If we don't have a refresh token for a known account, signal an error.
+  for (AccountInfoMap::const_iterator i = refresh_tokens_.begin();
+       i != refresh_tokens_.end(); ++i) {
+    if (!RefreshTokenIsAvailable(i->first)) {
+      UpdateAuthError(
+          i->first,
+          GoogleServiceAuthError(
+              GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+      break;
+    }
+  }
+
+  loading_primary_account_id_.clear();
+}
+
+void MutableProfileOAuth2TokenService::LoadAllCredentialsIntoMemory(
+    const std::map<std::string, std::string>& db_tokens) {
+  std::string old_login_token;
+
+  for (std::map<std::string, std::string>::const_iterator iter =
+           db_tokens.begin();
+       iter != db_tokens.end();
+       ++iter) {
+    std::string prefixed_account_id = iter->first;
+    std::string refresh_token = iter->second;
+
+    if (IsLegacyRefreshTokenId(prefixed_account_id) && !refresh_token.empty())
+      old_login_token = refresh_token;
+
+    if (IsLegacyServiceId(prefixed_account_id)) {
+      scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
+      if (token_web_data.get())
+        token_web_data->RemoveTokenForService(prefixed_account_id);
+    } else {
+      DCHECK(!refresh_token.empty());
+      std::string account_id = RemoveAccountIdPrefix(prefixed_account_id);
+      refresh_tokens()[account_id].reset(
+          new AccountInfo(this, account_id, refresh_token));
+      FireRefreshTokenAvailable(account_id);
+      // TODO(fgorski): Notify diagnostic observers.
+    }
+  }
+
+  if (!old_login_token.empty()) {
+    DCHECK(!loading_primary_account_id_.empty());
+    if (refresh_tokens().count(loading_primary_account_id_) == 0)
+      UpdateCredentials(loading_primary_account_id_, old_login_token);
+  }
+
+  FireRefreshTokensLoaded();
+}
+
+void MutableProfileOAuth2TokenService::UpdateAuthError(
+    const std::string& account_id,
+    const GoogleServiceAuthError& error) {
+  // Do not report connection errors as these are not actually auth errors.
+  // We also want to avoid masking a "real" auth error just because we
+  // subsequently get a transient network error.
+  if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
+      error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE)
+    return;
+
+#if defined(OS_IOS)
+  // ProfileOauth2TokenService does not manage the refresh tokens on iOS - the
+  // account info on iOS is only used to manage the authentication error state.
+  // Simply add an account info entry with empty refresh token if none exists.
+  if (refresh_tokens_.count(account_id) == 0) {
+      refresh_tokens_[account_id].reset(
+          new AccountInfo(this, account_id, std::string()));
+  }
+#endif
+
+  if (refresh_tokens_.count(account_id) == 0) {
+    // This could happen if the preferences have been corrupted (see
+    // http://crbug.com/321370). In a Debug build that would be a bug, but in a
+    // Release build we want to deal with it gracefully.
+    NOTREACHED();
+    return;
+  }
+  refresh_tokens_[account_id]->SetLastAuthError(error);
+}
+
+std::vector<std::string> MutableProfileOAuth2TokenService::GetAccounts() {
+  std::vector<std::string> account_ids;
+  for (AccountInfoMap::const_iterator iter = refresh_tokens_.begin();
+           iter != refresh_tokens_.end(); ++iter) {
+    account_ids.push_back(iter->first);
+  }
+  return account_ids;
+}
+
+void MutableProfileOAuth2TokenService::UpdateCredentials(
+    const std::string& account_id,
+    const std::string& refresh_token) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!account_id.empty());
+  DCHECK(!refresh_token.empty());
+
+  bool refresh_token_present = refresh_tokens_.count(account_id) > 0;
+  if (!refresh_token_present ||
+      refresh_tokens_[account_id]->refresh_token() != refresh_token) {
+    // If token present, and different from the new one, cancel its requests,
+    // and clear the entries in cache related to that account.
+    if (refresh_token_present) {
+      std::string revoke_reason = refresh_token_present ? "token differs" :
+                                                          "token is missing";
+      LOG(WARNING) << "Revoking refresh token on server. "
+                   << "Reason: token update, " << revoke_reason;
+      RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
+      CancelRequestsForAccount(account_id);
+      ClearCacheForAccount(account_id);
+      refresh_tokens_[account_id]->set_refresh_token(refresh_token);
+    } else {
+      refresh_tokens_[account_id].reset(
+          new AccountInfo(this, account_id, refresh_token));
+    }
+
+    // Save the token in memory and in persistent store.
+    PersistCredentials(account_id, refresh_token);
+
+    UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
+    FireRefreshTokenAvailable(account_id);
+  }
+}
+
+void MutableProfileOAuth2TokenService::RevokeCredentials(
+    const std::string& account_id) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  if (refresh_tokens_.count(account_id) > 0) {
+    RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
+    CancelRequestsForAccount(account_id);
+    ClearCacheForAccount(account_id);
+    refresh_tokens_.erase(account_id);
+    ClearPersistedCredentials(account_id);
+    FireRefreshTokenRevoked(account_id);
+  }
+}
+
+void MutableProfileOAuth2TokenService::PersistCredentials(
+    const std::string& account_id,
+    const std::string& refresh_token) {
+  scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
+  if (token_web_data.get()) {
+    token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id),
+                                       refresh_token);
+  }
+}
+
+void MutableProfileOAuth2TokenService::ClearPersistedCredentials(
+    const std::string& account_id) {
+  scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
+  if (token_web_data.get())
+    token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
+}
+
+void MutableProfileOAuth2TokenService::RevokeAllCredentials() {
+  if (!client()->CanRevokeCredentials())
+    return;
+  DCHECK(thread_checker_.CalledOnValidThread());
+  CancelWebTokenFetch();
+  CancelAllRequests();
+  ClearCache();
+  AccountInfoMap tokens = refresh_tokens_;
+  for (AccountInfoMap::iterator i = tokens.begin(); i != tokens.end(); ++i)
+    RevokeCredentials(i->first);
+
+  DCHECK_EQ(0u, refresh_tokens_.size());
+}
+
+void MutableProfileOAuth2TokenService::RevokeCredentialsOnServer(
+    const std::string& refresh_token) {
+  // Keep track or all server revoke requests.  This way they can be deleted
+  // before the token service is shutdown and won't outlive the profile.
+  server_revokes_.push_back(
+      new RevokeServerRefreshToken(this, refresh_token));
+}
+
+void MutableProfileOAuth2TokenService::CancelWebTokenFetch() {
+  if (web_data_service_request_ != 0) {
+    scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
+    DCHECK(token_web_data.get());
+    token_web_data->CancelRequest(web_data_service_request_);
+    web_data_service_request_  = 0;
+  }
+}
diff --git a/components/signin/core/browser/mutable_profile_oauth2_token_service.h b/components/signin/core/browser/mutable_profile_oauth2_token_service.h
new file mode 100644
index 0000000..4f10555
--- /dev/null
+++ b/components/signin/core/browser/mutable_profile_oauth2_token_service.h
@@ -0,0 +1,144 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+
+#include "base/memory/scoped_vector.h"
+#include "base/threading/thread_checker.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/webdata/common/web_data_service_base.h"
+#include "components/webdata/common/web_data_service_consumer.h"
+
+// A specialization of ProfileOAuth2TokenService that can can mutate its OAuth2
+// tokens.
+//
+// Note: This class is just a placeholder for now. Methods used to mutate
+// the tokens are currently being migrated from ProfileOAuth2TokenService.
+class MutableProfileOAuth2TokenService : public ProfileOAuth2TokenService,
+                                         public WebDataServiceConsumer  {
+ public:
+  // ProfileOAuth2TokenService overrides.
+  virtual void Shutdown() OVERRIDE;
+  virtual std::vector<std::string> GetAccounts() OVERRIDE;
+
+  // The below three methods should be called only on the thread on which this
+  // object was created.
+  virtual void LoadCredentials(const std::string& primary_account_id) OVERRIDE;
+  virtual void UpdateCredentials(const std::string& account_id,
+                                 const std::string& refresh_token) OVERRIDE;
+  virtual void RevokeAllCredentials() OVERRIDE;
+  virtual bool RefreshTokenIsAvailable(const std::string& account_id) const
+      OVERRIDE;
+
+  // Revokes credentials related to |account_id|.
+  void RevokeCredentials(const std::string& account_id);
+
+ protected:
+  class AccountInfo : public SigninErrorController::AuthStatusProvider {
+   public:
+    AccountInfo(ProfileOAuth2TokenService* token_service,
+                const std::string& account_id,
+                const std::string& refresh_token);
+    virtual ~AccountInfo();
+
+    const std::string& refresh_token() const { return refresh_token_; }
+    void set_refresh_token(const std::string& token) {
+      refresh_token_ = token;
+    }
+
+    void SetLastAuthError(const GoogleServiceAuthError& error);
+
+    // SigninErrorController::AuthStatusProvider implementation.
+    virtual std::string GetAccountId() const OVERRIDE;
+    virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
+
+   private:
+    ProfileOAuth2TokenService* token_service_;
+    std::string account_id_;
+    std::string refresh_token_;
+    GoogleServiceAuthError last_auth_error_;
+
+    DISALLOW_COPY_AND_ASSIGN(AccountInfo);
+  };
+
+  // Maps the |account_id| of accounts known to ProfileOAuth2TokenService
+  // to information about the account.
+  typedef std::map<std::string, linked_ptr<AccountInfo> > AccountInfoMap;
+
+  friend class ProfileOAuth2TokenServiceFactory;
+
+  MutableProfileOAuth2TokenService();
+  virtual ~MutableProfileOAuth2TokenService();
+
+  // OAuth2TokenService implementation.
+  virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
+      const std::string& account_id,
+      net::URLRequestContextGetter* getter,
+      OAuth2AccessTokenConsumer* consumer) OVERRIDE;
+  virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
+
+  // Updates the internal cache of the result from the most-recently-completed
+  // auth request (used for reporting errors to the user).
+  virtual void UpdateAuthError(const std::string& account_id,
+                               const GoogleServiceAuthError& error) OVERRIDE;
+
+  virtual std::string GetRefreshToken(const std::string& account_id) const;
+
+  AccountInfoMap& refresh_tokens() { return refresh_tokens_; }
+
+ private:
+  class RevokeServerRefreshToken;
+
+  FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceTest,
+                           TokenServiceUpdateClearsCache);
+  FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceTest,
+                           PersistenceDBUpgrade);
+  FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceTest,
+                           PersistenceLoadCredentials);
+
+  // WebDataServiceConsumer implementation:
+  virtual void OnWebDataServiceRequestDone(
+      WebDataServiceBase::Handle handle,
+      const WDTypedResult* result) OVERRIDE;
+
+  // Loads credentials into in memory stucture.
+  void LoadAllCredentialsIntoMemory(
+      const std::map<std::string, std::string>& db_tokens);
+
+  // Persists credentials for |account_id|. Enables overriding for
+  // testing purposes, or other cases, when accessing the DB is not desired.
+  void PersistCredentials(const std::string& account_id,
+                          const std::string& refresh_token);
+
+  // Clears credentials persisted for |account_id|. Enables overriding for
+  // testing purposes, or other cases, when accessing the DB is not desired.
+  void ClearPersistedCredentials(const std::string& account_id);
+
+  // Revokes the refresh token on the server.
+  void RevokeCredentialsOnServer(const std::string& refresh_token);
+
+  // Cancels any outstanding fetch for tokens from the web database.
+  void CancelWebTokenFetch();
+
+  // In memory refresh token store mapping account_id to refresh_token.
+  AccountInfoMap refresh_tokens_;
+
+  // Handle to the request reading tokens from database.
+  WebDataServiceBase::Handle web_data_service_request_;
+
+  // The primary account id of this service's profile during the loading of
+  // credentials.  This member is empty otherwise.
+  std::string loading_primary_account_id_;
+
+  ScopedVector<RevokeServerRefreshToken> server_revokes_;
+
+  // Used to verify that certain methods are called only on the thread on which
+  // this instance was created.
+  base::ThreadChecker thread_checker_;
+
+  DISALLOW_COPY_AND_ASSIGN(MutableProfileOAuth2TokenService);
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
diff --git a/components/signin/core/browser/profile_oauth2_token_service.cc b/components/signin/core/browser/profile_oauth2_token_service.cc
new file mode 100644
index 0000000..757d96e
--- /dev/null
+++ b/components/signin/core/browser/profile_oauth2_token_service.cc
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "base/stl_util.h"
+#include "base/time/time.h"
+#include "components/signin/core/browser/signin_error_controller.h"
+#include "net/url_request/url_request_context_getter.h"
+
+ProfileOAuth2TokenService::ProfileOAuth2TokenService()
+    : client_(NULL) {}
+
+ProfileOAuth2TokenService::~ProfileOAuth2TokenService() {
+  DCHECK(!signin_error_controller_.get()) <<
+      "ProfileOAuth2TokenService::Initialize called but not "
+      "ProfileOAuth2TokenService::Shutdown";
+}
+
+void ProfileOAuth2TokenService::Initialize(SigninClient* client) {
+  DCHECK(client);
+  DCHECK(!client_);
+  client_ = client;
+
+  signin_error_controller_.reset(new SigninErrorController());
+}
+
+void ProfileOAuth2TokenService::Shutdown() {
+  DCHECK(client_) << "Shutdown() called without matching call to Initialize()";
+  signin_error_controller_.reset();
+}
+
+net::URLRequestContextGetter* ProfileOAuth2TokenService::GetRequestContext() {
+  return NULL;
+}
+
+void ProfileOAuth2TokenService::UpdateAuthError(
+    const std::string& account_id,
+    const GoogleServiceAuthError& error) {
+  NOTREACHED();
+}
+
+std::vector<std::string> ProfileOAuth2TokenService::GetAccounts() {
+  NOTREACHED();
+  return std::vector<std::string>();
+}
+
+void ProfileOAuth2TokenService::LoadCredentials(
+    const std::string& primary_account_id) {
+  // Empty implementation by default.
+}
+
+void ProfileOAuth2TokenService::UpdateCredentials(
+    const std::string& account_id,
+    const std::string& refresh_token) {
+  NOTREACHED();
+}
+
+void ProfileOAuth2TokenService::RevokeAllCredentials() {
+  // Empty implementation by default.
+}
+
diff --git a/components/signin/core/browser/profile_oauth2_token_service.h b/components/signin/core/browser/profile_oauth2_token_service.h
new file mode 100644
index 0000000..365b53a
--- /dev/null
+++ b/components/signin/core/browser/profile_oauth2_token_service.h
@@ -0,0 +1,106 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
+
+#include <string>
+
+#include "base/gtest_prod_util.h"
+#include "base/memory/linked_ptr.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/signin_error_controller.h"
+#include "google_apis/gaia/oauth2_token_service.h"
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+class GoogleServiceAuthError;
+class SigninClient;
+
+// ProfileOAuth2TokenService is a KeyedService that retrieves
+// OAuth2 access tokens for a given set of scopes using the OAuth2 login
+// refresh tokens.
+//
+// See |OAuth2TokenService| for usage details.
+//
+// Note: after StartRequest returns, in-flight requests will continue
+// even if the TokenService refresh token that was used to initiate
+// the request changes or is cleared.  When the request completes,
+// Consumer::OnGetTokenSuccess will be invoked, but the access token
+// won't be cached.
+//
+// Note: requests should be started from the UI thread. To start a
+// request from other thread, please use ProfileOAuth2TokenServiceRequest.
+class ProfileOAuth2TokenService : public OAuth2TokenService,
+                                  public KeyedService {
+ public:
+  virtual ~ProfileOAuth2TokenService();
+
+  // Initializes this token service with the SigninClient.
+  virtual void Initialize(SigninClient* client);
+
+  // KeyedService implementation.
+  virtual void Shutdown() OVERRIDE;
+
+  // Lists account IDs of all accounts with a refresh token.
+  virtual std::vector<std::string> GetAccounts() OVERRIDE;
+
+  // Loads credentials from a backing persistent store to make them available
+  // after service is used between profile restarts.
+  //
+  // Only call this method if there is at least one account connected to the
+  // profile, otherwise startup will cause unneeded work on the IO thread.  The
+  // primary account is specified with the |primary_account_id| argument and
+  // should not be empty.  For a regular profile, the primary account id comes
+  // from SigninManager.  For a managed account, the id comes from
+  // ManagedUserService.
+  virtual void LoadCredentials(const std::string& primary_account_id);
+
+  // Updates a |refresh_token| for an |account_id|. Credentials are persisted,
+  // and available through |LoadCredentials| after service is restarted.
+  virtual void UpdateCredentials(const std::string& account_id,
+                                 const std::string& refresh_token);
+
+  // Revokes all credentials handled by the object.
+  virtual void RevokeAllCredentials();
+
+  SigninErrorController* signin_error_controller() {
+    return signin_error_controller_.get();
+  }
+
+  const SigninErrorController* signin_error_controller() const {
+    return signin_error_controller_.get();
+  }
+
+  SigninClient* client() const { return client_; }
+
+ protected:
+  ProfileOAuth2TokenService();
+
+  // OAuth2TokenService overrides.
+  // Note: These methods are overriden so that ProfileOAuth2TokenService is a
+  // concrete class.
+
+  // Simply returns NULL and should be overriden by subsclasses.
+  virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
+
+  // Updates the internal cache of the result from the most-recently-completed
+  // auth request (used for reporting errors to the user).
+  virtual void UpdateAuthError(
+      const std::string& account_id,
+      const GoogleServiceAuthError& error) OVERRIDE;
+
+ private:
+  // The client with which this instance was initialized, or NULL.
+  SigninClient* client_;
+
+  // Used to expose auth errors to the UI.
+  scoped_ptr<SigninErrorController> signin_error_controller_;
+
+  DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenService);
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_PROFILE_OAUTH2_TOKEN_SERVICE_H_
diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h
new file mode 100644
index 0000000..0a681f7
--- /dev/null
+++ b/components/signin/core/browser/signin_client.h
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_
+
+#include "components/signin/core/browser/webdata/token_web_data.h"
+
+class PrefService;
+class SigninManagerBase;
+class TokenWebData;
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+// An interface that needs to be supplied to the Signin component by its
+// embedder.
+class SigninClient {
+ public:
+  virtual ~SigninClient() {}
+
+  // Gets the preferences associated with the client.
+  virtual PrefService* GetPrefs() = 0;
+
+  // Gets the TokenWebData instance associated with the client.
+  virtual scoped_refptr<TokenWebData> GetDatabase() = 0;
+
+  // Returns whether it is possible to revoke credentials.
+  virtual bool CanRevokeCredentials() = 0;
+
+  // Returns the URL request context information associated with the client.
+  virtual net::URLRequestContextGetter* GetURLRequestContext() = 0;
+
+  // Called when Google signin has succeeded.
+  virtual void GoogleSigninSucceeded(const std::string& username,
+                                     const std::string& password) {}
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_CLIENT_H_
diff --git a/components/signin/core/browser/signin_error_controller.cc b/components/signin/core/browser/signin_error_controller.cc
new file mode 100644
index 0000000..3d3060b
--- /dev/null
+++ b/components/signin/core/browser/signin_error_controller.cc
@@ -0,0 +1,106 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/signin_error_controller.h"
+
+namespace {
+
+typedef std::set<const SigninErrorController::AuthStatusProvider*>
+    AuthStatusProviderSet;
+
+}  // namespace
+
+SigninErrorController::AuthStatusProvider::AuthStatusProvider() {
+}
+
+SigninErrorController::AuthStatusProvider::~AuthStatusProvider() {
+}
+
+SigninErrorController::SigninErrorController()
+    : auth_error_(GoogleServiceAuthError::AuthErrorNone()) {
+}
+
+SigninErrorController::~SigninErrorController() {
+  DCHECK(provider_set_.empty())
+      << "All AuthStatusProviders should be unregistered before"
+      << " SigninErrorController::Shutdown() is called";
+}
+
+void SigninErrorController::AddProvider(const AuthStatusProvider* provider) {
+  DCHECK(provider_set_.find(provider) == provider_set_.end())
+      << "Adding same AuthStatusProvider multiple times";
+  provider_set_.insert(provider);
+  AuthStatusChanged();
+}
+
+void SigninErrorController::RemoveProvider(const AuthStatusProvider* provider) {
+  AuthStatusProviderSet::iterator iter = provider_set_.find(provider);
+  DCHECK(iter != provider_set_.end())
+      << "Removing provider that was never added";
+  provider_set_.erase(iter);
+  AuthStatusChanged();
+}
+
+void SigninErrorController::AuthStatusChanged() {
+  GoogleServiceAuthError::State prev_state = auth_error_.state();
+  std::string prev_account_id = error_account_id_;
+  bool error_changed = false;
+
+  // Find an error among the status providers. If |auth_error_| has an
+  // actionable error state and some provider exposes a similar error and
+  // account id, use that error. Otherwise, just take the first actionable
+  // error we find.
+  for (AuthStatusProviderSet::const_iterator it = provider_set_.begin();
+       it != provider_set_.end(); ++it) {
+    GoogleServiceAuthError error = (*it)->GetAuthStatus();
+
+    // Ignore the states we don't want to elevate to the user.
+    if (error.state() == GoogleServiceAuthError::NONE ||
+        error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
+      continue;
+    }
+
+    std::string account_id = (*it)->GetAccountId();
+
+    // Prioritize this error if it matches the previous |auth_error_|.
+    if (error.state() == prev_state && account_id == prev_account_id) {
+      auth_error_ = error;
+      error_account_id_ = account_id;
+      error_changed = true;
+      break;
+    }
+
+    // Use this error if we haven't found one already, but keep looking for the
+    // previous |auth_error_| in case there's a match elsewhere in the set.
+    if (!error_changed) {
+      auth_error_ = error;
+      error_account_id_ = account_id;
+      error_changed = true;
+    }
+  }
+
+  if (!error_changed && prev_state != GoogleServiceAuthError::NONE) {
+    // No provider reported an error, so clear the error we have now.
+    auth_error_ = GoogleServiceAuthError::AuthErrorNone();
+    error_account_id_.clear();
+    error_changed = true;
+  }
+
+  if (error_changed) {
+    FOR_EACH_OBSERVER(Observer, observer_list_, OnErrorChanged());
+  }
+}
+
+bool SigninErrorController::HasError() const {
+  return auth_error_.state() != GoogleServiceAuthError::NONE &&
+      auth_error_.state() != GoogleServiceAuthError::CONNECTION_FAILED;
+}
+
+void SigninErrorController::AddObserver(Observer* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void SigninErrorController::RemoveObserver(Observer* observer) {
+  observer_list_.RemoveObserver(observer);
+}
diff --git a/components/signin/core/browser/signin_error_controller.h b/components/signin/core/browser/signin_error_controller.h
new file mode 100644
index 0000000..17515fc
--- /dev/null
+++ b/components/signin/core/browser/signin_error_controller.h
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_ERROR_CONTROLLER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_ERROR_CONTROLLER_H_
+
+#include <set>
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/observer_list.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+// Keep track of auth errors and expose them to observers in the UI. Services
+// that wish to expose auth errors to the user should register an
+// AuthStatusProvider to report their current authentication state, and should
+// invoke AuthStatusChanged() when their authentication state may have changed.
+class SigninErrorController {
+ public:
+  class AuthStatusProvider {
+   public:
+    AuthStatusProvider();
+    virtual ~AuthStatusProvider();
+
+    // Returns the account id with the status specified by GetAuthStatus().
+    virtual std::string GetAccountId() const = 0;
+
+    // API invoked by SigninErrorController to get the current auth status of
+    // the various signed in services.
+    virtual GoogleServiceAuthError GetAuthStatus() const = 0;
+  };
+
+  // The observer class for SigninErrorController lets the controller notify
+  // observers when an error arises or changes.
+  class Observer {
+   public:
+    virtual ~Observer() {}
+    virtual void OnErrorChanged() = 0;
+  };
+
+  SigninErrorController();
+  ~SigninErrorController();
+
+  // Adds a provider which the SigninErrorController object will start querying
+  // for auth status.
+  void AddProvider(const AuthStatusProvider* provider);
+
+  // Removes a provider previously added by SigninErrorController (generally
+  // only called in preparation for shutdown).
+  void RemoveProvider(const AuthStatusProvider* provider);
+
+  // Invoked when the auth status of an AuthStatusProvider has changed.
+  void AuthStatusChanged();
+
+  // True if there exists an error worth elevating to the user.
+  bool HasError() const;
+
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  const std::string& error_account_id() const { return error_account_id_; }
+  const GoogleServiceAuthError& auth_error() const { return auth_error_; }
+
+ private:
+  std::set<const AuthStatusProvider*> provider_set_;
+
+  // The account that generated the last auth error.
+  std::string error_account_id_;
+
+  // The auth error detected the last time AuthStatusChanged() was invoked (or
+  // NONE if AuthStatusChanged() has never been invoked).
+  GoogleServiceAuthError auth_error_;
+
+  ObserverList<Observer, false> observer_list_;
+
+  DISALLOW_COPY_AND_ASSIGN(SigninErrorController);
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_ERROR_CONTROLLER_H_
diff --git a/components/signin/core/browser/signin_error_controller_unittest.cc b/components/signin/core/browser/signin_error_controller_unittest.cc
new file mode 100644
index 0000000..d143edd
--- /dev/null
+++ b/components/signin/core/browser/signin_error_controller_unittest.cc
@@ -0,0 +1,254 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/signin_error_controller.h"
+
+#include <functional>
+
+#include "base/memory/scoped_ptr.h"
+#include "components/signin/core/browser/fake_auth_status_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+static const char kTestAccountId[] = "testuser@test.com";
+static const char kOtherTestAccountId[] = "otheruser@test.com";
+
+class SigninErrorControllerTest : public testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    error_controller_.reset(new SigninErrorController());
+  }
+
+  scoped_ptr<SigninErrorController> error_controller_;
+};
+
+TEST_F(SigninErrorControllerTest, NoErrorAuthStatusProviders) {
+  scoped_ptr<FakeAuthStatusProvider> provider;
+
+  // No providers.
+  ASSERT_FALSE(error_controller_->HasError());
+
+  // Add a provider.
+  provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
+  ASSERT_FALSE(error_controller_->HasError());
+
+  // Remove the provider.
+  provider.reset();
+  ASSERT_FALSE(error_controller_->HasError());
+}
+
+TEST_F(SigninErrorControllerTest, ErrorAuthStatusProvider) {
+  scoped_ptr<FakeAuthStatusProvider> provider;
+  scoped_ptr<FakeAuthStatusProvider> error_provider;
+
+  provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
+  ASSERT_FALSE(error_controller_->HasError());
+
+  error_provider.reset(new FakeAuthStatusProvider(error_controller_.get()));
+  error_provider->SetAuthError(kTestAccountId, GoogleServiceAuthError(
+      GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+  ASSERT_TRUE(error_controller_->HasError());
+
+  error_provider.reset();
+  ASSERT_FALSE(error_controller_->HasError());
+
+  provider.reset();
+  // All providers should be removed now.
+  ASSERT_FALSE(error_controller_->HasError());
+}
+
+TEST_F(SigninErrorControllerTest, AuthStatusProviderErrorTransition) {
+  scoped_ptr<FakeAuthStatusProvider> provider0(
+      new FakeAuthStatusProvider(error_controller_.get()));
+  scoped_ptr<FakeAuthStatusProvider> provider1(
+      new FakeAuthStatusProvider(error_controller_.get()));
+
+  ASSERT_FALSE(error_controller_->HasError());
+  provider0->SetAuthError(
+      kTestAccountId,
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+  ASSERT_TRUE(error_controller_->HasError());
+  provider1->SetAuthError(
+      kTestAccountId,
+      GoogleServiceAuthError(GoogleServiceAuthError::ACCOUNT_DISABLED));
+  ASSERT_TRUE(error_controller_->HasError());
+
+  // Now resolve the auth errors - the menu item should go away.
+  provider0->SetAuthError(kTestAccountId,
+                         GoogleServiceAuthError::AuthErrorNone());
+  ASSERT_TRUE(error_controller_->HasError());
+  provider1->SetAuthError(kTestAccountId,
+                         GoogleServiceAuthError::AuthErrorNone());
+  ASSERT_FALSE(error_controller_->HasError());
+
+  provider0.reset();
+  provider1.reset();
+  ASSERT_FALSE(error_controller_->HasError());
+}
+
+TEST_F(SigninErrorControllerTest, AuthStatusProviderAccountTransition) {
+  scoped_ptr<FakeAuthStatusProvider> provider0(
+      new FakeAuthStatusProvider(error_controller_.get()));
+  scoped_ptr<FakeAuthStatusProvider> provider1(
+      new FakeAuthStatusProvider(error_controller_.get()));
+
+  ASSERT_FALSE(error_controller_->HasError());
+
+  provider0->SetAuthError(
+      kTestAccountId,
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+  provider1->SetAuthError(
+      kOtherTestAccountId,
+      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
+  ASSERT_TRUE(error_controller_->HasError());
+  ASSERT_STREQ(kTestAccountId,
+               error_controller_->error_account_id().c_str());
+
+  // Swap providers reporting errors.
+  provider1->set_error_without_status_change(
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+  provider0->set_error_without_status_change(
+      GoogleServiceAuthError(GoogleServiceAuthError::NONE));
+  error_controller_->AuthStatusChanged();
+  ASSERT_TRUE(error_controller_->HasError());
+  ASSERT_STREQ(kOtherTestAccountId,
+               error_controller_->error_account_id().c_str());
+
+  // Now resolve the auth errors - the menu item should go away.
+  provider0->set_error_without_status_change(
+      GoogleServiceAuthError::AuthErrorNone());
+  provider1->set_error_without_status_change(
+      GoogleServiceAuthError::AuthErrorNone());
+  error_controller_->AuthStatusChanged();
+  ASSERT_FALSE(error_controller_->HasError());
+
+  provider0.reset();
+  provider1.reset();
+  ASSERT_FALSE(error_controller_->HasError());
+}
+
+// Verify that SigninErrorController handles errors properly.
+TEST_F(SigninErrorControllerTest, AuthStatusEnumerateAllErrors) {
+  typedef struct {
+    GoogleServiceAuthError::State error_state;
+    bool is_error;
+  } ErrorTableEntry;
+
+  ErrorTableEntry table[] = {
+    { GoogleServiceAuthError::NONE, false },
+    { GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS, true },
+    { GoogleServiceAuthError::USER_NOT_SIGNED_UP, true },
+    { GoogleServiceAuthError::CONNECTION_FAILED, false },
+    { GoogleServiceAuthError::CAPTCHA_REQUIRED, true },
+    { GoogleServiceAuthError::ACCOUNT_DELETED, true },
+    { GoogleServiceAuthError::ACCOUNT_DISABLED, true },
+    { GoogleServiceAuthError::SERVICE_UNAVAILABLE, true },
+    { GoogleServiceAuthError::TWO_FACTOR, true },
+    { GoogleServiceAuthError::REQUEST_CANCELED, true },
+    { GoogleServiceAuthError::HOSTED_NOT_ALLOWED, true },
+    { GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE, true },
+    { GoogleServiceAuthError::SERVICE_ERROR, true },
+  };
+  COMPILE_ASSERT(ARRAYSIZE_UNSAFE(table) == GoogleServiceAuthError::NUM_STATES,
+      kTable_size_does_not_match_number_of_auth_error_types);
+
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(table); ++i) {
+    FakeAuthStatusProvider provider(error_controller_.get());
+    provider.SetAuthError(kTestAccountId,
+                          GoogleServiceAuthError(table[i].error_state));
+
+    EXPECT_EQ(error_controller_->HasError(), table[i].is_error);
+
+    if (table[i].is_error) {
+      EXPECT_EQ(table[i].error_state,
+                error_controller_->auth_error().state());
+      EXPECT_STREQ(kTestAccountId,
+                   error_controller_->error_account_id().c_str());
+    } else {
+      EXPECT_EQ(GoogleServiceAuthError::NONE,
+                error_controller_->auth_error().state());
+      EXPECT_STREQ("",
+                   error_controller_->error_account_id().c_str());
+    }
+  }
+}
+
+// Verify that existing error is not replaced by new error.
+TEST_F(SigninErrorControllerTest, AuthStatusChange) {
+  scoped_ptr<FakeAuthStatusProvider> fake_provider0(
+      new FakeAuthStatusProvider(error_controller_.get()));
+  scoped_ptr<FakeAuthStatusProvider> fake_provider1(
+      new FakeAuthStatusProvider(error_controller_.get()));
+
+  // If there are multiple providers in the provider set...
+  //
+  // | provider0 |       provider1          | ...
+  // |   NONE    | INVALID_GAIA_CREDENTIALS | ...
+  //
+  // SigninErrorController picks the first error found when iterating through
+  // the set. But if another error crops up...
+  //
+  // |     provider0       |       provider1          | ...
+  // | SERVICE_UNAVAILABLE | INVALID_GAIA_CREDENTIALS | ...
+  //
+  // we want the controller to still use the original error.
+
+  // The provider pointers are stored in a set, which is sorted by std::less.
+  std::less<SigninErrorController::AuthStatusProvider*> compare;
+  FakeAuthStatusProvider* provider0 =
+      compare(fake_provider0.get(), fake_provider1.get()) ?
+          fake_provider0.get() : fake_provider1.get();
+  FakeAuthStatusProvider* provider1 =
+      provider0 == fake_provider0.get() ?
+          fake_provider1.get() : fake_provider0.get();
+
+  provider0->SetAuthError(
+      kTestAccountId,
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::NONE));
+  provider1->SetAuthError(
+      kOtherTestAccountId,
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+  ASSERT_EQ(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS,
+            error_controller_->auth_error().state());
+  ASSERT_STREQ(kOtherTestAccountId,
+               error_controller_->error_account_id().c_str());
+
+  // Change the 1st provider's error.
+  provider1->SetAuthError(
+      kOtherTestAccountId,
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::SERVICE_UNAVAILABLE));
+  ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE,
+            error_controller_->auth_error().state());
+  ASSERT_STREQ(kOtherTestAccountId,
+               error_controller_->error_account_id().c_str());
+
+  // Set the 0th provider's error -- nothing should change.
+  provider0->SetAuthError(
+      kTestAccountId,
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE));
+  ASSERT_EQ(GoogleServiceAuthError::SERVICE_UNAVAILABLE,
+            error_controller_->auth_error().state());
+  ASSERT_STREQ(kOtherTestAccountId,
+               error_controller_->error_account_id().c_str());
+
+  // Clear the 1st provider's error, so the 0th provider's error is used.
+  provider1->SetAuthError(
+      kOtherTestAccountId,
+      GoogleServiceAuthError(
+          GoogleServiceAuthError::NONE));
+  ASSERT_EQ(GoogleServiceAuthError::UNEXPECTED_SERVICE_RESPONSE,
+            error_controller_->auth_error().state());
+  ASSERT_STREQ(kTestAccountId,
+               error_controller_->error_account_id().c_str());
+
+  fake_provider0.reset();
+  fake_provider1.reset();
+  ASSERT_FALSE(error_controller_->HasError());
+}
diff --git a/components/signin/core/browser/signin_internals_util.cc b/components/signin/core/browser/signin_internals_util.cc
new file mode 100644
index 0000000..c16f92a
--- /dev/null
+++ b/components/signin/core/browser/signin_internals_util.cc
@@ -0,0 +1,74 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/signin_internals_util.h"
+
+#include <sstream>
+
+#include "base/logging.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "crypto/sha2.h"
+#include "google_apis/gaia/gaia_constants.h"
+
+namespace signin_internals_util {
+
+const char kSigninPrefPrefix[] = "google.services.signin.";
+const char kTokenPrefPrefix[] = "google.services.signin.tokens.";
+
+#define ENUM_CASE(x) case x: return (std::string(kSigninPrefPrefix) + #x)
+std::string SigninStatusFieldToString(UntimedSigninStatusField field) {
+  switch (field) {
+    ENUM_CASE(USERNAME);
+    case UNTIMED_FIELDS_END:
+      NOTREACHED();
+      return std::string();
+  }
+
+  NOTREACHED();
+  return std::string();
+}
+
+std::string SigninStatusFieldToString(TimedSigninStatusField field) {
+  switch (field) {
+    ENUM_CASE(SIGNIN_TYPE);
+    ENUM_CASE(CLIENT_LOGIN_STATUS);
+    ENUM_CASE(OAUTH_LOGIN_STATUS);
+    ENUM_CASE(GET_USER_INFO_STATUS);
+    ENUM_CASE(UBER_TOKEN_STATUS);
+    ENUM_CASE(MERGE_SESSION_STATUS);
+    case TIMED_FIELDS_END:
+      NOTREACHED();
+      return std::string();
+  }
+
+  NOTREACHED();
+  return std::string();
+}
+
+std::string TokenPrefPath(const std::string& token_name) {
+  return std::string(kTokenPrefPrefix) + token_name;
+}
+
+// Gets the first few hex characters of the SHA256 hash of the passed in string.
+// These are enough to perform equality checks across a single users tokens,
+// while preventing outsiders from reverse-engineering the actual token from
+// the displayed value.
+// Note that for readability (in about:signin-internals), an empty string
+// is not hashed, but simply returned as an empty string.
+std::string GetTruncatedHash(const std::string& str) {
+  if (str.empty())
+    return str;
+
+  // Since each character in the hash string generates two hex charaters
+  // we only need half as many charaters in |hash_val| as hex characters
+  // returned.
+  const int kTruncateSize = kTruncateTokenStringLength / 2;
+  char hash_val[kTruncateSize];
+  crypto::SHA256HashString(str, &hash_val[0], kTruncateSize);
+  return StringToLowerASCII(base::HexEncode(&hash_val[0], kTruncateSize));
+}
+
+} //  namespace signin_internals_util
diff --git a/components/signin/core/browser/signin_internals_util.h b/components/signin/core/browser/signin_internals_util.h
new file mode 100644
index 0000000..8395cdb
--- /dev/null
+++ b/components/signin/core/browser/signin_internals_util.h
@@ -0,0 +1,90 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_INTERNALS_UTIL_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_INTERNALS_UTIL_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+
+namespace signin_internals_util {
+
+// Preference prefixes for signin and token values.
+extern const char kSigninPrefPrefix[];
+extern const char kTokenPrefPrefix[];
+
+// The length of strings returned by GetTruncatedHash() below.
+const size_t kTruncateTokenStringLength = 6;
+
+// Helper enums to access fields from SigninStatus (declared below).
+enum {
+  SIGNIN_FIELDS_BEGIN = 0,
+  UNTIMED_FIELDS_BEGIN = SIGNIN_FIELDS_BEGIN
+};
+
+enum UntimedSigninStatusField {
+  USERNAME = UNTIMED_FIELDS_BEGIN,
+  UNTIMED_FIELDS_END
+};
+
+enum {
+  UNTIMED_FIELDS_COUNT = UNTIMED_FIELDS_END - UNTIMED_FIELDS_BEGIN,
+  TIMED_FIELDS_BEGIN = UNTIMED_FIELDS_END
+};
+
+enum TimedSigninStatusField {
+  SIGNIN_TYPE = TIMED_FIELDS_BEGIN,
+  CLIENT_LOGIN_STATUS,
+  OAUTH_LOGIN_STATUS,
+  GET_USER_INFO_STATUS,
+  UBER_TOKEN_STATUS,
+  MERGE_SESSION_STATUS,
+  TIMED_FIELDS_END
+};
+
+enum {
+  TIMED_FIELDS_COUNT = TIMED_FIELDS_END - TIMED_FIELDS_BEGIN,
+  SIGNIN_FIELDS_END = TIMED_FIELDS_END,
+  SIGNIN_FIELDS_COUNT = SIGNIN_FIELDS_END - SIGNIN_FIELDS_BEGIN
+};
+
+// Returns the root preference path for the service. The path should be
+// qualified with one of .value, .status or .time to get the respective
+// full preference path names.
+std::string TokenPrefPath(const std::string& service_name);
+
+// Returns the name of a SigninStatus field.
+std::string SigninStatusFieldToString(UntimedSigninStatusField field);
+std::string SigninStatusFieldToString(TimedSigninStatusField field);
+
+// An Observer class for authentication and token diagnostic information.
+class SigninDiagnosticsObserver {
+ public:
+  // Credentials and signin related changes.
+  virtual void NotifySigninValueChanged(const UntimedSigninStatusField& field,
+                                        const std::string& value) {}
+  virtual void NotifySigninValueChanged(const TimedSigninStatusField& field,
+                                        const std::string& value) {}
+  // OAuth tokens related changes.
+  virtual void NotifyTokenReceivedSuccess(const std::string& token_name,
+                                          const std::string& token,
+                                          bool update_time) {}
+  virtual void NotifyTokenReceivedFailure(const std::string& token_name,
+                                          const std::string& error) {}
+  virtual void NotifyClearStoredToken(const std::string& token_name) {}};
+
+// Gets the first 6 hex characters of the SHA256 hash of the passed in string.
+// These are enough to perform equality checks across a single users tokens,
+// while preventing outsiders from reverse-engineering the actual token from
+// the displayed value.
+// Note that for readability (in about:signin-internals), an empty string
+// is not hashed, but simply returned as an empty string.
+std::string GetTruncatedHash(const std::string& str);
+
+} // namespace signin_internals_util
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_INTERNALS_UTIL_H_
diff --git a/components/signin/core/browser/signin_manager_base.cc b/components/signin/core/browser/signin_manager_base.cc
new file mode 100644
index 0000000..9a03b4b
--- /dev/null
+++ b/components/signin/core/browser/signin_manager_base.cc
@@ -0,0 +1,138 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/signin_manager_base.h"
+
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/memory/ref_counted.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/signin/core/browser/signin_client.h"
+#include "components/signin/core/common/signin_pref_names.h"
+#include "components/signin/core/common/signin_switches.h"
+#include "google_apis/gaia/gaia_auth_util.h"
+#include "google_apis/gaia/gaia_constants.h"
+#include "google_apis/gaia/gaia_urls.h"
+
+using namespace signin_internals_util;
+
+SigninManagerBase::SigninManagerBase(SigninClient* client)
+    : client_(client), initialized_(false), weak_pointer_factory_(this) {}
+
+SigninManagerBase::~SigninManagerBase() {}
+
+void SigninManagerBase::Initialize(Profile* profile, PrefService* local_state) {
+  // Should never call Initialize() twice.
+  DCHECK(!IsInitialized());
+  initialized_ = true;
+
+  // If the user is clearing the token service from the command line, then
+  // clear their login info also (not valid to be logged in without any
+  // tokens).
+  CommandLine* cmd_line = CommandLine::ForCurrentProcess();
+  if (cmd_line->HasSwitch(switches::kClearTokenService))
+    client_->GetPrefs()->ClearPref(prefs::kGoogleServicesUsername);
+
+  std::string user =
+      client_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
+  if (!user.empty())
+    SetAuthenticatedUsername(user);
+}
+
+bool SigninManagerBase::IsInitialized() const { return initialized_; }
+
+bool SigninManagerBase::IsSigninAllowed() const {
+  return client_->GetPrefs()->GetBoolean(prefs::kSigninAllowed);
+}
+
+const std::string& SigninManagerBase::GetAuthenticatedUsername() const {
+  return authenticated_username_;
+}
+
+const std::string& SigninManagerBase::GetAuthenticatedAccountId() const {
+  return GetAuthenticatedUsername();
+}
+
+void SigninManagerBase::SetAuthenticatedUsername(const std::string& username) {
+  if (!authenticated_username_.empty()) {
+    DLOG_IF(ERROR, !gaia::AreEmailsSame(username, authenticated_username_))
+        << "Tried to change the authenticated username to something different: "
+        << "Current: " << authenticated_username_ << ", New: " << username;
+
+#if defined(OS_IOS)
+    // Prior to M26, chrome on iOS did not normalize the email before setting
+    // it in SigninManager.  If the emails are the same as given by
+    // gaia::AreEmailsSame() but not the same as given by std::string::op==(),
+    // make sure to set the authenticated name below.
+    if (!gaia::AreEmailsSame(username, authenticated_username_) ||
+        username == authenticated_username_) {
+      return;
+    }
+#else
+    return;
+#endif
+  }
+  std::string pref_username =
+      client_->GetPrefs()->GetString(prefs::kGoogleServicesUsername);
+  DCHECK(pref_username.empty() || gaia::AreEmailsSame(username, pref_username))
+      << "username: " << username << "; pref_username: " << pref_username;
+  authenticated_username_ = username;
+  client_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username);
+  NotifyDiagnosticsObservers(USERNAME, username);
+
+  // Go ahead and update the last signed in username here as well. Once a
+  // user is signed in the two preferences should match. Doing it here as
+  // opposed to on signin allows us to catch the upgrade scenario.
+  client_->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername, username);
+}
+
+void SigninManagerBase::clear_authenticated_username() {
+  authenticated_username_.clear();
+}
+
+bool SigninManagerBase::AuthInProgress() const {
+  // SigninManagerBase never kicks off auth processes itself.
+  return false;
+}
+
+void SigninManagerBase::Shutdown() {}
+
+void SigninManagerBase::AddObserver(Observer* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void SigninManagerBase::RemoveObserver(Observer* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
+void SigninManagerBase::AddSigninDiagnosticsObserver(
+    SigninDiagnosticsObserver* observer) {
+  signin_diagnostics_observers_.AddObserver(observer);
+}
+
+void SigninManagerBase::RemoveSigninDiagnosticsObserver(
+    SigninDiagnosticsObserver* observer) {
+  signin_diagnostics_observers_.RemoveObserver(observer);
+}
+
+void SigninManagerBase::NotifyDiagnosticsObservers(
+    const UntimedSigninStatusField& field,
+    const std::string& value) {
+  FOR_EACH_OBSERVER(SigninDiagnosticsObserver,
+                    signin_diagnostics_observers_,
+                    NotifySigninValueChanged(field, value));
+}
+
+void SigninManagerBase::NotifyDiagnosticsObservers(
+    const TimedSigninStatusField& field,
+    const std::string& value) {
+  FOR_EACH_OBSERVER(SigninDiagnosticsObserver,
+                    signin_diagnostics_observers_,
+                    NotifySigninValueChanged(field, value));
+}
diff --git a/components/signin/core/browser/signin_manager_base.h b/components/signin/core/browser/signin_manager_base.h
new file mode 100644
index 0000000..5b30da7
--- /dev/null
+++ b/components/signin/core/browser/signin_manager_base.h
@@ -0,0 +1,181 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The signin manager encapsulates some functionality tracking
+// which user is signed in.
+//
+// **NOTE** on semantics of SigninManager:
+//
+// Once a signin is successful, the username becomes "established" and will not
+// be cleared until a SignOut operation is performed (persists across
+// restarts). Until that happens, the signin manager can still be used to
+// refresh credentials, but changing the username is not permitted.
+//
+// On Chrome OS, because of the existence of other components that handle login
+// and signin at a higher level, all that is needed from a SigninManager is
+// caching / handling of the "authenticated username" field, and TokenService
+// initialization, so that components that depend on these two things
+// (i.e on desktop) can continue using it / don't need to change. For this
+// reason, SigninManagerBase is all that exists on Chrome OS. For desktop,
+// see signin/signin_manager.h.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/gtest_prod_util.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "base/prefs/pref_change_registrar.h"
+#include "base/prefs/pref_member.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/signin/core/browser/signin_internals_util.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+class PrefService;
+
+// TODO(blundell): Eliminate this forward declaration once SigninManager no
+// longer needs Profile. crbug.com/334209
+class Profile;
+class SigninClient;
+
+// Details for the Notification type GOOGLE_SIGNIN_SUCCESSFUL.
+// TODO(blundell): Eliminate this struct once crbug.com/333997 is fixed.
+// A listener might use this to make note of a username / password
+// pair for encryption keys.
+struct GoogleServiceSigninSuccessDetails {
+  GoogleServiceSigninSuccessDetails(const std::string& in_username,
+                                    const std::string& in_password)
+      : username(in_username), password(in_password) {}
+  std::string username;
+  std::string password;
+};
+
+// Details for the Notification type NOTIFICATION_GOOGLE_SIGNED_OUT.
+// TODO(blundell): Eliminate this struct once crbug.com/333997 is fixed.
+struct GoogleServiceSignoutDetails {
+  explicit GoogleServiceSignoutDetails(const std::string& in_username)
+      : username(in_username) {}
+  std::string username;
+};
+
+class SigninManagerBase : public KeyedService {
+ public:
+  class Observer {
+   public:
+    // Called when a user fails to sign into Google services such as sync.
+    virtual void GoogleSigninFailed(const GoogleServiceAuthError& error) {}
+
+    // Called when a user signs into Google services such as sync.
+    virtual void GoogleSigninSucceeded(const std::string& username,
+                                       const std::string& password) {}
+
+    // Called when the currently signed-in user for a user has been signed out.
+    virtual void GoogleSignedOut(const std::string& username) {}
+
+   protected:
+    virtual ~Observer() {}
+  };
+
+  SigninManagerBase(SigninClient* client);
+  virtual ~SigninManagerBase();
+
+  // If user was signed in, load tokens from DB if available.
+  // TODO(blundell): Eliminate the |profile| argument once SigninManager no
+  // longer needs Profile. crbug.com/334209
+  virtual void Initialize(Profile* profile, PrefService* local_state);
+  bool IsInitialized() const;
+
+  // Returns true if a signin to Chrome is allowed (by policy or pref).
+  // TODO(tim): kSigninAllowed is defined for all platforms in pref_names.h.
+  // If kSigninAllowed pref was non-Chrome OS-only, this method wouldn't be
+  // needed, but as is we provide this method to let all interested code
+  // code query the value in one way, versus half using PrefService directly
+  // and the other half using SigninManager.
+  virtual bool IsSigninAllowed() const;
+
+  // If a user has previously signed in (and has not signed out), this returns
+  // the normalized email address of the account. Otherwise, it returns an empty
+  // string.
+  const std::string& GetAuthenticatedUsername() const;
+
+  // If a user has previously signed in (and has not signed out), this returns
+  // the account id. Otherwise, it returns an empty string.  This id can be used
+  // to uniquely identify an account, so for example can be used as a key to
+  // map accounts to data.
+  //
+  // TODO(rogerta): eventually the account id should be an obfuscated gaia id.
+  // For now though, this function returns the same value as
+  // GetAuthenticatedUsername() since lots of code assumes the unique id for an
+  // account is the username.  For code that needs a unique id to represent the
+  // connected account, call this method. Example: the AccountInfoMap type
+  // in MutableProfileOAuth2TokenService.  For code that needs to know the
+  // normalized email address of the connected account, use
+  // GetAuthenticatedUsername().  Example: to show the string "Signed in as XXX"
+  // in the hotdog menu.
+  const std::string& GetAuthenticatedAccountId() const;
+
+  // Sets the user name.  Note: |username| should be already authenticated as
+  // this is a sticky operation (in contrast to StartSignIn).
+  // TODO(tim): Remove this in favor of passing username on construction by
+  // (by platform / depending on StartBehavior). Bug 88109.
+  void SetAuthenticatedUsername(const std::string& username);
+
+  // Returns true if there's a signin in progress.
+  virtual bool AuthInProgress() const;
+
+  // KeyedService implementation.
+  virtual void Shutdown() OVERRIDE;
+
+  // Methods to register or remove observers of signin.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
+  // Methods to register or remove SigninDiagnosticObservers.
+  void AddSigninDiagnosticsObserver(
+      signin_internals_util::SigninDiagnosticsObserver* observer);
+  void RemoveSigninDiagnosticsObserver(
+      signin_internals_util::SigninDiagnosticsObserver* observer);
+
+ protected:
+  // Used by subclass to clear authenticated_username_ instead of using
+  // SetAuthenticatedUsername, which enforces special preconditions due
+  // to the fact that it is part of the public API and called by clients.
+  void clear_authenticated_username();
+
+  // List of observers to notify on signin events.
+  // Makes sure list is empty on destruction.
+  ObserverList<Observer, true> observer_list_;
+
+  // Helper methods to notify all registered diagnostics observers with.
+  void NotifyDiagnosticsObservers(
+      const signin_internals_util::UntimedSigninStatusField& field,
+      const std::string& value);
+  void NotifyDiagnosticsObservers(
+      const signin_internals_util::TimedSigninStatusField& field,
+      const std::string& value);
+
+ private:
+  friend class FakeSigninManagerBase;
+  friend class FakeSigninManager;
+
+  SigninClient* client_;
+  bool initialized_;
+
+  // Actual username after successful authentication.
+  std::string authenticated_username_;
+
+  // The list of SigninDiagnosticObservers.
+  ObserverList<signin_internals_util::SigninDiagnosticsObserver, true>
+      signin_diagnostics_observers_;
+
+  base::WeakPtrFactory<SigninManagerBase> weak_pointer_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(SigninManagerBase);
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_BASE_H_
diff --git a/components/signin/core/browser/signin_manager_cookie_helper.cc b/components/signin/core/browser/signin_manager_cookie_helper.cc
new file mode 100644
index 0000000..8a6c355
--- /dev/null
+++ b/components/signin/core/browser/signin_manager_cookie_helper.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/signin_manager_cookie_helper.h"
+
+#include <vector>
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "net/cookies/cookie_monster.h"
+#include "net/url_request/url_request_context.h"
+
+SigninManagerCookieHelper::SigninManagerCookieHelper(
+    net::URLRequestContextGetter* request_context_getter,
+    scoped_refptr<base::MessageLoopProxy> ui_thread,
+    scoped_refptr<base::MessageLoopProxy> io_thread)
+    : request_context_getter_(request_context_getter),
+      ui_thread_(ui_thread),
+      io_thread_(io_thread) {
+  DCHECK(ui_thread_->BelongsToCurrentThread());
+}
+
+SigninManagerCookieHelper::~SigninManagerCookieHelper() {
+}
+
+void SigninManagerCookieHelper::StartFetchingGaiaCookiesOnUIThread(
+    const base::Callback<void(const net::CookieList& cookies)>& callback) {
+  StartFetchingCookiesOnUIThread(
+      GaiaUrls::GetInstance()->gaia_url(), callback);
+}
+
+void SigninManagerCookieHelper::StartFetchingCookiesOnUIThread(
+    const GURL& url,
+    const base::Callback<void(const net::CookieList& cookies)>& callback) {
+  DCHECK(ui_thread_->BelongsToCurrentThread());
+  DCHECK(!callback.is_null());
+  DCHECK(completion_callback_.is_null());
+
+  completion_callback_ = callback;
+  io_thread_->PostTask(FROM_HERE,
+      base::Bind(&SigninManagerCookieHelper::FetchCookiesOnIOThread,
+                 this,
+                 url));
+}
+
+void SigninManagerCookieHelper::FetchCookiesOnIOThread(const GURL& url) {
+  DCHECK(io_thread_->BelongsToCurrentThread());
+
+  scoped_refptr<net::CookieMonster> cookie_monster =
+      request_context_getter_->GetURLRequestContext()->
+      cookie_store()->GetCookieMonster();
+  if (cookie_monster.get()) {
+    cookie_monster->GetAllCookiesForURLAsync(
+        url, base::Bind(&SigninManagerCookieHelper::OnCookiesFetched, this));
+  } else {
+    OnCookiesFetched(net::CookieList());
+  }
+}
+
+void SigninManagerCookieHelper::OnCookiesFetched(
+    const net::CookieList& cookies) {
+  DCHECK(io_thread_->BelongsToCurrentThread());
+  ui_thread_->PostTask(FROM_HERE,
+      base::Bind(&SigninManagerCookieHelper::NotifyOnUIThread, this, cookies));
+}
+
+void SigninManagerCookieHelper::NotifyOnUIThread(
+    const net::CookieList& cookies) {
+  DCHECK(ui_thread_->BelongsToCurrentThread());
+  base::ResetAndReturn(&completion_callback_).Run(cookies);
+}
diff --git a/components/signin/core/browser/signin_manager_cookie_helper.h b/components/signin/core/browser/signin_manager_cookie_helper.h
new file mode 100644
index 0000000..c401c6f
--- /dev/null
+++ b/components/signin/core/browser/signin_manager_cookie_helper.h
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_COOKIE_HELPER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_COOKIE_HELPER_H_
+
+#include "base/callback_helpers.h"
+#include "base/memory/ref_counted.h"
+#include "net/cookies/canonical_cookie.h"
+#include "net/url_request/url_request_context_getter.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace net {
+class URLRequestContextGetter;
+}
+
+// This class fetches GAIA cookie on IO thread on behalf of SigninManager which
+// only lives on the UI thread.
+class SigninManagerCookieHelper
+    : public base::RefCountedThreadSafe<SigninManagerCookieHelper> {
+ public:
+  explicit SigninManagerCookieHelper(
+      net::URLRequestContextGetter* request_context_getter,
+      scoped_refptr<base::MessageLoopProxy> ui_thread,
+      scoped_refptr<base::MessageLoopProxy> io_thread);
+
+  // Starts fetching gaia cookies, which will notify its completion via
+  // callback.
+  void StartFetchingGaiaCookiesOnUIThread(
+      const base::Callback<void(const net::CookieList& cookies)>& callback);
+
+  // Starts fetching cookies for the given URL. This must be called on
+  // |ui_thread_|.
+  void StartFetchingCookiesOnUIThread(
+      const GURL& url,
+      const base::Callback<void(const net::CookieList& cookies)>& callback);
+
+ private:
+  friend class base::RefCountedThreadSafe<SigninManagerCookieHelper>;
+  ~SigninManagerCookieHelper();
+
+  // Fetch cookies for the given URL. This must be called on |io_thread_|.
+  void FetchCookiesOnIOThread(const GURL& url);
+
+  // Callback for fetching cookies. This must be called on |io_thread_|.
+  void OnCookiesFetched(const net::CookieList& cookies);
+
+  // Notifies the completion callback. This must be called on |ui_thread_|.
+  void NotifyOnUIThread(const net::CookieList& cookies);
+
+  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+  // This only mutates on |ui_thread_|.
+  base::Callback<void(const net::CookieList& cookies)> completion_callback_;
+
+  // The MessageLoopProxy that this class uses as its UI thread.
+  scoped_refptr<base::MessageLoopProxy> ui_thread_;
+  // The MessageLoopProxy that this class uses as its IO thread.
+  scoped_refptr<base::MessageLoopProxy> io_thread_;
+  DISALLOW_COPY_AND_ASSIGN(SigninManagerCookieHelper);
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_SIGNIN_MANAGER_COOKIE_HELPER_H_
diff --git a/components/signin/core/browser/webdata/token_service_table.cc b/components/signin/core/browser/webdata/token_service_table.cc
new file mode 100644
index 0000000..d1ccb08
--- /dev/null
+++ b/components/signin/core/browser/webdata/token_service_table.cc
@@ -0,0 +1,115 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/webdata/token_service_table.h"
+
+#include <map>
+#include <string>
+
+#include "base/logging.h"
+#include "components/os_crypt/os_crypt.h"
+#include "components/webdata/common/web_database.h"
+#include "sql/statement.h"
+
+namespace {
+
+WebDatabaseTable::TypeKey GetKey() {
+  // We just need a unique constant. Use the address of a static that
+  // COMDAT folding won't touch in an optimizing linker.
+  static int table_key = 0;
+  return reinterpret_cast<void*>(&table_key);
+}
+
+}  // namespace
+
+TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) {
+  return static_cast<TokenServiceTable*>(db->GetTable(GetKey()));
+
+}
+
+WebDatabaseTable::TypeKey TokenServiceTable::GetTypeKey() const {
+  return GetKey();
+}
+
+bool TokenServiceTable::CreateTablesIfNecessary() {
+  if (!db_->DoesTableExist("token_service")) {
+    if (!db_->Execute("CREATE TABLE token_service ("
+                      "service VARCHAR PRIMARY KEY NOT NULL,"
+                      "encrypted_token BLOB)")) {
+      NOTREACHED();
+      return false;
+    }
+  }
+  return true;
+}
+
+bool TokenServiceTable::IsSyncable() {
+  return true;
+}
+
+bool TokenServiceTable::MigrateToVersion(int version,
+                                         bool* update_compatible_version) {
+  return true;
+}
+
+bool TokenServiceTable::RemoveAllTokens() {
+  sql::Statement s(db_->GetUniqueStatement(
+      "DELETE FROM token_service"));
+
+  return s.Run();
+}
+
+bool TokenServiceTable::RemoveTokenForService(const std::string& service) {
+  sql::Statement s(db_->GetUniqueStatement(
+      "DELETE FROM token_service WHERE service = ?"));
+  s.BindString(0, service);
+
+  return s.Run();
+}
+
+bool TokenServiceTable::SetTokenForService(const std::string& service,
+                                           const std::string& token) {
+  std::string encrypted_token;
+  bool encrypted = OSCrypt::EncryptString(token, &encrypted_token);
+  if (!encrypted) {
+    return false;
+  }
+
+  // Don't bother with a cached statement since this will be a relatively
+  // infrequent operation.
+  sql::Statement s(db_->GetUniqueStatement(
+      "INSERT OR REPLACE INTO token_service "
+      "(service, encrypted_token) VALUES (?, ?)"));
+  s.BindString(0, service);
+  s.BindBlob(1, encrypted_token.data(),
+             static_cast<int>(encrypted_token.length()));
+
+  return s.Run();
+}
+
+bool TokenServiceTable::GetAllTokens(
+    std::map<std::string, std::string>* tokens) {
+  sql::Statement s(db_->GetUniqueStatement(
+      "SELECT service, encrypted_token FROM token_service"));
+
+  if (!s.is_valid())
+    return false;
+
+  while (s.Step()) {
+    std::string encrypted_token;
+    std::string decrypted_token;
+    std::string service;
+    service = s.ColumnString(0);
+    bool entry_ok = !service.empty() &&
+                    s.ColumnBlobAsString(1, &encrypted_token);
+    if (entry_ok) {
+      OSCrypt::DecryptString(encrypted_token, &decrypted_token);
+      (*tokens)[service] = decrypted_token;
+    } else {
+      NOTREACHED();
+      return false;
+    }
+  }
+  return true;
+}
diff --git a/components/signin/core/browser/webdata/token_service_table.h b/components/signin/core/browser/webdata/token_service_table.h
new file mode 100644
index 0000000..9590653
--- /dev/null
+++ b/components/signin/core/browser/webdata/token_service_table.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_SERVICE_TABLE_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_SERVICE_TABLE_H_
+
+#include <map>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "components/webdata/common/web_database_table.h"
+
+class WebDatabase;
+
+class TokenServiceTable : public WebDatabaseTable {
+ public:
+  TokenServiceTable() {}
+  virtual ~TokenServiceTable() {}
+
+  // Retrieves the TokenServiceTable* owned by |database|.
+  static TokenServiceTable* FromWebDatabase(WebDatabase* db);
+
+  virtual WebDatabaseTable::TypeKey GetTypeKey() const OVERRIDE;
+  virtual bool CreateTablesIfNecessary() OVERRIDE;
+  virtual bool IsSyncable() OVERRIDE;
+  virtual bool MigrateToVersion(int version,
+                                bool* update_compatible_version) OVERRIDE;
+
+  // Remove all tokens previously set with SetTokenForService.
+  bool RemoveAllTokens();
+
+  // Removes a token related to the service from the token_service table.
+  bool RemoveTokenForService(const std::string& service);
+
+  // Retrieves all tokens previously set with SetTokenForService.
+  // Returns true if there were tokens and we decrypted them,
+  // false if there was a failure somehow
+  bool GetAllTokens(std::map<std::string, std::string>* tokens);
+
+  // Store a token in the token_service table. Stored encrypted. May cause
+  // a mac keychain popup.
+  // True if we encrypted a token and stored it, false otherwise.
+  bool SetTokenForService(const std::string& service,
+                          const std::string& token);
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TokenServiceTable);
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_SERVICE_TABLE_H_
diff --git a/components/signin/core/browser/webdata/token_service_table_unittest.cc b/components/signin/core/browser/webdata/token_service_table_unittest.cc
new file mode 100644
index 0000000..8478aac
--- /dev/null
+++ b/components/signin/core/browser/webdata/token_service_table_unittest.cc
@@ -0,0 +1,117 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/files/scoped_temp_dir.h"
+#include "base/path_service.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/time/time.h"
+#include "components/signin/core/browser/webdata/token_service_table.h"
+#include "components/webdata/common/web_database.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::Time;
+
+class TokenServiceTableTest : public testing::Test {
+ public:
+  TokenServiceTableTest() {}
+  virtual ~TokenServiceTableTest() {}
+
+ protected:
+  virtual void SetUp() {
+    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+    file_ = temp_dir_.path().AppendASCII("TestWebDatabase");
+
+    table_.reset(new TokenServiceTable);
+    db_.reset(new WebDatabase);
+    db_->AddTable(table_.get());
+    ASSERT_EQ(sql::INIT_OK, db_->Init(file_));
+  }
+
+  base::FilePath file_;
+  base::ScopedTempDir temp_dir_;
+  scoped_ptr<TokenServiceTable> table_;
+  scoped_ptr<WebDatabase> db_;
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TokenServiceTableTest);
+};
+
+// Flaky on mac_rel. See http://crbug.com/228943
+#if defined(OS_MACOSX)
+#define MAYBE_TokenServiceGetAllRemoveAll DISABLED_TokenServiceGetAllRemoveAll
+#define MAYBE_TokenServiceGetSet DISABLED_TokenServiceGetSet
+#define MAYBE_TokenServiceRemove DISABLED_TokenServiceRemove
+#else
+#define MAYBE_TokenServiceGetAllRemoveAll TokenServiceGetAllRemoveAll
+#define MAYBE_TokenServiceGetSet TokenServiceGetSet
+#define MAYBE_TokenServiceRemove TokenServiceRemove
+#endif
+
+TEST_F(TokenServiceTableTest, MAYBE_TokenServiceGetAllRemoveAll) {
+  std::map<std::string, std::string> out_map;
+  std::string service;
+  std::string service2;
+  service = "testservice";
+  service2 = "othertestservice";
+
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_TRUE(out_map.empty());
+
+  // Check that get all tokens works
+  EXPECT_TRUE(table_->SetTokenForService(service, "pepperoni"));
+  EXPECT_TRUE(table_->SetTokenForService(service2, "steak"));
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_EQ("pepperoni", out_map.find(service)->second);
+  EXPECT_EQ("steak", out_map.find(service2)->second);
+  out_map.clear();
+
+  // Purge
+  EXPECT_TRUE(table_->RemoveAllTokens());
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_TRUE(out_map.empty());
+
+  // Check that you can still add it back in
+  EXPECT_TRUE(table_->SetTokenForService(service, "cheese"));
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_EQ("cheese", out_map.find(service)->second);
+}
+
+TEST_F(TokenServiceTableTest, MAYBE_TokenServiceGetSet) {
+  std::map<std::string, std::string> out_map;
+  std::string service;
+  service = "testservice";
+
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_TRUE(out_map.empty());
+
+  EXPECT_TRUE(table_->SetTokenForService(service, "pepperoni"));
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_EQ("pepperoni", out_map.find(service)->second);
+  out_map.clear();
+
+  // try blanking it - won't remove it from the db though!
+  EXPECT_TRUE(table_->SetTokenForService(service, std::string()));
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_EQ("", out_map.find(service)->second);
+  out_map.clear();
+
+  // try mutating it
+  EXPECT_TRUE(table_->SetTokenForService(service, "ham"));
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_EQ("ham", out_map.find(service)->second);
+}
+
+TEST_F(TokenServiceTableTest, MAYBE_TokenServiceRemove) {
+  std::map<std::string, std::string> out_map;
+  std::string service;
+  std::string service2;
+  service = "testservice";
+  service2 = "othertestservice";
+
+  EXPECT_TRUE(table_->SetTokenForService(service, "pepperoni"));
+  EXPECT_TRUE(table_->SetTokenForService(service2, "steak"));
+  EXPECT_TRUE(table_->RemoveTokenForService(service));
+  EXPECT_TRUE(table_->GetAllTokens(&out_map));
+  EXPECT_EQ(0u, out_map.count(service));
+  EXPECT_EQ("steak", out_map.find(service2)->second);
+}
diff --git a/components/signin/core/browser/webdata/token_web_data.cc b/components/signin/core/browser/webdata/token_web_data.cc
new file mode 100644
index 0000000..fc4b82d
--- /dev/null
+++ b/components/signin/core/browser/webdata/token_web_data.cc
@@ -0,0 +1,106 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/browser/webdata/token_web_data.h"
+
+#include "base/bind.h"
+#include "base/memory/ref_counted_delete_on_message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/stl_util.h"
+#include "components/signin/core/browser/webdata/token_service_table.h"
+#include "components/webdata/common/web_database_service.h"
+
+using base::Bind;
+using base::Time;
+
+class TokenWebDataBackend
+    : public base::RefCountedDeleteOnMessageLoop<TokenWebDataBackend> {
+
+ public:
+  TokenWebDataBackend(scoped_refptr<base::MessageLoopProxy> db_thread)
+      : base::RefCountedDeleteOnMessageLoop<TokenWebDataBackend>(db_thread) {
+  }
+
+  WebDatabase::State RemoveAllTokens(WebDatabase* db) {
+    if (TokenServiceTable::FromWebDatabase(db)->RemoveAllTokens()) {
+      return WebDatabase::COMMIT_NEEDED;
+    }
+    return WebDatabase::COMMIT_NOT_NEEDED;
+  }
+
+  WebDatabase::State RemoveTokenForService(
+      const std::string& service, WebDatabase* db) {
+    if (TokenServiceTable::FromWebDatabase(db)
+            ->RemoveTokenForService(service)) {
+      return WebDatabase::COMMIT_NEEDED;
+    }
+    return WebDatabase::COMMIT_NOT_NEEDED;
+  }
+
+  WebDatabase::State SetTokenForService(
+      const std::string& service, const std::string& token, WebDatabase* db) {
+    if (TokenServiceTable::FromWebDatabase(db)->SetTokenForService(service,
+                                                                   token)) {
+      return WebDatabase::COMMIT_NEEDED;
+    }
+    return WebDatabase::COMMIT_NOT_NEEDED;
+  }
+
+  scoped_ptr<WDTypedResult> GetAllTokens(WebDatabase* db) {
+    std::map<std::string, std::string> map;
+    TokenServiceTable::FromWebDatabase(db)->GetAllTokens(&map);
+    return scoped_ptr<WDTypedResult>(
+        new WDResult<std::map<std::string, std::string> >(TOKEN_RESULT, map));
+  }
+
+ protected:
+  virtual ~TokenWebDataBackend() {
+  }
+
+ private:
+  friend class base::RefCountedDeleteOnMessageLoop<TokenWebDataBackend>;
+  friend class base::DeleteHelper<TokenWebDataBackend>;
+};
+
+TokenWebData::TokenWebData(scoped_refptr<WebDatabaseService> wdbs,
+                           scoped_refptr<base::MessageLoopProxy> ui_thread,
+                           scoped_refptr<base::MessageLoopProxy> db_thread,
+                           const ProfileErrorCallback& callback)
+    : WebDataServiceBase(wdbs, callback, ui_thread),
+      token_backend_(new TokenWebDataBackend(db_thread)) {
+}
+
+void TokenWebData::SetTokenForService(const std::string& service,
+                                      const std::string& token) {
+  wdbs_->ScheduleDBTask(FROM_HERE,
+      Bind(&TokenWebDataBackend::SetTokenForService, token_backend_,
+           service, token));
+}
+
+void TokenWebData::RemoveAllTokens() {
+  wdbs_->ScheduleDBTask(FROM_HERE,
+      Bind(&TokenWebDataBackend::RemoveAllTokens, token_backend_));
+}
+
+void TokenWebData::RemoveTokenForService(const std::string& service) {
+  wdbs_->ScheduleDBTask(FROM_HERE,
+      Bind(&TokenWebDataBackend::RemoveTokenForService, token_backend_,
+           service));
+}
+
+// Null on failure. Success is WDResult<std::string>
+WebDataServiceBase::Handle TokenWebData::GetAllTokens(
+    WebDataServiceConsumer* consumer) {
+  return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
+      Bind(&TokenWebDataBackend::GetAllTokens, token_backend_), consumer);
+}
+
+TokenWebData::TokenWebData(scoped_refptr<base::MessageLoopProxy> ui_thread,
+                           scoped_refptr<base::MessageLoopProxy> db_thread)
+    : WebDataServiceBase(NULL, ProfileErrorCallback(), ui_thread),
+      token_backend_(new TokenWebDataBackend(db_thread)) {
+}
+
+TokenWebData::~TokenWebData() {
+}
diff --git a/components/signin/core/browser/webdata/token_web_data.h b/components/signin/core/browser/webdata/token_web_data.h
new file mode 100644
index 0000000..e63bde6
--- /dev/null
+++ b/components/signin/core/browser/webdata/token_web_data.h
@@ -0,0 +1,70 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Chromium settings and storage represent user-selected preferences and
+// information and MUST not be extracted, overwritten or modified except
+// through Chromium defined APIs.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_WEB_DATA_H__
+#define COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_WEB_DATA_H__
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/files/file_path.h"
+#include "base/location.h"
+#include "base/memory/ref_counted.h"
+#include "components/webdata/common/web_data_results.h"
+#include "components/webdata/common/web_data_service_base.h"
+#include "components/webdata/common/web_data_service_consumer.h"
+#include "components/webdata/common/web_database.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+class TokenWebDataBackend;
+class WebDatabaseService;
+class WebDataServiceConsumer;
+
+// TokenWebData is a data repository for storage of authentication tokens.
+
+class TokenWebData : public WebDataServiceBase {
+ public:
+  TokenWebData(scoped_refptr<WebDatabaseService> wdbs,
+               scoped_refptr<base::MessageLoopProxy> ui_thread,
+               scoped_refptr<base::MessageLoopProxy> db_thread,
+               const ProfileErrorCallback& callback);
+
+  TokenWebData(scoped_refptr<base::MessageLoopProxy> ui_thread,
+               scoped_refptr<base::MessageLoopProxy> db_thread);
+
+  // Set a token to use for a specified service.
+  void SetTokenForService(const std::string& service,
+                          const std::string& token);
+
+  // Remove all tokens stored in the web database.
+  void RemoveAllTokens();
+
+  // Removes a token related to |service| from the web database.
+  void RemoveTokenForService(const std::string& service);
+
+  // Null on failure. Success is WDResult<std::vector<std::string> >
+  virtual Handle GetAllTokens(WebDataServiceConsumer* consumer);
+
+ protected:
+  // For unit tests, passes a null callback.
+  TokenWebData();
+
+  virtual ~TokenWebData();
+
+ private:
+  scoped_refptr<TokenWebDataBackend> token_backend_;
+
+  DISALLOW_COPY_AND_ASSIGN(TokenWebData);
+};
+
+#endif  // COMPONENTS_SIGNIN_CORE_BROWSER_WEBDATA_TOKEN_WEB_DATA_H__
diff --git a/components/signin/core/common/signin_pref_names.cc b/components/signin/core/common/signin_pref_names.cc
new file mode 100644
index 0000000..0388fdc
--- /dev/null
+++ b/components/signin/core/common/signin_pref_names.cc
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/common/signin_pref_names.h"
+
+namespace prefs {
+
+// String the identifies the last user that logged into sync and other
+// google services. As opposed to kGoogleServicesUsername, this value is not
+// cleared on signout, but while the user is signed in the two values will
+// be the same.
+const char kGoogleServicesLastUsername[] = "google.services.last_username";
+
+// Obfuscated account ID that identifies the current user logged into sync and
+// other google services.
+const char kGoogleServicesUserAccountId[] = "google.services.user_account_id";
+
+// String that identifies the current user logged into sync and other google
+// services.
+const char kGoogleServicesUsername[] = "google.services.username";
+
+// Local state pref containing a string regex that restricts which accounts
+// can be used to log in to chrome (e.g. "*@google.com"). If missing or blank,
+// all accounts are allowed (no restrictions).
+const char kGoogleServicesUsernamePattern[] =
+    "google.services.username_pattern";
+
+// Boolean which stores if the user is allowed to signin to chrome.
+const char kSigninAllowed[] = "signin.allowed";
+
+}  // namespace prefs
diff --git a/components/signin/core/common/signin_pref_names.h b/components/signin/core/common/signin_pref_names.h
new file mode 100644
index 0000000..0a04f28
--- /dev/null
+++ b/components/signin/core/common/signin_pref_names.h
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_PREF_NAMES_H_
+#define COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_PREF_NAMES_H_
+
+namespace prefs {
+
+extern const char kGoogleServicesLastUsername[];
+extern const char kGoogleServicesUserAccountId[];
+extern const char kGoogleServicesUsername[];
+extern const char kGoogleServicesUsernamePattern[];
+extern const char kSigninAllowed[];
+
+}  // namespace prefs
+
+#endif  // COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_PREF_NAMES_H_
diff --git a/components/signin/core/common/signin_switches.cc b/components/signin/core/common/signin_switches.cc
new file mode 100644
index 0000000..a6d5b03
--- /dev/null
+++ b/components/signin/core/common/signin_switches.cc
@@ -0,0 +1,13 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/signin/core/common/signin_switches.h"
+
+namespace switches {
+
+// Clears the token service before using it. This allows simulating the
+// expiration of credentials during testing.
+const char kClearTokenService[] = "clear-token-service";
+
+}  // namespace switches
diff --git a/components/signin/core/common/signin_switches.h b/components/signin/core/common/signin_switches.h
new file mode 100644
index 0000000..30bd8d3
--- /dev/null
+++ b/components/signin/core/common/signin_switches.h
@@ -0,0 +1,16 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_SWITCHES_H_
+#define COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_SWITCHES_H_
+
+namespace switches {
+
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
+extern const char kClearTokenService[];
+
+}  // namespace switches
+
+#endif  // COMPONENTS_SIGNIN_CORE_COMMON_SIGNIN_SWITCHES_H_
diff --git a/components/signin/core/mutable_profile_oauth2_token_service.cc b/components/signin/core/mutable_profile_oauth2_token_service.cc
deleted file mode 100644
index 75e7c86..0000000
--- a/components/signin/core/mutable_profile_oauth2_token_service.cc
+++ /dev/null
@@ -1,384 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/mutable_profile_oauth2_token_service.h"
-
-#include "components/signin/core/signin_client.h"
-#include "components/signin/core/webdata/token_web_data.h"
-#include "components/webdata/common/web_data_service_base.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "google_apis/gaia/oauth2_access_token_fetcher_impl.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace {
-
-const char kAccountIdPrefix[] = "AccountId-";
-const size_t kAccountIdPrefixLength = 10;
-
-std::string ApplyAccountIdPrefix(const std::string& account_id) {
-  return kAccountIdPrefix + account_id;
-}
-
-bool IsLegacyRefreshTokenId(const std::string& service_id) {
-  return service_id == GaiaConstants::kGaiaOAuth2LoginRefreshToken;
-}
-
-bool IsLegacyServiceId(const std::string& account_id) {
-  return account_id.compare(0u, kAccountIdPrefixLength, kAccountIdPrefix) != 0;
-}
-
-std::string RemoveAccountIdPrefix(const std::string& prefixed_account_id) {
-  return prefixed_account_id.substr(kAccountIdPrefixLength);
-}
-
-}  // namespace
-
-// This class sends a request to GAIA to revoke the given refresh token from
-// the server.  This is a best effort attempt only.  This class deletes itself
-// when done sucessfully or otherwise.
-class MutableProfileOAuth2TokenService::RevokeServerRefreshToken
-    : public GaiaAuthConsumer {
- public:
-  RevokeServerRefreshToken(MutableProfileOAuth2TokenService* token_service,
-                           const std::string& account_id);
-  virtual ~RevokeServerRefreshToken();
-
- private:
-  // GaiaAuthConsumer overrides:
-  virtual void OnOAuth2RevokeTokenCompleted() OVERRIDE;
-
-  MutableProfileOAuth2TokenService* token_service_;
-  GaiaAuthFetcher fetcher_;
-
-  DISALLOW_COPY_AND_ASSIGN(RevokeServerRefreshToken);
-};
-
-MutableProfileOAuth2TokenService::
-    RevokeServerRefreshToken::RevokeServerRefreshToken(
-    MutableProfileOAuth2TokenService* token_service,
-    const std::string& refresh_token)
-    : token_service_(token_service),
-      fetcher_(this, GaiaConstants::kChromeSource,
-               token_service_->GetRequestContext()) {
-  fetcher_.StartRevokeOAuth2Token(refresh_token);
-}
-
-MutableProfileOAuth2TokenService::
-    RevokeServerRefreshToken::~RevokeServerRefreshToken() {}
-
-void MutableProfileOAuth2TokenService::
-    RevokeServerRefreshToken::OnOAuth2RevokeTokenCompleted() {
-  // |this| pointer will be deleted when removed from the vector, so don't
-  // access any members after call to erase().
-  token_service_->server_revokes_.erase(
-      std::find(token_service_->server_revokes_.begin(),
-                token_service_->server_revokes_.end(),
-                this));
-}
-
-MutableProfileOAuth2TokenService::AccountInfo::AccountInfo(
-    ProfileOAuth2TokenService* token_service,
-    const std::string& account_id,
-    const std::string& refresh_token)
-  : token_service_(token_service),
-    account_id_(account_id),
-    refresh_token_(refresh_token),
-    last_auth_error_(GoogleServiceAuthError::NONE) {
-  DCHECK(token_service_);
-  DCHECK(!account_id_.empty());
-  token_service_->signin_error_controller()->AddProvider(this);
-}
-
-MutableProfileOAuth2TokenService::AccountInfo::~AccountInfo() {
-  token_service_->signin_error_controller()->RemoveProvider(this);
-}
-
-void MutableProfileOAuth2TokenService::AccountInfo::SetLastAuthError(
-    const GoogleServiceAuthError& error) {
-  if (error.state() != last_auth_error_.state()) {
-    last_auth_error_ = error;
-    token_service_->signin_error_controller()->AuthStatusChanged();
-  }
-}
-
-std::string
-MutableProfileOAuth2TokenService::AccountInfo::GetAccountId() const {
-  return account_id_;
-}
-
-GoogleServiceAuthError
-MutableProfileOAuth2TokenService::AccountInfo::GetAuthStatus() const {
-  return last_auth_error_;
-}
-
-MutableProfileOAuth2TokenService::MutableProfileOAuth2TokenService()
-    : web_data_service_request_(0)  {
-}
-
-MutableProfileOAuth2TokenService::~MutableProfileOAuth2TokenService() {
-  DCHECK(server_revokes_.empty());
-}
-
-void MutableProfileOAuth2TokenService::Shutdown() {
-  server_revokes_.clear();
-  CancelWebTokenFetch();
-  CancelAllRequests();
-  refresh_tokens_.clear();
-
-  ProfileOAuth2TokenService::Shutdown();
-}
-
-bool MutableProfileOAuth2TokenService::RefreshTokenIsAvailable(
-    const std::string& account_id) const {
-  return !GetRefreshToken(account_id).empty();
-}
-
-std::string MutableProfileOAuth2TokenService::GetRefreshToken(
-    const std::string& account_id) const {
-  AccountInfoMap::const_iterator iter = refresh_tokens_.find(account_id);
-  if (iter != refresh_tokens_.end())
-    return iter->second->refresh_token();
-  return std::string();
-}
-
-OAuth2AccessTokenFetcher*
-MutableProfileOAuth2TokenService::CreateAccessTokenFetcher(
-    const std::string& account_id,
-    net::URLRequestContextGetter* getter,
-    OAuth2AccessTokenConsumer* consumer) {
-  std::string refresh_token = GetRefreshToken(account_id);
-  DCHECK(!refresh_token.empty());
-  return new OAuth2AccessTokenFetcherImpl(consumer, getter, refresh_token);
-}
-
-net::URLRequestContextGetter*
-MutableProfileOAuth2TokenService::GetRequestContext() {
-  return client()->GetURLRequestContext();
-}
-
-void MutableProfileOAuth2TokenService::LoadCredentials(
-    const std::string& primary_account_id) {
-  DCHECK(!primary_account_id.empty());
-  DCHECK(loading_primary_account_id_.empty());
-  DCHECK_EQ(0, web_data_service_request_);
-
-  CancelAllRequests();
-  refresh_tokens().clear();
-  loading_primary_account_id_ = primary_account_id;
-  scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
-  if (token_web_data.get())
-    web_data_service_request_ = token_web_data->GetAllTokens(this);
-}
-
-void MutableProfileOAuth2TokenService::OnWebDataServiceRequestDone(
-    WebDataServiceBase::Handle handle,
-    const WDTypedResult* result) {
-  DCHECK_EQ(web_data_service_request_, handle);
-  web_data_service_request_ = 0;
-
-  if (result) {
-    DCHECK(result->GetType() == TOKEN_RESULT);
-    const WDResult<std::map<std::string, std::string> > * token_result =
-        static_cast<const WDResult<std::map<std::string, std::string> > * > (
-            result);
-    LoadAllCredentialsIntoMemory(token_result->GetValue());
-  }
-
-  // Make sure that we have an entry for |loading_primary_account_id_| in the
-  // map.  The entry could be missing if there is a corruption in the token DB
-  // while this profile is connected to an account.
-  DCHECK(!loading_primary_account_id_.empty());
-  if (refresh_tokens().count(loading_primary_account_id_) == 0) {
-    refresh_tokens()[loading_primary_account_id_].reset(
-        new AccountInfo(this, loading_primary_account_id_, std::string()));
-  }
-
-  // If we don't have a refresh token for a known account, signal an error.
-  for (AccountInfoMap::const_iterator i = refresh_tokens_.begin();
-       i != refresh_tokens_.end(); ++i) {
-    if (!RefreshTokenIsAvailable(i->first)) {
-      UpdateAuthError(
-          i->first,
-          GoogleServiceAuthError(
-              GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
-      break;
-    }
-  }
-
-  loading_primary_account_id_.clear();
-}
-
-void MutableProfileOAuth2TokenService::LoadAllCredentialsIntoMemory(
-    const std::map<std::string, std::string>& db_tokens) {
-  std::string old_login_token;
-
-  for (std::map<std::string, std::string>::const_iterator iter =
-           db_tokens.begin();
-       iter != db_tokens.end();
-       ++iter) {
-    std::string prefixed_account_id = iter->first;
-    std::string refresh_token = iter->second;
-
-    if (IsLegacyRefreshTokenId(prefixed_account_id) && !refresh_token.empty())
-      old_login_token = refresh_token;
-
-    if (IsLegacyServiceId(prefixed_account_id)) {
-      scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
-      if (token_web_data.get())
-        token_web_data->RemoveTokenForService(prefixed_account_id);
-    } else {
-      DCHECK(!refresh_token.empty());
-      std::string account_id = RemoveAccountIdPrefix(prefixed_account_id);
-      refresh_tokens()[account_id].reset(
-          new AccountInfo(this, account_id, refresh_token));
-      FireRefreshTokenAvailable(account_id);
-      // TODO(fgorski): Notify diagnostic observers.
-    }
-  }
-
-  if (!old_login_token.empty()) {
-    DCHECK(!loading_primary_account_id_.empty());
-    if (refresh_tokens().count(loading_primary_account_id_) == 0)
-      UpdateCredentials(loading_primary_account_id_, old_login_token);
-  }
-
-  FireRefreshTokensLoaded();
-}
-
-void MutableProfileOAuth2TokenService::UpdateAuthError(
-    const std::string& account_id,
-    const GoogleServiceAuthError& error) {
-  // Do not report connection errors as these are not actually auth errors.
-  // We also want to avoid masking a "real" auth error just because we
-  // subsequently get a transient network error.
-  if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED ||
-      error.state() == GoogleServiceAuthError::SERVICE_UNAVAILABLE)
-    return;
-
-#if defined(OS_IOS)
-  // ProfileOauth2TokenService does not manage the refresh tokens on iOS - the
-  // account info on iOS is only used to manage the authentication error state.
-  // Simply add an account info entry with empty refresh token if none exists.
-  if (refresh_tokens_.count(account_id) == 0) {
-      refresh_tokens_[account_id].reset(
-          new AccountInfo(this, account_id, std::string()));
-  }
-#endif
-
-  if (refresh_tokens_.count(account_id) == 0) {
-    // This could happen if the preferences have been corrupted (see
-    // http://crbug.com/321370). In a Debug build that would be a bug, but in a
-    // Release build we want to deal with it gracefully.
-    NOTREACHED();
-    return;
-  }
-  refresh_tokens_[account_id]->SetLastAuthError(error);
-}
-
-std::vector<std::string> MutableProfileOAuth2TokenService::GetAccounts() {
-  std::vector<std::string> account_ids;
-  for (AccountInfoMap::const_iterator iter = refresh_tokens_.begin();
-           iter != refresh_tokens_.end(); ++iter) {
-    account_ids.push_back(iter->first);
-  }
-  return account_ids;
-}
-
-void MutableProfileOAuth2TokenService::UpdateCredentials(
-    const std::string& account_id,
-    const std::string& refresh_token) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(!account_id.empty());
-  DCHECK(!refresh_token.empty());
-
-  bool refresh_token_present = refresh_tokens_.count(account_id) > 0;
-  if (!refresh_token_present ||
-      refresh_tokens_[account_id]->refresh_token() != refresh_token) {
-    // If token present, and different from the new one, cancel its requests,
-    // and clear the entries in cache related to that account.
-    if (refresh_token_present) {
-      std::string revoke_reason = refresh_token_present ? "token differs" :
-                                                          "token is missing";
-      LOG(WARNING) << "Revoking refresh token on server. "
-                   << "Reason: token update, " << revoke_reason;
-      RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
-      CancelRequestsForAccount(account_id);
-      ClearCacheForAccount(account_id);
-      refresh_tokens_[account_id]->set_refresh_token(refresh_token);
-    } else {
-      refresh_tokens_[account_id].reset(
-          new AccountInfo(this, account_id, refresh_token));
-    }
-
-    // Save the token in memory and in persistent store.
-    PersistCredentials(account_id, refresh_token);
-
-    UpdateAuthError(account_id, GoogleServiceAuthError::AuthErrorNone());
-    FireRefreshTokenAvailable(account_id);
-  }
-}
-
-void MutableProfileOAuth2TokenService::RevokeCredentials(
-    const std::string& account_id) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (refresh_tokens_.count(account_id) > 0) {
-    RevokeCredentialsOnServer(refresh_tokens_[account_id]->refresh_token());
-    CancelRequestsForAccount(account_id);
-    ClearCacheForAccount(account_id);
-    refresh_tokens_.erase(account_id);
-    ClearPersistedCredentials(account_id);
-    FireRefreshTokenRevoked(account_id);
-  }
-}
-
-void MutableProfileOAuth2TokenService::PersistCredentials(
-    const std::string& account_id,
-    const std::string& refresh_token) {
-  scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
-  if (token_web_data.get()) {
-    token_web_data->SetTokenForService(ApplyAccountIdPrefix(account_id),
-                                       refresh_token);
-  }
-}
-
-void MutableProfileOAuth2TokenService::ClearPersistedCredentials(
-    const std::string& account_id) {
-  scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
-  if (token_web_data.get())
-    token_web_data->RemoveTokenForService(ApplyAccountIdPrefix(account_id));
-}
-
-void MutableProfileOAuth2TokenService::RevokeAllCredentials() {
-  if (!client()->CanRevokeCredentials())
-    return;
-  DCHECK(thread_checker_.CalledOnValidThread());
-  CancelWebTokenFetch();
-  CancelAllRequests();
-  ClearCache();
-  AccountInfoMap tokens = refresh_tokens_;
-  for (AccountInfoMap::iterator i = tokens.begin(); i != tokens.end(); ++i)
-    RevokeCredentials(i->first);
-
-  DCHECK_EQ(0u, refresh_tokens_.size());
-}
-
-void MutableProfileOAuth2TokenService::RevokeCredentialsOnServer(
-    const std::string& refresh_token) {
-  // Keep track or all server revoke requests.  This way they can be deleted
-  // before the token service is shutdown and won't outlive the profile.
-  server_revokes_.push_back(
-      new RevokeServerRefreshToken(this, refresh_token));
-}
-
-void MutableProfileOAuth2TokenService::CancelWebTokenFetch() {
-  if (web_data_service_request_ != 0) {
-    scoped_refptr<TokenWebData> token_web_data = client()->GetDatabase();
-    DCHECK(token_web_data.get());
-    token_web_data->CancelRequest(web_data_service_request_);
-    web_data_service_request_  = 0;
-  }
-}
diff --git a/components/signin/core/mutable_profile_oauth2_token_service.h b/components/signin/core/mutable_profile_oauth2_token_service.h
deleted file mode 100644
index b9ebc6e..0000000
--- a/components/signin/core/mutable_profile_oauth2_token_service.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
-#define COMPONENTS_SIGNIN_CORE_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
-
-#include "base/memory/scoped_vector.h"
-#include "base/threading/thread_checker.h"
-#include "components/signin/core/profile_oauth2_token_service.h"
-#include "components/webdata/common/web_data_service_base.h"
-#include "components/webdata/common/web_data_service_consumer.h"
-
-// A specialization of ProfileOAuth2TokenService that can can mutate its OAuth2
-// tokens.
-//
-// Note: This class is just a placeholder for now. Methods used to mutate
-// the tokens are currently being migrated from ProfileOAuth2TokenService.
-class MutableProfileOAuth2TokenService : public ProfileOAuth2TokenService,
-                                         public WebDataServiceConsumer  {
- public:
-  // ProfileOAuth2TokenService overrides.
-  virtual void Shutdown() OVERRIDE;
-  virtual std::vector<std::string> GetAccounts() OVERRIDE;
-
-  // The below three methods should be called only on the thread on which this
-  // object was created.
-  virtual void LoadCredentials(const std::string& primary_account_id) OVERRIDE;
-  virtual void UpdateCredentials(const std::string& account_id,
-                                 const std::string& refresh_token) OVERRIDE;
-  virtual void RevokeAllCredentials() OVERRIDE;
-  virtual bool RefreshTokenIsAvailable(const std::string& account_id) const
-      OVERRIDE;
-
-  // Revokes credentials related to |account_id|.
-  void RevokeCredentials(const std::string& account_id);
-
- protected:
-  class AccountInfo : public SigninErrorController::AuthStatusProvider {
-   public:
-    AccountInfo(ProfileOAuth2TokenService* token_service,
-                const std::string& account_id,
-                const std::string& refresh_token);
-    virtual ~AccountInfo();
-
-    const std::string& refresh_token() const { return refresh_token_; }
-    void set_refresh_token(const std::string& token) {
-      refresh_token_ = token;
-    }
-
-    void SetLastAuthError(const GoogleServiceAuthError& error);
-
-    // SigninErrorController::AuthStatusProvider implementation.
-    virtual std::string GetAccountId() const OVERRIDE;
-    virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
-
-   private:
-    ProfileOAuth2TokenService* token_service_;
-    std::string account_id_;
-    std::string refresh_token_;
-    GoogleServiceAuthError last_auth_error_;
-
-    DISALLOW_COPY_AND_ASSIGN(AccountInfo);
-  };
-
-  // Maps the |account_id| of accounts known to ProfileOAuth2TokenService
-  // to information about the account.
-  typedef std::map<std::string, linked_ptr<AccountInfo> > AccountInfoMap;
-
-  friend class ProfileOAuth2TokenServiceWrapperImpl;
-
-  MutableProfileOAuth2TokenService();
-  virtual ~MutableProfileOAuth2TokenService();
-
-  // OAuth2TokenService implementation.
-  virtual OAuth2AccessTokenFetcher* CreateAccessTokenFetcher(
-      const std::string& account_id,
-      net::URLRequestContextGetter* getter,
-      OAuth2AccessTokenConsumer* consumer) OVERRIDE;
-  virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
-
-  // Updates the internal cache of the result from the most-recently-completed
-  // auth request (used for reporting errors to the user).
-  virtual void UpdateAuthError(const std::string& account_id,
-                               const GoogleServiceAuthError& error) OVERRIDE;
-
-  virtual std::string GetRefreshToken(const std::string& account_id) const;
-
-  AccountInfoMap& refresh_tokens() { return refresh_tokens_; }
-
- private:
-  class RevokeServerRefreshToken;
-
-  FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceTest,
-                           TokenServiceUpdateClearsCache);
-  FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceTest,
-                           PersistenceDBUpgrade);
-  FRIEND_TEST_ALL_PREFIXES(MutableProfileOAuth2TokenServiceTest,
-                           PersistenceLoadCredentials);
-
-  // WebDataServiceConsumer implementation:
-  virtual void OnWebDataServiceRequestDone(
-      WebDataServiceBase::Handle handle,
-      const WDTypedResult* result) OVERRIDE;
-
-  // Loads credentials into in memory stucture.
-  void LoadAllCredentialsIntoMemory(
-      const std::map<std::string, std::string>& db_tokens);
-
-  // Persists credentials for |account_id|. Enables overriding for
-  // testing purposes, or other cases, when accessing the DB is not desired.
-  void PersistCredentials(const std::string& account_id,
-                          const std::string& refresh_token);
-
-  // Clears credentials persisted for |account_id|. Enables overriding for
-  // testing purposes, or other cases, when accessing the DB is not desired.
-  void ClearPersistedCredentials(const std::string& account_id);
-
-  // Revokes the refresh token on the server.
-  void RevokeCredentialsOnServer(const std::string& refresh_token);
-
-  // Cancels any outstanding fetch for tokens from the web database.
-  void CancelWebTokenFetch();
-
-  // In memory refresh token store mapping account_id to refresh_token.
-  AccountInfoMap refresh_tokens_;
-
-  // Handle to the request reading tokens from database.
-  WebDataServiceBase::Handle web_data_service_request_;
-
-  // The primary account id of this service's profile during the loading of
-  // credentials.  This member is empty otherwise.
-  std::string loading_primary_account_id_;
-
-  ScopedVector<RevokeServerRefreshToken> server_revokes_;
-
-  // Used to verify that certain methods are called only on the thread on which
-  // this instance was created.
-  base::ThreadChecker thread_checker_;
-
-  DISALLOW_COPY_AND_ASSIGN(MutableProfileOAuth2TokenService);
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_MUTABLE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
diff --git a/components/signin/core/profile_oauth2_token_service.cc b/components/signin/core/profile_oauth2_token_service.cc
deleted file mode 100644
index 2127012..0000000
--- a/components/signin/core/profile_oauth2_token_service.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/profile_oauth2_token_service.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "base/time/time.h"
-#include "components/signin/core/signin_error_controller.h"
-#include "net/url_request/url_request_context_getter.h"
-
-ProfileOAuth2TokenService::ProfileOAuth2TokenService()
-    : client_(NULL) {}
-
-ProfileOAuth2TokenService::~ProfileOAuth2TokenService() {
-  DCHECK(!signin_error_controller_.get()) <<
-      "ProfileOAuth2TokenService::Initialize called but not "
-      "ProfileOAuth2TokenService::Shutdown";
-}
-
-void ProfileOAuth2TokenService::Initialize(SigninClient* client) {
-  DCHECK(client);
-  DCHECK(!client_);
-  client_ = client;
-
-  signin_error_controller_.reset(new SigninErrorController());
-}
-
-void ProfileOAuth2TokenService::Shutdown() {
-  DCHECK(client_) << "Shutdown() called without matching call to Initialize()";
-  signin_error_controller_.reset();
-}
-
-net::URLRequestContextGetter* ProfileOAuth2TokenService::GetRequestContext() {
-  return NULL;
-}
-
-void ProfileOAuth2TokenService::UpdateAuthError(
-    const std::string& account_id,
-    const GoogleServiceAuthError& error) {
-  NOTREACHED();
-}
-
-std::vector<std::string> ProfileOAuth2TokenService::GetAccounts() {
-  NOTREACHED();
-  return std::vector<std::string>();
-}
-
-void ProfileOAuth2TokenService::LoadCredentials(
-    const std::string& primary_account_id) {
-  // Empty implementation by default.
-}
-
-void ProfileOAuth2TokenService::UpdateCredentials(
-    const std::string& account_id,
-    const std::string& refresh_token) {
-  NOTREACHED();
-}
-
-void ProfileOAuth2TokenService::RevokeAllCredentials() {
-  // Empty implementation by default.
-}
-
diff --git a/components/signin/core/profile_oauth2_token_service.h b/components/signin/core/profile_oauth2_token_service.h
deleted file mode 100644
index b4ede3a..0000000
--- a/components/signin/core/profile_oauth2_token_service.h
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
-#define COMPONENTS_SIGNIN_CORE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
-
-#include <string>
-
-#include "base/gtest_prod_util.h"
-#include "base/memory/linked_ptr.h"
-#include "components/keyed_service/core/keyed_service.h"
-#include "components/signin/core/signin_error_controller.h"
-#include "google_apis/gaia/oauth2_token_service.h"
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-class GoogleServiceAuthError;
-class SigninClient;
-
-// ProfileOAuth2TokenService is a class that retrieves
-// OAuth2 access tokens for a given set of scopes using the OAuth2 login
-// refresh tokens.
-//
-// See |OAuth2TokenService| for usage details.
-//
-// Note: after StartRequest returns, in-flight requests will continue
-// even if the TokenService refresh token that was used to initiate
-// the request changes or is cleared.  When the request completes,
-// Consumer::OnGetTokenSuccess will be invoked, but the access token
-// won't be cached.
-//
-// Note: requests should be started from the UI thread. To start a
-// request from other thread, please use ProfileOAuth2TokenServiceRequest.
-class ProfileOAuth2TokenService : public OAuth2TokenService {
- public:
-  virtual ~ProfileOAuth2TokenService();
-
-  // Initializes this token service with the SigninClient.
-  virtual void Initialize(SigninClient* client);
-
-  virtual void Shutdown();
-
-  // Lists account IDs of all accounts with a refresh token.
-  virtual std::vector<std::string> GetAccounts() OVERRIDE;
-
-  // Loads credentials from a backing persistent store to make them available
-  // after service is used between profile restarts.
-  //
-  // Only call this method if there is at least one account connected to the
-  // profile, otherwise startup will cause unneeded work on the IO thread.  The
-  // primary account is specified with the |primary_account_id| argument and
-  // should not be empty.  For a regular profile, the primary account id comes
-  // from SigninManager.  For a managed account, the id comes from
-  // ManagedUserService.
-  virtual void LoadCredentials(const std::string& primary_account_id);
-
-  // Updates a |refresh_token| for an |account_id|. Credentials are persisted,
-  // and available through |LoadCredentials| after service is restarted.
-  virtual void UpdateCredentials(const std::string& account_id,
-                                 const std::string& refresh_token);
-
-  // Revokes all credentials handled by the object.
-  virtual void RevokeAllCredentials();
-
-  SigninErrorController* signin_error_controller() {
-    return signin_error_controller_.get();
-  }
-
-  const SigninErrorController* signin_error_controller() const {
-    return signin_error_controller_.get();
-  }
-
-  SigninClient* client() const { return client_; }
-
- protected:
-  ProfileOAuth2TokenService();
-
-  // OAuth2TokenService overrides.
-  // Note: These methods are overriden so that ProfileOAuth2TokenService is a
-  // concrete class.
-
-  // Simply returns NULL and should be overriden by subsclasses.
-  virtual net::URLRequestContextGetter* GetRequestContext() OVERRIDE;
-
-  // Updates the internal cache of the result from the most-recently-completed
-  // auth request (used for reporting errors to the user).
-  virtual void UpdateAuthError(
-      const std::string& account_id,
-      const GoogleServiceAuthError& error) OVERRIDE;
-
- private:
-  // The client with which this instance was initialized, or NULL.
-  SigninClient* client_;
-
-  // Used to expose auth errors to the UI.
-  scoped_ptr<SigninErrorController> signin_error_controller_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenService);
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_PROFILE_OAUTH2_TOKEN_SERVICE_H_
diff --git a/components/signin/core/signin_client.h b/components/signin/core/signin_client.h
deleted file mode 100644
index 779d2f8..0000000
--- a/components/signin/core/signin_client.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_SIGNIN_CLIENT_H_
-#define COMPONENTS_SIGNIN_CORE_SIGNIN_CLIENT_H_
-
-#include "components/signin/core/webdata/token_web_data.h"
-
-class TokenWebData;
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-// An interface that needs to be supplied to the Signin component by its
-// embedder.
-class SigninClient {
- public:
-  virtual ~SigninClient() {}
-
-  // Gets the TokenWebData instance associated with the client.
-  virtual scoped_refptr<TokenWebData> GetDatabase() = 0;
-
-  // Returns whether it is possible to revoke credentials.
-  virtual bool CanRevokeCredentials() = 0;
-
-  // Returns the URL request context information associated with the client.
-  virtual net::URLRequestContextGetter* GetURLRequestContext() = 0;
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_SIGNIN_CLIENT_H_
diff --git a/components/signin/core/signin_error_controller.cc b/components/signin/core/signin_error_controller.cc
deleted file mode 100644
index e3e93c8..0000000
--- a/components/signin/core/signin_error_controller.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/signin_error_controller.h"
-
-namespace {
-
-typedef std::set<const SigninErrorController::AuthStatusProvider*>
-    AuthStatusProviderSet;
-
-}  // namespace
-
-SigninErrorController::AuthStatusProvider::AuthStatusProvider() {
-}
-
-SigninErrorController::AuthStatusProvider::~AuthStatusProvider() {
-}
-
-SigninErrorController::SigninErrorController()
-    : auth_error_(GoogleServiceAuthError::AuthErrorNone()) {
-}
-
-SigninErrorController::~SigninErrorController() {
-  DCHECK(provider_set_.empty())
-      << "All AuthStatusProviders should be unregistered before"
-      << " SigninErrorController::Shutdown() is called";
-}
-
-void SigninErrorController::AddProvider(const AuthStatusProvider* provider) {
-  DCHECK(provider_set_.find(provider) == provider_set_.end())
-      << "Adding same AuthStatusProvider multiple times";
-  provider_set_.insert(provider);
-  AuthStatusChanged();
-}
-
-void SigninErrorController::RemoveProvider(const AuthStatusProvider* provider) {
-  AuthStatusProviderSet::iterator iter = provider_set_.find(provider);
-  DCHECK(iter != provider_set_.end())
-      << "Removing provider that was never added";
-  provider_set_.erase(iter);
-  AuthStatusChanged();
-}
-
-void SigninErrorController::AuthStatusChanged() {
-  GoogleServiceAuthError::State prev_state = auth_error_.state();
-  std::string prev_account_id = error_account_id_;
-  bool error_changed = false;
-
-  // Find an error among the status providers. If |auth_error_| has an
-  // actionable error state and some provider exposes a similar error and
-  // account id, use that error. Otherwise, just take the first actionable
-  // error we find.
-  for (AuthStatusProviderSet::const_iterator it = provider_set_.begin();
-       it != provider_set_.end(); ++it) {
-    GoogleServiceAuthError error = (*it)->GetAuthStatus();
-
-    // Ignore the states we don't want to elevate to the user.
-    if (error.state() == GoogleServiceAuthError::NONE ||
-        error.state() == GoogleServiceAuthError::CONNECTION_FAILED) {
-      continue;
-    }
-
-    std::string account_id = (*it)->GetAccountId();
-
-    // Prioritize this error if it matches the previous |auth_error_|.
-    if (error.state() == prev_state && account_id == prev_account_id) {
-      auth_error_ = error;
-      error_account_id_ = account_id;
-      error_changed = true;
-      break;
-    }
-
-    // Use this error if we haven't found one already, but keep looking for the
-    // previous |auth_error_| in case there's a match elsewhere in the set.
-    if (!error_changed) {
-      auth_error_ = error;
-      error_account_id_ = account_id;
-      error_changed = true;
-    }
-  }
-
-  if (!error_changed && prev_state != GoogleServiceAuthError::NONE) {
-    // No provider reported an error, so clear the error we have now.
-    auth_error_ = GoogleServiceAuthError::AuthErrorNone();
-    error_account_id_.clear();
-    error_changed = true;
-  }
-
-  if (error_changed) {
-    FOR_EACH_OBSERVER(Observer, observer_list_, OnErrorChanged());
-  }
-}
-
-bool SigninErrorController::HasError() const {
-  return auth_error_.state() != GoogleServiceAuthError::NONE &&
-      auth_error_.state() != GoogleServiceAuthError::CONNECTION_FAILED;
-}
-
-void SigninErrorController::AddObserver(Observer* observer) {
-  observer_list_.AddObserver(observer);
-}
-
-void SigninErrorController::RemoveObserver(Observer* observer) {
-  observer_list_.RemoveObserver(observer);
-}
diff --git a/components/signin/core/signin_error_controller.h b/components/signin/core/signin_error_controller.h
deleted file mode 100644
index c66963e..0000000
--- a/components/signin/core/signin_error_controller.h
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_SIGNIN_ERROR_CONTROLLER_H_
-#define COMPONENTS_SIGNIN_CORE_SIGNIN_ERROR_CONTROLLER_H_
-
-#include <set>
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "base/observer_list.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-
-// Keep track of auth errors and expose them to observers in the UI. Services
-// that wish to expose auth errors to the user should register an
-// AuthStatusProvider to report their current authentication state, and should
-// invoke AuthStatusChanged() when their authentication state may have changed.
-class SigninErrorController {
- public:
-  class AuthStatusProvider {
-   public:
-    AuthStatusProvider();
-    virtual ~AuthStatusProvider();
-
-    // Returns the account id with the status specified by GetAuthStatus().
-    virtual std::string GetAccountId() const = 0;
-
-    // API invoked by SigninErrorController to get the current auth status of
-    // the various signed in services.
-    virtual GoogleServiceAuthError GetAuthStatus() const = 0;
-  };
-
-  // The observer class for SigninErrorController lets the controller notify
-  // observers when an error arises or changes.
-  class Observer {
-   public:
-    virtual ~Observer() {}
-    virtual void OnErrorChanged() = 0;
-  };
-
-  SigninErrorController();
-  ~SigninErrorController();
-
-  // Adds a provider which the SigninErrorController object will start querying
-  // for auth status.
-  void AddProvider(const AuthStatusProvider* provider);
-
-  // Removes a provider previously added by SigninErrorController (generally
-  // only called in preparation for shutdown).
-  void RemoveProvider(const AuthStatusProvider* provider);
-
-  // Invoked when the auth status of an AuthStatusProvider has changed.
-  void AuthStatusChanged();
-
-  // True if there exists an error worth elevating to the user.
-  bool HasError() const;
-
-  void AddObserver(Observer* observer);
-  void RemoveObserver(Observer* observer);
-
-  const std::string& error_account_id() const { return error_account_id_; }
-  const GoogleServiceAuthError& auth_error() const { return auth_error_; }
-
- private:
-  std::set<const AuthStatusProvider*> provider_set_;
-
-  // The account that generated the last auth error.
-  std::string error_account_id_;
-
-  // The auth error detected the last time AuthStatusChanged() was invoked (or
-  // NONE if AuthStatusChanged() has never been invoked).
-  GoogleServiceAuthError auth_error_;
-
-  ObserverList<Observer, false> observer_list_;
-
-  DISALLOW_COPY_AND_ASSIGN(SigninErrorController);
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_SIGNIN_ERROR_CONTROLLER_H_
diff --git a/components/signin/core/signin_manager_cookie_helper.cc b/components/signin/core/signin_manager_cookie_helper.cc
deleted file mode 100644
index 3001dd3..0000000
--- a/components/signin/core/signin_manager_cookie_helper.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/signin_manager_cookie_helper.h"
-
-#include <vector>
-
-#include "base/message_loop/message_loop_proxy.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "net/cookies/cookie_monster.h"
-#include "net/url_request/url_request_context.h"
-
-SigninManagerCookieHelper::SigninManagerCookieHelper(
-    net::URLRequestContextGetter* request_context_getter,
-    scoped_refptr<base::MessageLoopProxy> ui_thread,
-    scoped_refptr<base::MessageLoopProxy> io_thread)
-    : request_context_getter_(request_context_getter),
-      ui_thread_(ui_thread),
-      io_thread_(io_thread) {
-  DCHECK(ui_thread_->BelongsToCurrentThread());
-}
-
-SigninManagerCookieHelper::~SigninManagerCookieHelper() {
-}
-
-void SigninManagerCookieHelper::StartFetchingGaiaCookiesOnUIThread(
-    const base::Callback<void(const net::CookieList& cookies)>& callback) {
-  StartFetchingCookiesOnUIThread(
-      GaiaUrls::GetInstance()->gaia_url(), callback);
-}
-
-void SigninManagerCookieHelper::StartFetchingCookiesOnUIThread(
-    const GURL& url,
-    const base::Callback<void(const net::CookieList& cookies)>& callback) {
-  DCHECK(ui_thread_->BelongsToCurrentThread());
-  DCHECK(!callback.is_null());
-  DCHECK(completion_callback_.is_null());
-
-  completion_callback_ = callback;
-  io_thread_->PostTask(FROM_HERE,
-      base::Bind(&SigninManagerCookieHelper::FetchCookiesOnIOThread,
-                 this,
-                 url));
-}
-
-void SigninManagerCookieHelper::FetchCookiesOnIOThread(const GURL& url) {
-  DCHECK(io_thread_->BelongsToCurrentThread());
-
-  scoped_refptr<net::CookieMonster> cookie_monster =
-      request_context_getter_->GetURLRequestContext()->
-      cookie_store()->GetCookieMonster();
-  if (cookie_monster.get()) {
-    cookie_monster->GetAllCookiesForURLAsync(
-        url, base::Bind(&SigninManagerCookieHelper::OnCookiesFetched, this));
-  } else {
-    OnCookiesFetched(net::CookieList());
-  }
-}
-
-void SigninManagerCookieHelper::OnCookiesFetched(
-    const net::CookieList& cookies) {
-  DCHECK(io_thread_->BelongsToCurrentThread());
-  ui_thread_->PostTask(FROM_HERE,
-      base::Bind(&SigninManagerCookieHelper::NotifyOnUIThread, this, cookies));
-}
-
-void SigninManagerCookieHelper::NotifyOnUIThread(
-    const net::CookieList& cookies) {
-  DCHECK(ui_thread_->BelongsToCurrentThread());
-  base::ResetAndReturn(&completion_callback_).Run(cookies);
-}
diff --git a/components/signin/core/signin_manager_cookie_helper.h b/components/signin/core/signin_manager_cookie_helper.h
deleted file mode 100644
index ec45865..0000000
--- a/components/signin/core/signin_manager_cookie_helper.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_SIGNIN_MANAGER_COOKIE_HELPER_H_
-#define COMPONENTS_SIGNIN_CORE_SIGNIN_MANAGER_COOKIE_HELPER_H_
-
-#include "base/callback_helpers.h"
-#include "base/memory/ref_counted.h"
-#include "net/cookies/canonical_cookie.h"
-#include "net/url_request/url_request_context_getter.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-namespace net {
-class URLRequestContextGetter;
-}
-
-// This class fetches GAIA cookie on IO thread on behalf of SigninManager which
-// only lives on the UI thread.
-class SigninManagerCookieHelper
-    : public base::RefCountedThreadSafe<SigninManagerCookieHelper> {
- public:
-  explicit SigninManagerCookieHelper(
-      net::URLRequestContextGetter* request_context_getter,
-      scoped_refptr<base::MessageLoopProxy> ui_thread,
-      scoped_refptr<base::MessageLoopProxy> io_thread);
-
-  // Starts fetching gaia cookies, which will notify its completion via
-  // callback.
-  void StartFetchingGaiaCookiesOnUIThread(
-      const base::Callback<void(const net::CookieList& cookies)>& callback);
-
-  // Starts fetching cookies for the given URL. This must be called on
-  // |ui_thread_|.
-  void StartFetchingCookiesOnUIThread(
-      const GURL& url,
-      const base::Callback<void(const net::CookieList& cookies)>& callback);
-
- private:
-  friend class base::RefCountedThreadSafe<SigninManagerCookieHelper>;
-  ~SigninManagerCookieHelper();
-
-  // Fetch cookies for the given URL. This must be called on |io_thread_|.
-  void FetchCookiesOnIOThread(const GURL& url);
-
-  // Callback for fetching cookies. This must be called on |io_thread_|.
-  void OnCookiesFetched(const net::CookieList& cookies);
-
-  // Notifies the completion callback. This must be called on |ui_thread_|.
-  void NotifyOnUIThread(const net::CookieList& cookies);
-
-  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
-  // This only mutates on |ui_thread_|.
-  base::Callback<void(const net::CookieList& cookies)> completion_callback_;
-
-  // The MessageLoopProxy that this class uses as its UI thread.
-  scoped_refptr<base::MessageLoopProxy> ui_thread_;
-  // The MessageLoopProxy that this class uses as its IO thread.
-  scoped_refptr<base::MessageLoopProxy> io_thread_;
-  DISALLOW_COPY_AND_ASSIGN(SigninManagerCookieHelper);
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_SIGNIN_MANAGER_COOKIE_HELPER_H_
diff --git a/components/signin/core/webdata/token_service_table.cc b/components/signin/core/webdata/token_service_table.cc
deleted file mode 100644
index 7d51a02..0000000
--- a/components/signin/core/webdata/token_service_table.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/webdata/token_service_table.h"
-
-#include <map>
-#include <string>
-
-#include "base/logging.h"
-#include "components/os_crypt/os_crypt.h"
-#include "components/webdata/common/web_database.h"
-#include "sql/statement.h"
-
-namespace {
-
-WebDatabaseTable::TypeKey GetKey() {
-  // We just need a unique constant. Use the address of a static that
-  // COMDAT folding won't touch in an optimizing linker.
-  static int table_key = 0;
-  return reinterpret_cast<void*>(&table_key);
-}
-
-}  // namespace
-
-TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) {
-  return static_cast<TokenServiceTable*>(db->GetTable(GetKey()));
-
-}
-
-WebDatabaseTable::TypeKey TokenServiceTable::GetTypeKey() const {
-  return GetKey();
-}
-
-bool TokenServiceTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
-  WebDatabaseTable::Init(db, meta_table);
-  if (!db_->DoesTableExist("token_service")) {
-    if (!db_->Execute("CREATE TABLE token_service ("
-                      "service VARCHAR PRIMARY KEY NOT NULL,"
-                      "encrypted_token BLOB)")) {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
-}
-
-bool TokenServiceTable::IsSyncable() {
-  return true;
-}
-
-bool TokenServiceTable::MigrateToVersion(int version,
-                                         bool* update_compatible_version) {
-  return true;
-}
-
-bool TokenServiceTable::RemoveAllTokens() {
-  sql::Statement s(db_->GetUniqueStatement(
-      "DELETE FROM token_service"));
-
-  return s.Run();
-}
-
-bool TokenServiceTable::RemoveTokenForService(const std::string& service) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "DELETE FROM token_service WHERE service = ?"));
-  s.BindString(0, service);
-
-  return s.Run();
-}
-
-bool TokenServiceTable::SetTokenForService(const std::string& service,
-                                           const std::string& token) {
-  std::string encrypted_token;
-  bool encrypted = OSCrypt::EncryptString(token, &encrypted_token);
-  if (!encrypted) {
-    return false;
-  }
-
-  // Don't bother with a cached statement since this will be a relatively
-  // infrequent operation.
-  sql::Statement s(db_->GetUniqueStatement(
-      "INSERT OR REPLACE INTO token_service "
-      "(service, encrypted_token) VALUES (?, ?)"));
-  s.BindString(0, service);
-  s.BindBlob(1, encrypted_token.data(),
-             static_cast<int>(encrypted_token.length()));
-
-  return s.Run();
-}
-
-bool TokenServiceTable::GetAllTokens(
-    std::map<std::string, std::string>* tokens) {
-  sql::Statement s(db_->GetUniqueStatement(
-      "SELECT service, encrypted_token FROM token_service"));
-
-  if (!s.is_valid())
-    return false;
-
-  while (s.Step()) {
-    std::string encrypted_token;
-    std::string decrypted_token;
-    std::string service;
-    service = s.ColumnString(0);
-    bool entry_ok = !service.empty() &&
-                    s.ColumnBlobAsString(1, &encrypted_token);
-    if (entry_ok) {
-      OSCrypt::DecryptString(encrypted_token, &decrypted_token);
-      (*tokens)[service] = decrypted_token;
-    } else {
-      NOTREACHED();
-      return false;
-    }
-  }
-  return true;
-}
diff --git a/components/signin/core/webdata/token_service_table.h b/components/signin/core/webdata/token_service_table.h
deleted file mode 100644
index e8d0fba..0000000
--- a/components/signin/core/webdata/token_service_table.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_SIGNIN_CORE_WEBDATA_TOKEN_SERVICE_TABLE_H_
-#define COMPONENTS_SIGNIN_CORE_WEBDATA_TOKEN_SERVICE_TABLE_H_
-
-#include <map>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "components/webdata/common/web_database_table.h"
-
-class WebDatabase;
-
-class TokenServiceTable : public WebDatabaseTable {
- public:
-  TokenServiceTable() {}
-  virtual ~TokenServiceTable() {}
-
-  // Retrieves the TokenServiceTable* owned by |database|.
-  static TokenServiceTable* FromWebDatabase(WebDatabase* db);
-
-  virtual WebDatabaseTable::TypeKey GetTypeKey() const OVERRIDE;
-  virtual bool Init(sql::Connection* db, sql::MetaTable* meta_table) OVERRIDE;
-  virtual bool IsSyncable() OVERRIDE;
-  virtual bool MigrateToVersion(int version,
-                                bool* update_compatible_version) OVERRIDE;
-
-  // Remove all tokens previously set with SetTokenForService.
-  bool RemoveAllTokens();
-
-  // Removes a token related to the service from the token_service table.
-  bool RemoveTokenForService(const std::string& service);
-
-  // Retrieves all tokens previously set with SetTokenForService.
-  // Returns true if there were tokens and we decrypted them,
-  // false if there was a failure somehow
-  bool GetAllTokens(std::map<std::string, std::string>* tokens);
-
-  // Store a token in the token_service table. Stored encrypted. May cause
-  // a mac keychain popup.
-  // True if we encrypted a token and stored it, false otherwise.
-  bool SetTokenForService(const std::string& service,
-                          const std::string& token);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TokenServiceTable);
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_WEBDATA_TOKEN_SERVICE_TABLE_H_
diff --git a/components/signin/core/webdata/token_service_table_unittest.cc b/components/signin/core/webdata/token_service_table_unittest.cc
deleted file mode 100644
index cab89d5..0000000
--- a/components/signin/core/webdata/token_service_table_unittest.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/path_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/time/time.h"
-#include "components/signin/core/webdata/token_service_table.h"
-#include "components/webdata/common/web_database.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::Time;
-
-class TokenServiceTableTest : public testing::Test {
- public:
-  TokenServiceTableTest() {}
-  virtual ~TokenServiceTableTest() {}
-
- protected:
-  virtual void SetUp() {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    file_ = temp_dir_.path().AppendASCII("TestWebDatabase");
-
-    table_.reset(new TokenServiceTable);
-    db_.reset(new WebDatabase);
-    db_->AddTable(table_.get());
-    ASSERT_EQ(sql::INIT_OK, db_->Init(file_));
-  }
-
-  base::FilePath file_;
-  base::ScopedTempDir temp_dir_;
-  scoped_ptr<TokenServiceTable> table_;
-  scoped_ptr<WebDatabase> db_;
- private:
-  DISALLOW_COPY_AND_ASSIGN(TokenServiceTableTest);
-};
-
-// Flaky on mac_rel. See http://crbug.com/228943
-#if defined(OS_MACOSX)
-#define MAYBE_TokenServiceGetAllRemoveAll DISABLED_TokenServiceGetAllRemoveAll
-#define MAYBE_TokenServiceGetSet DISABLED_TokenServiceGetSet
-#define MAYBE_TokenServiceRemove DISABLED_TokenServiceRemove
-#else
-#define MAYBE_TokenServiceGetAllRemoveAll TokenServiceGetAllRemoveAll
-#define MAYBE_TokenServiceGetSet TokenServiceGetSet
-#define MAYBE_TokenServiceRemove TokenServiceRemove
-#endif
-
-TEST_F(TokenServiceTableTest, MAYBE_TokenServiceGetAllRemoveAll) {
-  std::map<std::string, std::string> out_map;
-  std::string service;
-  std::string service2;
-  service = "testservice";
-  service2 = "othertestservice";
-
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_TRUE(out_map.empty());
-
-  // Check that get all tokens works
-  EXPECT_TRUE(table_->SetTokenForService(service, "pepperoni"));
-  EXPECT_TRUE(table_->SetTokenForService(service2, "steak"));
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_EQ("pepperoni", out_map.find(service)->second);
-  EXPECT_EQ("steak", out_map.find(service2)->second);
-  out_map.clear();
-
-  // Purge
-  EXPECT_TRUE(table_->RemoveAllTokens());
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_TRUE(out_map.empty());
-
-  // Check that you can still add it back in
-  EXPECT_TRUE(table_->SetTokenForService(service, "cheese"));
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_EQ("cheese", out_map.find(service)->second);
-}
-
-TEST_F(TokenServiceTableTest, MAYBE_TokenServiceGetSet) {
-  std::map<std::string, std::string> out_map;
-  std::string service;
-  service = "testservice";
-
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_TRUE(out_map.empty());
-
-  EXPECT_TRUE(table_->SetTokenForService(service, "pepperoni"));
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_EQ("pepperoni", out_map.find(service)->second);
-  out_map.clear();
-
-  // try blanking it - won't remove it from the db though!
-  EXPECT_TRUE(table_->SetTokenForService(service, std::string()));
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_EQ("", out_map.find(service)->second);
-  out_map.clear();
-
-  // try mutating it
-  EXPECT_TRUE(table_->SetTokenForService(service, "ham"));
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_EQ("ham", out_map.find(service)->second);
-}
-
-TEST_F(TokenServiceTableTest, MAYBE_TokenServiceRemove) {
-  std::map<std::string, std::string> out_map;
-  std::string service;
-  std::string service2;
-  service = "testservice";
-  service2 = "othertestservice";
-
-  EXPECT_TRUE(table_->SetTokenForService(service, "pepperoni"));
-  EXPECT_TRUE(table_->SetTokenForService(service2, "steak"));
-  EXPECT_TRUE(table_->RemoveTokenForService(service));
-  EXPECT_TRUE(table_->GetAllTokens(&out_map));
-  EXPECT_EQ(0u, out_map.count(service));
-  EXPECT_EQ("steak", out_map.find(service2)->second);
-}
diff --git a/components/signin/core/webdata/token_web_data.cc b/components/signin/core/webdata/token_web_data.cc
deleted file mode 100644
index 97e2748..0000000
--- a/components/signin/core/webdata/token_web_data.cc
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/signin/core/webdata/token_web_data.h"
-
-#include "base/bind.h"
-#include "base/memory/ref_counted_delete_on_message_loop.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/stl_util.h"
-#include "components/signin/core/webdata/token_service_table.h"
-#include "components/webdata/common/web_database_service.h"
-
-using base::Bind;
-using base::Time;
-
-class TokenWebDataBackend
-    : public base::RefCountedDeleteOnMessageLoop<TokenWebDataBackend> {
-
- public:
-  TokenWebDataBackend(scoped_refptr<base::MessageLoopProxy> db_thread)
-      : base::RefCountedDeleteOnMessageLoop<TokenWebDataBackend>(db_thread) {
-  }
-
-  WebDatabase::State RemoveAllTokens(WebDatabase* db) {
-    if (TokenServiceTable::FromWebDatabase(db)->RemoveAllTokens()) {
-      return WebDatabase::COMMIT_NEEDED;
-    }
-    return WebDatabase::COMMIT_NOT_NEEDED;
-  }
-
-  WebDatabase::State RemoveTokenForService(
-      const std::string& service, WebDatabase* db) {
-    if (TokenServiceTable::FromWebDatabase(db)
-            ->RemoveTokenForService(service)) {
-      return WebDatabase::COMMIT_NEEDED;
-    }
-    return WebDatabase::COMMIT_NOT_NEEDED;
-  }
-
-  WebDatabase::State SetTokenForService(
-      const std::string& service, const std::string& token, WebDatabase* db) {
-    if (TokenServiceTable::FromWebDatabase(db)->SetTokenForService(service,
-                                                                   token)) {
-      return WebDatabase::COMMIT_NEEDED;
-    }
-    return WebDatabase::COMMIT_NOT_NEEDED;
-  }
-
-  scoped_ptr<WDTypedResult> GetAllTokens(WebDatabase* db) {
-    std::map<std::string, std::string> map;
-    TokenServiceTable::FromWebDatabase(db)->GetAllTokens(&map);
-    return scoped_ptr<WDTypedResult>(
-        new WDResult<std::map<std::string, std::string> >(TOKEN_RESULT, map));
-  }
-
- protected:
-  virtual ~TokenWebDataBackend() {
-  }
-
- private:
-  friend class base::RefCountedDeleteOnMessageLoop<TokenWebDataBackend>;
-  friend class base::DeleteHelper<TokenWebDataBackend>;
-};
-
-TokenWebData::TokenWebData(scoped_refptr<WebDatabaseService> wdbs,
-                           scoped_refptr<base::MessageLoopProxy> ui_thread,
-                           scoped_refptr<base::MessageLoopProxy> db_thread,
-                           const ProfileErrorCallback& callback)
-    : WebDataServiceBase(wdbs, callback, ui_thread),
-      token_backend_(new TokenWebDataBackend(db_thread)) {
-}
-
-void TokenWebData::SetTokenForService(const std::string& service,
-                                      const std::string& token) {
-  wdbs_->ScheduleDBTask(FROM_HERE,
-      Bind(&TokenWebDataBackend::SetTokenForService, token_backend_,
-           service, token));
-}
-
-void TokenWebData::RemoveAllTokens() {
-  wdbs_->ScheduleDBTask(FROM_HERE,
-      Bind(&TokenWebDataBackend::RemoveAllTokens, token_backend_));
-}
-
-void TokenWebData::RemoveTokenForService(const std::string& service) {
-  wdbs_->ScheduleDBTask(FROM_HERE,
-      Bind(&TokenWebDataBackend::RemoveTokenForService, token_backend_,
-           service));
-}
-
-// Null on failure. Success is WDResult<std::string>
-WebDataServiceBase::Handle TokenWebData::GetAllTokens(
-    WebDataServiceConsumer* consumer) {
-  return wdbs_->ScheduleDBTaskWithResult(FROM_HERE,
-      Bind(&TokenWebDataBackend::GetAllTokens, token_backend_), consumer);
-}
-
-TokenWebData::TokenWebData(scoped_refptr<base::MessageLoopProxy> ui_thread,
-                           scoped_refptr<base::MessageLoopProxy> db_thread)
-    : WebDataServiceBase(NULL, ProfileErrorCallback(), ui_thread),
-      token_backend_(new TokenWebDataBackend(db_thread)) {
-}
-
-TokenWebData::~TokenWebData() {
-}
diff --git a/components/signin/core/webdata/token_web_data.h b/components/signin/core/webdata/token_web_data.h
deleted file mode 100644
index 1c5d58e..0000000
--- a/components/signin/core/webdata/token_web_data.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Chromium settings and storage represent user-selected preferences and
-// information and MUST not be extracted, overwritten or modified except
-// through Chromium defined APIs.
-
-#ifndef COMPONENTS_SIGNIN_CORE_WEBDATA_TOKEN_WEB_DATA_H__
-#define COMPONENTS_SIGNIN_CORE_WEBDATA_TOKEN_WEB_DATA_H__
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/callback_forward.h"
-#include "base/files/file_path.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "components/webdata/common/web_data_results.h"
-#include "components/webdata/common/web_data_service_base.h"
-#include "components/webdata/common/web_data_service_consumer.h"
-#include "components/webdata/common/web_database.h"
-
-namespace base {
-class MessageLoopProxy;
-}
-
-class TokenWebDataBackend;
-class WebDatabaseService;
-class WebDataServiceConsumer;
-
-// TokenWebData is a data repository for storage of authentication tokens.
-
-class TokenWebData : public WebDataServiceBase {
- public:
-  TokenWebData(scoped_refptr<WebDatabaseService> wdbs,
-               scoped_refptr<base::MessageLoopProxy> ui_thread,
-               scoped_refptr<base::MessageLoopProxy> db_thread,
-               const ProfileErrorCallback& callback);
-
-  TokenWebData(scoped_refptr<base::MessageLoopProxy> ui_thread,
-               scoped_refptr<base::MessageLoopProxy> db_thread);
-
-  // Set a token to use for a specified service.
-  void SetTokenForService(const std::string& service,
-                          const std::string& token);
-
-  // Remove all tokens stored in the web database.
-  void RemoveAllTokens();
-
-  // Removes a token related to |service| from the web database.
-  void RemoveTokenForService(const std::string& service);
-
-  // Null on failure. Success is WDResult<std::vector<std::string> >
-  virtual Handle GetAllTokens(WebDataServiceConsumer* consumer);
-
- protected:
-  // For unit tests, passes a null callback.
-  TokenWebData();
-
-  virtual ~TokenWebData();
-
- private:
-  scoped_refptr<TokenWebDataBackend> token_backend_;
-
-  DISALLOW_COPY_AND_ASSIGN(TokenWebData);
-};
-
-#endif  // COMPONENTS_SIGNIN_CORE_WEBDATA_TOKEN_WEB_DATA_H__
diff --git a/components/storage_monitor/media_storage_util.cc b/components/storage_monitor/media_storage_util.cc
index 20190d4..c95f534 100644
--- a/components/storage_monitor/media_storage_util.cc
+++ b/components/storage_monitor/media_storage_util.cc
@@ -116,7 +116,7 @@
   if (type == StorageInfo::MAC_IMAGE_CAPTURE)
     return true;
 
-  return path.IsAbsolute() && !path.ReferencesParent();
+  return !path.empty() && path.IsAbsolute() && !path.ReferencesParent();
 }
 
 // static
diff --git a/components/storage_monitor/media_storage_util_unittest.cc b/components/storage_monitor/media_storage_util_unittest.cc
index aa0f37c..d16cd07 100644
--- a/components/storage_monitor/media_storage_util_unittest.cc
+++ b/components/storage_monitor/media_storage_util_unittest.cc
@@ -119,6 +119,8 @@
   EXPECT_TRUE(MediaStorageUtil::CanCreateFileSystem(kImageCaptureDeviceId,
                                                     base::FilePath()));
   EXPECT_FALSE(MediaStorageUtil::CanCreateFileSystem(
+      "dcim:xyz", base::FilePath()));
+  EXPECT_FALSE(MediaStorageUtil::CanCreateFileSystem(
       "dcim:xyz", base::FilePath(FILE_PATH_LITERAL("relative"))));
   EXPECT_FALSE(MediaStorageUtil::CanCreateFileSystem(
       "dcim:xyz", base::FilePath(FILE_PATH_LITERAL("../refparent"))));
diff --git a/components/storage_monitor/storage_monitor.h b/components/storage_monitor/storage_monitor.h
index 637c4ce..14223e6 100644
--- a/components/storage_monitor/storage_monitor.h
+++ b/components/storage_monitor/storage_monitor.h
@@ -20,7 +20,6 @@
 
 class MediaFileSystemRegistryTest;
 class MediaGalleriesPlatformAppBrowserTest;
-class MediaGalleriesPrivateApiTest;
 class SystemStorageApiTest;
 class SystemStorageEjectApiTest;
 
@@ -142,7 +141,6 @@
  protected:
   friend class ::MediaFileSystemRegistryTest;
   friend class ::MediaGalleriesPlatformAppBrowserTest;
-  friend class ::MediaGalleriesPrivateApiTest;
   friend class ::SystemStorageApiTest;
   friend class ::SystemStorageEjectApiTest;
 
diff --git a/components/storage_monitor/storage_monitor_chromeos_unittest.cc b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
index dd859d7..312a785 100644
--- a/components/storage_monitor/storage_monitor_chromeos_unittest.cc
+++ b/components/storage_monitor/storage_monitor_chromeos_unittest.cc
@@ -196,8 +196,16 @@
     uint64 device_size_in_bytes) {
   if (error_code == chromeos::MOUNT_ERROR_NONE) {
     disk_mount_manager_mock_->CreateDiskEntryForMountDevice(
-        mount_info, unique_id, device_label, vendor_name, product_name,
-        device_type, device_size_in_bytes);
+        mount_info,
+        unique_id,
+        device_label,
+        vendor_name,
+        product_name,
+        device_type,
+        device_size_in_bytes,
+        false /* is_parent */,
+        true /* has_media */,
+        false /* on_boot_device */);
   }
   monitor_->OnMountEvent(DiskMountManager::MOUNTING, error_code, mount_info);
   WaitForFileThread();
diff --git a/components/sync_driver/sync_frontend.h b/components/sync_driver/sync_frontend.h
index f7ed853..47d76be 100644
--- a/components/sync_driver/sync_frontend.h
+++ b/components/sync_driver/sync_frontend.h
@@ -15,6 +15,7 @@
 namespace syncer {
 class DataTypeDebugInfoListener;
 class JsBackend;
+class ProtocolEvent;
 }  // namespace syncer
 
 namespace sync_pb {
@@ -53,6 +54,14 @@
   // retried.
   virtual void OnSyncConfigureRetry() = 0;
 
+  // Informs the frontned of some network event.  These notifications are
+  // disabled by default and must be enabled through an explicit request to the
+  // SyncBackendHost.
+  //
+  // It's disabld by default to avoid copying data across threads when no one
+  // is listening for it.
+  virtual void OnProtocolEvent(const syncer::ProtocolEvent& event) = 0;
+
   // The status of the connection to the sync server has changed.
   virtual void OnConnectionStatusChange(
       syncer::ConnectionStatus status) = 0;
diff --git a/components/test/data/json_schema/pattern_properties_dot.json b/components/test/data/json_schema/pattern_properties_dot.json
new file mode 100644
index 0000000..6a15f3e
--- /dev/null
+++ b/components/test/data/json_schema/pattern_properties_dot.json
@@ -0,0 +1,6 @@
+{
+  "type": "object",
+  "patternProperties": {
+    "^.$": { "type": "any" }
+  }
+}
diff --git a/components/test/data/web_database/OWNERS b/components/test/data/web_database/OWNERS
index 59f8395..dbe16c9 100644
--- a/components/test/data/web_database/OWNERS
+++ b/components/test/data/web_database/OWNERS
@@ -1,4 +1,3 @@
-joi@chromium.org
 pkasting@chromium.org
 
 # For sqlite stuff:
diff --git a/components/test/data/web_database/version_20.sql b/components/test/data/web_database/version_20.sql
new file mode 100644
index 0000000..c3913ef
--- /dev/null
+++ b/components/test/data/web_database/version_20.sql
@@ -0,0 +1,23 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR);
+INSERT INTO "meta" VALUES('version','20');
+INSERT INTO "meta" VALUES('last_compatible_version','20');
+INSERT INTO "meta" VALUES('Builtin Keyword Version','27');
+INSERT INTO "meta" VALUES('Default Search Provider ID','7');
+CREATE TABLE keywords (id INTEGER PRIMARY KEY,short_name VARCHAR NOT NULL, keyword VARCHAR NOT NULL,favicon_url VARCHAR NOT NULL,url VARCHAR NOT NULL,show_in_default_list INTEGER,safe_for_autoreplace INTEGER,originating_url VARCHAR,date_created INTEGER DEFAULT 0,usage_count INTEGER DEFAULT 0,input_encodings VARCHAR,suggest_url VARCHAR,prepopulate_id INTEGER DEFAULT 0);
+INSERT INTO "keywords" VALUES(2,'Google','google.com','http://www.google.com/favicon.ico','{google:baseURL}search?{google:RLZ}{google:acceptedSuggestion}{google:originalQueryForSuggestion}sourceid=chrome&ie={inputEncoding}&q={searchTerms}',1,1,'',0,0,'UTF-8','{google:baseSuggestURL}search?client=chrome&hl={language}&q={searchTerms}',1);
+INSERT INTO "keywords" VALUES(3,'Yahoo!','yahoo.com','http://search.yahoo.com/favicon.ico','http://search.yahoo.com/search?ei={inputEncoding}&fr=crmas&p={searchTerms}',1,1,'',0,0,'UTF-8','http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}',2);
+INSERT INTO "keywords" VALUES(4,'Bing','bing.com','http://www.bing.com/s/wlflag.ico','http://www.bing.com/search?setmkt=en-US&q={searchTerms}',1,1,'',0,0,'UTF-8','http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}',3);
+INSERT INTO "keywords" VALUES(5,'Wikipedia (en)','en.wikipedia.org','','http://en.wikipedia.org/w/index.php?title=Special:Search&search={searchTerms}',1,0,'',1283287335,0,'','',0);
+INSERT INTO "keywords" VALUES(6,'NYTimes','query.nytimes.com','','http://query.nytimes.com/gst/handler.html?query={searchTerms}&opensearch=1',1,0,'',1283287335,0,'','',0);
+INSERT INTO "keywords" VALUES(7,'eBay','rover.ebay.com','','http://rover.ebay.com/rover/1/711-43047-14818-1/4?satitle={searchTerms}',1,0,'',1283287335,0,'','',0);
+INSERT INTO "keywords" VALUES(8,'ff','ff','','http://ff{searchTerms}',0,0,'',1283287356,0,'','',0);
+CREATE TABLE logins (origin_url VARCHAR NOT NULL, action_url VARCHAR, username_element VARCHAR, username_value VARCHAR, password_element VARCHAR, password_value BLOB, submit_element VARCHAR,signon_realm VARCHAR NOT NULL,ssl_valid INTEGER NOT NULL,preferred INTEGER NOT NULL,date_created INTEGER NOT NULL,blacklisted_by_user INTEGER NOT NULL,scheme INTEGER NOT NULL,UNIQUE (origin_url, username_element, username_value, password_element, submit_element, signon_realm));
+CREATE TABLE ie7_logins (url_hash VARCHAR NOT NULL, password_value BLOB, date_created INTEGER NOT NULL,UNIQUE (url_hash));
+CREATE TABLE web_app_icons (url LONGVARCHAR,width int,height int,image BLOB, UNIQUE (url, width, height));
+CREATE TABLE web_apps (url LONGVARCHAR UNIQUE,has_all_images INTEGER NOT NULL);
+CREATE INDEX logins_signon ON logins (signon_realm);
+CREATE INDEX ie7_logins_hash ON ie7_logins (url_hash);
+CREATE INDEX web_apps_url_index ON web_apps (url);
+COMMIT;
diff --git a/components/tracing.target.darwin-arm.mk b/components/tracing.target.darwin-arm.mk
index 10946f7..e4f97f4 100644
--- a/components/tracing.target.darwin-arm.mk
+++ b/components/tracing.target.darwin-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/tracing.target.darwin-mips.mk b/components/tracing.target.darwin-mips.mk
index 1feb1d4..da1e796 100644
--- a/components/tracing.target.darwin-mips.mk
+++ b/components/tracing.target.darwin-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/tracing.target.darwin-x86.mk b/components/tracing.target.darwin-x86.mk
index 1fb6338..200f51d 100644
--- a/components/tracing.target.darwin-x86.mk
+++ b/components/tracing.target.darwin-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/tracing.target.darwin-x86_64.mk b/components/tracing.target.darwin-x86_64.mk
new file mode 100644
index 0000000..ca5af5a
--- /dev/null
+++ b/components/tracing.target.darwin-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_tracing_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/tracing/child_trace_message_filter.cc \
+	components/tracing/tracing_messages.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_tracing_gyp
+
+# Alias gyp target name.
+.PHONY: tracing
+tracing: components_tracing_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/tracing.target.linux-arm.mk b/components/tracing.target.linux-arm.mk
index 10946f7..e4f97f4 100644
--- a/components/tracing.target.linux-arm.mk
+++ b/components/tracing.target.linux-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/tracing.target.linux-mips.mk b/components/tracing.target.linux-mips.mk
index 1feb1d4..da1e796 100644
--- a/components/tracing.target.linux-mips.mk
+++ b/components/tracing.target.linux-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/tracing.target.linux-x86.mk b/components/tracing.target.linux-x86.mk
index 1fb6338..200f51d 100644
--- a/components/tracing.target.linux-x86.mk
+++ b/components/tracing.target.linux-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/tracing.target.linux-x86_64.mk b/components/tracing.target.linux-x86_64.mk
new file mode 100644
index 0000000..ca5af5a
--- /dev/null
+++ b/components/tracing.target.linux-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_tracing_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/tracing/child_trace_message_filter.cc \
+	components/tracing/tracing_messages.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_tracing_gyp
+
+# Alias gyp target name.
+.PHONY: tracing
+tracing: components_tracing_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/translate/core/browser/translate_client.h b/components/translate/core/browser/translate_client.h
index 6288e79..2ca8162 100644
--- a/components/translate/core/browser/translate_client.h
+++ b/components/translate/core/browser/translate_client.h
@@ -5,6 +5,11 @@
 #ifndef COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_CLIENT_H_
 #define COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_CLIENT_H_
 
+#include "base/memory/ref_counted.h"
+#include "components/translate/core/browser/translate_prefs.h"
+
+class PrefService;
+class TranslateAcceptLanguages;
 class TranslateDriver;
 
 // A client interface that needs to be supplied to TranslateManager by the
@@ -16,6 +21,15 @@
  public:
   // Gets the TranslateDriver associated with the client.
   virtual TranslateDriver* GetTranslateDriver() = 0;
+
+  // Returns the associated PrefService.
+  virtual PrefService* GetPrefs() = 0;
+
+  // Returns the associated TranslatePrefs.
+  virtual scoped_ptr<TranslatePrefs> GetTranslatePrefs() = 0;
+
+  // Returns the associated TranslateAcceptLanguages.
+  virtual TranslateAcceptLanguages* GetTranslateAcceptLanguages() = 0;
 };
 
 #endif  // COMPONENTS_TRANSLATE_CORE_BROWSER_TRANSLATE_CLIENT_H_
diff --git a/components/user_prefs.target.darwin-arm.mk b/components/user_prefs.target.darwin-arm.mk
index 4eb09d0..8a98c92 100644
--- a/components/user_prefs.target.darwin-arm.mk
+++ b/components/user_prefs.target.darwin-arm.mk
@@ -91,9 +91,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -102,6 +100,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/user_prefs.target.darwin-mips.mk b/components/user_prefs.target.darwin-mips.mk
index 05ede3a..a94a593 100644
--- a/components/user_prefs.target.darwin-mips.mk
+++ b/components/user_prefs.target.darwin-mips.mk
@@ -90,9 +90,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -225,6 +222,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/user_prefs.target.darwin-x86.mk b/components/user_prefs.target.darwin-x86.mk
index 5327809..125155e 100644
--- a/components/user_prefs.target.darwin-x86.mk
+++ b/components/user_prefs.target.darwin-x86.mk
@@ -91,9 +91,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -102,6 +100,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -215,9 +214,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -226,6 +223,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/user_prefs.target.darwin-x86_64.mk b/components/user_prefs.target.darwin-x86_64.mk
new file mode 100644
index 0000000..391101a
--- /dev/null
+++ b/components/user_prefs.target.darwin-x86_64.mk
@@ -0,0 +1,344 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_user_prefs_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/user_prefs/pref_registry_syncable.cc \
+	components/user_prefs/user_prefs.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSER_PREFS_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSER_PREFS_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp \
+	ui_base_ui_base_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_user_prefs_gyp
+
+# Alias gyp target name.
+.PHONY: user_prefs
+user_prefs: components_user_prefs_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/user_prefs.target.linux-arm.mk b/components/user_prefs.target.linux-arm.mk
index 4eb09d0..8a98c92 100644
--- a/components/user_prefs.target.linux-arm.mk
+++ b/components/user_prefs.target.linux-arm.mk
@@ -91,9 +91,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -102,6 +100,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/user_prefs.target.linux-mips.mk b/components/user_prefs.target.linux-mips.mk
index 05ede3a..a94a593 100644
--- a/components/user_prefs.target.linux-mips.mk
+++ b/components/user_prefs.target.linux-mips.mk
@@ -90,9 +90,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -225,6 +222,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/user_prefs.target.linux-x86.mk b/components/user_prefs.target.linux-x86.mk
index 5327809..125155e 100644
--- a/components/user_prefs.target.linux-x86.mk
+++ b/components/user_prefs.target.linux-x86.mk
@@ -91,9 +91,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -102,6 +100,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -215,9 +214,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -226,6 +223,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/user_prefs.target.linux-x86_64.mk b/components/user_prefs.target.linux-x86_64.mk
new file mode 100644
index 0000000..391101a
--- /dev/null
+++ b/components/user_prefs.target.linux-x86_64.mk
@@ -0,0 +1,344 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_user_prefs_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/user_prefs/pref_registry_syncable.cc \
+	components/user_prefs/user_prefs.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSER_PREFS_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSER_PREFS_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp \
+	ui_base_ui_base_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_user_prefs_gyp
+
+# Alias gyp target name.
+.PHONY: user_prefs
+user_prefs: components_user_prefs_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/visitedlink_browser.target.darwin-arm.mk b/components/visitedlink_browser.target.darwin-arm.mk
index 81727c1..68a3edb 100644
--- a/components/visitedlink_browser.target.darwin-arm.mk
+++ b/components/visitedlink_browser.target.darwin-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_browser.target.darwin-mips.mk b/components/visitedlink_browser.target.darwin-mips.mk
index 6342e67..a6bd7a6 100644
--- a/components/visitedlink_browser.target.darwin-mips.mk
+++ b/components/visitedlink_browser.target.darwin-mips.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_browser.target.darwin-x86.mk b/components/visitedlink_browser.target.darwin-x86.mk
index 31a3f13..85c78e2 100644
--- a/components/visitedlink_browser.target.darwin-x86.mk
+++ b/components/visitedlink_browser.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_browser.target.darwin-x86_64.mk b/components/visitedlink_browser.target.darwin-x86_64.mk
new file mode 100644
index 0000000..3d590c7
--- /dev/null
+++ b/components/visitedlink_browser.target.darwin-x86_64.mk
@@ -0,0 +1,278 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_visitedlink_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/visitedlink/browser/visitedlink_event_listener.cc \
+	components/visitedlink/browser/visitedlink_master.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_visitedlink_browser_gyp
+
+# Alias gyp target name.
+.PHONY: visitedlink_browser
+visitedlink_browser: components_visitedlink_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/visitedlink_browser.target.linux-arm.mk b/components/visitedlink_browser.target.linux-arm.mk
index 81727c1..68a3edb 100644
--- a/components/visitedlink_browser.target.linux-arm.mk
+++ b/components/visitedlink_browser.target.linux-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_browser.target.linux-mips.mk b/components/visitedlink_browser.target.linux-mips.mk
index 6342e67..a6bd7a6 100644
--- a/components/visitedlink_browser.target.linux-mips.mk
+++ b/components/visitedlink_browser.target.linux-mips.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_browser.target.linux-x86.mk b/components/visitedlink_browser.target.linux-x86.mk
index 31a3f13..85c78e2 100644
--- a/components/visitedlink_browser.target.linux-x86.mk
+++ b/components/visitedlink_browser.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_browser.target.linux-x86_64.mk b/components/visitedlink_browser.target.linux-x86_64.mk
new file mode 100644
index 0000000..3d590c7
--- /dev/null
+++ b/components/visitedlink_browser.target.linux-x86_64.mk
@@ -0,0 +1,278 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_visitedlink_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/visitedlink/browser/visitedlink_event_listener.cc \
+	components/visitedlink/browser/visitedlink_master.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_visitedlink_browser_gyp
+
+# Alias gyp target name.
+.PHONY: visitedlink_browser
+visitedlink_browser: components_visitedlink_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/visitedlink_common.target.darwin-arm.mk b/components/visitedlink_common.target.darwin-arm.mk
index a4dafac..e2469cb 100644
--- a/components/visitedlink_common.target.darwin-arm.mk
+++ b/components/visitedlink_common.target.darwin-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_common.target.darwin-mips.mk b/components/visitedlink_common.target.darwin-mips.mk
index b5531fd..f14a4f6 100644
--- a/components/visitedlink_common.target.darwin-mips.mk
+++ b/components/visitedlink_common.target.darwin-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_common.target.darwin-x86.mk b/components/visitedlink_common.target.darwin-x86.mk
index adb7000..d1be7b5 100644
--- a/components/visitedlink_common.target.darwin-x86.mk
+++ b/components/visitedlink_common.target.darwin-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +172,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_common.target.darwin-x86_64.mk b/components/visitedlink_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..87d3f70
--- /dev/null
+++ b/components/visitedlink_common.target.darwin-x86_64.mk
@@ -0,0 +1,274 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_visitedlink_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/visitedlink/common/visitedlink_common.cc \
+	components/visitedlink/common/visitedlink_message_generator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_visitedlink_common_gyp
+
+# Alias gyp target name.
+.PHONY: visitedlink_common
+visitedlink_common: components_visitedlink_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/visitedlink_common.target.linux-arm.mk b/components/visitedlink_common.target.linux-arm.mk
index a4dafac..e2469cb 100644
--- a/components/visitedlink_common.target.linux-arm.mk
+++ b/components/visitedlink_common.target.linux-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_common.target.linux-mips.mk b/components/visitedlink_common.target.linux-mips.mk
index b5531fd..f14a4f6 100644
--- a/components/visitedlink_common.target.linux-mips.mk
+++ b/components/visitedlink_common.target.linux-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_common.target.linux-x86.mk b/components/visitedlink_common.target.linux-x86.mk
index adb7000..d1be7b5 100644
--- a/components/visitedlink_common.target.linux-x86.mk
+++ b/components/visitedlink_common.target.linux-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +172,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_common.target.linux-x86_64.mk b/components/visitedlink_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..87d3f70
--- /dev/null
+++ b/components/visitedlink_common.target.linux-x86_64.mk
@@ -0,0 +1,274 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_visitedlink_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/visitedlink/common/visitedlink_common.cc \
+	components/visitedlink/common/visitedlink_message_generator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_visitedlink_common_gyp
+
+# Alias gyp target name.
+.PHONY: visitedlink_common
+visitedlink_common: components_visitedlink_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/visitedlink_renderer.target.darwin-arm.mk b/components/visitedlink_renderer.target.darwin-arm.mk
index 921f7b8..39010f1 100644
--- a/components/visitedlink_renderer.target.darwin-arm.mk
+++ b/components/visitedlink_renderer.target.darwin-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -102,6 +100,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -239,6 +236,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_renderer.target.darwin-mips.mk b/components/visitedlink_renderer.target.darwin-mips.mk
index 8b6c092..d051bcd 100644
--- a/components/visitedlink_renderer.target.darwin-mips.mk
+++ b/components/visitedlink_renderer.target.darwin-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -237,6 +234,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_renderer.target.darwin-x86.mk b/components/visitedlink_renderer.target.darwin-x86.mk
index 91d5581..9c61b23 100644
--- a/components/visitedlink_renderer.target.darwin-x86.mk
+++ b/components/visitedlink_renderer.target.darwin-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -103,6 +101,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -240,6 +237,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_renderer.target.darwin-x86_64.mk b/components/visitedlink_renderer.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a488489
--- /dev/null
+++ b/components/visitedlink_renderer.target.darwin-x86_64.mk
@@ -0,0 +1,364 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_visitedlink_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/visitedlink/renderer/visitedlink_slave.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_visitedlink_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: visitedlink_renderer
+visitedlink_renderer: components_visitedlink_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/visitedlink_renderer.target.linux-arm.mk b/components/visitedlink_renderer.target.linux-arm.mk
index 921f7b8..39010f1 100644
--- a/components/visitedlink_renderer.target.linux-arm.mk
+++ b/components/visitedlink_renderer.target.linux-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -102,6 +100,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -239,6 +236,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_renderer.target.linux-mips.mk b/components/visitedlink_renderer.target.linux-mips.mk
index 8b6c092..d051bcd 100644
--- a/components/visitedlink_renderer.target.linux-mips.mk
+++ b/components/visitedlink_renderer.target.linux-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -237,6 +234,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_renderer.target.linux-x86.mk b/components/visitedlink_renderer.target.linux-x86.mk
index 91d5581..9c61b23 100644
--- a/components/visitedlink_renderer.target.linux-x86.mk
+++ b/components/visitedlink_renderer.target.linux-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -103,6 +101,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -240,6 +237,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/visitedlink_renderer.target.linux-x86_64.mk b/components/visitedlink_renderer.target.linux-x86_64.mk
new file mode 100644
index 0000000..a488489
--- /dev/null
+++ b/components/visitedlink_renderer.target.linux-x86_64.mk
@@ -0,0 +1,364 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_visitedlink_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/visitedlink/renderer/visitedlink_slave.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_visitedlink_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: visitedlink_renderer
+visitedlink_renderer: components_visitedlink_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/web_contents_delegate_android.target.darwin-arm.mk b/components/web_contents_delegate_android.target.darwin-arm.mk
index 3ec1c63..611ce9f 100644
--- a/components/web_contents_delegate_android.target.darwin-arm.mk
+++ b/components/web_contents_delegate_android.target.darwin-arm.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android.target.darwin-mips.mk b/components/web_contents_delegate_android.target.darwin-mips.mk
index 1e94d45..529fd38 100644
--- a/components/web_contents_delegate_android.target.darwin-mips.mk
+++ b/components/web_contents_delegate_android.target.darwin-mips.mk
@@ -93,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -104,6 +102,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -217,9 +216,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -228,6 +225,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android.target.darwin-x86.mk b/components/web_contents_delegate_android.target.darwin-x86.mk
index 0b9ca70..e9bd4de 100644
--- a/components/web_contents_delegate_android.target.darwin-x86.mk
+++ b/components/web_contents_delegate_android.target.darwin-x86.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -229,6 +226,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android.target.darwin-x86_64.mk b/components/web_contents_delegate_android.target.darwin-x86_64.mk
new file mode 100644
index 0000000..fb6a548
--- /dev/null
+++ b/components/web_contents_delegate_android.target.darwin-x86_64.mk
@@ -0,0 +1,348 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_web_contents_delegate_android_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,components_web_contents_delegate_android_jni_headers_gyp)/web_contents_delegate_android_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/web_contents_delegate_android/color_chooser_android.cc \
+	components/web_contents_delegate_android/component_jni_registrar.cc \
+	components/web_contents_delegate_android/validation_message_bubble_android.cc \
+	components/web_contents_delegate_android/web_contents_delegate_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_web_contents_delegate_android_gyp
+
+# Alias gyp target name.
+.PHONY: web_contents_delegate_android
+web_contents_delegate_android: components_web_contents_delegate_android_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/web_contents_delegate_android.target.linux-arm.mk b/components/web_contents_delegate_android.target.linux-arm.mk
index 3ec1c63..611ce9f 100644
--- a/components/web_contents_delegate_android.target.linux-arm.mk
+++ b/components/web_contents_delegate_android.target.linux-arm.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android.target.linux-mips.mk b/components/web_contents_delegate_android.target.linux-mips.mk
index 1e94d45..529fd38 100644
--- a/components/web_contents_delegate_android.target.linux-mips.mk
+++ b/components/web_contents_delegate_android.target.linux-mips.mk
@@ -93,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -104,6 +102,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -217,9 +216,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -228,6 +225,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android.target.linux-x86.mk b/components/web_contents_delegate_android.target.linux-x86.mk
index 0b9ca70..e9bd4de 100644
--- a/components/web_contents_delegate_android.target.linux-x86.mk
+++ b/components/web_contents_delegate_android.target.linux-x86.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -229,6 +226,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android.target.linux-x86_64.mk b/components/web_contents_delegate_android.target.linux-x86_64.mk
new file mode 100644
index 0000000..fb6a548
--- /dev/null
+++ b/components/web_contents_delegate_android.target.linux-x86_64.mk
@@ -0,0 +1,348 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_web_contents_delegate_android_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,components_web_contents_delegate_android_jni_headers_gyp)/web_contents_delegate_android_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/web_contents_delegate_android/color_chooser_android.cc \
+	components/web_contents_delegate_android/component_jni_registrar.cc \
+	components/web_contents_delegate_android/validation_message_bubble_android.cc \
+	components/web_contents_delegate_android/web_contents_delegate_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_web_contents_delegate_android_gyp
+
+# Alias gyp target name.
+.PHONY: web_contents_delegate_android
+web_contents_delegate_android: components_web_contents_delegate_android_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/web_contents_delegate_android/web_contents_delegate_android.cc b/components/web_contents_delegate_android/web_contents_delegate_android.cc
index d12a23f..a4f8213 100644
--- a/components/web_contents_delegate_android/web_contents_delegate_android.cc
+++ b/components/web_contents_delegate_android/web_contents_delegate_android.cc
@@ -139,7 +139,8 @@
   // to focus. Not implemented on Android.
 }
 
-void WebContentsDelegateAndroid::LoadingStateChanged(WebContents* source) {
+void WebContentsDelegateAndroid::LoadingStateChanged(WebContents* source,
+    bool to_different_document) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
   if (obj.is_null())
diff --git a/components/web_contents_delegate_android/web_contents_delegate_android.h b/components/web_contents_delegate_android/web_contents_delegate_android.h
index d672028..4c3568a 100644
--- a/components/web_contents_delegate_android/web_contents_delegate_android.h
+++ b/components/web_contents_delegate_android/web_contents_delegate_android.h
@@ -62,7 +62,8 @@
                                       unsigned changed_flags) OVERRIDE;
   virtual void ActivateContents(content::WebContents* contents) OVERRIDE;
   virtual void DeactivateContents(content::WebContents* contents) OVERRIDE;
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
   virtual void LoadProgressChanged(content::WebContents* source,
                                    double load_progress) OVERRIDE;
   virtual void RendererUnresponsive(content::WebContents* source) OVERRIDE;
diff --git a/components/web_contents_delegate_android_jni_headers.target.darwin-arm.mk b/components/web_contents_delegate_android_jni_headers.target.darwin-arm.mk
index 03b07ec..63ad00e 100644
--- a/components/web_contents_delegate_android_jni_headers.target.darwin-arm.mk
+++ b/components/web_contents_delegate_android_jni_headers.target.darwin-arm.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -201,6 +202,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android_jni_headers.target.darwin-mips.mk b/components/web_contents_delegate_android_jni_headers.target.darwin-mips.mk
index 11e8bf0..4e6f142 100644
--- a/components/web_contents_delegate_android_jni_headers.target.darwin-mips.mk
+++ b/components/web_contents_delegate_android_jni_headers.target.darwin-mips.mk
@@ -118,6 +118,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -199,6 +200,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android_jni_headers.target.darwin-x86.mk b/components/web_contents_delegate_android_jni_headers.target.darwin-x86.mk
index 5ca567b..61eb457 100644
--- a/components/web_contents_delegate_android_jni_headers.target.darwin-x86.mk
+++ b/components/web_contents_delegate_android_jni_headers.target.darwin-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -202,6 +203,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android_jni_headers.target.darwin-x86_64.mk b/components/web_contents_delegate_android_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..9e8a6e8
--- /dev/null
+++ b/components/web_contents_delegate_android_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,258 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_web_contents_delegate_android_jni_headers_gyp
+LOCAL_MODULE_STEM := web_contents_delegate_android_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "components_components_gyp_web_contents_delegate_android_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ColorChooserAndroid.java', 'web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java', 'web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: $(LOCAL_PATH)/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ColorChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ColorChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+components_web_contents_delegate_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: $(LOCAL_PATH)/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java --output_dir "$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+components_web_contents_delegate_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h
+
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: $(LOCAL_PATH)/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+components_web_contents_delegate_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h \
+	components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_web_contents_delegate_android_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: web_contents_delegate_android_jni_headers
+web_contents_delegate_android_jni_headers: components_web_contents_delegate_android_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/web_contents_delegate_android_jni_headers.target.linux-arm.mk b/components/web_contents_delegate_android_jni_headers.target.linux-arm.mk
index 03b07ec..63ad00e 100644
--- a/components/web_contents_delegate_android_jni_headers.target.linux-arm.mk
+++ b/components/web_contents_delegate_android_jni_headers.target.linux-arm.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -201,6 +202,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android_jni_headers.target.linux-mips.mk b/components/web_contents_delegate_android_jni_headers.target.linux-mips.mk
index 11e8bf0..4e6f142 100644
--- a/components/web_contents_delegate_android_jni_headers.target.linux-mips.mk
+++ b/components/web_contents_delegate_android_jni_headers.target.linux-mips.mk
@@ -118,6 +118,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -199,6 +200,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android_jni_headers.target.linux-x86.mk b/components/web_contents_delegate_android_jni_headers.target.linux-x86.mk
index 5ca567b..61eb457 100644
--- a/components/web_contents_delegate_android_jni_headers.target.linux-x86.mk
+++ b/components/web_contents_delegate_android_jni_headers.target.linux-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -202,6 +203,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/web_contents_delegate_android_jni_headers.target.linux-x86_64.mk b/components/web_contents_delegate_android_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..9e8a6e8
--- /dev/null
+++ b/components/web_contents_delegate_android_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,258 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := components_web_contents_delegate_android_jni_headers_gyp
+LOCAL_MODULE_STEM := web_contents_delegate_android_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "components_components_gyp_web_contents_delegate_android_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ColorChooserAndroid.java', 'web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java', 'web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h: $(LOCAL_PATH)/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ColorChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ColorChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+components_web_contents_delegate_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h: $(LOCAL_PATH)/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/ValidationMessageBubble.java --output_dir "$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+components_web_contents_delegate_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h
+
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h: $(LOCAL_PATH)/components/web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni; cd $(gyp_local_path)/components; ../base/android/jni_generator/jni_generator.py --input_file web_contents_delegate_android/android/java/src/org/chromium/components/web_contents_delegate_android/WebContentsDelegateAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+components_web_contents_delegate_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ColorChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/ValidationMessageBubble_jni.h \
+	$(gyp_shared_intermediate_dir)/web_contents_delegate_android/jni/WebContentsDelegateAndroid_jni.h \
+	components_web_contents_delegate_android_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_web_contents_delegate_android_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: web_contents_delegate_android_jni_headers
+web_contents_delegate_android_jni_headers: components_web_contents_delegate_android_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/components/webdata/DEPS b/components/webdata/DEPS
index eea3fed..2cd12ca 100644
--- a/components/webdata/DEPS
+++ b/components/webdata/DEPS
@@ -18,7 +18,7 @@
     "+chrome/browser/webdata/web_data_service_factory.h",
     "+chrome/browser/webdata/web_intents_table.h",
     "+components/autofill/core",
-    "+components/signin/core/webdata",
+    "+components/signin/core/browser/webdata",
     "+content/public/test",
   ],
 }
diff --git a/components/webdata/OWNERS b/components/webdata/OWNERS
index 59f8395..dbe16c9 100644
--- a/components/webdata/OWNERS
+++ b/components/webdata/OWNERS
@@ -1,4 +1,3 @@
-joi@chromium.org
 pkasting@chromium.org
 
 # For sqlite stuff:
diff --git a/components/webdata/common/web_data_service_test_util.h b/components/webdata/common/web_data_service_test_util.h
index 2e36a90..d2223d4 100644
--- a/components/webdata/common/web_data_service_test_util.h
+++ b/components/webdata/common/web_data_service_test_util.h
@@ -9,7 +9,7 @@
 #include "base/message_loop/message_loop.h"
 #include "chrome/browser/webdata/web_data_service.h"
 #include "chrome/browser/webdata/web_data_service_factory.h"
-#include "components/signin/core/webdata/token_web_data.h"
+#include "components/signin/core/browser/webdata/token_web_data.h"
 
 // Base class for mocks of WebDataService, that does nothing in
 // Shutdown().
diff --git a/components/webdata/common/web_database.cc b/components/webdata/common/web_database.cc
index 230eae1..0f7b6c4 100644
--- a/components/webdata/common/web_database.cc
+++ b/components/webdata/common/web_database.cc
@@ -101,13 +101,8 @@
   }
 
   // Initialize the tables.
-  for (TableMap::iterator it = tables_.begin();
-       it != tables_.end();
-       ++it) {
-    if (!it->second->Init(&db_, &meta_table_)) {
-      LOG(WARNING) << "Unable to initialize the web database.";
-      return sql::INIT_FAILURE;
-    }
+  for (TableMap::iterator it = tables_.begin(); it != tables_.end(); ++it) {
+    it->second->Init(&db_, &meta_table_);
   }
 
   // If the file on disk is an older database version, bring it up to date.
@@ -117,6 +112,17 @@
   if (migration_status != sql::INIT_OK)
     return migration_status;
 
+  // Create the desired SQL tables if they do not already exist.
+  // It's important that this happen *after* the migration code runs.
+  // Otherwise, the migration code would have to explicitly check for empty
+  // tables created in the new format, and skip the migration in that case.
+  for (TableMap::iterator it = tables_.begin(); it != tables_.end(); ++it) {
+    if (!it->second->CreateTablesIfNecessary()) {
+      LOG(WARNING) << "Unable to initialize the web database.";
+      return sql::INIT_FAILURE;
+    }
+  }
+
   return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE;
 }
 
@@ -140,8 +146,8 @@
     // migrate. If we do encounter such a legacy database, we will need a
     // better solution to handle it (i.e., pop up a dialog to tell the user,
     // erase all their prefs and start over, etc.).
-    LOG(WARNING) << "Web database version " << current_version <<
-        " is too old to handle.";
+    LOG(WARNING) << "Web database version " << current_version
+                 << " is too old to handle.";
     NOTREACHED();
     return sql::INIT_FAILURE;
   }
@@ -150,9 +156,7 @@
        next_version <= kCurrentVersionNumber;
        ++next_version) {
     // Give each table a chance to migrate to this version.
-    for (TableMap::iterator it = tables_.begin();
-         it != tables_.end();
-         ++it) {
+    for (TableMap::iterator it = tables_.begin(); it != tables_.end(); ++it) {
       // Any of the tables may set this to true, but by default it is false.
       bool update_compatible_version = false;
       if (!it->second->MigrateToVersion(next_version,
diff --git a/components/webdata/common/web_database_migration_unittest.cc b/components/webdata/common/web_database_migration_unittest.cc
index a72140c..0d0c487 100644
--- a/components/webdata/common/web_database_migration_unittest.cc
+++ b/components/webdata/common/web_database_migration_unittest.cc
@@ -26,7 +26,7 @@
 #include "components/autofill/core/browser/webdata/autofill_change.h"
 #include "components/autofill/core/browser/webdata/autofill_entry.h"
 #include "components/autofill/core/browser/webdata/autofill_table.h"
-#include "components/signin/core/webdata/token_service_table.h"
+#include "components/signin/core/browser/webdata/token_service_table.h"
 #include "components/webdata/common/web_database.h"
 #include "sql/statement.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -292,6 +292,40 @@
   }
 }
 
+// Tests that absent Autofill tables do not create any problems when migrating
+// from a DB written by the earliest publicly released version of Chrome.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion20ToCurrent) {
+  ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_20.sql")));
+
+  // Verify pre-conditions.
+  {
+    sql::Connection connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+
+    EXPECT_FALSE(connection.DoesTableExist("autofill"));
+    EXPECT_FALSE(connection.DoesTableExist("autofill_profiles"));
+    EXPECT_FALSE(connection.DoesTableExist("credit_cards"));
+  }
+
+  DoMigration();
+
+  // Verify post-conditions.  These are expectations for current version of the
+  // database.
+  {
+    sql::Connection connection;
+    ASSERT_TRUE(connection.Open(GetDatabasePath()));
+
+    // Check version.
+    EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+    // Mostly this test just verifies that no SQL errors occur during migration;
+    // but might as well verify that the tables were created as well.
+    EXPECT_TRUE(connection.DoesTableExist("autofill"));
+    EXPECT_TRUE(connection.DoesTableExist("autofill_profiles"));
+    EXPECT_TRUE(connection.DoesTableExist("credit_cards"));
+  }
+}
+
 // Tests that rows with empty values get removed from the autofill tables.
 TEST_F(WebDatabaseMigrationTest, MigrateVersion21ToCurrent) {
   ASSERT_NO_FATAL_FAILURE(LoadDatabase(FILE_PATH_LITERAL("version_21.sql")));
diff --git a/components/webdata/common/web_database_table.cc b/components/webdata/common/web_database_table.cc
index 57b5b96..28b0e1c 100644
--- a/components/webdata/common/web_database_table.cc
+++ b/components/webdata/common/web_database_table.cc
@@ -4,14 +4,10 @@
 
 #include "components/webdata/common/web_database_table.h"
 
-WebDatabaseTable::WebDatabaseTable() : db_(NULL), meta_table_(NULL) {
-}
+WebDatabaseTable::WebDatabaseTable() : db_(NULL), meta_table_(NULL) {}
+WebDatabaseTable::~WebDatabaseTable() {}
 
-WebDatabaseTable::~WebDatabaseTable() {
-}
-
-bool WebDatabaseTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
+void WebDatabaseTable::Init(sql::Connection* db, sql::MetaTable* meta_table) {
   db_ = db;
   meta_table_ = meta_table;
-  return true;
 }
diff --git a/components/webdata/common/web_database_table.h b/components/webdata/common/web_database_table.h
index b920ff6..d931c87 100644
--- a/components/webdata/common/web_database_table.h
+++ b/components/webdata/common/web_database_table.h
@@ -29,11 +29,12 @@
   // Retrieves the TypeKey for the concrete subtype.
   virtual TypeKey GetTypeKey() const = 0;
 
-  // Attempts to initialize the table and returns true if successful.
-  //
-  // The base class stores the members passed and always return true;
-  // subclasses may perform other initialization as needed.
-  virtual bool Init(sql::Connection* db, sql::MetaTable* meta_table);
+  // Stores the passed members as instance variables.
+  void Init(sql::Connection* db, sql::MetaTable* meta_table);
+
+  // Create all of the expected SQL tables if they do not already exist.
+  // Returns true on success, false on failure.
+  virtual bool CreateTablesIfNecessary() = 0;
 
   // In order to encourage developers to think about sync when adding or
   // or altering new tables, this method must be implemented. Please get in
diff --git a/components/webdata_common.target.darwin-arm.mk b/components/webdata_common.target.darwin-arm.mk
index 03b660a..d3d3545 100644
--- a/components/webdata_common.target.darwin-arm.mk
+++ b/components/webdata_common.target.darwin-arm.mk
@@ -86,6 +86,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/webdata_common.target.darwin-mips.mk b/components/webdata_common.target.darwin-mips.mk
index be0b547..d15c6c4 100644
--- a/components/webdata_common.target.darwin-mips.mk
+++ b/components/webdata_common.target.darwin-mips.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/webdata_common.target.darwin-x86.mk b/components/webdata_common.target.darwin-x86.mk
index 707ac63..acd71d9 100644
--- a/components/webdata_common.target.darwin-x86.mk
+++ b/components/webdata_common.target.darwin-x86.mk
@@ -87,6 +87,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -180,6 +181,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/webdata_common.target.darwin-x86_64.mk b/components/webdata_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..8a9520e
--- /dev/null
+++ b/components/webdata_common.target.darwin-x86_64.mk
@@ -0,0 +1,285 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_webdata_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/webdata/common/web_database.cc \
+	components/webdata/common/web_database_service.cc \
+	components/webdata/common/web_database_table.cc \
+	components/webdata/common/web_data_request_manager.cc \
+	components/webdata/common/web_data_service_backend.cc \
+	components/webdata/common/web_data_service_base.cc \
+	components/webdata/common/webdata_constants.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBDATA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBDATA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_webdata_common_gyp
+
+# Alias gyp target name.
+.PHONY: webdata_common
+webdata_common: components_webdata_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/webdata_common.target.linux-arm.mk b/components/webdata_common.target.linux-arm.mk
index 03b660a..d3d3545 100644
--- a/components/webdata_common.target.linux-arm.mk
+++ b/components/webdata_common.target.linux-arm.mk
@@ -86,6 +86,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/webdata_common.target.linux-mips.mk b/components/webdata_common.target.linux-mips.mk
index be0b547..d15c6c4 100644
--- a/components/webdata_common.target.linux-mips.mk
+++ b/components/webdata_common.target.linux-mips.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/webdata_common.target.linux-x86.mk b/components/webdata_common.target.linux-x86.mk
index 707ac63..acd71d9 100644
--- a/components/webdata_common.target.linux-x86.mk
+++ b/components/webdata_common.target.linux-x86.mk
@@ -87,6 +87,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -180,6 +181,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBDATA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/components/webdata_common.target.linux-x86_64.mk b/components/webdata_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..8a9520e
--- /dev/null
+++ b/components/webdata_common.target.linux-x86_64.mk
@@ -0,0 +1,285 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := components_webdata_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	components/webdata/common/web_database.cc \
+	components/webdata/common/web_database_service.cc \
+	components/webdata/common/web_database_table.cc \
+	components/webdata/common/web_data_request_manager.cc \
+	components/webdata/common/web_data_service_backend.cc \
+	components/webdata/common/web_data_service_base.cc \
+	components/webdata/common/webdata_constants.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBDATA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBDATA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: components_webdata_common_gyp
+
+# Alias gyp target name.
+.PHONY: webdata_common
+webdata_common: components_webdata_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/components/wifi/wifi_service_win.cc b/components/wifi/wifi_service_win.cc
index 1280b49..8b69e1a 100644
--- a/components/wifi/wifi_service_win.cc
+++ b/components/wifi/wifi_service_win.cc
@@ -35,9 +35,14 @@
 const wchar_t kNwCategoryWizardDeleteRegValue[] = L"ShowDelete";
 const wchar_t kWlanApiDll[] = L"wlanapi.dll";
 
+// Created Profile Dictionary keys
+const char kProfileXmlKey[] = "xml";
+const char kProfileSharedKey[] = "shared";
+
 // WlanApi function names
 const char kWlanConnect[] = "WlanConnect";
 const char kWlanCloseHandle[] = "WlanCloseHandle";
+const char kWlanDeleteProfile[] = "WlanDeleteProfile";
 const char kWlanDisconnect[] = "WlanDisconnect";
 const char kWlanEnumInterfaces[] = "WlanEnumInterfaces";
 const char kWlanFreeMemory[] = "WlanFreeMemory";
@@ -62,6 +67,12 @@
     HANDLE hClientHandle,
     PVOID pReserved);
 
+typedef DWORD (WINAPI* WlanDeleteProfileFunction)(
+    HANDLE hClientHandle,
+    const GUID *pInterfaceGuid,
+    LPCWSTR strProfileName,
+    PVOID pReserved);
+
 typedef DWORD (WINAPI* WlanDisconnectFunction)(
     HANDLE hClientHandle,
     CONST GUID *pInterfaceGuid,
@@ -222,6 +233,13 @@
   virtual void RequestConnectedNetworkUpdate() OVERRIDE {}
 
  private:
+  typedef int32 EncryptionType;
+  enum EncryptionTypeEnum {
+    kEncryptionTypeAny = 0,
+    kEncryptionTypeAES = 1,
+    kEncryptionTypeTKIP = 2
+  };
+
   // Static callback for Windows WLAN_NOTIFICATION. Calls OnWlanNotification
   // on WiFiServiceImpl passed back as |context|.
   static void __stdcall OnWlanNotificationCallback(
@@ -313,8 +331,13 @@
   // Deduce |onc::wifi| security from |alg|.
   std::string SecurityFromDot11AuthAlg(DOT11_AUTH_ALGORITHM alg) const;
 
+  // Convert |EncryptionType| into WPA(2) encryption type string.
+  std::string WpaEncryptionFromEncryptionType(
+      EncryptionType encryption_type) const;
+
   // Deduce WLANProfile |authEncryption| values from |onc::wifi| security.
   bool AuthEncryptionFromSecurity(const std::string& security,
+                                  EncryptionType encryption_type,
                                   std::string* authentication,
                                   std::string* encryption,
                                   std::string* key_type) const;
@@ -358,8 +381,11 @@
   // Normalizes |frequency_in_mhz| into one of |Frequency| values.
   Frequency GetNormalizedFrequency(int frequency_in_mhz) const;
 
-  // Create |profile_xml| based on |network_properties|.
+  // Create |profile_xml| based on |network_properties|. If |encryption_type|
+  // is |kEncryptionTypeAny| applies the type most suitable for parameters in
+  // |network_properties|.
   bool CreateProfile(const NetworkProperties& network_properties,
+                     EncryptionType encryption_type,
                      std::string* profile_xml);
 
   // Save temporary wireless profile for |network_guid|.
@@ -372,9 +398,16 @@
                    bool get_plaintext_key,
                    std::string* profile_xml);
 
+  // Set |profile_xml| to current user or all users depending on |shared| flag.
+  // If |overwrite| is false, then returns an error if profile exists.
+  DWORD SetProfile(bool shared, const std::string& profile_xml, bool overwrite);
+
   // Return true if there is previously stored profile xml for |network_guid|.
   bool HaveProfile(const std::string& network_guid);
 
+  // Delete profile that was created, but failed to connect.
+  DWORD DeleteCreatedProfile(const std::string& network_guid);
+
   // Notify |network_list_changed_observer_| that list of visible networks has
   // changed to |networks|.
   void NotifyNetworkListChanged(const NetworkList& networks);
@@ -390,6 +423,7 @@
   // WlanApi function pointers
   WlanConnectFunction WlanConnect_function_;
   WlanCloseHandleFunction WlanCloseHandle_function_;
+  WlanDeleteProfileFunction WlanDeleteProfile_function_;
   WlanDisconnectFunction WlanDisconnect_function_;
   WlanEnumInterfacesFunction WlanEnumInterfaces_function_;
   WlanFreeMemoryFunction WlanFreeMemory_function_;
@@ -415,6 +449,11 @@
   base::DictionaryValue connect_properties_;
   // Preserved WLAN profile xml.
   std::map<std::string, std::string> saved_profiles_xml_;
+  // Created WLAN Profiles, indexed by |network_guid|. Contains xml with TKIP
+  // encryption type saved by |CreateNetwork| if applicable. Profile has to be
+  // deleted if connection fails. Implicitly created profiles have to be deleted
+  // if connection succeeds. Persist only in memory.
+  base::DictionaryValue created_profiles_;
   // Observer to get notified when network(s) have changed (e.g. connect).
   NetworkGuidListCallback networks_changed_observer_;
   // Observer to get notified when network list has changed (scan complete).
@@ -438,6 +477,7 @@
     : wlan_api_library_(NULL),
       WlanConnect_function_(NULL),
       WlanCloseHandle_function_(NULL),
+      WlanDeleteProfile_function_(NULL),
       WlanDisconnect_function_(NULL),
       WlanEnumInterfaces_function_(NULL),
       WlanFreeMemory_function_(NULL),
@@ -536,28 +576,36 @@
 
   network_properties.guid = network_properties.ssid;
   std::string profile_xml;
-  if (!CreateProfile(network_properties, &profile_xml)) {
+  if (!CreateProfile(network_properties, kEncryptionTypeAny, &profile_xml)) {
     CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error);
     return;
   }
 
-  base::string16 profile_xml16(base::UTF8ToUTF16(profile_xml));
-  DWORD reason_code = 0u;
-
-  error_code = WlanSetProfile_function_(client_,
-                                        &interface_guid_,
-                                        shared ? 0 : WLAN_PROFILE_USER,
-                                        profile_xml16.c_str(),
-                                        NULL,
-                                        FALSE,
-                                        NULL,
-                                        &reason_code);
+  error_code = SetProfile(shared, profile_xml, false);
   if (CheckError(error_code, kWiFiServiceError, error)) {
     DVLOG(0) << profile_xml;
-    DVLOG(0) << "SetProfile Reason Code:" << reason_code;
     return;
   }
 
+  // WAP and WAP2 networks could use either AES or TKIP encryption type.
+  // Preserve alternative profile to use in case if connection with default
+  // encryption type fails.
+  std::string tkip_profile_xml;
+  if (!CreateProfile(network_properties,
+                     kEncryptionTypeTKIP,
+                     &tkip_profile_xml)) {
+    CheckError(ERROR_INVALID_DATA, kWiFiServiceError, error);
+    return;
+  }
+
+  if (tkip_profile_xml != profile_xml) {
+    scoped_ptr<base::DictionaryValue> tkip_profile(new base::DictionaryValue());
+    tkip_profile->SetString(kProfileXmlKey, tkip_profile_xml);
+    tkip_profile->SetBoolean(kProfileSharedKey, shared);
+    created_profiles_.SetWithoutPathExpansion(network_properties.guid,
+                                              tkip_profile.release());
+  }
+
   *network_guid = network_properties.guid;
 }
 
@@ -779,11 +827,49 @@
 
 void WiFiServiceImpl::WaitForNetworkConnect(const std::string& network_guid,
                                             int attempt) {
-  // If network didn't get connected in |kMaxAttempts|, then restore automatic
-  // network change notifications and stop waiting.
+  // If network didn't get connected in |kMaxAttempts|, then try to connect
+  // using different profile if it was created recently.
   if (attempt > kMaxAttempts) {
-    DLOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
-                << network_guid;
+    LOG(ERROR) << kMaxAttempts << " attempts exceeded waiting for connect to "
+               << network_guid;
+
+    base::DictionaryValue* created_profile = NULL;
+    // Check, whether this connection is using newly created profile.
+    if (created_profiles_.GetDictionaryWithoutPathExpansion(
+        network_guid, &created_profile)) {
+      std::string tkip_profile_xml;
+      bool shared = false;
+      // Check, if this connection there is alternative TKIP profile xml that
+      // should be tried. If there is, then set it up and try to connect again.
+      if (created_profile->GetString(kProfileXmlKey, &tkip_profile_xml) &&
+          created_profile->GetBoolean(kProfileSharedKey, &shared)) {
+        // Remove TKIP profile xml, so it will not be tried again.
+        created_profile->Remove(kProfileXmlKey, NULL);
+        created_profile->Remove(kProfileSharedKey, NULL);
+        DWORD error_code = SetProfile(shared, tkip_profile_xml, true);
+        if (error_code == ERROR_SUCCESS) {
+          // Try to connect with new profile.
+          error_code = Connect(network_guid,
+                               GetFrequencyToConnect(network_guid));
+          if (error_code == ERROR_SUCCESS) {
+            // Start waiting again.
+            WaitForNetworkConnect(network_guid, 0);
+            return;
+          } else {
+            LOG(ERROR) << "Failed to set created profile for " << network_guid
+                       << " error=" << error_code;
+          }
+        }
+      } else {
+        // Connection has failed, so delete bad created profile.
+        DWORD error_code = DeleteCreatedProfile(network_guid);
+        if (error_code != ERROR_SUCCESS) {
+          LOG(ERROR) << "Failed to delete created profile for " << network_guid
+                     << " error=" << error_code;
+        }
+      }
+    }
+    // Restore automatic network change notifications and stop waiting.
     enable_notify_network_changed_ = true;
     RestoreNwCategoryWizard();
     return;
@@ -796,6 +882,8 @@
     // e.g. after Chromecast device reset. Reset DHCP on wireless network to
     // work around this issue.
     error = ResetDHCP();
+    // There is no need to keep created profile as network is connected.
+    created_profiles_.RemoveWithoutPathExpansion(network_guid, NULL);
     // Restore previously suppressed notifications.
     enable_notify_network_changed_ = true;
     RestoreNwCategoryWizard();
@@ -877,6 +965,9 @@
   WlanCloseHandle_function_ =
       reinterpret_cast<WlanCloseHandleFunction>(
           ::GetProcAddress(wlan_api_library_, kWlanCloseHandle));
+  WlanDeleteProfile_function_ =
+      reinterpret_cast<WlanDeleteProfileFunction>(
+          ::GetProcAddress(wlan_api_library_, kWlanDeleteProfile));
   WlanDisconnect_function_ =
       reinterpret_cast<WlanDisconnectFunction>(
           ::GetProcAddress(wlan_api_library_, kWlanDisconnect));
@@ -916,6 +1007,7 @@
 
   if (!WlanConnect_function_ ||
       !WlanCloseHandle_function_ ||
+      !WlanDeleteProfile_function_ ||
       !WlanDisconnect_function_ ||
       !WlanEnumInterfaces_function_ ||
       !WlanFreeMemory_function_ ||
@@ -1088,6 +1180,7 @@
   if (wlan_api_library_ != NULL) {
     WlanConnect_function_ = NULL;
     WlanCloseHandle_function_ = NULL;
+    WlanDeleteProfile_function_ = NULL;
     WlanDisconnect_function_ = NULL;
     WlanEnumInterfaces_function_ = NULL;
     WlanFreeMemory_function_ = NULL;
@@ -1467,9 +1560,6 @@
       error = WlanConnect_function_(
           client_, &interface_guid_, &wlan_params, NULL);
     } else {
-      // TODO(mef): wlan_connection_mode_discovery_unsecure is not available on
-      // XP. If XP support is needed, then temporary profile will have to be
-      // created.
       WLAN_CONNECTION_PARAMETERS wlan_params = {
           wlan_connection_mode_discovery_unsecure,
           NULL,
@@ -1552,14 +1642,59 @@
   return error;
 }
 
+DWORD WiFiServiceImpl::SetProfile(bool shared,
+                                  const std::string& profile_xml,
+                                  bool overwrite) {
+  DWORD error_code = ERROR_SUCCESS;
+
+  base::string16 profile_xml16(base::UTF8ToUTF16(profile_xml));
+  DWORD reason_code = 0u;
+
+  error_code = WlanSetProfile_function_(client_,
+                                        &interface_guid_,
+                                        shared ? 0 : WLAN_PROFILE_USER,
+                                        profile_xml16.c_str(),
+                                        NULL,
+                                        overwrite,
+                                        NULL,
+                                        &reason_code);
+  return error_code;
+}
+
 bool WiFiServiceImpl::HaveProfile(const std::string& network_guid) {
   DWORD error = ERROR_SUCCESS;
   std::string profile_xml;
   return GetProfile(network_guid, false, &profile_xml) == ERROR_SUCCESS;
 }
 
+
+DWORD WiFiServiceImpl::DeleteCreatedProfile(const std::string& network_guid) {
+  base::DictionaryValue* created_profile = NULL;
+  DWORD error_code = ERROR_SUCCESS;
+  // Check, whether this connection is using new created profile, and remove it.
+  if (created_profiles_.GetDictionaryWithoutPathExpansion(
+      network_guid, &created_profile)) {
+    // Connection has failed, so delete it.
+    base::string16 profile_name = ProfileNameFromGUID(network_guid);
+    error_code = WlanDeleteProfile_function_(client_,
+                                              &interface_guid_,
+                                              profile_name.c_str(),
+                                              NULL);
+    created_profiles_.RemoveWithoutPathExpansion(network_guid, NULL);
+  }
+  return error_code;
+}
+
+std::string WiFiServiceImpl::WpaEncryptionFromEncryptionType(
+    EncryptionType encryption_type) const {
+  if (encryption_type == kEncryptionTypeTKIP)
+    return kEncryptionTKIP;
+  return kEncryptionAES;
+}
+
 bool WiFiServiceImpl::AuthEncryptionFromSecurity(
     const std::string& security,
+    EncryptionType encryption_type,
     std::string* authentication,
     std::string* encryption,
     std::string* key_type) const {
@@ -1572,15 +1707,11 @@
     *key_type = kKeyTypeNetwork;
   } else if (security == onc::wifi::kWPA_PSK) {
     *authentication = kAuthenticationWpaPsk;
-    // TODO(mef): WAP |encryption| could be either |AES| or |TKIP|. It has to be
-    // determined and adjusted properly during |Connect|.
-    *encryption = kEncryptionAES;
+    *encryption = WpaEncryptionFromEncryptionType(encryption_type);
     *key_type = kKeyTypePassphrase;
   } else if (security == onc::wifi::kWPA2_PSK) {
     *authentication = kAuthenticationWpa2Psk;
-    // TODO(mef): WAP |encryption| could be either |AES| or |TKIP|. It has to be
-    // determined and adjusted properly during |Connect|.
-    *encryption = kEncryptionAES;
+    *encryption = WpaEncryptionFromEncryptionType(encryption_type);
     *key_type = kKeyTypePassphrase;
   } else {
     return false;
@@ -1590,12 +1721,14 @@
 
 bool WiFiServiceImpl::CreateProfile(
     const NetworkProperties& network_properties,
+    EncryptionType encryption_type,
     std::string* profile_xml) {
   // Get authentication and encryption values from security.
   std::string authentication;
   std::string encryption;
   std::string key_type;
   bool valid = AuthEncryptionFromSecurity(network_properties.security,
+                                          encryption_type,
                                           &authentication,
                                           &encryption,
                                           &key_type);
diff --git a/content/DEPS b/content/DEPS
index 01732b9..56a4ab6 100644
--- a/content/DEPS
+++ b/content/DEPS
@@ -38,6 +38,7 @@
   "+mojo/public",
   "+mojo/bindings/js",
   "+mojo/embedder",
+  "+mojo/service_manager",
   "+net",
   "+ppapi",
   "+printing",
diff --git a/content/app/content_main_runner.cc b/content/app/content_main_runner.cc
index adf27a9..957d604 100644
--- a/content/app/content_main_runner.cc
+++ b/content/app/content_main_runner.cc
@@ -101,6 +101,10 @@
 }
 #endif
 
+#if defined(USE_MOJO)
+#include "content/app/mojo/mojo_init.h"
+#endif
+
 namespace content {
 extern int GpuMain(const content::MainFunctionParams&);
 #if defined(ENABLE_PLUGINS)
@@ -529,7 +533,7 @@
   virtual int Initialize(const ContentMainParams& params) OVERRIDE {
     ui_task_ = params.ui_task;
 
-#if defined(OS_WIN)   
+#if defined(OS_WIN)
     RegisterInvalidParamHandler();
     _Module.Init(NULL, static_cast<HINSTANCE>(params.instance));
 
@@ -661,6 +665,11 @@
     std::string process_type =
         command_line.GetSwitchValueASCII(switches::kProcessType);
 
+#if defined(USE_MOJO)
+    // Initialize mojo here so that services can be registered.
+    InitializeMojo();
+#endif
+
     if (!GetContentClient())
       SetContentClient(&empty_content_client_);
     ContentClientInitializer::Set(process_type, delegate_);
diff --git a/content/app/mojo/mojo_browsertest.cc b/content/app/mojo/mojo_browsertest.cc
new file mode 100644
index 0000000..f578b57
--- /dev/null
+++ b/content/app/mojo/mojo_browsertest.cc
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/test/content_browser_test.h"
+#include "mojo/service_manager/service_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class MojoTest : public ContentBrowserTest {
+ public:
+  MojoTest() {}
+
+ protected:
+  bool HasCreatedInstance() {
+    return mojo::ServiceManager::TestAPI::HasCreatedInstance();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MojoTest);
+};
+
+// Placeholder test to confirm we are initializing Mojo.
+IN_PROC_BROWSER_TEST_F(MojoTest, Init) {
+  EXPECT_TRUE(HasCreatedInstance());
+}
+
+}  // namespace content
diff --git a/content/app/mojo/mojo_init.cc b/content/app/mojo/mojo_init.cc
new file mode 100644
index 0000000..4552b66
--- /dev/null
+++ b/content/app/mojo/mojo_init.cc
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/app/mojo/mojo_init.h"
+
+#include "base/lazy_instance.h"
+#include "mojo/embedder/embedder.h"
+#include "mojo/service_manager/service_manager.h"
+
+namespace content {
+
+namespace {
+
+struct Initializer {
+  Initializer() {
+    // TODO(davemoore): Configuration goes here. For now just create the shared
+    // instance of the ServiceManager.
+    mojo::ServiceManager::GetInstance();
+    mojo::embedder::Init();
+  }
+};
+
+static base::LazyInstance<Initializer>::Leaky initializer =
+    LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace
+
+// Initializes mojo. Use a lazy instance to ensure we only do this once.
+void InitializeMojo() {
+  initializer.Get();
+}
+
+}  // namespace content
diff --git a/content/app/mojo/mojo_init.h b/content/app/mojo/mojo_init.h
new file mode 100644
index 0000000..9f5ad7d
--- /dev/null
+++ b/content/app/mojo/mojo_init.h
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_APP_MOJO_MOJO_INIT_H_
+#define CONTENT_APP_MOJO_MOJO_INIT_H_
+
+namespace content {
+
+// Perform any necessary Mojo initialization.
+void InitializeMojo();
+
+}  // namespace content
+
+#endif  // CONTENT_COMMON_MOJO_MOJO_INIT_H_
diff --git a/content/browser/DEPS b/content/browser/DEPS
index 6f05527..9a4957d 100644
--- a/content/browser/DEPS
+++ b/content/browser/DEPS
@@ -1,7 +1,6 @@
 include_rules = [
   "+content/port/browser",
   "+content/public/browser",
-  "+content/child/webkitplatformsupport_impl.h",  # For in-process webkit
   "+media/audio",  # For audio input for speech input feature.
   "+media/base",  # For Android JNI registration.
   "+media/midi",  # For Web MIDI API
@@ -19,6 +18,7 @@
   "+third_party/iaccessible2",
   "+third_party/isimpledom",
   "+third_party/khronos",   # For enum definitions only
+  "+third_party/power_gadget",
   "+third_party/speex",
   "+third_party/re2",
 
diff --git a/content/browser/accessibility/accessibility_mode_browsertest.cc b/content/browser/accessibility/accessibility_mode_browsertest.cc
new file mode 100644
index 0000000..6a0ae02
--- /dev/null
+++ b/content/browser/accessibility/accessibility_mode_browsertest.cc
@@ -0,0 +1,103 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_view_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/port/browser/render_widget_host_view_port.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+const char kMinimalPageDataURL[] =
+    "data:text/html,<html><head></head><body>Hello, world</body></html>";
+
+class AccessibilityModeTest : public ContentBrowserTest {
+ protected:
+  content::WebContents* web_contents() {
+    return shell()->web_contents();
+  }
+
+  content::RenderWidgetHostImpl* rwhi() {
+    content::RenderWidgetHost* rwh =
+        web_contents()->GetRenderWidgetHostView()->GetRenderWidgetHost();
+    return content::RenderWidgetHostImpl::From(rwh);
+  }
+
+  content::RenderWidgetHostViewPort* host_view() {
+    return RenderWidgetHostViewPort::FromRWHV(
+        shell()->web_contents()->GetRenderWidgetHostView());
+  }
+
+  void ExpectBrowserAccessibilityManager(bool expect_bam,
+                                         std::string message = "") {
+    if (expect_bam) {
+      EXPECT_NE((BrowserAccessibilityManager*)NULL,
+                host_view()->GetBrowserAccessibilityManager()) << message;
+    } else {
+      EXPECT_EQ((BrowserAccessibilityManager*)NULL,
+                host_view()->GetBrowserAccessibilityManager()) << message;
+    }
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeOff) {
+  NavigateToURL(shell(), GURL(kMinimalPageDataURL));
+
+  EXPECT_EQ(AccessibilityModeOff, rwhi()->accessibility_mode());
+  ExpectBrowserAccessibilityManager(false);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeComplete) {
+  NavigateToURL(shell(), GURL(kMinimalPageDataURL));
+  ASSERT_EQ(AccessibilityModeOff, rwhi()->accessibility_mode());
+
+  AccessibilityNotificationWaiter waiter(shell());
+  rwhi()->AddAccessibilityMode(AccessibilityModeComplete);
+  EXPECT_EQ(AccessibilityModeComplete, rwhi()->accessibility_mode());
+  waiter.WaitForNotification();
+  ExpectBrowserAccessibilityManager(true);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AccessibilityModeTreeOnly) {
+  NavigateToURL(shell(), GURL(kMinimalPageDataURL));
+  ASSERT_EQ(AccessibilityModeOff, rwhi()->accessibility_mode());
+
+  AccessibilityNotificationWaiter waiter(shell());
+  rwhi()->AddAccessibilityMode(AccessibilityModeTreeOnly);
+  EXPECT_EQ(AccessibilityModeTreeOnly, rwhi()->accessibility_mode());
+  waiter.WaitForNotification();
+  // No BrowserAccessibilityManager expected for AccessibilityModeTreeOnly
+  ExpectBrowserAccessibilityManager(false);
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityModeTest, AddingModes) {
+  NavigateToURL(shell(), GURL(kMinimalPageDataURL));
+
+  AccessibilityNotificationWaiter waiter(shell());
+  rwhi()->AddAccessibilityMode(AccessibilityModeTreeOnly);
+  EXPECT_EQ(AccessibilityModeTreeOnly, rwhi()->accessibility_mode());
+  waiter.WaitForNotification();
+  ExpectBrowserAccessibilityManager(false,
+                                    "Should be no BrowserAccessibilityManager "
+                                    "for AccessibilityModeTreeOnly");
+
+  AccessibilityNotificationWaiter waiter2(shell());
+  rwhi()->AddAccessibilityMode(AccessibilityModeComplete);
+  EXPECT_EQ(AccessibilityModeComplete, rwhi()->accessibility_mode());
+  waiter2.WaitForNotification();
+  ExpectBrowserAccessibilityManager(true,
+                                    "Should be a BrowserAccessibilityManager "
+                                    "for AccessibilityModeComplete");
+}
+
+}  // namespace content
diff --git a/content/browser/accessibility/accessibility_mode_helper.cc b/content/browser/accessibility/accessibility_mode_helper.cc
index 21eccaf..7988595 100644
--- a/content/browser/accessibility/accessibility_mode_helper.cc
+++ b/content/browser/accessibility/accessibility_mode_helper.cc
@@ -20,6 +20,7 @@
   case AccessibilityModeOff:
   case AccessibilityModeComplete:
   case AccessibilityModeEditableTextOnly:
+  case AccessibilityModeTreeOnly:
     return mode;
   }
   DCHECK(false) << "Could not convert to AccessibilityMode: " << int_mode;
diff --git a/content/browser/accessibility/accessibility_mode_helper_unittest.cc b/content/browser/accessibility/accessibility_mode_helper_unittest.cc
index 5e23643..f42a192 100644
--- a/content/browser/accessibility/accessibility_mode_helper_unittest.cc
+++ b/content/browser/accessibility/accessibility_mode_helper_unittest.cc
@@ -30,6 +30,10 @@
       AccessibilityModeComplete,
       AddAccessibilityModeTo(AccessibilityModeEditableTextOnly,
                              AccessibilityModeComplete));
+  EXPECT_EQ(
+      AccessibilityModeComplete,
+      AddAccessibilityModeTo(AccessibilityModeEditableTextOnly,
+                             AccessibilityModeTreeOnly));
 }
 
 }  // namespace content
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 230cd8d..f9321ee 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -83,6 +83,49 @@
   return 0 == strcmp([value objCType], @encode(NSRange));
 }
 
+scoped_ptr<base::Value> PopulateObject(id value);
+
+scoped_ptr<base::ListValue> PopulateArray(NSArray* array) {
+  scoped_ptr<base::ListValue> list(new base::ListValue);
+  for (NSUInteger i = 0; i < [array count]; i++)
+    list->Append(PopulateObject([array objectAtIndex:i]).release());
+  return list.Pass();
+}
+
+scoped_ptr<base::StringValue> StringForBrowserAccessibility(
+    BrowserAccessibilityCocoa* obj) {
+  NSString* description = [obj role];
+  id value = [obj value];
+  id roleDescription = [obj roleDescription];
+  if (value != nil && ![value isEqualToString:@""]) {
+    description = [NSString stringWithFormat:@"%@ %@", description, value];
+  } else if ([description isEqualToString:NSAccessibilityGroupRole] &&
+           roleDescription != nil &&
+           ![roleDescription isEqualToString:@""]) {
+    description = [NSString stringWithFormat:@"%@ %@",
+                            description, roleDescription];
+  }
+  return scoped_ptr<base::StringValue>(
+      new base::StringValue(SysNSStringToUTF16(description))).Pass();
+}
+
+scoped_ptr<base::Value> PopulateObject(id value) {
+  if ([value isKindOfClass:[NSArray class]])
+    return scoped_ptr<base::Value>(PopulateArray((NSArray*) value));
+  if (IsRangeValue(value))
+    return scoped_ptr<base::Value>(PopulateRange([value rangeValue]));
+  if ([value isKindOfClass:[BrowserAccessibilityCocoa class]]) {
+    std::string str;
+    StringForBrowserAccessibility(value)->GetAsString(&str);
+    return scoped_ptr<base::Value>(StringForBrowserAccessibility(
+        (BrowserAccessibilityCocoa*) value));
+  }
+
+  return scoped_ptr<base::Value>(
+      new base::StringValue(
+          SysNSStringToUTF16([NSString stringWithFormat:@"%@", value]))).Pass();
+}
+
 NSArray* BuildAllAttributesArray() {
   NSArray* array = [NSArray arrayWithObjects:
       NSAccessibilityRoleDescriptionAttribute,
@@ -111,9 +154,11 @@
       NSAccessibilityOrientationAttribute,
       @"AXRequired",
       NSAccessibilityRowIndexRangeAttribute,
+      NSAccessibilityTitleUIElementAttribute,
       NSAccessibilityURLAttribute,
       NSAccessibilityVisibleCharacterRangeAttribute,
       @"AXVisited",
+      @"AXLinkedUIElements",
       nil];
   return [array retain];
 }
@@ -143,18 +188,13 @@
 
   CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray()));
   for (NSString* requestedAttribute in all_attributes) {
-    if (![supportedAttributes containsObject:requestedAttribute]) {
+    if (![supportedAttributes containsObject:requestedAttribute])
       continue;
-    }
     id value = [cocoa_node accessibilityAttributeValue:requestedAttribute];
-    if (IsRangeValue(value)) {
+    if (value != nil) {
       dict->Set(
           SysNSStringToUTF8(requestedAttribute),
-          PopulateRange([value rangeValue]).release());
-    } else if (value != nil) {
-      dict->SetString(
-          SysNSStringToUTF8(requestedAttribute),
-          SysNSStringToUTF16([NSString stringWithFormat:@"%@", value]));
+          PopulateObject(value).release());
     }
   }
   dict->Set(kPositionDictAttr, PopulatePosition(node).release());
@@ -184,10 +224,18 @@
   CR_DEFINE_STATIC_LOCAL(NSArray*, all_attributes, (BuildAllAttributesArray()));
   for (NSString* requestedAttribute in all_attributes) {
     string requestedAttributeUTF8 = SysNSStringToUTF8(requestedAttribute);
-    const base::DictionaryValue* d_value;
-    if (dict.GetDictionary(requestedAttributeUTF8, &d_value)) {
+    if (dict.GetString(requestedAttributeUTF8, &s_value)) {
+      WriteAttribute([defaultAttributes containsObject:requestedAttribute],
+                     StringPrintf("%s='%s'",
+                                  requestedAttributeUTF8.c_str(),
+                                  s_value.c_str()),
+                     &line);
+      continue;
+    }
+    const base::Value* value;
+    if (dict.Get(requestedAttributeUTF8, &value)) {
       std::string json_value;
-      base::JSONWriter::Write(d_value, &json_value);
+      base::JSONWriter::Write(value, &json_value);
       WriteAttribute(
           [defaultAttributes containsObject:requestedAttribute],
           StringPrintf("%s=%s",
@@ -195,13 +243,6 @@
                        json_value.c_str()),
           &line);
     }
-    if (!dict.GetString(requestedAttributeUTF8, &s_value))
-      continue;
-    WriteAttribute([defaultAttributes containsObject:requestedAttribute],
-                   StringPrintf("%s='%s'",
-                                requestedAttributeUTF8.c_str(),
-                                s_value.c_str()),
-                   &line);
   }
   const base::DictionaryValue* d_value = NULL;
   if (dict.GetDictionary(kPositionDictAttr, &d_value)) {
diff --git a/content/browser/accessibility/accessibility_win_browsertest.cc b/content/browser/accessibility/accessibility_win_browsertest.cc
index 2fd8806..b380f96 100644
--- a/content/browser/accessibility/accessibility_win_browsertest.cc
+++ b/content/browser/accessibility/accessibility_win_browsertest.cc
@@ -17,10 +17,10 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/accessibility_browser_test_utils.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "third_party/iaccessible2/ia2_api_all.h"
 #include "third_party/isimpledom/ISimpleDOMNode.h"
 
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc
index ff57121..18a24b4 100644
--- a/content/browser/accessibility/browser_accessibility.cc
+++ b/content/browser/accessibility/browser_accessibility.cc
@@ -314,8 +314,15 @@
 
 BrowserAccessibility* BrowserAccessibility::BrowserAccessibilityForPoint(
     const gfx::Point& point) {
+  // The best result found that's a child of this object.
+  BrowserAccessibility* child_result = NULL;
+  // The best result that's an indirect descendant like grandchild, etc.
+  BrowserAccessibility* descendant_result = NULL;
+
   // Walk the children recursively looking for the BrowserAccessibility that
-  // most tightly encloses the specified point.
+  // most tightly encloses the specified point. Walk backwards so that in
+  // the absence of any other information, we assume the object that occurs
+  // later in the tree is on top of one that comes before it.
   for (int i = static_cast<int>(PlatformChildCount()) - 1; i >= 0; --i) {
     BrowserAccessibility* child = PlatformGetChild(i);
 
@@ -324,9 +331,29 @@
     if (child->role() == ui::AX_ROLE_COLUMN)
       continue;
 
-    if (child->GetGlobalBoundsRect().Contains(point))
-      return child->BrowserAccessibilityForPoint(point);
+    if (child->GetGlobalBoundsRect().Contains(point)) {
+      BrowserAccessibility* result = child->BrowserAccessibilityForPoint(point);
+      if (result == child && !child_result)
+        child_result = result;
+      if (result != child && !descendant_result)
+        descendant_result = result;
+    }
+
+    if (child_result && descendant_result)
+      break;
   }
+
+  // Explanation of logic: it's possible that this point overlaps more than
+  // one child of this object. If so, as a heuristic we prefer if the point
+  // overlaps a descendant of one of the two children and not the other.
+  // As an example, suppose you have two rows of buttons - the buttons don't
+  // overlap, but the rows do. Without this heuristic, we'd greedily only
+  // consider one of the containers.
+  if (descendant_result)
+    return descendant_result;
+  if (child_result)
+    return child_result;
+
   return this;
 }
 
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
index 66b7826..f1565eb 100644
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -256,6 +256,7 @@
     { NSAccessibilityHeaderAttribute, @"header" },
     { NSAccessibilityHelpAttribute, @"help" },
     { NSAccessibilityIndexAttribute, @"index" },
+    { NSAccessibilityLinkedUIElementsAttribute, @"linkedUIElements" },
     { NSAccessibilityMaxValueAttribute, @"maxValue" },
     { NSAccessibilityMinValueAttribute, @"minValue" },
     { NSAccessibilityNumberOfCharactersAttribute, @"numberOfCharacters" },
@@ -267,6 +268,7 @@
     { NSAccessibilityRowHeaderUIElementsAttribute, @"rowHeaders" },
     { NSAccessibilityRowIndexRangeAttribute, @"rowIndexRange" },
     { NSAccessibilityRowsAttribute, @"rows" },
+    // TODO(aboxhall): expose NSAccessibilityServesAsTitleForUIElementsAttribute
     { NSAccessibilitySizeAttribute, @"size" },
     { NSAccessibilitySubroleAttribute, @"subrole" },
     { NSAccessibilityTabsAttribute, @"tabs" },
@@ -578,6 +580,28 @@
   return invalid;
 }
 
+- (void)addLinkedUIElementsFromAttribute:(ui::AXIntListAttribute)attribute
+                                   addTo:(NSMutableArray*)outArray {
+  const std::vector<int32>& attributeValues =
+      browserAccessibility_->GetIntListAttribute(attribute);
+  for (size_t i = 0; i < attributeValues.size(); ++i) {
+    BrowserAccessibility* element =
+        browserAccessibility_->manager()->GetFromRendererID(attributeValues[i]);
+    if (element)
+      [outArray addObject:element->ToBrowserAccessibilityCocoa()];
+  }
+}
+
+- (NSArray*)linkedUIElements {
+  NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
+  [self addLinkedUIElementsFromAttribute:ui::AX_ATTR_OWNS_IDS addTo:ret];
+  [self addLinkedUIElementsFromAttribute:ui::AX_ATTR_CONTROLS_IDS addTo:ret];
+  [self addLinkedUIElementsFromAttribute:ui::AX_ATTR_FLOWTO_IDS addTo:ret];
+  if ([ret count] == 0)
+    return nil;
+  return ret;
+}
+
 - (NSNumber*)loaded {
   return [NSNumber numberWithBool:YES];
 }
@@ -851,6 +875,15 @@
     if (titleElement)
       return titleElement->ToBrowserAccessibilityCocoa();
   }
+  std::vector<int32> labelledby_ids =
+      browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS);
+  if (labelledby_ids.size() == 1) {
+    BrowserAccessibility* titleElement =
+        browserAccessibility_->manager()->GetFromRendererID(labelledby_ids[0]);
+    if (titleElement)
+      return titleElement->ToBrowserAccessibilityCocoa();
+  }
+
   return nil;
 }
 
@@ -1242,6 +1275,7 @@
       NSAccessibilityEnabledAttribute,
       NSAccessibilityFocusedAttribute,
       NSAccessibilityHelpAttribute,
+      NSAccessibilityLinkedUIElementsAttribute,
       NSAccessibilityParentAttribute,
       NSAccessibilityPositionAttribute,
       NSAccessibilityRoleAttribute,
@@ -1356,12 +1390,16 @@
   }
 
   // Title UI Element.
-  if (browserAccessibility_->HasIntAttribute(
-          ui::AX_ATTR_TITLE_UI_ELEMENT)) {
+  if (browserAccessibility_->HasIntAttribute(ui::AX_ATTR_TITLE_UI_ELEMENT) ||
+      (browserAccessibility_->HasIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS) &&
+       browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS)
+                            .size() == 1)) {
     [ret addObjectsFromArray:[NSArray arrayWithObjects:
          NSAccessibilityTitleUIElementAttribute,
          nil]];
   }
+  // TODO(aboxhall): expose NSAccessibilityServesAsTitleForUIElementsAttribute
+  // for elements which are referred to by labelledby or are labels
 
   return ret;
 }
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc
index 8b280be..f45c31d 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -63,11 +63,14 @@
 }
 
 void BrowserAccessibilityStateImpl::OnScreenReaderDetected() {
-  AddAccessibilityMode(AccessibilityModeComplete);
+  if (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableRendererAccessibility)) {
+    return;
+  }
+  EnableAccessibility();
 }
 
 void BrowserAccessibilityStateImpl::EnableAccessibility() {
-  // We may want to do something different with this later.
   AddAccessibilityMode(AccessibilityModeComplete);
 }
 
diff --git a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
index 1ce26de..4bee21d 100644
--- a/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
+++ b/content/browser/accessibility/cross_platform_accessibility_browsertest.cc
@@ -10,10 +10,10 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_widget_host_view.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/accessibility_browser_test_utils.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "ui/accessibility/ax_node.h"
 #include "ui/accessibility/ax_tree.h"
 
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index d60abbb..f234df7 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -23,14 +23,14 @@
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/test/accessibility_browser_test_utils.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-// TODO(dmazzoni): Disabled accessibility tests on Win64. crbug.com/179717
-#if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
+// TODO(aboxhall): Create expectations on Android for these
+#if defined(OS_ANDROID)
 #define MAYBE(x) DISABLED_##x
 #else
 #define MAYBE(x) x
@@ -275,6 +275,11 @@
   RunTest(FILE_PATH_LITERAL("aria-combobox.html"));
 }
 
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+                       MAYBE(AccessibilityAriaFlowto)) {
+  RunTest(FILE_PATH_LITERAL("aria-flowto.html"));
+}
+
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaInvalid) {
   RunTest(FILE_PATH_LITERAL("aria-invalid.html"));
 }
@@ -450,8 +455,10 @@
   RunTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-closed.html"));
 }
 
+// TODO(dmazzoni): fix this test after Blink change that broke it lands.
+// http://crbug.com/353067
 IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
-                       AccessibilityModalDialogInIframeOpened) {
+                       DISABLED_AccessibilityModalDialogInIframeOpened) {
   RunTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-opened.html"));
 }
 
diff --git a/content/browser/android/content_video_view.cc b/content/browser/android/content_video_view.cc
index 8623c5f..d483641 100644
--- a/content/browser/android/content_video_view.cc
+++ b/content/browser/android/content_video_view.cc
@@ -107,10 +107,8 @@
 void ContentVideoView::OnExitFullscreen() {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
-  if (!content_video_view.is_null()) {
+  if (!content_video_view.is_null())
     Java_ContentVideoView_onExitFullscreen(env, content_video_view.obj());
-    j_content_video_view_.reset();
-  }
 }
 
 void ContentVideoView::UpdateMediaMetadata() {
diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc
index 123ef82..8606d5c 100644
--- a/content/browser/android/content_view_core_impl.cc
+++ b/content/browser/android/content_view_core_impl.cc
@@ -682,6 +682,20 @@
                                                 params.is_anchor_first);
 }
 
+void ContentViewCoreImpl::OnSelectionRootBoundsChanged(
+    const gfx::Rect& bounds) {
+  JNIEnv* env = AttachCurrentThread();
+
+  ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+  if (obj.is_null())
+    return;
+
+  ScopedJavaLocalRef<jobject> rect_object(CreateJavaRect(env, bounds));
+  Java_ContentViewCore_setSelectionRootBounds(env,
+                                              obj.obj(),
+                                              rect_object.obj());
+}
+
 void ContentViewCoreImpl::ShowPastePopup(int x_dip, int y_dip) {
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
@@ -960,11 +974,6 @@
   LoadUrl(params);
 }
 
-jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
-  return GetRenderProcessIdFromRenderViewHost(
-      web_contents_->GetRenderViewHost());
-}
-
 ScopedJavaLocalRef<jstring> ContentViewCoreImpl::GetURL(
     JNIEnv* env, jobject) const {
   return ConvertUTF8ToJavaString(env, GetWebContents()->GetURL().spec());
@@ -1019,11 +1028,7 @@
 
   scoped_ptr<ui::MotionEvent> cancel_event = current_down_event->Cancel();
   DCHECK(cancel_event);
-  if (!gesture_provider_.OnTouchEvent(*cancel_event))
-    return;
-
-  rwhv->SendTouchEvent(
-      CreateWebTouchEventFromMotionEvent(*cancel_event, 1.f / dpi_scale()));
+  OnMotionEvent(*cancel_event);
 }
 
 jboolean ContentViewCoreImpl::OnTouchEvent(JNIEnv* env,
@@ -1043,6 +1048,7 @@
                                            jfloat touch_major_0,
                                            jfloat touch_major_1) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
+  // Avoid synthesizing a touch event if it cannot be forwarded.
   if (!rwhv)
     return false;
 
@@ -1062,11 +1068,7 @@
                            touch_major_0,
                            touch_major_1);
 
-  if (!gesture_provider_.OnTouchEvent(event))
-    return false;
-
-  rwhv->SendTouchEvent(WebTouchEventBuilder::Build(event, 1.f / dpi_scale()));
-  return true;
+  return OnMotionEvent(event);
 }
 
 float ContentViewCoreImpl::GetDpiScale() const {
@@ -1122,6 +1124,26 @@
       type, time_ms / 1000.0, x / dpi_scale(), y / dpi_scale());
 }
 
+bool ContentViewCoreImpl::OnMotionEvent(const ui::MotionEvent& event) {
+  RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
+  if (!rwhv)
+    return false;
+
+  if (!gesture_provider_.OnTouchEvent(event))
+    return false;
+
+  RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
+      rwhv->GetRenderWidgetHost());
+  if (!host->ShouldForwardTouchEvent()) {
+    ConfirmTouchEvent(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
+    return true;
+  }
+
+  rwhv->SendTouchEvent(
+      CreateWebTouchEventFromMotionEvent(event, 1.f / dpi_scale()));
+  return true;
+}
+
 void ContentViewCoreImpl::SendGestureEvent(
     const blink::WebGestureEvent& event) {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
@@ -1230,11 +1252,13 @@
 void ContentViewCoreImpl::SelectBetweenCoordinates(JNIEnv* env, jobject obj,
                                                    jfloat x1, jfloat y1,
                                                    jfloat x2, jfloat y2) {
-  if (GetRenderWidgetHostViewAndroid()) {
-    GetRenderWidgetHostViewAndroid()->SelectRange(
-        gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
-        gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
-  }
+  if (!web_contents_ || !web_contents_->GetFocusedFrame())
+    return;
+
+  RenderFrameHostImpl* frame =
+      static_cast<RenderFrameHostImpl*>(web_contents_->GetFocusedFrame());
+  frame->SelectRange(gfx::Point(x1 / dpi_scale(), y1 / dpi_scale()),
+                     gfx::Point(x2 / dpi_scale(), y2 / dpi_scale()));
 }
 
 void ContentViewCoreImpl::MoveCaret(JNIEnv* env, jobject obj,
@@ -1680,7 +1704,7 @@
 void ContentViewCoreImpl::SendOrientationChangeEventInternal() {
   RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
   if (rwhv)
-    rwhv->UpdateScreenInfo(rwhv->GetNativeView());
+    rwhv->UpdateScreenInfo(GetViewAndroid());
 
   RenderViewHostImpl* rvhi = static_cast<RenderViewHostImpl*>(
       web_contents_->GetRenderViewHost());
@@ -1736,6 +1760,11 @@
       GetWebContents()->GetRoutingID(), rect));
 }
 
+jint ContentViewCoreImpl::GetCurrentRenderProcessId(JNIEnv* env, jobject obj) {
+  return GetRenderProcessIdFromRenderViewHost(
+      web_contents_->GetRenderViewHost());
+}
+
 void ContentViewCoreImpl::OnSmartClipDataExtracted(
     const base::string16& result) {
   JNIEnv* env = AttachCurrentThread();
diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h
index 4513b60..0dbceef 100644
--- a/content/browser/android/content_view_core_impl.h
+++ b/content/browser/android/content_view_core_impl.h
@@ -55,7 +55,6 @@
   virtual ui::WindowAndroid* GetWindowAndroid() const OVERRIDE;
   virtual scoped_refptr<cc::Layer> GetLayer() const OVERRIDE;
   virtual void LoadUrl(NavigationController::LoadURLParams& params) OVERRIDE;
-  virtual jint GetCurrentRenderProcessId(JNIEnv* env, jobject obj) OVERRIDE;
   virtual void ShowPastePopup(int x, int y) OVERRIDE;
   virtual void GetScaledContentBitmap(
       float scale,
@@ -232,6 +231,9 @@
                             jint y,
                             jint width,
                             jint height);
+
+  jint GetCurrentRenderProcessId(JNIEnv* env, jobject obj);
+
   // --------------------------------------------------------------------------
   // Public methods that call to Java via JNI
   // --------------------------------------------------------------------------
@@ -274,6 +276,7 @@
   void OnSelectionChanged(const std::string& text);
   void OnSelectionBoundsChanged(
       const ViewHostMsg_SelectionBounds_Params& params);
+  void OnSelectionRootBoundsChanged(const gfx::Rect& bounds);
 
   void StartContentIntent(const GURL& content_url);
 
@@ -349,6 +352,7 @@
 
   void DeleteScaledSnapshotTexture();
 
+  bool OnMotionEvent(const ui::MotionEvent& event);
   void SendGestureEvent(const blink::WebGestureEvent& event);
 
   // Update focus state of the RenderWidgetHostView.
diff --git a/content/browser/android/content_view_statics.cc b/content/browser/android/content_view_statics.cc
index aa7ebff..b6cfde1 100644
--- a/content/browser/android/content_view_statics.cc
+++ b/content/browser/android/content_view_statics.cc
@@ -44,12 +44,12 @@
                                    base::ProcessHandle handle,
                                    base::TerminationStatus status,
                                    int exit_code) OVERRIDE {
-    std::vector<int>::iterator pos = std::find(suspended_processes_.begin(),
-                                               suspended_processes_.end(),
-                                               host->GetID());
-    DCHECK_NE(pos, suspended_processes_.end());
-    host->RemoveObserver(this);
-    suspended_processes_.erase(pos);
+    StopWatching(host);
+  }
+
+  virtual void RenderProcessHostDestroyed(
+      content::RenderProcessHost* host) OVERRIDE {
+    StopWatching(host);
   }
 
   // Suspends timers in all current render processes.
@@ -82,6 +82,15 @@
   }
 
  private:
+  void StopWatching(content::RenderProcessHost* host) {
+    std::vector<int>::iterator pos = std::find(suspended_processes_.begin(),
+                                               suspended_processes_.end(),
+                                               host->GetID());
+    DCHECK_NE(pos, suspended_processes_.end());
+    host->RemoveObserver(this);
+    suspended_processes_.erase(pos);
+  }
+
   std::vector<int /* RenderProcessHost id */> suspended_processes_;
 };
 
diff --git a/content/browser/android/in_process/synchronous_compositor_output_surface.cc b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
index 4a7ce90..88983d5 100644
--- a/content/browser/android/in_process/synchronous_compositor_output_surface.cc
+++ b/content/browser/android/in_process/synchronous_compositor_output_surface.cc
@@ -15,7 +15,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
-#include "third_party/skia/include/core/SkBitmapDevice.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "ui/gfx/rect_conversions.h"
 #include "ui/gfx/skia_util.h"
@@ -38,9 +37,7 @@
   : public cc::SoftwareOutputDevice {
  public:
   SoftwareDevice(SynchronousCompositorOutputSurface* surface)
-    : surface_(surface),
-      null_device_(SkBitmap::kARGB_8888_Config, 1, 1),
-      null_canvas_(&null_device_) {
+    : surface_(surface) {
   }
   virtual void Resize(const gfx::Size& size) OVERRIDE {
     // Intentional no-op: canvas size is controlled by the embedder.
@@ -56,13 +53,12 @@
   }
   virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE {
   }
-  virtual void CopyToBitmap(const gfx::Rect& rect, SkBitmap* output) OVERRIDE {
+  virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE {
     NOTIMPLEMENTED();
   }
 
  private:
   SynchronousCompositorOutputSurface* surface_;
-  SkBitmapDevice null_device_;
   SkCanvas null_canvas_;
 
   DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
diff --git a/content/browser/android/overscroll_glow.cc b/content/browser/android/overscroll_glow.cc
index 8e08de4..f4a0168 100644
--- a/content/browser/android/overscroll_glow.cc
+++ b/content/browser/android/overscroll_glow.cc
@@ -9,6 +9,7 @@
 #include "base/threading/worker_pool.h"
 #include "cc/layers/image_layer.h"
 #include "content/browser/android/edge_effect.h"
+#include "skia/ext/image_operations.h"
 #include "ui/gfx/android/java_bitmap.h"
 
 using std::max;
@@ -20,16 +21,30 @@
 
 const float kEpsilon = 1e-3f;
 
+SkBitmap CreateSkBitmapFromAndroidResource(const char* name, gfx::Size size) {
+  base::android::ScopedJavaLocalRef<jobject> jobj =
+      gfx::CreateJavaBitmapFromAndroidResource(name, size);
+  if (jobj.is_null())
+    return SkBitmap();
+
+  SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(gfx::JavaBitmap(jobj.obj()));
+  if (bitmap.isNull())
+    return bitmap;
+
+  return skia::ImageOperations::Resize(
+      bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
+}
+
 class OverscrollResources {
  public:
   OverscrollResources() {
     TRACE_EVENT0("browser", "OverscrollResources::Create");
     edge_bitmap_ =
-        gfx::CreateSkBitmapFromResource("android:drawable/overscroll_edge",
-                                        gfx::Size(128, 12));
+        CreateSkBitmapFromAndroidResource("android:drawable/overscroll_edge",
+                                          gfx::Size(128, 12));
     glow_bitmap_ =
-        gfx::CreateSkBitmapFromResource("android:drawable/overscroll_glow",
-                                        gfx::Size(128, 64));
+        CreateSkBitmapFromAndroidResource("android:drawable/overscroll_glow",
+                                          gfx::Size(128, 64));
   }
 
   const SkBitmap& edge_bitmap() { return edge_bitmap_; }
diff --git a/content/browser/bookmarklet_browsertest.cc b/content/browser/bookmarklet_browsertest.cc
index 35523ee..9381962 100644
--- a/content/browser/bookmarklet_browsertest.cc
+++ b/content/browser/bookmarklet_browsertest.cc
@@ -5,10 +5,10 @@
 #include "base/strings/string_util.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
index d042217..e1365f9 100644
--- a/content/browser/browser_child_process_host_impl.cc
+++ b/content/browser/browser_child_process_host_impl.cc
@@ -144,9 +144,6 @@
     switches::kTraceToConsole,
     switches::kV,
     switches::kVModule,
-#if defined(OS_POSIX)
-    switches::kChildCleanExit,
-#endif
 #if defined(OS_WIN)
     switches::kEnableHighResolutionTime,
 #endif
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 89a5281..ab045e4 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -959,7 +959,6 @@
   bool established_gpu_channel = false;
 #if defined(USE_AURA) || defined(OS_ANDROID)
   established_gpu_channel =
-      !parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) ||
       parsed_command_line_.HasSwitch(switches::kSingleProcess) ||
       parsed_command_line_.HasSwitch(switches::kInProcessGPU);
 #if defined(USE_AURA)
@@ -1032,7 +1031,6 @@
   if (GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL) &&
       !established_gpu_channel &&
       always_uses_gpu &&
-      !parsed_command_line_.HasSwitch(switches::kDisableGpuProcessPrelaunch) &&
       !parsed_command_line_.HasSwitch(switches::kSingleProcess) &&
       !parsed_command_line_.HasSwitch(switches::kInProcessGPU)) {
     TRACE_EVENT_INSTANT0("gpu", "Post task to launch GPU process",
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 7aba398..3217485 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -14,6 +14,7 @@
 #include "content/browser/browser_plugin/browser_plugin_host_factory.h"
 #include "content/browser/browser_thread_impl.h"
 #include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/frame_host/render_widget_host_view_guest.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -872,7 +873,7 @@
 }
 
 void BrowserPluginGuest::WebContentsCreated(WebContents* source_contents,
-                                            int64 source_frame_id,
+                                            int opener_render_frame_id,
                                             const base::string16& frame_name,
                                             const GURL& target_url,
                                             WebContents* new_contents) {
@@ -1372,7 +1373,10 @@
     int instance_id,
     int before,
     int after) {
-  Send(new ViewMsg_ExtendSelectionAndDelete(routing_id(), before, after));
+  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
+      web_contents()->GetFocusedFrame());
+  if (rfh)
+    rfh->ExtendSelectionAndDelete(before, after);
 }
 
 void BrowserPluginGuest::OnReclaimCompositorResources(
diff --git a/content/browser/browser_plugin/browser_plugin_guest.h b/content/browser/browser_plugin/browser_plugin_guest.h
index dc0d233..e55845ff 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/content/browser/browser_plugin/browser_plugin_guest.h
@@ -217,7 +217,7 @@
   virtual WebContents* OpenURLFromTab(WebContents* source,
                                       const OpenURLParams& params) OVERRIDE;
   virtual void WebContentsCreated(WebContents* source_contents,
-                                  int64 source_frame_id,
+                                  int opener_render_frame_id,
                                   const base::string16& frame_name,
                                   const GURL& target_url,
                                   WebContents* new_contents) OVERRIDE;
diff --git a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
index 16dfcfd..f3415cb 100644
--- a/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
+++ b/content/browser/browser_plugin/browser_plugin_host_browsertest.cc
@@ -16,6 +16,7 @@
 #include "content/browser/browser_plugin/test_browser_plugin_guest_delegate.h"
 #include "content/browser/browser_plugin/test_browser_plugin_guest_manager.h"
 #include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/frame_host/render_widget_host_view_guest.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
@@ -30,10 +31,10 @@
 #include "content/public/common/drop_data.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
@@ -1048,10 +1049,9 @@
                                         expected_value);
     // Delete 'Test' in 'InputTestABC', as the caret is after 'T':
     // delete before 1 character ('T') and after 3 characters ('est').
-    embedder_rvh->Send(
-        new ViewMsg_ExtendSelectionAndDelete(
-            test_embedder()->web_contents()->GetRoutingID(),
-            1, 3));
+    RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
+        test_embedder()->web_contents()->GetFocusedFrame());
+    rfh->ExtendSelectionAndDelete(1, 3);
     base::string16 actual_title = title_watcher.WaitAndGetTitle();
     EXPECT_EQ(expected_value, actual_title);
     scoped_ptr<base::Value> value =
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index 5d7b612..4d2a1dc 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -58,17 +58,12 @@
         client_thread_id_(BrowserThread::UI),
         termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
         exit_code_(RESULT_CODE_NORMAL_EXIT),
-        starting_(true)
+        starting_(true),
+        terminate_child_on_shutdown_(true)
 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
         , zygote_(false)
 #endif
         {
-#if defined(OS_POSIX)
-          terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()->
-              HasSwitch(switches::kChildCleanExit);
-#else
-          terminate_child_on_shutdown_ = true;
-#endif
   }
 
   void Launch(
@@ -499,7 +494,7 @@
 }
 
 void ChildProcessLauncher::SetTerminateChildOnShutdown(
-  bool terminate_on_shutdown) {
+    bool terminate_on_shutdown) {
   if (context_.get())
     context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
 }
diff --git a/content/browser/child_process_security_policy_browsertest.cc b/content/browser/child_process_security_policy_browsertest.cc
index c7cfe39..67d36e4 100644
--- a/content/browser/child_process_security_policy_browsertest.cc
+++ b/content/browser/child_process_security_policy_browsertest.cc
@@ -10,9 +10,9 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/common/result_codes.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index c6200dd..cadd31c 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -461,6 +461,16 @@
   GrantPermissionsForFile(child_id, file, CREATE_READ_WRITE_FILE_GRANT);
 }
 
+void ChildProcessSecurityPolicyImpl::GrantCopyInto(int child_id,
+                                                   const base::FilePath& dir) {
+  GrantPermissionsForFile(child_id, dir, COPY_INTO_FILE_GRANT);
+}
+
+void ChildProcessSecurityPolicyImpl::GrantDeleteFrom(
+    int child_id, const base::FilePath& dir) {
+  GrantPermissionsForFile(child_id, dir, DELETE_FILE_GRANT);
+}
+
 void ChildProcessSecurityPolicyImpl::GrantPermissionsForFile(
     int child_id, const base::FilePath& file, int permissions) {
   base::AutoLock lock(lock_);
diff --git a/content/browser/child_process_security_policy_impl.h b/content/browser/child_process_security_policy_impl.h
index db640d8..005292c 100644
--- a/content/browser/child_process_security_policy_impl.h
+++ b/content/browser/child_process_security_policy_impl.h
@@ -45,6 +45,9 @@
   virtual void GrantReadFile(int child_id, const base::FilePath& file) OVERRIDE;
   virtual void GrantCreateReadWriteFile(int child_id,
                                         const base::FilePath& file) OVERRIDE;
+  virtual void GrantCopyInto(int child_id, const base::FilePath& dir) OVERRIDE;
+  virtual void GrantDeleteFrom(int child_id,
+                               const base::FilePath& dir) OVERRIDE;
   virtual void GrantReadFileSystem(
       int child_id,
       const std::string& filesystem_id) OVERRIDE;
diff --git a/content/browser/compositor/image_transport_factory_browsertest.cc b/content/browser/compositor/image_transport_factory_browsertest.cc
index 766b52e..13998b5 100644
--- a/content/browser/compositor/image_transport_factory_browsertest.cc
+++ b/content/browser/compositor/image_transport_factory_browsertest.cc
@@ -6,7 +6,7 @@
 #include "cc/output/context_provider.h"
 #include "content/browser/compositor/image_transport_factory.h"
 #include "content/public/browser/gpu_data_manager.h"
-#include "content/test/content_browser_test.h"
+#include "content/public/test/content_browser_test.h"
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/content/browser/compositor/software_output_device_ozone.cc b/content/browser/compositor/software_output_device_ozone.cc
index 340eee9..ad7d031 100644
--- a/content/browser/compositor/software_output_device_ozone.cc
+++ b/content/browser/compositor/software_output_device_ozone.cc
@@ -41,7 +41,6 @@
                                             bounds);
 
   canvas_ = skia::SharePtr(factory->GetCanvasForWidget(realized_widget_));
-  device_ = skia::SharePtr(canvas_->getDevice());
 }
 
 SkCanvas* SoftwareOutputDeviceOzone::BeginPaint(const gfx::Rect& damage_rect) {
diff --git a/content/browser/compositor/software_output_device_ozone_unittest.cc b/content/browser/compositor/software_output_device_ozone_unittest.cc
index a232674..ed94e9f 100644
--- a/content/browser/compositor/software_output_device_ozone_unittest.cc
+++ b/content/browser/compositor/software_output_device_ozone_unittest.cc
@@ -7,7 +7,7 @@
 #include "cc/output/software_frame_data.h"
 #include "content/browser/compositor/software_output_device_ozone.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmapDevice.h"
+#include "third_party/skia/include/core/SkSurface.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/test/context_factories_for_test.h"
 #include "ui/gfx/ozone/surface_factory_ozone.h"
@@ -38,23 +38,19 @@
   }
   virtual bool AttemptToResizeAcceleratedWidget(
       gfx::AcceleratedWidget w, const gfx::Rect& bounds) OVERRIDE {
-    device_ = skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
-                                                bounds.width(),
-                                                bounds.height(),
-                                                true));
-    canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
+    surface_ = skia::AdoptRef(SkSurface::NewRaster(
+        SkImageInfo::MakeN32Premul(bounds.width(), bounds.height())));
     return true;
   }
   virtual SkCanvas* GetCanvasForWidget(gfx::AcceleratedWidget w) OVERRIDE {
-    return canvas_.get();
+    return surface_->getCanvas();
   }
   virtual scoped_ptr<gfx::VSyncProvider> CreateVSyncProvider(
       gfx::AcceleratedWidget w) OVERRIDE {
     return scoped_ptr<gfx::VSyncProvider>();
   }
  private:
-  skia::RefPtr<SkBitmapDevice> device_;
-  skia::RefPtr<SkCanvas> canvas_;
+  skia::RefPtr<SkSurface> surface_;
 
   DISALLOW_COPY_AND_ASSIGN(MockSurfaceFactoryOzone);
 };
@@ -173,7 +169,9 @@
 }
 
 TEST_F(SoftwareOutputDeviceOzonePixelTest, CheckCopyToBitmap) {
-  const gfx::Rect area(6, 4);
+  const int width = 6;
+  const int height = 4;
+  const gfx::Rect area(width, height);
   output_device_->Resize(area.size());
   SkCanvas* canvas = output_device_->BeginPaint(area);
 
@@ -191,18 +189,19 @@
 
   output_device_->EndPaint(&frame);
 
-  SkBitmap bitmap;
-  output_device_->CopyToBitmap(area, &bitmap);
+  SkPMColor pixels[width * height];
+  output_device_->CopyToPixels(area, pixels);
 
-  SkAutoLockPixels pixel_lock(bitmap);
   // Check that the copied bitmap contains the same pixel values as what we
   // painted.
+  const SkPMColor white = SkPreMultiplyColor(SK_ColorWHITE);
+  const SkPMColor black = SkPreMultiplyColor(SK_ColorBLACK);
   for (int i = 0; i < area.height(); ++i) {
     for (int j = 0; j < area.width(); ++j) {
       if (j < damage.width() && i < damage.height())
-        EXPECT_EQ(SK_ColorWHITE, bitmap.getColor(j, i));
+        EXPECT_EQ(white, pixels[i * area.width() + j]);
       else
-        EXPECT_EQ(SK_ColorBLACK, bitmap.getColor(j, i));
+        EXPECT_EQ(black, pixels[i * area.width() + j]);
     }
   }
 }
diff --git a/content/browser/compositor/software_output_device_win.cc b/content/browser/compositor/software_output_device_win.cc
index a65b7e0..3c938bf 100644
--- a/content/browser/compositor/software_output_device_win.cc
+++ b/content/browser/compositor/software_output_device_win.cc
@@ -92,12 +92,12 @@
   }
 }
 
-void SoftwareOutputDeviceWin::CopyToBitmap(
-    const gfx::Rect& rect, SkBitmap* output) {
+void SoftwareOutputDeviceWin::CopyToPixels(const gfx::Rect& rect,
+                                           void* pixels) {
   DCHECK(contents_);
-  SkBaseDevice* device = contents_->sk_canvas()->getDevice();
-  const SkBitmap& bitmap = device->accessBitmap(false);
-  bitmap.extractSubset(output, gfx::RectToSkIRect(rect));
+  SkImageInfo info = SkImageInfo::MakeN32Premul(rect.width(), rect.height());
+  contents_->sk_canvas()->readPixels(
+      info, pixels, info.minRowBytes(), rect.x(), rect.y());
 }
 
 }  // namespace content
diff --git a/content/browser/compositor/software_output_device_win.h b/content/browser/compositor/software_output_device_win.h
index 00b238c..30addbc 100644
--- a/content/browser/compositor/software_output_device_win.h
+++ b/content/browser/compositor/software_output_device_win.h
@@ -28,7 +28,7 @@
   virtual void Resize(const gfx::Size& viewport_size) OVERRIDE;
   virtual SkCanvas* BeginPaint(const gfx::Rect& damage_rect) OVERRIDE;
   virtual void EndPaint(cc::SoftwareFrameData* frame_data) OVERRIDE;
-  virtual void CopyToBitmap(const gfx::Rect& rect, SkBitmap* output) OVERRIDE;
+  virtual void CopyToPixels(const gfx::Rect& rect, void* pixels) OVERRIDE;
 
  private:
   HWND hwnd_;
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc
index c5ff7da..fff180d 100644
--- a/content/browser/cross_site_transfer_browsertest.cc
+++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -11,12 +11,12 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/escape.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/url_request/url_request.h"
@@ -234,10 +234,22 @@
   ResourceDispatcherHostDelegate* old_delegate_;
 };
 
+// The following tests crash in the ThreadSanitizer runtime,
+// http://crbug.com/356758.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_ReplaceEntryCrossProcessThenTransfer \
+    DISABLED_ReplaceEntryCrossProcessThenTransfer
+#define MAYBE_ReplaceEntryCrossProcessTwice \
+    DISABLED_ReplaceEntryCrossProcessTwice
+#else
+#define MAYBE_ReplaceEntryCrossProcessThenTransfer \
+    ReplaceEntryCrossProcessThenTransfer
+#define MAYBE_ReplaceEntryCrossProcessTwice ReplaceEntryCrossProcessTwice
+#endif
 // Tests that the |should_replace_current_entry| flag persists correctly across
 // request transfers that began with a cross-process navigation.
 IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
-                       ReplaceEntryCrossProcessThenTransfer) {
+                       MAYBE_ReplaceEntryCrossProcessThenTransfer) {
   const NavigationController& controller =
       shell()->web_contents()->GetController();
   host_resolver()->AddRule("*", "127.0.0.1");
@@ -347,7 +359,7 @@
 // Tests that the |should_replace_current_entry| flag persists correctly across
 // request transfers that cross processes twice from renderer policy.
 IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
-                       ReplaceEntryCrossProcessTwice) {
+                       MAYBE_ReplaceEntryCrossProcessTwice) {
   const NavigationController& controller =
       shell()->web_contents()->GetController();
   host_resolver()->AddRule("*", "127.0.0.1");
diff --git a/content/browser/database_browsertest.cc b/content/browser/database_browsertest.cc
index 373a06f..d3cc669 100644
--- a/content/browser/database_browsertest.cc
+++ b/content/browser/database_browsertest.cc
@@ -10,10 +10,10 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/net/url_request_mock_http_job.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/content/browser/device_monitor_mac.mm b/content/browser/device_monitor_mac.mm
index 1ba6d39..10dd620 100644
--- a/content/browser/device_monitor_mac.mm
+++ b/content/browser/device_monitor_mac.mm
@@ -6,6 +6,8 @@
 
 #import <QTKit/QTKit.h>
 
+#include <set>
+
 #include "base/logging.h"
 #include "base/mac/scoped_nsobject.h"
 #import "media/video/capture/mac/avfoundation_glue.h"
@@ -214,6 +216,8 @@
 @interface CrAVFoundationDeviceObserver : NSObject {
  @private
   AVFoundationMonitorImpl* receiver_;
+  // Member to keep track of the devices we are already monitoring.
+  std::set<CrAVCaptureDevice*> monitoredDevices_;
 }
 
 - (id)initWithChangeReceiver:(AVFoundationMonitorImpl*)receiver;
@@ -304,6 +308,11 @@
 
 - (void)startObserving:(CrAVCaptureDevice*)device {
   DCHECK(device != nil);
+  // Skip this device if there are already observers connected to it.
+  if (std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device) !=
+          monitoredDevices_.end()) {
+    return;
+  }
   [device addObserver:self
            forKeyPath:@"suspended"
               options:0
@@ -312,14 +321,19 @@
            forKeyPath:@"connected"
               options:0
               context:device];
+  monitoredDevices_.insert(device);
 }
 
 - (void)stopObserving:(CrAVCaptureDevice*)device {
   DCHECK(device != nil);
+  std::set<CrAVCaptureDevice*>::iterator found =
+      std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device);
+  DCHECK(found != monitoredDevices_.end());
   [device removeObserver:self
               forKeyPath:@"suspended"];
   [device removeObserver:self
               forKeyPath:@"connected"];
+  monitoredDevices_.erase(found);
 }
 
 - (void)observeValueForKeyPath:(NSString*)keyPath
diff --git a/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc b/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc
index 91ffd3e..2fb4ec3 100644
--- a/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc
+++ b/content/browser/device_orientation/data_fetcher_shared_memory_mac.cc
@@ -64,9 +64,6 @@
   double beta = kRad2deg * atan2(-axis_value[1], axis_value[2]);
   double gamma = kRad2deg * asin(axis_value[0]);
 
-  // TODO(aousterh): should absolute_ be set to false here?
-  // See crbug.com/136010.
-
   // Make sure that the interval boundaries comply with the specification. At
   // this point, beta is [-180, 180] and gamma is [-90, 90], but the spec has
   // the upper bound open on both.
@@ -120,22 +117,40 @@
   DCHECK(base::MessageLoop::current() == GetPollingMessageLoop());
   DCHECK(buffer);
 
+  if (!sudden_motion_sensor_)
+    sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
+  bool sudden_motion_sensor_available = sudden_motion_sensor_.get() != NULL;
+
   switch (consumer_type) {
     case CONSUMER_TYPE_MOTION:
       motion_buffer_ = static_cast<DeviceMotionHardwareBuffer*>(buffer);
-      if (!sudden_motion_sensor_)
-        sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
       UMA_HISTOGRAM_BOOLEAN("InertialSensor.MotionMacAvailable",
-          sudden_motion_sensor_.get() != NULL);
-      return sudden_motion_sensor_.get() != NULL;
+          sudden_motion_sensor_available);
+      if (!sudden_motion_sensor_available) {
+        // No motion sensor available, fire an all-null event.
+        motion_buffer_->seqlock.WriteBegin();
+        motion_buffer_->data.allAvailableSensorsAreActive = true;
+        motion_buffer_->seqlock.WriteEnd();
+      }
+      return sudden_motion_sensor_available;
     case CONSUMER_TYPE_ORIENTATION:
       orientation_buffer_ =
           static_cast<DeviceOrientationHardwareBuffer*>(buffer);
-      if (!sudden_motion_sensor_)
-        sudden_motion_sensor_.reset(SuddenMotionSensor::Create());
       UMA_HISTOGRAM_BOOLEAN("InertialSensor.OrientationMacAvailable",
-          sudden_motion_sensor_.get() != NULL);
-      return sudden_motion_sensor_.get() != NULL;
+          sudden_motion_sensor_available);
+      if (sudden_motion_sensor_available) {
+        // On Mac we cannot provide absolute orientation.
+        orientation_buffer_->seqlock.WriteBegin();
+        orientation_buffer_->data.absolute = false;
+        orientation_buffer_->data.hasAbsolute = true;
+        orientation_buffer_->seqlock.WriteEnd();
+      } else {
+        // No motion sensor available, fire an all-null event.
+        orientation_buffer_->seqlock.WriteBegin();
+        orientation_buffer_->data.allAvailableSensorsAreActive = true;
+        orientation_buffer_->seqlock.WriteEnd();
+      }
+      return sudden_motion_sensor_available;
     default:
       NOTREACHED();
   }
diff --git a/content/browser/device_orientation/device_inertial_sensor_browsertest.cc b/content/browser/device_orientation/device_inertial_sensor_browsertest.cc
index a176f71..0dadba3 100644
--- a/content/browser/device_orientation/device_inertial_sensor_browsertest.cc
+++ b/content/browser/device_orientation/device_inertial_sensor_browsertest.cc
@@ -11,9 +11,9 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 
 namespace content {
 
diff --git a/content/browser/devtools/devtools_resources.target.darwin-x86.mk b/content/browser/devtools/devtools_resources.target.darwin-x86.mk
index 344579a..8028423 100644
--- a/content/browser/devtools/devtools_resources.target.darwin-x86.mk
+++ b/content/browser/devtools/devtools_resources.target.darwin-x86.mk
@@ -21,7 +21,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
diff --git a/content/browser/devtools/devtools_resources.target.darwin-x86_64.mk b/content/browser/devtools/devtools_resources.target.darwin-x86_64.mk
new file mode 100644
index 0000000..8028423
--- /dev/null
+++ b/content/browser/devtools/devtools_resources.target.darwin-x86_64.mk
@@ -0,0 +1,70 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_browser_devtools_devtools_resources_gyp
+LOCAL_MODULE_STEM := devtools_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp
+
+### Rules for action "devtools_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+
+### Rules for action "devtools_protocol_constants":
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: $(LOCAL_PATH)/third_party/WebKit/Source/devtools/protocol.json $(LOCAL_PATH)/content/browser/devtools/browser_protocol.json $(LOCAL_PATH)/content/browser/devtools/devtools_protocol_constants_generator.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating DevTools protocol constants from ../../../third_party/WebKit/Source/devtools/protocol.json ($@)"
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/content/browser/devtools; python devtools_protocol_constants_generator.py ../../../third_party/WebKit/Source/devtools/protocol.json browser_protocol.json "$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc" "$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.h"
+
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.h: $(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h \
+	$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc \
+	$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_devtools_devtools_resources_gyp
+
+# Alias gyp target name.
+.PHONY: devtools_resources
+devtools_resources: content_browser_devtools_devtools_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/browser/devtools/devtools_resources.target.linux-x86.mk b/content/browser/devtools/devtools_resources.target.linux-x86.mk
index 344579a..8028423 100644
--- a/content/browser/devtools/devtools_resources.target.linux-x86.mk
+++ b/content/browser/devtools/devtools_resources.target.linux-x86.mk
@@ -21,7 +21,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
diff --git a/content/browser/devtools/devtools_resources.target.linux-x86_64.mk b/content/browser/devtools/devtools_resources.target.linux-x86_64.mk
new file mode 100644
index 0000000..8028423
--- /dev/null
+++ b/content/browser/devtools/devtools_resources.target.linux-x86_64.mk
@@ -0,0 +1,70 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_browser_devtools_devtools_resources_gyp
+LOCAL_MODULE_STEM := devtools_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_generate_devtools_grd_gyp)/blink_generate_devtools_grd.stamp
+
+### Rules for action "devtools_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h: $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from $(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../../../tools/grit/grit.py -i "$(gyp_shared_intermediate_dir)/devtools/devtools_resources.grd" build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D "SHARED_INTERMEDIATE_DIR=$(gyp_shared_intermediate_dir)" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h ;
+
+### Rules for action "devtools_protocol_constants":
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc: $(LOCAL_PATH)/third_party/WebKit/Source/devtools/protocol.json $(LOCAL_PATH)/content/browser/devtools/browser_protocol.json $(LOCAL_PATH)/content/browser/devtools/devtools_protocol_constants_generator.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating DevTools protocol constants from ../../../third_party/WebKit/Source/devtools/protocol.json ($@)"
+	$(hide)cd $(gyp_local_path)/content/browser/devtools; mkdir -p $(gyp_shared_intermediate_dir)/content/browser/devtools; python devtools_protocol_constants_generator.py ../../../third_party/WebKit/Source/devtools/protocol.json browser_protocol.json "$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc" "$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.h"
+
+$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.h: $(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/devtools_resources.pak \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.h \
+	$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc \
+	$(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_devtools_devtools_resources_gyp
+
+# Alias gyp target name.
+.PHONY: devtools_resources
+devtools_resources: content_browser_devtools_devtools_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/browser/devtools/render_view_devtools_agent_host.cc b/content/browser/devtools/render_view_devtools_agent_host.cc
index c6d7c49..c9d8634 100644
--- a/content/browser/devtools/render_view_devtools_agent_host.cc
+++ b/content/browser/devtools/render_view_devtools_agent_host.cc
@@ -36,6 +36,22 @@
 namespace {
 base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
 
+//Returns RenderViewDevToolsAgentHost attached to any of RenderViewHost
+//instances associated with |web_contents|
+static RenderViewDevToolsAgentHost* FindAgentHost(WebContents* web_contents) {
+  if (g_instances == NULL)
+    return NULL;
+  RenderViewHostDelegate* delegate =
+      static_cast<WebContentsImpl*>(web_contents);
+  for (Instances::iterator it = g_instances.Get().begin();
+       it != g_instances.Get().end(); ++it) {
+    RenderViewHost* rvh = (*it)->render_view_host();
+    if (rvh && rvh->GetDelegate() == delegate)
+      return *it;
+  }
+  return NULL;
+}
+
 static RenderViewDevToolsAgentHost* FindAgentHost(RenderViewHost* rvh) {
   if (g_instances == NULL)
     return NULL;
@@ -49,6 +65,14 @@
 
 }  // namespace
 
+scoped_refptr<DevToolsAgentHost>
+DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) {
+  RenderViewDevToolsAgentHost* result = FindAgentHost(web_contents);
+  if (!result)
+    result = new RenderViewDevToolsAgentHost(web_contents->GetRenderViewHost());
+  return result;
+}
+
 // static
 scoped_refptr<DevToolsAgentHost>
 DevToolsAgentHost::GetOrCreateFor(RenderViewHost* rvh) {
diff --git a/content/browser/devtools/renderer_overrides_handler.cc b/content/browser/devtools/renderer_overrides_handler.cc
index 4efb6e8..65c605b 100644
--- a/content/browser/devtools/renderer_overrides_handler.cc
+++ b/content/browser/devtools/renderer_overrides_handler.cc
@@ -13,6 +13,7 @@
 #include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/strings/string16.h"
+#include "base/thread_task_runner_handle.h"
 #include "base/values.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/devtools/devtools_protocol_constants.h"
@@ -201,10 +202,9 @@
 
   view_port->CopyFromCompositingSurface(
       view_bounds, snapshot_size,
-      base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
+      base::Bind(&RendererOverridesHandler::ScreencastFrameCaptured,
                  weak_factory_.GetWeakPtr(),
-                 scoped_refptr<DevToolsProtocol::Command>(), format, quality,
-                 last_compositor_frame_metadata_),
+                 format, quality, last_compositor_frame_metadata_),
       SkBitmap::kARGB_8888_Config);
 }
 
@@ -219,13 +219,13 @@
   double max_height = -1;
   base::DictionaryValue* params = command->params();
   if (params) {
-    params->GetString(devtools::Page::captureScreenshot::kParamFormat,
+    params->GetString(devtools::Page::startScreencast::kParamFormat,
                       format);
-    params->GetInteger(devtools::Page::captureScreenshot::kParamQuality,
+    params->GetInteger(devtools::Page::startScreencast::kParamQuality,
                        quality);
-    params->GetDouble(devtools::Page::captureScreenshot::kParamMaxWidth,
+    params->GetDouble(devtools::Page::startScreencast::kParamMaxWidth,
                       &max_width);
-    params->GetDouble(devtools::Page::captureScreenshot::kParamMaxHeight,
+    params->GetDouble(devtools::Page::startScreencast::kParamMaxHeight,
                       &max_height);
   }
 
@@ -247,6 +247,20 @@
     *scale = 5;
 }
 
+base::DictionaryValue* RendererOverridesHandler::CreateScreenshotResponse(
+    const std::vector<unsigned char>& png_data) {
+  std::string base_64_data;
+  base::Base64Encode(
+      base::StringPiece(reinterpret_cast<const char*>(&png_data[0]),
+                        png_data.size()),
+      &base_64_data);
+
+  base::DictionaryValue* response = new base::DictionaryValue();
+  response->SetString(
+      devtools::Page::captureScreenshot::kResponseData, base_64_data);
+  return response;
+}
+
 // DOM agent handlers  --------------------------------------------------------
 
 scoped_refptr<DevToolsProtocol::Response>
@@ -427,45 +441,41 @@
   if (!host->GetView())
     return command->InternalErrorResponse("Unable to access the view");
 
-  std::string format;
-  int quality = kDefaultScreenshotQuality;
-  double scale = 1;
-  ParseCaptureParameters(command.get(), &format, &quality, &scale);
-
   gfx::Rect view_bounds = host->GetView()->GetViewBounds();
-  gfx::Size snapshot_size = gfx::ToFlooredSize(
-      gfx::ScaleSize(view_bounds.size(), scale));
+  gfx::Rect snapshot_bounds(view_bounds.size());
+  gfx::Size snapshot_size = snapshot_bounds.size();
 
-  // Grab screen pixels if available for current platform.
-  // TODO(pfeldman): support format, scale and quality in ui::GrabViewSnapshot.
-  std::vector<unsigned char> png;
-  bool is_unscaled_png = scale == 1 && format == kPng;
-  if (is_unscaled_png && ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
-                                              &png,
-                                              gfx::Rect(snapshot_size))) {
-    std::string base64_data;
-    base::Base64Encode(
-        base::StringPiece(reinterpret_cast<char*>(&*png.begin()), png.size()),
-        &base64_data);
-    base::DictionaryValue* result = new base::DictionaryValue();
-    result->SetString(
-        devtools::Page::captureScreenshot::kResponseData, base64_data);
-    return command->SuccessResponse(result);
+  std::vector<unsigned char> png_data;
+  if (ui::GrabViewSnapshot(host->GetView()->GetNativeView(),
+                           &png_data,
+                           snapshot_bounds)) {
+    if (png_data.size())
+      return command->SuccessResponse(CreateScreenshotResponse(png_data));
+    else
+      return command->InternalErrorResponse("Unable to capture screenshot");
   }
 
-  // Fallback to copying from compositing surface.
-  RenderWidgetHostViewPort* view_port =
-      RenderWidgetHostViewPort::FromRWHV(host->GetView());
-
-  view_port->CopyFromCompositingSurface(
-      view_bounds, snapshot_size,
+  ui::GrabViewSnapshotAsync(
+      host->GetView()->GetNativeView(),
+      snapshot_bounds,
+      base::ThreadTaskRunnerHandle::Get(),
       base::Bind(&RendererOverridesHandler::ScreenshotCaptured,
-                 weak_factory_.GetWeakPtr(), command, format, quality,
-                 last_compositor_frame_metadata_),
-      SkBitmap::kARGB_8888_Config);
+                 weak_factory_.GetWeakPtr(), command));
   return command->AsyncResponsePromise();
 }
 
+void RendererOverridesHandler::ScreenshotCaptured(
+    scoped_refptr<DevToolsProtocol::Command> command,
+    scoped_refptr<base::RefCountedBytes> png_data) {
+  if (png_data) {
+    SendAsyncResponse(
+        command->SuccessResponse(CreateScreenshotResponse(png_data->data())));
+  } else {
+    SendAsyncResponse(
+        command->InternalErrorResponse("Unable to capture screenshot"));
+  }
+}
+
 scoped_refptr<DevToolsProtocol::Response>
 RendererOverridesHandler::PageCanScreencast(
     scoped_refptr<DevToolsProtocol::Command> command) {
@@ -499,18 +509,14 @@
   return command->SuccessResponse(NULL);
 }
 
-void RendererOverridesHandler::ScreenshotCaptured(
-    scoped_refptr<DevToolsProtocol::Command> command,
+void RendererOverridesHandler::ScreencastFrameCaptured(
     const std::string& format,
     int quality,
     const cc::CompositorFrameMetadata& metadata,
     bool success,
     const SkBitmap& bitmap) {
   if (!success) {
-    if (command) {
-      SendAsyncResponse(
-          command->InternalErrorResponse("Unable to capture screenshot"));
-    } else if (capture_retry_count_) {
+    if (capture_retry_count_) {
       --capture_retry_count_;
       base::MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
@@ -543,13 +549,8 @@
     encoded = false;
   }
 
-  if (!encoded) {
-    if (command) {
-      SendAsyncResponse(
-          command->InternalErrorResponse("Unable to encode screenshot"));
-    }
+  if (!encoded)
     return;
-  }
 
   std::string base_64_data;
   base::Base64Encode(
@@ -595,20 +596,11 @@
     response_metadata->Set(
         devtools::Page::ScreencastFrameMetadata::kParamViewport, viewport);
 
-    if (command) {
-      response->Set(devtools::Page::captureScreenshot::kResponseMetadata,
-                    response_metadata);
-    } else {
-      response->Set(devtools::Page::screencastFrame::kParamMetadata,
-                    response_metadata);
-    }
+    response->Set(devtools::Page::screencastFrame::kParamMetadata,
+                  response_metadata);
   }
 
-  if (command) {
-    SendAsyncResponse(command->SuccessResponse(response));
-  } else {
-    SendNotification(devtools::Page::screencastFrame::kName, response);
-  }
+  SendNotification(devtools::Page::screencastFrame::kName, response);
 }
 
 // Quota and Usage ------------------------------------------
diff --git a/content/browser/devtools/renderer_overrides_handler.h b/content/browser/devtools/renderer_overrides_handler.h
index cce3276..926af3b 100644
--- a/content/browser/devtools/renderer_overrides_handler.h
+++ b/content/browser/devtools/renderer_overrides_handler.h
@@ -7,6 +7,7 @@
 
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
+#include "base/memory/ref_counted_memory.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
@@ -43,6 +44,8 @@
   void ParseCaptureParameters(DevToolsProtocol::Command* command,
                               std::string* format, int* quality,
                               double* scale);
+  base::DictionaryValue* CreateScreenshotResponse(
+      const std::vector<unsigned char>& png_data);
 
   // DOM domain.
   scoped_refptr<DevToolsProtocol::Response>
@@ -75,6 +78,9 @@
 
   void ScreenshotCaptured(
       scoped_refptr<DevToolsProtocol::Command> command,
+      scoped_refptr<base::RefCountedBytes> png_data);
+
+  void ScreencastFrameCaptured(
       const std::string& format,
       int quality,
       const cc::CompositorFrameMetadata& metadata,
diff --git a/content/browser/devtools/renderer_overrides_handler_browsertest.cc b/content/browser/devtools/renderer_overrides_handler_browsertest.cc
index 3759fc0..d869d9d 100644
--- a/content/browser/devtools/renderer_overrides_handler_browsertest.cc
+++ b/content/browser/devtools/renderer_overrides_handler_browsertest.cc
@@ -8,9 +8,9 @@
 #include "content/browser/devtools/renderer_overrides_handler.h"
 #include "content/public/browser/devtools_agent_host.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 
 namespace content {
 
diff --git a/content/browser/devtools/worker_devtools_manager.cc b/content/browser/devtools/worker_devtools_manager.cc
index 00735f3..62f77e7 100644
--- a/content/browser/devtools/worker_devtools_manager.cc
+++ b/content/browser/devtools/worker_devtools_manager.cc
@@ -228,7 +228,7 @@
 WorkerDevToolsManager::~WorkerDevToolsManager() {
 }
 
-void WorkerDevToolsManager::WorkerCreated(
+bool WorkerDevToolsManager::WorkerCreated(
     WorkerProcessHost* worker,
     const WorkerProcessHost::WorkerInstance& instance) {
   for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin();
@@ -236,14 +236,13 @@
     if (instance.Matches(it->worker_url, it->worker_name,
                          instance.partition(),
                          instance.resource_context())) {
-      worker->Send(new DevToolsAgentMsg_PauseWorkerContextOnStart(
-          instance.worker_route_id()));
       WorkerId new_worker_id(worker->GetData().id, instance.worker_route_id());
       paused_workers_[new_worker_id] = it->old_worker_id;
       terminated_workers_.erase(it);
-      return;
+      return true;
     }
   }
+  return false;
 }
 
 void WorkerDevToolsManager::WorkerDestroyed(
diff --git a/content/browser/devtools/worker_devtools_manager.h b/content/browser/devtools/worker_devtools_manager.h
index 7ea8840..a70f178 100644
--- a/content/browser/devtools/worker_devtools_manager.h
+++ b/content/browser/devtools/worker_devtools_manager.h
@@ -40,7 +40,8 @@
                              const std::string& state);
 
   // Called on the IO thread.
-  void WorkerCreated(
+  // Returns true when the worker must be paused on start.
+  bool WorkerCreated(
       WorkerProcessHost* process,
       const WorkerProcessHost::WorkerInstance& instance);
   void WorkerDestroyed(WorkerProcessHost* process, int worker_route_id);
diff --git a/content/browser/dom_storage/dom_storage_browsertest.cc b/content/browser/dom_storage/dom_storage_browsertest.cc
index b2aa9f1..8d9e31d 100644
--- a/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -7,9 +7,9 @@
 #include "content/common/dom_storage/dom_storage_types.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
 
 namespace content {
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc
index 1bbef54..6aa94d9 100644
--- a/content/browser/download/download_browsertest.cc
+++ b/content/browser/download/download_browsertest.cc
@@ -25,6 +25,8 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/webplugininfo.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/download_test_observer.h"
 #include "content/public/test/test_file_error_injector.h"
 #include "content/public/test/test_utils.h"
@@ -32,8 +34,6 @@
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_download_manager_delegate.h"
 #include "content/shell/browser/shell_network_delegate.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/net/url_request_mock_http_job.h"
 #include "content/test/net/url_request_slow_download_job.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
diff --git a/content/browser/download/download_create_info.h b/content/browser/download/download_create_info.h
index e032fbf..e8e1443 100644
--- a/content/browser/download/download_create_info.h
+++ b/content/browser/download/download_create_info.h
@@ -45,6 +45,12 @@
   // The URL that referred us.
   GURL referrer_url;
 
+  // The URL of the tab that started us.
+  GURL tab_url;
+
+  // The referrer URL of the tab that started us.
+  GURL tab_referrer_url;
+
   // The time when the download started.
   base::Time start_time;
 
diff --git a/content/browser/download/download_item_impl.cc b/content/browser/download/download_item_impl.cc
index ebef253..cd2623e 100644
--- a/content/browser/download/download_item_impl.cc
+++ b/content/browser/download/download_item_impl.cc
@@ -175,6 +175,8 @@
               TARGET_DISPOSITION_PROMPT : TARGET_DISPOSITION_OVERWRITE),
       url_chain_(info.url_chain),
       referrer_url_(info.referrer_url),
+      tab_url_(info.tab_url),
+      tab_referrer_url_(info.tab_referrer_url),
       suggested_filename_(base::UTF16ToUTF8(info.save_info->suggested_name)),
       forced_file_path_(info.save_info->file_path),
       transition_type_(info.transition_type),
@@ -550,6 +552,14 @@
   return referrer_url_;
 }
 
+const GURL& DownloadItemImpl::GetTabUrl() const {
+  return tab_url_;
+}
+
+const GURL& DownloadItemImpl::GetTabReferrerUrl() const {
+  return tab_referrer_url_;
+}
+
 std::string DownloadItemImpl::GetSuggestedFilename() const {
   return suggested_filename_;
 }
diff --git a/content/browser/download/download_item_impl.h b/content/browser/download/download_item_impl.h
index f8f6cbc..e660262 100644
--- a/content/browser/download/download_item_impl.h
+++ b/content/browser/download/download_item_impl.h
@@ -111,6 +111,8 @@
   virtual const std::vector<GURL>& GetUrlChain() const OVERRIDE;
   virtual const GURL& GetOriginalUrl() const OVERRIDE;
   virtual const GURL& GetReferrerUrl() const OVERRIDE;
+  virtual const GURL& GetTabUrl() const OVERRIDE;
+  virtual const GURL& GetTabReferrerUrl() const OVERRIDE;
   virtual std::string GetSuggestedFilename() const OVERRIDE;
   virtual std::string GetContentDisposition() const OVERRIDE;
   virtual std::string GetMimeType() const OVERRIDE;
@@ -417,6 +419,12 @@
   // The URL of the page that initiated the download.
   GURL referrer_url_;
 
+  // The URL of the tab that initiated the download.
+  GURL tab_url_;
+
+  // The URL of the referrer of the tab that initiated the download.
+  GURL tab_referrer_url_;
+
   // Filename suggestion from DownloadSaveInfo. It could, among others, be the
   // suggested filename in 'download' attribute of an anchor. Details:
   // http://www.whatwg.org/specs/web-apps/current-work/#downloading-hyperlinks
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc
index 70a392f..5ab23a8 100644
--- a/content/browser/download/download_manager_impl_unittest.cc
+++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -132,6 +132,8 @@
   MOCK_CONST_METHOD0(GetURL, const GURL&());
   MOCK_CONST_METHOD0(GetOriginalUrl, const GURL&());
   MOCK_CONST_METHOD0(GetReferrerUrl, const GURL&());
+  MOCK_CONST_METHOD0(GetTabUrl, const GURL&());
+  MOCK_CONST_METHOD0(GetTabReferrerUrl, const GURL&());
   MOCK_CONST_METHOD0(GetSuggestedFilename, std::string());
   MOCK_CONST_METHOD0(GetContentDisposition, std::string());
   MOCK_CONST_METHOD0(GetMimeType, std::string());
@@ -404,11 +406,12 @@
   MOCK_METHOD2(GetMediaRequestContextForStoragePartition,
                net::URLRequestContextGetter*(
                    const base::FilePath& partition_path, bool in_memory));
-  MOCK_METHOD5(RequestMidiSysExPermission,
+  MOCK_METHOD6(RequestMidiSysExPermission,
                void(int render_process_id,
                     int render_view_id,
                     int bridge_id,
                     const GURL& requesting_frame,
+                    bool user_gesture,
                     const MidiSysExPermissionCallback& callback));
   MOCK_METHOD4(CancelMidiSysExPermissionRequest,
                void(int render_process_id,
diff --git a/content/browser/download/download_resource_handler.cc b/content/browser/download/download_resource_handler.cc
index ab9e19e..0a73a95 100644
--- a/content/browser/download/download_resource_handler.cc
+++ b/content/browser/download/download_resource_handler.cc
@@ -24,6 +24,8 @@
 #include "content/public/browser/download_interrupt_reasons.h"
 #include "content/public/browser/download_item.h"
 #include "content/public/browser/download_manager_delegate.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/common/resource_response.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -32,6 +34,12 @@
 #include "net/url_request/url_request_context.h"
 
 namespace content {
+
+struct DownloadResourceHandler::DownloadTabInfo {
+  GURL tab_url;
+  GURL tab_referrer_url;
+};
+
 namespace {
 
 void CallStartedCBOnUIThread(
@@ -49,6 +57,7 @@
 // DownloadResourceHandler members from the UI thread.
 static void StartOnUIThread(
     scoped_ptr<DownloadCreateInfo> info,
+    DownloadResourceHandler::DownloadTabInfo* tab_info,
     scoped_ptr<ByteStreamReader> stream,
     const DownloadUrlParameters::OnStartedCallback& started_cb) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
@@ -66,9 +75,27 @@
     return;
   }
 
+  info->tab_url = tab_info->tab_url;
+  info->tab_referrer_url = tab_info->tab_referrer_url;
+
   download_manager->StartDownload(info.Pass(), stream.Pass(), started_cb);
 }
 
+void InitializeDownloadTabInfoOnUIThread(
+    const DownloadRequestHandle& request_handle,
+    DownloadResourceHandler::DownloadTabInfo* tab_info) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+  WebContents* web_contents = request_handle.GetWebContents();
+  if (web_contents) {
+    NavigationEntry* entry = web_contents->GetController().GetVisibleEntry();
+    if (entry) {
+      tab_info->tab_url = entry->GetURL();
+      tab_info->tab_referrer_url = entry->GetReferrer().url;
+    }
+  }
+}
+
 }  // namespace
 
 const int DownloadResourceHandler::kDownloadByteStreamSize = 100 * 1024;
@@ -88,6 +115,20 @@
       was_deferred_(false),
       on_response_started_called_(false) {
   RecordDownloadCount(UNTHROTTLED_COUNT);
+
+  // Do UI thread initialization asap after DownloadResourceHandler creation
+  // since the tab could be navigated before StartOnUIThread gets called.
+  const ResourceRequestInfoImpl* request_info = GetRequestInfo();
+  tab_info_ = new DownloadTabInfo();
+  BrowserThread::PostTask(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&InitializeDownloadTabInfoOnUIThread,
+                 DownloadRequestHandle(AsWeakPtr(),
+                                       request_info->GetChildID(),
+                                       request_info->GetRouteID(),
+                                       request_info->GetRequestID()),
+                 tab_info_));
 }
 
 bool DownloadResourceHandler::OnUploadProgress(int request_id,
@@ -198,11 +239,14 @@
       BrowserThread::UI, FROM_HERE,
       base::Bind(&StartOnUIThread,
                  base::Passed(&info),
+                 base::Owned(tab_info_),
                  base::Passed(&stream_reader),
                  // Pass to StartOnUIThread so that variable
                  // access is always on IO thread but function
                  // is called on UI thread.
                  started_cb_));
+  // Now owned by the task that was just posted.
+  tab_info_ = NULL;
   // Guaranteed to be called in StartOnUIThread
   started_cb_.Reset();
 
@@ -482,6 +526,11 @@
   if (stream_writer_)
     stream_writer_->RegisterCallback(base::Closure());
 
+  // tab_info_ must be destroyed on UI thread, since
+  // InitializeDownloadTabInfoOnUIThread might still be using it.
+  if (tab_info_)
+    BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, tab_info_);
+
   UMA_HISTOGRAM_TIMES("SB2.DownloadDuration",
                       base::TimeTicks::Now() - download_start_time_);
 }
diff --git a/content/browser/download/download_resource_handler.h b/content/browser/download/download_resource_handler.h
index 2c1d477..52c5ce3 100644
--- a/content/browser/download/download_resource_handler.h
+++ b/content/browser/download/download_resource_handler.h
@@ -32,6 +32,8 @@
     : public ResourceHandler,
       public base::SupportsWeakPtr<DownloadResourceHandler> {
  public:
+  struct DownloadTabInfo;
+
   // Size of the buffer used between the DownloadResourceHandler and the
   // downstream receiver of its output.
   static const int kDownloadByteStreamSize;
@@ -109,6 +111,12 @@
   DownloadUrlParameters::OnStartedCallback started_cb_;
   scoped_ptr<DownloadSaveInfo> save_info_;
 
+  // Stores information about the download that must be acquired on the UI
+  // thread before StartOnUIThread is called.
+  // Created on IO thread, but only accessed on UI thread. |tab_info_| holds
+  // the pointer until we pass it off to StartOnUIThread or DeleteSoon.
+  DownloadTabInfo* tab_info_;
+
   // Data flow
   scoped_refptr<net::IOBuffer> read_buffer_;       // From URLRequest.
   scoped_ptr<ByteStreamWriter> stream_writer_; // To rest of system.
diff --git a/content/browser/download/drag_download_file_browsertest.cc b/content/browser/download/drag_download_file_browsertest.cc
index 5ea0e57..986171d 100644
--- a/content/browser/download/drag_download_file_browsertest.cc
+++ b/content/browser/download/drag_download_file_browsertest.cc
@@ -14,13 +14,13 @@
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/power_save_blocker.h"
 #include "content/public/common/content_client.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/download_test_observer.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_download_manager_delegate.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/net/url_request_mock_http_job.h"
 #include "content/test/net/url_request_slow_download_job.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/content/browser/download/mhtml_generation_browsertest.cc b/content/browser/download/mhtml_generation_browsertest.cc
index 11a0851..283e53a 100644
--- a/content/browser/download/mhtml_generation_browsertest.cc
+++ b/content/browser/download/mhtml_generation_browsertest.cc
@@ -8,10 +8,10 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/content/browser/download/save_package_browsertest.cc b/content/browser/download/save_package_browsertest.cc
index 3910332..2c7a652 100644
--- a/content/browser/download/save_package_browsertest.cc
+++ b/content/browser/download/save_package_browsertest.cc
@@ -4,9 +4,9 @@
 
 #include "base/files/scoped_temp_dir.h"
 #include "content/browser/download/save_package.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 
 namespace content {
 
diff --git a/content/browser/fileapi/file_system_browsertest.cc b/content/browser/fileapi/file_system_browsertest.cc
index a3a83ef..51fc416 100644
--- a/content/browser/fileapi/file_system_browsertest.cc
+++ b/content/browser/fileapi/file_system_browsertest.cc
@@ -13,9 +13,9 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "webkit/browser/quota/quota_manager.h"
 
 using quota::QuotaManager;
diff --git a/content/browser/fileapi/fileapi_message_filter.cc b/content/browser/fileapi/fileapi_message_filter.cc
index eaf5fa1..7dcaa63 100644
--- a/content/browser/fileapi/fileapi_message_filter.cc
+++ b/content/browser/fileapi/fileapi_message_filter.cc
@@ -733,7 +733,8 @@
     const std::vector<fileapi::DirectoryEntry>& entries,
     bool has_more) {
   if (result == base::File::FILE_OK) {
-    Send(new FileSystemMsg_DidReadDirectory(request_id, entries, has_more));
+    if (!entries.empty() || !has_more)
+      Send(new FileSystemMsg_DidReadDirectory(request_id, entries, has_more));
   } else {
     DCHECK(!has_more);
     Send(new FileSystemMsg_DidFail(request_id, result));
diff --git a/content/browser/frame_host/frame_tree_browsertest.cc b/content/browser/frame_host/frame_tree_browsertest.cc
index 150abff..bc5f1cb 100644
--- a/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/content/browser/frame_host/frame_tree_browsertest.cc
@@ -10,11 +10,11 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
 
 namespace content {
diff --git a/content/browser/frame_host/interstitial_page_impl.cc b/content/browser/frame_host/interstitial_page_impl.cc
index af32c0d..fd93639 100644
--- a/content/browser/frame_host/interstitial_page_impl.cc
+++ b/content/browser/frame_host/interstitial_page_impl.cc
@@ -77,6 +77,7 @@
   explicit InterstitialPageRVHDelegateView(InterstitialPageImpl* page);
 
   // RenderViewHostDelegateView implementation:
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
   virtual void ShowPopupMenu(const gfx::Rect& bounds,
                              int item_height,
                              double item_font_size,
@@ -84,6 +85,8 @@
                              const std::vector<MenuItem>& items,
                              bool right_aligned,
                              bool allow_multiple_selection) OVERRIDE;
+  virtual void HidePopupMenu() OVERRIDE;
+#endif
   virtual void StartDragging(const DropData& drop_data,
                              WebDragOperationsMask operations_allowed,
                              const gfx::ImageSkia& image,
@@ -455,7 +458,7 @@
   // an interstitial would hang.
   web_contents_was_loading_ = controller_->delegate()->IsLoading();
   controller_->delegate()->SetIsLoading(
-      controller_->delegate()->GetRenderViewHost(), false, NULL);
+      controller_->delegate()->GetRenderViewHost(), false, true, NULL);
 }
 
 void InterstitialPageImpl::UpdateTitle(
@@ -600,7 +603,7 @@
   // Resumes the throbber, if applicable.
   if (web_contents_was_loading_)
     controller_->delegate()->SetIsLoading(
-        controller_->delegate()->GetRenderViewHost(), true, NULL);
+        controller_->delegate()->GetRenderViewHost(), true, true, NULL);
 
   // If this is a new navigation, the old page is going away, so we cancel any
   // blocked requests for it.  If it is not a new navigation, then it means the
@@ -846,6 +849,7 @@
     : interstitial_page_(page) {
 }
 
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
 void InterstitialPageImpl::InterstitialPageRVHDelegateView::ShowPopupMenu(
     const gfx::Rect& bounds,
     int item_height,
@@ -857,6 +861,11 @@
   NOTREACHED() << "InterstitialPage does not support showing popup menus.";
 }
 
+void InterstitialPageImpl::InterstitialPageRVHDelegateView::HidePopupMenu() {
+  NOTREACHED() << "InterstitialPage does not support showing popup menus.";
+}
+#endif
+
 void InterstitialPageImpl::InterstitialPageRVHDelegateView::StartDragging(
     const DropData& drop_data,
     WebDragOperationsMask allowed_operations,
diff --git a/content/browser/frame_host/navigation_controller_delegate.h b/content/browser/frame_host/navigation_controller_delegate.h
index 404e927..77bc622 100644
--- a/content/browser/frame_host/navigation_controller_delegate.h
+++ b/content/browser/frame_host/navigation_controller_delegate.h
@@ -71,6 +71,7 @@
   virtual void DetachInterstitialPage() = 0;
   virtual void SetIsLoading(RenderViewHost* render_view_host,
                             bool is_loading,
+                            bool to_different_document,
                             LoadNotificationDetails* details) = 0;
 };
 
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 91a69f8..70f447e 100644
--- a/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
+#include "content/browser/frame_host/cross_site_transferring_request.h"
 #include "content/browser/frame_host/navigation_controller_impl.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
@@ -956,7 +957,6 @@
   // It may abort before committing, if it's a download or due to a stop or
   // a new navigation from the user.
   FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
-  params.is_main_frame = true;
   params.error_code = net::ERR_ABORTED;
   params.error_description = base::string16();
   params.url = kNewURL;
@@ -1033,7 +1033,6 @@
   // It may abort before committing, if it's a download or due to a stop or
   // a new navigation from the user.
   FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
-  params.is_main_frame = true;
   params.error_code = net::ERR_ABORTED;
   params.error_description = base::string16();
   params.url = kRedirectURL;
@@ -1062,6 +1061,7 @@
   NavigationControllerImpl& controller = controller_impl();
   TestNotificationTracker notifications;
   RegisterForAllNavNotifications(&notifications, &controller);
+  std::vector<GURL> url_chain;
 
   const GURL url1("http://foo1");
   const GURL url2("http://foo2");
@@ -1088,14 +1088,18 @@
       increment_active_view_count();
 
   // Navigate to a second URL, simulate the beforeunload ack for the cross-site
-  // transition, and set bindings on the pending RenderViewHost to simulate a
-  // privileged url.
+  // transition, run the unload handler, and set bindings on the pending
+  // RenderViewHost to simulate a privileged url.
   controller.LoadURL(url2, Referrer(), PAGE_TRANSITION_TYPED, std::string());
   orig_rvh->SendBeforeUnloadACK(true);
-  contents()->GetPendingRenderViewHost()->AllowBindings(1);
-  static_cast<TestRenderViewHost*>(
-      contents()->GetPendingRenderViewHost())->SendNavigate(1, url2);
-  orig_rvh->OnSwappedOut(false);
+  contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
+      contents()->GetRenderManagerForTesting()->pending_frame_host(),
+      GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
+      url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
+  TestRenderViewHost* new_rvh =
+      static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+  new_rvh->AllowBindings(1);
+  new_rvh->SendNavigate(1, url2);
 
   // The second load should be committed, and bindings should be remembered.
   EXPECT_EQ(controller.GetEntryCount(), 2);
@@ -1106,6 +1110,11 @@
 
   // Going back, the first entry should still appear unprivileged.
   controller.GoBack();
+  new_rvh->SendBeforeUnloadACK(true);
+  contents()->GetRenderManagerForTesting()->OnCrossSiteResponse(
+      contents()->GetRenderManagerForTesting()->pending_frame_host(),
+      GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
+      url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
   orig_rvh->SendNavigate(0, url1);
   EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
   EXPECT_EQ(0, NavigationEntryImpl::FromNavigationEntry(
@@ -2427,7 +2436,6 @@
   // This pending navigation may have caused a different navigation to fail,
   // which causes the pending entry to be cleared.
   FrameHostMsg_DidFailProvisionalLoadWithError_Params fail_load_params;
-  fail_load_params.is_main_frame = true;
   fail_load_params.error_code = net::ERR_ABORTED;
   fail_load_params.error_description = base::string16();
   fail_load_params.url = url;
@@ -2745,7 +2753,7 @@
 
   // We create pending entries for renderer-initiated navigations so that we
   // can show them in new tabs when it is safe.
-  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, true, url1);
+  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url1);
 
   // Simulate what happens if a BrowserURLHandler rewrites the URL, causing
   // the virtual URL to differ from the URL.
@@ -2759,7 +2767,7 @@
           is_renderer_initiated());
 
   // If the user clicks another link, we should replace the pending entry.
-  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, true, url2);
+  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url2);
   EXPECT_EQ(url2, controller.GetPendingEntry()->GetURL());
   EXPECT_EQ(url2, controller.GetPendingEntry()->GetVirtualURL());
 
@@ -2769,18 +2777,18 @@
   EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetVirtualURL());
 
   // We should not replace the pending entry for an error URL.
-  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, true, url1);
+  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url1);
   EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
   navigator->DidStartProvisionalLoad(
-      main_test_rfh(), -1, true, GURL(kUnreachableWebDataURL));
+      main_test_rfh(), -1, GURL(kUnreachableWebDataURL));
   EXPECT_EQ(url1, controller.GetPendingEntry()->GetURL());
 
   // We should remember if the pending entry will replace the current one.
   // http://crbug.com/308444.
-  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, true, url1);
+  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url1);
   NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
       set_should_replace_entry(true);
-  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, true, url2);
+  navigator->DidStartProvisionalLoad(main_test_rfh(), -1, url2);
   EXPECT_TRUE(
       NavigationEntryImpl::FromNavigationEntry(controller.GetPendingEntry())->
           should_replace_entry());
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
index ef41e9d..5d7b904 100644
--- a/content/browser/frame_host/navigator.h
+++ b/content/browser/frame_host/navigator.h
@@ -37,7 +37,6 @@
   // The RenderFrameHostImpl started a provisional load.
   virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
                                        int parent_routing_id,
-                                       bool main_frame,
                                        const GURL& url) {};
 
   // The RenderFrameHostImpl has failed a provisional load.
@@ -49,7 +48,6 @@
   virtual void DidFailLoadWithError(
       RenderFrameHostImpl* render_frame_host,
       const GURL& url,
-      bool is_main_frame,
       int error_code,
       const base::string16& error_description) {}
 
diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h
index e6057ae..ab70aac 100644
--- a/content/browser/frame_host/navigator_delegate.h
+++ b/content/browser/frame_host/navigator_delegate.h
@@ -30,7 +30,6 @@
   virtual void DidStartProvisionalLoad(
       RenderFrameHostImpl* render_frame_host,
       int parent_routing_id,
-      bool is_main_frame,
       const GURL& validated_url,
       bool is_error_page,
       bool is_iframe_srcdoc) {}
@@ -44,7 +43,6 @@
   virtual void DidFailLoadWithError(
       RenderFrameHostImpl* render_frame_host,
       const GURL& url,
-      bool is_main_frame,
       int error_code,
       const base::string16& error_description) {}
 
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 12cd287..a983608 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -134,7 +134,6 @@
 void NavigatorImpl::DidStartProvisionalLoad(
     RenderFrameHostImpl* render_frame_host,
     int parent_routing_id,
-    bool is_main_frame,
     const GURL& url) {
   bool is_error_page = (url.spec() == kUnreachableWebDataURL);
   bool is_iframe_srcdoc = (url.spec() == kAboutSrcDocURL);
@@ -142,16 +141,9 @@
   RenderProcessHost* render_process_host = render_frame_host->GetProcess();
   render_process_host->FilterURL(false, &validated_url);
 
-  // TODO(creis): This is a hack for now, until we mirror the frame tree and do
-  // cross-process subframe navigations in actual subframes.  As a result, we
-  // can currently only support a single cross-process subframe per RVH.
+  bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
   NavigationEntryImpl* pending_entry =
       NavigationEntryImpl::FromNavigationEntry(controller_->GetPendingEntry());
-  if (pending_entry &&
-      pending_entry->frame_tree_node_id() != -1 &&
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
-    is_main_frame = false;
-
   if (is_main_frame) {
     // If there is no browser-initiated pending entry for this navigation and it
     // is not for the error URL, create a pending entry using the current
@@ -188,7 +180,7 @@
   if (delegate_) {
     // Notify the observer about the start of the provisional load.
     delegate_->DidStartProvisionalLoad(
-        render_frame_host, parent_routing_id, is_main_frame,
+        render_frame_host, parent_routing_id,
         validated_url, is_error_page, is_iframe_srcdoc);
   }
 }
@@ -200,7 +192,6 @@
   VLOG(1) << "Failed Provisional Load: " << params.url.possibly_invalid_spec()
           << ", error_code: " << params.error_code
           << ", error_description: " << params.error_description
-          << ", is_main_frame: " << params.is_main_frame
           << ", showing_repost_interstitial: " <<
             params.showing_repost_interstitial
           << ", frame_id: " << render_frame_host->GetRoutingID();
@@ -258,12 +249,11 @@
 void NavigatorImpl::DidFailLoadWithError(
     RenderFrameHostImpl* render_frame_host,
     const GURL& url,
-    bool is_main_frame,
     int error_code,
     const base::string16& error_description) {
   if (delegate_) {
     delegate_->DidFailLoadWithError(
-        render_frame_host, url, is_main_frame, error_code,
+        render_frame_host, url, error_code,
         error_description);
   }
 }
@@ -311,17 +301,8 @@
     return false;
   }
 
-  // Use entry->frame_tree_node_id() to pick which RenderFrameHostManager to
-  // use when --site-per-process is used.
   RenderFrameHostManager* manager =
       render_frame_host->frame_tree_node()->render_manager();
-  if (entry.frame_tree_node_id() != -1 &&
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
-    int64 frame_tree_node_id = entry.frame_tree_node_id();
-    manager = render_frame_host->frame_tree_node()->frame_tree()->FindByID(
-        frame_tree_node_id)->render_manager();
-  }
-
   RenderFrameHostImpl* dest_render_frame_host = manager->Navigate(entry);
   if (!dest_render_frame_host)
     return false;  // Unable to create the desired RenderFrameHost.
@@ -351,9 +332,6 @@
   current_load_start_ = base::TimeTicks::Now();
 
   // Navigate in the desired RenderFrameHost.
-  // TODO(creis): As a temporary hack, we currently do cross-process subframe
-  // navigations in a top-level frame of the new process.  Thus, we don't yet
-  // need to store the correct frame ID in FrameMsg_Navigate_Params.
   FrameMsg_Navigate_Params navigate_params;
   MakeNavigateParams(entry, *controller_, reload_type, &navigate_params);
   dest_render_frame_host->Navigate(navigate_params);
@@ -399,35 +377,21 @@
     const FrameHostMsg_DidCommitProvisionalLoad_Params& input_params) {
   FrameHostMsg_DidCommitProvisionalLoad_Params params(input_params);
   FrameTree* frame_tree = render_frame_host->frame_tree_node()->frame_tree();
-  RenderViewHostImpl* rvh = render_frame_host->render_view_host();
   bool use_site_per_process =
       CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess);
 
-  // When using --site-per-process, look up the FrameTreeNode ID that the
-  // renderer-specific frame ID corresponds to.
-  int64 frame_tree_node_id = frame_tree->root()->frame_tree_node_id();
   if (use_site_per_process) {
-    frame_tree_node_id =
-        render_frame_host->frame_tree_node()->frame_tree_node_id();
-
-    // TODO(creis): In the short term, cross-process subframe navigations are
-    // happening in the pending RenderViewHost's top-level frame.  (We need to
-    // both mirror the frame tree and get the navigation to occur in the correct
-    // subframe to fix this.)  Until then, we should check whether we have a
-    // pending NavigationEntry with a frame ID and if so, treat the
-    // cross-process "main frame" navigation as a subframe navigation.  This
-    // limits us to a single cross-process subframe per RVH, and it affects
-    // NavigateToEntry, NavigatorImpl::DidStartProvisionalLoad, and
-    // OnDidFinishLoad.
+    // TODO(creis): Until we mirror the frame tree in the subframe's process,
+    // cross-process subframe navigations happen in a renderer's main frame.
+    // Correct the transition type here if we know it is for a subframe.
     NavigationEntryImpl* pending_entry =
         NavigationEntryImpl::FromNavigationEntry(
             controller_->GetPendingEntry());
-    int root_ftn_id = frame_tree->root()->frame_tree_node_id();
-    if (pending_entry &&
-        pending_entry->frame_tree_node_id() != -1 &&
-        pending_entry->frame_tree_node_id() != root_ftn_id) {
+    if (!render_frame_host->frame_tree_node()->IsMainFrame() &&
+        pending_entry &&
+        pending_entry->frame_tree_node_id() ==
+            render_frame_host->frame_tree_node()->frame_tree_node_id()) {
       params.transition = PAGE_TRANSITION_AUTO_SUBFRAME;
-      frame_tree_node_id = pending_entry->frame_tree_node_id();
     }
   }
 
@@ -442,15 +406,14 @@
       controller_->TakeScreenshot();
 
     if (!use_site_per_process)
-      frame_tree->root()->render_manager()->DidNavigateMainFrame(rvh);
+      frame_tree->root()->render_manager()->DidNavigateFrame(render_frame_host);
   }
 
   // When using --site-per-process, we notify the RFHM for all navigations,
   // not just main frame navigations.
   if (use_site_per_process) {
-    FrameTreeNode* frame = frame_tree->FindByID(frame_tree_node_id);
-    // TODO(creis): Rename to DidNavigateFrame.
-    frame->render_manager()->DidNavigateMainFrame(rvh);
+    FrameTreeNode* frame = render_frame_host->frame_tree_node();
+    frame->render_manager()->DidNavigateFrame(render_frame_host);
   }
 
   // Update the site of the SiteInstance if it doesn't have one yet, unless
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index 6c3bee3..47c3f37 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -26,7 +26,6 @@
   // Navigator implementation.
   virtual void DidStartProvisionalLoad(RenderFrameHostImpl* render_frame_host,
                                        int parent_routing_id,
-                                       bool main_frame,
                                        const GURL& url) OVERRIDE;
   virtual void DidFailProvisionalLoadWithError(
       RenderFrameHostImpl* render_frame_host,
@@ -35,7 +34,6 @@
   virtual void DidFailLoadWithError(
       RenderFrameHostImpl* render_frame_host,
       const GURL& url,
-      bool is_main_frame,
       int error_code,
       const base::string16& error_description) OVERRIDE;
   virtual void DidRedirectProvisionalLoad(
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index b6ebfa9..1d32fb1 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -32,12 +32,18 @@
 
   // The top-level RenderFrame began loading a new page. This corresponds to
   // Blink's notion of the throbber starting.
-  virtual void DidStartLoading(RenderFrameHost* render_frame_host) {}
+  // |to_different_document| will be true unless the load is a fragment
+  // navigation, or triggered by history.pushState/replaceState.
+  virtual void DidStartLoading(RenderFrameHost* render_frame_host,
+                               bool to_different_document) {}
 
   // The top-level RenderFrame stopped loading a page. This corresponds to
   // Blink's notion of the throbber stopping.
   virtual void DidStopLoading(RenderFrameHost* render_frame_host) {}
 
+  // The RenderFrameHost has been swapped out.
+  virtual void SwappedOut(RenderFrameHost* render_frame_host) {}
+
   // Notification that a worker process has crashed.
   virtual void WorkerCrashed(RenderFrameHost* render_frame_host) {}
 
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 4ed8a4c..cb4adee 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -14,6 +14,8 @@
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/navigator.h"
 #include "content/browser/frame_host/render_frame_host_delegate.h"
+#include "content/browser/renderer_host/input/input_router.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/common/frame_messages.h"
 #include "content/common/input_messages.h"
@@ -183,6 +185,16 @@
   Send(new FrameMsg_CustomContextMenuAction(routing_id_, context, action));
 }
 
+void RenderFrameHostImpl::Undo() {
+  Send(new InputMsg_Undo(routing_id_));
+  RecordAction(base::UserMetricsAction("Undo"));
+}
+
+void RenderFrameHostImpl::Redo() {
+  Send(new InputMsg_Redo(routing_id_));
+  RecordAction(base::UserMetricsAction("Redo"));
+}
+
 void RenderFrameHostImpl::Cut() {
   Send(new InputMsg_Cut(routing_id_));
   RecordAction(base::UserMetricsAction("Cut"));
@@ -193,11 +205,39 @@
   RecordAction(base::UserMetricsAction("Copy"));
 }
 
+void RenderFrameHostImpl::CopyToFindPboard() {
+#if defined(OS_MACOSX)
+  // Windows/Linux don't have the concept of a find pasteboard.
+  Send(new InputMsg_CopyToFindPboard(routing_id_));
+  RecordAction(base::UserMetricsAction("CopyToFindPboard"));
+#endif
+}
+
 void RenderFrameHostImpl::Paste() {
   Send(new InputMsg_Paste(routing_id_));
   RecordAction(base::UserMetricsAction("Paste"));
 }
 
+void RenderFrameHostImpl::PasteAndMatchStyle() {
+  Send(new InputMsg_PasteAndMatchStyle(routing_id_));
+  RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
+}
+
+void RenderFrameHostImpl::Delete() {
+  Send(new InputMsg_Delete(routing_id_));
+  RecordAction(base::UserMetricsAction("DeleteSelection"));
+}
+
+void RenderFrameHostImpl::SelectAll() {
+  Send(new InputMsg_SelectAll(routing_id_));
+  RecordAction(base::UserMetricsAction("SelectAll"));
+}
+
+void RenderFrameHostImpl::Unselect() {
+  Send(new InputMsg_Unselect(routing_id_));
+  RecordAction(base::UserMetricsAction("Unselect"));
+}
+
 void RenderFrameHostImpl::InsertCSS(const std::string& css) {
   Send(new FrameMsg_CSSInsertRequest(routing_id_, css));
 }
@@ -225,6 +265,11 @@
 }
 
 bool RenderFrameHostImpl::Send(IPC::Message* message) {
+  if (IPC_MESSAGE_ID_CLASS(message->type()) == InputMsgStart) {
+    return render_view_host_->input_router()->SendInput(
+        make_scoped_ptr(message));
+  }
+
   return GetProcess()->Send(message);
 }
 
@@ -323,10 +368,9 @@
 
 void RenderFrameHostImpl::OnDidStartProvisionalLoadForFrame(
     int parent_routing_id,
-    bool is_main_frame,
     const GURL& url) {
   frame_tree_node_->navigator()->DidStartProvisionalLoad(
-      this, parent_routing_id, is_main_frame, url);
+      this, parent_routing_id, url);
 }
 
 void RenderFrameHostImpl::OnDidFailProvisionalLoadWithError(
@@ -336,15 +380,13 @@
 
 void RenderFrameHostImpl::OnDidFailLoadWithError(
     const GURL& url,
-    bool is_main_frame,
     int error_code,
     const base::string16& error_description) {
   GURL validated_url(url);
   GetProcess()->FilterURL(false, &validated_url);
 
   frame_tree_node_->navigator()->DidFailLoadWithError(
-      this, validated_url, is_main_frame, error_code,
-      error_description);
+      this, validated_url, error_code, error_description);
 }
 
 void RenderFrameHostImpl::OnDidRedirectProvisionalLoad(
@@ -455,17 +497,33 @@
 }
 
 void RenderFrameHostImpl::SwapOut() {
-  if (render_view_host_->IsRenderViewLive()) {
-    Send(new FrameMsg_SwapOut(routing_id_));
-  } else {
-    // Our RenderViewHost doesn't have a live renderer, so just skip the unload
-    // event.
-    OnSwappedOut(true);
+  // TODO(creis): Move swapped out state to RFH.  Until then, only update it
+  // when swapping out the main frame.
+  if (!GetParent()) {
+    // If this RenderViewHost is not in the default state, it must have already
+    // gone through this, therefore just return.
+    if (render_view_host_->rvh_state_ != RenderViewHostImpl::STATE_DEFAULT)
+      return;
+
+    render_view_host_->SetState(
+        RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK);
+    render_view_host_->unload_event_monitor_timeout_->Start(
+        base::TimeDelta::FromMilliseconds(
+            RenderViewHostImpl::kUnloadTimeoutMS));
   }
+
+  if (render_view_host_->IsRenderViewLive())
+    Send(new FrameMsg_SwapOut(routing_id_));
+
+  if (!GetParent())
+    delegate_->SwappedOut(this);
+
+  // Allow the navigation to proceed.
+  frame_tree_node_->render_manager()->SwappedOut(this);
 }
 
-void RenderFrameHostImpl::OnDidStartLoading() {
-  delegate_->DidStartLoading(this);
+void RenderFrameHostImpl::OnDidStartLoading(bool to_different_document) {
+  delegate_->DidStartLoading(this, to_different_document);
 }
 
 void RenderFrameHostImpl::OnDidStopLoading() {
@@ -526,7 +584,12 @@
 }
 
 void RenderFrameHostImpl::OnSwappedOut(bool timed_out) {
-  frame_tree_node_->render_manager()->SwappedOutFrame(this);
+  // For now, we only need to update the RVH state machine for top-level swaps.
+  // Subframe swaps (in --site-per-process) can just continue via RFHM.
+  if (!GetParent())
+    render_view_host_->OnSwappedOut(timed_out);
+  else
+    frame_tree_node_->render_manager()->SwappedOut(this);
 }
 
 void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
@@ -623,7 +686,7 @@
   // Blink doesn't send throb notifications for JavaScript URLs, so we
   // don't want to either.
   if (!params.url.SchemeIs(kJavaScriptScheme))
-    delegate_->DidStartLoading(this);
+    delegate_->DidStartLoading(this, true);
 }
 
 void RenderFrameHostImpl::NavigateToURL(const GURL& url) {
@@ -638,4 +701,14 @@
   Navigate(params);
 }
 
+void RenderFrameHostImpl::SelectRange(const gfx::Point& start,
+                                      const gfx::Point& end) {
+  Send(new InputMsg_SelectRange(routing_id_, start, end));
+}
+
+void RenderFrameHostImpl::ExtendSelectionAndDelete(size_t before,
+                                                   size_t after) {
+  Send(new FrameMsg_ExtendSelectionAndDelete(routing_id_, before, after));
+}
+
 }  // namespace content
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index c268416..f313066 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -26,6 +26,10 @@
 class ListValue;
 }
 
+namespace gfx {
+class Point;
+}
+
 namespace content {
 
 class CrossProcessFrameConnector;
@@ -59,9 +63,16 @@
       const CustomContextMenuContext& context) OVERRIDE;
   virtual void ExecuteCustomContextMenuCommand(
       int action, const CustomContextMenuContext& context) OVERRIDE;
+  virtual void Undo() OVERRIDE;
+  virtual void Redo() OVERRIDE;
   virtual void Cut() OVERRIDE;
   virtual void Copy() OVERRIDE;
+  virtual void CopyToFindPboard() OVERRIDE;
   virtual void Paste() OVERRIDE;
+  virtual void PasteAndMatchStyle() OVERRIDE;
+  virtual void Delete() OVERRIDE;
+  virtual void SelectAll() OVERRIDE;
+  virtual void Unselect() OVERRIDE;
   virtual void InsertCSS(const std::string& css) OVERRIDE;
   virtual void ExecuteJavaScript(
       const base::string16& javascript) OVERRIDE;
@@ -114,9 +125,14 @@
       PageTransition page_transition,
       bool should_replace_current_entry);
 
-  // Hack to get this subframe to swap out, without yet moving over all the
-  // SwapOut state and machinery from RenderViewHost.
+  // Tells the renderer that this RenderFrame is being swapped out for one in a
+  // different renderer process.  It should run its unload handler and move to
+  // a blank document.  The renderer should preserve the Frame object until it
+  // exits, in case we come back.  The renderer can exit if it has no other
+  // active RenderFrames, but not until WasSwappedOut is called (when it is no
+  // longer visible).
   void SwapOut();
+
   void OnSwappedOut(bool timed_out);
   bool is_swapped_out() { return is_swapped_out_; }
   void set_swapped_out(bool is_swapped_out) {
@@ -129,7 +145,9 @@
 
   // TODO(nasko): This method is public so RenderViewHostImpl::Navigate can
   // call it directly. It should be made private once Navigate moves here.
-  void OnDidStartLoading();
+  // |to_different_document| will be true unless the load is a fragment
+  // navigation, or triggered by history.pushState/replaceState.
+  void OnDidStartLoading(bool to_different_document);
 
   // Sends the given navigation message. Use this rather than sending it
   // yourself since this does the internal bookkeeping described below. This
@@ -143,6 +161,13 @@
   // Load the specified URL; this is a shortcut for Navigate().
   void NavigateToURL(const GURL& url);
 
+  // Requests the renderer to select the region between two points.
+  void SelectRange(const gfx::Point& start, const gfx::Point& end);
+
+  // Deletes the current selection plus the specified number of characters
+  // before and after the selection or caret.
+  void ExtendSelectionAndDelete(size_t before, size_t after);
+
  protected:
   friend class RenderFrameHostFactory;
 
@@ -165,13 +190,11 @@
   void OnFrameFocused();
   void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
   void OnDidStartProvisionalLoadForFrame(int parent_routing_id,
-                                         bool main_frame,
                                          const GURL& url);
   void OnDidFailProvisionalLoadWithError(
       const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params);
   void OnDidFailLoadWithError(
       const GURL& url,
-      bool is_main_frame,
       int error_code,
       const base::string16& error_description);
   void OnDidRedirectProvisionalLoad(int32 page_id,
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index d697e18..b9c5be3 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -184,7 +184,7 @@
   if (!dest_render_frame_host->render_view_host()->IsRenderViewLive()) {
     // Recreate the opener chain.
     int opener_route_id = delegate_->CreateOpenerRenderViewsForRenderManager(
-        dest_render_frame_host->render_view_host()->GetSiteInstance());
+        dest_render_frame_host->GetSiteInstance());
     if (!InitRenderView(dest_render_frame_host->render_view_host(),
                         opener_route_id))
       return NULL;
@@ -344,14 +344,13 @@
   SwapOutOldPage();
 }
 
-// TODO(creis): Remove this in favor of SwappedOutFrame.
-void RenderFrameHostManager::SwappedOut(RenderViewHost* render_view_host) {
-  // Make sure this is from our current RVH, and that we have a pending
+void RenderFrameHostManager::SwappedOut(
+    RenderFrameHostImpl* render_frame_host) {
+  // Make sure this is from our current RFH, and that we have a pending
   // navigation from OnCrossSiteResponse.  (There may be no pending navigation
   // for data URLs that don't make network requests, for example.)   If not,
   // just return early and ignore.
-  if (render_view_host != render_frame_host_->render_view_host() ||
-      !pending_nav_params_.get()) {
+  if (render_frame_host != render_frame_host_ || !pending_nav_params_.get()) {
     pending_nav_params_.reset();
     return;
   }
@@ -362,18 +361,26 @@
   // we can shorten this by delivering the response directly, rather than
   // forcing an identical request to be made.
   if (pending_nav_params_->cross_site_transferring_request) {
+    // Sanity check that the params are for the correct frame and process.
+    // These should match the RenderFrameHost that made the request.
+    // If it started as a cross-process navigation via OpenURL, this is the
+    // pending one.  If it wasn't cross-process until the transfer, this is the
+    // current one.
+    int render_frame_id = pending_render_frame_host_ ?
+        pending_render_frame_host_->GetRoutingID() :
+        render_frame_host_->GetRoutingID();
+    DCHECK_EQ(render_frame_id, pending_nav_params_->render_frame_id);
+    int process_id = pending_render_frame_host_ ?
+        pending_render_frame_host_->GetProcess()->GetID() :
+        render_frame_host_->GetProcess()->GetID();
+    DCHECK_EQ(process_id, pending_nav_params_->global_request_id.child_id);
+
     // Treat the last URL in the chain as the destination and the remainder as
     // the redirect chain.
     CHECK(pending_nav_params_->transfer_url_chain.size());
     GURL transfer_url = pending_nav_params_->transfer_url_chain.back();
     pending_nav_params_->transfer_url_chain.pop_back();
 
-    // We use GetMainFrame here because this version of SwappedOut is only
-    // called for the main frame.  We will remove it in favor of the frame
-    // specific version.
-    RenderFrameHostImpl* render_frame_host =
-        static_cast<RenderFrameHostImpl*>(render_view_host->GetMainFrame());
-
     // We don't know whether the original request had |user_action| set to true.
     // However, since we force the navigation to be in the current tab, it
     // doesn't matter.
@@ -397,66 +404,13 @@
   pending_nav_params_.reset();
 }
 
-void RenderFrameHostManager::SwappedOutFrame(
+void RenderFrameHostManager::DidNavigateFrame(
     RenderFrameHostImpl* render_frame_host) {
-  // Make sure this is from our current RFH, and that we have a pending
-  // navigation from OnCrossSiteResponse.  (There may be no pending navigation
-  // for data URLs that don't make network requests, for example.)   If not,
-  // just return early and ignore.
-  if (render_frame_host != render_frame_host_ || !pending_nav_params_.get()) {
-    pending_nav_params_.reset();
-    return;
-  }
-
-  // Sanity check that this is for the correct frame.
-  DCHECK_EQ(render_frame_host_->GetRoutingID(),
-            pending_nav_params_->render_frame_id);
-  DCHECK_EQ(render_frame_host_->GetProcess()->GetID(),
-            pending_nav_params_->global_request_id.child_id);
-
-  // Now that the unload handler has run, we need to either initiate the
-  // pending transfer (if there is one) or resume the paused response (if not).
-  // TODO(creis): The blank swapped out page is visible during this time, but
-  // we can shorten this by delivering the response directly, rather than
-  // forcing an identical request to be made.
-  if (pending_nav_params_->cross_site_transferring_request) {
-    // Treat the last URL in the chain as the destination and the remainder as
-    // the redirect chain.
-    CHECK(pending_nav_params_->transfer_url_chain.size());
-    GURL transfer_url = pending_nav_params_->transfer_url_chain.back();
-    pending_nav_params_->transfer_url_chain.pop_back();
-
-    // We don't know whether the original request had |user_action| set to true.
-    // However, since we force the navigation to be in the current tab, it
-    // doesn't matter.
-    render_frame_host_->frame_tree_node()->navigator()->RequestTransferURL(
-        render_frame_host,
-        transfer_url,
-        pending_nav_params_->transfer_url_chain,
-        pending_nav_params_->referrer,
-        pending_nav_params_->page_transition,
-        CURRENT_TAB,
-        pending_nav_params_->global_request_id,
-        false,
-        true);
-  } else if (pending_render_frame_host_) {
-    RenderProcessHostImpl* pending_process =
-        static_cast<RenderProcessHostImpl*>(
-            pending_render_frame_host_->GetProcess());
-    pending_process->ResumeDeferredNavigation(
-        pending_nav_params_->global_request_id);
-  }
-  pending_nav_params_.reset();
-}
-
-// TODO(creis): This should take in a RenderFrameHost.
-void RenderFrameHostManager::DidNavigateMainFrame(
-    RenderViewHost* render_view_host) {
   if (!cross_navigation_pending_) {
     DCHECK(!pending_render_frame_host_);
 
     // We should only hear this from our current renderer.
-    DCHECK(render_view_host == render_frame_host_->render_view_host());
+    DCHECK_EQ(render_frame_host_, render_frame_host);
 
     // Even when there is no pending RVH, there may be a pending Web UI.
     if (pending_web_ui())
@@ -464,18 +418,22 @@
     return;
   }
 
-  if (render_view_host == pending_render_frame_host_->render_view_host()) {
+  if (render_frame_host == pending_render_frame_host_) {
     // The pending cross-site navigation completed, so show the renderer.
     // If it committed without sending network requests (e.g., data URLs),
     // then we still need to swap out the old RFH first and run its unload
-    // handler.  OK for that to happen in the background.
+    // handler, only if it hasn't happened yet.  OK for that to happen in the
+    // background.
     if (pending_render_frame_host_->render_view_host()->
-            HasPendingCrossSiteRequest())
+            HasPendingCrossSiteRequest() &&
+        pending_render_frame_host_->render_view_host()->rvh_state() ==
+            RenderViewHostImpl::STATE_DEFAULT) {
       SwapOutOldPage();
+    }
 
     CommitPending();
     cross_navigation_pending_ = false;
-  } else if (render_view_host == render_frame_host_->render_view_host()) {
+  } else if (render_frame_host == render_frame_host_) {
     // A navigation in the original page has taken place.  Cancel the pending
     // one.
     CancelPending();
@@ -492,8 +450,8 @@
   for (RenderFrameHostMap::iterator iter = swapped_out_hosts_.begin();
        iter != swapped_out_hosts_.end();
        ++iter) {
-    DCHECK_NE(iter->second->render_view_host()->GetSiteInstance(),
-              current_host()->GetSiteInstance());
+    DCHECK_NE(iter->second->GetSiteInstance(),
+              current_frame_host()->GetSiteInstance());
     iter->second->render_view_host()->DisownOpener();
   }
 }
@@ -526,6 +484,7 @@
   // Tell the renderer to suppress any further modal dialogs so that we can swap
   // it out.  This must be done before canceling any current dialog, in case
   // there is a loop creating additional dialogs.
+  // TODO(creis): Handle modal dialogs in subframe processes.
   render_frame_host_->render_view_host()->SuppressDialogsUntilSwapOut();
 
   // Now close any modal dialogs that would prevent us from swapping out.  This
@@ -533,16 +492,7 @@
   // no longer on the stack when we send the SwapOut message.
   delegate_->CancelModalDialogsForRenderManager();
 
-  // Tell the old renderer it is being swapped out.  This will fire the unload
-  // handler (without firing the beforeunload handler a second time).  When the
-  // unload handler finishes and the navigation completes, we will send a
-  // message to the ResourceDispatcherHost, allowing the pending RVH's response
-  // to resume.
-  // Note: This must be done on the RFH or else we'll swap out the top-level
-  // page when subframes navigate.
-  if (frame_tree_node_->IsMainFrame()) {
-    render_frame_host_->render_view_host()->SwapOut();
-  } else {
+  if (!frame_tree_node_->IsMainFrame()) {
     // The RenderFrameHost being swapped out becomes the proxy for this
     // frame in its parent's process. CrossProcessFrameConnector
     // initialization only needs to happen on an initial cross-process
@@ -555,9 +505,14 @@
       cross_process_frame_connector_ =
           new CrossProcessFrameConnector(render_frame_host_.get());
     }
-    render_frame_host_->SwapOut();
   }
 
+  // Tell the old frame it is being swapped out.  This will fire the unload
+  // handler in the background (without firing the beforeunload handler a second
+  // time).  When the navigation completes, we will send a message to the
+  // ResourceDispatcherHost, allowing the pending RVH's response to resume.
+  render_frame_host_->SwapOut();
+
   // ResourceDispatcherHost has told us to run the onunload handler, which
   // means it is not a download or unsafe page, and we are going to perform the
   // navigation.  Thus, we no longer need to remember that the RenderFrameHost
@@ -661,7 +616,7 @@
   const GURL& current_url = (current_entry) ?
       SiteInstanceImpl::GetEffectiveURL(browser_context,
                                         current_entry->GetURL()) :
-      render_frame_host_->render_view_host()->GetSiteInstance()->GetSiteURL();
+      render_frame_host_->GetSiteInstance()->GetSiteURL();
   const GURL& new_url = SiteInstanceImpl::GetEffectiveURL(browser_context,
                                                           new_entry->GetURL());
 
@@ -691,7 +646,7 @@
   // Check with the content client as well.  Important to pass current_url here,
   // which uses the SiteInstance's site if there is no current_entry.
   if (GetContentClient()->browser()->ShouldSwapBrowsingInstancesForNavigation(
-          render_frame_host_->render_view_host()->GetSiteInstance(),
+          render_frame_host_->GetSiteInstance(),
           current_url, new_url)) {
     return true;
   }
@@ -929,7 +884,7 @@
 
   // We are creating a pending or swapped out RFH here.  We should never create
   // it in the same SiteInstance as our current RFH.
-  CHECK_NE(render_frame_host_->render_view_host()->GetSiteInstance(), instance);
+  CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
 
   // Check if we've already created an RFH for this SiteInstance.  If so, try
   // to re-use the existing one, which has already been initialized.  We'll
@@ -1083,7 +1038,7 @@
   // If the old view is live and top-level, hide it now that the new one is
   // visible.
   int32 old_site_instance_id =
-      old_render_frame_host->render_view_host()->GetSiteInstance()->GetId();
+      old_render_frame_host->GetSiteInstance()->GetId();
   if (old_render_frame_host->render_view_host()->GetView()) {
     if (is_main_frame) {
       old_render_frame_host->render_view_host()->GetView()->Hide();
@@ -1120,8 +1075,7 @@
   }
 
   // If the pending frame was on the swapped out list, we can remove it.
-  swapped_out_hosts_.erase(render_frame_host_->render_view_host()->
-                               GetSiteInstance()->GetId());
+  swapped_out_hosts_.erase(render_frame_host_->GetSiteInstance()->GetId());
 
   if (old_render_frame_host->render_view_host()->IsRenderViewLive()) {
     // If the old RFH is live, we are swapping it out and should keep track of
@@ -1167,8 +1121,7 @@
     // in this SiteInstance.  We do this after ensuring the RFH is on the
     // swapped out list to simplify the deletion.
     if (!static_cast<SiteInstanceImpl*>(
-            old_render_frame_host->render_view_host()->GetSiteInstance())->
-                active_view_count()) {
+            old_render_frame_host->GetSiteInstance())->active_view_count()) {
       ShutdownRenderFrameHostsInSiteInstance(old_site_instance_id);
       // This is deleted while cleaning up the SiteInstance's views.
       old_render_frame_host = NULL;
@@ -1219,8 +1172,7 @@
   // render_frame_host_'s SiteInstance and new_instance will not be deleted
   // before the end of this method, so we don't have to worry about their ref
   // counts dropping to zero.
-  SiteInstance* current_instance =
-      render_frame_host_->render_view_host()->GetSiteInstance();
+  SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
   SiteInstance* new_instance = current_instance;
 
   // We do not currently swap processes for navigations in webview tag guests.
@@ -1387,8 +1339,7 @@
     // Any currently suspended navigations are no longer needed.
     pending_render_frame_host->render_view_host()->CancelSuspendedNavigations();
 
-    // TODO(creis): We need to swap out the RFH.
-    pending_render_frame_host->render_view_host()->SwapOut();
+    pending_render_frame_host->SwapOut();
   } else {
     // We won't be coming back, so shut this one down.
     delete pending_render_frame_host;
@@ -1439,11 +1390,11 @@
 
 bool RenderFrameHostManager::IsOnSwappedOutList(
     RenderFrameHostImpl* rfh) const {
-  if (!rfh->render_view_host()->GetSiteInstance())
+  if (!rfh->GetSiteInstance())
     return false;
 
   RenderFrameHostMap::const_iterator iter = swapped_out_hosts_.find(
-      rfh->render_view_host()->GetSiteInstance()->GetId());
+      rfh->GetSiteInstance()->GetId());
   if (iter == swapped_out_hosts_.end())
     return false;
 
diff --git a/content/browser/frame_host/render_frame_host_manager.h b/content/browser/frame_host/render_frame_host_manager.h
index c2c11d6..b06e2e3 100644
--- a/content/browser/frame_host/render_frame_host_manager.h
+++ b/content/browser/frame_host/render_frame_host_manager.h
@@ -217,16 +217,12 @@
       PageTransition page_transition,
       bool should_replace_current_entry);
 
-  // The RenderViewHost has been swapped out, so we should resume the pending
-  // network response and allow the pending RenderViewHost to commit.
-  void SwappedOut(RenderViewHost* render_view_host);
-
   // The RenderFrameHost has been swapped out, so we should resume the pending
   // network response and allow the pending RenderFrameHost to commit.
-  void SwappedOutFrame(RenderFrameHostImpl* render_frame_host);
+  void SwappedOut(RenderFrameHostImpl* render_frame_host);
 
-  // Called when a renderer's main frame navigates.
-  void DidNavigateMainFrame(RenderViewHost* render_view_host);
+  // Called when a renderer's frame navigates.
+  void DidNavigateFrame(RenderFrameHostImpl* render_frame_host);
 
   // Called when a renderer sets its opener to null.
   void DidDisownOpener(RenderViewHost* render_view_host);
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index e1d9a9c..cb1901f 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -24,11 +24,11 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
@@ -391,7 +391,8 @@
 // Test that setting the opener to null in a window affects cross-process
 // navigations, including those to existing entries.  http://crbug.com/156669.
 // Flaky on windows: http://crbug.com/291249
-#if defined(OS_WIN)
+// This test also crashes under ThreadSanitizer, http://crbug.com/356758.
+#if defined(OS_WIN) || defined(THREAD_SANITIZER)
 #define MAYBE_DisownOpener DISABLED_DisownOpener
 #else
 #define MAYBE_DisownOpener DisownOpener
@@ -978,10 +979,16 @@
   EXPECT_FALSE(contents->GetController().GetVisibleEntry());
 }
 
+// Crashes under ThreadSanitizer, http://crbug.com/356758.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_BackForwardNotStale DISABLED_BackForwardNotStale
+#else
+#define MAYBE_BackForwardNotStale BackForwardNotStale
+#endif
 // Test for http://crbug.com/93427.  Ensure that cross-site navigations
 // do not cause back/forward navigations to be considered stale by the
 // renderer.
-IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, BackForwardNotStale) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_BackForwardNotStale) {
   StartServer();
   NavigateToURL(shell(), GURL(kAboutBlankURL));
 
@@ -1143,12 +1150,19 @@
   std::set<RenderViewHost*> watched_render_view_hosts_;
 };
 
+// Crashes under ThreadSanitizer, http://crbug.com/356758.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_LeakingRenderViewHosts DISABLED_LeakingRenderViewHosts
+#else
+#define MAYBE_LeakingRenderViewHosts LeakingRenderViewHosts
+#endif
 // Test for crbug.com/90867. Make sure we don't leak render view hosts since
 // they may cause crashes or memory corruptions when trying to call dead
 // delegate_. This test also verifies crbug.com/117420 and crbug.com/143255 to
 // ensure that a separate SiteInstance is created when navigating to view-source
 // URLs, regardless of current URL.
-IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, LeakingRenderViewHosts) {
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+                       MAYBE_LeakingRenderViewHosts) {
   StartServer();
 
   // Observe the created render_view_host's to make sure they will not leak.
@@ -1364,7 +1378,8 @@
 // Test that we still swap processes for BrowsingInstance changes even in
 // --process-per-tab mode.  See http://crbug.com/343017.
 // Disabled on Android: http://crbug.com/345873.
-#if defined(OS_ANDROID)
+// Crashes under ThreadSanitizer, http://crbug.com/356758.
+#if defined(OS_ANDROID) || defined(THREAD_SANITIZER)
 #define MAYBE_BackFromWebUI DISABLED_BackFromWebUI
 #else
 #define MAYBE_BackFromWebUI BackFromWebUI
diff --git a/content/browser/frame_host/render_frame_host_manager_unittest.cc b/content/browser/frame_host/render_frame_host_manager_unittest.cc
index 2e7ad3f..fab23b3 100644
--- a/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/files/file_path.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/frame_host/cross_site_transferring_request.h"
 #include "content/browser/frame_host/navigation_controller_impl.h"
@@ -93,6 +94,76 @@
   DISALLOW_COPY_AND_ASSIGN(BeforeUnloadFiredWebContentsDelegate);
 };
 
+// This observer keeps track of the last deleted RenderViewHost to avoid
+// accessing it and causing use-after-free condition.
+class RenderViewHostDeletedObserver : public WebContentsObserver {
+ public:
+  RenderViewHostDeletedObserver(RenderViewHost* rvh)
+      : WebContentsObserver(WebContents::FromRenderViewHost(rvh)),
+        process_id_(rvh->GetProcess()->GetID()),
+        routing_id_(rvh->GetRoutingID()),
+        deleted_(false) {
+  }
+
+  virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE {
+    if (render_view_host->GetProcess()->GetID() == process_id_ &&
+        render_view_host->GetRoutingID() == routing_id_) {
+      deleted_ = true;
+    }
+  }
+
+  bool deleted() {
+    return deleted_;
+  }
+
+ private:
+  int process_id_;
+  int routing_id_;
+  bool deleted_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderViewHostDeletedObserver);
+};
+
+
+// This observer is used to check whether IPC messages are being filtered for
+// swapped out RenderFrameHost objects. It observes the plugin crash and favicon
+// update events, which the FilterMessagesWhileSwappedOut test simulates being
+// sent. The test is successful if the event is not observed.
+// See http://crbug.com/351815
+class PluginFaviconMessageObserver : public WebContentsObserver {
+ public:
+  PluginFaviconMessageObserver(WebContents* web_contents)
+      : WebContentsObserver(web_contents),
+        plugin_crashed_(false),
+        favicon_received_(false) { }
+
+  virtual void PluginCrashed(const base::FilePath& plugin_path,
+                             base::ProcessId plugin_pid) OVERRIDE {
+    plugin_crashed_ = true;
+  }
+
+  virtual void DidUpdateFaviconURL(
+      int32 page_id,
+      const std::vector<FaviconURL>& candidates) OVERRIDE {
+    favicon_received_ = true;
+  }
+
+  bool plugin_crashed() {
+    return plugin_crashed_;
+  }
+
+  bool favicon_received() {
+    return favicon_received_;
+  }
+
+ private:
+  bool plugin_crashed_;
+  bool favicon_received_;
+
+  DISALLOW_COPY_AND_ASSIGN(PluginFaviconMessageObserver);
+};
+
+
 }  // namespace
 
 class RenderFrameHostManagerTest
@@ -112,6 +183,19 @@
     factory_.set_should_create_webui(should_create_webui);
   }
 
+  void StartCrossSiteTransition(TestWebContents* contents) {
+    std::vector<GURL> url_chain;
+    contents->GetRenderManagerForTesting()->OnCrossSiteResponse(
+        contents->GetRenderManagerForTesting()->pending_frame_host(),
+        GlobalRequestID(0, 0), scoped_ptr<CrossSiteTransferringRequest>(),
+        url_chain, Referrer(), PAGE_TRANSITION_TYPED, false);
+    EXPECT_TRUE(contents->cross_navigation_pending());
+    RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
+        contents->GetRenderViewHost());
+    EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_UNLOAD_ACK,
+              rvh->rvh_state());
+  }
+
   void NavigateActiveAndCommit(const GURL& url) {
     // Note: we navigate the active RenderViewHost because previous navigations
     // won't have committed yet, so NavigateAndCommit does the wrong thing
@@ -121,19 +205,34 @@
 
     // Simulate the BeforeUnload_ACK that is received from the current renderer
     // for a cross-site navigation.
-    if (old_rvh != active_rvh())
+    if (old_rvh != active_rvh()) {
       old_rvh->SendBeforeUnloadACK(true);
+      EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, old_rvh->rvh_state());
+    }
 
     // Commit the navigation with a new page ID.
     int32 max_page_id = contents()->GetMaxPageIDForSiteInstance(
         active_rvh()->GetSiteInstance());
 
+    // Simulate the response coming from the pending renderer.
+    if (old_rvh != active_rvh())
+      StartCrossSiteTransition(contents());
+
     // Simulate the SwapOut_ACK that fires if you commit a cross-site
     // navigation.
-    if (old_rvh != active_rvh())
+    if (old_rvh != active_rvh()) {
       old_rvh->OnSwappedOut(false);
+      EXPECT_EQ(RenderViewHostImpl::STATE_WAITING_FOR_COMMIT,
+                old_rvh->rvh_state());
+    }
 
+    // Use an observer to avoid accessing a deleted renderer later on when the
+    // state is being checked.
+    RenderViewHostDeletedObserver rvh_observer(old_rvh);
     active_test_rvh()->SendNavigate(max_page_id + 1, url);
+
+    if (old_rvh != active_rvh() && !rvh_observer.deleted())
+      EXPECT_TRUE(old_rvh->IsSwappedOut());
   }
 
   bool ShouldSwapProcesses(RenderFrameHostManager* manager,
@@ -222,7 +321,7 @@
   ASSERT_TRUE(dest_rvh2);
 
   ntp_rvh2->SendBeforeUnloadACK(true);
-  ntp_rvh2->OnSwappedOut(false);
+  StartCrossSiteTransition(contents2.get());
   dest_rvh2->SendNavigate(101, kDestUrl);
 
   // The two RVH's should be different in every way.
@@ -238,9 +337,9 @@
   contents2->GetController().LoadURL(
       kChromeUrl, Referrer(), PAGE_TRANSITION_LINK, std::string());
   dest_rvh2->SendBeforeUnloadACK(true);
-  dest_rvh2->OnSwappedOut(false);
+  StartCrossSiteTransition(contents2.get());
   static_cast<TestRenderViewHost*>(contents2->GetRenderManagerForTesting()->
-     pending_render_view_host())->SendNavigate(102, kChromeUrl);
+      pending_render_view_host())->SendNavigate(102, kChromeUrl);
 
   EXPECT_NE(active_rvh()->GetSiteInstance(),
             contents2->GetRenderViewHost()->GetSiteInstance());
@@ -256,53 +355,69 @@
 TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) {
   const GURL kChromeURL("chrome://foo");
   const GURL kDestUrl("http://www.google.com/");
+  std::vector<FaviconURL> icons;
 
   // Navigate our first tab to a chrome url and then to the destination.
   NavigateActiveAndCommit(kChromeURL);
   TestRenderViewHost* ntp_rvh = static_cast<TestRenderViewHost*>(
       contents()->GetRenderManagerForTesting()->current_host());
 
-  // Send an update title message and make sure it works.
+  // Send an update favicon message and make sure it works.
   const base::string16 ntp_title = base::ASCIIToUTF16("NTP Title");
-  blink::WebTextDirection direction = blink::WebTextDirectionLeftToRight;
-  EXPECT_TRUE(ntp_rvh->OnMessageReceived(
-      ViewHostMsg_UpdateTitle(rvh()->GetRoutingID(), 0, ntp_title, direction)));
-  EXPECT_EQ(ntp_title, contents()->GetTitle());
-
-  // Navigate to a cross-site URL.
-  contents()->GetController().LoadURL(
-      kDestUrl, Referrer(), PAGE_TRANSITION_LINK, std::string());
-  EXPECT_TRUE(contents()->cross_navigation_pending());
-  TestRenderViewHost* dest_rvh = static_cast<TestRenderViewHost*>(
-      contents()->GetRenderManagerForTesting()->pending_render_view_host());
-  ASSERT_TRUE(dest_rvh);
-  EXPECT_NE(ntp_rvh, dest_rvh);
-
+  {
+    PluginFaviconMessageObserver observer(contents());
+    EXPECT_TRUE(ntp_rvh->OnMessageReceived(
+                    ViewHostMsg_UpdateFaviconURL(
+                        rvh()->GetRoutingID(), 0, icons)));
+    EXPECT_TRUE(observer.favicon_received());
+  }
   // Create one more view in the same SiteInstance where dest_rvh2
   // exists so that it doesn't get deleted on navigation to another
   // site.
   static_cast<SiteInstanceImpl*>(ntp_rvh->GetSiteInstance())->
       increment_active_view_count();
 
-  // BeforeUnload finishes.
-  ntp_rvh->SendBeforeUnloadACK(true);
 
-  // Assume SwapOutACK times out, so the dest_rvh proceeds and commits.
-  dest_rvh->SendNavigate(101, kDestUrl);
+  // Navigate to a cross-site URL.
+  NavigateActiveAndCommit(kDestUrl);
+  TestRenderViewHost* dest_rvh = static_cast<TestRenderViewHost*>(
+      contents()->GetRenderViewHost());
+  ASSERT_TRUE(dest_rvh);
+  EXPECT_NE(ntp_rvh, dest_rvh);
 
-  // The new RVH should be able to update its title.
+  // The new RVH should be able to update its favicon.
   const base::string16 dest_title = base::ASCIIToUTF16("Google");
-  EXPECT_TRUE(dest_rvh->OnMessageReceived(
-      ViewHostMsg_UpdateTitle(rvh()->GetRoutingID(), 101, dest_title,
-                              direction)));
-  EXPECT_EQ(dest_title, contents()->GetTitle());
+  {
+    PluginFaviconMessageObserver observer(contents());
+    EXPECT_TRUE(
+        dest_rvh->OnMessageReceived(
+            ViewHostMsg_UpdateFaviconURL(rvh()->GetRoutingID(), 101, icons)));
+    EXPECT_TRUE(observer.favicon_received());
+  }
 
-  // The old renderer, being slow, now updates the title. It should be filtered
-  // out and not take effect.
-  EXPECT_EQ(RenderViewHostImpl::STATE_PENDING_SWAP_OUT, ntp_rvh->rvh_state());
-  EXPECT_TRUE(ntp_rvh->OnMessageReceived(
-      ViewHostMsg_UpdateTitle(rvh()->GetRoutingID(), 0, ntp_title, direction)));
-  EXPECT_EQ(dest_title, contents()->GetTitle());
+  // The old renderer, being slow, now updates the favicon. It should be
+  // filtered out and not take effect.
+  EXPECT_TRUE(ntp_rvh->IsSwappedOut());
+  {
+    PluginFaviconMessageObserver observer(contents());
+    EXPECT_TRUE(
+        ntp_rvh->OnMessageReceived(
+            ViewHostMsg_UpdateFaviconURL(rvh()->GetRoutingID(), 101, icons)));
+    EXPECT_FALSE(observer.favicon_received());
+  }
+
+  // The same logic should apply to RenderFrameHosts as well and routing through
+  // swapped out RFH shouldn't be allowed. Use a PluginCrashObserver to check
+  // if the IPC message is allowed through or not.
+  {
+    PluginFaviconMessageObserver observer(contents());
+    // TODO(nasko): Check that the RFH is in swapped out when the state moves
+    // from RVH to RFH.
+    EXPECT_TRUE(ntp_rvh->main_render_frame_host()->OnMessageReceived(
+                    FrameHostMsg_PluginCrashed(
+                        main_rfh()->GetRoutingID(), base::FilePath(), 0)));
+    EXPECT_FALSE(observer.plugin_crashed());
+  }
 
   // We cannot filter out synchronous IPC messages, because the renderer would
   // be left waiting for a reply.  We pick RunBeforeUnloadConfirm as an example
@@ -627,7 +742,7 @@
   EXPECT_FALSE(manager->pending_frame_host());
 
   // Commit.
-  manager->DidNavigateMainFrame(host->render_view_host());
+  manager->DidNavigateFrame(host);
   // Commit to SiteInstance should be delayed until RenderView commit.
   EXPECT_TRUE(host == manager->current_frame_host());
   ASSERT_TRUE(host);
@@ -649,7 +764,7 @@
   EXPECT_FALSE(manager->pending_frame_host());
 
   // Commit.
-  manager->DidNavigateMainFrame(host->render_view_host());
+  manager->DidNavigateFrame(host);
   EXPECT_TRUE(host == manager->current_frame_host());
   ASSERT_TRUE(host);
   EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
@@ -671,7 +786,7 @@
   notifications.Reset();
 
   // Commit.
-  manager->DidNavigateMainFrame(manager->pending_render_view_host());
+  manager->DidNavigateFrame(manager->pending_frame_host());
   EXPECT_TRUE(host == manager->current_frame_host());
   ASSERT_TRUE(host);
   EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host->GetSiteInstance())->
@@ -725,7 +840,7 @@
   notifications.Reset();
 
   // Commit.
-  manager->DidNavigateMainFrame(host->render_view_host());
+  manager->DidNavigateFrame(host);
 
   // Commit to SiteInstance should be delayed until RenderView commit.
   EXPECT_TRUE(host == manager->current_frame_host());
@@ -771,11 +886,11 @@
 
   // CrossSiteResourceHandler::StartCrossSiteTransition triggers a
   // call of RenderFrameHostManager::SwapOutOldPage before
-  // RenderFrameHostManager::DidNavigateMainFrame is called.
+  // RenderFrameHostManager::DidNavigateFrame is called.
   // The RVH is swapped out after receiving the unload ack.
   manager->SwapOutOldPage();
   EXPECT_TRUE(test_process_host->sink().GetUniqueMessageMatching(
-      ViewMsg_SwapOut::ID));
+      FrameMsg_SwapOut::ID));
   test_host->OnSwappedOut(false);
 
   EXPECT_EQ(host, manager->current_frame_host());
@@ -813,14 +928,16 @@
 
   // CrossSiteResourceHandler::StartCrossSiteTransition triggers a
   // call of RenderFrameHostManager::SwapOutOldPage before
-  // RenderFrameHostManager::DidNavigateMainFrame is called.
+  // RenderFrameHostManager::DidNavigateFrame is called. Since the previous
+  // navigation has already caused the renderer to start swapping out, there
+  // will be no more SwapOut messages being sent.
   manager->SwapOutOldPage();
-  EXPECT_TRUE(test_process_host->sink().GetUniqueMessageMatching(
-      ViewMsg_SwapOut::ID));
+  EXPECT_FALSE(test_process_host->sink().GetUniqueMessageMatching(
+      FrameMsg_SwapOut::ID));
   test_host->OnSwappedOut(false);
 
   // Commit.
-  manager->DidNavigateMainFrame(host3->render_view_host());
+  manager->DidNavigateFrame(host3);
   EXPECT_TRUE(host3 == manager->current_frame_host());
   ASSERT_TRUE(host3);
   EXPECT_TRUE(static_cast<SiteInstanceImpl*>(host3->GetSiteInstance())->
@@ -877,7 +994,7 @@
   EXPECT_TRUE(manager->web_ui());
 
   // Commit.
-  manager->DidNavigateMainFrame(host->render_view_host());
+  manager->DidNavigateFrame(host);
   EXPECT_TRUE(
       host->render_view_host()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
 }
@@ -916,7 +1033,7 @@
       host1->render_view_host()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
 
   // Commit and ensure we still have bindings.
-  manager1->DidNavigateMainFrame(host1->render_view_host());
+  manager1->DidNavigateFrame(host1);
   SiteInstance* webui_instance = host1->GetSiteInstance();
   EXPECT_EQ(host1, manager1->current_frame_host());
   EXPECT_TRUE(
@@ -948,7 +1065,7 @@
   EXPECT_TRUE(
       host2->render_view_host()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI);
 
-  manager2->DidNavigateMainFrame(host2->render_view_host());
+  manager2->DidNavigateFrame(host2);
 }
 
 // Tests that we don't end up in an inconsistent state if a page does a back and
@@ -1029,7 +1146,7 @@
   EXPECT_TRUE(rvh2->is_waiting_for_beforeunload_ack());
   contents()->ProceedWithCrossSiteNavigation();
   EXPECT_FALSE(rvh2->is_waiting_for_beforeunload_ack());
-  rvh2->SwapOut();
+  StartCrossSiteTransition(contents());
   EXPECT_TRUE(rvh2->IsWaitingForUnloadACK());
 
   // The back navigation commits.
@@ -1040,6 +1157,7 @@
   // We should be able to navigate forward.
   contents()->GetController().GoForward();
   contents()->ProceedWithCrossSiteNavigation();
+  StartCrossSiteTransition(contents());
   const NavigationEntry* entry2 = contents()->GetController().GetPendingEntry();
   rvh2->SendNavigate(entry2->GetPageID(), entry2->GetURL());
   EXPECT_EQ(rvh2, rvh());
@@ -1242,7 +1360,7 @@
   EXPECT_EQ(manager->current_frame_host()->GetSiteInstance(), instance);
 
   // Commit.
-  manager->DidNavigateMainFrame(host->render_view_host());
+  manager->DidNavigateFrame(host);
   // Commit to SiteInstance should be delayed until RenderView commit.
   EXPECT_EQ(host, manager->current_frame_host());
   ASSERT_TRUE(host);
@@ -1264,7 +1382,7 @@
   EXPECT_FALSE(manager->pending_frame_host());
 
   // Commit.
-  manager->DidNavigateMainFrame(host->render_view_host());
+  manager->DidNavigateFrame(host);
   EXPECT_EQ(host, manager->current_frame_host());
   ASSERT_TRUE(host);
   EXPECT_EQ(static_cast<SiteInstanceImpl*>(host->GetSiteInstance()),
@@ -1312,7 +1430,7 @@
   notifications.Reset();
 
   // Commit.
-  manager->DidNavigateMainFrame(host->render_view_host());
+  manager->DidNavigateFrame(host);
 
   // Commit to SiteInstance should be delayed until RenderFrame commits.
   EXPECT_EQ(host, manager->current_frame_host());
@@ -1347,28 +1465,6 @@
   EXPECT_EQ(host, manager->current_frame_host());
 }
 
-// This checks that the given RVH has been properly deleted.
-class RenderViewHostDestructionObserver : public WebContentsObserver {
- public:
-  RenderViewHostDestructionObserver(RenderViewHost* render_view_host)
-      : WebContentsObserver(WebContents::FromRenderViewHost(render_view_host)),
-        render_view_host_(render_view_host),
-        rvh_deleted_(false) {}
-
-  bool rvh_deleted() { return rvh_deleted_; }
-
-  virtual void RenderViewDeleted(RenderViewHost* render_view_host) OVERRIDE {
-    if (render_view_host == render_view_host_)
-      rvh_deleted_ = true;
-  }
-
- private:
-  RenderViewHost* render_view_host_;
-  bool rvh_deleted_;
-
-  DISALLOW_COPY_AND_ASSIGN(RenderViewHostDestructionObserver);
-};
-
 // Tests that the RenderViewHost is properly deleted when the SwapOutACK is
 // received before the new page commits.
 TEST_F(RenderFrameHostManagerTest,
@@ -1379,7 +1475,7 @@
   // Navigate to the first page.
   contents()->NavigateAndCommit(kUrl1);
   TestRenderViewHost* rvh1 = test_rvh();
-  RenderViewHostDestructionObserver destruction_observer(rvh1);
+  RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
   EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
 
   // Navigate to new site, simulating onbeforeunload approval.
@@ -1415,7 +1511,7 @@
   EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
 
   // rvh1 should have been deleted.
-  EXPECT_TRUE(destruction_observer.rvh_deleted());
+  EXPECT_TRUE(rvh_deleted_observer.deleted());
   rvh1 = NULL;
 }
 
@@ -1429,7 +1525,7 @@
   // Navigate to the first page.
   contents()->NavigateAndCommit(kUrl1);
   TestRenderViewHost* rvh1 = test_rvh();
-  RenderViewHostDestructionObserver destruction_observer(rvh1);
+  RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
   EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
 
   // Increment the number of active views in SiteInstanceImpl so that rvh2 is
@@ -1470,7 +1566,7 @@
   EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
 
   // rvh1 should be swapped out.
-  EXPECT_FALSE(destruction_observer.rvh_deleted());
+  EXPECT_FALSE(rvh_deleted_observer.deleted());
   EXPECT_TRUE(rvh1->IsSwappedOut());
 }
 
@@ -1484,7 +1580,7 @@
   // Navigate to the first page.
   contents()->NavigateAndCommit(kUrl1);
   TestRenderViewHost* rvh1 = test_rvh();
-  RenderViewHostDestructionObserver destruction_observer(rvh1);
+  RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
   EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
 
   // Navigate to new site, simulating onbeforeunload approval.
@@ -1520,7 +1616,7 @@
   rvh1->OnSwappedOut(false);
 
   // rvh1 should have been deleted.
-  EXPECT_TRUE(destruction_observer.rvh_deleted());
+  EXPECT_TRUE(rvh_deleted_observer.deleted());
   rvh1 = NULL;
 }
 
@@ -1534,7 +1630,7 @@
   // Navigate to the first page.
   contents()->NavigateAndCommit(kUrl1);
   TestRenderViewHost* rvh1 = test_rvh();
-  RenderViewHostDestructionObserver destruction_observer(rvh1);
+  RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
   EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
 
   // Increment the number of active views in SiteInstanceImpl so that rvh1 is
@@ -1575,7 +1671,52 @@
   rvh1->OnSwappedOut(false);
 
   // rvh1 should be swapped out.
-  EXPECT_FALSE(destruction_observer.rvh_deleted());
+  EXPECT_FALSE(rvh_deleted_observer.deleted());
+  EXPECT_TRUE(rvh1->IsSwappedOut());
+}
+
+// Test that the RenderViewHost is properly swapped out if a navigation in the
+// new renderer commits before sending the SwapOut message to the old renderer.
+// This simulates a cross-site navigation to a synchronously committing URL
+// (e.g., a data URL) and ensures it works properly.
+TEST_F(RenderFrameHostManagerTest,
+       CommitNewNavigationBeforeSendingSwapOut) {
+  const GURL kUrl1("http://www.google.com/");
+  const GURL kUrl2("http://www.chromium.org/");
+
+  // Navigate to the first page.
+  contents()->NavigateAndCommit(kUrl1);
+  TestRenderViewHost* rvh1 = test_rvh();
+  RenderViewHostDeletedObserver rvh_deleted_observer(rvh1);
+  EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh1->rvh_state());
+
+  // Increment the number of active views in SiteInstanceImpl so that rvh1 is
+  // not deleted on swap out.
+  static_cast<SiteInstanceImpl*>(
+      rvh1->GetSiteInstance())->increment_active_view_count();
+
+  // Navigate to new site, simulating onbeforeunload approval.
+  controller().LoadURL(kUrl2, Referrer(), PAGE_TRANSITION_LINK, std::string());
+  base::TimeTicks now = base::TimeTicks::Now();
+  main_test_rfh()->OnMessageReceived(
+      FrameHostMsg_BeforeUnload_ACK(0, true, now, now));
+  EXPECT_TRUE(contents()->cross_navigation_pending());
+  TestRenderViewHost* rvh2 =
+      static_cast<TestRenderViewHost*>(contents()->GetPendingRenderViewHost());
+
+  // The new page commits.
+  contents()->TestDidNavigate(rvh2, 1, kUrl2, PAGE_TRANSITION_TYPED);
+  EXPECT_FALSE(contents()->cross_navigation_pending());
+  EXPECT_EQ(rvh2, rvh());
+  EXPECT_TRUE(contents()->GetPendingRenderViewHost() == NULL);
+  EXPECT_EQ(RenderViewHostImpl::STATE_DEFAULT, rvh2->rvh_state());
+  EXPECT_EQ(RenderViewHostImpl::STATE_PENDING_SWAP_OUT, rvh1->rvh_state());
+
+  // Simulate the swap out ack.
+  rvh1->OnSwappedOut(false);
+
+  // rvh1 should be swapped out.
+  EXPECT_FALSE(rvh_deleted_observer.deleted());
   EXPECT_TRUE(rvh1->IsSwappedOut());
 }
 
diff --git a/content/browser/gpu/compositor_util.h b/content/browser/gpu/compositor_util.h
index fec252f..ba135db 100644
--- a/content/browser/gpu/compositor_util.h
+++ b/content/browser/gpu/compositor_util.h
@@ -10,6 +10,9 @@
 
 namespace content {
 
+// Note: When adding a function here, please make sure the logic is not
+// duplicated in the renderer.
+
 // Returns true if the threaded compositor is on (via flags or field trial).
 CONTENT_EXPORT bool IsThreadedCompositingEnabled();
 
diff --git a/content/browser/gpu/compositor_util_browsertest.cc b/content/browser/gpu/compositor_util_browsertest.cc
index c43909f..7c52007 100644
--- a/content/browser/gpu/compositor_util_browsertest.cc
+++ b/content/browser/gpu/compositor_util_browsertest.cc
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 #include "content/browser/gpu/compositor_util.h"
-#include "content/test/content_browser_test.h"
+#include "content/public/test/content_browser_test.h"
 
 #if defined(OS_MACOSX)
 #include "base/mac/mac_util.h"
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc
index cb67a6d..a2b11bb 100644
--- a/content/browser/gpu/gpu_internals_ui.cc
+++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -157,6 +157,10 @@
                                              gpu_info.gl_ws_version));
   basic_info->Append(NewDescriptionValuePair("Window system binding extensions",
                                              gpu_info.gl_ws_extensions));
+  std::string direct_rendering = gpu_info.direct_rendering ? "Yes" : "No";
+  basic_info->Append(
+      NewDescriptionValuePair("Direct rendering", direct_rendering));
+
   std::string reset_strategy =
       base::StringPrintf("0x%04x", gpu_info.gl_reset_notification_strategy);
   basic_info->Append(NewDescriptionValuePair(
diff --git a/content/browser/gpu/gpu_ipc_browsertests.cc b/content/browser/gpu/gpu_ipc_browsertests.cc
index e417375..ebeceff 100644
--- a/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -11,7 +11,7 @@
 #include "content/common/gpu/gpu_process_launch_causes.h"
 #include "content/public/browser/gpu_data_manager.h"
 #include "content/public/common/content_switches.h"
-#include "content/test/content_browser_test.h"
+#include "content/public/test/content_browser_test.h"
 #include "ui/gl/gl_switches.h"
 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
 
@@ -69,7 +69,7 @@
 
 namespace content {
 
-class BrowserGpuChannelHostFactoryTest : public ContextTestBase {
+class BrowserGpuChannelHostFactoryTest : public ContentBrowserTest {
  public:
   virtual void SetUpOnMainThread() OVERRIDE {
     if (!BrowserGpuChannelHostFactory::CanUseForTesting())
@@ -85,16 +85,6 @@
     ContentBrowserTest::SetUpOnMainThread();
   }
 
-  virtual void TearDownOnMainThread() OVERRIDE {
-    ContextTestBase::TearDownOnMainThread();
-  }
-
-  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
-    // Start all tests without a gpu channel so that the tests exercise a
-    // consistent codepath.
-    command_line->AppendSwitch(switches::kDisableGpuProcessPrelaunch);
-  }
-
   void OnContextLost(const base::Closure callback, int* counter) {
     (*counter)++;
     callback.Run();
@@ -135,20 +125,16 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, Basic) {
-  if (!context_)
-    return;
-
+// Fails since UI Compositor establishes a GpuChannel.
+IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, DISABLED_Basic) {
   DCHECK(!IsChannelEstablished());
   EstablishAndWait();
   EXPECT_TRUE(GetGpuChannel() != NULL);
 }
 
+// Fails since UI Compositor establishes a GpuChannel.
 IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
-                       EstablishAndTerminate) {
-  if (!context_)
-    return;
-
+                       DISABLED_EstablishAndTerminate) {
   DCHECK(!IsChannelEstablished());
   base::RunLoop run_loop;
   GetFactory()->EstablishGpuChannel(kInitCause, run_loop.QuitClosure());
@@ -158,10 +144,9 @@
   run_loop.Run();
 }
 
-IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, AlreadyEstablished) {
-  if (!context_)
-    return;
-
+// Fails since UI Compositor establishes a GpuChannel.
+IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
+                       DISABLED_AlreadyEstablished) {
   DCHECK(!IsChannelEstablished());
   scoped_refptr<GpuChannelHost> gpu_channel =
       GetFactory()->EstablishGpuChannelSync(kInitCause);
@@ -175,10 +160,9 @@
   EXPECT_EQ(gpu_channel, GetGpuChannel());
 }
 
-IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest, CrashAndRecover) {
-  if (!context_)
-    return;
-
+// Fails since UI Compositor establishes a GpuChannel.
+IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
+                       DISABLED_CrashAndRecover) {
   DCHECK(!IsChannelEstablished());
   EstablishAndWait();
   scoped_refptr<GpuChannelHost> host = GetGpuChannel();
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 297f751..080ff5e 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -297,9 +297,6 @@
 
 // static
 bool GpuProcessHost::ValidateHost(GpuProcessHost* host) {
-  if (!host)
-    return false;
-
   // The Gpu process is invalid if it's not using SwiftShader, the card is
   // blacklisted, and we can kill it and start over.
   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess) ||
@@ -770,6 +767,8 @@
 
   if (!initialized_)
     GpuDataManagerImpl::GetInstance()->OnGpuProcessInitFailure();
+  else if (!in_process_)
+    GpuDataManagerImpl::GetInstance()->UpdateGpuInfo(gpu_info);
 }
 
 void GpuProcessHost::OnChannelEstablished(
@@ -1110,6 +1109,7 @@
     switches::kGpuStartupDialog,
     switches::kGpuSandboxAllowSysVShm,
     switches::kGpuSandboxFailuresFatal,
+    switches::kGpuSandboxStartAfterInitialization,
     switches::kLoggingLevel,
     switches::kNoSandbox,
     switches::kTestGLLib,
diff --git a/content/browser/gpu/shader_disk_cache.cc b/content/browser/gpu/shader_disk_cache.cc
index fc578bc..c987cef 100644
--- a/content/browser/gpu/shader_disk_cache.cc
+++ b/content/browser/gpu/shader_disk_cache.cc
@@ -524,7 +524,7 @@
 
   int rv = disk_cache::CreateCacheBackend(
       net::SHADER_CACHE,
-      net::CACHE_BACKEND_BLOCKFILE,
+      net::CACHE_BACKEND_DEFAULT,
       cache_path_.Append(kGpuCachePath),
       gpu::kDefaultMaxProgramCacheMemoryBytes,
       true,
@@ -541,7 +541,7 @@
   if (!cache_available_)
     return;
 
-  ShaderDiskCacheEntry* shim =
+  scoped_refptr<ShaderDiskCacheEntry> shim =
       new ShaderDiskCacheEntry(AsWeakPtr(), key, shader);
   shim->Cache();
 
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc
index 2aebb3e..e78ec1b 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -7,7 +7,6 @@
 #include "base/file_util.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
-#include "base/strings/string_piece.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
@@ -212,14 +211,14 @@
   return Compare(a, b, true /*index_keys*/);
 }
 
-class Comparator : public LevelDBComparator {
- public:
-  virtual int Compare(const StringPiece& a, const StringPiece& b) const
-      OVERRIDE {
-    return content::Compare(a, b, false /*index_keys*/);
-  }
-  virtual const char* Name() const OVERRIDE { return "idb_cmp1"; }
-};
+int IndexedDBBackingStore::Comparator::Compare(const StringPiece& a,
+                                               const StringPiece& b) const {
+  return content::Compare(a, b, false /*index_keys*/);
+}
+
+const char* IndexedDBBackingStore::Comparator::Name() const {
+  return "idb_cmp1";
+}
 
 // 0 - Initial version.
 // 1 - Adds UserIntVersion to DatabaseMetaData.
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h
index 8e5f7ac..e7aa21e 100644
--- a/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -12,6 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/strings/string_piece.h"
 #include "base/timer/timer.h"
 #include "content/browser/indexed_db/indexed_db.h"
 #include "content/browser/indexed_db/indexed_db_metadata.h"
@@ -45,6 +46,13 @@
  public:
   class CONTENT_EXPORT Transaction;
 
+  class Comparator : public LevelDBComparator {
+   public:
+    virtual int Compare(const base::StringPiece& a,
+                        const base::StringPiece& b) const OVERRIDE;
+    virtual const char* Name() const OVERRIDE;
+  };
+
   const GURL& origin_url() const { return origin_url_; }
   base::OneShotTimer<IndexedDBBackingStore>* close_timer() {
     return &close_timer_;
diff --git a/content/browser/indexed_db/indexed_db_browsertest.cc b/content/browser/indexed_db/indexed_db_browsertest.cc
index 5a23893..478a07b 100644
--- a/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -21,9 +21,9 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "webkit/browser/database/database_util.h"
 #include "webkit/browser/quota/quota_manager.h"
 
diff --git a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
index 527d339..d159a81 100644
--- a/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_leveldb_coding_unittest.cc
@@ -296,7 +296,7 @@
     slice = StringPiece(&*v.begin(), v.size() - 1);
     EXPECT_FALSE(DecodeVarInt(&slice, &res));
 
-    slice = StringPiece(&*v.begin(), 0u);
+    slice = StringPiece(&*v.begin(), static_cast<size_t>(0));
     EXPECT_FALSE(DecodeVarInt(&slice, &res));
 
     // Verify decoding at an offset, to detect unaligned memory access.
@@ -408,7 +408,7 @@
     slice = StringPiece(&*v.begin(), v.size() - 1);
     EXPECT_FALSE(DecodeStringWithLength(&slice, &res));
 
-    slice = StringPiece(&*v.begin(), 0u);
+    slice = StringPiece(&*v.begin(), static_cast<size_t>(0));
     EXPECT_FALSE(DecodeStringWithLength(&slice, &res));
 
     // Verify decoding at an offset, to detect unaligned memory access.
@@ -516,7 +516,7 @@
     slice = StringPiece(&*v.begin(), v.size() - 1);
     EXPECT_FALSE(DecodeBinary(&slice, &result));
 
-    slice = StringPiece(&*v.begin(), 0u);
+    slice = StringPiece(&*v.begin(), static_cast<size_t>(0));
     EXPECT_FALSE(DecodeBinary(&slice, &result));
 
     // Verify decoding at an offset, to detect unaligned memory access.
@@ -557,7 +557,7 @@
     slice = StringPiece(&*v.begin(), v.size() - 1);
     EXPECT_FALSE(DecodeDouble(&slice, &result));
 
-    slice = StringPiece(&*v.begin(), 0u);
+    slice = StringPiece(&*v.begin(), static_cast<size_t>(0));
     EXPECT_FALSE(DecodeDouble(&slice, &result));
 
     // Verify decoding at an offset, to detect unaligned memory access.
@@ -602,7 +602,7 @@
     slice = StringPiece(&*v.begin(), v.size() - 1);
     EXPECT_FALSE(DecodeIDBKey(&slice, &decoded_key));
 
-    slice = StringPiece(&*v.begin(), 0u);
+    slice = StringPiece(&*v.begin(), static_cast<size_t>(0));
     EXPECT_FALSE(DecodeIDBKey(&slice, &decoded_key));
   }
 }
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.cc b/content/browser/indexed_db/leveldb/leveldb_database.cc
index 2c2aefd..3c27340 100644
--- a/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -22,7 +22,6 @@
 #include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/env_idb.h"
 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
-#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
 #include "third_party/leveldatabase/src/include/leveldb/db.h"
 #include "third_party/leveldatabase/src/include/leveldb/env.h"
 #include "third_party/leveldatabase/src/include/leveldb/slice.h"
@@ -55,27 +54,26 @@
   return StringPiece(s.data(), s.size());
 }
 
-class ComparatorAdapter : public leveldb::Comparator {
- public:
-  explicit ComparatorAdapter(const LevelDBComparator* comparator)
-      : comparator_(comparator) {}
+LevelDBDatabase::ComparatorAdapter::ComparatorAdapter(
+    const LevelDBComparator* comparator)
+    : comparator_(comparator) {}
 
-  virtual int Compare(const leveldb::Slice& a, const leveldb::Slice& b) const
-      OVERRIDE {
-    return comparator_->Compare(MakeStringPiece(a), MakeStringPiece(b));
-  }
+int LevelDBDatabase::ComparatorAdapter::Compare(const leveldb::Slice& a,
+                                                const leveldb::Slice& b) const {
+  return comparator_->Compare(MakeStringPiece(a), MakeStringPiece(b));
+}
 
-  virtual const char* Name() const OVERRIDE { return comparator_->Name(); }
+const char* LevelDBDatabase::ComparatorAdapter::Name() const {
+  return comparator_->Name();
+}
 
-  // TODO(jsbell): Support the methods below in the future.
-  virtual void FindShortestSeparator(std::string* start,
-                                     const leveldb::Slice& limit) const
-      OVERRIDE {}
-  virtual void FindShortSuccessor(std::string* key) const OVERRIDE {}
+// TODO(jsbell): Support the methods below in the future.
+void LevelDBDatabase::ComparatorAdapter::FindShortestSeparator(
+    std::string* start,
+    const leveldb::Slice& limit) const {}
 
- private:
-  const LevelDBComparator* comparator_;
-};
+void LevelDBDatabase::ComparatorAdapter::FindShortSuccessor(
+    std::string* key) const {}
 
 LevelDBSnapshot::LevelDBSnapshot(LevelDBDatabase* db)
     : db_(db->db_.get()), snapshot_(db_->GetSnapshot()) {}
diff --git a/content/browser/indexed_db/leveldb/leveldb_database.h b/content/browser/indexed_db/leveldb/leveldb_database.h
index d2f0869..27ffcd5 100644
--- a/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -12,6 +12,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 #include "content/common/content_export.h"
+#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
 #include "third_party/leveldatabase/src/include/leveldb/status.h"
 
 namespace leveldb {
@@ -47,6 +48,24 @@
 
 class CONTENT_EXPORT LevelDBDatabase {
  public:
+  class ComparatorAdapter : public leveldb::Comparator {
+   public:
+    explicit ComparatorAdapter(const LevelDBComparator* comparator);
+
+    virtual int Compare(const leveldb::Slice& a,
+                        const leveldb::Slice& b) const OVERRIDE;
+
+    virtual const char* Name() const OVERRIDE;
+
+    virtual void FindShortestSeparator(std::string* start,
+                                       const leveldb::Slice& limit) const
+        OVERRIDE;
+    virtual void FindShortSuccessor(std::string* key) const OVERRIDE;
+
+   private:
+    const LevelDBComparator* comparator_;
+  };
+
   static leveldb::Status Open(const base::FilePath& file_name,
                               const LevelDBComparator* comparator,
                               scoped_ptr<LevelDBDatabase>* db,
diff --git a/content/browser/loader/async_resource_handler.cc b/content/browser/loader/async_resource_handler.cc
index 7014a47..7e3bd2e 100644
--- a/content/browser/loader/async_resource_handler.cc
+++ b/content/browser/loader/async_resource_handler.cc
@@ -201,8 +201,7 @@
   }
 
   // If the parent handler downloaded the resource to a file, grant the child
-  // read permissions on it. Note: there is similar logic in
-  // SyncResourceHandler.
+  // read permissions on it.
   if (!response->head.download_file_path.empty()) {
     rdh_->RegisterDownloadedTempFile(
         info->GetChildID(), info->GetRequestID(),
diff --git a/content/browser/loader/resource_dispatcher_host_browsertest.cc b/content/browser/loader/resource_dispatcher_host_browsertest.cc
index 239da69..9836d04 100644
--- a/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -12,12 +12,12 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/shell/browser/shell_network_delegate.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/net/url_request_failed_job.h"
 #include "content/test/net/url_request_mock_http_job.h"
 #include "net/base/net_errors.h"
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc
index 69f9a95..9234315 100644
--- a/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -610,9 +610,6 @@
                                                    ResourceResponse* response) {
   ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest(request);
   const std::string& mime_type = response->head.mime_type;
-  std::string response_headers;
-  if (response->head.headers)
-    response->head.headers->GetNormalizedHeaders(&response_headers);
 
   GURL origin;
   std::string target_id;
@@ -639,8 +636,10 @@
       info->GetChildID(),
       info->GetRouteID(),
       target_id,
-      handler->stream()->CreateHandle(request->url(), mime_type,
-                                      response_headers),
+      handler->stream()->CreateHandle(
+          request->url(),
+          mime_type,
+          response->head.headers),
       request->GetExpectedContentSize());
   return handler.PassAs<ResourceHandler>();
 }
@@ -1148,7 +1147,8 @@
            request_data, sync_result, route_id, process_type, child_id,
            resource_context));
 
-  BeginRequestInternal(new_request.Pass(), handler.Pass());
+  if (handler)
+    BeginRequestInternal(new_request.Pass(), handler.Pass());
 }
 
 scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
@@ -1162,15 +1162,22 @@
   // Construct the IPC resource handler.
   scoped_ptr<ResourceHandler> handler;
   if (sync_result) {
+    // download_to_file is not supported for synchronous requests.
+    if (request_data.download_to_file) {
+      RecordAction(base::UserMetricsAction("BadMessageTerminate_RDH"));
+      filter_->BadMessageReceived();
+      return scoped_ptr<ResourceHandler>();
+    }
+
     handler.reset(new SyncResourceHandler(request, sync_result, this));
   } else {
     handler.reset(new AsyncResourceHandler(request, this));
-  }
 
-  // The RedirectToFileResourceHandler depends on being next in the chain.
-  if (request_data.download_to_file) {
-    handler.reset(
-        new RedirectToFileResourceHandler(handler.Pass(), request));
+    // The RedirectToFileResourceHandler depends on being next in the chain.
+    if (request_data.download_to_file) {
+      handler.reset(
+          new RedirectToFileResourceHandler(handler.Pass(), request));
+    }
   }
 
   // Prefetches and <a ping> requests outlive their child process.
diff --git a/content/browser/loader/sync_resource_handler.cc b/content/browser/loader/sync_resource_handler.cc
index e39ae1c..865b29e 100644
--- a/content/browser/loader/sync_resource_handler.cc
+++ b/content/browser/loader/sync_resource_handler.cc
@@ -86,18 +86,6 @@
 
   DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
 
-  // If the parent handler downloaded the resource to a file, grant the child
-  // read permissions on it. Note: there is similar logic in
-  // AsyncResourceHandler.
-  //
-  // TODO(davidben): Can we remove support for download_file in sync requests
-  // altogether? I don't think Blink ever makes such requests.
-  if (!response->head.download_file_path.empty()) {
-    rdh_->RegisterDownloadedTempFile(
-        info->GetChildID(), info->GetRequestID(),
-        response->head.download_file_path);
-  }
-
   // We don't care about copying the status here.
   result_.headers = response->head.headers;
   result_.mime_type = response->head.mime_type;
diff --git a/content/browser/media/android/browser_media_player_manager.cc b/content/browser/media/android/browser_media_player_manager.cc
index 669cc60..40e1825 100644
--- a/content/browser/media/android/browser_media_player_manager.cc
+++ b/content/browser/media/android/browser_media_player_manager.cc
@@ -232,12 +232,14 @@
   MediaPlayerAndroid* player = GetFullscreenPlayer();
   if (!player)
     return;
-  if (!surface.IsEmpty()) {
-    Send(new MediaPlayerMsg_DidEnterFullscreen(routing_id(),
-                                               player->player_id()));
-  }
-  player->SetVideoSurface(surface.Pass());
 
+  bool empty_surface = surface.IsEmpty();
+  player->SetVideoSurface(surface.Pass());
+  if (empty_surface)
+    return;
+
+  Send(new MediaPlayerMsg_DidEnterFullscreen(routing_id(),
+                                             player->player_id()));
   if (CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kDisableOverlayFullscreenVideoSubtitle)) {
     return;
@@ -712,10 +714,6 @@
 void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
   DCHECK(!GetPlayer(player->player_id()));
   players_.push_back(player);
-  if (player->IsRemote()) {
-    Send(new MediaPlayerMsg_ConnectedToRemoteDevice(routing_id(),
-                                                    player->player_id()));
-  }
 }
 
 void BrowserMediaPlayerManager::RemovePlayer(int player_id) {
@@ -723,10 +721,6 @@
       it != players_.end(); ++it) {
     MediaPlayerAndroid* player = *it;
     if (player->player_id() == player_id) {
-      if (player->IsRemote()) {
-        Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
-            routing_id(), player->player_id()));
-      }
       players_.erase(it);
       break;
     }
@@ -742,13 +736,6 @@
       previous_player = *it;
       players_.weak_erase(it);
       players_.push_back(player);
-      if (!previous_player->IsRemote() && player->IsRemote()) {
-        Send(new MediaPlayerMsg_ConnectedToRemoteDevice(
-            routing_id(), player->player_id()));
-      } else if (previous_player->IsRemote() && !player->IsRemote()) {
-        Send(new MediaPlayerMsg_DisconnectedFromRemoteDevice(
-            routing_id(), player->player_id()));
-      }
       break;
     }
   }
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc
index 7e7e0e1..bcd0dbb 100644
--- a/content/browser/media/capture/desktop_capture_device.cc
+++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -57,6 +57,8 @@
                         scoped_ptr<Client> client);
   void StopAndDeAllocate();
 
+  void SetNotificationWindowId(gfx::NativeViewId window_id);
+
  private:
   friend class base::RefCountedThreadSafe<Core>;
   virtual ~Core();
@@ -86,6 +88,8 @@
   // Captures a single frame.
   void DoCapture();
 
+  void DoSetNotificationWindowId(gfx::NativeViewId window_id);
+
   // Task runner used for capturing operations.
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
@@ -152,6 +156,12 @@
                          base::Bind(&Core::DoStopAndDeAllocate, this));
 }
 
+void DesktopCaptureDevice::Core::SetNotificationWindowId(
+    gfx::NativeViewId window_id) {
+  task_runner_->PostTask(
+      FROM_HERE, base::Bind(&Core::DoSetNotificationWindowId, this, window_id));
+}
+
 webrtc::SharedMemory*
 DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) {
   return NULL;
@@ -348,6 +358,13 @@
   DCHECK(!capture_in_progress_);
 }
 
+void DesktopCaptureDevice::Core::DoSetNotificationWindowId(
+    gfx::NativeViewId window_id) {
+  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  DCHECK(window_id);
+  desktop_capturer_->SetExcludedWindow(window_id);
+}
+
 // static
 scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
     const DesktopMediaID& source) {
@@ -380,6 +397,7 @@
       scoped_ptr<webrtc::WindowCapturer> window_capturer(
           webrtc::WindowCapturer::Create(options));
       if (window_capturer && window_capturer->SelectWindow(source.id)) {
+        window_capturer->BringSelectedWindowToFront();
         capturer.reset(new webrtc::DesktopAndCursorComposer(
             window_capturer.release(),
             webrtc::MouseCursorMonitor::CreateForWindow(options, source.id)));
@@ -418,4 +436,9 @@
   core_->StopAndDeAllocate();
 }
 
+void DesktopCaptureDevice::SetNotificationWindowId(
+    gfx::NativeViewId window_id) {
+  core_->SetNotificationWindowId(window_id);
+}
+
 }  // namespace content
diff --git a/content/browser/media/capture/desktop_capture_device.h b/content/browser/media/capture/desktop_capture_device.h
index 9e6eaff..545b825 100644
--- a/content/browser/media/capture/desktop_capture_device.h
+++ b/content/browser/media/capture/desktop_capture_device.h
@@ -9,6 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "content/common/content_export.h"
 #include "media/video/capture/video_capture_device.h"
+#include "ui/gfx/native_widget_types.h"
 
 namespace base {
 class SequencedTaskRunner;
@@ -42,6 +43,9 @@
                                 scoped_ptr<Client> client) OVERRIDE;
   virtual void StopAndDeAllocate() OVERRIDE;
 
+  // Set the platform-dependent window id for the notification window.
+  void SetNotificationWindowId(gfx::NativeViewId window_id);
+
  private:
   class Core;
   scoped_refptr<Core> core_;
diff --git a/content/browser/media/capture/web_contents_video_capture_device.cc b/content/browser/media/capture/web_contents_video_capture_device.cc
index b25d316..01db7d2 100644
--- a/content/browser/media/capture/web_contents_video_capture_device.cc
+++ b/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -414,9 +414,17 @@
 
   // This message occurs on window resizes and visibility changes even when
   // accelerated compositing is active, so we need to filter out these cases.
-  if (!rwh || !rwh->GetView() || (rwh->is_accelerated_compositing_active() &&
-                                  rwh->GetView()->IsSurfaceAvailableForCopy()))
+  if (!rwh || !rwh->GetView())
     return;
+  // Mac sends DID_UPDATE_BACKING_STORE messages to inform the capture system
+  // of new software compositor frames, so always treat these messages as
+  // signals of a new frame on Mac.
+  // http://crbug.com/333986
+#if !defined(OS_MACOSX)
+  if (rwh->is_accelerated_compositing_active() &&
+      rwh->GetView()->IsSurfaceAvailableForCopy())
+    return;
+#endif
 
   TRACE_EVENT1("mirroring", "ContentCaptureSubscription::Observe",
                "instance", this);
diff --git a/content/browser/media/media_browsertest.cc b/content/browser/media/media_browsertest.cc
index d9ef168..f284add 100644
--- a/content/browser/media/media_browsertest.cc
+++ b/content/browser/media/media_browsertest.cc
@@ -9,8 +9,8 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test_utils.h"
 
 // TODO(wolenetz): Fix Media.YUV* tests on MSVS 2012 x64. crbug.com/180074
 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64) && _MSC_VER == 1700
diff --git a/content/browser/media/media_browsertest.h b/content/browser/media/media_browsertest.h
index 8bffb3d..b242db3 100644
--- a/content/browser/media/media_browsertest.h
+++ b/content/browser/media/media_browsertest.h
@@ -8,7 +8,7 @@
 #include <utility>
 #include <vector>
 
-#include "content/test/content_browser_test.h"
+#include "content/public/test/content_browser_test.h"
 
 namespace content {
 
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc
new file mode 100644
index 0000000..4a5b5a8
--- /dev/null
+++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -0,0 +1,1100 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "content/browser/media/media_browsertest.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+
+const char* kProbably = "probably";
+const char* kMaybe = "maybe";
+const char* kNot = "";
+
+#if defined(USE_PROPRIETARY_CODECS)
+const char* kPropProbably = "probably";
+const char* kPropMaybe = "maybe";
+const char* kPropProbablyElseMaybe = "probably";
+#else
+const char* kPropProbably = "";
+const char* kPropMaybe = "";
+const char* kPropProbablyElseMaybe = "maybe";
+#endif  // USE_PROPRIETARY_CODECS
+
+// TODO(amogh.bihani): Change the opus tests when opus is  on
+// Android. (http://crbug.com/318436).
+#if !defined(OS_ANDROID)
+const char* kOggVideoProbably = "probably";
+const char* kOggVideoMaybe = "maybe";
+const char* kTheoraProbably = "probably";
+const char* kOpusProbably = "probably";
+const char* kOpusProbablyElseMaybe = "probably";
+const char* kHLSProbably = "";
+const char* kHLSMaybe = "";
+#if defined(USE_PROPRIETARY_CODECS)
+const char* kTheoraAndPropProbably = "probably";
+const char* kTheoraAndPropProbablyElseMaybe = "probably";
+const char* kOpusAndPropProbably = "probably";
+#else
+const char* kTheoraAndPropProbably = "";
+const char* kTheoraAndPropProbablyElseMaybe = "maybe";
+const char* kOpusAndPropProbably = "";
+#endif  // USE_PROPRIETARY_CODECS
+#else
+const char* kOggVideoProbably = "";
+const char* kOggVideoMaybe = "";
+const char* kTheoraProbably = "maybe";
+const char* kOpusProbably = "";
+const char* kOpusProbablyElseMaybe = "maybe";
+const char* kTheoraAndPropProbably = "maybe";
+const char* kTheoraAndPropProbablyElseMaybe = "";
+const char* kOpusAndPropProbably = "maybe";
+const char* kHLSProbably = "probably";
+const char* kHLSMaybe = "maybe";
+#endif  // !OS_ANDROID
+
+namespace content {
+
+class MediaCanPlayTypeTest : public MediaBrowserTest {
+public:
+  MediaCanPlayTypeTest() : url_("about:blank") { }
+
+  virtual void SetUpOnMainThread() OVERRIDE {
+    NavigateToURL(shell(), url_);
+  }
+
+  std::string CanPlay(const std::string& type) {
+    std::string command("document.createElement('video').canPlayType(");
+    command.append(type);
+    command.append(")");
+
+    std::string result;
+    EXPECT_TRUE(ExecuteScriptAndExtractString(
+        shell()->web_contents(),
+        "window.domAutomationController.send(" + command + ");",
+        &result));
+    return result;
+  }
+
+private:
+  GURL url_;
+  DISALLOW_COPY_AND_ASSIGN(MediaCanPlayTypeTest);
+};
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_wav) {
+  EXPECT_EQ(kMaybe, CanPlay("'audio/wav'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/wav; codecs=\"1\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"theora\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp8\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp9\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vp9.0\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"opus\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc3\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"mp4a.40.5\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, mp4a\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, opus\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, theora\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"1, vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"opus, vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"opus, theora\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"vorbis, mp4a\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/wav; codecs=\"unknown\"'"));
+
+  EXPECT_EQ(kMaybe, CanPlay("'audio/x-wav'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"1\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kTheoraProbably, CanPlay("'audio/x-wav; codecs=\"theora\"'"));
+
+  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"vp8\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"vp9\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"vp9.0\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe, CanPlay("'audio/x-wav; codecs=\"opus\"'"));
+
+  EXPECT_EQ(kPropProbablyElseMaybe, CanPlay("'audio/x-wav; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe, CanPlay("'audio/x-wav; codecs=\"avc3\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe, CanPlay("'audio/x-wav; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/x-wav; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/x-wav; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/x-wav; codecs=\"mp4a.40.5\"'"));
+
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/x-wav; codecs=\"1, mp4a\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe,
+            CanPlay("'audio/x-wav; codecs=\"1, opus\"'"));
+  EXPECT_EQ(kTheoraProbably, CanPlay("'audio/x-wav; codecs=\"1, theora\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"1, vorbis\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe,
+            CanPlay("'audio/x-wav; codecs=\"opus, vorbis\"'"));
+  EXPECT_EQ(kTheoraProbably, CanPlay("'audio/x-wav; codecs=\"opus, theora\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/x-wav; codecs=\"vorbis, mp4a\"'"));
+
+  EXPECT_EQ(kMaybe, CanPlay("'audio/x-wav; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+}
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) {
+  EXPECT_EQ(kMaybe, CanPlay("'video/webm'"));
+
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, vorbis\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, vorbis\"'"));
+  EXPECT_EQ(kOpusProbably, CanPlay("'video/webm; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kOpusProbably, CanPlay("'video/webm; codecs=\"vp8.0, opus\"'"));
+
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9, vorbis\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0, vorbis\"'"));
+  EXPECT_EQ(kOpusProbably, CanPlay("'video/webm; codecs=\"vp9, opus\"'"));
+  EXPECT_EQ(kOpusProbably, CanPlay("'video/webm; codecs=\"vp9.0, opus\"'"));
+
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, vp9\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, vp9.0\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, theora\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, avc1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, avc3\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, 1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8.0, 1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, mp4a.40.2\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8.0, mp4a.40.2\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, 1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9.0, 1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, mp4a.40.2\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9.0, mp4a.40.2\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"theora\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"1\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc3\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"mp4a.40.2\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP8\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP8.0\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP9\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"Vp9.0\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP8, Vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp8, Vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"VP9, Opus\"'"));
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"vp9, Opus\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"unknown\"'"));
+
+  EXPECT_EQ(kMaybe, CanPlay("'audio/webm'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kOpusProbably, CanPlay("'audio/webm; codecs=\"opus\"'"));
+  EXPECT_EQ(kOpusProbably, CanPlay("'audio/webm; codecs=\"opus, vorbis\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8, vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8.0, vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8.0, opus\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9.0\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9, vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9.0, vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9, opus\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9.0, opus\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"1, opus\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"1, vorbis\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vorbis, mp4a\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc1\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc3\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"mp4a.40.2\"'"));
+
+  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"unknown\"'"));
+}
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
+  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg'"));
+  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"theora\"'"));
+  EXPECT_EQ(kOggVideoProbably,
+            CanPlay("'video/ogg; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kOggVideoProbably,
+            CanPlay("'video/ogg; codecs=\"theora, opus\"'"));
+  EXPECT_EQ(kOggVideoProbably,
+            CanPlay("'video/ogg; codecs=\"opus, vorbis\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp8\"'"));
+  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp9\"'"));
+  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc3\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1, vorbis\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc3, mp4a\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc3, vorbis\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1, vp8\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc3, vp9\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1, avc3\"'"));
+
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"mp4a.4.02\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc3.64001F, mp4a.40.2\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc1.4D401E, vorbis\"'"));
+  EXPECT_EQ(kTheoraAndPropProbablyElseMaybe,
+            CanPlay("'video/ogg; codecs=\"avc3.64001F, vorbis\"'"));
+
+  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg; codecs=\"Theora\"'"));
+  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg; codecs=\"Opus\"'"));
+  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg; codecs=\"Vorbis\"'"));
+  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg; codecs=\"Theora, Opus\"'"));
+  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg; codecs=\"Theora, Vorbis\"'"));
+
+  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe, CanPlay("'audio/ogg; codecs=\"opus\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe,
+            CanPlay("'audio/ogg; codecs=\"vorbis, opus\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kTheoraProbably, CanPlay("'audio/ogg; codecs=\"theora\"'"));
+  EXPECT_EQ(kTheoraProbably, CanPlay("'audio/ogg; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kTheoraProbably, CanPlay("'audio/ogg; codecs=\"theora, opus\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe, CanPlay("'audio/ogg; codecs=\"opus, 1\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vorbis, 1\"'"));
+
+  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vp8\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vp9\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kPropProbablyElseMaybe, CanPlay("'audio/ogg; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe, CanPlay("'audio/ogg; codecs=\"avc3\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe, CanPlay("'audio/ogg; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/ogg; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/ogg; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'audio/ogg; codecs=\"mp4a.40.2\"'"));
+
+  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg; codecs=\"Theora\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg; codecs=\"Opus\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg; codecs=\"Vorbis\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg; codecs=\"Theora, Vorbis\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg; codecs=\"Theora, Opus\"'"));
+
+  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kMaybe, CanPlay("'application/ogg'"));
+  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kTheoraProbably, CanPlay("'application/ogg; codecs=\"theora\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"opus\"'"));
+  EXPECT_EQ(kTheoraProbably,
+            CanPlay("'application/ogg; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kTheoraProbably,
+            CanPlay("'application/ogg; codecs=\"theora, opus\"'"));
+  EXPECT_EQ(kOpusProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"opus, vorbis\"'"));
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vp8\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vp9\"'"));
+  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc3\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1, vorbis\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc3, mp4a\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc3, vorbis\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1, vp8\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc3, vp9\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1, avc3\"'"));
+
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc3.64001F, mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc1.4D401E, vorbis\"'"));
+  EXPECT_EQ(kPropProbablyElseMaybe,
+            CanPlay("'application/ogg; codecs=\"avc3.64001F, vorbis\"'"));
+
+  EXPECT_EQ(kMaybe, CanPlay("'application/ogg; codecs=\"Theora\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'application/ogg; codecs=\"Vorbis\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'application/ogg; codecs=\"Opus\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'application/ogg; codecs=\"Theora, Vorbis\"'"));
+  EXPECT_EQ(kMaybe, CanPlay("'application/ogg; codecs=\"Theora, Opus\"'"));
+
+  EXPECT_EQ(kMaybe, CanPlay("'application/ogg; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+}
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
+  EXPECT_EQ(kNot, CanPlay("'video/mp3'"));
+  EXPECT_EQ(kNot, CanPlay("'video/mpeg'"));
+  EXPECT_EQ(kNot, CanPlay("'video/x-mp3'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg'"));
+
+  // audio/mpeg and audio/mp3 do not allow any codecs parameter
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc3\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc3.64001F\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp4a.40.2\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mpeg; codecs=\"opus\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably, CanPlay("'audio/mpeg; codecs=\"theora\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"vp8\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"vp9\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/mpeg; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/mpeg; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"avc2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mpeg; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc3\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc3.64001F\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"mp4a.40.2\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mp3; codecs=\"opus\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably, CanPlay("'audio/mp3; codecs=\"theora\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"vp8\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"vp9\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp3; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/mp3; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/mp3; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"avc2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp3; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"avc3\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"avc3.64001F\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.2\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/x-mp3; codecs=\"opus\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'audio/x-mp3; codecs=\"theora\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"vp8\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"vp9\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/x-mp3; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/x-mp3; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"avc2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-mp3; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+}
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1, avc3\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/mp4; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/mp4; codecs=\"avc3.64001F, mp4a.40.5\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"vp8\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"vp9\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1, vorbis\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3, vorbis\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/mp4; codecs=\"avc1.4D401E, vorbis\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/mp4; codecs=\"avc3.64001F, vorbis\"'"));
+
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/mp4; codecs=\"opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/mp4; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/mp4; codecs=\"vp9, opus\"'"));
+
+  EXPECT_EQ(kTheoraAndPropProbably, CanPlay("'video/mp4; codecs=\"theora\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/mp4; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/mp4; codecs=\"theora, mp4a\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/mp4; codecs=\"theora, mp4a.40.2\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/mp4; codecs=\"theora, avc1\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/mp4; codecs=\"theora, avc3\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/mp4; codecs=\"theora, avc1.4D401E\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/mp4; codecs=\"theora, avc3.64001F\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'video/mp4; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'video/mp4; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1, avc3\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"avc3.64001F, mp4a.40.5\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"vp8\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"vp9\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"vorbis\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1, vorbis\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3, vorbis\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"avc1.4D401E, vorbis\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"avc3.64001F, vorbis\"'"));
+
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'video/x-m4v; codecs=\"opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"vp9, opus\"'"));
+
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora, mp4a\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora, mp4a.40.2\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora, avc1\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora, avc3\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora, avc1.4D401E\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'video/x-m4v; codecs=\"theora, avc3.64001F\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'video/x-m4v; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'video/x-m4v; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.2\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3, mp4a\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3.64001F\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/mp4; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/mp4; codecs=\"avc3.64001F mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/mp4; codecs=\"mp4a, vorbis\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/mp4; codecs=\"mp4a.40.2, vorbis\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vorbis\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vp8\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vp9\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mp4; codecs=\"opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'audio/mp4; codecs=\"mp4a, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'audio/mp4; codecs=\"vorbis, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mp4; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/mp4; codecs=\"vp9, opus\"'"));
+
+  EXPECT_EQ(kTheoraAndPropProbably, CanPlay("'audio/mp4; codecs=\"theora\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'audio/mp4; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'audio/mp4; codecs=\"theora, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"avc1, vorbis\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/mp4; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/mp4; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.2\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3, mp4a\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3.64001F\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"avc3.64001F mp4a.40.2\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"mp4a, vorbis\"'"));
+  EXPECT_EQ(kPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"mp4a.40.2, vorbis\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vorbis\"'"));
+
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vp8\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vp8.0\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vp9\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"vp9.0\"'"));
+
+  EXPECT_EQ(kOpusAndPropProbably, CanPlay("'audio/x-m4a; codecs=\"opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"mp4a, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"vorbis, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kOpusAndPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"vp9, opus\"'"));
+
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"theora\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kTheoraAndPropProbably,
+            CanPlay("'audio/x-m4a; codecs=\"theora, mp4a\"'"));
+  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"avc1, vorbis\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/x-m4a; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kPropMaybe,
+            CanPlay("'audio/x-m4a; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc2\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+}
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) {
+  EXPECT_EQ(kHLSMaybe, CanPlay("'application/x-mpegurl'"));
+
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc1\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc3\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc3, mp4a\"'"));
+
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"mp4a.40.2\"'"));
+  EXPECT_EQ(kHLSProbably,
+        CanPlay("'application/x-mpegurl; codecs=\"avc1.4D401E, mp4a.40.2\"'"));
+  EXPECT_EQ(kHLSProbably,
+        CanPlay("'application/x-mpegurl; codecs=\"avc3.64001F, mp4a.40.5\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kHLSProbably, CanPlay("'application/x-mpegurl; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kHLSProbably, CanPlay("'application/x-mpegurl; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kHLSProbably, CanPlay("'application/x-mpegurl; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kHLSProbably, CanPlay("'application/x-mpegurl; codecs=\"vp8\"'"));
+  EXPECT_EQ(kHLSProbably, CanPlay("'application/x-mpegurl; codecs=\"vp9\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"vorbis\"'"));
+
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc1, vorbis\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc3, vorbis\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc1.4D401E, vorbis\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/x-mpegurl; codecs=\"avc3.64001F, vorbis\"'"));
+
+  EXPECT_EQ(kHLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"opus\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"vp9, opus\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"theora\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"theora, mp4a\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"theora, mp4a.40.2\"'"));
+
+  EXPECT_EQ(kHLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kHLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kHLSMaybe, CanPlay("'application/x-mpegurl; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kHLSMaybe,
+        CanPlay("'application/x-mpegurl; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kHLSMaybe,
+        CanPlay("'application/x-mpegurl; codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"avc2\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/x-mpegurl; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+
+  EXPECT_EQ(kHLSMaybe, CanPlay("'application/vnd.apple.mpegurl'"));
+
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, mp4a\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, mp4a\"'"));
+
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.4D401E\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.64001F\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40.2\"'"));
+
+  // TODO(amogh.bihani): Change these tests when bug 53193 is fixed.
+  // http://crbug.com/53193 ----------------------------------------------------
+  EXPECT_EQ(kHLSProbably,
+          CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.unknown\"'"));
+  EXPECT_EQ(kHLSProbably,
+          CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.unknown\"'"));
+  EXPECT_EQ(kHLSProbably,
+          CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.unknown\"'"));
+
+  EXPECT_EQ(kHLSProbably,
+          CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.\"'"));
+  EXPECT_EQ(kHLSProbably,
+          CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.\"'"));
+  EXPECT_EQ(kHLSProbably,
+          CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.\"'"));
+
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp8\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp9\"'"));
+  EXPECT_EQ(kHLSProbably,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"vorbis\"'"));
+
+  EXPECT_EQ(kHLSProbably,
+           CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, vorbis\"'"));
+  EXPECT_EQ(kHLSProbably,
+           CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, vorbis\"'"));
+  EXPECT_EQ(kHLSProbably,
+    CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.4D401E, vorbis\"'"));
+  EXPECT_EQ(kHLSProbably,
+    CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.64001F, vorbis\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"opus\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp8, opus\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"vp9, opus\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora\"'"));
+  EXPECT_EQ(kHLSMaybe,
+        CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora, vorbis\"'"));
+  EXPECT_EQ(kHLSMaybe,
+          CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora, mp4a\"'"));
+  EXPECT_EQ(kHLSMaybe,
+      CanPlay("'application/vnd.apple.mpegurl; codecs=\"theora, mp4a.40.2\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC1\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC1.4d401e\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC3\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC3.64001f\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"MP4A\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"MP4A.40.2\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC1, MP4\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"AVC3, MP4\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; "
+                    "codecs=\", AVC1.4D401E, MP4.40.2\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; "
+                    "codecs=\", AVC3.64001F, MP4.40.2\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc2\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc4\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1x\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3x\"'"));
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4ax\"'"));
+
+  EXPECT_EQ(kHLSMaybe,
+            CanPlay("'application/vnd.apple.mpegurl; codecs=\"unknown\"'"));
+  // ---------------------------------------------------------------------------
+}
+
+}  // namespace content
diff --git a/content/browser/media/webrtc_aecdump_browsertest.cc b/content/browser/media/webrtc_aecdump_browsertest.cc
index ff8cd14..2a4d8ea 100644
--- a/content/browser/media/webrtc_aecdump_browsertest.cc
+++ b/content/browser/media/webrtc_aecdump_browsertest.cc
@@ -11,8 +11,8 @@
 #include "base/test/trace_event_analyzer.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/webrtc_content_browsertest_base.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
diff --git a/content/browser/media/webrtc_browsertest.cc b/content/browser/media/webrtc_browsertest.cc
index 6b7ffaa..8bda016 100644
--- a/content/browser/media/webrtc_browsertest.cc
+++ b/content/browser/media/webrtc_browsertest.cc
@@ -9,9 +9,9 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/webrtc_content_browsertest_base.h"
 #include "media/audio/audio_manager.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -64,15 +64,23 @@
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
 // Timing out on ARM linux bot: http://crbug.com/238490
-#define MAYBE_CanSetupVideoCall DISABLED_CanSetupVideoCall
+#define MAYBE_CanSetupDefaultVideoCall DISABLED_CanSetupDefaultVideoCall
 #else
-#define MAYBE_CanSetupVideoCall CanSetupVideoCall
+#define MAYBE_CanSetupDefaultVideoCall CanSetupDefaultVideoCall
 #endif
 
 // These tests will make a complete PeerConnection-based call and verify that
 // video is playing for the call.
-IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupVideoCall) {
-  MakeTypicalPeerConnectionCall("call({video: true});");
+IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, MAYBE_CanSetupDefaultVideoCall) {
+  MakeTypicalPeerConnectionCall(
+      "callAndExpectResolution({video: true}, 640, 480);");
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CanSetupVideoCallWith1To1AspecRatio) {
+  const std::string javascript =
+      "callAndExpectResolution({video: {mandatory: {minWidth: 320,"
+      " maxWidth: 320, minHeight: 320, maxHeight: 320}}}, 320, 320);";
+  MakeTypicalPeerConnectionCall(javascript);
 }
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
@@ -302,11 +310,27 @@
           << "Must run with fake devices since the test will explicitly look "
           << "for the fake device signal.";
 
-  MakeTypicalPeerConnectionCall("callAndEnsureAudioMutingWorks();");
+  MakeTypicalPeerConnectionCall("callAndEnsureAudioTrackMutingWorks();");
+}
+
+IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest,
+                       EstablishAudioVideoCallAndVerifyUnmutingWorks) {
+  if (!media::AudioManager::Get()->HasAudioOutputDevices()) {
+    // See comment on EstablishAudioVideoCallAndVerifyMutingWorks.
+    LOG(INFO) << "Missing output devices: skipping test...";
+    return;
+  }
+
+  ASSERT_TRUE(CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kUseFakeDeviceForMediaStream))
+          << "Must run with fake devices since the test will explicitly look "
+          << "for the fake device signal.";
+
+  MakeTypicalPeerConnectionCall("callAndEnsureAudioTrackUnmutingWorks();");
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcBrowserTest, CallAndVerifyVideoMutingWorks) {
-  MakeTypicalPeerConnectionCall("callAndEnsureVideoMutingWorks();");
+  MakeTypicalPeerConnectionCall("callAndEnsureVideoTrackMutingWorks();");
 }
 
 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
diff --git a/content/browser/media/webrtc_getusermedia_browsertest.cc b/content/browser/media/webrtc_getusermedia_browsertest.cc
index 3b96b0b..03493c0 100644
--- a/content/browser/media/webrtc_getusermedia_browsertest.cc
+++ b/content/browser/media/webrtc_getusermedia_browsertest.cc
@@ -12,9 +12,9 @@
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/webrtc_content_browsertest_base.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/perf/perf_test.h"
@@ -315,6 +315,18 @@
 }
 
 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+                       RenderVideoTrackInMultipleTagsAndPause) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+  GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+  NavigateToURL(shell(), url);
+
+  ExecuteJavascriptAndWaitForOk("getUserMediaAndRenderInSeveralVideoTags();");
+}
+
+
+
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
                        GetUserMediaWithMandatorySourceID) {
   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
@@ -458,19 +470,14 @@
   std::string constraints_4_3 = GenerateGetUserMediaCall(
       kGetUserMediaAndAnalyseAndStop, 640, 640, 480, 480, 30, 30);
 
-  // TODO(mcasas): add more aspect ratios, in particular 16:10 crbug.com/275594.
-
   NavigateToURL(shell(), url);
-  ASSERT_EQ("4:3 letterbox",
+  ASSERT_EQ("w=640:h=480",
             ExecuteJavascriptAndReturnResult(constraints_4_3));
 }
 
 // This test calls getUserMedia and checks for aspect ratio behavior.
-// TODO(perkj): Enable this test as soon as crbug/349450 is fixed.
-// Currently the render pipeline doesn't support cropping where the new cropped
-// frame doesn't have the same top left coordinates as the original frame.
 IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
-                       DISABLED_TestGetUserMediaAspectRatio16To9) {
+                       TestGetUserMediaAspectRatio16To9) {
   ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
 
   GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
@@ -479,10 +486,25 @@
       kGetUserMediaAndAnalyseAndStop, 640, 640, 360, 360, 30, 30);
 
   NavigateToURL(shell(), url);
-  ASSERT_EQ("16:9 letterbox",
+  ASSERT_EQ("w=640:h=360",
             ExecuteJavascriptAndReturnResult(constraints_16_9));
 }
 
+// This test calls getUserMedia and checks for aspect ratio behavior.
+IN_PROC_BROWSER_TEST_P(WebRtcGetUserMediaBrowserTest,
+                       TestGetUserMediaAspectRatio1To1) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+
+  GURL url(embedded_test_server()->GetURL("/media/getusermedia.html"));
+
+  std::string constraints_1_1 = GenerateGetUserMediaCall(
+      kGetUserMediaAndAnalyseAndStop, 320, 320, 320, 320, 30, 30);
+
+  NavigateToURL(shell(), url);
+  ASSERT_EQ("w=320:h=320",
+            ExecuteJavascriptAndReturnResult(constraints_1_1));
+}
+
 namespace {
 
 struct UserMediaSizes {
diff --git a/content/browser/media/webrtc_internals.cc b/content/browser/media/webrtc_internals.cc
index 4f64cce..8ded1a0 100644
--- a/content/browser/media/webrtc_internals.cc
+++ b/content/browser/media/webrtc_internals.cc
@@ -289,6 +289,12 @@
 #endif
 }
 
+void WebRTCInternals::FileSelectionCanceled(void* params) {
+#if defined(ENABLE_WEBRTC)
+  SendUpdate("aecRecordingFileSelectionCancelled", NULL);
+#endif
+}
+
 void WebRTCInternals::OnRendererExit(int render_process_id) {
   // Iterates from the end of the list to remove the PeerConnections created
   // by the exitting renderer.
diff --git a/content/browser/media/webrtc_internals.h b/content/browser/media/webrtc_internals.h
index 8110336..7ff95b9 100644
--- a/content/browser/media/webrtc_internals.h
+++ b/content/browser/media/webrtc_internals.h
@@ -102,6 +102,8 @@
   FRIEND_TEST_ALL_PREFIXES(WebRtcBrowserTest, CallWithAecDump);
   FRIEND_TEST_ALL_PREFIXES(WebRtcBrowserTest,
                            CallWithAecDumpEnabledThenDisabled);
+  FRIEND_TEST_ALL_PREFIXES(WebRTCInternalsTest,
+                           AecRecordingFileSelectionCanceled);
 
   WebRTCInternals();
   virtual ~WebRTCInternals();
@@ -117,6 +119,7 @@
   virtual void FileSelected(const base::FilePath& path,
                             int index,
                             void* unused_params) OVERRIDE;
+  virtual void FileSelectionCanceled(void* params) OVERRIDE;
 
   // Called when a renderer exits (including crashes).
   void OnRendererExit(int render_process_id);
diff --git a/content/browser/media/webrtc_internals_browsertest.cc b/content/browser/media/webrtc_internals_browsertest.cc
index ed2a0da..8e071c7 100644
--- a/content/browser/media/webrtc_internals_browsertest.cc
+++ b/content/browser/media/webrtc_internals_browsertest.cc
@@ -9,9 +9,9 @@
 #include "base/values.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
 using std::string;
diff --git a/content/browser/media/webrtc_internals_message_handler.cc b/content/browser/media/webrtc_internals_message_handler.cc
index 7a31bb4..bffd509 100644
--- a/content/browser/media/webrtc_internals_message_handler.cc
+++ b/content/browser/media/webrtc_internals_message_handler.cc
@@ -75,7 +75,8 @@
                                              const base::Value* args) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
   std::vector<const base::Value*> args_vector;
-  args_vector.push_back(args);
+  if (args)
+    args_vector.push_back(args);
   base::string16 update = WebUI::GetJavascriptCall(command, args_vector);
 
   RenderFrameHost* host = web_ui()->GetWebContents()->GetMainFrame();
diff --git a/content/browser/media/webrtc_internals_ui_observer.h b/content/browser/media/webrtc_internals_ui_observer.h
index 8d2c60e..31082b6 100644
--- a/content/browser/media/webrtc_internals_ui_observer.h
+++ b/content/browser/media/webrtc_internals_ui_observer.h
@@ -18,7 +18,8 @@
  public:
   virtual ~WebRTCInternalsUIObserver() {}
 
-  // This is called on the browser IO thread.
+  // This is called on the browser IO thread. |args| can be NULL if there are no
+  // arguments.
   virtual void OnUpdate(const std::string& command,
                         const base::Value* args) = 0;
 };
diff --git a/content/browser/media/webrtc_internals_unittest.cc b/content/browser/media/webrtc_internals_unittest.cc
index e8fe15e..e4b0531 100644
--- a/content/browser/media/webrtc_internals_unittest.cc
+++ b/content/browser/media/webrtc_internals_unittest.cc
@@ -23,7 +23,8 @@
   virtual void OnUpdate(const std::string& command,
                         const base::Value* value) OVERRIDE {
     command_ = command;
-    value_.reset(value->DeepCopy());
+    if (value)
+      value_.reset(value->DeepCopy());
   }
 
   std::string command() {
@@ -270,4 +271,12 @@
   VerifyList(dict, "reports", list);
 }
 
+TEST_F(WebRTCInternalsTest, AecRecordingFileSelectionCanceled) {
+  scoped_ptr<MockWebRTCInternalsProxy> observer(new MockWebRTCInternalsProxy());
+  WebRTCInternals::GetInstance()->AddObserver(observer.get());
+  WebRTCInternals::GetInstance()->FileSelectionCanceled(NULL);
+  EXPECT_EQ("aecRecordingFileSelectionCancelled", observer->command());
+  EXPECT_EQ(NULL, observer->value());
+}
+
 }  // namespace content
diff --git a/content/browser/plugin_browsertest.cc b/content/browser/plugin_browsertest.cc
index 9c37d50..4fe4b13 100644
--- a/content/browser/plugin_browsertest.cc
+++ b/content/browser/plugin_browsertest.cc
@@ -12,11 +12,11 @@
 #include "content/public/browser/resource_dispatcher_host_delegate.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/common/shell_switches.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/net/url_request_mock_http_job.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/url_request/url_request.h"
diff --git a/content/browser/plugin_data_remover_impl_browsertest.cc b/content/browser/plugin_data_remover_impl_browsertest.cc
index 8308a51..3dfe492 100644
--- a/content/browser/plugin_data_remover_impl_browsertest.cc
+++ b/content/browser/plugin_data_remover_impl_browsertest.cc
@@ -10,9 +10,9 @@
 #include "content/browser/plugin_data_remover_impl.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
 
 namespace content {
 
diff --git a/content/browser/plugin_service_impl_browsertest.cc b/content/browser/plugin_service_impl_browsertest.cc
index e99f3e5..44f4754 100644
--- a/content/browser/plugin_service_impl_browsertest.cc
+++ b/content/browser/plugin_service_impl_browsertest.cc
@@ -13,10 +13,10 @@
 #include "content/public/browser/resource_context.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
 #include "content/public/test/test_browser_thread.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace content {
diff --git a/content/browser/power_profiler/power_data_provider_ia_win.cc b/content/browser/power_profiler/power_data_provider_ia_win.cc
new file mode 100644
index 0000000..597e3bd
--- /dev/null
+++ b/content/browser/power_profiler/power_data_provider_ia_win.cc
@@ -0,0 +1,90 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/power_profiler/power_data_provider_ia_win.h"
+
+#include "base/logging.h"
+
+namespace content {
+
+scoped_ptr<PowerDataProvider> PowerDataProvider::Create() {
+  scoped_ptr<PowerDataProviderIA> provider(new PowerDataProviderIA());
+  if (provider->Initialize())
+    return make_scoped_ptr<PowerDataProvider>(provider.release());
+
+  return make_scoped_ptr<PowerDataProvider>(NULL);
+}
+
+PowerDataProviderIA::PowerDataProviderIA()
+    : sockets_number_(0),
+      is_open_(false) {
+  for (int i = 0; i < PowerEvent::ID_COUNT; i++ )
+      power_msr_ids_[i] = -1;
+}
+
+PowerDataProviderIA::~PowerDataProviderIA() {
+}
+
+PowerEventVector PowerDataProviderIA::GetData() {
+  PowerEventVector events;
+
+  if (!energy_lib_.ReadSample())
+    return events;
+
+  PowerEvent event;
+  double package_power = 0.0;
+  double power[3];
+  int data_count;
+
+  for (int i = 0; i < sockets_number_; i++) {
+    if (power_msr_ids_[PowerEvent::SOC_PACKAGE] == -1)
+      break;
+
+    energy_lib_.GetPowerData(i,
+        power_msr_ids_[PowerEvent::SOC_PACKAGE], power, &data_count);
+    package_power += power[0];
+  }
+
+  event.type = PowerEvent::SOC_PACKAGE;
+  event.value = package_power;
+  event.time = base::TimeTicks::Now();
+  events.push_back(event);
+
+  return events;
+}
+
+bool PowerDataProviderIA::Initialize() {
+  if (is_open_)
+    return true;
+
+  if (!energy_lib_.IntelEnergyLibInitialize()) {
+    LOG(ERROR) << "Power Data Provider initialize failed!";
+    return false;
+  }
+
+  energy_lib_.GetNumNodes(&sockets_number_);
+
+  const std::wstring package_msr_name = L"Processor";
+
+  int msr_number;
+  energy_lib_.GetNumMsrs(&msr_number);
+
+  int func_id;
+  wchar_t name[32];
+  for(int i = 0; i < msr_number; i++) {
+    energy_lib_.GetMsrFunc(i, &func_id);
+    energy_lib_.GetMsrName(i, name);
+
+    if (func_id != 1)
+      continue;
+
+    if (package_msr_name.compare(name) == 0)
+      power_msr_ids_[PowerEvent::SOC_PACKAGE] = i;
+  }
+
+  is_open_ = true;
+  return true;
+}
+
+}  // namespace content
diff --git a/content/browser/power_profiler/power_data_provider_ia_win.h b/content/browser/power_profiler/power_data_provider_ia_win.h
new file mode 100644
index 0000000..1c30d5b
--- /dev/null
+++ b/content/browser/power_profiler/power_data_provider_ia_win.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_POWER_PROFILER_POWER_DATA_PROVIDER_IA_WIN_H_
+#define CONTENT_BROWSER_POWER_PROFILER_POWER_DATA_PROVIDER_IA_WIN_H_
+
+#include "base/basictypes.h"
+#include "content/browser/power_profiler/power_data_provider.h"
+#include "third_party/power_gadget/PowerGadgetLib.h"
+
+namespace content {
+
+// A class used to get power usage via Power Gadget API.
+class PowerDataProviderIA : public PowerDataProvider {
+ public:
+  PowerDataProviderIA();
+
+  virtual ~PowerDataProviderIA();
+
+  bool Initialize();
+  virtual PowerEventVector GetData() OVERRIDE;
+
+ private:
+  CIntelPowerGadgetLib energy_lib_;
+
+  int sockets_number_;
+  int power_msr_ids_[PowerEvent::ID_COUNT];
+  bool is_open_;
+  DISALLOW_COPY_AND_ASSIGN(PowerDataProviderIA);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_POWER_PROFILER_POWER_DATA_PROVIDER_IA_WIN_H_
diff --git a/content/browser/renderer_host/DEPS b/content/browser/renderer_host/DEPS
index 7d21550..6a9a8d3 100644
--- a/content/browser/renderer_host/DEPS
+++ b/content/browser/renderer_host/DEPS
@@ -23,6 +23,7 @@
     "+media/filters",
   ],
   "render_sandbox_host_linux\.cc": [
+    "+content/child/blink_platform_impl.h",
     "+third_party/WebKit/public/platform/linux/WebFontInfo.h",
     "+third_party/WebKit/public/web/WebKit.h",
   ],
@@ -40,4 +41,7 @@
   "render_view_host_impl\.(cc|h)": [
     "+content/browser/frame_host/frame_tree.h",
   ],
+  "render_widget_host_view_aura\.cc": [
+    "+content/browser/frame_host",
+  ],
 }
diff --git a/content/browser/renderer_host/clipboard_message_filter.cc b/content/browser/renderer_host/clipboard_message_filter.cc
index 64b12d78..ab0d2fb 100644
--- a/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/content/browser/renderer_host/clipboard_message_filter.cc
@@ -142,7 +142,7 @@
 // ui::Clipboard::WriteObjects().
 void ClipboardMessageFilter::WriteObjectsOnUIThread(
     const ui::Clipboard::ObjectMap* objects) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   static ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
   clipboard->WriteObjects(ui::CLIPBOARD_TYPE_COPY_PASTE, *objects);
 }
@@ -195,9 +195,11 @@
     case CLIPBOARD_FORMAT_HTML:
       *result = GetClipboard()->IsFormatAvailable(
           ui::Clipboard::GetHtmlFormatType(), type);
+      break;
     case CLIPBOARD_FORMAT_SMART_PASTE:
       *result = GetClipboard()->IsFormatAvailable(
           ui::Clipboard::GetWebKitSmartPasteFormatType(), type);
+      break;
     case CLIPBOARD_FORMAT_BOOKMARK:
 #if defined(OS_WIN) || defined(OS_MACOSX)
       *result = GetClipboard()->IsFormatAvailable(
@@ -205,6 +207,7 @@
 #else
       *result = false;
 #endif
+      break;
   }
 }
 
diff --git a/content/browser/renderer_host/compositing_iosurface_context_mac.h b/content/browser/renderer_host/compositing_iosurface_context_mac.h
index 55c20e2..f65c3c4 100644
--- a/content/browser/renderer_host/compositing_iosurface_context_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_context_mac.h
@@ -43,10 +43,12 @@
   // http://crbug.com/180463
   static scoped_refptr<CompositingIOSurfaceContext> Get(int window_number);
 
-  // Mark that all the currently existing GL contexts shouldn't be returned
-  // anymore by Get, but rather, new contexts should be created. This is
-  // called as a precaution when unexpected GL errors occur.
-  static void MarkExistingContextsAsNotShareable();
+  // Mark that all the GL contexts in the same sharegroup as this context as
+  // invalid, so they shouldn't be returned anymore by Get, but rather, new
+  // contexts should be created. This is called as a precaution when unexpected
+  // GL errors occur.
+  void PoisonContextAndSharegroup();
+  bool HasBeenPoisoned() const { return poisoned_; }
 
   CompositingIOSurfaceShaderPrograms* shader_program_cache() const {
     return shader_program_cache_.get();
@@ -78,7 +80,7 @@
 
   bool is_vsync_disabled_;
   scoped_ptr<CompositingIOSurfaceShaderPrograms> shader_program_cache_;
-  bool can_be_shared_;
+  bool poisoned_;
 
   bool initialized_is_intel_;
   bool is_intel_;
diff --git a/content/browser/renderer_host/compositing_iosurface_context_mac.mm b/content/browser/renderer_host/compositing_iosurface_context_mac.mm
index f9a639c..3d3e4ff 100644
--- a/content/browser/renderer_host/compositing_iosurface_context_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_context_mac.mm
@@ -20,8 +20,8 @@
 
 CoreAnimationStatus GetCoreAnimationStatus() {
   static CoreAnimationStatus status =
-      !CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableCoreAnimation) ?
+      CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kDisableCoreAnimation) ?
               CORE_ANIMATION_DISABLED : CORE_ANIMATION_ENABLED;
   return status;
 }
@@ -34,7 +34,7 @@
   // Return the context for this window_number, if it exists.
   WindowMap::iterator found = window_map()->find(window_number);
   if (found != window_map()->end()) {
-    DCHECK(found->second->can_be_shared_);
+    DCHECK(!found->second->poisoned_);
     return found->second;
   }
 
@@ -154,12 +154,14 @@
       shader_program_cache.Pass());
 }
 
-// static
-void CompositingIOSurfaceContext::MarkExistingContextsAsNotShareable() {
+void CompositingIOSurfaceContext::PoisonContextAndSharegroup() {
+  if (poisoned_)
+    return;
+
   for (WindowMap::iterator it = window_map()->begin();
        it != window_map()->end();
        ++it) {
-    it->second->can_be_shared_ = false;
+    it->second->poisoned_ = true;
   }
   window_map()->clear();
 }
@@ -177,7 +179,7 @@
       cgl_context_(cgl_context),
       is_vsync_disabled_(is_vsync_disabled),
       shader_program_cache_(shader_program_cache.Pass()),
-      can_be_shared_(true),
+      poisoned_(false),
       initialized_is_intel_(false),
       is_intel_(false),
       screen_(0) {
@@ -190,7 +192,7 @@
     gfx::ScopedCGLSetCurrentContext scoped_set_current_context(cgl_context_);
     shader_program_cache_->Reset();
   }
-  if (can_be_shared_) {
+  if (!poisoned_) {
     DCHECK(window_map()->find(window_number_) != window_map()->end());
     DCHECK(window_map()->find(window_number_)->second == this);
     window_map()->erase(window_number_);
diff --git a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
index 74be0f4..71e110e 100644
--- a/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_layer_mac.mm
@@ -27,21 +27,22 @@
     DCHECK(context_);
     needsDisplay_ = NO;
 
-    ScopedCAActionDisabler disabler;
     [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
+    [self setAnchorPoint:CGPointMake(0, 0)];
+    // Setting contents gravity is necessary to prevent the layer from being
+    // scaled during dyanmic resizes (especially with devtools open).
     [self setContentsGravity:kCAGravityTopLeft];
-    [self setFrame:NSRectToCGRect(
-        [renderWidgetHostView_->cocoa_view() bounds])];
-    if ([self respondsToSelector:(@selector(setContentsScale:))]) {
+    if (renderWidgetHostView_->compositing_iosurface_ &&
+        [self respondsToSelector:(@selector(setContentsScale:))]) {
       [self setContentsScale:
-          renderWidgetHostView_->backing_store_scale_factor_];
+          renderWidgetHostView_->compositing_iosurface_->scale_factor()];
     }
-    [self setNeedsDisplay];
   }
   return self;
 }
 
 - (void)disableCompositing{
+  // Disable the fade-out animation as the layer is removed.
   ScopedCAActionDisabler disabler;
   [self removeFromSuperlayer];
   renderWidgetHostView_ = nil;
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.h b/content/browser/renderer_host/compositing_iosurface_mac.h
index 18795af..fa13995 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.h
+++ b/content/browser/renderer_host/compositing_iosurface_mac.h
@@ -51,7 +51,7 @@
       scoped_refptr<CompositingIOSurfaceContext> current_context,
       uint64 io_surface_handle,
       const gfx::Size& size,
-      float scale_factor);
+      float scale_factor) WARN_UNUSED_RESULT;
 
   // Get the CGL renderer ID currently associated with this context.
   int GetRendererID();
@@ -64,7 +64,7 @@
       scoped_refptr<CompositingIOSurfaceContext> drawing_context,
       const gfx::Rect& window_rect,
       float window_scale_factor,
-      bool flush_drawable);
+      bool flush_drawable) WARN_UNUSED_RESULT;
 
   // Copy the data of the "live" OpenGL texture referring to this IOSurfaceRef
   // into |out|. The copied region is specified with |src_pixel_subrect| and
@@ -101,6 +101,10 @@
   // Returns true if asynchronous readback is supported on this system.
   bool IsAsynchronousReadbackSupported();
 
+  // Returns true if the offscreen context used by this surface has been
+  // poisoned.
+  bool HasBeenPoisoned() const;
+
  private:
   // Vertex structure for use in glDraw calls.
   struct SurfaceVertex {
@@ -204,7 +208,7 @@
   // Returns true if IOSurface is ready to render. False otherwise.
   bool MapIOSurfaceToTextureWithContextCurrent(
       const scoped_refptr<CompositingIOSurfaceContext>& current_context,
-      uint64 io_surface_handle);
+      uint64 io_surface_handle) WARN_UNUSED_RESULT;
 
   void UnrefIOSurfaceWithContextCurrent();
 
diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
index b98a1ba..e8fea29 100644
--- a/content/browser/renderer_host/compositing_iosurface_mac.mm
+++ b/content/browser/renderer_host/compositing_iosurface_mac.mm
@@ -38,11 +38,11 @@
 #else
 #define CHECK_GL_ERROR() do {                                           \
     GLenum gl_error = glGetError();                                     \
-    LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error :" << gl_error; \
+    LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
   } while (0)
 #define CHECK_AND_SAVE_GL_ERROR() do {                                  \
     GLenum gl_error = GetAndSaveGLError();                              \
-    LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error :" << gl_error; \
+    LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
   } while (0)
 #endif
 
@@ -393,6 +393,12 @@
   if (gl_error_ != GL_NO_ERROR) {
     LOG(ERROR) << "GL error in DrawIOSurface: " << gl_error_;
     result = false;
+    // If there was an error, clear the screen to a light grey to avoid
+    // rendering artifacts. If we're in a really bad way, this too may
+    // generate an error. Clear the GL error afterwards just in case.
+    glClearColor(0.8, 0.8, 0.8, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    glGetError();
   }
 
   // Try to finish previous copy requests after flush to get better pipelining.
@@ -576,6 +582,10 @@
   return true;
 }
 
+bool CompositingIOSurfaceMac::HasBeenPoisoned() const {
+  return offscreen_context_->HasBeenPoisoned();
+}
+
 base::Closure CompositingIOSurfaceMac::CopyToSelectedOutputWithinContext(
     const gfx::Rect& src_pixel_subrect,
     const gfx::Rect& dst_pixel_rect,
diff --git a/content/browser/renderer_host/database_message_filter.cc b/content/browser/renderer_host/database_message_filter.cc
index e266059..d0f07ba 100644
--- a/content/browser/renderer_host/database_message_filter.cc
+++ b/content/browser/renderer_host/database_message_filter.cc
@@ -57,12 +57,12 @@
 }
 
 void DatabaseMessageFilter::AddObserver() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   db_tracker_->AddObserver(this);
 }
 
 void DatabaseMessageFilter::RemoveObserver() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   db_tracker_->RemoveObserver(this);
 
   // If the renderer process died without closing all databases,
@@ -118,7 +118,8 @@
     const base::string16& vfs_file_name,
     int desired_flags,
     IPC::Message* reply_msg) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+  base::File file;
   base::PlatformFile file_handle = base::kInvalidPlatformFileValue;
   std::string origin_identifier;
   base::string16 database_name;
@@ -129,8 +130,8 @@
   // open handles to them in the database tracker to make sure they're
   // around for as long as needed.
   if (vfs_file_name.empty()) {
-    VfsBackend::OpenTempFileInDirectory(db_tracker_->DatabaseDirectory(),
-                                        desired_flags, &file_handle);
+    file = VfsBackend::OpenTempFileInDirectory(db_tracker_->DatabaseDirectory(),
+                                               desired_flags);
   } else if (DatabaseUtil::CrackVfsFileName(vfs_file_name, &origin_identifier,
                                             &database_name, NULL) &&
              !db_tracker_->IsDatabaseScheduledForDeletion(origin_identifier,
@@ -138,27 +139,33 @@
     base::FilePath db_file = DatabaseUtil::GetFullFilePathForVfsFile(
         db_tracker_.get(), vfs_file_name);
     if (!db_file.empty()) {
-        if (db_tracker_->IsIncognitoProfile()) {
-          db_tracker_->GetIncognitoFileHandle(vfs_file_name, &file_handle);
-          if (file_handle == base::kInvalidPlatformFileValue) {
-            VfsBackend::OpenFile(db_file,
-                                 desired_flags | SQLITE_OPEN_DELETEONCLOSE,
-                                 &file_handle);
-            if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE))
-              db_tracker_->SaveIncognitoFileHandle(vfs_file_name, file_handle);
+      if (db_tracker_->IsIncognitoProfile()) {
+        db_tracker_->GetIncognitoFileHandle(vfs_file_name, &file_handle);
+        if (file_handle == base::kInvalidPlatformFileValue) {
+          file =
+              VfsBackend::OpenFile(db_file,
+                                    desired_flags | SQLITE_OPEN_DELETEONCLOSE);
+          if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE)) {
+            file_handle = file.TakePlatformFile();
+            db_tracker_->SaveIncognitoFileHandle(vfs_file_name, file_handle);
           }
-        } else {
-          VfsBackend::OpenFile(db_file, desired_flags, &file_handle);
         }
+      } else {
+        file = VfsBackend::OpenFile(db_file, desired_flags);
       }
+    }
   }
 
   // Then we duplicate the file handle to make it useable in the renderer
   // process. The original handle is closed, unless we saved it in the
   // database tracker.
-  bool auto_close = !db_tracker_->HasSavedIncognitoFileHandle(vfs_file_name);
-  IPC::PlatformFileForTransit target_handle =
-      IPC::GetFileHandleForProcess(file_handle, PeerHandle(), auto_close);
+  IPC::PlatformFileForTransit target_handle;
+  if (file.IsValid()) {
+    target_handle = IPC::TakeFileHandleForProcess(file.Pass(), PeerHandle());
+  } else {
+    target_handle = IPC::GetFileHandleForProcess(file_handle, PeerHandle(),
+                                                 false);
+  }
 
   DatabaseHostMsg_OpenFile::WriteReplyParams(reply_msg, target_handle);
   Send(reply_msg);
@@ -176,7 +183,7 @@
     bool sync_dir,
     IPC::Message* reply_msg,
     int reschedule_count) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   // Return an error if the file name is invalid or if the file could not
   // be deleted after kNumDeleteRetries attempts.
@@ -221,7 +228,7 @@
 void DatabaseMessageFilter::OnDatabaseGetFileAttributes(
     const base::string16& vfs_file_name,
     IPC::Message* reply_msg) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   int32 attributes = -1;
   base::FilePath db_file =
       DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -235,7 +242,7 @@
 
 void DatabaseMessageFilter::OnDatabaseGetFileSize(
     const base::string16& vfs_file_name, IPC::Message* reply_msg) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   int64 size = 0;
   base::FilePath db_file =
       DatabaseUtil::GetFullFilePathForVfsFile(db_tracker_.get(), vfs_file_name);
@@ -248,7 +255,7 @@
 
 void DatabaseMessageFilter::OnDatabaseGetSpaceAvailable(
     const std::string& origin_identifier, IPC::Message* reply_msg) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(db_tracker_->quota_manager_proxy());
 
   QuotaManager* quota_manager =
@@ -285,7 +292,7 @@
     const base::string16& database_name,
     const base::string16& description,
     int64 estimated_size) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (!DatabaseUtil::IsValidOriginIdentifier(origin_identifier)) {
     RecordAction(base::UserMetricsAction("BadMessageTerminate_DBMF"));
@@ -304,7 +311,7 @@
 void DatabaseMessageFilter::OnDatabaseModified(
     const std::string& origin_identifier,
     const base::string16& database_name) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (!database_connections_.IsDatabaseOpened(
           origin_identifier, database_name)) {
     RecordAction(base::UserMetricsAction("BadMessageTerminate_DBMF"));
@@ -318,7 +325,7 @@
 void DatabaseMessageFilter::OnDatabaseClosed(
     const std::string& origin_identifier,
     const base::string16& database_name) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (!database_connections_.IsDatabaseOpened(
           origin_identifier, database_name)) {
     RecordAction(base::UserMetricsAction("BadMessageTerminate_DBMF"));
@@ -334,7 +341,7 @@
     const std::string& origin_identifier,
     const base::string16& database_name,
     int error) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (!DatabaseUtil::IsValidOriginIdentifier(origin_identifier)) {
     RecordAction(base::UserMetricsAction("BadMessageTerminate_DBMF"));
     BadMessageReceived();
@@ -348,7 +355,7 @@
     const std::string& origin_identifier,
     const base::string16& database_name,
     int64 database_size) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   if (database_connections_.IsOriginUsed(origin_identifier)) {
     Send(new DatabaseMsg_UpdateSize(origin_identifier, database_name,
                                     database_size));
@@ -358,7 +365,7 @@
 void DatabaseMessageFilter::OnDatabaseScheduledForDeletion(
     const std::string& origin_identifier,
     const base::string16& database_name) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   Send(new DatabaseMsg_CloseImmediately(origin_identifier, database_name));
 }
 
diff --git a/content/browser/renderer_host/gamepad_browser_message_filter.cc b/content/browser/renderer_host/gamepad_browser_message_filter.cc
index cd36e6a..e6e05f6 100644
--- a/content/browser/renderer_host/gamepad_browser_message_filter.cc
+++ b/content/browser/renderer_host/gamepad_browser_message_filter.cc
@@ -15,7 +15,7 @@
 }
 
 GamepadBrowserMessageFilter::~GamepadBrowserMessageFilter() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (is_started_)
     GamepadService::GetInstance()->RemoveConsumer();
 }
diff --git a/content/browser/renderer_host/gpu_message_filter.cc b/content/browser/renderer_host/gpu_message_filter.cc
index 8a14cf6..9928444 100644
--- a/content/browser/renderer_host/gpu_message_filter.cc
+++ b/content/browser/renderer_host/gpu_message_filter.cc
@@ -60,7 +60,7 @@
       share_contexts_(false),
       render_widget_helper_(render_widget_helper),
       weak_ptr_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
 #if defined(USE_AURA) || defined(OS_ANDROID)
   // We use the GPU process for UI on Aura, and we need to share renderer GL
@@ -78,7 +78,7 @@
 }
 
 GpuMessageFilter::~GpuMessageFilter() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   EndAllFrameSubscriptions();
 }
 
@@ -99,14 +99,14 @@
 void GpuMessageFilter::BeginFrameSubscription(
     int route_id,
     scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   linked_ptr<FrameSubscription> subscription(
       new FrameSubscription(route_id, subscriber.Pass()));
   BeginFrameSubscriptionInternal(subscription);
 }
 
 void GpuMessageFilter::EndFrameSubscription(int route_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   FrameSubscriptionList frame_subscription_list;
   frame_subscription_list.swap(frame_subscription_list_);
   for (FrameSubscriptionList::iterator it = frame_subscription_list.begin();
@@ -121,7 +121,7 @@
 void GpuMessageFilter::OnEstablishGpuChannel(
     CauseForGpuLaunch cause_for_gpu_launch,
     IPC::Message* reply_ptr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   scoped_ptr<IPC::Message> reply(reply_ptr);
 
   // TODO(apatrick): Eventually, this will return the route ID of a
@@ -159,7 +159,7 @@
     int32 surface_id,
     const GPUCreateCommandBufferConfig& init_params,
     IPC::Message* reply_ptr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   scoped_ptr<IPC::Message> reply(reply_ptr);
 
   GpuSurfaceTracker* surface_tracker = GpuSurfaceTracker::Get();
@@ -206,7 +206,7 @@
     scoped_ptr<IPC::Message> reply,
     const IPC::ChannelHandle& channel,
     const gpu::GPUInfo& gpu_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   GpuHostMsg_EstablishGpuChannel::WriteReplyParams(
       reply.get(), render_process_id_, channel, gpu_info);
@@ -215,7 +215,7 @@
 
 void GpuMessageFilter::CreateCommandBufferCallback(
     scoped_ptr<IPC::Message> reply, int32 route_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   GpuHostMsg_CreateViewCommandBuffer::WriteReplyParams(reply.get(), route_id);
   Send(reply.release());
 }
diff --git a/content/browser/renderer_host/ime_adapter_android.cc b/content/browser/renderer_host/ime_adapter_android.cc
index e32f530..266b65c 100644
--- a/content/browser/renderer_host/ime_adapter_android.cc
+++ b/content/browser/renderer_host/ime_adapter_android.cc
@@ -14,9 +14,11 @@
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/render_view_host_delegate.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_android.h"
+#include "content/common/frame_messages.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/native_web_keyboard_event.h"
@@ -196,52 +198,46 @@
 
 void ImeAdapterAndroid::SetEditableSelectionOffsets(JNIEnv*, jobject,
                                                     int start, int end) {
-  RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
-  if (!rwhi)
+  RenderFrameHost* rfh = GetFocusedFrame();
+  if (!rfh)
     return;
 
-  rwhi->Send(new ViewMsg_SetEditableSelectionOffsets(rwhi->GetRoutingID(),
+  rfh->Send(new FrameMsg_SetEditableSelectionOffsets(rfh->GetRoutingID(),
                                                      start, end));
 }
 
 void ImeAdapterAndroid::SetComposingRegion(JNIEnv*, jobject,
                                            int start, int end) {
-  RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
-  if (!rwhi)
+  RenderFrameHost* rfh = GetFocusedFrame();
+  if (!rfh)
     return;
 
   std::vector<blink::WebCompositionUnderline> underlines;
   underlines.push_back(
       blink::WebCompositionUnderline(0, end - start, SK_ColorBLACK, false));
 
-  rwhi->Send(new ViewMsg_SetCompositionFromExistingText(
-      rwhi->GetRoutingID(), start, end, underlines));
+  rfh->Send(new FrameMsg_SetCompositionFromExistingText(
+      rfh->GetRoutingID(), start, end, underlines));
 }
 
 void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*, jobject,
                                               int before, int after) {
-  RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
-  if (!rwhi)
-    return;
-
-  rwhi->Send(new ViewMsg_ExtendSelectionAndDelete(rwhi->GetRoutingID(),
-                                                  before, after));
+  RenderFrameHostImpl* rfh =
+      static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
+  if (rfh)
+    rfh->ExtendSelectionAndDelete(before, after);
 }
 
 void ImeAdapterAndroid::Unselect(JNIEnv* env, jobject) {
-  RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
-  if (!rwhi)
-    return;
-
-  rwhi->Unselect();
+  RenderFrameHost* rfh = GetFocusedFrame();
+  if (rfh)
+    rfh->Unselect();
 }
 
 void ImeAdapterAndroid::SelectAll(JNIEnv* env, jobject) {
-  RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
-  if (!rwhi)
-    return;
-
-  rwhi->SelectAll();
+  RenderFrameHost* rfh = GetFocusedFrame();
+  if (rfh)
+    rfh->SelectAll();
 }
 
 void ImeAdapterAndroid::Cut(JNIEnv* env, jobject) {
@@ -267,7 +263,7 @@
 }
 
 RenderWidgetHostImpl* ImeAdapterAndroid::GetRenderWidgetHostImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(rwhva_);
   RenderWidgetHost* rwh = rwhva_->GetRenderWidgetHost();
   if (!rwh)
@@ -283,10 +279,8 @@
   if (!rwh->IsRenderView())
     return NULL;
   RenderViewHost* rvh = RenderViewHost::From(rwh);
-  RenderFrameHostImpl* rfh =
-      static_cast<RenderFrameHostImpl*>(rvh->GetMainFrame());
   FrameTreeNode* focused_frame =
-      rfh->frame_tree_node()->frame_tree()->GetFocusedFrame();
+      rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
   if (!focused_frame)
     return NULL;
 
diff --git a/content/browser/renderer_host/input/gesture_event_queue.h b/content/browser/renderer_host/input/gesture_event_queue.h
index 8cbb253..4c34070 100644
--- a/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/content/browser/renderer_host/input/gesture_event_queue.h
@@ -68,6 +68,8 @@
 
   // Returns |true| if the caller should immediately forward the provided
   // |GestureEventWithLatencyInfo| argument to the renderer.
+  // If this function returns false, then the event may be queued and forwared
+  // at a later point.
   bool ShouldForward(const GestureEventWithLatencyInfo&);
 
   // Indicates that the caller has received an acknowledgement from the renderer
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index bc17077..1028668 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -242,6 +242,7 @@
     const GestureEventWithLatencyInfo& original_gesture_event) {
   event_stream_validator_.OnEvent(original_gesture_event.event);
   GestureEventWithLatencyInfo gesture_event(original_gesture_event);
+
   if (touch_action_filter_.FilterGestureEvent(&gesture_event.event))
     return;
 
@@ -311,8 +312,9 @@
 }
 
 bool InputRouterImpl::ShouldForwardTouchEvent() const {
-  // Always send a touch event if the renderer has a touch-event handler.
-  return touch_event_queue_->has_handlers();
+  // Always send a touch event if the renderer has a touch-event handler or
+  // there are pending touch events.
+  return touch_event_queue_->has_handlers() || !touch_event_queue_->empty();
 }
 
 void InputRouterImpl::OnViewUpdated(int view_flags) {
@@ -419,6 +421,18 @@
 void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event,
                                       const ui::LatencyInfo& latency_info,
                                       bool is_keyboard_shortcut) {
+  // Trackpad pinch gestures are not yet handled by the renderer.
+  // TODO(rbyers): Send mousewheel for trackpad pinch - crbug.com/289887.
+  if (input_event.type == WebInputEvent::GesturePinchUpdate &&
+      static_cast<const WebGestureEvent&>(input_event).sourceDevice ==
+          WebGestureEvent::Touchpad) {
+    ProcessInputEventAck(input_event.type,
+                         INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+                         latency_info,
+                         ACK_SOURCE_NONE);
+    return;
+  }
+
   if (OfferToOverscrollController(input_event, latency_info))
     return;
 
@@ -568,6 +582,8 @@
 void InputRouterImpl::OnSetTouchAction(TouchAction touch_action) {
   // Synthetic touchstart events should get filtered out in RenderWidget.
   DCHECK(touch_event_queue_->IsPendingAckTouchStart());
+  TRACE_EVENT1("input", "InputRouterImpl::OnSetTouchAction",
+               "action", touch_action);
 
   touch_action_filter_.OnSetTouchAction(touch_action);
 
diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 37fe462..9f6760b 100644
--- a/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -965,6 +965,8 @@
   EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
 
   // GesturePinchUpdate waits for an ack.
+  // This also verifies that GesturePinchUpdates for touchscreen are sent
+  // to the renderer (in contrast to the TrackpadPinchUpdate test).
   SimulateGestureEvent(WebInputEvent::GesturePinchUpdate,
                        WebGestureEvent::Touchscreen);
   EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
@@ -1297,4 +1299,19 @@
   EXPECT_EQ(0, client_->in_flight_event_count());
 }
 
+// Test that GesturePinchUpdate is handled specially for trackpad
+TEST_F(InputRouterImplTest, TrackpadPinchUpdate) {
+  // For now Trackpad PinchUpdate events are just immediately ACKed
+  // as unconsumed without going to the renderer.
+  // TODO(rbyers): Update for wheel event behavior - crbug.com/289887.
+  // Note that the Touchscreen case is verified as NOT doing this as
+  // part of the ShowPressIsInOrder test.
+  SimulateGestureEvent(WebInputEvent::GesturePinchUpdate,
+                       WebGestureEvent::Touchpad);
+  ASSERT_EQ(0U, GetSentMessageCountAndResetSink());
+  EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+  EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_handler_->ack_state());
+  EXPECT_EQ(0, client_->in_flight_event_count());
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index 433ab20..e7a9f9d 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -519,8 +519,9 @@
       static_cast<MockScrollGestureTarget*>(target_);
   EXPECT_EQ(1, num_success_);
   EXPECT_EQ(0, num_failure_);
+  // TODO(dominikg): Remove adjustment when crbug.com/332418 is fixed.
   EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
-            scroll_target->start_to_end_distance());
+            scroll_target->start_to_end_distance() - gfx::Vector2dF(0, 0.001f));
 }
 
 TEST_F(SyntheticGestureControllerTest, SingleScrollGestureTouchHorizontal) {
@@ -540,8 +541,15 @@
       static_cast<MockScrollGestureTarget*>(target_);
   EXPECT_EQ(1, num_success_);
   EXPECT_EQ(0, num_failure_);
-  EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
-            scroll_target->start_to_end_distance());
+  // TODO(dominikg): Use vector comparison when crbug.com/332418 is fixed.
+  //EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_),
+  //          scroll_target->start_to_end_distance());
+  EXPECT_EQ(AddTouchSlopToVector(params.distances[0], target_).x(),
+            scroll_target->start_to_end_distance().x());
+  EXPECT_LT(AddTouchSlopToVector(params.distances[0], target_).y(),
+            scroll_target->start_to_end_distance().y());
+  EXPECT_GE(AddTouchSlopToVector(params.distances[0], target_).y(),
+            scroll_target->start_to_end_distance().y() - 0.001f);
 }
 
 void CheckIsWithinRangeSingle(float scroll_distance,
@@ -831,13 +839,14 @@
       static_cast<MockScrollGestureTarget*>(target_);
   EXPECT_EQ(1, num_success_);
   EXPECT_EQ(0, num_failure_);
+  // TODO(dominikg): Remove adjustment when crbug.com/332418 is fixed.
   EXPECT_FLOAT_EQ(
       params.distances[0].Length() + params.distances[1].Length() +
           target_->GetTouchSlopInDips(),
-      scroll_target->total_abs_scroll_distance_length());
+      scroll_target->total_abs_scroll_distance_length() - 0.001f);
   EXPECT_EQ(AddTouchSlopToVector(params.distances[0] + params.distances[1],
                                  target_),
-            scroll_target->start_to_end_distance());
+            scroll_target->start_to_end_distance() - gfx::Vector2dF(0, 0.001f));
 }
 
 TEST_F(SyntheticGestureControllerTest, PinchGestureTouchZoomIn) {
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
index 4c8ab16..5f2bb2d 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_target_base.cc
@@ -21,8 +21,8 @@
 namespace {
 
 // This value was determined experimentally. It was sufficient to not cause a
-// fling on Android.
-const int kPointerAssumedStoppedTimeMs = 50;
+// fling on Android and Aura.
+const int kPointerAssumedStoppedTimeMs = 100;
 
 // SyntheticGestureTargetBase passes input events straight on to the renderer
 // without going through a gesture recognition framework. There is thus no touch
diff --git a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
index d4bfbfe..1af3dca 100644
--- a/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
+++ b/content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc
@@ -106,6 +106,12 @@
                           target->PointerAssumedStoppedTime();
         // Send one last move event, but don't change the location. Without this
         // we'd still sometimes cause a fling on Android.
+
+        // Required to suppress flings on Aura, see
+        // |UpdateWebTouchPointFromUIEvent|, remove when crbug.com/332418
+        // is fixed.
+        touch_event_.touches[0].position.y += 0.001f;
+
         ForwardTouchEvent(target, event_timestamp);
         ReleaseTouchPoint(target, event_timestamp);
         state_ = DONE;
diff --git a/content/browser/renderer_host/input/touch_action_browsertest.cc b/content/browser/renderer_host/input/touch_action_browsertest.cc
index 61a0516..9c49ca2 100644
--- a/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -22,10 +22,10 @@
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/events/event_switches.h"
 #include "ui/events/latency_info.h"
@@ -189,9 +189,16 @@
   }
 }
 
+// TouchActionBrowserTest.TouchActionNone fails under ThreadSanitizer v2,
+// see http://crbug.com/357505.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_TouchActionNone DISABLED_TouchActionNone
+#else
+#define MAYBE_TouchActionNone TouchActionNone
+#endif
 // Verify that touching a touch-action: none region disables scrolling and
 // enables all touch events to be sent.
-IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, TouchActionNone) {
+IN_PROC_BROWSER_TEST_F(TouchActionBrowserTest, MAYBE_TouchActionNone) {
   LoadURL();
 
   bool scrolled = DoTouchScroll(gfx::Point(50, 150), gfx::Vector2d(0, 45));
diff --git a/content/browser/renderer_host/input/touch_input_browsertest.cc b/content/browser/renderer_host/input/touch_input_browsertest.cc
index 5154473..59a3625 100644
--- a/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -13,9 +13,9 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/events/event_switches.h"
 #include "ui/events/latency_info.h"
diff --git a/content/browser/renderer_host/input/web_input_event_builders_android.cc b/content/browser/renderer_host/input/web_input_event_builders_android.cc
index a2ed46fc..a76df16 100644
--- a/content/browser/renderer_host/input/web_input_event_builders_android.cc
+++ b/content/browser/renderer_host/input/web_input_event_builders_android.cc
@@ -133,10 +133,4 @@
   return result;
 }
 
-blink::WebTouchEvent WebTouchEventBuilder::Build(
-    const MotionEventAndroid& event,
-    float scale) {
-  return CreateWebTouchEventFromMotionEvent(event, scale);
-}
-
 }  // namespace content
diff --git a/content/browser/renderer_host/input/web_input_event_builders_android.h b/content/browser/renderer_host/input/web_input_event_builders_android.h
index 656c233..49b0a65 100644
--- a/content/browser/renderer_host/input/web_input_event_builders_android.h
+++ b/content/browser/renderer_host/input/web_input_event_builders_android.h
@@ -57,12 +57,6 @@
                                       int y);
 };
 
-class WebTouchEventBuilder {
- public:
-  static blink::WebTouchEvent Build(const MotionEventAndroid& event,
-                                    float scale);
-};
-
 }  // namespace content
 
 #endif  // CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_BUILDERS_ANDROID_H_
diff --git a/content/browser/renderer_host/input/web_input_event_util.cc b/content/browser/renderer_host/input/web_input_event_util.cc
index 52063fa..75e762c 100644
--- a/content/browser/renderer_host/input/web_input_event_util.cc
+++ b/content/browser/renderer_host/input/web_input_event_util.cc
@@ -246,67 +246,67 @@
   switch (data.type) {
     case ui::ET_GESTURE_SHOW_PRESS:
       gesture.type = WebInputEvent::GestureShowPress;
-      gesture.data.showPress.width = data.details.show_press.width * scale;
-      gesture.data.showPress.width = data.details.show_press.width * scale;
+      gesture.data.showPress.width =
+          data.details.bounding_box_f().width() * scale;
+      gesture.data.showPress.height =
+          data.details.bounding_box_f().height() * scale;
       break;
     case ui::ET_GESTURE_DOUBLE_TAP:
       gesture.type = WebInputEvent::GestureDoubleTap;
-      DCHECK_EQ(1, data.details.tap.tap_count);
-      gesture.data.tap.tapCount = data.details.tap.tap_count;
-      gesture.data.tap.width = data.details.tap.width * scale;
-      gesture.data.tap.height = data.details.tap.height * scale;
+      DCHECK_EQ(1, data.details.tap_count());
+      gesture.data.tap.tapCount = data.details.tap_count();
+      gesture.data.tap.width = data.details.bounding_box_f().width() * scale;
+      gesture.data.tap.height = data.details.bounding_box_f().height() * scale;
       break;
     case ui::ET_GESTURE_TAP:
       gesture.type = WebInputEvent::GestureTap;
-      DCHECK_EQ(1, data.details.tap.tap_count);
-      gesture.data.tap.tapCount = data.details.tap.tap_count;
-      gesture.data.tap.width = data.details.tap.width * scale;
-      gesture.data.tap.height = data.details.tap.height * scale;
+      DCHECK_EQ(1, data.details.tap_count());
+      gesture.data.tap.tapCount = data.details.tap_count();
+      gesture.data.tap.width = data.details.bounding_box_f().width() * scale;
+      gesture.data.tap.height = data.details.bounding_box_f().height() * scale;
       break;
     case ui::ET_GESTURE_TAP_UNCONFIRMED:
       gesture.type = WebInputEvent::GestureTapUnconfirmed;
-      DCHECK_EQ(1, data.details.tap.tap_count);
-      gesture.data.tap.tapCount = data.details.tap.tap_count;
-      gesture.data.tap.width = data.details.tap.width * scale;
-      gesture.data.tap.height = data.details.tap.height * scale;
+      DCHECK_EQ(1, data.details.tap_count());
+      gesture.data.tap.tapCount = data.details.tap_count();
+      gesture.data.tap.width = data.details.bounding_box_f().width() * scale;
+      gesture.data.tap.height = data.details.bounding_box_f().height() * scale;
       break;
     case ui::ET_GESTURE_LONG_PRESS:
       gesture.type = WebInputEvent::GestureLongPress;
-      gesture.data.longPress.width = data.details.long_press.width * scale;
-      gesture.data.longPress.height = data.details.long_press.height * scale;
+      gesture.data.longPress.width =
+          data.details.bounding_box_f().width() * scale;
+      gesture.data.longPress.height =
+          data.details.bounding_box_f().height() * scale;
       break;
     case ui::ET_GESTURE_LONG_TAP:
       gesture.type = WebInputEvent::GestureLongTap;
-      gesture.data.longPress.width = data.details.long_press.width * scale;
-      gesture.data.longPress.height = data.details.long_press.height * scale;
+      gesture.data.longPress.width =
+          data.details.bounding_box_f().width() * scale;
+      gesture.data.longPress.height =
+          data.details.bounding_box_f().height() * scale;
       break;
     case ui::ET_GESTURE_SCROLL_BEGIN:
       gesture.type = WebInputEvent::GestureScrollBegin;
       gesture.data.scrollBegin.deltaXHint =
-          data.details.scroll_begin.delta_x_hint * scale;
+          data.details.scroll_x_hint() * scale;
       gesture.data.scrollBegin.deltaYHint =
-          data.details.scroll_begin.delta_y_hint * scale;
+          data.details.scroll_y_hint() * scale;
       break;
     case ui::ET_GESTURE_SCROLL_UPDATE:
       gesture.type = WebInputEvent::GestureScrollUpdate;
-      gesture.data.scrollUpdate.deltaX =
-          data.details.scroll_update.delta_x * scale;
-      gesture.data.scrollUpdate.deltaY =
-          data.details.scroll_update.delta_y * scale;
-      gesture.data.scrollUpdate.velocityX =
-          data.details.scroll_update.velocity_x * scale;
-      gesture.data.scrollUpdate.velocityY =
-          data.details.scroll_update.velocity_y * scale;
+      gesture.data.scrollUpdate.deltaX = data.details.scroll_x() * scale;
+      gesture.data.scrollUpdate.deltaY = data.details.scroll_y() * scale;
+      gesture.data.scrollUpdate.velocityX = data.details.velocity_x() * scale;
+      gesture.data.scrollUpdate.velocityY = data.details.velocity_y() * scale;
       break;
     case ui::ET_GESTURE_SCROLL_END:
       gesture.type = WebInputEvent::GestureScrollEnd;
       break;
     case ui::ET_SCROLL_FLING_START:
       gesture.type = WebInputEvent::GestureFlingStart;
-      gesture.data.flingStart.velocityX =
-          data.details.fling_start.velocity_x * scale;
-      gesture.data.flingStart.velocityY =
-          data.details.fling_start.velocity_y * scale;
+      gesture.data.flingStart.velocityX = data.details.velocity_x() * scale;
+      gesture.data.flingStart.velocityY = data.details.velocity_y() * scale;
       break;
     case ui::ET_SCROLL_FLING_CANCEL:
       gesture.type = WebInputEvent::GestureFlingCancel;
@@ -316,7 +316,7 @@
       break;
     case ui::ET_GESTURE_PINCH_UPDATE:
       gesture.type = WebInputEvent::GesturePinchUpdate;
-      gesture.data.pinchUpdate.scale = data.details.pinch_update.scale;
+      gesture.data.pinchUpdate.scale = data.details.scale();
       break;
     case ui::ET_GESTURE_PINCH_END:
       gesture.type = WebInputEvent::GesturePinchEnd;
@@ -326,8 +326,10 @@
       break;
     case ui::ET_GESTURE_TAP_DOWN:
       gesture.type = WebInputEvent::GestureTapDown;
-      gesture.data.tapDown.width = data.details.tap_down.width * scale;
-      gesture.data.tapDown.height = data.details.tap_down.height * scale;
+      gesture.data.tapDown.width =
+          data.details.bounding_box_f().width() * scale;
+      gesture.data.tapDown.height =
+          data.details.bounding_box_f().height() * scale;
       break;
     default:
       NOTREACHED() << "ui::EventType provided wasn't a valid gesture event.";
diff --git a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
index 45a9a04..25f31de 100644
--- a/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
+++ b/content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc
@@ -114,7 +114,7 @@
 }
 
 void JavaBridgeDispatcherHostManager::DocumentAvailableInMainFrame() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // Called when the window object has been cleared in the main frame.
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> retained_object_set =
@@ -134,7 +134,7 @@
 
 void JavaBridgeDispatcherHostManager::JavaBoundObjectCreated(
     const base::android::JavaRef<jobject>& object) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> retained_object_set =
@@ -146,7 +146,7 @@
 
 void JavaBridgeDispatcherHostManager::JavaBoundObjectDestroyed(
     const base::android::JavaRef<jobject>& object) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   JNIEnv* env = base::android::AttachCurrentThread();
   base::android::ScopedJavaLocalRef<jobject> retained_object_set =
diff --git a/content/browser/renderer_host/media/audio_input_device_manager.cc b/content/browser/renderer_host/media/audio_input_device_manager.cc
index dc4b1e3..8d0377d 100644
--- a/content/browser/renderer_host/media/audio_input_device_manager.cc
+++ b/content/browser/renderer_host/media/audio_input_device_manager.cc
@@ -45,7 +45,7 @@
 
 const StreamDeviceInfo* AudioInputDeviceManager::GetOpenedDeviceInfoById(
     int session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   StreamDeviceList::iterator device = GetDevice(session_id);
   if (device == devices_.end())
     return NULL;
@@ -56,7 +56,7 @@
 void AudioInputDeviceManager::Register(
     MediaStreamProviderListener* listener,
     const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!listener_);
   DCHECK(!device_task_runner_);
   listener_ = listener;
@@ -69,7 +69,7 @@
 }
 
 void AudioInputDeviceManager::EnumerateDevices(MediaStreamType stream_type) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(listener_);
 
   device_task_runner_->PostTask(
@@ -79,7 +79,7 @@
 }
 
 int AudioInputDeviceManager::Open(const StreamDeviceInfo& device) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // Generate a new id for this device.
   int session_id = next_capture_session_id_++;
   device_task_runner_->PostTask(
@@ -91,7 +91,7 @@
 }
 
 void AudioInputDeviceManager::Close(int session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(listener_);
   StreamDeviceList::iterator device = GetDevice(session_id);
   if (device == devices_.end())
@@ -109,12 +109,12 @@
 }
 
 void AudioInputDeviceManager::UseFakeDevice() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   use_fake_device_ = true;
 }
 
 bool AudioInputDeviceManager::ShouldUseFakeDevice() const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   return use_fake_device_;
 }
 
@@ -215,7 +215,7 @@
 void AudioInputDeviceManager::DevicesEnumeratedOnIOThread(
     MediaStreamType stream_type,
     scoped_ptr<StreamDeviceInfoArray> devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // Ensure that |devices| gets deleted on exit.
   if (listener_)
     listener_->DevicesEnumerated(stream_type, *devices);
@@ -223,7 +223,7 @@
 
 void AudioInputDeviceManager::OpenedOnIOThread(int session_id,
                                                const StreamDeviceInfo& info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK_EQ(session_id, info.session_id);
   DCHECK(GetDevice(session_id) == devices_.end());
 
@@ -235,7 +235,7 @@
 
 void AudioInputDeviceManager::ClosedOnIOThread(MediaStreamType stream_type,
                                                int session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (listener_)
     listener_->Closed(stream_type, session_id);
 }
diff --git a/content/browser/renderer_host/media/audio_input_renderer_host.cc b/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 931def4..67067c7 100644
--- a/content/browser/renderer_host/media/audio_input_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_input_renderer_host.cc
@@ -118,7 +118,7 @@
 
 void AudioInputRendererHost::DoCompleteCreation(
     media::AudioInputController* controller) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* entry = LookupByController(controller);
   if (!entry)
@@ -172,7 +172,7 @@
 
 void AudioInputRendererHost::DoSendRecordingMessage(
     media::AudioInputController* controller) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // TODO(henrika): See crbug.com/115262 for details on why this method
   // should be implemented.
 }
@@ -180,7 +180,7 @@
 void AudioInputRendererHost::DoHandleError(
     media::AudioInputController* controller,
     media::AudioInputController::ErrorCode error_code) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   MediaStreamManager::SendMessageToNativeLog(
       base::StringPrintf("AudioInputController error: %d", error_code));
 
@@ -211,7 +211,7 @@
     int render_view_id,
     int session_id,
     const AudioInputHostMsg_CreateStream_Config& config) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   DVLOG(1) << "AudioInputRendererHost@" << this
            << "::OnCreateStream(stream_id=" << stream_id
@@ -323,7 +323,7 @@
 }
 
 void AudioInputRendererHost::OnRecordStream(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* entry = LookupById(stream_id);
   if (!entry) {
@@ -336,7 +336,7 @@
 }
 
 void AudioInputRendererHost::OnCloseStream(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* entry = LookupById(stream_id);
 
@@ -345,7 +345,7 @@
 }
 
 void AudioInputRendererHost::OnSetVolume(int stream_id, double volume) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* entry = LookupById(stream_id);
   if (!entry) {
@@ -366,7 +366,7 @@
 }
 
 void AudioInputRendererHost::DeleteEntries() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   for (AudioEntryMap::iterator i = audio_entries_.begin();
        i != audio_entries_.end(); ++i) {
@@ -375,7 +375,7 @@
 }
 
 void AudioInputRendererHost::CloseAndDeleteStream(AudioEntry* entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!entry->pending_close) {
     entry->controller->Close(base::Bind(&AudioInputRendererHost::DeleteEntry,
@@ -386,7 +386,7 @@
 }
 
 void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Delete the entry when this method goes out of scope.
   scoped_ptr<AudioEntry> entry_deleter(entry);
@@ -397,7 +397,7 @@
 
 void AudioInputRendererHost::DeleteEntryOnError(AudioEntry* entry,
     ErrorCode error_code) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Sends the error message first before we close the stream because
   // |entry| is destroyed in DeleteEntry().
@@ -407,7 +407,7 @@
 
 AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupById(
     int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntryMap::iterator i = audio_entries_.find(stream_id);
   if (i != audio_entries_.end())
@@ -417,7 +417,7 @@
 
 AudioInputRendererHost::AudioEntry* AudioInputRendererHost::LookupByController(
     media::AudioInputController* controller) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Iterate the map of entries.
   // TODO(hclam): Implement a faster look up method.
diff --git a/content/browser/renderer_host/media/audio_renderer_host.cc b/content/browser/renderer_host/media/audio_renderer_host.cc
index 3d5b36f..ea633c0 100644
--- a/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -204,7 +204,7 @@
 }
 
 void AudioRendererHost::DoCompleteCreation(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!PeerHandle()) {
     DLOG(WARNING) << "Renderer process handle is invalid.";
@@ -254,7 +254,7 @@
 
 void AudioRendererHost::DoNotifyStreamStateChanged(int stream_id,
                                                    bool is_playing) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* const entry = LookupById(stream_id);
   if (!entry)
@@ -285,7 +285,7 @@
 
 RenderViewHost::AudioOutputControllerList
 AudioRendererHost::DoGetOutputControllers(int render_view_id) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   RenderViewHost::AudioOutputControllerList controllers;
   AudioEntryMap::const_iterator it = audio_entries_.begin();
@@ -318,7 +318,7 @@
 void AudioRendererHost::OnCreateStream(
     int stream_id, int render_view_id, int render_frame_id, int session_id,
     const media::AudioParameters& params) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   DVLOG(1) << "AudioRendererHost@" << this
            << "::OnCreateStream(stream_id=" << stream_id
@@ -382,7 +382,7 @@
 }
 
 void AudioRendererHost::OnPlayStream(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* entry = LookupById(stream_id);
   if (!entry) {
@@ -395,7 +395,7 @@
 }
 
 void AudioRendererHost::OnPauseStream(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* entry = LookupById(stream_id);
   if (!entry) {
@@ -408,7 +408,7 @@
 }
 
 void AudioRendererHost::OnSetVolume(int stream_id, double volume) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntry* entry = LookupById(stream_id);
   if (!entry) {
@@ -429,7 +429,7 @@
 }
 
 void AudioRendererHost::OnCloseStream(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Prevent oustanding callbacks from attempting to close/delete the same
   // AudioEntry twice.
@@ -450,7 +450,7 @@
 }
 
 void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // At this point, make the final "say" in audio playback state.
   MediaObserver* const media_observer =
@@ -463,7 +463,7 @@
 }
 
 void AudioRendererHost::ReportErrorAndClose(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Make sure this isn't a stray callback executing after the stream has been
   // closed, so error notifications aren't sent after clients believe the stream
@@ -478,7 +478,7 @@
 }
 
 AudioRendererHost::AudioEntry* AudioRendererHost::LookupById(int stream_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   AudioEntryMap::const_iterator i = audio_entries_.find(stream_id);
   return i != audio_entries_.end() ? i->second : NULL;
diff --git a/content/browser/renderer_host/media/device_request_message_filter.cc b/content/browser/renderer_host/media/device_request_message_filter.cc
index 0c34b53..3ae8c1a 100644
--- a/content/browser/renderer_host/media/device_request_message_filter.cc
+++ b/content/browser/renderer_host/media/device_request_message_filter.cc
@@ -5,6 +5,7 @@
 #include "content/browser/renderer_host/media/device_request_message_filter.h"
 
 #include "content/browser/browser_main_loop.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/renderer_host/media/media_stream_manager.h"
 #include "content/common/media/media_stream_messages.h"
 #include "content/public/browser/resource_context.h"
@@ -22,10 +23,12 @@
 
 DeviceRequestMessageFilter::DeviceRequestMessageFilter(
     ResourceContext* resource_context,
-    MediaStreamManager* media_stream_manager)
+    MediaStreamManager* media_stream_manager,
+    int render_process_id)
     : BrowserMessageFilter(MediaStreamMsgStart),
       resource_context_(resource_context),
-      media_stream_manager_(media_stream_manager) {
+      media_stream_manager_(media_stream_manager),
+      render_process_id_(render_process_id) {
   DCHECK(resource_context);
   DCHECK(media_stream_manager);
 }
@@ -63,7 +66,7 @@
     int page_request_id,
     const std::string& label,
     const StreamDeviceInfoArray& new_devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Look up the DeviceRequest by id.
   DeviceRequestList::iterator request_it = requests_.begin();
@@ -135,6 +138,12 @@
 
 void DeviceRequestMessageFilter::OnGetSources(int request_id,
                                               const GURL& security_origin) {
+  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+          render_process_id_, security_origin)) {
+    LOG(ERROR) << "Disallowed URL in DRMF::OnGetSources: " << security_origin;
+    return;
+  }
+
   // Make request to get audio devices.
   const std::string& audio_label = media_stream_manager_->EnumerateDevices(
       this, -1, -1, resource_context_->GetMediaDeviceIDSalt(), -1,
diff --git a/content/browser/renderer_host/media/device_request_message_filter.h b/content/browser/renderer_host/media/device_request_message_filter.h
index 3861f3d..f5f38b3 100644
--- a/content/browser/renderer_host/media/device_request_message_filter.h
+++ b/content/browser/renderer_host/media/device_request_message_filter.h
@@ -24,7 +24,8 @@
                                                   public MediaStreamRequester {
  public:
   DeviceRequestMessageFilter(ResourceContext* resource_context,
-                             MediaStreamManager* media_stream_manager);
+                             MediaStreamManager* media_stream_manager,
+                             int render_process_id);
 
   // MediaStreamRequester implementation.
   // TODO(vrk): Replace MediaStreamRequester interface with a single callback so
@@ -71,6 +72,8 @@
   // List of all requests.
   DeviceRequestList requests_;
 
+  int render_process_id_;
+
   DISALLOW_COPY_AND_ASSIGN(DeviceRequestMessageFilter);
 };
 
diff --git a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
index 82fee19..cb7d061 100644
--- a/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
+++ b/content/browser/renderer_host/media/device_request_message_filter_unittest.cc
@@ -54,7 +54,7 @@
  public:
   MockDeviceRequestMessageFilter(MockResourceContext* context,
                                  MockMediaStreamManager* manager)
-      : DeviceRequestMessageFilter(context, manager), received_id_(-1) {}
+      : DeviceRequestMessageFilter(context, manager, 0), received_id_(-1) {}
   StreamDeviceInfoArray requested_devices() { return requested_devices_; }
   int received_id() { return received_id_; }
 
diff --git a/content/browser/renderer_host/media/media_capture_devices_impl.cc b/content/browser/renderer_host/media/media_capture_devices_impl.cc
index f4e13ab..9cc8b12 100644
--- a/content/browser/renderer_host/media/media_capture_devices_impl.cc
+++ b/content/browser/renderer_host/media/media_capture_devices_impl.cc
@@ -13,7 +13,7 @@
 namespace {
 
 void EnsureMonitorCaptureDevices() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::Bind(&MediaStreamManager::EnsureDeviceMonitorStarted,
@@ -33,7 +33,7 @@
 
 const MediaStreamDevices&
 MediaCaptureDevicesImpl::GetAudioCaptureDevices() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!devices_enumerated_) {
     EnsureMonitorCaptureDevices();
     devices_enumerated_ = true;
@@ -43,7 +43,7 @@
 
 const MediaStreamDevices&
 MediaCaptureDevicesImpl::GetVideoCaptureDevices() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!devices_enumerated_) {
     EnsureMonitorCaptureDevices();
     devices_enumerated_ = true;
@@ -84,14 +84,14 @@
 
 void MediaCaptureDevicesImpl::UpdateAudioDevicesOnUIThread(
     const MediaStreamDevices& devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   devices_enumerated_ = true;
   audio_devices_ = devices;
 }
 
 void MediaCaptureDevicesImpl::UpdateVideoDevicesOnUIThread(
     const MediaStreamDevices& devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   devices_enumerated_ = true;
   video_devices_ = devices;
 }
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
index 7d1f955..37e2e19 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -5,8 +5,10 @@
 #include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
 
 #include "content/browser/browser_main_loop.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/common/media/media_stream_messages.h"
 #include "content/common/media/media_stream_options.h"
+#include "content/public/browser/render_process_host.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -27,7 +29,7 @@
     const std::string& label,
     const StreamDeviceInfoArray& audio_devices,
     const StreamDeviceInfoArray& video_devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerated("
            << ", {label = " << label <<  "})";
 
@@ -40,7 +42,7 @@
     int render_view_id,
     int page_request_id,
     content::MediaStreamRequestResult result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "MediaStreamDispatcherHost::StreamGenerationFailed("
            << ", {page_request_id = " << page_request_id <<  "}"
            << ", { result= " << result << "})";
@@ -54,7 +56,7 @@
 void MediaStreamDispatcherHost::DeviceStopped(int render_view_id,
                                               const std::string& label,
                                               const StreamDeviceInfo& device) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "MediaStreamDispatcherHost::DeviceStopped("
            << "{label = " << label << "}, "
            << "{type = " << device.device.type << "}, "
@@ -68,7 +70,7 @@
     int page_request_id,
     const std::string& label,
     const StreamDeviceInfoArray& devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "MediaStreamDispatcherHost::DevicesEnumerated("
            << ", {page_request_id = " << page_request_id <<  "})";
 
@@ -81,7 +83,7 @@
     int page_request_id,
     const std::string& label,
     const StreamDeviceInfo& video_device) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "MediaStreamDispatcherHost::DeviceOpened("
            << ", {page_request_id = " << page_request_id <<  "})";
 
@@ -125,18 +127,23 @@
     int render_view_id,
     int page_request_id,
     const StreamOptions& components,
-    const GURL& security_origin) {
+    const GURL& security_origin,
+    bool user_gesture) {
   DVLOG(1) << "MediaStreamDispatcherHost::OnGenerateStream("
            << render_view_id << ", "
            << page_request_id << ", ["
            << " audio:" << components.audio_requested
            << " video:" << components.video_requested
            << " ], "
-           << security_origin.spec() << ")";
+           << security_origin.spec()
+           << ", " << user_gesture << ")";
+
+  if (!IsURLAllowed(security_origin))
+    return;
 
   media_stream_manager_->GenerateStream(
       this, render_process_id_, render_view_id, salt_callback_,
-      page_request_id, components, security_origin);
+      page_request_id, components, security_origin, user_gesture);
 }
 
 void MediaStreamDispatcherHost::OnCancelGenerateStream(int render_view_id,
@@ -169,6 +176,9 @@
            << type << ", "
            << security_origin.spec() << ")";
 
+  if (!IsURLAllowed(security_origin))
+    return;
+
   media_stream_manager_->EnumerateDevices(
       this, render_process_id_, render_view_id, salt_callback_,
       page_request_id, type, security_origin);
@@ -197,10 +207,12 @@
            << type << ", "
            << security_origin.spec() << ")";
 
+  if (!IsURLAllowed(security_origin))
+    return;
+
   media_stream_manager_->OpenDevice(
       this, render_process_id_, render_view_id, salt_callback_,
       page_request_id, device_id, type, security_origin);
-
 }
 
 void MediaStreamDispatcherHost::OnCloseDevice(
@@ -213,4 +225,14 @@
   media_stream_manager_->CancelRequest(label);
 }
 
+bool MediaStreamDispatcherHost::IsURLAllowed(const GURL& url) {
+  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+          render_process_id_, url)) {
+    LOG(ERROR) << "MSDH: Renderer requested a URL it's not allowed to use.";
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
index 78d6622..f34054e 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -68,7 +68,8 @@
   void OnGenerateStream(int render_view_id,
                         int page_request_id,
                         const StreamOptions& components,
-                        const GURL& security_origin);
+                        const GURL& security_origin,
+                        bool user_gesture);
   void OnCancelGenerateStream(int render_view_id,
                               int page_request_id);
   void OnStopStreamDevice(int render_view_id,
@@ -95,6 +96,8 @@
                     int page_request_id,
                     const std::string& label);;
 
+  bool IsURLAllowed(const GURL& url);
+
   int render_process_id_;
   ResourceContext::SaltCallback salt_callback_;
   MediaStreamManager* media_stream_manager_;
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
index e00cfb2..65f2618 100644
--- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -68,7 +68,7 @@
                         const base::Closure& quit_closure) {
     quit_closures_.push(quit_closure);
     MediaStreamDispatcherHost::OnGenerateStream(
-        render_view_id, page_request_id, components, security_origin);
+        render_view_id, page_request_id, components, security_origin, false);
   }
 
   void OnStopStreamDevice(int render_view_id,
@@ -202,7 +202,10 @@
 
 class MockMediaStreamUIProxy : public FakeMediaStreamUIProxy {
  public:
-  MOCK_METHOD1(OnStarted, void(const base::Closure& stop));
+  MOCK_METHOD2(
+      OnStarted,
+      void(const base::Closure& stop,
+           const MediaStreamUIProxy::WindowIdCallback& window_id_callback));
 };
 
 class MediaStreamDispatcherHostTest : public testing::Test {
@@ -248,7 +251,7 @@
   virtual void SetupFakeUI(bool expect_started) {
     scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
     if (expect_started) {
-      EXPECT_CALL(*stream_ui, OnStarted(_));
+      EXPECT_CALL(*stream_ui, OnStarted(_, _));
     }
     media_stream_manager_->UseFakeUI(
         stream_ui.PassAs<FakeMediaStreamUIProxy>());
@@ -672,6 +675,7 @@
   media::FakeVideoCaptureDevice::GetDeviceNames(&physical_video_devices_);
   StreamOptions options(true, true);
 
+  SetupFakeUI(false);
   GenerateStreamAndWaitForFailure(kRenderId, kPageRequestId, options,
                                   MEDIA_DEVICE_NO_HARDWARE);
 
@@ -802,7 +806,7 @@
 
   base::Closure close_callback;
   scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
-  EXPECT_CALL(*stream_ui, OnStarted(_))
+  EXPECT_CALL(*stream_ui, OnStarted(_, _))
       .WillOnce(SaveArg<0>(&close_callback));
   media_stream_manager_->UseFakeUI(stream_ui.PassAs<FakeMediaStreamUIProxy>());
 
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc
index 67c0cd8..779c601 100644
--- a/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -11,6 +11,7 @@
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/logging.h"
+#include "base/power_monitor/power_monitor.h"
 #include "base/rand_util.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
@@ -119,7 +120,7 @@
 // webrtcLoggingPrivate API.
 void DoAddLogMessage(const std::string& message) {
   // Must be on the UI thread to access BrowserMainLoop.
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // May be null in tests.
   // TODO(vrk): Handle this more elegantly by having native log messages become
   // no-ops until MediaStreamManager is aware that a renderer process has
@@ -173,6 +174,7 @@
                 int requesting_view_id,
                 int page_request_id,
                 const GURL& security_origin,
+                bool user_gesture,
                 MediaStreamRequestType request_type,
                 const StreamOptions& options,
                 const ResourceContext::SaltCallback& salt_callback)
@@ -181,6 +183,7 @@
         requesting_view_id(requesting_view_id),
         page_request_id(page_request_id),
         security_origin(security_origin),
+        user_gesture(user_gesture),
         request_type(request_type),
         options(options),
         salt_callback(salt_callback),
@@ -214,6 +217,7 @@
                                              requesting_view_id,
                                              page_request_id,
                                              security_origin,
+                                             user_gesture,
                                              request_type,
                                              requested_audio_device_id,
                                              requested_video_device_id,
@@ -231,6 +235,7 @@
                                              target_render_view_id,
                                              page_request_id,
                                              security_origin,
+                                             user_gesture,
                                              request_type,
                                              "",
                                              "",
@@ -299,6 +304,8 @@
 
   const GURL security_origin;
 
+  const bool user_gesture;
+
   const MediaStreamRequestType request_type;
 
   const StreamOptions options;
@@ -353,22 +360,34 @@
         base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread,
                    base::Unretained(this)));
   }
+
+  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+  // BrowserMainLoop always creates the PowerMonitor instance before creating
+  // MediaStreamManager, but power_monitor may be NULL in unit tests.
+  if (power_monitor)
+    power_monitor->AddObserver(this);
 }
 
 MediaStreamManager::~MediaStreamManager() {
   DVLOG(1) << "~MediaStreamManager";
   DCHECK(requests_.empty());
   DCHECK(!device_task_runner_);
+
+  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
+  // The PowerMonitor instance owned by BrowserMainLoops always outlives the
+  // MediaStreamManager, but it may be NULL in unit tests.
+  if (power_monitor)
+    power_monitor->RemoveObserver(this);
 }
 
 VideoCaptureManager* MediaStreamManager::video_capture_manager() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(video_capture_manager_.get());
   return video_capture_manager_.get();
 }
 
 AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(audio_input_device_manager_.get());
   return audio_input_device_manager_.get();
 }
@@ -380,7 +399,7 @@
     const StreamOptions& options,
     const GURL& security_origin,
     const MediaRequestResponseCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // TODO(perkj): The argument list with NULL parameters to DeviceRequest
   // suggests that this is the wrong design. Can this be refactored?
@@ -389,6 +408,7 @@
                                              render_view_id,
                                              page_request_id,
                                              security_origin,
+                                             false,  // user gesture
                                              MEDIA_DEVICE_ACCESS,
                                              options,
                                              base::Bind(&ReturnEmptySalt));
@@ -414,8 +434,9 @@
                                         const ResourceContext::SaltCallback& sc,
                                         int page_request_id,
                                         const StreamOptions& options,
-                                        const GURL& security_origin) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+                                        const GURL& security_origin,
+                                        bool user_gesture) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "GenerateStream()";
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kUseFakeUIForMediaStream)) {
@@ -427,6 +448,7 @@
                                              render_view_id,
                                              page_request_id,
                                              security_origin,
+                                             user_gesture,
                                              MEDIA_GENERATE_STREAM,
                                              options,
                                              sc);
@@ -461,7 +483,7 @@
 }
 
 void MediaStreamManager::CancelRequest(const std::string& label) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "CancelRequest({label = " << label <<  "})";
   DeviceRequest* request = FindRequest(label);
   if (!request) {
@@ -515,7 +537,7 @@
 void MediaStreamManager::StopStreamDevice(int render_process_id,
                                           int render_view_id,
                                           const std::string& device_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id <<  "} "
            << ", {device_id = " << device_id << "})";
   // Find the first request for this |render_process_id| and |render_view_id|
@@ -609,7 +631,7 @@
     int page_request_id,
     MediaStreamType type,
     const GURL& security_origin) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(requester);
   DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
          type == MEDIA_DEVICE_VIDEO_CAPTURE);
@@ -619,6 +641,7 @@
                                              render_view_id,
                                              page_request_id,
                                              security_origin,
+                                             false,  // user gesture
                                              MEDIA_ENUMERATE_DEVICES,
                                              StreamOptions(),
                                              sc);
@@ -641,7 +664,7 @@
 }
 
 void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DeviceRequest* request = FindRequest(label);
   if (!request)
     return;  // This can happen if the request has been canceled.
@@ -677,7 +700,7 @@
                                     const std::string& device_id,
                                     MediaStreamType type,
                                     const GURL& security_origin) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
          type == MEDIA_DEVICE_VIDEO_CAPTURE);
   DVLOG(1) << "OpenDevice ({page_request_id = " << page_request_id <<  "})";
@@ -698,6 +721,7 @@
                                              render_view_id,
                                              page_request_id,
                                              security_origin,
+                                             false,  // user gesture
                                              MEDIA_OPEN_DEVICE,
                                              options,
                                              sc);
@@ -715,7 +739,7 @@
 }
 
 void MediaStreamManager::EnsureDeviceMonitorStarted() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   StartMonitoring();
 }
 
@@ -775,7 +799,7 @@
 }
 
 void MediaStreamManager::StartMonitoring() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (monitoring_started_)
     return;
 
@@ -802,7 +826,7 @@
 
 #if defined(OS_MACOSX)
 void MediaStreamManager::StartMonitoringOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserMainLoop* browser_main_loop = content::BrowserMainLoop::GetInstance();
   if (browser_main_loop)
     browser_main_loop->device_monitor_mac()->StartMonitoring();
@@ -947,7 +971,7 @@
 }
 
 void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Start monitoring the devices when doing the first enumeration.
   StartMonitoring();
@@ -968,7 +992,7 @@
 }
 
 std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Create a label for this request and verify it is unique.
   std::string unique_label;
@@ -996,7 +1020,7 @@
 
 void MediaStreamManager::PostRequestToUI(const std::string& label,
                                          DeviceRequest* request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(request->UIRequest());
   DVLOG(1) << "PostRequestToUI({label= " << label << "})";
 
@@ -1043,7 +1067,7 @@
 }
 
 void MediaStreamManager::SetupRequest(const std::string& label) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DeviceRequest* request = FindRequest(label);
   if (!request) {
     DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!";
@@ -1120,23 +1144,17 @@
          (request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE ||
           request->video_type() == MEDIA_NO_SERVICE));
   std::string audio_device_id;
-  if (request->options.audio_requested) {
-    if (audio_enumeration_cache_.devices.empty() ||
-        !GetRequestedDeviceCaptureId(request, request->audio_type(),
+  if (request->options.audio_requested &&
+      !GetRequestedDeviceCaptureId(request, request->audio_type(),
                                      &audio_device_id)) {
-      DLOG(WARNING) << "No available audio input device found.";
-      return false;
-    }
+    return false;
   }
 
   std::string video_device_id;
-  if (request->options.video_requested) {
-    if (video_enumeration_cache_.devices.empty() ||
-        !GetRequestedDeviceCaptureId(request, request->video_type(),
-                                     &video_device_id)) {
-      DLOG(WARNING) << "No available video capture device found.";
-      return false;
-    }
+  if (request->options.video_requested &&
+      !GetRequestedDeviceCaptureId(request, request->video_type(),
+                                   &video_device_id)) {
+    return false;
   }
   request->CreateUIRequest(audio_device_id, video_device_id);
   DVLOG(3) << "Audio requested " << request->options.audio_requested
@@ -1334,7 +1352,7 @@
 
 void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
                                                   DeviceRequest* request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES);
 
   if (request->security_origin.is_valid()) {
@@ -1394,7 +1412,7 @@
 }
 
 void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (device_task_runner_)
     return;
 
@@ -1420,7 +1438,7 @@
 
 void MediaStreamManager::Opened(MediaStreamType stream_type,
                                 int capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "Opened({stream_type = " << stream_type <<  "} "
            << "{capture_session_id = " << capture_session_id << "})";
   // Find the request(s) containing this device and mark it as used.
@@ -1482,18 +1500,23 @@
   if (request->ui_proxy.get()) {
     request->ui_proxy->OnStarted(
         base::Bind(&MediaStreamManager::StopMediaStreamFromBrowser,
-                   base::Unretained(this), label));
+                   base::Unretained(this),
+                   label),
+        base::Bind(&MediaStreamManager::OnMediaStreamUIWindowId,
+                   base::Unretained(this),
+                   request->video_type(),
+                   request->devices));
   }
 }
 
 void MediaStreamManager::Closed(MediaStreamType stream_type,
                                 int capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 }
 
 void MediaStreamManager::DevicesEnumerated(
     MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "DevicesEnumerated("
            << "{stream_type = " << stream_type << "})" << std::endl;
 
@@ -1582,9 +1605,17 @@
       base::Bind(DoAddLogMessage, message));
 }
 
+void MediaStreamManager::OnSuspend() {
+  SendMessageToNativeLog("Power state suspended.");
+}
+
+void MediaStreamManager::OnResume() {
+  SendMessageToNativeLog("Power state resumed.");
+}
+
 void MediaStreamManager::AddLogMessageOnIOThread(const std::string& message) {
   // Get render process ids on the IO thread.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Grab all unique process ids that request a MediaStream or have a
   // MediaStream running.
@@ -1613,7 +1644,7 @@
     const std::string& message) {
 #if defined(ENABLE_WEBRTC)
   // Must be on the UI thread to access RenderProcessHost from process ID.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   for (std::set<int>::const_iterator it = requesting_process_ids.begin();
        it != requesting_process_ids.end(); ++it) {
@@ -1632,7 +1663,7 @@
     const std::string& label,
     const MediaStreamDevices& devices,
     content::MediaStreamRequestResult result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "HandleAccessRequestResponse("
            << ", {label = " << label <<  "})";
 
@@ -1734,7 +1765,7 @@
 }
 
 void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   DeviceRequest* request = FindRequest(label);
   if (!request)
@@ -1754,13 +1785,13 @@
 }
 
 void MediaStreamManager::UseFakeDevice() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   video_capture_manager()->UseFakeDevice();
   audio_input_device_manager()->UseFakeDevice();
 }
 
 void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   use_fake_ui_ = true;
   fake_ui_ = fake_ui.Pass();
 }
@@ -1784,7 +1815,7 @@
 void MediaStreamManager::NotifyDevicesChanged(
     MediaStreamType stream_type,
     const StreamDeviceInfoArray& devices) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   MediaObserver* media_observer =
       GetContentClient()->browser()->GetMediaObserver();
   if (media_observer == NULL)
@@ -1811,7 +1842,7 @@
 }
 
 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   const bool requested_audio = IsAudioMediaType(request.audio_type());
   const bool requested_video = IsVideoMediaType(request.video_type());
@@ -1846,7 +1877,7 @@
 
 void MediaStreamManager::OnDevicesChanged(
     base::SystemMonitor::DeviceType device_type) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // NOTE: This method is only called in response to physical audio/video device
   // changes (from the operating system).
@@ -1867,4 +1898,25 @@
   GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
 }
 
+void MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type,
+                                                 StreamDeviceInfoArray devices,
+                                                 gfx::NativeViewId window_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (!window_id)
+    return;
+
+  // Pass along for desktop capturing. Ignored for other stream types.
+  if (video_type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
+    for (StreamDeviceInfoArray::iterator it = devices.begin();
+         it != devices.end();
+         ++it) {
+      if (it->device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
+        video_capture_manager_->SetDesktopCaptureWindowId(it->session_id,
+                                                          window_id);
+        break;
+      }
+    }
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h
index 6ecd66c..17bc6d2 100644
--- a/content/browser/renderer_host/media/media_stream_manager.h
+++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -31,6 +31,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/power_monitor/power_observer.h"
 #include "base/system_monitor/system_monitor.h"
 #include "content/browser/renderer_host/media/media_stream_provider.h"
 #include "content/common/content_export.h"
@@ -57,6 +58,7 @@
 class CONTENT_EXPORT MediaStreamManager
     : public MediaStreamProviderListener,
       public base::MessageLoop::DestructionObserver,
+      public base::PowerObserver,
       public base::SystemMonitor::DevicesChangedObserver {
  public:
   // Callback to deliver the result of a media request.
@@ -97,7 +99,8 @@
                       const ResourceContext::SaltCallback& sc,
                       int page_request_id,
                       const StreamOptions& components,
-                      const GURL& security_origin);
+                      const GURL& security_origin,
+                      bool user_gesture);
 
   void CancelRequest(int render_process_id,
                      int render_view_id,
@@ -192,6 +195,10 @@
   // logging from webrtcLoggingPrivate API. Safe to call from any thread.
   static void SendMessageToNativeLog(const std::string& message);
 
+  // base::PowerObserver overrides.
+  virtual void OnSuspend() OVERRIDE;
+  virtual void OnResume() OVERRIDE;
+
  protected:
   // Used for testing.
   MediaStreamManager();
@@ -338,6 +345,12 @@
       const std::string& source_id,
       std::string* device_id) const;
 
+  // Handles the callback from MediaStreamUIProxy to receive the UI window id,
+  // used for excluding the notification window in desktop capturing.
+  void OnMediaStreamUIWindowId(MediaStreamType video_type,
+                               StreamDeviceInfoArray devices,
+                               gfx::NativeViewId window_id);
+
   // Task runner shared by VideoCaptureManager and AudioInputDeviceManager.
   // Note: Enumeration tasks may take seconds to complete so must never be run
   // on any of the BrowserThreads (UI, IO, etc).  See http://crbug.com/256945.
diff --git a/content/browser/renderer_host/media/media_stream_track_metrics_host.cc b/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
index 1a7e420..2d3c7cd 100644
--- a/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
+++ b/content/browser/renderer_host/media/media_stream_track_metrics_host.cc
@@ -27,8 +27,8 @@
   for (TrackMap::iterator it = tracks_.begin();
        it != tracks_.end();
        ++it) {
-    IsAudioPlusTimestamp& audio_and_timestamp = it->second;
-    ReportDuration(audio_and_timestamp.first, audio_and_timestamp.second);
+    TrackInfo& info = it->second;
+    ReportDuration(info);
   }
   tracks_.clear();
 }
@@ -53,26 +53,36 @@
                                              bool is_audio,
                                              bool is_remote) {
   DCHECK(tracks_.find(id) == tracks_.end());
-  DCHECK(is_remote);  // Always the case for now.
-
-  tracks_[id] = IsAudioPlusTimestamp(is_audio, base::TimeTicks::Now());
+  TrackInfo info = {is_audio, is_remote, base::TimeTicks::Now()};
+  tracks_[id] = info;
 }
 
 void MediaStreamTrackMetricsHost::OnRemoveTrack(uint64 id) {
   DCHECK(tracks_.find(id) != tracks_.end());
 
-  IsAudioPlusTimestamp& info = tracks_[id];
-  ReportDuration(info.first, info.second);
+  TrackInfo& info = tracks_[id];
+  ReportDuration(info);
   tracks_.erase(id);
 }
 
-void MediaStreamTrackMetricsHost::ReportDuration(bool is_audio,
-                                                 base::TimeTicks start_time) {
-  base::TimeDelta duration = base::TimeTicks::Now() - start_time;
-  if (is_audio) {
-    UMA_HISTOGRAM_TIMES_16H("WebRTC.ReceivedAudioTrackDuration", duration);
+void MediaStreamTrackMetricsHost::ReportDuration(const TrackInfo& info) {
+  base::TimeDelta duration = base::TimeTicks::Now() - info.timestamp;
+  if (info.is_remote) {
+    if (info.is_audio) {
+      DVLOG(3) << "WebRTC.ReceivedAudioTrackDuration: " << duration.InSeconds();
+      UMA_HISTOGRAM_TIMES_16H("WebRTC.ReceivedAudioTrackDuration", duration);
+    } else {
+      DVLOG(3) << "WebRTC.ReceivedVideoTrackDuration: " << duration.InSeconds();
+      UMA_HISTOGRAM_TIMES_16H("WebRTC.ReceivedVideoTrackDuration", duration);
+    }
   } else {
-    UMA_HISTOGRAM_TIMES_16H("WebRTC.ReceivedVideoTrackDuration", duration);
+    if (info.is_audio) {
+      DVLOG(3) << "WebRTC.SentAudioTrackDuration: " << duration.InSeconds();
+      UMA_HISTOGRAM_TIMES_16H("WebRTC.SentAudioTrackDuration", duration);
+    } else {
+      DVLOG(3) << "WebRTC.SentVideoTrackDuration: " << duration.InSeconds();
+      UMA_HISTOGRAM_TIMES_16H("WebRTC.SentVideoTrackDuration", duration);
+    }
   }
 }
 
diff --git a/content/browser/renderer_host/media/media_stream_track_metrics_host.h b/content/browser/renderer_host/media/media_stream_track_metrics_host.h
index a80830e..b0d18f1 100644
--- a/content/browser/renderer_host/media/media_stream_track_metrics_host.h
+++ b/content/browser/renderer_host/media/media_stream_track_metrics_host.h
@@ -41,13 +41,21 @@
   void OnAddTrack(uint64 id, bool is_audio, bool is_remote);
   void OnRemoveTrack(uint64 id);
 
-  void ReportDuration(bool is_audio, base::TimeTicks start_time);
+  // Information for a track we're keeping in |tracks_|. |is_audio|
+  // specifies whether it's an audio or video track, |is_remote|
+  // specifies whether it's remote (received over a PeerConnection) or
+  // local (sent over a PeerConnection). |timestamp| specifies when
+  // the track was connected.
+  struct TrackInfo {
+    bool is_audio;
+    bool is_remote;
+    base::TimeTicks timestamp;
+  };
 
-  // Keys are unique (per renderer) track IDs, values are pairs: A
-  // boolean indicating whether the track is an audio track, and a
-  // timestamp from when the track was created.
-  typedef std::pair<bool, base::TimeTicks> IsAudioPlusTimestamp;
-  typedef std::map<uint64, IsAudioPlusTimestamp> TrackMap;
+  void ReportDuration(const TrackInfo& info);
+
+  // Values are unique (per renderer) track IDs.
+  typedef std::map<uint64, TrackInfo> TrackMap;
   TrackMap tracks_;
 };
 
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index 65986a1..b6c7f1f 100644
--- a/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -18,7 +18,7 @@
   ~Core();
 
   void RequestAccess(const MediaStreamRequest& request);
-  void OnStarted();
+  void OnStarted(gfx::NativeViewId* window_id);
 
  private:
   void ProcessAccessRequestResponse(const MediaStreamDevices& devices,
@@ -46,12 +46,12 @@
 }
 
 MediaStreamUIProxy::Core::~Core() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
 void MediaStreamUIProxy::Core::RequestAccess(
     const MediaStreamRequest& request) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   RenderViewHostDelegate* render_delegate;
 
@@ -78,11 +78,11 @@
                           weak_factory_.GetWeakPtr()));
 }
 
-void MediaStreamUIProxy::Core::OnStarted() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+void MediaStreamUIProxy::Core::OnStarted(gfx::NativeViewId* window_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (ui_) {
-    ui_->OnStarted(base::Bind(&Core::ProcessStopRequestFromUI,
-                              base::Unretained(this)));
+    *window_id = ui_->OnStarted(
+        base::Bind(&Core::ProcessStopRequestFromUI, base::Unretained(this)));
   }
 }
 
@@ -90,7 +90,7 @@
     const MediaStreamDevices& devices,
     content::MediaStreamRequestResult result,
     scoped_ptr<MediaStreamUI> stream_ui) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   ui_ = stream_ui.Pass();
   BrowserThread::PostTask(
@@ -100,7 +100,7 @@
 }
 
 void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
@@ -122,19 +122,19 @@
 MediaStreamUIProxy::MediaStreamUIProxy(
     RenderViewHostDelegate* test_render_delegate)
     : weak_factory_(this) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   core_.reset(new Core(weak_factory_.GetWeakPtr(), test_render_delegate));
 }
 
 MediaStreamUIProxy::~MediaStreamUIProxy() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, core_.release());
 }
 
 void MediaStreamUIProxy::RequestAccess(
     const MediaStreamRequest& request,
     const ResponseCallback& response_callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   response_callback_ = response_callback;
   BrowserThread::PostTask(
@@ -142,19 +142,36 @@
       base::Bind(&Core::RequestAccess, base::Unretained(core_.get()), request));
 }
 
-void MediaStreamUIProxy::OnStarted(const base::Closure& stop_callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+void MediaStreamUIProxy::OnStarted(const base::Closure& stop_callback,
+                                   const WindowIdCallback& window_id_callback) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   stop_callback_ = stop_callback;
-  BrowserThread::PostTask(
-      BrowserThread::UI, FROM_HERE,
-      base::Bind(&Core::OnStarted, base::Unretained(core_.get())));
+
+  // Owned by the PostTaskAndReply callback.
+  gfx::NativeViewId* window_id = new gfx::NativeViewId(0);
+
+  BrowserThread::PostTaskAndReply(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&Core::OnStarted, base::Unretained(core_.get()), window_id),
+      base::Bind(&MediaStreamUIProxy::OnWindowId,
+                 weak_factory_.GetWeakPtr(),
+                 window_id_callback,
+                 base::Owned(window_id)));
+}
+
+void MediaStreamUIProxy::OnWindowId(const WindowIdCallback& window_id_callback,
+                                    gfx::NativeViewId* window_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  if (!window_id_callback.is_null())
+    window_id_callback.Run(*window_id);
 }
 
 void MediaStreamUIProxy::ProcessAccessRequestResponse(
     const MediaStreamDevices& devices,
     content::MediaStreamRequestResult result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!response_callback_.is_null());
 
   ResponseCallback cb = response_callback_;
@@ -163,7 +180,7 @@
 }
 
 void MediaStreamUIProxy::ProcessStopRequestFromUI() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!stop_callback_.is_null());
 
   base::Closure cb = stop_callback_;
@@ -185,13 +202,14 @@
 void FakeMediaStreamUIProxy::RequestAccess(
     const MediaStreamRequest& request,
     const ResponseCallback& response_callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   response_callback_ = response_callback;
 
   MediaStreamDevices devices_to_use;
   bool accepted_audio = false;
   bool accepted_video = false;
+
   // Use the first capture device of the same media type in the list for the
   // fake UI.
   for (MediaStreamDevices::const_iterator it = devices_.begin();
@@ -213,6 +231,12 @@
     }
   }
 
+  // Fail the request if a device exist for the requested type.
+  if ((request.audio_type != MEDIA_NO_SERVICE && !accepted_audio) ||
+      (request.video_type != MEDIA_NO_SERVICE && !accepted_video)) {
+    devices_to_use.clear();
+  }
+
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE,
       base::Bind(&MediaStreamUIProxy::ProcessAccessRequestResponse,
@@ -223,7 +247,8 @@
                      MEDIA_DEVICE_OK));
 }
 
-void FakeMediaStreamUIProxy::OnStarted(const base::Closure& stop_callback) {
-}
+void FakeMediaStreamUIProxy::OnStarted(
+    const base::Closure& stop_callback,
+    const WindowIdCallback& window_id_callback) {}
 
 }  // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.h b/content/browser/renderer_host/media/media_stream_ui_proxy.h
index 61076be..01be166 100644
--- a/content/browser/renderer_host/media/media_stream_ui_proxy.h
+++ b/content/browser/renderer_host/media/media_stream_ui_proxy.h
@@ -25,6 +25,8 @@
             content::MediaStreamRequestResult result)>
         ResponseCallback;
 
+  typedef base::Callback<void(gfx::NativeViewId window_id)> WindowIdCallback;
+
   static scoped_ptr<MediaStreamUIProxy> Create();
   static scoped_ptr<MediaStreamUIProxy> CreateForTests(
       RenderViewHostDelegate* render_delegate);
@@ -41,8 +43,10 @@
   // Notifies the UI that the MediaStream has been started. Must be called after
   // access has been approved using RequestAccess(). |stop_callback| is be
   // called on the IO thread after the user has requests the stream to be
-  // stopped.
-  virtual void OnStarted(const base::Closure& stop_callback);
+  // stopped. |window_id_callback| is called on the IO thread with the platform-
+  // dependent window ID of the UI.
+  virtual void OnStarted(const base::Closure& stop_callback,
+                         const WindowIdCallback& window_id_callback);
 
   void SetRenderViewHostDelegateForTests(RenderViewHostDelegate* delegate);
 
@@ -58,6 +62,8 @@
       const MediaStreamDevices& devices,
       content::MediaStreamRequestResult result);
   void ProcessStopRequestFromUI();
+  void OnWindowId(const WindowIdCallback& window_id_callback,
+                  gfx::NativeViewId* window_id);
 
   scoped_ptr<Core> core_;
   ResponseCallback response_callback_;
@@ -79,7 +85,8 @@
   virtual void RequestAccess(
       const MediaStreamRequest& request,
       const ResponseCallback& response_callback) OVERRIDE;
-  virtual void OnStarted(const base::Closure& stop_callback) OVERRIDE;
+  virtual void OnStarted(const base::Closure& stop_callback,
+                         const WindowIdCallback& window_id_callback) OVERRIDE;
 
  private:
   MediaStreamDevices devices_;
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index 93b422f..4529b49 100644
--- a/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -13,6 +13,7 @@
 #include "ui/gfx/rect.h"
 
 using testing::_;
+using testing::Return;
 using testing::SaveArg;
 
 namespace content {
@@ -45,12 +46,13 @@
 
 class MockMediaStreamUI : public MediaStreamUI {
  public:
-  MOCK_METHOD1(OnStarted, void(const base::Closure& stop));
+  MOCK_METHOD1(OnStarted, gfx::NativeViewId(const base::Closure& stop));
 };
 
 class MockStopStreamHandler {
  public:
   MOCK_METHOD0(OnStop, void());
+  MOCK_METHOD1(OnWindowId, void(gfx::NativeViewId window_id));
 };
 
 
@@ -93,7 +95,7 @@
 }
 
 TEST_F(MediaStreamUIProxyTest, Deny) {
-  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
+  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), false,
                              MEDIA_GENERATE_STREAM, std::string(),
                              std::string(),
                              MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -119,7 +121,7 @@
 }
 
 TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
-  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
+  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), false,
                              MEDIA_GENERATE_STREAM, std::string(),
                              std::string(),
                              MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -137,7 +139,7 @@
   devices.push_back(
       MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic"));
   scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
-  EXPECT_CALL(*ui, OnStarted(_));
+  EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(0));
   callback.Run(devices, MEDIA_DEVICE_OK, ui.PassAs<MediaStreamUI>());
 
   MediaStreamDevices response;
@@ -147,13 +149,13 @@
 
   EXPECT_FALSE(response.empty());
 
-  proxy_->OnStarted(base::Closure());
+  proxy_->OnStarted(base::Closure(), MediaStreamUIProxy::WindowIdCallback());
   message_loop_.RunUntilIdle();
 }
 
 // Verify that the proxy can be deleted before the request is processed.
 TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) {
-  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
+  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), false,
                              MEDIA_GENERATE_STREAM, std::string(),
                              std::string(),
                              MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -175,7 +177,7 @@
 }
 
 TEST_F(MediaStreamUIProxyTest, StopFromUI) {
-  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"),
+  MediaStreamRequest request(0, 0, 0, GURL("http://origin/"), false,
                              MEDIA_GENERATE_STREAM, std::string(),
                              std::string(),
                              MEDIA_DEVICE_AUDIO_CAPTURE,
@@ -196,7 +198,7 @@
       MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic"));
   scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
   EXPECT_CALL(*ui, OnStarted(_))
-      .WillOnce(SaveArg<0>(&stop_callback));
+      .WillOnce(testing::DoAll(SaveArg<0>(&stop_callback), Return(0)));
   callback.Run(devices, MEDIA_DEVICE_OK, ui.PassAs<MediaStreamUI>());
 
   MediaStreamDevices response;
@@ -208,7 +210,8 @@
 
   MockStopStreamHandler stop_handler;
   proxy_->OnStarted(base::Bind(&MockStopStreamHandler::OnStop,
-                               base::Unretained(&stop_handler)));
+                               base::Unretained(&stop_handler)),
+                    MediaStreamUIProxy::WindowIdCallback());
   message_loop_.RunUntilIdle();
 
   ASSERT_FALSE(stop_callback.is_null());
@@ -217,4 +220,42 @@
   message_loop_.RunUntilIdle();
 }
 
+TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
+  MediaStreamRequest request(0,
+                             0,
+                             0,
+                             GURL("http://origin/"),
+                             false,
+                             MEDIA_GENERATE_STREAM,
+                             std::string(),
+                             std::string(),
+                             MEDIA_NO_SERVICE,
+                             MEDIA_DESKTOP_VIDEO_CAPTURE);
+  proxy_->RequestAccess(
+      request,
+      base::Bind(&MockResponseCallback::OnAccessRequestResponse,
+                 base::Unretained(&response_callback_)));
+  MediaResponseCallback callback;
+  EXPECT_CALL(delegate_, RequestMediaAccessPermission(SameRequest(request), _))
+      .WillOnce(SaveArg<1>(&callback));
+  message_loop_.RunUntilIdle();
+
+  const int kWindowId = 1;
+  scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
+  EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(kWindowId));
+
+  callback.Run(
+      MediaStreamDevices(), MEDIA_DEVICE_OK, ui.PassAs<MediaStreamUI>());
+  EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _));
+
+  MockStopStreamHandler handler;
+  EXPECT_CALL(handler, OnWindowId(kWindowId));
+
+  proxy_->OnStarted(
+      base::Bind(&MockStopStreamHandler::OnStop, base::Unretained(&handler)),
+      base::Bind(&MockStopStreamHandler::OnWindowId,
+                 base::Unretained(&handler)));
+  message_loop_.RunUntilIdle();
+}
+
 }  // content
diff --git a/content/browser/renderer_host/media/midi_dispatcher_host.cc b/content/browser/renderer_host/media/midi_dispatcher_host.cc
index e42fe11..2863e11 100644
--- a/content/browser/renderer_host/media/midi_dispatcher_host.cc
+++ b/content/browser/renderer_host/media/midi_dispatcher_host.cc
@@ -45,14 +45,16 @@
 
 void MidiDispatcherHost::OnRequestSysExPermission(int render_view_id,
                                                   int bridge_id,
-                                                  const GURL& origin) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+                                                  const GURL& origin,
+                                                  bool user_gesture) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   browser_context_->RequestMidiSysExPermission(
       render_process_id_,
       render_view_id,
       bridge_id,
       origin,
+      user_gesture,
       base::Bind(&MidiDispatcherHost::WasSysExPermissionGranted,
                  base::Unretained(this),
                  render_view_id,
@@ -63,7 +65,7 @@
     int render_view_id,
     int bridge_id,
     const GURL& requesting_frame) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DVLOG(1) << __FUNCTION__ << " " << render_process_id_ << ":" << render_view_id
            << ":" << bridge_id;
   browser_context_->CancelMidiSysExPermissionRequest(
diff --git a/content/browser/renderer_host/media/midi_dispatcher_host.h b/content/browser/renderer_host/media/midi_dispatcher_host.h
index 8bc1bb0..d8b3533 100644
--- a/content/browser/renderer_host/media/midi_dispatcher_host.h
+++ b/content/browser/renderer_host/media/midi_dispatcher_host.h
@@ -32,7 +32,8 @@
  private:
   void OnRequestSysExPermission(int render_view_id,
                                 int bridge_id,
-                                const GURL& origin);
+                                const GURL& origin,
+                                bool user_gesture);
   void OnCancelSysExPermissionRequest(int render_view_id,
                                       int bridge_id,
                                       const GURL& requesting_frame);
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index f625a07..9040913 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -178,7 +178,7 @@
     base::ProcessHandle render_process,
     media::VideoCaptureSessionId session_id,
     const media::VideoCaptureParams& params) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureController::AddClient, id " << id.device_id
            << ", " << params.requested_format.frame_size.ToString()
            << ", " << params.requested_format.frame_rate
@@ -212,7 +212,7 @@
 int VideoCaptureController::RemoveClient(
     const VideoCaptureControllerID& id,
     VideoCaptureControllerEventHandler* event_handler) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureController::RemoveClient, id " << id.device_id;
 
   ControllerClient* client = FindClient(id, event_handler, controller_clients_);
@@ -236,7 +236,7 @@
 }
 
 void VideoCaptureController::StopSession(int session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureController::StopSession, id " << session_id;
 
   ControllerClient* client = FindClient(session_id, controller_clients_);
@@ -252,7 +252,7 @@
     VideoCaptureControllerEventHandler* event_handler,
     int buffer_id,
     uint32 sync_point) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   ControllerClient* client = FindClient(id, event_handler, controller_clients_);
 
@@ -275,7 +275,7 @@
 
 const media::VideoCaptureFormat&
 VideoCaptureController::GetVideoCaptureFormat() const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   return video_capture_format_;
 }
 
@@ -534,7 +534,7 @@
     const media::VideoCaptureFormat& buffer_format,
     const scoped_refptr<media::VideoFrame>& frame,
     base::TimeTicks timestamp) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK_NE(buffer->id(), VideoCaptureBufferPool::kInvalidId);
 
   int count = 0;
@@ -578,7 +578,7 @@
 }
 
 void VideoCaptureController::DoErrorOnIOThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   state_ = VIDEO_CAPTURE_STATE_ERROR;
 
   for (ControllerClients::iterator client_it = controller_clients_.begin();
@@ -593,7 +593,7 @@
 
 void VideoCaptureController::DoBufferDestroyedOnIOThread(
     int buffer_id_to_drop) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   for (ControllerClients::iterator client_it = controller_clients_.begin();
        client_it != controller_clients_.end(); ++client_it) {
@@ -637,7 +637,7 @@
 }
 
 int VideoCaptureController::GetClientCount() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   return controller_clients_.size();
 }
 
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc
index 3d3417e..f261995 100644
--- a/content/browser/renderer_host/media/video_capture_host.cc
+++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -119,7 +119,7 @@
     base::SharedMemoryHandle handle,
     int length,
     int buffer_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (entries_.find(controller_id) == entries_.end())
     return;
@@ -131,7 +131,7 @@
 void VideoCaptureHost::DoSendFreeBufferOnIOThread(
     const VideoCaptureControllerID& controller_id,
     int buffer_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (entries_.find(controller_id) == entries_.end())
     return;
@@ -144,7 +144,7 @@
     int buffer_id,
     const media::VideoCaptureFormat& format,
     base::TimeTicks timestamp) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (entries_.find(controller_id) == entries_.end())
     return;
@@ -159,7 +159,7 @@
     const gpu::MailboxHolder& mailbox_holder,
     const media::VideoCaptureFormat& format,
     base::TimeTicks timestamp) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (entries_.find(controller_id) == entries_.end())
     return;
@@ -170,7 +170,7 @@
 
 void VideoCaptureHost::DoHandleErrorOnIOThread(
     const VideoCaptureControllerID& controller_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (entries_.find(controller_id) == entries_.end())
     return;
@@ -182,7 +182,7 @@
 
 void VideoCaptureHost::DoEndedOnIOThread(
     const VideoCaptureControllerID& controller_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureHost::DoEndedOnIOThread";
   if (entries_.find(controller_id) == entries_.end())
     return;
@@ -215,7 +215,7 @@
 void VideoCaptureHost::OnStartCapture(int device_id,
                                       media::VideoCaptureSessionId session_id,
                                       const media::VideoCaptureParams& params) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureHost::OnStartCapture:"
            << " session_id=" << session_id
            << ", device_id=" << device_id
@@ -255,7 +255,7 @@
 void VideoCaptureHost::DoControllerAddedOnIOThread(
     int device_id,
     const base::WeakPtr<VideoCaptureController>& controller) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   VideoCaptureControllerID controller_id(device_id);
   EntryMap::iterator it = entries_.find(controller_id);
   if (it == entries_.end()) {
@@ -278,7 +278,7 @@
 }
 
 void VideoCaptureHost::OnStopCapture(int device_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureHost::OnStopCapture, device_id " << device_id;
 
   VideoCaptureControllerID controller_id(device_id);
@@ -289,7 +289,7 @@
 }
 
 void VideoCaptureHost::OnPauseCapture(int device_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureHost::OnPauseCapture, device_id " << device_id;
   // Not used.
   Send(new VideoCaptureMsg_StateChanged(device_id, VIDEO_CAPTURE_STATE_ERROR));
@@ -298,7 +298,7 @@
 void VideoCaptureHost::OnReceiveEmptyBuffer(int device_id,
                                             int buffer_id,
                                             uint32 sync_point) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   VideoCaptureControllerID controller_id(device_id);
   EntryMap::iterator it = entries_.find(controller_id);
@@ -312,7 +312,7 @@
 void VideoCaptureHost::OnGetDeviceSupportedFormats(
     int device_id,
     media::VideoCaptureSessionId capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormats, capture_session_id "
            << capture_session_id;
   media::VideoCaptureFormats device_supported_formats;
@@ -330,7 +330,7 @@
 void VideoCaptureHost::OnGetDeviceFormatsInUse(
     int device_id,
     media::VideoCaptureSessionId capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureHost::OnGetDeviceFormatsInUse, capture_session_id "
            << capture_session_id;
   media::VideoCaptureFormats formats_in_use;
@@ -345,7 +345,7 @@
 
 void VideoCaptureHost::DeleteVideoCaptureControllerOnIOThread(
     const VideoCaptureControllerID& controller_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   EntryMap::iterator it = entries_.find(controller_id);
   if (it == entries_.end())
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc
index 54ad96e..a7cca9c 100644
--- a/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -33,6 +33,46 @@
 #endif
 #endif
 
+namespace {
+
+// Compares two VideoCaptureFormat by checking smallest frame_size area, then
+// by _largest_ frame_rate. Used to order a VideoCaptureFormats vector so that
+// the first entry for a given resolution has the largest frame rate, as needed
+// by the ConsolidateCaptureFormats() method.
+bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1,
+                            const media::VideoCaptureFormat& format2) {
+  if (format1.frame_size.GetArea() == format2.frame_size.GetArea())
+    return format1.frame_rate > format2.frame_rate;
+  return format1.frame_size.GetArea() < format2.frame_size.GetArea();
+}
+
+bool IsCaptureFormatSizeEqual(const media::VideoCaptureFormat& format1,
+                              const media::VideoCaptureFormat& format2) {
+  return format1.frame_size.GetArea() == format2.frame_size.GetArea();
+}
+
+// This function receives a list of capture formats, removes duplicated
+// resolutions while keeping the highest frame rate for each, and forcing I420
+// pixel format.
+void ConsolidateCaptureFormats(media::VideoCaptureFormats* formats) {
+  if (formats->empty())
+    return;
+  std::sort(formats->begin(), formats->end(), IsCaptureFormatSmaller);
+  // Due to the ordering imposed, the largest frame_rate is kept while removing
+  // duplicated resolutions.
+  media::VideoCaptureFormats::iterator last =
+      std::unique(formats->begin(), formats->end(), IsCaptureFormatSizeEqual);
+  formats->erase(last, formats->end());
+  // Mark all formats as I420, since this is what the renderer side will get
+  // anyhow: the actual pixel format is decided at the device level.
+  for (media::VideoCaptureFormats::iterator it = formats->begin();
+       it != formats->end(); ++it) {
+    it->pixel_format = media::PIXEL_FORMAT_I420;
+  }
+}
+
+}  // namespace
+
 namespace content {
 
 VideoCaptureManager::DeviceEntry::DeviceEntry(
@@ -68,7 +108,7 @@
 void VideoCaptureManager::Register(
     MediaStreamProviderListener* listener,
     const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(!listener_);
   DCHECK(!device_task_runner_.get());
   listener_ = listener;
@@ -81,7 +121,7 @@
 }
 
 void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureManager::EnumerateDevices, type " << stream_type;
   DCHECK(listener_);
   base::PostTaskAndReplyWithResult(
@@ -93,7 +133,7 @@
 }
 
 int VideoCaptureManager::Open(const StreamDeviceInfo& device_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(listener_);
 
   // Generate a new id for the session being opened.
@@ -116,7 +156,7 @@
 }
 
 void VideoCaptureManager::Close(int capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(listener_);
   DVLOG(1) << "VideoCaptureManager::Close, id " << capture_session_id;
 
@@ -156,6 +196,7 @@
 }
 
 void VideoCaptureManager::DoStartDeviceOnDeviceThread(
+    media::VideoCaptureSessionId session_id,
     DeviceEntry* entry,
     const media::VideoCaptureParams& params,
     scoped_ptr<media::VideoCaptureDevice::Client> device_client) {
@@ -203,6 +244,11 @@
       if (id.type != DesktopMediaID::TYPE_NONE &&
           id.type != DesktopMediaID::TYPE_AURA_WINDOW) {
         video_capture_device = DesktopCaptureDevice::Create(id);
+        if (notification_window_ids_.find(session_id) !=
+            notification_window_ids_.end()) {
+          static_cast<DesktopCaptureDevice*>(video_capture_device.get())
+              ->SetNotificationWindowId(notification_window_ids_[session_id]);
+        }
       }
 #endif  // defined(ENABLE_SCREEN_CAPTURE)
       break;
@@ -229,7 +275,7 @@
     VideoCaptureControllerID client_id,
     VideoCaptureControllerEventHandler* client_handler,
     const DoneCB& done_cb) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DVLOG(1) << "VideoCaptureManager::StartCaptureForClient, "
            << params.requested_format.frame_size.ToString() << ", "
            << params.requested_format.frame_rate << ", #" << session_id << ")";
@@ -252,6 +298,7 @@
         base::Bind(
             &VideoCaptureManager::DoStartDeviceOnDeviceThread,
             this,
+            session_id,
             entry,
             params,
             base::Passed(entry->video_capture_controller->NewDeviceClient())));
@@ -266,7 +313,7 @@
     VideoCaptureController* controller,
     VideoCaptureControllerID client_id,
     VideoCaptureControllerEventHandler* client_handler) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(controller);
   DCHECK(client_handler);
 
@@ -289,7 +336,7 @@
 bool VideoCaptureManager::GetDeviceSupportedFormats(
     media::VideoCaptureSessionId capture_session_id,
     media::VideoCaptureFormats* supported_formats) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(supported_formats->empty());
 
   std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator it =
@@ -309,7 +356,7 @@
 bool VideoCaptureManager::GetDeviceFormatsInUse(
     media::VideoCaptureSessionId capture_session_id,
     media::VideoCaptureFormats* formats_in_use) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(formats_in_use->empty());
 
   std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator it =
@@ -329,6 +376,43 @@
   return true;
 }
 
+void VideoCaptureManager::SetDesktopCaptureWindowId(
+    media::VideoCaptureSessionId session_id,
+    gfx::NativeViewId window_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator
+      session_it = sessions_.find(session_id);
+  if (session_it == sessions_.end()) {
+    device_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread,
+            this,
+            session_id,
+            window_id));
+    return;
+  }
+
+  DeviceEntry* const existing_device =
+      GetDeviceEntryForMediaStreamDevice(session_it->second);
+  if (!existing_device)
+    return;
+
+  DCHECK_EQ(MEDIA_DESKTOP_VIDEO_CAPTURE, existing_device->stream_type);
+  DesktopMediaID id = DesktopMediaID::Parse(existing_device->id);
+  if (id.type == DesktopMediaID::TYPE_NONE ||
+      id.type == DesktopMediaID::TYPE_AURA_WINDOW) {
+    return;
+  }
+
+  device_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread,
+                 this,
+                 existing_device,
+                 window_id));
+}
+
 void VideoCaptureManager::DoStopDeviceOnDeviceThread(DeviceEntry* entry) {
   SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
   DCHECK(IsOnDeviceThread());
@@ -341,7 +425,7 @@
 void VideoCaptureManager::OnOpened(
     MediaStreamType stream_type,
     media::VideoCaptureSessionId capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!listener_) {
     // Listener has been removed.
     return;
@@ -352,7 +436,7 @@
 void VideoCaptureManager::OnClosed(
     MediaStreamType stream_type,
     media::VideoCaptureSessionId capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!listener_) {
     // Listener has been removed.
     return;
@@ -363,7 +447,7 @@
 void VideoCaptureManager::OnDevicesInfoEnumerated(
     MediaStreamType stream_type,
     const DeviceInfos& new_devices_info_cache) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!listener_) {
     // Listener has been removed.
@@ -459,6 +543,7 @@
             *it, &(device_info.supported_formats));
         break;
     }
+    ConsolidateCaptureFormats(&device_info.supported_formats);
     new_devices_info_cache.push_back(device_info);
   }
   return new_devices_info_cache;
@@ -467,7 +552,7 @@
 VideoCaptureManager::DeviceEntry*
 VideoCaptureManager::GetDeviceEntryForMediaStreamDevice(
     const MediaStreamDevice& device_info) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   for (DeviceEntries::iterator it = devices_.begin();
        it != devices_.end(); ++it) {
@@ -494,7 +579,7 @@
 }
 
 void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // Removal of the last client stops the device.
   if (entry->video_capture_controller->GetClientCount() == 0) {
     DVLOG(1) << "VideoCaptureManager stopping device (type = "
@@ -515,7 +600,7 @@
 
 VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
     media::VideoCaptureSessionId capture_session_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   std::map<media::VideoCaptureSessionId, MediaStreamDevice>::iterator
       session_it = sessions_.find(capture_session_id);
@@ -553,4 +638,25 @@
   return NULL;
 }
 
+void VideoCaptureManager::SetDesktopCaptureWindowIdOnDeviceThread(
+    DeviceEntry* entry,
+    gfx::NativeViewId window_id) {
+  DCHECK(IsOnDeviceThread());
+  DCHECK(entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE);
+#if defined(ENABLE_SCREEN_CAPTURE)
+  DesktopCaptureDevice* device =
+      static_cast<DesktopCaptureDevice*>(entry->video_capture_device.get());
+  device->SetNotificationWindowId(window_id);
+#endif
+}
+
+void VideoCaptureManager::SaveDesktopCaptureWindowIdOnDeviceThread(
+    media::VideoCaptureSessionId session_id,
+    gfx::NativeViewId window_id) {
+  DCHECK(IsOnDeviceThread());
+  DCHECK(notification_window_ids_.find(session_id) ==
+         notification_window_ids_.end());
+  notification_window_ids_[session_id] = window_id;
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h
index b3537fa..35aee8e 100644
--- a/content/browser/renderer_host/media/video_capture_manager.h
+++ b/content/browser/renderer_host/media/video_capture_manager.h
@@ -98,6 +98,11 @@
   bool GetDeviceFormatsInUse(media::VideoCaptureSessionId capture_session_id,
                              media::VideoCaptureFormats* formats_in_use);
 
+  // Sets the platform-dependent window ID for the desktop capture notification
+  // UI for the given session.
+  void SetDesktopCaptureWindowId(media::VideoCaptureSessionId session_id,
+                                 gfx::NativeViewId window_id);
+
  private:
   virtual ~VideoCaptureManager();
   struct DeviceEntry;
@@ -156,6 +161,7 @@
   // |entry->video_capture_device|. Ownership of |client| passes to
   // the device.
   void DoStartDeviceOnDeviceThread(
+      media::VideoCaptureSessionId session_id,
       DeviceEntry* entry,
       const media::VideoCaptureParams& params,
       scoped_ptr<media::VideoCaptureDevice::Client> client);
@@ -167,6 +173,13 @@
   DeviceInfo* FindDeviceInfoById(const std::string& id,
                                  DeviceInfos& device_vector);
 
+  void SetDesktopCaptureWindowIdOnDeviceThread(DeviceEntry* entry,
+                                               gfx::NativeViewId window_id);
+
+  void SaveDesktopCaptureWindowIdOnDeviceThread(
+      media::VideoCaptureSessionId session_id,
+      gfx::NativeViewId window_id);
+
   // The message loop of media stream device thread, where VCD's live.
   scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
 
@@ -226,6 +239,10 @@
     Y4M_FILE
   } artificial_device_source_for_testing_;
 
+  // Accessed on the device thread only.
+  std::map<media::VideoCaptureSessionId, gfx::NativeViewId>
+      notification_window_ids_;
+
   DISALLOW_COPY_AND_ASSIGN(VideoCaptureManager);
 };
 
diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
index a24d2c1..7f6376f 100644
--- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc
+++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -452,4 +452,7 @@
   vcm_->Unregister();
 }
 
+// TODO(mcasas): Add a test to check consolidation of the supported formats
+// provided by the device when http://crbug.com/323913 is closed.
+
 }  // namespace content
diff --git a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index 18f20f7..be63c02 100644
--- a/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -276,7 +276,8 @@
 
 void P2PSocketDispatcherHost::DoGetNetworkList() {
   net::NetworkInterfaceList list;
-  net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES);
+  net::GetNetworkList(&list, net::EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES |
+                             net::INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE);
   BrowserThread::PostTask(
       BrowserThread::IO, FROM_HERE, base::Bind(
           &P2PSocketDispatcherHost::SendNetworkList, this, list));
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp.cc b/content/browser/renderer_host/p2p/socket_host_tcp.cc
index 9b4acb7..e1900ef 100644
--- a/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -460,7 +460,9 @@
   memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size());
 
   packet_processing_helpers::ApplyPacketOptions(
-      buffer->data(), buffer->BytesRemaining(), options, 0);
+      buffer->data() + kPacketHeaderSize,
+      buffer->BytesRemaining() - kPacketHeaderSize,
+      options, 0);
 
   WriteOrQueue(buffer);
 }
diff --git a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
index 7dea288..9e068d0 100644
--- a/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
+++ b/content/browser/renderer_host/p2p/socket_host_tcp_unittest.cc
@@ -239,6 +239,37 @@
   EXPECT_EQ(expected_data, sent_data_);
 }
 
+TEST_F(P2PSocketHostTcpTest, SendDataWithPacketOptions) {
+  std::vector<char> request_packet;
+  CreateStunRequest(&request_packet);
+
+  std::string received_data;
+  received_data.append(IntToSize(request_packet.size()));
+  received_data.append(request_packet.begin(), request_packet.end());
+
+  EXPECT_CALL(sender_, Send(
+      MatchMessage(static_cast<uint32>(P2PMsg_OnSendComplete::ID))))
+      .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
+  EXPECT_CALL(sender_, Send(MatchPacketMessage(request_packet)))
+      .WillOnce(DoAll(DeleteArg<0>(), Return(true)));
+  socket_->AppendInputData(&received_data[0], received_data.size());
+
+  talk_base::PacketOptions options;
+  options.packet_time_params.rtp_sendtime_extension_id = 3;
+  // Now we should be able to send any data to |dest_|.
+  std::vector<char> packet;
+  CreateRandomPacket(&packet);
+  // Make it a RTP packet.
+  *reinterpret_cast<uint16*>(&*packet.begin()) = base::HostToNet16(0x8000);
+  socket_host_->Send(dest_.ip_address, packet, options, 0);
+
+  std::string expected_data;
+  expected_data.append(IntToSize(packet.size()));
+  expected_data.append(packet.begin(), packet.end());
+
+  EXPECT_EQ(expected_data, sent_data_);
+}
+
 // Verify that we can send STUN message and that they are formatted
 // properly.
 TEST_F(P2PSocketHostStunTcpTest, SendStunNoAuth) {
diff --git a/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/content/browser/renderer_host/pepper/pepper_file_io_host.cc
index 74dc8c5..6b49815 100644
--- a/content/browser/renderer_host/pepper/pepper_file_io_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_file_io_host.cc
@@ -44,7 +44,7 @@
 PepperFileIOHost::UIThreadStuff
 GetUIThreadStuffForInternalFileSystems(int render_process_id) {
   PepperFileIOHost::UIThreadStuff stuff;
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
   if (host) {
     stuff.resolved_render_process_id = base::GetProcId(host->GetHandle());
@@ -56,7 +56,7 @@
 }
 
 base::ProcessId GetResolvedRenderProcessId(int render_process_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
   if (!host)
     return base::kNullProcessId;
@@ -65,7 +65,7 @@
 
 bool GetPluginAllowedToCallRequestOSFileHandle(int render_process_id,
                                                const GURL& document_url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ContentBrowserClient* client = GetContentClient()->browser();
   RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
   if (!host)
@@ -199,7 +199,7 @@
     ppapi::host::ReplyMessageContext reply_context,
     int platform_file_flags,
     UIThreadStuff ui_thread_stuff) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   file_system_context_ = ui_thread_stuff.file_system_context;
   resolved_render_process_id_ = ui_thread_stuff.resolved_render_process_id;
   if (resolved_render_process_id_ == base::kNullProcessId ||
@@ -255,7 +255,7 @@
     base::FilePath path,
     int platform_file_flags,
     base::ProcessId resolved_render_process_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   resolved_render_process_id_ = resolved_render_process_id;
   base::FileUtilProxy::CreateOrOpen(
       file_message_loop_,
@@ -394,7 +394,7 @@
 void PepperFileIOHost::GotPluginAllowedToCallRequestOSFileHandle(
     ppapi::host::ReplyMessageContext reply_context,
     bool plugin_allowed) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!browser_ppapi_host_->external_plugin() ||
       host()->permissions().HasPermission(ppapi::PERMISSION_PRIVATE) ||
       plugin_allowed) {
diff --git a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
index 0401ae2..0aca903 100644
--- a/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_file_system_browser_host.cc
@@ -36,7 +36,7 @@
 
 scoped_refptr<fileapi::FileSystemContext>
 GetFileSystemContextFromRenderId(int render_process_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
   if (!host)
     return NULL;
diff --git a/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc b/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
index 897fc4d..422005f 100644
--- a/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc
@@ -122,7 +122,7 @@
     const ppapi::host::HostMessageContext* context,
     const ppapi::HostPortPair& host_port,
     const PP_HostResolver_Private_Hint& hint) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // Check plugin permissions.
   SocketPermissionRequest request(
@@ -158,7 +158,7 @@
     const ppapi::HostPortPair& host_port,
     const PP_HostResolver_Private_Hint& hint,
     ResourceContext* resource_context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   net::HostResolver* host_resolver = resource_context->GetHostResolver();
   if (!host_resolver) {
diff --git a/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc b/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
index bc48bc9..c62e1de 100644
--- a/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
@@ -21,7 +21,7 @@
 bool CanUseNetworkMonitor(bool external_plugin,
                           int render_process_id,
                           int render_frame_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   SocketPermissionRequest request = SocketPermissionRequest(
       SocketPermissionRequest::NETWORK_STATE, std::string(), 0);
@@ -79,7 +79,7 @@
 }
 
 void PepperNetworkMonitorHost::GetAndSendNetworkList() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Call GetNetworkList() on a thread that allows blocking IO.
   base::PostTaskAndReplyWithResult(
@@ -91,7 +91,7 @@
 
 void PepperNetworkMonitorHost::SendNetworkList(
     scoped_ptr<net::NetworkInterfaceList> list) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   scoped_ptr<ppapi::proxy::SerializedNetworkList> list_copy(
       new ppapi::proxy::SerializedNetworkList(list->size()));
diff --git a/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc b/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
index 8f44537..7fdda73 100644
--- a/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc
@@ -67,7 +67,7 @@
 PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
                                                   int render_frame_id,
                                                   bool is_external_plugin) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   PepperNetworkProxyHost::UIThreadData result;
   RenderProcessHost* render_process_host =
       RenderProcessHost::FromID(render_process_id);
diff --git a/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc b/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
index 84aaddf..14fbc08 100644
--- a/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
+++ b/content/browser/renderer_host/pepper/pepper_print_settings_manager.cc
@@ -45,7 +45,7 @@
 PepperPrintSettingsManager::Result ComputeDefaultPrintSettings() {
   // This function should run on the UI thread because |PrintingContext| methods
   // call into platform APIs.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   scoped_ptr<printing::PrintingContext> context(
   printing::PrintingContext::Create(std::string()));
   if (!context.get() ||
diff --git a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
index f20562e..cd61bb8 100644
--- a/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
+++ b/content/browser/renderer_host/pepper/pepper_renderer_connection.cc
@@ -110,7 +110,7 @@
 
 BrowserPpapiHostImpl* PepperRendererConnection::GetHostForChildProcess(
     int child_process_id) const {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Find the plugin which this message refers to. Check NaCl plugins first.
   BrowserPpapiHostImpl* host = static_cast<BrowserPpapiHostImpl*>(
diff --git a/content/browser/renderer_host/pepper/pepper_socket_utils.cc b/content/browser/renderer_host/pepper/pepper_socket_utils.cc
index 9fc17c5..c667f31 100644
--- a/content/browser/renderer_host/pepper/pepper_socket_utils.cc
+++ b/content/browser/renderer_host/pepper/pepper_socket_utils.cc
@@ -41,7 +41,7 @@
                       const SocketPermissionRequest* params,
                       int render_process_id,
                       int render_frame_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!external_plugin) {
     // Always allow socket APIs for out-process plugins (other than external
     // plugins instantiated by the embeeder through
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
index 5c59870..517fb99 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc
@@ -100,7 +100,7 @@
     const ppapi::host::HostMessageContext* context,
     const PP_NetAddress_Private& addr,
     int32_t backlog) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(context);
 
   SocketPermissionRequest request =
@@ -123,7 +123,7 @@
 
 int32_t PepperTCPServerSocketMessageFilter::OnMsgAccept(
     const ppapi::host::HostMessageContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(context);
 
   if (state_ != STATE_LISTENING)
@@ -144,7 +144,7 @@
 
 int32_t PepperTCPServerSocketMessageFilter::OnMsgStopListening(
     const ppapi::host::HostMessageContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(context);
 
   state_ = STATE_CLOSED;
@@ -156,7 +156,7 @@
     const ppapi::host::ReplyMessageContext& context,
     const PP_NetAddress_Private& addr,
     int32_t backlog) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   net::IPAddressNumber address;
   int port;
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
index c5b752a..9a8be5c 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
+++ b/content/browser/renderer_host/pepper/pepper_tcp_socket.cc
@@ -78,7 +78,7 @@
 }
 
 void PepperTCPSocket::Connect(const std::string& host, uint16_t port) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (connection_state_ != BEFORE_CONNECT) {
     SendConnectACKError(PP_ERROR_FAILED);
@@ -101,7 +101,7 @@
 
 void PepperTCPSocket::ConnectWithNetAddress(
     const PP_NetAddress_Private& net_addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (connection_state_ != BEFORE_CONNECT) {
     SendConnectACKError(PP_ERROR_FAILED);
@@ -128,7 +128,7 @@
     uint16_t server_port,
     const std::vector<std::vector<char> >& trusted_certs,
     const std::vector<std::vector<char> >& untrusted_certs) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Allow to do SSL handshake only if currently the socket has been connected
   // and there isn't pending read or write.
@@ -167,7 +167,7 @@
 }
 
 void PepperTCPSocket::Read(int32 bytes_to_read) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!IsConnected() || end_of_file_reached_) {
     SendReadACKError(PP_ERROR_FAILED);
@@ -195,7 +195,7 @@
 }
 
 void PepperTCPSocket::Write(const std::string& data) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!IsConnected()) {
     SendWriteACKError(PP_ERROR_FAILED);
@@ -223,7 +223,7 @@
 
 void PepperTCPSocket::SetOption(PP_TCPSocket_Option name,
                                 const ppapi::SocketOptionData& value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!IsConnected() || IsSsl()) {
     SendSetOptionACK(PP_ERROR_FAILED);
diff --git a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
index 9727616..a76ca4e 100644
--- a/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -171,7 +171,7 @@
 int32_t PepperTCPSocketMessageFilter::OnMsgBind(
     const ppapi::host::HostMessageContext* context,
     const PP_NetAddress_Private& net_addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // This is only supported by PPB_TCPSocket v1.1 or above.
   if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
@@ -198,7 +198,7 @@
     const ppapi::host::HostMessageContext* context,
     const std::string& host,
     uint16_t port) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // This is only supported by PPB_TCPSocket_Private.
   if (!IsPrivateAPI()) {
@@ -234,7 +234,7 @@
 int32_t PepperTCPSocketMessageFilter::OnMsgConnectWithNetAddress(
     const ppapi::host::HostMessageContext* context,
     const PP_NetAddress_Private& net_addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   content::SocketPermissionRequest request =
       pepper_socket_utils::CreateSocketPermissionRequest(
@@ -258,7 +258,7 @@
     uint16_t server_port,
     const std::vector<std::vector<char> >& trusted_certs,
     const std::vector<std::vector<char> >& untrusted_certs) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Allow to do SSL handshake only if currently the socket has been connected
   // and there isn't pending read or write.
@@ -306,7 +306,7 @@
 int32_t PepperTCPSocketMessageFilter::OnMsgRead(
     const ppapi::host::HostMessageContext* context,
     int32_t bytes_to_read) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (!state_.IsConnected() || end_of_file_reached_)
     return PP_ERROR_FAILED;
   if (read_buffer_.get())
@@ -344,7 +344,7 @@
 int32_t PepperTCPSocketMessageFilter::OnMsgWrite(
     const ppapi::host::HostMessageContext* context,
     const std::string& data) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!state_.IsConnected())
     return PP_ERROR_FAILED;
@@ -368,7 +368,7 @@
 int32_t PepperTCPSocketMessageFilter::OnMsgListen(
     const ppapi::host::HostMessageContext* context,
     int32_t backlog) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   // This is only supported by PPB_TCPSocket v1.1 or above.
   if (version_ != ppapi::TCP_SOCKET_VERSION_1_1_OR_ABOVE) {
@@ -394,7 +394,7 @@
 
 int32_t PepperTCPSocketMessageFilter::OnMsgAccept(
     const ppapi::host::HostMessageContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (pending_accept_)
     return PP_ERROR_INPROGRESS;
@@ -416,7 +416,7 @@
 
 int32_t PepperTCPSocketMessageFilter::OnMsgClose(
     const ppapi::host::HostMessageContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (state_.state() == TCPSocketState::CLOSED)
     return PP_OK;
 
@@ -434,7 +434,7 @@
     const ppapi::host::HostMessageContext* context,
     PP_TCPSocket_Option name,
     const ppapi::SocketOptionData& value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   switch (name) {
     case PP_TCPSOCKET_OPTION_NO_DELAY: {
@@ -477,7 +477,7 @@
 void PepperTCPSocketMessageFilter::DoBind(
     const ppapi::host::ReplyMessageContext& context,
     const PP_NetAddress_Private& net_addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (state_.IsPending(TCPSocketState::BIND)) {
     SendBindError(context, PP_ERROR_INPROGRESS);
@@ -543,7 +543,7 @@
     const std::string& host,
     uint16_t port,
     ResourceContext* resource_context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
     SendConnectError(context, PP_ERROR_FAILED);
@@ -570,7 +570,7 @@
 void PepperTCPSocketMessageFilter::DoConnectWithNetAddress(
     const ppapi::host::ReplyMessageContext& context,
     const PP_NetAddress_Private& net_addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!state_.IsValidTransition(TCPSocketState::CONNECT)) {
     SendConnectError(context, PP_ERROR_FAILED);
@@ -597,7 +597,7 @@
 
 void PepperTCPSocketMessageFilter::DoWrite(
     const ppapi::host::ReplyMessageContext& context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(write_buffer_base_.get());
   DCHECK(write_buffer_.get());
   DCHECK_GT(write_buffer_->BytesRemaining(), 0);
@@ -626,7 +626,7 @@
 void PepperTCPSocketMessageFilter::DoListen(
     const ppapi::host::ReplyMessageContext& context,
     int32_t backlog) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (state_.IsPending(TCPSocketState::LISTEN)) {
     SendListenReply(context, PP_ERROR_INPROGRESS);
@@ -645,7 +645,7 @@
 void PepperTCPSocketMessageFilter::OnResolveCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!state_.IsPending(TCPSocketState::CONNECT)) {
     DCHECK(state_.state() == TCPSocketState::CLOSED);
@@ -664,7 +664,7 @@
 
 void PepperTCPSocketMessageFilter::StartConnect(
     const ppapi::host::ReplyMessageContext& context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(state_.IsPending(TCPSocketState::CONNECT));
   DCHECK_LT(address_index_, address_list_.size());
 
@@ -685,7 +685,7 @@
 void PepperTCPSocketMessageFilter::OnConnectCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!state_.IsPending(TCPSocketState::CONNECT)) {
     DCHECK(state_.state() == TCPSocketState::CLOSED);
@@ -758,7 +758,7 @@
 void PepperTCPSocketMessageFilter::OnSSLHandshakeCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!state_.IsPending(TCPSocketState::SSL_CONNECT)) {
     DCHECK(state_.state() == TCPSocketState::CLOSED);
@@ -773,7 +773,7 @@
 void PepperTCPSocketMessageFilter::OnReadCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(read_buffer_.get());
 
   if (net_result > 0) {
@@ -792,7 +792,7 @@
 void PepperTCPSocketMessageFilter::OnWriteCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(write_buffer_base_.get());
   DCHECK(write_buffer_.get());
 
@@ -818,7 +818,7 @@
 void PepperTCPSocketMessageFilter::OnAcceptCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(pending_accept_);
 
   pending_accept_ = false;
diff --git a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
index 82805cd..4162737 100644
--- a/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
+++ b/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc
@@ -107,7 +107,7 @@
     const ppapi::host::HostMessageContext* context,
     PP_UDPSocket_Option name,
     const ppapi::SocketOptionData& value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (closed_)
     return PP_ERROR_FAILED;
@@ -166,7 +166,7 @@
 int32_t PepperUDPSocketMessageFilter::OnMsgBind(
     const ppapi::host::HostMessageContext* context,
     const PP_NetAddress_Private& addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(context);
 
   SocketPermissionRequest request =
@@ -189,7 +189,7 @@
 int32_t PepperUDPSocketMessageFilter::OnMsgRecvFrom(
     const ppapi::host::HostMessageContext* context,
     int32_t num_bytes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(context);
   DCHECK(socket_.get());
 
@@ -229,7 +229,7 @@
     const ppapi::host::HostMessageContext* context,
     const std::string& data,
     const PP_NetAddress_Private& addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(context);
 
   SocketPermissionRequest request =
@@ -250,7 +250,7 @@
 
 int32_t PepperUDPSocketMessageFilter::OnMsgClose(
     const ppapi::host::HostMessageContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   Close();
   return PP_OK;
 }
@@ -258,7 +258,7 @@
 void PepperUDPSocketMessageFilter::DoBind(
     const ppapi::host::ReplyMessageContext& context,
     const PP_NetAddress_Private& addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (closed_ || socket_.get()) {
     SendBindError(context, PP_ERROR_FAILED);
@@ -313,7 +313,7 @@
     const ppapi::host::ReplyMessageContext& context,
     const std::string& data,
     const PP_NetAddress_Private& addr) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(socket_.get());
 
   if (closed_ || !socket_.get()) {
@@ -360,7 +360,7 @@
 }
 
 void PepperUDPSocketMessageFilter::Close() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   if (socket_.get() && !closed_)
     socket_->Close();
   closed_ = true;
@@ -369,7 +369,7 @@
 void PepperUDPSocketMessageFilter::OnRecvFromCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(recvfrom_buffer_.get());
 
   int32_t pp_result = NetErrorToPepperError(net_result);
@@ -396,7 +396,7 @@
 void PepperUDPSocketMessageFilter::OnSendToCompleted(
     const ppapi::host::ReplyMessageContext& context,
     int net_result) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(sendto_buffer_.get());
 
   int32_t pp_result = NetErrorToPepperError(net_result);
diff --git a/content/browser/renderer_host/popup_menu_helper_mac.h b/content/browser/renderer_host/popup_menu_helper_mac.h
index 332fecd..8a6f317 100644
--- a/content/browser/renderer_host/popup_menu_helper_mac.h
+++ b/content/browser/renderer_host/popup_menu_helper_mac.h
@@ -13,6 +13,12 @@
 #include "content/public/browser/notification_registrar.h"
 #include "ui/gfx/rect.h"
 
+#ifdef __OBJC__
+@class WebMenuRunner;
+#else
+class WebMenuRunner;
+#endif
+
 namespace content {
 class RenderViewHost;
 class RenderViewHostImpl;
@@ -24,6 +30,7 @@
   // Creates a PopupMenuHelper that will notify |render_view_host| when a user
   // selects or cancels the popup.
   explicit PopupMenuHelper(RenderViewHost* render_view_host);
+  void Hide();
 
   // Shows the popup menu and notifies the RenderViewHost of the selection/
   // cancel.
@@ -48,8 +55,9 @@
                        const NotificationDetails& details) OVERRIDE;
 
   NotificationRegistrar notification_registrar_;
-
   RenderViewHostImpl* render_view_host_;
+  WebMenuRunner* menu_runner_;
+  bool popup_was_hidden_;
 
   DISALLOW_COPY_AND_ASSIGN(PopupMenuHelper);
 };
diff --git a/content/browser/renderer_host/popup_menu_helper_mac.mm b/content/browser/renderer_host/popup_menu_helper_mac.mm
index d5b9ed8..1fb28ba 100644
--- a/content/browser/renderer_host/popup_menu_helper_mac.mm
+++ b/content/browser/renderer_host/popup_menu_helper_mac.mm
@@ -25,7 +25,9 @@
 }  // namespace
 
 PopupMenuHelper::PopupMenuHelper(RenderViewHost* render_view_host)
-    : render_view_host_(static_cast<RenderViewHostImpl*>(render_view_host)) {
+    : render_view_host_(static_cast<RenderViewHostImpl*>(render_view_host)),
+      menu_runner_(nil),
+      popup_was_hidden_(false) {
   notification_registrar_.Add(
       this, NOTIFICATION_RENDER_WIDGET_HOST_DESTROYED,
       Source<RenderWidgetHost>(render_view_host));
@@ -55,10 +57,9 @@
       [rwhvm->cocoa_view() retain]);
 
   // Display the menu.
-  base::scoped_nsobject<WebMenuRunner> menu_runner;
-   menu_runner.reset([[WebMenuRunner alloc] initWithItems:items
-                                                 fontSize:item_font_size
-                                             rightAligned:right_aligned]);
+  menu_runner_ = [[WebMenuRunner alloc] initWithItems:items
+                                             fontSize:item_font_size
+                                         rightAligned:right_aligned];
 
   {
     // Make sure events can be pumped while the menu is up.
@@ -73,23 +74,35 @@
     base::mac::ScopedSendingEvent sending_event_scoper;
 
     // Now run a SYNCHRONOUS NESTED EVENT LOOP until the pop-up is finished.
-    [menu_runner runMenuInView:cocoa_view
-                    withBounds:[cocoa_view flipRectToNSRect:bounds]
-                  initialIndex:selected_item];
+    [menu_runner_ runMenuInView:cocoa_view
+                     withBounds:[cocoa_view flipRectToNSRect:bounds]
+                   initialIndex:selected_item];
   }
 
   if (!render_view_host_) {
     // Bad news, the RenderViewHost got deleted while we were off running the
     // menu. Nothing to do.
+    [menu_runner_ release];
+    menu_runner_ = nil;
     return;
   }
 
-  if ([menu_runner menuItemWasChosen]) {
-    render_view_host_->DidSelectPopupMenuItem(
-        [menu_runner indexOfSelectedItem]);
-  } else {
-    render_view_host_->DidCancelPopupMenu();
+  if (!popup_was_hidden_) {
+    if ([menu_runner_ menuItemWasChosen]) {
+      render_view_host_->DidSelectPopupMenuItem(
+          [menu_runner_ indexOfSelectedItem]);
+    } else {
+      render_view_host_->DidCancelPopupMenu();
+    }
   }
+  [menu_runner_ release];
+  menu_runner_ = nil;
+}
+
+void PopupMenuHelper::Hide() {
+  if (menu_runner_)
+    [menu_runner_ hide];
+  popup_was_hidden_ = true;
 }
 
 // static
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc
index 958b491..db72620 100644
--- a/content/browser/renderer_host/render_message_filter.cc
+++ b/content/browser/renderer_host/render_message_filter.cc
@@ -62,7 +62,7 @@
 #include "net/base/mime_util.h"
 #include "net/base/request_priority.h"
 #include "net/cookies/canonical_cookie.h"
-#include "net/cookies/cookie_monster.h"
+#include "net/cookies/cookie_store.h"
 #include "net/http/http_cache.h"
 #include "net/url_request/url_request_context.h"
 #include "net/url_request/url_request_context_getter.h"
@@ -84,6 +84,7 @@
 #endif
 #if defined(OS_WIN)
 #include "content/common/font_cache_dispatcher_win.h"
+#include "content/common/sandbox_win.h"
 #endif
 #if defined(OS_ANDROID)
 #include "media/base/android/webaudio_media_codec_bridge.h"
@@ -350,7 +351,7 @@
 
 RenderMessageFilter::~RenderMessageFilter() {
   // This function should be called on the IO thread.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(plugin_host_clients_.empty());
 }
 
@@ -563,7 +564,7 @@
 
 void RenderMessageFilter::OnGetProcessMemorySizes(size_t* private_bytes,
                                                   size_t* shared_bytes) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   using base::ProcessMetrics;
 #if !defined(OS_MACOSX) || defined(OS_IOS)
   scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
@@ -594,7 +595,7 @@
     net::CookieStore* cookie_store = GetCookieStoreForURL(url);
     // Pass a null callback since we don't care about when the 'set' completes.
     cookie_store->SetCookieWithOptionsAsync(
-        url, cookie, options, net::CookieMonster::SetCookiesCallback());
+        url, cookie, options, net::CookieStore::SetCookiesCallback());
   }
 }
 
@@ -616,8 +617,7 @@
   base::debug::Alias(url_buf);
 
   net::CookieStore* cookie_store = GetCookieStoreForURL(url);
-  net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster();
-  cookie_monster->GetAllCookiesForURLAsync(
+  cookie_store->GetAllCookiesForURLAsync(
       url, base::Bind(&RenderMessageFilter::CheckPolicyForCookies, this,
                       render_frame_id, url, first_party_for_cookies,
                       reply_msg));
@@ -643,8 +643,7 @@
   // be applied to outbound requests for the given URL.  Since this cookie info
   // is visible in the developer tools, it is helpful to make it match reality.
   net::CookieStore* cookie_store = GetCookieStoreForURL(url);
-  net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster();
-  cookie_monster->GetAllCookiesForURLAsync(
+  cookie_store->GetAllCookiesForURLAsync(
       url, base::Bind(&RenderMessageFilter::SendGetRawCookiesResponse,
                       this, reply_msg));
 }
@@ -956,7 +955,7 @@
 
 net::CookieStore* RenderMessageFilter::GetCookieStoreForURL(
     const GURL& url) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   net::URLRequestContext* context =
       GetContentClient()->browser()->OverrideRequestContextForURL(
@@ -1134,7 +1133,7 @@
 
 void RenderMessageFilter::OnCompletedOpenChannelToNpapiPlugin(
     OpenChannelToNpapiPluginCallback* client) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   DCHECK(ContainsKey(plugin_host_clients_, client));
   plugin_host_clients_.erase(client);
 }
@@ -1201,6 +1200,9 @@
 #if defined(OS_WIN)
 void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font,
                                                    const base::string16& str) {
+  // TODO(scottmg): Move this to FontCacheDispatcher, http://crbug.com/356346.
+  if (!ShouldUseDirectWrite())
+    return;
   // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
   // Except that for True Type fonts,
   // GetTextMetrics will not load the font in memory.
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index ef59bf5..b1c89a5 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -9,9 +9,9 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace content {
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 43929cb..30d9f73 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -161,9 +161,7 @@
 #endif
 
 #if defined(USE_MOJO)
-#include "content/common/mojo/mojo_channel_init.h"
-#include "content/common/mojo/mojo_messages.h"
-#include "mojo/embedder/platform_channel_pair.h"
+#include "content/browser/renderer_host/render_process_host_mojo_impl.h"
 #endif
 
 extern bool g_exited_main_message_loop;
@@ -212,7 +210,7 @@
 IPC::PlatformFileForTransit CreateAecDumpFileForProcess(
     base::FilePath file_path,
     base::ProcessHandle process) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   base::PlatformFileError error = base::PLATFORM_FILE_OK;
   base::PlatformFile aec_dump_file = base::CreatePlatformFile(
       file_path,
@@ -228,7 +226,7 @@
 
 // Does nothing. Just to avoid races between enable and disable.
 void DisableAecDumpOnFileThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 }
 #endif
 
@@ -331,17 +329,6 @@
 #endif  // OS_POSIX
 };
 
-#if defined(USE_MOJO)
-base::PlatformFile PlatformFileFromScopedPlatformHandle(
-    mojo::embedder::ScopedPlatformHandle handle) {
-#if defined(OS_POSIX)
-  return handle.release().fd;
-#elif defined(OS_WIN)
-  return handle.release().handle;
-#endif
-}
-#endif
-
 }  // namespace
 
 RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
@@ -627,7 +614,7 @@
 }
 
 void RenderProcessHostImpl::CreateMessageFilters() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   AddFilter(new ResourceSchedulerFilter(GetID()));
   MediaInternals* media_internals = MediaInternals::GetInstance();
   media::AudioManager* audio_manager =
@@ -709,12 +696,6 @@
   AddFilter(new IndexedDBDispatcherHost(
       storage_partition_impl_->GetIndexedDBContext()));
 
-  scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter =
-      new ServiceWorkerDispatcherHost(GetID());
-  service_worker_filter->Init(
-      storage_partition_impl_->GetServiceWorkerContext());
-  AddFilter(service_worker_filter);
-
   if (IsGuest()) {
     if (!g_browser_plugin_geolocation_context.Get().get()) {
       g_browser_plugin_geolocation_context.Get() =
@@ -738,8 +719,8 @@
       GetID(),
       browser_context->GetResourceContext()->GetMediaDeviceIDSalt(),
       media_stream_manager));
-  AddFilter(
-      new DeviceRequestMessageFilter(resource_context, media_stream_manager));
+  AddFilter(new DeviceRequestMessageFilter(
+      resource_context, media_stream_manager, GetID()));
   AddFilter(new MediaStreamTrackMetricsHost());
 #endif
 #if defined(ENABLE_PLUGINS)
@@ -764,7 +745,9 @@
 #if defined(OS_MACOSX)
   AddFilter(new TextInputClientMessageFilter(GetID()));
 #elif defined(OS_WIN)
-  channel_->AddFilter(new FontCacheDispatcher());
+  // The FontCacheDispatcher is required only when we're using GDI rendering.
+  if (!ShouldUseDirectWrite())
+    channel_->AddFilter(new FontCacheDispatcher());
 #elif defined(OS_ANDROID)
   browser_demuxer_android_ = new BrowserDemuxerAndroid();
   AddFilter(browser_demuxer_android_);
@@ -785,13 +768,20 @@
           base::Bind(&GetRequestContext, request_context,
                      media_request_context, ResourceType::SUB_RESOURCE));
 
-  AddFilter(new WebSocketDispatcherHost(websocket_request_context_callback));
+  AddFilter(
+      new WebSocketDispatcherHost(GetID(), websocket_request_context_callback));
 
   message_port_message_filter_ = new MessagePortMessageFilter(
       base::Bind(&RenderWidgetHelper::GetNextRoutingID,
                  base::Unretained(widget_helper_.get())));
   AddFilter(message_port_message_filter_);
 
+  scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter =
+      new ServiceWorkerDispatcherHost(GetID(), message_port_message_filter_);
+  service_worker_filter->Init(
+      storage_partition_impl_->GetServiceWorkerContext());
+  AddFilter(service_worker_filter);
+
   // If "--enable-embedded-shared-worker" is set, we use
   // SharedWorkerMessageFilter in stead of WorkerMessageFilter.
   if (WorkerService::EmbeddedSharedWorkerEnabled()) {
@@ -966,13 +956,16 @@
 }
 
 static void AppendGpuCommandLineFlags(CommandLine* command_line) {
-  if (content::IsThreadedCompositingEnabled())
+  if (IsThreadedCompositingEnabled())
     command_line->AppendSwitch(switches::kEnableThreadedCompositing);
 
-  if (content::IsDelegatedRendererEnabled())
+  if (IsForceCompositingModeEnabled())
+    command_line->AppendSwitch(switches::kForceCompositingMode);
+
+  if (IsDelegatedRendererEnabled())
     command_line->AppendSwitch(switches::kEnableDelegatedRenderer);
 
-  if (content::IsImplSidePaintingEnabled())
+  if (IsImplSidePaintingEnabled())
     command_line->AppendSwitch(switches::kEnableImplSidePainting);
 
   // Appending disable-gpu-feature switches due to software rendering list.
@@ -1038,9 +1031,9 @@
     switches::kDisableCompositingForFixedPosition,
     switches::kDisableCompositingForTransition,
     switches::kDisableDatabases,
-    switches::kDisableDelegatedRenderer,
     switches::kDisableDesktopNotifications,
     switches::kDisableDirectNPAPIRequests,
+    switches::kDisableFastTextAutosizing,
     switches::kDisableFileSystem,
     switches::kDisableFiltersOverIPC,
     switches::kDisableGpu,
@@ -1049,7 +1042,6 @@
     switches::kDisableGpuVsync,
     switches::kDisableLowResTiling,
     switches::kDisableHistogramCustomizer,
-    switches::kDisableImplSidePainting,
     switches::kDisableLCDText,
     switches::kDisableLayerSquashing,
     switches::kDisableLocalStorage,
@@ -1063,7 +1055,6 @@
     switches::kDisableSessionStorage,
     switches::kDisableSharedWorkers,
     switches::kDisableSpeechInput,
-    switches::kDisableThreadedCompositing,
     switches::kDisableTouchAdjustment,
     switches::kDisableTouchDragDrop,
     switches::kDisableTouchEditing,
@@ -1081,7 +1072,6 @@
     switches::kEnableCompositingForFixedPosition,
     switches::kEnableCompositingForTransition,
     switches::kEnableDeferredImageDecoding,
-    switches::kEnableDelegatedRenderer,
     switches::kEnableEncryptedMedia,
     switches::kEnableExperimentalCanvasFeatures,
     switches::kEnableExperimentalWebPlatformFeatures,
@@ -1094,12 +1084,10 @@
     switches::kEnableHighDpiCompositingForFixedPosition,
     switches::kEnableHTMLImports,
     switches::kEnableLowResTiling,
-    switches::kEnableImplSidePainting,
     switches::kEnableInbandTextTracks,
     switches::kEnableLCDText,
     switches::kEnableLayerSquashing,
     switches::kEnableLogging,
-    switches::kEnableMP3StreamParser,
     switches::kEnableMapImage,
     switches::kEnableMemoryBenchmarking,
     switches::kEnableOverlayFullscreenVideo,
@@ -1115,7 +1103,6 @@
     switches::kEnableStatsTable,
     switches::kEnableStrictSiteIsolation,
     switches::kEnableTargetedStyleRecalc,
-    switches::kEnableThreadedCompositing,
     switches::kEnableUniversalAcceleratedOverflowScroll,
     switches::kEnableTouchDragDrop,
     switches::kEnableTouchEditing,
@@ -1207,21 +1194,12 @@
     switches::kEnableSpeechRecognition,
     switches::kMediaDrmEnableNonCompositing,
     switches::kNetworkCountryIso,
-#endif
-#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
-    switches::kEnableWebAudio,
-#else
-    // Need to be able to disable webaudio on other platforms where it
-    // is enabled by default.
     switches::kDisableWebAudio,
 #endif
 #if defined(OS_MACOSX)
     // Allow this to be set when invoking the browser and relayed along.
     switches::kEnableSandboxLogging,
 #endif
-#if defined(OS_POSIX)
-    switches::kChildCleanExit,
-#endif
 #if defined(OS_WIN)
     switches::kEnableDirectWrite,
     switches::kEnableHighResolutionTime,
@@ -1285,8 +1263,11 @@
   if (!SuddenTerminationAllowed())
     return false;
 
-  if (worker_ref_count_ != 0)
+  if (worker_ref_count_ != 0) {
+    if (survive_for_worker_start_time_.is_null())
+      survive_for_worker_start_time_ = base::TimeTicks::Now();
     return false;
+  }
 
   // Set this before ProcessDied() so observers can tell if the render process
   // died due to fast shutdown versus another cause.
@@ -1511,8 +1492,19 @@
   }
   delayed_cleanup_needed_ = false;
 
+  // Records the time when the process starts surviving for workers for UMA.
+  if (listeners_.IsEmpty() && worker_ref_count_ > 0 &&
+      survive_for_worker_start_time_.is_null()) {
+    survive_for_worker_start_time_ = base::TimeTicks::Now();
+  }
+
   // When there are no other owners of this object, we can delete ourselves.
   if (listeners_.IsEmpty() && worker_ref_count_ == 0) {
+    if (!survive_for_worker_start_time_.is_null()) {
+      UMA_HISTOGRAM_LONG_TIMES(
+          "SharedWorker.RendererSurviveForWorkerTime",
+          base::TimeTicks::Now() - survive_for_worker_start_time_);
+    }
     // We cannot clean up twice; if this fails, there is an issue with our
     // control flow.
     DCHECK(!deleting_soon_);
@@ -1579,7 +1571,7 @@
 
 #if defined(ENABLE_WEBRTC)
 void RenderProcessHostImpl::EnableAecDump(const base::FilePath& file) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserThread::PostTaskAndReplyWithResult(
       BrowserThread::FILE, FROM_HERE,
       base::Bind(&CreateAecDumpFileForProcess, file, GetHandle()),
@@ -1588,7 +1580,7 @@
 }
 
 void RenderProcessHostImpl::DisableAecDump() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   // Posting on the FILE thread and then replying back on the UI thread is only
   // for avoiding races between enable and disable. Nothing is done on the FILE
   // thread.
@@ -1754,13 +1746,13 @@
 
 // static
 RenderProcessHost::iterator RenderProcessHost::AllHostsIterator() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return iterator(g_all_hosts.Pointer());
 }
 
 // static
 RenderProcessHost* RenderProcessHost::FromID(int render_process_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return g_all_hosts.Get().Lookup(render_process_id);
 }
 
@@ -1941,6 +1933,10 @@
 
   ClearTransportDIBCache();
 
+#if defined(USE_MOJO)
+  render_process_host_mojo_.reset();
+#endif
+
   // It's possible that one of the calls out to the observers might have caused
   // this object to be no longer needed.
   if (delayed_cleanup_needed_)
@@ -1986,7 +1982,7 @@
 
 #if defined(ENABLE_WEBRTC)
 void RenderProcessHostImpl::WebRtcLogMessage(const std::string& message) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!webrtc_log_message_callback_.is_null())
     webrtc_log_message_callback_.Run(message);
 }
@@ -2083,6 +2079,11 @@
   if (WebRTCInternals::GetInstance()->aec_dump_enabled())
     EnableAecDump(WebRTCInternals::GetInstance()->aec_dump_file_path());
 #endif
+
+#if defined(USE_MOJO)
+  if (render_process_host_mojo_.get())
+    render_process_host_mojo_->OnProcessLaunched();
+#endif
 }
 
 scoped_refptr<AudioRendererHost>
@@ -2144,12 +2145,12 @@
 #endif
 
 void RenderProcessHostImpl::IncrementWorkerRefCount() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ++worker_ref_count_;
 }
 
 void RenderProcessHostImpl::DecrementWorkerRefCount() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK_GT(worker_ref_count_, 0);
   --worker_ref_count_;
   if (worker_ref_count_ == 0)
@@ -2157,24 +2158,12 @@
 }
 
 #if defined(USE_MOJO)
-void RenderProcessHostImpl::CreateMojoChannel() {
-  if (mojo_channel_init_.get())
-    return;
-
-  mojo::embedder::PlatformChannelPair channel_pair;
-  mojo_channel_init_.reset(new MojoChannelInit);
-  mojo_channel_init_->Init(
-      PlatformFileFromScopedPlatformHandle(channel_pair.PassServerHandle()),
-      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
-  if (mojo_channel_init_->is_handle_valid()) {
-    base::ProcessHandle process_handle = run_renderer_in_process() ?
-        base::Process::Current().handle() :
-        child_process_launcher_->GetHandle();
-    base::PlatformFile client_file =
-        PlatformFileFromScopedPlatformHandle(channel_pair.PassClientHandle());
-    Send(new MojoMsg_ChannelCreated(
-             IPC::GetFileHandleForProcess(client_file, process_handle, true)));
-  }
+void RenderProcessHostImpl::SetWebUIHandle(
+    int32 view_routing_id,
+    mojo::ScopedMessagePipeHandle handle) {
+  if (!render_process_host_mojo_)
+    render_process_host_mojo_.reset(new RenderProcessHostMojoImpl(this));
+  render_process_host_mojo_->SetWebUIHandle(view_routing_id, handle.Pass());
 }
 #endif
 
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index 1fc85d2..ac07b62 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -23,6 +23,10 @@
 #include "ipc/ipc_platform_file.h"
 #include "ui/surface/transport_dib.h"
 
+#if defined(USE_MOJO)
+#include "mojo/public/cpp/system/core.h"
+#endif
+
 struct ViewHostMsg_CompositorSurfaceBuffersSwapped_Params;
 
 namespace base {
@@ -51,7 +55,7 @@
 class StoragePartitionImpl;
 
 #if defined(USE_MOJO)
-class MojoChannelInit;
+class RenderProcessHostMojoImpl;
 #endif
 
 // Implements a concrete RenderProcessHost for the browser process for talking
@@ -237,6 +241,11 @@
   void IncrementWorkerRefCount();
   void DecrementWorkerRefCount();
 
+#if defined(USE_MOJO)
+  void SetWebUIHandle(int32 view_routing_id,
+                      mojo::ScopedMessagePipeHandle handle);
+#endif
+
  protected:
   // A proxy for our IPC::Channel that lives on the IO thread (see
   // browser_process.h)
@@ -300,11 +309,6 @@
   void SendDisableAecDumpToRenderer();
 #endif
 
-#if defined(USE_MOJO)
-  // Establishes the mojo channel to the renderer.
-  void CreateMojoChannel();
-#endif
-
   // The registered IPC listener objects. When this list is empty, we should
   // delete ourselves.
   IDMap<IPC::Listener> listeners_;
@@ -431,8 +435,11 @@
 
   int worker_ref_count_;
 
+  // Records the time when the process starts surviving for workers for UMA.
+  base::TimeTicks survive_for_worker_start_time_;
+
 #if defined(USE_MOJO)
-  scoped_ptr<MojoChannelInit> mojo_channel_init_;
+  scoped_ptr<RenderProcessHostMojoImpl> render_process_host_mojo_;
 #endif
 
   base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_;
diff --git a/content/browser/renderer_host/render_process_host_mojo_impl.cc b/content/browser/renderer_host/render_process_host_mojo_impl.cc
new file mode 100644
index 0000000..16348a6
--- /dev/null
+++ b/content/browser/renderer_host/render_process_host_mojo_impl.cc
@@ -0,0 +1,93 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_process_host_mojo_impl.h"
+
+#include "base/platform_file.h"
+#include "content/common/mojo/mojo_channel_init.h"
+#include "content/common/mojo/mojo_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "mojo/embedder/platform_channel_pair.h"
+
+namespace content {
+
+namespace {
+
+base::PlatformFile PlatformFileFromScopedPlatformHandle(
+    mojo::embedder::ScopedPlatformHandle handle) {
+#if defined(OS_POSIX)
+  return handle.release().fd;
+#elif defined(OS_WIN)
+  return handle.release().handle;
+#endif
+}
+
+}  // namespace
+
+struct RenderProcessHostMojoImpl::PendingHandle {
+  PendingHandle() : view_routing_id(0) {}
+
+  int32 view_routing_id;
+  mojo::ScopedMessagePipeHandle handle;
+};
+
+RenderProcessHostMojoImpl::RenderProcessHostMojoImpl(RenderProcessHost* host)
+    : host_(host) {
+}
+
+RenderProcessHostMojoImpl::~RenderProcessHostMojoImpl() {
+}
+
+void RenderProcessHostMojoImpl::SetWebUIHandle(
+    int32 view_routing_id,
+    mojo::ScopedMessagePipeHandle handle) {
+  base::ProcessHandle process = host_->GetHandle();
+  if (process != base::kNullProcessHandle) {
+    CreateMojoChannel(process);  // Does nothing if already connected.
+    if (!render_process_mojo_.is_null()) {
+      render_process_mojo_->SetWebUIHandle(view_routing_id, handle.Pass());
+      return;
+    }
+  }
+
+  // Remember the request, we'll attempt to reconnect once the child process is
+  // launched.
+  pending_handle_.reset(new PendingHandle);
+  pending_handle_->view_routing_id = view_routing_id;
+  pending_handle_->handle = handle.Pass();
+}
+
+void RenderProcessHostMojoImpl::OnProcessLaunched() {
+  if (pending_handle_) {
+    scoped_ptr<PendingHandle> handle(pending_handle_.Pass());
+    SetWebUIHandle(handle->view_routing_id, handle->handle.Pass());
+  }
+}
+
+
+void RenderProcessHostMojoImpl::CreateMojoChannel(
+    base::ProcessHandle process_handle) {
+  if (mojo_channel_init_.get())
+    return;
+
+  mojo::embedder::PlatformChannelPair channel_pair;
+  mojo_channel_init_.reset(new MojoChannelInit);
+  mojo_channel_init_->Init(
+      PlatformFileFromScopedPlatformHandle(channel_pair.PassServerHandle()),
+      BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO));
+  if (!mojo_channel_init_->is_handle_valid())
+    return;
+  base::PlatformFile client_file =
+      PlatformFileFromScopedPlatformHandle(channel_pair.PassClientHandle());
+  host_->Send(new MojoMsg_ChannelCreated(
+                  IPC::GetFileHandleForProcess(client_file, process_handle,
+                                               true)));
+  ScopedRenderProcessMojoHandle render_process_handle(
+      RenderProcessMojoHandle(
+          mojo_channel_init_->bootstrap_message_pipe().release().value()));
+  render_process_mojo_.reset(render_process_handle.Pass(), this);
+}
+
+}  // namespace content
diff --git a/content/browser/renderer_host/render_process_host_mojo_impl.h b/content/browser/renderer_host/render_process_host_mojo_impl.h
new file mode 100644
index 0000000..36d7404
--- /dev/null
+++ b/content/browser/renderer_host/render_process_host_mojo_impl.h
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_MOJO_IMPL_H_
+#define CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_MOJO_IMPL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/process/process_handle.h"
+#include "content/common/mojo/render_process.mojom.h"
+#include "mojo/public/bindings/remote_ptr.h"
+
+namespace content {
+
+class MojoChannelInit;
+class RenderProcessHost;
+
+// RenderProcessHostMojoImpl is responsible for initiating and maintaining the
+// connection with the content side of RenderProcessHostMojo.
+class RenderProcessHostMojoImpl : public RenderProcessHostMojo {
+ public:
+  explicit RenderProcessHostMojoImpl(RenderProcessHost* host);
+  virtual ~RenderProcessHostMojoImpl();
+
+  void SetWebUIHandle(int32 view_routing_id,
+                      mojo::ScopedMessagePipeHandle handle);
+
+  // Invoked when the RenderPorcessHost has established a channel.
+  void OnProcessLaunched();
+
+private:
+  struct PendingHandle;
+
+  // Establishes the mojo channel to the renderer.
+  void CreateMojoChannel(base::ProcessHandle process_handle);
+
+  RenderProcessHost* host_;
+
+  // Used to establish the connection.
+  scoped_ptr<MojoChannelInit> mojo_channel_init_;
+
+  mojo::RemotePtr<content::RenderProcessMojo> render_process_mojo_;
+
+  // If non-null we're waiting to send a WebUI handle to the renderer when
+  // connected.
+  scoped_ptr<PendingHandle> pending_handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderProcessHostMojoImpl);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_RENDERER_HOST_BROWSER_RENDER_PROCESS_HOST_MOJO_IMPL_H_
diff --git a/content/browser/renderer_host/render_sandbox_host_linux.cc b/content/browser/renderer_host/render_sandbox_host_linux.cc
index 0a3d4b6..8b86435 100644
--- a/content/browser/renderer_host/render_sandbox_host_linux.cc
+++ b/content/browser/renderer_host/render_sandbox_host_linux.cc
@@ -28,7 +28,7 @@
 #include "base/process/process_metrics.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#include "content/child/webkitplatformsupport_impl.h"
+#include "content/child/blink_platform_impl.h"
 #include "content/common/font_config_ipc_linux.h"
 #include "content/common/sandbox_linux/sandbox_linux.h"
 #include "content/common/set_process_title.h"
@@ -407,24 +407,27 @@
     }
 
     FcLangSet* langset = FcLangSetCreate();
-    MSCharSetToFontconfig(langset, charset);
+    bool is_lgc = MSCharSetToFontconfig(langset, charset);
 
     FcPattern* pattern = FcPatternCreate();
-    // TODO(agl): FC_FAMILy needs to change
     FcPatternAddString(pattern, FC_FAMILY,
                        reinterpret_cast<const FcChar8*>(face.c_str()));
 
+    // TODO(thestig) Check if we can access Chrome's per-script font preference
+    // here and select better default fonts for non-LGC case.
     std::string generic_font_name;
-    switch (fallback_family) {
-      case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF:
-        generic_font_name = "Times New Roman";
-        break;
-      case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF:
-        generic_font_name = "Arial";
-        break;
-      case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE:
-        generic_font_name = "Courier New";
-        break;
+    if (is_lgc) {
+      switch (fallback_family) {
+        case PP_BROWSERFONT_TRUSTED_FAMILY_SERIF:
+          generic_font_name = "Times New Roman";
+          break;
+        case PP_BROWSERFONT_TRUSTED_FAMILY_SANSSERIF:
+          generic_font_name = "Arial";
+          break;
+        case PP_BROWSERFONT_TRUSTED_FAMILY_MONOSPACE:
+          generic_font_name = "Courier New";
+          break;
+      }
     }
     if (!generic_font_name.empty()) {
       const FcChar8* fc_generic_font_name =
@@ -547,7 +550,8 @@
 
   // MSCharSetToFontconfig translates a Microsoft charset identifier to a
   // fontconfig language set by appending to |langset|.
-  static void MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) {
+  // Returns true if |langset| is Latin/Greek/Cyrillic.
+  static bool MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) {
     // We have need to translate raw fdwCharSet values into terms that
     // fontconfig can understand. (See the description of fdwCharSet in the MSDN
     // documentation for CreateFont:
@@ -566,6 +570,7 @@
     // So, for each of the documented fdwCharSet values I've had to take a
     // guess at the set of ISO 639-1 languages intended.
 
+    bool is_lgc = false;
     switch (fdwCharSet) {
       case NPCharsetAnsi:
       // These values I don't really know what to do with, so I'm going to map
@@ -574,23 +579,25 @@
       case NPCharsetMac:
       case NPCharsetOEM:
       case NPCharsetSymbol:
+        is_lgc = true;
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("en"));
         break;
       case NPCharsetBaltic:
         // The three baltic languages.
+        is_lgc = true;
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("et"));
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lv"));
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lt"));
         break;
-      // TODO(jungshik): Would we be better off mapping Big5 to zh-tw
-      // and GB2312 to zh-cn? Fontconfig has 4 separate orthography
-      // files (zh-{cn,tw,hk,mo}.
       case NPCharsetChineseBIG5:
+        FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-tw"));
+        break;
       case NPCharsetGB2312:
-        FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh"));
+        FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-cn"));
         break;
       case NPCharsetEastEurope:
         // A scattering of eastern European languages.
+        is_lgc = true;
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("pl"));
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("cs"));
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("sk"));
@@ -598,6 +605,7 @@
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hr"));
         break;
       case NPCharsetGreek:
+        is_lgc = true;
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("el"));
         break;
       case NPCharsetHangul:
@@ -606,6 +614,7 @@
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ko"));
         break;
       case NPCharsetRussian:
+        is_lgc = true;
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ru"));
         break;
       case NPCharsetShiftJIS:
@@ -613,9 +622,11 @@
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ja"));
         break;
       case NPCharsetTurkish:
+        is_lgc = true;
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("tr"));
         break;
       case NPCharsetVietnamese:
+        is_lgc = true;
         FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("vi"));
         break;
       case NPCharsetArabic:
@@ -631,6 +642,7 @@
       // Don't add any languages in that case that we don't recognise the
       // constant.
     }
+    return is_lgc;
   }
 
   void SendRendererReply(const std::vector<int>& fds, const Pickle& reply,
@@ -672,7 +684,7 @@
   const int lifeline_fd_;
   const int browser_socket_;
   std::vector<std::string> sandbox_cmd_;
-  scoped_ptr<WebKitPlatformSupportImpl> webkit_platform_support_;
+  scoped_ptr<BlinkPlatformImpl> webkit_platform_support_;
   SkTDArray<SkString*> paths_;
 };
 
@@ -685,7 +697,7 @@
 void SandboxIPCProcess::EnsureWebKitInitialized() {
   if (webkit_platform_support_)
     return;
-  webkit_platform_support_.reset(new WebKitPlatformSupportImpl);
+  webkit_platform_support_.reset(new BlinkPlatformImpl);
   blink::initializeWithoutV8(webkit_platform_support_.get());
 }
 
diff --git a/content/browser/renderer_host/render_view_host_browsertest.cc b/content/browser/renderer_host/render_view_host_browsertest.cc
index 3d2253b..b26d355 100644
--- a/content/browser/renderer_host/render_view_host_browsertest.cc
+++ b/content/browser/renderer_host/render_view_host_browsertest.cc
@@ -15,9 +15,9 @@
 #include "content/public/common/content_paths.h"
 #include "content/public/common/frame_navigate_params.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/net_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index 42419b7..618ab6f 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -133,9 +133,6 @@
   // The page is trying to close the RenderView's representation in the client.
   virtual void Close(RenderViewHost* render_view_host) {}
 
-  // The RenderViewHost has been swapped out.
-  virtual void SwappedOut(RenderViewHost* render_view_host) {}
-
   // The page is trying to move the RenderView's representation in the client.
   virtual void RequestMove(const gfx::Rect& new_bounds) {}
 
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index d7b5686..cad9788 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -368,10 +368,8 @@
       !command_line.HasSwitch(switches::kDisableLocalStorage);
   prefs.databases_enabled =
       !command_line.HasSwitch(switches::kDisableDatabases);
-#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
-  prefs.webaudio_enabled =
-      command_line.HasSwitch(switches::kEnableWebAudio);
-#else
+#if defined(OS_ANDROID)
+  // WebAudio is enabled by default on x86 and ARM.
   prefs.webaudio_enabled =
       !command_line.HasSwitch(switches::kDisableWebAudio);
 #endif
@@ -414,9 +412,7 @@
   prefs.accelerated_compositing_enabled =
       GpuProcessHost::gpu_enabled() &&
       !command_line.HasSwitch(switches::kDisableAcceleratedCompositing);
-  prefs.force_compositing_mode =
-      content::IsForceCompositingModeEnabled() &&
-      !command_line.HasSwitch(switches::kDisableForceCompositingMode);
+  prefs.force_compositing_mode = content::IsForceCompositingModeEnabled();
   prefs.accelerated_2d_canvas_enabled =
       GpuProcessHost::gpu_enabled() &&
       !command_line.HasSwitch(switches::kDisableAccelerated2dCanvas);
@@ -450,8 +446,6 @@
 #if defined(OS_ANDROID)
   prefs.user_gesture_required_for_media_playback = !command_line.HasSwitch(
       switches::kDisableGestureRequirementForMediaPlayback);
-  prefs.user_gesture_required_for_media_fullscreen = !command_line.HasSwitch(
-      switches::kDisableGestureRequirementForMediaFullscreen);
 #endif
 
   prefs.touch_enabled = ui::AreTouchEventsEnabled();
@@ -576,21 +570,6 @@
   Send(new ViewMsg_SuppressDialogsUntilSwapOut(GetRoutingID()));
 }
 
-void RenderViewHostImpl::SwapOut() {
-  SetState(STATE_WAITING_FOR_UNLOAD_ACK);
-  unload_event_monitor_timeout_->Start(
-      base::TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
-
-  if (IsRenderViewLive()) {
-    Send(new ViewMsg_SwapOut(GetRoutingID()));
-  }
-  delegate_->SwappedOut(this);
-}
-
-void RenderViewHostImpl::OnSwapOutACK() {
-  OnSwappedOut(false);
-}
-
 void RenderViewHostImpl::OnSwappedOut(bool timed_out) {
   // Ignore spurious swap out ack.
   if (!IsWaitingForUnloadACK())
@@ -735,6 +714,26 @@
 }
 #endif
 
+#if defined(USE_MOJO)
+void RenderViewHostImpl::SetWebUIHandle(mojo::ScopedMessagePipeHandle handle) {
+  // Never grant any bindings to browser plugin guests.
+  if (GetProcess()->IsGuest()) {
+    NOTREACHED() << "Never grant bindings to a guest process.";
+    return;
+  }
+
+  if ((enabled_bindings_ & BINDINGS_POLICY_WEB_UI) == 0) {
+    NOTREACHED() << "You must grant bindings before setting the handle";
+    return;
+  }
+
+  DCHECK(renderer_initialized_);
+  RenderProcessHostImpl* process =
+      static_cast<RenderProcessHostImpl*>(GetProcess());
+  process->SetWebUIHandle(GetRoutingID(), handle.Pass());
+}
+#endif
+
 void RenderViewHostImpl::DragTargetDragEnter(
     const DropData& drop_data,
     const gfx::Point& client_pt,
@@ -749,32 +748,34 @@
   // and can't be interpreted as a capability.
   DropData filtered_data(drop_data);
   GetProcess()->FilterURL(true, &filtered_data.url);
+  if (drop_data.did_originate_from_renderer) {
+    filtered_data.filenames.clear();
+  }
 
   // The filenames vector, on the other hand, does represent a capability to
   // access the given files.
   fileapi::IsolatedContext::FileInfoSet files;
-  for (std::vector<DropData::FileInfo>::iterator iter(
+  for (std::vector<ui::FileInfo>::iterator iter(
            filtered_data.filenames.begin());
-       iter != filtered_data.filenames.end(); ++iter) {
+       iter != filtered_data.filenames.end();
+       ++iter) {
     // A dragged file may wind up as the value of an input element, or it
     // may be used as the target of a navigation instead.  We don't know
     // which will happen at this point, so generously grant both access
     // and request permissions to the specific file to cover both cases.
     // We do not give it the permission to request all file:// URLs.
-    base::FilePath path =
-        base::FilePath::FromUTF8Unsafe(base::UTF16ToUTF8(iter->path));
 
     // Make sure we have the same display_name as the one we register.
     if (iter->display_name.empty()) {
       std::string name;
-      files.AddPath(path, &name);
-      iter->display_name = base::UTF8ToUTF16(name);
+      files.AddPath(iter->path, &name);
+      iter->display_name = base::FilePath::FromUTF8Unsafe(name);
     } else {
-      files.AddPathWithName(path, base::UTF16ToUTF8(iter->display_name));
+      files.AddPathWithName(iter->path, iter->display_name.AsUTF8Unsafe());
     }
 
     policy->GrantRequestSpecificFileURL(renderer_id,
-                                        net::FilePathToFileURL(path));
+                                        net::FilePathToFileURL(iter->path));
 
     // If the renderer already has permission to read these paths, we don't need
     // to re-grant them. This prevents problems with DnD for files in the CrOS
@@ -782,8 +783,8 @@
     // directories, but dragging a file would cause the read/write access to be
     // overwritten with read-only access, making them impossible to delete or
     // rename until the renderer was killed.
-    if (!policy->CanReadFile(renderer_id, path))
-      policy->GrantReadFile(renderer_id, path);
+    if (!policy->CanReadFile(renderer_id, iter->path))
+      policy->GrantReadFile(renderer_id, iter->path);
   }
 
   fileapi::IsolatedContext* isolated_context =
@@ -1121,10 +1122,6 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_FocusedNodeChanged, OnFocusedNodeChanged)
     IPC_MESSAGE_HANDLER(ViewHostMsg_AddMessageToConsole, OnAddMessageToConsole)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ClosePage_ACK, OnClosePageACK)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SwapOut_ACK, OnSwapOutACK)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
-                        OnSelectionBoundsChanged)
 #if defined(OS_ANDROID)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionRootBoundsChanged,
                         OnSelectionRootBoundsChanged)
@@ -1139,6 +1136,7 @@
                         OnCancelDesktopNotification)
 #if defined(OS_MACOSX) || defined(OS_ANDROID)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowPopup, OnShowPopup)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_HidePopup, OnHidePopup)
 #endif
     IPC_MESSAGE_HANDLER(ViewHostMsg_RunFileChooser, OnRunFileChooser)
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidAccessInitialDocument,
@@ -1355,7 +1353,7 @@
 }
 
 void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   delegate_->ToggleFullscreenMode(enter_fullscreen);
   // We need to notify the contents that its fullscreen state has changed. This
   // is done as part of the resize message.
@@ -1391,20 +1389,6 @@
 void RenderViewHostImpl::OnDidChangeNumWheelEvents(int count) {
 }
 
-void RenderViewHostImpl::OnSelectionChanged(const base::string16& text,
-                                            size_t offset,
-                                            const gfx::Range& range) {
-  if (view_)
-    view_->SelectionChanged(text, offset, range);
-}
-
-void RenderViewHostImpl::OnSelectionBoundsChanged(
-    const ViewHostMsg_SelectionBounds_Params& params) {
-  if (view_) {
-    view_->SelectionBoundsChanged(params);
-  }
-}
-
 #if defined(OS_ANDROID)
 void RenderViewHostImpl::OnSelectionRootBoundsChanged(
     const gfx::Rect& bounds) {
@@ -1479,12 +1463,11 @@
   //    still fire though, which causes read permissions to be granted to the
   //    renderer for any file paths in the drop.
   filtered_data.filenames.clear();
-  for (std::vector<DropData::FileInfo>::const_iterator it =
+  for (std::vector<ui::FileInfo>::const_iterator it =
            drop_data.filenames.begin();
-       it != drop_data.filenames.end(); ++it) {
-    base::FilePath path(
-        base::FilePath::FromUTF8Unsafe(base::UTF16ToUTF8(it->path)));
-    if (policy->CanReadFile(GetProcess()->GetID(), path))
+       it != drop_data.filenames.end();
+       ++it) {
+    if (policy->CanReadFile(GetProcess()->GetID(), it->path))
       filtered_data.filenames.push_back(*it);
   }
   float scale = ui::GetImageScale(GetScaleFactorForView(GetView()));
@@ -1754,16 +1737,16 @@
 
 void RenderViewHostImpl::OnAccessibilityEvents(
     const std::vector<AccessibilityHostMsg_EventParams>& params) {
-  if ((accessibility_mode() & AccessibilityModeFlagPlatform) && view_ &&
+  if ((accessibility_mode() != AccessibilityModeOff) && view_ &&
       IsRVHStateActive(rvh_state_)) {
-    view_->CreateBrowserAccessibilityManagerIfNeeded();
-    BrowserAccessibilityManager* manager =
-        view_->GetBrowserAccessibilityManager();
-    if (manager)
-      manager->OnAccessibilityEvents(params);
+    if (accessibility_mode() & AccessibilityModeFlagPlatform) {
+      view_->CreateBrowserAccessibilityManagerIfNeeded();
+      BrowserAccessibilityManager* manager =
+          view_->GetBrowserAccessibilityManager();
+      if (manager)
+        manager->OnAccessibilityEvents(params);
+    }
 
-    // TODO(aboxhall, dtseng): Only send notification when accessibility mode
-    // extension enabled.
     std::vector<AXEventNotificationDetails> details;
     for (unsigned int i = 0; i < params.size(); ++i) {
       const AccessibilityHostMsg_EventParams& param = params[i];
@@ -1800,11 +1783,14 @@
 void RenderViewHostImpl::OnAccessibilityLocationChanges(
     const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
   if (view_ && IsRVHStateActive(rvh_state_)) {
-    view_->CreateBrowserAccessibilityManagerIfNeeded();
-    BrowserAccessibilityManager* manager =
-        view_->GetBrowserAccessibilityManager();
-    if (manager)
-      manager->OnLocationChanges(params);
+    if (accessibility_mode() & AccessibilityModeFlagPlatform) {
+      view_->CreateBrowserAccessibilityManagerIfNeeded();
+      BrowserAccessibilityManager* manager =
+          view_->GetBrowserAccessibilityManager();
+      if (manager)
+        manager->OnLocationChanges(params);
+    }
+    // TODO(aboxhall): send location change events to web contents observers too
   }
 }
 
@@ -1893,6 +1879,12 @@
                         params.allow_multiple_selection);
   }
 }
+
+void RenderViewHostImpl::OnHidePopup() {
+  RenderViewHostDelegateView* view = delegate_->GetDelegateView();
+  if (view)
+    view->HidePopupMenu();
+}
 #endif
 
 void RenderViewHostImpl::SetState(RenderViewHostImplState rvh_state) {
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 8aef8e5..9dbd360 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -36,7 +36,6 @@
 struct AccessibilityHostMsg_LocationChangeParams;
 struct MediaPlayerAction;
 struct ViewHostMsg_CreateWindow_Params;
-struct ViewHostMsg_SelectionBounds_Params;
 struct ViewHostMsg_ShowPopup_Params;
 struct FrameMsg_Navigate_Params;
 struct ViewMsg_PostMessage_Params;
@@ -240,6 +239,10 @@
   virtual void DisableFullscreenEncryptedMediaPlayback() OVERRIDE;
 #endif
 
+#if defined(USE_MOJO)
+  virtual void SetWebUIHandle(mojo::ScopedMessagePipeHandle handle) OVERRIDE;
+#endif
+
   void set_delegate(RenderViewHostDelegate* d) {
     CHECK(d);  // http://crbug.com/82827
     delegate_ = d;
@@ -322,14 +325,6 @@
   // longer on the stack when we attempt to swap it out.
   void SuppressDialogsUntilSwapOut();
 
-  // Tells the renderer that this RenderView is being swapped out for one in a
-  // different renderer process.  It should run its unload handler and move to
-  // a blank document.  The renderer should preserve the Frame object until it
-  // exits, in case we come back.  The renderer can exit if it has no other
-  // active RenderViews, but not until WasSwappedOut is called (when it is no
-  // longer visible).
-  void SwapOut();
-
   // Called when either the SwapOut request has been acknowledged or has timed
   // out.
   void OnSwappedOut(bool timed_out);
@@ -543,11 +538,6 @@
   void OnDidChangeScrollOffsetPinningForMainFrame(bool is_pinned_to_left,
                                                   bool is_pinned_to_right);
   void OnDidChangeNumWheelEvents(int count);
-  void OnSelectionChanged(const base::string16& text,
-                          size_t offset,
-                          const gfx::Range& range);
-  void OnSelectionBoundsChanged(
-      const ViewHostMsg_SelectionBounds_Params& params);
 #if defined(OS_ANDROID)
   void OnSelectionRootBoundsChanged(const gfx::Rect& bounds);
 #endif
@@ -579,7 +569,6 @@
   void OnUpdateInspectorSetting(const std::string& key,
                                 const std::string& value);
   void OnClosePageACK();
-  void OnSwapOutACK();
   void OnAccessibilityEvents(
       const std::vector<AccessibilityHostMsg_EventParams>& params);
   void OnAccessibilityLocationChanges(
@@ -597,6 +586,7 @@
 
 #if defined(OS_MACOSX) || defined(OS_ANDROID)
   void OnShowPopup(const ViewHostMsg_ShowPopup_Params& params);
+  void OnHidePopup();
 #endif
 
  private:
diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc
index f951750..40a1fb6 100644
--- a/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/content/browser/renderer_host/render_view_host_unittest.cc
@@ -116,13 +116,6 @@
     : public RenderViewHostDelegateView {
  public:
   virtual ~MockDraggingRenderViewHostDelegateView() {}
-  virtual void ShowPopupMenu(const gfx::Rect& bounds,
-                             int item_height,
-                             double item_font_size,
-                             int selected_item,
-                             const std::vector<MenuItem>& items,
-                             bool right_aligned,
-                             bool allow_multiple_selection) OVERRIDE {}
   virtual void StartDragging(const DropData& drop_data,
                              blink::WebDragOperationsMask allowed_ops,
                              const gfx::ImageSkia& image,
@@ -197,8 +190,8 @@
   GURL dragged_file_url = net::FilePathToFileURL(dragged_file_path);
   GURL sensitive_file_url = net::FilePathToFileURL(sensitive_file_path);
   dropped_data.url = highlighted_file_url;
-  dropped_data.filenames.push_back(DropData::FileInfo(
-      base::UTF8ToUTF16(dragged_file_path.AsUTF8Unsafe()), base::string16()));
+  dropped_data.filenames.push_back(
+      ui::FileInfo(dragged_file_path, base::FilePath()));
 
   rvh()->DragTargetDragEnter(dropped_data, client_point, screen_point,
                               blink::WebDragOperationNone, 0);
diff --git a/content/browser/renderer_host/render_widget_helper.cc b/content/browser/renderer_host/render_widget_helper.cc
index 10e4e0f..ae12858 100644
--- a/content/browser/renderer_host/render_widget_helper.cc
+++ b/content/browser/renderer_host/render_widget_helper.cc
@@ -26,7 +26,7 @@
 
 void AddWidgetHelper(int render_process_id,
                      const scoped_refptr<RenderWidgetHelper>& widget_helper) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // We don't care if RenderWidgetHelpers overwrite an existing process_id. Just
   // want this to be up to date.
   g_widget_helpers.Get()[render_process_id] = widget_helper.get();
@@ -85,7 +85,7 @@
 }
 
 RenderWidgetHelper::~RenderWidgetHelper() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   // Delete this RWH from the map if it is found.
   WidgetHelperMap& widget_map = g_widget_helpers.Get();
@@ -121,7 +121,7 @@
 // static
 RenderWidgetHelper* RenderWidgetHelper::FromProcessHostID(
     int render_process_host_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   WidgetHelperMap::const_iterator ci = g_widget_helpers.Get().find(
       render_process_host_id);
   return (ci == g_widget_helpers.Get().end())? NULL : ci->second;
diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc
index 32715e8..47e5981 100644
--- a/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -7,9 +7,9 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_paths.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc
index a3b66e2..23687d0 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -22,6 +22,11 @@
   return false;
 }
 
+bool RenderWidgetHostDelegate::HandleGestureEvent(
+    const blink::WebGestureEvent& event) {
+  return false;
+}
+
 #if defined(OS_WIN)
 gfx::NativeViewAccessible
 RenderWidgetHostDelegate::GetParentNativeViewAccessible() {
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h
index e31975c..983f282 100644
--- a/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -52,6 +52,10 @@
   // Returns true if the |event| was handled.
   virtual bool PreHandleGestureEvent(const blink::WebGestureEvent& event);
 
+  // Callback to inform the browser that the renderer did not process the
+  // specified gesture event.  Returns true if the |event| was handled.
+  virtual bool HandleGestureEvent(const blink::WebGestureEvent& event);
+
   // Notifies that screen rects were sent to renderer process.
   virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) {}
 
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index b10e5bd..b08dff8 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -285,7 +285,7 @@
 RenderWidgetHostImpl* RenderWidgetHostImpl::FromID(
     int32 process_id,
     int32 routing_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   RoutingIDWidgetMap* widgets = g_routing_id_widget_map.Pointer();
   RoutingIDWidgetMap::iterator it = widgets->find(
       RenderWidgetHostID(process_id, routing_id));
@@ -474,10 +474,6 @@
                         OnUpdateScreenRectsAck)
     IPC_MESSAGE_HANDLER(ViewHostMsg_RequestMove, OnRequestMove)
     IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnSetTooltipText)
-#if defined(OS_MACOSX)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
-                        OnCompositorSurfaceBuffersSwapped)
-#endif
     IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_SwapCompositorFrame,
                                 msg_is_ok = OnSwapCompositorFrame(msg))
     IPC_MESSAGE_HANDLER(ViewHostMsg_DidOverscroll, OnOverscrolled)
@@ -497,13 +493,20 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_UnlockMouse, OnUnlockMouse)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ShowDisambiguationPopup,
                         OnShowDisambiguationPopup)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
+                        OnSelectionBoundsChanged)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot, OnSnapshot)
 #if defined(OS_WIN)
     IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
                         OnWindowlessPluginDummyWindowCreated)
     IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
                         OnWindowlessPluginDummyWindowDestroyed)
 #endif
-    IPC_MESSAGE_HANDLER(ViewHostMsg_Snapshot, OnSnapshot)
+#if defined(OS_MACOSX)
+    IPC_MESSAGE_HANDLER(ViewHostMsg_CompositorSurfaceBuffersSwapped,
+                        OnCompositorSurfaceBuffersSwapped)
+#endif
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
     IPC_MESSAGE_HANDLER(ViewHostMsg_ImeCompositionRangeChanged,
                         OnImeCompositionRangeChanged)
@@ -798,7 +801,7 @@
     return;
 
   // Waiting for a backing store will do the wait for us.
-  (void)GetBackingStore(true);
+  ignore_result(GetBackingStore(true));
 }
 
 bool RenderWidgetHostImpl::TryGetBackingStore(const gfx::Size& desired_size,
@@ -955,6 +958,18 @@
   AddAccessibilityMode(AccessibilityModeComplete);
 }
 
+bool RenderWidgetHostImpl::IsFullAccessibilityModeForTesting() {
+  return accessibility_mode() == AccessibilityModeComplete;
+}
+
+void RenderWidgetHostImpl::EnableTreeOnlyAccessibilityMode() {
+  AddAccessibilityMode(AccessibilityModeTreeOnly);
+}
+
+bool RenderWidgetHostImpl::IsTreeOnlyAccessibilityModeForTesting() {
+  return accessibility_mode() == AccessibilityModeTreeOnly;
+}
+
 void RenderWidgetHostImpl::ForwardMouseEvent(const WebMouseEvent& mouse_event) {
   ForwardMouseEventWithLatencyInfo(mouse_event, ui::LatencyInfo());
 }
@@ -1251,6 +1266,20 @@
   Send(new ViewMsg_Snapshot(GetRoutingID(), copy_rect_in_pixel));
 }
 
+void RenderWidgetHostImpl::OnSelectionChanged(const base::string16& text,
+                                              size_t offset,
+                                              const gfx::Range& range) {
+  if (view_)
+    view_->SelectionChanged(text, offset, range);
+}
+
+void RenderWidgetHostImpl::OnSelectionBoundsChanged(
+    const ViewHostMsg_SelectionBounds_Params& params) {
+  if (view_) {
+    view_->SelectionBoundsChanged(params);
+  }
+}
+
 void RenderWidgetHostImpl::OnSnapshot(bool success,
                                     const SkBitmap& bitmap) {
   if (pending_snapshots_.size() == 0) {
@@ -1372,12 +1401,6 @@
             std::vector<blink::WebCompositionUnderline>(), 0, 0));
 }
 
-void RenderWidgetHostImpl::ExtendSelectionAndDelete(
-    size_t before,
-    size_t after) {
-  Send(new ViewMsg_ExtendSelectionAndDelete(GetRoutingID(), before, after));
-}
-
 gfx::Rect RenderWidgetHostImpl::GetRootWindowResizerRect() const {
   return gfx::Rect();
 }
@@ -1762,6 +1785,14 @@
 
 void RenderWidgetHostImpl::OnQueueSyntheticGesture(
     const SyntheticGesturePacket& gesture_packet) {
+  // Only allow untrustworthy gestures if explicitly enabled.
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(
+          cc::switches::kEnableGpuBenchmarking)) {
+    RecordAction(base::UserMetricsAction("BadMessageTerminate_RWH7"));
+    GetProcess()->ReceivedBadMessage();
+    return;
+  }
+
   QueueSyntheticGesture(
         SyntheticGesture::Create(*gesture_packet.gesture_params()),
         base::Bind(&RenderWidgetHostImpl::OnSyntheticGestureCompleted,
@@ -2103,6 +2134,11 @@
         ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0 ,0);
   }
 
+  if (ack_result != INPUT_EVENT_ACK_STATE_CONSUMED) {
+    if (delegate_->HandleGestureEvent(event.event))
+      ack_result = INPUT_EVENT_ACK_STATE_CONSUMED;
+  }
+
   if (view_)
     view_->GestureEventAck(event.event, ack_result);
 }
@@ -2240,53 +2276,10 @@
   Send(new InputMsg_ScrollFocusedEditableNodeIntoRect(GetRoutingID(), rect));
 }
 
-void RenderWidgetHostImpl::SelectRange(const gfx::Point& start,
-                                       const gfx::Point& end) {
-  Send(new InputMsg_SelectRange(GetRoutingID(), start, end));
-}
-
 void RenderWidgetHostImpl::MoveCaret(const gfx::Point& point) {
   Send(new InputMsg_MoveCaret(GetRoutingID(), point));
 }
 
-void RenderWidgetHostImpl::Undo() {
-  Send(new InputMsg_Undo(GetRoutingID()));
-  RecordAction(base::UserMetricsAction("Undo"));
-}
-
-void RenderWidgetHostImpl::Redo() {
-  Send(new InputMsg_Redo(GetRoutingID()));
-  RecordAction(base::UserMetricsAction("Redo"));
-}
-
-void RenderWidgetHostImpl::CopyToFindPboard() {
-#if defined(OS_MACOSX)
-  // Windows/Linux don't have the concept of a find pasteboard.
-  Send(new InputMsg_CopyToFindPboard(GetRoutingID()));
-  RecordAction(base::UserMetricsAction("CopyToFindPboard"));
-#endif
-}
-
-void RenderWidgetHostImpl::PasteAndMatchStyle() {
-  Send(new InputMsg_PasteAndMatchStyle(GetRoutingID()));
-  RecordAction(base::UserMetricsAction("PasteAndMatchStyle"));
-}
-
-void RenderWidgetHostImpl::Delete() {
-  Send(new InputMsg_Delete(GetRoutingID()));
-  RecordAction(base::UserMetricsAction("DeleteSelection"));
-}
-
-void RenderWidgetHostImpl::SelectAll() {
-  Send(new InputMsg_SelectAll(GetRoutingID()));
-  RecordAction(base::UserMetricsAction("SelectAll"));
-}
-
-void RenderWidgetHostImpl::Unselect() {
-  Send(new InputMsg_Unselect(GetRoutingID()));
-  RecordAction(base::UserMetricsAction("Unselect"));
-}
-
 bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
   if (!allowed) {
     RejectMouseLockOrUnlockIfNecessary();
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 1e4d2a8..a20a5ff 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -39,10 +39,11 @@
 #include "ui/gfx/native_widget_types.h"
 
 struct AcceleratedSurfaceMsg_BufferPresented_Params;
-struct ViewHostMsg_CompositorSurfaceBuffersSwapped_Params;
-struct ViewHostMsg_UpdateRect_Params;
-struct ViewHostMsg_TextInputState_Params;
 struct ViewHostMsg_BeginSmoothScroll_Params;
+struct ViewHostMsg_CompositorSurfaceBuffersSwapped_Params;
+struct ViewHostMsg_SelectionBounds_Params;
+struct ViewHostMsg_TextInputState_Params;
+struct ViewHostMsg_UpdateRect_Params;
 
 namespace base {
 class TimeTicks;
@@ -121,13 +122,6 @@
   }
 
   // RenderWidgetHost implementation.
-  virtual void Undo() OVERRIDE;
-  virtual void Redo() OVERRIDE;
-  virtual void CopyToFindPboard() OVERRIDE;
-  virtual void PasteAndMatchStyle() OVERRIDE;
-  virtual void Delete() OVERRIDE;
-  virtual void SelectAll() OVERRIDE;
-  virtual void Unselect() OVERRIDE;
   virtual void UpdateTextDirection(blink::WebTextDirection direction) OVERRIDE;
   virtual void NotifyTextDirection() OVERRIDE;
   virtual void Focus() OVERRIDE;
@@ -152,6 +146,9 @@
                                                CGContextRef target) OVERRIDE;
 #endif
   virtual void EnableFullAccessibilityMode() OVERRIDE;
+  virtual bool IsFullAccessibilityModeForTesting() OVERRIDE;
+  virtual void EnableTreeOnlyAccessibilityMode() OVERRIDE;
+  virtual bool IsTreeOnlyAccessibilityModeForTesting() OVERRIDE;
   virtual void ForwardMouseEvent(
       const blink::WebMouseEvent& mouse_event) OVERRIDE;
   virtual void ForwardWheelEvent(
@@ -366,10 +363,6 @@
   // Cancels an ongoing composition.
   void ImeCancelComposition();
 
-  // Deletes the current selection plus the specified number of characters
-  // before and after the selection or caret.
-  void ExtendSelectionAndDelete(size_t before, size_t after);
-
   // This is for derived classes to give us access to the resizer rect.
   // And to also expose it to the RenderWidgetHostView.
   virtual gfx::Rect GetRootWindowResizerRect() const;
@@ -463,9 +456,6 @@
   // editable divs).
   void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
 
-  // Requests the renderer to select the region between two points.
-  void SelectRange(const gfx::Point& start, const gfx::Point& end);
-
   // Requests the renderer to move the caret selection towards the point.
   void MoveCaret(const gfx::Point& point);
 
@@ -573,6 +563,8 @@
   // component ID where necessary.
   void AddLatencyInfoComponentIds(ui::LatencyInfo* latency_info);
 
+  InputRouter* input_router() { return input_router_.get(); }
+
  protected:
   virtual RenderWidgetHostImpl* AsRenderWidgetHostImpl() OVERRIDE;
 
@@ -716,6 +708,11 @@
   void OnWindowlessPluginDummyWindowDestroyed(
       gfx::NativeViewId dummy_activation_window);
 #endif
+  void OnSelectionChanged(const base::string16& text,
+                          size_t offset,
+                          const gfx::Range& range);
+  void OnSelectionBoundsChanged(
+      const ViewHostMsg_SelectionBounds_Params& params);
   void OnSnapshot(bool success, const SkBitmap& bitmap);
 
   // Called (either immediately or asynchronously) after we're done with our
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 52e88b4..5494470 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -2393,15 +2393,6 @@
     EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \
   }
 
-TEST_InputRouterRoutes_NOARGS(Undo);
-TEST_InputRouterRoutes_NOARGS(Redo);
-#if defined(OS_MACOSX)
-TEST_InputRouterRoutes_NOARGS(CopyToFindPboard);
-#endif
-TEST_InputRouterRoutes_NOARGS(PasteAndMatchStyle);
-TEST_InputRouterRoutes_NOARGS(Delete);
-TEST_InputRouterRoutes_NOARGS(SelectAll);
-TEST_InputRouterRoutes_NOARGS(Unselect);
 TEST_InputRouterRoutes_NOARGS(Focus);
 TEST_InputRouterRoutes_NOARGS(Blur);
 TEST_InputRouterRoutes_NOARGS(LostCapture);
@@ -2415,9 +2406,19 @@
     EXPECT_TRUE(host_->mock_input_router()->send_event_called_); \
   }
 
+TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Undo);
+TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Redo);
 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Cut);
 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Copy);
+#if defined(OS_MACOSX)
+TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_CopyToFindPboard);
+#endif
 TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Paste);
+TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_PasteAndMatchStyle);
+TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Delete);
+TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_SelectAll);
+TEST_InputRouterRoutes_NOARGS_FromRFH(InputMsg_Unselect);
+
 #undef TEST_InputRouterRoutes_NOARGS_FromRFH
 
 TEST_F(RenderWidgetHostTest, InputRouterRoutesReplace) {
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc
index 03e069a..e76c3ed 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.cc
+++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -32,6 +32,7 @@
 #include "content/browser/android/in_process/synchronous_compositor_impl.h"
 #include "content/browser/android/overscroll_glow.h"
 #include "content/browser/devtools/render_view_devtools_agent_host.h"
+#include "content/browser/gpu/compositor_util.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/gpu/gpu_process_host_ui_shim.h"
 #include "content/browser/gpu/gpu_surface_tracker.h"
@@ -152,11 +153,9 @@
                                         widget_host->GetProcess()->GetID(),
                                         widget_host->GetRoutingID()) != NULL),
       frame_evictor_(new DelegatedFrameEvictor(this)),
-      using_delegated_renderer_(CommandLine::ForCurrentProcess()->HasSwitch(
-                                    switches::kEnableDelegatedRenderer) &&
-                                !CommandLine::ForCurrentProcess()->HasSwitch(
-                                    switches::kDisableDelegatedRenderer)),
-      locks_on_frame_count_(0) {
+      using_delegated_renderer_(IsDelegatedRendererEnabled()),
+      locks_on_frame_count_(0),
+      root_window_destroyed_(false) {
   if (!using_delegated_renderer_) {
     texture_layer_ = cc::TextureLayer::Create(NULL);
     layer_ = texture_layer_;
@@ -609,6 +608,9 @@
 
 void RenderWidgetHostViewAndroid::SelectionRootBoundsChanged(
     const gfx::Rect& bounds) {
+  if (content_view_core_) {
+    content_view_core_->OnSelectionRootBoundsChanged(bounds);
+  }
 }
 
 void RenderWidgetHostViewAndroid::ScrollOffsetChanged() {
@@ -1300,12 +1302,6 @@
     host_->ForwardGestureEventWithLatencyInfo(event, CreateLatencyInfo(event));
 }
 
-void RenderWidgetHostViewAndroid::SelectRange(const gfx::Point& start,
-                                              const gfx::Point& end) {
-  if (host_)
-    host_->SelectRange(start, end);
-}
-
 void RenderWidgetHostViewAndroid::MoveCaret(const gfx::Point& point) {
   if (host_)
     host_->MoveCaret(point);
@@ -1339,8 +1335,14 @@
   RunAckCallbacks();
 
   RemoveLayers();
-  if (content_view_core_ && !using_synchronous_compositor_)
+  // TODO: crbug.com/324341
+  // WindowAndroid and Compositor should outlive all WebContents.
+  // Allowing this here at runtime is a bandaid.
+  DCHECK(!root_window_destroyed_);
+  if (content_view_core_ && !root_window_destroyed_ &&
+      !using_synchronous_compositor_) {
     content_view_core_->GetWindowAndroid()->RemoveObserver(this);
+  }
 
   if (content_view_core != content_view_core_)
     ReleaseLocksOnSurface();
@@ -1356,8 +1358,10 @@
   }
 
   AttachLayers();
-  if (content_view_core_ && !using_synchronous_compositor_)
+  if (content_view_core_ && !root_window_destroyed_ &&
+      !using_synchronous_compositor_) {
     content_view_core_->GetWindowAndroid()->AddObserver(this);
+  }
 }
 
 void RenderWidgetHostViewAndroid::RunAckCallbacks() {
@@ -1374,6 +1378,7 @@
 void RenderWidgetHostViewAndroid::OnDetachCompositor() {
   DCHECK(content_view_core_);
   DCHECK(!using_synchronous_compositor_);
+  root_window_destroyed_ = true;
   RunAckCallbacks();
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h
index 89bbeb9..a5aa33c 100644
--- a/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -234,9 +234,6 @@
 
   bool HasValidFrame() const;
 
-  // Select all text between the given coordinates.
-  void SelectRange(const gfx::Point& start, const gfx::Point& end);
-
   void MoveCaret(const gfx::Point& point);
 
   // Returns true when animation ticks are still needed. This avoids a separate
@@ -376,6 +373,7 @@
   bool using_delegated_renderer_;
 
   size_t locks_on_frame_count_;
+  bool root_window_destroyed_;
 
   struct LastFrameInfo {
     LastFrameInfo(uint32 output_id,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 0c1b017..009b912 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -22,6 +22,9 @@
 #include "cc/trees/layer_tree_settings.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/gpu/compositor_util.h"
 #include "content/browser/renderer_host/backing_store_aura.h"
 #include "content/browser/renderer_host/compositor_resize_lock_aura.h"
@@ -29,6 +32,7 @@
 #include "content/browser/renderer_host/input/synthetic_gesture_target_aura.h"
 #include "content/browser/renderer_host/overscroll_controller.h"
 #include "content/browser/renderer_host/render_view_host_delegate.h"
+#include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/ui_events_helper.h"
 #include "content/browser/renderer_host/web_input_event_aura.h"
@@ -47,15 +51,11 @@
 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
 #include "third_party/WebKit/public/web/WebCompositionUnderline.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/cursor_client_observer.h"
 #include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/scoped_tooltip_disabler.h"
 #include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/tooltip_client.h"
-#include "ui/aura/client/transient_window_client.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -78,6 +78,10 @@
 #include "ui/gfx/screen.h"
 #include "ui/gfx/size_conversions.h"
 #include "ui/gfx/skia_util.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/scoped_tooltip_disabler.h"
+#include "ui/wm/public/tooltip_client.h"
+#include "ui/wm/public/transient_window_client.h"
 #include "ui/wm/public/window_types.h"
 
 #if defined(OS_WIN)
@@ -448,7 +452,8 @@
       view_->AddedToRootWindow();
   }
 
-  virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
+  virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
+                                              aura::Window* new_root) OVERRIDE {
     if (window == view_->window_)
       view_->RemovingFromRootWindow();
   }
@@ -494,6 +499,7 @@
   aura::client::SetActivationDelegate(window_, this);
   aura::client::SetActivationChangeObserver(window_, this);
   aura::client::SetFocusChangeObserver(window_, this);
+  window_->set_layer_owner_delegate(this);
   gfx::Screen::GetScreenFor(window_)->AddObserver(this);
   software_frame_manager_.reset(new SoftwareFrameManager(
       weak_ptr_factory_.GetWeakPtr()));
@@ -800,6 +806,18 @@
 #endif
 }
 
+RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
+  if (!host_->IsRenderView())
+    return NULL;
+  RenderViewHost* rvh = RenderViewHost::From(host_);
+  FrameTreeNode* focused_frame =
+      rvh->GetDelegate()->GetFrameTree()->GetFocusedFrame();
+  if (!focused_frame)
+    return NULL;
+
+  return focused_frame->current_frame_host();
+}
+
 void RenderWidgetHostViewAura::MovePluginWindows(
     const gfx::Vector2d& scroll_offset,
     const std::vector<WebPluginGeometry>& plugin_window_moves) {
@@ -1260,6 +1278,9 @@
           window_->GetBoundsInRootWindow());
     }
   }
+
+  if (mouse_locked_)
+    UpdateMouseLockRegion();
 #endif
 }
 
@@ -1400,6 +1421,14 @@
   LPARAM lparam = reinterpret_cast<LPARAM>(&params);
   EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
 }
+
+void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
+  // Clip the cursor if chrome is running on regular desktop.
+  if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
+    RECT window_rect = window_->GetBoundsInScreen().ToRECT();
+    ::ClipCursor(&window_rect);
+  }
+}
 #endif
 
 void RenderWidgetHostViewAura::AcceleratedSurfaceBuffersSwapped(
@@ -2269,6 +2298,8 @@
   mouse_locked_ = true;
 #if !defined(OS_WIN)
   window_->SetCapture();
+#else
+  UpdateMouseLockRegion();
 #endif
   aura::client::CursorClient* cursor_client =
       aura::client::GetCursorClient(root_window);
@@ -2282,8 +2313,6 @@
     window_->MoveCursorTo(gfx::Rect(window_->bounds().size()).CenterPoint());
   }
   tooltip_disabler_.reset(new aura::client::ScopedTooltipDisabler(root_window));
-
-  root_window->GetHost()->ConfineCursorToRootWindow();
   return true;
 }
 
@@ -2298,6 +2327,8 @@
 
 #if !defined(OS_WIN)
   window_->ReleaseCapture();
+#else
+  ::ClipCursor(NULL);
 #endif
   window_->MoveCursorTo(unlocked_mouse_position_);
   aura::client::CursorClient* cursor_client =
@@ -2308,7 +2339,6 @@
   }
 
   host_->LostMouseLock();
-  root_window->GetHost()->UnConfineCursor();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -2532,8 +2562,9 @@
 
 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
     size_t before, size_t after) {
-  if (host_)
-    host_->ExtendSelectionAndDelete(before, after);
+  RenderFrameHostImpl* rfh = GetFocusedFrame();
+  if (rfh)
+    rfh->ExtendSelectionAndDelete(before, after);
 }
 
 void RenderWidgetHostViewAura::EnsureCaretInRect(const gfx::Rect& rect) {
@@ -2708,60 +2739,6 @@
 void RenderWidgetHostViewAura::GetHitTestMask(gfx::Path* mask) const {
 }
 
-void RenderWidgetHostViewAura::DidRecreateLayer(ui::Layer *old_layer,
-                                                ui::Layer *new_layer) {
-  float mailbox_scale_factor;
-  cc::TextureMailbox old_mailbox =
-      old_layer->GetTextureMailbox(&mailbox_scale_factor);
-  scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
-  // The new_layer is the one that will be used by our Window, so that's the one
-  // that should keep our texture. old_layer will be returned to the
-  // RecreateLayer caller, and should have a copy.
-  if (old_texture.get()) {
-    ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
-    GLHelper* gl_helper = factory->GetGLHelper();
-    scoped_refptr<ui::Texture> new_texture;
-    if (host_->is_accelerated_compositing_active() &&
-        gl_helper && current_surface_.get()) {
-      GLuint texture_id =
-          gl_helper->CopyTexture(current_surface_->PrepareTexture(),
-                                 current_surface_->size());
-      if (texture_id) {
-        new_texture = factory->CreateOwnedTexture(
-          current_surface_->size(),
-          current_surface_->device_scale_factor(), texture_id);
-      }
-    }
-    if (new_texture.get())
-      old_layer->SetExternalTexture(new_texture.get());
-    else
-      old_layer->SetShowPaintedContent();
-    new_layer->SetExternalTexture(old_texture.get());
-  } else if (old_mailbox.IsSharedMemory()) {
-    base::SharedMemory* old_buffer = old_mailbox.shared_memory();
-    const size_t size = old_mailbox.shared_memory_size_in_bytes();
-
-    scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
-    new_buffer->CreateAndMapAnonymous(size);
-
-    if (old_buffer->memory() && new_buffer->memory()) {
-      memcpy(new_buffer->memory(), old_buffer->memory(), size);
-      base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
-      scoped_ptr<cc::SingleReleaseCallback> callback =
-          cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback,
-                                                       Passed(&new_buffer)));
-      cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
-                                     old_mailbox.shared_memory_size());
-      new_layer->SetTextureMailbox(new_mailbox,
-                                   callback.Pass(),
-                                   mailbox_scale_factor);
-    }
-  } else if (frame_provider_.get()) {
-    new_layer->SetShowDelegatedContent(frame_provider_.get(),
-                                       current_frame_size_);
-  }
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // RenderWidgetHostViewAura, ui::EventHandler implementation:
 
@@ -3607,6 +3584,63 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// RenderWidgetHostViewAura, ui::LayerOwnerDelegate implementation:
+
+void RenderWidgetHostViewAura::OnLayerRecreated(ui::Layer* old_layer,
+                                                ui::Layer* new_layer) {
+  float mailbox_scale_factor;
+  cc::TextureMailbox old_mailbox =
+      old_layer->GetTextureMailbox(&mailbox_scale_factor);
+  scoped_refptr<ui::Texture> old_texture = old_layer->external_texture();
+  // The new_layer is the one that will be used by our Window, so that's the one
+  // that should keep our texture. old_layer will be returned to the
+  // RecreateLayer caller, and should have a copy.
+  if (old_texture.get()) {
+    ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+    GLHelper* gl_helper = factory->GetGLHelper();
+    scoped_refptr<ui::Texture> new_texture;
+    if (host_->is_accelerated_compositing_active() &&
+        gl_helper && current_surface_.get()) {
+      GLuint texture_id =
+          gl_helper->CopyTexture(current_surface_->PrepareTexture(),
+                                 current_surface_->size());
+      if (texture_id) {
+        new_texture = factory->CreateOwnedTexture(
+          current_surface_->size(),
+          current_surface_->device_scale_factor(), texture_id);
+      }
+    }
+    if (new_texture.get())
+      old_layer->SetExternalTexture(new_texture.get());
+    else
+      old_layer->SetShowPaintedContent();
+    new_layer->SetExternalTexture(old_texture.get());
+  } else if (old_mailbox.IsSharedMemory()) {
+    base::SharedMemory* old_buffer = old_mailbox.shared_memory();
+    const size_t size = old_mailbox.shared_memory_size_in_bytes();
+
+    scoped_ptr<base::SharedMemory> new_buffer(new base::SharedMemory);
+    new_buffer->CreateAndMapAnonymous(size);
+
+    if (old_buffer->memory() && new_buffer->memory()) {
+      memcpy(new_buffer->memory(), old_buffer->memory(), size);
+      base::SharedMemory* new_buffer_raw_ptr = new_buffer.get();
+      scoped_ptr<cc::SingleReleaseCallback> callback =
+          cc::SingleReleaseCallback::Create(base::Bind(MailboxReleaseCallback,
+                                                       Passed(&new_buffer)));
+      cc::TextureMailbox new_mailbox(new_buffer_raw_ptr,
+                                     old_mailbox.shared_memory_size());
+      new_layer->SetTextureMailbox(new_mailbox,
+                                   callback.Pass(),
+                                   mailbox_scale_factor);
+    }
+  } else if (frame_provider_.get()) {
+    new_layer->SetShowDelegatedContent(frame_provider_.get(),
+                                       current_frame_size_);
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // RenderWidgetHostView, public:
 
 // static
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index fb57907..fa59156 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -29,8 +29,6 @@
 #include "content/common/cursors/webcursor.h"
 #include "content/common/gpu/client/gl_helper.h"
 #include "third_party/skia/include/core/SkRegion.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
 #include "ui/aura/client/cursor_client_observer.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/aura/window_delegate.h"
@@ -39,8 +37,11 @@
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_observer.h"
 #include "ui/compositor/compositor_vsync_manager.h"
+#include "ui/compositor/layer_owner_delegate.h"
 #include "ui/gfx/display_observer.h"
 #include "ui/gfx/rect.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace aura {
 class WindowTracker;
@@ -77,6 +78,7 @@
 class LegacyRenderWidgetHostHWND;
 #endif
 
+class RenderFrameHostImpl;
 class RenderWidgetHostImpl;
 class RenderWidgetHostView;
 class ResizeLock;
@@ -86,6 +88,7 @@
     : public RenderWidgetHostViewBase,
       public ui::CompositorObserver,
       public ui::CompositorVSyncManager::Observer,
+      public ui::LayerOwnerDelegate,
       public ui::TextInputClient,
       public gfx::DisplayObserver,
       public aura::WindowTreeHostObserver,
@@ -300,8 +303,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
   virtual bool HasHitTestMask() const OVERRIDE;
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
-  virtual void DidRecreateLayer(ui::Layer *old_layer,
-                                ui::Layer *new_layer) OVERRIDE;
 
   // Overridden from ui::EventHandler:
   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
@@ -342,6 +343,9 @@
   // windowed NPAPI plugins shouldn't paint in. Overwrites any previous cutout
   // rects.
   void UpdateConstrainedWindowRects(const std::vector<gfx::Rect>& rects);
+
+  // Updates the cursor clip region. Used for mouse locking.
+  void UpdateMouseLockRegion();
 #endif
 
   // Method to indicate if this instance is shutting down or closing.
@@ -380,12 +384,15 @@
   virtual void OnCompositingLockStateChanged(
       ui::Compositor* compositor) OVERRIDE;
 
-  // Overridden from ui::CompositorVSyncManager::Observer
+  // Overridden from ui::CompositorVSyncManager::Observer:
   virtual void OnUpdateVSyncParameters(base::TimeTicks timebase,
                                        base::TimeDelta interval) OVERRIDE;
-
   virtual SkBitmap::Config PreferredReadbackFormat() OVERRIDE;
 
+  // Overridden from ui::LayerOwnerObserver:
+  virtual void OnLayerRecreated(ui::Layer* old_layer,
+                                ui::Layer* new_layer) OVERRIDE;
+
  private:
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, SetCompositionText);
   FRIEND_TEST_ALL_PREFIXES(RenderWidgetHostViewAuraTest, TouchEventState);
@@ -578,6 +585,8 @@
   // Helper function to set keyboard focus to the main window.
   void SetKeyboardFocus();
 
+  RenderFrameHostImpl* GetFocusedFrame();
+
   // The model object.
   RenderWidgetHostImpl* host_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
index 648acfb..65f6536 100644
--- a/content/browser/renderer_host/render_widget_host_view_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_browsertest.cc
@@ -19,9 +19,9 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "media/base/video_frame.h"
 #include "media/filters/skcanvas_video_renderer.h"
 #include "net/base/net_util.h"
@@ -57,7 +57,7 @@
 // Convenience macro: Short-circuit a pass for platforms where setting up
 // high-DPI fails.
 #define PASS_TEST_IF_SCALE_FACTOR_NOT_SUPPORTED(factor) \
-  if (ui::GetImageScale( \
+  if (ui::GetScaleForScaleFactor( \
           GetScaleFactorForView(GetRenderWidgetHostViewPort())) != factor) {  \
     LOG(WARNING) << "Blindly passing this test: failed to set up "  \
                     "scale factor: " << factor;  \
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h
index 38a15e1..10b5afd 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.h
+++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -367,9 +367,10 @@
                              const std::vector<ui::LatencyInfo>& latency_info);
 
   // Draw the IOSurface by making its context current to this view.
-  bool DrawIOSurfaceWithoutCoreAnimation();
+  void DrawIOSurfaceWithoutCoreAnimation();
 
-  // Called when a GPU error is detected. Deletes all compositing state.
+  // Called when a GPU error is detected. Posts a task to destroy all
+  // compositing state.
   void GotAcceleratedCompositingError();
 
   // Sets the overlay view, which should be drawn in the same IOSurface
@@ -494,8 +495,8 @@
   // Ensure that the display link is associated with the correct display.
   void UpdateDisplayLink();
 
-  // The scale factor of the backing store and all CALayers. Note that this is
-  // updated based on ViewScaleFactor with some delay.
+  // The scale factor of the backing store. Note that this is updated based on
+  // ViewScaleFactor with some delay.
   float backing_store_scale_factor_;
 
   void AddPendingLatencyInfo(
@@ -505,7 +506,13 @@
 
   void SendPendingSwapAck();
 
-  void PauseForPendingResizeOrRepaints();
+  void PauseForPendingResizeOrRepaintsAndDraw();
+
+  // The geometric arrangement of the layers depends on cocoa_view's size, the
+  // compositing IOSurface's rounded size, and the software frame size. Update
+  // all of them using this function when any of those parameters changes. Also
+  // update the scale factor of the layers.
+  void LayoutLayers();
 
  private:
   friend class RenderWidgetHostView;
@@ -535,11 +542,11 @@
   // invoke it from the message loop.
   void ShutdownHost();
 
-  void CreateSoftwareLayer();
+  void EnsureSoftwareLayer();
   void DestroySoftwareLayer();
 
-  bool CreateCompositedIOSurface();
-  bool CreateCompositedIOSurfaceLayer();
+  bool EnsureCompositedIOSurface() WARN_UNUSED_RESULT;
+  void EnsureCompositedIOSurfaceLayer();
   enum DestroyContextBehavior {
     kLeaveContextBoundToView,
     kDestroyContext,
@@ -548,6 +555,8 @@
   void DestroyCompositedIOSurfaceAndLayer(DestroyContextBehavior
       destroy_context_behavior);
 
+  void DestroyCompositingStateOnError();
+
   // Unbind the GL context (if any) that is bound to |cocoa_view_|.
   void ClearBoundContextDrawable();
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm
index 4c02857..0e913b5 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -88,6 +88,7 @@
 using blink::WebInputEventFactory;
 using blink::WebMouseEvent;
 using blink::WebMouseWheelEvent;
+using blink::WebGestureEvent;
 
 // These are not documented, so use only after checking -respondsToSelector:.
 @interface NSApplication (UndocumentedSpeechMethods)
@@ -431,7 +432,6 @@
 
   if (GetCoreAnimationStatus() == CORE_ANIMATION_ENABLED) {
     use_core_animation_ = true;
-    ScopedCAActionDisabler disabler;
     background_layer_.reset([[CALayer alloc] init]);
     [background_layer_
         setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
@@ -476,7 +476,22 @@
 ///////////////////////////////////////////////////////////////////////////////
 // RenderWidgetHostViewMac, RenderWidgetHostView implementation:
 
-bool RenderWidgetHostViewMac::CreateCompositedIOSurface() {
+bool RenderWidgetHostViewMac::EnsureCompositedIOSurface() {
+  // If the context or the IOSurface's context has had an error, re-build
+  // everything from scratch.
+  if (compositing_iosurface_context_ &&
+      compositing_iosurface_context_->HasBeenPoisoned()) {
+    LOG(ERROR) << "Failing EnsureCompositedIOSurface because "
+               << "context was poisoned";
+    return false;
+  }
+  if (compositing_iosurface_ &&
+      compositing_iosurface_->HasBeenPoisoned()) {
+    LOG(ERROR) << "Failing EnsureCompositedIOSurface because "
+               << "surface was poisoned";
+    return false;
+  }
+
   int current_window_number = use_core_animation_ ?
       CompositingIOSurfaceContext::kOffscreenContextWindowNumber :
       window_number();
@@ -490,8 +505,6 @@
   if (!new_surface_needed && !new_context_needed)
     return true;
 
-  ScopedCAActionDisabler disabler;
-
   // Create the GL context and shaders.
   if (new_context_needed) {
     scoped_refptr<CompositingIOSurfaceContext> new_context =
@@ -520,22 +533,17 @@
   return true;
 }
 
-void RenderWidgetHostViewMac::CreateSoftwareLayer() {
-  TRACE_EVENT0("browser", "RenderWidgetHostViewMac::CreateSoftwareLayer");
+void RenderWidgetHostViewMac::EnsureSoftwareLayer() {
+  TRACE_EVENT0("browser", "RenderWidgetHostViewMac::EnsureSoftwareLayer");
   if (software_layer_ || !use_core_animation_)
     return;
 
-  ScopedCAActionDisabler disabler;
-
-  // Create the layer.
   software_layer_.reset([[SoftwareLayer alloc]
       initWithRenderWidgetHostViewMac:this]);
-  if (!software_layer_) {
-    LOG(ERROR) << "Failed to create CALayer for software rendering";
-    return;
-  }
+  DCHECK(software_layer_);
 
-  // Make the layer visible.
+  // Disable the fade-in animation as the layer is added.
+  ScopedCAActionDisabler disabler;
   [background_layer_ addSublayer:software_layer_];
 }
 
@@ -543,41 +551,34 @@
   if (!software_layer_)
     return;
 
+  // Disable the fade-out animation as the layer is removed.
   ScopedCAActionDisabler disabler;
   [software_layer_ removeFromSuperlayer];
   [software_layer_ disableRendering];
   software_layer_.reset();
 }
 
-bool RenderWidgetHostViewMac::CreateCompositedIOSurfaceLayer() {
+void RenderWidgetHostViewMac::EnsureCompositedIOSurfaceLayer() {
   TRACE_EVENT0("browser",
-               "RenderWidgetHostViewMac::CreateCompositedIOSurfaceLayer");
+               "RenderWidgetHostViewMac::EnsureCompositedIOSurfaceLayer");
+  DCHECK(compositing_iosurface_context_);
   if (compositing_iosurface_layer_ || !use_core_animation_)
-    return true;
+    return;
 
-  ScopedCAActionDisabler disabler;
-
-  // Create the layer.
   compositing_iosurface_layer_.reset([[CompositingIOSurfaceLayer alloc]
       initWithRenderWidgetHostViewMac:this]);
-  if (!compositing_iosurface_layer_) {
-    LOG(ERROR) << "Failed to create CALayer for IOSurface";
-    return false;
-  }
+  DCHECK(compositing_iosurface_layer_);
 
-  // Make the layer visible.
+  // Disable the fade-in animation as the layer is added.
+  ScopedCAActionDisabler disabler;
   [background_layer_ addSublayer:compositing_iosurface_layer_];
-
-  // Creating the CompositingIOSurfaceLayer may attempt to draw inside
-  // addSublayer, which, if it fails, will promptly tear down everything that
-  // was just created. If that happened, return failure.
-  return compositing_iosurface_layer_;
 }
 
 void RenderWidgetHostViewMac::DestroyCompositedIOSurfaceLayer() {
   if (!compositing_iosurface_layer_)
     return;
 
+  // Disable the fade-out animation as the layer is removed.
   ScopedCAActionDisabler disabler;
   [compositing_iosurface_layer_ removeFromSuperlayer];
   [compositing_iosurface_layer_ disableCompositing];
@@ -753,13 +754,15 @@
 }
 
 void RenderWidgetHostViewMac::SendVSyncParametersToRenderer() {
+  if (!render_widget_host_ || !display_link_)
+    return;
+
   base::TimeTicks timebase;
   base::TimeDelta interval;
-  if (display_link_ &&
-      display_link_->GetVSyncParameters(
-          &timebase, &interval)) {
-    render_widget_host_->UpdateVSyncParameters(timebase, interval);
-  }
+  if (!display_link_->GetVSyncParameters(&timebase, &interval))
+    return;
+
+  render_widget_host_->UpdateVSyncParameters(timebase, interval);
 }
 
 void RenderWidgetHostViewMac::UpdateBackingStoreScaleFactor() {
@@ -776,22 +779,6 @@
   if (backing_store)
     backing_store->ScaleFactorChanged(backing_store_scale_factor_);
 
-  ScopedCAActionDisabler disabler;
-
-  if (software_layer_) {
-    DestroySoftwareLayer();
-    CreateSoftwareLayer();
-  }
-
-  // Dynamically calling setContentsScale on a CAOpenGLLayer for which
-  // setAsynchronous is dynamically toggled can result in flashes of corrupt
-  // content. Work around this by replacing the entire layer when the scale
-  // factor changes.
-  if (compositing_iosurface_layer_) {
-    DestroyCompositedIOSurfaceLayer();
-    CreateCompositedIOSurfaceLayer();
-  }
-
   render_widget_host_->NotifyScreenInfoChanged();
 }
 
@@ -808,9 +795,11 @@
   render_widget_host_->WasShown();
   software_frame_manager_->SetVisibility(true);
 
+  // Call setNeedsDisplay before pausing for new frames to come in -- if any
+  // do, and are drawn, then the needsDisplay bit will be cleared.
   [software_layer_ setNeedsDisplay];
   [compositing_iosurface_layer_ setNeedsDisplay];
-  PauseForPendingResizeOrRepaints();
+  PauseForPendingResizeOrRepaintsAndDraw();
 
   // We're messing with the window, so do this to ensure no flashes.
   if (!use_core_animation_)
@@ -914,7 +903,7 @@
   // Must be overridden, but unused on this platform. Core Animation
   // plugins are drawn by the GPU process (through the compositor),
   // and Core Graphics plugins are drawn by the renderer process.
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
 void RenderWidgetHostViewMac::Focus() {
@@ -1022,26 +1011,15 @@
     const gfx::Vector2d& scroll_delta,
     const std::vector<gfx::Rect>& copy_rects,
     const std::vector<ui::LatencyInfo>& latency_info) {
-  GotSoftwareFrame();
-
+  // This can be called while already inside of a display function. Process the
+  // new frame in a callback to ensure a clean stack.
+  // TODO(ccameron): This should never be called. Remove the remaining callers
+  // and remove all places where the backing store is drawn.
   AddPendingLatencyInfo(latency_info);
-
-  if (render_widget_host_->is_hidden())
-    return;
-
-  std::vector<gfx::Rect> rects(copy_rects);
-
-  // Because the findbar might be open, we cannot use scrollRect:by: here. For
-  // now, simply mark all of scroll rect as dirty.
-  if (!scroll_rect.IsEmpty())
-    rects.push_back(scroll_rect);
-
-  for (size_t i = 0; i < rects.size(); ++i) {
-    NSRect ns_rect = [cocoa_view_ flipRectToNSRect:rects[i]];
-    [cocoa_view_ setNeedsDisplayInRect:ns_rect];
-  }
-
-  [cocoa_view_ displayIfNeeded];
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&RenderWidgetHostViewMac::GotSoftwareFrame,
+                 weak_factory_.GetWeakPtr()));
 }
 
 void RenderWidgetHostViewMac::RenderProcessGone(base::TerminationStatus status,
@@ -1369,26 +1347,32 @@
   if (render_widget_host_->is_hidden())
     return;
 
+  // Ensure that if this function exits before the frame is set up (but not
+  // necessarily drawn) then it is treated as an error.
+  base::ScopedClosureRunner scoped_error(
+      base::Bind(&RenderWidgetHostViewMac::GotAcceleratedCompositingError,
+                 weak_factory_.GetWeakPtr()));
+
   AddPendingLatencyInfo(latency_info);
 
   // Ensure compositing_iosurface_ and compositing_iosurface_context_ be
   // allocated.
-  if (!CreateCompositedIOSurface()) {
-    LOG(ERROR) << "Failed to create CompositingIOSurface";
-    GotAcceleratedCompositingError();
+  if (!EnsureCompositedIOSurface()) {
+    LOG(ERROR) << "Failed EnsureCompositingIOSurface";
     return;
   }
 
   // Make the context current and update the IOSurface with the handle
   // passed in by the swap command.
-  gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
-      compositing_iosurface_context_->cgl_context());
-  if (!compositing_iosurface_->SetIOSurfaceWithContextCurrent(
-          compositing_iosurface_context_, surface_handle, size,
-          surface_scale_factor)) {
-    LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac";
-    GotAcceleratedCompositingError();
-    return;
+  {
+    gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+        compositing_iosurface_context_->cgl_context());
+    if (!compositing_iosurface_->SetIOSurfaceWithContextCurrent(
+            compositing_iosurface_context_, surface_handle, size,
+            surface_scale_factor)) {
+      LOG(ERROR) << "Failed SetIOSurface on CompositingIOSurfaceMac";
+      return;
+    }
   }
 
   // Grab video frames now that the IOSurface has been set up. Note that this
@@ -1403,23 +1387,21 @@
                                               &frame, &callback)) {
       // Flush the context that updated the IOSurface, to ensure that the
       // context that does the copy picks up the correct version.
-      glFlush();
+      {
+        gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+            compositing_iosurface_context_->cgl_context());
+        glFlush();
+      }
       compositing_iosurface_->CopyToVideoFrame(
           gfx::Rect(size), frame,
           base::Bind(callback, present_time));
-      DCHECK_EQ(CGLGetCurrentContext(),
-                compositing_iosurface_context_->cgl_context());
       frame_was_captured = true;
     }
   }
 
-  // Create the layer for the composited content only after the IOSurface has
-  // been initialized.
-  if (!CreateCompositedIOSurfaceLayer()) {
-    LOG(ERROR) << "Failed to create CompositingIOSurface layer";
-    GotAcceleratedCompositingError();
-    return;
-  }
+  // At this point the surface, its context, and its layer have been set up, so
+  // don't generate an error (one may be generated when drawing).
+  ignore_result(scoped_error.Release());
 
   GotAcceleratedFrame();
 
@@ -1464,21 +1446,23 @@
 
   // If we reach here, then the frame will be displayed by a future draw
   // call, so don't make the callback.
-  (void)scoped_ack.Release();
+  ignore_result(scoped_ack.Release());
   if (use_core_animation_) {
     DCHECK(compositing_iosurface_layer_);
     compositing_iosurface_layer_async_timer_.Reset();
     [compositing_iosurface_layer_ gotNewFrame];
   } else {
-    if (!DrawIOSurfaceWithoutCoreAnimation()) {
-      [cocoa_view_ setNeedsDisplay:YES];
-      GotAcceleratedCompositingError();
-      return;
-    }
+    gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
+        compositing_iosurface_context_->cgl_context());
+    DrawIOSurfaceWithoutCoreAnimation();
   }
+
+  // The IOSurface's size may have changed, so re-layout the layers to take
+  // this into account. This may force an immediate draw.
+  LayoutLayers();
 }
 
-bool RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() {
+void RenderWidgetHostViewMac::DrawIOSurfaceWithoutCoreAnimation() {
   CHECK(!use_core_animation_);
   CHECK(compositing_iosurface_);
 
@@ -1505,7 +1489,7 @@
       underlay_view_->compositing_iosurface_ &&
       underlay_view_has_drawn_) {
     [underlay_view_->cocoa_view() setNeedsDisplayInRect:NSMakeRect(0, 0, 1, 1)];
-    return true;
+    return;
   }
 
   bool has_overlay = overlay_view_ && overlay_view_->compositing_iosurface_;
@@ -1521,7 +1505,8 @@
   if (!compositing_iosurface_->DrawIOSurface(
           compositing_iosurface_context_, view_rect,
           ViewScaleFactor(), !has_overlay)) {
-    return false;
+    GotAcceleratedCompositingError();
+    return;
   }
 
   if (has_overlay) {
@@ -1535,22 +1520,43 @@
     if (!overlay_view_->compositing_iosurface_->DrawIOSurface(
             compositing_iosurface_context_, overlay_view_rect,
             overlay_view_->ViewScaleFactor(), true)) {
-      return false;
+      GotAcceleratedCompositingError();
+      return;
     }
   }
 
   SendPendingLatencyInfoToHost();
-  return true;
 }
 
 void RenderWidgetHostViewMac::GotAcceleratedCompositingError() {
-  DestroyCompositedIOSurfaceAndLayer(kDestroyContext);
+  LOG(ERROR) << "Encountered accelerated compositing error";
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&RenderWidgetHostViewMac::DestroyCompositingStateOnError,
+                 weak_factory_.GetWeakPtr()));
+}
+
+void RenderWidgetHostViewMac::DestroyCompositingStateOnError() {
+  // This should be called with a clean stack. Make sure that no context is
+  // current.
+  DCHECK(!CGLGetCurrentContext());
+
   // The existing GL contexts may be in a bad state, so don't re-use any of the
   // existing ones anymore, rather, allocate new ones.
-  CompositingIOSurfaceContext::MarkExistingContextsAsNotShareable();
-  // Request that a new frame be generated.
+  if (compositing_iosurface_context_)
+    compositing_iosurface_context_->PoisonContextAndSharegroup();
+
+  DestroyCompositedIOSurfaceAndLayer(kDestroyContext);
+
+  // Request that a new frame be generated and dirty the view.
   if (render_widget_host_)
     render_widget_host_->ScheduleComposite();
+  [cocoa_view_ setNeedsDisplay:YES];
+
+  // Mark the last frame as not accelerated (so that the window is prepared for
+  // an underlay next time an accelerated frame comes in).
+  last_frame_was_accelerated_ = false;
+
   // TODO(ccameron): It may be a good idea to request that the renderer recreate
   // its GL context as well, and fall back to software if this happens
   // repeatedly.
@@ -1730,7 +1736,7 @@
     int gpu_host_id) {
   TRACE_EVENT0("browser",
       "RenderWidgetHostViewMac::AcceleratedSurfaceBuffersSwapped");
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   AddPendingSwapAck(params.route_id,
                     gpu_host_id,
@@ -1747,7 +1753,7 @@
     int gpu_host_id) {
   TRACE_EVENT0("browser",
       "RenderWidgetHostViewMac::AcceleratedSurfacePostSubBuffer");
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   AddPendingSwapAck(params.route_id,
                     gpu_host_id,
@@ -1808,17 +1814,6 @@
   AddPendingLatencyInfo(frame->metadata.latency_info);
   GotSoftwareFrame();
 
-  // Draw the contents of the frame immediately. It is critical that this
-  // happen before the frame be acked, otherwise the new frame will likely be
-  // ready before the drawing is complete, thrashing the browser main thread.
-  if (use_core_animation_) {
-    [software_layer_ setNeedsDisplay];
-    [software_layer_ displayIfNeeded];
-  } else {
-    [cocoa_view_ setNeedsDisplay:YES];
-    [cocoa_view_ displayIfNeeded];
-  }
-
   cc::CompositorFrameAck ack;
   RenderWidgetHostImpl::SendSwapCompositorFrameAck(
       render_widget_host_->GetRoutingID(),
@@ -1944,6 +1939,7 @@
 }
 
 void RenderWidgetHostViewMac::GotAcceleratedFrame() {
+  EnsureCompositedIOSurfaceLayer();
   SendVSyncParametersToRenderer();
   if (!last_frame_was_accelerated_) {
     last_frame_was_accelerated_ = true;
@@ -1962,10 +1958,21 @@
 }
 
 void RenderWidgetHostViewMac::GotSoftwareFrame() {
-  CreateSoftwareLayer();
-  [software_layer_ setNeedsDisplay];
+  EnsureSoftwareLayer();
+  LayoutLayers();
   SendVSyncParametersToRenderer();
 
+  // Draw the contents of the frame immediately. It is critical that this
+  // happen before the frame be acked, otherwise the new frame will likely be
+  // ready before the drawing is complete, thrashing the browser main thread.
+  if (use_core_animation_) {
+    [software_layer_ setNeedsDisplay];
+    [software_layer_ displayIfNeeded];
+  } else {
+    [cocoa_view_ setNeedsDisplay:YES];
+    [cocoa_view_ displayIfNeeded];
+  }
+
   if (last_frame_was_accelerated_) {
     last_frame_was_accelerated_ = false;
 
@@ -2027,7 +2034,8 @@
 
   if (compositing_iosurface_) {
     // This will migrate the context to the appropriate window.
-    CreateCompositedIOSurface();
+    if (!EnsureCompositedIOSurface())
+      GotAcceleratedCompositingError();
   }
 }
 
@@ -2180,7 +2188,7 @@
   pending_swap_ack_.reset();
 }
 
-void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaints() {
+void RenderWidgetHostViewMac::PauseForPendingResizeOrRepaintsAndDraw() {
   if (!render_widget_host_ || render_widget_host_->is_hidden())
     return;
 
@@ -2191,6 +2199,80 @@
 
   // Wait for a frame of the right size to come in.
   render_widget_host_->PauseForPendingResizeOrRepaints();
+
+  // Immediately draw any frames that haven't been drawn yet. This is necessary
+  // to keep the window and the window's contents in sync.
+  [cocoa_view_ displayIfNeeded];
+  [software_layer_ displayIfNeeded];
+  [compositing_iosurface_layer_ displayIfNeeded];
+}
+
+void RenderWidgetHostViewMac::LayoutLayers() {
+  if (!use_core_animation_)
+    return;
+
+  // Disable animation of the layer's resizing or change in contents scale.
+  ScopedCAActionDisabler disabler;
+
+  CGRect new_background_frame = NSRectToCGRect([cocoa_view() bounds]);
+
+  // Dynamically calling setContentsScale on a CAOpenGLLayer for which
+  // setAsynchronous is dynamically toggled can result in flashes of corrupt
+  // content. Work around this by replacing the entire layer when the scale
+  // factor changes.
+  if (compositing_iosurface_ &&
+      [compositing_iosurface_layer_
+          respondsToSelector:(@selector(contentsScale))]) {
+    if (compositing_iosurface_->scale_factor() !=
+        [compositing_iosurface_layer_ contentsScale]) {
+      DestroyCompositedIOSurfaceLayer();
+      EnsureCompositedIOSurfaceLayer();
+    }
+  }
+  if (compositing_iosurface_ && compositing_iosurface_layer_) {
+    CGRect layer_bounds = CGRectMake(
+      0,
+      0,
+      compositing_iosurface_->dip_io_surface_size().width(),
+      compositing_iosurface_->dip_io_surface_size().height());
+    CGPoint layer_position = CGPointMake(
+      0,
+      CGRectGetHeight(new_background_frame) - CGRectGetHeight(layer_bounds));
+    bool bounds_changed = !CGRectEqualToRect(
+        layer_bounds, [compositing_iosurface_layer_ bounds]);
+    [compositing_iosurface_layer_ setPosition:layer_position];
+    [compositing_iosurface_layer_ setBounds:layer_bounds];
+
+    // If the bounds changed, then draw the frame immediately, to ensure that
+    // content displayed is in sync with the window size.
+    if (bounds_changed) {
+      // Also, sometimes, especially when infobars are being removed, the
+      // setNeedsDisplay calls are dropped on the floor, and stale content is
+      // displayed. Calling displayIfNeeded will ensure that the right size
+      // frame is drawn to the screen.
+      // http://crbug.com/350817
+      [compositing_iosurface_layer_ setNeedsDisplay];
+      [compositing_iosurface_layer_ displayIfNeeded];
+    }
+  }
+
+  // Dynamically update the software layer's contents scale to match the
+  // software frame.
+  if (software_frame_manager_->HasCurrentFrame() &&
+      [software_layer_ respondsToSelector:(@selector(contentsScale))] &&
+      [software_layer_ respondsToSelector:(@selector(setContentsScale:))]) {
+    if (software_frame_manager_->GetCurrentFrameDeviceScaleFactor() !=
+        [software_layer_ contentsScale]) {
+      [software_layer_ setContentsScale:
+          software_frame_manager_->GetCurrentFrameDeviceScaleFactor()];
+    }
+  }
+  // Changing the software layer's bounds and position doesn't always result
+  // in the layer being anchored to the top-left. Set the layer's frame
+  // explicitly, since this is more reliable in practice.
+  if (software_layer_) {
+    [software_layer_ setFrame:new_background_frame];
+  }
 }
 
 SkBitmap::Config RenderWidgetHostViewMac::PreferredReadbackFormat() {
@@ -2843,6 +2925,20 @@
   }
 }
 
+// Called repeatedly during a pinch gesture, with incremental change values.
+- (void)magnifyWithEvent:(NSEvent*)event {
+  if (renderWidgetHostView_->render_widget_host_) {
+    // Send a GesturePinchUpdate event.
+    // Note that we don't attempt to bracket these by GesturePinchBegin/End (or
+    // GestureSrollBegin/End) as is done for touchscreen.  Keeping track of when
+    // a pinch is active would take a little more work here, and we don't need
+    // it for anything yet.
+    const WebGestureEvent& webEvent =
+        WebInputEventFactory::gestureEvent(event, self);
+    renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent);
+  }
+}
+
 - (void)viewWillMoveToWindow:(NSWindow*)newWindow {
   NSWindow* oldWindow = [self window];
 
@@ -2943,27 +3039,19 @@
   if (!renderWidgetHostView_->render_widget_host_)
     return;
 
+  // Move the CALayers to their positions in the new view size. Note that
+  // this will not draw anything because the non-background layers' sizes
+  // didn't actually change.
+  renderWidgetHostView_->LayoutLayers();
+
   renderWidgetHostView_->render_widget_host_->SendScreenRects();
   renderWidgetHostView_->render_widget_host_->WasResized();
 
-  // Resize the CALayers to be drawn to.
-  ScopedCAActionDisabler disabler;
-  CGRect frame = NSRectToCGRect([renderWidgetHostView_->cocoa_view() bounds]);
-  [renderWidgetHostView_->software_layer_ setFrame:frame];
-  [renderWidgetHostView_->software_layer_ setNeedsDisplay];
-  [renderWidgetHostView_->compositing_iosurface_layer_ setFrame:frame];
-  [renderWidgetHostView_->compositing_iosurface_layer_ setNeedsDisplay];
-
-  // Wait for the frame that WasResize might have requested.
-  renderWidgetHostView_->PauseForPendingResizeOrRepaints();
-
-  // Sometimes, especially when infobars are being removed, the setNeedsDisplay
-  // calls are dropped on the floor, and stale content is displayed. Calling
-  // displayIfNeeded will ensure that the right size frame is drawn to the
-  // screen.
-  // http://crbug.com/350817
-  [renderWidgetHostView_->software_layer_ displayIfNeeded];
-  [renderWidgetHostView_->compositing_iosurface_layer_ displayIfNeeded];
+  // Wait for the frame that WasResize might have requested. If the view is
+  // being made visible at a new size, then this call will have no effect
+  // because the view widget is still hidden, and the pause call in WasShown
+  // will have this effect for us.
+  renderWidgetHostView_->PauseForPendingResizeOrRepaintsAndDraw();
 }
 
 // Fills with white the parts of the area to the right and bottom for |rect|
@@ -3053,12 +3141,8 @@
 
     gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
         renderWidgetHostView_->compositing_iosurface_context_->cgl_context());
-    if (renderWidgetHostView_->DrawIOSurfaceWithoutCoreAnimation())
-      return;
-
-    // On error, fall back to software and fall through to the non-accelerated
-    // drawing path.
-    renderWidgetHostView_->GotAcceleratedCompositingError();
+    renderWidgetHostView_->DrawIOSurfaceWithoutCoreAnimation();
+    return;
   }
 
   CGContextRef context = static_cast<CGContextRef>(
@@ -3947,27 +4031,18 @@
 
     hasOpenMouseDown_ = NO;
   }
-
-  // Resize the view's layers to match the new window size.
-  ScopedCAActionDisabler disabler;
-  [renderWidgetHostView_->software_layer_
-      setFrame:NSRectToCGRect([self bounds])];
-  [renderWidgetHostView_->compositing_iosurface_layer_
-      setFrame:NSRectToCGRect([self bounds])];
 }
 
 - (void)undo:(id)sender {
-  if (renderWidgetHostView_->render_widget_host_->IsRenderView()) {
-    static_cast<RenderViewHostImpl*>(
-        renderWidgetHostView_->render_widget_host_)->Undo();
-  }
+  RenderFrameHost* host = renderWidgetHostView_->GetFocusedFrame();
+  if (host)
+    host->Undo();
 }
 
 - (void)redo:(id)sender {
-  if (renderWidgetHostView_->render_widget_host_->IsRenderView()) {
-    static_cast<RenderViewHostImpl*>(
-        renderWidgetHostView_->render_widget_host_)->Redo();
-  }
+  RenderFrameHost* host = renderWidgetHostView_->GetFocusedFrame();
+  if (host)
+    host->Redo();
 }
 
 - (void)cut:(id)sender {
@@ -3983,10 +4058,9 @@
 }
 
 - (void)copyToFindPboard:(id)sender {
-  if (renderWidgetHostView_->render_widget_host_->IsRenderView()) {
-    static_cast<RenderViewHostImpl*>(
-        renderWidgetHostView_->render_widget_host_)->CopyToFindPboard();
-  }
+  RenderFrameHost* host = renderWidgetHostView_->GetFocusedFrame();
+  if (host)
+    host->CopyToFindPboard();
 }
 
 - (void)paste:(id)sender {
@@ -3996,10 +4070,9 @@
 }
 
 - (void)pasteAndMatchStyle:(id)sender {
-  if (renderWidgetHostView_->render_widget_host_->IsRenderView()) {
-    static_cast<RenderViewHostImpl*>(
-        renderWidgetHostView_->render_widget_host_)->PasteAndMatchStyle();
-  }
+  RenderFrameHost* host = renderWidgetHostView_->GetFocusedFrame();
+  if (host)
+    host->PasteAndMatchStyle();
 }
 
 - (void)selectAll:(id)sender {
@@ -4010,10 +4083,9 @@
   // menu handler, neither is true.
   // Explicitly call SelectAll() here to make sure the renderer returns
   // selection results.
-  if (renderWidgetHostView_->render_widget_host_->IsRenderView()) {
-    static_cast<RenderViewHostImpl*>(
-        renderWidgetHostView_->render_widget_host_)->SelectAll();
-  }
+  RenderFrameHost* host = renderWidgetHostView_->GetFocusedFrame();
+  if (host)
+    host->SelectAll();
 }
 
 - (void)startSpeaking:(id)sender {
@@ -4201,20 +4273,19 @@
   if (self = [super init]) {
     renderWidgetHostView_ = r;
 
-    ScopedCAActionDisabler disabler;
     [self setBackgroundColor:CGColorGetConstantColor(kCGColorWhite)];
+    [self setAnchorPoint:CGPointMake(0, 0)];
+    // Setting contents gravity is necessary to prevent the layer from being
+    // scaled during dyanmic resizes (especially with devtools open).
     [self setContentsGravity:kCAGravityTopLeft];
-    [self setFrame:NSRectToCGRect(
-        [renderWidgetHostView_->cocoa_view() bounds])];
-    if ([self respondsToSelector:(@selector(setContentsScale:))]) {
-      [self setContentsScale:
-          renderWidgetHostView_->backing_store_scale_factor_];
+    if (renderWidgetHostView_->software_frame_manager_->HasCurrentFrame() &&
+        [self respondsToSelector:(@selector(setContentsScale:))]) {
+      [self setContentsScale:renderWidgetHostView_->software_frame_manager_->
+          GetCurrentFrameDeviceScaleFactor()];
     }
 
     // Ensure that the transition between frames not be animated.
     [self setActions:@{ @"contents" : [NSNull null] }];
-
-    [self setNeedsDisplay];
   }
   return self;
 }
@@ -4237,7 +4308,10 @@
 }
 
 - (void)disableRendering {
-  renderWidgetHostView_ = NULL;
+  // Disable the fade-out animation as the layer is removed.
+  ScopedCAActionDisabler disabler;
+  [self removeFromSuperlayer];
+  renderWidgetHostView_ = nil;
 }
 
 @end  // implementation SoftwareLayer
diff --git a/content/browser/renderer_host/socket_stream_dispatcher_host.cc b/content/browser/renderer_host/socket_stream_dispatcher_host.cc
index ca622f1..23e646f 100644
--- a/content/browser/renderer_host/socket_stream_dispatcher_host.cc
+++ b/content/browser/renderer_host/socket_stream_dispatcher_host.cc
@@ -191,7 +191,7 @@
 }
 
 SocketStreamDispatcherHost::~SocketStreamDispatcherHost() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   Shutdown();
 }
 
@@ -268,7 +268,7 @@
 }
 
 void SocketStreamDispatcherHost::Shutdown() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   // TODO(ukai): Implement IDMap::RemoveAll().
   for (IDMap<SocketStreamHost>::const_iterator iter(&hosts_);
        !iter.IsAtEnd();
diff --git a/content/browser/renderer_host/webmenurunner_mac.h b/content/browser/renderer_host/webmenurunner_mac.h
index e1ce91a..392ce9a 100644
--- a/content/browser/renderer_host/webmenurunner_mac.h
+++ b/content/browser/renderer_host/webmenurunner_mac.h
@@ -52,6 +52,9 @@
            withBounds:(NSRect)bounds
          initialIndex:(int)index;
 
+// Hides a popup menu if it's visible.
+- (void)hide;
+
 // Returns the index of selected menu item, or its initial value (-1) if no item
 // was selected.
 - (int)indexOfSelectedItem;
diff --git a/content/browser/renderer_host/webmenurunner_mac.mm b/content/browser/renderer_host/webmenurunner_mac.mm
index bb33a00..94e7745 100644
--- a/content/browser/renderer_host/webmenurunner_mac.mm
+++ b/content/browser/renderer_host/webmenurunner_mac.mm
@@ -148,6 +148,10 @@
     index_ = [cell indexOfSelectedItem];
 }
 
+- (void)hide {
+  [menu_ cancelTracking];
+}
+
 - (int)indexOfSelectedItem {
   return index_;
 }
diff --git a/content/browser/renderer_host/websocket_dispatcher_host.cc b/content/browser/renderer_host/websocket_dispatcher_host.cc
index e44e850..4c4b0e5 100644
--- a/content/browser/renderer_host/websocket_dispatcher_host.cc
+++ b/content/browser/renderer_host/websocket_dispatcher_host.cc
@@ -9,6 +9,7 @@
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/renderer_host/websocket_host.h"
 #include "content/common/websocket_messages.h"
 
@@ -24,17 +25,21 @@
 }  // namespace
 
 WebSocketDispatcherHost::WebSocketDispatcherHost(
+    int process_id,
     const GetRequestContextCallback& get_context_callback)
     : BrowserMessageFilter(WebSocketMsgStart),
+      process_id_(process_id),
       get_context_callback_(get_context_callback),
       websocket_host_factory_(
           base::Bind(&WebSocketDispatcherHost::CreateWebSocketHost,
                      base::Unretained(this))) {}
 
 WebSocketDispatcherHost::WebSocketDispatcherHost(
+    int process_id,
     const GetRequestContextCallback& get_context_callback,
     const WebSocketHostFactory& websocket_host_factory)
     : BrowserMessageFilter(WebSocketMsgStart),
+      process_id_(process_id),
       get_context_callback_(get_context_callback),
       websocket_host_factory_(websocket_host_factory) {}
 
@@ -79,6 +84,12 @@
   return host->OnMessageReceived(message, message_was_ok);
 }
 
+bool WebSocketDispatcherHost::CanReadRawCookies() const {
+  ChildProcessSecurityPolicyImpl* policy =
+      ChildProcessSecurityPolicyImpl::GetInstance();
+  return policy->CanReadRawCookies(process_id_);
+}
+
 WebSocketHost* WebSocketDispatcherHost::GetHost(int routing_id) const {
   WebSocketHostTable::const_iterator it = hosts_.find(routing_id);
   return it == hosts_.end() ? NULL : it->second;
diff --git a/content/browser/renderer_host/websocket_dispatcher_host.h b/content/browser/renderer_host/websocket_dispatcher_host.h
index 9aceb8f..c2812e5 100644
--- a/content/browser/renderer_host/websocket_dispatcher_host.h
+++ b/content/browser/renderer_host/websocket_dispatcher_host.h
@@ -45,14 +45,15 @@
     WEBSOCKET_HOST_DELETED
   };
 
-  explicit WebSocketDispatcherHost(
+  WebSocketDispatcherHost(
+      int process_id,
       const GetRequestContextCallback& get_context_callback);
 
   // For testing. Specify a factory method that creates mock version of
   // WebSocketHost.
-  WebSocketDispatcherHost(
-      const GetRequestContextCallback& get_context_callback,
-      const WebSocketHostFactory& websocket_host_factory);
+  WebSocketDispatcherHost(int process_id,
+                          const GetRequestContextCallback& get_context_callback,
+                          const WebSocketHostFactory& websocket_host_factory);
 
   // BrowserMessageFilter:
   virtual bool OnMessageReceived(const IPC::Message& message,
@@ -108,6 +109,9 @@
       uint16 code,
       const std::string& reason) WARN_UNUSED_RESULT;
 
+  // Returns whether the associated renderer process can read raw cookies.
+  bool CanReadRawCookies() const;
+
  private:
   typedef base::hash_map<int, WebSocketHost*> WebSocketHostTable;
 
@@ -133,6 +137,9 @@
   // routing_id.
   WebSocketHostTable hosts_;
 
+  // The the process ID of the associated renderer process.
+  const int process_id_;
+
   // A callback which returns the appropriate net::URLRequestContext for us to
   // use.
   GetRequestContextCallback get_context_callback_;
diff --git a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
index e1fc62b..f694649 100644
--- a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
+++ b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc
@@ -43,12 +43,12 @@
 class WebSocketDispatcherHostTest : public ::testing::Test {
  public:
   WebSocketDispatcherHostTest() {
-    dispatcher_host_ =
-        new WebSocketDispatcherHost(
-            base::Bind(&WebSocketDispatcherHostTest::OnGetRequestContext,
-                       base::Unretained(this)),
-            base::Bind(&WebSocketDispatcherHostTest::CreateWebSocketHost,
-                       base::Unretained(this)));
+    dispatcher_host_ = new WebSocketDispatcherHost(
+        0,
+        base::Bind(&WebSocketDispatcherHostTest::OnGetRequestContext,
+                   base::Unretained(this)),
+        base::Bind(&WebSocketDispatcherHostTest::CreateWebSocketHost,
+                   base::Unretained(this)));
   }
 
   virtual ~WebSocketDispatcherHostTest() {}
diff --git a/content/browser/renderer_host/websocket_host.cc b/content/browser/renderer_host/websocket_host.cc
index 36342f4..f0acd8a 100644
--- a/content/browser/renderer_host/websocket_host.cc
+++ b/content/browser/renderer_host/websocket_host.cc
@@ -179,9 +179,12 @@
 
 ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
     scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
-  DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake";
+  bool should_send = dispatcher_->CanReadRawCookies();
+  DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake "
+           << "should_send=" << should_send;
 
-  // TODO(yhirano) Do nothing if the inspector is not attached.
+  if (!should_send)
+    return WebSocketEventInterface::CHANNEL_ALIVE;
 
   WebSocketHandshakeRequest request_to_pass;
   request_to_pass.url.Swap(&request->url);
@@ -200,9 +203,12 @@
 
 ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
     scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
-  DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake";
+  bool should_send = dispatcher_->CanReadRawCookies();
+  DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
+           << "should_send=" << should_send;
 
-  // TODO(yhirano) Do nothing if the inspector is not attached.
+  if (!should_send)
+    return WebSocketEventInterface::CHANNEL_ALIVE;
 
   WebSocketHandshakeResponse response_to_pass;
   response_to_pass.url.Swap(&response->url);
diff --git a/content/browser/resources/media/dump_creator.js b/content/browser/resources/media/dump_creator.js
index 33abe57..06a1b38 100644
--- a/content/browser/resources/media/dump_creator.js
+++ b/content/browser/resources/media/dump_creator.js
@@ -55,11 +55,16 @@
   }
 
   DumpCreator.prototype = {
-    /** Mark the AEC recording checkbox checked.*/
+    // Mark the AEC recording checkbox checked.
     enableAecRecording: function() {
       this.root_.getElementsByTagName('input')[0].checked = true;
     },
 
+    // Mark the AEC recording checkbox unchecked.
+    disableAecRecording: function() {
+      this.root_.getElementsByTagName('input')[0].checked = false;
+    },
+
     /**
      * Downloads the PeerConnection updates and stats data as a file.
      *
diff --git a/content/browser/resources/media/webrtc_internals.js b/content/browser/resources/media/webrtc_internals.js
index f69e367..52ab9f7 100644
--- a/content/browser/resources/media/webrtc_internals.js
+++ b/content/browser/resources/media/webrtc_internals.js
@@ -276,6 +276,16 @@
   }
 }
 
+
+/**
+ * Notification that the AEC recording file selection dialog was cancelled,
+ * i.e. AEC has not been enabled.
+ */
+function aecRecordingFileSelectionCancelled() {
+  dumpCreator.disableAecRecording();
+}
+
+
 /**
  * Set
  */
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index a5896f4..9fadec0 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -15,10 +15,10 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 
 namespace content {
 
diff --git a/content/browser/service_worker/embedded_worker_test_helper.cc b/content/browser/service_worker/embedded_worker_test_helper.cc
index 70f7f0c..6617eea 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -87,14 +87,14 @@
   return handled;
 }
 
-void EmbeddedWorkerTestHelper::OnInstallEvent(
-    int embedded_worker_id,
-    int request_id,
-    int active_version_embedded_worker_id) {
+void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id,
+                                              int request_id,
+                                              int active_version_id) {
   SimulateSendMessageToBrowser(
       embedded_worker_id,
       request_id,
-      ServiceWorkerHostMsg_InstallEventFinished());
+      ServiceWorkerHostMsg_InstallEventFinished(
+          blink::WebServiceWorkerEventResultCompleted));
 }
 
 void EmbeddedWorkerTestHelper::OnFetchEvent(
@@ -179,15 +179,14 @@
           message));
 }
 
-void EmbeddedWorkerTestHelper::OnInstallEventStub(
-    int active_version_embedded_worker_id) {
+void EmbeddedWorkerTestHelper::OnInstallEventStub(int active_version_id) {
   base::MessageLoopProxy::current()->PostTask(
       FROM_HERE,
       base::Bind(&EmbeddedWorkerTestHelper::OnInstallEvent,
                  weak_factory_.GetWeakPtr(),
                  current_embedded_worker_id_,
                  current_request_id_,
-                 active_version_embedded_worker_id));
+                 active_version_id));
 }
 
 void EmbeddedWorkerTestHelper::OnFetchEventStub(
diff --git a/content/browser/service_worker/embedded_worker_test_helper.h b/content/browser/service_worker/embedded_worker_test_helper.h
index 77c1bde..01952f2 100644
--- a/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/content/browser/service_worker/embedded_worker_test_helper.h
@@ -85,7 +85,7 @@
   // SimulateSendMessageToBrowser.
   virtual void OnInstallEvent(int embedded_worker_id,
                               int request_id,
-                              int active_version_embedded_worker_id);
+                              int active_version_id);
   virtual void OnFetchEvent(int embedded_worker_id,
                             int request_id,
                             const ServiceWorkerFetchRequest& request);
@@ -107,7 +107,7 @@
                                  int embedded_worker_id,
                                  int request_id,
                                  const IPC::Message& message);
-  void OnInstallEventStub(int active_version_embedded_worker_id);
+  void OnInstallEventStub(int active_version_id);
   void OnFetchEventStub(const ServiceWorkerFetchRequest& request);
 
   EmbeddedWorkerRegistry* registry();
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index b833a0f..65afe8d 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -22,9 +22,9 @@
 #include "content/public/browser/storage_partition.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
 namespace content {
@@ -53,6 +53,20 @@
   run_loop.Run();
 }
 
+void RunOnIOThread(
+    const base::Callback<void(const base::Closure& continuation)>& closure) {
+  base::RunLoop run_loop;
+  base::Closure quit_on_original_thread =
+      base::Bind(base::IgnoreResult(&base::MessageLoopProxy::PostTask),
+                 base::MessageLoopProxy::current().get(),
+                 FROM_HERE,
+                 run_loop.QuitClosure());
+  BrowserThread::PostTask(BrowserThread::IO,
+                          FROM_HERE,
+                          base::Bind(closure, quit_on_original_thread));
+  run_loop.Run();
+}
+
 // Contrary to the style guide, the output parameter of this function comes
 // before input parameters so Bind can be used on it to create a FetchCallback
 // to pass to DispatchFetchEvent.
@@ -90,7 +104,8 @@
     ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
     StoragePartition* partition = BrowserContext::GetDefaultStoragePartition(
         shell()->web_contents()->GetBrowserContext());
-    wrapper_ = partition->GetServiceWorkerContext();
+    wrapper_ = static_cast<ServiceWorkerContextWrapper*>(
+        partition->GetServiceWorkerContext());
 
     // Navigate to the page to set up a renderer page (where we can embed
     // a worker).
@@ -110,6 +125,7 @@
   virtual void TearDownOnIOThread() {}
 
   ServiceWorkerContextWrapper* wrapper() { return wrapper_.get(); }
+  ServiceWorkerContext* public_context() { return wrapper(); }
 
   void AssociateRendererProcessToWorker(EmbeddedWorkerInstance* worker) {
     worker->AddProcessReference(
@@ -217,7 +233,8 @@
     }
   }
 
-  void InstallTestHelper(const std::string& worker_url) {
+  void InstallTestHelper(const std::string& worker_url,
+                         ServiceWorkerStatusCode expected_status) {
     RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
                              worker_url));
 
@@ -229,7 +246,7 @@
                                        install_run_loop.QuitClosure(),
                                        &status));
     install_run_loop.Run();
-    ASSERT_EQ(SERVICE_WORKER_OK, status);
+    ASSERT_EQ(expected_status, status);
 
     // Stop the worker.
     status = SERVICE_WORKER_ERROR_FAILED;
@@ -373,19 +390,19 @@
 }
 
 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Install) {
-  InstallTestHelper("/service_worker/worker.js");
+  InstallTestHelper("/service_worker/worker.js", SERVICE_WORKER_OK);
 }
 
 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_Fulfilled) {
-  InstallTestHelper("/service_worker/worker_install_fulfilled.js");
+  InstallTestHelper("/service_worker/worker_install_fulfilled.js",
+                    SERVICE_WORKER_OK);
 }
 
 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
                        InstallWithWaitUntil_Rejected) {
-  // TODO(kinuko): This should also report back an error, but we
-  // don't have plumbing for it yet.
-  InstallTestHelper("/service_worker/worker_install_rejected.js");
+  InstallTestHelper("/service_worker/worker_install_rejected.js",
+                    SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
 }
 
 IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
@@ -416,4 +433,96 @@
   ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, result);
 }
 
+class ServiceWorkerBlackBoxBrowserTest : public ServiceWorkerBrowserTest {
+ public:
+  typedef ServiceWorkerBlackBoxBrowserTest self;
+
+  static void ExpectResultAndRun(bool expected,
+                                 const base::Closure& continuation,
+                                 bool actual) {
+    EXPECT_EQ(expected, actual);
+    continuation.Run();
+  }
+
+  int RenderProcessID() {
+    return shell()->web_contents()->GetRenderProcessHost()->GetID();
+  }
+
+  void FindRegistrationOnIO(const GURL& document_url,
+                            ServiceWorkerStatusCode* status,
+                            GURL* script_url,
+                            const base::Closure& continuation) {
+    wrapper()->context()->storage()->FindRegistrationForDocument(
+        document_url,
+        base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO2,
+                   this,
+                   status,
+                   script_url,
+                   continuation));
+  }
+
+  void FindRegistrationOnIO2(
+      ServiceWorkerStatusCode* out_status,
+      GURL* script_url,
+      const base::Closure& continuation,
+      ServiceWorkerStatusCode status,
+      const scoped_refptr<ServiceWorkerRegistration>& registration) {
+    *out_status = status;
+    if (registration) {
+      *script_url = registration->script_url();
+    } else {
+      EXPECT_NE(SERVICE_WORKER_OK, status);
+    }
+    continuation.Run();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBlackBoxBrowserTest, Registration) {
+  const std::string kWorkerUrl = "/service_worker/fetch_event.js";
+  {
+    base::RunLoop run_loop;
+    public_context()->RegisterServiceWorker(
+        embedded_test_server()->GetURL("/*"),
+        embedded_test_server()->GetURL(kWorkerUrl),
+        RenderProcessID(),
+        base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
+                   true,
+                   run_loop.QuitClosure()));
+    run_loop.Run();
+  }
+  {
+    ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+    GURL script_url;
+    RunOnIOThread(
+        base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
+                   this,
+                   embedded_test_server()->GetURL("/service_worker/empty.html"),
+                   &status,
+                   &script_url));
+    EXPECT_EQ(SERVICE_WORKER_OK, status);
+    EXPECT_EQ(embedded_test_server()->GetURL(kWorkerUrl), script_url);
+  }
+  {
+    base::RunLoop run_loop;
+    public_context()->UnregisterServiceWorker(
+        embedded_test_server()->GetURL("/*"),
+        RenderProcessID(),
+        base::Bind(&ServiceWorkerBlackBoxBrowserTest::ExpectResultAndRun,
+                   true,
+                   run_loop.QuitClosure()));
+    run_loop.Run();
+  }
+  {
+    ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
+    GURL script_url;
+    RunOnIOThread(
+        base::Bind(&ServiceWorkerBlackBoxBrowserTest::FindRegistrationOnIO,
+                   this,
+                   embedded_test_server()->GetURL("/service_worker/empty.html"),
+                   &status,
+                   &script_url));
+    EXPECT_EQ(SERVICE_WORKER_ERROR_NOT_FOUND, status);
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context.h b/content/browser/service_worker/service_worker_context.h
deleted file mode 100644
index d9f51f3..0000000
--- a/content/browser/service_worker/service_worker_context.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_H_
-#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_H_
-
-#include "base/basictypes.h"
-
-namespace content {
-
-// Represents the per-BrowserContext ServiceWorker data.
-class ServiceWorkerContext {
- public:
-  // TODO(michaeln): This class is a place holder for content/public api
-  // which will come later. Promote this class when we get there.
-
- protected:
-  ServiceWorkerContext() {}
-  virtual ~ServiceWorkerContext() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContext);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CONTEXT_H_
diff --git a/content/browser/service_worker/service_worker_context_unittest.cc b/content/browser/service_worker/service_worker_context_unittest.cc
index c4d8a64..644eca6 100644
--- a/content/browser/service_worker/service_worker_context_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/browser/service_worker/service_worker_context.h"
+#include "content/public/browser/service_worker_context.h"
 
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
index e423d70..769df0a 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -45,8 +45,76 @@
 }
 
 ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
   return context_core_.get();
 }
 
+static void FinishRegistrationOnIO(
+    const ServiceWorkerContext::ResultCallback& continuation,
+    ServiceWorkerStatusCode status,
+    int64 registration_id) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(continuation, status == SERVICE_WORKER_OK));
+}
+
+void ServiceWorkerContextWrapper::RegisterServiceWorker(
+    const GURL& pattern,
+    const GURL& script_url,
+    int source_process_id,
+    const ResultCallback& continuation) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+    BrowserThread::PostTask(
+        BrowserThread::IO,
+        FROM_HERE,
+        base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker,
+                   this,
+                   pattern,
+                   script_url,
+                   source_process_id,
+                   continuation));
+    return;
+  }
+
+  context()->RegisterServiceWorker(
+      pattern,
+      script_url,
+      source_process_id,
+      base::Bind(&FinishRegistrationOnIO, continuation));
+}
+
+static void FinishUnregistrationOnIO(
+    const ServiceWorkerContext::ResultCallback& continuation,
+    ServiceWorkerStatusCode status) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  BrowserThread::PostTask(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(continuation, status == SERVICE_WORKER_OK));
+}
+
+void ServiceWorkerContextWrapper::UnregisterServiceWorker(
+    const GURL& pattern,
+    int source_process_id,
+    const ResultCallback& continuation) {
+  if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
+    BrowserThread::PostTask(
+        BrowserThread::IO,
+        FROM_HERE,
+        base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker,
+                   this,
+                   pattern,
+                   source_process_id,
+                   continuation));
+    return;
+  }
+
+  context()->UnregisterServiceWorker(
+      pattern,
+      source_process_id,
+      base::Bind(&FinishUnregistrationOnIO, continuation));
+}
+
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h
index 1b9b652..450538c 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -8,8 +8,9 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "content/browser/service_worker/service_worker_context.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/common/content_export.h"
+#include "content/public/browser/service_worker_context.h"
 
 namespace base {
 class FilePath;
@@ -42,6 +43,18 @@
   // The core context is only for use on the IO thread.
   ServiceWorkerContextCore* context();
 
+  // ServiceWorkerContext implementation:
+  virtual void RegisterServiceWorker(const GURL& pattern,
+                                     const GURL& script_url,
+                                     int source_process_id,
+                                     const ResultCallback& continuation)
+      OVERRIDE;
+
+  virtual void UnregisterServiceWorker(const GURL& pattern,
+                                       int source_process_id,
+                                       const ResultCallback& continuation)
+      OVERRIDE;
+
  private:
   friend class base::RefCountedThreadSafe<ServiceWorkerContextWrapper>;
   virtual ~ServiceWorkerContextWrapper();
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.cc b/content/browser/service_worker/service_worker_dispatcher_host.cc
index 9462bcd..3970f70 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -5,10 +5,12 @@
 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
 
 #include "base/strings/utf_string_conversions.h"
+#include "content/browser/message_port_message_filter.h"
+#include "content/browser/message_port_service.h"
 #include "content/browser/service_worker/embedded_worker_registry.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_provider_host.h"
+#include "content/browser/service_worker/service_worker_registration.h"
 #include "content/browser/service_worker/service_worker_utils.h"
 #include "content/common/service_worker/embedded_worker_messages.h"
 #include "content/common/service_worker/service_worker_messages.h"
@@ -35,11 +37,12 @@
 namespace content {
 
 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
-    int render_process_id)
-    : BrowserMessageFilter(
-          kFilteredMessageClasses, arraysize(kFilteredMessageClasses)),
-      render_process_id_(render_process_id) {
-}
+    int render_process_id,
+    MessagePortMessageFilter* message_port_message_filter)
+    : BrowserMessageFilter(kFilteredMessageClasses,
+                           arraysize(kFilteredMessageClasses)),
+      render_process_id_(render_process_id),
+      message_port_message_filter_(message_port_message_filter) {}
 
 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
   if (context_) {
@@ -85,6 +88,7 @@
                         OnAddScriptClient)
     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RemoveScriptClient,
                         OnRemoveScriptClient)
+    IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessage, OnPostMessage)
     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
                         OnWorkerStarted)
     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
@@ -158,6 +162,54 @@
                  request_id));
 }
 
+void ServiceWorkerDispatcherHost::OnPostMessage(
+    int64 registration_id,
+    const base::string16& message,
+    const std::vector<int>& sent_message_port_ids) {
+  if (!context_ || !ServiceWorkerUtils::IsFeatureEnabled())
+    return;
+
+  std::vector<int> new_routing_ids(sent_message_port_ids.size());
+  for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
+    new_routing_ids[i] = message_port_message_filter_->GetNextRoutingID();
+    MessagePortService::GetInstance()->UpdateMessagePort(
+        sent_message_port_ids[i],
+        message_port_message_filter_,
+        new_routing_ids[i]);
+  }
+
+  context_->storage()->FindRegistrationForId(
+      registration_id,
+      base::Bind(&ServiceWorkerDispatcherHost::PostMessageFoundRegistration,
+                 message,
+                 sent_message_port_ids,
+                 new_routing_ids));
+}
+
+namespace {
+void NoOpStatusCallback(ServiceWorkerStatusCode status) {}
+}  // namespace
+
+// static
+void ServiceWorkerDispatcherHost::PostMessageFoundRegistration(
+    const base::string16& message,
+    const std::vector<int>& sent_message_port_ids,
+    const std::vector<int>& new_routing_ids,
+    ServiceWorkerStatusCode status,
+    const scoped_refptr<ServiceWorkerRegistration>& result) {
+  if (status != SERVICE_WORKER_OK)
+    return;
+  DCHECK(result);
+
+  // TODO(jsbell): Route message to appropriate version. crbug.com/351797
+  ServiceWorkerVersion* version = result->active_version();
+  if (!version)
+    return;
+  version->SendMessage(
+      ServiceWorkerMsg_Message(message, sent_message_port_ids, new_routing_ids),
+      base::Bind(&NoOpStatusCallback));
+}
+
 void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
   if (!context_)
     return;
diff --git a/content/browser/service_worker/service_worker_dispatcher_host.h b/content/browser/service_worker/service_worker_dispatcher_host.h
index cb3a2b7..7b99255 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -13,13 +13,17 @@
 
 namespace content {
 
+class MessagePortMessageFilter;
 class ServiceWorkerContextCore;
 class ServiceWorkerContextWrapper;
 class ServiceWorkerProviderHost;
+class ServiceWorkerRegistration;
 
 class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
  public:
-  explicit ServiceWorkerDispatcherHost(int render_process_id);
+  ServiceWorkerDispatcherHost(
+      int render_process_id,
+      MessagePortMessageFilter* message_port_message_filter);
 
   void Init(ServiceWorkerContextWrapper* context_wrapper);
 
@@ -54,6 +58,16 @@
   void OnSendMessageToBrowser(int embedded_worker_id,
                               int request_id,
                               const IPC::Message& message);
+  void OnPostMessage(int64 registration_id,
+                     const base::string16& message,
+                     const std::vector<int>& sent_message_port_ids);
+
+  static void PostMessageFoundRegistration(
+      const base::string16& message,
+      const std::vector<int>& sent_message_port_ids,
+      const std::vector<int>& new_routing_ids,
+      ServiceWorkerStatusCode status,
+      const scoped_refptr<ServiceWorkerRegistration>& result);
 
   // Callbacks from ServiceWorkerContextCore
   void RegistrationComplete(int32 thread_id,
@@ -68,7 +82,10 @@
   void SendRegistrationError(int32 thread_id,
                              int32 request_id,
                              ServiceWorkerStatusCode status);
+
   int render_process_id_;
+  MessagePortMessageFilter* const message_port_message_filter_;
+
   base::WeakPtr<ServiceWorkerContextCore> context_;
 };
 
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 665736d..2adb94b 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -56,7 +56,7 @@
       int process_id,
       ServiceWorkerContextWrapper* context_wrapper,
       EmbeddedWorkerTestHelper* helper)
-      : ServiceWorkerDispatcherHost(process_id),
+      : ServiceWorkerDispatcherHost(process_id, NULL),
         bad_messages_received_count_(0),
         helper_(helper) {
     Init(context_wrapper);
diff --git a/content/browser/service_worker/service_worker_internals_ui.cc b/content/browser/service_worker/service_worker_internals_ui.cc
index 1836e10..18fef08 100644
--- a/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/content/browser/service_worker/service_worker_internals_ui.cc
@@ -124,7 +124,8 @@
 void ServiceWorkerInternalsUI::AddContextFromStoragePartition(
     StoragePartition* partition) {
   scoped_refptr<ServiceWorkerContextWrapper> context =
-      partition->GetServiceWorkerContext();
+      static_cast<ServiceWorkerContextWrapper*>(
+          partition->GetServiceWorkerContext());
   BrowserThread::PostTask(
       BrowserThread::IO,
       FROM_HERE,
@@ -142,7 +143,8 @@
                  StoragePartition* storage_partition) {
   if (storage_partition->GetPath() == partition_path) {
     *result_partition = storage_partition;
-    *result_context = storage_partition->GetServiceWorkerContext();
+    *result_context = static_cast<ServiceWorkerContextWrapper*>(
+        storage_partition->GetServiceWorkerContext());
   }
 }
 }  // namespace
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
index 724b243..5be0fbb 100644
--- a/content/browser/service_worker/service_worker_storage.cc
+++ b/content/browser/service_worker/service_worker_storage.cc
@@ -97,6 +97,24 @@
       BrowserThread::IO, FROM_HERE, base::Bind(callback, registrations));
 }
 
+void ServiceWorkerStorage::FindRegistrationForId(
+    int64 registration_id,
+    const FindRegistrationCallback& callback) {
+  ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NOT_FOUND;
+  scoped_refptr<ServiceWorkerRegistration> found;
+  for (PatternToRegistrationMap::const_iterator it =
+           registration_by_pattern_.begin();
+       it != registration_by_pattern_.end();
+       ++it) {
+    if (registration_id == it->second->id()) {
+      status = SERVICE_WORKER_OK;
+      found = it->second;
+      break;
+    }
+  }
+  RunSoon(base::Bind(callback, status, found));
+}
+
 void ServiceWorkerStorage::StoreRegistration(
     ServiceWorkerRegistration* registration,
     const StatusCallback& callback) {
diff --git a/content/browser/service_worker/service_worker_storage.h b/content/browser/service_worker/service_worker_storage.h
index eb25cf8..321d766 100644
--- a/content/browser/service_worker/service_worker_storage.h
+++ b/content/browser/service_worker/service_worker_storage.h
@@ -38,7 +38,7 @@
                        quota::QuotaManagerProxy* quota_manager_proxy);
   ~ServiceWorkerStorage();
 
-  // Finds registration for |document_url| or |pattern|.
+  // Finds registration for |document_url| or |pattern| or |registration_id|.
   // Returns SERVICE_WORKER_OK with non-null registration if registration
   // is found, or returns SERVICE_WORKER_ERROR_NOT_FOUND if no matching
   // registration is found.
@@ -46,6 +46,8 @@
                                    const FindRegistrationCallback& callback);
   void FindRegistrationForPattern(const GURL& pattern,
                                   const FindRegistrationCallback& callback);
+  void FindRegistrationForId(int64 registration_id,
+                             const FindRegistrationCallback& callback);
 
   typedef base::Callback<
       void(const std::vector<ServiceWorkerRegistrationInfo>& registrations)>
@@ -72,6 +74,8 @@
 
   typedef std::map<GURL, scoped_refptr<ServiceWorkerRegistration> >
       PatternToRegistrationMap;
+  typedef std::map<int64, scoped_refptr<ServiceWorkerRegistration> >
+      RegistrationIdToRegistrationMap;
 
   static bool PatternMatches(const GURL& pattern, const GURL& script_url);
 
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index fade655..be530d4 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -19,6 +19,39 @@
 
 namespace {
 
+typedef base::Callback<bool(const IPC::Message* message,
+                            Tuple1<blink::WebServiceWorkerEventResult>* result)>
+    InstallPhaseEventFinishedMessageReader;
+
+// Parameters for the HandleInstallPhaseEventFinished function, which cannot
+// accept them directly without exceeding the max arity supported by Bind().
+struct HandleInstallPhaseEventFinishedParameters {
+  HandleInstallPhaseEventFinishedParameters(
+      base::WeakPtr<ServiceWorkerVersion> version,
+      uint32 expected_message_type,
+      const InstallPhaseEventFinishedMessageReader& message_reader,
+      const StatusCallback& callback,
+      ServiceWorkerVersion::Status next_status_on_success,
+      ServiceWorkerVersion::Status next_status_on_error,
+      ServiceWorkerStatusCode next_status_code_on_event_rejection)
+      : version(version),
+        expected_message_type(expected_message_type),
+        message_reader(message_reader),
+        callback(callback),
+        next_status_on_success(next_status_on_success),
+        next_status_on_error(next_status_on_error),
+        next_status_code_on_event_rejection(
+            next_status_code_on_event_rejection) {}
+
+  base::WeakPtr<ServiceWorkerVersion> version;
+  uint32 expected_message_type;
+  InstallPhaseEventFinishedMessageReader message_reader;
+  StatusCallback callback;
+  ServiceWorkerVersion::Status next_status_on_success;
+  ServiceWorkerVersion::Status next_status_on_error;
+  ServiceWorkerStatusCode next_status_code_on_event_rejection;
+};
+
 void RunSoon(const base::Closure& callback) {
   if (!callback.is_null())
     base::MessageLoop::current()->PostTask(FROM_HERE, callback);
@@ -60,29 +93,34 @@
   callback.Run(status, IPC::Message());
 }
 
-void HandleEventFinished(base::WeakPtr<ServiceWorkerVersion> version,
-                         uint32 expected_message_type,
-                         const StatusCallback& callback,
-                         ServiceWorkerVersion::Status next_status_on_success,
-                         ServiceWorkerVersion::Status next_status_on_error,
-                         ServiceWorkerStatusCode status,
-                         const IPC::Message& message) {
-  if (!version)
+void HandleInstallPhaseEventFinished(
+    const HandleInstallPhaseEventFinishedParameters& params,
+    ServiceWorkerStatusCode status,
+    const IPC::Message& message) {
+  if (!params.version)
     return;
   if (status != SERVICE_WORKER_OK) {
-    version->SetStatus(next_status_on_error);
-    callback.Run(status);
+    params.version->SetStatus(params.next_status_on_error);
+    params.callback.Run(status);
     return;
   }
-  if (message.type() != expected_message_type) {
+  if (message.type() != params.expected_message_type) {
     NOTREACHED() << "Got unexpected response: " << message.type()
-                 << " expected:" << expected_message_type;
-    version->SetStatus(next_status_on_error);
-    callback.Run(SERVICE_WORKER_ERROR_FAILED);
+                 << " expected:" << params.expected_message_type;
+    params.version->SetStatus(params.next_status_on_error);
+    params.callback.Run(SERVICE_WORKER_ERROR_FAILED);
     return;
   }
-  version->SetStatus(next_status_on_success);
-  callback.Run(SERVICE_WORKER_OK);
+  params.version->SetStatus(params.next_status_on_success);
+
+  Tuple1<blink::WebServiceWorkerEventResult> result(
+      blink::WebServiceWorkerEventResultCompleted);
+  if (!params.message_reader.is_null()) {
+    params.message_reader.Run(&message, &result);
+    if (result.a == blink::WebServiceWorkerEventResultRejected)
+      status = params.next_status_code_on_event_rejection;
+  }
+  params.callback.Run(status);
 }
 
 void HandleFetchResponse(const ServiceWorkerVersion::FetchCallback& callback,
@@ -247,15 +285,21 @@
 }
 
 void ServiceWorkerVersion::DispatchInstallEvent(
-    int active_version_embedded_worker_id,
+    int active_version_id,
     const StatusCallback& callback) {
   DCHECK_EQ(NEW, status()) << status();
   SetStatus(INSTALLING);
+  HandleInstallPhaseEventFinishedParameters params(
+      weak_factory_.GetWeakPtr(),
+      ServiceWorkerHostMsg_InstallEventFinished::ID,
+      base::Bind(&ServiceWorkerHostMsg_InstallEventFinished::Read),
+      callback,
+      INSTALLED,
+      NEW,
+      SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
   SendMessageAndRegisterCallback(
-      ServiceWorkerMsg_InstallEvent(active_version_embedded_worker_id),
-      base::Bind(&HandleEventFinished, weak_factory_.GetWeakPtr(),
-                 ServiceWorkerHostMsg_InstallEventFinished::ID,
-                 callback, INSTALLED, NEW));
+      ServiceWorkerMsg_InstallEvent(active_version_id),
+      base::Bind(&HandleInstallPhaseEventFinished, params));
 }
 
 void ServiceWorkerVersion::DispatchActivateEvent(
@@ -264,8 +308,16 @@
   SetStatus(ACTIVATING);
   // TODO(kinuko): Implement.
   NOTIMPLEMENTED();
-  RunSoon(base::Bind(&HandleEventFinished, weak_factory_.GetWeakPtr(),
-                     -1 /* dummy message_id */, callback, ACTIVE, INSTALLED,
+  HandleInstallPhaseEventFinishedParameters params(
+      weak_factory_.GetWeakPtr(),
+      -1 /* dummy message_id */,
+      InstallPhaseEventFinishedMessageReader(),
+      callback,
+      ACTIVE,
+      INSTALLED,
+      SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
+  RunSoon(base::Bind(&HandleInstallPhaseEventFinished,
+                     params,
                      SERVICE_WORKER_OK,
                      IPC::Message(-1, -1, IPC::Message::PRIORITY_NORMAL)));
 }
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index d5463c4..5405268 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -122,14 +122,14 @@
   // Sends install event to the associated embedded worker and asynchronously
   // calls |callback| when it errors out or it gets response from the worker
   // to notify install completion.
-  // |active_version_embedded_worker_id| must be a valid positive ID
+  // |active_version_id| must be a valid positive ID
   // if there's an active (previous) version running.
   //
   // This must be called when the status() is NEW. Calling this changes
   // the version's status to INSTALLING.
   // Upon completion, the version's status will be changed to INSTALLED
   // on success, or back to NEW on failure.
-  void DispatchInstallEvent(int active_version_embedded_worker_id,
+  void DispatchInstallEvent(int active_version_id,
                             const StatusCallback& callback);
 
   // Sends activate event to the associated embedded worker and asynchronously
diff --git a/content/browser/session_history_browsertest.cc b/content/browser/session_history_browsertest.cc
index c1f0565..c4054b4 100644
--- a/content/browser/session_history_browsertest.cc
+++ b/content/browser/session_history_browsertest.cc
@@ -11,10 +11,10 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
diff --git a/content/browser/shared_worker/shared_worker_host.cc b/content/browser/shared_worker/shared_worker_host.cc
index eb58399..6018913 100644
--- a/content/browser/shared_worker/shared_worker_host.cc
+++ b/content/browser/shared_worker/shared_worker_host.cc
@@ -4,6 +4,7 @@
 
 #include "content/browser/shared_worker/shared_worker_host.h"
 
+#include "base/metrics/histogram.h"
 #include "content/browser/frame_host/render_frame_host_delegate.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/message_port_service.h"
@@ -31,12 +32,15 @@
 SharedWorkerHost::SharedWorkerHost(SharedWorkerInstance* instance)
     : instance_(instance),
       container_render_filter_(NULL),
-      worker_route_id_(MSG_ROUTING_NONE) {
+      worker_route_id_(MSG_ROUTING_NONE),
+      creation_time_(base::TimeTicks::Now()) {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
 }
 
 SharedWorkerHost::~SharedWorkerHost() {
   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+  UMA_HISTOGRAM_LONG_TIMES("SharedWorker.TimeToDeleted",
+                           base::TimeTicks::Now() - creation_time_);
   // If we crashed, tell the RenderViewHosts.
   if (instance_ && !instance_->load_failed()) {
     const WorkerDocumentSet::DocumentInfoSet& parents =
@@ -137,9 +141,13 @@
 
 void SharedWorkerHost::WorkerScriptLoaded() {
   // TODO(horo): implement this.
+  UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoaded",
+                      base::TimeTicks::Now() - creation_time_);
 }
 
 void SharedWorkerHost::WorkerScriptLoadFailed() {
+  UMA_HISTOGRAM_TIMES("SharedWorker.TimeToScriptLoadFailed",
+                      base::TimeTicks::Now() - creation_time_);
   if (!instance_)
     return;
   instance_->set_load_failed(true);
diff --git a/content/browser/shared_worker/shared_worker_host.h b/content/browser/shared_worker/shared_worker_host.h
index 4292d74..f46e3b2 100644
--- a/content/browser/shared_worker/shared_worker_host.h
+++ b/content/browser/shared_worker/shared_worker_host.h
@@ -9,6 +9,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
+#include "base/time/time.h"
 #include "content/browser/shared_worker/shared_worker_message_filter.h"
 
 class GURL;
@@ -88,6 +89,7 @@
   scoped_ptr<SharedWorkerInstance> instance_;
   SharedWorkerMessageFilter* container_render_filter_;
   int worker_route_id_;
+  const base::TimeTicks creation_time_;
   DISALLOW_COPY_AND_ASSIGN(SharedWorkerHost);
 };
 }  // namespace content
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 416b0dc..e90ec66 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -13,10 +13,10 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
 #include "url/gurl.h"
 
diff --git a/content/browser/speech/input_tag_speech_browsertest.cc b/content/browser/speech/input_tag_speech_browsertest.cc
index 10c1878..53529c4 100644
--- a/content/browser/speech/input_tag_speech_browsertest.cc
+++ b/content/browser/speech/input_tag_speech_browsertest.cc
@@ -16,11 +16,11 @@
 #include "content/public/common/speech_recognition_error.h"
 #include "content/public/common/speech_recognition_result.h"
 #include "content/public/common/url_constants.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/fake_speech_recognition_manager.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 
 namespace content {
diff --git a/content/browser/speech/input_tag_speech_dispatcher_host.cc b/content/browser/speech/input_tag_speech_dispatcher_host.cc
index e38f90f..dd6a4b2 100644
--- a/content/browser/speech/input_tag_speech_dispatcher_host.cc
+++ b/content/browser/speech/input_tag_speech_dispatcher_host.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/lazy_instance.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/speech/speech_recognition_manager_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
@@ -77,6 +78,17 @@
     const InputTagSpeechHostMsg_StartRecognition_Params& params) {
   InputTagSpeechHostMsg_StartRecognition_Params input_params(params);
   int render_process_id = render_process_id_;
+
+  // Check that the origin specified by the renderer process is one
+  // that it is allowed to access.
+  if (params.origin_url != "null" &&
+      !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+          render_process_id, GURL(params.origin_url))) {
+    LOG(ERROR) << "ITSDH::OnStartRecognition, disallowed origin: "
+               << params.origin_url;
+    return;
+  }
+
   // The chrome layer is mostly oblivious to BrowserPlugin guests and so it
   // cannot correctly place the speech bubble relative to a guest. Thus, we
   // set up the speech recognition context relative to the embedder.
diff --git a/content/browser/speech/proto/speech_proto.target.darwin-arm.mk b/content/browser/speech/proto/speech_proto.target.darwin-arm.mk
index 96eb2a1..e736de7 100644
--- a/content/browser/speech/proto/speech_proto.target.darwin-arm.mk
+++ b/content/browser/speech/proto/speech_proto.target.darwin-arm.mk
@@ -111,6 +111,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/content/browser/speech/proto/speech_proto.target.darwin-mips.mk b/content/browser/speech/proto/speech_proto.target.darwin-mips.mk
index 2f4b00a..10e119d 100644
--- a/content/browser/speech/proto/speech_proto.target.darwin-mips.mk
+++ b/content/browser/speech/proto/speech_proto.target.darwin-mips.mk
@@ -111,6 +111,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/content/browser/speech/proto/speech_proto.target.darwin-x86.mk b/content/browser/speech/proto/speech_proto.target.darwin-x86.mk
index ca63ca4..53c59b1 100644
--- a/content/browser/speech/proto/speech_proto.target.darwin-x86.mk
+++ b/content/browser/speech/proto/speech_proto.target.darwin-x86.mk
@@ -112,6 +112,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -203,6 +204,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/content/browser/speech/proto/speech_proto.target.darwin-x86_64.mk b/content/browser/speech/proto/speech_proto.target.darwin-x86_64.mk
new file mode 100644
index 0000000..5fccc82
--- /dev/null
+++ b/content/browser/speech/proto/speech_proto.target.darwin-x86_64.mk
@@ -0,0 +1,299 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_browser_speech_proto_speech_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "content_browser_speech_proto_speech_proto_gyp_speech_proto_target_genproto":
+# "{'inputs': ['../../../../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['google_streaming_api.proto'], 'action': ['python', '../../../../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', '.', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: $(LOCAL_PATH)/content/browser/speech/proto/google_streaming_api.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto; cd $(gyp_local_path)/content/browser/speech/proto; python ../../../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h" --proto-in-dir . --proto-in-file "google_streaming_api$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto" --python_out "$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto"
+
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py ;
+.PHONY: content_browser_speech_proto_speech_proto_gyp_rule_trigger
+content_browser_speech_proto_speech_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h \
+	content_browser_speech_proto_speech_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_speech_proto_speech_proto_gyp
+
+# Alias gyp target name.
+.PHONY: speech_proto
+speech_proto: content_browser_speech_proto_speech_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/browser/speech/proto/speech_proto.target.linux-arm.mk b/content/browser/speech/proto/speech_proto.target.linux-arm.mk
index 96eb2a1..e736de7 100644
--- a/content/browser/speech/proto/speech_proto.target.linux-arm.mk
+++ b/content/browser/speech/proto/speech_proto.target.linux-arm.mk
@@ -111,6 +111,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/content/browser/speech/proto/speech_proto.target.linux-mips.mk b/content/browser/speech/proto/speech_proto.target.linux-mips.mk
index 2f4b00a..10e119d 100644
--- a/content/browser/speech/proto/speech_proto.target.linux-mips.mk
+++ b/content/browser/speech/proto/speech_proto.target.linux-mips.mk
@@ -111,6 +111,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -202,6 +203,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/content/browser/speech/proto/speech_proto.target.linux-x86.mk b/content/browser/speech/proto/speech_proto.target.linux-x86.mk
index ca63ca4..53c59b1 100644
--- a/content/browser/speech/proto/speech_proto.target.linux-x86.mk
+++ b/content/browser/speech/proto/speech_proto.target.linux-x86.mk
@@ -112,6 +112,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -203,6 +204,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/content/browser/speech/proto/speech_proto.target.linux-x86_64.mk b/content/browser/speech/proto/speech_proto.target.linux-x86_64.mk
new file mode 100644
index 0000000..5fccc82
--- /dev/null
+++ b/content/browser/speech/proto/speech_proto.target.linux-x86_64.mk
@@ -0,0 +1,299 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_browser_speech_proto_speech_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "content_browser_speech_proto_speech_proto_gyp_speech_proto_target_genproto":
+# "{'inputs': ['../../../../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['google_streaming_api.proto'], 'action': ['python', '../../../../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', '.', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py: $(LOCAL_PATH)/content/browser/speech/proto/google_streaming_api.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto; cd $(gyp_local_path)/content/browser/speech/proto; python ../../../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h" --proto-in-dir . --proto-in-file "google_streaming_api$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto" --python_out "$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto"
+
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py ;
+.PHONY: content_browser_speech_proto_speech_proto_gyp_rule_trigger
+content_browser_speech_proto_speech_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/google_streaming_api.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/google_streaming_api.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/content/browser/speech/proto/google_streaming_api_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto/google_streaming_api.pb.h \
+	content_browser_speech_proto_speech_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/content/browser/speech/proto
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_browser_speech_proto_speech_proto_gyp
+
+# Alias gyp target name.
+.PHONY: speech_proto
+speech_proto: content_browser_speech_proto_speech_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/browser/speech/speech_recognition_browsertest.cc b/content/browser/speech/speech_recognition_browsertest.cc
index f97d222..e734843 100644
--- a/content/browser/speech/speech_recognition_browsertest.cc
+++ b/content/browser/speech/speech_recognition_browsertest.cc
@@ -15,10 +15,10 @@
 #include "content/public/browser/notification_types.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/mock_google_streaming_server.h"
 #include "media/audio/mock_audio_manager.h"
 #include "media/audio/test_audio_input_controller_factory.h"
diff --git a/content/browser/speech/speech_recognition_dispatcher_host.cc b/content/browser/speech/speech_recognition_dispatcher_host.cc
index fc6a69d..57b3bc6c 100644
--- a/content/browser/speech/speech_recognition_dispatcher_host.cc
+++ b/content/browser/speech/speech_recognition_dispatcher_host.cc
@@ -8,6 +8,7 @@
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "content/browser/browser_plugin/browser_plugin_guest.h"
+#include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/speech/speech_recognition_manager_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
@@ -74,6 +75,16 @@
     const SpeechRecognitionHostMsg_StartRequest_Params& params) {
   SpeechRecognitionHostMsg_StartRequest_Params input_params(params);
 
+  // Check that the origin specified by the renderer process is one
+  // that it is allowed to access.
+  if (params.origin_url != "null" &&
+      !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+          render_process_id_, GURL(params.origin_url))) {
+    LOG(ERROR) << "SRDH::OnStartRequest, disallowed origin: "
+               << params.origin_url;
+    return;
+  }
+
   int embedder_render_process_id = 0;
   int embedder_render_view_id = MSG_ROUTING_NONE;
   if (is_guest_) {
diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc
index e131968..a9d3de5 100644
--- a/content/browser/speech/speech_recognition_manager_impl.cc
+++ b/content/browser/speech/speech_recognition_manager_impl.cc
@@ -301,7 +301,8 @@
   SessionsTable::iterator iter = sessions_.find(session_id);
   if (iter->second->ui) {
     // Notify the UI that the devices are being used.
-    iter->second->ui->OnStarted(base::Closure());
+    iter->second->ui->OnStarted(base::Closure(),
+                                MediaStreamUIProxy::WindowIdCallback());
   }
 
   DCHECK_EQ(primary_session_id_, session_id);
diff --git a/content/browser/ssl/ssl_policy.cc b/content/browser/ssl/ssl_policy.cc
index 1127f8d..7316455 100644
--- a/content/browser/ssl/ssl_policy.cc
+++ b/content/browser/ssl/ssl_policy.cc
@@ -110,6 +110,9 @@
   if (!entry->GetURL().SchemeIsSecure())
     return;
 
+  if (!web_contents->DisplayedInsecureContent())
+    entry->GetSSL().content_status &= ~SSLStatus::DISPLAYED_INSECURE_CONTENT;
+
   // An HTTPS response may not have a certificate for some reason.  When that
   // happens, use the unauthenticated (HTTP) rather than the authentication
   // broken security style so that we can detect this error condition.
@@ -118,6 +121,9 @@
     return;
   }
 
+  if (web_contents->DisplayedInsecureContent())
+    entry->GetSSL().content_status |= SSLStatus::DISPLAYED_INSECURE_CONTENT;
+
   if (net::IsCertStatusError(entry->GetSSL().cert_status)) {
     // Minor errors don't lower the security style to
     // SECURITY_STYLE_AUTHENTICATION_BROKEN.
@@ -140,11 +146,6 @@
     entry->GetSSL().content_status |= SSLStatus::RAN_INSECURE_CONTENT;
     return;
   }
-
-  if (web_contents->DisplayedInsecureContent())
-    entry->GetSSL().content_status |= SSLStatus::DISPLAYED_INSECURE_CONTENT;
-  else
-    entry->GetSSL().content_status &= ~SSLStatus::DISPLAYED_INSECURE_CONTENT;
 }
 
 void SSLPolicy::OnAllowCertificate(scoped_refptr<SSLCertErrorHandler> handler,
diff --git a/content/browser/streams/stream.cc b/content/browser/streams/stream.cc
index ca0cf1b..d10770c 100644
--- a/content/browser/streams/stream.cc
+++ b/content/browser/streams/stream.cc
@@ -7,11 +7,13 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/values.h"
 #include "content/browser/streams/stream_handle_impl.h"
 #include "content/browser/streams/stream_read_observer.h"
 #include "content/browser/streams/stream_registry.h"
 #include "content/browser/streams/stream_write_observer.h"
 #include "net/base/io_buffer.h"
+#include "net/http/http_response_headers.h"
 
 namespace {
 // Start throttling the connection at about 1MB.
@@ -161,7 +163,7 @@
 scoped_ptr<StreamHandle> Stream::CreateHandle(
     const GURL& original_url,
     const std::string& mime_type,
-    const std::string& response_headers) {
+    scoped_refptr<net::HttpResponseHeaders> response_headers) {
   CHECK(!stream_handle_);
   stream_handle_ = new StreamHandleImpl(weak_ptr_factory_.GetWeakPtr(),
                                         original_url,
diff --git a/content/browser/streams/stream.h b/content/browser/streams/stream.h
index e439b72..e7e9586 100644
--- a/content/browser/streams/stream.h
+++ b/content/browser/streams/stream.h
@@ -13,6 +13,7 @@
 #include "url/gurl.h"
 
 namespace net {
+class HttpResponseHeaders;
 class IOBuffer;
 }
 
@@ -77,9 +78,10 @@
   // and STREAM_COMPLETE if the stream is finalized and all data has been read.
   StreamState ReadRawData(net::IOBuffer* buf, int buf_size, int* bytes_read);
 
-  scoped_ptr<StreamHandle> CreateHandle(const GURL& original_url,
-                                        const std::string& mime_type,
-                                        const std::string& response_headers);
+  scoped_ptr<StreamHandle> CreateHandle(
+      const GURL& original_url,
+      const std::string& mime_type,
+      scoped_refptr<net::HttpResponseHeaders> response_headers);
   void CloseHandle();
 
   // Indicates whether there is space in the buffer to add more data.
diff --git a/content/browser/streams/stream_handle_impl.cc b/content/browser/streams/stream_handle_impl.cc
index cdba12b..d13bdc6 100644
--- a/content/browser/streams/stream_handle_impl.cc
+++ b/content/browser/streams/stream_handle_impl.cc
@@ -8,13 +8,15 @@
 #include "base/location.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "content/browser/streams/stream.h"
+#include "net/http/http_response_headers.h"
 
 namespace content {
 
-StreamHandleImpl::StreamHandleImpl(const base::WeakPtr<Stream>& stream,
-                                   const GURL& original_url,
-                                   const std::string& mime_type,
-                                   const std::string& response_headers)
+StreamHandleImpl::StreamHandleImpl(
+    const base::WeakPtr<Stream>& stream,
+    const GURL& original_url,
+    const std::string& mime_type,
+    scoped_refptr<net::HttpResponseHeaders> response_headers)
     : stream_(stream),
       url_(stream->url()),
       original_url_(original_url),
@@ -39,7 +41,7 @@
   return mime_type_;
 }
 
-const std::string& StreamHandleImpl::GetResponseHeaders() {
+scoped_refptr<net::HttpResponseHeaders> StreamHandleImpl::GetResponseHeaders() {
   return response_headers_;
 }
 
diff --git a/content/browser/streams/stream_handle_impl.h b/content/browser/streams/stream_handle_impl.h
index deb094f..fc8f535 100644
--- a/content/browser/streams/stream_handle_impl.h
+++ b/content/browser/streams/stream_handle_impl.h
@@ -22,7 +22,7 @@
   StreamHandleImpl(const base::WeakPtr<Stream>& stream,
                    const GURL& original_url,
                    const std::string& mime_type,
-                   const std::string& response_headers);
+                   scoped_refptr<net::HttpResponseHeaders> response_headers);
   virtual ~StreamHandleImpl();
 
  private:
@@ -30,13 +30,13 @@
   virtual const GURL& GetURL() OVERRIDE;
   virtual const GURL& GetOriginalURL() OVERRIDE;
   virtual const std::string& GetMimeType() OVERRIDE;
-  virtual const std::string& GetResponseHeaders() OVERRIDE;
+  virtual scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders() OVERRIDE;
 
   base::WeakPtr<Stream> stream_;
   GURL url_;
   GURL original_url_;
   std::string mime_type_;
-  std::string response_headers_;
+  scoped_refptr<net::HttpResponseHeaders> response_headers_;
   base::MessageLoopProxy* stream_message_loop_;
 };
 
diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc
index 8449486..36f0dce 100644
--- a/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/content/browser/tracing/tracing_controller_browsertest.cc
@@ -6,9 +6,9 @@
 #include "base/run_loop.h"
 #include "content/browser/tracing/tracing_controller_impl.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 
 namespace content {
 
diff --git a/content/browser/web_contents/aura/image_window_delegate.cc b/content/browser/web_contents/aura/image_window_delegate.cc
index 440d557..0b40c0f 100644
--- a/content/browser/web_contents/aura/image_window_delegate.cc
+++ b/content/browser/web_contents/aura/image_window_delegate.cc
@@ -94,8 +94,4 @@
 void ImageWindowDelegate::GetHitTestMask(gfx::Path* mask) const {
 }
 
-void ImageWindowDelegate::DidRecreateLayer(ui::Layer *old_layer,
-                                           ui::Layer *new_layer) {
-}
-
 }  // namespace content
diff --git a/content/browser/web_contents/aura/image_window_delegate.h b/content/browser/web_contents/aura/image_window_delegate.h
index d0b9671..d0f9b06 100644
--- a/content/browser/web_contents/aura/image_window_delegate.h
+++ b/content/browser/web_contents/aura/image_window_delegate.h
@@ -43,8 +43,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
   virtual bool HasHitTestMask() const OVERRIDE;
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE;
 
  protected:
   gfx::Image image_;
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
index 8c47a7b..ac7b20c 100644
--- a/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
+++ b/content/browser/web_contents/aura/overscroll_navigation_overlay.cc
@@ -9,6 +9,7 @@
 #include "content/browser/web_contents/aura/image_window_delegate.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/common/view_messages.h"
+#include "content/public/browser/render_widget_host_view.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animation_observer.h"
@@ -236,29 +237,18 @@
   return CreateSlideLayer(1);
 }
 
-void OverscrollNavigationOverlay::OnWindowSlideComplete() {
-  if (slide_direction_ == SLIDE_UNKNOWN) {
-    window_slider_.reset();
-    StopObservingIfDone();
+void OverscrollNavigationOverlay::OnWindowSlideCompleting() {
+  if (slide_direction_ == SLIDE_UNKNOWN)
     return;
-  }
-
-  // Change the image used for the overlay window.
-  image_delegate_->SetImage(layer_delegate_->image());
-  window_->layer()->SetTransform(gfx::Transform());
-  window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size()));
-
-  SlideDirection direction = slide_direction_;
-  slide_direction_ = SLIDE_UNKNOWN;
 
   // Reset state and wait for the new navigation page to complete
   // loading/painting.
   StartObserving();
 
   // Perform the navigation.
-  if (direction == SLIDE_BACK)
+  if (slide_direction_ == SLIDE_BACK)
     web_contents_->GetController().GoBack();
-  else if (direction == SLIDE_FRONT)
+  else if (slide_direction_ == SLIDE_FRONT)
     web_contents_->GetController().GoForward();
   else
     NOTREACHED();
@@ -271,6 +261,34 @@
   pending_entry_id_ = pending_entry ? pending_entry->GetUniqueID() : 0;
 }
 
+void OverscrollNavigationOverlay::OnWindowSlideCompleted() {
+  if (slide_direction_ == SLIDE_UNKNOWN) {
+    window_slider_.reset();
+    StopObservingIfDone();
+    return;
+  }
+
+  // Change the image used for the overlay window.
+  image_delegate_->SetImage(layer_delegate_->image());
+  window_->layer()->SetTransform(gfx::Transform());
+  window_->SchedulePaintInRect(gfx::Rect(window_->bounds().size()));
+  slide_direction_ = SLIDE_UNKNOWN;
+
+  // Make sure the overlay layer is repainted before we dismiss it, otherwise
+  // OverlayDismissAnimator may end up showing the wrong screenshot during the
+  // fadeout animation.
+  if (received_paint_update_ && need_paint_update_) {
+    received_paint_update_ = false;
+    RenderWidgetHost* host =
+        web_contents_->GetRenderWidgetHostView()->GetRenderWidgetHost();
+    RenderViewHostImpl* view_host =
+        static_cast<RenderViewHostImpl*> (RenderViewHost::From(host));
+    view_host->ScheduleComposite();
+  } else if (!need_paint_update_) {
+    StopObservingIfDone();
+  }
+}
+
 void OverscrollNavigationOverlay::OnWindowSlideAborted() {
   StopObservingIfDone();
 }
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay.h b/content/browser/web_contents/aura/overscroll_navigation_overlay.h
index 68a60a2..32b8819 100644
--- a/content/browser/web_contents/aura/overscroll_navigation_overlay.h
+++ b/content/browser/web_contents/aura/overscroll_navigation_overlay.h
@@ -83,7 +83,8 @@
   // Overridden from WindowSlider::Delegate:
   virtual ui::Layer* CreateBackLayer() OVERRIDE;
   virtual ui::Layer* CreateFrontLayer() OVERRIDE;
-  virtual void OnWindowSlideComplete() OVERRIDE;
+  virtual void OnWindowSlideCompleting() OVERRIDE;
+  virtual void OnWindowSlideCompleted() OVERRIDE;
   virtual void OnWindowSlideAborted() OVERRIDE;
   virtual void OnWindowSliderDestroyed() OVERRIDE;
 
diff --git a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index f19d61e..463c795 100644
--- a/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -53,7 +53,8 @@
     delete GetOverlay()->CreateBackLayer();
     // Performs BACK navigation, sets image from layer_delegate_ on
     // image_delegate_.
-    GetOverlay()->OnWindowSlideComplete();
+    GetOverlay()->OnWindowSlideCompleting();
+    GetOverlay()->OnWindowSlideCompleted();
   }
 
  protected:
diff --git a/content/browser/web_contents/aura/window_slider.cc b/content/browser/web_contents/aura/window_slider.cc
index 14c3efb..61146e3 100644
--- a/content/browser/web_contents/aura/window_slider.cc
+++ b/content/browser/web_contents/aura/window_slider.cc
@@ -19,12 +19,6 @@
 
 namespace {
 
-void DeleteLayerAndShadow(ui::Layer* layer,
-                          ShadowLayerDelegate* shadow) {
-  delete shadow;
-  delete layer;
-}
-
 // An animation observer that runs a callback at the end of the animation, and
 // destroys itself.
 class CallbackAnimationObserver : public ui::ImplicitAnimationObserver {
@@ -56,6 +50,7 @@
     : delegate_(delegate),
       event_window_(event_window),
       owner_(owner),
+      active_animator_(NULL),
       delta_x_(0.f),
       weak_factory_(this),
       active_start_threshold_(0.f),
@@ -93,9 +88,7 @@
 
 bool WindowSlider::IsSlideInProgress() const {
   // if active_start_threshold_ is 0, it means that sliding hasn't been started
-  return active_start_threshold_ != 0 &&
-      (fabs(delta_x_) >= active_start_threshold_ || slider_.get() ||
-      weak_factory_.HasWeakPtrs());
+  return active_start_threshold_ != 0 && (slider_.get() || active_animator_);
 }
 
 void WindowSlider::SetupSliderLayer() {
@@ -110,6 +103,16 @@
 }
 
 void WindowSlider::UpdateForScroll(float x_offset, float y_offset) {
+  if (active_animator_) {
+    // If there is an active animation, complete it before processing the scroll
+    // so that the callbacks that are invoked on the Delegate are consistent.
+    // Completing the animation may destroy WindowSlider through the animation
+    // callback, so we can't continue processing the scroll event here.
+    delta_x_ += x_offset;
+    CompleteActiveAnimations();
+    return;
+  }
+
   float old_delta = delta_x_;
   delta_x_ += x_offset;
   if (fabs(delta_x_) < active_start_threshold_ && !slider_.get())
@@ -153,100 +156,96 @@
   translate_layer->SetTransform(transform);
 }
 
-void WindowSlider::UpdateForFling(float x_velocity, float y_velocity) {
+void WindowSlider::CompleteOrResetSlide() {
   if (!slider_.get())
     return;
 
   int width = owner_->bounds().width();
   float ratio = (fabs(delta_x_) - active_start_threshold_) / width;
   if (ratio < complete_threshold_) {
-    ResetScroll();
+    ResetSlide();
     return;
   }
 
   ui::Layer* sliding = delta_x_ < 0 ? slider_.get() : owner_->layer();
-  ui::ScopedLayerAnimationSettings settings(sliding->GetAnimator());
+  active_animator_ = sliding->GetAnimator();
+
+  ui::ScopedLayerAnimationSettings settings(active_animator_);
   settings.SetPreemptionStrategy(
       ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
   settings.SetTweenType(gfx::Tween::EASE_OUT);
   settings.AddObserver(new CallbackAnimationObserver(
-      base::Bind(&WindowSlider::CompleteWindowSlideAfterAnimation,
-                 weak_factory_.GetWeakPtr())));
+      base::Bind(&WindowSlider::SlideAnimationCompleted,
+                 weak_factory_.GetWeakPtr(),
+                 base::Passed(&slider_),
+                 base::Passed(&shadow_))));
 
   gfx::Transform transform;
   transform.Translate(delta_x_ < 0 ? 0 : width, 0);
+  delta_x_ = 0;
+  delegate_->OnWindowSlideCompleting();
   sliding->SetTransform(transform);
 }
 
-void WindowSlider::ResetScroll() {
+void WindowSlider::CompleteActiveAnimations() {
+  if (active_animator_)
+    active_animator_->StopAnimating();
+}
+
+void WindowSlider::ResetSlide() {
   if (!slider_.get())
     return;
 
-  // Do not trigger any callbacks if this animation replaces any in-progress
-  // animation.
-  weak_factory_.InvalidateWeakPtrs();
-
   // Reset the state of the sliding layer.
   if (slider_.get()) {
-    ui::Layer* layer = slider_.release();
-    ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
-    settings.SetPreemptionStrategy(
-        ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
-    settings.SetTweenType(gfx::Tween::EASE_OUT);
-
-    // Delete the layer and the shadow at the end of the animation.
-    settings.AddObserver(new CallbackAnimationObserver(
-        base::Bind(&DeleteLayerAndShadow,
-                   base::Unretained(layer),
-                   base::Unretained(shadow_.release()))));
-
+    ui::Layer* translate_layer;
     gfx::Transform transform;
-    transform.Translate(delta_x_ < 0 ? layer->bounds().width() : 0, 0);
-    layer->SetTransform(transform);
-  }
+    if (delta_x_ < 0) {
+      translate_layer = slider_.get();
+      transform.Translate(translate_layer->bounds().width(), 0);
+    } else {
+      translate_layer = owner_->layer();
+    }
 
-  // Reset the state of the main layer.
-  {
-    ui::ScopedLayerAnimationSettings settings(owner_->layer()->GetAnimator());
+    active_animator_ = translate_layer->GetAnimator();
+    ui::ScopedLayerAnimationSettings settings(active_animator_);
     settings.SetPreemptionStrategy(
         ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
     settings.SetTweenType(gfx::Tween::EASE_OUT);
     settings.AddObserver(new CallbackAnimationObserver(
-        base::Bind(&WindowSlider::AbortWindowSlideAfterAnimation,
-                   weak_factory_.GetWeakPtr())));
-    owner_->layer()->SetTransform(gfx::Transform());
-    owner_->layer()->SetLayerBrightness(0.f);
+        base::Bind(&WindowSlider::ResetSlideAnimationCompleted,
+                   weak_factory_.GetWeakPtr(),
+                   base::Passed(&slider_),
+                   base::Passed(&shadow_))));
+    translate_layer->SetTransform(transform);
   }
 
   delta_x_ = 0.f;
 }
 
-void WindowSlider::CancelScroll() {
-  ResetScroll();
+void WindowSlider::SlideAnimationCompleted(
+    scoped_ptr<ui::Layer> layer, scoped_ptr<ShadowLayerDelegate> shadow) {
+  active_animator_ = NULL;
+  shadow.reset();
+  layer.reset();
+  delegate_->OnWindowSlideCompleted();
 }
 
-void WindowSlider::CompleteWindowSlideAfterAnimation() {
-  weak_factory_.InvalidateWeakPtrs();
-  shadow_.reset();
-  slider_.reset();
-  delta_x_ = 0.f;
-
-  delegate_->OnWindowSlideComplete();
-}
-
-void WindowSlider::AbortWindowSlideAfterAnimation() {
-  weak_factory_.InvalidateWeakPtrs();
-
+void WindowSlider::ResetSlideAnimationCompleted(
+    scoped_ptr<ui::Layer> layer, scoped_ptr<ShadowLayerDelegate> shadow) {
+  active_animator_ = NULL;
+  shadow.reset();
+  layer.reset();
   delegate_->OnWindowSlideAborted();
 }
 
 void WindowSlider::OnKeyEvent(ui::KeyEvent* event) {
-  CancelScroll();
+  ResetSlide();
 }
 
 void WindowSlider::OnMouseEvent(ui::MouseEvent* event) {
   if (!(event->flags() & ui::EF_IS_SYNTHESIZED))
-    CancelScroll();
+    ResetSlide();
 }
 
 void WindowSlider::OnScrollEvent(ui::ScrollEvent* event) {
@@ -254,9 +253,9 @@
   if (event->type() == ui::ET_SCROLL)
     UpdateForScroll(event->x_offset_ordinal(), event->y_offset_ordinal());
   else if (event->type() == ui::ET_SCROLL_FLING_START)
-    UpdateForFling(event->x_offset_ordinal(), event->y_offset_ordinal());
+    CompleteOrResetSlide();
   else
-    CancelScroll();
+    ResetSlide();
   event->SetHandled();
 }
 
@@ -265,7 +264,7 @@
   const ui::GestureEventDetails& details = event->details();
   switch (event->type()) {
     case ui::ET_GESTURE_SCROLL_BEGIN:
-      ResetScroll();
+      CompleteActiveAnimations();
       break;
 
     case ui::ET_GESTURE_SCROLL_UPDATE:
@@ -273,17 +272,17 @@
       break;
 
     case ui::ET_GESTURE_SCROLL_END:
-      UpdateForFling(0.f, 0.f);
+      CompleteOrResetSlide();
       break;
 
     case ui::ET_SCROLL_FLING_START:
-      UpdateForFling(details.velocity_x(), details.velocity_y());
+      CompleteOrResetSlide();
       break;
 
     case ui::ET_GESTURE_PINCH_BEGIN:
     case ui::ET_GESTURE_PINCH_UPDATE:
     case ui::ET_GESTURE_PINCH_END:
-      CancelScroll();
+      ResetSlide();
       break;
 
     default:
@@ -293,7 +292,8 @@
   event->SetHandled();
 }
 
-void WindowSlider::OnWindowRemovingFromRootWindow(aura::Window* window) {
+void WindowSlider::OnWindowRemovingFromRootWindow(aura::Window* window,
+                                                  aura::Window* new_root) {
   if (window == event_window_) {
     window->RemoveObserver(this);
     window->RemovePreTargetHandler(this);
diff --git a/content/browser/web_contents/aura/window_slider.h b/content/browser/web_contents/aura/window_slider.h
index 0ebe792..6445883 100644
--- a/content/browser/web_contents/aura/window_slider.h
+++ b/content/browser/web_contents/aura/window_slider.h
@@ -10,6 +10,7 @@
 #include "base/memory/weak_ptr.h"
 #include "content/common/content_export.h"
 #include "ui/aura/window_observer.h"
+#include "ui/compositor/layer_animator.h"
 #include "ui/events/event_handler.h"
 
 namespace ui {
@@ -28,25 +29,33 @@
    public:
     virtual ~Delegate() {}
 
-    // Creates a layer to show in the background, as the window-layer slides
-    // with the scroll gesture.
+    // Creates a layer to show behind the window-layer. Called when the
+    // window-layer starts sliding out to reveal the layer underneath.
     // The WindowSlider takes ownership of the created layer.
     virtual ui::Layer* CreateBackLayer() = 0;
 
-    // Creates a layer to slide on top of the window-layer with the scroll
-    // gesture.
+    // Creates a layer to show on top of the window-layer. Called when the new
+    // layer needs to start sliding in on top of the window-layer.
     // The WindowSlider takes ownership of the created layer.
     virtual ui::Layer* CreateFrontLayer() = 0;
 
-    // Called when the slide is complete. Note that at the end of a completed
-    // slide, the window-layer may have been transformed. The callback here
-    // should reset the transform if necessary.
-    virtual void OnWindowSlideComplete() = 0;
-
     // Called when the slide is aborted. Note that when the slide is aborted,
     // the WindowSlider resets any transform it applied on the window-layer.
     virtual void OnWindowSlideAborted() = 0;
 
+    // Called when the slide is about to be complete. The delegate can take
+    // action with the assumption that slide will complete soon (within the
+    // duration of the final transition animation effect).
+    // This callback is always preceeded by CreateBackLayerAndSetAsTarget() or
+    // by CreateFrontLayerAndSetAsTarget() callback, and is guaranteed to be
+    // followed by the OnWindowSlideCompleted() callback.
+    virtual void OnWindowSlideCompleting() = 0;
+
+    // Called when the window slide completes. Note that at the end the
+    // window-layer may have been transformed. The callback here should reset
+    // the transform if necessary.
+    virtual void OnWindowSlideCompleted() = 0;
+
     // Called when the slider is destroyed.
     virtual void OnWindowSliderDestroyed() = 0;
   };
@@ -74,18 +83,25 @@
 
   void UpdateForScroll(float x_offset, float y_offset);
 
-  void UpdateForFling(float x_velocity, float y_velocity);
+  // Completes or resets the slide depending on whether the sliding layer
+  // passed the "complete slide threshold".
+  void CompleteOrResetSlide();
 
-  // Resets any in-progress slide.
-  void ResetScroll();
+  // Stops all slider-owned animations, progressing them to their end-points.
+  // Note that depending on the sate of the Delegate and the WindowSlider, this
+  // may destroy the WindowSlider through animation callbacks.
+  void CompleteActiveAnimations();
 
-  // Cancels any scroll/animation in progress.
-  void CancelScroll();
+  // Resets in-progress slide if any, and starts the animation of the slidden
+  // window to its original position.
+  void ResetSlide();
 
   // The following callbacks are triggered after an animation.
-  void CompleteWindowSlideAfterAnimation();
+  void SlideAnimationCompleted(scoped_ptr<ui::Layer> layer,
+                               scoped_ptr<ShadowLayerDelegate> shadow);
 
-  void AbortWindowSlideAfterAnimation();
+  void ResetSlideAnimationCompleted(scoped_ptr<ui::Layer> layer,
+                                    scoped_ptr<ShadowLayerDelegate> shadow);
 
   // Overridden from ui::EventHandler:
   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
@@ -94,7 +110,8 @@
   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
 
   // Overridden from aura::WindowObserver:
-  virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE;
+  virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
+                                              aura::Window* new_root) OVERRIDE;
 
   Delegate* delegate_;
 
@@ -109,6 +126,10 @@
   // destroy |owner_|.
   aura::Window* owner_;
 
+  // Set to the Animator of the currently active animation. If no animation is
+  // active, this is set to NULL.
+  ui::LayerAnimator* active_animator_;
+
   // The accumulated amount of horizontal scroll.
   float delta_x_;
 
diff --git a/content/browser/web_contents/aura/window_slider_unittest.cc b/content/browser/web_contents/aura/window_slider_unittest.cc
index ed41347..21a8d17 100644
--- a/content/browser/web_contents/aura/window_slider_unittest.cc
+++ b/content/browser/web_contents/aura/window_slider_unittest.cc
@@ -5,13 +5,19 @@
 #include "content/browser/web_contents/aura/window_slider.h"
 
 #include "base/bind.h"
+#include "base/time/time.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
 #include "ui/base/hit_test.h"
+#include "ui/compositor/scoped_animation_duration_scale_mode.h"
+#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/compositor/test/layer_animator_test_controller.h"
 #include "ui/events/event_processor.h"
+#include "ui/events/event_utils.h"
+#include "ui/gfx/frame_time.h"
 
 namespace content {
 
@@ -39,6 +45,28 @@
   window->reset(new_window);
 }
 
+void ConfirmSlideDuringScrollCallback(WindowSlider* slider,
+                                      ui::EventType type,
+                                      const gfx::Vector2dF& delta) {
+  static float total_delta_x = 0;
+  if (type == ui::ET_GESTURE_SCROLL_BEGIN)
+    total_delta_x = 0;
+
+  if (type == ui::ET_GESTURE_SCROLL_UPDATE) {
+    total_delta_x += delta.x();
+    if (total_delta_x >= 70)
+      EXPECT_TRUE(slider->IsSlideInProgress());
+  } else {
+    EXPECT_FALSE(slider->IsSlideInProgress());
+  }
+}
+
+void ConfirmNoSlideDuringScrollCallback(WindowSlider* slider,
+                                        ui::EventType type,
+                                        const gfx::Vector2dF& delta) {
+  EXPECT_FALSE(slider->IsSlideInProgress());
+}
+
 // The window delegate does not receive any events.
 class NoEventWindowDelegate : public aura::test::TestWindowDelegate {
  public:
@@ -59,16 +87,21 @@
       : can_create_layer_(true),
         created_back_layer_(false),
         created_front_layer_(false),
+        slide_completing_(false),
         slide_completed_(false),
         slide_aborted_(false),
         slider_destroyed_(false) {
   }
-  virtual ~WindowSliderDelegateTest() {}
+  virtual ~WindowSliderDelegateTest() {
+    // Make sure slide_completed() gets called if slide_completing() was called.
+    CHECK(!slide_completing_ || slide_completed_);
+  }
 
   void Reset() {
     can_create_layer_ = true;
     created_back_layer_ = false;
     created_front_layer_ = false;
+    slide_completing_ = false;
     slide_completed_ = false;
     slide_aborted_ = false;
     slider_destroyed_ = false;
@@ -80,6 +113,7 @@
 
   bool created_back_layer() const { return created_back_layer_; }
   bool created_front_layer() const { return created_front_layer_; }
+  bool slide_completing() const { return slide_completing_; }
   bool slide_completed() const { return slide_completed_; }
   bool slide_aborted() const { return slide_aborted_; }
   bool slider_destroyed() const { return slider_destroyed_; }
@@ -107,10 +141,14 @@
     return CreateLayerForTest();
   }
 
-  virtual void OnWindowSlideComplete() OVERRIDE {
+  virtual void OnWindowSlideCompleted() OVERRIDE {
     slide_completed_ = true;
   }
 
+  virtual void OnWindowSlideCompleting() OVERRIDE {
+    slide_completing_ = true;
+  }
+
   virtual void OnWindowSlideAborted() OVERRIDE {
     slide_aborted_ = true;
   }
@@ -123,6 +161,7 @@
   bool can_create_layer_;
   bool created_back_layer_;
   bool created_front_layer_;
+  bool slide_completing_;
   bool slide_completed_;
   bool slide_aborted_;
   bool slider_destroyed_;
@@ -159,8 +198,8 @@
 
  private:
   // Overridden from WindowSlider::Delegate:
-  virtual void OnWindowSlideComplete() OVERRIDE {
-    WindowSliderDelegateTest::OnWindowSlideComplete();
+  virtual void OnWindowSlideCompleted() OVERRIDE {
+    WindowSliderDelegateTest::OnWindowSlideCompleted();
     delete owner_;
   }
 
@@ -180,11 +219,14 @@
   // Generate a horizontal overscroll.
   WindowSlider* slider =
       new WindowSlider(&slider_delegate, root_window(), window.get());
-  generator.GestureScrollSequence(gfx::Point(10, 10),
-                                  gfx::Point(180, 10),
-                                  base::TimeDelta::FromMilliseconds(10),
-                                  10);
+  generator.GestureScrollSequenceWithCallback(
+      gfx::Point(10, 10),
+      gfx::Point(180, 10),
+      base::TimeDelta::FromMilliseconds(10),
+      10,
+      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
   EXPECT_TRUE(slider_delegate.created_back_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
   EXPECT_TRUE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_front_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
@@ -193,12 +235,15 @@
   slider_delegate.Reset();
   window->SetTransform(gfx::Transform());
 
-  // Generat a horizontal overscroll in the reverse direction.
-  generator.GestureScrollSequence(gfx::Point(180, 10),
-                                  gfx::Point(10, 10),
-                                  base::TimeDelta::FromMilliseconds(10),
-                                  10);
+  // Generate a horizontal overscroll in the reverse direction.
+  generator.GestureScrollSequenceWithCallback(
+      gfx::Point(180, 10),
+      gfx::Point(10, 10),
+      base::TimeDelta::FromMilliseconds(10),
+      10,
+      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
   EXPECT_TRUE(slider_delegate.created_front_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
   EXPECT_TRUE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_back_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
@@ -207,11 +252,14 @@
   slider_delegate.Reset();
 
   // Generate a vertical overscroll.
-  generator.GestureScrollSequence(gfx::Point(10, 10),
-                                  gfx::Point(10, 80),
-                                  base::TimeDelta::FromMilliseconds(10),
-                                  10);
+  generator.GestureScrollSequenceWithCallback(
+      gfx::Point(10, 10),
+      gfx::Point(10, 80),
+      base::TimeDelta::FromMilliseconds(10),
+      10,
+      base::Bind(&ConfirmNoSlideDuringScrollCallback, slider));
   EXPECT_FALSE(slider_delegate.created_back_layer());
+  EXPECT_FALSE(slider_delegate.slide_completing());
   EXPECT_FALSE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_front_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
@@ -220,13 +268,16 @@
 
   // Generate a horizontal scroll that starts overscroll, but doesn't scroll
   // enough to complete it.
-  generator.GestureScrollSequence(gfx::Point(10, 10),
-                                  gfx::Point(80, 10),
-                                  base::TimeDelta::FromMilliseconds(10),
-                                  10);
+  generator.GestureScrollSequenceWithCallback(
+      gfx::Point(10, 10),
+      gfx::Point(80, 10),
+      base::TimeDelta::FromMilliseconds(10),
+      10,
+      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
   EXPECT_TRUE(slider_delegate.created_back_layer());
   EXPECT_TRUE(slider_delegate.slide_aborted());
   EXPECT_FALSE(slider_delegate.created_front_layer());
+  EXPECT_FALSE(slider_delegate.slide_completing());
   EXPECT_FALSE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.slider_destroyed());
   EXPECT_FALSE(slider->IsSlideInProgress());
@@ -237,10 +288,11 @@
   EXPECT_TRUE(slider_delegate.slider_destroyed());
 }
 
-// Tests that the window slide is cancelled when a different type of event
+// Tests that the window slide is interrupted when a different type of event
 // happens.
 TEST_F(WindowSliderTest, WindowSlideIsCancelledOnEvent) {
   scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
+  window->SetBounds(gfx::Rect(0, 0, 400, 400));
   WindowSliderDelegateTest slider_delegate;
 
   ui::Event* events[] = {
@@ -270,6 +322,7 @@
     EXPECT_TRUE(slider_delegate.created_back_layer());
     EXPECT_TRUE(slider_delegate.slide_aborted());
     EXPECT_FALSE(slider_delegate.created_front_layer());
+    EXPECT_FALSE(slider_delegate.slide_completing());
     EXPECT_FALSE(slider_delegate.slide_completed());
     EXPECT_FALSE(slider_delegate.slider_destroyed());
     slider_delegate.Reset();
@@ -278,6 +331,112 @@
   EXPECT_TRUE(slider_delegate.slider_destroyed());
 }
 
+// Tests that the window slide can continue after it is interrupted by another
+// event if the user continues scrolling.
+TEST_F(WindowSliderTest, WindowSlideInterruptedThenContinues) {
+  scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
+  window->SetBounds(gfx::Rect(0, 0, 400, 400));
+  WindowSliderDelegateTest slider_delegate;
+
+  ui::ScopedAnimationDurationScaleMode normal_duration_(
+      ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+  ui::LayerAnimator* animator = window->layer()->GetAnimator();
+  gfx::AnimationContainerElement* element = animator;
+  animator->set_disable_timer_for_test(true);
+  ui::LayerAnimatorTestController test_controller(animator);
+
+  WindowSlider* slider =
+      new WindowSlider(&slider_delegate, root_window(), window.get());
+
+  ui::MouseEvent interrupt_event(ui::ET_MOUSE_MOVED,
+                                 gfx::Point(55, 10),
+                                 gfx::Point(55, 10),
+                                 0, 0);
+
+  aura::test::EventGenerator generator(root_window());
+
+  // Start the scroll sequence. Scroll forward so that |window|'s layer is the
+  // one animating.
+  const int kTouchId = 5;
+  ui::TouchEvent press(ui::ET_TOUCH_PRESSED,
+                       gfx::Point(10, 10),
+                       kTouchId,
+                       ui::EventTimeForNow());
+  generator.Dispatch(&press);
+
+  // First scroll event of the sequence.
+  ui::TouchEvent move1(ui::ET_TOUCH_MOVED,
+                       gfx::Point(100, 10),
+                       kTouchId,
+                       ui::EventTimeForNow());
+  generator.Dispatch(&move1);
+  EXPECT_TRUE(slider->IsSlideInProgress());
+  EXPECT_FALSE(animator->is_animating());
+  // Dispatch the event after the first scroll and confirm it interrupts the
+  // scroll and starts  the "reset slide" animation.
+  generator.Dispatch(&interrupt_event);
+  EXPECT_TRUE(slider->IsSlideInProgress());
+  EXPECT_TRUE(animator->is_animating());
+  EXPECT_TRUE(slider_delegate.created_back_layer());
+  // slide_aborted() should be false because the 'reset slide' animation
+  // hasn't completed yet.
+  EXPECT_FALSE(slider_delegate.slide_aborted());
+  EXPECT_FALSE(slider_delegate.created_front_layer());
+  EXPECT_FALSE(slider_delegate.slide_completing());
+  EXPECT_FALSE(slider_delegate.slide_completed());
+  EXPECT_FALSE(slider_delegate.slider_destroyed());
+  slider_delegate.Reset();
+
+  // Second scroll event of the sequence.
+  ui::TouchEvent move2(ui::ET_TOUCH_MOVED,
+                       gfx::Point(200, 10),
+                       kTouchId,
+                       ui::EventTimeForNow());
+  generator.Dispatch(&move2);
+  // The second scroll should instantly cause the animation to complete.
+  EXPECT_FALSE(animator->is_animating());
+  EXPECT_FALSE(slider_delegate.created_back_layer());
+  // The ResetScroll() animation was completed, so now slide_aborted()
+  // should be true.
+  EXPECT_TRUE(slider_delegate.slide_aborted());
+
+  // Third scroll event of the sequence.
+  ui::TouchEvent move3(ui::ET_TOUCH_MOVED,
+                       gfx::Point(300, 10),
+                       kTouchId,
+                       ui::EventTimeForNow());
+  generator.Dispatch(&move3);
+  // The third scroll should re-start the sliding.
+  EXPECT_TRUE(slider->IsSlideInProgress());
+  EXPECT_TRUE(slider_delegate.created_back_layer());
+
+  // Generate the release event, finishing the scroll sequence.
+  ui::TouchEvent release(ui::ET_TOUCH_RELEASED,
+                         gfx::Point(300, 10),
+                         kTouchId,
+                         ui::EventTimeForNow());
+  generator.Dispatch(&release);
+  // When the scroll gesture ends, the slide animation should start.
+  EXPECT_TRUE(slider->IsSlideInProgress());
+  EXPECT_TRUE(animator->is_animating());
+  EXPECT_TRUE(slider_delegate.slide_completing());
+  EXPECT_FALSE(slider_delegate.created_front_layer());
+  EXPECT_FALSE(slider_delegate.slide_completed());
+  EXPECT_FALSE(slider_delegate.slider_destroyed());
+
+  // Progress the animator to complete the slide animation.
+  ui::ScopedLayerAnimationSettings settings(animator);
+  base::TimeDelta duration = settings.GetTransitionDuration();
+  test_controller.StartThreadedAnimationsIfNeeded();
+  element->Step(gfx::FrameTime::Now() + duration);
+
+  EXPECT_TRUE(slider_delegate.slide_completed());
+  EXPECT_FALSE(slider_delegate.slider_destroyed());
+
+  window.reset();
+  EXPECT_TRUE(slider_delegate.slider_destroyed());
+}
+
 // Tests that the slide works correctly when the owner of the window changes
 // during the duration of the slide.
 TEST_F(WindowSliderTest, OwnerWindowChangesDuringWindowSlide) {
@@ -308,28 +467,37 @@
   EXPECT_NE(old_window, new_window);
 
   EXPECT_TRUE(slider_delegate.created_back_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
   EXPECT_TRUE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_front_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
   EXPECT_FALSE(slider_delegate.slider_destroyed());
 }
 
+// If the delegate doesn't create the layer to show while sliding, WindowSlider
+// shouldn't start the slide or change delegate's state in any way in response
+// to user input.
 TEST_F(WindowSliderTest, NoSlideWhenLayerCantBeCreated) {
   scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
   window->SetBounds(gfx::Rect(0, 0, 400, 400));
   WindowSliderDelegateTest slider_delegate;
   slider_delegate.SetCanCreateLayer(false);
+  WindowSlider* slider =
+      new WindowSlider(&slider_delegate, root_window(), window.get());
 
   aura::test::EventGenerator generator(root_window());
 
-  // Generate a horizontal overscroll.
-  scoped_ptr<WindowSlider> slider(
-      new WindowSlider(&slider_delegate, root_window(), window.get()));
-  generator.GestureScrollSequence(gfx::Point(10, 10),
-                                  gfx::Point(160, 10),
-                                  base::TimeDelta::FromMilliseconds(10),
-                                  10);
+  // No slide in progress should be reported during scroll since the layer
+  // wasn't created.
+  generator.GestureScrollSequenceWithCallback(
+      gfx::Point(10, 10),
+      gfx::Point(180, 10),
+      base::TimeDelta::FromMilliseconds(10),
+      1,
+      base::Bind(&ConfirmNoSlideDuringScrollCallback, slider));
+
   EXPECT_FALSE(slider_delegate.created_back_layer());
+  EXPECT_FALSE(slider_delegate.slide_completing());
   EXPECT_FALSE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_front_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
@@ -337,15 +505,21 @@
   window->SetTransform(gfx::Transform());
 
   slider_delegate.SetCanCreateLayer(true);
-  generator.GestureScrollSequence(gfx::Point(10, 10),
-                                  gfx::Point(160, 10),
-                                  base::TimeDelta::FromMilliseconds(10),
-                                  10);
+  generator.GestureScrollSequenceWithCallback(
+      gfx::Point(10, 10),
+      gfx::Point(180, 10),
+      base::TimeDelta::FromMilliseconds(10),
+      10,
+      base::Bind(&ConfirmSlideDuringScrollCallback, slider));
   EXPECT_TRUE(slider_delegate.created_back_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
   EXPECT_TRUE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_front_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
   EXPECT_FALSE(slider_delegate.slider_destroyed());
+
+  window.reset();
+  EXPECT_TRUE(slider_delegate.slider_destroyed());
 }
 
 // Tests that the owner window can be destroyed from |OnWindowSliderDestroyed()|
@@ -367,6 +541,7 @@
                                   base::TimeDelta::FromMilliseconds(10),
                                   10);
   EXPECT_TRUE(slider_delegate.created_back_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
   EXPECT_TRUE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_front_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
@@ -396,6 +571,7 @@
                                   base::TimeDelta::FromMilliseconds(10),
                                   10);
   EXPECT_TRUE(slider_delegate.created_back_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
   EXPECT_TRUE(slider_delegate.slide_completed());
   EXPECT_FALSE(slider_delegate.created_front_layer());
   EXPECT_FALSE(slider_delegate.slide_aborted());
@@ -406,4 +582,71 @@
   EXPECT_EQ(child_windows, root_window()->children().size());
 }
 
+// Test the scenario when two swipe gesture occur quickly one after another so
+// that the second swipe occurs while the transition animation triggered by the
+// first swipe is in progress.
+// The second swipe is supposed to instantly complete the animation caused by
+// the first swipe, ask the delegate to create a new layer, and animate it.
+TEST_F(WindowSliderTest, SwipeDuringSwipeAnimation) {
+  scoped_ptr<aura::Window> window(CreateNormalWindow(0, root_window(), NULL));
+  window->SetBounds(gfx::Rect(0, 0, 400, 400));
+  WindowSliderDelegateTest slider_delegate;
+  new WindowSlider(&slider_delegate, root_window(), window.get());
+
+  ui::ScopedAnimationDurationScaleMode normal_duration_(
+      ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
+  ui::LayerAnimator* animator = window->layer()->GetAnimator();
+  gfx::AnimationContainerElement* element = animator;
+  animator->set_disable_timer_for_test(true);
+  ui::LayerAnimatorTestController test_controller(animator);
+
+  aura::test::EventGenerator generator(root_window());
+
+  // Swipe forward so that |window|'s layer is the one animating.
+  generator.GestureScrollSequence(
+      gfx::Point(10, 10),
+      gfx::Point(180, 10),
+      base::TimeDelta::FromMilliseconds(10),
+      2);
+  EXPECT_TRUE(slider_delegate.created_back_layer());
+  EXPECT_FALSE(slider_delegate.slide_aborted());
+  EXPECT_FALSE(slider_delegate.created_front_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
+  EXPECT_FALSE(slider_delegate.slide_completed());
+  EXPECT_FALSE(slider_delegate.slider_destroyed());
+  ui::ScopedLayerAnimationSettings settings(animator);
+  base::TimeDelta duration = settings.GetTransitionDuration();
+  test_controller.StartThreadedAnimationsIfNeeded();
+  base::TimeTicks start_time1 =  gfx::FrameTime::Now();
+
+  element->Step(start_time1 + duration/2);
+  EXPECT_FALSE(slider_delegate.slide_completed());
+  slider_delegate.Reset();
+  // Generate another horizontal swipe while the animation from the previous
+  // swipe is in progress.
+  generator.GestureScrollSequence(
+      gfx::Point(10, 10),
+      gfx::Point(180, 10),
+      base::TimeDelta::FromMilliseconds(10),
+      2);
+  // Performing the second swipe should instantly complete the slide started
+  // by the first swipe and create a new layer.
+  EXPECT_TRUE(slider_delegate.created_back_layer());
+  EXPECT_FALSE(slider_delegate.slide_aborted());
+  EXPECT_FALSE(slider_delegate.created_front_layer());
+  EXPECT_TRUE(slider_delegate.slide_completing());
+  EXPECT_TRUE(slider_delegate.slide_completed());
+  EXPECT_FALSE(slider_delegate.slider_destroyed());
+  test_controller.StartThreadedAnimationsIfNeeded();
+  base::TimeTicks start_time2 =  gfx::FrameTime::Now();
+  slider_delegate.Reset();
+  element->Step(start_time2 + duration);
+  // The animation for the second slide should now be completed.
+  EXPECT_TRUE(slider_delegate.slide_completed());
+  slider_delegate.Reset();
+
+  window.reset();
+  EXPECT_TRUE(slider_delegate.slider_destroyed());
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/touch_editable_impl_aura.cc b/content/browser/web_contents/touch_editable_impl_aura.cc
index df07a00..8180afd 100644
--- a/content/browser/web_contents/touch_editable_impl_aura.cc
+++ b/content/browser/web_contents/touch_editable_impl_aura.cc
@@ -4,21 +4,21 @@
 
 #include "content/browser/web_contents/touch_editable_impl_aura.h"
 
+#include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_view_aura.h"
 #include "content/common/view_messages.h"
-#include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/browser/web_contents.h"
 #include "grit/ui_strings.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/ui_base_switches_util.h"
 #include "ui/gfx/range/range.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace content {
 
@@ -229,12 +229,11 @@
 
 void TouchEditableImplAura::SelectRect(const gfx::Point& start,
                                        const gfx::Point& end) {
-  if (!rwhva_)
+  RenderFrameHost* focused_frame = GetFocusedFrame();
+  if (!focused_frame)
     return;
 
-  RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
-      rwhva_->GetRenderWidgetHost());
-  host->SelectRange(start, end);
+  static_cast<RenderFrameHostImpl*>(focused_frame)->SelectRange(start, end);
 }
 
 void TouchEditableImplAura::MoveCaretTo(const gfx::Point& point) {
@@ -334,12 +333,9 @@
 }
 
 void TouchEditableImplAura::ExecuteCommand(int command_id, int event_flags) {
-  if (!rwhva_)
+  RenderFrameHost* focused_frame = GetFocusedFrame();
+  if (!focused_frame)
     return;
-  RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
-  RenderViewHost* rvh = RenderViewHost::From(host);
-  WebContents* wc = WebContents::FromRenderViewHost(rvh);
-  RenderFrameHost* focused_frame = wc->GetFocusedFrame();
   switch (command_id) {
     case IDS_APP_CUT:
       focused_frame->Cut();
@@ -351,10 +347,10 @@
       focused_frame->Paste();
       break;
     case IDS_APP_DELETE:
-      host->Delete();
+      focused_frame->Delete();
       break;
     case IDS_APP_SELECT_ALL:
-      host->SelectAll();
+      focused_frame->SelectAll();
       break;
     default:
       NOTREACHED();
@@ -388,4 +384,13 @@
   overscroll_in_progress_ = false;
 }
 
+RenderFrameHost* TouchEditableImplAura::GetFocusedFrame() {
+  if (!rwhva_)
+    return NULL;
+  RenderWidgetHost* host = rwhva_->GetRenderWidgetHost();
+  RenderViewHost* rvh = RenderViewHost::From(host);
+  WebContents* wc = WebContents::FromRenderViewHost(rvh);
+  return wc->GetFocusedFrame();
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/touch_editable_impl_aura.h b/content/browser/web_contents/touch_editable_impl_aura.h
index 8190b7c..332a053 100644
--- a/content/browser/web_contents/touch_editable_impl_aura.h
+++ b/content/browser/web_contents/touch_editable_impl_aura.h
@@ -21,6 +21,7 @@
 }
 
 namespace content {
+class RenderFrameHost;
 class TouchEditableImplAuraTest;
 
 // Aura specific implementation of ui::TouchEditable for a RenderWidgetHostView.
@@ -77,6 +78,8 @@
 
   void Cleanup();
 
+  RenderFrameHost* GetFocusedFrame();
+
   // Rectangles for the selection anchor and focus.
   gfx::Rect selection_anchor_rect_;
   gfx::Rect selection_focus_rect_;
diff --git a/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc b/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
index 876e3db..2a42dda 100644
--- a/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
+++ b/content/browser/web_contents/touch_editable_impl_aura_browsertest.cc
@@ -15,10 +15,10 @@
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 6eeef4b..005f768 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -332,6 +332,8 @@
       minimum_zoom_percent_(static_cast<int>(kMinimumZoomFactor * 100)),
       maximum_zoom_percent_(static_cast<int>(kMaximumZoomFactor * 100)),
       temporary_zoom_settings_(false),
+      totalPinchGestureAmount_(0),
+      currentPinchZoomStepDelta_(0),
       color_chooser_identifier_(0),
       render_view_message_source_(NULL),
       fullscreen_widget_routing_id_(MSG_ROUTING_NONE),
@@ -1215,6 +1217,44 @@
   return delegate_ && delegate_->PreHandleGestureEvent(this, event);
 }
 
+bool WebContentsImpl::HandleGestureEvent(
+    const blink::WebGestureEvent& event) {
+  // Some platforms (eg. Mac) send GesturePinch events for trackpad pinch-zoom.
+  // Use them to implement browser zoom, as for HandleWheelEvent above.
+  if (event.type == blink::WebInputEvent::GesturePinchUpdate &&
+      event.sourceDevice == blink::WebGestureEvent::Touchpad) {
+    // The scale difference necessary to trigger a zoom action. Derived from
+    // experimentation to find a value that feels reasonable.
+    const float kZoomStepValue = 0.6f;
+
+    // Find the (absolute) thresholds on either side of the current zoom factor,
+    // then convert those to actual numbers to trigger a zoom in or out.
+    // This logic deliberately makes the range around the starting zoom value
+    // for the gesture twice as large as the other ranges (i.e., the notches are
+    // at ..., -3*step, -2*step, -step, step, 2*step, 3*step, ... but not at 0)
+    // so that it's easier to get back to your starting point than it is to
+    // overshoot.
+    float nextStep = (abs(currentPinchZoomStepDelta_) + 1) * kZoomStepValue;
+    float backStep = abs(currentPinchZoomStepDelta_) * kZoomStepValue;
+    float zoomInThreshold = (currentPinchZoomStepDelta_ >= 0) ? nextStep
+        : -backStep;
+    float zoomOutThreshold = (currentPinchZoomStepDelta_ <= 0) ? -nextStep
+        : backStep;
+
+    totalPinchGestureAmount_ += event.data.pinchUpdate.scale;
+    if (totalPinchGestureAmount_ > zoomInThreshold) {
+      currentPinchZoomStepDelta_++;
+      delegate_->ContentsZoomChange(true);
+    } else if (totalPinchGestureAmount_ < zoomOutThreshold) {
+      currentPinchZoomStepDelta_--;
+      delegate_->ContentsZoomChange(false);
+    }
+    return true;
+  }
+
+  return false;
+}
+
 #if defined(OS_WIN)
 gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
   return accessible_parent_;
@@ -1400,7 +1440,7 @@
 
   if (delegate_) {
     delegate_->WebContentsCreated(
-        this, params.opener_frame_id, params.frame_name,
+        this, params.opener_render_frame_id, params.frame_name,
         params.target_url, new_contents);
   }
 
@@ -1668,8 +1708,19 @@
 
 bool WebContentsImpl::NavigateToPendingEntry(
     NavigationController::ReloadType reload_type) {
-  return frame_tree_.root()->navigator()->NavigateToPendingEntry(
-      frame_tree_.GetMainFrame(), reload_type);
+  FrameTreeNode* node = frame_tree_.root();
+
+  // If we are using --site-per-process, we should navigate in the FrameTreeNode
+  // specified in the pending entry.
+  NavigationEntryImpl* pending_entry =
+      NavigationEntryImpl::FromNavigationEntry(controller_.GetPendingEntry());
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
+      pending_entry->frame_tree_node_id() != -1) {
+    node = frame_tree_.FindByID(pending_entry->frame_tree_node_id());
+  }
+
+  return node->navigator()->NavigateToPendingEntry(
+      node->current_frame_host(), reload_type);
 }
 
 void WebContentsImpl::RenderFrameForInterstitialPageCreated(
@@ -2052,21 +2103,13 @@
 void WebContentsImpl::DidStartProvisionalLoad(
     RenderFrameHostImpl* render_frame_host,
     int parent_routing_id,
-    bool is_main_frame,
     const GURL& validated_url,
     bool is_error_page,
     bool is_iframe_srcdoc) {
+  bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
   if (is_main_frame)
     DidChangeLoadProgress(0);
 
-  // --site-per-process mode has a short-term hack allowing cross-process
-  // subframe pages to commit thinking they are top-level.  Correct it here to
-  // avoid confusing the observers.
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
-      render_frame_host != GetMainFrame()) {
-    is_main_frame = false;
-  }
-
   // Notify observers about the start of the provisional load.
   int render_frame_id = render_frame_host->GetRoutingID();
   RenderViewHost* render_view_host = render_frame_host->render_view_host();
@@ -2090,13 +2133,14 @@
     const FrameHostMsg_DidFailProvisionalLoadWithError_Params& params) {
   GURL validated_url(params.url);
   int render_frame_id = render_frame_host->GetRoutingID();
+  bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
   RenderViewHost* render_view_host = render_frame_host->render_view_host();
   FOR_EACH_OBSERVER(
       WebContentsObserver,
       observers_,
       DidFailProvisionalLoad(render_frame_id,
                              params.frame_unique_name,
-                             params.is_main_frame,
+                             is_main_frame,
                              validated_url,
                              params.error_code,
                              params.error_description,
@@ -2106,14 +2150,14 @@
 void WebContentsImpl::DidFailLoadWithError(
     RenderFrameHostImpl* render_frame_host,
     const GURL& url,
-    bool is_main_frame,
     int error_code,
     const base::string16& error_description) {
   int render_frame_id = render_frame_host->GetRoutingID();
+  bool is_main_frame = render_frame_host->frame_tree_node()->IsMainFrame();
   RenderViewHost* render_view_host = render_frame_host->render_view_host();
   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
                     DidFailLoad(render_frame_id, url, is_main_frame, error_code,
-                                error_description, render_view_host));;
+                                error_description, render_view_host));
 }
 
 void WebContentsImpl::NotifyChangedNavigationState(
@@ -2321,32 +2365,23 @@
 }
 
 void WebContentsImpl::OnDidFinishLoad(
-    const GURL& url,
-    bool is_main_frame) {
+    const GURL& url) {
   if (!render_frame_message_source_) {
     RecordAction(base::UserMetricsAction("BadMessageTerminate_RVD2"));
     GetRenderProcessHost()->ReceivedBadMessage();
     return;
   }
 
-  RenderFrameHostImpl* rfh =
-      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
-
-  // --site-per-process mode has a short-term hack allowing cross-process
-  // subframe pages to commit thinking they are top-level.  Correct it here to
-  // avoid confusing the observers.
-  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
-      rfh != GetMainFrame()) {
-    is_main_frame = false;
-  }
-
   GURL validated_url(url);
   RenderProcessHost* render_process_host =
       render_frame_message_source_->GetProcess();
   render_process_host->FilterURL(false, &validated_url);
 
+  RenderFrameHostImpl* rfh =
+      static_cast<RenderFrameHostImpl*>(render_frame_message_source_);
   int render_frame_id = rfh->GetRoutingID();
   RenderViewHost* render_view_host = rfh->render_view_host();
+  bool is_main_frame = rfh->frame_tree_node()->IsMainFrame();
   FOR_EACH_OBSERVER(WebContentsObserver, observers_,
                     DidFinishLoad(render_frame_id, validated_url,
                                   is_main_frame, render_view_host));
@@ -2619,6 +2654,7 @@
 // loading, or done loading.
 void WebContentsImpl::SetIsLoading(RenderViewHost* render_view_host,
                                    bool is_loading,
+                                   bool to_different_document,
                                    LoadNotificationDetails* details) {
   if (is_loading == is_loading_)
     return;
@@ -2637,7 +2673,7 @@
   waiting_for_response_ = is_loading;
 
   if (delegate_)
-    delegate_->LoadingStateChanged(this);
+    delegate_->LoadingStateChanged(this, to_different_document);
   NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
 
   std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
@@ -2907,7 +2943,7 @@
     dialog_manager_->CancelActiveAndPendingDialogs(this);
 
   ClearPowerSaveBlockers(rvh);
-  SetIsLoading(rvh, false, NULL);
+  SetIsLoading(rvh, false, true, NULL);
   NotifyDisconnected();
   SetIsCrashed(status, error_code);
   GetView()->OnTabCrashed(GetCrashedStatus(), crashed_error_code_);
@@ -3012,23 +3048,20 @@
     delegate_->CloseContents(this);
 }
 
-void WebContentsImpl::SwappedOut(RenderViewHost* rvh) {
-  if (rvh == GetRenderViewHost()) {
+void WebContentsImpl::SwappedOut(RenderFrameHost* rfh) {
+  // TODO(creis): Handle subframes that go fullscreen.
+  if (rfh->GetRenderViewHost() == GetRenderViewHost()) {
     // Exit fullscreen mode before the current RVH is swapped out.  For numerous
     // cases, there is no guarantee the renderer would/could initiate an exit.
     // Example: http://crbug.com/347232
     if (IsFullscreenForCurrentTab()) {
-      if (rvh)
-        rvh->ExitFullscreen();
+      rfh->GetRenderViewHost()->ExitFullscreen();
       DCHECK(!IsFullscreenForCurrentTab());
     }
 
     if (delegate_)
       delegate_->SwappedOut(this);
   }
-
-  // Allow the navigation to proceed.
-  GetRenderManager()->SwappedOut(rvh);
 }
 
 void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
@@ -3036,8 +3069,10 @@
     delegate_->MoveContents(this, new_bounds);
 }
 
-void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host) {
-  SetIsLoading(render_frame_host->GetRenderViewHost(), true, NULL);
+void WebContentsImpl::DidStartLoading(RenderFrameHost* render_frame_host,
+                                      bool to_different_document) {
+  SetIsLoading(render_frame_host->GetRenderViewHost(), true,
+               to_different_document, NULL);
 }
 
 void WebContentsImpl::DidStopLoading(RenderFrameHost* render_frame_host) {
@@ -3062,7 +3097,8 @@
         controller_.GetCurrentEntryIndex()));
   }
 
-  SetIsLoading(render_frame_host->GetRenderViewHost(), false, details.get());
+  SetIsLoading(render_frame_host->GetRenderViewHost(), false, true,
+               details.get());
 }
 
 void WebContentsImpl::DidCancelLoading() {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 7bbbce8..c1587c1 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -304,8 +304,10 @@
                                  const IPC::Message& message) OVERRIDE;
   virtual void RenderFrameCreated(RenderFrameHost* render_frame_host) OVERRIDE;
   virtual void RenderFrameDeleted(RenderFrameHost* render_frame_host) OVERRIDE;
-  virtual void DidStartLoading(RenderFrameHost* render_frame_host) OVERRIDE;
+  virtual void DidStartLoading(RenderFrameHost* render_frame_host,
+                               bool to_different_document) OVERRIDE;
   virtual void DidStopLoading(RenderFrameHost* render_frame_host) OVERRIDE;
+  virtual void SwappedOut(RenderFrameHost* render_frame_host) OVERRIDE;
   virtual void WorkerCrashed(RenderFrameHost* render_frame_host) OVERRIDE;
   virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
                                const ContextMenuParams& params) OVERRIDE;
@@ -340,7 +342,6 @@
   virtual void UpdateTargetURL(int32 page_id, const GURL& url) OVERRIDE;
   virtual void Close(RenderViewHost* render_view_host) OVERRIDE;
   virtual void RequestMove(const gfx::Rect& new_bounds) OVERRIDE;
-  virtual void SwappedOut(RenderViewHost* render_view_host) OVERRIDE;
   virtual void DidCancelLoading() OVERRIDE;
   virtual void DidChangeLoadProgress(double progress) OVERRIDE;
   virtual void DidDisownOpener(RenderViewHost* rvh) OVERRIDE;
@@ -432,7 +433,6 @@
   virtual void DidStartProvisionalLoad(
       RenderFrameHostImpl* render_frame_host,
       int parent_routing_id,
-      bool is_main_frame,
       const GURL& validated_url,
       bool is_error_page,
       bool is_iframe_srcdoc) OVERRIDE;
@@ -443,7 +443,6 @@
   virtual void DidFailLoadWithError(
       RenderFrameHostImpl* render_frame_host,
       const GURL& url,
-      bool is_main_frame,
       int error_code,
       const base::string16& error_description) OVERRIDE;
   virtual void DidRedirectProvisionalLoad(
@@ -488,6 +487,8 @@
       const blink::WebMouseWheelEvent& event) OVERRIDE;
   virtual bool PreHandleGestureEvent(
       const blink::WebGestureEvent& event) OVERRIDE;
+  virtual bool HandleGestureEvent(
+      const blink::WebGestureEvent& event) OVERRIDE;
   virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) OVERRIDE;
 #if defined(OS_WIN)
   virtual gfx::NativeViewAccessible GetParentNativeViewAccessible() OVERRIDE;
@@ -591,6 +592,7 @@
   // (but can be null if not applicable).
   virtual void SetIsLoading(RenderViewHost* render_view_host,
                             bool is_loading,
+                            bool to_different_document,
                             LoadNotificationDetails* details) OVERRIDE;
 
   typedef base::Callback<void(WebContents*)> CreatedCallback;
@@ -666,8 +668,7 @@
   void OnDidRunInsecureContent(const std::string& security_origin,
                                const GURL& target_url);
   void OnDocumentLoadedInFrame();
-  void OnDidFinishLoad(const GURL& url,
-                       bool is_main_frame);
+  void OnDidFinishLoad(const GURL& url);
   void OnGoToEntryAtOffset(int offset);
   void OnUpdateZoomLimits(int minimum_percent,
                           int maximum_percent,
@@ -987,6 +988,11 @@
   // remember it.
   bool temporary_zoom_settings_;
 
+  // The raw accumulated zoom value and the actual zoom increments made for an
+  // an in-progress pinch gesture.
+  float totalPinchGestureAmount_;
+  int currentPinchZoomStepDelta_;
+
   // The intrinsic size of the page.
   gfx::Size preferred_size_;
 
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 5194222..3949928 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/strings/utf_string_conversions.h"
 #include "base/values.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
@@ -16,10 +17,10 @@
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 
@@ -149,6 +150,31 @@
   gfx::Size rwhv_create_size_;
 };
 
+class LoadingStateChangedDelegate : public WebContentsDelegate {
+ public:
+  LoadingStateChangedDelegate()
+      : loadingStateChangedCount_(0)
+      , loadingStateToDifferentDocumentCount_(0) {
+  }
+
+  // WebContentsDelgate:
+  virtual void LoadingStateChanged(WebContents* contents,
+                                   bool to_different_document) OVERRIDE {
+      loadingStateChangedCount_++;
+      if (to_different_document)
+        loadingStateToDifferentDocumentCount_++;
+  }
+
+  int loadingStateChangedCount() const { return loadingStateChangedCount_; }
+  int loadingStateToDifferentDocumentCount() const {
+    return loadingStateToDifferentDocumentCount_;
+  }
+
+ private:
+  int loadingStateChangedCount_;
+  int loadingStateToDifferentDocumentCount_;
+};
+
 // See: http://crbug.com/298193
 #if defined(OS_WIN)
 #define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
@@ -233,7 +259,9 @@
 // TODO(shrikant): enable this for Windows when issue with
 // force-compositing-mode is resolved (http://crbug.com/281726).
 // For TOOLKIT_GTK failure, see http://crbug.com/351234.
-#if defined(OS_WIN) || defined(OS_ANDROID) || defined(TOOLKIT_GTK)
+// Also crashes under ThreadSanitizer, http://crbug.com/356758.
+#if defined(OS_WIN) || defined(OS_ANDROID) || defined(TOOLKIT_GTK) \
+    || defined(THREAD_SANITIZER)
 #define MAYBE_GetSizeForNewRenderView DISABLED_GetSizeForNewRenderView
 #else
 #define MAYBE_GetSizeForNewRenderView GetSizeForNewRenderView
@@ -385,4 +413,29 @@
   EXPECT_EQ(observer.last_rfh(), shell()->web_contents()->GetMainFrame());
 }
 
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+                       LoadingStateChangedForSameDocumentNavigation) {
+  ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
+  scoped_ptr<LoadingStateChangedDelegate> delegate(
+      new LoadingStateChangedDelegate());
+  shell()->web_contents()->SetDelegate(delegate.get());
+
+  LoadStopNotificationObserver load_observer(
+      &shell()->web_contents()->GetController());
+  TitleWatcher title_watcher(shell()->web_contents(),
+                             base::ASCIIToUTF16("pushState"));
+  NavigateToURL(shell(), embedded_test_server()->GetURL("/push_state.html"));
+  load_observer.Wait();
+  base::string16 title = title_watcher.WaitAndGetTitle();
+  ASSERT_EQ(title, base::ASCIIToUTF16("pushState"));
+
+  // LoadingStateChanged should be called 4 times: start and stop for the
+  // initial load of push_state.html, and start and stop for the "navigation"
+  // triggered by history.pushState(). However, the start notification for the
+  // history.pushState() navigation should set to_different_document to false.
+  EXPECT_EQ("pushState", shell()->web_contents()->GetURL().ref());
+  EXPECT_EQ(4, delegate->loadingStateChangedCount());
+  EXPECT_EQ(3, delegate->loadingStateToDifferentDocumentCount());
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc
index 35b29ee..a6a66bb 100644
--- a/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -2256,7 +2256,7 @@
   contents()->NavigateAndCommit(url_normalized);
 
   // Check that an IPC with about:whatever is correctly normalized.
-  contents()->TestDidFinishLoad(url_from_ipc, true);
+  contents()->TestDidFinishLoad(url_from_ipc);
 
   EXPECT_EQ(url_normalized, observer.last_url());
 
@@ -2268,7 +2268,7 @@
 
   // Check that an IPC with about:whatever is correctly normalized.
   other_contents->TestDidFailLoadWithError(
-      url_from_ipc, true, 1, base::string16());
+      url_from_ipc, 1, base::string16());
   EXPECT_EQ(url_normalized, other_observer.last_url());
 }
 
@@ -2430,4 +2430,54 @@
   contents()->SetDelegate(NULL);
 }
 
+// Tests that trackpad GesturePinchUpdate events get turned into browser zoom.
+TEST_F(WebContentsImplTest, HandleGestureEvent) {
+  using blink::WebGestureEvent;
+  using blink::WebInputEvent;
+
+  scoped_ptr<ContentsZoomChangedDelegate> delegate(
+      new ContentsZoomChangedDelegate());
+  contents()->SetDelegate(delegate.get());
+
+  const float kZoomStepValue = 0.6f;
+  blink::WebGestureEvent event = SyntheticWebGestureEventBuilder::Build(
+      WebInputEvent::GesturePinchUpdate, WebGestureEvent::Touchpad);
+
+  // A pinch less than the step value doesn't change the zoom level.
+  event.data.pinchUpdate.scale = kZoomStepValue * 0.8f;
+  EXPECT_TRUE(contents()->HandleGestureEvent(event));
+  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
+
+  // But repeating the event so the combined scale is greater does.
+  EXPECT_TRUE(contents()->HandleGestureEvent(event));
+  EXPECT_EQ(1, delegate->GetAndResetContentsZoomChangedCallCount());
+  EXPECT_TRUE(delegate->last_zoom_in());
+
+  // Pinching back out one step goes back to 100%.
+  event.data.pinchUpdate.scale = -kZoomStepValue;
+  EXPECT_TRUE(contents()->HandleGestureEvent(event));
+  EXPECT_EQ(1, delegate->GetAndResetContentsZoomChangedCallCount());
+  EXPECT_FALSE(delegate->last_zoom_in());
+
+  // Pinching out again doesn't zoom (step is twice as large around 100%).
+  EXPECT_TRUE(contents()->HandleGestureEvent(event));
+  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
+
+  // And again now it zooms once per step.
+  EXPECT_TRUE(contents()->HandleGestureEvent(event));
+  EXPECT_EQ(1, delegate->GetAndResetContentsZoomChangedCallCount());
+  EXPECT_FALSE(delegate->last_zoom_in());
+
+  // No other type of gesture event is handled by WebContentsImpl (for example
+  // a touchscreen pinch gesture).
+  event = SyntheticWebGestureEventBuilder::Build(
+      WebInputEvent::GesturePinchUpdate, WebGestureEvent::Touchscreen);
+  event.data.pinchUpdate.scale = kZoomStepValue * 3;
+  EXPECT_FALSE(contents()->HandleGestureEvent(event));
+  EXPECT_EQ(0, delegate->GetAndResetContentsZoomChangedCallCount());
+
+  // Ensure pointers to the delegate aren't kept beyond it's lifetime.
+  contents()->SetDelegate(NULL);
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index 76408a6..2092700 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -189,6 +189,10 @@
   }
 }
 
+void WebContentsViewAndroid::HidePopupMenu() {
+  // TODO(tkent): implement
+}
+
 void WebContentsViewAndroid::StartDragging(
     const DropData& drop_data,
     blink::WebDragOperationsMask allowed_ops,
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h
index aa2ef54..a5fb44c 100644
--- a/content/browser/web_contents/web_contents_view_android.h
+++ b/content/browser/web_contents/web_contents_view_android.h
@@ -66,6 +66,7 @@
                              const std::vector<MenuItem>& items,
                              bool right_aligned,
                              bool allow_multiple_selection) OVERRIDE;
+  virtual void HidePopupMenu() OVERRIDE;
   virtual void StartDragging(const DropData& drop_data,
                              blink::WebDragOperationsMask allowed_ops,
                              const gfx::ImageSkia& image,
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 361f43c..a671b3c 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -44,8 +44,6 @@
 #include "net/base/net_util.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/aura/client/aura_constants.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -68,6 +66,8 @@
 #include "ui/gfx/image/image_png_rep.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/screen.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/drag_drop_delegate.h"
 
 namespace content {
 WebContentsViewPort* CreateWebContentsView(
@@ -246,23 +246,26 @@
   DISALLOW_COPY_AND_ASSIGN(WebDragSourceAura);
 };
 
-#if defined(OS_WIN)
+#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
 // Fill out the OSExchangeData with a file contents, synthesizing a name if
 // necessary.
 void PrepareDragForFileContents(const DropData& drop_data,
                                 ui::OSExchangeData::Provider* provider) {
-  base::FilePath file_name(drop_data.file_description_filename);
+  base::FilePath file_name =
+      base::FilePath::FromUTF16Unsafe(drop_data.file_description_filename);
   // Images without ALT text will only have a file extension so we need to
   // synthesize one from the provided extension and URL.
   if (file_name.BaseName().RemoveExtension().empty()) {
-    const base::string16 extension = file_name.Extension();
+    const base::FilePath::StringType extension = file_name.Extension();
     // Retrieve the name from the URL.
-    file_name = base::FilePath(net::GetSuggestedFilename(
-        drop_data.url, "", "", "", "", "")).ReplaceExtension(extension);
+    file_name = net::GenerateFileName(drop_data.url, "", "", "", "", "")
+                    .ReplaceExtension(extension);
   }
   provider->SetFileContents(file_name, drop_data.file_contents);
 }
+#endif
 
+#if defined(OS_WIN)
 void PrepareDragForDownload(
     const DropData& drop_data,
     ui::OSExchangeData::Provider* provider,
@@ -321,17 +324,20 @@
                                                      download_file.get());
   provider->SetDownloadFileInfo(file_download);
 }
-#endif
+#endif  // defined(OS_WIN)
 
 // Utility to fill a ui::OSExchangeDataProvider object from DropData.
 void PrepareDragData(const DropData& drop_data,
                      ui::OSExchangeData::Provider* provider,
                      WebContentsImpl* web_contents) {
+  provider->MarkOriginatedFromRenderer();
 #if defined(OS_WIN)
   // Put download before file contents to prefer the download of a image over
   // its thumbnail link.
   if (!drop_data.download_metadata.empty())
     PrepareDragForDownload(drop_data, provider, web_contents);
+#endif
+#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
   // We set the file contents before the URL because the URL also sets file
   // contents (to a .URL shortcut).  We want to prefer file content data over
   // a shortcut so we add it first.
@@ -344,19 +350,8 @@
     provider->SetURL(drop_data.url, drop_data.url_title);
   if (!drop_data.html.string().empty())
     provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
-  if (!drop_data.filenames.empty()) {
-    std::vector<ui::OSExchangeData::FileInfo> filenames;
-    for (std::vector<DropData::FileInfo>::const_iterator it =
-             drop_data.filenames.begin();
-         it != drop_data.filenames.end(); ++it) {
-      filenames.push_back(
-          ui::OSExchangeData::FileInfo(
-              base::FilePath::FromUTF8Unsafe(base::UTF16ToUTF8(it->path)),
-              base::FilePath::FromUTF8Unsafe(
-                  base::UTF16ToUTF8(it->display_name))));
-    }
-    provider->SetFilenames(filenames);
-  }
+  if (!drop_data.filenames.empty())
+    provider->SetFilenames(drop_data.filenames);
   if (!drop_data.custom_data.empty()) {
     Pickle pickle;
     ui::WriteCustomDataToPickle(drop_data.custom_data, &pickle);
@@ -367,6 +362,8 @@
 
 // Utility to fill a DropData object from ui::OSExchangeData.
 void PrepareDropData(DropData* drop_data, const ui::OSExchangeData& data) {
+  drop_data->did_originate_from_renderer = data.DidOriginateFromRenderer();
+
   base::string16 plain_text;
   data.GetString(&plain_text);
   if (!plain_text.empty())
@@ -389,16 +386,7 @@
   if (html_base_url.is_valid())
     drop_data->html_base_url = html_base_url;
 
-  std::vector<ui::OSExchangeData::FileInfo> files;
-  if (data.GetFilenames(&files) && !files.empty()) {
-    for (std::vector<ui::OSExchangeData::FileInfo>::const_iterator
-             it = files.begin(); it != files.end(); ++it) {
-      drop_data->filenames.push_back(
-          DropData::FileInfo(
-              base::UTF8ToUTF16(it->path.AsUTF8Unsafe()),
-              base::UTF8ToUTF16(it->display_name.AsUTF8Unsafe())));
-    }
-  }
+  data.GetFilenames(&drop_data->filenames);
 
   Pickle pickle;
   if (data.GetPickledData(ui::Clipboard::GetWebCustomDataFormatType(), &pickle))
@@ -601,7 +589,8 @@
     }
   }
 
-  virtual void OnWindowRemovingFromRootWindow(aura::Window* window) OVERRIDE {
+  virtual void OnWindowRemovingFromRootWindow(aura::Window* window,
+                                              aura::Window* new_root) OVERRIDE {
     if (window == view_->window_) {
       window->GetHost()->RemoveObserver(this);
 #if defined(OS_WIN)
@@ -1154,17 +1143,6 @@
   }
 }
 
-void WebContentsViewAura::ShowPopupMenu(const gfx::Rect& bounds,
-                                        int item_height,
-                                        double item_font_size,
-                                        int selected_item,
-                                        const std::vector<MenuItem>& items,
-                                        bool right_aligned,
-                                        bool allow_multiple_selection) {
-  // External popup menus are only used on Mac and Android.
-  NOTIMPLEMENTED();
-}
-
 void WebContentsViewAura::StartDragging(
     const DropData& drop_data,
     blink::WebDragOperationsMask operations,
@@ -1441,10 +1419,6 @@
 void WebContentsViewAura::GetHitTestMask(gfx::Path* mask) const {
 }
 
-void WebContentsViewAura::DidRecreateLayer(ui::Layer *old_layer,
-                                           ui::Layer *new_layer) {
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // WebContentsViewAura, ui::EventHandler implementation:
 
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
index bef8648..e472a36 100644
--- a/content/browser/web_contents/web_contents_view_aura.h
+++ b/content/browser/web_contents/web_contents_view_aura.h
@@ -13,9 +13,9 @@
 #include "content/common/content_export.h"
 #include "content/port/browser/render_view_host_delegate_view.h"
 #include "content/port/browser/web_contents_view_port.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/compositor/layer_animation_observer.h"
+#include "ui/wm/public/drag_drop_delegate.h"
 
 namespace aura {
 class Window;
@@ -130,13 +130,6 @@
   // Overridden from RenderViewHostDelegateView:
   virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
                                const ContextMenuParams& params) OVERRIDE;
-  virtual void ShowPopupMenu(const gfx::Rect& bounds,
-                             int item_height,
-                             double item_font_size,
-                             int selected_item,
-                             const std::vector<MenuItem>& items,
-                             bool right_aligned,
-                             bool allow_multiple_selection) OVERRIDE;
   virtual void StartDragging(const DropData& drop_data,
                              blink::WebDragOperationsMask operations,
                              const gfx::ImageSkia& image,
@@ -175,8 +168,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
   virtual bool HasHitTestMask() const OVERRIDE;
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE;
 
   // Overridden from ui::EventHandler:
   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
diff --git a/content/browser/web_contents/web_contents_view_aura_browsertest.cc b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
index 4da3be8..adfebd1 100644
--- a/content/browser/web_contents/web_contents_view_aura_browsertest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_browsertest.cc
@@ -21,10 +21,10 @@
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "ui/aura/test/event_generator.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
@@ -380,7 +380,13 @@
 //  - interactively, when user does an overscroll gesture
 //  - interactively, when user navigates in history without the overscroll
 //    gesture.
-IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, OverscrollScreenshot) {
+#if defined(OS_WIN)
+// http://crbug.com/357311
+#define MAYBE_OverscrollScreenshot DISABLED_OverscrollScreenshot
+#else
+#define MAYBE_OverscrollScreenshot OverscrollScreenshot
+#endif
+IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest, MAYBE_OverscrollScreenshot) {
   // Disable the test for WinXP.  See http://crbug/294116.
 #if defined(OS_WIN)
   if (base::win::GetVersion() < base::win::VERSION_VISTA) {
@@ -478,10 +484,18 @@
   }
 }
 
+// Crashes under ThreadSanitizer, http://crbug.com/356758.
+#if defined(THREAD_SANITIZER)
+#define MAYBE_ScreenshotForSwappedOutRenderViews \
+    DISABLED_ScreenshotForSwappedOutRenderViews
+#else
+#define MAYBE_ScreenshotForSwappedOutRenderViews \
+    ScreenshotForSwappedOutRenderViews
+#endif
 // Tests that screenshot is taken correctly when navigation causes a
 // RenderViewHost to be swapped out.
 IN_PROC_BROWSER_TEST_F(WebContentsViewAuraTest,
-                       ScreenshotForSwappedOutRenderViews) {
+                       MAYBE_ScreenshotForSwappedOutRenderViews) {
   ASSERT_NO_FATAL_FAILURE(
       StartTestWithPage("files/overscroll_navigation.html"));
   // Create a new server with a different site.
diff --git a/content/browser/web_contents/web_contents_view_gtk.cc b/content/browser/web_contents/web_contents_view_gtk.cc
index 995f82d..1e77e9f 100644
--- a/content/browser/web_contents/web_contents_view_gtk.cc
+++ b/content/browser/web_contents/web_contents_view_gtk.cc
@@ -370,17 +370,6 @@
     DLOG(ERROR) << "Cannot show context menus without a delegate.";
 }
 
-void WebContentsViewGtk::ShowPopupMenu(const gfx::Rect& bounds,
-                                       int item_height,
-                                       double item_font_size,
-                                       int selected_item,
-                                       const std::vector<MenuItem>& items,
-                                       bool right_aligned,
-                                       bool allow_multiple_selection) {
-  // External popup menus are only used on Mac and Android.
-  NOTIMPLEMENTED();
-}
-
 // Render view DnD -------------------------------------------------------------
 
 void WebContentsViewGtk::StartDragging(const DropData& drop_data,
diff --git a/content/browser/web_contents/web_contents_view_gtk.h b/content/browser/web_contents/web_contents_view_gtk.h
index d536f65..ad575a3 100644
--- a/content/browser/web_contents/web_contents_view_gtk.h
+++ b/content/browser/web_contents/web_contents_view_gtk.h
@@ -74,13 +74,6 @@
   // Backend implementation of RenderViewHostDelegateView.
   virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
                                const ContextMenuParams& params) OVERRIDE;
-  virtual void ShowPopupMenu(const gfx::Rect& bounds,
-                             int item_height,
-                             double item_font_size,
-                             int selected_item,
-                             const std::vector<MenuItem>& items,
-                             bool right_aligned,
-                             bool allow_multiple_selection) OVERRIDE;
   virtual void StartDragging(const DropData& drop_data,
                              blink::WebDragOperationsMask allowed_ops,
                              const gfx::ImageSkia& image,
diff --git a/content/browser/web_contents/web_contents_view_guest.cc b/content/browser/web_contents/web_contents_view_guest.cc
index 8fbc909..8c30825 100644
--- a/content/browser/web_contents/web_contents_view_guest.cc
+++ b/content/browser/web_contents/web_contents_view_guest.cc
@@ -243,17 +243,6 @@
 #endif  // defined(USE_AURA) || defined(OS_WIN)
 }
 
-void WebContentsViewGuest::ShowPopupMenu(const gfx::Rect& bounds,
-                                         int item_height,
-                                         double item_font_size,
-                                         int selected_item,
-                                         const std::vector<MenuItem>& items,
-                                         bool right_aligned,
-                                         bool allow_multiple_selection) {
-  // External popup menus are only used on Mac and Android.
-  NOTIMPLEMENTED();
-}
-
 void WebContentsViewGuest::StartDragging(
     const DropData& drop_data,
     WebDragOperationsMask ops,
diff --git a/content/browser/web_contents/web_contents_view_guest.h b/content/browser/web_contents/web_contents_view_guest.h
index 3493231..aaa35c3 100644
--- a/content/browser/web_contents/web_contents_view_guest.h
+++ b/content/browser/web_contents/web_contents_view_guest.h
@@ -80,13 +80,6 @@
   // Backend implementation of RenderViewHostDelegateView.
   virtual void ShowContextMenu(RenderFrameHost* render_frame_host,
                                const ContextMenuParams& params) OVERRIDE;
-  virtual void ShowPopupMenu(const gfx::Rect& bounds,
-                             int item_height,
-                             double item_font_size,
-                             int selected_item,
-                             const std::vector<MenuItem>& items,
-                             bool right_aligned,
-                             bool allow_multiple_selection) OVERRIDE;
   virtual void StartDragging(const DropData& drop_data,
                              blink::WebDragOperationsMask allowed_ops,
                              const gfx::ImageSkia& image,
diff --git a/content/browser/web_contents/web_contents_view_mac.h b/content/browser/web_contents/web_contents_view_mac.h
index be6df61..c738c74 100644
--- a/content/browser/web_contents/web_contents_view_mac.h
+++ b/content/browser/web_contents/web_contents_view_mac.h
@@ -25,6 +25,7 @@
 @class WebDragSource;
 
 namespace content {
+class PopupMenuHelper;
 class WebContentsImpl;
 class WebContentsViewDelegate;
 class WebContentsViewMac;
@@ -108,6 +109,7 @@
                              const std::vector<MenuItem>& items,
                              bool right_aligned,
                              bool allow_multiple_selection) OVERRIDE;
+  virtual void HidePopupMenu() OVERRIDE;
   virtual void StartDragging(const DropData& drop_data,
                              blink::WebDragOperationsMask allowed_operations,
                              const gfx::ImageSkia& image,
@@ -155,6 +157,8 @@
   // Underlay view has |overlay_view_| set to this view.
   WebContentsViewMac* underlay_view_;
 
+  scoped_ptr<PopupMenuHelper> popup_menu_helper_;
+
   DISALLOW_COPY_AND_ASSIGN(WebContentsViewMac);
 };
 
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index 93e7c31..5da7917 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -248,10 +248,17 @@
     const std::vector<MenuItem>& items,
     bool right_aligned,
     bool allow_multiple_selection) {
-  PopupMenuHelper popup_menu_helper(web_contents_->GetRenderViewHost());
-  popup_menu_helper.ShowPopupMenu(bounds, item_height, item_font_size,
-                                  selected_item, items, right_aligned,
-                                  allow_multiple_selection);
+  popup_menu_helper_.reset(
+      new PopupMenuHelper(web_contents_->GetRenderViewHost()));
+  popup_menu_helper_->ShowPopupMenu(bounds, item_height, item_font_size,
+                                    selected_item, items, right_aligned,
+                                    allow_multiple_selection);
+  popup_menu_helper_.reset();
+}
+
+void WebContentsViewMac::HidePopupMenu() {
+  if (popup_menu_helper_)
+    popup_menu_helper_->Hide();
 }
 
 gfx::Rect WebContentsViewMac::GetViewBounds() const {
diff --git a/content/browser/web_contents/web_drag_dest_gtk.cc b/content/browser/web_contents/web_drag_dest_gtk.cc
index d3b9ff8..34a61c3 100644
--- a/content/browser/web_contents/web_drag_dest_gtk.cc
+++ b/content/browser/web_contents/web_drag_dest_gtk.cc
@@ -121,7 +121,10 @@
     // text/plain with file URLs when dragging files, we want to handle
     // text/uri-list after text/plain so that the plain text can be cleared if
     // it's a file drag.
+    // Similarly, renderer taint must occur before anything else so we can
+    // ignore potentially forged filenames when handling text/uri-list.
     static int supported_targets[] = {
+      ui::RENDERER_TAINT,
       ui::TEXT_PLAIN,
       ui::TEXT_URI_LIST,
       ui::TEXT_HTML,
@@ -182,7 +185,9 @@
   if (raw_data && data_length > 0) {
     // If the source can't provide us with valid data for a requested target,
     // raw_data will be NULL.
-    if (target == ui::GetAtomForTarget(ui::TEXT_PLAIN)) {
+    if (target == ui::GetAtomForTarget(ui::RENDERER_TAINT)) {
+      drop_data_->did_originate_from_renderer = true;
+    } else if (target == ui::GetAtomForTarget(ui::TEXT_PLAIN)) {
       guchar* text = gtk_selection_data_get_text(data);
       if (text) {
         drop_data_->text = base::NullableString16(
@@ -204,8 +209,7 @@
           if (url.SchemeIs(kFileScheme) &&
               net::FileURLToFilePath(url, &file_path)) {
             drop_data_->filenames.push_back(
-                DropData::FileInfo(base::UTF8ToUTF16(file_path.value()),
-                                   base::string16()));
+                ui::FileInfo(file_path, base::FilePath()));
             // This is a hack. Some file managers also populate text/plain with
             // a file URL when dragging files, so we clear it to avoid exposing
             // it to the web content.
diff --git a/content/browser/web_contents/web_drag_dest_mac.mm b/content/browser/web_contents/web_drag_dest_mac.mm
index 8768bed..b0cb8e2 100644
--- a/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/content/browser/web_contents/web_drag_dest_mac.mm
@@ -253,6 +253,9 @@
   DCHECK(pboard);
   NSArray* types = [pboard types];
 
+  data->did_originate_from_renderer =
+      [types containsObject:ui::kChromeDragDummyPboardType];
+
   // Get URL if possible. To avoid exposing file system paths to web content,
   // filenames in the drag are not converted to file URLs.
   ui::PopulateURLAndTitleFromPasteboard(&data->url,
@@ -288,9 +291,9 @@
         BOOL exists = [[NSFileManager defaultManager]
                            fileExistsAtPath:filename];
         if (exists) {
-          data->filenames.push_back(
-              DropData::FileInfo(
-                  base::SysNSStringToUTF16(filename), base::string16()));
+          data->filenames.push_back(ui::FileInfo(
+              base::FilePath::FromUTF8Unsafe(base::SysNSStringToUTF8(filename)),
+              base::FilePath()));
         }
       }
     }
diff --git a/content/browser/web_contents/web_drag_source_gtk.cc b/content/browser/web_contents/web_drag_source_gtk.cc
index a515e23..68a79f9 100644
--- a/content/browser/web_contents/web_drag_source_gtk.cc
+++ b/content/browser/web_contents/web_drag_source_gtk.cc
@@ -79,7 +79,7 @@
     return false;
   }
 
-  int targets_mask = 0;
+  int targets_mask = ui::RENDERER_TAINT;
 
   if (!drop_data.text.string().empty())
     targets_mask |= ui::TEXT_PLAIN;
@@ -285,6 +285,17 @@
       break;
     }
 
+    case ui::RENDERER_TAINT: {
+      static const char kPlaceholder[] = "x";
+      gtk_selection_data_set(
+          selection_data,
+          ui::GetAtomForTarget(ui::RENDERER_TAINT),
+          kBitsPerByte,
+          reinterpret_cast<const guchar*>(kPlaceholder),
+          strlen(kPlaceholder));
+      break;
+    }
+
     default:
       NOTREACHED();
   }
diff --git a/content/browser/webkit_browsertest.cc b/content/browser/webkit_browsertest.cc
index 5394f5b..d4b6015 100644
--- a/content/browser/webkit_browsertest.cc
+++ b/content/browser/webkit_browsertest.cc
@@ -4,9 +4,9 @@
 
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/web_contents.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "content/test/net/url_request_abort_on_end_job.h"
 
 namespace content {
diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc
index d6cff75..3531988 100644
--- a/content/browser/webui/web_ui_data_source_impl.cc
+++ b/content/browser/webui/web_ui_data_source_impl.cc
@@ -10,15 +10,45 @@
 #include "base/memory/ref_counted_memory.h"
 #include "base/strings/string_util.h"
 #include "content/public/common/content_client.h"
+#include "grit/content_resources.h"
 #include "ui/base/webui/jstemplate_builder.h"
 #include "ui/base/webui/web_ui_util.h"
 
+#if defined(USE_MOJO)
+#include "mojo/public/bindings/js/constants.h"
+#endif
+
 namespace content {
 
+// static
 WebUIDataSource* WebUIDataSource::Create(const std::string& source_name) {
   return new WebUIDataSourceImpl(source_name);
 }
 
+#if defined(USE_MOJO)
+// static
+WebUIDataSource* WebUIDataSource::AddMojoDataSource(
+    BrowserContext* browser_context) {
+  WebUIDataSource* mojo_source = Create("mojo");
+
+  static const struct {
+    const char* path;
+    int id;
+  } resources[] = {
+    { mojo::kCodecModuleName, IDR_MOJO_CODEC_JS },
+    { mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS },
+    { mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS },
+    { mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS },
+  };
+  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(resources); ++i)
+    mojo_source->AddResourcePath(resources[i].path, resources[i].id);
+
+  URLDataManager::AddWebUIDataSource(browser_context, mojo_source);
+  return mojo_source;
+}
+#endif
+
+// static
 void WebUIDataSource::Add(BrowserContext* browser_context,
                           WebUIDataSource* source) {
   URLDataManager::AddWebUIDataSource(browser_context, source);
diff --git a/content/browser/webui/web_ui_impl.cc b/content/browser/webui/web_ui_impl.cc
index dda934a..596caa0 100644
--- a/content/browser/webui/web_ui_impl.cc
+++ b/content/browser/webui/web_ui_impl.cc
@@ -10,11 +10,12 @@
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/renderer_host/dip_util.h"
 #include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/browser/webui/web_ui_controller_factory_registry.h"
 #include "content/common/view_messages.h"
 #include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents_view.h"
 #include "content/public/browser/web_ui_controller.h"
 #include "content/public/browser/web_ui_message_handler.h"
@@ -127,8 +128,8 @@
   bindings_ = bindings;
 }
 
-void WebUIImpl::SetFrameXPath(const std::string& xpath) {
-  frame_xpath_ = xpath;
+void WebUIImpl::OverrideJavaScriptFrame(const std::string& frame_name) {
+  frame_name_ = frame_name;
 }
 
 WebUIController* WebUIImpl::GetController() const {
@@ -228,9 +229,33 @@
 }
 
 void WebUIImpl::ExecuteJavascript(const base::string16& javascript) {
-  static_cast<RenderViewHostImpl*>(
-      web_contents_->GetRenderViewHost())->ExecuteJavascriptInWebFrame(
-      base::ASCIIToUTF16(frame_xpath_), javascript);
+  RenderFrameHost* target_frame = TargetFrame();
+  if (target_frame)
+    target_frame->ExecuteJavaScript(javascript);
+}
+
+RenderFrameHost* WebUIImpl::TargetFrame() {
+  if (frame_name_.empty())
+    return web_contents_->GetMainFrame();
+
+  std::set<RenderFrameHost*> frame_set;
+  web_contents_->ForEachFrame(base::Bind(&WebUIImpl::AddToSetIfFrameNameMatches,
+                                         base::Unretained(this),
+                                         &frame_set));
+
+  // It happens that some sub-pages attempt to send JavaScript messages before
+  // their frames are loaded.
+  DCHECK_GE(1U, frame_set.size());
+  if (frame_set.empty())
+    return NULL;
+  return *frame_set.begin();
+}
+
+void WebUIImpl::AddToSetIfFrameNameMatches(
+    std::set<RenderFrameHost*>* frame_set,
+    RenderFrameHost* host) {
+  if (host->GetFrameName() == frame_name_)
+    frame_set->insert(host);
 }
 
 }  // namespace content
diff --git a/content/browser/webui/web_ui_impl.h b/content/browser/webui/web_ui_impl.h
index 8715e43..b718dad 100644
--- a/content/browser/webui/web_ui_impl.h
+++ b/content/browser/webui/web_ui_impl.h
@@ -6,6 +6,7 @@
 #define CONTENT_BROWSER_WEBUI_WEB_UI_IMPL_H_
 
 #include <map>
+#include <set>
 
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_vector.h"
@@ -14,6 +15,7 @@
 #include "ipc/ipc_listener.h"
 
 namespace content {
+class RenderFrameHost;
 class RenderViewHost;
 
 class CONTENT_EXPORT WebUIImpl : public WebUI,
@@ -39,7 +41,7 @@
   virtual void SetLinkTransitionType(PageTransition type) OVERRIDE;
   virtual int GetBindings() const OVERRIDE;
   virtual void SetBindings(int bindings) OVERRIDE;
-  virtual void SetFrameXPath(const std::string& xpath) OVERRIDE;
+  virtual void OverrideJavaScriptFrame(const std::string& frame_name) OVERRIDE;
   virtual void AddMessageHandler(WebUIMessageHandler* handler) OVERRIDE;
   typedef base::Callback<void(const base::ListValue*)> MessageCallback;
   virtual void RegisterMessageCallback(
@@ -77,9 +79,19 @@
                    const std::string& message,
                    const base::ListValue& args);
 
-  // Execute a string of raw Javascript on the page.
+  // Execute a string of raw JavaScript on the page.
   void ExecuteJavascript(const base::string16& javascript);
 
+  // Finds the frame in which to execute JavaScript (the one specified by
+  // OverrideJavaScriptFrame). May return NULL if no frame of the specified name
+  // exists in the page.
+  RenderFrameHost* TargetFrame();
+
+  // A helper function for TargetFrame; adds a frame to the specified set if its
+  // name matches frame_name_.
+  void AddToSetIfFrameNameMatches(std::set<RenderFrameHost*>* frame_set,
+                                  RenderFrameHost* host);
+
   // A map of message name -> message handling callback.
   typedef std::map<std::string, MessageCallback> MessageCallbackMap;
   MessageCallbackMap message_callbacks_;
@@ -97,9 +109,9 @@
   // Non-owning pointer to the WebContents this WebUI is associated with.
   WebContents* web_contents_;
 
-  // The path for the iframe this WebUI is embedded in (empty if not in an
-  // iframe).
-  std::string frame_xpath_;
+  // The name of the iframe this WebUI is embedded in (empty if not explicitly
+  // overridden with OverrideJavaScriptFrame).
+  std::string frame_name_;
 
   scoped_ptr<WebUIController> controller_;
 
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc
new file mode 100644
index 0000000..ccef178
--- /dev/null
+++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -0,0 +1,197 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "content/browser/webui/web_ui_controller_factory_registry.h"
+#include "content/common/mojo/mojo_channel_init.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
+#include "grit/content_resources.h"
+#include "mojo/public/bindings/js/constants.h"
+#include "mojo/public/bindings/remote_ptr.h"
+
+namespace content {
+namespace {
+
+bool got_message = false;
+
+// Returns the path to the mojom js bindings file.
+base::FilePath GetFilePathForJSResource(const std::string& path) {
+  std::string binding_path = "gen/" + path + ".js";
+#if defined(OS_WIN)
+  std::string tmp;
+  base::ReplaceChars(binding_path, "//", "\\", &tmp);
+  binding_path.swap(tmp);
+#endif
+  base::FilePath file_path;
+  PathService::Get(CHILD_PROCESS_EXE, &file_path);
+  return file_path.DirName().AppendASCII(binding_path);
+}
+
+// The bindings for the page are generated from a .mojom file. This code looks
+// up the generated file from disk and returns it.
+bool GetResource(const std::string& id,
+                 const WebUIDataSource::GotDataCallback& callback) {
+  // These are handled by the WebUIDataSource that AddMojoDataSource() creates.
+  if (id == mojo::kCodecModuleName ||
+      id == mojo::kConnectionModuleName ||
+      id == mojo::kConnectorModuleName ||
+      id == mojo::kRouterModuleName)
+    return false;
+
+  std::string contents;
+  CHECK(base::ReadFileToString(GetFilePathForJSResource(id), &contents,
+                               std::string::npos));
+  base::RefCountedString* ref_contents = new base::RefCountedString;
+  ref_contents->data() = contents;
+  callback.Run(ref_contents);
+  return true;
+}
+
+// BrowserTarget implementation that quits a RunLoop when BrowserTarget::Test()
+// is called.
+class BrowserTargetImpl : public mojo::BrowserTarget {
+ public:
+  BrowserTargetImpl(mojo::ScopedRendererTargetHandle handle,
+                    base::RunLoop* run_loop)
+      : client_(handle.Pass(), this),
+        run_loop_(run_loop) {
+    client_->Test();
+  }
+  virtual ~BrowserTargetImpl() {}
+
+  // mojo::BrowserTarget overrides:
+  virtual void Test() OVERRIDE {
+    got_message = true;
+    run_loop_->Quit();
+  }
+
+ private:
+  mojo::RemotePtr<mojo::RendererTarget> client_;
+
+  base::RunLoop* run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl);
+};
+
+// WebUIController that sets up mojo bindings. Additionally it creates the
+// BrowserTarget implementation at the right time.
+class TestWebUIController : public WebUIController {
+ public:
+  explicit TestWebUIController(WebUI* web_ui, base::RunLoop* run_loop)
+      : WebUIController(web_ui),
+        run_loop_(run_loop) {
+    content::WebUIDataSource* data_source =
+        WebUIDataSource::AddMojoDataSource(
+            web_ui->GetWebContents()->GetBrowserContext());
+    data_source->SetRequestFilter(base::Bind(&GetResource));
+  }
+
+  // WebUIController overrides:
+  virtual void RenderViewCreated(RenderViewHost* render_view_host) OVERRIDE {
+    mojo::InterfacePipe<mojo::BrowserTarget, mojo::RendererTarget> pipe;
+    browser_target_.reset(
+        new BrowserTargetImpl(pipe.handle_to_peer.Pass(), run_loop_));
+    render_view_host->SetWebUIHandle(
+        mojo::ScopedMessagePipeHandle(pipe.handle_to_self.release()));
+  }
+
+ private:
+  base::RunLoop* run_loop_;
+
+  scoped_ptr<BrowserTargetImpl> browser_target_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestWebUIController);
+};
+
+// WebUIControllerFactory that creates TestWebUIController.
+class TestWebUIControllerFactory : public WebUIControllerFactory {
+ public:
+  TestWebUIControllerFactory() : run_loop_(NULL) {}
+
+  void set_run_loop(base::RunLoop* run_loop) { run_loop_ = run_loop; }
+
+  virtual WebUIController* CreateWebUIControllerForURL(
+      WebUI* web_ui, const GURL& url) const OVERRIDE {
+    return new TestWebUIController(web_ui, run_loop_);
+  }
+  virtual WebUI::TypeID GetWebUIType(BrowserContext* browser_context,
+      const GURL& url) const OVERRIDE {
+    return reinterpret_cast<WebUI::TypeID>(1);
+  }
+  virtual bool UseWebUIForURL(BrowserContext* browser_context,
+                              const GURL& url) const OVERRIDE {
+    return true;
+  }
+  virtual bool UseWebUIBindingsForURL(BrowserContext* browser_context,
+                                      const GURL& url) const OVERRIDE {
+    return true;
+  }
+
+ private:
+  base::RunLoop* run_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestWebUIControllerFactory);
+};
+
+class WebUIMojoTest : public ContentBrowserTest {
+ public:
+  WebUIMojoTest() {
+    WebUIControllerFactory::RegisterFactory(&factory_);
+  }
+
+  virtual ~WebUIMojoTest() {
+    WebUIControllerFactory::UnregisterFactoryForTesting(&factory_);
+  }
+
+  TestWebUIControllerFactory* factory() { return &factory_; }
+
+ private:
+  TestWebUIControllerFactory factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebUIMojoTest);
+};
+
+// Loads a webui page that contains mojo bindings and verifies a message makes
+// it from the browser to the page and back.
+IN_PROC_BROWSER_TEST_F(WebUIMojoTest, EndToEnd) {
+  // Currently there is no way to have a generated file included in the isolate
+  // files. If the bindings file doesn't exist assume we're on such a bot and
+  // pass.
+  // TODO(sky): remove this conditional when isolates support copying from gen.
+  const base::FilePath test_file_path(
+      GetFilePathForJSResource(
+          "content/test/data/web_ui_test_mojo_bindings.mojom"));
+  if (!base::PathExists(test_file_path)) {
+    LOG(WARNING) << " mojom binding file doesn't exist, assuming on isolate";
+    return;
+  }
+
+  got_message = false;
+  ASSERT_TRUE(test_server()->Start());
+  base::RunLoop run_loop;
+  factory()->set_run_loop(&run_loop);
+  GURL test_url(test_server()->GetURL("files/web_ui_mojo.html"));
+  NavigateToURL(shell(), test_url);
+  // RunLoop is quit when message received from page.
+  run_loop.Run();
+  EXPECT_TRUE(got_message);
+}
+
+}  // namespace
+}  // namespace content
diff --git a/content/browser/worker_host/test/worker_browsertest.cc b/content/browser/worker_host/test/worker_browsertest.cc
index 4884d03..fd352eb 100644
--- a/content/browser/worker_host/test/worker_browsertest.cc
+++ b/content/browser/worker_host/test/worker_browsertest.cc
@@ -16,12 +16,12 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/test_data_directory.h"
 #include "net/test/spawned_test_server/spawned_test_server.h"
 #include "url/gurl.h"
diff --git a/content/browser/worker_host/worker_process_host.cc b/content/browser/worker_host/worker_process_host.cc
index 24abf8e..4fb67e8 100644
--- a/content/browser/worker_host/worker_process_host.cc
+++ b/content/browser/worker_host/worker_process_host.cc
@@ -323,7 +323,8 @@
       new IndexedDBDispatcherHost(partition_.indexed_db_context()));
 }
 
-void WorkerProcessHost::CreateWorker(const WorkerInstance& instance) {
+void WorkerProcessHost::CreateWorker(const WorkerInstance& instance,
+                                     bool pause_on_start) {
   ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
       process_->GetData().id, instance.url());
 
@@ -334,6 +335,7 @@
   params.name = instance.name();
   params.content_security_policy = instance.content_security_policy();
   params.security_policy_type = instance.security_policy_type();
+  params.pause_on_start = pause_on_start;
   params.route_id = instance.worker_route_id();
   Send(new WorkerProcessMsg_CreateWorker(params));
 
diff --git a/content/browser/worker_host/worker_process_host.h b/content/browser/worker_host/worker_process_host.h
index c363168..10ea12a 100644
--- a/content/browser/worker_host/worker_process_host.h
+++ b/content/browser/worker_host/worker_process_host.h
@@ -170,7 +170,7 @@
   bool Init(int render_process_id, int render_frame_id);
 
   // Creates a worker object in the process.
-  void CreateWorker(const WorkerInstance& instance);
+  void CreateWorker(const WorkerInstance& instance, bool pause_on_start);
 
   // Returns true iff the given message from a renderer process was forwarded to
   // the worker.
diff --git a/content/browser/worker_host/worker_service_impl.cc b/content/browser/worker_host/worker_service_impl.cc
index d17f440..5064544 100644
--- a/content/browser/worker_host/worker_service_impl.cc
+++ b/content/browser/worker_host/worker_service_impl.cc
@@ -409,12 +409,13 @@
     return false;
   }
 
-  worker->CreateWorker(instance);
+  worker->CreateWorker(
+      instance,
+      WorkerDevToolsManager::GetInstance()->WorkerCreated(worker, instance));
   FOR_EACH_OBSERVER(
       WorkerServiceObserver, observers_,
       WorkerCreated(instance.url(), instance.name(), worker->GetData().id,
                     instance.worker_route_id()));
-  WorkerDevToolsManager::GetInstance()->WorkerCreated(worker, instance);
   return true;
 }
 
diff --git a/content/child/blink_platform_impl.cc b/content/child/blink_platform_impl.cc
index e648dd6..c47d31b 100644
--- a/content/child/blink_platform_impl.cc
+++ b/content/child/blink_platform_impl.cc
@@ -24,11 +24,18 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/sys_info.h"
 #include "base/time/time.h"
 #include "content/child/content_child_helpers.h"
+#include "content/child/fling_curve_configuration.h"
+#include "content/child/web_discardable_memory_impl.h"
 #include "content/child/web_socket_stream_handle_impl.h"
 #include "content/child/web_url_loader_impl.h"
+#include "content/child/webcrypto/webcrypto_impl.h"
+#include "content/child/websocket_bridge.h"
+#include "content/child/webthread_impl.h"
+#include "content/child/worker_task_runner.h"
 #include "content/public/common/content_client.h"
 #include "grit/blink_resources.h"
 #include "grit/webkit_resources.h"
@@ -38,10 +45,13 @@
 #include "net/base/net_errors.h"
 #include "third_party/WebKit/public/platform/WebData.h"
 #include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebWaitableEvent.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "ui/base/layout.h"
 
 #if defined(OS_ANDROID)
 #include "base/android/sys_utils.h"
+#include "content/child/fling_animator_impl_android.h"
 #endif
 
 #if !defined(NO_TCMALLOC) && defined(USE_TCMALLOC) && !defined(OS_WIN)
@@ -49,15 +59,36 @@
 #endif
 
 using blink::WebData;
+using blink::WebFallbackThemeEngine;
 using blink::WebLocalizedString;
 using blink::WebString;
 using blink::WebSocketStreamHandle;
+using blink::WebThemeEngine;
 using blink::WebURL;
 using blink::WebURLError;
 using blink::WebURLLoader;
 
+namespace content {
+
 namespace {
 
+class WebWaitableEventImpl : public blink::WebWaitableEvent {
+ public:
+  WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {}
+  virtual ~WebWaitableEventImpl() {}
+
+  virtual void wait() { impl_->Wait(); }
+  virtual void signal() { impl_->Signal(); }
+
+  base::WaitableEvent* impl() {
+    return impl_.get();
+  }
+
+ private:
+  scoped_ptr<base::WaitableEvent> impl_;
+  DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl);
+};
+
 // A simple class to cache the memory usage for a given amount of time.
 class MemoryUsageCache {
  public:
@@ -108,8 +139,6 @@
 
 }  // namespace
 
-namespace content {
-
 static int ToMessageID(WebLocalizedString::Name name) {
   switch (name) {
     case WebLocalizedString::AXAMPMFieldText:
@@ -349,27 +378,29 @@
       shared_timer_func_(NULL),
       shared_timer_fire_time_(0.0),
       shared_timer_fire_time_was_set_while_suspended_(false),
-      shared_timer_suspended_(0) {}
+      shared_timer_suspended_(0),
+      fling_curve_configuration_(new FlingCurveConfiguration),
+      current_thread_slot_(&DestroyCurrentThread) {}
 
 BlinkPlatformImpl::~BlinkPlatformImpl() {
 }
 
 WebURLLoader* BlinkPlatformImpl::createURLLoader() {
-  return new WebURLLoaderImpl(this);
+  return new WebURLLoaderImpl;
 }
 
 WebSocketStreamHandle* BlinkPlatformImpl::createSocketStreamHandle() {
-  return new WebSocketStreamHandleImpl(this);
+  return new WebSocketStreamHandleImpl;
+}
+
+blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
+  return new WebSocketBridge;
 }
 
 WebString BlinkPlatformImpl::userAgent() {
   return WebString::fromUTF8(GetContentClient()->GetUserAgent());
 }
 
-WebString BlinkPlatformImpl::userAgent(const WebURL& url) {
-  return userAgent();
-}
-
 WebData BlinkPlatformImpl::parseDataURL(const WebURL& url,
                                         WebString& mimetype_out,
                                         WebString& charset_out) {
@@ -388,6 +419,41 @@
   return WebURLLoaderImpl::CreateError(unreachableURL, false, net::ERR_ABORTED);
 }
 
+blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
+  return new WebThreadImpl(name);
+}
+
+blink::WebThread* BlinkPlatformImpl::currentThread() {
+  WebThreadImplForMessageLoop* thread =
+      static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get());
+  if (thread)
+    return (thread);
+
+  scoped_refptr<base::MessageLoopProxy> message_loop =
+      base::MessageLoopProxy::current();
+  if (!message_loop.get())
+    return NULL;
+
+  thread = new WebThreadImplForMessageLoop(message_loop.get());
+  current_thread_slot_.Set(thread);
+  return thread;
+}
+
+blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() {
+  return new WebWaitableEventImpl();
+}
+
+blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents(
+    const blink::WebVector<blink::WebWaitableEvent*>& web_events) {
+  std::vector<base::WaitableEvent*> events;
+  for (size_t i = 0; i < web_events.size(); ++i)
+    events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl());
+  size_t idx = base::WaitableEvent::WaitMany(
+      vector_as_array(&events), events.size());
+  DCHECK_LT(idx, web_events.size());
+  return web_events[idx];
+}
+
 void BlinkPlatformImpl::decrementStatsCounter(const char* name) {
   base::StatsCounter(name).Decrement();
 }
@@ -479,13 +545,11 @@
 
 namespace {
 
-WebData loadAudioSpatializationResource(BlinkPlatformImpl* platform,
-                                        const char* name) {
+WebData loadAudioSpatializationResource(const char* name) {
 #ifdef IDR_AUDIO_SPATIALIZATION_COMPOSITE
   if (!strcmp(name, "Composite")) {
-    base::StringPiece resource =
-        platform->GetDataResource(IDR_AUDIO_SPATIALIZATION_COMPOSITE,
-                                  ui::SCALE_FACTOR_NONE);
+    base::StringPiece resource = GetContentClient()->GetDataResource(
+        IDR_AUDIO_SPATIALIZATION_COMPOSITE, ui::SCALE_FACTOR_NONE);
     return WebData(resource.data(), resource.size());
   }
 #endif
@@ -528,9 +592,8 @@
   if (is_azimuth_index_good && is_elevation_index_good &&
       is_resource_index_good) {
     const int kFirstAudioResourceIndex = IDR_AUDIO_SPATIALIZATION_T000_P000;
-    base::StringPiece resource =
-        platform->GetDataResource(kFirstAudioResourceIndex + resource_index,
-                                  ui::SCALE_FACTOR_NONE);
+    base::StringPiece resource = GetContentClient()->GetDataResource(
+        kFirstAudioResourceIndex + resource_index, ui::SCALE_FACTOR_NONE);
     return WebData(resource.data(), resource.size());
   }
 #endif  // IDR_AUDIO_SPATIALIZATION_T000_P000
@@ -654,15 +717,14 @@
   // Check the name prefix to see if it's an audio resource.
   if (StartsWithASCII(name, "IRC_Composite", true) ||
       StartsWithASCII(name, "Composite", true))
-    return loadAudioSpatializationResource(this, name);
+    return loadAudioSpatializationResource(name);
 
   // TODO(flackr): We should use a better than linear search here, a trie would
   // be ideal.
   for (size_t i = 0; i < arraysize(kDataResources); ++i) {
     if (!strcmp(name, kDataResources[i].name)) {
-      base::StringPiece resource =
-          GetDataResource(kDataResources[i].id,
-                          kDataResources[i].scale_factor);
+      base::StringPiece resource = GetContentClient()->GetDataResource(
+          kDataResources[i].id, kDataResources[i].scale_factor);
       return WebData(resource.data(), resource.size());
     }
   }
@@ -676,7 +738,7 @@
   int message_id = ToMessageID(name);
   if (message_id < 0)
     return WebString();
-  return GetLocalizedString(message_id);
+  return GetContentClient()->GetLocalizedString(message_id);
 }
 
 WebString BlinkPlatformImpl::queryLocalizedString(
@@ -689,7 +751,8 @@
   int message_id = ToMessageID(name);
   if (message_id < 0)
     return WebString();
-  return ReplaceStringPlaceholders(GetLocalizedString(message_id), value, NULL);
+  return ReplaceStringPlaceholders(GetContentClient()->GetLocalizedString(
+      message_id), value, NULL);
 }
 
 WebString BlinkPlatformImpl::queryLocalizedString(
@@ -704,7 +767,7 @@
   values.push_back(value1);
   values.push_back(value2);
   return ReplaceStringPlaceholders(
-      GetLocalizedString(message_id), values, NULL);
+      GetContentClient()->GetLocalizedString(message_id), values, NULL);
 }
 
 double BlinkPlatformImpl::currentTime() {
@@ -765,6 +828,51 @@
   main_loop_->PostTask(FROM_HERE, base::Bind(func, context));
 }
 
+blink::WebGestureCurve* BlinkPlatformImpl::createFlingAnimationCurve(
+    int device_source,
+    const blink::WebFloatPoint& velocity,
+    const blink::WebSize& cumulative_scroll) {
+#if defined(OS_ANDROID)
+  return FlingAnimatorImpl::CreateAndroidGestureCurve(
+      velocity,
+      cumulative_scroll);
+#endif
+
+  if (device_source == blink::WebGestureEvent::Touchscreen)
+    return fling_curve_configuration_->CreateForTouchScreen(velocity,
+                                                            cumulative_scroll);
+
+  return fling_curve_configuration_->CreateForTouchPad(velocity,
+                                                       cumulative_scroll);
+}
+
+void BlinkPlatformImpl::didStartWorkerRunLoop(
+    const blink::WebWorkerRunLoop& runLoop) {
+  WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
+  worker_task_runner->OnWorkerRunLoopStarted(runLoop);
+}
+
+void BlinkPlatformImpl::didStopWorkerRunLoop(
+    const blink::WebWorkerRunLoop& runLoop) {
+  WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
+  worker_task_runner->OnWorkerRunLoopStopped(runLoop);
+}
+
+blink::WebCrypto* BlinkPlatformImpl::crypto() {
+  if (!web_crypto_)
+    web_crypto_.reset(new WebCryptoImpl());
+  return web_crypto_.get();
+}
+
+
+WebThemeEngine* BlinkPlatformImpl::themeEngine() {
+  return &native_theme_engine_;
+}
+
+WebFallbackThemeEngine* BlinkPlatformImpl::fallbackThemeEngine() {
+  return &fallback_theme_engine_;
+}
+
 base::PlatformFile BlinkPlatformImpl::databaseOpenFile(
     const blink::WebString& vfs_file_name, int desired_flags) {
   return base::kInvalidPlatformFileValue;
@@ -881,6 +989,15 @@
   return base::allocator::GetAllocatorWasteSize(size);
 }
 
+blink::WebDiscardableMemory*
+BlinkPlatformImpl::allocateAndLockDiscardableMemory(size_t bytes) {
+  base::DiscardableMemoryType type =
+      base::DiscardableMemory::GetPreferredType();
+  if (type == base::DISCARDABLE_MEMORY_TYPE_EMULATED)
+    return NULL;
+  return content::WebDiscardableMemoryImpl::CreateLockedMemory(bytes).release();
+}
+
 size_t BlinkPlatformImpl::maxDecodedImageBytes() {
 #if defined(OS_ANDROID)
   if (base::android::SysUtils::IsLowEndDevice()) {
@@ -896,6 +1013,12 @@
 #endif
 }
 
+void BlinkPlatformImpl::SetFlingCurveParameters(
+    const std::vector<float>& new_touchpad,
+    const std::vector<float>& new_touchscreen) {
+  fling_curve_configuration_->SetCurveParameters(new_touchpad, new_touchscreen);
+}
+
 void BlinkPlatformImpl::SuspendSharedTimer() {
   ++shared_timer_suspended_;
 }
@@ -913,4 +1036,11 @@
   }
 }
 
+// static
+void BlinkPlatformImpl::DestroyCurrentThread(void* thread) {
+  WebThreadImplForMessageLoop* impl =
+      static_cast<WebThreadImplForMessageLoop*>(thread);
+  delete impl;
+}
+
 }  // namespace content
diff --git a/content/child/blink_platform_impl.h b/content/child/blink_platform_impl.h
index e14808d..2ca543f 100644
--- a/content/child/blink_platform_impl.h
+++ b/content/child/blink_platform_impl.h
@@ -8,25 +8,32 @@
 #include "base/compiler_specific.h"
 #include "base/debug/trace_event.h"
 #include "base/platform_file.h"
+#include "base/threading/thread_local_storage.h"
 #include "base/timer/timer.h"
+#include "content/child/webfallbackthemeengine_impl.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/Platform.h"
 #include "third_party/WebKit/public/platform/WebURLError.h"
 #include "ui/base/layout.h"
 #include "webkit/child/resource_loader_bridge.h"
 
+#if defined(USE_DEFAULT_RENDER_THEME)
+#include "content/child/webthemeengine_impl_default.h"
+#elif defined(OS_WIN)
+#include "content/child/webthemeengine_impl_win.h"
+#elif defined(OS_MACOSX)
+#include "content/child/webthemeengine_impl_mac.h"
+#elif defined(OS_ANDROID)
+#include "content/child/webthemeengine_impl_android.h"
+#endif
+
 namespace base {
 class MessageLoop;
 }
 
-namespace blink {
-class WebSocketStreamHandle;
-}
-
 namespace content {
-
-class WebSocketStreamHandleDelegate;
-class WebSocketStreamHandleBridge;
+class FlingCurveConfiguration;
+class WebCryptoImpl;
 
 class CONTENT_EXPORT BlinkPlatformImpl
     : NON_EXPORTED_BASE(public blink::Platform) {
@@ -35,6 +42,8 @@
   virtual ~BlinkPlatformImpl();
 
   // Platform methods (partial implementation):
+  virtual blink::WebThemeEngine* themeEngine();
+  virtual blink::WebFallbackThemeEngine* fallbackThemeEngine();
   virtual base::PlatformFile databaseOpenFile(
       const blink::WebString& vfs_file_name, int desired_flags);
   virtual int databaseDeleteFile(const blink::WebString& vfs_file_name,
@@ -60,16 +69,22 @@
   virtual bool processMemorySizesInBytes(size_t* private_bytes,
                                          size_t* shared_bytes);
   virtual bool memoryAllocatorWasteInBytes(size_t* size);
+  virtual blink::WebDiscardableMemory* allocateAndLockDiscardableMemory(
+      size_t bytes);
   virtual size_t maxDecodedImageBytes() OVERRIDE;
   virtual blink::WebURLLoader* createURLLoader();
   virtual blink::WebSocketStreamHandle* createSocketStreamHandle();
+  virtual blink::WebSocketHandle* createWebSocketHandle() OVERRIDE;
   virtual blink::WebString userAgent();
-  // TODO(jam): remove this after Blink is updated
-  virtual blink::WebString userAgent(const blink::WebURL& url);
   virtual blink::WebData parseDataURL(
       const blink::WebURL& url, blink::WebString& mimetype,
       blink::WebString& charset);
   virtual blink::WebURLError cancelledError(const blink::WebURL& url) const;
+  virtual blink::WebThread* createThread(const char* name);
+  virtual blink::WebThread* currentThread();
+  virtual blink::WebWaitableEvent* createWaitableEvent();
+  virtual blink::WebWaitableEvent* waitMultipleEvents(
+      const blink::WebVector<blink::WebWaitableEvent*>& events);
   virtual void decrementStatsCounter(const char* name);
   virtual void incrementStatsCounter(const char* name);
   virtual void histogramCustomCounts(
@@ -113,44 +128,42 @@
   virtual void setSharedTimerFireInterval(double interval_seconds);
   virtual void stopSharedTimer();
   virtual void callOnMainThread(void (*func)(void*), void* context);
+  virtual blink::WebGestureCurve* createFlingAnimationCurve(
+      int device_source,
+      const blink::WebFloatPoint& velocity,
+      const blink::WebSize& cumulative_scroll) OVERRIDE;
+  virtual void didStartWorkerRunLoop(
+      const blink::WebWorkerRunLoop& runLoop) OVERRIDE;
+  virtual void didStopWorkerRunLoop(
+      const blink::WebWorkerRunLoop& runLoop) OVERRIDE;
+  virtual blink::WebCrypto* crypto() OVERRIDE;
 
-
-  // Embedder functions. The following are not implemented by the glue layer and
-  // need to be specialized by the embedder.
-
-  // Gets a localized string given a message id.  Returns an empty string if the
-  // message id is not found.
-  virtual base::string16 GetLocalizedString(int message_id) = 0;
-
-  // Returns the raw data for a resource.  This resource must have been
-  // specified as BINDATA in the relevant .rc file.
-  virtual base::StringPiece GetDataResource(int resource_id,
-                                            ui::ScaleFactor scale_factor) = 0;
-
-  // Creates a ResourceLoaderBridge.
-  virtual webkit_glue::ResourceLoaderBridge* CreateResourceLoader(
-      const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) = 0;
-  // Creates a WebSocketStreamHandleBridge.
-  virtual WebSocketStreamHandleBridge* CreateWebSocketStreamBridge(
-      blink::WebSocketStreamHandle* handle,
-      WebSocketStreamHandleDelegate* delegate) = 0;
+  void SetFlingCurveParameters(const std::vector<float>& new_touchpad,
+                               const std::vector<float>& new_touchscreen);
 
   void SuspendSharedTimer();
   void ResumeSharedTimer();
   virtual void OnStartSharedTimer(base::TimeDelta delay) {}
 
  private:
+  static void DestroyCurrentThread(void*);
+
   void DoTimeout() {
     if (shared_timer_func_ && !shared_timer_suspended_)
       shared_timer_func_();
   }
 
+  WebThemeEngineImpl native_theme_engine_;
+  WebFallbackThemeEngineImpl fallback_theme_engine_;
   base::MessageLoop* main_loop_;
   base::OneShotTimer<BlinkPlatformImpl> shared_timer_;
   void (*shared_timer_func_)();
   double shared_timer_fire_time_;
   bool shared_timer_fire_time_was_set_while_suspended_;
   int shared_timer_suspended_;  // counter
+  scoped_ptr<FlingCurveConfiguration> fling_curve_configuration_;
+  base::ThreadLocalStorage::Slot current_thread_slot_;
+  scoped_ptr<WebCryptoImpl> web_crypto_;
 };
 
 }  // namespace content
diff --git a/content/child/blink_platform_unittest.cc b/content/child/blink_platform_unittest.cc
index c045b30..88a3c0d 100644
--- a/content/child/blink_platform_unittest.cc
+++ b/content/child/blink_platform_unittest.cc
@@ -14,26 +14,6 @@
  public:
   TestBlinkPlatformImpl() : mock_monotonically_increasing_time_(0) {}
 
-  // webkit_glue::BlinkPlatformImpl:
-  virtual base::string16 GetLocalizedString(int) OVERRIDE {
-    return base::string16();
-  }
-
-  virtual base::StringPiece GetDataResource(int, ui::ScaleFactor) OVERRIDE {
-    return base::StringPiece();
-  }
-
-  virtual webkit_glue::ResourceLoaderBridge* CreateResourceLoader(
-      const webkit_glue::ResourceLoaderBridge::RequestInfo&) OVERRIDE {
-    return NULL;
-  }
-
-  virtual WebSocketStreamHandleBridge* CreateWebSocketStreamBridge(
-      blink::WebSocketStreamHandle*,
-      WebSocketStreamHandleDelegate*) OVERRIDE {
-    return NULL;
-  }
-
   // Returns mock time when enabled.
   virtual double monotonicallyIncreasingTime() OVERRIDE {
     if (mock_monotonically_increasing_time_ > 0.0)
diff --git a/content/child/child_thread.cc b/content/child/child_thread.cc
index 6d2c334..d5fc4b4 100644
--- a/content/child/child_thread.cc
+++ b/content/child/child_thread.cc
@@ -44,6 +44,7 @@
 #include "ipc/ipc_switches.h"
 #include "ipc/ipc_sync_channel.h"
 #include "ipc/ipc_sync_message_filter.h"
+#include "webkit/child/resource_loader_bridge.h"
 
 #if defined(OS_WIN)
 #include "content/common/handle_enumerator_win.h"
@@ -69,50 +70,6 @@
 // plugins), PluginThread has EnsureTerminateMessageFilter.
 #if defined(OS_POSIX)
 
-// A thread delegate that waits for |duration| and then signals the process
-// with SIGALRM.
-class WaitAndExitDelegate : public base::PlatformThread::Delegate {
- public:
-  explicit WaitAndExitDelegate(base::TimeDelta duration)
-      : duration_(duration) {}
-  virtual ~WaitAndExitDelegate() OVERRIDE {}
-
-  virtual void ThreadMain() OVERRIDE {
-    base::PlatformThread::Sleep(duration_);
-    // This used to be implemented with alarm(2). Make sure to not break
-    // anything that requires the process being signaled.
-    CHECK_EQ(0, raise(SIGALRM));
-
-    base::PlatformThread::Sleep((base::TimeDelta::FromSeconds(10)));
-    // If something erroneously blocked SIGALRM, this will trigger.
-    NOTREACHED();
-    _exit(0);
-  }
-
- private:
-  const base::TimeDelta duration_;
-  DISALLOW_COPY_AND_ASSIGN(WaitAndExitDelegate);
-};
-
-// This is similar to using alarm(2), except it will spawn a thread
-// which will sleep for |duration| before raising SIGALRM.
-bool CreateAlarmThread(base::TimeDelta duration) {
-  scoped_ptr<WaitAndExitDelegate> delegate(new WaitAndExitDelegate(duration));
-
-  const bool thread_created = base::PlatformThread::CreateNonJoinable(
-      0 /* stack_size */, delegate.get());
-  if (!thread_created)
-    return false;
-
-  // A non joinable thread has been created. The thread will either terminate
-  // the process or will be terminated by the process. Therefore, keep the
-  // delegate object alive for the lifetime of the process.
-  WaitAndExitDelegate* leaking_delegate = delegate.release();
-  ANNOTATE_LEAKING_OBJECT_PTR(leaking_delegate);
-  ignore_result(leaking_delegate);
-  return true;
-}
-
 class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter {
  public:
   // IPC::ChannelProxy::MessageFilter
@@ -132,21 +89,7 @@
     //
     // So, we install a filter on the channel so that we can process this event
     // here and kill the process.
-    if (CommandLine::ForCurrentProcess()->
-        HasSwitch(switches::kChildCleanExit)) {
-      // If clean exit is requested, we want to kill this process after giving
-      // it 60 seconds to run exit handlers. Exit handlers may including ones
-      // that write profile data to disk (which happens under profile collection
-      // mode).
-      CHECK(CreateAlarmThread(base::TimeDelta::FromSeconds(60)));
-#if defined(LEAK_SANITIZER)
-      // Invoke LeakSanitizer early to avoid detecting shutdown-only leaks. If
-      // leaks are found, the process will exit here.
-      __lsan_do_leak_check();
-#endif
-    } else {
-      _exit(0);
-    }
+    _exit(0);
   }
 
  protected:
@@ -369,7 +312,7 @@
 }
 
 webkit_glue::ResourceLoaderBridge* ChildThread::CreateBridge(
-    const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) {
+    const RequestInfo& request_info) {
   return resource_dispatcher()->CreateBridge(request_info);
 }
 
diff --git a/content/child/child_thread.h b/content/child/child_thread.h
index 233e9c8..f8d9bf4 100644
--- a/content/child/child_thread.h
+++ b/content/child/child_thread.h
@@ -16,7 +16,6 @@
 #include "content/common/content_export.h"
 #include "content/common/message_router.h"
 #include "ipc/ipc_message.h"  // For IPC_MESSAGE_LOG_ENABLED.
-#include "webkit/child/resource_loader_bridge.h"
 
 namespace base {
 class MessageLoop;
@@ -35,6 +34,10 @@
 class WebFrame;
 }  // namespace blink
 
+namespace webkit_glue {
+class ResourceLoaderBridge;
+}  // namespace webkit_glue
+
 namespace content {
 class ChildHistogramMessageFilter;
 class ChildResourceMessageFilter;
@@ -48,6 +51,7 @@
 class SocketStreamDispatcher;
 class ThreadSafeSender;
 class WebSocketDispatcher;
+struct RequestInfo;
 
 // The main thread of a child process derives from this class.
 class CONTENT_EXPORT ChildThread : public IPC::Listener, public IPC::Sender {
@@ -74,7 +78,7 @@
   // Creates a ResourceLoaderBridge.
   // Tests can override this method if they want a custom loading behavior.
   virtual webkit_glue::ResourceLoaderBridge* CreateBridge(
-      const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info);
+      const RequestInfo& request_info);
 
   // Allocates a block of shared memory of the given size and
   // maps in into the address space. Returns NULL of failure.
diff --git a/content/child/fling_curve_configuration.cc b/content/child/fling_curve_configuration.cc
index 799511a..8beeb36 100644
--- a/content/child/fling_curve_configuration.cc
+++ b/content/child/fling_curve_configuration.cc
@@ -5,8 +5,8 @@
 #include "content/child/fling_curve_configuration.h"
 
 #include "base/logging.h"
+#include "content/child/touch_fling_gesture_curve.h"
 #include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "webkit/child/touch_fling_gesture_curve.h"
 
 namespace content {
 
@@ -37,7 +37,7 @@
     p2 = coefs[2];
   }
 
-  return webkit_glue::TouchFlingGestureCurve::Create(velocity, p0, p1, p2,
+  return TouchFlingGestureCurve::Create(velocity, p0, p1, p2,
       cumulativeScroll);
 }
 
diff --git a/content/child/npapi/plugin_lib.cc b/content/child/npapi/plugin_lib.cc
index 8722d63..9df2f58 100644
--- a/content/child/npapi/plugin_lib.cc
+++ b/content/child/npapi/plugin_lib.cc
@@ -171,7 +171,7 @@
 
   bool rv = false;
   base::NativeLibrary library = 0;
-  std::string error;
+  base::NativeLibraryLoadError error;
 
 #if defined(OS_WIN)
   // This is to work around a bug in the Real player recorder plugin which
@@ -193,7 +193,7 @@
   if (!library) {
     LOG_IF(ERROR, PluginList::DebugPluginLoading())
         << "Couldn't load plugin " << web_plugin_info_.path.value() << " "
-        << error;
+        << error.ToString();
     return rv;
   }
 
diff --git a/content/child/npapi/plugin_url_fetcher.cc b/content/child/npapi/plugin_url_fetcher.cc
index 2a5c46b..a1d1530 100644
--- a/content/child/npapi/plugin_url_fetcher.cc
+++ b/content/child/npapi/plugin_url_fetcher.cc
@@ -13,6 +13,7 @@
 #include "content/child/npapi/webplugin_resource_client.h"
 #include "content/child/plugin_messages.h"
 #include "content/child/request_extra_data.h"
+#include "content/child/request_info.h"
 #include "content/child/resource_dispatcher.h"
 #include "content/child/web_url_loader_impl.h"
 #include "content/common/resource_request_body.h"
@@ -97,7 +98,7 @@
       copy_stream_data_(copy_stream_data),
       data_offset_(0),
       pending_failure_notification_(false) {
-  webkit_glue::ResourceLoaderBridge::RequestInfo request_info;
+  RequestInfo request_info;
   request_info.method = method;
   request_info.url = url;
   request_info.first_party_for_cookies = first_party_for_cookies;
@@ -107,21 +108,9 @@
   request_info.request_type = ResourceType::OBJECT;
   request_info.routing_id = render_view_id;
 
-  RequestExtraData extra_data(blink::WebPageVisibilityStateVisible,
-                              base::string16(),
-                              false,
-                              render_frame_id,
-                              false,
-                              GURL(),
-                              false,
-                              -1,
-                              true,
-                              PAGE_TRANSITION_LINK,
-                              false,
-                              -1,
-                              -1,
-                              kInvalidServiceWorkerProviderId);
-
+  RequestExtraData extra_data;
+  extra_data.set_render_frame_id(render_frame_id);
+  extra_data.set_is_main_frame(false);
   request_info.extra_data = &extra_data;
 
   std::vector<char> body;
diff --git a/content/child/request_extra_data.cc b/content/child/request_extra_data.cc
index ba9789d..1a9449f 100644
--- a/content/child/request_extra_data.cc
+++ b/content/child/request_extra_data.cc
@@ -4,39 +4,26 @@
 
 #include "content/child/request_extra_data.h"
 
+#include "content/common/service_worker/service_worker_types.h"
+#include "ipc/ipc_message.h"
+
 using blink::WebString;
 
 namespace content {
 
-RequestExtraData::RequestExtraData(
-    blink::WebPageVisibilityState visibility_state,
-    const WebString& custom_user_agent,
-    bool was_after_preconnect_request,
-    int render_frame_id,
-    bool is_main_frame,
-    const GURL& frame_origin,
-    bool parent_is_main_frame,
-    int parent_render_frame_id,
-    bool allow_download,
-    PageTransition transition_type,
-    bool should_replace_current_entry,
-    int transferred_request_child_id,
-    int transferred_request_request_id,
-    int service_worker_provider_id)
-    : webkit_glue::WebURLRequestExtraDataImpl(custom_user_agent,
-                                              was_after_preconnect_request),
-      visibility_state_(visibility_state),
-      render_frame_id_(render_frame_id),
-      is_main_frame_(is_main_frame),
-      frame_origin_(frame_origin),
-      parent_is_main_frame_(parent_is_main_frame),
-      parent_render_frame_id_(parent_render_frame_id),
-      allow_download_(allow_download),
-      transition_type_(transition_type),
-      should_replace_current_entry_(should_replace_current_entry),
-      transferred_request_child_id_(transferred_request_child_id),
-      transferred_request_request_id_(transferred_request_request_id),
-      service_worker_provider_id_(service_worker_provider_id) {
+RequestExtraData::RequestExtraData()
+    : visibility_state_(blink::WebPageVisibilityStateVisible),
+      render_frame_id_(MSG_ROUTING_NONE),
+      is_main_frame_(true),
+      parent_is_main_frame_(false),
+      parent_render_frame_id_(-1),
+      allow_download_(true),
+      transition_type_(PAGE_TRANSITION_LINK),
+      should_replace_current_entry_(false),
+      transferred_request_child_id_(-1),
+      transferred_request_request_id_(-1),
+      service_worker_provider_id_(kInvalidServiceWorkerProviderId),
+      was_after_preconnect_request_(false) {
 }
 
 RequestExtraData::~RequestExtraData() {
diff --git a/content/child/request_extra_data.h b/content/child/request_extra_data.h
index 3c98921..fb51922 100644
--- a/content/child/request_extra_data.h
+++ b/content/child/request_extra_data.h
@@ -8,54 +8,98 @@
 #include "base/compiler_specific.h"
 #include "content/common/content_export.h"
 #include "content/public/common/page_transition_types.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "third_party/WebKit/public/web/WebPageVisibilityState.h"
-#include "webkit/child/weburlrequest_extradata_impl.h"
 
 namespace content {
 
 // The RenderView stores an instance of this class in the "extra data" of each
 // ResourceRequest (see RenderFrameImpl::willSendRequest).
 class CONTENT_EXPORT RequestExtraData
-    : NON_EXPORTED_BASE(public webkit_glue::WebURLRequestExtraDataImpl) {
+    : public NON_EXPORTED_BASE(blink::WebURLRequest::ExtraData) {
  public:
-  RequestExtraData(blink::WebPageVisibilityState visibility_state,
-                   const blink::WebString& custom_user_agent,
-                   bool was_after_preconnect_request,
-                   int render_frame_id,
-                   bool is_main_frame,
-                   const GURL& frame_origin,
-                   bool parent_is_main_frame,
-                   int parent_render_frame_id,
-                   bool allow_download,
-                   PageTransition transition_type,
-                   bool should_replace_current_entry,
-                   int transferred_request_child_id,
-                   int transferred_request_request_id,
-                   int service_worker_provider_id);
+  RequestExtraData();
   virtual ~RequestExtraData();
 
   blink::WebPageVisibilityState visibility_state() const {
     return visibility_state_;
   }
+  void set_visibility_state(blink::WebPageVisibilityState visibility_state) {
+    visibility_state_ = visibility_state;
+  }
   int render_frame_id() const { return render_frame_id_; }
+  void set_render_frame_id(int render_frame_id) {
+    render_frame_id_ = render_frame_id;
+  }
   bool is_main_frame() const { return is_main_frame_; }
+  void set_is_main_frame(bool is_main_frame) {
+    is_main_frame_ = is_main_frame;
+  }
   GURL frame_origin() const { return frame_origin_; }
+  void set_frame_origin(const GURL& frame_origin) {
+    frame_origin_ = frame_origin;
+  }
   bool parent_is_main_frame() const { return parent_is_main_frame_; }
+  void set_parent_is_main_frame(bool parent_is_main_frame) {
+    parent_is_main_frame_ = parent_is_main_frame;
+  }
   int parent_render_frame_id() const { return parent_render_frame_id_; }
+  void set_parent_render_frame_id(int parent_render_frame_id) {
+    parent_render_frame_id_ = parent_render_frame_id;
+  }
   bool allow_download() const { return allow_download_; }
+  void set_allow_download(bool allow_download) {
+    allow_download_ = allow_download;
+  }
   PageTransition transition_type() const { return transition_type_; }
+  void set_transition_type(PageTransition transition_type) {
+    transition_type_ = transition_type;
+  }
   bool should_replace_current_entry() const {
     return should_replace_current_entry_;
   }
+  void set_should_replace_current_entry(
+      bool should_replace_current_entry) {
+    should_replace_current_entry_ = should_replace_current_entry;
+  }
   int transferred_request_child_id() const {
     return transferred_request_child_id_;
   }
+  void set_transferred_request_child_id(
+      int transferred_request_child_id) {
+    transferred_request_child_id_ = transferred_request_child_id;
+  }
   int transferred_request_request_id() const {
     return transferred_request_request_id_;
   }
+  void set_transferred_request_request_id(
+      int transferred_request_request_id) {
+    transferred_request_request_id_ = transferred_request_request_id;
+  }
   int service_worker_provider_id() const {
     return service_worker_provider_id_;
   }
+  void set_service_worker_provider_id(
+      int service_worker_provider_id) {
+    service_worker_provider_id_ = service_worker_provider_id;
+  }
+  // |custom_user_agent| is used to communicate an overriding custom user agent
+  // to |RenderViewImpl::willSendRequest()|; set to a null string to indicate no
+  // override and an empty string to indicate that there should be no user
+  // agent.
+  const blink::WebString& custom_user_agent() const {
+      return custom_user_agent_;
+  }
+  void set_custom_user_agent(
+      const blink::WebString& custom_user_agent) {
+    custom_user_agent_ = custom_user_agent;
+  }
+  bool was_after_preconnect_request() { return was_after_preconnect_request_; }
+  void set_was_after_preconnect_request(
+      bool was_after_preconnect_request) {
+    was_after_preconnect_request_ = was_after_preconnect_request;
+  }
 
  private:
   blink::WebPageVisibilityState visibility_state_;
@@ -70,6 +114,8 @@
   int transferred_request_child_id_;
   int transferred_request_request_id_;
   int service_worker_provider_id_;
+  blink::WebString custom_user_agent_;
+  bool was_after_preconnect_request_;
 
   DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
 };
diff --git a/content/child/request_info.cc b/content/child/request_info.cc
new file mode 100644
index 0000000..e75c54a
--- /dev/null
+++ b/content/child/request_info.cc
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/request_info.h"
+
+namespace content {
+
+RequestInfo::RequestInfo()
+    : referrer_policy(blink::WebReferrerPolicyDefault),
+      load_flags(0),
+      requestor_pid(0),
+      request_type(ResourceType::MAIN_FRAME),
+      priority(net::LOW),
+      request_context(0),
+      appcache_host_id(0),
+      routing_id(0),
+      download_to_file(false),
+      has_user_gesture(false),
+      extra_data(NULL) {
+}
+
+RequestInfo::~RequestInfo() {}
+
+}  // namespace content
diff --git a/content/child/request_info.h b/content/child/request_info.h
new file mode 100644
index 0000000..6dd1bed
--- /dev/null
+++ b/content/child/request_info.h
@@ -0,0 +1,87 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_REQUEST_INFO_H_
+#define CONTENT_CHILD_REQUEST_INFO_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "content/common/content_export.h"
+#include "net/base/request_priority.h"
+#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "url/gurl.h"
+#include "webkit/common/resource_type.h"
+
+namespace content {
+
+// Structure used when calling BlinkPlatformImpl::CreateResourceLoader().
+struct CONTENT_EXPORT RequestInfo {
+  RequestInfo();
+  ~RequestInfo();
+
+  // HTTP-style method name (e.g., "GET" or "POST").
+  std::string method;
+
+  // Absolute URL encoded in ASCII per the rules of RFC-2396.
+  GURL url;
+
+  // URL of the document in the top-level window, which may be checked by the
+  // third-party cookie blocking policy.
+  GURL first_party_for_cookies;
+
+  // Optional parameter, a URL with similar constraints in how it must be
+  // encoded as the url member.
+  GURL referrer;
+
+  // The referrer policy that applies to the referrer.
+  blink::WebReferrerPolicy referrer_policy;
+
+  // For HTTP(S) requests, the headers parameter can be a \r\n-delimited and
+  // \r\n-terminated list of MIME headers.  They should be ASCII-encoded using
+  // the standard MIME header encoding rules.  The headers parameter can also
+  // be null if no extra request headers need to be set.
+  std::string headers;
+
+  // Composed of the values defined in url_request_load_flags.h.
+  int load_flags;
+
+  // Process id of the process making the request.
+  int requestor_pid;
+
+  // Indicates if the current request is the main frame load, a sub-frame
+  // load, or a sub objects load.
+  ResourceType::Type request_type;
+
+  // Indicates the priority of this request, as determined by WebKit.
+  net::RequestPriority priority;
+
+  // Used for plugin to browser requests.
+  uint32_t request_context;
+
+  // Identifies what appcache host this request is associated with.
+  int appcache_host_id;
+
+  // Used to associated the bridge with a frame's network context.
+  int routing_id;
+
+  // If true, then the response body will be downloaded to a file and the
+  // path to that file will be provided in ResponseInfo::download_file_path.
+  bool download_to_file;
+
+  // True if the request was user initiated.
+  bool has_user_gesture;
+
+  // Extra data associated with this request.  We do not own this pointer.
+  blink::WebURLRequest::ExtraData* extra_data;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RequestInfo);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_CHILD_REQUEST_INFO_H_
diff --git a/content/child/resource_dispatcher.cc b/content/child/resource_dispatcher.cc
index c332de4..990bf84 100644
--- a/content/child/resource_dispatcher.cc
+++ b/content/child/resource_dispatcher.cc
@@ -16,6 +16,7 @@
 #include "base/metrics/histogram.h"
 #include "base/strings/string_util.h"
 #include "content/child/request_extra_data.h"
+#include "content/child/request_info.h"
 #include "content/child/site_isolation_policy.h"
 #include "content/common/inter_process_time_ticks_converter.h"
 #include "content/common/resource_messages.h"
@@ -69,7 +70,7 @@
 class IPCResourceLoaderBridge : public ResourceLoaderBridge {
  public:
   IPCResourceLoaderBridge(ResourceDispatcher* dispatcher,
-      const ResourceLoaderBridge::RequestInfo& request_info);
+                          const RequestInfo& request_info);
   virtual ~IPCResourceLoaderBridge();
 
   // ResourceLoaderBridge
@@ -105,7 +106,7 @@
 
 IPCResourceLoaderBridge::IPCResourceLoaderBridge(
     ResourceDispatcher* dispatcher,
-    const ResourceLoaderBridge::RequestInfo& request_info)
+    const RequestInfo& request_info)
     : peer_(NULL),
       dispatcher_(dispatcher),
       request_id_(-1),
@@ -700,7 +701,7 @@
 }
 
 ResourceLoaderBridge* ResourceDispatcher::CreateBridge(
-    const ResourceLoaderBridge::RequestInfo& request_info) {
+    const RequestInfo& request_info) {
   return new IPCResourceLoaderBridge(this, request_info);
 }
 
diff --git a/content/child/resource_dispatcher.h b/content/child/resource_dispatcher.h
index 4d8f786..e4a2d4f 100644
--- a/content/child/resource_dispatcher.h
+++ b/content/child/resource_dispatcher.h
@@ -19,11 +19,13 @@
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_sender.h"
 #include "webkit/child/resource_loader_bridge.h"
+#include "webkit/common/resource_type.h"
 
 struct ResourceMsg_RequestCompleteData;
 
 namespace content {
 class ResourceDispatcherDelegate;
+struct RequestInfo;
 struct ResourceResponseHead;
 struct SiteIsolationResponseMetaData;
 
@@ -42,7 +44,7 @@
   // this can be tested regardless of the ResourceLoaderBridge::Create
   // implementation.
   webkit_glue::ResourceLoaderBridge* CreateBridge(
-      const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info);
+      const RequestInfo& request_info);
 
   // Adds a request from the pending_requests_ list, returning the new
   // requests' ID
diff --git a/content/child/resource_dispatcher_unittest.cc b/content/child/resource_dispatcher_unittest.cc
index da0ef2a..a5231e5 100644
--- a/content/child/resource_dispatcher_unittest.cc
+++ b/content/child/resource_dispatcher_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/process/process.h"
 #include "base/process/process_handle.h"
 #include "content/child/request_extra_data.h"
+#include "content/child/request_info.h"
 #include "content/child/resource_dispatcher.h"
 #include "content/common/resource_messages.h"
 #include "content/common/service_worker/service_worker_types.h"
@@ -162,7 +163,7 @@
   }
 
   ResourceLoaderBridge* CreateBridge() {
-    webkit_glue::ResourceLoaderBridge::RequestInfo request_info;
+    RequestInfo request_info;
     request_info.method = "GET";
     request_info.url = GURL(test_page_url);
     request_info.first_party_for_cookies = GURL(test_page_url);
@@ -173,12 +174,7 @@
     request_info.request_type = ResourceType::SUB_RESOURCE;
     request_info.appcache_host_id = appcache::kNoHostId;
     request_info.routing_id = 0;
-    RequestExtraData extra_data(blink::WebPageVisibilityStateVisible,
-                                blink::WebString(),
-                                false, MSG_ROUTING_NONE, true, GURL(),
-                                false, -1, true,
-                                PAGE_TRANSITION_LINK, false, -1, -1,
-                                kInvalidServiceWorkerProviderId);
+    RequestExtraData extra_data;
     request_info.extra_data = &extra_data;
 
     return dispatcher_->CreateBridge(request_info);
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 1d6dc40..714943c 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -27,11 +27,12 @@
     WebRuntimeFeatures::enableMediaSource(false);
     WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
   }
-  // WebAudio is enabled by default only on ARM and only when the
+  // WebAudio is enabled by default on ARM and X86 and only when the
   // MediaCodec API is available.
   WebRuntimeFeatures::enableWebAudio(
       media::MediaCodecBridge::IsAvailable() &&
-      (android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM));
+      ((android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM) ||
+       (android_getCpuFamily() == ANDROID_CPU_FAMILY_X86)));
   // Android does not support the Gamepad API.
   WebRuntimeFeatures::enableGamepad(false);
   // Android does not have support for PagePopup
@@ -97,21 +98,12 @@
     WebRuntimeFeatures::enableServiceWorker(true);
 
 #if defined(OS_ANDROID)
-  // WebAudio requires the MediaCodec API.
-#if defined(ARCH_CPU_X86)
-  // WebAudio is disabled by default on x86.
-  WebRuntimeFeatures::enableWebAudio(
-      command_line.HasSwitch(switches::kEnableWebAudio) &&
-      media::MediaCodecBridge::IsAvailable());
-#elif defined(ARCH_CPU_ARMEL)
-  // WebAudio is enabled by default on ARM.
+  // WebAudio is enabled by default on ARM and X86, if the MediaCodec
+  // API is available.
   WebRuntimeFeatures::enableWebAudio(
       !command_line.HasSwitch(switches::kDisableWebAudio) &&
       media::MediaCodecBridge::IsAvailable());
 #else
-  WebRuntimeFeatures::enableWebAudio(false);
-#endif
-#else
   if (command_line.HasSwitch(switches::kDisableWebAudio))
     WebRuntimeFeatures::enableWebAudio(false);
 #endif
@@ -134,11 +126,6 @@
   if (command_line.HasSwitch(switches::kDisableFileSystem))
     WebRuntimeFeatures::enableFileSystem(false);
 
-#if defined(OS_WIN)
-  if (command_line.HasSwitch(switches::kEnableDirectWrite))
-    WebRuntimeFeatures::enableDirectWrite(true);
-#endif
-
   if (command_line.HasSwitch(switches::kEnableExperimentalCanvasFeatures))
     WebRuntimeFeatures::enableExperimentalCanvasFeatures(true);
 
@@ -157,7 +144,8 @@
   if (ui::IsOverlayScrollbarEnabled())
     WebRuntimeFeatures::enableOverlayScrollbars(true);
 
-  if (command_line.HasSwitch(switches::kEnableFastTextAutosizing))
+  if (command_line.HasSwitch(switches::kEnableFastTextAutosizing)
+      && !command_line.HasSwitch(switches::kDisableFastTextAutosizing))
     WebRuntimeFeatures::enableFastTextAutosizing(true);
 
   if (command_line.HasSwitch(switches::kDisableRepaintAfterLayout))
diff --git a/content/child/service_worker/service_worker_dispatcher.cc b/content/child/service_worker/service_worker_dispatcher.cc
index 0a4310e..ac870ac 100644
--- a/content/child/service_worker/service_worker_dispatcher.cc
+++ b/content/child/service_worker/service_worker_dispatcher.cc
@@ -128,7 +128,7 @@
   // duplicate registration. So for now we mint a new object each
   // time.
   scoped_ptr<WebServiceWorkerImpl> worker(
-      new WebServiceWorkerImpl(registration_id));
+      new WebServiceWorkerImpl(registration_id, thread_safe_sender_));
   callbacks->onSuccess(worker.release());
   pending_callbacks_.Remove(request_id);
 }
diff --git a/content/child/service_worker/web_service_worker_impl.cc b/content/child/service_worker/web_service_worker_impl.cc
index 02d9cf8..b5b3c46 100644
--- a/content/child/service_worker/web_service_worker_impl.cc
+++ b/content/child/service_worker/web_service_worker_impl.cc
@@ -4,8 +4,26 @@
 
 #include "content/child/service_worker/web_service_worker_impl.h"
 
+#include "content/child/thread_safe_sender.h"
+#include "content/child/webmessageportchannel_impl.h"
+#include "content/common/service_worker/service_worker_messages.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+
+using blink::WebMessagePortChannel;
+using blink::WebMessagePortChannelArray;
+using blink::WebMessagePortChannelClient;
+using blink::WebString;
+
 namespace content {
 
 WebServiceWorkerImpl::~WebServiceWorkerImpl() {}
 
+void WebServiceWorkerImpl::postMessage(const WebString& message,
+                                       WebMessagePortChannelArray* channels) {
+  thread_safe_sender_->Send(new ServiceWorkerHostMsg_PostMessage(
+      registration_id_,
+      message,
+      WebMessagePortChannelImpl::ExtractMessagePortIDs(channels)));
+}
+
 }  // namespace content
diff --git a/content/child/service_worker/web_service_worker_impl.h b/content/child/service_worker/web_service_worker_impl.h
index de6010e..3b8b28d 100644
--- a/content/child/service_worker/web_service_worker_impl.h
+++ b/content/child/service_worker/web_service_worker_impl.h
@@ -6,20 +6,29 @@
 #define CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_IMPL_H_
 
 #include "base/compiler_specific.h"
+#include "base/strings/string16.h"
+#include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
 #include "third_party/WebKit/public/platform/WebServiceWorker.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 
 namespace content {
+class ThreadSafeSender;
 
 class WebServiceWorkerImpl
     : NON_EXPORTED_BASE(public blink::WebServiceWorker) {
  public:
-  explicit WebServiceWorkerImpl(int64 registration_id)
-      : registration_id_(registration_id) {}
+  WebServiceWorkerImpl(int64 registration_id,
+                       ThreadSafeSender* thread_safe_sender)
+      : registration_id_(registration_id),
+        thread_safe_sender_(thread_safe_sender) {}
   virtual ~WebServiceWorkerImpl();
 
+  virtual void postMessage(const blink::WebString& message,
+                           blink::WebMessagePortChannelArray* channels);
+
  private:
   int64 registration_id_;
+  ThreadSafeSender* thread_safe_sender_;
 
   DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerImpl);
 };
diff --git a/content/child/shared_worker_devtools_agent.cc b/content/child/shared_worker_devtools_agent.cc
index 475f55f..853d08e 100644
--- a/content/child/shared_worker_devtools_agent.cc
+++ b/content/child/shared_worker_devtools_agent.cc
@@ -34,8 +34,6 @@
     IPC_MESSAGE_HANDLER(DevToolsAgentMsg_Detach, OnDetach)
     IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
                         OnDispatchOnInspectorBackend)
-    IPC_MESSAGE_HANDLER(DevToolsAgentMsg_PauseWorkerContextOnStart,
-                        OnPauseWorkerContextOnStart)
     IPC_MESSAGE_HANDLER(DevToolsAgentMsg_ResumeWorkerContext,
                         OnResumeWorkerContext)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -73,10 +71,6 @@
   webworker_->dispatchDevToolsMessage(WebString::fromUTF8(message));
 }
 
-void SharedWorkerDevToolsAgent::OnPauseWorkerContextOnStart() {
-  webworker_->pauseWorkerContextOnStart();
-}
-
 void SharedWorkerDevToolsAgent::OnResumeWorkerContext() {
   webworker_->resumeWorkerContext();
 }
diff --git a/content/child/shared_worker_devtools_agent.h b/content/child/shared_worker_devtools_agent.h
index 8106989..c8a4655 100644
--- a/content/child/shared_worker_devtools_agent.h
+++ b/content/child/shared_worker_devtools_agent.h
@@ -35,7 +35,6 @@
   void OnReattach(const std::string&);
   void OnDetach();
   void OnDispatchOnInspectorBackend(const std::string& message);
-  void OnPauseWorkerContextOnStart();
   void OnResumeWorkerContext();
 
   bool Send(IPC::Message* message);
diff --git a/content/child/site_isolation_policy_browsertest.cc b/content/child/site_isolation_policy_browsertest.cc
index 15cd06e..20d14ef 100644
--- a/content/child/site_isolation_policy_browsertest.cc
+++ b/content/child/site_isolation_policy_browsertest.cc
@@ -5,8 +5,8 @@
 #include "base/command_line.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 
 namespace content {
 
diff --git a/content/child/touch_fling_gesture_curve.cc b/content/child/touch_fling_gesture_curve.cc
new file mode 100644
index 0000000..43cbd5b
--- /dev/null
+++ b/content/child/touch_fling_gesture_curve.cc
@@ -0,0 +1,163 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/touch_fling_gesture_curve.h"
+
+#include <cmath>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
+
+using blink::WebFloatPoint;
+using blink::WebFloatSize;
+using blink::WebGestureCurve;
+using blink::WebGestureCurveTarget;
+using blink::WebSize;
+
+namespace {
+
+const char* kCurveName = "TouchFlingGestureCurve";
+
+inline double position(double t, float* p) {
+  return p[0] * exp(-p[2] * t) - p[1] * t - p[0];
+}
+
+inline double velocity(double t, float* p) {
+  return -p[0] * p[2] * exp(-p[2] * t) - p[1];
+}
+
+inline double timeAtVelocity(double v, float* p) {
+    DCHECK(p[0]);
+    DCHECK(p[2]);
+    return -log((v + p[1]) / (-p[0] * p[2])) / p[2];
+}
+
+} // namespace
+
+
+namespace content {
+
+// This curve implementation is based on the notion of a single, absolute
+// curve, which starts at a large velocity and smoothly decreases to
+// zero. For a given input velocity, we find where on the curve this
+// velocity occurs, and start the animation at this point---denoted by
+// (time_offset_, position_offset_).
+//
+// This has the effect of automatically determining an animation duration
+// that scales with input velocity, as faster initial velocities start
+// earlier on the curve and thus take longer to reach the end. No
+// complicated time scaling is required.
+//
+// Since the starting velocity is implicitly determined by our starting
+// point, we only store the relative magnitude and direction of both
+// initial x- and y-velocities, and use this to scale the computed
+// displacement at any point in time. This guarantees that fling
+// trajectories are straight lines when viewed in x-y space. Initial
+// velocities that lie outside the max velocity are constrained to start
+// at zero (and thus are implicitly scaled).
+//
+// The curve is modelled as a 4th order polynomial, starting at t = 0,
+// and ending at t = curve_duration_. Attempts to generate
+// position/velocity estimates outside this range are undefined.
+
+WebGestureCurve* TouchFlingGestureCurve::Create(
+    const WebFloatPoint& initial_velocity,
+    float p0,
+    float p1,
+    float p2,
+    const WebSize& cumulative_scroll) {
+  return new TouchFlingGestureCurve(initial_velocity, p0, p1, p2,
+                                    cumulative_scroll);
+}
+
+TouchFlingGestureCurve::TouchFlingGestureCurve(
+    const WebFloatPoint& initial_velocity,
+    float alpha,
+    float beta,
+    float gamma,
+    const WebSize& cumulative_scroll)
+    : cumulative_scroll_(WebFloatSize(cumulative_scroll.width,
+                                      cumulative_scroll.height)) {
+  DCHECK(initial_velocity != WebFloatPoint());
+
+  coefficients_[0] = alpha;
+  coefficients_[1] = beta;
+  coefficients_[2] = gamma;
+
+  // Curve ends when velocity reaches zero.
+  curve_duration_ = timeAtVelocity(0, coefficients_);
+  DCHECK(curve_duration_ > 0);
+
+  float max_start_velocity = std::max(fabs(initial_velocity.x),
+                                      fabs(initial_velocity.y));
+
+  // Force max_start_velocity to lie in the range v(0) to v(curve_duration),
+  // and assume that the curve parameters define a monotonically decreasing
+  // velocity, or else bisection search may fail.
+  if (max_start_velocity > velocity(0, coefficients_))
+    max_start_velocity = velocity(0, coefficients_);
+
+  if (max_start_velocity < 0)
+    max_start_velocity = 0;
+
+  // We keep track of relative magnitudes and directions of the
+  // velocity/displacement components here.
+  displacement_ratio_ = WebFloatPoint(initial_velocity.x / max_start_velocity,
+                                      initial_velocity.y / max_start_velocity);
+
+  // Compute time-offset for start velocity.
+  time_offset_ = timeAtVelocity(max_start_velocity, coefficients_);
+
+  // Compute curve position at offset time
+  position_offset_ = position(time_offset_, coefficients_);
+  TRACE_EVENT_ASYNC_BEGIN1("input", "GestureAnimation", this, "curve",
+      kCurveName);
+}
+
+TouchFlingGestureCurve::~TouchFlingGestureCurve() {
+  TRACE_EVENT_ASYNC_END0("input", "GestureAnimation", this);
+}
+
+bool TouchFlingGestureCurve::apply(double time, WebGestureCurveTarget* target) {
+  float displacement;
+  float speed;
+  if (time < 0) {
+    displacement = 0.f;
+    speed = 0.f;
+  } else if (time + time_offset_ < curve_duration_) {
+    displacement =
+        position(time + time_offset_, coefficients_) - position_offset_;
+    speed = velocity(time + time_offset_, coefficients_);
+  } else {
+    displacement = position(curve_duration_, coefficients_) - position_offset_;
+    speed = 0.f;
+  }
+
+  // Keep track of integer portion of scroll thus far, and prepare increment.
+  WebFloatSize scroll(displacement * displacement_ratio_.x,
+                      displacement * displacement_ratio_.y);
+  WebFloatSize scroll_increment(scroll.width - cumulative_scroll_.width,
+                                scroll.height - cumulative_scroll_.height);
+  WebFloatSize scroll_velocity(speed * displacement_ratio_.x,
+                               speed * displacement_ratio_.y);
+  cumulative_scroll_ = scroll;
+
+  if (time + time_offset_ < curve_duration_ ||
+      scroll_increment != WebFloatSize()) {
+    target->notifyCurrentFlingVelocity(scroll_velocity);
+    // scrollBy() could delete this curve if the animation is over, so don't
+    // touch any member variables after making that call.
+    target->scrollBy(scroll_increment);
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace content
diff --git a/content/child/touch_fling_gesture_curve.h b/content/child/touch_fling_gesture_curve.h
new file mode 100644
index 0000000..555fc74
--- /dev/null
+++ b/content/child/touch_fling_gesture_curve.h
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
+#define CONTENT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
+
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
+
+namespace blink {
+class WebGestureCurveTarget;
+}
+
+namespace content {
+
+// Implementation of WebGestureCurve suitable for touch pad/screen-based
+// fling scroll. Starts with a flat velocity profile based on 'velocity', which
+// tails off to zero. Time is scaled to that duration of the fling is
+// proportional to the initial velocity.
+class TouchFlingGestureCurve : public blink::WebGestureCurve {
+ public:
+
+  static CONTENT_EXPORT WebGestureCurve* Create(
+      const blink::WebFloatPoint& initial_velocity,
+      float p0, float p1, float p2,
+      const blink::WebSize& cumulativeScroll);
+
+ virtual bool apply(double monotonicTime,
+                    blink::WebGestureCurveTarget*) OVERRIDE;
+
+ private:
+  TouchFlingGestureCurve(const blink::WebFloatPoint& initial_velocity,
+                         float p0,
+                         float p1,
+                         float p2,
+                         const blink::WebSize& cumulativeScroll);
+  virtual ~TouchFlingGestureCurve();
+
+  blink::WebFloatPoint displacement_ratio_;
+  blink::WebFloatSize cumulative_scroll_;
+  float coefficients_[3];
+  float time_offset_;
+  float curve_duration_;
+  float position_offset_;
+
+  DISALLOW_COPY_AND_ASSIGN(TouchFlingGestureCurve);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
diff --git a/content/child/touch_fling_gesture_curve_unittest.cc b/content/child/touch_fling_gesture_curve_unittest.cc
new file mode 100644
index 0000000..872f1ef
--- /dev/null
+++ b/content/child/touch_fling_gesture_curve_unittest.cc
@@ -0,0 +1,71 @@
+  // Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Tests for the TouchFlingGestureCurve.
+
+#include "content/child/touch_fling_gesture_curve.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
+#include "third_party/WebKit/public/platform/WebFloatSize.h"
+#include "third_party/WebKit/public/platform/WebGestureCurve.h"
+#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
+#include "third_party/WebKit/public/platform/WebSize.h"
+
+using blink::WebFloatPoint;
+using blink::WebFloatSize;
+using blink::WebGestureCurve;
+using blink::WebGestureCurveTarget;
+using blink::WebSize;
+
+namespace {
+
+class MockGestureCurveTarget : public WebGestureCurveTarget {
+ public:
+  virtual void scrollBy(const WebFloatSize& delta) {
+    cumulative_delta_.width += delta.width;
+    cumulative_delta_.height += delta.height;
+  }
+
+  virtual void notifyCurrentFlingVelocity(const WebFloatSize& velocity) {
+    current_velocity_ = velocity;
+  }
+
+  WebFloatSize cumulative_delta() const { return cumulative_delta_; }
+  void resetCumulativeDelta() { cumulative_delta_ = WebFloatSize(); }
+
+  WebFloatSize current_velocity() const { return current_velocity_; }
+
+ private:
+  WebFloatSize cumulative_delta_;
+  WebFloatSize current_velocity_;
+};
+
+} // namespace anonymous
+
+TEST(TouchFlingGestureCurve, flingCurveTouch)
+{
+  double initialVelocity = 5000;
+  MockGestureCurveTarget target;
+
+  scoped_ptr<WebGestureCurve> curve(content::TouchFlingGestureCurve::Create(
+      WebFloatPoint(initialVelocity, 0),
+      -5.70762e+03f, 1.72e+02f, 3.7e+00f, WebSize()));
+
+  // Note: the expectations below are dependent on the curve parameters hard
+  // coded into the create call above.
+  EXPECT_TRUE(curve->apply(0, &target));
+  EXPECT_TRUE(curve->apply(0.25, &target));
+  EXPECT_NEAR(target.current_velocity().width, 1878, 1);
+  EXPECT_EQ(target.current_velocity().height, 0);
+  EXPECT_TRUE(curve->apply(0.45f, &target)); // Use non-uniform tick spacing.
+  EXPECT_TRUE(curve->apply(1, &target));
+  EXPECT_FALSE(curve->apply(1.5, &target));
+  EXPECT_NEAR(target.cumulative_delta().width, 1193, 1);
+  EXPECT_EQ(target.cumulative_delta().height, 0);
+  EXPECT_EQ(target.current_velocity().width, 0);
+  EXPECT_EQ(target.current_velocity().height, 0);
+}
+
diff --git a/content/child/web_socket_stream_handle_impl.cc b/content/child/web_socket_stream_handle_impl.cc
index 29152ec..24136df 100644
--- a/content/child/web_socket_stream_handle_impl.cc
+++ b/content/child/web_socket_stream_handle_impl.cc
@@ -13,7 +13,8 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
-#include "content/child/blink_platform_impl.h"
+#include "content/child/child_thread.h"
+#include "content/child/socket_stream_dispatcher.h"
 #include "content/child/web_socket_stream_handle_bridge.h"
 #include "content/child/web_socket_stream_handle_delegate.h"
 #include "third_party/WebKit/public/platform/WebData.h"
@@ -42,7 +43,7 @@
     client_ = client;
   }
 
-  void Connect(const WebURL& url, BlinkPlatformImpl* platform);
+  void Connect(const WebURL& url);
   bool Send(const WebData& data);
   void Close();
 
@@ -83,11 +84,14 @@
       client_(NULL) {
 }
 
-void WebSocketStreamHandleImpl::Context::Connect(const WebURL& url,
-                                                 BlinkPlatformImpl* platform) {
+void WebSocketStreamHandleImpl::Context::Connect(const WebURL& url) {
   VLOG(1) << "Connect url=" << url;
   DCHECK(!bridge_.get());
-  bridge_ = platform->CreateWebSocketStreamBridge(handle_, this);
+
+  SocketStreamDispatcher* dispatcher =
+      ChildThread::current()->socket_stream_dispatcher();
+  bridge_ = dispatcher->CreateBridge(handle_, this);
+
   AddRef();  // Will be released by DidClose().
   bridge_->Connect(url);
 }
@@ -163,10 +167,8 @@
 
 // WebSocketStreamHandleImpl ------------------------------------------------
 
-WebSocketStreamHandleImpl::WebSocketStreamHandleImpl(
-    BlinkPlatformImpl* platform)
-    : context_(new Context(this)),
-      platform_(platform) {
+WebSocketStreamHandleImpl::WebSocketStreamHandleImpl()
+    : context_(new Context(this)) {
 }
 
 WebSocketStreamHandleImpl::~WebSocketStreamHandleImpl() {
@@ -182,7 +184,7 @@
   DCHECK(!context_->client());
   context_->set_client(client);
 
-  context_->Connect(url, platform_);
+  context_->Connect(url);
 }
 
 bool WebSocketStreamHandleImpl::send(const WebData& data) {
diff --git a/content/child/web_socket_stream_handle_impl.h b/content/child/web_socket_stream_handle_impl.h
index 6e80676..c8c2aca 100644
--- a/content/child/web_socket_stream_handle_impl.h
+++ b/content/child/web_socket_stream_handle_impl.h
@@ -11,12 +11,10 @@
 
 namespace content {
 
-class BlinkPlatformImpl;
-
 class WebSocketStreamHandleImpl : public base::SupportsUserData,
                                   public blink::WebSocketStreamHandle {
  public:
-  explicit WebSocketStreamHandleImpl(BlinkPlatformImpl* platform);
+  WebSocketStreamHandleImpl();
   virtual ~WebSocketStreamHandleImpl();
 
   // WebSocketStreamHandle methods:
@@ -28,7 +26,6 @@
  private:
   class Context;
   scoped_refptr<Context> context_;
-  BlinkPlatformImpl* platform_;
 
   DISALLOW_COPY_AND_ASSIGN(WebSocketStreamHandleImpl);
 };
diff --git a/content/child/web_url_loader_impl.cc b/content/child/web_url_loader_impl.cc
index 18d8b82..b11a537 100644
--- a/content/child/web_url_loader_impl.cc
+++ b/content/child/web_url_loader_impl.cc
@@ -12,8 +12,10 @@
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/time/time.h"
-#include "content/child/blink_platform_impl.h"
+#include "content/child/child_thread.h"
 #include "content/child/ftp_directory_listing_response_delegate.h"
+#include "content/child/request_extra_data.h"
+#include "content/child/request_info.h"
 #include "content/common/resource_request_body.h"
 #include "net/base/data_url.h"
 #include "net/base/load_flags.h"
@@ -34,7 +36,6 @@
 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
 #include "webkit/child/multipart_response_delegate.h"
 #include "webkit/child/resource_loader_bridge.h"
-#include "webkit/child/weburlrequest_extradata_impl.h"
 #include "webkit/child/weburlresponse_extradata_impl.h"
 
 using base::Time;
@@ -230,8 +231,7 @@
   void SetDefersLoading(bool value);
   void DidChangePriority(WebURLRequest::Priority new_priority);
   void Start(const WebURLRequest& request,
-             ResourceLoaderBridge::SyncLoadResponse* sync_load_response,
-             BlinkPlatformImpl* platform);
+             ResourceLoaderBridge::SyncLoadResponse* sync_load_response);
 
   // ResourceLoaderBridge::Peer methods:
   virtual void OnUploadProgress(uint64 position, uint64 size) OVERRIDE;
@@ -308,8 +308,7 @@
 
 void WebURLLoaderImpl::Context::Start(
     const WebURLRequest& request,
-    ResourceLoaderBridge::SyncLoadResponse* sync_load_response,
-    BlinkPlatformImpl* platform) {
+    ResourceLoaderBridge::SyncLoadResponse* sync_load_response) {
   DCHECK(!bridge_.get());
 
   request_ = request;  // Save the request.
@@ -377,7 +376,7 @@
   // TODO(brettw) this should take parameter encoding into account when
   // creating the GURLs.
 
-  ResourceLoaderBridge::RequestInfo request_info;
+  RequestInfo request_info;
   request_info.method = method;
   request_info.url = url;
   request_info.first_party_for_cookies = request.firstPartyForCookies();
@@ -399,7 +398,7 @@
   request_info.extra_data = request.extraData();
   referrer_policy_ = request.referrerPolicy();
   request_info.referrer_policy = request.referrerPolicy();
-  bridge_.reset(platform->CreateResourceLoader(request_info));
+  bridge_.reset(ChildThread::current()->CreateBridge(request_info));
 
   if (!request.httpBody().isNull()) {
     // GET and HEAD requests shouldn't have http bodies.
@@ -689,9 +688,8 @@
 
 // WebURLLoaderImpl -----------------------------------------------------------
 
-WebURLLoaderImpl::WebURLLoaderImpl(BlinkPlatformImpl* platform)
-    : context_(new Context(this)),
-      platform_(platform) {
+WebURLLoaderImpl::WebURLLoaderImpl()
+    : context_(new Context(this)) {
 }
 
 WebURLLoaderImpl::~WebURLLoaderImpl() {
@@ -831,7 +829,7 @@
                                          WebURLError& error,
                                          WebData& data) {
   ResourceLoaderBridge::SyncLoadResponse sync_load_response;
-  context_->Start(request, &sync_load_response, platform_);
+  context_->Start(request, &sync_load_response);
 
   const GURL& final_url = sync_load_response.url;
 
@@ -857,7 +855,7 @@
   DCHECK(!context_->client());
 
   context_->set_client(client);
-  context_->Start(request, NULL, platform_);
+  context_->Start(request, NULL);
 }
 
 void WebURLLoaderImpl::cancel() {
diff --git a/content/child/web_url_loader_impl.h b/content/child/web_url_loader_impl.h
index 7b31358..3ac22a3 100644
--- a/content/child/web_url_loader_impl.h
+++ b/content/child/web_url_loader_impl.h
@@ -15,11 +15,9 @@
 
 namespace content {
 
-class BlinkPlatformImpl;
-
 class WebURLLoaderImpl : public blink::WebURLLoader {
  public:
-  explicit WebURLLoaderImpl(BlinkPlatformImpl* platform);
+  WebURLLoaderImpl();
   virtual ~WebURLLoaderImpl();
 
   static blink::WebURLError CreateError(const blink::WebURL& unreachable_url,
@@ -46,7 +44,6 @@
  private:
   class Context;
   scoped_refptr<Context> context_;
-  BlinkPlatformImpl* platform_;
 };
 
 }  // namespace content
diff --git a/content/child/webcrypto/jwk.cc b/content/child/webcrypto/jwk.cc
index 8e9e11c..4692d32 100644
--- a/content/child/webcrypto/jwk.cc
+++ b/content/child/webcrypto/jwk.cc
@@ -22,6 +22,22 @@
 
 namespace {
 
+// Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a
+// hash_id that is not a SHA*.
+blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm(
+    blink::WebCryptoAlgorithmId hash_id) {
+  return CreateRsaHashedImportAlgorithm(
+      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, hash_id);
+}
+
+// Creates an RSA-OAEP algorithm. It is an error to call this with a hash_id
+// that is not a SHA*.
+blink::WebCryptoAlgorithm CreateRsaOaepImportAlgorithm(
+    blink::WebCryptoAlgorithmId hash_id) {
+  return CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
+                                        hash_id);
+}
+
 // Web Crypto equivalent usage mask for JWK 'use' = 'enc'.
 // TODO(padolph): Add 'deriveBits' once supported by Blink.
 const blink::WebCryptoKeyUsageMask kJwkEncUsage =
@@ -92,6 +108,9 @@
     alg_to_info_["HS512"] =
         JwkAlgorithmInfo(&BindAlgorithmId<CreateHmacImportAlgorithm,
                                           blink::WebCryptoAlgorithmIdSha512>);
+    alg_to_info_["RS1"] =
+        JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
+                                          blink::WebCryptoAlgorithmIdSha1>);
     alg_to_info_["RS256"] =
         JwkAlgorithmInfo(&BindAlgorithmId<CreateRsaSsaImportAlgorithm,
                                           blink::WebCryptoAlgorithmIdSha256>);
@@ -295,6 +314,18 @@
   jwk_dict->SetString("k", Base64EncodeUrlSafe(key_str));
 }
 
+// Writes an RSA public key to a JWK dictionary
+void WriteRsaPublicKey(const std::vector<uint8>& modulus,
+                       const std::vector<uint8>& public_exponent,
+                       base::DictionaryValue* jwk_dict) {
+  DCHECK(jwk_dict);
+  DCHECK(modulus.size());
+  DCHECK(public_exponent.size());
+  jwk_dict->SetString("kty", "RSA");
+  jwk_dict->SetString("n", Base64EncodeUrlSafe(modulus));
+  jwk_dict->SetString("e", Base64EncodeUrlSafe(public_exponent));
+}
+
 // Writes a Web Crypto usage mask to a JWK dictionary.
 void WriteKeyOps(blink::WebCryptoKeyUsageMask key_usages,
                  base::DictionaryValue* jwk_dict) {
@@ -308,19 +339,19 @@
 
 // Writes a Web Crypto algorithm to a JWK dictionary.
 Status WriteAlg(const blink::WebCryptoKeyAlgorithm& algorithm,
-                unsigned int raw_key_length_bytes,
                 base::DictionaryValue* jwk_dict) {
   switch (algorithm.paramsType()) {
     case blink::WebCryptoKeyAlgorithmParamsTypeAes: {
+      DCHECK(algorithm.aesParams());
       const char* aes_prefix = "";
-      switch (raw_key_length_bytes) {
-        case 16:
+      switch (algorithm.aesParams()->lengthBits()) {
+        case 128:
           aes_prefix = "A128";
           break;
-        case 24:
+        case 192:
           aes_prefix = "A192";
           break;
-        case 32:
+        case 256:
           aes_prefix = "A256";
           break;
         default:
@@ -370,15 +401,61 @@
       break;
     }
     case blink::WebCryptoKeyAlgorithmParamsTypeRsa:
+      switch (algorithm.id()) {
+        case blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5:
+          jwk_dict->SetString("alg", "RSA1_5");
+          break;
+        default:
+          NOTREACHED();
+          return Status::ErrorUnexpected();
+      }
+      break;
     case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed:
-      // TODO(padolph): Handle RSA key
-      return Status::ErrorUnsupported();
+      switch (algorithm.rsaHashedParams()->hash().id()) {
+        case blink::WebCryptoAlgorithmIdRsaOaep:
+          jwk_dict->SetString("alg", "RSA-OAEP");
+          break;
+        case blink::WebCryptoAlgorithmIdSha1:
+          jwk_dict->SetString("alg", "RS1");
+          break;
+        case blink::WebCryptoAlgorithmIdSha256:
+          jwk_dict->SetString("alg", "RS256");
+          break;
+        case blink::WebCryptoAlgorithmIdSha384:
+          jwk_dict->SetString("alg", "RS384");
+          break;
+        case blink::WebCryptoAlgorithmIdSha512:
+          jwk_dict->SetString("alg", "RS512");
+          break;
+        default:
+          NOTREACHED();
+          return Status::ErrorUnexpected();
+      }
+      break;
     default:
       return Status::ErrorUnsupported();
   }
   return Status::Success();
 }
 
+bool IsRsaPublicKey(const blink::WebCryptoKey& key) {
+  if (key.type() != blink::WebCryptoKeyTypePublic)
+    return false;
+  const blink::WebCryptoAlgorithmId algorithm_id = key.algorithm().id();
+  return algorithm_id == blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 ||
+         algorithm_id == blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5 ||
+         algorithm_id == blink::WebCryptoAlgorithmIdRsaOaep;
+}
+
+// TODO(padolph): This function is duplicated in shared_crypto.cc
+Status ToPlatformPublicKey(const blink::WebCryptoKey& key,
+                           platform::PublicKey** out) {
+  *out = static_cast<platform::Key*>(key.handle())->AsPublicKey();
+  if (!*out)
+    return Status::ErrorUnexpectedKeyType();
+  return Status::Success();
+}
+
 }  // namespace
 
 Status ImportKeyJwk(const CryptoData& key_data,
@@ -478,6 +555,7 @@
   //   | "HS256"      | HMAC using SHA-256 hash algorithm                     |
   //   | "HS384"      | HMAC using SHA-384 hash algorithm                     |
   //   | "HS512"      | HMAC using SHA-512 hash algorithm                     |
+  //   | "RS1"        | RSASSA using SHA-1 hash algorithm
   //   | "RS256"      | RSASSA using SHA-256 hash algorithm                   |
   //   | "RS384"      | RSASSA using SHA-384 hash algorithm                   |
   //   | "RS512"      | RSASSA using SHA-512 hash algorithm                   |
@@ -714,23 +792,44 @@
 
 Status ExportKeyJwk(const blink::WebCryptoKey& key,
                     blink::WebArrayBuffer* buffer) {
+  DCHECK(key.extractable());
   base::DictionaryValue jwk_dict;
   Status status = Status::Error();
-  blink::WebArrayBuffer exported_key;
 
-  if (key.type() == blink::WebCryptoKeyTypeSecret) {
-    status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key);
-    if (status.IsError())
-      return status;
-    WriteSecretKey(exported_key, &jwk_dict);
-  } else {
-    // TODO(padolph): Handle asymmetric keys, at least the public key.
-    return Status::ErrorUnsupported();
+  switch (key.type()) {
+    case blink::WebCryptoKeyTypeSecret: {
+      blink::WebArrayBuffer exported_key;
+      status = ExportKey(blink::WebCryptoKeyFormatRaw, key, &exported_key);
+      if (status.IsError())
+        return status;
+      WriteSecretKey(exported_key, &jwk_dict);
+      break;
+    }
+    case blink::WebCryptoKeyTypePublic: {
+      // Currently only RSA public key export is supported.
+      if (!IsRsaPublicKey(key))
+        return Status::ErrorUnsupported();
+      platform::PublicKey* public_key;
+      status = ToPlatformPublicKey(key, &public_key);
+      if (status.IsError())
+        return status;
+      std::vector<uint8> modulus;
+      std::vector<uint8> public_exponent;
+      status =
+          platform::ExportRsaPublicKey(public_key, &modulus, &public_exponent);
+      if (status.IsError())
+        return status;
+      WriteRsaPublicKey(modulus, public_exponent, &jwk_dict);
+      break;
+    }
+    case blink::WebCryptoKeyTypePrivate:  // TODO(padolph)
+    default:
+      return Status::ErrorUnsupported();
   }
 
   WriteKeyOps(key.usages(), &jwk_dict);
   WriteExt(key.extractable(), &jwk_dict);
-  status = WriteAlg(key.algorithm(), exported_key.byteLength(), &jwk_dict);
+  status = WriteAlg(key.algorithm(), &jwk_dict);
   if (status.IsError())
     return status;
 
diff --git a/content/child/webcrypto/jwk.h b/content/child/webcrypto/jwk.h
new file mode 100644
index 0000000..17bf59e
--- /dev/null
+++ b/content/child/webcrypto/jwk.h
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_WEBCRYPTO_JWK_H_
+#define CONTENT_CHILD_WEBCRYPTO_JWK_H_
+
+#include "third_party/WebKit/public/platform/WebArrayBuffer.h"
+#include "third_party/WebKit/public/platform/WebCrypto.h"
+#include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
+
+namespace content {
+
+namespace webcrypto {
+
+class CryptoData;
+class Status;
+
+Status ImportKeyJwk(const CryptoData& key_data,
+                    const blink::WebCryptoAlgorithm& algorithm,
+                    bool extractable,
+                    blink::WebCryptoKeyUsageMask usage_mask,
+                    blink::WebCryptoKey* key);
+
+Status ExportKeyJwk(const blink::WebCryptoKey& key,
+                    blink::WebArrayBuffer* buffer);
+
+}  // namespace webcrypto
+
+}  // namespace content
+
+#endif  // CONTENT_CHILD_WEBCRYPTO_JWK_H_
diff --git a/content/child/webcrypto/platform_crypto.h b/content/child/webcrypto/platform_crypto.h
index 3f884d6..dac3aba 100644
--- a/content/child/webcrypto/platform_crypto.h
+++ b/content/child/webcrypto/platform_crypto.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_CHILD_WEBCRYPTO_PLATFORM_CRYPTO_H_
 #define CONTENT_CHILD_WEBCRYPTO_PLATFORM_CRYPTO_H_
 
+#include <vector>
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
@@ -177,6 +178,18 @@
 Status ExportKeySpki(PublicKey* key, blink::WebArrayBuffer* buffer);
 
 // Preconditions:
+//  * |key| is non-null.
+Status ExportRsaPublicKey(PublicKey* key,
+                          std::vector<uint8>* modulus,
+                          std::vector<uint8>* public_exponent);
+
+// Preconditions:
+//  * |key| is non-null.
+Status ExportKeyPkcs8(PrivateKey* key,
+                      const blink::WebCryptoKeyAlgorithm& key_algorithm,
+                      blink::WebArrayBuffer* buffer);
+
+// Preconditions:
 //  * |wrapping_key| is non-null
 //  * |key| is non-null
 Status WrapSymKeyAesKw(SymKey* wrapping_key,
diff --git a/content/child/webcrypto/platform_crypto_nss.cc b/content/child/webcrypto/platform_crypto_nss.cc
index 478c7aa..75a73d8 100644
--- a/content/child/webcrypto/platform_crypto_nss.cc
+++ b/content/child/webcrypto/platform_crypto_nss.cc
@@ -6,6 +6,7 @@
 
 #include <cryptohi.h>
 #include <pk11pub.h>
+#include <secerr.h>
 #include <sechash.h>
 
 #include <vector>
@@ -24,6 +25,7 @@
 
 #if defined(USE_NSS)
 #include <dlfcn.h>
+#include <secoid.h>
 #endif
 
 // At the time of this writing:
@@ -413,22 +415,20 @@
   switch (algorithm.paramsType()) {
     case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams:
     case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams:
-      *key_algorithm = blink::WebCryptoKeyAlgorithm::adoptParamsAndCreate(
+      *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(
           algorithm.id(),
-          new blink::WebCryptoRsaHashedKeyAlgorithmParams(
-              modulus_length_bits,
-              public_exponent.bytes(),
-              public_exponent.byte_length(),
-              GetInnerHashAlgorithm(algorithm)));
+          modulus_length_bits,
+          public_exponent.bytes(),
+          public_exponent.byte_length(),
+          GetInnerHashAlgorithm(algorithm).id());
       return true;
     case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams:
     case blink::WebCryptoAlgorithmParamsTypeNone:
-      *key_algorithm = blink::WebCryptoKeyAlgorithm::adoptParamsAndCreate(
+      *key_algorithm = blink::WebCryptoKeyAlgorithm::createRsa(
           algorithm.id(),
-          new blink::WebCryptoRsaKeyAlgorithmParams(
-              modulus_length_bits,
-              public_exponent.bytes(),
-              public_exponent.byte_length()));
+          modulus_length_bits,
+          public_exponent.bytes(),
+          public_exponent.byte_length());
       return true;
     default:
       return false;
@@ -506,6 +506,13 @@
   // The plaintext length is always 64 bits less than the data size.
   const unsigned int plaintext_length = wrapped_key_data.byte_length() - 8;
 
+#if defined(USE_NSS)
+  // Part of workaround for
+  // https://bugzilla.mozilla.org/show_bug.cgi?id=981170. See the explanation
+  // later in this function.
+  PORT_SetError(0);
+#endif
+
   crypto::ScopedPK11SymKey new_key(PK11_UnwrapSymKey(wrapping_key->key(),
                                                      CKM_NSS_AES_KEY_WRAP,
                                                      param_item.get(),
@@ -519,39 +526,141 @@
   if (!new_key)
     return Status::Error();
 
-// TODO(padolph): Change to "defined(USE_NSS)" once the NSS fix for
-// https://bugzilla.mozilla.org/show_bug.cgi?id=981170 rolls into chromium.
-#if 1
-  // ------- Start NSS bug workaround
-  // Workaround for https://code.google.com/p/chromium/issues/detail?id=349939
-  // If unwrap fails, NSS nevertheless returns a valid-looking PK11SymKey, with
-  // a reasonable length but with key data pointing to uninitialized memory.
-  // This workaround re-wraps the key and compares the result with the incoming
-  // data, and fails if there is a difference. This prevents returning a bad key
-  // to the caller.
-  const unsigned int output_length = wrapped_key_data.byte_length();
-  std::vector<unsigned char> buffer(output_length, 0);
-  SECItem wrapped_key_item = MakeSECItemForBuffer(CryptoData(buffer));
-  if (SECSuccess != PK11_WrapSymKey(CKM_NSS_AES_KEY_WRAP,
-                                    param_item.get(),
-                                    wrapping_key->key(),
-                                    new_key.get(),
-                                    &wrapped_key_item)) {
+#if defined(USE_NSS)
+  // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=981170
+  // which was fixed in NSS 3.16.0.
+  // If unwrap fails, NSS nevertheless returns a valid-looking PK11SymKey,
+  // with a reasonable length but with key data pointing to uninitialized
+  // memory.
+  // To understand this workaround see the fix for 981170:
+  // https://hg.mozilla.org/projects/nss/rev/753bb69e543c
+  if (!NSS_VersionCheck("3.16") && PORT_GetError() == SEC_ERROR_BAD_DATA)
     return Status::Error();
-  }
-  if (wrapped_key_item.len != wrapped_key_data.byte_length() ||
-      memcmp(wrapped_key_item.data,
-             wrapped_key_data.bytes(),
-             wrapped_key_item.len) != 0) {
-    return Status::Error();
-  }
-// ------- End NSS bug workaround
 #endif
 
   *unwrapped_key = new_key.Pass();
   return Status::Success();
 }
 
+void CopySECItemToVector(const SECItem& item, std::vector<uint8>* out) {
+  out->assign(item.data, item.data + item.len);
+}
+
+// The system NSS library doesn't have the new PK11_ExportDERPrivateKeyInfo
+// function yet (https://bugzilla.mozilla.org/show_bug.cgi?id=519255). So we
+// provide a fallback implementation.
+#if defined(USE_NSS)
+// From PKCS#1 [http://tools.ietf.org/html/rfc3447]:
+//
+//    RSAPrivateKey ::= SEQUENCE {
+//      version           Version,
+//      modulus           INTEGER,  -- n
+//      publicExponent    INTEGER,  -- e
+//      privateExponent   INTEGER,  -- d
+//      prime1            INTEGER,  -- p
+//      prime2            INTEGER,  -- q
+//      exponent1         INTEGER,  -- d mod (p-1)
+//      exponent2         INTEGER,  -- d mod (q-1)
+//      coefficient       INTEGER,  -- (inverse of q) mod p
+//      otherPrimeInfos   OtherPrimeInfos OPTIONAL
+//    }
+//
+// Note that otherPrimeInfos is only applicable for version=1. Since NSS
+// doesn't use multi-prime can safely use version=0.
+struct RSAPrivateKey {
+  SECItem version;
+  SECItem modulus;
+  SECItem public_exponent;
+  SECItem private_exponent;
+  SECItem prime1;
+  SECItem prime2;
+  SECItem exponent1;
+  SECItem exponent2;
+  SECItem coefficient;
+};
+
+const SEC_ASN1Template RSAPrivateKeyTemplate[] = {
+    {SEC_ASN1_SEQUENCE, 0, NULL, sizeof(RSAPrivateKey)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, version)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, modulus)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, public_exponent)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, private_exponent)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime1)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, prime2)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent1)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, exponent2)},
+    {SEC_ASN1_INTEGER, offsetof(RSAPrivateKey, coefficient)},
+    {0}};
+
+// On success |value| will be filled with data which must be freed by
+// SECITEM_FreeItem(value, PR_FALSE);
+bool ReadUint(SECKEYPrivateKey* key,
+              CK_ATTRIBUTE_TYPE attribute,
+              SECItem* value) {
+  SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, key, attribute, value);
+
+  // PK11_ReadRawAttribute() returns items of type siBuffer. However in order
+  // for the ASN.1 encoding to be correct, the items must be of type
+  // siUnsignedInteger.
+  value->type = siUnsignedInteger;
+
+  return rv == SECSuccess;
+}
+
+// Fills |out| with the RSA private key properties. Returns true on success.
+// Regardless of the return value, the caller must invoke FreeRSAPrivateKey()
+// to free up any allocated memory.
+//
+// The passed in RSAPrivateKey must be zero-initialized.
+bool InitRSAPrivateKey(SECKEYPrivateKey* key, RSAPrivateKey* out) {
+  if (key->keyType != rsaKey)
+    return false;
+
+  // Everything should be zero-ed out. These are just some spot checks.
+  DCHECK(!out->version.data);
+  DCHECK(!out->version.len);
+  DCHECK(!out->modulus.data);
+  DCHECK(!out->modulus.len);
+
+  // Always use version=0 since not using multi-prime.
+  if (!SEC_ASN1EncodeInteger(NULL, &out->version, 0))
+    return false;
+
+  if (!ReadUint(key, CKA_MODULUS, &out->modulus))
+    return false;
+  if (!ReadUint(key, CKA_PUBLIC_EXPONENT, &out->public_exponent))
+    return false;
+  if (!ReadUint(key, CKA_PRIVATE_EXPONENT, &out->private_exponent))
+    return false;
+  if (!ReadUint(key, CKA_PRIME_1, &out->prime1))
+    return false;
+  if (!ReadUint(key, CKA_PRIME_2, &out->prime2))
+    return false;
+  if (!ReadUint(key, CKA_EXPONENT_1, &out->exponent1))
+    return false;
+  if (!ReadUint(key, CKA_EXPONENT_2, &out->exponent2))
+    return false;
+  if (!ReadUint(key, CKA_COEFFICIENT, &out->coefficient))
+    return false;
+
+  return true;
+}
+
+struct FreeRsaPrivateKey {
+  void operator()(RSAPrivateKey* out) {
+    SECITEM_FreeItem(&out->version, PR_FALSE);
+    SECITEM_FreeItem(&out->modulus, PR_FALSE);
+    SECITEM_FreeItem(&out->public_exponent, PR_FALSE);
+    SECITEM_FreeItem(&out->private_exponent, PR_FALSE);
+    SECITEM_FreeItem(&out->prime1, PR_FALSE);
+    SECITEM_FreeItem(&out->prime2, PR_FALSE);
+    SECITEM_FreeItem(&out->exponent1, PR_FALSE);
+    SECITEM_FreeItem(&out->exponent2, PR_FALSE);
+    SECITEM_FreeItem(&out->coefficient, PR_FALSE);
+  }
+};
+#endif  // defined(USE_NSS)
+
 }  // namespace
 
 Status ImportKeyRaw(const blink::WebCryptoAlgorithm& algorithm,
@@ -695,6 +804,77 @@
   return Status::Success();
 }
 
+Status ExportRsaPublicKey(PublicKey* key,
+                          std::vector<uint8>* modulus,
+                          std::vector<uint8>* public_exponent) {
+  DCHECK(key);
+  DCHECK(key->key());
+  if (key->key()->keyType != rsaKey)
+    return Status::ErrorUnsupported();
+  CopySECItemToVector(key->key()->u.rsa.modulus, modulus);
+  CopySECItemToVector(key->key()->u.rsa.publicExponent, public_exponent);
+  if (modulus->empty() || public_exponent->empty())
+    return Status::ErrorUnexpected();
+  return Status::Success();
+}
+
+Status ExportKeyPkcs8(PrivateKey* key,
+                      const blink::WebCryptoKeyAlgorithm& key_algorithm,
+                      blink::WebArrayBuffer* buffer) {
+  // TODO(eroman): Support other RSA key types as they are added to Blink.
+  if (key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5 &&
+      key_algorithm.id() != blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5)
+    return Status::ErrorUnsupported();
+
+#if defined(USE_NSS)
+  // PK11_ExportDERPrivateKeyInfo isn't available. Use our fallback code.
+  const SECOidTag algorithm = SEC_OID_PKCS1_RSA_ENCRYPTION;
+  const int kPrivateKeyInfoVersion = 0;
+
+  SECKEYPrivateKeyInfo private_key_info = {};
+  RSAPrivateKey rsa_private_key = {};
+  scoped_ptr<RSAPrivateKey, FreeRsaPrivateKey> free_private_key(
+      &rsa_private_key);
+
+  if (!InitRSAPrivateKey(key->key(), &rsa_private_key))
+    return Status::Error();
+
+  crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
+  if (!arena.get())
+    return Status::Error();
+
+  if (!SEC_ASN1EncodeItem(arena.get(),
+                          &private_key_info.privateKey,
+                          &rsa_private_key,
+                          RSAPrivateKeyTemplate))
+    return Status::Error();
+
+  if (SECSuccess !=
+      SECOID_SetAlgorithmID(
+          arena.get(), &private_key_info.algorithm, algorithm, NULL))
+    return Status::Error();
+
+  if (!SEC_ASN1EncodeInteger(
+          arena.get(), &private_key_info.version, kPrivateKeyInfoVersion))
+    return Status::Error();
+
+  crypto::ScopedSECItem encoded_key(
+      SEC_ASN1EncodeItem(NULL,
+                         NULL,
+                         &private_key_info,
+                         SEC_ASN1_GET(SECKEY_PrivateKeyInfoTemplate)));
+#else  // defined(USE_NSS)
+  crypto::ScopedSECItem encoded_key(
+      PK11_ExportDERPrivateKeyInfo(key->key(), NULL));
+#endif  // defined(USE_NSS)
+
+  if (!encoded_key.get())
+    return Status::Error();
+
+  *buffer = CreateArrayBuffer(encoded_key->data, encoded_key->len);
+  return Status::Success();
+}
+
 Status ImportKeyPkcs8(const blink::WebCryptoAlgorithm& algorithm,
                       const CryptoData& key_data,
                       bool extractable,
@@ -984,7 +1164,11 @@
   }
   const CK_FLAGS operation_flags_mask =
       CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_VERIFY | CKF_WRAP | CKF_UNWRAP;
-  const PK11AttrFlags attribute_flags = 0;  // Default all PK11_ATTR_ flags.
+
+  // The private key must be marked as insensitive and extractable, otherwise it
+  // cannot later be exported in unencrypted form or structured-cloned.
+  const PK11AttrFlags attribute_flags =
+      PK11_ATTR_INSENSITIVE | PK11_ATTR_EXTRACTABLE;
 
   // Note: NSS does not generate an sec_public_key if the call below fails,
   // so there is no danger of a leaked sec_public_key.
diff --git a/content/child/webcrypto/platform_crypto_openssl.cc b/content/child/webcrypto/platform_crypto_openssl.cc
index 5fdee39..46a20e4 100644
--- a/content/child/webcrypto/platform_crypto_openssl.cc
+++ b/content/child/webcrypto/platform_crypto_openssl.cc
@@ -387,6 +387,20 @@
   return Status::ErrorUnsupported();
 }
 
+Status ExportKeyPkcs8(PrivateKey* key,
+                      const blink::WebCryptoKeyAlgorithm& key_algorithm,
+                      blink::WebArrayBuffer* buffer) {
+  // TODO(eroman): http://crbug.com/267888
+  return Status::ErrorUnsupported();
+}
+
+Status ExportRsaPublicKey(PublicKey* key,
+                          std::vector<uint8>* modulus,
+                          std::vector<uint8>* public_exponent) {
+  // TODO(eroman): http://crbug.com/267888
+  return Status::ErrorUnsupported();
+}
+
 Status WrapSymKeyAesKw(SymKey* wrapping_key,
                        SymKey* key,
                        blink::WebArrayBuffer* buffer) {
diff --git a/content/child/webcrypto/shared_crypto.cc b/content/child/webcrypto/shared_crypto.cc
index c5b116e..92aa342 100644
--- a/content/child/webcrypto/shared_crypto.cc
+++ b/content/child/webcrypto/shared_crypto.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "content/child/webcrypto/crypto_data.h"
+#include "content/child/webcrypto/jwk.h"
 #include "content/child/webcrypto/platform_crypto.h"
 #include "content/child/webcrypto/status.h"
 #include "content/child/webcrypto/webcrypto_util.h"
@@ -483,6 +484,21 @@
       wrapping_algorithm, wrapping_key, CryptoData(exported_data), buffer);
 }
 
+// Returns the internal block size for SHA-*
+unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) {
+  switch (hash_id) {
+    case blink::WebCryptoAlgorithmIdSha1:
+    case blink::WebCryptoAlgorithmIdSha256:
+      return 64;
+    case blink::WebCryptoAlgorithmIdSha384:
+    case blink::WebCryptoAlgorithmIdSha512:
+      return 128;
+    default:
+      NOTREACHED();
+      return 0;
+  }
+}
+
 }  // namespace
 
 void Init() { platform::Init(); }
@@ -646,11 +662,15 @@
         return status;
       return platform::ExportKeySpki(public_key, buffer);
     }
+    case blink::WebCryptoKeyFormatPkcs8: {
+      platform::PrivateKey* private_key;
+      Status status = ToPlatformPrivateKey(key, &private_key);
+      if (status.IsError())
+        return status;
+      return platform::ExportKeyPkcs8(private_key, key.algorithm(), buffer);
+    }
     case blink::WebCryptoKeyFormatJwk:
       return ExportKeyJwk(key, buffer);
-    case blink::WebCryptoKeyFormatPkcs8:
-      // TODO(eroman):
-      return Status::ErrorUnsupported();
     default:
       return Status::ErrorUnsupported();
   }
diff --git a/content/child/webcrypto/shared_crypto.h b/content/child/webcrypto/shared_crypto.h
index e341f59..50ce592 100644
--- a/content/child/webcrypto/shared_crypto.h
+++ b/content/child/webcrypto/shared_crypto.h
@@ -17,7 +17,6 @@
 namespace webcrypto {
 
 class CryptoData;
-
 class Status;
 
 // Do one-time initialization. It is safe to call this multiple times.
@@ -123,15 +122,6 @@
                     const CryptoData& data,
                     bool* signature_match);
 
-CONTENT_EXPORT Status ImportKeyJwk(const CryptoData& key_data,
-                                   const blink::WebCryptoAlgorithm& algorithm,
-                                   bool extractable,
-                                   blink::WebCryptoKeyUsageMask usage_mask,
-                                   blink::WebCryptoKey* key);
-
-CONTENT_EXPORT Status
-    ExportKeyJwk(const blink::WebCryptoKey& key, blink::WebArrayBuffer* buffer);
-
 CONTENT_EXPORT Status
     WrapKey(blink::WebCryptoKeyFormat format,
             const blink::WebCryptoKey& wrapping_key,
diff --git a/content/child/webcrypto/shared_crypto_unittest.cc b/content/child/webcrypto/shared_crypto_unittest.cc
index 6995b48..258d108 100644
--- a/content/child/webcrypto/shared_crypto_unittest.cc
+++ b/content/child/webcrypto/shared_crypto_unittest.cc
@@ -516,6 +516,19 @@
   return Decrypt(algorithm, key, CryptoData(cipher_text_with_tag), plain_text);
 }
 
+Status ImportKeyJwk(const CryptoData& key_data,
+                    const blink::WebCryptoAlgorithm& algorithm,
+                    bool extractable,
+                    blink::WebCryptoKeyUsageMask usage_mask,
+                    blink::WebCryptoKey* key) {
+  return ImportKey(blink::WebCryptoKeyFormatJwk,
+                   key_data,
+                   algorithm,
+                   extractable,
+                   usage_mask,
+                   key);
+}
+
 Status ImportKeyJwkFromDict(const base::DictionaryValue& dict,
                             const blink::WebCryptoAlgorithm& algorithm,
                             bool extractable,
@@ -540,25 +553,22 @@
   return scoped_ptr<base::DictionaryValue>(dict_value);
 }
 
-// Verifies that the JSON in the input ArrayBuffer contains the provided
-// expected values. Exact matches are required on the fields examined.
-::testing::AssertionResult VerifySymmetricJwk(
-    const blink::WebArrayBuffer& json,
+// Verifies the input dictionary contains the expected values. Exact matches are
+// required on the fields examined.
+::testing::AssertionResult VerifyJwk(
+    const scoped_ptr<base::DictionaryValue>& dict,
+    const std::string& kty_expected,
     const std::string& alg_expected,
-    const std::string& k_expected_hex,
     blink::WebCryptoKeyUsageMask use_mask_expected) {
 
-  scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
-  if (!dict.get() || dict->empty())
-    return ::testing::AssertionFailure() << "JSON parsing failed";
-
   // ---- kty
   std::string value_string;
   if (!dict->GetString("kty", &value_string))
     return ::testing::AssertionFailure() << "Missing 'kty'";
-  if (value_string != "oct")
-    return ::testing::AssertionFailure()
-           << "Expected 'kty' to be 'oct' but found " << value_string;
+  if (value_string != kty_expected)
+    return ::testing::AssertionFailure() << "Expected 'kty' to be "
+                                         << kty_expected << "but found "
+                                         << value_string;
 
   // ---- alg
   if (!dict->GetString("alg", &value_string))
@@ -568,18 +578,6 @@
                                          << alg_expected << " but found "
                                          << value_string;
 
-  // ---- k
-  if (!dict->GetString("k", &value_string))
-    return ::testing::AssertionFailure() << "Missing 'k'";
-  std::string k_value;
-  if (!webcrypto::Base64DecodeUrlSafe(value_string, &k_value))
-    return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
-  if (!LowerCaseEqualsASCII(base::HexEncode(k_value.data(), k_value.size()),
-                            k_expected_hex.c_str())) {
-    return ::testing::AssertionFailure() << "Expected 'k' to be "
-                                         << k_expected_hex
-                                         << " but found something different";
-  }
   // ---- ext
   // always expect ext == true in this case
   bool ext_value;
@@ -605,6 +603,75 @@
   return ::testing::AssertionSuccess();
 }
 
+// Verifies that the JSON in the input ArrayBuffer contains the provided
+// expected values. Exact matches are required on the fields examined.
+::testing::AssertionResult VerifySecretJwk(
+    const blink::WebArrayBuffer& json,
+    const std::string& alg_expected,
+    const std::string& k_expected_hex,
+    blink::WebCryptoKeyUsageMask use_mask_expected) {
+  scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
+  if (!dict.get() || dict->empty())
+    return ::testing::AssertionFailure() << "JSON parsing failed";
+
+  // ---- k
+  std::string value_string;
+  if (!dict->GetString("k", &value_string))
+    return ::testing::AssertionFailure() << "Missing 'k'";
+  std::string k_value;
+  if (!webcrypto::Base64DecodeUrlSafe(value_string, &k_value))
+    return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(k) failed";
+  if (!LowerCaseEqualsASCII(base::HexEncode(k_value.data(), k_value.size()),
+                            k_expected_hex.c_str())) {
+    return ::testing::AssertionFailure() << "Expected 'k' to be "
+                                         << k_expected_hex
+                                         << " but found something different";
+  }
+
+  return VerifyJwk(dict, "oct", alg_expected, use_mask_expected);
+}
+
+// Verifies that the JSON in the input ArrayBuffer contains the provided
+// expected values. Exact matches are required on the fields examined.
+::testing::AssertionResult VerifyPublicJwk(
+    const blink::WebArrayBuffer& json,
+    const std::string& alg_expected,
+    const std::string& n_expected_hex,
+    const std::string& e_expected_hex,
+    blink::WebCryptoKeyUsageMask use_mask_expected) {
+  scoped_ptr<base::DictionaryValue> dict = GetJwkDictionary(json);
+  if (!dict.get() || dict->empty())
+    return ::testing::AssertionFailure() << "JSON parsing failed";
+
+  // ---- n
+  std::string value_string;
+  if (!dict->GetString("n", &value_string))
+    return ::testing::AssertionFailure() << "Missing 'n'";
+  std::string n_value;
+  if (!webcrypto::Base64DecodeUrlSafe(value_string, &n_value))
+    return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(n) failed";
+  if (base::HexEncode(n_value.data(), n_value.size()) != n_expected_hex) {
+    return ::testing::AssertionFailure() << "'n' does not match the expected "
+                                            "value";
+  }
+  // TODO(padolph): LowerCaseEqualsASCII() does not work for above!
+
+  // ---- e
+  if (!dict->GetString("e", &value_string))
+    return ::testing::AssertionFailure() << "Missing 'e'";
+  std::string e_value;
+  if (!webcrypto::Base64DecodeUrlSafe(value_string, &e_value))
+    return ::testing::AssertionFailure() << "Base64DecodeUrlSafe(e) failed";
+  if (!LowerCaseEqualsASCII(base::HexEncode(e_value.data(), e_value.size()),
+                            e_expected_hex.c_str())) {
+    return ::testing::AssertionFailure() << "Expected 'e' to be "
+                                         << e_expected_hex
+                                         << " but found something different";
+  }
+
+  return VerifyJwk(dict, "RSA", alg_expected, use_mask_expected);
+}
+
 }  // namespace
 
 TEST_F(SharedCryptoTest, CheckAesGcm) {
@@ -810,7 +877,7 @@
   // keys).
   EXPECT_STATUS(Status::ErrorUnexpectedKeyType(),
                 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
-  EXPECT_STATUS(Status::ErrorUnsupported(),
+  EXPECT_STATUS(Status::ErrorUnexpectedKeyType(),
                 ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &output));
 }
 
@@ -1270,6 +1337,85 @@
   RestoreJwkOctDictionary(&dict);
 }
 
+TEST_F(SharedCryptoTest, MAYBE(ImportExportJwkRsaPublicKey)) {
+  // This test uses kPublicKeySpkiDerHex as the RSA key. The data below
+  // represents the modulus and public exponent extracted from this SPKI blob.
+  // These values appear explicitly in the JWK rendering of the key.
+  const std::string n_hex =
+      "A56E4A0E701017589A5187DC7EA841D156F2EC0E36AD52A44DFEB1E61F7AD991D8C51056"
+      "FFEDB162B4C0F283A12A88A394DFF526AB7291CBB307CEABFCE0B1DFD5CD9508096D5B2B"
+      "8B6DF5D671EF6377C0921CB23C270A70E2598E6FF89D19F105ACC2D3F0CB35F29280E138"
+      "6B6F64C4EF22E1E1F20D0CE8CFFB2249BD9A2137";
+  const std::string e_hex = "010001";
+
+  struct TestCase {
+    const blink::WebCryptoAlgorithm algorithm;
+    const blink::WebCryptoKeyUsageMask usage;
+    const char* const jwk_alg;
+  };
+  const TestCase kTests[] = {
+      // RSAES-PKCS1-v1_5
+      {CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
+       blink::WebCryptoKeyUsageEncrypt, "RSA1_5"},
+      // RSASSA-PKCS1-v1_5 SHA-1
+      {CreateRsaHashedImportAlgorithm(
+           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+           blink::WebCryptoAlgorithmIdSha1),
+       blink::WebCryptoKeyUsageSign, "RS1"},
+      // RSASSA-PKCS1-v1_5 SHA-256
+      {CreateRsaHashedImportAlgorithm(
+           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+           blink::WebCryptoAlgorithmIdSha256),
+       blink::WebCryptoKeyUsageSign, "RS256"},
+      // RSASSA-PKCS1-v1_5 SHA-384
+      {CreateRsaHashedImportAlgorithm(
+           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+           blink::WebCryptoAlgorithmIdSha384),
+       blink::WebCryptoKeyUsageSign, "RS384"},
+      // RSASSA-PKCS1-v1_5 SHA-512
+      {CreateRsaHashedImportAlgorithm(
+           blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5,
+           blink::WebCryptoAlgorithmIdSha512),
+       blink::WebCryptoKeyUsageSign, "RS512"}};
+
+  for (size_t test_index = 0; test_index < ARRAYSIZE_UNSAFE(kTests);
+       ++test_index) {
+    SCOPED_TRACE(test_index);
+    const TestCase& test = kTests[test_index];
+
+    // Import the spki to create a public key
+    blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
+    ASSERT_STATUS_SUCCESS(
+        ImportKey(blink::WebCryptoKeyFormatSpki,
+                  CryptoData(HexStringToBytes(kPublicKeySpkiDerHex)),
+                  test.algorithm,
+                  true,
+                  test.usage,
+                  &public_key));
+
+    // Export the public key as JWK and verify its contents
+    blink::WebArrayBuffer jwk;
+    ASSERT_STATUS_SUCCESS(
+        ExportKey(blink::WebCryptoKeyFormatJwk, public_key, &jwk));
+    EXPECT_TRUE(VerifyPublicJwk(jwk, test.jwk_alg, n_hex, e_hex, test.usage));
+
+    // Import the JWK back in to create a new key
+    blink::WebCryptoKey public_key2 = blink::WebCryptoKey::createNull();
+    EXPECT_STATUS_SUCCESS(ImportKeyJwk(
+        CryptoData(jwk), test.algorithm, true, test.usage, &public_key2));
+    EXPECT_TRUE(public_key2.handle());
+    EXPECT_EQ(blink::WebCryptoKeyTypePublic, public_key2.type());
+    EXPECT_EQ(true, public_key2.extractable());
+    EXPECT_EQ(test.algorithm.id(), public_key2.algorithm().id());
+
+    // Export the new key as spki and compare to the original.
+    blink::WebArrayBuffer spki;
+    ASSERT_STATUS_SUCCESS(
+        ExportKey(blink::WebCryptoKeyFormatSpki, public_key2, &spki));
+    ExpectCryptoDataMatchesHex(kPublicKeySpkiDerHex, CryptoData(spki));
+  }
+}
+
 TEST_F(SharedCryptoTest, MAYBE(ImportJwkRsaFailures)) {
   base::DictionaryValue dict;
   RestoreJwkRsaDictionary(&dict);
@@ -1587,9 +1733,8 @@
         HexStringToBytes(test.key_hex), test.algorithm, test.usage);
 
     // Export the key in JWK format and validate.
-    ASSERT_STATUS_SUCCESS(ExportKeyJwk(key, &json));
-    EXPECT_TRUE(
-        VerifySymmetricJwk(json, test.jwk_alg, test.key_hex, test.usage));
+    ASSERT_STATUS_SUCCESS(ExportKey(blink::WebCryptoKeyFormatJwk, key, &json));
+    EXPECT_TRUE(VerifySecretJwk(json, test.jwk_alg, test.key_hex, test.usage));
 
     // Import the JWK-formatted key.
     ASSERT_STATUS_SUCCESS(
@@ -1681,7 +1826,7 @@
                 ExportKey(blink::WebCryptoKeyFormatSpki, key, &output));
 }
 
-TEST_F(SharedCryptoTest, MAYBE(ImportPkcs8)) {
+TEST_F(SharedCryptoTest, MAYBE(ImportExportPkcs8)) {
   // Passing case: Import a valid RSA key in PKCS#8 format.
   blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
   ASSERT_STATUS_SUCCESS(ImportKey(
@@ -1704,6 +1849,11 @@
       "010001",
       CryptoData(key.algorithm().rsaHashedParams()->publicExponent()));
 
+  blink::WebArrayBuffer exported_key;
+  ASSERT_STATUS_SUCCESS(
+      ExportKey(blink::WebCryptoKeyFormatPkcs8, key, &exported_key));
+  ExpectArrayBufferMatchesHex(kPrivateKeyPkcs8DerHex, exported_key);
+
   // Failing case: Empty PKCS#8 data
   EXPECT_STATUS(Status::ErrorImportEmptyKeyData(),
                 ImportKey(blink::WebCryptoKeyFormatPkcs8,
@@ -1745,7 +1895,7 @@
       CreateRsaKeyGenAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5,
                                modulus_length,
                                public_exponent);
-  bool extractable = false;
+  bool extractable = true;
   const blink::WebCryptoKeyUsageMask usage_mask = 0;
   blink::WebCryptoKey public_key = blink::WebCryptoKey::createNull();
   blink::WebCryptoKey private_key = blink::WebCryptoKey::createNull();
@@ -1760,6 +1910,36 @@
   EXPECT_EQ(usage_mask, public_key.usages());
   EXPECT_EQ(usage_mask, private_key.usages());
 
+  // Try exporting the generated key pair, and then re-importing to verify that
+  // the exported data was valid.
+  blink::WebArrayBuffer public_key_spki;
+  EXPECT_STATUS_SUCCESS(
+      ExportKey(blink::WebCryptoKeyFormatSpki, public_key, &public_key_spki));
+  public_key = blink::WebCryptoKey::createNull();
+  EXPECT_STATUS_SUCCESS(
+      ImportKey(blink::WebCryptoKeyFormatSpki,
+                CryptoData(public_key_spki),
+                CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
+                true,
+                usage_mask,
+                &public_key));
+  EXPECT_EQ(modulus_length,
+            public_key.algorithm().rsaParams()->modulusLengthBits());
+
+  blink::WebArrayBuffer private_key_pkcs8;
+  EXPECT_STATUS_SUCCESS(ExportKey(
+      blink::WebCryptoKeyFormatPkcs8, private_key, &private_key_pkcs8));
+  private_key = blink::WebCryptoKey::createNull();
+  EXPECT_STATUS_SUCCESS(
+      ImportKey(blink::WebCryptoKeyFormatPkcs8,
+                CryptoData(private_key_pkcs8),
+                CreateAlgorithm(blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5),
+                true,
+                usage_mask,
+                &private_key));
+  EXPECT_EQ(modulus_length,
+            private_key.algorithm().rsaParams()->modulusLengthBits());
+
   // Fail with bad modulus.
   algorithm = CreateRsaKeyGenAlgorithm(
       blink::WebCryptoAlgorithmIdRsaEsPkcs1v1_5, 0, public_exponent);
diff --git a/content/child/webcrypto/webcrypto_impl.cc b/content/child/webcrypto/webcrypto_impl.cc
index d0c5196..076df0d 100644
--- a/content/child/webcrypto/webcrypto_impl.cc
+++ b/content/child/webcrypto/webcrypto_impl.cc
@@ -195,6 +195,47 @@
     result.completeWithBoolean(signature_match);
 }
 
+void WebCryptoImpl::wrapKey(blink::WebCryptoKeyFormat format,
+                            const blink::WebCryptoKey& key,
+                            const blink::WebCryptoKey& wrapping_key,
+                            const blink::WebCryptoAlgorithm& wrap_algorithm,
+                            blink::WebCryptoResult result) {
+  blink::WebArrayBuffer buffer;
+  // TODO(eroman): Use the same parameter ordering.
+  Status status = webcrypto::WrapKey(
+      format, wrapping_key, key, wrap_algorithm, &buffer);
+  if (status.IsError())
+    CompleteWithError(status, &result);
+  else
+    result.completeWithBuffer(buffer);
+}
+
+void WebCryptoImpl::unwrapKey(
+    blink::WebCryptoKeyFormat format,
+    const unsigned char* wrapped_key,
+    unsigned wrapped_key_size,
+    const blink::WebCryptoKey& wrapping_key,
+    const blink::WebCryptoAlgorithm& unwrap_algorithm,
+    const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
+    bool extractable,
+    blink::WebCryptoKeyUsageMask usages,
+    blink::WebCryptoResult result) {
+  blink::WebCryptoKey key = blink::WebCryptoKey::createNull();
+  Status status =
+      webcrypto::UnwrapKey(format,
+                           webcrypto::CryptoData(wrapped_key, wrapped_key_size),
+                           wrapping_key,
+                           unwrap_algorithm,
+                           unwrapped_key_algorithm,
+                           extractable,
+                           usages,
+                           &key);
+  if (status.IsError())
+    CompleteWithError(status, &result);
+  else
+    result.completeWithKey(key);
+}
+
 bool WebCryptoImpl::digestSynchronous(
     const blink::WebCryptoAlgorithmId algorithm_id,
     const unsigned char* data,
diff --git a/content/child/webcrypto/webcrypto_impl.h b/content/child/webcrypto/webcrypto_impl.h
index 9cc7c36..bdb3928 100644
--- a/content/child/webcrypto/webcrypto_impl.h
+++ b/content/child/webcrypto/webcrypto_impl.h
@@ -61,7 +61,22 @@
                                unsigned int signature_size,
                                const unsigned char* data,
                                unsigned int data_size,
-                               blink::WebCryptoResult result);
+                              blink::WebCryptoResult result);
+  virtual void wrapKey(blink::WebCryptoKeyFormat format,
+                       const blink::WebCryptoKey& key,
+                       const blink::WebCryptoKey& wrapping_key,
+                       const blink::WebCryptoAlgorithm& wrap_algorithm,
+                       blink::WebCryptoResult result);
+  virtual void unwrapKey(
+      blink::WebCryptoKeyFormat format,
+      const unsigned char* wrapped_key,
+      unsigned wrapped_key_size,
+      const blink::WebCryptoKey& wrapping_key,
+      const blink::WebCryptoAlgorithm& unwrap_algorithm,
+      const blink::WebCryptoAlgorithm& unwrapped_key_algorithm,
+      bool extractable,
+      blink::WebCryptoKeyUsageMask usages,
+      blink::WebCryptoResult result);
   // This method synchronously computes a digest for the given data, returning
   // |true| if successful and |false| otherwise.
   virtual bool digestSynchronous(const blink::WebCryptoAlgorithmId algorithm_id,
diff --git a/content/child/webcrypto/webcrypto_util.cc b/content/child/webcrypto/webcrypto_util.cc
index 294c4b2..0438274 100644
--- a/content/child/webcrypto/webcrypto_util.cc
+++ b/content/child/webcrypto/webcrypto_util.cc
@@ -67,6 +67,12 @@
   return output;
 }
 
+std::string Base64EncodeUrlSafe(const std::vector<uint8>& input) {
+  const base::StringPiece string_piece(
+      reinterpret_cast<const char*>(Uint8VectorStart(input)), input.size());
+  return Base64EncodeUrlSafe(string_piece);
+}
+
 struct JwkToWebCryptoUsage {
   const char* const jwk_key_op;
   const blink::WebCryptoKeyUsage webcrypto_usage;
@@ -169,32 +175,6 @@
       id, new blink::WebCryptoRsaHashedImportParams(CreateAlgorithm(hash_id)));
 }
 
-blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm(
-    blink::WebCryptoAlgorithmId hash_id) {
-  return CreateRsaHashedImportAlgorithm(
-      blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, hash_id);
-}
-
-blink::WebCryptoAlgorithm CreateRsaOaepImportAlgorithm(
-    blink::WebCryptoAlgorithmId hash_id) {
-  return CreateRsaHashedImportAlgorithm(blink::WebCryptoAlgorithmIdRsaOaep,
-                                        hash_id);
-}
-
-unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id) {
-  switch (hash_id) {
-    case blink::WebCryptoAlgorithmIdSha1:
-    case blink::WebCryptoAlgorithmIdSha256:
-      return 64;
-    case blink::WebCryptoAlgorithmIdSha384:
-    case blink::WebCryptoAlgorithmIdSha512:
-      return 128;
-    default:
-      NOTREACHED();
-      return 0;
-  }
-}
-
 bool CreateSecretKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
                               unsigned int keylen_bytes,
                               blink::WebCryptoKeyAlgorithm* key_algorithm) {
@@ -205,18 +185,16 @@
         return false;
       if (keylen_bytes > UINT_MAX / 8)
         return false;
-      *key_algorithm = blink::WebCryptoKeyAlgorithm::adoptParamsAndCreate(
-          algorithm.id(),
-          new blink::WebCryptoHmacKeyAlgorithmParams(hash, keylen_bytes * 8));
+      *key_algorithm =
+          blink::WebCryptoKeyAlgorithm::createHmac(hash.id(), keylen_bytes * 8);
       return true;
     }
     case blink::WebCryptoAlgorithmIdAesKw:
     case blink::WebCryptoAlgorithmIdAesCbc:
     case blink::WebCryptoAlgorithmIdAesCtr:
     case blink::WebCryptoAlgorithmIdAesGcm:
-      *key_algorithm = blink::WebCryptoKeyAlgorithm::adoptParamsAndCreate(
-          algorithm.id(),
-          new blink::WebCryptoAesKeyAlgorithmParams(keylen_bytes * 8));
+      *key_algorithm = blink::WebCryptoKeyAlgorithm::createAes(
+          algorithm.id(), keylen_bytes * 8);
       return true;
     default:
       return false;
diff --git a/content/child/webcrypto/webcrypto_util.h b/content/child/webcrypto/webcrypto_util.h
index e8e9dcc..60f0dbd 100644
--- a/content/child/webcrypto/webcrypto_util.h
+++ b/content/child/webcrypto/webcrypto_util.h
@@ -12,7 +12,6 @@
 #include "base/values.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebArrayBuffer.h"
-#include "third_party/WebKit/public/platform/WebCrypto.h"  // TODO(eroman): delete
 #include "third_party/WebKit/public/platform/WebCryptoAlgorithm.h"
 #include "third_party/WebKit/public/platform/WebCryptoKey.h"
 
@@ -36,7 +35,6 @@
 blink::WebArrayBuffer CreateArrayBuffer(const uint8* data,
                                         unsigned int data_size);
 
-// TODO(eroman): Move this to JWK file.
 // This function decodes unpadded 'base64url' encoded data, as described in
 // RFC4648 (http://www.ietf.org/rfc/rfc4648.txt) Section 5.
 // In Web Crypto, this type of encoding is only used inside JWK.
@@ -46,6 +44,7 @@
 // Returns an unpadded 'base64url' encoding of the input data, the opposite of
 // Base64DecodeUrlSafe() above.
 std::string Base64EncodeUrlSafe(const base::StringPiece& input);
+std::string Base64EncodeUrlSafe(const std::vector<uint8>& input);
 
 // Composes a Web Crypto usage mask from an array of JWK key_ops values.
 CONTENT_EXPORT Status GetWebCryptoUsagesFromJwkKeyOps(
@@ -79,21 +78,6 @@
     blink::WebCryptoAlgorithmId id,
     blink::WebCryptoAlgorithmId hash_id);
 
-// TODO(eroman): Move these to jwk.cc
-// Creates an RSASSA-PKCS1-v1_5 algorithm. It is an error to call this with a
-// hash_id that is not a SHA*.
-blink::WebCryptoAlgorithm CreateRsaSsaImportAlgorithm(
-    blink::WebCryptoAlgorithmId hash_id);
-
-// Creates an RSA-OAEP algorithm. It is an error to call this with a hash_id
-// that is not a SHA*.
-blink::WebCryptoAlgorithm CreateRsaOaepImportAlgorithm(
-    blink::WebCryptoAlgorithmId hash_id);
-
-// TODO(eroman): Move to shared_crypto.cc
-// Returns the internal block size for SHA-*
-unsigned int ShaBlockSizeBytes(blink::WebCryptoAlgorithmId hash_id);
-
 bool CreateSecretKeyAlgorithm(const blink::WebCryptoAlgorithm& algorithm,
                               unsigned int keylen_bytes,
                               blink::WebCryptoKeyAlgorithm* key_algorithm);
diff --git a/content/child/webfileutilities_impl.cc b/content/child/webfileutilities_impl.cc
index 9c05596..5188e51 100644
--- a/content/child/webfileutilities_impl.cc
+++ b/content/child/webfileutilities_impl.cc
@@ -31,7 +31,6 @@
     NOTREACHED();
     return false;
   }
-  // TODO(rvargas): convert this code to use base::File::Info.
   base::File::Info file_info;
   if (!base::GetFileInfo(base::FilePath::FromUTF16Unsafe(path),
                          reinterpret_cast<base::File::Info*>(&file_info)))
@@ -54,34 +53,4 @@
   return net::FilePathToFileURL(base::FilePath::FromUTF16Unsafe(path));
 }
 
-base::PlatformFile WebFileUtilitiesImpl::openFile(const WebString& path,
-                                                  int mode) {
-  if (sandbox_enabled_) {
-    NOTREACHED();
-    return base::kInvalidPlatformFileValue;
-  }
-  // mode==0 (read-only) is the only supported mode.
-  // TODO(kinuko): Remove this parameter.
-  DCHECK_EQ(0, mode);
-  return base::CreatePlatformFile(
-      base::FilePath::FromUTF16Unsafe(path),
-      base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ,
-      NULL, NULL);
-}
-
-void WebFileUtilitiesImpl::closeFile(base::PlatformFile& handle) {
-  if (handle == base::kInvalidPlatformFileValue)
-    return;
-  if (base::ClosePlatformFile(handle))
-    handle = base::kInvalidPlatformFileValue;
-}
-
-int WebFileUtilitiesImpl::readFromFile(base::PlatformFile handle,
-                                       char* data,
-                                       int length) {
-  if (handle == base::kInvalidPlatformFileValue || !data || length <= 0)
-    return -1;
-  return base::ReadPlatformFileCurPosNoBestEffort(handle, data, length);
-}
-
 }  // namespace content
diff --git a/content/child/webfileutilities_impl.h b/content/child/webfileutilities_impl.h
index c0119b6..46e2947 100644
--- a/content/child/webfileutilities_impl.h
+++ b/content/child/webfileutilities_impl.h
@@ -5,7 +5,6 @@
 #ifndef CONTENT_CHILD_WEBFILEUTILITIES_IMPL_H_
 #define CONTENT_CHILD_WEBFILEUTILITIES_IMPL_H_
 
-#include "base/platform_file.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebFileInfo.h"
 #include "third_party/WebKit/public/platform/WebFileUtilities.h"
@@ -24,9 +23,6 @@
   virtual blink::WebString directoryName(const blink::WebString& path);
   virtual blink::WebString baseName(const blink::WebString& path);
   virtual blink::WebURL filePathToURL(const blink::WebString& path);
-  virtual base::PlatformFile openFile(const blink::WebString& path, int mode);
-  virtual void closeFile(base::PlatformFile& handle);
-  virtual int readFromFile(base::PlatformFile handle, char* data, int length);
 
   void set_sandbox_enabled(bool sandbox_enabled) {
     sandbox_enabled_ = sandbox_enabled;
diff --git a/content/child/webkitplatformsupport_child_impl.cc b/content/child/webkitplatformsupport_child_impl.cc
deleted file mode 100644
index f3138c1..0000000
--- a/content/child/webkitplatformsupport_child_impl.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/webkitplatformsupport_child_impl.h"
-
-#include "base/memory/discardable_memory.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
-#include "base/synchronization/waitable_event.h"
-#include "content/child/fling_curve_configuration.h"
-#include "content/child/web_discardable_memory_impl.h"
-#include "content/child/webthread_impl.h"
-#include "content/child/worker_task_runner.h"
-#include "third_party/WebKit/public/platform/WebWaitableEvent.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-#if defined(OS_ANDROID)
-#include "content/child/fling_animator_impl_android.h"
-#endif
-
-using blink::WebFallbackThemeEngine;
-using blink::WebThemeEngine;
-
-namespace content {
-
-namespace {
-
-class WebWaitableEventImpl : public blink::WebWaitableEvent {
- public:
-  WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {}
-  virtual ~WebWaitableEventImpl() {}
-
-  virtual void wait() { impl_->Wait(); }
-  virtual void signal() { impl_->Signal(); }
-
-  base::WaitableEvent* impl() {
-    return impl_.get();
-  }
-
- private:
-  scoped_ptr<base::WaitableEvent> impl_;
-  DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl);
-};
-
-}  // namespace
-
-WebKitPlatformSupportChildImpl::WebKitPlatformSupportChildImpl()
-    : current_thread_slot_(&DestroyCurrentThread),
-      fling_curve_configuration_(new FlingCurveConfiguration) {}
-
-WebKitPlatformSupportChildImpl::~WebKitPlatformSupportChildImpl() {}
-
-WebThemeEngine* WebKitPlatformSupportChildImpl::themeEngine() {
-  return &native_theme_engine_;
-}
-
-WebFallbackThemeEngine* WebKitPlatformSupportChildImpl::fallbackThemeEngine() {
-  return &fallback_theme_engine_;
-}
-
-void WebKitPlatformSupportChildImpl::SetFlingCurveParameters(
-    const std::vector<float>& new_touchpad,
-    const std::vector<float>& new_touchscreen) {
-  fling_curve_configuration_->SetCurveParameters(new_touchpad, new_touchscreen);
-}
-
-blink::WebGestureCurve*
-WebKitPlatformSupportChildImpl::createFlingAnimationCurve(
-    int device_source,
-    const blink::WebFloatPoint& velocity,
-    const blink::WebSize& cumulative_scroll) {
-#if defined(OS_ANDROID)
-  return content::FlingAnimatorImpl::CreateAndroidGestureCurve(
-      velocity,
-      cumulative_scroll);
-#endif
-
-  if (device_source == blink::WebGestureEvent::Touchscreen)
-    return fling_curve_configuration_->CreateForTouchScreen(velocity,
-                                                            cumulative_scroll);
-
-  return fling_curve_configuration_->CreateForTouchPad(velocity,
-                                                       cumulative_scroll);
-}
-
-blink::WebThread* WebKitPlatformSupportChildImpl::createThread(
-    const char* name) {
-  return new WebThreadImpl(name);
-}
-
-blink::WebThread* WebKitPlatformSupportChildImpl::currentThread() {
-  WebThreadImplForMessageLoop* thread =
-      static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get());
-  if (thread)
-    return (thread);
-
-  scoped_refptr<base::MessageLoopProxy> message_loop =
-      base::MessageLoopProxy::current();
-  if (!message_loop.get())
-    return NULL;
-
-  thread = new WebThreadImplForMessageLoop(message_loop.get());
-  current_thread_slot_.Set(thread);
-  return thread;
-}
-
-blink::WebWaitableEvent* WebKitPlatformSupportChildImpl::createWaitableEvent() {
-  return new WebWaitableEventImpl();
-}
-
-blink::WebWaitableEvent* WebKitPlatformSupportChildImpl::waitMultipleEvents(
-    const blink::WebVector<blink::WebWaitableEvent*>& web_events) {
-  std::vector<base::WaitableEvent*> events;
-  for (size_t i = 0; i < web_events.size(); ++i)
-    events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl());
-  size_t idx = base::WaitableEvent::WaitMany(
-      vector_as_array(&events), events.size());
-  DCHECK_LT(idx, web_events.size());
-  return web_events[idx];
-}
-
-void WebKitPlatformSupportChildImpl::didStartWorkerRunLoop(
-    const blink::WebWorkerRunLoop& runLoop) {
-  WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
-  worker_task_runner->OnWorkerRunLoopStarted(runLoop);
-}
-
-void WebKitPlatformSupportChildImpl::didStopWorkerRunLoop(
-    const blink::WebWorkerRunLoop& runLoop) {
-  WorkerTaskRunner* worker_task_runner = WorkerTaskRunner::Instance();
-  worker_task_runner->OnWorkerRunLoopStopped(runLoop);
-}
-
-blink::WebDiscardableMemory*
-WebKitPlatformSupportChildImpl::allocateAndLockDiscardableMemory(size_t bytes) {
-  base::DiscardableMemoryType type =
-      base::DiscardableMemory::GetPreferredType();
-  if (type == base::DISCARDABLE_MEMORY_TYPE_EMULATED)
-    return NULL;
-  return content::WebDiscardableMemoryImpl::CreateLockedMemory(bytes).release();
-}
-
-// static
-void WebKitPlatformSupportChildImpl::DestroyCurrentThread(void* thread) {
-  WebThreadImplForMessageLoop* impl =
-      static_cast<WebThreadImplForMessageLoop*>(thread);
-  delete impl;
-}
-
-}  // namespace content
diff --git a/content/child/webkitplatformsupport_child_impl.h b/content/child/webkitplatformsupport_child_impl.h
deleted file mode 100644
index 91bf191..0000000
--- a/content/child/webkitplatformsupport_child_impl.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// // Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_WEBKITPLATFORMSUPPORT_CHILD_IMPL_H_
-#define CONTENT_CHILD_WEBKITPLATFORMSUPPORT_CHILD_IMPL_H_
-
-#include "base/threading/thread_local_storage.h"
-#include "content/child/blink_platform_impl.h"
-#include "content/child/webfallbackthemeengine_impl.h"
-#include "content/common/content_export.h"
-
-#if defined(USE_DEFAULT_RENDER_THEME)
-#include "content/child/webthemeengine_impl_default.h"
-#elif defined(OS_WIN)
-#include "content/child/webthemeengine_impl_win.h"
-#elif defined(OS_MACOSX)
-#include "content/child/webthemeengine_impl_mac.h"
-#elif defined(OS_ANDROID)
-#include "content/child/webthemeengine_impl_android.h"
-#endif
-
-namespace content {
-
-class FlingCurveConfiguration;
-
-class CONTENT_EXPORT WebKitPlatformSupportChildImpl : public BlinkPlatformImpl {
- public:
-  WebKitPlatformSupportChildImpl();
-  virtual ~WebKitPlatformSupportChildImpl();
-
-  // Platform methods (partial implementation):
-  virtual blink::WebThemeEngine* themeEngine();
-  virtual blink::WebFallbackThemeEngine* fallbackThemeEngine();
-
-  void SetFlingCurveParameters(
-    const std::vector<float>& new_touchpad,
-    const std::vector<float>& new_touchscreen);
-
-  virtual blink::WebGestureCurve* createFlingAnimationCurve(
-      int device_source,
-      const blink::WebFloatPoint& velocity,
-      const blink::WebSize& cumulative_scroll) OVERRIDE;
-
-  virtual blink::WebThread* createThread(const char* name);
-  virtual blink::WebThread* currentThread();
-
-  virtual blink::WebWaitableEvent* createWaitableEvent();
-  virtual blink::WebWaitableEvent* waitMultipleEvents(
-      const blink::WebVector<blink::WebWaitableEvent*>& events);
-
-  virtual void didStartWorkerRunLoop(
-      const blink::WebWorkerRunLoop& runLoop) OVERRIDE;
-  virtual void didStopWorkerRunLoop(
-      const blink::WebWorkerRunLoop& runLoop) OVERRIDE;
-
-  virtual blink::WebDiscardableMemory* allocateAndLockDiscardableMemory(
-      size_t bytes);
-
- private:
-  static void DestroyCurrentThread(void*);
-
-  WebThemeEngineImpl native_theme_engine_;
-  WebFallbackThemeEngineImpl fallback_theme_engine_;
-  base::ThreadLocalStorage::Slot current_thread_slot_;
-  scoped_ptr<FlingCurveConfiguration> fling_curve_configuration_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_CHILD_WEBKITPLATFORMSUPPORT_CHILD_IMPL_H_
diff --git a/content/child/webkitplatformsupport_impl.cc b/content/child/webkitplatformsupport_impl.cc
deleted file mode 100644
index 99b1632..0000000
--- a/content/child/webkitplatformsupport_impl.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/command_line.h"
-#include "content/child/child_thread.h"
-#include "content/child/socket_stream_dispatcher.h"
-#include "content/child/webcrypto/webcrypto_impl.h"
-#include "content/child/webkitplatformsupport_impl.h"
-#include "content/child/websocket_bridge.h"
-#include "content/public/common/content_client.h"
-
-namespace content {
-
-WebKitPlatformSupportImpl::WebKitPlatformSupportImpl() {
-}
-
-WebKitPlatformSupportImpl::~WebKitPlatformSupportImpl() {
-}
-
-base::string16 WebKitPlatformSupportImpl::GetLocalizedString(int message_id) {
-  return GetContentClient()->GetLocalizedString(message_id);
-}
-
-base::StringPiece WebKitPlatformSupportImpl::GetDataResource(
-    int resource_id,
-    ui::ScaleFactor scale_factor) {
-  return GetContentClient()->GetDataResource(resource_id, scale_factor);
-}
-
-webkit_glue::ResourceLoaderBridge*
-WebKitPlatformSupportImpl::CreateResourceLoader(
-    const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) {
-  return ChildThread::current()->CreateBridge(request_info);
-}
-
-WebSocketStreamHandleBridge*
-WebKitPlatformSupportImpl::CreateWebSocketStreamBridge(
-    blink::WebSocketStreamHandle* handle,
-    WebSocketStreamHandleDelegate* delegate) {
-  SocketStreamDispatcher* dispatcher =
-      ChildThread::current()->socket_stream_dispatcher();
-  return dispatcher->CreateBridge(handle, delegate);
-}
-
-blink::WebSocketHandle* WebKitPlatformSupportImpl::createWebSocketHandle() {
-  return new WebSocketBridge;
-}
-
-blink::WebCrypto* WebKitPlatformSupportImpl::crypto() {
-  if (!web_crypto_)
-    web_crypto_.reset(new WebCryptoImpl());
-  return web_crypto_.get();
-}
-
-}  // namespace content
diff --git a/content/child/webkitplatformsupport_impl.h b/content/child/webkitplatformsupport_impl.h
deleted file mode 100644
index 8eb60dd..0000000
--- a/content/child/webkitplatformsupport_impl.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_WEBKITPLATFORMSUPPORT_IMPL_H_
-#define CONTENT_CHILD_WEBKITPLATFORMSUPPORT_IMPL_H_
-
-#include "base/compiler_specific.h"
-#include "content/child/webkitplatformsupport_child_impl.h"
-#include "content/common/content_export.h"
-#include "ui/base/layout.h"
-
-namespace content {
-class WebCryptoImpl;
-
-// This is a specialization of WebKitPlatformSupportImpl that implements the
-// embedder functions in terms of ContentClient.
-class CONTENT_EXPORT WebKitPlatformSupportImpl
-    : NON_EXPORTED_BASE(public WebKitPlatformSupportChildImpl) {
- public:
-  typedef blink::WebGraphicsContext3D* (OffscreenContextFactory)();
-
-  WebKitPlatformSupportImpl();
-  virtual ~WebKitPlatformSupportImpl();
-
-  virtual base::string16 GetLocalizedString(int message_id) OVERRIDE;
-  virtual base::StringPiece GetDataResource(
-      int resource_id,
-      ui::ScaleFactor scale_factor) OVERRIDE;
-  virtual webkit_glue::ResourceLoaderBridge* CreateResourceLoader(
-      const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info)
-      OVERRIDE;
-  virtual WebSocketStreamHandleBridge* CreateWebSocketStreamBridge(
-      blink::WebSocketStreamHandle* handle,
-      WebSocketStreamHandleDelegate* delegate) OVERRIDE;
-  virtual blink::WebSocketHandle* createWebSocketHandle() OVERRIDE;
-  virtual blink::WebCrypto* crypto() OVERRIDE;
-
- private:
-  scoped_ptr<WebCryptoImpl> web_crypto_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_CHILD_WEBKITPLATFORMSUPPORT_IMPL_H_
diff --git a/content/child/webmessageportchannel_impl.cc b/content/child/webmessageportchannel_impl.cc
index cf439cc..17b7b16 100644
--- a/content/child/webmessageportchannel_impl.cc
+++ b/content/child/webmessageportchannel_impl.cc
@@ -59,6 +59,25 @@
     ChildThread::current()->GetRouter()->RemoveRoute(route_id_);
 }
 
+// static
+std::vector<int> WebMessagePortChannelImpl::ExtractMessagePortIDs(
+    WebMessagePortChannelArray* channels) {
+  std::vector<int> message_port_ids;
+  if (channels) {
+    message_port_ids.resize(channels->size());
+    // Extract the port IDs from the source array, then free it.
+    for (size_t i = 0; i < channels->size(); ++i) {
+      WebMessagePortChannelImpl* webchannel =
+          static_cast<WebMessagePortChannelImpl*>((*channels)[i]);
+      message_port_ids[i] = webchannel->message_port_id();
+      webchannel->QueueMessages();
+      DCHECK(message_port_ids[i] != MSG_ROUTING_NONE);
+    }
+    delete channels;
+  }
+  return message_port_ids;
+}
+
 void WebMessagePortChannelImpl::setClient(WebMessagePortChannelClient* client) {
   // Must lock here since client_ is called on the main thread.
   base::AutoLock auto_lock(lock_);
@@ -98,21 +117,8 @@
 void WebMessagePortChannelImpl::PostMessage(
     const base::string16& message,
     WebMessagePortChannelArray* channels) {
-  std::vector<int> message_port_ids(channels ? channels->size() : 0);
-  if (channels) {
-    // Extract the port IDs from the source array, then free it.
-    for (size_t i = 0; i < channels->size(); ++i) {
-      WebMessagePortChannelImpl* webchannel =
-          static_cast<WebMessagePortChannelImpl*>((*channels)[i]);
-      message_port_ids[i] = webchannel->message_port_id();
-      webchannel->QueueMessages();
-      DCHECK(message_port_ids[i] != MSG_ROUTING_NONE);
-    }
-    delete channels;
-  }
-
   IPC::Message* msg = new MessagePortHostMsg_PostMessage(
-      message_port_id_, message, message_port_ids);
+      message_port_id_, message, ExtractMessagePortIDs(channels));
   Send(msg);
 }
 
diff --git a/content/child/webmessageportchannel_impl.h b/content/child/webmessageportchannel_impl.h
index e737fc3..1fe46e8 100644
--- a/content/child/webmessageportchannel_impl.h
+++ b/content/child/webmessageportchannel_impl.h
@@ -33,6 +33,11 @@
                             int message_port_id,
                             base::MessageLoopProxy* child_thread_loop);
 
+  // Extracts port IDs for passing on to the browser process, and queues any
+  // received messages. Takes ownership of the passed array (and deletes it).
+  static std::vector<int> ExtractMessagePortIDs(
+      blink::WebMessagePortChannelArray* channels);
+
   // Queues received and incoming messages until there are no more in-flight
   // messages, then sends all of them to the browser process.
   void QueueMessages();
diff --git a/content/common/DEPS b/content/common/DEPS
index 9e5bef7..dbb7aff 100644
--- a/content/common/DEPS
+++ b/content/common/DEPS
@@ -23,6 +23,7 @@
   "+third_party/WebKit/public/platform/WebScreenOrientation.h",
   "+third_party/WebKit/public/platform/WebScreenInfo.h",
   "+third_party/WebKit/public/platform/WebServiceWorkerError.h",
+  "+third_party/WebKit/public/platform/WebServiceWorkerEventResult.h",
   "+third_party/WebKit/public/platform/WebStorageArea.h",
   "+third_party/WebKit/public/platform/WebString.h",
   "+third_party/WebKit/public/platform/linux/WebFontFamily.h",
diff --git a/content/common/cc_messages.cc b/content/common/cc_messages.cc
index 712c608..40e2441 100644
--- a/content/common/cc_messages.cc
+++ b/content/common/cc_messages.cc
@@ -285,7 +285,6 @@
 
 void ParamTraits<cc::RenderPass>::Write(
     Message* m, const param_type& p) {
-  DCHECK(p.overlay_state == cc::RenderPass::NO_OVERLAY);
   WriteParam(m, p.id);
   WriteParam(m, p.output_rect);
   WriteParam(m, p.damage_rect);
@@ -422,8 +421,7 @@
             output_rect,
             damage_rect,
             transform_to_root_target,
-            has_transparent_background,
-            cc::RenderPass::NO_OVERLAY);
+            has_transparent_background);
 
   size_t last_shared_quad_state_index = kuint32max;
   for (size_t i = 0; i < quad_list_size; ++i) {
diff --git a/content/common/cc_messages.h b/content/common/cc_messages.h
index 634c56b..b388bbb 100644
--- a/content/common/cc_messages.h
+++ b/content/common/cc_messages.h
@@ -215,7 +215,7 @@
 
 IPC_STRUCT_TRAITS_BEGIN(cc::YUVVideoDrawQuad)
   IPC_STRUCT_TRAITS_PARENT(cc::DrawQuad)
-  IPC_STRUCT_TRAITS_MEMBER(tex_scale)
+  IPC_STRUCT_TRAITS_MEMBER(tex_coord_rect)
   IPC_STRUCT_TRAITS_MEMBER(y_plane_resource_id)
   IPC_STRUCT_TRAITS_MEMBER(u_plane_resource_id)
   IPC_STRUCT_TRAITS_MEMBER(v_plane_resource_id)
diff --git a/content/common/cc_messages_unittest.cc b/content/common/cc_messages_unittest.cc
index 1e801d5..fb32ddf 100644
--- a/content/common/cc_messages_unittest.cc
+++ b/content/common/cc_messages_unittest.cc
@@ -195,7 +195,7 @@
   }
 
   void Compare(const YUVVideoDrawQuad* a, const YUVVideoDrawQuad* b) {
-    EXPECT_EQ(a->tex_scale, b->tex_scale);
+    EXPECT_EQ(a->tex_coord_rect, b->tex_coord_rect);
     EXPECT_EQ(a->y_plane_resource_id, b->y_plane_resource_id);
     EXPECT_EQ(a->u_plane_resource_id, b->u_plane_resource_id);
     EXPECT_EQ(a->v_plane_resource_id, b->v_plane_resource_id);
@@ -426,7 +426,7 @@
                       arbitrary_rect2_inside_rect1,
                       arbitrary_rect1_inside_rect1,
                       arbitrary_bool1,
-                      arbitrary_sizef1,
+                      arbitrary_rectf1,
                       arbitrary_resourceid1,
                       arbitrary_resourceid2,
                       arbitrary_resourceid3,
@@ -439,8 +439,7 @@
                   arbitrary_rect1,
                   arbitrary_rectf1,
                   arbitrary_matrix,
-                  arbitrary_bool1,
-                  cc::RenderPass::NO_OVERLAY);
+                  arbitrary_bool1);
 
   pass_in->shared_quad_state_list.push_back(shared_state1_in.Pass());
   pass_in->quad_list.push_back(checkerboard_in.PassAs<DrawQuad>());
@@ -461,8 +460,7 @@
                    arbitrary_rect1,
                    arbitrary_rectf1,
                    arbitrary_matrix,
-                   arbitrary_bool1,
-                   cc::RenderPass::NO_OVERLAY);
+                   arbitrary_bool1);
 
   pass_cmp->shared_quad_state_list.push_back(shared_state1_cmp.Pass());
   pass_cmp->quad_list.push_back(checkerboard_cmp.PassAs<DrawQuad>());
@@ -539,8 +537,7 @@
                   gfx::Rect(100, 100),
                   gfx::RectF(),
                   gfx::Transform(),
-                  false,
-                  cc::RenderPass::NO_OVERLAY);
+                  false);
 
   // The first SharedQuadState is used.
   scoped_ptr<SharedQuadState> shared_state1_in = SharedQuadState::Create();
diff --git a/content/common/content_param_traits_macros.h b/content/common/content_param_traits_macros.h
index dff46f3..633c14c 100644
--- a/content/common/content_param_traits_macros.h
+++ b/content/common/content_param_traits_macros.h
@@ -10,6 +10,7 @@
 
 #include "content/common/content_export.h"
 #include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
 #include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
 #include "third_party/WebKit/public/web/WebInputEvent.h"
 #include "third_party/WebKit/public/web/WebPageVisibilityState.h"
@@ -30,6 +31,13 @@
 IPC_ENUM_TRAITS_MAX_VALUE(ui::LatencyComponentType,
                           ui::LATENCY_COMPONENT_TYPE_LAST)
 
+IPC_STRUCT_TRAITS_BEGIN(blink::WebCompositionUnderline)
+  IPC_STRUCT_TRAITS_MEMBER(startOffset)
+  IPC_STRUCT_TRAITS_MEMBER(endOffset)
+  IPC_STRUCT_TRAITS_MEMBER(color)
+  IPC_STRUCT_TRAITS_MEMBER(thick)
+IPC_STRUCT_TRAITS_END()
+
 IPC_STRUCT_TRAITS_BEGIN(ui::LatencyInfo::LatencyComponent)
   IPC_STRUCT_TRAITS_MEMBER(sequence_number)
   IPC_STRUCT_TRAITS_MEMBER(event_time)
diff --git a/content/common/cursors/webcursor.h b/content/common/cursors/webcursor.h
index d717be3..29710a3 100644
--- a/content/common/cursors/webcursor.h
+++ b/content/common/cursors/webcursor.h
@@ -180,7 +180,7 @@
   HCURSOR external_cursor_;
 #endif
 
-#if defined(USE_AURA) && defined(USE_X11)
+#if defined(USE_AURA) && (defined(USE_X11) || defined(USE_OZONE))
   // Only used for custom cursors.
   ui::PlatformCursor platform_cursor_;
   float device_scale_factor_;
diff --git a/content/common/cursors/webcursor_aurax11.cc b/content/common/cursors/webcursor_aurax11.cc
index 81184e4..793fe23 100644
--- a/content/common/cursors/webcursor_aurax11.cc
+++ b/content/common/cursors/webcursor_aurax11.cc
@@ -12,6 +12,7 @@
 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/cursor/cursor_loader_x11.h"
+#include "ui/base/cursor/cursor_util.h"
 #include "ui/base/x/x11_util.h"
 
 namespace content {
diff --git a/content/common/cursors/webcursor_null.cc b/content/common/cursors/webcursor_null.cc
deleted file mode 100644
index f211f59..0000000
--- a/content/common/cursors/webcursor_null.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/cursors/webcursor.h"
-
-namespace content {
-
-const ui::PlatformCursor WebCursor::GetPlatformCursor() {
-  return NULL;
-}
-
-void WebCursor::SetDisplayInfo(const gfx::Display& display) {
-  return;
-}
-
-void WebCursor::InitPlatformData() {
-}
-
-bool WebCursor::SerializePlatformData(Pickle* pickle) const {
-  return true;
-}
-
-bool WebCursor::DeserializePlatformData(PickleIterator* iter) {
-  return true;
-}
-
-bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
-  return true;
-}
-
-void WebCursor::CleanupPlatformData() {
-}
-
-void WebCursor::CopyPlatformData(const WebCursor& other) {
-}
-
-}  // namespace content
diff --git a/content/common/cursors/webcursor_ozone.cc b/content/common/cursors/webcursor_ozone.cc
new file mode 100644
index 0000000..abd4cf0
--- /dev/null
+++ b/content/common/cursors/webcursor_ozone.cc
@@ -0,0 +1,77 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/cursors/webcursor.h"
+
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/cursor_util.h"
+#include "ui/base/cursor/ozone/cursor_factory_ozone.h"
+
+namespace content {
+
+const ui::PlatformCursor WebCursor::GetPlatformCursor() {
+  if (platform_cursor_)
+    return platform_cursor_;
+
+  SkBitmap bitmap;
+  ImageFromCustomData(&bitmap);
+  gfx::Point hotspot = hotspot_;
+  ui::ScaleAndRotateCursorBitmapAndHotpoint(
+      device_scale_factor_, rotation_, &bitmap, &hotspot);
+
+  return ui::CursorFactoryOzone::GetInstance()->CreateImageCursor(bitmap,
+                                                                  hotspot);
+}
+
+void WebCursor::SetDisplayInfo(const gfx::Display& display) {
+  if (rotation_ == display.rotation() &&
+      device_scale_factor_ == display.device_scale_factor())
+    return;
+
+  device_scale_factor_ = display.device_scale_factor();
+  rotation_ = display.rotation();
+  if (platform_cursor_)
+    ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor_);
+  platform_cursor_ = NULL;
+  // It is not necessary to recreate platform_cursor_ yet, since it will be
+  // recreated on demand when GetPlatformCursor is called.
+}
+
+void WebCursor::InitPlatformData() {
+  platform_cursor_ = NULL;
+  device_scale_factor_ = 1.f;
+  rotation_ = gfx::Display::ROTATE_0;
+}
+
+bool WebCursor::SerializePlatformData(Pickle* pickle) const {
+  return true;
+}
+
+bool WebCursor::DeserializePlatformData(PickleIterator* iter) {
+  return true;
+}
+
+bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
+  return true;
+}
+
+void WebCursor::CleanupPlatformData() {
+  if (platform_cursor_) {
+    ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor_);
+    platform_cursor_ = NULL;
+  }
+}
+
+void WebCursor::CopyPlatformData(const WebCursor& other) {
+  if (platform_cursor_)
+    ui::CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor_);
+  platform_cursor_ = other.platform_cursor_;
+  if (platform_cursor_)
+    ui::CursorFactoryOzone::GetInstance()->RefImageCursor(platform_cursor_);
+
+  device_scale_factor_ = other.device_scale_factor_;
+}
+
+}  // namespace content
diff --git a/content/common/devtools_messages.h b/content/common/devtools_messages.h
index cd4c4b5..8815a43 100644
--- a/content/common/devtools_messages.h
+++ b/content/common/devtools_messages.h
@@ -86,11 +86,6 @@
                     content::ConsoleMessageLevel /* level */,
                     std::string /* message */)
 
-// Notifies worker devtools agent that it should pause worker context
-// when it starts and wait until either DevTools client is attached or
-// explicit resume notification is received.
-IPC_MESSAGE_ROUTED0(DevToolsAgentMsg_PauseWorkerContextOnStart)
-
 // Worker DevTools agent should resume worker execution.
 IPC_MESSAGE_ROUTED0(DevToolsAgentMsg_ResumeWorkerContext)
 
diff --git a/content/common/drag_traits.h b/content/common/drag_traits.h
index fb3eef1..5b78528 100644
--- a/content/common/drag_traits.h
+++ b/content/common/drag_traits.h
@@ -15,7 +15,7 @@
 IPC_ENUM_TRAITS_MAX_VALUE(ui::DragDropTypes::DragEventSource,
                           ui::DragDropTypes::DRAG_EVENT_SOURCE_LAST)
 
-IPC_STRUCT_TRAITS_BEGIN(content::DropData::FileInfo)
+IPC_STRUCT_TRAITS_BEGIN(ui::FileInfo)
   IPC_STRUCT_TRAITS_MEMBER(path)
   IPC_STRUCT_TRAITS_MEMBER(display_name)
 IPC_STRUCT_TRAITS_END()
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 25c760b..c64490b 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -41,7 +41,6 @@
   IPC_STRUCT_TRAITS_MEMBER(page_url)
   IPC_STRUCT_TRAITS_MEMBER(keyword_url)
   IPC_STRUCT_TRAITS_MEMBER(frame_url)
-  IPC_STRUCT_TRAITS_MEMBER(frame_id)
   IPC_STRUCT_TRAITS_MEMBER(frame_page_state)
   IPC_STRUCT_TRAITS_MEMBER(media_flags)
   IPC_STRUCT_TRAITS_MEMBER(selection_text)
@@ -76,8 +75,6 @@
 IPC_STRUCT_BEGIN(FrameHostMsg_DidFailProvisionalLoadWithError_Params)
   // The WebFrame's uniqueName().
   IPC_STRUCT_MEMBER(base::string16, frame_unique_name)
-  // True if this is the top-most frame.
-  IPC_STRUCT_MEMBER(bool, is_main_frame)
   // Error code as reported in the DidFailProvisionalLoad callback.
   IPC_STRUCT_MEMBER(int, error_code)
   // An error message generated from the error_code. This can be an empty
@@ -318,6 +315,25 @@
                     int,  /* ID */
                     bool  /* if true, a reply is requested */)
 
+// Selects between the given start and end offsets in the currently focused
+// editable field.
+IPC_MESSAGE_ROUTED2(FrameMsg_SetEditableSelectionOffsets,
+                    int /* start */,
+                    int /* end */)
+
+// Sets the text composition to be between the given start and end offsets in
+// the currently focused editable field.
+IPC_MESSAGE_ROUTED3(FrameMsg_SetCompositionFromExistingText,
+    int /* start */,
+    int /* end */,
+    std::vector<blink::WebCompositionUnderline> /* underlines */)
+
+// Deletes the current selection plus the specified number of characters before
+// and after the selection or caret.
+IPC_MESSAGE_ROUTED2(FrameMsg_ExtendSelectionAndDelete,
+                    int /* before */,
+                    int /* after */)
+
 // -----------------------------------------------------------------------------
 // Messages sent from the renderer to the browser.
 
@@ -338,9 +354,8 @@
 IPC_MESSAGE_ROUTED0(FrameHostMsg_FrameFocused)
 
 // Sent when the renderer starts a provisional load for a frame.
-IPC_MESSAGE_ROUTED3(FrameHostMsg_DidStartProvisionalLoadForFrame,
+IPC_MESSAGE_ROUTED2(FrameHostMsg_DidStartProvisionalLoadForFrame,
                     int32 /* parent_routing_id */,
-                    bool /* true if it is the main frame */,
                     GURL /* url */)
 
 // Sent when the renderer fails a provisional load with an error.
@@ -362,16 +377,18 @@
 // Notifies the browser that a document has been loaded.
 IPC_MESSAGE_ROUTED0(FrameHostMsg_DidFinishDocumentLoad)
 
-IPC_MESSAGE_ROUTED4(FrameHostMsg_DidFailLoadWithError,
+IPC_MESSAGE_ROUTED3(FrameHostMsg_DidFailLoadWithError,
                     GURL /* validated_url */,
-                    bool /* is_main_frame */,
                     int /* error_code */,
                     base::string16 /* error_description */)
 
 // Sent when the renderer starts loading the page. This corresponds to
 // Blink's notion of the throbber starting. Note that sometimes you may get
 // duplicates of these during a single load.
-IPC_MESSAGE_ROUTED0(FrameHostMsg_DidStartLoading)
+// |to_different_document| will be true unless the load is a fragment
+// navigation, or triggered by history.pushState/replaceState.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_DidStartLoading,
+                    bool /* to_different_document */)
 
 // Sent when the renderer is done loading a page. This corresponds to Blink's
 // notion of the throbber stopping.
@@ -381,9 +398,8 @@
 IPC_MESSAGE_ROUTED1(FrameHostMsg_OpenURL, FrameHostMsg_OpenURL_Params)
 
 // Notifies the browser that a frame finished loading.
-IPC_MESSAGE_ROUTED2(FrameHostMsg_DidFinishLoad,
-                    GURL /* validated_url */,
-                    bool /* is_main_frame */)
+IPC_MESSAGE_ROUTED1(FrameHostMsg_DidFinishLoad,
+                    GURL /* validated_url */)
 
 // Following message is used to communicate the values received by the
 // callback binding the JS to Cpp.
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.cc b/content/common/gpu/client/command_buffer_proxy_impl.cc
index 904e5b0..8ed2802 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ b/content/common/gpu/client/command_buffer_proxy_impl.cc
@@ -35,15 +35,6 @@
   FOR_EACH_OBSERVER(DeletionObserver,
                     deletion_observers_,
                     OnWillDeleteImpl());
-
-  // Delete all the locally cached shared memory objects, closing the handle
-  // in this process.
-  for (TransferBufferMap::iterator it = transfer_buffers_.begin();
-       it != transfer_buffers_.end();
-       ++it) {
-    delete it->second.shared_memory;
-    it->second.shared_memory = NULL;
-  }
 }
 
 bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
@@ -265,12 +256,13 @@
   NOTREACHED();
 }
 
-gpu::Buffer CommandBufferProxyImpl::CreateTransferBuffer(size_t size,
-                                                         int32* id) {
+scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer(
+    size_t size,
+    int32* id) {
   *id = -1;
 
   if (last_state_.error != gpu::error::kNoError)
-    return gpu::Buffer();
+    return NULL;
 
   int32 new_id = channel_->ReserveTransferBufferId();
   DCHECK(transfer_buffers_.find(new_id) == transfer_buffers_.end());
@@ -278,11 +270,11 @@
   scoped_ptr<base::SharedMemory> shared_memory(
       channel_->factory()->AllocateSharedMemory(size));
   if (!shared_memory)
-    return gpu::Buffer();
+    return NULL;
 
   DCHECK(!shared_memory->memory());
   if (!shared_memory->Map(size))
-    return gpu::Buffer();
+    return NULL;
 
   // This handle is owned by the GPU process and must be passed to it or it
   // will leak. In otherwords, do not early out on error between here and the
@@ -290,22 +282,19 @@
   base::SharedMemoryHandle handle =
       channel_->ShareToGpuProcess(shared_memory->handle());
   if (!base::SharedMemory::IsHandleValid(handle))
-    return gpu::Buffer();
+    return NULL;
 
   if (!Send(new GpuCommandBufferMsg_RegisterTransferBuffer(route_id_,
                                                            new_id,
                                                            handle,
                                                            size))) {
-    return gpu::Buffer();
+    return NULL;
   }
 
   *id = new_id;
-  gpu::Buffer buffer;
-  buffer.ptr = shared_memory->memory();
-  buffer.size = size;
-  buffer.shared_memory = shared_memory.release();
+  scoped_refptr<gpu::Buffer> buffer =
+      new gpu::Buffer(shared_memory.Pass(), size);
   transfer_buffers_[new_id] = buffer;
-
   return buffer;
 }
 
@@ -315,17 +304,15 @@
 
   // Remove the transfer buffer from the client side cache.
   TransferBufferMap::iterator it = transfer_buffers_.find(id);
-  if (it != transfer_buffers_.end()) {
-    delete it->second.shared_memory;
+  if (it != transfer_buffers_.end())
     transfer_buffers_.erase(it);
-  }
 
   Send(new GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id));
 }
 
-gpu::Buffer CommandBufferProxyImpl::GetTransferBuffer(int32 id) {
+scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::GetTransferBuffer(int32 id) {
   if (last_state_.error != gpu::error::kNoError)
-    return gpu::Buffer();
+    return NULL;
 
   // Check local cache to see if there is already a client side shared memory
   // object for this id.
@@ -342,7 +329,7 @@
                                                       id,
                                                       &handle,
                                                       &size))) {
-    return gpu::Buffer();
+    return NULL;
   }
 
   // Cache the transfer buffer shared memory object client side.
@@ -352,13 +339,11 @@
   // Map the shared memory on demand.
   if (!shared_memory->memory()) {
     if (!shared_memory->Map(size))
-      return gpu::Buffer();
+      return NULL;
   }
 
-  gpu::Buffer buffer;
-  buffer.ptr = shared_memory->memory();
-  buffer.size = size;
-  buffer.shared_memory = shared_memory.release();
+  scoped_refptr<gpu::Buffer> buffer =
+      new gpu::Buffer(shared_memory.Pass(), size);
   transfer_buffers_[id] = buffer;
 
   return buffer;
diff --git a/content/common/gpu/client/command_buffer_proxy_impl.h b/content/common/gpu/client/command_buffer_proxy_impl.h
index e0132fd..dade999 100644
--- a/content/common/gpu/client/command_buffer_proxy_impl.h
+++ b/content/common/gpu/client/command_buffer_proxy_impl.h
@@ -86,10 +86,10 @@
   virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE;
   virtual void SetGetBuffer(int32 shm_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual gpu::Buffer CreateTransferBuffer(size_t size,
-                                           int32* id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+                                                          int32* id) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(gpu::error::Error error) OVERRIDE;
   virtual void SetContextLostReason(
@@ -141,7 +141,7 @@
   GpuChannelHost* channel() const { return channel_; }
 
  private:
-  typedef std::map<int32, gpu::Buffer> TransferBufferMap;
+  typedef std::map<int32, scoped_refptr<gpu::Buffer> > TransferBufferMap;
   typedef base::hash_map<uint32, base::Closure> SignalTaskMap;
   typedef std::map<int32, gfx::GpuMemoryBuffer*> GpuMemoryBufferMap;
 
diff --git a/content/common/gpu/client/context_provider_command_buffer_browsertest.cc b/content/common/gpu/client/context_provider_command_buffer_browsertest.cc
index eb552e5..d6378ad 100644
--- a/content/common/gpu/client/context_provider_command_buffer_browsertest.cc
+++ b/content/common/gpu/client/context_provider_command_buffer_browsertest.cc
@@ -5,7 +5,7 @@
 #include "content/browser/gpu/browser_gpu_channel_host_factory.h"
 #include "content/common/gpu/client/context_provider_command_buffer.h"
 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/test/content_browser_test.h"
+#include "content/public/test/content_browser_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
diff --git a/content/common/gpu/client/gl_helper.cc b/content/common/gpu/client/gl_helper.cc
index 9882203..4058d4f 100644
--- a/content/common/gpu/client/gl_helper.cc
+++ b/content/common/gpu/client/gl_helper.cc
@@ -163,6 +163,7 @@
                      int32 row_stride_bytes,  // generally dst_size.width() * 4
                      unsigned char* out,
                      const SkBitmap::Config config,
+                     ReadbackSwizzle swizzle,
                      const base::Callback<void(bool)>& callback);
 
   void ReadbackPlane(TextureFrameBufferPair* source,
@@ -170,6 +171,7 @@
                      int plane,
                      int size_shift,
                      const gfx::Rect& dst_subrect,
+                     ReadbackSwizzle swizzle,
                      const base::Callback<void(bool)>& callback);
 
   GLuint CopyAndScaleTexture(GLuint texture,
@@ -238,7 +240,8 @@
                     const gfx::Rect& src_subrect,
                     const gfx::Size& dst_size,
                     const gfx::Rect& dst_subrect,
-                    bool flip_vertically);
+                    bool flip_vertically,
+                    ReadbackSwizzle swizzle);
 
     virtual void ReadbackYUV(const gpu::Mailbox& mailbox,
                              uint32 sync_point,
@@ -253,6 +256,7 @@
     CopyTextureToImpl* copy_impl_;
     gfx::Size dst_size_;
     gfx::Rect dst_subrect_;
+    ReadbackSwizzle swizzle_;
     ScalerHolder scaler_;
     ScalerHolder y_;
     ScalerHolder u_;
@@ -274,7 +278,8 @@
                     const gfx::Rect& src_subrect,
                     const gfx::Size& dst_size,
                     const gfx::Rect& dst_subrect,
-                    bool flip_vertically);
+                    bool flip_vertically,
+                    ReadbackSwizzle swizzle);
 
     virtual void ReadbackYUV(const gpu::Mailbox& mailbox,
                              uint32 sync_point,
@@ -290,6 +295,7 @@
     gfx::Size dst_size_;
     gfx::Rect dst_subrect_;
     GLHelper::ScalerQuality quality_;
+    ReadbackSwizzle swizzle_;
     ScalerHolder scaler_;
     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass1_shader_;
     scoped_ptr<content::GLHelperScaling::ShaderInterface> pass2_shader_;
@@ -407,6 +413,7 @@
     int32 row_stride_bytes,
     unsigned char* out,
     const SkBitmap::Config bitmap_config,
+    ReadbackSwizzle swizzle,
     const base::Callback<void(bool)>& callback) {
   if (!IsReadbackConfigSupported(bitmap_config)) {
     callback.Run(false);
@@ -423,7 +430,8 @@
 
   switch (bitmap_config) {
     case SkBitmap::kARGB_8888_Config:
-      // Do nothing params already set.
+      if (swizzle == kSwizzleBGRA)
+        format = GL_BGRA_EXT;
       break;
     case SkBitmap::kRGB_565_Config:
       format = GL_RGB;
@@ -510,6 +518,7 @@
                 dst_size.width() * bytes_per_pixel,
                 out,
                 bitmap_config,
+                kSwizzleNone,
                 callback);
   gl_->DeleteTextures(1, &texture);
 }
@@ -566,6 +575,7 @@
                 dst_size.width() * bytes_per_pixel,
                 out,
                 bitmap_config,
+                kSwizzleNone,
                 callback);
 }
 
@@ -895,6 +905,7 @@
     int plane,
     int size_shift,
     const gfx::Rect& dst_subrect,
+    ReadbackSwizzle swizzle,
     const base::Callback<void(bool)>& callback) {
   gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
   size_t offset = target->stride(plane) * (dst_subrect.y() >> size_shift) +
@@ -904,6 +915,7 @@
                 target->stride(plane),
                 target->data(plane) + offset,
                 SkBitmap::kARGB_8888_Config,
+                swizzle,
                 callback);
 }
 
@@ -925,11 +937,13 @@
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     const gfx::Rect& dst_subrect,
-    bool flip_vertically)
+    bool flip_vertically,
+    ReadbackSwizzle swizzle)
     : gl_(gl),
       copy_impl_(copy_impl),
       dst_size_(dst_size),
       dst_subrect_(dst_subrect),
+      swizzle_(swizzle),
       scaler_(gl,
               scaler_impl->CreateScaler(quality,
                                         src_size,
@@ -946,6 +960,7 @@
                        dst_subrect.height()),
              gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
              false,
+             (swizzle == kSwizzleBGRA),
              kRGBtoYColorWeights)),
       u_(gl,
          scaler_impl->CreatePlanarScaler(
@@ -957,6 +972,7 @@
              gfx::Size((dst_subrect.width() + 7) / 8,
                        (dst_subrect.height() + 1) / 2),
              false,
+             (swizzle == kSwizzleBGRA),
              kRGBtoUColorWeights)),
       v_(gl,
          scaler_impl->CreatePlanarScaler(
@@ -968,6 +984,7 @@
              gfx::Size((dst_subrect.width() + 7) / 8,
                        (dst_subrect.height() + 1) / 2),
              false,
+             (swizzle == kSwizzleBGRA),
              kRGBtoVColorWeights)) {
   DCHECK(!(dst_size.width() & 1));
   DCHECK(!(dst_size.height() & 1));
@@ -1015,12 +1032,14 @@
                             media::VideoFrame::kYPlane,
                             0,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
   copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(),
                             target,
                             media::VideoFrame::kUPlane,
                             1,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
   copy_impl_->ReadbackPlane(
       v_.texture_and_framebuffer(),
@@ -1028,6 +1047,7 @@
       media::VideoFrame::kVPlane,
       1,
       dst_subrect_,
+      swizzle_,
       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
   media::LetterboxYUV(target, dst_subrect_);
@@ -1044,12 +1064,14 @@
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     const gfx::Rect& dst_subrect,
-    bool flip_vertically)
+    bool flip_vertically,
+    ReadbackSwizzle swizzle)
     : gl_(gl),
       copy_impl_(copy_impl),
       dst_size_(dst_size),
       dst_subrect_(dst_subrect),
       quality_(quality),
+      swizzle_(swizzle),
       scaler_(gl,
               scaler_impl->CreateScaler(quality,
                                         src_size,
@@ -1062,6 +1084,7 @@
           gfx::Rect(0, 0, (dst_subrect.width() + 3) & ~3, dst_subrect.height()),
           gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
           flip_vertically,
+          (swizzle == kSwizzleBGRA),
           GLHelperScaling::SHADER_YUV_MRT_PASS1)),
       pass2_shader_(scaler_impl->CreateYuvMrtShader(
           gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height()),
@@ -1072,6 +1095,7 @@
           gfx::Size((dst_subrect.width() + 7) / 8,
                     (dst_subrect.height() + 1) / 2),
           false,
+          (swizzle == kSwizzleBGRA),
           GLHelperScaling::SHADER_YUV_MRT_PASS2)),
       y_(gl, gfx::Size((dst_subrect.width() + 3) / 4, dst_subrect.height())),
       uv_(gl),
@@ -1146,12 +1170,14 @@
                             media::VideoFrame::kYPlane,
                             0,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
   copy_impl_->ReadbackPlane(&u_,
                             target,
                             media::VideoFrame::kUPlane,
                             1,
                             dst_subrect_,
+                            swizzle_,
                             base::Bind(&nullcallback));
   copy_impl_->ReadbackPlane(
       &v_,
@@ -1159,6 +1185,7 @@
       media::VideoFrame::kVPlane,
       1,
       dst_subrect_,
+      swizzle_,
       base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
   gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
   media::LetterboxYUV(target, dst_subrect_);
@@ -1178,6 +1205,15 @@
     bool flip_vertically,
     bool use_mrt) {
   helper_->InitScalerImpl();
+  // Query preferred format for glReadPixels, if is is GL_BGRA then use that
+  // and trigger the appropriate swizzle in the YUV shaders.
+  GLint format = 0, type = 0;
+  ReadbackSwizzle swizzle = kSwizzleNone;
+  helper_->readback_support_.get()->GetAdditionalFormat(GL_RGBA,
+                                                        GL_UNSIGNED_BYTE,
+                                                        &format, &type);
+  if (format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE)
+    swizzle = kSwizzleBGRA;
   if (max_draw_buffers_ >= 2 && use_mrt) {
     return new ReadbackYUV_MRT(gl_,
                                this,
@@ -1187,7 +1223,8 @@
                                src_subrect,
                                dst_size,
                                dst_subrect,
-                               flip_vertically);
+                               flip_vertically,
+                               swizzle);
   }
   return new ReadbackYUVImpl(gl_,
                              this,
@@ -1197,7 +1234,8 @@
                              src_subrect,
                              dst_size,
                              dst_subrect,
-                             flip_vertically);
+                             flip_vertically,
+                             swizzle);
 }
 
 ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV(
diff --git a/content/common/gpu/client/gl_helper.h b/content/common/gpu/client/gl_helper.h
index 543805a..81e3aa0 100644
--- a/content/common/gpu/client/gl_helper.h
+++ b/content/common/gpu/client/gl_helper.h
@@ -330,6 +330,11 @@
   // Creates |scaler_impl_| if NULL.
   void InitScalerImpl();
 
+  enum ReadbackSwizzle {
+    kSwizzleNone = 0,
+    kSwizzleBGRA
+  };
+
   gpu::gles2::GLES2Interface* gl_;
   gpu::ContextSupport* context_support_;
   scoped_ptr<CopyTextureToImpl> copy_texture_to_impl_;
diff --git a/content/common/gpu/client/gl_helper_readback_support.cc b/content/common/gpu/client/gl_helper_readback_support.cc
index e69f2a8..643b8ab 100644
--- a/content/common/gpu/client/gl_helper_readback_support.cc
+++ b/content/common/gpu/client/gl_helper_readback_support.cc
@@ -53,13 +53,18 @@
       supports_format ? FORMAT_SUPPORTED : FORMAT_NOT_SUPPORTED;
 }
 
-bool GLHelperReadbackSupport::SupportsFormat(GLint format, GLint type) {
-  // GLES2.0 Specification says this pairing is always supported
-  // with additional format from GL_IMPLEMENTATION_COLOR_READ_FORMAT/TYPE
-  if (format == GL_RGBA && type == GL_UNSIGNED_BYTE)
-    return true;
+void GLHelperReadbackSupport::GetAdditionalFormat(GLint format, GLint type,
+                                                  GLint *format_out,
+                                                  GLint *type_out) {
+  for (unsigned int i = 0; i < format_cache_.size(); i++) {
+    if (format_cache_[i].format == format && format_cache_[i].type == type) {
+      *format_out = format_cache_[i].read_format;
+      *type_out = format_cache_[i].read_type;
+      return;
+    }
+  }
+
   const int kTestSize = 64;
-  bool supports_format = false;
   content::ScopedTexture dst_texture(gl_);
   ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
   gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -73,9 +78,21 @@
                                                              dst_framebuffer);
   gl_->FramebufferTexture2D(
       GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_texture, 0);
+  gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, format_out);
+  gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, type_out);
+
+  struct FormatCacheEntry entry = { format, type, *format_out, *type_out };
+  format_cache_.push_back(entry);
+}
+
+bool GLHelperReadbackSupport::SupportsFormat(GLint format, GLint type) {
+  // GLES2.0 Specification says this pairing is always supported
+  // with additional format from GL_IMPLEMENTATION_COLOR_READ_FORMAT/TYPE
+  if (format == GL_RGBA && type == GL_UNSIGNED_BYTE)
+    return true;
+  bool supports_format = false;
   GLint ext_format = 0, ext_type = 0;
-  gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &ext_format);
-  gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &ext_type);
+  GetAdditionalFormat(format, type, &ext_format, &ext_type);
   if ((ext_format == format) && (ext_type == type)) {
     supports_format = true;
   }
diff --git a/content/common/gpu/client/gl_helper_readback_support.h b/content/common/gpu/client/gl_helper_readback_support.h
index c6e2304..e163c76 100644
--- a/content/common/gpu/client/gl_helper_readback_support.h
+++ b/content/common/gpu/client/gl_helper_readback_support.h
@@ -5,6 +5,8 @@
 #ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_READBACK_SUPPORT_H_
 #define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_READBACK_SUPPORT_H_
 
+#include <vector>
+
 #include "content/common/gpu/client/gl_helper.h"
 
 namespace content {
@@ -22,9 +24,20 @@
   // Here we pass the internal textureformat as skia config.
   bool IsReadbackConfigSupported(SkBitmap::Config texture_format);
 
+  // Provides the additional readback format/type pairing for a render target
+  // of a given format/type pairing
+  void GetAdditionalFormat(GLint format, GLint type, GLint *format_out,
+                           GLint *type_out);
  private:
   enum FormatSupport { FORMAT_NOT_SUPPORTED = 0, FORMAT_SUPPORTED, };
 
+  struct FormatCacheEntry {
+    GLint format;
+    GLint type;
+    GLint read_format;
+    GLint read_type;
+  };
+
   // This populates the format_support_table with the list of supported
   // formats.
   void InitializeReadbackSupport();
@@ -43,7 +56,7 @@
   FormatSupport format_support_table_[SkBitmap::kConfigCount];
 
   gpu::gles2::GLES2Interface* gl_;
-
+  std::vector<struct FormatCacheEntry> format_cache_;
 };
 
 }  // namespace content
diff --git a/content/common/gpu/client/gl_helper_scaling.cc b/content/common/gpu/client/gl_helper_scaling.cc
index ce72bec..219f46b 100644
--- a/content/common/gpu/client/gl_helper_scaling.cc
+++ b/content/common/gpu/client/gl_helper_scaling.cc
@@ -463,6 +463,7 @@
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     bool vertically_flip_texture,
+    bool swizzle,
     const float color_weights[4]) {
   ScalerStage stage(SHADER_PLANAR,
                     src_size,
@@ -470,7 +471,7 @@
                     dst_size,
                     true,
                     vertically_flip_texture,
-                    false);
+                    swizzle);
   return new ScalerImpl(gl_, this, stage, NULL, color_weights);
 }
 
@@ -479,6 +480,7 @@
     const gfx::Rect& src_subrect,
     const gfx::Size& dst_size,
     bool vertically_flip_texture,
+    bool swizzle,
     ShaderType shader) {
   DCHECK(shader == SHADER_YUV_MRT_PASS1 || shader == SHADER_YUV_MRT_PASS2);
   ScalerStage stage(shader,
@@ -487,7 +489,7 @@
                     dst_size,
                     true,
                     vertically_flip_texture,
-                    false);
+                    swizzle);
   return new ScalerImpl(gl_, this, stage, NULL, NULL);
 }
 
@@ -720,8 +722,6 @@
             "    vec4(texture2D(s_texture, v_texcoords[0].zw).rgb, 1.0),\n"
             "    vec4(texture2D(s_texture, v_texcoords[1].xy).rgb, 1.0),\n"
             "    vec4(texture2D(s_texture, v_texcoords[1].zw).rgb, 1.0));\n");
-        // Swizzle makes no sense for this shader.
-        DCHECK(!swizzle);
         break;
 
       case SHADER_YUV_MRT_PASS1:
@@ -784,8 +784,6 @@
             "                        dot(pixel34, kRGBtoU),\n"
             "                        dot(pixel12, kRGBtoV),\n"
             "                        dot(pixel34, kRGBtoV)) + kUVBias;\n");
-        // Swizzle makes no sense for this shader.
-        DCHECK(!swizzle);
         break;
 
       case SHADER_YUV_MRT_PASS2:
@@ -807,12 +805,21 @@
             "  vec4 hi_uuvv = texture2D(s_texture, v_texcoords.zw);\n"
             "  gl_FragData[0] = vec4(lo_uuvv.rg, hi_uuvv.rg);\n"
             "  gl_FragData[1] = vec4(lo_uuvv.ba, hi_uuvv.ba);\n");
-        // Swizzle makes no sense for this shader.
-        DCHECK(!swizzle);
         break;
     }
     if (swizzle) {
-      fragment_program.append("  gl_FragColor = gl_FragColor.bgra;\n");
+      switch(type) {
+        case SHADER_YUV_MRT_PASS1:
+          fragment_program.append("  gl_FragData[0] = gl_FragData[0].bgra;\n");
+          break;
+        case SHADER_YUV_MRT_PASS2:
+          fragment_program.append("  gl_FragData[0] = gl_FragData[0].bgra;\n");
+          fragment_program.append("  gl_FragData[1] = gl_FragData[1].bgra;\n");
+          break;
+        default:
+          fragment_program.append("  gl_FragColor = gl_FragColor.bgra;\n");
+          break;
+      }
     }
 
     vertex_program = vertex_header + shared_variables + "void main() {\n" +
diff --git a/content/common/gpu/client/gl_helper_scaling.h b/content/common/gpu/client/gl_helper_scaling.h
index 8b48331..a8896c6 100644
--- a/content/common/gpu/client/gl_helper_scaling.h
+++ b/content/common/gpu/client/gl_helper_scaling.h
@@ -69,6 +69,7 @@
       const gfx::Rect& src_subrect,
       const gfx::Size& dst_size,
       bool vertically_flip_texture,
+      bool swizzle,
       const float color_weights[4]);
 
   ShaderInterface* CreateYuvMrtShader(
@@ -76,6 +77,7 @@
       const gfx::Rect& src_subrect,
       const gfx::Size& dst_size,
       bool vertically_flip_texture,
+      bool swizzle,
       ShaderType shader);
 
  private:
diff --git a/content/common/gpu/devtools_gpu_agent.cc b/content/common/gpu/devtools_gpu_agent.cc
index 5c6baa1..5dd7669 100644
--- a/content/common/gpu/devtools_gpu_agent.cc
+++ b/content/common/gpu/devtools_gpu_agent.cc
@@ -48,7 +48,7 @@
 void DevToolsGpuAgent::ProcessEvent(
     TimeTicks timestamp,
     GpuEventsDispatcher::EventPhase phase,
-    GpuCommandBufferStub* stub) {
+    GpuChannel* channel) {
   DCHECK(CalledOnValidThread());
   if (route_id_ == MSG_ROUTING_NONE)
     return;
@@ -56,8 +56,8 @@
   GpuTaskInfo task;
   task.timestamp = (timestamp - TimeTicks()).InSecondsF();
   task.phase = phase;
-  task.foreign = stub->channel() != gpu_channel_;
-  task.used_gpu_memory_bytes = stub->GetMemoryUsage();
+  task.foreign = channel != gpu_channel_;
+  task.used_gpu_memory_bytes = channel->GetMemoryUsage();
 
   const int kFlushIntervalMs = 100;
   const unsigned kMaxPendingItems = 100;
diff --git a/content/common/gpu/devtools_gpu_agent.h b/content/common/gpu/devtools_gpu_agent.h
index 6adf54b..03167cc 100644
--- a/content/common/gpu/devtools_gpu_agent.h
+++ b/content/common/gpu/devtools_gpu_agent.h
@@ -20,7 +20,6 @@
 namespace content {
 
 class GpuChannel;
-class GpuCommandBufferStub;
 
 class DevToolsGpuAgent : public base::NonThreadSafe {
  public:
@@ -29,7 +28,7 @@
 
   void ProcessEvent(TimeTicks timestamp,
                     GpuEventsDispatcher::EventPhase,
-                    GpuCommandBufferStub* stub);
+                    GpuChannel* channel);
 
   void StartEventsRecording(int32* route_id);
   void StopEventsRecording();
diff --git a/content/common/gpu/devtools_gpu_instrumentation.cc b/content/common/gpu/devtools_gpu_instrumentation.cc
index 1425d13..0167cf8 100644
--- a/content/common/gpu/devtools_gpu_instrumentation.cc
+++ b/content/common/gpu/devtools_gpu_instrumentation.cc
@@ -36,14 +36,14 @@
 
 // static
 void GpuEventsDispatcher::DoFireEvent(EventPhase phase,
-                                      GpuCommandBufferStub* stub) {
+                                      GpuChannel* channel) {
   TimeTicks timestamp = base::TimeTicks::NowFromSystemTraceTime();
   GpuEventsDispatcher* self =
-      stub->channel()->gpu_channel_manager()->gpu_devtools_events_dispatcher();
+      channel->gpu_channel_manager()->gpu_devtools_events_dispatcher();
   DCHECK(self->CalledOnValidThread());
   std::vector<DevToolsGpuAgent*>::iterator it;
   for (it = self->processors_.begin(); it != self->processors_.end(); ++it) {
-    (*it)->ProcessEvent(timestamp, phase, stub);
+    (*it)->ProcessEvent(timestamp, phase, channel);
   }
 }
 
diff --git a/content/common/gpu/devtools_gpu_instrumentation.h b/content/common/gpu/devtools_gpu_instrumentation.h
index e67d52f..1296625 100644
--- a/content/common/gpu/devtools_gpu_instrumentation.h
+++ b/content/common/gpu/devtools_gpu_instrumentation.h
@@ -13,7 +13,7 @@
 namespace content {
 
 class DevToolsGpuAgent;
-class GpuCommandBufferStub;
+class GpuChannel;
 
 class GpuEventsDispatcher : public base::NonThreadSafe {
  public:
@@ -28,15 +28,15 @@
   void AddProcessor(DevToolsGpuAgent* processor);
   void RemoveProcessor(DevToolsGpuAgent* processor);
 
-  static void FireEvent(EventPhase phase, GpuCommandBufferStub* stub) {
+  static void FireEvent(EventPhase phase, GpuChannel* channel) {
     if (!IsEnabled())
       return;
-    DoFireEvent(phase, stub);
+    DoFireEvent(phase, channel);
   }
 
 private:
   static bool IsEnabled() { return enabled_; }
-  static void DoFireEvent(EventPhase, GpuCommandBufferStub* stub);
+  static void DoFireEvent(EventPhase, GpuChannel* channel);
 
   static bool enabled_;
   std::vector<DevToolsGpuAgent*> processors_;
@@ -46,15 +46,15 @@
 
 class ScopedGpuTask {
  public:
-  explicit ScopedGpuTask(GpuCommandBufferStub* stub) :
-      stub_(stub) {
-    GpuEventsDispatcher::FireEvent(GpuEventsDispatcher::kEventStart, stub_);
+  explicit ScopedGpuTask(GpuChannel* channel) :
+      channel_(channel) {
+    GpuEventsDispatcher::FireEvent(GpuEventsDispatcher::kEventStart, channel_);
   }
   ~ScopedGpuTask() {
-    GpuEventsDispatcher::FireEvent(GpuEventsDispatcher::kEventFinish, stub_);
+    GpuEventsDispatcher::FireEvent(GpuEventsDispatcher::kEventFinish, channel_);
   }
  private:
-  GpuCommandBufferStub* stub_;
+  GpuChannel* channel_;
   DISALLOW_COPY_AND_ASSIGN(ScopedGpuTask);
 };
 
diff --git a/content/common/gpu/gpu_channel.cc b/content/common/gpu/gpu_channel.cc
index a86c7df..9b01150 100644
--- a/content/common/gpu/gpu_channel.cc
+++ b/content/common/gpu/gpu_channel.cc
@@ -894,4 +894,13 @@
   channel_->RemoveFilter(filter);
 }
 
+uint64 GpuChannel::GetMemoryUsage() {
+  uint64 size = 0;
+  for (StubMap::Iterator<GpuCommandBufferStub> it(&stubs_);
+       !it.IsAtEnd(); it.Advance()) {
+    size += it.GetCurrentValue()->GetMemoryUsage();
+  }
+  return size;
+}
+
 }  // namespace content
diff --git a/content/common/gpu/gpu_channel.h b/content/common/gpu/gpu_channel.h
index b79b8a0..760327e 100644
--- a/content/common/gpu/gpu_channel.h
+++ b/content/common/gpu/gpu_channel.h
@@ -147,6 +147,8 @@
   void AddFilter(IPC::ChannelProxy::MessageFilter* filter);
   void RemoveFilter(IPC::ChannelProxy::MessageFilter* filter);
 
+  uint64 GetMemoryUsage();
+
  protected:
   virtual ~GpuChannel();
 
diff --git a/content/common/gpu/gpu_command_buffer_stub.cc b/content/common/gpu/gpu_command_buffer_stub.cc
index 497858a..ef6a45a 100644
--- a/content/common/gpu/gpu_command_buffer_stub.cc
+++ b/content/common/gpu/gpu_command_buffer_stub.cc
@@ -166,7 +166,7 @@
 }
 
 bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
-  devtools_gpu_instrumentation::ScopedGpuTask task(this);
+  devtools_gpu_instrumentation::ScopedGpuTask task(channel());
   FastSetActiveURL(active_url_, active_url_hash_);
 
   // Ensure the appropriate GL context is current before handling any IPC
@@ -686,10 +686,18 @@
     base::SharedMemoryHandle transfer_buffer,
     uint32 size) {
   TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterTransferBuffer");
-  base::SharedMemory shared_memory(transfer_buffer, false);
+
+  // Take ownership of the memory and map it into this process.
+  // This validates the size.
+  scoped_ptr<base::SharedMemory> shared_memory(
+      new base::SharedMemory(transfer_buffer, false));
+  if (!shared_memory->Map(size)) {
+    DVLOG(0) << "Failed to map shared memory.";
+    return;
+  }
 
   if (command_buffer_)
-    command_buffer_->RegisterTransferBuffer(id, &shared_memory, size);
+    command_buffer_->RegisterTransferBuffer(id, shared_memory.Pass(), size);
 }
 
 void GpuCommandBufferStub::OnDestroyTransferBuffer(int32 id) {
@@ -707,19 +715,21 @@
     base::SharedMemoryHandle transfer_buffer = base::SharedMemoryHandle();
     uint32 size = 0;
 
-    gpu::Buffer buffer = command_buffer_->GetTransferBuffer(id);
-    if (buffer.shared_memory) {
+    scoped_refptr<gpu::Buffer> buffer = command_buffer_->GetTransferBuffer(id);
+    if (buffer && buffer->shared_memory()) {
 #if defined(OS_WIN)
       transfer_buffer = NULL;
-      BrokerDuplicateHandle(buffer.shared_memory->handle(),
-          channel_->renderer_pid(), &transfer_buffer, FILE_MAP_READ |
-          FILE_MAP_WRITE, 0);
+      BrokerDuplicateHandle(buffer->shared_memory()->handle(),
+                            channel_->renderer_pid(),
+                            &transfer_buffer,
+                            FILE_MAP_READ | FILE_MAP_WRITE,
+                            0);
       DCHECK(transfer_buffer != NULL);
 #else
-      buffer.shared_memory->ShareToProcess(channel_->renderer_pid(),
-                                           &transfer_buffer);
+      buffer->shared_memory()->ShareToProcess(channel_->renderer_pid(),
+                                              &transfer_buffer);
 #endif
-      size = buffer.size;
+      size = buffer->size();
     }
 
     GpuCommandBufferMsg_GetTransferBuffer::WriteReplyParams(reply_message,
diff --git a/content/common/gpu/gpu_memory_manager.cc b/content/common/gpu/gpu_memory_manager.cc
index 5dfd3fb..9df7b58 100644
--- a/content/common/gpu/gpu_memory_manager.cc
+++ b/content/common/gpu/gpu_memory_manager.cc
@@ -343,7 +343,7 @@
 }
 
 uint64 GpuMemoryManager::GetClientMemoryUsage(
-    const GpuMemoryManagerClient* client) const{
+    const GpuMemoryManagerClient* client) const {
   TrackingGroupMap::const_iterator tracking_group_it =
       tracking_groups_.find(client->GetMemoryTracker());
   DCHECK(tracking_group_it != tracking_groups_.end());
diff --git a/content/common/gpu/gpu_messages.h b/content/common/gpu/gpu_messages.h
index 67f55b2..1f8c72d 100644
--- a/content/common/gpu/gpu_messages.h
+++ b/content/common/gpu/gpu_messages.h
@@ -177,6 +177,7 @@
   IPC_STRUCT_TRAITS_MEMBER(can_lose_context)
   IPC_STRUCT_TRAITS_MEMBER(performance_stats)
   IPC_STRUCT_TRAITS_MEMBER(software_rendering)
+  IPC_STRUCT_TRAITS_MEMBER(direct_rendering)
   IPC_STRUCT_TRAITS_MEMBER(sandboxed)
 #if defined(OS_WIN)
   IPC_STRUCT_TRAITS_MEMBER(dx_diagnostics)
diff --git a/content/common/gpu/image_transport_surface_mac.cc b/content/common/gpu/image_transport_surface_mac.cc
index 615c7d0..254d747 100644
--- a/content/common/gpu/image_transport_surface_mac.cc
+++ b/content/common/gpu/image_transport_surface_mac.cc
@@ -50,7 +50,7 @@
   virtual bool IsOffscreen() OVERRIDE;
   virtual bool SwapBuffers() OVERRIDE;
   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
-  virtual std::string GetExtensions() OVERRIDE;
+  virtual bool SupportsPostSubBuffer() OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
   virtual bool OnMakeCurrent(gfx::GLContext* context) OVERRIDE;
   virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
@@ -281,11 +281,8 @@
   return true;
 }
 
-std::string IOSurfaceImageTransportSurface::GetExtensions() {
-  std::string extensions = gfx::GLSurface::GetExtensions();
-  extensions += extensions.empty() ? "" : " ";
-  extensions += "GL_CHROMIUM_post_sub_buffer";
-  return extensions;
+bool IOSurfaceImageTransportSurface::SupportsPostSubBuffer() {
+  return true;
 }
 
 gfx::Size IOSurfaceImageTransportSurface::GetSize() {
diff --git a/content/common/gpu/media/android_video_encode_accelerator.cc b/content/common/gpu/media/android_video_encode_accelerator.cc
index fe2679f..bc14aa1 100644
--- a/content/common/gpu/media/android_video_encode_accelerator.cc
+++ b/content/common/gpu/media/android_video_encode_accelerator.cc
@@ -208,8 +208,8 @@
                             frame->stride(VideoFrame::kUPlane) &&
                         frame->row_bytes(VideoFrame::kVPlane) ==
                             frame->stride(VideoFrame::kVPlane) &&
-                        gfx::Rect(frame->coded_size()) == frame->visible_rect(),
-                    "Non-packed frame, or visible rect != coded size",
+                        frame->coded_size() == frame->visible_rect().size(),
+                    "Non-packed frame, or visible_rect != coded_size",
                     kInvalidArgumentError);
 
   pending_frames_.push(MakeTuple(frame, force_keyframe, base::Time::Now()));
diff --git a/content/common/gpu/media/video_encode_accelerator_unittest.cc b/content/common/gpu/media/video_encode_accelerator_unittest.cc
index 413d42c..7526fda 100644
--- a/content/common/gpu/media/video_encode_accelerator_unittest.cc
+++ b/content/common/gpu/media/video_encode_accelerator_unittest.cc
@@ -16,6 +16,7 @@
 #include "content/common/gpu/media/video_accelerator_unittest_helpers.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/bitstream_buffer.h"
+#include "media/base/test_data_util.h"
 #include "media/filters/h264_parser.h"
 #include "media/video/video_encode_accelerator.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -51,12 +52,12 @@
 //   Output stream is saved for the simple encode test only.
 // - |requested_bitrate| requested bitrate in bits per second (optional).
 //   Bitrate is only forced for tests that test bitrate.
-const base::FilePath::CharType* test_stream_data =
-    FILE_PATH_LITERAL("sync_192p_20frames.yuv:320:192:1:out.h264:200000");
+base::FilePath::StringType test_stream_data =
+    media::GetTestDataFilePath("sync_192p20_frames.yuv").value() +
+    ":320:192:1:out.h264:200000";
 
 struct TestStream {
-  explicit TestStream(base::FilePath::StringType filename)
-      : requested_bitrate(0) {}
+  TestStream() : requested_bitrate(0) {}
   ~TestStream() {}
 
   gfx::Size size;
@@ -680,7 +681,7 @@
   const unsigned int keyframe_period = GetParam().b;
   const bool force_bitrate = GetParam().c;
 
-  TestStream test_stream(test_stream_data);
+  TestStream test_stream;
   ParseAndReadTestStreamData(test_stream_data, &test_stream);
 
   // Disregard save_to_file if we didn't get an output filename.
diff --git a/content/common/gpu/texture_image_transport_surface.cc b/content/common/gpu/texture_image_transport_surface.cc
index 3de0647..45ce615 100644
--- a/content/common/gpu/texture_image_transport_surface.cc
+++ b/content/common/gpu/texture_image_transport_surface.cc
@@ -268,11 +268,8 @@
   return true;
 }
 
-std::string TextureImageTransportSurface::GetExtensions() {
-  std::string extensions = gfx::GLSurface::GetExtensions();
-  extensions += extensions.empty() ? "" : " ";
-  extensions += "GL_CHROMIUM_post_sub_buffer";
-  return extensions;
+bool TextureImageTransportSurface::SupportsPostSubBuffer() {
+  return true;
 }
 
 gfx::Size TextureImageTransportSurface::GetSize() {
diff --git a/content/common/gpu/texture_image_transport_surface.h b/content/common/gpu/texture_image_transport_surface.h
index a86ff27..95b75a5 100644
--- a/content/common/gpu/texture_image_transport_surface.h
+++ b/content/common/gpu/texture_image_transport_surface.h
@@ -37,7 +37,7 @@
   virtual gfx::Size GetSize() OVERRIDE;
   virtual void* GetHandle() OVERRIDE;
   virtual unsigned GetFormat() OVERRIDE;
-  virtual std::string GetExtensions() OVERRIDE;
+  virtual bool SupportsPostSubBuffer() OVERRIDE;
   virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
   virtual bool SetBackbufferAllocation(bool allocated) OVERRIDE;
diff --git a/content/common/input/synthetic_tap_gesture_params.cc b/content/common/input/synthetic_tap_gesture_params.cc
index a9f91da..c3bb8ff 100644
--- a/content/common/input/synthetic_tap_gesture_params.cc
+++ b/content/common/input/synthetic_tap_gesture_params.cc
@@ -8,7 +8,9 @@
 
 namespace content {
 
-SyntheticTapGestureParams::SyntheticTapGestureParams() : duration_ms(0) {}
+// Set the default tap duration to 50ms to lie within the bounds of the Aura
+// gesture recognizer for identifying clicks (currently 0.01s-0.80s).
+SyntheticTapGestureParams::SyntheticTapGestureParams() : duration_ms(50) {}
 
 SyntheticTapGestureParams::SyntheticTapGestureParams(
     const SyntheticTapGestureParams& other)
diff --git a/content/common/media/media_player_messages_android.h b/content/common/media/media_player_messages_android.h
index 2b2b383..05177ba 100644
--- a/content/common/media/media_player_messages_android.h
+++ b/content/common/media/media_player_messages_android.h
@@ -179,9 +179,12 @@
 IPC_MESSAGE_CONTROL1(MediaPlayerMsg_MediaConfigRequest,
                      int /* demuxer_client_id */)
 
-IPC_MESSAGE_ROUTED1(MediaPlayerMsg_ConnectedToRemoteDevice,
-                    int /* player_id */)
+// Clank has connected to the remote device.
+IPC_MESSAGE_ROUTED2(MediaPlayerMsg_ConnectedToRemoteDevice,
+                    int /* player_id */,
+                    std::string /* remote_playback_message */)
 
+// Clank has disconnected from the remote device.
 IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DisconnectedFromRemoteDevice,
                     int /* player_id */)
 
diff --git a/content/common/media/media_stream_messages.h b/content/common/media/media_stream_messages.h
index 5d106c0..0afa9ec 100644
--- a/content/common/media/media_stream_messages.h
+++ b/content/common/media/media_stream_messages.h
@@ -113,11 +113,12 @@
 // Messages sent from the renderer to the browser.
 
 // Request a new media stream.
-IPC_MESSAGE_CONTROL4(MediaStreamHostMsg_GenerateStream,
+IPC_MESSAGE_CONTROL5(MediaStreamHostMsg_GenerateStream,
                      int /* render view id */,
                      int /* request id */,
                      content::StreamOptions /* components */,
-                     GURL /* security origin */)
+                     GURL /* security origin */,
+                     bool /* user_gesture */)
 
 // Request to cancel the request for a new media stream.
 IPC_MESSAGE_CONTROL2(MediaStreamHostMsg_CancelGenerateStream,
diff --git a/content/common/media/midi_messages.h b/content/common/media/midi_messages.h
index 5a0fd7e..c907a98 100644
--- a/content/common/media/midi_messages.h
+++ b/content/common/media/midi_messages.h
@@ -25,10 +25,11 @@
 // Messages for IPC between MidiDispatcher and MidiDispatcherHost.
 
 // Renderer request to browser for using system exclusive messages.
-IPC_MESSAGE_CONTROL3(MidiHostMsg_RequestSysExPermission,
+IPC_MESSAGE_CONTROL4(MidiHostMsg_RequestSysExPermission,
                      int /* routing id */,
                      int /* client id */,
-                     GURL /* origin */)
+                     GURL /* origin */,
+                     bool /* user_gesture */)
 
 // Renderer request to browser for canceling a previous permission request.
 IPC_MESSAGE_CONTROL3(MidiHostMsg_CancelSysExPermissionRequest,
diff --git a/content/common/mojo/mojo_channel_init.cc b/content/common/mojo/mojo_channel_init.cc
index 088a8e9..16661ab 100644
--- a/content/common/mojo/mojo_channel_init.cc
+++ b/content/common/mojo/mojo_channel_init.cc
@@ -5,33 +5,11 @@
 #include "content/common/mojo/mojo_channel_init.h"
 
 #include "base/bind.h"
-#include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
-#include "base/synchronization/lock.h"
 #include "mojo/embedder/embedder.h"
 
 namespace content {
 
-namespace {
-
-struct Initializer {
-  Initializer() {
-    mojo::embedder::Init();
-  }
-};
-
-static base::LazyInstance<Initializer>::Leaky initializer =
-    LAZY_INSTANCE_INITIALIZER;
-
-// Initializes mojo. Use a lazy instance to ensure we only do this once.
-// TODO(sky): this likely wants to move to a more central location, such as
-// startup.
-void InitMojo() {
-  initializer.Get();
-}
-
-}  // namespace
-
 MojoChannelInit::MojoChannelInit()
     : channel_info_(NULL),
       weak_factory_(this) {
@@ -51,7 +29,6 @@
     scoped_refptr<base::TaskRunner> io_thread_task_runner) {
   DCHECK(!io_thread_task_runner_.get());  // Should only init once.
   io_thread_task_runner_ = io_thread_task_runner;
-  InitMojo();
   bootstrap_message_pipe_ = mojo::embedder::CreateChannel(
       mojo::embedder::ScopedPlatformHandle(
           mojo::embedder::PlatformHandle(file)),
diff --git a/content/common/mojo/mojo_channel_init.h b/content/common/mojo/mojo_channel_init.h
index 44ba07d..05b4e0c 100644
--- a/content/common/mojo/mojo_channel_init.h
+++ b/content/common/mojo/mojo_channel_init.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -9,7 +9,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/platform_file.h"
 #include "content/common/content_export.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace base {
 class MessageLoopProxy;
@@ -37,6 +37,10 @@
 
   bool is_handle_valid() const { return bootstrap_message_pipe_.is_valid(); }
 
+  mojo::ScopedMessagePipeHandle bootstrap_message_pipe() {
+    return bootstrap_message_pipe_.Pass();
+  }
+
  private:
   // Invoked on the main thread once the channel has been established.
   static void OnCreatedChannel(
diff --git a/content/common/mojo/mojo_messages.h b/content/common/mojo/mojo_messages.h
index 31cea20..6e7685b 100644
--- a/content/common/mojo/mojo_messages.h
+++ b/content/common/mojo/mojo_messages.h
@@ -11,6 +11,7 @@
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_message_utils.h"
 #include "ipc/ipc_param_traits.h"
+#include "ipc/ipc_platform_file.h"
 #include "ipc/param_traits_macros.h"
 
 #undef IPC_MESSAGE_EXPORT
diff --git a/content/common/mojo/render_process.mojom b/content/common/mojo/render_process.mojom
new file mode 100644
index 0000000..1ad9e55
--- /dev/null
+++ b/content/common/mojo/render_process.mojom
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content {
+
+[Peer=RenderProcessMojo]
+interface RenderProcessHostMojo {
+};
+
+[Peer=RenderProcessHostMojo]
+interface RenderProcessMojo {
+  SetWebUIHandle(int32 view_routing_id,
+                 handle<message_pipe> browser_web_ui_handle);
+};
+
+}
diff --git a/content/common/plugin_list_posix.cc b/content/common/plugin_list_posix.cc
index 72a9310..bdbd0c8 100644
--- a/content/common/plugin_list_posix.cc
+++ b/content/common/plugin_list_posix.cc
@@ -31,10 +31,6 @@
 #include "build/build_config.h"
 #include "third_party/npapi/bindings/nphostapi.h"
 
-// These headers must be included in this order to make the declaration gods
-// happy.
-#include "base/third_party/nspr/prcpucfg_linux.h"
-
 namespace content {
 
 namespace {
@@ -240,14 +236,14 @@
     return;
   }
 
-  std::string error;
+  base::NativeLibraryLoadError error;
   void* newdl = base::LoadNativeLibrary(path, &error);
   if (!newdl) {
     // We couldn't load the unwrapped plugin for some reason, despite
     // being able to load the wrapped one.  Just use the wrapped one.
     LOG_IF(ERROR, PluginList::DebugPluginLoading())
         << "Could not use unwrapped nspluginwrapper plugin "
-        << unwrapped_path->value() << " (" << error << "), "
+        << unwrapped_path->value() << " (" << error.ToString() << "), "
         << "using the wrapped one.";
     return;
   }
@@ -276,12 +272,12 @@
     return false;
   }
 
-  std::string error;
+  base::NativeLibraryLoadError error;
   void* dl = base::LoadNativeLibrary(filename, &error);
   if (!dl) {
     LOG_IF(ERROR, PluginList::DebugPluginLoading())
         << "While reading plugin info, unable to load library "
-        << filename.value() << " (" << error << "), skipping.";
+        << filename.value() << " (" << error.ToString() << "), skipping.";
     return false;
   }
 
diff --git a/content/common/quota_messages.h b/content/common/quota_messages.h
index 022633d..d3d0f83 100644
--- a/content/common/quota_messages.h
+++ b/content/common/quota_messages.h
@@ -11,7 +11,7 @@
 
 #define IPC_MESSAGE_START QuotaMsgStart
 
-IPC_ENUM_TRAITS(quota::StorageType)
+IPC_ENUM_TRAITS_MAX_VALUE(quota::StorageType, quota::kStorageTypeLast)
 IPC_ENUM_TRAITS(quota::QuotaStatusCode)
 
 // Quota messages sent from the browser to the child process.
diff --git a/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc b/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
index 82a91b3..02d5477 100644
--- a/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
+++ b/content/common/sandbox_linux/bpf_cros_arm_gpu_policy_linux.cc
@@ -73,39 +73,6 @@
   write_whitelist->push_back(kDevMfcEncPath);
 }
 
-void AddArmTegraGpuWhitelist(std::vector<std::string>* read_whitelist,
-                             std::vector<std::string>* write_whitelist) {
-  // Device files needed by the Tegra GPU userspace.
-  static const char kDevNvhostCtrlPath[] = "/dev/nvhost-ctrl";
-  static const char kDevNvhostIspPath[] = "/dev/nvhost-isp";
-  static const char kDevNvhostViPath[] = "/dev/nvhost-vi";
-  static const char kDevNvmapPath[] = "/dev/nvmap";
-  static const char kDevNvhostGpuPath[] = "/dev/nvhost-gpu";
-  static const char kDevNvhostAsGpuPath[] = "/dev/nvhost-as-gpu";
-  static const char kDevNvhostCtrlGpuPath[] = "/dev/nvhost-ctrl-gpu";
-  static const char kSysDevicesSocIDPath[] = "/sys/devices/soc0/soc_id";
-  static const char kSysDevicesSocRevPath[] = "/sys/devices/soc0/revision";
-  // TODO(davidung): remove these device nodes before nyan launch.
-
-  read_whitelist->push_back(kDevNvhostCtrlPath);
-  read_whitelist->push_back(kDevNvhostIspPath);
-  read_whitelist->push_back(kDevNvhostViPath);
-  read_whitelist->push_back(kDevNvmapPath);
-  read_whitelist->push_back(kDevNvhostGpuPath);
-  read_whitelist->push_back(kDevNvhostAsGpuPath);
-  read_whitelist->push_back(kDevNvhostCtrlGpuPath);
-  read_whitelist->push_back(kSysDevicesSocIDPath);
-  read_whitelist->push_back(kSysDevicesSocRevPath);
-
-  write_whitelist->push_back(kDevNvhostCtrlPath);
-  write_whitelist->push_back(kDevNvhostIspPath);
-  write_whitelist->push_back(kDevNvhostViPath);
-  write_whitelist->push_back(kDevNvmapPath);
-  write_whitelist->push_back(kDevNvhostGpuPath);
-  write_whitelist->push_back(kDevNvhostAsGpuPath);
-  write_whitelist->push_back(kDevNvhostCtrlGpuPath);
-}
-
 void AddArmGpuWhitelist(std::vector<std::string>* read_whitelist,
                         std::vector<std::string>* write_whitelist) {
   // On ARM we're enabling the sandbox before the X connection is made,
@@ -123,7 +90,6 @@
   read_whitelist->push_back(kLibEglPath);
 
   AddArmMaliGpuWhitelist(read_whitelist, write_whitelist);
-  AddArmTegraGpuWhitelist(read_whitelist, write_whitelist);
 }
 
 class CrosArmGpuBrokerProcessPolicy : public CrosArmGpuProcessPolicy {
@@ -215,14 +181,6 @@
   // Preload the Mali library.
   dlopen("/usr/lib/libmali.so", dlopen_flag);
 
-  // Preload the Tegra libraries.
-  dlopen("/usr/lib/libnvrm.so", dlopen_flag);
-  dlopen("/usr/lib/libnvrm_graphics.so", dlopen_flag);
-  dlopen("/usr/lib/libnvidia-glsi.so", dlopen_flag);
-  dlopen("/usr/lib/libnvidia-rmapi-tegra.so", dlopen_flag);
-  dlopen("/usr/lib/libnvidia-eglcore.so", dlopen_flag);
-  // TODO(davidung): remove these libraries before nyan launch.
-
   return true;
 }
 
diff --git a/content/common/sandbox_linux/sandbox_linux.cc b/content/common/sandbox_linux/sandbox_linux.cc
index 6f60584..de12bb0 100644
--- a/content/common/sandbox_linux/sandbox_linux.cc
+++ b/content/common/sandbox_linux/sandbox_linux.cc
@@ -15,6 +15,7 @@
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
+#include "base/debug/stack_trace.h"
 #include "base/files/scoped_file.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
@@ -135,6 +136,11 @@
 #endif
 
 #if !defined(NDEBUG)
+  // The in-process stack dumping needs to open /proc/self/maps and cache
+  // its contents before the sandbox is enabled.  It also pre-opens the
+  // object files that are already loaded in the process address space.
+  base::debug::EnableInProcessStackDumpingForSandbox();
+
   // Open proc_fd_ only in Debug mode so that forgetting to close it doesn't
   // produce a sandbox escape in Release mode.
   proc_fd_ = open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
diff --git a/content/common/sandbox_mac_system_access_unittest.mm b/content/common/sandbox_mac_system_access_unittest.mm
index 4ddc73a..c527ea5 100644
--- a/content/common/sandbox_mac_system_access_unittest.mm
+++ b/content/common/sandbox_mac_system_access_unittest.mm
@@ -87,7 +87,7 @@
 REGISTER_SANDBOX_TEST_CASE(MacSandboxedFileAccessTestCase);
 
 bool MacSandboxedFileAccessTestCase::SandboxedTest() {
-  base::ScopedFD fdes(open("/etc/passwd", O_RDONLY));
+  base::ScopedFD fdes(HANDLE_EINTR(open("/etc/passwd", O_RDONLY)));
   return !fdes.is_valid();
 }
 
@@ -105,14 +105,14 @@
 REGISTER_SANDBOX_TEST_CASE(MacSandboxedUrandomTestCase);
 
 bool MacSandboxedUrandomTestCase::SandboxedTest() {
-  base::ScopedFD fdes(open("/dev/urandom", O_RDONLY));
+  base::ScopedFD fdes(HANDLE_EINTR(open("/dev/urandom", O_RDONLY)));
 
   // Opening /dev/urandom succeeds under the sandbox.
   if (!fdes.is_valid())
     return false;
 
   char buf[16];
-  int rc = read(fdes.get(), buf, sizeof(buf));
+  int rc = HANDLE_EINTR(read(fdes.get(), buf, sizeof(buf)));
   return rc == sizeof(buf);
 }
 
diff --git a/content/common/sandbox_win.cc b/content/common/sandbox_win.cc
index a73296c..6f063d7 100644
--- a/content/common/sandbox_win.cc
+++ b/content/common/sandbox_win.cc
@@ -403,13 +403,15 @@
 #ifndef OFFICIAL_BUILD
 base::win::IATPatchFunction g_iat_patch_duplicate_handle;
 
-BOOL (WINAPI *g_iat_orig_duplicate_handle)(HANDLE source_process_handle,
-                                           HANDLE source_handle,
-                                           HANDLE target_process_handle,
-                                           LPHANDLE target_handle,
-                                           DWORD desired_access,
-                                           BOOL inherit_handle,
-                                           DWORD options);
+typedef BOOL (WINAPI *DuplicateHandleFunctionPtr)(HANDLE source_process_handle,
+                                                  HANDLE source_handle,
+                                                  HANDLE target_process_handle,
+                                                  LPHANDLE target_handle,
+                                                  DWORD desired_access,
+                                                  BOOL inherit_handle,
+                                                  DWORD options);
+
+DuplicateHandleFunctionPtr g_iat_orig_duplicate_handle;
 
 NtQueryObject g_QueryObject = NULL;
 
@@ -547,10 +549,13 @@
     DWORD result = ::GetModuleFileNameW(module, module_name, MAX_PATH);
     if (result && (result != MAX_PATH)) {
       ResolveNTFunctionPtr("NtQueryObject", &g_QueryObject);
-      g_iat_orig_duplicate_handle = ::DuplicateHandle;
-      g_iat_patch_duplicate_handle.Patch(
+      result = g_iat_patch_duplicate_handle.Patch(
           module_name, "kernel32.dll", "DuplicateHandle",
           DuplicateHandlePatch);
+      CHECK(result == 0);
+      g_iat_orig_duplicate_handle =
+          reinterpret_cast<DuplicateHandleFunctionPtr>(
+              g_iat_patch_duplicate_handle.original_function());
     }
   }
 #endif
@@ -566,6 +571,16 @@
   return sandbox::SBOX_ALL_OK == result;
 }
 
+bool ShouldUseDirectWrite() {
+  // If the flag is currently on, and we're on Win7 or above, we enable
+  // DirectWrite. Skia does not require the additions to DirectWrite in QFE
+  // 2670838, so a Win7 check is sufficient. We do not currently attempt to
+  // support Vista, where SP2 and the Platform Update are required.
+  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  return command_line.HasSwitch(switches::kEnableDirectWrite) &&
+         base::win::GetVersion() >= base::win::VERSION_WIN7;
+}
+
 base::ProcessHandle StartSandboxedProcess(
     SandboxedProcessLauncherDelegate* delegate,
     CommandLine* cmd_line) {
@@ -632,7 +647,15 @@
   if (!disable_default_policy && !AddPolicyForSandboxedProcess(policy))
     return 0;
 
-  if (type_str != switches::kRendererProcess) {
+  if (type_str == switches::kRendererProcess) {
+    if (ShouldUseDirectWrite()) {
+      AddDirectory(base::DIR_WINDOWS_FONTS,
+                  NULL,
+                  true,
+                  sandbox::TargetPolicy::FILES_ALLOW_READONLY,
+                  policy);
+    }
+  } else {
     // Hack for Google Desktop crash. Trick GD into not injecting its DLL into
     // this subprocess. See
     // http://code.google.com/p/chromium/issues/detail?id=25580
diff --git a/content/common/sandbox_win.h b/content/common/sandbox_win.h
index ac6ce90..92d8d04 100644
--- a/content/common/sandbox_win.h
+++ b/content/common/sandbox_win.h
@@ -33,6 +33,8 @@
 
 bool InitTargetServices(sandbox::TargetServices* target_services);
 
+bool ShouldUseDirectWrite();
+
 }  // namespace content
 
 #endif  // CONTENT_COMMON_SANDBOX_WIN_H_
diff --git a/content/common/service_worker/service_worker_messages.h b/content/common/service_worker/service_worker_messages.h
index 135761f..1ece594 100644
--- a/content/common/service_worker/service_worker_messages.h
+++ b/content/common/service_worker/service_worker_messages.h
@@ -10,6 +10,7 @@
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_param_traits.h"
 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerEventResult.h"
 #include "url/gurl.h"
 
 #undef IPC_MESSAGE_EXPORT
@@ -20,6 +21,9 @@
 IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerError::ErrorType,
                           blink::WebServiceWorkerError::ErrorTypeLast)
 
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerEventResult,
+                          blink::WebServiceWorkerEventResultLast)
+
 IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerFetchRequest)
   IPC_STRUCT_TRAITS_MEMBER(url)
   IPC_STRUCT_TRAITS_MEMBER(method)
@@ -49,6 +53,12 @@
                      int32 /* request_id */,
                      GURL /* scope (url pattern) */)
 
+// Sends a 'message' event to a service worker (renderer->browser).
+IPC_MESSAGE_CONTROL3(ServiceWorkerHostMsg_PostMessage,
+                     int64 /* registration_id */,
+                     base::string16 /* message */,
+                     std::vector<int> /* sent_message_port_ids */)
+
 // Messages sent from the browser to the child process.
 
 // Response to ServiceWorkerMsg_RegisterServiceWorker
@@ -71,13 +81,18 @@
                      base::string16 /* message */)
 
 // Sent via EmbeddedWorker to dispatch install event.
-IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_InstallEvent,
-                     int /* active_version_embedded_worker_id */)
+IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_InstallEvent, int /* active_version_id */)
 
 // Sent via EmbeddedWorker to dispatch fetch event.
 IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_FetchEvent,
                      content::ServiceWorkerFetchRequest)
 
+// Sends a 'message' event to a service worker (browser->EmbeddedWorker).
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_Message,
+                     base::string16 /* message */,
+                     std::vector<int> /* sent_message_port_ids */,
+                     std::vector<int> /* new_routing_ids */)
+
 // Informs the browser of a new ServiceWorkerProvider in the child process,
 // |provider_id| is unique within its child process.
 IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_ProviderCreated,
@@ -98,12 +113,12 @@
                      int /* provider_id */)
 
 // Informs the browser that install event handling has finished.
-// Sent via EmbeddedWorker. If there was an exception during the
-// event handling it'll be reported back separately (to be propagated
-// to the documents).
-IPC_MESSAGE_CONTROL0(ServiceWorkerHostMsg_InstallEventFinished)
+// Sent via EmbeddedWorker.
+IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_InstallEventFinished,
+                     blink::WebServiceWorkerEventResult)
 
 // Informs the browser that fetch event handling has finished.
+// Sent via EmbeddedWorker.
 IPC_MESSAGE_CONTROL2(ServiceWorkerHostMsg_FetchEventFinished,
                      content::ServiceWorkerFetchEventResult,
                      content::ServiceWorkerResponse)
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc
index 4b82e41..29709ed 100644
--- a/content/common/swapped_out_messages.cc
+++ b/content/common/swapped_out_messages.cc
@@ -25,7 +25,6 @@
     case ViewHostMsg_Focus::ID:
     // Handled by RenderViewHost.
     case ViewHostMsg_RenderProcessGone::ID:
-    case ViewHostMsg_SwapOut_ACK::ID:
     case ViewHostMsg_ClosePage_ACK::ID:
     case ViewHostMsg_SwapCompositorFrame::ID:
     case ViewHostMsg_UpdateIsDelayed::ID:
diff --git a/content/common/view_message_enums.h b/content/common/view_message_enums.h
index 4bbd217..1175568 100644
--- a/content/common/view_message_enums.h
+++ b/content/common/view_message_enums.h
@@ -36,21 +36,24 @@
   // Accessibility is on, and the full tree is computed. If this flag is off,
   // only limited information about editable text nodes is sent to the browser
   // process. Useful for implementing limited UIA on tablets.
-  AccessibilityModeFlagPlatformFullTree = 1 << 1,
+  AccessibilityModeFlagFullTree = 1 << 1,
 };
 
 enum AccessibilityMode {
   // All accessibility is off.
   AccessibilityModeOff = 0,
 
-  // Renderer accessibility is on, and platform APIs are called. Note that this
-  // is different to AccessibilityModeAll, which is defined to be all bits on.
-  AccessibilityModeComplete =
-      AccessibilityModeFlagPlatform | AccessibilityModeFlagPlatformFullTree,
-
   // Renderer accessibility is on, platform APIs are called, but only limited
   // information is available (see AccessibilityModeFlagEditableTextOnly).
-  AccessibilityModeEditableTextOnly = AccessibilityModeFlagPlatform
+  AccessibilityModeEditableTextOnly = AccessibilityModeFlagPlatform,
+
+  // Renderer accessibility is on, and platform APIs are called.
+  AccessibilityModeComplete =
+      AccessibilityModeFlagPlatform | AccessibilityModeFlagFullTree,
+
+  // Renderer accessibility is on, and events are passed to any extensions
+  // requesting automation, but not to platform accessibility.
+  AccessibilityModeTreeOnly = AccessibilityModeFlagFullTree,
 };
 
 #endif  // CONTENT_COMMON_VIEW_MESSAGES_ENUMS_H_
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 82c14f8..7846859 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -42,7 +42,6 @@
 #include "third_party/WebKit/public/platform/WebFloatPoint.h"
 #include "third_party/WebKit/public/platform/WebFloatRect.h"
 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
-#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
 #include "third_party/WebKit/public/web/WebFindOptions.h"
 #include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
 #include "third_party/WebKit/public/web/WebPluginAction.h"
@@ -100,13 +99,6 @@
 IPC_STRUCT_TRAITS_END()
 #endif
 
-IPC_STRUCT_TRAITS_BEGIN(blink::WebCompositionUnderline)
-  IPC_STRUCT_TRAITS_MEMBER(startOffset)
-  IPC_STRUCT_TRAITS_MEMBER(endOffset)
-  IPC_STRUCT_TRAITS_MEMBER(color)
-  IPC_STRUCT_TRAITS_MEMBER(thick)
-IPC_STRUCT_TRAITS_END()
-
 IPC_STRUCT_TRAITS_BEGIN(blink::WebFindOptions)
   IPC_STRUCT_TRAITS_MEMBER(forward)
   IPC_STRUCT_TRAITS_MEMBER(matchCase)
@@ -273,8 +265,8 @@
   // has been specified).
   IPC_STRUCT_MEMBER(base::string16, frame_name)
 
-  // The frame identifier of the frame initiating the open.
-  IPC_STRUCT_MEMBER(int64, opener_frame_id)
+  // The routing id of the frame initiating the open.
+  IPC_STRUCT_MEMBER(int, opener_render_frame_id)
 
   // The URL of the frame initiating the open.
   IPC_STRUCT_MEMBER(GURL, opener_url)
@@ -822,25 +814,6 @@
                     gfx::Range /* replacement_range */,
                     bool /* keep_selection */)
 
-// Sets the text composition to be between the given start and end offsets
-// in the currently focused editable field.
-IPC_MESSAGE_ROUTED3(ViewMsg_SetCompositionFromExistingText,
-    int /* start */,
-    int /* end */,
-    std::vector<blink::WebCompositionUnderline> /* underlines */)
-
-// Selects between the given start and end offsets in the currently focused
-// editable field.
-IPC_MESSAGE_ROUTED2(ViewMsg_SetEditableSelectionOffsets,
-                    int /* start */,
-                    int /* end */)
-
-// Deletes the current selection plus the specified number of characters before
-// and after the selection or caret.
-IPC_MESSAGE_ROUTED2(ViewMsg_ExtendSelectionAndDelete,
-                    int /* before */,
-                    int /* after */)
-
 // Used to notify the render-view that we have received a target URL. Used
 // to prevent target URLs spamming the browser.
 IPC_MESSAGE_ROUTED0(ViewMsg_UpdateTargetURL_ACK)
@@ -869,11 +842,6 @@
 // PageGroupLoadDeferrer is on the stack for SwapOut.
 IPC_MESSAGE_ROUTED0(ViewMsg_SuppressDialogsUntilSwapOut)
 
-// Instructs the renderer to swap out for a cross-site transition, including
-// running the unload event handler. Expects a SwapOut_ACK message when
-// finished.
-IPC_MESSAGE_ROUTED0(ViewMsg_SwapOut)
-
 // Instructs the renderer to close the current page, including running the
 // onunload event handler.
 //
@@ -1202,9 +1170,12 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_RequestMove,
                     gfx::Rect /* position */)
 
-// Message to show a popup menu using native cocoa controls (Mac only).
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+// Message to show/hide a popup menu using native controls.
 IPC_MESSAGE_ROUTED1(ViewHostMsg_ShowPopup,
                     ViewHostMsg_ShowPopup_Params)
+IPC_MESSAGE_ROUTED0(ViewHostMsg_HidePopup)
+#endif
 
 // Response from ViewMsg_ScriptEvalRequest. The ID is the parameter supplied
 // to ViewMsg_ScriptEvalRequest. The result has the value returned by the
@@ -1227,10 +1198,6 @@
                     int /* active_match_ordinal */,
                     bool /* final_update */)
 
-// Indicates that the current renderer has swapped out, after a SwapOut
-// message.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_SwapOut_ACK)
-
 // Indicates that the current page has been closed, after a ClosePage
 // message.
 IPC_MESSAGE_ROUTED0(ViewHostMsg_ClosePage_ACK)
diff --git a/content/common/worker_messages.h b/content/common/worker_messages.h
index 3cc6a6f..743d22f 100644
--- a/content/common/worker_messages.h
+++ b/content/common/worker_messages.h
@@ -42,6 +42,7 @@
   IPC_STRUCT_MEMBER(base::string16, name)
   IPC_STRUCT_MEMBER(base::string16, content_security_policy)
   IPC_STRUCT_MEMBER(blink::WebContentSecurityPolicyType, security_policy_type)
+  IPC_STRUCT_MEMBER(bool, pause_on_start)
   IPC_STRUCT_MEMBER(int, route_id)
 IPC_STRUCT_END()
 
diff --git a/content/common_aidl.target.darwin-arm.mk b/content/common_aidl.target.darwin-arm.mk
index 06520cd..5474229 100644
--- a/content/common_aidl.target.darwin-arm.mk
+++ b/content/common_aidl.target.darwin-arm.mk
@@ -106,6 +106,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -189,6 +190,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/common_aidl.target.darwin-mips.mk b/content/common_aidl.target.darwin-mips.mk
index e7613ca..3565952 100644
--- a/content/common_aidl.target.darwin-mips.mk
+++ b/content/common_aidl.target.darwin-mips.mk
@@ -105,6 +105,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/common_aidl.target.darwin-x86.mk b/content/common_aidl.target.darwin-x86.mk
index 186a86b..a168d33 100644
--- a/content/common_aidl.target.darwin-x86.mk
+++ b/content/common_aidl.target.darwin-x86.mk
@@ -107,6 +107,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/common_aidl.target.darwin-x86_64.mk b/content/common_aidl.target.darwin-x86_64.mk
new file mode 100644
index 0000000..1fa1fab
--- /dev/null
+++ b/content/common_aidl.target.darwin-x86_64.mk
@@ -0,0 +1,246 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_common_aidl_gyp
+LOCAL_MODULE_STEM := common_aidl
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_common_aidl_target_compile_aidl":
+# "{'inputs': ['$(PWD)/prebuilts/sdk/18/framework.aidl', 'public/android/java/src/org/chromium/content/common/common.aidl'], 'extension': 'aidl', 'rule_sources': ['public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl', 'public/android/java/src/org/chromium/content/common/IChildProcessService.aidl'], 'rule_name': 'compile_aidl', 'outputs': ['$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java'], 'action': ['$(PWD)/prebuilts/sdk/tools/darwin/aidl', '-p$(PWD)/prebuilts/sdk/18/framework.aidl', '-ppublic/android/java/src/org/chromium/content/common/common.aidl', '$(RULE_SOURCES)', '$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java']}":
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl $(PWD)/prebuilts/sdk/18/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(PWD)/prebuilts/sdk/tools/darwin/aidl" "-p$(PWD)/prebuilts/sdk/18/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java
+
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessService.aidl $(PWD)/prebuilts/sdk/18/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(PWD)/prebuilts/sdk/tools/darwin/aidl" "-p$(PWD)/prebuilts/sdk/18/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessService.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_common_aidl_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_common_aidl_gyp
+
+# Alias gyp target name.
+.PHONY: common_aidl
+common_aidl: content_common_aidl_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/common_aidl.target.linux-arm.mk b/content/common_aidl.target.linux-arm.mk
index 950e080..7e99482 100644
--- a/content/common_aidl.target.linux-arm.mk
+++ b/content/common_aidl.target.linux-arm.mk
@@ -106,6 +106,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -189,6 +190,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/common_aidl.target.linux-mips.mk b/content/common_aidl.target.linux-mips.mk
index f51d391..1edd299 100644
--- a/content/common_aidl.target.linux-mips.mk
+++ b/content/common_aidl.target.linux-mips.mk
@@ -105,6 +105,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/common_aidl.target.linux-x86.mk b/content/common_aidl.target.linux-x86.mk
index dab4287..91f6860 100644
--- a/content/common_aidl.target.linux-x86.mk
+++ b/content/common_aidl.target.linux-x86.mk
@@ -107,6 +107,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/common_aidl.target.linux-x86_64.mk b/content/common_aidl.target.linux-x86_64.mk
new file mode 100644
index 0000000..ad1e98e
--- /dev/null
+++ b/content/common_aidl.target.linux-x86_64.mk
@@ -0,0 +1,246 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_common_aidl_gyp
+LOCAL_MODULE_STEM := common_aidl
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_common_aidl_target_compile_aidl":
+# "{'inputs': ['$(PWD)/prebuilts/sdk/18/framework.aidl', 'public/android/java/src/org/chromium/content/common/common.aidl'], 'extension': 'aidl', 'rule_sources': ['public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl', 'public/android/java/src/org/chromium/content/common/IChildProcessService.aidl'], 'rule_name': 'compile_aidl', 'outputs': ['$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java'], 'action': ['$(PWD)/prebuilts/sdk/tools/linux/aidl', '-p$(PWD)/prebuilts/sdk/18/framework.aidl', '-ppublic/android/java/src/org/chromium/content/common/common.aidl', '$(RULE_SOURCES)', '$(gyp_shared_intermediate_dir)/common_aidl/aidl/%(INPUT_ROOT)s.java']}":
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl $(PWD)/prebuilts/sdk/18/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(PWD)/prebuilts/sdk/tools/linux/aidl" "-p$(PWD)/prebuilts/sdk/18/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessCallback.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java
+
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/IChildProcessService.aidl $(PWD)/prebuilts/sdk/18/framework.aidl $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/common.aidl $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/common_aidl/aidl; cd $(gyp_local_path)/content; "$(PWD)/prebuilts/sdk/tools/linux/aidl" "-p$(PWD)/prebuilts/sdk/18/framework.aidl" -ppublic/android/java/src/org/chromium/content/common/common.aidl public/android/java/src/org/chromium/content/common/IChildProcessService.aidl "$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java"
+
+.PHONY: content_common_aidl_gyp_rule_trigger
+content_common_aidl_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessCallback.java \
+	$(gyp_shared_intermediate_dir)/common_aidl/aidl/IChildProcessService.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_common_aidl_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_common_aidl_gyp
+
+# Alias gyp target name.
+.PHONY: common_aidl
+common_aidl: content_common_aidl_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content.gyp b/content/content.gyp
index 8aa3bfb..bc344e7 100644
--- a/content/content.gyp
+++ b/content/content.gyp
@@ -22,6 +22,11 @@
     ],
   },
   'conditions': [
+    ['use_mojo==1', {
+      'includes': [
+        'content_common_mojo_bindings.gypi',
+      ],
+    }],
     ['OS != "ios"', {
       'includes': [
         '../build/win_precompile.gypi',
diff --git a/content/content_app.gypi b/content/content_app.gypi
index 4908175..6187bce 100644
--- a/content/content_app.gypi
+++ b/content/content_app.gypi
@@ -24,6 +24,8 @@
     'app/android/library_loader_hooks.cc',
     'app/content_main.cc',
     'app/content_main_runner.cc',
+    'app/mojo/mojo_init.cc',
+    'app/mojo/mojo_init.h',
     'app/startup_helper_win.cc',
     'public/app/android_library_loader_hooks.h',
     'public/app/content_main.h',
@@ -55,5 +57,18 @@
         'app/content_main.cc',
       ],
     }],
+    ['use_mojo==0', {
+      'sources!': [
+        'app/mojo/mojo_init.cc',
+        'app/mojo/mojo_init.h',
+      ],
+    }, {
+      'dependencies': [
+        '../mojo/mojo.gyp:mojo_environment_chromium',
+        '../mojo/mojo.gyp:mojo_service_manager',
+        '../mojo/mojo.gyp:mojo_system',
+        '../mojo/mojo.gyp:mojo_system_impl',
+     ],
+    }],
   ],
 }
diff --git a/content/content_app_both.target.darwin-arm.mk b/content/content_app_both.target.darwin-arm.mk
index ec8e340..babb5b4 100644
--- a/content/content_app_both.target.darwin-arm.mk
+++ b/content/content_app_both.target.darwin-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_app_both.target.darwin-mips.mk b/content/content_app_both.target.darwin-mips.mk
index 8015733..51ff76c 100644
--- a/content/content_app_both.target.darwin-mips.mk
+++ b/content/content_app_both.target.darwin-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_app_both.target.darwin-x86.mk b/content/content_app_both.target.darwin-x86.mk
index 4e28e56..9c1b40b 100644
--- a/content/content_app_both.target.darwin-x86.mk
+++ b/content/content_app_both.target.darwin-x86.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_app_both.target.darwin-x86_64.mk b/content/content_app_both.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d979570
--- /dev/null
+++ b/content/content_app_both.target.darwin-x86_64.mk
@@ -0,0 +1,349 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_app_both_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/app/android/app_jni_registrar.cc \
+	content/app/android/child_process_service.cc \
+	content/app/android/content_main.cc \
+	content/app/android/library_loader_hooks.cc \
+	content/app/content_main_runner.cc \
+	content/public/app/content_main_delegate.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	ui_base_ui_base_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_app_both_gyp
+
+# Alias gyp target name.
+.PHONY: content_app_both
+content_app_both: content_content_app_both_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_app_both.target.linux-arm.mk b/content/content_app_both.target.linux-arm.mk
index ec8e340..babb5b4 100644
--- a/content/content_app_both.target.linux-arm.mk
+++ b/content/content_app_both.target.linux-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_app_both.target.linux-mips.mk b/content/content_app_both.target.linux-mips.mk
index 8015733..51ff76c 100644
--- a/content/content_app_both.target.linux-mips.mk
+++ b/content/content_app_both.target.linux-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_app_both.target.linux-x86.mk b/content/content_app_both.target.linux-x86.mk
index 4e28e56..9c1b40b 100644
--- a/content/content_app_both.target.linux-x86.mk
+++ b/content/content_app_both.target.linux-x86.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_app_both.target.linux-x86_64.mk b/content/content_app_both.target.linux-x86_64.mk
new file mode 100644
index 0000000..d979570
--- /dev/null
+++ b/content/content_app_both.target.linux-x86_64.mk
@@ -0,0 +1,349 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_app_both_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/app/android/app_jni_registrar.cc \
+	content/app/android/child_process_service.cc \
+	content/app/android/content_main.cc \
+	content/app/android/library_loader_hooks.cc \
+	content/app/content_main_runner.cc \
+	content/public/app/content_main_delegate.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	ui_base_ui_base_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_app_both_gyp
+
+# Alias gyp target name.
+.PHONY: content_app_both
+content_app_both: content_content_app_both_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_browser.gypi b/content/content_browser.gypi
index 3c6d0ba..2785b7c 100644
--- a/content/content_browser.gypi
+++ b/content/content_browser.gypi
@@ -181,6 +181,7 @@
     'public/browser/resource_request_info.h',
     'public/browser/resource_throttle.h',
     'public/browser/save_page_type.h',
+    'public/browser/service_worker_context.h',
     'public/browser/session_storage_namespace.h',
     'public/browser/session_storage_usage_info.h',
     'public/browser/signed_certificate_timestamp_store.h',
@@ -823,7 +824,6 @@
     'browser/power_monitor_message_broadcaster.cc',
     'browser/power_monitor_message_broadcaster.h',
     'browser/power_profiler/power_data_provider.h',
-    'browser/power_profiler/power_data_provider_dummy.cc',
     'browser/power_profiler/power_event.cc',
     'browser/power_profiler/power_event.h',
     'browser/power_profiler/power_profiler_observer.h',
@@ -1085,8 +1085,10 @@
     'browser/renderer_host/render_message_filter.h',
     'browser/renderer_host/render_process_host_impl.cc',
     'browser/renderer_host/render_process_host_impl.h',
+    'browser/renderer_host/render_process_host_mojo_impl.cc',
+    'browser/renderer_host/render_process_host_mojo_impl.h',
     'browser/renderer_host/render_sandbox_host_linux.cc',
-    'browser/renderer_host/render_sandbox_host_linux.h',
+    'browser/renderer_host/render_process_host_impl.h',
     'browser/renderer_host/render_view_host_delegate.cc',
     'browser/renderer_host/render_view_host_delegate.h',
     'browser/renderer_host/render_view_host_factory.cc',
@@ -1152,7 +1154,6 @@
     'browser/service_worker/embedded_worker_instance.h',
     'browser/service_worker/embedded_worker_registry.cc',
     'browser/service_worker/embedded_worker_registry.h',
-    'browser/service_worker/service_worker_context.h',
     'browser/service_worker/service_worker_context_core.cc',
     'browser/service_worker/service_worker_context_core.h',
     'browser/service_worker/service_worker_context_wrapper.cc',
@@ -1371,6 +1372,19 @@
         '../ui/events/events.gyp:events',
       ],
     }],
+    ['OS == "win"', {
+      'dependencies': [
+        '../third_party/power_gadget/power_gadget.gyp:power_gadget',
+      ],
+      'sources': [
+        'browser/power_profiler/power_data_provider_ia_win.cc',
+        'browser/power_profiler/power_data_provider_ia_win.h',
+      ]
+    }, { # os != "win"
+      'sources': [
+        'browser/power_profiler/power_data_provider_dummy.cc'
+      ]
+    }],
     ['OS!="win" and OS!="mac" and (OS!="linux" or use_udev==0)', {
       'sources': [
         'browser/gamepad/gamepad_platform_data_fetcher.cc',
@@ -1378,7 +1392,14 @@
     }],
     ['use_mojo==1', {
       'dependencies': [
+        '../mojo/mojo.gyp:mojo_bindings',
         '../mojo/mojo.gyp:mojo_system',
+        'content_common_mojo_bindings',
+      ],
+    }, {  # use_mojo==0
+      'sources!': [
+        'browser/renderer_host/render_process_host_mojo_impl.cc',
+        'browser/renderer_host/render_process_host_mojo_impl.h',
       ],
     }],
     ['OS=="ios"', {
@@ -1622,6 +1643,7 @@
     ['chromeos==1', {
       'dependencies': [
         '../build/linux/system.gyp:dbus',
+        '../chromeos/chromeos.gyp:power_manager_proto',
       ],
       'sources!': [
         'browser/geolocation/wifi_data_provider_linux.cc',
diff --git a/content/content_browser.target.darwin-arm.mk b/content/content_browser.target.darwin-arm.mk
index 9928e93..6c62af2 100644
--- a/content/content_browser.target.darwin-arm.mk
+++ b/content/content_browser.target.darwin-arm.mk
@@ -323,7 +323,6 @@
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
 	content/browser/power_monitor_message_broadcaster.cc \
-	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/power_profiler/power_event.cc \
 	content/browser/power_profiler/power_profiler_service.cc \
 	content/browser/power_save_blocker_android.cc \
@@ -482,6 +481,7 @@
 	content/browser/worker_host/worker_process_host.cc \
 	content/browser/worker_host/worker_service_impl.cc \
 	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/gamepad/gamepad_platform_data_fetcher.cc
 
 
@@ -547,9 +547,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -567,6 +565,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -704,9 +703,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -724,6 +721,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_browser.target.darwin-mips.mk b/content/content_browser.target.darwin-mips.mk
index 26a9ad2..c732346 100644
--- a/content/content_browser.target.darwin-mips.mk
+++ b/content/content_browser.target.darwin-mips.mk
@@ -323,7 +323,6 @@
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
 	content/browser/power_monitor_message_broadcaster.cc \
-	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/power_profiler/power_event.cc \
 	content/browser/power_profiler/power_profiler_service.cc \
 	content/browser/power_save_blocker_android.cc \
@@ -482,6 +481,7 @@
 	content/browser/worker_host/worker_process_host.cc \
 	content/browser/worker_host/worker_service_impl.cc \
 	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/gamepad/gamepad_platform_data_fetcher.cc
 
 
@@ -546,9 +546,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -566,6 +564,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -702,9 +701,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -722,6 +719,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_browser.target.darwin-x86.mk b/content/content_browser.target.darwin-x86.mk
index e6aa5b9..e620c7e 100644
--- a/content/content_browser.target.darwin-x86.mk
+++ b/content/content_browser.target.darwin-x86.mk
@@ -323,7 +323,6 @@
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
 	content/browser/power_monitor_message_broadcaster.cc \
-	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/power_profiler/power_event.cc \
 	content/browser/power_profiler/power_profiler_service.cc \
 	content/browser/power_save_blocker_android.cc \
@@ -482,6 +481,7 @@
 	content/browser/worker_host/worker_process_host.cc \
 	content/browser/worker_host/worker_service_impl.cc \
 	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/gamepad/gamepad_platform_data_fetcher.cc
 
 
@@ -547,9 +547,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -567,6 +565,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -703,9 +702,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -723,6 +720,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_browser.target.darwin-x86_64.mk b/content/content_browser.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7412772
--- /dev/null
+++ b/content/content_browser.target.darwin-x86_64.mk
@@ -0,0 +1,865 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
+	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_angle_src_commit_id_gyp)/commit_id.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/devtools_protocol_constants.cc: $(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/devtools_resources_map.cc \
+	$(gyp_intermediate_dir)/webui_resources_map.cc \
+	$(gyp_intermediate_dir)/devtools_protocol_constants.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit \
+	$(gyp_shared_intermediate_dir)/content/browser/devtools
+
+LOCAL_SRC_FILES := \
+	content/public/browser/android/synchronous_compositor.cc \
+	content/public/browser/ax_event_notification_details.cc \
+	content/public/browser/browser_child_process_host_delegate.cc \
+	content/public/browser/browser_child_process_host_iterator.cc \
+	content/public/browser/browser_child_process_observer.cc \
+	content/public/browser/browser_main_parts.cc \
+	content/public/browser/browser_message_filter.cc \
+	content/public/browser/browser_plugin_guest_delegate.cc \
+	content/public/browser/content_browser_client.cc \
+	content/public/browser/desktop_media_id.cc \
+	content/public/browser/download_manager_delegate.cc \
+	content/public/browser/download_save_info.cc \
+	content/public/browser/download_url_parameters.cc \
+	content/public/browser/favicon_status.cc \
+	content/public/browser/indexed_db_info.cc \
+	content/public/browser/javascript_dialog_manager.cc \
+	content/public/browser/load_from_memory_cache_details.cc \
+	content/public/browser/local_storage_usage_info.cc \
+	content/public/browser/media_device_id.cc \
+	content/public/browser/navigation_controller.cc \
+	content/public/browser/navigation_details.cc \
+	content/public/browser/notification_registrar.cc \
+	content/public/browser/page_navigator.cc \
+	content/public/browser/resource_dispatcher_host_delegate.cc \
+	content/public/browser/resource_request_details.cc \
+	content/public/browser/speech_recognition_session_config.cc \
+	content/public/browser/speech_recognition_session_context.cc \
+	content/public/browser/web_contents.cc \
+	content/public/browser/web_contents_delegate.cc \
+	content/public/browser/web_contents_observer.cc \
+	content/public/browser/web_ui_controller.cc \
+	content/public/browser/url_data_source.cc \
+	content/browser/accessibility/accessibility_mode_helper.cc \
+	content/browser/accessibility/accessibility_tree_formatter.cc \
+	content/browser/accessibility/accessibility_tree_formatter_android.cc \
+	content/browser/accessibility/accessibility_ui.cc \
+	content/browser/accessibility/browser_accessibility.cc \
+	content/browser/accessibility/browser_accessibility_android.cc \
+	content/browser/accessibility/browser_accessibility_manager.cc \
+	content/browser/accessibility/browser_accessibility_manager_android.cc \
+	content/browser/accessibility/browser_accessibility_state_impl.cc \
+	content/browser/android/browser_jni_registrar.cc \
+	content/browser/android/browser_startup_controller.cc \
+	content/browser/android/child_process_launcher_android.cc \
+	content/browser/android/content_settings.cc \
+	content/browser/android/content_startup_flags.cc \
+	content/browser/android/content_video_view.cc \
+	content/browser/android/content_view_core_impl.cc \
+	content/browser/android/content_view_render_view.cc \
+	content/browser/android/content_view_statics.cc \
+	content/browser/android/date_time_chooser_android.cc \
+	content/browser/android/download_controller_android_impl.cc \
+	content/browser/android/devtools_auth.cc \
+	content/browser/android/edge_effect.cc \
+	content/browser/android/in_process/synchronous_compositor_factory_impl.cc \
+	content/browser/android/in_process/synchronous_compositor_impl.cc \
+	content/browser/android/in_process/synchronous_compositor_output_surface.cc \
+	content/browser/android/in_process/synchronous_input_event_filter.cc \
+	content/browser/android/interstitial_page_delegate_android.cc \
+	content/browser/android/load_url_params.cc \
+	content/browser/android/overscroll_glow.cc \
+	content/browser/android/surface_texture_peer_browser_impl.cc \
+	content/browser/android/tracing_controller_android.cc \
+	content/browser/android/web_contents_observer_android.cc \
+	content/browser/appcache/appcache_dispatcher_host.cc \
+	content/browser/appcache/appcache_frontend_proxy.cc \
+	content/browser/appcache/chrome_appcache_service.cc \
+	content/browser/appcache/view_appcache_internals_job.cc \
+	content/browser/browser_child_process_host_impl.cc \
+	content/browser/browser_context.cc \
+	content/browser/browser_main.cc \
+	content/browser/browser_main_loop.cc \
+	content/browser/browser_main_runner.cc \
+	content/browser/browser_plugin/browser_plugin_embedder.cc \
+	content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc \
+	content/browser/browser_plugin/browser_plugin_guest.cc \
+	content/browser/browser_plugin/browser_plugin_guest_manager.cc \
+	content/browser/browser_plugin/browser_plugin_message_filter.cc \
+	content/browser/browser_process_sub_thread.cc \
+	content/browser/browser_shutdown_profile_dumper.cc \
+	content/browser/browser_thread_impl.cc \
+	content/browser/browser_url_handler_impl.cc \
+	content/browser/browsing_instance.cc \
+	content/browser/byte_stream.cc \
+	content/browser/cert_store_impl.cc \
+	content/browser/child_process_launcher.cc \
+	content/browser/child_process_security_policy_impl.cc \
+	content/browser/cross_site_request_manager.cc \
+	content/browser/devtools/devtools_agent_host_impl.cc \
+	content/browser/devtools/devtools_browser_target.cc \
+	content/browser/devtools/devtools_external_agent_proxy_impl.cc \
+	content/browser/devtools/devtools_frontend_host.cc \
+	content/browser/devtools/devtools_http_handler_impl.cc \
+	content/browser/devtools/devtools_manager_impl.cc \
+	content/browser/devtools/devtools_netlog_observer.cc \
+	content/browser/devtools/devtools_power_handler.cc \
+	content/browser/devtools/devtools_protocol.cc \
+	content/browser/devtools/devtools_system_info_handler.cc \
+	content/browser/devtools/devtools_tracing_handler.cc \
+	content/browser/devtools/ipc_devtools_agent_host.cc \
+	content/browser/devtools/render_view_devtools_agent_host.cc \
+	content/browser/devtools/renderer_overrides_handler.cc \
+	content/browser/devtools/tethering_handler.cc \
+	content/browser/devtools/worker_devtools_manager.cc \
+	content/browser/devtools/worker_devtools_message_filter.cc \
+	content/browser/device_orientation/data_fetcher_shared_memory_android.cc \
+	content/browser/device_orientation/data_fetcher_shared_memory_base.cc \
+	content/browser/device_orientation/device_inertial_sensor_service.cc \
+	content/browser/device_orientation/device_motion_message_filter.cc \
+	content/browser/device_orientation/device_orientation_message_filter.cc \
+	content/browser/device_orientation/sensor_manager_android.cc \
+	content/browser/dom_storage/dom_storage_area.cc \
+	content/browser/dom_storage/dom_storage_context_impl.cc \
+	content/browser/dom_storage/dom_storage_context_wrapper.cc \
+	content/browser/dom_storage/dom_storage_database.cc \
+	content/browser/dom_storage/dom_storage_host.cc \
+	content/browser/dom_storage/dom_storage_message_filter.cc \
+	content/browser/dom_storage/dom_storage_namespace.cc \
+	content/browser/dom_storage/dom_storage_session.cc \
+	content/browser/dom_storage/dom_storage_task_runner.cc \
+	content/browser/dom_storage/local_storage_database_adapter.cc \
+	content/browser/dom_storage/session_storage_database.cc \
+	content/browser/dom_storage/session_storage_database_adapter.cc \
+	content/browser/dom_storage/session_storage_namespace_impl.cc \
+	content/browser/download/base_file.cc \
+	content/browser/download/base_file_posix.cc \
+	content/browser/download/download_create_info.cc \
+	content/browser/download/download_file_factory.cc \
+	content/browser/download/download_file_impl.cc \
+	content/browser/download/download_interrupt_reasons_impl.cc \
+	content/browser/download/download_item_impl.cc \
+	content/browser/download/download_item_impl_delegate.cc \
+	content/browser/download/download_manager_impl.cc \
+	content/browser/download/download_net_log_parameters.cc \
+	content/browser/download/download_request_handle.cc \
+	content/browser/download/download_resource_handler.cc \
+	content/browser/download/download_stats.cc \
+	content/browser/download/drag_download_file.cc \
+	content/browser/download/drag_download_util.cc \
+	content/browser/download/mhtml_generation_manager.cc \
+	content/browser/download/rate_estimator.cc \
+	content/browser/download/save_file.cc \
+	content/browser/download/save_file_manager.cc \
+	content/browser/download/save_file_resource_handler.cc \
+	content/browser/download/save_item.cc \
+	content/browser/download/save_package.cc \
+	content/browser/download/save_types.cc \
+	content/browser/fileapi/browser_file_system_helper.cc \
+	content/browser/fileapi/chrome_blob_storage_context.cc \
+	content/browser/fileapi/fileapi_message_filter.cc \
+	content/browser/fileapi/upload_file_system_file_element_reader.cc \
+	content/browser/frame_host/debug_urls.cc \
+	content/browser/frame_host/frame_tree.cc \
+	content/browser/frame_host/frame_tree_node.cc \
+	content/browser/frame_host/interstitial_page_impl.cc \
+	content/browser/frame_host/interstitial_page_navigator_impl.cc \
+	content/browser/frame_host/navigation_controller_android.cc \
+	content/browser/frame_host/navigation_controller_impl.cc \
+	content/browser/frame_host/navigation_entry_impl.cc \
+	content/browser/frame_host/navigation_entry_screenshot_manager.cc \
+	content/browser/frame_host/navigator.cc \
+	content/browser/frame_host/navigator_impl.cc \
+	content/browser/frame_host/navigator_delegate.cc \
+	content/browser/frame_host/cross_process_frame_connector.cc \
+	content/browser/frame_host/cross_site_transferring_request.cc \
+	content/browser/frame_host/render_frame_host_delegate.cc \
+	content/browser/frame_host/render_frame_host_factory.cc \
+	content/browser/frame_host/render_frame_host_impl.cc \
+	content/browser/frame_host/render_frame_host_manager.cc \
+	content/browser/frame_host/render_frame_message_filter.cc \
+	content/browser/frame_host/render_widget_host_view_child_frame.cc \
+	content/browser/frame_host/render_widget_host_view_guest.cc \
+	content/browser/gamepad/gamepad_provider.cc \
+	content/browser/gamepad/gamepad_service.cc \
+	content/browser/gamepad/gamepad_standard_mappings.cc \
+	content/browser/geolocation/empty_wifi_data_provider.cc \
+	content/browser/geolocation/geolocation_dispatcher_host.cc \
+	content/browser/geolocation/geolocation_provider_impl.cc \
+	content/browser/geolocation/location_api_adapter_android.cc \
+	content/browser/geolocation/location_arbitrator_impl.cc \
+	content/browser/geolocation/location_provider_android.cc \
+	content/browser/geolocation/location_provider_base.cc \
+	content/browser/geolocation/wifi_data.cc \
+	content/browser/geolocation/wifi_data_provider.cc \
+	content/browser/gpu/browser_gpu_channel_host_factory.cc \
+	content/browser/gpu/compositor_util.cc \
+	content/browser/gpu/gpu_data_manager_impl.cc \
+	content/browser/gpu/gpu_data_manager_impl_private.cc \
+	content/browser/gpu/gpu_internals_ui.cc \
+	content/browser/gpu/gpu_process_host.cc \
+	content/browser/gpu/gpu_process_host_ui_shim.cc \
+	content/browser/gpu/gpu_surface_tracker.cc \
+	content/browser/gpu/shader_disk_cache.cc \
+	content/browser/histogram_controller.cc \
+	content/browser/histogram_internals_request_job.cc \
+	content/browser/histogram_message_filter.cc \
+	content/browser/histogram_synchronizer.cc \
+	content/browser/host_zoom_map_impl.cc \
+	content/browser/indexed_db/indexed_db_backing_store.cc \
+	content/browser/indexed_db/indexed_db_blob_info.cc \
+	content/browser/indexed_db/indexed_db_callbacks.cc \
+	content/browser/indexed_db/indexed_db_connection.cc \
+	content/browser/indexed_db/indexed_db_context_impl.cc \
+	content/browser/indexed_db/indexed_db_cursor.cc \
+	content/browser/indexed_db/indexed_db_database.cc \
+	content/browser/indexed_db/indexed_db_database_callbacks.cc \
+	content/browser/indexed_db/indexed_db_dispatcher_host.cc \
+	content/browser/indexed_db/indexed_db_factory.cc \
+	content/browser/indexed_db/indexed_db_index_writer.cc \
+	content/browser/indexed_db/indexed_db_internals_ui.cc \
+	content/browser/indexed_db/indexed_db_leveldb_coding.cc \
+	content/browser/indexed_db/indexed_db_metadata.cc \
+	content/browser/indexed_db/indexed_db_pending_connection.cc \
+	content/browser/indexed_db/indexed_db_quota_client.cc \
+	content/browser/indexed_db/indexed_db_transaction.cc \
+	content/browser/indexed_db/indexed_db_transaction_coordinator.cc \
+	content/browser/indexed_db/indexed_db_value.cc \
+	content/browser/indexed_db/leveldb/leveldb_database.cc \
+	content/browser/indexed_db/leveldb/leveldb_transaction.cc \
+	content/browser/indexed_db/leveldb/leveldb_write_batch.cc \
+	content/browser/loader/async_resource_handler.cc \
+	content/browser/loader/buffered_resource_handler.cc \
+	content/browser/loader/certificate_resource_handler.cc \
+	content/browser/loader/cross_site_resource_handler.cc \
+	content/browser/loader/detachable_resource_handler.cc \
+	content/browser/loader/layered_resource_handler.cc \
+	content/browser/loader/offline_policy.cc \
+	content/browser/loader/power_save_block_resource_throttle.cc \
+	content/browser/loader/redirect_to_file_resource_handler.cc \
+	content/browser/loader/resource_buffer.cc \
+	content/browser/loader/resource_dispatcher_host_impl.cc \
+	content/browser/loader/resource_handler.cc \
+	content/browser/loader/resource_loader.cc \
+	content/browser/loader/resource_message_delegate.cc \
+	content/browser/loader/resource_message_filter.cc \
+	content/browser/loader/resource_request_info_impl.cc \
+	content/browser/loader/resource_scheduler.cc \
+	content/browser/loader/resource_scheduler_filter.cc \
+	content/browser/loader/stream_resource_handler.cc \
+	content/browser/loader/sync_resource_handler.cc \
+	content/browser/loader/temporary_file_stream.cc \
+	content/browser/loader/throttling_resource_handler.cc \
+	content/browser/loader/upload_data_stream_builder.cc \
+	content/browser/media/android/browser_demuxer_android.cc \
+	content/browser/media/android/browser_media_player_manager.cc \
+	content/browser/media/android/media_drm_credential_manager.cc \
+	content/browser/media/android/media_resource_getter_impl.cc \
+	content/browser/media/capture/audio_mirroring_manager.cc \
+	content/browser/media/capture/content_video_capture_device_core.cc \
+	content/browser/media/capture/video_capture_oracle.cc \
+	content/browser/media/capture/web_contents_audio_input_stream.cc \
+	content/browser/media/capture/web_contents_capture_util.cc \
+	content/browser/media/capture/web_contents_tracker.cc \
+	content/browser/media/capture/web_contents_video_capture_device.cc \
+	content/browser/media/media_internals.cc \
+	content/browser/media/media_internals_handler.cc \
+	content/browser/media/media_internals_proxy.cc \
+	content/browser/media/media_internals_ui.cc \
+	content/browser/media/webrtc_identity_store.cc \
+	content/browser/media/webrtc_identity_store_backend.cc \
+	content/browser/media/webrtc_internals.cc \
+	content/browser/media/webrtc_internals_message_handler.cc \
+	content/browser/media/webrtc_internals_ui.cc \
+	content/browser/message_port_message_filter.cc \
+	content/browser/message_port_service.cc \
+	content/browser/mime_registry_message_filter.cc \
+	content/browser/net/browser_online_state_observer.cc \
+	content/browser/net/sqlite_persistent_cookie_store.cc \
+	content/browser/net/view_blob_internals_job_factory.cc \
+	content/browser/net/view_http_cache_job_factory.cc \
+	content/browser/notification_service_impl.cc \
+	content/browser/power_monitor_message_broadcaster.cc \
+	content/browser/power_profiler/power_event.cc \
+	content/browser/power_profiler/power_profiler_service.cc \
+	content/browser/power_save_blocker_android.cc \
+	content/browser/power_save_blocker_impl.cc \
+	content/browser/profiler_controller_impl.cc \
+	content/browser/profiler_message_filter.cc \
+	content/browser/quota_dispatcher_host.cc \
+	content/browser/renderer_host/backing_store.cc \
+	content/browser/renderer_host/backing_store_manager.cc \
+	content/browser/renderer_host/clipboard_message_filter.cc \
+	content/browser/renderer_host/compositor_impl_android.cc \
+	content/browser/renderer_host/database_message_filter.cc \
+	content/browser/renderer_host/delegated_frame_evictor.cc \
+	content/browser/renderer_host/dip_util.cc \
+	content/browser/renderer_host/file_utilities_message_filter.cc \
+	content/browser/renderer_host/gamepad_browser_message_filter.cc \
+	content/browser/renderer_host/gpu_message_filter.cc \
+	content/browser/renderer_host/image_transport_factory_android.cc \
+	content/browser/renderer_host/ime_adapter_android.cc \
+	content/browser/renderer_host/input/gesture_event_queue.cc \
+	content/browser/renderer_host/input/input_router_impl.cc \
+	content/browser/renderer_host/input/motion_event_android.cc \
+	content/browser/renderer_host/input/motion_event_web.cc \
+	content/browser/renderer_host/input/synthetic_gesture.cc \
+	content/browser/renderer_host/input/synthetic_gesture_controller.cc \
+	content/browser/renderer_host/input/synthetic_gesture_target_android.cc \
+	content/browser/renderer_host/input/synthetic_gesture_target_base.cc \
+	content/browser/renderer_host/input/synthetic_pinch_gesture.cc \
+	content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc \
+	content/browser/renderer_host/input/synthetic_tap_gesture.cc \
+	content/browser/renderer_host/input/tap_suppression_controller.cc \
+	content/browser/renderer_host/input/timeout_monitor.cc \
+	content/browser/renderer_host/input/touch_event_queue.cc \
+	content/browser/renderer_host/input/touch_action_filter.cc \
+	content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc \
+	content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc \
+	content/browser/renderer_host/input/web_input_event_builders_android.cc \
+	content/browser/renderer_host/input/web_input_event_util.cc \
+	content/browser/renderer_host/input/web_input_event_util_posix.cc \
+	content/browser/renderer_host/input/web_touch_event_traits.cc \
+	content/browser/renderer_host/java/java_bound_object.cc \
+	content/browser/renderer_host/java/java_bridge_channel_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc \
+	content/browser/renderer_host/java/java_method.cc \
+	content/browser/renderer_host/java/java_type.cc \
+	content/browser/renderer_host/java/jni_helper.cc \
+	content/browser/renderer_host/media/audio_input_device_manager.cc \
+	content/browser/renderer_host/media/audio_input_renderer_host.cc \
+	content/browser/renderer_host/media/audio_input_sync_writer.cc \
+	content/browser/renderer_host/media/audio_renderer_host.cc \
+	content/browser/renderer_host/media/audio_sync_reader.cc \
+	content/browser/renderer_host/media/device_request_message_filter.cc \
+	content/browser/renderer_host/media/media_capture_devices_impl.cc \
+	content/browser/renderer_host/media/media_stream_dispatcher_host.cc \
+	content/browser/renderer_host/media/media_stream_manager.cc \
+	content/browser/renderer_host/media/media_stream_track_metrics_host.cc \
+	content/browser/renderer_host/media/media_stream_ui_proxy.cc \
+	content/browser/renderer_host/media/midi_dispatcher_host.cc \
+	content/browser/renderer_host/media/midi_host.cc \
+	content/browser/renderer_host/media/video_capture_buffer_pool.cc \
+	content/browser/renderer_host/media/video_capture_controller.cc \
+	content/browser/renderer_host/media/video_capture_controller_event_handler.cc \
+	content/browser/renderer_host/media/video_capture_host.cc \
+	content/browser/renderer_host/media/video_capture_manager.cc \
+	content/browser/renderer_host/memory_benchmark_message_filter.cc \
+	content/browser/renderer_host/native_web_keyboard_event_android.cc \
+	content/browser/renderer_host/overscroll_configuration.cc \
+	content/browser/renderer_host/overscroll_controller.cc \
+	content/browser/renderer_host/render_message_filter.cc \
+	content/browser/renderer_host/render_process_host_impl.cc \
+	content/browser/renderer_host/render_view_host_delegate.cc \
+	content/browser/renderer_host/render_view_host_factory.cc \
+	content/browser/renderer_host/render_view_host_impl.cc \
+	content/browser/renderer_host/render_widget_helper.cc \
+	content/browser/renderer_host/render_widget_host_delegate.cc \
+	content/browser/renderer_host/render_widget_host_impl.cc \
+	content/browser/renderer_host/render_widget_host_view_android.cc \
+	content/browser/renderer_host/render_widget_host_view_base.cc \
+	content/browser/renderer_host/renderer_frame_manager.cc \
+	content/browser/renderer_host/software_frame_manager.cc \
+	content/browser/renderer_host/socket_stream_dispatcher_host.cc \
+	content/browser/renderer_host/socket_stream_host.cc \
+	content/browser/renderer_host/websocket_dispatcher_host.cc \
+	content/browser/renderer_host/websocket_host.cc \
+	content/browser/resolve_proxy_msg_helper.cc \
+	content/browser/resource_context_impl.cc \
+	content/browser/screen_orientation/screen_orientation_dispatcher_host.cc \
+	content/browser/screen_orientation/screen_orientation_provider_android.cc \
+	content/browser/service_worker/embedded_worker_instance.cc \
+	content/browser/service_worker/embedded_worker_registry.cc \
+	content/browser/service_worker/service_worker_context_core.cc \
+	content/browser/service_worker/service_worker_context_wrapper.cc \
+	content/browser/service_worker/service_worker_dispatcher_host.cc \
+	content/browser/service_worker/service_worker_info.cc \
+	content/browser/service_worker/service_worker_internals_ui.cc \
+	content/browser/service_worker/service_worker_job_coordinator.cc \
+	content/browser/service_worker/service_worker_provider_host.cc \
+	content/browser/service_worker/service_worker_fetch_dispatcher.cc \
+	content/browser/service_worker/service_worker_register_job.cc \
+	content/browser/service_worker/service_worker_registration.cc \
+	content/browser/service_worker/service_worker_registration_status.cc \
+	content/browser/service_worker/service_worker_request_handler.cc \
+	content/browser/service_worker/service_worker_storage.cc \
+	content/browser/service_worker/service_worker_url_request_job.cc \
+	content/browser/service_worker/service_worker_utils.cc \
+	content/browser/service_worker/service_worker_version.cc \
+	content/browser/shared_worker/shared_worker_host.cc \
+	content/browser/shared_worker/shared_worker_instance.cc \
+	content/browser/shared_worker/shared_worker_message_filter.cc \
+	content/browser/shared_worker/shared_worker_service_impl.cc \
+	content/browser/signed_certificate_timestamp_store_impl.cc \
+	content/browser/site_instance_impl.cc \
+	content/browser/speech/speech_recognition_dispatcher_host.cc \
+	content/browser/speech/speech_recognition_manager_impl.cc \
+	content/browser/speech/speech_recognizer_impl_android.cc \
+	content/browser/ssl/ssl_cert_error_handler.cc \
+	content/browser/ssl/ssl_client_auth_handler.cc \
+	content/browser/ssl/ssl_error_handler.cc \
+	content/browser/ssl/ssl_host_state.cc \
+	content/browser/ssl/ssl_manager.cc \
+	content/browser/ssl/ssl_policy_backend.cc \
+	content/browser/ssl/ssl_policy.cc \
+	content/browser/ssl/ssl_request_info.cc \
+	content/browser/startup_task_runner.cc \
+	content/browser/streams/stream.cc \
+	content/browser/streams/stream_context.cc \
+	content/browser/streams/stream_handle_impl.cc \
+	content/browser/streams/stream_registry.cc \
+	content/browser/streams/stream_url_request_job.cc \
+	content/browser/storage_partition_impl.cc \
+	content/browser/storage_partition_impl_map.cc \
+	content/browser/tcmalloc_internals_request_job.cc \
+	content/browser/tracing/trace_message_filter.cc \
+	content/browser/tracing/tracing_controller_impl.cc \
+	content/browser/user_metrics.cc \
+	content/browser/utility_process_host_impl.cc \
+	content/browser/vibration/vibration_message_filter.cc \
+	content/browser/vibration/vibration_provider_android.cc \
+	content/browser/web_contents/web_contents_android.cc \
+	content/browser/web_contents/web_contents_impl.cc \
+	content/browser/web_contents/web_contents_view_android.cc \
+	content/browser/web_contents/web_contents_view_guest.cc \
+	content/browser/webui/content_web_ui_controller_factory.cc \
+	content/browser/webui/generic_handler.cc \
+	content/browser/webui/shared_resources_data_source.cc \
+	content/browser/webui/url_data_manager.cc \
+	content/browser/webui/url_data_manager_backend.cc \
+	content/browser/webui/url_data_source_impl.cc \
+	content/browser/webui/web_ui_data_source_impl.cc \
+	content/browser/webui/web_ui_controller_factory_registry.cc \
+	content/browser/webui/web_ui_impl.cc \
+	content/browser/webui/web_ui_message_handler.cc \
+	content/browser/worker_host/worker_document_set.cc \
+	content/browser/worker_host/worker_message_filter.cc \
+	content/browser/worker_host/worker_process_host.cc \
+	content/browser/worker_host/worker_service_impl.cc \
+	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
+	content/browser/gamepad/gamepad_platform_data_fetcher.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DAVOID_LIBYUV_FOR_ANDROID_WEBVIEW' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DAVOID_LIBYUV_FOR_ANDROID_WEBVIEW' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	ui_base_ui_base_gyp \
+	content_browser_speech_proto_speech_proto_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_browser_gyp
+
+# Alias gyp target name.
+.PHONY: content_browser
+content_browser: content_content_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_browser.target.linux-arm.mk b/content/content_browser.target.linux-arm.mk
index 9928e93..6c62af2 100644
--- a/content/content_browser.target.linux-arm.mk
+++ b/content/content_browser.target.linux-arm.mk
@@ -323,7 +323,6 @@
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
 	content/browser/power_monitor_message_broadcaster.cc \
-	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/power_profiler/power_event.cc \
 	content/browser/power_profiler/power_profiler_service.cc \
 	content/browser/power_save_blocker_android.cc \
@@ -482,6 +481,7 @@
 	content/browser/worker_host/worker_process_host.cc \
 	content/browser/worker_host/worker_service_impl.cc \
 	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/gamepad/gamepad_platform_data_fetcher.cc
 
 
@@ -547,9 +547,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -567,6 +565,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -704,9 +703,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -724,6 +721,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_browser.target.linux-mips.mk b/content/content_browser.target.linux-mips.mk
index 26a9ad2..c732346 100644
--- a/content/content_browser.target.linux-mips.mk
+++ b/content/content_browser.target.linux-mips.mk
@@ -323,7 +323,6 @@
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
 	content/browser/power_monitor_message_broadcaster.cc \
-	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/power_profiler/power_event.cc \
 	content/browser/power_profiler/power_profiler_service.cc \
 	content/browser/power_save_blocker_android.cc \
@@ -482,6 +481,7 @@
 	content/browser/worker_host/worker_process_host.cc \
 	content/browser/worker_host/worker_service_impl.cc \
 	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/gamepad/gamepad_platform_data_fetcher.cc
 
 
@@ -546,9 +546,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -566,6 +564,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -702,9 +701,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -722,6 +719,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_browser.target.linux-x86.mk b/content/content_browser.target.linux-x86.mk
index e6aa5b9..e620c7e 100644
--- a/content/content_browser.target.linux-x86.mk
+++ b/content/content_browser.target.linux-x86.mk
@@ -323,7 +323,6 @@
 	content/browser/net/view_http_cache_job_factory.cc \
 	content/browser/notification_service_impl.cc \
 	content/browser/power_monitor_message_broadcaster.cc \
-	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/power_profiler/power_event.cc \
 	content/browser/power_profiler/power_profiler_service.cc \
 	content/browser/power_save_blocker_android.cc \
@@ -482,6 +481,7 @@
 	content/browser/worker_host/worker_process_host.cc \
 	content/browser/worker_host/worker_service_impl.cc \
 	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
 	content/browser/gamepad/gamepad_platform_data_fetcher.cc
 
 
@@ -547,9 +547,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -567,6 +565,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -703,9 +702,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -723,6 +720,7 @@
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DMEDIA_DISABLE_LIBVPX' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_browser.target.linux-x86_64.mk b/content/content_browser.target.linux-x86_64.mk
new file mode 100644
index 0000000..7412772
--- /dev/null
+++ b/content/content_browser.target.linux-x86_64.mk
@@ -0,0 +1,865 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,content_browser_speech_proto_speech_proto_gyp)/content_browser_speech_proto_speech_proto_gyp.a \
+	$(call intermediates-dir-for,GYP,content_browser_devtools_devtools_resources_gyp)/devtools_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_strings_gyp)/webkit_strings.stamp \
+	$(call intermediates-dir-for,GYP,third_party_angle_src_commit_id_gyp)/commit_id.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_gyp)/sandbox.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/devtools_resources_map.cc: $(gyp_shared_intermediate_dir)/webkit/grit/devtools_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/devtools_protocol_constants.cc: $(gyp_shared_intermediate_dir)/content/browser/devtools/devtools_protocol_constants.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/devtools_resources_map.cc \
+	$(gyp_intermediate_dir)/webui_resources_map.cc \
+	$(gyp_intermediate_dir)/devtools_protocol_constants.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit \
+	$(gyp_shared_intermediate_dir)/content/browser/devtools
+
+LOCAL_SRC_FILES := \
+	content/public/browser/android/synchronous_compositor.cc \
+	content/public/browser/ax_event_notification_details.cc \
+	content/public/browser/browser_child_process_host_delegate.cc \
+	content/public/browser/browser_child_process_host_iterator.cc \
+	content/public/browser/browser_child_process_observer.cc \
+	content/public/browser/browser_main_parts.cc \
+	content/public/browser/browser_message_filter.cc \
+	content/public/browser/browser_plugin_guest_delegate.cc \
+	content/public/browser/content_browser_client.cc \
+	content/public/browser/desktop_media_id.cc \
+	content/public/browser/download_manager_delegate.cc \
+	content/public/browser/download_save_info.cc \
+	content/public/browser/download_url_parameters.cc \
+	content/public/browser/favicon_status.cc \
+	content/public/browser/indexed_db_info.cc \
+	content/public/browser/javascript_dialog_manager.cc \
+	content/public/browser/load_from_memory_cache_details.cc \
+	content/public/browser/local_storage_usage_info.cc \
+	content/public/browser/media_device_id.cc \
+	content/public/browser/navigation_controller.cc \
+	content/public/browser/navigation_details.cc \
+	content/public/browser/notification_registrar.cc \
+	content/public/browser/page_navigator.cc \
+	content/public/browser/resource_dispatcher_host_delegate.cc \
+	content/public/browser/resource_request_details.cc \
+	content/public/browser/speech_recognition_session_config.cc \
+	content/public/browser/speech_recognition_session_context.cc \
+	content/public/browser/web_contents.cc \
+	content/public/browser/web_contents_delegate.cc \
+	content/public/browser/web_contents_observer.cc \
+	content/public/browser/web_ui_controller.cc \
+	content/public/browser/url_data_source.cc \
+	content/browser/accessibility/accessibility_mode_helper.cc \
+	content/browser/accessibility/accessibility_tree_formatter.cc \
+	content/browser/accessibility/accessibility_tree_formatter_android.cc \
+	content/browser/accessibility/accessibility_ui.cc \
+	content/browser/accessibility/browser_accessibility.cc \
+	content/browser/accessibility/browser_accessibility_android.cc \
+	content/browser/accessibility/browser_accessibility_manager.cc \
+	content/browser/accessibility/browser_accessibility_manager_android.cc \
+	content/browser/accessibility/browser_accessibility_state_impl.cc \
+	content/browser/android/browser_jni_registrar.cc \
+	content/browser/android/browser_startup_controller.cc \
+	content/browser/android/child_process_launcher_android.cc \
+	content/browser/android/content_settings.cc \
+	content/browser/android/content_startup_flags.cc \
+	content/browser/android/content_video_view.cc \
+	content/browser/android/content_view_core_impl.cc \
+	content/browser/android/content_view_render_view.cc \
+	content/browser/android/content_view_statics.cc \
+	content/browser/android/date_time_chooser_android.cc \
+	content/browser/android/download_controller_android_impl.cc \
+	content/browser/android/devtools_auth.cc \
+	content/browser/android/edge_effect.cc \
+	content/browser/android/in_process/synchronous_compositor_factory_impl.cc \
+	content/browser/android/in_process/synchronous_compositor_impl.cc \
+	content/browser/android/in_process/synchronous_compositor_output_surface.cc \
+	content/browser/android/in_process/synchronous_input_event_filter.cc \
+	content/browser/android/interstitial_page_delegate_android.cc \
+	content/browser/android/load_url_params.cc \
+	content/browser/android/overscroll_glow.cc \
+	content/browser/android/surface_texture_peer_browser_impl.cc \
+	content/browser/android/tracing_controller_android.cc \
+	content/browser/android/web_contents_observer_android.cc \
+	content/browser/appcache/appcache_dispatcher_host.cc \
+	content/browser/appcache/appcache_frontend_proxy.cc \
+	content/browser/appcache/chrome_appcache_service.cc \
+	content/browser/appcache/view_appcache_internals_job.cc \
+	content/browser/browser_child_process_host_impl.cc \
+	content/browser/browser_context.cc \
+	content/browser/browser_main.cc \
+	content/browser/browser_main_loop.cc \
+	content/browser/browser_main_runner.cc \
+	content/browser/browser_plugin/browser_plugin_embedder.cc \
+	content/browser/browser_plugin/browser_plugin_geolocation_permission_context.cc \
+	content/browser/browser_plugin/browser_plugin_guest.cc \
+	content/browser/browser_plugin/browser_plugin_guest_manager.cc \
+	content/browser/browser_plugin/browser_plugin_message_filter.cc \
+	content/browser/browser_process_sub_thread.cc \
+	content/browser/browser_shutdown_profile_dumper.cc \
+	content/browser/browser_thread_impl.cc \
+	content/browser/browser_url_handler_impl.cc \
+	content/browser/browsing_instance.cc \
+	content/browser/byte_stream.cc \
+	content/browser/cert_store_impl.cc \
+	content/browser/child_process_launcher.cc \
+	content/browser/child_process_security_policy_impl.cc \
+	content/browser/cross_site_request_manager.cc \
+	content/browser/devtools/devtools_agent_host_impl.cc \
+	content/browser/devtools/devtools_browser_target.cc \
+	content/browser/devtools/devtools_external_agent_proxy_impl.cc \
+	content/browser/devtools/devtools_frontend_host.cc \
+	content/browser/devtools/devtools_http_handler_impl.cc \
+	content/browser/devtools/devtools_manager_impl.cc \
+	content/browser/devtools/devtools_netlog_observer.cc \
+	content/browser/devtools/devtools_power_handler.cc \
+	content/browser/devtools/devtools_protocol.cc \
+	content/browser/devtools/devtools_system_info_handler.cc \
+	content/browser/devtools/devtools_tracing_handler.cc \
+	content/browser/devtools/ipc_devtools_agent_host.cc \
+	content/browser/devtools/render_view_devtools_agent_host.cc \
+	content/browser/devtools/renderer_overrides_handler.cc \
+	content/browser/devtools/tethering_handler.cc \
+	content/browser/devtools/worker_devtools_manager.cc \
+	content/browser/devtools/worker_devtools_message_filter.cc \
+	content/browser/device_orientation/data_fetcher_shared_memory_android.cc \
+	content/browser/device_orientation/data_fetcher_shared_memory_base.cc \
+	content/browser/device_orientation/device_inertial_sensor_service.cc \
+	content/browser/device_orientation/device_motion_message_filter.cc \
+	content/browser/device_orientation/device_orientation_message_filter.cc \
+	content/browser/device_orientation/sensor_manager_android.cc \
+	content/browser/dom_storage/dom_storage_area.cc \
+	content/browser/dom_storage/dom_storage_context_impl.cc \
+	content/browser/dom_storage/dom_storage_context_wrapper.cc \
+	content/browser/dom_storage/dom_storage_database.cc \
+	content/browser/dom_storage/dom_storage_host.cc \
+	content/browser/dom_storage/dom_storage_message_filter.cc \
+	content/browser/dom_storage/dom_storage_namespace.cc \
+	content/browser/dom_storage/dom_storage_session.cc \
+	content/browser/dom_storage/dom_storage_task_runner.cc \
+	content/browser/dom_storage/local_storage_database_adapter.cc \
+	content/browser/dom_storage/session_storage_database.cc \
+	content/browser/dom_storage/session_storage_database_adapter.cc \
+	content/browser/dom_storage/session_storage_namespace_impl.cc \
+	content/browser/download/base_file.cc \
+	content/browser/download/base_file_posix.cc \
+	content/browser/download/download_create_info.cc \
+	content/browser/download/download_file_factory.cc \
+	content/browser/download/download_file_impl.cc \
+	content/browser/download/download_interrupt_reasons_impl.cc \
+	content/browser/download/download_item_impl.cc \
+	content/browser/download/download_item_impl_delegate.cc \
+	content/browser/download/download_manager_impl.cc \
+	content/browser/download/download_net_log_parameters.cc \
+	content/browser/download/download_request_handle.cc \
+	content/browser/download/download_resource_handler.cc \
+	content/browser/download/download_stats.cc \
+	content/browser/download/drag_download_file.cc \
+	content/browser/download/drag_download_util.cc \
+	content/browser/download/mhtml_generation_manager.cc \
+	content/browser/download/rate_estimator.cc \
+	content/browser/download/save_file.cc \
+	content/browser/download/save_file_manager.cc \
+	content/browser/download/save_file_resource_handler.cc \
+	content/browser/download/save_item.cc \
+	content/browser/download/save_package.cc \
+	content/browser/download/save_types.cc \
+	content/browser/fileapi/browser_file_system_helper.cc \
+	content/browser/fileapi/chrome_blob_storage_context.cc \
+	content/browser/fileapi/fileapi_message_filter.cc \
+	content/browser/fileapi/upload_file_system_file_element_reader.cc \
+	content/browser/frame_host/debug_urls.cc \
+	content/browser/frame_host/frame_tree.cc \
+	content/browser/frame_host/frame_tree_node.cc \
+	content/browser/frame_host/interstitial_page_impl.cc \
+	content/browser/frame_host/interstitial_page_navigator_impl.cc \
+	content/browser/frame_host/navigation_controller_android.cc \
+	content/browser/frame_host/navigation_controller_impl.cc \
+	content/browser/frame_host/navigation_entry_impl.cc \
+	content/browser/frame_host/navigation_entry_screenshot_manager.cc \
+	content/browser/frame_host/navigator.cc \
+	content/browser/frame_host/navigator_impl.cc \
+	content/browser/frame_host/navigator_delegate.cc \
+	content/browser/frame_host/cross_process_frame_connector.cc \
+	content/browser/frame_host/cross_site_transferring_request.cc \
+	content/browser/frame_host/render_frame_host_delegate.cc \
+	content/browser/frame_host/render_frame_host_factory.cc \
+	content/browser/frame_host/render_frame_host_impl.cc \
+	content/browser/frame_host/render_frame_host_manager.cc \
+	content/browser/frame_host/render_frame_message_filter.cc \
+	content/browser/frame_host/render_widget_host_view_child_frame.cc \
+	content/browser/frame_host/render_widget_host_view_guest.cc \
+	content/browser/gamepad/gamepad_provider.cc \
+	content/browser/gamepad/gamepad_service.cc \
+	content/browser/gamepad/gamepad_standard_mappings.cc \
+	content/browser/geolocation/empty_wifi_data_provider.cc \
+	content/browser/geolocation/geolocation_dispatcher_host.cc \
+	content/browser/geolocation/geolocation_provider_impl.cc \
+	content/browser/geolocation/location_api_adapter_android.cc \
+	content/browser/geolocation/location_arbitrator_impl.cc \
+	content/browser/geolocation/location_provider_android.cc \
+	content/browser/geolocation/location_provider_base.cc \
+	content/browser/geolocation/wifi_data.cc \
+	content/browser/geolocation/wifi_data_provider.cc \
+	content/browser/gpu/browser_gpu_channel_host_factory.cc \
+	content/browser/gpu/compositor_util.cc \
+	content/browser/gpu/gpu_data_manager_impl.cc \
+	content/browser/gpu/gpu_data_manager_impl_private.cc \
+	content/browser/gpu/gpu_internals_ui.cc \
+	content/browser/gpu/gpu_process_host.cc \
+	content/browser/gpu/gpu_process_host_ui_shim.cc \
+	content/browser/gpu/gpu_surface_tracker.cc \
+	content/browser/gpu/shader_disk_cache.cc \
+	content/browser/histogram_controller.cc \
+	content/browser/histogram_internals_request_job.cc \
+	content/browser/histogram_message_filter.cc \
+	content/browser/histogram_synchronizer.cc \
+	content/browser/host_zoom_map_impl.cc \
+	content/browser/indexed_db/indexed_db_backing_store.cc \
+	content/browser/indexed_db/indexed_db_blob_info.cc \
+	content/browser/indexed_db/indexed_db_callbacks.cc \
+	content/browser/indexed_db/indexed_db_connection.cc \
+	content/browser/indexed_db/indexed_db_context_impl.cc \
+	content/browser/indexed_db/indexed_db_cursor.cc \
+	content/browser/indexed_db/indexed_db_database.cc \
+	content/browser/indexed_db/indexed_db_database_callbacks.cc \
+	content/browser/indexed_db/indexed_db_dispatcher_host.cc \
+	content/browser/indexed_db/indexed_db_factory.cc \
+	content/browser/indexed_db/indexed_db_index_writer.cc \
+	content/browser/indexed_db/indexed_db_internals_ui.cc \
+	content/browser/indexed_db/indexed_db_leveldb_coding.cc \
+	content/browser/indexed_db/indexed_db_metadata.cc \
+	content/browser/indexed_db/indexed_db_pending_connection.cc \
+	content/browser/indexed_db/indexed_db_quota_client.cc \
+	content/browser/indexed_db/indexed_db_transaction.cc \
+	content/browser/indexed_db/indexed_db_transaction_coordinator.cc \
+	content/browser/indexed_db/indexed_db_value.cc \
+	content/browser/indexed_db/leveldb/leveldb_database.cc \
+	content/browser/indexed_db/leveldb/leveldb_transaction.cc \
+	content/browser/indexed_db/leveldb/leveldb_write_batch.cc \
+	content/browser/loader/async_resource_handler.cc \
+	content/browser/loader/buffered_resource_handler.cc \
+	content/browser/loader/certificate_resource_handler.cc \
+	content/browser/loader/cross_site_resource_handler.cc \
+	content/browser/loader/detachable_resource_handler.cc \
+	content/browser/loader/layered_resource_handler.cc \
+	content/browser/loader/offline_policy.cc \
+	content/browser/loader/power_save_block_resource_throttle.cc \
+	content/browser/loader/redirect_to_file_resource_handler.cc \
+	content/browser/loader/resource_buffer.cc \
+	content/browser/loader/resource_dispatcher_host_impl.cc \
+	content/browser/loader/resource_handler.cc \
+	content/browser/loader/resource_loader.cc \
+	content/browser/loader/resource_message_delegate.cc \
+	content/browser/loader/resource_message_filter.cc \
+	content/browser/loader/resource_request_info_impl.cc \
+	content/browser/loader/resource_scheduler.cc \
+	content/browser/loader/resource_scheduler_filter.cc \
+	content/browser/loader/stream_resource_handler.cc \
+	content/browser/loader/sync_resource_handler.cc \
+	content/browser/loader/temporary_file_stream.cc \
+	content/browser/loader/throttling_resource_handler.cc \
+	content/browser/loader/upload_data_stream_builder.cc \
+	content/browser/media/android/browser_demuxer_android.cc \
+	content/browser/media/android/browser_media_player_manager.cc \
+	content/browser/media/android/media_drm_credential_manager.cc \
+	content/browser/media/android/media_resource_getter_impl.cc \
+	content/browser/media/capture/audio_mirroring_manager.cc \
+	content/browser/media/capture/content_video_capture_device_core.cc \
+	content/browser/media/capture/video_capture_oracle.cc \
+	content/browser/media/capture/web_contents_audio_input_stream.cc \
+	content/browser/media/capture/web_contents_capture_util.cc \
+	content/browser/media/capture/web_contents_tracker.cc \
+	content/browser/media/capture/web_contents_video_capture_device.cc \
+	content/browser/media/media_internals.cc \
+	content/browser/media/media_internals_handler.cc \
+	content/browser/media/media_internals_proxy.cc \
+	content/browser/media/media_internals_ui.cc \
+	content/browser/media/webrtc_identity_store.cc \
+	content/browser/media/webrtc_identity_store_backend.cc \
+	content/browser/media/webrtc_internals.cc \
+	content/browser/media/webrtc_internals_message_handler.cc \
+	content/browser/media/webrtc_internals_ui.cc \
+	content/browser/message_port_message_filter.cc \
+	content/browser/message_port_service.cc \
+	content/browser/mime_registry_message_filter.cc \
+	content/browser/net/browser_online_state_observer.cc \
+	content/browser/net/sqlite_persistent_cookie_store.cc \
+	content/browser/net/view_blob_internals_job_factory.cc \
+	content/browser/net/view_http_cache_job_factory.cc \
+	content/browser/notification_service_impl.cc \
+	content/browser/power_monitor_message_broadcaster.cc \
+	content/browser/power_profiler/power_event.cc \
+	content/browser/power_profiler/power_profiler_service.cc \
+	content/browser/power_save_blocker_android.cc \
+	content/browser/power_save_blocker_impl.cc \
+	content/browser/profiler_controller_impl.cc \
+	content/browser/profiler_message_filter.cc \
+	content/browser/quota_dispatcher_host.cc \
+	content/browser/renderer_host/backing_store.cc \
+	content/browser/renderer_host/backing_store_manager.cc \
+	content/browser/renderer_host/clipboard_message_filter.cc \
+	content/browser/renderer_host/compositor_impl_android.cc \
+	content/browser/renderer_host/database_message_filter.cc \
+	content/browser/renderer_host/delegated_frame_evictor.cc \
+	content/browser/renderer_host/dip_util.cc \
+	content/browser/renderer_host/file_utilities_message_filter.cc \
+	content/browser/renderer_host/gamepad_browser_message_filter.cc \
+	content/browser/renderer_host/gpu_message_filter.cc \
+	content/browser/renderer_host/image_transport_factory_android.cc \
+	content/browser/renderer_host/ime_adapter_android.cc \
+	content/browser/renderer_host/input/gesture_event_queue.cc \
+	content/browser/renderer_host/input/input_router_impl.cc \
+	content/browser/renderer_host/input/motion_event_android.cc \
+	content/browser/renderer_host/input/motion_event_web.cc \
+	content/browser/renderer_host/input/synthetic_gesture.cc \
+	content/browser/renderer_host/input/synthetic_gesture_controller.cc \
+	content/browser/renderer_host/input/synthetic_gesture_target_android.cc \
+	content/browser/renderer_host/input/synthetic_gesture_target_base.cc \
+	content/browser/renderer_host/input/synthetic_pinch_gesture.cc \
+	content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.cc \
+	content/browser/renderer_host/input/synthetic_tap_gesture.cc \
+	content/browser/renderer_host/input/tap_suppression_controller.cc \
+	content/browser/renderer_host/input/timeout_monitor.cc \
+	content/browser/renderer_host/input/touch_event_queue.cc \
+	content/browser/renderer_host/input/touch_action_filter.cc \
+	content/browser/renderer_host/input/touchpad_tap_suppression_controller.cc \
+	content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc \
+	content/browser/renderer_host/input/web_input_event_builders_android.cc \
+	content/browser/renderer_host/input/web_input_event_util.cc \
+	content/browser/renderer_host/input/web_input_event_util_posix.cc \
+	content/browser/renderer_host/input/web_touch_event_traits.cc \
+	content/browser/renderer_host/java/java_bound_object.cc \
+	content/browser/renderer_host/java/java_bridge_channel_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host.cc \
+	content/browser/renderer_host/java/java_bridge_dispatcher_host_manager.cc \
+	content/browser/renderer_host/java/java_method.cc \
+	content/browser/renderer_host/java/java_type.cc \
+	content/browser/renderer_host/java/jni_helper.cc \
+	content/browser/renderer_host/media/audio_input_device_manager.cc \
+	content/browser/renderer_host/media/audio_input_renderer_host.cc \
+	content/browser/renderer_host/media/audio_input_sync_writer.cc \
+	content/browser/renderer_host/media/audio_renderer_host.cc \
+	content/browser/renderer_host/media/audio_sync_reader.cc \
+	content/browser/renderer_host/media/device_request_message_filter.cc \
+	content/browser/renderer_host/media/media_capture_devices_impl.cc \
+	content/browser/renderer_host/media/media_stream_dispatcher_host.cc \
+	content/browser/renderer_host/media/media_stream_manager.cc \
+	content/browser/renderer_host/media/media_stream_track_metrics_host.cc \
+	content/browser/renderer_host/media/media_stream_ui_proxy.cc \
+	content/browser/renderer_host/media/midi_dispatcher_host.cc \
+	content/browser/renderer_host/media/midi_host.cc \
+	content/browser/renderer_host/media/video_capture_buffer_pool.cc \
+	content/browser/renderer_host/media/video_capture_controller.cc \
+	content/browser/renderer_host/media/video_capture_controller_event_handler.cc \
+	content/browser/renderer_host/media/video_capture_host.cc \
+	content/browser/renderer_host/media/video_capture_manager.cc \
+	content/browser/renderer_host/memory_benchmark_message_filter.cc \
+	content/browser/renderer_host/native_web_keyboard_event_android.cc \
+	content/browser/renderer_host/overscroll_configuration.cc \
+	content/browser/renderer_host/overscroll_controller.cc \
+	content/browser/renderer_host/render_message_filter.cc \
+	content/browser/renderer_host/render_process_host_impl.cc \
+	content/browser/renderer_host/render_view_host_delegate.cc \
+	content/browser/renderer_host/render_view_host_factory.cc \
+	content/browser/renderer_host/render_view_host_impl.cc \
+	content/browser/renderer_host/render_widget_helper.cc \
+	content/browser/renderer_host/render_widget_host_delegate.cc \
+	content/browser/renderer_host/render_widget_host_impl.cc \
+	content/browser/renderer_host/render_widget_host_view_android.cc \
+	content/browser/renderer_host/render_widget_host_view_base.cc \
+	content/browser/renderer_host/renderer_frame_manager.cc \
+	content/browser/renderer_host/software_frame_manager.cc \
+	content/browser/renderer_host/socket_stream_dispatcher_host.cc \
+	content/browser/renderer_host/socket_stream_host.cc \
+	content/browser/renderer_host/websocket_dispatcher_host.cc \
+	content/browser/renderer_host/websocket_host.cc \
+	content/browser/resolve_proxy_msg_helper.cc \
+	content/browser/resource_context_impl.cc \
+	content/browser/screen_orientation/screen_orientation_dispatcher_host.cc \
+	content/browser/screen_orientation/screen_orientation_provider_android.cc \
+	content/browser/service_worker/embedded_worker_instance.cc \
+	content/browser/service_worker/embedded_worker_registry.cc \
+	content/browser/service_worker/service_worker_context_core.cc \
+	content/browser/service_worker/service_worker_context_wrapper.cc \
+	content/browser/service_worker/service_worker_dispatcher_host.cc \
+	content/browser/service_worker/service_worker_info.cc \
+	content/browser/service_worker/service_worker_internals_ui.cc \
+	content/browser/service_worker/service_worker_job_coordinator.cc \
+	content/browser/service_worker/service_worker_provider_host.cc \
+	content/browser/service_worker/service_worker_fetch_dispatcher.cc \
+	content/browser/service_worker/service_worker_register_job.cc \
+	content/browser/service_worker/service_worker_registration.cc \
+	content/browser/service_worker/service_worker_registration_status.cc \
+	content/browser/service_worker/service_worker_request_handler.cc \
+	content/browser/service_worker/service_worker_storage.cc \
+	content/browser/service_worker/service_worker_url_request_job.cc \
+	content/browser/service_worker/service_worker_utils.cc \
+	content/browser/service_worker/service_worker_version.cc \
+	content/browser/shared_worker/shared_worker_host.cc \
+	content/browser/shared_worker/shared_worker_instance.cc \
+	content/browser/shared_worker/shared_worker_message_filter.cc \
+	content/browser/shared_worker/shared_worker_service_impl.cc \
+	content/browser/signed_certificate_timestamp_store_impl.cc \
+	content/browser/site_instance_impl.cc \
+	content/browser/speech/speech_recognition_dispatcher_host.cc \
+	content/browser/speech/speech_recognition_manager_impl.cc \
+	content/browser/speech/speech_recognizer_impl_android.cc \
+	content/browser/ssl/ssl_cert_error_handler.cc \
+	content/browser/ssl/ssl_client_auth_handler.cc \
+	content/browser/ssl/ssl_error_handler.cc \
+	content/browser/ssl/ssl_host_state.cc \
+	content/browser/ssl/ssl_manager.cc \
+	content/browser/ssl/ssl_policy_backend.cc \
+	content/browser/ssl/ssl_policy.cc \
+	content/browser/ssl/ssl_request_info.cc \
+	content/browser/startup_task_runner.cc \
+	content/browser/streams/stream.cc \
+	content/browser/streams/stream_context.cc \
+	content/browser/streams/stream_handle_impl.cc \
+	content/browser/streams/stream_registry.cc \
+	content/browser/streams/stream_url_request_job.cc \
+	content/browser/storage_partition_impl.cc \
+	content/browser/storage_partition_impl_map.cc \
+	content/browser/tcmalloc_internals_request_job.cc \
+	content/browser/tracing/trace_message_filter.cc \
+	content/browser/tracing/tracing_controller_impl.cc \
+	content/browser/user_metrics.cc \
+	content/browser/utility_process_host_impl.cc \
+	content/browser/vibration/vibration_message_filter.cc \
+	content/browser/vibration/vibration_provider_android.cc \
+	content/browser/web_contents/web_contents_android.cc \
+	content/browser/web_contents/web_contents_impl.cc \
+	content/browser/web_contents/web_contents_view_android.cc \
+	content/browser/web_contents/web_contents_view_guest.cc \
+	content/browser/webui/content_web_ui_controller_factory.cc \
+	content/browser/webui/generic_handler.cc \
+	content/browser/webui/shared_resources_data_source.cc \
+	content/browser/webui/url_data_manager.cc \
+	content/browser/webui/url_data_manager_backend.cc \
+	content/browser/webui/url_data_source_impl.cc \
+	content/browser/webui/web_ui_data_source_impl.cc \
+	content/browser/webui/web_ui_controller_factory_registry.cc \
+	content/browser/webui/web_ui_impl.cc \
+	content/browser/webui/web_ui_message_handler.cc \
+	content/browser/worker_host/worker_document_set.cc \
+	content/browser/worker_host/worker_message_filter.cc \
+	content/browser/worker_host/worker_process_host.cc \
+	content/browser/worker_host/worker_service_impl.cc \
+	content/browser/worker_host/worker_storage_partition.cc \
+	content/browser/power_profiler/power_data_provider_dummy.cc \
+	content/browser/gamepad/gamepad_platform_data_fetcher.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DAVOID_LIBYUV_FOR_ANDROID_WEBVIEW' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DAVOID_LIBYUV_FOR_ANDROID_WEBVIEW' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	ui_base_ui_base_gyp \
+	content_browser_speech_proto_speech_proto_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_browser_gyp
+
+# Alias gyp target name.
+.PHONY: content_browser
+content_browser: content_content_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_child.gypi b/content/content_child.gypi
index 95ee08a..354faed 100644
--- a/content/content_child.gypi
+++ b/content/content_child.gypi
@@ -135,6 +135,8 @@
     'child/quota_message_filter.h',
     'child/request_extra_data.cc',
     'child/request_extra_data.h',
+    'child/request_info.cc',
+    'child/request_info.h',
     'child/resource_dispatcher.cc',
     'child/resource_dispatcher.h',
     'child/runtime_features.cc',
@@ -159,6 +161,8 @@
     'child/site_isolation_policy.h',
     'child/socket_stream_dispatcher.cc',
     'child/socket_stream_dispatcher.h',
+    'child/touch_fling_gesture_curve.cc',
+    'child/touch_fling_gesture_curve.h',
     'child/thread_safe_sender.cc',
     'child/thread_safe_sender.h',
     'child/web_database_observer_impl.cc',
@@ -176,6 +180,7 @@
     'child/webcrypto/crypto_data.cc',
     'child/webcrypto/crypto_data.h',
     'child/webcrypto/jwk.cc',
+    'child/webcrypto/jwk.h',
     'child/webcrypto/platform_crypto.h',
     'child/webcrypto/platform_crypto_nss.cc',
     'child/webcrypto/platform_crypto_openssl.cc',
@@ -191,10 +196,6 @@
     'child/webfallbackthemeengine_impl.h',
     'child/webfileutilities_impl.cc',
     'child/webfileutilities_impl.h',
-    'child/webkitplatformsupport_child_impl.cc',
-    'child/webkitplatformsupport_child_impl.h',
-    'child/webkitplatformsupport_impl.cc',
-    'child/webkitplatformsupport_impl.h',
     'child/webmessageportchannel_impl.cc',
     'child/webmessageportchannel_impl.h',
     'child/websocket_bridge.cc',
diff --git a/content/content_child.target.darwin-arm.mk b/content/content_child.target.darwin-arm.mk
index 32812da..10fb0e4 100644
--- a/content/content_child.target.darwin-arm.mk
+++ b/content/content_child.target.darwin-arm.mk
@@ -71,6 +71,7 @@
 	content/child/quota_dispatcher.cc \
 	content/child/quota_message_filter.cc \
 	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
 	content/child/resource_dispatcher.cc \
 	content/child/runtime_features.cc \
 	content/child/scoped_child_process_reference.cc \
@@ -83,6 +84,7 @@
 	content/child/simple_webmimeregistry_impl.cc \
 	content/child/site_isolation_policy.cc \
 	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
 	content/child/thread_safe_sender.cc \
 	content/child/web_database_observer_impl.cc \
 	content/child/web_discardable_memory_impl.cc \
@@ -98,8 +100,6 @@
 	content/child/webcrypto/webcrypto_util.cc \
 	content/child/webfallbackthemeengine_impl.cc \
 	content/child/webfileutilities_impl.cc \
-	content/child/webkitplatformsupport_child_impl.cc \
-	content/child/webkitplatformsupport_impl.cc \
 	content/child/webmessageportchannel_impl.cc \
 	content/child/websocket_bridge.cc \
 	content/child/websocket_dispatcher.cc \
@@ -169,9 +169,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -185,6 +183,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -311,9 +310,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -327,6 +324,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_child.target.darwin-mips.mk b/content/content_child.target.darwin-mips.mk
index 9cb1ba4..8b451b6 100644
--- a/content/content_child.target.darwin-mips.mk
+++ b/content/content_child.target.darwin-mips.mk
@@ -71,6 +71,7 @@
 	content/child/quota_dispatcher.cc \
 	content/child/quota_message_filter.cc \
 	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
 	content/child/resource_dispatcher.cc \
 	content/child/runtime_features.cc \
 	content/child/scoped_child_process_reference.cc \
@@ -83,6 +84,7 @@
 	content/child/simple_webmimeregistry_impl.cc \
 	content/child/site_isolation_policy.cc \
 	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
 	content/child/thread_safe_sender.cc \
 	content/child/web_database_observer_impl.cc \
 	content/child/web_discardable_memory_impl.cc \
@@ -98,8 +100,6 @@
 	content/child/webcrypto/webcrypto_util.cc \
 	content/child/webfallbackthemeengine_impl.cc \
 	content/child/webfileutilities_impl.cc \
-	content/child/webkitplatformsupport_child_impl.cc \
-	content/child/webkitplatformsupport_impl.cc \
 	content/child/webmessageportchannel_impl.cc \
 	content/child/websocket_bridge.cc \
 	content/child/websocket_dispatcher.cc \
@@ -168,9 +168,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -184,6 +182,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -309,9 +308,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -325,6 +322,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_child.target.darwin-x86.mk b/content/content_child.target.darwin-x86.mk
index 4730c82..d6430b8 100644
--- a/content/content_child.target.darwin-x86.mk
+++ b/content/content_child.target.darwin-x86.mk
@@ -71,6 +71,7 @@
 	content/child/quota_dispatcher.cc \
 	content/child/quota_message_filter.cc \
 	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
 	content/child/resource_dispatcher.cc \
 	content/child/runtime_features.cc \
 	content/child/scoped_child_process_reference.cc \
@@ -83,6 +84,7 @@
 	content/child/simple_webmimeregistry_impl.cc \
 	content/child/site_isolation_policy.cc \
 	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
 	content/child/thread_safe_sender.cc \
 	content/child/web_database_observer_impl.cc \
 	content/child/web_discardable_memory_impl.cc \
@@ -98,8 +100,6 @@
 	content/child/webcrypto/webcrypto_util.cc \
 	content/child/webfallbackthemeengine_impl.cc \
 	content/child/webfileutilities_impl.cc \
-	content/child/webkitplatformsupport_child_impl.cc \
-	content/child/webkitplatformsupport_impl.cc \
 	content/child/webmessageportchannel_impl.cc \
 	content/child/websocket_bridge.cc \
 	content/child/websocket_dispatcher.cc \
@@ -170,9 +170,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -185,6 +183,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -311,9 +310,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -326,6 +323,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_child.target.darwin-x86_64.mk b/content/content_child.target.darwin-x86_64.mk
new file mode 100644
index 0000000..70b9749
--- /dev/null
+++ b/content/content_child.target.darwin-x86_64.mk
@@ -0,0 +1,460 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_child_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_child_webkit_child_gyp)/webkit_child_webkit_child_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/child/appcache/appcache_backend_proxy.cc \
+	content/child/appcache/appcache_dispatcher.cc \
+	content/child/appcache/appcache_frontend_impl.cc \
+	content/child/appcache/web_application_cache_host_impl.cc \
+	content/child/blink_glue.cc \
+	content/child/blink_platform_impl.cc \
+	content/child/child_histogram_message_filter.cc \
+	content/child/child_message_filter.cc \
+	content/child/child_process.cc \
+	content/child/child_resource_message_filter.cc \
+	content/child/child_shared_bitmap_manager.cc \
+	content/child/child_thread.cc \
+	content/child/content_child_helpers.cc \
+	content/child/database_util.cc \
+	content/child/db_message_filter.cc \
+	content/child/fileapi/file_system_dispatcher.cc \
+	content/child/fileapi/webfilesystem_impl.cc \
+	content/child/fileapi/webfilewriter_base.cc \
+	content/child/fileapi/webfilewriter_impl.cc \
+	content/child/fling_animator_impl_android.cc \
+	content/child/fling_curve_configuration.cc \
+	content/child/ftp_directory_listing_response_delegate.cc \
+	content/child/image_decoder.cc \
+	content/child/indexed_db/indexed_db_dispatcher.cc \
+	content/child/indexed_db/indexed_db_key_builders.cc \
+	content/child/indexed_db/indexed_db_message_filter.cc \
+	content/child/indexed_db/webidbcursor_impl.cc \
+	content/child/indexed_db/webidbdatabase_impl.cc \
+	content/child/indexed_db/webidbfactory_impl.cc \
+	content/child/npapi/np_channel_base.cc \
+	content/child/npapi/npobject_proxy.cc \
+	content/child/npapi/npobject_stub.cc \
+	content/child/npapi/npobject_util.cc \
+	content/child/npapi/npruntime_util.cc \
+	content/child/plugin_message_generator.cc \
+	content/child/plugin_param_traits.cc \
+	content/child/power_monitor_broadcast_source.cc \
+	content/child/quota_dispatcher.cc \
+	content/child/quota_message_filter.cc \
+	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
+	content/child/resource_dispatcher.cc \
+	content/child/runtime_features.cc \
+	content/child/scoped_child_process_reference.cc \
+	content/child/service_worker/service_worker_dispatcher.cc \
+	content/child/service_worker/service_worker_message_filter.cc \
+	content/child/service_worker/service_worker_network_provider.cc \
+	content/child/service_worker/web_service_worker_impl.cc \
+	content/child/service_worker/web_service_worker_provider_impl.cc \
+	content/child/shared_worker_devtools_agent.cc \
+	content/child/simple_webmimeregistry_impl.cc \
+	content/child/site_isolation_policy.cc \
+	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
+	content/child/thread_safe_sender.cc \
+	content/child/web_database_observer_impl.cc \
+	content/child/web_discardable_memory_impl.cc \
+	content/child/web_socket_stream_handle_impl.cc \
+	content/child/web_url_loader_impl.cc \
+	content/child/webblobregistry_impl.cc \
+	content/child/webcrypto/crypto_data.cc \
+	content/child/webcrypto/jwk.cc \
+	content/child/webcrypto/platform_crypto_openssl.cc \
+	content/child/webcrypto/shared_crypto.cc \
+	content/child/webcrypto/status.cc \
+	content/child/webcrypto/webcrypto_impl.cc \
+	content/child/webcrypto/webcrypto_util.cc \
+	content/child/webfallbackthemeengine_impl.cc \
+	content/child/webfileutilities_impl.cc \
+	content/child/webmessageportchannel_impl.cc \
+	content/child/websocket_bridge.cc \
+	content/child/websocket_dispatcher.cc \
+	content/child/webthemeengine_impl_android.cc \
+	content/child/webthread_impl.cc \
+	content/child/worker_task_runner.cc \
+	content/child/worker_thread_task_runner.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp \
+	webkit_child_webkit_child_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_child_gyp
+
+# Alias gyp target name.
+.PHONY: content_child
+content_child: content_content_child_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_child.target.linux-arm.mk b/content/content_child.target.linux-arm.mk
index 32812da..10fb0e4 100644
--- a/content/content_child.target.linux-arm.mk
+++ b/content/content_child.target.linux-arm.mk
@@ -71,6 +71,7 @@
 	content/child/quota_dispatcher.cc \
 	content/child/quota_message_filter.cc \
 	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
 	content/child/resource_dispatcher.cc \
 	content/child/runtime_features.cc \
 	content/child/scoped_child_process_reference.cc \
@@ -83,6 +84,7 @@
 	content/child/simple_webmimeregistry_impl.cc \
 	content/child/site_isolation_policy.cc \
 	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
 	content/child/thread_safe_sender.cc \
 	content/child/web_database_observer_impl.cc \
 	content/child/web_discardable_memory_impl.cc \
@@ -98,8 +100,6 @@
 	content/child/webcrypto/webcrypto_util.cc \
 	content/child/webfallbackthemeengine_impl.cc \
 	content/child/webfileutilities_impl.cc \
-	content/child/webkitplatformsupport_child_impl.cc \
-	content/child/webkitplatformsupport_impl.cc \
 	content/child/webmessageportchannel_impl.cc \
 	content/child/websocket_bridge.cc \
 	content/child/websocket_dispatcher.cc \
@@ -169,9 +169,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -185,6 +183,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -311,9 +310,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -327,6 +324,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_child.target.linux-mips.mk b/content/content_child.target.linux-mips.mk
index 9cb1ba4..8b451b6 100644
--- a/content/content_child.target.linux-mips.mk
+++ b/content/content_child.target.linux-mips.mk
@@ -71,6 +71,7 @@
 	content/child/quota_dispatcher.cc \
 	content/child/quota_message_filter.cc \
 	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
 	content/child/resource_dispatcher.cc \
 	content/child/runtime_features.cc \
 	content/child/scoped_child_process_reference.cc \
@@ -83,6 +84,7 @@
 	content/child/simple_webmimeregistry_impl.cc \
 	content/child/site_isolation_policy.cc \
 	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
 	content/child/thread_safe_sender.cc \
 	content/child/web_database_observer_impl.cc \
 	content/child/web_discardable_memory_impl.cc \
@@ -98,8 +100,6 @@
 	content/child/webcrypto/webcrypto_util.cc \
 	content/child/webfallbackthemeengine_impl.cc \
 	content/child/webfileutilities_impl.cc \
-	content/child/webkitplatformsupport_child_impl.cc \
-	content/child/webkitplatformsupport_impl.cc \
 	content/child/webmessageportchannel_impl.cc \
 	content/child/websocket_bridge.cc \
 	content/child/websocket_dispatcher.cc \
@@ -168,9 +168,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -184,6 +182,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -309,9 +308,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -325,6 +322,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_child.target.linux-x86.mk b/content/content_child.target.linux-x86.mk
index 4730c82..d6430b8 100644
--- a/content/content_child.target.linux-x86.mk
+++ b/content/content_child.target.linux-x86.mk
@@ -71,6 +71,7 @@
 	content/child/quota_dispatcher.cc \
 	content/child/quota_message_filter.cc \
 	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
 	content/child/resource_dispatcher.cc \
 	content/child/runtime_features.cc \
 	content/child/scoped_child_process_reference.cc \
@@ -83,6 +84,7 @@
 	content/child/simple_webmimeregistry_impl.cc \
 	content/child/site_isolation_policy.cc \
 	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
 	content/child/thread_safe_sender.cc \
 	content/child/web_database_observer_impl.cc \
 	content/child/web_discardable_memory_impl.cc \
@@ -98,8 +100,6 @@
 	content/child/webcrypto/webcrypto_util.cc \
 	content/child/webfallbackthemeengine_impl.cc \
 	content/child/webfileutilities_impl.cc \
-	content/child/webkitplatformsupport_child_impl.cc \
-	content/child/webkitplatformsupport_impl.cc \
 	content/child/webmessageportchannel_impl.cc \
 	content/child/websocket_bridge.cc \
 	content/child/websocket_dispatcher.cc \
@@ -170,9 +170,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -185,6 +183,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -311,9 +310,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -326,6 +323,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_child.target.linux-x86_64.mk b/content/content_child.target.linux-x86_64.mk
new file mode 100644
index 0000000..70b9749
--- /dev/null
+++ b/content/content_child.target.linux-x86_64.mk
@@ -0,0 +1,460 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_child_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_child_webkit_child_gyp)/webkit_child_webkit_child_gyp.a \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/child/appcache/appcache_backend_proxy.cc \
+	content/child/appcache/appcache_dispatcher.cc \
+	content/child/appcache/appcache_frontend_impl.cc \
+	content/child/appcache/web_application_cache_host_impl.cc \
+	content/child/blink_glue.cc \
+	content/child/blink_platform_impl.cc \
+	content/child/child_histogram_message_filter.cc \
+	content/child/child_message_filter.cc \
+	content/child/child_process.cc \
+	content/child/child_resource_message_filter.cc \
+	content/child/child_shared_bitmap_manager.cc \
+	content/child/child_thread.cc \
+	content/child/content_child_helpers.cc \
+	content/child/database_util.cc \
+	content/child/db_message_filter.cc \
+	content/child/fileapi/file_system_dispatcher.cc \
+	content/child/fileapi/webfilesystem_impl.cc \
+	content/child/fileapi/webfilewriter_base.cc \
+	content/child/fileapi/webfilewriter_impl.cc \
+	content/child/fling_animator_impl_android.cc \
+	content/child/fling_curve_configuration.cc \
+	content/child/ftp_directory_listing_response_delegate.cc \
+	content/child/image_decoder.cc \
+	content/child/indexed_db/indexed_db_dispatcher.cc \
+	content/child/indexed_db/indexed_db_key_builders.cc \
+	content/child/indexed_db/indexed_db_message_filter.cc \
+	content/child/indexed_db/webidbcursor_impl.cc \
+	content/child/indexed_db/webidbdatabase_impl.cc \
+	content/child/indexed_db/webidbfactory_impl.cc \
+	content/child/npapi/np_channel_base.cc \
+	content/child/npapi/npobject_proxy.cc \
+	content/child/npapi/npobject_stub.cc \
+	content/child/npapi/npobject_util.cc \
+	content/child/npapi/npruntime_util.cc \
+	content/child/plugin_message_generator.cc \
+	content/child/plugin_param_traits.cc \
+	content/child/power_monitor_broadcast_source.cc \
+	content/child/quota_dispatcher.cc \
+	content/child/quota_message_filter.cc \
+	content/child/request_extra_data.cc \
+	content/child/request_info.cc \
+	content/child/resource_dispatcher.cc \
+	content/child/runtime_features.cc \
+	content/child/scoped_child_process_reference.cc \
+	content/child/service_worker/service_worker_dispatcher.cc \
+	content/child/service_worker/service_worker_message_filter.cc \
+	content/child/service_worker/service_worker_network_provider.cc \
+	content/child/service_worker/web_service_worker_impl.cc \
+	content/child/service_worker/web_service_worker_provider_impl.cc \
+	content/child/shared_worker_devtools_agent.cc \
+	content/child/simple_webmimeregistry_impl.cc \
+	content/child/site_isolation_policy.cc \
+	content/child/socket_stream_dispatcher.cc \
+	content/child/touch_fling_gesture_curve.cc \
+	content/child/thread_safe_sender.cc \
+	content/child/web_database_observer_impl.cc \
+	content/child/web_discardable_memory_impl.cc \
+	content/child/web_socket_stream_handle_impl.cc \
+	content/child/web_url_loader_impl.cc \
+	content/child/webblobregistry_impl.cc \
+	content/child/webcrypto/crypto_data.cc \
+	content/child/webcrypto/jwk.cc \
+	content/child/webcrypto/platform_crypto_openssl.cc \
+	content/child/webcrypto/shared_crypto.cc \
+	content/child/webcrypto/status.cc \
+	content/child/webcrypto/webcrypto_impl.cc \
+	content/child/webcrypto/webcrypto_util.cc \
+	content/child/webfallbackthemeengine_impl.cc \
+	content/child/webfileutilities_impl.cc \
+	content/child/webmessageportchannel_impl.cc \
+	content/child/websocket_bridge.cc \
+	content/child/websocket_dispatcher.cc \
+	content/child/webthemeengine_impl_android.cc \
+	content/child/webthread_impl.cc \
+	content/child/worker_task_runner.cc \
+	content/child/worker_thread_task_runner.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp \
+	webkit_child_webkit_child_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_child_gyp
+
+# Alias gyp target name.
+.PHONY: content_child
+content_child: content_content_child_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_common.gypi b/content/content_common.gypi
index f5ccdad..6fcf141 100644
--- a/content/content_common.gypi
+++ b/content/content_common.gypi
@@ -171,7 +171,7 @@
     'common/cursors/webcursor_gtk.cc',
     'common/cursors/webcursor_gtk_data.h',
     'common/cursors/webcursor_mac.mm',
-    'common/cursors/webcursor_null.cc',
+    'common/cursors/webcursor_ozone.cc',
     'common/cursors/webcursor_win.cc',
     'common/database_messages.h',
     'common/date_time_suggestion.h',
@@ -452,11 +452,6 @@
         'common/cursors/webcursor_win.cc',
       ],
     }],
-    ['use_ozone==0', {
-      'sources!': [
-        'common/cursors/webcursor_null.cc',
-      ],
-    }],
     ['OS=="ios"', {
       # iOS has different user-agent construction utilities, since the
       # version strings is not derived from webkit_version, and follows
@@ -509,9 +504,9 @@
         'content.gyp:webkit_version',
       ],
     }],
-    # Work around for bug in linker used on ia32 machines (gold is not used on
-    # ia32 machines). See bug 353273.
-    ['use_mojo==1 and OS=="linux" and target_arch=="ia32" and component=="static_library"', {
+    # Work around for bug in linker used on ia32 and mipsel machines (gold is
+    # not used on ia32 and mipsel machines). See bug 353273.
+    ['use_mojo==1 and OS=="linux" and (target_arch=="ia32" or target_arch=="mipsel") and component=="static_library"', {
       'link_settings': {
         'libraries': [
           '<(PRODUCT_DIR)/lib/libmojo_system.so',
@@ -528,7 +523,7 @@
         '../mojo/mojo.gyp:mojo_environment_chromium',
         '../mojo/mojo.gyp:mojo_system',
         '../mojo/mojo.gyp:mojo_system_impl',
-      ],
+     ],
     }],
     ['OS=="mac"', {
       'dependencies': [
diff --git a/content/content_common.target.darwin-arm.mk b/content/content_common.target.darwin-arm.mk
index fcc7813..82d3c19 100644
--- a/content/content_common.target.darwin-arm.mk
+++ b/content/content_common.target.darwin-arm.mk
@@ -225,9 +225,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +249,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -386,9 +385,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -412,6 +409,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_common.target.darwin-mips.mk b/content/content_common.target.darwin-mips.mk
index f351c57..5876977 100644
--- a/content/content_common.target.darwin-mips.mk
+++ b/content/content_common.target.darwin-mips.mk
@@ -223,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +247,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -382,9 +381,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -408,6 +405,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_common.target.darwin-x86.mk b/content/content_common.target.darwin-x86.mk
index 8dbabe4..c8c5839 100644
--- a/content/content_common.target.darwin-x86.mk
+++ b/content/content_common.target.darwin-x86.mk
@@ -225,9 +225,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +249,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -385,9 +384,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -411,6 +408,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_common.target.darwin-x86_64.mk b/content/content_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..1be366c
--- /dev/null
+++ b/content/content_common.target.darwin-x86_64.mk
@@ -0,0 +1,550 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,content_webkit_version_gyp)/webkit_version.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/common/assert_matching_enums.cc \
+	content/public/common/child_process_host_delegate.cc \
+	content/public/common/color_suggestion.cc \
+	content/public/common/common_param_traits.cc \
+	content/public/common/content_client.cc \
+	content/public/common/content_constants.cc \
+	content/public/common/content_switches.cc \
+	content/public/common/context_menu_params.cc \
+	content/public/common/drop_data.cc \
+	content/public/common/favicon_url.cc \
+	content/public/common/file_chooser_params.cc \
+	content/public/common/frame_navigate_params.cc \
+	content/public/common/geoposition.cc \
+	content/public/common/gpu_memory_stats.cc \
+	content/public/common/media_stream_request.cc \
+	content/public/common/menu_item.cc \
+	content/public/common/page_state.cc \
+	content/public/common/page_transition_types.cc \
+	content/public/common/pepper_plugin_info.cc \
+	content/public/common/renderer_preferences.cc \
+	content/public/common/sandboxed_process_launcher_delegate.cc \
+	content/public/common/show_desktop_notification_params.cc \
+	content/public/common/signed_certificate_timestamp_id_and_status.cc \
+	content/public/common/speech_recognition_result.cc \
+	content/public/common/ssl_status.cc \
+	content/public/common/url_constants.cc \
+	content/public/common/url_utils.cc \
+	content/public/common/webplugininfo.cc \
+	content/public/common/window_container_type.cc \
+	content/common/android/address_parser.cc \
+	content/common/android/address_parser_internal.cc \
+	content/common/android/common_jni_registrar.cc \
+	content/common/android/device_telephony_info.cc \
+	content/common/android/hash_set.cc \
+	content/common/android/surface_texture_peer.cc \
+	content/common/browser_plugin/browser_plugin_constants.cc \
+	content/common/cc_messages.cc \
+	content/common/child_process_host_impl.cc \
+	content/common/content_constants_internal.cc \
+	content/common/content_ipc_logging.cc \
+	content/common/content_message_generator.cc \
+	content/common/content_param_traits.cc \
+	content/common/content_paths.cc \
+	content/common/content_switches_internal.cc \
+	content/common/cookie_data.cc \
+	content/common/cursors/webcursor.cc \
+	content/common/cursors/webcursor_android.cc \
+	content/common/dom_storage/dom_storage_map.cc \
+	content/common/font_list.cc \
+	content/common/font_list_android.cc \
+	content/common/frame_param.cc \
+	content/common/gamepad_user_gesture.cc \
+	content/common/gpu/client/command_buffer_proxy_impl.cc \
+	content/common/gpu/client/context_provider_command_buffer.cc \
+	content/common/gpu/client/gl_helper.cc \
+	content/common/gpu/client/gl_helper_readback_support.cc \
+	content/common/gpu/client/gl_helper_scaling.cc \
+	content/common/gpu/client/gpu_channel_host.cc \
+	content/common/gpu/client/gpu_memory_buffer_impl.cc \
+	content/common/gpu/client/gpu_memory_buffer_impl_android.cc \
+	content/common/gpu/client/gpu_memory_buffer_impl_shm.cc \
+	content/common/gpu/client/gpu_video_decode_accelerator_host.cc \
+	content/common/gpu/client/gpu_video_encode_accelerator_host.cc \
+	content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc \
+	content/common/gpu/devtools_gpu_agent.cc \
+	content/common/gpu/devtools_gpu_instrumentation.cc \
+	content/common/gpu/gpu_channel.cc \
+	content/common/gpu/gpu_channel_manager.cc \
+	content/common/gpu/gpu_command_buffer_stub.cc \
+	content/common/gpu/gpu_memory_manager.cc \
+	content/common/gpu/gpu_memory_manager_client.cc \
+	content/common/gpu/gpu_memory_tracking.cc \
+	content/common/gpu/gpu_surface_lookup.cc \
+	content/common/gpu/image_transport_surface.cc \
+	content/common/gpu/image_transport_surface_android.cc \
+	content/common/gpu/media/gpu_video_decode_accelerator.cc \
+	content/common/gpu/media/gpu_video_encode_accelerator.cc \
+	content/common/gpu/media/video_decode_accelerator_impl.cc \
+	content/common/gpu/stream_texture_android.cc \
+	content/common/gpu/sync_point_manager.cc \
+	content/common/gpu/texture_image_transport_surface.cc \
+	content/common/host_shared_bitmap_manager.cc \
+	content/common/indexed_db/indexed_db_key.cc \
+	content/common/indexed_db/indexed_db_key_path.cc \
+	content/common/indexed_db/indexed_db_key_range.cc \
+	content/common/indexed_db/indexed_db_param_traits.cc \
+	content/common/input/gesture_event_stream_validator.cc \
+	content/common/input/input_event.cc \
+	content/common/input/input_event_stream_validator.cc \
+	content/common/input/input_param_traits.cc \
+	content/common/input/scoped_web_input_event.cc \
+	content/common/input/synthetic_gesture_packet.cc \
+	content/common/input/synthetic_gesture_params.cc \
+	content/common/input/synthetic_pinch_gesture_params.cc \
+	content/common/input/synthetic_smooth_scroll_gesture_params.cc \
+	content/common/input/synthetic_tap_gesture_params.cc \
+	content/common/input/synthetic_web_input_event_builders.cc \
+	content/common/input/web_input_event_traits.cc \
+	content/common/inter_process_time_ticks_converter.cc \
+	content/common/media/media_param_traits.cc \
+	content/common/media/media_stream_options.cc \
+	content/common/message_router.cc \
+	content/common/net/url_fetcher.cc \
+	content/common/net/url_request_user_data.cc \
+	content/common/one_writer_seqlock.cc \
+	content/common/page_state_serialization.cc \
+	content/common/page_zoom.cc \
+	content/common/pepper_renderer_instance_data.cc \
+	content/common/plugin_list.cc \
+	content/common/plugin_list_posix.cc \
+	content/common/process_type.cc \
+	content/common/resource_messages.cc \
+	content/common/resource_request_body.cc \
+	content/common/savable_url_schemes.cc \
+	content/common/service_worker/service_worker_status_code.cc \
+	content/common/service_worker/service_worker_types.cc \
+	content/common/set_process_title.cc \
+	content/common/ssl_status_serialization.cc \
+	content/common/swapped_out_messages.cc \
+	content/common/url_schemes.cc \
+	content/common/user_agent.cc \
+	content/common/webplugin_geometry.cc \
+	content/common/websocket.cc \
+	content/common/gpu/media/android_video_decode_accelerator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SECCOMP_BPF' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SECCOMP_BPF' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	ui_base_ui_base_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_common_gyp
+
+# Alias gyp target name.
+.PHONY: content_common
+content_common: content_content_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_common.target.linux-arm.mk b/content/content_common.target.linux-arm.mk
index fcc7813..82d3c19 100644
--- a/content/content_common.target.linux-arm.mk
+++ b/content/content_common.target.linux-arm.mk
@@ -225,9 +225,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +249,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -386,9 +385,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -412,6 +409,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_common.target.linux-mips.mk b/content/content_common.target.linux-mips.mk
index f351c57..5876977 100644
--- a/content/content_common.target.linux-mips.mk
+++ b/content/content_common.target.linux-mips.mk
@@ -223,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +247,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -382,9 +381,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -408,6 +405,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_common.target.linux-x86.mk b/content/content_common.target.linux-x86.mk
index 8dbabe4..c8c5839 100644
--- a/content/content_common.target.linux-x86.mk
+++ b/content/content_common.target.linux-x86.mk
@@ -225,9 +225,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +249,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -385,9 +384,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -411,6 +408,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DAPPCACHE_USE_SIMPLE_CACHE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_common.target.linux-x86_64.mk b/content/content_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..1be366c
--- /dev/null
+++ b/content/content_common.target.linux-x86_64.mk
@@ -0,0 +1,550 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,content_webkit_version_gyp)/webkit_version.stamp \
+	$(call intermediates-dir-for,GYP,content_content_jni_headers_gyp)/content_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_common_aidl_gyp)/common_aidl.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/common/assert_matching_enums.cc \
+	content/public/common/child_process_host_delegate.cc \
+	content/public/common/color_suggestion.cc \
+	content/public/common/common_param_traits.cc \
+	content/public/common/content_client.cc \
+	content/public/common/content_constants.cc \
+	content/public/common/content_switches.cc \
+	content/public/common/context_menu_params.cc \
+	content/public/common/drop_data.cc \
+	content/public/common/favicon_url.cc \
+	content/public/common/file_chooser_params.cc \
+	content/public/common/frame_navigate_params.cc \
+	content/public/common/geoposition.cc \
+	content/public/common/gpu_memory_stats.cc \
+	content/public/common/media_stream_request.cc \
+	content/public/common/menu_item.cc \
+	content/public/common/page_state.cc \
+	content/public/common/page_transition_types.cc \
+	content/public/common/pepper_plugin_info.cc \
+	content/public/common/renderer_preferences.cc \
+	content/public/common/sandboxed_process_launcher_delegate.cc \
+	content/public/common/show_desktop_notification_params.cc \
+	content/public/common/signed_certificate_timestamp_id_and_status.cc \
+	content/public/common/speech_recognition_result.cc \
+	content/public/common/ssl_status.cc \
+	content/public/common/url_constants.cc \
+	content/public/common/url_utils.cc \
+	content/public/common/webplugininfo.cc \
+	content/public/common/window_container_type.cc \
+	content/common/android/address_parser.cc \
+	content/common/android/address_parser_internal.cc \
+	content/common/android/common_jni_registrar.cc \
+	content/common/android/device_telephony_info.cc \
+	content/common/android/hash_set.cc \
+	content/common/android/surface_texture_peer.cc \
+	content/common/browser_plugin/browser_plugin_constants.cc \
+	content/common/cc_messages.cc \
+	content/common/child_process_host_impl.cc \
+	content/common/content_constants_internal.cc \
+	content/common/content_ipc_logging.cc \
+	content/common/content_message_generator.cc \
+	content/common/content_param_traits.cc \
+	content/common/content_paths.cc \
+	content/common/content_switches_internal.cc \
+	content/common/cookie_data.cc \
+	content/common/cursors/webcursor.cc \
+	content/common/cursors/webcursor_android.cc \
+	content/common/dom_storage/dom_storage_map.cc \
+	content/common/font_list.cc \
+	content/common/font_list_android.cc \
+	content/common/frame_param.cc \
+	content/common/gamepad_user_gesture.cc \
+	content/common/gpu/client/command_buffer_proxy_impl.cc \
+	content/common/gpu/client/context_provider_command_buffer.cc \
+	content/common/gpu/client/gl_helper.cc \
+	content/common/gpu/client/gl_helper_readback_support.cc \
+	content/common/gpu/client/gl_helper_scaling.cc \
+	content/common/gpu/client/gpu_channel_host.cc \
+	content/common/gpu/client/gpu_memory_buffer_impl.cc \
+	content/common/gpu/client/gpu_memory_buffer_impl_android.cc \
+	content/common/gpu/client/gpu_memory_buffer_impl_shm.cc \
+	content/common/gpu/client/gpu_video_decode_accelerator_host.cc \
+	content/common/gpu/client/gpu_video_encode_accelerator_host.cc \
+	content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc \
+	content/common/gpu/devtools_gpu_agent.cc \
+	content/common/gpu/devtools_gpu_instrumentation.cc \
+	content/common/gpu/gpu_channel.cc \
+	content/common/gpu/gpu_channel_manager.cc \
+	content/common/gpu/gpu_command_buffer_stub.cc \
+	content/common/gpu/gpu_memory_manager.cc \
+	content/common/gpu/gpu_memory_manager_client.cc \
+	content/common/gpu/gpu_memory_tracking.cc \
+	content/common/gpu/gpu_surface_lookup.cc \
+	content/common/gpu/image_transport_surface.cc \
+	content/common/gpu/image_transport_surface_android.cc \
+	content/common/gpu/media/gpu_video_decode_accelerator.cc \
+	content/common/gpu/media/gpu_video_encode_accelerator.cc \
+	content/common/gpu/media/video_decode_accelerator_impl.cc \
+	content/common/gpu/stream_texture_android.cc \
+	content/common/gpu/sync_point_manager.cc \
+	content/common/gpu/texture_image_transport_surface.cc \
+	content/common/host_shared_bitmap_manager.cc \
+	content/common/indexed_db/indexed_db_key.cc \
+	content/common/indexed_db/indexed_db_key_path.cc \
+	content/common/indexed_db/indexed_db_key_range.cc \
+	content/common/indexed_db/indexed_db_param_traits.cc \
+	content/common/input/gesture_event_stream_validator.cc \
+	content/common/input/input_event.cc \
+	content/common/input/input_event_stream_validator.cc \
+	content/common/input/input_param_traits.cc \
+	content/common/input/scoped_web_input_event.cc \
+	content/common/input/synthetic_gesture_packet.cc \
+	content/common/input/synthetic_gesture_params.cc \
+	content/common/input/synthetic_pinch_gesture_params.cc \
+	content/common/input/synthetic_smooth_scroll_gesture_params.cc \
+	content/common/input/synthetic_tap_gesture_params.cc \
+	content/common/input/synthetic_web_input_event_builders.cc \
+	content/common/input/web_input_event_traits.cc \
+	content/common/inter_process_time_ticks_converter.cc \
+	content/common/media/media_param_traits.cc \
+	content/common/media/media_stream_options.cc \
+	content/common/message_router.cc \
+	content/common/net/url_fetcher.cc \
+	content/common/net/url_request_user_data.cc \
+	content/common/one_writer_seqlock.cc \
+	content/common/page_state_serialization.cc \
+	content/common/page_zoom.cc \
+	content/common/pepper_renderer_instance_data.cc \
+	content/common/plugin_list.cc \
+	content/common/plugin_list_posix.cc \
+	content/common/process_type.cc \
+	content/common/resource_messages.cc \
+	content/common/resource_request_body.cc \
+	content/common/savable_url_schemes.cc \
+	content/common/service_worker/service_worker_status_code.cc \
+	content/common/service_worker/service_worker_types.cc \
+	content/common/set_process_title.cc \
+	content/common/ssl_status_serialization.cc \
+	content/common/swapped_out_messages.cc \
+	content/common/url_schemes.cc \
+	content/common/user_agent.cc \
+	content/common/webplugin_geometry.cc \
+	content/common/websocket.cc \
+	content/common/gpu/media/android_video_decode_accelerator.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SECCOMP_BPF' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SECCOMP_BPF' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(gyp_shared_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	ui_base_ui_base_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_common_gyp
+
+# Alias gyp target name.
+.PHONY: content_common
+content_common: content_content_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_common_mojo_bindings.gypi b/content/content_common_mojo_bindings.gypi
new file mode 100644
index 0000000..3a495b3
--- /dev/null
+++ b/content/content_common_mojo_bindings.gypi
@@ -0,0 +1,31 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'targets': [
+    {
+      'target_name': 'content_common_mojo_bindings',
+      'type': 'static_library',
+      'dependencies': [
+        '../mojo/mojo.gyp:mojo_bindings',
+        '../mojo/mojo.gyp:mojo_environment_chromium',
+        '../mojo/mojo.gyp:mojo_system',
+      ],
+      'sources': [
+        'common/mojo/render_process.mojom',
+      ],
+      # TODO(sky): this shouldn't be necessary. It's working around a bug in
+      # gyp.
+      'variables': {
+        'mojom_base_output_dir': 'content',
+      },
+      'includes': [ '../mojo/public/bindings/mojom_bindings_generator.gypi' ],
+      'export_dependent_settings': [
+        '../mojo/mojo.gyp:mojo_bindings',
+        '../mojo/mojo.gyp:mojo_environment_chromium',
+        '../mojo/mojo.gyp:mojo_system',
+      ],
+    },
+  ],
+}
diff --git a/content/content_gpu.target.darwin-arm.mk b/content/content_gpu.target.darwin-arm.mk
index e4be16e..fa3419d 100644
--- a/content/content_gpu.target.darwin-arm.mk
+++ b/content/content_gpu.target.darwin-arm.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -229,6 +226,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_gpu.target.darwin-mips.mk b/content/content_gpu.target.darwin-mips.mk
index b5d82ec..ed303c2 100644
--- a/content/content_gpu.target.darwin-mips.mk
+++ b/content/content_gpu.target.darwin-mips.mk
@@ -93,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -104,6 +102,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_gpu.target.darwin-x86.mk b/content/content_gpu.target.darwin-x86.mk
index 1d0ad9f..9ab1a3c 100644
--- a/content/content_gpu.target.darwin-x86.mk
+++ b/content/content_gpu.target.darwin-x86.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_gpu.target.darwin-x86_64.mk b/content/content_gpu.target.darwin-x86_64.mk
new file mode 100644
index 0000000..9d22128
--- /dev/null
+++ b/content/content_gpu.target.darwin-x86_64.mk
@@ -0,0 +1,344 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_gpu_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/gpu/gpu_main.cc \
+	content/gpu/gpu_process.cc \
+	content/gpu/gpu_child_thread.cc \
+	content/gpu/gpu_watchdog_thread.cc \
+	content/gpu/in_process_gpu_thread.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: content_gpu
+content_gpu: content_content_gpu_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_gpu.target.linux-arm.mk b/content/content_gpu.target.linux-arm.mk
index e4be16e..fa3419d 100644
--- a/content/content_gpu.target.linux-arm.mk
+++ b/content/content_gpu.target.linux-arm.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -229,6 +226,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_gpu.target.linux-mips.mk b/content/content_gpu.target.linux-mips.mk
index b5d82ec..ed303c2 100644
--- a/content/content_gpu.target.linux-mips.mk
+++ b/content/content_gpu.target.linux-mips.mk
@@ -93,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -104,6 +102,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_gpu.target.linux-x86.mk b/content/content_gpu.target.linux-x86.mk
index 1d0ad9f..9ab1a3c 100644
--- a/content/content_gpu.target.linux-x86.mk
+++ b/content/content_gpu.target.linux-x86.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_gpu.target.linux-x86_64.mk b/content/content_gpu.target.linux-x86_64.mk
new file mode 100644
index 0000000..9d22128
--- /dev/null
+++ b/content/content_gpu.target.linux-x86_64.mk
@@ -0,0 +1,344 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_gpu_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/gpu/gpu_main.cc \
+	content/gpu/gpu_process.cc \
+	content/gpu/gpu_child_thread.cc \
+	content/gpu/gpu_watchdog_thread.cc \
+	content/gpu/in_process_gpu_thread.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: content_gpu
+content_gpu: content_content_gpu_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_jni_headers.target.darwin-arm.mk b/content/content_jni_headers.target.darwin-arm.mk
index 280671a..e488b4b 100644
--- a/content/content_jni_headers.target.darwin-arm.mk
+++ b/content/content_jni_headers.target.darwin-arm.mk
@@ -434,6 +434,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -517,6 +518,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_jni_headers.target.darwin-mips.mk b/content/content_jni_headers.target.darwin-mips.mk
index 3aaa9b5..2e4441d 100644
--- a/content/content_jni_headers.target.darwin-mips.mk
+++ b/content/content_jni_headers.target.darwin-mips.mk
@@ -433,6 +433,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -515,6 +516,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_jni_headers.target.darwin-x86.mk b/content/content_jni_headers.target.darwin-x86.mk
index 1982879..9b03a3d 100644
--- a/content/content_jni_headers.target.darwin-x86.mk
+++ b/content/content_jni_headers.target.darwin-x86.mk
@@ -435,6 +435,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -518,6 +519,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_jni_headers.target.darwin-x86_64.mk b/content/content_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..1d20550
--- /dev/null
+++ b/content/content_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,574 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_jni_headers_gyp
+LOCAL_MODULE_STEM := content_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_motionevent_jni_headers_gyp)/motionevent_jni_headers.stamp
+
+
+### Generated for rule "content_content_gyp_content_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java', 'public/android/java/src/org/chromium/content/browser/BrowserStartupController.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java', 'public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java', 'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java', 'public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java', 'public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java', 'public/android/java/src/org/chromium/content/browser/SpeechRecognition.java', 'public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java', 'public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java', 'public/android/java/src/org/chromium/content/browser/VibrationProvider.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java', 'public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ChildProcessService.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ContentMain.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ContentMain.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/BrowserStartupController.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentSettings.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentVideoView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewCore.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewStatics.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewStatics.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DownloadController.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DownloadController.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LoadUrlParams.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LoadUrlParams.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/SpeechRecognition.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/SpeechRecognition.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/VibrationProvider.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/VibrationProvider.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
+	content_content_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: content_jni_headers
+content_jni_headers: content_content_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_jni_headers.target.linux-arm.mk b/content/content_jni_headers.target.linux-arm.mk
index 280671a..e488b4b 100644
--- a/content/content_jni_headers.target.linux-arm.mk
+++ b/content/content_jni_headers.target.linux-arm.mk
@@ -434,6 +434,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -517,6 +518,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_jni_headers.target.linux-mips.mk b/content/content_jni_headers.target.linux-mips.mk
index 3aaa9b5..2e4441d 100644
--- a/content/content_jni_headers.target.linux-mips.mk
+++ b/content/content_jni_headers.target.linux-mips.mk
@@ -433,6 +433,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -515,6 +516,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_jni_headers.target.linux-x86.mk b/content/content_jni_headers.target.linux-x86.mk
index 1982879..9b03a3d 100644
--- a/content/content_jni_headers.target.linux-x86.mk
+++ b/content/content_jni_headers.target.linux-x86.mk
@@ -435,6 +435,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -518,6 +519,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_jni_headers.target.linux-x86_64.mk b/content/content_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..1d20550
--- /dev/null
+++ b/content/content_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,574 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_jni_headers_gyp
+LOCAL_MODULE_STEM := content_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_java_set_jni_headers_gyp)/java_set_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,content_motionevent_jni_headers_gyp)/motionevent_jni_headers.stamp
+
+
+### Generated for rule "content_content_gyp_content_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/content/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java', 'public/android/java/src/org/chromium/content/browser/BrowserStartupController.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', 'public/android/java/src/org/chromium/content/browser/ContentVideoView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewCore.java', 'public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java', 'public/android/java/src/org/chromium/content/browser/ContentViewStatics.java', 'public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java', 'public/android/java/src/org/chromium/content/browser/DownloadController.java', 'public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java', 'public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java', 'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java', 'public/android/java/src/org/chromium/content/browser/LoadUrlParams.java', 'public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java', 'public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java', 'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java', 'public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java', 'public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java', 'public/android/java/src/org/chromium/content/browser/SpeechRecognition.java', 'public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java', 'public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java', 'public/android/java/src/org/chromium/content/browser/VibrationProvider.java', 'public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java', 'public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java', 'public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java', 'public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/content/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ChildProcessService.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/app/ContentMain.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/app/ContentMain.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/BrowserStartupController.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentSettings.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentSettings.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentVideoView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentVideoView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewCore.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewRenderView.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ContentViewStatics.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ContentViewStatics.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DeviceMotionAndOrientation.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/DownloadController.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/DownloadController.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/ImeAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LoadUrlParams.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LoadUrlParams.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaDrmCredentialManager.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/PowerSaveBlocker.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/ScreenOrientationProvider.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/SpeechRecognition.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/SpeechRecognition.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TouchEventSynthesizer.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/TracingControllerAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/VibrationProvider.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/VibrationProvider.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/WebContentsObserverAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h
+
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/content/jni; cd $(gyp_local_path)/content; ../base/android/jni_generator/jni_generator.py --input_file public/android/java/src/org/chromium/content/common/DeviceTelephonyInfo.java --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: content_content_jni_headers_gyp_rule_trigger
+content_content_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessService_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentMain_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserAccessibilityManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/BrowserStartupController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ChildProcessLauncher_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentSettings_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentVideoView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewCore_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewRenderView_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ContentViewStatics_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceMotionAndOrientation_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DownloadController_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ImeAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DateTimeChooserAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/InterstitialPageDelegateAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LoadUrlParams_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/LocationProviderAdapter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaDrmCredentialManager_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/MediaResourceGetter_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/PowerSaveBlocker_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/ScreenOrientationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/SpeechRecognition_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TouchEventSynthesizer_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/TracingControllerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/VibrationProvider_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsObserverAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/NavigationControllerImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/WebContentsImpl_jni.h \
+	$(gyp_shared_intermediate_dir)/content/jni/DeviceTelephonyInfo_jni.h \
+	content_content_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: content_jni_headers
+content_jni_headers: content_content_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi
index 40eb4e4..9c2a4d1 100644
--- a/content/content_renderer.gypi
+++ b/content/content_renderer.gypi
@@ -135,8 +135,6 @@
     'renderer/dom_storage/webstoragenamespace_impl.h',
     'renderer/drop_data_builder.cc',
     'renderer/drop_data_builder.h',
-    'renderer/external_popup_menu.cc',
-    'renderer/external_popup_menu.h',
     'renderer/fetchers/image_resource_fetcher.cc',
     'renderer/fetchers/image_resource_fetcher.h',
     'renderer/fetchers/multi_resolution_image_resource_fetcher.cc',
@@ -275,6 +273,8 @@
     'renderer/media/video_capture_impl_manager.h',
     'renderer/media/video_capture_message_filter.cc',
     'renderer/media/video_capture_message_filter.h',
+    'renderer/media/video_frame_compositor.cc',
+    'renderer/media/video_frame_compositor.h',
     'renderer/media/video_frame_provider.cc',
     'renderer/media/video_frame_provider.h',
     'renderer/media/webaudiosourceprovider_impl.cc',
@@ -565,6 +565,10 @@
         'renderer/webscrollbarbehavior_impl_gtkoraura.cc',
         'renderer/webscrollbarbehavior_impl_gtkoraura.h',
       ],
+      'sources': [
+        'renderer/external_popup_menu.cc',
+        'renderer/external_popup_menu.h',
+      ],
     }, {
       'sources!': [
         'renderer/webscrollbarbehavior_impl_mac.mm',
@@ -589,17 +593,22 @@
       ],
     }, {
       'dependencies': [
+        'content_common_mojo_bindings',
         '../mojo/mojo.gyp:mojo_environment_chromium',
         '../mojo/mojo.gyp:mojo_js_bindings_lib',
       ],
     }],
     ['OS=="android"', {
       'sources!': [
-        'renderer/accessibility/renderer_accessibility_focus_only.cc'
+        'renderer/accessibility/renderer_accessibility_focus_only.cc',
         'renderer/media/audio_decoder.cc',
         'renderer/media/filter_helpers.cc',
         'renderer/media/webmediaplayer_impl.cc',
       ],
+      'sources': [
+        'renderer/external_popup_menu.cc',
+        'renderer/external_popup_menu.h',
+      ],
       'dependencies': [
         '../third_party/libphonenumber/libphonenumber.gyp:libphonenumber',
       ],
@@ -698,10 +707,14 @@
         'renderer/media/video_source_handler.h',
         'renderer/media/webaudio_capturer_source.cc',
         'renderer/media/webaudio_capturer_source.h',
+        'renderer/media/webrtc/media_stream_track_metrics.cc',
+        'renderer/media/webrtc/media_stream_track_metrics.h',
         'renderer/media/webrtc/webrtc_audio_sink_adapter.cc',
         'renderer/media/webrtc/webrtc_audio_sink_adapter.h',
         'renderer/media/webrtc/webrtc_local_audio_track_adapter.cc',
         'renderer/media/webrtc/webrtc_local_audio_track_adapter.h',
+        'renderer/media/webrtc/webrtc_video_capturer_adapter.cc',
+        'renderer/media/webrtc/webrtc_video_capturer_adapter.h',
         'renderer/media/webrtc/webrtc_video_sink_adapter.cc',
         'renderer/media/webrtc/webrtc_video_sink_adapter.h',
         'renderer/media/webrtc_audio_capturer.cc',
@@ -722,8 +735,8 @@
         'renderer/media/webrtc_local_audio_track.h',
         'renderer/media/webrtc_logging.cc',
         'renderer/media/webrtc_logging.h',
-        'renderer/media/webrtc/webrtc_video_capturer_adapter.cc',
-        'renderer/media/webrtc/webrtc_video_capturer_adapter.h',
+        'renderer/media/webrtc_uma_histograms.cc',
+        'renderer/media/webrtc_uma_histograms.h',
         'renderer/p2p/host_address_request.cc',
         'renderer/p2p/host_address_request.h',
         'renderer/p2p/ipc_network_manager.cc',
diff --git a/content/content_renderer.target.darwin-arm.mk b/content/content_renderer.target.darwin-arm.mk
index 9918ec4..52e5542 100644
--- a/content/content_renderer.target.darwin-arm.mk
+++ b/content/content_renderer.target.darwin-arm.mk
@@ -52,7 +52,6 @@
 	content/renderer/accessibility/blink_ax_enum_conversion.cc \
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
-	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -81,7 +80,6 @@
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/drop_data_builder.cc \
-	content/renderer/external_popup_menu.cc \
 	content/renderer/fetchers/image_resource_fetcher.cc \
 	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
 	content/renderer/fetchers/resource_fetcher_impl.cc \
@@ -116,7 +114,6 @@
 	content/renderer/media/android/stream_texture_factory_android_impl.cc \
 	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
 	content/renderer/media/android/webmediaplayer_android.cc \
-	content/renderer/media/audio_decoder.cc \
 	content/renderer/media/audio_device_factory.cc \
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
@@ -140,6 +137,7 @@
 	content/renderer/media/video_capture_impl.cc \
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
 	content/renderer/media/video_frame_provider.cc \
 	content/renderer/media/webaudiosourceprovider_impl.cc \
 	content/renderer/media/webcontentdecryptionmodule_impl.cc \
@@ -199,6 +197,7 @@
 	content/renderer/webpublicsuffixlist_impl.cc \
 	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
 	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
 	content/renderer/media/webrtc_logging_noop.cc
 
 
@@ -264,9 +263,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -291,6 +288,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -428,9 +426,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -455,6 +451,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_renderer.target.darwin-mips.mk b/content/content_renderer.target.darwin-mips.mk
index 565d20d..dc5de74 100644
--- a/content/content_renderer.target.darwin-mips.mk
+++ b/content/content_renderer.target.darwin-mips.mk
@@ -52,7 +52,6 @@
 	content/renderer/accessibility/blink_ax_enum_conversion.cc \
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
-	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -81,7 +80,6 @@
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/drop_data_builder.cc \
-	content/renderer/external_popup_menu.cc \
 	content/renderer/fetchers/image_resource_fetcher.cc \
 	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
 	content/renderer/fetchers/resource_fetcher_impl.cc \
@@ -116,7 +114,6 @@
 	content/renderer/media/android/stream_texture_factory_android_impl.cc \
 	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
 	content/renderer/media/android/webmediaplayer_android.cc \
-	content/renderer/media/audio_decoder.cc \
 	content/renderer/media/audio_device_factory.cc \
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
@@ -140,6 +137,7 @@
 	content/renderer/media/video_capture_impl.cc \
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
 	content/renderer/media/video_frame_provider.cc \
 	content/renderer/media/webaudiosourceprovider_impl.cc \
 	content/renderer/media/webcontentdecryptionmodule_impl.cc \
@@ -199,6 +197,7 @@
 	content/renderer/webpublicsuffixlist_impl.cc \
 	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
 	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
 	content/renderer/media/webrtc_logging_noop.cc
 
 
@@ -263,9 +262,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -290,6 +287,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -426,9 +424,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -453,6 +449,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_renderer.target.darwin-x86.mk b/content/content_renderer.target.darwin-x86.mk
index acc78dc..fe20a7d 100644
--- a/content/content_renderer.target.darwin-x86.mk
+++ b/content/content_renderer.target.darwin-x86.mk
@@ -52,7 +52,6 @@
 	content/renderer/accessibility/blink_ax_enum_conversion.cc \
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
-	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -81,7 +80,6 @@
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/drop_data_builder.cc \
-	content/renderer/external_popup_menu.cc \
 	content/renderer/fetchers/image_resource_fetcher.cc \
 	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
 	content/renderer/fetchers/resource_fetcher_impl.cc \
@@ -116,7 +114,6 @@
 	content/renderer/media/android/stream_texture_factory_android_impl.cc \
 	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
 	content/renderer/media/android/webmediaplayer_android.cc \
-	content/renderer/media/audio_decoder.cc \
 	content/renderer/media/audio_device_factory.cc \
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
@@ -140,6 +137,7 @@
 	content/renderer/media/video_capture_impl.cc \
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
 	content/renderer/media/video_frame_provider.cc \
 	content/renderer/media/webaudiosourceprovider_impl.cc \
 	content/renderer/media/webcontentdecryptionmodule_impl.cc \
@@ -199,6 +197,7 @@
 	content/renderer/webpublicsuffixlist_impl.cc \
 	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
 	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
 	content/renderer/media/webrtc_logging_noop.cc
 
 
@@ -264,9 +263,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -291,6 +288,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -427,9 +425,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -454,6 +450,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_renderer.target.darwin-x86_64.mk b/content/content_renderer.target.darwin-x86_64.mk
new file mode 100644
index 0000000..53ee0c2
--- /dev/null
+++ b/content/content_renderer.target.darwin-x86_64.mk
@@ -0,0 +1,596 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,jingle_jingle_glue_gyp)/jingle_glue.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,GYP,third_party_widevine_cdm_widevine_cdm_version_h_gyp)/widevine_cdm_version_h.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_child_webkit_child_gyp)/webkit_child_webkit_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/renderer/android_content_detection_prefixes.cc \
+	content/public/renderer/content_renderer_client.cc \
+	content/public/renderer/document_state.cc \
+	content/public/renderer/history_item_serialization.cc \
+	content/public/renderer/key_system_info.cc \
+	content/public/renderer/navigation_state.cc \
+	content/public/renderer/render_frame_observer.cc \
+	content/public/renderer/render_process_observer.cc \
+	content/public/renderer/render_thread.cc \
+	content/public/renderer/render_view_observer.cc \
+	content/public/renderer/video_encode_accelerator.cc \
+	content/renderer/accessibility/accessibility_node_serializer.cc \
+	content/renderer/accessibility/blink_ax_enum_conversion.cc \
+	content/renderer/accessibility/renderer_accessibility.cc \
+	content/renderer/accessibility/renderer_accessibility_complete.cc \
+	content/renderer/android/address_detector.cc \
+	content/renderer/android/content_detector.cc \
+	content/renderer/android/email_detector.cc \
+	content/renderer/android/phone_number_detector.cc \
+	content/renderer/android/synchronous_compositor_factory.cc \
+	content/renderer/browser_plugin/browser_plugin.cc \
+	content/renderer/browser_plugin/browser_plugin_backing_store.cc \
+	content/renderer/browser_plugin/browser_plugin_bindings.cc \
+	content/renderer/browser_plugin/browser_plugin_manager_impl.cc \
+	content/renderer/browser_plugin/browser_plugin_manager.cc \
+	content/renderer/clipboard_utils.cc \
+	content/renderer/child_frame_compositing_helper.cc \
+	content/renderer/context_menu_params_builder.cc \
+	content/renderer/cursor_utils.cc \
+	content/renderer/date_time_suggestion_builder.cc \
+	content/renderer/device_orientation/device_motion_event_pump.cc \
+	content/renderer/device_orientation/device_orientation_event_pump.cc \
+	content/renderer/device_orientation/device_sensor_event_pump.cc \
+	content/renderer/devtools/devtools_agent.cc \
+	content/renderer/devtools/devtools_agent_filter.cc \
+	content/renderer/devtools/devtools_client.cc \
+	content/renderer/disambiguation_popup_helper.cc \
+	content/renderer/dom_automation_controller.cc \
+	content/renderer/dom_storage/dom_storage_cached_area.cc \
+	content/renderer/dom_storage/dom_storage_dispatcher.cc \
+	content/renderer/dom_storage/webstoragearea_impl.cc \
+	content/renderer/dom_storage/webstoragenamespace_impl.cc \
+	content/renderer/drop_data_builder.cc \
+	content/renderer/fetchers/image_resource_fetcher.cc \
+	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
+	content/renderer/fetchers/resource_fetcher_impl.cc \
+	content/renderer/gamepad_shared_memory_reader.cc \
+	content/renderer/geolocation_dispatcher.cc \
+	content/renderer/gpu/compositor_output_surface.cc \
+	content/renderer/gpu/compositor_software_output_device.cc \
+	content/renderer/gpu/delegated_compositor_output_surface.cc \
+	content/renderer/gpu/gpu_benchmarking_extension.cc \
+	content/renderer/gpu/mailbox_output_surface.cc \
+	content/renderer/gpu/render_widget_compositor.cc \
+	content/renderer/gpu/stream_texture_host_android.cc \
+	content/renderer/idle_user_detector.cc \
+	content/renderer/image_loading_helper.cc \
+	content/renderer/ime_event_guard.cc \
+	content/renderer/in_process_renderer_thread.cc \
+	content/renderer/input/input_event_filter.cc \
+	content/renderer/input/input_handler_manager.cc \
+	content/renderer/input/input_handler_proxy.cc \
+	content/renderer/input/input_handler_wrapper.cc \
+	content/renderer/internal_document_state_data.cc \
+	content/renderer/java/java_bridge_channel.cc \
+	content/renderer/java/java_bridge_dispatcher.cc \
+	content/renderer/load_progress_tracker.cc \
+	content/renderer/media/active_loader.cc \
+	content/renderer/media/android/audio_decoder_android.cc \
+	content/renderer/media/android/media_info_loader.cc \
+	content/renderer/media/android/media_source_delegate.cc \
+	content/renderer/media/android/proxy_media_keys.cc \
+	content/renderer/media/android/renderer_demuxer_android.cc \
+	content/renderer/media/android/renderer_media_player_manager.cc \
+	content/renderer/media/android/stream_texture_factory_android_impl.cc \
+	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
+	content/renderer/media/android/webmediaplayer_android.cc \
+	content/renderer/media/audio_device_factory.cc \
+	content/renderer/media/audio_input_message_filter.cc \
+	content/renderer/media/audio_message_filter.cc \
+	content/renderer/media/audio_renderer_mixer_manager.cc \
+	content/renderer/media/buffered_data_source.cc \
+	content/renderer/media/buffered_resource_loader.cc \
+	content/renderer/media/cache_util.cc \
+	content/renderer/media/cdm_session_adapter.cc \
+	content/renderer/media/crypto/content_decryption_module_factory.cc \
+	content/renderer/media/crypto/key_systems.cc \
+	content/renderer/media/crypto/key_systems_support_uma.cc \
+	content/renderer/media/crypto/pepper_cdm_wrapper_impl.cc \
+	content/renderer/media/crypto/proxy_decryptor.cc \
+	content/renderer/media/midi_dispatcher.cc \
+	content/renderer/media/midi_message_filter.cc \
+	content/renderer/media/render_media_log.cc \
+	content/renderer/media/renderer_gpu_video_accelerator_factories.cc \
+	content/renderer/media/renderer_webaudiodevice_impl.cc \
+	content/renderer/media/renderer_webmidiaccessor_impl.cc \
+	content/renderer/media/texttrack_impl.cc \
+	content/renderer/media/video_capture_impl.cc \
+	content/renderer/media/video_capture_impl_manager.cc \
+	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
+	content/renderer/media/video_frame_provider.cc \
+	content/renderer/media/webaudiosourceprovider_impl.cc \
+	content/renderer/media/webcontentdecryptionmodule_impl.cc \
+	content/renderer/media/webcontentdecryptionmodulesession_impl.cc \
+	content/renderer/media/webinbandtexttrack_impl.cc \
+	content/renderer/media/webmediaplayer_ms.cc \
+	content/renderer/media/webmediaplayer_params.cc \
+	content/renderer/media/webmediaplayer_util.cc \
+	content/renderer/media/webmediasource_impl.cc \
+	content/renderer/media/websourcebuffer_impl.cc \
+	content/renderer/memory_benchmarking_extension.cc \
+	content/renderer/menu_item_builder.cc \
+	content/renderer/mhtml_generator.cc \
+	content/renderer/mouse_lock_dispatcher.cc \
+	content/renderer/paint_aggregator.cc \
+	content/renderer/render_frame_impl.cc \
+	content/renderer/render_process_impl.cc \
+	content/renderer/render_thread_impl.cc \
+	content/renderer/render_view_impl.cc \
+	content/renderer/render_view_impl_android.cc \
+	content/renderer/render_view_impl_params.cc \
+	content/renderer/render_view_linux.cc \
+	content/renderer/render_view_mouse_lock_dispatcher.cc \
+	content/renderer/render_widget.cc \
+	content/renderer/render_widget_fullscreen.cc \
+	content/renderer/renderer_clipboard_client.cc \
+	content/renderer/renderer_date_time_picker.cc \
+	content/renderer/renderer_main.cc \
+	content/renderer/renderer_main_platform_delegate_android.cc \
+	content/renderer/renderer_webapplicationcachehost_impl.cc \
+	content/renderer/renderer_webcolorchooser_impl.cc \
+	content/renderer/renderer_webcookiejar_impl.cc \
+	content/renderer/renderer_webkitplatformsupport_impl.cc \
+	content/renderer/resizing_mode_selector.cc \
+	content/renderer/sad_plugin.cc \
+	content/renderer/savable_resources.cc \
+	content/renderer/screen_orientation/screen_orientation_dispatcher.cc \
+	content/renderer/scoped_clipboard_writer_glue.cc \
+	content/renderer/service_worker/embedded_worker_context_client.cc \
+	content/renderer/service_worker/embedded_worker_context_message_filter.cc \
+	content/renderer/service_worker/embedded_worker_dispatcher.cc \
+	content/renderer/service_worker/service_worker_script_context.cc \
+	content/renderer/shared_memory_seqlock_reader.cc \
+	content/renderer/shared_worker_repository.cc \
+	content/renderer/shared_worker/embedded_shared_worker_stub.cc \
+	content/renderer/skia_benchmarking_extension.cc \
+	content/renderer/speech_recognition_dispatcher.cc \
+	content/renderer/stats_collection_controller.cc \
+	content/renderer/stats_collection_observer.cc \
+	content/renderer/text_input_client_observer.cc \
+	content/renderer/v8_value_converter_impl.cc \
+	content/renderer/web_preferences.cc \
+	content/renderer/web_ui_extension.cc \
+	content/renderer/web_ui_extension_data.cc \
+	content/renderer/webclipboard_impl.cc \
+	content/renderer/webgraphicscontext3d_provider_impl.cc \
+	content/renderer/webpublicsuffixlist_impl.cc \
+	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
+	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
+	content/renderer/media/webrtc_logging_noop.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	skia_skia_library_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	webkit_child_webkit_child_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: content_renderer
+content_renderer: content_content_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_renderer.target.linux-arm.mk b/content/content_renderer.target.linux-arm.mk
index 9918ec4..52e5542 100644
--- a/content/content_renderer.target.linux-arm.mk
+++ b/content/content_renderer.target.linux-arm.mk
@@ -52,7 +52,6 @@
 	content/renderer/accessibility/blink_ax_enum_conversion.cc \
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
-	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -81,7 +80,6 @@
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/drop_data_builder.cc \
-	content/renderer/external_popup_menu.cc \
 	content/renderer/fetchers/image_resource_fetcher.cc \
 	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
 	content/renderer/fetchers/resource_fetcher_impl.cc \
@@ -116,7 +114,6 @@
 	content/renderer/media/android/stream_texture_factory_android_impl.cc \
 	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
 	content/renderer/media/android/webmediaplayer_android.cc \
-	content/renderer/media/audio_decoder.cc \
 	content/renderer/media/audio_device_factory.cc \
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
@@ -140,6 +137,7 @@
 	content/renderer/media/video_capture_impl.cc \
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
 	content/renderer/media/video_frame_provider.cc \
 	content/renderer/media/webaudiosourceprovider_impl.cc \
 	content/renderer/media/webcontentdecryptionmodule_impl.cc \
@@ -199,6 +197,7 @@
 	content/renderer/webpublicsuffixlist_impl.cc \
 	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
 	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
 	content/renderer/media/webrtc_logging_noop.cc
 
 
@@ -264,9 +263,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -291,6 +288,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -428,9 +426,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -455,6 +451,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_renderer.target.linux-mips.mk b/content/content_renderer.target.linux-mips.mk
index 565d20d..dc5de74 100644
--- a/content/content_renderer.target.linux-mips.mk
+++ b/content/content_renderer.target.linux-mips.mk
@@ -52,7 +52,6 @@
 	content/renderer/accessibility/blink_ax_enum_conversion.cc \
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
-	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -81,7 +80,6 @@
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/drop_data_builder.cc \
-	content/renderer/external_popup_menu.cc \
 	content/renderer/fetchers/image_resource_fetcher.cc \
 	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
 	content/renderer/fetchers/resource_fetcher_impl.cc \
@@ -116,7 +114,6 @@
 	content/renderer/media/android/stream_texture_factory_android_impl.cc \
 	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
 	content/renderer/media/android/webmediaplayer_android.cc \
-	content/renderer/media/audio_decoder.cc \
 	content/renderer/media/audio_device_factory.cc \
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
@@ -140,6 +137,7 @@
 	content/renderer/media/video_capture_impl.cc \
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
 	content/renderer/media/video_frame_provider.cc \
 	content/renderer/media/webaudiosourceprovider_impl.cc \
 	content/renderer/media/webcontentdecryptionmodule_impl.cc \
@@ -199,6 +197,7 @@
 	content/renderer/webpublicsuffixlist_impl.cc \
 	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
 	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
 	content/renderer/media/webrtc_logging_noop.cc
 
 
@@ -263,9 +262,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -290,6 +287,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -426,9 +424,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -453,6 +449,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_renderer.target.linux-x86.mk b/content/content_renderer.target.linux-x86.mk
index acc78dc..fe20a7d 100644
--- a/content/content_renderer.target.linux-x86.mk
+++ b/content/content_renderer.target.linux-x86.mk
@@ -52,7 +52,6 @@
 	content/renderer/accessibility/blink_ax_enum_conversion.cc \
 	content/renderer/accessibility/renderer_accessibility.cc \
 	content/renderer/accessibility/renderer_accessibility_complete.cc \
-	content/renderer/accessibility/renderer_accessibility_focus_only.cc \
 	content/renderer/android/address_detector.cc \
 	content/renderer/android/content_detector.cc \
 	content/renderer/android/email_detector.cc \
@@ -81,7 +80,6 @@
 	content/renderer/dom_storage/webstoragearea_impl.cc \
 	content/renderer/dom_storage/webstoragenamespace_impl.cc \
 	content/renderer/drop_data_builder.cc \
-	content/renderer/external_popup_menu.cc \
 	content/renderer/fetchers/image_resource_fetcher.cc \
 	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
 	content/renderer/fetchers/resource_fetcher_impl.cc \
@@ -116,7 +114,6 @@
 	content/renderer/media/android/stream_texture_factory_android_impl.cc \
 	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
 	content/renderer/media/android/webmediaplayer_android.cc \
-	content/renderer/media/audio_decoder.cc \
 	content/renderer/media/audio_device_factory.cc \
 	content/renderer/media/audio_input_message_filter.cc \
 	content/renderer/media/audio_message_filter.cc \
@@ -140,6 +137,7 @@
 	content/renderer/media/video_capture_impl.cc \
 	content/renderer/media/video_capture_impl_manager.cc \
 	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
 	content/renderer/media/video_frame_provider.cc \
 	content/renderer/media/webaudiosourceprovider_impl.cc \
 	content/renderer/media/webcontentdecryptionmodule_impl.cc \
@@ -199,6 +197,7 @@
 	content/renderer/webpublicsuffixlist_impl.cc \
 	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
 	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
 	content/renderer/media/webrtc_logging_noop.cc
 
 
@@ -264,9 +263,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -291,6 +288,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
@@ -427,9 +425,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -454,6 +450,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-D__GNU_SOURCE=1' \
diff --git a/content/content_renderer.target.linux-x86_64.mk b/content/content_renderer.target.linux-x86_64.mk
new file mode 100644
index 0000000..53ee0c2
--- /dev/null
+++ b/content/content_renderer.target.linux-x86_64.mk
@@ -0,0 +1,596 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_renderer_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,content_content_resources_gyp)/content_resources.stamp \
+	$(call intermediates-dir-for,GYP,jingle_jingle_glue_gyp)/jingle_glue.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,third_party_npapi_npapi_gyp)/npapi.stamp \
+	$(call intermediates-dir-for,GYP,third_party_widevine_cdm_widevine_cdm_version_h_gyp)/widevine_cdm_version_h.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_accessibility_gyp)/ui_accessibility_accessibility_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,webkit_child_webkit_child_gyp)/webkit_child_webkit_child_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/renderer/android_content_detection_prefixes.cc \
+	content/public/renderer/content_renderer_client.cc \
+	content/public/renderer/document_state.cc \
+	content/public/renderer/history_item_serialization.cc \
+	content/public/renderer/key_system_info.cc \
+	content/public/renderer/navigation_state.cc \
+	content/public/renderer/render_frame_observer.cc \
+	content/public/renderer/render_process_observer.cc \
+	content/public/renderer/render_thread.cc \
+	content/public/renderer/render_view_observer.cc \
+	content/public/renderer/video_encode_accelerator.cc \
+	content/renderer/accessibility/accessibility_node_serializer.cc \
+	content/renderer/accessibility/blink_ax_enum_conversion.cc \
+	content/renderer/accessibility/renderer_accessibility.cc \
+	content/renderer/accessibility/renderer_accessibility_complete.cc \
+	content/renderer/android/address_detector.cc \
+	content/renderer/android/content_detector.cc \
+	content/renderer/android/email_detector.cc \
+	content/renderer/android/phone_number_detector.cc \
+	content/renderer/android/synchronous_compositor_factory.cc \
+	content/renderer/browser_plugin/browser_plugin.cc \
+	content/renderer/browser_plugin/browser_plugin_backing_store.cc \
+	content/renderer/browser_plugin/browser_plugin_bindings.cc \
+	content/renderer/browser_plugin/browser_plugin_manager_impl.cc \
+	content/renderer/browser_plugin/browser_plugin_manager.cc \
+	content/renderer/clipboard_utils.cc \
+	content/renderer/child_frame_compositing_helper.cc \
+	content/renderer/context_menu_params_builder.cc \
+	content/renderer/cursor_utils.cc \
+	content/renderer/date_time_suggestion_builder.cc \
+	content/renderer/device_orientation/device_motion_event_pump.cc \
+	content/renderer/device_orientation/device_orientation_event_pump.cc \
+	content/renderer/device_orientation/device_sensor_event_pump.cc \
+	content/renderer/devtools/devtools_agent.cc \
+	content/renderer/devtools/devtools_agent_filter.cc \
+	content/renderer/devtools/devtools_client.cc \
+	content/renderer/disambiguation_popup_helper.cc \
+	content/renderer/dom_automation_controller.cc \
+	content/renderer/dom_storage/dom_storage_cached_area.cc \
+	content/renderer/dom_storage/dom_storage_dispatcher.cc \
+	content/renderer/dom_storage/webstoragearea_impl.cc \
+	content/renderer/dom_storage/webstoragenamespace_impl.cc \
+	content/renderer/drop_data_builder.cc \
+	content/renderer/fetchers/image_resource_fetcher.cc \
+	content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc \
+	content/renderer/fetchers/resource_fetcher_impl.cc \
+	content/renderer/gamepad_shared_memory_reader.cc \
+	content/renderer/geolocation_dispatcher.cc \
+	content/renderer/gpu/compositor_output_surface.cc \
+	content/renderer/gpu/compositor_software_output_device.cc \
+	content/renderer/gpu/delegated_compositor_output_surface.cc \
+	content/renderer/gpu/gpu_benchmarking_extension.cc \
+	content/renderer/gpu/mailbox_output_surface.cc \
+	content/renderer/gpu/render_widget_compositor.cc \
+	content/renderer/gpu/stream_texture_host_android.cc \
+	content/renderer/idle_user_detector.cc \
+	content/renderer/image_loading_helper.cc \
+	content/renderer/ime_event_guard.cc \
+	content/renderer/in_process_renderer_thread.cc \
+	content/renderer/input/input_event_filter.cc \
+	content/renderer/input/input_handler_manager.cc \
+	content/renderer/input/input_handler_proxy.cc \
+	content/renderer/input/input_handler_wrapper.cc \
+	content/renderer/internal_document_state_data.cc \
+	content/renderer/java/java_bridge_channel.cc \
+	content/renderer/java/java_bridge_dispatcher.cc \
+	content/renderer/load_progress_tracker.cc \
+	content/renderer/media/active_loader.cc \
+	content/renderer/media/android/audio_decoder_android.cc \
+	content/renderer/media/android/media_info_loader.cc \
+	content/renderer/media/android/media_source_delegate.cc \
+	content/renderer/media/android/proxy_media_keys.cc \
+	content/renderer/media/android/renderer_demuxer_android.cc \
+	content/renderer/media/android/renderer_media_player_manager.cc \
+	content/renderer/media/android/stream_texture_factory_android_impl.cc \
+	content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc \
+	content/renderer/media/android/webmediaplayer_android.cc \
+	content/renderer/media/audio_device_factory.cc \
+	content/renderer/media/audio_input_message_filter.cc \
+	content/renderer/media/audio_message_filter.cc \
+	content/renderer/media/audio_renderer_mixer_manager.cc \
+	content/renderer/media/buffered_data_source.cc \
+	content/renderer/media/buffered_resource_loader.cc \
+	content/renderer/media/cache_util.cc \
+	content/renderer/media/cdm_session_adapter.cc \
+	content/renderer/media/crypto/content_decryption_module_factory.cc \
+	content/renderer/media/crypto/key_systems.cc \
+	content/renderer/media/crypto/key_systems_support_uma.cc \
+	content/renderer/media/crypto/pepper_cdm_wrapper_impl.cc \
+	content/renderer/media/crypto/proxy_decryptor.cc \
+	content/renderer/media/midi_dispatcher.cc \
+	content/renderer/media/midi_message_filter.cc \
+	content/renderer/media/render_media_log.cc \
+	content/renderer/media/renderer_gpu_video_accelerator_factories.cc \
+	content/renderer/media/renderer_webaudiodevice_impl.cc \
+	content/renderer/media/renderer_webmidiaccessor_impl.cc \
+	content/renderer/media/texttrack_impl.cc \
+	content/renderer/media/video_capture_impl.cc \
+	content/renderer/media/video_capture_impl_manager.cc \
+	content/renderer/media/video_capture_message_filter.cc \
+	content/renderer/media/video_frame_compositor.cc \
+	content/renderer/media/video_frame_provider.cc \
+	content/renderer/media/webaudiosourceprovider_impl.cc \
+	content/renderer/media/webcontentdecryptionmodule_impl.cc \
+	content/renderer/media/webcontentdecryptionmodulesession_impl.cc \
+	content/renderer/media/webinbandtexttrack_impl.cc \
+	content/renderer/media/webmediaplayer_ms.cc \
+	content/renderer/media/webmediaplayer_params.cc \
+	content/renderer/media/webmediaplayer_util.cc \
+	content/renderer/media/webmediasource_impl.cc \
+	content/renderer/media/websourcebuffer_impl.cc \
+	content/renderer/memory_benchmarking_extension.cc \
+	content/renderer/menu_item_builder.cc \
+	content/renderer/mhtml_generator.cc \
+	content/renderer/mouse_lock_dispatcher.cc \
+	content/renderer/paint_aggregator.cc \
+	content/renderer/render_frame_impl.cc \
+	content/renderer/render_process_impl.cc \
+	content/renderer/render_thread_impl.cc \
+	content/renderer/render_view_impl.cc \
+	content/renderer/render_view_impl_android.cc \
+	content/renderer/render_view_impl_params.cc \
+	content/renderer/render_view_linux.cc \
+	content/renderer/render_view_mouse_lock_dispatcher.cc \
+	content/renderer/render_widget.cc \
+	content/renderer/render_widget_fullscreen.cc \
+	content/renderer/renderer_clipboard_client.cc \
+	content/renderer/renderer_date_time_picker.cc \
+	content/renderer/renderer_main.cc \
+	content/renderer/renderer_main_platform_delegate_android.cc \
+	content/renderer/renderer_webapplicationcachehost_impl.cc \
+	content/renderer/renderer_webcolorchooser_impl.cc \
+	content/renderer/renderer_webcookiejar_impl.cc \
+	content/renderer/renderer_webkitplatformsupport_impl.cc \
+	content/renderer/resizing_mode_selector.cc \
+	content/renderer/sad_plugin.cc \
+	content/renderer/savable_resources.cc \
+	content/renderer/screen_orientation/screen_orientation_dispatcher.cc \
+	content/renderer/scoped_clipboard_writer_glue.cc \
+	content/renderer/service_worker/embedded_worker_context_client.cc \
+	content/renderer/service_worker/embedded_worker_context_message_filter.cc \
+	content/renderer/service_worker/embedded_worker_dispatcher.cc \
+	content/renderer/service_worker/service_worker_script_context.cc \
+	content/renderer/shared_memory_seqlock_reader.cc \
+	content/renderer/shared_worker_repository.cc \
+	content/renderer/shared_worker/embedded_shared_worker_stub.cc \
+	content/renderer/skia_benchmarking_extension.cc \
+	content/renderer/speech_recognition_dispatcher.cc \
+	content/renderer/stats_collection_controller.cc \
+	content/renderer/stats_collection_observer.cc \
+	content/renderer/text_input_client_observer.cc \
+	content/renderer/v8_value_converter_impl.cc \
+	content/renderer/web_preferences.cc \
+	content/renderer/web_ui_extension.cc \
+	content/renderer/web_ui_extension_data.cc \
+	content/renderer/webclipboard_impl.cc \
+	content/renderer/webgraphicscontext3d_provider_impl.cc \
+	content/renderer/webpublicsuffixlist_impl.cc \
+	content/renderer/webscrollbarbehavior_impl_gtkoraura.cc \
+	content/renderer/websharedworker_proxy.cc \
+	content/renderer/external_popup_menu.cc \
+	content/renderer/media/webrtc_logging_noop.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DANDROID' \
+	'-DPOSIX' \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(gyp_shared_intermediate_dir)/content \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures \
+	skia_skia_library_gyp \
+	ui_accessibility_accessibility_gyp \
+	ui_accessibility_ax_gen_gyp \
+	webkit_child_webkit_child_gyp \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_renderer_gyp
+
+# Alias gyp target name.
+.PHONY: content_renderer
+content_renderer: content_content_renderer_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_resources.grd b/content/content_resources.grd
index 806f28d..39e5874 100644
--- a/content/content_resources.grd
+++ b/content/content_resources.grd
@@ -34,8 +34,11 @@
         <include name="IDR_RENDERER_SANDBOX_PROFILE" file="renderer/renderer.sb" type="BINDATA" />
         <include name="IDR_UTILITY_SANDBOX_PROFILE" file="utility/utility.sb" type="BINDATA" />
       </if>
-      <if expr="is_android">
-        <include name="IDR_MEDIAPLAYER_REMOTE_PLAYBACK_ICON" file="renderer/resources/media/mediaplayer_remote_playback.png" type="BINDATA" />
+      <if expr="use_mojo">
+        <include name="IDR_MOJO_CODEC_JS" file="../mojo/public/bindings/js/codec.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_MOJO_CONNECTION_JS" file="../mojo/public/bindings/js/connection.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_MOJO_CONNECTOR_JS" file="../mojo/public/bindings/js/connector.js" flattenhtml="true" type="BINDATA" />
+        <include name="IDR_MOJO_ROUTER_JS" file="../mojo/public/bindings/js/router.js" flattenhtml="true" type="BINDATA" />
       </if>
     </includes>
   </release>
diff --git a/content/content_resources.target.darwin-arm.mk b/content/content_resources.target.darwin-arm.mk
index 4908da1..93b2936 100644
--- a/content/content_resources.target.darwin-arm.mk
+++ b/content/content_resources.target.darwin-arm.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/content/renderer/resources/media/mediaplayer_remote_playback.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/content/content_resources.target.darwin-mips.mk b/content/content_resources.target.darwin-mips.mk
index 4908da1..93b2936 100644
--- a/content/content_resources.target.darwin-mips.mk
+++ b/content/content_resources.target.darwin-mips.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/content/renderer/resources/media/mediaplayer_remote_playback.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/content/content_resources.target.darwin-x86.mk b/content/content_resources.target.darwin-x86.mk
index 24ccdee..93b2936 100644
--- a/content/content_resources.target.darwin-x86.mk
+++ b/content/content_resources.target.darwin-x86.mk
@@ -18,9 +18,9 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/content/renderer/resources/media/mediaplayer_remote_playback.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
 $(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
diff --git a/content/content_resources.target.darwin-x86_64.mk b/content/content_resources.target.darwin-x86_64.mk
new file mode 100644
index 0000000..93b2936
--- /dev/null
+++ b/content/content_resources.target.darwin-x86_64.mk
@@ -0,0 +1,63 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_resources_gyp
+LOCAL_MODULE_STEM := content_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_content_resources":
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+$(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+
+
+### Generated for copy rule.
+$(gyp_shared_intermediate_dir)/content_resources.pak: $(gyp_shared_intermediate_dir)/content/content_resources.pak $(GYP_TARGET_DEPENDENCIES) | $(ACP)
+	@echo Copying: $@
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(ACP) -rpf $< $@
+
+content_content_resources_gyp_content_resources_target_copies = $(gyp_shared_intermediate_dir)/content_resources.pak
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/grit/content_resources.h \
+	$(gyp_shared_intermediate_dir)/content/content_resources.pak \
+	$(gyp_shared_intermediate_dir)/content/content_resources.rc \
+	$(content_content_resources_gyp_content_resources_target_copies)
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_resources_gyp
+
+# Alias gyp target name.
+.PHONY: content_resources
+content_resources: content_content_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_resources.target.linux-arm.mk b/content/content_resources.target.linux-arm.mk
index 4908da1..93b2936 100644
--- a/content/content_resources.target.linux-arm.mk
+++ b/content/content_resources.target.linux-arm.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/content/renderer/resources/media/mediaplayer_remote_playback.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/content/content_resources.target.linux-mips.mk b/content/content_resources.target.linux-mips.mk
index 4908da1..93b2936 100644
--- a/content/content_resources.target.linux-mips.mk
+++ b/content/content_resources.target.linux-mips.mk
@@ -18,7 +18,7 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/content/renderer/resources/media/mediaplayer_remote_playback.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/content/content_resources.target.linux-x86.mk b/content/content_resources.target.linux-x86.mk
index 24ccdee..93b2936 100644
--- a/content/content_resources.target.linux-x86.mk
+++ b/content/content_resources.target.linux-x86.mk
@@ -18,9 +18,9 @@
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/content/renderer/resources/media/mediaplayer_remote_playback.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
 $(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
diff --git a/content/content_resources.target.linux-x86_64.mk b/content/content_resources.target.linux-x86_64.mk
new file mode 100644
index 0000000..93b2936
--- /dev/null
+++ b/content/content_resources.target.linux-x86_64.mk
@@ -0,0 +1,63 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_content_resources_gyp
+LOCAL_MODULE_STEM := content_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_content_resources":
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/grit/content_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/content/content_resources.grd $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.css $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.html $(LOCAL_PATH)/content/browser/resources/accessibility/accessibility.js $(LOCAL_PATH)/content/browser/resources/gpu/browser_bridge.js $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.html $(LOCAL_PATH)/content/browser/resources/gpu/gpu_internals.js $(LOCAL_PATH)/content/browser/resources/gpu/info_view.css $(LOCAL_PATH)/content/browser/resources/gpu/info_view.html $(LOCAL_PATH)/content/browser/resources/gpu/info_view.js $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.css $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.html $(LOCAL_PATH)/content/browser/resources/indexed_db/indexeddb_internals.js $(LOCAL_PATH)/content/browser/resources/media/cache_entry.js $(LOCAL_PATH)/content/browser/resources/media/client_renderer.js $(LOCAL_PATH)/content/browser/resources/media/data_series.js $(LOCAL_PATH)/content/browser/resources/media/disjoint_range_set.js $(LOCAL_PATH)/content/browser/resources/media/dump_creator.js $(LOCAL_PATH)/content/browser/resources/media/main.js $(LOCAL_PATH)/content/browser/resources/media/manager.js $(LOCAL_PATH)/content/browser/resources/media/media_internals.css $(LOCAL_PATH)/content/browser/resources/media/media_internals.html $(LOCAL_PATH)/content/browser/resources/media/media_internals.js $(LOCAL_PATH)/content/browser/resources/media/peer_connection_update_table.js $(LOCAL_PATH)/content/browser/resources/media/player_info.js $(LOCAL_PATH)/content/browser/resources/media/ssrc_info_manager.js $(LOCAL_PATH)/content/browser/resources/media/stats_graph_helper.js $(LOCAL_PATH)/content/browser/resources/media/stats_table.js $(LOCAL_PATH)/content/browser/resources/media/tab_view.js $(LOCAL_PATH)/content/browser/resources/media/timeline_graph_view.js $(LOCAL_PATH)/content/browser/resources/media/util.js $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.css $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.html $(LOCAL_PATH)/content/browser/resources/media/webrtc_internals.js $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.css $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.html $(LOCAL_PATH)/content/browser/resources/service_worker/serviceworker_internals.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from content_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/grit $(gyp_shared_intermediate_dir)/content; python ../tools/grit/grit.py -i content_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/content" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/content/content_resources.pak: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+$(gyp_shared_intermediate_dir)/content/content_resources.rc: $(gyp_shared_intermediate_dir)/content/grit/content_resources.h ;
+
+
+### Generated for copy rule.
+$(gyp_shared_intermediate_dir)/content_resources.pak: $(gyp_shared_intermediate_dir)/content/content_resources.pak $(GYP_TARGET_DEPENDENCIES) | $(ACP)
+	@echo Copying: $@
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(ACP) -rpf $< $@
+
+content_content_resources_gyp_content_resources_target_copies = $(gyp_shared_intermediate_dir)/content_resources.pak
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/grit/content_resources.h \
+	$(gyp_shared_intermediate_dir)/content/content_resources.pak \
+	$(gyp_shared_intermediate_dir)/content/content_resources.rc \
+	$(content_content_resources_gyp_content_resources_target_copies)
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_resources_gyp
+
+# Alias gyp target name.
+.PHONY: content_resources
+content_resources: content_content_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/content_shell.gypi b/content/content_shell.gypi
index 9290d49..5879e2d 100644
--- a/content/content_shell.gypi
+++ b/content/content_shell.gypi
@@ -173,12 +173,6 @@
         'shell/renderer/shell_render_process_observer.h',
         'shell/renderer/shell_render_view_observer.cc',
         'shell/renderer/shell_render_view_observer.h',
-        'shell/renderer/test_runner/CppBoundClass.cpp',
-        'shell/renderer/test_runner/CppBoundClass.h',
-        'shell/renderer/test_runner/CppVariant.cpp',
-        'shell/renderer/test_runner/CppVariant.h',
-        'shell/renderer/test_runner/EventSender.cpp',
-        'shell/renderer/test_runner/EventSender.h',
         'shell/renderer/test_runner/KeyCodeMapping.cpp',
         'shell/renderer/test_runner/KeyCodeMapping.h',
         'shell/renderer/test_runner/MockColorChooser.cpp',
@@ -232,6 +226,8 @@
         'shell/renderer/test_runner/WebUserMediaClientMock.h',
         'shell/renderer/test_runner/accessibility_controller.cc',
         'shell/renderer/test_runner/accessibility_controller.h',
+        'shell/renderer/test_runner/event_sender.cc',
+        'shell/renderer/test_runner/event_sender.h',
         'shell/renderer/test_runner/gamepad_controller.cc',
         'shell/renderer/test_runner/gamepad_controller.h',
         'shell/renderer/test_runner/notification_presenter.cc',
@@ -315,8 +311,8 @@
             '../components/components.gyp:breakpad_host',
           ],
         }],
-        # TODO(dmikurube): Kill linux_use_tcmalloc. http://crbug.com/345554
-        ['(os_posix==1 and use_aura==1 and ((use_allocator!="none" and use_allocator!="see_use_tcmalloc") or (use_allocator=="see_use_tcmalloc" and linux_use_tcmalloc==1))) or (android_use_tcmalloc==1)', {
+        # TODO(dmikurube): Kill {linux|android}_use_tcmalloc. http://crbug.com/345554
+        ['(use_allocator!="none" and use_allocator!="see_use_tcmalloc") or (use_allocator=="see_use_tcmalloc" and ((OS=="linux" and os_posix==1 and use_aura==1 and linux_use_tcmalloc==1) or (OS=="android" and android_use_tcmalloc==1)))', {
           'dependencies': [
             # This is needed by content/app/content_main_runner.cc
             '../base/allocator/allocator.gyp:allocator',
@@ -477,9 +473,6 @@
           ],
         }],
       ],
-      'variables': {
-        'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
-      },
       'actions': [
         {
           'action_name': 'repack_content_shell_pack',
@@ -497,29 +490,20 @@
               '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_resources_100_percent.pak',
               '<(SHARED_INTERMEDIATE_DIR)/webkit/webkit_strings_en-US.pak',
             ],
+            'conditions': [
+              ['OS!="android"', {
+                'variables': {
+                  'pak_inputs': [
+                    '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak',
+                  ],
+                },
+                'pak_output': '<(PRODUCT_DIR)/content_shell.pak',
+              }, {
+                'pak_output': '<(PRODUCT_DIR)/content_shell/assets/content_shell.pak',
+              }],
+            ],
           },
-          'inputs': [
-            '<(repack_path)',
-            '<@(pak_inputs)',
-          ],
-          'action': ['python', '<(repack_path)', '<@(_outputs)',
-                     '<@(pak_inputs)'],
-          'conditions': [
-            ['OS!="android"', {
-              'variables': {
-                'pak_inputs': [
-                  '<(SHARED_INTERMEDIATE_DIR)/webkit/devtools_resources.pak',
-                ],
-              },
-              'outputs': [
-                '<(PRODUCT_DIR)/content_shell.pak',
-              ],
-            }, {
-              'outputs': [
-                '<(PRODUCT_DIR)/content_shell/assets/content_shell.pak',
-              ],
-            }],
-          ],
+          'includes': [ '../build/repack_action.gypi' ],
         },
       ],
     },
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 9ff409a..e1fe546 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -517,6 +517,7 @@
         'child/power_monitor_broadcast_source_unittest.cc',
         'child/resource_dispatcher_unittest.cc',
         'child/site_isolation_policy_unittest.cc',
+        'child/touch_fling_gesture_curve_unittest.cc',
         'child/webcrypto/shared_crypto_unittest.cc',
         'child/worker_task_runner_unittest.cc',
         'common/android/address_parser_unittest.cc',
@@ -561,14 +562,17 @@
         'renderer/media/crypto/key_systems_unittest.cc',
         'renderer/media/media_stream_video_capture_source_unittest.cc',
         'renderer/media/media_stream_video_source_unittest.cc',
+        'renderer/media/media_stream_video_track_unittest.cc',
         'renderer/media/mock_media_stream_video_source.cc',
         'renderer/media/mock_media_stream_video_source.h',
+        'renderer/media/render_media_log_unittest.cc',
         'renderer/media/test_response_generator.cc',
         'renderer/media/test_response_generator.h',
         'renderer/media/video_capture_impl_manager_unittest.cc',
         'renderer/media/video_capture_impl_unittest.cc',
         'renderer/media/video_capture_message_filter_unittest.cc',
         'renderer/media/video_destination_handler_unittest.cc',
+        'renderer/media/video_frame_compositor_unittest.cc',
         'renderer/media/webaudiosourceprovider_impl_unittest.cc',
         'renderer/npapi/webplugin_impl_unittest.cc',
         'renderer/paint_aggregator_unittest.cc',
@@ -630,7 +634,6 @@
         '../webkit/browser/fileapi/sandbox_prioritized_origin_database_unittest.cc',
         '../webkit/browser/fileapi/timed_task_helper_unittest.cc',
         '../webkit/child/multipart_response_delegate_unittest.cc',
-        '../webkit/child/touch_fling_gesture_curve_unittest.cc',
         '../webkit/common/blob/shareable_file_reference_unittest.cc',
         '../webkit/common/database/database_connections_unittest.cc',
         '../webkit/common/database/database_identifier_unittest.cc',
@@ -720,6 +723,7 @@
             'renderer/media/rtc_peer_connection_handler_unittest.cc',
             'renderer/media/rtc_video_decoder_unittest.cc',
             'renderer/media/video_source_handler_unittest.cc',
+            'renderer/media/webrtc/media_stream_track_metrics_unittest.cc',
             'renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc',
             'renderer/media/webrtc/webrtc_video_capturer_adapter_unittest.cc',
             'renderer/media/webrtc_audio_capturer_unittest.cc',
@@ -727,6 +731,7 @@
             'renderer/media/webrtc_identity_service_unittest.cc',
             'renderer/media/webrtc_local_audio_source_provider_unittest.cc',
             'renderer/media/webrtc_local_audio_track_unittest.cc',
+            'renderer/media/webrtc_uma_histograms_unittest.cc',
           ],
           'dependencies': [
             '../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
@@ -907,16 +912,35 @@
             'content.gyp:content_browser',
             '../skia/skia.gyp:skia',
             '../testing/gtest.gyp:gtest',
-            '../ui/accessibility/accessibility.gyp:ax_gen',
           ],
           'sources': [
-            'test/accessibility_browser_test_utils.cc',
-            'test/accessibility_browser_test_utils.h',
-            'test/content_browser_test.cc',
-            'test/content_browser_test.h',
-            'test/content_browser_test_utils.cc',
-            'test/content_browser_test_utils.h',
-            'test/content_browser_test_utils_mac.mm',
+            'test/content_test_launcher.cc',
+            'public/test/content_browser_test.cc',
+            'public/test/content_browser_test.h',
+            'public/test/content_browser_test_utils.cc',
+            'public/test/content_browser_test_utils.h',
+            'public/test/content_browser_test_utils_mac.mm',
+          ],
+        },
+        {
+          'target_name': 'web_ui_test_mojo_bindings',
+          'type': 'static_library',
+          'dependencies': [
+            '../mojo/mojo.gyp:mojo_bindings',
+            '../mojo/mojo.gyp:mojo_system',
+          ],
+          'sources': [
+            'test/data/web_ui_test_mojo_bindings.mojom',
+          ],
+          # TODO(sky): this shouldn't be necessary. It's working around a bug in
+          # gyp.
+          'variables': {
+            'mojom_base_output_dir': 'content',
+          },
+          'includes': [ '../mojo/public/bindings/mojom_bindings_generator.gypi' ],
+          'export_dependent_settings': [
+            '../mojo/mojo.gyp:mojo_bindings',
+            '../mojo/mojo.gyp:mojo_system',
           ],
         },
         {
@@ -970,6 +994,8 @@
             'HAS_OUT_OF_PROC_TEST_RUNNER',
           ],
           'sources': [
+            'app/mojo/mojo_browsertest.cc',
+            'browser/accessibility/accessibility_mode_browsertest.cc',
             'browser/accessibility/accessibility_win_browsertest.cc',
             'browser/accessibility/cross_platform_accessibility_browsertest.cc',
             'browser/accessibility/dump_accessibility_tree_browsertest.cc',
@@ -1002,6 +1028,7 @@
             'browser/media/encrypted_media_browsertest.cc',
             'browser/media/media_browsertest.cc',
             'browser/media/media_browsertest.h',
+            'browser/media/media_canplaytype_browsertest.cc',
             'browser/media/media_source_browsertest.cc',
             'browser/media/webrtc_internals_browsertest.cc',
             'browser/plugin_data_remover_impl_browsertest.cc',
@@ -1024,6 +1051,7 @@
             'browser/web_contents/web_contents_impl_browsertest.cc',
             'browser/web_contents/web_contents_view_aura_browsertest.cc',
             'browser/webkit_browsertest.cc',
+            'browser/webui/web_ui_mojo_browsertest.cc',
             'browser/worker_host/test/worker_browsertest.cc',
             'child/site_isolation_policy_browsertest.cc',
             'common/gpu/client/context_provider_command_buffer_browsertest.cc',
@@ -1050,8 +1078,9 @@
             'renderer/render_widget_browsertest.cc',
             'renderer/resource_fetcher_browsertest.cc',
             'renderer/savable_resources_browsertest.cc',
+            'test/accessibility_browser_test_utils.cc',
+            'test/accessibility_browser_test_utils.h',
             'test/content_browser_test_test.cc',
-            'test/content_test_launcher.cc',
             'test/webui_resource_browsertest.cc',
           ],
           'conditions': [
@@ -1060,6 +1089,19 @@
                 'browser/web_contents/touch_editable_impl_aura_browsertest.cc',
               ],
             }],
+            ['use_mojo==0', {
+              'sources!': [
+                'browser/webui/web_ui_mojo_browsertest.cc',
+              ],
+            }, {  # use_mojo==1
+              'dependencies': [
+                'web_ui_test_mojo_bindings',
+                '../mojo/mojo.gyp:mojo_bindings',
+                '../mojo/mojo.gyp:mojo_environment_chromium',
+                '../mojo/mojo.gyp:mojo_system',
+                '../mojo/mojo.gyp:mojo_system_impl',
+              ],
+            }],
             ['OS=="win"', {
               'resource_include_dirs': [
                 '<(SHARED_INTERMEDIATE_DIR)/webkit',
@@ -1147,6 +1189,16 @@
                 ['exclude', '^browser/compositor/'],
               ],
             }],
+            ['use_mojo==1', {
+              'dependencies': [
+                '../mojo/mojo.gyp:mojo_environment_chromium',
+                '../mojo/mojo.gyp:mojo_service_manager',
+              ],
+            },{
+              'sources!': [
+                'app/mojo/mojo_browsertest.cc',
+              ],
+            }],
             ['OS!="android" and OS!="ios"', {
               # npapi test plugin doesn't build on android or ios
               'dependencies': [
@@ -1369,6 +1421,7 @@
           'dependencies': [
             '../base/base.gyp:base',
             '../media/media.gyp:media',
+            '../media/media.gyp:media_test_support',
             '../testing/gtest.gyp:gtest',
             '../ui/base/ui_base.gyp:ui_base',
             '../ui/gfx/gfx.gyp:gfx',
diff --git a/content/content_utility.gypi b/content/content_utility.gypi
index 47be4e0..2d2a7c0 100644
--- a/content/content_utility.gypi
+++ b/content/content_utility.gypi
@@ -5,6 +5,7 @@
 {
   'dependencies': [
     '../base/base.gyp:base',
+    '../courgette/courgette.gyp:courgette_lib',
   ],
   'sources': [
     'public/utility/content_utility_client.cc',
diff --git a/content/content_utility.target.darwin-arm.mk b/content/content_utility.target.darwin-arm.mk
index 7e78916..097c52a 100644
--- a/content/content_utility.target.darwin-arm.mk
+++ b/content/content_utility.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_utility.target.darwin-mips.mk b/content/content_utility.target.darwin-mips.mk
index 9f3c8d5..66d32d0 100644
--- a/content/content_utility.target.darwin-mips.mk
+++ b/content/content_utility.target.darwin-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_utility.target.darwin-x86.mk b/content/content_utility.target.darwin-x86.mk
index e4e766b..18a2326 100644
--- a/content/content_utility.target.darwin-x86.mk
+++ b/content/content_utility.target.darwin-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_utility.target.darwin-x86_64.mk b/content/content_utility.target.darwin-x86_64.mk
new file mode 100644
index 0000000..8d0603f
--- /dev/null
+++ b/content/content_utility.target.darwin-x86_64.mk
@@ -0,0 +1,279 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_utility_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/utility/content_utility_client.cc \
+	content/public/utility/utility_thread.cc \
+	content/utility/in_process_utility_thread.cc \
+	content/utility/utility_main.cc \
+	content/utility/utility_thread_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_utility_gyp
+
+# Alias gyp target name.
+.PHONY: content_utility
+content_utility: content_content_utility_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/content_utility.target.linux-arm.mk b/content/content_utility.target.linux-arm.mk
index 7e78916..097c52a 100644
--- a/content/content_utility.target.linux-arm.mk
+++ b/content/content_utility.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_utility.target.linux-mips.mk b/content/content_utility.target.linux-mips.mk
index 9f3c8d5..66d32d0 100644
--- a/content/content_utility.target.linux-mips.mk
+++ b/content/content_utility.target.linux-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_utility.target.linux-x86.mk b/content/content_utility.target.linux-x86.mk
index e4e766b..18a2326 100644
--- a/content/content_utility.target.linux-x86.mk
+++ b/content/content_utility.target.linux-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/content_utility.target.linux-x86_64.mk b/content/content_utility.target.linux-x86_64.mk
new file mode 100644
index 0000000..8d0603f
--- /dev/null
+++ b/content/content_utility.target.linux-x86_64.mk
@@ -0,0 +1,279 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := content_content_utility_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	content/public/utility/content_utility_client.cc \
+	content/public/utility/utility_thread.cc \
+	content/utility/in_process_utility_thread.cc \
+	content/utility/utility_main.cc \
+	content/utility/utility_thread_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_content_utility_gyp
+
+# Alias gyp target name.
+.PHONY: content_utility
+content_utility: content_content_utility_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/content/gesture_event_type_java.target.darwin-arm.mk b/content/gesture_event_type_java.target.darwin-arm.mk
index 90a069e..e001eec 100644
--- a/content/gesture_event_type_java.target.darwin-arm.mk
+++ b/content/gesture_event_type_java.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/gesture_event_type_java.target.darwin-mips.mk b/content/gesture_event_type_java.target.darwin-mips.mk
index afd743e..67a4d71 100644
--- a/content/gesture_event_type_java.target.darwin-mips.mk
+++ b/content/gesture_event_type_java.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/gesture_event_type_java.target.darwin-x86.mk b/content/gesture_event_type_java.target.darwin-x86.mk
index d73f56b..6c39822 100644
--- a/content/gesture_event_type_java.target.darwin-x86.mk
+++ b/content/gesture_event_type_java.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/gesture_event_type_java.target.darwin-x86_64.mk b/content/gesture_event_type_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..2436030
--- /dev/null
+++ b/content/gesture_event_type_java.target.darwin-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_gesture_event_type_java_gyp
+LOCAL_MODULE_STEM := gesture_event_type_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_gesture_event_type_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'browser/android/gesture_event_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/GestureEventType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/GestureEventType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/browser/android/gesture_event_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java" "--template=public/android/java/src/org/chromium/content/browser/GestureEventType.template"
+
+.PHONY: content_gesture_event_type_java_gyp_rule_trigger
+content_gesture_event_type_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_gesture_event_type_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_gesture_event_type_java_gyp
+
+# Alias gyp target name.
+.PHONY: gesture_event_type_java
+gesture_event_type_java: content_gesture_event_type_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/gesture_event_type_java.target.linux-arm.mk b/content/gesture_event_type_java.target.linux-arm.mk
index 90a069e..e001eec 100644
--- a/content/gesture_event_type_java.target.linux-arm.mk
+++ b/content/gesture_event_type_java.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/gesture_event_type_java.target.linux-mips.mk b/content/gesture_event_type_java.target.linux-mips.mk
index afd743e..67a4d71 100644
--- a/content/gesture_event_type_java.target.linux-mips.mk
+++ b/content/gesture_event_type_java.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/gesture_event_type_java.target.linux-x86.mk b/content/gesture_event_type_java.target.linux-x86.mk
index d73f56b..6c39822 100644
--- a/content/gesture_event_type_java.target.linux-x86.mk
+++ b/content/gesture_event_type_java.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/gesture_event_type_java.target.linux-x86_64.mk b/content/gesture_event_type_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..2436030
--- /dev/null
+++ b/content/gesture_event_type_java.target.linux-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_gesture_event_type_java_gyp
+LOCAL_MODULE_STEM := gesture_event_type_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_gesture_event_type_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'browser/android/gesture_event_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/GestureEventType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/GestureEventType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/browser/android/gesture_event_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java" "--template=public/android/java/src/org/chromium/content/browser/GestureEventType.template"
+
+.PHONY: content_gesture_event_type_java_gyp_rule_trigger
+content_gesture_event_type_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/GestureEventType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_gesture_event_type_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_gesture_event_type_java_gyp
+
+# Alias gyp target name.
+.PHONY: gesture_event_type_java
+gesture_event_type_java: content_gesture_event_type_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index 8f67d68..4607c6c 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -119,6 +119,9 @@
 }
 
 void GpuChildThread::OnInitialize() {
+  // Record initialization only after collecting the GPU info because that can
+  // take a significant amount of time.
+  gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
   Send(new GpuHostMsg_Initialized(!dead_on_arrival_, gpu_info_));
   while (!deferred_messages_.empty()) {
     Send(deferred_messages_.front());
@@ -142,10 +145,6 @@
   if (!in_browser_process_)
     logging::SetLogMessageHandler(GpuProcessLogMessageHandler);
 
-  // Record initialization only after collecting the GPU info because that can
-  // take a significant amount of time.
-  gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
-
   // Defer creation of the render thread. This is to prevent it from handling
   // IPC messages before the sandbox has been enabled and all other necessary
   // initialization has succeeded.
@@ -154,11 +153,6 @@
                             watchdog_thread_.get(),
                             ChildProcess::current()->io_message_loop_proxy(),
                             ChildProcess::current()->GetShutDownEvent()));
-
-  // Ensure the browser process receives the GPU info before a reply to any
-  // subsequent IPC it might send.
-  if (!in_browser_process_)
-    Send(new GpuHostMsg_GraphicsInfoCollected(gpu_info_));
 }
 
 void GpuChildThread::StopWatchdog() {
@@ -176,8 +170,19 @@
          in_browser_process_);
 #endif  // OS_WIN
 
-  if (!gpu::CollectContextGraphicsInfo(&gpu_info_))
-    VLOG(1) << "gpu::CollectGraphicsInfo failed";
+  gpu::CollectInfoResult result =
+      gpu::CollectContextGraphicsInfo(&gpu_info_);
+  switch (result) {
+    case gpu::kCollectInfoFatalFailure:
+      LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
+      // TODO(piman): can we signal overall failure?
+      break;
+    case gpu::kCollectInfoNonFatalFailure:
+      VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
+      break;
+    case gpu::kCollectInfoSuccess:
+      break;
+  }
   GetContentClient()->SetGpuInfo(gpu_info_);
 
 #if defined(OS_WIN)
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 8176221..fe4d3ce 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -208,11 +208,14 @@
     bool initialized_gl_context = false;
     bool should_initialize_gl_context = false;
 #if defined(OS_CHROMEOS) && defined(ARCH_CPU_ARMEL)
-    // On Chrome OS ARM, GPU driver userspace creates threads when initializing
-    // a GL context, so start the sandbox early.
-    gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(),
-                                           should_initialize_gl_context);
-    initialized_sandbox = true;
+    // On Chrome OS ARM Mali, GPU driver userspace creates threads when
+    // initializing a GL context, so start the sandbox early.
+    if (!command_line.HasSwitch(
+             switches::kGpuSandboxStartAfterInitialization)) {
+      gpu_info.sandboxed = StartSandboxLinux(gpu_info, watchdog_thread.get(),
+                                             should_initialize_gl_context);
+      initialized_sandbox = true;
+    }
 #endif
 #endif  // defined(OS_LINUX)
 
@@ -250,8 +253,19 @@
       base::TimeTicks before_collect_context_graphics_info =
           base::TimeTicks::Now();
 #if !defined(OS_MACOSX)
-      if (!gpu::CollectContextGraphicsInfo(&gpu_info))
-        VLOG(1) << "gpu::CollectGraphicsInfo failed";
+      gpu::CollectInfoResult result =
+          gpu::CollectContextGraphicsInfo(&gpu_info);
+      switch (result) {
+        case gpu::kCollectInfoFatalFailure:
+          LOG(ERROR) << "gpu::CollectGraphicsInfo failed (fatal).";
+          dead_on_arrival = true;
+          break;
+        case gpu::kCollectInfoNonFatalFailure:
+          VLOG(1) << "gpu::CollectGraphicsInfo failed (non-fatal).";
+          break;
+        case gpu::kCollectInfoSuccess:
+          break;
+      }
       GetContentClient()->SetGpuInfo(gpu_info);
 
 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
diff --git a/content/java_set_jni_headers.target.darwin-arm.mk b/content/java_set_jni_headers.target.darwin-arm.mk
index 5d0532a..487ba88 100644
--- a/content/java_set_jni_headers.target.darwin-arm.mk
+++ b/content/java_set_jni_headers.target.darwin-arm.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/java_set_jni_headers.target.darwin-mips.mk b/content/java_set_jni_headers.target.darwin-mips.mk
index 383263c..360ae7d 100644
--- a/content/java_set_jni_headers.target.darwin-mips.mk
+++ b/content/java_set_jni_headers.target.darwin-mips.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/java_set_jni_headers.target.darwin-x86.mk b/content/java_set_jni_headers.target.darwin-x86.mk
index f2e20b1..9126c88 100644
--- a/content/java_set_jni_headers.target.darwin-x86.mk
+++ b/content/java_set_jni_headers.target.darwin-x86.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/java_set_jni_headers.target.darwin-x86_64.mk b/content/java_set_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..06966a1
--- /dev/null
+++ b/content/java_set_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,231 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_java_set_jni_headers_gyp
+LOCAL_MODULE_STEM := java_set_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/java/util/HashSet.class ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file java/util/HashSet.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_java_set_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: java_set_jni_headers
+java_set_jni_headers: content_java_set_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/java_set_jni_headers.target.linux-arm.mk b/content/java_set_jni_headers.target.linux-arm.mk
index 5d0532a..487ba88 100644
--- a/content/java_set_jni_headers.target.linux-arm.mk
+++ b/content/java_set_jni_headers.target.linux-arm.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/java_set_jni_headers.target.linux-mips.mk b/content/java_set_jni_headers.target.linux-mips.mk
index 383263c..360ae7d 100644
--- a/content/java_set_jni_headers.target.linux-mips.mk
+++ b/content/java_set_jni_headers.target.linux-mips.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/java_set_jni_headers.target.linux-x86.mk b/content/java_set_jni_headers.target.linux-x86.mk
index f2e20b1..9126c88 100644
--- a/content/java_set_jni_headers.target.linux-x86.mk
+++ b/content/java_set_jni_headers.target.linux-x86.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/java_set_jni_headers.target.linux-x86_64.mk b/content/java_set_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..06966a1
--- /dev/null
+++ b/content/java_set_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,231 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_java_set_jni_headers_gyp
+LOCAL_MODULE_STEM := java_set_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/java/util/HashSet.class ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file java/util/HashSet.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/HashSet_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_java_set_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: java_set_jni_headers
+java_set_jni_headers: content_java_set_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/motionevent_jni_headers.target.darwin-arm.mk b/content/motionevent_jni_headers.target.darwin-arm.mk
index 8873523..9b1ba87 100644
--- a/content/motionevent_jni_headers.target.darwin-arm.mk
+++ b/content/motionevent_jni_headers.target.darwin-arm.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/motionevent_jni_headers.target.darwin-mips.mk b/content/motionevent_jni_headers.target.darwin-mips.mk
index f0c65ad2..2b6c874 100644
--- a/content/motionevent_jni_headers.target.darwin-mips.mk
+++ b/content/motionevent_jni_headers.target.darwin-mips.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/motionevent_jni_headers.target.darwin-x86.mk b/content/motionevent_jni_headers.target.darwin-x86.mk
index 75a52a8..57c98c9 100644
--- a/content/motionevent_jni_headers.target.darwin-x86.mk
+++ b/content/motionevent_jni_headers.target.darwin-x86.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/motionevent_jni_headers.target.darwin-x86_64.mk b/content/motionevent_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..31415eb
--- /dev/null
+++ b/content/motionevent_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,231 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_motionevent_jni_headers_gyp
+LOCAL_MODULE_STEM := motionevent_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/view/MotionEvent.class ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/view/MotionEvent.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_motionevent_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: motionevent_jni_headers
+motionevent_jni_headers: content_motionevent_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/motionevent_jni_headers.target.linux-arm.mk b/content/motionevent_jni_headers.target.linux-arm.mk
index 8873523..9b1ba87 100644
--- a/content/motionevent_jni_headers.target.linux-arm.mk
+++ b/content/motionevent_jni_headers.target.linux-arm.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/motionevent_jni_headers.target.linux-mips.mk b/content/motionevent_jni_headers.target.linux-mips.mk
index f0c65ad2..2b6c874 100644
--- a/content/motionevent_jni_headers.target.linux-mips.mk
+++ b/content/motionevent_jni_headers.target.linux-mips.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/motionevent_jni_headers.target.linux-x86.mk b/content/motionevent_jni_headers.target.linux-x86.mk
index 75a52a8..57c98c9 100644
--- a/content/motionevent_jni_headers.target.linux-x86.mk
+++ b/content/motionevent_jni_headers.target.linux-x86.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/motionevent_jni_headers.target.linux-x86_64.mk b/content/motionevent_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..31415eb
--- /dev/null
+++ b/content/motionevent_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,231 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_motionevent_jni_headers_gyp
+LOCAL_MODULE_STEM := motionevent_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/view/MotionEvent.class ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir)/content/jni; ../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/view/MotionEvent.class --output_dir "$(gyp_shared_intermediate_dir)/content/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/content/jni/MotionEvent_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_motionevent_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: motionevent_jni_headers
+motionevent_jni_headers: content_motionevent_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/page_transition_types_java.target.darwin-arm.mk b/content/page_transition_types_java.target.darwin-arm.mk
index 789774c..0abd012 100644
--- a/content/page_transition_types_java.target.darwin-arm.mk
+++ b/content/page_transition_types_java.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/page_transition_types_java.target.darwin-mips.mk b/content/page_transition_types_java.target.darwin-mips.mk
index c0224f4..399f9f8 100644
--- a/content/page_transition_types_java.target.darwin-mips.mk
+++ b/content/page_transition_types_java.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/page_transition_types_java.target.darwin-x86.mk b/content/page_transition_types_java.target.darwin-x86.mk
index e57a71e..5d2f8aa 100644
--- a/content/page_transition_types_java.target.darwin-x86.mk
+++ b/content/page_transition_types_java.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/page_transition_types_java.target.darwin-x86_64.mk b/content/page_transition_types_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d7abe0e
--- /dev/null
+++ b/content/page_transition_types_java.target.darwin-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_page_transition_types_java_gyp
+LOCAL_MODULE_STEM := page_transition_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_page_transition_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" "--template=public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template"
+
+.PHONY: content_page_transition_types_java_gyp_rule_trigger
+content_page_transition_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_page_transition_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_page_transition_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: page_transition_types_java
+page_transition_types_java: content_page_transition_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/page_transition_types_java.target.linux-arm.mk b/content/page_transition_types_java.target.linux-arm.mk
index 789774c..0abd012 100644
--- a/content/page_transition_types_java.target.linux-arm.mk
+++ b/content/page_transition_types_java.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/page_transition_types_java.target.linux-mips.mk b/content/page_transition_types_java.target.linux-mips.mk
index c0224f4..399f9f8 100644
--- a/content/page_transition_types_java.target.linux-mips.mk
+++ b/content/page_transition_types_java.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/page_transition_types_java.target.linux-x86.mk b/content/page_transition_types_java.target.linux-x86.mk
index e57a71e..5d2f8aa 100644
--- a/content/page_transition_types_java.target.linux-x86.mk
+++ b/content/page_transition_types_java.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/page_transition_types_java.target.linux-x86_64.mk b/content/page_transition_types_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..d7abe0e
--- /dev/null
+++ b/content/page_transition_types_java.target.linux-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_page_transition_types_java_gyp
+LOCAL_MODULE_STEM := page_transition_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_page_transition_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/page_transition_types_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/page_transition_types_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java" "--template=public/android/java/src/org/chromium/content/browser/PageTransitionTypes.template"
+
+.PHONY: content_page_transition_types_java_gyp_rule_trigger
+content_page_transition_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/PageTransitionTypes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_page_transition_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_page_transition_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: page_transition_types_java
+page_transition_types_java: content_page_transition_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/popup_item_type_java.target.darwin-arm.mk b/content/popup_item_type_java.target.darwin-arm.mk
index 5a96f1b..789019e 100644
--- a/content/popup_item_type_java.target.darwin-arm.mk
+++ b/content/popup_item_type_java.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/popup_item_type_java.target.darwin-mips.mk b/content/popup_item_type_java.target.darwin-mips.mk
index 836e441..78fb41b 100644
--- a/content/popup_item_type_java.target.darwin-mips.mk
+++ b/content/popup_item_type_java.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/popup_item_type_java.target.darwin-x86.mk b/content/popup_item_type_java.target.darwin-x86.mk
index 624f988..6d2bf66 100644
--- a/content/popup_item_type_java.target.darwin-x86.mk
+++ b/content/popup_item_type_java.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/popup_item_type_java.target.darwin-x86_64.mk b/content/popup_item_type_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..e3f88e5
--- /dev/null
+++ b/content/popup_item_type_java.target.darwin-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_popup_item_type_java_gyp
+LOCAL_MODULE_STEM := popup_item_type_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_popup_item_type_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'browser/android/popup_item_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/input/PopupItemType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/PopupItemType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/browser/android/popup_item_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java" "--template=public/android/java/src/org/chromium/content/browser/input/PopupItemType.template"
+
+.PHONY: content_popup_item_type_java_gyp_rule_trigger
+content_popup_item_type_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_popup_item_type_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_popup_item_type_java_gyp
+
+# Alias gyp target name.
+.PHONY: popup_item_type_java
+popup_item_type_java: content_popup_item_type_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/popup_item_type_java.target.linux-arm.mk b/content/popup_item_type_java.target.linux-arm.mk
index 5a96f1b..789019e 100644
--- a/content/popup_item_type_java.target.linux-arm.mk
+++ b/content/popup_item_type_java.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/popup_item_type_java.target.linux-mips.mk b/content/popup_item_type_java.target.linux-mips.mk
index 836e441..78fb41b 100644
--- a/content/popup_item_type_java.target.linux-mips.mk
+++ b/content/popup_item_type_java.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/popup_item_type_java.target.linux-x86.mk b/content/popup_item_type_java.target.linux-x86.mk
index 624f988..6d2bf66 100644
--- a/content/popup_item_type_java.target.linux-x86.mk
+++ b/content/popup_item_type_java.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/popup_item_type_java.target.linux-x86_64.mk b/content/popup_item_type_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..e3f88e5
--- /dev/null
+++ b/content/popup_item_type_java.target.linux-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_popup_item_type_java_gyp
+LOCAL_MODULE_STEM := popup_item_type_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_popup_item_type_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'browser/android/popup_item_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/input/PopupItemType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/input/PopupItemType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/browser/android/popup_item_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java" "--template=public/android/java/src/org/chromium/content/browser/input/PopupItemType.template"
+
+.PHONY: content_popup_item_type_java_gyp_rule_trigger
+content_popup_item_type_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/input/PopupItemType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_popup_item_type_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_popup_item_type_java_gyp
+
+# Alias gyp target name.
+.PHONY: popup_item_type_java
+popup_item_type_java: content_popup_item_type_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/port/OWNERS b/content/port/OWNERS
deleted file mode 100644
index e1e8d2c..0000000
--- a/content/port/OWNERS
+++ /dev/null
@@ -1,10 +0,0 @@
-joi@chromium.org
-
-# Please include jam@ on all reviews that are adding new interfaces.
-# For other reviews (modifying existing APIs), prefer avi@ or joi@.
-
-# While the Content API is being worked on (see
-# http://dev.chromium.org/developers/content-module/content-api), we have a very
-# limited set of owners to ensure that the API is consistent. Once the
-# implementation is complete, more owners will be added. If this is holding you
-# up, IM one of the owners above.
diff --git a/content/port/browser/render_view_host_delegate_view.h b/content/port/browser/render_view_host_delegate_view.h
index 4991926..e7af7c9 100644
--- a/content/port/browser/render_view_host_delegate_view.h
+++ b/content/port/browser/render_view_host_delegate_view.h
@@ -45,7 +45,10 @@
                              int selected_item,
                              const std::vector<MenuItem>& items,
                              bool right_aligned,
-                             bool allow_multiple_selection) = 0;
+                             bool allow_multiple_selection) {};
+
+  // Hides a popup menu opened by ShowPopupMenu().
+  virtual void HidePopupMenu() {};
 
   // The user started dragging content of the specified type within the
   // RenderView. Contextual information about the dragged content is supplied
diff --git a/content/ppapi_plugin/ppapi_thread.cc b/content/ppapi_plugin/ppapi_thread.cc
index ea74313..5ca0f83 100644
--- a/content/ppapi_plugin/ppapi_thread.cc
+++ b/content/ppapi_plugin/ppapi_thread.cc
@@ -11,6 +11,7 @@
 #include "base/debug/crash_logging.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
 #include "base/rand_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
@@ -52,6 +53,11 @@
 #endif
 
 #if defined(OS_WIN)
+
+// TODO(xhwang): Remove after http://crbug.com/345852 is fixed.
+const char kWidevineCdmFileName[] = "widevinecdm.dll";
+const char kWidevineCdmAdapterFileName[] = "widevinecdmadapter.dll";
+
 extern sandbox::TargetServices* g_target_services;
 
 // Used by EnumSystemLocales for warming up.
@@ -269,12 +275,26 @@
   base::ScopedNativeLibrary library;
   if (plugin_entry_points_.initialize_module == NULL) {
     // Load the plugin from the specified library.
-    std::string error;
+    base::NativeLibraryLoadError error;
     library.Reset(base::LoadNativeLibrary(path, &error));
     if (!library.is_valid()) {
-      LOG(ERROR) << "Failed to load Pepper module from "
-        << path.value() << " (error: " << error << ")";
+      LOG(ERROR) << "Failed to load Pepper module from " << path.value()
+                 << " (error: " << error.ToString() << ")";
       ReportLoadResult(path, LOAD_FAILED);
+      // Report detailed reason for load failure.
+      ReportLoadErrorCode(path, error);
+#if defined(OW_WIN)
+      // Extra check to help investigate http://crbug.com/345852. This should
+      // never fail because the paths are checked before registering the
+      // adapter.
+      // TODO(xhwang): Remove this after the issue is fixed. See
+      // http://crbug.com/356331
+      if (path.BaseName().MaybeAsASCII() == kWidevineCdmAdapterFileName) {
+        CHECK(base::PathExists(path));
+        CHECK(
+            base::PathExists(path.DirName().AppendASCII(kWidevineCdmFileName)));
+      }
+#endif
       return;
     }
 
@@ -502,15 +522,14 @@
 void PpapiThread::ReportLoadResult(const base::FilePath& path,
                                    LoadResult result) {
   DCHECK_LT(result, LOAD_RESULT_MAX);
-
-  std::ostringstream histogram_name;
-  histogram_name << "Plugin.Ppapi" << (is_broker_ ? "Broker" : "Plugin")
-                 << "LoadResult_" << path.BaseName().MaybeAsASCII();
+  std::string histogram_name = std::string("Plugin.Ppapi") +
+                               (is_broker_ ? "Broker" : "Plugin") +
+                               "LoadResult_" + path.BaseName().MaybeAsASCII();
 
   // Note: This leaks memory, which is expected behavior.
   base::HistogramBase* histogram =
       base::LinearHistogram::FactoryGet(
-          histogram_name.str(),
+          histogram_name,
           1,
           LOAD_RESULT_MAX,
           LOAD_RESULT_MAX + 1,
@@ -519,4 +538,20 @@
   histogram->Add(result);
 }
 
+void PpapiThread::ReportLoadErrorCode(
+    const base::FilePath& path,
+    const base::NativeLibraryLoadError& error) {
+#if defined(OS_WIN)
+  // Only report load error code on Windows because that's the only platform
+  // that has a numerical error value.
+  std::string histogram_name =
+      std::string("Plugin.Ppapi") + (is_broker_ ? "Broker" : "Plugin") +
+      "LoadErrorCode_" + path.BaseName().MaybeAsASCII();
+
+  // For sparse histograms, we can use the macro, as it does not incorporate a
+  // static.
+  UMA_HISTOGRAM_SPARSE_SLOWLY(histogram_name, error.code);
+#endif
+}
+
 }  // namespace content
diff --git a/content/ppapi_plugin/ppapi_thread.h b/content/ppapi_plugin/ppapi_thread.h
index faf85c7..9b40189 100644
--- a/content/ppapi_plugin/ppapi_thread.h
+++ b/content/ppapi_plugin/ppapi_thread.h
@@ -112,6 +112,10 @@
 
   void ReportLoadResult(const base::FilePath& path, LoadResult result);
 
+  // Reports |error| to UMA when plugin load fails.
+  void ReportLoadErrorCode(const base::FilePath& path,
+                           const base::NativeLibraryLoadError& error);
+
   // True if running in a broker process rather than a normal plugin process.
   bool is_broker_;
 
diff --git a/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h b/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
index c8e6ab9..f063506 100644
--- a/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
+++ b/content/ppapi_plugin/ppapi_webkitplatformsupport_impl.h
@@ -7,11 +7,11 @@
 
 #include "base/basictypes.h"
 #include "base/memory/scoped_ptr.h"
-#include "content/child/webkitplatformsupport_impl.h"
+#include "content/child/blink_platform_impl.h"
 
 namespace content {
 
-class PpapiWebKitPlatformSupportImpl : public WebKitPlatformSupportImpl {
+class PpapiWebKitPlatformSupportImpl : public BlinkPlatformImpl {
  public:
   PpapiWebKitPlatformSupportImpl();
   virtual ~PpapiWebKitPlatformSupportImpl();
diff --git a/content/public/OWNERS b/content/public/OWNERS
deleted file mode 100644
index e1e8d2c..0000000
--- a/content/public/OWNERS
+++ /dev/null
@@ -1,10 +0,0 @@
-joi@chromium.org
-
-# Please include jam@ on all reviews that are adding new interfaces.
-# For other reviews (modifying existing APIs), prefer avi@ or joi@.
-
-# While the Content API is being worked on (see
-# http://dev.chromium.org/developers/content-module/content-api), we have a very
-# limited set of owners to ensure that the API is consistent. Once the
-# implementation is complete, more owners will be added. If this is holding you
-# up, IM one of the owners above.
diff --git a/content/public/android/OWNERS b/content/public/android/OWNERS
index 29d0acf..11d36ee 100644
--- a/content/public/android/OWNERS
+++ b/content/public/android/OWNERS
@@ -1,3 +1,4 @@
+benm@chromium.org
 bulach@chromium.org
 tedchoc@chromium.org
 yfriedman@chromium.org
diff --git a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
index 769249e..4fec772 100644
--- a/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
+++ b/content/public/android/java/src/org/chromium/content/app/ChildProcessService.java
@@ -141,7 +141,7 @@
                         }
                     }
                     try {
-                        LibraryLoader.loadNow();
+                        LibraryLoader.loadNow(getApplicationContext());
                     } catch (ProcessInitException e) {
                         Log.e(TAG, "Failed to load native library, exiting child process", e);
                         System.exit(-1);
diff --git a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java
index caad20c..4bc70d3 100644
--- a/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/BrowserStartupController.java
@@ -271,7 +271,7 @@
 
         // Normally Main.java will have already loaded the library asynchronously, we only need
         // to load it here if we arrived via another flow, e.g. bookmark access & sync setup.
-        LibraryLoader.ensureInitialized();
+        LibraryLoader.ensureInitialized(mContext);
 
         // TODO(yfriedman): Remove dependency on a command line flag for this.
         DeviceUtils.addDeviceSpecificUserAgentSwitch(mContext);
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
index 5ae5dbb..7885f3c 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewClient.java
@@ -141,6 +141,13 @@
     }
 
     /**
+     * Notification that the selection has changed.
+     * @param selection The newly established selection.
+     */
+    public void onSelectionChanged(String selection) {
+    }
+
+    /**
      * Called when a new content intent is requested to be started.
      */
     public void onStartContentIntent(Context context, String intentUrl) {
diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
index 88f798d..fbd439b 100644
--- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
+++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java
@@ -357,6 +357,11 @@
     private final RenderCoordinates.NormalizedPoint mEndHandlePoint;
     private final RenderCoordinates.NormalizedPoint mInsertionHandlePoint;
 
+    // Cached copy of the visible rectangle defined by two points. Needed to determine
+    // visibility of insertion/selection handles.
+    private final RenderCoordinates.NormalizedPoint mTopLeftVisibilityClippingPoint;
+    private final RenderCoordinates.NormalizedPoint mBottomRightVisibilityClippingPoint;
+
     // Tracks whether a selection is currently active.  When applied to selected text, indicates
     // whether the last selected text is still highlighted.
     private boolean mHasSelection;
@@ -459,6 +464,8 @@
         mStartHandlePoint = mRenderCoordinates.createNormalizedPoint();
         mEndHandlePoint = mRenderCoordinates.createNormalizedPoint();
         mInsertionHandlePoint = mRenderCoordinates.createNormalizedPoint();
+        mTopLeftVisibilityClippingPoint = mRenderCoordinates.createNormalizedPoint();
+        mBottomRightVisibilityClippingPoint = mRenderCoordinates.createNormalizedPoint();
         mAccessibilityManager = (AccessibilityManager)
                 getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
         mGestureStateListeners = new ObserverList<GestureStateListener>();
@@ -1698,17 +1705,6 @@
             return mContainerViewInternals.super_dispatchKeyEvent(event);
         }
 
-        if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) {
-            showImeIfNeeded();
-            // Event is not consumed here, because ImeAdapter might interpret
-            // it as "Enter".
-            // showImeIfNeeded respects the policy of
-            // InputMethodService.onEvaluateInputViewShown. So IME will not be
-            // shown if you have QWERTY physical keyboard attached.
-            // Also, IME will not be shown if the focus is not on the input
-            // field. See ImeAdapter.attachAndShowIfNeeded
-        }
-
         if (mImeAdapter.dispatchKeyEvent(event)) return true;
 
         return mContainerViewInternals.super_dispatchKeyEvent(event);
@@ -1723,6 +1719,10 @@
     public boolean onHoverEvent(MotionEvent event) {
         TraceEvent.begin("onHoverEvent");
 
+        if (mBrowserAccessibilityManager != null) {
+            return mBrowserAccessibilityManager.onHoverEvent(event);
+        }
+
         // Work around Android bug where the x, y coordinates of a hover exit
         // event are incorrect when touch exploration is on.
         if (mTouchExplorationEnabled && event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
@@ -1730,9 +1730,6 @@
         }
 
         mContainerView.removeCallbacks(mFakeMouseMoveRunnable);
-        if (mBrowserAccessibilityManager != null) {
-            return mBrowserAccessibilityManager.onHoverEvent(event);
-        }
         if (mNativeContentViewCore != 0) {
             nativeSendMouseMoveEvent(mNativeContentViewCore, event.getEventTime(),
                     event.getX(), event.getY());
@@ -1991,6 +1988,7 @@
             };
 
             mSelectionHandleController.hideAndDisallowAutomaticShowing();
+            updateInsertionSelectionVisibleBounds();
         }
 
         return mSelectionHandleController;
@@ -2029,6 +2027,7 @@
             };
 
             mInsertionHandleController.hideAndDisallowAutomaticShowing();
+            updateInsertionSelectionVisibleBounds();
         }
 
         return mInsertionHandleController;
@@ -2446,6 +2445,7 @@
     @CalledByNative
     private void onSelectionChanged(String text) {
         mLastSelectedText = text;
+        getContentViewClient().onSelectionChanged(text);
     }
 
     @SuppressWarnings("unused")
@@ -2517,6 +2517,32 @@
         }
     }
 
+    @CalledByNative
+    private void setSelectionRootBounds(Rect bounds) {
+        mTopLeftVisibilityClippingPoint.setLocalDip(bounds.left, bounds.top);
+        mBottomRightVisibilityClippingPoint.setLocalDip(bounds.right, bounds.bottom);
+        updateInsertionSelectionVisibleBounds();
+    }
+
+    private void updateInsertionSelectionVisibleBounds() {
+        if (mSelectionHandleController == null && mInsertionHandleController == null) {
+            return;
+        }
+
+        int x1 = Math.round(mTopLeftVisibilityClippingPoint.getXPix());
+        int y1 = Math.round(mTopLeftVisibilityClippingPoint.getYPix());
+        int x2 = Math.round(mBottomRightVisibilityClippingPoint.getXPix());
+        int y2 = Math.round(mBottomRightVisibilityClippingPoint.getYPix());
+
+        if (mSelectionHandleController != null) {
+            mSelectionHandleController.setVisibleClippingRectangle(x1, y1, x2, y2);
+        }
+
+        if (mInsertionHandleController != null) {
+            mInsertionHandleController.setVisibleClippingRectangle(x1, y1, x2, y2);
+        }
+    }
+
     @SuppressWarnings("unused")
     @CalledByNative
     private static void onEvaluateJavaScriptResult(
diff --git a/content/public/android/java/src/org/chromium/content/browser/VSyncMonitor.java b/content/public/android/java/src/org/chromium/content/browser/VSyncMonitor.java
index 2d51679..ce9f36d 100644
--- a/content/public/android/java/src/org/chromium/content/browser/VSyncMonitor.java
+++ b/content/public/android/java/src/org/chromium/content/browser/VSyncMonitor.java
@@ -211,7 +211,7 @@
         final long currentTime = getCurrentNanoTime();
         final long lastRefreshTime = estimateLastVSyncTime(currentTime);
         long delay = (lastRefreshTime + mRefreshPeriodNano) - currentTime;
-        assert delay >= 0 && delay < mRefreshPeriodNano;
+        assert delay > 0 && delay <= mRefreshPeriodNano;
 
         if (currentTime + delay <= mLastPostedNano + mRefreshPeriodNano / 2) {
             delay += mRefreshPeriodNano;
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java
index 76cf1d9..8b6ba15 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java
@@ -44,7 +44,7 @@
     private final RenderCoordinates mRenderCoordinates;
     private long mNativeObj;
     private int mAccessibilityFocusId;
-    private int mCurrentHoverId;
+    private boolean mIsHovering;
     private int mCurrentRootId;
     private final int[] mTempLocation = new int[2];
     private final View mView;
@@ -83,7 +83,7 @@
         mContentViewCore = contentViewCore;
         mContentViewCore.setBrowserAccessibilityManager(this);
         mAccessibilityFocusId = View.NO_ID;
-        mCurrentHoverId = View.NO_ID;
+        mIsHovering = false;
         mCurrentRootId = View.NO_ID;
         mView = mContentViewCore.getContainerView();
         mRenderCoordinates = mContentViewCore.getRenderCoordinates();
@@ -170,7 +170,7 @@
                 mAccessibilityFocusId = virtualViewId;
                 sendAccessibilityEvent(mAccessibilityFocusId,
                         AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
-                if (mCurrentHoverId == View.NO_ID) {
+                if (!mIsHovering) {
                     nativeScrollToMakeNodeVisible(
                             mNativeObj, mAccessibilityFocusId);
                 } else {
@@ -232,10 +232,7 @@
         }
 
         if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) {
-            if (mCurrentHoverId != View.NO_ID) {
-                sendAccessibilityEvent(mCurrentHoverId, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
-                mCurrentHoverId = View.NO_ID;
-            }
+            mIsHovering = false;
             if (mPendingScrollToMakeNodeVisible) {
                 nativeScrollToMakeNodeVisible(
                         mNativeObj, mAccessibilityFocusId);
@@ -244,6 +241,7 @@
             return true;
         }
 
+        mIsHovering = true;
         mUserHasTouchExplored = true;
         float x = event.getX();
         float y = event.getY();
@@ -254,10 +252,9 @@
         int cssY = (int) (mRenderCoordinates.fromPixToLocalCss(y) +
                           mRenderCoordinates.getScrollY());
         int id = nativeHitTest(mNativeObj, cssX, cssY);
-        if (mCurrentHoverId != id) {
-            sendAccessibilityEvent(mCurrentHoverId, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
+        if (mAccessibilityFocusId != id) {
+            sendAccessibilityEvent(mAccessibilityFocusId, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
             sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
-            mCurrentHoverId = id;
         }
 
         return true;
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/CursorController.java b/content/public/android/java/src/org/chromium/content/browser/input/CursorController.java
index 68f88bc..5bf4bad 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/CursorController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/CursorController.java
@@ -4,38 +4,57 @@
 
 package org.chromium.content.browser.input;
 
+import android.graphics.Rect;
 import android.view.ViewTreeObserver;
 
 /**
  * A CursorController instance can be used to control a cursor in the text.
  */
-interface CursorController extends ViewTreeObserver.OnTouchModeChangeListener {
+abstract class CursorController implements ViewTreeObserver.OnTouchModeChangeListener {
+
+    private Rect mVisibleClippingRectangle;
 
     /**
      * Hide the cursor controller from screen.
      */
-    void hide();
+    abstract void hide();
 
     /**
      * @return true if the CursorController is currently visible
      */
-    boolean isShowing();
+    abstract boolean isShowing();
 
     /**
      * Called when the handle is about to start updating its position.
      * @param handle
      */
-    void beforeStartUpdatingPosition(HandleView handle);
+    abstract void beforeStartUpdatingPosition(HandleView handle);
 
     /**
      * Update the controller's position.
      */
-    void updatePosition(HandleView handle, int x, int y);
+    abstract void updatePosition(HandleView handle, int x, int y);
 
     /**
      * Called when the view is detached from window. Perform house keeping task, such as
      * stopping Runnable thread that would otherwise keep a reference on the context, thus
      * preventing the activity to be recycled.
      */
-    void onDetached();
+    abstract void onDetached();
+
+    /**
+     * Sets the visible rectangle for text input elements as supplied by Blink.
+     */
+    public void setVisibleClippingRectangle(int left, int top, int right, int bottom) {
+        if (mVisibleClippingRectangle == null) {
+            mVisibleClippingRectangle = new Rect(left, top, right, bottom);
+        } else {
+            mVisibleClippingRectangle.set(left,top,right,bottom);
+        }
+    }
+
+    Rect getVisibleClippingRectangle() {
+        return mVisibleClippingRectangle;
+    }
+
 }
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java b/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java
index e41efcf..b8bac44 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/HandleView.java
@@ -18,6 +18,8 @@
 import android.view.animation.AnimationUtils;
 import android.widget.PopupWindow;
 
+import com.google.common.annotations.VisibleForTesting;
+
 import org.chromium.content.browser.PositionObserver;
 
 /**
@@ -230,7 +232,8 @@
         return mContainer.isShowing();
     }
 
-    private boolean isPositionVisible() {
+    @VisibleForTesting
+    boolean isPositionVisible() {
         // Always show a dragging handle.
         if (mIsDragging) {
             return true;
@@ -250,8 +253,17 @@
         final int posX = getContainerPositionX() + (int) mHotspotX;
         final int posY = getContainerPositionY() + (int) mHotspotY;
 
-        return posX >= clip.left && posX <= clip.right &&
+        boolean result = posX >= clip.left && posX <= clip.right &&
                 posY >= clip.top && posY <= clip.bottom;
+
+        final Rect clippingRect = mController.getVisibleClippingRectangle();
+        if (result && clippingRect != null) {
+            // We need to clip against the visible areas as supplied by Blink,
+            // e.g. textaread and text input elements.
+            return clippingRect.contains(getAdjustedPositionX(), getAdjustedPositionY());
+        }
+
+        return result;
     }
 
     // x and y are in physical pixels.
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/InsertionHandleController.java b/content/public/android/java/src/org/chromium/content/browser/input/InsertionHandleController.java
index bd3a464..f7c6f5b 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/InsertionHandleController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/InsertionHandleController.java
@@ -23,7 +23,7 @@
 /**
  * CursorController for inserting text at the cursor position.
  */
-public abstract class InsertionHandleController implements CursorController {
+public abstract class InsertionHandleController extends CursorController {
 
     /** The handle view, lazily created when first shown */
     private HandleView mHandle;
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupAdapter.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupAdapter.java
index 1118e78..ca8e5f0 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupAdapter.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectPopupAdapter.java
@@ -60,7 +60,11 @@
             if (mItems.get(position).getType() == PopupItemType.GROUP) {
                 // Currently select_dialog_multichoice uses CheckedTextViews.
                 // If that changes, the class cast will no longer be valid.
-                ((CheckedTextView) convertView).setCheckMarkDrawable(null);
+                // The WebView build cannot rely on this being the case, so
+                // we must check.
+                if (convertView instanceof CheckedTextView) {
+                    ((CheckedTextView) convertView).setCheckMarkDrawable(null);
+                }
             } else {
                 // Draw the disabled element in a disabled state.
                 convertView.setEnabled(false);
diff --git a/content/public/android/java/src/org/chromium/content/browser/input/SelectionHandleController.java b/content/public/android/java/src/org/chromium/content/browser/input/SelectionHandleController.java
index 0edf551..db7efe7 100644
--- a/content/public/android/java/src/org/chromium/content/browser/input/SelectionHandleController.java
+++ b/content/public/android/java/src/org/chromium/content/browser/input/SelectionHandleController.java
@@ -13,7 +13,7 @@
 /**
  * CursorController for selecting a range of text.
  */
-public abstract class SelectionHandleController implements CursorController {
+public abstract class SelectionHandleController extends CursorController {
 
     // The following constants match the ones in
     // third_party/WebKit/public/web/WebTextDirection.h
diff --git a/content/public/android/java/strings/translations/android_content_strings_ca.xtb b/content/public/android/java/strings/translations/android_content_strings_ca.xtb
index 6cba65b..d85d9e5 100644
--- a/content/public/android/java/strings/translations/android_content_strings_ca.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_ca.xtb
@@ -4,7 +4,7 @@
 <translation id="376869769528291915">:</translation>
 <translation id="6015796118275082299">Any</translation>
 <translation id="2094750046714988961">No es pot iniciar el generador de perfils perquè l'emmagatzematge extern no està preparat.</translation>
-<translation id="1256337885411059545">No es pot reproduir el vídeo.</translation>
+<translation id="1256337885411059545">No es pot reproduir el vídeo</translation>
 <translation id="2520230379124234395">El generador de perfils s'ha iniciat.</translation>
 <translation id="7821540960913969614">Defineix la data</translation>
 <translation id="4859501799452851758">El generador de perfils ha finalitzat. Els resultats són a <ph name="FILENAME"/>.</translation>
diff --git a/content/public/android/java/strings/translations/android_content_strings_el.xtb b/content/public/android/java/strings/translations/android_content_strings_el.xtb
index bbb84a6..98057be 100644
--- a/content/public/android/java/strings/translations/android_content_strings_el.xtb
+++ b/content/public/android/java/strings/translations/android_content_strings_el.xtb
@@ -24,7 +24,7 @@
 <translation id="7096034533295549981">Φόρτωση βίντεο</translation>
 <translation id="1542044944667958430">Αναζήτηση στον Ιστό</translation>
 <translation id="6849295950938417341">Αποτυχία έναρξης προγράμματος προφίλ</translation>
-<translation id="6527303717912515753">Κοινή χρήση</translation>
+<translation id="6527303717912515753">Κοινοποίηση</translation>
 <translation id="1822429046913737220">Π.Μ./Μ.Μ.</translation>
 <translation id="5789643057113097023">.</translation>
 <translation id="1768717197362323622">Χιλιοστό του δευτερολέπτου</translation>
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentCommandLineTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentCommandLineTest.java
index a0a3d4e..3bb1ee4 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentCommandLineTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentCommandLineTest.java
@@ -47,7 +47,7 @@
             public void run() {
                 ContentShellApplication.initializeApplicationParameters();
                 try {
-                    LibraryLoader.ensureInitialized();
+                    LibraryLoader.ensureInitialized(null);
                 } catch (ProcessInitException e) {
                     throw new Error(e);
                 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreDpadTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreDpadTest.java
deleted file mode 100644
index 0db99aa..0000000
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewCoreDpadTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-package org.chromium.content.browser;
-
-import android.content.Context;
-import android.test.suitebuilder.annotation.SmallTest;
-import android.view.KeyEvent;
-
-import org.chromium.content.browser.input.ImeAdapter;
-import org.chromium.content_shell_apk.ContentShellTestBase;
-
-/**
- * Tests that ContentViewCore responds to DPAD key events correctly
- */
-public class ContentViewCoreDpadTest extends ContentShellTestBase {
-    TestContentViewCore mContentViewCore;
-    private static class TestImeAdapter extends ImeAdapter {
-        public TestImeAdapter() {
-            super(null, null);
-        }
-
-        @Override
-        public boolean dispatchKeyEvent(KeyEvent event) {
-            return true;
-        }
-    }
-
-    private static class TestContentViewCore extends ContentViewCore {
-        private boolean mIsShowImeIfNeededCalled = false;
-        public TestContentViewCore(Context context) {
-            super(context);
-        }
-
-        public boolean isShowImeIfNeededCalled() {
-            return mIsShowImeIfNeededCalled;
-        }
-
-        @Override
-        public void showImeIfNeeded() {
-            mIsShowImeIfNeededCalled = true;
-        }
-    }
-
-    public void setUp() throws Exception {
-        super.setUp();
-        mContentViewCore = new TestContentViewCore(getActivity());
-        mContentViewCore.setImeAdapterForTest(new TestImeAdapter());
-    }
-
-    @SmallTest
-    // Test KEYCODE_DPAD_CENTER keyevent will bring up the IME, if needed
-    public void testDpadCenterBringsUpIme() throws Exception {
-        KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
-
-        mContentViewCore.dispatchKeyEvent(event);
-
-        // Just assert showImeIfNeeded is called. Software keyboard may not show if a QWERTY
-        // keyboard is connected or if the focused object is not editable.
-        assertTrue(mContentViewCore.isShowImeIfNeededCalled());
-    }
-}
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
index 92d3a3d..6da349b 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java
@@ -197,6 +197,35 @@
         assertWaitForScroll(false, false);
     }
 
+
+    /**
+     * To ensure the device properly responds to bounds-exceeding scrolls, e.g., overscroll
+     * effects are properly initialized.
+     */
+    @SmallTest
+    @Feature({"Main"})
+    public void testOverScroll() throws Throwable {
+        // Overscroll lower-left.
+        scrollTo(-10000, 10000);
+        assertWaitForScroll(true, false);
+
+        // Overscroll lower-right.
+        scrollTo(10000, 10000);
+        assertWaitForScroll(false, false);
+
+        // Overscroll upper-right.
+        scrollTo(10000, -10000);
+        assertWaitForScroll(false, true);
+
+        // Overscroll top-left.
+        scrollTo(-10000, -10000);
+        assertWaitForScroll(true, true);
+
+        // Diagonal overscroll lower-right.
+        scrollTo(10000, 10000);
+        assertWaitForScroll(false, false);
+    }
+
     /**
      * To ensure the AccessibilityEvent notifications (Eg:TYPE_VIEW_SCROLLED) are being sent
      * properly on scrolling a page.
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ImportantFileWriterAndroidTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ImportantFileWriterAndroidTest.java
index 66c17e0..5ff9949 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ImportantFileWriterAndroidTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ImportantFileWriterAndroidTest.java
@@ -34,7 +34,7 @@
             public void run() {
                 ContentShellApplication.initializeApplicationParameters();
                 try {
-                    LibraryLoader.ensureInitialized();
+                    LibraryLoader.ensureInitialized(null);
                 } catch (ProcessInitException e) {
                     throw new Error(e);
                 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java
index 0ca6080..88c4b3b 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java
@@ -6,6 +6,7 @@
 
 import android.test.suitebuilder.annotation.SmallTest;
 
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
 import org.chromium.content_shell_apk.ContentShellActivity;
@@ -119,6 +120,19 @@
         onPageFinishedHelper.waitForCallback(currentCallCount);
     }
 
+    protected void synchronousPageReload() throws Throwable {
+        TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
+                mTestCallbackHelperContainer.getOnPageFinishedHelper();
+        int currentCallCount = onPageFinishedHelper.getCallCount();
+        runTestOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                getContentView().getContentViewCore().reload(true);
+            }
+        });
+        onPageFinishedHelper.waitForCallback(currentCallCount);
+    }
+
     // Note that this requires that we can pass a JavaScript boolean to Java.
     private void assertRaisesException(String script) throws Throwable {
         executeJavaScript("try {" +
@@ -148,16 +162,7 @@
             }
         });
         assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject"));
-        TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
-                mTestCallbackHelperContainer.getOnPageFinishedHelper();
-        int currentCallCount = onPageFinishedHelper.getCallCount();
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                getContentView().getContentViewCore().reload(true);
-            }
-        });
-        onPageFinishedHelper.waitForCallback(currentCallCount);
+        synchronousPageReload();
         assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
     }
 
@@ -173,16 +178,7 @@
             }
         });
         assertEquals("object", executeJavaScriptAndGetStringResult("typeof testObject"));
-        TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
-                mTestCallbackHelperContainer.getOnPageFinishedHelper();
-        int currentCallCount = onPageFinishedHelper.getCallCount();
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                getContentView().getContentViewCore().reload(true);
-            }
-        });
-        onPageFinishedHelper.waitForCallback(currentCallCount);
+        synchronousPageReload();
         assertEquals("undefined", executeJavaScriptAndGetStringResult("typeof testObject"));
     }
 
@@ -325,21 +321,22 @@
     @Feature({"AndroidWebView", "Android-JavaBridge"})
     public void testObjectPersistsAcrossPageLoads() throws Throwable {
         assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController"));
-        TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
-                mTestCallbackHelperContainer.getOnPageFinishedHelper();
-        int currentCallCount = onPageFinishedHelper.getCallCount();
-        runTestOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                getContentView().getContentViewCore().reload(true);
-            }
-        });
-        onPageFinishedHelper.waitForCallback(currentCallCount);
+        synchronousPageReload();
         assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController"));
     }
 
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
+    public void testClientPropertiesPersistAcrossPageLoads() throws Throwable {
+        assertEquals("object", executeJavaScriptAndGetStringResult("typeof testController"));
+        executeJavaScript("testController.myProperty = 42;");
+        assertEquals("42", executeJavaScriptAndGetStringResult("testController.myProperty"));
+        synchronousPageReload();
+        assertEquals("42", executeJavaScriptAndGetStringResult("testController.myProperty"));
+    }
+
+    @SmallTest
+    @Feature({"AndroidWebView", "Android-JavaBridge"})
     public void testSameObjectInjectedMultipleTimes() throws Throwable {
         class TestObject {
             private int mNumMethodInvocations;
@@ -458,6 +455,36 @@
         assertEquals(null, object.weakRefForInner.get());
     }
 
+    /*
+     * The current Java bridge implementation doesn't reuse JS wrappers when returning
+     * the same object from a method. That looks wrong. For example, in the case of DOM,
+     * wrappers are reused, which allows JS code to attach custom properties to interface
+     * objects and use them regardless of the way the reference has been obtained:
+     * via copying a JS reference or by calling the method one more time (assuming that
+     * the method is supposed to return a reference to the same object each time).
+     * TODO(mnaganov): Fix this in the new implementation.
+     *
+     * @SmallTest
+     * @Feature({"AndroidWebView", "Android-JavaBridge"})
+     */
+    @DisabledTest
+    public void testSameReturnedObjectUsesSameWrapper() throws Throwable {
+        class InnerObject {
+        }
+        final InnerObject innerObject = new InnerObject();
+        final Object injectedTestObject = new Object() {
+            public InnerObject getInnerObject() {
+                return innerObject;
+            }
+        };
+        injectObjectAndReload(injectedTestObject, "injectedTestObject");
+        executeJavaScript("inner1 = injectedTestObject.getInnerObject()");
+        executeJavaScript("inner2 = injectedTestObject.getInnerObject()");
+        assertEquals("object", executeJavaScriptAndGetStringResult("typeof inner1"));
+        assertEquals("object", executeJavaScriptAndGetStringResult("typeof inner2"));
+        assertEquals("true", executeJavaScriptAndGetStringResult("inner1 === inner2"));
+    }
+
     @SmallTest
     @Feature({"AndroidWebView", "Android-JavaBridge"})
     public void testMethodInvokedOnBackgroundThread() throws Throwable {
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java
index 70f6845..cdb00fe 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java
@@ -117,6 +117,10 @@
         return true;
     }
 
+    // At least one of these tests flakes 50% on all runs of
+    // contentshell_instrumentation_tests.
+    // crbug.com/356483
+    /*
     @SmallTest
     @Feature({"ScreenOrientation"})
     public void testConfigurationListenerDefault() throws Exception {
@@ -250,5 +254,5 @@
         lockOrientationAndWait(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
         assertEquals(-90, mObserver.mOrientation);
     }
-
+    */
 }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationProviderTest.java b/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationProviderTest.java
index 3af3d68..8e70da6 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationProviderTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/ScreenOrientationProviderTest.java
@@ -5,8 +5,7 @@
 package org.chromium.content.browser;
 
 import android.os.Build;
-import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.test.FlakyTest;
 
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
@@ -112,7 +111,9 @@
         super.tearDown();
     }
 
-    @SmallTest
+    // @SmallTest
+    // crbug.com/353500
+    @FlakyTest
     @Feature({"ScreenOrientation"})
     public void testBasicValues() throws Exception {
         lockOrientationAndWait(ScreenOrientationValues.PORTRAIT_PRIMARY);
@@ -128,7 +129,9 @@
         assertTrue(checkOrientationForLock(ScreenOrientationValues.LANDSCAPE_SECONDARY));
     }
 
-    @MediumTest
+    // @MediumTest
+    // crbug.com/353500
+    @FlakyTest
     @Feature({"ScreenOrientation"})
     public void testPortrait() throws Exception {
         lockOrientationAndWait(ScreenOrientationValues.PORTRAIT_PRIMARY);
@@ -148,7 +151,9 @@
                 ScreenOrientationValues.PORTRAIT_SECONDARY));
     }
 
-    @MediumTest
+    // @MediumTest
+    // crbug.com/353500
+    @FlakyTest
     @Feature({"ScreenOrientation"})
     public void testLandscape() throws Exception {
         int initialOrientation = mObserver.mOrientation;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/InsertionHandleTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/InsertionHandleTest.java
index 7cdbd89..c83a20e 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/InsertionHandleTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/InsertionHandleTest.java
@@ -209,6 +209,35 @@
         assertTrue(handle.getPositionX() < dragToX - 100);
     }
 
+    /**
+     * Tests insertion handle visibility relative to the clipping rectangle.
+     * This is currently not implemented using dragHandleTo, because of issues with
+     * http://crbug.com/169648.
+     */
+    @MediumTest
+    @Feature({"TextSelection", "TextInput", "Main"})
+    public void testInsertionHandleVisiblity() throws Throwable {
+        launchWithUrl(TEXTAREA_DATA_URL);
+        clickNodeToShowInsertionHandle(TEXTAREA_ID);
+
+        InsertionHandleController ihc = getContentViewCore().getInsertionHandleControllerForTest();
+        HandleView handle = ihc.getHandleViewForTest();
+
+        assertTrue(handle.isPositionVisible());
+
+        ihc.setVisibleClippingRectangle(
+                handle.getAdjustedPositionX() + 1, handle.getAdjustedPositionY() + 1,
+                handle.getAdjustedPositionX() + 100, handle.getAdjustedPositionY() + 100);
+
+        assertFalse(handle.isPositionVisible());
+
+        ihc.setVisibleClippingRectangle(
+                handle.getAdjustedPositionX() - 1, handle.getAdjustedPositionY() - 1,
+                handle.getAdjustedPositionX() + 1, handle.getAdjustedPositionY() + 1);
+
+        assertTrue(handle.isPositionVisible());
+    }
+
     @Override
     protected void tearDown() throws Exception {
         super.tearDown();
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/input/SelectionHandleTest.java b/content/public/android/javatests/src/org/chromium/content/browser/input/SelectionHandleTest.java
index 08dc1d4..baaf1aa 100644
--- a/content/public/android/javatests/src/org/chromium/content/browser/input/SelectionHandleTest.java
+++ b/content/public/android/javatests/src/org/chromium/content/browser/input/SelectionHandleTest.java
@@ -5,6 +5,7 @@
 package org.chromium.content.browser.input;
 
 import android.graphics.Point;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.SystemClock;
 import android.test.FlakyTest;
@@ -29,6 +30,10 @@
 
 import java.util.concurrent.Callable;
 
+/**
+ * Tests for the selection handles that allow to select text in both editable and non-editable
+ * elements.
+ */
 public class SelectionHandleTest extends ContentShellTestBase {
     private static final String META_DISABLE_ZOOM =
         "<meta name=\"viewport\" content=\"" +
@@ -152,6 +157,76 @@
         doSelectionHandleTest(TestPageType.EDITABLE);
     }
 
+    /**
+     * Verifies that the visibility of handles is correct when visible clipping
+     * rectangle is set.
+     */
+    @MediumTest
+    @Feature({ "TextSelection" })
+    public void testEditableSelectionHandlesStartNotVisibleEndVisible() throws Throwable {
+        doSelectionHandleTestVisibility(TestPageType.EDITABLE, false, true, new PointF(.5f, .5f),
+                new PointF(0,1));
+    }
+
+    @MediumTest
+    @Feature({ "TextSelection" })
+    public void testEditableSelectionHandlesStartVisibleEndNotVisible() throws Throwable {
+        doSelectionHandleTestVisibility(TestPageType.EDITABLE, true, false, new PointF(1,0),
+                new PointF(.5f, .5f));
+    }
+
+    @MediumTest
+    @Feature({ "TextSelection" })
+    public void testEditableSelectionHandlesStartVisibleEndVisible() throws Throwable {
+        doSelectionHandleTestVisibility(TestPageType.EDITABLE, true, true, new PointF(1, 0),
+                new PointF(0,1));
+    }
+
+    @MediumTest
+    @Feature({ "TextSelection" })
+    public void testEditableSelectionHandlesStartNotVisibleEndNotVisible() throws Throwable {
+        doSelectionHandleTestVisibility(TestPageType.EDITABLE, false, false, new PointF(1,0),
+                new PointF(1, 0));
+    }
+
+    private void doSelectionHandleTestVisibility(TestPageType pageType,
+            boolean startHandleVisible, boolean endHandleVisible,
+            PointF affineTopLeft, PointF affineBottomRight) throws Throwable {
+        launchWithUrl(pageType.dataUrl);
+
+        clickNodeToShowSelectionHandles(pageType.nodeId);
+        assertWaitForSelectionEditableEquals(pageType.selectionShouldBeEditable);
+
+        HandleView startHandle = getStartHandle();
+        HandleView endHandle = getEndHandle();
+
+        Rect nodeWindowBounds = getNodeBoundsPix(pageType.nodeId);
+
+        int visibleBoundsLeftX = Math.round(affineTopLeft.x * nodeWindowBounds.left
+                + affineTopLeft.y * nodeWindowBounds.right);
+        int visibleBoundsTopY = Math.round(affineTopLeft.x * nodeWindowBounds.top
+                + affineTopLeft.y * nodeWindowBounds.bottom);
+
+        int visibleBoundsRightX = Math.round(affineBottomRight.x * nodeWindowBounds.left
+                + affineBottomRight.y * nodeWindowBounds.right);
+        int visibleBoundsBottomY = Math.round(affineBottomRight.x * nodeWindowBounds.top
+                + affineBottomRight.y * nodeWindowBounds.bottom);
+
+        getContentViewCore().getSelectionHandleControllerForTest().setVisibleClippingRectangle(
+                visibleBoundsLeftX, visibleBoundsTopY, visibleBoundsRightX, visibleBoundsBottomY);
+
+        int leftX = (nodeWindowBounds.left + nodeWindowBounds.centerX()) / 2;
+        int rightX = (nodeWindowBounds.right + nodeWindowBounds.centerX()) / 2;
+
+        int topY = (nodeWindowBounds.top + nodeWindowBounds.centerY()) / 2;
+        int bottomY = (nodeWindowBounds.bottom + nodeWindowBounds.centerY()) / 2;
+
+        dragHandleAndCheckSelectionChange(startHandle, leftX, topY, -1, 0, startHandleVisible);
+        dragHandleAndCheckSelectionChange(endHandle, rightX, bottomY, 0, 1, endHandleVisible);
+
+        clickToDismissHandles();
+    }
+
     private void doSelectionHandleTest(TestPageType pageType) throws Throwable {
         launchWithUrl(pageType.dataUrl);
 
@@ -172,23 +247,25 @@
         int bottomY = (nodeWindowBounds.bottom + nodeWindowBounds.centerY()) / 2;
 
         // Drag start handle up and to the left. The selection start should decrease.
-        dragHandleAndCheckSelectionChange(startHandle, leftX, topY, -1, 0);
+        dragHandleAndCheckSelectionChange(startHandle, leftX, topY, -1, 0, true);
         // Drag end handle down and to the right. The selection end should increase.
-        dragHandleAndCheckSelectionChange(endHandle, rightX, bottomY, 0, 1);
+        dragHandleAndCheckSelectionChange(endHandle, rightX, bottomY, 0, 1, true);
         // Drag start handle back to the middle. The selection start should increase.
-        dragHandleAndCheckSelectionChange(startHandle, centerX, centerY, 1, 0);
+        dragHandleAndCheckSelectionChange(startHandle, centerX, centerY, 1, 0, true);
         // Drag end handle up and to the left past the start handle. Both selection start and end
         // should decrease.
-        dragHandleAndCheckSelectionChange(endHandle, leftX, topY, -1, -1);
+        dragHandleAndCheckSelectionChange(endHandle, leftX, topY, -1, -1, true);
         // Drag start handle down and to the right past the end handle. Both selection start and end
         // should increase.
-        dragHandleAndCheckSelectionChange(startHandle, rightX, bottomY, 1, 1);
+        dragHandleAndCheckSelectionChange(startHandle, rightX, bottomY, 1, 1, true);
 
         clickToDismissHandles();
     }
 
-    private void dragHandleAndCheckSelectionChange(HandleView handle, int dragToX, int dragToY,
-            final int expectedStartChange, final int expectedEndChange) throws Throwable {
+    private void dragHandleAndCheckSelectionChange(final HandleView handle,
+            final int dragToX, final int dragToY,
+            final int expectedStartChange, final int expectedEndChange,
+            final boolean expectedHandleVisible) throws Throwable {
         String initialText = getContentViewCore().getSelectedText();
         final int initialSelectionEnd = getSelectionEnd();
         final int initialSelectionStart = getSelectionStart();
@@ -212,6 +289,8 @@
                         if ((int) Math.signum(endChange) != expectedEndChange) return false;
                     }
 
+                    if (expectedHandleVisible != handle.isPositionVisible()) return false;
+
                     return true;
                 }
             }));
diff --git a/content/public/browser/android/content_view_core.h b/content/public/browser/android/content_view_core.h
index b2d227a..1501985 100644
--- a/content/public/browser/android/content_view_core.h
+++ b/content/public/browser/android/content_view_core.h
@@ -48,7 +48,6 @@
   virtual ui::WindowAndroid* GetWindowAndroid() const = 0;
   virtual scoped_refptr<cc::Layer> GetLayer() const = 0;
   virtual void LoadUrl(NavigationController::LoadURLParams& params) = 0;
-  virtual jint GetCurrentRenderProcessId(JNIEnv* env, jobject obj) = 0;
   virtual void ShowPastePopup(int x, int y) = 0;
 
   // Request a scaled content readback. The result is passed through the
diff --git a/content/public/browser/browser_context.h b/content/public/browser/browser_context.h
index 4f9e967..0cb1b5b 100644
--- a/content/public/browser/browser_context.h
+++ b/content/public/browser/browser_context.h
@@ -131,6 +131,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) = 0;
 
   // Cancels a pending MIDI permission request.
diff --git a/content/public/browser/child_process_security_policy.h b/content/public/browser/child_process_security_policy.h
index 2f462b2..261bf58 100644
--- a/content/public/browser/child_process_security_policy.h
+++ b/content/public/browser/child_process_security_policy.h
@@ -51,6 +51,12 @@
   virtual void GrantCreateReadWriteFile(int child_id,
                                         const base::FilePath& file) = 0;
 
+  // This permission grants copy-into permission for |dir|.
+  virtual void GrantCopyInto(int child_id, const base::FilePath& dir) = 0;
+
+  // This permission grants delete permission for |dir|.
+  virtual void GrantDeleteFrom(int child_id, const base::FilePath& dir) = 0;
+
   // These methods verify whether or not the child process has been granted
   // permissions perform these functions on |file|.
 
diff --git a/content/public/browser/devtools_agent_host.h b/content/public/browser/devtools_agent_host.h
index b98363e..0055d2b 100644
--- a/content/public/browser/devtools_agent_host.h
+++ b/content/public/browser/devtools_agent_host.h
@@ -24,6 +24,11 @@
   // Returns DevToolsAgentHost with a given |id| or NULL of it does not exist.
   static scoped_refptr<DevToolsAgentHost> GetForId(const std::string& id);
 
+  // Returns DevToolsAgentHost that can be used for inspecting |web_contents|.
+  // New DevToolsAgentHost will be created if it does not exist.
+  static scoped_refptr<DevToolsAgentHost> GetOrCreateFor(
+      WebContents* web_contents);
+
   // Returns DevToolsAgentHost that can be used for inspecting |rvh|.
   // New DevToolsAgentHost will be created if it does not exist.
   static scoped_refptr<DevToolsAgentHost> GetOrCreateFor(RenderViewHost* rvh);
diff --git a/content/public/browser/download_item.h b/content/public/browser/download_item.h
index 13d2d67..1e66f8b 100644
--- a/content/public/browser/download_item.h
+++ b/content/public/browser/download_item.h
@@ -181,6 +181,8 @@
   virtual const std::vector<GURL>& GetUrlChain() const = 0;
   virtual const GURL& GetOriginalUrl() const = 0;
   virtual const GURL& GetReferrerUrl() const = 0;
+  virtual const GURL& GetTabUrl() const = 0;
+  virtual const GURL& GetTabReferrerUrl() const = 0;
   virtual std::string GetSuggestedFilename() const = 0;
   virtual std::string GetContentDisposition() const = 0;
   virtual std::string GetMimeType() const = 0;
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index d83235c..1ea7d30 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -50,8 +50,8 @@
   // RenderFrameHost.
   virtual RenderFrameHost* GetParent() = 0;
 
-  // Returns the assigned name of the frame, the id of the iframe tag declaring
-  // it. For example, <iframe id="thisistheframename">[...]</iframe>. It is
+  // Returns the assigned name of the frame, the name of the iframe tag
+  // declaring it. For example, <iframe name="framename">[...]</iframe>. It is
   // quite possible for a frame to have no name, in which case GetFrameName will
   // return an empty string.
   virtual const std::string& GetFrameName() = 0;
@@ -90,9 +90,16 @@
       int action, const CustomContextMenuContext& context) = 0;
 
   // Edit operations.
+  virtual void Undo() = 0;
+  virtual void Redo() = 0;
   virtual void Cut() = 0;
   virtual void Copy() = 0;
+  virtual void CopyToFindPboard() = 0;
   virtual void Paste() = 0;
+  virtual void PasteAndMatchStyle() = 0;
+  virtual void Delete() = 0;
+  virtual void SelectAll() = 0;
+  virtual void Unselect() = 0;
 
   // Requests the renderer to insert CSS into the frame's document.
   virtual void InsertCSS(const std::string& css) = 0;
diff --git a/content/public/browser/render_view_host.h b/content/public/browser/render_view_host.h
index 5f172fe..fabeed3 100644
--- a/content/public/browser/render_view_host.h
+++ b/content/public/browser/render_view_host.h
@@ -14,6 +14,10 @@
 #include "content/public/common/page_zoom.h"
 #include "third_party/WebKit/public/web/WebDragOperation.h"
 
+#if defined(USE_MOJO)
+#include "mojo/public/cpp/system/core.h"
+#endif
+
 class GURL;
 struct WebPreferences;
 
@@ -248,6 +252,11 @@
   virtual void DisableFullscreenEncryptedMediaPlayback() = 0;
 #endif
 
+#if defined(USE_MOJO)
+  // Sets the mojo handle for WebUI pages.
+  virtual void SetWebUIHandle(mojo::ScopedMessagePipeHandle handle) = 0;
+#endif
+
  private:
   // This interface should only be implemented inside content.
   friend class RenderViewHostImpl;
diff --git a/content/public/browser/render_widget_host.h b/content/public/browser/render_widget_host.h
index b509fe9..3bbec3c 100644
--- a/content/public/browser/render_widget_host.h
+++ b/content/public/browser/render_widget_host.h
@@ -121,16 +121,6 @@
 
   virtual ~RenderWidgetHost() {}
 
-  // Edit operations.
-  // TODO(jam): move the rest of these to RenderFrameHost
-  virtual void Undo() = 0;
-  virtual void Redo() = 0;
-  virtual void CopyToFindPboard() = 0;
-  virtual void PasteAndMatchStyle() = 0;
-  virtual void Delete() = 0;
-  virtual void SelectAll() = 0;
-  virtual void Unselect() = 0;
-
   // Update the text direction of the focused input element and notify it to a
   // renderer process.
   // These functions have two usage scenarios: changing the text direction
@@ -216,6 +206,15 @@
   // Send a command to the renderer to turn on full accessibility.
   virtual void EnableFullAccessibilityMode() = 0;
 
+  // Check whether this RenderWidget has full accessibility mode.
+  virtual bool IsFullAccessibilityModeForTesting() = 0;
+
+  // Send a command to the renderer to turn on tree only accessibility.
+  virtual void EnableTreeOnlyAccessibilityMode() = 0;
+
+  // Check whether this RenderWidget has tree-only accessibility mode.
+  virtual bool IsTreeOnlyAccessibilityModeForTesting() = 0;
+
   // Forwards the given message to the renderer. These are called by
   // the view when it has received a message.
   virtual void ForwardMouseEvent(
diff --git a/content/public/browser/service_worker_context.h b/content/public/browser/service_worker_context.h
new file mode 100644
index 0000000..91be6eb
--- /dev/null
+++ b/content/public/browser/service_worker_context.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_CONTEXT_H_
+#define CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_CONTEXT_H_
+
+#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// Represents the per-StoragePartition ServiceWorker data.  Must be used from
+// the UI thread.
+class ServiceWorkerContext {
+ public:
+  // https://rawgithub.com/slightlyoff/ServiceWorker/master/spec/service_worker/index.html#url-scope:
+  // roughly, must be of the form "<origin>/<path>/*".
+  typedef GURL Scope;
+
+  typedef base::Callback<void(bool success)> ResultCallback;
+
+  // Equivalent to calling navigator.serviceWorker.register(script_url, {scope:
+  // pattern}) from a renderer in |source_process_id|, except that |pattern| is
+  // an absolute URL instead of relative to some current origin.  |callback| is
+  // passed true when the JS promise is fulfilled or false when the JS
+  // promise is rejected.
+  //
+  // The registration can fail if:
+  //  * |script_url| is on a different origin from |pattern|
+  //  * Fetching |script_url| fails.
+  //  * |script_url| fails to parse or its top-level execution fails.
+  //    TODO: The error message for this needs to be available to developers.
+  //  * Something unexpected goes wrong, like a renderer crash or a full disk.
+  virtual void RegisterServiceWorker(const Scope& pattern,
+                                     const GURL& script_url,
+                                     int source_process_id,
+                                     const ResultCallback& callback) = 0;
+
+  // Equivalent to calling navigator.serviceWorker.unregister(pattern) from a
+  // renderer in |source_process_id|, except that |pattern| is an absolute URL
+  // instead of relative to some current origin.  |callback| is passed true
+  // when the JS promise is fulfilled or false when the JS promise is rejected.
+  //
+  // Unregistration can fail if:
+  //  * No Service Worker was registered for |pattern|.
+  //  * Something unexpected goes wrong, like a renderer crash.
+  virtual void UnregisterServiceWorker(const Scope& pattern,
+                                       int source_process_id,
+                                       const ResultCallback& callback) = 0;
+
+  // TODO(jyasskin): Provide a way to SendMessage to a Scope.
+
+ protected:
+  ServiceWorkerContext() {}
+  virtual ~ServiceWorkerContext() {}
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_SERVICE_WORKER_CONTEXT_H_
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h
index e9682f1..3a4139d 100644
--- a/content/public/browser/storage_partition.h
+++ b/content/public/browser/storage_partition.h
@@ -38,7 +38,7 @@
 class BrowserContext;
 class IndexedDBContext;
 class DOMStorageContext;
-class ServiceWorkerContextWrapper;
+class ServiceWorkerContext;
 
 // Defines what persistent state a child process can access.
 //
@@ -57,7 +57,7 @@
   virtual webkit_database::DatabaseTracker* GetDatabaseTracker() = 0;
   virtual DOMStorageContext* GetDOMStorageContext() = 0;
   virtual IndexedDBContext* GetIndexedDBContext() = 0;
-  virtual ServiceWorkerContextWrapper* GetServiceWorkerContext() = 0;
+  virtual ServiceWorkerContext* GetServiceWorkerContext() = 0;
 
   enum RemoveDataMask {
     REMOVE_DATA_MASK_APPCACHE = 1 << 0,
diff --git a/content/public/browser/stream_handle.h b/content/public/browser/stream_handle.h
index 877c51d..b87402e 100644
--- a/content/public/browser/stream_handle.h
+++ b/content/public/browser/stream_handle.h
@@ -6,9 +6,14 @@
 #define CONTENT_PUBLIC_BROWSER_STREAM_HANDLE_H_
 
 #include "base/callback.h"
+#include "base/memory/ref_counted.h"
 #include "content/common/content_export.h"
 #include "url/gurl.h"
 
+namespace net {
+class HttpResponseHeaders;
+}
+
 namespace content {
 
 class CONTENT_EXPORT StreamHandle {
@@ -25,7 +30,7 @@
   virtual const std::string& GetMimeType() = 0;
 
   // Get the HTTP response headers associated with this Stream.
-  virtual const std::string& GetResponseHeaders() = 0;
+  virtual scoped_refptr<net::HttpResponseHeaders> GetResponseHeaders() = 0;
 };
 
 }  // namespace content
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
index d85636b..b869a52 100644
--- a/content/public/browser/web_contents_delegate.h
+++ b/content/public/browser/web_contents_delegate.h
@@ -112,7 +112,10 @@
   // Notifies the delegate that this contents is starting or is done loading
   // some resource. The delegate should use this notification to represent
   // loading feedback. See WebContents::IsLoading()
-  virtual void LoadingStateChanged(WebContents* source) {}
+  // |to_different_document| will be true unless the load is a fragment
+  // navigation, or triggered by history.pushState/replaceState.
+  virtual void LoadingStateChanged(WebContents* source,
+                                   bool to_different_document) {}
 
   // Notifies the delegate that the page has made some progress loading.
   // |progress| is a value between 0.0 (nothing loaded) to 1.0 (page fully
@@ -305,7 +308,7 @@
   // Notifies the delegate about the creation of a new WebContents. This
   // typically happens when popups are created.
   virtual void WebContentsCreated(WebContents* source_contents,
-                                  int64 source_frame_id,
+                                  int opener_render_frame_id,
                                   const base::string16& frame_name,
                                   const GURL& target_url,
                                   WebContents* new_contents) {}
diff --git a/content/public/browser/web_ui.h b/content/public/browser/web_ui.h
index 5427673..9d13240 100644
--- a/content/public/browser/web_ui.h
+++ b/content/public/browser/web_ui.h
@@ -73,8 +73,10 @@
   virtual int GetBindings() const = 0;
   virtual void SetBindings(int bindings) = 0;
 
-  // Sets the path for the iframe if this WebUI is embedded in a page.
-  virtual void SetFrameXPath(const std::string& xpath) = 0;
+  // Overrides which frame gets JavaScript messages; this is useful if this
+  // WebUI is embedded in a page. If no override is set, the main frame will
+  // receive the JavaScript messages.
+  virtual void OverrideJavaScriptFrame(const std::string& frame_name) = 0;
 
   // Takes ownership of |handler|, which will be destroyed when the WebUI is.
   virtual void AddMessageHandler(WebUIMessageHandler* handler) = 0;
diff --git a/content/public/browser/web_ui_data_source.h b/content/public/browser/web_ui_data_source.h
index b5cc6d5..ca4c9e8 100644
--- a/content/public/browser/web_ui_data_source.h
+++ b/content/public/browser/web_ui_data_source.h
@@ -25,6 +25,14 @@
 
   CONTENT_EXPORT static WebUIDataSource* Create(const std::string& source_name);
 
+#if defined(USE_MOJO)
+  // Adds the necessary resources for mojo bindings returning the
+  // WebUIDataSource that handles the resources. Callers do not own the return
+  // value.
+  CONTENT_EXPORT static WebUIDataSource* AddMojoDataSource(
+      BrowserContext* browser_context);
+#endif
+
   // Adds a WebUI data source to |browser_context|.
   CONTENT_EXPORT static void Add(BrowserContext* browser_context,
                                  WebUIDataSource* source);
diff --git a/content/public/common/common_param_traits_macros.h b/content/public/common/common_param_traits_macros.h
index a1cece3..4019287 100644
--- a/content/public/common/common_param_traits_macros.h
+++ b/content/public/common/common_param_traits_macros.h
@@ -193,7 +193,6 @@
   IPC_STRUCT_TRAITS_MEMBER(force_enable_zoom)
   IPC_STRUCT_TRAITS_MEMBER(double_tap_to_zoom_enabled)
   IPC_STRUCT_TRAITS_MEMBER(user_gesture_required_for_media_playback)
-  IPC_STRUCT_TRAITS_MEMBER(user_gesture_required_for_media_fullscreen)
   IPC_STRUCT_TRAITS_MEMBER(default_video_poster_url)
   IPC_STRUCT_TRAITS_MEMBER(support_deprecated_target_density_dpi)
   IPC_STRUCT_TRAITS_MEMBER(use_legacy_background_size_shorthand_behavior)
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 9190ca1..26d2d5a 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -155,6 +155,9 @@
 // Disable experimental WebGL support.
 const char kDisableExperimentalWebGL[]      = "disable-webgl";
 
+// Disable the fast text autosizing implementation.
+const char kDisableFastTextAutosizing[]     = "disable-fast-text-autosizing";
+
 // Disable FileSystem API.
 const char kDisableFileSystem[]             = "disable-file-system";
 
@@ -194,10 +197,6 @@
 extern const char kDisableGpuProcessCrashLimit[] =
     "disable-gpu-process-crash-limit";
 
-// Do not launch the GPU process shortly after browser process launch. Instead
-// launch it when it is first needed.
-const char kDisableGpuProcessPrelaunch[]    = "disable-gpu-process-prelaunch";
-
 // Disable GPU rasterization, i.e. rasterize on the CPU only.
 // Overrides the kEnableGpuRasterization and kForceGpuRasterization flags.
 const char kDisableGpuRasterization[]       = "disable-gpu-rasterization";
@@ -655,6 +654,10 @@
 // Makes GPU sandbox failures fatal.
 const char kGpuSandboxFailuresFatal[]       = "gpu-sandbox-failures-fatal";
 
+// Allow GPU sandbox to start later
+const char kGpuSandboxStartAfterInitialization[] =
+    "gpu-sandbox-start-after-initialization";
+
 // Causes the GPU process to display a dialog on launch.
 const char kGpuStartupDialog[]              = "gpu-startup-dialog";
 
@@ -673,10 +676,6 @@
 // Run the GPU process as a thread in the browser process.
 const char kInProcessGPU[]                  = "in-process-gpu";
 
-// These mappings only apply to the host resolver, and can insert additional
-// resolutions in front of resolutions that match a pattern.
-const char kIpResolverRules[]               = "ip-resolver-rules";
-
 // Specifies the flags passed to JS engine
 const char kJavaScriptFlags[]               = "js-flags";
 
@@ -1027,12 +1026,8 @@
 const char kRemoteDebuggingSocketName[]     = "remote-debugging-socket-name";
 #endif
 
-#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
-const char kEnableWebAudio[]                = "enable-webaudio";
-#else
 // Disable web audio API.
 const char kDisableWebAudio[]               = "disable-webaudio";
-#endif
 
 #if defined(OS_CHROMEOS)
 // Disables panel fitting (used for mirror mode).
@@ -1048,11 +1043,6 @@
     "disable-core-animation-plugins";
 #endif
 
-#if defined(OS_POSIX)
-// Causes the child processes to cleanly exit via calling exit().
-const char kChildCleanExit[]                = "child-clean-exit";
-#endif
-
 // Don't dump stuff here, follow the same order as the header.
 
 }  // namespace switches
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 5d467a4..b3f787b 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -53,6 +53,7 @@
 extern const char kDisableDirectNPAPIRequests[];
 extern const char kDisableDomainBlockingFor3DAPIs[];
 CONTENT_EXPORT extern const char kDisableExperimentalWebGL[];
+CONTENT_EXPORT extern const char kDisableFastTextAutosizing[];
 CONTENT_EXPORT extern const char kDisableFileSystem[];
 CONTENT_EXPORT extern const char kDisableFiltersOverIPC[];
 CONTENT_EXPORT extern const char kDisableFixedPositionCreatesStackingContext[];
@@ -65,7 +66,6 @@
 CONTENT_EXPORT extern const char kDisableGpu[];
 CONTENT_EXPORT extern const char kDisableGpuCompositing[];
 extern const char kDisableGpuProcessCrashLimit[];
-CONTENT_EXPORT extern const char kDisableGpuProcessPrelaunch[];
 CONTENT_EXPORT extern const char kDisableGpuRasterization[];
 CONTENT_EXPORT extern const char kDisableGpuSandbox[];
 CONTENT_EXPORT extern const char kDisableGpuWatchdog[];
@@ -189,13 +189,13 @@
 CONTENT_EXPORT extern const char kGpuProcess[];
 CONTENT_EXPORT extern const char kGpuSandboxAllowSysVShm[];
 CONTENT_EXPORT extern const char kGpuSandboxFailuresFatal[];
+CONTENT_EXPORT extern const char kGpuSandboxStartAfterInitialization[];
 CONTENT_EXPORT extern const char kGpuStartupDialog[];
 extern const char kGpuVendorID[];
 CONTENT_EXPORT extern const char kHostResolverRules[];
 CONTENT_EXPORT extern const char kIgnoreCertificateErrors[];
 CONTENT_EXPORT extern const char kIgnoreGpuBlacklist[];
 extern const char kInProcessGPU[];
-CONTENT_EXPORT extern const char kIpResolverRules[];
 CONTENT_EXPORT extern const char kJavaScriptFlags[];
 extern const char kLoadPlugin[];
 CONTENT_EXPORT extern const char kLogGpuControlListDecisions[];
@@ -297,11 +297,7 @@
 CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
 #endif
 
-#if defined(OS_ANDROID) && defined(ARCH_CPU_X86)
-CONTENT_EXPORT extern const char kEnableWebAudio[];
-#else
 CONTENT_EXPORT extern const char kDisableWebAudio[];
-#endif
 
 #if defined(OS_CHROMEOS)
 CONTENT_EXPORT extern const char kDisablePanelFitting[];
@@ -312,10 +308,6 @@
 extern const char kDisableCoreAnimationPlugins[];
 #endif
 
-#if defined(OS_POSIX)
-extern const char kChildCleanExit[];
-#endif
-
 // DON'T ADD RANDOM STUFF HERE. Put it in the main section above in
 // alphabetical order, or in one of the ifdefs (also in order in each section).
 
diff --git a/content/public/common/context_menu_params.cc b/content/public/common/context_menu_params.cc
index e125263..8289be0 100644
--- a/content/public/common/context_menu_params.cc
+++ b/content/public/common/context_menu_params.cc
@@ -19,7 +19,6 @@
       x(0),
       y(0),
       has_image_contents(true),
-      frame_id(0),
       media_flags(0),
       misspelling_hash(0),
       speech_input_enabled(false),
diff --git a/content/public/common/context_menu_params.h b/content/public/common/context_menu_params.h
index aca84e2..ccdb473 100644
--- a/content/public/common/context_menu_params.h
+++ b/content/public/common/context_menu_params.h
@@ -88,9 +88,6 @@
   // This is the URL of the subframe that the context menu was invoked on.
   GURL frame_url;
 
-  // This is the ID of the subframe that the context menu was invoked on.
-  int64 frame_id;
-
   // This is the page state of the frame on which the context menu was invoked.
   PageState frame_page_state;
 
diff --git a/content/public/common/drop_data.cc b/content/public/common/drop_data.cc
index 3536efb..5f9466b 100644
--- a/content/public/common/drop_data.cc
+++ b/content/public/common/drop_data.cc
@@ -6,18 +6,9 @@
 
 namespace content {
 
-DropData::FileInfo::FileInfo() {
-}
-
-DropData::FileInfo::FileInfo(const base::string16& path,
-                             const base::string16& display_name)
-    : path(path),
-      display_name(display_name) {
-}
-
 DropData::DropData()
-    : referrer_policy(blink::WebReferrerPolicyDefault) {
-}
+    : did_originate_from_renderer(false),
+      referrer_policy(blink::WebReferrerPolicyDefault) {}
 
 DropData::~DropData() {
 }
diff --git a/content/public/common/drop_data.h b/content/public/common/drop_data.h
index 74ad79d..91628bf 100644
--- a/content/public/common/drop_data.h
+++ b/content/public/common/drop_data.h
@@ -16,25 +16,18 @@
 #include "base/strings/nullable_string16.h"
 #include "content/common/content_export.h"
 #include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+#include "ui/base/dragdrop/file_info.h"
 #include "url/gurl.h"
 
 namespace content {
 
 struct CONTENT_EXPORT DropData {
-  // The struct is used to represent a file in the drop data.
-  struct CONTENT_EXPORT FileInfo {
-    FileInfo();
-    FileInfo(const base::string16& path, const base::string16& display_name);
-
-    // The path of the file.
-    base::string16 path;
-    // The display name of the file. This field is optional.
-    base::string16 display_name;
-  };
-
   DropData();
   ~DropData();
 
+  // Whether this drag originated from a renderer.
+  bool did_originate_from_renderer;
+
   // User is dragging a link into the webview.
   GURL url;
   base::string16 url_title;  // The title associated with |url|.
@@ -46,8 +39,10 @@
   // a download.
   blink::WebReferrerPolicy referrer_policy;
 
-  // User is dropping one or more files on the webview.
-  std::vector<FileInfo> filenames;
+  // User is dropping one or more files on the webview. This field is only
+  // populated if the drag is not renderer tainted, as this allows File access
+  // from web content.
+  std::vector<ui::FileInfo> filenames;
 
   // Isolated filesystem ID for the files being dragged on the webview.
   base::string16 filesystem_id;
diff --git a/content/public/common/media_stream_request.cc b/content/public/common/media_stream_request.cc
index 2f12be3..4a4bf72 100644
--- a/content/public/common/media_stream_request.cc
+++ b/content/public/common/media_stream_request.cc
@@ -72,6 +72,7 @@
     int render_view_id,
     int page_request_id,
     const GURL& security_origin,
+    bool user_gesture,
     MediaStreamRequestType request_type,
     const std::string& requested_audio_device_id,
     const std::string& requested_video_device_id,
@@ -81,6 +82,7 @@
       render_view_id(render_view_id),
       page_request_id(page_request_id),
       security_origin(security_origin),
+      user_gesture(user_gesture),
       request_type(request_type),
       requested_audio_device_id(requested_audio_device_id),
       requested_video_device_id(requested_video_device_id),
diff --git a/content/public/common/media_stream_request.h b/content/public/common/media_stream_request.h
index 5987e8d..7a58061 100644
--- a/content/public/common/media_stream_request.h
+++ b/content/public/common/media_stream_request.h
@@ -13,6 +13,7 @@
 #include "base/callback_forward.h"
 #include "base/memory/scoped_ptr.h"
 #include "content/common/content_export.h"
+#include "ui/gfx/native_widget_types.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -180,6 +181,7 @@
       int render_view_id,
       int page_request_id,
       const GURL& security_origin,
+      bool user_gesture,
       MediaStreamRequestType request_type,
       const std::string& requested_audio_device_id,
       const std::string& requested_video_device_id,
@@ -208,6 +210,9 @@
   // The WebKit security origin for the current request (e.g. "html5rocks.com").
   GURL security_origin;
 
+  // Set to true if the call was made in the context of a user gesture.
+  bool user_gesture;
+
   // Stores the type of request that was made to the media controller. Right now
   // this is only used to distinguish between WebRTC and Pepper requests, as the
   // latter should not be subject to user approval but only to policy check.
@@ -233,8 +238,9 @@
   virtual ~MediaStreamUI() {}
 
   // Called when MediaStream capturing is started. Chrome layer can call |stop|
-  // to stop the stream.
-  virtual void OnStarted(const base::Closure& stop) = 0;
+  // to stop the stream. Returns the platform-dependent window ID for the UI, or
+  // 0 if not applicable.
+  virtual gfx::NativeViewId OnStarted(const base::Closure& stop) = 0;
 };
 
 // Callback used return results of media access requests.
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index 793b0d9..f7de446 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -5,6 +5,7 @@
 #ifndef CONTENT_PUBLIC_RENDERER_RENDER_FRAME_H_
 #define CONTENT_PUBLIC_RENDERER_RENDER_FRAME_H_
 
+#include "base/strings/string16.h"
 #include "content/common/content_export.h"
 #include "ipc/ipc_listener.h"
 #include "ipc/ipc_sender.h"
@@ -81,6 +82,9 @@
       const blink::WebURLRequest& request,
       blink::WebNavigationPolicy policy) = 0;
 
+  // Execute a string of JavaScript in this frame's context.
+  virtual void ExecuteJavaScript(const base::string16& javascript) = 0;
+
  protected:
   virtual ~RenderFrame() {}
 
diff --git a/content/public/renderer/render_frame_observer.h b/content/public/renderer/render_frame_observer.h
index bfb40ce..b197a98 100644
--- a/content/public/renderer/render_frame_observer.h
+++ b/content/public/renderer/render_frame_observer.h
@@ -43,6 +43,7 @@
   virtual void DidStartProvisionalLoad() {}
   virtual void DidFailProvisionalLoad(const blink::WebURLError& error) {}
   virtual void DidFinishLoad() {}
+  virtual void DidFinishDocumentLoad() {}
   virtual void WillReleaseScriptContext(v8::Handle<v8::Context> context,
                                         int world_id) {}
   virtual void DidClearWindowObject(int world_id) {}
diff --git a/content/public/renderer/render_thread.h b/content/public/renderer/render_thread.h
index 4a4615e..40bcb77 100644
--- a/content/public/renderer/render_thread.h
+++ b/content/public/renderer/render_thread.h
@@ -78,9 +78,11 @@
 
   // Sends over a base::UserMetricsAction to be recorded by user metrics as
   // an action. Once a new user metric is added, run
-  //   tools/metrics/actions/extract_actions.py --hash
-  // to generate a new mapping of [action hashes -> metric names] and send it
-  // out for review to be updated.
+  //   tools/metrics/actions/extract_actions.py
+  // to add the metric to actions.xml, then update the <owner>s and
+  // <description> sections. Make sure to include the actions.xml file when you
+  // upload your code for review!
+  //
   // WARNING: When using base::UserMetricsAction, base::UserMetricsAction
   // and a string literal parameter must be on the same line, e.g.
   //   RenderThread::Get()->RecordAction(
diff --git a/content/public/renderer/render_view.h b/content/public/renderer/render_view.h
index b0e95fe..60de1c4 100644
--- a/content/public/renderer/render_view.h
+++ b/content/public/renderer/render_view.h
@@ -84,12 +84,6 @@
   // editable div, or has an ARIA role of textbox.
   virtual bool IsEditableNode(const blink::WebNode& node) const = 0;
 
-  // Evaluates a string of JavaScript in a particular frame.
-  virtual void EvaluateScript(const base::string16& frame_xpath,
-                              const base::string16& jscript,
-                              int id,
-                              bool notify_result) = 0;
-
   // Returns true if we should display scrollbars for the given view size and
   // false if the scrollbars should be hidden.
   virtual bool ShouldDisplayScrollbars(int width, int height) const = 0;
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 60c277e..9ddd8de 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -80,52 +80,11 @@
 };
 
 // Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
-bool ExecuteScriptInFrameHelper(
-    RenderViewHost* render_view_host,
-    const std::string& frame_xpath,
-    const std::string& original_script,
-    scoped_ptr<base::Value>* result) WARN_UNUSED_RESULT;
-
-// Specifying a prototype so that we can add the WARN_UNUSED_RESULT attribute.
 bool ExecuteScriptHelper(
     RenderFrameHost* render_frame_host,
     const std::string& original_script,
     scoped_ptr<base::Value>* result) WARN_UNUSED_RESULT;
 
-// Executes the passed |original_script| in the frame pointed to by
-// |frame_xpath|.  If |result| is not NULL, stores the value that the evaluation
-// of the script in |result|.  Returns true on success.
-bool ExecuteScriptInFrameHelper(RenderViewHost* render_view_host,
-                                const std::string& frame_xpath,
-                                const std::string& original_script,
-                                scoped_ptr<base::Value>* result) {
-  // TODO(jcampan): we should make the domAutomationController not require an
-  //                automation id.
-  std::string script =
-      "window.domAutomationController.setAutomationId(0);" + original_script;
-  DOMOperationObserver dom_op_observer(render_view_host);
-  render_view_host->ExecuteJavascriptInWebFrame(base::UTF8ToUTF16(frame_xpath),
-                                                base::UTF8ToUTF16(script));
-  std::string json;
-  if (!dom_op_observer.WaitAndGetResponse(&json)) {
-    DLOG(ERROR) << "Cannot communicate with DOMOperationObserver.";
-    return false;
-  }
-
-  // Nothing more to do for callers that ignore the returned JS value.
-  if (!result)
-    return true;
-
-  base::JSONReader reader(base::JSON_ALLOW_TRAILING_COMMAS);
-  result->reset(reader.ReadToValue(json));
-  if (!result->get()) {
-    DLOG(ERROR) << reader.GetErrorMessage();
-    return false;
-  }
-
-  return true;
-}
-
 // Executes the passed |original_script| in the frame specified by
 // |render_frame_host|.  If |result| is not NULL, stores the value that the
 // evaluation of the script in |result|.  Returns true on success.
@@ -429,14 +388,6 @@
 
 namespace internal {
 
-ToRenderViewHost::ToRenderViewHost(WebContents* web_contents)
-    : render_view_host_(web_contents->GetRenderViewHost()) {
-}
-
-ToRenderViewHost::ToRenderViewHost(RenderViewHost* render_view_host)
-    : render_view_host_(render_view_host) {
-}
-
 ToRenderFrameHost::ToRenderFrameHost(WebContents* web_contents)
     : render_frame_host_(web_contents->GetMainFrame()) {
 }
@@ -451,63 +402,6 @@
 
 }  // namespace internal
 
-bool ExecuteScriptInFrame(const internal::ToRenderViewHost& adapter,
-                          const std::string& frame_xpath,
-                          const std::string& original_script) {
-  std::string script =
-      original_script + ";window.domAutomationController.send(0);";
-  return ExecuteScriptInFrameHelper(
-      adapter.render_view_host(), frame_xpath, script, NULL);
-}
-
-bool ExecuteScriptInFrameAndExtractInt(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    int* result) {
-  DCHECK(result);
-  scoped_ptr<base::Value> value;
-  if (!ExecuteScriptInFrameHelper(adapter.render_view_host(),
-                                  frame_xpath, script, &value) ||
-      !value.get()) {
-    return false;
-  }
-
-  return value->GetAsInteger(result);
-}
-
-bool ExecuteScriptInFrameAndExtractBool(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    bool* result) {
-  DCHECK(result);
-  scoped_ptr<base::Value> value;
-  if (!ExecuteScriptInFrameHelper(adapter.render_view_host(),
-                                  frame_xpath, script, &value) ||
-      !value.get()) {
-    return false;
-  }
-
-  return value->GetAsBoolean(result);
-}
-
-bool ExecuteScriptInFrameAndExtractString(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    std::string* result) {
-  DCHECK(result);
-  scoped_ptr<base::Value> value;
-  if (!ExecuteScriptInFrameHelper(adapter.render_view_host(),
-                                  frame_xpath, script, &value) ||
-      !value.get()) {
-    return false;
-  }
-
-  return value->GetAsString(result);
-}
-
 bool ExecuteScript(const internal::ToRenderFrameHost& adapter,
                    const std::string& script) {
   std::string new_script =
@@ -751,7 +645,7 @@
     message_loop_runner_->Quit();
 }
 
-DOMMessageQueue::DOMMessageQueue() : waiting_for_message_(false) {
+DOMMessageQueue::DOMMessageQueue() {
   registrar_.Add(this, NOTIFICATION_DOM_OPERATION_RESPONSE,
                  NotificationService::AllSources());
 }
@@ -762,12 +656,9 @@
                               const NotificationSource& source,
                               const NotificationDetails& details) {
   Details<DomOperationNotificationDetails> dom_op_details(details);
-  Source<RenderViewHost> sender(source);
   message_queue_.push(dom_op_details->json);
-  if (waiting_for_message_) {
-    waiting_for_message_ = false;
+  if (message_loop_runner_)
     message_loop_runner_->Quit();
-  }
 }
 
 void DOMMessageQueue::ClearQueue() {
@@ -775,8 +666,8 @@
 }
 
 bool DOMMessageQueue::WaitForMessage(std::string* message) {
+  DCHECK(message);
   if (message_queue_.empty()) {
-    waiting_for_message_ = true;
     // This will be quit when a new message comes in.
     message_loop_runner_ = new MessageLoopRunner;
     message_loop_runner_->Run();
@@ -784,8 +675,7 @@
   // The queue should not be empty, unless we were quit because of a timeout.
   if (message_queue_.empty())
     return false;
-  if (message)
-    *message = message_queue_.front();
+  *message = message_queue_.front();
   message_queue_.pop();
   return true;
 }
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h
index c1feaf5..63d68bd 100644
--- a/content/public/test/browser_test_utils.h
+++ b/content/public/test/browser_test_utils.h
@@ -112,24 +112,6 @@
                               bool command);
 
 namespace internal {
-// Allow ExecuteScriptInFrame* methods to target either a WebContents or a
-// RenderViewHost.  Targetting a WebContents means executing the script in the
-// RenderViewHost returned by WebContents::GetRenderViewHost(), which is the
-// "current" RenderViewHost.  Pass a specific RenderViewHost to target, for
-// example, a "swapped-out" RenderViewHost.
-// OBSOLETE; DO NOT USE! Use ExecuteScript* methods that target a
-// RenderFrameHost instead.
-class ToRenderViewHost {
- public:
-  ToRenderViewHost(WebContents* web_contents);
-  ToRenderViewHost(RenderViewHost* render_view_host);
-
-  RenderViewHost* render_view_host() const { return render_view_host_; }
-
- private:
-  RenderViewHost* render_view_host_;
-};
-
 // Allow ExecuteScript* methods to target either a WebContents or a
 // RenderFrameHost.  Targetting a WebContents means executing the script in the
 // RenderFrameHost returned by WebContents::GetMainFrame(), which is the
@@ -147,39 +129,6 @@
 };
 }  // namespace internal
 
-// Executes the passed |script| in the frame pointed to by |frame_xpath| (use
-// empty string for main frame). The |script| should not invoke
-// domAutomationController.send(); otherwise, your test will hang or be flaky.
-// If you want to extract a result, use one of the below functions.
-// Returns true on success.
-// OBSOLETE; DO NOT USE! Use ExecuteScript and specify a RenderFrameHost.
-bool ExecuteScriptInFrame(const internal::ToRenderViewHost& adapter,
-                          const std::string& frame_xpath,
-                          const std::string& script) WARN_UNUSED_RESULT;
-
-// The following methods executes the passed |script| in the frame pointed to by
-// |frame_xpath| (use empty string for main frame) and sets |result| to the
-// value passed to "window.domAutomationController.send" by the executed script.
-// They return true on success, false if the script execution failed or did not
-// evaluate to the expected type.
-// OBSOLETE; DO NOT USE! Use ExecuteScriptAndExtract[Int|Bool|String] and
-// specify a RenderFrameHost.
-bool ExecuteScriptInFrameAndExtractInt(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    int* result) WARN_UNUSED_RESULT;
-bool ExecuteScriptInFrameAndExtractBool(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    bool* result) WARN_UNUSED_RESULT;
-bool ExecuteScriptInFrameAndExtractString(
-    const internal::ToRenderViewHost& adapter,
-    const std::string& frame_xpath,
-    const std::string& script,
-    std::string* result) WARN_UNUSED_RESULT;
-
 // Executes the passed |script| in the specified frame. The |script| should not
 // invoke domAutomationController.send(); otherwise, your test will hang or be
 // flaky. If you want to extract a result, use one of the below functions.
@@ -328,7 +277,7 @@
   void ClearQueue();
 
   // Wait for the next message to arrive. |message| will be set to the next
-  // message, if not null. Returns true on success.
+  // message. Returns true on success.
   bool WaitForMessage(std::string* message) WARN_UNUSED_RESULT;
 
   // Overridden NotificationObserver methods.
@@ -339,7 +288,6 @@
  private:
   NotificationRegistrar registrar_;
   std::queue<std::string> message_queue_;
-  bool waiting_for_message_;
   scoped_refptr<MessageLoopRunner> message_loop_runner_;
 
   DISALLOW_COPY_AND_ASSIGN(DOMMessageQueue);
diff --git a/content/public/test/content_browser_test.cc b/content/public/test/content_browser_test.cc
new file mode 100644
index 0000000..8d26969
--- /dev/null
+++ b/content/public/test/content_browser_test.cc
@@ -0,0 +1,175 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/test/content_browser_test.h"
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_browser_context.h"
+#include "content/shell/browser/shell_content_browser_client.h"
+#include "content/shell/common/shell_switches.h"
+#include "content/shell/renderer/shell_content_renderer_client.h"
+#include "content/test/test_content_client.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+
+#if defined(OS_ANDROID)
+#include "content/shell/app/shell_main_delegate.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif
+
+#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(USE_X11)
+#include "ui/base/ime/input_method_initializer.h"
+#endif
+
+namespace content {
+
+ContentBrowserTest::ContentBrowserTest()
+    : setup_called_(false) {
+#if defined(OS_MACOSX)
+  // See comment in InProcessBrowserTest::InProcessBrowserTest().
+  base::FilePath content_shell_path;
+  CHECK(PathService::Get(base::FILE_EXE, &content_shell_path));
+  content_shell_path = content_shell_path.DirName();
+  content_shell_path = content_shell_path.Append(
+      FILE_PATH_LITERAL("Content Shell.app/Contents/MacOS/Content Shell"));
+  CHECK(PathService::Override(base::FILE_EXE, content_shell_path));
+#endif
+  base::FilePath content_test_data(FILE_PATH_LITERAL("content/test/data"));
+  CreateTestServer(content_test_data);
+  base::FilePath content_test_data_absolute;
+  CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &content_test_data_absolute));
+  content_test_data_absolute =
+      content_test_data_absolute.Append(content_test_data);
+  embedded_test_server()->ServeFilesFromDirectory(content_test_data_absolute);
+}
+
+ContentBrowserTest::~ContentBrowserTest() {
+  CHECK(setup_called_) << "Overridden SetUp() did not call parent "
+                          "implementation, so test not run.";
+}
+
+void ContentBrowserTest::SetUp() {
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  command_line->AppendSwitch(switches::kContentBrowserTest);
+
+  SetUpCommandLine(command_line);
+
+#if defined(OS_ANDROID)
+  shell_main_delegate_.reset(new ShellMainDelegate);
+  shell_main_delegate_->PreSandboxStartup();
+  if (command_line->HasSwitch(switches::kSingleProcess)) {
+    // We explicitly leak the new ContentRendererClient as we're
+    // setting a global that may be used after ContentBrowserTest is
+    // destroyed.
+    ContentRendererClient* old_client =
+        SetRendererClientForTesting(new ShellContentRendererClient());
+    // No-one should have set this value before we did.
+    DCHECK(!old_client);
+  }
+#elif defined(OS_MACOSX)
+  // See InProcessBrowserTest::PrepareTestCommandLine().
+  base::FilePath subprocess_path;
+  PathService::Get(base::FILE_EXE, &subprocess_path);
+  subprocess_path = subprocess_path.DirName().DirName();
+  DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
+  subprocess_path = subprocess_path.Append(
+      "Frameworks/Content Shell Helper.app/Contents/MacOS/Content Shell Helper");
+  command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
+                                 subprocess_path);
+#endif
+
+  // LinuxInputMethodContextFactory has to be initialized.
+#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(USE_X11)
+  ui::InitializeInputMethodForTesting();
+#endif
+
+  setup_called_ = true;
+
+  BrowserTestBase::SetUp();
+}
+
+void ContentBrowserTest::TearDown() {
+  BrowserTestBase::TearDown();
+
+  // LinuxInputMethodContextFactory has to be shutdown.
+#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(USE_X11)
+  ui::ShutdownInputMethodForTesting();
+#endif
+
+#if defined(OS_ANDROID)
+  shell_main_delegate_.reset();
+#endif
+}
+
+void ContentBrowserTest::RunTestOnMainThreadLoop() {
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
+    CHECK_EQ(Shell::windows().size(), 1u);
+    shell_ = Shell::windows()[0];
+  }
+
+#if defined(OS_MACOSX)
+  // On Mac, without the following autorelease pool, code which is directly
+  // executed (as opposed to executed inside a message loop) would autorelease
+  // objects into a higher-level pool. This pool is not recycled in-sync with
+  // the message loops' pools and causes problems with code relying on
+  // deallocation via an autorelease pool (such as browser window closure and
+  // browser shutdown). To avoid this, the following pool is recycled after each
+  // time code is directly executed.
+  base::mac::ScopedNSAutoreleasePool pool;
+#endif
+
+  // Pump startup related events.
+  base::MessageLoopForUI::current()->RunUntilIdle();
+
+#if defined(OS_MACOSX)
+  pool.Recycle();
+#endif
+
+  SetUpOnMainThread();
+
+  RunTestOnMainThread();
+
+  TearDownOnMainThread();
+#if defined(OS_MACOSX)
+  pool.Recycle();
+#endif
+
+  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
+       !i.IsAtEnd(); i.Advance()) {
+    i.GetCurrentValue()->FastShutdownIfPossible();
+  }
+
+  Shell::CloseAllWindows();
+}
+
+Shell* ContentBrowserTest::CreateBrowser() {
+  return Shell::CreateNewWindow(
+      ShellContentBrowserClient::Get()->browser_context(),
+      GURL(kAboutBlankURL),
+      NULL,
+      MSG_ROUTING_NONE,
+      gfx::Size());
+}
+
+Shell* ContentBrowserTest::CreateOffTheRecordBrowser() {
+  return Shell::CreateNewWindow(
+      ShellContentBrowserClient::Get()->off_the_record_browser_context(),
+      GURL(kAboutBlankURL),
+      NULL,
+      MSG_ROUTING_NONE,
+      gfx::Size());
+}
+
+}  // namespace content
diff --git a/content/public/test/content_browser_test.h b/content/public/test/content_browser_test.h
new file mode 100644
index 0000000..7fa9d34
--- /dev/null
+++ b/content/public/test/content_browser_test.h
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_H_
+#define CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_base.h"
+
+namespace content {
+class Shell;
+class ShellMainDelegate;
+
+// Base class for browser tests which use content_shell.
+class ContentBrowserTest : public BrowserTestBase {
+ protected:
+  ContentBrowserTest();
+  virtual ~ContentBrowserTest();
+
+  // testing::Test:
+  virtual void SetUp() OVERRIDE;
+  virtual void TearDown() OVERRIDE;
+
+  // BrowserTestBase:
+  virtual void RunTestOnMainThreadLoop() OVERRIDE;
+
+ protected:
+  // Creates a new window and loads about:blank.
+  Shell* CreateBrowser();
+
+  // Creates an off-the-record window and loads about:blank.
+  Shell* CreateOffTheRecordBrowser();
+
+  // Returns the window for the test.
+  Shell* shell() const { return shell_; }
+
+ private:
+  Shell* shell_;
+
+  bool setup_called_;
+
+#if defined(OS_ANDROID)
+  // For all other platforms, this is done automatically when calling into
+  // ContentMain. For Android we set things up manually.
+  scoped_ptr<ShellMainDelegate> shell_main_delegate_;
+#endif
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_H_
diff --git a/content/public/test/content_browser_test_utils.cc b/content/public/test/content_browser_test_utils.cc
new file mode 100644
index 0000000..44e5089
--- /dev/null
+++ b/content/public/test/content_browser_test_utils.cc
@@ -0,0 +1,85 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/test/content_browser_test_utils.h"
+
+#include "base/bind.h"
+#include "base/files/file_path.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/notification_source.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/shell/browser/shell_javascript_dialog_manager.h"
+#include "net/base/net_util.h"
+
+namespace content {
+
+base::FilePath GetTestFilePath(const char* dir, const char* file) {
+  base::FilePath path;
+  PathService::Get(DIR_TEST_DATA, &path);
+  return path.Append(base::FilePath().AppendASCII(dir).Append(
+      base::FilePath().AppendASCII(file)));
+}
+
+GURL GetTestUrl(const char* dir, const char* file) {
+  return net::FilePathToFileURL(GetTestFilePath(dir, file));
+}
+
+void NavigateToURLBlockUntilNavigationsComplete(Shell* window,
+                                                const GURL& url,
+                                                int number_of_navigations) {
+  WaitForLoadStop(window->web_contents());
+  TestNavigationObserver same_tab_observer(window->web_contents(),
+                                           number_of_navigations);
+
+  window->LoadURL(url);
+  same_tab_observer.Wait();
+}
+
+void NavigateToURL(Shell* window, const GURL& url) {
+  NavigateToURLBlockUntilNavigationsComplete(window, url, 1);
+}
+
+void WaitForAppModalDialog(Shell* window) {
+  ShellJavaScriptDialogManager* dialog_manager=
+      static_cast<ShellJavaScriptDialogManager*>(
+          window->GetJavaScriptDialogManager());
+
+  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
+  dialog_manager->set_dialog_request_callback(runner->QuitClosure());
+  runner->Run();
+}
+
+ShellAddedObserver::ShellAddedObserver()
+    : shell_(NULL) {
+  Shell::SetShellCreatedCallback(
+      base::Bind(&ShellAddedObserver::ShellCreated, base::Unretained(this)));
+}
+
+ShellAddedObserver::~ShellAddedObserver() {
+}
+
+Shell* ShellAddedObserver::GetShell() {
+  if (shell_)
+    return shell_;
+
+  runner_ = new MessageLoopRunner();
+  runner_->Run();
+  return shell_;
+}
+
+void ShellAddedObserver::ShellCreated(Shell* shell) {
+  DCHECK(!shell_);
+  shell_ = shell;
+  if (runner_.get())
+    runner_->QuitClosure().Run();
+}
+
+}  // namespace content
diff --git a/content/public/test/content_browser_test_utils.h b/content/public/test/content_browser_test_utils.h
new file mode 100644
index 0000000..2afc936
--- /dev/null
+++ b/content/public/test/content_browser_test_utils.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_
+#define CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_
+
+#include "base/memory/ref_counted.h"
+#include "ui/gfx/native_widget_types.h"
+#include "url/gurl.h"
+
+namespace base {
+class FilePath;
+}
+
+namespace gfx {
+class Rect;
+}
+
+// A collections of functions designed for use with content_shell based browser
+// tests.
+// Note: if a function here also works with browser_tests, it should be in
+// content\public\test\browser_test_utils.h
+
+namespace content {
+
+class MessageLoopRunner;
+class Shell;
+
+// Generate the file path for testing a particular test.
+// The file for the tests is all located in
+// content/test/data/dir/<file>
+// The returned path is FilePath format.
+base::FilePath GetTestFilePath(const char* dir, const char* file);
+
+// Generate the URL for testing a particular test.
+// HTML for the tests is all located in
+// test_root_directory/dir/<file>
+// The returned path is GURL format.
+GURL GetTestUrl(const char* dir, const char* file);
+
+// Navigates the selected tab of |window| to |url|, blocking until the
+// navigation finishes.
+void NavigateToURL(Shell* window, const GURL& url);
+
+// Navigates the selected tab of |window| to |url|, blocking until the given
+// number of navigations finishes.
+void NavigateToURLBlockUntilNavigationsComplete(Shell* window,
+                                                const GURL& url,
+                                                int number_of_navigations);
+
+// Wait until an application modal dialog is requested.
+void WaitForAppModalDialog(Shell* window);
+
+// Used to wait for a new Shell window to be created. Instantiate this object
+// before the operation that will create the window.
+class ShellAddedObserver {
+ public:
+  ShellAddedObserver();
+  ~ShellAddedObserver();
+
+  // Will run a message loop to wait for the new window if it hasn't been
+  // created since the constructor.
+  Shell* GetShell();
+
+ private:
+  void ShellCreated(Shell* shell);
+
+  Shell* shell_;
+  scoped_refptr<MessageLoopRunner> runner_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShellAddedObserver);
+};
+
+#if defined OS_MACOSX
+void SetWindowBounds(gfx::NativeWindow window, const gfx::Rect& bounds);
+#endif
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_TEST_CONTENT_BROWSER_TEST_UTILS_H_
diff --git a/content/public/test/content_browser_test_utils_mac.mm b/content/public/test/content_browser_test_utils_mac.mm
new file mode 100644
index 0000000..629f63f
--- /dev/null
+++ b/content/public/test/content_browser_test_utils_mac.mm
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/test/content_browser_test_utils.h"
+
+#include <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+
+#include "ui/gfx/rect.h"
+
+namespace content {
+
+void SetWindowBounds(gfx::NativeWindow window, const gfx::Rect& bounds) {
+  NSRect new_bounds = NSRectFromCGRect(bounds.ToCGRect());
+  if ([[NSScreen screens] count] > 0) {
+    new_bounds.origin.y =
+        [[[NSScreen screens] objectAtIndex:0] frame].size.height -
+        new_bounds.origin.y - new_bounds.size.height;
+  }
+
+  [window setFrame:new_bounds display:NO];
+}
+
+}  // namespace content
diff --git a/content/public/test/layouttest_support.h b/content/public/test/layouttest_support.h
index 370a6e4..6c7e847 100644
--- a/content/public/test/layouttest_support.h
+++ b/content/public/test/layouttest_support.h
@@ -11,6 +11,7 @@
 namespace blink {
 class WebDeviceMotionData;
 class WebDeviceOrientationData;
+class WebGamepad;
 class WebGamepads;
 struct WebSize;
 }
@@ -42,6 +43,12 @@
 // WebKitPlatformSupport::sampleGamepads().
 void SetMockGamepads(const blink::WebGamepads& pads);
 
+// Notifies blink about a new gamepad.
+void MockGamepadConnected(int index, const blink::WebGamepad& pad);
+
+// Notifies blink that a gamepad has been disconnected.
+void MockGamepadDisconnected(int index, const blink::WebGamepad& pad);
+
 // Sets WebDeviceMotionData that should be used when registering
 // a listener through WebKitPlatformSupport::setDeviceMotionListener().
 void SetMockDeviceMotionData(const blink::WebDeviceMotionData& data);
diff --git a/content/public/test/mock_download_item.h b/content/public/test/mock_download_item.h
index 23b140c..6a365f5 100644
--- a/content/public/test/mock_download_item.h
+++ b/content/public/test/mock_download_item.h
@@ -41,6 +41,8 @@
   MOCK_CONST_METHOD0(GetUrlChain, const std::vector<GURL>&());
   MOCK_CONST_METHOD0(GetOriginalUrl, const GURL&());
   MOCK_CONST_METHOD0(GetReferrerUrl, const GURL&());
+  MOCK_CONST_METHOD0(GetTabUrl, const GURL&());
+  MOCK_CONST_METHOD0(GetTabReferrerUrl, const GURL&());
   MOCK_CONST_METHOD0(GetSuggestedFilename, std::string());
   MOCK_CONST_METHOD0(GetContentDisposition, std::string());
   MOCK_CONST_METHOD0(GetMimeType, std::string());
diff --git a/content/public/test/test_browser_context.cc b/content/public/test/test_browser_context.cc
index a708c26..20b7b88 100644
--- a/content/public/test/test_browser_context.cc
+++ b/content/public/test/test_browser_context.cc
@@ -103,6 +103,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) {
   // Always reject requests for testing.
   callback.Run(false);
diff --git a/content/public/test/test_browser_context.h b/content/public/test/test_browser_context.h
index 2c0021e..9019330 100644
--- a/content/public/test/test_browser_context.h
+++ b/content/public/test/test_browser_context.h
@@ -45,6 +45,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) OVERRIDE;
   virtual void CancelMidiSysExPermissionRequest(
         int render_process_id,
diff --git a/content/renderer/accessibility/accessibility_node_serializer.cc b/content/renderer/accessibility/accessibility_node_serializer.cc
index 9912332..08e6f1d 100644
--- a/content/renderer/accessibility/accessibility_node_serializer.cc
+++ b/content/renderer/accessibility/accessibility_node_serializer.cc
@@ -75,6 +75,17 @@
   return std::string();
 }
 
+void AddIntListAttributeFromWebObjects(ui::AXIntListAttribute attr,
+                                       WebVector<WebAXObject> objects,
+                                       ui::AXNodeData* dst) {
+  std::vector<int32> ids;
+  for(size_t i = 0; i < objects.size(); i++)
+    ids.push_back(objects[i].axID());
+  if (ids.size() > 0)
+    dst->AddIntListAttribute(attr, ids);
+}
+
+
 }  // Anonymous namespace
 
 void SerializeAccessibilityNode(
@@ -158,6 +169,11 @@
     dst->AddIntAttribute(ui::AX_ATTR_TITLE_UI_ELEMENT,
                          src.titleUIElement().axID());
   }
+  if (!src.ariaActiveDescendant().isDetached()) {
+    dst->AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
+                         src.ariaActiveDescendant().axID());
+  }
+
   if (!src.url().isEmpty())
     dst->AddStringAttribute(ui::AX_ATTR_URL, src.url().spec());
 
@@ -409,16 +425,40 @@
   // parent is the row, the row adds it as a child, and the column adds it
   // as an indirect child.
   int child_count = src.childCount();
+  std::vector<int32> indirect_child_ids;
   for (int i = 0; i < child_count; ++i) {
     WebAXObject child = src.childAt(i);
-    std::vector<int32> indirect_child_ids;
     if (!is_iframe && !child.isDetached() && !IsParentUnignoredOf(src, child))
       indirect_child_ids.push_back(child.axID());
-    if (indirect_child_ids.size() > 0) {
-      dst->AddIntListAttribute(
-          ui::AX_ATTR_INDIRECT_CHILD_IDS, indirect_child_ids);
-    }
   }
+  if (indirect_child_ids.size() > 0) {
+    dst->AddIntListAttribute(ui::AX_ATTR_INDIRECT_CHILD_IDS,
+                             indirect_child_ids);
+  }
+
+  WebVector<WebAXObject> controls;
+  if (src.ariaControls(controls))
+    AddIntListAttributeFromWebObjects(ui::AX_ATTR_CONTROLS_IDS, controls, dst);
+
+  WebVector<WebAXObject> describedby;
+  if (src.ariaDescribedby(describedby)) {
+    AddIntListAttributeFromWebObjects(
+        ui::AX_ATTR_DESCRIBEDBY_IDS, describedby, dst);
+  }
+
+  WebVector<WebAXObject> flowTo;
+  if (src.ariaFlowTo(flowTo))
+    AddIntListAttributeFromWebObjects(ui::AX_ATTR_FLOWTO_IDS, flowTo, dst);
+
+  WebVector<WebAXObject> labelledby;
+  if (src.ariaLabelledby(labelledby)) {
+    AddIntListAttributeFromWebObjects(
+        ui::AX_ATTR_LABELLEDBY_IDS, labelledby, dst);
+  }
+
+  WebVector<WebAXObject> owns;
+  if (src.ariaOwns(owns))
+    AddIntListAttributeFromWebObjects(ui::AX_ATTR_OWNS_IDS, owns, dst);
 }
 
 bool ShouldIncludeChildNode(
diff --git a/content/renderer/accessibility/blink_ax_enum_conversion.cc b/content/renderer/accessibility/blink_ax_enum_conversion.cc
index ba7833f..8a2c5aa 100644
--- a/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -344,7 +344,7 @@
     case blink::WebAXEventMenuListItemSelected:
       return ui::AX_EVENT_MENU_LIST_ITEM_SELECTED;
     case blink::WebAXEventMenuListValueChanged:
-      return ui::AX_EVENT_MENU_LIST_VALUE_CHANGED;
+        return ui::AX_EVENT_MENU_LIST_VALUE_CHANGED;
     case blink::WebAXEventRowCollapsed:
       return ui::AX_EVENT_ROW_COLLAPSED;
     case blink::WebAXEventRowCountChanged:
diff --git a/content/renderer/accessibility/renderer_accessibility.h b/content/renderer/accessibility/renderer_accessibility.h
index 0bb804c..1f9fd36 100644
--- a/content/renderer/accessibility/renderer_accessibility.h
+++ b/content/renderer/accessibility/renderer_accessibility.h
@@ -16,6 +16,18 @@
 namespace content {
 class RenderViewImpl;
 
+enum RendererAccessibilityType {
+  // Turns on Blink accessibility and provides a full accessibility
+  // implementation for when assistive technology is running.
+  RendererAccessibilityTypeComplete,
+
+  // Does not turn on Blink accessibility. Only sends a minimal accessible tree
+  // to the browser whenever focus changes. This mode is currently used to
+  // support opening the on-screen keyboard in response to touch events on
+  // Windows 8 in Metro mode.
+  RendererAccessibilityTypeFocusOnly
+};
+
 // The browser process implement native accessibility APIs, allowing
 // assistive technology (e.g., screen readers, magnifiers) to access and
 // control the web contents with high-level APIs. These APIs are also used
@@ -36,27 +48,29 @@
 // This base class just contains common code and will not do anything by itself.
 // The two subclasses are:
 //
-//   RendererAccessibilityComplete - turns on WebKit accessibility and
+//   RendererAccessibilityComplete - turns on Blink accessibility and
 //       provides a full accessibility implementation for when
 //       assistive technology is running.
 //
-//   RendererAccessibilityFocusOnly - does not turn on WebKit
+//   RendererAccessibilityFocusOnly - does not turn on Blink
 //       accessibility. Only sends a minimal accessible tree to the
 //       browser whenever focus changes. This mode is currently used
 //       to support opening the on-screen keyboard in response to
 //       touch events on Windows 8 in Metro mode.
 //
-// What both subclasses have in common is that they are responsible for
-//
 class CONTENT_EXPORT RendererAccessibility : public RenderViewObserver {
  public:
   explicit RendererAccessibility(RenderViewImpl* render_view);
   virtual ~RendererAccessibility();
 
-  // Called when an accessibility notification occurs in WebKit.
+  // Called when an accessibility notification occurs in Blink.
   virtual void HandleWebAccessibilityEvent(
       const blink::WebAXObject& obj, blink::WebAXEvent event) = 0;
 
+  // Gets the type of this RendererAccessibility object. Primarily intended for
+  // testing.
+  virtual RendererAccessibilityType GetType() = 0;
+
  protected:
   // Returns the main top-level document for this page, or NULL if there's
   // no view or frame.
diff --git a/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
index 4c1ab58..95f2c42 100644
--- a/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/content/renderer/accessibility/renderer_accessibility_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "content/common/frame_messages.h"
+#include "content/common/view_message_enums.h"
 #include "content/public/test/render_view_test.h"
 #include "content/renderer/accessibility/renderer_accessibility_complete.h"
 #include "content/renderer/render_view_impl.h"
@@ -71,7 +72,7 @@
     sink_ = &render_thread_->sink();
   }
 
-  void SetMode(unsigned int mode) {
+  void SetMode(AccessibilityMode mode) {
     view()->OnSetAccessibilityMode(mode);
   }
 
@@ -349,7 +350,7 @@
   accessibility->HandleAXEvent(
       root_obj,
       ui::AX_EVENT_VALUE_CHANGED);
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
   accessibility->SendPendingAccessibilityEvents();
   EXPECT_FALSE(sink_->GetUniqueMessageMatching(
       AccessibilityHostMsg_Events::ID));
diff --git a/content/renderer/accessibility/renderer_accessibility_complete.cc b/content/renderer/accessibility/renderer_accessibility_complete.cc
index 660cd76..b4ea81e 100644
--- a/content/renderer/accessibility/renderer_accessibility_complete.cc
+++ b/content/renderer/accessibility/renderer_accessibility_complete.cc
@@ -93,7 +93,7 @@
 
   if (node.isNull()) {
     // When focus is cleared, implicitly focus the document.
-    // TODO(dmazzoni): Make WebKit send this notification instead.
+    // TODO(dmazzoni): Make Blink send this notification instead.
     HandleAXEvent(document.accessibilityObject(), ui::AX_EVENT_BLUR);
   }
 }
@@ -104,7 +104,7 @@
     return;
 
   // Check to see if the root accessibility object has changed, to work
-  // around WebKit bugs that cause AXObjectCache to be cleared
+  // around Blink bugs that cause AXObjectCache to be cleared
   // unnecessarily.
   // TODO(dmazzoni): remove this once rdar://5794454 is fixed.
   WebAXObject new_root = document.accessibilityObject();
@@ -165,6 +165,10 @@
   }
 }
 
+RendererAccessibilityType RendererAccessibilityComplete::GetType() {
+  return RendererAccessibilityTypeComplete;
+}
+
 RendererAccessibilityComplete::BrowserTreeNode::BrowserTreeNode() : id(0) {}
 
 RendererAccessibilityComplete::BrowserTreeNode::~BrowserTreeNode() {}
@@ -189,7 +193,7 @@
       pending_events_;
   pending_events_.clear();
 
-  // Generate an event message from each WebKit event.
+  // Generate an event message from each Blink event.
   std::vector<AccessibilityHostMsg_EventParams> event_msgs;
 
   // Loop over each event and generate an updated event message.
@@ -202,7 +206,7 @@
     if (!obj.updateBackingStoreAndCheckValidity())
       continue;
 
-    // When we get a "selected children changed" event, WebKit
+    // When we get a "selected children changed" event, Blink
     // doesn't also send us events for each child that changed
     // selection state, so make sure we re-send that whole subtree.
     if (event.event_type ==
@@ -268,7 +272,7 @@
       }
     }
 
-    // Allow WebKit to cache intermediate results since we're doing a bunch
+    // Allow Blink to cache intermediate results since we're doing a bunch
     // of read-only queries at once.
     root_object.startCachingComputedObjectAttributesUntilTreeMutates();
 
@@ -392,7 +396,7 @@
 
       BrowserTreeNode* child = browser_id_map_[new_child_id];
       if (child && child->parent != browser_node) {
-        // The child is being reparented. Find the WebKit accessibility
+        // The child is being reparented. Find the Blink accessibility
         // object corresponding to the old parent, or the closest ancestor
         // still in the tree.
         BrowserTreeNode* parent = child->parent;
diff --git a/content/renderer/accessibility/renderer_accessibility_complete.h b/content/renderer/accessibility/renderer_accessibility_complete.h
index 6e18a2a..2511e3e 100644
--- a/content/renderer/accessibility/renderer_accessibility_complete.h
+++ b/content/renderer/accessibility/renderer_accessibility_complete.h
@@ -28,7 +28,7 @@
 // complete accessibility support for assistive technology (as opposed to
 // partial support - see RendererAccessibilityFocusOnly).
 //
-// This version turns on WebKit's accessibility code and sends
+// This version turns on Blink's accessibility code and sends
 // a serialized representation of that tree whenever it changes. It also
 // handles requests from the browser to perform accessibility actions on
 // nodes in the tree (e.g., change focus, or click on a button).
@@ -46,6 +46,7 @@
   // RendererAccessibility.
   virtual void HandleWebAccessibilityEvent(
       const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE;
+  virtual RendererAccessibilityType GetType() OVERRIDE;
 
   void HandleAXEvent(const blink::WebAXObject& obj, ui::AXEvent event);
 
@@ -96,10 +97,10 @@
   void OnSetTextSelection(int acc_obj_id, int start_offset, int end_offset);
   void OnFatalError();
 
-  // Checks if a WebKit accessibility object is an editable text node.
+  // Checks if a Blink accessibility object is an editable text node.
   bool IsEditableText(const blink::WebAXObject& node);
 
-  // Recursively explore the tree of WebKit accessibility objects rooted
+  // Recursively explore the tree of Blink accessibility objects rooted
   // at |src|, and for each editable text node encountered, add a
   // corresponding WebAccessibility node as a child of |dst|.
   void RecursiveAddEditableTextNodesToTree(
@@ -107,7 +108,7 @@
       ui::AXNodeData* dst);
 
   // Build a tree of serializable ui::AXNodeData nodes to send to the
-  // browser process, given a WebAXObject node from WebKit.
+  // browser process, given a WebAXObject node from Blink.
   // Modifies |dst| in-place, it's assumed to be empty.
   void BuildAccessibilityTree(const blink::WebAXObject& src,
                               bool include_children,
@@ -116,7 +117,7 @@
   // So we can queue up tasks to be executed later.
   base::WeakPtrFactory<RendererAccessibilityComplete> weak_factory_;
 
-  // Events from WebKit are collected until they are ready to be
+  // Events from Blink are collected until they are ready to be
   // sent to the browser.
   std::vector<AccessibilityHostMsg_EventParams> pending_events_;
 
diff --git a/content/renderer/accessibility/renderer_accessibility_focus_only.cc b/content/renderer/accessibility/renderer_accessibility_focus_only.cc
index 59a168a..651b30b 100644
--- a/content/renderer/accessibility/renderer_accessibility_focus_only.cc
+++ b/content/renderer/accessibility/renderer_accessibility_focus_only.cc
@@ -40,6 +40,10 @@
   // Do nothing.
 }
 
+RendererAccessibilityType RendererAccessibilityFocusOnly::GetType() {
+  return RendererAccessibilityTypeFocusOnly;
+}
+
 void RendererAccessibilityFocusOnly::FocusedNodeChanged(const WebNode& node) {
   // Send the new accessible tree and post a native focus event.
   HandleFocusedNodeChanged(node, true);
@@ -69,7 +73,7 @@
   bool node_is_editable_text;
   // Check HasIMETextFocus first, because it will correctly handle
   // focus in a text box inside a ppapi plug-in. Otherwise fall back on
-  // checking the focused node in WebKit.
+  // checking the focused node in Blink.
   if (render_view_->HasIMETextFocus()) {
     node_has_focus = true;
     node_is_editable_text = true;
diff --git a/content/renderer/accessibility/renderer_accessibility_focus_only.h b/content/renderer/accessibility/renderer_accessibility_focus_only.h
index c8e09c5..f5152fd 100644
--- a/content/renderer/accessibility/renderer_accessibility_focus_only.h
+++ b/content/renderer/accessibility/renderer_accessibility_focus_only.h
@@ -55,6 +55,7 @@
   // RendererAccessibility implementation.
   virtual void HandleWebAccessibilityEvent(
       const blink::WebAXObject& obj, blink::WebAXEvent event) OVERRIDE;
+  virtual RendererAccessibilityType GetType() OVERRIDE;
 
   // RenderView::Observer implementation.
   virtual void FocusedNodeChanged(const blink::WebNode& node) OVERRIDE;
diff --git a/content/renderer/bmp_image_decoder_unittest.cc b/content/renderer/bmp_image_decoder_unittest.cc
index 666196a..a249126 100644
--- a/content/renderer/bmp_image_decoder_unittest.cc
+++ b/content/renderer/bmp_image_decoder_unittest.cc
@@ -26,7 +26,7 @@
 }
 
 #if defined(THREAD_SANITIZER)
-// BMPImageDecoderTest.DecodingSlow als times out under ThreadSanitizer v2.
+// BMPImageDecoderTest.DecodingSlow always times out under ThreadSanitizer v2.
 #define MAYBE_DecodingSlow DISABLED_DecodingSlow
 #else
 #define MAYBE_DecodingSlow DecodingSlow
diff --git a/content/renderer/browser_render_view_browsertest.cc b/content/renderer/browser_render_view_browsertest.cc
index 3557f6f..1172d02 100644
--- a/content/renderer/browser_render_view_browsertest.cc
+++ b/content/renderer/browser_render_view_browsertest.cc
@@ -19,14 +19,14 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_browser_context.h"
 #include "content/shell/browser/shell_content_browser_client.h"
 #include "content/shell/common/shell_content_client.h"
 #include "content/shell/renderer/shell_content_renderer_client.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/net_errors.h"
 #include "net/disk_cache/disk_cache.h"
 #include "net/http/failing_http_transaction_factory.h"
diff --git a/content/renderer/device_orientation/device_orientation_event_pump.cc b/content/renderer/device_orientation/device_orientation_event_pump.cc
index 1493043..2ee6d21 100644
--- a/content/renderer/device_orientation/device_orientation_event_pump.cc
+++ b/content/renderer/device_orientation/device_orientation_event_pump.cc
@@ -60,13 +60,20 @@
 
 bool DeviceOrientationEventPump::ShouldFireEvent(
     const blink::WebDeviceOrientationData& data) const {
-  return data.allAvailableSensorsAreActive &&
-      (IsSignificantlyDifferent(
-          data_.hasAlpha, data_.alpha, data.hasAlpha, data.alpha) ||
-       IsSignificantlyDifferent(
-          data_.hasBeta, data_.beta, data.hasBeta, data.beta) ||
-       IsSignificantlyDifferent(
-          data_.hasGamma, data_.gamma, data.hasGamma, data.gamma));
+  if (!data.allAvailableSensorsAreActive)
+    return false;
+
+  if (!data.hasAlpha && !data.hasBeta && !data.hasGamma) {
+    // no data can be provided, this is an all-null event.
+    return true;
+  }
+
+  return IsSignificantlyDifferent(
+             data_.hasAlpha, data_.alpha, data.hasAlpha, data.alpha) ||
+         IsSignificantlyDifferent(
+             data_.hasBeta, data_.beta, data.hasBeta, data.beta) ||
+         IsSignificantlyDifferent(
+             data_.hasGamma, data_.gamma, data.hasGamma, data.gamma);
 }
 
 bool DeviceOrientationEventPump::InitializeReader(
diff --git a/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc b/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc
index 402cd07..b5c86bf 100644
--- a/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc
+++ b/content/renderer/device_orientation/device_orientation_event_pump_unittest.cc
@@ -85,6 +85,11 @@
     data.allAvailableSensorsAreActive = true;
   }
 
+  void InitBufferNoData() {
+    blink::WebDeviceOrientationData& data = buffer_->data;
+    data.allAvailableSensorsAreActive = true;
+  }
+
   scoped_ptr<MockDeviceOrientationListener> listener_;
   scoped_ptr<DeviceOrientationEventPumpForTesting> orientation_pump_;
   base::SharedMemoryHandle handle_;
@@ -120,6 +125,29 @@
 
 // Always failing in the win try bot. See http://crbug.com/256782.
 #if defined(OS_WIN)
+#define MAYBE_FireAllNullEvent DISABLED_FireAllNullEvent
+#else
+#define MAYBE_FireAllNullEvent FireAllNullEvent
+#endif
+TEST_F(DeviceOrientationEventPumpTest, MAYBE_FireAllNullEvent) {
+  base::MessageLoop loop;
+
+  InitBufferNoData();
+  orientation_pump_->SetListener(listener_.get());
+  orientation_pump_->OnDidStart(handle_);
+
+  base::MessageLoop::current()->Run();
+
+  blink::WebDeviceOrientationData& received_data = listener_->data_;
+  EXPECT_TRUE(listener_->did_change_device_orientation_);
+  EXPECT_TRUE(received_data.allAvailableSensorsAreActive);
+  EXPECT_FALSE(received_data.hasAlpha);
+  EXPECT_FALSE(received_data.hasBeta);
+  EXPECT_FALSE(received_data.hasGamma);
+}
+
+// Always failing in the win try bot. See http://crbug.com/256782.
+#if defined(OS_WIN)
 #define MAYBE_UpdateRespectsOrientationThreshold \
     DISABLED_UpdateRespectsOrientationThreshold
 #else
diff --git a/content/renderer/dom_serializer_browsertest.cc b/content/renderer/dom_serializer_browsertest.cc
index f3861b2..7ecb34c 100644
--- a/content/renderer/dom_serializer_browsertest.cc
+++ b/content/renderer/dom_serializer_browsertest.cc
@@ -13,11 +13,11 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_view.h"
 #include "content/public/renderer/render_view_observer.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/renderer/savable_resources.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
 #include "net/url_request/url_request_context.h"
 #include "third_party/WebKit/public/platform/WebCString.h"
diff --git a/content/renderer/drop_data_builder.cc b/content/renderer/drop_data_builder.cc
index f9e5c42..d2d4583 100644
--- a/content/renderer/drop_data_builder.cc
+++ b/content/renderer/drop_data_builder.cc
@@ -55,8 +55,9 @@
         break;
       case WebDragData::Item::StorageTypeFilename:
         // TODO(varunjain): This only works on chromeos. Support win/mac/gtk.
-        result.filenames.push_back(
-            DropData::FileInfo(item.filenameData, item.displayNameData));
+        result.filenames.push_back(ui::FileInfo(
+            base::FilePath::FromUTF16Unsafe(item.filenameData),
+            base::FilePath::FromUTF16Unsafe(item.displayNameData)));
         break;
     }
   }
diff --git a/content/renderer/external_popup_menu.cc b/content/renderer/external_popup_menu.cc
index 0190913..a1bb247 100644
--- a/content/renderer/external_popup_menu.cc
+++ b/content/renderer/external_popup_menu.cc
@@ -54,8 +54,9 @@
 }
 
 void ExternalPopupMenu::close()  {
-  popup_menu_client_ = NULL;
-  render_view_ = NULL;
+  render_view_->Send(new ViewHostMsg_HidePopup(render_view_->routing_id()));
+  render_view_->DidHideExternalPopupMenu();
+  // |this| was deleted.
 }
 
 #if defined(OS_MACOSX)
diff --git a/content/renderer/gpu/compositor_software_output_device.cc b/content/renderer/gpu/compositor_software_output_device.cc
index e93367c..d1e0293 100644
--- a/content/renderer/gpu/compositor_software_output_device.cc
+++ b/content/renderer/gpu/compositor_software_output_device.cc
@@ -144,12 +144,11 @@
   current->SetFree(false);
 
   // Set up a canvas for the current front buffer.
-  bitmap_.setConfig(SkBitmap::kARGB_8888_Config,
-                    viewport_size_.width(),
-                    viewport_size_.height());
-  bitmap_.setPixels(current->memory());
-  device_ = skia::AdoptRef(new SkBitmapDevice(bitmap_));
-  canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
+  SkImageInfo info = SkImageInfo::MakeN32Premul(viewport_size_.width(),
+                                                viewport_size_.height());
+  SkBitmap bitmap;
+  bitmap.installPixels(info, current->memory(), info.minRowBytes());
+  canvas_ = skia::AdoptRef(new SkCanvas(bitmap));
 
   if (!previous) {
     DCHECK(damage_rect == gfx::Rect(viewport_size_));
diff --git a/content/renderer/gpu/compositor_software_output_device.h b/content/renderer/gpu/compositor_software_output_device.h
index c04f4f1..815cd96 100644
--- a/content/renderer/gpu/compositor_software_output_device.h
+++ b/content/renderer/gpu/compositor_software_output_device.h
@@ -89,7 +89,6 @@
   unsigned next_buffer_id_;
   ScopedVector<Buffer> buffers_;
   ScopedVector<Buffer> awaiting_ack_;
-  SkBitmap bitmap_;
   RenderThread* render_thread_;
 };
 
diff --git a/content/renderer/gpu/delegated_compositor_output_surface.cc b/content/renderer/gpu/delegated_compositor_output_surface.cc
index 02ad158..263d5f4 100644
--- a/content/renderer/gpu/delegated_compositor_output_surface.cc
+++ b/content/renderer/gpu/delegated_compositor_output_surface.cc
@@ -9,12 +9,11 @@
 DelegatedCompositorOutputSurface::DelegatedCompositorOutputSurface(
     int32 routing_id,
     uint32 output_surface_id,
-    const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
-    scoped_ptr<cc::SoftwareOutputDevice> software)
+    const scoped_refptr<ContextProviderCommandBuffer>& context_provider)
     : CompositorOutputSurface(routing_id,
                               output_surface_id,
                               context_provider,
-                              software.Pass(),
+                              scoped_ptr<cc::SoftwareOutputDevice>(),
                               true) {
   capabilities_.delegated_rendering = true;
   capabilities_.max_frames_pending = 1;
diff --git a/content/renderer/gpu/delegated_compositor_output_surface.h b/content/renderer/gpu/delegated_compositor_output_surface.h
index 1e02c3d..f971f1c 100644
--- a/content/renderer/gpu/delegated_compositor_output_surface.h
+++ b/content/renderer/gpu/delegated_compositor_output_surface.h
@@ -14,8 +14,7 @@
   DelegatedCompositorOutputSurface(
       int32 routing_id,
       uint32 output_surface_id,
-      const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
-      scoped_ptr<cc::SoftwareOutputDevice> software);
+      const scoped_refptr<ContextProviderCommandBuffer>& context_provider);
   virtual ~DelegatedCompositorOutputSurface() {}
 };
 
diff --git a/content/renderer/gpu/gpu_benchmarking_extension.cc b/content/renderer/gpu/gpu_benchmarking_extension.cc
index 1e5c8d1..e3a0587 100644
--- a/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -300,7 +300,7 @@
           "    function(position_x, position_y, opt_callback, opt_duration_ms,"
           "             opt_gesture_source_type) {"
           "  callback = opt_callback || function() { };"
-          "  duration_ms = opt_duration_ms || 0;"
+          "  duration_ms = opt_duration_ms || 50;"
           "  gesture_source_type = opt_gesture_source_type ||"
           "      chrome.gpuBenchmarking.DEFAULT_INPUT;"
           "  native function BeginTap();"
diff --git a/content/renderer/gpu/render_widget_compositor.cc b/content/renderer/gpu/render_widget_compositor.cc
index f059451..c316795 100644
--- a/content/renderer/gpu/render_widget_compositor.cc
+++ b/content/renderer/gpu/render_widget_compositor.cc
@@ -279,6 +279,9 @@
     // raster-on-demand, and use 50% of the memory otherwise.
     settings.max_memory_for_prepaint_percentage = 50;
   }
+  // Webview does not own the surface so should not clear it.
+  settings.should_clear_root_render_pass =
+      !widget->UsingSynchronousRendererCompositor();
 
 #elif !defined(OS_MACOSX)
   if (ui::IsOverlayScrollbarEnabled()) {
diff --git a/content/renderer/ico_image_decoder_unittest.cc b/content/renderer/ico_image_decoder_unittest.cc
index 4beca93..b59cfe3 100644
--- a/content/renderer/ico_image_decoder_unittest.cc
+++ b/content/renderer/ico_image_decoder_unittest.cc
@@ -23,11 +23,11 @@
 }
 
 TEST_F(ICOImageDecoderTest, ImageNonZeroFrameIndex) {
-  if (data_dir_.empty())
+  if (data_dir().empty())
     return;
   // Test that the decoder decodes multiple sizes of icons which have them.
   // Load an icon that has both favicon-size and larger entries.
-  base::FilePath multisize_icon_path(data_dir_.AppendASCII("yahoo.ico"));
+  base::FilePath multisize_icon_path(data_dir().AppendASCII("yahoo.ico"));
   const base::FilePath md5_sum_path(
       GetMD5SumPath(multisize_icon_path).value() + FILE_PATH_LITERAL("2"));
   static const int kDesiredFrameIndex = 3;
diff --git a/content/renderer/input/input_handler_proxy.cc b/content/renderer/input/input_handler_proxy.cc
index 763e0d9..f75dc9d 100644
--- a/content/renderer/input/input_handler_proxy.cc
+++ b/content/renderer/input/input_handler_proxy.cc
@@ -164,6 +164,9 @@
         cc::InputHandler::Gesture);
     switch (scroll_status) {
       case cc::InputHandler::ScrollStarted:
+        TRACE_EVENT_INSTANT0("input",
+                             "InputHandlerProxy::handle_input gesture scroll",
+                             TRACE_EVENT_SCOPE_THREAD);
         gesture_scroll_on_impl_thread_ = true;
         return DID_HANDLE;
       case cc::InputHandler::ScrollOnMainThread:
diff --git a/content/renderer/media/android/media_source_delegate.cc b/content/renderer/media/android/media_source_delegate.cc
index 563240e..bd32e70 100644
--- a/content/renderer/media/android/media_source_delegate.cc
+++ b/content/renderer/media/android/media_source_delegate.cc
@@ -153,11 +153,12 @@
   access_unit_size_ = kAccessUnitSizeForMediaSource;
 
   chunk_demuxer_.reset(new media::ChunkDemuxer(
-      media::BindToCurrentLoop(base::Bind(
-          &MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)),
-      media::BindToCurrentLoop(base::Bind(
-          &MediaSourceDelegate::OnNeedKey, main_weak_this_)),
-      base::Bind(&LogMediaSourceError, media_log_)));
+      media::BindToCurrentLoop(
+          base::Bind(&MediaSourceDelegate::OnDemuxerOpened, main_weak_this_)),
+      media::BindToCurrentLoop(
+          base::Bind(&MediaSourceDelegate::OnNeedKey, main_weak_this_)),
+      base::Bind(&LogMediaSourceError, media_log_),
+      false));
 
   // |this| will be retained until StopDemuxer() is posted, so Unretained() is
   // safe here.
diff --git a/content/renderer/media/android/renderer_media_player_manager.cc b/content/renderer/media/android/renderer_media_player_manager.cc
index a37a4e1..614d9e6 100644
--- a/content/renderer/media/android/renderer_media_player_manager.cc
+++ b/content/renderer/media/android/renderer_media_player_manager.cc
@@ -186,10 +186,11 @@
     player->OnPlayerReleased();
 }
 
-void RendererMediaPlayerManager::OnConnectedToRemoteDevice(int player_id) {
+void RendererMediaPlayerManager::OnConnectedToRemoteDevice(int player_id,
+    const std::string& remote_playback_message) {
   WebMediaPlayerAndroid* player = GetMediaPlayer(player_id);
   if (player)
-    player->OnConnectedToRemoteDevice();
+    player->OnConnectedToRemoteDevice(remote_playback_message);
 }
 
 void RendererMediaPlayerManager::OnDisconnectedFromRemoteDevice(int player_id) {
diff --git a/content/renderer/media/android/renderer_media_player_manager.h b/content/renderer/media/android/renderer_media_player_manager.h
index 0c775f8..ed94b76 100644
--- a/content/renderer/media/android/renderer_media_player_manager.h
+++ b/content/renderer/media/android/renderer_media_player_manager.h
@@ -156,7 +156,8 @@
   void OnVideoSizeChanged(int player_id, int width, int height);
   void OnTimeUpdate(int player_id, base::TimeDelta current_time);
   void OnMediaPlayerReleased(int player_id);
-  void OnConnectedToRemoteDevice(int player_id);
+  void OnConnectedToRemoteDevice(int player_id,
+      const std::string& remote_playback_message);
   void OnDisconnectedFromRemoteDevice(int player_id);
   void OnDidExitFullscreen(int player_id);
   void OnDidEnterFullscreen(int player_id);
diff --git a/content/renderer/media/android/stream_texture_factory_android.h b/content/renderer/media/android/stream_texture_factory_android.h
index f898d75..39c106d 100644
--- a/content/renderer/media/android/stream_texture_factory_android.h
+++ b/content/renderer/media/android/stream_texture_factory_android.h
@@ -29,8 +29,6 @@
   // a connected client will receive callbacks on.
   virtual void BindToCurrentThread(int32 stream_id) = 0;
 
-  virtual bool IsBoundToThread() = 0;
-
   // Setting the target for callback when a frame is available. This function
   // could be called on both the main thread and the compositor thread.
   virtual void SetClient(cc::VideoFrameProvider::Client* client) = 0;
diff --git a/content/renderer/media/android/stream_texture_factory_android_impl.cc b/content/renderer/media/android/stream_texture_factory_android_impl.cc
index 8febd3f..4ccaf51 100644
--- a/content/renderer/media/android/stream_texture_factory_android_impl.cc
+++ b/content/renderer/media/android/stream_texture_factory_android_impl.cc
@@ -23,7 +23,6 @@
 
   // StreamTextureProxy implementation:
   virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
-  virtual bool IsBoundToThread() OVERRIDE { return loop_.get() != NULL; }
   virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
   virtual void Release() OVERRIDE;
 
diff --git a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
index 0c65e41..45eeb9a 100644
--- a/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
+++ b/content/renderer/media/android/stream_texture_factory_android_synchronous_impl.cc
@@ -15,6 +15,7 @@
 #include "base/synchronization/lock.h"
 #include "cc/output/context_provider.h"
 #include "content/common/android/surface_texture_peer.h"
+#include "content/renderer/render_thread_impl.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "ui/gl/android/surface_texture.h"
 
@@ -34,11 +35,11 @@
 
   // StreamTextureProxy implementation:
   virtual void BindToCurrentThread(int32 stream_id) OVERRIDE;
-  virtual bool IsBoundToThread() OVERRIDE { return loop_.get() != NULL; }
   virtual void SetClient(cc::VideoFrameProvider::Client* client) OVERRIDE;
   virtual void Release() OVERRIDE;
 
  private:
+  void BindOnCompositorThread(int stream_id);
   void OnFrameAvailable();
 
   scoped_refptr<base::MessageLoopProxy> loop_;
@@ -59,6 +60,8 @@
 StreamTextureProxyImpl::StreamTextureProxyImpl(
     StreamTextureFactorySynchronousImpl::ContextProvider* provider)
     : context_provider_(provider), has_updated_(false) {
+  DCHECK(RenderThreadImpl::current());
+  loop_ = RenderThreadImpl::current()->compositor_message_loop_proxy();
   std::fill(current_matrix_, current_matrix_ + 16, 0);
 }
 
@@ -66,7 +69,7 @@
 
 void StreamTextureProxyImpl::Release() {
   SetClient(NULL);
-  if (loop_.get() && !loop_->BelongsToCurrentThread())
+  if (!loop_->BelongsToCurrentThread())
     loop_->DeleteSoon(FROM_HERE, this);
   else
     delete this;
@@ -78,8 +81,19 @@
 }
 
 void StreamTextureProxyImpl::BindToCurrentThread(int stream_id) {
-  loop_ = base::MessageLoopProxy::current();
+  if (loop_->BelongsToCurrentThread()) {
+    BindOnCompositorThread(stream_id);
+    return;
+  }
 
+  // Weakptr is only used on compositor thread loop, so this is safe.
+  loop_->PostTask(FROM_HERE,
+                  base::Bind(&StreamTextureProxyImpl::BindOnCompositorThread,
+                             AsWeakPtr(),
+                             stream_id));
+}
+
+void StreamTextureProxyImpl::BindOnCompositorThread(int stream_id) {
   surface_texture_ = context_provider_->GetSurfaceTexture(stream_id);
   if (!surface_texture_) {
     LOG(ERROR) << "Failed to get SurfaceTexture for stream.";
diff --git a/content/renderer/media/android/webmediaplayer_android.cc b/content/renderer/media/android/webmediaplayer_android.cc
index 3679178..c107d32 100644
--- a/content/renderer/media/android/webmediaplayer_android.cc
+++ b/content/renderer/media/android/webmediaplayer_android.cc
@@ -29,7 +29,6 @@
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/common/mailbox_holder.h"
-#include "grit/content_resources.h"
 #include "media/base/android/media_player_android.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/media_switches.h"
@@ -45,6 +44,7 @@
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkTypeface.h"
 #include "ui/gfx/image/image.h"
 #include "webkit/renderer/compositor_bindings/web_layer_impl.h"
 
@@ -430,28 +430,46 @@
     unsigned int type,
     bool premultiply_alpha,
     bool flip_y) {
-  if (is_remote_ || !texture_id_)
+  // Don't allow clients to copy an encrypted video frame.
+  if (needs_external_surface_)
     return false;
 
+  scoped_refptr<VideoFrame> video_frame;
+  {
+    base::AutoLock auto_lock(current_frame_lock_);
+    video_frame = current_frame_;
+  }
+
+  if (!video_frame ||
+      video_frame->format() != media::VideoFrame::NATIVE_TEXTURE)
+    return false;
+  DCHECK((!is_remote_ && texture_id_) ||
+         (is_remote_ && remote_playback_texture_id_));
+  gpu::MailboxHolder* mailbox_holder = video_frame->mailbox_holder();
+  DCHECK((texture_id_ &&
+          mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES) ||
+         (remote_playback_texture_id_ &&
+          mailbox_holder->texture_target == GL_TEXTURE_2D));
+
   // For hidden video element (with style "display:none"), ensure the texture
   // size is set.
-  if (cached_stream_texture_size_.width != natural_size_.width ||
-      cached_stream_texture_size_.height != natural_size_.height) {
+  if (!is_remote_ &&
+      (cached_stream_texture_size_.width != natural_size_.width ||
+       cached_stream_texture_size_.height != natural_size_.height)) {
     stream_texture_factory_->SetStreamTextureSize(
         stream_id_, gfx::Size(natural_size_.width, natural_size_.height));
     cached_stream_texture_size_ = natural_size_;
   }
 
   uint32 source_texture = web_graphics_context->createTexture();
-  // This is strictly not necessary, because we flush when we create the
-  // one and only stream texture.
-  web_graphics_context->waitSyncPoint(texture_mailbox_sync_point_);
+  web_graphics_context->waitSyncPoint(mailbox_holder->sync_point);
 
   // Ensure the target of texture is set before copyTextureCHROMIUM, otherwise
   // an invalid texture target may be used for copy texture.
-  web_graphics_context->bindTexture(GL_TEXTURE_EXTERNAL_OES, source_texture);
-  web_graphics_context->consumeTextureCHROMIUM(GL_TEXTURE_EXTERNAL_OES,
-                                               texture_mailbox_.name);
+  web_graphics_context->bindTexture(mailbox_holder->texture_target,
+                                    source_texture);
+  web_graphics_context->consumeTextureCHROMIUM(mailbox_holder->texture_target,
+                                               mailbox_holder->mailbox.name);
 
   // The video is stored in an unmultiplied format, so premultiply if
   // necessary.
@@ -470,8 +488,12 @@
   web_graphics_context->pixelStorei(GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM,
                                     false);
 
-  web_graphics_context->bindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+  if (mailbox_holder->texture_target == GL_TEXTURE_EXTERNAL_OES)
+    web_graphics_context->bindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
+  else
+    web_graphics_context->bindTexture(GL_TEXTURE_2D, texture);
   web_graphics_context->deleteTexture(source_texture);
+  web_graphics_context->flush();
   return true;
 }
 
@@ -662,7 +684,14 @@
   natural_size_.width = width;
   natural_size_.height = height;
   ReallocateVideoFrame();
-  CreateWebLayerIfNeeded();
+
+  // Lazily allocate compositing layer.
+  if (!video_weblayer_) {
+    video_weblayer_.reset(
+        new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
+    client_->setWebLayer(video_weblayer_.get());
+  }
+
   // TODO(qinmin): This is a hack. We need the media element to stop showing the
   // poster image by forcing it to call setDisplayMode(video). Should move the
   // logic into HTMLMediaElement.cpp.
@@ -674,10 +703,11 @@
   current_time_ = current_time.InSecondsF();
 }
 
-void WebMediaPlayerAndroid::OnConnectedToRemoteDevice() {
+void WebMediaPlayerAndroid::OnConnectedToRemoteDevice(
+    const std::string& remote_playback_message) {
   DCHECK(main_thread_checker_.CalledOnValidThread());
   DCHECK(!media_source_delegate_);
-  DrawRemotePlaybackIcon();
+  DrawRemotePlaybackText(remote_playback_message);
   is_remote_ = true;
   SetNeedsEstablishPeer(false);
 }
@@ -832,7 +862,9 @@
   UpdatePlayingState(false);
 }
 
-void WebMediaPlayerAndroid::DrawRemotePlaybackIcon() {
+void WebMediaPlayerAndroid::DrawRemotePlaybackText(
+    const std::string& remote_playback_message) {
+
   DCHECK(main_thread_checker_.CalledOnValidThread());
   if (!video_weblayer_)
     return;
@@ -853,34 +885,64 @@
       SkBitmap::kARGB_8888_Config, canvas_size.width(), canvas_size.height());
   bitmap.allocPixels();
 
+  // Create the canvas and draw the "Casting to <Chromecast>" text on it.
   SkCanvas canvas(bitmap);
   canvas.drawColor(SK_ColorBLACK);
+
+  const SkScalar kTextSize(40);
+  const SkScalar kMinPadding(40);
+
   SkPaint paint;
   paint.setAntiAlias(true);
   paint.setFilterLevel(SkPaint::kHigh_FilterLevel);
-  const SkBitmap* icon_bitmap =
-      GetContentClient()
-          ->GetNativeImageNamed(IDR_MEDIAPLAYER_REMOTE_PLAYBACK_ICON)
-          .ToSkBitmap();
-  // In order to get a reasonable margin around the icon:
-  // - the icon should be under half the frame width
-  // - the icon should be at most 3/5 of the frame height
-  // Additionally, on very large screens, the icon size should be capped. A max
-  // width of 320 was arbitrarily chosen; since this is half the resource's
-  // pixel width, it should look crisp even on 2x deviceScaleFactor displays.
-  int icon_width = 320;
-  icon_width = std::min(icon_width, canvas_size.width() / 2);
-  icon_width = std::min(icon_width,
-                        canvas_size.height() * icon_bitmap->width() /
-                            icon_bitmap->height() * 3 / 5);
-  int icon_height = icon_width * icon_bitmap->height() / icon_bitmap->width();
-  // Center the icon within the frame
-  SkRect icon_rect = SkRect::MakeXYWH((canvas_size.width() - icon_width) / 2,
-                                      (canvas_size.height() - icon_height) / 2,
-                                      icon_width,
-                                      icon_height);
-  canvas.drawBitmapRectToRect(
-      *icon_bitmap, NULL /* src */, icon_rect /* dest */, &paint);
+  paint.setColor(SK_ColorWHITE);
+  paint.setTypeface(SkTypeface::CreateFromName("sans", SkTypeface::kBold));
+  paint.setTextSize(kTextSize);
+
+  // Calculate the vertical margin from the top
+  SkPaint::FontMetrics font_metrics;
+  paint.getFontMetrics(&font_metrics);
+  SkScalar sk_vertical_margin = kMinPadding - font_metrics.fAscent;
+
+  // Measure the width of the entire text to display
+  size_t display_text_width = paint.measureText(
+      remote_playback_message.c_str(), remote_playback_message.size());
+  std::string display_text(remote_playback_message);
+
+  if (display_text_width + (kMinPadding * 2) > canvas_size.width()) {
+    // The text is too long to fit in one line, truncate it and append ellipsis
+    // to the end.
+
+    // First, figure out how much of the canvas the '...' will take up.
+    const std::string kTruncationEllipsis("\xE2\x80\xA6");
+    SkScalar sk_ellipse_width = paint.measureText(
+        kTruncationEllipsis.c_str(), kTruncationEllipsis.size());
+
+    // Then calculate how much of the text can be drawn with the '...' appended
+    // to the end of the string.
+    SkScalar sk_max_original_text_width(
+        canvas_size.width() - (kMinPadding * 2) - sk_ellipse_width);
+    size_t sk_max_original_text_length = paint.breakText(
+        remote_playback_message.c_str(),
+        remote_playback_message.size(),
+        sk_max_original_text_width);
+
+    // Remove the part of the string that doesn't fit and append '...'.
+    display_text.erase(sk_max_original_text_length,
+        remote_playback_message.size() - sk_max_original_text_length);
+    display_text.append(kTruncationEllipsis);
+    display_text_width = paint.measureText(
+        display_text.c_str(), display_text.size());
+  }
+
+  // Center the text horizontally.
+  SkScalar sk_horizontal_margin =
+      (canvas_size.width() - display_text_width) / 2.0;
+  canvas.drawText(display_text.c_str(),
+      display_text.size(),
+      sk_horizontal_margin,
+      sk_vertical_margin,
+      paint);
 
   GLES2Interface* gl = stream_texture_factory_->ContextGL();
 
@@ -955,13 +1017,6 @@
   }
 }
 
-void WebMediaPlayerAndroid::CreateWebLayerIfNeeded() {
-  if (!hasVideo() || video_weblayer_ || !client_->needsWebLayerForVideo())
-    return;
-  video_weblayer_.reset(new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
-  client_->setWebLayer(video_weblayer_.get());
-}
-
 void WebMediaPlayerAndroid::SetVideoFrameProviderClient(
     cc::VideoFrameProvider::Client* client) {
   // This is called from both the main renderer thread and the compositor
@@ -1182,6 +1237,17 @@
   return e;
 }
 
+// Guess the type of |init_data|. This is only used to handle some corner cases
+// so we keep it as simple as possible without breaking major use cases.
+static std::string GuessInitDataType(const unsigned char* init_data,
+                                     unsigned init_data_length) {
+  // Most WebM files use KeyId of 16 bytes. MP4 init data are always >16 bytes.
+  if (init_data_length == 16)
+    return "video/webm";
+
+  return "video/mp4";
+}
+
 // TODO(xhwang): Report an error when there is encrypted stream but EME is
 // not enabled. Currently the player just doesn't start and waits for
 // ever.
@@ -1228,11 +1294,15 @@
     return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
   }
 
+  std::string init_data_type = init_data_type_;
+  if (init_data_type.empty())
+    init_data_type = GuessInitDataType(init_data, init_data_length);
+
   // TODO(xhwang): We assume all streams are from the same container (thus have
   // the same "type") for now. In the future, the "type" should be passed down
   // from the application.
   if (!proxy_decryptor_->GenerateKeyRequest(
-           init_data_type_, init_data, init_data_length)) {
+           init_data_type, init_data, init_data_length)) {
     current_key_system_.clear();
     return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
   }
diff --git a/content/renderer/media/android/webmediaplayer_android.h b/content/renderer/media/android/webmediaplayer_android.h
index dbcca0d..3ccf5ce 100644
--- a/content/renderer/media/android/webmediaplayer_android.h
+++ b/content/renderer/media/android/webmediaplayer_android.h
@@ -169,7 +169,7 @@
   void OnTimeUpdate(const base::TimeDelta& current_time);
 
   // Functions called when media player status changes.
-  void OnConnectedToRemoteDevice();
+  void OnConnectedToRemoteDevice(const std::string& remote_playback_message);
   void OnDisconnectedFromRemoteDevice();
   void OnDidEnterFullscreen();
   void OnDidExitFullscreen();
@@ -250,9 +250,8 @@
 
  private:
   void Pause(bool is_media_related_action);
-  void DrawRemotePlaybackIcon();
+  void DrawRemotePlaybackText(const std::string& remote_playback_message);
   void ReallocateVideoFrame();
-  void CreateWebLayerIfNeeded();
   void SetCurrentFrameInternal(scoped_refptr<media::VideoFrame>& frame);
   void DidLoadMediaInfo(MediaInfoLoader::Status status);
   void DoReleaseRemotePlaybackTexture(
diff --git a/content/renderer/media/media_stream_audio_level_calculator.cc b/content/renderer/media/media_stream_audio_level_calculator.cc
index 29b7fae..a136e32 100644
--- a/content/renderer/media/media_stream_audio_level_calculator.cc
+++ b/content/renderer/media/media_stream_audio_level_calculator.cc
@@ -42,12 +42,6 @@
                                                int number_of_channels,
                                                int number_of_frames) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  // Permutation of bars that reprents the amplitude level of the audio signal.
-  // The number of elements is 33 because we are indexing them in the range of
-  // [0, 32].
-  static const int kPermutation[33] =
-      {0,1,2,3,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,8,8,8,9,9,9,9,9,9,9,9,9,9,9};
-
   // |level_| is updated every 10 callbacks. For the case where callback comes
   // every 10ms, |level_| will be updated approximately every 100ms.
   static const int kUpdateFrequency = 10;
@@ -56,18 +50,7 @@
   max_amplitude_ = std::max(max_amplitude_, max);
 
   if (counter_++ == kUpdateFrequency) {
-    // Divide the max amplitude (32768) by 1000 to get in the range of [0,32]
-    // which is the range of the permutation array.
-    int index = static_cast<int>(max_amplitude_ / 1000);
-
-    // Make it less likely that the bar stays at position 0. I.e. only if
-    // its in the range 0-250 (instead of 0-1000)
-    if (index == 0 && max_amplitude_ > 250)
-      index = 1;
-
-    // |level_| will be the value in the permutation array that the |index| is
-    // pointing to.
-    level_ = kPermutation[index];
+    level_ = max_amplitude_;
 
     // Decay the absolute maximum amplitude by 1/4.
     max_amplitude_ >>= 2;
diff --git a/content/renderer/media/media_stream_audio_level_calculator.h b/content/renderer/media/media_stream_audio_level_calculator.h
index 1440d2b..41c9c34 100644
--- a/content/renderer/media/media_stream_audio_level_calculator.h
+++ b/content/renderer/media/media_stream_audio_level_calculator.h
@@ -20,8 +20,7 @@
   ~MediaStreamAudioLevelCalculator();
 
   // Calculates the signal level of the audio data.
-  // Returns the level of bars that the volume animation UI uses for
-  // presenting the energy level of the audio data.
+  // Returns the absolute value of the amplitude of the signal.
   int Calculate(const int16* audio_data, int number_of_channels,
                 int number_of_frames);
 
diff --git a/content/renderer/media/media_stream_audio_processor.cc b/content/renderer/media/media_stream_audio_processor.cc
index 11e8892..c83ffff 100644
--- a/content/renderer/media/media_stream_audio_processor.cc
+++ b/content/renderer/media/media_stream_audio_processor.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
 #include "base/metrics/field_trial.h"
+#include "base/metrics/histogram.h"
 #include "content/public/common/content_switches.h"
 #include "content/renderer/media/media_stream_audio_processor_options.h"
 #include "content/renderer/media/rtc_media_constraints.h"
@@ -30,10 +31,23 @@
 #else
 const int kAudioProcessingSampleRate = 32000;
 #endif
-const int kAudioProcessingNumberOfChannel = 1;
+const int kAudioProcessingNumberOfChannels = 1;
 
 const int kMaxNumberOfBuffersInFifo = 2;
 
+// Used by UMA histograms and entries shouldn't be re-ordered or removed.
+enum AudioTrackProcessingStates {
+  AUDIO_PROCESSING_ENABLED = 0,
+  AUDIO_PROCESSING_DISABLED,
+  AUDIO_PROCESSING_IN_WEBRTC,
+  AUDIO_PROCESSING_MAX
+};
+
+void RecordProcessingState(AudioTrackProcessingStates state) {
+  UMA_HISTOGRAM_ENUMERATION("Media.AudioTrackProcessingStates",
+                            state, AUDIO_PROCESSING_MAX);
+}
+
 }  // namespace
 
 class MediaStreamAudioProcessor::MediaStreamAudioConverter
@@ -265,11 +279,19 @@
     const blink::WebMediaConstraints& constraints, int effects,
     MediaStreamType type) {
   DCHECK(!audio_processing_);
-  if (!IsAudioTrackProcessingEnabled())
-    return;
 
   RTCMediaConstraints native_constraints(constraints);
 
+  // Audio mirroring can be enabled even though audio processing is otherwise
+  // disabled.
+  audio_mirroring_ = GetPropertyFromConstraints(
+      &native_constraints, webrtc::MediaConstraintsInterface::kAudioMirroring);
+
+  if (!IsAudioTrackProcessingEnabled()) {
+    RecordProcessingState(AUDIO_PROCESSING_IN_WEBRTC);
+    return;
+  }
+
   // Only apply the fixed constraints for gUM of MEDIA_DEVICE_AUDIO_CAPTURE.
   DCHECK(IsAudioMediaType(type));
   if (type == MEDIA_DEVICE_AUDIO_CAPTURE)
@@ -312,13 +334,11 @@
   const bool enable_high_pass_filter = GetPropertyFromConstraints(
       &native_constraints, MediaConstraintsInterface::kHighpassFilter);
 
-  audio_mirroring_ = GetPropertyFromConstraints(
-      &native_constraints, webrtc::MediaConstraintsInterface::kAudioMirroring);
-
   // Return immediately if no audio processing component is enabled.
   if (!enable_aec && !enable_experimental_aec && !enable_ns &&
       !enable_high_pass_filter && !enable_typing_detection && !enable_agc &&
       !enable_experimental_ns) {
+    RecordProcessingState(AUDIO_PROCESSING_DISABLED);
     return;
   }
 
@@ -356,11 +376,12 @@
 
   // Configure the audio format the audio processing is running on. This
   // has to be done after all the needed components are enabled.
-  CHECK_EQ(audio_processing_->set_sample_rate_hz(kAudioProcessingSampleRate),
-           0);
-  CHECK_EQ(audio_processing_->set_num_channels(kAudioProcessingNumberOfChannel,
-                                               kAudioProcessingNumberOfChannel),
-           0);
+  CHECK_EQ(0,
+           audio_processing_->set_sample_rate_hz(kAudioProcessingSampleRate));
+  CHECK_EQ(0, audio_processing_->set_num_channels(
+      kAudioProcessingNumberOfChannels, kAudioProcessingNumberOfChannels));
+
+  RecordProcessingState(AUDIO_PROCESSING_ENABLED);
 }
 
 void MediaStreamAudioProcessor::InitializeCaptureConverter(
@@ -376,7 +397,7 @@
   const int sink_sample_rate = audio_processing_ ?
       kAudioProcessingSampleRate : source_params.sample_rate();
   const media::ChannelLayout sink_channel_layout = audio_processing_ ?
-      media::GuessChannelLayout(kAudioProcessingNumberOfChannel) :
+      media::GuessChannelLayout(kAudioProcessingNumberOfChannels) :
       source_params.channel_layout();
 
   // WebRtc AudioProcessing requires 10ms as its packet size. We use this
diff --git a/content/renderer/media/media_stream_audio_source.cc b/content/renderer/media/media_stream_audio_source.cc
index fd058b3..34f3087 100644
--- a/content/renderer/media/media_stream_audio_source.cc
+++ b/content/renderer/media/media_stream_audio_source.cc
@@ -48,9 +48,4 @@
   callback.Run(this, result);
 }
 
-void MediaStreamAudioSource::RemoveTrack(
-    const blink::WebMediaStreamTrack& track) {
-  NOTIMPLEMENTED();
-}
-
 }  // namespace content
diff --git a/content/renderer/media/media_stream_audio_source.h b/content/renderer/media/media_stream_audio_source.h
index 2e73395..08730d9 100644
--- a/content/renderer/media/media_stream_audio_source.h
+++ b/content/renderer/media/media_stream_audio_source.h
@@ -24,10 +24,9 @@
   MediaStreamAudioSource();
   virtual ~MediaStreamAudioSource();
 
-  virtual void AddTrack(const blink::WebMediaStreamTrack& track,
-                        const blink::WebMediaConstraints& constraints,
-                        const ConstraintsCallback& callback) OVERRIDE;
-  virtual void RemoveTrack(const blink::WebMediaStreamTrack& track) OVERRIDE;
+  void AddTrack(const blink::WebMediaStreamTrack& track,
+                const blink::WebMediaConstraints& constraints,
+                const ConstraintsCallback& callback);
 
   void SetLocalAudioSource(webrtc::AudioSourceInterface* source) {
     local_audio_source_ = source;
diff --git a/content/renderer/media/media_stream_center.cc b/content/renderer/media/media_stream_center.cc
index c97851b..32314bd 100644
--- a/content/renderer/media/media_stream_center.cc
+++ b/content/renderer/media/media_stream_center.cc
@@ -10,11 +10,15 @@
 #include "base/logging.h"
 #include "content/common/media/media_stream_messages.h"
 #include "content/public/common/content_switches.h"
+#include "content/public/renderer/media_stream_audio_sink.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/media/media_stream.h"
 #include "content/renderer/media/media_stream_dependency_factory.h"
 #include "content/renderer/media/media_stream_source.h"
+#include "content/renderer/media/media_stream_video_source.h"
 #include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/webrtc_local_audio_source_provider.h"
+#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
@@ -46,17 +50,19 @@
   DCHECK(track.extraData() == NULL);
   blink::WebMediaStreamSource source = track.source();
   DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo);
-
-  if (!source.extraData()) {
+  MediaStreamVideoSource* native_source =
+      MediaStreamVideoSource::GetVideoSource(source);
+  if (!native_source) {
     // TODO(perkj): Implement support for sources from
     // remote MediaStreams.
     NOTIMPLEMENTED();
     return;
   }
-  MediaStreamTrack* native_track = new MediaStreamVideoTrack(factory);
-  native_track->SetEnabled(track.isEnabled());
   blink::WebMediaStreamTrack writable_track(track);
-  writable_track.setExtraData(native_track);
+  writable_track.setExtraData(
+      new MediaStreamVideoTrack(native_source, source.constraints(),
+                                MediaStreamVideoSource::ConstraintsCallback(),
+                                track.isEnabled(), factory));
 }
 
 void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track,
@@ -132,6 +138,27 @@
   return true;
 }
 
+blink::WebAudioSourceProvider*
+MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack(
+    const blink::WebMediaStreamTrack& track) {
+  DVLOG(1) << "MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack";
+  MediaStreamTrack* media_stream_track =
+      static_cast<MediaStreamTrack*>(track.extraData());
+  // Only local audio track is supported now.
+  // TODO(xians): Support remote audio track.
+  if (!media_stream_track || !media_stream_track->is_local_track ()) {
+    NOTIMPLEMENTED();
+    return NULL;
+  }
+
+  blink::WebMediaStreamSource source = track.source();
+  DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
+  WebRtcLocalAudioSourceProvider* source_provider =
+      new WebRtcLocalAudioSourceProvider();
+  MediaStreamAudioSink::AddToAudioTrack(source_provider, track);
+  return source_provider;
+}
+
 void MediaStreamCenter::didStopLocalMediaStream(
     const blink::WebMediaStream& stream) {
   DVLOG(1) << "MediaStreamCenter::didStopLocalMediaStream";
diff --git a/content/renderer/media/media_stream_center.h b/content/renderer/media/media_stream_center.h
index fbf1be7..90b6980 100644
--- a/content/renderer/media/media_stream_center.h
+++ b/content/renderer/media/media_stream_center.h
@@ -18,6 +18,7 @@
 #include "third_party/WebKit/public/platform/WebMediaStreamTrackSourcesRequest.h"
 
 namespace blink {
+class WebAudioSourceProvider;
 class WebMediaStreamCenterClient;
 }
 
@@ -51,6 +52,11 @@
   virtual bool didStopMediaStreamTrack(
       const blink::WebMediaStreamTrack& track) OVERRIDE;
 
+  virtual blink::WebAudioSourceProvider*
+      createWebAudioSourceFromMediaStreamTrack(
+          const blink::WebMediaStreamTrack& track) OVERRIDE;
+
+
   virtual void didCreateMediaStream(
       blink::WebMediaStream& stream) OVERRIDE;
 
diff --git a/content/renderer/media/media_stream_dependency_factory.cc b/content/renderer/media/media_stream_dependency_factory.cc
index a27b475..1a829c3 100644
--- a/content/renderer/media/media_stream_dependency_factory.cc
+++ b/content/renderer/media/media_stream_dependency_factory.cc
@@ -402,7 +402,7 @@
   signaling_thread_ = jingle_glue::JingleThreadWrapper::current();
   CHECK(signaling_thread_);
 
-  chrome_worker_thread_.Start();
+  CHECK(chrome_worker_thread_.Start());
 
   base::WaitableEvent start_worker_event(true, false);
   chrome_worker_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
@@ -725,7 +725,7 @@
 
   if (track.source().type() == blink::WebMediaStreamSource::TypeVideo) {
     DVLOG(1) << "AddNativeTrackToBlinkTrack() video";
-    track.setExtraData(new MediaStreamVideoTrack(
+    track.setExtraData(new WebRtcMediaStreamVideoTrack(
         static_cast<webrtc::VideoTrackInterface*>(native_track)));
   } else {
     DVLOG(1) << "AddNativeTrackToBlinkTrack() audio";
diff --git a/content/renderer/media/media_stream_dependency_factory_unittest.cc b/content/renderer/media/media_stream_dependency_factory_unittest.cc
index 2f4c53d..9236c23 100644
--- a/content/renderer/media/media_stream_dependency_factory_unittest.cc
+++ b/content/renderer/media/media_stream_dependency_factory_unittest.cc
@@ -100,13 +100,17 @@
       audio_track_vector[i].setExtraData(native_track);
     }
 
+    blink::WebMediaConstraints constraints;
+    constraints.initialize();
     blink::WebVector<blink::WebMediaStreamTrack> video_track_vector(
         video_sources.size());
     for (size_t i = 0; i < video_track_vector.size(); ++i) {
-      video_track_vector[i].initialize(video_sources[i].id(),
-                                       video_sources[i]);
-      video_track_vector[i].setExtraData(
-          new MediaStreamVideoTrack(dependency_factory_.get()));
+      MediaStreamVideoSource* native_source =
+             MediaStreamVideoSource::GetVideoSource(video_sources[i]);
+      video_track_vector[i] = MediaStreamVideoTrack::CreateVideoTrack(
+          native_source, constraints,
+          MediaStreamVideoSource::ConstraintsCallback(), true,
+          dependency_factory_.get());
     }
 
     stream_desc.initialize("media stream", audio_track_vector,
diff --git a/content/renderer/media/media_stream_dispatcher.cc b/content/renderer/media/media_stream_dispatcher.cc
index 51b708b..6446c3c 100644
--- a/content/renderer/media/media_stream_dispatcher.cc
+++ b/content/renderer/media/media_stream_dispatcher.cc
@@ -10,6 +10,7 @@
 #include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_view_impl.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -78,10 +79,9 @@
   DVLOG(1) << "MediaStreamDispatcher::GenerateStream(" << request_id << ")";
 
   requests_.push_back(Request(event_handler, request_id, next_ipc_id_));
-  Send(new MediaStreamHostMsg_GenerateStream(routing_id(),
-                                             next_ipc_id_++,
-                                             components,
-                                             security_origin));
+  Send(new MediaStreamHostMsg_GenerateStream(
+      routing_id(), next_ipc_id_++, components, security_origin,
+      blink::WebUserGestureIndicator::isProcessingUserGesture()));
 }
 
 void MediaStreamDispatcher::CancelGenerateStream(
diff --git a/content/renderer/media/media_stream_impl.cc b/content/renderer/media/media_stream_impl.cc
index bb5bcbf..9c6d33b 100644
--- a/content/renderer/media/media_stream_impl.cc
+++ b/content/renderer/media/media_stream_impl.cc
@@ -480,10 +480,9 @@
                            constraints,
                            request->frame,
                            &webkit_source);
-    (*webkit_tracks)[i].initialize(webkit_source);
-    (*webkit_tracks)[i].setExtraData(new MediaStreamVideoTrack(
-        dependency_factory_));
-    request->StartTrack((*webkit_tracks)[i], constraints);
+    (*webkit_tracks)[i] =
+        request->CreateAndStartVideoTrack(webkit_source, constraints,
+                                          dependency_factory_);
   }
 }
 
@@ -524,7 +523,7 @@
                            request->frame,
                            &webkit_source);
     (*webkit_tracks)[i].initialize(webkit_source);
-    request->StartTrack((*webkit_tracks)[i], constraints);
+    request->StartAudioTrack((*webkit_tracks)[i], constraints);
   }
 }
 
@@ -870,11 +869,12 @@
   DVLOG(1) << "~UserMediaRequestInfo";
 }
 
-void MediaStreamImpl::UserMediaRequestInfo::StartTrack(
+void MediaStreamImpl::UserMediaRequestInfo::StartAudioTrack(
     const blink::WebMediaStreamTrack& track,
     const blink::WebMediaConstraints& constraints) {
-  MediaStreamSource* native_source =
-      static_cast <MediaStreamSource*>(track.source().extraData());
+  DCHECK(track.source().type() == blink::WebMediaStreamSource::TypeAudio);
+  MediaStreamAudioSource* native_source =
+      static_cast <MediaStreamAudioSource*>(track.source().extraData());
   DCHECK(native_source);
 
   sources_.push_back(track.source());
@@ -885,6 +885,24 @@
           AsWeakPtr()));
 }
 
+blink::WebMediaStreamTrack
+MediaStreamImpl::UserMediaRequestInfo::CreateAndStartVideoTrack(
+    const blink::WebMediaStreamSource& source,
+    const blink::WebMediaConstraints& constraints,
+    MediaStreamDependencyFactory* factory) {
+  DCHECK(source.type() == blink::WebMediaStreamSource::TypeVideo);
+  MediaStreamVideoSource* native_source =
+      MediaStreamVideoSource::GetVideoSource(source);
+  DCHECK(native_source);
+  sources_.push_back(source);
+  sources_waiting_for_callback_.push_back(native_source);
+  return MediaStreamVideoTrack::CreateVideoTrack(
+      native_source, constraints, base::Bind(
+          &MediaStreamImpl::UserMediaRequestInfo::OnTrackStarted,
+          AsWeakPtr()),
+      true, factory);
+}
+
 void MediaStreamImpl::UserMediaRequestInfo::CallbackOnTracksStarted(
     const ResourcesReady& callback) {
   DCHECK(ready_callback_.is_null());
diff --git a/content/renderer/media/media_stream_impl.h b/content/renderer/media/media_stream_impl.h
index 4ffed1b..12de8de 100644
--- a/content/renderer/media/media_stream_impl.h
+++ b/content/renderer/media/media_stream_impl.h
@@ -149,8 +149,13 @@
     blink::WebMediaStream web_stream;
     blink::WebUserMediaRequest request;
 
-    void StartTrack(const blink::WebMediaStreamTrack& track,
-                    const blink::WebMediaConstraints& constraints);
+    void StartAudioTrack(const blink::WebMediaStreamTrack& track,
+                         const blink::WebMediaConstraints& constraints);
+
+    blink::WebMediaStreamTrack CreateAndStartVideoTrack(
+        const blink::WebMediaStreamSource& source,
+        const blink::WebMediaConstraints& constraints,
+        MediaStreamDependencyFactory* factory);
 
     // Triggers |callback| when all sources used in this request have either
     // successfully started, or a source has failed to start.
diff --git a/content/renderer/media/media_stream_source.h b/content/renderer/media/media_stream_source.h
index 5eb7c3f..138e58e 100644
--- a/content/renderer/media/media_stream_source.h
+++ b/content/renderer/media/media_stream_source.h
@@ -30,11 +30,6 @@
   MediaStreamSource();
   virtual ~MediaStreamSource();
 
-  virtual void AddTrack(const blink::WebMediaStreamTrack& track,
-                        const blink::WebMediaConstraints& constraints,
-                        const ConstraintsCallback& callback) = 0;
-  virtual void RemoveTrack(const blink::WebMediaStreamTrack& track) = 0;
-
   // Returns device information about a source that has been created by a
   // JavaScript call to GetUserMedia, e.g., a camera or microphone.
   const StreamDeviceInfo& device_info() const {
diff --git a/content/renderer/media/media_stream_track.h b/content/renderer/media/media_stream_track.h
index 050e8c5..e1e2e4f 100644
--- a/content/renderer/media/media_stream_track.h
+++ b/content/renderer/media/media_stream_track.h
@@ -32,6 +32,7 @@
   static MediaStreamTrack* GetTrack(
       const blink::WebMediaStreamTrack& track);
 
+  // If a subclass overrides this method it has to call the base class.
   virtual void SetEnabled(bool enabled);
 
   virtual webrtc::AudioTrackInterface* GetAudioAdapter();
diff --git a/content/renderer/media/media_stream_video_capture_source_unittest.cc b/content/renderer/media/media_stream_video_capture_source_unittest.cc
index dd73273..0a29e76 100644
--- a/content/renderer/media/media_stream_video_capture_source_unittest.cc
+++ b/content/renderer/media/media_stream_video_capture_source_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "content/renderer/media/media_stream_video_capturer_source.h"
+#include "content/renderer/media/media_stream_video_track.h"
 #include "content/renderer/media/mock_media_constraint_factory.h"
 #include "content/renderer/media/mock_media_stream_dependency_factory.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -43,16 +44,15 @@
 
   void StartSource() {
     MockMediaConstraintFactory factory;
-
-    blink::WebMediaStreamTrack track;
-    track.initialize(base::UTF8ToUTF16("test"), webkit_source_);
-
-    // AddTrack will trigger OnSupportedFormats.
-    source_->AddTrack(
-        track,
-        factory.CreateWebMediaConstraints(),
-        base::Bind(&MediaStreamVideoCapturerSourceTest::OnConstraintsApplied,
-                   base::Unretained(this)));
+    bool enabled = true;
+    MediaStreamDependencyFactory* dependency_factory = NULL;
+    // CreateVideoTrack will trigger OnSupportedFormats.
+    MediaStreamVideoTrack::CreateVideoTrack(
+        source_, factory.CreateWebMediaConstraints(),
+        base::Bind(
+            &MediaStreamVideoCapturerSourceTest::OnConstraintsApplied,
+            base::Unretained(this)),
+            enabled, dependency_factory);
   }
 
  protected:
diff --git a/content/renderer/media/media_stream_video_capturer_source.cc b/content/renderer/media/media_stream_video_capturer_source.cc
index e35413c..b4c254d 100644
--- a/content/renderer/media/media_stream_video_capturer_source.cc
+++ b/content/renderer/media/media_stream_video_capturer_source.cc
@@ -96,7 +96,7 @@
     const NewFrameCallback& new_frame_callback,
     const StartedCallback& started_callback) {
   DCHECK(params.requested_format.IsValid());
-  DCHECK(message_loop_proxy_ == base::MessageLoopProxy::current());
+  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
   new_frame_callback_ = new_frame_callback;
   started_callback_ = started_callback;
   got_first_frame_ = false;
@@ -110,7 +110,7 @@
 void VideoCapturerDelegate::StopDeliver() {
   // Immediately make sure we don't provide more frames.
   DVLOG(3) << "VideoCapturerDelegate::StopCapture()";
-  DCHECK(message_loop_proxy_ == base::MessageLoopProxy::current());
+  DCHECK(message_loop_proxy_->BelongsToCurrentThread());
   capture_engine_->StopCapture(this);
   new_frame_callback_.Reset();
   started_callback_.Reset();
@@ -118,25 +118,29 @@
 
 void VideoCapturerDelegate::OnStarted(media::VideoCapture* capture) {
   DVLOG(3) << "VideoCapturerDelegate::OnStarted";
+  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
 }
 
 void VideoCapturerDelegate::OnStopped(media::VideoCapture* capture) {
+  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
 }
 
 void VideoCapturerDelegate::OnPaused(media::VideoCapture* capture) {
+  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
 }
 
 void VideoCapturerDelegate::OnError(media::VideoCapture* capture,
                                     int error_code) {
   DVLOG(3) << "VideoCapturerDelegate::OnError";
+  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
   message_loop_proxy_->PostTask(
       FROM_HERE,
-      base::Bind(&VideoCapturerDelegate::OnErrorOnCaptureThread,
-                 this, capture));
+      base::Bind(&VideoCapturerDelegate::OnErrorOnRenderThread, this, capture));
 }
 
 void VideoCapturerDelegate::OnRemoved(media::VideoCapture* capture) {
   DVLOG(3) << " MediaStreamVideoCapturerSource::OnRemoved";
+  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
 
   // Balance the AddRef in StartDeliver.
   // This means we are no longer registered as an event handler and can safely
@@ -147,15 +151,16 @@
 void VideoCapturerDelegate::OnFrameReady(
     media::VideoCapture* capture,
     const scoped_refptr<media::VideoFrame>& frame) {
+  DCHECK(!message_loop_proxy_->BelongsToCurrentThread());
   message_loop_proxy_->PostTask(
       FROM_HERE,
-      base::Bind(&VideoCapturerDelegate::OnFrameReadyOnCaptureThread,
+      base::Bind(&VideoCapturerDelegate::OnFrameReadyOnRenderThread,
                  this,
                  capture,
                  frame));
 }
 
-void VideoCapturerDelegate::OnFrameReadyOnCaptureThread(
+void VideoCapturerDelegate::OnFrameReadyOnRenderThread(
     media::VideoCapture* capture,
     const scoped_refptr<media::VideoFrame>& frame) {
   if (!got_first_frame_) {
@@ -169,7 +174,7 @@
   }
 }
 
-void VideoCapturerDelegate::OnErrorOnCaptureThread(
+void VideoCapturerDelegate::OnErrorOnRenderThread(
     media::VideoCapture* capture) {
   if (!started_callback_.is_null())
     started_callback_.Run(false);
diff --git a/content/renderer/media/media_stream_video_capturer_source.h b/content/renderer/media/media_stream_video_capturer_source.h
index e381eba..1d08ff2 100644
--- a/content/renderer/media/media_stream_video_capturer_source.h
+++ b/content/renderer/media/media_stream_video_capturer_source.h
@@ -72,10 +72,10 @@
 
   virtual ~VideoCapturerDelegate();
 
-  void OnFrameReadyOnCaptureThread(
+  void OnFrameReadyOnRenderThread(
       media::VideoCapture* capture,
       const scoped_refptr<media::VideoFrame>& frame);
-  void OnErrorOnCaptureThread(media::VideoCapture* capture);
+  void OnErrorOnRenderThread(media::VideoCapture* capture);
 
   // The id identifies which video capture device is used for this video
   // capture session.
diff --git a/content/renderer/media/media_stream_video_source.cc b/content/renderer/media/media_stream_video_source.cc
index d3359c6..243d361 100644
--- a/content/renderer/media/media_stream_video_source.cc
+++ b/content/renderer/media/media_stream_video_source.cc
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/renderer/media/media_stream_video_track.h"
 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
 
 namespace content {
@@ -276,6 +277,12 @@
 
 }  // anonymous namespace
 
+// static
+MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
+    const blink::WebMediaStreamSource& source) {
+  return static_cast<MediaStreamVideoSource*>(source.extraData());
+}
+
 MediaStreamVideoSource::MediaStreamVideoSource(
     MediaStreamDependencyFactory* factory)
     : state_(NEW),
@@ -288,12 +295,17 @@
 }
 
 void MediaStreamVideoSource::AddTrack(
-    const blink::WebMediaStreamTrack& track,
+    MediaStreamVideoTrack* track,
     const blink::WebMediaConstraints& constraints,
     const ConstraintsCallback& callback) {
   DCHECK(CalledOnValidThread());
-  requested_constraints_.push_back(RequestedConstraints(constraints,
-                                                        callback));
+  DCHECK(std::find(tracks_.begin(), tracks_.end(),
+                   track) == tracks_.end());
+  tracks_.push_back(track);
+
+  requested_constraints_.push_back(
+      RequestedConstraints(constraints, callback));
+
   switch (state_) {
     case NEW: {
       // Tab capture and Screen capture needs the maximum requested height
@@ -312,7 +324,7 @@
     }
     case STARTING:
     case RETRIEVING_CAPABILITIES: {
-      // The |callback| will be triggered once the delegate has started or
+      // The |callback| will be triggered once the source has started or
       // the capabilities have been retrieved.
       break;
     }
@@ -324,9 +336,11 @@
   }
 }
 
-void MediaStreamVideoSource::RemoveTrack(
-    const blink::WebMediaStreamTrack& track) {
-  // TODO(ronghuawu): What should be done here? Do we really need RemoveTrack?
+void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) {
+  std::vector<MediaStreamVideoTrack*>::iterator it =
+      std::find(tracks_.begin(), tracks_.end(), video_track);
+  DCHECK(it != tracks_.end());
+  tracks_.erase(it);
 }
 
 void MediaStreamVideoSource::InitAdapter() {
@@ -356,6 +370,7 @@
   DVLOG(3) << "DoStopSource()";
   StopSourceImpl();
   state_ = ENDED;
+  SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
 }
 
 void MediaStreamVideoSource::DeliverVideoFrame(
@@ -369,22 +384,16 @@
     const int visible_width = std::min(frame_output_size_.width(),
                                        frame->visible_rect().width());
 
-    // TODO(perkj): horiz_crop and vert_crop must be 0 until local
-    // rendering can support offsets on media::VideoFrame::visible_rect().
-    // crbug/349450. The effect of this is that the cropped frame originates
-    // from the top left of the original frame instead of being centered.
-    // Find a new horizontal offset within |frame|.
-    // const int horiz_crop = frame->visible_rect().x() +
-    //     ((frame->visible_rect().width() - visible_width) / 2);
-    // Find a new vertical offset within |frame|.
-    // const int vert_crop = frame->visible_rect().y() +
-    //     ((frame->visible_rect().height() - visible_height) / 2);
-    const int horiz_crop = 0;
-    const int vert_crop = 0;
-
     const int visible_height = std::min(frame_output_size_.height(),
                                         frame->visible_rect().height());
 
+    // Find a new horizontal offset within |frame|.
+    const int horiz_crop = frame->visible_rect().x() +
+        ((frame->visible_rect().width() - visible_width) / 2);
+    // Find a new vertical offset within |frame|.
+    const int vert_crop = frame->visible_rect().y() +
+        ((frame->visible_rect().height() - visible_height) / 2);
+
     gfx::Rect rect(horiz_crop, vert_crop, visible_width, visible_height);
     video_frame = media::VideoFrame::WrapVideoFrame(
         frame, rect, rect.size(), base::Bind(&ReleaseOriginalFrame, frame));
@@ -395,6 +404,11 @@
       capture_adapter_) {
     capture_adapter_->OnFrameCaptured(video_frame);
   }
+
+  for (std::vector<MediaStreamVideoTrack*>::iterator it = tracks_.begin();
+       it != tracks_.end(); ++it) {
+    (*it)->OnVideoFrame(video_frame);
+  }
 }
 
 void MediaStreamVideoSource::OnSupportedFormats(
@@ -474,8 +488,9 @@
   callbacks.swap(requested_constraints_);
   for (std::vector<RequestedConstraints>::iterator it = callbacks.begin();
        it != callbacks.end(); ++it) {
+
     bool success = state_ == STARTED &&
-                   !FilterFormats(it->constraints, formats).empty();
+        !FilterFormats(it->constraints, formats).empty();
     DVLOG(3) << "FinalizeAddTrack() success " << success;
     if (!it->callback.is_null())
       it->callback.Run(this, success);
@@ -487,7 +502,10 @@
   if (!owner().isNull()) {
     owner().setReadyState(state);
   }
-  // TODO(perkj): Notify all registered tracks.
+  for (std::vector<MediaStreamVideoTrack*>::iterator it = tracks_.begin();
+       it != tracks_.end(); ++it) {
+    (*it)->OnReadyStateChanged(state);
+  }
 }
 
 MediaStreamVideoSource::RequestedConstraints::RequestedConstraints(
diff --git a/content/renderer/media/media_stream_video_source.h b/content/renderer/media/media_stream_video_source.h
index 9b5c13b..651f003 100644
--- a/content/renderer/media/media_stream_video_source.h
+++ b/content/renderer/media/media_stream_video_source.h
@@ -25,6 +25,7 @@
 namespace content {
 
 class MediaStreamDependencyFactory;
+class MediaStreamVideoTrack;
 class WebRtcVideoCapturerAdapter;
 
 // MediaStreamVideoSource is an interface used for sending video frames to a
@@ -49,11 +50,15 @@
   explicit MediaStreamVideoSource(MediaStreamDependencyFactory* factory);
   virtual ~MediaStreamVideoSource();
 
+  // Returns the MediaStreamVideoSource object owned by |source|.
+  static MediaStreamVideoSource* GetVideoSource(
+      const blink::WebMediaStreamSource& source);
+
   // Puts |track| in the registered tracks list.
-  virtual void AddTrack(const blink::WebMediaStreamTrack& track,
-                        const blink::WebMediaConstraints& constraints,
-                        const ConstraintsCallback& callback) OVERRIDE;
-  virtual void RemoveTrack(const blink::WebMediaStreamTrack& track) OVERRIDE;
+  void AddTrack(MediaStreamVideoTrack* track,
+                const blink::WebMediaConstraints& constraints,
+                const ConstraintsCallback& callback);
+  void RemoveTrack(MediaStreamVideoTrack* track);
 
   // TODO(ronghuawu): Remove webrtc::VideoSourceInterface from the public
   // interface of this class.
@@ -160,6 +165,9 @@
 
   media::VideoCaptureFormats supported_formats_;
 
+  // Tracks that currently are receiving video frames.
+  std::vector<MediaStreamVideoTrack*> tracks_;
+
   // TODO(perkj): The below classes use webrtc/libjingle types. The goal is to
   // get rid of them as far as possible.
   MediaStreamDependencyFactory* factory_;
diff --git a/content/renderer/media/media_stream_video_source_unittest.cc b/content/renderer/media/media_stream_video_source_unittest.cc
index 9387d45..5a360ca 100644
--- a/content/renderer/media/media_stream_video_source_unittest.cc
+++ b/content/renderer/media/media_stream_video_source_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/renderer/media/media_stream_video_source.h"
+#include "content/renderer/media/media_stream_video_track.h"
 #include "content/renderer/media/mock_media_constraint_factory.h"
 #include "content/renderer/media/mock_media_stream_dependency_factory.h"
 #include "content/renderer/media/mock_media_stream_video_source.h"
@@ -44,18 +45,14 @@
   blink::WebMediaStreamTrack CreateTrack(
       const std::string& id,
       const blink::WebMediaConstraints& constraints) {
-    blink::WebMediaStreamTrack track;
-    track.initialize(base::UTF8ToUTF16(id), webkit_source_);
-
-    MediaStreamVideoSource* source =
-        static_cast<MediaStreamVideoSource*>(track.source().extraData());
-
-    source->AddTrack(track,
-                     constraints,
-                     base::Bind(
-                         &MediaStreamVideoSourceTest::OnConstraintsApplied,
-                         base::Unretained(this)));
-    return track;
+    bool enabled = true;
+    MediaStreamDependencyFactory* factory = NULL;
+    return MediaStreamVideoTrack::CreateVideoTrack(
+        mock_source_, constraints,
+        base::Bind(
+            &MediaStreamVideoSourceTest::OnConstraintsApplied,
+            base::Unretained(this)),
+        enabled, factory);
   }
 
   blink::WebMediaStreamTrack CreateTrackAndStartSource(
@@ -142,7 +139,7 @@
 TEST_F(MediaStreamVideoSourceTest, AddTrackAndStartSource) {
   blink::WebMediaConstraints constraints;
   constraints.initialize();
-  blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
+  CreateTrack("123", constraints);
   mock_source()->CompleteGetSupportedFormats();
   mock_source()->StartMockedSource();
   EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
@@ -162,18 +159,18 @@
 TEST_F(MediaStreamVideoSourceTest, AddTrackAfterSourceStarts) {
   blink::WebMediaConstraints constraints;
   constraints.initialize();
-  blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
+  CreateTrack("123", constraints);
   mock_source()->CompleteGetSupportedFormats();
   mock_source()->StartMockedSource();
   EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
-  blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
+  CreateTrack("123", constraints);
   EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
 }
 
 TEST_F(MediaStreamVideoSourceTest, AddTrackAndFailToStartSource) {
   blink::WebMediaConstraints constraints;
   constraints.initialize();
-  blink::WebMediaStreamTrack track = CreateTrack("123", constraints);
+  CreateTrack("123", constraints);
   mock_source()->CompleteGetSupportedFormats();
   mock_source()->FailToStartMockedSource();
   EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
@@ -182,8 +179,8 @@
 TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeGetSupportedFormats) {
   blink::WebMediaConstraints constraints;
   constraints.initialize();
-  blink::WebMediaStreamTrack track1 = CreateTrack("123", constraints);
-  blink::WebMediaStreamTrack track2 = CreateTrack("123", constraints);
+  CreateTrack("123", constraints);
+  CreateTrack("123", constraints);
   mock_source()->CompleteGetSupportedFormats();
   mock_source()->StartMockedSource();
   EXPECT_EQ(2, NumberOfSuccessConstraintsCallbacks());
@@ -227,7 +224,7 @@
   CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 640, 480, 30);
 }
 
-// Test that ApplyConstraints fail if the mandatory aspect ratio
+// Test that AddTrack fail if the mandatory aspect ratio
 // is set higher than supported.
 TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatioTooHigh) {
   MockMediaConstraintFactory factory;
diff --git a/content/renderer/media/media_stream_video_track.cc b/content/renderer/media/media_stream_video_track.cc
index 7038323..80d202b 100644
--- a/content/renderer/media/media_stream_video_track.cc
+++ b/content/renderer/media/media_stream_video_track.cc
@@ -5,11 +5,145 @@
 #include "content/renderer/media/media_stream_video_track.h"
 
 #include "content/renderer/media/media_stream_dependency_factory.h"
-#include "content/renderer/media/media_stream_video_source.h"
 #include "content/renderer/media/webrtc/webrtc_video_sink_adapter.h"
 
 namespace content {
 
+// Empty method used for keeping a reference to the original media::VideoFrame
+// in RTCVideoRenderer::OnVideoFrame if a color conversion between I420 and
+// YV12 is needed.
+static void ReleaseOriginalFrame(
+    const scoped_refptr<media::VideoFrame>& frame) {
+}
+
+//static
+blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
+    MediaStreamVideoSource* source,
+    const blink::WebMediaConstraints& constraints,
+    const MediaStreamVideoSource::ConstraintsCallback& callback,
+    bool enabled,
+    MediaStreamDependencyFactory* factory) {
+  blink::WebMediaStreamTrack track;
+  track.initialize(source->owner());
+  track.setExtraData(new MediaStreamVideoTrack(source,
+                                               constraints,
+                                               callback,
+                                               enabled,
+                                               factory));
+  return track;
+}
+
+// static
+MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack(
+     const blink::WebMediaStreamTrack& track) {
+  return static_cast<MediaStreamVideoTrack*>(track.extraData());
+}
+
+MediaStreamVideoTrack::MediaStreamVideoTrack(
+    MediaStreamVideoSource* source,
+    const blink::WebMediaConstraints& constraints,
+    const MediaStreamVideoSource::ConstraintsCallback& callback,
+    bool enabled,
+    MediaStreamDependencyFactory* factory)
+    : MediaStreamTrack(NULL, true),
+      enabled_(enabled),
+      source_(source),
+      factory_(factory) {
+  // TODO(perkj): source can be NULL if this is actually a remote video track.
+  // Remove as soon as we only have one implementation of video tracks.
+  if (source)
+    source->AddTrack(this, constraints, callback);
+}
+
+MediaStreamVideoTrack::~MediaStreamVideoTrack() {
+  DCHECK(sinks_.empty());
+  // TODO(perkj): source can be NULL if this is actually a remote video track.
+  // Remove as soon as we only have one implementation of video tracks.
+  if (source_)
+    source_->RemoveTrack(this);
+}
+
+void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
+  sinks_.push_back(sink);
+}
+
+void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  std::vector<MediaStreamVideoSink*>::iterator it =
+      std::find(sinks_.begin(), sinks_.end(), sink);
+  DCHECK(it != sinks_.end());
+  sinks_.erase(it);
+}
+
+webrtc::VideoTrackInterface* MediaStreamVideoTrack::GetVideoAdapter() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK_EQ(owner().source().type(), blink::WebMediaStreamSource::TypeVideo);
+  if (!track_.get()) {
+    MediaStreamVideoSource* source =
+          static_cast<MediaStreamVideoSource*>(owner().source().extraData());
+    scoped_refptr<webrtc::VideoTrackInterface> video_track(
+        factory_->CreateLocalVideoTrack(owner().id().utf8(),
+                                        source->GetAdapter()));
+    video_track->set_enabled(owner().isEnabled());
+    track_ = video_track;
+  }
+  return static_cast<webrtc::VideoTrackInterface*>(track_.get());
+}
+
+void MediaStreamVideoTrack::SetEnabled(bool enabled) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  enabled_ = enabled;
+  MediaStreamTrack::SetEnabled(enabled);
+  for (std::vector<MediaStreamVideoSink*>::iterator it = sinks_.begin();
+       it != sinks_.end(); ++it) {
+    (*it)->OnEnabledChanged(enabled);
+  }
+}
+
+void MediaStreamVideoTrack::OnVideoFrame(
+    const scoped_refptr<media::VideoFrame>& frame) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  if (!enabled_)
+    return;
+
+  scoped_refptr<media::VideoFrame> video_frame = frame;
+  if (frame->format() == media::VideoFrame::I420) {
+    // Rendering do not support I420 but video capture use I420.
+    // The only difference between YV12 and I420 is the order of U and V plane.
+    // To solve that the I420 frame is simply wrapped in an YV12 video frame.
+    // crbug/341452.
+    video_frame = media::VideoFrame::WrapExternalYuvData(
+        media::VideoFrame::YV12,
+        frame->coded_size(),
+        frame->visible_rect(),
+        frame->natural_size(),
+        frame->stride(media::VideoFrame::kYPlane),
+        frame->stride(media::VideoFrame::kUPlane),
+        frame->stride(media::VideoFrame::kVPlane),
+        frame->data(media::VideoFrame::kYPlane),
+        frame->data(media::VideoFrame::kUPlane),
+        frame->data(media::VideoFrame::kVPlane),
+        frame->GetTimestamp(),
+        base::Bind(&ReleaseOriginalFrame, frame));
+  }
+
+  for (std::vector<MediaStreamVideoSink*>::iterator it = sinks_.begin();
+       it != sinks_.end(); ++it) {
+    (*it)->OnVideoFrame(video_frame);
+  }
+}
+
+void MediaStreamVideoTrack::OnReadyStateChanged(
+    blink::WebMediaStreamSource::ReadyState state) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  for (std::vector<MediaStreamVideoSink*>::iterator it = sinks_.begin();
+       it != sinks_.end(); ++it) {
+    (*it)->OnReadyStateChanged(state);
+  }
+}
+
 // Wrapper which allows to use std::find_if() when adding and removing
 // sinks to/from |sinks_|.
 struct SinkWrapper {
@@ -21,31 +155,27 @@
   MediaStreamVideoSink* sink_;
 };
 
-MediaStreamVideoTrack::MediaStreamVideoTrack(
+WebRtcMediaStreamVideoTrack::WebRtcMediaStreamVideoTrack(
     webrtc::VideoTrackInterface* track)
-    : MediaStreamTrack(track, false),
-      factory_(NULL) {
+    : MediaStreamVideoTrack(NULL,
+                            blink::WebMediaConstraints(),
+                            MediaStreamVideoSource::ConstraintsCallback(),
+                            track->enabled(),
+                            NULL) {
+  track_ = track;
 }
 
-MediaStreamVideoTrack::MediaStreamVideoTrack(
-    MediaStreamDependencyFactory* factory)
-    : MediaStreamTrack(NULL, true),
-      factory_(factory) {
-  DCHECK(factory_);
+WebRtcMediaStreamVideoTrack::~WebRtcMediaStreamVideoTrack() {
 }
 
-MediaStreamVideoTrack::~MediaStreamVideoTrack() {
-  DCHECK(sinks_.empty());
-}
-
-void MediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) {
+void WebRtcMediaStreamVideoTrack::AddSink(MediaStreamVideoSink* sink) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK(std::find_if(sinks_.begin(), sinks_.end(),
                       SinkWrapper(sink)) == sinks_.end());
   sinks_.push_back(new WebRtcVideoSinkAdapter(GetVideoAdapter(), sink));
 }
 
-void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
+void WebRtcMediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
   DCHECK(thread_checker_.CalledOnValidThread());
   ScopedVector<WebRtcVideoSinkAdapter>::iterator it =
       std::find_if(sinks_.begin(), sinks_.end(), SinkWrapper(sink));
@@ -53,18 +183,4 @@
   sinks_.erase(it);
 }
 
-webrtc::VideoTrackInterface* MediaStreamVideoTrack::GetVideoAdapter() {
-  DCHECK_EQ(owner().source().type(), blink::WebMediaStreamSource::TypeVideo);
-  if (!track_.get()) {
-    MediaStreamVideoSource* source =
-          static_cast<MediaStreamVideoSource*>(owner().source().extraData());
-    scoped_refptr<webrtc::VideoTrackInterface> video_track(
-        factory_->CreateLocalVideoTrack(owner().id().utf8(),
-                                        source->GetAdapter()));
-    video_track->set_enabled(owner().isEnabled());
-    track_ = video_track;
-  }
-  return static_cast<webrtc::VideoTrackInterface*>(track_.get());
-}
-
 }  // namespace content
diff --git a/content/renderer/media/media_stream_video_track.h b/content/renderer/media/media_stream_video_track.h
index 2599590..16c0a91 100644
--- a/content/renderer/media/media_stream_video_track.h
+++ b/content/renderer/media/media_stream_video_track.h
@@ -5,12 +5,15 @@
 #ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_
 #define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_
 
+#include <vector>
+
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_vector.h"
 #include "base/threading/thread_checker.h"
 #include "content/common/content_export.h"
 #include "content/public/renderer/media_stream_video_sink.h"
 #include "content/renderer/media/media_stream_track.h"
+#include "content/renderer/media/media_stream_video_source.h"
 
 namespace webrtc {
 class VideoTrackInterface;
@@ -24,23 +27,58 @@
 // MediaStreamVideoTrack is a video specific representation of a
 // blink::WebMediaStreamTrack in content. It is owned by the blink object
 // and can be retrieved from a blink object using
-// WebMediaStreamTrack::extraData()
+// WebMediaStreamTrack::extraData() or MediaStreamVideoTrack::GetVideoTrack.
 class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
  public:
+  // Help method to create a blink::WebMediaStreamTrack and a
+  // MediaStreamVideoTrack instance. The MediaStreamVideoTrack object is owned
+  // by the blink object in its WebMediaStreamTrack::ExtraData member.
+  // |callback| is triggered if the track is added to the source
+  // successfully and will receive video frames that match |constraints|
+  // or if the source fail to provide video frames.
+  // If |enabled| is true, sinks added to the track will
+  // receive video frames when the source deliver frames to the track.
+  static blink::WebMediaStreamTrack CreateVideoTrack(
+      MediaStreamVideoSource* source,
+      const blink::WebMediaConstraints& constraints,
+      const MediaStreamVideoSource::ConstraintsCallback& callback,
+      bool enabled,
+      MediaStreamDependencyFactory* factory);
+
+  static MediaStreamVideoTrack* GetVideoTrack(
+      const blink::WebMediaStreamTrack& track);
+
   // Constructor for local video tracks.
-  explicit MediaStreamVideoTrack(MediaStreamDependencyFactory* factory);
-  // Constructor for remote video tracks.
-  explicit MediaStreamVideoTrack(webrtc::VideoTrackInterface* track);
+   MediaStreamVideoTrack(
+       MediaStreamVideoSource* source,
+       const blink::WebMediaConstraints& constraints,
+       const MediaStreamVideoSource::ConstraintsCallback& callback,
+       bool enabled,
+       MediaStreamDependencyFactory* factory);
   virtual ~MediaStreamVideoTrack();
-  void AddSink(MediaStreamVideoSink* sink);
-  void RemoveSink(MediaStreamVideoSink* sink);
+  virtual void AddSink(MediaStreamVideoSink* sink);
+  virtual void RemoveSink(MediaStreamVideoSink* sink);
 
+  // TODO(perkj): GetVideoAdapter is webrtc specific. Move GetVideoAdapter to
+  // where the track is added to a RTCPeerConnection. crbug/323223.
   virtual webrtc::VideoTrackInterface* GetVideoAdapter() OVERRIDE;
+  virtual void SetEnabled(bool enabled) OVERRIDE;
 
- private:
+  void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame);
+  void OnReadyStateChanged(blink::WebMediaStreamSource::ReadyState state);
+
+ protected:
   // Used to DCHECK that we are called on the correct thread.
   base::ThreadChecker thread_checker_;
-  ScopedVector<WebRtcVideoSinkAdapter> sinks_;
+
+ private:
+  bool enabled_;
+  std::vector<MediaStreamVideoSink*> sinks_;
+
+  // Weak ref to the source this tracks is connected to.  |source_| is owned
+  // by the blink::WebMediaStreamSource and is guaranteed to outlive the
+  // track.
+  MediaStreamVideoSource* source_;
 
   // Weak ref to a MediaStreamDependencyFactory, owned by the RenderThread.
   // It's valid for the lifetime of RenderThread.
@@ -49,6 +87,26 @@
   DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoTrack);
 };
 
+// WebRtcMediaStreamVideoTrack is a content representation of a video track.
+// received on a PeerConnection.
+// TODO(perkj): Replace WebRtcMediaStreamVideoTrack with a remote
+// MediaStreamVideoSource class so that all tracks are MediaStreamVideoTracks
+// and new tracks can be cloned from the original remote video track.
+// crbug/334243.
+class CONTENT_EXPORT WebRtcMediaStreamVideoTrack
+    : public MediaStreamVideoTrack {
+ public:
+  explicit WebRtcMediaStreamVideoTrack(webrtc::VideoTrackInterface* track);
+  virtual ~WebRtcMediaStreamVideoTrack();
+  virtual void AddSink(MediaStreamVideoSink* sink) OVERRIDE;
+  virtual void RemoveSink(MediaStreamVideoSink* sink) OVERRIDE;
+
+ private:
+  ScopedVector<WebRtcVideoSinkAdapter> sinks_;
+
+  DISALLOW_COPY_AND_ASSIGN(WebRtcMediaStreamVideoTrack);
+};
+
 }  // namespace content
 
 #endif  // CONTENT_RENDERER_MEDIA_MEDIA_STREAM_VIDEO_TRACK_H_
diff --git a/content/renderer/media/media_stream_video_track_unittest.cc b/content/renderer/media/media_stream_video_track_unittest.cc
new file mode 100644
index 0000000..242b9ce
--- /dev/null
+++ b/content/renderer/media/media_stream_video_track_unittest.cc
@@ -0,0 +1,144 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/strings/utf_string_conversions.h"
+#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+#include "content/renderer/media/mock_media_stream_video_source.h"
+#include "media/base/video_frame.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class MockVideoSink : public MediaStreamVideoSink {
+ public:
+  MockVideoSink()
+      : number_of_frames_(0), enabled_(true),
+        state_(blink::WebMediaStreamSource::ReadyStateLive) {
+  }
+
+  virtual void OnVideoFrame(
+      const scoped_refptr<media::VideoFrame>& frame) OVERRIDE {
+    ++number_of_frames_;
+  }
+
+  virtual void OnReadyStateChanged(
+        blink::WebMediaStreamSource::ReadyState state) OVERRIDE {
+    state_ = state;
+  }
+
+  virtual void OnEnabledChanged(bool enabled) OVERRIDE {
+    enabled_ = enabled;
+  }
+
+  int number_of_frames() const { return number_of_frames_; }
+  bool enabled() const { return enabled_; }
+  blink::WebMediaStreamSource::ReadyState state() const { return state_; }
+
+ private:
+  int number_of_frames_;
+  bool enabled_;
+  blink::WebMediaStreamSource::ReadyState state_;
+};
+
+class MediaStreamVideoTrackTest : public ::testing::Test {
+ public:
+  MediaStreamVideoTrackTest()
+      : mock_source_(new MockMediaStreamVideoSource(&factory_, false)) {
+    webkit_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
+                              blink::WebMediaStreamSource::TypeVideo,
+                              base::UTF8ToUTF16("dummy_source_name"));
+    webkit_source_.setExtraData(mock_source_);
+  }
+
+ protected:
+  // Create a track that's associated with |mock_source_|.
+  blink::WebMediaStreamTrack CreateTrack() {
+    blink::WebMediaConstraints constraints;
+    constraints.initialize();
+    bool enabled = true;
+    blink::WebMediaStreamTrack track =
+        MediaStreamVideoTrack::CreateVideoTrack(
+            mock_source_, constraints,
+            MediaStreamSource::ConstraintsCallback(), enabled, &factory_);
+    mock_source_->StartMockedSource();
+
+    return track;
+  }
+
+  MockMediaStreamVideoSource* mock_source() { return mock_source_; }
+
+ private:
+  MockMediaStreamDependencyFactory factory_;
+  blink::WebMediaStreamSource webkit_source_;
+  // |mock_source_| is owned by |webkit_source_|.
+  MockMediaStreamVideoSource* mock_source_;
+};
+
+TEST_F(MediaStreamVideoTrackTest, GetAdapter) {
+  blink::WebMediaStreamTrack track = CreateTrack();
+  MediaStreamVideoTrack* video_track =
+      MediaStreamVideoTrack::GetVideoTrack(track);
+  EXPECT_TRUE(video_track->GetVideoAdapter() != NULL);
+}
+
+TEST_F(MediaStreamVideoTrackTest, AddAndRemoveSink) {
+  MockVideoSink sink;
+  blink::WebMediaStreamTrack track = CreateTrack();
+  MediaStreamVideoSink::AddToVideoTrack(&sink, track);
+
+  MediaStreamVideoTrack* video_track =
+        MediaStreamVideoTrack::GetVideoTrack(track);
+  scoped_refptr<media::VideoFrame> frame =
+      media::VideoFrame::CreateBlackFrame(
+          gfx::Size(MediaStreamVideoSource::kDefaultWidth,
+                    MediaStreamVideoSource::kDefaultHeight));
+  video_track->OnVideoFrame(frame);
+  EXPECT_EQ(1, sink.number_of_frames());
+  video_track->OnVideoFrame(frame);
+  EXPECT_EQ(2, sink.number_of_frames());
+
+  MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+  video_track->OnVideoFrame(frame);
+  EXPECT_EQ(2, sink.number_of_frames());
+}
+
+TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
+  MockVideoSink sink;
+  blink::WebMediaStreamTrack track = CreateTrack();
+  MediaStreamVideoSink::AddToVideoTrack(&sink, track);
+
+  MediaStreamVideoTrack* video_track =
+      MediaStreamVideoTrack::GetVideoTrack(track);
+  scoped_refptr<media::VideoFrame> frame =
+      media::VideoFrame::CreateBlackFrame(
+          gfx::Size(MediaStreamVideoSource::kDefaultWidth,
+                    MediaStreamVideoSource::kDefaultHeight));
+  video_track->OnVideoFrame(frame);
+  EXPECT_EQ(1, sink.number_of_frames());
+
+  video_track->SetEnabled(false);
+  EXPECT_FALSE(sink.enabled());
+  video_track->OnVideoFrame(frame);
+  EXPECT_EQ(1, sink.number_of_frames());
+
+  video_track->SetEnabled(true);
+  EXPECT_TRUE(sink.enabled());
+  video_track->OnVideoFrame(frame);
+  EXPECT_EQ(2, sink.number_of_frames());
+  MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+}
+
+TEST_F(MediaStreamVideoTrackTest, SourceStopped) {
+  MockVideoSink sink;
+  blink::WebMediaStreamTrack track = CreateTrack();
+  MediaStreamVideoSink::AddToVideoTrack(&sink, track);
+  EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink.state());
+
+  mock_source()->StopSource();
+  EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink.state());
+  MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+}
+
+}  // namespace content
diff --git a/content/renderer/media/midi_dispatcher.cc b/content/renderer/media/midi_dispatcher.cc
index a7c0679..eaf89de 100644
--- a/content/renderer/media/midi_dispatcher.cc
+++ b/content/renderer/media/midi_dispatcher.cc
@@ -10,6 +10,7 @@
 #include "content/renderer/render_view_impl.h"
 #include "third_party/WebKit/public/web/WebMIDIPermissionRequest.h"
 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
+#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
 
 using blink::WebMIDIPermissionRequest;
 using blink::WebSecurityOrigin;
@@ -32,16 +33,17 @@
   return handled;
 }
 
-void MidiDispatcher::requestSysExPermission(
+void MidiDispatcher::requestSysexPermission(
       const WebMIDIPermissionRequest& request) {
   int bridge_id = requests_.Add(new WebMIDIPermissionRequest(request));
   WebSecurityOrigin security_origin = request.securityOrigin();
   std::string origin = security_origin.toString().utf8();
   GURL url(origin);
-  Send(new MidiHostMsg_RequestSysExPermission(routing_id(), bridge_id, url));
+  Send(new MidiHostMsg_RequestSysExPermission(routing_id(), bridge_id, url,
+      blink::WebUserGestureIndicator::isProcessingUserGesture()));
 }
 
-void MidiDispatcher::cancelSysExPermissionRequest(
+void MidiDispatcher::cancelSysexPermissionRequest(
     const WebMIDIPermissionRequest& request) {
   for (IDMap<WebMIDIPermissionRequest>::iterator it(&requests_);
        !it.IsAtEnd();
diff --git a/content/renderer/media/midi_dispatcher.h b/content/renderer/media/midi_dispatcher.h
index 8c875aa..1e6c8e3 100644
--- a/content/renderer/media/midi_dispatcher.h
+++ b/content/renderer/media/midi_dispatcher.h
@@ -33,16 +33,16 @@
   virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
 
   // blink::WebMIDIClient implementation.
-  virtual void requestSysExPermission(
-      const blink::WebMIDIPermissionRequest& request) OVERRIDE;
-  virtual void cancelSysExPermissionRequest(
-      const blink::WebMIDIPermissionRequest& request) OVERRIDE;
+  virtual void requestSysexPermission(
+      const blink::WebMIDIPermissionRequest& request);
+  virtual void cancelSysexPermissionRequest(
+      const blink::WebMIDIPermissionRequest& request);
 
   // Permission for using system exclusive messages has been set.
   void OnSysExPermissionApproved(int client_id, bool is_allowed);
 
   // Each WebMIDIPermissionRequest object is valid until
-  // cancelSysExPermissionRequest() is called with the object, or used to call
+  // cancelSysexPermissionRequest() is called with the object, or used to call
   // WebMIDIPermissionRequest::setIsAllowed().
   IDMap<blink::WebMIDIPermissionRequest> requests_;
 
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.cc b/content/renderer/media/mock_media_stream_dependency_factory.cc
index 92192b9..f934cce 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.cc
+++ b/content/renderer/media/mock_media_stream_dependency_factory.cc
@@ -43,22 +43,17 @@
   return it;
 };
 
-MockMediaStream::MockMediaStream(const std::string& label)
-    : label_(label),
-      observer_(NULL) {
-}
+MockMediaStream::MockMediaStream(const std::string& label) : label_(label) {}
 
 bool MockMediaStream::AddTrack(AudioTrackInterface* track) {
   audio_track_vector_.push_back(track);
-  if (observer_)
-    observer_->OnChanged();
+  NotifyObservers();
   return true;
 }
 
 bool MockMediaStream::AddTrack(VideoTrackInterface* track) {
   video_track_vector_.push_back(track);
-  if (observer_)
-    observer_->OnChanged();
+  NotifyObservers();
   return true;
 }
 
@@ -68,8 +63,7 @@
   if (it == audio_track_vector_.end())
     return false;
   audio_track_vector_.erase(it);
-  if (observer_)
-    observer_->OnChanged();
+  NotifyObservers();
   return true;
 }
 
@@ -79,8 +73,7 @@
   if (it == video_track_vector_.end())
     return false;
   video_track_vector_.erase(it);
-  if (observer_)
-    observer_->OnChanged();
+  NotifyObservers();
   return true;
 }
 
@@ -109,13 +102,21 @@
 }
 
 void MockMediaStream::RegisterObserver(ObserverInterface* observer) {
-  DCHECK(!observer_);
-  observer_ = observer;
+  DCHECK(observers_.find(observer) == observers_.end());
+  observers_.insert(observer);
 }
 
 void MockMediaStream::UnregisterObserver(ObserverInterface* observer) {
-  DCHECK(observer_ == observer);
-  observer_ = NULL;
+  ObserverSet::iterator it = observers_.find(observer);
+  DCHECK(it != observers_.end());
+  observers_.erase(it);
+}
+
+void MockMediaStream::NotifyObservers() {
+  for (ObserverSet::iterator it = observers_.begin(); it != observers_.end();
+       ++it) {
+    (*it)->OnChanged();
+  }
 }
 
 MockMediaStream::~MockMediaStream() {}
diff --git a/content/renderer/media/mock_media_stream_dependency_factory.h b/content/renderer/media/mock_media_stream_dependency_factory.h
index 243920d..05cd5c7 100644
--- a/content/renderer/media/mock_media_stream_dependency_factory.h
+++ b/content/renderer/media/mock_media_stream_dependency_factory.h
@@ -154,10 +154,14 @@
   virtual ~MockMediaStream();
 
  private:
+  void NotifyObservers();
+
   std::string label_;
   webrtc::AudioTrackVector audio_track_vector_;
   webrtc::VideoTrackVector video_track_vector_;
-  webrtc::ObserverInterface* observer_;
+
+  typedef std::set<webrtc::ObserverInterface*> ObserverSet;
+  ObserverSet observers_;
 };
 
 // A mock factory for creating different objects for
diff --git a/content/renderer/media/remote_media_stream_impl.cc b/content/renderer/media/remote_media_stream_impl.cc
index c156007..66bdb60 100644
--- a/content/renderer/media/remote_media_stream_impl.cc
+++ b/content/renderer/media/remote_media_stream_impl.cc
@@ -8,10 +8,8 @@
 
 #include "base/logging.h"
 #include "base/strings/utf_string_conversions.h"
-#include "content/common/media/media_stream_track_metrics_host_messages.h"
 #include "content/renderer/media/media_stream.h"
 #include "content/renderer/media/media_stream_dependency_factory.h"
-#include "content/renderer/render_thread_impl.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 
 namespace content {
@@ -36,26 +34,13 @@
   // webrtc::ObserverInterface implementation.
   virtual void OnChanged() OVERRIDE;
 
-  // May be overridden by unit tests to avoid sending IPC messages.
-  virtual void SendLifetimeMessage(bool creation);
-
   webrtc::MediaStreamTrackInterface::TrackState state_;
   scoped_refptr<webrtc::MediaStreamTrackInterface> webrtc_track_;
   blink::WebMediaStreamTrack webkit_track_;
-  bool sent_ended_message_;
 
   DISALLOW_COPY_AND_ASSIGN(RemoteMediaStreamTrackObserver);
 };
 
-// We need an ID that is unique for this observer, within the current
-// renderer process, for the lifetime of the observer object. The
-// simplest approach is to just use the object's pointer value. We
-// store it in a uint64 which will be large enough regardless of
-// platform.
-uint64 MakeUniqueId(RemoteMediaStreamTrackObserver* observer) {
-  return reinterpret_cast<uint64>(reinterpret_cast<void*>(observer));
-}
-
 }  // namespace content
 
 namespace {
@@ -93,19 +78,11 @@
     const blink::WebMediaStreamTrack& webkit_track)
     : state_(webrtc_track->state()),
       webrtc_track_(webrtc_track),
-      webkit_track_(webkit_track),
-      sent_ended_message_(false) {
+      webkit_track_(webkit_track) {
   webrtc_track->RegisterObserver(this);
-
-  SendLifetimeMessage(true);
 }
 
 RemoteMediaStreamTrackObserver::~RemoteMediaStreamTrackObserver() {
-  // We send the lifetime-ended message here (it will only get sent if
-  // not previously sent) in case we never received a kEnded state
-  // change.
-  SendLifetimeMessage(false);
-
   webrtc_track_->UnregisterObserver(this);
 }
 
@@ -127,10 +104,6 @@
           blink::WebMediaStreamSource::ReadyStateLive);
       break;
     case webrtc::MediaStreamTrackInterface::kEnded:
-      // This is a more reliable signal to use for duration, as
-      // destruction of this object might not happen until
-      // considerably later.
-      SendLifetimeMessage(false);
       webkit_track_.source().setReadyState(
           blink::WebMediaStreamSource::ReadyStateEnded);
       break;
@@ -140,32 +113,6 @@
   }
 }
 
-void RemoteMediaStreamTrackObserver::SendLifetimeMessage(bool creation) {
-  // We need to mirror the lifetime state for tracks to the browser
-  // process so that the duration of tracks can be accurately
-  // reported, because of RenderProcessHost::FastShutdownIfPossible,
-  // which in many cases will simply kill the renderer process.
-  //
-  // RenderThreadImpl::current() may be NULL in unit tests.
-  RenderThreadImpl* render_thread = RenderThreadImpl::current();
-  if (render_thread) {
-    if (creation) {
-      RenderThreadImpl::current()->Send(
-          new MediaStreamTrackMetricsHost_AddTrack(
-              MakeUniqueId(this),
-              webkit_track_.source().type() ==
-                  blink::WebMediaStreamSource::TypeAudio,
-              true));
-    } else {
-      if (!sent_ended_message_) {
-        sent_ended_message_ = true;
-        RenderThreadImpl::current()->Send(
-            new MediaStreamTrackMetricsHost_RemoveTrack(MakeUniqueId(this)));
-      }
-    }
-  }
-}
-
 RemoteMediaStreamImpl::RemoteMediaStreamImpl(
     webrtc::MediaStreamInterface* webrtc_stream)
     : webrtc_stream_(webrtc_stream) {
diff --git a/content/renderer/media/render_media_log.cc b/content/renderer/media/render_media_log.cc
index 7efb659..d20f622 100644
--- a/content/renderer/media/render_media_log.cc
+++ b/content/renderer/media/render_media_log.cc
@@ -8,22 +8,20 @@
 #include "base/logging.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "content/common/view_messages.h"
-#include "content/renderer/render_thread_impl.h"
-
-using base::Time;
-using base::TimeDelta;
+#include "content/public/renderer/render_thread.h"
 
 namespace content {
 
 RenderMediaLog::RenderMediaLog()
     : render_loop_(base::MessageLoopProxy::current()),
-      last_ipc_send_time_(Time::Now()) {
-  DCHECK(RenderThreadImpl::current()) <<
+      tick_clock_(new base::DefaultTickClock()),
+      last_ipc_send_time_(tick_clock_->NowTicks()) {
+  DCHECK(RenderThread::Get()) <<
       "RenderMediaLog must be constructed on the render thread";
 }
 
 void RenderMediaLog::AddEvent(scoped_ptr<media::MediaLogEvent> event) {
-  if (!RenderThreadImpl::current()) {
+  if (!RenderThread::Get()) {
     render_loop_->PostTask(FROM_HERE, base::Bind(
         &RenderMediaLog::AddEvent, this, base::Passed(&event)));
     return;
@@ -40,8 +38,8 @@
     queued_media_events_.push_back(*event);
 
   // Limit the send rate of high frequency events.
-  Time curr_time = Time::Now();
-  if ((curr_time - last_ipc_send_time_) < TimeDelta::FromSeconds(1))
+  base::TimeTicks curr_time = tick_clock_->NowTicks();
+  if ((curr_time - last_ipc_send_time_) < base::TimeDelta::FromSeconds(1))
     return;
   last_ipc_send_time_ = curr_time;
 
@@ -52,11 +50,17 @@
 
   DVLOG(1) << "media log events array size " << queued_media_events_.size();
 
-  RenderThreadImpl::current()->Send(
+  RenderThread::Get()->Send(
       new ViewHostMsg_MediaLogEvents(queued_media_events_));
   queued_media_events_.clear();
 }
 
 RenderMediaLog::~RenderMediaLog() {}
 
+void RenderMediaLog::SetTickClockForTesting(
+    scoped_ptr<base::TickClock> tick_clock) {
+  tick_clock_.swap(tick_clock);
+  last_ipc_send_time_ = tick_clock_->NowTicks();
+}
+
 }  // namespace content
diff --git a/content/renderer/media/render_media_log.h b/content/renderer/media/render_media_log.h
index 7e0a334..9aac107 100644
--- a/content/renderer/media/render_media_log.h
+++ b/content/renderer/media/render_media_log.h
@@ -6,7 +6,9 @@
 #define CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
 
 #include <vector>
+
 #include "base/time/time.h"
+#include "content/common/content_export.h"
 #include "media/base/media_log.h"
 
 namespace base {
@@ -17,18 +19,25 @@
 
 // RenderMediaLog is an implementation of MediaLog that forwards events to the
 // browser process, throttling as necessary.
-class RenderMediaLog : public media::MediaLog {
+//
+// To minimize the number of events sent over the wire, only the latest event
+// added is sent for high frequency events (e.g., BUFFERED_EXTENTS_CHANGED).
+class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
  public:
   RenderMediaLog();
 
   // MediaLog implementation.
   virtual void AddEvent(scoped_ptr<media::MediaLogEvent> event) OVERRIDE;
 
+  // Will reset |last_ipc_send_time_| with the value of NowTicks().
+  void SetTickClockForTesting(scoped_ptr<base::TickClock> tick_clock);
+
  private:
   virtual ~RenderMediaLog();
 
   scoped_refptr<base::MessageLoopProxy> render_loop_;
-  base::Time last_ipc_send_time_;
+  scoped_ptr<base::TickClock> tick_clock_;
+  base::TimeTicks last_ipc_send_time_;
   std::vector<media::MediaLogEvent> queued_media_events_;
 
   // Limits the number buffered extents changed events we send over IPC to one.
diff --git a/content/renderer/media/render_media_log_unittest.cc b/content/renderer/media/render_media_log_unittest.cc
new file mode 100644
index 0000000..83708aa
--- /dev/null
+++ b/content/renderer/media/render_media_log_unittest.cc
@@ -0,0 +1,104 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/simple_test_tick_clock.h"
+#include "content/common/view_messages.h"
+#include "content/public/test/mock_render_thread.h"
+#include "content/renderer/media/render_media_log.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class RenderMediaLogTest : public testing::Test {
+ public:
+  RenderMediaLogTest()
+      : log_(new RenderMediaLog()),
+        tick_clock_(new base::SimpleTestTickClock()) {
+    log_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
+  }
+
+  virtual ~RenderMediaLogTest() {}
+
+  void AddEvent(media::MediaLogEvent::Type type) {
+    log_->AddEvent(log_->CreateEvent(type));
+  }
+
+  void Advance(base::TimeDelta delta) { tick_clock_->Advance(delta); }
+
+  int message_count() { return render_thread_.sink().message_count(); }
+
+  std::vector<media::MediaLogEvent> GetMediaLogEvents() {
+    const IPC::Message* msg = render_thread_.sink().GetFirstMessageMatching(
+        ViewHostMsg_MediaLogEvents::ID);
+    if (!msg) {
+      ADD_FAILURE() << "Did not find ViewHostMsg_MediaLogEvents IPC message";
+      return std::vector<media::MediaLogEvent>();
+    }
+
+    Tuple1<std::vector<media::MediaLogEvent> > events;
+    ViewHostMsg_MediaLogEvents::Read(msg, &events);
+    return events.a;
+  }
+
+ private:
+  MockRenderThread render_thread_;
+  scoped_refptr<RenderMediaLog> log_;
+  base::SimpleTestTickClock* tick_clock_;  // Owned by |log_|.
+
+  DISALLOW_COPY_AND_ASSIGN(RenderMediaLogTest);
+};
+
+TEST_F(RenderMediaLogTest, ThrottleSendingEvents) {
+  AddEvent(media::MediaLogEvent::LOAD);
+  EXPECT_EQ(0, message_count());
+
+  // Still shouldn't send anything.
+  Advance(base::TimeDelta::FromMilliseconds(500));
+  AddEvent(media::MediaLogEvent::SEEK);
+  EXPECT_EQ(0, message_count());
+
+  // Now we should expect an IPC.
+  Advance(base::TimeDelta::FromMilliseconds(500));
+  AddEvent(media::MediaLogEvent::PLAY);
+  EXPECT_EQ(1, message_count());
+
+  // Verify contents.
+  std::vector<media::MediaLogEvent> events = GetMediaLogEvents();
+  ASSERT_EQ(3u, events.size());
+  EXPECT_EQ(media::MediaLogEvent::LOAD, events[0].type);
+  EXPECT_EQ(media::MediaLogEvent::SEEK, events[1].type);
+  EXPECT_EQ(media::MediaLogEvent::PLAY, events[2].type);
+
+  // Adding another event shouldn't send anything.
+  AddEvent(media::MediaLogEvent::PIPELINE_ERROR);
+  EXPECT_EQ(1, message_count());
+}
+
+TEST_F(RenderMediaLogTest, BufferedExtents) {
+  AddEvent(media::MediaLogEvent::LOAD);
+  AddEvent(media::MediaLogEvent::SEEK);
+
+  // This event is handled separately and should always appear last regardless
+  // of how many times we see it.
+  AddEvent(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED);
+  AddEvent(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED);
+  AddEvent(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED);
+
+  // Trigger IPC message.
+  EXPECT_EQ(0, message_count());
+  Advance(base::TimeDelta::FromMilliseconds(1000));
+  AddEvent(media::MediaLogEvent::PLAY);
+  EXPECT_EQ(1, message_count());
+
+  // Verify contents. There should only be a single buffered extents changed
+  // event.
+  std::vector<media::MediaLogEvent> events = GetMediaLogEvents();
+  ASSERT_EQ(4u, events.size());
+  EXPECT_EQ(media::MediaLogEvent::LOAD, events[0].type);
+  EXPECT_EQ(media::MediaLogEvent::SEEK, events[1].type);
+  EXPECT_EQ(media::MediaLogEvent::PLAY, events[2].type);
+  EXPECT_EQ(media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED, events[3].type);
+}
+
+}  // namespace content
diff --git a/content/renderer/media/rtc_peer_connection_handler.cc b/content/renderer/media/rtc_peer_connection_handler.cc
index 3d22ac5..3b94de7 100644
--- a/content/renderer/media/rtc_peer_connection_handler.cc
+++ b/content/renderer/media/rtc_peer_connection_handler.cc
@@ -9,12 +9,14 @@
 #include <vector>
 
 #include "base/command_line.h"
+#include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/common/content_switches.h"
+#include "content/renderer/media/media_stream.h"
 #include "content/renderer/media/media_stream_audio_source.h"
 #include "content/renderer/media/media_stream_dependency_factory.h"
 #include "content/renderer/media/media_stream_track.h"
@@ -25,6 +27,7 @@
 #include "content/renderer/media/rtc_media_constraints.h"
 #include "content/renderer/media/webrtc_audio_capturer.h"
 #include "content/renderer/media/webrtc_audio_device_impl.h"
+#include "content/renderer/media/webrtc_uma_histograms.h"
 #include "content/renderer/render_thread_impl.h"
 #include "third_party/WebKit/public/platform/WebMediaConstraints.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
@@ -34,6 +37,7 @@
 #include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
 #include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
 #include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
 
 namespace content {
 
@@ -234,6 +238,7 @@
 
   virtual void OnComplete(
       const std::vector<webrtc::StatsReport>& reports) OVERRIDE {
+    TRACE_EVENT0("webrtc", "StatsResponse::OnComplete")
     for (std::vector<webrtc::StatsReport>::const_iterator it = reports.begin();
          it != reports.end(); ++it) {
       if (it->values.size() > 0) {
@@ -549,6 +554,11 @@
     peer_connection_tracker_->TrackAddStream(
         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
 
+  PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
+
+  track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
+                           MediaStream::GetAdapter(stream));
+
   // A media stream is connected to a peer connection, enable the
   // peer connection mode for the sources.
   blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
@@ -584,6 +594,9 @@
   if (peer_connection_tracker_)
     peer_connection_tracker_->TrackRemoveStream(
         this, stream, PeerConnectionTracker::SOURCE_LOCAL);
+  PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
+  track_metrics_.RemoveStream(MediaStreamTrackMetrics::SENT_STREAM,
+                              MediaStream::GetAdapter(stream));
 }
 
 void RTCPeerConnectionHandler::getStats(
@@ -627,6 +640,7 @@
     webrtc::StatsObserver* observer,
     webrtc::MediaStreamTrackInterface* track,
     webrtc::PeerConnectionInterface::StatsOutputLevel level) {
+  TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::GetStats");
   if (!native_peer_connection_->GetStats(observer, track, level)) {
     DVLOG(1) << "GetStats failed.";
     // TODO(hta): Consider how to get an error back.
@@ -716,6 +730,7 @@
 // Called any time the IceConnectionState changes
 void RTCPeerConnectionHandler::OnIceConnectionChange(
     webrtc::PeerConnectionInterface::IceConnectionState new_state) {
+  track_metrics_.IceConnectionChange(new_state);
   blink::WebRTCPeerConnectionHandlerClient::ICEConnectionState state =
       GetWebKitIceConnectionState(new_state);
   if (peer_connection_tracker_)
@@ -756,6 +771,11 @@
         this, remote_stream->webkit_stream(),
         PeerConnectionTracker::SOURCE_REMOTE);
 
+  PerSessionWebRTCAPIMetrics::GetInstance()->IncrementStreamCounter();
+
+  track_metrics_.AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
+                           stream_interface);
+
   client_->didAddRemoteStream(remote_stream->webkit_stream());
 }
 
@@ -768,6 +788,10 @@
     return;
   }
 
+  track_metrics_.RemoveStream(MediaStreamTrackMetrics::RECEIVED_STREAM,
+                              stream_interface);
+  PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
+
   scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
   const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
   DCHECK(!webkit_stream.isNull());
diff --git a/content/renderer/media/rtc_peer_connection_handler.h b/content/renderer/media/rtc_peer_connection_handler.h
index e766dcd..3944376 100644
--- a/content/renderer/media/rtc_peer_connection_handler.h
+++ b/content/renderer/media/rtc_peer_connection_handler.h
@@ -9,6 +9,7 @@
 #include "base/compiler_specific.h"
 #include "content/common/content_export.h"
 #include "content/renderer/media/peer_connection_handler_base.h"
+#include "content/renderer/media/webrtc/media_stream_track_metrics.h"
 #include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandler.h"
 #include "third_party/WebKit/public/platform/WebRTCStatsRequest.h"
 #include "third_party/WebKit/public/platform/WebRTCStatsResponse.h"
@@ -179,6 +180,8 @@
 
   PeerConnectionTracker* peer_connection_tracker_;
 
+  MediaStreamTrackMetrics track_metrics_;
+
   // Counter for a UMA stat reported at destruction time.
   int num_data_channels_created_;
 
diff --git a/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index 293a327..c2b21dc 100644
--- a/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -230,9 +230,11 @@
     video_source.initialize(blink::WebString::fromUTF8(video_track_label),
                             blink::WebMediaStreamSource::TypeVideo,
                             blink::WebString::fromUTF8("video_track"));
-    video_source.setExtraData(
+    MockMediaStreamVideoSource* native_video_source =
         new MockMediaStreamVideoSource(mock_dependency_factory_.get(),
-                                       false));
+                                       false);
+    video_source.setExtraData(native_video_source);
+
 
     blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
         static_cast<size_t>(1));
@@ -244,9 +246,12 @@
                                                  true));
     blink::WebVector<blink::WebMediaStreamTrack> video_tracks(
         static_cast<size_t>(1));
-    video_tracks[0].initialize(video_source.id(), video_source);
-    video_tracks[0].setExtraData(
-            new MediaStreamVideoTrack(mock_dependency_factory_.get()));
+    blink::WebMediaConstraints constraints;
+    constraints.initialize();
+    video_tracks[0] = MediaStreamVideoTrack::CreateVideoTrack(
+        native_video_source, constraints,
+        MediaStreamVideoSource::ConstraintsCallback(), true,
+        mock_dependency_factory_.get());
 
     blink::WebMediaStream local_stream;
     local_stream.initialize(base::UTF8ToUTF16(stream_label), audio_tracks,
diff --git a/content/renderer/media/rtc_video_decoder.cc b/content/renderer/media/rtc_video_decoder.cc
index 1fbabb6..629102f 100644
--- a/content/renderer/media/rtc_video_decoder.cc
+++ b/content/renderer/media/rtc_video_decoder.cc
@@ -347,18 +347,13 @@
   media::PictureBuffer buffer_to_dismiss = it->second;
   assigned_picture_buffers_.erase(it);
 
-  std::set<int32>::iterator at_display_it =
-      picture_buffers_at_display_.find(id);
-
-  if (at_display_it == picture_buffers_at_display_.end()) {
+  if (!picture_buffers_at_display_.count(id)) {
     // We can delete the texture immediately as it's not being displayed.
     factories_->DeleteTexture(buffer_to_dismiss.texture_id());
-  } else {
-    // Texture in display. Postpone deletion until after it's returned to us.
-    bool inserted = dismissed_picture_buffers_
-        .insert(std::make_pair(id, buffer_to_dismiss)).second;
-    DCHECK(inserted);
+    return;
   }
+  // Not destroying a texture in display in |picture_buffers_at_display_|.
+  // Postpone deletion until after it's returned to us.
 }
 
 void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
@@ -382,7 +377,9 @@
   scoped_refptr<media::VideoFrame> frame =
       CreateVideoFrame(picture, pb, timestamp, width, height, size);
   bool inserted =
-      picture_buffers_at_display_.insert(picture.picture_buffer_id()).second;
+      picture_buffers_at_display_.insert(std::make_pair(
+                                             picture.picture_buffer_id(),
+                                             pb.texture_id())).second;
   DCHECK(inserted);
 
   // Create a WebRTC video frame.
@@ -443,9 +440,11 @@
   return media::VideoFrame::WrapNativeTexture(
       make_scoped_ptr(new gpu::MailboxHolder(
           pb.texture_mailbox(), decoder_texture_target_, 0)),
-      media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReusePictureBuffer,
+      media::BindToCurrentLoop(base::Bind(&RTCVideoDecoder::ReleaseMailbox,
                                           weak_factory_.GetWeakPtr(),
-                                          picture.picture_buffer_id())),
+                                          factories_,
+                                          picture.picture_buffer_id(),
+                                          pb.texture_id())),
       pb.size(),
       visible_rect,
       visible_rect.size(),
@@ -639,35 +638,45 @@
     vda_->Reset();
 }
 
-void RTCVideoDecoder::ReusePictureBuffer(
+// static
+void RTCVideoDecoder::ReleaseMailbox(
+    base::WeakPtr<RTCVideoDecoder> decoder,
+    const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
     int64 picture_buffer_id,
+    uint32 texture_id,
     scoped_ptr<gpu::MailboxHolder> mailbox_holder) {
+  DCHECK(factories->GetTaskRunner()->BelongsToCurrentThread());
+  factories->WaitSyncPoint(mailbox_holder->sync_point);
+
+  if (decoder) {
+    decoder->ReusePictureBuffer(picture_buffer_id);
+    return;
+  }
+  // It's the last chance to delete the texture after display,
+  // because RTCVideoDecoder was destructed.
+  factories->DeleteTexture(texture_id);
+}
+
+void RTCVideoDecoder::ReusePictureBuffer(int64 picture_buffer_id) {
   DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
   DVLOG(3) << "ReusePictureBuffer. id=" << picture_buffer_id;
 
-  if (!vda_)
-    return;
+  DCHECK(!picture_buffers_at_display_.empty());
+  PictureBufferTextureMap::iterator display_iterator =
+      picture_buffers_at_display_.find(picture_buffer_id);
+  uint32 texture_id = display_iterator->second;
+  DCHECK(display_iterator != picture_buffers_at_display_.end());
+  picture_buffers_at_display_.erase(display_iterator);
 
-  CHECK(!picture_buffers_at_display_.empty());
-
-  size_t num_erased = picture_buffers_at_display_.erase(picture_buffer_id);
-  DCHECK(num_erased);
-
-  factories_->WaitSyncPoint(mailbox_holder->sync_point);
-
-  std::map<int32, media::PictureBuffer>::iterator it =
-      assigned_picture_buffers_.find(picture_buffer_id);
-
-  if (it == assigned_picture_buffers_.end()) {
+  if (!assigned_picture_buffers_.count(picture_buffer_id)) {
     // This picture was dismissed while in display, so we postponed deletion.
-    it = dismissed_picture_buffers_.find(picture_buffer_id);
-    DCHECK(it != dismissed_picture_buffers_.end());
-    factories_->DeleteTexture(it->second.texture_id());
-    dismissed_picture_buffers_.erase(it);
+    factories_->DeleteTexture(texture_id);
     return;
   }
 
-  vda_->ReusePictureBuffer(picture_buffer_id);
+  // DestroyVDA() might already have been called.
+  if (vda_)
+    vda_->ReusePictureBuffer(picture_buffer_id);
 }
 
 void RTCVideoDecoder::CreateVDA(media::VideoCodecProfile profile,
@@ -681,21 +690,23 @@
 
 void RTCVideoDecoder::DestroyTextures() {
   DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
-  std::map<int32, media::PictureBuffer>::iterator it;
 
-  for (it = assigned_picture_buffers_.begin();
+  // Not destroying PictureBuffers in |picture_buffers_at_display_| yet, since
+  // their textures may still be in use by the user of this RTCVideoDecoder.
+  for (PictureBufferTextureMap::iterator it =
+           picture_buffers_at_display_.begin();
+       it != picture_buffers_at_display_.end();
+       ++it) {
+    assigned_picture_buffers_.erase(it->first);
+  }
+
+  for (std::map<int32, media::PictureBuffer>::iterator it =
+           assigned_picture_buffers_.begin();
        it != assigned_picture_buffers_.end();
        ++it) {
     factories_->DeleteTexture(it->second.texture_id());
   }
   assigned_picture_buffers_.clear();
-
-  for (it = dismissed_picture_buffers_.begin();
-       it != dismissed_picture_buffers_.end();
-       ++it) {
-    factories_->DeleteTexture(it->second.texture_id());
-  }
-  dismissed_picture_buffers_.clear();
 }
 
 void RTCVideoDecoder::DestroyVDA() {
diff --git a/content/renderer/media/rtc_video_decoder.h b/content/renderer/media/rtc_video_decoder.h
index 1686876..3c693e5 100644
--- a/content/renderer/media/rtc_video_decoder.h
+++ b/content/renderer/media/rtc_video_decoder.h
@@ -151,9 +151,15 @@
   // Resets VDA.
   void ResetInternal();
 
+  // Static method is to allow it to run even after RVD is deleted.
+  static void ReleaseMailbox(
+      base::WeakPtr<RTCVideoDecoder> decoder,
+      const scoped_refptr<media::GpuVideoAcceleratorFactories>& factories,
+      int64 picture_buffer_id,
+      uint32 texture_id,
+      scoped_ptr<gpu::MailboxHolder> mailbox_holder);
   // Tells VDA that a picture buffer can be recycled.
-  void ReusePictureBuffer(int64 picture_buffer_id,
-                          scoped_ptr<gpu::MailboxHolder> mailbox_holder);
+  void ReusePictureBuffer(int64 picture_buffer_id);
 
   // Create |vda_| on |vda_loop_proxy_|.
   void CreateVDA(media::VideoCodecProfile profile, base::WaitableEvent* waiter);
@@ -219,13 +225,12 @@
   // A map from picture buffer IDs to texture-backed picture buffers.
   std::map<int32, media::PictureBuffer> assigned_picture_buffers_;
 
-  // Picture buffers that are dismissed but not deleted yet.
-  std::map<int32, media::PictureBuffer> dismissed_picture_buffers_;
-
   // PictureBuffers given to us by VDA via PictureReady, which we sent forward
   // as VideoFrames to be rendered via read_cb_, and which will be returned
   // to us via ReusePictureBuffer.
-  std::set<int32> picture_buffers_at_display_;
+  typedef std::map<int32 /* picture_buffer_id */, uint32 /* texture_id */>
+      PictureBufferTextureMap;
+  PictureBufferTextureMap picture_buffers_at_display_;
 
   // The id that will be given to the next picture buffer.
   int32 next_picture_buffer_id_;
diff --git a/content/renderer/media/rtc_video_encoder.cc b/content/renderer/media/rtc_video_encoder.cc
index 047bb8c..c930a7c 100644
--- a/content/renderer/media/rtc_video_encoder.cc
+++ b/content/renderer/media/rtc_video_encoder.cc
@@ -10,6 +10,7 @@
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/metrics/histogram.h"
+#include "base/rand_util.h"
 #include "base/synchronization/waitable_event.h"
 #include "media/base/bitstream_buffer.h"
 #include "media/base/video_frame.h"
@@ -152,6 +153,9 @@
   // encoder.
   int output_buffers_free_count_;
 
+  // 15 bits running index of the VP8 frames. See VP8 RTP spec for details.
+  uint16 picture_id_;
+
   DISALLOW_COPY_AND_ASSIGN(Impl);
 };
 
@@ -167,6 +171,8 @@
       input_next_frame_keyframe_(false),
       output_buffers_free_count_(0) {
   thread_checker_.DetachFromThread();
+  // Picture ID should start on a random number.
+  picture_id_ = static_cast<uint16_t>(base::RandInt(0, 0x7FFF));
 }
 
 void RTCVideoEncoder::Impl::CreateAndInitializeVEA(
@@ -378,7 +384,10 @@
       base::Bind(&RTCVideoEncoder::ReturnEncodedImage,
                  weak_encoder_,
                  base::Passed(&image),
-                 bitstream_buffer_id));
+                 bitstream_buffer_id,
+                 picture_id_));
+  // Picture ID must wrap after reaching the maximum.
+  picture_id_ = (picture_id_ + 1) & 0x7FFF;
 }
 
 void RTCVideoEncoder::Impl::NotifyError(
@@ -637,10 +646,12 @@
 }
 
 void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
-                                         int32 bitstream_buffer_id) {
+                                         int32 bitstream_buffer_id,
+                                         uint16 picture_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
   DVLOG(3) << "ReturnEncodedImage(): "
-              "bitstream_buffer_id=" << bitstream_buffer_id;
+           << "bitstream_buffer_id=" << bitstream_buffer_id
+           << ", picture_id=" << picture_id;
 
   if (!encoded_image_callback_)
     return;
@@ -649,7 +660,7 @@
   memset(&info, 0, sizeof(info));
   info.codecType = video_codec_type_;
   if (video_codec_type_ == webrtc::kVideoCodecVP8) {
-    info.codecSpecific.VP8.pictureId = -1;
+    info.codecSpecific.VP8.pictureId = picture_id;
     info.codecSpecific.VP8.tl0PicIdx = -1;
     info.codecSpecific.VP8.keyIdx = -1;
   }
diff --git a/content/renderer/media/rtc_video_encoder.h b/content/renderer/media/rtc_video_encoder.h
index 8e179ac..eb1677e 100644
--- a/content/renderer/media/rtc_video_encoder.h
+++ b/content/renderer/media/rtc_video_encoder.h
@@ -69,7 +69,8 @@
 
   // Return an encoded output buffer to WebRTC.
   void ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
-                          int32 bitstream_buffer_id);
+                          int32 bitstream_buffer_id,
+                          uint16 picture_id);
 
   void NotifyError(int32_t error);
 
diff --git a/content/renderer/media/rtc_video_renderer.cc b/content/renderer/media/rtc_video_renderer.cc
index 013fcad..2003862 100644
--- a/content/renderer/media/rtc_video_renderer.cc
+++ b/content/renderer/media/rtc_video_renderer.cc
@@ -9,6 +9,8 @@
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
 
+const int kMinFrameSize = 2;
+
 namespace content {
 
 RTCVideoRenderer::RTCVideoRenderer(
@@ -19,7 +21,7 @@
       repaint_cb_(repaint_cb),
       message_loop_proxy_(base::MessageLoopProxy::current()),
       state_(STOPPED),
-      first_frame_rendered_(false),
+      frame_size_(kMinFrameSize, kMinFrameSize),
       video_track_(video_track) {
 }
 
@@ -29,7 +31,6 @@
 void RTCVideoRenderer::Start() {
   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
   DCHECK_EQ(state_, STOPPED);
-  DCHECK(!first_frame_rendered_);
 
   AddToVideoTrack(this, video_track_);
   state_ = STARTED;
@@ -37,7 +38,7 @@
   if (video_track_.source().readyState() ==
           blink::WebMediaStreamSource::ReadyStateEnded ||
       !video_track_.isEnabled()) {
-    MaybeRenderSignalingFrame();
+    RenderSignalingFrame();
   }
 }
 
@@ -46,7 +47,8 @@
   DCHECK(state_ == STARTED || state_ == PAUSED);
   RemoveFromVideoTrack(this, video_track_);
   state_ = STOPPED;
-  first_frame_rendered_ = false;
+  frame_size_.set_width(kMinFrameSize);
+  frame_size_.set_height(kMinFrameSize);
 }
 
 void RTCVideoRenderer::Play() {
@@ -67,13 +69,13 @@
     blink::WebMediaStreamSource::ReadyState state) {
   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
   if (state == blink::WebMediaStreamSource::ReadyStateEnded)
-    MaybeRenderSignalingFrame();
+    RenderSignalingFrame();
 }
 
 void RTCVideoRenderer::OnEnabledChanged(bool enabled) {
   DCHECK(message_loop_proxy_->BelongsToCurrentThread());
   if (!enabled)
-    MaybeRenderSignalingFrame();
+    RenderSignalingFrame();
 }
 
 void RTCVideoRenderer::OnVideoFrame(
@@ -83,26 +85,25 @@
     return;
   }
 
+  frame_size_ = frame->natural_size();
+
   TRACE_EVENT_INSTANT1("rtc_video_renderer",
                        "OnVideoFrame",
                        TRACE_EVENT_SCOPE_THREAD,
                        "timestamp",
                        frame->GetTimestamp().InMilliseconds());
   repaint_cb_.Run(frame);
-  first_frame_rendered_ = true;
 }
 
-void RTCVideoRenderer::MaybeRenderSignalingFrame() {
-  // Render a small black frame if no frame has been rendered.
+void RTCVideoRenderer::RenderSignalingFrame() {
   // This is necessary to make sure audio can play if the video tag src is
   // a MediaStream video track that has been rejected, ended or disabled.
-  if (first_frame_rendered_)
-    return;
-
-  const int kMinFrameSize = 2;
-  const gfx::Size size(kMinFrameSize, kMinFrameSize);
+  // It also ensure that the renderer don't hold a reference to a real video
+  // frame if no more frames are provided. This is since there might be a
+  // finite number of available buffers. E.g, video that
+  // originates from a video camera.
   scoped_refptr<media::VideoFrame> video_frame =
-      media::VideoFrame::CreateBlackFrame(size);
+      media::VideoFrame::CreateBlackFrame(frame_size_);
   OnVideoFrame(video_frame);
 }
 
diff --git a/content/renderer/media/rtc_video_renderer.h b/content/renderer/media/rtc_video_renderer.h
index b72a586..35a8da9 100644
--- a/content/renderer/media/rtc_video_renderer.h
+++ b/content/renderer/media/rtc_video_renderer.h
@@ -59,13 +59,13 @@
       blink::WebMediaStreamSource::ReadyState state) OVERRIDE;
   virtual void OnEnabledChanged(bool enabled) OVERRIDE;
 
-  void MaybeRenderSignalingFrame();
+  void RenderSignalingFrame();
 
   base::Closure error_cb_;
   RepaintCB repaint_cb_;
   scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
   State state_;
-  bool first_frame_rendered_;
+  gfx::Size frame_size_;
   blink::WebMediaStreamTrack video_track_;
 
   DISALLOW_COPY_AND_ASSIGN(RTCVideoRenderer);
diff --git a/content/renderer/media/video_destination_handler.cc b/content/renderer/media/video_destination_handler.cc
index fc1157f..a76ca89 100644
--- a/content/renderer/media/video_destination_handler.cc
+++ b/content/renderer/media/video_destination_handler.cc
@@ -15,7 +15,9 @@
 #include "content/renderer/pepper/ppb_image_data_impl.h"
 #include "content/renderer/render_thread_impl.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
+#include "url/gurl.h"
 
 using cricket::CaptureState;
 using cricket::VideoFormat;
diff --git a/content/renderer/media/video_frame_compositor.cc b/content/renderer/media/video_frame_compositor.cc
new file mode 100644
index 0000000..bf11d15
--- /dev/null
+++ b/content/renderer/media/video_frame_compositor.cc
@@ -0,0 +1,143 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/video_frame_compositor.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/single_thread_task_runner.h"
+#include "cc/layers/video_frame_provider.h"
+#include "content/renderer/render_thread_impl.h"
+#include "media/base/video_frame.h"
+
+namespace content {
+
+class VideoFrameCompositor::Internal : public cc::VideoFrameProvider {
+ public:
+  Internal(
+      const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
+      const base::Callback<void(gfx::Size)>& natural_size_changed_cb)
+      : compositor_task_runner_(compositor_task_runner),
+        natural_size_changed_cb_(natural_size_changed_cb),
+        client_(NULL),
+        compositor_notification_pending_(false),
+        frames_dropped_before_compositor_was_notified_(0) {}
+
+  virtual ~Internal() {
+    if (client_)
+      client_->StopUsingProvider();
+  }
+
+  void DeleteSoon() {
+    compositor_task_runner_->DeleteSoon(FROM_HERE, this);
+  }
+
+  void UpdateCurrentFrame(const scoped_refptr<media::VideoFrame>& frame) {
+    base::AutoLock auto_lock(lock_);
+
+    if (current_frame_ &&
+        current_frame_->natural_size() != frame->natural_size()) {
+      natural_size_changed_cb_.Run(frame->natural_size());
+    }
+
+    current_frame_ = frame;
+
+    // Count frames as dropped if and only if we updated the frame but didn't
+    // finish notifying the compositor for the previous frame.
+    if (compositor_notification_pending_) {
+      if (frames_dropped_before_compositor_was_notified_ < kuint32max)
+        ++frames_dropped_before_compositor_was_notified_;
+      return;
+    }
+
+    compositor_notification_pending_ = true;
+    compositor_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&Internal::NotifyCompositorOfNewFrame,
+                   base::Unretained(this)));
+  }
+
+  uint32 GetFramesDroppedBeforeCompositorWasNotified() {
+    base::AutoLock auto_lock(lock_);
+    return frames_dropped_before_compositor_was_notified_;
+  }
+
+  void SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
+      uint32 dropped_frames) {
+    base::AutoLock auto_lock(lock_);
+    frames_dropped_before_compositor_was_notified_ = dropped_frames;
+  }
+
+  // cc::VideoFrameProvider implementation.
+  virtual void SetVideoFrameProviderClient(
+      cc::VideoFrameProvider::Client* client) OVERRIDE {
+    if (client_)
+      client_->StopUsingProvider();
+    client_ = client;
+  }
+
+  virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE {
+    base::AutoLock auto_lock(lock_);
+    return current_frame_;
+  }
+
+  virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
+      OVERRIDE {}
+
+ private:
+  void NotifyCompositorOfNewFrame() {
+    base::AutoLock auto_lock(lock_);
+    compositor_notification_pending_ = false;
+    if (client_)
+      client_->DidReceiveFrame();
+  }
+
+  scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
+  base::Callback<void(gfx::Size)>natural_size_changed_cb_;
+
+  cc::VideoFrameProvider::Client* client_;
+
+  base::Lock lock_;
+  scoped_refptr<media::VideoFrame> current_frame_;
+  bool compositor_notification_pending_;
+  uint32 frames_dropped_before_compositor_was_notified_;
+
+  DISALLOW_COPY_AND_ASSIGN(Internal);
+};
+
+VideoFrameCompositor::VideoFrameCompositor(
+    const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
+    const base::Callback<void(gfx::Size)>& natural_size_changed_cb)
+    : internal_(new Internal(compositor_task_runner, natural_size_changed_cb)) {
+}
+
+VideoFrameCompositor::~VideoFrameCompositor() {
+  internal_->DeleteSoon();
+}
+
+cc::VideoFrameProvider* VideoFrameCompositor::GetVideoFrameProvider() {
+  return internal_;
+}
+
+void VideoFrameCompositor::UpdateCurrentFrame(
+    const scoped_refptr<media::VideoFrame>& frame) {
+  internal_->UpdateCurrentFrame(frame);
+}
+
+scoped_refptr<media::VideoFrame> VideoFrameCompositor::GetCurrentFrame() {
+  return internal_->GetCurrentFrame();
+}
+
+uint32 VideoFrameCompositor::GetFramesDroppedBeforeCompositorWasNotified() {
+  return internal_->GetFramesDroppedBeforeCompositorWasNotified();
+}
+
+void
+VideoFrameCompositor::SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
+    uint32 dropped_frames) {
+  internal_->SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
+      dropped_frames);
+}
+
+}  // namespace content
diff --git a/content/renderer/media/video_frame_compositor.h b/content/renderer/media/video_frame_compositor.h
new file mode 100644
index 0000000..7a8b0a8
--- /dev/null
+++ b/content/renderer/media/video_frame_compositor.h
@@ -0,0 +1,77 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
+#define CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/size.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace cc {
+class VideoFrameProvider;
+}
+
+namespace media {
+class VideoFrame;
+}
+
+namespace content {
+
+// VideoFrameCompositor handles incoming frames by notifying the compositor in a
+// thread-safe manner.
+//
+// Typical usage is to deliver the output of VideoRendererImpl to
+// UpdateCurrentFrame() so that VideoFrameCompositor can take care of tracking
+// dropped frames and firing callbacks as needed.
+//
+// All APIs are callable from any thread.
+class CONTENT_EXPORT VideoFrameCompositor {
+ public:
+  // |compositor_task_runner| is the task runner of the compositor.
+  //
+  // |natural_size_changed_cb| is run with the new natural size of the video
+  // frame whenever a change in natural size is detected. It is not called the
+  // first time UpdateCurrentFrame() is called. Run on the same thread as the
+  // caller of UpdateCurrentFrame().
+  VideoFrameCompositor(
+      const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
+      const base::Callback<void(gfx::Size)>& natural_size_changed_cb);
+  ~VideoFrameCompositor();
+
+  cc::VideoFrameProvider* GetVideoFrameProvider();
+
+  // Updates the current frame and notifies the compositor.
+  void UpdateCurrentFrame(const scoped_refptr<media::VideoFrame>& frame);
+
+  // Retrieves the last frame set via UpdateCurrentFrame() for non-compositing
+  // purposes (e.g., painting to a canvas).
+  //
+  // Note that the compositor retrieves frames via the cc::VideoFrameProvider
+  // interface instead of using this method.
+  scoped_refptr<media::VideoFrame> GetCurrentFrame();
+
+  // Returns the number of frames dropped before the compositor was notified
+  // of a new frame.
+  uint32 GetFramesDroppedBeforeCompositorWasNotified();
+
+  void SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
+      uint32 dropped_frames);
+
+ private:
+  class Internal;
+  Internal* internal_;
+
+  DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositor);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_RENDERER_MEDIA_VIDEO_FRAME_COMPOSITOR_H_
diff --git a/content/renderer/media/video_frame_compositor_unittest.cc b/content/renderer/media/video_frame_compositor_unittest.cc
new file mode 100644
index 0000000..19c12bd
--- /dev/null
+++ b/content/renderer/media/video_frame_compositor_unittest.cc
@@ -0,0 +1,162 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "cc/layers/video_frame_provider.h"
+#include "content/renderer/media/video_frame_compositor.h"
+#include "media/base/video_frame.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+using media::VideoFrame;
+
+class VideoFrameCompositorTest : public testing::Test,
+                                 public cc::VideoFrameProvider::Client {
+ public:
+  VideoFrameCompositorTest()
+      : compositor_(new VideoFrameCompositor(
+            message_loop_.message_loop_proxy(),
+            base::Bind(&VideoFrameCompositorTest::NaturalSizeChanged,
+                       base::Unretained(this)))),
+        did_receive_frame_count_(0),
+        natural_size_changed_count_(0) {
+    provider()->SetVideoFrameProviderClient(this);
+  }
+
+  virtual ~VideoFrameCompositorTest() {
+    provider()->SetVideoFrameProviderClient(NULL);
+    compositor_.reset();
+    message_loop_.RunUntilIdle();
+  }
+
+  base::MessageLoop* message_loop() { return &message_loop_; }
+  VideoFrameCompositor* compositor() { return compositor_.get(); }
+  cc::VideoFrameProvider* provider() {
+    return compositor_->GetVideoFrameProvider();
+  }
+  int did_receive_frame_count() { return did_receive_frame_count_; }
+  int natural_size_changed_count() { return natural_size_changed_count_; }
+  gfx::Size natural_size() { return natural_size_; }
+
+ private:
+  // cc::VideoFrameProvider::Client implementation.
+  virtual void StopUsingProvider() OVERRIDE {}
+  virtual void DidReceiveFrame() OVERRIDE {
+    ++did_receive_frame_count_;
+  }
+  virtual void DidUpdateMatrix(const float* matrix) OVERRIDE {}
+
+  void NaturalSizeChanged(gfx::Size natural_size) {
+    ++natural_size_changed_count_;
+    natural_size_ = natural_size;
+  }
+
+  base::MessageLoop message_loop_;
+  scoped_ptr<VideoFrameCompositor> compositor_;
+  int did_receive_frame_count_;
+  int natural_size_changed_count_;
+  gfx::Size natural_size_;
+
+  DISALLOW_COPY_AND_ASSIGN(VideoFrameCompositorTest);
+};
+
+TEST_F(VideoFrameCompositorTest, InitialValues) {
+  EXPECT_TRUE(compositor()->GetVideoFrameProvider());
+  EXPECT_FALSE(compositor()->GetCurrentFrame());
+  EXPECT_EQ(0u, compositor()->GetFramesDroppedBeforeCompositorWasNotified());
+}
+
+TEST_F(VideoFrameCompositorTest, UpdateCurrentFrame) {
+  scoped_refptr<VideoFrame> expected = VideoFrame::CreateEOSFrame();
+
+  compositor()->UpdateCurrentFrame(expected);
+  scoped_refptr<VideoFrame> actual = compositor()->GetCurrentFrame();
+  EXPECT_EQ(expected, actual);
+
+  // Should notify compositor asynchronously.
+  EXPECT_EQ(0, did_receive_frame_count());
+  message_loop()->RunUntilIdle();
+  EXPECT_EQ(1, did_receive_frame_count());
+}
+
+TEST_F(VideoFrameCompositorTest, NaturalSizeChanged) {
+  gfx::Size initial_size(8, 8);
+  scoped_refptr<VideoFrame> initial_frame =
+      VideoFrame::CreateBlackFrame(initial_size);
+
+  gfx::Size larger_size(16, 16);
+  scoped_refptr<VideoFrame> larger_frame =
+      VideoFrame::CreateBlackFrame(larger_size);
+
+  // Initial expectations.
+  EXPECT_EQ(0, natural_size().width());
+  EXPECT_EQ(0, natural_size().height());
+  EXPECT_EQ(0, natural_size_changed_count());
+
+  // Callback isn't fired for the first frame.
+  compositor()->UpdateCurrentFrame(initial_frame);
+  EXPECT_EQ(0, natural_size().width());
+  EXPECT_EQ(0, natural_size().height());
+  EXPECT_EQ(0, natural_size_changed_count());
+
+  // Callback should be fired once.
+  compositor()->UpdateCurrentFrame(larger_frame);
+  EXPECT_EQ(larger_size.width(), natural_size().width());
+  EXPECT_EQ(larger_size.height(), natural_size().height());
+  EXPECT_EQ(1, natural_size_changed_count());
+
+  compositor()->UpdateCurrentFrame(larger_frame);
+  EXPECT_EQ(larger_size.width(), natural_size().width());
+  EXPECT_EQ(larger_size.height(), natural_size().height());
+  EXPECT_EQ(1, natural_size_changed_count());
+
+  // Callback is fired once more when switching back to initial size.
+  compositor()->UpdateCurrentFrame(initial_frame);
+  EXPECT_EQ(initial_size.width(), natural_size().width());
+  EXPECT_EQ(initial_size.height(), natural_size().height());
+  EXPECT_EQ(2, natural_size_changed_count());
+
+  compositor()->UpdateCurrentFrame(initial_frame);
+  EXPECT_EQ(initial_size.width(), natural_size().width());
+  EXPECT_EQ(initial_size, natural_size());
+  EXPECT_EQ(2, natural_size_changed_count());
+}
+
+TEST_F(VideoFrameCompositorTest, GetFramesDroppedBeforeCompositorWasNotified) {
+  scoped_refptr<VideoFrame> frame = VideoFrame::CreateEOSFrame();
+
+  compositor()->UpdateCurrentFrame(frame);
+  EXPECT_EQ(0, did_receive_frame_count());
+  EXPECT_EQ(0u, compositor()->GetFramesDroppedBeforeCompositorWasNotified());
+
+  // Should not increment if we finished notifying the compositor.
+  //
+  // This covers the normal scenario where the compositor is getting
+  // notifications in a timely manner.
+  message_loop()->RunUntilIdle();
+  compositor()->UpdateCurrentFrame(frame);
+  EXPECT_EQ(1, did_receive_frame_count());
+  EXPECT_EQ(0u, compositor()->GetFramesDroppedBeforeCompositorWasNotified());
+
+  // Should increment if we didn't notify the compositor.
+  //
+  // This covers the scenario where the compositor is falling behind.
+  // Consider it dropped.
+  message_loop()->RunUntilIdle();
+  compositor()->UpdateCurrentFrame(frame);
+  compositor()->UpdateCurrentFrame(frame);
+  EXPECT_EQ(2, did_receive_frame_count());
+  EXPECT_EQ(1u, compositor()->GetFramesDroppedBeforeCompositorWasNotified());
+
+  // Shouldn't overflow.
+  compositor()->SetFramesDroppedBeforeCompositorWasNotifiedForTesting(
+      kuint32max);
+  compositor()->UpdateCurrentFrame(frame);
+  EXPECT_EQ(kuint32max,
+            compositor()->GetFramesDroppedBeforeCompositorWasNotified());
+}
+
+}  // namespace content
diff --git a/content/renderer/media/video_source_handler.cc b/content/renderer/media/video_source_handler.cc
index 6d274b8..e9756d0 100644
--- a/content/renderer/media/video_source_handler.cc
+++ b/content/renderer/media/video_source_handler.cc
@@ -12,9 +12,11 @@
 #include "content/renderer/media/media_stream_registry_interface.h"
 #include "content/renderer/render_thread_impl.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
 #include "third_party/libjingle/source/talk/media/base/videoframe.h"
 #include "third_party/libjingle/source/talk/media/base/videorenderer.h"
+#include "url/gurl.h"
 
 using cricket::VideoFrame;
 using cricket::VideoRenderer;
diff --git a/content/renderer/media/webcontentdecryptionmodule_impl.cc b/content/renderer/media/webcontentdecryptionmodule_impl.cc
index 8a4cf47..a9b201f 100644
--- a/content/renderer/media/webcontentdecryptionmodule_impl.cc
+++ b/content/renderer/media/webcontentdecryptionmodule_impl.cc
@@ -15,15 +15,27 @@
 #include "content/renderer/media/cdm_session_adapter.h"
 #include "content/renderer/media/webcontentdecryptionmodulesession_impl.h"
 #include "media/base/media_keys.h"
+#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
 
 #if defined(ENABLE_PEPPER_CDMS)
 #include "content/renderer/media/crypto/pepper_cdm_wrapper_impl.h"
 #endif
 
+namespace blink {
+class WebFrame;
+}
+
 namespace content {
 
 WebContentDecryptionModuleImpl* WebContentDecryptionModuleImpl::Create(
+    blink::WebFrame* frame,
+    const blink::WebSecurityOrigin& security_origin,
     const base::string16& key_system) {
+  // TODO(jrummell): Use |security_origin| rather than using the document URL.
+  DCHECK(frame);
+  DCHECK(!security_origin.isNull());
+  DCHECK(!key_system.empty());
+
   // TODO(ddorwin): Guard against this in supported types check and remove this.
   // Chromium only supports ASCII key systems.
   if (!IsStringASCII(key_system)) {
@@ -34,11 +46,7 @@
   scoped_refptr<CdmSessionAdapter> adapter(new CdmSessionAdapter());
   if (!adapter->Initialize(
 #if defined(ENABLE_PEPPER_CDMS)
-          // TODO(jrummell): Figure out how to get a WebFrame from Blink (or
-          // something equivalent) so the plugin can actually get created.
-          // http://crbug.com/250049
-          base::Bind(&PepperCdmWrapperImpl::Create,
-                     static_cast<blink::WebFrame*>(NULL)),
+          base::Bind(&PepperCdmWrapperImpl::Create, frame),
 #endif
           base::UTF16ToASCII(key_system))) {
     return NULL;
diff --git a/content/renderer/media/webcontentdecryptionmodule_impl.h b/content/renderer/media/webcontentdecryptionmodule_impl.h
index 6ec3a95..3a07a24 100644
--- a/content/renderer/media/webcontentdecryptionmodule_impl.h
+++ b/content/renderer/media/webcontentdecryptionmodule_impl.h
@@ -12,6 +12,11 @@
 #include "base/strings/string16.h"
 #include "third_party/WebKit/public/platform/WebContentDecryptionModule.h"
 
+namespace blink {
+class WebFrame;
+class WebSecurityOrigin;
+}
+
 namespace media {
 class Decryptor;
 class MediaKeys;
@@ -26,6 +31,8 @@
     : public blink::WebContentDecryptionModule {
  public:
   static WebContentDecryptionModuleImpl* Create(
+      blink::WebFrame* frame,
+      const blink::WebSecurityOrigin& security_origin,
       const base::string16& key_system);
 
   virtual ~WebContentDecryptionModuleImpl();
diff --git a/content/renderer/media/webmediaplayer_impl.cc b/content/renderer/media/webmediaplayer_impl.cc
index 9399476..dbe3924 100644
--- a/content/renderer/media/webmediaplayer_impl.cc
+++ b/content/renderer/media/webmediaplayer_impl.cc
@@ -40,6 +40,7 @@
 #include "gpu/GLES2/gl2extchromium.h"
 #include "gpu/command_buffer/common/mailbox_holder.h"
 #include "media/audio/null_audio_sink.h"
+#include "media/base/audio_hardware_config.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/filter_collection.h"
 #include "media/base/limits.h"
@@ -165,10 +166,11 @@
       supports_save_(true),
       starting_(false),
       chunk_demuxer_(NULL),
-      painter_(
-          BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::InvalidateOnMainThread),
+      compositor_(  // Threaded compositing isn't enabled universally yet.
+          (RenderThreadImpl::current()->compositor_message_loop_proxy()
+               ? RenderThreadImpl::current()->compositor_message_loop_proxy()
+               : base::MessageLoopProxy::current()),
           BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNaturalSizeChange)),
-      video_frame_provider_client_(NULL),
       text_track_index_(0),
       web_cdm_(NULL) {
   media_log_->AddEvent(
@@ -198,7 +200,6 @@
 }
 
 WebMediaPlayerImpl::~WebMediaPlayerImpl() {
-  SetVideoFrameProviderClient(NULL);
   client_->setWebLayer(NULL);
 
   DCHECK(main_loop_->BelongsToCurrentThread());
@@ -436,19 +437,19 @@
 bool WebMediaPlayerImpl::hasVideo() const {
   DCHECK(main_loop_->BelongsToCurrentThread());
 
-  return pipeline_.HasVideo();
+  return pipeline_metadata_.has_video;
 }
 
 bool WebMediaPlayerImpl::hasAudio() const {
   DCHECK(main_loop_->BelongsToCurrentThread());
 
-  return pipeline_.HasAudio();
+  return pipeline_metadata_.has_audio;
 }
 
 blink::WebSize WebMediaPlayerImpl::naturalSize() const {
   DCHECK(main_loop_->BelongsToCurrentThread());
 
-  return blink::WebSize(natural_size_);
+  return blink::WebSize(pipeline_metadata_.natural_size);
 }
 
 bool WebMediaPlayerImpl::paused() const {
@@ -533,9 +534,14 @@
         frame_->view()->isAcceleratedCompositingActive());
   }
 
+  // TODO(scherkus): Clarify paint() API contract to better understand when and
+  // why it's being called. For example, today paint() is called when:
+  //   - We haven't reached HAVE_CURRENT_DATA and need to paint black
+  //   - We're painting to a canvas
+  // See http://crbug.com/341225 http://crbug.com/342621 for details.
+  scoped_refptr<media::VideoFrame> video_frame = compositor_.GetCurrentFrame();
 
   TRACE_EVENT0("media", "WebMediaPlayerImpl:paint");
-  scoped_refptr<media::VideoFrame> video_frame = painter_.GetCurrentFrame(true);
   gfx::Rect gfx_rect(rect);
   skcanvas_video_renderer_.Paint(video_frame.get(), canvas, gfx_rect, alpha);
 }
@@ -568,9 +574,11 @@
 
   media::PipelineStatistics stats = pipeline_.GetStatistics();
 
-  unsigned frames_dropped = stats.video_frames_dropped +
-      const_cast<media::VideoFramePainter*>(&painter_)
-          ->GetFramesDroppedBeforePaint();
+  unsigned frames_dropped = stats.video_frames_dropped;
+
+  frames_dropped += const_cast<VideoFrameCompositor&>(compositor_)
+                        .GetFramesDroppedBeforeCompositorWasNotified();
+
   DCHECK_LE(frames_dropped, stats.video_frames_decoded);
   return frames_dropped;
 }
@@ -589,33 +597,6 @@
   return stats.video_bytes_decoded;
 }
 
-void WebMediaPlayerImpl::SetVideoFrameProviderClient(
-    cc::VideoFrameProvider::Client* client) {
-  // This is called from both the main renderer thread and the compositor
-  // thread (when the main thread is blocked).
-  if (video_frame_provider_client_)
-    video_frame_provider_client_->StopUsingProvider();
-  video_frame_provider_client_ = client;
-}
-
-scoped_refptr<media::VideoFrame> WebMediaPlayerImpl::GetCurrentFrame() {
-  scoped_refptr<media::VideoFrame> current_frame =
-      painter_.GetCurrentFrame(true);
-  TRACE_EVENT_ASYNC_BEGIN0(
-      "media", "WebMediaPlayerImpl:compositing", this);
-  return current_frame;
-}
-
-void WebMediaPlayerImpl::PutCurrentFrame(
-    const scoped_refptr<media::VideoFrame>& frame) {
-  if (!accelerated_compositing_reported_) {
-    accelerated_compositing_reported_ = true;
-    DCHECK(frame_->view()->isAcceleratedCompositingActive());
-    UMA_HISTOGRAM_BOOLEAN("Media.AcceleratedCompositingActive", true);
-  }
-  TRACE_EVENT_ASYNC_END0("media", "WebMediaPlayerImpl:compositing", this);
-}
-
 bool WebMediaPlayerImpl::copyVideoTextureToPlatformTexture(
     blink::WebGraphicsContext3D* web_graphics_context,
     unsigned int texture,
@@ -624,8 +605,7 @@
     unsigned int type,
     bool premultiply_alpha,
     bool flip_y) {
-  scoped_refptr<media::VideoFrame> video_frame =
-      painter_.GetCurrentFrame(false);
+  scoped_refptr<media::VideoFrame> video_frame = compositor_.GetCurrentFrame();
 
   TRACE_EVENT0("media", "WebMediaPlayerImpl:copyVideoTextureToPlatformTexture");
 
@@ -680,9 +660,6 @@
   web_graphics_context->bindTexture(GL_TEXTURE_2D, texture);
 
   web_graphics_context->deleteTexture(source_texture);
-
-  // The flush() operation is not necessary here. It is kept since the
-  // performance will be better when it is added than not.
   web_graphics_context->flush();
   return true;
 }
@@ -768,6 +745,17 @@
   return e;
 }
 
+// Guess the type of |init_data|. This is only used to handle some corner cases
+// so we keep it as simple as possible without breaking major use cases.
+static std::string GuessInitDataType(const unsigned char* init_data,
+                                     unsigned init_data_length) {
+  // Most WebM files use KeyId of 16 bytes. MP4 init data are always >16 bytes.
+  if (init_data_length == 16)
+    return "video/webm";
+
+  return "video/mp4";
+}
+
 WebMediaPlayer::MediaKeyException
 WebMediaPlayerImpl::GenerateKeyRequestInternal(const std::string& key_system,
                                                const unsigned char* init_data,
@@ -804,11 +792,15 @@
     return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
   }
 
+  std::string init_data_type = init_data_type_;
+  if (init_data_type.empty())
+    init_data_type = GuessInitDataType(init_data, init_data_length);
+
   // TODO(xhwang): We assume all streams are from the same container (thus have
   // the same "type") for now. In the future, the "type" should be passed down
   // from the application.
   if (!proxy_decryptor_->GenerateKeyRequest(
-           init_data_type_, init_data, init_data_length)) {
+           init_data_type, init_data, init_data_length)) {
     current_key_system_.clear();
     return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
   }
@@ -912,7 +904,6 @@
   DCHECK(main_loop_->BelongsToCurrentThread());
   TRACE_EVENT0("media", "WebMediaPlayerImpl::InvalidateOnMainThread");
 
-  painter_.DidFinishInvalidating();
   client_->repaint();
 }
 
@@ -968,33 +959,19 @@
   InvalidateOnMainThread();
 }
 
-void WebMediaPlayerImpl::OnPipelineBufferingState(
-    media::Pipeline::BufferingState buffering_state) {
-  DVLOG(1) << "OnPipelineBufferingState(" << buffering_state << ")";
+void WebMediaPlayerImpl::OnPipelineMetadata(
+    media::PipelineMetadata metadata) {
+  DVLOG(1) << "OnPipelineMetadata";
 
-  switch (buffering_state) {
-    case media::Pipeline::kHaveMetadata:
-      // TODO(scherkus): Would be better to have a metadata changed callback
-      // that contained the size information as well whether audio/video is
-      // present. Doing so would let us remove more methods off Pipeline.
-      natural_size_ = pipeline_.GetInitialNaturalSize();
+  pipeline_metadata_ = metadata;
 
-      SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
+  SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
 
-      if (hasVideo() && client_->needsWebLayerForVideo()) {
-        DCHECK(!video_weblayer_);
-        video_weblayer_.reset(
-            new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
-        client_->setWebLayer(video_weblayer_.get());
-      }
-      break;
-    case media::Pipeline::kPrerollCompleted:
-      // Only transition to ReadyStateHaveEnoughData if we don't have
-      // any pending seeks because the transition can cause Blink to
-      // report that the most recent seek has completed.
-      if (!pending_seek_)
-        SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
-      break;
+  if (hasVideo()) {
+    DCHECK(!video_weblayer_);
+    video_weblayer_.reset(new webkit::WebLayerImpl(
+        cc::VideoLayer::Create(compositor_.GetVideoFrameProvider())));
+    client_->setWebLayer(video_weblayer_.get());
   }
 
   // TODO(scherkus): This should be handled by HTMLMediaElement and controls
@@ -1002,6 +979,21 @@
   InvalidateOnMainThread();
 }
 
+void WebMediaPlayerImpl::OnPipelinePrerollCompleted() {
+  DVLOG(1) << "OnPipelinePrerollCompleted";
+
+  // Only transition to ReadyStateHaveEnoughData if we don't have
+  // any pending seeks because the transition can cause Blink to
+  // report that the most recent seek has completed.
+  if (!pending_seek_) {
+    SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
+
+    // TODO(scherkus): This should be handled by HTMLMediaElement and controls
+    // should know when to invalidate themselves http://crbug.com/337015
+    InvalidateOnMainThread();
+  }
+}
+
 void WebMediaPlayerImpl::OnDemuxerOpened() {
   DCHECK(main_loop_->BelongsToCurrentThread());
   client_->mediaSourceOpened(new WebMediaSourceImpl(
@@ -1157,7 +1149,8 @@
     chunk_demuxer_ = new media::ChunkDemuxer(
         BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDemuxerOpened),
         BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnNeedKey),
-        base::Bind(&LogMediaSourceError, media_log_));
+        base::Bind(&LogMediaSourceError, media_log_),
+        false);
     demuxer_.reset(chunk_demuxer_);
   }
 
@@ -1173,11 +1166,12 @@
   audio_decoders.push_back(new media::FFmpegAudioDecoder(media_loop_));
   audio_decoders.push_back(new media::OpusAudioDecoder(media_loop_));
 
-  scoped_ptr<media::AudioRenderer> audio_renderer(
-      new media::AudioRendererImpl(media_loop_,
-                                   audio_source_provider_.get(),
-                                   audio_decoders.Pass(),
-                                   set_decryptor_ready_cb));
+  scoped_ptr<media::AudioRenderer> audio_renderer(new media::AudioRendererImpl(
+      media_loop_,
+      audio_source_provider_.get(),
+      audio_decoders.Pass(),
+      set_decryptor_ready_cb,
+      RenderThreadImpl::current()->GetAudioHardwareConfig()));
   filter_collection->SetAudioRenderer(audio_renderer.Pass());
 
   // Create our video decoders and renderer.
@@ -1220,7 +1214,8 @@
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineEnded),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineError),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineSeek),
-      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineBufferingState),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelineMetadata),
+      BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnPipelinePrerollCompleted),
       BIND_TO_RENDER_LOOP(&WebMediaPlayerImpl::OnDurationChange));
 }
 
@@ -1282,17 +1277,14 @@
 
   media_log_->AddEvent(
       media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
-  natural_size_ = size;
+  pipeline_metadata_.natural_size = size;
 
   client_->sizeChanged();
 }
 
 void WebMediaPlayerImpl::FrameReady(
     const scoped_refptr<media::VideoFrame>& frame) {
-  // TODO(scherkus): Today we always invalidate on the main thread even when
-  // compositing is available, which is less efficient and involves more
-  // thread hops. Refer to http://crbug.com/335345 for details.
-  painter_.UpdateCurrentFrame(frame);
+  compositor_.UpdateCurrentFrame(frame);
 }
 
 void WebMediaPlayerImpl::SetDecryptorReadyCB(
diff --git a/content/renderer/media/webmediaplayer_impl.h b/content/renderer/media/webmediaplayer_impl.h
index 7f765a8..cdbeae9 100644
--- a/content/renderer/media/webmediaplayer_impl.h
+++ b/content/renderer/media/webmediaplayer_impl.h
@@ -13,15 +13,14 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread.h"
-#include "cc/layers/video_frame_provider.h"
 #include "content/renderer/media/crypto/proxy_decryptor.h"
+#include "content/renderer/media/video_frame_compositor.h"
 #include "media/base/audio_renderer_sink.h"
 #include "media/base/decryptor.h"
 #include "media/base/media_keys.h"
 #include "media/base/pipeline.h"
 #include "media/base/text_track.h"
 #include "media/filters/skcanvas_video_renderer.h"
-#include "media/filters/video_frame_painter.h"
 #include "skia/ext/platform_canvas.h"
 #include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
@@ -52,6 +51,7 @@
 
 namespace content {
 class BufferedDataSource;
+class VideoFrameCompositor;
 class WebAudioSourceProviderImpl;
 class WebContentDecryptionModuleImpl;
 class WebMediaPlayerDelegate;
@@ -63,7 +63,6 @@
 // Encrypted Media.
 class WebMediaPlayerImpl
     : public blink::WebMediaPlayer,
-      public cc::VideoFrameProvider,
       public base::SupportsWeakPtr<WebMediaPlayerImpl> {
  public:
   // Constructs a WebMediaPlayer implementation using Chromium's media stack.
@@ -126,13 +125,6 @@
   virtual unsigned audioDecodedByteCount() const;
   virtual unsigned videoDecodedByteCount() const;
 
-  // cc::VideoFrameProvider implementation.
-  virtual void SetVideoFrameProviderClient(
-      cc::VideoFrameProvider::Client* client) OVERRIDE;
-  virtual scoped_refptr<media::VideoFrame> GetCurrentFrame() OVERRIDE;
-  virtual void PutCurrentFrame(const scoped_refptr<media::VideoFrame>& frame)
-      OVERRIDE;
-
   virtual bool copyVideoTextureToPlatformTexture(
       blink::WebGraphicsContext3D* web_graphics_context,
       unsigned int texture,
@@ -174,8 +166,8 @@
   void OnPipelineSeek(media::PipelineStatus status);
   void OnPipelineEnded();
   void OnPipelineError(media::PipelineStatus error);
-  void OnPipelineBufferingState(
-      media::Pipeline::BufferingState buffering_state);
+  void OnPipelineMetadata(media::PipelineMetadata metadata);
+  void OnPipelinePrerollCompleted();
   void OnDemuxerOpened();
   void OnKeyAdded(const std::string& session_id);
   void OnKeyError(const std::string& session_id,
@@ -269,6 +261,9 @@
   // The LoadType passed in the |load_type| parameter of the load() call.
   LoadType load_type_;
 
+  // Cache of metadata for answering hasAudio(), hasVideo(), and naturalSize().
+  media::PipelineMetadata pipeline_metadata_;
+
   // Playback state.
   //
   // TODO(scherkus): we have these because Pipeline favours the simplicity of a
@@ -329,18 +324,13 @@
   std::string init_data_type_;
 
   // Video rendering members.
-  media::VideoFramePainter painter_;
+  VideoFrameCompositor compositor_;
   media::SkCanvasVideoRenderer skcanvas_video_renderer_;
-  gfx::Size natural_size_;
 
   // The compositor layer for displaying the video content when using composited
   // playback.
   scoped_ptr<webkit::WebLayerImpl> video_weblayer_;
 
-  // A pointer back to the compositor to inform it about state changes. This is
-  // not NULL while the compositor is actively using this webmediaplayer.
-  cc::VideoFrameProvider::Client* video_frame_provider_client_;
-
   // Text track objects get a unique index value when they're created.
   int text_track_index_;
 
diff --git a/content/renderer/media/webmediaplayer_ms.cc b/content/renderer/media/webmediaplayer_ms.cc
index c8eb020..9fe9306 100644
--- a/content/renderer/media/webmediaplayer_ms.cc
+++ b/content/renderer/media/webmediaplayer_ms.cc
@@ -19,12 +19,14 @@
 #include "content/renderer/render_frame_impl.h"
 #include "media/base/media_log.h"
 #include "media/base/video_frame.h"
+#include "media/base/video_util.h"
 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
 #include "third_party/WebKit/public/platform/WebRect.h"
 #include "third_party/WebKit/public/platform/WebSize.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebView.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "webkit/renderer/compositor_bindings/web_layer_impl.h"
 
 using blink::WebCanvas;
@@ -32,6 +34,45 @@
 using blink::WebRect;
 using blink::WebSize;
 
+namespace {
+
+// This function copies a YV12 or NATIVE_TEXTURE to a new YV12
+// media::VideoFrame.
+scoped_refptr<media::VideoFrame> CopyFrameToYV12(
+    const scoped_refptr<media::VideoFrame>& frame) {
+  DCHECK(frame->format() == media::VideoFrame::YV12 ||
+         frame->format() == media::VideoFrame::NATIVE_TEXTURE);
+  scoped_refptr<media::VideoFrame> new_frame =
+      media::VideoFrame::CreateFrame(media::VideoFrame::YV12,
+                                     frame->coded_size(),
+                                     frame->visible_rect(),
+                                     frame->natural_size(),
+                                     frame->GetTimestamp());
+
+  if (frame->format() == media::VideoFrame::NATIVE_TEXTURE) {
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(frame->visible_rect().width(),
+                          frame->visible_rect().height());
+    frame->ReadPixelsFromNativeTexture(bitmap);
+
+    media::CopyRGBToVideoFrame(
+        reinterpret_cast<uint8*>(bitmap.getPixels()),
+        bitmap.rowBytes(),
+        frame->visible_rect(),
+        new_frame.get());
+  } else {
+    size_t number_of_planes =
+        media::VideoFrame::NumPlanes(frame->format());
+    for (size_t i = 0; i < number_of_planes; ++i) {
+      media::CopyPlane(i, frame->data(i), frame->stride(i),
+                       frame->rows(i), new_frame.get());
+    }
+  }
+  return new_frame;
+}
+
+}  // anonymous namespace
+
 namespace content {
 
 WebMediaPlayerMS::WebMediaPlayerMS(
@@ -165,6 +206,17 @@
   paused_ = true;
 
   media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
+
+  if (!current_frame_)
+    return;
+
+  // Copy the frame so that rendering can show the last received frame.
+  // The original frame must not be referenced when the player is paused since
+  // there might be a finite number of available buffers. E.g, video that
+  // originates from a video camera.
+  scoped_refptr<media::VideoFrame> new_frame = CopyFrameToYV12(current_frame_);
+  base::AutoLock auto_lock(current_frame_lock_);
+  current_frame_ = new_frame;
 }
 
 bool WebMediaPlayerMS::supportsSave() const {
@@ -229,8 +281,8 @@
 
 double WebMediaPlayerMS::currentTime() const {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (current_frame_.get()) {
-    return current_frame_->GetTimestamp().InSecondsF();
+  if (current_time_.ToInternalValue() != 0) {
+    return current_time_.InSecondsF();
   } else if (audio_renderer_.get()) {
     return audio_renderer_->GetCurrentRenderTime().InSecondsF();
   }
@@ -361,7 +413,7 @@
     SetReadyState(WebMediaPlayer::ReadyStateHaveEnoughData);
     GetClient()->sizeChanged();
 
-    if (video_frame_provider_.get() && GetClient()->needsWebLayerForVideo()) {
+    if (video_frame_provider_) {
       video_weblayer_.reset(
           new webkit::WebLayerImpl(cc::VideoLayer::Create(this)));
       GetClient()->setWebLayer(video_weblayer_.get());
@@ -384,7 +436,7 @@
     if (!current_frame_used_ && current_frame_.get())
       ++dropped_frame_count_;
     current_frame_ = frame;
-    current_frame_->SetTimestamp(frame->GetTimestamp() - start_time_);
+    current_time_ = frame->GetTimestamp() - start_time_;
     current_frame_used_ = false;
   }
 
diff --git a/content/renderer/media/webmediaplayer_ms.h b/content/renderer/media/webmediaplayer_ms.h
index 19d53f2..9ba5aa7 100644
--- a/content/renderer/media/webmediaplayer_ms.h
+++ b/content/renderer/media/webmediaplayer_ms.h
@@ -158,12 +158,15 @@
 
   // |current_frame_| is updated only on main thread. The object it holds
   // can be freed on the compositor thread if it is the last to hold a
-  // reference but media::VideoFrame is a thread-safe ref-pointer.
+  // reference but media::VideoFrame is a thread-safe ref-pointer. It is
+  // however read on the compositing thread so locking is required around all
+  // modifications on the main thread, and all reads on the compositing thread.
   scoped_refptr<media::VideoFrame> current_frame_;
   // |current_frame_used_| is updated on both main and compositing thread.
   // It's used to track whether |current_frame_| was painted for detecting
   // when to increase |dropped_frame_count_|.
   bool current_frame_used_;
+  // |current_frame_lock_| protects |current_frame_used_| and |current_frame_|.
   base::Lock current_frame_lock_;
   bool pending_repaint_;
 
@@ -176,6 +179,7 @@
   bool received_first_frame_;
   bool sequence_started_;
   base::TimeDelta start_time_;
+  base::TimeDelta current_time_;
   unsigned total_frame_count_;
   unsigned dropped_frame_count_;
   media::SkCanvasVideoRenderer video_renderer_;
diff --git a/content/renderer/media/webrtc/OWNERS b/content/renderer/media/webrtc/OWNERS
index dbd443f..7aa733c 100644
--- a/content/renderer/media/webrtc/OWNERS
+++ b/content/renderer/media/webrtc/OWNERS
@@ -2,9 +2,8 @@
 xians@chromium.org
 perkj@chromium.org
 hclam@chromium.org
-joi@chromium.org
 
 # To be able to roll new libjingle releases.
 ronghuawu@chromium.org
 mallinath@chromium.org
-sergeyu@chromium.org
\ No newline at end of file
+sergeyu@chromium.org
diff --git a/content/renderer/media/webrtc/media_stream_track_metrics.cc b/content/renderer/media/webrtc/media_stream_track_metrics.cc
new file mode 100644
index 0000000..29b56cb
--- /dev/null
+++ b/content/renderer/media/webrtc/media_stream_track_metrics.cc
@@ -0,0 +1,336 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc/media_stream_track_metrics.h"
+
+#include <inttypes.h>
+#include <algorithm>
+#include <set>
+#include <string>
+
+#include "base/md5.h"
+#include "content/common/media/media_stream_track_metrics_host_messages.h"
+#include "content/renderer/render_thread_impl.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+
+using webrtc::AudioTrackVector;
+using webrtc::MediaStreamInterface;
+using webrtc::MediaStreamTrackInterface;
+using webrtc::PeerConnectionInterface;
+using webrtc::VideoTrackVector;
+
+namespace content {
+
+class MediaStreamTrackMetricsObserver : public webrtc::ObserverInterface {
+ public:
+  MediaStreamTrackMetricsObserver(
+      MediaStreamTrackMetrics::StreamType stream_type,
+      MediaStreamInterface* stream,
+      MediaStreamTrackMetrics* owner);
+  virtual ~MediaStreamTrackMetricsObserver();
+
+  // Sends begin/end messages for all tracks currently tracked.
+  void SendLifetimeMessages(MediaStreamTrackMetrics::LifetimeEvent event);
+
+  MediaStreamInterface* stream() { return stream_; }
+  MediaStreamTrackMetrics::StreamType stream_type() { return stream_type_; }
+
+ private:
+  typedef std::set<std::string> IdSet;
+
+  // webrtc::ObserverInterface implementation.
+  virtual void OnChanged() OVERRIDE;
+
+  template <class T>
+  IdSet GetTrackIds(const std::vector<talk_base::scoped_refptr<T> >& tracks) {
+    IdSet track_ids;
+    typename std::vector<talk_base::scoped_refptr<T> >::const_iterator it =
+        tracks.begin();
+    for (; it != tracks.end(); ++it) {
+      track_ids.insert((*it)->id());
+    }
+    return track_ids;
+  }
+
+  void ReportAddedAndRemovedTracks(
+      const IdSet& new_ids,
+      const IdSet& old_ids,
+      MediaStreamTrackMetrics::TrackType track_type);
+
+  // Sends a lifetime message for the given tracks. OK to call with an
+  // empty |ids|, in which case the method has no side effects.
+  void ReportTracks(const IdSet& ids,
+                    MediaStreamTrackMetrics::TrackType track_type,
+                    MediaStreamTrackMetrics::LifetimeEvent event);
+
+  // False until start/end of lifetime messages have been sent.
+  bool has_reported_start_;
+  bool has_reported_end_;
+
+  // IDs of audio and video tracks in the stream being observed.
+  IdSet audio_track_ids_;
+  IdSet video_track_ids_;
+
+  MediaStreamTrackMetrics::StreamType stream_type_;
+  talk_base::scoped_refptr<MediaStreamInterface> stream_;
+
+  // Non-owning.
+  MediaStreamTrackMetrics* owner_;
+};
+
+namespace {
+
+// Used with std::find_if.
+struct ObserverFinder {
+  ObserverFinder(MediaStreamTrackMetrics::StreamType stream_type,
+                 MediaStreamInterface* stream)
+      : stream_type(stream_type), stream_(stream) {}
+  bool operator()(MediaStreamTrackMetricsObserver* observer) {
+    return stream_ == observer->stream() &&
+           stream_type == observer->stream_type();
+  }
+  MediaStreamTrackMetrics::StreamType stream_type;
+  MediaStreamInterface* stream_;
+};
+
+}  // namespace
+
+MediaStreamTrackMetricsObserver::MediaStreamTrackMetricsObserver(
+    MediaStreamTrackMetrics::StreamType stream_type,
+    MediaStreamInterface* stream,
+    MediaStreamTrackMetrics* owner)
+    : has_reported_start_(false),
+      has_reported_end_(false),
+      stream_type_(stream_type),
+      stream_(stream),
+      owner_(owner) {
+  OnChanged();  // To populate initial tracks.
+  stream_->RegisterObserver(this);
+}
+
+MediaStreamTrackMetricsObserver::~MediaStreamTrackMetricsObserver() {
+  stream_->UnregisterObserver(this);
+  SendLifetimeMessages(MediaStreamTrackMetrics::DISCONNECTED);
+}
+
+void MediaStreamTrackMetricsObserver::SendLifetimeMessages(
+    MediaStreamTrackMetrics::LifetimeEvent event) {
+  if (event == MediaStreamTrackMetrics::CONNECTED) {
+    // Both ICE CONNECTED and COMPLETED can trigger the first
+    // start-of-life event, so we only report the first.
+    if (has_reported_start_)
+      return;
+    DCHECK(!has_reported_start_ && !has_reported_end_);
+    has_reported_start_ = true;
+  } else {
+    DCHECK(event == MediaStreamTrackMetrics::DISCONNECTED);
+
+    // We only report the first end-of-life event, since there are
+    // several cases where end-of-life can be reached. We also don't
+    // report end unless we've reported start.
+    if (has_reported_end_ || !has_reported_start_)
+      return;
+    has_reported_end_ = true;
+  }
+
+  ReportTracks(audio_track_ids_, MediaStreamTrackMetrics::AUDIO_TRACK, event);
+  ReportTracks(video_track_ids_, MediaStreamTrackMetrics::VIDEO_TRACK, event);
+
+  if (event == MediaStreamTrackMetrics::DISCONNECTED) {
+    // After disconnection, we can get reconnected, so we need to
+    // forget that we've sent lifetime events, while retaining all
+    // other state.
+    DCHECK(has_reported_start_ && has_reported_end_);
+    has_reported_start_ = false;
+    has_reported_end_ = false;
+  }
+}
+
+void MediaStreamTrackMetricsObserver::OnChanged() {
+  AudioTrackVector all_audio_tracks = stream_->GetAudioTracks();
+  IdSet all_audio_track_ids = GetTrackIds(all_audio_tracks);
+
+  VideoTrackVector all_video_tracks = stream_->GetVideoTracks();
+  IdSet all_video_track_ids = GetTrackIds(all_video_tracks);
+
+  // We only report changes after our initial report, and never after
+  // our last report.
+  if (has_reported_start_ && !has_reported_end_) {
+    ReportAddedAndRemovedTracks(all_audio_track_ids,
+                                audio_track_ids_,
+                                MediaStreamTrackMetrics::AUDIO_TRACK);
+    ReportAddedAndRemovedTracks(all_video_track_ids,
+                                video_track_ids_,
+                                MediaStreamTrackMetrics::VIDEO_TRACK);
+  }
+
+  // We always update our sets of tracks.
+  audio_track_ids_ = all_audio_track_ids;
+  video_track_ids_ = all_video_track_ids;
+}
+
+void MediaStreamTrackMetricsObserver::ReportAddedAndRemovedTracks(
+    const IdSet& new_ids,
+    const IdSet& old_ids,
+    MediaStreamTrackMetrics::TrackType track_type) {
+  DCHECK(has_reported_start_ && !has_reported_end_);
+
+  IdSet added_tracks;
+  std::set_difference(new_ids.begin(),
+                      new_ids.end(),
+                      old_ids.begin(),
+                      old_ids.end(),
+                      std::inserter(added_tracks, added_tracks.end()));
+
+  IdSet removed_tracks;
+  std::set_difference(old_ids.begin(),
+                      old_ids.end(),
+                      new_ids.begin(),
+                      new_ids.end(),
+                      std::inserter(removed_tracks, removed_tracks.end()));
+
+  ReportTracks(added_tracks, track_type, MediaStreamTrackMetrics::CONNECTED);
+  ReportTracks(
+      removed_tracks, track_type, MediaStreamTrackMetrics::DISCONNECTED);
+}
+
+void MediaStreamTrackMetricsObserver::ReportTracks(
+    const IdSet& ids,
+    MediaStreamTrackMetrics::TrackType track_type,
+    MediaStreamTrackMetrics::LifetimeEvent event) {
+  for (IdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
+    owner_->SendLifetimeMessage(*it, track_type, event, stream_type_);
+  }
+}
+
+MediaStreamTrackMetrics::MediaStreamTrackMetrics() {}
+
+MediaStreamTrackMetrics::~MediaStreamTrackMetrics() {
+  for (ObserverVector::iterator it = observers_.begin(); it != observers_.end();
+       ++it) {
+    (*it)->SendLifetimeMessages(DISCONNECTED);
+  }
+}
+
+void MediaStreamTrackMetrics::AddStream(StreamType type,
+                                        MediaStreamInterface* stream) {
+  DCHECK(CalledOnValidThread());
+  observers_.insert(observers_.end(),
+                    new MediaStreamTrackMetricsObserver(type, stream, this));
+}
+
+void MediaStreamTrackMetrics::RemoveStream(StreamType type,
+                                           MediaStreamInterface* stream) {
+  DCHECK(CalledOnValidThread());
+  ObserverVector::iterator it = std::find_if(
+      observers_.begin(), observers_.end(), ObserverFinder(type, stream));
+  if (it == observers_.end()) {
+    // Since external apps could call removeStream with a stream they
+    // never added, this can happen without it being an error.
+    return;
+  }
+
+  observers_.erase(it);
+}
+
+void MediaStreamTrackMetrics::IceConnectionChange(
+    PeerConnectionInterface::IceConnectionState new_state) {
+  DCHECK(CalledOnValidThread());
+  for (ObserverVector::iterator it = observers_.begin(); it != observers_.end();
+       ++it) {
+    // There is a state transition diagram for these states at
+    // http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCIceConnectionState
+    switch (new_state) {
+      case PeerConnectionInterface::kIceConnectionConnected:
+      case PeerConnectionInterface::kIceConnectionCompleted:
+        (*it)->SendLifetimeMessages(CONNECTED);
+        break;
+
+      case PeerConnectionInterface::kIceConnectionFailed:
+        // We don't really need to handle FAILED (it is only supposed
+        // to be preceded by CHECKING so we wouldn't yet have sent a
+        // lifetime message) but we might as well use belt and
+        // suspenders and handle it the same as the other "end call"
+        // states. It will be ignored anyway if the call is not
+        // already connected.
+      case PeerConnectionInterface::kIceConnectionNew:
+        // It's a bit weird to count NEW as an end-lifetime event, but
+        // it's possible to transition directly from a connected state
+        // (CONNECTED or COMPLETED) to NEW, which can then be followed
+        // by a new connection. The observer will ignore the end
+        // lifetime event if it was not preceded by a begin-lifetime
+        // event.
+      case PeerConnectionInterface::kIceConnectionDisconnected:
+      case PeerConnectionInterface::kIceConnectionClosed:
+        (*it)->SendLifetimeMessages(DISCONNECTED);
+        break;
+
+      default:
+        // We ignore the remaining state (CHECKING) as it is never
+        // involved in a transition from connected to disconnected or
+        // vice versa.
+        break;
+    }
+  }
+}
+
+void MediaStreamTrackMetrics::SendLifetimeMessage(const std::string& track_id,
+                                                  TrackType track_type,
+                                                  LifetimeEvent event,
+                                                  StreamType stream_type) {
+  RenderThreadImpl* render_thread = RenderThreadImpl::current();
+  // |render_thread| can be NULL in certain cases when running as part
+  // |of a unit test.
+  if (render_thread) {
+    if (event == CONNECTED) {
+      RenderThreadImpl::current()->Send(
+          new MediaStreamTrackMetricsHost_AddTrack(
+              MakeUniqueId(track_id, stream_type),
+              track_type == AUDIO_TRACK,
+              stream_type == RECEIVED_STREAM));
+    } else {
+      DCHECK_EQ(DISCONNECTED, event);
+      RenderThreadImpl::current()->Send(
+          new MediaStreamTrackMetricsHost_RemoveTrack(
+              MakeUniqueId(track_id, stream_type)));
+    }
+  }
+}
+
+uint64 MediaStreamTrackMetrics::MakeUniqueIdImpl(uint64 pc_id,
+                                                 const std::string& track_id,
+                                                 StreamType stream_type) {
+  // We use a hash over the |track| pointer and the PeerConnection ID,
+  // plus a boolean flag indicating whether the track is remote (since
+  // you might conceivably have a remote track added back as a sent
+  // track) as the unique ID.
+  //
+  // We don't need a cryptographically secure hash (which MD5 should
+  // no longer be considered), just one with virtually zero chance of
+  // collisions when faced with non-malicious data.
+  std::string unique_id_string =
+      base::StringPrintf("%" PRIu64 " %s %d",
+                         pc_id,
+                         track_id.c_str(),
+                         stream_type == RECEIVED_STREAM ? 1 : 0);
+
+  base::MD5Context ctx;
+  base::MD5Init(&ctx);
+  base::MD5Update(&ctx, unique_id_string);
+  base::MD5Digest digest;
+  base::MD5Final(&digest, &ctx);
+
+  COMPILE_ASSERT(sizeof(digest.a) > sizeof(uint64), NeedBiggerDigest);
+  return *reinterpret_cast<uint64*>(digest.a);
+}
+
+uint64 MediaStreamTrackMetrics::MakeUniqueId(const std::string& track_id,
+                                             StreamType stream_type) {
+  return MakeUniqueIdImpl(
+      reinterpret_cast<uint64>(reinterpret_cast<void*>(this)),
+      track_id,
+      stream_type);
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc/media_stream_track_metrics.h b/content/renderer/media/webrtc/media_stream_track_metrics.h
new file mode 100644
index 0000000..79709b0
--- /dev/null
+++ b/content/renderer/media/webrtc/media_stream_track_metrics.h
@@ -0,0 +1,95 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_TRACK_METRICS_H_
+#define CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_TRACK_METRICS_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_vector.h"
+#include "base/threading/non_thread_safe.h"
+#include "content/common/content_export.h"
+#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+
+namespace webrtc {
+class MediaStreamInterface;
+class MediaStreamTrackInterface;
+}
+
+namespace content {
+
+class MediaStreamTrackMetricsObserver;
+class RTCPeerConnectionHandler;
+
+// Responsible for observing the connected lifetimes of tracks going
+// over a PeerConnection, and sending messages to the browser process
+// about lifetime events.
+//
+// There should be exactly one of these objects owned by each
+// RTCPeerConnectionHandler, and its lifetime should match the
+// lifetime of its owner.
+class CONTENT_EXPORT MediaStreamTrackMetrics : public base::NonThreadSafe {
+ public:
+  explicit MediaStreamTrackMetrics();
+  ~MediaStreamTrackMetrics();
+
+  enum StreamType { SENT_STREAM, RECEIVED_STREAM };
+
+  enum TrackType { AUDIO_TRACK, VIDEO_TRACK };
+
+  enum LifetimeEvent { CONNECTED, DISCONNECTED };
+
+  // Starts tracking lifetimes of all the tracks in |stream| and any
+  // tracks added or removed to/from the stream until |RemoveStream|
+  // is called or this object's lifetime ends.
+  void AddStream(StreamType type, webrtc::MediaStreamInterface* stream);
+
+  // Stops tracking lifetimes of tracks in |stream|.
+  void RemoveStream(StreamType type, webrtc::MediaStreamInterface* stream);
+
+  // Called to indicate changes in the ICE connection state for the
+  // PeerConnection this object is associated with. Used to generate
+  // the connected/disconnected lifetime events for these tracks.
+  void IceConnectionChange(
+      webrtc::PeerConnectionInterface::IceConnectionState new_state);
+
+  // Send a lifetime message to the browser process. Virtual so that
+  // it can be overridden in unit tests.
+  //
+  // |track_id| is the ID of the track that just got connected or
+  // disconnected.
+  //
+  // |is_audio| is true for an audio track, false for a video track.
+  //
+  // |start_lifetime| is true to indicate that it just got connected,
+  // false to indicate it is no longer connected.
+  //
+  // |is_remote| is true for remote streams (received over a
+  // PeerConnection), false for local streams (sent over a
+  // PeerConnection).
+  virtual void SendLifetimeMessage(const std::string& track_id,
+                                   TrackType track_type,
+                                   LifetimeEvent lifetime_event,
+                                   StreamType stream_type);
+
+ protected:
+  // Implements MakeUniqueId. |pc_id| is a cast of this object's
+  // |this| pointer to a 64-bit integer, which is usable as a unique
+  // ID for the PeerConnection this object is attached to (since there
+  // is a one-to-one relationship).
+  uint64 MakeUniqueIdImpl(uint64 pc_id,
+                          const std::string& track,
+                          StreamType stream_type);
+
+ private:
+  // Make a unique ID for the given track, that is valid while the
+  // track object and the PeerConnection it is attached to both exist.
+  uint64 MakeUniqueId(const std::string& track, StreamType stream_type);
+
+  typedef ScopedVector<MediaStreamTrackMetricsObserver> ObserverVector;
+  ObserverVector observers_;
+};
+
+}  // namespace
+
+#endif  // CONTENT_RENDERER_MEDIA_WEBRTC_MEDIA_STREAM_TRACK_METRICS_H_
diff --git a/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc b/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
new file mode 100644
index 0000000..9aa76f6
--- /dev/null
+++ b/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
@@ -0,0 +1,499 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/mock_media_stream_dependency_factory.h"
+#include "content/renderer/media/webrtc/media_stream_track_metrics.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+
+using webrtc::AudioSourceInterface;
+using webrtc::AudioTrackInterface;
+using webrtc::AudioTrackSinkInterface;
+using webrtc::MediaStreamInterface;
+using webrtc::ObserverInterface;
+using webrtc::PeerConnectionInterface;
+using webrtc::VideoRendererInterface;
+using webrtc::VideoSourceInterface;
+using webrtc::VideoTrackInterface;
+
+namespace content {
+
+// A very simple mock that implements only the id() method.
+class MockAudioTrackInterface : public AudioTrackInterface {
+ public:
+  explicit MockAudioTrackInterface(const std::string& id) : id_(id) {}
+  virtual ~MockAudioTrackInterface() {}
+
+  virtual std::string id() const OVERRIDE { return id_; }
+
+  MOCK_METHOD1(RegisterObserver, void(ObserverInterface*));
+  MOCK_METHOD1(UnregisterObserver, void(ObserverInterface*));
+  MOCK_CONST_METHOD0(kind, std::string());
+  MOCK_CONST_METHOD0(enabled, bool());
+  MOCK_CONST_METHOD0(state, TrackState());
+  MOCK_METHOD1(set_enabled, bool(bool));
+  MOCK_METHOD1(set_state, bool(TrackState));
+  MOCK_CONST_METHOD0(GetSource, AudioSourceInterface*());
+  MOCK_METHOD1(AddSink, void(AudioTrackSinkInterface*));
+  MOCK_METHOD1(RemoveSink, void(AudioTrackSinkInterface*));
+
+ private:
+  std::string id_;
+};
+
+// A very simple mock that implements only the id() method.
+class MockVideoTrackInterface : public VideoTrackInterface {
+ public:
+  explicit MockVideoTrackInterface(const std::string& id) : id_(id) {}
+  virtual ~MockVideoTrackInterface() {}
+
+  virtual std::string id() const OVERRIDE { return id_; }
+
+  MOCK_METHOD1(RegisterObserver, void(ObserverInterface*));
+  MOCK_METHOD1(UnregisterObserver, void(ObserverInterface*));
+  MOCK_CONST_METHOD0(kind, std::string());
+  MOCK_CONST_METHOD0(enabled, bool());
+  MOCK_CONST_METHOD0(state, TrackState());
+  MOCK_METHOD1(set_enabled, bool(bool));
+  MOCK_METHOD1(set_state, bool(TrackState));
+  MOCK_METHOD1(AddRenderer, void(VideoRendererInterface*));
+  MOCK_METHOD1(RemoveRenderer, void(VideoRendererInterface*));
+  MOCK_CONST_METHOD0(GetSource, VideoSourceInterface*());
+
+ private:
+  std::string id_;
+};
+
+class MockMediaStreamTrackMetrics : public MediaStreamTrackMetrics {
+ public:
+  virtual ~MockMediaStreamTrackMetrics() {}
+
+  MOCK_METHOD4(SendLifetimeMessage,
+               void(const std::string&, TrackType, LifetimeEvent, StreamType));
+
+  using MediaStreamTrackMetrics::MakeUniqueIdImpl;
+};
+
+class MediaStreamTrackMetricsTest : public testing::Test {
+ public:
+  virtual void SetUp() OVERRIDE {
+    metrics_.reset(new MockMediaStreamTrackMetrics());
+    stream_ = new talk_base::RefCountedObject<MockMediaStream>("stream");
+  }
+
+  virtual void TearDown() OVERRIDE {
+    metrics_.reset();
+    stream_ = NULL;
+  }
+
+  scoped_refptr<MockAudioTrackInterface> MakeAudioTrack(std::string id) {
+    return new talk_base::RefCountedObject<MockAudioTrackInterface>(id);
+  }
+
+  scoped_refptr<MockVideoTrackInterface> MakeVideoTrack(std::string id) {
+    return new talk_base::RefCountedObject<MockVideoTrackInterface>(id);
+  }
+
+  scoped_ptr<MockMediaStreamTrackMetrics> metrics_;
+  scoped_refptr<MediaStreamInterface> stream_;
+};
+
+TEST_F(MediaStreamTrackMetricsTest, MakeUniqueId) {
+  // The important testable properties of the unique ID are that it
+  // should differ when any of the three constituents differ
+  // (PeerConnection pointer, track ID, remote or not. Also, testing
+  // that the implementation does not discard the upper 32 bits of the
+  // PeerConnection pointer is important.
+  //
+  // The important hard-to-test property is that the ID be generated
+  // using a hash function with virtually zero chance of
+  // collisions. We don't test this, we rely on MD5 having this
+  // property.
+
+  // Lower 32 bits the same, upper 32 differ.
+  EXPECT_NE(
+      metrics_->MakeUniqueIdImpl(
+          0x1000000000000001, "x", MediaStreamTrackMetrics::RECEIVED_STREAM),
+      metrics_->MakeUniqueIdImpl(
+          0x2000000000000001, "x", MediaStreamTrackMetrics::RECEIVED_STREAM));
+
+  // Track ID differs.
+  EXPECT_NE(metrics_->MakeUniqueIdImpl(
+                42, "x", MediaStreamTrackMetrics::RECEIVED_STREAM),
+            metrics_->MakeUniqueIdImpl(
+                42, "y", MediaStreamTrackMetrics::RECEIVED_STREAM));
+
+  // Remove vs. local track differs.
+  EXPECT_NE(metrics_->MakeUniqueIdImpl(
+                42, "x", MediaStreamTrackMetrics::RECEIVED_STREAM),
+            metrics_->MakeUniqueIdImpl(
+                42, "x", MediaStreamTrackMetrics::SENT_STREAM));
+}
+
+TEST_F(MediaStreamTrackMetricsTest, BasicRemoteStreams) {
+  scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
+  scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
+  stream_->AddTrack(audio);
+  stream_->AddTrack(video);
+  metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionDisconnected);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, BasicLocalStreams) {
+  scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
+  scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
+  stream_->AddTrack(audio);
+  stream_->AddTrack(video);
+  metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, RemoteStreamTrackAdded) {
+  scoped_refptr<MockAudioTrackInterface> initial(MakeAudioTrack("initial"));
+  scoped_refptr<MockAudioTrackInterface> added(MakeAudioTrack("added"));
+  stream_->AddTrack(initial);
+  metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("initial",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("added",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  stream_->AddTrack(added);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("initial",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("added",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, LocalStreamTrackRemoved) {
+  scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first"));
+  scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second"));
+  stream_->AddTrack(first);
+  stream_->AddTrack(second);
+  metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("first",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("second",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("first",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->RemoveTrack(first);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("second",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, LocalStreamModificationsBeforeAndAfter) {
+  scoped_refptr<MockAudioTrackInterface> first(MakeAudioTrack("first"));
+  scoped_refptr<MockAudioTrackInterface> second(MakeAudioTrack("second"));
+  stream_->AddTrack(first);
+  metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+
+  // This gets added after we start observing, but no lifetime message
+  // should be sent at this point since the call is not connected. It
+  // should get sent only once it gets connected.
+  stream_->AddTrack(second);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("first",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("second",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("first",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("second",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed);
+
+  // This happens after the call is disconnected so no lifetime
+  // message should be sent.
+  stream_->RemoveTrack(first);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, RemoteStreamMultipleDisconnects) {
+  scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
+  stream_->AddTrack(audio);
+  metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::RECEIVED_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionDisconnected);
+  metrics_->IceConnectionChange(PeerConnectionInterface::kIceConnectionFailed);
+  stream_->RemoveTrack(audio);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, RemoteStreamConnectDisconnectTwice) {
+  scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
+  stream_->AddTrack(audio);
+  metrics_->AddStream(MediaStreamTrackMetrics::RECEIVED_STREAM, stream_);
+
+  for (size_t i = 0; i < 2; ++i) {
+    EXPECT_CALL(*metrics_,
+                SendLifetimeMessage("audio",
+                                    MediaStreamTrackMetrics::AUDIO_TRACK,
+                                    MediaStreamTrackMetrics::CONNECTED,
+                                    MediaStreamTrackMetrics::RECEIVED_STREAM));
+    metrics_->IceConnectionChange(
+        PeerConnectionInterface::kIceConnectionConnected);
+
+    EXPECT_CALL(*metrics_,
+                SendLifetimeMessage("audio",
+                                    MediaStreamTrackMetrics::AUDIO_TRACK,
+                                    MediaStreamTrackMetrics::DISCONNECTED,
+                                    MediaStreamTrackMetrics::RECEIVED_STREAM));
+    metrics_->IceConnectionChange(
+        PeerConnectionInterface::kIceConnectionDisconnected);
+  }
+
+  stream_->RemoveTrack(audio);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, LocalStreamRemovedNoDisconnect) {
+  scoped_refptr<MockAudioTrackInterface> audio(MakeAudioTrack("audio"));
+  scoped_refptr<MockVideoTrackInterface> video(MakeVideoTrack("video"));
+  stream_->AddTrack(audio);
+  stream_->AddTrack(video);
+  metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+}
+
+TEST_F(MediaStreamTrackMetricsTest, LocalStreamLargerTest) {
+  scoped_refptr<MockAudioTrackInterface> audio1(MakeAudioTrack("audio1"));
+  scoped_refptr<MockAudioTrackInterface> audio2(MakeAudioTrack("audio2"));
+  scoped_refptr<MockAudioTrackInterface> audio3(MakeAudioTrack("audio3"));
+  scoped_refptr<MockVideoTrackInterface> video1(MakeVideoTrack("video1"));
+  scoped_refptr<MockVideoTrackInterface> video2(MakeVideoTrack("video2"));
+  scoped_refptr<MockVideoTrackInterface> video3(MakeVideoTrack("video3"));
+  stream_->AddTrack(audio1);
+  stream_->AddTrack(video1);
+  metrics_->AddStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio1",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video1",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->IceConnectionChange(
+      PeerConnectionInterface::kIceConnectionConnected);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio2",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->AddTrack(audio2);
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video2",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->AddTrack(video2);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio1",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->RemoveTrack(audio1);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio3",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->AddTrack(audio3);
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video3",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->AddTrack(video3);
+
+  // Add back audio1
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio1",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::CONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->AddTrack(audio1);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio2",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->RemoveTrack(audio2);
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video2",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->RemoveTrack(video2);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio1",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->RemoveTrack(audio1);
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video1",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  stream_->RemoveTrack(video1);
+
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("audio3",
+                                  MediaStreamTrackMetrics::AUDIO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  EXPECT_CALL(*metrics_,
+              SendLifetimeMessage("video3",
+                                  MediaStreamTrackMetrics::VIDEO_TRACK,
+                                  MediaStreamTrackMetrics::DISCONNECTED,
+                                  MediaStreamTrackMetrics::SENT_STREAM));
+  metrics_->RemoveStream(MediaStreamTrackMetrics::SENT_STREAM, stream_);
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc_logging.cc b/content/renderer/media/webrtc_logging.cc
index 2bdc7a3..29cf5f5 100644
--- a/content/renderer/media/webrtc_logging.cc
+++ b/content/renderer/media/webrtc_logging.cc
@@ -4,6 +4,10 @@
 
 #include "content/renderer/media/webrtc_logging.h"
 
+#include <iomanip>
+#include <sstream>
+
+#include "base/time/time.h"
 #include "content/public/renderer/webrtc_log_message_delegate.h"
 #include "third_party/libjingle/overrides/talk/base/logging.h"
 
@@ -11,21 +15,44 @@
 
 // Shall only be set once and never go back to NULL.
 WebRtcLogMessageDelegate* g_webrtc_logging_delegate = NULL;
+uint64 g_started_time_ms_ = 0;
 
 void InitWebRtcLoggingDelegate(WebRtcLogMessageDelegate* delegate) {
   CHECK(!g_webrtc_logging_delegate);
   CHECK(delegate);
 
   g_webrtc_logging_delegate = delegate;
+
+  g_started_time_ms_ = base::Time::Now().ToInternalValue() /
+      base::Time::kMicrosecondsPerMillisecond;
+}
+
+void WebRtcLogMessageWithTimestamp(const std::string& message) {
+  if (g_webrtc_logging_delegate)
+    g_webrtc_logging_delegate->LogMessage(message);
 }
 
 void InitWebRtcLogging() {
-  talk_base::InitDiagnosticLoggingDelegateFunction(WebRtcLogMessage);
+  // Log messages from Libjingle should always have timestamps.
+  talk_base::InitDiagnosticLoggingDelegateFunction(
+      WebRtcLogMessageWithTimestamp);
 }
 
 void WebRtcLogMessage(const std::string& message) {
-  if (g_webrtc_logging_delegate)
-    g_webrtc_logging_delegate->LogMessage(message);
+  // Keep consistent with talk_base::DiagnosticLogMessage::CreateTimestamp.
+  // TODO(grunell): remove the duplicated code and unify the timestamp creation.
+  uint64 now_us = base::Time::Now().ToInternalValue();
+  uint64 interval_ms = now_us / base::Time::kMicrosecondsPerMillisecond -
+      g_started_time_ms_;
+
+  std::ostringstream message_oss;
+  message_oss << "[" << std::setfill('0') << std::setw(3)
+              << (interval_ms / 1000)
+              << ":" << std::setw(3)
+              << (interval_ms % 1000)
+              << std::setfill(' ') << "] " << message;
+
+  WebRtcLogMessageWithTimestamp(message_oss.str());
 }
 
 }  // namespace content
diff --git a/content/renderer/media/webrtc_uma_histograms.cc b/content/renderer/media/webrtc_uma_histograms.cc
new file mode 100644
index 0000000..16da393
--- /dev/null
+++ b/content/renderer/media/webrtc_uma_histograms.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc_uma_histograms.h"
+
+#include "base/metrics/histogram.h"
+
+namespace content {
+
+void UpdateWebRTCMethodCount(JavaScriptAPIName api_name) {
+  DVLOG(3) << "Incrementing WebRTC.webkitApiCount for " << api_name;
+  UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCount", api_name, INVALID_NAME);
+  PerSessionWebRTCAPIMetrics::GetInstance()->LogUsageOnlyOnce(api_name);
+}
+
+PerSessionWebRTCAPIMetrics::~PerSessionWebRTCAPIMetrics() {
+}
+
+// static
+PerSessionWebRTCAPIMetrics* PerSessionWebRTCAPIMetrics::GetInstance() {
+  return Singleton<PerSessionWebRTCAPIMetrics>::get();
+}
+
+void PerSessionWebRTCAPIMetrics::IncrementStreamCounter() {
+  DCHECK(CalledOnValidThread());
+  ++num_streams_;
+}
+
+void PerSessionWebRTCAPIMetrics::DecrementStreamCounter() {
+  DCHECK(CalledOnValidThread());
+  if (--num_streams_ == 0) {
+    ResetUsage();
+  }
+}
+
+PerSessionWebRTCAPIMetrics::PerSessionWebRTCAPIMetrics() : num_streams_(0) {
+  ResetUsage();
+}
+
+void PerSessionWebRTCAPIMetrics::LogUsage(JavaScriptAPIName api_name) {
+  DVLOG(3) << "Incrementing WebRTC.webkitApiCountPerSession for " << api_name;
+  UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCountPerSession",
+                            api_name, INVALID_NAME);
+}
+
+void PerSessionWebRTCAPIMetrics::LogUsageOnlyOnce(JavaScriptAPIName api_name) {
+  DCHECK(CalledOnValidThread());
+  if (!has_used_api_[api_name]) {
+    has_used_api_[api_name] = true;
+    LogUsage(api_name);
+  }
+}
+
+void PerSessionWebRTCAPIMetrics::ResetUsage() {
+  for (size_t i = 0; i < arraysize(has_used_api_); ++i)
+    has_used_api_[i] = false;
+}
+
+}  // namespace content
diff --git a/content/renderer/media/webrtc_uma_histograms.h b/content/renderer/media/webrtc_uma_histograms.h
index de358f4..453e1c6 100644
--- a/content/renderer/media/webrtc_uma_histograms.h
+++ b/content/renderer/media/webrtc_uma_histograms.h
@@ -5,7 +5,9 @@
 #ifndef CONTENT_RENDERER_MEDIA_WEBRTC_UMA_HISTOGRAMS_H_
 #define CONTENT_RENDERER_MEDIA_WEBRTC_UMA_HISTOGRAMS_H_
 
-#include "base/metrics/histogram.h"
+#include "base/memory/singleton.h"
+#include "base/threading/non_thread_safe.h"
+#include "content/common/content_export.h"
 
 namespace content {
 
@@ -19,11 +21,61 @@
 };
 
 // Helper method used to collect information about the number of times
-// different WebRTC API:s are called from JavaScript.
-// The histogram can be viewed at chrome://histograms/WebRTC.webkitApiCount.
-inline void UpdateWebRTCMethodCount(JavaScriptAPIName api_name) {
-  UMA_HISTOGRAM_ENUMERATION("WebRTC.webkitApiCount", api_name, INVALID_NAME);
-}
+// different WebRTC APIs are called from JavaScript.
+//
+// This contributes to two histograms; the former is a raw count of
+// the number of times the APIs are called, and be viewed at
+// chrome://histograms/WebRTC.webkitApiCount.
+//
+// The latter is a count of the number of times the APIs are called
+// that gets incremented only once per "session" as established by the
+// PerSessionWebRTCAPIMetrics singleton below. It can be viewed at
+// chrome://histograms/WebRTC.webkitApiCountPerSession.
+void UpdateWebRTCMethodCount(JavaScriptAPIName api_name);
+
+// A singleton that keeps track of the number of MediaStreams being
+// sent over PeerConnections. It uses the transition to zero such
+// streams to demarcate the start of a new "session". Note that this
+// is a rough approximation of sessions, as you could conceivably have
+// multiple tabs using this renderer process, and each of them using
+// PeerConnections.
+//
+// The UpdateWebRTCMethodCount function above uses this class to log a
+// metric at most once per session.
+class CONTENT_EXPORT PerSessionWebRTCAPIMetrics : public base::NonThreadSafe {
+ public:
+  virtual ~PerSessionWebRTCAPIMetrics();
+
+  static PerSessionWebRTCAPIMetrics* GetInstance();
+
+  // Increment/decrement the number of streams being sent or received
+  // over any current PeerConnection.
+  void IncrementStreamCounter();
+  void DecrementStreamCounter();
+
+ protected:
+  friend struct DefaultSingletonTraits<PerSessionWebRTCAPIMetrics>;
+  friend void UpdateWebRTCMethodCount(JavaScriptAPIName);
+
+  // Protected so that unit tests can test without this being a
+  // singleton.
+  PerSessionWebRTCAPIMetrics();
+
+  // Overridable by unit tests.
+  virtual void LogUsage(JavaScriptAPIName api_name);
+
+  // Called by UpdateWebRTCMethodCount above. Protected rather than
+  // private so that unit tests can call it.
+  void LogUsageOnlyOnce(JavaScriptAPIName api_name);
+
+ private:
+  void ResetUsage();
+
+  int num_streams_;
+  bool has_used_api_[INVALID_NAME];
+
+  DISALLOW_COPY_AND_ASSIGN(PerSessionWebRTCAPIMetrics);
+};
 
 } //  namespace content
 
diff --git a/content/renderer/media/webrtc_uma_histograms_unittest.cc b/content/renderer/media/webrtc_uma_histograms_unittest.cc
new file mode 100644
index 0000000..7d3a919
--- /dev/null
+++ b/content/renderer/media/webrtc_uma_histograms_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/webrtc_uma_histograms.h"
+
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using ::testing::_;
+
+namespace content {
+
+class MockPerSessionWebRTCAPIMetrics : public PerSessionWebRTCAPIMetrics {
+ public:
+  MockPerSessionWebRTCAPIMetrics() {}
+
+  using PerSessionWebRTCAPIMetrics::LogUsageOnlyOnce;
+
+  MOCK_METHOD1(LogUsage, void(JavaScriptAPIName));
+};
+
+TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingGetUserMedia) {
+  MockPerSessionWebRTCAPIMetrics metrics;
+  EXPECT_CALL(metrics, LogUsage(_)).Times(1);
+  metrics.LogUsageOnlyOnce(WEBKIT_GET_USER_MEDIA);
+}
+
+TEST(PerSessionWebRTCAPIMetrics, CallOngoingGetUserMedia) {
+  MockPerSessionWebRTCAPIMetrics metrics;
+  metrics.IncrementStreamCounter();
+  EXPECT_CALL(metrics, LogUsage(WEBKIT_GET_USER_MEDIA)).Times(1);
+  metrics.LogUsageOnlyOnce(WEBKIT_GET_USER_MEDIA);
+}
+
+TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingRTCPeerConnection) {
+  MockPerSessionWebRTCAPIMetrics metrics;
+  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION));
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+}
+
+TEST(PerSessionWebRTCAPIMetrics, NoCallOngoingMultiplePC) {
+  MockPerSessionWebRTCAPIMetrics metrics;
+  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION)).Times(1);
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+}
+
+TEST(PerSessionWebRTCAPIMetrics, BeforeAfterCallMultiplePC) {
+  MockPerSessionWebRTCAPIMetrics metrics;
+  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION)).Times(1);
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.IncrementStreamCounter();
+  metrics.IncrementStreamCounter();
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.DecrementStreamCounter();
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.DecrementStreamCounter();
+  EXPECT_CALL(metrics, LogUsage(WEBKIT_RTC_PEER_CONNECTION)).Times(1);
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+  metrics.LogUsageOnlyOnce(WEBKIT_RTC_PEER_CONNECTION);
+}
+
+}  // namespace content
diff --git a/content/renderer/mojo/mojo_render_process_observer.cc b/content/renderer/mojo/mojo_render_process_observer.cc
index f72e398..7f01d3f 100644
--- a/content/renderer/mojo/mojo_render_process_observer.cc
+++ b/content/renderer/mojo/mojo_render_process_observer.cc
@@ -9,6 +9,8 @@
 #include "content/common/mojo/mojo_channel_init.h"
 #include "content/common/mojo/mojo_messages.h"
 #include "content/public/renderer/render_thread.h"
+#include "content/public/renderer/render_view.h"
+#include "content/renderer/web_ui_mojo.h"
 
 namespace content {
 
@@ -46,6 +48,25 @@
   DCHECK(!channel_init_.get());
   channel_init_.reset(new MojoChannelInit);
   channel_init_->Init(handle, ChildProcess::current()->io_message_loop_proxy());
+  if (!channel_init_->is_handle_valid())
+    return;
+
+  ScopedRenderProcessHostMojoHandle render_process_host_handle(
+      RenderProcessHostMojoHandle(
+          channel_init_->bootstrap_message_pipe().release().value()));
+  render_process_host_mojo_.reset(render_process_host_handle.Pass(), this);
+}
+
+void MojoRenderProcessObserver::SetWebUIHandle(
+    int32 view_routing_id,
+    mojo::ScopedMessagePipeHandle web_ui_handle) {
+  RenderView* render_view = RenderView::FromRoutingID(view_routing_id);
+  if (!render_view)
+    return;
+  WebUIMojo* web_ui_mojo = WebUIMojo::Get(render_view);
+  if (!web_ui_mojo)
+    return;
+  web_ui_mojo->SetBrowserHandle(web_ui_handle.Pass());
 }
 
 }  // namespace content
diff --git a/content/renderer/mojo/mojo_render_process_observer.h b/content/renderer/mojo/mojo_render_process_observer.h
index 95f1b70..c3649c5 100644
--- a/content/renderer/mojo/mojo_render_process_observer.h
+++ b/content/renderer/mojo/mojo_render_process_observer.h
@@ -6,8 +6,10 @@
 #define CONTENT_RENDERER_MOJO_MOJO_RENDER_PROCESS_OBSERVER_H_
 
 #include "base/memory/scoped_ptr.h"
+#include "content/common/mojo/render_process.mojom.h"
 #include "content/public/renderer/render_process_observer.h"
 #include "ipc/ipc_platform_file.h"
+#include "mojo/public/bindings/remote_ptr.h"
 
 namespace mojo {
 namespace embedder{
@@ -23,7 +25,9 @@
 // RenderProcessObserver implementation that initializes the mojo channel when
 // the right IPC is seen.
 // MojoRenderProcessObserver deletes itself when the RenderProcess is shutdown.
-class MojoRenderProcessObserver : public content::RenderProcessObserver {
+class MojoRenderProcessObserver
+    : public content::RenderProcessObserver,
+      public RenderProcessMojo {
  public:
   MojoRenderProcessObserver(RenderThread* render_thread);
 
@@ -36,10 +40,17 @@
 
   void OnChannelCreated(const IPC::PlatformFileForTransit& file);
 
+  // RenderProcessMojo overrides:
+  virtual void SetWebUIHandle(
+      int32 view_routing_id,
+      mojo::ScopedMessagePipeHandle web_ui_handle) OVERRIDE;
+
   content::RenderThread* render_thread_;
 
   scoped_ptr<MojoChannelInit> channel_init_;
 
+  mojo::RemotePtr<content::RenderProcessHostMojo> render_process_host_mojo_;
+
   DISALLOW_COPY_AND_ASSIGN(MojoRenderProcessObserver);
 };
 
diff --git a/content/renderer/p2p/ipc_socket_factory.cc b/content/renderer/p2p/ipc_socket_factory.cc
index 0fe5367..59d94ff 100644
--- a/content/renderer/p2p/ipc_socket_factory.cc
+++ b/content/renderer/p2p/ipc_socket_factory.cc
@@ -524,7 +524,7 @@
 
   for (size_t i = 0; i < addresses_.size(); ++i) {
     if (family == addresses_[i].family()) {
-      addr->SetIP(addresses_[i]);
+      addr->SetResolvedIP(addresses_[i]);
       addr->SetPort(port_);
       return true;
     }
diff --git a/content/renderer/p2p/socket_client_impl.cc b/content/renderer/p2p/socket_client_impl.cc
index 804a9a8..5f18805 100644
--- a/content/renderer/p2p/socket_client_impl.cc
+++ b/content/renderer/p2p/socket_client_impl.cc
@@ -46,6 +46,7 @@
     const P2PHostAndIPEndPoint& remote_address,
     P2PSocketClientDelegate* delegate) {
   DCHECK(delegate_message_loop_->BelongsToCurrentThread());
+  DCHECK(delegate);
   // |delegate_| is only accessesed on |delegate_message_loop_|.
   delegate_ = delegate;
 
@@ -61,7 +62,6 @@
                                  const net::IPEndPoint& local_address,
                                  const P2PHostAndIPEndPoint& remote_address) {
   DCHECK_EQ(state_, STATE_UNINITIALIZED);
-  DCHECK(delegate_);
   state_ = STATE_OPENING;
   socket_id_ = dispatcher_->RegisterClient(this);
   dispatcher_->SendP2PMessage(new P2PHostMsg_CreateSocket(
diff --git a/content/renderer/pepper/content_decryptor_delegate.cc b/content/renderer/pepper/content_decryptor_delegate.cc
index 4cb4ddf..aea22ba 100644
--- a/content/renderer/pepper/content_decryptor_delegate.cc
+++ b/content/renderer/pepper/content_decryptor_delegate.cc
@@ -473,7 +473,8 @@
     Decryptor::StreamType stream_type) {
   CancelDecode(stream_type);
 
-  natural_size_ = gfx::Size();
+  if (stream_type == Decryptor::kVideo)
+    natural_size_ = gfx::Size();
 
   // TODO(tomfinegan): Add decoder deinitialize request tracking, and get
   // stream type from media stack.
@@ -1023,6 +1024,7 @@
     scoped_refptr<media::AudioBuffer> frame = media::AudioBuffer::CopyFrom(
         sample_format,
         audio_channel_layout_,
+        audio_channel_count_,
         audio_samples_per_second_,
         frame_count,
         &channel_ptrs[0],
diff --git a/content/renderer/pepper/event_conversion.cc b/content/renderer/pepper/event_conversion.cc
index 52d382a..0243434 100644
--- a/content/renderer/pepper/event_conversion.cc
+++ b/content/renderer/pepper/event_conversion.cc
@@ -459,7 +459,7 @@
 #endif
 
 // Convert a character string to a Windows virtual key code. Adapted from
-// src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp. This
+// src/content/shell/renderer/test_runner/event_sender.cc. This
 // is used by CreateSimulatedWebInputEvents to convert keyboard events.
 void GetKeyCode(const std::string& char_text,
                 WebUChar* code,
@@ -606,7 +606,7 @@
 }
 
 // Generate a coherent sequence of input events to simulate a user event.
-// From src/third_party/WebKit/Tools/DumpRenderTree/chromium/EventSender.cpp.
+// From src/content/shell/renderer/test_runner/event_sender.cc.
 std::vector<linked_ptr<WebInputEvent> > CreateSimulatedWebInputEvents(
     const ppapi::InputEventData& event,
     int plugin_x,
diff --git a/content/renderer/pepper/message_channel.cc b/content/renderer/pepper/message_channel.cc
index 51132a6..9e23e64 100644
--- a/content/renderer/pepper/message_channel.cc
+++ b/content/renderer/pepper/message_channel.cc
@@ -405,17 +405,6 @@
     return;
   }
 
-  // This is for backward compatibility. It usually makes sense for us to return
-  // a string object rather than a string primitive because it allows multiple
-  // references to the same string (as with PP_Var strings). However, prior to
-  // implementing dictionary and array, vars we would return a string primitive
-  // here. Changing it to an object now will break existing code that uses
-  // strict comparisons for strings returned from PostMessage. e.g. x === "123"
-  // will no longer return true. So if the only value to return is a string
-  // object, just return the string primitive.
-  if (v8_val->IsStringObject())
-    v8_val = v8_val->ToString();
-
   WebSerializedScriptValue serialized_val =
       WebSerializedScriptValue::serialize(v8_val);
 
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
index dd3dbd9..e5eab7e 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -51,9 +51,7 @@
 #include "content/renderer/render_widget_fullscreen_pepper.h"
 #include "content/renderer/sad_plugin.h"
 #include "media/base/audio_hardware_config.h"
-#include "ppapi/c/dev/ppb_find_dev.h"
 #include "ppapi/c/dev/ppb_zoom_dev.h"
-#include "ppapi/c/dev/ppp_find_dev.h"
 #include "ppapi/c/dev/ppp_selection_dev.h"
 #include "ppapi/c/dev/ppp_text_input_dev.h"
 #include "ppapi/c/dev/ppp_zoom_dev.h"
@@ -65,6 +63,8 @@
 #include "ppapi/c/ppp_instance.h"
 #include "ppapi/c/ppp_messaging.h"
 #include "ppapi/c/ppp_mouse_lock.h"
+#include "ppapi/c/private/ppb_find_private.h"
+#include "ppapi/c/private/ppp_find_private.h"
 #include "ppapi/c/private/ppp_instance_private.h"
 #include "ppapi/c/private/ppp_pdf.h"
 #include "ppapi/host/ppapi_host.h"
@@ -92,6 +92,7 @@
 #include "skia/ext/platform_device.h"
 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
 #include "third_party/WebKit/public/platform/WebGamepads.h"
+#include "third_party/WebKit/public/platform/WebRect.h"
 #include "third_party/WebKit/public/platform/WebString.h"
 #include "third_party/WebKit/public/platform/WebURL.h"
 #include "third_party/WebKit/public/platform/WebURLError.h"
@@ -1394,8 +1395,8 @@
     return false;
   if (!plugin_find_interface_) {
     plugin_find_interface_ =
-        static_cast<const PPP_Find_Dev*>(module_->GetPluginInterface(
-            PPP_FIND_DEV_INTERFACE));
+        static_cast<const PPP_Find_Private*>(module_->GetPluginInterface(
+            PPP_FIND_PRIVATE_INTERFACE));
   }
 
   return !!plugin_find_interface_;
@@ -2420,6 +2421,24 @@
   }
 }
 
+void PepperPluginInstanceImpl::SetTickmarks(PP_Instance instance,
+                                            const PP_Rect* tickmarks,
+                                            uint32_t count) {
+  if (!render_frame_ || !render_frame_->GetWebFrame())
+    return;
+
+  blink::WebVector<blink::WebRect> tickmarks_converted(
+      static_cast<size_t>(count));
+  for (uint32 i = 0; i < count; ++i) {
+    tickmarks_converted[i] = blink::WebRect(tickmarks[i].point.x,
+                                            tickmarks[i].point.y,
+                                            tickmarks[i].size.width,
+                                            tickmarks[i].size.height);;
+  }
+  blink::WebFrame* frame = render_frame_->GetWebFrame();
+  frame->setTickmarks(tickmarks_converted);
+}
+
 PP_Bool PepperPluginInstanceImpl::IsFullscreen(PP_Instance instance) {
   return PP_FromBool(view_data_.is_fullscreen);
 }
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.h b/content/renderer/pepper/pepper_plugin_instance_impl.h
index 555685c..8bddfb1 100644
--- a/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -23,7 +23,6 @@
 #include "content/public/renderer/render_frame_observer.h"
 #include "content/renderer/mouse_lock_dispatcher.h"
 #include "ppapi/c/dev/pp_cursor_type_dev.h"
-#include "ppapi/c/dev/ppp_find_dev.h"
 #include "ppapi/c/dev/ppp_printing_dev.h"
 #include "ppapi/c/dev/ppp_selection_dev.h"
 #include "ppapi/c/dev/ppp_text_input_dev.h"
@@ -40,6 +39,7 @@
 #include "ppapi/c/ppp_messaging.h"
 #include "ppapi/c/ppp_mouse_lock.h"
 #include "ppapi/c/private/ppb_content_decryptor_private.h"
+#include "ppapi/c/private/ppp_find_private.h"
 #include "ppapi/c/private/ppp_instance_private.h"
 #include "ppapi/c/private/ppp_pdf.h"
 #include "ppapi/shared_impl/ppb_instance_shared.h"
@@ -398,6 +398,9 @@
                                           PP_Bool final_result) OVERRIDE;
   virtual void SelectedFindResultChanged(PP_Instance instance,
                                          int32_t index) OVERRIDE;
+  virtual void SetTickmarks(PP_Instance instance,
+                            const PP_Rect* tickmarks,
+                            uint32_t count) OVERRIDE;
   virtual PP_Bool IsFullscreen(PP_Instance instance) OVERRIDE;
   virtual PP_Bool SetFullscreen(PP_Instance instance,
                                 PP_Bool fullscreen) OVERRIDE;
@@ -718,7 +721,7 @@
 
   // The plugin-provided interfaces.
   // When adding PPP interfaces, make sure to reset them in ResetAsProxied.
-  const PPP_Find_Dev* plugin_find_interface_;
+  const PPP_Find_Private* plugin_find_interface_;
   const PPP_InputEvent* plugin_input_event_interface_;
   const PPP_Messaging* plugin_messaging_interface_;
   const PPP_MouseLock* plugin_mouse_lock_interface_;
diff --git a/content/renderer/pepper/plugin_module.cc b/content/renderer/pepper/plugin_module.cc
index 84ed5b8..7c722d5 100644
--- a/content/renderer/pepper/plugin_module.cc
+++ b/content/renderer/pepper/plugin_module.cc
@@ -37,7 +37,6 @@
 #include "ppapi/c/dev/ppb_cursor_control_dev.h"
 #include "ppapi/c/dev/ppb_device_ref_dev.h"
 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
-#include "ppapi/c/dev/ppb_find_dev.h"
 #include "ppapi/c/dev/ppb_font_dev.h"
 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
 #include "ppapi/c/dev/ppb_graphics_2d_dev.h"
@@ -101,6 +100,7 @@
 #include "ppapi/c/private/ppb_ext_crx_file_system_private.h"
 #include "ppapi/c/private/ppb_file_io_private.h"
 #include "ppapi/c/private/ppb_file_ref_private.h"
+#include "ppapi/c/private/ppb_find_private.h"
 #include "ppapi/c/private/ppb_flash.h"
 #include "ppapi/c/private/ppb_flash_clipboard.h"
 #include "ppapi/c/private/ppb_flash_device_id.h"
diff --git a/content/renderer/pepper/ppb_graphics_3d_impl.cc b/content/renderer/pepper/ppb_graphics_3d_impl.cc
index c0c02d0..18a8e90 100644
--- a/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -127,8 +127,9 @@
 PP_Bool PPB_Graphics3D_Impl::GetTransferBuffer(int32_t id,
                                                int* shm_handle,
                                                uint32_t* shm_size) {
-  gpu::Buffer buffer = GetCommandBuffer()->GetTransferBuffer(id);
-  return ShmToHandle(buffer.shared_memory, buffer.size, shm_handle, shm_size);
+  scoped_refptr<gpu::Buffer> buffer = GetCommandBuffer()->GetTransferBuffer(id);
+  return ShmToHandle(
+      buffer->shared_memory(), buffer->size(), shm_handle, shm_size);
 }
 
 PP_Bool PPB_Graphics3D_Impl::Flush(int32_t put_offset) {
diff --git a/content/renderer/pepper/ppp_pdf.h b/content/renderer/pepper/ppp_pdf.h
deleted file mode 100644
index 7f1e257..0000000
--- a/content/renderer/pepper/ppp_pdf.h
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO(koz): Remove this when the PDF plugin doesn't refer to it.
-#include "ppapi/c/private/ppp_pdf.h"
diff --git a/content/renderer/pepper/url_request_info_util.cc b/content/renderer/pepper/url_request_info_util.cc
index 3059a61..101fe04 100644
--- a/content/renderer/pepper/url_request_info_util.cc
+++ b/content/renderer/pepper/url_request_info_util.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/strings/string_util.h"
+#include "content/child/request_extra_data.h"
 #include "content/common/fileapi/file_system_messages.h"
 #include "content/renderer/pepper/common.h"
 #include "content/renderer/pepper/host_globals.h"
@@ -27,7 +28,6 @@
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "url/gurl.h"
 #include "url/url_util.h"
-#include "webkit/child/weburlrequest_extradata_impl.h"
 
 using ppapi::Resource;
 using ppapi::URLRequestInfoData;
@@ -176,9 +176,11 @@
 
   if (data->has_custom_user_agent) {
     bool was_after_preconnect_request = false;
-    dest->setExtraData(new webkit_glue::WebURLRequestExtraDataImpl(
-        WebString::fromUTF8(data->custom_user_agent),
-        was_after_preconnect_request));
+    RequestExtraData* extra_data = new RequestExtraData();
+    extra_data->set_custom_user_agent(
+        WebString::fromUTF8(data->custom_user_agent));
+    extra_data->set_was_after_preconnect_request(was_after_preconnect_request);
+    dest->setExtraData(extra_data);
   }
 
   return true;
diff --git a/content/renderer/pepper/v8_var_converter.cc b/content/renderer/pepper/v8_var_converter.cc
index ceeeb0e..1affa20 100644
--- a/content/renderer/pepper/v8_var_converter.cc
+++ b/content/renderer/pepper/v8_var_converter.cc
@@ -128,13 +128,14 @@
         return false;
       }
       const std::string& value = string->value();
-      // Create a string object rather than a string primitive. This allows us
-      // to have multiple references to the same string in javascript, which
-      // matches the reference behavior of PP_Vars.
+      // Create a string primitive rather than a string object. This is lossy
+      // in the sense that string primitives in JavaScript can't be referenced
+      // in the same way that string vars can in pepper. But that information
+      // isn't very useful and primitive strings are a more expected form in JS.
       *result = v8::String::NewFromUtf8(isolate,
                                         value.c_str(),
                                         v8::String::kNormalString,
-                                        value.size())->ToObject();
+                                        value.size());
       break;
     }
     case PP_VARTYPE_ARRAY_BUFFER: {
diff --git a/content/renderer/pepper/v8_var_converter_unittest.cc b/content/renderer/pepper/v8_var_converter_unittest.cc
index 52c1713..7c254f1 100644
--- a/content/renderer/pepper/v8_var_converter_unittest.cc
+++ b/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -226,7 +226,7 @@
     if (!RoundTrip(expected.get(), &actual_var))
       return false;
     ScopedPPVar actual(ScopedPPVar::PassRef(), actual_var);
-    return TestEqual(expected.get(), actual.get());
+    return TestEqual(expected.get(), actual.get(), false);
   }
 
   v8::Isolate* isolate_;
@@ -444,7 +444,7 @@
     ScopedPPVar release_expected(
         ScopedPPVar::PassRef(), expected->GetPPVar());
 
-    ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get()));
+    ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get(), true));
   }
 }
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index c399451..9f3f8eb 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -24,6 +24,7 @@
 #include "content/child/service_worker/service_worker_network_provider.h"
 #include "content/child/service_worker/web_service_worker_provider_impl.h"
 #include "content/child/web_socket_stream_handle_impl.h"
+#include "content/common/clipboard_messages.h"
 #include "content/common/frame_messages.h"
 #include "content/common/input_messages.h"
 #include "content/common/service_worker/service_worker_types.h"
@@ -48,8 +49,10 @@
 #include "content/renderer/child_frame_compositing_helper.h"
 #include "content/renderer/context_menu_params_builder.h"
 #include "content/renderer/dom_automation_controller.h"
+#include "content/renderer/ime_event_guard.h"
 #include "content/renderer/internal_document_state_data.h"
 #include "content/renderer/java/java_bridge_dispatcher.h"
+#include "content/renderer/media/webcontentdecryptionmodule_impl.h"
 #include "content/renderer/npapi/plugin_channel_host.h"
 #include "content/renderer/render_process.h"
 #include "content/renderer/render_thread_impl.h"
@@ -75,6 +78,7 @@
 #include "third_party/WebKit/public/web/WebNavigationPolicy.h"
 #include "third_party/WebKit/public/web/WebPlugin.h"
 #include "third_party/WebKit/public/web/WebPluginParams.h"
+#include "third_party/WebKit/public/web/WebRange.h"
 #include "third_party/WebKit/public/web/WebScriptSource.h"
 #include "third_party/WebKit/public/web/WebSearchableFormData.h"
 #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
@@ -107,6 +111,7 @@
 using blink::WebNavigationType;
 using blink::WebNode;
 using blink::WebPluginParams;
+using blink::WebRange;
 using blink::WebReferrerPolicy;
 using blink::WebScriptSource;
 using blink::WebSearchableFormData;
@@ -130,6 +135,8 @@
 
 namespace {
 
+const size_t kExtraCharsBeforeAndAfterSelection = 100;
+
 typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap;
 base::LazyInstance<FrameMap> g_frame_map = LAZY_INSTANCE_INITIALIZER;
 
@@ -145,8 +152,7 @@
 
 WebURLResponseExtraDataImpl* GetExtraDataFromResponse(
     const WebURLResponse& response) {
-  return static_cast<WebURLResponseExtraDataImpl*>(
-      response.extraData());
+  return static_cast<WebURLResponseExtraDataImpl*>(response.extraData());
 }
 
 void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
@@ -170,7 +176,7 @@
   *zero = 0;
 }
 
-#if defined(ADDRESS_SANITIZER)
+#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
 NOINLINE static void MaybeTriggerAsanError(const GURL& url) {
   // NOTE(rogerm): We intentionally perform an invalid heap access here in
   //     order to trigger an Address Sanitizer (ASAN) error report.
@@ -202,7 +208,7 @@
   // Make sure the assignments to the dummy value aren't optimized away.
   base::debug::Alias(&dummy);
 }
-#endif  // ADDRESS_SANITIZER
+#endif  // ADDRESS_SANITIZER || SYZYASAN
 
 static void MaybeHandleDebugURL(const GURL& url) {
   if (!url.SchemeIs(kChromeUIScheme))
@@ -219,9 +225,9 @@
     base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
   }
 
-#if defined(ADDRESS_SANITIZER)
+#if defined(ADDRESS_SANITIZER) || defined(SYZYASAN)
   MaybeTriggerAsanError(url);
-#endif  // ADDRESS_SANITIZER
+#endif  // ADDRESS_SANITIZER || SYZYASAN
 }
 
 // Returns false unless this is a top-level navigation.
@@ -305,7 +311,10 @@
       is_loading_(false),
       is_swapped_out_(false),
       is_detaching_(false),
-      cookie_jar_(this) {
+      cookie_jar_(this),
+      selection_text_offset_(0),
+      selection_range_(gfx::Range::InvalidRange()),
+      handling_select_range_(false) {
   RenderThread::Get()->AddRoute(routing_id_, this);
 
 #if defined(OS_ANDROID)
@@ -396,7 +405,7 @@
     PepperPluginInstanceImpl* instance) {
   if (instance != render_view_->focused_pepper_plugin())
     return;
-  render_view_->SyncSelectionIfRequired();
+  SyncSelectionIfRequired();
 }
 
 RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer(
@@ -554,12 +563,28 @@
     IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed)
     IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction,
                         OnCustomContextMenuAction)
+    IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
+    IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
     IPC_MESSAGE_HANDLER(InputMsg_Cut, OnCut)
     IPC_MESSAGE_HANDLER(InputMsg_Copy, OnCopy)
     IPC_MESSAGE_HANDLER(InputMsg_Paste, OnPaste)
+    IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
+    IPC_MESSAGE_HANDLER(InputMsg_Delete, OnDelete)
+    IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
+    IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
+    IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
     IPC_MESSAGE_HANDLER(FrameMsg_CSSInsertRequest, OnCSSInsertRequest)
     IPC_MESSAGE_HANDLER(FrameMsg_JavaScriptExecuteRequest,
                         OnJavaScriptExecuteRequest)
+    IPC_MESSAGE_HANDLER(FrameMsg_SetEditableSelectionOffsets,
+                        OnSetEditableSelectionOffsets)
+    IPC_MESSAGE_HANDLER(FrameMsg_SetCompositionFromExistingText,
+                        OnSetCompositionFromExistingText)
+    IPC_MESSAGE_HANDLER(FrameMsg_ExtendSelectionAndDelete,
+                        OnExtendSelectionAndDelete)
+#if defined(OS_MACOSX)
+    IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
+#endif
   IPC_END_MESSAGE_MAP_EX()
 
   if (!msg_is_ok) {
@@ -769,19 +794,24 @@
 
 void RenderFrameImpl::OnSwapOut() {
   // Only run unload if we're not swapped out yet, but send the ack either way.
-  if (!is_swapped_out_) {
-    // Swap this RenderView out so the tab can navigate to a page rendered by a
-    // different process.  This involves running the unload handler and clearing
-    // the page.  Once WasSwappedOut is called, we also allow this process to
-    // exit if there are no other active RenderViews in it.
+  if (!is_swapped_out_ || !render_view_->is_swapped_out_) {
+    // Swap this RenderFrame out so the frame can navigate to a page rendered by
+    // a different process.  This involves running the unload handler and
+    // clearing the page.  Once WasSwappedOut is called, we also allow this
+    // process to exit if there are no other active RenderFrames in it.
 
     // Send an UpdateState message before we get swapped out.
     render_view_->SyncNavigationState();
 
     // Synchronously run the unload handler before sending the ACK.
-    // TODO(creis): Add a WebFrame::dispatchUnloadEvent and call it here.
+    // TODO(creis): Move WebView::dispatchUnloadEvent to WebFrame and call it
+    // here to support unload on subframes as well.
+    if (!frame_->parent())
+      render_view_->webview()->dispatchUnloadEvent();
 
     // Swap out and stop sending any IPC messages that are not ACKs.
+    if (!frame_->parent())
+      render_view_->SetSwappedOut(true);
     is_swapped_out_ = true;
 
     // Now that we're swapped out and filtering IPC messages, stop loading to
@@ -790,9 +820,15 @@
     // TODO(creis): Should we be stopping all frames here and using
     // StopAltErrorPageFetcher with RenderView::OnStop, or just stopping this
     // frame?
-    frame_->stopLoading();
+    if (!frame_->parent())
+      render_view_->OnStop();
+    else
+      frame_->stopLoading();
 
-    frame_->setIsRemote(true);
+    // Let subframes know that the frame is now rendered remotely, for the
+    // purposes of compositing and input events.
+    if (frame_->parent())
+      frame_->setIsRemote(true);
 
     // Replace the page with a blank dummy URL. The unload handler will not be
     // run a second time, thanks to a check in FrameLoader::stopLoading.
@@ -800,9 +836,23 @@
     // beforeunload handler. For now, we just run it a second time silently.
     render_view_->NavigateToSwappedOutURL(frame_);
 
-    render_view_->RegisterSwappedOutChildFrame(this);
+    if (frame_->parent())
+      render_view_->RegisterSwappedOutChildFrame(this);
+
+    // Let WebKit know that this view is hidden so it can drop resources and
+    // stop compositing.
+    // TODO(creis): Support this for subframes as well.
+    if (!frame_->parent()) {
+      render_view_->webview()->setVisibilityState(
+          blink::WebPageVisibilityStateHidden, false);
+    }
   }
 
+  // It is now safe to show modal dialogs again.
+  // TODO(creis): Deal with modal dialogs from subframes.
+  if (!frame_->parent())
+    render_view_->suppress_dialogs_until_swap_out_ = false;
+
   Send(new FrameHostMsg_SwapOut_ACK(routing_id_));
 }
 
@@ -872,26 +922,72 @@
   }
 }
 
+void RenderFrameImpl::OnUndo() {
+  frame_->executeCommand(WebString::fromUTF8("Undo"), GetFocusedElement());
+}
+
+void RenderFrameImpl::OnRedo() {
+  frame_->executeCommand(WebString::fromUTF8("Redo"), GetFocusedElement());
+}
+
 void RenderFrameImpl::OnCut() {
-  base::AutoReset<bool> handling_select_range(
-      &render_view_->handling_select_range_, true);
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   frame_->executeCommand(WebString::fromUTF8("Cut"), GetFocusedElement());
 }
 
 void RenderFrameImpl::OnCopy() {
-  base::AutoReset<bool> handling_select_range(
-      &render_view_->handling_select_range_, true);
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   WebNode current_node = context_menu_node_.isNull() ?
       GetFocusedElement() : context_menu_node_;
   frame_->executeCommand(WebString::fromUTF8("Copy"), current_node);
 }
 
 void RenderFrameImpl::OnPaste() {
-  base::AutoReset<bool> handling_select_range(
-      &render_view_->handling_select_range_, true);
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
   frame_->executeCommand(WebString::fromUTF8("Paste"), GetFocusedElement());
 }
 
+void RenderFrameImpl::OnPasteAndMatchStyle() {
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+  frame_->executeCommand(
+      WebString::fromUTF8("PasteAndMatchStyle"), GetFocusedElement());
+}
+
+#if defined(OS_MACOSX)
+void RenderFrameImpl::OnCopyToFindPboard() {
+  // Since the find pasteboard supports only plain text, this can be simpler
+  // than the |OnCopy()| case.
+  if (frame_->hasSelection()) {
+    base::string16 selection = frame_->selectionAsText();
+    RenderThread::Get()->Send(
+        new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
+  }
+}
+#endif
+
+void RenderFrameImpl::OnDelete() {
+  frame_->executeCommand(WebString::fromUTF8("Delete"), GetFocusedElement());
+}
+
+void RenderFrameImpl::OnSelectAll() {
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+  frame_->executeCommand(WebString::fromUTF8("SelectAll"), GetFocusedElement());
+}
+
+void RenderFrameImpl::OnSelectRange(const gfx::Point& start,
+                                    const gfx::Point& end) {
+  // This IPC is dispatched by RenderWidgetHost, so use its routing id.
+  Send(new ViewHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
+
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+  frame_->selectRange(start, end);
+}
+
+void RenderFrameImpl::OnUnselect() {
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+  frame_->executeCommand(WebString::fromUTF8("Unselect"), GetFocusedElement());
+}
+
 void RenderFrameImpl::OnCSSInsertRequest(const std::string& css) {
   frame_->document().insertStyleSheet(WebString::fromUTF8(css));
 }
@@ -923,6 +1019,31 @@
   }
 }
 
+void RenderFrameImpl::OnSetEditableSelectionOffsets(int start, int end) {
+  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
+  if (!GetRenderWidget()->ShouldHandleImeEvent())
+    return;
+  ImeEventGuard guard(GetRenderWidget());
+  frame_->setEditableSelectionOffsets(start, end);
+}
+
+void RenderFrameImpl::OnSetCompositionFromExistingText(
+    int start, int end,
+    const std::vector<blink::WebCompositionUnderline>& underlines) {
+  if (!GetRenderWidget()->ShouldHandleImeEvent())
+    return;
+  ImeEventGuard guard(GetRenderWidget());
+  frame_->setCompositionFromExistingText(start, end, underlines);
+}
+
+void RenderFrameImpl::OnExtendSelectionAndDelete(int before, int after) {
+  if (!GetRenderWidget()->ShouldHandleImeEvent())
+    return;
+  ImeEventGuard guard(GetRenderWidget());
+  frame_->extendSelectionAndDelete(before, after);
+}
+
+
 bool RenderFrameImpl::ShouldUpdateSelectionTextFromContextMenuParams(
     const base::string16& selection_text,
     size_t selection_text_offset,
@@ -1017,6 +1138,10 @@
   loadURLExternally(frame, request, policy);
 }
 
+void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) {
+  OnJavaScriptExecuteRequest(javascript, 0, false);
+}
+
 void RenderFrameImpl::OnChildFrameProcessGone() {
   if (compositing_helper_)
     compositing_helper_->ChildFrameGone();
@@ -1068,6 +1193,16 @@
   return render_view_->CreateMediaPlayer(this, frame, url, client);
 }
 
+blink::WebContentDecryptionModule*
+RenderFrameImpl::createContentDecryptionModule(
+    blink::WebFrame* frame,
+    const blink::WebSecurityOrigin& security_origin,
+    const blink::WebString& key_system) {
+  DCHECK(!frame_ || frame_ == frame);
+  return WebContentDecryptionModuleImpl::Create(
+      frame, security_origin, key_system);
+}
+
 blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
     blink::WebFrame* frame,
     blink::WebApplicationCacheHostClient* client) {
@@ -1379,8 +1514,7 @@
   int parent_routing_id = frame->parent() ?
       FromWebFrame(frame->parent())->GetRoutingID() : -1;
   Send(new FrameHostMsg_DidStartProvisionalLoadForFrame(
-       routing_id_, parent_routing_id,
-       is_top_most, ds->request().url()));
+       routing_id_, parent_routing_id, ds->request().url()));
 }
 
 void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
@@ -1427,7 +1561,6 @@
 
   FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
   params.frame_unique_name = frame->uniqueName();
-  params.is_main_frame = !frame->parent();
   params.error_code = error.reason;
   GetContentClient()->renderer()->GetNavigationErrorStrings(
       render_view_.get(),
@@ -1668,6 +1801,8 @@
   // TODO(nasko): Remove once we have RenderFrameObserver for this method.
   render_view_->didFinishDocumentLoad(frame);
 
+  FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidFinishDocumentLoad());
+
   // Check whether we have new encoding name.
   render_view_->UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
 }
@@ -1699,7 +1834,6 @@
       &error_description);
   Send(new FrameHostMsg_DidFailLoadWithError(routing_id_,
                                              failed_request.url(),
-                                             !frame->parent(),
                                              error.reason,
                                              error_description));
 }
@@ -1724,8 +1858,7 @@
     return;
 
   Send(new FrameHostMsg_DidFinishLoad(routing_id_,
-                                      ds->request().url(),
-                                      !frame->parent()));
+                                      ds->request().url()));
 }
 
 void RenderFrameImpl::didNavigateWithinPage(blink::WebFrame* frame,
@@ -1756,7 +1889,22 @@
 }
 
 void RenderFrameImpl::didChangeSelection(bool is_empty_selection) {
-  render_view_->didChangeSelection(is_empty_selection);
+  if (!GetRenderWidget()->handling_input_event() && !handling_select_range_)
+    return;
+
+  if (is_empty_selection)
+    selection_text_.clear();
+
+  // UpdateTextInputType should be called before SyncSelectionIfRequired.
+  // UpdateTextInputType may send TextInputTypeChanged to notify the focus
+  // was changed, and SyncSelectionIfRequired may send SelectionChanged
+  // to notify the selection was changed.  Focus change should be notified
+  // before selection change.
+  GetRenderWidget()->UpdateTextInputType();
+  SyncSelectionIfRequired();
+#if defined(OS_ANDROID)
+  GetRenderWidget()->UpdateTextInputState(false, true);
+#endif
 }
 
 void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
@@ -1774,24 +1922,17 @@
   // to showing the context menu.
   // TODO(asvitkine): http://crbug.com/152432
   if (ShouldUpdateSelectionTextFromContextMenuParams(
-          render_view_->selection_text_,
-          render_view_->selection_text_offset_,
-          render_view_->selection_range_,
-          params)) {
-    render_view_->selection_text_ = params.selection_text;
+          selection_text_, selection_text_offset_, selection_range_, params)) {
+    selection_text_ = params.selection_text;
     // TODO(asvitkine): Text offset and range is not available in this case.
-    render_view_->selection_text_offset_ = 0;
-    render_view_->selection_range_ =
-        gfx::Range(0, render_view_->selection_text_.length());
+    selection_text_offset_ = 0;
+    selection_range_ = gfx::Range(0, selection_text_.length());
+    // This IPC is dispatched by RenderWidetHost, so use its routing ID.
     Send(new ViewHostMsg_SelectionChanged(
-        routing_id_,
-        render_view_->selection_text_,
-        render_view_->selection_text_offset_,
-        render_view_->selection_range_));
+        GetRenderWidget()->routing_id(), selection_text_,
+        selection_text_offset_, selection_range_));
   }
 
-  params.frame_id = routing_id_;
-
   // Serializing a GURL longer than kMaxURLChars will fail, so don't do
   // it.  We replace it with an empty GURL so the appropriate items are disabled
   // in the context menu.
@@ -1804,7 +1945,7 @@
 #if defined(OS_ANDROID)
   gfx::Rect start_rect;
   gfx::Rect end_rect;
-  render_view_->GetSelectionBounds(&start_rect, &end_rect);
+  GetRenderWidget()->GetSelectionBounds(&start_rect, &end_rect);
   params.selection_start = gfx::Point(start_rect.x(), start_rect.bottom());
   params.selection_end = gfx::Point(end_rect.right(), end_rect.bottom());
 #endif
@@ -1828,8 +1969,10 @@
   bool was_after_preconnect_request = true;
   // The args after |was_after_preconnect_request| are not used, and set to
   // correct values at |willSendRequest|.
-  request.setExtraData(new webkit_glue::WebURLRequestExtraDataImpl(
-      custom_user_agent, was_after_preconnect_request));
+  RequestExtraData* extra_data = new RequestExtraData();
+  extra_data->set_custom_user_agent(custom_user_agent);
+  extra_data->set_was_after_preconnect_request(was_after_preconnect_request);
+  request.setExtraData(extra_data);
 }
 
 void RenderFrameImpl::willSendRequest(
@@ -1878,8 +2021,8 @@
   WebString custom_user_agent;
   bool was_after_preconnect_request = false;
   if (request.extraData()) {
-    webkit_glue::WebURLRequestExtraDataImpl* old_extra_data =
-        static_cast<webkit_glue::WebURLRequestExtraDataImpl*>(
+    RequestExtraData* old_extra_data =
+        static_cast<RequestExtraData*>(
             request.extraData());
     custom_user_agent = old_extra_data->custom_user_agent();
     was_after_preconnect_request =
@@ -1929,21 +2072,25 @@
 
   int parent_routing_id = frame->parent() ?
       FromWebFrame(frame->parent())->GetRoutingID() : -1;
-  request.setExtraData(
-      new RequestExtraData(render_view_->visibilityState(),
-                           custom_user_agent,
-                           was_after_preconnect_request,
-                           routing_id_,
-                           (frame == top_frame),
-                           GURL(frame->document().securityOrigin().toString()),
-                           frame->parent() == top_frame,
-                           parent_routing_id,
-                           navigation_state->allow_download(),
-                           transition_type,
-                           should_replace_current_entry,
-                           navigation_state->transferred_request_child_id(),
-                           navigation_state->transferred_request_request_id(),
-                           provider_id));
+  RequestExtraData* extra_data = new RequestExtraData();
+  extra_data->set_visibility_state(render_view_->visibilityState());
+  extra_data->set_custom_user_agent(custom_user_agent);
+  extra_data->set_was_after_preconnect_request(was_after_preconnect_request);
+  extra_data->set_render_frame_id(routing_id_);
+  extra_data->set_is_main_frame(frame == top_frame);
+  extra_data->set_frame_origin(
+      GURL(frame->document().securityOrigin().toString()));
+  extra_data->set_parent_is_main_frame(frame->parent() == top_frame);
+  extra_data->set_parent_render_frame_id(parent_routing_id);
+  extra_data->set_allow_download(navigation_state->allow_download());
+  extra_data->set_transition_type(transition_type);
+  extra_data->set_should_replace_current_entry(should_replace_current_entry);
+  extra_data->set_transferred_request_child_id(
+      navigation_state->transferred_request_child_id());
+  extra_data->set_transferred_request_request_id(
+      navigation_state->transferred_request_request_id());
+  extra_data->set_service_worker_provider_id(provider_id);
+  request.setExtraData(extra_data);
 
   DocumentState* top_document_state =
       DocumentState::FromDataSource(top_data_source);
@@ -2008,7 +2155,8 @@
   int http_status_code = response.httpStatusCode();
 
   // Record page load flags.
-  WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(response);
+  WebURLResponseExtraDataImpl* extra_data =
+      GetExtraDataFromResponse(response);
   if (extra_data) {
     document_state->set_was_fetched_via_spdy(
         extra_data->was_fetched_via_spdy());
@@ -2476,9 +2624,11 @@
 
   is_loading_ = true;
 
-  render_view_->didStartLoading(frame_);
+  bool view_was_loading = render_view_->is_loading();
+  render_view_->FrameDidStartLoading(frame_);
 
-  Send(new FrameHostMsg_DidStartLoading(routing_id_));
+  if (!view_was_loading)
+    Send(new FrameHostMsg_DidStartLoading(routing_id_, to_different_document));
 }
 
 void RenderFrameImpl::didStopLoading() {
@@ -2487,9 +2637,10 @@
     return;
   }
 
+  DCHECK(render_view_->is_loading());
   is_loading_ = false;
 
-  render_view_->didStopLoading(frame_);
+  render_view_->FrameDidStopLoading(frame_);
 
   // NOTE: For now we're doing the safest thing, and sending out notification
   // when done loading. This currently isn't an issue as the favicon is only
@@ -2497,7 +2648,12 @@
   // finished parsing the head, but webkit doesn't support that yet.
   // The feed discovery code would also benefit from access to the head.
   // NOTE: Sending of the IPC message happens through the top-level frame.
-  Send(new FrameHostMsg_DidStopLoading(routing_id_));
+  if (!render_view_->is_loading())
+    Send(new FrameHostMsg_DidStopLoading(routing_id_));
+}
+
+void RenderFrameImpl::didChangeLoadProgress(double load_progress) {
+  render_view_->FrameDidChangeLoadProgress(frame_, load_progress);
 }
 
 WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
@@ -2757,8 +2913,65 @@
   Send(new FrameHostMsg_OpenURL(routing_id_, params));
 }
 
-void RenderFrameImpl::didChangeLoadProgress(double load_progress) {
-  render_view_->didChangeLoadProgress(frame_, load_progress);
+void RenderFrameImpl::SyncSelectionIfRequired() {
+  base::string16 text;
+  size_t offset;
+  gfx::Range range;
+#if defined(ENABLE_PLUGINS)
+  if (render_view_->focused_pepper_plugin_) {
+    render_view_->focused_pepper_plugin_->GetSurroundingText(&text, &range);
+    offset = 0;  // Pepper API does not support offset reporting.
+    // TODO(kinaba): cut as needed.
+  } else
+#endif
+  {
+    size_t location, length;
+    if (!GetRenderWidget()->webwidget()->caretOrSelectionRange(
+            &location, &length)) {
+      return;
+    }
+
+    range = gfx::Range(location, location + length);
+
+    if (GetRenderWidget()->webwidget()->textInputInfo().type !=
+            blink::WebTextInputTypeNone) {
+      // If current focused element is editable, we will send 100 more chars
+      // before and after selection. It is for input method surrounding text
+      // feature.
+      if (location > kExtraCharsBeforeAndAfterSelection)
+        offset = location - kExtraCharsBeforeAndAfterSelection;
+      else
+        offset = 0;
+      length = location + length - offset + kExtraCharsBeforeAndAfterSelection;
+      WebRange webrange = WebRange::fromDocumentRange(frame_, offset, length);
+      if (!webrange.isNull())
+        text = WebRange::fromDocumentRange(
+            frame_, offset, length).toPlainText();
+    } else {
+      offset = location;
+      text = frame_->selectionAsText();
+      // http://crbug.com/101435
+      // In some case, frame->selectionAsText() returned text's length is not
+      // equal to the length returned from webwidget()->caretOrSelectionRange().
+      // So we have to set the range according to text.length().
+      range.set_end(range.start() + text.length());
+    }
+  }
+
+  // Sometimes we get repeated didChangeSelection calls from webkit when
+  // the selection hasn't actually changed. We don't want to report these
+  // because it will cause us to continually claim the X clipboard.
+  if (selection_text_offset_ != offset ||
+      selection_range_ != range ||
+      selection_text_ != text) {
+    selection_text_ = text;
+    selection_text_offset_ = offset;
+    selection_range_ = range;
+    // This IPC is dispatched by RenderWidetHost, so use its routing ID.
+    Send(new ViewHostMsg_SelectionChanged(
+        GetRenderWidget()->routing_id(), text, offset, range));
+  }
+  GetRenderWidget()->UpdateSelectionBounds();
 }
 
 }  // namespace content
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 8aee1f2..e8abca1 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -14,13 +14,13 @@
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
 #include "base/process/process_handle.h"
-#include "base/strings/string16.h"
 #include "content/public/common/referrer.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/renderer/renderer_webcookiejar_impl.h"
 #include "ipc/ipc_message.h"
 #include "third_party/WebKit/public/web/WebDataSource.h"
 #include "third_party/WebKit/public/web/WebFrameClient.h"
+#include "ui/gfx/range/range.h"
 
 class TransportDIB;
 struct FrameMsg_BuffersSwapped_Params;
@@ -30,6 +30,8 @@
 namespace blink {
 class WebInputEvent;
 class WebMouseEvent;
+class WebContentDecryptionModule;
+class WebSecurityOrigin;
 struct WebCompositionUnderline;
 struct WebContextMenuData;
 struct WebCursorInfo;
@@ -99,6 +101,8 @@
   // TODO(nasko): Those are page-level methods at this time and come from
   // WebViewClient. We should move them to be WebFrameClient calls and put
   // logic in the browser side to balance starts/stops.
+  // |to_different_document| will be true unless the load is a fragment
+  // navigation, or triggered by history.pushState/replaceState.
   virtual void didStartLoading(bool to_different_document);
   virtual void didStopLoading();
   virtual void didChangeLoadProgress(double load_progress);
@@ -181,6 +185,7 @@
       blink::WebFrame* frame,
       const blink::WebURLRequest& request,
       blink::WebNavigationPolicy policy) OVERRIDE;
+  virtual void ExecuteJavaScript(const base::string16& javascript) OVERRIDE;
 
   // blink::WebFrameClient implementation -------------------------------------
   virtual blink::WebPlugin* createPlugin(
@@ -190,6 +195,10 @@
       blink::WebFrame* frame,
       const blink::WebURL& url,
       blink::WebMediaPlayerClient* client);
+  virtual blink::WebContentDecryptionModule* createContentDecryptionModule(
+      blink::WebFrame* frame,
+      const blink::WebSecurityOrigin& security_origin,
+      const blink::WebString& key_system);
   virtual blink::WebApplicationCacheHost* createApplicationCacheHost(
       blink::WebFrame* frame,
       blink::WebApplicationCacheHostClient* client);
@@ -341,8 +350,16 @@
 
  private:
   friend class RenderFrameObserver;
-  FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest,
+  FRIEND_TEST_ALL_PREFIXES(RendererAccessibilityTest,
+                           AccessibilityMessagesQueueWhileSwappedOut);
+    FRIEND_TEST_ALL_PREFIXES(RenderFrameImplTest,
                            ShouldUpdateSelectionTextFromContextMenuParams);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
+                           OnExtendSelectionAndDelete);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ReloadWhileSwappedOut);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SendSwapOutACK);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
+                           SetEditableSelectionAndComposition);
 
   typedef std::map<GURL, double> HostZoomLevels;
 
@@ -369,13 +386,28 @@
   void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
   void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
                                  unsigned action);
+  void OnUndo();
+  void OnRedo();
   void OnCut();
   void OnCopy();
   void OnPaste();
+  void OnPasteAndMatchStyle();
+  void OnDelete();
+  void OnSelectAll();
+  void OnSelectRange(const gfx::Point& start, const gfx::Point& end);
+  void OnUnselect();
   void OnCSSInsertRequest(const std::string& css);
   void OnJavaScriptExecuteRequest(const base::string16& javascript,
                                   int id,
                                   bool notify_result);
+  void OnSetEditableSelectionOffsets(int start, int end);
+  void OnSetCompositionFromExistingText(
+      int start, int end,
+      const std::vector<blink::WebCompositionUnderline>& underlines);
+  void OnExtendSelectionAndDelete(int before, int after);
+#if defined(OS_MACOSX)
+  void OnCopyToFindPboard();
+#endif
 
   // Virtual since overridden by WebTestProxy for layout tests.
   virtual blink::WebNavigationPolicy DecidePolicyForNavigation(
@@ -391,6 +423,12 @@
                const Referrer& referrer,
                blink::WebNavigationPolicy policy);
 
+  // Dispatches the current state of selection on the webpage to the browser if
+  // it has changed.
+  // TODO(varunjain): delete this method once we figure out how to keep
+  // selection handles in sync with the webpage.
+  void SyncSelectionIfRequired();
+
   // Returns whether |params.selection_text| should be synchronized to the
   // browser before bringing up the context menu. Static for testing.
   static bool ShouldUpdateSelectionTextFromContextMenuParams(
@@ -437,6 +475,21 @@
   // much about leaks.
   IDMap<ContextMenuClient, IDMapExternalPointer> pending_context_menus_;
 
+  // The text selection the last time DidChangeSelection got called. May contain
+  // additional characters before and after the selected text, for IMEs. The
+  // portion of this string that is the actual selected text starts at index
+  // |selection_range_.GetMin() - selection_text_offset_| and has length
+  // |selection_range_.length()|.
+  base::string16 selection_text_;
+  // The offset corresponding to the start of |selection_text_| in the document.
+  size_t selection_text_offset_;
+  // Range over the document corresponding to the actual selected text (which
+  // could correspond to a substring of |selection_text_|; see above).
+  gfx::Range selection_range_;
+  // Used to inform didChangeSelection() when it is called in the context
+  // of handling a InputMsg_SelectRange IPC.
+  bool handling_select_range_;
+
   DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
 };
 
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 140fa79..00aedb9 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -411,8 +411,7 @@
       RegisterExtension(GpuBenchmarkingExtension::Get());
 
   is_impl_side_painting_enabled_ =
-      command_line.HasSwitch(switches::kEnableImplSidePainting) &&
-      !command_line.HasSwitch(switches::kDisableImplSidePainting);
+      command_line.HasSwitch(switches::kEnableImplSidePainting);
   webkit::WebLayerImpl::SetImplSidePaintingEnabled(
       is_impl_side_painting_enabled_);
 
@@ -445,7 +444,7 @@
     }
   }
 
-  is_low_res_tiling_enabled_ = !is_gpu_rasterization_enabled_;
+  is_low_res_tiling_enabled_ = true;
   if (command_line.HasSwitch(switches::kDisableLowResTiling) &&
       !command_line.HasSwitch(switches::kEnableLowResTiling)) {
     is_low_res_tiling_enabled_ = false;
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index cbab25c..b26266f 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -28,6 +28,9 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/render_view_test.h"
 #include "content/public/test/test_utils.h"
+#include "content/renderer/accessibility/renderer_accessibility.h"
+#include "content/renderer/accessibility/renderer_accessibility_complete.h"
+#include "content/renderer/accessibility/renderer_accessibility_focus_only.h"
 #include "content/renderer/render_view_impl.h"
 #include "content/shell/browser/shell.h"
 #include "content/shell/browser/shell_browser_context.h"
@@ -519,22 +522,22 @@
   int initial_page_id = view()->GetPageId();
 
   // Respond to a swap out request.
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
 
   // Ensure the swap out commits synchronously.
   EXPECT_NE(initial_page_id, view()->GetPageId());
 
   // Check for a valid OnSwapOutACK.
   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_SwapOut_ACK::ID);
+      FrameHostMsg_SwapOut_ACK::ID);
   ASSERT_TRUE(msg);
 
   // It is possible to get another swap out request.  Ensure that we send
   // an ACK, even if we don't have to do anything else.
   render_thread_->sink().ClearMessages();
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
   const IPC::Message* msg2 = render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_SwapOut_ACK::ID);
+      FrameHostMsg_SwapOut_ACK::ID);
   ASSERT_TRUE(msg2);
 
   // If we navigate back to this RenderView, ensure we don't send a state
@@ -587,11 +590,11 @@
   ProcessPendingMessages();
 
   // Respond to a swap out request.
-  view()->OnSwapOut();
+  view()->main_render_frame()->OnSwapOut();
 
   // Check for a OnSwapOutACK.
   const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
-      ViewHostMsg_SwapOut_ACK::ID);
+      FrameHostMsg_SwapOut_ACK::ID);
   ASSERT_TRUE(msg);
   render_thread_->sink().ClearMessages();
 
@@ -1949,15 +1952,15 @@
            "</body>"
            "</html>");
   ExecuteJavaScript("document.getElementById('test1').focus();");
-  view()->OnSetEditableSelectionOffsets(4, 8);
+  frame()->OnSetEditableSelectionOffsets(4, 8);
   const std::vector<blink::WebCompositionUnderline> empty_underline;
-  view()->OnSetCompositionFromExistingText(7, 10, empty_underline);
+  frame()->OnSetCompositionFromExistingText(7, 10, empty_underline);
   blink::WebTextInputInfo info = view()->webview()->textInputInfo();
   EXPECT_EQ(4, info.selectionStart);
   EXPECT_EQ(8, info.selectionEnd);
   EXPECT_EQ(7, info.compositionStart);
   EXPECT_EQ(10, info.compositionEnd);
-  view()->OnUnselect();
+  frame()->OnUnselect();
   info = view()->webview()->textInputInfo();
   EXPECT_EQ(0, info.selectionStart);
   EXPECT_EQ(0, info.selectionEnd);
@@ -1974,14 +1977,14 @@
            "</body>"
            "</html>");
   ExecuteJavaScript("document.getElementById('test1').focus();");
-  view()->OnSetEditableSelectionOffsets(10, 10);
-  view()->OnExtendSelectionAndDelete(3, 4);
+  frame()->OnSetEditableSelectionOffsets(10, 10);
+  frame()->OnExtendSelectionAndDelete(3, 4);
   blink::WebTextInputInfo info = view()->webview()->textInputInfo();
   EXPECT_EQ("abcdefgopqrstuvwxyz", info.value);
   EXPECT_EQ(7, info.selectionStart);
   EXPECT_EQ(7, info.selectionEnd);
-  view()->OnSetEditableSelectionOffsets(4, 8);
-  view()->OnExtendSelectionAndDelete(2, 5);
+  frame()->OnSetEditableSelectionOffsets(4, 8);
+  frame()->OnExtendSelectionAndDelete(2, 5);
   info = view()->webview()->textInputInfo();
   EXPECT_EQ("abuvwxyz", info.value);
   EXPECT_EQ(2, info.selectionStart);
@@ -2327,4 +2330,31 @@
             provider->provider_id());
 }
 
+TEST_F(RenderViewImplTest, OnSetAccessibilityMode) {
+  ASSERT_EQ(AccessibilityModeOff, view()->accessibility_mode());
+  ASSERT_EQ((RendererAccessibility*) NULL, view()->renderer_accessibility());
+
+  view()->OnSetAccessibilityMode(AccessibilityModeTreeOnly);
+  ASSERT_EQ(AccessibilityModeTreeOnly, view()->accessibility_mode());
+  ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
+  ASSERT_EQ(RendererAccessibilityTypeComplete,
+            view()->renderer_accessibility()->GetType());
+
+  view()->OnSetAccessibilityMode(AccessibilityModeOff);
+  ASSERT_EQ(AccessibilityModeOff, view()->accessibility_mode());
+  ASSERT_EQ((RendererAccessibility*) NULL, view()->renderer_accessibility());
+
+  view()->OnSetAccessibilityMode(AccessibilityModeComplete);
+  ASSERT_EQ(AccessibilityModeComplete, view()->accessibility_mode());
+  ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
+  ASSERT_EQ(RendererAccessibilityTypeComplete,
+            view()->renderer_accessibility()->GetType());
+
+  view()->OnSetAccessibilityMode(AccessibilityModeEditableTextOnly);
+  ASSERT_EQ(AccessibilityModeEditableTextOnly, view()->accessibility_mode());
+  ASSERT_NE((RendererAccessibility*) NULL, view()->renderer_accessibility());
+  ASSERT_EQ(RendererAccessibilityTypeFocusOnly,
+            view()->renderer_accessibility()->GetType());
+}
+
 }  // namespace content
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 0847fa9..ec6cb60 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -38,7 +38,6 @@
 #include "content/child/npapi/webplugin_delegate_impl.h"
 #include "content/child/request_extra_data.h"
 #include "content/child/webmessageportchannel_impl.h"
-#include "content/common/clipboard_messages.h"
 #include "content/common/database_messages.h"
 #include "content/common/dom_storage/dom_storage_types.h"
 #include "content/common/drag_messages.h"
@@ -188,6 +187,7 @@
 #include "third_party/WebKit/public/web/WebView.h"
 #include "third_party/WebKit/public/web/WebWindowFeatures.h"
 #include "third_party/WebKit/public/web/default/WebRenderTheme.h"
+#include "ui/base/clipboard/clipboard.h"
 #include "ui/base/ui_base_switches_util.h"
 #include "ui/events/latency_info.h"
 #include "ui/gfx/native_widget_types.h"
@@ -238,6 +238,10 @@
 #include "content/renderer/media/rtc_peer_connection_handler.h"
 #endif
 
+#if defined(USE_MOJO)
+#include "content/renderer/web_ui_mojo.h"
+#endif
+
 using blink::WebAXObject;
 using blink::WebApplicationCacheHost;
 using blink::WebApplicationCacheHostClient;
@@ -346,8 +350,6 @@
 const int kDelaySecondsForContentStateSyncHidden = 5;
 const int kDelaySecondsForContentStateSync = 1;
 
-const size_t kExtraCharsBeforeAndAfterSelection = 100;
-
 #if defined(OS_ANDROID)
 // Delay between tapping in content and launching the associated android intent.
 // Used to allow users see what has been recognized as content.
@@ -606,14 +608,14 @@
     item_list.push_back(item);
   }
 
-  for (std::vector<DropData::FileInfo>::const_iterator it =
+  for (std::vector<ui::FileInfo>::const_iterator it =
            drop_data.filenames.begin();
        it != drop_data.filenames.end();
        ++it) {
     WebDragData::Item item;
     item.storageType = WebDragData::Item::StorageTypeFilename;
-    item.filenameData = it->path;
-    item.displayNameData = it->display_name;
+    item.filenameData = it->path.AsUTF16Unsafe();
+    item.displayNameData = it->display_name.AsUTF16Unsafe();
     item_list.push_back(item);
   }
 
@@ -655,9 +657,8 @@
       next_page_id_(params->next_page_id),
       history_list_offset_(-1),
       history_list_length_(0),
+      frames_in_progress_(0),
       target_url_status_(TARGET_NONE),
-      selection_text_offset_(0),
-      selection_range_(gfx::Range::InvalidRange()),
 #if defined(OS_ANDROID)
       top_controls_constraints_(cc::BOTH),
 #endif
@@ -695,7 +696,6 @@
       enumeration_completion_id_(0),
       load_progress_tracker_(new LoadProgressTracker(this)),
       session_storage_namespace_id_(params->session_storage_namespace_id),
-      handling_select_range_(false),
       next_snapshot_id_(0) {
 }
 
@@ -929,7 +929,7 @@
     bool hidden,
     int32 next_page_id,
     const blink::WebScreenInfo& screen_info,
-    unsigned int accessibility_mode) {
+    AccessibilityMode accessibility_mode) {
   DCHECK(routing_id != MSG_ROUTING_NONE);
   RenderViewImplParams params(opener_id,
                               renderer_prefs,
@@ -1071,31 +1071,18 @@
   bool handled = true;
   bool msg_is_ok = true;
   IPC_BEGIN_MESSAGE_MAP_EX(RenderViewImpl, message, msg_is_ok)
-    IPC_MESSAGE_HANDLER(InputMsg_Delete, OnDelete)
     IPC_MESSAGE_HANDLER(InputMsg_ExecuteEditCommand, OnExecuteEditCommand)
     IPC_MESSAGE_HANDLER(InputMsg_MoveCaret, OnMoveCaret)
-    IPC_MESSAGE_HANDLER(InputMsg_PasteAndMatchStyle, OnPasteAndMatchStyle)
-    IPC_MESSAGE_HANDLER(InputMsg_Redo, OnRedo)
     IPC_MESSAGE_HANDLER(InputMsg_Replace, OnReplace)
     IPC_MESSAGE_HANDLER(InputMsg_ReplaceMisspelling, OnReplaceMisspelling)
     IPC_MESSAGE_HANDLER(InputMsg_ScrollFocusedEditableNodeIntoRect,
                         OnScrollFocusedEditableNodeIntoRect)
-    IPC_MESSAGE_HANDLER(InputMsg_SelectAll, OnSelectAll)
-    IPC_MESSAGE_HANDLER(InputMsg_SelectRange, OnSelectRange)
     IPC_MESSAGE_HANDLER(InputMsg_SetEditCommandsForNextKeyEvent,
                         OnSetEditCommandsForNextKeyEvent)
-    IPC_MESSAGE_HANDLER(InputMsg_Undo, OnUndo)
-    IPC_MESSAGE_HANDLER(InputMsg_Unselect, OnUnselect)
     IPC_MESSAGE_HANDLER(FrameMsg_Navigate, OnNavigate)
     IPC_MESSAGE_HANDLER(ViewMsg_Stop, OnStop)
     IPC_MESSAGE_HANDLER(ViewMsg_ReloadFrame, OnReloadFrame)
     IPC_MESSAGE_HANDLER(ViewMsg_SetName, OnSetName)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetEditableSelectionOffsets,
-                        OnSetEditableSelectionOffsets)
-    IPC_MESSAGE_HANDLER(ViewMsg_SetCompositionFromExistingText,
-                        OnSetCompositionFromExistingText)
-    IPC_MESSAGE_HANDLER(ViewMsg_ExtendSelectionAndDelete,
-                        OnExtendSelectionAndDelete)
     IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
     IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
     IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
@@ -1124,7 +1111,6 @@
     IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
     IPC_MESSAGE_HANDLER(ViewMsg_SuppressDialogsUntilSwapOut,
                         OnSuppressDialogsUntilSwapOut)
-    IPC_MESSAGE_HANDLER(ViewMsg_SwapOut, OnSwapOut)
     IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
     IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
     IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
@@ -1168,7 +1154,6 @@
     IPC_MESSAGE_HANDLER(ViewMsg_PauseVideo, OnPauseVideo)
     IPC_MESSAGE_HANDLER(ViewMsg_ExtractSmartClipData, OnExtractSmartClipData)
 #elif defined(OS_MACOSX)
-    IPC_MESSAGE_HANDLER(InputMsg_CopyToFindPboard, OnCopyToFindPboard)
     IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
                         OnPluginImeCompositionCompleted)
     IPC_MESSAGE_HANDLER(ViewMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
@@ -1266,14 +1251,6 @@
   target_url_status_ = TARGET_NONE;
 }
 
-void RenderViewImpl::OnDelete() {
-  if (!webview())
-    return;
-
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Delete"),
-                                            GetFocusedElement());
-}
-
 void RenderViewImpl::OnExecuteEditCommand(const std::string& name,
     const std::string& value) {
   if (!webview() || !webview()->focusedFrame())
@@ -1292,23 +1269,6 @@
   webview()->focusedFrame()->moveCaretSelection(point);
 }
 
-void RenderViewImpl::OnPasteAndMatchStyle() {
-  if (!webview())
-    return;
-
-  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->executeCommand(
-      WebString::fromUTF8("PasteAndMatchStyle"), GetFocusedElement());
-}
-
-void RenderViewImpl::OnRedo() {
-  if (!webview())
-    return;
-
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Redo"),
-                                            GetFocusedElement());
-}
-
 void RenderViewImpl::OnReplace(const base::string16& text) {
   if (!webview())
     return;
@@ -1346,64 +1306,11 @@
   }
 }
 
-void RenderViewImpl::OnSelectAll() {
-  if (!webview())
-    return;
-
-  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->executeCommand(
-      WebString::fromUTF8("SelectAll"), GetFocusedElement());
-}
-
-void RenderViewImpl::OnSelectRange(const gfx::Point& start,
-                                   const gfx::Point& end) {
-  if (!webview())
-    return;
-
-  Send(new ViewHostMsg_SelectRange_ACK(routing_id_));
-
-  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->selectRange(start, end);
-}
-
 void RenderViewImpl::OnSetEditCommandsForNextKeyEvent(
     const EditCommands& edit_commands) {
   edit_commands_ = edit_commands;
 }
 
-void RenderViewImpl::OnUndo() {
-  if (!webview())
-    return;
-
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Undo"),
-                                            GetFocusedElement());
-}
-
-void RenderViewImpl::OnUnselect() {
-  if (!webview())
-    return;
-
-  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  webview()->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
-                                            GetFocusedElement());
-}
-
-#if defined(OS_MACOSX)
-void RenderViewImpl::OnCopyToFindPboard() {
-  if (!webview())
-    return;
-
-  // Since the find pasteboard supports only plain text, this can be simpler
-  // than the |OnCopy()| case.
-  WebFrame* frame = webview()->focusedFrame();
-  if (frame->hasSelection()) {
-    base::string16 selection = frame->selectionAsText();
-    RenderThread::Get()->Send(
-        new ClipboardHostMsg_FindPboardWriteStringAsync(selection));
-  }
-}
-#endif
-
 void RenderViewImpl::OnSetName(const std::string& name) {
   if (!webview())
     return;
@@ -1411,30 +1318,6 @@
   webview()->mainFrame()->setName(WebString::fromUTF8(name));
 }
 
-void RenderViewImpl::OnSetEditableSelectionOffsets(int start, int end) {
-  base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
-  if (!ShouldHandleImeEvent())
-    return;
-  ImeEventGuard guard(this);
-  webview()->setEditableSelectionOffsets(start, end);
-}
-
-void RenderViewImpl::OnSetCompositionFromExistingText(
-    int start, int end,
-    const std::vector<blink::WebCompositionUnderline>& underlines) {
-  if (!ShouldHandleImeEvent())
-    return;
-  ImeEventGuard guard(this);
-  webview()->setCompositionFromExistingText(start, end, underlines);
-}
-
-void RenderViewImpl::OnExtendSelectionAndDelete(int before, int after) {
-  if (!ShouldHandleImeEvent())
-    return;
-  ImeEventGuard guard(this);
-  webview()->extendSelectionAndDelete(before, after);
-}
-
 void RenderViewImpl::OnSetHistoryLengthAndPrune(int history_length,
                                                 int32 minimum_page_id) {
   DCHECK_GE(history_length, 0);
@@ -1640,7 +1523,7 @@
   params.session_storage_namespace_id = session_storage_namespace_id_;
   if (frame_name != "_blank")
     params.frame_name = frame_name;
-  params.opener_frame_id =
+  params.opener_render_frame_id =
       RenderFrameImpl::FromWebFrame(creator)->GetRoutingID();
   params.opener_url = creator->document().url();
   params.opener_top_level_frame_url = creator->top()->document().url();
@@ -1732,6 +1615,7 @@
 WebExternalPopupMenu* RenderViewImpl::createExternalPopupMenu(
     const WebPopupMenuInfo& popup_menu_info,
     WebExternalPopupMenuClient* popup_menu_client) {
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
   // An IPC message is sent to the browser to build and display the actual
   // popup.  The user could have time to click a different select by the time
   // the popup is shown.  In that case external_popup_menu_ is non NULL.
@@ -1747,6 +1631,9 @@
         external_popup_menu_.get(), screen_metrics_emulator_.get());
   }
   return external_popup_menu_.get();
+#else
+  return NULL;
+#endif
 }
 
 WebStorageNamespace* RenderViewImpl::createSessionStorageNamespace() {
@@ -1828,27 +1715,32 @@
   main_render_frame_->didStopLoading();
 }
 
-void RenderViewImpl::didStartLoading(WebFrame* frame) {
+void RenderViewImpl::FrameDidStartLoading(WebFrame* frame) {
   if (load_progress_tracker_ != NULL) {
     load_progress_tracker_->DidStartLoading(
         RenderFrameImpl::FromWebFrame(frame)->GetRoutingID());
   }
-  FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStartLoading());
+  DCHECK_GE(frames_in_progress_, 0);
+  if (frames_in_progress_ == 0)
+    FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStartLoading());
+  frames_in_progress_++;
 }
 
-void RenderViewImpl::didStopLoading(WebFrame* frame) {
+void RenderViewImpl::FrameDidStopLoading(WebFrame* frame) {
   if (load_progress_tracker_ != NULL) {
     load_progress_tracker_->DidStopLoading(
         RenderFrameImpl::FromWebFrame(frame)->GetRoutingID());
   }
-
-  DidStopLoadingIcons();
-
-  FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStopLoading());
+  frames_in_progress_--;
+  DCHECK_GE(frames_in_progress_, 0);
+  if (frames_in_progress_ == 0) {
+    DidStopLoadingIcons();
+    FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidStopLoading());
+  }
 }
 
-void RenderViewImpl::didChangeLoadProgress(WebFrame* frame,
-                                           double load_progress) {
+void RenderViewImpl::FrameDidChangeLoadProgress(WebFrame* frame,
+                                                double load_progress) {
   if (load_progress_tracker_ != NULL) {
     load_progress_tracker_->DidChangeLoadProgress(
         RenderFrameImpl::FromWebFrame(frame)->GetRoutingID(), load_progress);
@@ -1859,25 +1751,6 @@
   Send(new ViewHostMsg_ImeCancelComposition(routing_id()));
 }
 
-void RenderViewImpl::didChangeSelection(bool is_empty_selection) {
-  if (!handling_input_event_ && !handling_select_range_)
-    return;
-
-  if (is_empty_selection)
-    selection_text_.clear();
-
-  // UpdateTextInputType should be called before SyncSelectionIfRequired.
-  // UpdateTextInputType may send TextInputTypeChanged to notify the focus
-  // was changed, and SyncSelectionIfRequired may send SelectionChanged
-  // to notify the selection was changed.  Focus change should be notified
-  // before selection change.
-  UpdateTextInputType();
-  SyncSelectionIfRequired();
-#if defined(OS_ANDROID)
-  UpdateTextInputState(false, true);
-#endif
-}
-
 void RenderViewImpl::didExecuteCommand(const WebString& command_name) {
   const std::string& name = base::UTF16ToUTF8(command_name);
   if (StartsWithASCII(name, "Move", true) ||
@@ -3290,65 +3163,6 @@
   SendUpdateState(item);
 }
 
-void RenderViewImpl::SyncSelectionIfRequired() {
-  WebFrame* frame = webview()->focusedFrame();
-  if (!frame)
-    return;
-
-  base::string16 text;
-  size_t offset;
-  gfx::Range range;
-#if defined(ENABLE_PLUGINS)
-  if (focused_pepper_plugin_) {
-    focused_pepper_plugin_->GetSurroundingText(&text, &range);
-    offset = 0;  // Pepper API does not support offset reporting.
-    // TODO(kinaba): cut as needed.
-  } else
-#endif
-  {
-    size_t location, length;
-    if (!webview()->caretOrSelectionRange(&location, &length))
-      return;
-
-    range = gfx::Range(location, location + length);
-
-    if (webview()->textInputInfo().type != blink::WebTextInputTypeNone) {
-      // If current focused element is editable, we will send 100 more chars
-      // before and after selection. It is for input method surrounding text
-      // feature.
-      if (location > kExtraCharsBeforeAndAfterSelection)
-        offset = location - kExtraCharsBeforeAndAfterSelection;
-      else
-        offset = 0;
-      length = location + length - offset + kExtraCharsBeforeAndAfterSelection;
-      WebRange webrange = WebRange::fromDocumentRange(frame, offset, length);
-      if (!webrange.isNull())
-        text = WebRange::fromDocumentRange(frame, offset, length).toPlainText();
-    } else {
-      offset = location;
-      text = frame->selectionAsText();
-      // http://crbug.com/101435
-      // In some case, frame->selectionAsText() returned text's length is not
-      // equal to the length returned from webview()->caretOrSelectionRange().
-      // So we have to set the range according to text.length().
-      range.set_end(range.start() + text.length());
-    }
-  }
-
-  // Sometimes we get repeated didChangeSelection calls from webkit when
-  // the selection hasn't actually changed. We don't want to report these
-  // because it will cause us to continually claim the X clipboard.
-  if (selection_text_offset_ != offset ||
-      selection_range_ != range ||
-      selection_text_ != text) {
-    selection_text_ = text;
-    selection_text_offset_ = offset;
-    selection_range_ = range;
-    Send(new ViewHostMsg_SelectionChanged(routing_id_, text, offset, range));
-  }
-  UpdateSelectionBounds();
-}
-
 GURL RenderViewImpl::GetLoadingUrl(blink::WebFrame* frame) const {
   WebDataSource* ds = frame->dataSource();
   if (ds->hasUnreachableURL())
@@ -3690,7 +3504,12 @@
 void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) {
   if ((enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) &&
       !(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) {
+    // WebUIExtensionData deletes itself when we're destroyed.
     new WebUIExtensionData(this);
+#if defined(USE_MOJO)
+    // WebUIMojo deletes itself when we're destroyed.
+    new WebUIMojo(this);
+#endif
   }
 
   enabled_bindings_ |= enabled_bindings_flags;
@@ -3972,45 +3791,6 @@
   suppress_dialogs_until_swap_out_ = true;
 }
 
-void RenderViewImpl::OnSwapOut() {
-  // Only run unload if we're not swapped out yet, but send the ack either way.
-  if (!is_swapped_out_) {
-    // Swap this RenderView out so the tab can navigate to a page rendered by a
-    // different process.  This involves running the unload handler and clearing
-    // the page.  Once WasSwappedOut is called, we also allow this process to
-    // exit if there are no other active RenderViews in it.
-
-    // Send an UpdateState message before we get swapped out.
-    SyncNavigationState();
-
-    // Synchronously run the unload handler before sending the ACK.
-    webview()->dispatchUnloadEvent();
-
-    // Swap out and stop sending any IPC messages that are not ACKs.
-    SetSwappedOut(true);
-
-    // Now that we're swapped out and filtering IPC messages, stop loading to
-    // ensure that no other in-progress navigation continues.  We do this here
-    // to avoid sending a DidStopLoading message to the browser process.
-    OnStop();
-
-    // Replace the page with a blank dummy URL. The unload handler will not be
-    // run a second time, thanks to a check in FrameLoader::stopLoading.
-    // TODO(creis): Need to add a better way to do this that avoids running the
-    // beforeunload handler. For now, we just run it a second time silently.
-    NavigateToSwappedOutURL(webview()->mainFrame());
-
-    // Let WebKit know that this view is hidden so it can drop resources and
-    // stop compositing.
-    webview()->setVisibilityState(blink::WebPageVisibilityStateHidden, false);
-  }
-
-  // It is now safe to show modal dialogs again.
-  suppress_dialogs_until_swap_out_ = false;
-
-  Send(new ViewHostMsg_SwapOut_ACK(routing_id_));
-}
-
 void RenderViewImpl::NavigateToSwappedOutURL(blink::WebFrame* frame) {
   // We use loadRequest instead of loadHTMLString because the former commits
   // synchronously.  Otherwise a new navigation can interrupt the navigation
@@ -4187,7 +3967,7 @@
   SetBackground(background);
 }
 
-void RenderViewImpl::OnSetAccessibilityMode(unsigned int new_mode) {
+void RenderViewImpl::OnSetAccessibilityMode(AccessibilityMode new_mode) {
   if (accessibility_mode_ == new_mode)
     return;
   accessibility_mode_ = new_mode;
@@ -4198,7 +3978,7 @@
   if (accessibility_mode_ == AccessibilityModeOff)
     return;
 
-  if (accessibility_mode_ & AccessibilityModeFlagPlatformFullTree)
+  if (accessibility_mode_ & AccessibilityModeFlagFullTree)
     renderer_accessibility_ = new RendererAccessibilityComplete(this);
 #if !defined(OS_ANDROID)
   else
@@ -4909,14 +4689,8 @@
 
 #if defined(OS_MACOSX)
 void RenderViewImpl::OnSelectPopupMenuItem(int selected_index) {
-  if (external_popup_menu_ == NULL) {
-    // Crash reports from the field indicate that we can be notified with a
-    // NULL external popup menu (we probably get notified twice).
-    // If you hit this please file a bug against jcivelli and include the page
-    // and steps to repro.
-    NOTREACHED();
+  if (external_popup_menu_ == NULL)
     return;
-  }
   external_popup_menu_->DidSelectItem(selected_index);
   external_popup_menu_.reset();
 }
@@ -4938,6 +4712,14 @@
 }
 #endif
 
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+void RenderViewImpl::DidHideExternalPopupMenu() {
+  // We need to clear external_popup_menu_ as soon as ExternalPopupMenu::close
+  // is called. Otherwise, createExternalPopupMenu() for new popup will fail.
+  external_popup_menu_.reset();
+}
+#endif
+
 void RenderViewImpl::OnShowContextMenu(const gfx::Point& location) {
   context_menu_source_type_ = ui::MENU_SOURCE_TOUCH_EDIT_MENU;
   touch_editing_context_menu_location_ = location;
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 3f7a5dd..7e5c632 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -195,7 +195,7 @@
                                 bool hidden,
                                 int32 next_page_id,
                                 const blink::WebScreenInfo& screen_info,
-                                unsigned int accessibility_mode);
+                                AccessibilityMode accessibility_mode);
 
   // Used by content_layouttest_support to hook into the creation of
   // RenderViewImpls.
@@ -231,6 +231,10 @@
     return media_stream_dispatcher_;
   }
 
+  AccessibilityMode accessibility_mode() {
+    return accessibility_mode_;
+  }
+
   RendererAccessibility* renderer_accessibility() {
     return renderer_accessibility_;
   }
@@ -270,6 +274,17 @@
 #if defined(OS_ANDROID)
   void DismissDateTimeDialog();
 #endif
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+  void DidHideExternalPopupMenu();
+#endif
+
+  bool is_loading() const { return frames_in_progress_ != 0; }
+
+  void FrameDidStartLoading(blink::WebFrame* frame);
+  void FrameDidStopLoading(blink::WebFrame* frame);
+
+  void FrameDidChangeLoadProgress(blink::WebFrame* frame,
+                                  double load_progress);
 
   // Plugin-related functions --------------------------------------------------
 
@@ -426,12 +441,8 @@
   virtual void didStartLoading(bool to_different_document);
   // DEPRECATED
   virtual void didStopLoading();
-  virtual void didStartLoading(blink::WebFrame* frame);
-  virtual void didStopLoading(blink::WebFrame* frame);
-  virtual void didChangeLoadProgress(blink::WebFrame* frame,
-                                     double load_progress);
+
   virtual void didCancelCompositionOnSelectionChange();
-  virtual void didChangeSelection(bool is_selection_empty);
   virtual void didExecuteCommand(const blink::WebString& command_name);
   virtual bool handleCurrentKeyboardEvent();
   virtual blink::WebColorChooser* createColorChooser(
@@ -638,10 +649,6 @@
   virtual blink::WebView* GetWebView() OVERRIDE;
   virtual blink::WebElement GetFocusedElement() const OVERRIDE;
   virtual bool IsEditableNode(const blink::WebNode& node) const OVERRIDE;
-  virtual void EvaluateScript(const base::string16& frame_xpath,
-                              const base::string16& jscript,
-                              int id,
-                              bool notify_result) OVERRIDE;
   virtual bool ShouldDisplayScrollbars(int width, int height) const OVERRIDE;
   virtual int GetEnabledBindings() const OVERRIDE;
   virtual bool GetContentStateImmediately() const OVERRIDE;
@@ -758,8 +765,6 @@
   FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange);
   FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, NormalCase);
   FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuTest, ShowPopupThenNavigate);
-  FRIEND_TEST_ALL_PREFIXES(RendererAccessibilityTest,
-                           AccessibilityMessagesQueueWhileSwappedOut);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, DecideNavigationPolicyForWebUI);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            DidFailProvisionalLoadWithErrorForError);
@@ -771,14 +776,12 @@
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, InsertCharacters);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, JSBlockSentAfterPageLoad);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, LastCommittedUpdateState);
-  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnExtendSelectionAndDelete);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnHandleKeyboardEvent);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnImeTypeChanged);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnNavStateChanged);
+  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnSetAccessibilityMode);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnSetTextDirection);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnUpdateWebPreferences);
-  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, SendSwapOutACK);
-  FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ReloadWhileSwappedOut);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
                            SetEditableSelectionAndComposition);
   FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, StaleNavigationsIgnored);
@@ -852,24 +855,21 @@
   // Called when the "pinned to left/right edge" state needs to be updated.
   void UpdateScrollState(blink::WebFrame* frame);
 
+  void EvaluateScript(const base::string16& frame_xpath,
+                      const base::string16& jscript,
+                      int id,
+                      bool notify_result);
+
   // IPC message handlers ------------------------------------------------------
   //
   // The documentation for these functions should be in
   // content/common/*_messages.h for the message that the function is handling.
-
-  void OnDelete();
   void OnExecuteEditCommand(const std::string& name, const std::string& value);
   void OnMoveCaret(const gfx::Point& point);
-  void OnPasteAndMatchStyle();
-  void OnRedo();
   void OnReplace(const base::string16& text);
   void OnReplaceMisspelling(const base::string16& text);
   void OnScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect);
-  void OnSelectAll();
-  void OnSelectRange(const gfx::Point& start, const gfx::Point& end);
   void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands);
-  void OnUndo();
-  void OnUnselect();
   void OnAllowBindings(int enabled_bindings_flags);
   void OnAllowScriptToClose(bool script_can_close);
   void OnCancelDownload(int32 download_id);
@@ -904,7 +904,6 @@
   void OnDisableAutoResize(const gfx::Size& new_size);
   void OnEnumerateDirectoryResponse(int id,
                                     const std::vector<base::FilePath>& paths);
-  void OnExtendSelectionAndDelete(int before, int after);
   void OnFileChooserResponse(
       const std::vector<ui::SelectedFileInfo>& files);
   void OnFind(int request_id,
@@ -929,14 +928,10 @@
                            const base::string16& jscript,
                            int id,
                            bool notify_result);
-  void OnSetAccessibilityMode(unsigned int new_mode);
+  void OnSetAccessibilityMode(AccessibilityMode new_mode);
   void OnSetActive(bool active);
   void OnSetBackground(const SkBitmap& background);
-  void OnSetCompositionFromExistingText(
-      int start, int end,
-      const std::vector<blink::WebCompositionUnderline>& underlines);
   void OnExitFullscreen();
-  void OnSetEditableSelectionOffsets(int start, int end);
   void OnSetHistoryLengthAndPrune(int history_length, int32 minimum_page_id);
   void OnSetInitialFocus(bool reverse);
   void OnSetPageEncoding(const std::string& encoding_name);
@@ -947,7 +942,6 @@
   void OnStop();
   void OnStopFinding(StopFindAction action);
   void OnSuppressDialogsUntilSwapOut();
-  void OnSwapOut();
   void OnThemeChanged();
   void OnUpdateTargetURLAck();
   void OnUpdateWebPreferences(const WebPreferences& prefs);
@@ -969,7 +963,6 @@
   void OnExtractSmartClipData(const gfx::Rect& rect);
   void GetSelectionRootBounds(gfx::Rect* bounds) const;
 #elif defined(OS_MACOSX)
-  void OnCopyToFindPboard();
   void OnPluginImeCompositionCompleted(const base::string16& text,
                                        int plugin_id);
   void OnSelectPopupMenuItem(int selected_index);
@@ -1021,7 +1014,8 @@
   // RenderFrameObserver.
   void OnNavigate(const FrameMsg_Navigate_Params& params);
 
-  // Make this RenderView show an empty, unscriptable page.
+  // Make the given |frame| show an empty, unscriptable page.
+  // TODO(creis): Move this to RenderFrame.
   void NavigateToSwappedOutURL(blink::WebFrame* frame);
 
   // If we initiated a navigation, this function will populate |document_state|
@@ -1062,12 +1056,6 @@
   // Starts nav_state_sync_timer_ if it isn't already running.
   void StartNavStateSyncTimerIfNecessary();
 
-  // Dispatches the current state of selection on the webpage to the browser if
-  // it has changed.
-  // TODO(varunjain): delete this method once we figure out how to keep
-  // selection handles in sync with the webpage.
-  void SyncSelectionIfRequired();
-
 #if defined(OS_POSIX) && !defined(OS_MACOSX)
   void UpdateFontRenderingFromRendererPrefs();
 #else
@@ -1200,6 +1188,12 @@
   // process.
   int history_list_length_;
 
+  // Counter to track how many frames have sent start notifications but not
+  // stop notifications.
+  // TODO(japhet): This state will need to move to the browser process
+  // (probably WebContents) for site isolation.
+  int frames_in_progress_;
+
   // The list of page IDs for each history item this RenderView knows about.
   // Some entries may be -1 if they were rendered by other processes or were
   // restored from a previous session.  This lets us detect attempts to
@@ -1242,18 +1236,6 @@
   // The next target URL we want to send to the browser.
   GURL pending_target_url_;
 
-  // The text selection the last time DidChangeSelection got called. May contain
-  // additional characters before and after the selected text, for IMEs. The
-  // portion of this string that is the actual selected text starts at index
-  // |selection_range_.GetMin() - selection_text_offset_| and has length
-  // |selection_range_.length()|.
-  base::string16 selection_text_;
-  // The offset corresponding to the start of |selection_text_| in the document.
-  size_t selection_text_offset_;
-  // Range over the document corresponding to the actual selected text (which
-  // could correspond to a substring of |selection_text_|; see above).
-  gfx::Range selection_range_;
-
 #if defined(OS_ANDROID)
   // Cache the old top controls state constraints. Used when updating
   // current value only without altering the constraints.
@@ -1324,7 +1306,7 @@
   DevToolsAgent* devtools_agent_;
 
   // The current accessibility mode.
-  unsigned int accessibility_mode_;
+  AccessibilityMode accessibility_mode_;
 
   // Only valid if |accessibility_mode_| is anything other than
   // AccessibilityModeOff.
@@ -1415,17 +1397,15 @@
   // Shall be cleared as soon as the next key event is processed.
   EditCommands edit_commands_;
 
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
   // The external popup for the currently showing select popup.
   scoped_ptr<ExternalPopupMenu> external_popup_menu_;
+#endif
 
   // All the registered observers.  We expect this list to be small, so vector
   // is fine.
   ObserverList<RenderViewObserver> observers_;
 
-  // Used to inform didChangeSelection() when it is called in the context
-  // of handling a InputMsg_SelectRange IPC.
-  bool handling_select_range_;
-
   // Wraps the |webwidget_| as a MouseLockDispatcher::LockTarget interface.
   scoped_ptr<MouseLockDispatcher::LockTarget> webwidget_mouse_lock_target_;
 
diff --git a/content/renderer/render_view_impl_params.cc b/content/renderer/render_view_impl_params.cc
index aa1325c..54ef8af 100644
--- a/content/renderer/render_view_impl_params.cc
+++ b/content/renderer/render_view_impl_params.cc
@@ -20,7 +20,7 @@
     bool hidden,
     int32 next_page_id,
     const blink::WebScreenInfo& screen_info,
-    unsigned int accessibility_mode)
+    AccessibilityMode accessibility_mode)
     : opener_id(opener_id),
       renderer_prefs(renderer_prefs),
       webkit_prefs(webkit_prefs),
diff --git a/content/renderer/render_view_impl_params.h b/content/renderer/render_view_impl_params.h
index eabf7e6..6872dc0 100644
--- a/content/renderer/render_view_impl_params.h
+++ b/content/renderer/render_view_impl_params.h
@@ -36,7 +36,7 @@
                        bool hidden,
                        int32 next_page_id,
                        const blink::WebScreenInfo& screen_info,
-                       unsigned int accessibility_mode);
+                       AccessibilityMode accessibility_mode);
   ~RenderViewImplParams();
 
   int32 opener_id;
@@ -52,7 +52,7 @@
   bool hidden;
   int32 next_page_id;
   const blink::WebScreenInfo& screen_info;
-  unsigned int accessibility_mode;
+  AccessibilityMode accessibility_mode;
 };
 
 }  // namespace content
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 5f19a2f..ba54a00 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -69,6 +69,7 @@
 #include "ui/surface/transport_dib.h"
 
 #if defined(OS_ANDROID)
+#include <android/keycodes.h>
 #include "base/android/sys_utils.h"
 #include "content/renderer/android/synchronous_compositor_factory.h"
 #endif
@@ -185,6 +186,7 @@
   void OnShowContextMenu(ContextMenuParams* params);
 
  private:
+  void CalculateScaleAndOffset();
   void Apply(float overdraw_bottom_height,
       gfx::Rect resizer_rect, bool is_fullscreen);
 
@@ -254,8 +256,7 @@
         widget_->resizer_rect_, widget_->is_fullscreen_);
 }
 
-void RenderWidget::ScreenMetricsEmulator::Apply(
-    float overdraw_bottom_height, gfx::Rect resizer_rect, bool is_fullscreen) {
+void RenderWidget::ScreenMetricsEmulator::CalculateScaleAndOffset() {
   if (fit_to_view_) {
     DCHECK(!original_size_.IsEmpty());
 
@@ -269,17 +270,42 @@
         static_cast<float>(widget_rect_.height()) / height_with_gutter;
     float ratio = std::max(1.0f, std::max(width_ratio, height_ratio));
     scale_ = 1.f / ratio;
+
+    // Center emulated view inside available view space.
+    offset_.set_x((original_size_.width() - scale_ * widget_rect_.width()) / 2);
+    offset_.set_y(
+        (original_size_.height() - scale_ * widget_rect_.height()) / 2);
   } else {
     scale_ = 1.f;
+    offset_.SetPoint(0, 0);
+  }
+}
+
+void RenderWidget::ScreenMetricsEmulator::Apply(
+    float overdraw_bottom_height, gfx::Rect resizer_rect, bool is_fullscreen) {
+  gfx::Rect applied_widget_rect = widget_rect_;
+  if (widget_rect_.size().IsEmpty()) {
+    scale_ = 1.f;
+    offset_.SetPoint(0, 0);
+    applied_widget_rect =
+        gfx::Rect(original_view_screen_rect_.origin(), original_size_);
+  } else {
+    CalculateScaleAndOffset();
   }
 
-  // Center emulated view inside available view space.
-  offset_.set_x((original_size_.width() - scale_ * widget_rect_.width()) / 2);
-  offset_.set_y((original_size_.height() - scale_ * widget_rect_.height()) / 2);
+  if (device_rect_.size().IsEmpty()) {
+    widget_->screen_info_.rect = original_screen_info_.rect;
+    widget_->screen_info_.availableRect = original_screen_info_.availableRect;
+    widget_->window_screen_rect_ = original_window_screen_rect_;
+  } else {
+    widget_->screen_info_.rect = gfx::Rect(device_rect_.size());
+    widget_->screen_info_.availableRect = gfx::Rect(device_rect_.size());
+    widget_->window_screen_rect_ = widget_->screen_info_.availableRect;
+  }
 
-  widget_->screen_info_.rect = gfx::Rect(device_rect_.size());
-  widget_->screen_info_.availableRect = gfx::Rect(device_rect_.size());
-  widget_->screen_info_.deviceScaleFactor = device_scale_factor_;
+  float applied_device_scale_factor = device_scale_factor_ ?
+      device_scale_factor_ : original_screen_info_.deviceScaleFactor;
+  widget_->screen_info_.deviceScaleFactor = applied_device_scale_factor;
 
   // Pass three emulation parameters to the blink side:
   // - we keep the real device scale factor in compositor to produce sharp image
@@ -289,13 +315,12 @@
   widget_->SetScreenMetricsEmulationParameters(
       original_screen_info_.deviceScaleFactor, offset_, scale_);
 
-  widget_->SetDeviceScaleFactor(device_scale_factor_);
-  widget_->view_screen_rect_ = widget_rect_;
-  widget_->window_screen_rect_ = widget_->screen_info_.availableRect;
+  widget_->SetDeviceScaleFactor(applied_device_scale_factor);
+  widget_->view_screen_rect_ = applied_widget_rect;
 
   gfx::Size physical_backing_size = gfx::ToCeiledSize(gfx::ScaleSize(
       original_size_, original_screen_info_.deviceScaleFactor));
-  widget_->Resize(widget_rect_.size(), physical_backing_size,
+  widget_->Resize(applied_widget_rect.size(), physical_backing_size,
       overdraw_bottom_height, resizer_rect, is_fullscreen, NO_RESIZE_ACK);
 }
 
@@ -321,6 +346,10 @@
     const gfx::Rect& window_screen_rect) {
   original_view_screen_rect_ = view_screen_rect;
   original_window_screen_rect_ = window_screen_rect;
+  if (device_rect_.size().IsEmpty())
+    widget_->window_screen_rect_ = window_screen_rect;
+  if (widget_rect_.size().IsEmpty())
+    widget_->view_screen_rect_ = view_screen_rect;
 }
 
 void RenderWidget::ScreenMetricsEmulator::OnShowContextMenu(
@@ -552,11 +581,13 @@
   NOTREACHED();
 }
 
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
 void RenderWidget::SetExternalPopupOriginAdjustmentsForEmulation(
     ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator) {
   popup->SetOriginScaleAndOffsetForEmulation(
       emulator->scale(), emulator->offset());
 }
+#endif
 
 void RenderWidget::OnShowHostContextMenu(ContextMenuParams* params) {
   if (screen_metrics_emulator_)
@@ -878,32 +909,47 @@
   }
 #endif
 
-  // Explicitly disable antialiasing for the compositor. As of the time of
-  // this writing, the only platform that supported antialiasing for the
-  // compositor was Mac OS X, because the on-screen OpenGL context creation
-  // code paths on Windows and Linux didn't yet have multisampling support.
-  // Mac OS X essentially always behaves as though it's rendering offscreen.
-  // Multisampling has a heavy cost especially on devices with relatively low
-  // fill rate like most notebooks, and the Mac implementation would need to
-  // be optimized to resolve directly into the IOSurface shared between the
-  // GPU and browser processes. For these reasons and to avoid platform
-  // disparities we explicitly disable antialiasing.
-  blink::WebGraphicsContext3D::Attributes attributes;
-  attributes.antialias = false;
-  attributes.shareResources = true;
-  attributes.noAutomaticFlushes = true;
-  attributes.depth = false;
-  attributes.stencil = false;
-
   const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+  bool use_software = fallback;
+  if (command_line.HasSwitch(switches::kDisableGpuCompositing))
+    use_software = true;
+
   scoped_refptr<ContextProviderCommandBuffer> context_provider;
-  if (!fallback) {
+  if (!use_software) {
+    // Explicitly disable antialiasing for the compositor. As of the time of
+    // this writing, the only platform that supported antialiasing for the
+    // compositor was Mac OS X, because the on-screen OpenGL context creation
+    // code paths on Windows and Linux didn't yet have multisampling support.
+    // Mac OS X essentially always behaves as though it's rendering offscreen.
+    // Multisampling has a heavy cost especially on devices with relatively low
+    // fill rate like most notebooks, and the Mac implementation would need to
+    // be optimized to resolve directly into the IOSurface shared between the
+    // GPU and browser processes. For these reasons and to avoid platform
+    // disparities we explicitly disable antialiasing.
+    blink::WebGraphicsContext3D::Attributes attributes;
+    attributes.antialias = false;
+    attributes.shareResources = true;
+    attributes.noAutomaticFlushes = true;
+    attributes.depth = false;
+    attributes.stencil = false;
     context_provider = ContextProviderCommandBuffer::Create(
         CreateGraphicsContext3D(attributes),
         "RenderCompositor");
+    if (!context_provider.get()) {
+      // Cause the compositor to wait and try again.
+      return scoped_ptr<cc::OutputSurface>();
+    }
   }
 
   uint32 output_surface_id = next_output_surface_id_++;
+  if (command_line.HasSwitch(switches::kEnableDelegatedRenderer)) {
+    DCHECK(is_threaded_compositing_enabled_);
+    return scoped_ptr<cc::OutputSurface>(
+        new DelegatedCompositorOutputSurface(
+            routing_id(),
+            output_surface_id,
+            context_provider));
+  }
   if (!context_provider.get()) {
     if (!command_line.HasSwitch(switches::kEnableSoftwareCompositing))
       return scoped_ptr<cc::OutputSurface>();
@@ -919,16 +965,6 @@
         true));
   }
 
-  if (command_line.HasSwitch(switches::kEnableDelegatedRenderer) &&
-      !command_line.HasSwitch(switches::kDisableDelegatedRenderer)) {
-    DCHECK(is_threaded_compositing_enabled_);
-    return scoped_ptr<cc::OutputSurface>(
-        new DelegatedCompositorOutputSurface(
-            routing_id(),
-            output_surface_id,
-            context_provider,
-            scoped_ptr<cc::SoftwareOutputDevice>()));
-  }
   if (command_line.HasSwitch(cc::switches::kCompositeToMailbox)) {
     DCHECK(is_threaded_compositing_enabled_);
     cc::ResourceFormat format = cc::RGBA_8888;
@@ -1096,8 +1132,27 @@
     prevent_default = WillHandleMouseEvent(mouse_event);
   }
 
-  if (WebInputEvent::isKeyboardEventType(input_event->type))
+  if (WebInputEvent::isKeyboardEventType(input_event->type)) {
     context_menu_source_type_ = ui::MENU_SOURCE_KEYBOARD;
+#if defined(OS_ANDROID)
+    // The DPAD_CENTER key on Android has a dual semantic: (1) in the general
+    // case it should behave like a select key (i.e. causing a click if a button
+    // is focused). However, if a text field is focused (2), its intended
+    // behavior is to just show the IME and don't propagate the key.
+    // A typical use case is a web form: the DPAD_CENTER should bring up the IME
+    // when clicked on an input text field and cause the form submit if clicked
+    // when the submit button is focused, but not vice-versa.
+    // The UI layer takes care of translating DPAD_CENTER into a RETURN key,
+    // but at this point we have to swallow the event for the scenario (2).
+    const WebKeyboardEvent& key_event =
+        *static_cast<const WebKeyboardEvent*>(input_event);
+    if (key_event.nativeKeyCode == AKEYCODE_DPAD_CENTER &&
+        GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE) {
+      OnShowImeIfNeeded();
+      prevent_default = true;
+    }
+#endif
+  }
 
   if (WebInputEvent::isGestureEventType(input_event->type)) {
     const WebGestureEvent& gesture_event =
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index f725b9d..b43cfe5 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -91,27 +91,23 @@
   // Creates a WebWidget based on the popup type.
   static blink::WebWidget* CreateWebWidget(RenderWidget* render_widget);
 
-  // The compositing surface assigned by the RenderWidgetHost
-  // (or RenderViewHost). Will be gfx::kNullPluginWindow if not assigned yet,
-  // in which case we should not create any GPU command buffers with it.
-  // The routing ID assigned by the RenderProcess. Will be MSG_ROUTING_NONE if
-  // not yet assigned a view ID, in which case, the process MUST NOT send
-  // messages with this ID to the parent.
-  int32 routing_id() const {
-    return routing_id_;
-  }
-
-  int32 surface_id() const {
-    return surface_id_;
-  }
-
-  // May return NULL when the window is closing.
+  int32 routing_id() const { return routing_id_; }
+  int32 surface_id() const { return surface_id_; }
   blink::WebWidget* webwidget() const { return webwidget_; }
-
   gfx::Size size() const { return size_; }
+  float filtered_time_per_frame() const { return filtered_time_per_frame_; }
   bool has_focus() const { return has_focus_; }
   bool is_fullscreen() const { return is_fullscreen_; }
   bool is_hidden() const { return is_hidden_; }
+  bool handling_input_event() const { return handling_input_event_; }
+  // Temporary for debugging purposes...
+  bool closing() const { return closing_; }
+  bool is_swapped_out() { return is_swapped_out_; }
+  ui::MenuSourceType context_menu_source_type() {
+    return context_menu_source_type_; }
+  gfx::Point touch_editing_context_menu_location() {
+    return touch_editing_context_menu_location_;
+  }
 
   // Functions to track out-of-process frames for special notifications.
   void RegisterSwappedOutChildFrame(RenderFrameImpl* frame);
@@ -189,14 +185,13 @@
   // Notifies about a compositor frame commit operation having finished.
   virtual void DidCommitCompositorFrame();
 
-  float filtered_time_per_frame() const {
-    return filtered_time_per_frame_;
-  }
-
   // Handle common setup/teardown for handling IME events.
   void StartHandlingImeEvent();
   void FinishHandlingImeEvent();
 
+  // Returns whether we currently should handle an IME event.
+  bool ShouldHandleImeEvent();
+
   virtual void InstrumentWillBeginFrame(int frame_id) {}
   virtual void InstrumentDidBeginFrame() {}
   virtual void InstrumentDidCancelFrame() {}
@@ -204,8 +199,6 @@
 
   bool UsingSynchronousRendererCompositor() const;
 
-  bool is_swapped_out() { return is_swapped_out_; }
-
   // ScreenMetricsEmulator class manages screen emulation inside a render
   // widget. This includes resizing, placing view on the screen at desired
   // position, changing device scale factor, and scaling down the whole
@@ -238,8 +231,20 @@
   // the new value will be sent to the browser process.
   void UpdateSelectionBounds();
 
+  virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
+
   void OnShowHostContextMenu(ContextMenuParams* params);
 
+#if defined(OS_ANDROID) || defined(USE_AURA)
+  // |show_ime_if_needed| should be true iff the update may cause the ime to be
+  // displayed, e.g. after a tap on an input field on mobile.
+  // |send_ime_ack| should be true iff the browser side is required to
+  // acknowledge the change before the renderer handles any more IME events.
+  // This is when the event did not originate from the browser side IME, such as
+  // changes from JavaScript or autofill.
+  void UpdateTextInputState(bool show_ime_if_needed, bool send_ime_ack);
+#endif
+
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(USE_AURA)
   // Checks if the composition range or composition character bounds have been
   // changed. If they are changed, the new value will be sent to the browser
@@ -247,15 +252,6 @@
   void UpdateCompositionInfo(bool should_update_range);
 #endif
 
-  // Temporary for debugging purposes...
-  bool closing() const { return closing_; }
-
-  ui::MenuSourceType context_menu_source_type() {
-    return context_menu_source_type_; }
-  gfx::Point touch_editing_context_menu_location() {
-    return touch_editing_context_menu_location_;
-  }
-
  protected:
   // Friend RefCounted so that the dtor can be non-public. Using this class
   // without ref-counting is an error.
@@ -331,8 +327,10 @@
       float device_scale_factor,
       const gfx::Point& root_layer_offset,
       float root_layer_scale);
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
   void SetExternalPopupOriginAdjustmentsForEmulation(
       ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator);
+#endif
 
   // RenderWidget IPC message handlers
   void OnHandleInputEvent(const blink::WebInputEvent* event,
@@ -382,8 +380,6 @@
   // Called by the browser process for every required IME acknowledgement.
   void OnImeEventAck();
 #endif
-  // Returns whether we currently should handle an IME event.
-  bool ShouldHandleImeEvent();
 
   void OnSnapshot(const gfx::Rect& src_subrect);
 
@@ -448,20 +444,9 @@
   void set_next_paint_is_restore_ack();
   void set_next_paint_is_repaint_ack();
 
-#if defined(OS_ANDROID) || defined(USE_AURA)
-  // |show_ime_if_needed| should be true iff the update may cause the ime to be
-  // displayed, e.g. after a tap on an input field on mobile.
-  // |send_ime_ack| should be true iff the browser side is required to
-  // acknowledge the change before the renderer handles any more IME events.
-  // This is when the event did not originate from the browser side IME, such as
-  // changes from JavaScript or autofill.
-  void UpdateTextInputState(bool show_ime_if_needed, bool send_ime_ack);
-#endif
-
   // Override point to obtain that the current input method state and caret
   // position.
   virtual ui::TextInputType GetTextInputType();
-  virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
   virtual ui::TextInputType WebKitToUiTextInputType(
       blink::WebTextInputType type);
 
@@ -557,6 +542,7 @@
   int32 surface_id_;
 
   // We are responsible for destroying this object via its Close method.
+  // May be NULL when the window is closing.
   blink::WebWidget* webwidget_;
 
   // This is lazily constructed and must not outlive webwidget_.
diff --git a/content/renderer/renderer_main.cc b/content/renderer/renderer_main.cc
index def189a..bc538fd 100644
--- a/content/renderer/renderer_main.cc
+++ b/content/renderer/renderer_main.cc
@@ -226,9 +226,9 @@
     } else {
       LOG(ERROR) << "Running without renderer sandbox";
 #ifndef NDEBUG
-      // For convenience, we print the stack trace for crashes. We can't get
-      // symbols when the sandbox is enabled, so only try when the sandbox is
-      // disabled.
+      // For convenience, we print the stack traces for crashes.  When sandbox
+      // is enabled, the in-process stack dumping is enabled as part of the
+      // EnableSandbox() call.
       base::debug::EnableInProcessStackDumping();
 #endif
     }
diff --git a/content/renderer/renderer_main_platform_delegate_win.cc b/content/renderer/renderer_main_platform_delegate_win.cc
index 58fce15..f907a19 100644
--- a/content/renderer/renderer_main_platform_delegate_win.cc
+++ b/content/renderer/renderer_main_platform_delegate_win.cc
@@ -8,13 +8,17 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
+#include "base/win/scoped_comptr.h"
 #include "base/win/win_util.h"
+#include "base/win/windows_version.h"
+#include "content/common/sandbox_win.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/injection_test_win.h"
 #include "content/public/renderer/render_thread.h"
 #include "content/renderer/render_thread_impl.h"
 #include "sandbox/win/src/sandbox.h"
 #include "skia/ext/vector_platform_device_emf_win.h"
+#include "third_party/WebKit/public/web/win/WebFontRendering.h"
 #include "third_party/icu/source/i18n/unicode/timezone.h"
 #include "third_party/skia/include/ports/SkTypeface_win.h"
 
@@ -22,10 +26,13 @@
 #include "v8/src/third_party/vtune/v8-vtune.h"
 #endif
 
+#include <dwrite.h>
+
 namespace content {
 namespace {
 
 // Windows-only skia sandbox support
+// These are used for GDI-path rendering.
 void SkiaPreCacheFont(const LOGFONT& logfont) {
   RenderThread* render_thread = RenderThread::Get();
   if (render_thread) {
@@ -44,6 +51,51 @@
   }
 }
 
+// Windows-only DirectWrite support. These warm up the DirectWrite paths
+// before sandbox lock down to allow Skia access to the Font Manager service.
+bool CreateDirectWriteFactory(IDWriteFactory** factory) {
+  typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
+  DWriteCreateFactoryProc dwrite_create_factory_proc =
+      reinterpret_cast<DWriteCreateFactoryProc>(
+          GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
+  if (!dwrite_create_factory_proc)
+    return false;
+  CHECK(SUCCEEDED(
+      dwrite_create_factory_proc(DWRITE_FACTORY_TYPE_SHARED,
+                                 __uuidof(IDWriteFactory),
+                                 reinterpret_cast<IUnknown**>(factory))));
+  return true;
+}
+
+void WarmupDirectWrite() {
+  base::win::ScopedComPtr<IDWriteFactory> factory;
+  if (!CreateDirectWriteFactory(factory.Receive()))
+    return;
+
+  base::win::ScopedComPtr<IDWriteFontCollection> font_collection;
+  CHECK(SUCCEEDED(
+      factory->GetSystemFontCollection(font_collection.Receive(), FALSE)));
+  base::win::ScopedComPtr<IDWriteFontFamily> font_family;
+
+  UINT32 index;
+  BOOL exists;
+  CHECK(SUCCEEDED(
+      font_collection->FindFamilyName(L"Times New Roman", &index, &exists)));
+  CHECK(exists);
+  CHECK(
+      SUCCEEDED(font_collection->GetFontFamily(index, font_family.Receive())));
+  base::win::ScopedComPtr<IDWriteFont> font;
+  base::win::ScopedComPtr<IDWriteFontFace> font_face;
+  CHECK(SUCCEEDED(font_family->GetFirstMatchingFont(DWRITE_FONT_WEIGHT_NORMAL,
+                                                    DWRITE_FONT_STRETCH_NORMAL,
+                                                    DWRITE_FONT_STYLE_NORMAL,
+                                                    font.Receive())));
+  CHECK(SUCCEEDED(font->CreateFontFace(font_face.Receive())));
+  DWRITE_GLYPH_METRICS gm;
+  UINT16 glyph = L'S';
+  CHECK(SUCCEEDED(font_face->GetDesignGlyphMetrics(&glyph, 1, &gm)));
+}
+
 }  // namespace
 
 RendererMainPlatformDelegate::RendererMainPlatformDelegate(
@@ -67,6 +119,7 @@
   // malicious code if the renderer gets compromised.
   bool no_sandbox = command_line.HasSwitch(switches::kNoSandbox);
 
+  bool use_direct_write = ShouldUseDirectWrite();
   if (!no_sandbox) {
     // ICU DateFormat class (used in base/time_format.cc) needs to get the
     // Olson timezone ID by accessing the registry keys under
@@ -75,10 +128,17 @@
     // cached and there's no more need to access the registry. If the sandbox
     // is disabled, we don't have to make this dummy call.
     scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
-    SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont);
-    skia::SetSkiaEnsureTypefaceCharactersAccessible(
-        SkiaPreCacheFontCharacters);
+
+    if (use_direct_write) {
+      WarmupDirectWrite();
+    } else {
+      SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont);
+      skia::SetSkiaEnsureTypefaceCharactersAccessible(
+          SkiaPreCacheFontCharacters);
+    }
   }
+  blink::WebFontRendering::setUseDirectWrite(use_direct_write);
+  blink::WebFontRendering::setUseSubpixelPositioning(use_direct_write);
 }
 
 void RendererMainPlatformDelegate::PlatformUninitialize() {
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.cc b/content/renderer/renderer_webkitplatformsupport_impl.cc
index 8ccd60a..6e8d083 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.cc
+++ b/content/renderer/renderer_webkitplatformsupport_impl.cc
@@ -120,6 +120,7 @@
 using blink::WebDatabaseObserver;
 using blink::WebFileInfo;
 using blink::WebFileSystem;
+using blink::WebGamepad;
 using blink::WebGamepads;
 using blink::WebIDBFactory;
 using blink::WebMIDIAccessor;
@@ -136,6 +137,7 @@
 namespace content {
 
 static bool g_sandbox_enabled = true;
+static blink::WebGamepadListener* web_gamepad_listener = NULL;
 base::LazyInstance<WebGamepads>::Leaky g_test_gamepads =
     LAZY_INSTANCE_INITIALIZER;
 base::LazyInstance<blink::WebDeviceMotionData>::Leaky
@@ -287,7 +289,7 @@
       GetContentClient()->renderer()->OverrideThemeEngine();
   if (theme_engine)
     return theme_engine;
-  return WebKitPlatformSupportImpl::themeEngine();
+  return BlinkPlatformImpl::themeEngine();
 }
 
 bool RendererWebKitPlatformSupportImpl::sandboxEnabled() {
@@ -797,14 +799,6 @@
 
 //------------------------------------------------------------------------------
 
-blink::WebContentDecryptionModule*
-RendererWebKitPlatformSupportImpl::createContentDecryptionModule(
-    const blink::WebString& key_system) {
-  return WebContentDecryptionModuleImpl::Create(key_system);
-}
-
-//------------------------------------------------------------------------------
-
 blink::WebMIDIAccessor*
 RendererWebKitPlatformSupportImpl::createMIDIAccessor(
     blink::WebMIDIAccessorClient* client) {
@@ -915,6 +909,11 @@
   }
 }
 
+void RendererWebKitPlatformSupportImpl::setGamepadListener(
+      blink::WebGamepadListener* listener) {
+  web_gamepad_listener = listener;
+}
+
 //------------------------------------------------------------------------------
 
 WebRTCPeerConnectionHandler*
@@ -966,6 +965,22 @@
   g_test_gamepads.Get() = pads;
 }
 
+// static
+void RendererWebKitPlatformSupportImpl::MockGamepadConnected(
+    int index,
+    const WebGamepad& pad) {
+  if (web_gamepad_listener)
+    web_gamepad_listener->didConnectGamepad(index, pad);
+}
+
+// static
+void RendererWebKitPlatformSupportImpl::MockGamepadDisconnected(
+    int index,
+    const WebGamepad& pad) {
+  if (web_gamepad_listener)
+    web_gamepad_listener->didDisconnectGamepad(index, pad);
+}
+
 //------------------------------------------------------------------------------
 
 blink::WebSpeechSynthesizer*
diff --git a/content/renderer/renderer_webkitplatformsupport_impl.h b/content/renderer/renderer_webkitplatformsupport_impl.h
index 4d3e342..093ec44 100644
--- a/content/renderer/renderer_webkitplatformsupport_impl.h
+++ b/content/renderer/renderer_webkitplatformsupport_impl.h
@@ -8,7 +8,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/platform_file.h"
-#include "content/child/webkitplatformsupport_impl.h"
+#include "content/child/blink_platform_impl.h"
 #include "content/common/content_export.h"
 #include "content/renderer/webpublicsuffixlist_impl.h"
 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
@@ -46,7 +46,7 @@
 class WebFileSystemImpl;
 
 class CONTENT_EXPORT RendererWebKitPlatformSupportImpl
-    : public WebKitPlatformSupportImpl {
+    : public BlinkPlatformImpl {
  public:
   RendererWebKitPlatformSupportImpl();
   virtual ~RendererWebKitPlatformSupportImpl();
@@ -120,13 +120,12 @@
       blink::WebAudioBus* destination_bus, const char* audio_file_data,
       size_t data_size);
 
-  virtual blink::WebContentDecryptionModule* createContentDecryptionModule(
-      const blink::WebString& key_system);
   virtual blink::WebMIDIAccessor*
       createMIDIAccessor(blink::WebMIDIAccessorClient* client);
 
   virtual blink::WebBlobRegistry* blobRegistry();
-  virtual void sampleGamepads(blink::WebGamepads&);
+  virtual void sampleGamepads(blink::WebGamepads&) OVERRIDE;
+  virtual void setGamepadListener(blink::WebGamepadListener*) OVERRIDE;
   virtual blink::WebRTCPeerConnectionHandler* createRTCPeerConnectionHandler(
       blink::WebRTCPeerConnectionHandlerClient* client);
   virtual blink::WebMediaStreamCenter* createMediaStreamCenter(
@@ -169,6 +168,15 @@
 
   // Set WebGamepads to return when sampleGamepads() is invoked.
   static void SetMockGamepadsForTesting(const blink::WebGamepads& pads);
+
+  // Notifies blink::WebGamepadListener about a new gamepad if a listener
+  // has been set via setGamepadListener.
+  static void MockGamepadConnected(int index, const blink::WebGamepad& pad);
+
+  // Notifies blink::WebGamepadListener that a gamepad has been disconnected if
+  // a listener has been set via setGamepadListener.
+  static void MockGamepadDisconnected(int index, const blink::WebGamepad& pad);
+
   // Set WebDeviceMotionData to return when setDeviceMotionListener is invoked.
   static void SetMockDeviceMotionDataForTesting(
       const blink::WebDeviceMotionData& data);
diff --git a/content/renderer/resource_fetcher_browsertest.cc b/content/renderer/resource_fetcher_browsertest.cc
index 03efe3f..667bacf 100644
--- a/content/renderer/resource_fetcher_browsertest.cc
+++ b/content/renderer/resource_fetcher_browsertest.cc
@@ -13,10 +13,10 @@
 #include "content/public/common/content_switches.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/renderer/render_view.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "third_party/WebKit/public/platform/WebURLResponse.h"
 #include "third_party/WebKit/public/web/WebFrame.h"
 #include "third_party/WebKit/public/web/WebView.h"
diff --git a/content/renderer/resources/media/mediaplayer_remote_playback.png b/content/renderer/resources/media/mediaplayer_remote_playback.png
deleted file mode 100644
index 6916ce6..0000000
--- a/content/renderer/resources/media/mediaplayer_remote_playback.png
+++ /dev/null
Binary files differ
diff --git a/content/renderer/savable_resources_browsertest.cc b/content/renderer/savable_resources_browsertest.cc
index aa7b728..344dbe4 100644
--- a/content/renderer/savable_resources_browsertest.cc
+++ b/content/renderer/savable_resources_browsertest.cc
@@ -8,10 +8,10 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/render_view.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/renderer/savable_resources.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "net/base/net_util.h"
 
 namespace content {
diff --git a/content/renderer/service_worker/embedded_worker_context_client.cc b/content/renderer/service_worker/embedded_worker_context_client.cc
index c0e1191..56fa30c 100644
--- a/content/renderer/service_worker/embedded_worker_context_client.cc
+++ b/content/renderer/service_worker/embedded_worker_context_client.cc
@@ -120,9 +120,11 @@
                  embedded_worker_id_));
 }
 
-void EmbeddedWorkerContextClient::didHandleInstallEvent(int request_id) {
+void EmbeddedWorkerContextClient::didHandleInstallEvent(
+    int request_id,
+    blink::WebServiceWorkerEventResult result) {
   DCHECK(script_context_);
-  script_context_->DidHandleInstallEvent(request_id);
+  script_context_->DidHandleInstallEvent(request_id, result);
 }
 
 void EmbeddedWorkerContextClient::didHandleFetchEvent(int request_id) {
diff --git a/content/renderer/service_worker/embedded_worker_context_client.h b/content/renderer/service_worker/embedded_worker_context_client.h
index 1f7a9fd..67b0ef2 100644
--- a/content/renderer/service_worker/embedded_worker_context_client.h
+++ b/content/renderer/service_worker/embedded_worker_context_client.h
@@ -10,6 +10,7 @@
 #include "base/strings/string16.h"
 #include "content/common/service_worker/service_worker_types.h"
 #include "ipc/ipc_listener.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerEventResult.h"
 #include "third_party/WebKit/public/web/WebServiceWorkerContextClient.h"
 #include "url/gurl.h"
 
@@ -55,7 +56,8 @@
   virtual void workerContextFailedToStart();
   virtual void workerContextStarted(blink::WebServiceWorkerContextProxy* proxy);
   virtual void workerContextDestroyed();
-  virtual void didHandleInstallEvent(int request_id);
+  virtual void didHandleInstallEvent(int request_id,
+                                     blink::WebServiceWorkerEventResult result);
   virtual void didHandleFetchEvent(int request_id);
   virtual void didHandleFetchEvent(
       int request_id,
@@ -64,6 +66,9 @@
   // TODO: Implement DevTools related method overrides.
 
   int embedded_worker_id() const { return embedded_worker_id_; }
+  base::MessageLoopProxy* main_thread_proxy() const {
+    return main_thread_proxy_;
+  }
 
  private:
   void OnSendMessageToWorker(int thread_id,
diff --git a/content/renderer/service_worker/service_worker_script_context.cc b/content/renderer/service_worker/service_worker_script_context.cc
index 4773ed5..2043e78 100644
--- a/content/renderer/service_worker/service_worker_script_context.cc
+++ b/content/renderer/service_worker/service_worker_script_context.cc
@@ -5,6 +5,7 @@
 #include "content/renderer/service_worker/service_worker_script_context.h"
 
 #include "base/logging.h"
+#include "content/child/webmessageportchannel_impl.h"
 #include "content/common/service_worker/service_worker_messages.h"
 #include "content/renderer/service_worker/embedded_worker_context_client.h"
 #include "ipc/ipc_message.h"
@@ -31,14 +32,17 @@
   IPC_BEGIN_MESSAGE_MAP(ServiceWorkerScriptContext, message)
     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEvent)
     IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEvent)
+    IPC_MESSAGE_HANDLER(ServiceWorkerMsg_Message, OnPostMessage)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   DCHECK(handled);
   current_request_id_ = kInvalidServiceWorkerRequestId;
 }
 
-void ServiceWorkerScriptContext::DidHandleInstallEvent(int request_id) {
-  Send(request_id, ServiceWorkerHostMsg_InstallEventFinished());
+void ServiceWorkerScriptContext::DidHandleInstallEvent(
+    int request_id,
+    blink::WebServiceWorkerEventResult result) {
+  Send(request_id, ServiceWorkerHostMsg_InstallEventFinished(result));
 }
 
 void ServiceWorkerScriptContext::DidHandleFetchEvent(
@@ -53,8 +57,7 @@
   embedded_context_->SendMessageToBrowser(request_id, message);
 }
 
-void ServiceWorkerScriptContext::OnInstallEvent(
-    int active_version_embedded_worker_id) {
+void ServiceWorkerScriptContext::OnInstallEvent(int active_version_id) {
   proxy_->dispatchInstallEvent(current_request_id_);
 }
 
@@ -64,4 +67,21 @@
   proxy_->dispatchFetchEvent(current_request_id_);
 }
 
+void ServiceWorkerScriptContext::OnPostMessage(
+    const base::string16& message,
+    const std::vector<int>& sent_message_port_ids,
+    const std::vector<int>& new_routing_ids) {
+  std::vector<WebMessagePortChannelImpl*> ports;
+  if (!sent_message_port_ids.empty()) {
+    base::MessageLoopProxy* loop_proxy = embedded_context_->main_thread_proxy();
+    ports.resize(sent_message_port_ids.size());
+    for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
+      ports[i] = new WebMessagePortChannelImpl(
+          new_routing_ids[i], sent_message_port_ids[i], loop_proxy);
+    }
+  }
+
+  proxy_->dispatchMessageEvent(message, ports);
+}
+
 }  // namespace content
diff --git a/content/renderer/service_worker/service_worker_script_context.h b/content/renderer/service_worker/service_worker_script_context.h
index eafe16f..1a90ceb 100644
--- a/content/renderer/service_worker/service_worker_script_context.h
+++ b/content/renderer/service_worker/service_worker_script_context.h
@@ -5,9 +5,13 @@
 #ifndef CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_CONTEXT_H_
 #define CONTENT_RENDERER_SERVICE_WORKER_SERVICE_WORKER_SCRIPT_CONTEXT_H_
 
+#include <vector>
+
 #include "base/basictypes.h"
+#include "base/strings/string16.h"
 
 #include "content/common/service_worker/service_worker_types.h"
+#include "third_party/WebKit/public/platform/WebServiceWorkerEventResult.h"
 
 namespace blink {
 class WebServiceWorkerContextProxy;
@@ -34,7 +38,8 @@
 
   void OnMessageReceived(int request_id, const IPC::Message& message);
 
-  void DidHandleInstallEvent(int request_id);
+  void DidHandleInstallEvent(int request_id,
+                             blink::WebServiceWorkerEventResult result);
   void DidHandleFetchEvent(int request_id,
                            ServiceWorkerFetchEventResult result,
                            const ServiceWorkerResponse& response);
@@ -43,8 +48,11 @@
   // Send message back to the browser.
   void Send(int request_id, const IPC::Message& message);
 
-  void OnInstallEvent(int active_version_embedded_worker_id);
+  void OnInstallEvent(int active_version_id);
   void OnFetchEvent(const ServiceWorkerFetchRequest& request);
+  void OnPostMessage(const base::string16& message,
+                     const std::vector<int>& sent_message_port_ids,
+                     const std::vector<int>& new_routing_ids);
 
   // Not owned; embedded_context_ owns this.
   EmbeddedWorkerContextClient* embedded_context_;
@@ -52,7 +60,9 @@
   // Not owned; this object is destroyed when proxy_ becomes invalid.
   blink::WebServiceWorkerContextProxy* proxy_;
 
-  // Used by message handlers.
+  // Used for incoming messages from the browser for which an outgoing response
+  // back to the browser is expected, the id must be sent back with the
+  // response.
   int current_request_id_;
 
   DISALLOW_COPY_AND_ASSIGN(ServiceWorkerScriptContext);
diff --git a/content/renderer/skia_benchmarking_extension_unittest.cc b/content/renderer/skia_benchmarking_extension_unittest.cc
index c9f4e90..b21c973 100644
--- a/content/renderer/skia_benchmarking_extension_unittest.cc
+++ b/content/renderer/skia_benchmarking_extension_unittest.cc
@@ -50,7 +50,7 @@
                                      SkIntToScalar(50), SkIntToScalar(50));
 
   // Draw a trivial scene.
-  canvas.save(SkCanvas::kMatrixClip_SaveFlag);
+  canvas.save();
   canvas.clipRect(fullRect, SkRegion::kIntersect_Op, false);
   canvas.translate(SkIntToScalar(10), SkIntToScalar(10));
   canvas.scale(SkIntToScalar(2), SkIntToScalar(2));
diff --git a/content/renderer/web_preferences.cc b/content/renderer/web_preferences.cc
index a188af2..3555116 100644
--- a/content/renderer/web_preferences.cc
+++ b/content/renderer/web_preferences.cc
@@ -325,8 +325,6 @@
   settings->setDoubleTapToZoomEnabled(prefs.double_tap_to_zoom_enabled);
   settings->setMediaPlaybackRequiresUserGesture(
       prefs.user_gesture_required_for_media_playback);
-  settings->setMediaFullscreenRequiresUserGesture(
-      prefs.user_gesture_required_for_media_fullscreen);
   settings->setDefaultVideoPosterURL(
         base::ASCIIToUTF16(prefs.default_video_poster_url.spec()));
   settings->setSupportDeprecatedTargetDensityDPI(
diff --git a/content/renderer/web_ui_mojo.cc b/content/renderer/web_ui_mojo.cc
index 04712e2..58f67a8 100644
--- a/content/renderer/web_ui_mojo.cc
+++ b/content/renderer/web_ui_mojo.cc
@@ -41,21 +41,26 @@
   web_ui_mojo_->DestroyContextState(context);
 }
 
+void WebUIMojo::MainFrameObserver::DidFinishDocumentLoad() {
+  web_ui_mojo_->OnDidFinishDocumentLoad();
+}
+
 WebUIMojo::WebUIMojo(RenderView* render_view)
     : RenderViewObserver(render_view),
       RenderViewObserverTracker<WebUIMojo>(render_view),
-      main_frame_observer_(this) {
+      main_frame_observer_(this),
+      did_finish_document_load_(false) {
   CreateContextState();
 }
 
-WebUIMojo::~WebUIMojo() {
+void WebUIMojo::SetBrowserHandle(mojo::ScopedMessagePipeHandle handle) {
+  if (did_finish_document_load_)
+    SetHandleOnContextState(handle.Pass());
+  else
+    pending_handle_ = handle.Pass();
 }
 
-void WebUIMojo::OnSetBrowserHandle(MojoHandle handle) {
-  v8::HandleScope handle_scope(blink::mainThreadIsolate());
-  WebUIMojoContextState* state = GetContextState();
-  if (state)
-    state->SetHandle(mojo::MakeScopedHandle(mojo::Handle(handle)));
+WebUIMojo::~WebUIMojo() {
 }
 
 void WebUIMojo::CreateContextState() {
@@ -76,6 +81,20 @@
   context_data->RemoveUserData(kWebUIMojoContextStateKey);
 }
 
+void WebUIMojo::OnDidFinishDocumentLoad() {
+  did_finish_document_load_ = true;
+  if (pending_handle_.is_valid())
+    SetHandleOnContextState(pending_handle_.Pass());
+}
+
+void WebUIMojo::SetHandleOnContextState(mojo::ScopedMessagePipeHandle handle) {
+  DCHECK(did_finish_document_load_);
+  v8::HandleScope handle_scope(blink::mainThreadIsolate());
+  WebUIMojoContextState* state = GetContextState();
+  if (state)
+    state->SetHandle(handle.Pass());
+}
+
 WebUIMojoContextState* WebUIMojo::GetContextState() {
   blink::WebFrame* frame = render_view()->GetWebView()->mainFrame();
   v8::HandleScope handle_scope(blink::mainThreadIsolate());
diff --git a/content/renderer/web_ui_mojo.h b/content/renderer/web_ui_mojo.h
index 5b9e591..d9a7f00 100644
--- a/content/renderer/web_ui_mojo.h
+++ b/content/renderer/web_ui_mojo.h
@@ -10,7 +10,7 @@
 #include "content/public/renderer/render_frame_observer.h"
 #include "content/public/renderer/render_view_observer.h"
 #include "content/public/renderer/render_view_observer_tracker.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace gin {
 class PerContextData;
@@ -30,6 +30,9 @@
  public:
   explicit WebUIMojo(RenderView* render_view);
 
+  // Sets the handle to the current WebUI.
+  void SetBrowserHandle(mojo::ScopedMessagePipeHandle handle);
+
  private:
   class MainFrameObserver : public RenderFrameObserver {
    public:
@@ -39,6 +42,7 @@
     // RenderFrameObserver overrides:
     virtual void WillReleaseScriptContext(v8::Handle<v8::Context> context,
                                           int world_id) OVERRIDE;
+    virtual void DidFinishDocumentLoad() OVERRIDE;
 
    private:
     WebUIMojo* web_ui_mojo_;
@@ -48,13 +52,16 @@
 
   virtual ~WebUIMojo();
 
-  // Invoked from ViewMsg_SetBrowserHandle. Passes handle to current
-  // MojoWebUIContextState.
-  void OnSetBrowserHandle(MojoHandle handle);
-
   void CreateContextState();
   void DestroyContextState(v8::Handle<v8::Context> context);
 
+  // Invoked when the frame finishes loading. Invokes SetHandleOnContextState()
+  // if necessary.
+  void OnDidFinishDocumentLoad();
+
+  // Invokes SetHandle() on the WebUIMojoContextState (if there is one).
+  void SetHandleOnContextState(mojo::ScopedMessagePipeHandle handle);
+
   WebUIMojoContextState* GetContextState();
 
   // RenderViewObserver overrides:
@@ -63,6 +70,16 @@
 
   MainFrameObserver main_frame_observer_;
 
+  // Set to true in DidFinishDocumentLoad(). 'main' is only executed once this
+  // happens.
+  bool did_finish_document_load_;
+
+  // If SetBrowserHandle() is invoked before the document finishes loading the
+  // MessagePipeHandle is stored here. When the document finishes loading
+  // SetHandleOnContextState() is invoked to send the handle to the
+  // WebUIMojoContextState and ultimately the page.
+  mojo::ScopedMessagePipeHandle pending_handle_;
+
   DISALLOW_COPY_AND_ASSIGN(WebUIMojo);
 };
 
diff --git a/content/renderer/web_ui_mojo_context_state.cc b/content/renderer/web_ui_mojo_context_state.cc
index 0c8ab24..18c61fa 100644
--- a/content/renderer/web_ui_mojo_context_state.cc
+++ b/content/renderer/web_ui_mojo_context_state.cc
@@ -35,7 +35,7 @@
 const char kModulePrefix[] = "chrome://mojo/";
 
 void RunMain(base::WeakPtr<gin::Runner> runner,
-             mojo::ScopedHandle* handle,
+             mojo::ScopedMessagePipeHandle* handle,
              v8::Handle<v8::Value> module) {
   v8::Isolate* isolate = runner->GetContextHolder()->isolate();
   v8::Handle<v8::Function> start;
@@ -70,9 +70,10 @@
       runner_->GetContextHolder()->context())->RemoveObserver(this);
 }
 
-void WebUIMojoContextState::SetHandle(mojo::ScopedHandle handle) {
+void WebUIMojoContextState::SetHandle(mojo::ScopedMessagePipeHandle handle) {
   gin::ContextHolder* context_holder = runner_->GetContextHolder();
-  mojo::ScopedHandle* passed_handle = new mojo::ScopedHandle(handle.Pass());
+  mojo::ScopedMessagePipeHandle* passed_handle =
+      new mojo::ScopedMessagePipeHandle(handle.Pass());
   gin::ModuleRegistry::From(context_holder->context())->LoadModule(
       context_holder->isolate(),
       "main",
@@ -112,7 +113,7 @@
   DCHECK_EQ(kModulePrefix,
       response.url().string().utf8().substr(0, arraysize(kModulePrefix) - 1));
   const std::string module =
-      response.url().string().utf8().substr(arraysize(kModulePrefix));
+      response.url().string().utf8().substr(arraysize(kModulePrefix) - 1);
   // We can't delete fetch right now as the arguments to this function come from
   // it and are used below. Instead use a scope_ptr to cleanup.
   scoped_ptr<ResourceFetcher> deleter(fetcher);
diff --git a/content/renderer/web_ui_mojo_context_state.h b/content/renderer/web_ui_mojo_context_state.h
index 21b2f7e..e4eb0a4 100644
--- a/content/renderer/web_ui_mojo_context_state.h
+++ b/content/renderer/web_ui_mojo_context_state.h
@@ -11,7 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "gin/modules/module_registry_observer.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "v8/include/v8.h"
 
 namespace blink {
@@ -39,7 +39,7 @@
   virtual ~WebUIMojoContextState();
 
   // Called once the mojo::Handle is available.
-  void SetHandle(mojo::ScopedHandle handle);
+  void SetHandle(mojo::ScopedMessagePipeHandle handle);
 
   // Returns true if at least one module was added.
   bool module_added() const { return module_added_; }
diff --git a/content/result_codes_java.target.darwin-arm.mk b/content/result_codes_java.target.darwin-arm.mk
index 00fc473..226fd02 100644
--- a/content/result_codes_java.target.darwin-arm.mk
+++ b/content/result_codes_java.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/result_codes_java.target.darwin-mips.mk b/content/result_codes_java.target.darwin-mips.mk
index 23fdbf0..ced900b 100644
--- a/content/result_codes_java.target.darwin-mips.mk
+++ b/content/result_codes_java.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/result_codes_java.target.darwin-x86.mk b/content/result_codes_java.target.darwin-x86.mk
index 2c6b6c0..21bd3df 100644
--- a/content/result_codes_java.target.darwin-x86.mk
+++ b/content/result_codes_java.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/result_codes_java.target.darwin-x86_64.mk b/content/result_codes_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..f69828b
--- /dev/null
+++ b/content/result_codes_java.target.darwin-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_result_codes_java_gyp
+LOCAL_MODULE_STEM := result_codes_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_result_codes_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" "--template=public/android/java/src/org/chromium/content/common/ResultCodes.template"
+
+.PHONY: content_result_codes_java_gyp_rule_trigger
+content_result_codes_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_result_codes_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_result_codes_java_gyp
+
+# Alias gyp target name.
+.PHONY: result_codes_java
+result_codes_java: content_result_codes_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/result_codes_java.target.linux-arm.mk b/content/result_codes_java.target.linux-arm.mk
index 00fc473..226fd02 100644
--- a/content/result_codes_java.target.linux-arm.mk
+++ b/content/result_codes_java.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/result_codes_java.target.linux-mips.mk b/content/result_codes_java.target.linux-mips.mk
index 23fdbf0..ced900b 100644
--- a/content/result_codes_java.target.linux-mips.mk
+++ b/content/result_codes_java.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/result_codes_java.target.linux-x86.mk b/content/result_codes_java.target.linux-x86.mk
index 2c6b6c0..21bd3df 100644
--- a/content/result_codes_java.target.linux-x86.mk
+++ b/content/result_codes_java.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/result_codes_java.target.linux-x86_64.mk b/content/result_codes_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..f69828b
--- /dev/null
+++ b/content/result_codes_java.target.linux-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_result_codes_java_gyp
+LOCAL_MODULE_STEM := result_codes_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_result_codes_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/result_codes_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ResultCodes.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ResultCodes.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/result_codes_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java" "--template=public/android/java/src/org/chromium/content/common/ResultCodes.template"
+
+.PHONY: content_result_codes_java_gyp_rule_trigger
+content_result_codes_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ResultCodes.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_result_codes_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_result_codes_java_gyp
+
+# Alias gyp target name.
+.PHONY: result_codes_java
+result_codes_java: content_result_codes_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/screen_orientation_values_java.target.darwin-arm.mk b/content/screen_orientation_values_java.target.darwin-arm.mk
index f8d8fef..e44e79d 100644
--- a/content/screen_orientation_values_java.target.darwin-arm.mk
+++ b/content/screen_orientation_values_java.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/screen_orientation_values_java.target.darwin-mips.mk b/content/screen_orientation_values_java.target.darwin-mips.mk
index d3410e6..8edfd6b 100644
--- a/content/screen_orientation_values_java.target.darwin-mips.mk
+++ b/content/screen_orientation_values_java.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/screen_orientation_values_java.target.darwin-x86.mk b/content/screen_orientation_values_java.target.darwin-x86.mk
index c030988..7e6e3a5 100644
--- a/content/screen_orientation_values_java.target.darwin-x86.mk
+++ b/content/screen_orientation_values_java.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/screen_orientation_values_java.target.darwin-x86_64.mk b/content/screen_orientation_values_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..83a9dec
--- /dev/null
+++ b/content/screen_orientation_values_java.target.darwin-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_screen_orientation_values_java_gyp
+LOCAL_MODULE_STEM := screen_orientation_values_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_screen_orientation_values_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/screen_orientation_values_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ScreenOrientationValues.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ScreenOrientationValues.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/screen_orientation_values_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java" "--template=public/android/java/src/org/chromium/content/common/ScreenOrientationValues.template"
+
+.PHONY: content_screen_orientation_values_java_gyp_rule_trigger
+content_screen_orientation_values_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_screen_orientation_values_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_screen_orientation_values_java_gyp
+
+# Alias gyp target name.
+.PHONY: screen_orientation_values_java
+screen_orientation_values_java: content_screen_orientation_values_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/screen_orientation_values_java.target.linux-arm.mk b/content/screen_orientation_values_java.target.linux-arm.mk
index f8d8fef..e44e79d 100644
--- a/content/screen_orientation_values_java.target.linux-arm.mk
+++ b/content/screen_orientation_values_java.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/screen_orientation_values_java.target.linux-mips.mk b/content/screen_orientation_values_java.target.linux-mips.mk
index d3410e6..8edfd6b 100644
--- a/content/screen_orientation_values_java.target.linux-mips.mk
+++ b/content/screen_orientation_values_java.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/screen_orientation_values_java.target.linux-x86.mk b/content/screen_orientation_values_java.target.linux-x86.mk
index c030988..7e6e3a5 100644
--- a/content/screen_orientation_values_java.target.linux-x86.mk
+++ b/content/screen_orientation_values_java.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/screen_orientation_values_java.target.linux-x86_64.mk b/content/screen_orientation_values_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..83a9dec
--- /dev/null
+++ b/content/screen_orientation_values_java.target.linux-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_screen_orientation_values_java_gyp
+LOCAL_MODULE_STEM := screen_orientation_values_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_screen_orientation_values_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/screen_orientation_values_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/common/ScreenOrientationValues.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/common/ScreenOrientationValues.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/screen_orientation_values_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java" "--template=public/android/java/src/org/chromium/content/common/ScreenOrientationValues.template"
+
+.PHONY: content_screen_orientation_values_java_gyp_rule_trigger
+content_screen_orientation_values_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/common/ScreenOrientationValues.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_screen_orientation_values_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_screen_orientation_values_java_gyp
+
+# Alias gyp target name.
+.PHONY: screen_orientation_values_java
+screen_orientation_values_java: content_screen_orientation_values_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java
index f00dfd1..987a6d2 100644
--- a/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java
+++ b/content/shell/android/browsertests_apk/src/org/chromium/content_browsertests_apk/ContentBrowserTestsActivity.java
@@ -34,7 +34,7 @@
         super.onCreate(savedInstanceState);
 
         try {
-            LibraryLoader.ensureInitialized();
+            LibraryLoader.ensureInitialized(null);
         } catch (ProcessInitException e) {
             Log.i(TAG, "Cannot load content_browsertests:" +  e);
             System.exit(-1);
diff --git a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
index b3bca6b..91dc5f3 100644
--- a/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
+++ b/content/shell/android/linker_test_apk/src/org/chromium/chromium_linker_test_apk/ChromiumLinkerTestActivity.java
@@ -85,7 +85,7 @@
         // Load the library in the browser process, this will also run the test
         // runner in this process.
         try {
-            LibraryLoader.ensureInitialized();
+            LibraryLoader.ensureInitialized(null);
         } catch (ProcessInitException e) {
             Log.i(TAG, "Cannot load chromium_linker_test:" +  e);
         }
diff --git a/content/shell/android/shell_apk/AndroidManifest.xml b/content/shell/android/shell_apk/AndroidManifest.xml
index d61d289..3cd5a12 100644
--- a/content/shell/android/shell_apk/AndroidManifest.xml
+++ b/content/shell/android/shell_apk/AndroidManifest.xml
@@ -100,6 +100,7 @@
     <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
     <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
     <uses-permission android:name="android.permission.CAMERA"/>
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
diff --git a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
index be8ceaf..a8424d7 100644
--- a/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
+++ b/content/shell/android/shell_apk/src/org/chromium/content_shell_apk/ContentShellActivity.java
@@ -56,7 +56,7 @@
 
         DeviceUtils.addDeviceSpecificUserAgentSwitch(this);
         try {
-            LibraryLoader.ensureInitialized();
+            LibraryLoader.ensureInitialized(null);
         } catch (ProcessInitException e) {
             Log.e(TAG, "ContentView initialization failed.", e);
             // Since the library failed to initialize nothing in the application
diff --git a/content/shell/browser/shell.cc b/content/shell/browser/shell.cc
index 6549123..b19ad1f 100644
--- a/content/shell/browser/shell.cc
+++ b/content/shell/browser/shell.cc
@@ -205,13 +205,14 @@
   web_contents_->GetView()->Focus();
 }
 
-void Shell::UpdateNavigationControls() {
+void Shell::UpdateNavigationControls(bool to_different_document) {
   int current_index = web_contents_->GetController().GetCurrentEntryIndex();
   int max_index = web_contents_->GetController().GetEntryCount() - 1;
 
   PlatformEnableUIControl(BACK_BUTTON, current_index > 0);
   PlatformEnableUIControl(FORWARD_BUTTON, current_index < max_index);
-  PlatformEnableUIControl(STOP_BUTTON, web_contents_->IsLoading());
+  PlatformEnableUIControl(STOP_BUTTON,
+      to_different_document && web_contents_->IsLoading());
 }
 
 void Shell::ShowDevTools() {
@@ -266,8 +267,9 @@
   return source;
 }
 
-void Shell::LoadingStateChanged(WebContents* source) {
-  UpdateNavigationControls();
+void Shell::LoadingStateChanged(WebContents* source,
+    bool to_different_document) {
+  UpdateNavigationControls(to_different_document);
   PlatformSetIsLoading(source->IsLoading());
 }
 
diff --git a/content/shell/browser/shell.h b/content/shell/browser/shell.h
index 5248199..1156f21 100644
--- a/content/shell/browser/shell.h
+++ b/content/shell/browser/shell.h
@@ -65,7 +65,7 @@
   void GoBackOrForward(int offset);
   void Reload();
   void Stop();
-  void UpdateNavigationControls();
+  void UpdateNavigationControls(bool to_different_document);
   void Close();
   void ShowDevTools();
   void ShowDevToolsForElementAt(int x, int y);
@@ -119,7 +119,8 @@
                               const gfx::Rect& initial_pos,
                               bool user_gesture,
                               bool* was_blocked) OVERRIDE;
-  virtual void LoadingStateChanged(WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(WebContents* source,
+                                   bool to_different_document) OVERRIDE;
 #if defined(OS_ANDROID)
   virtual void LoadProgressChanged(WebContents* source,
                                    double progress) OVERRIDE;
diff --git a/content/shell/browser/shell_browser_context.cc b/content/shell/browser/shell_browser_context.cc
index dbceb62..b37521e 100644
--- a/content/shell/browser/shell_browser_context.cc
+++ b/content/shell/browser/shell_browser_context.cc
@@ -183,6 +183,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) {
   // Always reject requests for LayoutTests for now.
   // TODO(toyoshim): Make it programmable to improve test coverage.
diff --git a/content/shell/browser/shell_browser_context.h b/content/shell/browser/shell_browser_context.h
index e9ca9bd..3bd5192 100644
--- a/content/shell/browser/shell_browser_context.h
+++ b/content/shell/browser/shell_browser_context.h
@@ -48,6 +48,7 @@
       int render_view_id,
       int bridge_id,
       const GURL& requesting_frame,
+      bool user_gesture,
       const MidiSysExPermissionCallback& callback) OVERRIDE;
   virtual void CancelMidiSysExPermissionRequest(
       int render_process_id,
diff --git a/content/shell/browser/shell_network_delegate.cc b/content/shell/browser/shell_network_delegate.cc
index 1a65163..5ed9634 100644
--- a/content/shell/browser/shell_network_delegate.cc
+++ b/content/shell/browser/shell_network_delegate.cc
@@ -47,7 +47,8 @@
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     const net::HttpResponseHeaders* original_response_headers,
-    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   return net::OK;
 }
 
diff --git a/content/shell/browser/shell_network_delegate.h b/content/shell/browser/shell_network_delegate.h
index 37c5082..09b0ee5 100644
--- a/content/shell/browser/shell_network_delegate.h
+++ b/content/shell/browser/shell_network_delegate.h
@@ -32,8 +32,8 @@
       net::URLRequest* request,
       const net::CompletionCallback& callback,
       const net::HttpResponseHeaders* original_response_headers,
-      scoped_refptr<net::HttpResponseHeaders>*
-          override_response_headers) OVERRIDE;
+      scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE;
   virtual void OnBeforeRedirect(net::URLRequest* request,
                                 const GURL& new_location) OVERRIDE;
   virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE;
diff --git a/content/shell/browser/shell_views.cc b/content/shell/browser/shell_views.cc
index 5789cd6..a2684b5 100644
--- a/content/shell/browser/shell_views.cc
+++ b/content/shell/browser/shell_views.cc
@@ -33,7 +33,6 @@
 #include "ui/views/layout/grid_layout.h"
 #include "ui/views/test/desktop_test_views_delegate.h"
 #include "ui/views/view.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
@@ -41,6 +40,8 @@
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "ui/aura/test/test_screen.h"
 #include "ui/wm/test/wm_test_helper.h"
+#else  // !defined(OS_CHROMEOS)
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #endif
 
 #if defined(OS_WIN)
diff --git a/content/shell/browser/shell_web_contents_view_delegate_gtk.cc b/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
index 9b4ac3f..9065174 100644
--- a/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
+++ b/content/shell/browser/shell_web_contents_view_delegate_gtk.cc
@@ -239,7 +239,9 @@
 }
 
 void ShellWebContentsViewDelegate::OnDeleteMenuActivated(GtkWidget* widget) {
-  web_contents_->GetRenderViewHost()->Delete();
+  RenderFrameHost* frame = web_contents_->GetFocusedFrame();
+  if (frame)
+    frame->Delete();
 }
 
 void ShellWebContentsViewDelegate::OnInspectMenuActivated(GtkWidget* widget) {
diff --git a/content/shell/browser/shell_web_contents_view_delegate_mac.mm b/content/shell/browser/shell_web_contents_view_delegate_mac.mm
index 91541c9..7dd810c 100644
--- a/content/shell/browser/shell_web_contents_view_delegate_mac.mm
+++ b/content/shell/browser/shell_web_contents_view_delegate_mac.mm
@@ -238,7 +238,8 @@
         frame->Paste();
       break;
     case ShellContextMenuItemDeleteTag:
-      web_contents_->GetRenderViewHost()->Delete();
+      if (frame)
+        frame->Delete();
       break;
     case ShellContextMenuItemOpenLinkTag: {
       ShellBrowserContext* browser_context =
diff --git a/content/shell/browser/shell_web_contents_view_delegate_win.cc b/content/shell/browser/shell_web_contents_view_delegate_win.cc
index 177cdb2..ce86db2 100644
--- a/content/shell/browser/shell_web_contents_view_delegate_win.cc
+++ b/content/shell/browser/shell_web_contents_view_delegate_win.cc
@@ -206,7 +206,8 @@
         frame->Paste();
       break;
     case ShellContextMenuItemDeleteId:
-      web_contents_->GetRenderViewHost()->Delete();
+      if (frame)
+        frame->Delete();
       break;
     case ShellContextMenuItemOpenLinkId: {
       ShellBrowserContext* browser_context =
diff --git a/content/shell/renderer/test_runner/CppBoundClass.cpp b/content/shell/renderer/test_runner/CppBoundClass.cpp
deleted file mode 100644
index 088610f..0000000
--- a/content/shell/renderer/test_runner/CppBoundClass.cpp
+++ /dev/null
@@ -1,367 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2009 Pawel Hajdan (phajdan.jr@chromium.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// This file contains definitions for CppBoundClass
-
-// Here's the control flow of a JS method getting forwarded to a class.
-// - Something calls our NPObject with a function like "Invoke".
-// - CppNPObject's static invoke() function forwards it to its attached
-//   CppBoundClass's invoke() method.
-// - CppBoundClass has then overridden invoke() to look up the function
-//   name in its internal map of methods, and then calls the appropriate
-//   method.
-
-#include "content/shell/renderer/test_runner/CppBoundClass.h"
-
-#include "content/shell/renderer/test_runner/TestCommon.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-
-using namespace blink;
-using namespace std;
-
-namespace WebTestRunner {
-
-namespace {
-
-class CppVariantPropertyCallback : public CppBoundClass::PropertyCallback {
-public:
-    CppVariantPropertyCallback(CppVariant* value) : m_value(value) { }
-
-    virtual bool getValue(CppVariant* value) OVERRIDE
-    {
-        value->set(*m_value);
-        return true;
-    }
-
-    virtual bool setValue(const CppVariant& value) OVERRIDE
-    {
-        m_value->set(value);
-        return true;
-    }
-
-private:
-    CppVariant* m_value;
-};
-
-class GetterPropertyCallback : public CppBoundClass::PropertyCallback {
-public:
-    GetterPropertyCallback(scoped_ptr<CppBoundClass::GetterCallback> callback)
-        : m_callback(callback.Pass())
-    {
-    }
-
-    virtual bool getValue(CppVariant* value) OVERRIDE
-    {
-        m_callback->run(value);
-        return true;
-    }
-
-    virtual bool setValue(const CppVariant& value) OVERRIDE { return false; }
-
-private:
-    scoped_ptr<CppBoundClass::GetterCallback> m_callback;
-};
-
-}
-
-// Our special NPObject type. We extend an NPObject with a pointer to a
-// CppBoundClass, which is just a C++ interface that we forward all NPObject
-// callbacks to.
-struct CppNPObject {
-    NPObject parent; // This must be the first field in the struct.
-    CppBoundClass* boundClass;
-
-    //
-    // All following objects and functions are static, and just used to interface
-    // with NPObject/NPClass.
-    //
-
-    // An NPClass associates static functions of CppNPObject with the
-    // function pointers used by the JS runtime.
-    static NPClass npClass;
-
-    // Allocate a new NPObject with the specified class.
-    static NPObject* allocate(NPP, NPClass*);
-
-    // Free an object.
-    static void deallocate(NPObject*);
-
-    // Returns true if the C++ class associated with this NPObject exposes the
-    // given property. Called by the JS runtime.
-    static bool hasProperty(NPObject*, NPIdentifier);
-
-    // Returns true if the C++ class associated with this NPObject exposes the
-    // given method. Called by the JS runtime.
-    static bool hasMethod(NPObject*, NPIdentifier);
-
-    // If the given method is exposed by the C++ class associated with this
-    // NPObject, invokes it with the given arguments and returns a result. Otherwise,
-    // returns "undefined" (in the JavaScript sense). Called by the JS runtime.
-    static bool invoke(NPObject*, NPIdentifier,
-                       const NPVariant* arguments, uint32_t argumentCount,
-                       NPVariant* result);
-
-    // If the given property is exposed by the C++ class associated with this
-    // NPObject, returns its value. Otherwise, returns "undefined" (in the
-    // JavaScript sense). Called by the JS runtime.
-    static bool getProperty(NPObject*, NPIdentifier, NPVariant* result);
-
-    // If the given property is exposed by the C++ class associated with this
-    // NPObject, sets its value. Otherwise, does nothing. Called by the JS
-    // runtime.
-    static bool setProperty(NPObject*, NPIdentifier, const NPVariant* value);
-};
-
-// Build CppNPObject's static function pointers into an NPClass, for use
-// in constructing NPObjects for the C++ classes.
-NPClass CppNPObject::npClass = {
-    NP_CLASS_STRUCT_VERSION,
-    CppNPObject::allocate,
-    CppNPObject::deallocate,
-    /* NPInvalidateFunctionPtr */ 0,
-    CppNPObject::hasMethod,
-    CppNPObject::invoke,
-    /* NPInvokeDefaultFunctionPtr */ 0,
-    CppNPObject::hasProperty,
-    CppNPObject::getProperty,
-    CppNPObject::setProperty,
-    /* NPRemovePropertyFunctionPtr */ 0
-};
-
-NPObject* CppNPObject::allocate(NPP npp, NPClass* aClass)
-{
-    CppNPObject* obj = new CppNPObject;
-    // obj->parent will be initialized by the NPObject code calling this.
-    obj->boundClass = 0;
-    return &obj->parent;
-}
-
-void CppNPObject::deallocate(NPObject* npObj)
-{
-    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
-    delete obj;
-}
-
-bool CppNPObject::hasMethod(NPObject* npObj, NPIdentifier ident)
-{
-    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
-    return obj->boundClass->hasMethod(ident);
-}
-
-bool CppNPObject::hasProperty(NPObject* npObj, NPIdentifier ident)
-{
-    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
-    return obj->boundClass->hasProperty(ident);
-}
-
-bool CppNPObject::invoke(NPObject* npObj, NPIdentifier ident,
-                         const NPVariant* arguments, uint32_t argumentCount,
-                         NPVariant* result)
-{
-    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
-    return obj->boundClass->invoke(ident, arguments, argumentCount, result);
-}
-
-bool CppNPObject::getProperty(NPObject* npObj, NPIdentifier ident, NPVariant* result)
-{
-    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
-    return obj->boundClass->getProperty(ident, result);
-}
-
-bool CppNPObject::setProperty(NPObject* npObj, NPIdentifier ident, const NPVariant* value)
-{
-    CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
-    return obj->boundClass->setProperty(ident, value);
-}
-
-CppBoundClass::CppBoundClass()
-    : m_boundToFrame(false)
-{
-}
-
-CppBoundClass::~CppBoundClass()
-{
-    for (MethodList::iterator i = m_methods.begin(); i != m_methods.end(); ++i)
-        delete i->second;
-
-    for (PropertyList::iterator i = m_properties.begin(); i != m_properties.end(); ++i)
-        delete i->second;
-
-    // Unregister ourselves if we were bound to a frame.
-    if (m_boundToFrame)
-        WebBindings::unregisterObject(NPVARIANT_TO_OBJECT(m_selfVariant));
-}
-
-bool CppBoundClass::hasMethod(NPIdentifier ident) const
-{
-    return m_methods.find(ident) != m_methods.end();
-}
-
-bool CppBoundClass::hasProperty(NPIdentifier ident) const
-{
-    return m_properties.find(ident) != m_properties.end();
-}
-
-bool CppBoundClass::invoke(NPIdentifier ident,
-                           const NPVariant* arguments,
-                           size_t argumentCount,
-                           NPVariant* result) {
-    MethodList::const_iterator end = m_methods.end();
-    MethodList::const_iterator method = m_methods.find(ident);
-    Callback* callback;
-    if (method == end) {
-        if (!m_fallbackCallback.get()) {
-            VOID_TO_NPVARIANT(*result);
-            return false;
-        }
-        callback = m_fallbackCallback.get();
-    } else
-        callback = (*method).second;
-
-    // Build a CppArgumentList argument vector from the NPVariants coming in.
-    CppArgumentList cppArguments(argumentCount);
-    for (size_t i = 0; i < argumentCount; i++)
-        cppArguments[i].set(arguments[i]);
-
-    CppVariant cppResult;
-    callback->run(cppArguments, &cppResult);
-
-    cppResult.copyToNPVariant(result);
-    return true;
-}
-
-bool CppBoundClass::getProperty(NPIdentifier ident, NPVariant* result) const
-{
-    PropertyList::const_iterator callback = m_properties.find(ident);
-    if (callback == m_properties.end()) {
-        VOID_TO_NPVARIANT(*result);
-        return false;
-    }
-
-    CppVariant cppValue;
-    if (!callback->second->getValue(&cppValue))
-        return false;
-    cppValue.copyToNPVariant(result);
-    return true;
-}
-
-bool CppBoundClass::setProperty(NPIdentifier ident, const NPVariant* value)
-{
-    PropertyList::iterator callback = m_properties.find(ident);
-    if (callback == m_properties.end())
-        return false;
-
-    CppVariant cppValue;
-    cppValue.set(*value);
-    return (*callback).second->setValue(cppValue);
-}
-
-void CppBoundClass::bindCallback(const string& name, Callback* callback)
-{
-    NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
-    MethodList::iterator oldCallback = m_methods.find(ident);
-    if (oldCallback != m_methods.end()) {
-        delete oldCallback->second;
-        if (!callback) {
-            m_methods.erase(oldCallback);
-            return;
-        }
-    }
-
-    m_methods[ident] = callback;
-}
-
-void CppBoundClass::bindGetterCallback(const string& name, scoped_ptr<GetterCallback> callback)
-{
-    PropertyCallback* propertyCallback = callback.get() ? new GetterPropertyCallback(callback.Pass()) : 0;
-    bindProperty(name, propertyCallback);
-}
-
-void CppBoundClass::bindProperty(const string& name, CppVariant* prop)
-{
-    PropertyCallback* propertyCallback = prop ? new CppVariantPropertyCallback(prop) : 0;
-    bindProperty(name, propertyCallback);
-}
-
-void CppBoundClass::bindProperty(const string& name, PropertyCallback* callback)
-{
-    NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
-    PropertyList::iterator oldCallback = m_properties.find(ident);
-    if (oldCallback != m_properties.end()) {
-        delete oldCallback->second;
-        if (!callback) {
-            m_properties.erase(oldCallback);
-            return;
-        }
-    }
-
-    m_properties[ident] = callback;
-}
-
-bool CppBoundClass::isMethodRegistered(const string& name) const
-{
-    NPIdentifier ident = WebBindings::getStringIdentifier(name.c_str());
-    MethodList::const_iterator callback = m_methods.find(ident);
-    return callback != m_methods.end();
-}
-
-CppVariant* CppBoundClass::getAsCppVariant()
-{
-    if (!m_selfVariant.isObject()) {
-        // Create an NPObject using our static NPClass. The first argument (a
-        // plugin's instance handle) is passed through to the allocate function
-        // directly, and we don't use it, so it's ok to be 0.
-        NPObject* npObj = WebBindings::createObject(0, &CppNPObject::npClass);
-        CppNPObject* obj = reinterpret_cast<CppNPObject*>(npObj);
-        obj->boundClass = this;
-        m_selfVariant.set(npObj);
-        WebBindings::releaseObject(npObj); // CppVariant takes the reference.
-    }
-    BLINK_ASSERT(m_selfVariant.isObject());
-    return &m_selfVariant;
-}
-
-void CppBoundClass::bindToJavascript(WebFrame* frame, const WebString& classname)
-{
-    // BindToWindowObject will take its own reference to the NPObject, and clean
-    // up after itself. It will also (indirectly) register the object with V8,
-    // so we must remember this so we can unregister it when we're destroyed.
-    frame->bindToWindowObject(classname, NPVARIANT_TO_OBJECT(*getAsCppVariant()), 0);
-    m_boundToFrame = true;
-}
-
-}
diff --git a/content/shell/renderer/test_runner/CppBoundClass.h b/content/shell/renderer/test_runner/CppBoundClass.h
deleted file mode 100644
index 96e3983..0000000
--- a/content/shell/renderer/test_runner/CppBoundClass.h
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2009 Pawel Hajdan (phajdan.jr@chromium.org)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
-  CppBoundClass class:
-  This base class serves as a parent for C++ classes designed to be bound to
-  JavaScript objects.
-
-  Subclasses should define the constructor to build the property and method
-  lists needed to bind this class to a JS object.  They should also declare
-  and define member variables and methods to be exposed to JS through
-  that object.
-*/
-
-#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_CPPBOUNDCLASS_H_
-#define CONTENT_SHELL_RENDERER_TEST_RUNNER_CPPBOUNDCLASS_H_
-
-#include <map>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/shell/renderer/test_runner/CppVariant.h"
-
-namespace blink {
-class WebFrame;
-class WebString;
-}
-
-namespace WebTestRunner {
-
-typedef std::vector<CppVariant> CppArgumentList;
-
-// CppBoundClass lets you map Javascript method calls and property accesses
-// directly to C++ method calls and CppVariant* variable access.
-class CppBoundClass {
-public:
-    class PropertyCallback {
-    public:
-        virtual ~PropertyCallback() { }
-
-        // Sets |value| to the value of the property. Returns false in case of
-        // failure. |value| is always non-0.
-        virtual bool getValue(CppVariant* result) = 0;
-
-        // sets the property value to |value|. Returns false in case of failure.
-        virtual bool setValue(const CppVariant&) = 0;
-    };
-
-    // Callback class for "void function(CppVariant*)"
-    class GetterCallback {
-    public:
-        virtual ~GetterCallback() { }
-        virtual void run(CppVariant*) = 0;
-    };
-
-    // The constructor should call BindMethod, BindProperty, and
-    // SetFallbackMethod as needed to set up the methods, properties, and
-    // fallback method.
-    CppBoundClass();
-    virtual ~CppBoundClass();
-
-    // Return a CppVariant representing this class, for use with BindProperty().
-    // The variant type is guaranteed to be NPVariantType_Object.
-    CppVariant* getAsCppVariant();
-
-    // Given a WebFrame, BindToJavascript builds the NPObject that will represent
-    // the class and binds it to the frame's window under the given name. This
-    // should generally be called from the WebView delegate's
-    // WindowObjectCleared(). A class so bound will be accessible to JavaScript
-    // as window.<classname>. The owner of the CppBoundObject is responsible for
-    // keeping the object around while the frame is alive, and for destroying it
-    // afterwards.
-    void bindToJavascript(blink::WebFrame*, const blink::WebString& classname);
-
-    // Used by a test. Returns true if a method with the specified name exists,
-    // regardless of whether a fallback is registered.
-    bool isMethodRegistered(const std::string&) const;
-
-protected:
-    // Callback for "void function(const CppArguemntList&, CppVariant*)"
-    class Callback {
-    public:
-        virtual ~Callback() { }
-        virtual void run(const CppArgumentList&, CppVariant*) = 0;
-    };
-
-    // Callback for "void T::method(const CppArguemntList&, CppVariant*)"
-    template <class T> class MemberCallback : public Callback {
-    public:
-        typedef void (T::*MethodType)(const CppArgumentList&, CppVariant*);
-        MemberCallback(T* object, MethodType method)
-            : m_object(object)
-            , m_method(method) { }
-        virtual ~MemberCallback() { }
-
-        virtual void run(const CppArgumentList& arguments, CppVariant* result)
-        {
-            (m_object->*m_method)(arguments, result);
-        }
-
-    private:
-        T* m_object;
-        MethodType m_method;
-    };
-
-    // Callback class for "void T::method(CppVariant*)"
-    template <class T> class MemberGetterCallback : public GetterCallback {
-    public:
-        typedef void (T::*MethodType)(CppVariant*);
-        MemberGetterCallback(T* object, MethodType method)
-            : m_object(object)
-            , m_method(method) { }
-        virtual ~MemberGetterCallback() { }
-
-        virtual void run(CppVariant* result) { (m_object->*m_method)(result); }
-
-    private:
-        T* m_object;
-        MethodType m_method;
-    };
-
-    // Bind the Javascript method called the string parameter to the C++ method.
-    void bindCallback(const std::string&, Callback*);
-
-    // A wrapper for bindCallback, to simplify the common case of binding a
-    // method on the current object. Though not verified here, the method parameter
-    // must be a method of this CppBoundClass subclass.
-    template<class T>
-    void bindMethod(const std::string& name, void (T::*method)(const CppArgumentList&, CppVariant*))
-    {
-        Callback* callback = new MemberCallback<T>(static_cast<T*>(this), method);
-        bindCallback(name, callback);
-    }
-
-    // Bind Javascript property |name| to the C++ getter callback |callback|.
-    // This can be used to create read-only properties.
-    void bindGetterCallback(const std::string&, scoped_ptr<GetterCallback>);
-
-    // A wrapper for BindGetterCallback, to simplify the common case of binding a
-    // property on the current object. Though not verified here, the method parameter
-    // must be a method of this CppBoundClass subclass.
-    template<class T>
-    void bindProperty(const std::string& name, void (T::*method)(CppVariant*))
-    {
-        scoped_ptr<GetterCallback> callback(new MemberGetterCallback<T>(static_cast<T*>(this), method));
-        bindGetterCallback(name, callback.Pass());
-    }
-
-    // Bind the Javascript property called |name| to a CppVariant.
-    void bindProperty(const std::string&, CppVariant*);
-
-    // Bind Javascript property called |name| to a PropertyCallback.
-    // CppBoundClass assumes control over the life time of the callback.
-    void bindProperty(const std::string&, PropertyCallback*);
-
-    // Set the fallback callback, which is called when when a callback is
-    // invoked that isn't bound.
-    // If it is 0 (its default value), a JavaScript exception is thrown in
-    // that case (as normally expected). If non 0, the fallback method is
-    // invoked and the script continues its execution.
-    // Passing 0 clears out any existing binding.
-    // It is used for tests and should probably only be used in such cases
-    // as it may cause unexpected behaviors (a JavaScript object with a
-    // fallback always returns true when checked for a method's
-    // existence).
-    void bindFallbackCallback(scoped_ptr<Callback> fallbackCallback)
-    {
-        m_fallbackCallback = fallbackCallback.Pass();
-    }
-
-    // A wrapper for BindFallbackCallback, to simplify the common case of
-    // binding a method on the current object. Though not verified here,
-    // |method| must be a method of this CppBoundClass subclass.
-    // Passing 0 for |method| clears out any existing binding.
-    template<class T>
-    void bindFallbackMethod(void (T::*method)(const CppArgumentList&, CppVariant*))
-    {
-        if (method)
-            bindFallbackCallback(scoped_ptr<Callback>(new MemberCallback<T>(static_cast<T*>(this), method)).Pass());
-        else
-            bindFallbackCallback(scoped_ptr<Callback>().Pass());
-    }
-
-    // Some fields are protected because some tests depend on accessing them,
-    // but otherwise they should be considered private.
-
-    typedef std::map<NPIdentifier, PropertyCallback*> PropertyList;
-    typedef std::map<NPIdentifier, Callback*> MethodList;
-    // These maps associate names with property and method pointers to be
-    // exposed to JavaScript.
-    PropertyList m_properties;
-    MethodList m_methods;
-
-    // The callback gets invoked when a call is made to an nonexistent method.
-    scoped_ptr<Callback> m_fallbackCallback;
-
-private:
-    // NPObject callbacks.
-    friend struct CppNPObject;
-    bool hasMethod(NPIdentifier) const;
-    bool invoke(NPIdentifier, const NPVariant* args, size_t argCount,
-                NPVariant* result);
-    bool hasProperty(NPIdentifier) const;
-    bool getProperty(NPIdentifier, NPVariant* result) const;
-    bool setProperty(NPIdentifier, const NPVariant*);
-
-    // A lazily-initialized CppVariant representing this class. We retain 1
-    // reference to this object, and it is released on deletion.
-    CppVariant m_selfVariant;
-
-    // True if our np_object has been bound to a WebFrame, in which case it must
-    // be unregistered with V8 when we delete it.
-    bool m_boundToFrame;
-
-    DISALLOW_COPY_AND_ASSIGN(CppBoundClass);
-};
-
-}
-
-#endif  // CONTENT_SHELL_RENDERER_TEST_RUNNER_CPPBOUNDCLASS_H_
diff --git a/content/shell/renderer/test_runner/CppVariant.cpp b/content/shell/renderer/test_runner/CppVariant.cpp
deleted file mode 100644
index 47936df..0000000
--- a/content/shell/renderer/test_runner/CppVariant.cpp
+++ /dev/null
@@ -1,296 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/shell/renderer/test_runner/CppVariant.h"
-
-#include <limits>
-#include "content/shell/renderer/test_runner/TestCommon.h"
-
-using namespace blink;
-using namespace std;
-
-namespace WebTestRunner {
-
-CppVariant::CppVariant()
-{
-    type = NPVariantType_Null;
-}
-
-// Note that Set() performs a deep copy, which is necessary to safely
-// call FreeData() on the value in the destructor.
-CppVariant::CppVariant(const CppVariant& original)
-{
-    type = NPVariantType_Null;
-    set(original);
-}
-
-// See comment for copy constructor, above.
-CppVariant& CppVariant::operator=(const CppVariant& original)
-{
-    if (&original != this)
-        set(original);
-    return *this;
-}
-
-CppVariant::~CppVariant()
-{
-    freeData();
-}
-
-void CppVariant::freeData()
-{
-    WebBindings::releaseVariantValue(this);
-}
-
-bool CppVariant::isEqual(const CppVariant& other) const
-{
-    if (type != other.type)
-        return false;
-
-    switch (type) {
-    case NPVariantType_Bool:
-        return (value.boolValue == other.value.boolValue);
-    case NPVariantType_Int32:
-        return (value.intValue == other.value.intValue);
-    case NPVariantType_Double:
-        return (value.doubleValue == other.value.doubleValue);
-    case NPVariantType_String: {
-        const NPString *this_value = &value.stringValue;
-        const NPString *other_value = &other.value.stringValue;
-        uint32_t len = this_value->UTF8Length;
-        return len == other_value->UTF8Length
-            && !strncmp(this_value->UTF8Characters,
-                        other_value->UTF8Characters, len);
-    }
-    case NPVariantType_Null:
-    case NPVariantType_Void:
-        return true;
-    case NPVariantType_Object: {
-        NPObject* thisValue = value.objectValue;
-        NPObject* otherValue = other.value.objectValue;
-        return thisValue->_class == otherValue->_class
-            && thisValue->referenceCount == otherValue->referenceCount;
-    }
-    }
-    return false;
-}
-
-void CppVariant::copyToNPVariant(NPVariant* result) const
-{
-    result->type = type;
-    switch (type) {
-    case NPVariantType_Bool:
-        result->value.boolValue = value.boolValue;
-        break;
-    case NPVariantType_Int32:
-        result->value.intValue = value.intValue;
-        break;
-    case NPVariantType_Double:
-        result->value.doubleValue = value.doubleValue;
-        break;
-    case NPVariantType_String:
-        WebBindings::initializeVariantWithStringCopy(result, &value.stringValue);
-        break;
-    case NPVariantType_Null:
-    case NPVariantType_Void:
-        // Nothing to set.
-        break;
-    case NPVariantType_Object:
-        result->type = NPVariantType_Object;
-        result->value.objectValue = WebBindings::retainObject(value.objectValue);
-        break;
-    }
-}
-
-void CppVariant::set(const NPVariant& newValue)
-{
-    freeData();
-    switch (newValue.type) {
-    case NPVariantType_Bool:
-        set(newValue.value.boolValue);
-        break;
-    case NPVariantType_Int32:
-        set(newValue.value.intValue);
-        break;
-    case NPVariantType_Double:
-        set(newValue.value.doubleValue);
-        break;
-    case NPVariantType_String:
-        set(newValue.value.stringValue);
-        break;
-    case NPVariantType_Null:
-    case NPVariantType_Void:
-        type = newValue.type;
-        break;
-    case NPVariantType_Object:
-        set(newValue.value.objectValue);
-        break;
-    }
-}
-
-void CppVariant::setNull()
-{
-    freeData();
-    type = NPVariantType_Null;
-}
-
-void CppVariant::set(bool newValue)
-{
-    freeData();
-    type = NPVariantType_Bool;
-    value.boolValue = newValue;
-}
-
-void CppVariant::set(int32_t newValue)
-{
-    freeData();
-    type = NPVariantType_Int32;
-    value.intValue = newValue;
-}
-
-void CppVariant::set(double newValue)
-{
-    freeData();
-    type = NPVariantType_Double;
-    value.doubleValue = newValue;
-}
-
-// The newValue must be a null-terminated string.
-void CppVariant::set(const char* newValue)
-{
-    freeData();
-    type = NPVariantType_String;
-    NPString newString = {newValue,
-                          static_cast<uint32_t>(strlen(newValue))};
-    WebBindings::initializeVariantWithStringCopy(this, &newString);
-}
-
-void CppVariant::set(const string& newValue)
-{
-    freeData();
-    type = NPVariantType_String;
-    NPString newString = {newValue.data(),
-                          static_cast<uint32_t>(newValue.size())};
-    WebBindings::initializeVariantWithStringCopy(this, &newString);
-}
-
-void CppVariant::set(const NPString& newValue)
-{
-    freeData();
-    type = NPVariantType_String;
-    WebBindings::initializeVariantWithStringCopy(this, &newValue);
-}
-
-void CppVariant::set(NPObject* newValue)
-{
-    freeData();
-    type = NPVariantType_Object;
-    value.objectValue = WebBindings::retainObject(newValue);
-}
-
-string CppVariant::toString() const
-{
-    BLINK_ASSERT(isString());
-    return string(value.stringValue.UTF8Characters,
-                  value.stringValue.UTF8Length);
-}
-
-int32_t CppVariant::toInt32() const
-{
-    if (isInt32())
-        return value.intValue;
-    if (isDouble())
-        return static_cast<int32_t>(value.doubleValue);
-    BLINK_ASSERT_NOT_REACHED();
-    return 0;
-}
-
-double CppVariant::toDouble() const
-{
-    if (isInt32())
-        return static_cast<double>(value.intValue);
-    if (isDouble())
-        return value.doubleValue;
-    BLINK_ASSERT_NOT_REACHED();
-    return 0;
-}
-
-bool CppVariant::toBoolean() const
-{
-    BLINK_ASSERT(isBool());
-    return value.boolValue;
-}
-
-vector<string> CppVariant::toStringVector() const
-{
-
-    BLINK_ASSERT(isObject());
-    vector<string> stringVector;
-    NPObject* npValue = value.objectValue;
-    NPIdentifier lengthId = WebBindings::getStringIdentifier("length");
-
-    if (!WebBindings::hasProperty(0, npValue, lengthId))
-        return stringVector;
-
-    NPVariant lengthValue;
-    if (!WebBindings::getProperty(0, npValue, lengthId, &lengthValue))
-        return stringVector;
-
-    int length = 0;
-    // The length is a double in some cases.
-    if (NPVARIANT_IS_DOUBLE(lengthValue))
-        length = static_cast<int>(NPVARIANT_TO_DOUBLE(lengthValue));
-    else if (NPVARIANT_IS_INT32(lengthValue))
-        length = NPVARIANT_TO_INT32(lengthValue);
-    WebBindings::releaseVariantValue(&lengthValue);
-
-    // For sanity, only allow 100 items.
-    length = min(100, length);
-    for (int i = 0; i < length; ++i) {
-        // Get each of the items.
-        char indexInChar[20]; // Enough size to store 32-bit integer
-        snprintf(indexInChar, 20, "%d", i);
-        string index(indexInChar);
-        NPIdentifier indexId = WebBindings::getStringIdentifier(index.c_str());
-        if (!WebBindings::hasProperty(0, npValue, indexId))
-            continue;
-        NPVariant indexValue;
-        if (!WebBindings::getProperty(0, npValue, indexId, &indexValue))
-            continue;
-        if (NPVARIANT_IS_STRING(indexValue)) {
-            string item(NPVARIANT_TO_STRING(indexValue).UTF8Characters,
-                        NPVARIANT_TO_STRING(indexValue).UTF8Length);
-            stringVector.push_back(item);
-        }
-        WebBindings::releaseVariantValue(&indexValue);
-    }
-    return stringVector;
-}
-
-bool CppVariant::invoke(const string& method, const CppVariant* arguments,
-                        uint32_t argumentCount, CppVariant& result) const
-{
-    BLINK_ASSERT(isObject());
-    NPIdentifier methodName = WebBindings::getStringIdentifier(method.c_str());
-    NPObject* npObject = value.objectValue;
-    if (!WebBindings::hasMethod(0, npObject, methodName))
-        return false;
-    NPVariant r;
-    bool status = WebBindings::invoke(0, npObject, methodName, arguments, argumentCount, &r);
-    result.set(r);
-    return status;
-}
-
-bool CppVariant::invokeDefault(const CppVariant* arguments, uint32_t argumentCount,
-                               CppVariant& result) const
-{
-    BLINK_ASSERT(isObject());
-    NPObject* npObject = value.objectValue;
-    NPVariant r;
-    bool status = WebBindings::invokeDefault(0, npObject, arguments, argumentCount, &r);
-    result.set(r);
-    return status;
-}
-
-}
diff --git a/content/shell/renderer/test_runner/CppVariant.h b/content/shell/renderer/test_runner/CppVariant.h
deleted file mode 100644
index 257d04c..0000000
--- a/content/shell/renderer/test_runner/CppVariant.h
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/*
-  This file contains the declaration for CppVariant, a type used by C++ classes
-  that are to be bound to JavaScript objects.
-
-  CppVariant exists primarily as an interface between C++ callers and the
-  corresponding NPVariant type.  CppVariant also provides a number of
-  convenience constructors and accessors, so that the NPVariantType values
-  don't need to be exposed, and a destructor to free any memory allocated for
-  string values.
-*/
-
-#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_CPPVARIANT_H_
-#define CONTENT_SHELL_RENDERER_TEST_RUNNER_CPPVARIANT_H_
-
-#include <string>
-#include <vector>
-
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-namespace WebTestRunner {
-
-class CppVariant : public NPVariant {
-public:
-    CppVariant();
-    ~CppVariant();
-    void setNull();
-    void set(bool);
-    void set(int32_t);
-    void set(double);
-
-    // Note that setting a CppVariant to a string value involves copying the
-    // string data, which must be freed with a call to freeData() when the
-    // CppVariant is set to a different value or is no longer needed. Normally
-    // this is handled by the other set() methods and by the destructor.
-    void set(const char*); // Must be a null-terminated string.
-    void set(const std::string&);
-    void set(const NPString&);
-    void set(const NPVariant&);
-
-    // Note that setting a CppVariant to an NPObject involves ref-counting
-    // the actual object. freeData() should only be called if the CppVariant
-    // is no longer needed. The other set() methods handle this internally.
-    // Also, the object's NPClass is expected to be a static object: neither
-    // the NP runtime nor CppVariant will ever free it.
-    void set(NPObject*_value);
-
-    // These three methods all perform deep copies of any string data. This
-    // allows local CppVariants to be released by the destructor without
-    // corrupting their sources. In performance-critical code, or when strings
-    // are very long, avoid creating new CppVariants.
-    // In case of NPObject as the data, the copying involves ref-counting
-    // as opposed to deep-copying. The ref-counting ensures that sources don't
-    // get corrupted when the copies get destroyed.
-    void copyToNPVariant(NPVariant* result) const;
-    CppVariant& operator=(const CppVariant& original);
-    CppVariant(const CppVariant& original);
-
-    // Calls NPN_ReleaseVariantValue, which frees any string data
-    // held by the object and sets its type to null.
-    // In case of NPObject, the NPN_ReleaseVariantValue decrements
-    // the ref-count (releases when ref-count becomes 0)
-    void freeData();
-
-    // Compares this CppVariant's type and value to another's. They must be
-    // identical in both type and value to be considered equal. For string and
-    // object types, a deep comparison is performed; that is, the contents of the
-    // strings, or the classes and refcounts of the objects, must be the same,
-    // but they need not be the same pointers.
-    bool isEqual(const CppVariant&) const;
-
-    // The value of a CppVariant may be read directly from its NPVariant (but
-    // should only be set using one of the set() methods above). Although the
-    // type of a CppVariant is likewise public, it can be accessed through these
-    // functions rather than directly if a caller wishes to avoid dependence on
-    // the NPVariantType values.
-    bool isBool() const { return (type == NPVariantType_Bool); }
-    bool isInt32() const { return (type == NPVariantType_Int32); }
-    bool isDouble() const { return (type == NPVariantType_Double); }
-    bool isNumber() const { return (isInt32() || isDouble()); }
-    bool isString() const { return (type == NPVariantType_String); }
-    bool isVoid() const { return (type == NPVariantType_Void); }
-    bool isNull() const { return (type == NPVariantType_Null); }
-    bool isEmpty() const { return (isVoid() || isNull()); }
-    bool isObject() const { return (type == NPVariantType_Object); }
-
-    // Converters. The CppVariant must be of a type convertible to these values.
-    // For example, toInt32() works only if isNumber() is true.
-    std::string toString() const;
-    int32_t toInt32() const;
-    double toDouble() const;
-    bool toBoolean() const;
-    // Returns a vector of strings for the specified argument. This is useful
-    // for converting a JavaScript array of strings into a vector of strings.
-    std::vector<std::string> toStringVector() const;
-
-    // Invoke method of the given name on an object with the supplied arguments.
-    // The first argument should be the object on which the method is to be
-    // invoked. Returns whether the method was successfully invoked. If the
-    // method was invoked successfully, any return value is stored in the
-    // CppVariant specified by result.
-    bool invoke(const std::string&, const CppVariant* arguments,
-                uint32_t argumentCount, CppVariant& result) const;
-
-    // Invoke an object's default method with the supplied arguments.
-    // The first argument should be the object on which the method is to be
-    // invoked. Returns whether the method was successfully invoked. If the
-    // method was invoked successfully, any return value is stored in the
-    // CppVariant specified by result.
-    bool invokeDefault(const CppVariant* arguments,
-                       uint32_t argumentCount, CppVariant& result) const;
-};
-
-}
-
-#endif  // CONTENT_SHELL_RENDERER_TEST_RUNNER_CPPVARIANT_H_
diff --git a/content/shell/renderer/test_runner/EventSender.cpp b/content/shell/renderer/test_runner/EventSender.cpp
deleted file mode 100644
index 3106396..0000000
--- a/content/shell/renderer/test_runner/EventSender.cpp
+++ /dev/null
@@ -1,1465 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file contains the definition for EventSender.
-//
-// Some notes about drag and drop handling:
-// Windows drag and drop goes through a system call to doDragDrop. At that
-// point, program control is given to Windows which then periodically makes
-// callbacks into the webview. This won't work for layout tests, so instead,
-// we queue up all the mouse move and mouse up events. When the test tries to
-// start a drag (by calling EvenSendingController::doDragDrop), we take the
-// events in the queue and replay them.
-// The behavior of queuing events and replaying them can be disabled by a
-// layout test by setting eventSender.dragMode to false.
-
-#include "content/shell/renderer/test_runner/EventSender.h"
-
-#include <deque>
-
-#include "content/shell/renderer/test_runner/KeyCodeMapping.h"
-#include "content/shell/renderer/test_runner/MockSpellCheck.h"
-#include "content/shell/renderer/test_runner/TestCommon.h"
-#include "content/shell/renderer/test_runner/TestInterfaces.h"
-#include "content/shell/renderer/test_runner/WebTestDelegate.h"
-#include "content/shell/renderer/test_runner/WebTestProxy.h"
-#include "third_party/WebKit/public/platform/WebDragData.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/WebKit/public/web/WebContextMenuData.h"
-#include "third_party/WebKit/public/web/WebTouchPoint.h"
-#include "third_party/WebKit/public/web/WebView.h"
-
-#ifdef WIN32
-#include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
-#elif __APPLE__
-#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
-#elif defined(ANDROID)
-#include "third_party/WebKit/public/web/android/WebInputEventFactory.h"
-#elif defined(TOOLKIT_GTK)
-#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
-#endif
-
-// FIXME: layout before each event?
-
-using namespace std;
-using namespace blink;
-
-namespace WebTestRunner {
-
-WebPoint EventSender::lastMousePos;
-WebMouseEvent::Button EventSender::pressedButton = WebMouseEvent::ButtonNone;
-WebMouseEvent::Button EventSender::lastButtonType = WebMouseEvent::ButtonNone;
-
-namespace {
-
-struct SavedEvent {
-    enum SavedEventType {
-        Unspecified,
-        MouseUp,
-        MouseMove,
-        LeapForward
-    };
-
-    SavedEventType type;
-    WebMouseEvent::Button buttonType; // For MouseUp.
-    WebPoint pos; // For MouseMove.
-    int milliseconds; // For LeapForward.
-    int modifiers;
-
-    SavedEvent()
-        : type(Unspecified)
-        , buttonType(WebMouseEvent::ButtonNone)
-        , milliseconds(0)
-        , modifiers(0) { }
-};
-
-WebDragData currentDragData;
-WebDragOperation currentDragEffect;
-WebDragOperationsMask currentDragEffectsAllowed;
-bool replayingSavedEvents = false;
-deque<SavedEvent> mouseEventQueue;
-int touchModifiers;
-vector<WebTouchPoint> touchPoints;
-
-// Time and place of the last mouse up event.
-double lastClickTimeSec = 0;
-WebPoint lastClickPos;
-int clickCount = 0;
-
-// maximum distance (in space and time) for a mouse click
-// to register as a double or triple click
-const double multipleClickTimeSec = 1;
-const int multipleClickRadiusPixels = 5;
-
-// How much we should scroll per event - the value here is chosen to
-// match the WebKit impl and layout test results.
-const float scrollbarPixelsPerTick = 40.0f;
-
-inline bool outsideMultiClickRadius(const WebPoint& a, const WebPoint& b)
-{
-    return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
-        multipleClickRadiusPixels * multipleClickRadiusPixels;
-}
-
-// Used to offset the time the event hander things an event happened. This is
-// done so tests can run without a delay, but bypass checks that are time
-// dependent (e.g., dragging has a timeout vs selection).
-uint32 timeOffsetMs = 0;
-
-double getCurrentEventTimeSec(WebTestDelegate* delegate)
-{
-    return (delegate->getCurrentTimeInMillisecond() + timeOffsetMs) / 1000.0;
-}
-
-void advanceEventTime(int32_t deltaMs)
-{
-    timeOffsetMs += deltaMs;
-}
-
-void initMouseEvent(WebInputEvent::Type t, WebMouseEvent::Button b, const WebPoint& pos, WebMouseEvent* e, double ts, int modifiers)
-{
-    e->type = t;
-    e->button = b;
-    e->modifiers = modifiers;
-    e->x = pos.x;
-    e->y = pos.y;
-    e->globalX = pos.x;
-    e->globalY = pos.y;
-    e->timeStampSeconds = ts;
-    e->clickCount = clickCount;
-}
-
-int getKeyModifier(const string& modifierName)
-{
-    const char* characters = modifierName.c_str();
-    if (!strcmp(characters, "ctrlKey")
-#ifndef __APPLE__
-        || !strcmp(characters, "addSelectionKey")
-#endif
-        ) {
-        return WebInputEvent::ControlKey;
-    } else if (!strcmp(characters, "shiftKey") || !strcmp(characters, "rangeSelectionKey")) {
-        return WebInputEvent::ShiftKey;
-    } else if (!strcmp(characters, "altKey")) {
-        return WebInputEvent::AltKey;
-#ifdef __APPLE__
-    } else if (!strcmp(characters, "metaKey") || !strcmp(characters, "addSelectionKey")) {
-        return WebInputEvent::MetaKey;
-#else
-    } else if (!strcmp(characters, "metaKey")) {
-        return WebInputEvent::MetaKey;
-#endif
-    } else if (!strcmp(characters, "autoRepeat")) {
-        return WebInputEvent::IsAutoRepeat;
-    } else if (!strcmp(characters, "copyKey")) {
-#ifdef __APPLE__
-        return WebInputEvent::AltKey;
-#else
-        return WebInputEvent::ControlKey;
-#endif
-    }
-
-    return 0;
-}
-
-int getKeyModifiers(const CppVariant* argument)
-{
-    int modifiers = 0;
-    if (argument->isObject()) {
-        vector<string> modifierNames = argument->toStringVector();
-        for (vector<string>::const_iterator i = modifierNames.begin(); i != modifierNames.end(); ++i)
-            modifiers |= getKeyModifier(*i);
-    } else if (argument->isString()) {
-        modifiers |= getKeyModifier(argument->toString());
-    }
-    return modifiers;
-}
-
-// Get the edit command corresponding to a keyboard event.
-// Returns true if the specified event corresponds to an edit command, the name
-// of the edit command will be stored in |*name|.
-bool getEditCommand(const WebKeyboardEvent& event, string* name)
-{
-#ifdef __APPLE__
-    // We only cares about Left,Right,Up,Down keys with Command or Command+Shift
-    // modifiers. These key events correspond to some special movement and
-    // selection editor commands, and was supposed to be handled in
-    // WebKit/chromium/src/EditorClientImpl.cpp. But these keys will be marked
-    // as system key, which prevents them from being handled. Thus they must be
-    // handled specially.
-    if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) != WebKeyboardEvent::MetaKey)
-        return false;
-
-    switch (event.windowsKeyCode) {
-    case VKEY_LEFT:
-        *name = "MoveToBeginningOfLine";
-        break;
-    case VKEY_RIGHT:
-        *name = "MoveToEndOfLine";
-        break;
-    case VKEY_UP:
-        *name = "MoveToBeginningOfDocument";
-        break;
-    case VKEY_DOWN:
-        *name = "MoveToEndOfDocument";
-        break;
-    default:
-        return false;
-    }
-
-    if (event.modifiers & WebKeyboardEvent::ShiftKey)
-        name->append("AndModifySelection");
-
-    return true;
-#else
-    return false;
-#endif
-}
-
-// Key event location code introduced in DOM Level 3.
-// See also: http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
-enum KeyLocationCode {
-    DOMKeyLocationStandard      = 0x00,
-    DOMKeyLocationLeft          = 0x01,
-    DOMKeyLocationRight         = 0x02,
-    DOMKeyLocationNumpad        = 0x03
-};
-
-}
-
-EventSender::EventSender(TestInterfaces* interfaces)
-    : m_testInterfaces(interfaces)
-    , m_delegate(0)
-{
-    // Initialize the map that associates methods of this class with the names
-    // they will use when called by JavaScript. The actual binding of those
-    // names to their methods will be done by calling bindToJavaScript() (defined
-    // by CppBoundClass, the parent to EventSender).
-    bindMethod("addTouchPoint", &EventSender::addTouchPoint);
-    bindMethod("beginDragWithFiles", &EventSender::beginDragWithFiles);
-    bindMethod("cancelTouchPoint", &EventSender::cancelTouchPoint);
-    bindMethod("clearKillRing", &EventSender::clearKillRing);
-    bindMethod("clearTouchPoints", &EventSender::clearTouchPoints);
-    bindMethod("contextClick", &EventSender::contextClick);
-    bindMethod("continuousMouseScrollBy", &EventSender::continuousMouseScrollBy);
-    bindMethod("dispatchMessage", &EventSender::dispatchMessage);
-    bindMethod("dumpFilenameBeingDragged", &EventSender::dumpFilenameBeingDragged);
-    bindMethod("enableDOMUIEventLogging", &EventSender::enableDOMUIEventLogging);
-    bindMethod("fireKeyboardEventsToElement", &EventSender::fireKeyboardEventsToElement);
-    bindMethod("keyDown", &EventSender::keyDown);
-    bindMethod("leapForward", &EventSender::leapForward);
-    bindMethod("mouseDown", &EventSender::mouseDown);
-    bindMethod("mouseMoveTo", &EventSender::mouseMoveTo);
-    bindMethod("mouseScrollBy", &EventSender::mouseScrollBy);
-    bindMethod("mouseUp", &EventSender::mouseUp);
-    bindMethod("mouseDragBegin", &EventSender::mouseDragBegin);
-    bindMethod("mouseDragEnd", &EventSender::mouseDragEnd);
-    bindMethod("mouseMomentumBegin", &EventSender::mouseMomentumBegin);
-    bindMethod("mouseMomentumScrollBy", &EventSender::mouseMomentumScrollBy);
-    bindMethod("mouseMomentumEnd", &EventSender::mouseMomentumEnd);
-    bindMethod("releaseTouchPoint", &EventSender::releaseTouchPoint);
-    bindMethod("scheduleAsynchronousClick", &EventSender::scheduleAsynchronousClick);
-    bindMethod("scheduleAsynchronousKeyDown", &EventSender::scheduleAsynchronousKeyDown);
-    bindMethod("setTouchModifier", &EventSender::setTouchModifier);
-    bindMethod("textZoomIn", &EventSender::textZoomIn);
-    bindMethod("textZoomOut", &EventSender::textZoomOut);
-    bindMethod("touchCancel", &EventSender::touchCancel);
-    bindMethod("touchEnd", &EventSender::touchEnd);
-    bindMethod("touchMove", &EventSender::touchMove);
-    bindMethod("touchStart", &EventSender::touchStart);
-    bindMethod("updateTouchPoint", &EventSender::updateTouchPoint);
-    bindMethod("gestureFlingCancel", &EventSender::gestureFlingCancel);
-    bindMethod("gestureFlingStart", &EventSender::gestureFlingStart);
-    bindMethod("gestureScrollBegin", &EventSender::gestureScrollBegin);
-    bindMethod("gestureScrollEnd", &EventSender::gestureScrollEnd);
-    bindMethod("gestureScrollFirstPoint", &EventSender::gestureScrollFirstPoint);
-    bindMethod("gestureScrollUpdate", &EventSender::gestureScrollUpdate);
-    bindMethod("gestureScrollUpdateWithoutPropagation", &EventSender::gestureScrollUpdateWithoutPropagation);
-    bindMethod("gestureTap", &EventSender::gestureTap);
-    bindMethod("gestureTapDown", &EventSender::gestureTapDown);
-    bindMethod("gestureShowPress", &EventSender::gestureShowPress);
-    bindMethod("gestureTapCancel", &EventSender::gestureTapCancel);
-    bindMethod("gestureLongPress", &EventSender::gestureLongPress);
-    bindMethod("gestureLongTap", &EventSender::gestureLongTap);
-    bindMethod("gestureTwoFingerTap", &EventSender::gestureTwoFingerTap);
-    bindMethod("zoomPageIn", &EventSender::zoomPageIn);
-    bindMethod("zoomPageOut", &EventSender::zoomPageOut);
-    bindMethod("setPageScaleFactor", &EventSender::setPageScaleFactor);
-
-    bindProperty("forceLayoutOnEvents", &forceLayoutOnEvents);
-
-    // When set to true (the default value), we batch mouse move and mouse up
-    // events so we can simulate drag & drop.
-    bindProperty("dragMode", &dragMode);
-#ifdef WIN32
-    bindProperty("WM_KEYDOWN", &wmKeyDown);
-    bindProperty("WM_KEYUP", &wmKeyUp);
-    bindProperty("WM_CHAR", &wmChar);
-    bindProperty("WM_DEADCHAR", &wmDeadChar);
-    bindProperty("WM_SYSKEYDOWN", &wmSysKeyDown);
-    bindProperty("WM_SYSKEYUP", &wmSysKeyUp);
-    bindProperty("WM_SYSCHAR", &wmSysChar);
-    bindProperty("WM_SYSDEADCHAR", &wmSysDeadChar);
-#endif
-}
-
-EventSender::~EventSender()
-{
-}
-
-void EventSender::setContextMenuData(const WebContextMenuData& contextMenuData)
-{
-    m_lastContextMenuData = scoped_ptr<WebContextMenuData>(new WebContextMenuData(contextMenuData));
-}
-
-void EventSender::reset()
-{
-    // The test should have finished a drag and the mouse button state.
-    BLINK_ASSERT(currentDragData.isNull());
-    currentDragData.reset();
-    currentDragEffect = blink::WebDragOperationNone;
-    currentDragEffectsAllowed = blink::WebDragOperationNone;
-    if (webview() && pressedButton != WebMouseEvent::ButtonNone)
-        webview()->mouseCaptureLost();
-    pressedButton = WebMouseEvent::ButtonNone;
-    dragMode.set(true);
-    forceLayoutOnEvents.set(true);
-#ifdef WIN32
-    wmKeyDown.set(WM_KEYDOWN);
-    wmKeyUp.set(WM_KEYUP);
-    wmChar.set(WM_CHAR);
-    wmDeadChar.set(WM_DEADCHAR);
-    wmSysKeyDown.set(WM_SYSKEYDOWN);
-    wmSysKeyUp.set(WM_SYSKEYUP);
-    wmSysChar.set(WM_SYSCHAR);
-    wmSysDeadChar.set(WM_SYSDEADCHAR);
-#endif
-    lastMousePos = WebPoint(0, 0);
-    lastClickTimeSec = 0;
-    lastClickPos = WebPoint(0, 0);
-    clickCount = 0;
-    lastButtonType = WebMouseEvent::ButtonNone;
-    timeOffsetMs = 0;
-    touchModifiers = 0;
-    touchPoints.clear();
-    m_taskList.revokeAll();
-    m_currentGestureLocation = WebPoint(0, 0);
-    mouseEventQueue.clear();
-}
-
-void EventSender::doDragDrop(const WebDragData& dragData, WebDragOperationsMask mask)
-{
-    WebMouseEvent event;
-    initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-    WebPoint clientPoint(event.x, event.y);
-    WebPoint screenPoint(event.globalX, event.globalY);
-    currentDragData = dragData;
-    currentDragEffectsAllowed = mask;
-    currentDragEffect = webview()->dragTargetDragEnter(dragData, clientPoint, screenPoint, currentDragEffectsAllowed, 0);
-
-    // Finish processing events.
-    replaySavedEvents();
-}
-
-void EventSender::dumpFilenameBeingDragged(const CppArgumentList&, CppVariant*)
-{
-    WebString filename;
-    WebVector<WebDragData::Item> items = currentDragData.items();
-    for (size_t i = 0; i < items.size(); ++i) {
-        if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
-            filename = items[i].title;
-            break;
-        }
-    }
-    m_delegate->printMessage(std::string("Filename being dragged: ") + filename.utf8().data() + "\n");
-}
-
-WebMouseEvent::Button EventSender::getButtonTypeFromButtonNumber(int buttonCode)
-{
-    if (!buttonCode)
-        return WebMouseEvent::ButtonLeft;
-    if (buttonCode == 2)
-        return WebMouseEvent::ButtonRight;
-    return WebMouseEvent::ButtonMiddle;
-}
-
-int EventSender::getButtonNumberFromSingleArg(const CppArgumentList& arguments)
-{
-    int buttonCode = 0;
-    if (arguments.size() > 0 && arguments[0].isNumber())
-        buttonCode = arguments[0].toInt32();
-    return buttonCode;
-}
-
-void EventSender::updateClickCountForButton(WebMouseEvent::Button buttonType)
-{
-    if ((getCurrentEventTimeSec(m_delegate) - lastClickTimeSec < multipleClickTimeSec)
-        && (!outsideMultiClickRadius(lastMousePos, lastClickPos))
-        && (buttonType == lastButtonType))
-        ++clickCount;
-    else {
-        clickCount = 1;
-        lastButtonType = buttonType;
-    }
-}
-
-//
-// Implemented javascript methods.
-//
-
-void EventSender::mouseDown(const CppArgumentList& arguments, CppVariant* result)
-{
-    if (result) // Could be 0 if invoked asynchronously.
-        result->setNull();
-
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    int buttonNumber = getButtonNumberFromSingleArg(arguments);
-    BLINK_ASSERT(buttonNumber != -1);
-
-    WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumber);
-
-    updateClickCountForButton(buttonType);
-
-    WebMouseEvent event;
-    pressedButton = buttonType;
-    int modifiers = 0;
-    if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString()))
-        modifiers = getKeyModifiers(&(arguments[1]));
-    initMouseEvent(WebInputEvent::MouseDown, buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), modifiers);
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseUp(const CppArgumentList& arguments, CppVariant* result)
-{
-    if (result) // Could be 0 if invoked asynchronously.
-        result->setNull();
-
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    int buttonNumber = getButtonNumberFromSingleArg(arguments);
-    BLINK_ASSERT(buttonNumber != -1);
-
-    WebMouseEvent::Button buttonType = getButtonTypeFromButtonNumber(buttonNumber);
-
-    int modifiers = 0;
-    if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString()))
-        modifiers = getKeyModifiers(&(arguments[1]));
-
-    if (isDragMode() && !replayingSavedEvents) {
-        SavedEvent savedEvent;
-        savedEvent.type = SavedEvent::MouseUp;
-        savedEvent.buttonType = buttonType;
-        savedEvent.modifiers = modifiers;
-        mouseEventQueue.push_back(savedEvent);
-        replaySavedEvents();
-    } else {
-        WebMouseEvent event;
-        initMouseEvent(WebInputEvent::MouseUp, buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), modifiers);
-        doMouseUp(event);
-    }
-}
-
-void EventSender::doMouseUp(const WebMouseEvent& e)
-{
-    webview()->handleInputEvent(e);
-
-    pressedButton = WebMouseEvent::ButtonNone;
-    lastClickTimeSec = e.timeStampSeconds;
-    lastClickPos = lastMousePos;
-
-    // If we're in a drag operation, complete it.
-    if (currentDragData.isNull())
-        return;
-
-    WebPoint clientPoint(e.x, e.y);
-    WebPoint screenPoint(e.globalX, e.globalY);
-    finishDragAndDrop(e, webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0));
-}
-
-void EventSender::finishDragAndDrop(const WebMouseEvent& e, blink::WebDragOperation dragEffect)
-{
-    WebPoint clientPoint(e.x, e.y);
-    WebPoint screenPoint(e.globalX, e.globalY);
-    currentDragEffect = dragEffect;
-    if (currentDragEffect) {
-        // Specifically pass any keyboard modifiers to the drop
-        // method. This allows tests to control the drop type
-        // (i.e. copy or move).
-        webview()->dragTargetDrop(clientPoint, screenPoint, e.modifiers);
-    } else {
-        webview()->dragTargetDragLeave();
-    }
-    webview()->dragSourceEndedAt(clientPoint, screenPoint, currentDragEffect);
-    webview()->dragSourceSystemDragEnded();
-
-    currentDragData.reset();
-}
-
-void EventSender::mouseMoveTo(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-    if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
-        return;
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    WebPoint mousePos(arguments[0].toInt32(), arguments[1].toInt32());
-
-    int modifiers = 0;
-    if (arguments.size() >= 3 && (arguments[2].isObject() || arguments[2].isString()))
-        modifiers = getKeyModifiers(&(arguments[2]));
-
-    if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
-        SavedEvent savedEvent;
-        savedEvent.type = SavedEvent::MouseMove;
-        savedEvent.pos = mousePos;
-        savedEvent.modifiers = modifiers;
-        mouseEventQueue.push_back(savedEvent);
-    } else {
-        WebMouseEvent event;
-        initMouseEvent(WebInputEvent::MouseMove, pressedButton, mousePos, &event, getCurrentEventTimeSec(m_delegate), modifiers);
-        doMouseMove(event);
-    }
-}
-
-void EventSender::doMouseMove(const WebMouseEvent& e)
-{
-    lastMousePos = WebPoint(e.x, e.y);
-
-    webview()->handleInputEvent(e);
-
-    if (pressedButton == WebMouseEvent::ButtonNone || currentDragData.isNull())
-        return;
-    WebPoint clientPoint(e.x, e.y);
-    WebPoint screenPoint(e.globalX, e.globalY);
-    currentDragEffect = webview()->dragTargetDragOver(clientPoint, screenPoint, currentDragEffectsAllowed, 0);
-}
-
-void EventSender::keyDown(const CppArgumentList& arguments, CppVariant* result)
-{
-    if (result)
-        result->setNull();
-    if (arguments.size() < 1 || !arguments[0].isString())
-        return;
-    bool generateChar = false;
-
-    // FIXME: I'm not exactly sure how we should convert the string to a key
-    // event. This seems to work in the cases I tested.
-    // FIXME: Should we also generate a KEY_UP?
-    string codeStr = arguments[0].toString();
-
-    // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
-    // Windows uses \r for "Enter".
-    int code = 0;
-    int text = 0;
-    bool needsShiftKeyModifier = false;
-    if ("\n" == codeStr) {
-        generateChar = true;
-        text = code = VKEY_RETURN;
-    } else if ("rightArrow" == codeStr)
-        code = VKEY_RIGHT;
-    else if ("downArrow" == codeStr)
-        code = VKEY_DOWN;
-    else if ("leftArrow" == codeStr)
-        code = VKEY_LEFT;
-    else if ("upArrow" == codeStr)
-        code = VKEY_UP;
-    else if ("insert" == codeStr)
-        code = VKEY_INSERT;
-    else if ("delete" == codeStr)
-        code = VKEY_DELETE;
-    else if ("pageUp" == codeStr)
-        code = VKEY_PRIOR;
-    else if ("pageDown" == codeStr)
-        code = VKEY_NEXT;
-    else if ("home" == codeStr)
-        code = VKEY_HOME;
-    else if ("end" == codeStr)
-        code = VKEY_END;
-    else if ("printScreen" == codeStr)
-        code = VKEY_SNAPSHOT;
-    else if ("menu" == codeStr)
-        code = VKEY_APPS;
-    else if ("leftControl" == codeStr)
-        code = VKEY_LCONTROL;
-    else if ("rightControl" == codeStr)
-        code = VKEY_RCONTROL;
-    else if ("leftShift" == codeStr)
-        code = VKEY_LSHIFT;
-    else if ("rightShift" == codeStr)
-        code = VKEY_RSHIFT;
-    else if ("leftAlt" == codeStr)
-        code = VKEY_LMENU;
-    else if ("rightAlt" == codeStr)
-        code = VKEY_RMENU;
-    else if ("numLock" == codeStr)
-        code = VKEY_NUMLOCK;
-    else {
-        // Compare the input string with the function-key names defined by the
-        // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
-        // name, set its key code.
-        for (int i = 1; i <= 24; ++i) {
-            char functionChars[10];
-            snprintf(functionChars, 10, "F%d", i);
-            string functionKeyName(functionChars);
-            if (functionKeyName == codeStr) {
-                code = VKEY_F1 + (i - 1);
-                break;
-            }
-        }
-        if (!code) {
-            WebString webCodeStr = WebString::fromUTF8(codeStr.data(), codeStr.size());
-            BLINK_ASSERT(webCodeStr.length() == 1);
-            text = code = webCodeStr.at(0);
-            needsShiftKeyModifier = needsShiftModifier(code);
-            if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
-                code -= 'a' - 'A';
-            generateChar = true;
-        }
-
-        if ("(" == codeStr) {
-            code = '9';
-            needsShiftKeyModifier = true;
-        }
-    }
-
-    // For one generated keyboard event, we need to generate a keyDown/keyUp
-    // pair; refer to EventSender.cpp in Tools/DumpRenderTree/win.
-    // On Windows, we might also need to generate a char event to mimic the
-    // Windows event flow; on other platforms we create a merged event and test
-    // the event flow that that platform provides.
-    WebKeyboardEvent eventDown, eventChar, eventUp;
-    eventDown.type = WebInputEvent::RawKeyDown;
-    eventDown.modifiers = 0;
-    eventDown.windowsKeyCode = code;
-#if defined(__linux__) && defined(TOOLKIT_GTK)
-    eventDown.nativeKeyCode = NativeKeyCodeForWindowsKeyCode(code);
-#endif
-
-    if (generateChar) {
-        eventDown.text[0] = text;
-        eventDown.unmodifiedText[0] = text;
-    }
-    eventDown.setKeyIdentifierFromWindowsKeyCode();
-
-    if (arguments.size() >= 2 && (arguments[1].isObject() || arguments[1].isString())) {
-        eventDown.modifiers = getKeyModifiers(&(arguments[1]));
-#if WIN32 || __APPLE__ || defined(ANDROID) || defined(TOOLKIT_GTK)
-        eventDown.isSystemKey = WebInputEventFactory::isSystemKeyEvent(eventDown);
-#endif
-    }
-
-    if (needsShiftKeyModifier)
-        eventDown.modifiers |= WebInputEvent::ShiftKey;
-
-    // See if KeyLocation argument is given.
-    if (arguments.size() >= 3 && arguments[2].isNumber()) {
-        int location = arguments[2].toInt32();
-        if (location == DOMKeyLocationNumpad)
-            eventDown.modifiers |= WebInputEvent::IsKeyPad;
-    }
-
-    eventChar = eventUp = eventDown;
-    eventUp.type = WebInputEvent::KeyUp;
-    // EventSender.m forces a layout here, with at least one
-    // test (fast/forms/focus-control-to-page.html) relying on this.
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    // In the browser, if a keyboard event corresponds to an editor command,
-    // the command will be dispatched to the renderer just before dispatching
-    // the keyboard event, and then it will be executed in the
-    // RenderView::handleCurrentKeyboardEvent() method, which is called from
-    // third_party/WebKit/Source/WebKit/chromium/src/EditorClientImpl.cpp.
-    // We just simulate the same behavior here.
-    string editCommand;
-    if (getEditCommand(eventDown, &editCommand))
-        m_delegate->setEditCommand(editCommand, "");
-
-    webview()->handleInputEvent(eventDown);
-
-    if (code == VKEY_ESCAPE && !currentDragData.isNull()) {
-        WebMouseEvent event;
-        initMouseEvent(WebInputEvent::MouseDown, pressedButton, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-        finishDragAndDrop(event, blink::WebDragOperationNone);
-    }
-
-    m_delegate->clearEditCommand();
-
-    if (generateChar) {
-        eventChar.type = WebInputEvent::Char;
-        eventChar.keyIdentifier[0] = '\0';
-        webview()->handleInputEvent(eventChar);
-    }
-
-    webview()->handleInputEvent(eventUp);
-}
-
-void EventSender::dispatchMessage(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-#ifdef WIN32
-    if (arguments.size() == 3) {
-        // Grab the message id to see if we need to dispatch it.
-        int msg = arguments[0].toInt32();
-
-        // WebKit's version of this function stuffs a MSG struct and uses
-        // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, which
-        // doesn't need to receive the DeadChar and SysDeadChar messages.
-        if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
-            return;
-
-        if (shouldForceLayoutOnEvents())
-            webview()->layout();
-
-        unsigned long lparam = static_cast<unsigned long>(arguments[2].toDouble());
-        webview()->handleInputEvent(WebInputEventFactory::keyboardEvent(0, msg, arguments[1].toInt32(), lparam));
-    } else
-        BLINK_ASSERT_NOT_REACHED();
-#endif
-}
-
-bool EventSender::needsShiftModifier(int keyCode)
-{
-    // If code is an uppercase letter, assign a SHIFT key to
-    // eventDown.modifier, this logic comes from
-    // Tools/DumpRenderTree/win/EventSender.cpp
-    return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
-}
-
-void EventSender::leapForward(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-    if (arguments.size() < 1 || !arguments[0].isNumber())
-        return;
-
-    int milliseconds = arguments[0].toInt32();
-    if (isDragMode() && pressedButton == WebMouseEvent::ButtonLeft && !replayingSavedEvents) {
-        SavedEvent savedEvent;
-        savedEvent.type = SavedEvent::LeapForward;
-        savedEvent.milliseconds = milliseconds;
-        mouseEventQueue.push_back(savedEvent);
-    } else
-        doLeapForward(milliseconds);
-}
-
-void EventSender::doLeapForward(int milliseconds)
-{
-    advanceEventTime(milliseconds);
-}
-
-// Apple's port of WebKit zooms by a factor of 1.2 (see
-// WebKit/WebView/WebView.mm)
-void EventSender::textZoomIn(const CppArgumentList&, CppVariant* result)
-{
-    webview()->setTextZoomFactor(webview()->textZoomFactor() * 1.2f);
-    result->setNull();
-}
-
-void EventSender::textZoomOut(const CppArgumentList&, CppVariant* result)
-{
-    webview()->setTextZoomFactor(webview()->textZoomFactor() / 1.2f);
-    result->setNull();
-}
-
-void EventSender::zoomPageIn(const CppArgumentList&, CppVariant* result)
-{
-    const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList();
-
-    for (size_t i = 0; i < windowList.size(); ++i)
-        windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->zoomLevel() + 1);
-    result->setNull();
-}
-
-void EventSender::zoomPageOut(const CppArgumentList&, CppVariant* result)
-{
-    const vector<WebTestProxyBase*>& windowList = m_testInterfaces->windowList();
-
-    for (size_t i = 0; i < windowList.size(); ++i)
-        windowList.at(i)->webView()->setZoomLevel(windowList.at(i)->webView()->zoomLevel() - 1);
-    result->setNull();
-}
-
-void EventSender::setPageScaleFactor(const CppArgumentList& arguments, CppVariant* result)
-{
-    if (arguments.size() < 3 || !arguments[0].isNumber() || !arguments[1].isNumber() || !arguments[2].isNumber())
-        return;
-
-    float scaleFactor = static_cast<float>(arguments[0].toDouble());
-    int x = arguments[1].toInt32();
-    int y = arguments[2].toInt32();
-    webview()->setPageScaleFactorLimits(scaleFactor, scaleFactor);
-    webview()->setPageScaleFactor(scaleFactor, WebPoint(x, y));
-    result->setNull();
-}
-
-void EventSender::mouseScrollBy(const CppArgumentList& arguments, CppVariant* result)
-{
-    WebMouseWheelEvent event;
-    initMouseWheelEvent(arguments, result, false, &event);
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::continuousMouseScrollBy(const CppArgumentList& arguments, CppVariant* result)
-{
-    WebMouseWheelEvent event;
-    initMouseWheelEvent(arguments, result, true, &event);
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::replaySavedEvents()
-{
-    replayingSavedEvents = true;
-    while (!mouseEventQueue.empty()) {
-        SavedEvent e = mouseEventQueue.front();
-        mouseEventQueue.pop_front();
-
-        switch (e.type) {
-        case SavedEvent::MouseMove: {
-            WebMouseEvent event;
-            initMouseEvent(WebInputEvent::MouseMove, pressedButton, e.pos, &event, getCurrentEventTimeSec(m_delegate), e.modifiers);
-            doMouseMove(event);
-            break;
-        }
-        case SavedEvent::LeapForward:
-            doLeapForward(e.milliseconds);
-            break;
-        case SavedEvent::MouseUp: {
-            WebMouseEvent event;
-            initMouseEvent(WebInputEvent::MouseUp, e.buttonType, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), e.modifiers);
-            doMouseUp(event);
-            break;
-        }
-        default:
-            BLINK_ASSERT_NOT_REACHED();
-        }
-    }
-
-    replayingSavedEvents = false;
-}
-
-// Because actual context menu is implemented by the browser side,
-// this function does only what LayoutTests are expecting:
-// - Many test checks the count of items. So returning non-zero value makes sense.
-// - Some test compares the count before and after some action. So changing the count based on flags
-//   also makes sense. This function is doing such for some flags.
-// - Some test even checks actual string content. So providing it would be also helpful.
-//
-static vector<WebString> makeMenuItemStringsFor(WebContextMenuData* contextMenu, WebTestDelegate* delegate)
-{
-    // These constants are based on Safari's context menu because tests are made for it.
-    static const char* nonEditableMenuStrings[] = { "Back", "Reload Page", "Open in Dashbaord", "<separator>", "View Source", "Save Page As", "Print Page", "Inspect Element", 0 };
-    static const char* editableMenuStrings[] = { "Cut", "Copy", "<separator>", "Paste", "Spelling and Grammar", "Substitutions, Transformations", "Font", "Speech", "Paragraph Direction", "<separator>", 0 };
-
-    // This is possible because mouse events are cancelleable.
-    if (!contextMenu)
-        return vector<WebString>();
-
-    vector<WebString> strings;
-
-    if (contextMenu->isEditable) {
-        for (const char** item = editableMenuStrings; *item; ++item)
-            strings.push_back(WebString::fromUTF8(*item));
-        WebVector<WebString> suggestions;
-        MockSpellCheck::fillSuggestionList(contextMenu->misspelledWord, &suggestions);
-        for (size_t i = 0; i < suggestions.size(); ++i)
-            strings.push_back(suggestions[i]);
-    } else {
-        for (const char** item = nonEditableMenuStrings; *item; ++item)
-            strings.push_back(WebString::fromUTF8(*item));
-    }
-
-    return strings;
-}
-
-void EventSender::contextClick(const CppArgumentList& arguments, CppVariant* result)
-{
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    updateClickCountForButton(WebMouseEvent::ButtonRight);
-
-    // Clears last context menu data because we need to know if the context menu be requested
-    // after following mouse events.
-    m_lastContextMenuData.reset();
-
-    // Generate right mouse down and up.
-    WebMouseEvent event;
-    // This is a hack to work around only allowing a single pressed button since we want to
-    // test the case where both the left and right mouse buttons are pressed.
-    if (pressedButton == WebMouseEvent::ButtonNone)
-        pressedButton = WebMouseEvent::ButtonRight;
-    initMouseEvent(WebInputEvent::MouseDown, WebMouseEvent::ButtonRight, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-    webview()->handleInputEvent(event);
-
-#ifdef WIN32
-    initMouseEvent(WebInputEvent::MouseUp, WebMouseEvent::ButtonRight, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-    webview()->handleInputEvent(event);
-
-    pressedButton = WebMouseEvent::ButtonNone;
-#endif
-
-    NPObject* resultArray = WebBindings::makeStringArray(makeMenuItemStringsFor(m_lastContextMenuData.get(), m_delegate));
-    result->set(resultArray);
-    WebBindings::releaseObject(resultArray);
-
-    m_lastContextMenuData.reset();
-}
-
-class MouseDownTask: public WebMethodTask<EventSender> {
-public:
-    MouseDownTask(EventSender* obj, const CppArgumentList& arg)
-        : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
-    virtual void runIfValid() OVERRIDE { m_object->mouseDown(m_arguments, 0); }
-
-private:
-    CppArgumentList m_arguments;
-};
-
-class MouseUpTask: public WebMethodTask<EventSender> {
-public:
-    MouseUpTask(EventSender* obj, const CppArgumentList& arg)
-        : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
-    virtual void runIfValid() OVERRIDE { m_object->mouseUp(m_arguments, 0); }
-
-private:
-    CppArgumentList m_arguments;
-};
-
-void EventSender::scheduleAsynchronousClick(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    m_delegate->postTask(new MouseDownTask(this, arguments));
-    m_delegate->postTask(new MouseUpTask(this, arguments));
-}
-
-class KeyDownTask : public WebMethodTask<EventSender> {
-public:
-    KeyDownTask(EventSender* obj, const CppArgumentList& arg)
-        : WebMethodTask<EventSender>(obj), m_arguments(arg) { }
-    virtual void runIfValid() OVERRIDE { m_object->keyDown(m_arguments, 0); }
-
-private:
-    CppArgumentList m_arguments;
-};
-
-void EventSender::scheduleAsynchronousKeyDown(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    m_delegate->postTask(new KeyDownTask(this, arguments));
-}
-
-void EventSender::beginDragWithFiles(const CppArgumentList& arguments, CppVariant* result)
-{
-    currentDragData.initialize();
-    vector<string> files = arguments[0].toStringVector();
-    WebVector<WebString> absoluteFilenames(files.size());
-    for (size_t i = 0; i < files.size(); ++i) {
-        WebDragData::Item item;
-        item.storageType = WebDragData::Item::StorageTypeFilename;
-        item.filenameData = m_delegate->getAbsoluteWebStringFromUTF8Path(files[i]);
-        currentDragData.addItem(item);
-        absoluteFilenames[i] = item.filenameData;
-    }
-    currentDragData.setFilesystemId(m_delegate->registerIsolatedFileSystem(absoluteFilenames));
-    currentDragEffectsAllowed = blink::WebDragOperationCopy;
-
-    // Provide a drag source.
-    webview()->dragTargetDragEnter(currentDragData, lastMousePos, lastMousePos, currentDragEffectsAllowed, 0);
-
-    // dragMode saves events and then replays them later. We don't need/want that.
-    dragMode.set(false);
-
-    // Make the rest of eventSender think a drag is in progress.
-    pressedButton = WebMouseEvent::ButtonLeft;
-
-    result->setNull();
-}
-
-void EventSender::addTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-    WebTouchPoint touchPoint;
-    touchPoint.state = WebTouchPoint::StatePressed;
-    touchPoint.position = WebFloatPoint(arguments[0].toInt32(), arguments[1].toInt32());
-    touchPoint.screenPosition = touchPoint.position;
-
-    if (arguments.size() > 2) {
-        int radiusX = arguments[2].toInt32();
-        int radiusY = radiusX;
-        if (arguments.size() > 3)
-            radiusY = arguments[3].toInt32();
-
-        touchPoint.radiusX = radiusX;
-        touchPoint.radiusY = radiusY;
-    }
-
-    int lowestId = 0;
-    for (size_t i = 0; i < touchPoints.size(); i++) {
-        if (touchPoints[i].id == lowestId)
-            lowestId++;
-    }
-    touchPoint.id = lowestId;
-    touchPoints.push_back(touchPoint);
-}
-
-void EventSender::clearTouchPoints(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-    touchPoints.clear();
-}
-
-void EventSender::releaseTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-    const unsigned index = arguments[0].toInt32();
-    BLINK_ASSERT(index < touchPoints.size());
-
-    WebTouchPoint* touchPoint = &touchPoints[index];
-    touchPoint->state = WebTouchPoint::StateReleased;
-}
-
-void EventSender::setTouchModifier(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-    int mask = 0;
-    const string keyName = arguments[0].toString();
-    if (keyName == "shift")
-        mask = WebInputEvent::ShiftKey;
-    else if (keyName == "alt")
-        mask = WebInputEvent::AltKey;
-    else if (keyName == "ctrl")
-        mask = WebInputEvent::ControlKey;
-    else if (keyName == "meta")
-        mask = WebInputEvent::MetaKey;
-
-    if (arguments[1].toBoolean())
-        touchModifiers |= mask;
-    else
-        touchModifiers &= ~mask;
-}
-
-void EventSender::updateTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-    const unsigned index = arguments[0].toInt32();
-    BLINK_ASSERT(index < touchPoints.size());
-
-    WebTouchPoint* touchPoint = &touchPoints[index];
-    touchPoint->state = WebTouchPoint::StateMoved;
-    touchPoint->position = WebFloatPoint(arguments[1].toInt32(), arguments[2].toInt32());
-    touchPoint->screenPosition = touchPoint->position;
-}
-
-void EventSender::cancelTouchPoint(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-
-    const unsigned index = arguments[0].toInt32();
-    BLINK_ASSERT(index < touchPoints.size());
-
-    WebTouchPoint* touchPoint = &touchPoints[index];
-    touchPoint->state = WebTouchPoint::StateCancelled;
-}
-
-void EventSender::sendCurrentTouchEvent(const WebInputEvent::Type type)
-{
-    BLINK_ASSERT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap) > touchPoints.size());
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    WebTouchEvent touchEvent;
-    touchEvent.type = type;
-    touchEvent.modifiers = touchModifiers;
-    touchEvent.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
-    touchEvent.touchesLength = touchPoints.size();
-    for (unsigned i = 0; i < touchPoints.size(); ++i)
-        touchEvent.touches[i] = touchPoints[i];
-    webview()->handleInputEvent(touchEvent);
-
-    for (unsigned i = 0; i < touchPoints.size(); ++i) {
-        WebTouchPoint* touchPoint = &touchPoints[i];
-        if (touchPoint->state == WebTouchPoint::StateReleased) {
-            touchPoints.erase(touchPoints.begin() + i);
-            --i;
-        } else
-            touchPoint->state = WebTouchPoint::StateStationary;
-    }
-}
-
-void EventSender::mouseDragBegin(const CppArgumentList& arguments, CppVariant* result)
-{
-    WebMouseWheelEvent event;
-    initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-    event.phase = WebMouseWheelEvent::PhaseBegan;
-    event.hasPreciseScrollingDeltas = true;
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseDragEnd(const CppArgumentList& arguments, CppVariant* result)
-{
-    WebMouseWheelEvent event;
-    initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-    event.phase = WebMouseWheelEvent::PhaseEnded;
-    event.hasPreciseScrollingDeltas = true;
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseMomentumBegin(const CppArgumentList& arguments, CppVariant* result)
-{
-    WebMouseWheelEvent event;
-    initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-    event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
-    event.hasPreciseScrollingDeltas = true;
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseMomentumScrollBy(const CppArgumentList& arguments, CppVariant* result)
-{
-    WebMouseWheelEvent event;
-    initMouseWheelEvent(arguments, result, true, &event);
-    event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
-    event.hasPreciseScrollingDeltas = true;
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::mouseMomentumEnd(const CppArgumentList& arguments, CppVariant* result)
-{
-    WebMouseWheelEvent event;
-    initMouseEvent(WebInputEvent::MouseWheel, WebMouseEvent::ButtonNone, lastMousePos, &event, getCurrentEventTimeSec(m_delegate), 0);
-    event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
-    event.hasPreciseScrollingDeltas = true;
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::initMouseWheelEvent(const CppArgumentList& arguments, CppVariant* result, bool continuous, WebMouseWheelEvent* event)
-{
-    result->setNull();
-
-    if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
-        return;
-
-    // Force a layout here just to make sure every position has been
-    // determined before we send events (as well as all the other methods
-    // that send an event do).
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    int horizontal = arguments[0].toInt32();
-    int vertical = arguments[1].toInt32();
-    int paged = false;
-    int hasPreciseScrollingDeltas = false;
-    int modifiers = 0;
-
-    if (arguments.size() > 2 && arguments[2].isBool())
-        paged = arguments[2].toBoolean();
-
-    if (arguments.size() > 3 && arguments[3].isBool())
-        hasPreciseScrollingDeltas = arguments[3].toBoolean();
-
-    if (arguments.size() > 4 && (arguments[4].isObject() || arguments[4].isString()))
-        modifiers = getKeyModifiers(&(arguments[4]));
-
-    initMouseEvent(WebInputEvent::MouseWheel, pressedButton, lastMousePos, event, getCurrentEventTimeSec(m_delegate), modifiers);
-    event->wheelTicksX = static_cast<float>(horizontal);
-    event->wheelTicksY = static_cast<float>(vertical);
-    event->deltaX = event->wheelTicksX;
-    event->deltaY = event->wheelTicksY;
-    event->scrollByPage = paged;
-    event->hasPreciseScrollingDeltas = hasPreciseScrollingDeltas;
-
-    if (continuous) {
-        event->wheelTicksX /= scrollbarPixelsPerTick;
-        event->wheelTicksY /= scrollbarPixelsPerTick;
-    } else {
-        event->deltaX *= scrollbarPixelsPerTick;
-        event->deltaY *= scrollbarPixelsPerTick;
-    }
-}
-
-void EventSender::touchEnd(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-    sendCurrentTouchEvent(WebInputEvent::TouchEnd);
-}
-
-void EventSender::touchMove(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-    sendCurrentTouchEvent(WebInputEvent::TouchMove);
-}
-
-void EventSender::touchStart(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-    sendCurrentTouchEvent(WebInputEvent::TouchStart);
-}
-
-void EventSender::touchCancel(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-    sendCurrentTouchEvent(WebInputEvent::TouchCancel);
-}
-
-void EventSender::gestureScrollBegin(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureScrollBegin, arguments);
-}
-
-void EventSender::gestureScrollEnd(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureScrollEnd, arguments);
-}
-
-void EventSender::gestureScrollUpdate(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureScrollUpdate, arguments);
-}
-
-void EventSender::gestureScrollUpdateWithoutPropagation(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, arguments);
-}
-
-void EventSender::gestureTap(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureTap, arguments);
-}
-
-void EventSender::gestureTapDown(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureTapDown, arguments);
-}
-
-void EventSender::gestureShowPress(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureShowPress, arguments);
-}
-
-void EventSender::gestureTapCancel(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureTapCancel, arguments);
-}
-
-void EventSender::gestureLongPress(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureLongPress, arguments);
-}
-
-void EventSender::gestureLongTap(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureLongTap, arguments);
-}
-
-void EventSender::gestureTwoFingerTap(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    gestureEvent(WebInputEvent::GestureTwoFingerTap, arguments);
-}
-
-void EventSender::gestureScrollFirstPoint(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
-        return;
-
-    WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
-    m_currentGestureLocation = point;
-}
-
-void EventSender::gestureEvent(WebInputEvent::Type type, const CppArgumentList& arguments)
-{
-    if (arguments.size() < 2 || !arguments[0].isNumber() || !arguments[1].isNumber())
-        return;
-
-    WebPoint point(arguments[0].toInt32(), arguments[1].toInt32());
-
-    WebGestureEvent event;
-    event.type = type;
-
-    switch (type) {
-    case WebInputEvent::GestureScrollUpdate:
-    case WebInputEvent::GestureScrollUpdateWithoutPropagation:
-        event.data.scrollUpdate.deltaX = static_cast<float>(arguments[0].toDouble());
-        event.data.scrollUpdate.deltaY = static_cast<float>(arguments[1].toDouble());
-        event.x = m_currentGestureLocation.x;
-        event.y = m_currentGestureLocation.y;
-        m_currentGestureLocation.x = m_currentGestureLocation.x + event.data.scrollUpdate.deltaX;
-        m_currentGestureLocation.y = m_currentGestureLocation.y + event.data.scrollUpdate.deltaY;
-        break;
-
-    case WebInputEvent::GestureScrollBegin:
-        m_currentGestureLocation = WebPoint(point.x, point.y);
-        event.x = m_currentGestureLocation.x;
-        event.y = m_currentGestureLocation.y;
-        break;
-    case WebInputEvent::GestureScrollEnd:
-    case WebInputEvent::GestureFlingStart:
-        event.x = m_currentGestureLocation.x;
-        event.y = m_currentGestureLocation.y;
-        break;
-    case WebInputEvent::GestureTap:
-        if (arguments.size() >= 3)
-            event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
-        else
-          event.data.tap.tapCount = 1;
-        event.x = point.x;
-        event.y = point.y;
-        break;
-    case WebInputEvent::GestureTapUnconfirmed:
-        if (arguments.size() >= 3)
-            event.data.tap.tapCount = static_cast<float>(arguments[2].toDouble());
-        else
-          event.data.tap.tapCount = 1;
-        event.x = point.x;
-        event.y = point.y;
-        break;
-    case WebInputEvent::GestureTapDown:
-        event.x = point.x;
-        event.y = point.y;
-        if (arguments.size() >= 4) {
-            event.data.tapDown.width = static_cast<float>(arguments[2].toDouble());
-            event.data.tapDown.height = static_cast<float>(arguments[3].toDouble());
-        }
-        break;
-    case WebInputEvent::GestureShowPress:
-        event.x = point.x;
-        event.y = point.y;
-        if (arguments.size() >= 4) {
-            event.data.showPress.width = static_cast<float>(arguments[2].toDouble());
-            event.data.showPress.height = static_cast<float>(arguments[3].toDouble());
-        }
-        break;
-    case WebInputEvent::GestureTapCancel:
-        event.x = point.x;
-        event.y = point.y;
-        break;
-    case WebInputEvent::GestureLongPress:
-        event.x = point.x;
-        event.y = point.y;
-        if (arguments.size() >= 4) {
-            event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
-            event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
-        }
-        break;
-    case WebInputEvent::GestureLongTap:
-        event.x = point.x;
-        event.y = point.y;
-        if (arguments.size() >= 4) {
-            event.data.longPress.width = static_cast<float>(arguments[2].toDouble());
-            event.data.longPress.height = static_cast<float>(arguments[3].toDouble());
-        }
-        break;
-    case WebInputEvent::GestureTwoFingerTap:
-        event.x = point.x;
-        event.y = point.y;
-        if (arguments.size() >= 4) {
-            event.data.twoFingerTap.firstFingerWidth = static_cast<float>(arguments[2].toDouble());
-            event.data.twoFingerTap.firstFingerHeight = static_cast<float>(arguments[3].toDouble());
-        }
-        break;
-    default:
-        BLINK_ASSERT_NOT_REACHED();
-    }
-
-    event.globalX = event.x;
-    event.globalY = event.y;
-    event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
-
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    webview()->handleInputEvent(event);
-
-    // Long press might start a drag drop session. Complete it if so.
-    if (type == WebInputEvent::GestureLongPress && !currentDragData.isNull()) {
-        WebMouseEvent mouseEvent;
-        initMouseEvent(WebInputEvent::MouseDown, pressedButton, point, &mouseEvent, getCurrentEventTimeSec(m_delegate), 0);
-        finishDragAndDrop(mouseEvent, blink::WebDragOperationNone);
-    }
-}
-
-void EventSender::gestureFlingCancel(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-
-    WebGestureEvent event;
-    event.type = WebInputEvent::GestureFlingCancel;
-    event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
-
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    webview()->handleInputEvent(event);
-}
-
-void EventSender::gestureFlingStart(const CppArgumentList& arguments, CppVariant* result)
-{
-    result->setNull();
-    if (arguments.size() < 4)
-        return;
-
-    for (int i = 0; i < 4; i++)
-        if (!arguments[i].isNumber())
-            return;
-
-    WebGestureEvent event;
-    event.type = WebInputEvent::GestureFlingStart;
-
-    event.x = static_cast<float>(arguments[0].toDouble());
-    event.y = static_cast<float>(arguments[1].toDouble());
-    event.globalX = event.x;
-    event.globalY = event.y;
-
-    event.data.flingStart.velocityX = static_cast<float>(arguments[2].toDouble());
-    event.data.flingStart.velocityY = static_cast<float>(arguments[3].toDouble());
-    event.timeStampSeconds = getCurrentEventTimeSec(m_delegate);
-
-    if (shouldForceLayoutOnEvents())
-        webview()->layout();
-
-    webview()->handleInputEvent(event);
-}
-
-//
-// Unimplemented stubs
-//
-
-void EventSender::enableDOMUIEventLogging(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-}
-
-void EventSender::fireKeyboardEventsToElement(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-}
-
-void EventSender::clearKillRing(const CppArgumentList&, CppVariant* result)
-{
-    result->setNull();
-}
-
-}
diff --git a/content/shell/renderer/test_runner/EventSender.h b/content/shell/renderer/test_runner/EventSender.h
deleted file mode 100644
index 1f5244f..0000000
--- a/content/shell/renderer/test_runner/EventSender.h
+++ /dev/null
@@ -1,188 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/*
-  EventSender class:
-  Bound to a JavaScript window.eventSender object using
-  CppBoundClass::bindToJavascript(), this allows layout tests to fire DOM events.
-*/
-
-#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENTSENDER_H_
-#define CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENTSENDER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/shell/renderer/test_runner/CppBoundClass.h"
-#include "content/shell/renderer/test_runner/WebTask.h"
-#include "third_party/WebKit/public/platform/WebPoint.h"
-#include "third_party/WebKit/public/web/WebDragOperation.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace blink {
-class WebDragData;
-class WebView;
-struct WebContextMenuData;
-}
-
-namespace WebTestRunner {
-
-class TestInterfaces;
-class WebTestDelegate;
-
-class EventSender : public CppBoundClass {
-public:
-    explicit EventSender(TestInterfaces*);
-    virtual ~EventSender();
-
-    void setDelegate(WebTestDelegate* delegate) { m_delegate = delegate; }
-    void setWebView(blink::WebView* webView) { m_webView = webView; }
-
-    void setContextMenuData(const blink::WebContextMenuData&);
-
-    // Resets some static variable state.
-    void reset();
-
-    // Simulate drag&drop system call.
-    void doDragDrop(const blink::WebDragData&, blink::WebDragOperationsMask);
-
-    // Test helper for dragging out images.
-    void dumpFilenameBeingDragged(const CppArgumentList&, CppVariant*);
-
-    // JS callback methods.
-    void contextClick(const CppArgumentList&, CppVariant*);
-    void mouseDown(const CppArgumentList&, CppVariant*);
-    void mouseUp(const CppArgumentList&, CppVariant*);
-    void mouseMoveTo(const CppArgumentList&, CppVariant*);
-    void leapForward(const CppArgumentList&, CppVariant*);
-    void keyDown(const CppArgumentList&, CppVariant*);
-    void dispatchMessage(const CppArgumentList&, CppVariant*);
-    // FIXME: These aren't really events. They should be moved to layout controller.
-    void textZoomIn(const CppArgumentList&, CppVariant*);
-    void textZoomOut(const CppArgumentList&, CppVariant*);
-    void zoomPageIn(const CppArgumentList&, CppVariant*);
-    void zoomPageOut(const CppArgumentList&, CppVariant*);
-    void setPageScaleFactor(const CppArgumentList&, CppVariant*);
-
-    void mouseDragBegin(const CppArgumentList&, CppVariant*);
-    void mouseDragEnd(const CppArgumentList&, CppVariant*);
-    void mouseMomentumBegin(const CppArgumentList&, CppVariant*);
-    void mouseMomentumScrollBy(const CppArgumentList&, CppVariant*);
-    void mouseMomentumEnd(const CppArgumentList&, CppVariant*);
-    void mouseScrollBy(const CppArgumentList&, CppVariant*);
-    void continuousMouseScrollBy(const CppArgumentList&, CppVariant*);
-    void scheduleAsynchronousClick(const CppArgumentList&, CppVariant*);
-    void scheduleAsynchronousKeyDown(const CppArgumentList&, CppVariant*);
-    void beginDragWithFiles(const CppArgumentList&, CppVariant*);
-    CppVariant dragMode;
-
-    void addTouchPoint(const CppArgumentList&, CppVariant*);
-    void cancelTouchPoint(const CppArgumentList&, CppVariant*);
-    void clearTouchPoints(const CppArgumentList&, CppVariant*);
-    void releaseTouchPoint(const CppArgumentList&, CppVariant*);
-    void setTouchModifier(const CppArgumentList&, CppVariant*);
-    void touchCancel(const CppArgumentList&, CppVariant*);
-    void touchEnd(const CppArgumentList&, CppVariant*);
-    void touchMove(const CppArgumentList&, CppVariant*);
-    void touchStart(const CppArgumentList&, CppVariant*);
-    void updateTouchPoint(const CppArgumentList&, CppVariant*);
-
-    void gestureFlingCancel(const CppArgumentList&, CppVariant*);
-    void gestureFlingStart(const CppArgumentList&, CppVariant*);
-    void gestureScrollBegin(const CppArgumentList&, CppVariant*);
-    void gestureScrollEnd(const CppArgumentList&, CppVariant*);
-    void gestureScrollFirstPoint(const CppArgumentList&, CppVariant*);
-    void gestureScrollUpdate(const CppArgumentList&, CppVariant*);
-    void gestureScrollUpdateWithoutPropagation(const CppArgumentList&, CppVariant*);
-    void gestureTap(const CppArgumentList&, CppVariant*);
-    void gestureTapDown(const CppArgumentList&, CppVariant*);
-    void gestureShowPress(const CppArgumentList&, CppVariant*);
-    void gestureTapCancel(const CppArgumentList&, CppVariant*);
-    void gestureLongPress(const CppArgumentList&, CppVariant*);
-    void gestureLongTap(const CppArgumentList&, CppVariant*);
-    void gestureTwoFingerTap(const CppArgumentList&, CppVariant*);
-    void gestureEvent(blink::WebInputEvent::Type, const CppArgumentList&);
-
-    // Setting this to false makes EventSender not force layout() calls.
-    // This makes it possible to test the standard WebCore event dispatch.
-    CppVariant forceLayoutOnEvents;
-
-    // Unimplemented stubs
-    void enableDOMUIEventLogging(const CppArgumentList&, CppVariant*);
-    void fireKeyboardEventsToElement(const CppArgumentList&, CppVariant*);
-    void clearKillRing(const CppArgumentList&, CppVariant*);
-
-    // Properties used in layout tests.
-#if defined(OS_WIN)
-    CppVariant wmKeyDown;
-    CppVariant wmKeyUp;
-    CppVariant wmChar;
-    CppVariant wmDeadChar;
-    CppVariant wmSysKeyDown;
-    CppVariant wmSysKeyUp;
-    CppVariant wmSysChar;
-    CppVariant wmSysDeadChar;
-#endif
-
-    WebTaskList* taskList() { return &m_taskList; }
-
-private:
-    blink::WebView* webview() { return m_webView; }
-
-    // Returns true if dragMode is true.
-    bool isDragMode() { return dragMode.isBool() && dragMode.toBoolean(); }
-
-    bool shouldForceLayoutOnEvents() const { return forceLayoutOnEvents.isBool() && forceLayoutOnEvents.toBoolean(); }
-
-    // Sometimes we queue up mouse move and mouse up events for drag drop
-    // handling purposes. These methods dispatch the event.
-    void doMouseMove(const blink::WebMouseEvent&);
-    void doMouseUp(const blink::WebMouseEvent&);
-    static void doLeapForward(int milliseconds);
-    void replaySavedEvents();
-
-    // Helper to return the button type given a button code
-    static blink::WebMouseEvent::Button getButtonTypeFromButtonNumber(int);
-
-    // Helper to extract the button number from the optional argument in
-    // mouseDown and mouseUp
-    static int getButtonNumberFromSingleArg(const CppArgumentList&);
-
-    // Returns true if the specified key code passed in needs a shift key
-    // modifier to be passed into the generated event.
-    bool needsShiftModifier(int);
-
-    void finishDragAndDrop(const blink::WebMouseEvent&, blink::WebDragOperation);
-    void updateClickCountForButton(blink::WebMouseEvent::Button);
-
-    // Compose a touch event from the current touch points and send it.
-    void sendCurrentTouchEvent(const blink::WebInputEvent::Type);
-
-    // Init a mouse wheel event from the given args.
-    void initMouseWheelEvent(const CppArgumentList&, CppVariant*, bool continuous, blink::WebMouseWheelEvent*);
-
-    WebTaskList m_taskList;
-
-    TestInterfaces* m_testInterfaces;
-    WebTestDelegate* m_delegate;
-    blink::WebView* m_webView;
-
-    scoped_ptr<blink::WebContextMenuData> m_lastContextMenuData;
-
-    // Location of the touch point that initiated a gesture.
-    blink::WebPoint m_currentGestureLocation;
-
-    // Location of last mouseMoveTo event.
-    static blink::WebPoint lastMousePos;
-
-    // Currently pressed mouse button (Left/Right/Middle or None)
-    static blink::WebMouseEvent::Button pressedButton;
-
-    // The last button number passed to mouseDown and mouseUp.
-    // Used to determine whether the click count continues to
-    // increment or not.
-    static blink::WebMouseEvent::Button lastButtonType;
-};
-
-}
-
-#endif  // CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENTSENDER_H_
diff --git a/content/shell/renderer/test_runner/MockWebMediaStreamCenter.cpp b/content/shell/renderer/test_runner/MockWebMediaStreamCenter.cpp
index 46cd8f5..94ba472 100644
--- a/content/shell/renderer/test_runner/MockWebMediaStreamCenter.cpp
+++ b/content/shell/renderer/test_runner/MockWebMediaStreamCenter.cpp
@@ -7,6 +7,7 @@
 #include "content/shell/renderer/test_runner/TestInterfaces.h"
 #include "content/shell/renderer/test_runner/WebTestDelegate.h"
 #include "third_party/WebKit/public/platform/WebAudioDestinationConsumer.h"
+#include "third_party/WebKit/public/platform/WebAudioSourceProvider.h"
 #include "third_party/WebKit/public/platform/WebMediaStream.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
 #include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
@@ -116,4 +117,9 @@
     m_interfaces->delegate()->postTask(new NewTrackTask(this, stream));
 }
 
+blink::WebAudioSourceProvider* MockWebMediaStreamCenter::createWebAudioSourceFromMediaStreamTrack(const blink::WebMediaStreamTrack& track)
+{
+    return NULL;
+}
+
 }
diff --git a/content/shell/renderer/test_runner/MockWebMediaStreamCenter.h b/content/shell/renderer/test_runner/MockWebMediaStreamCenter.h
index 79e5fdb..fbc67a7 100644
--- a/content/shell/renderer/test_runner/MockWebMediaStreamCenter.h
+++ b/content/shell/renderer/test_runner/MockWebMediaStreamCenter.h
@@ -12,6 +12,7 @@
 #include "content/shell/renderer/test_runner/WebTask.h"
 
 namespace blink {
+class WebAudioSourceProvider;
 class WebMediaStreamCenterClient;
 };
 
@@ -31,6 +32,8 @@
     virtual void didStopLocalMediaStream(const blink::WebMediaStream&) OVERRIDE;
     virtual bool didStopMediaStreamTrack(const blink::WebMediaStreamTrack&) OVERRIDE;
     virtual void didCreateMediaStream(blink::WebMediaStream&) OVERRIDE;
+    virtual blink::WebAudioSourceProvider* createWebAudioSourceFromMediaStreamTrack(
+        const blink::WebMediaStreamTrack&) OVERRIDE;
 
    // Task related methods
     WebTaskList* taskList() { return &m_taskList; }
diff --git a/content/shell/renderer/test_runner/TestInterfaces.cpp b/content/shell/renderer/test_runner/TestInterfaces.cpp
index 5e08ac3..c7c4d2d 100644
--- a/content/shell/renderer/test_runner/TestInterfaces.cpp
+++ b/content/shell/renderer/test_runner/TestInterfaces.cpp
@@ -7,9 +7,9 @@
 #include <string>
 
 #include "base/strings/stringprintf.h"
-#include "content/shell/renderer/test_runner/EventSender.h"
 #include "content/shell/renderer/test_runner/WebTestProxy.h"
 #include "content/shell/renderer/test_runner/accessibility_controller.h"
+#include "content/shell/renderer/test_runner/event_sender.h"
 #include "content/shell/renderer/test_runner/gamepad_controller.h"
 #include "content/shell/renderer/test_runner/text_input_controller.h"
 #include "content/shell/renderer/test_runner/test_runner.h"
@@ -27,7 +27,7 @@
 
 TestInterfaces::TestInterfaces()
     : m_accessibilityController(new content::AccessibilityController())
-    , m_eventSender(new EventSender(this))
+    , m_eventSender(new content::EventSender(this))
     , m_gamepadController(new content::GamepadController())
     , m_textInputController(new content::TextInputController())
     , m_testRunner(new content::TestRunner(this))
@@ -44,13 +44,13 @@
 TestInterfaces::~TestInterfaces()
 {
     m_accessibilityController->SetWebView(0);
-    m_eventSender->setWebView(0);
+    m_eventSender->SetWebView(0);
     // m_gamepadController doesn't depend on WebView.
     m_textInputController->SetWebView(NULL);
     m_testRunner->SetWebView(0, 0);
 
     m_accessibilityController->SetDelegate(0);
-    m_eventSender->setDelegate(0);
+    m_eventSender->SetDelegate(0);
     m_gamepadController->SetDelegate(0);
     // m_textInputController doesn't depend on WebTestDelegate.
     m_testRunner->SetDelegate(0);
@@ -60,7 +60,7 @@
 {
     m_proxy = proxy;
     m_accessibilityController->SetWebView(webView);
-    m_eventSender->setWebView(webView);
+    m_eventSender->SetWebView(webView);
     // m_gamepadController doesn't depend on WebView.
     m_textInputController->SetWebView(webView);
     m_testRunner->SetWebView(webView, proxy);
@@ -69,7 +69,7 @@
 void TestInterfaces::setDelegate(WebTestDelegate* delegate)
 {
     m_accessibilityController->SetDelegate(delegate);
-    m_eventSender->setDelegate(delegate);
+    m_eventSender->SetDelegate(delegate);
     m_gamepadController->SetDelegate(delegate);
     // m_textInputController doesn't depend on WebTestDelegate.
     m_testRunner->SetDelegate(delegate);
@@ -79,7 +79,7 @@
 void TestInterfaces::bindTo(WebFrame* frame)
 {
     m_accessibilityController->Install(frame);
-    m_eventSender->bindToJavascript(frame, WebString::fromUTF8("eventSender"));
+    m_eventSender->Install(frame);
     m_gamepadController->Install(frame);
     m_textInputController->Install(frame);
     m_testRunner->Install(frame);
@@ -88,7 +88,7 @@
 void TestInterfaces::resetTestHelperControllers()
 {
     m_accessibilityController->Reset();
-    m_eventSender->reset();
+    m_eventSender->Reset();
     m_gamepadController->Reset();
     // m_textInputController doesn't have any state to reset.
     WebCache::clear();
@@ -157,7 +157,7 @@
     return m_accessibilityController.get();
 }
 
-EventSender* TestInterfaces::eventSender()
+content::EventSender* TestInterfaces::eventSender()
 {
     return m_eventSender.get();
 }
diff --git a/content/shell/renderer/test_runner/TestInterfaces.h b/content/shell/renderer/test_runner/TestInterfaces.h
index 5e6ba1f..4bc50d9 100644
--- a/content/shell/renderer/test_runner/TestInterfaces.h
+++ b/content/shell/renderer/test_runner/TestInterfaces.h
@@ -26,6 +26,7 @@
 
 namespace content {
 class AccessibilityController;
+class EventSender;
 class GamepadController;
 class TestRunner;
 class TextInputController;
@@ -33,7 +34,6 @@
 
 namespace WebTestRunner {
 
-class EventSender;
 class WebTestDelegate;
 class WebTestProxyBase;
 
@@ -54,7 +54,7 @@
     void windowClosed(WebTestProxyBase*);
 
     content::AccessibilityController* accessibilityController();
-    EventSender* eventSender();
+    content::EventSender* eventSender();
     content::TestRunner* testRunner();
     WebTestDelegate* delegate();
     WebTestProxyBase* proxy();
@@ -63,7 +63,7 @@
 
 private:
     scoped_ptr<content::AccessibilityController> m_accessibilityController;
-    scoped_ptr<EventSender> m_eventSender;
+    scoped_ptr<content::EventSender> m_eventSender;
     scoped_ptr<content::GamepadController> m_gamepadController;
     scoped_ptr<content::TextInputController> m_textInputController;
     scoped_ptr<content::TestRunner> m_testRunner;
diff --git a/content/shell/renderer/test_runner/TestPlugin.cpp b/content/shell/renderer/test_runner/TestPlugin.cpp
index b416808..91045ce 100644
--- a/content/shell/renderer/test_runner/TestPlugin.cpp
+++ b/content/shell/renderer/test_runner/TestPlugin.cpp
@@ -91,7 +91,7 @@
         char buffer[100];
         snprintf(buffer,
                  sizeof(buffer),
-                 "* %f, %f: %s\n",
+                 "* %.2f, %.2f: %s\n",
                  points[i].position.x,
                  points[i].position.y,
                  pointState(points[i].state));
diff --git a/content/shell/renderer/test_runner/WebFrameTestProxy.h b/content/shell/renderer/test_runner/WebFrameTestProxy.h
index 238712b..fef3218 100644
--- a/content/shell/renderer/test_runner/WebFrameTestProxy.h
+++ b/content/shell/renderer/test_runner/WebFrameTestProxy.h
@@ -92,6 +92,10 @@
     {
         Base::didFinishLoad(frame);
     }
+    virtual void didChangeSelection(bool is_selection_empty) {
+        m_baseProxy->didChangeSelection(is_selection_empty);
+        Base::didChangeSelection(is_selection_empty);
+    }
     virtual void showContextMenu(const blink::WebContextMenuData& contextMenuData) {
         m_baseProxy->showContextMenu(Base::GetWebFrame(), contextMenuData);
         Base::showContextMenu(contextMenuData);
@@ -156,6 +160,11 @@
             return true;
         return Base::willCheckAndDispatchMessageEvent(sourceFrame, targetFrame, target, event);
     }
+    virtual void didStopLoading()
+    {
+        m_baseProxy->didStopLoading();
+        Base::didStopLoading();
+    }
 
 private:
     WebTestProxyBase* m_baseProxy;
diff --git a/content/shell/renderer/test_runner/WebTestDelegate.h b/content/shell/renderer/test_runner/WebTestDelegate.h
index 577f28e..6337aee 100644
--- a/content/shell/renderer/test_runner/WebTestDelegate.h
+++ b/content/shell/renderer/test_runner/WebTestDelegate.h
@@ -18,6 +18,7 @@
 class WebDeviceMotionData;
 class WebDeviceOrientationData;
 class WebFrame;
+class WebGamepad;
 class WebGamepads;
 class WebHistoryItem;
 struct WebRect;
@@ -41,6 +42,12 @@
     // Set the gamepads to return from Platform::sampleGamepads().
     virtual void setGamepadData(const blink::WebGamepads&) = 0;
 
+    // Notifies blink about a new gamepad.
+    virtual void didConnectGamepad(int index, const blink::WebGamepad&) = 0;
+
+    // Notifies blink that a gamepad has been disconnected.
+    virtual void didDisconnectGamepad(int index, const blink::WebGamepad&) = 0;
+
     // Set data to return when registering via Platform::setDeviceMotionListener().
     virtual void setDeviceMotionData(const blink::WebDeviceMotionData&) = 0;
     // Set data to return when registering via Platform::setDeviceOrientationListener().
diff --git a/content/shell/renderer/test_runner/WebTestProxy.cpp b/content/shell/renderer/test_runner/WebTestProxy.cpp
index 0b8ddd5..9d454a2 100644
--- a/content/shell/renderer/test_runner/WebTestProxy.cpp
+++ b/content/shell/renderer/test_runner/WebTestProxy.cpp
@@ -6,7 +6,7 @@
 
 #include <cctype>
 
-#include "content/shell/renderer/test_runner/EventSender.h"
+#include "content/shell/renderer/test_runner/event_sender.h"
 #include "content/shell/renderer/test_runner/MockColorChooser.h"
 #include "content/shell/renderer/test_runner/MockWebSpeechInputController.h"
 #include "content/shell/renderer/test_runner/MockWebSpeechRecognizer.h"
@@ -875,7 +875,7 @@
 {
     // When running a test, we need to fake a drag drop operation otherwise
     // Windows waits for real mouse events to know when the drag is over.
-    m_testInterfaces->eventSender()->doDragDrop(data, mask);
+    m_testInterfaces->eventSender()->DoDragDrop(data, mask);
 }
 
 // The output from these methods in layout test mode should match that
@@ -924,7 +924,7 @@
 
 void WebTestProxyBase::showContextMenu(WebFrame*, const WebContextMenuData& contextMenuData)
 {
-    m_testInterfaces->eventSender()->setContextMenuData(contextMenuData);
+    m_testInterfaces->eventSender()->SetContextMenuData(contextMenuData);
 }
 
 WebUserMediaClient* WebTestProxyBase::userMediaClient()
diff --git a/content/shell/renderer/test_runner/WebTestProxy.h b/content/shell/renderer/test_runner/WebTestProxy.h
index ea10c5a..a6c14a2 100644
--- a/content/shell/renderer/test_runner/WebTestProxy.h
+++ b/content/shell/renderer/test_runner/WebTestProxy.h
@@ -288,11 +288,6 @@
         WebTestProxyBase::startDragging(frame, data, mask, image, point);
         // Don't forward this call to Base because we don't want to do a real drag-and-drop.
     }
-    virtual void didChangeSelection(bool isEmptySelection)
-    {
-        WebTestProxyBase::didChangeSelection(isEmptySelection);
-        Base::didChangeSelection(isEmptySelection);
-    }
     virtual void didChangeContents()
     {
         WebTestProxyBase::didChangeContents();
@@ -309,11 +304,6 @@
         WebTestProxyBase::setStatusText(text);
         Base::setStatusText(text);
     }
-    virtual void didStopLoading(blink::WebFrame* frame)
-    {
-        WebTestProxyBase::didStopLoading();
-        Base::didStopLoading(frame);
-    }
     virtual blink::WebUserMediaClient* userMediaClient()
     {
         return WebTestProxyBase::userMediaClient();
diff --git a/content/shell/renderer/test_runner/event_sender.cc b/content/shell/renderer/test_runner/event_sender.cc
new file mode 100644
index 0000000..4685f3e
--- /dev/null
+++ b/content/shell/renderer/test_runner/event_sender.cc
@@ -0,0 +1,2158 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/renderer/test_runner/event_sender.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "content/shell/renderer/test_runner/KeyCodeMapping.h"
+#include "content/shell/renderer/test_runner/MockSpellCheck.h"
+#include "content/shell/renderer/test_runner/TestInterfaces.h"
+#include "content/shell/renderer/test_runner/WebTestDelegate.h"
+#include "content/shell/renderer/test_runner/WebTestProxy.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/wrappable.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebVector.h"
+#include "third_party/WebKit/public/web/WebContextMenuData.h"
+#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebKit.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "v8/include/v8.h"
+
+#if defined(OS_WIN)
+#include "third_party/WebKit/public/web/win/WebInputEventFactory.h"
+#elif defined(OS_MACOSX)
+#include "third_party/WebKit/public/web/mac/WebInputEventFactory.h"
+#elif defined(OS_ANDROID)
+#include "third_party/WebKit/public/web/android/WebInputEventFactory.h"
+#elif defined(TOOLKIT_GTK)
+#include "third_party/WebKit/public/web/gtk/WebInputEventFactory.h"
+#endif
+
+using blink::WebContextMenuData;
+using blink::WebDragData;
+using blink::WebDragOperationsMask;
+using blink::WebFloatPoint;
+using blink::WebFrame;
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebPoint;
+using blink::WebString;
+using blink::WebTouchEvent;
+using blink::WebTouchPoint;
+using blink::WebVector;
+using blink::WebView;
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
+    defined(TOOLKIT_GTK)
+using blink::WebInputEventFactory;
+#endif
+
+namespace content {
+
+namespace {
+
+void InitMouseEvent(WebInputEvent::Type t,
+                    WebMouseEvent::Button b,
+                    const WebPoint& pos,
+                    double time_stamp,
+                    int click_count,
+                    int modifiers,
+                    WebMouseEvent* e) {
+  e->type = t;
+  e->button = b;
+  e->modifiers = modifiers;
+  e->x = pos.x;
+  e->y = pos.y;
+  e->globalX = pos.x;
+  e->globalY = pos.y;
+  e->timeStampSeconds = time_stamp;
+  e->clickCount = click_count;
+}
+
+int GetKeyModifier(const std::string& modifier_name) {
+  const char* characters = modifier_name.c_str();
+  if (!strcmp(characters, "ctrlKey")
+#ifndef __APPLE__
+      || !strcmp(characters, "addSelectionKey")
+#endif
+      ) {
+    return WebInputEvent::ControlKey;
+  } else if (!strcmp(characters, "shiftKey") ||
+             !strcmp(characters, "rangeSelectionKey")) {
+    return WebInputEvent::ShiftKey;
+  } else if (!strcmp(characters, "altKey")) {
+    return WebInputEvent::AltKey;
+#ifdef __APPLE__
+  } else if (!strcmp(characters, "metaKey") ||
+             !strcmp(characters, "addSelectionKey")) {
+    return WebInputEvent::MetaKey;
+#else
+  } else if (!strcmp(characters, "metaKey")) {
+    return WebInputEvent::MetaKey;
+#endif
+  } else if (!strcmp(characters, "autoRepeat")) {
+    return WebInputEvent::IsAutoRepeat;
+  } else if (!strcmp(characters, "copyKey")) {
+#ifdef __APPLE__
+    return WebInputEvent::AltKey;
+#else
+    return WebInputEvent::ControlKey;
+#endif
+  }
+
+  return 0;
+}
+
+int GetKeyModifiers(const std::vector<std::string>& modifier_names) {
+  int modifiers = 0;
+  for (std::vector<std::string>::const_iterator it = modifier_names.begin();
+       it != modifier_names.end(); ++it) {
+    modifiers |= GetKeyModifier(*it);
+  }
+  return modifiers;
+}
+
+int GetKeyModifiersFromV8(v8::Handle<v8::Value> value) {
+  std::vector<std::string> modifier_names;
+  if (value->IsString()) {
+    modifier_names.push_back(gin::V8ToString(value));
+  } else if (value->IsArray()) {
+    gin::Converter<std::vector<std::string> >::FromV8(
+        NULL, value, &modifier_names);
+  }
+  return GetKeyModifiers(modifier_names);
+}
+
+// Maximum distance (in space and time) for a mouse click to register as a
+// double or triple click.
+const double kMultipleClickTimeSec = 1;
+const int kMultipleClickRadiusPixels = 5;
+
+bool OutsideMultiClickRadius(const WebPoint& a, const WebPoint& b) {
+  return ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)) >
+         kMultipleClickRadiusPixels * kMultipleClickRadiusPixels;
+}
+
+// Because actual context menu is implemented by the browser side,
+// this function does only what LayoutTests are expecting:
+// - Many test checks the count of items. So returning non-zero value makes
+// sense.
+// - Some test compares the count before and after some action. So changing the
+// count based on flags also makes sense. This function is doing such for some
+// flags.
+// - Some test even checks actual string content. So providing it would be also
+// helpful.
+std::vector<std::string> MakeMenuItemStringsFor(
+    WebContextMenuData* context_menu,
+    WebTestRunner::WebTestDelegate* delegate) {
+  // These constants are based on Safari's context menu because tests are made
+  // for it.
+  static const char* kNonEditableMenuStrings[] = {
+    "Back",
+    "Reload Page",
+    "Open in Dashbaord",
+    "<separator>",
+    "View Source",
+    "Save Page As",
+    "Print Page",
+    "Inspect Element",
+    0
+  };
+  static const char* kEditableMenuStrings[] = {
+    "Cut",
+    "Copy",
+    "<separator>",
+    "Paste",
+    "Spelling and Grammar",
+    "Substitutions, Transformations",
+    "Font",
+    "Speech",
+    "Paragraph Direction",
+    "<separator>",
+    0
+  };
+
+  // This is possible because mouse events are cancelleable.
+  if (!context_menu)
+    return std::vector<std::string>();
+
+  std::vector<std::string> strings;
+
+  if (context_menu->isEditable) {
+    for (const char** item = kEditableMenuStrings; *item; ++item) {
+      strings.push_back(*item);
+    }
+    WebVector<WebString> suggestions;
+    WebTestRunner::MockSpellCheck::fillSuggestionList(
+        context_menu->misspelledWord, &suggestions);
+    for (size_t i = 0; i < suggestions.size(); ++i) {
+      strings.push_back(suggestions[i].utf8());
+    }
+  } else {
+    for (const char** item = kNonEditableMenuStrings; *item; ++item) {
+      strings.push_back(*item);
+    }
+  }
+
+  return strings;
+}
+
+// How much we should scroll per event - the value here is chosen to match the
+// WebKit impl and layout test results.
+const float kScrollbarPixelsPerTick = 40.0f;
+
+WebMouseEvent::Button GetButtonTypeFromButtonNumber(int button_code) {
+  if (!button_code)
+    return WebMouseEvent::ButtonLeft;
+  if (button_code == 2)
+    return WebMouseEvent::ButtonRight;
+  return WebMouseEvent::ButtonMiddle;
+}
+
+class MouseDownTask : public WebTestRunner::WebMethodTask<EventSender> {
+ public:
+  MouseDownTask(EventSender* obj, int button_number, int modifiers)
+      : WebMethodTask<EventSender>(obj),
+        button_number_(button_number),
+        modifiers_(modifiers) {}
+
+  virtual void runIfValid() OVERRIDE {
+    m_object->MouseDown(button_number_, modifiers_);
+  }
+
+ private:
+  int button_number_;
+  int modifiers_;
+};
+
+class MouseUpTask : public WebTestRunner::WebMethodTask<EventSender> {
+ public:
+  MouseUpTask(EventSender* obj, int button_number, int modifiers)
+      : WebMethodTask<EventSender>(obj),
+        button_number_(button_number),
+        modifiers_(modifiers) {}
+
+  virtual void runIfValid() OVERRIDE {
+    m_object->MouseUp(button_number_, modifiers_);
+  }
+
+ private:
+  int button_number_;
+  int modifiers_;
+};
+
+class KeyDownTask : public WebTestRunner::WebMethodTask<EventSender> {
+ public:
+  KeyDownTask(EventSender* obj,
+              const std::string code_str,
+              int modifiers,
+              KeyLocationCode location)
+      : WebMethodTask<EventSender>(obj),
+        code_str_(code_str),
+        modifiers_(modifiers),
+        location_(location) {}
+
+  virtual void runIfValid() OVERRIDE {
+    m_object->KeyDown(code_str_, modifiers_, location_);
+  }
+
+ private:
+  std::string code_str_;
+  int modifiers_;
+  KeyLocationCode location_;
+};
+
+bool NeedsShiftModifier(int keyCode) {
+  // If code is an uppercase letter, assign a SHIFT key to eventDown.modifier.
+  return (keyCode & 0xFF) >= 'A' && (keyCode & 0xFF) <= 'Z';
+}
+
+// Get the edit command corresponding to a keyboard event.
+// Returns true if the specified event corresponds to an edit command, the name
+// of the edit command will be stored in |*name|.
+bool GetEditCommand(const WebKeyboardEvent& event, std::string* name) {
+#if defined(OS_MACOSX)
+// We only cares about Left,Right,Up,Down keys with Command or Command+Shift
+// modifiers. These key events correspond to some special movement and
+// selection editor commands. These keys will be marked as system key, which
+// prevents them from being handled. Thus they must be handled specially.
+  if ((event.modifiers & ~WebKeyboardEvent::ShiftKey) !=
+      WebKeyboardEvent::MetaKey)
+    return false;
+
+  switch (event.windowsKeyCode) {
+    case WebTestRunner::VKEY_LEFT:
+      *name = "MoveToBeginningOfLine";
+      break;
+    case WebTestRunner::VKEY_RIGHT:
+      *name = "MoveToEndOfLine";
+      break;
+    case WebTestRunner::VKEY_UP:
+      *name = "MoveToBeginningOfDocument";
+      break;
+    case WebTestRunner::VKEY_DOWN:
+      *name = "MoveToEndOfDocument";
+      break;
+    default:
+      return false;
+  }
+
+  if (event.modifiers & WebKeyboardEvent::ShiftKey)
+    name->append("AndModifySelection");
+
+  return true;
+#else
+  return false;
+#endif
+}
+
+}  // namespace
+
+class EventSenderBindings : public gin::Wrappable<EventSenderBindings> {
+ public:
+  static gin::WrapperInfo kWrapperInfo;
+
+  static void Install(base::WeakPtr<EventSender> sender,
+                      blink::WebFrame* frame);
+
+ private:
+  explicit EventSenderBindings(base::WeakPtr<EventSender> sender);
+  virtual ~EventSenderBindings();
+
+  // gin::Wrappable:
+  virtual gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
+      v8::Isolate* isolate) OVERRIDE;
+
+  // Bound methods:
+  void EnableDOMUIEventLogging();
+  void FireKeyboardEventsToElement();
+  void ClearKillRing();
+  std::vector<std::string> ContextClick();
+  void TextZoomIn();
+  void TextZoomOut();
+  void ZoomPageIn();
+  void ZoomPageOut();
+  void SetPageScaleFactor(gin::Arguments* args);
+  void ClearTouchPoints();
+  void ReleaseTouchPoint(unsigned index);
+  void UpdateTouchPoint(unsigned index, int x, int y);
+  void CancelTouchPoint(unsigned index);
+  void SetTouchModifier(const std::string& key_name, bool set_mask);
+  void DumpFilenameBeingDragged();
+  void GestureFlingCancel();
+  void GestureFlingStart(float x, float y, float velocity_x, float velocity_y);
+  void GestureScrollFirstPoint(int x, int y);
+  void TouchStart();
+  void TouchMove();
+  void TouchCancel();
+  void TouchEnd();
+  void LeapForward(int milliseconds);
+  void BeginDragWithFiles(const std::vector<std::string>& files);
+  void AddTouchPoint(gin::Arguments* args);
+  void MouseDragBegin();
+  void MouseDragEnd();
+  void MouseMomentumBegin();
+  void GestureScrollBegin(gin::Arguments* args);
+  void GestureScrollEnd(gin::Arguments* args);
+  void GestureScrollUpdate(gin::Arguments* args);
+  void GestureScrollUpdateWithoutPropagation(gin::Arguments* args);
+  void GestureTap(gin::Arguments* args);
+  void GestureTapDown(gin::Arguments* args);
+  void GestureShowPress(gin::Arguments* args);
+  void GestureTapCancel(gin::Arguments* args);
+  void GestureLongPress(gin::Arguments* args);
+  void GestureLongTap(gin::Arguments* args);
+  void GestureTwoFingerTap(gin::Arguments* args);
+  void ContinuousMouseScrollBy(gin::Arguments* args);
+  void DispatchMessage(int msg, int wparam, int lparam);
+  void MouseMoveTo(gin::Arguments* args);
+  void MouseScrollBy(gin::Arguments* args);
+  void MouseMomentumScrollBy(gin::Arguments* args);
+  void MouseMomentumEnd();
+  void ScheduleAsynchronousClick(gin::Arguments* args);
+  void ScheduleAsynchronousKeyDown(gin::Arguments* args);
+  void MouseDown(gin::Arguments* args);
+  void MouseUp(gin::Arguments* args);
+  void KeyDown(gin::Arguments* args);
+
+  // Binding properties:
+  bool ForceLayoutOnEvents() const;
+  void SetForceLayoutOnEvents(bool force);
+  bool IsDragMode() const;
+  void SetIsDragMode(bool drag_mode);
+
+#if defined(OS_WIN)
+  int WmKeyDown() const;
+  void SetWmKeyDown(int key_down);
+
+  int WmKeyUp() const;
+  void SetWmKeyUp(int key_up);
+
+  int WmChar() const;
+  void SetWmChar(int wm_char);
+
+  int WmDeadChar() const;
+  void SetWmDeadChar(int dead_char);
+
+  int WmSysKeyDown() const;
+  void SetWmSysKeyDown(int key_down);
+
+  int WmSysKeyUp() const;
+  void SetWmSysKeyUp(int key_up);
+
+  int WmSysChar() const;
+  void SetWmSysChar(int sys_char);
+
+  int WmSysDeadChar() const;
+  void SetWmSysDeadChar(int sys_dead_char);
+#endif
+
+  base::WeakPtr<EventSender> sender_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventSenderBindings);
+};
+
+gin::WrapperInfo EventSenderBindings::kWrapperInfo = {gin::kEmbedderNativeGin};
+
+EventSenderBindings::EventSenderBindings(base::WeakPtr<EventSender> sender)
+    : sender_(sender) {
+}
+
+EventSenderBindings::~EventSenderBindings() {}
+
+// static
+void EventSenderBindings::Install(base::WeakPtr<EventSender> sender,
+                                  WebFrame* frame) {
+  v8::Isolate* isolate = blink::mainThreadIsolate();
+  v8::HandleScope handle_scope(isolate);
+  v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+  if (context.IsEmpty())
+    return;
+
+  v8::Context::Scope context_scope(context);
+
+  gin::Handle<EventSenderBindings> bindings =
+      gin::CreateHandle(isolate, new EventSenderBindings(sender));
+  v8::Handle<v8::Object> global = context->Global();
+  global->Set(gin::StringToV8(isolate, "eventSender"), bindings.ToV8());
+}
+
+gin::ObjectTemplateBuilder
+EventSenderBindings::GetObjectTemplateBuilder(v8::Isolate* isolate) {
+  return gin::Wrappable<EventSenderBindings>::GetObjectTemplateBuilder(isolate)
+      .SetMethod("enableDOMUIEventLogging",
+                 &EventSenderBindings::EnableDOMUIEventLogging)
+      .SetMethod("fireKeyboardEventsToElement",
+                 &EventSenderBindings::FireKeyboardEventsToElement)
+      .SetMethod("clearKillRing", &EventSenderBindings::ClearKillRing)
+      .SetMethod("contextClick", &EventSenderBindings::ContextClick)
+      .SetMethod("textZoomIn", &EventSenderBindings::TextZoomIn)
+      .SetMethod("textZoomOut", &EventSenderBindings::TextZoomOut)
+      .SetMethod("zoomPageIn", &EventSenderBindings::ZoomPageIn)
+      .SetMethod("zoomPageOut", &EventSenderBindings::ZoomPageOut)
+      .SetMethod("setPageScaleFactor", &EventSenderBindings::SetPageScaleFactor)
+      .SetMethod("clearTouchPoints", &EventSenderBindings::ClearTouchPoints)
+      .SetMethod("releaseTouchPoint", &EventSenderBindings::ReleaseTouchPoint)
+      .SetMethod("updateTouchPoint", &EventSenderBindings::UpdateTouchPoint)
+      .SetMethod("cancelTouchPoint", &EventSenderBindings::CancelTouchPoint)
+      .SetMethod("setTouchModifier", &EventSenderBindings::SetTouchModifier)
+      .SetMethod("dumpFilenameBeingDragged",
+                 &EventSenderBindings::DumpFilenameBeingDragged)
+      .SetMethod("gestureFlingCancel", &EventSenderBindings::GestureFlingCancel)
+      .SetMethod("gestureFlingStart", &EventSenderBindings::GestureFlingStart)
+      .SetMethod("gestureScrollFirstPoint",
+                 &EventSenderBindings::GestureScrollFirstPoint)
+      .SetMethod("touchStart", &EventSenderBindings::TouchStart)
+      .SetMethod("touchMove", &EventSenderBindings::TouchMove)
+      .SetMethod("touchCancel", &EventSenderBindings::TouchCancel)
+      .SetMethod("touchEnd", &EventSenderBindings::TouchEnd)
+      .SetMethod("leapForward", &EventSenderBindings::LeapForward)
+      .SetMethod("beginDragWithFiles", &EventSenderBindings::BeginDragWithFiles)
+      .SetMethod("addTouchPoint", &EventSenderBindings::AddTouchPoint)
+      .SetMethod("mouseDragBegin", &EventSenderBindings::MouseDragBegin)
+      .SetMethod("mouseDragEnd", &EventSenderBindings::MouseDragEnd)
+      .SetMethod("mouseMomentumBegin", &EventSenderBindings::MouseMomentumBegin)
+      .SetMethod("gestureScrollBegin", &EventSenderBindings::GestureScrollBegin)
+      .SetMethod("gestureScrollEnd", &EventSenderBindings::GestureScrollEnd)
+      .SetMethod("gestureScrollUpdate",
+                 &EventSenderBindings::GestureScrollUpdate)
+      .SetMethod("gestureScrollUpdateWithoutPropagation",
+                 &EventSenderBindings::GestureScrollUpdateWithoutPropagation)
+      .SetMethod("gestureTap", &EventSenderBindings::GestureTap)
+      .SetMethod("gestureTapDown", &EventSenderBindings::GestureTapDown)
+      .SetMethod("gestureShowPress", &EventSenderBindings::GestureShowPress)
+      .SetMethod("gestureTapCancel", &EventSenderBindings::GestureTapCancel)
+      .SetMethod("gestureLongPress", &EventSenderBindings::GestureLongPress)
+      .SetMethod("gestureLongTap", &EventSenderBindings::GestureLongTap)
+      .SetMethod("gestureTwoFingerTap",
+                 &EventSenderBindings::GestureTwoFingerTap)
+      .SetMethod("continuousMouseScrollBy",
+                 &EventSenderBindings::ContinuousMouseScrollBy)
+      .SetMethod("dispatchMessage", &EventSenderBindings::DispatchMessage)
+      .SetMethod("keyDown", &EventSenderBindings::KeyDown)
+      .SetMethod("mouseDown", &EventSenderBindings::MouseDown)
+      .SetMethod("mouseMoveTo", &EventSenderBindings::MouseMoveTo)
+      .SetMethod("mouseScrollBy", &EventSenderBindings::MouseScrollBy)
+      .SetMethod("mouseUp", &EventSenderBindings::MouseUp)
+      .SetMethod("mouseMomentumScrollBy",
+                 &EventSenderBindings::MouseMomentumScrollBy)
+      .SetMethod("mouseMomentumEnd", &EventSenderBindings::MouseMomentumEnd)
+      .SetMethod("scheduleAsynchronousClick",
+                 &EventSenderBindings::ScheduleAsynchronousClick)
+      .SetMethod("scheduleAsynchronousKeyDown",
+                 &EventSenderBindings::ScheduleAsynchronousKeyDown)
+      .SetProperty("forceLayoutOnEvents",
+                   &EventSenderBindings::ForceLayoutOnEvents,
+                   &EventSenderBindings::SetForceLayoutOnEvents)
+      .SetProperty("dragMode",
+                   &EventSenderBindings::IsDragMode,
+                   &EventSenderBindings::SetIsDragMode)
+#if defined(OS_WIN)
+      .SetProperty("WM_KEYDOWN",
+                   &EventSenderBindings::WmKeyDown,
+                   &EventSenderBindings::SetWmKeyDown)
+      .SetProperty("WM_KEYUP",
+                   &EventSenderBindings::WmKeyUp,
+                   &EventSenderBindings::SetWmKeyUp)
+      .SetProperty("WM_CHAR",
+                   &EventSenderBindings::WmChar,
+                   &EventSenderBindings::SetWmChar)
+      .SetProperty("WM_DEADCHAR",
+                   &EventSenderBindings::WmDeadChar,
+                   &EventSenderBindings::SetWmDeadChar)
+      .SetProperty("WM_SYSKEYDOWN",
+                   &EventSenderBindings::WmSysKeyDown,
+                   &EventSenderBindings::SetWmSysKeyDown)
+      .SetProperty("WM_SYSKEYUP",
+                   &EventSenderBindings::WmSysKeyUp,
+                   &EventSenderBindings::SetWmSysKeyUp)
+      .SetProperty("WM_SYSCHAR",
+                   &EventSenderBindings::WmSysChar,
+                   &EventSenderBindings::SetWmSysChar)
+      .SetProperty("WM_SYSDEADCHAR",
+                   &EventSenderBindings::WmSysDeadChar,
+                   &EventSenderBindings::SetWmSysDeadChar);
+#else
+      ;
+#endif
+}
+
+void EventSenderBindings::EnableDOMUIEventLogging() {
+  if (sender_)
+    sender_->EnableDOMUIEventLogging();
+}
+
+void EventSenderBindings::FireKeyboardEventsToElement() {
+  if (sender_)
+    sender_->FireKeyboardEventsToElement();
+}
+
+void EventSenderBindings::ClearKillRing() {
+  if (sender_)
+    sender_->ClearKillRing();
+}
+
+std::vector<std::string> EventSenderBindings::ContextClick() {
+  if (sender_)
+    return sender_->ContextClick();
+  return std::vector<std::string>();
+}
+
+void EventSenderBindings::TextZoomIn() {
+  if (sender_)
+    sender_->TextZoomIn();
+}
+
+void EventSenderBindings::TextZoomOut() {
+  if (sender_)
+    sender_->TextZoomOut();
+}
+
+void EventSenderBindings::ZoomPageIn() {
+  if (sender_)
+    sender_->ZoomPageIn();
+}
+
+void EventSenderBindings::ZoomPageOut() {
+  if (sender_)
+    sender_->ZoomPageOut();
+}
+
+void EventSenderBindings::SetPageScaleFactor(gin::Arguments* args) {
+  if (!sender_)
+    return;
+  float scale_factor;
+  int x;
+  int y;
+  if (args->PeekNext().IsEmpty())
+    return;
+  args->GetNext(&scale_factor);
+  if (args->PeekNext().IsEmpty())
+    return;
+  args->GetNext(&x);
+  if (args->PeekNext().IsEmpty())
+    return;
+  args->GetNext(&y);
+  sender_->SetPageScaleFactor(scale_factor, x, y);
+}
+
+void EventSenderBindings::ClearTouchPoints() {
+  if (sender_)
+    sender_->ClearTouchPoints();
+}
+
+void EventSenderBindings::ReleaseTouchPoint(unsigned index) {
+  if (sender_)
+    sender_->ReleaseTouchPoint(index);
+}
+
+void EventSenderBindings::UpdateTouchPoint(unsigned index, int x, int y) {
+  if (sender_)
+    sender_->UpdateTouchPoint(index, x, y);
+}
+
+void EventSenderBindings::CancelTouchPoint(unsigned index) {
+  if (sender_)
+    sender_->CancelTouchPoint(index);
+}
+
+void EventSenderBindings::SetTouchModifier(const std::string& key_name,
+                                           bool set_mask) {
+  if (sender_)
+    sender_->SetTouchModifier(key_name, set_mask);
+}
+
+void EventSenderBindings::DumpFilenameBeingDragged() {
+  if (sender_)
+    sender_->DumpFilenameBeingDragged();
+}
+
+void EventSenderBindings::GestureFlingCancel() {
+  if (sender_)
+    sender_->GestureFlingCancel();
+}
+
+void EventSenderBindings::GestureFlingStart(float x,
+                                            float y,
+                                            float velocity_x,
+                                            float velocity_y) {
+  if (sender_)
+    sender_->GestureFlingStart(x, y, velocity_x, velocity_y);
+}
+
+void EventSenderBindings::GestureScrollFirstPoint(int x, int y) {
+  if (sender_)
+    sender_->GestureScrollFirstPoint(x, y);
+}
+
+void EventSenderBindings::TouchStart() {
+  if (sender_)
+    sender_->TouchStart();
+}
+
+void EventSenderBindings::TouchMove() {
+  if (sender_)
+    sender_->TouchMove();
+}
+
+void EventSenderBindings::TouchCancel() {
+  if (sender_)
+    sender_->TouchCancel();
+}
+
+void EventSenderBindings::TouchEnd() {
+  if (sender_)
+    sender_->TouchEnd();
+}
+
+void EventSenderBindings::LeapForward(int milliseconds) {
+  if (sender_)
+    sender_->LeapForward(milliseconds);
+}
+
+void EventSenderBindings::BeginDragWithFiles(
+    const std::vector<std::string>& files) {
+  if (sender_)
+    sender_->BeginDragWithFiles(files);
+}
+
+void EventSenderBindings::AddTouchPoint(gin::Arguments* args) {
+  if (sender_)
+    sender_->AddTouchPoint(args);
+}
+
+void EventSenderBindings::MouseDragBegin() {
+  if (sender_)
+    sender_->MouseDragBegin();
+}
+
+void EventSenderBindings::MouseDragEnd() {
+  if (sender_)
+    sender_->MouseDragEnd();
+}
+
+void EventSenderBindings::MouseMomentumBegin() {
+  if (sender_)
+    sender_->MouseMomentumBegin();
+}
+
+void EventSenderBindings::GestureScrollBegin(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureScrollBegin(args);
+}
+
+void EventSenderBindings::GestureScrollEnd(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureScrollEnd(args);
+}
+
+void EventSenderBindings::GestureScrollUpdate(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureScrollUpdate(args);
+}
+
+void EventSenderBindings::GestureScrollUpdateWithoutPropagation(
+    gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureScrollUpdateWithoutPropagation(args);
+}
+
+void EventSenderBindings::GestureTap(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureTap(args);
+}
+
+void EventSenderBindings::GestureTapDown(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureTapDown(args);
+}
+
+void EventSenderBindings::GestureShowPress(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureShowPress(args);
+}
+
+void EventSenderBindings::GestureTapCancel(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureTapCancel(args);
+}
+
+void EventSenderBindings::GestureLongPress(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureLongPress(args);
+}
+
+void EventSenderBindings::GestureLongTap(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureLongTap(args);
+}
+
+void EventSenderBindings::GestureTwoFingerTap(gin::Arguments* args) {
+  if (sender_)
+    sender_->GestureTwoFingerTap(args);
+}
+
+void EventSenderBindings::ContinuousMouseScrollBy(gin::Arguments* args) {
+  if (sender_)
+    sender_->ContinuousMouseScrollBy(args);
+}
+
+void EventSenderBindings::DispatchMessage(int msg, int wparam, int lparam) {
+  if (sender_)
+    sender_->DispatchMessage(msg, wparam, lparam);
+}
+
+void EventSenderBindings::MouseMoveTo(gin::Arguments* args) {
+  if (sender_)
+    sender_->MouseMoveTo(args);
+}
+
+void EventSenderBindings::MouseScrollBy(gin::Arguments* args) {
+  if (sender_)
+    sender_->MouseScrollBy(args);
+}
+
+void EventSenderBindings::MouseMomentumScrollBy(gin::Arguments* args) {
+  if (sender_)
+    sender_->MouseMomentumScrollBy(args);
+}
+
+void EventSenderBindings::MouseMomentumEnd() {
+  if (sender_)
+    sender_->MouseMomentumEnd();
+}
+
+void EventSenderBindings::ScheduleAsynchronousClick(gin::Arguments* args) {
+  if (!sender_)
+    return;
+
+  int button_number = 0;
+  int modifiers = 0;
+  if (!args->PeekNext().IsEmpty()) {
+    args->GetNext(&button_number);
+    if (!args->PeekNext().IsEmpty())
+      modifiers = GetKeyModifiersFromV8(args->PeekNext());
+  }
+  sender_->ScheduleAsynchronousClick(button_number, modifiers);
+}
+
+void EventSenderBindings::ScheduleAsynchronousKeyDown(gin::Arguments* args) {
+  if (!sender_)
+    return;
+
+  std::string code_str;
+  int modifiers = 0;
+  int location = DOMKeyLocationStandard;
+  args->GetNext(&code_str);
+  if (!args->PeekNext().IsEmpty()) {
+    v8::Handle<v8::Value> value;
+    args->GetNext(&value);
+    modifiers = GetKeyModifiersFromV8(value);
+    if (!args->PeekNext().IsEmpty())
+      args->GetNext(&location);
+  }
+  sender_->ScheduleAsynchronousKeyDown(code_str, modifiers,
+                                       static_cast<KeyLocationCode>(location));
+}
+
+void EventSenderBindings::MouseDown(gin::Arguments* args) {
+  if (!sender_)
+    return;
+
+  int button_number = 0;
+  int modifiers = 0;
+  if (!args->PeekNext().IsEmpty()) {
+    args->GetNext(&button_number);
+    if (!args->PeekNext().IsEmpty())
+      modifiers = GetKeyModifiersFromV8(args->PeekNext());
+  }
+  sender_->MouseDown(button_number, modifiers);
+}
+
+void EventSenderBindings::MouseUp(gin::Arguments* args) {
+  if (!sender_)
+    return;
+
+  int button_number = 0;
+  int modifiers = 0;
+  if (!args->PeekNext().IsEmpty()) {
+    args->GetNext(&button_number);
+    if (!args->PeekNext().IsEmpty())
+      modifiers = GetKeyModifiersFromV8(args->PeekNext());
+  }
+  sender_->MouseUp(button_number, modifiers);
+}
+
+void EventSenderBindings::KeyDown(gin::Arguments* args) {
+  if (!sender_)
+    return;
+
+  std::string code_str;
+  int modifiers = 0;
+  int location = DOMKeyLocationStandard;
+  args->GetNext(&code_str);
+  if (!args->PeekNext().IsEmpty()) {
+    v8::Handle<v8::Value> value;
+    args->GetNext(&value);
+    modifiers = GetKeyModifiersFromV8(value);
+    if (!args->PeekNext().IsEmpty())
+      args->GetNext(&location);
+  }
+  sender_->KeyDown(code_str, modifiers, static_cast<KeyLocationCode>(location));
+}
+
+bool EventSenderBindings::ForceLayoutOnEvents() const {
+  if (sender_)
+    return sender_->force_layout_on_events();
+  return false;
+}
+
+void EventSenderBindings::SetForceLayoutOnEvents(bool force) {
+  if (sender_)
+    sender_->set_force_layout_on_events(force);
+}
+
+bool EventSenderBindings::IsDragMode() const {
+  if (sender_)
+    return sender_->is_drag_mode();
+  return true;
+}
+
+void EventSenderBindings::SetIsDragMode(bool drag_mode) {
+  if (sender_)
+    sender_->set_is_drag_mode(drag_mode);
+}
+
+#if defined(OS_WIN)
+int EventSenderBindings::WmKeyDown() const {
+  if (sender_)
+    return sender_->wm_key_down();
+  return 0;
+}
+
+void EventSenderBindings::SetWmKeyDown(int key_down) {
+  if (sender_)
+    sender_->set_wm_key_down(key_down);
+}
+
+int EventSenderBindings::WmKeyUp() const {
+  if (sender_)
+    return sender_->wm_key_up();
+  return 0;
+}
+
+void EventSenderBindings::SetWmKeyUp(int key_up) {
+  if (sender_)
+    sender_->set_wm_key_up(key_up);
+}
+
+int EventSenderBindings::WmChar() const {
+  if (sender_)
+    return sender_->wm_char();
+  return 0;
+}
+
+void EventSenderBindings::SetWmChar(int wm_char) {
+  if (sender_)
+    sender_->set_wm_char(wm_char);
+}
+
+int EventSenderBindings::WmDeadChar() const {
+  if (sender_)
+    return sender_->wm_dead_char();
+  return 0;
+}
+
+void EventSenderBindings::SetWmDeadChar(int dead_char) {
+  if (sender_)
+    sender_->set_wm_dead_char(dead_char);
+}
+
+int EventSenderBindings::WmSysKeyDown() const {
+  if (sender_)
+    return sender_->wm_sys_key_down();
+  return 0;
+}
+
+void EventSenderBindings::SetWmSysKeyDown(int key_down) {
+  if (sender_)
+    sender_->set_wm_sys_key_down(key_down);
+}
+
+int EventSenderBindings::WmSysKeyUp() const {
+  if (sender_)
+    return sender_->wm_sys_key_up();
+  return 0;
+}
+
+void EventSenderBindings::SetWmSysKeyUp(int key_up) {
+  if (sender_)
+    sender_->set_wm_sys_key_up(key_up);
+}
+
+int EventSenderBindings::WmSysChar() const {
+  if (sender_)
+    return sender_->wm_sys_char();
+  return 0;
+}
+
+void EventSenderBindings::SetWmSysChar(int sys_char) {
+  if (sender_)
+    sender_->set_wm_sys_char(sys_char);
+}
+
+int EventSenderBindings::WmSysDeadChar() const {
+  if (sender_)
+    return sender_->wm_sys_dead_char();
+  return 0;
+}
+
+void EventSenderBindings::SetWmSysDeadChar(int sys_dead_char) {
+  if (sender_)
+    sender_->set_wm_sys_dead_char(sys_dead_char);
+}
+#endif
+
+// EventSender -----------------------------------------------------------------
+
+WebMouseEvent::Button EventSender::pressed_button_ = WebMouseEvent::ButtonNone;
+
+WebPoint EventSender::last_mouse_pos_;
+
+WebMouseEvent::Button EventSender::last_button_type_ =
+    WebMouseEvent::ButtonNone;
+
+EventSender::SavedEvent::SavedEvent()
+    : type(TYPE_UNSPECIFIED),
+      button_type(WebMouseEvent::ButtonNone),
+      milliseconds(0),
+      modifiers(0) {}
+
+EventSender::EventSender(WebTestRunner::TestInterfaces* interfaces)
+    : interfaces_(interfaces),
+      delegate_(NULL),
+      view_(NULL),
+      force_layout_on_events_(false),
+      is_drag_mode_(true),
+      touch_modifiers_(0),
+      replaying_saved_events_(false),
+      current_drag_effects_allowed_(blink::WebDragOperationNone),
+      last_click_time_sec_(0),
+      current_drag_effect_(blink::WebDragOperationNone),
+      time_offset_ms_(0),
+      click_count_(0),
+#if defined(OS_WIN)
+      wm_key_down_(0),
+      wm_key_up_(0),
+      wm_char_(0),
+      wm_dead_char_(0),
+      wm_sys_key_down_(0),
+      wm_sys_key_up_(0),
+      wm_sys_char_(0),
+      wm_sys_dead_char_(0),
+#endif
+      weak_factory_(this) {}
+
+EventSender::~EventSender() {}
+
+void EventSender::Reset() {
+  DCHECK(current_drag_data_.isNull());
+  current_drag_data_.reset();
+  current_drag_effect_ = blink::WebDragOperationNone;
+  current_drag_effects_allowed_ = blink::WebDragOperationNone;
+  if (view_ && pressed_button_ != WebMouseEvent::ButtonNone)
+    view_->mouseCaptureLost();
+  pressed_button_ = WebMouseEvent::ButtonNone;
+  is_drag_mode_ = true;
+  force_layout_on_events_ = true;
+
+#if defined(OS_WIN)
+  wm_key_down_ = WM_KEYDOWN;
+  wm_key_up_ = WM_KEYUP;
+  wm_char_ = WM_CHAR;
+  wm_dead_char_ = WM_DEADCHAR;
+  wm_sys_key_down_ = WM_SYSKEYDOWN;
+  wm_sys_key_up_ = WM_SYSKEYUP;
+  wm_sys_char_ = WM_SYSCHAR;
+  wm_sys_dead_char_ = WM_SYSDEADCHAR;
+#endif
+
+  last_mouse_pos_ = WebPoint(0, 0);
+  last_click_time_sec_ = 0;
+  last_click_pos_ = WebPoint(0, 0);
+  last_button_type_ = WebMouseEvent::ButtonNone;
+  touch_points_.clear();
+  last_context_menu_data_.reset();
+  task_list_.revokeAll();
+  current_gesture_location_ = WebPoint(0, 0);
+  mouse_event_queue_.clear();
+
+  time_offset_ms_ = 0;
+  click_count_ = 0;
+}
+
+void EventSender::Install(WebFrame* frame) {
+  EventSenderBindings::Install(weak_factory_.GetWeakPtr(), frame);
+}
+
+void EventSender::SetDelegate(WebTestRunner::WebTestDelegate* delegate) {
+  delegate_ = delegate;
+}
+
+void EventSender::SetWebView(WebView* view) {
+  view_ = view;
+}
+
+void EventSender::SetContextMenuData(const WebContextMenuData& data) {
+  last_context_menu_data_.reset(new WebContextMenuData(data));
+}
+
+void EventSender::DoDragDrop(const WebDragData& drag_data,
+                              WebDragOperationsMask mask) {
+  WebMouseEvent event;
+  InitMouseEvent(WebInputEvent::MouseDown,
+                 pressed_button_,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 0,
+                 &event);
+  WebPoint client_point(event.x, event.y);
+  WebPoint screen_point(event.globalX, event.globalY);
+  current_drag_data_ = drag_data;
+  current_drag_effects_allowed_ = mask;
+  current_drag_effect_ = view_->dragTargetDragEnter(
+      drag_data, client_point, screen_point, current_drag_effects_allowed_, 0);
+
+  // Finish processing events.
+  ReplaySavedEvents();
+}
+
+void EventSender::MouseDown(int button_number, int modifiers) {
+  if (force_layout_on_events_)
+    view_->layout();
+
+  DCHECK_NE(-1, button_number);
+
+  WebMouseEvent::Button button_type =
+      GetButtonTypeFromButtonNumber(button_number);
+
+  UpdateClickCountForButton(button_type);
+
+  pressed_button_ = button_type;
+
+  WebMouseEvent event;
+  InitMouseEvent(WebInputEvent::MouseDown,
+                 button_type,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 modifiers,
+                 &event);
+  view_->handleInputEvent(event);
+}
+
+void EventSender::MouseUp(int button_number, int modifiers) {
+  if (force_layout_on_events_)
+    view_->layout();
+
+  DCHECK_NE(-1, button_number);
+
+  WebMouseEvent::Button button_type =
+      GetButtonTypeFromButtonNumber(button_number);
+
+  if (is_drag_mode_ && !replaying_saved_events_) {
+    SavedEvent saved_event;
+    saved_event.type = SavedEvent::TYPE_MOUSE_UP;
+    saved_event.button_type = button_type;
+    saved_event.modifiers = modifiers;
+    mouse_event_queue_.push_back(saved_event);
+    ReplaySavedEvents();
+  } else {
+    WebMouseEvent event;
+    InitMouseEvent(WebInputEvent::MouseUp,
+                   button_type,
+                   last_mouse_pos_,
+                   GetCurrentEventTimeSec(),
+                   click_count_,
+                   modifiers,
+                   &event);
+    DoMouseUp(event);
+  }
+}
+
+void EventSender::KeyDown(const std::string& code_str,
+                          int modifiers,
+                          KeyLocationCode location) {
+  // FIXME: I'm not exactly sure how we should convert the string to a key
+  // event. This seems to work in the cases I tested.
+  // FIXME: Should we also generate a KEY_UP?
+
+  bool generate_char = false;
+
+  // Convert \n -> VK_RETURN. Some layout tests use \n to mean "Enter", when
+  // Windows uses \r for "Enter".
+  int code = 0;
+  int text = 0;
+  bool needs_shift_key_modifier = false;
+
+  if ("\n" == code_str) {
+    generate_char = true;
+    text = code = WebTestRunner::VKEY_RETURN;
+  } else if ("rightArrow" == code_str) {
+    code = WebTestRunner::VKEY_RIGHT;
+  } else if ("downArrow" == code_str) {
+    code = WebTestRunner::VKEY_DOWN;
+  } else if ("leftArrow" == code_str) {
+    code = WebTestRunner::VKEY_LEFT;
+  } else if ("upArrow" == code_str) {
+    code = WebTestRunner::VKEY_UP;
+  } else if ("insert" == code_str) {
+    code = WebTestRunner::VKEY_INSERT;
+  } else if ("delete" == code_str) {
+    code = WebTestRunner::VKEY_DELETE;
+  } else if ("pageUp" == code_str) {
+    code = WebTestRunner::VKEY_PRIOR;
+  } else if ("pageDown" == code_str) {
+    code = WebTestRunner::VKEY_NEXT;
+  } else if ("home" == code_str) {
+    code = WebTestRunner::VKEY_HOME;
+  } else if ("end" == code_str) {
+    code = WebTestRunner::VKEY_END;
+  } else if ("printScreen" == code_str) {
+    code = WebTestRunner::VKEY_SNAPSHOT;
+  } else if ("menu" == code_str) {
+    code = WebTestRunner::VKEY_APPS;
+  } else if ("leftControl" == code_str) {
+    code = WebTestRunner::VKEY_LCONTROL;
+  } else if ("rightControl" == code_str) {
+    code = WebTestRunner::VKEY_RCONTROL;
+  } else if ("leftShift" == code_str) {
+    code = WebTestRunner::VKEY_LSHIFT;
+  } else if ("rightShift" == code_str) {
+    code = WebTestRunner::VKEY_RSHIFT;
+  } else if ("leftAlt" == code_str) {
+    code = WebTestRunner::VKEY_LMENU;
+  } else if ("rightAlt" == code_str) {
+    code = WebTestRunner::VKEY_RMENU;
+  } else if ("numLock" == code_str) {
+    code = WebTestRunner::VKEY_NUMLOCK;
+  } else {
+    // Compare the input string with the function-key names defined by the
+    // DOM spec (i.e. "F1",...,"F24"). If the input string is a function-key
+    // name, set its key code.
+    for (int i = 1; i <= 24; ++i) {
+      std::string function_key_name = base::StringPrintf("F%d", i);
+      if (function_key_name == code_str) {
+        code = WebTestRunner::VKEY_F1 + (i - 1);
+        break;
+      }
+    }
+    if (!code) {
+      WebString web_code_str =
+          WebString::fromUTF8(code_str.data(), code_str.size());
+      DCHECK_EQ(1u, web_code_str.length());
+      text = code = web_code_str.at(0);
+      needs_shift_key_modifier = NeedsShiftModifier(code);
+      if ((code & 0xFF) >= 'a' && (code & 0xFF) <= 'z')
+        code -= 'a' - 'A';
+      generate_char = true;
+    }
+
+    if ("(" == code_str) {
+      code = '9';
+      needs_shift_key_modifier = true;
+    }
+  }
+
+  // For one generated keyboard event, we need to generate a keyDown/keyUp
+  // pair;
+  // On Windows, we might also need to generate a char event to mimic the
+  // Windows event flow; on other platforms we create a merged event and test
+  // the event flow that that platform provides.
+  WebKeyboardEvent event_down;
+  event_down.type = WebInputEvent::RawKeyDown;
+  event_down.modifiers = modifiers;
+  event_down.windowsKeyCode = code;
+
+#if defined(OS_LINUX) && defined(TOOLKIT_GTK)
+  event_down.nativeKeyCode =
+      WebTestRunner::NativeKeyCodeForWindowsKeyCode(code);
+#endif
+
+  if (generate_char) {
+    event_down.text[0] = text;
+    event_down.unmodifiedText[0] = text;
+  }
+
+  event_down.setKeyIdentifierFromWindowsKeyCode();
+
+#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
+    defined(TOOLKIT_GTK)
+  if (event_down.modifiers != 0)
+    event_down.isSystemKey = WebInputEventFactory::isSystemKeyEvent(event_down);
+#endif
+
+  if (needs_shift_key_modifier)
+    event_down.modifiers |= WebInputEvent::ShiftKey;
+
+  // See if KeyLocation argument is given.
+  if (location == DOMKeyLocationNumpad)
+    event_down.modifiers |= WebInputEvent::IsKeyPad;
+
+  WebKeyboardEvent event_up;
+  event_up = event_down;
+  event_up.type = WebInputEvent::KeyUp;
+  // EventSender.m forces a layout here, with at least one
+  // test (fast/forms/focus-control-to-page.html) relying on this.
+  if (force_layout_on_events_)
+    view_->layout();
+
+  // In the browser, if a keyboard event corresponds to an editor command,
+  // the command will be dispatched to the renderer just before dispatching
+  // the keyboard event, and then it will be executed in the
+  // RenderView::handleCurrentKeyboardEvent() method.
+  // We just simulate the same behavior here.
+  std::string edit_command;
+  if (GetEditCommand(event_down, &edit_command))
+    delegate_->setEditCommand(edit_command, "");
+
+  view_->handleInputEvent(event_down);
+
+  if (code == WebTestRunner::VKEY_ESCAPE && !current_drag_data_.isNull()) {
+    WebMouseEvent event;
+    InitMouseEvent(WebInputEvent::MouseDown,
+                   pressed_button_,
+                   last_mouse_pos_,
+                   GetCurrentEventTimeSec(),
+                   click_count_,
+                   0,
+                   &event);
+    FinishDragAndDrop(event, blink::WebDragOperationNone);
+  }
+
+  delegate_->clearEditCommand();
+
+  if (generate_char) {
+    WebKeyboardEvent event_char = event_up;
+    event_char.type = WebInputEvent::Char;
+    event_char.keyIdentifier[0] = '\0';
+    view_->handleInputEvent(event_char);
+  }
+
+  view_->handleInputEvent(event_up);
+}
+
+void EventSender::EnableDOMUIEventLogging() {}
+
+void EventSender::FireKeyboardEventsToElement() {}
+
+void EventSender::ClearKillRing() {}
+
+std::vector<std::string> EventSender::ContextClick() {
+  if (force_layout_on_events_) {
+    view_->layout();
+  }
+
+  UpdateClickCountForButton(WebMouseEvent::ButtonRight);
+
+  // Clears last context menu data because we need to know if the context menu
+  // be requested after following mouse events.
+  last_context_menu_data_.reset();
+
+  // Generate right mouse down and up.
+  WebMouseEvent event;
+  // This is a hack to work around only allowing a single pressed button since
+  // we want to test the case where both the left and right mouse buttons are
+  // pressed.
+  if (pressed_button_ == WebMouseEvent::ButtonNone) {
+    pressed_button_ = WebMouseEvent::ButtonRight;
+  }
+  InitMouseEvent(WebInputEvent::MouseDown,
+                 WebMouseEvent::ButtonRight,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 0,
+                 &event);
+  view_->handleInputEvent(event);
+
+#if defined(OS_WIN)
+  InitMouseEvent(WebInputEvent::MouseUp,
+                 WebMouseEvent::ButtonRight,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 0,
+                 &event);
+  view_->handleInputEvent(event);
+
+  pressed_button_= WebMouseEvent::ButtonNone;
+#endif
+
+  return MakeMenuItemStringsFor(last_context_menu_data_.release(), delegate_);
+}
+
+void EventSender::TextZoomIn() {
+  view_->setTextZoomFactor(view_->textZoomFactor() * 1.2f);
+}
+
+void EventSender::TextZoomOut() {
+  view_->setTextZoomFactor(view_->textZoomFactor() / 1.2f);
+}
+
+void EventSender::ZoomPageIn() {
+  const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
+      interfaces_->windowList();
+
+  for (size_t i = 0; i < window_list.size(); ++i) {
+    window_list.at(i)->webView()->setZoomLevel(
+        window_list.at(i)->webView()->zoomLevel() + 1);
+  }
+}
+
+void EventSender::ZoomPageOut() {
+  const std::vector<WebTestRunner::WebTestProxyBase*>& window_list =
+      interfaces_->windowList();
+
+  for (size_t i = 0; i < window_list.size(); ++i) {
+    window_list.at(i)->webView()->setZoomLevel(
+        window_list.at(i)->webView()->zoomLevel() - 1);
+  }
+}
+
+void EventSender::SetPageScaleFactor(float scale_factor, int x, int y) {
+  view_->setPageScaleFactorLimits(scale_factor, scale_factor);
+  view_->setPageScaleFactor(scale_factor, WebPoint(x, y));
+}
+
+void EventSender::ClearTouchPoints() {
+  touch_points_.clear();
+}
+
+void EventSender::ReleaseTouchPoint(unsigned index) {
+  DCHECK_LT(index, touch_points_.size());
+
+  WebTouchPoint* touch_point = &touch_points_[index];
+  touch_point->state = WebTouchPoint::StateReleased;
+}
+
+void EventSender::UpdateTouchPoint(unsigned index, int x, int y) {
+  DCHECK_LT(index, touch_points_.size());
+
+  WebTouchPoint* touch_point = &touch_points_[index];
+  touch_point->state = WebTouchPoint::StateMoved;
+  touch_point->position = WebFloatPoint(x, y);
+  touch_point->screenPosition = touch_point->position;
+}
+
+void EventSender::CancelTouchPoint(unsigned index) {
+  DCHECK_LT(index, touch_points_.size());
+
+  WebTouchPoint* touch_point = &touch_points_[index];
+  touch_point->state = WebTouchPoint::StateCancelled;
+}
+
+void EventSender::SetTouchModifier(const std::string& key_name,
+                                    bool set_mask) {
+  int mask = 0;
+  if (key_name == "shift")
+    mask = WebInputEvent::ShiftKey;
+  else if (key_name == "alt")
+    mask = WebInputEvent::AltKey;
+  else if (key_name == "ctrl")
+    mask = WebInputEvent::ControlKey;
+  else if (key_name == "meta")
+    mask = WebInputEvent::MetaKey;
+
+  if (set_mask)
+    touch_modifiers_ |= mask;
+  else
+    touch_modifiers_ &= ~mask;
+}
+
+void EventSender::DumpFilenameBeingDragged() {
+  WebString filename;
+  WebVector<WebDragData::Item> items = current_drag_data_.items();
+  for (size_t i = 0; i < items.size(); ++i) {
+    if (items[i].storageType == WebDragData::Item::StorageTypeBinaryData) {
+      filename = items[i].title;
+      break;
+    }
+  }
+  delegate_->printMessage(std::string("Filename being dragged: ") +
+                          filename.utf8().data() + "\n");
+}
+
+void EventSender::GestureFlingCancel() {
+  WebGestureEvent event;
+  event.type = WebInputEvent::GestureFlingCancel;
+  event.timeStampSeconds = GetCurrentEventTimeSec();
+
+  if (force_layout_on_events_)
+    view_->layout();
+
+  view_->handleInputEvent(event);
+}
+
+void EventSender::GestureFlingStart(float x,
+                                     float y,
+                                     float velocity_x,
+                                     float velocity_y) {
+  WebGestureEvent event;
+  event.type = WebInputEvent::GestureFlingStart;
+
+  event.x = x;
+  event.y = y;
+  event.globalX = event.x;
+  event.globalY = event.y;
+
+  event.data.flingStart.velocityX = velocity_x;
+  event.data.flingStart.velocityY = velocity_y;
+  event.timeStampSeconds = GetCurrentEventTimeSec();
+
+  if (force_layout_on_events_)
+    view_->layout();
+
+  view_->handleInputEvent(event);
+}
+
+void EventSender::GestureScrollFirstPoint(int x, int y) {
+  current_gesture_location_ = WebPoint(x, y);
+}
+
+void EventSender::TouchStart() {
+  SendCurrentTouchEvent(WebInputEvent::TouchStart);
+}
+
+void EventSender::TouchMove() {
+  SendCurrentTouchEvent(WebInputEvent::TouchMove);
+}
+
+void EventSender::TouchCancel() {
+  SendCurrentTouchEvent(WebInputEvent::TouchCancel);
+}
+
+void EventSender::TouchEnd() {
+  SendCurrentTouchEvent(WebInputEvent::TouchEnd);
+}
+
+void EventSender::LeapForward(int milliseconds) {
+  if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
+      !replaying_saved_events_) {
+    SavedEvent saved_event;
+    saved_event.type = SavedEvent::TYPE_LEAP_FORWARD;
+    saved_event.milliseconds = milliseconds;
+    mouse_event_queue_.push_back(saved_event);
+  } else {
+    DoLeapForward(milliseconds);
+  }
+}
+
+void EventSender::BeginDragWithFiles(const std::vector<std::string>& files) {
+  current_drag_data_.initialize();
+  WebVector<WebString> absolute_filenames(files.size());
+  for (size_t i = 0; i < files.size(); ++i) {
+    WebDragData::Item item;
+    item.storageType = WebDragData::Item::StorageTypeFilename;
+    item.filenameData = delegate_->getAbsoluteWebStringFromUTF8Path(files[i]);
+    current_drag_data_.addItem(item);
+    absolute_filenames[i] = item.filenameData;
+  }
+  current_drag_data_.setFilesystemId(
+      delegate_->registerIsolatedFileSystem(absolute_filenames));
+  current_drag_effects_allowed_ = blink::WebDragOperationCopy;
+
+  // Provide a drag source.
+  view_->dragTargetDragEnter(current_drag_data_,
+                             last_mouse_pos_,
+                             last_mouse_pos_,
+                             current_drag_effects_allowed_,
+                             0);
+  // |is_drag_mode_| saves events and then replays them later. We don't
+  // need/want that.
+  is_drag_mode_ = false;
+
+  // Make the rest of eventSender think a drag is in progress.
+  pressed_button_ = WebMouseEvent::ButtonLeft;
+}
+
+void EventSender::AddTouchPoint(gin::Arguments* args) {
+  int x;
+  int y;
+  args->GetNext(&x);
+  args->GetNext(&y);
+
+  WebTouchPoint touch_point;
+  touch_point.state = WebTouchPoint::StatePressed;
+  touch_point.position = WebFloatPoint(x, y);
+  touch_point.screenPosition = touch_point.position;
+
+  if (!args->PeekNext().IsEmpty()) {
+    int radius_x;
+    if (!args->GetNext(&radius_x)) {
+      args->ThrowError();
+      return;
+    }
+
+    int radius_y = radius_x;
+    if (!args->PeekNext().IsEmpty()) {
+      if (!args->GetNext(&radius_y)) {
+        args->ThrowError();
+        return;
+      }
+    }
+
+    touch_point.radiusX = radius_x;
+    touch_point.radiusY = radius_y;
+  }
+
+  int lowest_id = 0;
+  for (size_t i = 0; i < touch_points_.size(); i++) {
+    if (touch_points_[i].id == lowest_id)
+      lowest_id++;
+  }
+  touch_point.id = lowest_id;
+  touch_points_.push_back(touch_point);
+}
+
+void EventSender::MouseDragBegin() {
+  WebMouseWheelEvent event;
+  InitMouseEvent(WebInputEvent::MouseWheel,
+                 WebMouseEvent::ButtonNone,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 0,
+                 &event);
+  event.phase = WebMouseWheelEvent::PhaseBegan;
+  event.hasPreciseScrollingDeltas = true;
+  view_->handleInputEvent(event);
+}
+
+void EventSender::MouseDragEnd() {
+  WebMouseWheelEvent event;
+  InitMouseEvent(WebInputEvent::MouseWheel,
+                 WebMouseEvent::ButtonNone,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 0,
+                 &event);
+  event.phase = WebMouseWheelEvent::PhaseEnded;
+  event.hasPreciseScrollingDeltas = true;
+  view_->handleInputEvent(event);
+}
+
+void EventSender::MouseMomentumBegin() {
+  WebMouseWheelEvent event;
+  InitMouseEvent(WebInputEvent::MouseWheel,
+                 WebMouseEvent::ButtonNone,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 0,
+                 &event);
+  event.momentumPhase = WebMouseWheelEvent::PhaseBegan;
+  event.hasPreciseScrollingDeltas = true;
+  view_->handleInputEvent(event);
+}
+
+void EventSender::GestureScrollBegin(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureScrollBegin, args);
+}
+
+void EventSender::GestureScrollEnd(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureScrollEnd, args);
+}
+
+void EventSender::GestureScrollUpdate(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureScrollUpdate, args);
+}
+
+void EventSender::GestureScrollUpdateWithoutPropagation(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureScrollUpdateWithoutPropagation, args);
+}
+
+void EventSender::GestureTap(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureTap, args);
+}
+
+void EventSender::GestureTapDown(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureTapDown, args);
+}
+
+void EventSender::GestureShowPress(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureShowPress, args);
+}
+
+void EventSender::GestureTapCancel(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureTapCancel, args);
+}
+
+void EventSender::GestureLongPress(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureLongPress, args);
+}
+
+void EventSender::GestureLongTap(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureLongTap, args);
+}
+
+void EventSender::GestureTwoFingerTap(gin::Arguments* args) {
+  GestureEvent(WebInputEvent::GestureTwoFingerTap, args);
+}
+
+void EventSender::ContinuousMouseScrollBy(gin::Arguments* args) {
+  WebMouseWheelEvent event;
+  InitMouseWheelEvent(args, true, &event);
+  view_->handleInputEvent(event);
+}
+
+void EventSender::DispatchMessage(int msg, int wparam, int lparam) {
+#if defined(OS_WIN)
+  // WebKit's version of this function stuffs a MSG struct and uses
+  // TranslateMessage and DispatchMessage. We use a WebKeyboardEvent, which
+  // doesn't need to receive the DeadChar and SysDeadChar messages.
+  if (msg == WM_DEADCHAR || msg == WM_SYSDEADCHAR)
+    return;
+
+  if (force_layout_on_events_)
+    view_->layout();
+
+  view_->handleInputEvent(
+      WebInputEventFactory::keyboardEvent(0, msg, wparam, lparam));
+#endif
+}
+
+void EventSender::MouseMoveTo(gin::Arguments* args) {
+  if (force_layout_on_events_)
+    view_->layout();
+
+  int x;
+  int y;
+  args->GetNext(&x);
+  args->GetNext(&y);
+  WebPoint mouse_pos(x, y);
+
+  int modifiers = 0;
+  if (!args->PeekNext().IsEmpty())
+    modifiers = GetKeyModifiersFromV8(args->PeekNext());
+
+  if (is_drag_mode_ && pressed_button_ == WebMouseEvent::ButtonLeft &&
+      !replaying_saved_events_) {
+    SavedEvent saved_event;
+    saved_event.type = SavedEvent::TYPE_MOUSE_MOVE;
+    saved_event.pos = mouse_pos;
+    saved_event.modifiers = modifiers;
+    mouse_event_queue_.push_back(saved_event);
+  } else {
+    WebMouseEvent event;
+    InitMouseEvent(WebInputEvent::MouseMove,
+                   pressed_button_,
+                   mouse_pos,
+                   GetCurrentEventTimeSec(),
+                   click_count_,
+                   modifiers,
+                   &event);
+    DoMouseMove(event);
+  }
+}
+
+void EventSender::MouseScrollBy(gin::Arguments* args) {
+   WebMouseWheelEvent event;
+  InitMouseWheelEvent(args, false, &event);
+  view_->handleInputEvent(event);
+}
+
+void EventSender::MouseMomentumScrollBy(gin::Arguments* args) {
+  WebMouseWheelEvent event;
+  InitMouseWheelEvent(args, true, &event);
+  event.momentumPhase = WebMouseWheelEvent::PhaseChanged;
+  event.hasPreciseScrollingDeltas = true;
+  view_->handleInputEvent(event);
+}
+
+void EventSender::MouseMomentumEnd() {
+  WebMouseWheelEvent event;
+  InitMouseEvent(WebInputEvent::MouseWheel,
+                 WebMouseEvent::ButtonNone,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 0,
+                 &event);
+  event.momentumPhase = WebMouseWheelEvent::PhaseEnded;
+  event.hasPreciseScrollingDeltas = true;
+  view_->handleInputEvent(event);
+}
+
+void EventSender::ScheduleAsynchronousClick(int button_number, int modifiers) {
+  delegate_->postTask(new MouseDownTask(this, button_number, modifiers));
+  delegate_->postTask(new MouseUpTask(this, button_number, modifiers));
+}
+
+void EventSender::ScheduleAsynchronousKeyDown(const std::string& code_str,
+                                              int modifiers,
+                                              KeyLocationCode location) {
+  delegate_->postTask(new KeyDownTask(this, code_str, modifiers, location));
+}
+
+double EventSender::GetCurrentEventTimeSec() {
+  return (delegate_->getCurrentTimeInMillisecond() + time_offset_ms_) / 1000.0;
+}
+
+void EventSender::DoLeapForward(int milliseconds) {
+  time_offset_ms_ += milliseconds;
+}
+
+void EventSender::SendCurrentTouchEvent(WebInputEvent::Type type) {
+  DCHECK_GT(static_cast<unsigned>(WebTouchEvent::touchesLengthCap),
+            touch_points_.size());
+  if (force_layout_on_events_)
+    view_->layout();
+
+  WebTouchEvent touch_event;
+  touch_event.type = type;
+  touch_event.modifiers = touch_modifiers_;
+  touch_event.timeStampSeconds = GetCurrentEventTimeSec();
+  touch_event.touchesLength = touch_points_.size();
+  for (size_t i = 0; i < touch_points_.size(); ++i)
+    touch_event.touches[i] = touch_points_[i];
+  view_->handleInputEvent(touch_event);
+
+  for (size_t i = 0; i < touch_points_.size(); ++i) {
+    WebTouchPoint* touch_point = &touch_points_[i];
+    if (touch_point->state == WebTouchPoint::StateReleased) {
+      touch_points_.erase(touch_points_.begin() + i);
+      --i;
+    } else
+      touch_point->state = WebTouchPoint::StateStationary;
+  }
+}
+
+void EventSender::GestureEvent(WebInputEvent::Type type,
+                               gin::Arguments* args) {
+  double x;
+  double y;
+  args->GetNext(&x);
+  args->GetNext(&y);
+  WebPoint point(x, y);
+
+  WebGestureEvent event;
+  event.type = type;
+
+  switch (type) {
+    case WebInputEvent::GestureScrollUpdate:
+    case WebInputEvent::GestureScrollUpdateWithoutPropagation:
+      event.data.scrollUpdate.deltaX = static_cast<float>(x);
+      event.data.scrollUpdate.deltaY = static_cast<float>(y);
+      event.x = current_gesture_location_.x;
+      event.y = current_gesture_location_.y;
+      current_gesture_location_.x =
+          current_gesture_location_.x + event.data.scrollUpdate.deltaX;
+      current_gesture_location_.y =
+          current_gesture_location_.y + event.data.scrollUpdate.deltaY;
+      break;
+    case WebInputEvent::GestureScrollBegin:
+      current_gesture_location_ = WebPoint(point.x, point.y);
+      event.x = current_gesture_location_.x;
+      event.y = current_gesture_location_.y;
+      break;
+    case WebInputEvent::GestureScrollEnd:
+    case WebInputEvent::GestureFlingStart:
+      event.x = current_gesture_location_.x;
+      event.y = current_gesture_location_.y;
+      break;
+    case WebInputEvent::GestureTap:
+      if (!args->PeekNext().IsEmpty()) {
+        float tap_count;
+        if (!args->GetNext(&tap_count)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.tap.tapCount = tap_count;
+      } else {
+        event.data.tap.tapCount = 1;
+      }
+
+      event.x = point.x;
+      event.y = point.y;
+      break;
+    case WebInputEvent::GestureTapUnconfirmed:
+      if (!args->PeekNext().IsEmpty()) {
+        float tap_count;
+        if (!args->GetNext(&tap_count)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.tap.tapCount = tap_count;
+      } else {
+        event.data.tap.tapCount = 1;
+      }
+      event.x = point.x;
+      event.y = point.y;
+      break;
+    case WebInputEvent::GestureTapDown:
+      event.x = point.x;
+      event.y = point.y;
+      if (!args->PeekNext().IsEmpty()) {
+        float width;
+        if (!args->GetNext(&width)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.tapDown.width = width;
+      }
+      if (!args->PeekNext().IsEmpty()) {
+        float height;
+        if (!args->GetNext(&height)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.tapDown.height = height;
+      }
+      break;
+    case WebInputEvent::GestureShowPress:
+      event.x = point.x;
+      event.y = point.y;
+      if (!args->PeekNext().IsEmpty()) {
+        float width;
+        if (!args->GetNext(&width)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.showPress.width = width;
+        if (!args->PeekNext().IsEmpty()) {
+          float height;
+          if (!args->GetNext(&height)) {
+            args->ThrowError();
+            return;
+          }
+          event.data.showPress.height = height;
+        }
+      }
+      break;
+    case WebInputEvent::GestureTapCancel:
+      event.x = point.x;
+      event.y = point.y;
+      break;
+    case WebInputEvent::GestureLongPress:
+      event.x = point.x;
+      event.y = point.y;
+      if (!args->PeekNext().IsEmpty()) {
+        float width;
+        if (!args->GetNext(&width)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.longPress.width = width;
+        if (!args->PeekNext().IsEmpty()) {
+          float height;
+          if (!args->GetNext(&height)) {
+            args->ThrowError();
+            return;
+          }
+          event.data.longPress.height = height;
+        }
+      }
+      break;
+    case WebInputEvent::GestureLongTap:
+      event.x = point.x;
+      event.y = point.y;
+      if (!args->PeekNext().IsEmpty()) {
+        float width;
+        if (!args->GetNext(&width)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.longPress.width = width;
+        if (!args->PeekNext().IsEmpty()) {
+          float height;
+          if (!args->GetNext(&height)) {
+            args->ThrowError();
+            return;
+          }
+          event.data.longPress.height = height;
+        }
+      }
+      break;
+    case WebInputEvent::GestureTwoFingerTap:
+      event.x = point.x;
+      event.y = point.y;
+      if (!args->PeekNext().IsEmpty()) {
+        float first_finger_width;
+        if (!args->GetNext(&first_finger_width)) {
+          args->ThrowError();
+          return;
+        }
+        event.data.twoFingerTap.firstFingerWidth = first_finger_width;
+        if (!args->PeekNext().IsEmpty()) {
+          float first_finger_height;
+          if (!args->GetNext(&first_finger_height)) {
+            args->ThrowError();
+            return;
+          }
+          event.data.twoFingerTap.firstFingerHeight = first_finger_height;
+        }
+      }
+      break;
+    default:
+      NOTREACHED();
+  }
+
+  event.globalX = event.x;
+  event.globalY = event.y;
+  event.timeStampSeconds = GetCurrentEventTimeSec();
+
+  if (force_layout_on_events_)
+    view_->layout();
+
+  view_->handleInputEvent(event);
+
+  // Long press might start a drag drop session. Complete it if so.
+  if (type == WebInputEvent::GestureLongPress && !current_drag_data_.isNull()) {
+    WebMouseEvent mouse_event;
+    InitMouseEvent(WebInputEvent::MouseDown,
+                   pressed_button_,
+                   point,
+                   GetCurrentEventTimeSec(),
+                   click_count_,
+                   0,
+                   &mouse_event);
+
+    FinishDragAndDrop(mouse_event, blink::WebDragOperationNone);
+  }
+}
+
+void EventSender::UpdateClickCountForButton(
+    WebMouseEvent::Button button_type) {
+  if ((GetCurrentEventTimeSec() - last_click_time_sec_ <
+       kMultipleClickTimeSec) &&
+      (!OutsideMultiClickRadius(last_mouse_pos_, last_click_pos_)) &&
+      (button_type == last_button_type_)) {
+    ++click_count_;
+  } else {
+    click_count_ = 1;
+    last_button_type_ = button_type;
+  }
+}
+
+void EventSender::InitMouseWheelEvent(gin::Arguments* args,
+                                      bool continuous,
+                                      WebMouseWheelEvent* event) {
+  // Force a layout here just to make sure every position has been
+  // determined before we send events (as well as all the other methods
+  // that send an event do).
+  if (force_layout_on_events_)
+    view_->layout();
+
+  double horizontal;
+  if (!args->GetNext(&horizontal)) {
+    args->ThrowError();
+    return;
+  }
+  double vertical;
+  if (!args->GetNext(&vertical)) {
+    args->ThrowError();
+    return;
+  }
+
+  bool paged = false;
+  bool has_precise_scrolling_deltas = false;
+  int modifiers = 0;
+  if (!args->PeekNext().IsEmpty()) {
+    args->GetNext(&paged);
+    if (!args->PeekNext().IsEmpty()) {
+      args->GetNext(&has_precise_scrolling_deltas);
+      if (!args->PeekNext().IsEmpty())
+        modifiers = GetKeyModifiersFromV8(args->PeekNext());
+    }
+  }
+
+  InitMouseEvent(WebInputEvent::MouseWheel,
+                 pressed_button_,
+                 last_mouse_pos_,
+                 GetCurrentEventTimeSec(),
+                 click_count_,
+                 modifiers,
+                 event);
+  event->wheelTicksX = static_cast<float>(horizontal);
+  event->wheelTicksY = static_cast<float>(vertical);
+  event->deltaX = event->wheelTicksX;
+  event->deltaY = event->wheelTicksY;
+  event->scrollByPage = paged;
+  event->hasPreciseScrollingDeltas = has_precise_scrolling_deltas;
+
+  if (continuous) {
+    event->wheelTicksX /= kScrollbarPixelsPerTick;
+    event->wheelTicksY /= kScrollbarPixelsPerTick;
+  } else {
+    event->deltaX *= kScrollbarPixelsPerTick;
+    event->deltaY *= kScrollbarPixelsPerTick;
+  }
+}
+
+void EventSender::FinishDragAndDrop(const WebMouseEvent& e,
+                                     blink::WebDragOperation drag_effect) {
+  WebPoint client_point(e.x, e.y);
+  WebPoint screen_point(e.globalX, e.globalY);
+  current_drag_effect_ = drag_effect;
+  if (current_drag_effect_) {
+    // Specifically pass any keyboard modifiers to the drop method. This allows
+    // tests to control the drop type (i.e. copy or move).
+    view_->dragTargetDrop(client_point, screen_point, e.modifiers);
+  } else {
+    view_->dragTargetDragLeave();
+  }
+  view_->dragSourceEndedAt(client_point, screen_point, current_drag_effect_);
+  view_->dragSourceSystemDragEnded();
+
+  current_drag_data_.reset();
+}
+
+void EventSender::DoMouseUp(const WebMouseEvent& e) {
+  view_->handleInputEvent(e);
+
+  pressed_button_ = WebMouseEvent::ButtonNone;
+  last_click_time_sec_ = e.timeStampSeconds;
+  last_click_pos_ = last_mouse_pos_;
+
+  // If we're in a drag operation, complete it.
+  if (current_drag_data_.isNull())
+    return;
+
+  WebPoint client_point(e.x, e.y);
+  WebPoint screen_point(e.globalX, e.globalY);
+  FinishDragAndDrop(
+      e,
+      view_->dragTargetDragOver(
+          client_point, screen_point, current_drag_effects_allowed_, 0));
+}
+
+void EventSender::DoMouseMove(const WebMouseEvent& e) {
+  last_mouse_pos_ = WebPoint(e.x, e.y);
+
+  view_->handleInputEvent(e);
+
+  if (pressed_button_ == WebMouseEvent::ButtonNone ||
+      current_drag_data_.isNull()) {
+    return;
+  }
+
+  WebPoint client_point(e.x, e.y);
+  WebPoint screen_point(e.globalX, e.globalY);
+  current_drag_effect_ = view_->dragTargetDragOver(
+      client_point, screen_point, current_drag_effects_allowed_, 0);
+}
+
+void EventSender::ReplaySavedEvents() {
+  replaying_saved_events_ = true;
+  while (!mouse_event_queue_.empty()) {
+    SavedEvent e = mouse_event_queue_.front();
+    mouse_event_queue_.pop_front();
+
+    switch (e.type) {
+      case SavedEvent::TYPE_MOUSE_MOVE: {
+        WebMouseEvent event;
+        InitMouseEvent(WebInputEvent::MouseMove,
+                       pressed_button_,
+                       e.pos,
+                       GetCurrentEventTimeSec(),
+                       click_count_,
+                       e.modifiers,
+                       &event);
+        DoMouseMove(event);
+        break;
+      }
+      case SavedEvent::TYPE_LEAP_FORWARD:
+        DoLeapForward(e.milliseconds);
+        break;
+      case SavedEvent::TYPE_MOUSE_UP: {
+        WebMouseEvent event;
+        InitMouseEvent(WebInputEvent::MouseUp,
+                       e.button_type,
+                       last_mouse_pos_,
+                       GetCurrentEventTimeSec(),
+                       click_count_,
+                       e.modifiers,
+                       &event);
+        DoMouseUp(event);
+        break;
+      }
+      default:
+        NOTREACHED();
+    }
+  }
+
+  replaying_saved_events_ = false;
+}
+
+}  // namespace content
diff --git a/content/shell/renderer/test_runner/event_sender.h b/content/shell/renderer/test_runner/event_sender.h
new file mode 100644
index 0000000..e1423a5
--- /dev/null
+++ b/content/shell/renderer/test_runner/event_sender.h
@@ -0,0 +1,276 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENT_SENDER_H_
+#define CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENT_SENDER_H_
+
+#include <queue>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "content/shell/renderer/test_runner/WebTask.h"
+#include "third_party/WebKit/public/platform/WebDragData.h"
+#include "third_party/WebKit/public/platform/WebPoint.h"
+#include "third_party/WebKit/public/web/WebDragOperation.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "third_party/WebKit/public/web/WebTouchPoint.h"
+
+namespace blink {
+class WebFrame;
+class WebView;
+struct WebContextMenuData;
+}
+
+namespace gin {
+class Arguments;
+}
+
+namespace WebTestRunner {
+class TestInterfaces;
+class WebTestDelegate;
+}
+
+namespace content {
+
+// Key event location code introduced in DOM Level 3.
+// See also: http://www.w3.org/TR/DOM-Level-3-Events/#events-keyboardevents
+enum KeyLocationCode {
+  DOMKeyLocationStandard      = 0x00,
+  DOMKeyLocationLeft          = 0x01,
+  DOMKeyLocationRight         = 0x02,
+  DOMKeyLocationNumpad        = 0x03
+};
+
+class EventSender : public base::SupportsWeakPtr<EventSender> {
+ public:
+  explicit EventSender(WebTestRunner::TestInterfaces*);
+  virtual ~EventSender();
+
+  void Reset();
+  void Install(blink::WebFrame*);
+  void SetDelegate(WebTestRunner::WebTestDelegate*);
+  void SetWebView(blink::WebView*);
+
+  void SetContextMenuData(const blink::WebContextMenuData&);
+
+  void DoDragDrop(const blink::WebDragData&, blink::WebDragOperationsMask);
+
+  void MouseDown(int button_number, int modifiers);
+  void MouseUp(int button_number, int modifiers);
+  void KeyDown(const std::string& code_str,
+               int modifiers,
+               KeyLocationCode location);
+
+  WebTestRunner::WebTaskList* taskList() { return &task_list_; }
+
+ private:
+  friend class EventSenderBindings;
+
+  struct SavedEvent {
+    enum SavedEventType {
+      TYPE_UNSPECIFIED,
+      TYPE_MOUSE_UP,
+      TYPE_MOUSE_MOVE,
+      TYPE_LEAP_FORWARD
+    };
+
+    SavedEvent();
+
+    SavedEventType type;
+    blink::WebMouseEvent::Button button_type;  // For MouseUp.
+    blink::WebPoint pos;                       // For MouseMove.
+    int milliseconds;                          // For LeapForward.
+    int modifiers;
+  };
+
+  void EnableDOMUIEventLogging();
+  void FireKeyboardEventsToElement();
+  void ClearKillRing();
+
+  std::vector<std::string> ContextClick();
+
+  void TextZoomIn();
+  void TextZoomOut();
+
+  void ZoomPageIn();
+  void ZoomPageOut();
+
+  void SetPageScaleFactor(float scale_factor, int x, int y);
+
+  void ClearTouchPoints();
+  void ReleaseTouchPoint(unsigned index);
+  void UpdateTouchPoint(unsigned index, int x, int y);
+  void CancelTouchPoint(unsigned index);
+  void SetTouchModifier(const std::string& key_name, bool set_mask);
+
+  void DumpFilenameBeingDragged();
+
+  void GestureFlingCancel();
+  void GestureFlingStart(float x, float y, float velocity_x, float velocity_y);
+  void GestureScrollFirstPoint(int x, int y);
+
+  void TouchStart();
+  void TouchMove();
+  void TouchCancel();
+  void TouchEnd();
+
+  void LeapForward(int milliseconds);
+
+  void BeginDragWithFiles(const std::vector<std::string>& files);
+
+  void AddTouchPoint(gin::Arguments* args);
+
+  void MouseDragBegin();
+  void MouseDragEnd();
+  void MouseMomentumBegin();
+
+  void GestureScrollBegin(gin::Arguments* args);
+  void GestureScrollEnd(gin::Arguments* args);
+  void GestureScrollUpdate(gin::Arguments* args);
+  void GestureScrollUpdateWithoutPropagation(gin::Arguments* args);
+  void GestureTap(gin::Arguments* args);
+  void GestureTapDown(gin::Arguments* args);
+  void GestureShowPress(gin::Arguments* args);
+  void GestureTapCancel(gin::Arguments* args);
+  void GestureLongPress(gin::Arguments* args);
+  void GestureLongTap(gin::Arguments* args);
+  void GestureTwoFingerTap(gin::Arguments* args);
+
+  void ContinuousMouseScrollBy(gin::Arguments* args);
+  void DispatchMessage(int msg, int wparam, int lparam);
+  void MouseMoveTo(gin::Arguments* args);
+  void MouseScrollBy(gin::Arguments* args);
+  void MouseMomentumScrollBy(gin::Arguments* args);
+  void MouseMomentumEnd();
+  void ScheduleAsynchronousClick(int button_number, int modifiers);
+  void ScheduleAsynchronousKeyDown(const std::string& code_str,
+                                   int modifiers,
+                                   KeyLocationCode location);
+
+  double GetCurrentEventTimeSec();
+
+  void DoLeapForward(int milliseconds);
+
+  void SendCurrentTouchEvent(blink::WebInputEvent::Type);
+
+  void GestureEvent(blink::WebInputEvent::Type, gin::Arguments*);
+
+  void UpdateClickCountForButton(blink::WebMouseEvent::Button);
+
+  void InitMouseWheelEvent(gin::Arguments* args,
+                           bool continuous,
+                           blink::WebMouseWheelEvent* event);
+
+  void FinishDragAndDrop(const blink::WebMouseEvent&, blink::WebDragOperation);
+
+  void DoMouseUp(const blink::WebMouseEvent&);
+  void DoMouseMove(const blink::WebMouseEvent&);
+  void ReplaySavedEvents();
+
+  bool force_layout_on_events() const { return force_layout_on_events_; }
+  void set_force_layout_on_events(bool force) {
+    force_layout_on_events_ = force;
+  }
+
+  bool is_drag_mode() const { return is_drag_mode_; }
+  void set_is_drag_mode(bool drag_mode) { is_drag_mode_ = drag_mode; }
+
+#if defined(OS_WIN)
+  int wm_key_down() const { return wm_key_down_; }
+  void set_wm_key_down(int key_down) { wm_key_down_ = key_down; }
+
+  int wm_key_up() const { return wm_key_up_; }
+  void set_wm_key_up(int key_up) { wm_key_up_ = key_up; }
+
+  int wm_char() const { return wm_char_; }
+  void set_wm_char(int wm_char) { wm_char_ = wm_char; }
+
+  int wm_dead_char() const { return wm_dead_char_; }
+  void set_wm_dead_char(int dead_char) {
+    wm_dead_char_ = dead_char;
+  }
+
+  int wm_sys_key_down() const { return wm_sys_key_down_; }
+  void set_wm_sys_key_down(int key_down) { wm_sys_key_down_ = key_down; }
+
+  int wm_sys_key_up() const { return wm_sys_key_up_; }
+  void set_wm_sys_key_up(int key_up) { wm_sys_key_up_ = key_up; }
+
+  int wm_sys_char() const { return wm_sys_char_; }
+  void set_wm_sys_char(int sys_char) { wm_sys_char_ = sys_char; }
+
+  int wm_sys_dead_char() const { return wm_sys_dead_char_; }
+  void set_wm_sys_dead_char(int sys_dead_char) {
+    wm_sys_dead_char_ = sys_dead_char;
+  }
+
+  int wm_key_down_;
+  int wm_key_up_;
+  int wm_char_;
+  int wm_dead_char_;
+  int wm_sys_key_down_;
+  int wm_sys_key_up_;
+  int wm_sys_char_;
+  int wm_sys_dead_char_;
+#endif
+
+  WebTestRunner::WebTaskList task_list_;
+
+  WebTestRunner::TestInterfaces* interfaces_;
+  WebTestRunner::WebTestDelegate* delegate_;
+  blink::WebView* view_;
+
+  bool force_layout_on_events_;
+
+  // When set to true (the default value), we batch mouse move and mouse up
+  // events so we can simulate drag & drop.
+  bool is_drag_mode_;
+
+  int touch_modifiers_;
+  std::vector<blink::WebTouchPoint> touch_points_;
+
+  scoped_ptr<blink::WebContextMenuData> last_context_menu_data_;
+
+  blink::WebDragData current_drag_data_;
+
+  // Location of the touch point that initiated a gesture.
+  blink::WebPoint current_gesture_location_;
+
+  // Currently pressed mouse button (Left/Right/Middle or None).
+  static blink::WebMouseEvent::Button pressed_button_;
+
+  bool replaying_saved_events_;
+
+  std::deque<SavedEvent> mouse_event_queue_;
+
+  blink::WebDragOperationsMask current_drag_effects_allowed_;
+
+  // Location of last mouseMoveTo event.
+  static blink::WebPoint last_mouse_pos_;
+
+  // Time and place of the last mouse up event.
+  double last_click_time_sec_;
+  blink::WebPoint last_click_pos_;
+
+  // The last button number passed to mouseDown and mouseUp.
+  // Used to determine whether the click count continues to increment or not.
+  static blink::WebMouseEvent::Button last_button_type_;
+
+  blink::WebDragOperation current_drag_effect_;
+
+  uint32 time_offset_ms_;
+  int click_count_;
+
+  base::WeakPtrFactory<EventSender> weak_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(EventSender);
+};
+
+}  // namespace content
+
+#endif  // CONTENT_SHELL_RENDERER_TEST_RUNNER_EVENT_SENDER_H_
diff --git a/content/shell/renderer/test_runner/gamepad_controller.cc b/content/shell/renderer/test_runner/gamepad_controller.cc
index 576469d..6affefb 100644
--- a/content/shell/renderer/test_runner/gamepad_controller.cc
+++ b/content/shell/renderer/test_runner/gamepad_controller.cc
@@ -38,6 +38,7 @@
       v8::Isolate* isolate) OVERRIDE;
 
   void Connect(int index);
+  void DispatchConnected(int index);
   void Disconnect(int index);
   void SetId(int index, const std::string& src);
   void SetButtonCount(int index, int buttons);
@@ -82,6 +83,7 @@
   return gin::Wrappable<GamepadControllerBindings>::GetObjectTemplateBuilder(
              isolate)
       .SetMethod("connect", &GamepadControllerBindings::Connect)
+      .SetMethod("dispatchConnected", &GamepadControllerBindings::DispatchConnected)
       .SetMethod("disconnect", &GamepadControllerBindings::Disconnect)
       .SetMethod("setId", &GamepadControllerBindings::SetId)
       .SetMethod("setButtonCount", &GamepadControllerBindings::SetButtonCount)
@@ -95,6 +97,11 @@
     controller_->Connect(index);
 }
 
+void GamepadControllerBindings::DispatchConnected(int index) {
+  if (controller_)
+    controller_->DispatchConnected(index);
+}
+
 void GamepadControllerBindings::Disconnect(int index) {
   if (controller_)
     controller_->Disconnect(index);
@@ -158,17 +165,28 @@
     delegate_->setGamepadData(gamepads_);
 }
 
+void GamepadController::DispatchConnected(int index) {
+  if (index < 0 || index >= static_cast<int>(WebGamepads::itemsLengthCap))
+    return;
+  const WebGamepad& pad = gamepads_.items[index];
+  if (pad.connected && delegate_)
+    delegate_->didConnectGamepad(index, pad);
+}
+
 void GamepadController::Disconnect(int index) {
   if (index < 0 || index >= static_cast<int>(WebGamepads::itemsLengthCap))
     return;
-  gamepads_.items[index].connected = false;
+  WebGamepad& pad = gamepads_.items[index];
+  pad.connected = false;
   gamepads_.length = 0;
   for (unsigned i = 0; i < WebGamepads::itemsLengthCap; ++i) {
     if (gamepads_.items[i].connected)
       gamepads_.length = i + 1;
   }
-  if (delegate_)
+  if (delegate_) {
     delegate_->setGamepadData(gamepads_);
+    delegate_->didDisconnectGamepad(index, pad);
+  }
 }
 
 void GamepadController::SetId(int index, const std::string& src) {
diff --git a/content/shell/renderer/test_runner/gamepad_controller.h b/content/shell/renderer/test_runner/gamepad_controller.h
index 1bc050a..f38fc32 100644
--- a/content/shell/renderer/test_runner/gamepad_controller.h
+++ b/content/shell/renderer/test_runner/gamepad_controller.h
@@ -30,7 +30,15 @@
  private:
   friend class GamepadControllerBindings;
 
+  // TODO(b.kelemen): for historical reasons Connect just initializes the
+  // object. The 'gamepadconnected' event will be dispatched via
+  // DispatchConnected. Tests for connected events need to first connect(),
+  // then set the gamepad data and finally call dispatchConnected().
+  // We should consider renaming Connect to Init and DispatchConnected to
+  // Connect and at the same time updating all the gamepad tests.
   void Connect(int index);
+  void DispatchConnected(int index);
+
   void Disconnect(int index);
   void SetId(int index, const std::string& src);
   void SetButtonCount(int index, int buttons);
diff --git a/content/shell/renderer/test_runner/test_runner.cc b/content/shell/renderer/test_runner/test_runner.cc
index 06ba74b..de6d749 100644
--- a/content/shell/renderer/test_runner/test_runner.cc
+++ b/content/shell/renderer/test_runner/test_runner.cc
@@ -234,7 +234,7 @@
   void SetBackingScaleFactor(double value, v8::Handle<v8::Function> callback);
   void SetPOSIXLocale(const std::string& locale);
   void SetMIDIAccessorResult(bool result);
-  void SetMIDISysExPermission(bool value);
+  void SetMIDISysexPermission(bool value);
   void GrantWebNotificationPermission(gin::Arguments* args);
   bool SimulateWebNotificationClick(const std::string& value);
   void AddMockSpeechInputResult(const std::string& result,
@@ -460,8 +460,8 @@
       .SetMethod("setPOSIXLocale", &TestRunnerBindings::SetPOSIXLocale)
       .SetMethod("setMIDIAccessorResult",
                  &TestRunnerBindings::SetMIDIAccessorResult)
-      .SetMethod("setMIDISysExPermission",
-                 &TestRunnerBindings::SetMIDISysExPermission)
+      .SetMethod("setMIDISysexPermission",
+                 &TestRunnerBindings::SetMIDISysexPermission)
       .SetMethod("grantWebNotificationPermission",
                  &TestRunnerBindings::GrantWebNotificationPermission)
       .SetMethod("simulateWebNotificationClick",
@@ -1169,9 +1169,9 @@
     runner_->SetMIDIAccessorResult(result);
 }
 
-void TestRunnerBindings::SetMIDISysExPermission(bool value) {
+void TestRunnerBindings::SetMIDISysexPermission(bool value) {
   if (runner_)
-    runner_->SetMIDISysExPermission(value);
+    runner_->SetMIDISysexPermission(value);
 }
 
 void TestRunnerBindings::GrantWebNotificationPermission(gin::Arguments* args) {
@@ -2511,11 +2511,11 @@
   midi_accessor_result_ = result;
 }
 
-void TestRunner::SetMIDISysExPermission(bool value) {
+void TestRunner::SetMIDISysexPermission(bool value) {
   const std::vector<WebTestProxyBase*>& windowList =
       test_interfaces_->windowList();
   for (unsigned i = 0; i < windowList.size(); ++i)
-    windowList.at(i)->midiClientMock()->setSysExPermission(value);
+    windowList.at(i)->midiClientMock()->setSysexPermission(value);
 }
 
 void TestRunner::GrantWebNotificationPermission(const std::string& origin,
diff --git a/content/shell/renderer/test_runner/test_runner.h b/content/shell/renderer/test_runner/test_runner.h
index 29472e6..ff0f3ac 100644
--- a/content/shell/renderer/test_runner/test_runner.h
+++ b/content/shell/renderer/test_runner/test_runner.h
@@ -478,7 +478,7 @@
 
   // MIDI function to control permission handling.
   void SetMIDIAccessorResult(bool result);
-  void SetMIDISysExPermission(bool value);
+  void SetMIDISysexPermission(bool value);
 
   // Grants permission for desktop notifications to an origin
   void GrantWebNotificationPermission(const std::string& origin,
diff --git a/content/shell/renderer/test_runner/web_ax_object_proxy.cc b/content/shell/renderer/test_runner/web_ax_object_proxy.cc
index ee3ea43..3ff89f8 100644
--- a/content/shell/renderer/test_runner/web_ax_object_proxy.cc
+++ b/content/shell/renderer/test_runner/web_ax_object_proxy.cc
@@ -325,7 +325,7 @@
     DCHECK_EQ(inline_text_box.role(), blink::WebAXRoleInlineTextBox);
     int start = end;
     end += inline_text_box.stringValue().length();
-    if (end <= characterIndex)
+    if (characterIndex < start || characterIndex >= end)
       continue;
     blink::WebRect inline_text_box_rect = inline_text_box.boundingBoxRect();
     int localIndex = characterIndex - start;
diff --git a/content/shell/renderer/webkit_test_runner.cc b/content/shell/renderer/webkit_test_runner.cc
index d08eca4..4141520 100644
--- a/content/shell/renderer/webkit_test_runner.cc
+++ b/content/shell/renderer/webkit_test_runner.cc
@@ -236,6 +236,18 @@
   SetMockGamepads(gamepads);
 }
 
+void WebKitTestRunner::didConnectGamepad(
+    int index,
+    const blink::WebGamepad& gamepad) {
+  MockGamepadConnected(index, gamepad);
+}
+
+void WebKitTestRunner::didDisconnectGamepad(
+    int index,
+    const blink::WebGamepad& gamepad) {
+  MockGamepadDisconnected(index, gamepad);
+}
+
 void WebKitTestRunner::setDeviceMotionData(const WebDeviceMotionData& data) {
   SetMockDeviceMotionData(data);
 }
diff --git a/content/shell/renderer/webkit_test_runner.h b/content/shell/renderer/webkit_test_runner.h
index 67f50b0..0492d33 100644
--- a/content/shell/renderer/webkit_test_runner.h
+++ b/content/shell/renderer/webkit_test_runner.h
@@ -57,6 +57,10 @@
   virtual void setEditCommand(const std::string& name,
                               const std::string& value) OVERRIDE;
   virtual void setGamepadData(const blink::WebGamepads& gamepads) OVERRIDE;
+  virtual void didConnectGamepad(int index,
+                                const blink::WebGamepad& gamepad) OVERRIDE;
+  virtual void didDisconnectGamepad(int index,
+                                   const blink::WebGamepad& gamepad) OVERRIDE;
   virtual void setDeviceMotionData(
       const blink::WebDeviceMotionData& data) OVERRIDE;
   virtual void setDeviceOrientationData(
diff --git a/content/shell/tools/plugin/main.cpp b/content/shell/tools/plugin/main.cpp
index 0a4c3b8..6cfab1c 100644
--- a/content/shell/tools/plugin/main.cpp
+++ b/content/shell/tools/plugin/main.cpp
@@ -792,14 +792,16 @@
     int16_t ret = 0;
 #ifdef XP_MACOSX
 #ifndef NP_NO_CARBON
-    if (obj->eventModel == NPEventModelCarbon)
-        ret = handleEventCarbon(instance, obj, static_cast<EventRecord*>(event));
-#endif
     assert(obj->eventModel == NPEventModelCarbon ||
            obj->eventModel == NPEventModelCocoa);
     if (obj->eventModel == NPEventModelCocoa)
-      ret = handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event));
-
+        ret = handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event));
+    else if (obj->eventModel == NPEventModelCarbon)
+        ret = handleEventCarbon(instance, obj, static_cast<EventRecord*>(event));
+#else
+    assert(obj->eventModel == NPEventModelCocoa);
+    ret = handleEventCocoa(instance, obj, static_cast<NPCocoaEvent*>(event));
+#endif
 #elif defined(XP_UNIX)
     ret = handleEventX11(instance, obj, static_cast<XEvent*>(event));
 #elif defined(XP_WIN)
diff --git a/content/speech_recognition_error_java.target.darwin-arm.mk b/content/speech_recognition_error_java.target.darwin-arm.mk
index dd72489..75e1b9c 100644
--- a/content/speech_recognition_error_java.target.darwin-arm.mk
+++ b/content/speech_recognition_error_java.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/speech_recognition_error_java.target.darwin-mips.mk b/content/speech_recognition_error_java.target.darwin-mips.mk
index 81e680c..b61c334 100644
--- a/content/speech_recognition_error_java.target.darwin-mips.mk
+++ b/content/speech_recognition_error_java.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/speech_recognition_error_java.target.darwin-x86.mk b/content/speech_recognition_error_java.target.darwin-x86.mk
index 787ba0a..eed8456 100644
--- a/content/speech_recognition_error_java.target.darwin-x86.mk
+++ b/content/speech_recognition_error_java.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/speech_recognition_error_java.target.darwin-x86_64.mk b/content/speech_recognition_error_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..1ee40c2
--- /dev/null
+++ b/content/speech_recognition_error_java.target.darwin-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_speech_recognition_error_java_gyp
+LOCAL_MODULE_STEM := speech_recognition_error_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_speech_recognition_error_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/speech_recognition_error_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/SpeechRecognitionError.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/SpeechRecognitionError.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/speech_recognition_error_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java" "--template=public/android/java/src/org/chromium/content/browser/SpeechRecognitionError.template"
+
+.PHONY: content_speech_recognition_error_java_gyp_rule_trigger
+content_speech_recognition_error_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_speech_recognition_error_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_speech_recognition_error_java_gyp
+
+# Alias gyp target name.
+.PHONY: speech_recognition_error_java
+speech_recognition_error_java: content_speech_recognition_error_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/speech_recognition_error_java.target.linux-arm.mk b/content/speech_recognition_error_java.target.linux-arm.mk
index dd72489..75e1b9c 100644
--- a/content/speech_recognition_error_java.target.linux-arm.mk
+++ b/content/speech_recognition_error_java.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/speech_recognition_error_java.target.linux-mips.mk b/content/speech_recognition_error_java.target.linux-mips.mk
index 81e680c..b61c334 100644
--- a/content/speech_recognition_error_java.target.linux-mips.mk
+++ b/content/speech_recognition_error_java.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/speech_recognition_error_java.target.linux-x86.mk b/content/speech_recognition_error_java.target.linux-x86.mk
index 787ba0a..eed8456 100644
--- a/content/speech_recognition_error_java.target.linux-x86.mk
+++ b/content/speech_recognition_error_java.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/content/speech_recognition_error_java.target.linux-x86_64.mk b/content/speech_recognition_error_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..1ee40c2
--- /dev/null
+++ b/content/speech_recognition_error_java.target.linux-x86_64.mk
@@ -0,0 +1,235 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_speech_recognition_error_java_gyp
+LOCAL_MODULE_STEM := speech_recognition_error_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "content_content_gyp_speech_recognition_error_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'public/common/speech_recognition_error_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['public/android/java/src/org/chromium/content/browser/SpeechRecognitionError.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java: $(LOCAL_PATH)/content/public/android/java/src/org/chromium/content/browser/SpeechRecognitionError.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/content/public/common/speech_recognition_error_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser; cd $(gyp_local_path)/content; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java" "--template=public/android/java/src/org/chromium/content/browser/SpeechRecognitionError.template"
+
+.PHONY: content_speech_recognition_error_java_gyp_rule_trigger
+content_speech_recognition_error_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/content/browser/SpeechRecognitionError.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	content_speech_recognition_error_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DCONTENT_IMPLEMENTATION' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_speech_recognition_error_java_gyp
+
+# Alias gyp target name.
+.PHONY: speech_recognition_error_java
+speech_recognition_error_java: content_speech_recognition_error_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/test/accessibility_browser_test_utils.cc b/content/test/accessibility_browser_test_utils.cc
index f6cfbc9..8cb74ec 100644
--- a/content/test/accessibility_browser_test_utils.cc
+++ b/content/test/accessibility_browser_test_utils.cc
@@ -19,6 +19,19 @@
 
 namespace content {
 
+AccessibilityNotificationWaiter::AccessibilityNotificationWaiter(Shell* shell)
+    : shell_(shell),
+      event_to_wait_for_(ui::AX_EVENT_NONE),
+      loop_runner_(new MessageLoopRunner()),
+      weak_factory_(this) {
+  WebContents* web_contents = shell_->web_contents();
+  view_host_ = static_cast<RenderViewHostImpl*>(
+      web_contents->GetRenderViewHost());
+  view_host_->SetAccessibilityCallbackForTesting(
+      base::Bind(&AccessibilityNotificationWaiter::OnAccessibilityEvent,
+                 weak_factory_.GetWeakPtr()));
+}
+
 AccessibilityNotificationWaiter::AccessibilityNotificationWaiter(
     Shell* shell,
     AccessibilityMode accessibility_mode,
@@ -49,8 +62,10 @@
 
 void AccessibilityNotificationWaiter::OnAccessibilityEvent(
     ui::AXEvent event_type) {
-  if (!IsAboutBlank() && event_to_wait_for_ == event_type)
+  if (!IsAboutBlank() && (event_to_wait_for_ == ui::AX_EVENT_NONE ||
+                          event_to_wait_for_ == event_type)) {
     loop_runner_->Quit();
+  }
 }
 
 bool AccessibilityNotificationWaiter::IsAboutBlank() {
diff --git a/content/test/accessibility_browser_test_utils.h b/content/test/accessibility_browser_test_utils.h
index 25abe20..4cffa08 100644
--- a/content/test/accessibility_browser_test_utils.h
+++ b/content/test/accessibility_browser_test_utils.h
@@ -23,6 +23,8 @@
 // received.
 class AccessibilityNotificationWaiter {
  public:
+  explicit AccessibilityNotificationWaiter(Shell* shell);
+
   AccessibilityNotificationWaiter(
       Shell* shell,
       AccessibilityMode accessibility_mode,
diff --git a/content/test/content_browser_test.cc b/content/test/content_browser_test.cc
deleted file mode 100644
index 41df7f7..0000000
--- a/content/test/content_browser_test.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/test/content_browser_test.h"
-
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/path_service.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/url_constants.h"
-#include "content/shell/browser/shell.h"
-#include "content/shell/browser/shell_browser_context.h"
-#include "content/shell/browser/shell_content_browser_client.h"
-#include "content/shell/common/shell_switches.h"
-#include "content/shell/renderer/shell_content_renderer_client.h"
-#include "content/test/test_content_client.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-
-#if defined(OS_ANDROID)
-#include "content/shell/app/shell_main_delegate.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
-#endif
-
-#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(USE_X11)
-#include "ui/base/ime/input_method_initializer.h"
-#endif
-
-namespace content {
-
-ContentBrowserTest::ContentBrowserTest()
-    : setup_called_(false) {
-#if defined(OS_MACOSX)
-  // See comment in InProcessBrowserTest::InProcessBrowserTest().
-  base::FilePath content_shell_path;
-  CHECK(PathService::Get(base::FILE_EXE, &content_shell_path));
-  content_shell_path = content_shell_path.DirName();
-  content_shell_path = content_shell_path.Append(
-      FILE_PATH_LITERAL("Content Shell.app/Contents/MacOS/Content Shell"));
-  CHECK(PathService::Override(base::FILE_EXE, content_shell_path));
-#endif
-  base::FilePath content_test_data(FILE_PATH_LITERAL("content/test/data"));
-  CreateTestServer(content_test_data);
-  base::FilePath content_test_data_absolute;
-  CHECK(PathService::Get(base::DIR_SOURCE_ROOT, &content_test_data_absolute));
-  content_test_data_absolute =
-      content_test_data_absolute.Append(content_test_data);
-  embedded_test_server()->ServeFilesFromDirectory(content_test_data_absolute);
-}
-
-ContentBrowserTest::~ContentBrowserTest() {
-  CHECK(setup_called_) << "Overridden SetUp() did not call parent "
-                          "implementation, so test not run.";
-}
-
-void ContentBrowserTest::SetUp() {
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  command_line->AppendSwitch(switches::kContentBrowserTest);
-
-  SetUpCommandLine(command_line);
-
-#if defined(OS_ANDROID)
-  shell_main_delegate_.reset(new ShellMainDelegate);
-  shell_main_delegate_->PreSandboxStartup();
-  if (command_line->HasSwitch(switches::kSingleProcess)) {
-    // We explicitly leak the new ContentRendererClient as we're
-    // setting a global that may be used after ContentBrowserTest is
-    // destroyed.
-    ContentRendererClient* old_client =
-        SetRendererClientForTesting(new ShellContentRendererClient());
-    // No-one should have set this value before we did.
-    DCHECK(!old_client);
-  }
-#elif defined(OS_MACOSX)
-  // See InProcessBrowserTest::PrepareTestCommandLine().
-  base::FilePath subprocess_path;
-  PathService::Get(base::FILE_EXE, &subprocess_path);
-  subprocess_path = subprocess_path.DirName().DirName();
-  DCHECK_EQ(subprocess_path.BaseName().value(), "Contents");
-  subprocess_path = subprocess_path.Append(
-      "Frameworks/Content Shell Helper.app/Contents/MacOS/Content Shell Helper");
-  command_line->AppendSwitchPath(switches::kBrowserSubprocessPath,
-                                 subprocess_path);
-#endif
-
-  // LinuxInputMethodContextFactory has to be initialized.
-#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(USE_X11)
-  ui::InitializeInputMethodForTesting();
-#endif
-
-  setup_called_ = true;
-
-  BrowserTestBase::SetUp();
-}
-
-void ContentBrowserTest::TearDown() {
-  BrowserTestBase::TearDown();
-
-  // LinuxInputMethodContextFactory has to be shutdown.
-#if !defined(OS_CHROMEOS) && defined(USE_AURA) && defined(USE_X11)
-  ui::ShutdownInputMethodForTesting();
-#endif
-
-#if defined(OS_ANDROID)
-  shell_main_delegate_.reset();
-#endif
-}
-
-void ContentBrowserTest::RunTestOnMainThreadLoop() {
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpRenderTree)) {
-    CHECK_EQ(Shell::windows().size(), 1u);
-    shell_ = Shell::windows()[0];
-  }
-
-#if defined(OS_MACOSX)
-  // On Mac, without the following autorelease pool, code which is directly
-  // executed (as opposed to executed inside a message loop) would autorelease
-  // objects into a higher-level pool. This pool is not recycled in-sync with
-  // the message loops' pools and causes problems with code relying on
-  // deallocation via an autorelease pool (such as browser window closure and
-  // browser shutdown). To avoid this, the following pool is recycled after each
-  // time code is directly executed.
-  base::mac::ScopedNSAutoreleasePool pool;
-#endif
-
-  // Pump startup related events.
-  base::MessageLoopForUI::current()->RunUntilIdle();
-
-#if defined(OS_MACOSX)
-  pool.Recycle();
-#endif
-
-  SetUpOnMainThread();
-
-  RunTestOnMainThread();
-
-  TearDownOnMainThread();
-#if defined(OS_MACOSX)
-  pool.Recycle();
-#endif
-
-  for (RenderProcessHost::iterator i(RenderProcessHost::AllHostsIterator());
-       !i.IsAtEnd(); i.Advance()) {
-    i.GetCurrentValue()->FastShutdownIfPossible();
-  }
-
-  Shell::CloseAllWindows();
-}
-
-Shell* ContentBrowserTest::CreateBrowser() {
-  return Shell::CreateNewWindow(
-      ShellContentBrowserClient::Get()->browser_context(),
-      GURL(kAboutBlankURL),
-      NULL,
-      MSG_ROUTING_NONE,
-      gfx::Size());
-}
-
-Shell* ContentBrowserTest::CreateOffTheRecordBrowser() {
-  return Shell::CreateNewWindow(
-      ShellContentBrowserClient::Get()->off_the_record_browser_context(),
-      GURL(kAboutBlankURL),
-      NULL,
-      MSG_ROUTING_NONE,
-      gfx::Size());
-}
-
-}  // namespace content
diff --git a/content/test/content_browser_test.h b/content/test/content_browser_test.h
deleted file mode 100644
index d59c296..0000000
--- a/content/test/content_browser_test.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_TEST_CONTENT_BROWSER_TEST_H_
-#define CONTENT_TEST_CONTENT_BROWSER_TEST_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/public/test/browser_test.h"
-#include "content/public/test/browser_test_base.h"
-
-class GURL;
-
-namespace content {
-class ContentRendererClient;
-class Shell;
-class ShellMainDelegate;
-
-class ContentBrowserTest : public BrowserTestBase {
- protected:
-  ContentBrowserTest();
-  virtual ~ContentBrowserTest();
-
-  // testing::Test:
-  virtual void SetUp() OVERRIDE;
-  virtual void TearDown() OVERRIDE;
-
-  // BrowserTestBase:
-  virtual void RunTestOnMainThreadLoop() OVERRIDE;
-
- protected:
-  // Creates a new window and loads about:blank.
-  Shell* CreateBrowser();
-
-  // Creates an off-the-record window and loads about:blank.
-  Shell* CreateOffTheRecordBrowser();
-
-  // Returns the window for the test.
-  Shell* shell() const { return shell_; }
-
- private:
-  Shell* shell_;
-
-  bool setup_called_;
-
-#if defined(OS_ANDROID)
-  // For all other platforms, this is done automatically when calling into
-  // ContentMain. For Android we set things up manually.
-  scoped_ptr<ShellMainDelegate> shell_main_delegate_;
-#endif
-};
-
-}  // namespace content
-
-#endif  // CONTENT_TEST_CONTENT_BROWSER_TEST_H_
diff --git a/content/test/content_browser_test_test.cc b/content/test/content_browser_test_test.cc
index 21b4543..1714f0b 100644
--- a/content/test/content_browser_test_test.cc
+++ b/content/test/content_browser_test_test.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/test/content_browser_test.h"
+#include "content/public/test/content_browser_test.h"
 
 #include "base/command_line.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace content {
diff --git a/content/test/content_browser_test_utils.cc b/content/test/content_browser_test_utils.cc
deleted file mode 100644
index 083f404..0000000
--- a/content/test/content_browser_test_utils.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/test/content_browser_test_utils.h"
-
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/run_loop.h"
-#include "content/public/browser/navigation_controller.h"
-#include "content/public/browser/notification_source.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/test/browser_test_utils.h"
-#include "content/public/test/test_navigation_observer.h"
-#include "content/public/test/test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/shell/browser/shell_javascript_dialog_manager.h"
-#include "net/base/net_util.h"
-
-namespace content {
-
-base::FilePath GetTestFilePath(const char* dir, const char* file) {
-  base::FilePath path;
-  PathService::Get(DIR_TEST_DATA, &path);
-  return path.Append(base::FilePath().AppendASCII(dir).Append(
-      base::FilePath().AppendASCII(file)));
-}
-
-GURL GetTestUrl(const char* dir, const char* file) {
-  return net::FilePathToFileURL(GetTestFilePath(dir, file));
-}
-
-void NavigateToURLBlockUntilNavigationsComplete(Shell* window,
-                                                const GURL& url,
-                                                int number_of_navigations) {
-  WaitForLoadStop(window->web_contents());
-  TestNavigationObserver same_tab_observer(window->web_contents(),
-                                           number_of_navigations);
-
-  window->LoadURL(url);
-  same_tab_observer.Wait();
-}
-
-void NavigateToURL(Shell* window, const GURL& url) {
-  NavigateToURLBlockUntilNavigationsComplete(window, url, 1);
-}
-
-void WaitForAppModalDialog(Shell* window) {
-  ShellJavaScriptDialogManager* dialog_manager=
-      static_cast<ShellJavaScriptDialogManager*>(
-          window->GetJavaScriptDialogManager());
-
-  scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
-  dialog_manager->set_dialog_request_callback(runner->QuitClosure());
-  runner->Run();
-}
-
-ShellAddedObserver::ShellAddedObserver()
-    : shell_(NULL) {
-  Shell::SetShellCreatedCallback(
-      base::Bind(&ShellAddedObserver::ShellCreated, base::Unretained(this)));
-}
-
-ShellAddedObserver::~ShellAddedObserver() {
-}
-
-Shell* ShellAddedObserver::GetShell() {
-  if (shell_)
-    return shell_;
-
-  runner_ = new MessageLoopRunner();
-  runner_->Run();
-  return shell_;
-}
-
-void ShellAddedObserver::ShellCreated(Shell* shell) {
-  DCHECK(!shell_);
-  shell_ = shell;
-  if (runner_.get())
-    runner_->QuitClosure().Run();
-}
-
-}  // namespace content
diff --git a/content/test/content_browser_test_utils.h b/content/test/content_browser_test_utils.h
deleted file mode 100644
index 09f44b8..0000000
--- a/content/test/content_browser_test_utils.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_H_
-#define CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_H_
-
-#include "base/memory/ref_counted.h"
-#include "ui/gfx/native_widget_types.h"
-#include "url/gurl.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace gfx {
-class Rect;
-}
-
-// A collections of functions designed for use with content_browsertests.
-// Note: if a function here also works with browser_tests, it should be in
-// content\public\test\browser_test_utils.h
-
-namespace content {
-
-class MessageLoopRunner;
-class Shell;
-
-// Generate the file path for testing a particular test.
-// The file for the tests is all located in
-// content/test/data/dir/<file>
-// The returned path is FilePath format.
-base::FilePath GetTestFilePath(const char* dir, const char* file);
-
-// Generate the URL for testing a particular test.
-// HTML for the tests is all located in
-// test_root_directory/dir/<file>
-// The returned path is GURL format.
-GURL GetTestUrl(const char* dir, const char* file);
-
-// Navigates the selected tab of |window| to |url|, blocking until the
-// navigation finishes.
-void NavigateToURL(Shell* window, const GURL& url);
-
-// Navigates the selected tab of |window| to |url|, blocking until the given
-// number of navigations finishes.
-void NavigateToURLBlockUntilNavigationsComplete(Shell* window,
-                                                const GURL& url,
-                                                int number_of_navigations);
-
-// Wait until an application modal dialog is requested.
-void WaitForAppModalDialog(Shell* window);
-
-// Used to wait for a new Shell window to be created. Instantiate this object
-// before the operation that will create the window.
-class ShellAddedObserver {
- public:
-  ShellAddedObserver();
-  ~ShellAddedObserver();
-
-  // Will run a message loop to wait for the new window if it hasn't been
-  // created since the constructor.
-  Shell* GetShell();
-
- private:
-  void ShellCreated(Shell* shell);
-
-  Shell* shell_;
-  scoped_refptr<MessageLoopRunner> runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(ShellAddedObserver);
-};
-
-#if defined OS_MACOSX
-void SetWindowBounds(gfx::NativeWindow window, const gfx::Rect& bounds);
-#endif
-
-}  // namespace content
-
-#endif  // CONTENT_TEST_CONTENT_BROWSER_TEST_UTILS_H_
diff --git a/content/test/content_browser_test_utils_mac.mm b/content/test/content_browser_test_utils_mac.mm
deleted file mode 100644
index d850890..0000000
--- a/content/test/content_browser_test_utils_mac.mm
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/test/content_browser_test_utils.h"
-
-#include <Carbon/Carbon.h>
-#import <Cocoa/Cocoa.h>
-
-#include "ui/gfx/rect.h"
-
-namespace content {
-
-void SetWindowBounds(gfx::NativeWindow window, const gfx::Rect& bounds) {
-  NSRect new_bounds = NSRectFromCGRect(bounds.ToCGRect());
-  if ([[NSScreen screens] count] > 0) {
-    new_bounds.origin.y =
-        [[[NSScreen screens] objectAtIndex:0] frame].size.height -
-        new_bounds.origin.y - new_bounds.size.height;
-  }
-
-  [window setFrame:new_bounds display:NO];
-}
-
-}  // namespace content
diff --git a/content/test/data/accessibility/aria-combobox-expected-mac.txt b/content/test/data/accessibility/aria-combobox-expected-mac.txt
index 6fc5996..151caf4 100644
--- a/content/test/data/accessibility/aria-combobox-expected-mac.txt
+++ b/content/test/data/accessibility/aria-combobox-expected-mac.txt
@@ -1,7 +1,8 @@
 AXWebArea
     AXGroup
         AXStaticText AXValue='State'
-        AXComboBox
+    AXGroup
+        AXComboBox AXTitleUIElement='AXGroup group' AXLinkedUIElements=["AXList"]
     AXList
         AXStaticText AXTitle='Alabama'
-        AXStaticText AXTitle='Alaska'
+        AXStaticText AXTitle='Alaska' AXFocused='1'
diff --git a/content/test/data/accessibility/aria-combobox.html b/content/test/data/accessibility/aria-combobox.html
index f93bfb2..b4da1b7 100644
--- a/content/test/data/accessibility/aria-combobox.html
+++ b/content/test/data/accessibility/aria-combobox.html
@@ -1,19 +1,23 @@
 <!--
 @WIN-DENY:description*
+@MAC-ALLOW:AXFocused='1'
+@MAC-ALLOW:AXLinkedUIElements*
+@MAC-ALLOW:AXTitleUIElement*
 -->
 <html>
   <body>
-    <span id="state_label">State</span>
+    <div id="state_label">State</div>
     <input type="text"
-        role="combobox" 
+        role="combobox"
         aria-labelledby="state_label"
         aria-autocomplete="list"
-        aria-owns="state_list" 
-        aria-readonly="true" 
-        aria-activedescendant="state2"/> 
+        aria-owns="state_list"
+        aria-readonly="true"
+        aria-activedescendant="state2"
+        autofocus="true"/>
     <ul id="state_list" role="listbox" aria-expanded="true">
-      <li id="state1" role="option" tabindex="-1">Alabama</li> 
-      <li id="state2" role="option" tabindex="-1">Alaska</li> 
+      <li id="state1" role="option" tabindex="-1">Alabama</li>
+      <li id="state2" role="option" tabindex="-1">Alaska</li>
     </ul>
   </body>
 </html>
diff --git a/content/test/data/accessibility/aria-flowto-expected-android.txt b/content/test/data/accessibility/aria-flowto-expected-android.txt
new file mode 100644
index 0000000..8620d59
--- /dev/null
+++ b/content/test/data/accessibility/aria-flowto-expected-android.txt
@@ -0,0 +1 @@
+#<skip - need to generate expectation>
diff --git a/content/test/data/accessibility/aria-flowto-expected-mac.txt b/content/test/data/accessibility/aria-flowto-expected-mac.txt
new file mode 100644
index 0000000..1ab9ab2
--- /dev/null
+++ b/content/test/data/accessibility/aria-flowto-expected-mac.txt
@@ -0,0 +1,5 @@
+AXWebArea AXRoleDescription='HTML content'
+    AXGroup AXRoleDescription='group' AXLinkedUIElements=["AXGroup footer"]
+        AXStaticText AXRoleDescription='text' AXValue='Lorem ipsum'
+    AXGroup AXRoleDescription='footer'
+        AXStaticText AXRoleDescription='text' AXValue='dolor sit amet'
diff --git a/content/test/data/accessibility/aria-flowto-expected-win.txt b/content/test/data/accessibility/aria-flowto-expected-win.txt
new file mode 100644
index 0000000..8620d59
--- /dev/null
+++ b/content/test/data/accessibility/aria-flowto-expected-win.txt
@@ -0,0 +1 @@
+#<skip - need to generate expectation>
diff --git a/content/test/data/accessibility/aria-flowto.html b/content/test/data/accessibility/aria-flowto.html
new file mode 100644
index 0000000..53ab196
--- /dev/null
+++ b/content/test/data/accessibility/aria-flowto.html
@@ -0,0 +1,10 @@
+<!--
+@MAC-ALLOW:AXLinkedUIElements*
+@MAC-ALLOW:AXRoleDescription*
+-->
+<html>
+  <body>
+    <section aria-flowto="next">Lorem ipsum</section>
+    <footer id="next">dolor sit amet</footer>
+  </body>
+</html>
diff --git a/content/test/data/accessibility/aria-menu-expected-mac.txt b/content/test/data/accessibility/aria-menu-expected-mac.txt
index 570809e..7c1715a 100644
--- a/content/test/data/accessibility/aria-menu-expected-mac.txt
+++ b/content/test/data/accessibility/aria-menu-expected-mac.txt
@@ -1,6 +1,6 @@
 AXWebArea
     AXMenuBar
-        AXMenuItem AXTitle='File'
+        AXMenuItem AXTitle='File' AXLinkedUIElements=["AXMenu"]
         AXMenuItem AXTitle='Edit'
         AXMenuItem AXTitle='View'
     AXMenu AXDescription='File'
diff --git a/content/test/data/accessibility/aria-menu.html b/content/test/data/accessibility/aria-menu.html
index 1fd7ebb..2211f94 100644
--- a/content/test/data/accessibility/aria-menu.html
+++ b/content/test/data/accessibility/aria-menu.html
@@ -1,16 +1,18 @@
 <!--
 @MAC-ALLOW:AXDescription='File'
 @MAC-DENY:AXValue*
+@MAC-ALLOW:AXLinkedUIElements*
 @WIN-DENY:description=''
 -->
 <html>
   <body>
     <ul role="menubar" style="list-style-type: none">
-      <li role="menuitem">File</span>
+      <li role="menuitem" aria-controls="filemenu">File</span>
       <li role="menuitem">Edit</span>
       <li role="menuitem">View</span>
     </ul>
-    <ul role="menu" aria-label="File" style="list-style-type: none">
+    <ul id="filemenu" role="menu" aria-label="File"
+        style="list-style-type: none">
       <li role="menuitem">New</span>
       <li role="menuitem">Open</span>
       <li role="menuitem">Save</span>
diff --git a/content/test/data/media/getusermedia.html b/content/test/data/media/getusermedia.html
index 76ae768..7da1175 100644
--- a/content/test/data/media/getusermedia.html
+++ b/content/test/data/media/getusermedia.html
@@ -133,6 +133,13 @@
         failedCallback);
   }
 
+  function getUserMediaAndRenderInSeveralVideoTags() {
+    navigator.webkitGetUserMedia(
+        {video: true},
+        createMultipleVideoRenderersAndPause,
+        function(error) { failedCallback(); });
+  }
+
   // Gets a video stream up, analyses it and returns the aspect ratio to the
   // test through the automation controller.
   function getUserMediaAndAnalyseAndStop(constraints) {
@@ -239,30 +246,82 @@
     });
   }
 
+  // This test make sure multiple video renderers can be created for the same
+  // local video track and make sure a renderer can still render if other
+  // renderers are paused. See http://crbug/352619.
+  function createMultipleVideoRenderersAndPause(stream) {
+    function createDetectableRenderer(stream, id) {
+      var video = document.createElement('video');
+      document.body.appendChild(video);
+      var localStreamUrl = URL.createObjectURL(stream);
+      video.id = id;
+      video.src = localStreamUrl;
+      video.autoplay = true;
+      video.play();
+      // The detector needs a canvas.
+      var canvas = document.createElement('canvas');
+      canvas.id = video.id + "-canvas";
+      document.body.appendChild(canvas);
+    };
+
+    // Once 3 renderers are created and paused, create one last renderer and
+    // make sure it can play video.
+    setAllEventsOccuredHandler(function() {
+      var id = "lastVideoTag";
+      createDetectableRenderer(stream, id);
+      detectVideoPlaying(id, function () { reportTestSuccess(); });
+    });
+
+    // Create 3 video renderers and pause them once video is playing.
+    for (var i = 0; i < 3; ++i) {
+      var id = "video" + i;
+      createDetectableRenderer(stream, id);
+      addExpectedEvent();
+      // |video_detected_function| creates a new function that pause the video
+      // tag |id|.
+      var video_detected_function =
+          function (j) {
+            return function () {
+              console.log("pause " + j);
+              $(j).pause();
+              eventOccured();
+           };
+          };
+      // Detect video id |id| and trigger the function returned by
+      // |video_detected_function| when video is playing.
+      detectVideoPlaying(id, video_detected_function(id));
+     }
+   }
+
   // This function tries to calculate the aspect ratio shown by the fake capture
   // device in the video tag. For this, we count the amount of light green
   // pixels along |aperture| pixels on the positive X and Y axis starting from
   // the center of the image. In this very center there should be a time-varying
   // pacman; the algorithm counts for a couple of iterations and keeps the
   // maximum amount of light green pixels on both directions. From this data
-  // the aspect ratio is calculated relative to a 320x240 window, so 4:3 would
-  // show as a 1. Furthermore, since an original non-4:3 might be letterboxed or
-  // cropped, the actual X and Y pixel amounts are compared with the fake video
-  // capture expected pacman radius (see further below).
+  // the aspect ratio is calculated and the test fails if the number of green
+  // pixels are not the same along the X and Y axis.
+  // The result of the analysis is sent back to the test as a string on the
+  // format "w=xxx:h=yyy".
   function detectAspectRatio(callback) {
-    var width = VIDEO_TAG_WIDTH;
-    var height = VIDEO_TAG_HEIGHT;
     var videoElement = $('local-view');
     var canvas = $('local-view-canvas');
 
     var maxLightGreenPixelsX = 0;
     var maxLightGreenPixelsY = 0;
 
-    var aperture = Math.min(width, height) / 2;
     var iterations = 0;
     var maxIterations = 10;
 
     var detectorFunction = function() {
+      var width = videoElement.videoWidth;
+      var height = videoElement.videoHeight;
+      if (width == 0 || height == 0)
+        return;
+
+      canvas.width = width;
+      canvas.height = height;
+      var aperture = Math.min(width, height) / 2;
       var context = canvas.getContext('2d');
       context.drawImage(videoElement, 0, 0, width, height);
 
@@ -281,50 +340,32 @@
       }
       // Walk vertically counting light green pixels.
       for (var y = 0; y < aperture; ++y) {
-        if (pixels.data[4 * y * aperture + 1] != 135)
+        if (pixels.data[4 * y * aperture + 1] != COLOR_BACKGROUND_GREEN)
           lightGreenPixelsY++;
       }
-      if (lightGreenPixelsX > maxLightGreenPixelsX &&
-          lightGreenPixelsX < aperture)
+      if (lightGreenPixelsX > maxLightGreenPixelsX)
         maxLightGreenPixelsX = lightGreenPixelsX;
-      if (lightGreenPixelsY > maxLightGreenPixelsY &&
-          lightGreenPixelsY < aperture)
+      if (lightGreenPixelsY > maxLightGreenPixelsY)
         maxLightGreenPixelsY = lightGreenPixelsY;
 
-      var detectedAspectRatioString = "";
       if (++iterations > maxIterations) {
-        clearInterval(detectorFunction);
-        observedAspectRatio = maxLightGreenPixelsY / maxLightGreenPixelsX;
-        // At this point the observed aspect ratio is either 1, for undistorted
-        // 4:3, or some other aspect ratio that is seen as distorted.
-        if (Math.abs(observedAspectRatio - 1.333) < 0.1)
-          detectedAspectRatioString = "16:9";
-        else if (Math.abs(observedAspectRatio - 1.20) < 0.1)
-          detectedAspectRatioString = "16:10";
-        else if (Math.abs(observedAspectRatio - 1.0) < 0.1)
-          detectedAspectRatioString = "4:3";
-        else
-          detectedAspectRatioString = "UNKNOWN aspect ratio";
-        console.log(detectedAspectRatioString + " observed aspect ratio (" +
-                    observedAspectRatio + ")");
+        clearInterval(detectorInterval);
+        // Allow maxLightGreenPixelsY = maxLightGreenPixelsX +-1 due to 
+        // possible subpixel rendering on Mac and Android.
+        if (maxLightGreenPixelsY > maxLightGreenPixelsX + 1 ||
+            maxLightGreenPixelsY < maxLightGreenPixelsX -1 ||
+            maxLightGreenPixelsY == 0 ||
+            maxLightGreenPixelsX == width || maxLightGreenPixelsY == height) {
+          failTest("Aspect ratio corrupted. X " + maxLightGreenPixelsX  +
+            " Y " + maxLightGreenPixelsY);
+        }
 
-        // The FakeVideoCapture calculates the circle radius as
-        // std::min(capture_format_.width, capture_format_.height) / 4;
-        // we do the same and see if both dimensions are scaled, meaning
-        // we started from a cropped or stretched image.
-        var nonDistortedRadius = Math.min(width, height) / 4;
-        if ((maxLightGreenPixelsX != nonDistortedRadius) &&
-            (maxLightGreenPixelsY != nonDistortedRadius)) {
-          detectedAspectRatioString += " cropped";
-        } else
-          detectedAspectRatioString += " letterbox";
-
-        console.log("Original image is: " + detectedAspectRatioString);
-        callback(detectedAspectRatioString);
+        var result = "w=" + width + ":h=" + height;
+        console.log(result);
+        callback(result);
       }
     }
-
-    setInterval(detectorFunction, 50);
+    var detectorInterval = setInterval(detectorFunction, 50);
   }
   </script>
 </head>
@@ -336,7 +377,7 @@
     <tr>
       <td><video width="320" height="240" id="local-view"
           autoplay="autoplay"></video></td>
-      <td><canvas width="320" height="240" id="local-view-canvas"
+      <td><canvas id="local-view-canvas"
           style="display:none"></canvas></td>
     </tr>
     <tr>
diff --git a/content/test/data/media/peerconnection-call.html b/content/test/data/media/peerconnection-call.html
index b4aa947..2327647 100644
--- a/content/test/data/media/peerconnection-call.html
+++ b/content/test/data/media/peerconnection-call.html
@@ -63,6 +63,23 @@
     waitForVideo('remote-view-2');
   }
 
+  // Test that we can setup call with an audio and video track and check that 
+  // the video resolution is as expected.
+  function callAndExpectResolution(constraints,
+                                   expected_width,
+                                   expected_height) {
+    createConnections(null);
+    navigator.webkitGetUserMedia(constraints,
+      addStreamToBothConnectionsAndNegotiate, printGetUserMediaError);
+    waitForVideoWithResolution('remote-view-1',
+                               expected_width,
+                               expected_height);
+    waitForVideoWithResolution('remote-view-2',
+                               expected_width,
+                               expected_height);
+  }
+
+
   // First calls without streams on any connections, and then adds a stream
   // to peer connection 1 which gets sent to peer connection 2. We must wait
   // for the first negotiation to complete before starting the second one, which
@@ -304,7 +321,7 @@
     detectVideoPlaying('remote-view-2', onCallEstablished);
   }
 
-  function callAndEnsureAudioMutingWorks() {
+  function callAndEnsureAudioTrackMutingWorks() {
     callAndEnsureAudioIsPlaying();
     setAllEventsOccuredHandler(function() {
       // Call is up, now mute the track and check everything goes silent (give
@@ -320,7 +337,26 @@
     });
   }
 
-  function callAndEnsureVideoMutingWorks() {
+  function callAndEnsureAudioTrackUnmutingWorks() {
+    callAndEnsureAudioIsPlaying();
+    setAllEventsOccuredHandler(function() {
+      // Mute, wait a while, unmute, verify audio gets back up.
+      enableRemoteAudio(gSecondConnection, false);
+
+      setTimeout(function() {
+        enableRemoteAudio(gSecondConnection, true);
+      }, 500);
+
+      setTimeout(function() {
+        gatherAudioLevelSamples(gSecondConnection, 200, 100, function(samples) {
+          verifyAudioIsPlaying(samples);
+          reportTestSuccess();
+        });
+      }, 1000);
+    });
+  }
+
+  function callAndEnsureVideoTrackMutingWorks() {
     createConnections(null);
     navigator.webkitGetUserMedia({audio: true, video: true},
       addStreamToBothConnectionsAndNegotiate, printGetUserMediaError);
@@ -775,7 +811,6 @@
 
   function onIceCandidate(event, target) {
     if (event.candidate) {
-      console.log("onIceCandidate, candidate is:" + event.candidate.candidate);
       var candidate = new RTCIceCandidate(event.candidate);
       candidate.candidate = transformCandidate(candidate.candidate);
       target.addIceCandidate(candidate);
diff --git a/content/test/data/media/webrtc_test_audio.js b/content/test/data/media/webrtc_test_audio.js
index 1f5b6ec..40668c6 100644
--- a/content/test/data/media/webrtc_test_audio.js
+++ b/content/test/data/media/webrtc_test_audio.js
@@ -40,10 +40,10 @@
   // to see a number of peaks with relative silence between them. The following
   // seems to work fine on a nexus 7.
   if (average < 3000 || average > 8000)
-    throw 'Unexpected avg audio level: got ' + average + ', expected it ' +
-          'to be 4000 < avg < 8000.'
+    failTest('Unexpected avg audio level: got ' + average + ', expected it ' +
+             'to be 4000 < avg < 8000.');
   if (largest < 25000)
-    throw 'Too low max audio level: got ' + largest + ', expected > 30000.';
+    failTest('Too low max audio level: got ' + largest + ', expected > 30000.');
 }
 
 // If silent (like when muted), we should get very near zero audio level.
@@ -53,8 +53,8 @@
     average += samples[i] / samples.length;
 
   console.log('Average audio level: ' + average);
-  if (average > 10)
-    throw 'Expected silence, but avg audio level was ' + average;
+  if (average > 500)
+    failTest('Expected silence, but avg audio level was ' + average);
 }
 
 /**
diff --git a/content/test/data/media/webrtc_test_utilities.js b/content/test/data/media/webrtc_test_utilities.js
index c56953f..644a812 100644
--- a/content/test/data/media/webrtc_test_utilities.js
+++ b/content/test/data/media/webrtc_test_utilities.js
@@ -72,12 +72,22 @@
         predicate(pixels, oldPixels)) {
       console.log('Done looking at video in element ' + videoElementName);
       clearInterval(waitVideo);
-      callback();
+      callback(videoElement.videoWidth, videoElement.videoHeight);
     }
     oldPixels = pixels;
   }, 200);
 }
 
+function waitForVideoWithResolution(element, expected_width, expected_height) {
+  addExpectedEvent();
+  detectVideoPlaying(element,
+      function (width, height) {
+        assertEquals(expected_width, width);
+        assertEquals(expected_height, height);
+        eventOccured();
+      });
+}
+
 function waitForVideo(videoElement) {
   addExpectedEvent();
   detectVideoPlaying(videoElement, function () { eventOccured(); });
diff --git a/content/test/data/push_state.html b/content/test/data/push_state.html
new file mode 100644
index 0000000..22178ee
--- /dev/null
+++ b/content/test/data/push_state.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+<script>
+window.onload = function() {
+  setTimeout(function() {
+    history.pushState("", "", "#pushState");
+    document.title = "pushState";
+  }, 0);
+}
+</script>
+</head>
+</html>
diff --git a/content/test/data/web_ui_mojo.html b/content/test/data/web_ui_mojo.html
new file mode 100644
index 0000000..54a5027
--- /dev/null
+++ b/content/test/data/web_ui_mojo.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+  <script src="web_ui_mojo.js"></script>
+</head>
+<body>
+  x
+</body>
+</html>
diff --git a/content/test/data/web_ui_mojo.js b/content/test/data/web_ui_mojo.js
new file mode 100644
index 0000000..31791cb
--- /dev/null
+++ b/content/test/data/web_ui_mojo.js
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define('main', [
+    'mojo/public/bindings/js/connection',
+    'content/test/data/web_ui_test_mojo_bindings.mojom',
+], function(connection, bindings) {
+
+  function RendererTargetTest(bindings) {
+    this.bindings_ = bindings;
+  }
+
+  // TODO(aa): It is a bummer to need this stub object in JavaScript. We should
+  // have a 'client' object that contains both the sending and receiving bits of
+  // the client side of the interface. Since JS is loosely typed, we do not need
+  // a separate base class to inherit from to receive callbacks.
+  RendererTargetTest.prototype =
+      Object.create(bindings.RendererTargetStub.prototype);
+
+  RendererTargetTest.prototype.test = function() {
+    this.bindings_.test();
+  };
+
+  var retainedConnection;
+
+  return function(handle) {
+    retainedConnection = new connection.Connection(handle, RendererTargetTest,
+                                                   bindings.BrowserTargetProxy);
+  };
+});
diff --git a/content/test/data/web_ui_test_mojo_bindings.mojom b/content/test/data/web_ui_test_mojo_bindings.mojom
new file mode 100644
index 0000000..3fa0259
--- /dev/null
+++ b/content/test/data/web_ui_test_mojo_bindings.mojom
@@ -0,0 +1,13 @@
+module mojo {
+
+[Peer=RendererTarget]
+interface BrowserTarget {
+  Test();
+};
+
+[Peer=BrowserTarget]
+interface RendererTarget {
+  Test();
+};
+
+}
diff --git a/content/test/gpu/gpu_tests/pixel.py b/content/test/gpu/gpu_tests/pixel.py
index 46ba353..fbbb063 100644
--- a/content/test/gpu/gpu_tests/pixel.py
+++ b/content/test/gpu/gpu_tests/pixel.py
@@ -8,6 +8,7 @@
 import re
 
 import cloud_storage_test_base
+import pixel_expectations
 
 from telemetry import test
 from telemetry.core import bitmap
@@ -149,3 +150,6 @@
     for page in page_set.pages:
       page.script_to_evaluate_on_commit = test_harness_script
     return page_set
+
+  def CreateExpectations(self, page_set):
+    return pixel_expectations.PixelExpectations()
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
new file mode 100644
index 0000000..1d9594a
--- /dev/null
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -0,0 +1,27 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page import test_expectations
+
+# Valid expectation conditions are:
+#
+# Operating systems:
+#     win, xp, vista, win7, mac, leopard, snowleopard, lion, mountainlion,
+#     linux, chromeos, android
+#
+# GPU vendors:
+#     amd, arm, broadcom, hisilicon, intel, imagination, nvidia, qualcomm,
+#     vivante
+#
+# Specific GPUs can be listed as a tuple with vendor name and device ID.
+# Examples: ('nvidia', 0x1234), ('arm', 'Mali-T604')
+# Device IDs must be paired with a GPU vendor.
+
+class PixelExpectations(test_expectations.TestExpectations):
+  def SetExpectations(self):
+    # Sample Usage:
+    # self.Fail('Pixel.Canvas2DRedBox',
+    #     ['mac', 'amd', ('nvidia', 0x1234)], bug=123)
+
+    pass
diff --git a/content/test/gpu/page_sets/pixel_tests.json b/content/test/gpu/page_sets/pixel_tests.json
index 82ba9c4..0776fd7 100644
--- a/content/test/gpu/page_sets/pixel_tests.json
+++ b/content/test/gpu/page_sets/pixel_tests.json
@@ -41,7 +41,7 @@
             "timeout": 30
         }
       ],
-      "revision": 2,
+      "revision": 4,
       "test_rect": [0, 0, 400, 300]
     }
   ]
diff --git a/content/test/image_decoder_test.cc b/content/test/image_decoder_test.cc
index 7d89e18..581c6f3 100644
--- a/content/test/image_decoder_test.cc
+++ b/content/test/image_decoder_test.cc
@@ -17,7 +17,8 @@
 #include "third_party/WebKit/public/platform/WebSize.h"
 #include "third_party/WebKit/public/web/WebImageDecoder.h"
 
-using base::Time;
+// Uncomment this to recalculate the MD5 sums; see header comments.
+// #define CALCULATE_MD5_SUMS
 
 namespace {
 
@@ -42,7 +43,7 @@
   std::string raw_image_data;
   base::ReadFileToString(path, &raw_image_data);
   contents->resize(raw_image_data.size());
-  memcpy(&contents->at(0), raw_image_data.data(), raw_image_data.size());
+  memcpy(&contents->front(), raw_image_data.data(), raw_image_data.size());
 }
 
 base::FilePath GetMD5SumPath(const base::FilePath& path) {
@@ -57,13 +58,13 @@
   base::MD5Digest digest;
   web_image.getSkBitmap().lockPixels();
   base::MD5Sum(web_image.getSkBitmap().getPixels(),
-         web_image.getSkBitmap().width() * web_image.getSkBitmap().height() *
-         sizeof(uint32_t),
-         &digest);
+               web_image.getSkBitmap().width() *
+                   web_image.getSkBitmap().height() * sizeof(uint32_t),
+               &digest);
 
   // Write sum to disk.
-  int bytes_written = base::WriteFile(path,
-      reinterpret_cast<const char*>(&digest), sizeof digest);
+  int bytes_written = base::WriteFile(
+      path, reinterpret_cast<const char*>(&digest), sizeof digest);
   ASSERT_EQ(sizeof digest, bytes_written);
   web_image.getSkBitmap().unlockPixels();
 }
@@ -85,9 +86,9 @@
   blink::WebImage web_image = decoder.getFrameAtIndex(frame_index);
   web_image.getSkBitmap().lockPixels();
   base::MD5Sum(web_image.getSkBitmap().getPixels(),
-         web_image.getSkBitmap().width() * web_image.getSkBitmap().height() *
-         sizeof(uint32_t),
-         &actual_digest);
+               web_image.getSkBitmap().width() *
+                   web_image.getSkBitmap().height() * sizeof(uint32_t),
+               &actual_digest);
 
   // Read the MD5 sum off disk.
   std::string file_bytes;
@@ -97,9 +98,8 @@
   memcpy(&expected_digest, file_bytes.data(), sizeof expected_digest);
 
   // Verify that the sums are the same.
-  EXPECT_EQ(0,
-            memcmp(&expected_digest, &actual_digest, sizeof(base::MD5Digest)))
-    << path.value();
+  EXPECT_EQ(0, memcmp(&expected_digest, &actual_digest, sizeof actual_digest))
+      << path.value();
   web_image.getSkBitmap().unlockPixels();
 }
 #endif
@@ -107,14 +107,13 @@
 void ImageDecoderTest::SetUp() {
   base::FilePath data_dir;
   ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir));
-  data_dir_ = data_dir.AppendASCII("webkit").
-                       AppendASCII("data").
-                       AppendASCII(format_ + "_decoder");
+  data_dir_ = data_dir.AppendASCII("webkit").AppendASCII("data").AppendASCII(
+      format_ + "_decoder");
   if (!base::PathExists(data_dir_)) {
     const testing::TestInfo* const test_info =
         testing::UnitTest::GetInstance()->current_test_info();
-    VLOG(0) << test_info->name() <<
-                 " not running because test data wasn't found.";
+    VLOG(0) << test_info->name()
+            << " not running because test data wasn't found.";
     data_dir_.clear();
     return;
   }
@@ -122,23 +121,19 @@
 
 std::vector<base::FilePath> ImageDecoderTest::GetImageFiles() const {
   std::string pattern = "*." + format_;
-
-  base::FileEnumerator enumerator(data_dir_,
-                                  false,
+  base::FileEnumerator enumerator(data_dir_, false,
                                   base::FileEnumerator::FILES);
-
   std::vector<base::FilePath> image_files;
-  base::FilePath next_file_name;
-  while (!(next_file_name = enumerator.Next()).empty()) {
+  for (base::FilePath next_file_name = enumerator.Next();
+       !next_file_name.empty(); next_file_name = enumerator.Next()) {
     base::FilePath base_name = next_file_name.BaseName();
 #if defined(OS_WIN)
     std::string base_name_ascii = base::UTF16ToASCII(base_name.value());
 #else
     std::string base_name_ascii = base_name.value();
 #endif
-    if (!MatchPattern(base_name_ascii, pattern))
-      continue;
-    image_files.push_back(next_file_name);
+    if (MatchPattern(base_name_ascii, pattern))
+      image_files.push_back(next_file_name);
   }
 
   return image_files;
@@ -160,21 +155,19 @@
   const std::vector<base::FilePath> image_files(GetImageFiles());
   for (std::vector<base::FilePath>::const_iterator i = image_files.begin();
        i != image_files.end(); ++i) {
-    if (ShouldSkipFile(*i, file_selection, threshold))
-      continue;
-    const base::FilePath md5_sum_path(GetMD5SumPath(*i));
-    TestWebKitImageDecoder(*i, md5_sum_path, kFirstFrameIndex);
+    if (!ShouldSkipFile(*i, file_selection, threshold))
+      TestWebKitImageDecoder(*i, GetMD5SumPath(*i), kFirstFrameIndex);
   }
 }
 
-void  ImageDecoderTest::TestWebKitImageDecoder(const base::FilePath& image_path,
-  const base::FilePath& md5_sum_path, int desired_frame_index) const {
-  bool should_test_chunking = true;
-  bool should_test_failed_images = true;
-#ifdef CALCULATE_MD5_SUMS
-    // Do not test anything just get the md5 sums.
-    should_test_chunking = false;
-    should_test_failed_images = false;
+void ImageDecoderTest::TestWebKitImageDecoder(
+    const base::FilePath& image_path,
+    const base::FilePath& md5_sum_path,
+    int desired_frame_index) const {
+#if defined(CALCULATE_MD5_SUMS)
+  // If we're just calculating the MD5 sums, skip failing images quickly.
+  if (ShouldImageFail(image_path))
+    return;
 #endif
 
   std::vector<char> image_contents;
@@ -183,45 +176,35 @@
   scoped_ptr<blink::WebImageDecoder> decoder(CreateWebKitImageDecoder());
   EXPECT_FALSE(decoder->isFailed());
 
-  if (should_test_chunking) {
-    // Test chunking file into half.
-    const int partial_size = image_contents.size()/2;
+#if !defined(CALCULATE_MD5_SUMS)
+  // Test chunking file into half.
+  const int partial_size = image_contents.size()/2;
 
-    blink::WebData partial_data(
-      reinterpret_cast<const char*>(&(image_contents.at(0))), partial_size);
+  blink::WebData partial_data(
+    reinterpret_cast<const char*>(&(image_contents.at(0))), partial_size);
 
-    // Make Sure the image decoder doesn't fail when we ask for the frame
-    // buffer for this partial image.
-    // NOTE: We can't check that frame 0 is non-NULL, because if this is an
-    // ICO and we haven't yet supplied enough data to read the directory,
-    // there is no framecount and thus no first frame.
-    decoder->setData(const_cast<blink::WebData&>(partial_data), false);
-    EXPECT_FALSE(decoder->isFailed()) << image_path.value();
-  }
+  // Make Sure the image decoder doesn't fail when we ask for the frame
+  // buffer for this partial image.
+  // NOTE: We can't check that frame 0 is non-NULL, because if this is an
+  // ICO and we haven't yet supplied enough data to read the directory,
+  // there is no framecount and thus no first frame.
+  decoder->setData(const_cast<blink::WebData&>(partial_data), false);
+  EXPECT_FALSE(decoder->isFailed()) << image_path.value();
+#endif
 
   // Make sure passing the complete image results in successful decoding.
   blink::WebData data(reinterpret_cast<const char*>(&(image_contents.at(0))),
     image_contents.size());
   decoder->setData(const_cast<blink::WebData&>(data), true);
-
-  if (should_test_failed_images) {
-    if (ShouldImageFail(image_path)) {
-      EXPECT_FALSE(decoder->isFrameCompleteAtIndex(kFirstFrameIndex));
-      EXPECT_TRUE(decoder->isFailed());
-         return;
-    }
-  }
-
-  EXPECT_FALSE(decoder->isFailed()) << image_path.value();
-
-#ifdef CALCULATE_MD5_SUMS
-  // Since WebImage does not expose get data by frame, get the size
-  // through decoder and pass it to fromData so that the closest
-  // image dats to the size is returned.
-  blink::WebSize size(decoder->getImage(desired_frame_index).size());
-  const blink::WebImage& image = blink::WebImage::fromData(data, size);
-  SaveMD5Sum(md5_sum_path, image);
+  if (ShouldImageFail(image_path)) {
+    EXPECT_FALSE(decoder->isFrameCompleteAtIndex(kFirstFrameIndex));
+    EXPECT_TRUE(decoder->isFailed());
+  } else {
+    EXPECT_FALSE(decoder->isFailed()) << image_path.value();
+#if defined(CALCULATE_MD5_SUMS)
+    SaveMD5Sum(md5_sum_path, decoder->getFrameAtIndex(desired_frame_index));
 #else
-  VerifyImage(*decoder, image_path, md5_sum_path, desired_frame_index);
+    VerifyImage(*decoder, image_path, md5_sum_path, desired_frame_index);
 #endif
+  }
 }
diff --git a/content/test/image_decoder_test.h b/content/test/image_decoder_test.h
index 5983e7a..379cf4e 100644
--- a/content/test/image_decoder_test.h
+++ b/content/test/image_decoder_test.h
@@ -16,10 +16,9 @@
 
 namespace blink { class WebImageDecoder; }
 
-// If CALCULATE_MD5_SUMS is not defined, then this test decodes a handful of
-// image files and compares their MD5 sums to the stored sums on disk.
-//
-// To recalculate the MD5 sums, uncommment CALCULATE_MD5_SUMS.
+// Decodes a handful of image files and compares their MD5 sums to the stored
+// sums on disk.  To recalculate the MD5 sums, uncomment the CALCULATE_MD5_SUMS
+// #define in the .cc file.
 //
 // The image files and corresponding MD5 sums live in the directory
 // chrome/test/data/*_decoder (where "*" is the format being tested).
@@ -28,8 +27,6 @@
 // will differ, since no endianness correction is done.  If we start compiling
 // for big endian machines this should be fixed.
 
-// #define CALCULATE_MD5_SUMS
-
 enum ImageDecoderTestFileSelection {
   TEST_ALL,
   TEST_SMALLER,
@@ -54,9 +51,10 @@
 
   // Tests if decoder decodes image at image_path with underlying frame at
   // index desired_frame_index. The md5_sum_path is needed if the test is not
-  // asked to generate one i.e. if # #define CALCULATE_MD5_SUMS is set.
+  // asked to generate one, i.e. if #define CALCULATE_MD5_SUMS is not set.
   void TestWebKitImageDecoder(const base::FilePath& image_path,
-    const base::FilePath& md5_sum_path, int desired_frame_index) const;
+                              const base::FilePath& md5_sum_path,
+                              int desired_frame_index) const;
 
   // Verifies each of the test image files is decoded correctly and matches the
   // expected state. |file_selection| and |threshold| can be used to select
@@ -76,10 +74,12 @@
   std::string format_;
 
  protected:
+  const base::FilePath& data_dir() const { return data_dir_; }
+
+ private:
   // Path to the test files.
   base::FilePath data_dir_;
 
- private:
   DISALLOW_COPY_AND_ASSIGN(ImageDecoderTest);
 };
 
diff --git a/content/test/layouttest_support.cc b/content/test/layouttest_support.cc
index 9734a22..9d27ced 100644
--- a/content/test/layouttest_support.cc
+++ b/content/test/layouttest_support.cc
@@ -24,6 +24,7 @@
 
 using blink::WebDeviceMotionData;
 using blink::WebDeviceOrientationData;
+using blink::WebGamepad;
 using blink::WebGamepads;
 using blink::WebRect;
 using blink::WebSize;
@@ -82,6 +83,14 @@
   RendererWebKitPlatformSupportImpl::SetMockGamepadsForTesting(pads);
 }
 
+void MockGamepadConnected(int index, const WebGamepad& pad) {
+  RendererWebKitPlatformSupportImpl::MockGamepadConnected(index, pad);
+}
+
+void MockGamepadDisconnected(int index, const WebGamepad& pad) {
+  RendererWebKitPlatformSupportImpl::MockGamepadDisconnected(index, pad);
+}
+
 void SetMockDeviceMotionData(const WebDeviceMotionData& data) {
   RendererWebKitPlatformSupportImpl::SetMockDeviceMotionDataForTesting(data);
 }
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc
index 3e77c7f..305fc73 100644
--- a/content/test/test_render_frame_host.cc
+++ b/content/test/test_render_frame_host.cc
@@ -56,7 +56,7 @@
   // DidStartProvisionalLoad may delete the pending entry that holds |url|,
   // so we keep a copy of it to use in SendNavigateWithParameters.
   GURL url_copy(url);
-  OnDidStartProvisionalLoadForFrame(-1, true, url_copy);
+  OnDidStartProvisionalLoadForFrame(-1, url_copy);
   SendNavigateWithParameters(
       page_id, url_copy, transition, url_copy, response_code, 0);
 }
@@ -65,7 +65,7 @@
     int page_id,
     const GURL& url,
     const GURL& original_request_url) {
-  OnDidStartProvisionalLoadForFrame(-1, true, url);
+  OnDidStartProvisionalLoadForFrame(-1, url);
   SendNavigateWithParameters(
       page_id, url, PAGE_TRANSITION_LINK, original_request_url, 200, 0);
 }
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 260e209..55cab77 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -129,7 +129,7 @@
 }
 
 void TestWebContents::TestSetIsLoading(bool value) {
-  SetIsLoading(GetRenderViewHost(), value, NULL);
+  SetIsLoading(GetRenderViewHost(), value, true, NULL);
 }
 
 void TestWebContents::CommitPendingNavigation() {
@@ -207,19 +207,17 @@
   EXPECT_EQ(expect_set_history_length_and_prune_min_page_id_, min_page_id);
 }
 
-void TestWebContents::TestDidFinishLoad(const GURL& url,
-                                        bool is_main_frame) {
-  FrameHostMsg_DidFinishLoad msg(0, url, is_main_frame);
+void TestWebContents::TestDidFinishLoad(const GURL& url) {
+  FrameHostMsg_DidFinishLoad msg(0, url);
   frame_tree_.root()->current_frame_host()->OnMessageReceived(msg);
 }
 
 void TestWebContents::TestDidFailLoadWithError(
     const GURL& url,
-    bool is_main_frame,
     int error_code,
     const base::string16& error_description) {
   FrameHostMsg_DidFailLoadWithError msg(
-      0, url, is_main_frame, error_code, error_description);
+      0, url, error_code, error_description);
   frame_tree_.root()->current_frame_host()->OnMessageReceived(msg);
 }
 
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 18b7013..a0d6825 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -94,9 +94,8 @@
                                         int history_length,
                                         int32 min_page_id) OVERRIDE;
 
-  void TestDidFinishLoad(const GURL& url, bool is_main_frame);
+  void TestDidFinishLoad(const GURL& url);
   void TestDidFailLoadWithError(const GURL& url,
-                                bool is_main_frame,
                                 int error_code,
                                 const base::string16& error_description);
 
diff --git a/content/test/test_web_contents_view.cc b/content/test/test_web_contents_view.cc
index 7f0fb0a..41a1f30 100644
--- a/content/test/test_web_contents_view.cc
+++ b/content/test/test_web_contents_view.cc
@@ -12,15 +12,6 @@
 TestWebContentsView::~TestWebContentsView() {
 }
 
-void TestWebContentsView::ShowPopupMenu(const gfx::Rect& bounds,
-                                        int item_height,
-                                        double item_font_size,
-                                        int selected_item,
-                                        const std::vector<MenuItem>& items,
-                                        bool right_aligned,
-                                        bool allow_multiple_selection) {
-}
-
 void TestWebContentsView::StartDragging(
     const DropData& drop_data,
     blink::WebDragOperationsMask allowed_ops,
diff --git a/content/test/test_web_contents_view.h b/content/test/test_web_contents_view.h
index b7dcca3..053582e 100644
--- a/content/test/test_web_contents_view.h
+++ b/content/test/test_web_contents_view.h
@@ -18,13 +18,6 @@
   virtual ~TestWebContentsView();
 
   // RenderViewHostDelegateView:
-  virtual void ShowPopupMenu(const gfx::Rect& bounds,
-                             int item_height,
-                             double item_font_size,
-                             int selected_item,
-                             const std::vector<MenuItem>& items,
-                             bool right_aligned,
-                             bool allow_multiple_selection) OVERRIDE;
   virtual void StartDragging(const DropData& drop_data,
                              blink::WebDragOperationsMask allowed_ops,
                              const gfx::ImageSkia& image,
diff --git a/content/test/test_webkit_platform_support.cc b/content/test/test_webkit_platform_support.cc
index f7cc6b6..47c11c2 100644
--- a/content/test/test_webkit_platform_support.cc
+++ b/content/test/test_webkit_platform_support.cc
@@ -11,7 +11,6 @@
 #include "base/metrics/stats_counters.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
-#include "content/child/blink_platform_impl.h"
 #include "content/public/common/content_switches.h"
 #include "content/test/mock_webclipboard_impl.h"
 #include "content/test/web_gesture_curve_mock.h"
@@ -130,11 +129,6 @@
   return blink::WebString::fromUTF8("DumpRenderTree/0.0.0.0");
 }
 
-blink::WebString TestWebKitPlatformSupport::userAgent(
-    const blink::WebURL& url) {
-  return userAgent();
-}
-
 blink::WebData TestWebKitPlatformSupport::loadResource(const char* name) {
   if (!strcmp(name, "deleteButton")) {
     // Create a red 30x30 square.
@@ -152,7 +146,7 @@
         "\x82";
     return blink::WebData(red_square, arraysize(red_square));
   }
-  return BlinkPlatformImpl::loadResource(name);
+  return blink::WebData();
 }
 
 blink::WebString TestWebKitPlatformSupport::queryLocalizedString(
@@ -178,7 +172,7 @@
     case blink::WebLocalizedString::WeekFormatTemplate:
       return base::ASCIIToUTF16("Week $2, $1");
     default:
-      return BlinkPlatformImpl::queryLocalizedString(name);
+      return blink::WebString();
   }
 }
 
@@ -209,8 +203,7 @@
 
 #if defined(OS_WIN) || defined(OS_MACOSX)
 void TestWebKitPlatformSupport::SetThemeEngine(blink::WebThemeEngine* engine) {
-  active_theme_engine_ = engine ?
-      engine : WebKitPlatformSupportChildImpl::themeEngine();
+  active_theme_engine_ = engine ? engine : BlinkPlatformImpl::themeEngine();
 }
 
 blink::WebThemeEngine* TestWebKitPlatformSupport::themeEngine() {
@@ -222,31 +215,6 @@
   return &compositor_support_;
 }
 
-base::string16 TestWebKitPlatformSupport::GetLocalizedString(int message_id) {
-  return base::string16();
-}
-
-base::StringPiece TestWebKitPlatformSupport::GetDataResource(
-    int resource_id,
-    ui::ScaleFactor scale_factor) {
-  return base::StringPiece();
-}
-
-webkit_glue::ResourceLoaderBridge*
-TestWebKitPlatformSupport::CreateResourceLoader(
-    const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) {
-  NOTREACHED();
-  return NULL;
-}
-
-WebSocketStreamHandleBridge*
-TestWebKitPlatformSupport::CreateWebSocketStreamBridge(
-    blink::WebSocketStreamHandle* handle,
-    WebSocketStreamHandleDelegate* delegate) {
-  NOTREACHED();
-  return NULL;
-}
-
 blink::WebGestureCurve* TestWebKitPlatformSupport::createFlingAnimationCurve(
     int device_source,
     const blink::WebFloatPoint& velocity,
diff --git a/content/test/test_webkit_platform_support.h b/content/test/test_webkit_platform_support.h
index d26c8cc..53650c6 100644
--- a/content/test/test_webkit_platform_support.h
+++ b/content/test/test_webkit_platform_support.h
@@ -7,9 +7,9 @@
 
 #include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
+#include "content/child/blink_platform_impl.h"
 #include "content/child/simple_webmimeregistry_impl.h"
 #include "content/child/webfileutilities_impl.h"
-#include "content/child/webkitplatformsupport_child_impl.h"
 #include "content/test/mock_webclipboard_impl.h"
 #include "content/test/weburl_loader_mock_factory.h"
 #include "third_party/WebKit/public/platform/WebUnitTestSupport.h"
@@ -24,7 +24,7 @@
 // An implementation of WebKitPlatformSupport for tests.
 class TestWebKitPlatformSupport
     : public blink::WebUnitTestSupport,
-      public content::WebKitPlatformSupportChildImpl {
+      public BlinkPlatformImpl {
  public:
   TestWebKitPlatformSupport();
   virtual ~TestWebKitPlatformSupport();
@@ -36,8 +36,6 @@
 
   virtual blink::WebURLLoader* createURLLoader();
   virtual blink::WebString userAgent() OVERRIDE;
-  // TODO(jam): remove this after Blink is updated
-  virtual blink::WebString userAgent(const blink::WebURL& url);
   virtual blink::WebData loadResource(const char* name);
   virtual blink::WebString queryLocalizedString(
       blink::WebLocalizedString::Name name);
@@ -65,17 +63,6 @@
     return file_system_root_.path();
   }
 
-  virtual base::string16 GetLocalizedString(int message_id) OVERRIDE;
-  virtual base::StringPiece GetDataResource(
-      int resource_id,
-      ui::ScaleFactor scale_factor) OVERRIDE;
-  virtual webkit_glue::ResourceLoaderBridge* CreateResourceLoader(
-      const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info)
-     OVERRIDE;
-  virtual WebSocketStreamHandleBridge* CreateWebSocketStreamBridge(
-      blink::WebSocketStreamHandle* handle,
-      WebSocketStreamHandleDelegate* delegate) OVERRIDE;
-
   virtual blink::WebGestureCurve* createFlingAnimationCurve(
       int device_source,
       const blink::WebFloatPoint& velocity,
diff --git a/content/test/webrtc_content_browsertest_base.cc b/content/test/webrtc_content_browsertest_base.cc
index b52a68e..e3f7191 100644
--- a/content/test/webrtc_content_browsertest_base.cc
+++ b/content/test/webrtc_content_browsertest_base.cc
@@ -9,8 +9,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test_utils.h"
 
 namespace content {
 
diff --git a/content/test/webrtc_content_browsertest_base.h b/content/test/webrtc_content_browsertest_base.h
index 8d0112c..16745f7 100644
--- a/content/test/webrtc_content_browsertest_base.h
+++ b/content/test/webrtc_content_browsertest_base.h
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "content/test/content_browser_test.h"
+#include "content/public/test/content_browser_test.h"
 
 namespace base {
 class CommandLine;
diff --git a/content/test/webui_resource_browsertest.cc b/content/test/webui_resource_browsertest.cc
index 18ee37e..011b141 100644
--- a/content/test/webui_resource_browsertest.cc
+++ b/content/test/webui_resource_browsertest.cc
@@ -8,9 +8,9 @@
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
 #include "content/shell/browser/shell.h"
-#include "content/test/content_browser_test.h"
-#include "content/test/content_browser_test_utils.h"
 #include "grit/content_resources.h"
 #include "grit/webui_resources.h"
 #include "net/base/net_util.h"
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc
index 6fa43c8..c94312f 100644
--- a/content/utility/utility_thread_impl.cc
+++ b/content/utility/utility_thread_impl.cc
@@ -9,8 +9,8 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_vector.h"
+#include "content/child/blink_platform_impl.h"
 #include "content/child/child_process.h"
-#include "content/child/webkitplatformsupport_impl.h"
 #include "content/common/child_process_messages.h"
 #include "content/common/plugin_list.h"
 #include "content/common/utility_messages.h"
@@ -91,7 +91,7 @@
     // we run the utility thread on separate thread. This means that if any code
     // needs WebKit initialized in the utility process, they need to have
     // another path to support single process mode.
-    webkit_platform_support_.reset(new WebKitPlatformSupportImpl);
+    webkit_platform_support_.reset(new BlinkPlatformImpl);
     blink::initialize(webkit_platform_support_.get());
   }
   GetContentClient()->utility()->UtilityThreadStarted();
diff --git a/content/utility/utility_thread_impl.h b/content/utility/utility_thread_impl.h
index 8c4f79b..b4b5037 100644
--- a/content/utility/utility_thread_impl.h
+++ b/content/utility/utility_thread_impl.h
@@ -19,7 +19,7 @@
 }
 
 namespace content {
-class WebKitPlatformSupportImpl;
+class BlinkPlatformImpl;
 
 // This class represents the background thread where the utility task runs.
 class UtilityThreadImpl : public UtilityThread,
@@ -58,7 +58,7 @@
   // True if running in single process mode.
   bool single_process_;
 
-  scoped_ptr<WebKitPlatformSupportImpl> webkit_platform_support_;
+  scoped_ptr<BlinkPlatformImpl> webkit_platform_support_;
 
   DISALLOW_COPY_AND_ASSIGN(UtilityThreadImpl);
 };
diff --git a/content/webkit_version.target.darwin-x86_64.mk b/content/webkit_version.target.darwin-x86_64.mk
new file mode 100644
index 0000000..2033e86
--- /dev/null
+++ b/content/webkit_version.target.darwin-x86_64.mk
@@ -0,0 +1,50 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_webkit_version_gyp
+LOCAL_MODULE_STEM := webkit_version
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_webkit_version":
+$(gyp_shared_intermediate_dir)/webkit_version.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit_version.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit_version.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit_version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit_version.h: $(LOCAL_PATH)/build/util/version.py $(LOCAL_PATH)/build/util/LASTCHANGE.blink $(LOCAL_PATH)/content/webkit_version.h.in $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: content_content_gyp_webkit_version_target_generate_webkit_version ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir); python ../build/util/version.py -f ../build/util/LASTCHANGE.blink webkit_version.h.in "$(gyp_shared_intermediate_dir)/webkit_version.h"
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit_version.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_webkit_version_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_version
+webkit_version: content_webkit_version_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/webkit_version.target.linux-x86_64.mk b/content/webkit_version.target.linux-x86_64.mk
new file mode 100644
index 0000000..2033e86
--- /dev/null
+++ b/content/webkit_version.target.linux-x86_64.mk
@@ -0,0 +1,50 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := content_webkit_version_gyp
+LOCAL_MODULE_STEM := webkit_version
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_webkit_version":
+$(gyp_shared_intermediate_dir)/webkit_version.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit_version.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit_version.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit_version.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit_version.h: $(LOCAL_PATH)/build/util/version.py $(LOCAL_PATH)/build/util/LASTCHANGE.blink $(LOCAL_PATH)/content/webkit_version.h.in $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: content_content_gyp_webkit_version_target_generate_webkit_version ($@)"
+	$(hide)cd $(gyp_local_path)/content; mkdir -p $(gyp_shared_intermediate_dir); python ../build/util/version.py -f ../build/util/LASTCHANGE.blink webkit_version.h.in "$(gyp_shared_intermediate_dir)/webkit_version.h"
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit_version.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: content_webkit_version_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_version
+webkit_version: content_webkit_version_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/content/worker/websharedworker_stub.cc b/content/worker/websharedworker_stub.cc
index fd33a61..474feb3 100644
--- a/content/worker/websharedworker_stub.cc
+++ b/content/worker/websharedworker_stub.cc
@@ -23,6 +23,7 @@
     const base::string16& name,
     const base::string16& content_security_policy,
     blink::WebContentSecurityPolicyType security_policy_type,
+    bool pause_on_start,
     int route_id)
     : route_id_(route_id),
       client_(route_id, this),
@@ -37,6 +38,11 @@
 
   // TODO(atwilson): Add support for NaCl when they support MessagePorts.
   impl_ = blink::WebSharedWorker::create(client());
+  if (pause_on_start) {
+    // Pause worker context when it starts and wait until either DevTools client
+    // is attached or explicit resume notification is received.
+    impl_->pauseWorkerContextOnStart();
+  }
   worker_devtools_agent_.reset(new SharedWorkerDevToolsAgent(route_id, impl_));
   client()->set_devtools_agent(worker_devtools_agent_.get());
   impl_->startWorkerContext(url_, name,
diff --git a/content/worker/websharedworker_stub.h b/content/worker/websharedworker_stub.h
index 1f9aadd..c1a6287 100644
--- a/content/worker/websharedworker_stub.h
+++ b/content/worker/websharedworker_stub.h
@@ -30,6 +30,7 @@
                       const base::string16& name,
                       const base::string16& content_security_policy,
                       blink::WebContentSecurityPolicyType security_policy_type,
+                      bool pause_on_start,
                       int route_id);
 
   // IPC::Listener implementation.
diff --git a/content/worker/worker_thread.cc b/content/worker/worker_thread.cc
index 8425c16..687637b 100644
--- a/content/worker/worker_thread.cc
+++ b/content/worker/worker_thread.cc
@@ -123,6 +123,7 @@
       params.name,
       params.content_security_policy,
       params.security_policy_type,
+      params.pause_on_start,
       params.route_id);
 }
 
diff --git a/content/worker/worker_webkitplatformsupport_impl.h b/content/worker/worker_webkitplatformsupport_impl.h
index d6f711c..6038b85 100644
--- a/content/worker/worker_webkitplatformsupport_impl.h
+++ b/content/worker/worker_webkitplatformsupport_impl.h
@@ -6,7 +6,7 @@
 #define CONTENT_WORKER_WORKER_WEBKITPLATFORMSUPPORT_IMPL_H_
 
 #include "base/memory/scoped_ptr.h"
-#include "content/child/webkitplatformsupport_impl.h"
+#include "content/child/blink_platform_impl.h"
 #include "third_party/WebKit/public/platform/WebIDBFactory.h"
 #include "third_party/WebKit/public/platform/WebMimeRegistry.h"
 
@@ -28,7 +28,7 @@
 class WebDatabaseObserverImpl;
 class WebFileSystemImpl;
 
-class WorkerWebKitPlatformSupportImpl : public WebKitPlatformSupportImpl,
+class WorkerWebKitPlatformSupportImpl : public BlinkPlatformImpl,
                                         public blink::WebMimeRegistry {
  public:
   WorkerWebKitPlatformSupportImpl(
diff --git a/content/zygote/zygote_main_linux.cc b/content/zygote/zygote_main_linux.cc
index f6c32f9..5dc09fa 100644
--- a/content/zygote/zygote_main_linux.cc
+++ b/content/zygote/zygote_main_linux.cc
@@ -292,12 +292,12 @@
   ComputePepperPluginList(&plugins);
   for (size_t i = 0; i < plugins.size(); ++i) {
     if (!plugins[i].is_internal && plugins[i].is_sandboxed) {
-      std::string error;
+      base::NativeLibraryLoadError error;
       base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path,
                                                             &error);
       VLOG_IF(1, !library) << "Unable to load plugin "
                            << plugins[i].path.value() << " "
-                           << error;
+                           << error.ToString();
 
       (void)library;  // Prevent release-mode warning.
     }
diff --git a/courgette/courgette_lib.target.darwin-arm.mk b/courgette/courgette_lib.target.darwin-arm.mk
new file mode 100644
index 0000000..3e6a5e5
--- /dev/null
+++ b/courgette/courgette_lib.target.darwin-arm.mk
@@ -0,0 +1,284 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/courgette/courgette_lib.target.darwin-mips.mk b/courgette/courgette_lib.target.darwin-mips.mk
new file mode 100644
index 0000000..185e312
--- /dev/null
+++ b/courgette/courgette_lib.target.darwin-mips.mk
@@ -0,0 +1,278 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/courgette/courgette_lib.target.darwin-x86.mk b/courgette/courgette_lib.target.darwin-x86.mk
new file mode 100644
index 0000000..3c2f1d3
--- /dev/null
+++ b/courgette/courgette_lib.target.darwin-x86.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/courgette/courgette_lib.target.darwin-x86_64.mk b/courgette/courgette_lib.target.darwin-x86_64.mk
new file mode 100644
index 0000000..9421d4f
--- /dev/null
+++ b/courgette/courgette_lib.target.darwin-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/courgette/courgette_lib.target.linux-arm.mk b/courgette/courgette_lib.target.linux-arm.mk
new file mode 100644
index 0000000..3e6a5e5
--- /dev/null
+++ b/courgette/courgette_lib.target.linux-arm.mk
@@ -0,0 +1,284 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/courgette/courgette_lib.target.linux-mips.mk b/courgette/courgette_lib.target.linux-mips.mk
new file mode 100644
index 0000000..185e312
--- /dev/null
+++ b/courgette/courgette_lib.target.linux-mips.mk
@@ -0,0 +1,278 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/courgette/courgette_lib.target.linux-x86.mk b/courgette/courgette_lib.target.linux-x86.mk
new file mode 100644
index 0000000..3c2f1d3
--- /dev/null
+++ b/courgette/courgette_lib.target.linux-x86.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/courgette/courgette_lib.target.linux-x86_64.mk b/courgette/courgette_lib.target.linux-x86_64.mk
new file mode 100644
index 0000000..9421d4f
--- /dev/null
+++ b/courgette/courgette_lib.target.linux-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := courgette_courgette_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	courgette/adjustment_method.cc \
+	courgette/adjustment_method_2.cc \
+	courgette/assembly_program.cc \
+	courgette/third_party/bsdiff_apply.cc \
+	courgette/third_party/bsdiff_create.cc \
+	courgette/crc.cc \
+	courgette/difference_estimator.cc \
+	courgette/disassembler.cc \
+	courgette/disassembler_elf_32.cc \
+	courgette/disassembler_elf_32_arm.cc \
+	courgette/disassembler_elf_32_x86.cc \
+	courgette/disassembler_win32_x86.cc \
+	courgette/disassembler_win32_x64.cc \
+	courgette/encoded_program.cc \
+	courgette/ensemble.cc \
+	courgette/ensemble_apply.cc \
+	courgette/ensemble_create.cc \
+	courgette/memory_allocator.cc \
+	courgette/simple_delta.cc \
+	courgette/streams.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: courgette_courgette_lib_gyp
+
+# Alias gyp target name.
+.PHONY: courgette_lib
+courgette_lib: courgette_courgette_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/crypto/crypto.gyp b/crypto/crypto.gyp
index 95f02b3..ab19f69 100644
--- a/crypto/crypto.gyp
+++ b/crypto/crypto.gyp
@@ -54,17 +54,6 @@
           ],
         }],
         [ 'OS == "android"', {
-            'dependencies': [
-              '../third_party/openssl/openssl.gyp:openssl',
-            ],
-            'sources/': [
-              ['exclude', 'ec_private_key_nss\.cc$'],
-              ['exclude', 'ec_signature_creator_nss\.cc$'],
-              ['exclude', 'encryptor_nss\.cc$'],
-              ['exclude', 'hmac_nss\.cc$'],
-              ['exclude', 'signature_verifier_nss\.cc$'],
-              ['exclude', 'symmetric_key_nss\.cc$'],
-            ],
             'includes': [
               '../build/android/cpufeatures.gypi',
             ],
@@ -91,7 +80,7 @@
             'mac_security_services_lock.h',
           ],
         }],
-        [ 'OS == "mac" or OS == "ios" or OS == "win"', {
+        [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', {
           'dependencies': [
             '../third_party/nss/nss.gyp:nspr',
             '../third_party/nss/nss.gyp:nss',
@@ -112,6 +101,9 @@
           'msvs_disabled_warnings': [4267, ],
         }],
         [ 'use_openssl==1', {
+            'dependencies': [
+              '../third_party/openssl/openssl.gyp:openssl',
+            ],
             # TODO(joth): Use a glob to match exclude patterns once the
             #             OpenSSL file set is complete.
             'sources!': [
@@ -130,6 +122,7 @@
               'third_party/nss/chromium-blapi.h',
               'third_party/nss/chromium-blapit.h',
               'third_party/nss/chromium-nss.h',
+              'third_party/nss/chromium-prtypes.h',
               'third_party/nss/chromium-sha256.h',
               'third_party/nss/pk11akey.cc',
               'third_party/nss/rsawrapr.c',
@@ -208,12 +201,7 @@
             'openpgp_symmetric_encryption_unittest.cc',
           ]
         }],
-        [ 'OS == "mac" or OS == "ios" or OS == "win"', {
-          'dependencies': [
-            '../third_party/nss/nss.gyp:nss',
-          ],
-        }],
-        [ 'OS == "mac"', {
+        [ 'use_openssl == 0 and (OS == "mac" or OS == "ios" or OS == "win")', {
           'dependencies': [
             '../third_party/nss/nss.gyp:nspr',
           ],
diff --git a/crypto/crypto.gypi b/crypto/crypto.gypi
index 005921e..0759cca 100644
--- a/crypto/crypto.gypi
+++ b/crypto/crypto.gypi
@@ -15,6 +15,9 @@
         'secure_util.h',
         'symmetric_key.h',
         'symmetric_key_win.cc',
+        'third_party/nss/chromium-blapi.h',
+        'third_party/nss/chromium-blapit.h',
+        'third_party/nss/chromium-prtypes.h',
         'third_party/nss/chromium-sha256.h',
         'third_party/nss/sha512.cc',
       ],
@@ -92,8 +95,6 @@
       'signature_verifier_openssl.cc',
       'symmetric_key_nss.cc',
       'symmetric_key_openssl.cc',
-      'third_party/nss/chromium-blapi.h',
-      'third_party/nss/chromium-blapit.h',
       'third_party/nss/chromium-nss.h',
       'third_party/nss/pk11akey.cc',
       'third_party/nss/rsawrapr.c',
diff --git a/crypto/crypto.target.darwin-arm.mk b/crypto/crypto.target.darwin-arm.mk
index 3be7394..6a9c3b8 100644
--- a/crypto/crypto.target.darwin-arm.mk
+++ b/crypto/crypto.target.darwin-arm.mk
@@ -101,6 +101,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/crypto/crypto.target.darwin-mips.mk b/crypto/crypto.target.darwin-mips.mk
index 4cda7f4..e379109 100644
--- a/crypto/crypto.target.darwin-mips.mk
+++ b/crypto/crypto.target.darwin-mips.mk
@@ -100,6 +100,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -185,6 +186,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/crypto/crypto.target.darwin-x86.mk b/crypto/crypto.target.darwin-x86.mk
index 141aaa0..11f5bb0 100644
--- a/crypto/crypto.target.darwin-x86.mk
+++ b/crypto/crypto.target.darwin-x86.mk
@@ -102,6 +102,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/crypto/crypto.target.darwin-x86_64.mk b/crypto/crypto.target.darwin-x86_64.mk
new file mode 100644
index 0000000..197d99b
--- /dev/null
+++ b/crypto/crypto.target.darwin-x86_64.mk
@@ -0,0 +1,288 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := crypto_crypto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	crypto/hmac.cc \
+	crypto/secure_util.cc \
+	crypto/curve25519.cc \
+	crypto/curve25519-donna.c \
+	crypto/ghash.cc \
+	crypto/ec_private_key_openssl.cc \
+	crypto/ec_signature_creator.cc \
+	crypto/ec_signature_creator_openssl.cc \
+	crypto/encryptor.cc \
+	crypto/encryptor_openssl.cc \
+	crypto/hkdf.cc \
+	crypto/hmac_openssl.cc \
+	crypto/p224_spake.cc \
+	crypto/openssl_util.cc \
+	crypto/p224.cc \
+	crypto/random.cc \
+	crypto/rsa_private_key.cc \
+	crypto/rsa_private_key_openssl.cc \
+	crypto/secure_hash_openssl.cc \
+	crypto/sha2.cc \
+	crypto/signature_creator_openssl.cc \
+	crypto/signature_verifier_openssl.cc \
+	crypto/symmetric_key_openssl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCRYPTO_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCRYPTO_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: crypto_crypto_gyp
+
+# Alias gyp target name.
+.PHONY: crypto
+crypto: crypto_crypto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/crypto/crypto.target.linux-arm.mk b/crypto/crypto.target.linux-arm.mk
index 3be7394..6a9c3b8 100644
--- a/crypto/crypto.target.linux-arm.mk
+++ b/crypto/crypto.target.linux-arm.mk
@@ -101,6 +101,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/crypto/crypto.target.linux-mips.mk b/crypto/crypto.target.linux-mips.mk
index 4cda7f4..e379109 100644
--- a/crypto/crypto.target.linux-mips.mk
+++ b/crypto/crypto.target.linux-mips.mk
@@ -100,6 +100,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -185,6 +186,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/crypto/crypto.target.linux-x86.mk b/crypto/crypto.target.linux-x86.mk
index 141aaa0..11f5bb0 100644
--- a/crypto/crypto.target.linux-x86.mk
+++ b/crypto/crypto.target.linux-x86.mk
@@ -102,6 +102,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DCRYPTO_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/crypto/crypto.target.linux-x86_64.mk b/crypto/crypto.target.linux-x86_64.mk
new file mode 100644
index 0000000..197d99b
--- /dev/null
+++ b/crypto/crypto.target.linux-x86_64.mk
@@ -0,0 +1,288 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := crypto_crypto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	crypto/hmac.cc \
+	crypto/secure_util.cc \
+	crypto/curve25519.cc \
+	crypto/curve25519-donna.c \
+	crypto/ghash.cc \
+	crypto/ec_private_key_openssl.cc \
+	crypto/ec_signature_creator.cc \
+	crypto/ec_signature_creator_openssl.cc \
+	crypto/encryptor.cc \
+	crypto/encryptor_openssl.cc \
+	crypto/hkdf.cc \
+	crypto/hmac_openssl.cc \
+	crypto/p224_spake.cc \
+	crypto/openssl_util.cc \
+	crypto/p224.cc \
+	crypto/random.cc \
+	crypto/rsa_private_key.cc \
+	crypto/rsa_private_key_openssl.cc \
+	crypto/secure_hash_openssl.cc \
+	crypto/sha2.cc \
+	crypto/signature_creator_openssl.cc \
+	crypto/signature_verifier_openssl.cc \
+	crypto/symmetric_key_openssl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCRYPTO_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCRYPTO_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: crypto_crypto_gyp
+
+# Alias gyp target name.
+.PHONY: crypto
+crypto: crypto_crypto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/crypto/ec_private_key_openssl.cc b/crypto/ec_private_key_openssl.cc
index ce921dd..8504ab5 100644
--- a/crypto/ec_private_key_openssl.cc
+++ b/crypto/ec_private_key_openssl.cc
@@ -132,6 +132,11 @@
       PKCS8_decrypt(p8_encrypted.get(),
                     password.c_str(),
                     static_cast<int>(password.size())));
+  if (!p8_decrypted.get() && password.empty()) {
+    // Hack for reading keys generated by ec_private_key_nss. Passing NULL
+    // causes OpenSSL to use an empty password instead of "\0\0".
+    p8_decrypted.reset(PKCS8_decrypt(p8_encrypted.get(), NULL, 0));
+  }
   if (!p8_decrypted.get())
     return NULL;
 
diff --git a/crypto/ec_private_key_unittest.cc b/crypto/ec_private_key_unittest.cc
index d1a4c86..8f653f1 100644
--- a/crypto/ec_private_key_unittest.cc
+++ b/crypto/ec_private_key_unittest.cc
@@ -9,9 +9,6 @@
 #include "base/memory/scoped_ptr.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-// TODO(mattm): Add some exported keys from each to test
-// interop between NSS and OpenSSL.
-
 // Generate random private keys. Export, then re-import. We should get
 // back the same exact public key, and the private key should have the same
 // value and elliptic curve params.
@@ -97,3 +94,126 @@
           password2, privkey1, pubkey1));
   ASSERT_FALSE(keypair2.get());
 }
+
+TEST(ECPrivateKeyUnitTest, LoadNSSKeyTest) {
+  static const unsigned char nss_key[] = {
+      0x30, 0x81, 0xb8, 0x30, 0x23, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+      0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x15, 0x04, 0x10, 0x3f, 0xac, 0xe9,
+      0x38, 0xdb, 0x40, 0x6b, 0x26, 0x89, 0x09, 0x73, 0x18, 0x8d, 0x7f, 0x1c,
+      0x82, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0x5e, 0x5e, 0x11, 0xef, 0xbb,
+      0x7c, 0x4d, 0xec, 0xc0, 0xdc, 0xc7, 0x23, 0xd2, 0xc4, 0x77, 0xbc, 0xf4,
+      0x5d, 0x59, 0x4c, 0x07, 0xc2, 0x8a, 0x26, 0xfa, 0x25, 0x1c, 0xaa, 0x42,
+      0xed, 0xd0, 0xed, 0xbb, 0x5c, 0xe9, 0x13, 0x07, 0xaa, 0xdd, 0x52, 0x3c,
+      0x65, 0x25, 0xbf, 0x94, 0x02, 0xaf, 0xd6, 0x97, 0xe9, 0x33, 0x00, 0x76,
+      0x64, 0x4a, 0x73, 0xab, 0xfb, 0x99, 0x6e, 0x83, 0x12, 0x05, 0x86, 0x72,
+      0x6c, 0xd5, 0xa4, 0xcf, 0xb1, 0xd5, 0x4d, 0x54, 0x87, 0x8b, 0x4b, 0x95,
+      0x1d, 0xcd, 0xf3, 0xfe, 0xa8, 0xda, 0xe0, 0xb6, 0x72, 0x13, 0x3f, 0x2e,
+      0x66, 0xe0, 0xb9, 0x2e, 0xfa, 0x69, 0x40, 0xbe, 0xd7, 0x67, 0x6e, 0x53,
+      0x2b, 0x3f, 0x53, 0xe5, 0x39, 0x54, 0x77, 0xe1, 0x1d, 0xe6, 0x81, 0x92,
+      0x58, 0x82, 0x14, 0xfb, 0x47, 0x85, 0x3c, 0xc3, 0xdf, 0xdd, 0xcc, 0x79,
+      0x9f, 0x41, 0x83, 0x72, 0xf2, 0x0a, 0xe9, 0xe1, 0x2c, 0x12, 0xb0, 0xb0,
+      0x0a, 0xb2, 0x1d, 0xca, 0x15, 0xb2, 0xca};
+  unsigned int nss_key_len = 187;
+  static const unsigned char nss_pub_key[] = {
+      0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+      0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+      0x42, 0x00, 0x04, 0x85, 0x92, 0x9e, 0x95, 0x5c, 0x6b, 0x9e, 0xd6, 0x1e,
+      0xb8, 0x64, 0xea, 0xc2, 0xb3, 0xef, 0x18, 0xed, 0x3a, 0x5e, 0xc4, 0x5c,
+      0x15, 0x37, 0x6a, 0xe9, 0xaa, 0x0b, 0x34, 0x03, 0xfd, 0xca, 0x83, 0x0f,
+      0xd7, 0x5c, 0x5d, 0xc5, 0x53, 0x6e, 0xe5, 0xa9, 0x33, 0xd5, 0xcc, 0xab,
+      0x53, 0x78, 0xdd, 0xd6, 0x12, 0x3a, 0x5e, 0xeb, 0xbf, 0xdf, 0x16, 0xd3,
+      0x2c, 0x3b, 0xe8, 0xdb, 0x19, 0xfc, 0x5e};
+  unsigned int nss_pub_key_len = 91;
+
+  scoped_ptr<crypto::ECPrivateKey> keypair_nss(
+      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+          "",
+          std::vector<uint8>(nss_key, nss_key + nss_key_len),
+          std::vector<uint8>(nss_pub_key, nss_pub_key + nss_pub_key_len)));
+
+  EXPECT_TRUE(keypair_nss.get());
+}
+
+// The plan is to migrate to OpenSSL everywhere, so making NSS implementation be
+// able to load the OpenSSL generated keys isn't that important.
+#if defined(USE_OPENSSL)
+TEST(ECPrivateKeyUnitTest, LoadOpenSSLKeyTest) {
+  static const unsigned char openssl_key[] = {
+      0x30, 0x82, 0x01, 0xa1, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86,
+      0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0x86, 0xaa,
+      0xd7, 0xdf, 0x3b, 0x91, 0x97, 0x60, 0x02, 0x01, 0x01, 0x04, 0x82, 0x01,
+      0x80, 0xcb, 0x2a, 0x14, 0xaa, 0x4f, 0x38, 0x4c, 0xe1, 0x49, 0x00, 0xe2,
+      0x1a, 0x3a, 0x75, 0x87, 0x7e, 0x3d, 0xea, 0x4d, 0x53, 0xd4, 0x46, 0x47,
+      0x23, 0x8f, 0xa1, 0x72, 0x51, 0x92, 0x86, 0x8b, 0xeb, 0x53, 0xe6, 0x6a,
+      0x0a, 0x6b, 0xb6, 0xa0, 0xdc, 0x0f, 0xdc, 0x20, 0xc3, 0x45, 0x85, 0xf1,
+      0x95, 0x90, 0x5c, 0xf4, 0xfa, 0xee, 0x47, 0xaf, 0x35, 0xd0, 0xd0, 0xd3,
+      0x14, 0xde, 0x0d, 0xca, 0x1b, 0xd3, 0xbb, 0x20, 0xec, 0x9d, 0x6a, 0xd4,
+      0xc1, 0xce, 0x60, 0x81, 0xab, 0x0c, 0x72, 0x10, 0xfa, 0x28, 0x3c, 0xac,
+      0x87, 0x7b, 0x82, 0x85, 0x00, 0xb8, 0x58, 0x9c, 0x07, 0xc4, 0x7d, 0xa9,
+      0xc5, 0x94, 0x95, 0xf7, 0x23, 0x93, 0x3f, 0xed, 0xef, 0x92, 0x55, 0x25,
+      0x74, 0xbb, 0xd3, 0xd1, 0x67, 0x3b, 0x3d, 0x5a, 0xfe, 0x84, 0xf8, 0x97,
+      0x7d, 0x7c, 0x01, 0xc7, 0xd7, 0x0d, 0xf8, 0xc3, 0x6d, 0xd6, 0xf1, 0xaa,
+      0x9d, 0x1f, 0x69, 0x97, 0x45, 0x06, 0xc4, 0x1c, 0x95, 0x3c, 0xe0, 0xef,
+      0x11, 0xb2, 0xb3, 0x72, 0x91, 0x9e, 0x7d, 0x0f, 0x7f, 0xc8, 0xf6, 0x64,
+      0x49, 0x5e, 0x3c, 0x53, 0x37, 0x79, 0x03, 0x1c, 0x3f, 0x29, 0x6c, 0x6b,
+      0xea, 0x4c, 0x35, 0x9b, 0x6d, 0x1b, 0x59, 0x43, 0x4c, 0x14, 0x47, 0x2a,
+      0x36, 0x39, 0x2a, 0xd8, 0x96, 0x90, 0xdc, 0xfc, 0xd2, 0xdd, 0x23, 0x0e,
+      0x2c, 0xb3, 0x83, 0xf9, 0xf2, 0xe3, 0xe6, 0x99, 0x53, 0x57, 0x33, 0xc5,
+      0x5f, 0xf9, 0xfd, 0x56, 0x0b, 0x32, 0xd4, 0xf3, 0x9d, 0x5b, 0x34, 0xe5,
+      0x94, 0xbf, 0xb6, 0xc0, 0xce, 0xe1, 0x73, 0x5c, 0x02, 0x7a, 0x4c, 0xed,
+      0xde, 0x23, 0x38, 0x89, 0x9f, 0xcd, 0x51, 0xf3, 0x90, 0x80, 0xd3, 0x4b,
+      0x83, 0xd3, 0xee, 0xf2, 0x9e, 0x35, 0x91, 0xa5, 0xa3, 0xc0, 0x5c, 0xce,
+      0xdb, 0xaa, 0x70, 0x1e, 0x1d, 0xc1, 0x44, 0xea, 0x3b, 0xa7, 0x5a, 0x11,
+      0xd1, 0xf3, 0xf3, 0xd0, 0xf4, 0x5a, 0xc4, 0x99, 0xaf, 0x8d, 0xe2, 0xbc,
+      0xa2, 0xb9, 0x3d, 0x86, 0x5e, 0xba, 0xa0, 0xdf, 0x78, 0x81, 0x7c, 0x54,
+      0x31, 0xe3, 0x98, 0xb5, 0x46, 0xcb, 0x4d, 0x26, 0x4b, 0xf8, 0xac, 0x3a,
+      0x54, 0x1b, 0x77, 0x5a, 0x18, 0xa5, 0x43, 0x0e, 0x14, 0xde, 0x7b, 0xb7,
+      0x4e, 0x45, 0x99, 0x03, 0xd1, 0x3d, 0x18, 0xb2, 0x36, 0x00, 0x48, 0x07,
+      0x72, 0xbb, 0x4f, 0x21, 0x25, 0x3e, 0xda, 0x25, 0x24, 0x5b, 0xc8, 0xa0,
+      0x28, 0xd5, 0x9b, 0x96, 0x87, 0x07, 0x77, 0x84, 0xff, 0xd7, 0xac, 0x71,
+      0xf6, 0x61, 0x63, 0x0b, 0xfb, 0x42, 0xfd, 0x52, 0xf4, 0xc4, 0x35, 0x0c,
+      0xc2, 0xc1, 0x55, 0x22, 0x42, 0x2f, 0x13, 0x7d, 0x93, 0x27, 0xc8, 0x11,
+      0x35, 0xc5, 0xe3, 0xc5, 0xaa, 0x15, 0x3c, 0xac, 0x30, 0xbc, 0x45, 0x16,
+      0xed};
+  unsigned int openssl_key_len = 421;
+  static const unsigned char openssl_pub_key[] = {
+      0x30, 0x82, 0x01, 0x4b, 0x30, 0x82, 0x01, 0x03, 0x06, 0x07, 0x2a, 0x86,
+      0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02, 0x01, 0x01, 0x30,
+      0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01, 0x02, 0x21,
+      0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x5b, 0x04,
+      0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x04, 0x20, 0x5a,
+      0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55, 0x76,
+      0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6, 0x3b,
+      0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15, 0x00, 0xc4, 0x9d,
+      0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78, 0xe1, 0x13, 0x9d,
+      0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04, 0x6b, 0x17, 0xd1,
+      0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40,
+      0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39,
+      0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f,
+      0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33,
+      0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51,
+      0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad,
+      0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
+      0x02, 0x01, 0x01, 0x03, 0x42, 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03,
+      0x2e, 0x8f, 0x37, 0x9a, 0xd5, 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7,
+      0x4a, 0xe7, 0x20, 0xcb, 0x90, 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21,
+      0x88, 0x38, 0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9,
+      0xe3, 0xd5, 0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40,
+      0x41, 0x3b, 0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec};
+  unsigned int openssl_pub_key_len = 335;
+
+  scoped_ptr<crypto::ECPrivateKey> keypair_openssl(
+      crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+          "",
+          std::vector<uint8>(openssl_key, openssl_key + openssl_key_len),
+          std::vector<uint8>(openssl_pub_key,
+                             openssl_pub_key + openssl_pub_key_len)));
+
+  EXPECT_TRUE(keypair_openssl.get());
+}
+#endif  // defined(USE_OPENSSL)
diff --git a/crypto/encryptor.h b/crypto/encryptor.h
index bcc647b..ec1498b 100644
--- a/crypto/encryptor.h
+++ b/crypto/encryptor.h
@@ -13,7 +13,8 @@
 #include "build/build_config.h"
 #include "crypto/crypto_export.h"
 
-#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
+#if defined(USE_NSS) || \
+    (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX)))
 #include "crypto/scoped_nss_types.h"
 #endif
 
diff --git a/crypto/symmetric_key.h b/crypto/symmetric_key.h
index 1d903f1..413f61e 100644
--- a/crypto/symmetric_key.h
+++ b/crypto/symmetric_key.h
@@ -14,7 +14,8 @@
 // See comments for crypto_nacl_win64 in crypto.gyp.
 // Must test for NACL_WIN64 before OS_WIN since former is a subset of latter.
 #include "crypto/scoped_capi_types.h"
-#elif defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
+#elif defined(USE_NSS) || \
+    (!defined(USE_OPENSSL) && (defined(OS_WIN) || defined(OS_MACOSX)))
 #include "crypto/scoped_nss_types.h"
 #endif
 
diff --git a/crypto/third_party/nss/chromium-blapit.h b/crypto/third_party/nss/chromium-blapit.h
index 669f64d..938547a 100644
--- a/crypto/third_party/nss/chromium-blapit.h
+++ b/crypto/third_party/nss/chromium-blapit.h
@@ -43,7 +43,7 @@
 #ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_
 #define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_BLAPIT_H_
 
-#include "base/third_party/nspr/prtypes.h"
+#include "crypto/third_party/nss/chromium-prtypes.h"
 
 /*
 ** A status code. Status's are used by procedures that return status
diff --git a/crypto/third_party/nss/chromium-prtypes.h b/crypto/third_party/nss/chromium-prtypes.h
new file mode 100644
index 0000000..d5ea8a9
--- /dev/null
+++ b/crypto/third_party/nss/chromium-prtypes.h
@@ -0,0 +1,77 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2002
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/* Emulates the real prtypes.h. Defines the types and macros that sha512.cc
+ * needs. */
+
+#ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_
+#define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_
+
+#include <limits.h>
+#include <stdint.h>
+
+#include "build/build_config.h"
+
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+#define IS_LITTLE_ENDIAN 1
+#else
+#define IS_BIG_ENDIAN 1
+#endif
+
+/*
+ * The C language requires that 'long' be at least 32 bits. 2147483647 is the
+ * largest signed 32-bit integer.
+ */
+#if LONG_MAX > 2147483647L
+#define PR_BYTES_PER_LONG 8
+#else
+#define PR_BYTES_PER_LONG 4
+#endif
+
+#define HAVE_LONG_LONG
+
+#if defined(__linux__)
+#define LINUX
+#endif
+
+typedef uint8_t PRUint8;
+typedef uint32_t PRUint32;
+
+typedef int PRBool;
+
+#define PR_MIN(x,y) ((x)<(y)?(x):(y))
+
+#endif  /* CRYPTO_THIRD_PARTY_NSS_CHROMIUM_PRTYPES_H_ */
diff --git a/crypto/third_party/nss/chromium-sha256.h b/crypto/third_party/nss/chromium-sha256.h
index 14661dc..52815ca 100644
--- a/crypto/third_party/nss/chromium-sha256.h
+++ b/crypto/third_party/nss/chromium-sha256.h
@@ -37,7 +37,7 @@
 #ifndef CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_
 #define CRYPTO_THIRD_PARTY_NSS_CHROMIUM_SHA_256_H_
 
-#include "base/third_party/nspr/prtypes.h"
+#include "crypto/third_party/nss/chromium-prtypes.h"
 
 struct SHA256ContextStr {
     union {
diff --git a/crypto/third_party/nss/sha512.cc b/crypto/third_party/nss/sha512.cc
index 976a604..5ef4e50 100644
--- a/crypto/third_party/nss/sha512.cc
+++ b/crypto/third_party/nss/sha512.cc
@@ -42,7 +42,7 @@
 // size from ~10k to ~1k.  The performance should be reasonable for our use.
 #define NOUNROLL256 1
 
-#include "base/third_party/nspr/prtypes.h"  /* for PRUintXX */
+#include "crypto/third_party/nss/chromium-prtypes.h"  /* for PRUintXX */
 #if defined(_X86_) || defined(SHA_NO_LONG_LONG)
 #define NOUNROLL512 1
 #undef HAVE_LONG_LONG
diff --git a/device/bluetooth/bluetooth_chromeos_unittest.cc b/device/bluetooth/bluetooth_chromeos_unittest.cc
index b7733dd..924ea3c 100644
--- a/device/bluetooth/bluetooth_chromeos_unittest.cc
+++ b/device/bluetooth/bluetooth_chromeos_unittest.cc
@@ -706,16 +706,16 @@
   ASSERT_EQ((size_t)1, discovery_sessions_.size());
   ASSERT_TRUE(discovery_sessions_[0]->IsActive());
 
-  // First device to appear.
+  // First two devices to appear.
   message_loop_.Run();
 
-  EXPECT_EQ(1, observer.device_added_count_);
-  EXPECT_EQ(FakeBluetoothDeviceClient::kLegacyAutopairAddress,
+  EXPECT_EQ(2, observer.device_added_count_);
+  EXPECT_EQ(FakeBluetoothDeviceClient::kLowEnergyAddress,
             observer.last_device_address_);
 
   // Next we should get another two devices...
   message_loop_.Run();
-  EXPECT_EQ(3, observer.device_added_count_);
+  EXPECT_EQ(4, observer.device_added_count_);
 
   // Okay, let's run forward until a device is actually removed...
   while (!observer.device_removed_count_)
diff --git a/device/bluetooth/bluetooth_profile_chromeos.cc b/device/bluetooth/bluetooth_profile_chromeos.cc
index 5fe87fe..704b68c 100644
--- a/device/bluetooth/bluetooth_profile_chromeos.cc
+++ b/device/bluetooth/bluetooth_profile_chromeos.cc
@@ -254,7 +254,6 @@
 void BluetoothProfileChromeOS::OnUnregisterProfile() {
   VLOG(1) << object_path_.value() << ": Profile unregistered";
   object_path_ = dbus::ObjectPath("");
-  adapter_ = NULL;
   delete this;
 }
 
@@ -268,7 +267,6 @@
   LOG(WARNING) << object_path_.value() << ": Failed to unregister profile: "
                << error_name << ": " << error_message;
   object_path_ = dbus::ObjectPath("");
-  adapter_ = NULL;
   delete this;
 }
 
diff --git a/device/bluetooth/bluetooth_utils.cc b/device/bluetooth/bluetooth_utils.cc
index df0c875..b874736 100644
--- a/device/bluetooth/bluetooth_utils.cc
+++ b/device/bluetooth/bluetooth_utils.cc
@@ -79,9 +79,6 @@
   GetCanonicalUuid(uuid, &value_, &canonical_value_, &format_);
 }
 
-UUID::UUID() : format_(kFormatInvalid) {
-}
-
 UUID::~UUID() {
 }
 
diff --git a/device/bluetooth/bluetooth_utils.h b/device/bluetooth/bluetooth_utils.h
index 44b52b1..1f9a2c9 100644
--- a/device/bluetooth/bluetooth_utils.h
+++ b/device/bluetooth/bluetooth_utils.h
@@ -74,8 +74,6 @@
   bool operator!=(const UUID& uuid) const;
 
  private:
-  UUID();
-
   // String representation of the UUID that was used during construction. For
   // the supported sizes, this representation can have the following formats:
   //   - 16 bit:  XXXX
@@ -106,4 +104,3 @@
 }  // namespace device
 
 #endif  // DEVICE_BLUETOOTH_BLUETOOTH_UTILS_H_
-
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS
index 57b1dfc..32ebfd6 100644
--- a/extensions/browser/DEPS
+++ b/extensions/browser/DEPS
@@ -14,13 +14,10 @@
   # TODO(jamescook): Remove these. http://crbug.com/162530
   "+chrome/browser/chrome_notification_types.h",
   "+chrome/browser/extensions/api/content_settings/content_settings_store.h",
-  "+chrome/browser/extensions/api/dns/host_resolver_wrapper.h",
-  "+chrome/browser/extensions/api/preference/preference_api.h",
   "+chrome/browser/extensions/api/runtime/runtime_api.h",
   "+chrome/browser/renderer_host/chrome_render_message_filter.h",
   "+chrome/common/extensions/api/sockets/sockets_manifest_data.h",
   "+chrome/common/extensions/features/feature_channel.h",
-  "+chrome/common/extensions/permissions",
   "+grit/generated_resources.h",
 ]
 
diff --git a/extensions/browser/PRESUBMIT.py b/extensions/browser/PRESUBMIT.py
index 29a709b..659c176 100644
--- a/extensions/browser/PRESUBMIT.py
+++ b/extensions/browser/PRESUBMIT.py
@@ -8,6 +8,8 @@
 for more details on the presubmit API built into gcl.
 """
 
+import sys
+
 def GetPreferredTryMasters(project, change):
   return {
     'tryserver.chromium': {
@@ -15,294 +17,26 @@
     }
   }
 
-class HistogramValueChecker(object):
-  """Verify that changes to "extension_function_histogram_value.h" are valid.
+def _CreateHistogramValueChecker(input_api, output_api):
+  original_sys_path = sys.path
 
-  See comments at the top of the "extension_function_histogram_value.h" file
-  for what are considered valid changes. There are situations where this script
-  gives false positive warnings, i.e. it warns even though the edit is
-  legitimate. Since the script warns using prompt warnings, the user can always
-  choose to continue. The main point is to attract the attention to all
-  (potentially or not) invalid edits.
+  try:
+    sys.path.append(input_api.os_path.join(
+        input_api.PresubmitLocalPath(), '..', '..', 'tools',
+        'strict_enum_value_checker'))
+    from strict_enum_value_checker import StrictEnumValueChecker
+  finally:
+    sys.path = original_sys_path
 
-  """
-
-  # The name of the file we want to check against
-  LOCAL_PATH = "extensions/browser/extension_function_histogram_value.h"
-
-  # The markers we look for in the above source file as delimiters of the enum
-  # definition.
-  ENUM_START_MARKER = "enum HistogramValue {"
-  ENUM_END_MARKER = "  // Last entry:"
-
-  def __init__(self, input_api, output_api):
-    self.input_api = input_api
-    self.output_api = output_api
-    self.results = []
-
-  class EnumRange(object):
-    """Represents a range of line numbers (1-based)"""
-    def __init__(self, first_line, last_line):
-      self.first_line = first_line
-      self.last_line = last_line
-
-    def Count(self):
-      return self.last_line - self.first_line + 1
-
-    def Contains(self, line_num):
-      return self.first_line <= line_num and line_num <= self.last_line
-
-  def LogInfo(self, message):
-    self.input_api.logging.info(message)
-    return
-
-  def LogDebug(self, message):
-    self.input_api.logging.debug(message)
-    return
-
-  def ComputeEnumRangeInContents(self, contents):
-    """Returns an |EnumRange| object representing the line extent of the
-    HistogramValue enum members in |contents|. The line numbers are 1-based,
-    compatible with line numbers returned by AffectedFile.ChangeContents().
-    |contents| is a list of strings reprenting the lines of a text file.
-
-    If either ENUM_START_MARKER or ENUM_END_MARKER cannot be found in
-    |contents|, returns None and emits detailed warnings about the problem.
-
-    """
-    first_enum_line = 0
-    last_enum_line = 0
-    line_num = 1  # Line numbers are 1-based
-    for line in contents:
-      if line.startswith(self.ENUM_START_MARKER):
-        first_enum_line = line_num + 1
-      elif line.startswith(self.ENUM_END_MARKER):
-        last_enum_line = line_num
-      line_num += 1
-
-    if first_enum_line == 0:
-      self.EmitWarning("The presubmit script could not find the start of the "
-                       "enum definition (\"%s\"). Did the enum definition "
-                       "change?" % self.ENUM_START_MARKER)
-      return None
-
-    if last_enum_line == 0:
-      self.EmitWarning("The presubmit script could not find the end of the "
-                       "enum definition (\"%s\"). Did the enum definition "
-                       "change?" % self.ENUM_END_MARKER)
-      return None
-
-    if first_enum_line >= last_enum_line:
-      self.EmitWarning("The presubmit script located the start of the enum "
-                       "definition (\"%s\" at line %d) *after* its end "
-                       "(\"%s\" at line %d). Something is not quite right."
-                       % (self.ENUM_START_MARKER, first_enum_line,
-                          self.ENUM_END_MARKER, last_enum_line))
-      return None
-
-    self.LogInfo("Line extent of |HistogramValue| enum definition: "
-                 "first_line=%d, last_line=%d."
-                 % (first_enum_line, last_enum_line))
-    return self.EnumRange(first_enum_line, last_enum_line)
-
-  def ComputeEnumRangeInNewFile(self, affected_file):
-    return self.ComputeEnumRangeInContents(affected_file.NewContents())
-
-  def GetLongMessage(self):
-    return str("The file \"%s\" contains the definition of the "
-               "|HistogramValue| enum which should be edited in specific ways "
-               "only - *** read the comments at the top of the header file ***"
-               ". There are changes to the file that may be incorrect and "
-               "warrant manual confirmation after review. Note that this "
-               "presubmit script can not reliably report the nature of all "
-               "types of invalid changes, especially when the diffs are "
-               "complex. For example, an invalid deletion may be reported "
-               "whereas the change contains a valid rename."
-               % self.LOCAL_PATH)
-
-  def EmitWarning(self, message, line_number=None, line_text=None):
-    """Emits a presubmit prompt warning containing the short message
-    |message|. |item| is |LOCAL_PATH| with optional |line_number| and
-    |line_text|.
-
-    """
-    if line_number is not None and line_text is not None:
-      item = "%s(%d): %s" % (self.LOCAL_PATH, line_number, line_text)
-    elif line_number is not None:
-      item = "%s(%d)" % (self.LOCAL_PATH, line_number)
-    else:
-      item = self.LOCAL_PATH
-    long_message = self.GetLongMessage()
-    self.LogInfo(message)
-    self.results.append(
-      self.output_api.PresubmitPromptWarning(message, [item], long_message))
-
-  def CollectRangesInsideEnumDefinition(self, affected_file,
-                                        first_line, last_line):
-    """Returns a list of triplet (line_start, line_end, line_text) of ranges of
-    edits changes. The |line_text| part is the text at line |line_start|.
-    Since it used only for reporting purposes, we do not need all the text
-    lines in the range.
-
-    """
-    results = []
-    previous_line_number = 0
-    previous_range_start_line_number = 0
-    previous_range_start_text = ""
-
-    def addRange():
-      tuple = (previous_range_start_line_number,
-               previous_line_number,
-               previous_range_start_text)
-      results.append(tuple)
-
-    for line_number, line_text in affected_file.ChangedContents():
-      if first_line <= line_number and line_number <= last_line:
-        self.LogDebug("Line change at line number " + str(line_number) + ": " +
-                      line_text)
-        # Start a new interval if none started
-        if previous_range_start_line_number == 0:
-          previous_range_start_line_number = line_number
-          previous_range_start_text = line_text
-        # Add new interval if we reached past the previous one
-        elif line_number != previous_line_number + 1:
-          addRange()
-          previous_range_start_line_number = line_number
-          previous_range_start_text = line_text
-        previous_line_number = line_number
-
-    # Add a last interval if needed
-    if previous_range_start_line_number != 0:
-        addRange()
-    return results
-
-  def CheckForFileDeletion(self, affected_file):
-    """Emits a warning notification if file has been deleted """
-    if not affected_file.NewContents():
-      self.EmitWarning("The file seems to be deleted in the changelist. If "
-                       "your intent is to really delete the file, the code in "
-                       "PRESUBMIT.py should be updated to remove the "
-                       "|HistogramValueChecker| class.");
-      return False
-    return True
-
-  def GetDeletedLinesFromScmDiff(self, affected_file):
-    """Return a list of of line numbers (1-based) corresponding to lines
-    deleted from the new source file (if they had been present in it). Note
-    that if multiple contiguous lines have been deleted, the returned list will
-    contain contiguous line number entries. To prevent false positives, we
-    return deleted line numbers *only* from diff chunks which decrease the size
-    of the new file.
-
-    Note: We need this method because we have access to neither the old file
-    content nor the list of "delete" changes from the current presubmit script
-    API.
-
-    """
-    results = []
-    line_num = 0
-    deleting_lines = False
-    for line in affected_file.GenerateScmDiff().splitlines():
-      # Parse the unified diff chunk optional section heading, which looks like
-      # @@ -l,s +l,s @@ optional section heading
-      m = self.input_api.re.match(
-        r'^@@ \-([0-9]+)\,([0-9]+) \+([0-9]+)\,([0-9]+) @@', line)
-      if m:
-        old_line_num = int(m.group(1))
-        old_size = int(m.group(2))
-        new_line_num = int(m.group(3))
-        new_size = int(m.group(4))
-        line_num = new_line_num
-        # Return line numbers only from diff chunks decreasing the size of the
-        # new file
-        deleting_lines = old_size > new_size
-        continue
-      if not line.startswith('-'):
-        line_num += 1
-      if deleting_lines and line.startswith('-') and not line.startswith('--'):
-        results.append(line_num)
-    return results
-
-  def CheckForEnumEntryDeletions(self, affected_file):
-    """Look for deletions inside the enum definition. We currently use a
-    simple heuristics (not 100% accurate): if there are deleted lines inside
-    the enum definition, this might be a deletion.
-
-    """
-    range_new = self.ComputeEnumRangeInNewFile(affected_file)
-    if not range_new:
-      return False
-
-    is_ok = True
-    for line_num in self.GetDeletedLinesFromScmDiff(affected_file):
-      if range_new.Contains(line_num):
-        self.EmitWarning("It looks like you are deleting line(s) from the "
-                         "enum definition. This should never happen.",
-                         line_num)
-        is_ok = False
-    return is_ok
-
-  def CheckForEnumEntryInsertions(self, affected_file):
-    range = self.ComputeEnumRangeInNewFile(affected_file)
-    if not range:
-      return False
-
-    first_line = range.first_line
-    last_line = range.last_line
-
-    # Collect the range of changes inside the enum definition range.
-    is_ok = True
-    for line_start, line_end, line_text in \
-          self.CollectRangesInsideEnumDefinition(affected_file,
-                                                 first_line,
-                                                 last_line):
-      # The only edit we consider valid is adding 1 or more entries *exactly*
-      # at the end of the enum definition. Every other edit inside the enum
-      # definition will result in a "warning confirmation" message.
-      #
-      # TODO(rpaquay): We currently cannot detect "renames" of existing entries
-      # vs invalid insertions, so we sometimes will warn for valid edits.
-      is_valid_edit = (line_end == last_line - 1)
-
-      self.LogDebug("Edit range in new file at starting at line number %d and "
-                    "ending at line number %d: valid=%s"
-                    % (line_start, line_end, is_valid_edit))
-
-      if not is_valid_edit:
-        self.EmitWarning("The change starting at line %d and ending at line "
-                         "%d is *not* located *exactly* at the end of the "
-                         "enum definition. Unless you are renaming an "
-                         "existing entry, this is not a valid changes, as new "
-                         "entries should *always* be added at the end of the "
-                         "enum definition, right before the 'ENUM_BOUNDARY' "
-                         "entry." % (line_start, line_end),
-                         line_start,
-                         line_text)
-        is_ok = False
-    return is_ok
-
-  def PerformChecks(self, affected_file):
-    if not self.CheckForFileDeletion(affected_file):
-      return
-    if not self.CheckForEnumEntryDeletions(affected_file):
-      return
-    if not self.CheckForEnumEntryInsertions(affected_file):
-      return
-
-  def ProcessHistogramValueFile(self, affected_file):
-    self.LogInfo("Start processing file \"%s\"" % affected_file.LocalPath())
-    self.PerformChecks(affected_file)
-    self.LogInfo("Done processing file \"%s\"" % affected_file.LocalPath())
-
-  def Run(self):
-    for file in self.input_api.AffectedFiles(include_deletes=True):
-      if file.LocalPath() == self.LOCAL_PATH:
-        self.ProcessHistogramValueFile(file)
-    return self.results
+  return StrictEnumValueChecker(input_api, output_api,
+      start_marker='enum HistogramValue {', end_marker='  // Last entry:',
+      path='extensions/browser/extension_function_histogram_value.h')
 
 def CheckChangeOnUpload(input_api, output_api):
   results = []
-  results += HistogramValueChecker(input_api, output_api).Run()
+  results += _CreateHistogramValueChecker(input_api, output_api).Run()
   results += input_api.canned_checks.CheckPatchFormatted(input_api, output_api)
   return results
 
+def CheckChangeOnCommit(input_api, output_api):
+  return _CreateHistogramValueChecker(input_api, output_api).Run()
diff --git a/extensions/browser/PRESUBMIT_test.py b/extensions/browser/PRESUBMIT_test.py
deleted file mode 100755
index 99cabf5..0000000
--- a/extensions/browser/PRESUBMIT_test.py
+++ /dev/null
@@ -1,236 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import difflib
-import os
-import re
-import unittest
-
-import PRESUBMIT
-
-class MockLogging(object):
-  def __init__(self):
-    self.lines = []
-
-  def info(self, message):
-    self.lines.append(message)
-
-  def debug(self, message):
-    self.lines.append(message)
-
-class MockInputApi(object):
-  def __init__(self):
-    self.re = re
-    self.os_path = os.path
-    self.files = []
-    self.is_committing = False
-    self.logging = MockLogging()
-
-  def AffectedFiles(self, include_deletes=None):
-    return self.files
-
-
-class MockOutputApi(object):
-  class PresubmitResult(object):
-    def __init__(self, message, items=None, long_text=''):
-      self.message = message
-      self.items = items
-      self.long_text = long_text
-
-  class PresubmitError(PresubmitResult):
-    def __init__(self, message, items, long_text=''):
-      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
-      self.type = 'error'
-
-  class PresubmitPromptWarning(PresubmitResult):
-    def __init__(self, message, items, long_text=''):
-      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
-      self.type = 'warning'
-
-  class PresubmitNotifyResult(PresubmitResult):
-    def __init__(self, message, items, long_text=''):
-      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
-      self.type = 'notify'
-
-
-class MockFile(object):
-  def __init__(self, local_path, old_contents, new_contents):
-    self._local_path = local_path
-    self._new_contents = new_contents
-    self._old_contents = old_contents
-    self._cached_changed_contents = None
-
-  def ChangedContents(self):
-    return self._changed_contents
-
-  def NewContents(self):
-    return self._new_contents
-
-  def LocalPath(self):
-    return self._local_path
-
-  def IsDirectory(self):
-    return False
-
-  def GenerateScmDiff(self):
-    result = ""
-    for line in difflib.unified_diff(self._old_contents, self._new_contents,
-                                     self._local_path, self._local_path):
-      result += line
-    return result
-
-  # NOTE: This method is a copy of ChangeContents method of AffectedFile in
-  # presubmit_support.py
-  def ChangedContents(self):
-    """Returns a list of tuples (line number, line text) of all new lines.
-
-     This relies on the scm diff output describing each changed code section
-     with a line of the form
-
-     ^@@ <old line num>,<old size> <new line num>,<new size> @@$
-    """
-    if self._cached_changed_contents is not None:
-      return self._cached_changed_contents[:]
-    self._cached_changed_contents = []
-    line_num = 0
-
-    if self.IsDirectory():
-      return []
-
-    for line in self.GenerateScmDiff().splitlines():
-      m = re.match(r'^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@', line)
-      if m:
-        line_num = int(m.groups(1)[0])
-        continue
-      if line.startswith('+') and not line.startswith('++'):
-        self._cached_changed_contents.append((line_num, line[1:]))
-      if not line.startswith('-'):
-        line_num += 1
-    return self._cached_changed_contents[:]
-
-
-class MockChange(object):
-  def __init__(self, changed_files):
-    self._changed_files = changed_files
-
-  def LocalPaths(self):
-    return self._changed_files
-
-
-class HistogramValueCheckerTest(unittest.TestCase):
-  TEST_FILE_PATTERN = "PRESUBMIT_test_new_file_%s.txt"
-
-  def _ReadTextFileContents(self, path):
-    """Given a path, returns a list of strings corresponding to the text lines
-    in the file. Reads files in text format.
-
-    """
-    fo = open(path, 'r')
-    try:
-      contents = fo.readlines()
-    finally:
-      fo.close()
-    return contents
-
-  def _ReadInputFile(self):
-    return self._ReadTextFileContents("PRESUBMIT_test_old_file.txt")
-
-  def _PrepareTest(self, new_file_path):
-    old_contents = self._ReadInputFile()
-    if not new_file_path:
-      new_contents = []
-    else:
-      new_contents = self._ReadTextFileContents(new_file_path)
-    input_api = MockInputApi()
-    mock_file = MockFile(PRESUBMIT.HistogramValueChecker.LOCAL_PATH,
-                         old_contents,
-                         new_contents)
-    input_api.files.append(mock_file)
-    output_api = MockOutputApi()
-    return input_api, output_api
-
-  def _RunTest(self, new_file_path):
-    input_api, output_api = self._PrepareTest(new_file_path)
-    checker = PRESUBMIT.HistogramValueChecker(input_api, output_api)
-    results = checker.Run()
-    return results
-
-  def testDeleteFile(self):
-    results = self._RunTest(new_file_path=None)
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(1, len(results),
-                      "We hould get a single warning about file deletion.")
-
-  def testSimpleValidEdit(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "1")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(0, len(results),
-                      "We should get no warning for simple edits.")
-
-  def testSingleDeletionOfEntry(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "2")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(1, len(results),
-                      "We should get a warning for an entry deletion.")
-
-  def testSingleRenameOfEntry(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "3")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(1, len(results),
-                      "We should get a warning for an entry rename, even "
-                      "though it is not optimal.")
-
-  def testMissingEnumStartOfEntry(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "4")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(1, len(results),
-                      "We should get a warning for a missing enum marker.")
-
-  def testMissingEnumEndOfEntry(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "5")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(1, len(results),
-                      "We should get a warning for a missing enum marker.")
-
-  def testInvertedEnumMarkersOfEntry(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "6")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(1, len(results),
-                      "We should get a warning for inverted enum markers.")
-
-  def testMultipleInvalidEdits(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "7")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(3, len(results),
-                      "We should get 3 warnings (one per edit).")
-
-  def testSingleInvalidInserts(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "8")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(1, len(results),
-                      "We should get a warning for a single invalid "
-                      "insertion inside the enum.")
-
-  def testMulitpleValidInserts(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "9")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(0, len(results),
-                      "We should not get a warning mulitple valid edits")
-
-  def testSingleValidDeleteOutsideOfEnum(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "10")
-    # TODO(rpaquay) How to check it's the expected warning?'
-    self.assertEquals(0, len(results),
-                      "We should not get a warning for a deletion outside of "
-                      "the enum")
-
-  def testCommentIsNotEnumEndMarker(self):
-    results = self._RunTest(self.TEST_FILE_PATTERN % "11")
-    self.assertEquals(1, len(results),
-                      "We should get a warning if '// Last Entry' is not the "
-                      "enum end marker")
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/extensions/browser/PRESUBMIT_test_new_file_1.txt b/extensions/browser/PRESUBMIT_test_new_file_1.txt
deleted file mode 100644
index cf894a7..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_1.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  VALID_INSERTION,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_new_file_10.txt b/extensions/browser/PRESUBMIT_test_new_file_10.txt
deleted file mode 100644
index 745b130..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_10.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_new_file_11.txt b/extensions/browser/PRESUBMIT_test_new_file_11.txt
deleted file mode 100644
index d02dd03..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_11.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_new_file_2.txt b/extensions/browser/PRESUBMIT_test_new_file_2.txt
deleted file mode 100644
index e242545..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_2.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_new_file_3.txt b/extensions/browser/PRESUBMIT_test_new_file_3.txt
deleted file mode 100644
index 3e18f29b..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_3.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES2, // Rename here!!!
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_new_file_4.txt b/extensions/browser/PRESUBMIT_test_new_file_4.txt
deleted file mode 100644
index 8bab558..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_4.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-// Missing "HistrogramValue" enum 
-
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
diff --git a/extensions/browser/PRESUBMIT_test_new_file_5.txt b/extensions/browser/PRESUBMIT_test_new_file_5.txt
deleted file mode 100644
index 5c75baa..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_5.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-
-enum HistogramValue {
-
-
-// Missing end enum marker
diff --git a/extensions/browser/PRESUBMIT_test_new_file_6.txt b/extensions/browser/PRESUBMIT_test_new_file_6.txt
deleted file mode 100644
index d5d847b..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_6.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-// End enum marker is before start enum marker
-
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-
diff --git a/extensions/browser/PRESUBMIT_test_new_file_7.txt b/extensions/browser/PRESUBMIT_test_new_file_7.txt
deleted file mode 100644
index f928b71..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_7.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  BROWSINGDATA_REMOVEWEBSQL2,
-  BROWSINGDATA_REMOVEWEBSQL3,
-  BROWSINGDATA_REMOVEWEBSQL4,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME2,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME3,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS2,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_new_file_8.txt b/extensions/browser/PRESUBMIT_test_new_file_8.txt
deleted file mode 100644
index 8142053..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_8.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  BROWSINGDATA_REMOVEWEBSQL2,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_new_file_9.txt b/extensions/browser/PRESUBMIT_test_new_file_9.txt
deleted file mode 100644
index 75d8cce..0000000
--- a/extensions/browser/PRESUBMIT_test_new_file_9.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  BLAH1,
-  BLAH2,
-  BLAH3,
-  BLAH4,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/PRESUBMIT_test_old_file.txt b/extensions/browser/PRESUBMIT_test_old_file.txt
deleted file mode 100644
index 51cd734..0000000
--- a/extensions/browser/PRESUBMIT_test_old_file.txt
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-#define CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
-
-
-namespace extensions {
-namespace functions {
-
-//
-// This is some comment.
-// This is another comment.
-// This is yet another comment.
-//
-enum HistogramValue {
-  UNKNOWN = 0,
-  WEBNAVIGATION_GETALLFRAMES,
-  BROWSINGDATA_REMOVEWEBSQL,
-  WALLPAPERPRIVATE_SETCUSTOMWALLPAPERLAYOUT,
-  DOWNLOADSINTERNAL_DETERMINEFILENAME,
-  SYNCFILESYSTEM_GETFILESYNCSTATUSES,
-  MEDIAGALLERIESPRIVATE_GETHANDLERS,
-  WALLPAPERPRIVATE_RESETWALLPAPER,
-  // Last entry: Add new entries above and ensure to update
-  // tools/metrics/histograms/histograms/histograms.xml.
-  ENUM_BOUNDARY
-};
-
-}  // namespace functions
-}  // namespace extensions
-
-#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_FUNCTION_HISTOGRAM_VALUE_H_
diff --git a/extensions/browser/api/api_resource_manager.h b/extensions/browser/api/api_resource_manager.h
index a3c7740..6374abe 100644
--- a/extensions/browser/api/api_resource_manager.h
+++ b/extensions/browser/api/api_resource_manager.h
@@ -176,7 +176,7 @@
         : next_id_(1), thread_id_(thread_id) {}
 
     int Add(T* api_resource) {
-      DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+      DCHECK_CURRENTLY_ON(thread_id_);
       int id = GenerateId();
       if (id > 0) {
         linked_ptr<T> resource_ptr(api_resource);
@@ -195,7 +195,7 @@
     }
 
     void Remove(const std::string& extension_id, int api_resource_id) {
-      DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+      DCHECK_CURRENTLY_ON(thread_id_);
       if (GetOwnedResource(extension_id, api_resource_id) != NULL) {
         DCHECK(extension_resource_map_.find(extension_id) !=
                extension_resource_map_.end());
@@ -205,12 +205,12 @@
     }
 
     T* Get(const std::string& extension_id, int api_resource_id) {
-      DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+      DCHECK_CURRENTLY_ON(thread_id_);
       return GetOwnedResource(extension_id, api_resource_id);
     }
 
     base::hash_set<int>* GetResourceIds(const std::string& extension_id) {
-      DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+      DCHECK_CURRENTLY_ON(thread_id_);
       return GetOwnedResourceIds(extension_id);
     }
 
@@ -251,7 +251,7 @@
     }
 
     base::hash_set<int>* GetOwnedResourceIds(const std::string& extension_id) {
-      DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+      DCHECK_CURRENTLY_ON(thread_id_);
       if (extension_resource_map_.find(extension_id) ==
           extension_resource_map_.end())
         return NULL;
@@ -271,7 +271,7 @@
 
     void CleanupResourcesFromExtension(const std::string& extension_id,
                                        bool remove_all) {
-      DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+      DCHECK_CURRENTLY_ON(thread_id_);
 
       if (extension_resource_map_.find(extension_id) ==
           extension_resource_map_.end()) {
@@ -307,7 +307,7 @@
     }
 
     void Cleanup() {
-      DCHECK(content::BrowserThread::CurrentlyOn(thread_id_));
+      DCHECK_CURRENTLY_ON(thread_id_);
 
       api_resource_map_.clear();
       extension_resource_map_.clear();
diff --git a/extensions/browser/api/async_api_function.cc b/extensions/browser/api/async_api_function.cc
index 2ed484d..1152f20 100644
--- a/extensions/browser/api/async_api_function.cc
+++ b/extensions/browser/api/async_api_function.cc
@@ -17,7 +17,7 @@
 AsyncApiFunction::~AsyncApiFunction() {}
 
 bool AsyncApiFunction::RunImpl() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!PrePrepare() || !Prepare()) {
     return false;
@@ -52,7 +52,7 @@
 }
 
 void AsyncApiFunction::WorkOnWorkThread() {
-  DCHECK(BrowserThread::CurrentlyOn(work_thread_id_));
+  DCHECK_CURRENTLY_ON(work_thread_id_);
   DLOG_IF(ERROR, (work_thread_id_ == BrowserThread::UI))
       << "You have specified that AsyncApiFunction::Work() should happen on "
          "the UI thread. This nullifies the point of this class. Either "
@@ -61,7 +61,7 @@
 }
 
 void AsyncApiFunction::RespondOnUIThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   SendResponse(Respond());
 }
 
diff --git a/extensions/browser/api/dns/dns_api.cc b/extensions/browser/api/dns/dns_api.cc
new file mode 100644
index 0000000..a3a7eb1
--- /dev/null
+++ b/extensions/browser/api/dns/dns_api.cc
@@ -0,0 +1,104 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/dns/dns_api.h"
+
+#include "base/bind.h"
+#include "base/values.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/resource_context.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
+#include "extensions/common/api/dns.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_log.h"
+
+using content::BrowserThread;
+using extensions::core_api::dns::ResolveCallbackResolveInfo;
+
+namespace Resolve = extensions::core_api::dns::Resolve;
+
+namespace extensions {
+
+DnsResolveFunction::DnsResolveFunction()
+    : resource_context_(NULL),
+      response_(false),
+      request_handle_(new net::HostResolver::RequestHandle()),
+      addresses_(new net::AddressList) {}
+
+DnsResolveFunction::~DnsResolveFunction() {}
+
+bool DnsResolveFunction::RunImpl() {
+  scoped_ptr<Resolve::Params> params(Resolve::Params::Create(*args_));
+  EXTENSION_FUNCTION_VALIDATE(params.get());
+
+  hostname_ = params->hostname;
+  resource_context_ = browser_context()->GetResourceContext();
+
+  bool result = BrowserThread::PostTask(
+      BrowserThread::IO,
+      FROM_HERE,
+      base::Bind(&DnsResolveFunction::WorkOnIOThread, this));
+  DCHECK(result);
+  return true;
+}
+
+void DnsResolveFunction::WorkOnIOThread() {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+  net::HostResolver* host_resolver =
+      HostResolverWrapper::GetInstance()->GetHostResolver(
+          resource_context_->GetHostResolver());
+  DCHECK(host_resolver);
+
+  // Yes, we are passing zero as the port. There are some interesting but not
+  // presently relevant reasons why HostResolver asks for the port of the
+  // hostname you'd like to resolve, even though it doesn't use that value in
+  // determining its answer.
+  net::HostPortPair host_port_pair(hostname_, 0);
+
+  net::HostResolver::RequestInfo request_info(host_port_pair);
+  int resolve_result = host_resolver->Resolve(
+      request_info,
+      net::DEFAULT_PRIORITY,
+      addresses_.get(),
+      base::Bind(&DnsResolveFunction::OnLookupFinished, this),
+      request_handle_.get(),
+      net::BoundNetLog());
+
+  // Balanced in OnLookupFinished.
+  AddRef();
+
+  if (resolve_result != net::ERR_IO_PENDING)
+    OnLookupFinished(resolve_result);
+}
+
+void DnsResolveFunction::RespondOnUIThread() {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  SendResponse(response_);
+}
+
+void DnsResolveFunction::OnLookupFinished(int resolve_result) {
+  scoped_ptr<ResolveCallbackResolveInfo> resolve_info(
+      new ResolveCallbackResolveInfo());
+  resolve_info->result_code = resolve_result;
+  if (resolve_result == net::OK) {
+    DCHECK(!addresses_->empty());
+    resolve_info->address.reset(
+        new std::string(addresses_->front().ToStringWithoutPort()));
+  }
+  results_ = Resolve::Results::Create(*resolve_info);
+  response_ = true;
+
+  bool post_task_result = BrowserThread::PostTask(
+      BrowserThread::UI,
+      FROM_HERE,
+      base::Bind(&DnsResolveFunction::RespondOnUIThread, this));
+  DCHECK(post_task_result);
+
+  Release();  // Added in WorkOnIOThread().
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/api/dns/dns_api.h b/extensions/browser/api/dns/dns_api.h
new file mode 100644
index 0000000..f14769b
--- /dev/null
+++ b/extensions/browser/api/dns/dns_api.h
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_API_DNS_DNS_API_H_
+#define EXTENSIONS_BROWSER_API_DNS_DNS_API_H_
+
+#include <string>
+
+#include "extensions/browser/extension_function.h"
+#include "net/base/address_list.h"
+#include "net/base/completion_callback.h"
+#include "net/dns/host_resolver.h"
+
+namespace content {
+class ResourceContext;
+}
+
+namespace extensions {
+
+class DnsResolveFunction : public AsyncExtensionFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("dns.resolve", DNS_RESOLVE)
+
+  DnsResolveFunction();
+
+ protected:
+  virtual ~DnsResolveFunction();
+
+  // ExtensionFunction:
+  virtual bool RunImpl() OVERRIDE;
+
+  void WorkOnIOThread();
+  void RespondOnUIThread();
+
+ private:
+  void OnLookupFinished(int result);
+
+  std::string hostname_;
+
+  // Not owned.
+  content::ResourceContext* resource_context_;
+
+  bool response_;  // The value sent in SendResponse().
+
+  scoped_ptr<net::HostResolver::RequestHandle> request_handle_;
+  scoped_ptr<net::AddressList> addresses_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_API_DNS_DNS_API_H_
diff --git a/extensions/browser/api/dns/host_resolver_wrapper.cc b/extensions/browser/api/dns/host_resolver_wrapper.cc
new file mode 100644
index 0000000..f97a9c7
--- /dev/null
+++ b/extensions/browser/api/dns/host_resolver_wrapper.cc
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
+
+namespace extensions {
+
+HostResolverWrapper::HostResolverWrapper() : resolver_(NULL) {}
+
+// static
+HostResolverWrapper* HostResolverWrapper::GetInstance() {
+  return Singleton<extensions::HostResolverWrapper>::get();
+}
+
+net::HostResolver* HostResolverWrapper::GetHostResolver(
+    net::HostResolver* real_resolver) {
+  return resolver_ ? resolver_ : real_resolver;
+}
+
+void HostResolverWrapper::SetHostResolverForTesting(
+    net::HostResolver* mock_resolver) {
+  resolver_ = mock_resolver;
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/api/dns/host_resolver_wrapper.h b/extensions/browser/api/dns/host_resolver_wrapper.h
new file mode 100644
index 0000000..4eb4282
--- /dev/null
+++ b/extensions/browser/api/dns/host_resolver_wrapper.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_BROWSER_API_DNS_HOST_RESOLVER_WRAPPER_H_
+#define EXTENSIONS_BROWSER_API_DNS_HOST_RESOLVER_WRAPPER_H_
+
+#include "base/memory/singleton.h"
+#include "net/dns/host_resolver.h"
+
+namespace extensions {
+
+// Used for testing. In production code, this class does nothing interesting.
+// This class is a singleton that holds a pointer to a mock HostResolver, or
+// else to NULL. API classes that need to resolve hostnames ask this class for
+// the correct HostResolver to use, passing in the one that they want to use,
+// thereby avoiding most lifetime issues, and it will reply with either that
+// same one, or else the test version to use instead.
+//
+// This is a pretty complicated way to replace a single pointer with another.
+// TODO(miket): make the previous statement obsolete.
+class HostResolverWrapper {
+ public:
+  static HostResolverWrapper* GetInstance();
+
+  // Given a pointer to a real host resolver, returns the same pointer or else
+  // a substitute MockHostResolver to use instead. If
+  // SetHostResolverForTesting() hasn't been called, then this method returns
+  // the supplied argument as its result.
+  net::HostResolver* GetHostResolver(net::HostResolver* real_resolver);
+
+  // Sets the MockHostResolver to return in GetHostResolver().
+  void SetHostResolverForTesting(net::HostResolver* mock_resolver);
+
+ private:
+  HostResolverWrapper();
+  friend struct DefaultSingletonTraits<HostResolverWrapper>;
+
+  net::HostResolver* resolver_;
+
+  DISALLOW_COPY_AND_ASSIGN(HostResolverWrapper);
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_API_DNS_HOST_RESOLVER_WRAPPER_H_
diff --git a/extensions/browser/api/socket/socket_api.cc b/extensions/browser/api/socket/socket_api.cc
index 34a5517..5d40b84 100644
--- a/extensions/browser/api/socket/socket_api.cc
+++ b/extensions/browser/api/socket/socket_api.cc
@@ -8,16 +8,16 @@
 
 #include "base/bind.h"
 #include "base/containers/hash_tables.h"
-#include "chrome/browser/extensions/api/dns/host_resolver_wrapper.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/resource_context.h"
+#include "extensions/browser/api/dns/host_resolver_wrapper.h"
 #include "extensions/browser/api/socket/socket.h"
 #include "extensions/browser/api/socket/tcp_socket.h"
 #include "extensions/browser/api/socket/udp_socket.h"
 #include "extensions/browser/extension_system.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/socket_permission.h"
 #include "net/base/host_port_pair.h"
 #include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
@@ -668,14 +668,14 @@
 }
 
 void SocketGetNetworkListFunction::HandleGetNetworkListError() {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   error_ = kNetworkListError;
   SendResponse(false);
 }
 
 void SocketGetNetworkListFunction::SendResponseOnUIThread(
     const net::NetworkInterfaceList& interface_list) {
-  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
   std::vector<linked_ptr<core_api::socket::NetworkInterface> > create_arg;
   create_arg.reserve(interface_list.size());
diff --git a/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc b/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
index 11d4cee..92e58da 100644
--- a/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
+++ b/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
@@ -32,7 +32,7 @@
 // static
 TCPSocketEventDispatcher* TCPSocketEventDispatcher::Get(
     content::BrowserContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   return BrowserContextKeyedAPIFactory<TCPSocketEventDispatcher>::Get(context);
 }
@@ -58,21 +58,21 @@
 
 void TCPSocketEventDispatcher::OnSocketConnect(const std::string& extension_id,
                                                int socket_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   StartSocketRead(extension_id, socket_id);
 }
 
 void TCPSocketEventDispatcher::OnSocketResume(const std::string& extension_id,
                                               int socket_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   StartSocketRead(extension_id, socket_id);
 }
 
 void TCPSocketEventDispatcher::StartSocketRead(const std::string& extension_id,
                                                int socket_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   ReadParams params;
   params.thread_id = thread_id_;
@@ -86,7 +86,7 @@
 
 // static
 void TCPSocketEventDispatcher::StartRead(const ReadParams& params) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   ResumableTCPSocket* socket =
       params.sockets->Get(params.extension_id, params.socket_id);
@@ -113,7 +113,7 @@
     const ReadParams& params,
     int bytes_read,
     scoped_refptr<net::IOBuffer> io_buffer) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   // If |bytes_read| == 0, the connection has been closed by the peer.
   // If |bytes_read| < 0, there was a network error, and |bytes_read| is a value
@@ -168,7 +168,7 @@
 // static
 void TCPSocketEventDispatcher::PostEvent(const ReadParams& params,
                                          scoped_ptr<Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   BrowserThread::PostTask(BrowserThread::UI,
                           FROM_HERE,
@@ -182,7 +182,7 @@
 void TCPSocketEventDispatcher::DispatchEvent(void* browser_context_id,
                                              const std::string& extension_id,
                                              scoped_ptr<Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   content::BrowserContext* context =
       reinterpret_cast<content::BrowserContext*>(browser_context_id);
diff --git a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
index 6adc0fc..4a0c8e6 100644
--- a/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
+++ b/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
@@ -5,11 +5,11 @@
 #include "extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.h"
 
 #include "chrome/common/extensions/api/sockets/sockets_manifest_data.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
 #include "content/public/common/socket_permission_request.h"
 #include "extensions/browser/api/socket/tcp_socket.h"
 #include "extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/socket_permission.h"
 #include "net/base/net_errors.h"
 
 using content::SocketPermissionRequest;
diff --git a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
index 31eeeab..2818857 100644
--- a/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
+++ b/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
@@ -28,7 +28,7 @@
 // static
 TCPServerSocketEventDispatcher* TCPServerSocketEventDispatcher::Get(
     content::BrowserContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   return BrowserContextKeyedAPIFactory<TCPServerSocketEventDispatcher>::Get(
       context);
@@ -65,7 +65,7 @@
 void TCPServerSocketEventDispatcher::OnServerSocketListen(
     const std::string& extension_id,
     int socket_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   StartSocketAccept(extension_id, socket_id);
 }
@@ -73,7 +73,7 @@
 void TCPServerSocketEventDispatcher::OnServerSocketResume(
     const std::string& extension_id,
     int socket_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   StartSocketAccept(extension_id, socket_id);
 }
@@ -81,7 +81,7 @@
 void TCPServerSocketEventDispatcher::StartSocketAccept(
     const std::string& extension_id,
     int socket_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   AcceptParams params;
   params.thread_id = thread_id_;
@@ -96,7 +96,7 @@
 
 // static
 void TCPServerSocketEventDispatcher::StartAccept(const AcceptParams& params) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   ResumableTCPServerSocket* socket =
       params.server_sockets->Get(params.extension_id, params.socket_id);
@@ -120,7 +120,7 @@
     const AcceptParams& params,
     int result_code,
     net::TCPClientSocket* socket) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   if (result_code >= 0) {
     ResumableTCPSocket* client_socket =
@@ -169,7 +169,7 @@
 // static
 void TCPServerSocketEventDispatcher::PostEvent(const AcceptParams& params,
                                                scoped_ptr<Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   BrowserThread::PostTask(BrowserThread::UI,
                           FROM_HERE,
@@ -184,7 +184,7 @@
     void* browser_context_id,
     const std::string& extension_id,
     scoped_ptr<Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   content::BrowserContext* context =
       reinterpret_cast<content::BrowserContext*>(browser_context_id);
diff --git a/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc b/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
index e985dfb..09fd3f4 100644
--- a/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
+++ b/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
@@ -28,7 +28,7 @@
 // static
 UDPSocketEventDispatcher* UDPSocketEventDispatcher::Get(
     content::BrowserContext* context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   return BrowserContextKeyedAPIFactory<UDPSocketEventDispatcher>::Get(context);
 }
@@ -59,7 +59,7 @@
 
 void UDPSocketEventDispatcher::OnSocketResume(const std::string& extension_id,
                                               int socket_id) {
-  DCHECK(BrowserThread::CurrentlyOn(thread_id_));
+  DCHECK_CURRENTLY_ON(thread_id_);
 
   ReceiveParams params;
   params.thread_id = thread_id_;
@@ -73,7 +73,7 @@
 
 /* static */
 void UDPSocketEventDispatcher::StartReceive(const ReceiveParams& params) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   ResumableUDPSocket* socket =
       params.sockets->Get(params.extension_id, params.socket_id);
@@ -101,7 +101,7 @@
     scoped_refptr<net::IOBuffer> io_buffer,
     const std::string& address,
     int port) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   // If |bytes_read| == 0, the message contained no data.
   // If |bytes_read| < 0, there was a network error, and |bytes_read| is a value
@@ -154,7 +154,7 @@
 /* static */
 void UDPSocketEventDispatcher::PostEvent(const ReceiveParams& params,
                                          scoped_ptr<Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(params.thread_id));
+  DCHECK_CURRENTLY_ON(params.thread_id);
 
   BrowserThread::PostTask(BrowserThread::UI,
                           FROM_HERE,
@@ -168,7 +168,7 @@
 void UDPSocketEventDispatcher::DispatchEvent(void* browser_context_id,
                                              const std::string& extension_id,
                                              scoped_ptr<Event> event) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   content::BrowserContext* context =
       reinterpret_cast<content::BrowserContext*>(browser_context_id);
diff --git a/extensions/browser/api/storage/local_value_store_cache.cc b/extensions/browser/api/storage/local_value_store_cache.cc
index 6d05ca2..6946f33 100644
--- a/extensions/browser/api/storage/local_value_store_cache.cc
+++ b/extensions/browser/api/storage/local_value_store_cache.cc
@@ -46,17 +46,17 @@
           profile_path.AppendASCII(kLocalExtensionSettingsDirectoryName)),
       app_base_path_(profile_path.AppendASCII(kLocalAppSettingsDirectoryName)),
       quota_(GetLocalQuotaLimits()) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
 LocalValueStoreCache::~LocalValueStoreCache() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 }
 
 void LocalValueStoreCache::RunWithValueStoreForExtension(
     const StorageCallback& callback,
     scoped_refptr<const Extension> extension) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   ValueStore* storage = GetStorage(extension);
 
@@ -71,7 +71,7 @@
 }
 
 void LocalValueStoreCache::DeleteStorageSoon(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   storage_map_.erase(extension_id);
   storage_factory_->DeleteDatabaseIfExists(app_base_path_, extension_id);
   storage_factory_->DeleteDatabaseIfExists(extension_base_path_, extension_id);
diff --git a/extensions/browser/api/storage/storage_frontend.cc b/extensions/browser/api/storage/storage_frontend.cc
index 503205d..836858d 100644
--- a/extensions/browser/api/storage/storage_frontend.cc
+++ b/extensions/browser/api/storage/storage_frontend.cc
@@ -87,7 +87,7 @@
     const scoped_refptr<SettingsStorageFactory>& factory) {
   observers_ = new SettingsObserverList();
   browser_context_observer_.reset(new DefaultObserver(browser_context_));
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!browser_context_->IsOffTheRecord());
 
   observers_->AddObserver(browser_context_observer_.get());
@@ -102,7 +102,7 @@
 }
 
 StorageFrontend::~StorageFrontend() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   observers_->RemoveObserver(browser_context_observer_.get());
   for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
     ValueStoreCache* cache = it->second;
@@ -128,7 +128,7 @@
     scoped_refptr<const Extension> extension,
     settings_namespace::Namespace settings_namespace,
     const ValueStoreCache::StorageCallback& callback) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   CHECK(extension.get());
 
   ValueStoreCache* cache = caches_[settings_namespace];
@@ -141,7 +141,7 @@
 }
 
 void StorageFrontend::DeleteStorageSoon(const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   for (CacheMap::iterator it = caches_.begin(); it != caches_.end(); ++it) {
     ValueStoreCache* cache = it->second;
     BrowserThread::PostTask(
@@ -153,7 +153,7 @@
 }
 
 scoped_refptr<SettingsObserverList> StorageFrontend::GetObservers() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   return observers_;
 }
 
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc
index f9c7a86..4a165e3 100644
--- a/extensions/browser/event_router.cc
+++ b/extensions/browser/event_router.cc
@@ -128,6 +128,11 @@
 }
 
 // static
+EventRouter* EventRouter::Get(content::BrowserContext* browser_context) {
+  return ExtensionSystem::Get(browser_context)->event_router();
+}
+
+// static
 std::string EventRouter::GetBaseEventName(const std::string& full_event_name) {
   size_t slash_sep = full_event_name.find('/');
   return full_event_name.substr(0, slash_sep);
@@ -605,7 +610,7 @@
 void EventRouter::IncrementInFlightEventsOnUI(
     void* browser_context_id,
     const std::string& extension_id) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BrowserContext* browser_context =
       reinterpret_cast<BrowserContext*>(browser_context_id);
   if (!ExtensionsBrowserClient::Get()->IsValidContext(browser_context))
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h
index 467e7f3..79a0c94 100644
--- a/extensions/browser/event_router.h
+++ b/extensions/browser/event_router.h
@@ -68,6 +68,11 @@
     virtual void OnListenerRemoved(const EventListenerInfo& details) {}
   };
 
+  // Gets the EventRouter for |browser_context|.
+  // Shorthand for ExtensionSystem::Get(browser_context)->event_router(); it's
+  // a very common operation.
+  static EventRouter* Get(content::BrowserContext* browser_context);
+
   // Converts event names like "foo.onBar/123" into "foo.onBar". Event names
   // without a "/" are returned unchanged.
   static std::string GetBaseEventName(const std::string& full_event_name);
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc
index 3e29582..e5ab1e4 100644
--- a/extensions/browser/extension_function_dispatcher.cc
+++ b/extensions/browser/extension_function_dispatcher.cc
@@ -163,7 +163,7 @@
   // content::WebContentsObserver overrides.
   virtual void RenderViewDeleted(
       RenderViewHost* render_view_host) OVERRIDE {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     if (render_view_host != render_view_host_)
       return;
 
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 0c9c19b..52915dd 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -762,6 +762,8 @@
   BLUETOOTH_GETDEVICE,
   GCM_UNREGISTER,
   FILEBROWSERPRIVATE_REQUESTDRIVESHARE,
+  METRICSPRIVATE_RECORDSPARSEVALUE,
+  HOTWORDPRIVATE_SETAUDIOLOGGINGENABLED,
   // Last entry: Add new entries above and ensure to update
   // tools/metrics/histograms/histograms/histograms.xml.
   ENUM_BOUNDARY
diff --git a/extensions/browser/extension_message_filter.cc b/extensions/browser/extension_message_filter.cc
index bcd5621..d31f6e0 100644
--- a/extensions/browser/extension_message_filter.cc
+++ b/extensions/browser/extension_message_filter.cc
@@ -23,7 +23,7 @@
     : BrowserMessageFilter(ExtensionMsgStart),
       render_process_id_(render_process_id),
       browser_context_(context) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 }
 
 ExtensionMessageFilter::~ExtensionMessageFilter() {}
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index d48a13b..24f7e58 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -13,7 +13,6 @@
 #include "base/strings/string_util.h"
 #include "base/value_conversions.h"
 #include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
-#include "chrome/browser/extensions/api/preference/preference_api.h"
 #include "components/user_prefs/pref_registry_syncable.h"
 #include "extensions/browser/admin_policy.h"
 #include "extensions/browser/app_sorting.h"
@@ -77,6 +76,7 @@
 const char kPrefExternalAcknowledged[] = "ack_external";
 const char kPrefBlacklistAcknowledged[] = "ack_blacklist";
 const char kPrefWipeoutAcknowledged[] = "ack_wiped";
+const char kPrefSettingsBubbleAcknowledged[] = "ack_settings_bubble";
 
 // Indicates whether the external extension was installed during the first
 // run of this profile.
@@ -179,6 +179,14 @@
 // A preference that indicates when an extension is last launched.
 const char kPrefLastLaunchTime[] = "last_launch_time";
 
+// A preference that marks an ephemeral app that was evicted from the cache.
+// Their data is retained and garbage collected when inactive for a long period
+// of time.
+const char kPrefEvictedEphemeralApp[] = "evicted_ephemeral_app";
+
+// Am installation parameter bundled with an extension.
+const char kPrefInstallParam[] = "install_parameter";
+
 // A list of installed ids and a signature.
 const char kInstallSignature[] = "extensions.install_signature";
 
@@ -223,6 +231,80 @@
   return ext->GetBoolean(kPrefBlacklist, &bool_value) && bool_value;
 }
 
+bool IsEvictedEphemeralApp(const base::DictionaryValue* ext) {
+  bool bool_value;
+  return ext->GetBoolean(kPrefEvictedEphemeralApp, &bool_value) && bool_value;
+}
+
+void LoadExtensionControlledPrefs(ExtensionPrefs* prefs,
+                                  ExtensionPrefValueMap* value_map,
+                                  const std::string& extension_id,
+                                  ExtensionPrefsScope scope) {
+  std::string scope_string;
+  if (!pref_names::ScopeToPrefName(scope, &scope_string))
+    return;
+  std::string key = extension_id + "." + scope_string;
+
+  const base::DictionaryValue* source_dict =
+      prefs->pref_service()->GetDictionary(pref_names::kExtensions);
+  const base::DictionaryValue* preferences = NULL;
+  if (!source_dict->GetDictionary(key, &preferences))
+    return;
+
+  for (base::DictionaryValue::Iterator iter(*preferences); !iter.IsAtEnd();
+       iter.Advance()) {
+    value_map->SetExtensionPref(
+        extension_id, iter.key(), scope, iter.value().DeepCopy());
+  }
+}
+
+void InitExtensionControlledPrefs(ExtensionPrefs* prefs,
+                                  ExtensionPrefValueMap* value_map) {
+  ExtensionIdList extension_ids;
+  prefs->GetExtensions(&extension_ids);
+
+  for (ExtensionIdList::iterator extension_id = extension_ids.begin();
+       extension_id != extension_ids.end();
+       ++extension_id) {
+    base::Time install_time = prefs->GetInstallTime(*extension_id);
+    bool is_enabled = !prefs->IsExtensionDisabled(*extension_id);
+    bool is_incognito_enabled = prefs->IsIncognitoEnabled(*extension_id);
+    value_map->RegisterExtension(
+        *extension_id, install_time, is_enabled, is_incognito_enabled);
+    prefs->content_settings_store()->RegisterExtension(
+        *extension_id, install_time, is_enabled);
+
+    // Set regular extension controlled prefs.
+    LoadExtensionControlledPrefs(
+        prefs, value_map, *extension_id, kExtensionPrefsScopeRegular);
+    // Set incognito extension controlled prefs.
+    LoadExtensionControlledPrefs(prefs,
+                                 value_map,
+                                 *extension_id,
+                                 kExtensionPrefsScopeIncognitoPersistent);
+    // Set regular-only extension controlled prefs.
+    LoadExtensionControlledPrefs(
+        prefs, value_map, *extension_id, kExtensionPrefsScopeRegularOnly);
+
+    // Set content settings.
+    const base::ListValue* content_settings = NULL;
+    if (prefs->ReadPrefAsList(*extension_id,
+                              pref_names::kPrefContentSettings,
+                              &content_settings)) {
+      prefs->content_settings_store()->SetExtensionContentSettingFromList(
+          *extension_id, content_settings, kExtensionPrefsScopeRegular);
+    }
+    if (prefs->ReadPrefAsList(*extension_id,
+                              pref_names::kPrefIncognitoContentSettings,
+                              &content_settings)) {
+      prefs->content_settings_store()->SetExtensionContentSettingFromList(
+          *extension_id,
+          content_settings,
+          kExtensionPrefsScopeIncognitoPersistent);
+    }
+  }
+}
+
 }  // namespace
 
 //
@@ -683,6 +765,20 @@
                       value ? base::Value::CreateBooleanValue(value) : NULL);
 }
 
+bool ExtensionPrefs::HasSettingsApiBubbleBeenAcknowledged(
+    const std::string& extension_id) {
+  return ReadPrefAsBooleanAndReturn(extension_id,
+                                    kPrefSettingsBubbleAcknowledged);
+}
+
+void ExtensionPrefs::SetSettingsApiBubbleBeenAcknowledged(
+    const std::string& extension_id,
+    bool value) {
+  UpdateExtensionPref(extension_id,
+                      kPrefSettingsBubbleAcknowledged,
+                      value ? base::Value::CreateBooleanValue(value) : NULL);
+}
+
 bool ExtensionPrefs::SetAlertSystemFirstRun() {
   if (prefs_->GetBoolean(pref_names::kAlertsInitialized)) {
     return true;
@@ -719,27 +815,51 @@
 
 void ExtensionPrefs::AddDisableReason(const std::string& extension_id,
                                       Extension::DisableReason disable_reason) {
-  int new_value = GetDisableReasons(extension_id) |
-      static_cast<int>(disable_reason);
-  UpdateExtensionPref(extension_id, kPrefDisableReasons,
-                      new base::FundamentalValue(new_value));
+  ModifyDisableReason(extension_id, disable_reason, DISABLE_REASON_ADD);
 }
 
 void ExtensionPrefs::RemoveDisableReason(
     const std::string& extension_id,
     Extension::DisableReason disable_reason) {
-  int new_value = GetDisableReasons(extension_id) &
-      ~static_cast<int>(disable_reason);
-  if (new_value == Extension::DISABLE_NONE) {
-    UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
-  } else {
-    UpdateExtensionPref(extension_id, kPrefDisableReasons,
-                        new base::FundamentalValue(new_value));
-  }
+  ModifyDisableReason(extension_id, disable_reason, DISABLE_REASON_REMOVE);
 }
 
 void ExtensionPrefs::ClearDisableReasons(const std::string& extension_id) {
-  UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
+  ModifyDisableReason(
+      extension_id, Extension::DISABLE_NONE, DISABLE_REASON_CLEAR);
+}
+
+void ExtensionPrefs::ModifyDisableReason(const std::string& extension_id,
+                                         Extension::DisableReason reason,
+                                         DisableReasonChange change) {
+  int old_value = GetDisableReasons(extension_id);
+  int new_value = old_value;
+  switch (change) {
+    case DISABLE_REASON_ADD:
+      new_value |= static_cast<int>(reason);
+      break;
+    case DISABLE_REASON_REMOVE:
+      new_value &= ~static_cast<int>(reason);
+      break;
+    case DISABLE_REASON_CLEAR:
+      new_value = Extension::DISABLE_NONE;
+      break;
+  }
+
+  if (old_value == new_value)  // no change, return.
+    return;
+
+  if (new_value == Extension::DISABLE_NONE) {
+    UpdateExtensionPref(extension_id, kPrefDisableReasons, NULL);
+  } else {
+    UpdateExtensionPref(extension_id,
+                        kPrefDisableReasons,
+                        new base::FundamentalValue(new_value));
+  }
+
+  FOR_EACH_OBSERVER(Observer,
+                    observer_list_,
+                    OnExtensionDisableReasonsChanged(extension_id, new_value));
 }
 
 std::set<std::string> ExtensionPrefs::GetBlacklistedExtensions() {
@@ -1107,12 +1227,17 @@
     const Extension* extension,
     Extension::State initial_state,
     bool blacklisted_for_malware,
-    const syncer::StringOrdinal& page_ordinal) {
+    const syncer::StringOrdinal& page_ordinal,
+    const std::string& install_parameter) {
   ScopedExtensionPrefUpdate update(prefs_, extension->id());
   base::DictionaryValue* extension_dict = update.Get();
   const base::Time install_time = time_provider_->GetCurrentTime();
-  PopulateExtensionInfoPrefs(extension, install_time, initial_state,
-                             blacklisted_for_malware, extension_dict);
+  PopulateExtensionInfoPrefs(extension,
+                             install_time,
+                             initial_state,
+                             blacklisted_for_malware,
+                             install_parameter,
+                             extension_dict);
   FinishExtensionInfoPrefs(extension->id(), install_time,
                            extension->RequiresSortOrdinal(),
                            page_ordinal, extension_dict);
@@ -1134,7 +1259,14 @@
     extension_pref_value_map_->SetExtensionState(extension_id, false);
     content_settings_store_->SetExtensionState(extension_id, false);
   } else {
-    DeleteExtensionPrefs(extension_id);
+    int creation_flags = GetCreationFlags(extension_id);
+    if (creation_flags & Extension::IS_EPHEMERAL) {
+      // Keep ephemeral apps around, but mark them as evicted.
+      UpdateExtensionPref(extension_id, kPrefEvictedEphemeralApp,
+                          new base::FundamentalValue(true));
+    } else {
+      DeleteExtensionPrefs(extension_id);
+    }
   }
 }
 
@@ -1267,6 +1399,11 @@
     return scoped_ptr<ExtensionInfo>();
   }
 
+  if (IsEvictedEphemeralApp(ext)) {
+    // Hide evicted ephemeral apps.
+    return scoped_ptr<ExtensionInfo>();
+  }
+
   return GetInstalledInfoHelper(extension_id, ext);
 }
 
@@ -1318,10 +1455,14 @@
     Extension::State initial_state,
     bool blacklisted_for_malware,
     DelayReason delay_reason,
-    const syncer::StringOrdinal& page_ordinal) {
+    const syncer::StringOrdinal& page_ordinal,
+    const std::string& install_parameter) {
   base::DictionaryValue* extension_dict = new base::DictionaryValue();
-  PopulateExtensionInfoPrefs(extension, time_provider_->GetCurrentTime(),
-                             initial_state, blacklisted_for_malware,
+  PopulateExtensionInfoPrefs(extension,
+                             time_provider_->GetCurrentTime(),
+                             initial_state,
+                             blacklisted_for_malware,
+                             install_parameter,
                              extension_dict);
 
   // Add transient data that is needed by FinishDelayedInstallInfo(), but
@@ -1439,6 +1580,54 @@
   return extensions_info.Pass();
 }
 
+scoped_ptr<ExtensionPrefs::ExtensionsInfo>
+ExtensionPrefs::GetEvictedEphemeralAppsInfo() const {
+  scoped_ptr<ExtensionsInfo> extensions_info(new ExtensionsInfo);
+
+  const base::DictionaryValue* extensions =
+      prefs_->GetDictionary(pref_names::kExtensions);
+  for (base::DictionaryValue::Iterator extension_id(*extensions);
+       !extension_id.IsAtEnd(); extension_id.Advance()) {
+    const base::DictionaryValue* ext = NULL;
+    if (!Extension::IdIsValid(extension_id.key()) ||
+        !extension_id.value().GetAsDictionary(&ext)) {
+      continue;
+    }
+
+    if (!IsEvictedEphemeralApp(ext))
+      continue;
+
+    scoped_ptr<ExtensionInfo> info =
+        GetInstalledInfoHelper(extension_id.key(), ext);
+    if (info)
+      extensions_info->push_back(linked_ptr<ExtensionInfo>(info.release()));
+  }
+
+  return extensions_info.Pass();
+}
+
+scoped_ptr<ExtensionInfo> ExtensionPrefs::GetEvictedEphemeralAppInfo(
+    const std::string& extension_id) const {
+  const base::DictionaryValue* extension_prefs = GetExtensionPref(extension_id);
+  if (!extension_prefs)
+    return scoped_ptr<ExtensionInfo>();
+
+  if (!IsEvictedEphemeralApp(extension_prefs))
+    return scoped_ptr<ExtensionInfo>();
+
+  return GetInstalledInfoHelper(extension_id, extension_prefs);
+}
+
+void ExtensionPrefs::RemoveEvictedEphemeralApp(
+    const std::string& extension_id) {
+  bool evicted_ephemeral_app = false;
+  if (ReadPrefAsBoolean(extension_id,
+                        kPrefEvictedEphemeralApp,
+                        &evicted_ephemeral_app) && evicted_ephemeral_app) {
+    DeleteExtensionPrefs(extension_id);
+  }
+}
+
 bool ExtensionPrefs::WasAppDraggedByUser(const std::string& extension_id) {
   return ReadPrefAsBooleanAndReturn(extension_id, kPrefUserDraggedApp);
 }
@@ -1586,6 +1775,14 @@
   return result;
 }
 
+void ExtensionPrefs::AddObserver(Observer* observer) {
+  observer_list_.AddObserver(observer);
+}
+
+void ExtensionPrefs::RemoveObserver(Observer* observer) {
+  observer_list_.RemoveObserver(observer);
+}
+
 void ExtensionPrefs::FixMissingPrefs(const ExtensionIdList& extension_ids) {
   // Fix old entries that did not get an installation time entry when they
   // were installed or don't have a preferences field.
@@ -1629,7 +1826,7 @@
   MigrateDisableReasons(extension_ids);
   app_sorting_->Initialize(extension_ids);
 
-  PreferenceAPI::InitExtensionControlledPrefs(this, extension_pref_value_map_);
+  InitExtensionControlledPrefs(this, extension_pref_value_map_);
 
   extension_pref_value_map_->NotifyInitializationCompleted();
 }
@@ -1697,6 +1894,25 @@
   }
 }
 
+std::string ExtensionPrefs::GetInstallParam(
+    const std::string& extension_id) const {
+  const base::DictionaryValue* extension = GetExtensionPref(extension_id);
+  if (!extension) {
+    NOTREACHED();
+    return std::string();
+  }
+  std::string install_parameter;
+  if (!extension->GetString(kPrefInstallParam, &install_parameter))
+    return std::string();
+  return install_parameter;
+}
+
+void ExtensionPrefs::SetInstallParam(const std::string& extension_id,
+                                     const std::string& install_parameter) {
+  UpdateExtensionPref(extension_id,
+                      kPrefInstallParam,
+                      new base::StringValue(install_parameter));
+}
 
 ExtensionPrefs::ExtensionPrefs(
     PrefService* prefs,
@@ -1832,6 +2048,7 @@
     const base::Time install_time,
     Extension::State initial_state,
     bool blacklisted_for_malware,
+    const std::string& install_parameter,
     base::DictionaryValue* extension_dict) {
   // Leave the state blank for component extensions so that old chrome versions
   // loading new profiles do not fail in GetInstalledExtensionInfo. Older
@@ -1862,6 +2079,10 @@
   base::FilePath::StringType path = MakePathRelative(install_directory_,
                                                      extension->path());
   extension_dict->Set(kPrefPath, new base::StringValue(path));
+  if (!install_parameter.empty()) {
+    extension_dict->Set(kPrefInstallParam,
+                        new base::StringValue(install_parameter));
+  }
   // We store prefs about LOAD extensions, but don't cache their manifest
   // since it may change on disk.
   if (!Manifest::IsUnpackedLocation(extension->location())) {
@@ -1907,6 +2128,9 @@
   // Clear state that may be registered from a previous install.
   extension_dict->Remove(EventRouter::kRegisteredEvents, NULL);
 
+  // When evicted ephemeral apps are re-installed, this flag must be reset.
+  extension_dict->Remove(kPrefEvictedEphemeralApp, NULL);
+
   // FYI, all code below here races on sudden shutdown because |extension_dict|,
   // |app_sorting_|, |extension_pref_value_map_|, and |content_settings_store_|
   // are updated non-transactionally. This is probably not fixable without
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h
index 032c578..98a2e87 100644
--- a/extensions/browser/extension_prefs.h
+++ b/extensions/browser/extension_prefs.h
@@ -11,6 +11,7 @@
 
 #include "base/memory/linked_ptr.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
 #include "base/prefs/scoped_user_pref_update.h"
 #include "base/time/time.h"
 #include "base/values.h"
@@ -122,6 +123,14 @@
   typedef ScopedUpdate<base::ListValue, base::Value::TYPE_LIST>
       ScopedListUpdate;
 
+  class Observer {
+   public:
+    // Called when the reasons for an extension being disabled have changed.
+    virtual void OnExtensionDisableReasonsChanged(
+        const std::string& extension_id,
+        int disabled_reasons) = 0;
+  };
+
   // Creates and initializes an ExtensionPrefs object.
   // Does not take ownership of |prefs| and |extension_pref_value_map|.
   // If |extensions_disabled| is true, extension controlled preferences and
@@ -153,6 +162,10 @@
   // access to the extension ID list before the ExtensionService is initialized.
   static ExtensionIdList GetExtensionsFrom(const PrefService* pref_service);
 
+  // Add or remove an observer from the ExtensionPrefs.
+  void AddObserver(Observer* observer);
+  void RemoveObserver(Observer* observer);
+
   // Returns true if the specified external extension was uninstalled by the
   // user.
   bool IsExternalExtensionUninstalled(const std::string& id) const;
@@ -180,7 +193,8 @@
   void OnExtensionInstalled(const Extension* extension,
                             Extension::State initial_state,
                             bool blacklisted_for_malware,
-                            const syncer::StringOrdinal& page_ordinal);
+                            const syncer::StringOrdinal& page_ordinal,
+                            const std::string& install_parameter);
 
   // Called when an extension is uninstalled, so that prefs get cleaned up.
   void OnExtensionUninstalled(const std::string& extension_id,
@@ -305,6 +319,13 @@
   bool HasWipeoutBeenAcknowledged(const std::string& extension_id);
   void SetWipeoutAcknowledged(const std::string& extension_id, bool value);
 
+  // Whether the user has been notified about extension with |extension_id|
+  // taking over some aspect of the user's settings (homepage, startup pages,
+  // or search engine).
+  bool HasSettingsApiBubbleBeenAcknowledged(const std::string& extension_id);
+  void SetSettingsApiBubbleBeenAcknowledged(const std::string& extension_id,
+                                            bool value);
+
   // Returns true if the extension notification code has already run for the
   // first time for this profile. Currently we use this flag to mean that any
   // extensions that would trigger notifications should get silently
@@ -417,7 +438,8 @@
                              Extension::State initial_state,
                              bool blacklisted_for_malware,
                              DelayReason delay_reason,
-                             const syncer::StringOrdinal& page_ordinal);
+                             const syncer::StringOrdinal& page_ordinal,
+                             const std::string& install_parameter);
 
   // Removes any delayed install information we have for the given
   // |extension_id|. Returns true if there was info to remove; false otherwise.
@@ -437,6 +459,17 @@
   // information.
   scoped_ptr<ExtensionsInfo> GetAllDelayedInstallInfo() const;
 
+  // Returns information about evicted ephemeral apps.
+  scoped_ptr<ExtensionsInfo> GetEvictedEphemeralAppsInfo() const;
+
+  // Return information about a specific evicted ephemeral app. Can return NULL
+  // if no such evicted app exists or is currently installed.
+  scoped_ptr<ExtensionInfo> GetEvictedEphemeralAppInfo(
+      const std::string& extension_id) const;
+
+  // Permanently remove the preferences for an evicted ephemeral app.
+  void RemoveEvictedEphemeralApp(const std::string& extension_id);
+
   // Returns true if the user repositioned the app on the app launcher via drag
   // and drop.
   bool WasAppDraggedByUser(const std::string& extension_id);
@@ -480,7 +513,7 @@
 
   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
 
-  bool extensions_disabled() { return extensions_disabled_; }
+  bool extensions_disabled() const { return extensions_disabled_; }
 
   ContentSettingsStore* content_settings_store() {
     return content_settings_store_.get();
@@ -514,10 +547,21 @@
   const base::DictionaryValue* GetInstallSignature();
   void SetInstallSignature(const base::DictionaryValue* signature);
 
+  // The installation parameter associated with the extension.
+  std::string GetInstallParam(const std::string& extension_id) const;
+  void SetInstallParam(const std::string& extension_id,
+                       const std::string& install_parameter);
+
  private:
   friend class ExtensionPrefsBlacklistedExtensions;  // Unit test.
   friend class ExtensionPrefsUninstallExtension;     // Unit test.
 
+  enum DisableReasonChange {
+    DISABLE_REASON_ADD,
+    DISABLE_REASON_REMOVE,
+    DISABLE_REASON_CLEAR
+  };
+
   // See the Create methods.
   ExtensionPrefs(PrefService* prefs,
                  const base::FilePath& root_dir,
@@ -574,6 +618,14 @@
   // doesn't exist.
   const base::DictionaryValue* GetExtensionPref(const std::string& id) const;
 
+  // Modifies the extensions disable reasons to add a new reason, remove an
+  // existing reason, or clear all reasons. Notifies observers if the set of
+  // DisableReasons has changed.
+  // If |change| is DISABLE_REASON_CLEAR, then |reason| is ignored.
+  void ModifyDisableReason(const std::string& extension_id,
+                           Extension::DisableReason reason,
+                           DisableReasonChange change);
+
   // Fix missing preference entries in the extensions that are were introduced
   // in a later Chrome version.
   void FixMissingPrefs(const ExtensionIdList& extension_ids);
@@ -614,6 +666,7 @@
                                   const base::Time install_time,
                                   Extension::State initial_state,
                                   bool blacklisted_for_malware,
+                                  const std::string& install_parameter,
                                   base::DictionaryValue* extension_dict);
 
   // Helper function to complete initialization of the values in
@@ -646,6 +699,8 @@
 
   bool extensions_disabled_;
 
+  ObserverList<Observer> observer_list_;
+
   DISALLOW_COPY_AND_ASSIGN(ExtensionPrefs);
 };
 
diff --git a/extensions/browser/extension_registry.cc b/extensions/browser/extension_registry.cc
index 1d64ced..1f52ee1 100644
--- a/extensions/browser/extension_registry.cc
+++ b/extensions/browser/extension_registry.cc
@@ -36,6 +36,12 @@
   observers_.RemoveObserver(observer);
 }
 
+void ExtensionRegistry::TriggerOnLoaded(const Extension* extension) {
+  DCHECK(enabled_extensions_.Contains(extension->id()));
+  FOR_EACH_OBSERVER(
+      ExtensionRegistryObserver, observers_, OnExtensionLoaded(extension));
+}
+
 void ExtensionRegistry::TriggerOnUnloaded(const Extension* extension) {
   DCHECK(!enabled_extensions_.Contains(extension->id()));
   FOR_EACH_OBSERVER(
diff --git a/extensions/browser/extension_registry.h b/extensions/browser/extension_registry.h
index 9f2fae3..3030c07 100644
--- a/extensions/browser/extension_registry.h
+++ b/extensions/browser/extension_registry.h
@@ -65,6 +65,10 @@
   void AddObserver(ExtensionRegistryObserver* observer);
   void RemoveObserver(ExtensionRegistryObserver* observer);
 
+  // Invokes the observer method OnExtensionLoaded(). The extension must be
+  // enabled at the time of the call.
+  void TriggerOnLoaded(const Extension* extension);
+
   // Invokes the observer method OnExtensionUnloaded(). The extension must not
   // be enabled at the time of the call.
   void TriggerOnUnloaded(const Extension* extension);
diff --git a/extensions/browser/extension_registry_observer.h b/extensions/browser/extension_registry_observer.h
index 3382885..ae1281c 100644
--- a/extensions/browser/extension_registry_observer.h
+++ b/extensions/browser/extension_registry_observer.h
@@ -15,6 +15,10 @@
  public:
   virtual ~ExtensionRegistryObserver() {}
 
+  // Called after an extension is loaded. The extension will exclusively exist
+  // in the enabled_extensions set of ExtensionRegistry.
+  virtual void OnExtensionLoaded(const Extension* extension) {}
+
   // Called after an extension is unloaded. The extension no longer exists in
   // any of the ExtensionRegistry sets (enabled, disabled, etc.).
   virtual void OnExtensionUnloaded(const Extension* extension) {}
diff --git a/extensions/browser/extension_registry_unittest.cc b/extensions/browser/extension_registry_unittest.cc
index 075019b..7eaec65 100644
--- a/extensions/browser/extension_registry_unittest.cc
+++ b/extensions/browser/extension_registry_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/memory/ref_counted.h"
+#include "extensions/browser/extension_registry_observer.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -16,6 +17,44 @@
 
 typedef testing::Test ExtensionRegistryTest;
 
+testing::AssertionResult HasSingleExtension(
+    const ExtensionList& list,
+    const scoped_refptr<const Extension>& extension) {
+  if (list.empty())
+    return testing::AssertionFailure() << "No extensions in list";
+  if (list.size() > 1)
+    return testing::AssertionFailure() << list.size()
+                                       << " extensions, expected 1";
+  const Extension* did_load = list[0].get();
+  if (did_load != extension)
+    return testing::AssertionFailure() << "Expected " << extension->id()
+                                       << " found " << did_load->id();
+  return testing::AssertionSuccess();
+}
+
+class TestObserver : public ExtensionRegistryObserver {
+ public:
+  void Reset() {
+    loaded_.clear();
+    unloaded_.clear();
+  }
+
+  const ExtensionList& loaded() { return loaded_; }
+  const ExtensionList& unloaded() { return unloaded_; }
+
+ private:
+  virtual void OnExtensionLoaded(const Extension* extension) OVERRIDE {
+    loaded_.push_back(extension);
+  }
+
+  virtual void OnExtensionUnloaded(const Extension* extension) OVERRIDE {
+    unloaded_.push_back(extension);
+  }
+
+  ExtensionList loaded_;
+  ExtensionList unloaded_;
+};
+
 TEST_F(ExtensionRegistryTest, FillAndClearRegistry) {
   ExtensionRegistry registry;
   scoped_refptr<Extension> extension1 = test_util::CreateExtensionWithID("id1");
@@ -165,5 +204,33 @@
       "enabled", ExtensionRegistry::DISABLED | ExtensionRegistry::BLACKLISTED));
 }
 
+TEST_F(ExtensionRegistryTest, Observer) {
+  ExtensionRegistry registry;
+  TestObserver observer;
+  registry.AddObserver(&observer);
+
+  EXPECT_TRUE(observer.loaded().empty());
+  EXPECT_TRUE(observer.unloaded().empty());
+
+  scoped_refptr<const Extension> extension =
+      test_util::CreateExtensionWithID("id");
+
+  registry.AddEnabled(extension);
+  registry.TriggerOnLoaded(extension);
+
+  EXPECT_TRUE(HasSingleExtension(observer.loaded(), extension.get()));
+  EXPECT_TRUE(observer.unloaded().empty());
+  observer.Reset();
+
+  registry.RemoveEnabled(extension->id());
+  registry.TriggerOnUnloaded(extension);
+
+  EXPECT_TRUE(observer.loaded().empty());
+  EXPECT_TRUE(HasSingleExtension(observer.unloaded(), extension.get()));
+  observer.Reset();
+
+  registry.RemoveObserver(&observer);
+}
+
 }  // namespace
 }  // namespace extensions
diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc
index e64fff1..62ebed8 100644
--- a/extensions/browser/extension_web_contents_observer.cc
+++ b/extensions/browser/extension_web_contents_observer.cc
@@ -21,14 +21,15 @@
 ExtensionWebContentsObserver::ExtensionWebContentsObserver(
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
-      browser_context_(web_contents->GetBrowserContext()) {}
+      browser_context_(web_contents->GetBrowserContext()) {
+  NotifyRenderViewType(web_contents->GetRenderViewHost());
+}
 
 ExtensionWebContentsObserver::~ExtensionWebContentsObserver() {}
 
 void ExtensionWebContentsObserver::RenderViewCreated(
     content::RenderViewHost* render_view_host) {
-  render_view_host->Send(new ExtensionMsg_NotifyRenderViewType(
-      render_view_host->GetRoutingID(), GetViewType(web_contents())));
+  NotifyRenderViewType(render_view_host);
 
   const Extension* extension = GetExtension(render_view_host);
   if (!extension)
@@ -82,6 +83,14 @@
   }
 }
 
+void ExtensionWebContentsObserver::NotifyRenderViewType(
+    content::RenderViewHost* render_view_host) {
+  if (render_view_host) {
+    render_view_host->Send(new ExtensionMsg_NotifyRenderViewType(
+        render_view_host->GetRoutingID(), GetViewType(web_contents())));
+  }
+}
+
 const Extension* ExtensionWebContentsObserver::GetExtension(
     content::RenderViewHost* render_view_host) {
   std::string extension_id = GetExtensionId(render_view_host);
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h
index a366e43..5cb797b 100644
--- a/extensions/browser/extension_web_contents_observer.h
+++ b/extensions/browser/extension_web_contents_observer.h
@@ -45,6 +45,9 @@
   // NULL if the render view host is not for a valid extension.
   const Extension* GetExtension(content::RenderViewHost* render_view_host);
 
+  // Updates ViewType for RenderViewHost based on GetViewType(web_contents()).
+  void NotifyRenderViewType(content::RenderViewHost* render_view_host);
+
   // Returns the extension or app ID associated with a render view host. Returns
   // the empty string if the render view host is not for a valid extension.
   static std::string GetExtensionId(content::RenderViewHost* render_view_host);
diff --git a/extensions/browser/external_provider_interface.h b/extensions/browser/external_provider_interface.h
index 5c96773..dd80e31 100644
--- a/extensions/browser/external_provider_interface.h
+++ b/extensions/browser/external_provider_interface.h
@@ -46,6 +46,7 @@
     // location.
     virtual bool OnExternalExtensionUpdateUrlFound(
         const std::string& id,
+        const std::string& install_parameter,
         const GURL& update_url,
         Manifest::Location location,
         int creation_flags,
diff --git a/extensions/browser/info_map.cc b/extensions/browser/info_map.cc
index 7122eb0..408b4f1 100644
--- a/extensions/browser/info_map.cc
+++ b/extensions/browser/info_map.cc
@@ -16,9 +16,7 @@
 
 namespace {
 
-void CheckOnValidThread() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
-}
+void CheckOnValidThread() { DCHECK_CURRENTLY_ON(BrowserThread::IO); }
 
 }  // namespace
 
diff --git a/extensions/browser/value_store/leveldb_value_store.cc b/extensions/browser/value_store/leveldb_value_store.cc
index 58a8cb5..0f09f5b 100644
--- a/extensions/browser/value_store/leveldb_value_store.cc
+++ b/extensions/browser/value_store/leveldb_value_store.cc
@@ -48,7 +48,7 @@
 
 LeveldbValueStore::LeveldbValueStore(const base::FilePath& db_path)
     : db_path_(db_path) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<Error> open_error = EnsureDbIsOpen();
   if (open_error)
@@ -56,7 +56,7 @@
 }
 
 LeveldbValueStore::~LeveldbValueStore() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   // Delete the database from disk if it's empty (but only if we managed to
   // open it!). This is safe on destruction, assuming that we have exclusive
@@ -85,7 +85,7 @@
 }
 
 ValueStore::ReadResult LeveldbValueStore::Get(const std::string& key) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<Error> open_error = EnsureDbIsOpen();
   if (open_error)
@@ -104,7 +104,7 @@
 
 ValueStore::ReadResult LeveldbValueStore::Get(
     const std::vector<std::string>& keys) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<Error> open_error = EnsureDbIsOpen();
   if (open_error)
@@ -131,7 +131,7 @@
 }
 
 ValueStore::ReadResult LeveldbValueStore::Get() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<Error> open_error = EnsureDbIsOpen();
   if (open_error)
@@ -169,7 +169,7 @@
 
 ValueStore::WriteResult LeveldbValueStore::Set(
     WriteOptions options, const std::string& key, const base::Value& value) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<Error> open_error = EnsureDbIsOpen();
   if (open_error)
@@ -189,7 +189,7 @@
 
 ValueStore::WriteResult LeveldbValueStore::Set(
     WriteOptions options, const base::DictionaryValue& settings) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<Error> open_error = EnsureDbIsOpen();
   if (open_error)
@@ -212,13 +212,13 @@
 }
 
 ValueStore::WriteResult LeveldbValueStore::Remove(const std::string& key) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   return Remove(std::vector<std::string>(1, key));
 }
 
 ValueStore::WriteResult LeveldbValueStore::Remove(
     const std::vector<std::string>& keys) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<Error> open_error = EnsureDbIsOpen();
   if (open_error)
@@ -248,7 +248,7 @@
 }
 
 ValueStore::WriteResult LeveldbValueStore::Clear() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList());
 
@@ -270,7 +270,7 @@
 }
 
 bool LeveldbValueStore::Restore() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   ReadResult result = Get();
   std::string previous_key;
@@ -297,7 +297,7 @@
 }
 
 bool LeveldbValueStore::RestoreKey(const std::string& key) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   ReadResult result = Get(key);
   if (result->IsCorrupted()) {
@@ -319,7 +319,7 @@
 }
 
 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
 
   if (db_)
     return util::NoError();
@@ -343,7 +343,7 @@
     leveldb::ReadOptions options,
     const std::string& key,
     scoped_ptr<base::Value>* setting) {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   DCHECK(setting);
 
   std::string value_as_json;
@@ -405,7 +405,7 @@
 }
 
 bool LeveldbValueStore::IsEmpty() {
-  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+  DCHECK_CURRENTLY_ON(BrowserThread::FILE);
   scoped_ptr<leveldb::Iterator> it(db_->NewIterator(leveldb::ReadOptions()));
 
   it->SeekToFirst();
diff --git a/extensions/browser/value_store/value_store_frontend.cc b/extensions/browser/value_store/value_store_frontend.cc
index 6ef11cc..73b6aff 100644
--- a/extensions/browser/value_store/value_store_frontend.cc
+++ b/extensions/browser/value_store/value_store_frontend.cc
@@ -18,7 +18,7 @@
   Backend() : storage_(NULL) {}
 
   void Init(const base::FilePath& db_path) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+    DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     DCHECK(!storage_);
     TRACE_EVENT0("ValueStoreFrontend::Backend", "Init");
     db_path_ = db_path;
@@ -27,14 +27,14 @@
 
   // This variant is useful for testing (using a mock ValueStore).
   void InitWithStore(scoped_ptr<ValueStore> storage) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+    DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     DCHECK(!storage_);
     storage_ = storage.release();
   }
 
   void Get(const std::string& key,
            const ValueStoreFrontend::ReadCallback& callback) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+    DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     ValueStore::ReadResult result = storage_->Get(key);
 
     // Extract the value from the ReadResult and pass ownership of it to the
@@ -53,14 +53,14 @@
   }
 
   void Set(const std::string& key, scoped_ptr<base::Value> value) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+    DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     // We don't need the old value, so skip generating changes.
     storage_->Set(ValueStore::IGNORE_QUOTA | ValueStore::NO_GENERATE_CHANGES,
                   key, *value.get());
   }
 
   void Remove(const std::string& key) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+    DCHECK_CURRENTLY_ON(BrowserThread::FILE);
     storage_->Remove(key);
   }
 
@@ -77,7 +77,7 @@
 
   void RunCallback(const ValueStoreFrontend::ReadCallback& callback,
                    scoped_ptr<base::Value> value) {
-    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     callback.Run(value.Pass());
   }
 
diff --git a/extensions/common/DEPS b/extensions/common/DEPS
index c75b833..12baab5 100644
--- a/extensions/common/DEPS
+++ b/extensions/common/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+device/usb",
   "+net",
   "+third_party/re2",
 
@@ -9,8 +10,6 @@
   #
   # TODO(benwells): Remove these. http://crbug.com/162530
   "+chrome/common/extensions/api/generated_schemas.h",
-  "+chrome/common/extensions/api/messaging/message.h",
-  "+chrome/common/extensions/permissions",
   "+grit/chromium_strings.h",
   "+grit/common_resources.h",
   "+grit/extensions_api_resources.h",
diff --git a/extensions/common/api/api.gyp b/extensions/common/api/api.gyp
index 8297269..fb3c2b9 100644
--- a/extensions/common/api/api.gyp
+++ b/extensions/common/api/api.gyp
@@ -22,6 +22,7 @@
         ],
         # TODO: Eliminate these on Android. See crbug.com/305852.
         'schema_files': [
+          'dns.idl',
           'socket.idl',
           'sockets_tcp.idl',
           'sockets_tcp_server.idl',
diff --git a/extensions/common/api/dns.idl b/extensions/common/api/dns.idl
new file mode 100644
index 0000000..0500c0f
--- /dev/null
+++ b/extensions/common/api/dns.idl
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Use the <code>chrome.dns</code> API for dns resolution.
+namespace dns {
+
+  dictionary ResolveCallbackResolveInfo {
+    // The result code. Zero indicates success.
+    long resultCode;
+
+    // A string representing the IP address literal. Supplied only if resultCode
+    // indicates success. Note that we presently return only IPv4 addresses.
+    DOMString? address;
+  };
+
+  callback ResolveCallback = void (ResolveCallbackResolveInfo resolveInfo);
+
+  interface Functions {
+    // Resolves the given hostname or IP address literal.
+    // |hostname| : The hostname to resolve.
+    // |callback| : Called when the resolution operation completes.
+    static void resolve(DOMString hostname,
+                        ResolveCallback callback);
+  };
+
+};
diff --git a/extensions/common/api/messaging/message.h b/extensions/common/api/messaging/message.h
new file mode 100644
index 0000000..64ecb82
--- /dev/null
+++ b/extensions/common/api/messaging/message.h
@@ -0,0 +1,22 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_API_MESSAGING_MESSAGE_H_
+#define EXTENSIONS_COMMON_API_MESSAGING_MESSAGE_H_
+
+namespace extensions {
+
+// A message consists of both the data itself as well as a user gesture state.
+struct Message {
+  std::string data;
+  bool user_gesture;
+
+  Message() : data(), user_gesture(false) {}
+  Message(const std::string& data, bool user_gesture)
+      : data(data), user_gesture(user_gesture) {}
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_API_MESSAGING_MESSAGE_H_
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc
index 9bdd1e4..002bbb3 100644
--- a/extensions/common/extension_api.cc
+++ b/extensions/common/extension_api.cc
@@ -232,13 +232,11 @@
   CHECK(unloaded_schemas_.empty());
   RegisterSchemaResource("app", IDR_EXTENSION_API_JSON_APP);
   RegisterSchemaResource("browserAction", IDR_EXTENSION_API_JSON_BROWSERACTION);
-  RegisterSchemaResource("browsingData", IDR_EXTENSION_API_JSON_BROWSINGDATA);
   RegisterSchemaResource("commands", IDR_EXTENSION_API_JSON_COMMANDS);
   RegisterSchemaResource("declarativeContent",
       IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT);
   RegisterSchemaResource("declarativeWebRequest",
       IDR_EXTENSION_API_JSON_DECLARATIVE_WEBREQUEST);
-  RegisterSchemaResource("runtime", IDR_EXTENSION_API_JSON_RUNTIME);
   RegisterSchemaResource("fileBrowserHandler",
       IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER);
   RegisterSchemaResource("inputMethodPrivate",
@@ -256,12 +254,8 @@
   RegisterSchemaResource("webRequestInternal",
       IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL);
   RegisterSchemaResource("webstore", IDR_EXTENSION_API_JSON_WEBSTORE);
-  RegisterSchemaResource("webstorePrivate",
-      IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE);
   RegisterSchemaResource("webViewRequest",
       IDR_EXTENSION_API_JSON_WEBVIEW_REQUEST);
-  RegisterSchemaResource("contextMenusInternal",
-                         IDR_EXTENSION_API_JSON_CONTEXTMENUSINTERNAL);
 
   default_configuration_initialized_ = true;
 }
diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h
index f5c2817..aa69efa 100644
--- a/extensions/common/extension_messages.h
+++ b/extensions/common/extension_messages.h
@@ -10,16 +10,16 @@
 
 #include "base/memory/shared_memory.h"
 #include "base/values.h"
-#include "chrome/common/extensions/api/messaging/message.h"
-#include "chrome/common/extensions/permissions/media_galleries_permission_data.h"
-#include "chrome/common/extensions/permissions/socket_permission_data.h"
-#include "chrome/common/extensions/permissions/usb_device_permission_data.h"
 #include "content/public/common/common_param_traits.h"
 #include "content/public/common/socket_permission_request.h"
+#include "extensions/common/api/messaging/message.h"
 #include "extensions/common/draggable_region.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extensions_client.h"
+#include "extensions/common/permissions/media_galleries_permission_data.h"
 #include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/permissions/socket_permission_data.h"
+#include "extensions/common/permissions/usb_device_permission_data.h"
 #include "extensions/common/url_pattern.h"
 #include "extensions/common/url_pattern_set.h"
 #include "extensions/common/view_type.h"
@@ -407,13 +407,6 @@
 IPC_MESSAGE_CONTROL1(ExtensionMsg_CancelSuspend,
                      std::string /* extension_id */)
 
-// Send to renderer once the installation mentioned on
-// ExtensionHostMsg_InlineWebstoreInstall is complete.
-IPC_MESSAGE_ROUTED3(ExtensionMsg_InlineWebstoreInstallResponse,
-                    int32 /* install id */,
-                    bool /* whether the install was successful */,
-                    std::string /* error */)
-
 // Response to the renderer for ExtensionHostMsg_GetAppInstallState.
 IPC_MESSAGE_ROUTED2(ExtensionMsg_GetAppInstallStateResponse,
                     std::string /* state */,
@@ -573,13 +566,6 @@
                     int32 /* page_id of the _topmost_ frame */,
                     GURL /* url of the _topmost_ frame */)
 
-// Sent by the renderer to implement chrome.webstore.install().
-IPC_MESSAGE_ROUTED4(ExtensionHostMsg_InlineWebstoreInstall,
-                    int32 /* install id */,
-                    int32 /* return route id */,
-                    std::string /* Web Store item ID */,
-                    GURL /* requestor URL */)
-
 // Sent by the renderer when a web page is checking if its app is installed.
 IPC_MESSAGE_ROUTED3(ExtensionHostMsg_GetAppInstallState,
                     GURL /* requestor_url */,
diff --git a/extensions/common/feature_switch.cc b/extensions/common/feature_switch.cc
index 83a4107..e97f270 100644
--- a/extensions/common/feature_switch.cc
+++ b/extensions/common/feature_switch.cc
@@ -25,7 +25,11 @@
             FeatureSwitch::DEFAULT_DISABLED),
         global_commands(
             switches::kGlobalCommands,
+#if defined(OS_CHROMEOS)
             FeatureSwitch::DEFAULT_DISABLED),
+#else
+            FeatureSwitch::DEFAULT_ENABLED),
+#endif
         prompt_for_external_extensions(
             NULL,
 #if defined(OS_WIN)
diff --git a/extensions/common/manifest_constants.cc b/extensions/common/manifest_constants.cc
index 4b6017b..e0433b3 100644
--- a/extensions/common/manifest_constants.cc
+++ b/extensions/common/manifest_constants.cc
@@ -17,7 +17,7 @@
 const char kBackgroundPersistent[] = "background.persistent";
 const char kBackgroundScripts[] = "background.scripts";
 const char kBluetooth[] = "bluetooth";
-const char kBookmarkUI[] = "chrome_ui_overrides.bookmarks_ui";
+const char kBookmarkUI[] = "bookmarks_ui";
 const char kBrowserAction[] = "browser_action";
 const char kChromeURLOverrides[] = "chrome_url_overrides";
 const char kCommands[] = "commands";
@@ -92,6 +92,10 @@
 const char kOmniboxKeyword[] = "omnibox.keyword";
 const char kOptionalPermissions[] = "optional_permissions";
 const char kOptionsPage[] = "options_page";
+const char kOverrideHomepage[] = "chrome_settings_overrides.homepage";
+const char kOverrideSearchProvider[] =
+    "chrome_settings_overrides.search_provider";
+const char kOverrideStartupPage[] = "chrome_settings_overrides.startup_pages";
 const char kPageAction[] = "page_action";
 const char kPageActionDefaultIcon[] = "default_icon";
 const char kPageActionDefaultPopup[] = "default_popup";
@@ -119,7 +123,6 @@
 const char kSandboxedPages[] = "sandbox.pages";
 const char kSandboxedPagesCSP[] = "sandbox.content_security_policy";
 const char kScriptBadge[] = "script_badge";
-const char kSearchProvider[] = "chrome_settings_overrides.search_provider";
 const char kSettingsOverride[] = "chrome_settings_overrides";
 const char kSettingsOverrideAlternateUrls[] =
     "chrome_settings_overrides.search_provider.alternate_urls";
diff --git a/extensions/common/manifest_constants.h b/extensions/common/manifest_constants.h
index ac14f5c..398b082 100644
--- a/extensions/common/manifest_constants.h
+++ b/extensions/common/manifest_constants.h
@@ -101,6 +101,9 @@
 extern const char kOmniboxKeyword[];
 extern const char kOptionalPermissions[];
 extern const char kOptionsPage[];
+extern const char kOverrideHomepage[];
+extern const char kOverrideSearchProvider[];
+extern const char kOverrideStartupPage[];
 extern const char kPageAction[];
 extern const char kPageActionDefaultIcon[];
 extern const char kPageActionDefaultPopup[];
@@ -128,7 +131,6 @@
 extern const char kSandboxedPages[];
 extern const char kSandboxedPagesCSP[];
 extern const char kScriptBadge[];
-extern const char kSearchProvider[];
 extern const char kSettingsOverride[];
 extern const char kSettingsOverrideAlternateUrls[];
 extern const char kShiftKey[];
diff --git a/extensions/common/permissions/PRESUBMIT.py b/extensions/common/permissions/PRESUBMIT.py
new file mode 100644
index 0000000..96aa267
--- /dev/null
+++ b/extensions/common/permissions/PRESUBMIT.py
@@ -0,0 +1,32 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Chromium presubmit script for src/extensions/common/permissions.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details on the presubmit API built into gcl.
+"""
+import sys
+
+def GetPreferredTrySlaves():
+  return ['linux_chromeos']
+
+def _CreatePermissionMessageEnumChecker(input_api, output_api):
+  original_sys_path = sys.path
+
+  try:
+    sys.path.append(input_api.os_path.join(
+        input_api.PresubmitLocalPath(), '..', '..', '..', 'tools',
+        'strict_enum_value_checker'))
+    from strict_enum_value_checker import StrictEnumValueChecker
+  finally:
+    sys.path = original_sys_path
+
+  return StrictEnumValueChecker(input_api, output_api,
+      start_marker='  enum ID {', end_marker='    kEnumBoundary',
+      path='extensions/common/permissions/permission_message.h')
+
+def CheckChangeOnUpload(input_api, output_api):
+    return _CreatePermissionMessageEnumChecker(input_api, output_api).Run()
+
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h
index b6933c2..6366756 100644
--- a/extensions/common/permissions/api_permission.h
+++ b/extensions/common/permissions/api_permission.h
@@ -35,6 +35,8 @@
     kUnknown = -1,
 
     // Real permissions.
+    kAccessibilityFeaturesModify,
+    kAccessibilityFeaturesRead,
     kActiveTab,
     kActivityLogPrivate,
     kAdView,
diff --git a/extensions/common/permissions/media_galleries_permission.cc b/extensions/common/permissions/media_galleries_permission.cc
new file mode 100644
index 0000000..baf7162
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission.cc
@@ -0,0 +1,157 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/media_galleries_permission.h"
+
+#include <set>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace {
+
+// copyTo permission requires delete permission as a prerequisite.
+// delete permission requires read permission as a prerequisite.
+bool IsValidPermissionSet(bool has_read, bool has_copy_to, bool has_delete,
+                          std::string* error) {
+  if (has_copy_to) {
+    if (has_read && has_delete)
+      return true;
+    if (error)
+      *error = "copyTo permission requires read and delete permissions";
+    return false;
+  }
+  if (has_delete) {
+    if (has_read)
+      return true;
+    if (error)
+      *error = "delete permission requires read permission";
+    return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+namespace extensions {
+
+const char MediaGalleriesPermission::kAllAutoDetectedPermission[] =
+    "allAutoDetected";
+const char MediaGalleriesPermission::kScanPermission[] = "scan";
+const char MediaGalleriesPermission::kReadPermission[] = "read";
+const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo";
+const char MediaGalleriesPermission::kDeletePermission[] = "delete";
+
+MediaGalleriesPermission::MediaGalleriesPermission(
+    const APIPermissionInfo* info)
+  : SetDisjunctionPermission<MediaGalleriesPermissionData,
+                             MediaGalleriesPermission>(info) {
+}
+
+MediaGalleriesPermission::~MediaGalleriesPermission() {
+}
+
+bool MediaGalleriesPermission::FromValue(const base::Value* value,
+                                         std::string* error) {
+  if (!SetDisjunctionPermission<MediaGalleriesPermissionData,
+                                MediaGalleriesPermission>::FromValue(value,
+                                                                     error)) {
+    return false;
+  }
+
+  bool has_read = false;
+  bool has_copy_to = false;
+  bool has_delete = false;
+  for (std::set<MediaGalleriesPermissionData>::const_iterator it =
+      data_set_.begin(); it != data_set_.end(); ++it) {
+    if (it->permission() == kAllAutoDetectedPermission ||
+        it->permission() == kScanPermission) {
+      continue;
+    }
+    if (it->permission() == kReadPermission) {
+      has_read = true;
+      continue;
+    }
+    if (it->permission() == kCopyToPermission) {
+      has_copy_to = true;
+      continue;
+    }
+    if (it->permission() == kDeletePermission) {
+      has_delete = true;
+      continue;
+    }
+
+    // No other permissions, so reaching this means
+    // MediaGalleriesPermissionData is probably out of sync in some way.
+    // Fail so developers notice this.
+    NOTREACHED();
+    return false;
+  }
+
+  return IsValidPermissionSet(has_read, has_copy_to, has_delete, error);
+}
+
+PermissionMessages MediaGalleriesPermission::GetMessages() const {
+  DCHECK(HasMessages());
+  PermissionMessages result;
+
+  bool has_all_auto_detected = false;
+  bool has_read = false;
+  bool has_copy_to = false;
+  bool has_delete = false;
+
+  for (std::set<MediaGalleriesPermissionData>::const_iterator it =
+      data_set_.begin(); it != data_set_.end(); ++it) {
+    if (it->permission() == kAllAutoDetectedPermission)
+      has_all_auto_detected = true;
+    else if (it->permission() == kReadPermission)
+      has_read = true;
+    else if (it->permission() == kCopyToPermission)
+      has_copy_to = true;
+    else if (it->permission() == kDeletePermission)
+      has_delete = true;
+  }
+
+  if (!IsValidPermissionSet(has_read, has_copy_to, has_delete, NULL)) {
+    NOTREACHED();
+    return result;
+  }
+
+  // If |has_all_auto_detected| is false, then Chrome will prompt the user at
+  // runtime when the extension call the getMediaGalleries API.
+  if (!has_all_auto_detected)
+    return result;
+  // No access permission case.
+  if (!has_read)
+    return result;
+
+  // Separate PermissionMessage IDs for read, copyTo, and delete. Otherwise an
+  // extension can silently gain new access capabilities.
+  result.push_back(PermissionMessage(
+      PermissionMessage::kMediaGalleriesAllGalleriesRead,
+      l10n_util::GetStringUTF16(
+          IDS_EXTENSION_PROMPT_WARNING_MEDIA_GALLERIES_READ)));
+
+  // For copyTo and delete, the proper combined permission message will be
+  // derived in ChromePermissionMessageProvider::GetWarningMessages(), such
+  // that the user get 1 entry for all media galleries access permissions,
+  // rather than several separate entries.
+  if (has_copy_to) {
+    result.push_back(PermissionMessage(
+        PermissionMessage::kMediaGalleriesAllGalleriesCopyTo,
+        base::string16()));
+  }
+  if (has_delete) {
+    result.push_back(PermissionMessage(
+        PermissionMessage::kMediaGalleriesAllGalleriesDelete,
+        base::string16()));
+  }
+  return result;
+}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/media_galleries_permission.h b/extensions/common/permissions/media_galleries_permission.h
new file mode 100644
index 0000000..36b6dba
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission.h
@@ -0,0 +1,56 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
+
+#include "base/basictypes.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/media_galleries_permission_data.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+
+namespace extensions {
+
+// Media Galleries permissions are as follows:
+//   <media-galleries-permission-pattern>
+//             := <access> | <access> 'allAutoDetected' | 'allAutoDetected' |
+//                <access> 'scan' | 'scan'
+//   <access>  := 'read' | 'read' <access> | 'read' <secondary-access>
+//   <secondary-access>
+//             := 'delete' | 'delete' <secondary-access> |
+//                'delete' <tertiary-access>
+//   <tertiary-access>
+//             := 'copyTo' | 'copyTo' <tertiary-access>
+class MediaGalleriesPermission
+  : public SetDisjunctionPermission<MediaGalleriesPermissionData,
+                                    MediaGalleriesPermission> {
+ public:
+  struct CheckParam : public APIPermission::CheckParam {
+    explicit CheckParam(const std::string& permission)
+      : permission(permission) {}
+    const std::string permission;
+  };
+
+  explicit MediaGalleriesPermission(const APIPermissionInfo* info);
+  virtual ~MediaGalleriesPermission();
+
+  // SetDisjunctionPermission overrides.
+  // MediaGalleriesPermission does additional checks to make sure the
+  // permissions do not contain unknown values.
+  virtual bool FromValue(const base::Value* value, std::string* error) OVERRIDE;
+
+  // APIPermission overrides.
+  virtual PermissionMessages GetMessages() const OVERRIDE;
+
+  // Permission strings.
+  static const char kAllAutoDetectedPermission[];
+  static const char kScanPermission[];
+  static const char kReadPermission[];
+  static const char kCopyToPermission[];
+  static const char kDeletePermission[];
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_H_
diff --git a/extensions/common/permissions/media_galleries_permission_data.cc b/extensions/common/permissions/media_galleries_permission_data.cc
new file mode 100644
index 0000000..d7e7937
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission_data.cc
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/media_galleries_permission_data.h"
+
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "extensions/common/permissions/media_galleries_permission.h"
+
+namespace extensions {
+
+MediaGalleriesPermissionData::MediaGalleriesPermissionData() {
+}
+
+bool MediaGalleriesPermissionData::Check(
+    const APIPermission::CheckParam* param) const {
+  if (!param)
+    return false;
+
+  const MediaGalleriesPermission::CheckParam& specific_param =
+      *static_cast<const MediaGalleriesPermission::CheckParam*>(param);
+  return permission_ == specific_param.permission;
+}
+
+scoped_ptr<base::Value> MediaGalleriesPermissionData::ToValue() const {
+  return scoped_ptr<base::Value>(new base::StringValue(permission_));
+}
+
+bool MediaGalleriesPermissionData::FromValue(const base::Value* value) {
+  if (!value)
+    return false;
+
+  std::string raw_permission;
+  if (!value->GetAsString(&raw_permission))
+    return false;
+
+  std::string permission;
+  base::TrimWhitespaceASCII(raw_permission, base::TRIM_ALL, &permission);
+
+  if (permission == MediaGalleriesPermission::kAllAutoDetectedPermission ||
+      permission == MediaGalleriesPermission::kScanPermission ||
+      permission == MediaGalleriesPermission::kReadPermission ||
+      permission == MediaGalleriesPermission::kCopyToPermission ||
+      permission == MediaGalleriesPermission::kDeletePermission) {
+    permission_ = permission;
+    return true;
+  }
+  return false;
+}
+
+bool MediaGalleriesPermissionData::operator<(
+    const MediaGalleriesPermissionData& rhs) const {
+  return permission_ < rhs.permission_;
+}
+
+bool MediaGalleriesPermissionData::operator==(
+    const MediaGalleriesPermissionData& rhs) const {
+  return permission_ == rhs.permission_;
+}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/media_galleries_permission_data.h b/extensions/common/permissions/media_galleries_permission_data.h
new file mode 100644
index 0000000..920a905
--- /dev/null
+++ b/extensions/common/permissions/media_galleries_permission_data.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "extensions/common/permissions/api_permission.h"
+
+namespace base {
+class Value;
+}
+
+namespace extensions {
+
+// A MediaGalleriesPermissionData instance represents a single part of the
+// MediaGalleriesPermission. e.g. "read" or "allAutoDetected".
+class MediaGalleriesPermissionData {
+ public:
+  MediaGalleriesPermissionData();
+
+  // Check if |param| (which must be a MediaGalleriesPermission::CheckParam)
+  // matches the encapsulated attribute.
+  bool Check(const APIPermission::CheckParam* param) const;
+
+  // Convert |this| into a base::Value.
+  scoped_ptr<base::Value> ToValue() const;
+
+  // Populate |this| from a base::Value.
+  bool FromValue(const base::Value* value);
+
+  bool operator<(const MediaGalleriesPermissionData& rhs) const;
+  bool operator==(const MediaGalleriesPermissionData& rhs) const;
+
+  std::string permission() const { return permission_; }
+
+  // This accessor is provided for IPC_STRUCT_TRAITS_MEMBER.  Please think
+  // twice before using it for anything else.
+  std::string& permission() { return permission_; }
+
+ private:
+  std::string permission_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_MEDIA_GALLERIES_PERMISSION_DATA_H_
diff --git a/extensions/common/permissions/permission_message.h b/extensions/common/permissions/permission_message.h
index e7cbbf1..bd5269b 100644
--- a/extensions/common/permissions/permission_message.h
+++ b/extensions/common/permissions/permission_message.h
@@ -82,6 +82,8 @@
     kScreenlockPrivate,
     kOverrideBookmarksUI,
     kAutomation,
+    kAccessibilityFeaturesModify,
+    kAccessibilityFeaturesRead,
     kEnumBoundary,
   };
   COMPILE_ASSERT(PermissionMessage::kNone > PermissionMessage::kUnknown,
diff --git a/extensions/common/permissions/permission_message_util.cc b/extensions/common/permissions/permission_message_util.cc
new file mode 100644
index 0000000..76d1c61
--- /dev/null
+++ b/extensions/common/permissions/permission_message_util.cc
@@ -0,0 +1,150 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/permission_message_util.h"
+
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/url_constants.h"
+#include "extensions/common/permissions/permission_message.h"
+#include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/url_pattern_set.h"
+#include "grit/generated_resources.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "ui/base/l10n/l10n_util.h"
+
+using extensions::PermissionMessage;
+using extensions::PermissionSet;
+using extensions::URLPatternSet;
+
+namespace {
+
+// Helper for GetDistinctHosts(): com > net > org > everything else.
+bool RcdBetterThan(const std::string& a, const std::string& b) {
+  if (a == b)
+    return false;
+  if (a == "com")
+    return true;
+  if (a == "net")
+    return b != "com";
+  if (a == "org")
+    return b != "com" && b != "net";
+  return false;
+}
+
+}  // namespace
+
+namespace permission_message_util {
+
+PermissionMessage CreateFromHostList(const std::set<std::string>& hosts) {
+  std::vector<std::string> host_list(hosts.begin(), hosts.end());
+  DCHECK(host_list.size());
+  PermissionMessage::ID message_id;
+  base::string16 message;
+  base::string16 details;
+
+  switch (host_list.size()) {
+    case 1:
+      message_id = PermissionMessage::kHosts1;
+      message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_1_HOST,
+                                           base::UTF8ToUTF16(host_list[0]));
+      break;
+    case 2:
+      message_id = PermissionMessage::kHosts2;
+      message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_2_HOSTS,
+                                           base::UTF8ToUTF16(host_list[0]),
+                                           base::UTF8ToUTF16(host_list[1]));
+      break;
+    case 3:
+      message_id = PermissionMessage::kHosts3;
+      message = l10n_util::GetStringFUTF16(IDS_EXTENSION_PROMPT_WARNING_3_HOSTS,
+                                           base::UTF8ToUTF16(host_list[0]),
+                                           base::UTF8ToUTF16(host_list[1]),
+                                           base::UTF8ToUTF16(host_list[2]));
+      break;
+    default:
+      message_id = PermissionMessage::kHosts4OrMore;
+
+      const int kRetainedFilesMessageIDs[6] = {
+          IDS_EXTENSION_PROMPT_WARNING_HOSTS_DEFAULT,
+          IDS_EXTENSION_PROMPT_WARNING_HOST_SINGULAR,
+          IDS_EXTENSION_PROMPT_WARNING_HOSTS_ZERO,
+          IDS_EXTENSION_PROMPT_WARNING_HOSTS_TWO,
+          IDS_EXTENSION_PROMPT_WARNING_HOSTS_FEW,
+          IDS_EXTENSION_PROMPT_WARNING_HOSTS_MANY, };
+      std::vector<int> message_ids;
+      for (size_t i = 0; i < arraysize(kRetainedFilesMessageIDs); i++) {
+        message_ids.push_back(kRetainedFilesMessageIDs[i]);
+      }
+      message = l10n_util::GetPluralStringFUTF16(message_ids, host_list.size());
+
+      for (size_t i = 0; i < host_list.size(); ++i) {
+        if (i > 0)
+          details += base::ASCIIToUTF16("\n");
+        details += l10n_util::GetStringFUTF16(
+            IDS_EXTENSION_PROMPT_WARNING_HOST_LIST_ENTRY,
+            base::UTF8ToUTF16(host_list[i]));
+      }
+  }
+
+  return PermissionMessage(message_id, message, details);
+}
+
+std::set<std::string> GetDistinctHosts(const URLPatternSet& host_patterns,
+                                       bool include_rcd,
+                                       bool exclude_file_scheme) {
+  // Use a vector to preserve order (also faster than a map on small sets).
+  // Each item is a host split into two parts: host without RCDs and
+  // current best RCD.
+  typedef std::vector<std::pair<std::string, std::string> > HostVector;
+  HostVector hosts_best_rcd;
+  for (URLPatternSet::const_iterator i = host_patterns.begin();
+       i != host_patterns.end();
+       ++i) {
+    if (exclude_file_scheme && i->scheme() == content::kFileScheme)
+      continue;
+
+    std::string host = i->host();
+
+    // Add the subdomain wildcard back to the host, if necessary.
+    if (i->match_subdomains())
+      host = "*." + host;
+
+    // If the host has an RCD, split it off so we can detect duplicates.
+    std::string rcd;
+    size_t reg_len = net::registry_controlled_domains::GetRegistryLength(
+        host,
+        net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
+        net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+    if (reg_len && reg_len != std::string::npos) {
+      if (include_rcd)  // else leave rcd empty
+        rcd = host.substr(host.size() - reg_len);
+      host = host.substr(0, host.size() - reg_len);
+    }
+
+    // Check if we've already seen this host.
+    HostVector::iterator it = hosts_best_rcd.begin();
+    for (; it != hosts_best_rcd.end(); ++it) {
+      if (it->first == host)
+        break;
+    }
+    // If this host was found, replace the RCD if this one is better.
+    if (it != hosts_best_rcd.end()) {
+      if (include_rcd && RcdBetterThan(rcd, it->second))
+        it->second = rcd;
+    } else {  // Previously unseen host, append it.
+      hosts_best_rcd.push_back(std::make_pair(host, rcd));
+    }
+  }
+
+  // Build up the final vector by concatenating hosts and RCDs.
+  std::set<std::string> distinct_hosts;
+  for (HostVector::iterator it = hosts_best_rcd.begin();
+       it != hosts_best_rcd.end();
+       ++it)
+    distinct_hosts.insert(it->first + it->second);
+  return distinct_hosts;
+}
+
+}  // namespace permission_message_util
diff --git a/extensions/common/permissions/permission_message_util.h b/extensions/common/permissions/permission_message_util.h
new file mode 100644
index 0000000..410e1a2
--- /dev/null
+++ b/extensions/common/permissions/permission_message_util.h
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
+
+#include <set>
+#include <string>
+
+namespace extensions {
+class PermissionMessage;
+class PermissionSet;
+class URLPatternSet;
+}
+
+namespace permission_message_util {
+
+// Creates the corresponding permission message for a list of hosts.
+// The messages change depending on what hosts are present.
+extensions::PermissionMessage CreateFromHostList(
+    const std::set<std::string>& hosts);
+
+std::set<std::string> GetDistinctHosts(
+    const extensions::URLPatternSet& host_patterns,
+    bool include_rcd,
+    bool exclude_file_scheme);
+
+}  // namespace permission_message_util
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_PERMISSION_MESSAGE_UTIL_H_
diff --git a/extensions/common/permissions/permissions_data_unittest.cc b/extensions/common/permissions/permissions_data_unittest.cc
index fda57f9..2ebc9ba 100644
--- a/extensions/common/permissions/permissions_data_unittest.cc
+++ b/extensions/common/permissions/permissions_data_unittest.cc
@@ -11,7 +11,6 @@
 #include "chrome/common/chrome_version_info.h"
 #include "chrome/common/extensions/extension_test_util.h"
 #include "chrome/common/extensions/features/feature_channel.h"
-#include "chrome/common/extensions/permissions/socket_permission.h"
 #include "content/public/common/socket_permission_request.h"
 #include "extensions/common/error_utils.h"
 #include "extensions/common/extension.h"
@@ -20,6 +19,7 @@
 #include "extensions/common/permissions/api_permission.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/permissions/socket_permission.h"
 #include "extensions/common/switches.h"
 #include "extensions/common/url_pattern_set.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/extensions/common/permissions/set_disjunction_permission.h b/extensions/common/permissions/set_disjunction_permission.h
new file mode 100644
index 0000000..3a3e9c5
--- /dev/null
+++ b/extensions/common/permissions/set_disjunction_permission.h
@@ -0,0 +1,172 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
+
+#include <algorithm>
+#include <set>
+#include <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "extensions/common/extension_messages.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_message_utils.h"
+
+namespace extensions {
+
+// An abstract base class for permissions that are represented by the
+// disjunction of a set of conditions.  Each condition is represented by a
+// |PermissionDataType| (e.g. SocketPermissionData).  If an
+// APIPermission::CheckParam matches any of the conditions in the set, the
+// permission is granted.
+//
+// For an example of how to use this class, see SocketPermission.
+template <class PermissionDataType, class DerivedType>
+class SetDisjunctionPermission : public APIPermission {
+ public:
+  explicit SetDisjunctionPermission(const APIPermissionInfo* info)
+      : APIPermission(info) {}
+
+  ~SetDisjunctionPermission() {}
+
+  // APIPermission overrides
+  virtual bool HasMessages() const OVERRIDE { return !data_set_.empty(); }
+
+  virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE {
+    for (typename std::set<PermissionDataType>::const_iterator i =
+             data_set_.begin();
+         i != data_set_.end();
+         ++i) {
+      if (i->Check(param))
+        return true;
+    }
+    return false;
+  }
+
+  virtual bool Contains(const APIPermission* rhs) const OVERRIDE {
+    CHECK(rhs->info() == info());
+    const SetDisjunctionPermission* perm =
+        static_cast<const SetDisjunctionPermission*>(rhs);
+    return std::includes(data_set_.begin(),
+                         data_set_.end(),
+                         perm->data_set_.begin(),
+                         perm->data_set_.end());
+  }
+
+  virtual bool Equal(const APIPermission* rhs) const OVERRIDE {
+    CHECK(rhs->info() == info());
+    const SetDisjunctionPermission* perm =
+        static_cast<const SetDisjunctionPermission*>(rhs);
+    return data_set_ == perm->data_set_;
+  }
+
+  virtual APIPermission* Clone() const OVERRIDE {
+    SetDisjunctionPermission* result = new DerivedType(info());
+    result->data_set_ = data_set_;
+    return result;
+  }
+
+  virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE {
+    CHECK(rhs->info() == info());
+    const SetDisjunctionPermission* perm =
+        static_cast<const SetDisjunctionPermission*>(rhs);
+    scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
+    std::set_difference(data_set_.begin(),
+                        data_set_.end(),
+                        perm->data_set_.begin(),
+                        perm->data_set_.end(),
+                        std::inserter<std::set<PermissionDataType> >(
+                            result->data_set_, result->data_set_.begin()));
+    return result->data_set_.empty() ? NULL : result.release();
+  }
+
+  virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE {
+    CHECK(rhs->info() == info());
+    const SetDisjunctionPermission* perm =
+        static_cast<const SetDisjunctionPermission*>(rhs);
+    scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
+    std::set_union(data_set_.begin(),
+                   data_set_.end(),
+                   perm->data_set_.begin(),
+                   perm->data_set_.end(),
+                   std::inserter<std::set<PermissionDataType> >(
+                       result->data_set_, result->data_set_.begin()));
+    return result.release();
+  }
+
+  virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE {
+    CHECK(rhs->info() == info());
+    const SetDisjunctionPermission* perm =
+        static_cast<const SetDisjunctionPermission*>(rhs);
+    scoped_ptr<SetDisjunctionPermission> result(new DerivedType(info()));
+    std::set_intersection(data_set_.begin(),
+                          data_set_.end(),
+                          perm->data_set_.begin(),
+                          perm->data_set_.end(),
+                          std::inserter<std::set<PermissionDataType> >(
+                              result->data_set_, result->data_set_.begin()));
+    return result->data_set_.empty() ? NULL : result.release();
+  }
+
+  virtual bool FromValue(const base::Value* value,
+                         std::string* error) OVERRIDE {
+    data_set_.clear();
+    const base::ListValue* list = NULL;
+
+    if (!value || !value->GetAsList(&list) || list->GetSize() == 0) {
+      if (error)
+        *error = "NULL or empty permission list";
+      return false;
+    }
+
+    for (size_t i = 0; i < list->GetSize(); ++i) {
+      const base::Value* item_value = NULL;
+      bool got_item = list->Get(i, &item_value);
+      DCHECK(got_item);
+      DCHECK(item_value);
+
+      PermissionDataType data;
+      if (!data.FromValue(item_value)) {
+        if (error)
+          *error = "Cannot parse an item from the permission list";
+        return false;
+      }
+
+      data_set_.insert(data);
+    }
+    return true;
+  }
+
+  virtual scoped_ptr<base::Value> ToValue() const OVERRIDE {
+    base::ListValue* list = new base::ListValue();
+    typename std::set<PermissionDataType>::const_iterator i;
+    for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+      scoped_ptr<base::Value> item_value(i->ToValue());
+      list->Append(item_value.release());
+    }
+    return scoped_ptr<base::Value>(list);
+  }
+
+  virtual void Write(IPC::Message* m) const OVERRIDE {
+    IPC::WriteParam(m, data_set_);
+  }
+
+  virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE {
+    return IPC::ReadParam(m, iter, &data_set_);
+  }
+
+  virtual void Log(std::string* log) const OVERRIDE {
+    IPC::LogParam(data_set_, log);
+  }
+
+ protected:
+  std::set<PermissionDataType> data_set_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_SET_DISJUNCTION_PERMISSION_H_
diff --git a/extensions/common/permissions/settings_override_permission.cc b/extensions/common/permissions/settings_override_permission.cc
new file mode 100644
index 0000000..b58d937
--- /dev/null
+++ b/extensions/common/permissions/settings_override_permission.cc
@@ -0,0 +1,107 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/settings_override_permission.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+SettingsOverrideAPIPermission::SettingsOverrideAPIPermission(
+    const APIPermissionInfo* permission,
+    const std::string& setting_value)
+    : APIPermission(permission), setting_value_(setting_value) {}
+
+SettingsOverrideAPIPermission::~SettingsOverrideAPIPermission() {}
+
+bool SettingsOverrideAPIPermission::HasMessages() const {
+  return info()->message_id() > PermissionMessage::kNone;
+}
+
+PermissionMessages SettingsOverrideAPIPermission::GetMessages() const {
+  DCHECK(HasMessages());
+  int string_id = -1;
+  switch (id()) {
+    case kHomepage: {
+      string_id = IDS_EXTENSION_PROMPT_WARNING_HOME_PAGE_SETTING_OVERRIDE;
+      break;
+    }
+    case kStartupPages: {
+      string_id = IDS_EXTENSION_PROMPT_WARNING_START_PAGE_SETTING_OVERRIDE;
+      break;
+    }
+    case kSearchProvider: {
+      string_id = IDS_EXTENSION_PROMPT_WARNING_SEARCH_SETTINGS_OVERRIDE;
+      break;
+    }
+    default:
+      NOTREACHED();
+  }
+  PermissionMessages result;
+  result.push_back(
+      PermissionMessage(info()->message_id(),
+                        l10n_util::GetStringFUTF16(
+                            string_id, base::UTF8ToUTF16(setting_value_))));
+  return result;
+}
+
+bool SettingsOverrideAPIPermission::Check(
+    const APIPermission::CheckParam* param) const {
+  return (param == NULL);
+}
+
+bool SettingsOverrideAPIPermission::Contains(const APIPermission* rhs) const {
+  CHECK_EQ(info(), rhs->info());
+  return true;
+}
+
+bool SettingsOverrideAPIPermission::Equal(const APIPermission* rhs) const {
+  if (this != rhs)
+    CHECK_EQ(info(), rhs->info());
+  return true;
+}
+
+bool SettingsOverrideAPIPermission::FromValue(const base::Value* value,
+                                              std::string* /*error*/) {
+  return (value == NULL);
+}
+
+scoped_ptr<base::Value> SettingsOverrideAPIPermission::ToValue() const {
+  return scoped_ptr<base::Value>();
+}
+
+APIPermission* SettingsOverrideAPIPermission::Clone() const {
+  return new SettingsOverrideAPIPermission(info(), setting_value_);
+}
+
+APIPermission* SettingsOverrideAPIPermission::Diff(
+    const APIPermission* rhs) const {
+  CHECK_EQ(info(), rhs->info());
+  return NULL;
+}
+
+APIPermission* SettingsOverrideAPIPermission::Union(
+    const APIPermission* rhs) const {
+  CHECK_EQ(info(), rhs->info());
+  return new SettingsOverrideAPIPermission(info(), setting_value_);
+}
+
+APIPermission* SettingsOverrideAPIPermission::Intersect(
+    const APIPermission* rhs) const {
+  CHECK_EQ(info(), rhs->info());
+  return new SettingsOverrideAPIPermission(info(), setting_value_);
+}
+
+void SettingsOverrideAPIPermission::Write(IPC::Message* m) const {}
+
+bool SettingsOverrideAPIPermission::Read(const IPC::Message* m,
+                                         PickleIterator* iter) {
+  return true;
+}
+
+void SettingsOverrideAPIPermission::Log(std::string* log) const {}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/settings_override_permission.h b/extensions/common/permissions/settings_override_permission.h
new file mode 100644
index 0000000..48d3d71
--- /dev/null
+++ b/extensions/common/permissions/settings_override_permission.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
+
+#include <string>
+
+#include "extensions/common/permissions/api_permission.h"
+
+namespace extensions {
+
+// Takes care of creating custom permission messages for extensions that
+// override settings.
+class SettingsOverrideAPIPermission : public APIPermission {
+ public:
+  SettingsOverrideAPIPermission(const APIPermissionInfo* permission,
+                                const std::string& setting_value);
+  virtual ~SettingsOverrideAPIPermission();
+
+  // APIPermission overrides.
+  virtual bool HasMessages() const OVERRIDE;
+  virtual PermissionMessages GetMessages() const OVERRIDE;
+  virtual bool Check(const APIPermission::CheckParam* param) const OVERRIDE;
+  virtual bool Contains(const APIPermission* rhs) const OVERRIDE;
+  virtual bool Equal(const APIPermission* rhs) const OVERRIDE;
+  virtual bool FromValue(const base::Value* value, std::string* error) OVERRIDE;
+  virtual scoped_ptr<base::Value> ToValue() const OVERRIDE;
+  virtual APIPermission* Clone() const OVERRIDE;
+  virtual APIPermission* Diff(const APIPermission* rhs) const OVERRIDE;
+  virtual APIPermission* Union(const APIPermission* rhs) const OVERRIDE;
+  virtual APIPermission* Intersect(const APIPermission* rhs) const OVERRIDE;
+  virtual void Write(IPC::Message* m) const OVERRIDE;
+  virtual bool Read(const IPC::Message* m, PickleIterator* iter) OVERRIDE;
+  virtual void Log(std::string* log) const OVERRIDE;
+
+ private:
+  std::string setting_value_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_SETTINGS_OVERRIDE_PERMISSION_H_
diff --git a/extensions/common/permissions/socket_permission.cc b/extensions/common/permissions/socket_permission.cc
new file mode 100644
index 0000000..bc7d0c9
--- /dev/null
+++ b/extensions/common/permissions/socket_permission.cc
@@ -0,0 +1,108 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/socket_permission.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace extensions {
+
+SocketPermission::SocketPermission(const APIPermissionInfo* info)
+    : SetDisjunctionPermission<SocketPermissionData, SocketPermission>(info) {}
+
+SocketPermission::~SocketPermission() {}
+
+PermissionMessages SocketPermission::GetMessages() const {
+  DCHECK(HasMessages());
+  PermissionMessages result;
+  if (!AddAnyHostMessage(result)) {
+    AddSpecificHostMessage(result);
+    AddSubdomainHostMessage(result);
+  }
+  AddNetworkListMessage(result);
+  return result;
+}
+
+bool SocketPermission::AddAnyHostMessage(PermissionMessages& messages) const {
+  std::set<SocketPermissionData>::const_iterator i;
+  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+    if (i->entry().IsAddressBoundType() &&
+        i->entry().GetHostType() == SocketPermissionEntry::ANY_HOST) {
+      messages.push_back(
+          PermissionMessage(PermissionMessage::kSocketAnyHost,
+                            l10n_util::GetStringUTF16(
+                                IDS_EXTENSION_PROMPT_WARNING_SOCKET_ANY_HOST)));
+      return true;
+    }
+  }
+  return false;
+}
+
+void SocketPermission::AddSubdomainHostMessage(
+    PermissionMessages& messages) const {
+  std::set<base::string16> domains;
+  std::set<SocketPermissionData>::const_iterator i;
+  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+    if (i->entry().GetHostType() == SocketPermissionEntry::HOSTS_IN_DOMAINS)
+      domains.insert(base::UTF8ToUTF16(i->entry().pattern().host));
+  }
+  if (!domains.empty()) {
+    int id = (domains.size() == 1)
+                 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAIN
+                 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_HOSTS_IN_DOMAINS;
+    messages.push_back(PermissionMessage(
+        PermissionMessage::kSocketDomainHosts,
+        l10n_util::GetStringFUTF16(
+            id,
+            JoinString(
+                std::vector<base::string16>(domains.begin(), domains.end()),
+                ' '))));
+  }
+}
+
+void SocketPermission::AddSpecificHostMessage(
+    PermissionMessages& messages) const {
+  std::set<base::string16> hostnames;
+  std::set<SocketPermissionData>::const_iterator i;
+  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+    if (i->entry().GetHostType() == SocketPermissionEntry::SPECIFIC_HOSTS)
+      hostnames.insert(base::UTF8ToUTF16(i->entry().pattern().host));
+  }
+  if (!hostnames.empty()) {
+    int id = (hostnames.size() == 1)
+                 ? IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOST
+                 : IDS_EXTENSION_PROMPT_WARNING_SOCKET_SPECIFIC_HOSTS;
+    messages.push_back(PermissionMessage(
+        PermissionMessage::kSocketSpecificHosts,
+        l10n_util::GetStringFUTF16(
+            id,
+            JoinString(
+                std::vector<base::string16>(hostnames.begin(), hostnames.end()),
+                ' '))));
+  }
+}
+
+void SocketPermission::AddNetworkListMessage(
+    PermissionMessages& messages) const {
+  std::set<SocketPermissionData>::const_iterator i;
+  for (i = data_set_.begin(); i != data_set_.end(); ++i) {
+    if (i->entry().pattern().type ==
+        content::SocketPermissionRequest::NETWORK_STATE) {
+      messages.push_back(
+          PermissionMessage(PermissionMessage::kNetworkState,
+                            l10n_util::GetStringUTF16(
+                                IDS_EXTENSION_PROMPT_WARNING_NETWORK_STATE)));
+    }
+  }
+}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/socket_permission.h b/extensions/common/permissions/socket_permission.h
new file mode 100644
index 0000000..2bfea7c
--- /dev/null
+++ b/extensions/common/permissions/socket_permission.h
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_H_
+
+#include <string>
+
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+#include "extensions/common/permissions/socket_permission_data.h"
+
+namespace extensions {
+
+class SocketPermission
+    : public SetDisjunctionPermission<SocketPermissionData, SocketPermission> {
+ public:
+  struct CheckParam : APIPermission::CheckParam {
+    CheckParam(content::SocketPermissionRequest::OperationType type,
+               const std::string& host,
+               int port)
+        : request(type, host, port) {}
+    content::SocketPermissionRequest request;
+  };
+
+  explicit SocketPermission(const APIPermissionInfo* info);
+
+  virtual ~SocketPermission();
+
+  // Returns the localized permission messages of this permission.
+  virtual PermissionMessages GetMessages() const OVERRIDE;
+
+ private:
+  bool AddAnyHostMessage(PermissionMessages& messages) const;
+  void AddSubdomainHostMessage(PermissionMessages& messages) const;
+  void AddSpecificHostMessage(PermissionMessages& messages) const;
+  void AddNetworkListMessage(PermissionMessages& messages) const;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_H_
diff --git a/extensions/common/permissions/socket_permission_data.cc b/extensions/common/permissions/socket_permission_data.cc
new file mode 100644
index 0000000..b679268
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_data.cc
@@ -0,0 +1,158 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/socket_permission_data.h"
+
+#include <cstdlib>
+#include <sstream>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/socket_permission.h"
+#include "url/url_canon.h"
+
+namespace {
+
+using content::SocketPermissionRequest;
+using extensions::SocketPermissionData;
+
+const char kColon = ':';
+const char kInvalid[] = "invalid";
+const char kTCPConnect[] = "tcp-connect";
+const char kTCPListen[] = "tcp-listen";
+const char kUDPBind[] = "udp-bind";
+const char kUDPSendTo[] = "udp-send-to";
+const char kUDPMulticastMembership[] = "udp-multicast-membership";
+const char kResolveHost[] = "resolve-host";
+const char kResolveProxy[] = "resolve-proxy";
+const char kNetworkState[] = "network-state";
+
+SocketPermissionRequest::OperationType StringToType(const std::string& s) {
+  if (s == kTCPConnect)
+    return SocketPermissionRequest::TCP_CONNECT;
+  if (s == kTCPListen)
+    return SocketPermissionRequest::TCP_LISTEN;
+  if (s == kUDPBind)
+    return SocketPermissionRequest::UDP_BIND;
+  if (s == kUDPSendTo)
+    return SocketPermissionRequest::UDP_SEND_TO;
+  if (s == kUDPMulticastMembership)
+    return SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP;
+  if (s == kResolveHost)
+    return SocketPermissionRequest::RESOLVE_HOST;
+  if (s == kResolveProxy)
+    return SocketPermissionRequest::RESOLVE_PROXY;
+  if (s == kNetworkState)
+    return SocketPermissionRequest::NETWORK_STATE;
+  return SocketPermissionRequest::NONE;
+}
+
+const char* TypeToString(SocketPermissionRequest::OperationType type) {
+  switch (type) {
+    case SocketPermissionRequest::TCP_CONNECT:
+      return kTCPConnect;
+    case SocketPermissionRequest::TCP_LISTEN:
+      return kTCPListen;
+    case SocketPermissionRequest::UDP_BIND:
+      return kUDPBind;
+    case SocketPermissionRequest::UDP_SEND_TO:
+      return kUDPSendTo;
+    case SocketPermissionRequest::UDP_MULTICAST_MEMBERSHIP:
+      return kUDPMulticastMembership;
+    case SocketPermissionRequest::RESOLVE_HOST:
+      return kResolveHost;
+    case SocketPermissionRequest::RESOLVE_PROXY:
+      return kResolveProxy;
+    case SocketPermissionRequest::NETWORK_STATE:
+      return kNetworkState;
+    default:
+      return kInvalid;
+  }
+}
+
+}  // namespace
+
+namespace extensions {
+
+SocketPermissionData::SocketPermissionData() {}
+
+SocketPermissionData::~SocketPermissionData() {}
+
+bool SocketPermissionData::operator<(const SocketPermissionData& rhs) const {
+  return entry_ < rhs.entry_;
+}
+
+bool SocketPermissionData::operator==(const SocketPermissionData& rhs) const {
+  return entry_ == rhs.entry_;
+}
+
+bool SocketPermissionData::Check(const APIPermission::CheckParam* param) const {
+  if (!param)
+    return false;
+  const SocketPermission::CheckParam& specific_param =
+      *static_cast<const SocketPermission::CheckParam*>(param);
+  const SocketPermissionRequest& request = specific_param.request;
+
+  return entry_.Check(request);
+}
+
+scoped_ptr<base::Value> SocketPermissionData::ToValue() const {
+  return scoped_ptr<base::Value>(new base::StringValue(GetAsString()));
+}
+
+bool SocketPermissionData::FromValue(const base::Value* value) {
+  std::string spec;
+  if (!value->GetAsString(&spec))
+    return false;
+
+  return Parse(spec);
+}
+
+SocketPermissionEntry& SocketPermissionData::entry() {
+  // Clear the spec because the caller could mutate |this|.
+  spec_.clear();
+  return entry_;
+}
+
+// TODO(ikarienator): Rewrite this method to support IPv6.
+bool SocketPermissionData::Parse(const std::string& permission) {
+  Reset();
+
+  std::vector<std::string> tokens;
+  base::SplitStringDontTrim(permission, kColon, &tokens);
+  if (tokens.empty())
+    return false;
+
+  SocketPermissionRequest::OperationType type = StringToType(tokens[0]);
+  if (type == SocketPermissionRequest::NONE)
+    return false;
+
+  tokens.erase(tokens.begin());
+  return SocketPermissionEntry::ParseHostPattern(type, tokens, &entry_);
+}
+
+const std::string& SocketPermissionData::GetAsString() const {
+  if (!spec_.empty())
+    return spec_;
+
+  spec_.reserve(64);
+  spec_.append(TypeToString(entry_.pattern().type));
+  std::string pattern = entry_.GetHostPatternAsString();
+  if (!pattern.empty()) {
+    spec_.append(1, kColon).append(pattern);
+  }
+  return spec_;
+}
+
+void SocketPermissionData::Reset() {
+  entry_ = SocketPermissionEntry();
+  spec_.clear();
+}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/socket_permission_data.h b/extensions/common/permissions/socket_permission_data.h
new file mode 100644
index 0000000..f227f8d
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_data.h
@@ -0,0 +1,89 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
+
+#include <string>
+
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/socket_permission_entry.h"
+#include "ipc/ipc_param_traits.h"
+
+namespace ipc_fuzzer {
+template <class T>
+struct FuzzTraits;
+template <class T>
+struct GenerateTraits;
+}  // namespace ipc_fuzzer
+
+namespace extensions {
+
+// A pattern that can be used to match socket permission.
+//   <socket-permission-pattern>
+//          := <op> |
+//             <op> ':' <host> |
+//             <op> ':' ':' <port> |
+//             <op> ':' <host> ':' <port> |
+//             'udp-multicast-membership'
+//   <op>   := 'tcp-connect' |
+//             'tcp-listen' |
+//             'udp-bind' |
+//             'udp-send-to' |
+//             'udp-multicast-membership' |
+//             'resolve-host' |
+//             'resolve-proxy' |
+//             'network-state'
+//   <host> := '*' |
+//             '*.' <anychar except '/' and '*'>+ |
+//             <anychar except '/' and '*'>+
+//   <port> := '*' |
+//             <port number between 0 and 65535>)
+// The multicast membership permission implies a permission to any address.
+class SocketPermissionData {
+ public:
+  SocketPermissionData();
+  ~SocketPermissionData();
+
+  // operators <, == are needed by container std::set and algorithms
+  // std::set_includes and std::set_differences.
+  bool operator<(const SocketPermissionData& rhs) const;
+  bool operator==(const SocketPermissionData& rhs) const;
+
+  // Check if |param| (which must be a SocketPermissionData::CheckParam)
+  // matches the spec of |this|.
+  bool Check(const APIPermission::CheckParam* param) const;
+
+  // Convert |this| into a base::Value.
+  scoped_ptr<base::Value> ToValue() const;
+
+  // Populate |this| from a base::Value.
+  bool FromValue(const base::Value* value);
+
+  // TODO(bryeung): SocketPermissionData should be encoded as a base::Value
+  // instead of a string.  Until that is done, expose these methods for
+  // testing.
+  bool ParseForTest(const std::string& permission) { return Parse(permission); }
+  const std::string& GetAsStringForTest() const { return GetAsString(); }
+
+  const SocketPermissionEntry& entry() const { return entry_; }
+
+ private:
+  // Friend so ParamTraits can serialize us.
+  friend struct IPC::ParamTraits<SocketPermissionData>;
+  friend struct ipc_fuzzer::FuzzTraits<SocketPermissionData>;
+  friend struct ipc_fuzzer::GenerateTraits<SocketPermissionData>;
+
+  SocketPermissionEntry& entry();
+
+  bool Parse(const std::string& permission);
+  const std::string& GetAsString() const;
+  void Reset();
+
+  SocketPermissionEntry entry_;
+  mutable std::string spec_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_DATA_H_
diff --git a/extensions/common/permissions/socket_permission_entry.cc b/extensions/common/permissions/socket_permission_entry.cc
new file mode 100644
index 0000000..8c21edc
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_entry.cc
@@ -0,0 +1,226 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/socket_permission_entry.h"
+
+#include <cstdlib>
+#include <sstream>
+#include <vector>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/socket_permission.h"
+#include "url/url_canon.h"
+
+namespace {
+
+using content::SocketPermissionRequest;
+
+const char kColon = ':';
+const char kDot = '.';
+const char kWildcard[] = "*";
+const int kWildcardPortNumber = 0;
+const int kInvalidPort = -1;
+
+bool StartsOrEndsWithWhitespace(const std::string& str) {
+  if (str.find_first_not_of(base::kWhitespaceASCII) != 0)
+    return true;
+  if (str.find_last_not_of(base::kWhitespaceASCII) != str.length() - 1)
+    return true;
+  return false;
+}
+
+}  // namespace
+
+namespace extensions {
+
+SocketPermissionEntry::SocketPermissionEntry()
+    : pattern_(SocketPermissionRequest::NONE, std::string(), kInvalidPort),
+      match_subdomains_(false) {}
+
+SocketPermissionEntry::~SocketPermissionEntry() {}
+
+bool SocketPermissionEntry::operator<(const SocketPermissionEntry& rhs) const {
+  if (pattern_.type < rhs.pattern_.type)
+    return true;
+  if (pattern_.type > rhs.pattern_.type)
+    return false;
+
+  if (pattern_.host < rhs.pattern_.host)
+    return true;
+  if (pattern_.host > rhs.pattern_.host)
+    return false;
+
+  if (match_subdomains_ < rhs.match_subdomains_)
+    return true;
+  if (match_subdomains_ > rhs.match_subdomains_)
+    return false;
+
+  if (pattern_.port < rhs.pattern_.port)
+    return true;
+  return false;
+}
+
+bool SocketPermissionEntry::operator==(const SocketPermissionEntry& rhs) const {
+  return (pattern_.type == rhs.pattern_.type) &&
+         (pattern_.host == rhs.pattern_.host) &&
+         (match_subdomains_ == rhs.match_subdomains_) &&
+         (pattern_.port == rhs.pattern_.port);
+}
+
+bool SocketPermissionEntry::Check(
+    const content::SocketPermissionRequest& request) const {
+  if (pattern_.type != request.type)
+    return false;
+
+  std::string lhost = StringToLowerASCII(request.host);
+  if (pattern_.host != lhost) {
+    if (!match_subdomains_)
+      return false;
+
+    if (!pattern_.host.empty()) {
+      // Do not wildcard part of IP address.
+      url_parse::Component component(0, lhost.length());
+      url_canon::RawCanonOutputT<char, 128> ignored_output;
+      url_canon::CanonHostInfo host_info;
+      url_canon::CanonicalizeIPAddress(
+          lhost.c_str(), component, &ignored_output, &host_info);
+      if (host_info.IsIPAddress())
+        return false;
+
+      // host should equal one or more chars + "." +  host_.
+      int i = lhost.length() - pattern_.host.length();
+      if (i < 2)
+        return false;
+
+      if (lhost.compare(i, pattern_.host.length(), pattern_.host) != 0)
+        return false;
+
+      if (lhost[i - 1] != kDot)
+        return false;
+    }
+  }
+
+  if (pattern_.port != request.port && pattern_.port != kWildcardPortNumber)
+    return false;
+
+  return true;
+}
+
+SocketPermissionEntry::HostType SocketPermissionEntry::GetHostType() const {
+  return pattern_.host.empty()
+             ? SocketPermissionEntry::ANY_HOST
+             : match_subdomains_ ? SocketPermissionEntry::HOSTS_IN_DOMAINS
+                                 : SocketPermissionEntry::SPECIFIC_HOSTS;
+}
+
+bool SocketPermissionEntry::IsAddressBoundType() const {
+  return pattern_.type == SocketPermissionRequest::TCP_CONNECT ||
+         pattern_.type == SocketPermissionRequest::TCP_LISTEN ||
+         pattern_.type == SocketPermissionRequest::UDP_BIND ||
+         pattern_.type == SocketPermissionRequest::UDP_SEND_TO;
+}
+
+// static
+bool SocketPermissionEntry::ParseHostPattern(
+    SocketPermissionRequest::OperationType type,
+    const std::string& pattern,
+    SocketPermissionEntry* entry) {
+  std::vector<std::string> tokens;
+  base::SplitStringDontTrim(pattern, kColon, &tokens);
+  return ParseHostPattern(type, tokens, entry);
+}
+
+// static
+bool SocketPermissionEntry::ParseHostPattern(
+    SocketPermissionRequest::OperationType type,
+    const std::vector<std::string>& pattern_tokens,
+    SocketPermissionEntry* entry) {
+
+  SocketPermissionEntry result;
+
+  if (type == SocketPermissionRequest::NONE)
+    return false;
+
+  if (pattern_tokens.size() > 2)
+    return false;
+
+  result.pattern_.type = type;
+  result.pattern_.port = kWildcardPortNumber;
+  result.match_subdomains_ = true;
+
+  if (pattern_tokens.size() == 0) {
+    *entry = result;
+    return true;
+  }
+
+  // Return an error if address is specified for permissions that don't
+  // need it (such as 'resolve-host').
+  if (!result.IsAddressBoundType())
+    return false;
+
+  result.pattern_.host = pattern_tokens[0];
+  if (!result.pattern_.host.empty()) {
+    if (StartsOrEndsWithWhitespace(result.pattern_.host))
+      return false;
+    result.pattern_.host = StringToLowerASCII(result.pattern_.host);
+
+    // The first component can optionally be '*' to match all subdomains.
+    std::vector<std::string> host_components;
+    base::SplitString(result.pattern_.host, kDot, &host_components);
+    DCHECK(!host_components.empty());
+
+    if (host_components[0] == kWildcard || host_components[0].empty()) {
+      host_components.erase(host_components.begin(),
+                            host_components.begin() + 1);
+    } else {
+      result.match_subdomains_ = false;
+    }
+    result.pattern_.host = JoinString(host_components, kDot);
+  }
+
+  if (pattern_tokens.size() == 1 || pattern_tokens[1].empty() ||
+      pattern_tokens[1] == kWildcard) {
+    *entry = result;
+    return true;
+  }
+
+  if (StartsOrEndsWithWhitespace(pattern_tokens[1]))
+    return false;
+
+  if (!base::StringToInt(pattern_tokens[1], &result.pattern_.port) ||
+      result.pattern_.port < 1 || result.pattern_.port > 65535)
+    return false;
+
+  *entry = result;
+  return true;
+}
+
+std::string SocketPermissionEntry::GetHostPatternAsString() const {
+  std::string result;
+
+  if (!IsAddressBoundType())
+    return result;
+
+  if (match_subdomains()) {
+    result.append(kWildcard);
+    if (!pattern_.host.empty())
+      result.append(1, kDot).append(pattern_.host);
+  } else {
+    result.append(pattern_.host);
+  }
+
+  if (pattern_.port == kWildcardPortNumber)
+    result.append(1, kColon).append(kWildcard);
+  else
+    result.append(1, kColon).append(base::IntToString(pattern_.port));
+
+  return result;
+}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/socket_permission_entry.h b/extensions/common/permissions/socket_permission_entry.h
new file mode 100644
index 0000000..ee4e212
--- /dev/null
+++ b/extensions/common/permissions/socket_permission_entry.h
@@ -0,0 +1,84 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
+
+#include <string>
+#include <vector>
+
+#include "content/public/common/socket_permission_request.h"
+#include "ipc/ipc_param_traits.h"
+
+namespace ipc_fuzzer {
+template <class T>
+struct FuzzTraits;
+template <class T>
+struct GenerateTraits;
+}  // namespace ipc_fuzzer
+
+namespace extensions {
+
+// Internal representation of a socket permission for a specific operation, such
+// as UDP "bind", host 127.0.0.1, port *.
+class SocketPermissionEntry {
+ public:
+  enum HostType { ANY_HOST, HOSTS_IN_DOMAINS, SPECIFIC_HOSTS, };
+
+  SocketPermissionEntry();
+  ~SocketPermissionEntry();
+
+  // operators <, == are needed by container std::set and algorithms
+  // std::set_includes and std::set_differences.
+  bool operator<(const SocketPermissionEntry& rhs) const;
+  bool operator==(const SocketPermissionEntry& rhs) const;
+
+  bool Check(const content::SocketPermissionRequest& request) const;
+
+  // Parse a host:port pattern for a given operation type.
+  //   <pattern> := '' |
+  //                <host> |
+  //                ':' <port> |
+  //                <host> ':' <port> |
+  //
+  //   <host> := '*' |
+  //             '*.' <anychar except '/' and '*'>+ |
+  //             <anychar except '/' and '*'>+
+  //
+  //   <port> := '*' |
+  //             <port number between 0 and 65535>)
+  static bool ParseHostPattern(
+      content::SocketPermissionRequest::OperationType type,
+      const std::string& pattern,
+      SocketPermissionEntry* entry);
+
+  static bool ParseHostPattern(
+      content::SocketPermissionRequest::OperationType type,
+      const std::vector<std::string>& pattern_tokens,
+      SocketPermissionEntry* entry);
+
+  // Returns true if the permission type can be bound to a host or port.
+  bool IsAddressBoundType() const;
+
+  std::string GetHostPatternAsString() const;
+  HostType GetHostType() const;
+
+  const content::SocketPermissionRequest& pattern() const { return pattern_; }
+  bool match_subdomains() const { return match_subdomains_; }
+
+ private:
+  // Friend so ParamTraits can serialize us.
+  friend struct IPC::ParamTraits<SocketPermissionEntry>;
+  friend struct ipc_fuzzer::FuzzTraits<SocketPermissionEntry>;
+  friend struct ipc_fuzzer::GenerateTraits<SocketPermissionEntry>;
+
+  // The permission type, host and port.
+  content::SocketPermissionRequest pattern_;
+
+  // True if there was a wildcard in the host name.
+  bool match_subdomains_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_SOCKET_PERMISSION_ENTRY_H_
diff --git a/extensions/common/permissions/usb_device_permission.cc b/extensions/common/permissions/usb_device_permission.cc
new file mode 100644
index 0000000..c381b89
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission.cc
@@ -0,0 +1,74 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/usb_device_permission.h"
+
+#include <set>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+#if defined(ENABLE_EXTENSIONS)
+#include "device/usb/usb_ids.h"
+#endif
+
+namespace extensions {
+
+UsbDevicePermission::UsbDevicePermission(
+    const APIPermissionInfo* info)
+  : SetDisjunctionPermission<UsbDevicePermissionData,
+                             UsbDevicePermission>(info) {
+}
+
+UsbDevicePermission::~UsbDevicePermission() {
+}
+
+PermissionMessages UsbDevicePermission::GetMessages() const {
+  DCHECK(HasMessages());
+  PermissionMessages result;
+
+#if defined(ENABLE_EXTENSIONS)
+  // //device/usb/usb.gyp:device_usb is not available when extensions are
+  // disabled.
+  for (std::set<UsbDevicePermissionData>::const_iterator i =
+      data_set_.begin(); i != data_set_.end(); ++i) {
+    const char* vendor = device::UsbIds::GetVendorName(i->vendor_id());
+
+    if (vendor) {
+      const char* product =
+          device::UsbIds::GetProductName(i->vendor_id(), i->product_id());
+      if (product) {
+        result.push_back(PermissionMessage(
+            PermissionMessage::kUsbDevice,
+            l10n_util::GetStringFUTF16(
+                IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE,
+                base::ASCIIToUTF16(product),
+                base::ASCIIToUTF16(vendor))));
+      } else {
+        result.push_back(PermissionMessage(
+            PermissionMessage::kUsbDevice,
+            l10n_util::GetStringFUTF16(
+                IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_MISSING_PRODUCT,
+                base::ASCIIToUTF16(vendor))));
+      }
+    } else {
+      result.push_back(PermissionMessage(
+          PermissionMessage::kUsbDevice,
+          l10n_util::GetStringUTF16(
+              IDS_EXTENSION_PROMPT_WARNING_USB_DEVICE_MISSING_VENDOR)));
+    }
+  }
+#else
+  NOTREACHED();
+#endif  // defined(ENABLE_EXTENSIONS)
+
+  return result;
+}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/usb_device_permission.h b/extensions/common/permissions/usb_device_permission.h
new file mode 100644
index 0000000..7f6b52a
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission.h
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_H_
+
+#include "base/basictypes.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+#include "extensions/common/permissions/usb_device_permission_data.h"
+
+namespace extensions {
+
+class UsbDevicePermission
+  : public SetDisjunctionPermission<UsbDevicePermissionData,
+                                    UsbDevicePermission> {
+ public:
+  struct CheckParam : public APIPermission::CheckParam {
+    CheckParam(uint16 vendor_id, uint16 product_id, int interface_id)
+      : vendor_id(vendor_id),
+        product_id(product_id),
+        interface_id(interface_id) {}
+    const uint16 vendor_id;
+    const uint16 product_id;
+    const int interface_id;
+  };
+
+  explicit UsbDevicePermission(const APIPermissionInfo* info);
+  virtual ~UsbDevicePermission();
+
+  // APIPermission overrides
+  virtual PermissionMessages GetMessages() const OVERRIDE;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_H_
diff --git a/extensions/common/permissions/usb_device_permission_data.cc b/extensions/common/permissions/usb_device_permission_data.cc
new file mode 100644
index 0000000..532886d
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission_data.cc
@@ -0,0 +1,109 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "extensions/common/permissions/usb_device_permission_data.h"
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/values.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/usb_device_permission.h"
+
+namespace {
+
+const char* kProductIdKey = "productId";
+const char* kVendorIdKey = "vendorId";
+const char* kInterfaceIdKey = "interfaceId";
+
+}  // namespace
+
+namespace extensions {
+
+UsbDevicePermissionData::UsbDevicePermissionData()
+  : vendor_id_(0), product_id_(0), interface_id_(ANY_INTERFACE) {
+}
+
+UsbDevicePermissionData::UsbDevicePermissionData(uint16 vendor_id,
+                                                 uint16 product_id,
+                                                 int interface_id)
+  : vendor_id_(vendor_id),
+    product_id_(product_id),
+    interface_id_(interface_id) {
+}
+
+bool UsbDevicePermissionData::Check(
+    const APIPermission::CheckParam* param) const {
+  if (!param)
+    return false;
+  const UsbDevicePermission::CheckParam& specific_param =
+      *static_cast<const UsbDevicePermission::CheckParam*>(param);
+  return vendor_id_ == specific_param.vendor_id &&
+         product_id_ == specific_param.product_id &&
+         (specific_param.interface_id == UNSPECIFIED_INTERFACE ||
+          interface_id_ == specific_param.interface_id);
+}
+
+scoped_ptr<base::Value> UsbDevicePermissionData::ToValue() const {
+  base::DictionaryValue* result = new base::DictionaryValue();
+  result->SetInteger(kVendorIdKey, vendor_id_);
+  result->SetInteger(kProductIdKey, product_id_);
+  result->SetInteger(kInterfaceIdKey, interface_id_);
+  return scoped_ptr<base::Value>(result);
+}
+
+bool UsbDevicePermissionData::FromValue(const base::Value* value) {
+  if (!value)
+    return false;
+
+  const base::DictionaryValue* dict_value;
+  if (!value->GetAsDictionary(&dict_value))
+    return false;
+
+  int temp;
+  if (!dict_value->GetInteger(kVendorIdKey, &temp))
+    return false;
+  if (temp < 0 || temp > kuint16max)
+    return false;
+  vendor_id_ = temp;
+
+  if (!dict_value->GetInteger(kProductIdKey, &temp))
+    return false;
+  if (temp < 0 || temp > kuint16max)
+    return false;
+  product_id_ = temp;
+
+  if (!dict_value->GetInteger(kInterfaceIdKey, &temp))
+    interface_id_ = ANY_INTERFACE;
+  else if (temp < ANY_INTERFACE || temp > kuint8max)
+    return false;
+  else
+    interface_id_ = temp;
+
+  return true;
+}
+
+bool UsbDevicePermissionData::operator<(
+    const UsbDevicePermissionData& rhs) const {
+  if (vendor_id_ == rhs.vendor_id_) {
+    if (product_id_ == rhs.product_id_)
+      return interface_id_ < rhs.interface_id_;
+
+    return product_id_ < rhs.product_id_;
+  }
+  return vendor_id_ < rhs.vendor_id_;
+}
+
+bool UsbDevicePermissionData::operator==(
+    const UsbDevicePermissionData& rhs) const {
+  return vendor_id_ == rhs.vendor_id_ &&
+      product_id_ == rhs.product_id_ &&
+      interface_id_ == rhs.interface_id_;
+}
+
+}  // namespace extensions
diff --git a/extensions/common/permissions/usb_device_permission_data.h b/extensions/common/permissions/usb_device_permission_data.h
new file mode 100644
index 0000000..001b12c
--- /dev/null
+++ b/extensions/common/permissions/usb_device_permission_data.h
@@ -0,0 +1,71 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+#ifndef EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
+#define EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "extensions/common/permissions/api_permission.h"
+
+namespace base {
+
+class Value;
+
+}  // namespace base
+
+namespace extensions {
+
+// A pattern that can be used to match a USB device permission.
+// Should be of the format: vendorId:productId, where both vendorId and
+// productId are decimal strings representing uint16 values.
+class UsbDevicePermissionData {
+ public:
+  enum SpecialInterfaces {
+    // A special interface id for stating permissions for an entire USB device,
+    // no specific interface. This value must match value of Rule::ANY_INTERFACE
+    // from ChromeOS permission_broker project.
+    ANY_INTERFACE = -1,
+
+    // A special interface id for |Check| to indicate that interface field is
+    // not to be checked. Not used in manifest file.
+    UNSPECIFIED_INTERFACE = -2
+  };
+
+  UsbDevicePermissionData();
+  UsbDevicePermissionData(uint16 vendor_id,
+                          uint16 product_id,
+                          int interface_id);
+
+  // Check if |param| (which must be a UsbDevicePermissionData::CheckParam)
+  // matches the vendor and product IDs associated with |this|.
+  bool Check(const APIPermission::CheckParam* param) const;
+
+  // Convert |this| into a base::Value.
+  scoped_ptr<base::Value> ToValue() const;
+
+  // Populate |this| from a base::Value.
+  bool FromValue(const base::Value* value);
+
+  bool operator<(const UsbDevicePermissionData& rhs) const;
+  bool operator==(const UsbDevicePermissionData& rhs) const;
+
+  const uint16& vendor_id() const { return vendor_id_; }
+  const uint16& product_id() const { return product_id_; }
+
+  // These accessors are provided for IPC_STRUCT_TRAITS_MEMBER.  Please
+  // think twice before using them for anything else.
+  uint16& vendor_id() { return vendor_id_; }
+  uint16& product_id() { return product_id_; }
+
+ private:
+  uint16 vendor_id_;
+  uint16 product_id_;
+  int interface_id_;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_COMMON_PERMISSIONS_USB_DEVICE_PERMISSION_DATA_H_
diff --git a/extensions/common/switches.cc b/extensions/common/switches.cc
index b709630..64b9af5 100644
--- a/extensions/common/switches.cc
+++ b/extensions/common/switches.cc
@@ -16,11 +16,6 @@
 const char kAllowLegacyExtensionManifests[] =
     "allow-legacy-extension-manifests";
 
-// Allows injecting extensions and user scripts on the extensions gallery
-// site. Normally prevented for security reasons, but can be useful for
-// automation testing of the gallery.
-const char kAllowScriptingGallery[] = "allow-scripting-gallery";
-
 // Enables extensions to be easily installed from sites other than the web
 // store. Without this flag, they can still be installed, but must be manually
 // dragged onto chrome://extensions/.
diff --git a/extensions/common/switches.h b/extensions/common/switches.h
index 64f8189..ba1e131 100644
--- a/extensions/common/switches.h
+++ b/extensions/common/switches.h
@@ -13,7 +13,6 @@
 
 extern const char kAllowHTTPBackgroundPage[];
 extern const char kAllowLegacyExtensionManifests[];
-extern const char kAllowScriptingGallery[];
 extern const char kEasyOffStoreExtensionInstall[];
 extern const char kEnableExperimentalExtensionApis[];
 extern const char kEnableOverrideBookmarksUI[];
diff --git a/extensions/extensions.gyp b/extensions/extensions.gyp
index f64f675..99a3b07 100644
--- a/extensions/extensions.gyp
+++ b/extensions/extensions.gyp
@@ -11,7 +11,6 @@
       'target_name': 'extensions_common',
       'type': 'static_library',
       'dependencies': [
-        'common/api/api.gyp:extensions_api',
         '../third_party/re2/re2.gyp:re2',
         # TODO(benwells): figure out what to do with the api target and
         # api resources compiled into the chrome resource bundle.
@@ -28,6 +27,7 @@
         '<(INTERMEDIATE_DIR)',
       ],
       'sources': [
+        'common/api/messaging/message.h',
         'common/common_manifest_handlers.cc',
         'common/common_manifest_handlers.h',
         'common/crx_file.cc',
@@ -112,10 +112,16 @@
         'common/permissions/manifest_permission.h',
         'common/permissions/manifest_permission_set.cc',
         'common/permissions/manifest_permission_set.h',
+        'common/permissions/media_galleries_permission.cc',
+        'common/permissions/media_galleries_permission.h',
+        'common/permissions/media_galleries_permission_data.cc',
+        'common/permissions/media_galleries_permission_data.h',
         'common/permissions/permission_message.cc',
         'common/permissions/permission_message.h',
         'common/permissions/permission_message_provider.cc',
         'common/permissions/permission_message_provider.h',
+        'common/permissions/permission_message_util.cc',
+        'common/permissions/permission_message_util.h',
         'common/permissions/permission_set.cc',
         'common/permissions/permission_set.h',
         'common/permissions/permissions_data.cc',
@@ -123,6 +129,19 @@
         'common/permissions/permissions_info.cc',
         'common/permissions/permissions_info.h',
         'common/permissions/permissions_provider.h',
+        'common/permissions/set_disjunction_permission.h',
+        'common/permissions/settings_override_permission.cc',
+        'common/permissions/settings_override_permission.h',
+        'common/permissions/socket_permission.cc',
+        'common/permissions/socket_permission.h',
+        'common/permissions/socket_permission_data.cc',
+        'common/permissions/socket_permission_data.h',
+        'common/permissions/socket_permission_entry.cc',
+        'common/permissions/socket_permission_entry.h',
+        'common/permissions/usb_device_permission.cc',
+        'common/permissions/usb_device_permission.h',
+        'common/permissions/usb_device_permission_data.cc',
+        'common/permissions/usb_device_permission_data.h',
         'common/stack_frame.cc',
         'common/stack_frame.h',
         'common/switches.cc',
@@ -155,6 +174,7 @@
       'type': 'static_library',
       'dependencies': [
         'extensions_common',
+        'common/api/api.gyp:extensions_api',
         # TODO(jamescook|derat): Pull strings into extensions module.
         '../chrome/chrome_resources.gyp:chrome_strings',
         '../chrome/common/extensions/api/api.gyp:chrome_api',
@@ -180,6 +200,10 @@
         'browser/api/api_resource_manager.h',
         'browser/api/async_api_function.cc',
         'browser/api/async_api_function.h',
+        'browser/api/dns/dns_api.cc',
+        'browser/api/dns/dns_api.h',
+        'browser/api/dns/host_resolver_wrapper.cc',
+        'browser/api/dns/host_resolver_wrapper.h',
         'browser/api/extensions_api_client.cc',
         'browser/api/extensions_api_client.h',
         'browser/api/socket/socket.cc',
diff --git a/gin/gin.target.darwin-arm.mk b/gin/gin.target.darwin-arm.mk
index fa58bca..2167464 100644
--- a/gin/gin.target.darwin-arm.mk
+++ b/gin/gin.target.darwin-arm.mk
@@ -100,6 +100,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gin/gin.target.darwin-mips.mk b/gin/gin.target.darwin-mips.mk
index e165d4f..cc0a291 100644
--- a/gin/gin.target.darwin-mips.mk
+++ b/gin/gin.target.darwin-mips.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -186,6 +187,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gin/gin.target.darwin-x86.mk b/gin/gin.target.darwin-x86.mk
index 5c8c2fa..5c05c80 100644
--- a/gin/gin.target.darwin-x86.mk
+++ b/gin/gin.target.darwin-x86.mk
@@ -101,6 +101,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -189,6 +190,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gin/gin.target.darwin-x86_64.mk b/gin/gin.target.darwin-x86_64.mk
new file mode 100644
index 0000000..e2a9b04
--- /dev/null
+++ b/gin/gin.target.darwin-x86_64.mk
@@ -0,0 +1,288 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gin_gin_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gin/arguments.cc \
+	gin/array_buffer.cc \
+	gin/context_holder.cc \
+	gin/converter.cc \
+	gin/dictionary.cc \
+	gin/function_template.cc \
+	gin/interceptor.cc \
+	gin/isolate_holder.cc \
+	gin/modules/console.cc \
+	gin/modules/file_module_provider.cc \
+	gin/modules/module_registry.cc \
+	gin/modules/module_runner_delegate.cc \
+	gin/modules/timer.cc \
+	gin/object_template_builder.cc \
+	gin/per_context_data.cc \
+	gin/per_isolate_data.cc \
+	gin/runner.cc \
+	gin/shell_runner.cc \
+	gin/try_catch.cc \
+	gin/wrappable.cc \
+	gin/wrapper_info.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGIN_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/v8/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGIN_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/v8/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gin_gin_gyp
+
+# Alias gyp target name.
+.PHONY: gin
+gin: gin_gin_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gin/gin.target.linux-arm.mk b/gin/gin.target.linux-arm.mk
index fa58bca..2167464 100644
--- a/gin/gin.target.linux-arm.mk
+++ b/gin/gin.target.linux-arm.mk
@@ -100,6 +100,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gin/gin.target.linux-mips.mk b/gin/gin.target.linux-mips.mk
index e165d4f..cc0a291 100644
--- a/gin/gin.target.linux-mips.mk
+++ b/gin/gin.target.linux-mips.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -186,6 +187,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gin/gin.target.linux-x86.mk b/gin/gin.target.linux-x86.mk
index 5c8c2fa..5c05c80 100644
--- a/gin/gin.target.linux-x86.mk
+++ b/gin/gin.target.linux-x86.mk
@@ -101,6 +101,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -189,6 +190,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGIN_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gin/gin.target.linux-x86_64.mk b/gin/gin.target.linux-x86_64.mk
new file mode 100644
index 0000000..e2a9b04
--- /dev/null
+++ b/gin/gin.target.linux-x86_64.mk
@@ -0,0 +1,288 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gin_gin_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gin/arguments.cc \
+	gin/array_buffer.cc \
+	gin/context_holder.cc \
+	gin/converter.cc \
+	gin/dictionary.cc \
+	gin/function_template.cc \
+	gin/interceptor.cc \
+	gin/isolate_holder.cc \
+	gin/modules/console.cc \
+	gin/modules/file_module_provider.cc \
+	gin/modules/module_registry.cc \
+	gin/modules/module_runner_delegate.cc \
+	gin/modules/timer.cc \
+	gin/object_template_builder.cc \
+	gin/per_context_data.cc \
+	gin/per_isolate_data.cc \
+	gin/runner.cc \
+	gin/shell_runner.cc \
+	gin/try_catch.cc \
+	gin/wrappable.cc \
+	gin/wrapper_info.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGIN_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/v8/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGIN_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/v8/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gin_gin_gyp
+
+# Alias gyp target name.
+.PHONY: gin
+gin: gin_gin_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/google_apis/OWNERS b/google_apis/OWNERS
index e3221f4..258354a 100644
--- a/google_apis/OWNERS
+++ b/google_apis/OWNERS
@@ -1,2 +1 @@
-joi@chromium.org
 rogerta@chromium.org
diff --git a/google_apis/drive/drive_api_parser.cc b/google_apis/drive/drive_api_parser.cc
index 1eefb8b..fff3d9d 100644
--- a/google_apis/drive/drive_api_parser.cc
+++ b/google_apis/drive/drive_api_parser.cc
@@ -38,6 +38,28 @@
   return true;
 }
 
+// Converts |value| to |result|.
+bool GetParentsFromValue(const base::Value* value,
+                         std::vector<ParentReference>* result) {
+  DCHECK(value);
+  DCHECK(result);
+
+  const base::ListValue* list_value = NULL;
+  if (!value->GetAsList(&list_value))
+    return false;
+
+  base::JSONValueConverter<ParentReference> converter;
+  result->resize(list_value->GetSize());
+  for (size_t i = 0; i < list_value->GetSize(); ++i) {
+    const base::Value* parent_value = NULL;
+    if (!list_value->Get(i, &parent_value) ||
+        !converter.Convert(*parent_value, &(*result)[i]))
+      return false;
+  }
+
+  return true;
+}
+
 // Converts |value| to |result|. The key of |value| is app_id, and its value
 // is URL to open the resource on the web app.
 bool GetOpenWithLinksFromDictionaryValue(
@@ -469,8 +491,10 @@
   converter->RegisterCustomField<GURL>(kAlternateLink,
                                        &FileResource::alternate_link_,
                                        GetGURLFromString);
-  converter->RegisterRepeatedMessage<ParentReference>(kParents,
-                                                      &FileResource::parents_);
+  converter->RegisterCustomValueField<std::vector<ParentReference> >(
+      kParents,
+      &FileResource::parents_,
+      GetParentsFromValue);
   converter->RegisterCustomValueField<std::vector<OpenWithLink> >(
       kOpenWithLinks,
       &FileResource::open_with_links_,
diff --git a/google_apis/drive/drive_api_parser.h b/google_apis/drive/drive_api_parser.h
index e51b864..daa2b4b 100644
--- a/google_apis/drive/drive_api_parser.h
+++ b/google_apis/drive/drive_api_parser.h
@@ -365,8 +365,6 @@
   void set_is_root(bool is_root) { is_root_ = is_root; }
 
  private:
-  friend class base::internal::RepeatedMessageConverter<ParentReference>;
-
   // Parses and initializes data members from content of |value|.
   // Return false if parsing fails.
   bool Parse(const base::Value& value);
@@ -374,8 +372,6 @@
   std::string file_id_;
   GURL parent_link_;
   bool is_root_;
-
-  DISALLOW_COPY_AND_ASSIGN(ParentReference);
 };
 
 // FileLabels represents labels for file or folder.
@@ -422,8 +418,6 @@
   bool trashed_;
   bool restricted_;
   bool viewed_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileLabels);
 };
 
 // ImageMediaMetadata represents image metadata for a file.
@@ -462,8 +456,6 @@
   int width_;
   int height_;
   int rotation_;
-
-  DISALLOW_COPY_AND_ASSIGN(ImageMediaMetadata);
 };
 
 
@@ -549,8 +541,7 @@
   const GURL& alternate_link() const { return alternate_link_; }
 
   // Returns parent references (directories) of this file.
-  const ScopedVector<ParentReference>& parents() const { return parents_; }
-  ScopedVector<ParentReference>* mutable_parents() { return &parents_; }
+  const std::vector<ParentReference>& parents() const { return parents_; }
 
   // Returns the list of links to open the resource with a web app.
   const std::vector<OpenWithLink>& open_with_links() const {
@@ -605,8 +596,9 @@
   void set_alternate_link(const GURL& alternate_link) {
     alternate_link_ = alternate_link;
   }
-  void set_parents(ScopedVector<ParentReference> parents) {
-    parents_ = parents.Pass();
+  std::vector<ParentReference>* mutable_parents() { return &parents_; }
+  std::vector<OpenWithLink>* mutable_open_with_links() {
+    return &open_with_links_;
   }
 
  private:
@@ -634,10 +626,8 @@
   std::string md5_checksum_;
   int64 file_size_;
   GURL alternate_link_;
-  ScopedVector<ParentReference> parents_;
+  std::vector<ParentReference> parents_;
   std::vector<OpenWithLink> open_with_links_;
-
-  DISALLOW_COPY_AND_ASSIGN(FileResource);
 };
 
 // FileList represents a collection of files and folders.
diff --git a/google_apis/drive/drive_api_parser_unittest.cc b/google_apis/drive/drive_api_parser_unittest.cc
index fd9b0c3..89f4c01 100644
--- a/google_apis/drive/drive_api_parser_unittest.cc
+++ b/google_apis/drive/drive_api_parser_unittest.cc
@@ -169,11 +169,11 @@
   EXPECT_EQ(modified_time, file1.modified_by_me_date());
 
   ASSERT_EQ(1U, file1.parents().size());
-  EXPECT_EQ("0B4v7G8yEYAWHYW1OcExsUVZLABC", file1.parents()[0]->file_id());
+  EXPECT_EQ("0B4v7G8yEYAWHYW1OcExsUVZLABC", file1.parents()[0].file_id());
   EXPECT_EQ(GURL("https://www.googleapis.com/drive/v2/files/"
                  "0B4v7G8yEYAWHYW1OcExsUVZLABC"),
-            file1.parents()[0]->parent_link());
-  EXPECT_FALSE(file1.parents()[0]->is_root());
+            file1.parents()[0].parent_link());
+  EXPECT_FALSE(file1.parents()[0].is_root());
 
   EXPECT_EQ("ext", file1.file_extension());
   EXPECT_EQ("d41d8cd98f00b204e9800998ecf8427e", file1.md5_checksum());
@@ -223,8 +223,8 @@
   EXPECT_FALSE(file3.shared());
 
   ASSERT_EQ(1U, file3.parents().size());
-  EXPECT_EQ("0AIv7G8yEYAWHUk9ABC", file3.parents()[0]->file_id());
-  EXPECT_TRUE(file3.parents()[0]->is_root());
+  EXPECT_EQ("0AIv7G8yEYAWHUk9ABC", file3.parents()[0].file_id());
+  EXPECT_TRUE(file3.parents()[0].is_root());
   EXPECT_EQ(0U, file3.open_with_links().size());
 }
 
diff --git a/google_apis/drive/task_util.h b/google_apis/drive/task_util.h
index 358c280..3cba9bd 100644
--- a/google_apis/drive/task_util.h
+++ b/google_apis/drive/task_util.h
@@ -95,17 +95,6 @@
   }
 };
 
-// ComposedCallback with four arguments, and the second one is scoped_ptr.
-template<typename T1, typename T2, typename D2, typename T3, typename T4>
-struct ComposedCallback<void(T1, scoped_ptr<T2, D2>, T3, T4)> {
-  static void Run(
-      const base::Callback<void(const base::Closure&)>& runner,
-      const base::Callback<void(T1, scoped_ptr<T2, D2>, T3, T4)>& callback,
-      T1 arg1, scoped_ptr<T2, D2> arg2, T3 arg3, T4 arg4) {
-    runner.Run(base::Bind(callback, arg1, base::Passed(&arg2), arg3, arg4));
-  }
-};
-
 }  // namespace internal
 
 // Returns callback that takes arguments (arg1, arg2, ...), create a closure
diff --git a/google_apis/gaia/google_service_auth_error.cc b/google_apis/gaia/google_service_auth_error.cc
index 736bbd6..d968136 100644
--- a/google_apis/gaia/google_service_auth_error.cc
+++ b/google_apis/gaia/google_service_auth_error.cc
@@ -81,12 +81,6 @@
       error_message_(error_message) {
 }
 
-GoogleServiceAuthError::GoogleServiceAuthError(const std::string& error_message)
-    : state_(INVALID_GAIA_CREDENTIALS),
-      network_error_(0),
-      error_message_(error_message) {
-}
-
 // static
 GoogleServiceAuthError
     GoogleServiceAuthError::FromConnectionError(int error) {
@@ -259,14 +253,3 @@
                captcha_unlock_url, image_width, image_height),
       network_error_(0) {
 }
-
-GoogleServiceAuthError::GoogleServiceAuthError(
-    State s,
-    const std::string& captcha_token,
-    const std::string& prompt_text,
-    const std::string& alternate_text,
-    int field_length)
-    : state_(s),
-      second_factor_(captcha_token, prompt_text, alternate_text, field_length),
-      network_error_(0) {
-}
diff --git a/google_apis/gaia/google_service_auth_error.h b/google_apis/gaia/google_service_auth_error.h
index 19fdb51..3d441ef 100644
--- a/google_apis/gaia/google_service_auth_error.h
+++ b/google_apis/gaia/google_service_auth_error.h
@@ -189,8 +189,6 @@
   // Construct a GoogleServiceAuthError from |state| and |error_message|.
   GoogleServiceAuthError(State state, const std::string& error_message);
 
-  explicit GoogleServiceAuthError(const std::string& error_message);
-
   GoogleServiceAuthError(State s, const std::string& captcha_token,
                          const GURL& captcha_audio_url,
                          const GURL& captcha_image_url,
@@ -198,11 +196,6 @@
                          int image_width,
                          int image_height);
 
-  GoogleServiceAuthError(State s, const std::string& captcha_token,
-                         const std::string& prompt_text,
-                         const std::string& alternate_text,
-                         int field_length);
-
   State state_;
   Captcha captcha_;
   SecondFactor second_factor_;
diff --git a/google_apis/gcm/engine/connection_factory.h b/google_apis/gcm/engine/connection_factory.h
index 298bf5e..393d6a9 100644
--- a/google_apis/gcm/engine/connection_factory.h
+++ b/google_apis/gcm/engine/connection_factory.h
@@ -30,6 +30,7 @@
     CLOSE_COMMAND,      // Received a close command.
     HEARTBEAT_FAILURE,  // Heartbeat was not acknowledged in time.
     SOCKET_FAILURE,     // net::Socket error.
+    NETWORK_CHANGE,     // NetworkChangeNotifier notified of a network change.
     // Count of total number of connection reset reasons. All new reset reasons
     // should be added above this line.
     CONNECTION_RESET_COUNT,
diff --git a/google_apis/gcm/engine/connection_factory_impl.cc b/google_apis/gcm/engine/connection_factory_impl.cc
index ebfd367..9dff1f6 100644
--- a/google_apis/gcm/engine/connection_factory_impl.cc
+++ b/google_apis/gcm/engine/connection_factory_impl.cc
@@ -41,19 +41,23 @@
 }  // namespace
 
 ConnectionFactoryImpl::ConnectionFactoryImpl(
-    const GURL& mcs_endpoint,
+    const std::vector<GURL>& mcs_endpoints,
     const net::BackoffEntry::Policy& backoff_policy,
     scoped_refptr<net::HttpNetworkSession> network_session,
     net::NetLog* net_log)
-  : mcs_endpoint_(mcs_endpoint),
+  : mcs_endpoints_(mcs_endpoints),
+    next_endpoint_(0),
+    last_successful_endpoint_(0),
     backoff_policy_(backoff_policy),
     network_session_(network_session),
     bound_net_log_(
         net::BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)),
     pac_request_(NULL),
     connecting_(false),
+    waiting_for_backoff_(false),
     logging_in_(false),
     weak_ptr_factory_(this) {
+  DCHECK_GE(mcs_endpoints_.size(), 1U);
 }
 
 ConnectionFactoryImpl::~ConnectionFactoryImpl() {
@@ -75,13 +79,12 @@
 
   net::NetworkChangeNotifier::AddIPAddressObserver(this);
   net::NetworkChangeNotifier::AddConnectionTypeObserver(this);
-  connection_handler_.reset(
-      new ConnectionHandlerImpl(
-          base::TimeDelta::FromMilliseconds(kReadTimeoutMs),
-          read_callback,
-          write_callback,
-          base::Bind(&ConnectionFactoryImpl::ConnectionHandlerCallback,
-                     weak_ptr_factory_.GetWeakPtr())));
+  connection_handler_ = CreateConnectionHandler(
+      base::TimeDelta::FromMilliseconds(kReadTimeoutMs),
+      read_callback,
+      write_callback,
+      base::Bind(&ConnectionFactoryImpl::ConnectionHandlerCallback,
+                 weak_ptr_factory_.GetWeakPtr())).Pass();
 }
 
 ConnectionHandler* ConnectionFactoryImpl::GetConnectionHandler() const {
@@ -91,35 +94,53 @@
 void ConnectionFactoryImpl::Connect() {
   DCHECK(connection_handler_);
 
-  connecting_ = true;
+  if (connecting_ || waiting_for_backoff_)
+    return;  // Connection attempt already in progress or pending.
+
+  if (IsEndpointReachable())
+    return;  // Already connected.
+
+  ConnectWithBackoff();
+}
+
+void ConnectionFactoryImpl::ConnectWithBackoff() {
+  // If a canary managed to connect while a backoff expiration was pending,
+  // just cleanup the internal state.
+  if (connecting_ || IsEndpointReachable()) {
+    waiting_for_backoff_ = false;
+    return;
+  }
+
   if (backoff_entry_->ShouldRejectRequest()) {
     DVLOG(1) << "Delaying MCS endpoint connection for "
              << backoff_entry_->GetTimeUntilRelease().InMilliseconds()
              << " milliseconds.";
+    waiting_for_backoff_ = true;
     base::MessageLoop::current()->PostDelayedTask(
         FROM_HERE,
-        base::Bind(&ConnectionFactoryImpl::Connect,
+        base::Bind(&ConnectionFactoryImpl::ConnectWithBackoff,
                    weak_ptr_factory_.GetWeakPtr()),
         backoff_entry_->GetTimeUntilRelease());
     return;
   }
 
   DVLOG(1) << "Attempting connection to MCS endpoint.";
+  waiting_for_backoff_ = false;
   ConnectImpl();
 }
 
 bool ConnectionFactoryImpl::IsEndpointReachable() const {
-  return connection_handler_ &&
-      connection_handler_->CanSendMessage() &&
-      !connecting_;
+  return connection_handler_ && connection_handler_->CanSendMessage();
 }
 
 void ConnectionFactoryImpl::SignalConnectionReset(
     ConnectionResetReason reason) {
   // A failure can trigger multiple resets, so no need to do anything if a
   // connection is already in progress.
-  if (connecting_)
+  if (connecting_) {
+    DVLOG(1) << "Connection in progress, ignoring reset.";
     return;
+  }
 
   UMA_HISTOGRAM_ENUMERATION("GCM.ConnectionResetReason",
                             reason,
@@ -135,6 +156,16 @@
   }
 
   CloseSocket();
+  DCHECK(!IsEndpointReachable());
+
+  // Network changes get special treatment as they can trigger a one-off canary
+  // request that bypasses backoff (but does nothing if a connection is in
+  // progress). Other connection reset events can be ignored as a connection
+  // is already awaiting backoff expiration.
+  if (waiting_for_backoff_ && reason != NETWORK_CHANGE) {
+    DVLOG(1) << "Backoff expiration pending, ignoring reset.";
+    return;
+  }
 
   if (logging_in_) {
     // Failures prior to login completion just reuse the existing backoff entry.
@@ -146,10 +177,15 @@
     // the backoff entry that was saved off at login completion time.
     backoff_entry_.swap(previous_backoff_);
     backoff_entry_->InformOfRequest(false);
+  } else if (reason == NETWORK_CHANGE) {
+    ConnectImpl();  // Canary attempts bypass backoff without resetting it.
+    return;
   } else {
     // We shouldn't be in backoff in thise case.
     DCHECK_EQ(0, backoff_entry_->failure_count());
   }
+  DCHECK(!connecting_);
+  DCHECK(!waiting_for_backoff_);
 
   // At this point the last login time has been consumed or deemed irrelevant,
   // reset it.
@@ -169,27 +205,34 @@
   if (type == net::NetworkChangeNotifier::CONNECTION_NONE)
     return;
 
-  // TODO(zea): implement different backoff/retry policies based on connection
-  // type.
-  DVLOG(1) << "Connection type changed to " << type << ", resetting backoff.";
-  backoff_entry_->Reset();
-  // Connect(..) should be retrying with backoff already if a connection is
-  // necessary, so no need to call again.
+  DVLOG(1) << "Connection type changed to " << type << ", reconnecting.";
+
+  // The connection may have been silently dropped, attempt to reconnect.
+  SignalConnectionReset(NETWORK_CHANGE);
 }
 
 void ConnectionFactoryImpl::OnIPAddressChanged() {
-  DVLOG(1) << "IP Address changed, resetting backoff.";
-  backoff_entry_->Reset();
-  // Connect(..) should be retrying with backoff already if a connection is
-  // necessary, so no need to call again.
+  DVLOG(1) << "IP Address changed, reconnecting.";
+
+  // The connection may have been silently dropped, attempt to reconnect.
+  SignalConnectionReset(NETWORK_CHANGE);
+}
+
+GURL ConnectionFactoryImpl::GetCurrentEndpoint() const {
+  // Note that IsEndpointReachable() returns false anytime connecting_ is true,
+  // so while connecting this always uses |next_endpoint_|.
+  if (IsEndpointReachable())
+    return mcs_endpoints_[last_successful_endpoint_];
+  return mcs_endpoints_[next_endpoint_];
 }
 
 void ConnectionFactoryImpl::ConnectImpl() {
-  DCHECK(connecting_);
+  DCHECK(!IsEndpointReachable());
   DCHECK(!socket_handle_.socket());
 
+  connecting_ = true;
   int status = network_session_->proxy_service()->ResolveProxy(
-      mcs_endpoint_,
+      GetCurrentEndpoint(),
       &proxy_info_,
       base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
                  weak_ptr_factory_.GetWeakPtr()),
@@ -215,6 +258,18 @@
   return scoped_ptr<net::BackoffEntry>(new net::BackoffEntry(policy));
 }
 
+scoped_ptr<ConnectionHandler> ConnectionFactoryImpl::CreateConnectionHandler(
+    base::TimeDelta read_timeout,
+    const ConnectionHandler::ProtoReceivedCallback& read_callback,
+    const ConnectionHandler::ProtoSentCallback& write_callback,
+    const ConnectionHandler::ConnectionChangedCallback& connection_callback) {
+  return make_scoped_ptr<ConnectionHandler>(
+      new ConnectionHandlerImpl(read_timeout,
+                                read_callback,
+                                write_callback,
+                                connection_callback));
+}
+
 base::TimeTicks ConnectionFactoryImpl::NowTicks() {
   return base::TimeTicks::Now();
 }
@@ -234,13 +289,29 @@
     CloseSocket();
     backoff_entry_->InformOfRequest(false);
     UMA_HISTOGRAM_SPARSE_SLOWLY("GCM.ConnectionFailureErrorCode", result);
+
+    // If there are other endpoints available, use the next endpoint on the
+    // subsequent retry.
+    next_endpoint_++;
+    if (next_endpoint_ >= mcs_endpoints_.size())
+      next_endpoint_ = 0;
+    connecting_ = false;
     Connect();
     return;
   }
 
   UMA_HISTOGRAM_BOOLEAN("GCM.ConnectionSuccessRate", true);
+  UMA_HISTOGRAM_COUNTS("GCM.ConnectionEndpoint", next_endpoint_);
+  UMA_HISTOGRAM_BOOLEAN("GCM.ConnectedViaProxy",
+                        !(proxy_info_.is_empty() || proxy_info_.is_direct()));
   ReportSuccessfulProxyConnection();
 
+  // Reset the endpoint back to the default.
+  // TODO(zea): consider prioritizing endpoints more intelligently based on
+  // which ones succeed most for this client? Although that will affect
+  // measuring the success rate of the default endpoint vs fallback.
+  last_successful_endpoint_ = next_endpoint_;
+  next_endpoint_ = 0;
   connecting_ = false;
   logging_in_ = true;
   DVLOG(1) << "MCS endpoint socket connection success, starting login.";
@@ -300,7 +371,7 @@
   net::SSLConfig ssl_config;
   network_session_->ssl_config_service()->GetSSLConfig(&ssl_config);
   status = net::InitSocketHandleForTlsConnect(
-      net::HostPortPair::FromURL(mcs_endpoint_),
+      net::HostPortPair::FromURL(GetCurrentEndpoint()),
       network_session_.get(),
       proxy_info_,
       ssl_config,
@@ -374,7 +445,7 @@
   }
 
   int status = network_session_->proxy_service()->ReconsiderProxyAfterError(
-      mcs_endpoint_, &proxy_info_,
+      GetCurrentEndpoint(), &proxy_info_,
       base::Bind(&ConnectionFactoryImpl::OnProxyResolveDone,
                  weak_ptr_factory_.GetWeakPtr()),
       &pac_request_,
diff --git a/google_apis/gcm/engine/connection_factory_impl.h b/google_apis/gcm/engine/connection_factory_impl.h
index 967c6c1..f637232 100644
--- a/google_apis/gcm/engine/connection_factory_impl.h
+++ b/google_apis/gcm/engine/connection_factory_impl.h
@@ -32,7 +32,7 @@
     public net::NetworkChangeNotifier::IPAddressObserver {
  public:
   ConnectionFactoryImpl(
-      const GURL& mcs_endpoint,
+      const std::vector<GURL>& mcs_endpoints,
       const net::BackoffEntry::Policy& backoff_policy,
       scoped_refptr<net::HttpNetworkSession> network_session,
       net::NetLog* net_log);
@@ -54,6 +54,11 @@
       net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
   virtual void OnIPAddressChanged() OVERRIDE;
 
+  // Returns the server to which the factory is currently connected, or if
+  // a connection is currently pending, the server to which the next connection
+  // attempt will be made.
+  GURL GetCurrentEndpoint() const;
+
  protected:
   // Implementation of Connect(..). If not in backoff, uses |login_request_|
   // in attempting a connection/handshake. On connection/handshake failure, goes
@@ -70,6 +75,14 @@
   virtual scoped_ptr<net::BackoffEntry> CreateBackoffEntry(
       const net::BackoffEntry::Policy* const policy);
 
+  // Helper method for creating the connection handler.
+  // Virtual for testing.
+  virtual scoped_ptr<ConnectionHandler> CreateConnectionHandler(
+      base::TimeDelta read_timeout,
+      const ConnectionHandler::ProtoReceivedCallback& read_callback,
+      const ConnectionHandler::ProtoSentCallback& write_callback,
+      const ConnectionHandler::ConnectionChangedCallback& connection_callback);
+
   // Returns the current time in Ticks.
   // Virtual for testing.
   virtual base::TimeTicks NowTicks();
@@ -81,6 +94,10 @@
   void ConnectionHandlerCallback(int result);
 
  private:
+  // Helper method for checking backoff and triggering a connection as
+  // necessary.
+  void ConnectWithBackoff();
+
   // Proxy resolution and connection functions.
   void OnProxyResolveDone(int status);
   void OnProxyConnectDone(int status);
@@ -89,8 +106,12 @@
 
   void CloseSocket();
 
-  // The MCS endpoint to make connections to.
-  const GURL mcs_endpoint_;
+  // The MCS endpoints to make connections to, sorted in order of priority.
+  const std::vector<GURL> mcs_endpoints_;
+  // Index to the endpoint for which a connection should be attempted next.
+  size_t next_endpoint_;
+  // Index to the endpoint that was last successfully connected.
+  size_t last_successful_endpoint_;
 
   // The backoff policy to use.
   const net::BackoffEntry::Policy backoff_policy_;
@@ -112,11 +133,14 @@
   // completion.
   scoped_ptr<net::BackoffEntry> previous_backoff_;
 
-  // Whether a connection attempt is currently in progress or we're in backoff
-  // waiting until the next connection attempt. |!connecting_| denotes
-  // steady state with an active connection.
+  // Whether a connection attempt is currently actively in progress.
   bool connecting_;
 
+  // Whether the client is waiting for backoff to finish before attempting to
+  // connect. Canary jobs are able to preempt connections pending backoff
+  // expiration.
+  bool waiting_for_backoff_;
+
   // Whether login successfully completed after the connection was established.
   // If a connection reset happens while attempting to log in, the current
   // backoff entry is reused (after incrementing with a new failure).
@@ -127,7 +151,7 @@
   base::TimeTicks last_login_time_;
 
   // The current connection handler, if one exists.
-  scoped_ptr<ConnectionHandlerImpl> connection_handler_;
+  scoped_ptr<ConnectionHandler> connection_handler_;
 
   // Builder for generating new login requests.
   BuildLoginRequestCallback request_builder_;
diff --git a/google_apis/gcm/engine/connection_factory_impl_unittest.cc b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
index 82c3f18..4983ea9 100644
--- a/google_apis/gcm/engine/connection_factory_impl_unittest.cc
+++ b/google_apis/gcm/engine/connection_factory_impl_unittest.cc
@@ -9,6 +9,8 @@
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
+#include "google_apis/gcm/base/mcs_util.h"
+#include "google_apis/gcm/engine/fake_connection_handler.h"
 #include "net/base/backoff_entry.h"
 #include "net/http/http_network_session.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -19,6 +21,7 @@
 namespace {
 
 const char kMCSEndpoint[] = "http://my.server";
+const char kMCSEndpoint2[] = "http://my.alt.server";
 
 const int kBackoffDelayMs = 1;
 const int kBackoffMultiplier = 2;
@@ -50,6 +53,13 @@
   false,
 };
 
+std::vector<GURL> BuildEndpoints() {
+  std::vector<GURL> endpoints;
+  endpoints.push_back(GURL(kMCSEndpoint));
+  endpoints.push_back(GURL(kMCSEndpoint2));
+  return endpoints;
+}
+
 // Helper for calculating total expected exponential backoff delay given an
 // arbitrary number of failed attempts. See BackoffEntry::CalculateReleaseTime.
 double CalculateBackoff(int num_attempts) {
@@ -62,15 +72,11 @@
   return delay;
 }
 
-// Helper methods that should never actually be called due to real connections
-// being stubbed out.
 void ReadContinuation(
     scoped_ptr<google::protobuf::MessageLite> message) {
-  ADD_FAILURE();
 }
 
 void WriteContinuation() {
-  ADD_FAILURE();
 }
 
 class TestBackoffEntry : public net::BackoffEntry {
@@ -102,11 +108,19 @@
   TestConnectionFactoryImpl(const base::Closure& finished_callback);
   virtual ~TestConnectionFactoryImpl();
 
+  void InitializeFactory();
+
   // Overridden stubs.
   virtual void ConnectImpl() OVERRIDE;
   virtual void InitHandler() OVERRIDE;
   virtual scoped_ptr<net::BackoffEntry> CreateBackoffEntry(
       const net::BackoffEntry::Policy* const policy) OVERRIDE;
+  virtual scoped_ptr<ConnectionHandler> CreateConnectionHandler(
+      base::TimeDelta read_timeout,
+      const ConnectionHandler::ProtoReceivedCallback& read_callback,
+      const ConnectionHandler::ProtoSentCallback& write_callback,
+      const ConnectionHandler::ConnectionChangedCallback& connection_callback)
+          OVERRIDE;
   virtual base::TimeTicks NowTicks() OVERRIDE;
 
   // Helpers for verifying connection attempts are made. Connection results
@@ -128,18 +142,21 @@
   bool connections_fulfilled_;
   // Callback to invoke when all connection attempts have been made.
   base::Closure finished_callback_;
+  // The current fake connection handler..
+  FakeConnectionHandler* fake_handler_;
 };
 
 TestConnectionFactoryImpl::TestConnectionFactoryImpl(
     const base::Closure& finished_callback)
-    : ConnectionFactoryImpl(GURL(kMCSEndpoint),
+    : ConnectionFactoryImpl(BuildEndpoints(),
                             net::BackoffEntry::Policy(),
                             NULL,
                             NULL),
       connect_result_(net::ERR_UNEXPECTED),
       num_expected_attempts_(0),
       connections_fulfilled_(true),
-      finished_callback_(finished_callback) {
+      finished_callback_(finished_callback),
+      fake_handler_(NULL) {
   // Set a non-null time.
   tick_clock_.Advance(base::TimeDelta::FromMilliseconds(1));
 }
@@ -150,7 +167,8 @@
 
 void TestConnectionFactoryImpl::ConnectImpl() {
   ASSERT_GT(num_expected_attempts_, 0);
-
+  scoped_ptr<mcs_proto::LoginRequest> request(BuildLoginRequest(0, 0, ""));
+  GetConnectionHandler()->Init(*request, NULL);
   OnConnectDone(connect_result_);
   if (!NextRetryAttempt().is_null()) {
     // Advance the time to the next retry time.
@@ -176,6 +194,18 @@
   return scoped_ptr<net::BackoffEntry>(new TestBackoffEntry(&tick_clock_));
 }
 
+scoped_ptr<ConnectionHandler>
+TestConnectionFactoryImpl::CreateConnectionHandler(
+    base::TimeDelta read_timeout,
+    const ConnectionHandler::ProtoReceivedCallback& read_callback,
+    const ConnectionHandler::ProtoSentCallback& write_callback,
+    const ConnectionHandler::ConnectionChangedCallback& connection_callback) {
+  fake_handler_ = new FakeConnectionHandler(
+      base::Bind(&ReadContinuation),
+      base::Bind(&WriteContinuation));
+  return make_scoped_ptr<ConnectionHandler>(fake_handler_);
+}
+
 base::TimeTicks TestConnectionFactoryImpl::NowTicks() {
   return tick_clock_.NowTicks();
 }
@@ -186,6 +216,10 @@
   connections_fulfilled_ = false;
   connect_result_ = connect_result;
   num_expected_attempts_ = 1;
+  fake_handler_->ExpectOutgoingMessage(
+      MCSMessage(kLoginRequestTag,
+                 BuildLoginRequest(0, 0, "").PassAs<
+                     const google::protobuf::MessageLite>()));
 }
 
 void TestConnectionFactoryImpl::SetMultipleConnectResults(
@@ -197,6 +231,12 @@
   connections_fulfilled_ = false;
   connect_result_ = connect_result;
   num_expected_attempts_ = num_expected_attempts;
+  for (int i = 0 ; i < num_expected_attempts; ++i) {
+    fake_handler_->ExpectOutgoingMessage(
+        MCSMessage(kLoginRequestTag,
+                   BuildLoginRequest(0, 0, "").PassAs<
+                       const google::protobuf::MessageLite>()));
+  }
 }
 
 class ConnectionFactoryImplTest : public testing::Test {
@@ -219,7 +259,12 @@
 ConnectionFactoryImplTest::ConnectionFactoryImplTest()
    : factory_(base::Bind(&ConnectionFactoryImplTest::ConnectionsComplete,
                          base::Unretained(this))),
-     run_loop_(new base::RunLoop()) {}
+     run_loop_(new base::RunLoop()) {
+  factory()->Initialize(
+      ConnectionFactory::BuildLoginRequestCallback(),
+      ConnectionHandler::ProtoReceivedCallback(),
+      ConnectionHandler::ProtoSentCallback());
+}
 ConnectionFactoryImplTest::~ConnectionFactoryImplTest() {}
 
 void ConnectionFactoryImplTest::WaitForConnections() {
@@ -235,11 +280,6 @@
 
 // Verify building a connection handler works.
 TEST_F(ConnectionFactoryImplTest, Initialize) {
-  EXPECT_FALSE(factory()->IsEndpointReachable());
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      base::Bind(&ReadContinuation),
-      base::Bind(&WriteContinuation));
   ConnectionHandler* handler = factory()->GetConnectionHandler();
   ASSERT_TRUE(handler);
   EXPECT_FALSE(factory()->IsEndpointReachable());
@@ -247,51 +287,42 @@
 
 // An initial successful connection should not result in backoff.
 TEST_F(ConnectionFactoryImplTest, ConnectSuccess) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::OK);
   factory()->Connect();
   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+  EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[0]);
+  EXPECT_TRUE(factory()->IsEndpointReachable());
 }
 
-// A connection failure should result in backoff.
+// A connection failure should result in backoff, and attempting the fallback
+// endpoint next.
 TEST_F(ConnectionFactoryImplTest, ConnectFail) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
   factory()->Connect();
   EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
+  EXPECT_EQ(factory()->GetCurrentEndpoint(), BuildEndpoints()[1]);
+  EXPECT_FALSE(factory()->IsEndpointReachable());
 }
 
 // A connection success after a failure should reset backoff.
 TEST_F(ConnectionFactoryImplTest, FailThenSucceed) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
   base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
   factory()->Connect();
   WaitForConnections();
+  EXPECT_FALSE(factory()->IsEndpointReachable());
   base::TimeTicks retry_time = factory()->NextRetryAttempt();
   EXPECT_FALSE(retry_time.is_null());
   EXPECT_GE((retry_time - connect_time).InMilliseconds(), CalculateBackoff(1));
   factory()->SetConnectResult(net::OK);
   WaitForConnections();
   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+  EXPECT_TRUE(factory()->IsEndpointReachable());
 }
 
 // Multiple connection failures should retry with an exponentially increasing
 // backoff, then reset on success.
 TEST_F(ConnectionFactoryImplTest, MultipleFailuresThenSucceed) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
 
   const int kNumAttempts = 5;
   factory()->SetMultipleConnectResults(net::ERR_CONNECTION_FAILED,
@@ -300,6 +331,7 @@
   base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
   factory()->Connect();
   WaitForConnections();
+  EXPECT_FALSE(factory()->IsEndpointReachable());
   base::TimeTicks retry_time = factory()->NextRetryAttempt();
   EXPECT_FALSE(retry_time.is_null());
   EXPECT_GE((retry_time - connect_time).InMilliseconds(),
@@ -308,59 +340,80 @@
   factory()->SetConnectResult(net::OK);
   WaitForConnections();
   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+  EXPECT_TRUE(factory()->IsEndpointReachable());
 }
 
-// IP events should reset backoff.
+// IP events should trigger canary connections.
 TEST_F(ConnectionFactoryImplTest, FailThenIPEvent) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
   factory()->Connect();
   WaitForConnections();
-  EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
+  base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
+  EXPECT_FALSE(initial_backoff.is_null());
 
+  factory()->SetConnectResult(net::ERR_FAILED);
   factory()->OnIPAddressChanged();
-  EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+  WaitForConnections();
+
+  // Backoff should increase.
+  base::TimeTicks next_backoff = factory()->NextRetryAttempt();
+  EXPECT_GT(next_backoff, initial_backoff);
+  EXPECT_FALSE(factory()->IsEndpointReachable());
 }
 
-// Connection type events should reset backoff.
+// Connection type events should trigger canary connections.
 TEST_F(ConnectionFactoryImplTest, FailThenConnectionTypeEvent) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
   factory()->Connect();
   WaitForConnections();
-  EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
+  base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
+  EXPECT_FALSE(initial_backoff.is_null());
 
+  factory()->SetConnectResult(net::ERR_FAILED);
   factory()->OnConnectionTypeChanged(
       net::NetworkChangeNotifier::CONNECTION_WIFI);
-  EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+  WaitForConnections();
+
+  // Backoff should increase.
+  base::TimeTicks next_backoff = factory()->NextRetryAttempt();
+  EXPECT_GT(next_backoff, initial_backoff);
+  EXPECT_FALSE(factory()->IsEndpointReachable());
+}
+
+// Verify that we reconnect even if a canary succeeded then disconnected while
+// a backoff was pending.
+TEST_F(ConnectionFactoryImplTest, CanarySucceedsThenDisconnects) {
+  factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
+  factory()->Connect();
+  WaitForConnections();
+  base::TimeTicks initial_backoff = factory()->NextRetryAttempt();
+  EXPECT_FALSE(initial_backoff.is_null());
+
+  factory()->SetConnectResult(net::OK);
+  factory()->OnConnectionTypeChanged(
+      net::NetworkChangeNotifier::CONNECTION_WIFI);
+  WaitForConnections();
+  EXPECT_TRUE(factory()->IsEndpointReachable());
+
+  factory()->SetConnectResult(net::OK);
+  factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
+  EXPECT_FALSE(factory()->IsEndpointReachable());
+  WaitForConnections();
+  EXPECT_TRUE(factory()->IsEndpointReachable());
 }
 
 // Fail after successful connection via signal reset.
 TEST_F(ConnectionFactoryImplTest, FailViaSignalReset) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::OK);
   factory()->Connect();
   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
 
   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
   EXPECT_FALSE(factory()->NextRetryAttempt().is_null());
-  EXPECT_FALSE(factory()->GetConnectionHandler()->CanSendMessage());
+  EXPECT_FALSE(factory()->IsEndpointReachable());
 }
 
 TEST_F(ConnectionFactoryImplTest, IgnoreResetWhileConnecting) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::OK);
   factory()->Connect();
   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
@@ -368,21 +421,19 @@
   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
   base::TimeTicks retry_time = factory()->NextRetryAttempt();
   EXPECT_FALSE(retry_time.is_null());
+  EXPECT_FALSE(factory()->IsEndpointReachable());
 
   const int kNumAttempts = 5;
   for (int i = 0; i < kNumAttempts; ++i)
     factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
   EXPECT_EQ(retry_time, factory()->NextRetryAttempt());
+  EXPECT_FALSE(factory()->IsEndpointReachable());
 }
 
 // Go into backoff due to connection failure. On successful connection, receive
 // a signal reset. The original backoff should be restored and extended, rather
 // than a new backoff starting from scratch.
 TEST_F(ConnectionFactoryImplTest, SignalResetRestoresBackoff) {
-  factory()->Initialize(
-      ConnectionFactory::BuildLoginRequestCallback(),
-      ConnectionHandler::ProtoReceivedCallback(),
-      ConnectionHandler::ProtoSentCallback());
   factory()->SetConnectResult(net::ERR_CONNECTION_FAILED);
   base::TimeTicks connect_time = factory()->tick_clock()->NowTicks();
   factory()->Connect();
@@ -396,7 +447,7 @@
   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
 
   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
-  EXPECT_FALSE(factory()->GetConnectionHandler()->CanSendMessage());
+  EXPECT_FALSE(factory()->IsEndpointReachable());
   EXPECT_NE(retry_time, factory()->NextRetryAttempt());
   retry_time = factory()->NextRetryAttempt();
   EXPECT_FALSE(retry_time.is_null());
@@ -409,6 +460,7 @@
       factory()->NextRetryAttempt() - connect_time);
   WaitForConnections();
   EXPECT_TRUE(factory()->NextRetryAttempt().is_null());
+  EXPECT_TRUE(factory()->IsEndpointReachable());
 
   factory()->SignalConnectionReset(ConnectionFactory::SOCKET_FAILURE);
   EXPECT_NE(retry_time, factory()->NextRetryAttempt());
@@ -416,6 +468,7 @@
   EXPECT_FALSE(retry_time.is_null());
   EXPECT_GE((retry_time - connect_time).InMilliseconds(),
             CalculateBackoff(3));
+  EXPECT_FALSE(factory()->IsEndpointReachable());
 }
 
 }  // namespace
diff --git a/google_apis/gcm/engine/connection_handler_impl.cc b/google_apis/gcm/engine/connection_handler_impl.cc
index 513220d..d1ef0ee 100644
--- a/google_apis/gcm/engine/connection_handler_impl.cc
+++ b/google_apis/gcm/engine/connection_handler_impl.cc
@@ -402,6 +402,9 @@
   if (socket_)
     socket_->Disconnect();
   socket_ = NULL;
+  handshake_complete_ = false;
+  message_tag_ = 0;
+  message_size_ = 0;
   input_stream_.reset();
   output_stream_.reset();
   weak_ptr_factory_.InvalidateWeakPtrs();
diff --git a/google_apis/gcm/engine/gcm_store.cc b/google_apis/gcm/engine/gcm_store.cc
index f6c81dd..91ad60f 100644
--- a/google_apis/gcm/engine/gcm_store.cc
+++ b/google_apis/gcm/engine/gcm_store.cc
@@ -6,13 +6,6 @@
 
 namespace gcm {
 
-GCMStore::SerialNumberMappings::SerialNumberMappings()
-    : next_serial_number(1LL) {
-}
-
-GCMStore::SerialNumberMappings::~SerialNumberMappings() {
-}
-
 GCMStore::LoadResult::LoadResult()
     : success(false),
       device_android_id(0),
diff --git a/google_apis/gcm/engine/gcm_store.h b/google_apis/gcm/engine/gcm_store.h
index 4387042..659fc7f 100644
--- a/google_apis/gcm/engine/gcm_store.h
+++ b/google_apis/gcm/engine/gcm_store.h
@@ -15,6 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "google_apis/gcm/base/gcm_export.h"
+#include "google_apis/gcm/engine/registration_info.h"
 #include "google_apis/gcm/protocol/mcs.pb.h"
 
 namespace google {
@@ -35,15 +36,6 @@
   typedef std::map<std::string, linked_ptr<google::protobuf::MessageLite> >
       OutgoingMessageMap;
 
-  // Part of load results storing user serial number mapping related values.
-  struct GCM_EXPORT SerialNumberMappings {
-    SerialNumberMappings();
-    ~SerialNumberMappings();
-
-    int64 next_serial_number;
-    std::map<std::string, int64> user_serial_numbers;
-  };
-
   // Container for Load(..) results.
   struct GCM_EXPORT LoadResult {
     LoadResult();
@@ -52,9 +44,9 @@
     bool success;
     uint64 device_android_id;
     uint64 device_security_token;
+    RegistrationInfoMap registrations;
     std::vector<std::string> incoming_messages;
     OutgoingMessageMap outgoing_messages;
-    SerialNumberMappings serial_number_mappings;
   };
 
   typedef std::vector<std::string> PersistentIdList;
@@ -79,6 +71,13 @@
                                     uint64 device_security_token,
                                     const UpdateCallback& callback) = 0;
 
+  // Registration info.
+  virtual void AddRegistration(const std::string& app_id,
+                               const linked_ptr<RegistrationInfo>& registration,
+                               const UpdateCallback& callback) = 0;
+  virtual void RemoveRegistration(const std::string& app_id,
+                                  const UpdateCallback& callback) = 0;
+
   // Unacknowledged incoming message handling.
   virtual void AddIncomingMessage(const std::string& persistent_id,
                                   const UpdateCallback& callback) = 0;
@@ -102,15 +101,6 @@
   virtual void RemoveOutgoingMessages(const PersistentIdList& persistent_ids,
                                       const UpdateCallback& callback) = 0;
 
-  // User serial number handling.
-  virtual void SetNextSerialNumber(int64 next_serial_number,
-                                   const UpdateCallback& callback) = 0;
-  virtual void AddUserSerialNumber(const std::string& username,
-                                   int64 serial_number,
-                                   const UpdateCallback& callback) = 0;
-  virtual void RemoveUserSerialNumber(const std::string& username,
-                                      const UpdateCallback& callback) = 0;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(GCMStore);
 };
diff --git a/google_apis/gcm/engine/gcm_store_impl.cc b/google_apis/gcm/engine/gcm_store_impl.cc
index 100cd57..7f27287 100644
--- a/google_apis/gcm/engine/gcm_store_impl.cc
+++ b/google_apis/gcm/engine/gcm_store_impl.cc
@@ -35,29 +35,32 @@
 const char kDeviceAIDKey[] = "device_aid_key";
 // Key for this device's android security token.
 const char kDeviceTokenKey[] = "device_token_key";
+// Lowest lexicographically ordered app ids.
+// Used for prefixing app id.
+const char kRegistrationKeyStart[] = "reg1-";
+// Key guaranteed to be higher than all app ids.
+// Used for limiting iteration.
+const char kRegistrationKeyEnd[] = "reg2-";
 // Lowest lexicographically ordered incoming message key.
 // Used for prefixing messages.
 const char kIncomingMsgKeyStart[] = "incoming1-";
 // Key guaranteed to be higher than all incoming message keys.
 // Used for limiting iteration.
 const char kIncomingMsgKeyEnd[] = "incoming2-";
-// Key for next serial number assigned to the user.
-const char kNextSerialNumberKey[] = "next_serial_number_key";
 // Lowest lexicographically ordered outgoing message key.
 // Used for prefixing outgoing messages.
 const char kOutgoingMsgKeyStart[] = "outgoing1-";
 // Key guaranteed to be higher than all outgoing message keys.
 // Used for limiting iteration.
 const char kOutgoingMsgKeyEnd[] = "outgoing2-";
-// Lowest lexicographically ordered username.
-// Used for prefixing username to serial number mappings.
-const char kUserSerialNumberKeyStart[] = "user1-";
-// Key guaranteed to be higher than all usernames.
-// Used for limiting iteration.
-const char kUserSerialNumberKeyEnd[] = "user2-";
 
-// Value indicating that serial number was not assigned.
-const int64 kSerialNumberMissing = -1LL;
+std::string MakeRegistrationKey(const std::string& app_id) {
+  return kRegistrationKeyStart + app_id;
+}
+
+std::string ParseRegistrationKey(const std::string& key) {
+  return key.substr(arraysize(kRegistrationKeyStart) - 1);
+}
 
 std::string MakeIncomingKey(const std::string& persistent_id) {
   return kIncomingMsgKeyStart + persistent_id;
@@ -67,18 +70,10 @@
   return kOutgoingMsgKeyStart + persistent_id;
 }
 
-std::string MakeUserSerialNumberKey(const std::string& username) {
-  return kUserSerialNumberKeyStart + username;
-}
-
 std::string ParseOutgoingKey(const std::string& key) {
   return key.substr(arraysize(kOutgoingMsgKeyStart) - 1);
 }
 
-std::string ParseUsername(const std::string& key) {
-  return key.substr(arraysize(kUserSerialNumberKeyStart) - 1);
-}
-
 // Note: leveldb::Slice keeps a pointer to the data in |s|, which must therefore
 // outlive the slice.
 // For example: MakeSlice(MakeOutgoingKey(x)) is invalid.
@@ -101,6 +96,11 @@
   void SetDeviceCredentials(uint64 device_android_id,
                             uint64 device_security_token,
                             const UpdateCallback& callback);
+  void AddRegistration(const std::string& app_id,
+                       const linked_ptr<RegistrationInfo>& registration,
+                       const UpdateCallback& callback);
+  void RemoveRegistration(const std::string& app_id,
+                          const UpdateCallback& callback);
   void AddIncomingMessage(const std::string& persistent_id,
                           const UpdateCallback& callback);
   void RemoveIncomingMessages(const PersistentIdList& persistent_ids,
@@ -124,11 +124,9 @@
   ~Backend();
 
   bool LoadDeviceCredentials(uint64* android_id, uint64* security_token);
+  bool LoadRegistrations(RegistrationInfoMap* registrations);
   bool LoadIncomingMessages(std::vector<std::string>* incoming_messages);
   bool LoadOutgoingMessages(OutgoingMessageMap* outgoing_messages);
-  bool LoadNextSerialNumber(int64* next_serial_number);
-  bool LoadUserSerialNumberMap(
-      std::map<std::string, int64>* user_serial_number_map);
 
   const base::FilePath path_;
   scoped_refptr<base::SequencedTaskRunner> foreground_task_runner_;
@@ -171,14 +169,12 @@
 
   if (!LoadDeviceCredentials(&result->device_android_id,
                              &result->device_security_token) ||
+      !LoadRegistrations(&result->registrations) ||
       !LoadIncomingMessages(&result->incoming_messages) ||
-      !LoadOutgoingMessages(&result->outgoing_messages) ||
-      !LoadNextSerialNumber(
-           &result->serial_number_mappings.next_serial_number) ||
-      !LoadUserSerialNumberMap(
-           &result->serial_number_mappings.user_serial_numbers)) {
+      !LoadOutgoingMessages(&result->outgoing_messages)) {
     result->device_android_id = 0;
     result->device_security_token = 0;
+    result->registrations.clear();
     result->incoming_messages.clear();
     result->outgoing_messages.clear();
     foreground_task_runner_->PostTask(FROM_HERE,
@@ -194,16 +190,17 @@
       UMA_HISTOGRAM_COUNTS("GCM.StoreSizeKB",
                            static_cast<int>(file_size / 1024));
     }
+    UMA_HISTOGRAM_COUNTS("GCM.RestoredRegistrations",
+                         result->registrations.size());
     UMA_HISTOGRAM_COUNTS("GCM.RestoredOutgoingMessages",
                          result->outgoing_messages.size());
     UMA_HISTOGRAM_COUNTS("GCM.RestoredIncomingMessages",
                          result->incoming_messages.size());
-    UMA_HISTOGRAM_COUNTS(
-        "GCM.NumUsers",
-        result->serial_number_mappings.user_serial_numbers.size());
   }
 
-  DVLOG(1) << "Succeeded in loading " << result->incoming_messages.size()
+  DVLOG(1) << "Succeeded in loading " << result->registrations.size()
+           << " registrations, "
+           << result->incoming_messages.size()
            << " unacknowledged incoming messages and "
            << result->outgoing_messages.size()
            << " unacknowledged outgoing messages.";
@@ -266,6 +263,51 @@
   foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
 }
 
+void GCMStoreImpl::Backend::AddRegistration(
+    const std::string& app_id,
+    const linked_ptr<RegistrationInfo>& registration,
+    const UpdateCallback& callback) {
+  DVLOG(1) << "Saving registration info for app: " << app_id;
+  if (!db_.get()) {
+    LOG(ERROR) << "GCMStore db doesn't exist.";
+    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
+    return;
+  }
+  leveldb::WriteOptions write_options;
+  write_options.sync = true;
+
+  std::string key = MakeRegistrationKey(app_id);
+  std::string value = registration->SerializeAsString();
+  const leveldb::Status status = db_->Put(write_options,
+                                          MakeSlice(key),
+                                          MakeSlice(value));
+  if (status.ok()) {
+    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
+    return;
+  }
+  LOG(ERROR) << "LevelDB put failed: " << status.ToString();
+  foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
+}
+
+void GCMStoreImpl::Backend::RemoveRegistration(const std::string& app_id,
+                                               const UpdateCallback& callback) {
+  if (!db_.get()) {
+    LOG(ERROR) << "GCMStore db doesn't exist.";
+    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
+    return;
+  }
+  leveldb::WriteOptions write_options;
+  write_options.sync = true;
+
+  leveldb::Status status = db_->Delete(write_options, MakeSlice(app_id));
+  if (status.ok()) {
+    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
+    return;
+  }
+  LOG(ERROR) << "LevelDB remove failed: " << status.ToString();
+  foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
+}
+
 void GCMStoreImpl::Backend::AddIncomingMessage(const std::string& persistent_id,
                                                const UpdateCallback& callback) {
   DVLOG(1) << "Saving incoming message with id " << persistent_id;
@@ -403,79 +445,6 @@
                                                AppIdToMessageCountMap()));
 }
 
-void GCMStoreImpl::Backend::AddUserSerialNumber(
-    const std::string& username,
-    int64 serial_number,
-    const UpdateCallback& callback) {
-  DVLOG(1) << "Saving username to serial number mapping for user: " << username;
-  if (!db_.get()) {
-    LOG(ERROR) << "GCMStore db doesn't exist.";
-    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
-    return;
-  }
-  leveldb::WriteOptions write_options;
-  write_options.sync = true;
-
-  std::string key = MakeUserSerialNumberKey(username);
-  std::string serial_number_str = base::Int64ToString(serial_number);
-  const leveldb::Status status =
-      db_->Put(write_options,
-               MakeSlice(key),
-               MakeSlice(serial_number_str));
-  if (status.ok()) {
-    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
-    return;
-  }
-  LOG(ERROR) << "LevelDB put failed: " << status.ToString();
-  foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
-}
-
-void GCMStoreImpl::Backend::RemoveUserSerialNumber(
-    const std::string& username,
-    const UpdateCallback& callback) {
-  if (!db_.get()) {
-    LOG(ERROR) << "GCMStore db doesn't exist.";
-    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
-    return;
-  }
-  leveldb::WriteOptions write_options;
-  write_options.sync = true;
-
-  leveldb::Status status = db_->Delete(write_options, MakeSlice(username));
-  if (status.ok()) {
-    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
-    return;
-  }
-  LOG(ERROR) << "LevelDB remove failed: " << status.ToString();
-  foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
-}
-
-void GCMStoreImpl::Backend::SetNextSerialNumber(
-    int64 next_serial_number,
-    const UpdateCallback& callback) {
-  DVLOG(1) << "Updating the value of next user serial number to: "
-           << next_serial_number;
-  if (!db_.get()) {
-    LOG(ERROR) << "GCMStore db doesn't exist.";
-    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
-    return;
-  }
-  leveldb::WriteOptions write_options;
-  write_options.sync = true;
-
-  std::string serial_number_str = base::Int64ToString(next_serial_number);
-  const leveldb::Status status =
-      db_->Put(write_options,
-               MakeSlice(kNextSerialNumberKey),
-               MakeSlice(serial_number_str));
-  if (status.ok()) {
-    foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, true));
-    return;
-  }
-  LOG(ERROR) << "LevelDB put failed: " << status.ToString();
-  foreground_task_runner_->PostTask(FROM_HERE, base::Bind(callback, false));
-}
-
 bool GCMStoreImpl::Backend::LoadDeviceCredentials(uint64* android_id,
                                                   uint64* security_token) {
   leveldb::ReadOptions read_options;
@@ -510,6 +479,33 @@
   return false;
 }
 
+bool GCMStoreImpl::Backend::LoadRegistrations(
+    RegistrationInfoMap* registrations) {
+  leveldb::ReadOptions read_options;
+  read_options.verify_checksums = true;
+
+  scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
+  for (iter->Seek(MakeSlice(kRegistrationKeyStart));
+       iter->Valid() && iter->key().ToString() < kRegistrationKeyEnd;
+       iter->Next()) {
+    leveldb::Slice s = iter->value();
+    if (s.size() <= 1) {
+      LOG(ERROR) << "Error reading registration with key " << s.ToString();
+      return false;
+    }
+    std::string app_id = ParseRegistrationKey(iter->key().ToString());
+    linked_ptr<RegistrationInfo> registration(new RegistrationInfo);
+    if (!registration->ParseFromString(iter->value().ToString())) {
+      LOG(ERROR) << "Failed to parse registration with app id " << app_id;
+      return false;
+    }
+    DVLOG(1) << "Found registration with app id " << app_id;
+    (*registrations)[app_id] = registration;
+  }
+
+  return true;
+}
+
 bool GCMStoreImpl::Backend::LoadIncomingMessages(
     std::vector<std::string>* incoming_messages) {
   leveldb::ReadOptions read_options;
@@ -564,57 +560,6 @@
   return true;
 }
 
-bool GCMStoreImpl::Backend::LoadNextSerialNumber(int64* next_serial_number) {
-  leveldb::ReadOptions read_options;
-  read_options.verify_checksums = true;
-
-  std::string result;
-  leveldb::Status status =
-      db_->Get(read_options, MakeSlice(kNextSerialNumberKey), &result);
-  if (status.ok()) {
-    if (!base::StringToInt64(result, next_serial_number)) {
-      LOG(ERROR) << "Failed to restore the next serial number.";
-      return false;
-    }
-    return true;
-  }
-
-  if (status.IsNotFound()) {
-    DVLOG(1) << "No next serial number found.";
-    return true;
-  }
-
-  LOG(ERROR) << "Error when reading the next serial number.";
-  return false;
-}
-
-bool GCMStoreImpl::Backend::LoadUserSerialNumberMap(
-    std::map<std::string, int64>* user_serial_number_map) {
-  leveldb::ReadOptions read_options;
-  read_options.verify_checksums = true;
-
-  scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(read_options));
-  for (iter->Seek(MakeSlice(kUserSerialNumberKeyStart));
-       iter->Valid() && iter->key().ToString() < kUserSerialNumberKeyEnd;
-       iter->Next()) {
-    std::string username = ParseUsername(iter->key().ToString());
-    if (username.empty()) {
-      LOG(ERROR) << "Error reading username. It should not be empty.";
-      return false;
-    }
-    std::string serial_number_string = iter->value().ToString();
-    int64 serial_number = kSerialNumberMissing;
-    if (!base::StringToInt64(serial_number_string, &serial_number)) {
-      LOG(ERROR) << "Error reading user serial number for user: " << username;
-      return false;
-    }
-
-    (*user_serial_number_map)[username] = serial_number;
-  }
-
-  return true;
-}
-
 GCMStoreImpl::GCMStoreImpl(
     bool use_mock_keychain,
     const base::FilePath& path,
@@ -664,6 +609,29 @@
                  callback));
 }
 
+void GCMStoreImpl::AddRegistration(
+    const std::string& app_id,
+    const linked_ptr<RegistrationInfo>& registration,
+    const UpdateCallback& callback) {
+  blocking_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&GCMStoreImpl::Backend::AddRegistration,
+                 backend_,
+                 app_id,
+                 registration,
+                 callback));
+}
+
+void GCMStoreImpl::RemoveRegistration(const std::string& app_id,
+                                          const UpdateCallback& callback) {
+  blocking_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&GCMStoreImpl::Backend::RemoveRegistration,
+                 backend_,
+                 app_id,
+                 callback));
+}
+
 void GCMStoreImpl::AddIncomingMessage(const std::string& persistent_id,
                                       const UpdateCallback& callback) {
   blocking_task_runner_->PostTask(
@@ -766,38 +734,6 @@
                             callback)));
 }
 
-void GCMStoreImpl::SetNextSerialNumber(int64 next_serial_number,
-                                       const UpdateCallback& callback) {
-  blocking_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&GCMStoreImpl::Backend::SetNextSerialNumber,
-                 backend_,
-                 next_serial_number,
-                 callback));
-}
-
-void GCMStoreImpl::AddUserSerialNumber(const std::string& username,
-                                       int64 serial_number,
-                                       const UpdateCallback& callback) {
-  blocking_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&GCMStoreImpl::Backend::AddUserSerialNumber,
-                 backend_,
-                 username,
-                 serial_number,
-                 callback));
-}
-
-void GCMStoreImpl::RemoveUserSerialNumber(const std::string& username,
-                                          const UpdateCallback& callback) {
-  blocking_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&GCMStoreImpl::Backend::RemoveUserSerialNumber,
-                 backend_,
-                 username,
-                 callback));
-}
-
 void GCMStoreImpl::LoadContinuation(const LoadCallback& callback,
                                     scoped_ptr<LoadResult> result) {
   if (!result->success) {
diff --git a/google_apis/gcm/engine/gcm_store_impl.h b/google_apis/gcm/engine/gcm_store_impl.h
index 88ed164..971367a 100644
--- a/google_apis/gcm/engine/gcm_store_impl.h
+++ b/google_apis/gcm/engine/gcm_store_impl.h
@@ -46,6 +46,13 @@
                                     uint64 device_security_token,
                                     const UpdateCallback& callback) OVERRIDE;
 
+  // Registration info.
+  virtual void AddRegistration(const std::string& app_id,
+                               const linked_ptr<RegistrationInfo>& registration,
+                               const UpdateCallback& callback) OVERRIDE;
+  virtual void RemoveRegistration(const std::string& app_id,
+                                  const UpdateCallback& callback) OVERRIDE;
+
   // Unacknowledged incoming message handling.
   virtual void AddIncomingMessage(const std::string& persistent_id,
                                   const UpdateCallback& callback) OVERRIDE;
@@ -67,15 +74,6 @@
   virtual void RemoveOutgoingMessages(const PersistentIdList& persistent_ids,
                                       const UpdateCallback& callback) OVERRIDE;
 
-  // User serial number handling.
-  virtual void SetNextSerialNumber(int64 next_serial_number,
-                                   const UpdateCallback& callback) OVERRIDE;
-  virtual void AddUserSerialNumber(const std::string& username,
-                                   int64 serial_number,
-                                   const UpdateCallback& callback) OVERRIDE;
-  virtual void RemoveUserSerialNumber(const std::string& username,
-                                      const UpdateCallback& callback) OVERRIDE;
-
  private:
   typedef std::map<std::string, int> AppIdToMessageCountMap;
 
diff --git a/google_apis/gcm/engine/gcm_store_impl_unittest.cc b/google_apis/gcm/engine/gcm_store_impl_unittest.cc
index 0a34307..0656ad2 100644
--- a/google_apis/gcm/engine/gcm_store_impl_unittest.cc
+++ b/google_apis/gcm/engine/gcm_store_impl_unittest.cc
@@ -108,8 +108,6 @@
   EXPECT_EQ(0U, load_result->device_security_token);
   EXPECT_TRUE(load_result->incoming_messages.empty());
   EXPECT_TRUE(load_result->outgoing_messages.empty());
-  EXPECT_EQ(1LL, load_result->serial_number_mappings.next_serial_number);
-  EXPECT_TRUE(load_result->serial_number_mappings.user_serial_numbers.empty());
 }
 
 TEST_F(GCMStoreImplTest, DeviceCredentials) {
@@ -134,6 +132,58 @@
   ASSERT_EQ(kDeviceToken, load_result->device_security_token);
 }
 
+TEST_F(GCMStoreImplTest, Registrations) {
+  scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
+  scoped_ptr<GCMStore::LoadResult> load_result;
+  gcm_store->Load(base::Bind(
+      &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
+  PumpLoop();
+
+  // Add one registration with one sender.
+  linked_ptr<RegistrationInfo> registration1(new RegistrationInfo);
+  registration1->sender_ids.push_back("sender1");
+  registration1->registration_id = "registration1";
+  gcm_store->AddRegistration(
+      "app1",
+      registration1,
+      base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
+  PumpLoop();
+
+  // Add one registration with multiple senders.
+  linked_ptr<RegistrationInfo> registration2(new RegistrationInfo);
+  registration2->sender_ids.push_back("sender2_1");
+  registration2->sender_ids.push_back("sender2_2");
+  registration2->registration_id = "registration2";
+  gcm_store->AddRegistration(
+      "app2",
+      registration2,
+      base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
+  PumpLoop();
+
+  gcm_store = BuildGCMStore().Pass();
+  gcm_store->Load(base::Bind(
+      &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
+  PumpLoop();
+
+  ASSERT_EQ(2u, load_result->registrations.size());
+  ASSERT_TRUE(load_result->registrations.find("app1") !=
+              load_result->registrations.end());
+  EXPECT_EQ(registration1->registration_id,
+            load_result->registrations["app1"]->registration_id);
+  ASSERT_EQ(1u, load_result->registrations["app1"]->sender_ids.size());
+  EXPECT_EQ(registration1->sender_ids[0],
+            load_result->registrations["app1"]->sender_ids[0]);
+  ASSERT_TRUE(load_result->registrations.find("app2") !=
+              load_result->registrations.end());
+  EXPECT_EQ(registration2->registration_id,
+            load_result->registrations["app2"]->registration_id);
+  ASSERT_EQ(2u, load_result->registrations["app2"]->sender_ids.size());
+  EXPECT_EQ(registration2->sender_ids[0],
+            load_result->registrations["app2"]->sender_ids[0]);
+  EXPECT_EQ(registration2->sender_ids[1],
+            load_result->registrations["app2"]->sender_ids[1]);
+}
+
 // Verify saving some incoming messages, reopening the directory, and then
 // removing those incoming messages.
 TEST_F(GCMStoreImplTest, IncomingMessages) {
@@ -294,70 +344,6 @@
   ASSERT_TRUE(load_result->outgoing_messages.empty());
 }
 
-// Verify that the next serial number of persisted properly.
-TEST_F(GCMStoreImplTest, NextSerialNumber) {
-  const int64 kNextSerialNumber = 77LL;
-  scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
-  scoped_ptr<GCMStore::LoadResult> load_result;
-  gcm_store->Load(base::Bind(
-      &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
-  PumpLoop();
-
-  gcm_store->SetNextSerialNumber(
-      kNextSerialNumber,
-      base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
-  PumpLoop();
-
-  gcm_store = BuildGCMStore().Pass();
-  gcm_store->Load(base::Bind(
-      &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
-  PumpLoop();
-
-  EXPECT_EQ(kNextSerialNumber,
-            load_result->serial_number_mappings.next_serial_number);
-}
-
-// Verify that user serial number mappings are persisted properly.
-TEST_F(GCMStoreImplTest, UserSerialNumberMappings) {
-  scoped_ptr<GCMStore> gcm_store(BuildGCMStore());
-  scoped_ptr<GCMStore::LoadResult> load_result;
-  gcm_store->Load(base::Bind(
-      &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
-  PumpLoop();
-
-  std::string username1 = "username1";
-  int64 serial_number1 = 34LL;
-  gcm_store->AddUserSerialNumber(
-      username1,
-      serial_number1,
-      base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
-
-  std::string username2 = "username2";
-  int64 serial_number2 = 56LL;
-  gcm_store->AddUserSerialNumber(
-      username2,
-      serial_number2,
-      base::Bind(&GCMStoreImplTest::UpdateCallback, base::Unretained(this)));
-  PumpLoop();
-
-  gcm_store = BuildGCMStore().Pass();
-  gcm_store->Load(base::Bind(
-      &GCMStoreImplTest::LoadCallback, base::Unretained(this), &load_result));
-  PumpLoop();
-
-  ASSERT_EQ(2u, load_result->serial_number_mappings.user_serial_numbers.size());
-  ASSERT_NE(
-      load_result->serial_number_mappings.user_serial_numbers.end(),
-      load_result->serial_number_mappings.user_serial_numbers.find(username1));
-  EXPECT_EQ(serial_number1,
-            load_result->serial_number_mappings.user_serial_numbers[username1]);
-  ASSERT_NE(
-      load_result->serial_number_mappings.user_serial_numbers.end(),
-      load_result->serial_number_mappings.user_serial_numbers.find(username2));
-  EXPECT_EQ(serial_number2,
-            load_result->serial_number_mappings.user_serial_numbers[username2]);
-}
-
 // Test that per-app message limits are enforced, persisted across restarts,
 // and updated as messages are removed.
 TEST_F(GCMStoreImplTest, PerAppMessageLimits) {
diff --git a/google_apis/gcm/engine/mcs_client.cc b/google_apis/gcm/engine/mcs_client.cc
index c203c2a..da8300c 100644
--- a/google_apis/gcm/engine/mcs_client.cc
+++ b/google_apis/gcm/engine/mcs_client.cc
@@ -869,10 +869,6 @@
       status);
 }
 
-void MCSClient::SetGCMStoreForTesting(GCMStore* gcm_store) {
-  gcm_store_ = gcm_store;
-}
-
 MCSClient::MCSPacketInternal MCSClient::PopMessageForSend() {
   MCSPacketInternal packet = to_send_.front();
   to_send_.pop_front();
diff --git a/google_apis/gcm/engine/mcs_client.h b/google_apis/gcm/engine/mcs_client.h
index c3009b8..1943be6 100644
--- a/google_apis/gcm/engine/mcs_client.h
+++ b/google_apis/gcm/engine/mcs_client.h
@@ -130,12 +130,6 @@
   // Returns text representation of the state enum.
   std::string GetStateString() const;
 
- protected:
-  // Sets a |gcm_store| for testing. Does not take ownership.
-  // TODO(fgorski): Remove this method. Create GCMEngineFactory that will create
-  // components of the engine.
-  void SetGCMStoreForTesting(GCMStore* gcm_store);
-
  private:
   typedef uint32 StreamId;
   typedef std::string PersistentId;
diff --git a/google_apis/gcm/engine/registration_info.cc b/google_apis/gcm/engine/registration_info.cc
new file mode 100644
index 0000000..6a41c76
--- /dev/null
+++ b/google_apis/gcm/engine/registration_info.cc
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "google_apis/gcm/engine/registration_info.h"
+
+#include "base/strings/string_util.h"
+
+namespace gcm {
+
+RegistrationInfo::RegistrationInfo() {
+}
+
+RegistrationInfo::~RegistrationInfo() {
+}
+
+std::string RegistrationInfo::SerializeAsString() const {
+  if (sender_ids.empty() || registration_id.empty())
+    return std::string();
+
+  // Serialize as:
+  //    sender1,sender2,...=reg_id
+  std::string value;
+  for (std::vector<std::string>::const_iterator iter = sender_ids.begin();
+       iter != sender_ids.end(); ++iter) {
+    DCHECK(!iter->empty() &&
+           iter->find(',') == std::string::npos &&
+           iter->find('=') == std::string::npos);
+    if (!value.empty())
+      value += ",";
+    value += *iter;
+  }
+
+  DCHECK(registration_id.find('=') == std::string::npos);
+  value += '=';
+  value += registration_id;
+  return value;
+}
+
+bool RegistrationInfo::ParseFromString(const std::string& value) {
+  if (value.empty())
+    return true;
+
+  size_t pos = value.find('=');
+  if (pos == std::string::npos)
+    return false;
+
+  std::string senders = value.substr(0, pos);
+  registration_id = value.substr(pos + 1);
+
+  Tokenize(senders, ",", &sender_ids);
+
+  if (sender_ids.empty() || registration_id.empty()) {
+    sender_ids.clear();
+    registration_id.clear();
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace gcm
diff --git a/google_apis/gcm/engine/registration_info.h b/google_apis/gcm/engine/registration_info.h
new file mode 100644
index 0000000..c06a6aa
--- /dev/null
+++ b/google_apis/gcm/engine/registration_info.h
@@ -0,0 +1,35 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GOOGLE_APIS_GCM_ENGINE_REGISTRATION_INFO_H_
+#define GOOGLE_APIS_GCM_ENGINE_REGISTRATION_INFO_H_
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/linked_ptr.h"
+#include "google_apis/gcm/base/gcm_export.h"
+
+namespace gcm {
+
+struct GCM_EXPORT RegistrationInfo {
+  RegistrationInfo();
+  ~RegistrationInfo();
+
+  std::string SerializeAsString() const;
+  bool ParseFromString(const std::string& value);
+
+  std::vector<std::string> sender_ids;
+  std::string registration_id;
+};
+
+// Map of app id to registration info.
+typedef std::map<std::string, linked_ptr<RegistrationInfo> >
+RegistrationInfoMap;
+
+}  // namespace gcm
+
+#endif  // GOOGLE_APIS_GCM_ENGINE_REGISTRATION_INFO_H_
diff --git a/google_apis/gcm/gcm.gyp b/google_apis/gcm/gcm.gyp
index c5dfa6dd..9843776 100644
--- a/google_apis/gcm/gcm.gyp
+++ b/google_apis/gcm/gcm.gyp
@@ -62,6 +62,8 @@
         'engine/heartbeat_manager.h',
         'engine/mcs_client.cc',
         'engine/mcs_client.h',
+        'engine/registration_info.cc',
+        'engine/registration_info.h',
         'engine/registration_request.cc',
         'engine/registration_request.h',
         'engine/unregistration_request.cc',
diff --git a/google_apis/gcm/gcm_client_impl.cc b/google_apis/gcm/gcm_client_impl.cc
index 5663eae..4cc0fdd 100644
--- a/google_apis/gcm/gcm_client_impl.cc
+++ b/google_apis/gcm/gcm_client_impl.cc
@@ -67,7 +67,13 @@
   SEND_ERROR,        // Error sending a message.
 };
 
-const char kMCSEndpoint[] = "https://mtalk.google.com:5228";
+// MCS endpoints. SSL Key pinning is done automatically due to the *.google.com
+// pinning rule.
+// Note: modifying the endpoints will affect the ability to compare the
+// GCM.CurrentEnpoint histogram across versions.
+const char kMCSEndpointMain[] = "https://mtalk.google.com:5228";
+const char kMCSEndpointFallback[] = "https://mtalk.google.com:443";
+
 const int kMaxRegistrationRetries = 5;
 const char kMessageTypeDataMessage[] = "gcm";
 const char kMessageTypeDeletedMessagesKey[] = "deleted_messages";
@@ -111,12 +117,45 @@
 
 }  // namespace
 
-GCMClientImpl::GCMClientImpl()
-    : state_(UNINITIALIZED),
-      clock_(new base::DefaultClock()),
+GCMInternalsBuilder::GCMInternalsBuilder() {}
+GCMInternalsBuilder::~GCMInternalsBuilder() {}
+
+scoped_ptr<base::Clock> GCMInternalsBuilder::BuildClock() {
+  return make_scoped_ptr<base::Clock>(new base::DefaultClock());
+}
+
+scoped_ptr<MCSClient> GCMInternalsBuilder::BuildMCSClient(
+    const std::string& version,
+    base::Clock* clock,
+    ConnectionFactory* connection_factory,
+    GCMStore* gcm_store) {
+  return make_scoped_ptr<MCSClient>(
+      new MCSClient(version,
+                    clock,
+                    connection_factory,
+                    gcm_store));
+}
+
+scoped_ptr<ConnectionFactory> GCMInternalsBuilder::BuildConnectionFactory(
+      const std::vector<GURL>& endpoints,
+      const net::BackoffEntry::Policy& backoff_policy,
+      scoped_refptr<net::HttpNetworkSession> network_session,
+      net::NetLog* net_log) {
+  return make_scoped_ptr<ConnectionFactory>(
+      new ConnectionFactoryImpl(endpoints,
+                                backoff_policy,
+                                network_session,
+                                net_log));
+}
+
+GCMClientImpl::GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder)
+    : internals_builder_(internals_builder.Pass()),
+      state_(UNINITIALIZED),
+      clock_(internals_builder_->BuildClock()),
       url_request_context_getter_(NULL),
-      pending_registrations_deleter_(&pending_registrations_),
-      pending_unregistrations_deleter_(&pending_unregistrations_),
+      pending_registration_requests_deleter_(&pending_registration_requests_),
+      pending_unregistration_requests_deleter_(
+          &pending_unregistration_requests_),
       weak_ptr_factory_(this) {
 }
 
@@ -135,8 +174,14 @@
   DCHECK(url_request_context_getter);
   DCHECK(delegate);
 
-  chrome_build_proto_.CopyFrom(chrome_build_proto);
   url_request_context_getter_ = url_request_context_getter;
+  const net::HttpNetworkSession::Params* network_session_params =
+      url_request_context_getter_->GetURLRequestContext()->
+          GetNetworkSessionParams();
+  DCHECK(network_session_params);
+  network_session_ = new net::HttpNetworkSession(*network_session_params);
+
+  chrome_build_proto_.CopyFrom(chrome_build_proto);
   account_ids_ = account_ids;
 
   gcm_store_.reset(new GCMStoreImpl(false, path, blocking_task_runner));
@@ -163,6 +208,8 @@
     return;
   }
 
+  registrations_ = result->registrations;
+
   device_checkin_info_.android_id = result->device_android_id;
   device_checkin_info_.secret = result->device_security_token;
   InitializeMCSClient(result.Pass());
@@ -178,24 +225,19 @@
 
 void GCMClientImpl::InitializeMCSClient(
     scoped_ptr<GCMStore::LoadResult> result) {
-  // |mcs_client_| might already be set for testing at this point. No need to
-  // create a |connection_factory_|.
-  if (!mcs_client_.get()) {
-    const net::HttpNetworkSession::Params* network_session_params =
-        url_request_context_getter_->GetURLRequestContext()->
-            GetNetworkSessionParams();
-    DCHECK(network_session_params);
-    network_session_ = new net::HttpNetworkSession(*network_session_params);
-    connection_factory_.reset(new ConnectionFactoryImpl(
-        GURL(kMCSEndpoint),
-        kDefaultBackoffPolicy,
-        network_session_,
-        net_log_.net_log()));
-    mcs_client_.reset(new MCSClient(chrome_build_proto_.chrome_version(),
-                                    clock_.get(),
-                                    connection_factory_.get(),
-                                    gcm_store_.get()));
-  }
+  std::vector<GURL> endpoints;
+  endpoints.push_back(GURL(kMCSEndpointMain));
+  endpoints.push_back(GURL(kMCSEndpointFallback));
+  connection_factory_ = internals_builder_->BuildConnectionFactory(
+      endpoints,
+      kDefaultBackoffPolicy,
+      network_session_,
+      net_log_.net_log());
+  mcs_client_ = internals_builder_->BuildMCSClient(
+      chrome_build_proto_.chrome_version(),
+      clock_.get(),
+      connection_factory_.get(),
+      gcm_store_.get()).Pass();
 
   mcs_client_->Initialize(
       base::Bind(&GCMClientImpl::OnMCSError, weak_ptr_factory_.GetWeakPtr()),
@@ -284,11 +326,17 @@
   DCHECK(success);
 }
 
+void GCMClientImpl::UpdateRegistrationCallback(bool success) {
+  // TODO(fgorski): This is one of the signals that store needs a rebuild.
+  DCHECK(success);
+}
+
 void GCMClientImpl::Stop() {
   device_checkin_info_.Reset();
+  connection_factory_.reset();
   mcs_client_.reset();
   checkin_request_.reset();
-  pending_registrations_.clear();
+  pending_registration_requests_.clear();
   state_ = INITIALIZED;
   gcm_store_->Close();
 }
@@ -302,33 +350,49 @@
 void GCMClientImpl::Register(const std::string& app_id,
                              const std::vector<std::string>& sender_ids) {
   DCHECK_EQ(state_, READY);
+
+  // If the same sender ids is provided, return the cached registration ID
+  // directly.
+  RegistrationInfoMap::const_iterator registrations_iter =
+      registrations_.find(app_id);
+  if (registrations_iter != registrations_.end() &&
+      registrations_iter->second->sender_ids == sender_ids) {
+    delegate_->OnRegisterFinished(
+        app_id, registrations_iter->second->registration_id, SUCCESS);
+    return;
+  }
+
   RegistrationRequest::RequestInfo request_info(
       device_checkin_info_.android_id,
       device_checkin_info_.secret,
       app_id,
       sender_ids);
-  DCHECK_EQ(0u, pending_registrations_.count(app_id));
+  DCHECK_EQ(0u, pending_registration_requests_.count(app_id));
 
   RegistrationRequest* registration_request =
       new RegistrationRequest(request_info,
                               kDefaultBackoffPolicy,
                               base::Bind(&GCMClientImpl::OnRegisterCompleted,
                                          weak_ptr_factory_.GetWeakPtr(),
-                                         app_id),
+                                         app_id,
+                                         sender_ids),
                               kMaxRegistrationRetries,
                               url_request_context_getter_);
-  pending_registrations_[app_id] = registration_request;
+  pending_registration_requests_[app_id] = registration_request;
   registration_request->Start();
 }
 
-void GCMClientImpl::OnRegisterCompleted(const std::string& app_id,
-                                        RegistrationRequest::Status status,
-                                        const std::string& registration_id) {
+void GCMClientImpl::OnRegisterCompleted(
+    const std::string& app_id,
+    const std::vector<std::string>& sender_ids,
+    RegistrationRequest::Status status,
+    const std::string& registration_id) {
   DCHECK(delegate_);
 
   Result result;
-  PendingRegistrations::iterator iter = pending_registrations_.find(app_id);
-  if (iter == pending_registrations_.end())
+  PendingRegistrationRequests::iterator iter =
+      pending_registration_requests_.find(app_id);
+  if (iter == pending_registration_requests_.end())
     result = UNKNOWN_ERROR;
   else if (status == RegistrationRequest::INVALID_SENDER)
     result = INVALID_PARAMETER;
@@ -337,20 +401,42 @@
   else
     result = SUCCESS;
 
+  if (result == SUCCESS) {
+    // Cache it.
+    linked_ptr<RegistrationInfo> registration(new RegistrationInfo);
+    registration->sender_ids = sender_ids;
+    registration->registration_id = registration_id;
+    registrations_[app_id] = registration;
+
+    // Save it in the persistent store.
+    gcm_store_->AddRegistration(
+        app_id,
+        registration,
+        base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
+                   weak_ptr_factory_.GetWeakPtr()));
+  }
+
   delegate_->OnRegisterFinished(
       app_id, result == SUCCESS ? registration_id : std::string(), result);
 
-  if (iter != pending_registrations_.end()) {
+  if (iter != pending_registration_requests_.end()) {
     delete iter->second;
-    pending_registrations_.erase(iter);
+    pending_registration_requests_.erase(iter);
   }
 }
 
 void GCMClientImpl::Unregister(const std::string& app_id) {
   DCHECK_EQ(state_, READY);
-  if (pending_unregistrations_.count(app_id) == 1)
+  if (pending_unregistration_requests_.count(app_id) == 1)
     return;
 
+  // Remove from the cache and persistent store.
+  registrations_.erase(app_id);
+  gcm_store_->RemoveRegistration(
+      app_id,
+      base::Bind(&GCMClientImpl::UpdateRegistrationCallback,
+                 weak_ptr_factory_.GetWeakPtr()));
+
   UnregistrationRequest::RequestInfo request_info(
       device_checkin_info_.android_id,
       device_checkin_info_.secret,
@@ -364,7 +450,7 @@
                      weak_ptr_factory_.GetWeakPtr(),
                      app_id),
           url_request_context_getter_);
-  pending_unregistrations_[app_id] = unregistration_request;
+  pending_unregistration_requests_[app_id] = unregistration_request;
   unregistration_request->Start();
 }
 
@@ -377,12 +463,13 @@
       app_id,
       status == UnregistrationRequest::SUCCESS ? SUCCESS : SERVER_ERROR);
 
-  PendingUnregistrations::iterator iter = pending_unregistrations_.find(app_id);
-  if (iter == pending_unregistrations_.end())
+  PendingUnregistrationRequests::iterator iter =
+      pending_unregistration_requests_.find(app_id);
+  if (iter == pending_unregistration_requests_.end())
     return;
 
   delete iter->second;
-  pending_unregistrations_.erase(iter);
+  pending_unregistration_requests_.erase(iter);
 }
 
 void GCMClientImpl::OnGCMStoreDestroyed(bool success) {
@@ -539,13 +626,24 @@
 void GCMClientImpl::HandleIncomingDataMessage(
     const mcs_proto::DataMessageStanza& data_message_stanza,
     MessageData& message_data) {
+  std::string app_id = data_message_stanza.category();
+
+  // Drop the message when the app is not registered for the sender of the
+  // message.
+  RegistrationInfoMap::iterator iter = registrations_.find(app_id);
+  if (iter == registrations_.end() ||
+      std::find(iter->second->sender_ids.begin(),
+                iter->second->sender_ids.end(),
+                data_message_stanza.from()) == iter->second->sender_ids.end()) {
+    return;
+  }
+
   IncomingMessage incoming_message;
   incoming_message.sender_id = data_message_stanza.from();
   if (data_message_stanza.has_token())
     incoming_message.collapse_key = data_message_stanza.token();
   incoming_message.data = message_data;
-  delegate_->OnMessageReceived(data_message_stanza.category(),
-                               incoming_message);
+  delegate_->OnMessageReceived(app_id, incoming_message);
 }
 
 void GCMClientImpl::HandleIncomingSendError(
@@ -566,8 +664,4 @@
                                 send_error_details);
 }
 
-void GCMClientImpl::SetMCSClientForTesting(scoped_ptr<MCSClient> mcs_client) {
-  mcs_client_ = mcs_client.Pass();
-}
-
 }  // namespace gcm
diff --git a/google_apis/gcm/gcm_client_impl.h b/google_apis/gcm/gcm_client_impl.h
index f91a820..4aa38ba 100644
--- a/google_apis/gcm/gcm_client_impl.h
+++ b/google_apis/gcm/gcm_client_impl.h
@@ -23,6 +23,8 @@
 #include "net/base/net_log.h"
 #include "net/url_request/url_request_context_getter.h"
 
+class GURL;
+
 namespace base {
 class Clock;
 }  // namespace base
@@ -37,13 +39,33 @@
 class ConnectionFactory;
 class GCMClientImplTest;
 
+// Helper class for building GCM internals. Allows tests to inject fake versions
+// as necessary.
+class GCM_EXPORT GCMInternalsBuilder {
+ public:
+  GCMInternalsBuilder();
+  virtual ~GCMInternalsBuilder();
+
+  virtual scoped_ptr<base::Clock> BuildClock();
+  virtual scoped_ptr<MCSClient> BuildMCSClient(
+      const std::string& version,
+      base::Clock* clock,
+      ConnectionFactory* connection_factory,
+      GCMStore* gcm_store);
+  virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory(
+      const std::vector<GURL>& endpoints,
+      const net::BackoffEntry::Policy& backoff_policy,
+      scoped_refptr<net::HttpNetworkSession> network_session,
+      net::NetLog* net_log);
+};
+
 // Implements the GCM Client. It is used to coordinate MCS Client (communication
 // with MCS) and other pieces of GCM infrastructure like Registration and
 // Checkins. It also allows for registering user delegates that host
 // applications that send and receive messages.
 class GCM_EXPORT GCMClientImpl : public GCMClient {
  public:
-  GCMClientImpl();
+  explicit GCMClientImpl(scoped_ptr<GCMInternalsBuilder> internals_builder);
   virtual ~GCMClientImpl();
 
   // Overridden from GCMClient:
@@ -100,13 +122,13 @@
   // are pending registration requests to obtain a registration ID for
   // requesting application.
   typedef std::map<std::string, RegistrationRequest*>
-      PendingRegistrations;
+      PendingRegistrationRequests;
 
   // Collection of pending unregistration requests. Keys are app IDs, while
   // values are pending unregistration requests to disable the registration ID
   // currently assigned to the application.
   typedef std::map<std::string, UnregistrationRequest*>
-      PendingUnregistrations;
+      PendingUnregistrationRequests;
 
   friend class GCMClientImplTest;
 
@@ -150,8 +172,12 @@
   // Callback for persisting device credentials in the |gcm_store_|.
   void SetDeviceCredentialsCallback(bool success);
 
+  // Callback for persisting registration info in the |gcm_store_|.
+  void UpdateRegistrationCallback(bool success);
+
   // Completes the registration request.
   void OnRegisterCompleted(const std::string& app_id,
+                           const std::vector<std::string>& sender_ids,
                            RegistrationRequest::Status status,
                            const std::string& registration_id);
 
@@ -177,11 +203,8 @@
       const mcs_proto::DataMessageStanza& data_message_stanza,
       MessageData& message_data);
 
-  // For testing purpose only.
-  // Sets an |mcs_client_| for testing. Takes the ownership of |mcs_client|.
-  // TODO(fgorski): Remove this method. Create GCMEngineFactory that will create
-  // components of the engine.
-  void SetMCSClientForTesting(scoped_ptr<MCSClient> mcs_client);
+  // Builder for the GCM internals (mcs client, etc.).
+  scoped_ptr<GCMInternalsBuilder> internals_builder_;
 
   // State of the GCM Client Implementation.
   State state_;
@@ -214,15 +237,20 @@
   scoped_ptr<CheckinRequest> checkin_request_;
   std::vector<std::string> account_ids_;
 
-  // Currently pending registrations. GCMClientImpl owns the
-  // RegistrationRequests.
-  PendingRegistrations pending_registrations_;
-  STLValueDeleter<PendingRegistrations> pending_registrations_deleter_;
+  // Cached registration info.
+  RegistrationInfoMap registrations_;
 
-  // Currently pending unregistrations. GCMClientImpl owns the
+  // Currently pending registration requests. GCMClientImpl owns the
+  // RegistrationRequests.
+  PendingRegistrationRequests pending_registration_requests_;
+  STLValueDeleter<PendingRegistrationRequests>
+      pending_registration_requests_deleter_;
+
+  // Currently pending unregistration requests. GCMClientImpl owns the
   // UnregistrationRequests.
-  PendingUnregistrations pending_unregistrations_;
-  STLValueDeleter<PendingUnregistrations> pending_unregistrations_deleter_;
+  PendingUnregistrationRequests pending_unregistration_requests_;
+  STLValueDeleter<PendingUnregistrationRequests>
+      pending_unregistration_requests_deleter_;
 
   // Factory for creating references in callbacks.
   base::WeakPtrFactory<GCMClientImpl> weak_ptr_factory_;
diff --git a/google_apis/gcm/gcm_client_impl_unittest.cc b/google_apis/gcm/gcm_client_impl_unittest.cc
index f8129b4..229feab 100644
--- a/google_apis/gcm/gcm_client_impl_unittest.cc
+++ b/google_apis/gcm/gcm_client_impl_unittest.cc
@@ -37,6 +37,10 @@
 
 const uint64 kDeviceAndroidId = 54321;
 const uint64 kDeviceSecurityToken = 12345;
+const char kAppId[] = "app_id";
+const char kSender[] = "project_id";
+const char kSender2[] = "project_id2";
+const char kSender3[] = "project_id3";
 const char kRegistrationResponsePrefix[] = "token=";
 const char kUnregistrationResponsePrefix[] = "deleted=";
 
@@ -61,11 +65,11 @@
 class FakeMCSClient : public MCSClient {
  public:
   FakeMCSClient(base::Clock* clock,
-                ConnectionFactory* connection_factory);
+                ConnectionFactory* connection_factory,
+                GCMStore* gcm_store);
   virtual ~FakeMCSClient();
   virtual void Login(uint64 android_id, uint64 security_token) OVERRIDE;
   virtual void SendMessage(const MCSMessage& message) OVERRIDE;
-  void set_gcm_store(GCMStore* gcm_store);
 
   uint64 last_android_id() const { return last_android_id_; }
   uint64 last_security_token() const { return last_security_token_; }
@@ -82,8 +86,9 @@
 };
 
 FakeMCSClient::FakeMCSClient(base::Clock* clock,
-                             ConnectionFactory* connection_factory)
-    : MCSClient("", clock, connection_factory, NULL),
+                             ConnectionFactory* connection_factory,
+                             GCMStore* gcm_store)
+    : MCSClient("", clock, connection_factory, gcm_store),
       last_android_id_(0u),
       last_security_token_(0u),
       last_message_tag_(kNumProtoTypes) {
@@ -92,10 +97,6 @@
 FakeMCSClient::~FakeMCSClient() {
 }
 
-void FakeMCSClient::set_gcm_store(GCMStore* gcm_store) {
-  SetGCMStoreForTesting(gcm_store);
-}
-
 void FakeMCSClient::Login(uint64 android_id, uint64 security_token) {
   last_android_id_ = android_id;
   last_security_token_ = security_token;
@@ -110,6 +111,50 @@
   }
 }
 
+class FakeGCMInternalsBuilder : public GCMInternalsBuilder {
+ public:
+  FakeGCMInternalsBuilder();
+  virtual ~FakeGCMInternalsBuilder();
+
+  virtual scoped_ptr<base::Clock> BuildClock() OVERRIDE;
+  virtual scoped_ptr<MCSClient> BuildMCSClient(
+      const std::string& version,
+      base::Clock* clock,
+      ConnectionFactory* connection_factory,
+      GCMStore* gcm_store) OVERRIDE;
+  virtual scoped_ptr<ConnectionFactory> BuildConnectionFactory(
+      const std::vector<GURL>& endpoints,
+      const net::BackoffEntry::Policy& backoff_policy,
+      scoped_refptr<net::HttpNetworkSession> network_session,
+      net::NetLog* net_log) OVERRIDE;
+};
+
+FakeGCMInternalsBuilder::FakeGCMInternalsBuilder() {}
+
+FakeGCMInternalsBuilder::~FakeGCMInternalsBuilder() {}
+
+scoped_ptr<base::Clock> FakeGCMInternalsBuilder::BuildClock() {
+  return make_scoped_ptr<base::Clock>(new base::SimpleTestClock());
+}
+
+scoped_ptr<MCSClient> FakeGCMInternalsBuilder::BuildMCSClient(
+    const std::string& version,
+    base::Clock* clock,
+    ConnectionFactory* connection_factory,
+    GCMStore* gcm_store) {
+  return make_scoped_ptr<MCSClient>(new FakeMCSClient(clock,
+                                                      connection_factory,
+                                                      gcm_store));
+}
+
+scoped_ptr<ConnectionFactory> FakeGCMInternalsBuilder::BuildConnectionFactory(
+    const std::vector<GURL>& endpoints,
+    const net::BackoffEntry::Policy& backoff_policy,
+    scoped_refptr<net::HttpNetworkSession> network_session,
+    net::NetLog* net_log) {
+  return make_scoped_ptr<ConnectionFactory>(new FakeConnectionFactory());
+}
+
 }  // namespace
 
 class GCMClientImplTest : public testing::Test,
@@ -127,6 +172,11 @@
   void CompleteRegistration(const std::string& registration_id);
   void CompleteUnregistration(const std::string& app_id);
 
+  bool ExistsRegistration(const std::string& app_id) const;
+  void AddRegistration(const std::string& app_id,
+                       const std::vector<std::string>& sender_ids,
+                       const std::string& registration_id);
+
   // GCMClient::Delegate overrides (for verification).
   virtual void OnRegisterFinished(const std::string& app_id,
                                   const std::string& registration_id,
@@ -149,6 +199,17 @@
   FakeMCSClient* mcs_client() const {
     return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get());
   }
+  ConnectionFactory* connection_factory() const {
+    return gcm_client_->connection_factory_.get();
+  }
+
+  void reset_last_event() {
+    last_event_ = NONE;
+    last_app_id_.clear();
+    last_registration_id_.clear();
+    last_message_id_.clear();
+    last_result_ = GCMClient::UNKNOWN_ERROR;
+  }
 
   LastEvent last_event() const { return last_event_; }
   const std::string& last_app_id() const { return last_app_id_; }
@@ -186,7 +247,6 @@
   GCMClient::SendErrorDetails last_error_details_;
 
   scoped_ptr<GCMClientImpl> gcm_client_;
-  scoped_ptr<FakeConnectionFactory> connection_factory_;
 
   base::MessageLoop message_loop_;
   scoped_ptr<base::RunLoop> run_loop_;
@@ -211,6 +271,7 @@
   run_loop_.reset(new base::RunLoop);
   BuildGCMClient();
   InitializeGCMClient();
+  CompleteCheckin(kDeviceAndroidId, kDeviceSecurityToken);
 }
 
 void GCMClientImplTest::PumpLoop() {
@@ -229,7 +290,8 @@
 }
 
 void GCMClientImplTest::BuildGCMClient() {
-  gcm_client_.reset(new GCMClientImpl());
+  gcm_client_.reset(new GCMClientImpl(
+      make_scoped_ptr<GCMInternalsBuilder>(new FakeGCMInternalsBuilder())));
 }
 
 void GCMClientImplTest::CompleteCheckin(uint64 android_id,
@@ -259,6 +321,7 @@
   fetcher->set_response_code(net::HTTP_OK);
   fetcher->SetResponseString(response);
   fetcher->delegate()->OnURLFetchComplete(fetcher);
+  url_fetcher_factory_.RemoveFetcherFromMap(0);
 }
 
 void GCMClientImplTest::CompleteUnregistration(
@@ -270,16 +333,26 @@
   fetcher->set_response_code(net::HTTP_OK);
   fetcher->SetResponseString(response);
   fetcher->delegate()->OnURLFetchComplete(fetcher);
+  url_fetcher_factory_.RemoveFetcherFromMap(0);
+}
+
+bool GCMClientImplTest::ExistsRegistration(const std::string& app_id) const {
+  return gcm_client_->registrations_.count(app_id) > 0;
+}
+
+void GCMClientImplTest::AddRegistration(
+    const std::string& app_id,
+    const std::vector<std::string>& sender_ids,
+    const std::string& registration_id) {
+  linked_ptr<RegistrationInfo> registration(new RegistrationInfo);
+  registration->sender_ids = sender_ids;
+  registration->registration_id = registration_id;
+  gcm_client_->registrations_[app_id] = registration;
 }
 
 void GCMClientImplTest::InitializeGCMClient() {
-  // Creating and advancing the clock.
-  gcm_client_->clock_.reset(new base::SimpleTestClock);
   clock()->Advance(base::TimeDelta::FromMilliseconds(1));
-  // Creating and injecting the mcs_client.
-  connection_factory_.reset(new FakeConnectionFactory());
-  gcm_client_->SetMCSClientForTesting(scoped_ptr<MCSClient>(
-      new FakeMCSClient(clock(), connection_factory_.get())).Pass());
+
   // Actual initialization.
   checkin_proto::ChromeBuildProto chrome_build_proto;
   gcm_client_->Initialize(chrome_build_proto,
@@ -294,13 +367,10 @@
   OSCrypt::UseMockKeychain(true);  // Must be after Initialize.
 #endif
 
-  // Starting loading and check-in.
+  // Start loading and check-in.
   gcm_client_->Load();
 
-  // Ensuring that mcs_client is using the same gcm_store as gcm_client.
-  mcs_client()->set_gcm_store(gcm_client_->gcm_store_.get());
   PumpLoopUntilIdle();
-  CompleteCheckin(kDeviceAndroidId, kDeviceSecurityToken);
 }
 
 void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) {
@@ -362,47 +432,112 @@
 
 TEST_F(GCMClientImplTest, CheckOut) {
   EXPECT_TRUE(mcs_client());
+  EXPECT_TRUE(connection_factory());
   gcm_client()->CheckOut();
   EXPECT_FALSE(mcs_client());
+  EXPECT_FALSE(connection_factory());
 }
 
 TEST_F(GCMClientImplTest, RegisterApp) {
+  EXPECT_FALSE(ExistsRegistration(kAppId));
+
   std::vector<std::string> senders;
   senders.push_back("sender");
-  gcm_client()->Register("app_id", senders);
+  gcm_client()->Register(kAppId, senders);
   CompleteRegistration("reg_id");
 
   EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
-  EXPECT_EQ("app_id", last_app_id());
+  EXPECT_EQ(kAppId, last_app_id());
   EXPECT_EQ("reg_id", last_registration_id());
   EXPECT_EQ(GCMClient::SUCCESS, last_result());
+  EXPECT_TRUE(ExistsRegistration(kAppId));
+}
+
+TEST_F(GCMClientImplTest, DISABLED_RegisterAppFromCache) {
+  EXPECT_FALSE(ExistsRegistration(kAppId));
+
+  std::vector<std::string> senders;
+  senders.push_back("sender");
+  gcm_client()->Register(kAppId, senders);
+  CompleteRegistration("reg_id");
+  EXPECT_TRUE(ExistsRegistration(kAppId));
+
+  EXPECT_EQ(kAppId, last_app_id());
+  EXPECT_EQ("reg_id", last_registration_id());
+  EXPECT_EQ(GCMClient::SUCCESS, last_result());
+  EXPECT_EQ(REGISTRATION_COMPLETED, last_event());
+
+  // Recreate GCMClient in order to load from the persistent store.
+  BuildGCMClient();
+  InitializeGCMClient();
+
+  EXPECT_TRUE(ExistsRegistration(kAppId));
 }
 
 TEST_F(GCMClientImplTest, UnregisterApp) {
-  gcm_client()->Unregister("app_id");
-  CompleteUnregistration("app_id");
+  EXPECT_FALSE(ExistsRegistration(kAppId));
+
+  std::vector<std::string> senders;
+  senders.push_back("sender");
+  gcm_client()->Register(kAppId, senders);
+  CompleteRegistration("reg_id");
+  EXPECT_TRUE(ExistsRegistration(kAppId));
+
+  gcm_client()->Unregister(kAppId);
+  CompleteUnregistration(kAppId);
 
   EXPECT_EQ(UNREGISTRATION_COMPLETED, last_event());
-  EXPECT_EQ("app_id", last_app_id());
+  EXPECT_EQ(kAppId, last_app_id());
   EXPECT_EQ(GCMClient::SUCCESS, last_result());
+  EXPECT_FALSE(ExistsRegistration(kAppId));
 }
 
 TEST_F(GCMClientImplTest, DispatchDownstreamMessage) {
+  // Register to receive messages from kSender and kSender2 only.
+  std::vector<std::string> senders;
+  senders.push_back(kSender);
+  senders.push_back(kSender2);
+  AddRegistration(kAppId, senders, "reg_id");
+
   std::map<std::string, std::string> expected_data;
   expected_data["message_type"] = "gcm";
   expected_data["key"] = "value";
   expected_data["key2"] = "value2";
-  MCSMessage message(BuildDownstreamMessage(
-      "project_id", "app_id", expected_data));
+
+  // Message for kSender will be received.
+  MCSMessage message(BuildDownstreamMessage(kSender, kAppId, expected_data));
   EXPECT_TRUE(message.IsValid());
   ReceiveMessageFromMCS(message);
 
   expected_data.erase(expected_data.find("message_type"));
   EXPECT_EQ(MESSAGE_RECEIVED, last_event());
-  EXPECT_EQ("app_id", last_app_id());
+  EXPECT_EQ(kAppId, last_app_id());
   EXPECT_EQ(expected_data.size(), last_message().data.size());
   EXPECT_EQ(expected_data, last_message().data);
-  EXPECT_EQ("project_id", last_message().sender_id);
+  EXPECT_EQ(kSender, last_message().sender_id);
+
+  reset_last_event();
+
+  // Message for kSender2 will be received.
+  MCSMessage message2(BuildDownstreamMessage(kSender2, kAppId, expected_data));
+  EXPECT_TRUE(message2.IsValid());
+  ReceiveMessageFromMCS(message2);
+
+  EXPECT_EQ(MESSAGE_RECEIVED, last_event());
+  EXPECT_EQ(kAppId, last_app_id());
+  EXPECT_EQ(expected_data.size(), last_message().data.size());
+  EXPECT_EQ(expected_data, last_message().data);
+  EXPECT_EQ(kSender2, last_message().sender_id);
+
+  reset_last_event();
+
+  // Message from kSender3 will be dropped.
+  MCSMessage message3(BuildDownstreamMessage(kSender3, kAppId, expected_data));
+  EXPECT_TRUE(message3.IsValid());
+  ReceiveMessageFromMCS(message3);
+
+  EXPECT_NE(MESSAGE_RECEIVED, last_event());
+  EXPECT_NE(kAppId, last_app_id());
 }
 
 TEST_F(GCMClientImplTest, DispatchDownstreamMessageSendError) {
@@ -411,12 +546,12 @@
   expected_data["google.message_id"] = "007";
   expected_data["error_details"] = "some details";
   MCSMessage message(BuildDownstreamMessage(
-      "project_id", "app_id", expected_data));
+      kSender, kAppId, expected_data));
   EXPECT_TRUE(message.IsValid());
   ReceiveMessageFromMCS(message);
 
   EXPECT_EQ(MESSAGE_SEND_ERROR, last_event());
-  EXPECT_EQ("app_id", last_app_id());
+  EXPECT_EQ(kAppId, last_app_id());
   EXPECT_EQ("007", last_error_details().message_id);
   EXPECT_EQ(1UL, last_error_details().additional_data.size());
   GCMClient::MessageData::const_iterator iter =
@@ -429,12 +564,12 @@
   std::map<std::string, std::string> expected_data;
   expected_data["message_type"] = "deleted_messages";
   MCSMessage message(BuildDownstreamMessage(
-      "project_id", "app_id", expected_data));
+      kSender, kAppId, expected_data));
   EXPECT_TRUE(message.IsValid());
   ReceiveMessageFromMCS(message);
 
   EXPECT_EQ(MESSAGES_DELETED, last_event());
-  EXPECT_EQ("app_id", last_app_id());
+  EXPECT_EQ(kAppId, last_app_id());
 }
 
 TEST_F(GCMClientImplTest, SendMessage) {
@@ -445,16 +580,16 @@
   message.id = "007";
   message.time_to_live = 500;
   message.data["key"] = "value";
-  gcm_client()->Send("app_id", "project_id", message);
+  gcm_client()->Send(kAppId, kSender, message);
 
   EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag());
-  EXPECT_EQ("app_id", mcs_client()->last_data_message_stanza().category());
-  EXPECT_EQ("project_id", mcs_client()->last_data_message_stanza().to());
+  EXPECT_EQ(kAppId, mcs_client()->last_data_message_stanza().category());
+  EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
   EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl());
   EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent());
   EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id());
   EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from());
-  EXPECT_EQ("project_id", mcs_client()->last_data_message_stanza().to());
+  EXPECT_EQ(kSender, mcs_client()->last_data_message_stanza().to());
   EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key());
   EXPECT_EQ("value",
             mcs_client()->last_data_message_stanza().app_data(0).value());
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc
index 48815df..157a73f 100644
--- a/google_apis/gcm/tools/mcs_probe.cc
+++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -290,9 +290,12 @@
   file_thread_.Start();
   InitializeNetworkState();
   BuildNetworkSession();
+  std::vector<GURL> endpoints(1,
+                              GURL("https://" +
+                                   net::HostPortPair(server_host_,
+                                                     server_port_).ToString()));
   connection_factory_.reset(
-      new ConnectionFactoryImpl(GURL("https://" + net::HostPortPair(
-                                    server_host_, server_port_).ToString()),
+      new ConnectionFactoryImpl(endpoints,
                                 kDefaultBackoffPolicy,
                                 network_session_,
                                 &net_log_));
diff --git a/google_apis/google_apis.target.darwin-arm.mk b/google_apis/google_apis.target.darwin-arm.mk
index 6a848bd..8d98e0f 100644
--- a/google_apis/google_apis.target.darwin-arm.mk
+++ b/google_apis/google_apis.target.darwin-arm.mk
@@ -112,6 +112,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -206,6 +207,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/google_apis/google_apis.target.darwin-mips.mk b/google_apis/google_apis.target.darwin-mips.mk
index 0dcc81a..b00e0bb 100644
--- a/google_apis/google_apis.target.darwin-mips.mk
+++ b/google_apis/google_apis.target.darwin-mips.mk
@@ -111,6 +111,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -204,6 +205,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/google_apis/google_apis.target.darwin-x86.mk b/google_apis/google_apis.target.darwin-x86.mk
index 1f969c1..ec48a8c 100644
--- a/google_apis/google_apis.target.darwin-x86.mk
+++ b/google_apis/google_apis.target.darwin-x86.mk
@@ -112,6 +112,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -205,6 +206,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/google_apis/google_apis.target.darwin-x86_64.mk b/google_apis/google_apis.target.darwin-x86_64.mk
new file mode 100644
index 0000000..2001ba9
--- /dev/null
+++ b/google_apis/google_apis.target.darwin-x86_64.mk
@@ -0,0 +1,312 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := google_apis_google_apis_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	google_apis/cup/client_update_protocol.cc \
+	google_apis/cup/client_update_protocol_openssl.cc \
+	google_apis/drive/auth_service.cc \
+	google_apis/drive/base_requests.cc \
+	google_apis/drive/drive_api_parser.cc \
+	google_apis/drive/drive_api_requests.cc \
+	google_apis/drive/drive_api_url_generator.cc \
+	google_apis/drive/gdata_errorcode.cc \
+	google_apis/drive/gdata_wapi_requests.cc \
+	google_apis/drive/gdata_wapi_parser.cc \
+	google_apis/drive/gdata_wapi_url_generator.cc \
+	google_apis/drive/request_sender.cc \
+	google_apis/drive/request_util.cc \
+	google_apis/drive/task_util.cc \
+	google_apis/drive/time_util.cc \
+	google_apis/gaia/gaia_auth_consumer.cc \
+	google_apis/gaia/gaia_auth_fetcher.cc \
+	google_apis/gaia/gaia_auth_util.cc \
+	google_apis/gaia/gaia_constants.cc \
+	google_apis/gaia/gaia_oauth_client.cc \
+	google_apis/gaia/gaia_switches.cc \
+	google_apis/gaia/gaia_urls.cc \
+	google_apis/gaia/google_service_auth_error.cc \
+	google_apis/gaia/merge_session_helper.cc \
+	google_apis/gaia/oauth_request_signer.cc \
+	google_apis/gaia/oauth2_access_token_fetcher.cc \
+	google_apis/gaia/oauth2_access_token_fetcher_impl.cc \
+	google_apis/gaia/oauth2_api_call_flow.cc \
+	google_apis/gaia/oauth2_mint_token_flow.cc \
+	google_apis/gaia/oauth2_token_service.cc \
+	google_apis/gaia/ubertoken_fetcher.cc \
+	google_apis/google_api_keys.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: google_apis_google_apis_gyp
+
+# Alias gyp target name.
+.PHONY: google_apis
+google_apis: google_apis_google_apis_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/google_apis/google_apis.target.linux-arm.mk b/google_apis/google_apis.target.linux-arm.mk
index 6a848bd..8d98e0f 100644
--- a/google_apis/google_apis.target.linux-arm.mk
+++ b/google_apis/google_apis.target.linux-arm.mk
@@ -112,6 +112,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -206,6 +207,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/google_apis/google_apis.target.linux-mips.mk b/google_apis/google_apis.target.linux-mips.mk
index 0dcc81a..b00e0bb 100644
--- a/google_apis/google_apis.target.linux-mips.mk
+++ b/google_apis/google_apis.target.linux-mips.mk
@@ -111,6 +111,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -204,6 +205,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/google_apis/google_apis.target.linux-x86.mk b/google_apis/google_apis.target.linux-x86.mk
index 1f969c1..ec48a8c 100644
--- a/google_apis/google_apis.target.linux-x86.mk
+++ b/google_apis/google_apis.target.linux-x86.mk
@@ -112,6 +112,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -205,6 +206,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/google_apis/google_apis.target.linux-x86_64.mk b/google_apis/google_apis.target.linux-x86_64.mk
new file mode 100644
index 0000000..2001ba9
--- /dev/null
+++ b/google_apis/google_apis.target.linux-x86_64.mk
@@ -0,0 +1,312 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := google_apis_google_apis_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	google_apis/cup/client_update_protocol.cc \
+	google_apis/cup/client_update_protocol_openssl.cc \
+	google_apis/drive/auth_service.cc \
+	google_apis/drive/base_requests.cc \
+	google_apis/drive/drive_api_parser.cc \
+	google_apis/drive/drive_api_requests.cc \
+	google_apis/drive/drive_api_url_generator.cc \
+	google_apis/drive/gdata_errorcode.cc \
+	google_apis/drive/gdata_wapi_requests.cc \
+	google_apis/drive/gdata_wapi_parser.cc \
+	google_apis/drive/gdata_wapi_url_generator.cc \
+	google_apis/drive/request_sender.cc \
+	google_apis/drive/request_util.cc \
+	google_apis/drive/task_util.cc \
+	google_apis/drive/time_util.cc \
+	google_apis/gaia/gaia_auth_consumer.cc \
+	google_apis/gaia/gaia_auth_fetcher.cc \
+	google_apis/gaia/gaia_auth_util.cc \
+	google_apis/gaia/gaia_constants.cc \
+	google_apis/gaia/gaia_oauth_client.cc \
+	google_apis/gaia/gaia_switches.cc \
+	google_apis/gaia/gaia_urls.cc \
+	google_apis/gaia/google_service_auth_error.cc \
+	google_apis/gaia/merge_session_helper.cc \
+	google_apis/gaia/oauth_request_signer.cc \
+	google_apis/gaia/oauth2_access_token_fetcher.cc \
+	google_apis/gaia/oauth2_access_token_fetcher_impl.cc \
+	google_apis/gaia/oauth2_api_call_flow.cc \
+	google_apis/gaia/oauth2_mint_token_flow.cc \
+	google_apis/gaia/oauth2_token_service.cc \
+	google_apis/gaia/ubertoken_fetcher.cc \
+	google_apis/google_api_keys.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: google_apis_google_apis_gyp
+
+# Alias gyp target name.
+.PHONY: google_apis
+google_apis: google_apis_google_apis_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index 5059b77..f1fab9b 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -2170,9 +2170,8 @@
     'pepper_interface': 'ChromiumMapSub',
   },
   'UseProgram': {
+    'type': 'Bind',
     'decoder_func': 'DoUseProgram',
-    'impl_func': False,
-    'unit_test': False,
   },
   'ValidateProgram': {'decoder_func': 'DoValidateProgram'},
   'VertexAttrib1f': {'decoder_func': 'DoVertexAttrib1f'},
@@ -3701,7 +3700,9 @@
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 }
-
+"""
+      if func.GetInfo("gen_func"):
+          valid_test += """
 TEST_F(%(test_name)s, %(name)sValidArgsNewId) {
   EXPECT_CALL(*gl_, %(gl_func_name)s(kNewServiceId));
   EXPECT_CALL(*gl_, %(gl_gen_func_name)s(1, _))
@@ -3714,8 +3715,6 @@
   EXPECT_TRUE(Get%(resource_type)s(kNewClientId) != NULL);
 }
 """
-      gen_func_names = {
-      }
       self.WriteValidUnitTest(func, file, valid_test, {
           'resource_type': func.GetOriginalArgs()[0].resource_type,
           'gl_gen_func_name': func.GetInfo("gen_func"),
@@ -3730,7 +3729,9 @@
   EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
   EXPECT_EQ(GL_NO_ERROR, GetGLError());
 }
-
+"""
+      if func.GetInfo("gen_func"):
+          valid_test += """
 TEST_F(%(test_name)s, %(name)sValidArgsNewId) {
   EXPECT_CALL(*gl_, %(gl_func_name)s(%(first_gl_arg)s, kNewServiceId));
   EXPECT_CALL(*gl_, %(gl_gen_func_name)s(1, _))
@@ -3743,8 +3744,6 @@
   EXPECT_TRUE(Get%(resource_type)s(kNewClientId) != NULL);
 }
 """
-      gen_func_names = {
-      }
       self.WriteValidUnitTest(func, file, valid_test, {
           'first_arg': func.GetOriginalArgs()[0].GetValidArg(func, 0, 0),
           'first_gl_arg': func.GetOriginalArgs()[0].GetValidGLArg(func, 0, 0),
@@ -3786,7 +3785,7 @@
     SetGLError(GL_INVALID_OPERATION, "%(name)s\", \"%(id)s reserved id");
     return;
   }
-  if (Bind%(type)sHelper(%(arg_string)s)) {
+  if (%(name)sHelper(%(arg_string)s)) {
     helper_->%(name)s(%(arg_string)s);
   }
   CheckGLError();
diff --git a/gpu/command_buffer/client/buffer_tracker_unittest.cc b/gpu/command_buffer/client/buffer_tracker_unittest.cc
index 51f4f94..a298844 100644
--- a/gpu/command_buffer/client/buffer_tracker_unittest.cc
+++ b/gpu/command_buffer/client/buffer_tracker_unittest.cc
@@ -25,10 +25,11 @@
         context_lost_(false) {}
   virtual ~MockClientCommandBufferImpl() {}
 
-  virtual Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE {
+  virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+                                                          int32* id) OVERRIDE {
     if (context_lost_) {
       *id = -1;
-      return gpu::Buffer();
+      return NULL;
     }
     return MockClientCommandBuffer::CreateTransferBuffer(size, id);
   }
diff --git a/gpu/command_buffer/client/client_test_helper.cc b/gpu/command_buffer/client/client_test_helper.cc
index c731edf..f5e58f2 100644
--- a/gpu/command_buffer/client/client_test_helper.cc
+++ b/gpu/command_buffer/client/client_test_helper.cc
@@ -15,6 +15,9 @@
 
 namespace gpu {
 
+MockCommandBufferBase::MockCommandBufferBase() {
+}
+
 MockCommandBufferBase::~MockCommandBufferBase() {
 }
 
@@ -47,29 +50,32 @@
 
 void MockCommandBufferBase::SetGetBuffer(int transfer_buffer_id) {
   ring_buffer_buffer_ = GetTransferBuffer(transfer_buffer_id);
-  ring_buffer_ = static_cast<CommandBufferEntry*>(ring_buffer_buffer_.ptr);
-  state_.num_entries = ring_buffer_buffer_.size / sizeof(ring_buffer_[0]);
+  ring_buffer_ =
+      static_cast<CommandBufferEntry*>(ring_buffer_buffer_->memory());
+  state_.num_entries = ring_buffer_buffer_->size() / sizeof(ring_buffer_[0]);
   state_.token = 10000;  // All token checks in the tests should pass.
 }
 
 // Get's the Id of the next transfer buffer that will be returned
 // by CreateTransferBuffer. This is useful for testing expected ids.
 int32 MockCommandBufferBase::GetNextFreeTransferBufferId() {
-  for (size_t ii = 0; ii < arraysize(transfer_buffers_); ++ii) {
-    if (!transfer_buffers_[ii].get()) {
+  for (size_t ii = 0; ii < arraysize(transfer_buffer_buffers_); ++ii) {
+    if (!transfer_buffer_buffers_[ii].get()) {
       return kTransferBufferBaseId + ii;
     }
   }
   return -1;
 }
 
-Buffer MockCommandBufferBase::CreateTransferBuffer(size_t size, int32* id) {
+scoped_refptr<gpu::Buffer> MockCommandBufferBase::CreateTransferBuffer(
+    size_t size,
+    int32* id) {
   *id = GetNextFreeTransferBufferId();
   if (*id >= 0) {
     int32 ndx = *id - kTransferBufferBaseId;
-    transfer_buffers_[ndx].reset(new int8[size]);
-    transfer_buffer_buffers_[ndx].ptr = transfer_buffers_[ndx].get();
-    transfer_buffer_buffers_[ndx].size = size;
+    scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+    shared_memory->CreateAndMapAnonymous(size);
+    transfer_buffer_buffers_[ndx] = new gpu::Buffer(shared_memory.Pass(), size);
   }
   return GetTransferBuffer(*id);
 }
@@ -78,11 +84,10 @@
   DCHECK_GE(id, kTransferBufferBaseId);
   DCHECK_LT(id, kTransferBufferBaseId + kMaxTransferBuffers);
   id -= kTransferBufferBaseId;
-  transfer_buffers_[id].reset();
-  transfer_buffer_buffers_[id] = Buffer();
+  transfer_buffer_buffers_[id] = NULL;
 }
 
-Buffer MockCommandBufferBase::GetTransferBuffer(int32 id) {
+scoped_refptr<Buffer> MockCommandBufferBase::GetTransferBuffer(int32 id) {
   DCHECK_GE(id, kTransferBufferBaseId);
   DCHECK_LT(id, kTransferBufferBaseId + kMaxTransferBuffers);
   return transfer_buffer_buffers_[id - kTransferBufferBaseId];
diff --git a/gpu/command_buffer/client/client_test_helper.h b/gpu/command_buffer/client/client_test_helper.h
index 6cf98ba..33fae26 100644
--- a/gpu/command_buffer/client/client_test_helper.h
+++ b/gpu/command_buffer/client/client_test_helper.h
@@ -25,7 +25,7 @@
   static const int32 kTransferBufferBaseId = 0x123;
   static const int32 kMaxTransferBuffers = 6;
 
-  MockCommandBufferBase() { }
+  MockCommandBufferBase();
   virtual ~MockCommandBufferBase();
 
   virtual bool Initialize() OVERRIDE;
@@ -36,8 +36,9 @@
   virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE;
   virtual void SetGetBuffer(int transfer_buffer_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE;
-  virtual Buffer GetTransferBuffer(int32 id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+                                                          int32* id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(error::Error error) OVERRIDE;
   virtual void SetContextLostReason(error::ContextLostReason reason) OVERRIDE;
@@ -52,10 +53,9 @@
   virtual void OnFlush() = 0;
 
  private:
-  scoped_ptr<int8[]> transfer_buffers_[kMaxTransferBuffers];
-  Buffer transfer_buffer_buffers_[kMaxTransferBuffers];
+  scoped_refptr<Buffer> transfer_buffer_buffers_[kMaxTransferBuffers];
   CommandBufferEntry* ring_buffer_;
-  Buffer ring_buffer_buffer_;
+  scoped_refptr<Buffer> ring_buffer_buffer_;
   State state_;
 };
 
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.cc b/gpu/command_buffer/client/cmd_buffer_helper.cc
index c32154f..d8ca823 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.cc
+++ b/gpu/command_buffer/client/cmd_buffer_helper.cc
@@ -95,7 +95,8 @@
   }
 
   int32 id = -1;
-  Buffer buffer = command_buffer_->CreateTransferBuffer(ring_buffer_size_, &id);
+  scoped_refptr<Buffer> buffer =
+      command_buffer_->CreateTransferBuffer(ring_buffer_size_, &id);
   if (id < 0) {
     ClearUsable();
     return false;
@@ -108,7 +109,7 @@
   // TODO(gman): Do we really need to call GetState here? We know get & put = 0
   // Also do we need to check state.num_entries?
   CommandBuffer::State state = command_buffer_->GetState();
-  entries_ = static_cast<CommandBufferEntry*>(ring_buffer_.ptr);
+  entries_ = static_cast<CommandBufferEntry*>(ring_buffer_->memory());
   int32 num_ring_buffer_entries =
       ring_buffer_size_ / sizeof(CommandBufferEntry);
   if (num_ring_buffer_entries > state.num_entries) {
diff --git a/gpu/command_buffer/client/cmd_buffer_helper.h b/gpu/command_buffer/client/cmd_buffer_helper.h
index c62071b..49230b4 100644
--- a/gpu/command_buffer/client/cmd_buffer_helper.h
+++ b/gpu/command_buffer/client/cmd_buffer_helper.h
@@ -244,9 +244,7 @@
     return command_buffer_;
   }
 
-  Buffer get_ring_buffer() const {
-    return ring_buffer_;
-  }
+  scoped_refptr<Buffer> get_ring_buffer() const { return ring_buffer_; }
 
   uint32 flush_generation() const { return flush_generation_; }
 
@@ -287,7 +285,7 @@
   CommandBuffer* command_buffer_;
   int32 ring_buffer_id_;
   int32 ring_buffer_size_;
-  Buffer ring_buffer_;
+  scoped_refptr<gpu::Buffer> ring_buffer_;
   CommandBufferEntry* entries_;
   int32 total_entry_count_;  // the total number of entries
   int32 immediate_entry_count_;
diff --git a/gpu/command_buffer/client/context_support.h b/gpu/command_buffer/client/context_support.h
index b5e7713..7344d1e 100644
--- a/gpu/command_buffer/client/context_support.h
+++ b/gpu/command_buffer/client/context_support.h
@@ -33,6 +33,15 @@
   virtual void SetSwapBuffersCompleteCallback(
       const base::Closure& callback) = 0;
 
+  // Schedule a texture to be presented as an overlay synchronously with the
+  // primary surface during the next buffer swap.
+  // This method is not stateful and needs to be re-scheduled every frame.
+  virtual void ScheduleOverlayPlane(int plane_z_order,
+                                    unsigned plane_transform,
+                                    unsigned overlay_texture_id,
+                                    const gfx::Rect& display_bounds,
+                                    const gfx::RectF& uv_rect) = 0;
+
  protected:
   ContextSupport() {}
   virtual ~ContextSupport() {}
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index e0b0cb8..147714a 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -1142,16 +1142,6 @@
   return loc;
 }
 
-void GLES2Implementation::UseProgram(GLuint program) {
-  GPU_CLIENT_SINGLE_THREAD_CHECK();
-  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUseProgram(" << program << ")");
-  if (current_program_ != program) {
-    current_program_ = program;
-    helper_->UseProgram(program);
-  }
-  CheckGLError();
-}
-
 bool GLES2Implementation::GetProgramivHelper(
     GLuint program, GLenum pname, GLint* params) {
   bool got_value = share_group_->program_info_manager()->GetProgramiv(
@@ -2526,7 +2516,7 @@
   return changed;
 }
 
-bool GLES2Implementation::BindVertexArrayHelper(GLuint array) {
+bool GLES2Implementation::BindVertexArrayOESHelper(GLuint array) {
   // TODO(gman): See note #1 above.
   bool changed = false;
   if (!vertex_array_object_manager_->BindVertexArray(array, &changed)) {
@@ -2541,6 +2531,15 @@
   return changed;
 }
 
+bool GLES2Implementation::UseProgramHelper(GLuint program) {
+  bool changed = false;
+  if (current_program_ != program) {
+    current_program_ = program;
+    changed = true;
+  }
+  return changed;
+}
+
 bool GLES2Implementation::IsBufferReservedId(GLuint id) {
   return vertex_array_object_manager_->IsReservedId(id);
 }
@@ -2792,6 +2791,14 @@
   swap_buffers_complete_callback_ = swap_buffers_complete_callback;
 }
 
+void GLES2Implementation::ScheduleOverlayPlane(int plane_z_order,
+                                               unsigned plane_transform,
+                                               unsigned overlay_texture_id,
+                                               const gfx::Rect& display_bounds,
+                                               const gfx::RectF& uv_rect) {
+  NOTREACHED() << "Overlay supported isn't finished.";
+}
+
 void GLES2Implementation::OnSwapBuffersComplete() {
   if (!swap_buffers_complete_callback_.is_null())
     swap_buffers_complete_callback_.Run();
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h
index 314261f..bd5ee04 100644
--- a/gpu/command_buffer/client/gles2_implementation.h
+++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -220,6 +220,11 @@
   virtual void SetSwapBuffersCompleteCallback(
       const base::Closure& swap_buffers_complete_callback)
           OVERRIDE;
+  virtual void ScheduleOverlayPlane(int plane_z_order,
+                                    unsigned plane_transform,
+                                    unsigned overlay_texture_id,
+                                    const gfx::Rect& display_bounds,
+                                    const gfx::RectF& uv_rect) OVERRIDE;
 
   void GetProgramInfoCHROMIUMHelper(GLuint program, std::vector<int8>* result);
   GLint GetAttribLocationHelper(GLuint program, const char* name);
@@ -494,12 +499,14 @@
   bool IsRenderbufferReservedId(GLuint id) { return false; }
   bool IsTextureReservedId(GLuint id) { return false; }
   bool IsVertexArrayReservedId(GLuint id) { return false; }
+  bool IsProgramReservedId(GLuint id) { return false; }
 
   bool BindBufferHelper(GLenum target, GLuint texture);
   bool BindFramebufferHelper(GLenum target, GLuint texture);
   bool BindRenderbufferHelper(GLenum target, GLuint texture);
   bool BindTextureHelper(GLenum target, GLuint texture);
-  bool BindVertexArrayHelper(GLuint array);
+  bool BindVertexArrayOESHelper(GLuint array);
+  bool UseProgramHelper(GLuint program);
 
   void GenBuffersHelper(GLsizei n, const GLuint* buffers);
   void GenFramebuffersHelper(GLsizei n, const GLuint* framebuffers);
diff --git a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
index dd42a18..7e1144c 100644
--- a/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_impl_autogen.h
@@ -1549,6 +1549,19 @@
   CheckGLError();
 }
 
+void GLES2Implementation::UseProgram(GLuint program) {
+  GPU_CLIENT_SINGLE_THREAD_CHECK();
+  GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUseProgram(" << program << ")");
+  if (IsProgramReservedId(program)) {
+    SetGLError(GL_INVALID_OPERATION, "UseProgram", "program reserved id");
+    return;
+  }
+  if (UseProgramHelper(program)) {
+    helper_->UseProgram(program);
+  }
+  CheckGLError();
+}
+
 void GLES2Implementation::ValidateProgram(GLuint program) {
   GPU_CLIENT_SINGLE_THREAD_CHECK();
   GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glValidateProgram(" << program
@@ -1906,7 +1919,7 @@
     SetGLError(GL_INVALID_OPERATION, "BindVertexArrayOES", "array reserved id");
     return;
   }
-  if (BindVertexArrayHelper(array)) {
+  if (BindVertexArrayOESHelper(array)) {
     helper_->BindVertexArrayOES(array);
   }
   CheckGLError();
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc
index 3e9acb1..aa90733 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest.cc
+++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc
@@ -167,11 +167,11 @@
   static const int kNumBuffers = 2;
 
   uint8* actual_buffer() const {
-    return static_cast<uint8*>(buffers_[actual_buffer_index_].ptr);
+    return static_cast<uint8*>(buffers_[actual_buffer_index_]->memory());
   }
 
   uint8* expected_buffer() const {
-    return static_cast<uint8*>(buffers_[expected_buffer_index_].ptr);
+    return static_cast<uint8*>(buffers_[expected_buffer_index_]->memory());
   }
 
   uint32 AllocateExpectedTransferBuffer(size_t size) {
@@ -214,7 +214,7 @@
   size_t result_size_;
   uint32 alignment_;
   int buffer_ids_[kNumBuffers];
-  gpu::Buffer buffers_[kNumBuffers];
+  scoped_refptr<Buffer> buffers_[kNumBuffers];
   int actual_buffer_index_;
   int expected_buffer_index_;
   void* last_alloc_;
@@ -455,8 +455,8 @@
       helper_->CommandBufferHelper::Finish();
       ::testing::Mock::VerifyAndClearExpectations(gl_.get());
 
-      Buffer ring_buffer = helper_->get_ring_buffer();
-      commands_ = static_cast<CommandBufferEntry*>(ring_buffer.ptr) +
+      scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
+      commands_ = static_cast<CommandBufferEntry*>(ring_buffer->memory()) +
                   command_buffer()->GetState().put_offset;
       ClearCommands();
       EXPECT_TRUE(transfer_buffer_->InSync());
@@ -480,8 +480,8 @@
     int GetNextToken() { return ++token_; }
 
     void ClearCommands() {
-      Buffer ring_buffer = helper_->get_ring_buffer();
-      memset(ring_buffer.ptr, kInitialValue, ring_buffer.size);
+      scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
+      memset(ring_buffer->memory(), kInitialValue, ring_buffer->size());
     }
 
     scoped_ptr<MockClientCommandBuffer> command_buffer_;
@@ -499,9 +499,9 @@
   virtual void TearDown() OVERRIDE;
 
   bool NoCommandsWritten() {
-    Buffer ring_buffer = helper_->get_ring_buffer();
-    const uint8* cmds = reinterpret_cast<const uint8*>(ring_buffer.ptr);
-    const uint8* end = cmds + ring_buffer.size;
+    scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
+    const uint8* cmds = reinterpret_cast<const uint8*>(ring_buffer->memory());
+    const uint8* end = cmds + ring_buffer->size();
     for (; cmds < end; ++cmds) {
       if (*cmds != kInitialValue) {
         return false;
@@ -539,8 +539,8 @@
   }
 
   void ClearCommands() {
-    Buffer ring_buffer = helper_->get_ring_buffer();
-    memset(ring_buffer.ptr, kInitialValue, ring_buffer.size);
+    scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
+    memset(ring_buffer->memory(), kInitialValue, ring_buffer->size());
   }
 
   size_t MaxTransferBufferSize() {
diff --git a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
index 18f7c12..ffae3bf 100644
--- a/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
+++ b/gpu/command_buffer/client/gles2_implementation_unittest_autogen.h
@@ -1397,6 +1397,9 @@
 
   gl_->UseProgram(1);
   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
+  ClearCommands();
+  gl_->UseProgram(1);
+  EXPECT_TRUE(NoCommandsWritten());
 }
 
 TEST_F(GLES2ImplementationTest, ValidateProgram) {
diff --git a/gpu/command_buffer/client/mapped_memory.cc b/gpu/command_buffer/client/mapped_memory.cc
index 15584aa..aeab080 100644
--- a/gpu/command_buffer/client/mapped_memory.cc
+++ b/gpu/command_buffer/client/mapped_memory.cc
@@ -13,12 +13,14 @@
 
 namespace gpu {
 
-MemoryChunk::MemoryChunk(
-    int32 shm_id, gpu::Buffer shm, CommandBufferHelper* helper)
+MemoryChunk::MemoryChunk(int32 shm_id,
+                         scoped_refptr<gpu::Buffer> shm,
+                         CommandBufferHelper* helper)
     : shm_id_(shm_id),
       shm_(shm),
-      allocator_(shm.size, helper, shm.ptr) {
-}
+      allocator_(shm->size(), helper, shm->memory()) {}
+
+MemoryChunk::~MemoryChunk() {}
 
 MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper,
                                          size_t unused_memory_reclaim_limit)
@@ -82,7 +84,8 @@
       ((size + chunk_size_multiple_ - 1) / chunk_size_multiple_) *
       chunk_size_multiple_;
   int32 id = -1;
-  gpu::Buffer shm = cmd_buf->CreateTransferBuffer(chunk_size, &id);
+  scoped_refptr<gpu::Buffer> shm =
+      cmd_buf->CreateTransferBuffer(chunk_size, &id);
   if (id  < 0)
     return NULL;
   MemoryChunk* mc = new MemoryChunk(id, shm, helper_);
diff --git a/gpu/command_buffer/client/mapped_memory.h b/gpu/command_buffer/client/mapped_memory.h
index b8f3129..00251e8 100644
--- a/gpu/command_buffer/client/mapped_memory.h
+++ b/gpu/command_buffer/client/mapped_memory.h
@@ -18,7 +18,10 @@
 // Manages a shared memory segment.
 class GPU_EXPORT MemoryChunk {
  public:
-  MemoryChunk(int32 shm_id, gpu::Buffer shm, CommandBufferHelper* helper);
+  MemoryChunk(int32 shm_id,
+              scoped_refptr<gpu::Buffer> shm,
+              CommandBufferHelper* helper);
+  ~MemoryChunk();
 
   // Gets the size of the largest free block that is available without waiting.
   unsigned int GetLargestFreeSizeWithoutWaiting() {
@@ -33,7 +36,7 @@
 
   // Gets the size of the chunk.
   unsigned int GetSize() const {
-    return static_cast<unsigned int>(shm_.size);
+    return static_cast<unsigned int>(shm_->size());
   }
 
   // The shared memory id for this chunk.
@@ -86,8 +89,9 @@
 
   // Returns true if pointer is in the range of this block.
   bool IsInChunk(void* pointer) const {
-    return pointer >= shm_.ptr &&
-           pointer < reinterpret_cast<const int8*>(shm_.ptr) + shm_.size;
+    return pointer >= shm_->memory() &&
+           pointer <
+               reinterpret_cast<const int8*>(shm_->memory()) + shm_->size();
   }
 
   // Returns true of any memory in this chunk is in use.
@@ -101,7 +105,7 @@
 
  private:
   int32 shm_id_;
-  gpu::Buffer shm_;
+  scoped_refptr<gpu::Buffer> shm_;
   FencedAllocatorWrapper allocator_;
 
   DISALLOW_COPY_AND_ASSIGN(MemoryChunk);
diff --git a/gpu/command_buffer/client/mapped_memory_unittest.cc b/gpu/command_buffer/client/mapped_memory_unittest.cc
index 90d1ce7..3e174fa 100644
--- a/gpu/command_buffer/client/mapped_memory_unittest.cc
+++ b/gpu/command_buffer/client/mapped_memory_unittest.cc
@@ -94,11 +94,10 @@
   static const int32 kShmId = 123;
   virtual void SetUp() {
     MappedMemoryTestBase::SetUp();
-    buffer_.reset(new uint8[kBufferSize]);
-    gpu::Buffer buf;
-    buf.size = kBufferSize;
-    buf.ptr = buffer_.get();
-    chunk_.reset(new MemoryChunk(kShmId, buf, helper_.get()));
+    scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+    shared_memory->CreateAndMapAnonymous(kBufferSize);
+    buffer_ = new gpu::Buffer(shared_memory.Pass(), kBufferSize);
+    chunk_.reset(new MemoryChunk(kShmId, buffer_, helper_.get()));
   }
 
   virtual void TearDown() {
@@ -108,8 +107,10 @@
     MappedMemoryTestBase::TearDown();
   }
 
+  uint8* buffer_memory() { return static_cast<uint8*>(buffer_->memory()); }
+
   scoped_ptr<MemoryChunk> chunk_;
-  scoped_ptr<uint8[]> buffer_;
+  scoped_refptr<gpu::Buffer> buffer_;
 };
 
 #ifndef _MSC_VER
@@ -124,8 +125,9 @@
   EXPECT_EQ(kBufferSize, chunk_->GetSize());
   void *pointer = chunk_->Alloc(kSize);
   ASSERT_TRUE(pointer);
-  EXPECT_LE(buffer_.get(), static_cast<uint8 *>(pointer));
-  EXPECT_GE(kBufferSize, static_cast<uint8 *>(pointer) - buffer_.get() + kSize);
+  EXPECT_LE(buffer_->memory(), static_cast<uint8*>(pointer));
+  EXPECT_GE(kBufferSize,
+            static_cast<uint8*>(pointer) - buffer_memory() + kSize);
   EXPECT_EQ(kBufferSize - kSize, chunk_->GetLargestFreeSizeWithoutWaiting());
   EXPECT_EQ(kBufferSize - kSize, chunk_->GetLargestFreeSizeWithWaiting());
   EXPECT_EQ(kBufferSize, chunk_->GetSize());
@@ -136,8 +138,8 @@
 
   uint8 *pointer_char = static_cast<uint8*>(chunk_->Alloc(kSize));
   ASSERT_TRUE(pointer_char);
-  EXPECT_LE(buffer_.get(), pointer_char);
-  EXPECT_GE(buffer_.get() + kBufferSize, pointer_char + kSize);
+  EXPECT_LE(buffer_memory(), pointer_char);
+  EXPECT_GE(buffer_memory() + kBufferSize, pointer_char + kSize);
   EXPECT_EQ(kBufferSize - kSize, chunk_->GetLargestFreeSizeWithoutWaiting());
   EXPECT_EQ(kBufferSize - kSize, chunk_->GetLargestFreeSizeWithWaiting());
   chunk_->Free(pointer_char);
diff --git a/gpu/command_buffer/client/transfer_buffer.cc b/gpu/command_buffer/client/transfer_buffer.cc
index 00d1f48..da3996b 100644
--- a/gpu/command_buffer/client/transfer_buffer.cc
+++ b/gpu/command_buffer/client/transfer_buffer.cc
@@ -58,8 +58,7 @@
     helper_->Finish();
     helper_->command_buffer()->DestroyTransferBuffer(buffer_id_);
     buffer_id_ = -1;
-    buffer_.ptr = NULL;
-    buffer_.size = 0;
+    buffer_ = NULL;
     result_buffer_ = NULL;
     result_shm_offset_ = 0;
     ring_buffer_.reset();
@@ -86,7 +85,7 @@
 void TransferBuffer::AllocateRingBuffer(unsigned int size) {
   for (;size >= min_buffer_size_; size /= 2) {
     int32 id = -1;
-    gpu::Buffer buffer =
+    scoped_refptr<gpu::Buffer> buffer =
         helper_->command_buffer()->CreateTransferBuffer(size, &id);
     if (id != -1) {
       buffer_ = buffer;
@@ -94,11 +93,11 @@
           alignment_,
           id,
           result_size_,
-          buffer_.size - result_size_,
+          buffer_->size() - result_size_,
           helper_,
-          static_cast<char*>(buffer_.ptr) + result_size_));
+          static_cast<char*>(buffer_->memory()) + result_size_));
       buffer_id_ = id;
-      result_buffer_ = buffer_.ptr;
+      result_buffer_ = buffer_->memory();
       result_shm_offset_ = 0;
       return;
     }
@@ -147,7 +146,7 @@
   needed_buffer_size = std::max(needed_buffer_size, default_buffer_size_);
   needed_buffer_size = std::min(needed_buffer_size, max_buffer_size_);
 
-  if (usable_ && (!HaveBuffer() || needed_buffer_size > buffer_.size)) {
+  if (usable_ && (!HaveBuffer() || needed_buffer_size > buffer_->size())) {
     if (HaveBuffer()) {
       Free();
     }
diff --git a/gpu/command_buffer/client/transfer_buffer.h b/gpu/command_buffer/client/transfer_buffer.h
index 1117398..28971d7 100644
--- a/gpu/command_buffer/client/transfer_buffer.h
+++ b/gpu/command_buffer/client/transfer_buffer.h
@@ -144,7 +144,7 @@
   unsigned int bytes_since_last_flush_;
 
   // the current buffer.
-  gpu::Buffer buffer_;
+  scoped_refptr<gpu::Buffer> buffer_;
 
   // id of buffer. -1 = no buffer
   int32 buffer_id_;
diff --git a/gpu/command_buffer/client/transfer_buffer_unittest.cc b/gpu/command_buffer/client/transfer_buffer_unittest.cc
index 39ce923..7201477 100644
--- a/gpu/command_buffer/client/transfer_buffer_unittest.cc
+++ b/gpu/command_buffer/client/transfer_buffer_unittest.cc
@@ -214,9 +214,10 @@
   virtual ~MockClientCommandBufferCanFail() {
   }
 
-  MOCK_METHOD2(CreateTransferBuffer, Buffer(size_t size, int32* id));
+  MOCK_METHOD2(CreateTransferBuffer,
+               scoped_refptr<Buffer>(size_t size, int32* id));
 
-  Buffer RealCreateTransferBuffer(size_t size, int32* id) {
+  scoped_refptr<gpu::Buffer> RealCreateTransferBuffer(size_t size, int32* id) {
     return MockCommandBufferBase::CreateTransferBuffer(size, id);
   }
 };
@@ -375,7 +376,8 @@
   // Try to allocate again, fail first request
   EXPECT_CALL(*command_buffer(),
               CreateTransferBuffer(kStartTransferBufferSize, _))
-      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
+      .WillOnce(
+           DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
       .RetiresOnSaturation();
   EXPECT_CALL(*command_buffer(),
               CreateTransferBuffer(kMinTransferBufferSize, _))
@@ -427,9 +429,12 @@
 
   // Try to allocate again, fail both requests.
   EXPECT_CALL(*command_buffer(), CreateTransferBuffer(_, _))
-      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
-      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
-      .WillOnce(DoAll(SetArgPointee<1>(-1), Return(Buffer())))
+      .WillOnce(
+           DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
+      .WillOnce(
+           DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
+      .WillOnce(
+           DoAll(SetArgPointee<1>(-1), Return(scoped_refptr<gpu::Buffer>())))
       .RetiresOnSaturation();
 
   const size_t kSize1 = 512 - kStartingOffset;
diff --git a/gpu/command_buffer/common/buffer.cc b/gpu/command_buffer/common/buffer.cc
new file mode 100644
index 0000000..bbf40a1
--- /dev/null
+++ b/gpu/command_buffer/common/buffer.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/common/buffer.h"
+
+#include "base/logging.h"
+
+#include "base/numerics/safe_math.h"
+
+namespace gpu {
+
+Buffer::Buffer(scoped_ptr<base::SharedMemory> shared_memory, size_t size)
+    : shared_memory_(shared_memory.Pass()),
+      memory_(shared_memory_->memory()),
+      size_(size) {
+  DCHECK(memory_) << "The memory must be mapped to create a Buffer";
+}
+
+Buffer::~Buffer() {}
+
+void* Buffer::GetDataAddress(uint32 data_offset, uint32 data_size) const {
+  base::CheckedNumeric<uint32> end = data_offset;
+  end += data_size;
+  if (!end.IsValid() || end.ValueOrDie() > static_cast<uint32>(size_))
+    return NULL;
+  return static_cast<uint8*>(memory_) + data_offset;
+}
+
+} // namespace gpu
diff --git a/gpu/command_buffer/common/buffer.h b/gpu/command_buffer/common/buffer.h
index a2721a8..e9a1558 100644
--- a/gpu/command_buffer/common/buffer.h
+++ b/gpu/command_buffer/common/buffer.h
@@ -1,11 +1,15 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef GPU_COMMAND_BUFFER_COMMON_BUFFER_H_
 #define GPU_COMMAND_BUFFER_COMMON_BUFFER_H_
 
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
 #include "gpu/command_buffer/common/types.h"
+#include "gpu/gpu_export.h"
 
 namespace base {
   class SharedMemory;
@@ -13,17 +17,27 @@
 
 namespace gpu {
 
-// Address and size of a buffer and optionally a shared memory object. This
-// type has value semantics.
-struct Buffer {
-  Buffer() : ptr(NULL), size(0), shared_memory(NULL) {
-  }
+// Buffer owns a piece of shared-memory of a certain size.
+class GPU_EXPORT Buffer : public base::RefCountedThreadSafe<Buffer> {
+ public:
+  Buffer(scoped_ptr<base::SharedMemory> shared_memory, size_t size);
 
-  void* ptr;
-  size_t size;
+  base::SharedMemory* shared_memory() const { return shared_memory_.get(); }
+  void* memory() const { return memory_; }
+  size_t size() const { return size_; }
 
-  // Null if the buffer is not shared memory or if it is not exposed as such.
-  base::SharedMemory* shared_memory;
+  // Returns NULL if the address overflows the memory.
+  void* GetDataAddress(uint32 data_offset, uint32 data_size) const;
+
+ private:
+  friend class base::RefCountedThreadSafe<Buffer>;
+  ~Buffer();
+
+  scoped_ptr<base::SharedMemory> shared_memory_;
+  void* memory_;
+  size_t size_;
+
+  DISALLOW_COPY_AND_ASSIGN(Buffer);
 };
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/common/command_buffer.h b/gpu/command_buffer/common/command_buffer.h
index ac52c8b..10f6026 100644
--- a/gpu/command_buffer/common/command_buffer.h
+++ b/gpu/command_buffer/common/command_buffer.h
@@ -118,14 +118,15 @@
 
   // Create a transfer buffer of the given size. Returns its ID or -1 on
   // error.
-  virtual Buffer CreateTransferBuffer(size_t size, int32* id) = 0;
+  virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+                                                          int32* id) = 0;
 
   // Destroy a transfer buffer. The ID must be positive.
   virtual void DestroyTransferBuffer(int32 id) = 0;
 
   // Get the transfer buffer associated with an ID. Returns a null buffer for
   // ID 0.
-  virtual Buffer GetTransferBuffer(int32 id) = 0;
+  virtual scoped_refptr<gpu::Buffer> GetTransferBuffer(int32 id) = 0;
 
   // Allows the reader to update the current token value.
   virtual void SetToken(int32 token) = 0;
diff --git a/gpu/command_buffer/common/command_buffer_mock.cc b/gpu/command_buffer/common/command_buffer_mock.cc
index 6ed2eee..a64dc45 100644
--- a/gpu/command_buffer/common/command_buffer_mock.cc
+++ b/gpu/command_buffer/common/command_buffer_mock.cc
@@ -8,7 +8,7 @@
 
 MockCommandBuffer::MockCommandBuffer() {
   ON_CALL(*this, GetTransferBuffer(testing::_))
-      .WillByDefault(testing::Return(Buffer()));
+      .WillByDefault(testing::Return(scoped_refptr<gpu::Buffer>()));
 }
 
 MockCommandBuffer::~MockCommandBuffer() {}
diff --git a/gpu/command_buffer/common/command_buffer_mock.h b/gpu/command_buffer/common/command_buffer_mock.h
index 6e99fee..50c6f5b 100644
--- a/gpu/command_buffer/common/command_buffer_mock.h
+++ b/gpu/command_buffer/common/command_buffer_mock.h
@@ -30,9 +30,10 @@
   MOCK_METHOD2(WaitForGetOffsetInRange, void(int32 start, int32 end));
   MOCK_METHOD1(SetGetBuffer, void(int32 transfer_buffer_id));
   MOCK_METHOD1(SetGetOffset, void(int32 get_offset));
-  MOCK_METHOD2(CreateTransferBuffer, Buffer(size_t size, int32* id));
+  MOCK_METHOD2(CreateTransferBuffer,
+               scoped_refptr<gpu::Buffer>(size_t size, int32* id));
   MOCK_METHOD1(DestroyTransferBuffer, void(int32 id));
-  MOCK_METHOD1(GetTransferBuffer, Buffer(int32 id));
+  MOCK_METHOD1(GetTransferBuffer, scoped_refptr<gpu::Buffer>(int32 id));
   MOCK_METHOD1(SetToken, void(int32 token));
   MOCK_METHOD1(SetParseError, void(error::Error error));
   MOCK_METHOD1(SetContextLostReason,
diff --git a/gpu/command_buffer/gles2_utils.target.darwin-arm.mk b/gpu/command_buffer/gles2_utils.target.darwin-arm.mk
index 6270eac..31687e9 100644
--- a/gpu/command_buffer/gles2_utils.target.darwin-arm.mk
+++ b/gpu/command_buffer/gles2_utils.target.darwin-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
diff --git a/gpu/command_buffer/gles2_utils.target.darwin-mips.mk b/gpu/command_buffer/gles2_utils.target.darwin-mips.mk
index 56c339b..67bc15e 100644
--- a/gpu/command_buffer/gles2_utils.target.darwin-mips.mk
+++ b/gpu/command_buffer/gles2_utils.target.darwin-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
diff --git a/gpu/command_buffer/gles2_utils.target.darwin-x86.mk b/gpu/command_buffer/gles2_utils.target.darwin-x86.mk
index 374c2940..e5e395e 100644
--- a/gpu/command_buffer/gles2_utils.target.darwin-x86.mk
+++ b/gpu/command_buffer/gles2_utils.target.darwin-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
diff --git a/gpu/command_buffer/gles2_utils.target.darwin-x86_64.mk b/gpu/command_buffer/gles2_utils.target.darwin-x86_64.mk
new file mode 100644
index 0000000..484e040
--- /dev/null
+++ b/gpu/command_buffer/gles2_utils.target.darwin-x86_64.mk
@@ -0,0 +1,266 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_gles2_utils_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/gles2_cmd_utils.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DGLES2_UTILS_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DGLES2_UTILS_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_gles2_utils_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_utils
+gles2_utils: gpu_command_buffer_gles2_utils_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer/gles2_utils.target.linux-arm.mk b/gpu/command_buffer/gles2_utils.target.linux-arm.mk
index 6270eac..31687e9 100644
--- a/gpu/command_buffer/gles2_utils.target.linux-arm.mk
+++ b/gpu/command_buffer/gles2_utils.target.linux-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
diff --git a/gpu/command_buffer/gles2_utils.target.linux-mips.mk b/gpu/command_buffer/gles2_utils.target.linux-mips.mk
index 56c339b..67bc15e 100644
--- a/gpu/command_buffer/gles2_utils.target.linux-mips.mk
+++ b/gpu/command_buffer/gles2_utils.target.linux-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
diff --git a/gpu/command_buffer/gles2_utils.target.linux-x86.mk b/gpu/command_buffer/gles2_utils.target.linux-x86.mk
index 374c2940..e5e395e 100644
--- a/gpu/command_buffer/gles2_utils.target.linux-x86.mk
+++ b/gpu/command_buffer/gles2_utils.target.linux-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DGLES2_UTILS_IMPLEMENTATION' \
diff --git a/gpu/command_buffer/gles2_utils.target.linux-x86_64.mk b/gpu/command_buffer/gles2_utils.target.linux-x86_64.mk
new file mode 100644
index 0000000..484e040
--- /dev/null
+++ b/gpu/command_buffer/gles2_utils.target.linux-x86_64.mk
@@ -0,0 +1,266 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_gles2_utils_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/gles2_cmd_utils.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DGLES2_UTILS_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DGLES2_UTILS_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_gles2_utils_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_utils
+gles2_utils: gpu_command_buffer_gles2_utils_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate.cc b/gpu/command_buffer/service/async_pixel_transfer_delegate.cc
index 074f675..6b1dbc6 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate.cc
@@ -4,26 +4,18 @@
 
 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
 
-#include "base/memory/shared_memory.h"
-#include "gpu/command_buffer/service/safe_shared_memory_pool.h"
-
 namespace gpu {
 
-namespace {
-
-void* GetAddressImpl(base::SharedMemory* shared_memory,
-                     uint32 shm_size,
-                     uint32 shm_data_offset,
-                     uint32 shm_data_size) {
-  // Memory bounds have already been validated, so there
-  // are just DCHECKS here.
-  DCHECK(shared_memory);
-  DCHECK(shared_memory->memory());
-  DCHECK_LE(shm_data_offset + shm_data_size, shm_size);
-  return static_cast<int8*>(shared_memory->memory()) + shm_data_offset;
+AsyncMemoryParams::AsyncMemoryParams(scoped_refptr<Buffer> buffer,
+                    uint32 data_offset,
+                    uint32 data_size)
+    : buffer_(buffer), data_offset_(data_offset), data_size_(data_size) {
+  DCHECK(buffer_);
+  DCHECK(buffer_->memory());
 }
 
-}  // namespace
+AsyncMemoryParams::~AsyncMemoryParams() {
+}
 
 AsyncPixelTransferUploadStats::AsyncPixelTransferUploadStats()
     : texture_upload_count_(0) {}
@@ -44,27 +36,8 @@
   return texture_upload_count_;
 }
 
-AsyncPixelTransferDelegate::AsyncPixelTransferDelegate(){}
+AsyncPixelTransferDelegate::AsyncPixelTransferDelegate() {}
 
-AsyncPixelTransferDelegate::~AsyncPixelTransferDelegate(){}
-
-// static
-void* AsyncPixelTransferDelegate::GetAddress(
-    const AsyncMemoryParams& mem_params) {
-  return GetAddressImpl(mem_params.shared_memory,
-                        mem_params.shm_size,
-                        mem_params.shm_data_offset,
-                        mem_params.shm_data_size);
-}
-
-// static
-void* AsyncPixelTransferDelegate::GetAddress(
-    ScopedSafeSharedMemory* safe_shared_memory,
-    const AsyncMemoryParams& mem_params) {
-  return GetAddressImpl(safe_shared_memory->shared_memory(),
-                        mem_params.shm_size,
-                        mem_params.shm_data_offset,
-                        mem_params.shm_data_size);
-}
+AsyncPixelTransferDelegate::~AsyncPixelTransferDelegate() {}
 
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/async_pixel_transfer_delegate.h b/gpu/command_buffer/service/async_pixel_transfer_delegate.h
index dc0f2d7..47d71d8 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_delegate.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_delegate.h
@@ -11,6 +11,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
 #include "base/time/time.h"
+#include "gpu/command_buffer/common/buffer.h"
 #include "gpu/gpu_export.h"
 #include "ui/gl/gl_bindings.h"
 
@@ -44,11 +45,24 @@
   GLenum type;
 };
 
-struct AsyncMemoryParams {
-  base::SharedMemory* shared_memory;
-  uint32 shm_size;
-  uint32 shm_data_offset;
-  uint32 shm_data_size;
+class AsyncMemoryParams {
+ public:
+  AsyncMemoryParams(scoped_refptr<Buffer> buffer,
+                    uint32 data_offset,
+                    uint32 data_size);
+  ~AsyncMemoryParams();
+
+  scoped_refptr<Buffer> buffer() const { return buffer_; }
+  uint32 data_size() const { return data_size_; }
+  uint32 data_offset() const { return data_offset_; }
+  void* GetDataAddress() const {
+    return buffer_->GetDataAddress(data_offset_, data_size_);
+  }
+
+ private:
+  scoped_refptr<Buffer> buffer_;
+  uint32 data_offset_;
+  uint32 data_size_;
 };
 
 class AsyncPixelTransferUploadStats
@@ -92,13 +106,6 @@
   // Block until the specified transfer completes.
   virtual void WaitForTransferCompletion() = 0;
 
-  // Gets the address of the data from shared memory.
-  static void* GetAddress(const AsyncMemoryParams& mem_params);
-
-  // Sometimes the |safe_shared_memory| is duplicate to prevent use after free.
-  static void* GetAddress(ScopedSafeSharedMemory* safe_shared_memory,
-                          const AsyncMemoryParams& mem_params);
-
  protected:
   AsyncPixelTransferDelegate();
 
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager.h b/gpu/command_buffer/service/async_pixel_transfer_manager.h
index d0ea5da..4b57619 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager.h
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager.h
@@ -32,7 +32,7 @@
 
 namespace gpu {
 class AsyncPixelTransferDelegate;
-struct AsyncMemoryParams;
+class AsyncMemoryParams;
 struct AsyncTexImage2DParams;
 
 class AsyncPixelTransferCompletionObserver
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
index 3f3acc5..32fa4c0 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
@@ -16,7 +16,6 @@
 #include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
-#include "gpu/command_buffer/service/safe_shared_memory_pool.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/scoped_binders.h"
@@ -81,12 +80,9 @@
 
 void PerformNotifyCompletion(
     AsyncMemoryParams mem_params,
-    ScopedSafeSharedMemory* safe_shared_memory,
     scoped_refptr<AsyncPixelTransferCompletionObserver> observer) {
   TRACE_EVENT0("gpu", "PerformNotifyCompletion");
-  AsyncMemoryParams safe_mem_params = mem_params;
-  safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
-  observer->DidComplete(safe_mem_params);
+  observer->DidComplete(mem_params);
 }
 
 class TransferThread : public base::Thread {
@@ -117,16 +113,10 @@
     context_ = NULL;
   }
 
-  SafeSharedMemoryPool* safe_shared_memory_pool() {
-      return &safe_shared_memory_pool_;
-  }
-
  private:
   scoped_refptr<gfx::GLContext> context_;
   scoped_refptr<gfx::GLSurface> surface_;
 
-  SafeSharedMemoryPool safe_shared_memory_pool_;
-
   DISALLOW_COPY_AND_ASSIGN(TransferThread);
 };
 
@@ -137,10 +127,6 @@
   return g_transfer_thread.Pointer()->message_loop_proxy().get();
 }
 
-SafeSharedMemoryPool* safe_shared_memory_pool() {
-  return g_transfer_thread.Pointer()->safe_shared_memory_pool();
-}
-
 // Class which holds async pixel transfers state (EGLImage).
 // The EGLImage is accessed by either thread, but everything
 // else accessed only on the main thread.
@@ -254,7 +240,6 @@
   void PerformAsyncTexImage2D(
       AsyncTexImage2DParams tex_params,
       AsyncMemoryParams mem_params,
-      ScopedSafeSharedMemory* safe_shared_memory,
       scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) {
     TRACE_EVENT2("gpu",
                  "PerformAsyncTexImage",
@@ -269,8 +254,7 @@
       return;
     }
 
-    void* data =
-        AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
+    void* data = mem_params.GetDataAddress();
 
     base::TimeTicks begin_time;
     if (texture_upload_stats.get())
@@ -317,7 +301,6 @@
   void PerformAsyncTexSubImage2D(
       AsyncTexSubImage2DParams tex_params,
       AsyncMemoryParams mem_params,
-      ScopedSafeSharedMemory* safe_shared_memory,
       scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) {
     TRACE_EVENT2("gpu",
                  "PerformAsyncTexSubImage2D",
@@ -329,8 +312,7 @@
     DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
     DCHECK_EQ(0, tex_params.level);
 
-    void* data =
-        AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
+    void* data = mem_params.GetDataAddress();
 
     base::TimeTicks begin_time;
     if (texture_upload_stats.get())
@@ -509,9 +491,6 @@
   if (WorkAroundAsyncTexImage2D(tex_params, mem_params, bind_callback))
     return;
 
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
   DCHECK(!state_->TransferIsInProgress());
   DCHECK_EQ(state_->egl_image_, EGL_NO_IMAGE_KHR);
   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
@@ -533,9 +512,6 @@
           state_,
           tex_params,
           mem_params,
-          base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                                 mem_params.shared_memory,
-                                                 mem_params.shm_size)),
           shared_state_->texture_upload_stats));
 
   DCHECK(CHECK_GL());
@@ -550,9 +526,6 @@
   if (WorkAroundAsyncTexSubImage2D(tex_params, mem_params))
     return;
   DCHECK(!state_->TransferIsInProgress());
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
   DCHECK_EQ(tex_params.level, 0);
 
@@ -571,9 +544,6 @@
           state_,
           tex_params,
           mem_params,
-          base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                                 mem_params.shared_memory,
-                                                 mem_params.shm_size)),
           shared_state_->texture_upload_stats));
 
   DCHECK(CHECK_GL());
@@ -621,7 +591,7 @@
   // On imagination we allocate synchronously all the time, even
   // if the dimensions support fast uploads. This is for part a.)
   // above, so allocations occur on a different thread/context as uploads.
-  void* data = GetAddress(mem_params);
+  void* data = mem_params.GetDataAddress();
   SetGlParametersForEglImageTexture();
 
   {
@@ -672,7 +642,7 @@
   DCHECK_EQ(state_->define_params_.format, tex_params.format);
   DCHECK_EQ(state_->define_params_.type, tex_params.type);
 
-  void* data = GetAddress(mem_params);
+  void* data = mem_params.GetDataAddress();
   base::TimeTicks begin_time;
   if (shared_state_->texture_upload_stats.get())
     begin_time = base::TimeTicks::HighResNow();
@@ -733,19 +703,12 @@
 void AsyncPixelTransferManagerEGL::AsyncNotifyCompletion(
     const AsyncMemoryParams& mem_params,
     AsyncPixelTransferCompletionObserver* observer) {
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
   // Post a PerformNotifyCompletion task to the upload thread. This task
   // will run after all async transfers are complete.
   transfer_message_loop_proxy()->PostTask(
       FROM_HERE,
       base::Bind(&PerformNotifyCompletion,
                  mem_params,
-                 base::Owned(
-                     new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                                mem_params.shared_memory,
-                                                mem_params.shm_size)),
                  make_scoped_refptr(observer)));
 }
 
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
index dcd870d..58748dd 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc
@@ -9,30 +9,19 @@
 #include "base/debug/trace_event_synthetic_delay.h"
 #include "base/lazy_instance.h"
 #include "base/memory/weak_ptr.h"
-#include "gpu/command_buffer/service/safe_shared_memory_pool.h"
 #include "ui/gl/scoped_binders.h"
 
 namespace gpu {
 
 namespace {
 
-base::LazyInstance<SafeSharedMemoryPool> g_safe_shared_memory_pool =
-    LAZY_INSTANCE_INITIALIZER;
-
-SafeSharedMemoryPool* safe_shared_memory_pool() {
-  return g_safe_shared_memory_pool.Pointer();
-}
-
 static uint64 g_next_pixel_transfer_state_id = 1;
 
 void PerformNotifyCompletion(
     AsyncMemoryParams mem_params,
-    ScopedSafeSharedMemory* safe_shared_memory,
     scoped_refptr<AsyncPixelTransferCompletionObserver> observer) {
   TRACE_EVENT0("gpu", "PerformNotifyCompletion");
-  AsyncMemoryParams safe_mem_params = mem_params;
-  safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
-  observer->DidComplete(safe_mem_params);
+  observer->DidComplete(mem_params);
 }
 
 }  // namespace
@@ -61,15 +50,11 @@
   virtual void WaitForTransferCompletion() OVERRIDE;
 
  private:
-  void PerformAsyncTexImage2D(
-      AsyncTexImage2DParams tex_params,
-      AsyncMemoryParams mem_params,
-      const base::Closure& bind_callback,
-      ScopedSafeSharedMemory* safe_shared_memory);
-  void PerformAsyncTexSubImage2D(
-      AsyncTexSubImage2DParams tex_params,
-      AsyncMemoryParams mem_params,
-      ScopedSafeSharedMemory* safe_shared_memory);
+  void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params,
+                              AsyncMemoryParams mem_params,
+                              const base::Closure& bind_callback);
+  void PerformAsyncTexSubImage2D(AsyncTexSubImage2DParams tex_params,
+                                 AsyncMemoryParams mem_params);
 
   uint64 id_;
   GLuint texture_id_;
@@ -101,21 +86,14 @@
     const base::Closure& bind_callback) {
   TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage");
   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
 
   shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
       id_,
-      base::Bind(
-          &AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D,
-          AsWeakPtr(),
-          tex_params,
-          mem_params,
-          bind_callback,
-          base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                                 mem_params.shared_memory,
-                                                 mem_params.shm_size)))));
+      base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D,
+                 AsWeakPtr(),
+                 tex_params,
+                 mem_params,
+                 bind_callback)));
 
   transfer_in_progress_ = true;
 }
@@ -125,20 +103,13 @@
     const AsyncMemoryParams& mem_params) {
   TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage");
   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
 
   shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
       id_,
-      base::Bind(
-          &AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D,
-          AsWeakPtr(),
-          tex_params,
-          mem_params,
-          base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                                 mem_params.shared_memory,
-                                                 mem_params.shm_size)))));
+      base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D,
+                 AsWeakPtr(),
+                 tex_params,
+                 mem_params)));
 
   transfer_in_progress_ = true;
 }
@@ -166,13 +137,12 @@
 void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D(
     AsyncTexImage2DParams tex_params,
     AsyncMemoryParams mem_params,
-    const base::Closure& bind_callback,
-    ScopedSafeSharedMemory* safe_shared_memory) {
+    const base::Closure& bind_callback) {
   TRACE_EVENT2("gpu", "PerformAsyncTexImage2D",
                "width", tex_params.width,
                "height", tex_params.height);
 
-  void* data = GetAddress(safe_shared_memory, mem_params);
+  void* data = mem_params.GetDataAddress();
 
   base::TimeTicks begin_time(base::TimeTicks::HighResNow());
   gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
@@ -203,13 +173,12 @@
 
 void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D(
     AsyncTexSubImage2DParams tex_params,
-    AsyncMemoryParams mem_params,
-    ScopedSafeSharedMemory* safe_shared_memory) {
+    AsyncMemoryParams mem_params) {
   TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
                "width", tex_params.width,
                "height", tex_params.height);
 
-  void* data = GetAddress(safe_shared_memory, mem_params);
+  void* data = mem_params.GetDataAddress();
 
   base::TimeTicks begin_time(base::TimeTicks::HighResNow());
   gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
@@ -301,9 +270,6 @@
            base::Bind(
                &PerformNotifyCompletion,
                mem_params,
-               base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                                      mem_params.shared_memory,
-                                                      mem_params.shm_size)),
                make_scoped_refptr(observer))));
 }
 
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
index dcdab1c..e670dc7 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc
@@ -19,7 +19,6 @@
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
 #include "gpu/command_buffer/service/async_pixel_transfer_delegate.h"
-#include "gpu/command_buffer/service/safe_shared_memory_pool.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_surface.h"
@@ -34,12 +33,9 @@
 
 void PerformNotifyCompletion(
     AsyncMemoryParams mem_params,
-    ScopedSafeSharedMemory* safe_shared_memory,
     scoped_refptr<AsyncPixelTransferCompletionObserver> observer) {
   TRACE_EVENT0("gpu", "PerformNotifyCompletion");
-  AsyncMemoryParams safe_mem_params = mem_params;
-  safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
-  observer->DidComplete(safe_mem_params);
+  observer->DidComplete(mem_params);
 }
 
 // TODO(backer): Factor out common thread scheduling logic from the EGL and
@@ -80,16 +76,11 @@
     context_ = NULL;
   }
 
-  SafeSharedMemoryPool* safe_shared_memory_pool() {
-    return &safe_shared_memory_pool_;
-  }
-
  private:
   bool initialized_;
 
   scoped_refptr<gfx::GLSurface> surface_;
   scoped_refptr<gfx::GLContext> context_;
-  SafeSharedMemoryPool safe_shared_memory_pool_;
 
   void InitializeOnTransferThread(gfx::GLContext* parent_context,
                                    base::WaitableEvent* caller_wait) {
@@ -136,10 +127,6 @@
   return g_transfer_thread.Pointer()->message_loop_proxy().get();
 }
 
-SafeSharedMemoryPool* safe_shared_memory_pool() {
-  return g_transfer_thread.Pointer()->safe_shared_memory_pool();
-}
-
 class PendingTask : public base::RefCountedThreadSafe<PendingTask> {
  public:
   explicit PendingTask(const base::Closure& task)
@@ -258,11 +245,6 @@
         this,
         tex_params,
         mem_params,
-        // Duplicate the shared memory so there is no way we can get
-        // a use-after-free of the raw pixels.
-        base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                               mem_params.shared_memory,
-                                               mem_params.shm_size)),
         texture_upload_stats));
     transfer_message_loop_proxy()->PostTask(
         FROM_HERE,
@@ -284,9 +266,6 @@
         this,
         tex_params,
         mem_params,
-        base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                               mem_params.shared_memory,
-                                               mem_params.shm_size)),
         texture_upload_stats));
     transfer_message_loop_proxy()->PostTask(
         FROM_HERE,
@@ -303,7 +282,6 @@
   void PerformAsyncTexImage2D(
       AsyncTexImage2DParams tex_params,
       AsyncMemoryParams mem_params,
-      ScopedSafeSharedMemory* safe_shared_memory,
       scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) {
     TRACE_EVENT2("gpu",
                  "PerformAsyncTexImage",
@@ -317,8 +295,7 @@
     if (texture_upload_stats.get())
       begin_time = base::TimeTicks::HighResNow();
 
-    void* data =
-        AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
+    void* data = mem_params.GetDataAddress();
 
     {
       TRACE_EVENT0("gpu", "glTexImage2D");
@@ -343,7 +320,6 @@
   void PerformAsyncTexSubImage2D(
       AsyncTexSubImage2DParams tex_params,
       AsyncMemoryParams mem_params,
-      ScopedSafeSharedMemory* safe_shared_memory,
       scoped_refptr<AsyncPixelTransferUploadStats> texture_upload_stats) {
     TRACE_EVENT2("gpu",
                  "PerformAsyncTexSubImage2D",
@@ -357,9 +333,7 @@
     if (texture_upload_stats.get())
       begin_time = base::TimeTicks::HighResNow();
 
-    void* data =
-        AsyncPixelTransferDelegate::GetAddress(safe_shared_memory, mem_params);
-
+    void* data = mem_params.GetDataAddress();
     {
       TRACE_EVENT0("gpu", "glTexSubImage2D");
       glTexSubImage2D(GL_TEXTURE_2D,
@@ -467,9 +441,6 @@
     const AsyncTexImage2DParams& tex_params,
     const AsyncMemoryParams& mem_params,
     const base::Closure& bind_callback) {
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
   DCHECK(!state_->TransferIsInProgress());
   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
   DCHECK_EQ(tex_params.level, 0);
@@ -488,9 +459,6 @@
                "width", tex_params.width,
                "height", tex_params.height);
   DCHECK(!state_->TransferIsInProgress());
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
   DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
   DCHECK_EQ(tex_params.level, 0);
 
@@ -539,19 +507,12 @@
 void AsyncPixelTransferManagerShareGroup::AsyncNotifyCompletion(
     const AsyncMemoryParams& mem_params,
     AsyncPixelTransferCompletionObserver* observer) {
-  DCHECK(mem_params.shared_memory);
-  DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
-            mem_params.shm_size);
   // Post a PerformNotifyCompletion task to the upload thread. This task
   // will run after all async transfers are complete.
   transfer_message_loop_proxy()->PostTask(
       FROM_HERE,
       base::Bind(&PerformNotifyCompletion,
                  mem_params,
-                 base::Owned(
-                     new ScopedSafeSharedMemory(safe_shared_memory_pool(),
-                                                mem_params.shared_memory,
-                                                mem_params.shm_size)),
                  make_scoped_refptr(observer)));
 }
 
diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc
index ffe5584..69e3c34 100644
--- a/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc
+++ b/gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc
@@ -46,7 +46,7 @@
     const base::Closure& bind_callback) {
   // Save the define params to return later during deferred
   // binding of the transfer texture.
-  void* data = GetAddress(mem_params);
+  void* data = mem_params.GetDataAddress();
   base::TimeTicks begin_time(base::TimeTicks::HighResNow());
   glTexImage2D(
       tex_params.target,
@@ -68,7 +68,7 @@
 void AsyncPixelTransferDelegateSync::AsyncTexSubImage2D(
     const AsyncTexSubImage2DParams& tex_params,
     const AsyncMemoryParams& mem_params) {
-  void* data = GetAddress(mem_params);
+  void* data = mem_params.GetDataAddress();
   base::TimeTicks begin_time(base::TimeTicks::HighResNow());
   glTexSubImage2D(
       tex_params.target,
diff --git a/gpu/command_buffer/service/cmd_buffer_engine.h b/gpu/command_buffer/service/cmd_buffer_engine.h
index 6aefe82..75e6069 100644
--- a/gpu/command_buffer/service/cmd_buffer_engine.h
+++ b/gpu/command_buffer/service/cmd_buffer_engine.h
@@ -24,7 +24,7 @@
   // Gets the base address and size of a registered shared memory buffer.
   // Parameters:
   //   shm_id: the identifier for the shared memory buffer.
-  virtual Buffer GetSharedMemoryBuffer(int32 shm_id) = 0;
+  virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id) = 0;
 
   // Sets the token value.
   virtual void set_token(int32 token) = 0;
diff --git a/gpu/command_buffer/service/command_buffer_service.cc b/gpu/command_buffer/service/command_buffer_service.cc
index 76a5f51..58b96ac 100644
--- a/gpu/command_buffer/service/command_buffer_service.cc
+++ b/gpu/command_buffer/service/command_buffer_service.cc
@@ -89,9 +89,9 @@
   DCHECK_EQ(-1, ring_buffer_id_);
   DCHECK_EQ(put_offset_, get_offset_);  // Only if it's empty.
   ring_buffer_ = GetTransferBuffer(transfer_buffer_id);
-  DCHECK(ring_buffer_.ptr);
+  DCHECK(ring_buffer_);
   ring_buffer_id_ = transfer_buffer_id;
-  num_entries_ = ring_buffer_.size / sizeof(CommandBufferEntry);
+  num_entries_ = ring_buffer_->size() / sizeof(CommandBufferEntry);
   put_offset_ = 0;
   SetGetOffset(0);
   if (!get_buffer_change_callback_.is_null()) {
@@ -119,20 +119,20 @@
   get_offset_ = get_offset;
 }
 
-Buffer CommandBufferService::CreateTransferBuffer(size_t size,
-                                                  int32* id) {
+scoped_refptr<Buffer> CommandBufferService::CreateTransferBuffer(size_t size,
+                                                                 int32* id) {
   *id = -1;
 
-  SharedMemory buffer;
-  if (!buffer.CreateAnonymous(size))
-    return Buffer();
+  scoped_ptr<SharedMemory> shared_memory(new SharedMemory());
+  if (!shared_memory->CreateAndMapAnonymous(size))
+    return NULL;
 
   static int32 next_id = 1;
   *id = next_id++;
 
-  if (!RegisterTransferBuffer(*id, &buffer, size)) {
+  if (!RegisterTransferBuffer(*id, shared_memory.Pass(), size)) {
     *id = -1;
-    return Buffer();
+    return NULL;
   }
 
   return GetTransferBuffer(*id);
@@ -142,24 +142,23 @@
   transfer_buffer_manager_->DestroyTransferBuffer(id);
   if (id == ring_buffer_id_) {
     ring_buffer_id_ = -1;
-    ring_buffer_ = Buffer();
+    ring_buffer_ = NULL;
     num_entries_ = 0;
     get_offset_ = 0;
     put_offset_ = 0;
   }
 }
 
-Buffer CommandBufferService::GetTransferBuffer(int32 id) {
+scoped_refptr<Buffer> CommandBufferService::GetTransferBuffer(int32 id) {
   return transfer_buffer_manager_->GetTransferBuffer(id);
 }
 
 bool CommandBufferService::RegisterTransferBuffer(
     int32 id,
-    base::SharedMemory* shared_memory,
+    scoped_ptr<base::SharedMemory> shared_memory,
     size_t size) {
-  return transfer_buffer_manager_->RegisterTransferBuffer(id,
-                                                          shared_memory,
-                                                          size);
+  return transfer_buffer_manager_->RegisterTransferBuffer(
+      id, shared_memory.Pass(), size);
 }
 
 void CommandBufferService::SetToken(int32 token) {
diff --git a/gpu/command_buffer/service/command_buffer_service.h b/gpu/command_buffer/service/command_buffer_service.h
index fd28653..15c38dd 100644
--- a/gpu/command_buffer/service/command_buffer_service.h
+++ b/gpu/command_buffer/service/command_buffer_service.h
@@ -33,9 +33,10 @@
   virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE;
   virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE;
+  virtual scoped_refptr<Buffer> CreateTransferBuffer(size_t size,
+                                                     int32* id) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual Buffer GetTransferBuffer(int32 id) OVERRIDE;
+  virtual scoped_refptr<Buffer> GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(error::Error error) OVERRIDE;
   virtual void SetContextLostReason(error::ContextLostReason) OVERRIDE;
@@ -64,12 +65,12 @@
   // to identify it in the command buffer. Callee dups the handle until
   // DestroyTransferBuffer is called.
   bool RegisterTransferBuffer(int32 id,
-                              base::SharedMemory* shared_memory,
+                              scoped_ptr<base::SharedMemory> shared_memory,
                               size_t size);
 
  private:
   int32 ring_buffer_id_;
-  Buffer ring_buffer_;
+  scoped_refptr<Buffer> ring_buffer_;
   scoped_ptr<base::SharedMemory> shared_state_shm_;
   CommandBufferSharedState* shared_state_;
   int32 num_entries_;
diff --git a/gpu/command_buffer/service/common_decoder.cc b/gpu/command_buffer/service/common_decoder.cc
index bd4a919..06cf3a4 100644
--- a/gpu/command_buffer/service/common_decoder.cc
+++ b/gpu/command_buffer/service/common_decoder.cc
@@ -61,20 +61,17 @@
 CommonDecoder::~CommonDecoder() {}
 
 void* CommonDecoder::GetAddressAndCheckSize(unsigned int shm_id,
-                                            unsigned int offset,
-                                            unsigned int size) {
+                                            unsigned int data_offset,
+                                            unsigned int data_size) {
   CHECK(engine_);
-  Buffer buffer = engine_->GetSharedMemoryBuffer(shm_id);
-  if (!buffer.ptr)
+  scoped_refptr<gpu::Buffer> buffer = engine_->GetSharedMemoryBuffer(shm_id);
+  if (!buffer)
     return NULL;
-  unsigned int end = offset + size;
-  if (end > buffer.size || end < offset) {
-    return NULL;
-  }
-  return static_cast<int8*>(buffer.ptr) + offset;
+  return buffer->GetDataAddress(data_offset, data_size);
 }
 
-Buffer CommonDecoder::GetSharedMemoryBuffer(unsigned int shm_id) {
+scoped_refptr<gpu::Buffer> CommonDecoder::GetSharedMemoryBuffer(
+    unsigned int shm_id) {
   return engine_->GetSharedMemoryBuffer(shm_id);
 }
 
diff --git a/gpu/command_buffer/service/common_decoder.h b/gpu/command_buffer/service/common_decoder.h
index 03002c8..2132afb 100644
--- a/gpu/command_buffer/service/common_decoder.h
+++ b/gpu/command_buffer/service/common_decoder.h
@@ -132,7 +132,7 @@
   }
 
   // Get the actual shared memory buffer.
-  Buffer GetSharedMemoryBuffer(unsigned int shm_id);
+  scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(unsigned int shm_id);
 
  protected:
   // Executes a common command.
diff --git a/gpu/command_buffer/service/common_decoder_unittest.cc b/gpu/command_buffer/service/common_decoder_unittest.cc
index d90e34b..5e89a5f 100644
--- a/gpu/command_buffer/service/common_decoder_unittest.cc
+++ b/gpu/command_buffer/service/common_decoder_unittest.cc
@@ -81,26 +81,29 @@
       : CommandBufferEngine(),
         token_(),
         get_offset_(0) {
+    scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+    shared_memory->CreateAndMapAnonymous(kBufferSize);
+    buffer_ = new gpu::Buffer(shared_memory.Pass(), kBufferSize);
   }
 
   // Overridden from CommandBufferEngine.
-  virtual Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE {
-    Buffer buffer;
-    if (IsValidSharedMemoryId(shm_id)) {
-      buffer.ptr = buffer_;
-      buffer.size = kBufferSize;
-    }
-    return buffer;
+  virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id)
+      OVERRIDE {
+    if (IsValidSharedMemoryId(shm_id))
+      return buffer_;
+    return NULL;
   }
 
   template <typename T>
   T GetSharedMemoryAs(uint32 offset) {
     DCHECK_LT(offset, kBufferSize);
-    return reinterpret_cast<T>(&buffer_[offset]);
+    int8* buffer_memory = static_cast<int8*>(buffer_->memory());
+    return reinterpret_cast<T>(&buffer_memory[offset]);
   }
 
   int32 GetSharedMemoryOffset(const void* memory) {
-    ptrdiff_t offset = reinterpret_cast<const int8*>(memory) - &buffer_[0];
+    int8* buffer_memory = static_cast<int8*>(buffer_->memory());
+    ptrdiff_t offset = static_cast<const int8*>(memory) - &buffer_memory[0];
     DCHECK_GE(offset, 0);
     DCHECK_LT(static_cast<size_t>(offset), kBufferSize);
     return static_cast<int32>(offset);
@@ -140,7 +143,7 @@
     return shm_id == kValidShmId || shm_id == kStartValidShmId;
   }
 
-  int8 buffer_[kBufferSize];
+  scoped_refptr<gpu::Buffer> buffer_;
   int32 token_;
   int32 get_offset_;
 };
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc
index 88358ef..f046872 100644
--- a/gpu/command_buffer/service/context_state.cc
+++ b/gpu/command_buffer/service/context_state.cc
@@ -46,6 +46,38 @@
       ? unit.bound_texture_rectangle_arb->service_id() : 0;
 }
 
+GLuint GetServiceId(const TextureUnit& unit, GLuint target) {
+  switch (target) {
+    case GL_TEXTURE_2D:
+      return Get2dServiceId(unit);
+    case GL_TEXTURE_CUBE_MAP:
+      return GetCubeServiceId(unit);
+    case GL_TEXTURE_RECTANGLE_ARB:
+      return GetArbServiceId(unit);
+    case GL_TEXTURE_EXTERNAL_OES:
+      return GetOesServiceId(unit);
+    default:
+      NOTREACHED();
+      return 0;
+  }
+}
+
+bool TargetIsSupported(const FeatureInfo* feature_info, GLuint target) {
+  switch (target) {
+    case GL_TEXTURE_2D:
+      return true;
+    case GL_TEXTURE_CUBE_MAP:
+      return true;
+    case GL_TEXTURE_RECTANGLE_ARB:
+      return feature_info->feature_flags().arb_texture_rectangle;
+    case GL_TEXTURE_EXTERNAL_OES:
+      return feature_info->feature_flags().oes_egl_image_external;
+    default:
+      NOTREACHED();
+      return false;
+  }
+}
+
 }  // anonymous namespace.
 
 TextureUnit::TextureUnit()
@@ -147,6 +179,13 @@
   RestoreActiveTexture();
 }
 
+void ContextState::RestoreActiveTextureUnitBinding(unsigned int target) const {
+  DCHECK_LT(active_texture_unit, texture_units.size());
+  const TextureUnit& texture_unit = texture_units[active_texture_unit];
+  if (TargetIsSupported(feature_info_, target))
+    glBindTexture(target, GetServiceId(texture_unit, target));
+}
+
 void ContextState::RestoreAttribute(GLuint attrib_index) const {
   const VertexAttrib* attrib =
       vertex_attrib_manager->GetVertexAttrib(attrib_index);
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h
index c2479cb..2697e15 100644
--- a/gpu/command_buffer/service/context_state.h
+++ b/gpu/command_buffer/service/context_state.h
@@ -104,6 +104,7 @@
 
   void RestoreActiveTexture() const;
   void RestoreAllTextureUnitBindings(const ContextState* prev_state) const;
+  void RestoreActiveTextureUnitBinding(unsigned int target) const;
   void RestoreAttribute(GLuint index) const;
   void RestoreBufferBindings() const;
   void RestoreGlobalState() const;
diff --git a/gpu/command_buffer/service/gl_state_restorer_impl.cc b/gpu/command_buffer/service/gl_state_restorer_impl.cc
index 710eb2a..5fbd425 100644
--- a/gpu/command_buffer/service/gl_state_restorer_impl.cc
+++ b/gpu/command_buffer/service/gl_state_restorer_impl.cc
@@ -34,6 +34,11 @@
   decoder_->RestoreAllTextureUnitBindings(NULL);
 }
 
+void GLStateRestorerImpl::RestoreActiveTextureUnitBinding(unsigned int target) {
+  DCHECK(decoder_.get());
+  decoder_->RestoreActiveTextureUnitBinding(target);
+}
+
 void GLStateRestorerImpl::RestoreFramebufferBindings() {
   DCHECK(decoder_.get());
   decoder_->RestoreFramebufferBindings();
diff --git a/gpu/command_buffer/service/gl_state_restorer_impl.h b/gpu/command_buffer/service/gl_state_restorer_impl.h
index 29f3746..73534b8 100644
--- a/gpu/command_buffer/service/gl_state_restorer_impl.h
+++ b/gpu/command_buffer/service/gl_state_restorer_impl.h
@@ -27,6 +27,7 @@
    virtual bool IsInitialized() OVERRIDE;
    virtual void RestoreState(const gfx::GLStateRestorer* prev_state) OVERRIDE;
    virtual void RestoreAllTextureUnitBindings() OVERRIDE;
+   virtual void RestoreActiveTextureUnitBinding(unsigned int target) OVERRIDE;
    virtual void RestoreFramebufferBindings() OVERRIDE;
 
  private:
diff --git a/gpu/command_buffer/service/gl_surface_mock.h b/gpu/command_buffer/service/gl_surface_mock.h
index 372a9b3..0652be6 100644
--- a/gpu/command_buffer/service/gl_surface_mock.h
+++ b/gpu/command_buffer/service/gl_surface_mock.h
@@ -20,7 +20,7 @@
   MOCK_METHOD0(IsOffscreen, bool());
   MOCK_METHOD0(SwapBuffers, bool());
   MOCK_METHOD4(PostSubBuffer, bool(int x, int y, int width, int height));
-  MOCK_METHOD0(GetExtensions, std::string());
+  MOCK_METHOD0(SupportsPostSubBuffer, bool());
   MOCK_METHOD0(GetSize, gfx::Size());
   MOCK_METHOD0(GetHandle, void*());
   MOCK_METHOD0(GetBackingFrameBufferObject, unsigned int());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index d6f9fc8..9ca8213 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -581,6 +581,10 @@
       const ContextState* prev_state) const OVERRIDE {
     state_.RestoreAllTextureUnitBindings(prev_state);
   }
+  virtual void RestoreActiveTextureUnitBinding(
+      unsigned int target) const OVERRIDE {
+    state_.RestoreActiveTextureUnitBinding(target);
+  }
   virtual void RestoreAttribute(unsigned index) const OVERRIDE {
     state_.RestoreAttribute(index);
   }
@@ -1702,6 +1706,7 @@
   bool has_robustness_extension_;
   GLenum reset_status_;
   bool reset_by_robustness_extension_;
+  bool supports_post_sub_buffer_;
 
   // These flags are used to override the state of the shared feature_info_
   // member.  Because the same FeatureInfo instance may be shared among many
@@ -2207,6 +2212,7 @@
       has_robustness_extension_(false),
       reset_status_(GL_NO_ERROR),
       reset_by_robustness_extension_(false),
+      supports_post_sub_buffer_(false),
       force_webgl_glsl_validation_(false),
       derivatives_explicitly_enabled_(false),
       frag_depth_explicitly_enabled_(false),
@@ -2567,6 +2573,12 @@
     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
   }
 
+  supports_post_sub_buffer_ = surface->SupportsPostSubBuffer();
+  if (feature_info_->workarounds()
+          .disable_post_sub_buffers_for_onscreen_surfaces &&
+      !surface->IsOffscreen())
+    supports_post_sub_buffer_ = false;
+
   if (feature_info_->workarounds().reverse_point_sprite_coord_origin) {
     glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
   }
@@ -2619,7 +2631,7 @@
   caps.iosurface = true;
 #endif
 
-  caps.post_sub_buffer = surface_->HasExtension("GL_CHROMIUM_post_sub_buffer");
+  caps.post_sub_buffer = supports_post_sub_buffer_;
 
   return caps;
 }
@@ -4165,7 +4177,25 @@
     switch (pname) {
       case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
         *num_written = 1;
+        // Return the GL implementation's preferred format and (see below type)
+        // if we have the GL extension that exposes this. This allows the GPU
+        // client to use the implementation's preferred format for glReadPixels
+        // for optimisation.
+        //
+        // A conflicting extension (GL_ARB_ES2_compatibility) specifies an error
+        // case when requested on integer/floating point buffers but which is
+        // acceptable on GLES2 and with the GL_OES_read_format extension.
+        //
+        // Therefore if an error occurs we swallow the error and use the
+        // internal implementation.
         if (params) {
+          if (context_->HasExtension("GL_OES_read_format")) {
+            ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
+                                               GetErrorState());
+            glGetIntegerv(pname, params);
+            if (glGetError() == GL_NO_ERROR)
+              return true;
+          }
           *params = GLES2Util::GetPreferredGLReadPixelsFormat(
               GetBoundReadFrameBufferInternalFormat());
         }
@@ -4173,6 +4203,13 @@
       case GL_IMPLEMENTATION_COLOR_READ_TYPE:
         *num_written = 1;
         if (params) {
+          if (context_->HasExtension("GL_OES_read_format")) {
+            ScopedGLErrorSuppressor suppressor("GLES2DecoderImpl::GetHelper",
+                                               GetErrorState());
+            glGetIntegerv(pname, params);
+            if (glGetError() == GL_NO_ERROR)
+              return true;
+          }
           *params = GLES2Util::GetPreferredGLReadPixelsType(
               GetBoundReadFrameBufferInternalFormat(),
               GetBoundReadFrameBufferTextureType());
@@ -7222,6 +7259,7 @@
 
 error::Error GLES2DecoderImpl::HandleReadPixels(
     uint32 immediate_data_size, const cmds::ReadPixels& c) {
+  TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleReadPixels");
   error::Error fbo_error = WillAccessBoundFramebufferForRead();
   if (fbo_error != error::kNoError)
     return fbo_error;
@@ -7433,7 +7471,7 @@
 error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
     uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
   TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
-  if (!surface_->HasExtension("GL_CHROMIUM_post_sub_buffer")) {
+  if (!supports_post_sub_buffer_) {
     LOCAL_SET_GL_ERROR(
         GL_INVALID_OPERATION,
         "glPostSubBufferCHROMIUM", "command not supported by surface");
@@ -7627,9 +7665,8 @@
         } else {
           extensions = feature_info_->extensions().c_str();
         }
-        std::string surface_extensions = surface_->GetExtensions();
-        if (!surface_extensions.empty())
-          extensions += " " + surface_extensions;
+        if (supports_post_sub_buffer_)
+          extensions += " GL_CHROMIUM_post_sub_buffer";
         str = extensions.c_str();
       }
       break;
@@ -10381,20 +10418,12 @@
     return error::kNoError;
   }
 
-  // We know the memory/size is safe, so get the real shared memory since
-  // it might need to be duped to prevent use-after-free of the memory.
-  gpu::Buffer buffer = GetSharedMemoryBuffer(c.pixels_shm_id);
-  base::SharedMemory* shared_memory = buffer.shared_memory;
-  uint32 shm_size = buffer.size;
-  uint32 shm_data_offset = c.pixels_shm_offset;
-  uint32 shm_data_size = pixels_size;
-
   // Setup the parameters.
   AsyncTexImage2DParams tex_params = {
       target, level, static_cast<GLenum>(internal_format),
       width, height, border, format, type};
-  AsyncMemoryParams mem_params = {
-      shared_memory, shm_size, shm_data_offset, shm_data_size};
+  AsyncMemoryParams mem_params(
+      GetSharedMemoryBuffer(c.pixels_shm_id), c.pixels_shm_offset, pixels_size);
 
   // Set up the async state if needed, and make the texture
   // immutable so the async state stays valid. The level info
@@ -10471,19 +10500,11 @@
     }
   }
 
-  // We know the memory/size is safe, so get the real shared memory since
-  // it might need to be duped to prevent use-after-free of the memory.
-  gpu::Buffer buffer = GetSharedMemoryBuffer(c.data_shm_id);
-  base::SharedMemory* shared_memory = buffer.shared_memory;
-  uint32 shm_size = buffer.size;
-  uint32 shm_data_offset = c.data_shm_offset;
-  uint32 shm_data_size = data_size;
-
   // Setup the parameters.
   AsyncTexSubImage2DParams tex_params = {target, level, xoffset, yoffset,
                                               width, height, format, type};
-  AsyncMemoryParams mem_params = {shared_memory, shm_size,
-                                       shm_data_offset, shm_data_size};
+  AsyncMemoryParams mem_params(
+      GetSharedMemoryBuffer(c.data_shm_id), c.data_shm_offset, data_size);
   AsyncPixelTransferDelegate* delegate =
       async_pixel_transfer_manager_->GetPixelTransferDelegate(texture_ref);
   if (!delegate) {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.h b/gpu/command_buffer/service/gles2_cmd_decoder.h
index 409ae7b..03a4b54 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.h
@@ -141,6 +141,7 @@
   virtual void RestoreActiveTexture() const = 0;
   virtual void RestoreAllTextureUnitBindings(
       const ContextState* prev_state) const = 0;
+  virtual void RestoreActiveTextureUnitBinding(unsigned int target) const = 0;
   virtual void RestoreAttribute(unsigned index) const = 0;
   virtual void RestoreBufferBindings() const = 0;
   virtual void RestoreFramebufferBindings() const = 0;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
index f22ade0..ff678c9 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_mock.h
@@ -59,6 +59,8 @@
   MOCK_CONST_METHOD0(RestoreActiveTexture, void());
   MOCK_CONST_METHOD1(
       RestoreAllTextureUnitBindings, void(const ContextState* state));
+  MOCK_CONST_METHOD1(
+      RestoreActiveTextureUnitBinding, void(unsigned int target));
   MOCK_CONST_METHOD1(RestoreAttribute, void(unsigned index));
   MOCK_CONST_METHOD0(RestoreBufferBindings, void());
   MOCK_CONST_METHOD0(RestoreFramebufferBindings, void());
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
index 15fd1d1..d2e6e97 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc
@@ -9204,6 +9204,137 @@
                                     GL_LUMINANCE_ALPHA32F_ARB);
 }
 
+TEST_F(GLES2DecoderManualInitTest, ReadFormatExtension) {
+  InitDecoder(
+      "GL_OES_read_format",  // extensions
+      "2.1",   // gl version
+      false,   // has alpha
+      false,   // has depth
+      false,   // has stencil
+      false,   // request alpha
+      false,   // request depth
+      false,   // request stencil
+      true);   // bind generates resource
+
+  EXPECT_CALL(*gl_, GetError())
+      .WillOnce(Return(GL_NO_ERROR))
+      .WillOnce(Return(GL_NO_ERROR))
+      .WillOnce(Return(GL_NO_ERROR))
+      .WillOnce(Return(GL_NO_ERROR))
+      .RetiresOnSaturation();
+  EXPECT_CALL(*gl_, GetError())
+      .Times(6)
+      .RetiresOnSaturation();
+
+  typedef GetIntegerv::Result Result;
+  Result* result = static_cast<Result*>(shared_memory_address_);
+  GetIntegerv cmd;
+  const GLuint kFBOClientTextureId = 4100;
+  const GLuint kFBOServiceTextureId = 4101;
+
+  // Register a texture id.
+  EXPECT_CALL(*gl_, GenTextures(_, _))
+      .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId))
+      .RetiresOnSaturation();
+  GenHelper<GenTexturesImmediate>(kFBOClientTextureId);
+
+  // Setup "render to" texture.
+  DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId);
+  DoTexImage2D(
+      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
+  DoBindFramebuffer(
+      GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
+  DoFramebufferTexture2D(
+      GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+      kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR);
+
+  result->size = 0;
+  EXPECT_CALL(*gl_, GetIntegerv(_, _))
+      .Times(1)
+      .RetiresOnSaturation();
+  cmd.Init(
+      GL_IMPLEMENTATION_COLOR_READ_FORMAT,
+      shared_memory_id_, shared_memory_offset_);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(1, result->GetNumResults());
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+  result->size = 0;
+  EXPECT_CALL(*gl_, GetIntegerv(_, _))
+      .Times(1)
+      .RetiresOnSaturation();
+  cmd.Init(
+      GL_IMPLEMENTATION_COLOR_READ_TYPE,
+      shared_memory_id_, shared_memory_offset_);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(1, result->GetNumResults());
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_F(GLES2DecoderManualInitTest, NoReadFormatExtension) {
+  InitDecoder(
+      "",  // extensions
+      "2.1",   // gl version
+      false,   // has alpha
+      false,   // has depth
+      false,   // has stencil
+      false,   // request alpha
+      false,   // request depth
+      false,   // request stencil
+      true);   // bind generates resource
+
+  EXPECT_CALL(*gl_, GetError())
+      .WillOnce(Return(GL_NO_ERROR))
+      .WillOnce(Return(GL_NO_ERROR))
+      .WillOnce(Return(GL_NO_ERROR))
+      .WillOnce(Return(GL_NO_ERROR))
+      .RetiresOnSaturation();
+
+  typedef GetIntegerv::Result Result;
+  Result* result = static_cast<Result*>(shared_memory_address_);
+  GetIntegerv cmd;
+  const GLuint kFBOClientTextureId = 4100;
+  const GLuint kFBOServiceTextureId = 4101;
+
+  // Register a texture id.
+  EXPECT_CALL(*gl_, GenTextures(_, _))
+      .WillOnce(SetArgumentPointee<1>(kFBOServiceTextureId))
+      .RetiresOnSaturation();
+  GenHelper<GenTexturesImmediate>(kFBOClientTextureId);
+
+  // Setup "render to" texture.
+  DoBindTexture(GL_TEXTURE_2D, kFBOClientTextureId, kFBOServiceTextureId);
+  DoTexImage2D(
+      GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0, 0);
+  DoBindFramebuffer(
+      GL_FRAMEBUFFER, client_framebuffer_id_, kServiceFramebufferId);
+  DoFramebufferTexture2D(
+      GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+      kFBOClientTextureId, kFBOServiceTextureId, 0, GL_NO_ERROR);
+
+  result->size = 0;
+  EXPECT_CALL(*gl_, GetIntegerv(_, _))
+      .Times(0)
+      .RetiresOnSaturation();
+  cmd.Init(
+      GL_IMPLEMENTATION_COLOR_READ_FORMAT,
+      shared_memory_id_, shared_memory_offset_);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(1, result->GetNumResults());
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+
+  result->size = 0;
+  EXPECT_CALL(*gl_, GetIntegerv(_, _))
+      .Times(0)
+      .RetiresOnSaturation();
+  cmd.Init(
+      GL_IMPLEMENTATION_COLOR_READ_TYPE,
+      shared_memory_id_, shared_memory_offset_);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(1, result->GetNumResults());
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
 // TODO(gman): Complete this test.
 // TEST_F(GLES2DecoderTest, CompressedTexImage2DGLError) {
 // }
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
index 0c6d16b..93f3faf 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2.cc
@@ -327,6 +327,21 @@
 };
 
 template <>
+void GLES2DecoderTestBase::SpecializedSetup<cmds::UseProgram, 0>(
+    bool /* valid */) {
+  // Needs the same setup as LinkProgram.
+  SpecializedSetup<cmds::LinkProgram, 0>(false);
+
+  EXPECT_CALL(*gl_, LinkProgram(kServiceProgramId))
+      .Times(1)
+      .RetiresOnSaturation();
+
+  cmds::LinkProgram link_cmd;
+  link_cmd.Init(client_program_id_);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd));
+};
+
+template <>
 void GLES2DecoderTestBase::SpecializedSetup<cmds::ValidateProgram, 0>(
     bool /* valid */) {
   // Needs the same setup as LinkProgram.
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
index bed0dbd..5e022bf 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h
@@ -1338,7 +1338,24 @@
   EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
   EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
 }
-// TODO(gman): UseProgram
+
+TEST_F(GLES2DecoderTest2, UseProgramValidArgs) {
+  EXPECT_CALL(*gl_, UseProgram(kServiceProgramId));
+  SpecializedSetup<cmds::UseProgram, 0>(true);
+  cmds::UseProgram cmd;
+  cmd.Init(client_program_id_);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_NO_ERROR, GetGLError());
+}
+
+TEST_F(GLES2DecoderTest2, UseProgramInvalidArgs0_0) {
+  EXPECT_CALL(*gl_, UseProgram(_)).Times(0);
+  SpecializedSetup<cmds::UseProgram, 0>(false);
+  cmds::UseProgram cmd;
+  cmd.Init(kInvalidClientId);
+  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
+  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
+}
 
 TEST_F(GLES2DecoderTest2, ValidateProgramValidArgs) {
   EXPECT_CALL(*gl_, ValidateProgram(kServiceProgramId));
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 8cf0421..1acdf35 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -284,12 +284,13 @@
 #endif
 
   engine_.reset(new StrictMock<MockCommandBufferEngine>());
-  gpu::Buffer buffer = engine_->GetSharedMemoryBuffer(kSharedMemoryId);
+  scoped_refptr<gpu::Buffer> buffer =
+      engine_->GetSharedMemoryBuffer(kSharedMemoryId);
   shared_memory_offset_ = kSharedMemoryOffset;
-  shared_memory_address_ = reinterpret_cast<int8*>(buffer.ptr) +
-      shared_memory_offset_;
+  shared_memory_address_ =
+      reinterpret_cast<int8*>(buffer->memory()) + shared_memory_offset_;
   shared_memory_id_ = kSharedMemoryId;
-  shared_memory_base_ = buffer.ptr;
+  shared_memory_base_ = buffer->memory();
 
   int32 attributes[] = {
     EGL_ALPHA_SIZE, request_alpha ? 8 : 0,
@@ -1419,18 +1420,18 @@
 
 GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::
 MockCommandBufferEngine() {
-  shm_.reset(new base::SharedMemory());
-  shm_->CreateAndMapAnonymous(kSharedBufferSize);
-  valid_buffer_.size = kSharedBufferSize;
-  valid_buffer_.shared_memory = shm_.get();
-  valid_buffer_.ptr = shm_->memory();
+
+  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+  shm->CreateAndMapAnonymous(kSharedBufferSize);
+  valid_buffer_ = new gpu::Buffer(shm.Pass(), kSharedBufferSize);
+
   ClearSharedMemory();
 }
 
 GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::
 ~MockCommandBufferEngine() {}
 
-gpu::Buffer
+scoped_refptr<gpu::Buffer>
 GLES2DecoderWithShaderTestBase::MockCommandBufferEngine::GetSharedMemoryBuffer(
     int32 shm_id) {
   return shm_id == kSharedMemoryId ? valid_buffer_ : invalid_buffer_;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index 4bd06cd..5ceb445 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -519,10 +519,11 @@
 
     virtual ~MockCommandBufferEngine();
 
-    virtual gpu::Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE;
+    virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id)
+        OVERRIDE;
 
     void ClearSharedMemory() {
-      memset(shm_->memory(), kInitialMemoryValue, kSharedBufferSize);
+      memset(valid_buffer_->memory(), kInitialMemoryValue, kSharedBufferSize);
     }
 
     virtual void set_token(int32 token) OVERRIDE;
@@ -536,9 +537,8 @@
     virtual int32 GetGetOffset() OVERRIDE;
 
    private:
-    scoped_ptr<base::SharedMemory> shm_;
-    gpu::Buffer valid_buffer_;
-    gpu::Buffer invalid_buffer_;
+    scoped_refptr<gpu::Buffer> valid_buffer_;
+    scoped_refptr<gpu::Buffer> invalid_buffer_;
   };
 
   void AddExpectationsForVertexAttribManager();
diff --git a/gpu/command_buffer/service/gpu_scheduler.cc b/gpu/command_buffer/service/gpu_scheduler.cc
index d9457dc..bce2fdd 100644
--- a/gpu/command_buffer/service/gpu_scheduler.cc
+++ b/gpu/command_buffer/service/gpu_scheduler.cc
@@ -181,7 +181,7 @@
   scheduling_changed_callback_ = callback;
 }
 
-Buffer GpuScheduler::GetSharedMemoryBuffer(int32 shm_id) {
+scoped_refptr<Buffer> GpuScheduler::GetSharedMemoryBuffer(int32 shm_id) {
   return command_buffer_->GetTransferBuffer(shm_id);
 }
 
@@ -190,8 +190,9 @@
 }
 
 bool GpuScheduler::SetGetBuffer(int32 transfer_buffer_id) {
-  Buffer ring_buffer = command_buffer_->GetTransferBuffer(transfer_buffer_id);
-  if (!ring_buffer.ptr) {
+  scoped_refptr<Buffer> ring_buffer =
+      command_buffer_->GetTransferBuffer(transfer_buffer_id);
+  if (!ring_buffer) {
     return false;
   }
 
@@ -200,10 +201,7 @@
   }
 
   parser_->SetBuffer(
-      ring_buffer.ptr,
-      ring_buffer.size,
-      0,
-      ring_buffer.size);
+      ring_buffer->memory(), ring_buffer->size(), 0, ring_buffer->size());
 
   SetGetOffset(0);
   return true;
diff --git a/gpu/command_buffer/service/gpu_scheduler.h b/gpu/command_buffer/service/gpu_scheduler.h
index 8fb791c..22ab07f 100644
--- a/gpu/command_buffer/service/gpu_scheduler.h
+++ b/gpu/command_buffer/service/gpu_scheduler.h
@@ -83,7 +83,7 @@
   void SetSchedulingChangedCallback(const SchedulingChangedCallback& callback);
 
   // Implementation of CommandBufferEngine.
-  virtual Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE;
+  virtual scoped_refptr<Buffer> GetSharedMemoryBuffer(int32 shm_id) OVERRIDE;
   virtual void set_token(int32 token) OVERRIDE;
   virtual bool SetGetBuffer(int32 transfer_buffer_id) OVERRIDE;
   virtual bool SetGetOffset(int32 offset) OVERRIDE;
diff --git a/gpu/command_buffer/service/gpu_scheduler_unittest.cc b/gpu/command_buffer/service/gpu_scheduler_unittest.cc
index 84e40c7..7a663d0 100644
--- a/gpu/command_buffer/service/gpu_scheduler_unittest.cc
+++ b/gpu/command_buffer/service/gpu_scheduler_unittest.cc
@@ -33,11 +33,11 @@
   static const int32 kTransferBufferId = 123;
 
   virtual void SetUp() {
-    shared_memory_.reset(new ::base::SharedMemory);
-    shared_memory_->CreateAndMapAnonymous(kRingBufferSize);
-    buffer_ = static_cast<int32*>(shared_memory_->memory());
-    shared_memory_buffer_.ptr = buffer_;
-    shared_memory_buffer_.size = kRingBufferSize;
+    scoped_ptr<base::SharedMemory> shared_memory(new ::base::SharedMemory);
+    shared_memory->CreateAndMapAnonymous(kRingBufferSize);
+    buffer_ = static_cast<int32*>(shared_memory->memory());
+    shared_memory_buffer_ =
+        new gpu::Buffer(shared_memory.Pass(), kRingBufferSize);
     memset(buffer_, 0, kRingBufferSize);
 
     command_buffer_.reset(new MockCommandBuffer);
@@ -72,8 +72,7 @@
 #endif
   base::MessageLoop message_loop;
   scoped_ptr<MockCommandBuffer> command_buffer_;
-  scoped_ptr<base::SharedMemory> shared_memory_;
-  Buffer shared_memory_buffer_;
+  scoped_refptr<Buffer> shared_memory_buffer_;
   int32* buffer_;
   scoped_ptr<gles2::MockGLES2Decoder> decoder_;
   scoped_ptr<GpuScheduler> scheduler_;
@@ -196,7 +195,7 @@
   EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
     .WillOnce(Return(shared_memory_buffer_));
 
-  EXPECT_EQ(&buffer_[0], scheduler_->GetSharedMemoryBuffer(7).ptr);
+  EXPECT_EQ(&buffer_[0], scheduler_->GetSharedMemoryBuffer(7)->memory());
 }
 
 ACTION_P2(SetPointee, address, value) {
@@ -207,7 +206,7 @@
   EXPECT_CALL(*command_buffer_.get(), GetTransferBuffer(7))
     .WillOnce(Return(shared_memory_buffer_));
 
-  EXPECT_EQ(kRingBufferSize, scheduler_->GetSharedMemoryBuffer(7).size);
+  EXPECT_EQ(kRingBufferSize, scheduler_->GetSharedMemoryBuffer(7)->size());
 }
 
 TEST_F(GpuSchedulerTest, SetTokenForwardsToCommandBuffer) {
diff --git a/gpu/command_buffer/service/in_process_command_buffer.cc b/gpu/command_buffer/service/in_process_command_buffer.cc
index 3e2b1fb..97ec15e 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.cc
+++ b/gpu/command_buffer/service/in_process_command_buffer.cc
@@ -570,8 +570,8 @@
   }
 }
 
-gpu::Buffer InProcessCommandBuffer::CreateTransferBuffer(size_t size,
-                                                         int32* id) {
+scoped_refptr<Buffer> InProcessCommandBuffer::CreateTransferBuffer(size_t size,
+                                                                   int32* id) {
   CheckSequencedThread();
   base::AutoLock lock(command_buffer_lock_);
   return command_buffer_->CreateTransferBuffer(size, id);
@@ -586,9 +586,9 @@
   QueueTask(task);
 }
 
-gpu::Buffer InProcessCommandBuffer::GetTransferBuffer(int32 id) {
+scoped_refptr<gpu::Buffer> InProcessCommandBuffer::GetTransferBuffer(int32 id) {
   NOTREACHED();
-  return gpu::Buffer();
+  return NULL;
 }
 
 gpu::Capabilities InProcessCommandBuffer::GetCapabilities() {
diff --git a/gpu/command_buffer/service/in_process_command_buffer.h b/gpu/command_buffer/service/in_process_command_buffer.h
index f42e19e..4b9f54a 100644
--- a/gpu/command_buffer/service/in_process_command_buffer.h
+++ b/gpu/command_buffer/service/in_process_command_buffer.h
@@ -88,9 +88,10 @@
   virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE;
   virtual void SetGetBuffer(int32 shm_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+                                                          int32* id) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(gpu::error::Error error) OVERRIDE;
   virtual void SetContextLostReason(
diff --git a/gpu/command_buffer/service/mailbox_manager_unittest.cc b/gpu/command_buffer/service/mailbox_manager_unittest.cc
index 13005e6..ae871f9 100644
--- a/gpu/command_buffer/service/mailbox_manager_unittest.cc
+++ b/gpu/command_buffer/service/mailbox_manager_unittest.cc
@@ -8,9 +8,7 @@
 #include "gpu/command_buffer/service/mailbox_synchronizer.h"
 #include "gpu/command_buffer/service/texture_manager.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gl/gl_context_stub.h"
 #include "ui/gl/gl_mock.h"
-#include "ui/gl/gl_surface_stub.h"
 
 namespace gpu {
 namespace gles2 {
@@ -190,9 +188,6 @@
     manager2_ = new MailboxManager;
     gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
     ::gfx::MockGLInterface::SetGLInterface(gl_.get());
-    context_ = new gfx::GLContextStub();
-    surface_ = new gfx::GLSurfaceStub();
-    context_->MakeCurrent(surface_);
   }
 
   Texture* DefineTexture() {
@@ -254,15 +249,12 @@
   virtual void TearDown() {
     MailboxManagerTest::TearDown();
     MailboxSynchronizer::Terminate();
-    context_->ReleaseCurrent(NULL);
     ::gfx::MockGLInterface::SetGLInterface(NULL);
     gl_.reset();
   }
 
   scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
   scoped_refptr<MailboxManager> manager2_;
-  scoped_refptr<gfx::GLContext> context_;
-  scoped_refptr<gfx::GLSurface> surface_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MailboxManagerSyncTest);
@@ -291,6 +283,7 @@
   EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
 
   // Synchronize
+  EXPECT_CALL(*gl_, Flush()).Times(1);
   manager_->PushTextureUpdates();
   manager2_->PullTextureUpdates();
 
@@ -312,6 +305,7 @@
   EXPECT_EQ(texture, manager_->ConsumeTexture(GL_TEXTURE_2D, name));
 
   // Synchronize
+  EXPECT_CALL(*gl_, Flush()).Times(1);
   manager_->PushTextureUpdates();
   manager2_->PullTextureUpdates();
 
@@ -340,6 +334,7 @@
   EXPECT_TRUE(texture->GetLevelImage(GL_TEXTURE_2D, 0) == NULL);
 
   // Synchronize again
+  EXPECT_CALL(*gl_, Flush()).Times(1);
   manager_->PushTextureUpdates();
   SetupUpdateTexParamExpectations(
       kNewTextureId, GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT);
@@ -401,6 +396,7 @@
   manager2_->ProduceTexture(GL_TEXTURE_2D, name2, texture2);
 
   // Make visible.
+  EXPECT_CALL(*gl_, Flush()).Times(2);
   manager_->PushTextureUpdates();
   manager2_->PushTextureUpdates();
 
@@ -439,6 +435,7 @@
   Mock::VerifyAndClearExpectations(gl_.get());
 
   // Synchronize in both directions
+  EXPECT_CALL(*gl_, Flush()).Times(2);
   manager_->PushTextureUpdates();
   manager2_->PushTextureUpdates();
   // manager1 should see the change to texture2 mag_filter being applied.
diff --git a/gpu/command_buffer/service/mailbox_synchronizer.cc b/gpu/command_buffer/service/mailbox_synchronizer.cc
index d25368a..0503fb1 100644
--- a/gpu/command_buffer/service/mailbox_synchronizer.cc
+++ b/gpu/command_buffer/service/mailbox_synchronizer.cc
@@ -174,6 +174,8 @@
       textures_.insert(std::make_pair(texture, TextureVersion(group)));
     }
   }
+  // Make sure all write fences are flushed.
+  glFlush();
 }
 
 void MailboxSynchronizer::UpdateTextureLocked(Texture* texture,
diff --git a/gpu/command_buffer/service/query_manager.cc b/gpu/command_buffer/service/query_manager.cc
index 94f31fa..9f1d3a7 100644
--- a/gpu/command_buffer/service/query_manager.cc
+++ b/gpu/command_buffer/service/query_manager.cc
@@ -36,12 +36,9 @@
   virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
     base::AutoLock locked(lock_);
     if (!cancelled_) {
-      DCHECK(mem_params.shared_memory);
-      DCHECK(mem_params.shared_memory->memory());
-      void* data = static_cast<int8*>(mem_params.shared_memory->memory()) +
-                   mem_params.shm_data_offset;
+      DCHECK(mem_params.buffer());
+      void* data = mem_params.GetDataAddress();
       QuerySync* sync = static_cast<QuerySync*>(data);
-
       base::subtle::Release_Store(&sync->process_count, submit_count_);
     }
   }
@@ -86,19 +83,14 @@
 
 bool AsyncPixelTransfersCompletedQuery::End(
     base::subtle::Atomic32 submit_count) {
-  AsyncMemoryParams mem_params;
   // Get the real shared memory since it might need to be duped to prevent
   // use-after-free of the memory.
-  Buffer buffer = manager()->decoder()->GetSharedMemoryBuffer(shm_id());
-  if (!buffer.shared_memory)
+  scoped_refptr<Buffer> buffer =
+      manager()->decoder()->GetSharedMemoryBuffer(shm_id());
+  if (!buffer)
     return false;
-  mem_params.shared_memory = buffer.shared_memory;
-  mem_params.shm_size = buffer.size;
-  mem_params.shm_data_offset = shm_offset();
-  mem_params.shm_data_size = sizeof(QuerySync);
-  base::CheckedNumeric<uint32> end = mem_params.shm_data_offset;
-  end += mem_params.shm_data_size;
-  if (!end.IsValid() || end.ValueOrDie() > mem_params.shm_size)
+  AsyncMemoryParams mem_params(buffer, shm_offset(), sizeof(QuerySync));
+  if (!mem_params.GetDataAddress())
     return false;
 
   observer_ = new AsyncPixelTransferCompletionObserverImpl(submit_count);
diff --git a/gpu/command_buffer/service/query_manager_unittest.cc b/gpu/command_buffer/service/query_manager_unittest.cc
index 110d3fb..b5f6609 100644
--- a/gpu/command_buffer/service/query_manager_unittest.cc
+++ b/gpu/command_buffer/service/query_manager_unittest.cc
@@ -91,21 +91,23 @@
   class MockCommandBufferEngine : public CommandBufferEngine {
    public:
     MockCommandBufferEngine() {
-      data_.reset(new int8[kSharedBufferSize]);
+      scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+      shared_memory->CreateAndMapAnonymous(kSharedBufferSize);
+      valid_buffer_ = new gpu::Buffer(shared_memory.Pass(), kSharedBufferSize);
+      data_ = static_cast<uint8*>(valid_buffer_->memory());
       ClearSharedMemory();
-      valid_buffer_.ptr = data_.get();
-      valid_buffer_.size = kSharedBufferSize;
     }
 
     virtual ~MockCommandBufferEngine() {
     }
 
-    virtual gpu::Buffer GetSharedMemoryBuffer(int32 shm_id) OVERRIDE {
+    virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id)
+        OVERRIDE {
       return shm_id == kSharedMemoryId ? valid_buffer_ : invalid_buffer_;
     }
 
     void ClearSharedMemory() {
-      memset(data_.get(), kInitialMemoryValue, kSharedBufferSize);
+      memset(data_, kInitialMemoryValue, kSharedBufferSize);
     }
 
     virtual void set_token(int32 token) OVERRIDE {
@@ -130,9 +132,9 @@
     }
 
    private:
-    scoped_ptr<int8[]> data_;
-    gpu::Buffer valid_buffer_;
-    gpu::Buffer invalid_buffer_;
+    uint8* data_;
+    scoped_refptr<gpu::Buffer> valid_buffer_;
+    scoped_refptr<gpu::Buffer> invalid_buffer_;
   };
 
   scoped_ptr<MockCommandBufferEngine> engine_;
diff --git a/gpu/command_buffer/service/safe_shared_memory_pool.cc b/gpu/command_buffer/service/safe_shared_memory_pool.cc
deleted file mode 100644
index 9ba5390..0000000
--- a/gpu/command_buffer/service/safe_shared_memory_pool.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gpu/command_buffer/service/safe_shared_memory_pool.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/process/process_handle.h"
-#include "build/build_config.h"
-
-using base::SharedMemory;
-using base::SharedMemoryHandle;
-
-namespace gpu {
-
-ScopedSafeSharedMemory::ScopedSafeSharedMemory(SafeSharedMemoryPool* pool,
-                                               base::SharedMemory* memory,
-                                               size_t shm_size) {
-  DCHECK(pool);
-  DCHECK(memory);
-  DCHECK(memory->memory());
-  pool_ = pool;
-  original_handle_ = memory->handle();
-  safe_shared_memory_ = pool->AcquireSafeSharedMemory(memory, shm_size);
-  CHECK(safe_shared_memory_);
-}
-
-ScopedSafeSharedMemory::~ScopedSafeSharedMemory() {
-  // Release the handle. The pool will delete the SharedMemory
-  // object when it is no longer referenced.
-  pool_->ReleaseSafeSharedMemory(original_handle_);
-}
-
-base::SharedMemory* ScopedSafeSharedMemory::shared_memory() {
-  return safe_shared_memory_;
-}
-
-SafeSharedMemoryPool::SafeSharedMemoryPool()
-    : handles_acquired_(0),
-      handles_consumed_(0),
-      address_space_consumed_(0),
-      max_handles_acquired_(0),
-      max_handles_consumed_(0),
-      max_address_space_consumed_(0) {
-}
-
-SafeSharedMemoryPool::~SafeSharedMemoryPool() {
-}
-
-base::SharedMemory* SafeSharedMemoryPool::
-    AcquireSafeSharedMemory(base::SharedMemory* shared_memory,
-                            size_t shm_size) {
-  DCHECK(shared_memory);
-  DCHECK(shared_memory->memory());
-  base::AutoLock scoped_lock(lock_);
-
-  // Adjust stats.
-  handles_acquired_++;
-  max_handles_acquired_ = std::max(max_handles_acquired_,
-                                   handles_acquired_);
-
-  MemoryMap::iterator it = memory_.find(shared_memory->handle());
-  // If we don't already have it, duplicated it.
-  if (it == memory_.end()) {
-    // Duplicate a new shared memory and track it.
-    TrackedMemory tracker;
-    tracker.safe_shared_memory = DuplicateSharedMemory(shared_memory, shm_size);
-    tracker.reference_count = 1;
-    tracker.shm_size = shm_size;
-    memory_[shared_memory->handle()] = tracker;
-
-    // Adjust stats.
-    handles_consumed_++;
-    address_space_consumed_ += shm_size;
-    max_handles_consumed_ = std::max(max_handles_consumed_,
-                                         handles_consumed_);
-    max_address_space_consumed_ = std::max(max_address_space_consumed_,
-                                               address_space_consumed_);
-    return tracker.safe_shared_memory;
-  }
-
-  // Otherwise, add a reference and return the existing one.
-  DCHECK(it->second.reference_count);
-  DCHECK(it->second.safe_shared_memory);
-  DCHECK(it->second.safe_shared_memory->memory());
-  it->second.reference_count++;
-  return it->second.safe_shared_memory;
-}
-
-void SafeSharedMemoryPool::
-    ReleaseSafeSharedMemory(const base::SharedMemoryHandle& handle) {
-  base::AutoLock scoped_lock(lock_);
-
-  // Adjust stats.
-  DCHECK_GT(handles_acquired_, 0);
-  handles_acquired_--;
-
-  MemoryMap::iterator it = memory_.find(handle);
-  CHECK(it != memory_.end());
-  CHECK(it->second.reference_count);
-  CHECK(it->second.safe_shared_memory);
-  if (--it->second.reference_count == 0) {
-    // Adjust stats.
-    DCHECK_GT(handles_consumed_, 0);
-    handles_consumed_--;
-    DCHECK_LE(it->second.shm_size, address_space_consumed_);
-    address_space_consumed_ -= it->second.shm_size;
-    // Delete the safe memory and remove it.
-    delete it->second.safe_shared_memory;
-    memory_.erase(it);
-  }
-}
-
-SharedMemory* SafeSharedMemoryPool::DuplicateSharedMemory(
-    SharedMemory* shared_memory, size_t size) {
-  // Duplicate the handle.
-  SharedMemoryHandle duped_shared_memory_handle;
-  if (!shared_memory->ShareToProcess(
-      base::GetCurrentProcessHandle(),
-      &duped_shared_memory_handle)) {
-    PLOG(ERROR) << "Failed SharedMemory::ShareToProcess";
-    LOG(ERROR) << "Total handles acquired " << handles_acquired_;
-    LOG(ERROR) << "Total handles open " << handles_consumed_;
-    LOG(ERROR) << "Total address space " << address_space_consumed_;
-    LOG(ERROR) << "Max handles acquired " << max_handles_acquired_;
-    LOG(ERROR) << "Max handles open " << max_handles_consumed_;
-    LOG(ERROR) << "Max address space " << max_address_space_consumed_;
-    CHECK(false); // Diagnosing a crash.
-    return NULL;
-  }
-  scoped_ptr<SharedMemory> duped_shared_memory(
-      new SharedMemory(duped_shared_memory_handle, false));
-  // Map the shared memory into this process. This validates the size.
-  if (!duped_shared_memory->Map(size)) {
-    PLOG(ERROR) << "Failed SharedMemory::Map(" << size << ")";
-    LOG(ERROR) << "Total handles acquired " << handles_acquired_;
-    LOG(ERROR) << "Total handles open " << handles_consumed_;
-    LOG(ERROR) << "Total address space " << address_space_consumed_;
-    LOG(ERROR) << "Max handles acquired " << max_handles_acquired_;
-    LOG(ERROR) << "Max handles open " << max_handles_consumed_;
-    LOG(ERROR) << "Max address space " << max_address_space_consumed_;
-    CHECK(false); // Diagnosing a crash.
-    return NULL;
-  }
-  return duped_shared_memory.release();
-}
-
-}  // namespace gpu
diff --git a/gpu/command_buffer/service/safe_shared_memory_pool.h b/gpu/command_buffer/service/safe_shared_memory_pool.h
deleted file mode 100644
index fed17ff..0000000
--- a/gpu/command_buffer/service/safe_shared_memory_pool.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_
-#define GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_
-
-#include <map>
-
-#include "base/basictypes.h"
-#include "base/memory/shared_memory.h"
-#include "base/synchronization/lock.h"
-#include "build/build_config.h"
-
-namespace gpu {
-class SafeSharedMemoryPool;
-
-// These classes exist to help protect against deletion of shared
-// memory that is being used on a worker thread. It's mainly a
-// security measure to prevent use-after-free in the browser, due
-// to a misbehaving client. That said, this should be removed
-// in favor of higher-level reference counting of an appropriate
-// opaque 'memory blob' data-structure.
-
-class ScopedSafeSharedMemory {
- public:
-  base::SharedMemory* shared_memory();
-  ScopedSafeSharedMemory(SafeSharedMemoryPool* pool,
-                         base::SharedMemory* memory,
-                         size_t shm_size);
-  ~ScopedSafeSharedMemory();
- private:
-  base::SharedMemory* safe_shared_memory_;
-  base::SharedMemoryHandle original_handle_;
-  SafeSharedMemoryPool* pool_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedSafeSharedMemory);
-};
-
-class SafeSharedMemoryPool {
- public:
-  SafeSharedMemoryPool();
-  virtual ~SafeSharedMemoryPool();
-
- private:
-  friend class ScopedSafeSharedMemory;
-
-  // Acquires and release shared memory. The acquired shared memory
-  // is guaranteed to live until it is released.
-  base::SharedMemory* AcquireSafeSharedMemory(base::SharedMemory*, size_t size);
-  void ReleaseSafeSharedMemory(const base::SharedMemoryHandle&);
-
-  // Utility function to duplicate shared memory.
-  base::SharedMemory* DuplicateSharedMemory(base::SharedMemory*, size_t size);
-
-  // Track all SharedMemory's that we have already duplicated.
-  struct TrackedMemory {
-    base::SharedMemory* safe_shared_memory;
-    size_t shm_size;
-    int reference_count;
-  };
-
-  typedef std::map<base::SharedMemoryHandle, TrackedMemory> MemoryMap;
-  MemoryMap memory_;
-
-  // Track usage to diagnose crashes.
-  int handles_acquired_;
-  int handles_consumed_;
-  size_t address_space_consumed_;
-  int max_handles_acquired_;
-  int max_handles_consumed_;
-  size_t max_address_space_consumed_;
-
-  base::Lock lock_;
-
-  DISALLOW_COPY_AND_ASSIGN(SafeSharedMemoryPool);
-};
-
-}  // namespace gfx
-
-#endif  // GPU_COMMAND_BUFFER_SERVICE_SAFE_SHARED_MEMORY_POOL_H_
-
diff --git a/gpu/command_buffer/service/texture_definition.cc b/gpu/command_buffer/service/texture_definition.cc
index 9b31dac..462131f 100644
--- a/gpu/command_buffer/service/texture_definition.cc
+++ b/gpu/command_buffer/service/texture_definition.cc
@@ -278,8 +278,12 @@
 
 void NativeImageBuffer::DidWrite(gfx::GLImage* client) {
   base::AutoLock lock(lock_);
-  // Sharing semantics require the client to flush in order to make changes
-  // visible to other clients.
+  // TODO(sievers): crbug.com/352419
+  // This is super-risky. We need to somehow find out about when the current
+  // context gets flushed, so that we will only ever wait on the write fence
+  // (esp. from another context) if it was flushed and is guaranteed to clear.
+  // On the other hand, proactively flushing here is not feasible in terms
+  // of perf when there are multiple draw calls per frame.
   write_fence_.reset(gfx::GLFence::CreateWithoutFlush());
   write_client_ = client;
   for (std::list<ClientInfo>::iterator it = client_infos_.begin();
diff --git a/gpu/command_buffer/service/transfer_buffer_manager.cc b/gpu/command_buffer/service/transfer_buffer_manager.cc
index 51484e3..7f81115 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager.cc
+++ b/gpu/command_buffer/service/transfer_buffer_manager.cc
@@ -27,9 +27,8 @@
 TransferBufferManager::~TransferBufferManager() {
   while (!registered_buffers_.empty()) {
     BufferMap::iterator it = registered_buffers_.begin();
-    DCHECK(shared_memory_bytes_allocated_ >= it->second.size);
-    shared_memory_bytes_allocated_ -= it->second.size;
-    delete it->second.shared_memory;
+    DCHECK(shared_memory_bytes_allocated_ >= it->second->size());
+    shared_memory_bytes_allocated_ -= it->second->size();
     registered_buffers_.erase(it);
   }
   DCHECK(!shared_memory_bytes_allocated_);
@@ -41,7 +40,7 @@
 
 bool TransferBufferManager::RegisterTransferBuffer(
     int32 id,
-    base::SharedMemory* shared_memory,
+    scoped_ptr<base::SharedMemory> shared_memory,
     size_t size) {
   if (id <= 0) {
     DVLOG(0) << "Cannot register transfer buffer with non-positive ID.";
@@ -54,30 +53,11 @@
     return false;
   }
 
-  // Duplicate the handle.
-  base::SharedMemoryHandle duped_shared_memory_handle;
-  if (!shared_memory->ShareToProcess(base::GetCurrentProcessHandle(),
-                                     &duped_shared_memory_handle)) {
-    DVLOG(0) << "Failed to duplicate shared memory handle.";
-    return false;
-  }
-  scoped_ptr<SharedMemory> duped_shared_memory(
-      new SharedMemory(duped_shared_memory_handle, false));
-
-  // Map the shared memory into this process. This validates the size.
-  if (!duped_shared_memory->Map(size)) {
-    DVLOG(0) << "Failed to map shared memory.";
-    return false;
-  }
-
-  // If it could be mapped register the shared memory with the ID.
-  Buffer buffer;
-  buffer.ptr = duped_shared_memory->memory();
-  buffer.size = size;
-  buffer.shared_memory = duped_shared_memory.release();
+  // Register the shared memory with the ID.
+  scoped_refptr<Buffer> buffer = new gpu::Buffer(shared_memory.Pass(), size);
 
   // Check buffer alignment is sane.
-  DCHECK(!(reinterpret_cast<uintptr_t>(buffer.ptr) &
+  DCHECK(!(reinterpret_cast<uintptr_t>(buffer->memory()) &
            (kCommandBufferEntrySize - 1)));
 
   shared_memory_bytes_allocated_ += size;
@@ -96,22 +76,21 @@
     return;
   }
 
-  DCHECK(shared_memory_bytes_allocated_ >= it->second.size);
-  shared_memory_bytes_allocated_ -= it->second.size;
+  DCHECK(shared_memory_bytes_allocated_ >= it->second->size());
+  shared_memory_bytes_allocated_ -= it->second->size();
   TRACE_COUNTER_ID1(
       "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_);
 
-  delete it->second.shared_memory;
   registered_buffers_.erase(it);
 }
 
-Buffer TransferBufferManager::GetTransferBuffer(int32 id) {
+scoped_refptr<Buffer> TransferBufferManager::GetTransferBuffer(int32 id) {
   if (id == 0)
-    return Buffer();
+    return NULL;
 
   BufferMap::iterator it = registered_buffers_.find(id);
   if (it == registered_buffers_.end())
-    return Buffer();
+    return NULL;
 
   return it->second;
 }
diff --git a/gpu/command_buffer/service/transfer_buffer_manager.h b/gpu/command_buffer/service/transfer_buffer_manager.h
index 5e1a746..5f8f946 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager.h
+++ b/gpu/command_buffer/service/transfer_buffer_manager.h
@@ -20,12 +20,12 @@
  public:
   virtual ~TransferBufferManagerInterface();
 
-  virtual bool RegisterTransferBuffer(int32 id,
-                                      base::SharedMemory* shared_memory,
-                                      size_t size) = 0;
+  virtual bool RegisterTransferBuffer(
+      int32 id,
+      scoped_ptr<base::SharedMemory> shared_memory,
+      size_t size) = 0;
   virtual void DestroyTransferBuffer(int32 id) = 0;
-  virtual Buffer GetTransferBuffer(int32 id) = 0;
-
+  virtual scoped_refptr<Buffer> GetTransferBuffer(int32 id) = 0;
 };
 
 class GPU_EXPORT TransferBufferManager
@@ -34,16 +34,17 @@
   TransferBufferManager();
 
   bool Initialize();
-  virtual bool RegisterTransferBuffer(int32 id,
-                                      base::SharedMemory* shared_memory,
-                                      size_t size) OVERRIDE;
+  virtual bool RegisterTransferBuffer(
+      int32 id,
+      scoped_ptr<base::SharedMemory> shared_memory,
+      size_t size) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual Buffer GetTransferBuffer(int32 id) OVERRIDE;
+  virtual scoped_refptr<Buffer> GetTransferBuffer(int32 id) OVERRIDE;
 
  private:
   virtual ~TransferBufferManager();
 
-  typedef base::hash_map<int32, Buffer> BufferMap;
+  typedef base::hash_map<int32, scoped_refptr<Buffer> > BufferMap;
   BufferMap registered_buffers_;
   size_t shared_memory_bytes_allocated_;
 
diff --git a/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc b/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
index 68c5c2e..c7dc04a 100644
--- a/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/transfer_buffer_manager_unittest.cc
@@ -17,83 +17,78 @@
 class TransferBufferManagerTest : public testing::Test {
  protected:
   virtual void SetUp() {
-    for (size_t i = 0; i < arraysize(buffers_); ++i) {
-      buffers_[i].CreateAnonymous(kBufferSize);
-      buffers_[i].Map(kBufferSize);
-    }
-
     TransferBufferManager* manager = new TransferBufferManager();
     transfer_buffer_manager_.reset(manager);
     ASSERT_TRUE(manager->Initialize());
   }
 
-  base::SharedMemory buffers_[3];
   scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
 };
 
 TEST_F(TransferBufferManagerTest, ZeroHandleMapsToNull) {
-  EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(0).ptr);
+  EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(0));
 }
 
 TEST_F(TransferBufferManagerTest, NegativeHandleMapsToNull) {
-  EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(-1).ptr);
+  EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(-1));
 }
 
 TEST_F(TransferBufferManagerTest, OutOfRangeHandleMapsToNull) {
-  EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(1).ptr);
+  EXPECT_TRUE(NULL == transfer_buffer_manager_->GetTransferBuffer(1));
 }
 
 TEST_F(TransferBufferManagerTest, CanRegisterTransferBuffer) {
-  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
-                                                               &buffers_[0],
-                                                               kBufferSize));
-  Buffer registered = transfer_buffer_manager_->GetTransferBuffer(1);
+  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+  shm->CreateAndMapAnonymous(kBufferSize);
+  base::SharedMemory* shm_raw_pointer = shm.get();
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(
+      1, shm.Pass(), kBufferSize));
+  scoped_refptr<Buffer> registered =
+      transfer_buffer_manager_->GetTransferBuffer(1);
 
-  // Distinct memory range and shared memory handle from that originally
-  // registered.
-  EXPECT_NE(static_cast<void*>(NULL), registered.ptr);
-  EXPECT_NE(buffers_[0].memory(), registered.ptr);
-  EXPECT_EQ(kBufferSize, registered.size);
-  EXPECT_NE(&buffers_[0], registered.shared_memory);
-
-  // But maps to the same physical memory.
-  *static_cast<int*>(registered.ptr) = 7;
-  *static_cast<int*>(buffers_[0].memory()) = 8;
-  EXPECT_EQ(8, *static_cast<int*>(registered.ptr));
+  // Shared-memory ownership is transfered. It should be the same memory.
+  EXPECT_EQ(shm_raw_pointer, registered->shared_memory());
 }
 
 TEST_F(TransferBufferManagerTest, CanDestroyTransferBuffer) {
-  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
-                                                               &buffers_[0],
-                                                               kBufferSize));
+  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+  shm->CreateAndMapAnonymous(kBufferSize);
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(
+      1, shm.Pass(), kBufferSize));
   transfer_buffer_manager_->DestroyTransferBuffer(1);
-  Buffer registered = transfer_buffer_manager_->GetTransferBuffer(1);
+  scoped_refptr<Buffer> registered =
+      transfer_buffer_manager_->GetTransferBuffer(1);
 
-  EXPECT_EQ(static_cast<void*>(NULL), registered.ptr);
-  EXPECT_EQ(0U, registered.size);
-  EXPECT_EQ(static_cast<base::SharedMemory*>(NULL), registered.shared_memory);
+  scoped_refptr<Buffer> null_buffer;
+  EXPECT_EQ(null_buffer, registered);
 }
 
 TEST_F(TransferBufferManagerTest, CannotRegregisterTransferBufferId) {
-  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
-                                                               &buffers_[0],
-                                                               kBufferSize));
-  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(1,
-                                                                &buffers_[0],
-                                                                kBufferSize));
-  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(1,
-                                                                &buffers_[1],
-                                                                kBufferSize));
+  scoped_ptr<base::SharedMemory> shm1(new base::SharedMemory());
+  scoped_ptr<base::SharedMemory> shm2(new base::SharedMemory());
+  scoped_ptr<base::SharedMemory> shm3(new base::SharedMemory());
+  shm1->CreateAndMapAnonymous(kBufferSize);
+  shm2->CreateAndMapAnonymous(kBufferSize);
+  shm3->CreateAndMapAnonymous(kBufferSize);
+
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(
+      1, shm1.Pass(), kBufferSize));
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(
+      1, shm2.Pass(), kBufferSize));
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(
+      1, shm3.Pass(), kBufferSize));
 }
 
 TEST_F(TransferBufferManagerTest, CanReuseTransferBufferIdAfterDestroying) {
-  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
-                                                               &buffers_[0],
-                                                               kBufferSize));
+  scoped_ptr<base::SharedMemory> shm1(new base::SharedMemory());
+  scoped_ptr<base::SharedMemory> shm2(new base::SharedMemory());
+  shm1->CreateAndMapAnonymous(kBufferSize);
+  shm2->CreateAndMapAnonymous(kBufferSize);
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(
+      1, shm1.Pass(), kBufferSize));
   transfer_buffer_manager_->DestroyTransferBuffer(1);
-  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(1,
-                                                               &buffers_[1],
-                                                               kBufferSize));
+  EXPECT_TRUE(transfer_buffer_manager_->RegisterTransferBuffer(
+      1, shm2.Pass(), kBufferSize));
 }
 
 TEST_F(TransferBufferManagerTest, DestroyUnusedTransferBufferIdDoesNotCrash) {
@@ -101,15 +96,17 @@
 }
 
 TEST_F(TransferBufferManagerTest, CannotRegisterNullTransferBuffer) {
-  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(0,
-                                                                &buffers_[0],
-                                                                kBufferSize));
+  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+  shm->CreateAndMapAnonymous(kBufferSize);
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(
+      0, shm.Pass(), kBufferSize));
 }
 
 TEST_F(TransferBufferManagerTest, CannotRegisterNegativeTransferBufferId) {
-  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(-1,
-                                                                &buffers_[0],
-                                                                kBufferSize));
+  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+  shm->CreateAndMapAnonymous(kBufferSize);
+  EXPECT_FALSE(transfer_buffer_manager_->RegisterTransferBuffer(
+      -1, shm.Pass(), kBufferSize));
 }
 
 }  // namespace gpu
diff --git a/gpu/command_buffer_client.target.darwin-arm.mk b/gpu/command_buffer_client.target.darwin-arm.mk
index 63ec676..c72f58a 100644
--- a/gpu/command_buffer_client.target.darwin-arm.mk
+++ b/gpu/command_buffer_client.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_client.target.darwin-mips.mk b/gpu/command_buffer_client.target.darwin-mips.mk
index 0c572b6..9097c57 100644
--- a/gpu/command_buffer_client.target.darwin-mips.mk
+++ b/gpu/command_buffer_client.target.darwin-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_client.target.darwin-x86.mk b/gpu/command_buffer_client.target.darwin-x86.mk
index e91a888..273567e 100644
--- a/gpu/command_buffer_client.target.darwin-x86.mk
+++ b/gpu/command_buffer_client.target.darwin-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_client.target.darwin-x86_64.mk b/gpu/command_buffer_client.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7011383
--- /dev/null
+++ b/gpu/command_buffer_client.target.darwin-x86_64.mk
@@ -0,0 +1,268 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_client_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/cmd_buffer_helper.cc \
+	gpu/command_buffer/client/fenced_allocator.cc \
+	gpu/command_buffer/client/mapped_memory.cc \
+	gpu/command_buffer/client/ring_buffer.cc \
+	gpu/command_buffer/client/transfer_buffer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_client_gyp
+
+# Alias gyp target name.
+.PHONY: command_buffer_client
+command_buffer_client: gpu_command_buffer_client_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer_client.target.linux-arm.mk b/gpu/command_buffer_client.target.linux-arm.mk
index 63ec676..c72f58a 100644
--- a/gpu/command_buffer_client.target.linux-arm.mk
+++ b/gpu/command_buffer_client.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_client.target.linux-mips.mk b/gpu/command_buffer_client.target.linux-mips.mk
index 0c572b6..9097c57 100644
--- a/gpu/command_buffer_client.target.linux-mips.mk
+++ b/gpu/command_buffer_client.target.linux-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_client.target.linux-x86.mk b/gpu/command_buffer_client.target.linux-x86.mk
index e91a888..273567e 100644
--- a/gpu/command_buffer_client.target.linux-x86.mk
+++ b/gpu/command_buffer_client.target.linux-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_client.target.linux-x86_64.mk b/gpu/command_buffer_client.target.linux-x86_64.mk
new file mode 100644
index 0000000..7011383
--- /dev/null
+++ b/gpu/command_buffer_client.target.linux-x86_64.mk
@@ -0,0 +1,268 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_client_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/cmd_buffer_helper.cc \
+	gpu/command_buffer/client/fenced_allocator.cc \
+	gpu/command_buffer/client/mapped_memory.cc \
+	gpu/command_buffer/client/ring_buffer.cc \
+	gpu/command_buffer/client/transfer_buffer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_client_gyp
+
+# Alias gyp target name.
+.PHONY: command_buffer_client
+command_buffer_client: gpu_command_buffer_client_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer_common.gypi b/gpu/command_buffer_common.gypi
index b983119..b5f3858 100644
--- a/gpu/command_buffer_common.gypi
+++ b/gpu/command_buffer_common.gypi
@@ -8,6 +8,7 @@
   ],
   'sources': [
     'command_buffer/common/bitfield_helpers.h',
+    'command_buffer/common/buffer.cc',
     'command_buffer/common/buffer.h',
     'command_buffer/common/capabilities.cc',
     'command_buffer/common/capabilities.h',
diff --git a/gpu/command_buffer_common.target.darwin-arm.mk b/gpu/command_buffer_common.target.darwin-arm.mk
index 43bfb46..77db218 100644
--- a/gpu/command_buffer_common.target.darwin-arm.mk
+++ b/gpu/command_buffer_common.target.darwin-arm.mk
@@ -24,6 +24,7 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
 	gpu/command_buffer/common/capabilities.cc \
 	gpu/command_buffer/common/cmd_buffer_common.cc \
 	gpu/command_buffer/common/debug_marker_manager.cc \
@@ -85,6 +86,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_common.target.darwin-mips.mk b/gpu/command_buffer_common.target.darwin-mips.mk
index 989f906..4acce79 100644
--- a/gpu/command_buffer_common.target.darwin-mips.mk
+++ b/gpu/command_buffer_common.target.darwin-mips.mk
@@ -24,6 +24,7 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
 	gpu/command_buffer/common/capabilities.cc \
 	gpu/command_buffer/common/cmd_buffer_common.cc \
 	gpu/command_buffer/common/debug_marker_manager.cc \
@@ -84,6 +85,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -169,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_common.target.darwin-x86.mk b/gpu/command_buffer_common.target.darwin-x86.mk
index 6964b50..fa4984e 100644
--- a/gpu/command_buffer_common.target.darwin-x86.mk
+++ b/gpu/command_buffer_common.target.darwin-x86.mk
@@ -24,6 +24,7 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
 	gpu/command_buffer/common/capabilities.cc \
 	gpu/command_buffer/common/cmd_buffer_common.cc \
 	gpu/command_buffer/common/debug_marker_manager.cc \
@@ -86,6 +87,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_common.target.darwin-x86_64.mk b/gpu/command_buffer_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..cf80487
--- /dev/null
+++ b/gpu/command_buffer_common.target.darwin-x86_64.mk
@@ -0,0 +1,271 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
+	gpu/command_buffer/common/capabilities.cc \
+	gpu/command_buffer/common/cmd_buffer_common.cc \
+	gpu/command_buffer/common/debug_marker_manager.cc \
+	gpu/command_buffer/common/gles2_cmd_format.cc \
+	gpu/command_buffer/common/id_allocator.cc \
+	gpu/command_buffer/common/mailbox.cc \
+	gpu/command_buffer/common/mailbox_holder.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_common_gyp
+
+# Alias gyp target name.
+.PHONY: command_buffer_common
+command_buffer_common: gpu_command_buffer_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer_common.target.linux-arm.mk b/gpu/command_buffer_common.target.linux-arm.mk
index 43bfb46..77db218 100644
--- a/gpu/command_buffer_common.target.linux-arm.mk
+++ b/gpu/command_buffer_common.target.linux-arm.mk
@@ -24,6 +24,7 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
 	gpu/command_buffer/common/capabilities.cc \
 	gpu/command_buffer/common/cmd_buffer_common.cc \
 	gpu/command_buffer/common/debug_marker_manager.cc \
@@ -85,6 +86,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_common.target.linux-mips.mk b/gpu/command_buffer_common.target.linux-mips.mk
index 989f906..4acce79 100644
--- a/gpu/command_buffer_common.target.linux-mips.mk
+++ b/gpu/command_buffer_common.target.linux-mips.mk
@@ -24,6 +24,7 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
 	gpu/command_buffer/common/capabilities.cc \
 	gpu/command_buffer/common/cmd_buffer_common.cc \
 	gpu/command_buffer/common/debug_marker_manager.cc \
@@ -84,6 +85,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -169,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_common.target.linux-x86.mk b/gpu/command_buffer_common.target.linux-x86.mk
index 6964b50..fa4984e 100644
--- a/gpu/command_buffer_common.target.linux-x86.mk
+++ b/gpu/command_buffer_common.target.linux-x86.mk
@@ -24,6 +24,7 @@
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
 LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
 	gpu/command_buffer/common/capabilities.cc \
 	gpu/command_buffer/common/cmd_buffer_common.cc \
 	gpu/command_buffer/common/debug_marker_manager.cc \
@@ -86,6 +87,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_common.target.linux-x86_64.mk b/gpu/command_buffer_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..cf80487
--- /dev/null
+++ b/gpu/command_buffer_common.target.linux-x86_64.mk
@@ -0,0 +1,271 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/common/buffer.cc \
+	gpu/command_buffer/common/capabilities.cc \
+	gpu/command_buffer/common/cmd_buffer_common.cc \
+	gpu/command_buffer/common/debug_marker_manager.cc \
+	gpu/command_buffer/common/gles2_cmd_format.cc \
+	gpu/command_buffer/common/id_allocator.cc \
+	gpu/command_buffer/common/mailbox.cc \
+	gpu/command_buffer/common/mailbox_holder.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_common_gyp
+
+# Alias gyp target name.
+.PHONY: command_buffer_common
+command_buffer_common: gpu_command_buffer_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer_service.gypi b/gpu/command_buffer_service.gypi
index 89689cf..cd4662d 100644
--- a/gpu/command_buffer_service.gypi
+++ b/gpu/command_buffer_service.gypi
@@ -111,8 +111,6 @@
     'command_buffer/service/renderbuffer_manager.cc',
     'command_buffer/service/program_cache.h',
     'command_buffer/service/program_cache.cc',
-    'command_buffer/service/safe_shared_memory_pool.h',
-    'command_buffer/service/safe_shared_memory_pool.cc',
     'command_buffer/service/shader_manager.h',
     'command_buffer/service/shader_manager.cc',
     'command_buffer/service/shader_translator.h',
diff --git a/gpu/command_buffer_service.target.darwin-arm.mk b/gpu/command_buffer_service.target.darwin-arm.mk
index faf9524..3a6caf0 100644
--- a/gpu/command_buffer_service.target.darwin-arm.mk
+++ b/gpu/command_buffer_service.target.darwin-arm.mk
@@ -64,7 +64,6 @@
 	gpu/command_buffer/service/query_manager.cc \
 	gpu/command_buffer/service/renderbuffer_manager.cc \
 	gpu/command_buffer/service/program_cache.cc \
-	gpu/command_buffer/service/safe_shared_memory_pool.cc \
 	gpu/command_buffer/service/shader_manager.cc \
 	gpu/command_buffer/service/shader_translator.cc \
 	gpu/command_buffer/service/shader_translator_cache.cc \
@@ -140,9 +139,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -152,6 +149,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -272,9 +270,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -284,6 +280,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_service.target.darwin-mips.mk b/gpu/command_buffer_service.target.darwin-mips.mk
index 66a83db..1bc1ffb 100644
--- a/gpu/command_buffer_service.target.darwin-mips.mk
+++ b/gpu/command_buffer_service.target.darwin-mips.mk
@@ -64,7 +64,6 @@
 	gpu/command_buffer/service/query_manager.cc \
 	gpu/command_buffer/service/renderbuffer_manager.cc \
 	gpu/command_buffer/service/program_cache.cc \
-	gpu/command_buffer/service/safe_shared_memory_pool.cc \
 	gpu/command_buffer/service/shader_manager.cc \
 	gpu/command_buffer/service/shader_translator.cc \
 	gpu/command_buffer/service/shader_translator_cache.cc \
@@ -139,9 +138,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -151,6 +148,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -270,9 +268,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -282,6 +278,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_service.target.darwin-x86.mk b/gpu/command_buffer_service.target.darwin-x86.mk
index 9e78222..02d834e 100644
--- a/gpu/command_buffer_service.target.darwin-x86.mk
+++ b/gpu/command_buffer_service.target.darwin-x86.mk
@@ -64,7 +64,6 @@
 	gpu/command_buffer/service/query_manager.cc \
 	gpu/command_buffer/service/renderbuffer_manager.cc \
 	gpu/command_buffer/service/program_cache.cc \
-	gpu/command_buffer/service/safe_shared_memory_pool.cc \
 	gpu/command_buffer/service/shader_manager.cc \
 	gpu/command_buffer/service/shader_translator.cc \
 	gpu/command_buffer/service/shader_translator_cache.cc \
@@ -141,9 +140,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -153,6 +150,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -273,9 +271,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -285,6 +281,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_service.target.darwin-x86_64.mk b/gpu/command_buffer_service.target.darwin-x86_64.mk
new file mode 100644
index 0000000..f083bfb
--- /dev/null
+++ b/gpu/command_buffer_service.target.darwin-x86_64.mk
@@ -0,0 +1,403 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_service_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_disk_cache_proto_gyp)/gpu_disk_cache_proto_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/service/async_pixel_transfer_delegate.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_android.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_stub.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager.cc \
+	gpu/command_buffer/service/buffer_manager.cc \
+	gpu/command_buffer/service/cmd_parser.cc \
+	gpu/command_buffer/service/command_buffer_service.cc \
+	gpu/command_buffer/service/common_decoder.cc \
+	gpu/command_buffer/service/context_group.cc \
+	gpu/command_buffer/service/context_state.cc \
+	gpu/command_buffer/service/error_state.cc \
+	gpu/command_buffer/service/feature_info.cc \
+	gpu/command_buffer/service/framebuffer_manager.cc \
+	gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc \
+	gpu/command_buffer/service/gles2_cmd_decoder.cc \
+	gpu/command_buffer/service/gles2_cmd_validation.cc \
+	gpu/command_buffer/service/gl_context_virtual.cc \
+	gpu/command_buffer/service/gl_state_restorer_impl.cc \
+	gpu/command_buffer/service/gpu_control_service.cc \
+	gpu/command_buffer/service/gpu_scheduler.cc \
+	gpu/command_buffer/service/gpu_state_tracer.cc \
+	gpu/command_buffer/service/gpu_switches.cc \
+	gpu/command_buffer/service/gpu_tracer.cc \
+	gpu/command_buffer/service/id_manager.cc \
+	gpu/command_buffer/service/image_manager.cc \
+	gpu/command_buffer/service/in_process_command_buffer.cc \
+	gpu/command_buffer/service/logger.cc \
+	gpu/command_buffer/service/mailbox_manager.cc \
+	gpu/command_buffer/service/mailbox_synchronizer.cc \
+	gpu/command_buffer/service/memory_program_cache.cc \
+	gpu/command_buffer/service/program_manager.cc \
+	gpu/command_buffer/service/query_manager.cc \
+	gpu/command_buffer/service/renderbuffer_manager.cc \
+	gpu/command_buffer/service/program_cache.cc \
+	gpu/command_buffer/service/shader_manager.cc \
+	gpu/command_buffer/service/shader_translator.cc \
+	gpu/command_buffer/service/shader_translator_cache.cc \
+	gpu/command_buffer/service/stream_texture_manager_in_process_android.cc \
+	gpu/command_buffer/service/texture_definition.cc \
+	gpu/command_buffer/service/texture_manager.cc \
+	gpu/command_buffer/service/transfer_buffer_manager.cc \
+	gpu/command_buffer/service/vertex_array_manager.cc \
+	gpu/command_buffer/service/vertex_attrib_manager.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables \
+	-O2
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	gpu_disk_cache_proto_gyp \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_service_gyp
+
+# Alias gyp target name.
+.PHONY: command_buffer_service
+command_buffer_service: gpu_command_buffer_service_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/command_buffer_service.target.linux-arm.mk b/gpu/command_buffer_service.target.linux-arm.mk
index faf9524..3a6caf0 100644
--- a/gpu/command_buffer_service.target.linux-arm.mk
+++ b/gpu/command_buffer_service.target.linux-arm.mk
@@ -64,7 +64,6 @@
 	gpu/command_buffer/service/query_manager.cc \
 	gpu/command_buffer/service/renderbuffer_manager.cc \
 	gpu/command_buffer/service/program_cache.cc \
-	gpu/command_buffer/service/safe_shared_memory_pool.cc \
 	gpu/command_buffer/service/shader_manager.cc \
 	gpu/command_buffer/service/shader_translator.cc \
 	gpu/command_buffer/service/shader_translator_cache.cc \
@@ -140,9 +139,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -152,6 +149,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -272,9 +270,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -284,6 +280,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_service.target.linux-mips.mk b/gpu/command_buffer_service.target.linux-mips.mk
index 66a83db..1bc1ffb 100644
--- a/gpu/command_buffer_service.target.linux-mips.mk
+++ b/gpu/command_buffer_service.target.linux-mips.mk
@@ -64,7 +64,6 @@
 	gpu/command_buffer/service/query_manager.cc \
 	gpu/command_buffer/service/renderbuffer_manager.cc \
 	gpu/command_buffer/service/program_cache.cc \
-	gpu/command_buffer/service/safe_shared_memory_pool.cc \
 	gpu/command_buffer/service/shader_manager.cc \
 	gpu/command_buffer/service/shader_translator.cc \
 	gpu/command_buffer/service/shader_translator_cache.cc \
@@ -139,9 +138,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -151,6 +148,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -270,9 +268,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -282,6 +278,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_service.target.linux-x86.mk b/gpu/command_buffer_service.target.linux-x86.mk
index 9e78222..02d834e 100644
--- a/gpu/command_buffer_service.target.linux-x86.mk
+++ b/gpu/command_buffer_service.target.linux-x86.mk
@@ -64,7 +64,6 @@
 	gpu/command_buffer/service/query_manager.cc \
 	gpu/command_buffer/service/renderbuffer_manager.cc \
 	gpu/command_buffer/service/program_cache.cc \
-	gpu/command_buffer/service/safe_shared_memory_pool.cc \
 	gpu/command_buffer/service/shader_manager.cc \
 	gpu/command_buffer/service/shader_translator.cc \
 	gpu/command_buffer/service/shader_translator_cache.cc \
@@ -141,9 +140,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -153,6 +150,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -273,9 +271,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -285,6 +281,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/command_buffer_service.target.linux-x86_64.mk b/gpu/command_buffer_service.target.linux-x86_64.mk
new file mode 100644
index 0000000..f083bfb
--- /dev/null
+++ b/gpu/command_buffer_service.target.linux-x86_64.mk
@@ -0,0 +1,403 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_command_buffer_service_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_disk_cache_proto_gyp)/gpu_disk_cache_proto_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/service/async_pixel_transfer_delegate.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_android.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_idle.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_share_group.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_stub.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_sync.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager.cc \
+	gpu/command_buffer/service/buffer_manager.cc \
+	gpu/command_buffer/service/cmd_parser.cc \
+	gpu/command_buffer/service/command_buffer_service.cc \
+	gpu/command_buffer/service/common_decoder.cc \
+	gpu/command_buffer/service/context_group.cc \
+	gpu/command_buffer/service/context_state.cc \
+	gpu/command_buffer/service/error_state.cc \
+	gpu/command_buffer/service/feature_info.cc \
+	gpu/command_buffer/service/framebuffer_manager.cc \
+	gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.cc \
+	gpu/command_buffer/service/gles2_cmd_decoder.cc \
+	gpu/command_buffer/service/gles2_cmd_validation.cc \
+	gpu/command_buffer/service/gl_context_virtual.cc \
+	gpu/command_buffer/service/gl_state_restorer_impl.cc \
+	gpu/command_buffer/service/gpu_control_service.cc \
+	gpu/command_buffer/service/gpu_scheduler.cc \
+	gpu/command_buffer/service/gpu_state_tracer.cc \
+	gpu/command_buffer/service/gpu_switches.cc \
+	gpu/command_buffer/service/gpu_tracer.cc \
+	gpu/command_buffer/service/id_manager.cc \
+	gpu/command_buffer/service/image_manager.cc \
+	gpu/command_buffer/service/in_process_command_buffer.cc \
+	gpu/command_buffer/service/logger.cc \
+	gpu/command_buffer/service/mailbox_manager.cc \
+	gpu/command_buffer/service/mailbox_synchronizer.cc \
+	gpu/command_buffer/service/memory_program_cache.cc \
+	gpu/command_buffer/service/program_manager.cc \
+	gpu/command_buffer/service/query_manager.cc \
+	gpu/command_buffer/service/renderbuffer_manager.cc \
+	gpu/command_buffer/service/program_cache.cc \
+	gpu/command_buffer/service/shader_manager.cc \
+	gpu/command_buffer/service/shader_translator.cc \
+	gpu/command_buffer/service/shader_translator_cache.cc \
+	gpu/command_buffer/service/stream_texture_manager_in_process_android.cc \
+	gpu/command_buffer/service/texture_definition.cc \
+	gpu/command_buffer/service/texture_manager.cc \
+	gpu/command_buffer/service/transfer_buffer_manager.cc \
+	gpu/command_buffer/service/vertex_array_manager.cc \
+	gpu/command_buffer/service/vertex_attrib_manager.cc \
+	gpu/command_buffer/service/async_pixel_transfer_manager_egl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables \
+	-O2
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	gpu_disk_cache_proto_gyp \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_command_buffer_service_gyp
+
+# Alias gyp target name.
+.PHONY: command_buffer_service
+command_buffer_service: gpu_command_buffer_service_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc
index f051ea1..2465007 100644
--- a/gpu/config/gpu_control_list.cc
+++ b/gpu/config/gpu_control_list.cc
@@ -414,6 +414,12 @@
   return op_ != kUnknown;
 }
 
+GpuControlList::BoolInfo::BoolInfo(bool value) : value_(value) {}
+
+bool GpuControlList::BoolInfo::Contains(bool value) const {
+  return value_ == value;
+}
+
 // static
 GpuControlList::ScopedGpuControlListEntry
 GpuControlList::GpuControlListEntry::GetEntryFromValue(
@@ -744,6 +750,12 @@
     dictionary_entry_count++;
   }
 
+  bool direct_rendering;
+  if (value->GetBoolean("direct_rendering", &direct_rendering)) {
+    entry->SetDirectRenderingInfo(direct_rendering);
+    dictionary_entry_count++;
+  }
+
   if (top_level) {
     const base::ListValue* feature_value = NULL;
     if (value->GetList("features", &feature_value)) {
@@ -970,6 +982,10 @@
   return gpu_count_info_->IsValid();
 }
 
+void GpuControlList::GpuControlListEntry::SetDirectRenderingInfo(bool value) {
+  direct_rendering_info_.reset(new BoolInfo(value));
+}
+
 bool GpuControlList::GpuControlListEntry::SetFeatures(
     const std::vector<std::string>& feature_strings,
     const FeatureMap& feature_map,
@@ -1119,6 +1135,9 @@
   if (gpu_count_info_.get() != NULL &&
       !gpu_count_info_->Contains(gpu_info.secondary_gpus.size() + 1))
     return false;
+  if (direct_rendering_info_.get() != NULL &&
+      !direct_rendering_info_->Contains(gpu_info.direct_rendering))
+    return false;
   if (cpu_brand_.get() != NULL) {
     base::CPU cpu_info;
     if (!cpu_brand_->Contains(cpu_info.cpu_brand()))
diff --git a/gpu/config/gpu_control_list.h b/gpu/config/gpu_control_list.h
index 9510a5a..80a95ba 100644
--- a/gpu/config/gpu_control_list.h
+++ b/gpu/config/gpu_control_list.h
@@ -254,6 +254,17 @@
     int value2_;
   };
 
+  class GPU_EXPORT BoolInfo {
+   public:
+    explicit BoolInfo(bool value);
+
+    // Determines if a given bool is included in the BoolInfo.
+    bool Contains(bool value) const;
+
+   private:
+    bool value_;
+  };
+
   class GPU_EXPORT MachineModelInfo {
    public:
     MachineModelInfo(const std::string& name_op,
@@ -413,6 +424,8 @@
                          const std::string& int_string,
                          const std::string& int_string2);
 
+    void SetDirectRenderingInfo(bool value);
+
     bool SetFeatures(const std::vector<std::string>& features,
                      const FeatureMap& feature_map,
                      bool supports_feature_type_all);
@@ -453,6 +466,7 @@
     scoped_ptr<FloatInfo> perf_overall_info_;
     scoped_ptr<MachineModelInfo> machine_model_info_;
     scoped_ptr<IntInfo> gpu_count_info_;
+    scoped_ptr<BoolInfo> direct_rendering_info_;
     std::set<int> features_;
     std::vector<ScopedGpuControlListEntry> exceptions_;
   };
diff --git a/gpu/config/gpu_control_list_format.txt b/gpu/config/gpu_control_list_format.txt
index e9522c3..482a8b1 100644
--- a/gpu/config/gpu_control_list_format.txt
+++ b/gpu/config/gpu_control_list_format.txt
@@ -50,6 +50,8 @@
 // 23. "cr_bugs" is an array of associated webkit bug numbers.
 // 24. "disabled" is a boolean. If it is present, the entry will be skipped.
 //     This can not be used in exceptions.
+// 25. "direct_rendering" is a boolean. If present, this will filter on whether
+// the GL contexts are direct or indirect based on the value.
 //
 // VERSION includes "op", "style", "value", and "value2".  "op" can be any of
 // the following values: "=", "<", "<=", ">", ">=", "any", "between".  "style"
diff --git a/gpu/config/gpu_control_list_number_info_unittest.cc b/gpu/config/gpu_control_list_number_info_unittest.cc
index 5bd732c..bbddcb9 100644
--- a/gpu/config/gpu_control_list_number_info_unittest.cc
+++ b/gpu/config/gpu_control_list_number_info_unittest.cc
@@ -14,6 +14,7 @@
 
   typedef GpuControlList::FloatInfo FloatInfo;
   typedef GpuControlList::IntInfo IntInfo;
+  typedef GpuControlList::BoolInfo BoolInfo;
 };
 
 TEST_F(NumberInfoTest, ValidFloatInfo) {
@@ -206,5 +207,18 @@
   }
 }
 
+TEST_F(NumberInfoTest, Bool) {
+  {
+    BoolInfo info(true);
+    EXPECT_TRUE(info.Contains(true));
+    EXPECT_FALSE(info.Contains(false));
+  }
+  {
+    BoolInfo info(false);
+    EXPECT_FALSE(info.Contains(true));
+    EXPECT_TRUE(info.Contains(false));
+  }
+}
+
 }  // namespace gpu
 
diff --git a/gpu/config/gpu_driver_bug_list_json.cc b/gpu/config/gpu_driver_bug_list_json.cc
index 8d1f98f..08febf0 100644
--- a/gpu/config/gpu_driver_bug_list_json.cc
+++ b/gpu/config/gpu_driver_bug_list_json.cc
@@ -19,7 +19,7 @@
 {
   "name": "gpu driver bug list",
   // Please update the version number whenever you change this file.
-  "version": "4.7",
+  "version": "4.8",
   "entries": [
     {
       "id": 1,
@@ -908,6 +908,17 @@
       "features": [
         "force_gl_finish_after_compositing"
       ]
+    },
+    {
+      "id": 68,
+      "description": "Disable partial swaps on linux drivers",
+      "cr_bugs": [339493],
+      "os": {
+        "type": "linux"
+      },
+      "features": [
+        "disable_post_sub_buffers_for_onscreen_surfaces"
+      ]
     }
   ]
 }
diff --git a/gpu/config/gpu_driver_bug_workaround_type.h b/gpu/config/gpu_driver_bug_workaround_type.h
index 922d971..85776e2 100644
--- a/gpu/config/gpu_driver_bug_workaround_type.h
+++ b/gpu/config/gpu_driver_bug_workaround_type.h
@@ -36,6 +36,8 @@
          disable_multisampling)                              \
   GPU_OP(DISABLE_OES_STANDARD_DERIVATIVES,                   \
          disable_oes_standard_derivatives)                   \
+  GPU_OP(DISABLE_POST_SUB_BUFFERS_FOR_ONSCREEN_SURFACES,     \
+         disable_post_sub_buffers_for_onscreen_surfaces)     \
   GPU_OP(ENABLE_CHROMIUM_FAST_NPOT_MO8_TEXTURES,             \
          enable_chromium_fast_npot_mo8_textures)             \
   GPU_OP(EXIT_ON_CONTEXT_LOST,                               \
diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc
index c3dc16f..bb26147 100644
--- a/gpu/config/gpu_info.cc
+++ b/gpu/config/gpu_info.cc
@@ -36,6 +36,7 @@
       gl_reset_notification_strategy(0),
       can_lose_context(false),
       software_rendering(false),
+      direct_rendering(true),
       sandboxed(false) {
 }
 
@@ -70,6 +71,7 @@
     bool can_lose_context;
     GpuPerformanceStats performance_stats;
     bool software_rendering;
+    bool direct_rendering;
     bool sandboxed;
 #if defined(OS_WIN)
     DxDiagNode dx_diagnostics;
@@ -121,6 +123,7 @@
   enumerator->AddBool("can_lose_context", can_lose_context);
   // TODO(kbr): add performance_stats.
   enumerator->AddBool("softwareRendering", software_rendering);
+  enumerator->AddBool("directRendering", direct_rendering);
   enumerator->AddBool("sandboxed", sandboxed);
   // TODO(kbr): add dx_diagnostics on Windows.
   enumerator->EndAuxAttributes();
diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h
index 09417f7..3828b44 100644
--- a/gpu/config/gpu_info.h
+++ b/gpu/config/gpu_info.h
@@ -138,6 +138,10 @@
 
   bool software_rendering;
 
+  // Whether the driver uses direct rendering. True on most platforms, false on
+  // X11 when using remote X.
+  bool direct_rendering;
+
   // Whether the gpu process is running in a sandbox.
   bool sandboxed;
 
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index d81ee69..2f57a4b 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -80,17 +80,21 @@
 
 namespace gpu {
 
-bool CollectGraphicsInfoGL(GPUInfo* gpu_info) {
+CollectInfoResult CollectGraphicsInfoGL(GPUInfo* gpu_info) {
   TRACE_EVENT0("startup", "gpu_info_collector::CollectGraphicsInfoGL");
   DCHECK_NE(gfx::GetGLImplementation(), gfx::kGLImplementationNone);
 
   scoped_refptr<gfx::GLSurface> surface(InitializeGLSurface());
-  if (!surface.get())
-    return false;
+  if (!surface.get()) {
+    LOG(ERROR) << "Could not create surface for info collection.";
+    return kCollectInfoFatalFailure;
+  }
 
   scoped_refptr<gfx::GLContext> context(InitializeGLContext(surface.get()));
-  if (!context.get())
-    return false;
+  if (!context.get()) {
+    LOG(ERROR) << "Could not create context for info collection.";
+    return kCollectInfoFatalFailure;
+  }
 
   gpu_info->gl_renderer = GetGLString(GL_RENDERER);
   gpu_info->gl_vendor = GetGLString(GL_VENDOR);
@@ -103,6 +107,7 @@
     gpu_info->gl_ws_vendor = window_system_binding_info.vendor;
     gpu_info->gl_ws_version = window_system_binding_info.version;
     gpu_info->gl_ws_extensions = window_system_binding_info.extensions;
+    gpu_info->direct_rendering = window_system_binding_info.direct_rendering;
   }
 
   bool supports_robustness =
@@ -150,6 +155,7 @@
 
   basic_gpu_info->can_lose_context = context_gpu_info.can_lose_context;
   basic_gpu_info->sandboxed = context_gpu_info.sandboxed;
+  basic_gpu_info->direct_rendering = context_gpu_info.direct_rendering;
   basic_gpu_info->finalized = context_gpu_info.finalized;
   basic_gpu_info->initialization_time = context_gpu_info.initialization_time;
 }
diff --git a/gpu/config/gpu_info_collector.h b/gpu/config/gpu_info_collector.h
index e89535a..f3d339e 100644
--- a/gpu/config/gpu_info_collector.h
+++ b/gpu/config/gpu_info_collector.h
@@ -18,6 +18,18 @@
   kGpuIDNotSupported
 };
 
+// Result for the various Collect*Info* functions below.
+// Fatal failures are for cases where we can't create a context at all or
+// something, making the use of the GPU impossible.
+// Non-fatal failures are for cases where we could gather most info, but maybe
+// some is missing (e.g. unable to parse a version string or to detect the exact
+// model).
+enum CollectInfoResult {
+  kCollectInfoFatalFailure,
+  kCollectInfoNonFatalFailure,
+  kCollectInfoSuccess
+};
+
 // Collect GPU vendor_id and device ID.
 GPU_EXPORT GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id);
 
@@ -25,12 +37,11 @@
 // the danger of crashing), including vendor_id and device_id.
 // This is called at browser process startup time.
 // The subset each platform collects may be different.
-GPU_EXPORT bool CollectBasicGraphicsInfo(GPUInfo* gpu_info);
+GPU_EXPORT CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info);
 
 // Create a GL/DirectX context and collect related info.
 // This is called at GPU process startup time.
-// Returns true on success.
-GPU_EXPORT bool CollectContextGraphicsInfo(GPUInfo* gpu_info);
+GPU_EXPORT CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info);
 
 #if defined(OS_WIN)
 // Collect the DirectX Disagnostics information about the attached displays.
@@ -38,10 +49,10 @@
 #endif  // OS_WIN
 
 // Create a GL context and collect GL strings and versions.
-GPU_EXPORT bool CollectGraphicsInfoGL(GPUInfo* gpu_info);
+GPU_EXPORT CollectInfoResult CollectGraphicsInfoGL(GPUInfo* gpu_info);
 
 // Each platform stores the driver version on the GL_VERSION string differently
-GPU_EXPORT bool CollectDriverInfoGL(GPUInfo* gpu_info);
+GPU_EXPORT CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info);
 
 // Merge GPUInfo from CollectContextGraphicsInfo into basic GPUInfo.
 // This is platform specific, depending on which info are collected at which
diff --git a/gpu/config/gpu_info_collector_android.cc b/gpu/config/gpu_info_collector_android.cc
index 03f357e..e2905b0 100644
--- a/gpu/config/gpu_info_collector_android.cc
+++ b/gpu/config/gpu_info_collector_android.cc
@@ -84,7 +84,7 @@
 
 namespace gpu {
 
-bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
   return CollectBasicGraphicsInfo(gpu_info);
 }
 
@@ -95,7 +95,7 @@
   return kGpuIDNotSupported;
 }
 
-bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
   gpu_info->can_lose_context = false;
   gpu_info->finalized = true;
 
@@ -107,12 +107,12 @@
   return CollectGraphicsInfoGL(gpu_info);
 }
 
-bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
   gpu_info->driver_version = GetDriverVersionFromString(
       gpu_info->gl_version_string);
   gpu_info->gpu.vendor_string = gpu_info->gl_vendor;
   gpu_info->gpu.device_string = gpu_info->gl_renderer;
-  return true;
+  return kCollectInfoSuccess;
 }
 
 void MergeGPUInfo(GPUInfo* basic_gpu_info,
diff --git a/gpu/config/gpu_info_collector_mac.mm b/gpu/config/gpu_info_collector_mac.mm
index 73194dc..547f6a8 100644
--- a/gpu/config/gpu_info_collector_mac.mm
+++ b/gpu/config/gpu_info_collector_mac.mm
@@ -157,7 +157,7 @@
 
 }  // namespace anonymous
 
-bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
   DCHECK(gpu_info);
 
   TRACE_EVENT0("gpu", "gpu_info_collector::CollectGraphicsInfo");
@@ -182,7 +182,7 @@
   return kGpuIDFailure;
 }
 
-bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
   DCHECK(gpu_info);
 
   std::string model_name;
@@ -193,10 +193,11 @@
   gpu_info->machine_model += " " + base::IntToString(model_major) +
                              "." + base::IntToString(model_minor);
 
-  return CollectPCIVideoCardInfo(gpu_info);
+  bool result = CollectPCIVideoCardInfo(gpu_info);
+  return result ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
 }
 
-bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
   DCHECK(gpu_info);
 
   // Extract the OpenGL driver version string from the GL_VERSION string.
@@ -206,9 +207,9 @@
   std::string gl_version_string = gpu_info->gl_version_string;
   size_t pos = gl_version_string.find_last_of('-');
   if (pos == std::string::npos)
-    return false;
+    return kCollectInfoNonFatalFailure;
   gpu_info->driver_version = gl_version_string.substr(pos + 1);
-  return true;
+  return kCollectInfoSuccess;
 }
 
 void MergeGPUInfo(GPUInfo* basic_gpu_info,
diff --git a/gpu/config/gpu_info_collector_ozone.cc b/gpu/config/gpu_info_collector_ozone.cc
index acef6ae..41bc21a 100644
--- a/gpu/config/gpu_info_collector_ozone.cc
+++ b/gpu/config/gpu_info_collector_ozone.cc
@@ -8,7 +8,7 @@
 
 namespace gpu {
 
-bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
   return CollectBasicGraphicsInfo(gpu_info);
 }
 
@@ -19,14 +19,14 @@
   return kGpuIDNotSupported;
 }
 
-bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
   gpu_info->can_lose_context = false;
-  return true;
+  return kCollectInfoSuccess;
 }
 
-bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
   NOTIMPLEMENTED();
-  return false;
+  return kCollectInfoNonFatalFailure;
 }
 
 void MergeGPUInfo(GPUInfo* basic_gpu_info,
diff --git a/gpu/config/gpu_info_collector_win.cc b/gpu/config/gpu_info_collector_win.cc
index ca737b9..ed92fee 100644
--- a/gpu/config/gpu_info_collector_win.cc
+++ b/gpu/config/gpu_info_collector_win.cc
@@ -452,7 +452,7 @@
   return found;
 }
 
-bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
   TRACE_EVENT0("gpu", "CollectGraphicsInfo");
 
   DCHECK(gpu_info);
@@ -462,12 +462,13 @@
         CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
     if (requested_implementation_name == "swiftshader") {
       gpu_info->software_rendering = true;
-      return false;
+      return kCollectInfoNonFatalFailure;
     }
   }
 
-  if (!CollectGraphicsInfoGL(gpu_info))
-    return false;
+  CollectInfoResult result = CollectGraphicsInfoGL(gpu_info);
+  if (result != kCollectInfoSuccess)
+    return result;
 
   // ANGLE's renderer strings are of the form:
   // ANGLE (<adapter_identifier> Direct3D<version> vs_x_x ps_x_x)
@@ -517,7 +518,7 @@
     gpu_info->finalized = true;
   }
 
-  return true;
+  return kCollectInfoSuccess;
 }
 
 GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
@@ -549,7 +550,7 @@
   return kGpuIDFailure;
 }
 
-bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
   TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo");
 
   DCHECK(gpu_info);
@@ -590,7 +591,7 @@
   }
 
   if (id.length() <= 20)
-    return false;
+    return kCollectInfoNonFatalFailure;
 
   int vendor_id = 0, device_id = 0;
   base::string16 vendor_id_string = id.substr(8, 4);
@@ -601,7 +602,7 @@
   gpu_info->gpu.device_id = device_id;
   // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
   if (!CollectDriverInfoD3D(id, gpu_info))
-    return false;
+    return kCollectInfoNonFatalFailure;
 
   // Collect basic information about supported D3D11 features. Delay for 45
   // seconds so as not to regress performance tests.
@@ -623,20 +624,20 @@
     }
   }
 
-  return true;
+  return kCollectInfoSuccess;
 }
 
-bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
   TRACE_EVENT0("gpu", "CollectDriverInfoGL");
 
   if (!gpu_info->driver_version.empty())
-    return true;
+    return kCollectInfoSuccess;
 
   std::string gl_version_string = gpu_info->gl_version_string;
 
-  return RE2::PartialMatch(gl_version_string,
-                           "([\\d\\.]+)$",
-                           &gpu_info->driver_version);
+  bool parsed = RE2::PartialMatch(
+      gl_version_string, "([\\d\\.]+)$", &gpu_info->driver_version);
+  return parsed ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
 }
 
 void MergeGPUInfo(GPUInfo* basic_gpu_info,
diff --git a/gpu/config/gpu_info_collector_x11.cc b/gpu/config/gpu_info_collector_x11.cc
index e0374fa..8516918 100644
--- a/gpu/config/gpu_info_collector_x11.cc
+++ b/gpu/config/gpu_info_collector_x11.cc
@@ -77,7 +77,7 @@
   }
   int event_base = 0, error_base = 0;
   if (!XNVCTRLQueryExtension(display, &event_base, &error_base)) {
-    LOG(INFO) << "NVCtrl extension does not exist.";
+    VLOG(1) << "NVCtrl extension does not exist.";
     return std::string();
   }
   int screen_count = ScreenCount(display);
@@ -164,7 +164,7 @@
 
 }  // namespace anonymous
 
-bool CollectContextGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectContextGraphicsInfo(GPUInfo* gpu_info) {
   DCHECK(gpu_info);
 
   TRACE_EVENT0("gpu", "gpu_info_collector::CollectGraphicsInfo");
@@ -183,10 +183,9 @@
 #endif
   }
 
+  CollectInfoResult result = CollectGraphicsInfoGL(gpu_info);
   gpu_info->finalized = true;
-  bool rt = CollectGraphicsInfoGL(gpu_info);
-
-  return rt;
+  return result;
 }
 
 GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
@@ -203,7 +202,7 @@
   return kGpuIDFailure;
 }
 
-bool CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
+CollectInfoResult CollectBasicGraphicsInfo(GPUInfo* gpu_info) {
   DCHECK(gpu_info);
 
   bool rt = CollectPCIVideoCardInfo(gpu_info);
@@ -238,10 +237,10 @@
       break;
   }
 
-  return rt;
+  return rt ? kCollectInfoSuccess : kCollectInfoNonFatalFailure;
 }
 
-bool CollectDriverInfoGL(GPUInfo* gpu_info) {
+CollectInfoResult CollectDriverInfoGL(GPUInfo* gpu_info) {
   DCHECK(gpu_info);
 
   std::string gl_version_string = gpu_info->gl_version_string;
@@ -252,18 +251,18 @@
   // In linux, the gl version string might be in the format of
   //   GLVersion DriverVendor DriverVersion
   if (pieces.size() < 3)
-    return false;
+    return kCollectInfoNonFatalFailure;
 
   std::string driver_version = pieces[2];
   size_t pos = driver_version.find_first_not_of("0123456789.");
   if (pos == 0)
-    return false;
+    return kCollectInfoNonFatalFailure;
   if (pos != std::string::npos)
     driver_version = driver_version.substr(0, pos);
 
   gpu_info->driver_vendor = pieces[1];
   gpu_info->driver_version = driver_version;
-  return true;
+  return kCollectInfoSuccess;
 }
 
 void MergeGPUInfo(GPUInfo* basic_gpu_info,
diff --git a/gpu/config/software_rendering_list_json.cc b/gpu/config/software_rendering_list_json.cc
index 35060a9..e163177 100644
--- a/gpu/config/software_rendering_list_json.cc
+++ b/gpu/config/software_rendering_list_json.cc
@@ -18,7 +18,7 @@
 {
   "name": "software rendering list",
   // Please update the version number whenever you change this file.
-  "version": "7.1",
+  "version": "7.2",
   "entries": [
     {
       "id": 1,
@@ -1032,8 +1032,19 @@
       "features": [
         "accelerated_video_decode"
       ]
+    },
+    {
+      "id": 93,
+      "description": "GLX indirect rendering (X remoting) is not supported",
+      "cr_bugs": [72373],
+      "os": {
+        "type": "linux"
+      },
+      "direct_rendering": false,
+      "features": [
+        "all"
+      ]
     }
-
   ]
 }
 
diff --git a/gpu/disk_cache_proto.target.darwin-arm.mk b/gpu/disk_cache_proto.target.darwin-arm.mk
index f05a89e..d28e7fe 100644
--- a/gpu/disk_cache_proto.target.darwin-arm.mk
+++ b/gpu/disk_cache_proto.target.darwin-arm.mk
@@ -108,6 +108,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -197,6 +198,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/disk_cache_proto.target.darwin-mips.mk b/gpu/disk_cache_proto.target.darwin-mips.mk
index 1672c6d..615d1b9 100644
--- a/gpu/disk_cache_proto.target.darwin-mips.mk
+++ b/gpu/disk_cache_proto.target.darwin-mips.mk
@@ -107,6 +107,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -195,6 +196,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/disk_cache_proto.target.darwin-x86.mk b/gpu/disk_cache_proto.target.darwin-x86.mk
index 6e285e6..a181616 100644
--- a/gpu/disk_cache_proto.target.darwin-x86.mk
+++ b/gpu/disk_cache_proto.target.darwin-x86.mk
@@ -109,6 +109,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -198,6 +199,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/disk_cache_proto.target.darwin-x86_64.mk b/gpu/disk_cache_proto.target.darwin-x86_64.mk
new file mode 100644
index 0000000..84bc0a3
--- /dev/null
+++ b/gpu/disk_cache_proto.target.darwin-x86_64.mk
@@ -0,0 +1,296 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_disk_cache_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "gpu_gpu_gyp_disk_cache_proto_target_genproto":
+# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['command_buffer/service/disk_cache_proto.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'command_buffer/service', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: $(LOCAL_PATH)/gpu/command_buffer/service/disk_cache_proto.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service; cd $(gyp_local_path)/gpu; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h" --proto-in-dir command_buffer/service --proto-in-file "disk_cache_proto$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service" --python_out "$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service"
+
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+.PHONY: gpu_disk_cache_proto_gyp_rule_trigger
+gpu_disk_cache_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/disk_cache_proto.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h \
+	gpu_disk_cache_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_disk_cache_proto_gyp
+
+# Alias gyp target name.
+.PHONY: disk_cache_proto
+disk_cache_proto: gpu_disk_cache_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/disk_cache_proto.target.linux-arm.mk b/gpu/disk_cache_proto.target.linux-arm.mk
index f05a89e..d28e7fe 100644
--- a/gpu/disk_cache_proto.target.linux-arm.mk
+++ b/gpu/disk_cache_proto.target.linux-arm.mk
@@ -108,6 +108,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -197,6 +198,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/disk_cache_proto.target.linux-mips.mk b/gpu/disk_cache_proto.target.linux-mips.mk
index 1672c6d..615d1b9 100644
--- a/gpu/disk_cache_proto.target.linux-mips.mk
+++ b/gpu/disk_cache_proto.target.linux-mips.mk
@@ -107,6 +107,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -195,6 +196,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/disk_cache_proto.target.linux-x86.mk b/gpu/disk_cache_proto.target.linux-x86.mk
index 6e285e6..a181616 100644
--- a/gpu/disk_cache_proto.target.linux-x86.mk
+++ b/gpu/disk_cache_proto.target.linux-x86.mk
@@ -109,6 +109,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -198,6 +199,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/disk_cache_proto.target.linux-x86_64.mk b/gpu/disk_cache_proto.target.linux-x86_64.mk
new file mode 100644
index 0000000..84bc0a3
--- /dev/null
+++ b/gpu/disk_cache_proto.target.linux-x86_64.mk
@@ -0,0 +1,296 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_disk_cache_proto_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "gpu_gpu_gyp_disk_cache_proto_target_genproto":
+# "{'inputs': ['../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['command_buffer/service/disk_cache_proto.proto'], 'action': ['python', '../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'command_buffer/service', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py: $(LOCAL_PATH)/gpu/command_buffer/service/disk_cache_proto.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service; cd $(gyp_local_path)/gpu; python ../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h" --proto-in-dir command_buffer/service --proto-in-file "disk_cache_proto$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service" --python_out "$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service"
+
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py ;
+.PHONY: gpu_disk_cache_proto_gyp_rule_trigger
+gpu_disk_cache_proto_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/disk_cache_proto.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/disk_cache_proto.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/gpu/command_buffer/service/disk_cache_proto_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service/disk_cache_proto.pb.h \
+	gpu_disk_cache_proto_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/gpu/command_buffer/service
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_disk_cache_proto_gyp
+
+# Alias gyp target name.
+.PHONY: disk_cache_proto
+disk_cache_proto: gpu_disk_cache_proto_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gles2_c_lib.target.darwin-arm.mk b/gpu/gles2_c_lib.target.darwin-arm.mk
index 6d1bc4d..d24df6e 100644
--- a/gpu/gles2_c_lib.target.darwin-arm.mk
+++ b/gpu/gles2_c_lib.target.darwin-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_c_lib.target.darwin-mips.mk b/gpu/gles2_c_lib.target.darwin-mips.mk
index bf64ed8..afc5eac 100644
--- a/gpu/gles2_c_lib.target.darwin-mips.mk
+++ b/gpu/gles2_c_lib.target.darwin-mips.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_c_lib.target.darwin-x86.mk b/gpu/gles2_c_lib.target.darwin-x86.mk
index 670df04..51b77a0 100644
--- a/gpu/gles2_c_lib.target.darwin-x86.mk
+++ b/gpu/gles2_c_lib.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +172,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_c_lib.target.darwin-x86_64.mk b/gpu/gles2_c_lib.target.darwin-x86_64.mk
new file mode 100644
index 0000000..0a31fd9
--- /dev/null
+++ b/gpu/gles2_c_lib.target.darwin-x86_64.mk
@@ -0,0 +1,272 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gles2_c_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/gles2_c_lib.cc \
+	gpu/command_buffer/client/gles2_lib.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_C_LIB_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_C_LIB_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gles2_c_lib_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_c_lib
+gles2_c_lib: gpu_gles2_c_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gles2_c_lib.target.linux-arm.mk b/gpu/gles2_c_lib.target.linux-arm.mk
index 6d1bc4d..d24df6e 100644
--- a/gpu/gles2_c_lib.target.linux-arm.mk
+++ b/gpu/gles2_c_lib.target.linux-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_c_lib.target.linux-mips.mk b/gpu/gles2_c_lib.target.linux-mips.mk
index bf64ed8..afc5eac 100644
--- a/gpu/gles2_c_lib.target.linux-mips.mk
+++ b/gpu/gles2_c_lib.target.linux-mips.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_c_lib.target.linux-x86.mk b/gpu/gles2_c_lib.target.linux-x86.mk
index 670df04..51b77a0 100644
--- a/gpu/gles2_c_lib.target.linux-x86.mk
+++ b/gpu/gles2_c_lib.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +172,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGLES2_C_LIB_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_c_lib.target.linux-x86_64.mk b/gpu/gles2_c_lib.target.linux-x86_64.mk
new file mode 100644
index 0000000..0a31fd9
--- /dev/null
+++ b/gpu/gles2_c_lib.target.linux-x86_64.mk
@@ -0,0 +1,272 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gles2_c_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/gles2_c_lib.cc \
+	gpu/command_buffer/client/gles2_lib.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_C_LIB_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_C_LIB_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gles2_c_lib_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_c_lib
+gles2_c_lib: gpu_gles2_c_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gles2_cmd_helper.target.darwin-arm.mk b/gpu/gles2_cmd_helper.target.darwin-arm.mk
index b968657..e339809 100644
--- a/gpu/gles2_cmd_helper.target.darwin-arm.mk
+++ b/gpu/gles2_cmd_helper.target.darwin-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_cmd_helper.target.darwin-mips.mk b/gpu/gles2_cmd_helper.target.darwin-mips.mk
index 7123cbd..c48b044 100644
--- a/gpu/gles2_cmd_helper.target.darwin-mips.mk
+++ b/gpu/gles2_cmd_helper.target.darwin-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_cmd_helper.target.darwin-x86.mk b/gpu/gles2_cmd_helper.target.darwin-x86.mk
index 55c6474..ad0dc05 100644
--- a/gpu/gles2_cmd_helper.target.darwin-x86.mk
+++ b/gpu/gles2_cmd_helper.target.darwin-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_cmd_helper.target.darwin-x86_64.mk b/gpu/gles2_cmd_helper.target.darwin-x86_64.mk
new file mode 100644
index 0000000..3c6fe2b
--- /dev/null
+++ b/gpu/gles2_cmd_helper.target.darwin-x86_64.mk
@@ -0,0 +1,263 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gles2_cmd_helper_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/gles2_cmd_helper.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gles2_cmd_helper_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_cmd_helper
+gles2_cmd_helper: gpu_gles2_cmd_helper_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gles2_cmd_helper.target.linux-arm.mk b/gpu/gles2_cmd_helper.target.linux-arm.mk
index b968657..e339809 100644
--- a/gpu/gles2_cmd_helper.target.linux-arm.mk
+++ b/gpu/gles2_cmd_helper.target.linux-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_cmd_helper.target.linux-mips.mk b/gpu/gles2_cmd_helper.target.linux-mips.mk
index 7123cbd..c48b044 100644
--- a/gpu/gles2_cmd_helper.target.linux-mips.mk
+++ b/gpu/gles2_cmd_helper.target.linux-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_cmd_helper.target.linux-x86.mk b/gpu/gles2_cmd_helper.target.linux-x86.mk
index 55c6474..ad0dc05 100644
--- a/gpu/gles2_cmd_helper.target.linux-x86.mk
+++ b/gpu/gles2_cmd_helper.target.linux-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_cmd_helper.target.linux-x86_64.mk b/gpu/gles2_cmd_helper.target.linux-x86_64.mk
new file mode 100644
index 0000000..3c6fe2b
--- /dev/null
+++ b/gpu/gles2_cmd_helper.target.linux-x86_64.mk
@@ -0,0 +1,263 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gles2_cmd_helper_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/gles2_cmd_helper.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gles2_cmd_helper_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_cmd_helper
+gles2_cmd_helper: gpu_gles2_cmd_helper_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gles2_implementation.target.darwin-arm.mk b/gpu/gles2_implementation.target.darwin-arm.mk
index f09dae9..6fe008b 100644
--- a/gpu/gles2_implementation.target.darwin-arm.mk
+++ b/gpu/gles2_implementation.target.darwin-arm.mk
@@ -100,9 +100,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +109,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_implementation.target.darwin-mips.mk b/gpu/gles2_implementation.target.darwin-mips.mk
index c974c63..0683de0 100644
--- a/gpu/gles2_implementation.target.darwin-mips.mk
+++ b/gpu/gles2_implementation.target.darwin-mips.mk
@@ -99,9 +99,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -223,9 +222,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -234,6 +231,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_implementation.target.darwin-x86.mk b/gpu/gles2_implementation.target.darwin-x86.mk
index 55551f9..88e248f 100644
--- a/gpu/gles2_implementation.target.darwin-x86.mk
+++ b/gpu/gles2_implementation.target.darwin-x86.mk
@@ -101,9 +101,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -112,6 +110,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -226,9 +225,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -237,6 +234,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_implementation.target.darwin-x86_64.mk b/gpu/gles2_implementation.target.darwin-x86_64.mk
new file mode 100644
index 0000000..fcd4899
--- /dev/null
+++ b/gpu/gles2_implementation.target.darwin-x86_64.mk
@@ -0,0 +1,351 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gles2_implementation_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/buffer_tracker.cc \
+	gpu/command_buffer/client/client_context_state.cc \
+	gpu/command_buffer/client/gles2_implementation.cc \
+	gpu/command_buffer/client/gles2_trace_implementation.cc \
+	gpu/command_buffer/client/gpu_memory_buffer_tracker.cc \
+	gpu/command_buffer/client/program_info_manager.cc \
+	gpu/command_buffer/client/query_tracker.cc \
+	gpu/command_buffer/client/share_group.cc \
+	gpu/command_buffer/client/vertex_array_object_manager.cc \
+	gpu/command_buffer/client/gl_in_process_context.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_IMPL_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_IMPL_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_gl_gl_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gles2_implementation_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_implementation
+gles2_implementation: gpu_gles2_implementation_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gles2_implementation.target.linux-arm.mk b/gpu/gles2_implementation.target.linux-arm.mk
index f09dae9..6fe008b 100644
--- a/gpu/gles2_implementation.target.linux-arm.mk
+++ b/gpu/gles2_implementation.target.linux-arm.mk
@@ -100,9 +100,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +109,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_implementation.target.linux-mips.mk b/gpu/gles2_implementation.target.linux-mips.mk
index c974c63..0683de0 100644
--- a/gpu/gles2_implementation.target.linux-mips.mk
+++ b/gpu/gles2_implementation.target.linux-mips.mk
@@ -99,9 +99,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -223,9 +222,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -234,6 +231,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_implementation.target.linux-x86.mk b/gpu/gles2_implementation.target.linux-x86.mk
index 55551f9..88e248f 100644
--- a/gpu/gles2_implementation.target.linux-x86.mk
+++ b/gpu/gles2_implementation.target.linux-x86.mk
@@ -101,9 +101,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -112,6 +110,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -226,9 +225,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -237,6 +234,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gles2_implementation.target.linux-x86_64.mk b/gpu/gles2_implementation.target.linux-x86_64.mk
new file mode 100644
index 0000000..fcd4899
--- /dev/null
+++ b/gpu/gles2_implementation.target.linux-x86_64.mk
@@ -0,0 +1,351 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gles2_implementation_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/command_buffer/client/buffer_tracker.cc \
+	gpu/command_buffer/client/client_context_state.cc \
+	gpu/command_buffer/client/gles2_implementation.cc \
+	gpu/command_buffer/client/gles2_trace_implementation.cc \
+	gpu/command_buffer/client/gpu_memory_buffer_tracker.cc \
+	gpu/command_buffer/client/program_info_manager.cc \
+	gpu/command_buffer/client/query_tracker.cc \
+	gpu/command_buffer/client/share_group.cc \
+	gpu/command_buffer/client/vertex_array_object_manager.cc \
+	gpu/command_buffer/client/gl_in_process_context.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_IMPL_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGLES2_IMPL_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_gl_gl_gyp \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gles2_implementation_gyp
+
+# Alias gyp target name.
+.PHONY: gles2_implementation
+gles2_implementation: gpu_gles2_implementation_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu.target.darwin-arm.mk b/gpu/gpu.target.darwin-arm.mk
index 23d4673..eb9f615 100644
--- a/gpu/gpu.target.darwin-arm.mk
+++ b/gpu/gpu.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu.target.darwin-mips.mk b/gpu/gpu.target.darwin-mips.mk
index 3461529..257efce 100644
--- a/gpu/gpu.target.darwin-mips.mk
+++ b/gpu/gpu.target.darwin-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu.target.darwin-x86.mk b/gpu/gpu.target.darwin-x86.mk
index e256451..05991c6 100644
--- a/gpu/gpu.target.darwin-x86.mk
+++ b/gpu/gpu.target.darwin-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu.target.darwin-x86_64.mk b/gpu/gpu.target.darwin-x86_64.mk
new file mode 100644
index 0000000..11db667
--- /dev/null
+++ b/gpu/gpu.target.darwin-x86_64.mk
@@ -0,0 +1,236 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := gpu_gpu_gyp
+LOCAL_MODULE_STEM := gpu
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_client_gyp)/gpu_command_buffer_client_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: gpu
+gpu: gpu_gpu_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/gpu/gpu.target.linux-arm.mk b/gpu/gpu.target.linux-arm.mk
index 23d4673..eb9f615 100644
--- a/gpu/gpu.target.linux-arm.mk
+++ b/gpu/gpu.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu.target.linux-mips.mk b/gpu/gpu.target.linux-mips.mk
index 3461529..257efce 100644
--- a/gpu/gpu.target.linux-mips.mk
+++ b/gpu/gpu.target.linux-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu.target.linux-x86.mk b/gpu/gpu.target.linux-x86.mk
index e256451..05991c6 100644
--- a/gpu/gpu.target.linux-x86.mk
+++ b/gpu/gpu.target.linux-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu.target.linux-x86_64.mk b/gpu/gpu.target.linux-x86_64.mk
new file mode 100644
index 0000000..11db667
--- /dev/null
+++ b/gpu/gpu.target.linux-x86_64.mk
@@ -0,0 +1,236 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := gpu_gpu_gyp
+LOCAL_MODULE_STEM := gpu
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_client_gyp)/gpu_command_buffer_client_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_common_gyp)/gpu_command_buffer_common_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_command_buffer_service_gyp)/gpu_command_buffer_service_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gles2_cmd_helper_gyp)/gpu_gles2_cmd_helper_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_config_gyp)/gpu_gpu_config_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,gpu_gpu_ipc_gyp)/gpu_gpu_ipc_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: gpu
+gpu: gpu_gpu_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/gpu/gpu_config.target.darwin-arm.mk b/gpu/gpu_config.target.darwin-arm.mk
index 99d8453..6446b06 100644
--- a/gpu/gpu_config.target.darwin-arm.mk
+++ b/gpu/gpu_config.target.darwin-arm.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -186,6 +187,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_config.target.darwin-mips.mk b/gpu/gpu_config.target.darwin-mips.mk
index ace0802..41c6b9c 100644
--- a/gpu/gpu_config.target.darwin-mips.mk
+++ b/gpu/gpu_config.target.darwin-mips.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -184,6 +185,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_config.target.darwin-x86.mk b/gpu/gpu_config.target.darwin-x86.mk
index c01b204..6876bdb 100644
--- a/gpu/gpu_config.target.darwin-x86.mk
+++ b/gpu/gpu_config.target.darwin-x86.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_config.target.darwin-x86_64.mk b/gpu/gpu_config.target.darwin-x86_64.mk
new file mode 100644
index 0000000..8ca1921
--- /dev/null
+++ b/gpu/gpu_config.target.darwin-x86_64.mk
@@ -0,0 +1,292 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_config_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/config/dx_diag_node.cc \
+	gpu/config/gpu_blacklist.cc \
+	gpu/config/gpu_control_list.cc \
+	gpu/config/gpu_driver_bug_list_json.cc \
+	gpu/config/gpu_driver_bug_list.cc \
+	gpu/config/gpu_info.cc \
+	gpu/config/gpu_info_collector_android.cc \
+	gpu/config/gpu_info_collector.cc \
+	gpu/config/gpu_test_config.cc \
+	gpu/config/gpu_test_expectations_parser.cc \
+	gpu/config/gpu_util.cc \
+	gpu/config/software_rendering_list_json.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_config_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_config
+gpu_config: gpu_gpu_config_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu_config.target.linux-arm.mk b/gpu/gpu_config.target.linux-arm.mk
index 99d8453..6446b06 100644
--- a/gpu/gpu_config.target.linux-arm.mk
+++ b/gpu/gpu_config.target.linux-arm.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -186,6 +187,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_config.target.linux-mips.mk b/gpu/gpu_config.target.linux-mips.mk
index ace0802..41c6b9c 100644
--- a/gpu/gpu_config.target.linux-mips.mk
+++ b/gpu/gpu_config.target.linux-mips.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -184,6 +185,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_config.target.linux-x86.mk b/gpu/gpu_config.target.linux-x86.mk
index c01b204..6876bdb 100644
--- a/gpu/gpu_config.target.linux-x86.mk
+++ b/gpu/gpu_config.target.linux-x86.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -187,6 +188,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_config.target.linux-x86_64.mk b/gpu/gpu_config.target.linux-x86_64.mk
new file mode 100644
index 0000000..8ca1921
--- /dev/null
+++ b/gpu/gpu_config.target.linux-x86_64.mk
@@ -0,0 +1,292 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_config_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/config/dx_diag_node.cc \
+	gpu/config/gpu_blacklist.cc \
+	gpu/config/gpu_control_list.cc \
+	gpu/config/gpu_driver_bug_list_json.cc \
+	gpu/config/gpu_driver_bug_list.cc \
+	gpu/config/gpu_info.cc \
+	gpu/config/gpu_info_collector_android.cc \
+	gpu/config/gpu_info_collector.cc \
+	gpu/config/gpu_test_config.cc \
+	gpu/config/gpu_test_expectations_parser.cc \
+	gpu/config/gpu_util.cc \
+	gpu/config/software_rendering_list_json.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_config_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_config
+gpu_config: gpu_gpu_config_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu_ipc.target.darwin-arm.mk b/gpu/gpu_ipc.target.darwin-arm.mk
index 35b1c44..d196119 100644
--- a/gpu/gpu_ipc.target.darwin-arm.mk
+++ b/gpu/gpu_ipc.target.darwin-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_ipc.target.darwin-mips.mk b/gpu/gpu_ipc.target.darwin-mips.mk
index d24b5a3..8d1c9b5 100644
--- a/gpu/gpu_ipc.target.darwin-mips.mk
+++ b/gpu/gpu_ipc.target.darwin-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_ipc.target.darwin-x86.mk b/gpu/gpu_ipc.target.darwin-x86.mk
index 218b1c1..1fdbe80 100644
--- a/gpu/gpu_ipc.target.darwin-x86.mk
+++ b/gpu/gpu_ipc.target.darwin-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_ipc.target.darwin-x86_64.mk b/gpu/gpu_ipc.target.darwin-x86_64.mk
new file mode 100644
index 0000000..603b028
--- /dev/null
+++ b/gpu/gpu_ipc.target.darwin-x86_64.mk
@@ -0,0 +1,264 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_ipc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/ipc/gpu_command_buffer_traits.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_ipc_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_ipc
+gpu_ipc: gpu_gpu_ipc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/gpu_ipc.target.linux-arm.mk b/gpu/gpu_ipc.target.linux-arm.mk
index 35b1c44..d196119 100644
--- a/gpu/gpu_ipc.target.linux-arm.mk
+++ b/gpu/gpu_ipc.target.linux-arm.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_ipc.target.linux-mips.mk b/gpu/gpu_ipc.target.linux-mips.mk
index d24b5a3..8d1c9b5 100644
--- a/gpu/gpu_ipc.target.linux-mips.mk
+++ b/gpu/gpu_ipc.target.linux-mips.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_ipc.target.linux-x86.mk b/gpu/gpu_ipc.target.linux-x86.mk
index 218b1c1..1fdbe80 100644
--- a/gpu/gpu_ipc.target.linux-x86.mk
+++ b/gpu/gpu_ipc.target.linux-x86.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/gpu_ipc.target.linux-x86_64.mk b/gpu/gpu_ipc.target.linux-x86_64.mk
new file mode 100644
index 0000000..603b028
--- /dev/null
+++ b/gpu/gpu_ipc.target.linux-x86_64.mk
@@ -0,0 +1,264 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_gpu_ipc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_khronos_khronos_headers_gyp)/khronos_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/ipc/gpu_command_buffer_traits.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_gpu_ipc_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_ipc
+gpu_ipc: gpu_gpu_ipc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.darwin-arm.mk b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-arm.mk
index ba357b1..85d7973 100644
--- a/gpu/skia_bindings/gpu_skia_bindings.target.darwin-arm.mk
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -97,6 +95,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -204,9 +203,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -214,6 +211,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.darwin-mips.mk b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-mips.mk
index 4ed1ec4..c9c1a4d 100644
--- a/gpu/skia_bindings/gpu_skia_bindings.target.darwin-mips.mk
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -96,6 +94,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -202,9 +201,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -212,6 +209,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86.mk b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86.mk
index a4ec3ca..701a5fd 100644
--- a/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86.mk
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -98,6 +96,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -205,9 +204,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -215,6 +212,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86_64.mk b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86_64.mk
new file mode 100644
index 0000000..43582f4
--- /dev/null
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.darwin-x86_64.mk
@@ -0,0 +1,324 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_skia_bindings_gpu_skia_bindings_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_skia_bindings_gpu_skia_bindings_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_skia_bindings
+gpu_skia_bindings: gpu_skia_bindings_gpu_skia_bindings_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.linux-arm.mk b/gpu/skia_bindings/gpu_skia_bindings.target.linux-arm.mk
index ba357b1..85d7973 100644
--- a/gpu/skia_bindings/gpu_skia_bindings.target.linux-arm.mk
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.linux-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -97,6 +95,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -204,9 +203,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -214,6 +211,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.linux-mips.mk b/gpu/skia_bindings/gpu_skia_bindings.target.linux-mips.mk
index 4ed1ec4..c9c1a4d 100644
--- a/gpu/skia_bindings/gpu_skia_bindings.target.linux-mips.mk
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.linux-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -96,6 +94,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -202,9 +201,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -212,6 +209,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86.mk b/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86.mk
index a4ec3ca..701a5fd 100644
--- a/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86.mk
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -98,6 +96,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -205,9 +204,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -215,6 +212,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86_64.mk b/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86_64.mk
new file mode 100644
index 0000000..43582f4
--- /dev/null
+++ b/gpu/skia_bindings/gpu_skia_bindings.target.linux-x86_64.mk
@@ -0,0 +1,324 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := gpu_skia_bindings_gpu_skia_bindings_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	gpu/skia_bindings/gl_bindings_skia_cmd_buffer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: gpu_skia_bindings_gpu_skia_bindings_gyp
+
+# Alias gyp target name.
+.PHONY: gpu_skia_bindings
+gpu_skia_bindings: gpu_skia_bindings_gpu_skia_bindings_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ipc/ipc.target.darwin-arm.mk b/ipc/ipc.target.darwin-arm.mk
index a412e09..21ed6c2 100644
--- a/ipc/ipc.target.darwin-arm.mk
+++ b/ipc/ipc.target.darwin-arm.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
diff --git a/ipc/ipc.target.darwin-mips.mk b/ipc/ipc.target.darwin-mips.mk
index 1402a20..9f8985c 100644
--- a/ipc/ipc.target.darwin-mips.mk
+++ b/ipc/ipc.target.darwin-mips.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
diff --git a/ipc/ipc.target.darwin-x86.mk b/ipc/ipc.target.darwin-x86.mk
index 383525e..622c94d 100644
--- a/ipc/ipc.target.darwin-x86.mk
+++ b/ipc/ipc.target.darwin-x86.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
diff --git a/ipc/ipc.target.darwin-x86_64.mk b/ipc/ipc.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4aa928c
--- /dev/null
+++ b/ipc/ipc.target.darwin-x86_64.mk
@@ -0,0 +1,276 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ipc_ipc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ipc/file_descriptor_set_posix.cc \
+	ipc/ipc_channel.cc \
+	ipc/ipc_channel_factory.cc \
+	ipc/ipc_channel_posix.cc \
+	ipc/ipc_channel_proxy.cc \
+	ipc/ipc_channel_reader.cc \
+	ipc/ipc_forwarding_message_filter.cc \
+	ipc/ipc_logging.cc \
+	ipc/ipc_message.cc \
+	ipc/ipc_message_utils.cc \
+	ipc/ipc_platform_file.cc \
+	ipc/ipc_switches.cc \
+	ipc/ipc_sync_channel.cc \
+	ipc/ipc_sync_message.cc \
+	ipc/ipc_sync_message_filter.cc \
+	ipc/unix_domain_socket_util.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DIPC_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DIPC_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ipc_ipc_gyp
+
+# Alias gyp target name.
+.PHONY: ipc
+ipc: ipc_ipc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ipc/ipc.target.linux-arm.mk b/ipc/ipc.target.linux-arm.mk
index a412e09..21ed6c2 100644
--- a/ipc/ipc.target.linux-arm.mk
+++ b/ipc/ipc.target.linux-arm.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
diff --git a/ipc/ipc.target.linux-mips.mk b/ipc/ipc.target.linux-mips.mk
index 1402a20..9f8985c 100644
--- a/ipc/ipc.target.linux-mips.mk
+++ b/ipc/ipc.target.linux-mips.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
diff --git a/ipc/ipc.target.linux-x86.mk b/ipc/ipc.target.linux-x86.mk
index 383525e..622c94d 100644
--- a/ipc/ipc.target.linux-x86.mk
+++ b/ipc/ipc.target.linux-x86.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DIPC_IMPLEMENTATION' \
diff --git a/ipc/ipc.target.linux-x86_64.mk b/ipc/ipc.target.linux-x86_64.mk
new file mode 100644
index 0000000..4aa928c
--- /dev/null
+++ b/ipc/ipc.target.linux-x86_64.mk
@@ -0,0 +1,276 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ipc_ipc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ipc/file_descriptor_set_posix.cc \
+	ipc/ipc_channel.cc \
+	ipc/ipc_channel_factory.cc \
+	ipc/ipc_channel_posix.cc \
+	ipc/ipc_channel_proxy.cc \
+	ipc/ipc_channel_reader.cc \
+	ipc/ipc_forwarding_message_filter.cc \
+	ipc/ipc_logging.cc \
+	ipc/ipc_message.cc \
+	ipc/ipc_message_utils.cc \
+	ipc/ipc_platform_file.cc \
+	ipc/ipc_switches.cc \
+	ipc/ipc_sync_channel.cc \
+	ipc/ipc_sync_message.cc \
+	ipc/ipc_sync_message_filter.cc \
+	ipc/unix_domain_socket_util.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DIPC_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DIPC_IMPLEMENTATION' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ipc_ipc_gyp
+
+# Alias gyp target name.
+.PHONY: ipc
+ipc: ipc_ipc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ipc/ipc_platform_file.h b/ipc/ipc_platform_file.h
index 8fb1a39..95b66b7 100644
--- a/ipc/ipc_platform_file.h
+++ b/ipc/ipc_platform_file.h
@@ -40,6 +40,15 @@
 #endif
 }
 
+inline base::File PlatformFileForTransitToFile(
+    const PlatformFileForTransit& transit) {
+#if defined(OS_WIN)
+  return base::File(transit);
+#elif defined(OS_POSIX)
+  return base::File(transit.fd);
+#endif
+}
+
 // Returns a file handle equivalent to |file| that can be used in |process|.
 IPC_EXPORT PlatformFileForTransit GetFileHandleForProcess(
     base::PlatformFile file,
diff --git a/jingle/jingle.gyp b/jingle/jingle.gyp
index b2e9f76..8ccda5d 100644
--- a/jingle/jingle.gyp
+++ b/jingle/jingle.gyp
@@ -3,6 +3,9 @@
 # found in the LICENSE file.
 
 {
+  'includes': [
+    'jingle.gypi',
+  ],
   'variables': {
     'chromium_code': 1,
   },  # variables
@@ -14,25 +17,7 @@
           'target_name': 'jingle_glue',
           'type': 'static_library',
           'sources': [
-            'glue/channel_socket_adapter.cc',
-            'glue/channel_socket_adapter.h',
-            'glue/chrome_async_socket.cc',
-            'glue/chrome_async_socket.h',
-            'glue/fake_ssl_client_socket.cc',
-            'glue/fake_ssl_client_socket.h',
-            'glue/proxy_resolving_client_socket.cc',
-            'glue/proxy_resolving_client_socket.h',
-            'glue/pseudotcp_adapter.cc',
-            'glue/pseudotcp_adapter.h',
-            'glue/resolving_client_socket_factory.h',
-            'glue/task_pump.cc',
-            'glue/task_pump.h',
-            'glue/thread_wrapper.cc',
-            'glue/thread_wrapper.h',
-            'glue/utils.cc',
-            'glue/utils.h',
-            'glue/xmpp_client_socket_factory.cc',
-            'glue/xmpp_client_socket_factory.h',
+            '<@(jingle_glue_sources)',
           ],
           'dependencies': [
             '../base/base.gyp:base',
diff --git a/jingle/jingle.gypi b/jingle/jingle.gypi
new file mode 100644
index 0000000..eb74bbc
--- /dev/null
+++ b/jingle/jingle.gypi
@@ -0,0 +1,29 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'jingle_glue_sources': [
+      'glue/channel_socket_adapter.cc',
+      'glue/channel_socket_adapter.h',
+      'glue/chrome_async_socket.cc',
+      'glue/chrome_async_socket.h',
+      'glue/fake_ssl_client_socket.cc',
+      'glue/fake_ssl_client_socket.h',
+      'glue/proxy_resolving_client_socket.cc',
+      'glue/proxy_resolving_client_socket.h',
+      'glue/pseudotcp_adapter.cc',
+      'glue/pseudotcp_adapter.h',
+      'glue/resolving_client_socket_factory.h',
+      'glue/task_pump.cc',
+      'glue/task_pump.h',
+      'glue/thread_wrapper.cc',
+      'glue/thread_wrapper.h',
+      'glue/utils.cc',
+      'glue/utils.h',
+      'glue/xmpp_client_socket_factory.cc',
+      'glue/xmpp_client_socket_factory.h',
+    ]
+  }
+}
diff --git a/jingle/jingle_glue.target.darwin-x86_64.mk b/jingle/jingle_glue.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d8b7bf9
--- /dev/null
+++ b/jingle/jingle_glue.target.darwin-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := jingle_jingle_glue_gyp
+LOCAL_MODULE_STEM := jingle_glue
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: jingle_jingle_glue_gyp
+
+# Alias gyp target name.
+.PHONY: jingle_glue
+jingle_glue: jingle_jingle_glue_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/jingle/jingle_glue.target.linux-x86_64.mk b/jingle/jingle_glue.target.linux-x86_64.mk
new file mode 100644
index 0000000..d8b7bf9
--- /dev/null
+++ b/jingle/jingle_glue.target.linux-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := jingle_jingle_glue_gyp
+LOCAL_MODULE_STEM := jingle_glue
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: jingle_jingle_glue_gyp
+
+# Alias gyp target name.
+.PHONY: jingle_glue
+jingle_glue: jingle_jingle_glue_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/jingle/jingle_nacl.gyp b/jingle/jingle_nacl.gyp
new file mode 100644
index 0000000..13f9ff1
--- /dev/null
+++ b/jingle/jingle_nacl.gyp
@@ -0,0 +1,38 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'includes': [
+    '../native_client/build/untrusted.gypi',
+    'jingle.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'jingle_glue_nacl',
+      'type': 'none',
+      'variables': {
+        'nacl_untrusted_build': 1,
+        'nlib_target': 'libjingle_glue_nacl.a',
+        'build_glibc': 0,
+        'build_newlib': 0,
+        'build_pnacl_newlib': 1,
+      },
+      'sources': [
+        '<@(jingle_glue_sources)',
+      ],
+      'dependencies': [
+        '../base/base_nacl.gyp:base_nacl',
+        '../native_client/tools.gyp:prep_toolchain',
+        '../net/net_nacl.gyp:net_nacl',
+        '../third_party/libjingle/libjingle_nacl.gyp:libjingle_nacl',
+      ],
+      'export_dependent_settings': [
+        '../third_party/libjingle/libjingle_nacl.gyp:libjingle_nacl',
+      ],
+    }
+  ]
+}
diff --git a/media/audio/audio_input_controller.cc b/media/audio/audio_input_controller.cc
index 7cac8a7..ef2c4a9 100644
--- a/media/audio/audio_input_controller.cc
+++ b/media/audio/audio_input_controller.cc
@@ -18,6 +18,8 @@
 // to resolve http://crbug.com/79936 for Windows platforms.  This then caused
 // breakage (very hard to repro bugs!) on other platforms: See
 // http://crbug.com/226327 and http://crbug.com/230972.
+// See also that the timer has been disabled on Mac now due to
+// crbug.com/357501.
 const int kTimerResetIntervalSeconds = 1;
 // We have received reports that the timer can be too trigger happy on some
 // Mac devices and the initial timer interval has therefore been increased
@@ -199,6 +201,13 @@
   }
 
   DCHECK(!no_data_timer_.get());
+
+#if defined(OS_MACOSX)
+  // This is a fix for crbug.com/357501.  The timer can trigger when closing
+  // the lid on Macs, which causes more problems than the timer fixes.
+  enable_nodata_timer = false;
+#endif
+
   if (enable_nodata_timer) {
     // Create the data timer which will call DoCheckForNoData(). The timer
     // is started in DoRecord() and restarted in each DoCheckForNoData()
diff --git a/media/audio/audio_input_controller_unittest.cc b/media/audio/audio_input_controller_unittest.cc
index d5b5039..2673cd2 100644
--- a/media/audio/audio_input_controller_unittest.cc
+++ b/media/audio/audio_input_controller_unittest.cc
@@ -145,7 +145,14 @@
 // Test that the AudioInputController reports an error when the input stream
 // stops. This can happen when the underlying audio layer stops feeding data as
 // a result of a removed microphone device.
-TEST_F(AudioInputControllerTest, RecordAndError) {
+#if defined(OS_MACOSX)
+// Disabled on Mac due to crbug.com/357501.
+// TODO(tommi): Remove the test when the timer workaround has been removed.
+#define MAYBE_RecordAndError DISABLED_RecordAndError
+#else
+#define MAYBE_RecordAndError RecordAndError
+#endif
+TEST_F(AudioInputControllerTest, MAYBE_RecordAndError) {
   MockAudioInputControllerEventHandler event_handler;
   int count = 0;
 
diff --git a/media/audio/audio_manager_base.cc b/media/audio/audio_manager_base.cc
index 6bd927f..eab950d 100644
--- a/media/audio/audio_manager_base.cc
+++ b/media/audio/audio_manager_base.cc
@@ -334,22 +334,10 @@
 
 void AudioManagerBase::ShutdownOnAudioThread() {
   DCHECK(task_runner_->BelongsToCurrentThread());
-
-  AudioOutputDispatchers::iterator it = output_dispatchers_.begin();
-  for (; it != output_dispatchers_.end(); ++it) {
-    scoped_refptr<AudioOutputDispatcher>& dispatcher = (*it)->dispatcher;
-    dispatcher->Shutdown();
-
-    // All AudioOutputProxies must have been freed before Shutdown is called.
-    // If they still exist, things will go bad.  They have direct pointers to
-    // both physical audio stream objects that belong to the dispatcher as
-    // well as the message loop of the audio thread that will soon go away.
-    // So, better crash now than later.
-    DCHECK(dispatcher->HasOneRef()) << "AudioOutputProxies are still alive";
-    dispatcher = NULL;
+  while (!output_dispatchers_.empty()) {
+    output_dispatchers_.back()->dispatcher->Shutdown();
+    output_dispatchers_.pop_back();
   }
-
-  output_dispatchers_.clear();
 }
 
 void AudioManagerBase::AddOutputDeviceChangeListener(
diff --git a/media/audio/audio_output_dispatcher_impl.cc b/media/audio/audio_output_dispatcher_impl.cc
index 5db170e..4989900 100644
--- a/media/audio/audio_output_dispatcher_impl.cc
+++ b/media/audio/audio_output_dispatcher_impl.cc
@@ -124,6 +124,10 @@
   // Close all idle streams immediately.  The |close_timer_| will handle
   // invalidating any outstanding tasks upon its destruction.
   CloseAllIdleStreams();
+
+  // No AudioOutputProxy objects should hold a reference to us when we get
+  // to this stage.
+  DCHECK(HasOneRef()) << "Only the AudioManager should hold a reference";
 }
 
 bool AudioOutputDispatcherImpl::CreateAndOpenStream() {
diff --git a/media/audio/mac/audio_manager_mac.cc b/media/audio/mac/audio_manager_mac.cc
index 6db1ed4..60c8a3e 100644
--- a/media/audio/mac/audio_manager_mac.cc
+++ b/media/audio/mac/audio_manager_mac.cc
@@ -210,6 +210,18 @@
   return audio_device_id;
 }
 
+template <class T>
+void StopStreams(std::list<T*>* streams) {
+  for (typename std::list<T*>::iterator it = streams->begin();
+       it != streams->end();
+       ++it) {
+    // Stop() is safe to call multiple times, so it doesn't matter if a stream
+    // has already been stopped.
+    (*it)->Stop();
+  }
+  streams->clear();
+}
+
 class AudioManagerMac::AudioPowerObserver : public base::PowerObserver {
  public:
   AudioPowerObserver()
@@ -581,7 +593,9 @@
     current_sample_rate_ = params.sample_rate();
   }
 
-  return new AUHALStream(this, params, device);
+  AudioOutputStream* stream = new AUHALStream(this, params, device);
+  output_streams_.push_back(stream);
+  return stream;
 }
 
 std::string AudioManagerMac::GetDefaultOutputDeviceID() {
@@ -614,7 +628,9 @@
 AudioInputStream* AudioManagerMac::MakeLinearInputStream(
     const AudioParameters& params, const std::string& device_id) {
   DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
-  return new PCMQueueInAudioInputStream(this, params);
+  AudioInputStream* stream = new PCMQueueInAudioInputStream(this, params);
+  input_streams_.push_back(stream);
+  return stream;
 }
 
 AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream(
@@ -637,6 +653,7 @@
             params);
     stream = new AUAudioInputStream(this, params, output_params,
         audio_device_id);
+    input_streams_.push_back(stream);
   }
 
   return stream;
@@ -700,6 +717,18 @@
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
   output_device_listener_.reset();
   power_observer_.reset();
+
+  // Since CoreAudio calls have to run on the UI thread and browser shutdown
+  // doesn't wait for outstanding tasks to complete, we may have input/output
+  // streams still running at shutdown.
+  //
+  // To avoid calls into destructed classes, we need to stop the OS callbacks
+  // by stopping the streams.  Note: The streams are leaked since process
+  // destruction is imminent.
+  //
+  // See http://crbug.com/354139 for crash details.
+  StopStreams(&input_streams_);
+  StopStreams(&output_streams_);
 }
 
 void AudioManagerMac::HandleDeviceChanges() {
@@ -739,6 +768,16 @@
   return power_observer_->ShouldDeferOutputStreamStart();
 }
 
+void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) {
+  output_streams_.remove(stream);
+  AudioManagerBase::ReleaseOutputStream(stream);
+}
+
+void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) {
+  input_streams_.remove(stream);
+  AudioManagerBase::ReleaseInputStream(stream);
+}
+
 AudioManager* CreateAudioManager(AudioLogFactory* audio_log_factory) {
   return new AudioManagerMac(audio_log_factory);
 }
diff --git a/media/audio/mac/audio_manager_mac.h b/media/audio/mac/audio_manager_mac.h
index 48f18ec..7cc1a63 100644
--- a/media/audio/mac/audio_manager_mac.h
+++ b/media/audio/mac/audio_manager_mac.h
@@ -6,6 +6,7 @@
 #define MEDIA_AUDIO_MAC_AUDIO_MANAGER_MAC_H_
 
 #include <CoreAudio/AudioHardware.h>
+#include <list>
 #include <string>
 
 #include "base/basictypes.h"
@@ -46,6 +47,10 @@
       const AudioParameters& params, const std::string& device_id) OVERRIDE;
   virtual std::string GetDefaultOutputDeviceID() OVERRIDE;
 
+  // Used to track destruction of input and output streams.
+  virtual void ReleaseOutputStream(AudioOutputStream* stream) OVERRIDE;
+  virtual void ReleaseInputStream(AudioInputStream* stream) OVERRIDE;
+
   static bool GetDefaultInputDevice(AudioDeviceID* device);
   static bool GetDefaultOutputDevice(AudioDeviceID* device);
   static bool GetDefaultDevice(AudioDeviceID* device, bool input);
@@ -100,6 +105,11 @@
   class AudioPowerObserver;
   scoped_ptr<AudioPowerObserver> power_observer_;
 
+  // Tracks all constructed input and output streams so they can be stopped at
+  // shutdown.  See ShutdownOnAudioThread() for more details.
+  std::list<AudioInputStream*> input_streams_;
+  std::list<AudioOutputStream*> output_streams_;
+
   DISALLOW_COPY_AND_ASSIGN(AudioManagerMac);
 };
 
diff --git a/media/audio/sounds/sounds_manager.cc b/media/audio/sounds/sounds_manager.cc
index bc86c96..bec8622 100644
--- a/media/audio/sounds/sounds_manager.cc
+++ b/media/audio/sounds/sounds_manager.cc
@@ -79,43 +79,6 @@
   return wav_audio.params().GetBufferDuration();
 }
 
-// SoundsManagerStub ---------------------------------------------------
-
-class SoundsManagerStub : public SoundsManager {
- public:
-  SoundsManagerStub();
-  virtual ~SoundsManagerStub();
-
-  // SoundsManager implementation:
-  virtual bool Initialize(SoundKey key,
-                          const base::StringPiece& data) OVERRIDE;
-  virtual bool Play(SoundKey key) OVERRIDE;
-  virtual base::TimeDelta GetDuration(SoundKey key) OVERRIDE;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SoundsManagerStub);
-};
-
-SoundsManagerStub::SoundsManagerStub() {}
-
-SoundsManagerStub::~SoundsManagerStub() { DCHECK(CalledOnValidThread()); }
-
-bool SoundsManagerStub::Initialize(SoundKey /* key */,
-                                   const base::StringPiece& /* data */) {
-  DCHECK(CalledOnValidThread());
-  return false;
-}
-
-bool SoundsManagerStub::Play(SoundKey /* key */) {
-  DCHECK(CalledOnValidThread());
-  return false;
-}
-
-base::TimeDelta SoundsManagerStub::GetDuration(SoundKey /* key */) {
-  DCHECK(CalledOnValidThread());
-  return base::TimeDelta();
-}
-
 }  // namespace
 
 SoundsManager::SoundsManager() {}
@@ -128,13 +91,7 @@
       << "SoundsManager::Create() is called twice";
   if (g_initialized_for_testing)
     return;
-
-  const bool enabled = !CommandLine::ForCurrentProcess()->HasSwitch(
-                            ::switches::kDisableSystemSoundsManager);
-  if (enabled)
-    g_instance = new SoundsManagerImpl();
-  else
-    g_instance = new SoundsManagerStub();
+  g_instance = new SoundsManagerImpl();
 }
 
 // static
diff --git a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
index 29181ff..3f15061 100644
--- a/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
+++ b/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java
@@ -398,7 +398,12 @@
 
     @CalledByNative
     private void releaseOutputBuffer(int index, boolean render) {
-        mMediaCodec.releaseOutputBuffer(index, render);
+        try {
+            mMediaCodec.releaseOutputBuffer(index, render);
+        } catch(IllegalStateException e) {
+            // TODO(qinmin): May need to report the error to the caller. crbug.com/356498.
+            Log.e(TAG, "Failed to release output buffer", e);
+        }
     }
 
     @CalledByNative
diff --git a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java
index 08d572e..a6cb24b 100644
--- a/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java
+++ b/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java
@@ -11,6 +11,7 @@
 import android.hardware.usb.UsbInterface;
 import android.hardware.usb.UsbManager;
 import android.hardware.usb.UsbRequest;
+import android.os.Handler;
 import android.util.SparseArray;
 
 import org.chromium.base.CalledByNative;
@@ -29,7 +30,7 @@
     /**
      * A connection handle for this device.
      */
-    private UsbDeviceConnection mConnection;
+    private final UsbDeviceConnection mConnection;
 
     /**
      * A map from endpoint number to UsbEndpoint.
@@ -42,6 +43,21 @@
     private final Map<UsbEndpoint, UsbRequest> mRequestMap;
 
     /**
+     * The handler used for posting events on the main thread.
+     */
+    private final Handler mHandler;
+
+    /**
+     * True if this device is closed.
+     */
+    private boolean mIsClosed;
+
+    /**
+     * The identifier of this device.
+     */
+    private long mNativePointer;
+
+    /**
      * Audio interface subclass code for MIDI.
      */
     static final int MIDI_SUBCLASS = 3;
@@ -55,6 +71,9 @@
         mConnection = manager.openDevice(device);
         mEndpointMap = new SparseArray<UsbEndpoint>();
         mRequestMap = new HashMap<UsbEndpoint, UsbRequest>();
+        mHandler = new Handler();
+        mIsClosed = false;
+        mNativePointer = 0;
 
         for (int i = 0; i < device.getInterfaceCount(); ++i) {
             UsbInterface iface = device.getInterface(i);
@@ -70,6 +89,89 @@
                 }
             }
         }
+        // Start listening for input endpoints.
+        // This function will create and run a thread if there is USB-MIDI endpoints in the
+        // device. Note that because UsbMidiDevice is shared among all tabs and the thread
+        // will be terminated when the device is disconnected, at most one thread can be created
+        // for each connected USB-MIDI device.
+        startListen(device);
+    }
+
+    /**
+     * Starts listening for input endpoints.
+     */
+    private void startListen(final UsbDevice device) {
+        final Map<UsbEndpoint, ByteBuffer> bufferForEndpoints =
+            new HashMap<UsbEndpoint, ByteBuffer>();
+
+        for (int i = 0; i < device.getInterfaceCount(); ++i) {
+            UsbInterface iface = device.getInterface(i);
+            if (iface.getInterfaceClass() != UsbConstants.USB_CLASS_AUDIO ||
+                iface.getInterfaceSubclass() != MIDI_SUBCLASS) {
+                continue;
+            }
+            for (int j = 0; j < iface.getEndpointCount(); ++j) {
+                UsbEndpoint endpoint = iface.getEndpoint(j);
+                if (endpoint.getDirection() == UsbConstants.USB_DIR_IN) {
+                    ByteBuffer buffer = ByteBuffer.allocate(endpoint.getMaxPacketSize());
+                    UsbRequest request = new UsbRequest();
+                    request.initialize(mConnection, endpoint);
+                    request.queue(buffer, buffer.remaining());
+                    bufferForEndpoints.put(endpoint, buffer);
+                }
+            }
+        }
+        if (bufferForEndpoints.isEmpty()) {
+            return;
+        }
+        // bufferForEndpoints must not be accessed hereafter on this thread.
+        new Thread() {
+            public void run() {
+                while (true) {
+                    UsbRequest request = mConnection.requestWait();
+                    if (request == null) {
+                        // When the device is closed requestWait will fail.
+                        break;
+                    }
+                    UsbEndpoint endpoint = request.getEndpoint();
+                    if (endpoint.getDirection() != UsbConstants.USB_DIR_IN) {
+                        continue;
+                    }
+                    ByteBuffer buffer = bufferForEndpoints.get(endpoint);
+                    int length = getInputDataLength(buffer);
+                    if (length > 0) {
+                        buffer.rewind();
+                        final byte[] bs = new byte[length];
+                        buffer.get(bs, 0, length);
+                        postOnDataEvent(endpoint.getEndpointNumber(), bs);
+                    }
+                    buffer.rewind();
+                    request.queue(buffer, buffer.capacity());
+                }
+            }
+        }.start();
+    }
+
+    /**
+     * Posts a data input event to the main thread.
+     */
+    private void postOnDataEvent(final int endpointNumber, final byte[] bs) {
+        mHandler.post(new Runnable() {
+                public void run() {
+                    if (mIsClosed) {
+                        return;
+                    }
+                    nativeOnData(mNativePointer, endpointNumber, bs);
+                }
+            });
+    }
+
+    /**
+     * Register the own native pointer.
+     */
+    @CalledByNative
+    void registerSelf(long nativePointer) {
+        mNativePointer = nativePointer;
     }
 
     /**
@@ -79,7 +181,7 @@
      */
     @CalledByNative
     void send(int endpointNumber, byte[] bs) {
-        if (mConnection == null) {
+        if (mIsClosed) {
             return;
         }
         UsbEndpoint endpoint = mEndpointMap.get(endpointNumber);
@@ -117,9 +219,29 @@
             request.close();
         }
         mRequestMap.clear();
-        if (mConnection != null) {
-            mConnection.close();
-            mConnection = null;
-        }
+        mConnection.close();
+        mNativePointer = 0;
+        mIsClosed = true;
     }
+
+    /**
+     * Returns the length of a USB-MIDI input.
+     * Since the Android API doesn't provide us the length,
+     * we calculate it manually.
+     */
+    private static int getInputDataLength(ByteBuffer buffer) {
+        int position = buffer.position();
+        // We assume that the data length is always divisable by 4.
+        for (int i = 0; i < position; i += 4) {
+            // Since Code Index Number 0 is reserved, it is not a valid USB-MIDI data.
+            if (buffer.get(i) == 0) {
+                return i;
+            }
+        }
+        return position;
+    }
+
+    private static native void nativeOnData(long nativeUsbMidiDeviceAndroid,
+                                            int endpointNumber,
+                                            byte[] data);
 }
diff --git a/media/base/android/media_player_android.cc b/media/base/android/media_player_android.cc
index 2a98b7e..3969652 100644
--- a/media/base/android/media_player_android.cc
+++ b/media/base/android/media_player_android.cc
@@ -23,10 +23,6 @@
 
 MediaPlayerAndroid::~MediaPlayerAndroid() {}
 
-bool MediaPlayerAndroid::IsRemote() const {
-  return false;
-}
-
 GURL MediaPlayerAndroid::GetUrl() {
   return GURL();
 }
diff --git a/media/base/android/media_player_android.h b/media/base/android/media_player_android.h
index 2e5e371..0fd4815 100644
--- a/media/base/android/media_player_android.h
+++ b/media/base/android/media_player_android.h
@@ -61,7 +61,6 @@
   virtual void SetVolume(double volume) = 0;
 
   // Get the media information from the player.
-  virtual bool IsRemote() const;
   virtual int GetVideoWidth() = 0;
   virtual int GetVideoHeight() = 0;
   virtual base::TimeDelta GetDuration() = 0;
diff --git a/media/base/audio_buffer.cc b/media/base/audio_buffer.cc
index eba658b..4b972b9 100644
--- a/media/base/audio_buffer.cc
+++ b/media/base/audio_buffer.cc
@@ -13,6 +13,7 @@
 
 AudioBuffer::AudioBuffer(SampleFormat sample_format,
                          ChannelLayout channel_layout,
+                         int channel_count,
                          int sample_rate,
                          int frame_count,
                          bool create_buffer,
@@ -21,7 +22,7 @@
                          const base::TimeDelta duration)
     : sample_format_(sample_format),
       channel_layout_(channel_layout),
-      channel_count_(ChannelLayoutToChannelCount(channel_layout)),
+      channel_count_(channel_count),
       sample_rate_(sample_rate),
       adjusted_frame_count_(frame_count),
       trim_start_(0),
@@ -31,6 +32,9 @@
   CHECK_GE(channel_count_, 0);
   CHECK_LE(channel_count_, limits::kMaxChannels);
   CHECK_GE(frame_count, 0);
+  DCHECK(channel_layout == CHANNEL_LAYOUT_DISCRETE ||
+         ChannelLayoutToChannelCount(channel_layout) == channel_count);
+
   int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format);
   DCHECK_LE(bytes_per_channel, kChannelAlignment);
   int data_size = frame_count * bytes_per_channel;
@@ -83,6 +87,7 @@
 scoped_refptr<AudioBuffer> AudioBuffer::CopyFrom(
     SampleFormat sample_format,
     ChannelLayout channel_layout,
+    int channel_count,
     int sample_rate,
     int frame_count,
     const uint8* const* data,
@@ -93,6 +98,7 @@
   CHECK(data[0]);
   return make_scoped_refptr(new AudioBuffer(sample_format,
                                             channel_layout,
+                                            channel_count,
                                             sample_rate,
                                             frame_count,
                                             true,
@@ -105,11 +111,13 @@
 scoped_refptr<AudioBuffer> AudioBuffer::CreateBuffer(
     SampleFormat sample_format,
     ChannelLayout channel_layout,
+    int channel_count,
     int sample_rate,
     int frame_count) {
   CHECK_GT(frame_count, 0);  // Otherwise looks like an EOF buffer.
   return make_scoped_refptr(new AudioBuffer(sample_format,
                                             channel_layout,
+                                            channel_count,
                                             sample_rate,
                                             frame_count,
                                             true,
@@ -121,6 +129,7 @@
 // static
 scoped_refptr<AudioBuffer> AudioBuffer::CreateEmptyBuffer(
     ChannelLayout channel_layout,
+    int channel_count,
     int sample_rate,
     int frame_count,
     const base::TimeDelta timestamp,
@@ -129,6 +138,7 @@
   // Since data == NULL, format doesn't matter.
   return make_scoped_refptr(new AudioBuffer(kSampleFormatF32,
                                             channel_layout,
+                                            channel_count,
                                             sample_rate,
                                             frame_count,
                                             false,
@@ -143,6 +153,7 @@
                                             CHANNEL_LAYOUT_NONE,
                                             0,
                                             0,
+                                            0,
                                             false,
                                             NULL,
                                             kNoTimestamp(),
diff --git a/media/base/audio_buffer.h b/media/base/audio_buffer.h
index cd2047d..902407f 100644
--- a/media/base/audio_buffer.h
+++ b/media/base/audio_buffer.h
@@ -38,6 +38,7 @@
   // TODO(jrummell): Compute duration rather than pass it in.
   static scoped_refptr<AudioBuffer> CopyFrom(SampleFormat sample_format,
                                              ChannelLayout channel_layout,
+                                             int channel_count,
                                              int sample_rate,
                                              int frame_count,
                                              const uint8* const* data,
@@ -48,12 +49,14 @@
   // not initialized. Timestamp and duration are set to kNoTimestamp().
   static scoped_refptr<AudioBuffer> CreateBuffer(SampleFormat sample_format,
                                                  ChannelLayout channel_layout,
+                                                 int channel_count,
                                                  int sample_rate,
                                                  int frame_count);
 
   // Create an empty AudioBuffer with |frame_count| frames.
   static scoped_refptr<AudioBuffer> CreateEmptyBuffer(
       ChannelLayout channel_layout,
+      int channel_count,
       int sample_rate,
       int frame_count,
       const base::TimeDelta timestamp,
@@ -123,6 +126,7 @@
   // copied to).
   AudioBuffer(SampleFormat sample_format,
               ChannelLayout channel_layout,
+              int channel_count,
               int sample_rate,
               int frame_count,
               bool create_buffer,
diff --git a/media/base/audio_buffer_converter.cc b/media/base/audio_buffer_converter.cc
new file mode 100644
index 0000000..cdd3e08
--- /dev/null
+++ b/media/base/audio_buffer_converter.cc
@@ -0,0 +1,249 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/base/audio_buffer_converter.h"
+
+#include <cmath>
+
+#include "base/logging.h"
+#include "media/base/audio_buffer.h"
+#include "media/base/audio_bus.h"
+#include "media/base/audio_decoder_config.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/base/buffers.h"
+#include "media/base/sinc_resampler.h"
+#include "media/base/vector_math.h"
+
+namespace media {
+
+// Is the config presented by |buffer| a config change from |params|?
+static bool IsConfigChange(const AudioParameters& params,
+                           const scoped_refptr<AudioBuffer>& buffer) {
+  return buffer->sample_rate() != params.sample_rate() ||
+         buffer->channel_count() != params.channels() ||
+         buffer->channel_layout() != params.channel_layout();
+}
+
+AudioBufferConverter::AudioBufferConverter(const AudioParameters& output_params)
+    : output_params_(output_params),
+      input_params_(output_params),
+      last_input_buffer_offset_(0),
+      input_frames_(0),
+      buffered_input_frames_(0.0),
+      io_sample_rate_ratio_(1.0),
+      timestamp_helper_(output_params_.sample_rate()),
+      is_flushing_(false) {}
+
+AudioBufferConverter::~AudioBufferConverter() {}
+
+void AudioBufferConverter::AddInput(const scoped_refptr<AudioBuffer>& buffer) {
+  // On EOS flush any remaining buffered data.
+  if (buffer->end_of_stream()) {
+    Flush();
+    queued_outputs_.push_back(buffer);
+    return;
+  }
+
+  // We'll need a new |audio_converter_| if there was a config change.
+  if (IsConfigChange(input_params_, buffer))
+    ResetConverter(buffer);
+
+  // Pass straight through if there's no work to be done.
+  if (!audio_converter_) {
+    queued_outputs_.push_back(buffer);
+    return;
+  }
+
+  if (timestamp_helper_.base_timestamp() == kNoTimestamp())
+    timestamp_helper_.SetBaseTimestamp(buffer->timestamp());
+
+  queued_inputs_.push_back(buffer);
+  input_frames_ += buffer->frame_count();
+
+  ConvertIfPossible();
+}
+
+bool AudioBufferConverter::HasNextBuffer() { return !queued_outputs_.empty(); }
+
+scoped_refptr<AudioBuffer> AudioBufferConverter::GetNextBuffer() {
+  DCHECK(!queued_outputs_.empty());
+  scoped_refptr<AudioBuffer> out = queued_outputs_.front();
+  queued_outputs_.pop_front();
+  return out;
+}
+
+void AudioBufferConverter::Reset() {
+  audio_converter_.reset();
+  queued_inputs_.clear();
+  queued_outputs_.clear();
+  timestamp_helper_.SetBaseTimestamp(kNoTimestamp());
+  input_params_ = output_params_;
+  input_frames_ = 0;
+  buffered_input_frames_ = 0.0;
+  last_input_buffer_offset_ = 0;
+}
+
+void AudioBufferConverter::ResetTimestampState() {
+  Flush();
+  timestamp_helper_.SetBaseTimestamp(kNoTimestamp());
+}
+
+double AudioBufferConverter::ProvideInput(AudioBus* audio_bus,
+                                          base::TimeDelta buffer_delay) {
+  DCHECK(is_flushing_ || input_frames_ >= audio_bus->frames());
+
+  int requested_frames_left = audio_bus->frames();
+  int dest_index = 0;
+
+  while (requested_frames_left > 0 && !queued_inputs_.empty()) {
+    scoped_refptr<AudioBuffer> input_buffer = queued_inputs_.front();
+
+    int frames_to_read =
+        std::min(requested_frames_left,
+                 input_buffer->frame_count() - last_input_buffer_offset_);
+    input_buffer->ReadFrames(
+        frames_to_read, last_input_buffer_offset_, dest_index, audio_bus);
+    last_input_buffer_offset_ += frames_to_read;
+
+    if (last_input_buffer_offset_ == input_buffer->frame_count()) {
+      // We've consumed all the frames in |input_buffer|.
+      queued_inputs_.pop_front();
+      last_input_buffer_offset_ = 0;
+    }
+
+    requested_frames_left -= frames_to_read;
+    dest_index += frames_to_read;
+  }
+
+  // If we're flushing, zero any extra space, otherwise we should always have
+  // enough data to completely fulfill the request.
+  if (is_flushing_ && requested_frames_left > 0) {
+    audio_bus->ZeroFramesPartial(audio_bus->frames() - requested_frames_left,
+                                 requested_frames_left);
+  } else {
+    DCHECK_EQ(requested_frames_left, 0);
+  }
+
+  input_frames_ -= audio_bus->frames() - requested_frames_left;
+  DCHECK_GE(input_frames_, 0);
+
+  buffered_input_frames_ += audio_bus->frames() - requested_frames_left;
+
+  // Full volume.
+  return 1.0;
+}
+
+void AudioBufferConverter::ResetConverter(
+    const scoped_refptr<AudioBuffer>& buffer) {
+  Flush();
+  audio_converter_.reset();
+  input_params_.Reset(
+      input_params_.format(),
+      buffer->channel_layout(),
+      buffer->channel_count(),
+      0,
+      buffer->sample_rate(),
+      input_params_.bits_per_sample(),
+      // This is arbitrary, but small buffer sizes result in a lot of tiny
+      // ProvideInput calls, so we'll use at least the SincResampler's default
+      // request size.
+      std::max(buffer->frame_count(),
+               static_cast<int>(SincResampler::kDefaultRequestSize)));
+
+  io_sample_rate_ratio_ = static_cast<double>(input_params_.sample_rate()) /
+                          output_params_.sample_rate();
+
+  // If |buffer| matches |output_params_| we don't need an AudioConverter at
+  // all, and can early-out here.
+  if (!IsConfigChange(output_params_, buffer))
+    return;
+
+  audio_converter_.reset(
+      new AudioConverter(input_params_, output_params_, true));
+  audio_converter_->AddInput(this);
+}
+
+void AudioBufferConverter::ConvertIfPossible() {
+  DCHECK(audio_converter_);
+
+  int request_frames = 0;
+
+  if (is_flushing_) {
+    // If we're flushing we want to convert *everything* even if this means
+    // we'll have to pad some silence in ProvideInput().
+    request_frames =
+        ceil((buffered_input_frames_ + input_frames_) / io_sample_rate_ratio_);
+  } else {
+    // How many calls to ProvideInput() we can satisfy completely.
+    int chunks = input_frames_ / input_params_.frames_per_buffer();
+
+    // How many output frames that corresponds to:
+    request_frames = chunks * audio_converter_->ChunkSize();
+  }
+
+  if (!request_frames)
+    return;
+
+  scoped_refptr<AudioBuffer> output_buffer =
+      AudioBuffer::CreateBuffer(kSampleFormatPlanarF32,
+                                output_params_.channel_layout(),
+                                output_params_.channels(),
+                                output_params_.sample_rate(),
+                                request_frames);
+  scoped_ptr<AudioBus> output_bus =
+      AudioBus::CreateWrapper(output_buffer->channel_count());
+
+  int frames_remaining = request_frames;
+
+  // The AudioConverter wants requests of a fixed size, so we'll slide an
+  // AudioBus of that size across the |output_buffer|.
+  while (frames_remaining != 0) {
+    // It's important that this is a multiple of AudioBus::kChannelAlignment in
+    // all requests except for the last, otherwise downstream SIMD optimizations
+    // will crash on unaligned data.
+    const int frames_this_iteration = std::min(
+        static_cast<int>(SincResampler::kDefaultRequestSize), frames_remaining);
+    const int offset_into_buffer =
+        output_buffer->frame_count() - frames_remaining;
+
+    // Wrap the portion of the AudioBuffer in an AudioBus so the AudioConverter
+    // can fill it.
+    output_bus->set_frames(frames_this_iteration);
+    for (int ch = 0; ch < output_buffer->channel_count(); ++ch) {
+      output_bus->SetChannelData(
+          ch,
+          reinterpret_cast<float*>(output_buffer->channel_data()[ch]) +
+              offset_into_buffer);
+    }
+
+    // Do the actual conversion.
+    audio_converter_->Convert(output_bus.get());
+    frames_remaining -= frames_this_iteration;
+    buffered_input_frames_ -= frames_this_iteration * io_sample_rate_ratio_;
+  }
+
+  // Compute the timestamp.
+  output_buffer->set_timestamp(timestamp_helper_.GetTimestamp());
+  output_buffer->set_duration(
+      timestamp_helper_.GetFrameDuration(request_frames));
+  timestamp_helper_.AddFrames(request_frames);
+
+  queued_outputs_.push_back(output_buffer);
+}
+
+void AudioBufferConverter::Flush() {
+  if (!audio_converter_)
+    return;
+  is_flushing_ = true;
+  ConvertIfPossible();
+  is_flushing_ = false;
+  audio_converter_->Reset();
+  DCHECK_EQ(input_frames_, 0);
+  DCHECK_EQ(last_input_buffer_offset_, 0);
+  DCHECK_LT(buffered_input_frames_, 1.0);
+  DCHECK(queued_inputs_.empty());
+  buffered_input_frames_ = 0.0;
+}
+
+}  // namespace media
diff --git a/media/base/audio_buffer_converter.h b/media/base/audio_buffer_converter.h
new file mode 100644
index 0000000..9785b10
--- /dev/null
+++ b/media/base/audio_buffer_converter.h
@@ -0,0 +1,101 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_BASE_AUDIO_BUFFER_CONVERTER
+#define MEDIA_BASE_AUDIO_BUFFER_CONVERTER
+
+#include <deque>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_converter.h"
+#include "media/base/audio_timestamp_helper.h"
+#include "media/base/media_export.h"
+
+namespace media {
+
+class AudioBuffer;
+class AudioBus;
+
+// Takes AudioBuffers in any format and uses an AudioConverter to convert them
+// to a common format (usually the hardware output format).
+class MEDIA_EXPORT AudioBufferConverter : public AudioConverter::InputCallback {
+ public:
+  explicit AudioBufferConverter(const AudioParameters& output_params);
+  virtual ~AudioBufferConverter();
+
+  void AddInput(const scoped_refptr<AudioBuffer>& buffer);
+
+  // Is an output buffer available via GetNextBuffer()?
+  bool HasNextBuffer();
+
+  // This should only be called this is HasNextBuffer() returns true.
+  scoped_refptr<AudioBuffer> GetNextBuffer();
+
+  // Reset internal state.
+  void Reset();
+
+  // Reset internal timestamp state. Upon the next AddInput() call, our base
+  // timestamp will be set to match the input buffer.
+  void ResetTimestampState();
+
+ private:
+  // Callback to provide data to the AudioConverter
+  virtual double ProvideInput(AudioBus* audio_bus,
+                              base::TimeDelta buffer_delay) OVERRIDE;
+
+  // Reset the converter in response to a configuration change.
+  void ResetConverter(const scoped_refptr<AudioBuffer>& input_buffer);
+
+  // Perform conversion if we have enough data.
+  void ConvertIfPossible();
+
+  // Flush remaining output
+  void Flush();
+
+  // The output parameters.
+  AudioParameters output_params_;
+
+  // The current input parameters (we cache these to detect configuration
+  // changes, so we know when to reset the AudioConverter).
+  AudioParameters input_params_;
+
+  typedef std::deque<scoped_refptr<AudioBuffer> > BufferQueue;
+
+  // Queued up inputs (there will never be all that much data stored here, as
+  // soon as there's enough here to produce an output buffer we will do so).
+  BufferQueue queued_inputs_;
+
+  // Offset into the front element of |queued_inputs_|. A ProvideInput() call
+  // doesn't necessarily always consume an entire buffer.
+  int last_input_buffer_offset_;
+
+  // Buffer of output frames, to be returned by GetNextBuffer().
+  BufferQueue queued_outputs_;
+
+  // How many frames of input we have in |queued_inputs_|.
+  int input_frames_;
+
+  // Input frames in the AudioConverter's internal buffers.
+  double buffered_input_frames_;
+
+  // Ratio of sample rates, in/out.
+  double io_sample_rate_ratio_;
+
+  // Computes timestamps in terms of the output sample rate.
+  AudioTimestampHelper timestamp_helper_;
+
+  // Are we flushing everything, without regard for providing AudioConverter
+  // full AudioBuses in ProvideInput()?
+  bool is_flushing_;
+
+  // The AudioConverter which does the real work here.
+  scoped_ptr<AudioConverter> audio_converter_;
+};
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_AUDIO_BUFFER_CONVERTER
diff --git a/media/base/audio_buffer_converter_unittest.cc b/media/base/audio_buffer_converter_unittest.cc
new file mode 100644
index 0000000..77e787e
--- /dev/null
+++ b/media/base/audio_buffer_converter_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/scoped_ptr.h"
+#include "media/base/audio_buffer.h"
+#include "media/base/audio_buffer_converter.h"
+#include "media/base/sinc_resampler.h"
+#include "media/base/test_helpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+// Important: Use an odd buffer size here so SIMD issues are caught.
+const int kOutFrameSize = 441;
+const int kOutSampleRate = 44100;
+const ChannelLayout kOutChannelLayout = CHANNEL_LAYOUT_STEREO;
+const int kOutChannelCount = 2;
+
+static scoped_refptr<AudioBuffer> MakeTestBuffer(int sample_rate,
+                                                 ChannelLayout channel_layout,
+                                                 int channel_count,
+                                                 int frames) {
+  return MakeAudioBuffer<uint8>(kSampleFormatU8,
+                                channel_layout,
+                                channel_count,
+                                sample_rate,
+                                0,
+                                1,
+                                frames,
+                                base::TimeDelta::FromSeconds(0),
+                                base::TimeDelta::FromSeconds(0));
+}
+
+class AudioBufferConverterTest : public ::testing::Test {
+ public:
+  AudioBufferConverterTest()
+      : input_frames_(0), expected_output_frames_(0.0), output_frames_(0) {
+    AudioParameters output_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+                                  kOutChannelLayout,
+                                  kOutSampleRate,
+                                  16,
+                                  kOutFrameSize);
+    ResetConverter(output_params);
+  }
+
+  void Reset() {
+    audio_buffer_converter_->Reset();
+    output_frames_ = expected_output_frames_ = input_frames_ = 0;
+  }
+
+  void AddInput(const scoped_refptr<AudioBuffer>& in) {
+    if (!in->end_of_stream()) {
+      input_frames_ += in->frame_count();
+      expected_output_frames_ +=
+          in->frame_count() *
+          (static_cast<double>(kOutSampleRate) / in->sample_rate());
+    }
+    audio_buffer_converter_->AddInput(in);
+  }
+
+  void ConsumeAllOutput() {
+    AddInput(AudioBuffer::CreateEOSBuffer());
+    while (audio_buffer_converter_->HasNextBuffer()) {
+      scoped_refptr<AudioBuffer> out = audio_buffer_converter_->GetNextBuffer();
+      if (!out->end_of_stream()) {
+        output_frames_ += out->frame_count();
+        EXPECT_EQ(out->sample_rate(), out_sample_rate_);
+        EXPECT_EQ(out->channel_layout(), out_channel_layout_);
+        EXPECT_EQ(out->channel_count(), out_channel_count_);
+      } else {
+        EXPECT_FALSE(audio_buffer_converter_->HasNextBuffer());
+      }
+    }
+    EXPECT_EQ(output_frames_, ceil(expected_output_frames_));
+  }
+
+  void ResetConverter(AudioParameters out_params) {
+    audio_buffer_converter_.reset(new AudioBufferConverter(out_params));
+    out_channel_layout_ = out_params.channel_layout();
+    out_channel_count_ = out_params.channels();
+    out_sample_rate_ = out_params.sample_rate();
+  }
+
+ private:
+  scoped_ptr<AudioBufferConverter> audio_buffer_converter_;
+
+  int input_frames_;
+  double expected_output_frames_;
+  int output_frames_;
+
+  int out_sample_rate_;
+  ChannelLayout out_channel_layout_;
+  int out_channel_count_;
+};
+
+TEST_F(AudioBufferConverterTest, PassThrough) {
+  scoped_refptr<AudioBuffer> in =
+      MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512);
+  AddInput(in);
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, Downsample) {
+  scoped_refptr<AudioBuffer> in =
+      MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512);
+  AddInput(in);
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, Upsample) {
+  scoped_refptr<AudioBuffer> in =
+      MakeTestBuffer(8000, kOutChannelLayout, kOutChannelCount, 512);
+  AddInput(in);
+  ConsumeAllOutput();
+}
+
+// Test resampling a buffer smaller than the SincResampler's kernel size.
+TEST_F(AudioBufferConverterTest, Resample_TinyBuffer) {
+  AddInput(MakeTestBuffer(
+      48000, CHANNEL_LAYOUT_STEREO, 2, SincResampler::kKernelSize - 1));
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, Resample_DifferingBufferSizes) {
+  const int input_sample_rate = 48000;
+  AddInput(MakeTestBuffer(
+      input_sample_rate, kOutChannelLayout, kOutChannelCount, 100));
+  AddInput(MakeTestBuffer(
+      input_sample_rate, kOutChannelLayout, kOutChannelCount, 200));
+  AddInput(MakeTestBuffer(
+      input_sample_rate, kOutChannelLayout, kOutChannelCount, 300));
+  AddInput(MakeTestBuffer(
+      input_sample_rate, kOutChannelLayout, kOutChannelCount, 400));
+  AddInput(MakeTestBuffer(
+      input_sample_rate, kOutChannelLayout, kOutChannelCount, 500));
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ChannelDownmix) {
+  scoped_refptr<AudioBuffer> in =
+      MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_MONO, 1, 512);
+  AddInput(in);
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ChannelUpmix) {
+  scoped_refptr<AudioBuffer> in =
+      MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_5_1, 6, 512);
+  AddInput(in);
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ResampleAndRemix) {
+  scoped_refptr<AudioBuffer> in =
+      MakeTestBuffer(48000, CHANNEL_LAYOUT_5_1, 6, 512);
+  AddInput(in);
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ConfigChange_SampleRate) {
+  AddInput(MakeTestBuffer(48000, kOutChannelLayout, kOutChannelCount, 512));
+  AddInput(MakeTestBuffer(44100, kOutChannelLayout, kOutChannelCount, 512));
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ConfigChange_ChannelLayout) {
+  AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_STEREO, 2, 512));
+  AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_MONO, 1, 512));
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ConfigChange_SampleRateAndChannelLayout) {
+  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
+  AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_MONO, 1, 512));
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ConfigChange_Multiple) {
+  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
+  AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_MONO, 1, 512));
+  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_5_1, 6, 512));
+  AddInput(MakeTestBuffer(22050, CHANNEL_LAYOUT_STEREO, 2, 512));
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, Reset) {
+  AddInput(MakeTestBuffer(44100, CHANNEL_LAYOUT_STEREO, 2, 512));
+  Reset();
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ResampleThenReset) {
+  // Resampling is likely to leave some data buffered in AudioConverter's
+  // fifo or resampler, so make sure Reset() cleans that all up.
+  AddInput(MakeTestBuffer(48000, CHANNEL_LAYOUT_STEREO, 2, 512));
+  Reset();
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, ResetThenConvert) {
+  AddInput(
+      MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512));
+  Reset();
+  // Make sure we can keep using the AudioBufferConverter after we've Reset().
+  AddInput(
+      MakeTestBuffer(kOutSampleRate, kOutChannelLayout, kOutChannelCount, 512));
+  ConsumeAllOutput();
+}
+
+TEST_F(AudioBufferConverterTest, DiscreteChannelLayout) {
+  AudioParameters output_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+                                CHANNEL_LAYOUT_DISCRETE,
+                                2,
+                                0,
+                                kOutSampleRate,
+                                16,
+                                512,
+                                0);
+  ResetConverter(output_params);
+  AddInput(MakeTestBuffer(kOutSampleRate, CHANNEL_LAYOUT_STEREO, 2, 512));
+  ConsumeAllOutput();
+}
+
+}  // namespace media
diff --git a/media/base/audio_buffer_queue_unittest.cc b/media/base/audio_buffer_queue_unittest.cc
index adbac75..fc04857 100644
--- a/media/base/audio_buffer_queue_unittest.cc
+++ b/media/base/audio_buffer_queue_unittest.cc
@@ -39,6 +39,7 @@
   const base::TimeDelta kNoTime = kNoTimestamp();
   return MakeAudioBuffer<T>(format,
                             channel_layout,
+                            ChannelLayoutToChannelCount(channel_layout),
                             kSampleRate,
                             start,
                             end,
@@ -388,6 +389,7 @@
   //   second: start=30s, duration=10s
   buffer.Append(MakeAudioBuffer<int16>(kSampleFormatS16,
                                        channel_layout,
+                                       channels,
                                        kSampleRate,
                                        1,
                                        1,
@@ -412,6 +414,7 @@
   // Add second buffer for more data.
   buffer.Append(MakeAudioBuffer<int16>(kSampleFormatS16,
                                        channel_layout,
+                                       channels,
                                        kSampleRate,
                                        1,
                                        1,
diff --git a/media/base/audio_buffer_unittest.cc b/media/base/audio_buffer_unittest.cc
index 55a67c8..c40c076 100644
--- a/media/base/audio_buffer_unittest.cc
+++ b/media/base/audio_buffer_unittest.cc
@@ -30,14 +30,16 @@
   const int frames = 8;
   const base::TimeDelta start_time;
   const base::TimeDelta duration = base::TimeDelta::FromSeconds(frames);
-  scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<uint8>(kSampleFormatU8,
-                                                             channel_layout,
-                                                             kSampleRate,
-                                                             1,
-                                                             1,
-                                                             frames,
-                                                             start_time,
-                                                             duration);
+  scoped_refptr<AudioBuffer> buffer =
+      MakeAudioBuffer<uint8>(kSampleFormatU8,
+                             channel_layout,
+                             ChannelLayoutToChannelCount(channel_layout),
+                             kSampleRate,
+                             1,
+                             1,
+                             frames,
+                             start_time,
+                             duration);
   EXPECT_EQ(frames, buffer->frame_count());
   EXPECT_EQ(buffer->timestamp(), start_time);
   EXPECT_EQ(buffer->duration().InSeconds(), frames);
@@ -60,6 +62,7 @@
   scoped_refptr<AudioBuffer> buffer =
       AudioBuffer::CopyFrom(kSampleFormatU8,
                             CHANNEL_LAYOUT_STEREO,
+                            2,
                             kSampleRate,
                             16,
                             data,
@@ -69,6 +72,7 @@
 
   buffer = AudioBuffer::CopyFrom(kSampleFormatF32,
                                  CHANNEL_LAYOUT_4_0,
+                                 4,
                                  kSampleRate,
                                  2,
                                  data,
@@ -85,6 +89,7 @@
   const base::TimeDelta duration = base::TimeDelta::FromSeconds(frames);
   scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<uint8>(kSampleFormatU8,
                                                              channel_layout,
+                                                             channels,
                                                              kSampleRate,
                                                              128,
                                                              1,
@@ -112,6 +117,7 @@
   const base::TimeDelta duration = base::TimeDelta::FromSeconds(frames);
   scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<int16>(kSampleFormatS16,
                                                              channel_layout,
+                                                             channels,
                                                              kSampleRate,
                                                              1,
                                                              1,
@@ -144,6 +150,7 @@
   const base::TimeDelta duration = base::TimeDelta::FromSeconds(frames);
   scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<int32>(kSampleFormatS32,
                                                              channel_layout,
+                                                             channels,
                                                              kSampleRate,
                                                              1,
                                                              1,
@@ -174,6 +181,7 @@
   const base::TimeDelta duration = base::TimeDelta::FromSeconds(frames);
   scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<float>(kSampleFormatF32,
                                                              channel_layout,
+                                                             channels,
                                                              kSampleRate,
                                                              1.0f,
                                                              1.0f,
@@ -204,6 +212,7 @@
   scoped_refptr<AudioBuffer> buffer =
       MakeAudioBuffer<int16>(kSampleFormatPlanarS16,
                              channel_layout,
+                             channels,
                              kSampleRate,
                              1,
                              1,
@@ -245,6 +254,7 @@
   scoped_refptr<AudioBuffer> buffer =
       MakeAudioBuffer<float>(kSampleFormatPlanarF32,
                              channel_layout,
+                             channels,
                              kSampleRate,
                              1.0f,
                              1.0f,
@@ -278,7 +288,7 @@
   const base::TimeDelta start_time;
   const base::TimeDelta duration = base::TimeDelta::FromSeconds(frames);
   scoped_refptr<AudioBuffer> buffer = AudioBuffer::CreateEmptyBuffer(
-      channel_layout, kSampleRate, frames, start_time, duration);
+      channel_layout, channels, kSampleRate, frames, start_time, duration);
   EXPECT_EQ(frames, buffer->frame_count());
   EXPECT_EQ(start_time, buffer->timestamp());
   EXPECT_EQ(frames, buffer->duration().InSeconds());
@@ -302,6 +312,7 @@
   scoped_refptr<AudioBuffer> buffer =
       MakeAudioBuffer<float>(kSampleFormatPlanarF32,
                              channel_layout,
+                             channels,
                              kSampleRate,
                              1.0f,
                              1.0f,
diff --git a/media/base/audio_converter.cc b/media/base/audio_converter.cc
index cdc6642..aa0be4f 100644
--- a/media/base/audio_converter.cc
+++ b/media/base/audio_converter.cc
@@ -25,7 +25,7 @@
 AudioConverter::AudioConverter(const AudioParameters& input_params,
                                const AudioParameters& output_params,
                                bool disable_fifo)
-    : chunk_size_(output_params.frames_per_buffer()),
+    : chunk_size_(input_params.frames_per_buffer()),
       downmix_early_(false),
       resampler_frame_delay_(0),
       input_channel_count_(input_params.channels()) {
@@ -48,15 +48,16 @@
   if (input_params.sample_rate() != output_params.sample_rate()) {
     DVLOG(1) << "Resampling from " << input_params.sample_rate() << " to "
              << output_params.sample_rate();
-    const double io_sample_rate_ratio = input_params.sample_rate() /
-        static_cast<double>(output_params.sample_rate());
     const int request_size = disable_fifo ? SincResampler::kDefaultRequestSize :
         input_params.frames_per_buffer();
+    const double io_sample_rate_ratio =
+        input_params.sample_rate() /
+        static_cast<double>(output_params.sample_rate());
     resampler_.reset(new MultiChannelResampler(
-        downmix_early_ ? output_params.channels() :
-            input_params.channels(),
-        io_sample_rate_ratio, request_size, base::Bind(
-            &AudioConverter::ProvideInput, base::Unretained(this))));
+        downmix_early_ ? output_params.channels() : input_params.channels(),
+        io_sample_rate_ratio,
+        request_size,
+        base::Bind(&AudioConverter::ProvideInput, base::Unretained(this))));
   }
 
   input_frame_duration_ = base::TimeDelta::FromMicroseconds(
@@ -160,7 +161,7 @@
 }
 
 void AudioConverter::SourceCallback(int fifo_frame_delay, AudioBus* dest) {
-  bool needs_downmix = channel_mixer_ && downmix_early_;
+  const bool needs_downmix = channel_mixer_ && downmix_early_;
 
   if (!mixer_input_audio_bus_ ||
       mixer_input_audio_bus_->frames() != dest->frames()) {
@@ -174,7 +175,7 @@
   if (needs_downmix)
     CreateUnmixedAudioIfNecessary(dest->frames());
 
-  AudioBus* temp_dest = needs_downmix ? unmixed_audio_.get() : dest;
+  AudioBus* const temp_dest = needs_downmix ? unmixed_audio_.get() : dest;
 
   // Sanity check our inputs.
   DCHECK_EQ(temp_dest->frames(), mixer_input_audio_bus_->frames());
@@ -191,23 +192,27 @@
         fifo_frame_delay * input_frame_duration_.InMicroseconds());
   }
 
+  // If we only have a single input, avoid an extra copy.
+  AudioBus* const provide_input_dest =
+      transform_inputs_.size() == 1 ? temp_dest : mixer_input_audio_bus_.get();
+
   // Have each mixer render its data into an output buffer then mix the result.
   for (InputCallbackSet::iterator it = transform_inputs_.begin();
        it != transform_inputs_.end(); ++it) {
     InputCallback* input = *it;
 
-    float volume = input->ProvideInput(
-        mixer_input_audio_bus_.get(), buffer_delay);
+    const float volume = input->ProvideInput(provide_input_dest, buffer_delay);
 
     // Optimize the most common single input, full volume case.
     if (it == transform_inputs_.begin()) {
       if (volume == 1.0f) {
-        mixer_input_audio_bus_->CopyTo(temp_dest);
+        if (temp_dest != provide_input_dest)
+          provide_input_dest->CopyTo(temp_dest);
       } else if (volume > 0) {
-        for (int i = 0; i < mixer_input_audio_bus_->channels(); ++i) {
+        for (int i = 0; i < provide_input_dest->channels(); ++i) {
           vector_math::FMUL(
-              mixer_input_audio_bus_->channel(i), volume,
-              mixer_input_audio_bus_->frames(), temp_dest->channel(i));
+              provide_input_dest->channel(i), volume,
+              provide_input_dest->frames(), temp_dest->channel(i));
         }
       } else {
         // Zero |temp_dest| otherwise, so we're mixing into a clean buffer.
diff --git a/media/base/audio_decoder.h b/media/base/audio_decoder.h
index 901126d..b1ee2cd 100644
--- a/media/base/audio_decoder.h
+++ b/media/base/audio_decoder.h
@@ -69,11 +69,6 @@
   // complete before deleting the decoder.
   virtual void Stop(const base::Closure& closure) = 0;
 
-  // Returns various information about the decoded audio format.
-  virtual int bits_per_channel() = 0;
-  virtual ChannelLayout channel_layout() = 0;
-  virtual int samples_per_second() = 0;
-
  private:
   DISALLOW_COPY_AND_ASSIGN(AudioDecoder);
 };
diff --git a/media/base/audio_splicer.cc b/media/base/audio_splicer.cc
index 7299081..1a56fa4 100644
--- a/media/base/audio_splicer.cc
+++ b/media/base/audio_splicer.cc
@@ -29,9 +29,6 @@
 // in the source content. Unit is frames.
 static const int kMinGapSize = 2;
 
-// The number of milliseconds to crossfade before trimming when buffers overlap.
-static const int kCrossfadeDurationInMilliseconds = 5;
-
 // AudioBuffer::TrimStart() is not as accurate as the timestamp helper, so
 // manually adjust the duration and timestamp after trimming.
 static void AccurateTrimStart(int frames_to_trim,
@@ -102,6 +99,10 @@
     return output_timestamp_helper_;
   }
 
+  // Transfer all buffers into |output|.  Returns false if AddInput() on the
+  // |output| sanitizer fails for any buffer removed from |this|.
+  bool DrainInto(AudioStreamSanitizer* output);
+
  private:
   void AddOutputBuffer(const scoped_refptr<AudioBuffer>& buffer);
 
@@ -181,6 +182,7 @@
     // add it to the output buffer.
     scoped_refptr<AudioBuffer> gap = AudioBuffer::CreateEmptyBuffer(
         input->channel_layout(),
+        input->channel_count(),
         input->sample_rate(),
         frames_to_fill,
         expected_timestamp,
@@ -248,6 +250,14 @@
          output_timestamp_helper_.base_timestamp();
 }
 
+bool AudioStreamSanitizer::DrainInto(AudioStreamSanitizer* output) {
+  while (HasNextBuffer()) {
+    if (!output->AddInput(GetNextBuffer()))
+      return false;
+  }
+  return true;
+}
+
 AudioSplicer::AudioSplicer(int samples_per_second)
     : max_crossfade_duration_(
           base::TimeDelta::FromMilliseconds(kCrossfadeDurationInMilliseconds)),
@@ -333,6 +343,19 @@
     return true;
   }
 
+  // If a splice frame was incorrectly marked due to poor demuxed timestamps, we
+  // may not actually have a splice frame.  In this case, just transfer all data
+  // to the output sanitizer.
+  if (pre_splice_sanitizer_->timestamp_helper().GetTimestamp() ==
+      post_splice_sanitizer_->timestamp_helper().base_timestamp()) {
+    CHECK(pre_splice_sanitizer_->DrainInto(output_sanitizer_.get()));
+    CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get()));
+    splice_timestamp_ = kNoTimestamp();
+    pre_splice_sanitizer_->Reset();
+    post_splice_sanitizer_->Reset();
+    return true;
+  }
+
   scoped_refptr<AudioBuffer> crossfade_buffer;
   scoped_ptr<AudioBus> pre_splice =
       ExtractCrossfadeFromPreSplice(&crossfade_buffer);
@@ -393,6 +416,9 @@
       max_crossfade_frame_count,
       std::min(pre_splice_sanitizer_->GetFrameCount() - frames_before_splice,
                post_splice_sanitizer_->GetFrameCount()));
+  // There must always be frames to crossfade, otherwise the splice should not
+  // have been generated.
+  DCHECK_GT(frames_to_crossfade, 0);
 
   int frames_read = 0;
   scoped_ptr<AudioBus> output_bus;
@@ -408,6 +434,7 @@
       // Allocate output buffer for crossfade.
       *crossfade_buffer = AudioBuffer::CreateBuffer(kSampleFormatPlanarF32,
                                                     preroll->channel_layout(),
+                                                    preroll->channel_count(),
                                                     preroll->sample_rate(),
                                                     frames_to_crossfade);
     }
@@ -504,8 +531,7 @@
   }
 
   // Transfer all remaining buffers out and reset once empty.
-  while (post_splice_sanitizer_->HasNextBuffer())
-    CHECK(output_sanitizer_->AddInput(post_splice_sanitizer_->GetNextBuffer()));
+  CHECK(post_splice_sanitizer_->DrainInto(output_sanitizer_.get()));
   post_splice_sanitizer_->Reset();
 }
 
diff --git a/media/base/audio_splicer.h b/media/base/audio_splicer.h
index ce961d7..f3af577 100644
--- a/media/base/audio_splicer.h
+++ b/media/base/audio_splicer.h
@@ -23,6 +23,11 @@
   explicit AudioSplicer(int samples_per_second);
   ~AudioSplicer();
 
+  enum {
+    // The number of ms to crossfade before trimming when buffers overlap.
+    kCrossfadeDurationInMilliseconds = 5,
+  };
+
   // Resets the splicer state by clearing the output buffers queue and resetting
   // the timestamp helper.
   void Reset();
diff --git a/media/base/audio_splicer_unittest.cc b/media/base/audio_splicer_unittest.cc
index be72273..481178e 100644
--- a/media/base/audio_splicer_unittest.cc
+++ b/media/base/audio_splicer_unittest.cc
@@ -38,6 +38,7 @@
     scoped_refptr<AudioBuffer> buffer = MakeAudioBuffer<float>(
         kSampleFormat,
         kChannelLayout,
+        kChannels,
         kDefaultSampleRate,
         value,
         0.0f,
@@ -130,6 +131,7 @@
             ? AudioBuffer::CreateEOSBuffer()
             : AudioBuffer::CopyFrom(kSampleFormat,
                                     input->channel_layout(),
+                                    input->channel_count(),
                                     input->sample_rate(),
                                     input->frame_count(),
                                     &input->channel_data()[0],
@@ -590,4 +592,41 @@
   EXPECT_FALSE(splicer_.HasNextBuffer());
 }
 
+// Test behavior when a splice frame is incorrectly marked and does not actually
+// overlap.
+// +----------+
+// |1111111111|
+// +----------+
+//            +--------------+
+//            |22222222222222|
+//            +--------------+
+// Results in:
+// +----------+--------------+
+// |1111111111|22222222222222|
+// +----------+--------------+
+TEST_F(AudioSplicerTest, IncorrectlyMarkedSplice) {
+  const int kBufferSize =
+      input_timestamp_helper_.GetFramesToTarget(max_crossfade_duration()) * 2;
+
+  scoped_refptr<AudioBuffer> first_buffer =
+      GetNextInputBuffer(1.0f, kBufferSize);
+  splicer_.SetSpliceTimestamp(input_timestamp_helper_.GetTimestamp());
+  scoped_refptr<AudioBuffer> second_buffer =
+      GetNextInputBuffer(0.0f, kBufferSize);
+
+  // The splicer should be internally queuing input since |first_buffer| is part
+  // of the supposed splice.
+  EXPECT_TRUE(AddInput(first_buffer));
+  EXPECT_FALSE(splicer_.HasNextBuffer());
+
+  // |second_buffer| should complete the supposed splice, so ensure output is
+  // now available.
+  EXPECT_TRUE(AddInput(second_buffer));
+  ASSERT_TRUE(splicer_.HasNextBuffer());
+
+  VerifyNextBuffer(first_buffer);
+  VerifyNextBuffer(second_buffer);
+  EXPECT_FALSE(splicer_.HasNextBuffer());
+}
+
 }  // namespace media
diff --git a/media/base/decoder_buffer.cc b/media/base/decoder_buffer.cc
index d4e7541..b6d7d26 100644
--- a/media/base/decoder_buffer.cc
+++ b/media/base/decoder_buffer.cc
@@ -5,6 +5,7 @@
 #include "media/base/decoder_buffer.h"
 
 #include "base/logging.h"
+#include "media/base/buffers.h"
 #include "media/base/decrypt_config.h"
 
 namespace media {
@@ -43,6 +44,7 @@
         base::AlignedAlloc(side_data_size_ + kPaddingSize, kAlignmentSize)));
     memset(side_data_.get() + side_data_size_, 0, kPaddingSize);
   }
+  splice_timestamp_ = kNoTimestamp();
 }
 
 // static
diff --git a/media/base/decoder_buffer.h b/media/base/decoder_buffer.h
index 82347bf..8edc539 100644
--- a/media/base/decoder_buffer.h
+++ b/media/base/decoder_buffer.h
@@ -130,6 +130,20 @@
     return data_ == NULL;
   }
 
+  // Indicates this buffer is part of a splice around |splice_timestamp_|.
+  // Returns kNoTimestamp() if the buffer is not part of a splice.
+  base::TimeDelta splice_timestamp() const {
+    DCHECK(!end_of_stream());
+    return splice_timestamp_;
+  }
+
+  // When set to anything but kNoTimestamp() indicates this buffer is part of a
+  // splice around |splice_timestamp|.
+  void set_splice_timestamp(base::TimeDelta splice_timestamp) {
+    DCHECK(!end_of_stream());
+    splice_timestamp_ = splice_timestamp;
+  }
+
   // Returns a human-readable string describing |*this|.
   std::string AsHumanReadableString();
 
@@ -153,6 +167,7 @@
   scoped_ptr<uint8, base::AlignedFreeDeleter> side_data_;
   scoped_ptr<DecryptConfig> decrypt_config_;
   base::TimeDelta discard_padding_;
+  base::TimeDelta splice_timestamp_;
 
   // Constructor helper method for memory allocations.
   void Initialize();
diff --git a/media/base/demuxer_stream.h b/media/base/demuxer_stream.h
index 4e07c66..87f53e7 100644
--- a/media/base/demuxer_stream.h
+++ b/media/base/demuxer_stream.h
@@ -40,6 +40,8 @@
   //                  new configuration to properly decode the buffers read
   //                  from this point forward. The second parameter MUST be NULL
   //                  when this status is returned.
+  //                  This will only be returned if SupportsConfigChanges()
+  //                  returns 'true' for this DemuxerStream.
   enum Status {
     kOk,
     kAborted,
@@ -68,6 +70,16 @@
 
   virtual void EnableBitstreamConverter() = 0;
 
+  // Whether or not this DemuxerStream allows midstream configuration changes.
+  //
+  // A DemuxerStream that returns 'true' to this may return the 'kConfigChange'
+  // status from a Read() call. In this case the client is expected to be
+  // capable of taking appropriate action to handle config changes. Otherwise
+  // audio_decoder_config() and video_decoder_config()'s return values are
+  // guaranteed to remain constant, and the client may make optimizations based
+  // on this.
+  virtual bool SupportsConfigChanges() = 0;
+
  protected:
   // Only allow concrete implementations to get deleted.
   virtual ~DemuxerStream();
diff --git a/media/base/fake_text_track_stream.cc b/media/base/fake_text_track_stream.cc
index c37b1b5..2e9a1e1 100644
--- a/media/base/fake_text_track_stream.cc
+++ b/media/base/fake_text_track_stream.cc
@@ -36,6 +36,8 @@
   return DemuxerStream::TEXT;
 }
 
+bool FakeTextTrackStream::SupportsConfigChanges() { return false; }
+
 void FakeTextTrackStream::SatisfyPendingRead(
     const base::TimeDelta& start,
     const base::TimeDelta& duration,
diff --git a/media/base/fake_text_track_stream.h b/media/base/fake_text_track_stream.h
index 88c1366..db7a3e1 100644
--- a/media/base/fake_text_track_stream.h
+++ b/media/base/fake_text_track_stream.h
@@ -23,6 +23,7 @@
   MOCK_METHOD0(video_decoder_config, VideoDecoderConfig());
   virtual Type type() OVERRIDE;
   MOCK_METHOD0(EnableBitstreamConverter, void());
+  virtual bool SupportsConfigChanges();
 
   void SatisfyPendingRead(const base::TimeDelta& start,
                           const base::TimeDelta& duration,
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 4be852d..68b6e5e 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -15,9 +15,6 @@
 // Enables ADTS stream parser for Media Source Extensions.
 const char kEnableADTSStreamParser[] = "enable-adts-stream-parser";
 
-// Enables MP3 stream parser for Media Source Extensions.
-const char kEnableMP3StreamParser[] = "enable-mp3-stream-parser";
-
 #if defined(OS_ANDROID)
 // Disables the infobar popup for accessing protected media identifier.
 const char kDisableInfobarForProtectedMediaIdentifier[] =
@@ -83,9 +80,6 @@
 const char kUseCras[] = "use-cras";
 #endif
 
-// Disables system sounds manager.
-const char kDisableSystemSoundsManager[] = "disable-system-sounds-manager";
-
 // Use a raw video file as fake video capture device.
 const char kUseFileForFakeVideoCapture[] = "use-file-for-fake-video-capture";
 
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index dd865ff..289a3b1 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -17,7 +17,6 @@
 MEDIA_EXPORT extern const char kVideoThreads[];
 
 MEDIA_EXPORT extern const char kEnableADTSStreamParser[];
-MEDIA_EXPORT extern const char kEnableMP3StreamParser[];
 
 #if defined(OS_ANDROID)
 MEDIA_EXPORT extern const char kDisableInfobarForProtectedMediaIdentifier[];
@@ -46,8 +45,6 @@
 MEDIA_EXPORT extern const char kUseCras[];
 #endif
 
-MEDIA_EXPORT extern const char kDisableSystemSoundsManager[];
-
 MEDIA_EXPORT extern const char kUseFileForFakeVideoCapture[];
 
 }  // namespace switches
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h
index 8b2a1c2..0392d11 100644
--- a/media/base/mock_filters.h
+++ b/media/base/mock_filters.h
@@ -55,6 +55,7 @@
   virtual AudioDecoderConfig audio_decoder_config() OVERRIDE;
   virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
   MOCK_METHOD0(EnableBitstreamConverter, void());
+  MOCK_METHOD0(SupportsConfigChanges, bool());
 
   void set_audio_decoder_config(const AudioDecoderConfig& config);
   void set_video_decoder_config(const VideoDecoderConfig& config);
@@ -96,9 +97,6 @@
   MOCK_METHOD2(Decode,
                void(const scoped_refptr<DecoderBuffer>& buffer,
                     const DecodeCB&));
-  MOCK_METHOD0(bits_per_channel, int(void));
-  MOCK_METHOD0(channel_layout, ChannelLayout(void));
-  MOCK_METHOD0(samples_per_second, int(void));
   MOCK_METHOD1(Reset, void(const base::Closure&));
   MOCK_METHOD1(Stop, void(const base::Closure&));
 
diff --git a/media/base/pipeline.cc b/media/base/pipeline.cc
index 824585f..8c0ca54 100644
--- a/media/base/pipeline.cc
+++ b/media/base/pipeline.cc
@@ -45,8 +45,6 @@
       clock_(new Clock(&default_tick_clock_)),
       waiting_for_clock_update_(false),
       status_(PIPELINE_OK),
-      has_audio_(false),
-      has_video_(false),
       state_(kCreated),
       audio_ended_(false),
       video_ended_(false),
@@ -74,16 +72,29 @@
                      const base::Closure& ended_cb,
                      const PipelineStatusCB& error_cb,
                      const PipelineStatusCB& seek_cb,
-                     const BufferingStateCB& buffering_state_cb,
+                     const PipelineMetadataCB& metadata_cb,
+                     const base::Closure& preroll_completed_cb,
                      const base::Closure& duration_change_cb) {
+  DCHECK(!ended_cb.is_null());
+  DCHECK(!error_cb.is_null());
+  DCHECK(!seek_cb.is_null());
+  DCHECK(!metadata_cb.is_null());
+  DCHECK(!preroll_completed_cb.is_null());
+
   base::AutoLock auto_lock(lock_);
   CHECK(!running_) << "Media pipeline is already running";
-  DCHECK(!buffering_state_cb.is_null());
-
   running_ = true;
-  task_runner_->PostTask(FROM_HERE, base::Bind(
-      &Pipeline::StartTask, base::Unretained(this), base::Passed(&collection),
-      ended_cb, error_cb, seek_cb, buffering_state_cb, duration_change_cb));
+
+  filter_collection_ = collection.Pass();
+  ended_cb_ = ended_cb;
+  error_cb_ = error_cb;
+  seek_cb_ = seek_cb;
+  metadata_cb_ = metadata_cb;
+  preroll_completed_cb_ = preroll_completed_cb;
+  duration_change_cb_ = duration_change_cb;
+
+  task_runner_->PostTask(
+      FROM_HERE, base::Bind(&Pipeline::StartTask, base::Unretained(this)));
 }
 
 void Pipeline::Stop(const base::Closure& stop_cb) {
@@ -108,16 +119,6 @@
   return running_;
 }
 
-bool Pipeline::HasAudio() const {
-  base::AutoLock auto_lock(lock_);
-  return has_audio_;
-}
-
-bool Pipeline::HasVideo() const {
-  base::AutoLock auto_lock(lock_);
-  return has_video_;
-}
-
 float Pipeline::GetPlaybackRate() const {
   base::AutoLock auto_lock(lock_);
   return playback_rate_;
@@ -188,11 +189,6 @@
   return total_bytes_;
 }
 
-gfx::Size Pipeline::GetInitialNaturalSize() const {
-  base::AutoLock auto_lock(lock_);
-  return initial_natural_size_;
-}
-
 bool Pipeline::DidLoadingProgress() const {
   base::AutoLock auto_lock(lock_);
   bool ret = did_loading_progress_;
@@ -333,8 +329,9 @@
   DCHECK(IsRunning());
   base::AutoLock auto_lock(lock_);
 
-  if (!has_audio_)
+  if (audio_disabled_)
     return;
+
   if (waiting_for_clock_update_ && time < clock_->Elapsed())
     return;
 
@@ -351,7 +348,7 @@
   DCHECK(IsRunning());
   base::AutoLock auto_lock(lock_);
 
-  if (has_audio_)
+  if (audio_renderer_ && !audio_disabled_)
     return;
 
   // TODO(scherkus): |state_| should only be accessed on pipeline thread, see
@@ -462,20 +459,21 @@
         // We do not want to start the clock running. We only want to set the
         // base media time so our timestamp calculations will be correct.
         clock_->SetTime(demuxer_->GetStartTime(), demuxer_->GetStartTime());
-
-        // TODO(scherkus): |has_audio_| should be true no matter what --
-        // otherwise people with muted/disabled sound cards will make our
-        // default controls look as if every video doesn't contain an audio
-        // track.
-        has_audio_ = audio_renderer_ != NULL && !audio_disabled_;
-        has_video_ = video_renderer_ != NULL;
       }
       if (!audio_renderer_ && !video_renderer_) {
         done_cb.Run(PIPELINE_ERROR_COULD_NOT_RENDER);
         return;
       }
 
-      buffering_state_cb_.Run(kHaveMetadata);
+      {
+        PipelineMetadata metadata;
+        metadata.has_audio = audio_renderer_;
+        metadata.has_video = video_renderer_;
+        DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
+        if (stream)
+          metadata.natural_size = stream->video_decoder_config().natural_size();
+        metadata_cb_.Run(metadata);
+      }
 
       return DoInitialPreroll(done_cb);
 
@@ -488,7 +486,7 @@
         // We use audio stream to update the clock. So if there is such a
         // stream, we pause the clock until we receive a valid timestamp.
         waiting_for_clock_update_ = true;
-        if (!has_audio_) {
+        if (!audio_renderer_ || audio_disabled_) {
           clock_->SetMaxTime(clock_->Duration());
           StartClockIfWaitingForTimeUpdate_Locked();
         }
@@ -500,7 +498,7 @@
       // Fire canplaythrough immediately after playback begins because of
       // crbug.com/106480.
       // TODO(vrk): set ready state to HaveFutureData when bug above is fixed.
-      buffering_state_cb_.Run(kPrerollCompleted);
+      preroll_completed_cb_.Run();
       return base::ResetAndReturn(&seek_cb_).Run(PIPELINE_OK);
 
     case kStopping:
@@ -731,23 +729,11 @@
   statistics_.video_frames_dropped += stats.video_frames_dropped;
 }
 
-void Pipeline::StartTask(scoped_ptr<FilterCollection> filter_collection,
-                         const base::Closure& ended_cb,
-                         const PipelineStatusCB& error_cb,
-                         const PipelineStatusCB& seek_cb,
-                         const BufferingStateCB& buffering_state_cb,
-                         const base::Closure& duration_change_cb) {
+void Pipeline::StartTask() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   CHECK_EQ(kCreated, state_)
       << "Media pipeline cannot be started more than once";
 
-  filter_collection_ = filter_collection.Pass();
-  ended_cb_ = ended_cb;
-  error_cb_ = error_cb;
-  seek_cb_ = seek_cb;
-  buffering_state_cb_ = buffering_state_cb;
-  duration_change_cb_ = duration_change_cb;
-
   text_renderer_ = filter_collection_->GetTextRenderer();
 
   if (text_renderer_) {
@@ -925,7 +911,6 @@
   DCHECK(task_runner_->BelongsToCurrentThread());
 
   base::AutoLock auto_lock(lock_);
-  has_audio_ = false;
   audio_disabled_ = true;
 
   // Notify our demuxer that we're no longer rendering audio.
@@ -974,23 +959,9 @@
 void Pipeline::InitializeVideoRenderer(const PipelineStatusCB& done_cb) {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
-  // Get an initial natural size so we have something when we signal
-  // the kHaveMetadata buffering state.
-  //
-  // TODO(acolwell): We have to query demuxer outside of the lock to prevent a
-  // deadlock between ChunkDemuxer and Pipeline. See http://crbug.com/334325 for
-  // ideas on removing locking from ChunkDemuxer.
-  DemuxerStream* stream = demuxer_->GetStream(DemuxerStream::VIDEO);
-  gfx::Size initial_natural_size =
-      stream->video_decoder_config().natural_size();
-  {
-    base::AutoLock l(lock_);
-    initial_natural_size_ = initial_natural_size;
-  }
-
   video_renderer_ = filter_collection_->GetVideoRenderer();
   video_renderer_->Initialize(
-      stream,
+      demuxer_->GetStream(DemuxerStream::VIDEO),
       done_cb,
       base::Bind(&Pipeline::OnUpdateStatistics, base::Unretained(this)),
       base::Bind(&Pipeline::OnVideoTimeUpdate, base::Unretained(this)),
diff --git a/media/base/pipeline.h b/media/base/pipeline.h
index 9b0ebdf..4b78eb7 100644
--- a/media/base/pipeline.h
+++ b/media/base/pipeline.h
@@ -34,6 +34,17 @@
 class TextTrackConfig;
 class VideoRenderer;
 
+// Metadata describing a pipeline once it has been initialized.
+struct PipelineMetadata {
+  PipelineMetadata() : has_audio(false), has_video(false) {}
+
+  bool has_audio;
+  bool has_video;
+  gfx::Size natural_size;
+};
+
+typedef base::Callback<void(PipelineMetadata)> PipelineMetadataCB;
+
 // Pipeline runs the media pipeline.  Filters are created and called on the
 // task runner injected into this object. Pipeline works like a state
 // machine to perform asynchronous initialization, pausing, seeking and playing.
@@ -67,21 +78,6 @@
 // "Stopped" state.
 class MEDIA_EXPORT Pipeline : public DemuxerHost {
  public:
-  // Buffering states the pipeline transitions between during playback.
-  // kHaveMetadata:
-  //   Indicates that the following things are known:
-  //   content duration, container video size, start time, and whether the
-  //   content has audio and/or video in supported formats.
-  // kPrerollCompleted:
-  //   All renderers have buffered enough data to satisfy preroll and are ready
-  //   to start playback.
-  enum BufferingState {
-    kHaveMetadata,
-    kPrerollCompleted,
-  };
-
-  typedef base::Callback<void(BufferingState)> BufferingStateCB;
-
   // Constructs a media pipeline that will execute on |task_runner|.
   Pipeline(const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
            MediaLog* media_log);
@@ -97,18 +93,23 @@
   // The following permanent callbacks will be executed as follows up until
   // Stop() has completed:
   //   |ended_cb| will be executed whenever the media reaches the end.
-  //   |error_cb| will be executed whenever an error occurs but hasn't
-  //              been reported already through another callback.
-  //   |buffering_state_cb| Optional callback that will be executed whenever the
-  //                    pipeline's buffering state changes.
-  //   |duration_change_cb| Optional callback that will be executed whenever the
+  //   |error_cb| will be executed whenever an error occurs but hasn't been
+  //              reported already through another callback.
+  //   |metadata_cb| will be executed when the content duration, container video
+  //                 size, start time, and whether the content has audio and/or
+  //                 video in supported formats are known.
+  //   |preroll_completed_cb| will be executed when all renderers have buffered
+  //                          enough data to satisfy preroll and are ready to
+  //                          start playback.
+  //   |duration_change_cb| optional callback that will be executed whenever the
   //                        presentation duration changes.
   // It is an error to call this method after the pipeline has already started.
   void Start(scoped_ptr<FilterCollection> filter_collection,
              const base::Closure& ended_cb,
              const PipelineStatusCB& error_cb,
              const PipelineStatusCB& seek_cb,
-             const BufferingStateCB& buffering_state_cb,
+             const PipelineMetadataCB& metadata_cb,
+             const base::Closure& preroll_completed_cb,
              const base::Closure& duration_change_cb);
 
   // Asynchronously stops the pipeline, executing |stop_cb| when the pipeline
@@ -134,12 +135,6 @@
   // the pipeline.
   bool IsRunning() const;
 
-  // Returns true if the media has audio.
-  bool HasAudio() const;
-
-  // Returns true if the media has video.
-  bool HasVideo() const;
-
   // Gets the current playback rate of the pipeline.  When the pipeline is
   // started, the playback rate will be 0.0f.  A rate of 1.0f indicates
   // that the pipeline is rendering the media at the standard rate.  Valid
@@ -178,10 +173,6 @@
   // determined or can not be determined, this value is 0.
   int64 GetTotalBytes() const;
 
-  // Get the video's initial natural size as reported by the container. Note
-  // that the natural size can change during playback.
-  gfx::Size GetInitialNaturalSize() const;
-
   // Return true if loading progress has been made since the last time this
   // method was called.
   bool DidLoadingProgress() const;
@@ -262,12 +253,7 @@
   // The following "task" methods correspond to the public methods, but these
   // methods are run as the result of posting a task to the Pipeline's
   // task runner.
-  void StartTask(scoped_ptr<FilterCollection> filter_collection,
-                 const base::Closure& ended_cb,
-                 const PipelineStatusCB& error_cb,
-                 const PipelineStatusCB& seek_cb,
-                 const BufferingStateCB& buffering_state_cb,
-                 const base::Closure& duration_change_cb);
+  void StartTask();
 
   // Stops and destroys all filters, placing the pipeline in the kStopped state.
   void StopTask(const base::Closure& stop_cb);
@@ -370,9 +356,6 @@
   // Total size of the media.  Set by filters.
   int64 total_bytes_;
 
-  // The initial natural size of the video as reported by the container.
-  gfx::Size initial_natural_size_;
-
   // Current volume level (from 0.0f to 1.0f).  This value is set immediately
   // via SetVolume() and a task is dispatched on the task runner to notify the
   // filters.
@@ -402,13 +385,6 @@
   // reset the pipeline state, and restore this to PIPELINE_OK.
   PipelineStatus status_;
 
-  // Whether the media contains rendered audio or video streams.
-  // TODO(fischman,scherkus): replace these with checks for
-  // {audio,video}_decoder_ once extraction of {Audio,Video}Decoder from the
-  // Filter heirarchy is done.
-  bool has_audio_;
-  bool has_video_;
-
   // The following data members are only accessed by tasks posted to
   // |task_runner_|.
 
@@ -432,7 +408,8 @@
   // Permanent callbacks passed in via Start().
   base::Closure ended_cb_;
   PipelineStatusCB error_cb_;
-  BufferingStateCB buffering_state_cb_;
+  PipelineMetadataCB metadata_cb_;
+  base::Closure preroll_completed_cb_;
   base::Closure duration_change_cb_;
 
   // Contains the demuxer and renderers to use when initializing.
diff --git a/media/base/pipeline_unittest.cc b/media/base/pipeline_unittest.cc
index 3264226..6e51802 100644
--- a/media/base/pipeline_unittest.cc
+++ b/media/base/pipeline_unittest.cc
@@ -66,7 +66,8 @@
   MOCK_METHOD0(OnStop, void());
   MOCK_METHOD0(OnEnded, void());
   MOCK_METHOD1(OnError, void(PipelineStatus));
-  MOCK_METHOD1(OnBufferingState, void(Pipeline::BufferingState));
+  MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
+  MOCK_METHOD0(OnPrerollCompleted, void());
   MOCK_METHOD0(OnDurationChange, void());
 
  private:
@@ -203,7 +204,7 @@
     EXPECT_CALL(callbacks_, OnStart(start_status));
 
     if (start_status == PIPELINE_OK) {
-      EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata));
+      EXPECT_CALL(callbacks_, OnMetadata(_)).WillOnce(SaveArg<0>(&metadata_));
 
       if (audio_stream_) {
         EXPECT_CALL(*audio_renderer_, SetPlaybackRate(0.0f));
@@ -215,7 +216,7 @@
         EXPECT_CALL(*audio_renderer_, Play(_))
             .WillOnce(RunClosure<0>());
       }
-      EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
+      EXPECT_CALL(callbacks_, OnPrerollCompleted());
     }
 
     pipeline_->Start(
@@ -223,7 +224,8 @@
         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
-        base::Bind(&CallbackHelper::OnBufferingState,
+        base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
+        base::Bind(&CallbackHelper::OnPrerollCompleted,
                    base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnDurationChange,
                    base::Unretained(&callbacks_)));
@@ -286,7 +288,7 @@
           .WillOnce(RunClosure<0>());
     }
 
-    EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
+    EXPECT_CALL(callbacks_, OnPrerollCompleted());
 
     // We expect a successful seek callback.
     EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
@@ -340,6 +342,7 @@
   scoped_ptr<FakeTextTrackStream> text_stream_;
   AudioRenderer::TimeCB audio_time_cb_;
   VideoDecoderConfig video_decoder_config_;
+  PipelineMetadata metadata_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(PipelineTest);
@@ -351,8 +354,6 @@
   const base::TimeDelta kZero;
 
   EXPECT_FALSE(pipeline_->IsRunning());
-  EXPECT_FALSE(pipeline_->HasAudio());
-  EXPECT_FALSE(pipeline_->HasVideo());
 
   // Setting should still work.
   EXPECT_EQ(0.0f, pipeline_->GetPlaybackRate());
@@ -373,11 +374,6 @@
   EXPECT_TRUE(kZero == pipeline_->GetMediaDuration());
 
   EXPECT_EQ(0, pipeline_->GetTotalBytes());
-
-  // Should always be zero.
-  gfx::Size size = pipeline_->GetInitialNaturalSize();
-  EXPECT_EQ(0, size.width());
-  EXPECT_EQ(0, size.height());
 }
 
 TEST_F(PipelineTest, NeverInitializes) {
@@ -392,7 +388,8 @@
         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
-        base::Bind(&CallbackHelper::OnBufferingState,
+        base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
+        base::Bind(&CallbackHelper::OnPrerollCompleted,
                    base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnDurationChange,
                    base::Unretained(&callbacks_)));
@@ -433,8 +430,8 @@
   InitializeAudioRenderer(audio_stream(), false);
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_TRUE(pipeline_->HasAudio());
-  EXPECT_FALSE(pipeline_->HasVideo());
+  EXPECT_TRUE(metadata_.has_audio);
+  EXPECT_FALSE(metadata_.has_video);
 }
 
 TEST_F(PipelineTest, VideoStream) {
@@ -446,8 +443,8 @@
   InitializeVideoRenderer(video_stream());
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_FALSE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_FALSE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 }
 
 TEST_F(PipelineTest, AudioVideoStream) {
@@ -462,8 +459,8 @@
   InitializeVideoRenderer(video_stream());
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_TRUE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_TRUE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 }
 
 TEST_F(PipelineTest, VideoTextStream) {
@@ -476,8 +473,8 @@
   InitializeVideoRenderer(video_stream());
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_FALSE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_FALSE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 
   AddTextStream();
   message_loop_.RunUntilIdle();
@@ -496,8 +493,8 @@
   InitializeAudioRenderer(audio_stream(), false);
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_TRUE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_TRUE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 
   AddTextStream();
   message_loop_.RunUntilIdle();
@@ -623,8 +620,8 @@
   InitializeVideoRenderer(video_stream());
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_TRUE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_TRUE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 
   EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
   pipeline_->OnAudioDisabled();
@@ -648,8 +645,8 @@
   EXPECT_CALL(*demuxer_, OnAudioRendererDisabled());
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_FALSE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_TRUE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 
   // Verify that ended event is fired when video ends.
   EXPECT_CALL(callbacks_, OnEnded());
@@ -831,8 +828,8 @@
   InitializeVideoRenderer(video_stream());
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_FALSE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_FALSE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 
   EXPECT_EQ(base::TimeDelta(), pipeline_->GetMediaTime());
 }
@@ -852,8 +849,8 @@
   InitializeVideoRenderer(video_stream());
 
   InitializePipeline(PIPELINE_OK);
-  EXPECT_FALSE(pipeline_->HasAudio());
-  EXPECT_TRUE(pipeline_->HasVideo());
+  EXPECT_FALSE(metadata_.has_audio);
+  EXPECT_TRUE(metadata_.has_video);
 
   EXPECT_EQ(kStartTime, pipeline_->GetMediaTime());
 }
@@ -905,7 +902,7 @@
   EXPECT_CALL(*audio_renderer_, Play(_))
       .WillOnce(RunClosure<0>());
 
-  EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
+  EXPECT_CALL(callbacks_, OnPrerollCompleted());
   EXPECT_CALL(callbacks_, OnSeek(PIPELINE_OK));
   DoSeek(seek_time);
 
@@ -999,7 +996,8 @@
         base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)),
-        base::Bind(&CallbackHelper::OnBufferingState,
+        base::Bind(&CallbackHelper::OnMetadata, base::Unretained(&callbacks_)),
+        base::Bind(&CallbackHelper::OnPrerollCompleted,
                    base::Unretained(&callbacks_)),
         base::Bind(&CallbackHelper::OnDurationChange,
                    base::Unretained(&callbacks_)));
@@ -1076,7 +1074,7 @@
     EXPECT_CALL(*video_renderer_, Initialize(_, _, _, _, _, _, _, _))
         .WillOnce(RunCallback<1>(PIPELINE_OK));
 
-    EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kHaveMetadata));
+    EXPECT_CALL(callbacks_, OnMetadata(_));
 
     // If we get here it's a successful initialization.
     EXPECT_CALL(*audio_renderer_, Preroll(base::TimeDelta(), _))
@@ -1094,7 +1092,7 @@
         .WillOnce(RunClosure<0>());
 
     if (status == PIPELINE_OK)
-      EXPECT_CALL(callbacks_, OnBufferingState(Pipeline::kPrerollCompleted));
+      EXPECT_CALL(callbacks_, OnPrerollCompleted());
 
     return status;
   }
diff --git a/media/base/run_all_perftests.cc b/media/base/run_all_perftests.cc
index f9f53e7..ddfb8be 100644
--- a/media/base/run_all_perftests.cc
+++ b/media/base/run_all_perftests.cc
@@ -41,7 +41,6 @@
   media::InitializeMediaLibraryForTesting();
   CommandLine* cmd_line = CommandLine::ForCurrentProcess();
   cmd_line->AppendSwitch(switches::kEnableADTSStreamParser);
-  cmd_line->AppendSwitch(switches::kEnableMP3StreamParser);
 }
 
 int main(int argc, char** argv) {
diff --git a/media/base/run_all_unittests.cc b/media/base/run_all_unittests.cc
index 543098e..cb900de 100644
--- a/media/base/run_all_unittests.cc
+++ b/media/base/run_all_unittests.cc
@@ -41,7 +41,6 @@
   media::InitializeMediaLibraryForTesting();
   CommandLine* cmd_line = CommandLine::ForCurrentProcess();
   cmd_line->AppendSwitch(switches::kEnableADTSStreamParser);
-  cmd_line->AppendSwitch(switches::kEnableMP3StreamParser);
 }
 
 int main(int argc, char** argv) {
diff --git a/media/base/sinc_resampler.cc b/media/base/sinc_resampler.cc
index 82168db..1c527af 100644
--- a/media/base/sinc_resampler.cc
+++ b/media/base/sinc_resampler.cc
@@ -154,7 +154,7 @@
           base::AlignedAlloc(sizeof(float) * input_buffer_size_, 16))),
       r1_(input_buffer_.get()),
       r2_(input_buffer_.get() + kKernelSize / 2),
-      currently_resampling_(0) {
+      not_currently_resampling_(1) {
   CHECK_GT(request_frames_, 0);
   Flush();
   CHECK_GT(block_size_, kKernelSize)
@@ -172,7 +172,7 @@
 
 SincResampler::~SincResampler() {
   // TODO(dalecurtis): Remove debugging for http://crbug.com/295278
-  CHECK(base::AtomicRefCountIsZero(&currently_resampling_));
+  CHECK(!base::AtomicRefCountDec(&not_currently_resampling_));
 }
 
 void SincResampler::UpdateRegions(bool second_load) {
@@ -212,8 +212,8 @@
 
       // Compute Blackman window, matching the offset of the sinc().
       const float x = (i - subsample_offset) / kKernelSize;
-      const float window = kA0 - kA1 * cos(2.0 * M_PI * x) + kA2
-          * cos(4.0 * M_PI * x);
+      const float window =
+          kA0 - kA1 * cos(2.0 * M_PI * x) + kA2 * cos(4.0 * M_PI * x);
       kernel_window_storage_[idx] = window;
 
       // Compute the sinc with offset, then window the sinc() function and store
@@ -256,7 +256,7 @@
 }
 
 void SincResampler::Resample(int frames, float* destination) {
-  base::AtomicRefCountInc(&currently_resampling_);
+  CHECK(!base::AtomicRefCountDec(&not_currently_resampling_));
 
   int remaining_frames = frames;
 
@@ -271,18 +271,12 @@
   const double current_io_ratio = io_sample_rate_ratio_;
   const float* const kernel_ptr = kernel_storage_.get();
   while (remaining_frames) {
-    // |i| may be negative if the last Resample() call ended on an iteration
-    // that put |virtual_source_idx_| over the limit.
-    //
     // Note: The loop construct here can severely impact performance on ARM
     // or when built with clang.  See https://codereview.chromium.org/18566009/
-    for (int i = ceil((block_size_ - virtual_source_idx_) / current_io_ratio);
-         i > 0; --i) {
-      DCHECK_LT(virtual_source_idx_, block_size_);
-
+    int source_idx = virtual_source_idx_;
+    while (source_idx < block_size_) {
       // |virtual_source_idx_| lies in between two kernel offsets so figure out
       // what they are.
-      const int source_idx = virtual_source_idx_;
       const double subsample_remainder = virtual_source_idx_ - source_idx;
 
       const double virtual_offset_idx =
@@ -310,14 +304,16 @@
 
       // Advance the virtual index.
       virtual_source_idx_ += current_io_ratio;
+      source_idx = virtual_source_idx_;
 
       if (!--remaining_frames) {
-        CHECK(!base::AtomicRefCountDec(&currently_resampling_));
+        base::AtomicRefCountInc(&not_currently_resampling_);
         return;
       }
     }
 
     // Wrap back around to the start.
+    DCHECK_GE(virtual_source_idx_, block_size_);
     virtual_source_idx_ -= block_size_;
 
     // Step (3) -- Copy r3_, r4_ to r1_, r2_.
@@ -332,7 +328,7 @@
     read_cb_.Run(request_frames_, r0_);
   }
 
-  CHECK(!base::AtomicRefCountDec(&currently_resampling_));
+  base::AtomicRefCountInc(&not_currently_resampling_);
 }
 
 #undef CONVOLVE_FUNC
@@ -342,7 +338,7 @@
 }
 
 void SincResampler::Flush() {
-  CHECK(base::AtomicRefCountIsZero(&currently_resampling_));
+  CHECK(base::AtomicRefCountIsOne(&not_currently_resampling_));
   virtual_source_idx_ = 0;
   buffer_primed_ = false;
   memset(input_buffer_.get(), 0,
diff --git a/media/base/sinc_resampler.h b/media/base/sinc_resampler.h
index 07ecf09..2d0cdea 100644
--- a/media/base/sinc_resampler.h
+++ b/media/base/sinc_resampler.h
@@ -136,10 +136,10 @@
   float* r3_;
   float* r4_;
 
-  // Atomic ref count indicating when when we're in the middle of resampling.
-  // Will be CHECK'd to find crashes...
+  // Atomic ref count indicating when when we're not currently resampling.  Will
+  // be CHECK'd to find crashes...
   // TODO(dalecurtis): Remove debug helpers for http://crbug.com/295278
-  base::AtomicRefCount currently_resampling_;
+  base::AtomicRefCount not_currently_resampling_;
 
   DISALLOW_COPY_AND_ASSIGN(SincResampler);
 };
diff --git a/media/base/stream_parser_buffer.cc b/media/base/stream_parser_buffer.cc
index bceafbd..8f46f5f 100644
--- a/media/base/stream_parser_buffer.cc
+++ b/media/base/stream_parser_buffer.cc
@@ -9,13 +9,33 @@
 
 namespace media {
 
-static bool HasNestedFadeOutPreroll(
-    const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll) {
-  for (size_t i = 0; i < fade_out_preroll.size(); ++i) {
-    if (!fade_out_preroll[i]->GetFadeOutPreroll().empty())
-      return true;
+static scoped_refptr<StreamParserBuffer> CopyBuffer(
+    const StreamParserBuffer& buffer) {
+  if (buffer.end_of_stream())
+    return StreamParserBuffer::CreateEOSBuffer();
+
+  scoped_refptr<StreamParserBuffer> copied_buffer =
+      StreamParserBuffer::CopyFrom(buffer.data(),
+                                   buffer.data_size(),
+                                   buffer.side_data(),
+                                   buffer.side_data_size(),
+                                   buffer.IsKeyframe(),
+                                   buffer.type(),
+                                   buffer.track_id());
+  copied_buffer->SetDecodeTimestamp(buffer.GetDecodeTimestamp());
+  copied_buffer->SetConfigId(buffer.GetConfigId());
+  copied_buffer->set_timestamp(buffer.timestamp());
+  copied_buffer->set_duration(buffer.duration());
+  copied_buffer->set_discard_padding(buffer.discard_padding());
+  const DecryptConfig* decrypt_config = buffer.decrypt_config();
+  if (decrypt_config) {
+    copied_buffer->set_decrypt_config(
+        make_scoped_ptr(new DecryptConfig(decrypt_config->key_id(),
+                                          decrypt_config->iv(),
+                                          decrypt_config->subsamples())));
   }
-  return false;
+
+  return copied_buffer;
 }
 
 scoped_refptr<StreamParserBuffer> StreamParserBuffer::CreateEOSBuffer() {
@@ -68,8 +88,7 @@
   }
 }
 
-StreamParserBuffer::~StreamParserBuffer() {
-}
+StreamParserBuffer::~StreamParserBuffer() {}
 
 int StreamParserBuffer::GetConfigId() const {
   return config_id_;
@@ -79,15 +98,53 @@
   config_id_ = config_id;
 }
 
-const std::vector<scoped_refptr<StreamParserBuffer> >&
-StreamParserBuffer::GetFadeOutPreroll() const {
-  return fade_out_preroll_;
-}
+void StreamParserBuffer::ConvertToSpliceBuffer(
+    const BufferQueue& pre_splice_buffers) {
+  DCHECK(splice_buffers_.empty());
+  DCHECK(!end_of_stream());
 
-void StreamParserBuffer::SetFadeOutPreroll(
-    const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll) {
-  DCHECK(!HasNestedFadeOutPreroll(fade_out_preroll));
-  fade_out_preroll_ = fade_out_preroll;
+  // Make a copy of this first, before making any changes.
+  scoped_refptr<StreamParserBuffer> overlapping_buffer = CopyBuffer(*this);
+
+  const scoped_refptr<StreamParserBuffer>& first_splice_buffer =
+      pre_splice_buffers.front();
+
+  // Ensure the given buffers are actually before the splice point.
+  DCHECK(first_splice_buffer->timestamp() <= overlapping_buffer->timestamp());
+
+  // TODO(dalecurtis): We should also clear |data| and |side_data|, but since
+  // that implies EOS care must be taken to ensure there are no clients relying
+  // on that behavior.
+
+  // Rewrite |this| buffer as a splice buffer.
+  SetDecodeTimestamp(first_splice_buffer->GetDecodeTimestamp());
+  SetConfigId(first_splice_buffer->GetConfigId());
+  set_timestamp(first_splice_buffer->timestamp());
+  is_keyframe_ = first_splice_buffer->IsKeyframe();
+  type_ = first_splice_buffer->type();
+  track_id_ = first_splice_buffer->track_id();
+  set_splice_timestamp(overlapping_buffer->timestamp());
+
+  // The splice duration is the duration of all buffers before the splice plus
+  // the highest ending timestamp after the splice point.
+  set_duration(
+      std::max(overlapping_buffer->timestamp() + overlapping_buffer->duration(),
+               pre_splice_buffers.back()->timestamp() +
+                   pre_splice_buffers.back()->duration()) -
+      first_splice_buffer->timestamp());
+
+  // Copy all pre splice buffers into our wrapper buffer.
+  for (BufferQueue::const_iterator it = pre_splice_buffers.begin();
+       it != pre_splice_buffers.end();
+       ++it) {
+    const scoped_refptr<StreamParserBuffer>& buffer = *it;
+    DCHECK(!buffer->end_of_stream());
+    DCHECK(buffer->get_splice_buffers().empty());
+    buffer->set_splice_timestamp(splice_timestamp());
+    splice_buffers_.push_back(CopyBuffer(*buffer));
+  }
+
+  splice_buffers_.push_back(overlapping_buffer);
 }
 
 }  // namespace media
diff --git a/media/base/stream_parser_buffer.h b/media/base/stream_parser_buffer.h
index 146e78a..0dbb1b3 100644
--- a/media/base/stream_parser_buffer.h
+++ b/media/base/stream_parser_buffer.h
@@ -5,6 +5,8 @@
 #ifndef MEDIA_BASE_STREAM_PARSER_BUFFER_H_
 #define MEDIA_BASE_STREAM_PARSER_BUFFER_H_
 
+#include <deque>
+
 #include "media/base/decoder_buffer.h"
 #include "media/base/demuxer_stream.h"
 #include "media/base/media_export.h"
@@ -21,6 +23,7 @@
   typedef StreamParser::TrackId TrackId;
 
   static scoped_refptr<StreamParserBuffer> CreateEOSBuffer();
+
   static scoped_refptr<StreamParserBuffer> CopyFrom(
       const uint8* data, int data_size, bool is_keyframe, Type type,
       TrackId track_id);
@@ -47,12 +50,17 @@
   // meaningless for EOS buffers.
   TrackId track_id() const { return track_id_; }
 
-  // Buffers to be exhausted before using the data in this DecoderBuffer.  Used
-  // to implement the Audio Splice Frame Algorithm per the MSE specification.
-  const std::vector<scoped_refptr<StreamParserBuffer> >& GetFadeOutPreroll()
-      const;
-  void SetFadeOutPreroll(
-      const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll);
+  // Converts this buffer to a splice buffer.  |pre_splice_buffers| must not
+  // have any  EOS buffers and must not have any nested splice buffers.
+  //
+  // |pre_splice_buffers| will be deep copied and each copy's splice_timestamp()
+  // will be set to this buffer's splice_timestamp().  A copy of |this| will be
+  // added to the end of |splice_buffers_|.
+  //
+  // See the Audio Splice Frame Algorithm in the MSE specification for details.
+  typedef StreamParser::BufferQueue BufferQueue;
+  void ConvertToSpliceBuffer(const BufferQueue& pre_splice_buffers);
+  const BufferQueue& get_splice_buffers() const { return splice_buffers_; }
 
  private:
   StreamParserBuffer(const uint8* data, int data_size,
@@ -67,7 +75,7 @@
   Type type_;
   TrackId track_id_;
 
-  std::vector<scoped_refptr<StreamParserBuffer> > fade_out_preroll_;
+  BufferQueue splice_buffers_;
 
   DISALLOW_COPY_AND_ASSIGN(StreamParserBuffer);
 };
diff --git a/media/base/test_helpers.cc b/media/base/test_helpers.cc
index 6cd0690..fd571dd 100644
--- a/media/base/test_helpers.cc
+++ b/media/base/test_helpers.cc
@@ -151,6 +151,7 @@
 template <class T>
 scoped_refptr<AudioBuffer> MakeAudioBuffer(SampleFormat format,
                                            ChannelLayout channel_layout,
+                                           int channel_count,
                                            int sample_rate,
                                            T start,
                                            T increment,
@@ -158,8 +159,8 @@
                                            base::TimeDelta timestamp,
                                            base::TimeDelta duration) {
   int channels = ChannelLayoutToChannelCount(channel_layout);
-  scoped_refptr<AudioBuffer> output =
-      AudioBuffer::CreateBuffer(format, channel_layout, sample_rate, frames);
+  scoped_refptr<AudioBuffer> output = AudioBuffer::CreateBuffer(
+      format, channel_layout, channel_count, sample_rate, frames);
   output->set_timestamp(timestamp);
   output->set_duration(duration);
 
@@ -198,6 +199,7 @@
   template scoped_refptr<AudioBuffer> MakeAudioBuffer<type>( \
       SampleFormat format,                                   \
       ChannelLayout channel_layout,                          \
+      int channel_count,                                     \
       int sample_rate,                                       \
       type start,                                            \
       type increment,                                        \
diff --git a/media/base/test_helpers.h b/media/base/test_helpers.h
index eb5b1f5..f342af4 100644
--- a/media/base/test_helpers.h
+++ b/media/base/test_helpers.h
@@ -114,6 +114,7 @@
 template <class T>
 scoped_refptr<AudioBuffer> MakeAudioBuffer(SampleFormat format,
                                            ChannelLayout channel_layout,
+                                           int channel_count,
                                            int sample_rate,
                                            T start,
                                            T increment,
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
index 64e8989..874e23a 100644
--- a/media/base/video_frame.cc
+++ b/media/base/video_frame.cc
@@ -18,6 +18,12 @@
 
 namespace media {
 
+static inline size_t RoundUp(size_t value, size_t alignment) {
+  // Check that |alignment| is a power of 2.
+  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
+  return ((value + (alignment - 1)) & ~(alignment - 1));
+}
+
 // static
 scoped_refptr<VideoFrame> VideoFrame::CreateFrame(
     VideoFrame::Format format,
@@ -25,20 +31,28 @@
     const gfx::Rect& visible_rect,
     const gfx::Size& natural_size,
     base::TimeDelta timestamp) {
-  DCHECK(IsValidConfig(format, coded_size, visible_rect, natural_size));
-  scoped_refptr<VideoFrame> frame(new VideoFrame(
-      format, coded_size, visible_rect, natural_size, timestamp, false));
+  // Since we're creating a new YUV frame (and allocating memory for it
+  // ourselves), we can pad the requested |coded_size| if necessary if the
+  // request does not line up on sample boundaries.
+  gfx::Size new_coded_size(coded_size);
   switch (format) {
     case VideoFrame::YV12:
     case VideoFrame::YV12A:
-    case VideoFrame::YV16:
     case VideoFrame::I420:
     case VideoFrame::YV12J:
-      frame->AllocateYUV();
+      new_coded_size.set_height((new_coded_size.height() + 1) / 2 * 2);
+    // Fallthrough.
+    case VideoFrame::YV16:
+      new_coded_size.set_width((new_coded_size.width() + 1) / 2 * 2);
       break;
     default:
-      LOG(FATAL) << "Unsupported frame format: " << format;
+      LOG(FATAL) << "Only YUV formats supported: " << format;
+      return NULL;
   }
+  DCHECK(IsValidConfig(format, new_coded_size, visible_rect, natural_size));
+  scoped_refptr<VideoFrame> frame(new VideoFrame(
+      format, new_coded_size, visible_rect, natural_size, timestamp, false));
+  frame->AllocateYUV();
   return frame;
 }
 
@@ -73,19 +87,49 @@
                                const gfx::Size& coded_size,
                                const gfx::Rect& visible_rect,
                                const gfx::Size& natural_size) {
-  return (format != VideoFrame::UNKNOWN &&
-          !coded_size.IsEmpty() &&
-          coded_size.GetArea() <= limits::kMaxCanvas &&
-          coded_size.width() <= limits::kMaxDimension &&
-          coded_size.height() <= limits::kMaxDimension &&
-          !visible_rect.IsEmpty() &&
-          visible_rect.x() >= 0 && visible_rect.y() >= 0 &&
-          visible_rect.right() <= coded_size.width() &&
-          visible_rect.bottom() <= coded_size.height() &&
-          !natural_size.IsEmpty() &&
-          natural_size.GetArea() <= limits::kMaxCanvas &&
-          natural_size.width() <= limits::kMaxDimension &&
-          natural_size.height() <= limits::kMaxDimension);
+  // Check maximum limits for all formats.
+  if (coded_size.GetArea() > limits::kMaxCanvas ||
+      coded_size.width() > limits::kMaxDimension ||
+      coded_size.height() > limits::kMaxDimension ||
+      visible_rect.x() < 0 || visible_rect.y() < 0 ||
+      visible_rect.right() > coded_size.width() ||
+      visible_rect.bottom() > coded_size.height() ||
+      natural_size.GetArea() > limits::kMaxCanvas ||
+      natural_size.width() > limits::kMaxDimension ||
+      natural_size.height() > limits::kMaxDimension)
+    return false;
+
+  // Check format-specific width/height requirements.
+  switch (format) {
+    case VideoFrame::UNKNOWN:
+      return (coded_size.IsEmpty() && visible_rect.IsEmpty() &&
+              natural_size.IsEmpty());
+    case VideoFrame::YV12:
+    case VideoFrame::YV12J:
+    case VideoFrame::I420:
+    case VideoFrame::YV12A:
+      // YUV formats have width/height requirements due to chroma subsampling.
+      if (static_cast<size_t>(coded_size.height()) <
+          RoundUp(visible_rect.bottom(), 2))
+        return false;
+    // Fallthrough.
+    case VideoFrame::YV16:
+      if (static_cast<size_t>(coded_size.width()) <
+          RoundUp(visible_rect.right(), 2))
+        return false;
+      break;
+    case VideoFrame::NATIVE_TEXTURE:
+#if defined(VIDEO_HOLE)
+    case VideoFrame::HOLE:
+#endif  // defined(VIDEO_HOLE)
+      // NATIVE_TEXTURE and HOLE have no software-allocated buffers and are
+      // allowed to skip the below check and be empty.
+      return true;
+  }
+
+  // Check that software-allocated buffer formats are not empty.
+  return (!coded_size.IsEmpty() && !visible_rect.IsEmpty() &&
+          !natural_size.IsEmpty());
 }
 
 // static
@@ -127,6 +171,8 @@
     base::SharedMemoryHandle handle,
     base::TimeDelta timestamp,
     const base::Closure& no_longer_needed_cb) {
+  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
+    return NULL;
   if (data_size < AllocationSize(format, coded_size))
     return NULL;
 
@@ -164,7 +210,9 @@
     uint8* v_data,
     base::TimeDelta timestamp,
     const base::Closure& no_longer_needed_cb) {
-  DCHECK(format == YV12 || format == YV16 || format == I420) << format;
+  if (!IsValidConfig(format, coded_size, visible_rect, natural_size))
+    return NULL;
+
   scoped_refptr<VideoFrame> frame(new VideoFrame(
       format, coded_size, visible_rect, natural_size, timestamp, false));
   frame->strides_[kYPlane] = y_stride;
@@ -212,7 +260,6 @@
     const gfx::Size& size,
     uint8 y, uint8 u, uint8 v,
     base::TimeDelta timestamp) {
-  DCHECK(IsValidConfig(VideoFrame::YV12, size, gfx::Rect(size), size));
   scoped_refptr<VideoFrame> frame = VideoFrame::CreateFrame(
       VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
   FillYUV(frame.get(), y, u, v);
@@ -267,11 +314,6 @@
   return 0;
 }
 
-static inline size_t RoundUp(size_t value, size_t alignment) {
-  // Check that |alignment| is a power of 2.
-  DCHECK((alignment + (alignment - 1)) == (alignment | (alignment - 1)));
-  return ((value + (alignment - 1)) & ~(alignment-1));
-}
 
 // static
 size_t VideoFrame::AllocationSize(Format format, const gfx::Size& coded_size) {
@@ -282,21 +324,21 @@
 }
 
 // static
-size_t VideoFrame::PlaneAllocationSize(Format format,
-                                       size_t plane,
-                                       const gfx::Size& coded_size) {
-  const size_t area =
-      RoundUp(coded_size.width(), 2) * RoundUp(coded_size.height(), 2);
+gfx::Size VideoFrame::PlaneSize(Format format,
+                                size_t plane,
+                                const gfx::Size& coded_size) {
+  const int width = RoundUp(coded_size.width(), 2);
+  const int height = RoundUp(coded_size.height(), 2);
   switch (format) {
     case VideoFrame::YV12:
     case VideoFrame::YV12J:
     case VideoFrame::I420: {
       switch (plane) {
         case VideoFrame::kYPlane:
-          return area;
+          return gfx::Size(width, height);
         case VideoFrame::kUPlane:
         case VideoFrame::kVPlane:
-          return area / 4;
+          return gfx::Size(width / 2, height / 2);
         default:
           break;
       }
@@ -305,10 +347,10 @@
       switch (plane) {
         case VideoFrame::kYPlane:
         case VideoFrame::kAPlane:
-          return area;
+          return gfx::Size(width, height);
         case VideoFrame::kUPlane:
         case VideoFrame::kVPlane:
-          return area / 4;
+          return gfx::Size(width / 2, height / 2);
         default:
           break;
       }
@@ -316,10 +358,10 @@
     case VideoFrame::YV16: {
       switch (plane) {
         case VideoFrame::kYPlane:
-          return area;
+          return gfx::Size(width, height);
         case VideoFrame::kUPlane:
         case VideoFrame::kVPlane:
-          return area / 2;
+          return gfx::Size(width / 2, height);
         default:
           break;
       }
@@ -333,7 +375,14 @@
   }
   NOTREACHED() << "Unsupported video frame format/plane: "
                << format << "/" << plane;
-  return 0;
+  return gfx::Size();
+}
+
+size_t VideoFrame::PlaneAllocationSize(Format format,
+                                       size_t plane,
+                                       const gfx::Size& coded_size) {
+  // VideoFrame formats are (so far) all YUV and 1 byte per sample.
+  return PlaneSize(format, plane, coded_size).GetArea();
 }
 
 // Release data allocated by AllocateYUV().
@@ -409,6 +458,8 @@
       shared_memory_handle_(base::SharedMemory::NULLHandle()),
       timestamp_(timestamp),
       end_of_stream_(end_of_stream) {
+  DCHECK(IsValidConfig(format_, coded_size_, visible_rect_, natural_size_));
+
   memset(&strides_, 0, sizeof(strides_));
   memset(&data_, 0, sizeof(data_));
 }
diff --git a/media/base/video_frame.h b/media/base/video_frame.h
index 0c69627..aa9c078 100644
--- a/media/base/video_frame.h
+++ b/media/base/video_frame.h
@@ -60,11 +60,6 @@
 
   // Creates a new frame in system memory with given parameters. Buffers for
   // the frame are allocated but not initialized.
-  // |coded_size| is the width and height of the frame data in pixels.
-  // |visible_rect| is the visible portion of |coded_size|, after cropping (if
-  // any) is applied.
-  // |natural_size| is the width and height of the frame when the frame's aspect
-  // ratio is applied to |visible_rect|.
   static scoped_refptr<VideoFrame> CreateFrame(
       Format format,
       const gfx::Size& coded_size,
@@ -91,12 +86,6 @@
   // backing of the VideoFrame is held in the mailbox held by |mailbox_holder|,
   // and |mailbox_holder_release_cb| will be called with |mailbox_holder| as the
   // argument when the VideoFrame is to be destroyed.
-  // |coded_size| is the width and height of the frame data in pixels.
-  // |visible_rect| is the visible portion of |coded_size|, after cropping (if
-  // any) is applied.
-  // |natural_size| is the width and height of the frame when the frame's aspect
-  // ratio is applied to |visible_rect|.
-
   // |read_pixels_cb| may be used to do (slow!) readbacks from the
   // texture to main memory.
   static scoped_refptr<VideoFrame> WrapNativeTexture(
@@ -110,7 +99,7 @@
 
   // Read pixels from the native texture backing |*this| and write
   // them to |pixels| as BGRA.  |pixels| must point to a buffer at
-  // least as large as 4*visible_rect().width()*visible_rect().height().
+  // least as large as 4 * visible_rect().size().GetArea().
   void ReadPixelsFromNativeTexture(const SkBitmap& pixels);
 
   // Wraps packed image data residing in a memory buffer with a VideoFrame.
@@ -182,6 +171,11 @@
   // given coded size and format.
   static size_t AllocationSize(Format format, const gfx::Size& coded_size);
 
+  // Returns the plane size for a plane of the given coded size and format.
+  static gfx::Size PlaneSize(Format format,
+                             size_t plane,
+                             const gfx::Size& coded_size);
+
   // Returns the required allocation size for a (tightly packed) plane of the
   // given coded size and format.
   static size_t PlaneAllocationSize(Format format,
@@ -246,17 +240,23 @@
   bool IsValidPlane(size_t plane) const;
 
   // Frame format.
-  Format format_;
+  const Format format_;
 
-  // Width and height of the video frame.
-  gfx::Size coded_size_;
+  // Width and height of the video frame, in pixels. This must include pixel
+  // data for the whole image; i.e. for YUV formats with subsampled chroma
+  // planes, in the case that the visible portion of the image does not line up
+  // on a sample boundary, |coded_size_| must be rounded up appropriately and
+  // the pixel data provided for the odd pixels.
+  const gfx::Size coded_size_;
 
-  // Width, height, and offsets of the visible portion of the video frame.
-  gfx::Rect visible_rect_;
+  // Width, height, and offsets of the visible portion of the video frame. Must
+  // be a subrect of |coded_size_|. Can be odd with respect to the sample
+  // boundaries, e.g. for formats with subsampled chroma.
+  const gfx::Rect visible_rect_;
 
-  // Width and height of the visible portion of the video frame with aspect
-  // ratio taken into account.
-  gfx::Size natural_size_;
+  // Width and height of the visible portion of the video frame
+  // (|visible_rect_.size()|) with aspect ratio taken into account.
+  const gfx::Size natural_size_;
 
   // Array of strides for each plane, typically greater or equal to the width
   // of the surface divided by the horizontal sampling period.  Note that
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc
index 967d376..9229b6a 100644
--- a/media/base/video_frame_unittest.cc
+++ b/media/base/video_frame_unittest.cc
@@ -88,8 +88,7 @@
 // Fill each plane to its reported extents and verify accessors report non
 // zero values.  Additionally, for the first plane verify the rows and
 // row_bytes values are correct.
-void ExpectFrameExtents(VideoFrame::Format format, int planes,
-                        int bytes_per_pixel, const char* expected_hash) {
+void ExpectFrameExtents(VideoFrame::Format format, const char* expected_hash) {
   const unsigned char kFillByte = 0x80;
   const int kWidth = 61;
   const int kHeight = 31;
@@ -100,18 +99,14 @@
       format, size, gfx::Rect(size), size, kTimestamp);
   ASSERT_TRUE(frame.get());
 
-  for(int plane = 0; plane < planes; plane++) {
+  int planes = VideoFrame::NumPlanes(format);
+  for (int plane = 0; plane < planes; plane++) {
     SCOPED_TRACE(base::StringPrintf("Checking plane %d", plane));
     EXPECT_TRUE(frame->data(plane));
     EXPECT_TRUE(frame->stride(plane));
     EXPECT_TRUE(frame->rows(plane));
     EXPECT_TRUE(frame->row_bytes(plane));
 
-    if (plane == 0) {
-      EXPECT_EQ(frame->rows(plane), kHeight);
-      EXPECT_EQ(frame->row_bytes(plane), kWidth * bytes_per_pixel);
-    }
-
     memset(frame->data(plane), kFillByte,
            frame->stride(plane) * frame->rows(plane));
   }
@@ -239,13 +234,10 @@
 // Ensure each frame is properly sized and allocated.  Will trigger OOB reads
 // and writes as well as incorrect frame hashes otherwise.
 TEST(VideoFrame, CheckFrameExtents) {
-  // Each call consists of a VideoFrame::Format, # of planes, bytes per pixel,
-  // and the expected hash of all planes if filled with kFillByte (defined in
-  // ExpectFrameExtents).
-  ExpectFrameExtents(
-      VideoFrame::YV12,   3, 1, "71113bdfd4c0de6cf62f48fb74f7a0b1");
-  ExpectFrameExtents(
-      VideoFrame::YV16,   3, 1, "9bb99ac3ff350644ebff4d28dc01b461");
+  // Each call consists of a VideoFrame::Format and the expected hash of all
+  // planes if filled with kFillByte (defined in ExpectFrameExtents).
+  ExpectFrameExtents(VideoFrame::YV12, "8e5d54cb23cd0edca111dd35ffb6ff05");
+  ExpectFrameExtents(VideoFrame::YV16, "cce408a044b212db42a10dfec304b3ef");
 }
 
 static void TextureCallback(uint32* called_sync_point,
diff --git a/media/cast/audio_receiver/audio_decoder.cc b/media/cast/audio_receiver/audio_decoder.cc
index 2033199..b1a8256 100644
--- a/media/cast/audio_receiver/audio_decoder.cc
+++ b/media/cast/audio_receiver/audio_decoder.cc
@@ -62,7 +62,7 @@
                                     int desired_frequency,
                                     PcmAudioFrame* audio_frame,
                                     uint32* rtp_timestamp) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO_DECODER));
+  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO));
   // We don't care about the race case where a packet arrives at the same time
   // as this function in called. The data will be there the next time this
   // function is called.
diff --git a/media/cast/audio_receiver/audio_decoder_unittest.cc b/media/cast/audio_receiver/audio_decoder_unittest.cc
index 703d733..46629b9 100644
--- a/media/cast/audio_receiver/audio_decoder_unittest.cc
+++ b/media/cast/audio_receiver/audio_decoder_unittest.cc
@@ -34,11 +34,7 @@
         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
                             task_runner_,
                             task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            GetDefaultCastReceiverLoggingConfig());
+                            task_runner_);
   }
   virtual ~AudioDecoderTest() {}
 
diff --git a/media/cast/audio_receiver/audio_receiver.cc b/media/cast/audio_receiver/audio_receiver.cc
index f7988f5..e7b126c 100644
--- a/media/cast/audio_receiver/audio_receiver.cc
+++ b/media/cast/audio_receiver/audio_receiver.cc
@@ -31,24 +31,6 @@
 
 DecodedAudioCallbackData::~DecodedAudioCallbackData() {}
 
-// Local implementation of RtpData (defined in rtp_rtcp_defines.h).
-// Used to pass payload data into the audio receiver.
-class LocalRtpAudioData : public RtpData {
- public:
-  explicit LocalRtpAudioData(AudioReceiver* audio_receiver)
-      : audio_receiver_(audio_receiver) {}
-
-  virtual void OnReceivedPayloadData(const uint8* payload_data,
-                                     size_t payload_size,
-                                     const RtpCastHeader* rtp_header) OVERRIDE {
-    audio_receiver_->IncomingParsedRtpPacket(payload_data, payload_size,
-                                             *rtp_header);
-  }
-
- private:
-  AudioReceiver* audio_receiver_;
-};
-
 // Local implementation of RtpPayloadFeedback (defined in rtp_defines.h)
 // Used to convey cast-specific feedback from receiver to sender.
 class LocalRtpAudioFeedback : public RtpPayloadFeedback {
@@ -64,27 +46,11 @@
   AudioReceiver* audio_receiver_;
 };
 
-class LocalRtpReceiverStatistics : public RtpReceiverStatistics {
- public:
-  explicit LocalRtpReceiverStatistics(RtpReceiver* rtp_receiver)
-      : rtp_receiver_(rtp_receiver) {}
-
-  virtual void GetStatistics(uint8* fraction_lost,
-                             uint32* cumulative_lost,  // 24 bits valid.
-                             uint32* extended_high_sequence_number,
-                             uint32* jitter) OVERRIDE {
-    rtp_receiver_->GetStatistics(fraction_lost, cumulative_lost,
-                                 extended_high_sequence_number, jitter);
-  }
-
- private:
-  RtpReceiver* rtp_receiver_;
-};
-
 AudioReceiver::AudioReceiver(scoped_refptr<CastEnvironment> cast_environment,
                              const AudioReceiverConfig& audio_config,
                              transport::PacedPacketSender* const packet_sender)
-    : cast_environment_(cast_environment),
+    : RtpReceiver(cast_environment->Clock(), &audio_config, NULL),
+      cast_environment_(cast_environment),
       event_subscriber_(kReceiverRtcpEventHistorySize,
                         ReceiverRtcpEventSubscriber::kAudioEventSubscriber),
       codec_(audio_config.codec),
@@ -95,7 +61,6 @@
       weak_factory_(this) {
   target_delay_delta_ =
       base::TimeDelta::FromMilliseconds(audio_config.rtp_max_delay_ms);
-  incoming_payload_callback_.reset(new LocalRtpAudioData(this));
   incoming_payload_feedback_.reset(new LocalRtpAudioFeedback(this));
   if (audio_config.use_external_decoder) {
     audio_buffer_.reset(new Framer(cast_environment->Clock(),
@@ -106,16 +71,10 @@
                                           incoming_payload_feedback_.get()));
   }
   decryptor_.Initialize(audio_config.aes_key, audio_config.aes_iv_mask);
-  rtp_receiver_.reset(new RtpReceiver(cast_environment->Clock(),
-                                      &audio_config,
-                                      NULL,
-                                      incoming_payload_callback_.get()));
-  rtp_audio_receiver_statistics_.reset(
-      new LocalRtpReceiverStatistics(rtp_receiver_.get()));
   base::TimeDelta rtcp_interval_delta =
       base::TimeDelta::FromMilliseconds(audio_config.rtcp_interval);
   rtcp_.reset(new Rtcp(cast_environment, NULL, NULL, packet_sender,
-                       rtp_audio_receiver_statistics_.get(),
+                       GetStatistics(),
                        audio_config.rtcp_mode, rtcp_interval_delta,
                        audio_config.feedback_ssrc, audio_config.incoming_ssrc,
                        audio_config.rtcp_c_name));
@@ -135,9 +94,9 @@
   ScheduleNextCastMessage();
 }
 
-void AudioReceiver::IncomingParsedRtpPacket(const uint8* payload_data,
-                                            size_t payload_size,
-                                            const RtpCastHeader& rtp_header) {
+void AudioReceiver::OnReceivedPayloadData(const uint8* payload_data,
+                                          size_t payload_size,
+                                          const RtpCastHeader& rtp_header) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
 
@@ -149,7 +108,6 @@
       payload_size);
 
   // TODO(pwestin): update this as video to refresh over time.
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   if (time_first_incoming_packet_.is_null()) {
     InitializeTimers();
     first_incoming_rtp_timestamp_ = rtp_header.webrtc.header.timestamp;
@@ -177,7 +135,7 @@
       DecodedAudioCallbackData decoded_data = queued_decoded_callbacks_.front();
       queued_decoded_callbacks_.pop_front();
       cast_environment_->PostTask(
-          CastEnvironment::AUDIO_DECODER, FROM_HERE,
+          CastEnvironment::AUDIO, FROM_HERE,
           base::Bind(&AudioReceiver::DecodeAudioFrameThread,
                      base::Unretained(this), decoded_data.number_of_10ms_blocks,
                      decoded_data.desired_frequency, decoded_data.callback));
@@ -215,7 +173,7 @@
   DCHECK(audio_decoder_) << "Invalid function call in this configuration";
   // TODO(pwestin): we can skip this function by posting direct to the decoder.
   cast_environment_->PostTask(
-      CastEnvironment::AUDIO_DECODER, FROM_HERE,
+      CastEnvironment::AUDIO, FROM_HERE,
       base::Bind(&AudioReceiver::DecodeAudioFrameThread, base::Unretained(this),
                  number_of_10ms_blocks, desired_frequency, callback));
 }
@@ -223,7 +181,7 @@
 void AudioReceiver::DecodeAudioFrameThread(
     int number_of_10ms_blocks, int desired_frequency,
     const AudioFrameDecodedCallback callback) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO_DECODER));
+  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::AUDIO));
   // TODO(mikhal): Allow the application to allocate this memory.
   scoped_ptr<PcmAudioFrame> audio_frame(new PcmAudioFrame());
 
@@ -363,7 +321,7 @@
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   bool rtcp_packet = Rtcp::IsRtcpPacket(&packet->front(), packet->size());
   if (!rtcp_packet) {
-    rtp_receiver_->ReceivedPacket(&packet->front(), packet->size());
+    ReceivedPacket(&packet->front(), packet->size());
   } else {
     rtcp_->IncomingRtcpPacket(&packet->front(), packet->size());
   }
diff --git a/media/cast/audio_receiver/audio_receiver.gypi b/media/cast/audio_receiver/audio_receiver.gypi
index 1c64b84..16b425c 100644
--- a/media/cast/audio_receiver/audio_receiver.gypi
+++ b/media/cast/audio_receiver/audio_receiver.gypi
@@ -19,7 +19,7 @@
         'audio_receiver.cc',
       ], # source
       'dependencies': [
-        '<(DEPTH)/media/cast/transport/utility/utility.gypi:transport_utility',
+        '<(DEPTH)/media/cast/transport/utility/utility.gyp:transport_utility',
         '<(DEPTH)/media/cast/rtcp/rtcp.gyp:cast_rtcp',
         '<(DEPTH)/media/cast/rtp_receiver/rtp_receiver.gyp:cast_rtp_receiver',
         '<(DEPTH)/third_party/webrtc/webrtc.gyp:webrtc',
diff --git a/media/cast/audio_receiver/audio_receiver.h b/media/cast/audio_receiver/audio_receiver.h
index 6270498..cbf52f9 100644
--- a/media/cast/audio_receiver/audio_receiver.h
+++ b/media/cast/audio_receiver/audio_receiver.h
@@ -19,6 +19,7 @@
 #include "media/cast/cast_receiver.h"
 #include "media/cast/rtcp/receiver_rtcp_event_subscriber.h"
 #include "media/cast/rtcp/rtcp.h"                          // RtcpCastMessage
+#include "media/cast/rtp_receiver/rtp_receiver.h"
 #include "media/cast/rtp_receiver/rtp_receiver_defines.h"  // RtpCastHeader
 #include "media/cast/transport/utility/transport_encryption_handler.h"
 
@@ -27,7 +28,6 @@
 
 class AudioDecoder;
 class Framer;
-class LocalRtpAudioData;
 class LocalRtpAudioFeedback;
 class RtpReceiver;
 class RtpReceiverStatistics;
@@ -43,7 +43,8 @@
 // This class is not thread safe. Should only be called from the Main cast
 // thread.
 class AudioReceiver : public base::NonThreadSafe,
-                      public base::SupportsWeakPtr<AudioReceiver> {
+                      public base::SupportsWeakPtr<AudioReceiver>,
+                      public RtpReceiver {
  public:
   AudioReceiver(scoped_refptr<CastEnvironment> cast_environment,
                 const AudioReceiverConfig& audio_config,
@@ -67,13 +68,11 @@
   // will also be updated (will be included in all outgoing reports).
   void SetTargetDelay(base::TimeDelta target_delay);
 
- protected:
-  void IncomingParsedRtpPacket(const uint8* payload_data,
-                               size_t payload_size,
-                               const RtpCastHeader& rtp_header);
+  virtual void OnReceivedPayloadData(const uint8* payload_data,
+                                     size_t payload_size,
+                                     const RtpCastHeader& rtp_header) OVERRIDE;
 
  private:
-  friend class LocalRtpAudioData;
   friend class LocalRtpAudioFeedback;
 
   void CastFeedback(const RtcpCastMessage& cast_message);
@@ -128,11 +127,8 @@
   base::TimeDelta target_delay_delta_;
   scoped_ptr<Framer> audio_buffer_;
   scoped_ptr<AudioDecoder> audio_decoder_;
-  scoped_ptr<LocalRtpAudioData> incoming_payload_callback_;
   scoped_ptr<LocalRtpAudioFeedback> incoming_payload_feedback_;
-  scoped_ptr<RtpReceiver> rtp_receiver_;
   scoped_ptr<Rtcp> rtcp_;
-  scoped_ptr<RtpReceiverStatistics> rtp_audio_receiver_statistics_;
   base::TimeDelta time_offset_;
   base::TimeTicks time_first_incoming_packet_;
   uint32 first_incoming_rtp_timestamp_;
diff --git a/media/cast/audio_receiver/audio_receiver_unittest.cc b/media/cast/audio_receiver/audio_receiver_unittest.cc
index 9d4917a..17721da 100644
--- a/media/cast/audio_receiver/audio_receiver_unittest.cc
+++ b/media/cast/audio_receiver/audio_receiver_unittest.cc
@@ -57,16 +57,6 @@
 };
 }  // namespace
 
-class PeerAudioReceiver : public AudioReceiver {
- public:
-  PeerAudioReceiver(scoped_refptr<CastEnvironment> cast_environment,
-                    const AudioReceiverConfig& audio_config,
-                    transport::PacedPacketSender* const packet_sender)
-      : AudioReceiver(cast_environment, audio_config, packet_sender) {}
-
-  using AudioReceiver::IncomingParsedRtpPacket;
-};
-
 class AudioReceiverTest : public ::testing::Test {
  protected:
   AudioReceiverTest() {
@@ -82,21 +72,19 @@
         base::TimeDelta::FromMilliseconds(kStartMillisecond));
     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
 
-    CastLoggingConfig logging_config(GetDefaultCastReceiverLoggingConfig());
-    logging_config.enable_raw_data_collection = true;
-
     cast_environment_ = new CastEnvironment(
-        scoped_ptr<base::TickClock>(testing_clock_).Pass(), task_runner_,
-        task_runner_, task_runner_, task_runner_, task_runner_, task_runner_,
-        logging_config);
+        scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+        task_runner_,
+        task_runner_,
+        task_runner_);
 
     test_audio_encoder_callback_ = new TestAudioEncoderCallback();
   }
 
   void Configure(bool use_external_decoder) {
     audio_config_.use_external_decoder = use_external_decoder;
-    receiver_.reset(new PeerAudioReceiver(cast_environment_, audio_config_,
-                                          &mock_transport_));
+    receiver_.reset(new AudioReceiver(cast_environment_, audio_config_,
+                                      &mock_transport_));
   }
 
   virtual ~AudioReceiverTest() {}
@@ -120,7 +108,7 @@
   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
   transport::MockPacedPacketSender mock_transport_;
   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
-  scoped_ptr<PeerAudioReceiver> receiver_;
+  scoped_ptr<AudioReceiver> receiver_;
   scoped_refptr<CastEnvironment> cast_environment_;
   scoped_refptr<TestAudioEncoderCallback> test_audio_encoder_callback_;
 };
@@ -132,8 +120,8 @@
   Configure(true);
   EXPECT_CALL(mock_transport_, SendRtcpPacket(testing::_)).Times(1);
 
-  receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
-                                     rtp_header_);
+  receiver_->OnReceivedPayloadData(
+      payload_.data(), payload_.size(), rtp_header_);
   transport::EncodedAudioFrame audio_frame;
   base::TimeTicks playout_time;
   test_audio_encoder_callback_->SetExpectedResult(0,
@@ -170,8 +158,8 @@
 
   receiver_->GetEncodedAudioFrame(frame_encoded_callback);
 
-  receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
-                                     rtp_header_);
+  receiver_->OnReceivedPayloadData(
+      payload_.data(), payload_.size(), rtp_header_);
 
   transport::EncodedAudioFrame audio_frame;
   base::TimeTicks playout_time;
@@ -203,8 +191,8 @@
   test_audio_encoder_callback_->SetExpectedResult(
       2, testing_clock_->NowTicks() + base::TimeDelta::FromMilliseconds(100));
 
-  receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
-                                     rtp_header_);
+  receiver_->OnReceivedPayloadData(
+      payload_.data(), payload_.size(), rtp_header_);
   receiver_->GetEncodedAudioFrame(frame_encoded_callback);
   task_runner_->RunTasks();
 
@@ -227,8 +215,8 @@
   rtp_header_.is_reference = false;
   rtp_header_.reference_frame_id = 0;
   rtp_header_.webrtc.header.timestamp = 1280;
-  receiver_->IncomingParsedRtpPacket(payload_.data(), payload_.size(),
-                                     rtp_header_);
+  receiver_->OnReceivedPayloadData(
+      payload_.data(), payload_.size(), rtp_header_);
 
   receiver_->GetEncodedAudioFrame(frame_encoded_callback);
   task_runner_->RunTasks();
diff --git a/media/cast/audio_sender/audio_encoder.cc b/media/cast/audio_sender/audio_encoder.cc
index ece368f..ab39a6a 100644
--- a/media/cast/audio_sender/audio_encoder.cc
+++ b/media/cast/audio_sender/audio_encoder.cc
@@ -8,16 +8,30 @@
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
+#include "base/location.h"
 #include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
 #include "base/sys_byteorder.h"
 #include "base/time/time.h"
 #include "media/base/audio_bus.h"
 #include "media/cast/cast_defines.h"
 #include "media/cast/cast_environment.h"
+#include "media/cast/logging/logging_defines.h"
 #include "third_party/opus/src/include/opus.h"
 
+namespace {
+
+void LogAudioFrameEvent(
+    const scoped_refptr<media::cast::CastEnvironment>& cast_environment,
+    base::TimeTicks event_time,
+    media::cast::CastLoggingEvent event_type,
+    media::cast::RtpTimestamp rtp_timestamp,
+    uint32 frame_id) {
+  cast_environment->Logging()->InsertFrameEvent(
+      event_time, event_type, rtp_timestamp, frame_id);
+}
+
+}  // namespace
+
 namespace media {
 namespace cast {
 
@@ -28,8 +42,7 @@
 // Subclasses complete the implementation by handling the actual encoding
 // details.
 class AudioEncoder::ImplBase
-    : public base::RefCountedThreadSafe<AudioEncoder::ImplBase>,
-      public base::SupportsWeakPtr<ImplBase> {
+    : public base::RefCountedThreadSafe<AudioEncoder::ImplBase> {
  public:
   ImplBase(const scoped_refptr<CastEnvironment>& cast_environment,
            transport::AudioCodec codec,
@@ -41,39 +54,26 @@
         num_channels_(num_channels),
         samples_per_10ms_(sampling_rate / 100),
         callback_(callback),
+        cast_initialization_status_(STATUS_AUDIO_UNINITIALIZED),
         buffer_fill_end_(0),
         frame_id_(0),
-        rtp_timestamp_(0),
-        weak_factory_(this) {
-    DCHECK_GT(num_channels_, 0);
-    DCHECK_GT(samples_per_10ms_, 0);
-    DCHECK_EQ(sampling_rate % 100, 0);
-    DCHECK_LE(samples_per_10ms_ * num_channels_,
-              transport::EncodedAudioFrame::kMaxNumberOfSamples);
-
+        rtp_timestamp_(0) {
     if (num_channels_ <= 0 || samples_per_10ms_ <= 0 ||
         sampling_rate % 100 != 0 ||
         samples_per_10ms_ * num_channels_ >
             transport::EncodedAudioFrame::kMaxNumberOfSamples) {
-      cast_initialization_cb_ = STATUS_INVALID_AUDIO_CONFIGURATION;
-    } else {
-      cast_initialization_cb_ = STATUS_AUDIO_INITIALIZED;
+      cast_initialization_status_ = STATUS_INVALID_AUDIO_CONFIGURATION;
     }
   }
 
   CastInitializationStatus InitializationResult() const {
-    return cast_initialization_cb_;
-  }
-
-  void LogAudioFrameEvent(uint32 rtp_timestamp,
-                          uint32 frame_id,
-                          CastLoggingEvent type) {
-    cast_environment_->Logging()->InsertFrameEvent(
-        cast_environment_->Clock()->NowTicks(), type, rtp_timestamp, frame_id);
+    return cast_initialization_status_;
   }
 
   void EncodeAudio(scoped_ptr<AudioBus> audio_bus,
                    const base::TimeTicks& recorded_time) {
+    DCHECK_EQ(cast_initialization_status_, STATUS_AUDIO_INITIALIZED);
+
     int src_pos = 0;
     int packet_count = 0;
     while (src_pos < audio_bus->frames()) {
@@ -94,23 +94,27 @@
         audio_frame->rtp_timestamp = rtp_timestamp_;
 
         // Update logging.
-        cast_environment_->PostTask(CastEnvironment::MAIN,
-                                    FROM_HERE,
-                                    base::Bind(&ImplBase::LogAudioFrameEvent,
-                                               weak_factory_.GetWeakPtr(),
-                                               audio_frame->rtp_timestamp,
-                                               audio_frame->frame_id,
-                                               kAudioFrameReceived));
+        cast_environment_->PostTask(
+            CastEnvironment::MAIN,
+            FROM_HERE,
+            base::Bind(&LogAudioFrameEvent,
+                       cast_environment_,
+                       cast_environment_->Clock()->NowTicks(),
+                       kAudioFrameReceived,
+                       audio_frame->rtp_timestamp,
+                       audio_frame->frame_id));
 
         if (EncodeFromFilledBuffer(&audio_frame->data)) {
           // Update logging.
-          cast_environment_->PostTask(CastEnvironment::MAIN,
-                                      FROM_HERE,
-                                      base::Bind(&ImplBase::LogAudioFrameEvent,
-                                                 weak_factory_.GetWeakPtr(),
-                                                 audio_frame->rtp_timestamp,
-                                                 audio_frame->frame_id,
-                                                 kAudioFrameEncoded));
+          cast_environment_->PostTask(
+              CastEnvironment::MAIN,
+              FROM_HERE,
+              base::Bind(&LogAudioFrameEvent,
+                         cast_environment_,
+                         cast_environment_->Clock()->NowTicks(),
+                         kAudioFrameEncoded,
+                         audio_frame->rtp_timestamp,
+                         audio_frame->frame_id));
           // Compute an offset to determine the recorded time for the first
           // audio sample in the buffer.
           const base::TimeDelta buffer_time_offset =
@@ -152,7 +156,9 @@
   const int num_channels_;
   const int samples_per_10ms_;
   const FrameEncodedCallback callback_;
-  CastInitializationStatus cast_initialization_cb_;
+
+  // Subclass' ctor is expected to set this to STATUS_AUDIO_INITIALIZED.
+  CastInitializationStatus cast_initialization_status_;
 
  private:
   // In the case where a call to EncodeAudio() cannot completely fill the
@@ -167,9 +173,6 @@
   // so far.
   uint32 rtp_timestamp_;
 
-  // NOTE: Weak pointers must be invalidated before all other member variables.
-  base::WeakPtrFactory<ImplBase> weak_factory_;
-
   DISALLOW_COPY_AND_ASSIGN(ImplBase);
 };
 
@@ -188,14 +191,18 @@
         encoder_memory_(new uint8[opus_encoder_get_size(num_channels)]),
         opus_encoder_(reinterpret_cast<OpusEncoder*>(encoder_memory_.get())),
         buffer_(new float[num_channels * samples_per_10ms_]) {
-    if (ImplBase::cast_initialization_cb_ != STATUS_AUDIO_INITIALIZED) {
+    if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED)
+      return;
+    if (opus_encoder_init(opus_encoder_,
+                          sampling_rate,
+                          num_channels,
+                          OPUS_APPLICATION_AUDIO) != OPUS_OK) {
+      ImplBase::cast_initialization_status_ =
+          STATUS_INVALID_AUDIO_CONFIGURATION;
       return;
     }
+    ImplBase::cast_initialization_status_ = STATUS_AUDIO_INITIALIZED;
 
-    CHECK_EQ(
-        opus_encoder_init(
-            opus_encoder_, sampling_rate, num_channels, OPUS_APPLICATION_AUDIO),
-        OPUS_OK);
     if (bitrate <= 0) {
       // Note: As of 2013-10-31, the encoder in "auto bitrate" mode would use a
       // variable bitrate up to 102kbps for 2-channel, 48 kHz audio and a 10 ms
@@ -271,7 +278,11 @@
                  num_channels,
                  sampling_rate,
                  callback),
-        buffer_(new int16[num_channels * samples_per_10ms_]) {}
+        buffer_(new int16[num_channels * samples_per_10ms_]) {
+    if (ImplBase::cast_initialization_status_ != STATUS_AUDIO_UNINITIALIZED)
+      return;
+    cast_initialization_status_ = STATUS_AUDIO_INITIALIZED;
+  }
 
  private:
   virtual ~Pcm16Impl() {}
@@ -350,7 +361,7 @@
     NOTREACHED();
     return;
   }
-  cast_environment_->PostTask(CastEnvironment::AUDIO_ENCODER,
+  cast_environment_->PostTask(CastEnvironment::AUDIO,
                               FROM_HERE,
                               base::Bind(&AudioEncoder::ImplBase::EncodeAudio,
                                          impl_,
diff --git a/media/cast/audio_sender/audio_encoder_unittest.cc b/media/cast/audio_sender/audio_encoder_unittest.cc
index 37f5b49..52b8e56 100644
--- a/media/cast/audio_sender/audio_encoder_unittest.cc
+++ b/media/cast/audio_sender/audio_encoder_unittest.cc
@@ -95,11 +95,7 @@
         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
                             task_runner_,
                             task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            GetDefaultCastSenderLoggingConfig());
+                            task_runner_);
   }
 
   virtual ~AudioEncoderTest() {}
diff --git a/media/cast/audio_sender/audio_sender.cc b/media/cast/audio_sender/audio_sender.cc
index aa1fa6c..590010d 100644
--- a/media/cast/audio_sender/audio_sender.cc
+++ b/media/cast/audio_sender/audio_sender.cc
@@ -91,31 +91,13 @@
     const base::TimeTicks& recorded_time) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   InitializeTimers();
-  cast_environment_->PostTask(
-      CastEnvironment::TRANSPORT,
-      FROM_HERE,
-      base::Bind(&AudioSender::SendEncodedAudioFrameToTransport,
-                 base::Unretained(this),
-                 base::Passed(&audio_frame),
-                 recorded_time));
-}
-
-void AudioSender::SendEncodedAudioFrameToTransport(
-    scoped_ptr<transport::EncodedAudioFrame> audio_frame,
-    const base::TimeTicks& recorded_time) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
   transport_sender_->InsertCodedAudioFrame(audio_frame.get(), recorded_time);
 }
 
 void AudioSender::ResendPackets(
     const MissingFramesAndPacketsMap& missing_frames_and_packets) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
-  cast_environment_->PostTask(
-      CastEnvironment::TRANSPORT,
-      FROM_HERE,
-      base::Bind(&AudioSender::ResendPacketsOnTransportThread,
-                 base::Unretained(this),
-                 missing_frames_and_packets));
+  transport_sender_->ResendPackets(true, missing_frames_and_packets);
 }
 
 void AudioSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) {
@@ -155,11 +137,5 @@
   ScheduleNextRtcpReport();
 }
 
-void AudioSender::ResendPacketsOnTransportThread(
-    const transport::MissingFramesAndPacketsMap& missing_packets) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
-  transport_sender_->ResendPackets(true, missing_packets);
-}
-
 }  // namespace cast
 }  // namespace media
diff --git a/media/cast/audio_sender/audio_sender.h b/media/cast/audio_sender/audio_sender.h
index 2acba8a..1a2eedd 100644
--- a/media/cast/audio_sender/audio_sender.h
+++ b/media/cast/audio_sender/audio_sender.h
@@ -52,16 +52,9 @@
  private:
   friend class LocalRtcpAudioSenderFeedback;
 
-  void SendEncodedAudioFrameToTransport(
-      scoped_ptr<transport::EncodedAudioFrame> audio_frame,
-      const base::TimeTicks& recorded_time);
-
   void ResendPackets(
       const MissingFramesAndPacketsMap& missing_frames_and_packets);
 
-  void ResendPacketsOnTransportThread(
-      const transport::MissingFramesAndPacketsMap& missing_packets);
-
   void StoreStatistics(const transport::RtcpSenderInfo& sender_info,
                        base::TimeTicks time_sent,
                        uint32 rtp_timestamp);
diff --git a/media/cast/audio_sender/audio_sender_unittest.cc b/media/cast/audio_sender/audio_sender_unittest.cc
index 49607ba..ad0f3db 100644
--- a/media/cast/audio_sender/audio_sender_unittest.cc
+++ b/media/cast/audio_sender/audio_sender_unittest.cc
@@ -54,16 +54,11 @@
     testing_clock_->Advance(
         base::TimeDelta::FromMilliseconds(kStartMillisecond));
     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
-    CastLoggingConfig logging_config = GetDefaultCastSenderLoggingConfig();
     cast_environment_ =
         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
                             task_runner_,
                             task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            logging_config);
+                            task_runner_);
     audio_config_.codec = transport::kOpus;
     audio_config_.use_external_encoder = false;
     audio_config_.frequency = kDefaultAudioSamplingRate;
@@ -80,7 +75,6 @@
         NULL,
         testing_clock_,
         dummy_endpoint,
-        logging_config,
         base::Bind(&UpdateCastTransportStatus),
         transport::BulkRawEventsCallback(),
         base::TimeDelta(),
diff --git a/media/cast/cast.gyp b/media/cast/cast.gyp
index ef67982..b8ef6cd 100644
--- a/media/cast/cast.gyp
+++ b/media/cast/cast.gyp
@@ -49,6 +49,7 @@
             'logging/logging_impl_unittest.cc',
             'logging/logging_raw_unittest.cc',
             'logging/simple_event_subscriber_unittest.cc',
+            'logging/stats_event_subscriber_unittest.cc',
             'rtcp/mock_rtcp_receiver_feedback.cc',
             'rtcp/mock_rtcp_receiver_feedback.h',
             'rtcp/mock_rtcp_sender_feedback.cc',
@@ -66,8 +67,6 @@
             'rtp_receiver/rtp_parser/rtp_parser_unittest.cc',
             'test/encode_decode_test.cc',
             'test/end2end_unittest.cc',
-            'test/fake_gpu_video_accelerator_factories.cc',
-            'test/fake_gpu_video_accelerator_factories.h',
             'test/fake_single_thread_task_runner.cc',
             'test/fake_single_thread_task_runner.h',
             'test/fake_video_encode_accelerator.cc',
diff --git a/media/cast/cast_config.h b/media/cast/cast_config.h
index 21caea0..88bbdbc 100644
--- a/media/cast/cast_config.h
+++ b/media/cast/cast_config.h
@@ -12,10 +12,14 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory.h"
+#include "base/single_thread_task_runner.h"
 #include "media/cast/cast_defines.h"
 #include "media/cast/transport/cast_transport_config.h"
 
 namespace media {
+class VideoEncodeAccelerator;
+
 namespace cast {
 
 enum RtcpMode {
@@ -137,6 +141,18 @@
 typedef base::Callback<void(CastInitializationStatus)>
     CastInitializationCallback;
 
+typedef base::Callback<void(scoped_refptr<base::SingleThreadTaskRunner>,
+                            scoped_ptr<media::VideoEncodeAccelerator>)>
+    ReceiveVideoEncodeAcceleratorCallback;
+typedef base::Callback<void(const ReceiveVideoEncodeAcceleratorCallback&)>
+    CreateVideoEncodeAcceleratorCallback;
+
+typedef base::Callback<void(scoped_ptr<base::SharedMemory>)>
+    ReceiveVideoEncodeMemoryCallback;
+typedef base::Callback<void(size_t size,
+                            const ReceiveVideoEncodeMemoryCallback&)>
+    CreateVideoEncodeMemoryCallback;
+
 }  // namespace cast
 }  // namespace media
 
diff --git a/media/cast/cast_environment.cc b/media/cast/cast_environment.cc
index 9077b52..93eb8c7 100644
--- a/media/cast/cast_environment.cc
+++ b/media/cast/cast_environment.cc
@@ -24,20 +24,13 @@
 CastEnvironment::CastEnvironment(
     scoped_ptr<base::TickClock> clock,
     scoped_refptr<SingleThreadTaskRunner> main_thread_proxy,
-    scoped_refptr<SingleThreadTaskRunner> audio_encode_thread_proxy,
-    scoped_refptr<SingleThreadTaskRunner> audio_decode_thread_proxy,
-    scoped_refptr<SingleThreadTaskRunner> video_encode_thread_proxy,
-    scoped_refptr<SingleThreadTaskRunner> video_decode_thread_proxy,
-    scoped_refptr<SingleThreadTaskRunner> transport_thread_proxy,
-    const CastLoggingConfig& logging_config)
+    scoped_refptr<SingleThreadTaskRunner> audio_thread_proxy,
+    scoped_refptr<SingleThreadTaskRunner> video_thread_proxy)
     : main_thread_proxy_(main_thread_proxy),
-      audio_encode_thread_proxy_(audio_encode_thread_proxy),
-      audio_decode_thread_proxy_(audio_decode_thread_proxy),
-      video_encode_thread_proxy_(video_encode_thread_proxy),
-      video_decode_thread_proxy_(video_decode_thread_proxy),
-      transport_thread_proxy_(transport_thread_proxy),
+      audio_thread_proxy_(audio_thread_proxy),
+      video_thread_proxy_(video_thread_proxy),
       clock_(clock.Pass()),
-      logging_(new LoggingImpl(logging_config)) {}
+      logging_(new LoggingImpl) {}
 
 CastEnvironment::~CastEnvironment() {
   // Logging must be deleted on the main thread.
@@ -67,16 +60,10 @@
   switch (identifier) {
     case CastEnvironment::MAIN:
       return main_thread_proxy_;
-    case CastEnvironment::AUDIO_ENCODER:
-      return audio_encode_thread_proxy_;
-    case CastEnvironment::AUDIO_DECODER:
-      return audio_decode_thread_proxy_;
-    case CastEnvironment::VIDEO_ENCODER:
-      return video_encode_thread_proxy_;
-    case CastEnvironment::VIDEO_DECODER:
-      return video_decode_thread_proxy_;
-    case CastEnvironment::TRANSPORT:
-      return transport_thread_proxy_;
+    case CastEnvironment::AUDIO:
+      return audio_thread_proxy_;
+    case CastEnvironment::VIDEO:
+      return video_thread_proxy_;
     default:
       NOTREACHED() << "Invalid Thread identifier";
       return NULL;
@@ -88,21 +75,12 @@
     case CastEnvironment::MAIN:
       return main_thread_proxy_ &&
              main_thread_proxy_->RunsTasksOnCurrentThread();
-    case CastEnvironment::AUDIO_ENCODER:
-      return audio_encode_thread_proxy_ &&
-             audio_encode_thread_proxy_->RunsTasksOnCurrentThread();
-    case CastEnvironment::AUDIO_DECODER:
-      return audio_decode_thread_proxy_ &&
-             audio_decode_thread_proxy_->RunsTasksOnCurrentThread();
-    case CastEnvironment::VIDEO_ENCODER:
-      return video_encode_thread_proxy_ &&
-             video_encode_thread_proxy_->RunsTasksOnCurrentThread();
-    case CastEnvironment::VIDEO_DECODER:
-      return video_decode_thread_proxy_ &&
-             video_decode_thread_proxy_->RunsTasksOnCurrentThread();
-    case CastEnvironment::TRANSPORT:
-      return transport_thread_proxy_ &&
-             transport_thread_proxy_->RunsTasksOnCurrentThread();
+    case CastEnvironment::AUDIO:
+      return audio_thread_proxy_ &&
+             audio_thread_proxy_->RunsTasksOnCurrentThread();
+    case CastEnvironment::VIDEO:
+      return video_thread_proxy_ &&
+             video_thread_proxy_->RunsTasksOnCurrentThread();
     default:
       NOTREACHED() << "Invalid thread identifier";
       return false;
diff --git a/media/cast/cast_environment.h b/media/cast/cast_environment.h
index 95d4ccb..e9d1eb4 100644
--- a/media/cast/cast_environment.h
+++ b/media/cast/cast_environment.h
@@ -24,29 +24,18 @@
     // The main thread is where the cast system is configured and where timers
     // and network IO is performed.
     MAIN,
-    // The audio encoder thread is where all send side audio processing is done,
-    // primarily encoding but also re-sampling.
-    AUDIO_ENCODER,
-    // The audio decoder thread is where all receive side audio processing is
-    // done, primarily decoding but also error concealment and re-sampling.
-    AUDIO_DECODER,
-    // The video encoder thread is where the video encode processing is done.
-    VIDEO_ENCODER,
-    // The video decoder thread is where the video decode processing is done.
-    VIDEO_DECODER,
-    // The transport thread is where the transport processing is done.
-    TRANSPORT,
+    // The audio thread is where all send side audio processing is done,
+    // primarily encoding / decoding but also re-sampling.
+    AUDIO,
+    // The video encoder thread is where the video processing is done.
+    VIDEO,
   };
 
   CastEnvironment(
       scoped_ptr<base::TickClock> clock,
       scoped_refptr<base::SingleThreadTaskRunner> main_thread_proxy,
-      scoped_refptr<base::SingleThreadTaskRunner> audio_encode_thread_proxy,
-      scoped_refptr<base::SingleThreadTaskRunner> audio_decode_thread_proxy,
-      scoped_refptr<base::SingleThreadTaskRunner> video_encode_thread_proxy,
-      scoped_refptr<base::SingleThreadTaskRunner> video_decode_thread_proxy,
-      scoped_refptr<base::SingleThreadTaskRunner> transport_thread_proxy,
-      const CastLoggingConfig& logging_config);
+      scoped_refptr<base::SingleThreadTaskRunner> audio_thread_proxy,
+      scoped_refptr<base::SingleThreadTaskRunner> video_thread_proxy);
 
   // These are the same methods in message_loop.h, but are guaranteed to either
   // get posted to the MessageLoop if it's still alive, or be deleted otherwise.
@@ -69,17 +58,18 @@
 
   // Logging is not thread safe. Its methods should always be called from the
   // main thread.
+  // TODO(hubbe): Logging should be a thread-safe interface.
   LoggingImpl* Logging() const { return logging_.get(); }
 
   scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(
       ThreadId identifier) const;
 
-  bool HasAudioEncoderThread() {
-    return audio_encode_thread_proxy_ ? true : false;
+  bool HasAudioThread() {
+    return audio_thread_proxy_ ? true : false;
   }
 
-  bool HasVideoEncoderThread() {
-    return video_encode_thread_proxy_ ? true : false;
+  bool HasVideoThread() {
+    return video_thread_proxy_ ? true : false;
   }
 
  protected:
@@ -87,11 +77,8 @@
 
   // Subclasses may override these.
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_proxy_;
-  scoped_refptr<base::SingleThreadTaskRunner> audio_encode_thread_proxy_;
-  scoped_refptr<base::SingleThreadTaskRunner> audio_decode_thread_proxy_;
-  scoped_refptr<base::SingleThreadTaskRunner> video_encode_thread_proxy_;
-  scoped_refptr<base::SingleThreadTaskRunner> video_decode_thread_proxy_;
-  scoped_refptr<base::SingleThreadTaskRunner> transport_thread_proxy_;
+  scoped_refptr<base::SingleThreadTaskRunner> audio_thread_proxy_;
+  scoped_refptr<base::SingleThreadTaskRunner> video_thread_proxy_;
 
  private:
   friend class base::RefCountedThreadSafe<CastEnvironment>;
diff --git a/media/cast/cast_receiver_impl.cc b/media/cast/cast_receiver_impl.cc
index 6aff388..cee29ec 100644
--- a/media/cast/cast_receiver_impl.cc
+++ b/media/cast/cast_receiver_impl.cc
@@ -99,7 +99,7 @@
     : pacer_(cast_environment->Clock(),
              cast_environment->Logging(),
              packet_sender,
-             cast_environment->GetTaskRunner(CastEnvironment::TRANSPORT)),
+             cast_environment->GetTaskRunner(CastEnvironment::MAIN)),
       audio_receiver_(cast_environment, audio_config, &pacer_),
       video_receiver_(cast_environment,
                       video_config,
diff --git a/media/cast/cast_sender.h b/media/cast/cast_sender.h
index 64d07d4..eb3327f 100644
--- a/media/cast/cast_sender.h
+++ b/media/cast/cast_sender.h
@@ -20,10 +20,8 @@
 #include "media/cast/cast_config.h"
 #include "media/cast/cast_environment.h"
 #include "media/cast/transport/cast_transport_sender.h"
-#include "media/filters/gpu_video_accelerator_factories.h"
 
 namespace media {
-class GpuVideoAcceleratorFactories;
 class VideoFrame;
 
 namespace cast {
@@ -59,8 +57,8 @@
   friend class base::RefCountedThreadSafe<AudioFrameInput>;
 };
 
-// The provided CastTransportSender and the CastSender should be called from the
-// main thread.
+// All methods of CastSender must be called on the main thread.
+// Provided CastTransportSender will also be called on the main thread.
 class CastSender {
  public:
   static scoped_ptr<CastSender> Create(
@@ -90,7 +88,8 @@
   virtual void InitializeVideo(
       const VideoSenderConfig& video_config,
       const CastInitializationCallback& cast_initialization_cb,
-      const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) = 0;
+      const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) = 0;
 };
 
 }  // namespace cast
diff --git a/media/cast/cast_sender_impl.cc b/media/cast/cast_sender_impl.cc
index 3c90461..0b5a2ac 100644
--- a/media/cast/cast_sender_impl.cc
+++ b/media/cast/cast_sender_impl.cc
@@ -95,7 +95,7 @@
     const CastInitializationCallback& cast_initialization_cb) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   CHECK(audio_config.use_external_encoder ||
-        cast_environment_->HasAudioEncoderThread());
+        cast_environment_->HasAudioThread());
 
   audio_sender_.reset(
       new AudioSender(cast_environment_, audio_config, transport_sender_));
@@ -113,14 +113,16 @@
 void CastSenderImpl::InitializeVideo(
     const VideoSenderConfig& video_config,
     const CastInitializationCallback& cast_initialization_cb,
-    const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories) {
+    const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+    const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   CHECK(video_config.use_external_encoder ||
-        cast_environment_->HasVideoEncoderThread());
+        cast_environment_->HasVideoThread());
 
   video_sender_.reset(new VideoSender(cast_environment_,
                                       video_config,
-                                      gpu_factories,
+                                      create_vea_cb,
+                                      create_video_encode_mem_cb,
                                       cast_initialization_cb,
                                       transport_sender_));
 
diff --git a/media/cast/cast_sender_impl.h b/media/cast/cast_sender_impl.h
index b90bec4..d09a869 100644
--- a/media/cast/cast_sender_impl.h
+++ b/media/cast/cast_sender_impl.h
@@ -33,7 +33,8 @@
   virtual void InitializeVideo(
       const VideoSenderConfig& video_config,
       const CastInitializationCallback& cast_initialization_cb,
-      const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories)
+      const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb)
       OVERRIDE;
 
   virtual ~CastSenderImpl();
diff --git a/media/cast/logging/encoding_event_subscriber.cc b/media/cast/logging/encoding_event_subscriber.cc
index 24e3477..50aaf4f 100644
--- a/media/cast/logging/encoding_event_subscriber.cc
+++ b/media/cast/logging/encoding_event_subscriber.cc
@@ -12,7 +12,6 @@
 
 using google::protobuf::RepeatedPtrField;
 using media::cast::proto::AggregatedFrameEvent;
-using media::cast::proto::AggregatedGenericEvent;
 using media::cast::proto::AggregatedPacketEvent;
 using media::cast::proto::BasePacketEvent;
 using media::cast::proto::LogMetadata;
@@ -53,8 +52,8 @@
     }
 
     event_proto->add_event_type(ToProtoEventType(frame_event.type));
-    event_proto->add_event_timestamp_micros(
-        frame_event.timestamp.ToInternalValue());
+    event_proto->add_event_timestamp_ms(
+        (frame_event.timestamp - base::TimeTicks()).InMilliseconds());
 
     if (frame_event.type == kAudioFrameEncoded ||
         frame_event.type == kVideoFrameEncoded) {
@@ -113,8 +112,8 @@
 
     base_packet_event_proto->add_event_type(
         ToProtoEventType(packet_event.type));
-    base_packet_event_proto->add_event_timestamp_micros(
-        packet_event.timestamp.ToInternalValue());
+    base_packet_event_proto->add_event_timestamp_ms(
+        (packet_event.timestamp - base::TimeTicks()).InMilliseconds());
 
     TruncatePacketEventMapIfNeeded();
   }
diff --git a/media/cast/logging/encoding_event_subscriber_unittest.cc b/media/cast/logging/encoding_event_subscriber_unittest.cc
index f0f552d..119ec07 100644
--- a/media/cast/logging/encoding_event_subscriber_unittest.cc
+++ b/media/cast/logging/encoding_event_subscriber_unittest.cc
@@ -17,6 +17,14 @@
 using media::cast::proto::BasePacketEvent;
 using media::cast::proto::LogMetadata;
 
+namespace {
+
+int64 InMilliseconds(base::TimeTicks event_time) {
+  return (event_time - base::TimeTicks()).InMilliseconds();
+}
+
+}
+
 namespace media {
 namespace cast {
 
@@ -29,11 +37,7 @@
             scoped_ptr<base::TickClock>(testing_clock_).Pass(),
             task_runner_,
             task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            GetLoggingConfigWithRawEventsAndStatsEnabled())),
+            task_runner_)),
         first_rtp_timestamp_(0) {}
 
   void Init(EventMediaType event_media_type) {
@@ -167,8 +171,8 @@
 
   ASSERT_EQ(1, event->event_type_size());
   EXPECT_EQ(media::cast::proto::VIDEO_FRAME_DECODED, event->event_type(0));
-  ASSERT_EQ(1, event->event_timestamp_micros_size());
-  EXPECT_EQ(now.ToInternalValue(), event->event_timestamp_micros(0));
+  ASSERT_EQ(1, event->event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now), event->event_timestamp_ms(0));
 
   EXPECT_EQ(0, event->encoded_frame_size());
   EXPECT_EQ(0, event->delay_millis());
@@ -200,8 +204,8 @@
 
   ASSERT_EQ(1, event->event_type_size());
   EXPECT_EQ(media::cast::proto::AUDIO_PLAYOUT_DELAY, event->event_type(0));
-  ASSERT_EQ(1, event->event_timestamp_micros_size());
-  EXPECT_EQ(now.ToInternalValue(), event->event_timestamp_micros(0));
+  ASSERT_EQ(1, event->event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now), event->event_timestamp_ms(0));
 
   EXPECT_EQ(0, event->encoded_frame_size());
   EXPECT_EQ(100, event->delay_millis());
@@ -230,8 +234,8 @@
 
   ASSERT_EQ(1, event->event_type_size());
   EXPECT_EQ(media::cast::proto::VIDEO_FRAME_ENCODED, event->event_type(0));
-  ASSERT_EQ(1, event->event_timestamp_micros_size());
-  EXPECT_EQ(now.ToInternalValue(), event->event_timestamp_micros(0));
+  ASSERT_EQ(1, event->event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now), event->event_timestamp_ms(0));
 
   EXPECT_EQ(size, event->encoded_frame_size());
   EXPECT_EQ(0, event->delay_millis());
@@ -273,9 +277,9 @@
   EXPECT_EQ(media::cast::proto::AUDIO_PLAYOUT_DELAY, event->event_type(0));
   EXPECT_EQ(media::cast::proto::AUDIO_FRAME_DECODED, event->event_type(1));
 
-  ASSERT_EQ(2, event->event_timestamp_micros_size());
-  EXPECT_EQ(now1.ToInternalValue(), event->event_timestamp_micros(0));
-  EXPECT_EQ(now3.ToInternalValue(), event->event_timestamp_micros(1));
+  ASSERT_EQ(2, event->event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now1), event->event_timestamp_ms(0));
+  EXPECT_EQ(InMilliseconds(now3), event->event_timestamp_ms(1));
 
   relative_rtp_timestamp = rtp_timestamp2 - first_rtp_timestamp_;
   it = frame_events_.find(relative_rtp_timestamp);
@@ -288,8 +292,8 @@
   ASSERT_EQ(1, event->event_type_size());
   EXPECT_EQ(media::cast::proto::AUDIO_FRAME_ENCODED, event->event_type(0));
 
-  ASSERT_EQ(1, event->event_timestamp_micros_size());
-  EXPECT_EQ(now2.ToInternalValue(), event->event_timestamp_micros(0));
+  ASSERT_EQ(1, event->event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now2), event->event_timestamp_ms(0));
 }
 
 TEST_F(EncodingEventSubscriberTest, PacketEvent) {
@@ -320,8 +324,8 @@
   ASSERT_EQ(1, base_event.event_type_size());
   EXPECT_EQ(media::cast::proto::AUDIO_PACKET_RECEIVED,
             base_event.event_type(0));
-  ASSERT_EQ(1, base_event.event_timestamp_micros_size());
-  EXPECT_EQ(now.ToInternalValue(), base_event.event_timestamp_micros(0));
+  ASSERT_EQ(1, base_event.event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now), base_event.event_timestamp_ms(0));
 
   GetEventsAndReset();
   EXPECT_TRUE(packet_events_.empty());
@@ -371,9 +375,9 @@
             base_event.event_type(0));
   EXPECT_EQ(media::cast::proto::VIDEO_PACKET_SENT_TO_NETWORK,
             base_event.event_type(1));
-  ASSERT_EQ(2, base_event.event_timestamp_micros_size());
-  EXPECT_EQ(now1.ToInternalValue(), base_event.event_timestamp_micros(0));
-  EXPECT_EQ(now2.ToInternalValue(), base_event.event_timestamp_micros(1));
+  ASSERT_EQ(2, base_event.event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now1), base_event.event_timestamp_ms(0));
+  EXPECT_EQ(InMilliseconds(now2), base_event.event_timestamp_ms(1));
 }
 
 TEST_F(EncodingEventSubscriberTest, MultiplePacketEventsForFrame) {
@@ -419,16 +423,16 @@
   ASSERT_EQ(1, base_event.event_type_size());
   EXPECT_EQ(media::cast::proto::VIDEO_PACKET_SENT_TO_PACER,
             base_event.event_type(0));
-  ASSERT_EQ(1, base_event.event_timestamp_micros_size());
-  EXPECT_EQ(now1.ToInternalValue(), base_event.event_timestamp_micros(0));
+  ASSERT_EQ(1, base_event.event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now1), base_event.event_timestamp_ms(0));
 
   const BasePacketEvent& base_event_2 = event->base_packet_event(1);
   EXPECT_EQ(packet_id_2, base_event_2.packet_id());
   ASSERT_EQ(1, base_event_2.event_type_size());
   EXPECT_EQ(media::cast::proto::VIDEO_PACKET_RETRANSMITTED,
             base_event_2.event_type(0));
-  ASSERT_EQ(1, base_event_2.event_timestamp_micros_size());
-  EXPECT_EQ(now2.ToInternalValue(), base_event_2.event_timestamp_micros(0));
+  ASSERT_EQ(1, base_event_2.event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now2), base_event_2.event_timestamp_ms(0));
 }
 
 TEST_F(EncodingEventSubscriberTest, MultiplePacketEvents) {
@@ -475,8 +479,8 @@
   ASSERT_EQ(1, base_event.event_type_size());
   EXPECT_EQ(media::cast::proto::VIDEO_PACKET_SENT_TO_PACER,
             base_event.event_type(0));
-  ASSERT_EQ(1, base_event.event_timestamp_micros_size());
-  EXPECT_EQ(now1.ToInternalValue(), base_event.event_timestamp_micros(0));
+  ASSERT_EQ(1, base_event.event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now1), base_event.event_timestamp_ms(0));
 
   relative_rtp_timestamp = rtp_timestamp_2 - first_rtp_timestamp_;
   it = packet_events_.find(relative_rtp_timestamp);
@@ -492,8 +496,8 @@
   ASSERT_EQ(1, base_event_2.event_type_size());
   EXPECT_EQ(media::cast::proto::VIDEO_PACKET_RETRANSMITTED,
             base_event_2.event_type(0));
-  ASSERT_EQ(1, base_event_2.event_timestamp_micros_size());
-  EXPECT_EQ(now2.ToInternalValue(), base_event_2.event_timestamp_micros(0));
+  ASSERT_EQ(1, base_event_2.event_timestamp_ms_size());
+  EXPECT_EQ(InMilliseconds(now2), base_event_2.event_timestamp_ms(0));
 }
 
 TEST_F(EncodingEventSubscriberTest, FirstRtpTimestamp) {
diff --git a/media/cast/logging/logging.gyp b/media/cast/logging/logging.gyp
index ba2c2dc..30e8119 100644
--- a/media/cast/logging/logging.gyp
+++ b/media/cast/logging/logging.gyp
@@ -23,11 +23,13 @@
         'logging_impl.h',
         'logging_raw.cc',
         'logging_raw.h',
-        'logging_stats.cc',
-        'logging_stats.h',
         'raw_event_subscriber.h',
         'simple_event_subscriber.cc',
         'simple_event_subscriber.h',
+        'stats_event_subscriber.cc',
+        'stats_event_subscriber.h',
+        'stats_util.cc',
+        'stats_util.h',
       ], # source
     },
     {
diff --git a/media/cast/logging/logging_defines.cc b/media/cast/logging/logging_defines.cc
index adb1f04..5dbf9d2 100644
--- a/media/cast/logging/logging_defines.cc
+++ b/media/cast/logging/logging_defines.cc
@@ -13,27 +13,6 @@
 namespace media {
 namespace cast {
 
-CastLoggingConfig::CastLoggingConfig()
-    : enable_raw_data_collection(false),
-      enable_stats_data_collection(false) {}
-
-CastLoggingConfig::~CastLoggingConfig() {}
-
-CastLoggingConfig GetDefaultCastSenderLoggingConfig() {
-  return CastLoggingConfig();
-}
-
-CastLoggingConfig GetDefaultCastReceiverLoggingConfig() {
-  return CastLoggingConfig();
-}
-
-CastLoggingConfig GetLoggingConfigWithRawEventsAndStatsEnabled() {
-  CastLoggingConfig config;
-  config.enable_raw_data_collection = true;
-  config.enable_stats_data_collection = true;
-  return config;
-}
-
 const char* CastLoggingToString(CastLoggingEvent event) {
   switch (event) {
     // Can happen if the sender and receiver of RTCP log messages are not
diff --git a/media/cast/logging/logging_defines.h b/media/cast/logging/logging_defines.h
index b4e1814..02eeec7 100644
--- a/media/cast/logging/logging_defines.h
+++ b/media/cast/logging/logging_defines.h
@@ -18,22 +18,6 @@
 
 typedef uint32 RtpTimestamp;
 
-struct CastLoggingConfig {
-  // Constructs default config - all logging is disabled.
-  CastLoggingConfig();
-  ~CastLoggingConfig();
-
-  bool enable_raw_data_collection;
-  bool enable_stats_data_collection;
-};
-
-// Currently these are the same as the default config.
-CastLoggingConfig GetDefaultCastSenderLoggingConfig();
-CastLoggingConfig GetDefaultCastReceiverLoggingConfig();
-
-// Enable raw and stats data collection. Disable tracing.
-CastLoggingConfig GetLoggingConfigWithRawEventsAndStatsEnabled();
-
 enum CastLoggingEvent {
   // Generic events.
   kUnknown,
diff --git a/media/cast/logging/logging_impl.cc b/media/cast/logging/logging_impl.cc
index 0f07a5a..3ab4b4d 100644
--- a/media/cast/logging/logging_impl.cc
+++ b/media/cast/logging/logging_impl.cc
@@ -9,8 +9,8 @@
 namespace media {
 namespace cast {
 
-LoggingImpl::LoggingImpl(const CastLoggingConfig& config)
-    : config_(config), raw_(), stats_() {
+// TODO(imcheng): Collapse LoggingRaw onto LoggingImpl.
+LoggingImpl::LoggingImpl() {
   // LoggingImpl can be constructed on any thread, but its methods should all be
   // called on the same thread.
   thread_checker_.DetachFromThread();
@@ -22,12 +22,7 @@
                                    CastLoggingEvent event, uint32 rtp_timestamp,
                                    uint32 frame_id) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (config_.enable_raw_data_collection) {
-    raw_.InsertFrameEvent(time_of_event, event, rtp_timestamp, frame_id);
-  }
-  if (config_.enable_stats_data_collection) {
-    stats_.InsertFrameEvent(time_of_event, event, rtp_timestamp, frame_id);
-  }
+  raw_.InsertFrameEvent(time_of_event, event, rtp_timestamp, frame_id);
 }
 
 void LoggingImpl::InsertFrameEventWithSize(const base::TimeTicks& time_of_event,
@@ -35,28 +30,16 @@
                                            uint32 rtp_timestamp,
                                            uint32 frame_id, int frame_size) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (config_.enable_raw_data_collection) {
-    raw_.InsertFrameEventWithSize(time_of_event, event, rtp_timestamp, frame_id,
-                                  frame_size);
-  }
-  if (config_.enable_stats_data_collection) {
-    stats_.InsertFrameEventWithSize(time_of_event, event, rtp_timestamp,
-                                    frame_id, frame_size);
-  }
+  raw_.InsertFrameEventWithSize(time_of_event, event, rtp_timestamp, frame_id,
+                                frame_size);
 }
 
 void LoggingImpl::InsertFrameEventWithDelay(
     const base::TimeTicks& time_of_event, CastLoggingEvent event,
     uint32 rtp_timestamp, uint32 frame_id, base::TimeDelta delay) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (config_.enable_raw_data_collection) {
-    raw_.InsertFrameEventWithDelay(time_of_event, event, rtp_timestamp,
-                                   frame_id, delay);
-  }
-  if (config_.enable_stats_data_collection) {
-    stats_.InsertFrameEventWithDelay(time_of_event, event, rtp_timestamp,
-                                     frame_id, delay);
-  }
+  raw_.InsertFrameEventWithDelay(time_of_event, event, rtp_timestamp,
+                                 frame_id, delay);
 }
 
 void LoggingImpl::InsertSinglePacketEvent(const base::TimeTicks& time_of_event,
@@ -102,25 +85,14 @@
                                     uint16 packet_id, uint16 max_packet_id,
                                     size_t size) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (config_.enable_raw_data_collection) {
-    raw_.InsertPacketEvent(time_of_event, event, rtp_timestamp, frame_id,
-                           packet_id, max_packet_id, size);
-  }
-  if (config_.enable_stats_data_collection) {
-    stats_.InsertPacketEvent(time_of_event, event, rtp_timestamp, frame_id,
-                             packet_id, max_packet_id, size);
-  }
+  raw_.InsertPacketEvent(time_of_event, event, rtp_timestamp, frame_id,
+                         packet_id, max_packet_id, size);
 }
 
 void LoggingImpl::InsertGenericEvent(const base::TimeTicks& time_of_event,
                                      CastLoggingEvent event, int value) {
   DCHECK(thread_checker_.CalledOnValidThread());
-  if (config_.enable_raw_data_collection) {
-    raw_.InsertGenericEvent(time_of_event, event, value);
-  }
-  if (config_.enable_stats_data_collection) {
-    stats_.InsertGenericEvent(time_of_event, event, value);
-  }
+  raw_.InsertGenericEvent(time_of_event, event, value);
 }
 
 void LoggingImpl::AddRawEventSubscriber(RawEventSubscriber* subscriber) {
@@ -133,26 +105,5 @@
   raw_.RemoveSubscriber(subscriber);
 }
 
-FrameStatsMap LoggingImpl::GetFrameStatsData(EventMediaType media_type) const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return stats_.GetFrameStatsData(media_type);
-}
-
-PacketStatsMap LoggingImpl::GetPacketStatsData(
-    EventMediaType media_type) const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return stats_.GetPacketStatsData(media_type);
-}
-
-GenericStatsMap LoggingImpl::GetGenericStatsData() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return stats_.GetGenericStatsData();
-}
-
-void LoggingImpl::ResetStats() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  stats_.Reset();
-}
-
 }  // namespace cast
 }  // namespace media
diff --git a/media/cast/logging/logging_impl.h b/media/cast/logging/logging_impl.h
index 7b5c62f..5b35dff 100644
--- a/media/cast/logging/logging_impl.h
+++ b/media/cast/logging/logging_impl.h
@@ -14,15 +14,13 @@
 #include "media/cast/cast_config.h"
 #include "media/cast/logging/logging_defines.h"
 #include "media/cast/logging/logging_raw.h"
-#include "media/cast/logging/logging_stats.h"
 
 namespace media {
 namespace cast {
 
 class LoggingImpl {
  public:
-  explicit LoggingImpl(const CastLoggingConfig& config);
-
+  LoggingImpl();
   ~LoggingImpl();
 
   // Note: All methods below should be called from the same thread.
@@ -61,19 +59,9 @@
   // Delegates to |LoggingRaw::RemoveRawEventSubscriber()|.
   void RemoveRawEventSubscriber(RawEventSubscriber* subscriber);
 
-  // Get stats only.
-  FrameStatsMap GetFrameStatsData(EventMediaType media_type) const;
-  PacketStatsMap GetPacketStatsData(EventMediaType media_type) const;
-  GenericStatsMap GetGenericStatsData() const;
-
-  // Reset stats logging data.
-  void ResetStats();
-
  private:
   base::ThreadChecker thread_checker_;
-  const CastLoggingConfig config_;
   LoggingRaw raw_;
-  LoggingStats stats_;
 
   DISALLOW_COPY_AND_ASSIGN(LoggingImpl);
 };
diff --git a/media/cast/logging/logging_impl_unittest.cc b/media/cast/logging/logging_impl_unittest.cc
index 39bf91d..d9a67dd 100644
--- a/media/cast/logging/logging_impl_unittest.cc
+++ b/media/cast/logging/logging_impl_unittest.cc
@@ -26,22 +26,16 @@
 class LoggingImplTest : public ::testing::Test {
  protected:
   LoggingImplTest() {
-    // Enable all logging types.
-    config_.enable_raw_data_collection = true;
-    config_.enable_stats_data_collection = true;
-
     testing_clock_.Advance(
         base::TimeDelta::FromMilliseconds(kStartMillisecond));
-    logging_.reset(new LoggingImpl(config_));
-    logging_->AddRawEventSubscriber(&event_subscriber_);
+    logging_.AddRawEventSubscriber(&event_subscriber_);
   }
 
   virtual ~LoggingImplTest() {
-    logging_->RemoveRawEventSubscriber(&event_subscriber_);
+    logging_.RemoveRawEventSubscriber(&event_subscriber_);
   }
 
-  CastLoggingConfig config_;
-  scoped_ptr<LoggingImpl> logging_;
+  LoggingImpl logging_;
   base::SimpleTestTickClock testing_clock_;
   SimpleEventSubscriber event_subscriber_;
 
@@ -56,7 +50,7 @@
   base::TimeTicks now;
   do {
     now = testing_clock_.NowTicks();
-    logging_->InsertFrameEvent(now, kAudioFrameCaptured, rtp_timestamp,
+    logging_.InsertFrameEvent(now, kAudioFrameCaptured, rtp_timestamp,
                                frame_id);
     testing_clock_.Advance(
         base::TimeDelta::FromMilliseconds(kFrameIntervalMs));
@@ -64,7 +58,6 @@
     ++frame_id;
     time_interval = now - start_time;
   }  while (time_interval.InSeconds() < kIntervalTime1S);
-  base::TimeTicks end_time = now;
 
   // Get logging data.
   std::vector<FrameEvent> frame_events;
@@ -72,19 +65,6 @@
   // Size of vector should be equal to the number of events logged,
   // which equals to number of frames in this case.
   EXPECT_EQ(frame_id, frame_events.size());
-  // Verify stats.
-  FrameStatsMap frame_stats = logging_->GetFrameStatsData(AUDIO_EVENT);
-  // Size of stats equals the number of events.
-  EXPECT_EQ(1u, frame_stats.size());
-  FrameStatsMap::const_iterator it = frame_stats.find(kAudioFrameCaptured);
-  EXPECT_TRUE(it != frame_stats.end());
-  EXPECT_EQ(0, it->second.max_delay.InMilliseconds());
-  EXPECT_EQ(0, it->second.min_delay.InMilliseconds());
-  EXPECT_EQ(start_time, it->second.first_event_time);
-  EXPECT_EQ(end_time, it->second.last_event_time);
-  EXPECT_EQ(0u, it->second.sum_size);
-  // Number of events is equal to the number of frames.
-  EXPECT_EQ(static_cast<int>(frame_id), it->second.event_counter);
 }
 
 TEST_F(LoggingImplTest, FrameLoggingWithSize) {
@@ -100,7 +80,7 @@
     int size = kBaseFrameSizeBytes +
         base::RandInt(-kRandomSizeInterval, kRandomSizeInterval);
     sum_size += static_cast<size_t>(size);
-    logging_->InsertFrameEventWithSize(testing_clock_.NowTicks(),
+    logging_.InsertFrameEventWithSize(testing_clock_.NowTicks(),
                                        kAudioFrameCaptured, rtp_timestamp,
                                        frame_id, size);
     testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs));
@@ -114,16 +94,6 @@
   // Size of vector should be equal to the number of events logged, which
   // equals to number of frames in this case.
   EXPECT_EQ(frame_id, frame_events.size());
-  // Verify stats.
-  FrameStatsMap frame_stats = logging_->GetFrameStatsData(AUDIO_EVENT);
-  // Size of stats equals the number of events.
-  EXPECT_EQ(1u, frame_stats.size());
-  FrameStatsMap::const_iterator it = frame_stats.find(kAudioFrameCaptured);
-  EXPECT_TRUE(it != frame_stats.end());
-  EXPECT_EQ(0, it->second.max_delay.InMilliseconds());
-  EXPECT_EQ(0, it->second.min_delay.InMilliseconds());
-  EXPECT_EQ(0, it->second.sum_delay.InMilliseconds());
-  EXPECT_EQ(sum_size, it->second.sum_size);
 }
 
 TEST_F(LoggingImplTest, FrameLoggingWithDelay) {
@@ -137,7 +107,7 @@
   do {
     int delay = kPlayoutDelayMs +
                 base::RandInt(-kRandomSizeInterval, kRandomSizeInterval);
-    logging_->InsertFrameEventWithDelay(
+    logging_.InsertFrameEventWithDelay(
         testing_clock_.NowTicks(), kAudioFrameCaptured, rtp_timestamp, frame_id,
         base::TimeDelta::FromMilliseconds(delay));
     testing_clock_.Advance(base::TimeDelta::FromMilliseconds(kFrameIntervalMs));
@@ -150,16 +120,6 @@
   event_subscriber_.GetFrameEventsAndReset(&frame_events);
   // Size of vector should be equal to the number of frames logged.
   EXPECT_EQ(frame_id, frame_events.size());
-  // Verify stats.
-  FrameStatsMap frame_stats = logging_->GetFrameStatsData(AUDIO_EVENT);
-  // Size of stats equals the number of events.
-  EXPECT_EQ(1u, frame_stats.size());
-  FrameStatsMap::const_iterator it = frame_stats.find(kAudioFrameCaptured);
-  EXPECT_TRUE(it != frame_stats.end());
-  EXPECT_GE(kPlayoutDelayMs + kRandomSizeInterval,
-      it->second.max_delay.InMilliseconds());
-  EXPECT_LE(kPlayoutDelayMs - kRandomSizeInterval,
-      it->second.min_delay.InMilliseconds());
 }
 
 TEST_F(LoggingImplTest, MultipleEventFrameLogging) {
@@ -169,18 +129,18 @@
   uint32 frame_id = 0u;
   uint32 num_events = 0u;
   do {
-    logging_->InsertFrameEvent(testing_clock_.NowTicks(), kAudioFrameCaptured,
+    logging_.InsertFrameEvent(testing_clock_.NowTicks(), kAudioFrameCaptured,
                                rtp_timestamp, frame_id);
     ++num_events;
     if (frame_id % 2) {
-      logging_->InsertFrameEventWithSize(testing_clock_.NowTicks(),
+      logging_.InsertFrameEventWithSize(testing_clock_.NowTicks(),
                                          kAudioFrameEncoded, rtp_timestamp,
                                          frame_id, 1500);
     } else if (frame_id % 3) {
-      logging_->InsertFrameEvent(testing_clock_.NowTicks(), kVideoFrameDecoded,
+      logging_.InsertFrameEvent(testing_clock_.NowTicks(), kVideoFrameDecoded,
                                  rtp_timestamp, frame_id);
     } else {
-      logging_->InsertFrameEventWithDelay(
+      logging_.InsertFrameEventWithDelay(
           testing_clock_.NowTicks(), kVideoRenderDelay, rtp_timestamp, frame_id,
           base::TimeDelta::FromMilliseconds(20));
     }
@@ -216,7 +176,7 @@
       sum_size += size;
       latest_time = testing_clock_.NowTicks();
       ++num_packets;
-      logging_->InsertPacketEvent(latest_time,
+      logging_.InsertPacketEvent(latest_time,
                                   kDuplicateVideoPacketReceived,
                                   rtp_timestamp,
                                   frame_id,
@@ -234,17 +194,6 @@
   event_subscriber_.GetPacketEventsAndReset(&packet_events);
   // Size of vector should be equal to the number of packets logged.
   EXPECT_EQ(num_packets, static_cast<int>(packet_events.size()));
-  // Verify stats.
-  PacketStatsMap stats_map = logging_->GetPacketStatsData(VIDEO_EVENT);
-  // Size of stats equals the number of event types.
-  EXPECT_EQ(1u, stats_map.size());
-  PacketStatsMap::const_iterator it =
-      stats_map.find(kDuplicateVideoPacketReceived);
-  ASSERT_NE(stats_map.end(), it);
-  EXPECT_EQ(start_time, it->second.first_event_time);
-  EXPECT_EQ(latest_time, it->second.last_event_time);
-  EXPECT_EQ(num_packets, it->second.event_counter);
-  EXPECT_EQ(sum_size, static_cast<int>(it->second.sum_size));
 }
 
 TEST_F(LoggingImplTest, GenericLogging) {
@@ -267,11 +216,11 @@
     int value = kBaseValue + base::RandInt(-5, 5);
     sum_value_rtt += value;
     sumsq_value_rtt += value * value;
-    logging_->InsertGenericEvent(testing_clock_.NowTicks(), kRttMs, value);
+    logging_.InsertGenericEvent(testing_clock_.NowTicks(), kRttMs, value);
     ++num_events;
     ++expected_rtt_count;
     if (i % 2) {
-      logging_->InsertGenericEvent(testing_clock_.NowTicks(), kPacketLoss,
+      logging_.InsertGenericEvent(testing_clock_.NowTicks(), kPacketLoss,
                                    value);
       ++num_events;
       ++expected_packet_loss_count;
@@ -279,7 +228,7 @@
       sumsq_value_pl += value * value;
     }
     if (!(i % 4)) {
-      logging_->InsertGenericEvent(testing_clock_.NowTicks(), kJitterMs, value);
+      logging_.InsertGenericEvent(testing_clock_.NowTicks(), kJitterMs, value);
       ++num_events;
       ++expected_jitter_count;
       sum_value_jitter += value;
@@ -314,34 +263,15 @@
       ++jitter_event_count;
     }
   }
-
-  // Size of generic stats map = number of different events.
-  // Stats - one value per all events.
-  GenericStatsMap stats_map = logging_->GetGenericStatsData();
-  EXPECT_EQ(3u, stats_map.size());
-  GenericStatsMap::const_iterator sit = stats_map.find(kRttMs);
-  EXPECT_EQ(sum_value_rtt, sit->second.sum);
-  EXPECT_EQ(sumsq_value_rtt, sit->second.sum_squared);
-  EXPECT_LE(min_value, sit->second.min);
-  EXPECT_GE(max_value, sit->second.max);
-  sit = stats_map.find(kPacketLoss);
-  EXPECT_EQ(sum_value_pl, sit->second.sum);
-  EXPECT_EQ(sumsq_value_pl, sit->second.sum_squared);
-  EXPECT_LE(min_value, sit->second.min);
-  EXPECT_GE(max_value, sit->second.max);
-  sit = stats_map.find(kJitterMs);
-  EXPECT_EQ(sumsq_value_jitter, sit->second.sum_squared);
-  EXPECT_LE(min_value, sit->second.min);
-  EXPECT_GE(max_value, sit->second.max);
 }
 
 TEST_F(LoggingImplTest, MultipleRawEventSubscribers) {
   SimpleEventSubscriber event_subscriber_2;
 
   // Now logging_ has two subscribers.
-  logging_->AddRawEventSubscriber(&event_subscriber_2);
+  logging_.AddRawEventSubscriber(&event_subscriber_2);
 
-  logging_->InsertFrameEvent(testing_clock_.NowTicks(), kAudioFrameCaptured,
+  logging_.InsertFrameEvent(testing_clock_.NowTicks(), kAudioFrameCaptured,
                              /*rtp_timestamp*/ 0u,
                              /*frame_id*/ 0u);
 
@@ -352,7 +282,7 @@
   event_subscriber_2.GetFrameEventsAndReset(&frame_events);
   EXPECT_EQ(1u, frame_events.size());
 
-  logging_->RemoveRawEventSubscriber(&event_subscriber_2);
+  logging_.RemoveRawEventSubscriber(&event_subscriber_2);
 }
 
 }  // namespace cast
diff --git a/media/cast/logging/logging_stats.cc b/media/cast/logging/logging_stats.cc
deleted file mode 100644
index 08ed47a..0000000
--- a/media/cast/logging/logging_stats.cc
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/cast/logging/logging_stats.h"
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-
-namespace media {
-namespace cast {
-
-LoggingStats::LoggingStats()
-    : frame_stats_(),
-      packet_stats_(),
-      generic_stats_() {
-}
-
-LoggingStats::~LoggingStats() {}
-
-void LoggingStats::Reset() {
-  frame_stats_.clear();
-  packet_stats_.clear();
-  generic_stats_.clear();
-}
-
-void LoggingStats::InsertFrameEvent(const base::TimeTicks& time_of_event,
-                                    CastLoggingEvent event,
-                                    uint32 rtp_timestamp,
-                                    uint32 frame_id) {
-  InsertBaseFrameEvent(time_of_event, event, frame_id, rtp_timestamp);
-}
-
-void LoggingStats::InsertFrameEventWithSize(
-    const base::TimeTicks& time_of_event,
-    CastLoggingEvent event,
-    uint32 rtp_timestamp,
-    uint32 frame_id,
-    int frame_size) {
-  InsertBaseFrameEvent(time_of_event, event, frame_id, rtp_timestamp);
-  // Update size.
-  FrameStatsMap::iterator it = frame_stats_.find(event);
-  DCHECK(it != frame_stats_.end());
-  it->second.sum_size += frame_size;
-}
-
-void LoggingStats::InsertFrameEventWithDelay(
-    const base::TimeTicks& time_of_event,
-    CastLoggingEvent event,
-    uint32 rtp_timestamp,
-    uint32 frame_id,
-    base::TimeDelta delay) {
-  InsertBaseFrameEvent(time_of_event, event, frame_id, rtp_timestamp);
-  // Update size.
-  FrameStatsMap::iterator it = frame_stats_.find(event);
-  DCHECK(it != frame_stats_.end());
-  it->second.sum_delay += delay;
-  if (delay > it->second.max_delay || it->second.event_counter == 1)
-    it->second.max_delay = delay;
-  if (delay < it->second.min_delay || it->second.event_counter == 1)
-    it->second.min_delay = delay;
-}
-
-void LoggingStats::InsertBaseFrameEvent(const base::TimeTicks& time_of_event,
-                                        CastLoggingEvent event,
-                                        uint32 frame_id,
-                                        uint32 rtp_timestamp) {
-  // Does this belong to an existing event?
-  FrameStatsMap::iterator it = frame_stats_.find(event);
-  if (it == frame_stats_.end()) {
-    // New event.
-    FrameLogStats stats;
-    stats.first_event_time = time_of_event;
-    stats.last_event_time = time_of_event;
-    stats.event_counter = 1;
-    frame_stats_.insert(std::make_pair(event, stats));
-  } else {
-    ++(it->second.event_counter);
-    it->second.last_event_time = time_of_event;
-  }
-}
-
-void LoggingStats::InsertPacketEvent(const base::TimeTicks& time_of_event,
-                                     CastLoggingEvent event,
-                                     uint32 rtp_timestamp,
-                                     uint32 frame_id,
-                                     uint16 packet_id,
-                                     uint16 max_packet_id,
-                                     size_t size) {
-  // Does this packet belong to an existing event?
-  PacketStatsMap::iterator it = packet_stats_.find(event);
-  if (it == packet_stats_.end()) {
-    // New event.
-    PacketLogStats stats;
-    stats.first_event_time = time_of_event;
-    stats.last_event_time = time_of_event;
-    stats.sum_size = size;
-    stats.event_counter = 1;
-    packet_stats_.insert(std::make_pair(event, stats));
-  } else {
-    // Add to an existing event.
-    it->second.sum_size += size;
-    ++(it->second.event_counter);
-    it->second.last_event_time = time_of_event;
-  }
-}
-
-void LoggingStats::InsertGenericEvent(const base::TimeTicks& time_of_event,
-                                      CastLoggingEvent event, int value) {
-  // Does this event belong to an existing event?
-  GenericStatsMap::iterator it = generic_stats_.find(event);
-  if (it == generic_stats_.end()) {
-    // New event.
-    GenericLogStats stats;
-    stats.first_event_time = time_of_event;
-    stats.last_event_time = time_of_event;
-    stats.sum = value;
-    stats.sum_squared = value * value;
-    stats.min = value;
-    stats.max = value;
-    stats.event_counter = 1;
-    generic_stats_.insert(std::make_pair(event, stats));
-  } else {
-    // Add to existing event.
-    it->second.sum += value;
-    it->second.sum_squared += value * value;
-    ++(it->second.event_counter);
-    it->second.last_event_time = time_of_event;
-    if (it->second.min > value) {
-      it->second.min = value;
-    } else if (it->second.max < value) {
-      it->second.max = value;
-    }
-  }
-}
-
-FrameStatsMap LoggingStats::GetFrameStatsData(EventMediaType media_type) const {
-  DCHECK(media_type == AUDIO_EVENT || media_type == VIDEO_EVENT);
-
-  FrameStatsMap frame_map_to_return;
-  for (FrameStatsMap::const_iterator it = frame_stats_.begin();
-       it != frame_stats_.end();
-       ++it) {
-    if (GetEventMediaType(it->first) == media_type) {
-      frame_map_to_return.insert(std::make_pair(it->first, it->second));
-    }
-  }
-
-  return frame_map_to_return;
-}
-
-PacketStatsMap LoggingStats::GetPacketStatsData(
-    EventMediaType media_type) const {
-  DCHECK(media_type == AUDIO_EVENT || media_type == VIDEO_EVENT);
-
-  PacketStatsMap packet_map_to_return;
-  for (PacketStatsMap::const_iterator it = packet_stats_.begin();
-       it != packet_stats_.end();
-       ++it) {
-    if (GetEventMediaType(it->first) == media_type) {
-      packet_map_to_return.insert(std::make_pair(it->first, it->second));
-    }
-  }
-
-  return packet_map_to_return;
-}
-
-GenericStatsMap LoggingStats::GetGenericStatsData() const {
-  return generic_stats_;
-}
-
-scoped_ptr<base::DictionaryValue> ConvertStats(
-    const FrameStatsMap& frame_stats_map,
-    const PacketStatsMap& packet_stats_map) {
-  scoped_ptr<base::DictionaryValue> overall_stats(new base::DictionaryValue);
-
-  scoped_ptr<base::DictionaryValue> overall_frame_stats(
-      new base::DictionaryValue);
-  for (FrameStatsMap::const_iterator it = frame_stats_map.begin();
-       it != frame_stats_map.end();
-       ++it) {
-    scoped_ptr<base::DictionaryValue> frame_stats(new base::DictionaryValue);
-
-    frame_stats->SetDouble("firstEventTime",
-                           it->second.first_event_time.ToInternalValue());
-    frame_stats->SetDouble("lastEventTime",
-                           it->second.last_event_time.ToInternalValue());
-    frame_stats->SetInteger("count", it->second.event_counter);
-    frame_stats->SetInteger("sizeTotal",
-                            static_cast<int>(it->second.sum_size));
-    frame_stats->SetInteger("minDelayMs",
-                            it->second.min_delay.InMilliseconds());
-    frame_stats->SetInteger("maxDelayMs",
-                            it->second.max_delay.InMilliseconds());
-    frame_stats->SetInteger("sumDelayMs",
-                            it->second.sum_delay.InMilliseconds());
-
-    overall_frame_stats->Set(CastLoggingToString(it->first),
-                             frame_stats.release());
-  }
-
-  overall_stats->Set("frameStats", overall_frame_stats.release());
-
-  scoped_ptr<base::DictionaryValue> overall_packet_stats(
-      new base::DictionaryValue);
-  for (PacketStatsMap::const_iterator it = packet_stats_map.begin();
-       it != packet_stats_map.end();
-       ++it) {
-    scoped_ptr<base::DictionaryValue> packet_stats(new base::DictionaryValue);
-
-    packet_stats->SetDouble("firstEventTime",
-                            it->second.first_event_time.ToInternalValue());
-    packet_stats->SetDouble("lastEventTime",
-                            it->second.last_event_time.ToInternalValue());
-    packet_stats->SetDouble("lastEventTime",
-                            it->second.last_event_time.ToInternalValue());
-    packet_stats->SetInteger("count", it->second.event_counter);
-    packet_stats->SetInteger("sizeTotal",
-                             static_cast<int>(it->second.sum_size));
-
-    overall_packet_stats->Set(CastLoggingToString(it->first),
-                              packet_stats.release());
-  }
-
-  overall_stats->Set("packetStats", overall_packet_stats.release());
-
-  return overall_stats.Pass();
-}
-
-}  // namespace cast
-}  // namespace media
diff --git a/media/cast/logging/logging_stats.h b/media/cast/logging/logging_stats.h
deleted file mode 100644
index e04db8d..0000000
--- a/media/cast/logging/logging_stats.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_CAST_LOGGING_LOGGING_STATS_H_
-#define MEDIA_CAST_LOGGING_LOGGING_STATS_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/time/time.h"
-#include "media/cast/logging/logging_defines.h"
-
-namespace base {
-class DictionaryValue;
-}
-
-namespace media {
-namespace cast {
-
-class LoggingStats {
- public:
-  LoggingStats();
-  ~LoggingStats();
-
-  void Reset();
-
-  void InsertFrameEvent(const base::TimeTicks& time_of_event,
-                        CastLoggingEvent event,
-                        uint32 rtp_timestamp,
-                        uint32 frame_id);
-
-  void InsertFrameEventWithSize(const base::TimeTicks& time_of_event,
-                                CastLoggingEvent event,
-                                uint32 rtp_timestamp,
-                                uint32 frame_id,
-                                int frame_size);
-
-  void InsertFrameEventWithDelay(const base::TimeTicks& time_of_event,
-                                 CastLoggingEvent event,
-                                 uint32 rtp_timestamp,
-                                 uint32 frame_id,
-                                 base::TimeDelta delay);
-
-  void InsertPacketEvent(const base::TimeTicks& time_of_event,
-                         CastLoggingEvent event,
-                         uint32 rtp_timestamp,
-                         uint32 frame_id,
-                         uint16 packet_id,
-                         uint16 max_packet_id,
-                         size_t size);
-
-  void InsertGenericEvent(const base::TimeTicks& time_of_event,
-                          CastLoggingEvent event, int value);
-
-  FrameStatsMap GetFrameStatsData(EventMediaType media_type) const;
-
-  PacketStatsMap GetPacketStatsData(EventMediaType media_type) const;
-
-  GenericStatsMap GetGenericStatsData() const;
-
- private:
-  void InsertBaseFrameEvent(const base::TimeTicks& time_of_event,
-                            CastLoggingEvent event,
-                            uint32 frame_id,
-                            uint32 rtp_timestamp);
-
-  FrameStatsMap frame_stats_;
-  PacketStatsMap packet_stats_;
-  GenericStatsMap generic_stats_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoggingStats);
-};
-
-// Converts stats provided in |frame_stats_map| and |packet_stats_map| to
-// base::DictionaryValue format. See .cc file for the exact structure.
-scoped_ptr<base::DictionaryValue> ConvertStats(
-    const FrameStatsMap& frame_stats_map,
-    const PacketStatsMap& packet_stats_map);
-
-}  // namespace cast
-}  // namespace media
-
-#endif  // MEDIA_CAST_LOGGING_LOGGING_STATS_H_
-
diff --git a/media/cast/logging/proto/raw_events.proto b/media/cast/logging/proto/raw_events.proto
index 4664c62..afca046 100644
--- a/media/cast/logging/proto/raw_events.proto
+++ b/media/cast/logging/proto/raw_events.proto
@@ -75,7 +75,7 @@
   optional uint32 relative_rtp_timestamp = 1;
 
   repeated EventType event_type = 2 [packed = true];
-  repeated int64 event_timestamp_micros = 3 [packed = true];
+  repeated int64 event_timestamp_ms = 3 [packed = true];
 
   // Size is set only for kAudioFrameEncoded and kVideoFrameEncoded.
   optional int32 encoded_frame_size = 4;
@@ -87,7 +87,7 @@
 message BasePacketEvent {
   optional int32 packet_id = 1;
   repeated EventType event_type = 2 [packed = true];
-  repeated int64 event_timestamp_micros = 3 [packed = true];
+  repeated int64 event_timestamp_ms = 3 [packed = true];
 }
 
 message AggregatedPacketEvent {
@@ -95,8 +95,3 @@
   repeated BasePacketEvent base_packet_event = 2;
 };
 
-message AggregatedGenericEvent {
-  optional EventType event_type = 1;
-  repeated int64 event_timestamp_micros = 2 [packed = true];
-  repeated int32 value = 3 [packed = true];
-};
diff --git a/media/cast/logging/serialize_deserialize_test.cc b/media/cast/logging/serialize_deserialize_test.cc
index caf06a0..788b276 100644
--- a/media/cast/logging/serialize_deserialize_test.cc
+++ b/media/cast/logging/serialize_deserialize_test.cc
@@ -50,7 +50,7 @@
     metadata_.set_num_frame_events(10);
     metadata_.set_num_packet_events(10);
 
-    int64 event_time_micros = 0;
+    int64 event_time_ms = 0;
     // Insert frame and packet events with RTP timestamps 0, 90, 180, ...
     for (int i = 0; i < metadata_.num_frame_events(); i++) {
       linked_ptr<AggregatedFrameEvent> frame_event(new AggregatedFrameEvent);
@@ -59,8 +59,8 @@
            ++event_index) {
         frame_event->add_event_type(
             ToProtoEventType(kVideoFrameEvents[event_index]));
-        frame_event->add_event_timestamp_micros(event_time_micros);
-        event_time_micros += 1024;
+        frame_event->add_event_timestamp_ms(event_time_ms);
+        event_time_ms += 1024;
       }
       frame_event->set_encoded_frame_size(
           kEncodedFrameSize[i % arraysize(kEncodedFrameSize)]);
@@ -70,7 +70,7 @@
           std::make_pair(frame_event->relative_rtp_timestamp(), frame_event));
     }
 
-    event_time_micros = 0;
+    event_time_ms = 0;
     int packet_id = 0;
     for (int i = 0; i < metadata_.num_packet_events(); i++) {
       linked_ptr<AggregatedPacketEvent> packet_event(new AggregatedPacketEvent);
@@ -84,8 +84,8 @@
              ++event_index) {
           base_event->add_event_type(
               ToProtoEventType(kVideoPacketEvents[event_index]));
-          base_event->add_event_timestamp_micros(event_time_micros);
-          event_time_micros += 256;
+          base_event->add_event_timestamp_ms(event_time_ms);
+          event_time_ms += 256;
         }
       }
       packet_event_map_.insert(
diff --git a/media/cast/logging/simple_event_subscriber_unittest.cc b/media/cast/logging/simple_event_subscriber_unittest.cc
index 310db9c..e6905e1 100644
--- a/media/cast/logging/simple_event_subscriber_unittest.cc
+++ b/media/cast/logging/simple_event_subscriber_unittest.cc
@@ -21,9 +21,10 @@
       : testing_clock_(new base::SimpleTestTickClock()),
         task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
         cast_environment_(new CastEnvironment(
-            scoped_ptr<base::TickClock>(testing_clock_).Pass(), task_runner_,
-            task_runner_, task_runner_, task_runner_, task_runner_,
-            task_runner_, GetLoggingConfigWithRawEventsAndStatsEnabled())) {
+            scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+            task_runner_,
+            task_runner_,
+            task_runner_)) {
     cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_);
   }
 
diff --git a/media/cast/logging/stats_event_subscriber.cc b/media/cast/logging/stats_event_subscriber.cc
new file mode 100644
index 0000000..9a2df9d
--- /dev/null
+++ b/media/cast/logging/stats_event_subscriber.cc
@@ -0,0 +1,139 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/cast/logging/stats_event_subscriber.h"
+
+#include "base/logging.h"
+
+namespace media {
+namespace cast {
+
+StatsEventSubscriber::StatsEventSubscriber(EventMediaType event_media_type)
+    : event_media_type_(event_media_type) {}
+
+StatsEventSubscriber::~StatsEventSubscriber() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void StatsEventSubscriber::OnReceiveFrameEvent(const FrameEvent& frame_event) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  CastLoggingEvent type = frame_event.type;
+  if (GetEventMediaType(type) != event_media_type_)
+    return;
+
+  FrameStatsMap::iterator it = frame_stats_.find(type);
+  if (it == frame_stats_.end()) {
+    FrameLogStats stats;
+    stats.first_event_time = frame_event.timestamp;
+    stats.last_event_time = frame_event.timestamp;
+    stats.event_counter = 1;
+    stats.sum_size = frame_event.size;
+    stats.min_delay = frame_event.delay_delta;
+    stats.max_delay = frame_event.delay_delta;
+    stats.sum_delay = frame_event.delay_delta;
+    frame_stats_.insert(std::make_pair(type, stats));
+  } else {
+    ++(it->second.event_counter);
+    it->second.last_event_time = frame_event.timestamp;
+    it->second.sum_size += frame_event.size;
+    it->second.sum_delay += frame_event.delay_delta;
+    if (frame_event.delay_delta > it->second.max_delay)
+      it->second.max_delay = frame_event.delay_delta;
+    if (frame_event.delay_delta < it->second.min_delay)
+      it->second.min_delay = frame_event.delay_delta;
+  }
+}
+
+void StatsEventSubscriber::OnReceivePacketEvent(
+    const PacketEvent& packet_event) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  CastLoggingEvent type = packet_event.type;
+  if (GetEventMediaType(type) != event_media_type_)
+    return;
+
+  PacketStatsMap::iterator it = packet_stats_.find(type);
+  if (it == packet_stats_.end()) {
+    PacketLogStats stats;
+    stats.first_event_time = packet_event.timestamp;
+    stats.last_event_time = packet_event.timestamp;
+    stats.event_counter = 1;
+    stats.sum_size = packet_event.size;
+    packet_stats_.insert(std::make_pair(type, stats));
+  } else {
+    it->second.last_event_time = packet_event.timestamp;
+    ++(it->second.event_counter);
+    it->second.sum_size += packet_event.size;
+  }
+}
+
+void StatsEventSubscriber::OnReceiveGenericEvent(
+    const GenericEvent& generic_event) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  CastLoggingEvent type = generic_event.type;
+  if (GetEventMediaType(type) != event_media_type_)
+    return;
+
+  GenericStatsMap::iterator it = generic_stats_.find(type);
+  if (it == generic_stats_.end()) {
+    GenericLogStats stats;
+    stats.first_event_time = generic_event.timestamp;
+    stats.last_event_time = generic_event.timestamp;
+    stats.event_counter = 1;
+    stats.sum = generic_event.value;
+    stats.sum_squared = generic_event.value * generic_event.value;
+    stats.min = generic_event.value;
+    stats.max = generic_event.value;
+    generic_stats_.insert(std::make_pair(type, stats));
+  } else {
+    it->second.last_event_time = generic_event.timestamp;
+    ++(it->second.event_counter);
+    it->second.sum += generic_event.value;
+    it->second.sum_squared += generic_event.value * generic_event.value;
+    if (it->second.min > generic_event.value) {
+      it->second.min = generic_event.value;
+    } else if (it->second.max < generic_event.value) {
+      it->second.max = generic_event.value;
+    }
+  }
+}
+
+void StatsEventSubscriber::GetFrameStats(FrameStatsMap* frame_stats_map) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(frame_stats_map);
+
+  frame_stats_map->clear();
+  frame_stats_map->insert(frame_stats_.begin(), frame_stats_.end());
+}
+
+void StatsEventSubscriber::GetPacketStats(
+    PacketStatsMap* packet_stats_map) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(packet_stats_map);
+
+  packet_stats_map->clear();
+  packet_stats_map->insert(packet_stats_.begin(), packet_stats_.end());
+}
+
+void StatsEventSubscriber::GetGenericStats(
+    GenericStatsMap* generic_stats_map) const {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(generic_stats_map);
+
+  generic_stats_map->clear();
+  generic_stats_map->insert(generic_stats_.begin(), generic_stats_.end());
+}
+
+void StatsEventSubscriber::Reset() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+
+  frame_stats_.clear();
+  packet_stats_.clear();
+  generic_stats_.clear();
+}
+
+}  // namespace cast
+}  // namespace media
diff --git a/media/cast/logging/stats_event_subscriber.h b/media/cast/logging/stats_event_subscriber.h
new file mode 100644
index 0000000..8541982
--- /dev/null
+++ b/media/cast/logging/stats_event_subscriber.h
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAST_LOGGING_STATS_EVENT_SUBSCRIBER_H_
+#define MEDIA_CAST_LOGGING_STATS_EVENT_SUBSCRIBER_H_
+
+#include "base/threading/thread_checker.h"
+#include "media/cast/logging/logging_defines.h"
+#include "media/cast/logging/raw_event_subscriber.h"
+
+namespace media {
+namespace cast {
+
+// A RawEventSubscriber implementation that subscribes to events,
+// and aggregates them into stats.
+class StatsEventSubscriber : public RawEventSubscriber {
+ public:
+  StatsEventSubscriber(EventMediaType media_type);
+
+  virtual ~StatsEventSubscriber();
+
+  // RawReventSubscriber implementations.
+  virtual void OnReceiveFrameEvent(const FrameEvent& frame_event) OVERRIDE;
+  virtual void OnReceivePacketEvent(const PacketEvent& packet_event) OVERRIDE;
+  virtual void OnReceiveGenericEvent(const GenericEvent& generic_event)
+      OVERRIDE;
+
+  // Assigns |frame_stats_map| with frame stats.
+  void GetFrameStats(FrameStatsMap* frame_stats_map) const;
+
+  // Assigns |packet_stats_map| with packet stats.
+  void GetPacketStats(PacketStatsMap* packet_stats_map) const;
+
+  // Assigns |generic_stats_map| with generic stats data.
+  void GetGenericStats(GenericStatsMap* generic_stats_map) const;
+
+  // Resets all stats maps in this object.
+  void Reset();
+
+ private:
+  EventMediaType event_media_type_;
+  FrameStatsMap frame_stats_;
+  PacketStatsMap packet_stats_;
+  GenericStatsMap generic_stats_;
+  base::ThreadChecker thread_checker_;
+  DISALLOW_COPY_AND_ASSIGN(StatsEventSubscriber);
+};
+
+}  // namespace cast
+}  // namespace media
+
+#endif  // MEDIA_CAST_LOGGING_STATS_EVENT_SUBSCRIBER_H_
diff --git a/media/cast/logging/stats_event_subscriber_unittest.cc b/media/cast/logging/stats_event_subscriber_unittest.cc
new file mode 100644
index 0000000..9af3369
--- /dev/null
+++ b/media/cast/logging/stats_event_subscriber_unittest.cc
@@ -0,0 +1,173 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/time/tick_clock.h"
+#include "media/cast/cast_environment.h"
+#include "media/cast/logging/logging_defines.h"
+#include "media/cast/logging/stats_event_subscriber.h"
+#include "media/cast/test/fake_single_thread_task_runner.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+namespace cast {
+
+class StatsEventSubscriberTest : public ::testing::Test {
+ protected:
+  StatsEventSubscriberTest()
+      : testing_clock_(new base::SimpleTestTickClock()),
+        task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
+        cast_environment_(new CastEnvironment(
+            scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+            task_runner_,
+            task_runner_,
+            task_runner_)) {}
+
+  virtual ~StatsEventSubscriberTest() {
+    if (subscriber_.get())
+      cast_environment_->Logging()->RemoveRawEventSubscriber(subscriber_.get());
+  }
+
+  void Init(EventMediaType event_media_type) {
+    DCHECK(!subscriber_.get());
+    subscriber_.reset(new StatsEventSubscriber(event_media_type));
+    cast_environment_->Logging()->AddRawEventSubscriber(subscriber_.get());
+  }
+
+  base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
+  scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
+  scoped_refptr<CastEnvironment> cast_environment_;
+  scoped_ptr<StatsEventSubscriber> subscriber_;
+};
+
+TEST_F(StatsEventSubscriberTest, FrameStats) {
+  Init(VIDEO_EVENT);
+  uint32 rtp_timestamp = 0;
+  uint32 frame_id = 0;
+  int num_frames = 10;
+  int frame_size = 123;
+  int delay_base_ms = 10;
+  base::TimeTicks now;
+  for (int i = 0; i < num_frames; i++) {
+    now = testing_clock_->NowTicks();
+    cast_environment_->Logging()->InsertFrameEvent(
+        now, kVideoFrameReceived, rtp_timestamp, frame_id);
+    testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30));
+
+    cast_environment_->Logging()->InsertFrameEventWithSize(
+        now, kVideoFrameEncoded, rtp_timestamp, i, frame_size);
+    testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30));
+
+    cast_environment_->Logging()->InsertFrameEventWithDelay(
+        now,
+        kVideoRenderDelay,
+        rtp_timestamp,
+        i,
+        base::TimeDelta::FromMilliseconds(i * delay_base_ms));
+    testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30));
+
+    rtp_timestamp += 90;
+  }
+
+  // Verify stats.
+  FrameStatsMap frame_stats;
+  subscriber_->GetFrameStats(&frame_stats);
+
+  // Size of stats equals the number of events.
+  EXPECT_EQ(3u, frame_stats.size());
+  FrameStatsMap::const_iterator it = frame_stats.find(kVideoFrameReceived);
+  ASSERT_TRUE(it != frame_stats.end());
+  EXPECT_EQ(num_frames, it->second.event_counter);
+
+  it = frame_stats.find(kVideoFrameEncoded);
+  ASSERT_TRUE(it != frame_stats.end());
+
+  EXPECT_EQ(num_frames * frame_size, static_cast<int>(it->second.sum_size));
+
+  it = frame_stats.find(kVideoRenderDelay);
+  ASSERT_TRUE(it != frame_stats.end());
+
+  EXPECT_EQ(0, it->second.min_delay.InMilliseconds());
+  EXPECT_EQ((num_frames - 1) * delay_base_ms,
+            it->second.max_delay.InMilliseconds());
+  EXPECT_EQ((num_frames - 1) * num_frames / 2 * delay_base_ms,
+            it->second.sum_delay.InMilliseconds());
+}
+
+TEST_F(StatsEventSubscriberTest, PacketStats) {
+  Init(AUDIO_EVENT);
+  uint32 rtp_timestamp = 0;
+  uint32 frame_id = 0;
+  int num_packets = 10;
+  int packet_size = 123;
+  base::TimeTicks first_event_time = testing_clock_->NowTicks();
+  base::TimeTicks now;
+  for (int i = 0; i < num_packets; i++) {
+    now = testing_clock_->NowTicks();
+    cast_environment_->Logging()->InsertPacketEvent(now,
+                                                    kAudioPacketSentToPacer,
+                                                    rtp_timestamp,
+                                                    frame_id,
+                                                    0,
+                                                    10,
+                                                    packet_size);
+    testing_clock_->Advance(base::TimeDelta::FromMilliseconds(30));
+  }
+
+  PacketStatsMap stats_map;
+  subscriber_->GetPacketStats(&stats_map);
+
+  // Size of stats equals the number of event types.
+  EXPECT_EQ(1u, stats_map.size());
+  PacketStatsMap::const_iterator it = stats_map.find(kAudioPacketSentToPacer);
+  ASSERT_NE(stats_map.end(), it);
+
+  EXPECT_EQ(first_event_time, it->second.first_event_time);
+  EXPECT_EQ(now, it->second.last_event_time);
+  EXPECT_EQ(num_packets, it->second.event_counter);
+  EXPECT_EQ(num_packets * packet_size, static_cast<int>(it->second.sum_size));
+}
+
+TEST_F(StatsEventSubscriberTest, GenericStats) {
+  Init(OTHER_EVENT);
+  int num_generic_events = 10;
+  int value = 123;
+  for (int i = 0; i < num_generic_events; i++) {
+    cast_environment_->Logging()->InsertGenericEvent(
+        testing_clock_->NowTicks(), kRttMs, value);
+  }
+
+  GenericStatsMap stats_map;
+  subscriber_->GetGenericStats(&stats_map);
+
+  EXPECT_EQ(1u, stats_map.size());
+  GenericStatsMap::const_iterator it = stats_map.find(kRttMs);
+  ASSERT_NE(stats_map.end(), it);
+
+  EXPECT_EQ(num_generic_events, it->second.event_counter);
+  EXPECT_EQ(num_generic_events * value, it->second.sum);
+  EXPECT_EQ(static_cast<uint64>(num_generic_events * value * value),
+            it->second.sum_squared);
+  EXPECT_LE(value, it->second.min);
+  EXPECT_GE(value, it->second.max);
+}
+
+TEST_F(StatsEventSubscriberTest, Reset) {
+  Init(VIDEO_EVENT);
+  cast_environment_->Logging()->InsertFrameEvent(
+      testing_clock_->NowTicks(), kVideoFrameReceived, 0, 0);
+
+  FrameStatsMap frame_stats;
+  subscriber_->GetFrameStats(&frame_stats);
+  EXPECT_EQ(1u, frame_stats.size());
+
+  subscriber_->Reset();
+  subscriber_->GetFrameStats(&frame_stats);
+  EXPECT_TRUE(frame_stats.empty());
+}
+
+}  // namespace cast
+}  // namespace media
diff --git a/media/cast/logging/stats_util.cc b/media/cast/logging/stats_util.cc
new file mode 100644
index 0000000..9b50b5d
--- /dev/null
+++ b/media/cast/logging/stats_util.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/cast/logging/stats_util.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+
+namespace media {
+namespace cast {
+
+scoped_ptr<base::DictionaryValue> ConvertStats(
+    const FrameStatsMap& frame_stats_map,
+    const PacketStatsMap& packet_stats_map) {
+  scoped_ptr<base::DictionaryValue> overall_stats(new base::DictionaryValue);
+
+  scoped_ptr<base::DictionaryValue> overall_frame_stats(
+      new base::DictionaryValue);
+  for (FrameStatsMap::const_iterator it = frame_stats_map.begin();
+       it != frame_stats_map.end();
+       ++it) {
+    scoped_ptr<base::DictionaryValue> frame_stats(new base::DictionaryValue);
+
+    frame_stats->SetDouble("firstEventTime",
+                           it->second.first_event_time.ToInternalValue());
+    frame_stats->SetDouble("lastEventTime",
+                           it->second.last_event_time.ToInternalValue());
+    frame_stats->SetInteger("count", it->second.event_counter);
+    frame_stats->SetInteger("sizeTotal", static_cast<int>(it->second.sum_size));
+    frame_stats->SetInteger("minDelayMs",
+                            it->second.min_delay.InMilliseconds());
+    frame_stats->SetInteger("maxDelayMs",
+                            it->second.max_delay.InMilliseconds());
+    frame_stats->SetInteger("sumDelayMs",
+                            it->second.sum_delay.InMilliseconds());
+
+    overall_frame_stats->Set(CastLoggingToString(it->first),
+                             frame_stats.release());
+  }
+
+  overall_stats->Set("frameStats", overall_frame_stats.release());
+
+  scoped_ptr<base::DictionaryValue> overall_packet_stats(
+      new base::DictionaryValue);
+  for (PacketStatsMap::const_iterator it = packet_stats_map.begin();
+       it != packet_stats_map.end();
+       ++it) {
+    scoped_ptr<base::DictionaryValue> packet_stats(new base::DictionaryValue);
+
+    packet_stats->SetDouble("firstEventTime",
+                            it->second.first_event_time.ToInternalValue());
+    packet_stats->SetDouble("lastEventTime",
+                            it->second.last_event_time.ToInternalValue());
+    packet_stats->SetDouble("lastEventTime",
+                            it->second.last_event_time.ToInternalValue());
+    packet_stats->SetInteger("count", it->second.event_counter);
+    packet_stats->SetInteger("sizeTotal",
+                             static_cast<int>(it->second.sum_size));
+
+    overall_packet_stats->Set(CastLoggingToString(it->first),
+                              packet_stats.release());
+  }
+
+  overall_stats->Set("packetStats", overall_packet_stats.release());
+
+  return overall_stats.Pass();
+}
+
+}  // namespace cast
+}  // namespace media
diff --git a/media/cast/logging/stats_util.h b/media/cast/logging/stats_util.h
new file mode 100644
index 0000000..bbac273
--- /dev/null
+++ b/media/cast/logging/stats_util.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAST_LOGGING_STATS_UTIL_H_
+#define MEDIA_CAST_LOGGING_STATS_UTIL_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "media/cast/logging/logging_defines.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace media {
+namespace cast {
+
+// Converts stats provided in |frame_stats_map| and |packet_stats_map| to
+// base::DictionaryValue format. See .cc file for the exact structure.
+scoped_ptr<base::DictionaryValue> ConvertStats(
+    const FrameStatsMap& frame_stats_map,
+    const PacketStatsMap& packet_stats_map);
+
+}  // namespace cast
+}  // namespace media
+
+#endif  // MEDIA_CAST_LOGGING_STATS_UTIL_H_
diff --git a/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc b/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc
index 6feea7c..41411c3 100644
--- a/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc
+++ b/media/cast/rtcp/receiver_rtcp_event_subscriber_unittest.cc
@@ -28,9 +28,10 @@
       : testing_clock_(new base::SimpleTestTickClock()),
         task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
         cast_environment_(new CastEnvironment(
-            scoped_ptr<base::TickClock>(testing_clock_).Pass(), task_runner_,
-            task_runner_, task_runner_, task_runner_, task_runner_,
-            task_runner_, GetLoggingConfigWithRawEventsAndStatsEnabled())) {}
+            scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+            task_runner_,
+            task_runner_,
+            task_runner_)) {}
 
   virtual ~ReceiverRtcpEventSubscriberTest() {}
 
diff --git a/media/cast/rtcp/rtcp.cc b/media/cast/rtcp/rtcp.cc
index c56d093..bb19f3e 100644
--- a/media/cast/rtcp/rtcp.cc
+++ b/media/cast/rtcp/rtcp.cc
@@ -310,24 +310,12 @@
     dlrr.delay_since_last_rr = ConvertToNtpDiff(delay_seconds, delay_fraction);
   }
 
-  cast_environment_->PostTask(
-      CastEnvironment::TRANSPORT, FROM_HERE,
-      base::Bind(&Rtcp::SendRtcpFromRtpSenderOnTransportThread,
-                 base::Unretained(this), packet_type_flags, sender_info, dlrr,
-                 sender_log_message, local_ssrc_, c_name_));
+  transport_sender_->SendRtcpFromRtpSender(
+      packet_type_flags, sender_info, dlrr, sender_log_message, local_ssrc_,
+      c_name_);
   UpdateNextTimeToSendRtcp();
 }
 
-void Rtcp::SendRtcpFromRtpSenderOnTransportThread(
-    uint32 packet_type_flags, const transport::RtcpSenderInfo& sender_info,
-    const transport::RtcpDlrrReportBlock& dlrr,
-    const transport::RtcpSenderLogMessage& sender_log, uint32 sending_ssrc,
-    std::string c_name) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
-  transport_sender_->SendRtcpFromRtpSender(packet_type_flags, sender_info, dlrr,
-                                           sender_log, sending_ssrc, c_name);
-}
-
 void Rtcp::OnReceivedNtp(uint32 ntp_seconds, uint32 ntp_fraction) {
   last_report_received_ = (ntp_seconds << 16) + (ntp_fraction >> 16);
 
diff --git a/media/cast/rtcp/rtcp.h b/media/cast/rtcp/rtcp.h
index 8759f6b..30a155d 100644
--- a/media/cast/rtcp/rtcp.h
+++ b/media/cast/rtcp/rtcp.h
@@ -144,14 +144,6 @@
                            uint32 last_ntp_seconds,
                            uint32 last_ntp_fraction);
 
-  void SendRtcpFromRtpSenderOnTransportThread(
-      uint32 packet_type_flags,
-      const transport::RtcpSenderInfo& sender_info,
-      const transport::RtcpDlrrReportBlock& dlrr,
-      const transport::RtcpSenderLogMessage& sender_log,
-      uint32 sending_ssrc,
-      std::string c_name);
-
   scoped_refptr<CastEnvironment> cast_environment_;
   transport::CastTransportSender* const transport_sender_;
   const base::TimeDelta rtcp_interval_;
diff --git a/media/cast/rtcp/rtcp_receiver_unittest.cc b/media/cast/rtcp/rtcp_receiver_unittest.cc
index 06b25e9..8e8e4f9 100644
--- a/media/cast/rtcp/rtcp_receiver_unittest.cc
+++ b/media/cast/rtcp/rtcp_receiver_unittest.cc
@@ -162,11 +162,7 @@
             scoped_ptr<base::TickClock>(testing_clock_).Pass(),
             task_runner_,
             task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            GetDefaultCastReceiverLoggingConfig())),
+            task_runner_)),
         rtcp_receiver_(new RtcpReceiver(cast_environment_,
                                         &mock_sender_feedback_,
                                         &mock_receiver_feedback_,
diff --git a/media/cast/rtcp/rtcp_sender_unittest.cc b/media/cast/rtcp/rtcp_sender_unittest.cc
index 18d67d1..8e6ceb2 100644
--- a/media/cast/rtcp/rtcp_sender_unittest.cc
+++ b/media/cast/rtcp/rtcp_sender_unittest.cc
@@ -79,11 +79,7 @@
             scoped_ptr<base::TickClock>(testing_clock_).Pass(),
             task_runner_,
             task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            GetDefaultCastSenderLoggingConfig())),
+            task_runner_)),
         rtcp_sender_(new RtcpSender(cast_environment_,
                                     &test_transport_,
                                     kSendingSsrc,
diff --git a/media/cast/rtcp/rtcp_unittest.cc b/media/cast/rtcp/rtcp_unittest.cc
index bcf7be1..628f0d2 100644
--- a/media/cast/rtcp/rtcp_unittest.cc
+++ b/media/cast/rtcp/rtcp_unittest.cc
@@ -143,16 +143,11 @@
   RtcpTest()
       : testing_clock_(new base::SimpleTestTickClock()),
         task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
-        logging_config_(GetDefaultCastSenderLoggingConfig()),
         cast_environment_(new CastEnvironment(
             scoped_ptr<base::TickClock>(testing_clock_).Pass(),
             task_runner_,
             task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            logging_config_)),
+            task_runner_)),
         sender_to_receiver_(testing_clock_),
         receiver_to_sender_(cast_environment_, testing_clock_),
         rtp_sender_stats_(kVideoFrequency) {
@@ -163,7 +158,6 @@
         NULL,
         testing_clock_,
         dummy_endpoint,
-        logging_config_,
         base::Bind(&UpdateCastTransportStatus),
         transport::BulkRawEventsCallback(),
         base::TimeDelta(),
@@ -190,7 +184,6 @@
 
   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
-  CastLoggingConfig logging_config_;
   scoped_refptr<CastEnvironment> cast_environment_;
   RtcpTestPacketSender sender_to_receiver_;
   scoped_ptr<transport::CastTransportSenderImpl> transport_sender_;
diff --git a/media/cast/rtcp/sender_rtcp_event_subscriber_unittest.cc b/media/cast/rtcp/sender_rtcp_event_subscriber_unittest.cc
index 56897c2..3850e80 100644
--- a/media/cast/rtcp/sender_rtcp_event_subscriber_unittest.cc
+++ b/media/cast/rtcp/sender_rtcp_event_subscriber_unittest.cc
@@ -27,9 +27,10 @@
       : testing_clock_(new base::SimpleTestTickClock()),
         task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
         cast_environment_(new CastEnvironment(
-            scoped_ptr<base::TickClock>(testing_clock_).Pass(), task_runner_,
-            task_runner_, task_runner_, task_runner_, task_runner_,
-            task_runner_, GetLoggingConfigWithRawEventsAndStatsEnabled())),
+            scoped_ptr<base::TickClock>(testing_clock_).Pass(),
+            task_runner_,
+            task_runner_,
+            task_runner_)),
         event_subscriber_(kMaxEventEntries) {
     cast_environment_->Logging()->AddRawEventSubscriber(&event_subscriber_);
   }
diff --git a/media/cast/rtp_receiver/receiver_stats.h b/media/cast/rtp_receiver/receiver_stats.h
index 33b393e..05a067f 100644
--- a/media/cast/rtp_receiver/receiver_stats.h
+++ b/media/cast/rtp_receiver/receiver_stats.h
@@ -7,20 +7,21 @@
 
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
+#include "media/cast/rtcp/rtcp.h"
 #include "media/cast/rtp_receiver/rtp_receiver_defines.h"
 
 namespace media {
 namespace cast {
 
-class ReceiverStats {
+class ReceiverStats : public RtpReceiverStatistics {
  public:
   explicit ReceiverStats(base::TickClock* clock);
-  ~ReceiverStats();
+  virtual ~ReceiverStats() OVERRIDE;
 
-  void GetStatistics(uint8* fraction_lost,
-                     uint32* cumulative_lost,  // 24 bits valid.
-                     uint32* extended_high_sequence_number,
-                     uint32* jitter);
+  virtual void GetStatistics(uint8* fraction_lost,
+                             uint32* cumulative_lost,  // 24 bits valid.
+                             uint32* extended_high_sequence_number,
+                             uint32* jitter) OVERRIDE;
   void UpdateStatistics(const RtpCastHeader& header);
 
  private:
diff --git a/media/cast/rtp_receiver/rtp_parser/rtp_parser.cc b/media/cast/rtp_receiver/rtp_parser/rtp_parser.cc
index fabc5fd..31fae9a 100644
--- a/media/cast/rtp_receiver/rtp_parser/rtp_parser.cc
+++ b/media/cast/rtp_receiver/rtp_parser/rtp_parser.cc
@@ -17,10 +17,8 @@
 static const uint8 kCastKeyFrameBitMask = 0x80;
 static const uint8 kCastReferenceFrameIdBitMask = 0x40;
 
-RtpParser::RtpParser(RtpData* incoming_payload_callback,
-                     const RtpParserConfig parser_config)
-    : data_callback_(incoming_payload_callback),
-      parser_config_(parser_config) {}
+RtpParser::RtpParser(const RtpParserConfig parser_config)
+    : parser_config_(parser_config) {}
 
 RtpParser::~RtpParser() {}
 
@@ -112,7 +110,7 @@
   if (rtp_header->max_packet_id < rtp_header->packet_id)
     return false;
 
-  data_callback_->OnReceivedPayloadData(data_ptr, data_length, rtp_header);
+  OnReceivedPayloadData(data_ptr, data_length, *rtp_header);
   return true;
 }
 
diff --git a/media/cast/rtp_receiver/rtp_parser/rtp_parser.h b/media/cast/rtp_receiver/rtp_parser/rtp_parser.h
index d5cbb34..7e4c948 100644
--- a/media/cast/rtp_receiver/rtp_parser/rtp_parser.h
+++ b/media/cast/rtp_receiver/rtp_parser/rtp_parser.h
@@ -11,8 +11,6 @@
 namespace media {
 namespace cast {
 
-class RtpData;
-
 struct RtpParserConfig {
   RtpParserConfig() {
     ssrc = 0;
@@ -29,15 +27,17 @@
 
 class RtpParser {
  public:
-  RtpParser(RtpData* incoming_payload_callback,
-            const RtpParserConfig parser_config);
+  RtpParser(const RtpParserConfig parser_config);
 
-  ~RtpParser();
+  virtual ~RtpParser();
 
   bool ParsePacket(const uint8* packet,
                    size_t length,
                    RtpCastHeader* rtp_header);
-
+ protected:
+  virtual void OnReceivedPayloadData(const uint8* payload_data,
+                                     size_t payload_size,
+                                     const RtpCastHeader& rtp_header) = 0;
  private:
   bool ParseCommon(const uint8* packet,
                    size_t length,
@@ -45,7 +45,6 @@
 
   bool ParseCast(const uint8* packet, size_t length, RtpCastHeader* rtp_header);
 
-  RtpData* data_callback_;
   RtpParserConfig parser_config_;
   transport::FrameIdWrapHelper frame_id_wrap_helper_;
   transport::FrameIdWrapHelper reference_frame_id_wrap_helper_;
diff --git a/media/cast/rtp_receiver/rtp_parser/rtp_parser_unittest.cc b/media/cast/rtp_receiver/rtp_parser/rtp_parser_unittest.cc
index fbf1e93..94e67c6 100644
--- a/media/cast/rtp_receiver/rtp_parser/rtp_parser_unittest.cc
+++ b/media/cast/rtp_receiver/rtp_parser/rtp_parser_unittest.cc
@@ -20,11 +20,13 @@
 static const uint16 kTestSeqNum = 4321;
 static const uint8 kRefFrameId = 17;
 
-class RtpDataTest : public RtpData {
+class RtpTestParser : public RtpParser {
  public:
-  RtpDataTest() { expected_header_.reset(new RtpCastHeader()); }
+  RtpTestParser(const RtpParserConfig config) : RtpParser(config) {
+    expected_header_.reset(new RtpCastHeader());
+  }
 
-  virtual ~RtpDataTest() {}
+  virtual ~RtpTestParser() {}
 
   void SetExpectedHeader(const RtpCastHeader& cast_header) {
     memcpy(expected_header_.get(), &cast_header, sizeof(RtpCastHeader));
@@ -32,9 +34,9 @@
 
   virtual void OnReceivedPayloadData(const uint8* payloadData,
                                      size_t payloadSize,
-                                     const RtpCastHeader* rtpHeader) OVERRIDE {
-    VerifyCommonHeader(*rtpHeader);
-    VerifyCastHeader(*rtpHeader);
+                                     const RtpCastHeader& rtpHeader) OVERRIDE {
+    VerifyCommonHeader(rtpHeader);
+    VerifyCastHeader(rtpHeader);
   }
 
   void VerifyCommonHeader(const RtpCastHeader& parsed_header) {
@@ -56,15 +58,14 @@
  private:
   scoped_ptr<RtpCastHeader> expected_header_;
 
-  DISALLOW_COPY_AND_ASSIGN(RtpDataTest);
+  DISALLOW_COPY_AND_ASSIGN(RtpTestParser);
 };
 
 class RtpParserTest : public ::testing::Test {
  protected:
   RtpParserTest() {
     PopulateConfig();
-    rtp_data_.reset(new RtpDataTest());
-    rtp_parser_.reset(new RtpParser(rtp_data_.get(), config_));
+    rtp_parser_.reset(new RtpTestParser(config_));
     cast_header_.is_reference = true;
     cast_header_.reference_frame_id = kRefFrameId;
     packet_builder_.SetSsrc(kTestSsrc);
@@ -82,9 +83,8 @@
     config_.ssrc = kTestSsrc;
   }
 
-  scoped_ptr<RtpDataTest> rtp_data_;
   RtpPacketBuilder packet_builder_;
-  scoped_ptr<RtpParser> rtp_parser_;
+  scoped_ptr<RtpTestParser> rtp_parser_;
   RtpParserConfig config_;
   RtpCastHeader cast_header_;
 };
@@ -95,7 +95,7 @@
   packet_builder_.BuildHeader(packet, kPacketLength);
   // Parse packet as is.
   RtpCastHeader rtp_header;
-  rtp_data_->SetExpectedHeader(cast_header_);
+  rtp_parser_->SetExpectedHeader(cast_header_);
   EXPECT_TRUE(rtp_parser_->ParsePacket(packet, kPacketLength, &rtp_header));
 }
 
@@ -112,7 +112,7 @@
   cast_header_.frame_id = 10;
   cast_header_.packet_id = 5;
   cast_header_.max_packet_id = 15;
-  rtp_data_->SetExpectedHeader(cast_header_);
+  rtp_parser_->SetExpectedHeader(cast_header_);
   // Parse packet as is.
   RtpCastHeader rtp_header;
   EXPECT_TRUE(rtp_parser_->ParsePacket(packet, kPacketLength, &rtp_header));
@@ -143,7 +143,7 @@
   cast_header_.frame_id = 10;
   cast_header_.packet_id = 65535;
   cast_header_.max_packet_id = 65535;
-  rtp_data_->SetExpectedHeader(cast_header_);
+  rtp_parser_->SetExpectedHeader(cast_header_);
   // Parse packet as is.
   RtpCastHeader rtp_header;
   EXPECT_TRUE(rtp_parser_->ParsePacket(packet, kPacketLength, &rtp_header));
@@ -187,7 +187,7 @@
   packet_builder_.BuildHeader(packet, kPacketLength);
   // Parse packet as is.
   RtpCastHeader rtp_header;
-  rtp_data_->SetExpectedHeader(cast_header_);
+  rtp_parser_->SetExpectedHeader(cast_header_);
   EXPECT_TRUE(rtp_parser_->ParsePacket(packet, kPacketLength, &rtp_header));
 }
 
diff --git a/media/cast/rtp_receiver/rtp_receiver.cc b/media/cast/rtp_receiver/rtp_receiver.cc
index 808235f..f640261 100644
--- a/media/cast/rtp_receiver/rtp_receiver.cc
+++ b/media/cast/rtp_receiver/rtp_receiver.cc
@@ -13,15 +13,13 @@
 namespace media {
 namespace cast {
 
-RtpReceiver::RtpReceiver(base::TickClock* clock,
-                         const AudioReceiverConfig* audio_config,
-                         const VideoReceiverConfig* video_config,
-                         RtpData* incoming_payload_callback) {
-  DCHECK(incoming_payload_callback) << "Invalid argument";
-  DCHECK(audio_config || video_config) << "Invalid argument";
+namespace {
 
-  // Configure parser.
+static RtpParserConfig GetRtpParserConfig(
+    const AudioReceiverConfig* audio_config,
+    const VideoReceiverConfig* video_config) {
   RtpParserConfig config;
+  DCHECK(audio_config || video_config) << "Invalid argument";
   if (audio_config) {
     config.ssrc = audio_config->incoming_ssrc;
     config.payload_type = audio_config->rtp_payload_type;
@@ -32,8 +30,16 @@
     config.payload_type = video_config->rtp_payload_type;
     config.video_codec = video_config->codec;
   }
-  stats_.reset(new ReceiverStats(clock));
-  parser_.reset(new RtpParser(incoming_payload_callback, config));
+  return config;
+}
+
+}  // namespace
+
+RtpReceiver::RtpReceiver(base::TickClock* clock,
+                         const AudioReceiverConfig* audio_config,
+                         const VideoReceiverConfig* video_config) :
+    RtpParser(GetRtpParserConfig(audio_config, video_config)),
+    stats_(clock) {
 }
 
 RtpReceiver::~RtpReceiver() {}
@@ -51,20 +57,12 @@
 
 bool RtpReceiver::ReceivedPacket(const uint8* packet, size_t length) {
   RtpCastHeader rtp_header;
-  if (!parser_->ParsePacket(packet, length, &rtp_header))
+  if (!ParsePacket(packet, length, &rtp_header))
     return false;
 
-  stats_->UpdateStatistics(rtp_header);
+  stats_.UpdateStatistics(rtp_header);
   return true;
 }
 
-void RtpReceiver::GetStatistics(uint8* fraction_lost,
-                                uint32* cumulative_lost,
-                                uint32* extended_high_sequence_number,
-                                uint32* jitter) {
-  stats_->GetStatistics(
-      fraction_lost, cumulative_lost, extended_high_sequence_number, jitter);
-}
-
 }  // namespace cast
 }  // namespace media
diff --git a/media/cast/rtp_receiver/rtp_receiver.h b/media/cast/rtp_receiver/rtp_receiver.h
index 5cfa8c6..421d124 100644
--- a/media/cast/rtp_receiver/rtp_receiver.h
+++ b/media/cast/rtp_receiver/rtp_receiver.h
@@ -10,44 +10,30 @@
 #include "base/memory/scoped_ptr.h"
 #include "media/cast/cast_config.h"
 #include "media/cast/rtcp/rtcp.h"
+#include "media/cast/rtp_receiver/receiver_stats.h"
+#include "media/cast/rtp_receiver/rtp_parser/rtp_parser.h"
 #include "media/cast/rtp_receiver/rtp_receiver_defines.h"
 
 namespace media {
 namespace cast {
 
-class RtpData {
- public:
-  virtual void OnReceivedPayloadData(const uint8* payload_data,
-                                     size_t payload_size,
-                                     const RtpCastHeader* rtp_header) = 0;
-
- protected:
-  virtual ~RtpData() {}
-};
-
-class ReceiverStats;
-class RtpParser;
-
-class RtpReceiver {
+class RtpReceiver : public RtpParser {
  public:
   RtpReceiver(base::TickClock* clock,
               const AudioReceiverConfig* audio_config,
-              const VideoReceiverConfig* video_config,
-              RtpData* incoming_payload_callback);
-  ~RtpReceiver();
+              const VideoReceiverConfig* video_config);
+  virtual ~RtpReceiver();
 
   static uint32 GetSsrcOfSender(const uint8* rtcp_buffer, size_t length);
 
   bool ReceivedPacket(const uint8* packet, size_t length);
 
-  void GetStatistics(uint8* fraction_lost,
-                     uint32* cumulative_lost,  // 24 bits valid.
-                     uint32* extended_high_sequence_number,
-                     uint32* jitter);
+  RtpReceiverStatistics* GetStatistics() {
+    return &stats_;
+  }
 
  private:
-  scoped_ptr<ReceiverStats> stats_;
-  scoped_ptr<RtpParser> parser_;
+  ReceiverStats stats_;
 
   DISALLOW_COPY_AND_ASSIGN(RtpReceiver);
 };
diff --git a/media/cast/test/encode_decode_test.cc b/media/cast/test/encode_decode_test.cc
index a405242..3151833 100644
--- a/media/cast/test/encode_decode_test.cc
+++ b/media/cast/test/encode_decode_test.cc
@@ -73,16 +73,12 @@
       : testing_clock_(new base::SimpleTestTickClock()),
         task_runner_(new test::FakeSingleThreadTaskRunner(testing_clock_)),
         // CastEnvironment will only be used by the vp8 decoder; Enable only the
-        // video decoder and main threads.
+        // video and main threads.
         cast_environment_(new CastEnvironment(
             scoped_ptr<base::TickClock>(testing_clock_).Pass(),
             task_runner_,
             NULL,
-            NULL,
-            NULL,
-            task_runner_,
-            NULL,
-            GetDefaultCastReceiverLoggingConfig())),
+            task_runner_)),
         test_callback_(new EncodeDecodeTestFrameCallback()) {
     testing_clock_->Advance(
         base::TimeDelta::FromMilliseconds(kStartMillisecond));
diff --git a/media/cast/test/end2end_unittest.cc b/media/cast/test/end2end_unittest.cc
index e85f9aa..6949fa8 100644
--- a/media/cast/test/end2end_unittest.cc
+++ b/media/cast/test/end2end_unittest.cc
@@ -28,6 +28,7 @@
 #include "media/cast/logging/simple_event_subscriber.h"
 #include "media/cast/test/fake_single_thread_task_runner.h"
 #include "media/cast/test/utility/audio_utility.h"
+#include "media/cast/test/utility/default_config.h"
 #include "media/cast/test/utility/video_utility.h"
 #include "media/cast/transport/cast_transport_config.h"
 #include "media/cast/transport/cast_transport_defines.h"
@@ -368,8 +369,9 @@
         << "time_since_capture - upper_bound == "
         << (time_since_capture - upper_bound).InMilliseconds() << " mS";
     EXPECT_LE(expected_video_frame.capture_time, render_time);
-    EXPECT_EQ(expected_video_frame.width, video_frame->coded_size().width());
-    EXPECT_EQ(expected_video_frame.height, video_frame->coded_size().height());
+    EXPECT_EQ(expected_video_frame.width, video_frame->visible_rect().width());
+    EXPECT_EQ(expected_video_frame.height,
+              video_frame->visible_rect().height());
 
     gfx::Size size(expected_video_frame.width, expected_video_frame.height);
     scoped_refptr<media::VideoFrame> expected_I420_frame =
@@ -402,25 +404,16 @@
         testing_clock_receiver_(new base::SimpleTestTickClock()),
         task_runner_(
             new test::FakeSingleThreadTaskRunner(testing_clock_sender_)),
-        logging_config_(GetLoggingConfigWithRawEventsAndStatsEnabled()),
         cast_environment_sender_(new CastEnvironment(
             scoped_ptr<base::TickClock>(testing_clock_sender_).Pass(),
             task_runner_,
             task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            logging_config_)),
+            task_runner_)),
         cast_environment_receiver_(new CastEnvironment(
             scoped_ptr<base::TickClock>(testing_clock_receiver_).Pass(),
             task_runner_,
             task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            task_runner_,
-            logging_config_)),
+            task_runner_)),
         receiver_to_sender_(cast_environment_receiver_),
         sender_to_receiver_(cast_environment_sender_),
         test_receiver_audio_callback_(new TestReceiverAudioCallback()),
@@ -505,7 +498,6 @@
         NULL,
         testing_clock_sender_,
         dummy_endpoint,
-        logging_config_,
         base::Bind(&UpdateCastTransportStatus),
         base::Bind(&End2EndTest::LogRawEvents, base::Unretained(this)),
         base::TimeDelta::FromSeconds(1),
@@ -520,8 +512,10 @@
     // Initializing audio and video senders.
     cast_sender_->InitializeAudio(audio_sender_config_,
                                   base::Bind(&AudioInitializationStatus));
-    cast_sender_->InitializeVideo(
-        video_sender_config_, base::Bind(&VideoInitializationStatus), NULL);
+    cast_sender_->InitializeVideo(video_sender_config_,
+                                  base::Bind(&VideoInitializationStatus),
+                                  CreateDefaultVideoEncodeAcceleratorCallback(),
+                                  CreateDefaultVideoEncodeMemoryCallback());
 
     receiver_to_sender_.SetPacketReceiver(cast_sender_->packet_receiver());
     sender_to_receiver_.SetPacketReceiver(cast_receiver_->packet_receiver());
@@ -599,7 +593,6 @@
   base::SimpleTestTickClock* testing_clock_sender_;
   base::SimpleTestTickClock* testing_clock_receiver_;
   scoped_refptr<test::FakeSingleThreadTaskRunner> task_runner_;
-  CastLoggingConfig logging_config_;
   scoped_refptr<CastEnvironment> cast_environment_sender_;
   scoped_refptr<CastEnvironment> cast_environment_receiver_;
 
diff --git a/media/cast/test/fake_gpu_video_accelerator_factories.cc b/media/cast/test/fake_gpu_video_accelerator_factories.cc
deleted file mode 100644
index 9718a56..0000000
--- a/media/cast/test/fake_gpu_video_accelerator_factories.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/cast/test/fake_gpu_video_accelerator_factories.h"
-
-#include "base/logging.h"
-#include "media/cast/test/fake_video_encode_accelerator.h"
-#include "media/video/video_decode_accelerator.h"
-
-namespace media {
-namespace cast {
-namespace test {
-
-FakeGpuVideoAcceleratorFactories::FakeGpuVideoAcceleratorFactories(
-    const scoped_refptr<base::SingleThreadTaskRunner>& fake_task_runner)
-    : fake_task_runner_(fake_task_runner) {}
-
-FakeGpuVideoAcceleratorFactories::~FakeGpuVideoAcceleratorFactories() {}
-
-scoped_ptr<VideoEncodeAccelerator>
-FakeGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
-  return scoped_ptr<VideoEncodeAccelerator>(new FakeVideoEncodeAccelerator());
-}
-
-base::SharedMemory* FakeGpuVideoAcceleratorFactories::CreateSharedMemory(
-    size_t size) {
-  base::SharedMemory* shm = new base::SharedMemory();
-  if (!shm->CreateAndMapAnonymous(size)) {
-    NOTREACHED();
-  }
-  return shm;
-}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-FakeGpuVideoAcceleratorFactories::GetTaskRunner() {
-  return fake_task_runner_;
-}
-
-bool FakeGpuVideoAcceleratorFactories::CreateTextures(
-    int32 count,
-    const gfx::Size& size,
-    std::vector<uint32>* texture_ids,
-    std::vector<gpu::Mailbox>* texture_mailboxes,
-    uint32 texture_target) {
-  return false;
-}
-
-scoped_ptr<VideoDecodeAccelerator>
-FakeGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator(
-    VideoCodecProfile profile) {
-  return scoped_ptr<VideoDecodeAccelerator>(
-      static_cast<media::VideoDecodeAccelerator*>(NULL));
-}
-
-}  // namespace test
-}  // namespace cast
-}  // namespace media
diff --git a/media/cast/test/fake_gpu_video_accelerator_factories.h b/media/cast/test/fake_gpu_video_accelerator_factories.h
deleted file mode 100644
index ebcadfd..0000000
--- a/media/cast/test/fake_gpu_video_accelerator_factories.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_CAST_TEST_FAKE_GPU_VIDEO_ACCELERATOR_FACTORIES_H_
-#define MEDIA_CAST_TEST_FAKE_GPU_VIDEO_ACCELERATOR_FACTORIES_H_
-
-#include "media/filters/gpu_video_accelerator_factories.h"
-
-#include "base/message_loop/message_loop.h"
-#include "media/cast/test/fake_single_thread_task_runner.h"
-
-namespace media {
-namespace cast {
-namespace test {
-
-class FakeGpuVideoAcceleratorFactories : public GpuVideoAcceleratorFactories {
- public:
-  explicit FakeGpuVideoAcceleratorFactories(
-      const scoped_refptr<base::SingleThreadTaskRunner>& fake_task_runner);
-
-  virtual scoped_ptr<VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
-      OVERRIDE;
-
-  virtual base::SharedMemory* CreateSharedMemory(size_t size) OVERRIDE;
-
-  virtual scoped_refptr<base::SingleThreadTaskRunner>
-      GetTaskRunner() OVERRIDE;
-  //
-  //  The following functions are no-op.
-  //
-  virtual bool CreateTextures(int32 count,
-                              const gfx::Size& size,
-                              std::vector<uint32>* texture_ids,
-                              std::vector<gpu::Mailbox>* texture_mailboxes,
-                              uint32 texture_target) OVERRIDE;
-
-  virtual void DeleteTexture(uint32 texture_id) OVERRIDE {}
-
-  virtual void WaitSyncPoint(uint32 sync_point) OVERRIDE {}
-
-  virtual void ReadPixels(uint32 texture_id,
-                          const gfx::Rect& visible_rect,
-                          const SkBitmap& pixels) OVERRIDE {};
-
-  virtual scoped_ptr<VideoDecodeAccelerator> CreateVideoDecodeAccelerator(
-      VideoCodecProfile profile) OVERRIDE;
-
- private:
-  friend class base::RefCountedThreadSafe<FakeGpuVideoAcceleratorFactories>;
-  virtual ~FakeGpuVideoAcceleratorFactories();
-
-  const scoped_refptr<base::SingleThreadTaskRunner> fake_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeGpuVideoAcceleratorFactories);
-};
-
-}  // namespace test
-}  // namespace cast
-}  // namespace media
-
-#endif  // MEDIA_CAST_TEST_FAKE_GPU_VIDEO_ACCELERATOR_FACTORIES_H_
diff --git a/media/cast/test/fake_video_encode_accelerator.h b/media/cast/test/fake_video_encode_accelerator.h
index 20ad7c3..2e0c93a 100644
--- a/media/cast/test/fake_video_encode_accelerator.h
+++ b/media/cast/test/fake_video_encode_accelerator.h
@@ -18,6 +18,7 @@
 class FakeVideoEncodeAccelerator : public VideoEncodeAccelerator {
  public:
   FakeVideoEncodeAccelerator();
+  virtual ~FakeVideoEncodeAccelerator();
 
   virtual void Initialize(media::VideoFrame::Format input_format,
                           const gfx::Size& input_visible_size,
@@ -36,8 +37,6 @@
   virtual void Destroy() OVERRIDE;
 
  private:
-  virtual ~FakeVideoEncodeAccelerator();
-
   VideoEncodeAccelerator::Client* client_;
   bool first_;
 
diff --git a/media/cast/test/receiver.cc b/media/cast/test/receiver.cc
index 052d02d..77abee8 100644
--- a/media/cast/test/receiver.cc
+++ b/media/cast/test/receiver.cc
@@ -83,7 +83,7 @@
 
   test::InputBuilder input_rx(
       "Choose audio receiver SSRC.", DEFAULT_AUDIO_INCOMING_SSRC, 1, INT_MAX);
-  audio_config->incoming_ssrc = input_tx.GetIntInput();
+  audio_config->incoming_ssrc = input_rx.GetIntInput();
 }
 
 void GetSsrcs(VideoReceiverConfig* video_config) {
@@ -190,12 +190,8 @@
   CommandLine::Init(argc, argv);
   InitLogging(logging::LoggingSettings());
 
-  // Enable raw event logging only.
-  media::cast::CastLoggingConfig logging_config;
-  logging_config.enable_raw_data_collection = true;
-
   scoped_refptr<media::cast::CastEnvironment> cast_environment(
-      new media::cast::StandaloneCastEnvironment(logging_config));
+      new media::cast::StandaloneCastEnvironment);
 
   media::cast::AudioReceiverConfig audio_config =
       media::cast::GetAudioReceiverConfig();
diff --git a/media/cast/test/sender.cc b/media/cast/test/sender.cc
index 62c6bf3..8c2681b 100644
--- a/media/cast/test/sender.cc
+++ b/media/cast/test/sender.cc
@@ -22,6 +22,7 @@
 #include "media/cast/logging/logging_defines.h"
 #include "media/cast/logging/proto/raw_events.pb.h"
 #include "media/cast/test/utility/audio_utility.h"
+#include "media/cast/test/utility/default_config.h"
 #include "media/cast/test/utility/input_builder.h"
 #include "media/cast/test/utility/video_utility.h"
 #include "media/cast/transport/cast_transport_defines.h"
@@ -452,11 +453,7 @@
   media::cast::VideoSenderConfig video_config =
       media::cast::GetVideoSenderConfig();
 
-  // Enable main and send side threads only. Enable raw event logging.
   // Running transport on the main thread.
-  media::cast::CastLoggingConfig logging_config;
-  logging_config.enable_raw_data_collection = true;
-
   // Setting up transport config.
   media::cast::transport::CastTransportAudioConfig transport_audio_config;
   media::cast::transport::CastTransportVideoConfig transport_video_config;
@@ -467,25 +464,20 @@
   transport_video_config.base.ssrc = video_config.sender_ssrc;
   transport_video_config.base.rtp_config = video_config.rtp_config;
 
-  // Enable main and send side threads only. Enable raw event and stats logging.
+  // Enable raw event and stats logging.
   // Running transport on the main thread.
   scoped_refptr<media::cast::CastEnvironment> cast_environment(
       new media::cast::CastEnvironment(
           make_scoped_ptr<base::TickClock>(new base::DefaultTickClock()),
           io_message_loop.message_loop_proxy(),
           audio_thread.message_loop_proxy(),
-          NULL,
-          video_thread.message_loop_proxy(),
-          NULL,
-          io_message_loop.message_loop_proxy(),
-          media::cast::GetLoggingConfigWithRawEventsAndStatsEnabled()));
+          video_thread.message_loop_proxy()));
 
   scoped_ptr<media::cast::transport::CastTransportSender> transport_sender =
       media::cast::transport::CastTransportSender::Create(
           NULL,  // net log.
           cast_environment->Clock(),
           remote_endpoint,
-          logging_config,
           base::Bind(&UpdateCastTransportStatus),
           base::Bind(&LogRawEvents, cast_environment),
           base::TimeDelta::FromSeconds(1),
@@ -498,7 +490,11 @@
       media::cast::CastSender::Create(cast_environment, transport_sender.get());
 
   cast_sender->InitializeVideo(
-      video_config, base::Bind(&InitializationResult), NULL);
+      video_config,
+      base::Bind(&InitializationResult),
+      media::cast::CreateDefaultVideoEncodeAcceleratorCallback(),
+      media::cast::CreateDefaultVideoEncodeMemoryCallback());
+
   cast_sender->InitializeAudio(audio_config, base::Bind(&InitializationResult));
 
   transport_sender->SetPacketReceiver(cast_sender->packet_receiver());
diff --git a/media/cast/test/utility/barcode.h b/media/cast/test/utility/barcode.h
index 64650a0..6dbd085 100644
--- a/media/cast/test/utility/barcode.h
+++ b/media/cast/test/utility/barcode.h
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#ifndef MEDIA_CAST_TEST_UTILITY_BARCODE_H_
+#define MEDIA_CAST_TEST_UTILITY_BARCODE_H_
+
 #include <vector>
 
 #include "base/memory/ref_counted.h"
@@ -49,3 +52,5 @@
 }  // namespace test
 }  // namespace cast
 }  // namespace media
+
+#endif  // MEDIA_CAST_TEST_UTILITY_BARCODE_H_
diff --git a/media/cast/test/utility/default_config.cc b/media/cast/test/utility/default_config.cc
index 34eaedc..1631bfe 100644
--- a/media/cast/test/utility/default_config.cc
+++ b/media/cast/test/utility/default_config.cc
@@ -4,8 +4,24 @@
 
 #include "media/cast/test/utility/default_config.h"
 
+#include "base/bind.h"
 #include "media/cast/transport/cast_transport_config.h"
 
+namespace {
+
+void CreateVideoEncodeAccelerator(
+    const media::cast::ReceiveVideoEncodeAcceleratorCallback& callback) {
+  // Do nothing.
+}
+
+void CreateVideoEncodeMemory(
+    size_t size,
+    const media::cast::ReceiveVideoEncodeMemoryCallback& callback) {
+  // Do nothing.
+}
+
+}  // namespace
+
 namespace media {
 namespace cast {
 
@@ -33,5 +49,14 @@
   return config;
 }
 
+CreateVideoEncodeAcceleratorCallback
+CreateDefaultVideoEncodeAcceleratorCallback() {
+  return base::Bind(&CreateVideoEncodeAccelerator);
+}
+
+CreateVideoEncodeMemoryCallback CreateDefaultVideoEncodeMemoryCallback() {
+  return base::Bind(&CreateVideoEncodeMemory);
+}
+
 }  // namespace cast
 }  // namespace media
diff --git a/media/cast/test/utility/default_config.h b/media/cast/test/utility/default_config.h
index ef7c79a..59a2440 100644
--- a/media/cast/test/utility/default_config.h
+++ b/media/cast/test/utility/default_config.h
@@ -20,6 +20,13 @@
 // name.
 VideoReceiverConfig GetDefaultVideoReceiverConfig();
 
+// Returns a callback that does nothing.
+CreateVideoEncodeAcceleratorCallback
+    CreateDefaultVideoEncodeAcceleratorCallback();
+
+// Returns a callback that does nothing.
+CreateVideoEncodeMemoryCallback CreateDefaultVideoEncodeMemoryCallback();
+
 }  // namespace cast
 }  // namespace media
 
diff --git a/media/cast/test/utility/standalone_cast_environment.cc b/media/cast/test/utility/standalone_cast_environment.cc
index 7e82620..790b283 100644
--- a/media/cast/test/utility/standalone_cast_environment.cc
+++ b/media/cast/test/utility/standalone_cast_environment.cc
@@ -9,34 +9,23 @@
 namespace media {
 namespace cast {
 
-StandaloneCastEnvironment::StandaloneCastEnvironment(
-    const CastLoggingConfig& logging_config)
+StandaloneCastEnvironment::StandaloneCastEnvironment()
     : CastEnvironment(
           make_scoped_ptr<base::TickClock>(new base::DefaultTickClock()),
           NULL,
           NULL,
-          NULL,
-          NULL,
-          NULL,
-          NULL,
-          logging_config),
+          NULL),
       main_thread_("StandaloneCastEnvironment Main"),
-      audio_encode_thread_("StandaloneCastEnvironment Audio Encode"),
-      audio_decode_thread_("StandaloneCastEnvironment Audio Decode"),
-      video_encode_thread_("StandaloneCastEnvironment Video Encode"),
-      video_decode_thread_("StandaloneCastEnvironment Video Decode"),
-      transport_thread_("StandaloneCastEnvironment Transport") {
+      audio_thread_("StandaloneCastEnvironment Audio"),
+      video_thread_("StandaloneCastEnvironment Video") {
 #define CREATE_TASK_RUNNER(name, options)   \
   name##_thread_.StartWithOptions(options); \
   CastEnvironment::name##_thread_proxy_ = name##_thread_.message_loop_proxy()
 
   CREATE_TASK_RUNNER(main,
                      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
-  CREATE_TASK_RUNNER(audio_encode, base::Thread::Options());
-  CREATE_TASK_RUNNER(audio_decode, base::Thread::Options());
-  CREATE_TASK_RUNNER(video_encode, base::Thread::Options());
-  CREATE_TASK_RUNNER(video_decode, base::Thread::Options());
-  CREATE_TASK_RUNNER(transport, base::Thread::Options());
+  CREATE_TASK_RUNNER(audio, base::Thread::Options());
+  CREATE_TASK_RUNNER(video, base::Thread::Options());
 
 #undef CREATE_TASK_RUNNER
 }
@@ -48,11 +37,8 @@
 void StandaloneCastEnvironment::Shutdown() {
   DCHECK(CalledOnValidThread());
   main_thread_.Stop();
-  audio_encode_thread_.Stop();
-  audio_decode_thread_.Stop();
-  video_encode_thread_.Stop();
-  video_decode_thread_.Stop();
-  transport_thread_.Stop();
+  audio_thread_.Stop();
+  video_thread_.Stop();
 }
 
 }  // namespace cast
diff --git a/media/cast/test/utility/standalone_cast_environment.h b/media/cast/test/utility/standalone_cast_environment.h
index 39c6e7c..0deab6d 100644
--- a/media/cast/test/utility/standalone_cast_environment.h
+++ b/media/cast/test/utility/standalone_cast_environment.h
@@ -17,7 +17,7 @@
 class StandaloneCastEnvironment : public CastEnvironment,
                                   public base::ThreadChecker {
  public:
-  explicit StandaloneCastEnvironment(const CastLoggingConfig& logging_config);
+  explicit StandaloneCastEnvironment();
 
   // Stops all threads backing the task runners, blocking the caller until
   // complete.
@@ -27,11 +27,8 @@
   virtual ~StandaloneCastEnvironment();
 
   base::Thread main_thread_;
-  base::Thread audio_encode_thread_;
-  base::Thread audio_decode_thread_;
-  base::Thread video_encode_thread_;
-  base::Thread video_decode_thread_;
-  base::Thread transport_thread_;
+  base::Thread audio_thread_;
+  base::Thread video_thread_;
 
   DISALLOW_COPY_AND_ASSIGN(StandaloneCastEnvironment);
 };
diff --git a/media/cast/test/utility/udp_proxy.cc b/media/cast/test/utility/udp_proxy.cc
new file mode 100644
index 0000000..8f8c41b
--- /dev/null
+++ b/media/cast/test/utility/udp_proxy.cc
@@ -0,0 +1,527 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/cast/test/utility/udp_proxy.h"
+
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/thread.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/udp/udp_socket.h"
+
+namespace media {
+namespace cast {
+namespace test {
+
+const size_t kMaxPacketSize = 65536;
+
+Packet::Packet(size_t size) : data(size) {}
+Packet::~Packet() {}
+
+PacketPipe::PacketPipe() {}
+PacketPipe::~PacketPipe() {}
+void PacketPipe::InitOnIOThread() {}
+void PacketPipe::AppendToPipe(scoped_ptr<PacketPipe> pipe) {
+  if (pipe_) {
+    pipe_->AppendToPipe(pipe.Pass());
+  } else {
+    pipe_ = pipe.Pass();
+  }
+}
+
+// Roughly emulates a buffer inside a device.
+// If the buffer is full, packets are dropped.
+// Packets are output at a maximum bandwidth.
+class Buffer : public PacketPipe {
+ public:
+  Buffer(size_t buffer_size,
+         double max_megabits_per_second) :
+      buffer_size_(0),
+      max_buffer_size_(buffer_size),
+      max_megabits_per_second_(max_megabits_per_second),
+      weak_factory_(this) {
+  }
+
+  virtual void Send(scoped_refptr<Packet> packet) OVERRIDE {
+    if (packet->data.size() + buffer_size_ <= max_buffer_size_) {
+      buffer_.push_back(packet);
+      buffer_size_ += packet->data.size();
+      if (buffer_.size() == 1) {
+        Schedule();
+      }
+    }
+  }
+
+ private:
+  void Schedule() {
+    double megabits = buffer_.front()->data.size() * 8 / 1000000.0;
+    double seconds = megabits / max_megabits_per_second_;
+    int64 microseconds = static_cast<int64>(seconds * 1E6);
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&Buffer::ProcessBuffer, weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMicroseconds(microseconds));
+  }
+
+  void ProcessBuffer() {
+    CHECK(!buffer_.empty());
+    pipe_->Send(buffer_.front());
+    buffer_size_ -= buffer_.front()->data.size();
+    buffer_.pop_front();
+    if (!buffer_.empty()) {
+      Schedule();
+    }
+  }
+
+  std::deque<scoped_refptr<Packet> > buffer_;
+  size_t buffer_size_;
+  size_t max_buffer_size_;
+  double max_megabits_per_second_;  // megabits per second
+  base::WeakPtrFactory<Buffer> weak_factory_;
+};
+
+scoped_ptr<PacketPipe> NewBuffer(size_t buffer_size, double bandwidth) {
+  return scoped_ptr<PacketPipe>(new Buffer(buffer_size, bandwidth)).Pass();
+}
+
+class RandomDrop : public PacketPipe {
+ public:
+  RandomDrop(double drop_fraction) : drop_fraction_(drop_fraction) {
+  }
+
+  virtual void Send(scoped_refptr<Packet> packet) OVERRIDE {
+    if (base::RandDouble() >= drop_fraction_) {
+      pipe_->Send(packet);
+    }
+  }
+
+ private:
+  double drop_fraction_;
+};
+
+scoped_ptr<PacketPipe> NewRandomDrop(double drop_fraction) {
+  return scoped_ptr<PacketPipe>(new RandomDrop(drop_fraction)).Pass();
+}
+
+class SimpleDelayBase : public PacketPipe {
+ public:
+  SimpleDelayBase() : weak_factory_(this) {
+  }
+  virtual ~SimpleDelayBase() {}
+
+  virtual void Send(scoped_refptr<Packet> packet) OVERRIDE {
+    double seconds = GetDelay();
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&SimpleDelayBase::SendInternal,
+                   weak_factory_.GetWeakPtr(),
+                   packet),
+        base::TimeDelta::FromMicroseconds(
+            static_cast<int64>(seconds * 1E6)));
+  }
+ protected:
+  virtual double GetDelay() = 0;
+
+ private:
+  virtual void SendInternal(scoped_refptr<Packet> packet) {
+    pipe_->Send(packet);
+  }
+
+  base::WeakPtrFactory<SimpleDelayBase> weak_factory_;
+};
+
+class ConstantDelay : public SimpleDelayBase {
+ public:
+  ConstantDelay(double delay_seconds) : delay_seconds_(delay_seconds) {
+  }
+  virtual double GetDelay() OVERRIDE {
+    return delay_seconds_;
+  }
+
+ private:
+  double delay_seconds_;
+};
+
+scoped_ptr<PacketPipe> NewConstantDelay(double delay_seconds) {
+  return scoped_ptr<PacketPipe>(
+      new ConstantDelay(delay_seconds)).Pass();
+}
+
+class RandomUnsortedDelay : public SimpleDelayBase {
+ public:
+  RandomUnsortedDelay(double random_delay) :
+      random_delay_(random_delay) {
+  }
+
+  virtual double GetDelay() OVERRIDE {
+    return random_delay_ * base::RandDouble();
+  }
+
+ private:
+  double random_delay_;
+};
+
+scoped_ptr<PacketPipe> NewRandomUnsortedDelay(double random_delay) {
+  return scoped_ptr<PacketPipe>(
+      new RandomUnsortedDelay(random_delay)).Pass();
+}
+
+
+class RandomSortedDelay : public PacketPipe {
+ public:
+  RandomSortedDelay(double random_delay,
+                    double extra_delay,
+                    double seconds_between_extra_delay) :
+      random_delay_(random_delay),
+      extra_delay_(extra_delay),
+      seconds_between_extra_delay_(seconds_between_extra_delay),
+      weak_factory_(this) {
+  }
+
+  virtual void Send(scoped_refptr<Packet> packet) OVERRIDE {
+    buffer_.push_back(packet);
+    if (buffer_.size() == 1) {
+      Schedule();
+    }
+  }
+  virtual void InitOnIOThread() OVERRIDE {
+    // As we start the stream, assume that we are in a random
+    // place between two extra delays, thus multiplier = 1.0;
+    ScheduleExtraDelay(1.0);
+  }
+
+ private:
+  void ScheduleExtraDelay(double mult) {
+    double seconds = seconds_between_extra_delay_ * mult * base::RandDouble();
+    int64 microseconds = static_cast<int64>(seconds * 1E6);
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&RandomSortedDelay::CauseExtraDelay,
+                   weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMicroseconds(microseconds));
+  }
+
+  void CauseExtraDelay() {
+    block_until_ = base::TimeTicks::Now() +
+        base::TimeDelta::FromMicroseconds(
+            static_cast<int64>(extra_delay_ * 1E6));
+    // An extra delay just happened, wait up to seconds_between_extra_delay_*2
+    // before scheduling another one to make the average equal to
+    // seconds_between_extra_delay_.
+    ScheduleExtraDelay(2.0);
+  }
+
+  void Schedule() {
+    double seconds = base::RandDouble() * random_delay_;
+    base::TimeDelta block_time = block_until_ - base::TimeTicks::Now();
+    base::TimeDelta delay_time =
+        base::TimeDelta::FromMicroseconds(
+            static_cast<int64>(seconds * 1E6));
+    if (block_time > delay_time) {
+      block_time = delay_time;
+    }
+
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&RandomSortedDelay::ProcessBuffer,
+                   weak_factory_.GetWeakPtr()),
+        delay_time);
+  }
+
+  void ProcessBuffer() {
+    CHECK(!buffer_.empty());
+    pipe_->Send(buffer_.front());
+    buffer_.pop_front();
+    if (!buffer_.empty()) {
+      Schedule();
+    }
+  }
+
+  base::TimeTicks block_until_;
+  std::deque<scoped_refptr<Packet> > buffer_;
+  double random_delay_;
+  double extra_delay_;
+  double seconds_between_extra_delay_;
+  base::WeakPtrFactory<RandomSortedDelay> weak_factory_;
+};
+
+scoped_ptr<PacketPipe> NewRandomSortedDelay(
+    double random_delay,
+    double extra_delay,
+    double seconds_between_extra_delay) {
+  return scoped_ptr<PacketPipe>(
+      new RandomSortedDelay(random_delay,
+                            extra_delay,
+                            seconds_between_extra_delay)).Pass();
+}
+
+class NetworkGlitchPipe : public PacketPipe {
+ public:
+  NetworkGlitchPipe(double average_work_time,
+                    double average_outage_time) :
+      works_(false),
+      max_work_time_(average_work_time * 2),
+      max_outage_time_(average_outage_time * 2),
+      weak_factory_(this) {
+  }
+
+  virtual void InitOnIOThread() OVERRIDE {
+    Flip();
+  }
+
+  virtual void Send(scoped_refptr<Packet> packet) OVERRIDE {
+    if (works_) {
+      pipe_->Send(packet);
+    }
+  }
+
+ private:
+  void Flip() {
+    works_ = !works_;
+    double seconds = base::RandDouble() *
+        (works_ ? max_work_time_ : max_outage_time_);
+    int64 microseconds = static_cast<int64>(seconds * 1E6);
+    base::MessageLoop::current()->PostDelayedTask(
+        FROM_HERE,
+        base::Bind(&NetworkGlitchPipe::Flip,
+                   weak_factory_.GetWeakPtr()),
+        base::TimeDelta::FromMicroseconds(microseconds));
+  }
+
+  bool works_;
+  double max_work_time_;
+  double max_outage_time_;
+  base::WeakPtrFactory<NetworkGlitchPipe> weak_factory_;
+};
+
+scoped_ptr<PacketPipe> NewNetworkGlitchPipe(double average_work_time,
+                                            double average_outage_time) {
+  return scoped_ptr<PacketPipe>(
+      new NetworkGlitchPipe(average_work_time, average_outage_time)).Pass();
+}
+
+class PacketSender : public PacketPipe {
+ public:
+  PacketSender(net::UDPSocket* udp_socket,
+               const net::IPEndPoint* destination) :
+      blocked_(false),
+      udp_socket_(udp_socket),
+      destination_(destination),
+      weak_factory_(this) {
+  }
+  virtual void Send(scoped_refptr<Packet> packet) OVERRIDE {
+    if (blocked_) {
+      LOG(ERROR) << "Cannot write packet right now: blocked";
+      return;
+    }
+
+    VLOG(1) << "Sending packet, len = " << packet->data.size();
+    // We ignore all problems, callbacks and errors.
+    // If it didn't work we just drop the packet at and call it a day.
+    scoped_refptr<net::IOBuffer> buf = new net::WrappedIOBuffer(
+        reinterpret_cast<char*>(&packet->data.front()));
+    int result;
+    if (destination_->address().empty()) {
+      VLOG(1) << "Destination has not been set yet.";
+    } else {
+      VLOG(1) << "Destination:" << destination_->ToString();
+      result = udp_socket_->SendTo(buf,
+                                   static_cast<int>(packet->data.size()),
+                                   *destination_,
+                                   base::Bind(&PacketSender::AllowWrite,
+                                              weak_factory_.GetWeakPtr(),
+                                              buf,
+                                              packet));
+    }
+    if (result == net::ERR_IO_PENDING) {
+      blocked_ = true;
+    } else if (result < 0) {
+      LOG(ERROR) << "Failed to write packet.";
+    }
+  }
+  virtual void AppendToPipe(scoped_ptr<PacketPipe> pipe) OVERRIDE {
+    NOTREACHED();
+  }
+
+ private:
+  void AllowWrite(scoped_refptr<net::IOBuffer> buf,
+                  scoped_refptr<Packet> packet,
+                  int unused_len) {
+    DCHECK(blocked_);
+    blocked_ = false;
+  }
+  bool blocked_;
+  net::UDPSocket* udp_socket_;
+  const net::IPEndPoint* destination_;  // not owned
+  base::WeakPtrFactory<PacketSender> weak_factory_;
+};
+
+namespace {
+void BuildPipe(scoped_ptr<PacketPipe>* pipe, PacketPipe* next) {
+  if (*pipe) {
+    (*pipe)->AppendToPipe(scoped_ptr<PacketPipe>(next).Pass());
+  } else {
+    pipe->reset(next);
+  }
+}
+}  // namespace
+
+scoped_ptr<PacketPipe> WifiNetwork() {
+  // This represents the buffer on the sender.
+  scoped_ptr<PacketPipe> pipe;
+  BuildPipe(&pipe, new Buffer(256 << 10, 5000000));
+  BuildPipe(&pipe, new RandomDrop(0.005));
+  // This represents the buffer on the router.
+  BuildPipe(&pipe, new ConstantDelay(1E-3));
+  BuildPipe(&pipe, new RandomSortedDelay(1E-3, 20E-3, 3));
+  BuildPipe(&pipe, new Buffer(256 << 10, 5000000));
+  BuildPipe(&pipe, new ConstantDelay(1E-3));
+  BuildPipe(&pipe, new RandomSortedDelay(1E-3, 20E-3, 3));
+  BuildPipe(&pipe, new RandomDrop(0.005));
+  // This represents the buffer on the receiving device.
+  BuildPipe(&pipe, new Buffer(256 << 10, 5000000));
+  return pipe.Pass();
+}
+
+scoped_ptr<PacketPipe> EvilNetwork() {
+  // This represents the buffer on the sender.
+  scoped_ptr<PacketPipe> pipe;
+  BuildPipe(&pipe, new Buffer(4 << 10, 2000000));
+  // This represents the buffer on the router.
+  BuildPipe(&pipe, new RandomDrop(0.1));  // 10% packet drop
+  BuildPipe(&pipe, new RandomSortedDelay(20E-3, 60E-3, 1));
+  BuildPipe(&pipe, new Buffer(4 << 10, 1000000));  // 4 kb buf, 1mbit/s
+  BuildPipe(&pipe, new RandomDrop(0.1));  // 10% packet drop
+  BuildPipe(&pipe, new ConstantDelay(1E-3));
+  BuildPipe(&pipe, new NetworkGlitchPipe(2.0, 0.3));
+  BuildPipe(&pipe, new RandomUnsortedDelay(20E-3));
+  // This represents the buffer on the receiving device.
+  BuildPipe(&pipe, new Buffer(4 << 10, 2000000));  // 4 kb buf, 2mbit/s
+  return pipe.Pass();
+}
+
+class UDPProxyImpl : public UDPProxy {
+ public:
+  UDPProxyImpl(const net::IPEndPoint& local_port,
+               const net::IPEndPoint& destination,
+               scoped_ptr<PacketPipe> to_dest_pipe,
+               scoped_ptr<PacketPipe> from_dest_pipe,
+               net::NetLog* net_log) :
+      proxy_thread_("media::cast::test::UdpProxy Thread"),
+      local_port_(local_port),
+      destination_(destination),
+      start_event_(false, false),
+      to_dest_pipe_(to_dest_pipe.Pass()),
+      from_dest_pipe_(to_dest_pipe.Pass()) {
+    proxy_thread_.StartWithOptions(
+        base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+    proxy_thread_.message_loop_proxy()->PostTask(
+        FROM_HERE,
+        base::Bind(&UDPProxyImpl::Start,
+                   base::Unretained(this),
+                   net_log));
+    start_event_.Wait();
+  }
+
+  void Start(net::NetLog* net_log) {
+    socket_.reset(new net::UDPSocket(net::DatagramSocket::DEFAULT_BIND,
+                                     net::RandIntCallback(),
+                                     net_log,
+                                     net::NetLog::Source()));
+    BuildPipe(&to_dest_pipe_, new PacketSender(socket_.get(), &destination_));
+    BuildPipe(&from_dest_pipe_,
+              new PacketSender(socket_.get(), &return_address_));
+    to_dest_pipe_->InitOnIOThread();
+    from_dest_pipe_->InitOnIOThread();
+
+    VLOG(0) << "From:" << local_port_.ToString();
+    VLOG(0) << "To:" << destination_.ToString();
+
+    CHECK_GE(socket_->Bind(local_port_), 0);
+
+    start_event_.Signal();
+    PollRead();
+  }
+
+  virtual ~UDPProxyImpl() {
+    proxy_thread_.Stop();
+  }
+
+
+  void ProcessPacket(scoped_refptr<Packet> packet,
+                     scoped_refptr<net::IOBuffer> recv_buf,
+                     int len) {
+    DCHECK_NE(len, net::ERR_IO_PENDING);
+    VLOG(1) << "Got packet, len = " << len;
+    if (len < 0) {
+      LOG(WARNING) << "Socket read error: " << len;
+      return;
+    }
+    packet->data.resize(len);
+    if (recv_address_ == destination_) {
+      from_dest_pipe_->Send(packet);
+    } else {
+      VLOG(1) << "Return address = " << recv_address_.ToString();
+      return_address_ = recv_address_;
+      to_dest_pipe_->Send(packet);
+    }
+  }
+
+  void ReadCallback(scoped_refptr<Packet> packet,
+                    scoped_refptr<net::IOBuffer> recv_buf,
+                    int len) {
+    ProcessPacket(packet, recv_buf, len);
+    PollRead();
+  }
+
+  void PollRead() {
+    while (true) {
+      scoped_refptr<Packet> packet(new Packet(kMaxPacketSize));
+      scoped_refptr<net::IOBuffer> recv_buf = new net::WrappedIOBuffer(
+          reinterpret_cast<char*>(&packet->data.front()));
+      int len = socket_->RecvFrom(
+          recv_buf,
+          kMaxPacketSize,
+          &recv_address_,
+          base::Bind(&UDPProxyImpl::ReadCallback,
+                     base::Unretained(this),
+                     packet,
+                     recv_buf));
+      if (len == net::ERR_IO_PENDING)
+        break;
+      ProcessPacket(packet, recv_buf, len);
+    }
+  }
+
+ private:
+  net::IPEndPoint local_port_;
+  net::IPEndPoint destination_;
+  net::IPEndPoint recv_address_;
+  net::IPEndPoint return_address_;
+  base::Thread proxy_thread_;
+  scoped_ptr<net::UDPSocket> socket_;
+  scoped_ptr<PacketPipe> to_dest_pipe_;
+  scoped_ptr<PacketPipe> from_dest_pipe_;
+  base::WaitableEvent start_event_;
+};
+
+scoped_ptr<UDPProxy> UDPProxy::Create(
+    const net::IPEndPoint& local_port,
+    const net::IPEndPoint& destination,
+    scoped_ptr<PacketPipe> to_dest_pipe,
+    scoped_ptr<PacketPipe> from_dest_pipe,
+    net::NetLog* net_log) {
+  scoped_ptr<UDPProxy> ret(new UDPProxyImpl(local_port,
+                                            destination,
+                                            to_dest_pipe.Pass(),
+                                            from_dest_pipe.Pass(),
+                                            net_log));
+  return ret.Pass();
+}
+
+}  // namespace test
+}  // namespace cast
+}  // namespace media
diff --git a/media/cast/test/utility/udp_proxy.h b/media/cast/test/utility/udp_proxy.h
new file mode 100644
index 0000000..c66f2e1
--- /dev/null
+++ b/media/cast/test/utility/udp_proxy.h
@@ -0,0 +1,114 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_
+#define MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "net/base/ip_endpoint.h"
+
+namespace net {
+class NetLog;
+};
+
+namespace media {
+namespace cast {
+namespace test {
+
+// A single UDP packet.
+// Technically, our UDP proxy should really chop UDP packets
+// into MTU-sized chunks and then do all the horribly things it
+// does to those chunks, but since cast *should* normally only
+// send packets that are sized below the MTU limit, we should
+// be able to ignore that.
+struct Packet : public base::RefCountedThreadSafe<Packet> {
+  explicit Packet(size_t size);
+  std::vector<unsigned char> data;
+ private:
+  friend class base::RefCountedThreadSafe<Packet>;
+  ~Packet();
+};
+
+class PacketPipe {
+ public:
+  PacketPipe();
+  virtual ~PacketPipe();
+  virtual void Send(scoped_refptr<Packet> packet) = 0;
+  virtual void InitOnIOThread();
+  virtual void AppendToPipe(scoped_ptr<PacketPipe> pipe);
+ protected:
+  scoped_ptr<PacketPipe> pipe_;
+};
+
+// A UDPProxy will set up a UDP socket and bind to |local_port|.
+// Packets send to that port will be forwarded to |destination|.
+// Packets send from |destination| to |local_port| will be returned
+// to whoever sent a packet to |local_port| last. (Not counting packets
+// from |destination|.) The UDPProxy will run a separate thread to
+// do the forwarding of packets, and will keep doing so until destroyed.
+// You can insert delays and packet drops by supplying a PacketPipe.
+// The PacketPipes may also be NULL if you just want to forward packets.
+class UDPProxy {
+ public:
+  virtual ~UDPProxy() {}
+  static scoped_ptr<UDPProxy> Create(const net::IPEndPoint& local_port,
+                                     const net::IPEndPoint& destination,
+                                     scoped_ptr<PacketPipe> to_dest_pipe,
+                                     scoped_ptr<PacketPipe> from_dest_pipe,
+                                     net::NetLog* net_log);
+};
+
+// The following functions create PacketPipes which can be linked
+// together (with AppendToPipe) and passed into UdpProxy::Create below.
+
+// This PacketPipe emulates a buffer of a given size. Limits our output
+// from the buffer at a rate given by |bandwidth| (in megabits per second).
+// Packets entering the buffer will be dropped if there is not enough
+// room for them.
+scoped_ptr<PacketPipe> NewBuffer(size_t buffer_size, double bandwidth);
+
+// Randomly drops |drop_fraction|*100% of packets.
+scoped_ptr<PacketPipe> NewRandomDrop(double drop_fraction);
+
+// Delays each packet by |delay_seconds|.
+scoped_ptr<PacketPipe> NewConstantDelay(double delay_seconds);
+
+// Delays packets by a random amount between zero and |delay|.
+// This PacketPipe can reorder packets.
+scoped_ptr<PacketPipe> NewRandomUnsortedDelay(double delay);
+
+// This PacketPipe inserts a random delay between each packet.
+// This PacketPipe cannot re-order packets. The delay between each
+// packet is asically |min_delay| + random( |random_delay| )
+// However, every now and then a delay of |big_delay| will be
+// inserted (roughly every |seconds_between_big_delay| seconds).
+scoped_ptr<PacketPipe> NewRandomSortedDelay(double random_delay,
+                                            double big_delay,
+                                            double seconds_between_big_delay);
+
+// This PacketPipe emulates network outages. It basically waits
+// for 0-2*|average_work_time| seconds, then kills the network for
+// 0-|2*average_outage_time| seconds. Then it starts over again.
+scoped_ptr<PacketPipe> NewNetworkGlitchPipe(double average_work_time,
+                                            double average_outage_time);
+
+
+// This method builds a stack of PacketPipes to emulate a reasonably
+// good wifi network. ~5mbit, 1% packet loss, ~3ms latency.
+scoped_ptr<PacketPipe> WifiNetwork();
+
+// This method builds a stack of PacketPipes to emulate a crappy wifi network.
+// ~1mbit, 20% packet loss, ~40ms latency and packets can get reordered.
+scoped_ptr<PacketPipe> EvilNetwork();
+
+
+}  // namespace test
+}  // namespace cast
+}  // namespace media
+
+#endif  // MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_
diff --git a/media/cast/test/utility/udp_proxy_main.cc b/media/cast/test/utility/udp_proxy_main.cc
new file mode 100644
index 0000000..4e196d7
--- /dev/null
+++ b/media/cast/test/utility/udp_proxy_main.cc
@@ -0,0 +1,63 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "media/cast/test/utility/udp_proxy.h"
+
+int main(int argc, char** argv) {
+  if (argc < 5) {
+    fprintf(stderr,
+            "Usage: udp_proxy <localport> <remotehost> <remoteport> <type>\n",
+            "Where type is one of: perfect, wifi, evil\n");
+    exit(1);
+  }
+
+  base::AtExitManager exit_manager;
+  CommandLine::Init(argc, argv);
+  InitLogging(logging::LoggingSettings());
+
+  int local_port = atoi(argv[1]);
+  int remote_port = atoi(argv[3]);
+  net::IPAddressNumber remote_ip_number;
+  net::IPAddressNumber local_ip_number;
+
+  CHECK(net::ParseIPLiteralToNumber(argv[2], &remote_ip_number));
+  CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &local_ip_number));
+  net::IPEndPoint remote_endpoint(remote_ip_number, remote_port);
+  net::IPEndPoint local_endpoint(local_ip_number, local_port);
+
+  scoped_ptr<media::cast::test::PacketPipe> in_pipe, out_pipe;
+  std::string network_type = argv[4];
+  if (network_type == "perfect") {
+    // No action needed.
+  } else if (network_type == "wifi") {
+    in_pipe = media::cast::test::WifiNetwork().Pass();
+    out_pipe = media::cast::test::WifiNetwork().Pass();
+  } else if (network_type == "evil") {
+    in_pipe = media::cast::test::EvilNetwork().Pass();
+    out_pipe = media::cast::test::EvilNetwork().Pass();
+  } else {
+    fprintf(stderr, "Unknown network type.\n");
+    exit(1);
+  }
+
+  printf("Press Ctrl-C when done.\n");
+  scoped_ptr<media::cast::test::UDPProxy> proxy(
+      media::cast::test::UDPProxy::Create(local_endpoint,
+                                          remote_endpoint,
+                                          in_pipe.Pass(),
+                                          out_pipe.Pass(),
+                                          NULL));
+  while (true) {
+    sleep(1000);
+  }
+  return 1;
+}
diff --git a/media/cast/test/utility/utility.gyp b/media/cast/test/utility/utility.gyp
index 035ce2c..698579c 100644
--- a/media/cast/test/utility/utility.gyp
+++ b/media/cast/test/utility/utility.gyp
@@ -36,6 +36,8 @@
         'standalone_cast_environment.h',
         'video_utility.cc',
         'video_utility.h',
+        'udp_proxy.cc',
+        'udp_proxy.h',
       ], # source
     },
     {
@@ -68,5 +70,19 @@
         '<(DEPTH)/media/cast/test/utility/generate_timecode_audio.cc',
       ],
     },
+    {
+      'target_name': 'udp_proxy',
+      'type': 'executable',
+      'include_dirs': [
+        '<(DEPTH)/',
+      ],
+      'dependencies': [
+        '<(DEPTH)/media/media.gyp:media',
+        '<(DEPTH)/media/cast/test/utility/utility.gyp:cast_test_utility',
+      ],
+      'sources': [
+        '<(DEPTH)/media/cast/test/utility/udp_proxy_main.cc',
+      ],
+    },
   ],
 }
diff --git a/media/cast/transport/cast_transport.gyp b/media/cast/transport/cast_transport.gyp
index 9809db3..434658e 100644
--- a/media/cast/transport/cast_transport.gyp
+++ b/media/cast/transport/cast_transport.gyp
@@ -18,7 +18,7 @@
         '<(DEPTH)/base/base.gyp:base',
         '<(DEPTH)/media/cast/logging/logging.gyp:cast_common_logging',
         '<(DEPTH)/net/net.gyp:net',
-        'utility/utility.gypi:transport_utility',
+        'utility/utility.gyp:transport_utility',
       ],
       'sources': [
         'cast_transport_config.cc',
diff --git a/media/cast/transport/cast_transport_sender.h b/media/cast/transport/cast_transport_sender.h
index dda12cc..79abce6 100644
--- a/media/cast/transport/cast_transport_sender.h
+++ b/media/cast/transport/cast_transport_sender.h
@@ -60,7 +60,6 @@
       net::NetLog* net_log,
       base::TickClock* clock,
       const net::IPEndPoint& remote_end_point,
-      const CastLoggingConfig& logging_config,
       const CastTransportStatusCallback& status_callback,
       const BulkRawEventsCallback& raw_events_callback,
       base::TimeDelta raw_events_callback_interval,
diff --git a/media/cast/transport/cast_transport_sender_impl.cc b/media/cast/transport/cast_transport_sender_impl.cc
index 1157fff..ba97a96 100644
--- a/media/cast/transport/cast_transport_sender_impl.cc
+++ b/media/cast/transport/cast_transport_sender_impl.cc
@@ -16,7 +16,6 @@
     net::NetLog* net_log,
     base::TickClock* clock,
     const net::IPEndPoint& remote_end_point,
-    const CastLoggingConfig& logging_config,
     const CastTransportStatusCallback& status_callback,
     const BulkRawEventsCallback& raw_events_callback,
     base::TimeDelta raw_events_callback_interval,
@@ -25,7 +24,6 @@
       new CastTransportSenderImpl(net_log,
                                   clock,
                                   remote_end_point,
-                                  logging_config,
                                   status_callback,
                                   raw_events_callback,
                                   raw_events_callback_interval,
@@ -37,7 +35,6 @@
     net::NetLog* net_log,
     base::TickClock* clock,
     const net::IPEndPoint& remote_end_point,
-    const CastLoggingConfig& logging_config,
     const CastTransportStatusCallback& status_callback,
     const BulkRawEventsCallback& raw_events_callback,
     base::TimeDelta raw_events_callback_interval,
@@ -52,7 +49,7 @@
                                                        net::IPEndPoint(),
                                                        remote_end_point,
                                                        status_callback)),
-      logging_(logging_config),
+      logging_(),
       pacer_(clock,
              &logging_,
              external_transport ? external_transport : transport_.get(),
@@ -60,7 +57,6 @@
       rtcp_builder_(&pacer_),
       raw_events_callback_(raw_events_callback) {
   if (!raw_events_callback_.is_null()) {
-    DCHECK(logging_config.enable_raw_data_collection);
     DCHECK(raw_events_callback_interval > base::TimeDelta());
     event_subscriber_.reset(new SimpleEventSubscriber);
     logging_.AddRawEventSubscriber(event_subscriber_.get());
diff --git a/media/cast/transport/cast_transport_sender_impl.h b/media/cast/transport/cast_transport_sender_impl.h
index c8ead5e..dd81217 100644
--- a/media/cast/transport/cast_transport_sender_impl.h
+++ b/media/cast/transport/cast_transport_sender_impl.h
@@ -38,7 +38,6 @@
       net::NetLog* net_log,
       base::TickClock* clock,
       const net::IPEndPoint& remote_end_point,
-      const CastLoggingConfig& logging_config,
       const CastTransportStatusCallback& status_callback,
       const BulkRawEventsCallback& raw_events_callback,
       base::TimeDelta raw_events_callback_interval,
@@ -81,9 +80,8 @@
       const CastTransportRtpStatistics& callback) OVERRIDE;
 
  private:
-  // If raw events logging is enabled, this is called periodically.
-  // Calls |raw_events_callback_| with events collected by |event_subscriber_|
-  // since last call.
+  // If |raw_events_callback_| is non-null, calls it with events collected
+  // by |event_subscriber_| since last call.
   void SendRawEvents();
 
   base::TickClock* clock_;  // Not owned by this class.
@@ -97,7 +95,7 @@
   scoped_ptr<TransportAudioSender> audio_sender_;
   scoped_ptr<TransportVideoSender> video_sender_;
 
-  // This is non-null iff raw events logging is enabled.
+  // This is non-null iff |raw_events_callback_| is non-null.
   scoped_ptr<SimpleEventSubscriber> event_subscriber_;
   base::RepeatingTimer<CastTransportSenderImpl> raw_events_timer_;
 
diff --git a/media/cast/transport/cast_transport_sender_impl_unittest.cc b/media/cast/transport/cast_transport_sender_impl_unittest.cc
index 34ebf80..7077bf6 100644
--- a/media/cast/transport/cast_transport_sender_impl_unittest.cc
+++ b/media/cast/transport/cast_transport_sender_impl_unittest.cc
@@ -46,7 +46,6 @@
         new CastTransportSenderImpl(NULL,
                                     &testing_clock_,
                                     net::IPEndPoint(),
-                                    GetDefaultCastSenderLoggingConfig(),
                                     base::Bind(&UpdateCastTransportStatus),
                                     BulkRawEventsCallback(),
                                     base::TimeDelta(),
@@ -60,7 +59,6 @@
         NULL,
         &testing_clock_,
         net::IPEndPoint(),
-        GetLoggingConfigWithRawEventsAndStatsEnabled(),
         base::Bind(&UpdateCastTransportStatus),
         base::Bind(&CastTransportSenderImplTest::LogRawEvents,
                    base::Unretained(this)),
diff --git a/media/cast/transport/pacing/paced_sender_unittest.cc b/media/cast/transport/pacing/paced_sender_unittest.cc
index 97e0a6d..bd558dc 100644
--- a/media/cast/transport/pacing/paced_sender_unittest.cc
+++ b/media/cast/transport/pacing/paced_sender_unittest.cc
@@ -51,7 +51,7 @@
 
 class PacedSenderTest : public ::testing::Test {
  protected:
-  PacedSenderTest() : logging_(GetLoggingConfigWithRawEventsAndStatsEnabled()) {
+  PacedSenderTest() {
     logging_.AddRawEventSubscriber(&subscriber_);
     testing_clock_.Advance(
         base::TimeDelta::FromMilliseconds(kStartMillisecond));
diff --git a/media/cast/transport/rtp_sender/rtp_packetizer/rtp_packetizer_unittest.cc b/media/cast/transport/rtp_sender/rtp_packetizer/rtp_packetizer_unittest.cc
index f5a1d0c..8aa8fff 100644
--- a/media/cast/transport/rtp_sender/rtp_packetizer/rtp_packetizer_unittest.cc
+++ b/media/cast/transport/rtp_sender/rtp_packetizer/rtp_packetizer_unittest.cc
@@ -100,8 +100,7 @@
   RtpPacketizerTest()
       : task_runner_(new test::FakeSingleThreadTaskRunner(&testing_clock_)),
         video_frame_(),
-        packet_storage_(&testing_clock_, kMaxPacketStorageTimeMs),
-        logging_(GetLoggingConfigWithRawEventsAndStatsEnabled()) {
+        packet_storage_(&testing_clock_, kMaxPacketStorageTimeMs) {
     logging_.AddRawEventSubscriber(&subscriber_);
     config_.sequence_number = kSeqNum;
     config_.ssrc = kSsrc;
diff --git a/media/cast/transport/utility/transport_encryption_handler.cc b/media/cast/transport/utility/transport_encryption_handler.cc
index a958b13..89db2cf 100644
--- a/media/cast/transport/utility/transport_encryption_handler.cc
+++ b/media/cast/transport/utility/transport_encryption_handler.cc
@@ -39,7 +39,7 @@
 }
 
 bool TransportEncryptionHandler::Encrypt(uint32 frame_id,
-                                         std::string data,
+                                         const base::StringPiece& data,
                                          std::string* encrypted_data) {
   if (!initialized_)
     return false;
diff --git a/media/cast/transport/utility/transport_encryption_handler.h b/media/cast/transport/utility/transport_encryption_handler.h
index db28084..dd740be 100644
--- a/media/cast/transport/utility/transport_encryption_handler.h
+++ b/media/cast/transport/utility/transport_encryption_handler.h
@@ -29,7 +29,9 @@
 
   bool Initialize(std::string aes_key, std::string aes_iv_mask);
 
-  bool Encrypt(uint32 frame_id, std::string data, std::string* encrypted_data);
+  bool Encrypt(uint32 frame_id,
+               const base::StringPiece& data,
+               std::string* encrypted_data);
 
   bool Decrypt(uint32 frame_id,
                const base::StringPiece& ciphertext,
diff --git a/media/cast/transport/utility/utility.gypi b/media/cast/transport/utility/utility.gyp
similarity index 100%
rename from media/cast/transport/utility/utility.gypi
rename to media/cast/transport/utility/utility.gyp
diff --git a/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc b/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc
index 02b94b3..f25a518 100644
--- a/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc
+++ b/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc
@@ -10,27 +10,31 @@
 #include "base/message_loop/message_loop.h"
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
+#include "media/cast/logging/logging_defines.h"
 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
 #include "ui/gfx/size.h"
 
+namespace {
+
+void LogFrameDecodedEvent(
+    const scoped_refptr<media::cast::CastEnvironment>& cast_environment,
+    base::TimeTicks event_time,
+    media::cast::RtpTimestamp rtp_timestamp,
+    uint32 frame_id) {
+  cast_environment->Logging()->InsertFrameEvent(
+      event_time, media::cast::kVideoFrameDecoded, rtp_timestamp, frame_id);
+}
+
+}  // namespace
+
 namespace media {
 namespace cast {
 
-void LogFrameDecodedEvent(CastEnvironment* const cast_environment,
-                          uint32 rtp_timestamp,
-                          uint32 frame_id) {
-  cast_environment->Logging()->InsertFrameEvent(
-      cast_environment->Clock()->NowTicks(),
-      kVideoFrameDecoded,
-      rtp_timestamp,
-      frame_id);
-}
-
 Vp8Decoder::Vp8Decoder(scoped_refptr<CastEnvironment> cast_environment)
     : cast_environment_(cast_environment) {
   // Make sure that we initialize the decoder from the correct thread.
   cast_environment_->PostTask(
-      CastEnvironment::VIDEO_DECODER,
+      CastEnvironment::VIDEO,
       FROM_HERE,
       base::Bind(&Vp8Decoder::InitDecoder, base::Unretained(this)));
 }
@@ -61,7 +65,7 @@
 bool Vp8Decoder::Decode(const transport::EncodedVideoFrame* encoded_frame,
                         const base::TimeTicks render_time,
                         const VideoFrameDecodedCallback& frame_decoded_cb) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO_DECODER));
+  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO));
   const int frame_id_int = static_cast<int>(encoded_frame->frame_id);
   VLOG(2) << "VP8 decode frame:" << frame_id_int
           << " sized:" << encoded_frame->data.size();
@@ -123,8 +127,9 @@
   // Update logging from the main thread.
   cast_environment_->PostTask(CastEnvironment::MAIN,
                               FROM_HERE,
-                              base::Bind(LogFrameDecodedEvent,
+                              base::Bind(&LogFrameDecodedEvent,
                                          cast_environment_,
+                                         cast_environment_->Clock()->NowTicks(),
                                          encoded_frame->rtp_timestamp,
                                          encoded_frame->frame_id));
 
diff --git a/media/cast/video_receiver/video_decoder_unittest.cc b/media/cast/video_receiver/video_decoder_unittest.cc
index 105d1fe..dd1c0e6 100644
--- a/media/cast/video_receiver/video_decoder_unittest.cc
+++ b/media/cast/video_receiver/video_decoder_unittest.cc
@@ -50,11 +50,7 @@
             new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_),
                                 task_runner_,
                                 task_runner_,
-                                task_runner_,
-                                task_runner_,
-                                task_runner_,
-                                task_runner_,
-                                GetDefaultCastReceiverLoggingConfig())),
+                                task_runner_)),
         test_callback_(new DecodeTestFrameCallback()) {
     // Configure to vp8.
     config_.codec = transport::kVp8;
diff --git a/media/cast/video_receiver/video_receiver.cc b/media/cast/video_receiver/video_receiver.cc
index 5855218..bf8844b 100644
--- a/media/cast/video_receiver/video_receiver.cc
+++ b/media/cast/video_receiver/video_receiver.cc
@@ -28,28 +28,6 @@
 namespace media {
 namespace cast {
 
-// Local implementation of RtpData (defined in rtp_rtcp_defines.h).
-// Used to pass payload data into the video receiver.
-class LocalRtpVideoData : public RtpData {
- public:
-  explicit LocalRtpVideoData(VideoReceiver* video_receiver)
-      : video_receiver_(video_receiver) {}
-
-  virtual ~LocalRtpVideoData() {}
-
-  virtual void OnReceivedPayloadData(const uint8* payload_data,
-                                     size_t payload_size,
-                                     const RtpCastHeader* rtp_header) OVERRIDE {
-    video_receiver_->IncomingParsedRtpPacket(
-        payload_data, payload_size, *rtp_header);
-  }
-
- private:
-  VideoReceiver* video_receiver_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtpVideoData);
-};
-
 // Local implementation of RtpPayloadFeedback (defined in rtp_defines.h)
 // Used to convey cast-specific feedback from receiver to sender.
 // Callback triggered by the Framer (cast message builder).
@@ -68,32 +46,12 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtpVideoFeedback);
 };
 
-// Local implementation of RtpReceiverStatistics (defined by rtcp.h).
-// Used to pass statistics data from the RTP module to the RTCP module.
-class LocalRtpReceiverStatistics : public RtpReceiverStatistics {
- public:
-  explicit LocalRtpReceiverStatistics(RtpReceiver* rtp_receiver)
-      : rtp_receiver_(rtp_receiver) {}
-
-  virtual void GetStatistics(uint8* fraction_lost,
-                             uint32* cumulative_lost,  // 24 bits valid.
-                             uint32* extended_high_sequence_number,
-                             uint32* jitter) OVERRIDE {
-    rtp_receiver_->GetStatistics(
-        fraction_lost, cumulative_lost, extended_high_sequence_number, jitter);
-  }
-
- private:
-  RtpReceiver* rtp_receiver_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(LocalRtpReceiverStatistics);
-};
-
 VideoReceiver::VideoReceiver(scoped_refptr<CastEnvironment> cast_environment,
                              const VideoReceiverConfig& video_config,
                              transport::PacedPacketSender* const packet_sender,
                              const SetTargetDelayCallback& target_delay_cb)
-    : cast_environment_(cast_environment),
+    : RtpReceiver(cast_environment->Clock(), NULL, &video_config),
+      cast_environment_(cast_environment),
       event_subscriber_(kReceiverRtcpEventHistorySize,
                         ReceiverRtcpEventSubscriber::kVideoEventSubscriber),
       codec_(video_config.codec),
@@ -101,14 +59,7 @@
           base::TimeDelta::FromMilliseconds(video_config.rtp_max_delay_ms)),
       frame_delay_(base::TimeDelta::FromMilliseconds(
           1000 / video_config.max_frame_rate)),
-      incoming_payload_callback_(new LocalRtpVideoData(this)),
       incoming_payload_feedback_(new LocalRtpVideoFeedback(this)),
-      rtp_receiver_(cast_environment_->Clock(),
-                    NULL,
-                    &video_config,
-                    incoming_payload_callback_.get()),
-      rtp_video_receiver_statistics_(
-          new LocalRtpReceiverStatistics(&rtp_receiver_)),
       time_offset_counter_(0),
       decryptor_(),
       time_incoming_packet_updated_(false),
@@ -135,7 +86,7 @@
                NULL,
                NULL,
                packet_sender,
-               rtp_video_receiver_statistics_.get(),
+               GetStatistics(),
                video_config.rtcp_mode,
                base::TimeDelta::FromMilliseconds(video_config.rtcp_interval),
                video_config.feedback_ssrc,
@@ -172,7 +123,7 @@
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
 
   // Hand the ownership of the encoded frame to the decode thread.
-  cast_environment_->PostTask(CastEnvironment::VIDEO_DECODER,
+  cast_environment_->PostTask(CastEnvironment::VIDEO,
                               FROM_HERE,
                               base::Bind(&VideoReceiver::DecodeVideoFrameThread,
                                          base::Unretained(this),
@@ -186,7 +137,7 @@
     scoped_ptr<transport::EncodedVideoFrame> encoded_frame,
     const base::TimeTicks render_time,
     const VideoFrameDecodedCallback& frame_decoded_callback) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO_DECODER));
+  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO));
   DCHECK(video_decoder_);
 
   if (!(video_decoder_->DecodeVideoFrame(
@@ -421,13 +372,13 @@
   if (Rtcp::IsRtcpPacket(&packet->front(), packet->size())) {
     rtcp_->IncomingRtcpPacket(&packet->front(), packet->size());
   } else {
-    rtp_receiver_.ReceivedPacket(&packet->front(), packet->size());
+    ReceivedPacket(&packet->front(), packet->size());
   }
 }
 
-void VideoReceiver::IncomingParsedRtpPacket(const uint8* payload_data,
-                                            size_t payload_size,
-                                            const RtpCastHeader& rtp_header) {
+void VideoReceiver::OnReceivedPayloadData(const uint8* payload_data,
+                                          size_t payload_size,
+                                          const RtpCastHeader& rtp_header) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
 
   base::TimeTicks now = cast_environment_->Clock()->NowTicks();
diff --git a/media/cast/video_receiver/video_receiver.gypi b/media/cast/video_receiver/video_receiver.gypi
index ed56ef5..1f7d1ee 100644
--- a/media/cast/video_receiver/video_receiver.gypi
+++ b/media/cast/video_receiver/video_receiver.gypi
@@ -19,7 +19,7 @@
         'video_receiver.cc',
       ], # source
       'dependencies': [
-        '<(DEPTH)/media/cast/transport/utility/utility.gypi:transport_utility',
+        '<(DEPTH)/media/cast/transport/utility/utility.gyp:transport_utility',
         'framer/framer.gyp:cast_framer',
         'video_receiver/codecs/vp8/vp8_decoder.gyp:cast_vp8_decoder',
         'rtp_receiver/rtp_receiver.gyp:cast_rtp_receiver',
diff --git a/media/cast/video_receiver/video_receiver.h b/media/cast/video_receiver/video_receiver.h
index 839f131..b0c636f 100644
--- a/media/cast/video_receiver/video_receiver.h
+++ b/media/cast/video_receiver/video_receiver.h
@@ -26,7 +26,6 @@
 namespace cast {
 
 class Framer;
-class LocalRtpVideoData;
 class LocalRtpVideoFeedback;
 class PeerVideoReceiver;
 class Rtcp;
@@ -39,7 +38,8 @@
 
 // Should only be called from the Main cast thread.
 class VideoReceiver : public base::NonThreadSafe,
-                      public base::SupportsWeakPtr<VideoReceiver> {
+                      public base::SupportsWeakPtr<VideoReceiver>,
+                      public RtpReceiver {
  public:
   VideoReceiver(scoped_refptr<CastEnvironment> cast_environment,
                 const VideoReceiverConfig& video_config,
@@ -57,18 +57,17 @@
   // Insert a RTP packet to the video receiver.
   void IncomingPacket(scoped_ptr<Packet> packet);
 
- protected:
-  void IncomingParsedRtpPacket(const uint8* payload_data,
-                               size_t payload_size,
-                               const RtpCastHeader& rtp_header);
+  virtual void OnReceivedPayloadData(const uint8* payload_data,
+                                     size_t payload_size,
+                                     const RtpCastHeader& rtp_header) OVERRIDE;
 
+ protected:
   void DecodeVideoFrameThread(
       scoped_ptr<transport::EncodedVideoFrame> encoded_frame,
       const base::TimeTicks render_time,
       const VideoFrameDecodedCallback& frame_decoded_callback);
 
  private:
-  friend class LocalRtpVideoData;
   friend class LocalRtpVideoFeedback;
 
   void CastFeedback(const RtcpCastMessage& cast_message);
@@ -118,11 +117,8 @@
   const transport::VideoCodec codec_;
   base::TimeDelta target_delay_delta_;
   base::TimeDelta frame_delay_;
-  scoped_ptr<LocalRtpVideoData> incoming_payload_callback_;
   scoped_ptr<LocalRtpVideoFeedback> incoming_payload_feedback_;
-  RtpReceiver rtp_receiver_;
   scoped_ptr<Rtcp> rtcp_;
-  scoped_ptr<RtpReceiverStatistics> rtp_video_receiver_statistics_;
   base::TimeDelta time_offset_;  // Sender-receiver offset estimation.
   int time_offset_counter_;
   transport::TransportEncryptionHandler decryptor_;
diff --git a/media/cast/video_receiver/video_receiver_unittest.cc b/media/cast/video_receiver/video_receiver_unittest.cc
index 04a7f9d..94a7841 100644
--- a/media/cast/video_receiver/video_receiver_unittest.cc
+++ b/media/cast/video_receiver/video_receiver_unittest.cc
@@ -56,19 +56,6 @@
 };
 }  // namespace
 
-class PeerVideoReceiver : public VideoReceiver {
- public:
-  PeerVideoReceiver(scoped_refptr<CastEnvironment> cast_environment,
-                    const VideoReceiverConfig& video_config,
-                    transport::PacedPacketSender* const packet_sender,
-                    const SetTargetDelayCallback& target_delay_cb)
-      : VideoReceiver(cast_environment,
-                      video_config,
-                      packet_sender,
-                      target_delay_cb) {}
-  using VideoReceiver::IncomingParsedRtpPacket;
-};
-
 class VideoReceiverTest : public ::testing::Test {
  protected:
   VideoReceiverTest() {
@@ -81,12 +68,8 @@
         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
                             task_runner_,
                             task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            GetLoggingConfigWithRawEventsAndStatsEnabled());
-    receiver_.reset(new PeerVideoReceiver(
+                            task_runner_);
+    receiver_.reset(new VideoReceiver(
         cast_environment_, config_, &mock_transport_, target_delay_cb_));
     testing_clock_->Advance(
         base::TimeDelta::FromMilliseconds(kStartMillisecond));
@@ -108,7 +91,7 @@
 
   transport::MockPacedPacketSender mock_transport_;
   VideoReceiverConfig config_;
-  scoped_ptr<PeerVideoReceiver> receiver_;
+  scoped_ptr<VideoReceiver> receiver_;
   std::vector<uint8> payload_;
   RtpCastHeader rtp_header_;
   base::SimpleTestTickClock* testing_clock_;  // Owned by CastEnvironment.
@@ -124,7 +107,7 @@
 TEST_F(VideoReceiverTest, GetOnePacketEncodedframe) {
   EXPECT_CALL(mock_transport_, SendRtcpPacket(_))
       .WillRepeatedly(testing::Return(true));
-  receiver_->IncomingParsedRtpPacket(
+  receiver_->OnReceivedPayloadData(
       payload_.data(), payload_.size(), rtp_header_);
 
   VideoFrameEncodedCallback frame_to_decode_callback = base::Bind(
@@ -142,14 +125,14 @@
   EXPECT_CALL(mock_transport_, SendRtcpPacket(_))
       .WillRepeatedly(testing::Return(true));
   rtp_header_.max_packet_id = 2;
-  receiver_->IncomingParsedRtpPacket(
+  receiver_->OnReceivedPayloadData(
       payload_.data(), payload_.size(), rtp_header_);
   ++rtp_header_.packet_id;
   ++rtp_header_.webrtc.header.sequenceNumber;
-  receiver_->IncomingParsedRtpPacket(
+  receiver_->OnReceivedPayloadData(
       payload_.data(), payload_.size(), rtp_header_);
   ++rtp_header_.packet_id;
-  receiver_->IncomingParsedRtpPacket(
+  receiver_->OnReceivedPayloadData(
       payload_.data(), payload_.size(), rtp_header_);
 
   VideoFrameEncodedCallback frame_to_decode_callback = base::Bind(
@@ -174,7 +157,7 @@
 TEST_F(VideoReceiverTest, GetOnePacketRawframe) {
   EXPECT_CALL(mock_transport_, SendRtcpPacket(_))
       .WillRepeatedly(testing::Return(true));
-  receiver_->IncomingParsedRtpPacket(
+  receiver_->OnReceivedPayloadData(
       payload_.data(), payload_.size(), rtp_header_);
   // Decode error - requires legal input.
   VideoFrameDecodedCallback frame_decoded_callback = base::Bind(
diff --git a/media/cast/video_sender/external_video_encoder.cc b/media/cast/video_sender/external_video_encoder.cc
index 4f97dac..4b59379 100644
--- a/media/cast/video_sender/external_video_encoder.cc
+++ b/media/cast/video_sender/external_video_encoder.cc
@@ -12,22 +12,45 @@
 #include "media/base/video_frame.h"
 #include "media/base/video_util.h"
 #include "media/cast/cast_defines.h"
+#include "media/cast/logging/logging_defines.h"
 #include "media/cast/transport/cast_transport_config.h"
 #include "media/video/video_encode_accelerator.h"
 
+namespace media {
+namespace cast {
+class LocalVideoEncodeAcceleratorClient;
+}  // namespace cast
+}  // namespace media
+
 namespace {
-// We allocate more input buffers than what is asked for by
-// RequireBitstreamBuffers() due to potential threading timing.
-static const int kInputBufferExtraCount = 1;
 static const int kOutputBufferCount = 3;
 
-void LogFrameEncodedEvent(media::cast::CastEnvironment* const cast_environment,
-                          const base::TimeTicks& capture_time) {
+void LogFrameEncodedEvent(
+    const scoped_refptr<media::cast::CastEnvironment>& cast_environment,
+    base::TimeTicks event_time,
+    media::cast::RtpTimestamp rtp_timestamp,
+    uint32 frame_id) {
   cast_environment->Logging()->InsertFrameEvent(
-      cast_environment->Clock()->NowTicks(),
-      media::cast::kVideoFrameEncoded,
-      media::cast::GetVideoRtpTimestamp(capture_time),
-      media::cast::kFrameIdUnknown);
+      event_time, media::cast::kVideoFrameEncoded, rtp_timestamp, frame_id);
+}
+
+// Proxy this call to ExternalVideoEncoder on the cast main thread.
+void ProxyCreateVideoEncodeAccelerator(
+    const scoped_refptr<media::cast::CastEnvironment>& cast_environment,
+    const base::WeakPtr<media::cast::ExternalVideoEncoder>& weak_ptr,
+    const media::cast::CreateVideoEncodeMemoryCallback&
+        create_video_encode_mem_cb,
+    scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
+    scoped_ptr<media::VideoEncodeAccelerator> vea) {
+  cast_environment->PostTask(
+      media::cast::CastEnvironment::MAIN,
+      FROM_HERE,
+      base::Bind(
+          &media::cast::ExternalVideoEncoder::OnCreateVideoEncodeAccelerator,
+          weak_ptr,
+          create_video_encode_mem_cb,
+          encoder_task_runner,
+          base::Passed(&vea)));
 }
 }  // namespace
 
@@ -54,11 +77,14 @@
  public:
   LocalVideoEncodeAcceleratorClient(
       scoped_refptr<CastEnvironment> cast_environment,
-      scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories,
+      scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
+      scoped_ptr<media::VideoEncodeAccelerator> vea,
+      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
       const base::WeakPtr<ExternalVideoEncoder>& weak_owner)
       : cast_environment_(cast_environment),
-        gpu_factories_(gpu_factories),
-        encoder_task_runner_(gpu_factories->GetTaskRunner()),
+        encoder_task_runner_(encoder_task_runner),
+        video_encode_accelerator_(vea.Pass()),
+        create_video_encode_memory_cb_(create_video_encode_mem_cb),
         weak_owner_(weak_owner),
         last_encoded_frame_id_(kStartFrameId) {
     DCHECK(encoder_task_runner_);
@@ -66,16 +92,9 @@
 
   // Initialize the real HW encoder.
   void Initialize(const VideoSenderConfig& video_config) {
-    DCHECK(gpu_factories_);
     DCHECK(encoder_task_runner_);
-
     DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
 
-    video_encode_accelerator_ =
-        gpu_factories_->CreateVideoEncodeAccelerator().Pass();
-    if (!video_encode_accelerator_)
-      return;
-
     VideoCodecProfile output_profile = media::VIDEO_CODEC_PROFILE_UNKNOWN;
     switch (video_config.codec) {
       case transport::kVp8:
@@ -124,55 +143,11 @@
     DCHECK(encoder_task_runner_);
     DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
 
-    if (input_buffers_free_.empty()) {
-      NOTREACHED();
-      VLOG(2) << "EncodeVideoFrame(): drop frame due to no hw buffers";
-      return;
-    }
-    const int index = input_buffers_free_.back();
-    base::SharedMemory* input_buffer = input_buffers_[index];
-
-    // TODO(pwestin): this allocation and copy can be removed once we don't
-    // pass the video frame through liblingle.
-
-    scoped_refptr<media::VideoFrame> frame =
-        media::VideoFrame::WrapExternalPackedMemory(
-            video_frame->format(),
-            video_frame->coded_size(),
-            video_frame->visible_rect(),
-            video_frame->natural_size(),
-            reinterpret_cast<uint8*>(input_buffer->memory()),
-            input_buffer->mapped_size(),
-            input_buffer->handle(),
-            video_frame->GetTimestamp(),
-            base::Bind(&LocalVideoEncodeAcceleratorClient::FinishedWithInBuffer,
-                       this,
-                       index));
-
-    if (!frame) {
-      VLOG(1) << "EncodeVideoFrame(): failed to create frame";
-      NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
-      return;
-    }
-    // Do a stride copy of the input frame to match the input requirements.
-    media::CopyYPlane(video_frame->data(VideoFrame::kYPlane),
-                      video_frame->stride(VideoFrame::kYPlane),
-                      video_frame->natural_size().height(),
-                      frame.get());
-    media::CopyUPlane(video_frame->data(VideoFrame::kUPlane),
-                      video_frame->stride(VideoFrame::kUPlane),
-                      video_frame->natural_size().height(),
-                      frame.get());
-    media::CopyVPlane(video_frame->data(VideoFrame::kVPlane),
-                      video_frame->stride(VideoFrame::kVPlane),
-                      video_frame->natural_size().height(),
-                      frame.get());
-
     encoded_frame_data_storage_.push_back(
         EncodedFrameReturnData(capture_time, frame_encoded_callback));
 
     // BitstreamBufferReady will be called once the encoder is done.
-    video_encode_accelerator_->Encode(frame, key_frame_requested);
+    video_encode_accelerator_->Encode(video_frame, key_frame_requested);
   }
 
  protected:
@@ -180,10 +155,8 @@
     DCHECK(encoder_task_runner_);
     DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
 
-    cast_environment_->PostTask(
-        CastEnvironment::MAIN,
-        FROM_HERE,
-        base::Bind(&ExternalVideoEncoder::EncoderInitialized, weak_owner_));
+    // Wait until shared memory is allocated to indicate that encoder is
+    // initialized.
   }
 
   virtual void NotifyError(VideoEncodeAccelerator::Error error) OVERRIDE {
@@ -208,33 +181,11 @@
     DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
     DCHECK(video_encode_accelerator_);
 
-    for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) {
-      base::SharedMemory* shm =
-          gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize(
-              media::VideoFrame::I420, input_coded_size));
-      if (!shm) {
-        VLOG(1) << "RequireBitstreamBuffers(): failed to create input buffer ";
-        return;
-      }
-      input_buffers_.push_back(shm);
-      input_buffers_free_.push_back(i);
-    }
-
     for (int j = 0; j < kOutputBufferCount; ++j) {
-      base::SharedMemory* shm =
-          gpu_factories_->CreateSharedMemory(output_buffer_size);
-      if (!shm) {
-        VLOG(1) << "RequireBitstreamBuffers(): failed to create input buffer ";
-        return;
-      }
-      output_buffers_.push_back(shm);
-    }
-    // Immediately provide all output buffers to the VEA.
-    for (size_t i = 0; i < output_buffers_.size(); ++i) {
-      video_encode_accelerator_->UseOutputBitstreamBuffer(
-          media::BitstreamBuffer(static_cast<int32>(i),
-                                 output_buffers_[i]->handle(),
-                                 output_buffers_[i]->mapped_size()));
+      create_video_encode_memory_cb_.Run(
+          output_buffer_size,
+          base::Bind(&LocalVideoEncodeAcceleratorClient::OnCreateSharedMemory,
+                     this));
     }
   }
 
@@ -287,9 +238,11 @@
     cast_environment_->PostTask(
         CastEnvironment::MAIN,
         FROM_HERE,
-        base::Bind(LogFrameEncodedEvent,
+        base::Bind(&LogFrameEncodedEvent,
                    cast_environment_,
-                   encoded_frame_data_storage_.front().capture_time));
+                   cast_environment_->Clock()->NowTicks(),
+                   encoded_frame->rtp_timestamp,
+                   encoded_frame->frame_id));
 
     cast_environment_->PostTask(
         CastEnvironment::MAIN,
@@ -309,14 +262,37 @@
   }
 
  private:
-  // Encoder is done with the provided input buffer.
-  void FinishedWithInBuffer(int input_index) {
+  // Note: This method can be called on any thread.
+  void OnCreateSharedMemory(scoped_ptr<base::SharedMemory> memory) {
+    encoder_task_runner_->PostTask(
+        FROM_HERE,
+        base::Bind(&LocalVideoEncodeAcceleratorClient::ReceivedSharedMemory,
+                   this,
+                   base::Passed(&memory)));
+  }
+
+  void ReceivedSharedMemory(scoped_ptr<base::SharedMemory> memory) {
     DCHECK(encoder_task_runner_);
     DCHECK(encoder_task_runner_->RunsTasksOnCurrentThread());
-    DCHECK_GE(input_index, 0);
-    DCHECK_LT(input_index, static_cast<int>(input_buffers_.size()));
-    VLOG(2) << "EncodeFrameFinished(): index=" << input_index;
-    input_buffers_free_.push_back(input_index);
+
+    output_buffers_.push_back(memory.release());
+
+    // Wait until all requested buffers are received.
+    if (output_buffers_.size() < kOutputBufferCount)
+      return;
+
+    // Immediately provide all output buffers to the VEA.
+    for (size_t i = 0; i < output_buffers_.size(); ++i) {
+      video_encode_accelerator_->UseOutputBitstreamBuffer(
+          media::BitstreamBuffer(static_cast<int32>(i),
+                                 output_buffers_[i]->handle(),
+                                 output_buffers_[i]->mapped_size()));
+    }
+
+    cast_environment_->PostTask(
+        CastEnvironment::MAIN,
+        FROM_HERE,
+        base::Bind(&ExternalVideoEncoder::EncoderInitialized, weak_owner_));
   }
 
   friend class base::RefCountedThreadSafe<LocalVideoEncodeAcceleratorClient>;
@@ -324,23 +300,17 @@
   virtual ~LocalVideoEncodeAcceleratorClient() {}
 
   const scoped_refptr<CastEnvironment> cast_environment_;
-  scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories_;
   scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner_;
-  const base::WeakPtr<ExternalVideoEncoder> weak_owner_;
-
   scoped_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_;
+  const CreateVideoEncodeMemoryCallback create_video_encode_memory_cb_;
+  const base::WeakPtr<ExternalVideoEncoder> weak_owner_;
   int max_frame_rate_;
   transport::VideoCodec codec_;
   uint32 last_encoded_frame_id_;
 
-  // Shared memory buffers for input/output with the VideoAccelerator.
-  ScopedVector<base::SharedMemory> input_buffers_;
+  // Shared memory buffers for output with the VideoAccelerator.
   ScopedVector<base::SharedMemory> output_buffers_;
 
-  // Input buffers ready to be filled with input from Encode(). As a LIFO since
-  // we don't care about ordering.
-  std::vector<int> input_buffers_free_;
-
   // FIFO list.
   std::list<EncodedFrameReturnData> encoded_frame_data_storage_;
 
@@ -350,25 +320,21 @@
 ExternalVideoEncoder::ExternalVideoEncoder(
     scoped_refptr<CastEnvironment> cast_environment,
     const VideoSenderConfig& video_config,
-    scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories)
+    const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+    const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb)
     : video_config_(video_config),
       cast_environment_(cast_environment),
       encoder_active_(false),
       key_frame_requested_(false),
       skip_next_frame_(false),
       skip_count_(0),
-      encoder_task_runner_(gpu_factories->GetTaskRunner()),
       weak_factory_(this) {
-  DCHECK(gpu_factories);
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
-  video_accelerator_client_ = new LocalVideoEncodeAcceleratorClient(
-      cast_environment, gpu_factories, weak_factory_.GetWeakPtr());
 
-  encoder_task_runner_->PostTask(
-      FROM_HERE,
-      base::Bind(&LocalVideoEncodeAcceleratorClient::Initialize,
-                 video_accelerator_client_,
-                 video_config));
+  create_vea_cb.Run(base::Bind(&ProxyCreateVideoEncodeAccelerator,
+                               cast_environment,
+                               weak_factory_.GetWeakPtr(),
+                               create_video_encode_mem_cb));
 }
 
 ExternalVideoEncoder::~ExternalVideoEncoder() {
@@ -388,6 +354,26 @@
   encoder_active_ = false;
 }
 
+void ExternalVideoEncoder::OnCreateVideoEncodeAccelerator(
+    const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
+    scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
+    scoped_ptr<media::VideoEncodeAccelerator> vea) {
+  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
+  encoder_task_runner_ = encoder_task_runner;
+
+  video_accelerator_client_ =
+      new LocalVideoEncodeAcceleratorClient(cast_environment_,
+                                            encoder_task_runner,
+                                            vea.Pass(),
+                                            create_video_encode_mem_cb,
+                                            weak_factory_.GetWeakPtr());
+  encoder_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&LocalVideoEncodeAcceleratorClient::Initialize,
+                 video_accelerator_client_,
+                 video_config_));
+}
+
 bool ExternalVideoEncoder::EncodeVideoFrame(
     const scoped_refptr<media::VideoFrame>& video_frame,
     const base::TimeTicks& capture_time,
diff --git a/media/cast/video_sender/external_video_encoder.h b/media/cast/video_sender/external_video_encoder.h
index 6c4c97e..0a71026 100644
--- a/media/cast/video_sender/external_video_encoder.h
+++ b/media/cast/video_sender/external_video_encoder.h
@@ -10,7 +10,7 @@
 #include "media/cast/cast_config.h"
 #include "media/cast/cast_environment.h"
 #include "media/cast/video_sender/video_encoder.h"
-#include "media/filters/gpu_video_accelerator_factories.h"
+#include "media/video/video_encode_accelerator.h"
 
 namespace media {
 class VideoFrame;
@@ -28,7 +28,8 @@
   ExternalVideoEncoder(
       scoped_refptr<CastEnvironment> cast_environment,
       const VideoSenderConfig& video_config,
-      scoped_refptr<GpuVideoAcceleratorFactories> gpu_factories);
+      const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb);
 
   virtual ~ExternalVideoEncoder();
 
@@ -51,6 +52,12 @@
   virtual void LatestFrameIdToReference(uint32 frame_id) OVERRIDE;
   virtual int NumberOfSkippedFrames() const OVERRIDE;
 
+  // Called when a VEA is created.
+  void OnCreateVideoEncodeAccelerator(
+      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
+      scoped_refptr<base::SingleThreadTaskRunner> encoder_task_runner,
+      scoped_ptr<media::VideoEncodeAccelerator> vea);
+
  protected:
   void EncoderInitialized();
   void EncoderError();
diff --git a/media/cast/video_sender/external_video_encoder_unittest.cc b/media/cast/video_sender/external_video_encoder_unittest.cc
index 8f9b2f7..c550fba 100644
--- a/media/cast/video_sender/external_video_encoder_unittest.cc
+++ b/media/cast/video_sender/external_video_encoder_unittest.cc
@@ -10,7 +10,6 @@
 #include "media/base/video_frame.h"
 #include "media/cast/cast_defines.h"
 #include "media/cast/cast_environment.h"
-#include "media/cast/test/fake_gpu_video_accelerator_factories.h"
 #include "media/cast/test/fake_single_thread_task_runner.h"
 #include "media/cast/test/fake_video_encode_accelerator.h"
 #include "media/cast/test/utility/video_utility.h"
@@ -23,6 +22,24 @@
 using testing::_;
 
 namespace {
+
+void CreateVideoEncodeAccelerator(
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+    scoped_ptr<VideoEncodeAccelerator> fake_vea,
+    const ReceiveVideoEncodeAcceleratorCallback& callback) {
+  callback.Run(task_runner, fake_vea.Pass());
+}
+
+void CreateSharedMemory(
+    size_t size, const ReceiveVideoEncodeMemoryCallback& callback) {
+  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+  if (!shm->CreateAndMapAnonymous(size)) {
+    NOTREACHED();
+    return;
+  }
+  callback.Run(shm.Pass());
+}
+
 class TestVideoEncoderCallback
     : public base::RefCountedThreadSafe<TestVideoEncoderCallback> {
  public:
@@ -92,15 +109,16 @@
         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
                             task_runner_,
                             task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            GetDefaultCastSenderLoggingConfig());
-    video_encoder_.reset(new ExternalVideoEncoder(
-        cast_environment_,
-        video_config_,
-        new test::FakeGpuVideoAcceleratorFactories(task_runner_)));
+                            task_runner_);
+    scoped_ptr<VideoEncodeAccelerator> fake_vea(
+        new test::FakeVideoEncodeAccelerator());
+    video_encoder_.reset(
+        new ExternalVideoEncoder(cast_environment_,
+                                 video_config_,
+                                 base::Bind(&CreateVideoEncodeAccelerator,
+                                            task_runner_,
+                                            base::Passed(&fake_vea)),
+                                 base::Bind(&CreateSharedMemory)));
   }
 
   virtual ~ExternalVideoEncoderTest() {}
diff --git a/media/cast/video_sender/video_encoder_impl.cc b/media/cast/video_sender/video_encoder_impl.cc
index bd5281d..854f8c4 100644
--- a/media/cast/video_sender/video_encoder_impl.cc
+++ b/media/cast/video_sender/video_encoder_impl.cc
@@ -23,7 +23,7 @@
 void InitializeVp8EncoderOnEncoderThread(
     const scoped_refptr<CastEnvironment>& environment,
     Vp8Encoder* vp8_encoder) {
-  DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO_ENCODER));
+  DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO));
   vp8_encoder->Initialize();
 }
 
@@ -34,7 +34,7 @@
     const base::TimeTicks& capture_time,
     const VideoEncoderImpl::CodecDynamicConfig& dynamic_config,
     const VideoEncoderImpl::FrameEncodedCallback& frame_encoded_callback) {
-  DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO_ENCODER));
+  DCHECK(environment->CurrentlyOn(CastEnvironment::VIDEO));
   if (dynamic_config.key_frame_requested) {
     vp8_encoder->GenerateKeyFrame();
   }
@@ -74,7 +74,7 @@
       skip_count_(0) {
   if (video_config.codec == transport::kVp8) {
     vp8_encoder_.reset(new Vp8Encoder(video_config, max_unacked_frames));
-    cast_environment_->PostTask(CastEnvironment::VIDEO_ENCODER,
+    cast_environment_->PostTask(CastEnvironment::VIDEO,
                                 FROM_HERE,
                                 base::Bind(&InitializeVp8EncoderOnEncoderThread,
                                            cast_environment,
@@ -92,7 +92,7 @@
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   if (vp8_encoder_) {
     cast_environment_->PostTask(
-        CastEnvironment::VIDEO_ENCODER,
+        CastEnvironment::VIDEO,
         FROM_HERE,
         base::Bind(&base::DeletePointer<Vp8Encoder>, vp8_encoder_.release()));
   }
@@ -117,7 +117,7 @@
       kVideoFrameSentToEncoder,
       GetVideoRtpTimestamp(capture_time),
       kFrameIdUnknown);
-  cast_environment_->PostTask(CastEnvironment::VIDEO_ENCODER,
+  cast_environment_->PostTask(CastEnvironment::VIDEO,
                               FROM_HERE,
                               base::Bind(&EncodeVideoFrameOnEncoderThread,
                                          cast_environment_,
diff --git a/media/cast/video_sender/video_encoder_impl_unittest.cc b/media/cast/video_sender/video_encoder_impl_unittest.cc
index 6efcd6f..b4eed6d 100644
--- a/media/cast/video_sender/video_encoder_impl_unittest.cc
+++ b/media/cast/video_sender/video_encoder_impl_unittest.cc
@@ -94,11 +94,7 @@
         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
                             task_runner_,
                             task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            GetDefaultCastSenderLoggingConfig());
+                            task_runner_);
   }
 
   virtual void TearDown() OVERRIDE {
diff --git a/media/cast/video_sender/video_sender.cc b/media/cast/video_sender/video_sender.cc
index f395527..b35ce55 100644
--- a/media/cast/video_sender/video_sender.cc
+++ b/media/cast/video_sender/video_sender.cc
@@ -47,7 +47,8 @@
 VideoSender::VideoSender(
     scoped_refptr<CastEnvironment> cast_environment,
     const VideoSenderConfig& video_config,
-    const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
+    const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+    const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
     const CastInitializationCallback& cast_initialization_cb,
     transport::CastTransportSender* const transport_sender)
     : rtp_max_delay_(base::TimeDelta::FromMilliseconds(
@@ -77,9 +78,10 @@
   DCHECK_GT(max_unacked_frames_, 0) << "Invalid argument";
 
   if (video_config.use_external_encoder) {
-    CHECK(gpu_factories);
-    video_encoder_.reset(new ExternalVideoEncoder(
-        cast_environment, video_config, gpu_factories));
+    video_encoder_.reset(new ExternalVideoEncoder(cast_environment,
+                                                  video_config,
+                                                  create_vea_cb,
+                                                  create_video_encode_mem_cb));
   } else {
     video_encoder_.reset(new VideoEncoderImpl(
         cast_environment, video_config, max_unacked_frames_));
@@ -179,24 +181,11 @@
   frame_id_to_rtp_timestamp_[frame_id & 0xff] = encoded_frame->rtp_timestamp;
 
   last_sent_frame_id_ = static_cast<int>(encoded_frame->frame_id);
-  cast_environment_->PostTask(
-      CastEnvironment::TRANSPORT,
-      FROM_HERE,
-      base::Bind(&VideoSender::SendEncodedVideoFrameToTransport,
-                 base::Unretained(this),
-                 base::Passed(&encoded_frame),
-                 capture_time));
+  transport_sender_->InsertCodedVideoFrame(encoded_frame.get(), capture_time);
   UpdateFramesInFlight();
   InitializeTimers();
 }
 
-void VideoSender::SendEncodedVideoFrameToTransport(
-    scoped_ptr<transport::EncodedVideoFrame> encoded_frame,
-    const base::TimeTicks& capture_time) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
-  transport_sender_->InsertCodedVideoFrame(encoded_frame.get(), capture_time);
-}
-
 void VideoSender::IncomingRtcpPacket(scoped_ptr<Packet> packet) {
   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::MAIN));
   rtcp_->IncomingRtcpPacket(&packet->front(), packet->size());
@@ -404,13 +393,8 @@
       ResendFrame(static_cast<uint32>(resend_frame));
     }
   } else {
-    cast_environment_->PostTask(
-        CastEnvironment::TRANSPORT,
-        FROM_HERE,
-        base::Bind(&VideoSender::ResendPacketsOnTransportThread,
-                   base::Unretained(this),
-                   cast_feedback.missing_frames_and_packets_));
-
+    transport_sender_->ResendPackets(
+        false, cast_feedback.missing_frames_and_packets_);
     uint32 new_bitrate = 0;
     if (congestion_control_.OnNack(rtt, &new_bitrate)) {
       video_encoder_->SetBitRate(new_bitrate);
@@ -469,19 +453,8 @@
   MissingFramesAndPacketsMap missing_frames_and_packets;
   PacketIdSet missing;
   missing_frames_and_packets.insert(std::make_pair(resend_frame_id, missing));
-  cast_environment_->PostTask(
-      CastEnvironment::TRANSPORT,
-      FROM_HERE,
-      base::Bind(&VideoSender::ResendPacketsOnTransportThread,
-                 base::Unretained(this),
-                 missing_frames_and_packets));
-}
-
-void VideoSender::ResendPacketsOnTransportThread(
-    const transport::MissingFramesAndPacketsMap& missing_packets) {
-  DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::TRANSPORT));
   last_send_time_ = cast_environment_->Clock()->NowTicks();
-  transport_sender_->ResendPackets(false, missing_packets);
+  transport_sender_->ResendPackets(false, missing_frames_and_packets);
 }
 
 }  // namespace cast
diff --git a/media/cast/video_sender/video_sender.h b/media/cast/video_sender/video_sender.h
index 5b436dc..1ef4a73 100644
--- a/media/cast/video_sender/video_sender.h
+++ b/media/cast/video_sender/video_sender.h
@@ -18,8 +18,6 @@
 #include "media/cast/logging/logging_defines.h"
 #include "media/cast/rtcp/rtcp.h"
 #include "media/cast/rtcp/sender_rtcp_event_subscriber.h"
-#include "media/filters/gpu_video_accelerator_factories.h"
-#include "media/video/video_encode_accelerator.h"
 
 namespace media {
 class VideoFrame;
@@ -44,7 +42,8 @@
  public:
   VideoSender(scoped_refptr<CastEnvironment> cast_environment,
               const VideoSenderConfig& video_config,
-              const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
+              const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+              const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
               const CastInitializationCallback& cast_initialization_cb,
               transport::CastTransportSender* const transport_sender);
 
@@ -101,15 +100,8 @@
       scoped_ptr<transport::EncodedVideoFrame> encoded_frame,
       const base::TimeTicks& capture_time);
 
-  void SendEncodedVideoFrameToTransport(
-      scoped_ptr<transport::EncodedVideoFrame> encoded_frame,
-      const base::TimeTicks& capture_time);
-
   void InitializeTimers();
 
-  void ResendPacketsOnTransportThread(
-      const transport::MissingFramesAndPacketsMap& missing_packets);
-
   base::TimeDelta rtp_max_delay_;
   const int max_frame_rate_;
 
diff --git a/media/cast/video_sender/video_sender_unittest.cc b/media/cast/video_sender/video_sender_unittest.cc
index 8847013..1eafe40 100644
--- a/media/cast/video_sender/video_sender_unittest.cc
+++ b/media/cast/video_sender/video_sender_unittest.cc
@@ -10,8 +10,9 @@
 #include "media/base/video_frame.h"
 #include "media/cast/cast_environment.h"
 #include "media/cast/logging/simple_event_subscriber.h"
-#include "media/cast/test/fake_gpu_video_accelerator_factories.h"
 #include "media/cast/test/fake_single_thread_task_runner.h"
+#include "media/cast/test/fake_video_encode_accelerator.h"
+#include "media/cast/test/utility/default_config.h"
 #include "media/cast/test/utility/video_utility.h"
 #include "media/cast/transport/cast_transport_config.h"
 #include "media/cast/transport/cast_transport_sender_impl.h"
@@ -32,6 +33,23 @@
 using testing::_;
 using testing::AtLeast;
 
+void CreateVideoEncodeAccelerator(
+    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+    scoped_ptr<VideoEncodeAccelerator> fake_vea,
+    const ReceiveVideoEncodeAcceleratorCallback& callback) {
+  callback.Run(task_runner, fake_vea.Pass());
+}
+
+void CreateSharedMemory(
+    size_t size, const ReceiveVideoEncodeMemoryCallback& callback) {
+  scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+  if (!shm->CreateAndMapAnonymous(size)) {
+    NOTREACHED();
+    return;
+  }
+  callback.Run(shm.Pass());
+}
+
 class TestPacketSender : public transport::PacketSender {
  public:
   TestPacketSender() : number_of_rtp_packets_(0), number_of_rtcp_packets_(0) {}
@@ -62,12 +80,14 @@
   PeerVideoSender(
       scoped_refptr<CastEnvironment> cast_environment,
       const VideoSenderConfig& video_config,
-      const scoped_refptr<GpuVideoAcceleratorFactories>& gpu_factories,
+      const CreateVideoEncodeAcceleratorCallback& create_vea_cb,
+      const CreateVideoEncodeMemoryCallback& create_video_encode_mem_cb,
       const CastInitializationCallback& cast_initialization_cb,
       transport::CastTransportSender* const transport_sender)
       : VideoSender(cast_environment,
                     video_config,
-                    gpu_factories,
+                    create_vea_cb,
+                    create_video_encode_mem_cb,
                     cast_initialization_cb,
                     transport_sender) {}
   using VideoSender::OnReceivedCastFeedback;
@@ -81,24 +101,17 @@
     testing_clock_->Advance(
         base::TimeDelta::FromMilliseconds(kStartMillisecond));
     task_runner_ = new test::FakeSingleThreadTaskRunner(testing_clock_);
-    CastLoggingConfig logging_config =
-        GetLoggingConfigWithRawEventsAndStatsEnabled();
     cast_environment_ =
         new CastEnvironment(scoped_ptr<base::TickClock>(testing_clock_).Pass(),
                             task_runner_,
                             task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            task_runner_,
-                            logging_config);
+                            task_runner_);
     transport::CastTransportVideoConfig transport_config;
     net::IPEndPoint dummy_endpoint;
     transport_sender_.reset(new transport::CastTransportSenderImpl(
         NULL,
         testing_clock_,
         dummy_endpoint,
-        logging_config,
         base::Bind(&UpdateCastTransportStatus),
         transport::BulkRawEventsCallback(),
         base::TimeDelta(),
@@ -137,18 +150,24 @@
     video_config.codec = transport::kVp8;
 
     if (external) {
-      video_sender_.reset(new PeerVideoSender(
-          cast_environment_,
-          video_config,
-          new test::FakeGpuVideoAcceleratorFactories(task_runner_),
-          base::Bind(&VideoSenderTest::InitializationResult,
-                     base::Unretained(this)),
-          transport_sender_.get()));
+      scoped_ptr<VideoEncodeAccelerator> fake_vea(
+          new test::FakeVideoEncodeAccelerator());
+      video_sender_.reset(
+          new PeerVideoSender(cast_environment_,
+                              video_config,
+                              base::Bind(&CreateVideoEncodeAccelerator,
+                                         task_runner_,
+                                         base::Passed(&fake_vea)),
+                              base::Bind(&CreateSharedMemory),
+                              base::Bind(&VideoSenderTest::InitializationResult,
+                                         base::Unretained(this)),
+                              transport_sender_.get()));
     } else {
       video_sender_.reset(
           new PeerVideoSender(cast_environment_,
                               video_config,
-                              NULL,
+                              CreateDefaultVideoEncodeAcceleratorCallback(),
+                              CreateDefaultVideoEncodeMemoryCallback(),
                               base::Bind(&VideoSenderTest::InitializationResult,
                                          base::Unretained(this)),
                               transport_sender_.get()));
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc
index 05dcd17..344e265 100644
--- a/media/ffmpeg/ffmpeg_common.cc
+++ b/media/ffmpeg/ffmpeg_common.cc
@@ -404,6 +404,11 @@
     coded_size = natural_size;
   }
 
+  // Pad out |coded_size| for subsampled YUV formats.
+  coded_size.set_width((coded_size.width() + 1) / 2 * 2);
+  if (format != VideoFrame::YV16)
+    coded_size.set_height((coded_size.height() + 1) / 2 * 2);
+
   bool is_encrypted = false;
   AVDictionaryEntry* key = av_dict_get(stream->metadata, "enc_key_id", NULL, 0);
   if (key)
diff --git a/media/filters/audio_renderer_algorithm_unittest.cc b/media/filters/audio_renderer_algorithm_unittest.cc
index bde07a2..13fa28b 100644
--- a/media/filters/audio_renderer_algorithm_unittest.cc
+++ b/media/filters/audio_renderer_algorithm_unittest.cc
@@ -105,34 +105,40 @@
     while (!algorithm_.IsQueueFull()) {
       switch (sample_format_) {
         case kSampleFormatU8:
-          buffer = MakeAudioBuffer<uint8>(sample_format_,
-                                          channel_layout_,
-                                          samples_per_second_,
-                                          1,
-                                          1,
-                                          kFrameSize,
-                                          kNoTimestamp(),
-                                          kNoTimestamp());
+          buffer = MakeAudioBuffer<uint8>(
+              sample_format_,
+              channel_layout_,
+              ChannelLayoutToChannelCount(channel_layout_),
+              samples_per_second_,
+              1,
+              1,
+              kFrameSize,
+              kNoTimestamp(),
+              kNoTimestamp());
           break;
         case kSampleFormatS16:
-          buffer = MakeAudioBuffer<int16>(sample_format_,
-                                          channel_layout_,
-                                          samples_per_second_,
-                                          1,
-                                          1,
-                                          kFrameSize,
-                                          kNoTimestamp(),
-                                          kNoTimestamp());
+          buffer = MakeAudioBuffer<int16>(
+              sample_format_,
+              channel_layout_,
+              ChannelLayoutToChannelCount(channel_layout_),
+              samples_per_second_,
+              1,
+              1,
+              kFrameSize,
+              kNoTimestamp(),
+              kNoTimestamp());
           break;
         case kSampleFormatS32:
-          buffer = MakeAudioBuffer<int32>(sample_format_,
-                                          channel_layout_,
-                                          samples_per_second_,
-                                          1,
-                                          1,
-                                          kFrameSize,
-                                          kNoTimestamp(),
-                                          kNoTimestamp());
+          buffer = MakeAudioBuffer<int32>(
+              sample_format_,
+              channel_layout_,
+              ChannelLayoutToChannelCount(channel_layout_),
+              samples_per_second_,
+              1,
+              1,
+              kFrameSize,
+              kNoTimestamp(),
+              kNoTimestamp());
           break;
         default:
           NOTREACHED() << "Unrecognized format " << sample_format_;
@@ -232,7 +238,7 @@
 
   void WsolaTest(float playback_rate) {
     const int kSampleRateHz = 48000;
-    const media::ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
+    const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
     const int kBytesPerSample = 2;
     const int kNumFrames = kSampleRateHz / 100;  // 10 milliseconds.
 
@@ -252,6 +258,7 @@
     scoped_refptr<AudioBuffer> input =
         AudioBuffer::CreateBuffer(kSampleFormatPlanarF32,
                                   kChannelLayout,
+                                  channels_,
                                   kSampleRateHz,
                                   kPulseWidthSamples);
 
diff --git a/media/filters/audio_renderer_impl.cc b/media/filters/audio_renderer_impl.cc
index 2dab601..acb43f7 100644
--- a/media/filters/audio_renderer_impl.cc
+++ b/media/filters/audio_renderer_impl.cc
@@ -15,6 +15,8 @@
 #include "base/metrics/histogram.h"
 #include "base/single_thread_task_runner.h"
 #include "media/base/audio_buffer.h"
+#include "media/base/audio_buffer_converter.h"
+#include "media/base/audio_hardware_config.h"
 #include "media/base/audio_splicer.h"
 #include "media/base/bind_to_current_loop.h"
 #include "media/base/demuxer_stream.h"
@@ -41,12 +43,14 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     media::AudioRendererSink* sink,
     ScopedVector<AudioDecoder> decoders,
-    const SetDecryptorReadyCB& set_decryptor_ready_cb)
+    const SetDecryptorReadyCB& set_decryptor_ready_cb,
+    AudioHardwareConfig* hardware_config)
     : task_runner_(task_runner),
       sink_(sink),
       audio_buffer_stream_(task_runner,
                            decoders.Pass(),
                            set_decryptor_ready_cb),
+      hardware_config_(hardware_config),
       now_cb_(base::Bind(&base::TimeTicks::Now)),
       state_(kUninitialized),
       sink_playing_(false),
@@ -57,7 +61,12 @@
       current_time_(kNoTimestamp()),
       underflow_disabled_(false),
       preroll_aborted_(false),
-      weak_factory_(this) {}
+      weak_factory_(this) {
+  audio_buffer_stream_.set_splice_observer(base::Bind(
+      &AudioRendererImpl::OnNewSpliceBuffer, weak_factory_.GetWeakPtr()));
+  audio_buffer_stream_.set_config_change_observer(base::Bind(
+      &AudioRendererImpl::OnConfigChange, weak_factory_.GetWeakPtr()));
+}
 
 AudioRendererImpl::~AudioRendererImpl() {
   // Stop() should have been called and |algorithm_| should have been destroyed.
@@ -168,6 +177,8 @@
 
     earliest_end_time_ = now_cb_.Run();
     splicer_->Reset();
+    if (buffer_converter_)
+      buffer_converter_->Reset();
     algorithm_->FlushBuffers();
   }
   base::ResetAndReturn(&flush_cb_).Run();
@@ -250,6 +261,26 @@
   disabled_cb_ = disabled_cb;
   error_cb_ = error_cb;
 
+  expecting_config_changes_ = stream->SupportsConfigChanges();
+  if (!expecting_config_changes_) {
+    // The actual buffer size is controlled via the size of the AudioBus
+    // provided to Render(), so just choose something reasonable here for looks.
+    int buffer_size = stream->audio_decoder_config().samples_per_second() / 100;
+    audio_parameters_.Reset(
+        AudioParameters::AUDIO_PCM_LOW_LATENCY,
+        stream->audio_decoder_config().channel_layout(),
+        ChannelLayoutToChannelCount(
+            stream->audio_decoder_config().channel_layout()),
+        0,
+        stream->audio_decoder_config().samples_per_second(),
+        stream->audio_decoder_config().bits_per_channel(),
+        buffer_size);
+    buffer_converter_.reset();
+  } else {
+    // TODO(rileya): Support hardware config changes
+    audio_parameters_ = hardware_config_->GetOutputConfig();
+  }
+
   audio_buffer_stream_.Initialize(
       stream,
       statistics_cb,
@@ -273,27 +304,15 @@
     return;
   }
 
-  int sample_rate = audio_buffer_stream_.decoder()->samples_per_second();
-
-  // The actual buffer size is controlled via the size of the AudioBus
-  // provided to Render(), so just choose something reasonable here for looks.
-  int buffer_size = audio_buffer_stream_.decoder()->samples_per_second() / 100;
-
-  // TODO(rileya): Remove the channel_layout/bits_per_channel/samples_per_second
-  // getters from AudioDecoder, and adjust this accordingly.
-  audio_parameters_ =
-      AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
-                      audio_buffer_stream_.decoder()->channel_layout(),
-                      sample_rate,
-                      audio_buffer_stream_.decoder()->bits_per_channel(),
-                      buffer_size);
   if (!audio_parameters_.IsValid()) {
     ChangeState_Locked(kUninitialized);
     base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
     return;
   }
 
-  splicer_.reset(new AudioSplicer(sample_rate));
+  if (expecting_config_changes_)
+    buffer_converter_.reset(new AudioBufferConverter(audio_parameters_));
+  splicer_.reset(new AudioSplicer(audio_parameters_.sample_rate()));
 
   // We're all good! Continue initializing the rest of the audio renderer
   // based on the decoder format.
@@ -373,9 +392,20 @@
     return;
   }
 
-  if (!splicer_->AddInput(buffer)) {
-    HandleAbortedReadOrDecodeError(true);
-    return;
+  if (expecting_config_changes_) {
+    DCHECK(buffer_converter_);
+    buffer_converter_->AddInput(buffer);
+    while (buffer_converter_->HasNextBuffer()) {
+      if (!splicer_->AddInput(buffer_converter_->GetNextBuffer())) {
+        HandleAbortedReadOrDecodeError(true);
+        return;
+      }
+    }
+  } else {
+    if (!splicer_->AddInput(buffer)) {
+      HandleAbortedReadOrDecodeError(true);
+      return;
+    }
   }
 
   if (!splicer_->HasNextBuffer()) {
@@ -711,4 +741,15 @@
   state_ = new_state;
 }
 
+void AudioRendererImpl::OnNewSpliceBuffer(base::TimeDelta splice_timestamp) {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  splicer_->SetSpliceTimestamp(splice_timestamp);
+}
+
+void AudioRendererImpl::OnConfigChange() {
+  DCHECK(task_runner_->BelongsToCurrentThread());
+  DCHECK(expecting_config_changes_);
+  buffer_converter_->ResetTimestampState();
+}
+
 }  // namespace media
diff --git a/media/filters/audio_renderer_impl.h b/media/filters/audio_renderer_impl.h
index 8c0ce80..f6f41f1 100644
--- a/media/filters/audio_renderer_impl.h
+++ b/media/filters/audio_renderer_impl.h
@@ -38,8 +38,10 @@
 namespace media {
 
 class AudioBus;
+class AudioBufferConverter;
 class AudioSplicer;
 class DecryptingDemuxerStream;
+class AudioHardwareConfig;
 
 class MEDIA_EXPORT AudioRendererImpl
     : public AudioRenderer,
@@ -57,7 +59,8 @@
       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
       AudioRendererSink* sink,
       ScopedVector<AudioDecoder> decoders,
-      const SetDecryptorReadyCB& set_decryptor_ready_cb);
+      const SetDecryptorReadyCB& set_decryptor_ready_cb,
+      AudioHardwareConfig* hardware_params);
   virtual ~AudioRendererImpl();
 
   // AudioRenderer implementation.
@@ -179,9 +182,19 @@
   // Called when the |decoder_|.Reset() has completed.
   void ResetDecoderDone();
 
+  // Called by the AudioBufferStream when a splice buffer is demuxed.
+  void OnNewSpliceBuffer(base::TimeDelta);
+
+  // Called by the AudioBufferStream when a config change occurs.
+  void OnConfigChange();
+
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
   scoped_ptr<AudioSplicer> splicer_;
+  scoped_ptr<AudioBufferConverter> buffer_converter_;
+
+  // Whether or not we expect to handle config changes.
+  bool expecting_config_changes_;
 
   // The sink (destination) for rendered audio. |sink_| must only be accessed
   // on |task_runner_|. |sink_| must never be called under |lock_| or else we
@@ -190,7 +203,10 @@
 
   AudioBufferStream audio_buffer_stream_;
 
-  // AudioParameters constructed during Initialize().
+  // Interface to the hardware audio params.
+  const AudioHardwareConfig* const hardware_config_;
+
+  // Cached copy of hardware params from |hardware_config_|.
   AudioParameters audio_parameters_;
 
   // Callbacks provided during Initialize().
diff --git a/media/filters/audio_renderer_impl_unittest.cc b/media/filters/audio_renderer_impl_unittest.cc
index 965e5cf..7cccdfc 100644
--- a/media/filters/audio_renderer_impl_unittest.cc
+++ b/media/filters/audio_renderer_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/stl_util.h"
 #include "base/strings/stringprintf.h"
 #include "media/base/audio_buffer.h"
+#include "media/base/audio_hardware_config.h"
 #include "media/base/audio_timestamp_helper.h"
 #include "media/base/fake_audio_renderer_sink.h"
 #include "media/base/gmock_callback_support.h"
@@ -33,6 +34,7 @@
 static AudioCodec kCodec = kCodecVorbis;
 static SampleFormat kSampleFormat = kSampleFormatPlanarF32;
 static ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
+static int kChannelCount = 2;
 static int kChannels = ChannelLayoutToChannelCount(kChannelLayout);
 static int kSamplesPerSecond = 44100;
 
@@ -51,7 +53,8 @@
  public:
   // Give the decoder some non-garbage media properties.
   AudioRendererImplTest()
-      : needs_stop_(true),
+      : hardware_config_(AudioParameters(), AudioParameters()),
+        needs_stop_(true),
         demuxer_stream_(DemuxerStream::AUDIO),
         decoder_(new MockAudioDecoder()) {
     AudioDecoderConfig audio_config(kCodec,
@@ -73,26 +76,24 @@
     EXPECT_CALL(*decoder_, Stop(_))
         .WillRepeatedly(Invoke(this, &AudioRendererImplTest::StopDecoder));
 
-    // Set up audio properties.
-    EXPECT_CALL(*decoder_, bits_per_channel())
-        .WillRepeatedly(Return(audio_config.bits_per_channel()));
-    EXPECT_CALL(*decoder_, channel_layout())
-        .WillRepeatedly(Return(audio_config.channel_layout()));
-    EXPECT_CALL(*decoder_, samples_per_second())
-        .WillRepeatedly(Return(audio_config.samples_per_second()));
-
     // Mock out demuxer reads
     EXPECT_CALL(demuxer_stream_, Read(_)).WillRepeatedly(
         RunCallback<0>(DemuxerStream::kOk, DecoderBuffer::CreateEOSBuffer()));
-
+    AudioParameters out_params =
+        AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+                        kChannelLayout,
+                        kSamplesPerSecond,
+                        SampleFormatToBytesPerChannel(kSampleFormat) * 8,
+                        512);
+    hardware_config_.UpdateOutputConfig(out_params);
     ScopedVector<AudioDecoder> decoders;
     decoders.push_back(decoder_);
     sink_ = new FakeAudioRendererSink();
-    renderer_.reset(new AudioRendererImpl(
-        message_loop_.message_loop_proxy(),
-        sink_,
-        decoders.Pass(),
-        SetDecryptorReadyCB()));
+    renderer_.reset(new AudioRendererImpl(message_loop_.message_loop_proxy(),
+                                          sink_,
+                                          decoders.Pass(),
+                                          SetDecryptorReadyCB(),
+                                          &hardware_config_));
 
     // Stub out time.
     renderer_->set_now_cb_for_testing(base::Bind(
@@ -113,17 +114,6 @@
         .WillOnce(RunCallback<1>(DECODER_ERROR_NOT_SUPPORTED));
   }
 
-  void ExpectUnsupportedAudioDecoderConfig() {
-    EXPECT_CALL(*decoder_, bits_per_channel())
-        .WillRepeatedly(Return(3));
-    EXPECT_CALL(*decoder_, channel_layout())
-        .WillRepeatedly(Return(CHANNEL_LAYOUT_UNSUPPORTED));
-    EXPECT_CALL(*decoder_, samples_per_second())
-        .WillRepeatedly(Return(0));
-    EXPECT_CALL(*decoder_, Initialize(_, _))
-        .WillOnce(RunCallback<1>(PIPELINE_OK));
-  }
-
   MOCK_METHOD1(OnStatistics, void(const PipelineStatistics&));
   MOCK_METHOD0(OnUnderflow, void());
   MOCK_METHOD0(OnDisabled, void());
@@ -138,8 +128,8 @@
         .WillOnce(RunCallback<1>(PIPELINE_OK));
     InitializeWithStatus(PIPELINE_OK);
 
-    next_timestamp_.reset(
-        new AudioTimestampHelper(decoder_->samples_per_second()));
+    next_timestamp_.reset(new AudioTimestampHelper(
+        hardware_config_.GetOutputConfig().sample_rate()));
   }
 
   void InitializeWithStatus(PipelineStatus expected) {
@@ -308,6 +298,7 @@
     scoped_refptr<AudioBuffer> buffer =
         MakeAudioBuffer<float>(kSampleFormat,
                                kChannelLayout,
+                               kChannelCount,
                                kSamplesPerSecond,
                                kPlayingAudio,
                                0.0f,
@@ -368,7 +359,7 @@
     do {
       TimeDelta audio_delay = TimeDelta::FromMicroseconds(
           total_frames_read * Time::kMicrosecondsPerSecond /
-          static_cast<float>(decoder_->samples_per_second()));
+          static_cast<float>(hardware_config_.GetOutputConfig().sample_rate()));
 
       frames_read = renderer_->Render(
           bus.get(), audio_delay.InMilliseconds());
@@ -460,6 +451,7 @@
   base::MessageLoop message_loop_;
   scoped_ptr<AudioRendererImpl> renderer_;
   scoped_refptr<FakeAudioRendererSink> sink_;
+  AudioHardwareConfig hardware_config_;
 
   // Whether or not the test needs the destructor to call Stop() on
   // |renderer_| at destruction.
@@ -535,11 +527,6 @@
   DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest);
 };
 
-TEST_F(AudioRendererImplTest, Initialize_Failed) {
-  ExpectUnsupportedAudioDecoderConfig();
-  InitializeWithStatus(PIPELINE_ERROR_INITIALIZATION_FAILED);
-}
-
 TEST_F(AudioRendererImplTest, Initialize_Successful) {
   Initialize();
 }
diff --git a/media/filters/chunk_demuxer.cc b/media/filters/chunk_demuxer.cc
index 697396b..1eb22d5 100644
--- a/media/filters/chunk_demuxer.cc
+++ b/media/filters/chunk_demuxer.cc
@@ -702,10 +702,10 @@
   base::ResetAndReturn(&init_cb_).Run(success, duration);
 }
 
-ChunkDemuxerStream::ChunkDemuxerStream(Type type)
+ChunkDemuxerStream::ChunkDemuxerStream(Type type, bool splice_frames_enabled)
     : type_(type),
-      state_(UNINITIALIZED) {
-}
+      state_(UNINITIALIZED),
+      splice_frames_enabled_(splice_frames_enabled) {}
 
 void ChunkDemuxerStream::StartReturningData() {
   DVLOG(1) << "ChunkDemuxerStream::StartReturningData()";
@@ -836,7 +836,8 @@
   base::AutoLock auto_lock(lock_);
   if (!stream_) {
     DCHECK_EQ(state_, UNINITIALIZED);
-    stream_.reset(new SourceBufferStream(config, log_cb));
+    stream_.reset(
+        new SourceBufferStream(config, log_cb, splice_frames_enabled_));
     return true;
   }
 
@@ -851,7 +852,8 @@
 
   if (!stream_) {
     DCHECK_EQ(state_, UNINITIALIZED);
-    stream_.reset(new SourceBufferStream(config, log_cb));
+    stream_.reset(
+        new SourceBufferStream(config, log_cb, splice_frames_enabled_));
     return true;
   }
 
@@ -864,7 +866,7 @@
   base::AutoLock auto_lock(lock_);
   DCHECK(!stream_);
   DCHECK_EQ(state_, UNINITIALIZED);
-  stream_.reset(new SourceBufferStream(config, log_cb));
+  stream_.reset(new SourceBufferStream(config, log_cb, splice_frames_enabled_));
 }
 
 void ChunkDemuxerStream::MarkEndOfStream() {
@@ -903,6 +905,8 @@
   return stream_->GetCurrentVideoDecoderConfig();
 }
 
+bool ChunkDemuxerStream::SupportsConfigChanges() { return true; }
+
 TextTrackConfig ChunkDemuxerStream::text_track_config() {
   CHECK_EQ(type_, TEXT);
   base::AutoLock auto_lock(lock_);
@@ -968,7 +972,8 @@
 
 ChunkDemuxer::ChunkDemuxer(const base::Closure& open_cb,
                            const NeedKeyCB& need_key_cb,
-                           const LogCB& log_cb)
+                           const LogCB& log_cb,
+                           bool splice_frames_enabled)
     : state_(WAITING_FOR_INIT),
       cancel_next_seek_(false),
       host_(NULL),
@@ -977,7 +982,8 @@
       enable_text_(false),
       log_cb_(log_cb),
       duration_(kNoTimestamp()),
-      user_specified_duration_(-1) {
+      user_specified_duration_(-1),
+      splice_frames_enabled_(splice_frames_enabled) {
   DCHECK(!open_cb_.is_null());
   DCHECK(!need_key_cb_.is_null());
 }
@@ -1509,17 +1515,20 @@
     case DemuxerStream::AUDIO:
       if (audio_)
         return NULL;
-      audio_.reset(new ChunkDemuxerStream(DemuxerStream::AUDIO));
+      audio_.reset(
+          new ChunkDemuxerStream(DemuxerStream::AUDIO, splice_frames_enabled_));
       return audio_.get();
       break;
     case DemuxerStream::VIDEO:
       if (video_)
         return NULL;
-      video_.reset(new ChunkDemuxerStream(DemuxerStream::VIDEO));
+      video_.reset(
+          new ChunkDemuxerStream(DemuxerStream::VIDEO, splice_frames_enabled_));
       return video_.get();
       break;
     case DemuxerStream::TEXT: {
-      return new ChunkDemuxerStream(DemuxerStream::TEXT);
+      return new ChunkDemuxerStream(DemuxerStream::TEXT,
+                                    splice_frames_enabled_);
       break;
     }
     case DemuxerStream::UNKNOWN:
diff --git a/media/filters/chunk_demuxer.h b/media/filters/chunk_demuxer.h
index e469aa9..589dbd8 100644
--- a/media/filters/chunk_demuxer.h
+++ b/media/filters/chunk_demuxer.h
@@ -27,7 +27,7 @@
  public:
   typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
 
-  explicit ChunkDemuxerStream(Type type);
+  explicit ChunkDemuxerStream(Type type, bool splice_frames_enabled);
   virtual ~ChunkDemuxerStream();
 
   // ChunkDemuxerStream control methods.
@@ -85,6 +85,7 @@
   virtual void EnableBitstreamConverter() OVERRIDE;
   virtual AudioDecoderConfig audio_decoder_config() OVERRIDE;
   virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
+  virtual bool SupportsConfigChanges() OVERRIDE;
 
   // Returns the text track configuration.  It is an error to call this method
   // if type() != TEXT.
@@ -116,6 +117,7 @@
   mutable base::Lock lock_;
   State state_;
   ReadCB read_cb_;
+  const bool splice_frames_enabled_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(ChunkDemuxerStream);
 };
@@ -138,9 +140,13 @@
   //   otherwise ignore them.
   // |log_cb| Run when parsing error messages need to be logged to the error
   //   console.
+  // |splice_frames_enabled| Indicates that it's okay to generate splice frames
+  //   per the MSE specification.  Renderers must understand DecoderBuffer's
+  //   splice_timestamp() field.
   ChunkDemuxer(const base::Closure& open_cb,
                const NeedKeyCB& need_key_cb,
-               const LogCB& log_cb);
+               const LogCB& log_cb,
+               bool splice_frames_enabled);
   virtual ~ChunkDemuxer();
 
   // Demuxer implementation.
@@ -366,6 +372,9 @@
   std::string source_id_audio_;
   std::string source_id_video_;
 
+  // Indicates that splice frame generation is enabled.
+  const bool splice_frames_enabled_;
+
   DISALLOW_COPY_AND_ASSIGN(ChunkDemuxer);
 };
 
diff --git a/media/filters/chunk_demuxer_unittest.cc b/media/filters/chunk_demuxer_unittest.cc
index 475ac39..8f3be9a 100644
--- a/media/filters/chunk_demuxer_unittest.cc
+++ b/media/filters/chunk_demuxer_unittest.cc
@@ -164,8 +164,8 @@
         base::Bind(&ChunkDemuxerTest::DemuxerOpened, base::Unretained(this));
     Demuxer::NeedKeyCB need_key_cb =
         base::Bind(&ChunkDemuxerTest::DemuxerNeedKey, base::Unretained(this));
-    demuxer_.reset(new ChunkDemuxer(open_cb, need_key_cb,
-                                    base::Bind(&LogFunc)));
+    demuxer_.reset(
+        new ChunkDemuxer(open_cb, need_key_cb, base::Bind(&LogFunc), false));
   }
 
   virtual ~ChunkDemuxerTest() {
@@ -542,14 +542,14 @@
   // bear-640x360.webm VideoDecoderConfig returns 640x360 for its natural_size()
   // The resulting video stream returns data from each file for the following
   // time ranges.
-  // bear-320x240.webm : [0-501)       [801-2737)
+  // bear-320x240.webm : [0-501)       [801-2736)
   // bear-640x360.webm :       [527-793)
   //
   // bear-320x240.webm AudioDecoderConfig returns 3863 for its extra_data_size()
   // bear-640x360.webm AudioDecoderConfig returns 3935 for its extra_data_size()
   // The resulting audio stream returns data from each file for the following
   // time ranges.
-  // bear-320x240.webm : [0-524)       [779-2737)
+  // bear-320x240.webm : [0-524)       [779-2736)
   // bear-640x360.webm :       [527-759)
   bool InitDemuxerWithConfigChangeData() {
     scoped_refptr<DecoderBuffer> bear1 = ReadTestDataFile("bear-320x240.webm");
@@ -565,7 +565,11 @@
 
     // Append the whole bear1 file.
     AppendData(bear1->data(), bear1->data_size());
-    CheckExpectedRanges(kSourceId, "{ [0,2737) }");
+    // Last audio frame has timestamp 2721 and duration 24 (estimated from max
+    // seen so far for audio track).
+    // Last video frame has timestamp 2703 and duration 33 (from TrackEntry
+    // DefaultDuration for video track).
+    CheckExpectedRanges(kSourceId, "{ [0,2736) }");
 
     // Append initialization segment for bear2.
     // Note: Offsets here and below are derived from
@@ -577,13 +581,13 @@
 
     // Append a media segment that goes from [0.527000, 1.014000).
     AppendData(bear2->data() + 55290, 18785);
-    CheckExpectedRanges(kSourceId, "{ [0,1028) [1201,2737) }");
+    CheckExpectedRanges(kSourceId, "{ [0,1027) [1201,2736) }");
 
     // Append initialization segment for bear1 & fill gap with [779-1197)
     // segment.
     AppendData(bear1->data(), 4370);
     AppendData(bear1->data() + 72737, 28183);
-    CheckExpectedRanges(kSourceId, "{ [0,2737) }");
+    CheckExpectedRanges(kSourceId, "{ [0,2736) }");
 
     MarkEndOfStream(PIPELINE_OK);
     return true;
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc
index 682fba5..2863d22 100644
--- a/media/filters/decoder_stream.cc
+++ b/media/filters/decoder_stream.cc
@@ -375,6 +375,11 @@
 
   if (status == DemuxerStream::kConfigChanged) {
     FUNCTION_DVLOG(2) << ": " << "ConfigChanged";
+    DCHECK(stream_->SupportsConfigChanges());
+
+    if (!config_change_observer_cb_.is_null())
+      config_change_observer_cb_.Run();
+
     state_ = STATE_FLUSHING_DECODER;
     if (!reset_cb_.is_null()) {
       AbortRead();
@@ -403,6 +408,11 @@
     return;
   }
 
+  if (!splice_observer_cb_.is_null() && !buffer->end_of_stream() &&
+      buffer->splice_timestamp() != kNoTimestamp()) {
+    splice_observer_cb_.Run(buffer->splice_timestamp());
+  }
+
   DCHECK(status == DemuxerStream::kOk) << status;
   Decode(buffer);
 }
diff --git a/media/filters/decoder_stream.h b/media/filters/decoder_stream.h
index 1b002a6..cc44885 100644
--- a/media/filters/decoder_stream.h
+++ b/media/filters/decoder_stream.h
@@ -91,6 +91,22 @@
   // have been removed from AudioDecoder and plumbed elsewhere.
   Decoder* decoder() { return decoder_.get(); }
 
+  // Allows callers to register for notification of splice buffers from the
+  // demuxer.  I.e., DecoderBuffer::splice_timestamp() is not kNoTimestamp().
+  typedef base::Callback<void(base::TimeDelta)> SpliceObserverCB;
+  void set_splice_observer(const SpliceObserverCB& splice_observer) {
+    splice_observer_cb_ = splice_observer;
+  }
+
+  // Allows callers to register for notification of config changes; this is
+  // called immediately after recieving the 'kConfigChanged' status from the
+  // DemuxerStream, before any action is taken to handle the config change.
+  typedef base::Closure ConfigChangeObserverCB;
+  void set_config_change_observer(
+      const ConfigChangeObserverCB& config_change_observer) {
+    config_change_observer_cb_ = config_change_observer;
+  }
+
  private:
   enum State {
     STATE_UNINITIALIZED,
@@ -166,6 +182,9 @@
   scoped_ptr<Decoder> decoder_;
   scoped_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream_;
 
+  SpliceObserverCB splice_observer_cb_;
+  ConfigChangeObserverCB config_change_observer_cb_;
+
   // NOTE: Weak pointers must be invalidated before all other member variables.
   base::WeakPtrFactory<DecoderStream<StreamType> > weak_factory_;
 
diff --git a/media/filters/decrypting_audio_decoder.cc b/media/filters/decrypting_audio_decoder.cc
index 279e19b..7336f21 100644
--- a/media/filters/decrypting_audio_decoder.cc
+++ b/media/filters/decrypting_audio_decoder.cc
@@ -42,9 +42,6 @@
       set_decryptor_ready_cb_(set_decryptor_ready_cb),
       decryptor_(NULL),
       key_added_while_decode_pending_(false),
-      bits_per_channel_(0),
-      channel_layout_(CHANNEL_LAYOUT_NONE),
-      samples_per_second_(0),
       weak_factory_(this) {}
 
 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config,
@@ -185,21 +182,6 @@
   task_runner_->PostTask(FROM_HERE, closure);
 }
 
-int DecryptingAudioDecoder::bits_per_channel() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return bits_per_channel_;
-}
-
-ChannelLayout DecryptingAudioDecoder::channel_layout() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return channel_layout_;
-}
-
-int DecryptingAudioDecoder::samples_per_second() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return samples_per_second_;
-}
-
 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
   DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
 }
@@ -260,7 +242,8 @@
   }
 
   // Success!
-  UpdateDecoderConfig();
+  timestamp_helper_.reset(
+      new AudioTimestampHelper(config_.samples_per_second()));
 
   decryptor_->RegisterNewKeyCB(
       Decryptor::kAudio,
@@ -380,13 +363,6 @@
   base::ResetAndReturn(&reset_cb_).Run();
 }
 
-void DecryptingAudioDecoder::UpdateDecoderConfig() {
-  bits_per_channel_ = kSupportedBitsPerChannel;
-  channel_layout_ = config_.channel_layout();
-  samples_per_second_ = config_.samples_per_second();
-  timestamp_helper_.reset(new AudioTimestampHelper(samples_per_second_));
-}
-
 void DecryptingAudioDecoder::EnqueueFrames(
     const Decryptor::AudioBuffers& frames) {
   queued_audio_frames_ = frames;
diff --git a/media/filters/decrypting_audio_decoder.h b/media/filters/decrypting_audio_decoder.h
index 8184d42..562faa0 100644
--- a/media/filters/decrypting_audio_decoder.h
+++ b/media/filters/decrypting_audio_decoder.h
@@ -50,9 +50,6 @@
   virtual scoped_refptr<AudioBuffer> GetDecodeOutput() OVERRIDE;
   virtual void Reset(const base::Closure& closure) OVERRIDE;
   virtual void Stop(const base::Closure& closure) OVERRIDE;
-  virtual int bits_per_channel() OVERRIDE;
-  virtual ChannelLayout channel_layout() OVERRIDE;
-  virtual int samples_per_second() OVERRIDE;
 
  private:
   // For a detailed state diagram please see this link: http://goo.gl/8jAok
@@ -93,10 +90,6 @@
   // Resets decoder and calls |reset_cb_|.
   void DoReset();
 
-  // Updates audio configs from |demuxer_stream_| and resets
-  // |output_timestamp_base_| and |total_samples_decoded_|.
-  void UpdateDecoderConfig();
-
   // Sets timestamp and duration for |queued_audio_frames_| to make sure the
   // renderer always receives continuous frames without gaps and overlaps.
   void EnqueueFrames(const Decryptor::AudioBuffers& frames);
@@ -130,11 +123,6 @@
 
   Decryptor::AudioBuffers queued_audio_frames_;
 
-  // Decoded audio format.
-  int bits_per_channel_;
-  ChannelLayout channel_layout_;
-  int samples_per_second_;
-
   scoped_ptr<AudioTimestampHelper> timestamp_helper_;
 
   // NOTE: Weak pointers must be invalidated before all other member variables.
diff --git a/media/filters/decrypting_audio_decoder_unittest.cc b/media/filters/decrypting_audio_decoder_unittest.cc
index a6a8152..c711cbd 100644
--- a/media/filters/decrypting_audio_decoder_unittest.cc
+++ b/media/filters/decrypting_audio_decoder_unittest.cc
@@ -94,7 +94,14 @@
 
   void InitializeAndExpectStatus(const AudioDecoderConfig& config,
                                  PipelineStatus status) {
+    // Initialize data now that the config is known. Since the code uses
+    // invalid values (that CreateEmptyBuffer() doesn't support), tweak them
+    // just for CreateEmptyBuffer().
+    int channels = ChannelLayoutToChannelCount(config.channel_layout());
+    if (channels < 0)
+      channels = 0;
     decoded_frame_ = AudioBuffer::CreateEmptyBuffer(config.channel_layout(),
+                                                    channels,
                                                     kSampleRate,
                                                     kFakeAudioFrameSize,
                                                     kNoTimestamp(),
@@ -118,11 +125,6 @@
                        CHANNEL_LAYOUT_STEREO, kSampleRate, NULL, 0, true, true,
                        base::TimeDelta(), base::TimeDelta());
     InitializeAndExpectStatus(config_, PIPELINE_OK);
-
-    EXPECT_EQ(DecryptingAudioDecoder::kSupportedBitsPerChannel,
-              decoder_->bits_per_channel());
-    EXPECT_EQ(config_.channel_layout(), decoder_->channel_layout());
-    EXPECT_EQ(config_.samples_per_second(), decoder_->samples_per_second());
   }
 
   void Reinitialize() {
@@ -358,12 +360,14 @@
 
   scoped_refptr<AudioBuffer> frame_a = AudioBuffer::CreateEmptyBuffer(
       config_.channel_layout(),
+      ChannelLayoutToChannelCount(config_.channel_layout()),
       kSampleRate,
       kFakeAudioFrameSize,
       kNoTimestamp(),
       kNoTimestamp());
   scoped_refptr<AudioBuffer> frame_b = AudioBuffer::CreateEmptyBuffer(
       config_.channel_layout(),
+      ChannelLayoutToChannelCount(config_.channel_layout()),
       kSampleRate,
       kFakeAudioFrameSize,
       kNoTimestamp(),
@@ -405,10 +409,6 @@
 
   ReinitializeConfigChange(new_config);
   message_loop_.RunUntilIdle();
-
-  EXPECT_EQ(new_config.bits_per_channel(), decoder_->bits_per_channel());
-  EXPECT_EQ(new_config.channel_layout(), decoder_->channel_layout());
-  EXPECT_EQ(new_config.samples_per_second(), decoder_->samples_per_second());
 }
 
 // Test the case where the a key is added when the decryptor is in
diff --git a/media/filters/decrypting_demuxer_stream.cc b/media/filters/decrypting_demuxer_stream.cc
index b069567..821ea8b 100644
--- a/media/filters/decrypting_demuxer_stream.cc
+++ b/media/filters/decrypting_demuxer_stream.cc
@@ -161,6 +161,10 @@
   demuxer_stream_->EnableBitstreamConverter();
 }
 
+bool DecryptingDemuxerStream::SupportsConfigChanges() {
+  return demuxer_stream_->SupportsConfigChanges();
+}
+
 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
   DVLOG(2) << __FUNCTION__ << " : state_ = " << state_;
 }
diff --git a/media/filters/decrypting_demuxer_stream.h b/media/filters/decrypting_demuxer_stream.h
index 6b29a21..ec9f4b4 100644
--- a/media/filters/decrypting_demuxer_stream.h
+++ b/media/filters/decrypting_demuxer_stream.h
@@ -55,6 +55,7 @@
   virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
   virtual Type type() OVERRIDE;
   virtual void EnableBitstreamConverter() OVERRIDE;
+  virtual bool SupportsConfigChanges() OVERRIDE;
 
  private:
   // For a detailed state diagram please see this link: http://goo.gl/8jAok
diff --git a/media/filters/fake_demuxer_stream.cc b/media/filters/fake_demuxer_stream.cc
index 51e4236..5c5ca50 100644
--- a/media/filters/fake_demuxer_stream.cc
+++ b/media/filters/fake_demuxer_stream.cc
@@ -36,6 +36,7 @@
     : task_runner_(base::MessageLoopProxy::current()),
       num_configs_left_(num_configs),
       num_buffers_in_one_config_(num_buffers_in_one_config),
+      config_changes_(num_configs > 1),
       is_encrypted_(is_encrypted),
       num_buffers_left_in_current_config_(num_buffers_in_one_config),
       num_buffers_returned_(0),
@@ -85,6 +86,10 @@
   DCHECK(task_runner_->BelongsToCurrentThread());
 }
 
+bool FakeDemuxerStream::SupportsConfigChanges() {
+  return config_changes_;
+}
+
 void FakeDemuxerStream::HoldNextRead() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   read_to_hold_ = next_read_num_;
diff --git a/media/filters/fake_demuxer_stream.h b/media/filters/fake_demuxer_stream.h
index b6fd7f3..1c1144e 100644
--- a/media/filters/fake_demuxer_stream.h
+++ b/media/filters/fake_demuxer_stream.h
@@ -33,6 +33,7 @@
   virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
   virtual Type type() OVERRIDE;
   virtual void EnableBitstreamConverter() OVERRIDE;
+  virtual bool SupportsConfigChanges() OVERRIDE;
 
   int num_buffers_returned() const { return num_buffers_returned_; }
 
@@ -60,6 +61,7 @@
 
   int num_configs_left_;
   int num_buffers_in_one_config_;
+  bool config_changes_;
   bool is_encrypted_;
 
   // Number of frames left with the current decoder config.
diff --git a/media/filters/fake_demuxer_stream_unittest.cc b/media/filters/fake_demuxer_stream_unittest.cc
index 553a2f0..6ce8b39 100644
--- a/media/filters/fake_demuxer_stream_unittest.cc
+++ b/media/filters/fake_demuxer_stream_unittest.cc
@@ -72,6 +72,7 @@
         break;
 
       case CONFIG_CHANGED:
+        EXPECT_TRUE(stream_->SupportsConfigChanges());
         EXPECT_FALSE(read_pending_);
         EXPECT_EQ(DemuxerStream::kConfigChanged, status_);
         EXPECT_FALSE(buffer_.get());
@@ -244,4 +245,13 @@
   ReadAndExpect(EOS);
 }
 
+TEST_F(FakeDemuxerStreamTest, NoConfigChanges) {
+  stream_.reset(
+      new FakeDemuxerStream(1, kNumBuffersInOneConfig, false));
+  EXPECT_FALSE(stream_->SupportsConfigChanges());
+  for (int i = 0; i < kNumBuffersInOneConfig; ++i)
+    ReadAndExpect(OK);
+  ReadAndExpect(EOS);
+}
+
 }  // namespace media
diff --git a/media/filters/ffmpeg_audio_decoder.cc b/media/filters/ffmpeg_audio_decoder.cc
index 61dea52..3cb69c0 100644
--- a/media/filters/ffmpeg_audio_decoder.cc
+++ b/media/filters/ffmpeg_audio_decoder.cc
@@ -92,6 +92,7 @@
   scoped_refptr<AudioBuffer> buffer = AudioBuffer::CreateBuffer(
       sample_format,
       ChannelLayoutToChromeChannelLayout(s->channel_layout, s->channels),
+      channels,
       s->sample_rate,
       frames_required);
 
@@ -128,10 +129,6 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
     : task_runner_(task_runner),
       state_(kUninitialized),
-      bytes_per_channel_(0),
-      channel_layout_(CHANNEL_LAYOUT_NONE),
-      channels_(0),
-      samples_per_second_(0),
       av_sample_format_(0),
       last_input_timestamp_(kNoTimestamp()),
       output_frames_to_drop_(0) {}
@@ -197,21 +194,6 @@
   return out;
 }
 
-int FFmpegAudioDecoder::bits_per_channel() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return bytes_per_channel_ * 8;
-}
-
-ChannelLayout FFmpegAudioDecoder::channel_layout() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return channel_layout_;
-}
-
-int FFmpegAudioDecoder::samples_per_second() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return samples_per_second_;
-}
-
 void FFmpegAudioDecoder::Reset(const base::Closure& closure) {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
@@ -286,8 +268,8 @@
         buffer->timestamp() < base::TimeDelta()) {
       // Dropping frames for negative timestamps as outlined in section A.2
       // in the Vorbis spec. http://xiph.org/vorbis/doc/Vorbis_I_spec.html
-      output_frames_to_drop_ = floor(
-          0.5 + -buffer->timestamp().InSecondsF() * samples_per_second_);
+      output_frames_to_drop_ = floor(0.5 + -buffer->timestamp().InSecondsF() *
+                                               config_.samples_per_second());
     } else {
       if (last_input_timestamp_ != kNoTimestamp() &&
           buffer->timestamp() < last_input_timestamp_) {
@@ -392,17 +374,14 @@
     int original_frames = 0;
     int channels = DetermineChannels(av_frame_.get());
     if (frame_decoded) {
-
-      // TODO(rileya) Remove this check once we properly support midstream audio
-      // config changes.
       if (av_frame_->sample_rate != config_.samples_per_second() ||
-          channels != channels_ ||
+          channels != ChannelLayoutToChannelCount(config_.channel_layout()) ||
           av_frame_->format != av_sample_format_) {
         DLOG(ERROR) << "Unsupported midstream configuration change!"
                     << " Sample Rate: " << av_frame_->sample_rate << " vs "
-                    << samples_per_second_
+                    << config_.samples_per_second()
                     << ", Channels: " << channels << " vs "
-                    << channels_
+                    << ChannelLayoutToChannelCount(config_.channel_layout())
                     << ", Sample Format: " << av_frame_->format << " vs "
                     << av_sample_format_;
 
@@ -417,7 +396,8 @@
       output = reinterpret_cast<AudioBuffer*>(
           av_buffer_get_opaque(av_frame_->buf[0]));
 
-      DCHECK_EQ(channels_, output->channel_count());
+      DCHECK_EQ(ChannelLayoutToChannelCount(config_.channel_layout()),
+                output->channel_count());
       original_frames = av_frame_->nb_samples;
       int unread_frames = output->frame_count() - original_frames;
       DCHECK_GE(unread_frames, 0);
@@ -480,22 +460,6 @@
     return false;
   }
 
-  // TODO(rileya) Remove this check once we properly support midstream audio
-  // config changes.
-  if (codec_context_.get() &&
-      (bytes_per_channel_ != config_.bytes_per_channel() ||
-       channel_layout_ != config_.channel_layout() ||
-       samples_per_second_ != config_.samples_per_second())) {
-    DVLOG(1) << "Unsupported config change :";
-    DVLOG(1) << "\tbytes_per_channel : " << bytes_per_channel_
-             << " -> " << config_.bytes_per_channel();
-    DVLOG(1) << "\tchannel_layout : " << channel_layout_
-             << " -> " << config_.channel_layout();
-    DVLOG(1) << "\tsample_rate : " << samples_per_second_
-             << " -> " << config_.samples_per_second();
-    return false;
-  }
-
   // Release existing decoder resources if necessary.
   ReleaseFFmpegResources();
 
@@ -518,27 +482,21 @@
 
   // Success!
   av_frame_.reset(av_frame_alloc());
-  channel_layout_ = config_.channel_layout();
-  samples_per_second_ = config_.samples_per_second();
   output_timestamp_helper_.reset(
       new AudioTimestampHelper(config_.samples_per_second()));
 
-  // Store initial values to guard against midstream configuration changes.
-  channels_ = codec_context_->channels;
-  if (channels_ != ChannelLayoutToChannelCount(channel_layout_)) {
+  av_sample_format_ = codec_context_->sample_fmt;
+
+  if (codec_context_->channels !=
+      ChannelLayoutToChannelCount(config_.channel_layout())) {
     DLOG(ERROR) << "Audio configuration specified "
-                << ChannelLayoutToChannelCount(channel_layout_)
+                << ChannelLayoutToChannelCount(config_.channel_layout())
                 << " channels, but FFmpeg thinks the file contains "
-                << channels_ << " channels";
+                << codec_context_->channels << " channels";
     ReleaseFFmpegResources();
     state_ = kUninitialized;
     return false;
   }
-  av_sample_format_ = codec_context_->sample_fmt;
-  sample_format_ = AVSampleFormatToSampleFormat(
-      static_cast<AVSampleFormat>(av_sample_format_));
-  bytes_per_channel_ = SampleFormatToBytesPerChannel(sample_format_);
-
   return true;
 }
 
diff --git a/media/filters/ffmpeg_audio_decoder.h b/media/filters/ffmpeg_audio_decoder.h
index ca965d7..32fddb8 100644
--- a/media/filters/ffmpeg_audio_decoder.h
+++ b/media/filters/ffmpeg_audio_decoder.h
@@ -39,9 +39,6 @@
   virtual void Decode(const scoped_refptr<DecoderBuffer>& buffer,
                       const DecodeCB& decode_cb) OVERRIDE;
   virtual scoped_refptr<AudioBuffer> GetDecodeOutput() OVERRIDE;
-  virtual int bits_per_channel() OVERRIDE;
-  virtual ChannelLayout channel_layout() OVERRIDE;
-  virtual int samples_per_second() OVERRIDE;
   virtual void Reset(const base::Closure& closure) OVERRIDE;
   virtual void Stop(const base::Closure& closure) OVERRIDE;
 
@@ -79,17 +76,10 @@
   scoped_ptr<AVCodecContext, ScopedPtrAVFreeContext> codec_context_;
   scoped_ptr<AVFrame, ScopedPtrAVFreeFrame> av_frame_;
 
-  // Decoded audio format.
-  int bytes_per_channel_;
-  ChannelLayout channel_layout_;
-  int channels_;
-  int samples_per_second_;
+  AudioDecoderConfig config_;
 
   // AVSampleFormat initially requested; not Chrome's SampleFormat.
   int av_sample_format_;
-  SampleFormat sample_format_;
-
-  AudioDecoderConfig config_;
 
   // Used for computing output timestamps.
   scoped_ptr<AudioTimestampHelper> output_timestamp_helper_;
diff --git a/media/filters/ffmpeg_audio_decoder_unittest.cc b/media/filters/ffmpeg_audio_decoder_unittest.cc
index 6f571e7..ee09669 100644
--- a/media/filters/ffmpeg_audio_decoder_unittest.cc
+++ b/media/filters/ffmpeg_audio_decoder_unittest.cc
@@ -174,9 +174,6 @@
                             vorbis_extradata_->data(),
                             vorbis_extradata_->data_size(),
                             false);  // Not encrypted.
-  EXPECT_EQ(config.bits_per_channel(), decoder_->bits_per_channel());
-  EXPECT_EQ(config.channel_layout(), decoder_->channel_layout());
-  EXPECT_EQ(config.samples_per_second(), decoder_->samples_per_second());
   Stop();
 }
 
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 5e3409d..d2267f3 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -268,6 +268,8 @@
   bitstream_converter_enabled_ = true;
 }
 
+bool FFmpegDemuxerStream::SupportsConfigChanges() { return false; }
+
 AudioDecoderConfig FFmpegDemuxerStream::audio_decoder_config() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   CHECK_EQ(type_, AUDIO);
diff --git a/media/filters/ffmpeg_demuxer.h b/media/filters/ffmpeg_demuxer.h
index 6068e0d..7acdd43 100644
--- a/media/filters/ffmpeg_demuxer.h
+++ b/media/filters/ffmpeg_demuxer.h
@@ -81,6 +81,7 @@
   virtual Type type() OVERRIDE;
   virtual void Read(const ReadCB& read_cb) OVERRIDE;
   virtual void EnableBitstreamConverter() OVERRIDE;
+  virtual bool SupportsConfigChanges() OVERRIDE;
   virtual AudioDecoderConfig audio_decoder_config() OVERRIDE;
   virtual VideoDecoderConfig video_decoder_config() OVERRIDE;
 
diff --git a/media/filters/opus_audio_decoder.cc b/media/filters/opus_audio_decoder.cc
index 1d132c5..3fd28f4 100644
--- a/media/filters/opus_audio_decoder.cc
+++ b/media/filters/opus_audio_decoder.cc
@@ -251,10 +251,6 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
     : task_runner_(task_runner),
       opus_decoder_(NULL),
-      channel_layout_(CHANNEL_LAYOUT_NONE),
-      samples_per_second_(0),
-      sample_format_(kSampleFormatF32),
-      bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8),
       last_input_timestamp_(kNoTimestamp()),
       frames_to_discard_(0),
       frame_delay_at_start_(0),
@@ -283,21 +279,6 @@
   DecodeBuffer(buffer, BindToCurrentLoop(decode_cb));
 }
 
-int OpusAudioDecoder::bits_per_channel() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return bits_per_channel_;
-}
-
-ChannelLayout OpusAudioDecoder::channel_layout() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return channel_layout_;
-}
-
-int OpusAudioDecoder::samples_per_second() {
-  DCHECK(task_runner_->BelongsToCurrentThread());
-  return samples_per_second_;
-}
-
 void OpusAudioDecoder::Reset(const base::Closure& closure) {
   DCHECK(task_runner_->BelongsToCurrentThread());
 
@@ -401,19 +382,6 @@
     return false;
   }
 
-  // TODO(rileya) Remove this check once we properly support midstream audio
-  // config changes.
-  if (opus_decoder_ &&
-      (channel_layout_ != config_.channel_layout() ||
-       samples_per_second_ != config_.samples_per_second())) {
-    DLOG(ERROR) << "Unsupported config change -"
-                << ", channel_layout: " << channel_layout_
-                << " -> " << config_.channel_layout()
-                << ", sample_rate: " << samples_per_second_
-                << " -> " << config_.samples_per_second();
-    return false;
-  }
-
   // Clean up existing decoder if necessary.
   CloseDecoder();
 
@@ -473,8 +441,6 @@
     return false;
   }
 
-  channel_layout_ = config_.channel_layout();
-  samples_per_second_ = config_.samples_per_second();
   output_timestamp_helper_.reset(
       new AudioTimestampHelper(config_.samples_per_second()));
   start_input_timestamp_ = kNoTimestamp();
@@ -491,22 +457,23 @@
 void OpusAudioDecoder::ResetTimestampState() {
   output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
   last_input_timestamp_ = kNoTimestamp();
-  frames_to_discard_ =
-      TimeDeltaToAudioFrames(config_.seek_preroll(), samples_per_second_);
+  frames_to_discard_ = TimeDeltaToAudioFrames(config_.seek_preroll(),
+                                              config_.samples_per_second());
 }
 
 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input,
                               scoped_refptr<AudioBuffer>* output_buffer) {
   // Allocate a buffer for the output samples.
   *output_buffer = AudioBuffer::CreateBuffer(
-      sample_format_,
-      channel_layout_,
-      samples_per_second_,
+      config_.sample_format(),
+      config_.channel_layout(),
+      ChannelLayoutToChannelCount(config_.channel_layout()),
+      config_.samples_per_second(),
       kMaxOpusOutputPacketSizeSamples);
   const int buffer_size =
       output_buffer->get()->channel_count() *
       output_buffer->get()->frame_count() *
-      SampleFormatToBytesPerChannel(sample_format_);
+      SampleFormatToBytesPerChannel(config_.sample_format());
 
   float* float_output_buffer = reinterpret_cast<float*>(
       output_buffer->get()->channel_data()[0]);
@@ -548,8 +515,8 @@
       frames_to_discard_ = 0;
     }
     if (input->discard_padding().InMicroseconds() > 0) {
-      int discard_padding = TimeDeltaToAudioFrames(input->discard_padding(),
-                                                   samples_per_second_);
+      int discard_padding = TimeDeltaToAudioFrames(
+          input->discard_padding(), config_.samples_per_second());
       if (discard_padding < 0 || discard_padding > frames_to_output) {
         DVLOG(1) << "Invalid file. Incorrect discard padding value.";
         return false;
diff --git a/media/filters/opus_audio_decoder.h b/media/filters/opus_audio_decoder.h
index aa0331f..5855719 100644
--- a/media/filters/opus_audio_decoder.h
+++ b/media/filters/opus_audio_decoder.h
@@ -35,9 +35,6 @@
                           const PipelineStatusCB& status_cb) OVERRIDE;
   virtual void Decode(const scoped_refptr<DecoderBuffer>& buffer,
                       const DecodeCB& decode_cb) OVERRIDE;
-  virtual int bits_per_channel() OVERRIDE;
-  virtual ChannelLayout channel_layout() OVERRIDE;
-  virtual int samples_per_second() OVERRIDE;
   virtual void Reset(const base::Closure& closure) OVERRIDE;
   virtual void Stop(const base::Closure& closure) OVERRIDE;
 
@@ -61,12 +58,6 @@
   AudioDecoderConfig config_;
   OpusMSDecoder* opus_decoder_;
 
-  // Decoded audio format.
-  ChannelLayout channel_layout_;
-  int samples_per_second_;
-  const SampleFormat sample_format_;
-  const int bits_per_channel_;
-
   // Used for computing output timestamps.
   scoped_ptr<AudioTimestampHelper> output_timestamp_helper_;
   base::TimeDelta last_input_timestamp_;
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index 05ba993..efbd144 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -17,6 +17,7 @@
 #include "media/cdm/json_web_key.h"
 #include "media/filters/chunk_demuxer.h"
 
+using testing::_;
 using testing::AnyNumber;
 using testing::AtMost;
 
@@ -58,8 +59,8 @@
 // Constants for the Media Source config change tests.
 const int kAppendTimeSec = 1;
 const int kAppendTimeMs = kAppendTimeSec * 1000;
-const int k320WebMFileDurationMs = 2737;
-const int k640WebMFileDurationMs = 2763;
+const int k320WebMFileDurationMs = 2736;
+const int k640WebMFileDurationMs = 2762;
 const int kOpusEndTrimmingWebMFileDurationMs = 2771;
 const int kVP9WebMFileDurationMs = 2703;
 const int kVP8AWebMFileDurationMs = 2700;
@@ -251,18 +252,19 @@
 // Media Source API.
 class MockMediaSource {
  public:
-  MockMediaSource(const std::string& filename, const std::string& mimetype,
+  MockMediaSource(const std::string& filename,
+                  const std::string& mimetype,
                   int initial_append_size)
       : file_path_(GetTestDataFilePath(filename)),
         current_position_(0),
         initial_append_size_(initial_append_size),
         mimetype_(mimetype),
         chunk_demuxer_(new ChunkDemuxer(
-            base::Bind(&MockMediaSource::DemuxerOpened,
-                       base::Unretained(this)),
+            base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
             base::Bind(&MockMediaSource::DemuxerNeedKey,
                        base::Unretained(this)),
-            LogCB())),
+            LogCB(),
+            false)),
         owned_chunk_demuxer_(chunk_demuxer_) {
 
     file_data_ = ReadTestDataFile(filename);
@@ -393,16 +395,16 @@
       public PipelineIntegrationTestBase {
  public:
   void StartPipelineWithMediaSource(MockMediaSource* source) {
-    EXPECT_CALL(*this, OnBufferingState(Pipeline::kHaveMetadata))
-        .Times(AtMost(1));
-    EXPECT_CALL(*this, OnBufferingState(Pipeline::kPrerollCompleted))
-        .Times(AtMost(1));
+    EXPECT_CALL(*this, OnMetadata(_)).Times(AtMost(1));
+    EXPECT_CALL(*this, OnPrerollCompleted()).Times(AtMost(1));
     pipeline_->Start(
         CreateFilterCollection(source->GetDemuxer(), NULL),
         base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
         base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
         QuitOnStatusCB(PIPELINE_OK),
-        base::Bind(&PipelineIntegrationTest::OnBufferingState,
+        base::Bind(&PipelineIntegrationTest::OnMetadata,
+                   base::Unretained(this)),
+        base::Bind(&PipelineIntegrationTest::OnPrerollCompleted,
                    base::Unretained(this)),
         base::Closure());
 
@@ -417,17 +419,17 @@
   void StartPipelineWithEncryptedMedia(
       MockMediaSource* source,
       FakeEncryptedMedia* encrypted_media) {
-    EXPECT_CALL(*this, OnBufferingState(Pipeline::kHaveMetadata))
-        .Times(AtMost(1));
-    EXPECT_CALL(*this, OnBufferingState(Pipeline::kPrerollCompleted))
-        .Times(AtMost(1));
+    EXPECT_CALL(*this, OnMetadata(_)).Times(AtMost(1));
+    EXPECT_CALL(*this, OnPrerollCompleted()).Times(AtMost(1));
     pipeline_->Start(
         CreateFilterCollection(source->GetDemuxer(),
                                encrypted_media->decryptor()),
         base::Bind(&PipelineIntegrationTest::OnEnded, base::Unretained(this)),
         base::Bind(&PipelineIntegrationTest::OnError, base::Unretained(this)),
         QuitOnStatusCB(PIPELINE_OK),
-        base::Bind(&PipelineIntegrationTest::OnBufferingState,
+        base::Bind(&PipelineIntegrationTest::OnMetadata,
+                   base::Unretained(this)),
+        base::Bind(&PipelineIntegrationTest::OnPrerollCompleted,
                    base::Unretained(this)),
         base::Closure());
 
@@ -653,7 +655,10 @@
 
   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
-  EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs,
+  // The "+ 1" is due to estimated audio and video frame durations on the last
+  // frames appended. The unencrypted file has a TrackEntry DefaultDuration
+  // field for the video track, but the encrypted file does not.
+  EXPECT_EQ(kAppendTimeMs + k640WebMFileDurationMs + 1,
             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
 
   Play();
@@ -713,7 +718,10 @@
   EXPECT_EQ(1u, pipeline_->GetBufferedTimeRanges().size());
   EXPECT_EQ(0, pipeline_->GetBufferedTimeRanges().start(0).InMilliseconds());
   // The second video was not added, so its time has not been added.
-  EXPECT_EQ(k320WebMFileDurationMs,
+  // The "+ 1" is due to estimated audio and video frame durations on the last
+  // frames appended. The unencrypted file has a TrackEntry DefaultDuration
+  // field for the video track, but the encrypted file does not.
+  EXPECT_EQ(k320WebMFileDurationMs + 1,
             pipeline_->GetBufferedTimeRanges().end(0).InMilliseconds());
 
   Play();
@@ -1124,7 +1132,7 @@
 TEST_F(PipelineIntegrationTest, ChunkDemuxerAbortRead_VideoOnly) {
   ASSERT_TRUE(TestSeekDuringRead("bear-320x240-video-only.webm", kVideoOnlyWebM,
                                  32768,
-                                 base::TimeDelta::FromMilliseconds(200),
+                                 base::TimeDelta::FromMilliseconds(167),
                                  base::TimeDelta::FromMilliseconds(1668),
                                  0x1C896, 65536));
 }
diff --git a/media/filters/pipeline_integration_test_base.cc b/media/filters/pipeline_integration_test_base.cc
index 8dce18c..bf639cc 100644
--- a/media/filters/pipeline_integration_test_base.cc
+++ b/media/filters/pipeline_integration_test_base.cc
@@ -17,6 +17,7 @@
 #include "media/filters/opus_audio_decoder.h"
 #include "media/filters/vpx_video_decoder.h"
 
+using ::testing::_;
 using ::testing::AnyNumber;
 using ::testing::AtMost;
 
@@ -28,11 +29,12 @@
 PipelineIntegrationTestBase::PipelineIntegrationTestBase()
     : hashing_enabled_(false),
       clockless_playback_(false),
-      pipeline_(new Pipeline(message_loop_.message_loop_proxy(),
-                             new MediaLog())),
+      pipeline_(
+          new Pipeline(message_loop_.message_loop_proxy(), new MediaLog())),
       ended_(false),
       pipeline_status_(PIPELINE_OK),
-      last_video_frame_format_(VideoFrame::UNKNOWN) {
+      last_video_frame_format_(VideoFrame::UNKNOWN),
+      hardware_config_(AudioParameters(), AudioParameters()) {
   base::MD5Init(&md5_context_);
   EXPECT_CALL(*this, OnSetOpaque(true)).Times(AnyNumber());
 }
@@ -102,16 +104,16 @@
 
 bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path,
                                         PipelineStatus expected_status) {
-  EXPECT_CALL(*this, OnBufferingState(Pipeline::kHaveMetadata))
-      .Times(AtMost(1));
-  EXPECT_CALL(*this, OnBufferingState(Pipeline::kPrerollCompleted))
-      .Times(AtMost(1));
+  EXPECT_CALL(*this, OnMetadata(_)).Times(AtMost(1));
+  EXPECT_CALL(*this, OnPrerollCompleted()).Times(AtMost(1));
   pipeline_->Start(
       CreateFilterCollection(file_path, NULL),
       base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)),
       base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)),
       QuitOnStatusCB(expected_status),
-      base::Bind(&PipelineIntegrationTestBase::OnBufferingState,
+      base::Bind(&PipelineIntegrationTestBase::OnMetadata,
+                 base::Unretained(this)),
+      base::Bind(&PipelineIntegrationTestBase::OnPrerollCompleted,
                  base::Unretained(this)),
       base::Closure());
   message_loop_.Run();
@@ -135,17 +137,17 @@
 
 bool PipelineIntegrationTestBase::Start(const base::FilePath& file_path,
                                         Decryptor* decryptor) {
-  EXPECT_CALL(*this, OnBufferingState(Pipeline::kHaveMetadata))
-      .Times(AtMost(1));
-  EXPECT_CALL(*this, OnBufferingState(Pipeline::kPrerollCompleted))
-      .Times(AtMost(1));
+  EXPECT_CALL(*this, OnMetadata(_)).Times(AtMost(1));
+  EXPECT_CALL(*this, OnPrerollCompleted()).Times(AtMost(1));
   pipeline_->Start(
       CreateFilterCollection(file_path, decryptor),
       base::Bind(&PipelineIntegrationTestBase::OnEnded, base::Unretained(this)),
       base::Bind(&PipelineIntegrationTestBase::OnError, base::Unretained(this)),
       base::Bind(&PipelineIntegrationTestBase::OnStatusCallback,
                  base::Unretained(this)),
-      base::Bind(&PipelineIntegrationTestBase::OnBufferingState,
+      base::Bind(&PipelineIntegrationTestBase::OnMetadata,
+                 base::Unretained(this)),
+      base::Bind(&PipelineIntegrationTestBase::OnPrerollCompleted,
                  base::Unretained(this)),
       base::Closure());
   message_loop_.Run();
@@ -163,7 +165,7 @@
 bool PipelineIntegrationTestBase::Seek(base::TimeDelta seek_time) {
   ended_ = false;
 
-  EXPECT_CALL(*this, OnBufferingState(Pipeline::kPrerollCompleted));
+  EXPECT_CALL(*this, OnPrerollCompleted());
   pipeline_->Seek(seek_time, QuitOnStatusCB(PIPELINE_OK));
   message_loop_.Run();
   return (pipeline_status_ == PIPELINE_OK);
@@ -265,6 +267,13 @@
   audio_decoders.push_back(
       new OpusAudioDecoder(message_loop_.message_loop_proxy()));
 
+  AudioParameters out_params(AudioParameters::AUDIO_PCM_LOW_LATENCY,
+                             CHANNEL_LAYOUT_STEREO,
+                             44100,
+                             16,
+                             512);
+  hardware_config_.UpdateOutputConfig(out_params);
+
   AudioRendererImpl* audio_renderer_impl = new AudioRendererImpl(
       message_loop_.message_loop_proxy(),
       (clockless_playback_)
@@ -273,7 +282,8 @@
       audio_decoders.Pass(),
       base::Bind(&PipelineIntegrationTestBase::SetDecryptor,
                  base::Unretained(this),
-                 decryptor));
+                 decryptor),
+      &hardware_config_);
   // Disable underflow if hashing is enabled.
   if (hashing_enabled_) {
     audio_sink_->StartAudioHashForTesting();
diff --git a/media/filters/pipeline_integration_test_base.h b/media/filters/pipeline_integration_test_base.h
index d162d0b..25a5924 100644
--- a/media/filters/pipeline_integration_test_base.h
+++ b/media/filters/pipeline_integration_test_base.h
@@ -9,6 +9,7 @@
 #include "base/message_loop/message_loop.h"
 #include "media/audio/clockless_audio_sink.h"
 #include "media/audio/null_audio_sink.h"
+#include "media/base/audio_hardware_config.h"
 #include "media/base/demuxer.h"
 #include "media/base/filter_collection.h"
 #include "media/base/media_keys.h"
@@ -109,6 +110,7 @@
   Demuxer::NeedKeyCB need_key_cb_;
   VideoFrame::Format last_video_frame_format_;
   DummyTickClock dummy_clock_;
+  AudioHardwareConfig hardware_config_;
 
   void OnStatusCallbackChecked(PipelineStatus expected_status,
                                PipelineStatus status);
@@ -131,7 +133,8 @@
   void OnVideoRendererPaint(const scoped_refptr<VideoFrame>& frame);
 
   MOCK_METHOD1(OnSetOpaque, void(bool));
-  MOCK_METHOD1(OnBufferingState, void(Pipeline::BufferingState));
+  MOCK_METHOD1(OnMetadata, void(PipelineMetadata));
+  MOCK_METHOD0(OnPrerollCompleted, void());
 };
 
 }  // namespace media
diff --git a/media/filters/skcanvas_video_renderer_unittest.cc b/media/filters/skcanvas_video_renderer_unittest.cc
index 138b9a3..842a8f7 100644
--- a/media/filters/skcanvas_video_renderer_unittest.cc
+++ b/media/filters/skcanvas_video_renderer_unittest.cc
@@ -109,8 +109,8 @@
 
   // Make sure the cropped video frame's aspect ratio matches the output device.
   // Update cropped_frame_'s crop dimensions if this is not the case.
-  EXPECT_EQ(cropped_frame()->natural_size().width() * kHeight,
-      cropped_frame()->natural_size().height() * kWidth);
+  EXPECT_EQ(cropped_frame()->visible_rect().width() * kHeight,
+            cropped_frame()->visible_rect().height() * kWidth);
 
   // Fill in the cropped frame's entire data with colors:
   //
diff --git a/media/filters/source_buffer_stream.cc b/media/filters/source_buffer_stream.cc
index 286300d..89281d6 100644
--- a/media/filters/source_buffer_stream.cc
+++ b/media/filters/source_buffer_stream.cc
@@ -10,9 +10,12 @@
 #include "base/bind.h"
 #include "base/debug/trace_event.h"
 #include "base/logging.h"
+#include "media/base/audio_splicer.h"
 
 namespace media {
 
+typedef StreamParser::BufferQueue BufferQueue;
+
 // Buffers with the same timestamp are only allowed under certain conditions.
 // More precisely, it is allowed in all situations except when the previous
 // frame is not a key frame and the current is a key frame.
@@ -28,12 +31,12 @@
   return prev_is_keyframe || !current_is_keyframe;
 }
 
-// Returns the config ID of |buffer| if |buffer| has no fade out preroll or
+// Returns the config ID of |buffer| if |buffer| has no splice buffers or
 // |index| is out of range.  Otherwise returns the config ID for the fade out
 // preroll buffer at position |index|.
 static int GetConfigId(StreamParserBuffer* buffer, size_t index) {
-  return index < buffer->GetFadeOutPreroll().size()
-             ? buffer->GetFadeOutPreroll()[index]->GetConfigId()
+  return index < buffer->get_splice_buffers().size()
+             ? buffer->get_splice_buffers()[index]->GetConfigId()
              : buffer->GetConfigId();
 }
 
@@ -42,8 +45,6 @@
 // gaps.
 class SourceBufferRange {
  public:
-  typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
-
   // Returns the maximum distance in time between any buffer seen in this
   // stream. Used to estimate the duration of a buffer if its duration is not
   // known.
@@ -196,6 +197,11 @@
   // sequence after |buffers_.back()|, false otherwise.
   bool IsNextInSequence(base::TimeDelta timestamp, bool is_keyframe) const;
 
+  // Adds all buffers which overlap [start, end) to the end of |buffers|.  If
+  // no buffers exist in the range returns false, true otherwise.
+  bool GetBuffersInRange(base::TimeDelta start, base::TimeDelta end,
+                         BufferQueue* buffers);
+
   int size_in_bytes() const { return size_in_bytes_; }
 
  private:
@@ -334,7 +340,8 @@
 namespace media {
 
 SourceBufferStream::SourceBufferStream(const AudioDecoderConfig& audio_config,
-                                       const LogCB& log_cb)
+                                       const LogCB& log_cb,
+                                       bool splice_frames_enabled)
     : log_cb_(log_cb),
       current_config_index_(0),
       append_config_index_(0),
@@ -351,13 +358,15 @@
       max_interbuffer_distance_(kNoTimestamp()),
       memory_limit_(kDefaultAudioMemoryLimit),
       config_change_pending_(false),
-      fade_out_preroll_index_(0) {
+      splice_buffers_index_(0),
+      splice_frames_enabled_(splice_frames_enabled) {
   DCHECK(audio_config.IsValidConfig());
   audio_configs_.push_back(audio_config);
 }
 
 SourceBufferStream::SourceBufferStream(const VideoDecoderConfig& video_config,
-                                       const LogCB& log_cb)
+                                       const LogCB& log_cb,
+                                       bool splice_frames_enabled)
     : log_cb_(log_cb),
       current_config_index_(0),
       append_config_index_(0),
@@ -374,13 +383,15 @@
       max_interbuffer_distance_(kNoTimestamp()),
       memory_limit_(kDefaultVideoMemoryLimit),
       config_change_pending_(false),
-      fade_out_preroll_index_(0) {
+      splice_buffers_index_(0),
+      splice_frames_enabled_(splice_frames_enabled) {
   DCHECK(video_config.IsValidConfig());
   video_configs_.push_back(video_config);
 }
 
 SourceBufferStream::SourceBufferStream(const TextTrackConfig& text_config,
-                                       const LogCB& log_cb)
+                                       const LogCB& log_cb,
+                                       bool splice_frames_enabled)
     : log_cb_(log_cb),
       current_config_index_(0),
       append_config_index_(0),
@@ -398,8 +409,8 @@
       max_interbuffer_distance_(kNoTimestamp()),
       memory_limit_(kDefaultAudioMemoryLimit),
       config_change_pending_(false),
-      fade_out_preroll_index_(0) {
-}
+      splice_buffers_index_(0),
+      splice_frames_enabled_(splice_frames_enabled) {}
 
 SourceBufferStream::~SourceBufferStream() {
   while (!ranges_.empty()) {
@@ -429,8 +440,7 @@
   }
 }
 
-bool SourceBufferStream::Append(
-    const SourceBufferStream::BufferQueue& buffers) {
+bool SourceBufferStream::Append(const BufferQueue& buffers) {
   TRACE_EVENT2("media", "SourceBufferStream::Append",
                "stream type", GetStreamTypeName(),
                "buffers to append", buffers.size());
@@ -677,8 +687,8 @@
   track_buffer_.clear();
   config_change_pending_ = false;
   last_output_buffer_timestamp_ = kNoTimestamp();
-  fade_out_preroll_index_ = 0;
-  fade_in_buffer_ = NULL;
+  splice_buffers_index_ = 0;
+  splice_buffer_ = NULL;
 }
 
 bool SourceBufferStream::ShouldSeekToStartOfBuffered(
@@ -957,6 +967,12 @@
     }
   }
 
+  // Handle splices between the existing buffers and the new buffers.  If a
+  // splice is generated the timestamp and duration of the first buffer in
+  // |new_buffers| will be modified.
+  if (splice_frames_enabled_)
+    GenerateSpliceFrame(new_buffers);
+
   base::TimeDelta prev_timestamp = last_appended_buffer_timestamp_;
   bool prev_is_keyframe = last_appended_buffer_is_keyframe_;
   base::TimeDelta next_timestamp = new_buffers.front()->GetDecodeTimestamp();
@@ -1106,55 +1122,56 @@
 
 SourceBufferStream::Status SourceBufferStream::GetNextBuffer(
     scoped_refptr<StreamParserBuffer>* out_buffer) {
-  if (!fade_in_buffer_) {
+  if (!splice_buffer_) {
     const SourceBufferStream::Status status = GetNextBufferInternal(out_buffer);
 
     // Just return if GetNextBufferInternal() failed or there's no fade out
     // preroll, there's nothing else to do.
     if (status != SourceBufferStream::kSuccess ||
-        (*out_buffer)->GetFadeOutPreroll().empty()) {
+        (*out_buffer)->get_splice_buffers().empty()) {
       return status;
     }
 
-    // Setup fade in buffer and fall through into splice frame buffer handling.
-    fade_out_preroll_index_ = 0;
-    fade_in_buffer_.swap(*out_buffer);
+    // Fall through into splice buffer processing.
+    splice_buffers_index_ = 0;
+    splice_buffer_.swap(*out_buffer);
   }
 
-  DCHECK(fade_in_buffer_);
-  const std::vector<scoped_refptr<StreamParserBuffer> >& fade_out_preroll =
-      fade_in_buffer_->GetFadeOutPreroll();
+  DCHECK(splice_buffer_);
+  const BufferQueue& splice_buffers = splice_buffer_->get_splice_buffers();
+  const size_t last_splice_buffer_index = splice_buffers.size() - 1;
 
-  // Are there any fade out buffers left to hand out?
-  if (fade_out_preroll_index_ < fade_out_preroll.size()) {
+  // Are there any splice buffers left to hand out?  The last buffer should be
+  // handed out separately since it represents the first post-splice buffer.
+  if (splice_buffers_index_ < last_splice_buffer_index) {
     // Account for config changes which occur between fade out buffers.
     if (current_config_index_ !=
-        fade_out_preroll[fade_out_preroll_index_]->GetConfigId()) {
+        splice_buffers[splice_buffers_index_]->GetConfigId()) {
       config_change_pending_ = true;
-      DVLOG(1) << "Config change (fade out preroll config ID does not match).";
+      DVLOG(1) << "Config change (splice buffer config ID does not match).";
       return SourceBufferStream::kConfigChange;
     }
 
-    *out_buffer = fade_out_preroll[fade_out_preroll_index_++];
+    *out_buffer = splice_buffers[splice_buffers_index_++];
     return SourceBufferStream::kSuccess;
   }
 
-  // Did we hand out the last fade out buffer on the last call?
-  if (fade_out_preroll_index_ == fade_out_preroll.size()) {
-    fade_out_preroll_index_++;
+  // Did we hand out the last pre-splice buffer on the previous call?
+  if (splice_buffers_index_ == last_splice_buffer_index) {
+    splice_buffers_index_++;
     config_change_pending_ = true;
     DVLOG(1) << "Config change (forced for fade in of splice frame).";
     return SourceBufferStream::kConfigChange;
   }
 
-  // All fade out buffers have been handed out and a config change completed, so
-  // hand out the final buffer for fade in.  Because a config change is always
-  // issued prior to handing out this buffer, any changes in config id have been
-  // inherently handled.
-  DCHECK_GT(fade_out_preroll_index_, fade_out_preroll.size());
-  out_buffer->swap(fade_in_buffer_);
-  fade_in_buffer_ = NULL;
-  fade_out_preroll_index_ = 0;
+  // All pre-splice buffers have been handed out and a config change completed,
+  // so hand out the final buffer for fade in.  Because a config change is
+  // always issued prior to handing out this buffer, any changes in config id
+  // have been inherently handled.
+  DCHECK_GE(splice_buffers_index_, splice_buffers.size());
+  *out_buffer = splice_buffers.back();
+  splice_buffer_ = NULL;
+  splice_buffers_index_ = 0;
   return SourceBufferStream::kSuccess;
 }
 
@@ -1167,7 +1184,7 @@
     scoped_refptr<StreamParserBuffer>& next_buffer = track_buffer_.front();
 
     // If the next buffer is an audio splice frame, the next effective config id
-    // comes from the first fade out preroll buffer.
+    // comes from the first splice buffer.
     if (GetConfigId(next_buffer, 0) != current_config_index_) {
       config_change_pending_ = true;
       DVLOG(1) << "Config change (track buffer config ID does not match).";
@@ -1335,21 +1352,6 @@
     return false;
   }
 
-  if (audio_configs_[0].samples_per_second() != config.samples_per_second()) {
-    MEDIA_LOG(log_cb_) << "Audio sample rate changes not allowed.";
-    return false;
-  }
-
-  if (audio_configs_[0].channel_layout() != config.channel_layout()) {
-    MEDIA_LOG(log_cb_) << "Audio channel layout changes not allowed.";
-    return false;
-  }
-
-  if (audio_configs_[0].bits_per_channel() != config.bits_per_channel()) {
-    MEDIA_LOG(log_cb_) << "Audio bits per channel changes not allowed.";
-    return false;
-  }
-
   if (audio_configs_[0].is_encrypted() != config.is_encrypted()) {
     MEDIA_LOG(log_cb_) << "Audio encryption changes not allowed.";
     return false;
@@ -1410,9 +1412,9 @@
 void SourceBufferStream::CompleteConfigChange() {
   config_change_pending_ = false;
 
-  if (fade_in_buffer_) {
+  if (splice_buffer_) {
     current_config_index_ =
-        GetConfigId(fade_in_buffer_, fade_out_preroll_index_);
+        GetConfigId(splice_buffer_, splice_buffers_index_);
     return;
   }
 
@@ -1586,6 +1588,69 @@
   *itr = ranges_.erase(*itr);
 }
 
+void SourceBufferStream::GenerateSpliceFrame(const BufferQueue& new_buffers) {
+  DCHECK(!new_buffers.empty());
+
+  // Splice frames are only supported for audio.
+  if (GetType() != kAudio)
+    return;
+
+  // Find the overlapped range (if any).
+  const base::TimeDelta splice_timestamp = new_buffers.front()->timestamp();
+  RangeList::iterator range_itr = FindExistingRangeFor(splice_timestamp);
+  if (range_itr == ranges_.end())
+    return;
+
+  const base::TimeDelta max_splice_end_timestamp =
+      splice_timestamp + base::TimeDelta::FromMilliseconds(
+                             AudioSplicer::kCrossfadeDurationInMilliseconds);
+
+  // Find all buffers involved before the splice point.
+  BufferQueue pre_splice_buffers;
+  if (!(*range_itr)->GetBuffersInRange(
+          splice_timestamp, max_splice_end_timestamp, &pre_splice_buffers)) {
+    return;
+  }
+
+  // If there are gaps in the timeline, it's possible that we only find buffers
+  // after the splice point but within the splice range.  For simplicity, we do
+  // not generate splice frames in this case.
+  if (pre_splice_buffers.front()->timestamp() > splice_timestamp)
+    return;
+
+  // Sanitize |pre_splice_buffers| so that there are no recursive splices.
+  for (size_t i = 0; i < pre_splice_buffers.size(); ++i) {
+    const BufferQueue& original_splice_buffers =
+        pre_splice_buffers[i]->get_splice_buffers();
+    if (original_splice_buffers.empty())
+      continue;
+
+    // Remove the original splice and move our index back to compensate.  NOTE:
+    // |i| will underflow if the splice is the first buffer, this is okay.  It
+    // will be corrected below or on the next loop iteration.
+    pre_splice_buffers.erase(pre_splice_buffers.begin() + i--);
+
+    // Cull all buffers which start after the end of the new splice point or
+    // after original overlapping buffer; this may introduce gaps, but no more
+    // than Remove() does currently.
+    const scoped_refptr<StreamParserBuffer>& overlapping_buffer =
+        original_splice_buffers.back();
+    for (BufferQueue::const_iterator it = original_splice_buffers.begin();
+         it != original_splice_buffers.end();
+         ++it) {
+      const scoped_refptr<StreamParserBuffer>& buffer = *it;
+      if (buffer->timestamp() <= max_splice_end_timestamp &&
+          (buffer->timestamp() < overlapping_buffer->timestamp() ||
+           buffer == overlapping_buffer)) {
+        // Add the buffer and adjust the index forward to compensate.
+        pre_splice_buffers.insert(pre_splice_buffers.begin() + ++i, buffer);
+      }
+    }
+  }
+
+  new_buffers.front()->ConvertToSpliceBuffer(pre_splice_buffers);
+}
+
 SourceBufferRange::SourceBufferRange(
     SourceBufferStream::Type type, const BufferQueue& new_buffers,
     base::TimeDelta media_segment_start_time,
@@ -1604,7 +1669,6 @@
 
 void SourceBufferRange::AppendBuffersToEnd(const BufferQueue& new_buffers) {
   DCHECK(buffers_.empty() || CanAppendBuffersToEnd(new_buffers));
-
   for (BufferQueue::const_iterator itr = new_buffers.begin();
        itr != new_buffers.end(); ++itr) {
     DCHECK((*itr)->GetDecodeTimestamp() != kNoTimestamp());
@@ -1694,7 +1758,7 @@
   return split_range;
 }
 
-SourceBufferRange::BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
+BufferQueue::iterator SourceBufferRange::GetBufferItrAt(
     base::TimeDelta timestamp,
     bool skip_given_timestamp) {
   return skip_given_timestamp
@@ -2086,4 +2150,32 @@
   return max_interbuffer_distance;
 }
 
+bool SourceBufferRange::GetBuffersInRange(base::TimeDelta start,
+                                          base::TimeDelta end,
+                                          BufferQueue* buffers) {
+  // Find the nearest buffer with a decode timestamp <= start.
+  const base::TimeDelta first_timestamp = KeyframeBeforeTimestamp(start);
+  if (first_timestamp == kNoTimestamp())
+    return false;
+
+  // Find all buffers involved in the range.
+  const size_t previous_size = buffers->size();
+  for (BufferQueue::iterator it = GetBufferItrAt(first_timestamp, false);
+       it != buffers_.end();
+       ++it) {
+    const scoped_refptr<StreamParserBuffer>& buffer = *it;
+    // Buffers without duration are not supported, so bail if we encounter any.
+    if (buffer->duration() == kNoTimestamp() ||
+        buffer->duration() <= base::TimeDelta()) {
+      return false;
+    }
+    if (buffer->end_of_stream() || buffer->timestamp() >= end)
+      break;
+    if (buffer->timestamp() + buffer->duration() <= start)
+      continue;
+    buffers->push_back(buffer);
+  }
+  return previous_size < buffers->size();
+}
+
 }  // namespace media
diff --git a/media/filters/source_buffer_stream.h b/media/filters/source_buffer_stream.h
index 7aa5855..d1fb29a 100644
--- a/media/filters/source_buffer_stream.h
+++ b/media/filters/source_buffer_stream.h
@@ -32,7 +32,7 @@
 // See file-level comment for complete description.
 class MEDIA_EXPORT SourceBufferStream {
  public:
-  typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
+  typedef StreamParser::BufferQueue BufferQueue;
 
   // Status returned by GetNextBuffer().
   // kSuccess: Indicates that the next buffer was returned.
@@ -53,11 +53,14 @@
   };
 
   SourceBufferStream(const AudioDecoderConfig& audio_config,
-                     const LogCB& log_cb);
+                     const LogCB& log_cb,
+                     bool splice_frames_enabled);
   SourceBufferStream(const VideoDecoderConfig& video_config,
-                     const LogCB& log_cb);
+                     const LogCB& log_cb,
+                     bool splice_frames_enabled);
   SourceBufferStream(const TextTrackConfig& text_config,
-                     const LogCB& log_cb);
+                     const LogCB& log_cb,
+                     bool splice_frames_enabled);
 
   ~SourceBufferStream();
 
@@ -304,6 +307,12 @@
   // processing for splice frame buffers; which is handled by GetNextBuffer().
   Status GetNextBufferInternal(scoped_refptr<StreamParserBuffer>* out_buffer);
 
+  // Called by PrepareRangesForNextAppend() before pruning overlapped buffers to
+  // generate a splice frame with a small portion of the overlapped buffers.  If
+  // a splice frame is generated, the first buffer in |new_buffers| will have
+  // its timestamps, duration, and fade out preroll updated.
+  void GenerateSpliceFrame(const BufferQueue& new_buffers);
+
   // Callback used to report error strings that can help the web developer
   // figure out what is wrong with the content.
   LogCB log_cb_;
@@ -382,12 +391,15 @@
 
   // Used by GetNextBuffer() when a buffer with fade out is returned from
   // GetNextBufferInternal().  Will be set to the returned buffer and will be
-  // consumed after the fade out section has been exhausted.
-  scoped_refptr<StreamParserBuffer> fade_in_buffer_;
+  // destroyed after the splice_buffers() section has been exhausted.
+  scoped_refptr<StreamParserBuffer> splice_buffer_;
 
-  // Indicates which of the fade out preroll buffers in |fade_in_buffer_| should
-  // be handled out next.
-  size_t fade_out_preroll_index_;
+  // Indicates which of the splice buffers in |splice_buffer_| should be
+  // handled out next.
+  size_t splice_buffers_index_;
+
+  // Indicates that splice frame generation is enabled.
+  const bool splice_frames_enabled_;
 
   DISALLOW_COPY_AND_ASSIGN(SourceBufferStream);
 };
diff --git a/media/filters/source_buffer_stream_unittest.cc b/media/filters/source_buffer_stream_unittest.cc
index dfa16ee..8ad3389 100644
--- a/media/filters/source_buffer_stream_unittest.cc
+++ b/media/filters/source_buffer_stream_unittest.cc
@@ -21,6 +21,8 @@
 
 namespace media {
 
+typedef StreamParser::BufferQueue BufferQueue;
+
 static const int kDefaultFramesPerSecond = 30;
 static const int kDefaultKeyframesPerSecond = 6;
 static const uint8 kDataA = 0x11;
@@ -29,10 +31,11 @@
 
 class SourceBufferStreamTest : public testing::Test {
  protected:
-  SourceBufferStreamTest() {
+  SourceBufferStreamTest()
+      : accurate_durations_(false) {
     video_config_ = TestVideoConfig::Normal();
     SetStreamInfo(kDefaultFramesPerSecond, kDefaultKeyframesPerSecond);
-    stream_.reset(new SourceBufferStream(video_config_, log_cb()));
+    stream_.reset(new SourceBufferStream(video_config_, log_cb(), true));
   }
 
   void SetMemoryLimit(int buffers_of_data) {
@@ -48,10 +51,26 @@
   void SetTextStream() {
     video_config_ = TestVideoConfig::Invalid();
     TextTrackConfig config(kTextSubtitles, "", "", "");
-    stream_.reset(new SourceBufferStream(config, LogCB()));
+    stream_.reset(new SourceBufferStream(config, LogCB(), true));
     SetStreamInfo(2, 2);
   }
 
+  void SetAudioStream() {
+    video_config_ = TestVideoConfig::Invalid();
+    accurate_durations_ = true;
+    AudioDecoderConfig config(kCodecVorbis,
+                              kSampleFormatPlanarF32,
+                              CHANNEL_LAYOUT_STEREO,
+                              1000,
+                              NULL,
+                              0,
+                              false);
+    stream_.reset(new SourceBufferStream(config, LogCB(), true));
+
+    // Equivalent to 2ms per frame.
+    SetStreamInfo(500, 500);
+  }
+
   void NewSegmentAppend(int starting_position, int number_of_buffers) {
     AppendBuffers(starting_position, number_of_buffers, true,
                   base::TimeDelta(), true, &kDataA, kDataSize);
@@ -234,6 +253,7 @@
     std::vector<std::string> timestamps;
     base::SplitString(expected, ' ', &timestamps);
     std::stringstream ss;
+    const SourceBufferStream::Type type = stream_->GetType();
     for (size_t i = 0; i < timestamps.size(); i++) {
       scoped_refptr<StreamParserBuffer> buffer;
       SourceBufferStream::Status status = stream_->GetNextBuffer(&buffer);
@@ -241,10 +261,23 @@
       if (i > 0)
         ss << " ";
 
-      if (timestamps[i] == "C") {
-        EXPECT_EQ(SourceBufferStream::kConfigChange, status);
-        stream_->GetCurrentVideoDecoderConfig();
-        ss << timestamps[i];
+      if (status == SourceBufferStream::kConfigChange) {
+        switch (type) {
+          case SourceBufferStream::kVideo:
+            stream_->GetCurrentVideoDecoderConfig();
+            break;
+          case SourceBufferStream::kAudio:
+            stream_->GetCurrentAudioDecoderConfig();
+            break;
+          case SourceBufferStream::kText:
+            stream_->GetCurrentTextTrackConfig();
+            break;
+        }
+
+        if (timestamps[i] == "C")
+          EXPECT_EQ(SourceBufferStream::kConfigChange, status);
+
+        ss << "C";
         continue;
       }
 
@@ -299,7 +332,7 @@
 
     int keyframe_interval = frames_per_second_ / keyframes_per_second_;
 
-    SourceBufferStream::BufferQueue queue;
+    BufferQueue queue;
     for (int i = 0; i < number_of_buffers; i++) {
       int position = starting_position + i;
       bool is_keyframe = position % keyframe_interval == 0;
@@ -327,6 +360,8 @@
         presentation_timestamp = timestamp - frame_duration_;
       }
       buffer->set_timestamp(presentation_timestamp);
+      if (accurate_durations_)
+        buffer->set_duration(frame_duration_);
 
       queue.push_back(buffer);
     }
@@ -349,8 +384,7 @@
   // the splice frame.  If a timestamp within the preroll ends with C the config
   // id to use for that and subsequent preroll appends is incremented by one.
   // The config id for non-splice frame appends will not be affected.
-  SourceBufferStream::BufferQueue StringToBufferQueue(
-      const std::string& buffers_to_append) {
+  BufferQueue StringToBufferQueue(const std::string& buffers_to_append) {
     std::vector<std::string> timestamps;
     base::SplitString(buffers_to_append, ' ', &timestamps);
 
@@ -358,8 +392,8 @@
 
     bool splice_frame = false;
     size_t splice_config_id = stream_->append_config_index_;
-    std::vector<scoped_refptr<StreamParserBuffer> > fade_out_preroll;
-    SourceBufferStream::BufferQueue buffers;
+    BufferQueue pre_splice_buffers;
+    BufferQueue buffers;
     for (size_t i = 0; i < timestamps.size(); i++) {
       bool is_keyframe = false;
       bool last_splice_frame = false;
@@ -400,25 +434,27 @@
       base::TimeDelta timestamp =
           base::TimeDelta::FromMilliseconds(time_in_ms);
       buffer->set_timestamp(timestamp);
+      if (accurate_durations_)
+        buffer->set_duration(frame_duration_);
       buffer->SetDecodeTimestamp(timestamp);
 
       if (splice_frame) {
-        if (!fade_out_preroll.empty()) {
+        if (!pre_splice_buffers.empty()) {
           // Enforce strictly monotonically increasing timestamps.
           CHECK_GT(
               timestamp.InMicroseconds(),
-              fade_out_preroll.back()->GetDecodeTimestamp().InMicroseconds());
+              pre_splice_buffers.back()->GetDecodeTimestamp().InMicroseconds());
         }
         buffer->SetConfigId(splice_config_id);
-        fade_out_preroll.push_back(buffer);
+        pre_splice_buffers.push_back(buffer);
         continue;
       }
 
       if (last_splice_frame) {
-        // Forbid splice frames without preroll.
-        CHECK(!fade_out_preroll.empty());
-        buffer->SetFadeOutPreroll(fade_out_preroll);
-        fade_out_preroll.clear();
+        // Require at least one additional buffer for a splice.
+        CHECK(!pre_splice_buffers.empty());
+        buffer->ConvertToSpliceBuffer(pre_splice_buffers);
+        pre_splice_buffers.clear();
       }
 
       buffers.push_back(buffer);
@@ -431,8 +467,7 @@
                      base::TimeDelta segment_start_timestamp,
                      bool one_by_one,
                      bool expect_success) {
-    SourceBufferStream::BufferQueue buffers =
-        StringToBufferQueue(buffers_to_append);
+    BufferQueue buffers = StringToBufferQueue(buffers_to_append);
 
     if (start_new_segment) {
       base::TimeDelta start_timestamp = segment_start_timestamp;
@@ -451,7 +486,7 @@
 
     // Append each buffer one by one.
     for (size_t i = 0; i < buffers.size(); i++) {
-      SourceBufferStream::BufferQueue wrapper;
+      BufferQueue wrapper;
       wrapper.push_back(buffers[i]);
       EXPECT_TRUE(stream_->Append(wrapper));
     }
@@ -464,6 +499,10 @@
   int frames_per_second_;
   int keyframes_per_second_;
   base::TimeDelta frame_duration_;
+  // TODO(dalecurtis): It's silly to have this, all tests should use accurate
+  // durations instead.  However, currently all tests are written with an
+  // expectation of 0 duration, so it's an involved change.
+  bool accurate_durations_;
   DISALLOW_COPY_AND_ASSIGN(SourceBufferStreamTest);
 };
 
@@ -3156,7 +3195,7 @@
 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio) {
   AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO,
                             44100, NULL, 0, false);
-  stream_.reset(new SourceBufferStream(config, log_cb()));
+  stream_.reset(new SourceBufferStream(config, log_cb(), true));
   Seek(0);
   NewSegmentAppend("0K 0K 30K 30 60 60");
   CheckExpectedBuffers("0K 0K 30K 30 60 60");
@@ -3165,7 +3204,7 @@
 TEST_F(SourceBufferStreamTest, SameTimestamp_Audio_Invalid_1) {
   AudioDecoderConfig config(kCodecMP3, kSampleFormatF32, CHANNEL_LAYOUT_STEREO,
                             44100, NULL, 0, false);
-  stream_.reset(new SourceBufferStream(config, log_cb()));
+  stream_.reset(new SourceBufferStream(config, log_cb(), true));
   Seek(0);
   NewSegmentAppend_ExpectFailure("0K 30 30K 60");
 }
@@ -3582,6 +3621,68 @@
   CheckNoNextBuffer();
 }
 
+TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_Basic) {
+  SetAudioStream();
+  Seek(0);
+  NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
+  NewSegmentAppend("11K 13K 15K 17K");
+  CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K C 11K 13K 15K 17K");
+  CheckNoNextBuffer();
+}
+
+TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_DoubleSpliceExactOverlap) {
+  SetAudioStream();
+  Seek(0);
+  NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
+  NewSegmentAppend("10K 13K 15K 17K");
+
+  // Create a splice on top of the first splice.
+  NewSegmentAppend("10K");
+
+  CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 13K C 10K 15K 17K");
+  CheckNoNextBuffer();
+}
+
+TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_DoubleSpliceEarlierOverlap) {
+  SetAudioStream();
+  Seek(0);
+  NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
+  NewSegmentAppend("11K 13K 15K 17K");
+
+  // Create a splice before the first splice which would include it.
+  NewSegmentAppend("9K");
+
+  // TODO(dalecurtis/wolenetz): Technically 15K and 17K should be included here,
+  // but since the range merge algorithm doesn't use exact durations, they're
+  // currently dropped.
+  CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 11K 13K C 9K");
+  CheckNoNextBuffer();
+}
+
+TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_DoubleSpliceLaterOverlap) {
+  SetAudioStream();
+  Seek(0);
+  NewSegmentAppend("0K 2K 4K 6K 8K 10K 12K");
+  NewSegmentAppend("10K 13K 15K 17K");
+
+  // Create a splice after the first splice which would include it.
+  NewSegmentAppend("11K");
+
+  CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 13K 15K C 11K");
+  CheckNoNextBuffer();
+}
+
+// Test that a splice is not created if an end timestamp and start timestamp
+// overlap.
+TEST_F(SourceBufferStreamTest, Audio_SpliceFrame_NoSplice) {
+  SetAudioStream();
+  Seek(0);
+  NewSegmentAppend("0K 2K 4K 6K 8K 10K");
+  NewSegmentAppend("12K 14K 16K 18K");
+  CheckExpectedBuffers("0K 2K 4K 6K 8K 10K 12K 14K 16K 18K");
+  CheckNoNextBuffer();
+}
+
 // TODO(vrk): Add unit tests where keyframes are unaligned between streams.
 // (crbug.com/133557)
 
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc
index 407e305..5a5603e 100644
--- a/media/filters/stream_parser_factory.cc
+++ b/media/filters/stream_parser_factory.cc
@@ -318,13 +318,6 @@
     if (type == type_info.type) {
       if (codecs.empty()) {
 #if defined(USE_PROPRIETARY_CODECS)
-        if (type_info.codecs == kAudioMP3Codecs &&
-            !CommandLine::ForCurrentProcess()->HasSwitch(
-                switches::kEnableMP3StreamParser)) {
-          DVLOG(1) << "MP3StreamParser is not enabled.";
-          return false;
-        }
-
         if (type_info.codecs == kAudioADTSCodecs &&
             !CommandLine::ForCurrentProcess()->HasSwitch(
                 switches::kEnableADTSStreamParser)) {
diff --git a/media/filters/video_frame_painter.cc b/media/filters/video_frame_painter.cc
deleted file mode 100644
index 6da2521..0000000
--- a/media/filters/video_frame_painter.cc
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "media/filters/video_frame_painter.h"
-
-#include "media/base/video_frame.h"
-
-namespace media {
-
-VideoFramePainter::VideoFramePainter(
-    const base::Closure& invalidate_cb,
-    const base::Callback<void(gfx::Size)>& natural_size_changed_cb)
-    : invalidate_cb_(invalidate_cb),
-      natural_size_changed_cb_(natural_size_changed_cb),
-      invalidation_finished_(true),
-      current_frame_painted_(false),
-      frames_dropped_before_paint_(0) {}
-
-VideoFramePainter::~VideoFramePainter() {}
-
-void VideoFramePainter::UpdateCurrentFrame(
-    const scoped_refptr<VideoFrame>& frame) {
-  base::AutoLock auto_lock(lock_);
-
-  // Count frames as dropped if and only if we updated the frame but didn't
-  // finish invalidating nor managed to paint the current frame.
-  if (!current_frame_painted_ && !invalidation_finished_ &&
-      frames_dropped_before_paint_ < kuint32max) {
-    ++frames_dropped_before_paint_;
-  }
-
-  if (current_frame_ &&
-      current_frame_->natural_size() != frame->natural_size()) {
-    natural_size_changed_cb_.Run(frame->natural_size());
-  }
-
-  current_frame_ = frame;
-  current_frame_painted_ = false;
-
-  if (!invalidation_finished_)
-    return;
-
-  invalidation_finished_ = false;
-  invalidate_cb_.Run();
-}
-
-scoped_refptr<VideoFrame> VideoFramePainter::GetCurrentFrame(
-    bool frame_being_painted) {
-  base::AutoLock auto_lock(lock_);
-  if (frame_being_painted)
-    current_frame_painted_ = true;
-
-  return current_frame_;
-}
-
-void VideoFramePainter::DidFinishInvalidating() {
-  base::AutoLock auto_lock(lock_);
-  invalidation_finished_ = true;
-}
-
-uint32 VideoFramePainter::GetFramesDroppedBeforePaint() {
-  base::AutoLock auto_lock(lock_);
-  return frames_dropped_before_paint_;
-}
-
-void VideoFramePainter::SetFramesDroppedBeforePaintForTesting(
-    uint32 dropped_frames) {
-  base::AutoLock auto_lock(lock_);
-  frames_dropped_before_paint_ = dropped_frames;
-}
-
-}  // namespace media
diff --git a/media/filters/video_frame_painter.h b/media/filters/video_frame_painter.h
deleted file mode 100644
index b7bb1ff..0000000
--- a/media/filters/video_frame_painter.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MEDIA_FILTERS_VIDEO_FRAME_PAINTER_H_
-#define MEDIA_FILTERS_VIDEO_FRAME_PAINTER_H_
-
-#include "base/callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "media/base/media_export.h"
-#include "ui/gfx/size.h"
-
-namespace media {
-
-class VideoFrame;
-
-// VideoFramePainter handles incoming frames by managing painting-related
-// information and rate-limiting paint invalidations in a thread-safe manner.
-//
-// Typical usage is to deliver the output of VideoRendererImpl to
-// UpdateCurrentFrame() so that VideoFramePainter can take care of tracking
-// dropped frames and firing callbacks as needed.
-//
-// All APIs are callable from any thread.
-class MEDIA_EXPORT VideoFramePainter {
- public:
-  // |invalidate_cb| is run whenever the current frame has been updated and
-  // the previous invalidation is no longer pending.
-  //
-  // |natural_size_changed_cb| is run with the new natural size of the video
-  // frame whenever a change in natural size is detected.
-  VideoFramePainter(
-      const base::Closure& invalidate_cb,
-      const base::Callback<void(gfx::Size)>& natural_size_changed_cb);
-  ~VideoFramePainter();
-
-  // Updates the current frame and runs |invalidate_cb| if there isn't an
-  // outstanding invalidation.
-  //
-  // Clients are expected to run DidFinishInvalidating() to inform the painter
-  // that invalidation has completed.
-  void UpdateCurrentFrame(const scoped_refptr<VideoFrame>& frame);
-
-  // Retrieves the last frame set via SetCurrentFrame().
-  //
-  // Clients must specify whether the frame will be painted to allow proper
-  // dropped frame count.
-  scoped_refptr<VideoFrame> GetCurrentFrame(bool frame_being_painted);
-
-  // Informs the painter that the client has finished invalidating.
-  void DidFinishInvalidating();
-
-  // Returns the number of frames dropped before the painter was notified of
-  // painting via DidPaintCurrentFrame().
-  uint32 GetFramesDroppedBeforePaint();
-
-  void SetFramesDroppedBeforePaintForTesting(uint32 dropped_frames);
-
- private:
-  base::Closure invalidate_cb_;
-  base::Callback<void(gfx::Size)> natural_size_changed_cb_;
-
-  base::Lock lock_;
-  scoped_refptr<VideoFrame> current_frame_;
-  bool invalidation_finished_;
-  bool current_frame_painted_;
-  uint32 frames_dropped_before_paint_;
-
-  DISALLOW_IMPLICIT_CONSTRUCTORS(VideoFramePainter);
-};
-
-}  // namespace media
-
-#endif  // MEDIA_FILTERS_VIDEO_FRAME_PAINTER_H_
diff --git a/media/filters/video_frame_painter_unittest.cc b/media/filters/video_frame_painter_unittest.cc
deleted file mode 100644
index 71534ff..0000000
--- a/media/filters/video_frame_painter_unittest.cc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "media/base/video_frame.h"
-#include "media/filters/video_frame_painter.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace media {
-
-class VideoFramePainterTest : public testing::Test {
- public:
-  VideoFramePainterTest()
-      : painter_(base::Bind(&VideoFramePainterTest::Invalidate,
-                            base::Unretained(this)),
-                 base::Bind(&VideoFramePainterTest::NaturalSizeChanged,
-                            base::Unretained(this))),
-        invalidate_count_(0),
-        natural_size_changed_count_(0) {}
-  virtual ~VideoFramePainterTest() {}
-
-  VideoFramePainter* painter() { return &painter_; }
-  int invalidate_count() { return invalidate_count_; }
-  int natural_size_changed_count() { return natural_size_changed_count_; }
-  gfx::Size natural_size() { return natural_size_; }
-
- private:
-  void Invalidate() {
-    ++invalidate_count_;
-  }
-
-  void NaturalSizeChanged(gfx::Size natural_size) {
-    ++natural_size_changed_count_;
-    natural_size_ = natural_size;
-  }
-
-  VideoFramePainter painter_;
-  int invalidate_count_;
-  int natural_size_changed_count_;
-  gfx::Size natural_size_;
-
-  DISALLOW_COPY_AND_ASSIGN(VideoFramePainterTest);
-};
-
-TEST_F(VideoFramePainterTest, InitialValues) {
-  EXPECT_FALSE(painter()->GetCurrentFrame(false));
-  EXPECT_EQ(0u, painter()->GetFramesDroppedBeforePaint());
-}
-
-TEST_F(VideoFramePainterTest, UpdateCurrentFrame) {
-  scoped_refptr<VideoFrame> expected = VideoFrame::CreateEOSFrame();
-
-  painter()->UpdateCurrentFrame(expected);
-  scoped_refptr<VideoFrame> actual = painter()->GetCurrentFrame(false);
-
-  EXPECT_EQ(1, invalidate_count());
-  EXPECT_EQ(expected, actual);
-}
-
-TEST_F(VideoFramePainterTest, NaturalSizeChanged) {
-  gfx::Size initial_size(8, 8);
-  scoped_refptr<VideoFrame> initial_frame =
-      VideoFrame::CreateBlackFrame(initial_size);
-
-  gfx::Size larger_size(16, 16);
-  scoped_refptr<VideoFrame> larger_frame =
-      VideoFrame::CreateBlackFrame(larger_size);
-
-  // Initial expectations.
-  EXPECT_EQ(0, natural_size().width());
-  EXPECT_EQ(0, natural_size().height());
-  EXPECT_EQ(0, natural_size_changed_count());
-
-  // Callback isn't fired for the first frame.
-  painter()->UpdateCurrentFrame(initial_frame);
-  EXPECT_EQ(0, natural_size().width());
-  EXPECT_EQ(0, natural_size().height());
-  EXPECT_EQ(0, natural_size_changed_count());
-
-  // Callback should be fired once.
-  painter()->UpdateCurrentFrame(larger_frame);
-  EXPECT_EQ(larger_size.width(), natural_size().width());
-  EXPECT_EQ(larger_size.height(), natural_size().height());
-  EXPECT_EQ(1, natural_size_changed_count());
-
-  painter()->UpdateCurrentFrame(larger_frame);
-  EXPECT_EQ(larger_size.width(), natural_size().width());
-  EXPECT_EQ(larger_size.height(), natural_size().height());
-  EXPECT_EQ(1, natural_size_changed_count());
-
-  // Callback is fired once more when switching back to initial size.
-  painter()->UpdateCurrentFrame(initial_frame);
-  EXPECT_EQ(initial_size.width(), natural_size().width());
-  EXPECT_EQ(initial_size.height(), natural_size().height());
-  EXPECT_EQ(2, natural_size_changed_count());
-
-  painter()->UpdateCurrentFrame(initial_frame);
-  EXPECT_EQ(initial_size.width(), natural_size().width());
-  EXPECT_EQ(initial_size, natural_size());
-  EXPECT_EQ(2, natural_size_changed_count());
-}
-
-TEST_F(VideoFramePainterTest, DidFinishInvalidating) {
-  scoped_refptr<VideoFrame> frame = VideoFrame::CreateEOSFrame();
-
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(1, invalidate_count());
-
-  // Shouldn't increment until DidFinishInvalidating() is called.
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(1, invalidate_count());
-
-  painter()->DidFinishInvalidating();
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(2, invalidate_count());
-}
-
-TEST_F(VideoFramePainterTest, GetFramesDroppedBeforePaint) {
-  scoped_refptr<VideoFrame> frame = VideoFrame::CreateEOSFrame();
-
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(1, invalidate_count());
-  EXPECT_EQ(0u, painter()->GetFramesDroppedBeforePaint());
-
-  // Should not increment if we finished invalidating but didn't paint the
-  // frame.
-  //
-  // This covers the scenario where the region we're invalidating isn't
-  // visible so there wasn't a need to paint.
-  painter()->DidFinishInvalidating();
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(2, invalidate_count());
-  EXPECT_EQ(0u, painter()->GetFramesDroppedBeforePaint());
-
-  // Should not increment if we didn't finish invalidating but still managed
-  // to paint the frame.
-  //
-  // This covers the scenario where something else may have invalidated the
-  // video's region and managed to paint the current frame.
-  painter()->GetCurrentFrame(true);
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(2, invalidate_count());
-  EXPECT_EQ(0u, painter()->GetFramesDroppedBeforePaint());
-
-  // Should increment if we didn't invalidate and didn't paint the frame.
-  //
-  // This covers the scenario where we didn't even finish invalidating nor
-  // painting the current frame before updating. Consider it dropped.
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(2, invalidate_count());
-  EXPECT_EQ(1u, painter()->GetFramesDroppedBeforePaint());
-
-  // Shouldn't overflow.
-  painter()->SetFramesDroppedBeforePaintForTesting(kuint32max);
-  painter()->UpdateCurrentFrame(frame);
-  EXPECT_EQ(kuint32max, painter()->GetFramesDroppedBeforePaint());
-}
-
-}  // namespace media
diff --git a/media/formats/mp4/box_reader.cc b/media/formats/mp4/box_reader.cc
index 57e095a..7910217 100644
--- a/media/formats/mp4/box_reader.cc
+++ b/media/formats/mp4/box_reader.cc
@@ -155,11 +155,13 @@
     case FOURCC_SIDX:
     case FOURCC_SSIX:
     case FOURCC_PRFT:
+    case FOURCC_UUID:
+    case FOURCC_EMSG:
       return true;
     default:
       // Hex is used to show nonprintable characters and aid in debugging
-      MEDIA_LOG(log_cb) << "Unrecognized top-level box type 0x"
-                        << std::hex << type;
+      MEDIA_LOG(log_cb) << "Unrecognized top-level box type "
+                        << FourCCToString(type);
       return false;
   }
 }
diff --git a/media/formats/mp4/box_reader_unittest.cc b/media/formats/mp4/box_reader_unittest.cc
index eae3fa5..69239e6 100644
--- a/media/formats/mp4/box_reader_unittest.cc
+++ b/media/formats/mp4/box_reader_unittest.cc
@@ -181,12 +181,9 @@
   EXPECT_EQ(kids[0].val, 0xdeadbeef);   // Ensure order is preserved
 }
 
-TEST_F(BoxReaderTest, SkippingBloc) {
-  static const uint8 kData[] = {
-    0x00, 0x00, 0x00, 0x09,  'b',  'l',  'o',  'c', 0x00
-  };
+static void TestTopLevelBox(const uint8* data, int size, uint32 fourCC) {
 
-  std::vector<uint8> buf(kData, kData + sizeof(kData));
+  std::vector<uint8> buf(data, data + size);
 
   bool err;
   scoped_ptr<BoxReader> reader(
@@ -194,7 +191,44 @@
 
   EXPECT_FALSE(err);
   EXPECT_TRUE(reader);
-  EXPECT_EQ(FOURCC_BLOC, reader->type());
+  EXPECT_EQ(fourCC, reader->type());
+  EXPECT_EQ(reader->size(), size);
+}
+
+TEST_F(BoxReaderTest, SkippingBloc) {
+  static const uint8 kData[] = {
+    0x00, 0x00, 0x00, 0x09,  'b',  'l',  'o',  'c', 0x00
+  };
+
+  TestTopLevelBox(kData, sizeof(kData), FOURCC_BLOC);
+}
+
+TEST_F(BoxReaderTest, SkippingEmsg) {
+  static const uint8 kData[] = {
+    0x00, 0x00, 0x00, 0x24,  'e',  'm',  's',  'g',
+    0x00,  // version = 0
+    0x00, 0x00, 0x00,  // flags = 0
+    0x61, 0x00,  // scheme_id_uri = "a"
+    0x61, 0x00,  // value = "a"
+    0x00, 0x00, 0x00, 0x01,  // timescale = 1
+    0x00, 0x00, 0x00, 0x02,  // presentation_time_delta = 2
+    0x00, 0x00, 0x00, 0x03,  // event_duration = 3
+    0x00, 0x00, 0x00, 0x04,  // id = 3
+    0x05, 0x06, 0x07, 0x08,  // message_data[4] = 0x05060708
+  };
+
+  TestTopLevelBox(kData, sizeof(kData), FOURCC_EMSG);
+}
+
+TEST_F(BoxReaderTest, SkippingUuid) {
+  static const uint8 kData[] = {
+    0x00, 0x00, 0x00, 0x19,  'u',  'u',  'i',  'd',
+    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+    0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,  // usertype
+    0x00,
+  };
+
+  TestTopLevelBox(kData, sizeof(kData), FOURCC_UUID);
 }
 
 }  // namespace mp4
diff --git a/media/formats/mp4/fourccs.h b/media/formats/mp4/fourccs.h
index 3914221..fce069b 100644
--- a/media/formats/mp4/fourccs.h
+++ b/media/formats/mp4/fourccs.h
@@ -21,6 +21,7 @@
   FOURCC_CTTS = 0x63747473,
   FOURCC_DINF = 0x64696e66,
   FOURCC_EDTS = 0x65647473,
+  FOURCC_EMSG = 0x656d7367,
   FOURCC_ELST = 0x656c7374,
   FOURCC_ENCA = 0x656e6361,
   FOURCC_ENCV = 0x656e6376,
diff --git a/media/formats/webm/tracks_builder.cc b/media/formats/webm/tracks_builder.cc
index 5a49ce0..fb402c4 100644
--- a/media/formats/webm/tracks_builder.cc
+++ b/media/formats/webm/tracks_builder.cc
@@ -4,6 +4,7 @@
 
 #include "media/formats/webm/tracks_builder.h"
 
+#include "base/logging.h"
 #include "media/formats/webm/webm_constants.h"
 
 namespace media {
@@ -54,6 +55,10 @@
   return GetUIntSize(element_id) + 1 + GetUIntSize(value);
 }
 
+static int DoubleElementSize(int element_id) {
+  return GetUIntSize(element_id) + 1 + 8;
+}
+
 static int StringElementSize(int element_id, const std::string& value) {
  return GetUIntSize(element_id) +
         GetUIntMkvSize(value.length()) +
@@ -71,6 +76,19 @@
   }
 }
 
+static void SerializeDouble(uint8** buf_ptr, int* buf_size_ptr,
+                            double value) {
+  // Use a union to convert |value| to native endian integer bit pattern.
+  union {
+    double src;
+    int64 dst;
+  } tmp;
+  tmp.src = value;
+
+  // Write the bytes from native endian |tmp.dst| to big-endian form in |buf|.
+  SerializeInt(buf_ptr, buf_size_ptr, tmp.dst, 8);
+}
+
 static void WriteElementId(uint8** buf, int* buf_size, int element_id) {
   SerializeInt(buf, buf_size, element_id, GetUIntSize(element_id));
 }
@@ -97,6 +115,13 @@
   SerializeInt(buf, buf_size, value, size);
 }
 
+static void WriteDoubleElement(uint8** buf, int* buf_size,
+                               int element_id, double value) {
+  WriteElementId(buf, buf_size, element_id);
+  WriteUInt(buf, buf_size, 8);
+  SerializeDouble(buf, buf_size, value);
+}
+
 static void WriteStringElement(uint8** buf_ptr, int* buf_size_ptr,
                                int element_id, const std::string& value) {
   uint8*& buf = *buf_ptr;
@@ -112,18 +137,48 @@
   buf_size -= size;
 }
 
-TracksBuilder::TracksBuilder() {}
+TracksBuilder::TracksBuilder(bool allow_invalid_values)
+    : allow_invalid_values_(allow_invalid_values) {}
+TracksBuilder::TracksBuilder()
+    : allow_invalid_values_(false) {}
 TracksBuilder::~TracksBuilder() {}
 
-void TracksBuilder::AddTrack(
+void TracksBuilder::AddVideoTrack(
     int track_num,
-    int track_type,
+    int track_uid,
+    const std::string& codec_id,
+    const std::string& name,
+    const std::string& language,
+    int default_duration,
+    int video_pixel_width,
+    int video_pixel_height) {
+  AddTrackInternal(track_num, kWebMTrackTypeVideo, track_uid, codec_id, name,
+                   language, default_duration, video_pixel_width,
+                   video_pixel_height, -1, -1);
+}
+
+void TracksBuilder::AddAudioTrack(
+    int track_num,
+    int track_uid,
+    const std::string& codec_id,
+    const std::string& name,
+    const std::string& language,
+    int default_duration,
+    int audio_channels,
+    double audio_sampling_frequency) {
+  AddTrackInternal(track_num, kWebMTrackTypeAudio, track_uid, codec_id, name,
+                   language, default_duration, -1, -1, audio_channels,
+                   audio_sampling_frequency);
+}
+
+void TracksBuilder::AddTextTrack(
+    int track_num,
     int track_uid,
     const std::string& codec_id,
     const std::string& name,
     const std::string& language) {
-  tracks_.push_back(Track(track_num, track_type, track_uid, codec_id, name,
-                          language));
+  AddTrackInternal(track_num, kWebMTrackTypeSubtitlesOrCaptions, track_uid,
+                   codec_id, name, language, -1, -1, -1, -1, -1);
 }
 
 std::vector<uint8> TracksBuilder::Finish() {
@@ -137,6 +192,24 @@
   return buffer;
 }
 
+void TracksBuilder::AddTrackInternal(
+    int track_num,
+    int track_type,
+    int track_uid,
+    const std::string& codec_id,
+    const std::string& name,
+    const std::string& language,
+    int default_duration,
+    int video_pixel_width,
+    int video_pixel_height,
+    int audio_channels,
+    double audio_sampling_frequency) {
+  tracks_.push_back(Track(track_num, track_type, track_uid, codec_id, name,
+                          language, default_duration, video_pixel_width,
+                          video_pixel_height, audio_channels,
+                          audio_sampling_frequency, allow_invalid_values_));
+}
+
 int TracksBuilder::GetTracksSize() const {
   return MasterElementSize(kWebMIdTracks, GetTracksPayloadSize());
 }
@@ -164,19 +237,78 @@
 TracksBuilder::Track::Track(int track_num, int track_type, int track_uid,
                             const std::string& codec_id,
                             const std::string& name,
-                            const std::string& language)
+                            const std::string& language,
+                            int default_duration,
+                            int video_pixel_width, int video_pixel_height,
+                            int audio_channels, double audio_sampling_frequency,
+                            bool allow_invalid_values)
     : track_num_(track_num),
       track_type_(track_type),
       track_uid_(track_uid),
       codec_id_(codec_id),
       name_(name),
-      language_(language) {
+      language_(language),
+      default_duration_(default_duration),
+      video_pixel_width_(video_pixel_width),
+      video_pixel_height_(video_pixel_height),
+      audio_channels_(audio_channels),
+      audio_sampling_frequency_(audio_sampling_frequency) {
+  if (!allow_invalid_values) {
+    CHECK_GT(track_num_, 0);
+    CHECK_GT(track_type_, 0);
+    CHECK_LT(track_type_, 255);
+    CHECK_GT(track_uid_, 0);
+    if (track_type != kWebMTrackTypeVideo &&
+        track_type != kWebMTrackTypeAudio) {
+      CHECK_EQ(default_duration_, -1);
+    } else {
+      CHECK(default_duration_ == -1 || default_duration_ > 0);
+    }
+
+    if (track_type == kWebMTrackTypeVideo) {
+      CHECK_GT(video_pixel_width_, 0);
+      CHECK_GT(video_pixel_height_, 0);
+    } else {
+      CHECK_EQ(video_pixel_width_, -1);
+      CHECK_EQ(video_pixel_height_, -1);
+    }
+
+    if (track_type == kWebMTrackTypeAudio) {
+      CHECK_GT(audio_channels_, 0);
+      CHECK_GT(audio_sampling_frequency_, 0.0);
+    } else {
+      CHECK_EQ(audio_channels_, -1);
+      CHECK_EQ(audio_sampling_frequency_, -1.0);
+    }
+  }
 }
 
 int TracksBuilder::Track::GetSize() const {
   return MasterElementSize(kWebMIdTrackEntry, GetPayloadSize());
 }
 
+int TracksBuilder::Track::GetVideoPayloadSize() const {
+  int payload_size = 0;
+
+  if (video_pixel_width_ >= 0)
+    payload_size += IntElementSize(kWebMIdPixelWidth, video_pixel_width_);
+  if (video_pixel_height_ >= 0)
+    payload_size += IntElementSize(kWebMIdPixelHeight, video_pixel_height_);
+
+  return payload_size;
+}
+
+int TracksBuilder::Track::GetAudioPayloadSize() const {
+  int payload_size = 0;
+
+  if (audio_channels_ >= 0)
+    payload_size += IntElementSize(kWebMIdChannels, audio_channels_);
+  if (audio_sampling_frequency_ >= 0)
+    payload_size += DoubleElementSize(kWebMIdSamplingFrequency);
+
+  return payload_size;
+}
+
 int TracksBuilder::Track::GetPayloadSize() const {
   int size = 0;
 
@@ -184,6 +316,9 @@
   size += IntElementSize(kWebMIdTrackType, track_type_);
   size += IntElementSize(kWebMIdTrackUID, track_uid_);
 
+  if (default_duration_ >= 0)
+    size += IntElementSize(kWebMIdDefaultDuration, default_duration_);
+
   if (!codec_id_.empty())
     size += StringElementSize(kWebMIdCodecID, codec_id_);
 
@@ -193,6 +328,14 @@
   if (!language_.empty())
     size += StringElementSize(kWebMIdLanguage, language_);
 
+  if (GetVideoPayloadSize() > 0) {
+    size += MasterElementSize(kWebMIdVideo, GetVideoPayloadSize());
+  }
+
+  if (GetAudioPayloadSize() > 0) {
+    size += MasterElementSize(kWebMIdAudio, GetAudioPayloadSize());
+  }
+
   return size;
 }
 
@@ -203,6 +346,9 @@
   WriteIntElement(buf, buf_size, kWebMIdTrackType, track_type_);
   WriteIntElement(buf, buf_size, kWebMIdTrackUID, track_uid_);
 
+  if (default_duration_ >= 0)
+    WriteIntElement(buf, buf_size, kWebMIdDefaultDuration, default_duration_);
+
   if (!codec_id_.empty())
     WriteStringElement(buf, buf_size, kWebMIdCodecID, codec_id_);
 
@@ -211,6 +357,28 @@
 
   if (!language_.empty())
     WriteStringElement(buf, buf_size, kWebMIdLanguage, language_);
+
+  if (GetVideoPayloadSize() > 0) {
+    WriteMasterElement(buf, buf_size, kWebMIdVideo, GetVideoPayloadSize());
+
+    if (video_pixel_width_ >= 0)
+      WriteIntElement(buf, buf_size, kWebMIdPixelWidth, video_pixel_width_);
+
+    if (video_pixel_height_ >= 0)
+      WriteIntElement(buf, buf_size, kWebMIdPixelHeight, video_pixel_height_);
+  }
+
+  if (GetAudioPayloadSize() > 0) {
+    WriteMasterElement(buf, buf_size, kWebMIdAudio, GetAudioPayloadSize());
+
+    if (audio_channels_ >= 0)
+      WriteIntElement(buf, buf_size, kWebMIdChannels, audio_channels_);
+
+    if (audio_sampling_frequency_ >= 0) {
+      WriteDoubleElement(buf, buf_size, kWebMIdSamplingFrequency,
+          audio_sampling_frequency_);
+    }
+  }
 }
 
 }  // namespace media
diff --git a/media/formats/webm/tracks_builder.h b/media/formats/webm/tracks_builder.h
index ecd0fe5..35f8955 100644
--- a/media/formats/webm/tracks_builder.h
+++ b/media/formats/webm/tracks_builder.h
@@ -15,16 +15,37 @@
 
 class TracksBuilder {
  public:
-  TracksBuilder();
+  // If |allow_invalid_values| is false, some AddTrack() parameters will be
+  // basically checked and will assert if out of valid range. |codec_id|,
+  // |name|, |language| and any device-specific constraints are not checked.
+  explicit TracksBuilder(bool allow_invalid_values);
+  TracksBuilder();  // Sets |allow_invalid_values| to false.
   ~TracksBuilder();
 
-  void AddTrack(int track_num, int track_type, int track_uid,
-                const std::string& codec_id, const std::string& name,
-                const std::string& language);
+  // Only a non-negative |default_duration| will result in a serialized
+  // kWebMIdDefaultDuration element. Note, 0 is allowed here for testing only
+  // if |allow_invalid_values_| is true, since it is an illegal value for
+  // DefaultDuration. Similar applies to |audio_channels|,
+  // |audio_sampling_frequency|, |video_pixel_width| and |video_pixel_height|.
+  void AddVideoTrack(int track_num, int track_uid, const std::string& codec_id,
+                     const std::string& name, const std::string& language,
+                     int default_duration, int video_pixel_width,
+                     int video_pixel_height);
+  void AddAudioTrack(int track_num, int track_uid, const std::string& codec_id,
+                     const std::string& name, const std::string& language,
+                     int default_duration, int audio_channels,
+                     double audio_sampling_frequency);
+  void AddTextTrack(int track_num, int track_uid, const std::string& codec_id,
+                    const std::string& name, const std::string& language);
 
   std::vector<uint8> Finish();
 
  private:
+  void AddTrackInternal(int track_num, int track_type, int track_uid,
+                        const std::string& codec_id, const std::string& name,
+                        const std::string& language, int default_duration,
+                        int video_pixel_width, int video_pixel_height,
+                        int audio_channels, double audio_sampling_frequency);
   int GetTracksSize() const;
   int GetTracksPayloadSize() const;
   void WriteTracks(uint8* buffer, int buffer_size) const;
@@ -33,12 +54,17 @@
    public:
     Track(int track_num, int track_type, int track_uid,
           const std::string& codec_id, const std::string& name,
-          const std::string& language);
+          const std::string& language, int default_duration,
+          int video_pixel_width, int video_pixel_height,
+          int audio_channels, double audio_sampling_frequency,
+          bool allow_invalid_values);
 
     int GetSize() const;
     void Write(uint8** buf, int* buf_size) const;
    private:
     int GetPayloadSize() const;
+    int GetVideoPayloadSize() const;
+    int GetAudioPayloadSize() const;
 
     int track_num_;
     int track_type_;
@@ -46,10 +72,16 @@
     std::string codec_id_;
     std::string name_;
     std::string language_;
+    int default_duration_;
+    int video_pixel_width_;
+    int video_pixel_height_;
+    int audio_channels_;
+    double audio_sampling_frequency_;
   };
 
   typedef std::list<Track> TrackList;
   TrackList tracks_;
+  bool allow_invalid_values_;
 
   DISALLOW_COPY_AND_ASSIGN(TracksBuilder);
 };
diff --git a/media/formats/webm/webm_cluster_parser.cc b/media/formats/webm/webm_cluster_parser.cc
index a762e2c..6e2424b 100644
--- a/media/formats/webm/webm_cluster_parser.cc
+++ b/media/formats/webm/webm_cluster_parser.cc
@@ -15,10 +15,21 @@
 #include "media/formats/webm/webm_crypto_helpers.h"
 #include "media/formats/webm/webm_webvtt_parser.h"
 
+// Arbitrarily-chosen numbers to estimate the duration of a buffer if none is
+// set and there is not enough information to get a better estimate.
+// TODO(wolenetz/acolwell): Parse audio codebook to determine missing audio
+// frame durations. See http://crbug.com/351166.
+static int kDefaultAudioBufferDurationInMs = 23;  // Common 1k samples @44.1kHz
+static int kDefaultVideoBufferDurationInMs = 42;  // Low 24fps to reduce stalls
+
 namespace media {
 
 WebMClusterParser::WebMClusterParser(
-    int64 timecode_scale, int audio_track_num, int video_track_num,
+    int64 timecode_scale,
+    int audio_track_num,
+    base::TimeDelta audio_default_duration,
+    int video_track_num,
+    base::TimeDelta video_default_duration,
     const WebMTracksParser::TextTracks& text_tracks,
     const std::set<int64>& ignored_tracks,
     const std::string& audio_encryption_key_id,
@@ -38,13 +49,14 @@
       cluster_timecode_(-1),
       cluster_start_time_(kNoTimestamp()),
       cluster_ended_(false),
-      audio_(audio_track_num, false),
-      video_(video_track_num, true),
+      audio_(audio_track_num, false, audio_default_duration),
+      video_(video_track_num, true, video_default_duration),
       log_cb_(log_cb) {
   for (WebMTracksParser::TextTracks::const_iterator it = text_tracks.begin();
        it != text_tracks.end();
        ++it) {
-    text_track_map_.insert(std::make_pair(it->first, Track(it->first, false)));
+    text_track_map_.insert(std::make_pair(
+        it->first, Track(it->first, false, kNoTimestamp())));
   }
 }
 
@@ -62,8 +74,8 @@
 }
 
 int WebMClusterParser::Parse(const uint8* buf, int size) {
-  audio_.Reset();
-  video_.Reset();
+  audio_.ClearBuffersButKeepLastIfMissingDuration();
+  video_.ClearBuffersButKeepLastIfMissingDuration();
   ResetTextTracks();
 
   int result = parser_.Parse(buf, size);
@@ -99,6 +111,18 @@
   return result;
 }
 
+const WebMClusterParser::BufferQueue& WebMClusterParser::GetAudioBuffers() {
+  if (cluster_ended_)
+    audio_.ApplyDurationDefaultOrEstimateIfNeeded();
+  return audio_.buffers();
+}
+
+const WebMClusterParser::BufferQueue& WebMClusterParser::GetVideoBuffers() {
+  if (cluster_ended_)
+    video_.ApplyDurationDefaultOrEstimateIfNeeded();
+  return video_.buffers();
+}
+
 const WebMClusterParser::TextBufferQueueMap&
 WebMClusterParser::GetTextBuffers() {
   // Translate our |text_track_map_| into |text_buffers_map_|, inserting rows in
@@ -107,6 +131,9 @@
   for (TextTrackMap::const_iterator itr = text_track_map_.begin();
        itr != text_track_map_.end();
        ++itr) {
+    // Per OnBlock(), all text buffers should already have valid durations, so
+    // there is no need to call
+    // itr->second.ApplyDurationDefaultOrEstimateIfNeeded() here.
     const BufferQueue& text_buffers = itr->second.buffers();
     if (!text_buffers.empty())
       text_buffers_map_.insert(std::make_pair(itr->first, text_buffers));
@@ -390,9 +417,14 @@
   return track->AddBuffer(buffer);
 }
 
-WebMClusterParser::Track::Track(int track_num, bool is_video)
+WebMClusterParser::Track::Track(int track_num, bool is_video,
+                                base::TimeDelta default_duration)
     : track_num_(track_num),
-      is_video_(is_video) {
+      is_video_(is_video),
+      default_duration_(default_duration),
+      estimated_next_frame_duration_(kNoTimestamp()) {
+  DCHECK(default_duration_ == kNoTimestamp() ||
+         default_duration_ > base::TimeDelta());
 }
 
 WebMClusterParser::Track::~Track() {}
@@ -405,12 +437,64 @@
            << " kf " << buffer->IsKeyframe()
            << " size " << buffer->data_size();
 
-  buffers_.push_back(buffer);
-  return true;
+  if (last_added_buffer_missing_duration_) {
+    base::TimeDelta derived_duration =
+        buffer->timestamp() - last_added_buffer_missing_duration_->timestamp();
+    last_added_buffer_missing_duration_->set_duration(derived_duration);
+
+    DVLOG(2) << "AddBuffer() : applied derived duration to held-back buffer : "
+             << " ts "
+             << last_added_buffer_missing_duration_->timestamp().InSecondsF()
+             << " dur "
+             << last_added_buffer_missing_duration_->duration().InSecondsF()
+             << " kf " << last_added_buffer_missing_duration_->IsKeyframe()
+             << " size " << last_added_buffer_missing_duration_->data_size();
+    scoped_refptr<StreamParserBuffer> updated_buffer =
+        last_added_buffer_missing_duration_;
+    last_added_buffer_missing_duration_ = NULL;
+    if (!QueueBuffer(updated_buffer))
+      return false;
+  }
+
+  if (buffer->duration() == kNoTimestamp()) {
+    last_added_buffer_missing_duration_ = buffer;
+    DVLOG(2) << "AddBuffer() : holding back buffer that is missing duration";
+    return true;
+  }
+
+  return QueueBuffer(buffer);
+}
+
+void WebMClusterParser::Track::ApplyDurationDefaultOrEstimateIfNeeded() {
+  if (!last_added_buffer_missing_duration_)
+    return;
+
+  last_added_buffer_missing_duration_->set_duration(
+      GetDurationDefaultOrEstimate());
+
+  DVLOG(2) << "ApplyDurationDefaultOrEstimateIfNeeded() : new dur : "
+           << " ts "
+           << last_added_buffer_missing_duration_->timestamp().InSecondsF()
+           << " dur "
+           << last_added_buffer_missing_duration_->duration().InSecondsF()
+           << " kf " << last_added_buffer_missing_duration_->IsKeyframe()
+           << " size " << last_added_buffer_missing_duration_->data_size();
+
+  // Don't use the applied duration as a future estimation (don't use
+  // QueueBuffer() here.)
+  buffers_.push_back(last_added_buffer_missing_duration_);
+  last_added_buffer_missing_duration_ = NULL;
+}
+
+void WebMClusterParser::Track::ClearBuffersButKeepLastIfMissingDuration() {
+  // Note that |estimated_next_frame_duration_| is not reset, so it can be
+  // reused on subsequent buffers added to this instance.
+  buffers_.clear();
 }
 
 void WebMClusterParser::Track::Reset() {
-  buffers_.clear();
+  ClearBuffersButKeepLastIfMissingDuration();
+  last_added_buffer_missing_duration_ = NULL;
 }
 
 bool WebMClusterParser::Track::IsKeyframe(const uint8* data, int size) const {
@@ -436,6 +520,45 @@
   return true;
 }
 
+bool WebMClusterParser::Track::QueueBuffer(
+    const scoped_refptr<StreamParserBuffer>& buffer) {
+  DCHECK(!last_added_buffer_missing_duration_);
+  base::TimeDelta duration = buffer->duration();
+  if (duration < base::TimeDelta() || duration == kNoTimestamp()) {
+    DVLOG(2) << "QueueBuffer() : Invalid buffer duration: "
+             << duration.InSecondsF();
+    return false;
+  }
+
+  estimated_next_frame_duration_ = std::max(duration,
+                                            estimated_next_frame_duration_);
+  buffers_.push_back(buffer);
+  return true;
+}
+
+base::TimeDelta WebMClusterParser::Track::GetDurationDefaultOrEstimate() {
+  base::TimeDelta duration = default_duration_;
+  if (duration != kNoTimestamp()) {
+    DVLOG(3) << __FUNCTION__ << " : using TrackEntry DefaultDuration";
+  } else if (estimated_next_frame_duration_ != kNoTimestamp()) {
+    DVLOG(3) << __FUNCTION__ << " : using estimated duration";
+    duration = estimated_next_frame_duration_;
+  } else {
+    DVLOG(3) << __FUNCTION__ << " : using hardcoded default duration";
+    if (is_video_) {
+      duration = base::TimeDelta::FromMilliseconds(
+          kDefaultVideoBufferDurationInMs);
+    } else {
+      duration = base::TimeDelta::FromMilliseconds(
+          kDefaultAudioBufferDurationInMs);
+    }
+  }
+
+  DCHECK(duration > base::TimeDelta());
+  DCHECK(duration != kNoTimestamp());
+  return duration;
+}
+
 void WebMClusterParser::ResetTextTracks() {
   text_buffers_map_.clear();
   for (TextTrackMap::iterator it = text_track_map_.begin();
diff --git a/media/formats/webm/webm_cluster_parser.h b/media/formats/webm/webm_cluster_parser.h
index cc546cc..749b6bd 100644
--- a/media/formats/webm/webm_cluster_parser.h
+++ b/media/formats/webm/webm_cluster_parser.h
@@ -28,7 +28,7 @@
   // Helper class that manages per-track state.
   class Track {
    public:
-    Track(int track_num, bool is_video);
+    Track(int track_num, bool is_video, base::TimeDelta default_duration);
     ~Track();
 
     int track_num() const { return track_num_; }
@@ -36,9 +36,27 @@
       return buffers_;
     }
 
+    // If |last_added_buffer_missing_duration_| is set, updates its duration
+    // relative to |buffer|'s timestamp, and adds it to |buffers_| and unsets
+    // |last_added_buffer_missing_duration_|. Then, if |buffer| is missing
+    // duration, saves |buffer| into |last_added_buffer_missing_duration_|, or
+    // otherwise adds |buffer| to |buffers_|.
     bool AddBuffer(const scoped_refptr<StreamParserBuffer>& buffer);
 
-    // Clears all buffer state.
+    // If |last_added_buffer_missing_duration_| is set, updates its duration
+    // to be the first non-kNoTimestamp() value of |default_duration_|,
+    // |estimated_next_frame_duration_|, or an arbitrary default, then adds it
+    // to |buffers_| and unsets |last_added_buffer_missing_duration_|. (This
+    // method helps stream parser emit all buffers in a media segment before
+    // signaling end of segment.)
+    void ApplyDurationDefaultOrEstimateIfNeeded();
+
+    // Clears all buffer state, except a possibly held-aside buffer that is
+    // missing duration.
+    void ClearBuffersButKeepLastIfMissingDuration();
+
+    // Clears all buffer state, including any possibly held-aside buffer that
+    // was missing duration.
     void Reset();
 
     // Helper function used to inspect block data to determine if the
@@ -48,9 +66,27 @@
     bool IsKeyframe(const uint8* data, int size) const;
 
    private:
+    // Helper that sanity-checks |buffer| duration, updates
+    // |estimated_next_frame_duration_|, and adds |buffer| to |buffers_|.
+    // Returns false if |buffer| failed sanity check and therefore was not added
+    // to |buffers_|. Returns true otherwise.
+    bool QueueBuffer(const scoped_refptr<StreamParserBuffer>& buffer);
+
+    // Helper that calculates the buffer duration to use in
+    // ApplyDurationDefaultOrEstimateIfNeeded().
+    base::TimeDelta GetDurationDefaultOrEstimate();
+
     int track_num_;
     std::deque<scoped_refptr<StreamParserBuffer> > buffers_;
     bool is_video_;
+    scoped_refptr<StreamParserBuffer> last_added_buffer_missing_duration_;
+
+    // If kNoTimestamp(), then |estimated_next_frame_duration_| will be used.
+    base::TimeDelta default_duration_;
+    // If kNoTimestamp(), then a default value will be used. This estimate is
+    // the maximum duration seen or derived so far for this track, and is valid
+    // only if |default_duration_| is kNoTimestamp().
+    base::TimeDelta estimated_next_frame_duration_;
   };
 
   typedef std::map<int, Track> TextTrackMap;
@@ -61,7 +97,9 @@
 
   WebMClusterParser(int64 timecode_scale,
                     int audio_track_num,
+                    base::TimeDelta audio_default_duration,
                     int video_track_num,
+                    base::TimeDelta video_default_duration,
                     const WebMTracksParser::TextTracks& text_tracks,
                     const std::set<int64>& ignored_tracks,
                     const std::string& audio_encryption_key_id,
@@ -80,8 +118,13 @@
   int Parse(const uint8* buf, int size);
 
   base::TimeDelta cluster_start_time() const { return cluster_start_time_; }
-  const BufferQueue& audio_buffers() const { return audio_.buffers(); }
-  const BufferQueue& video_buffers() const { return video_.buffers(); }
+
+  // Get the buffers resulting from Parse().
+  // If the parse reached the end of cluster and the last buffer was held aside
+  // due to missing duration, the buffer is given an estimated duration and
+  // included in the result.
+  const BufferQueue& GetAudioBuffers();
+  const BufferQueue& GetVideoBuffers();
 
   // Constructs and returns a subset of |text_track_map_| containing only
   // tracks with non-empty buffer queues produced by the last Parse().
diff --git a/media/formats/webm/webm_cluster_parser_unittest.cc b/media/formats/webm/webm_cluster_parser_unittest.cc
index c968be0..8b32f5d 100644
--- a/media/formats/webm/webm_cluster_parser_unittest.cc
+++ b/media/formats/webm/webm_cluster_parser_unittest.cc
@@ -36,7 +36,7 @@
 static const BlockInfo kDefaultBlockInfo[] = {
   { kAudioTrackNum, 0, 23, true },
   { kAudioTrackNum, 23, 23, true },
-  { kVideoTrackNum, 33, 34, true },
+  { kVideoTrackNum, 33, 34, true },  // Assumes not using DefaultDuration
   { kAudioTrackNum, 46, 23, true },
   { kVideoTrackNum, 67, 33, false },
   { kAudioTrackNum, 69, 23, false },
@@ -121,13 +121,7 @@
     scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++];
 
     EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds());
-
-    if (!block_info[i].use_simple_block)
-      EXPECT_NE(kNoTimestamp(), buffer->duration());
-
-    if (buffer->duration() != kNoTimestamp())
-      EXPECT_EQ(block_info[i].duration, buffer->duration().InMilliseconds());
-
+    EXPECT_EQ(block_info[i].duration, buffer->duration().InMilliseconds());
     EXPECT_EQ(expected_type, buffer->type());
     EXPECT_EQ(block_info[i].track_num, buffer->track_id());
   }
@@ -147,8 +141,8 @@
   else
     text_buffers = &no_text_buffers;
 
-  return VerifyBuffers(parser->audio_buffers(),
-                       parser->video_buffers(),
+  return VerifyBuffers(parser->GetAudioBuffers(),
+                       parser->GetVideoBuffers(),
                        *text_buffers,
                        block_info,
                        block_count);
@@ -206,7 +200,9 @@
   WebMClusterParserTest()
       : parser_(new WebMClusterParser(kTimecodeScale,
                                       kAudioTrackNum,
+                                      kNoTimestamp(),
                                       kVideoTrackNum,
+                                      kNoTimestamp(),
                                       WebMTracksParser::TextTracks(),
                                       std::set<int64>(),
                                       std::string(),
@@ -272,8 +268,8 @@
       continue;
     }
 
-    AppendToEnd(parser_->audio_buffers(), &audio_buffers);
-    AppendToEnd(parser_->video_buffers(), &video_buffers);
+    AppendToEnd(parser_->GetAudioBuffers(), &audio_buffers);
+    AppendToEnd(parser_->GetVideoBuffers(), &video_buffers);
 
     parse_size = default_parse_size;
 
@@ -338,7 +334,9 @@
 
   parser_.reset(new WebMClusterParser(kTimecodeScale,
                                       kAudioTrackNum,
+                                      kNoTimestamp(),
                                       kVideoTrackNum,
+                                      kNoTimestamp(),
                                       WebMTracksParser::TextTracks(),
                                       ignored_tracks,
                                       std::string(),
@@ -348,19 +346,19 @@
   const BlockInfo kInputBlockInfo[] = {
     { kAudioTrackNum, 0,  23, true },
     { kAudioTrackNum, 23, 23, true },
-    { kVideoTrackNum, 33, 33, true },
+    { kVideoTrackNum, 33, 34, true },
     { kTextTrackNum,  33, 99, true },
     { kAudioTrackNum, 46, 23, true },
-    { kVideoTrackNum, 67, 33, true },
+    { kVideoTrackNum, 67, 34, true },
   };
   int input_block_count = arraysize(kInputBlockInfo);
 
   const BlockInfo kOutputBlockInfo[] = {
     { kAudioTrackNum, 0,  23, true },
     { kAudioTrackNum, 23, 23, true },
-    { kVideoTrackNum, 33, 33, true },
+    { kVideoTrackNum, 33, 34, true },
     { kAudioTrackNum, 46, 23, true },
-    { kVideoTrackNum, 67, 33, true },
+    { kVideoTrackNum, 67, 34, true },
   };
   int output_block_count = arraysize(kOutputBlockInfo);
 
@@ -382,7 +380,9 @@
 
   parser_.reset(new WebMClusterParser(kTimecodeScale,
                                       kAudioTrackNum,
+                                      kNoTimestamp(),
                                       kVideoTrackNum,
+                                      kNoTimestamp(),
                                       text_tracks,
                                       std::set<int64>(),
                                       std::string(),
@@ -392,11 +392,11 @@
   const BlockInfo kInputBlockInfo[] = {
     { kAudioTrackNum, 0,  23, true },
     { kAudioTrackNum, 23, 23, true },
-    { kVideoTrackNum, 33, 33, true },
+    { kVideoTrackNum, 33, 34, true },
     { kTextTrackNum,  33, 42, false },
     { kAudioTrackNum, 46, 23, true },
     { kTextTrackNum, 55, 44, false },
-    { kVideoTrackNum, 67, 33, true },
+    { kVideoTrackNum, 67, 34, true },
   };
   int input_block_count = arraysize(kInputBlockInfo);
 
@@ -418,7 +418,9 @@
 
   parser_.reset(new WebMClusterParser(kTimecodeScale,
                                       kAudioTrackNum,
+                                      kNoTimestamp(),
                                       kVideoTrackNum,
+                                      kNoTimestamp(),
                                       text_tracks,
                                       std::set<int64>(),
                                       std::string(),
@@ -454,7 +456,9 @@
 
   parser_.reset(new WebMClusterParser(kTimecodeScale,
                                       kAudioTrackNum,
+                                      kNoTimestamp(),
                                       kVideoTrackNum,
+                                      kNoTimestamp(),
                                       text_tracks,
                                       std::set<int64>(),
                                       std::string(),
@@ -464,11 +468,11 @@
   const BlockInfo kInputBlockInfo[] = {
     { kAudioTrackNum, 0,  23, true },
     { kAudioTrackNum, 23, 23, true },
-    { kVideoTrackNum, 33, 33, true },
+    { kVideoTrackNum, 33, 34, true },
     { kSubtitleTextTrackNum,  33, 42, false },
     { kAudioTrackNum, 46, 23, true },
     { kCaptionTextTrackNum, 55, 44, false },
-    { kVideoTrackNum, 67, 33, true },
+    { kVideoTrackNum, 67, 34, true },
     { kSubtitleTextTrackNum,  67, 33, false },
   };
   int input_block_count = arraysize(kInputBlockInfo);
@@ -498,7 +502,9 @@
 
   parser_.reset(new WebMClusterParser(kTimecodeScale,
                                       kAudioTrackNum,
+                                      kNoTimestamp(),
                                       kVideoTrackNum,
+                                      kNoTimestamp(),
                                       WebMTracksParser::TextTracks(),
                                       std::set<int64>(),
                                       std::string(),
@@ -506,8 +512,8 @@
                                       LogCB()));
   int result = parser_->Parse(cluster->data(), cluster->size());
   EXPECT_EQ(cluster->size(), result);
-  ASSERT_EQ(1UL, parser_->video_buffers().size());
-  scoped_refptr<StreamParserBuffer> buffer = parser_->video_buffers()[0];
+  ASSERT_EQ(1UL, parser_->GetVideoBuffers().size());
+  scoped_refptr<StreamParserBuffer> buffer = parser_->GetVideoBuffers()[0];
   VerifyEncryptedBuffer(buffer);
 }
 
@@ -517,7 +523,9 @@
 
   parser_.reset(new WebMClusterParser(kTimecodeScale,
                                       kAudioTrackNum,
+                                      kNoTimestamp(),
                                       kVideoTrackNum,
+                                      kNoTimestamp(),
                                       WebMTracksParser::TextTracks(),
                                       std::set<int64>(),
                                       std::string(),
diff --git a/media/formats/webm/webm_stream_parser.cc b/media/formats/webm/webm_stream_parser.cc
index eae0371..1a49c66 100644
--- a/media/formats/webm/webm_stream_parser.cc
+++ b/media/formats/webm/webm_stream_parser.cc
@@ -180,11 +180,11 @@
 
   bytes_parsed += result;
 
+  double timecode_scale_in_us = info_parser.timecode_scale() / 1000.0;
   base::TimeDelta duration = kInfiniteDuration();
 
   if (info_parser.duration() > 0) {
-    double mult = info_parser.timecode_scale() / 1000.0;
-    int64 duration_in_us = info_parser.duration() * mult;
+    int64 duration_in_us = info_parser.duration() * timecode_scale_in_us;
     duration = base::TimeDelta::FromMicroseconds(duration_in_us);
   }
 
@@ -203,10 +203,13 @@
     return -1;
   }
 
+
   cluster_parser_.reset(new WebMClusterParser(
       info_parser.timecode_scale(),
       tracks_parser.audio_track_num(),
+      tracks_parser.GetAudioDefaultDuration(timecode_scale_in_us),
       tracks_parser.video_track_num(),
+      tracks_parser.GetVideoDefaultDuration(timecode_scale_in_us),
       tracks_parser.text_tracks(),
       tracks_parser.ignored_tracks(),
       tracks_parser.audio_encryption_key_id(),
@@ -263,9 +266,10 @@
     new_segment_cb_.Run();
   }
 
-  const BufferQueue& audio_buffers = cluster_parser_->audio_buffers();
-  const BufferQueue& video_buffers = cluster_parser_->video_buffers();
+  const BufferQueue& audio_buffers = cluster_parser_->GetAudioBuffers();
+  const BufferQueue& video_buffers = cluster_parser_->GetVideoBuffers();
   const TextBufferQueueMap& text_map = cluster_parser_->GetTextBuffers();
+
   bool cluster_ended = cluster_parser_->cluster_ended();
 
   if ((!audio_buffers.empty() || !video_buffers.empty() || !text_map.empty()) &&
diff --git a/media/formats/webm/webm_tracks_parser.cc b/media/formats/webm/webm_tracks_parser.cc
index 01fc83b..ed7fd52 100644
--- a/media/formats/webm/webm_tracks_parser.cc
+++ b/media/formats/webm/webm_tracks_parser.cc
@@ -29,14 +29,31 @@
   return kTextNone;
 }
 
+static base::TimeDelta PrecisionCappedDefaultDuration(
+    const double timecode_scale_in_us, const int64 duration_in_ns) {
+  if (duration_in_ns <= 0)
+    return kNoTimestamp();
+
+  int64 mult = duration_in_ns / 1000;
+  mult /= timecode_scale_in_us;
+  if (mult == 0)
+    return kNoTimestamp();
+
+  mult = static_cast<double>(mult) * timecode_scale_in_us;
+  return base::TimeDelta::FromMicroseconds(mult);
+}
+
 WebMTracksParser::WebMTracksParser(const LogCB& log_cb, bool ignore_text_tracks)
     : track_type_(-1),
       track_num_(-1),
       track_uid_(-1),
       seek_preroll_(-1),
       codec_delay_(-1),
+      default_duration_(-1),
       audio_track_num_(-1),
+      audio_default_duration_(-1),
       video_track_num_(-1),
+      video_default_duration_(-1),
       ignore_text_tracks_(ignore_text_tracks),
       log_cb_(log_cb),
       audio_client_(log_cb),
@@ -49,11 +66,14 @@
   track_type_ =-1;
   track_num_ = -1;
   track_uid_ = -1;
+  default_duration_ = -1;
   track_name_.clear();
   track_language_.clear();
   audio_track_num_ = -1;
+  audio_default_duration_ = -1;
   audio_decoder_config_ = AudioDecoderConfig();
   video_track_num_ = -1;
+  video_default_duration_ = -1;
   video_decoder_config_ = VideoDecoderConfig();
   text_tracks_.clear();
   ignored_tracks_.clear();
@@ -68,6 +88,18 @@
   return parser.IsParsingComplete() ? result : 0;
 }
 
+base::TimeDelta WebMTracksParser::GetAudioDefaultDuration(
+    const double timecode_scale_in_us) const {
+  return PrecisionCappedDefaultDuration(timecode_scale_in_us,
+                                        audio_default_duration_);
+}
+
+base::TimeDelta WebMTracksParser::GetVideoDefaultDuration(
+    const double timecode_scale_in_us) const {
+  return PrecisionCappedDefaultDuration(timecode_scale_in_us,
+                                        video_default_duration_);
+}
+
 WebMParserClient* WebMTracksParser::OnListStart(int id) {
   if (id == kWebMIdContentEncodings) {
     DCHECK(!track_content_encodings_client_.get());
@@ -79,6 +111,7 @@
   if (id == kWebMIdTrackEntry) {
     track_type_ = -1;
     track_num_ = -1;
+    default_duration_ = -1;
     track_name_.clear();
     track_language_.clear();
     codec_id_ = "";
@@ -165,6 +198,12 @@
         audio_track_num_ = track_num_;
         audio_encryption_key_id_ = encryption_key_id;
 
+        if (default_duration_ == 0) {
+          MEDIA_LOG(log_cb_) << "Illegal 0ns audio TrackEntry DefaultDuration";
+          return false;
+        }
+        audio_default_duration_ = default_duration_;
+
         DCHECK(!audio_decoder_config_.IsValidConfig());
         if (!audio_client_.InitializeConfig(
                 codec_id_, codec_private_, seek_preroll_, codec_delay_,
@@ -180,6 +219,12 @@
         video_track_num_ = track_num_;
         video_encryption_key_id_ = encryption_key_id;
 
+        if (default_duration_ == 0) {
+          MEDIA_LOG(log_cb_) << "Illegal 0ns video TrackEntry DefaultDuration";
+          return false;
+        }
+        video_default_duration_ = default_duration_;
+
         DCHECK(!video_decoder_config_.IsValidConfig());
         if (!video_client_.InitializeConfig(
                 codec_id_, codec_private_, !video_encryption_key_id_.empty(),
@@ -210,6 +255,7 @@
     track_type_ = -1;
     track_num_ = -1;
     track_uid_ = -1;
+    default_duration_ = -1;
     track_name_.clear();
     track_language_.clear();
     codec_id_ = "";
@@ -243,6 +289,9 @@
     case kWebMIdCodecDelay:
       dst = &codec_delay_;
       break;
+    case kWebMIdDefaultDuration:
+      dst = &default_duration_;
+      break;
     default:
       return true;
   }
diff --git a/media/formats/webm/webm_tracks_parser.h b/media/formats/webm/webm_tracks_parser.h
index 4ace29d..61d79af 100644
--- a/media/formats/webm/webm_tracks_parser.h
+++ b/media/formats/webm/webm_tracks_parser.h
@@ -12,6 +12,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
+#include "base/time/time.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/media_log.h"
 #include "media/base/text_track_config.h"
@@ -38,6 +39,16 @@
 
   int64 audio_track_num() const { return audio_track_num_; }
   int64 video_track_num() const { return video_track_num_; }
+
+  // If TrackEntry DefaultDuration field existed for the associated audio or
+  // video track, returns that value converted from ns to base::TimeDelta with
+  // precision not greater than |timecode_scale_in_us|. Defaults to
+  // kNoTimestamp().
+  base::TimeDelta GetAudioDefaultDuration(
+      const double timecode_scale_in_us) const;
+  base::TimeDelta GetVideoDefaultDuration(
+      const double timecode_scale_in_us) const;
+
   const std::set<int64>& ignored_tracks() const { return ignored_tracks_; }
 
   const std::string& audio_encryption_key_id() const {
@@ -80,10 +91,13 @@
   std::vector<uint8> codec_private_;
   int64 seek_preroll_;
   int64 codec_delay_;
+  int64 default_duration_;
   scoped_ptr<WebMContentEncodingsClient> track_content_encodings_client_;
 
   int64 audio_track_num_;
+  int64 audio_default_duration_;
   int64 video_track_num_;
+  int64 video_default_duration_;
   bool ignore_text_tracks_;
   TextTracks text_tracks_;
   std::set<int64> ignored_tracks_;
diff --git a/media/formats/webm/webm_tracks_parser_unittest.cc b/media/formats/webm/webm_tracks_parser_unittest.cc
index 0f8e351..b81aa21 100644
--- a/media/formats/webm/webm_tracks_parser_unittest.cc
+++ b/media/formats/webm/webm_tracks_parser_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/logging.h"
+#include "media/base/channel_layout.h"
 #include "media/formats/webm/tracks_builder.h"
 #include "media/formats/webm/webm_constants.h"
 #include "media/formats/webm/webm_tracks_parser.h"
@@ -15,6 +16,8 @@
 
 namespace media {
 
+static const double kDefaultTimecodeScaleInUs = 1000.0;  // 1 ms resolution
+
 class WebMTracksParserTest : public testing::Test {
  public:
   WebMTracksParserTest() {}
@@ -47,8 +50,7 @@
   InSequence s;
 
   TracksBuilder tb;
-  tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions, 1,
-              kWebMCodecSubtitles, "", "");
+  tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", "");
 
   const std::vector<uint8> buf = tb.Finish();
   VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "");
@@ -58,8 +60,7 @@
   InSequence s;
 
   TracksBuilder tb;
-  tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions, 1,
-              kWebMCodecSubtitles, "Spock", "");
+  tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Spock", "");
 
   const std::vector<uint8> buf = tb.Finish();
   VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Spock", "");
@@ -69,8 +70,7 @@
   InSequence s;
 
   TracksBuilder tb;
-  tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions, 1,
-              kWebMCodecSubtitles, "", "eng");
+  tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "", "eng");
 
   const std::vector<uint8> buf = tb.Finish();
   VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "", "eng");
@@ -80,8 +80,7 @@
   InSequence s;
 
   TracksBuilder tb;
-  tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions, 1,
-              kWebMCodecSubtitles, "Picard", "fre");
+  tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Picard", "fre");
 
   const std::vector<uint8> buf = tb.Finish();
   VerifyTextTrackInfo(&buf[0], buf.size(), kTextSubtitles, "Picard", "fre");
@@ -91,10 +90,8 @@
   InSequence s;
 
   TracksBuilder tb;
-  tb.AddTrack(1, kWebMTrackTypeSubtitlesOrCaptions, 1,
-              kWebMCodecSubtitles, "Subtitles", "fre");
-  tb.AddTrack(2, kWebMTrackTypeSubtitlesOrCaptions, 2,
-              kWebMCodecSubtitles, "Commentary", "fre");
+  tb.AddTextTrack(1, 1, kWebMCodecSubtitles, "Subtitles", "fre");
+  tb.AddTextTrack(2, 2, kWebMCodecSubtitles, "Commentary", "fre");
 
   const std::vector<uint8> buf = tb.Finish();
   scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true));
@@ -119,4 +116,70 @@
   EXPECT_EQ(parser->text_tracks().size(), 2u);
 }
 
+TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationUnset) {
+  // Other audio/video decoder config fields are necessary in the test
+  // audio/video TrackEntry configurations. This method does only very minimal
+  // verification of their inclusion and parsing; the goal is to confirm
+  // TrackEntry DefaultDuration defaults to -1 if not included in audio or
+  // video TrackEntry.
+  TracksBuilder tb;
+  tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", -1, 2, 8000);
+  tb.AddVideoTrack(2, 2, "V_VP8", "video", "", -1, 320, 240);
+  const std::vector<uint8> buf = tb.Finish();
+
+  scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true));
+  int result = parser->Parse(&buf[0], buf.size());
+  EXPECT_LE(0, result);
+  EXPECT_EQ(static_cast<int>(buf.size()), result);
+
+  EXPECT_EQ(kNoTimestamp(),
+            parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs));
+  EXPECT_EQ(kNoTimestamp(),
+            parser->GetVideoDefaultDuration(kDefaultTimecodeScaleInUs));
+
+  const VideoDecoderConfig& video_config = parser->video_decoder_config();
+  EXPECT_TRUE(video_config.IsValidConfig());
+  EXPECT_EQ(320, video_config.coded_size().width());
+  EXPECT_EQ(240, video_config.coded_size().height());
+
+  const AudioDecoderConfig& audio_config = parser->audio_decoder_config();
+  EXPECT_TRUE(audio_config.IsValidConfig());
+  EXPECT_EQ(CHANNEL_LAYOUT_STEREO, audio_config.channel_layout());
+  EXPECT_EQ(8000, audio_config.samples_per_second());
+}
+
+TEST_F(WebMTracksParserTest, AudioVideoDefaultDurationSet) {
+  // Confirm audio or video TrackEntry DefaultDuration values are parsed, if
+  // present.
+  TracksBuilder tb;
+  tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 12345678, 2, 8000);
+  tb.AddVideoTrack(2, 2, "V_VP8", "video", "", 987654321, 320, 240);
+  const std::vector<uint8> buf = tb.Finish();
+
+  scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true));
+  int result = parser->Parse(&buf[0], buf.size());
+  EXPECT_LE(0, result);
+  EXPECT_EQ(static_cast<int>(buf.size()), result);
+
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(12000),
+            parser->GetAudioDefaultDuration(kDefaultTimecodeScaleInUs));
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(985000),
+            parser->GetVideoDefaultDuration(5000.0));  // 5 ms resolution
+  EXPECT_EQ(kNoTimestamp(), parser->GetAudioDefaultDuration(12346.0));
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(12345),
+            parser->GetAudioDefaultDuration(12345.0));
+  EXPECT_EQ(base::TimeDelta::FromMicroseconds(12003),
+            parser->GetAudioDefaultDuration(1000.3));  // 1.0003 ms resolution
+}
+
+TEST_F(WebMTracksParserTest, InvalidZeroDefaultDurationSet) {
+  // Confirm parse error if TrackEntry DefaultDuration is present, but is 0ns.
+  TracksBuilder tb(true);
+  tb.AddAudioTrack(1, 1, "A_VORBIS", "audio", "", 0, 2, 8000);
+  const std::vector<uint8> buf = tb.Finish();
+
+  scoped_ptr<WebMTracksParser> parser(new WebMTracksParser(LogCB(), true));
+  EXPECT_EQ(-1, parser->Parse(&buf[0], buf.size()));
+}
+
 }  // namespace media
diff --git a/media/media.gyp b/media/media.gyp
index e12c04e..d439453 100644
--- a/media/media.gyp
+++ b/media/media.gyp
@@ -210,6 +210,8 @@
         'base/audio_buffer_queue.cc',
         'base/audio_buffer_queue.h',
         'base/audio_capturer_source.h',
+        'base/audio_buffer_converter.cc',
+        'base/audio_buffer_converter.h',
         'base/audio_converter.cc',
         'base/audio_converter.h',
         'base/audio_decoder.cc',
@@ -410,8 +412,6 @@
         'filters/source_buffer_stream.h',
         'filters/stream_parser_factory.cc',
         'filters/stream_parser_factory.h',
-        'filters/video_frame_painter.cc',
-        'filters/video_frame_painter.h',
         'filters/video_renderer_impl.cc',
         'filters/video_renderer_impl.h',
         'filters/vpx_video_decoder.cc',
@@ -952,6 +952,7 @@
         'base/android/media_codec_bridge_unittest.cc',
         'base/android/media_drm_bridge_unittest.cc',
         'base/android/media_source_player_unittest.cc',
+        'base/audio_buffer_converter_unittest.cc',
         'base/audio_buffer_unittest.cc',
         'base/audio_buffer_queue_unittest.cc',
         'base/audio_bus_unittest.cc',
@@ -1028,7 +1029,6 @@
         'filters/skcanvas_video_renderer_unittest.cc',
         'filters/source_buffer_stream_unittest.cc',
         'filters/video_decoder_selector_unittest.cc',
-        'filters/video_frame_painter_unittest.cc',
         'filters/video_frame_stream_unittest.cc',
         'filters/video_renderer_impl_unittest.cc',
         'midi/midi_manager_usb_unittest.cc',
@@ -1458,6 +1458,7 @@
           'type': 'executable',
           'dependencies': [
             'media',
+	    'shared_memory_support',
             '../base/base.gyp:base',
             '../ui/gl/gl.gyp:gl',
             '../ui/gfx/gfx.gyp:gfx',
@@ -1672,6 +1673,7 @@
             '../testing/gmock.gyp:gmock',
             '../testing/gtest.gyp:gtest',
             '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+            '../ui/gfx/gfx.gyp:gfx_geometry',
             'media',
             'media_test_support',
           ],
diff --git a/media/media.target.darwin-arm.mk b/media/media.target.darwin-arm.mk
index 903198a..a06a797 100644
--- a/media/media.target.darwin-arm.mk
+++ b/media/media.target.darwin-arm.mk
@@ -67,6 +67,7 @@
 	media/base/android/media_resource_getter.cc \
 	media/base/audio_buffer.cc \
 	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
 	media/base/audio_converter.cc \
 	media/base/audio_decoder.cc \
 	media/base/audio_decoder_config.cc \
@@ -147,7 +148,6 @@
 	media/filters/skcanvas_video_renderer.cc \
 	media/filters/source_buffer_stream.cc \
 	media/filters/stream_parser_factory.cc \
-	media/filters/video_frame_painter.cc \
 	media/filters/video_renderer_impl.cc \
 	media/filters/wsola_internals.cc \
 	media/midi/midi_manager.cc \
@@ -267,9 +267,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -278,6 +276,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -391,9 +390,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -402,6 +399,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media.target.darwin-mips.mk b/media/media.target.darwin-mips.mk
index 66a6f71..a3fecf3 100644
--- a/media/media.target.darwin-mips.mk
+++ b/media/media.target.darwin-mips.mk
@@ -67,6 +67,7 @@
 	media/base/android/media_resource_getter.cc \
 	media/base/audio_buffer.cc \
 	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
 	media/base/audio_converter.cc \
 	media/base/audio_decoder.cc \
 	media/base/audio_decoder_config.cc \
@@ -147,7 +148,6 @@
 	media/filters/skcanvas_video_renderer.cc \
 	media/filters/source_buffer_stream.cc \
 	media/filters/stream_parser_factory.cc \
-	media/filters/video_frame_painter.cc \
 	media/filters/video_renderer_impl.cc \
 	media/filters/wsola_internals.cc \
 	media/midi/midi_manager.cc \
@@ -266,9 +266,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -277,6 +275,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -389,9 +388,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -400,6 +397,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media.target.darwin-x86.mk b/media/media.target.darwin-x86.mk
index 30f995e..9adf2f2 100644
--- a/media/media.target.darwin-x86.mk
+++ b/media/media.target.darwin-x86.mk
@@ -67,6 +67,7 @@
 	media/base/android/media_resource_getter.cc \
 	media/base/audio_buffer.cc \
 	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
 	media/base/audio_converter.cc \
 	media/base/audio_decoder.cc \
 	media/base/audio_decoder_config.cc \
@@ -147,7 +148,6 @@
 	media/filters/skcanvas_video_renderer.cc \
 	media/filters/source_buffer_stream.cc \
 	media/filters/stream_parser_factory.cc \
-	media/filters/video_frame_painter.cc \
 	media/filters/video_renderer_impl.cc \
 	media/filters/wsola_internals.cc \
 	media/midi/midi_manager.cc \
@@ -269,9 +269,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -280,6 +278,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -393,9 +392,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -404,6 +401,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media.target.darwin-x86_64.mk b/media/media.target.darwin-x86_64.mk
new file mode 100644
index 0000000..612d510
--- /dev/null
+++ b/media/media.target.darwin-x86_64.mk
@@ -0,0 +1,517 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,media_media_android_jni_headers_gyp)/media_android_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,media_video_capture_android_jni_headers_gyp)/video_capture_android_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/audio/android/audio_manager_android.cc \
+	media/audio/android/audio_record_input.cc \
+	media/audio/android/opensles_input.cc \
+	media/audio/android/opensles_output.cc \
+	media/audio/android/opensles_wrapper.cc \
+	media/audio/audio_buffers_state.cc \
+	media/audio/audio_device_name.cc \
+	media/audio/audio_device_thread.cc \
+	media/audio/audio_input_controller.cc \
+	media/audio/audio_input_device.cc \
+	media/audio/audio_input_ipc.cc \
+	media/audio/audio_manager.cc \
+	media/audio/audio_manager_base.cc \
+	media/audio/audio_output_controller.cc \
+	media/audio/audio_output_device.cc \
+	media/audio/audio_output_dispatcher.cc \
+	media/audio/audio_output_dispatcher_impl.cc \
+	media/audio/audio_output_ipc.cc \
+	media/audio/audio_output_proxy.cc \
+	media/audio/audio_output_resampler.cc \
+	media/audio/audio_power_monitor.cc \
+	media/audio/clockless_audio_sink.cc \
+	media/audio/fake_audio_consumer.cc \
+	media/audio/fake_audio_input_stream.cc \
+	media/audio/fake_audio_log_factory.cc \
+	media/audio/fake_audio_manager.cc \
+	media/audio/fake_audio_output_stream.cc \
+	media/audio/null_audio_sink.cc \
+	media/audio/sample_rates.cc \
+	media/audio/scoped_task_runner_observer.cc \
+	media/audio/simple_sources.cc \
+	media/audio/sounds/audio_stream_handler.cc \
+	media/audio/sounds/sounds_manager.cc \
+	media/audio/sounds/wav_audio_handler.cc \
+	media/audio/virtual_audio_input_stream.cc \
+	media/audio/virtual_audio_output_stream.cc \
+	media/base/android/demuxer_stream_player_params.cc \
+	media/base/android/media_resource_getter.cc \
+	media/base/audio_buffer.cc \
+	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
+	media/base/audio_converter.cc \
+	media/base/audio_decoder.cc \
+	media/base/audio_decoder_config.cc \
+	media/base/audio_fifo.cc \
+	media/base/audio_hardware_config.cc \
+	media/base/audio_hash.cc \
+	media/base/audio_pull_fifo.cc \
+	media/base/audio_renderer.cc \
+	media/base/audio_renderer_mixer.cc \
+	media/base/audio_renderer_mixer_input.cc \
+	media/base/audio_splicer.cc \
+	media/base/audio_timestamp_helper.cc \
+	media/base/bit_reader.cc \
+	media/base/bit_reader_core.cc \
+	media/base/byte_queue.cc \
+	media/base/channel_mixer.cc \
+	media/base/clock.cc \
+	media/base/data_buffer.cc \
+	media/base/data_source.cc \
+	media/base/decoder_buffer.cc \
+	media/base/decoder_buffer_queue.cc \
+	media/base/decrypt_config.cc \
+	media/base/decryptor.cc \
+	media/base/demuxer.cc \
+	media/base/demuxer_stream.cc \
+	media/base/djb2.cc \
+	media/base/filter_collection.cc \
+	media/base/media.cc \
+	media/base/media_keys.cc \
+	media/base/media_log.cc \
+	media/base/media_switches.cc \
+	media/base/multi_channel_resampler.cc \
+	media/base/pipeline.cc \
+	media/base/ranges.cc \
+	media/base/sample_format.cc \
+	media/base/seekable_buffer.cc \
+	media/base/serial_runner.cc \
+	media/base/simd/convert_rgb_to_yuv_c.cc \
+	media/base/simd/convert_yuv_to_rgb_c.cc \
+	media/base/simd/filter_yuv_c.cc \
+	media/base/simd/yuv_to_rgb_table.cc \
+	media/base/sinc_resampler.cc \
+	media/base/stream_parser.cc \
+	media/base/stream_parser_buffer.cc \
+	media/base/text_cue.cc \
+	media/base/text_ranges.cc \
+	media/base/text_renderer.cc \
+	media/base/text_track_config.cc \
+	media/base/user_input_monitor.cc \
+	media/base/video_decoder.cc \
+	media/base/video_decoder_config.cc \
+	media/base/video_frame.cc \
+	media/base/video_frame_pool.cc \
+	media/base/video_renderer.cc \
+	media/base/video_util.cc \
+	media/base/yuv_convert.cc \
+	media/cdm/aes_decryptor.cc \
+	media/cdm/json_web_key.cc \
+	media/cdm/key_system_names.cc \
+	media/filters/audio_renderer_algorithm.cc \
+	media/filters/audio_renderer_impl.cc \
+	media/filters/chunk_demuxer.cc \
+	media/filters/decoder_selector.cc \
+	media/filters/decoder_stream.cc \
+	media/filters/decoder_stream_traits.cc \
+	media/filters/decrypting_audio_decoder.cc \
+	media/filters/decrypting_demuxer_stream.cc \
+	media/filters/decrypting_video_decoder.cc \
+	media/filters/file_data_source.cc \
+	media/filters/frame_processor_base.cc \
+	media/filters/gpu_video_accelerator_factories.cc \
+	media/filters/gpu_video_decoder.cc \
+	media/filters/h264_bit_reader.cc \
+	media/filters/h264_parser.cc \
+	media/filters/h264_to_annex_b_bitstream_converter.cc \
+	media/filters/in_memory_url_protocol.cc \
+	media/filters/legacy_frame_processor.cc \
+	media/filters/skcanvas_video_renderer.cc \
+	media/filters/source_buffer_stream.cc \
+	media/filters/stream_parser_factory.cc \
+	media/filters/video_renderer_impl.cc \
+	media/filters/wsola_internals.cc \
+	media/midi/midi_manager.cc \
+	media/midi/midi_manager_android.cc \
+	media/midi/midi_manager_usb.cc \
+	media/midi/midi_message_queue.cc \
+	media/midi/midi_message_util.cc \
+	media/midi/midi_port_info.cc \
+	media/midi/usb_midi_descriptor_parser.cc \
+	media/midi/usb_midi_device_android.cc \
+	media/midi/usb_midi_device_factory_android.cc \
+	media/midi/usb_midi_input_stream.cc \
+	media/midi/usb_midi_output_stream.cc \
+	media/video/capture/android/video_capture_device_android.cc \
+	media/video/capture/fake_video_capture_device.cc \
+	media/video/capture/file_video_capture_device.cc \
+	media/video/capture/video_capture_device.cc \
+	media/video/capture/video_capture_proxy.cc \
+	media/video/capture/video_capture_types.cc \
+	media/video/picture.cc \
+	media/video/video_decode_accelerator.cc \
+	media/video/video_encode_accelerator.cc \
+	media/formats/common/offset_byte_queue.cc \
+	media/formats/webm/webm_audio_client.cc \
+	media/formats/webm/webm_cluster_parser.cc \
+	media/formats/webm/webm_constants.cc \
+	media/formats/webm/webm_content_encodings.cc \
+	media/formats/webm/webm_content_encodings_client.cc \
+	media/formats/webm/webm_crypto_helpers.cc \
+	media/formats/webm/webm_info_parser.cc \
+	media/formats/webm/webm_parser.cc \
+	media/formats/webm/webm_stream_parser.cc \
+	media/formats/webm/webm_tracks_parser.cc \
+	media/formats/webm/webm_video_client.cc \
+	media/formats/webm/webm_webvtt_parser.cc \
+	media/base/media_stub.cc \
+	media/formats/mp2t/es_parser_adts.cc \
+	media/formats/mp2t/es_parser_h264.cc \
+	media/formats/mp2t/mp2t_stream_parser.cc \
+	media/formats/mp2t/ts_packet.cc \
+	media/formats/mp2t/ts_section_pat.cc \
+	media/formats/mp2t/ts_section_pes.cc \
+	media/formats/mp2t/ts_section_pmt.cc \
+	media/formats/mp2t/ts_section_psi.cc \
+	media/formats/mp4/aac.cc \
+	media/formats/mp4/avc.cc \
+	media/formats/mp4/box_definitions.cc \
+	media/formats/mp4/box_reader.cc \
+	media/formats/mp4/cenc.cc \
+	media/formats/mp4/es_descriptor.cc \
+	media/formats/mp4/mp4_stream_parser.cc \
+	media/formats/mp4/track_run_iterator.cc \
+	media/formats/mpeg/adts_constants.cc \
+	media/formats/mpeg/adts_stream_parser.cc \
+	media/formats/mpeg/mp3_stream_parser.cc \
+	media/formats/mpeg/mpeg_audio_stream_parser_base.cc \
+	media/base/simd/convert_yuv_to_rgb_x86.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DDISABLE_USER_INPUT_MONITOR' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DDISABLE_USER_INPUT_MONITOR' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_gyp
+
+# Alias gyp target name.
+.PHONY: media
+media: media_media_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media.target.linux-arm.mk b/media/media.target.linux-arm.mk
index 903198a..a06a797 100644
--- a/media/media.target.linux-arm.mk
+++ b/media/media.target.linux-arm.mk
@@ -67,6 +67,7 @@
 	media/base/android/media_resource_getter.cc \
 	media/base/audio_buffer.cc \
 	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
 	media/base/audio_converter.cc \
 	media/base/audio_decoder.cc \
 	media/base/audio_decoder_config.cc \
@@ -147,7 +148,6 @@
 	media/filters/skcanvas_video_renderer.cc \
 	media/filters/source_buffer_stream.cc \
 	media/filters/stream_parser_factory.cc \
-	media/filters/video_frame_painter.cc \
 	media/filters/video_renderer_impl.cc \
 	media/filters/wsola_internals.cc \
 	media/midi/midi_manager.cc \
@@ -267,9 +267,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -278,6 +276,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -391,9 +390,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -402,6 +399,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media.target.linux-mips.mk b/media/media.target.linux-mips.mk
index 66a6f71..a3fecf3 100644
--- a/media/media.target.linux-mips.mk
+++ b/media/media.target.linux-mips.mk
@@ -67,6 +67,7 @@
 	media/base/android/media_resource_getter.cc \
 	media/base/audio_buffer.cc \
 	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
 	media/base/audio_converter.cc \
 	media/base/audio_decoder.cc \
 	media/base/audio_decoder_config.cc \
@@ -147,7 +148,6 @@
 	media/filters/skcanvas_video_renderer.cc \
 	media/filters/source_buffer_stream.cc \
 	media/filters/stream_parser_factory.cc \
-	media/filters/video_frame_painter.cc \
 	media/filters/video_renderer_impl.cc \
 	media/filters/wsola_internals.cc \
 	media/midi/midi_manager.cc \
@@ -266,9 +266,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -277,6 +275,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -389,9 +388,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -400,6 +397,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media.target.linux-x86.mk b/media/media.target.linux-x86.mk
index 30f995e..9adf2f2 100644
--- a/media/media.target.linux-x86.mk
+++ b/media/media.target.linux-x86.mk
@@ -67,6 +67,7 @@
 	media/base/android/media_resource_getter.cc \
 	media/base/audio_buffer.cc \
 	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
 	media/base/audio_converter.cc \
 	media/base/audio_decoder.cc \
 	media/base/audio_decoder_config.cc \
@@ -147,7 +148,6 @@
 	media/filters/skcanvas_video_renderer.cc \
 	media/filters/source_buffer_stream.cc \
 	media/filters/stream_parser_factory.cc \
-	media/filters/video_frame_painter.cc \
 	media/filters/video_renderer_impl.cc \
 	media/filters/wsola_internals.cc \
 	media/midi/midi_manager.cc \
@@ -269,9 +269,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -280,6 +278,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -393,9 +392,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -404,6 +401,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media.target.linux-x86_64.mk b/media/media.target.linux-x86_64.mk
new file mode 100644
index 0000000..612d510
--- /dev/null
+++ b/media/media.target.linux-x86_64.mk
@@ -0,0 +1,517 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,media_media_android_jni_headers_gyp)/media_android_jni_headers.stamp \
+	$(call intermediates-dir-for,GYP,media_video_capture_android_jni_headers_gyp)/video_capture_android_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/audio/android/audio_manager_android.cc \
+	media/audio/android/audio_record_input.cc \
+	media/audio/android/opensles_input.cc \
+	media/audio/android/opensles_output.cc \
+	media/audio/android/opensles_wrapper.cc \
+	media/audio/audio_buffers_state.cc \
+	media/audio/audio_device_name.cc \
+	media/audio/audio_device_thread.cc \
+	media/audio/audio_input_controller.cc \
+	media/audio/audio_input_device.cc \
+	media/audio/audio_input_ipc.cc \
+	media/audio/audio_manager.cc \
+	media/audio/audio_manager_base.cc \
+	media/audio/audio_output_controller.cc \
+	media/audio/audio_output_device.cc \
+	media/audio/audio_output_dispatcher.cc \
+	media/audio/audio_output_dispatcher_impl.cc \
+	media/audio/audio_output_ipc.cc \
+	media/audio/audio_output_proxy.cc \
+	media/audio/audio_output_resampler.cc \
+	media/audio/audio_power_monitor.cc \
+	media/audio/clockless_audio_sink.cc \
+	media/audio/fake_audio_consumer.cc \
+	media/audio/fake_audio_input_stream.cc \
+	media/audio/fake_audio_log_factory.cc \
+	media/audio/fake_audio_manager.cc \
+	media/audio/fake_audio_output_stream.cc \
+	media/audio/null_audio_sink.cc \
+	media/audio/sample_rates.cc \
+	media/audio/scoped_task_runner_observer.cc \
+	media/audio/simple_sources.cc \
+	media/audio/sounds/audio_stream_handler.cc \
+	media/audio/sounds/sounds_manager.cc \
+	media/audio/sounds/wav_audio_handler.cc \
+	media/audio/virtual_audio_input_stream.cc \
+	media/audio/virtual_audio_output_stream.cc \
+	media/base/android/demuxer_stream_player_params.cc \
+	media/base/android/media_resource_getter.cc \
+	media/base/audio_buffer.cc \
+	media/base/audio_buffer_queue.cc \
+	media/base/audio_buffer_converter.cc \
+	media/base/audio_converter.cc \
+	media/base/audio_decoder.cc \
+	media/base/audio_decoder_config.cc \
+	media/base/audio_fifo.cc \
+	media/base/audio_hardware_config.cc \
+	media/base/audio_hash.cc \
+	media/base/audio_pull_fifo.cc \
+	media/base/audio_renderer.cc \
+	media/base/audio_renderer_mixer.cc \
+	media/base/audio_renderer_mixer_input.cc \
+	media/base/audio_splicer.cc \
+	media/base/audio_timestamp_helper.cc \
+	media/base/bit_reader.cc \
+	media/base/bit_reader_core.cc \
+	media/base/byte_queue.cc \
+	media/base/channel_mixer.cc \
+	media/base/clock.cc \
+	media/base/data_buffer.cc \
+	media/base/data_source.cc \
+	media/base/decoder_buffer.cc \
+	media/base/decoder_buffer_queue.cc \
+	media/base/decrypt_config.cc \
+	media/base/decryptor.cc \
+	media/base/demuxer.cc \
+	media/base/demuxer_stream.cc \
+	media/base/djb2.cc \
+	media/base/filter_collection.cc \
+	media/base/media.cc \
+	media/base/media_keys.cc \
+	media/base/media_log.cc \
+	media/base/media_switches.cc \
+	media/base/multi_channel_resampler.cc \
+	media/base/pipeline.cc \
+	media/base/ranges.cc \
+	media/base/sample_format.cc \
+	media/base/seekable_buffer.cc \
+	media/base/serial_runner.cc \
+	media/base/simd/convert_rgb_to_yuv_c.cc \
+	media/base/simd/convert_yuv_to_rgb_c.cc \
+	media/base/simd/filter_yuv_c.cc \
+	media/base/simd/yuv_to_rgb_table.cc \
+	media/base/sinc_resampler.cc \
+	media/base/stream_parser.cc \
+	media/base/stream_parser_buffer.cc \
+	media/base/text_cue.cc \
+	media/base/text_ranges.cc \
+	media/base/text_renderer.cc \
+	media/base/text_track_config.cc \
+	media/base/user_input_monitor.cc \
+	media/base/video_decoder.cc \
+	media/base/video_decoder_config.cc \
+	media/base/video_frame.cc \
+	media/base/video_frame_pool.cc \
+	media/base/video_renderer.cc \
+	media/base/video_util.cc \
+	media/base/yuv_convert.cc \
+	media/cdm/aes_decryptor.cc \
+	media/cdm/json_web_key.cc \
+	media/cdm/key_system_names.cc \
+	media/filters/audio_renderer_algorithm.cc \
+	media/filters/audio_renderer_impl.cc \
+	media/filters/chunk_demuxer.cc \
+	media/filters/decoder_selector.cc \
+	media/filters/decoder_stream.cc \
+	media/filters/decoder_stream_traits.cc \
+	media/filters/decrypting_audio_decoder.cc \
+	media/filters/decrypting_demuxer_stream.cc \
+	media/filters/decrypting_video_decoder.cc \
+	media/filters/file_data_source.cc \
+	media/filters/frame_processor_base.cc \
+	media/filters/gpu_video_accelerator_factories.cc \
+	media/filters/gpu_video_decoder.cc \
+	media/filters/h264_bit_reader.cc \
+	media/filters/h264_parser.cc \
+	media/filters/h264_to_annex_b_bitstream_converter.cc \
+	media/filters/in_memory_url_protocol.cc \
+	media/filters/legacy_frame_processor.cc \
+	media/filters/skcanvas_video_renderer.cc \
+	media/filters/source_buffer_stream.cc \
+	media/filters/stream_parser_factory.cc \
+	media/filters/video_renderer_impl.cc \
+	media/filters/wsola_internals.cc \
+	media/midi/midi_manager.cc \
+	media/midi/midi_manager_android.cc \
+	media/midi/midi_manager_usb.cc \
+	media/midi/midi_message_queue.cc \
+	media/midi/midi_message_util.cc \
+	media/midi/midi_port_info.cc \
+	media/midi/usb_midi_descriptor_parser.cc \
+	media/midi/usb_midi_device_android.cc \
+	media/midi/usb_midi_device_factory_android.cc \
+	media/midi/usb_midi_input_stream.cc \
+	media/midi/usb_midi_output_stream.cc \
+	media/video/capture/android/video_capture_device_android.cc \
+	media/video/capture/fake_video_capture_device.cc \
+	media/video/capture/file_video_capture_device.cc \
+	media/video/capture/video_capture_device.cc \
+	media/video/capture/video_capture_proxy.cc \
+	media/video/capture/video_capture_types.cc \
+	media/video/picture.cc \
+	media/video/video_decode_accelerator.cc \
+	media/video/video_encode_accelerator.cc \
+	media/formats/common/offset_byte_queue.cc \
+	media/formats/webm/webm_audio_client.cc \
+	media/formats/webm/webm_cluster_parser.cc \
+	media/formats/webm/webm_constants.cc \
+	media/formats/webm/webm_content_encodings.cc \
+	media/formats/webm/webm_content_encodings_client.cc \
+	media/formats/webm/webm_crypto_helpers.cc \
+	media/formats/webm/webm_info_parser.cc \
+	media/formats/webm/webm_parser.cc \
+	media/formats/webm/webm_stream_parser.cc \
+	media/formats/webm/webm_tracks_parser.cc \
+	media/formats/webm/webm_video_client.cc \
+	media/formats/webm/webm_webvtt_parser.cc \
+	media/base/media_stub.cc \
+	media/formats/mp2t/es_parser_adts.cc \
+	media/formats/mp2t/es_parser_h264.cc \
+	media/formats/mp2t/mp2t_stream_parser.cc \
+	media/formats/mp2t/ts_packet.cc \
+	media/formats/mp2t/ts_section_pat.cc \
+	media/formats/mp2t/ts_section_pes.cc \
+	media/formats/mp2t/ts_section_pmt.cc \
+	media/formats/mp2t/ts_section_psi.cc \
+	media/formats/mp4/aac.cc \
+	media/formats/mp4/avc.cc \
+	media/formats/mp4/box_definitions.cc \
+	media/formats/mp4/box_reader.cc \
+	media/formats/mp4/cenc.cc \
+	media/formats/mp4/es_descriptor.cc \
+	media/formats/mp4/mp4_stream_parser.cc \
+	media/formats/mp4/track_run_iterator.cc \
+	media/formats/mpeg/adts_constants.cc \
+	media/formats/mpeg/adts_stream_parser.cc \
+	media/formats/mpeg/mp3_stream_parser.cc \
+	media/formats/mpeg/mpeg_audio_stream_parser_base.cc \
+	media/base/simd/convert_yuv_to_rgb_x86.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DDISABLE_USER_INPUT_MONITOR' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DDISABLE_USER_INPUT_MONITOR' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_gyp
+
+# Alias gyp target name.
+.PHONY: media
+media: media_media_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_android_imageformat_list.target.darwin-arm.mk b/media/media_android_imageformat_list.target.darwin-arm.mk
index 67f7eb1..5bfc4fd 100644
--- a/media/media_android_imageformat_list.target.darwin-arm.mk
+++ b/media/media_android_imageformat_list.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_imageformat_list.target.darwin-mips.mk b/media/media_android_imageformat_list.target.darwin-mips.mk
index 21515eb..024979a 100644
--- a/media/media_android_imageformat_list.target.darwin-mips.mk
+++ b/media/media_android_imageformat_list.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_imageformat_list.target.darwin-x86.mk b/media/media_android_imageformat_list.target.darwin-x86.mk
index a2f133c..bea533b 100644
--- a/media/media_android_imageformat_list.target.darwin-x86.mk
+++ b/media/media_android_imageformat_list.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_imageformat_list.target.darwin-x86_64.mk b/media/media_android_imageformat_list.target.darwin-x86_64.mk
new file mode 100644
index 0000000..8ac9f2d
--- /dev/null
+++ b/media/media_android_imageformat_list.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := media_media_android_imageformat_list_gyp
+LOCAL_MODULE_STEM := media_android_imageformat_list
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "media_media_gyp_media_android_imageformat_list_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'video/capture/android/imageformat_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/media/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/media/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['base/android/java/src/org/chromium/media/ImageFormat.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/media/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/ImageFormat.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/media/video/capture/android/imageformat_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/media; cd $(gyp_local_path)/media; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java" "--template=base/android/java/src/org/chromium/media/ImageFormat.template"
+
+.PHONY: media_media_android_imageformat_list_gyp_rule_trigger
+media_media_android_imageformat_list_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	media_media_android_imageformat_list_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_android_imageformat_list_gyp
+
+# Alias gyp target name.
+.PHONY: media_android_imageformat_list
+media_android_imageformat_list: media_media_android_imageformat_list_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/media/media_android_imageformat_list.target.linux-arm.mk b/media/media_android_imageformat_list.target.linux-arm.mk
index 67f7eb1..5bfc4fd 100644
--- a/media/media_android_imageformat_list.target.linux-arm.mk
+++ b/media/media_android_imageformat_list.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_imageformat_list.target.linux-mips.mk b/media/media_android_imageformat_list.target.linux-mips.mk
index 21515eb..024979a 100644
--- a/media/media_android_imageformat_list.target.linux-mips.mk
+++ b/media/media_android_imageformat_list.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_imageformat_list.target.linux-x86.mk b/media/media_android_imageformat_list.target.linux-x86.mk
index a2f133c..bea533b 100644
--- a/media/media_android_imageformat_list.target.linux-x86.mk
+++ b/media/media_android_imageformat_list.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_imageformat_list.target.linux-x86_64.mk b/media/media_android_imageformat_list.target.linux-x86_64.mk
new file mode 100644
index 0000000..8ac9f2d
--- /dev/null
+++ b/media/media_android_imageformat_list.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := media_media_android_imageformat_list_gyp
+LOCAL_MODULE_STEM := media_android_imageformat_list
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "media_media_gyp_media_android_imageformat_list_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'video/capture/android/imageformat_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/media/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/media/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['base/android/java/src/org/chromium/media/ImageFormat.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/media/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/ImageFormat.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/media/video/capture/android/imageformat_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/media; cd $(gyp_local_path)/media; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java" "--template=base/android/java/src/org/chromium/media/ImageFormat.template"
+
+.PHONY: media_media_android_imageformat_list_gyp_rule_trigger
+media_media_android_imageformat_list_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/media/ImageFormat.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	media_media_android_imageformat_list_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_android_imageformat_list_gyp
+
+# Alias gyp target name.
+.PHONY: media_android_imageformat_list
+media_android_imageformat_list: media_media_android_imageformat_list_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/media/media_android_jni_headers.target.darwin-arm.mk b/media/media_android_jni_headers.target.darwin-arm.mk
index 6af7420..6eab284 100644
--- a/media/media_android_jni_headers.target.darwin-arm.mk
+++ b/media/media_android_jni_headers.target.darwin-arm.mk
@@ -191,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -273,6 +274,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_jni_headers.target.darwin-mips.mk b/media/media_android_jni_headers.target.darwin-mips.mk
index f9cbf2d..0e5e708 100644
--- a/media/media_android_jni_headers.target.darwin-mips.mk
+++ b/media/media_android_jni_headers.target.darwin-mips.mk
@@ -190,6 +190,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -271,6 +272,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_jni_headers.target.darwin-x86.mk b/media/media_android_jni_headers.target.darwin-x86.mk
index b5e3e81..ee93305 100644
--- a/media/media_android_jni_headers.target.darwin-x86.mk
+++ b/media/media_android_jni_headers.target.darwin-x86.mk
@@ -192,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -274,6 +275,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_jni_headers.target.darwin-x86_64.mk b/media/media_android_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..40d2b6c
--- /dev/null
+++ b/media/media_android_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,330 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := media_media_android_jni_headers_gyp
+LOCAL_MODULE_STEM := media_android_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "media_media_gyp_media_android_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/media/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['base/android/java/src/org/chromium/media/AudioManagerAndroid.java', 'base/android/java/src/org/chromium/media/AudioRecordInput.java', 'base/android/java/src/org/chromium/media/MediaCodecBridge.java', 'base/android/java/src/org/chromium/media/MediaDrmBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerListener.java', 'base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java', 'base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java', 'base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/media/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/AudioManagerAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/AudioRecordInput.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/AudioRecordInput.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaCodecBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaDrmBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaPlayerBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaPlayerListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaPlayerListener.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h \
+	media_media_android_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_android_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: media_android_jni_headers
+media_android_jni_headers: media_media_android_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/media/media_android_jni_headers.target.linux-arm.mk b/media/media_android_jni_headers.target.linux-arm.mk
index 6af7420..6eab284 100644
--- a/media/media_android_jni_headers.target.linux-arm.mk
+++ b/media/media_android_jni_headers.target.linux-arm.mk
@@ -191,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -273,6 +274,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_jni_headers.target.linux-mips.mk b/media/media_android_jni_headers.target.linux-mips.mk
index f9cbf2d..0e5e708 100644
--- a/media/media_android_jni_headers.target.linux-mips.mk
+++ b/media/media_android_jni_headers.target.linux-mips.mk
@@ -190,6 +190,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -271,6 +272,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_jni_headers.target.linux-x86.mk b/media/media_android_jni_headers.target.linux-x86.mk
index b5e3e81..ee93305 100644
--- a/media/media_android_jni_headers.target.linux-x86.mk
+++ b/media/media_android_jni_headers.target.linux-x86.mk
@@ -192,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -274,6 +275,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_android_jni_headers.target.linux-x86_64.mk b/media/media_android_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..40d2b6c
--- /dev/null
+++ b/media/media_android_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,330 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := media_media_android_jni_headers_gyp
+LOCAL_MODULE_STEM := media_android_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "media_media_gyp_media_android_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/media/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['base/android/java/src/org/chromium/media/AudioManagerAndroid.java', 'base/android/java/src/org/chromium/media/AudioRecordInput.java', 'base/android/java/src/org/chromium/media/MediaCodecBridge.java', 'base/android/java/src/org/chromium/media/MediaDrmBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerBridge.java', 'base/android/java/src/org/chromium/media/MediaPlayerListener.java', 'base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java', 'base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java', 'base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/media/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/AudioManagerAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/AudioManagerAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/AudioRecordInput.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/AudioRecordInput.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaCodecBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaCodecBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaDrmBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaDrmBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaPlayerBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaPlayerBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/MediaPlayerListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/MediaPlayerListener.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/UsbMidiDeviceAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/UsbMidiDeviceFactoryAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/WebAudioMediaCodecBridge.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_media_android_jni_headers_gyp_rule_trigger
+media_media_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioManagerAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/AudioRecordInput_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaCodecBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaDrmBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerBridge_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/MediaPlayerListener_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/UsbMidiDeviceFactoryAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/media/jni/WebAudioMediaCodecBridge_jni.h \
+	media_media_android_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_android_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: media_android_jni_headers
+media_android_jni_headers: media_media_android_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/media/media_asm.target.darwin-x86.mk b/media/media_asm.target.darwin-x86.mk
index 3f2c8c2..b43e8ef 100644
--- a/media/media_asm.target.darwin-x86.mk
+++ b/media/media_asm.target.darwin-x86.mk
@@ -192,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -274,6 +275,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_asm.target.darwin-x86_64.mk b/media/media_asm.target.darwin-x86_64.mk
new file mode 100644
index 0000000..0ba7f9f
--- /dev/null
+++ b/media/media_asm.target.darwin-x86_64.mk
@@ -0,0 +1,392 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_asm_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/yasm
+
+
+### Generated for rule "media_media_gyp_media_asm_target_assemble":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/yasm', '../third_party/x86inc/x86inc.asm', 'base/simd/convert_rgb_to_yuv_ssse3.inc', 'base/simd/convert_yuv_to_rgb_mmx.inc', 'base/simd/convert_yuva_to_argb_mmx.inc', 'base/simd/linear_scale_yuv_to_rgb_mmx.inc', 'base/simd/media_export.asm', 'base/simd/scale_yuv_to_rgb_mmx.inc'], 'extension': 'asm', 'process_outputs_as_sources': '1', 'outputs': ['$(gyp_shared_intermediate_dir)/media/%(INPUT_ROOT)s.o'], 'rule_name': 'assemble', 'rule_sources': ['base/simd/convert_rgb_to_yuv_ssse3.asm', 'base/simd/convert_yuv_to_rgb_mmx.asm', 'base/simd/convert_yuv_to_rgb_sse.asm', 'base/simd/convert_yuva_to_argb_mmx.asm', 'base/simd/empty_register_state_mmx.asm', 'base/simd/linear_scale_yuv_to_rgb_mmx.asm', 'base/simd/linear_scale_yuv_to_rgb_sse.asm', 'base/simd/scale_yuv_to_rgb_mmx.asm', 'base/simd/scale_yuv_to_rgb_sse.asm', 'base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm', 'base/simd/scale_yuv_to_rgb_sse2_x64.asm'], 'action': ['$(gyp_shared_intermediate_dir)/yasm', '-DCHROMIUM', '-I..', '-DPIC', '-felf64', '-m', 'amd64', '-DARCH_X86_64', '-DARCH_X86_64', '-DELF', '-DPIC', '-o', '$(gyp_shared_intermediate_dir)/media/%(INPUT_ROOT)s.o', '$(RULE_SOURCES)'], 'message': 'Compile assembly $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o" base/simd/convert_rgb_to_yuv_ssse3.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o
+
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o" base/simd/convert_yuv_to_rgb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_sse.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o" base/simd/convert_yuv_to_rgb_sse.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o
+
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o" base/simd/convert_yuva_to_argb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: $(LOCAL_PATH)/media/base/simd/empty_register_state_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o" base/simd/empty_register_state_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o" base/simd/linear_scale_yuv_to_rgb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_sse.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o" base/simd/linear_scale_yuv_to_rgb_sse.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o
+
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o" base/simd/scale_yuv_to_rgb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_sse.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o" base/simd/scale_yuv_to_rgb_sse.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o
+
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o" base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o
+
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_sse2_x64.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o" base/simd/scale_yuv_to_rgb_sse2_x64.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o \
+	media_media_asm_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_asm_gyp
+
+# Alias gyp target name.
+.PHONY: media_asm
+media_asm: media_media_asm_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_asm.target.linux-x86.mk b/media/media_asm.target.linux-x86.mk
index 3f2c8c2..b43e8ef 100644
--- a/media/media_asm.target.linux-x86.mk
+++ b/media/media_asm.target.linux-x86.mk
@@ -192,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -274,6 +275,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_asm.target.linux-x86_64.mk b/media/media_asm.target.linux-x86_64.mk
new file mode 100644
index 0000000..0ba7f9f
--- /dev/null
+++ b/media/media_asm.target.linux-x86_64.mk
@@ -0,0 +1,392 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_asm_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/yasm
+
+
+### Generated for rule "media_media_gyp_media_asm_target_assemble":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/yasm', '../third_party/x86inc/x86inc.asm', 'base/simd/convert_rgb_to_yuv_ssse3.inc', 'base/simd/convert_yuv_to_rgb_mmx.inc', 'base/simd/convert_yuva_to_argb_mmx.inc', 'base/simd/linear_scale_yuv_to_rgb_mmx.inc', 'base/simd/media_export.asm', 'base/simd/scale_yuv_to_rgb_mmx.inc'], 'extension': 'asm', 'process_outputs_as_sources': '1', 'outputs': ['$(gyp_shared_intermediate_dir)/media/%(INPUT_ROOT)s.o'], 'rule_name': 'assemble', 'rule_sources': ['base/simd/convert_rgb_to_yuv_ssse3.asm', 'base/simd/convert_yuv_to_rgb_mmx.asm', 'base/simd/convert_yuv_to_rgb_sse.asm', 'base/simd/convert_yuva_to_argb_mmx.asm', 'base/simd/empty_register_state_mmx.asm', 'base/simd/linear_scale_yuv_to_rgb_mmx.asm', 'base/simd/linear_scale_yuv_to_rgb_sse.asm', 'base/simd/scale_yuv_to_rgb_mmx.asm', 'base/simd/scale_yuv_to_rgb_sse.asm', 'base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm', 'base/simd/scale_yuv_to_rgb_sse2_x64.asm'], 'action': ['$(gyp_shared_intermediate_dir)/yasm', '-DCHROMIUM', '-I..', '-DPIC', '-felf64', '-m', 'amd64', '-DARCH_X86_64', '-DARCH_X86_64', '-DELF', '-DPIC', '-o', '$(gyp_shared_intermediate_dir)/media/%(INPUT_ROOT)s.o', '$(RULE_SOURCES)'], 'message': 'Compile assembly $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o: $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o" base/simd/convert_rgb_to_yuv_ssse3.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o
+
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o: $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o" base/simd/convert_yuv_to_rgb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o: $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_sse.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o" base/simd/convert_yuv_to_rgb_sse.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o
+
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o: $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o" base/simd/convert_yuva_to_argb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o: $(LOCAL_PATH)/media/base/simd/empty_register_state_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o" base/simd/empty_register_state_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o: $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o" base/simd/linear_scale_yuv_to_rgb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o: $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_sse.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o" base/simd/linear_scale_yuv_to_rgb_sse.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o
+
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o: $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o" base/simd/scale_yuv_to_rgb_mmx.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o
+
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o: $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_sse.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o" base/simd/scale_yuv_to_rgb_sse.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o
+
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o: $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o" base/simd/linear_scale_yuv_to_rgb_mmx_x64.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o
+
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o: $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_sse2_x64.asm $(gyp_shared_intermediate_dir)/yasm $(LOCAL_PATH)/third_party/x86inc/x86inc.asm $(LOCAL_PATH)/media/base/simd/convert_rgb_to_yuv_ssse3.inc $(LOCAL_PATH)/media/base/simd/convert_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/convert_yuva_to_argb_mmx.inc $(LOCAL_PATH)/media/base/simd/linear_scale_yuv_to_rgb_mmx.inc $(LOCAL_PATH)/media/base/simd/media_export.asm $(LOCAL_PATH)/media/base/simd/scale_yuv_to_rgb_mmx.inc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media; cd $(gyp_local_path)/media; "$(gyp_shared_intermediate_dir)/yasm" -DCHROMIUM -I.. -DPIC -felf64 -m amd64 -DARCH_X86_64 -DARCH_X86_64 -DELF -DPIC -o "$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o" base/simd/scale_yuv_to_rgb_sse2_x64.asm
+
+.PHONY: media_media_asm_gyp_rule_trigger
+media_media_asm_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/media/convert_rgb_to_yuv_ssse3.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/convert_yuva_to_argb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/empty_register_state_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_mmx.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse.o \
+	$(gyp_shared_intermediate_dir)/media/linear_scale_yuv_to_rgb_mmx_x64.o \
+	$(gyp_shared_intermediate_dir)/media/scale_yuv_to_rgb_sse2_x64.o \
+	media_media_asm_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_asm_gyp
+
+# Alias gyp target name.
+.PHONY: media_asm
+media_asm: media_media_asm_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_mmx.target.darwin-x86.mk b/media/media_mmx.target.darwin-x86.mk
index 80da87a..461cc13 100644
--- a/media/media_mmx.target.darwin-x86.mk
+++ b/media/media_mmx.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_mmx.target.darwin-x86_64.mk b/media/media_mmx.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4d57379
--- /dev/null
+++ b/media/media_mmx.target.darwin-x86_64.mk
@@ -0,0 +1,261 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_mmx_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/filter_yuv_mmx.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mmmx \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mmmx \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_mmx_gyp
+
+# Alias gyp target name.
+.PHONY: media_mmx
+media_mmx: media_media_mmx_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_mmx.target.linux-x86.mk b/media/media_mmx.target.linux-x86.mk
index 80da87a..461cc13 100644
--- a/media/media_mmx.target.linux-x86.mk
+++ b/media/media_mmx.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_mmx.target.linux-x86_64.mk b/media/media_mmx.target.linux-x86_64.mk
new file mode 100644
index 0000000..4d57379
--- /dev/null
+++ b/media/media_mmx.target.linux-x86_64.mk
@@ -0,0 +1,261 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_mmx_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/filter_yuv_mmx.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mmmx \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mmmx \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_mmx_gyp
+
+# Alias gyp target name.
+.PHONY: media_mmx
+media_mmx: media_media_mmx_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_sse.target.darwin-x86.mk b/media/media_sse.target.darwin-x86.mk
index 72454a2..f15373e 100644
--- a/media/media_sse.target.darwin-x86.mk
+++ b/media/media_sse.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_sse.target.darwin-x86_64.mk b/media/media_sse.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a5732e3
--- /dev/null
+++ b/media/media_sse.target.darwin-x86_64.mk
@@ -0,0 +1,261 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_sse_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/sinc_resampler_sse.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_sse_gyp
+
+# Alias gyp target name.
+.PHONY: media_sse
+media_sse: media_media_sse_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_sse.target.linux-x86.mk b/media/media_sse.target.linux-x86.mk
index 72454a2..f15373e 100644
--- a/media/media_sse.target.linux-x86.mk
+++ b/media/media_sse.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_sse.target.linux-x86_64.mk b/media/media_sse.target.linux-x86_64.mk
new file mode 100644
index 0000000..a5732e3
--- /dev/null
+++ b/media/media_sse.target.linux-x86_64.mk
@@ -0,0 +1,261 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_sse_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/sinc_resampler_sse.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_sse_gyp
+
+# Alias gyp target name.
+.PHONY: media_sse
+media_sse: media_media_sse_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_sse2.target.darwin-x86.mk b/media/media_sse2.target.darwin-x86.mk
index f0948db..a86c9a0 100644
--- a/media/media_sse2.target.darwin-x86.mk
+++ b/media/media_sse2.target.darwin-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_sse2.target.darwin-x86_64.mk b/media/media_sse2.target.darwin-x86_64.mk
new file mode 100644
index 0000000..1134a74
--- /dev/null
+++ b/media/media_sse2.target.darwin-x86_64.mk
@@ -0,0 +1,263 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_sse2_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/convert_rgb_to_yuv_sse2.cc \
+	media/base/simd/convert_rgb_to_yuv_ssse3.cc \
+	media/base/simd/filter_yuv_sse2.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse2 \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse2 \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_sse2_gyp
+
+# Alias gyp target name.
+.PHONY: media_sse2
+media_sse2: media_media_sse2_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/media_sse2.target.linux-x86.mk b/media/media_sse2.target.linux-x86.mk
index f0948db..a86c9a0 100644
--- a/media/media_sse2.target.linux-x86.mk
+++ b/media/media_sse2.target.linux-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/media_sse2.target.linux-x86_64.mk b/media/media_sse2.target.linux-x86_64.mk
new file mode 100644
index 0000000..1134a74
--- /dev/null
+++ b/media/media_sse2.target.linux-x86_64.mk
@@ -0,0 +1,263 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_media_sse2_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/convert_rgb_to_yuv_sse2.cc \
+	media/base/simd/convert_rgb_to_yuv_ssse3.cc \
+	media/base/simd/filter_yuv_sse2.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse2 \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse2 \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_media_sse2_gyp
+
+# Alias gyp target name.
+.PHONY: media_sse2
+media_sse2: media_media_sse2_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/midi/usb_midi_device_android.cc b/media/midi/usb_midi_device_android.cc
index f3ccc43..58fba0a 100644
--- a/media/midi/usb_midi_device_android.cc
+++ b/media/midi/usb_midi_device_android.cc
@@ -14,7 +14,11 @@
 
 UsbMidiDeviceAndroid::UsbMidiDeviceAndroid(ObjectRef raw_device,
                                            UsbMidiDeviceDelegate* delegate)
-    : raw_device_(raw_device), delegate_(delegate) {}
+    : raw_device_(raw_device), delegate_(delegate) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_UsbMidiDeviceAndroid_registerSelf(
+      env, raw_device_.obj(), reinterpret_cast<jlong>(this));
+}
 
 UsbMidiDeviceAndroid::~UsbMidiDeviceAndroid() {
   JNIEnv* env = base::android::AttachCurrentThread();
@@ -42,6 +46,18 @@
       env, raw_device_.obj(), endpoint_number, data_to_pass.obj());
 }
 
+void UsbMidiDeviceAndroid::OnData(JNIEnv* env,
+                                  jobject caller,
+                                  jint endpoint_number,
+                                  jbyteArray data) {
+  std::vector<uint8> bytes;
+  base::android::JavaByteArrayToByteVector(env, data, &bytes);
+
+  const uint8* head = bytes.size() ? &bytes[0] : NULL;
+  // TODO(yhirano): Provide the correct timestamp.
+  delegate_->ReceiveUsbMidiData(this, endpoint_number, head, bytes.size(), 0);
+}
+
 bool UsbMidiDeviceAndroid::RegisterUsbMidiDevice(JNIEnv* env) {
   return RegisterNativesImpl(env);
 }
diff --git a/media/midi/usb_midi_device_android.h b/media/midi/usb_midi_device_android.h
index ed0a414..70d1855 100644
--- a/media/midi/usb_midi_device_android.h
+++ b/media/midi/usb_midi_device_android.h
@@ -30,6 +30,12 @@
   virtual void Send(int endpoint_number,
                     const std::vector<uint8>& data) OVERRIDE;
 
+  // Called by the Java world.
+  void OnData(JNIEnv* env,
+              jobject caller,
+              jint endpoint_number,
+              jbyteArray data);
+
   static bool RegisterUsbMidiDevice(JNIEnv* env);
 
  private:
diff --git a/media/player_android.target.darwin-arm.mk b/media/player_android.target.darwin-arm.mk
index 7ab44e3..6bbd68b 100644
--- a/media/player_android.target.darwin-arm.mk
+++ b/media/player_android.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/player_android.target.darwin-mips.mk b/media/player_android.target.darwin-mips.mk
index ef3a95c..8726e3a 100644
--- a/media/player_android.target.darwin-mips.mk
+++ b/media/player_android.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/player_android.target.darwin-x86.mk b/media/player_android.target.darwin-x86.mk
index 53332ab..8c4e17a 100644
--- a/media/player_android.target.darwin-x86.mk
+++ b/media/player_android.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -191,6 +192,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/player_android.target.darwin-x86_64.mk b/media/player_android.target.darwin-x86_64.mk
new file mode 100644
index 0000000..317a1c0
--- /dev/null
+++ b/media/player_android.target.darwin-x86_64.mk
@@ -0,0 +1,297 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_player_android_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_widevine_cdm_widevine_cdm_version_h_gyp)/widevine_cdm_version_h.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,media_media_android_jni_headers_gyp)/media_android_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/android/audio_decoder_job.cc \
+	media/base/android/media_codec_bridge.cc \
+	media/base/android/media_decoder_job.cc \
+	media/base/android/media_drm_bridge.cc \
+	media/base/android/media_jni_registrar.cc \
+	media/base/android/media_player_android.cc \
+	media/base/android/media_player_bridge.cc \
+	media/base/android/media_player_listener.cc \
+	media/base/android/media_source_player.cc \
+	media/base/android/video_decoder_job.cc \
+	media/base/android/webaudio_media_codec_bridge.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_player_android_gyp
+
+# Alias gyp target name.
+.PHONY: player_android
+player_android: media_player_android_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/player_android.target.linux-arm.mk b/media/player_android.target.linux-arm.mk
index 7ab44e3..6bbd68b 100644
--- a/media/player_android.target.linux-arm.mk
+++ b/media/player_android.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/player_android.target.linux-mips.mk b/media/player_android.target.linux-mips.mk
index ef3a95c..8726e3a 100644
--- a/media/player_android.target.linux-mips.mk
+++ b/media/player_android.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/player_android.target.linux-x86.mk b/media/player_android.target.linux-x86.mk
index 53332ab..8c4e17a 100644
--- a/media/player_android.target.linux-x86.mk
+++ b/media/player_android.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -191,6 +192,7 @@
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/player_android.target.linux-x86_64.mk b/media/player_android.target.linux-x86_64.mk
new file mode 100644
index 0000000..317a1c0
--- /dev/null
+++ b/media/player_android.target.linux-x86_64.mk
@@ -0,0 +1,297 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_player_android_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_widevine_cdm_widevine_cdm_version_h_gyp)/widevine_cdm_version_h.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a \
+	$(call intermediates-dir-for,GYP,media_media_android_jni_headers_gyp)/media_android_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/android/audio_decoder_job.cc \
+	media/base/android/media_codec_bridge.cc \
+	media/base/android/media_decoder_job.cc \
+	media/base/android/media_drm_bridge.cc \
+	media/base/android/media_jni_registrar.cc \
+	media/base/android/media_player_android.cc \
+	media/base/android/media_player_bridge.cc \
+	media/base/android/media_player_listener.cc \
+	media/base/android/media_source_player.cc \
+	media/base/android/video_decoder_job.cc \
+	media/base/android/webaudio_media_codec_bridge.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/media \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_player_android_gyp
+
+# Alias gyp target name.
+.PHONY: player_android
+player_android: media_player_android_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/shared_memory_support.target.darwin-arm.mk b/media/shared_memory_support.target.darwin-arm.mk
index 70ca281..3d4d038 100644
--- a/media/shared_memory_support.target.darwin-arm.mk
+++ b/media/shared_memory_support.target.darwin-arm.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -167,6 +168,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support.target.darwin-mips.mk b/media/shared_memory_support.target.darwin-mips.mk
index 1ebe4de..d804765 100644
--- a/media/shared_memory_support.target.darwin-mips.mk
+++ b/media/shared_memory_support.target.darwin-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support.target.darwin-x86.mk b/media/shared_memory_support.target.darwin-x86.mk
index 725e5e5..9b9dd09 100644
--- a/media/shared_memory_support.target.darwin-x86.mk
+++ b/media/shared_memory_support.target.darwin-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support.target.darwin-x86_64.mk b/media/shared_memory_support.target.darwin-x86_64.mk
new file mode 100644
index 0000000..3dba22e
--- /dev/null
+++ b/media/shared_memory_support.target.darwin-x86_64.mk
@@ -0,0 +1,264 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_shared_memory_support_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/audio/audio_parameters.cc \
+	media/base/audio_bus.cc \
+	media/base/channel_layout.cc \
+	media/base/vector_math.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_shared_memory_support_gyp
+
+# Alias gyp target name.
+.PHONY: shared_memory_support
+shared_memory_support: media_shared_memory_support_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/shared_memory_support.target.linux-arm.mk b/media/shared_memory_support.target.linux-arm.mk
index 70ca281..3d4d038 100644
--- a/media/shared_memory_support.target.linux-arm.mk
+++ b/media/shared_memory_support.target.linux-arm.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -167,6 +168,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support.target.linux-mips.mk b/media/shared_memory_support.target.linux-mips.mk
index 1ebe4de..d804765 100644
--- a/media/shared_memory_support.target.linux-mips.mk
+++ b/media/shared_memory_support.target.linux-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support.target.linux-x86.mk b/media/shared_memory_support.target.linux-x86.mk
index 725e5e5..9b9dd09 100644
--- a/media/shared_memory_support.target.linux-x86.mk
+++ b/media/shared_memory_support.target.linux-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support.target.linux-x86_64.mk b/media/shared_memory_support.target.linux-x86_64.mk
new file mode 100644
index 0000000..3dba22e
--- /dev/null
+++ b/media/shared_memory_support.target.linux-x86_64.mk
@@ -0,0 +1,264 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_shared_memory_support_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/audio/audio_parameters.cc \
+	media/base/audio_bus.cc \
+	media/base/channel_layout.cc \
+	media/base/vector_math.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_shared_memory_support_gyp
+
+# Alias gyp target name.
+.PHONY: shared_memory_support
+shared_memory_support: media_shared_memory_support_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/shared_memory_support_sse.target.darwin-x86.mk b/media/shared_memory_support_sse.target.darwin-x86.mk
index 0c13e87..f732038 100644
--- a/media/shared_memory_support_sse.target.darwin-x86.mk
+++ b/media/shared_memory_support_sse.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support_sse.target.darwin-x86_64.mk b/media/shared_memory_support_sse.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a6d60e5
--- /dev/null
+++ b/media/shared_memory_support_sse.target.darwin-x86_64.mk
@@ -0,0 +1,261 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_shared_memory_support_sse_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/vector_math_sse.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_shared_memory_support_sse_gyp
+
+# Alias gyp target name.
+.PHONY: shared_memory_support_sse
+shared_memory_support_sse: media_shared_memory_support_sse_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/shared_memory_support_sse.target.linux-x86.mk b/media/shared_memory_support_sse.target.linux-x86.mk
index 0c13e87..f732038 100644
--- a/media/shared_memory_support_sse.target.linux-x86.mk
+++ b/media/shared_memory_support_sse.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -166,6 +167,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DMEDIA_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/shared_memory_support_sse.target.linux-x86_64.mk b/media/shared_memory_support_sse.target.linux-x86_64.mk
new file mode 100644
index 0000000..a6d60e5
--- /dev/null
+++ b/media/shared_memory_support_sse.target.linux-x86_64.mk
@@ -0,0 +1,261 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := media_shared_memory_support_sse_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	media/base/simd/vector_math_sse.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-msse \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DMEDIA_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_shared_memory_support_sse_gyp
+
+# Alias gyp target name.
+.PHONY: shared_memory_support_sse
+shared_memory_support_sse: media_shared_memory_support_sse_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc
index 32e5019..0cec7b8 100644
--- a/media/tools/player_x11/player_x11.cc
+++ b/media/tools/player_x11/player_x11.cc
@@ -16,6 +16,7 @@
 #include "base/threading/thread.h"
 #include "media/audio/audio_manager.h"
 #include "media/audio/null_audio_sink.h"
+#include "media/base/audio_hardware_config.h"
 #include "media/base/decryptor.h"
 #include "media/base/filter_collection.h"
 #include "media/base/media.h"
@@ -93,7 +94,11 @@
   paint_cb.Run(video_frame.get());
 }
 
-static void OnBufferingState(media::Pipeline::BufferingState buffering_state) {}
+static void DoNothing() {}
+
+static void OnStatus(media::PipelineStatus status) {}
+
+static void OnMetadata(media::PipelineMetadata metadata) {}
 
 static void NeedKey(const std::string& type,
                     const std::vector<uint8>& init_data) {
@@ -133,20 +138,31 @@
 
   ScopedVector<media::AudioDecoder> audio_decoders;
   audio_decoders.push_back(new media::FFmpegAudioDecoder(task_runner));
-  scoped_ptr<media::AudioRenderer> audio_renderer(new media::AudioRendererImpl(
-      task_runner,
-      new media::NullAudioSink(task_runner),
-      audio_decoders.Pass(),
-      media::SetDecryptorReadyCB()));
+  media::AudioParameters out_params(
+      media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+      media::CHANNEL_LAYOUT_STEREO,
+      44100,
+      16,
+      512);
+  media::AudioHardwareConfig hardware_config(out_params, out_params);
+
+  scoped_ptr<media::AudioRenderer> audio_renderer(
+      new media::AudioRendererImpl(task_runner,
+                                   new media::NullAudioSink(task_runner),
+                                   audio_decoders.Pass(),
+                                   media::SetDecryptorReadyCB(),
+                                   &hardware_config));
+
   collection->SetAudioRenderer(audio_renderer.Pass());
 
   base::WaitableEvent event(true, false);
   media::PipelineStatus status;
 
   pipeline->Start(
-      collection.Pass(), base::Closure(), media::PipelineStatusCB(),
+      collection.Pass(), base::Bind(&DoNothing), base::Bind(&OnStatus),
       base::Bind(&SaveStatusAndSignal, &event, &status),
-      base::Bind(&OnBufferingState), base::Closure());
+      base::Bind(&OnMetadata), base::Bind(&DoNothing),
+      base::Bind(&DoNothing));
 
   // Wait until the pipeline is fully initialized.
   event.Wait();
@@ -162,8 +178,7 @@
 
 void PeriodicalUpdate(
     media::Pipeline* pipeline,
-    base::MessageLoop* message_loop,
-    bool audio_only) {
+    base::MessageLoop* message_loop) {
   if (!g_running) {
     // interrupt signal was received during last time period.
     // Quit message_loop only when pipeline is fully stopped.
@@ -191,7 +206,7 @@
                        &border_width,
                        &depth);
           base::TimeDelta time = pipeline->GetMediaDuration();
-          pipeline->Seek(time*e.xbutton.x/width, media::PipelineStatusCB());
+          pipeline->Seek(time*e.xbutton.x/width, base::Bind(&OnStatus));
         }
         break;
       case KeyPress:
@@ -219,8 +234,7 @@
       FROM_HERE,
       base::Bind(&PeriodicalUpdate,
                  base::Unretained(pipeline),
-                 message_loop,
-                 audio_only),
+                 message_loop),
       base::TimeDelta::FromMilliseconds(10));
 }
 
@@ -291,8 +305,7 @@
   g_running = true;
 
   message_loop.PostTask(FROM_HERE, base::Bind(
-      &PeriodicalUpdate, base::Unretained(&pipeline), &message_loop,
-      !pipeline.HasVideo()));
+      &PeriodicalUpdate, base::Unretained(&pipeline), &message_loop));
   message_loop.Run();
 
   // Cleanup tasks.
diff --git a/media/video/capture/mac/avfoundation_glue.mm b/media/video/capture/mac/avfoundation_glue.mm
index 7373a66..6d968f3 100644
--- a/media/video/capture/mac/avfoundation_glue.mm
+++ b/media/video/capture/mac/avfoundation_glue.mm
@@ -9,6 +9,7 @@
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/mac/mac_util.h"
+#include "base/metrics/field_trial.h"
 #include "media/base/media_switches.h"
 
 namespace {
@@ -122,8 +123,10 @@
   // DeviceMonitorMac will initialize this static bool from the main UI thread
   // once, during Chrome startup so this construction is thread safe.
   static bool is_av_foundation_supported = base::mac::IsOSLionOrLater() &&
-      CommandLine::ForCurrentProcess()->HasSwitch(
-          switches::kEnableAVFoundation) && [AVFoundationBundle() load];
+      (CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableAVFoundation) ||
+          base::FieldTrialList::FindFullName("AVFoundationMacVideoCapture")
+              == "Enabled") && [AVFoundationBundle() load];
   return is_av_foundation_supported;
 }
 
diff --git a/media/video/capture/win/video_capture_device_win.cc b/media/video/capture/win/video_capture_device_win.cc
index 16d8ec3..490c59d 100644
--- a/media/video/capture/win/video_capture_device_win.cc
+++ b/media/video/capture/win/video_capture_device_win.cc
@@ -150,6 +150,34 @@
   }
 }
 
+// A utility class that wraps the AM_MEDIA_TYPE type and guarantees that
+// we free the structure when exiting the scope.  DCHECKing is also done to
+// avoid memory leaks.
+class ScopedMediaType {
+ public:
+  ScopedMediaType() : media_type_(NULL) {}
+  ~ScopedMediaType() { Free(); }
+
+  AM_MEDIA_TYPE* operator->() { return media_type_; }
+  AM_MEDIA_TYPE* get() { return media_type_; }
+
+  void Free() {
+    if (!media_type_)
+      return;
+
+    DeleteMediaType(media_type_);
+    media_type_= NULL;
+  }
+
+  AM_MEDIA_TYPE** Receive() {
+    DCHECK(!media_type_);
+    return &media_type_;
+  }
+
+ private:
+  AM_MEDIA_TYPE* media_type_;
+};
+
 VideoPixelFormat TranslateMediaSubtypeToPixelFormat(const GUID& sub_type) {
   static struct {
     const GUID& sub_type;
@@ -378,10 +406,10 @@
       return;
     }
 
-    AM_MEDIA_TYPE* media_type = NULL;
     scoped_ptr<BYTE[]> caps(new BYTE[size]);
     for (int i = 0; i < count; ++i) {
-      hr = stream_config->GetStreamCaps(i, &media_type, caps.get());
+      ScopedMediaType media_type;
+      hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get());
       // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED()
       // macros here since they'll trigger incorrectly.
       if (hr != S_OK) {
@@ -391,21 +419,21 @@
 
       if (media_type->majortype == MEDIATYPE_Video &&
           media_type->formattype == FORMAT_VideoInfo) {
-          VIDEOINFOHEADER* h =
-              reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
-          VideoCaptureFormat format;
-          format.frame_size.SetSize(h->bmiHeader.biWidth,
-                                    h->bmiHeader.biHeight);
-          // Trust the frame rate from the VIDEOINFOHEADER.
-          format.frame_rate = (h->AvgTimePerFrame > 0) ?
-              static_cast<int>(kSecondsToReferenceTime / h->AvgTimePerFrame) :
-              0;
-          format.pixel_format =
-              TranslateMediaSubtypeToPixelFormat(media_type->subtype);
-          formats->push_back(format);
-          DVLOG(1) << device.name() << " resolution: "
-               << format.frame_size.ToString() << ", fps: " << format.frame_rate
-               << ", pixel format: " << format.pixel_format;
+        VIDEOINFOHEADER* h =
+            reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
+        VideoCaptureFormat format;
+        format.frame_size.SetSize(h->bmiHeader.biWidth,
+                                  h->bmiHeader.biHeight);
+        // Trust the frame rate from the VIDEOINFOHEADER.
+        format.frame_rate = (h->AvgTimePerFrame > 0) ?
+            static_cast<int>(kSecondsToReferenceTime / h->AvgTimePerFrame) :
+            0;
+        format.pixel_format =
+            TranslateMediaSubtypeToPixelFormat(media_type->subtype);
+        formats->push_back(format);
+        DVLOG(1) << device.name() << " resolution: "
+             << format.frame_size.ToString() << ", fps: " << format.frame_rate
+             << ", pixel format: " << format.pixel_format;
       }
     }
   }
@@ -524,22 +552,23 @@
     return;
   }
 
-  AM_MEDIA_TYPE* pmt = NULL;
   scoped_ptr<BYTE[]> caps(new BYTE[size]);
+  ScopedMediaType media_type;
 
   // Get the windows capability from the capture device.
   hr = stream_config->GetStreamCaps(
-      found_capability.stream_index, &pmt, caps.get());
+      found_capability.stream_index, media_type.Receive(), caps.get());
   if (SUCCEEDED(hr)) {
-    if (pmt->formattype == FORMAT_VideoInfo) {
-      VIDEOINFOHEADER* h = reinterpret_cast<VIDEOINFOHEADER*>(pmt->pbFormat);
+    if (media_type->formattype == FORMAT_VideoInfo) {
+      VIDEOINFOHEADER* h =
+          reinterpret_cast<VIDEOINFOHEADER*>(media_type->pbFormat);
       if (format.frame_rate > 0)
         h->AvgTimePerFrame = kSecondsToReferenceTime / format.frame_rate;
     }
     // Set the sink filter to request this format.
     sink_filter_->SetRequestedMediaFormat(format);
     // Order the capture device to use this format.
-    hr = stream_config->SetFormat(pmt);
+    hr = stream_config->SetFormat(media_type.get());
   }
 
   if (FAILED(hr))
@@ -658,10 +687,10 @@
     return false;
   }
 
-  AM_MEDIA_TYPE* media_type = NULL;
   scoped_ptr<BYTE[]> caps(new BYTE[size]);
   for (int i = 0; i < count; ++i) {
-    hr = stream_config->GetStreamCaps(i, &media_type, caps.get());
+    ScopedMediaType media_type;
+    hr = stream_config->GetStreamCaps(i, media_type.Receive(), caps.get());
     // GetStreamCaps() may return S_FALSE, so don't use FAILED() or SUCCEED()
     // macros here since they'll trigger incorrectly.
     if (hr != S_OK) {
@@ -716,8 +745,6 @@
           TranslateMediaSubtypeToPixelFormat(media_type->subtype);
       capabilities_.Add(capability);
     }
-    DeleteMediaType(media_type);
-    media_type = NULL;
   }
 
   return !capabilities_.empty();
diff --git a/media/video_capture_android_jni_headers.target.darwin-arm.mk b/media/video_capture_android_jni_headers.target.darwin-arm.mk
index 8b20d18..fc84275 100644
--- a/media/video_capture_android_jni_headers.target.darwin-arm.mk
+++ b/media/video_capture_android_jni_headers.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/video_capture_android_jni_headers.target.darwin-mips.mk b/media/video_capture_android_jni_headers.target.darwin-mips.mk
index 843482a..408a841 100644
--- a/media/video_capture_android_jni_headers.target.darwin-mips.mk
+++ b/media/video_capture_android_jni_headers.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/video_capture_android_jni_headers.target.darwin-x86.mk b/media/video_capture_android_jni_headers.target.darwin-x86.mk
index 838ada9..ca5e1b7 100644
--- a/media/video_capture_android_jni_headers.target.darwin-x86.mk
+++ b/media/video_capture_android_jni_headers.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/video_capture_android_jni_headers.target.darwin-x86_64.mk b/media/video_capture_android_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..c62eaf9
--- /dev/null
+++ b/media/video_capture_android_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,234 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := media_video_capture_android_jni_headers_gyp
+LOCAL_MODULE_STEM := video_capture_android_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "media_media_gyp_video_capture_android_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/media/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['base/android/java/src/org/chromium/media/VideoCapture.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/media/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/VideoCapture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/VideoCapture.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_video_capture_android_jni_headers_gyp_rule_trigger
+media_video_capture_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h \
+	media_video_capture_android_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_video_capture_android_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: video_capture_android_jni_headers
+video_capture_android_jni_headers: media_video_capture_android_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/media/video_capture_android_jni_headers.target.linux-arm.mk b/media/video_capture_android_jni_headers.target.linux-arm.mk
index 8b20d18..fc84275 100644
--- a/media/video_capture_android_jni_headers.target.linux-arm.mk
+++ b/media/video_capture_android_jni_headers.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/video_capture_android_jni_headers.target.linux-mips.mk b/media/video_capture_android_jni_headers.target.linux-mips.mk
index 843482a..408a841 100644
--- a/media/video_capture_android_jni_headers.target.linux-mips.mk
+++ b/media/video_capture_android_jni_headers.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/video_capture_android_jni_headers.target.linux-x86.mk b/media/video_capture_android_jni_headers.target.linux-x86.mk
index 838ada9..ca5e1b7 100644
--- a/media/video_capture_android_jni_headers.target.linux-x86.mk
+++ b/media/video_capture_android_jni_headers.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/media/video_capture_android_jni_headers.target.linux-x86_64.mk b/media/video_capture_android_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..c62eaf9
--- /dev/null
+++ b/media/video_capture_android_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,234 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := media_video_capture_android_jni_headers_gyp
+LOCAL_MODULE_STEM := video_capture_android_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "media_media_gyp_video_capture_android_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/media/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['base/android/java/src/org/chromium/media/VideoCapture.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/media/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h: $(LOCAL_PATH)/media/base/android/java/src/org/chromium/media/VideoCapture.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/media/jni; cd $(gyp_local_path)/media; ../base/android/jni_generator/jni_generator.py --input_file base/android/java/src/org/chromium/media/VideoCapture.java --output_dir "$(gyp_shared_intermediate_dir)/media/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: media_video_capture_android_jni_headers_gyp_rule_trigger
+media_video_capture_android_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/media/jni/VideoCapture_jni.h \
+	media_video_capture_android_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: media_video_capture_android_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: video_capture_android_jni_headers
+video_capture_android_jni_headers: media_video_capture_android_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/mojo/apps/js/bindings/connection_unittests.js b/mojo/apps/js/bindings/connection_unittests.js
new file mode 100644
index 0000000..14bb92f
--- /dev/null
+++ b/mojo/apps/js/bindings/connection_unittests.js
@@ -0,0 +1,237 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Mock out the support module to avoid depending on the message loop.
+define("mojo/bindings/js/support", function() {
+  var waitingCallbacks = [];
+
+  function WaitCookie(id) {
+    this.id = id;
+  }
+
+  function asyncWait(handle, flags, callback) {
+    var id = waitingCallbacks.length;
+    waitingCallbacks.push(callback);
+    return new WaitCookie(id);
+  }
+
+  function cancelWait(cookie) {
+    waitingCallbacks[cookie.id] = null;
+  }
+
+  function numberOfWaitingCallbacks() {
+    var count = 0;
+    for (var i = 0; i < waitingCallbacks.length; ++i) {
+      if (waitingCallbacks[i])
+        ++count;
+    }
+    return count;
+  }
+
+  function pumpOnce(result) {
+    var callbacks = waitingCallbacks;
+    waitingCallbacks = [];
+    for (var i = 0; i < callbacks.length; ++i) {
+      if (callbacks[i])
+        callbacks[i](result);
+    }
+  }
+
+  var exports = {};
+  exports.asyncWait = asyncWait;
+  exports.cancelWait = cancelWait;
+  exports.numberOfWaitingCallbacks = numberOfWaitingCallbacks;
+  exports.pumpOnce = pumpOnce;
+  return exports;
+});
+
+define([
+    "gin/test/expect",
+    "mojo/bindings/js/support",
+    "mojo/bindings/js/core",
+    "mojo/public/bindings/js/connection",
+    "mojo/public/bindings/tests/sample_interfaces.mojom",
+    "mojo/public/bindings/tests/sample_service.mojom",
+], function(expect,
+            mockSupport,
+            core,
+            connection,
+            sample_interfaces,
+            sample_service) {
+  testClientServer();
+  testWriteToClosedPipe();
+  testRequestResponse();
+  this.result = "PASS";
+
+  function testClientServer() {
+    var receivedFrobinate = false;
+    var receivedDidFrobinate = false;
+
+    // ServiceImpl -------------------------------------------------------------
+
+    function ServiceImpl(peer) {
+      this.peer = peer;
+    }
+
+    ServiceImpl.prototype = Object.create(sample_service.ServiceStub.prototype);
+
+    ServiceImpl.prototype.frobinate = function(foo, baz, port) {
+      receivedFrobinate = true;
+
+      expect(foo.name).toBe("Example name");
+      expect(baz).toBeTruthy();
+      expect(core.close(port)).toBe(core.RESULT_OK);
+
+      this.peer.didFrobinate(42);
+    };
+
+    // ServiceImpl -------------------------------------------------------------
+
+    function ServiceClientImpl(peer) {
+      this.peer = peer;
+    }
+
+    ServiceClientImpl.prototype =
+        Object.create(sample_service.ServiceClientStub.prototype);
+
+    ServiceClientImpl.prototype.didFrobinate = function(result) {
+      receivedDidFrobinate = true;
+
+      expect(result).toBe(42);
+    };
+
+    var pipe = core.createMessagePipe();
+    var anotherPipe = core.createMessagePipe();
+    var sourcePipe = core.createMessagePipe();
+
+    var connection0 = new connection.Connection(
+        pipe.handle0, ServiceImpl, sample_service.ServiceClientProxy);
+
+    var connection1 = new connection.Connection(
+        pipe.handle1, ServiceClientImpl, sample_service.ServiceProxy);
+
+    var foo = new sample_service.Foo();
+    foo.bar = new sample_service.Bar();
+    foo.name = "Example name";
+    foo.source = sourcePipe.handle0;
+    connection1.remote.frobinate(foo, true, anotherPipe.handle0);
+
+    mockSupport.pumpOnce(core.RESULT_OK);
+
+    expect(receivedFrobinate).toBeTruthy();
+    expect(receivedDidFrobinate).toBeTruthy();
+
+    connection0.close();
+    connection1.close();
+
+    expect(mockSupport.numberOfWaitingCallbacks()).toBe(0);
+
+    // sourcePipe.handle0 was closed automatically when sent over IPC.
+    expect(core.close(sourcePipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
+    // sourcePipe.handle1 hasn't been closed yet.
+    expect(core.close(sourcePipe.handle1)).toBe(core.RESULT_OK);
+
+    // anotherPipe.handle0 was closed automatically when sent over IPC.
+    expect(core.close(anotherPipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
+    // anotherPipe.handle1 hasn't been closed yet.
+    expect(core.close(anotherPipe.handle1)).toBe(core.RESULT_OK);
+
+    // The Connection object is responsible for closing these handles.
+    expect(core.close(pipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
+    expect(core.close(pipe.handle1)).toBe(core.RESULT_INVALID_ARGUMENT);
+  }
+
+  function testWriteToClosedPipe() {
+    var pipe = core.createMessagePipe();
+
+    var connection1 = new connection.Connection(
+        pipe.handle1, function() {}, sample_service.ServiceProxy);
+
+    // Close the other end of the pipe.
+    core.close(pipe.handle0);
+
+    // Not observed yet because we haven't pumped events yet.
+    expect(connection1.encounteredError()).toBeFalsy();
+
+    var foo = new sample_service.Foo();
+    foo.bar = new sample_service.Bar();
+    // TODO(darin): crbug.com/357043: pass null in place of |foo| here.
+    connection1.remote.frobinate(foo, true, core.kInvalidHandle);
+
+    // Write failures are not reported.
+    expect(connection1.encounteredError()).toBeFalsy();
+
+    // Pump events, and then we should start observing the closed pipe.
+    mockSupport.pumpOnce(core.RESULT_OK);
+
+    expect(connection1.encounteredError()).toBeTruthy();
+
+    connection1.close();
+  }
+
+  function testRequestResponse() {
+
+    // ProviderImpl ------------------------------------------------------------
+
+    function ProviderImpl(peer) {
+      this.peer = peer;
+    }
+
+    ProviderImpl.prototype =
+        Object.create(sample_interfaces.ProviderStub.prototype);
+
+    ProviderImpl.prototype.echoString = function(a, callback) {
+      callback(a);
+    };
+
+    ProviderImpl.prototype.echoStrings = function(a, b, callback) {
+      callback(a, b);
+    };
+
+    // ProviderClientImpl ------------------------------------------------------
+
+    function ProviderClientImpl(peer) {
+      this.peer = peer;
+    }
+
+    ProviderClientImpl.prototype =
+        Object.create(sample_interfaces.ProviderClientStub.prototype);
+
+    ProviderClientImpl.prototype.didFrobinate = function(result) {
+      receivedDidFrobinate = true;
+
+      expect(result).toBe(42);
+    };
+
+    var pipe = core.createMessagePipe();
+
+    var connection0 = new connection.Connection(
+        pipe.handle0, ProviderImpl, sample_interfaces.ProviderClientProxy);
+
+    var connection1 = new connection.Connection(
+        pipe.handle1, ProviderClientImpl, sample_interfaces.ProviderProxy);
+
+    var echoedString;
+
+    // echoString
+
+    connection1.remote.echoString("hello", function(a) {
+      echoedString = a;
+    });
+
+    mockSupport.pumpOnce(core.RESULT_OK);
+
+    expect(echoedString).toBe("hello");
+
+    // echoStrings
+
+    connection1.remote.echoStrings("hello", "world", function(a, b) {
+      echoedString = a + " " + b;
+    });
+
+    mockSupport.pumpOnce(core.RESULT_OK);
+
+    expect(echoedString).toBe("hello world");
+  }
+});
diff --git a/mojo/apps/js/bindings/connector_unittests.js b/mojo/apps/js/bindings/connector_unittests.js
deleted file mode 100644
index 8777b6f..0000000
--- a/mojo/apps/js/bindings/connector_unittests.js
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Mock out the support module to avoid depending on the message loop.
-define("mojo/bindings/js/support", function() {
-  var waitingCallbacks = [];
-
-  function WaitCookie(id) {
-    this.id = id;
-  }
-
-  function asyncWait(handle, flags, callback) {
-    var id = waitingCallbacks.length;
-    waitingCallbacks.push(callback);
-    return new WaitCookie(id);
-  }
-
-  function cancelWait(cookie) {
-    waitingCallbacks[cookie.id] = null;
-  }
-
-  function numberOfWaitingCallbacks() {
-    var count = 0;
-    for (var i = 0; i < waitingCallbacks.length; ++i) {
-      if (waitingCallbacks[i])
-        ++count;
-    }
-    return count;
-  }
-
-  function pumpOnce(result) {
-    var callbacks = waitingCallbacks;
-    waitingCallbacks = [];
-    for (var i = 0; i < callbacks.length; ++i)
-      callbacks[i](result);
-  }
-
-  var exports = {};
-  exports.asyncWait = asyncWait;
-  exports.cancelWait = cancelWait;
-  exports.numberOfWaitingCallbacks = numberOfWaitingCallbacks;
-  exports.pumpOnce = pumpOnce;
-  return exports;
-});
-
-define([
-    "gin/test/expect",
-    "mojo/bindings/js/support",
-    "mojo/bindings/js/core",
-    "mojo/public/bindings/js/connector",
-    "mojo/public/bindings/tests/sample_service.mojom",
-], function(expect, mockSupport, core, connector, sample) {
-
-  var receivedFrobinate = false;
-  var receivedDidFrobinate = false;
-
-  // ServiceImpl --------------------------------------------------------------
-
-  function ServiceImpl(peer) {
-    this.peer = peer;
-  }
-
-  ServiceImpl.prototype = Object.create(sample.ServiceStub.prototype);
-
-  ServiceImpl.prototype.frobinate = function(foo, baz, port) {
-    receivedFrobinate = true;
-
-    expect(foo.name).toBe("Example name");
-    expect(baz).toBeTruthy();
-    expect(core.close(port)).toBe(core.RESULT_OK);
-
-    this.peer.didFrobinate(42);
-  };
-
-  // ServiceImpl --------------------------------------------------------------
-
-  function ServiceClientImpl(peer) {
-    this.peer = peer;
-  }
-
-  ServiceClientImpl.prototype =
-      Object.create(sample.ServiceClientStub.prototype);
-
-  ServiceClientImpl.prototype.didFrobinate = function(result) {
-    receivedDidFrobinate = true;
-
-    expect(result).toBe(42);
-  };
-
-  var pipe = core.createMessagePipe();
-  var anotherPipe = core.createMessagePipe();
-  var sourcePipe = core.createMessagePipe();
-
-  var connection0 = new connector.Connection(
-      pipe.handle0, ServiceImpl, sample.ServiceClientProxy);
-
-  var connection1 = new connector.Connection(
-      pipe.handle1, ServiceClientImpl, sample.ServiceProxy);
-
-  var foo = new sample.Foo();
-  foo.bar = new sample.Bar();
-  foo.name = "Example name";
-  foo.source = sourcePipe.handle0;
-  connection1.remote.frobinate(foo, true, anotherPipe.handle0);
-
-  mockSupport.pumpOnce(core.RESULT_OK);
-
-  expect(receivedFrobinate).toBeTruthy();
-  expect(receivedDidFrobinate).toBeTruthy();
-
-  connection0.close();
-  connection1.close();
-
-  expect(mockSupport.numberOfWaitingCallbacks()).toBe(0);
-
-  // sourcePipe.handle0 was closed automatically when sent over IPC.
-  expect(core.close(sourcePipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
-  // sourcePipe.handle1 hasn't been closed yet.
-  expect(core.close(sourcePipe.handle1)).toBe(core.RESULT_OK);
-
-  // anotherPipe.handle0 was closed automatically when sent over IPC.
-  expect(core.close(anotherPipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
-  // anotherPipe.handle1 hasn't been closed yet.
-  expect(core.close(anotherPipe.handle1)).toBe(core.RESULT_OK);
-
-  // The Connection object is responsible for closing these handles.
-  expect(core.close(pipe.handle0)).toBe(core.RESULT_INVALID_ARGUMENT);
-  expect(core.close(pipe.handle1)).toBe(core.RESULT_INVALID_ARGUMENT);
-
-  this.result = "PASS";
-});
diff --git a/mojo/apps/js/bindings/monotonic_clock.cc b/mojo/apps/js/bindings/monotonic_clock.cc
index 3ca87af..733af8a 100644
--- a/mojo/apps/js/bindings/monotonic_clock.cc
+++ b/mojo/apps/js/bindings/monotonic_clock.cc
@@ -7,7 +7,7 @@
 #include "gin/object_template_builder.h"
 #include "gin/per_isolate_data.h"
 #include "gin/public/wrapper_info.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 namespace apps {
diff --git a/mojo/apps/js/main.cc b/mojo/apps/js/main.cc
index 26dc5a3..a712c2a 100644
--- a/mojo/apps/js/main.cc
+++ b/mojo/apps/js/main.cc
@@ -5,9 +5,9 @@
 #include "base/message_loop/message_loop.h"
 #include "gin/public/isolate_holder.h"
 #include "mojo/apps/js/mojo_runner_delegate.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/system/macros.h"
 #include "mojo/public/gles2/gles2_cpp.h"
-#include "mojo/public/system/core_cpp.h"
-#include "mojo/public/system/macros.h"
 
 #if defined(WIN32)
 #if !defined(CDECL)
diff --git a/mojo/apps/js/main.js b/mojo/apps/js/main.js
index 355fb97..6f6fb56 100644
--- a/mojo/apps/js/main.js
+++ b/mojo/apps/js/main.js
@@ -6,7 +6,7 @@
     'console',
     'monotonic_clock',
     'timer',
-    'mojo/public/bindings/js/connector',
+    'mojo/public/bindings/js/connection',
     'mojo/bindings/js/core',
     'mojo/apps/js/bindings/gl',
     'mojo/apps/js/bindings/threading',
@@ -15,7 +15,7 @@
 ], function(console,
             monotonicClock,
             timer,
-            connector,
+            connection,
             core,
             gljs,
             threading,
@@ -281,8 +281,8 @@
 
     var pipe = new core.createMessagePipe();
     this.shell_.connect('mojo:mojo_native_viewport_service', pipe.handle1);
-    new connector.Connection(pipe.handle0, NativeViewportClientImpl,
-                             nativeViewport.NativeViewportProxy);
+    new connection.Connection(pipe.handle0, NativeViewportClientImpl,
+                              nativeViewport.NativeViewportProxy);
   }
   // TODO(aa): It is a bummer to need this stub object in JavaScript. We should
   // have a 'client' object that contains both the sending and receiving bits of
@@ -390,6 +390,6 @@
 
 
   return function(handle) {
-    new connector.Connection(handle, SampleApp, shell.ShellProxy);
+    new connection.Connection(handle, SampleApp, shell.ShellProxy);
   };
 });
diff --git a/mojo/apps/js/mojo_runner_delegate.h b/mojo/apps/js/mojo_runner_delegate.h
index 04f7449..71ee4af 100644
--- a/mojo/apps/js/mojo_runner_delegate.h
+++ b/mojo/apps/js/mojo_runner_delegate.h
@@ -7,7 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "gin/modules/module_runner_delegate.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 
 namespace mojo {
 namespace apps {
diff --git a/mojo/apps/js/test/run_apps_js_tests.cc b/mojo/apps/js/test/run_apps_js_tests.cc
index 3427ca4..ade8c26 100644
--- a/mojo/apps/js/test/run_apps_js_tests.cc
+++ b/mojo/apps/js/test/run_apps_js_tests.cc
@@ -60,12 +60,12 @@
 
 // http://crbug.com/351214
 #if defined(OS_POSIX)
-#define MAYBE_connector DISABLED_connector
+#define MAYBE_connection DISABLED_connection
 #else
-#define MAYBE_connector connector
+#define MAYBE_connection connection
 #endif
-TEST(JSTest, MAYBE_connector) {
-  RunTest("connector_unittests.js", true);
+TEST(JSTest, MAYBE_connection) {
+  RunTest("connection_unittests.js", true);
 }
 
 TEST(JSTest, monotonic_clock) {
diff --git a/mojo/bindings/js/handle.h b/mojo/bindings/js/handle.h
index ee83396..3cd4cf5 100644
--- a/mojo/bindings/js/handle.h
+++ b/mojo/bindings/js/handle.h
@@ -6,7 +6,7 @@
 #define MOJO_BINDINGS_JS_HANDLE_H_
 
 #include "gin/converter.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace gin {
 
diff --git a/mojo/bindings/js/support.cc b/mojo/bindings/js/support.cc
index e5e5378..ba62e8a 100644
--- a/mojo/bindings/js/support.cc
+++ b/mojo/bindings/js/support.cc
@@ -14,8 +14,8 @@
 #include "gin/wrappable.h"
 #include "mojo/bindings/js/handle.h"
 #include "mojo/bindings/js/waiting_callback.h"
-#include "mojo/public/environment/default_async_waiter.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/environment/default_async_waiter.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 namespace js {
diff --git a/mojo/bindings/js/waiting_callback.h b/mojo/bindings/js/waiting_callback.h
index a7f5a49..bc17d19 100644
--- a/mojo/bindings/js/waiting_callback.h
+++ b/mojo/bindings/js/waiting_callback.h
@@ -8,7 +8,7 @@
 #include "gin/handle.h"
 #include "gin/runner.h"
 #include "gin/wrappable.h"
-#include "mojo/public/system/async_waiter.h"
+#include "mojo/public/c/system/async_waiter.h"
 
 namespace mojo {
 namespace js {
diff --git a/mojo/common/common_type_converters.cc b/mojo/common/common_type_converters.cc
index f02be67..3aa0e94 100644
--- a/mojo/common/common_type_converters.cc
+++ b/mojo/common/common_type_converters.cc
@@ -4,12 +4,18 @@
 
 #include "mojo/common/common_type_converters.h"
 
+#include <string>
+
+#include "base/strings/utf_string_conversions.h"
+
 namespace mojo {
 
 // static
 String TypeConverter<String, base::StringPiece>::ConvertFrom(
     const base::StringPiece& input,
     Buffer* buf) {
+  if (input.empty())
+    return String();
   String::Builder result(input.size(), buf);
   memcpy(&result[0], input.data(), input.size());
   return result.Finish();
@@ -21,4 +27,18 @@
                            base::StringPiece(&input[0], input.size());
 }
 
+// static
+String TypeConverter<String, base::string16>::ConvertFrom(
+    const base::string16& input,
+    Buffer* buf) {
+  return TypeConverter<String, base::StringPiece>::ConvertFrom(
+      base::UTF16ToUTF8(input), buf);
+}
+// static
+base::string16 TypeConverter<String, base::string16>::ConvertTo(
+    const String& input) {
+  return input.is_null() ? base::string16() :
+      base::UTF8ToUTF16(base::StringPiece(&input[0], input.size()));
+}
+
 }  // namespace mojo
diff --git a/mojo/common/common_type_converters.h b/mojo/common/common_type_converters.h
index 1c4ca75..5437ec4 100644
--- a/mojo/common/common_type_converters.h
+++ b/mojo/common/common_type_converters.h
@@ -5,6 +5,7 @@
 #ifndef MOJO_COMMON_COMMON_TYPE_CONVERTERS_H_
 #define MOJO_COMMON_COMMON_TYPE_CONVERTERS_H_
 
+#include "base/strings/string16.h"
 #include "base/strings/string_piece.h"
 #include "mojo/common/mojo_common_export.h"
 #include "mojo/public/bindings/array.h"
@@ -19,6 +20,13 @@
   static base::StringPiece ConvertTo(const String& input);
 };
 
+template <>
+class MOJO_COMMON_EXPORT TypeConverter<String, base::string16> {
+ public:
+  static String ConvertFrom(const base::string16& input, Buffer* buf);
+  static base::string16 ConvertTo(const String& input);
+};
+
 }  // namespace mojo
 
 #endif  // MOJO_COMMON_COMMON_TYPE_CONVERTERS_H_
diff --git a/mojo/common/common_type_converters_unittest.cc b/mojo/common/common_type_converters_unittest.cc
index 5c7a47b..1f3894c 100644
--- a/mojo/common/common_type_converters_unittest.cc
+++ b/mojo/common/common_type_converters_unittest.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "mojo/common/common_type_converters.h"
+
+#include "base/strings/utf_string_conversions.h"
 #include "mojo/public/bindings/allocation_scope.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -21,6 +23,16 @@
   EXPECT_EQ(expected, str.To<std::string>());
 }
 
+void ExpectEqualsString16(const base::string16& expected,
+                          const base::string16& actual) {
+  EXPECT_EQ(expected, actual);
+}
+
+void ExpectEqualsMojoString(const base::string16& expected,
+                            const String& str) {
+  EXPECT_EQ(expected, str.To<base::string16>());
+}
+
 }  // namespace
 
 TEST(CommonTypeConvertersTest, StringPiece) {
@@ -43,6 +55,23 @@
   EXPECT_TRUE(empty_string_piece.empty());
 }
 
+TEST(CommonTypeConvertersTest, String16) {
+  AllocationScope scope;
+
+  const base::string16 string16(base::ASCIIToUTF16("hello world"));
+  const String mojo_string(string16);
+
+  ExpectEqualsMojoString(string16, mojo_string);
+  EXPECT_EQ(string16, mojo_string.To<base::string16>());
+
+  // Test implicit construction and conversion:
+  ExpectEqualsMojoString(string16, string16);
+  ExpectEqualsString16(string16, mojo_string);
+
+  // Test empty string conversion.
+  ExpectEqualsMojoString(base::string16(), base::string16());
+}
+
 }  // namespace test
 }  // namespace common
 }  // namespace mojo
diff --git a/mojo/common/handle_watcher.h b/mojo/common/handle_watcher.h
index 115ac4a..aa151dc 100644
--- a/mojo/common/handle_watcher.h
+++ b/mojo/common/handle_watcher.h
@@ -10,7 +10,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/run_loop.h"
 #include "mojo/common/mojo_common_export.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace base {
 class Thread;
diff --git a/mojo/common/handle_watcher_unittest.cc b/mojo/common/handle_watcher_unittest.cc
index 4fc03b1..3eace0c 100644
--- a/mojo/common/handle_watcher_unittest.cc
+++ b/mojo/common/handle_watcher_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "mojo/common/time_helper.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/tests/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/mojo/common/message_pump_mojo.h b/mojo/common/message_pump_mojo.h
index b5b6443..cc21565 100644
--- a/mojo/common/message_pump_mojo.h
+++ b/mojo/common/message_pump_mojo.h
@@ -11,7 +11,7 @@
 #include "base/message_loop/message_pump.h"
 #include "base/time/time.h"
 #include "mojo/common/mojo_common_export.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 namespace common {
diff --git a/mojo/common/message_pump_mojo_handler.h b/mojo/common/message_pump_mojo_handler.h
index e8c6a86..5809051 100644
--- a/mojo/common/message_pump_mojo_handler.h
+++ b/mojo/common/message_pump_mojo_handler.h
@@ -6,7 +6,7 @@
 #define MOJO_COMMON_MESSAGE_PUMP_MOJO_HANDLER_H_
 
 #include "mojo/common/mojo_common_export.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 namespace common {
diff --git a/mojo/embedder/embedder.h b/mojo/embedder/embedder.h
index 097c7c6..9914104 100644
--- a/mojo/embedder/embedder.h
+++ b/mojo/embedder/embedder.h
@@ -9,7 +9,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/task_runner.h"
 #include "mojo/embedder/scoped_platform_handle.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/system/system_impl_export.h"
 
 namespace mojo {
diff --git a/mojo/embedder/embedder_unittest.cc b/mojo/embedder/embedder_unittest.cc
index 0a8eeab..be663fd 100644
--- a/mojo/embedder/embedder_unittest.cc
+++ b/mojo/embedder/embedder_unittest.cc
@@ -15,7 +15,7 @@
 #include "mojo/common/test/multiprocess_test_helper.h"
 #include "mojo/embedder/platform_channel_pair.h"
 #include "mojo/embedder/test_embedder.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/mojo/embedder/platform_channel_pair_posix.cc b/mojo/embedder/platform_channel_pair_posix.cc
index d9e65ed..2d5e2ca 100644
--- a/mojo/embedder/platform_channel_pair_posix.cc
+++ b/mojo/embedder/platform_channel_pair_posix.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/posix/global_descriptors.h"
 #include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
 #include "mojo/embedder/platform_handle.h"
 
 namespace mojo {
@@ -40,6 +41,17 @@
   PCHECK(fcntl(fds[0], F_SETFL, O_NONBLOCK) == 0);
   PCHECK(fcntl(fds[1], F_SETFL, O_NONBLOCK) == 0);
 
+#if defined(OS_MACOSX)
+  // This turns off |SIGPIPE| when writing to a closed socket (causing it to
+  // fail with |EPIPE| instead). On Linux, we have to use |send...()| with
+  // |MSG_NOSIGNAL| -- which is not supported on Mac -- instead.
+  int no_sigpipe = 1;
+  PCHECK(setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
+                    sizeof(no_sigpipe)) == 0);
+  PCHECK(setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &no_sigpipe,
+                    sizeof(no_sigpipe)) == 0);
+#endif  // defined(OS_MACOSX)
+
   server_handle_.reset(PlatformHandle(fds[0]));
   DCHECK(server_handle_.is_valid());
   client_handle_.reset(PlatformHandle(fds[1]));
diff --git a/mojo/embedder/platform_channel_pair_posix_unittest.cc b/mojo/embedder/platform_channel_pair_posix_unittest.cc
new file mode 100644
index 0000000..e03c053
--- /dev/null
+++ b/mojo/embedder/platform_channel_pair_posix_unittest.cc
@@ -0,0 +1,89 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/embedder/platform_channel_pair.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "mojo/embedder/scoped_platform_handle.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace embedder {
+namespace {
+
+class PlatformChannelPairPosixTest : public testing::Test {
+ public:
+  PlatformChannelPairPosixTest() {}
+  virtual ~PlatformChannelPairPosixTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    // Make sure |SIGPIPE| isn't being ignored.
+    struct sigaction action = {};
+    action.sa_handler = SIG_DFL;
+    ASSERT_EQ(0, sigaction(SIGPIPE, &action, &old_action_));
+  }
+
+  virtual void TearDown() OVERRIDE {
+    // Restore the |SIGPIPE| handler.
+    ASSERT_EQ(0, sigaction(SIGPIPE, &old_action_, NULL));
+  }
+
+ private:
+  struct sigaction old_action_;
+
+  DISALLOW_COPY_AND_ASSIGN(PlatformChannelPairPosixTest);
+};
+
+TEST_F(PlatformChannelPairPosixTest, NoSigPipe) {
+  PlatformChannelPair channel_pair;
+
+  ScopedPlatformHandle server_handle = channel_pair.PassServerHandle().Pass();
+  ScopedPlatformHandle client_handle = channel_pair.PassClientHandle().Pass();
+
+  // Write to the client.
+  static const char kHello[] = "hello";
+  EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
+            write(client_handle.get().fd, kHello, sizeof(kHello)));
+
+  // Close the client.
+  client_handle.reset();
+
+  // Read from the server; this should be okay.
+  char buffer[100] = {};
+  EXPECT_EQ(static_cast<ssize_t>(sizeof(kHello)),
+            read(server_handle.get().fd, buffer, sizeof(buffer)));
+  EXPECT_STREQ(kHello, buffer);
+
+  // Try reading again.
+  ssize_t result = read(server_handle.get().fd, buffer, sizeof(buffer));
+  // We should probably get zero (for "end of file"), but -1 would also be okay.
+  EXPECT_TRUE(result == 0 || result == -1);
+  if (result == -1)
+    PLOG(WARNING) << "read (expected 0 for EOF)";
+
+  // However, |write()|/|send()| should fail outright.
+  // On Mac, |SIGPIPE| needs to be suppressed on the socket itself and we can
+  // use |write()|/|writev()|. On Linux, we have to suppress it by using
+  // |send()|/|sendmsg()| with |MSG_NOSIGNAL|.
+#if defined(OS_MACOSX)
+  result = write(server_handle.get().fd, kHello, sizeof(kHello));
+#else
+  result = send(server_handle.get().fd, kHello, sizeof(kHello), MSG_NOSIGNAL);
+#endif
+  EXPECT_EQ(-1, result);
+  if (errno != EPIPE)
+    PLOG(WARNING) << "write (expected EPIPE)";
+}
+
+}  // namespace
+}  // namespace embedder
+}  // namespace mojo
diff --git a/mojo/environment/async_waiter_impl.h b/mojo/environment/async_waiter_impl.h
index 686d3ce..1d7335d 100644
--- a/mojo/environment/async_waiter_impl.h
+++ b/mojo/environment/async_waiter_impl.h
@@ -5,8 +5,8 @@
 #ifndef MOJO_ENVIRONMENT_ASYNC_WAITER_IMPL_H_
 #define MOJO_ENVIRONMENT_ASYNC_WAITER_IMPL_H_
 
-#include "mojo/public/environment/async_waiter.h"
 #include "mojo/environment/mojo_environment_impl_export.h"
+#include "mojo/public/cpp/environment/async_waiter.h"
 
 namespace mojo {
 namespace internal {
diff --git a/mojo/environment/buffer_tls.cc b/mojo/environment/buffer_tls.cc
index 4d078ef..827b493 100644
--- a/mojo/environment/buffer_tls.cc
+++ b/mojo/environment/buffer_tls.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "mojo/public/environment/buffer_tls.h"
+#include "mojo/public/cpp/environment/buffer_tls.h"
 
 #include "mojo/environment/buffer_tls_impl.h"
 
diff --git a/mojo/environment/default_async_waiter.cc b/mojo/environment/default_async_waiter.cc
index 7a46c07..bbd7229 100644
--- a/mojo/environment/default_async_waiter.cc
+++ b/mojo/environment/default_async_waiter.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "mojo/public/environment/default_async_waiter.h"
+#include "mojo/public/cpp/environment/default_async_waiter.h"
 
 #include "mojo/environment/default_async_waiter_impl.h"
 
diff --git a/mojo/environment/default_async_waiter_impl.h b/mojo/environment/default_async_waiter_impl.h
index cf2f7c2..266a70f 100644
--- a/mojo/environment/default_async_waiter_impl.h
+++ b/mojo/environment/default_async_waiter_impl.h
@@ -6,7 +6,7 @@
 #define MOJO_ENVIRONMENT_DEFAULT_ASYNC_WAITER_IMPL_H_
 
 #include "mojo/environment/mojo_environment_impl_export.h"
-#include "mojo/public/system/async_waiter.h"
+#include "mojo/public/c/system/async_waiter.h"
 
 namespace mojo {
 namespace internal {
diff --git a/mojo/environment/environment.cc b/mojo/environment/environment.cc
index c65908c..27af33b 100644
--- a/mojo/environment/environment.cc
+++ b/mojo/environment/environment.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
 
 namespace mojo {
 
diff --git a/mojo/examples/aura_demo/aura_demo.cc b/mojo/examples/aura_demo/aura_demo.cc
index a65036a..0b5391d 100644
--- a/mojo/examples/aura_demo/aura_demo.cc
+++ b/mojo/examples/aura_demo/aura_demo.cc
@@ -11,11 +11,10 @@
 #include "mojo/examples/aura_demo/demo_screen.h"
 #include "mojo/examples/aura_demo/window_tree_host_mojo.h"
 #include "mojo/public/bindings/allocation_scope.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/gles2/gles2_cpp.h"
 #include "mojo/public/shell/application.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core.h"
-#include "mojo/public/system/macros.h"
 #include "mojo/services/native_viewport/native_viewport.mojom.h"
 #include "ui/aura/client/default_capture_client.h"
 #include "ui/aura/client/window_tree_client.h"
@@ -76,8 +75,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
   virtual bool HasHitTestMask() const OVERRIDE { return false; }
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE {}
 
  private:
   SkColor color_;
diff --git a/mojo/examples/compositor_app/compositor_app.cc b/mojo/examples/compositor_app/compositor_app.cc
index 68e9350..75ca06f 100644
--- a/mojo/examples/compositor_app/compositor_app.cc
+++ b/mojo/examples/compositor_app/compositor_app.cc
@@ -10,11 +10,10 @@
 #include "mojo/examples/compositor_app/compositor_host.h"
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/remote_ptr.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/gles2/gles2_cpp.h"
 #include "mojo/public/shell/application.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core.h"
-#include "mojo/public/system/macros.h"
 #include "mojo/services/native_viewport/geometry_conversions.h"
 #include "mojo/services/native_viewport/native_viewport.mojom.h"
 #include "ui/gfx/rect.h"
diff --git a/mojo/examples/compositor_app/compositor_host.h b/mojo/examples/compositor_app/compositor_host.h
index 97f5b14..5bbe71d 100644
--- a/mojo/examples/compositor_app/compositor_host.h
+++ b/mojo/examples/compositor_app/compositor_host.h
@@ -9,7 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/thread.h"
 #include "cc/trees/layer_tree_host_client.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "ui/gfx/size.h"
 
 namespace cc {
diff --git a/mojo/examples/compositor_app/mojo_context_provider.h b/mojo/examples/compositor_app/mojo_context_provider.h
index 884470a..4f2cc15 100644
--- a/mojo/examples/compositor_app/mojo_context_provider.h
+++ b/mojo/examples/compositor_app/mojo_context_provider.h
@@ -3,8 +3,8 @@
 // found in the LICENSE file.
 
 #include "cc/output/context_provider.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/gles2/gles2.h"
-#include "mojo/public/system/core_cpp.h"
 
 namespace mojo {
 namespace examples {
diff --git a/mojo/examples/launcher/launcher.cc b/mojo/examples/launcher/launcher.cc
index a641c0f..310d526 100644
--- a/mojo/examples/launcher/launcher.cc
+++ b/mojo/examples/launcher/launcher.cc
@@ -17,11 +17,10 @@
 #include "mojo/examples/launcher/launcher.mojom.h"
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/remote_ptr.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/gles2/gles2_cpp.h"
 #include "mojo/public/shell/application.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core.h"
-#include "mojo/public/system/macros.h"
 #include "mojo/services/native_viewport/native_viewport.mojom.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/default_activation_client.h"
diff --git a/mojo/examples/pepper_container_app/DEPS b/mojo/examples/pepper_container_app/DEPS
new file mode 100644
index 0000000..b1e8ef3
--- /dev/null
+++ b/mojo/examples/pepper_container_app/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+base",
+  "+ppapi/c",
+  "+ppapi/shared_impl",
+  "+ppapi/thunk",
+]
diff --git a/mojo/examples/pepper_container_app/graphics_3d_resource.cc b/mojo/examples/pepper_container_app/graphics_3d_resource.cc
new file mode 100644
index 0000000..d354cef
--- /dev/null
+++ b/mojo/examples/pepper_container_app/graphics_3d_resource.cc
@@ -0,0 +1,170 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/examples/pepper_container_app/graphics_3d_resource.h"
+
+#include "base/logging.h"
+#include "mojo/examples/pepper_container_app/mojo_ppapi_globals.h"
+#include "mojo/examples/pepper_container_app/plugin_instance.h"
+#include "mojo/public/gles2/gles2.h"
+#include "ppapi/c/pp_errors.h"
+
+namespace mojo {
+namespace examples {
+
+namespace {
+
+gpu::CommandBuffer::State GetErrorState() {
+  gpu::CommandBuffer::State error_state;
+  error_state.error = gpu::error::kGenericError;
+  return error_state;
+}
+
+}  // namespace
+
+Graphics3DResource::Graphics3DResource(PP_Instance instance)
+    : Resource(ppapi::OBJECT_IS_IMPL, instance) {
+  ScopedMessagePipeHandle pipe = MojoPpapiGlobals::Get()->CreateGLES2Context();
+  context_ = MojoGLES2CreateContext(pipe.release().value(),
+                                    &ContextLostThunk,
+                                    &DrawAnimationFrameThunk,
+                                    this);
+}
+
+bool Graphics3DResource::IsBoundGraphics() const {
+  PluginInstance* plugin_instance =
+      MojoPpapiGlobals::Get()->GetInstance(pp_instance());
+  return plugin_instance && plugin_instance->IsBoundGraphics(pp_resource());
+}
+
+void Graphics3DResource::BindGraphics() {
+  MojoGLES2MakeCurrent(context_);
+}
+
+ppapi::thunk::PPB_Graphics3D_API* Graphics3DResource::AsPPB_Graphics3D_API() {
+  return this;
+}
+
+int32_t Graphics3DResource::GetAttribs(int32_t attrib_list[]) {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+int32_t Graphics3DResource::SetAttribs(const int32_t attrib_list[]) {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+int32_t Graphics3DResource::GetError() {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+int32_t Graphics3DResource::ResizeBuffers(int32_t width, int32_t height) {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+int32_t Graphics3DResource::SwapBuffers(
+    scoped_refptr<ppapi::TrackedCallback> callback) {
+  if (!IsBoundGraphics())
+    return PP_ERROR_FAILED;
+
+  MojoGLES2SwapBuffers();
+  return PP_OK;
+}
+
+int32_t Graphics3DResource::GetAttribMaxValue(int32_t attribute,
+                                              int32_t* value) {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+PP_Bool Graphics3DResource::SetGetBuffer(int32_t shm_id) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+gpu::CommandBuffer::State Graphics3DResource::GetState() {
+  NOTIMPLEMENTED();
+  return GetErrorState();
+}
+
+int32_t Graphics3DResource::CreateTransferBuffer(uint32_t size) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Bool Graphics3DResource::DestroyTransferBuffer(int32_t id) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Bool Graphics3DResource::GetTransferBuffer(int32_t id,
+                                              int* shm_handle,
+                                              uint32_t* shm_size) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Bool Graphics3DResource::Flush(int32_t put_offset) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+gpu::CommandBuffer::State Graphics3DResource::WaitForTokenInRange(int32_t start,
+                                                                  int32_t end) {
+  NOTIMPLEMENTED();
+  return GetErrorState();
+}
+
+gpu::CommandBuffer::State Graphics3DResource::WaitForGetOffsetInRange(
+    int32_t start, int32_t end) {
+  NOTIMPLEMENTED();
+  return GetErrorState();
+}
+
+void* Graphics3DResource::MapTexSubImage2DCHROMIUM(GLenum target,
+                                                   GLint level,
+                                                   GLint xoffset,
+                                                   GLint yoffset,
+                                                   GLsizei width,
+                                                   GLsizei height,
+                                                   GLenum format,
+                                                   GLenum type,
+                                                   GLenum access) {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+void Graphics3DResource::UnmapTexSubImage2DCHROMIUM(const void* mem) {
+  NOTIMPLEMENTED();
+}
+
+uint32_t Graphics3DResource::InsertSyncPoint() {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+Graphics3DResource::~Graphics3DResource() {
+  MojoGLES2DestroyContext(context_);
+}
+
+void Graphics3DResource::ContextLostThunk(void* closure) {
+  static_cast<Graphics3DResource*>(closure)->ContextLost();
+}
+
+void Graphics3DResource::DrawAnimationFrameThunk(void* closure) {
+  // TODO(yzshen): Use this notification to drive the SwapBuffers() callback.
+}
+
+void Graphics3DResource::ContextLost() {
+  PluginInstance* plugin_instance =
+      MojoPpapiGlobals::Get()->GetInstance(pp_instance());
+  if (plugin_instance)
+    plugin_instance->Graphics3DContextLost();
+}
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/graphics_3d_resource.h b/mojo/examples/pepper_container_app/graphics_3d_resource.h
new file mode 100644
index 0000000..482c678
--- /dev/null
+++ b/mojo/examples/pepper_container_app/graphics_3d_resource.h
@@ -0,0 +1,75 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_GRAPHICS_3D_RESOURCE_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_GRAPHICS_3D_RESOURCE_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "mojo/public/gles2/gles2_types.h"
+#include "ppapi/shared_impl/resource.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/ppb_graphics_3d_api.h"
+
+namespace mojo {
+namespace examples {
+
+class Graphics3DResource : public ppapi::Resource,
+                           public ppapi::thunk::PPB_Graphics3D_API {
+ public:
+  explicit Graphics3DResource(PP_Instance instance);
+
+  bool IsBoundGraphics() const;
+  void BindGraphics();
+
+  // ppapi::Resource overrides.
+  virtual ppapi::thunk::PPB_Graphics3D_API* AsPPB_Graphics3D_API() OVERRIDE;
+
+  // ppapi::thunk::PPB_Graphics3D_API implementation.
+  virtual int32_t GetAttribs(int32_t attrib_list[]) OVERRIDE;
+  virtual int32_t SetAttribs(const int32_t attrib_list[]) OVERRIDE;
+  virtual int32_t GetError() OVERRIDE;
+  virtual int32_t ResizeBuffers(int32_t width, int32_t height) OVERRIDE;
+  virtual int32_t SwapBuffers(
+      scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
+  virtual int32_t GetAttribMaxValue(int32_t attribute, int32_t* value) OVERRIDE;
+  virtual PP_Bool SetGetBuffer(int32_t shm_id) OVERRIDE;
+  virtual gpu::CommandBuffer::State GetState() OVERRIDE;
+  virtual int32_t CreateTransferBuffer(uint32_t size) OVERRIDE;
+  virtual PP_Bool DestroyTransferBuffer(int32_t id) OVERRIDE;
+  virtual PP_Bool GetTransferBuffer(int32_t id,
+                                    int* shm_handle,
+                                    uint32_t* shm_size) OVERRIDE;
+  virtual PP_Bool Flush(int32_t put_offset) OVERRIDE;
+  virtual gpu::CommandBuffer::State WaitForTokenInRange(int32_t start,
+                                                        int32_t end) OVERRIDE;
+  virtual gpu::CommandBuffer::State WaitForGetOffsetInRange(
+      int32_t start, int32_t end) OVERRIDE;
+  virtual void* MapTexSubImage2DCHROMIUM(GLenum target,
+                                         GLint level,
+                                         GLint xoffset,
+                                         GLint yoffset,
+                                         GLsizei width,
+                                         GLsizei height,
+                                         GLenum format,
+                                         GLenum type,
+                                         GLenum access) OVERRIDE;
+  virtual void UnmapTexSubImage2DCHROMIUM(const void* mem) OVERRIDE;
+  virtual uint32_t InsertSyncPoint() OVERRIDE;
+
+ private:
+  virtual ~Graphics3DResource();
+
+  static void ContextLostThunk(void* closure);
+  static void DrawAnimationFrameThunk(void* closure);
+  void ContextLost();
+
+  MojoGLES2Context context_;
+  DISALLOW_COPY_AND_ASSIGN(Graphics3DResource);
+};
+
+}  // namespace examples
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_GRAPHICS_3D_RESOURCE_H_
diff --git a/mojo/examples/pepper_container_app/interface_list.cc b/mojo/examples/pepper_container_app/interface_list.cc
new file mode 100644
index 0000000..7f4d2ea
--- /dev/null
+++ b/mojo/examples/pepper_container_app/interface_list.cc
@@ -0,0 +1,50 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/examples/pepper_container_app/interface_list.h"
+
+#include "base/memory/singleton.h"
+#include "mojo/examples/pepper_container_app/thunk.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_graphics_3d.h"
+#include "ppapi/c/ppb_instance.h"
+#include "ppapi/c/ppb_opengles2.h"
+#include "ppapi/c/ppb_view.h"
+#include "ppapi/thunk/thunk.h"
+
+namespace mojo {
+namespace examples {
+
+InterfaceList::InterfaceList() {
+  browser_interfaces_[PPB_CORE_INTERFACE_1_0] = GetPPB_Core_1_0_Thunk();
+  browser_interfaces_[PPB_GRAPHICS_3D_INTERFACE_1_0] =
+      ppapi::thunk::GetPPB_Graphics3D_1_0_Thunk();
+  browser_interfaces_[PPB_OPENGLES2_INTERFACE_1_0] =
+      GetPPB_OpenGLES2_Thunk();
+  browser_interfaces_[PPB_INSTANCE_INTERFACE_1_0] =
+      ppapi::thunk::GetPPB_Instance_1_0_Thunk();
+  browser_interfaces_[PPB_VIEW_INTERFACE_1_0] =
+      ppapi::thunk::GetPPB_View_1_0_Thunk();
+  browser_interfaces_[PPB_VIEW_INTERFACE_1_1] =
+      ppapi::thunk::GetPPB_View_1_1_Thunk();
+}
+
+InterfaceList::~InterfaceList() {}
+
+// static
+InterfaceList* InterfaceList::GetInstance() {
+  return Singleton<InterfaceList>::get();
+}
+
+const void* InterfaceList::GetBrowserInterface(const std::string& name) const {
+  NameToInterfaceMap::const_iterator iter = browser_interfaces_.find(name);
+
+  if (iter == browser_interfaces_.end())
+    return NULL;
+
+  return iter->second;
+}
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/interface_list.h b/mojo/examples/pepper_container_app/interface_list.h
new file mode 100644
index 0000000..5cff06c
--- /dev/null
+++ b/mojo/examples/pepper_container_app/interface_list.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_INTERFACE_LIST_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_INTERFACE_LIST_H_
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+
+namespace mojo {
+namespace examples {
+
+// InterfaceList maintains the mapping from Pepper interface names to
+// interface pointers.
+class InterfaceList {
+ public:
+  InterfaceList();
+  ~InterfaceList();
+
+  static InterfaceList* GetInstance();
+
+  const void* GetBrowserInterface(const std::string& name) const;
+
+ private:
+  typedef std::map<std::string, const void*> NameToInterfaceMap;
+  NameToInterfaceMap browser_interfaces_;
+
+  DISALLOW_COPY_AND_ASSIGN(InterfaceList);
+};
+
+}  // namespace examples
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_INTERFACE_LIST_H_
diff --git a/mojo/examples/pepper_container_app/mojo_ppapi_globals.cc b/mojo/examples/pepper_container_app/mojo_ppapi_globals.cc
new file mode 100644
index 0000000..33f8717
--- /dev/null
+++ b/mojo/examples/pepper_container_app/mojo_ppapi_globals.cc
@@ -0,0 +1,184 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/examples/pepper_container_app/mojo_ppapi_globals.h"
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/time/time.h"
+#include "mojo/examples/pepper_container_app/plugin_instance.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/shared_impl/ppb_message_loop_shared.h"
+
+namespace mojo {
+namespace examples {
+
+namespace {
+
+const PP_Instance kInstanceId = 1;
+
+}  // namespace
+
+// A non-abstract subclass of ppapi::MessageLoopShared that represents the
+// message loop of the main thread.
+// TODO(yzshen): Build a more general ppapi::MessageLoopShared subclass to fully
+// support PPB_MessageLoop.
+class MojoPpapiGlobals::MainThreadMessageLoopResource
+    : public ppapi::MessageLoopShared {
+ public:
+  explicit MainThreadMessageLoopResource(
+      base::MessageLoopProxy* main_thread_message_loop)
+      : MessageLoopShared(ForMainThread()),
+        main_thread_message_loop_(main_thread_message_loop) {}
+
+  // ppapi::MessageLoopShared implementation.
+  virtual void PostClosure(const tracked_objects::Location& from_here,
+                           const base::Closure& closure,
+                           int64 delay_ms) OVERRIDE {
+    main_thread_message_loop_->PostDelayedTask(
+        from_here, closure, base::TimeDelta::FromMilliseconds(delay_ms));
+  }
+
+  virtual base::MessageLoopProxy* GetMessageLoopProxy() OVERRIDE {
+    return main_thread_message_loop_.get();
+  }
+
+  // ppapi::thunk::PPB_MessageLoop_API implementation.
+  virtual int32_t AttachToCurrentThread() OVERRIDE {
+    NOTIMPLEMENTED();
+    return PP_ERROR_FAILED;
+  }
+
+  virtual int32_t Run() OVERRIDE {
+    NOTIMPLEMENTED();
+    return PP_ERROR_FAILED;
+  }
+
+  virtual int32_t PostWork(PP_CompletionCallback callback,
+                           int64_t delay_ms) OVERRIDE {
+    NOTIMPLEMENTED();
+    return PP_ERROR_FAILED;
+  }
+
+  virtual int32_t PostQuit(PP_Bool should_destroy) OVERRIDE {
+    NOTIMPLEMENTED();
+    return PP_ERROR_FAILED;
+  }
+
+ private:
+  virtual ~MainThreadMessageLoopResource() {}
+
+  scoped_refptr<base::MessageLoopProxy> main_thread_message_loop_;
+  DISALLOW_COPY_AND_ASSIGN(MainThreadMessageLoopResource);
+};
+
+MojoPpapiGlobals::MojoPpapiGlobals(Delegate* delegate)
+    : delegate_(delegate),
+      plugin_instance_(NULL),
+      resource_tracker_(ppapi::ResourceTracker::THREAD_SAFE) {}
+
+MojoPpapiGlobals::~MojoPpapiGlobals() {}
+
+PP_Instance MojoPpapiGlobals::AddInstance(PluginInstance* instance) {
+  DCHECK(!plugin_instance_);
+  plugin_instance_ = instance;
+  resource_tracker_.DidCreateInstance(kInstanceId);
+  return kInstanceId;
+}
+
+void MojoPpapiGlobals::InstanceDeleted(PP_Instance instance) {
+  DCHECK_EQ(instance, kInstanceId);
+  DCHECK(plugin_instance_);
+  resource_tracker_.DidDeleteInstance(instance);
+  plugin_instance_ = NULL;
+}
+
+PluginInstance* MojoPpapiGlobals::GetInstance(PP_Instance instance) {
+  if (instance == kInstanceId)
+    return plugin_instance_;
+  return NULL;
+}
+
+ScopedMessagePipeHandle MojoPpapiGlobals::CreateGLES2Context() {
+  return delegate_->CreateGLES2Context();
+}
+
+ppapi::ResourceTracker* MojoPpapiGlobals::GetResourceTracker() {
+  return &resource_tracker_;
+}
+
+ppapi::VarTracker* MojoPpapiGlobals::GetVarTracker() {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+ppapi::CallbackTracker* MojoPpapiGlobals::GetCallbackTrackerForInstance(
+    PP_Instance instance) {
+  if (instance == kInstanceId && plugin_instance_)
+    return plugin_instance_->plugin_module()->callback_tracker();
+  return NULL;
+}
+
+void MojoPpapiGlobals::LogWithSource(PP_Instance instance,
+                                     PP_LogLevel level,
+                                     const std::string& source,
+                                     const std::string& value) {
+  NOTIMPLEMENTED();
+}
+
+void MojoPpapiGlobals::BroadcastLogWithSource(PP_Module module,
+                                              PP_LogLevel level,
+                                              const std::string& source,
+                                              const std::string& value) {
+  NOTIMPLEMENTED();
+}
+
+ppapi::thunk::PPB_Instance_API* MojoPpapiGlobals::GetInstanceAPI(
+    PP_Instance instance) {
+  if (instance == kInstanceId && plugin_instance_)
+    return plugin_instance_;
+  return NULL;
+}
+
+ppapi::thunk::ResourceCreationAPI* MojoPpapiGlobals::GetResourceCreationAPI(
+    PP_Instance instance) {
+  if (instance == kInstanceId && plugin_instance_)
+    return plugin_instance_->resource_creation();
+  return NULL;
+}
+
+PP_Module MojoPpapiGlobals::GetModuleForInstance(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+ppapi::MessageLoopShared* MojoPpapiGlobals::GetCurrentMessageLoop() {
+  if (base::MessageLoopProxy::current().get() == GetMainThreadMessageLoop()) {
+    if (!main_thread_message_loop_resource_) {
+      main_thread_message_loop_resource_ = new MainThreadMessageLoopResource(
+          GetMainThreadMessageLoop());
+    }
+    return main_thread_message_loop_resource_.get();
+  }
+
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+base::TaskRunner* MojoPpapiGlobals::GetFileTaskRunner() {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+std::string MojoPpapiGlobals::GetCmdLine() {
+  NOTIMPLEMENTED();
+  return std::string();
+}
+
+void MojoPpapiGlobals::PreCacheFontForFlash(const void* logfontw) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/mojo_ppapi_globals.h b/mojo/examples/pepper_container_app/mojo_ppapi_globals.h
new file mode 100644
index 0000000..349f885
--- /dev/null
+++ b/mojo/examples/pepper_container_app/mojo_ppapi_globals.h
@@ -0,0 +1,90 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_MOJO_PPAPI_GLOBALS_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_MOJO_PPAPI_GLOBALS_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "mojo/public/cpp/system/core.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+
+namespace base {
+class MessageLoopProxy;
+}
+
+namespace mojo {
+namespace examples {
+
+class PluginInstance;
+
+class MojoPpapiGlobals : public ppapi::PpapiGlobals {
+ public:
+  class Delegate {
+   public:
+    virtual ~Delegate() {}
+
+    virtual ScopedMessagePipeHandle CreateGLES2Context() = 0;
+  };
+
+  // |delegate| must live longer than this object.
+  explicit MojoPpapiGlobals(Delegate* delegate);
+  virtual ~MojoPpapiGlobals();
+
+  inline static MojoPpapiGlobals* Get() {
+    return static_cast<MojoPpapiGlobals*>(PpapiGlobals::Get());
+  }
+
+  PP_Instance AddInstance(PluginInstance* instance);
+  void InstanceDeleted(PP_Instance instance);
+  PluginInstance* GetInstance(PP_Instance instance);
+
+  ScopedMessagePipeHandle CreateGLES2Context();
+
+  // ppapi::PpapiGlobals implementation.
+  virtual ppapi::ResourceTracker* GetResourceTracker() OVERRIDE;
+  virtual ppapi::VarTracker* GetVarTracker() OVERRIDE;
+  virtual ppapi::CallbackTracker* GetCallbackTrackerForInstance(
+      PP_Instance instance) OVERRIDE;
+  virtual void LogWithSource(PP_Instance instance,
+                             PP_LogLevel level,
+                             const std::string& source,
+                             const std::string& value) OVERRIDE;
+  virtual void BroadcastLogWithSource(PP_Module module,
+                                      PP_LogLevel level,
+                                      const std::string& source,
+                                      const std::string& value) OVERRIDE;
+  virtual ppapi::thunk::PPB_Instance_API* GetInstanceAPI(
+      PP_Instance instance) OVERRIDE;
+  virtual ppapi::thunk::ResourceCreationAPI* GetResourceCreationAPI(
+      PP_Instance instance) OVERRIDE;
+  virtual PP_Module GetModuleForInstance(PP_Instance instance) OVERRIDE;
+  virtual ppapi::MessageLoopShared* GetCurrentMessageLoop() OVERRIDE;
+  virtual base::TaskRunner* GetFileTaskRunner() OVERRIDE;
+  virtual std::string GetCmdLine() OVERRIDE;
+  virtual void PreCacheFontForFlash(const void* logfontw) OVERRIDE;
+
+ private:
+  class MainThreadMessageLoopResource;
+
+  // Non-owning pointer.
+  Delegate* const delegate_;
+
+  // Non-owning pointer.
+  PluginInstance* plugin_instance_;
+
+  ppapi::ResourceTracker resource_tracker_;
+
+  scoped_refptr<MainThreadMessageLoopResource>
+      main_thread_message_loop_resource_;
+
+  DISALLOW_COPY_AND_ASSIGN(MojoPpapiGlobals);
+};
+
+}  // namespace examples
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_MOJO_PPAPI_GLOBALS_H_
diff --git a/mojo/examples/pepper_container_app/pepper_container_app.cc b/mojo/examples/pepper_container_app/pepper_container_app.cc
new file mode 100644
index 0000000..ec45a45
--- /dev/null
+++ b/mojo/examples/pepper_container_app/pepper_container_app.cc
@@ -0,0 +1,134 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "build/build_config.h"
+#include "mojo/examples/pepper_container_app/mojo_ppapi_globals.h"
+#include "mojo/examples/pepper_container_app/plugin_instance.h"
+#include "mojo/examples/pepper_container_app/plugin_module.h"
+#include "mojo/examples/pepper_container_app/type_converters.h"
+#include "mojo/public/bindings/allocation_scope.h"
+#include "mojo/public/bindings/remote_ptr.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/gles2/gles2_cpp.h"
+#include "mojo/public/shell/application.h"
+#include "mojo/public/shell/shell.mojom.h"
+#include "mojo/services/native_viewport/native_viewport.mojom.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+
+#if defined(OS_WIN)
+#if !defined(CDECL)
+#define CDECL __cdecl
+#endif
+#define PEPPER_CONTAINER_APP_EXPORT __declspec(dllexport)
+#else
+#define CDECL
+#define PEPPER_CONTAINER_APP_EXPORT __attribute__((visibility("default")))
+#endif
+
+namespace mojo {
+namespace examples {
+
+class PepperContainerApp: public Application,
+                          public NativeViewportClient,
+                          public MojoPpapiGlobals::Delegate {
+ public:
+  explicit PepperContainerApp(MojoHandle shell_handle)
+      : Application(shell_handle),
+        ppapi_globals_(this),
+        plugin_module_(new PluginModule) {
+    InterfacePipe<NativeViewport, AnyInterface> viewport_pipe;
+    mojo::AllocationScope scope;
+    shell()->Connect("mojo:mojo_native_viewport_service",
+                     viewport_pipe.handle_to_peer.Pass());
+    viewport_.reset(viewport_pipe.handle_to_self.Pass(), this);
+    Rect::Builder rect;
+    Point::Builder point;
+    point.set_x(10);
+    point.set_y(10);
+    rect.set_position(point.Finish());
+    Size::Builder size;
+    size.set_width(800);
+    size.set_height(600);
+    rect.set_size(size.Finish());
+    viewport_->Create(rect.Finish());
+    viewport_->Show();
+  }
+
+  virtual ~PepperContainerApp() {}
+
+  // NativeViewportClient implementation.
+  virtual void OnCreated() OVERRIDE {
+    ppapi::ProxyAutoLock lock;
+
+    plugin_instance_ = plugin_module_->CreateInstance().Pass();
+    if (!plugin_instance_->DidCreate())
+      plugin_instance_.reset();
+  }
+
+  virtual void OnDestroyed() OVERRIDE {
+    ppapi::ProxyAutoLock lock;
+
+    if (plugin_instance_) {
+      plugin_instance_->DidDestroy();
+      plugin_instance_.reset();
+    }
+
+    base::MessageLoop::current()->Quit();
+  }
+
+  virtual void OnBoundsChanged(const Rect& bounds) OVERRIDE {
+    ppapi::ProxyAutoLock lock;
+
+    if (plugin_instance_)
+      plugin_instance_->DidChangeView(bounds);
+  }
+
+  virtual void OnEvent(const Event& event) OVERRIDE {
+    if (event.location().is_null())
+      return;
+
+    {
+      ppapi::ProxyAutoLock lock;
+
+      // TODO(yzshen): Handle events.
+    }
+    viewport_->AckEvent(event);
+  }
+
+  // MojoPpapiGlobals::Delegate implementation.
+  virtual ScopedMessagePipeHandle CreateGLES2Context() OVERRIDE {
+    MessagePipe gles2_pipe;
+    viewport_->CreateGLES2Context(gles2_pipe.handle1.Pass());
+    return gles2_pipe.handle0.Pass();
+  }
+
+ private:
+  MojoPpapiGlobals ppapi_globals_;
+
+  RemotePtr<NativeViewport> viewport_;
+  scoped_refptr<PluginModule> plugin_module_;
+  scoped_ptr<PluginInstance> plugin_instance_;
+
+  DISALLOW_COPY_AND_ASSIGN(PepperContainerApp);
+};
+
+}  // namespace examples
+}  // namespace mojo
+
+extern "C" PEPPER_CONTAINER_APP_EXPORT MojoResult CDECL MojoMain(
+    MojoHandle shell_handle) {
+  mojo::Environment env;
+  mojo::GLES2Initializer gles2;
+  base::MessageLoop run_loop;
+  mojo::examples::PepperContainerApp app(shell_handle);
+
+  run_loop.Run();
+  return MOJO_RESULT_OK;
+}
diff --git a/mojo/examples/pepper_container_app/plugin_instance.cc b/mojo/examples/pepper_container_app/plugin_instance.cc
new file mode 100644
index 0000000..cb39240
--- /dev/null
+++ b/mojo/examples/pepper_container_app/plugin_instance.cc
@@ -0,0 +1,384 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/examples/pepper_container_app/plugin_instance.h"
+
+#include "base/logging.h"
+#include "mojo/examples/pepper_container_app/graphics_3d_resource.h"
+#include "mojo/examples/pepper_container_app/mojo_ppapi_globals.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/pp_var.h"
+#include "ppapi/c/ppp_graphics_3d.h"
+#include "ppapi/c/ppp_instance.h"
+#include "ppapi/shared_impl/ppb_view_shared.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_graphics_3d_api.h"
+
+namespace mojo {
+namespace examples {
+
+PluginInstance::PluginInstance(scoped_refptr<PluginModule> plugin_module)
+    : pp_instance_(0),
+      plugin_module_(plugin_module) {
+  pp_instance_ = MojoPpapiGlobals::Get()->AddInstance(this);
+}
+
+PluginInstance::~PluginInstance() {
+  MojoPpapiGlobals::Get()->InstanceDeleted(pp_instance_);
+}
+
+bool PluginInstance::DidCreate() {
+  ppapi::ProxyAutoUnlock unlock;
+  const PPP_Instance_1_1* instance_interface =
+      static_cast<const PPP_Instance_1_1*>(plugin_module_->GetPluginInterface(
+          PPP_INSTANCE_INTERFACE_1_1));
+  return !!instance_interface->DidCreate(pp_instance(), 0, NULL, NULL);
+}
+
+void PluginInstance::DidDestroy() {
+  ppapi::ProxyAutoUnlock unlock;
+  const PPP_Instance_1_1* instance_interface =
+      static_cast<const PPP_Instance_1_1*>(plugin_module_->GetPluginInterface(
+          PPP_INSTANCE_INTERFACE_1_1));
+  instance_interface->DidDestroy(pp_instance());
+}
+
+void PluginInstance::DidChangeView(const PP_Rect& bounds) {
+  ppapi::ViewData view_data;
+  view_data.rect = bounds;
+  view_data.is_fullscreen = false;
+  view_data.is_page_visible = true;
+  view_data.clip_rect = bounds;
+  view_data.device_scale = 1.0f;
+  view_data.css_scale = 1.0f;
+
+  ppapi::ScopedPPResource resource(ppapi::ScopedPPResource::PassRef(),
+      (new ppapi::PPB_View_Shared(
+          ppapi::OBJECT_IS_IMPL, pp_instance(), view_data))->GetReference());
+  {
+    ppapi::ProxyAutoUnlock unlock;
+    const PPP_Instance_1_1* instance_interface =
+        static_cast<const PPP_Instance_1_1*>(plugin_module_->GetPluginInterface(
+            PPP_INSTANCE_INTERFACE_1_1));
+    instance_interface->DidChangeView(pp_instance(), resource);
+  }
+}
+
+void PluginInstance::Graphics3DContextLost() {
+  ppapi::ProxyAutoUnlock unlock;
+  const PPP_Graphics3D_1_0* graphic_3d_interface =
+      static_cast<const PPP_Graphics3D_1_0*>(plugin_module_->GetPluginInterface(
+          PPP_GRAPHICS_3D_INTERFACE_1_0));
+  // TODO(yzshen): Maybe we only need to notify for the bound graphics context?
+  graphic_3d_interface->Graphics3DContextLost(pp_instance());
+}
+
+bool PluginInstance::IsBoundGraphics(PP_Resource device) const {
+  return device != 0 && device == bound_graphics_.get();
+}
+
+PP_Bool PluginInstance::BindGraphics(PP_Instance instance, PP_Resource device) {
+  if (bound_graphics_.get() == device)
+    return PP_TRUE;
+
+  ppapi::thunk::EnterResourceNoLock<ppapi::thunk::PPB_Graphics3D_API>
+      enter(device, false);
+  if (enter.failed())
+    return PP_FALSE;
+
+  bound_graphics_ = device;
+  static_cast<Graphics3DResource*>(enter.object())->BindGraphics();
+
+  return PP_TRUE;
+}
+
+PP_Bool PluginInstance::IsFullFrame(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+const ppapi::ViewData* PluginInstance::GetViewData(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+PP_Bool PluginInstance::FlashIsFullscreen(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Var PluginInstance::GetWindowObject(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+PP_Var PluginInstance::GetOwnerElementObject(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+PP_Var PluginInstance::ExecuteScript(PP_Instance instance,
+                                     PP_Var script,
+                                     PP_Var* exception) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+uint32_t PluginInstance::GetAudioHardwareOutputSampleRate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+uint32_t PluginInstance::GetAudioHardwareOutputBufferSize(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Var PluginInstance::GetDefaultCharSet(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+void PluginInstance::Log(PP_Instance instance,
+                         PP_LogLevel log_level,
+                         PP_Var value) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::LogWithSource(PP_Instance instance,
+                                   PP_LogLevel log_level,
+                                   PP_Var source,
+                                   PP_Var value) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SetPluginToHandleFindRequests(PP_Instance instance) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::NumberOfFindResultsChanged(PP_Instance instance,
+                                                int32_t total,
+                                                PP_Bool final_result) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SelectedFindResultChanged(PP_Instance instance,
+                                               int32_t index) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SetTickmarks(PP_Instance instance,
+                                  const PP_Rect* tickmarks,
+                                  uint32_t count) {
+  NOTIMPLEMENTED();
+}
+
+PP_Bool PluginInstance::IsFullscreen(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Bool PluginInstance::SetFullscreen(PP_Instance instance,
+                                      PP_Bool fullscreen) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Bool PluginInstance::GetScreenSize(PP_Instance instance, PP_Size* size) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+ppapi::Resource* PluginInstance::GetSingletonResource(
+    PP_Instance instance,
+    ppapi::SingletonResourceID id) {
+  NOTIMPLEMENTED();
+  return NULL;
+}
+
+int32_t PluginInstance::RequestInputEvents(PP_Instance instance,
+                                           uint32_t event_classes) {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+int32_t PluginInstance::RequestFilteringInputEvents(PP_Instance instance,
+                                                    uint32_t event_classes) {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+void PluginInstance::ClearInputEventRequest(PP_Instance instance,
+                                            uint32_t event_classes) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::PostMessage(PP_Instance instance, PP_Var message) {
+  NOTIMPLEMENTED();
+}
+
+PP_Bool PluginInstance::SetCursor(PP_Instance instance,
+                                  PP_MouseCursor_Type type,
+                                  PP_Resource image,
+                                  const PP_Point* hot_spot) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+int32_t PluginInstance::LockMouse(
+    PP_Instance instance,
+    scoped_refptr<ppapi::TrackedCallback> callback) {
+  NOTIMPLEMENTED();
+  return PP_ERROR_FAILED;
+}
+
+void PluginInstance::UnlockMouse(PP_Instance instance) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SetTextInputType(PP_Instance instance,
+                                      PP_TextInput_Type type) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::UpdateCaretPosition(PP_Instance instance,
+                                         const PP_Rect& caret,
+                                         const PP_Rect& bounding_box) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::CancelCompositionText(PP_Instance instance) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SelectionChanged(PP_Instance instance) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::UpdateSurroundingText(PP_Instance instance,
+                                           const char* text,
+                                           uint32_t caret,
+                                           uint32_t anchor) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::ZoomChanged(PP_Instance instance, double factor) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::ZoomLimitsChanged(PP_Instance instance,
+                                       double minimum_factor,
+                                       double maximum_factor) {
+  NOTIMPLEMENTED();
+}
+
+PP_Var PluginInstance::GetDocumentURL(PP_Instance instance,
+                                      PP_URLComponents_Dev* components) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+void PluginInstance::SessionCreated(PP_Instance instance,
+                                    uint32_t session_id,
+                                    PP_Var web_session_id) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SessionMessage(PP_Instance instance,
+                                    uint32_t session_id,
+                                    PP_Var message,
+                                    PP_Var destination_url) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SessionReady(PP_Instance instance, uint32_t session_id) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SessionClosed(PP_Instance instance, uint32_t session_id) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::SessionError(PP_Instance instance,
+                                  uint32_t session_id,
+                                  int32_t media_error,
+                                  uint32_t system_code) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::DeliverBlock(PP_Instance instance,
+                                  PP_Resource decrypted_block,
+                                  const PP_DecryptedBlockInfo* block_info) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::DecoderInitializeDone(PP_Instance instance,
+                                           PP_DecryptorStreamType decoder_type,
+                                           uint32_t request_id,
+                                           PP_Bool success) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::DecoderDeinitializeDone(
+    PP_Instance instance,
+    PP_DecryptorStreamType decoder_type,
+    uint32_t request_id) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::DecoderResetDone(PP_Instance instance,
+                                      PP_DecryptorStreamType decoder_type,
+                                      uint32_t request_id) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::DeliverFrame(PP_Instance instance,
+                                  PP_Resource decrypted_frame,
+                                  const PP_DecryptedFrameInfo* frame_info) {
+  NOTIMPLEMENTED();
+}
+
+void PluginInstance::DeliverSamples(PP_Instance instance,
+                                    PP_Resource audio_frames,
+                                    const PP_DecryptedSampleInfo* sample_info) {
+  NOTIMPLEMENTED();
+}
+
+PP_Var PluginInstance::ResolveRelativeToDocument(
+    PP_Instance instance,
+    PP_Var relative,
+    PP_URLComponents_Dev* components) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+PP_Bool PluginInstance::DocumentCanRequest(PP_Instance instance, PP_Var url) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Bool PluginInstance::DocumentCanAccessDocument(PP_Instance instance,
+                                                  PP_Instance target) {
+  NOTIMPLEMENTED();
+  return PP_FALSE;
+}
+
+PP_Var PluginInstance::GetPluginInstanceURL(PP_Instance instance,
+                                            PP_URLComponents_Dev* components) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+PP_Var PluginInstance::GetPluginReferrerURL(PP_Instance instance,
+                                            PP_URLComponents_Dev* components) {
+  NOTIMPLEMENTED();
+  return PP_MakeUndefined();
+}
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/plugin_instance.h b/mojo/examples/pepper_container_app/plugin_instance.h
new file mode 100644
index 0000000..56bd73f
--- /dev/null
+++ b/mojo/examples/pepper_container_app/plugin_instance.h
@@ -0,0 +1,170 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_PLUGIN_INSTANCE_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_PLUGIN_INSTANCE_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "mojo/examples/pepper_container_app/plugin_module.h"
+#include "mojo/examples/pepper_container_app/resource_creation_impl.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/shared_impl/scoped_pp_resource.h"
+#include "ppapi/thunk/ppb_instance_api.h"
+
+namespace mojo {
+namespace examples {
+
+class PluginInstance : public ppapi::thunk::PPB_Instance_API {
+ public:
+  explicit PluginInstance(scoped_refptr<PluginModule> plugin_module);
+  virtual ~PluginInstance();
+
+  // Notifies the plugin that a new instance has been created.
+  bool DidCreate();
+  // Notifies the plugin that the instance has been destroyed.
+  void DidDestroy();
+  // Notifies the plugin that the position or size of the instance has changed.
+  void DidChangeView(const PP_Rect& bounds);
+  // Notifies the plugin that the Graphics 3D context has been invalidated.
+  void Graphics3DContextLost();
+
+  // Returns true if |device| has been bound as the current display surface.
+  bool IsBoundGraphics(PP_Resource device) const;
+
+  PP_Instance pp_instance() const { return pp_instance_; }
+  ResourceCreationImpl* resource_creation() { return &resource_creation_; }
+  PluginModule* plugin_module() { return plugin_module_.get(); }
+
+  // ppapi::thunk::PPB_Instance_API implementation.
+  virtual PP_Bool BindGraphics(PP_Instance instance,
+                               PP_Resource device) OVERRIDE;
+  virtual PP_Bool IsFullFrame(PP_Instance instance) OVERRIDE;
+  virtual const ppapi::ViewData* GetViewData(PP_Instance instance) OVERRIDE;
+  virtual PP_Bool FlashIsFullscreen(PP_Instance instance) OVERRIDE;
+  virtual PP_Var GetWindowObject(PP_Instance instance) OVERRIDE;
+  virtual PP_Var GetOwnerElementObject(PP_Instance instance) OVERRIDE;
+  virtual PP_Var ExecuteScript(PP_Instance instance,
+                               PP_Var script,
+                               PP_Var* exception) OVERRIDE;
+  virtual uint32_t GetAudioHardwareOutputSampleRate(
+      PP_Instance instance) OVERRIDE;
+  virtual uint32_t GetAudioHardwareOutputBufferSize(
+      PP_Instance instance) OVERRIDE;
+  virtual PP_Var GetDefaultCharSet(PP_Instance instance) OVERRIDE;
+  virtual void Log(PP_Instance instance,
+                   PP_LogLevel log_level,
+                   PP_Var value) OVERRIDE;
+  virtual void LogWithSource(PP_Instance instance,
+                             PP_LogLevel log_level,
+                             PP_Var source,
+                             PP_Var value) OVERRIDE;
+  virtual void SetPluginToHandleFindRequests(PP_Instance instance) OVERRIDE;
+  virtual void NumberOfFindResultsChanged(PP_Instance instance,
+                                          int32_t total,
+                                          PP_Bool final_result) OVERRIDE;
+  virtual void SelectedFindResultChanged(PP_Instance instance,
+                                         int32_t index) OVERRIDE;
+  virtual void SetTickmarks(PP_Instance instance,
+                            const PP_Rect* tickmarks,
+                            uint32_t count) OVERRIDE;
+  virtual PP_Bool IsFullscreen(PP_Instance instance) OVERRIDE;
+  virtual PP_Bool SetFullscreen(PP_Instance instance,
+                                PP_Bool fullscreen) OVERRIDE;
+  virtual PP_Bool GetScreenSize(PP_Instance instance, PP_Size* size) OVERRIDE;
+  virtual ppapi::Resource* GetSingletonResource(
+      PP_Instance instance, ppapi::SingletonResourceID id) OVERRIDE;
+  virtual int32_t RequestInputEvents(PP_Instance instance,
+                                     uint32_t event_classes) OVERRIDE;
+  virtual int32_t RequestFilteringInputEvents(PP_Instance instance,
+                                              uint32_t event_classes) OVERRIDE;
+  virtual void ClearInputEventRequest(PP_Instance instance,
+                                      uint32_t event_classes) OVERRIDE;
+  virtual void PostMessage(PP_Instance instance, PP_Var message) OVERRIDE;
+  virtual PP_Bool SetCursor(PP_Instance instance,
+                            PP_MouseCursor_Type type,
+                            PP_Resource image,
+                            const PP_Point* hot_spot) OVERRIDE;
+  virtual int32_t LockMouse(
+      PP_Instance instance,
+      scoped_refptr<ppapi::TrackedCallback> callback) OVERRIDE;
+  virtual void UnlockMouse(PP_Instance instance) OVERRIDE;
+  virtual void SetTextInputType(PP_Instance instance,
+                                PP_TextInput_Type type) OVERRIDE;
+  virtual void UpdateCaretPosition(PP_Instance instance,
+                                   const PP_Rect& caret,
+                                   const PP_Rect& bounding_box) OVERRIDE;
+  virtual void CancelCompositionText(PP_Instance instance) OVERRIDE;
+  virtual void SelectionChanged(PP_Instance instance) OVERRIDE;
+  virtual void UpdateSurroundingText(PP_Instance instance,
+                                     const char* text,
+                                     uint32_t caret,
+                                     uint32_t anchor) OVERRIDE;
+  virtual void ZoomChanged(PP_Instance instance, double factor) OVERRIDE;
+  virtual void ZoomLimitsChanged(PP_Instance instance,
+                                 double minimum_factor,
+                                 double maximum_factor) OVERRIDE;
+  virtual PP_Var GetDocumentURL(PP_Instance instance,
+                                PP_URLComponents_Dev* components) OVERRIDE;
+  virtual void SessionCreated(PP_Instance instance,
+                              uint32_t session_id,
+                              PP_Var web_session_id) OVERRIDE;
+  virtual void SessionMessage(PP_Instance instance,
+                              uint32_t session_id,
+                              PP_Var message,
+                              PP_Var destination_url) OVERRIDE;
+  virtual void SessionReady(PP_Instance instance, uint32_t session_id) OVERRIDE;
+  virtual void SessionClosed(PP_Instance instance,
+                             uint32_t session_id) OVERRIDE;
+  virtual void SessionError(PP_Instance instance,
+                            uint32_t session_id,
+                            int32_t media_error,
+                            uint32_t system_code) OVERRIDE;
+  virtual void DeliverBlock(PP_Instance instance,
+                            PP_Resource decrypted_block,
+                            const PP_DecryptedBlockInfo* block_info) OVERRIDE;
+  virtual void DecoderInitializeDone(PP_Instance instance,
+                                     PP_DecryptorStreamType decoder_type,
+                                     uint32_t request_id,
+                                     PP_Bool success) OVERRIDE;
+  virtual void DecoderDeinitializeDone(PP_Instance instance,
+                                       PP_DecryptorStreamType decoder_type,
+                                       uint32_t request_id) OVERRIDE;
+  virtual void DecoderResetDone(PP_Instance instance,
+                                PP_DecryptorStreamType decoder_type,
+                                uint32_t request_id) OVERRIDE;
+  virtual void DeliverFrame(PP_Instance instance,
+                            PP_Resource decrypted_frame,
+                            const PP_DecryptedFrameInfo* frame_info) OVERRIDE;
+  virtual void DeliverSamples(
+      PP_Instance instance,
+      PP_Resource audio_frames,
+      const PP_DecryptedSampleInfo* sample_info) OVERRIDE;
+  virtual PP_Var ResolveRelativeToDocument(
+      PP_Instance instance,
+      PP_Var relative,
+      PP_URLComponents_Dev* components) OVERRIDE;
+  virtual PP_Bool DocumentCanRequest(PP_Instance instance, PP_Var url) OVERRIDE;
+  virtual PP_Bool DocumentCanAccessDocument(PP_Instance instance,
+                                            PP_Instance target) OVERRIDE;
+  virtual PP_Var GetPluginInstanceURL(
+      PP_Instance instance,
+      PP_URLComponents_Dev* components) OVERRIDE;
+  virtual PP_Var GetPluginReferrerURL(
+      PP_Instance instance,
+      PP_URLComponents_Dev* components) OVERRIDE;
+
+ private:
+  PP_Instance pp_instance_;
+  ResourceCreationImpl resource_creation_;
+  scoped_refptr<PluginModule> plugin_module_;
+  ppapi::ScopedPPResource bound_graphics_;
+
+  DISALLOW_COPY_AND_ASSIGN(PluginInstance);
+};
+
+}  // namespace examples
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_PLUGIN_INSTANCE_H_
diff --git a/mojo/examples/pepper_container_app/plugin_module.cc b/mojo/examples/pepper_container_app/plugin_module.cc
new file mode 100644
index 0000000..d09d42d
--- /dev/null
+++ b/mojo/examples/pepper_container_app/plugin_module.cc
@@ -0,0 +1,110 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/examples/pepper_container_app/plugin_module.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "mojo/examples/pepper_container_app/interface_list.h"
+#include "mojo/examples/pepper_container_app/plugin_instance.h"
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/shared_impl/callback_tracker.h"
+
+namespace mojo {
+namespace examples {
+
+namespace {
+
+const void* GetInterface(const char* name) {
+  const void* interface =
+      InterfaceList::GetInstance()->GetBrowserInterface(name);
+
+  if (!interface)
+    LOG(WARNING) << "Interface requested " << name;
+
+  return interface;
+}
+
+}  // namespace
+
+PluginModule::EntryPoints::EntryPoints() : get_interface(NULL),
+                                           initialize_module(NULL),
+                                           shutdown_module(NULL) {}
+
+PluginModule::PluginModule() : callback_tracker_(new ppapi::CallbackTracker) {
+  Initialize();
+}
+
+PluginModule::~PluginModule() {
+  callback_tracker_->AbortAll();
+
+  if (entry_points_.shutdown_module)
+    entry_points_.shutdown_module();
+}
+
+scoped_ptr<PluginInstance> PluginModule::CreateInstance() {
+  return make_scoped_ptr(new PluginInstance(this));
+}
+
+const void* PluginModule::GetPluginInterface(const char* name) const {
+  if (entry_points_.get_interface)
+    return entry_points_.get_interface(name);
+  return NULL;
+}
+
+void PluginModule::Initialize() {
+  // Platform-specific filename.
+  // TODO(yzshen): Don't hard-code it.
+#if defined(OS_WIN)
+  static const wchar_t plugin_name[] = L"ppapi_example_gles2_spinning_cube.dll";
+#elif defined(OS_MACOSX)
+  static const char plugin_name[] = "ppapi_example_gles2_spinning_cube.plugin";
+#elif defined(OS_POSIX)
+  static const char plugin_name[] = "libppapi_example_gles2_spinning_cube.so";
+#endif
+
+  base::FilePath plugin_path(plugin_name);
+
+  base::NativeLibraryLoadError error;
+  plugin_module_.Reset(base::LoadNativeLibrary(plugin_path, &error));
+
+  if (!plugin_module_.is_valid()) {
+    LOG(WARNING) << "Cannot load " << plugin_path.AsUTF8Unsafe()
+                 << ". Error: " << error.ToString();
+    return;
+  }
+
+  entry_points_.get_interface =
+      reinterpret_cast<PP_GetInterface_Func>(
+          plugin_module_.GetFunctionPointer("PPP_GetInterface"));
+  if (!entry_points_.get_interface) {
+    LOG(WARNING) << "No PPP_GetInterface in plugin library";
+    return;
+  }
+
+  entry_points_.initialize_module =
+      reinterpret_cast<PP_InitializeModule_Func>(
+          plugin_module_.GetFunctionPointer("PPP_InitializeModule"));
+  if (!entry_points_.initialize_module) {
+    LOG(WARNING) << "No PPP_InitializeModule in plugin library";
+    return;
+  }
+
+  // It's okay for PPP_ShutdownModule to not be defined and |shutdown_module| to
+  // be NULL.
+  entry_points_.shutdown_module =
+      reinterpret_cast<PP_ShutdownModule_Func>(
+          plugin_module_.GetFunctionPointer("PPP_ShutdownModule"));
+
+  int32_t result = entry_points_.initialize_module(pp_module(),
+                                                   &GetInterface);
+  if (result != PP_OK)
+    LOG(WARNING) << "Initializing module failed with error " << result;
+}
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/plugin_module.h b/mojo/examples/pepper_container_app/plugin_module.h
new file mode 100644
index 0000000..05aad3b
--- /dev/null
+++ b/mojo/examples/pepper_container_app/plugin_module.h
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_PLUGIN_MODULE_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_PLUGIN_MODULE_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/native_library.h"
+#include "base/scoped_native_library.h"
+#include "ppapi/c/pp_module.h"
+#include "ppapi/c/ppp.h"
+
+namespace ppapi {
+class CallbackTracker;
+}
+
+namespace mojo {
+namespace examples {
+
+class PluginInstance;
+
+class PluginModule : public base::RefCounted<PluginModule> {
+ public:
+  PluginModule();
+
+  scoped_ptr<PluginInstance> CreateInstance();
+
+  const void* GetPluginInterface(const char* name) const;
+
+  PP_Module pp_module() const { return 1; }
+  ppapi::CallbackTracker* callback_tracker() { return callback_tracker_.get(); }
+
+ private:
+  friend class base::RefCounted<PluginModule>;
+
+  struct EntryPoints {
+    EntryPoints();
+
+    PP_GetInterface_Func get_interface;
+    PP_InitializeModule_Func initialize_module;
+    PP_ShutdownModule_Func shutdown_module;  // Optional, may be NULL.
+  };
+
+  ~PluginModule();
+
+  void Initialize();
+
+  base::ScopedNativeLibrary plugin_module_;
+  EntryPoints entry_points_;
+  scoped_refptr<ppapi::CallbackTracker> callback_tracker_;
+
+  DISALLOW_COPY_AND_ASSIGN(PluginModule);
+};
+
+}  // namespace examples
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_PLUGIN_MODULE_H_
diff --git a/mojo/examples/pepper_container_app/ppb_core_thunk.cc b/mojo/examples/pepper_container_app/ppb_core_thunk.cc
new file mode 100644
index 0000000..a76a976
--- /dev/null
+++ b/mojo/examples/pepper_container_app/ppb_core_thunk.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "mojo/examples/pepper_container_app/thunk.h"
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/shared_impl/ppapi_globals.h"
+#include "ppapi/shared_impl/proxy_lock.h"
+#include "ppapi/shared_impl/resource_tracker.h"
+
+namespace mojo {
+namespace examples {
+
+namespace {
+
+void AddRefResource(PP_Resource resource) {
+  ppapi::ProxyAutoLock lock;
+  ppapi::PpapiGlobals::Get()->GetResourceTracker()->AddRefResource(resource);
+}
+
+void ReleaseResource(PP_Resource resource) {
+  ppapi::ProxyAutoLock lock;
+  ppapi::PpapiGlobals::Get()->GetResourceTracker()->ReleaseResource(resource);
+}
+
+PP_Time GetTime() {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_TimeTicks GetTimeTicks() {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+void CallOnMainThread(int32_t delay_in_milliseconds,
+                      PP_CompletionCallback callback,
+                      int32_t result) {
+  NOTIMPLEMENTED();
+}
+
+PP_Bool IsMainThread() {
+  NOTIMPLEMENTED();
+  return PP_TRUE;
+}
+
+}  // namespace
+
+const PPB_Core_1_0 g_ppb_core_thunk_1_0 = {
+  &AddRefResource,
+  &ReleaseResource,
+  &GetTime,
+  &GetTimeTicks,
+  &CallOnMainThread,
+  &IsMainThread
+};
+
+const PPB_Core_1_0* GetPPB_Core_1_0_Thunk() {
+  return &g_ppb_core_thunk_1_0;
+}
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/ppb_opengles2_thunk.cc b/mojo/examples/pepper_container_app/ppb_opengles2_thunk.cc
new file mode 100644
index 0000000..56fc891
--- /dev/null
+++ b/mojo/examples/pepper_container_app/ppb_opengles2_thunk.cc
@@ -0,0 +1,1454 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "mojo/examples/pepper_container_app/graphics_3d_resource.h"
+#include "mojo/examples/pepper_container_app/thunk.h"
+#include "mojo/public/gles2/gles2.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppb_graphics_3d_api.h"
+
+namespace mojo {
+namespace examples {
+
+namespace {
+
+typedef ppapi::thunk::EnterResource<ppapi::thunk::PPB_Graphics3D_API> Enter3D;
+
+bool IsBoundGraphics(Enter3D* enter) {
+  return enter->succeeded() &&
+         static_cast<Graphics3DResource*>(enter->object())->IsBoundGraphics();
+}
+
+void ActiveTexture(PP_Resource context_id, GLenum texture) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glActiveTexture(texture);
+  }
+}
+
+void AttachShader(PP_Resource context_id, GLuint program, GLuint shader) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glAttachShader(program, shader);
+  }
+}
+
+void BindAttribLocation(PP_Resource context_id,
+                        GLuint program,
+                        GLuint index,
+                        const char* name) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBindAttribLocation(program, index, name);
+  }
+}
+
+void BindBuffer(PP_Resource context_id, GLenum target, GLuint buffer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBindBuffer(target, buffer);
+  }
+}
+
+void BindFramebuffer(PP_Resource context_id,
+                     GLenum target,
+                     GLuint framebuffer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBindFramebuffer(target, framebuffer);
+  }
+}
+
+void BindRenderbuffer(PP_Resource context_id,
+                      GLenum target,
+                      GLuint renderbuffer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBindRenderbuffer(target, renderbuffer);
+  }
+}
+
+void BindTexture(PP_Resource context_id, GLenum target, GLuint texture) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBindTexture(target, texture);
+  }
+}
+
+void BlendColor(PP_Resource context_id,
+                GLclampf red,
+                GLclampf green,
+                GLclampf blue,
+                GLclampf alpha) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBlendColor(red, green, blue, alpha);
+  }
+}
+
+void BlendEquation(PP_Resource context_id, GLenum mode) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBlendEquation(mode);
+  }
+}
+
+void BlendEquationSeparate(PP_Resource context_id,
+                           GLenum modeRGB,
+                           GLenum modeAlpha) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBlendEquationSeparate(modeRGB, modeAlpha);
+  }
+}
+
+void BlendFunc(PP_Resource context_id, GLenum sfactor, GLenum dfactor) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBlendFunc(sfactor, dfactor);
+  }
+}
+
+void BlendFuncSeparate(PP_Resource context_id,
+                       GLenum srcRGB,
+                       GLenum dstRGB,
+                       GLenum srcAlpha,
+                       GLenum dstAlpha) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
+  }
+}
+
+void BufferData(PP_Resource context_id,
+                GLenum target,
+                GLsizeiptr size,
+                const void* data,
+                GLenum usage) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBufferData(target, size, data, usage);
+  }
+}
+
+void BufferSubData(PP_Resource context_id,
+                   GLenum target,
+                   GLintptr offset,
+                   GLsizeiptr size,
+                   const void* data) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glBufferSubData(target, offset, size, data);
+  }
+}
+
+GLenum CheckFramebufferStatus(PP_Resource context_id, GLenum target) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glCheckFramebufferStatus(target);
+  } else {
+    return 0;
+  }
+}
+
+void Clear(PP_Resource context_id, GLbitfield mask) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glClear(mask);
+  }
+}
+
+void ClearColor(PP_Resource context_id,
+                GLclampf red,
+                GLclampf green,
+                GLclampf blue,
+                GLclampf alpha) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glClearColor(red, green, blue, alpha);
+  }
+}
+
+void ClearDepthf(PP_Resource context_id, GLclampf depth) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glClearDepthf(depth);
+  }
+}
+
+void ClearStencil(PP_Resource context_id, GLint s) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glClearStencil(s);
+  }
+}
+
+void ColorMask(PP_Resource context_id,
+               GLboolean red,
+               GLboolean green,
+               GLboolean blue,
+               GLboolean alpha) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glColorMask(red, green, blue, alpha);
+  }
+}
+
+void CompileShader(PP_Resource context_id, GLuint shader) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glCompileShader(shader);
+  }
+}
+
+void CompressedTexImage2D(PP_Resource context_id,
+                          GLenum target,
+                          GLint level,
+                          GLenum internalformat,
+                          GLsizei width,
+                          GLsizei height,
+                          GLint border,
+                          GLsizei imageSize,
+                          const void* data) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glCompressedTexImage2D(
+        target, level, internalformat, width, height, border, imageSize, data);
+  }
+}
+
+void CompressedTexSubImage2D(PP_Resource context_id,
+                             GLenum target,
+                             GLint level,
+                             GLint xoffset,
+                             GLint yoffset,
+                             GLsizei width,
+                             GLsizei height,
+                             GLenum format,
+                             GLsizei imageSize,
+                             const void* data) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glCompressedTexSubImage2D(target,
+                              level,
+                              xoffset,
+                              yoffset,
+                              width,
+                              height,
+                              format,
+                              imageSize,
+                              data);
+  }
+}
+
+void CopyTexImage2D(PP_Resource context_id,
+                    GLenum target,
+                    GLint level,
+                    GLenum internalformat,
+                    GLint x,
+                    GLint y,
+                    GLsizei width,
+                    GLsizei height,
+                    GLint border) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glCopyTexImage2D(
+        target, level, internalformat, x, y, width, height, border);
+  }
+}
+
+void CopyTexSubImage2D(PP_Resource context_id,
+                       GLenum target,
+                       GLint level,
+                       GLint xoffset,
+                       GLint yoffset,
+                       GLint x,
+                       GLint y,
+                       GLsizei width,
+                       GLsizei height) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+  }
+}
+
+GLuint CreateProgram(PP_Resource context_id) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glCreateProgram();
+  } else {
+    return 0;
+  }
+}
+
+GLuint CreateShader(PP_Resource context_id, GLenum type) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glCreateShader(type);
+  } else {
+    return 0;
+  }
+}
+
+void CullFace(PP_Resource context_id, GLenum mode) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glCullFace(mode);
+  }
+}
+
+void DeleteBuffers(PP_Resource context_id, GLsizei n, const GLuint* buffers) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDeleteBuffers(n, buffers);
+  }
+}
+
+void DeleteFramebuffers(PP_Resource context_id,
+                        GLsizei n,
+                        const GLuint* framebuffers) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDeleteFramebuffers(n, framebuffers);
+  }
+}
+
+void DeleteProgram(PP_Resource context_id, GLuint program) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDeleteProgram(program);
+  }
+}
+
+void DeleteRenderbuffers(PP_Resource context_id,
+                         GLsizei n,
+                         const GLuint* renderbuffers) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDeleteRenderbuffers(n, renderbuffers);
+  }
+}
+
+void DeleteShader(PP_Resource context_id, GLuint shader) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDeleteShader(shader);
+  }
+}
+
+void DeleteTextures(PP_Resource context_id, GLsizei n, const GLuint* textures) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDeleteTextures(n, textures);
+  }
+}
+
+void DepthFunc(PP_Resource context_id, GLenum func) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDepthFunc(func);
+  }
+}
+
+void DepthMask(PP_Resource context_id, GLboolean flag) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDepthMask(flag);
+  }
+}
+
+void DepthRangef(PP_Resource context_id, GLclampf zNear, GLclampf zFar) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDepthRangef(zNear, zFar);
+  }
+}
+
+void DetachShader(PP_Resource context_id, GLuint program, GLuint shader) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDetachShader(program, shader);
+  }
+}
+
+void Disable(PP_Resource context_id, GLenum cap) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDisable(cap);
+  }
+}
+
+void DisableVertexAttribArray(PP_Resource context_id, GLuint index) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDisableVertexAttribArray(index);
+  }
+}
+
+void DrawArrays(PP_Resource context_id,
+                GLenum mode,
+                GLint first,
+                GLsizei count) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDrawArrays(mode, first, count);
+  }
+}
+
+void DrawElements(PP_Resource context_id,
+                  GLenum mode,
+                  GLsizei count,
+                  GLenum type,
+                  const void* indices) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glDrawElements(mode, count, type, indices);
+  }
+}
+
+void Enable(PP_Resource context_id, GLenum cap) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glEnable(cap);
+  }
+}
+
+void EnableVertexAttribArray(PP_Resource context_id, GLuint index) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glEnableVertexAttribArray(index);
+  }
+}
+
+void Finish(PP_Resource context_id) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glFinish();
+  }
+}
+
+void Flush(PP_Resource context_id) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glFlush();
+  }
+}
+
+void FramebufferRenderbuffer(PP_Resource context_id,
+                             GLenum target,
+                             GLenum attachment,
+                             GLenum renderbuffertarget,
+                             GLuint renderbuffer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glFramebufferRenderbuffer(
+        target, attachment, renderbuffertarget, renderbuffer);
+  }
+}
+
+void FramebufferTexture2D(PP_Resource context_id,
+                          GLenum target,
+                          GLenum attachment,
+                          GLenum textarget,
+                          GLuint texture,
+                          GLint level) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glFramebufferTexture2D(target, attachment, textarget, texture, level);
+  }
+}
+
+void FrontFace(PP_Resource context_id, GLenum mode) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glFrontFace(mode);
+  }
+}
+
+void GenBuffers(PP_Resource context_id, GLsizei n, GLuint* buffers) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGenBuffers(n, buffers);
+  }
+}
+
+void GenerateMipmap(PP_Resource context_id, GLenum target) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGenerateMipmap(target);
+  }
+}
+
+void GenFramebuffers(PP_Resource context_id, GLsizei n, GLuint* framebuffers) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGenFramebuffers(n, framebuffers);
+  }
+}
+
+void GenRenderbuffers(PP_Resource context_id,
+                      GLsizei n,
+                      GLuint* renderbuffers) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGenRenderbuffers(n, renderbuffers);
+  }
+}
+
+void GenTextures(PP_Resource context_id, GLsizei n, GLuint* textures) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGenTextures(n, textures);
+  }
+}
+
+void GetActiveAttrib(PP_Resource context_id,
+                     GLuint program,
+                     GLuint index,
+                     GLsizei bufsize,
+                     GLsizei* length,
+                     GLint* size,
+                     GLenum* type,
+                     char* name) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetActiveAttrib(program, index, bufsize, length, size, type, name);
+  }
+}
+
+void GetActiveUniform(PP_Resource context_id,
+                      GLuint program,
+                      GLuint index,
+                      GLsizei bufsize,
+                      GLsizei* length,
+                      GLint* size,
+                      GLenum* type,
+                      char* name) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetActiveUniform(program, index, bufsize, length, size, type, name);
+  }
+}
+
+void GetAttachedShaders(PP_Resource context_id,
+                        GLuint program,
+                        GLsizei maxcount,
+                        GLsizei* count,
+                        GLuint* shaders) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetAttachedShaders(program, maxcount, count, shaders);
+  }
+}
+
+GLint GetAttribLocation(PP_Resource context_id,
+                        GLuint program,
+                        const char* name) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glGetAttribLocation(program, name);
+  } else {
+    return -1;
+  }
+}
+
+void GetBooleanv(PP_Resource context_id, GLenum pname, GLboolean* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetBooleanv(pname, params);
+  }
+}
+
+void GetBufferParameteriv(PP_Resource context_id,
+                          GLenum target,
+                          GLenum pname,
+                          GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetBufferParameteriv(target, pname, params);
+  }
+}
+
+GLenum GetError(PP_Resource context_id) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glGetError();
+  } else {
+    return 0;
+  }
+}
+
+void GetFloatv(PP_Resource context_id, GLenum pname, GLfloat* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetFloatv(pname, params);
+  }
+}
+
+void GetFramebufferAttachmentParameteriv(PP_Resource context_id,
+                                         GLenum target,
+                                         GLenum attachment,
+                                         GLenum pname,
+                                         GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+  }
+}
+
+void GetIntegerv(PP_Resource context_id, GLenum pname, GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetIntegerv(pname, params);
+  }
+}
+
+void GetProgramiv(PP_Resource context_id,
+                  GLuint program,
+                  GLenum pname,
+                  GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetProgramiv(program, pname, params);
+  }
+}
+
+void GetProgramInfoLog(PP_Resource context_id,
+                       GLuint program,
+                       GLsizei bufsize,
+                       GLsizei* length,
+                       char* infolog) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetProgramInfoLog(program, bufsize, length, infolog);
+  }
+}
+
+void GetRenderbufferParameteriv(PP_Resource context_id,
+                                GLenum target,
+                                GLenum pname,
+                                GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetRenderbufferParameteriv(target, pname, params);
+  }
+}
+
+void GetShaderiv(PP_Resource context_id,
+                 GLuint shader,
+                 GLenum pname,
+                 GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetShaderiv(shader, pname, params);
+  }
+}
+
+void GetShaderInfoLog(PP_Resource context_id,
+                      GLuint shader,
+                      GLsizei bufsize,
+                      GLsizei* length,
+                      char* infolog) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetShaderInfoLog(shader, bufsize, length, infolog);
+  }
+}
+
+void GetShaderPrecisionFormat(PP_Resource context_id,
+                              GLenum shadertype,
+                              GLenum precisiontype,
+                              GLint* range,
+                              GLint* precision) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
+  }
+}
+
+void GetShaderSource(PP_Resource context_id,
+                     GLuint shader,
+                     GLsizei bufsize,
+                     GLsizei* length,
+                     char* source) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetShaderSource(shader, bufsize, length, source);
+  }
+}
+
+const GLubyte* GetString(PP_Resource context_id, GLenum name) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glGetString(name);
+  } else {
+    return NULL;
+  }
+}
+
+void GetTexParameterfv(PP_Resource context_id,
+                       GLenum target,
+                       GLenum pname,
+                       GLfloat* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetTexParameterfv(target, pname, params);
+  }
+}
+
+void GetTexParameteriv(PP_Resource context_id,
+                       GLenum target,
+                       GLenum pname,
+                       GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetTexParameteriv(target, pname, params);
+  }
+}
+
+void GetUniformfv(PP_Resource context_id,
+                  GLuint program,
+                  GLint location,
+                  GLfloat* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetUniformfv(program, location, params);
+  }
+}
+
+void GetUniformiv(PP_Resource context_id,
+                  GLuint program,
+                  GLint location,
+                  GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetUniformiv(program, location, params);
+  }
+}
+
+GLint GetUniformLocation(PP_Resource context_id,
+                         GLuint program,
+                         const char* name) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glGetUniformLocation(program, name);
+  } else {
+    return -1;
+  }
+}
+
+void GetVertexAttribfv(PP_Resource context_id,
+                       GLuint index,
+                       GLenum pname,
+                       GLfloat* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetVertexAttribfv(index, pname, params);
+  }
+}
+
+void GetVertexAttribiv(PP_Resource context_id,
+                       GLuint index,
+                       GLenum pname,
+                       GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetVertexAttribiv(index, pname, params);
+  }
+}
+
+void GetVertexAttribPointerv(PP_Resource context_id,
+                             GLuint index,
+                             GLenum pname,
+                             void** pointer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glGetVertexAttribPointerv(index, pname, pointer);
+  }
+}
+
+void Hint(PP_Resource context_id, GLenum target, GLenum mode) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glHint(target, mode);
+  }
+}
+
+GLboolean IsBuffer(PP_Resource context_id, GLuint buffer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glIsBuffer(buffer);
+  } else {
+    return GL_FALSE;
+  }
+}
+
+GLboolean IsEnabled(PP_Resource context_id, GLenum cap) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glIsEnabled(cap);
+  } else {
+    return GL_FALSE;
+  }
+}
+
+GLboolean IsFramebuffer(PP_Resource context_id, GLuint framebuffer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glIsFramebuffer(framebuffer);
+  } else {
+    return GL_FALSE;
+  }
+}
+
+GLboolean IsProgram(PP_Resource context_id, GLuint program) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glIsProgram(program);
+  } else {
+    return GL_FALSE;
+  }
+}
+
+GLboolean IsRenderbuffer(PP_Resource context_id, GLuint renderbuffer) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glIsRenderbuffer(renderbuffer);
+  } else {
+    return GL_FALSE;
+  }
+}
+
+GLboolean IsShader(PP_Resource context_id, GLuint shader) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glIsShader(shader);
+  } else {
+    return GL_FALSE;
+  }
+}
+
+GLboolean IsTexture(PP_Resource context_id, GLuint texture) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    return glIsTexture(texture);
+  } else {
+    return GL_FALSE;
+  }
+}
+
+void LineWidth(PP_Resource context_id, GLfloat width) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glLineWidth(width);
+  }
+}
+
+void LinkProgram(PP_Resource context_id, GLuint program) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glLinkProgram(program);
+  }
+}
+
+void PixelStorei(PP_Resource context_id, GLenum pname, GLint param) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glPixelStorei(pname, param);
+  }
+}
+
+void PolygonOffset(PP_Resource context_id, GLfloat factor, GLfloat units) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glPolygonOffset(factor, units);
+  }
+}
+
+void ReadPixels(PP_Resource context_id,
+                GLint x,
+                GLint y,
+                GLsizei width,
+                GLsizei height,
+                GLenum format,
+                GLenum type,
+                void* pixels) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glReadPixels(x, y, width, height, format, type, pixels);
+  }
+}
+
+void ReleaseShaderCompiler(PP_Resource context_id) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glReleaseShaderCompiler();
+  }
+}
+
+void RenderbufferStorage(PP_Resource context_id,
+                         GLenum target,
+                         GLenum internalformat,
+                         GLsizei width,
+                         GLsizei height) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glRenderbufferStorage(target, internalformat, width, height);
+  }
+}
+
+void SampleCoverage(PP_Resource context_id, GLclampf value, GLboolean invert) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glSampleCoverage(value, invert);
+  }
+}
+
+void Scissor(PP_Resource context_id,
+             GLint x,
+             GLint y,
+             GLsizei width,
+             GLsizei height) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glScissor(x, y, width, height);
+  }
+}
+
+void ShaderBinary(PP_Resource context_id,
+                  GLsizei n,
+                  const GLuint* shaders,
+                  GLenum binaryformat,
+                  const void* binary,
+                  GLsizei length) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glShaderBinary(n, shaders, binaryformat, binary, length);
+  }
+}
+
+void ShaderSource(PP_Resource context_id,
+                  GLuint shader,
+                  GLsizei count,
+                  const char** str,
+                  const GLint* length) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glShaderSource(shader, count, str, length);
+  }
+}
+
+void StencilFunc(PP_Resource context_id, GLenum func, GLint ref, GLuint mask) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glStencilFunc(func, ref, mask);
+  }
+}
+
+void StencilFuncSeparate(PP_Resource context_id,
+                         GLenum face,
+                         GLenum func,
+                         GLint ref,
+                         GLuint mask) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glStencilFuncSeparate(face, func, ref, mask);
+  }
+}
+
+void StencilMask(PP_Resource context_id, GLuint mask) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glStencilMask(mask);
+  }
+}
+
+void StencilMaskSeparate(PP_Resource context_id, GLenum face, GLuint mask) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glStencilMaskSeparate(face, mask);
+  }
+}
+
+void StencilOp(PP_Resource context_id,
+               GLenum fail,
+               GLenum zfail,
+               GLenum zpass) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glStencilOp(fail, zfail, zpass);
+  }
+}
+
+void StencilOpSeparate(PP_Resource context_id,
+                       GLenum face,
+                       GLenum fail,
+                       GLenum zfail,
+                       GLenum zpass) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glStencilOpSeparate(face, fail, zfail, zpass);
+  }
+}
+
+void TexImage2D(PP_Resource context_id,
+                GLenum target,
+                GLint level,
+                GLint internalformat,
+                GLsizei width,
+                GLsizei height,
+                GLint border,
+                GLenum format,
+                GLenum type,
+                const void* pixels) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glTexImage2D(target,
+                 level,
+                 internalformat,
+                 width,
+                 height,
+                 border,
+                 format,
+                 type,
+                 pixels);
+  }
+}
+
+void TexParameterf(PP_Resource context_id,
+                   GLenum target,
+                   GLenum pname,
+                   GLfloat param) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glTexParameterf(target, pname, param);
+  }
+}
+
+void TexParameterfv(PP_Resource context_id,
+                    GLenum target,
+                    GLenum pname,
+                    const GLfloat* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glTexParameterfv(target, pname, params);
+  }
+}
+
+void TexParameteri(PP_Resource context_id,
+                   GLenum target,
+                   GLenum pname,
+                   GLint param) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glTexParameteri(target, pname, param);
+  }
+}
+
+void TexParameteriv(PP_Resource context_id,
+                    GLenum target,
+                    GLenum pname,
+                    const GLint* params) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glTexParameteriv(target, pname, params);
+  }
+}
+
+void TexSubImage2D(PP_Resource context_id,
+                   GLenum target,
+                   GLint level,
+                   GLint xoffset,
+                   GLint yoffset,
+                   GLsizei width,
+                   GLsizei height,
+                   GLenum format,
+                   GLenum type,
+                   const void* pixels) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glTexSubImage2D(
+        target, level, xoffset, yoffset, width, height, format, type, pixels);
+  }
+}
+
+void Uniform1f(PP_Resource context_id, GLint location, GLfloat x) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform1f(location, x);
+  }
+}
+
+void Uniform1fv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLfloat* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform1fv(location, count, v);
+  }
+}
+
+void Uniform1i(PP_Resource context_id, GLint location, GLint x) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform1i(location, x);
+  }
+}
+
+void Uniform1iv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLint* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform1iv(location, count, v);
+  }
+}
+
+void Uniform2f(PP_Resource context_id, GLint location, GLfloat x, GLfloat y) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform2f(location, x, y);
+  }
+}
+
+void Uniform2fv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLfloat* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform2fv(location, count, v);
+  }
+}
+
+void Uniform2i(PP_Resource context_id, GLint location, GLint x, GLint y) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform2i(location, x, y);
+  }
+}
+
+void Uniform2iv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLint* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform2iv(location, count, v);
+  }
+}
+
+void Uniform3f(PP_Resource context_id,
+               GLint location,
+               GLfloat x,
+               GLfloat y,
+               GLfloat z) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform3f(location, x, y, z);
+  }
+}
+
+void Uniform3fv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLfloat* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform3fv(location, count, v);
+  }
+}
+
+void Uniform3i(PP_Resource context_id,
+               GLint location,
+               GLint x,
+               GLint y,
+               GLint z) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform3i(location, x, y, z);
+  }
+}
+
+void Uniform3iv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLint* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform3iv(location, count, v);
+  }
+}
+
+void Uniform4f(PP_Resource context_id,
+               GLint location,
+               GLfloat x,
+               GLfloat y,
+               GLfloat z,
+               GLfloat w) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform4f(location, x, y, z, w);
+  }
+}
+
+void Uniform4fv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLfloat* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform4fv(location, count, v);
+  }
+}
+
+void Uniform4i(PP_Resource context_id,
+               GLint location,
+               GLint x,
+               GLint y,
+               GLint z,
+               GLint w) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform4i(location, x, y, z, w);
+  }
+}
+
+void Uniform4iv(PP_Resource context_id,
+                GLint location,
+                GLsizei count,
+                const GLint* v) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniform4iv(location, count, v);
+  }
+}
+
+void UniformMatrix2fv(PP_Resource context_id,
+                      GLint location,
+                      GLsizei count,
+                      GLboolean transpose,
+                      const GLfloat* value) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniformMatrix2fv(location, count, transpose, value);
+  }
+}
+
+void UniformMatrix3fv(PP_Resource context_id,
+                      GLint location,
+                      GLsizei count,
+                      GLboolean transpose,
+                      const GLfloat* value) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniformMatrix3fv(location, count, transpose, value);
+  }
+}
+
+void UniformMatrix4fv(PP_Resource context_id,
+                      GLint location,
+                      GLsizei count,
+                      GLboolean transpose,
+                      const GLfloat* value) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUniformMatrix4fv(location, count, transpose, value);
+  }
+}
+
+void UseProgram(PP_Resource context_id, GLuint program) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glUseProgram(program);
+  }
+}
+
+void ValidateProgram(PP_Resource context_id, GLuint program) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glValidateProgram(program);
+  }
+}
+
+void VertexAttrib1f(PP_Resource context_id, GLuint indx, GLfloat x) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib1f(indx, x);
+  }
+}
+
+void VertexAttrib1fv(PP_Resource context_id,
+                     GLuint indx,
+                     const GLfloat* values) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib1fv(indx, values);
+  }
+}
+
+void VertexAttrib2f(PP_Resource context_id, GLuint indx, GLfloat x, GLfloat y) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib2f(indx, x, y);
+  }
+}
+
+void VertexAttrib2fv(PP_Resource context_id,
+                     GLuint indx,
+                     const GLfloat* values) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib2fv(indx, values);
+  }
+}
+
+void VertexAttrib3f(PP_Resource context_id,
+                    GLuint indx,
+                    GLfloat x,
+                    GLfloat y,
+                    GLfloat z) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib3f(indx, x, y, z);
+  }
+}
+
+void VertexAttrib3fv(PP_Resource context_id,
+                     GLuint indx,
+                     const GLfloat* values) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib3fv(indx, values);
+  }
+}
+
+void VertexAttrib4f(PP_Resource context_id,
+                    GLuint indx,
+                    GLfloat x,
+                    GLfloat y,
+                    GLfloat z,
+                    GLfloat w) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib4f(indx, x, y, z, w);
+  }
+}
+
+void VertexAttrib4fv(PP_Resource context_id,
+                     GLuint indx,
+                     const GLfloat* values) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttrib4fv(indx, values);
+  }
+}
+
+void VertexAttribPointer(PP_Resource context_id,
+                         GLuint indx,
+                         GLint size,
+                         GLenum type,
+                         GLboolean normalized,
+                         GLsizei stride,
+                         const void* ptr) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+  }
+}
+
+void Viewport(PP_Resource context_id,
+              GLint x,
+              GLint y,
+              GLsizei width,
+              GLsizei height) {
+  Enter3D enter(context_id, true);
+  if (IsBoundGraphics(&enter)) {
+    glViewport(x, y, width, height);
+  }
+}
+
+}  // namespace
+
+const PPB_OpenGLES2* GetPPB_OpenGLES2_Thunk() {
+  static const struct PPB_OpenGLES2 ppb_opengles2 = {
+      &ActiveTexture,                       &AttachShader,
+      &BindAttribLocation,                  &BindBuffer,
+      &BindFramebuffer,                     &BindRenderbuffer,
+      &BindTexture,                         &BlendColor,
+      &BlendEquation,                       &BlendEquationSeparate,
+      &BlendFunc,                           &BlendFuncSeparate,
+      &BufferData,                          &BufferSubData,
+      &CheckFramebufferStatus,              &Clear,
+      &ClearColor,                          &ClearDepthf,
+      &ClearStencil,                        &ColorMask,
+      &CompileShader,                       &CompressedTexImage2D,
+      &CompressedTexSubImage2D,             &CopyTexImage2D,
+      &CopyTexSubImage2D,                   &CreateProgram,
+      &CreateShader,                        &CullFace,
+      &DeleteBuffers,                       &DeleteFramebuffers,
+      &DeleteProgram,                       &DeleteRenderbuffers,
+      &DeleteShader,                        &DeleteTextures,
+      &DepthFunc,                           &DepthMask,
+      &DepthRangef,                         &DetachShader,
+      &Disable,                             &DisableVertexAttribArray,
+      &DrawArrays,                          &DrawElements,
+      &Enable,                              &EnableVertexAttribArray,
+      &Finish,                              &Flush,
+      &FramebufferRenderbuffer,             &FramebufferTexture2D,
+      &FrontFace,                           &GenBuffers,
+      &GenerateMipmap,                      &GenFramebuffers,
+      &GenRenderbuffers,                    &GenTextures,
+      &GetActiveAttrib,                     &GetActiveUniform,
+      &GetAttachedShaders,                  &GetAttribLocation,
+      &GetBooleanv,                         &GetBufferParameteriv,
+      &GetError,                            &GetFloatv,
+      &GetFramebufferAttachmentParameteriv, &GetIntegerv,
+      &GetProgramiv,                        &GetProgramInfoLog,
+      &GetRenderbufferParameteriv,          &GetShaderiv,
+      &GetShaderInfoLog,                    &GetShaderPrecisionFormat,
+      &GetShaderSource,                     &GetString,
+      &GetTexParameterfv,                   &GetTexParameteriv,
+      &GetUniformfv,                        &GetUniformiv,
+      &GetUniformLocation,                  &GetVertexAttribfv,
+      &GetVertexAttribiv,                   &GetVertexAttribPointerv,
+      &Hint,                                &IsBuffer,
+      &IsEnabled,                           &IsFramebuffer,
+      &IsProgram,                           &IsRenderbuffer,
+      &IsShader,                            &IsTexture,
+      &LineWidth,                           &LinkProgram,
+      &PixelStorei,                         &PolygonOffset,
+      &ReadPixels,                          &ReleaseShaderCompiler,
+      &RenderbufferStorage,                 &SampleCoverage,
+      &Scissor,                             &ShaderBinary,
+      &ShaderSource,                        &StencilFunc,
+      &StencilFuncSeparate,                 &StencilMask,
+      &StencilMaskSeparate,                 &StencilOp,
+      &StencilOpSeparate,                   &TexImage2D,
+      &TexParameterf,                       &TexParameterfv,
+      &TexParameteri,                       &TexParameteriv,
+      &TexSubImage2D,                       &Uniform1f,
+      &Uniform1fv,                          &Uniform1i,
+      &Uniform1iv,                          &Uniform2f,
+      &Uniform2fv,                          &Uniform2i,
+      &Uniform2iv,                          &Uniform3f,
+      &Uniform3fv,                          &Uniform3i,
+      &Uniform3iv,                          &Uniform4f,
+      &Uniform4fv,                          &Uniform4i,
+      &Uniform4iv,                          &UniformMatrix2fv,
+      &UniformMatrix3fv,                    &UniformMatrix4fv,
+      &UseProgram,                          &ValidateProgram,
+      &VertexAttrib1f,                      &VertexAttrib1fv,
+      &VertexAttrib2f,                      &VertexAttrib2fv,
+      &VertexAttrib3f,                      &VertexAttrib3fv,
+      &VertexAttrib4f,                      &VertexAttrib4fv,
+      &VertexAttribPointer,                 &Viewport};
+  return &ppb_opengles2;
+}
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/resource_creation_impl.cc b/mojo/examples/pepper_container_app/resource_creation_impl.cc
new file mode 100644
index 0000000..cfb0679
--- /dev/null
+++ b/mojo/examples/pepper_container_app/resource_creation_impl.cc
@@ -0,0 +1,393 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/examples/pepper_container_app/resource_creation_impl.h"
+
+#include "base/logging.h"
+#include "mojo/examples/pepper_container_app/graphics_3d_resource.h"
+
+namespace mojo {
+namespace examples {
+
+ResourceCreationImpl::ResourceCreationImpl() {}
+
+ResourceCreationImpl::~ResourceCreationImpl() {}
+
+PP_Resource ResourceCreationImpl::CreateFileIO(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateFileRef(
+    PP_Instance instance,
+    const ppapi::FileRefCreateInfo& create_info) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateFileSystem(
+    PP_Instance instance,
+    PP_FileSystemType type) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateIMEInputEvent(
+    PP_Instance instance,
+    PP_InputEvent_Type type,
+    PP_TimeTicks time_stamp,
+    struct PP_Var text,
+    uint32_t segment_number,
+    const uint32_t* segment_offsets,
+    int32_t target_segment,
+    uint32_t selection_start,
+    uint32_t selection_end) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateKeyboardInputEvent_1_0(
+    PP_Instance instance,
+    PP_InputEvent_Type type,
+    PP_TimeTicks time_stamp,
+    uint32_t modifiers,
+    uint32_t key_code,
+    struct PP_Var character_text) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateKeyboardInputEvent_1_2(
+    PP_Instance instance,
+    PP_InputEvent_Type type,
+    PP_TimeTicks time_stamp,
+    uint32_t modifiers,
+    uint32_t key_code,
+    struct PP_Var character_text,
+    struct PP_Var code) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateMouseInputEvent(
+    PP_Instance instance,
+    PP_InputEvent_Type type,
+    PP_TimeTicks time_stamp,
+    uint32_t modifiers,
+    PP_InputEvent_MouseButton mouse_button,
+    const PP_Point* mouse_position,
+    int32_t click_count,
+    const PP_Point* mouse_movement) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateTouchInputEvent(
+    PP_Instance instance,
+    PP_InputEvent_Type type,
+    PP_TimeTicks time_stamp,
+    uint32_t modifiers) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateTrueTypeFont(
+    PP_Instance instance,
+    const PP_TrueTypeFontDesc_Dev* desc) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateURLLoader(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateURLRequestInfo(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateWheelInputEvent(
+    PP_Instance instance,
+    PP_TimeTicks time_stamp,
+    uint32_t modifiers,
+    const PP_FloatPoint* wheel_delta,
+    const PP_FloatPoint* wheel_ticks,
+    PP_Bool scroll_by_page) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateAudio1_0(
+    PP_Instance instance,
+    PP_Resource config_id,
+    PPB_Audio_Callback_1_0 audio_callback,
+    void* user_data) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateAudio(
+    PP_Instance instance,
+    PP_Resource config_id,
+    PPB_Audio_Callback audio_callback,
+    void* user_data) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateAudioTrusted(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateAudioConfig(
+    PP_Instance instance,
+    PP_AudioSampleRate sample_rate,
+    uint32_t sample_frame_count) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateFileChooser(
+    PP_Instance instance,
+    PP_FileChooserMode_Dev mode,
+    const PP_Var& accept_types) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateGraphics2D(PP_Instance instance,
+                                                   const PP_Size* size,
+                                                   PP_Bool is_always_opaque) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateGraphics3D(
+    PP_Instance instance,
+    PP_Resource share_context,
+    const int32_t* attrib_list) {
+  return (new Graphics3DResource(instance))->GetReference();
+}
+
+PP_Resource ResourceCreationImpl::CreateGraphics3DRaw(
+    PP_Instance instance,
+    PP_Resource share_context,
+    const int32_t* attrib_list) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateHostResolver(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateHostResolverPrivate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateImageData(
+    PP_Instance instance,
+    PP_ImageDataFormat format,
+    const PP_Size* size,
+    PP_Bool init_to_zero) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateImageDataSimple(
+    PP_Instance instance,
+    PP_ImageDataFormat format,
+    const PP_Size* size,
+    PP_Bool init_to_zero) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateNetAddressFromIPv4Address(
+    PP_Instance instance,
+    const PP_NetAddress_IPv4* ipv4_addr) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateNetAddressFromIPv6Address(
+    PP_Instance instance,
+    const PP_NetAddress_IPv6* ipv6_addr) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateNetAddressFromNetAddressPrivate(
+    PP_Instance instance,
+    const PP_NetAddress_Private& private_addr) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateNetworkMonitor(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateOutputProtectionPrivate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreatePrinting(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateTCPServerSocketPrivate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateTCPSocket1_0(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateTCPSocket(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateTCPSocketPrivate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateUDPSocket(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateUDPSocketPrivate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateVideoDestination(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateVideoSource(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateWebSocket(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateX509CertificatePrivate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+#if !defined(OS_NACL)
+PP_Resource ResourceCreationImpl::CreateAudioInput(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateBroker(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateBrowserFont(
+    PP_Instance instance,
+    const PP_BrowserFont_Trusted_Description* description) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateBuffer(PP_Instance instance,
+                                                uint32_t size) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateFlashDRM(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateFlashFontFile(
+    PP_Instance instance,
+    const PP_BrowserFont_Trusted_Description* description,
+    PP_PrivateFontCharset charset) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateFlashMenu(
+    PP_Instance instance,
+    const PP_Flash_Menu* menu_data) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateFlashMessageLoop(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreatePlatformVerificationPrivate(
+    PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateScrollbar(PP_Instance instance,
+                                                   PP_Bool vertical) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateTalk(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateVideoCapture(PP_Instance instance) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+
+PP_Resource ResourceCreationImpl::CreateVideoDecoder(
+    PP_Instance instance,
+    PP_Resource context3d_id,
+    PP_VideoDecoder_Profile profile) {
+  NOTIMPLEMENTED();
+  return 0;
+}
+#endif  // !defined(OS_NACL)
+
+}  // namespace examples
+}  // namespace mojo
diff --git a/mojo/examples/pepper_container_app/resource_creation_impl.h b/mojo/examples/pepper_container_app/resource_creation_impl.h
new file mode 100644
index 0000000..de1760e
--- /dev/null
+++ b/mojo/examples/pepper_container_app/resource_creation_impl.h
@@ -0,0 +1,174 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_RESOURCE_CREATION_IMPL_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_RESOURCE_CREATION_IMPL_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "ppapi/thunk/resource_creation_api.h"
+
+namespace mojo {
+namespace examples {
+
+class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
+ public:
+  ResourceCreationImpl();
+  virtual ~ResourceCreationImpl();
+
+  // ppapi::thunk::ResourceCreationAPI implementation.
+  virtual PP_Resource CreateFileIO(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateFileRef(
+      PP_Instance instance,
+      const ppapi::FileRefCreateInfo& create_info) OVERRIDE;
+  virtual PP_Resource CreateFileSystem(PP_Instance instance,
+                                       PP_FileSystemType type) OVERRIDE;
+  virtual PP_Resource CreateIMEInputEvent(PP_Instance instance,
+                                          PP_InputEvent_Type type,
+                                          PP_TimeTicks time_stamp,
+                                          struct PP_Var text,
+                                          uint32_t segment_number,
+                                          const uint32_t* segment_offsets,
+                                          int32_t target_segment,
+                                          uint32_t selection_start,
+                                          uint32_t selection_end) OVERRIDE;
+  virtual PP_Resource CreateKeyboardInputEvent_1_0(
+      PP_Instance instance,
+      PP_InputEvent_Type type,
+      PP_TimeTicks time_stamp,
+      uint32_t modifiers,
+      uint32_t key_code,
+      PP_Var character_text) OVERRIDE;
+  virtual PP_Resource CreateKeyboardInputEvent_1_2(
+      PP_Instance instance,
+      PP_InputEvent_Type type,
+      PP_TimeTicks time_stamp,
+      uint32_t modifiers,
+      uint32_t key_code,
+      PP_Var character_text,
+      PP_Var code) OVERRIDE;
+  virtual PP_Resource CreateMouseInputEvent(
+      PP_Instance instance,
+      PP_InputEvent_Type type,
+      PP_TimeTicks time_stamp,
+      uint32_t modifiers,
+      PP_InputEvent_MouseButton mouse_button,
+      const PP_Point* mouse_position,
+      int32_t click_count,
+      const PP_Point* mouse_movement) OVERRIDE;
+  virtual PP_Resource CreateTouchInputEvent(
+      PP_Instance instance,
+      PP_InputEvent_Type type,
+      PP_TimeTicks time_stamp,
+      uint32_t modifiers) OVERRIDE;
+  virtual PP_Resource CreateTrueTypeFont(
+      PP_Instance instance,
+      const PP_TrueTypeFontDesc_Dev* desc) OVERRIDE;
+  virtual PP_Resource CreateURLLoader(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateURLRequestInfo(
+      PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateWheelInputEvent(
+      PP_Instance instance,
+      PP_TimeTicks time_stamp,
+      uint32_t modifiers,
+      const PP_FloatPoint* wheel_delta,
+      const PP_FloatPoint* wheel_ticks,
+      PP_Bool scroll_by_page) OVERRIDE;
+  virtual PP_Resource CreateAudio1_0(PP_Instance instance,
+                                     PP_Resource config_id,
+                                     PPB_Audio_Callback_1_0 audio_callback,
+                                     void* user_data) OVERRIDE;
+  virtual PP_Resource CreateAudio(PP_Instance instance,
+                                  PP_Resource config_id,
+                                  PPB_Audio_Callback audio_callback,
+                                  void* user_data) OVERRIDE;
+  virtual PP_Resource CreateAudioTrusted(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateAudioConfig(PP_Instance instance,
+                                        PP_AudioSampleRate sample_rate,
+                                        uint32_t sample_frame_count) OVERRIDE;
+  virtual PP_Resource CreateFileChooser(PP_Instance instance,
+                                        PP_FileChooserMode_Dev mode,
+                                        const PP_Var& accept_types) OVERRIDE;
+  virtual PP_Resource CreateGraphics2D(PP_Instance pp_instance,
+                                       const PP_Size* size,
+                                       PP_Bool is_always_opaque) OVERRIDE;
+  virtual PP_Resource CreateGraphics3D(PP_Instance instance,
+                                       PP_Resource share_context,
+                                       const int32_t* attrib_list) OVERRIDE;
+  virtual PP_Resource CreateGraphics3DRaw(
+      PP_Instance instance,
+      PP_Resource share_context,
+      const int32_t* attrib_list) OVERRIDE;
+  virtual PP_Resource CreateHostResolver(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateHostResolverPrivate(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateImageData(PP_Instance instance,
+                                      PP_ImageDataFormat format,
+                                      const PP_Size* size,
+                                      PP_Bool init_to_zero) OVERRIDE;
+  virtual PP_Resource CreateImageDataSimple(PP_Instance instance,
+                                            PP_ImageDataFormat format,
+                                            const PP_Size* size,
+                                            PP_Bool init_to_zero) OVERRIDE;
+  virtual PP_Resource CreateNetAddressFromIPv4Address(
+      PP_Instance instance,
+      const PP_NetAddress_IPv4* ipv4_addr) OVERRIDE;
+  virtual PP_Resource CreateNetAddressFromIPv6Address(
+      PP_Instance instance,
+      const PP_NetAddress_IPv6* ipv6_addr) OVERRIDE;
+  virtual PP_Resource CreateNetAddressFromNetAddressPrivate(
+      PP_Instance instance,
+      const PP_NetAddress_Private& private_addr) OVERRIDE;
+  virtual PP_Resource CreateNetworkMonitor(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateOutputProtectionPrivate(
+      PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreatePrinting(PP_Instance) OVERRIDE;
+  virtual PP_Resource CreateTCPServerSocketPrivate(
+      PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateTCPSocket1_0(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateTCPSocket(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateTCPSocketPrivate(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateUDPSocket(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateUDPSocketPrivate(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateVideoDestination(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateVideoSource(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateWebSocket(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateX509CertificatePrivate(
+      PP_Instance instance) OVERRIDE;
+#if !defined(OS_NACL)
+  virtual PP_Resource CreateAudioInput(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateBroker(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateBrowserFont(
+      PP_Instance instance,
+      const PP_BrowserFont_Trusted_Description* description) OVERRIDE;
+  virtual PP_Resource CreateBuffer(PP_Instance instance,
+                                   uint32_t size) OVERRIDE;
+  virtual PP_Resource CreateFlashDRM(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateFlashFontFile(
+      PP_Instance instance,
+      const PP_BrowserFont_Trusted_Description* description,
+      PP_PrivateFontCharset charset) OVERRIDE;
+  virtual PP_Resource CreateFlashMenu(PP_Instance instance,
+                                      const PP_Flash_Menu* menu_data) OVERRIDE;
+  virtual PP_Resource CreateFlashMessageLoop(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreatePlatformVerificationPrivate(
+      PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateScrollbar(PP_Instance instance,
+                                      PP_Bool vertical) OVERRIDE;
+  virtual PP_Resource CreateTalk(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateVideoCapture(PP_Instance instance) OVERRIDE;
+  virtual PP_Resource CreateVideoDecoder(
+      PP_Instance instance,
+      PP_Resource context3d_id,
+      PP_VideoDecoder_Profile profile) OVERRIDE;
+#endif  // !defined(OS_NACL)
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ResourceCreationImpl);
+};
+
+}  // namespace examples
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_RESOURCE_CREATION_IMPL_H_
diff --git a/mojo/examples/pepper_container_app/thunk.h b/mojo/examples/pepper_container_app/thunk.h
new file mode 100644
index 0000000..f3b3d54
--- /dev/null
+++ b/mojo/examples/pepper_container_app/thunk.h
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_THUNK_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_THUNK_H_
+
+#include "ppapi/c/ppb_core.h"
+#include "ppapi/c/ppb_opengles2.h"
+
+namespace mojo {
+namespace examples {
+
+const PPB_Core_1_0* GetPPB_Core_1_0_Thunk();
+const PPB_OpenGLES2* GetPPB_OpenGLES2_Thunk();
+
+}  // namespace examples
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_THUNK_H_
diff --git a/mojo/examples/pepper_container_app/type_converters.h b/mojo/examples/pepper_container_app/type_converters.h
new file mode 100644
index 0000000..7362c3a
--- /dev/null
+++ b/mojo/examples/pepper_container_app/type_converters.h
@@ -0,0 +1,67 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_EXAMPLES_PEPPER_CONTAINER_APP_TYPE_CONVERTERS_H_
+#define MOJO_EXAMPLES_PEPPER_CONTAINER_APP_TYPE_CONVERTERS_H_
+
+#include "mojo/public/bindings/type_converter.h"
+#include "mojo/services/native_viewport/native_viewport.mojom.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_size.h"
+
+namespace mojo {
+
+template <>
+class TypeConverter<Point, PP_Point> {
+ public:
+  static Point ConvertFrom(const PP_Point& input, Buffer* buf) {
+    Point::Builder point(buf);
+    point.set_x(input.x);
+    point.set_y(input.y);
+    return point.Finish();
+  }
+
+  static PP_Point ConvertTo(const Point& input) {
+    return PP_MakePoint(static_cast<int32_t>(input.x()),
+                        static_cast<int32_t>(input.y()));
+  }
+};
+
+template <>
+class TypeConverter<Size, PP_Size> {
+ public:
+  static Size ConvertFrom(const PP_Size& input, Buffer* buf) {
+    Size::Builder size(buf);
+    size.set_width(input.width);
+    size.set_height(input.height);
+    return size.Finish();
+  }
+
+  static PP_Size ConvertTo(const Size& input) {
+    return PP_MakeSize(static_cast<int32_t>(input.width()),
+                       static_cast<int32_t>(input.height()));
+  }
+};
+
+template <>
+class TypeConverter<Rect, PP_Rect> {
+ public:
+  static Rect ConvertFrom(const PP_Rect& input, Buffer* buf) {
+    Rect::Builder rect(buf);
+    rect.set_position(input.point);
+    rect.set_size(input.size);
+    return rect.Finish();
+  }
+
+  static PP_Rect ConvertTo(const Rect& input) {
+    PP_Rect rect = { input.position().To<PP_Point>(),
+                     input.size().To<PP_Size>() };
+    return rect;
+  }
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_EXAMPLES_PEPPER_CONTAINER_APP_TYPE_CONVERTERS_H_
diff --git a/mojo/examples/sample_app/sample_app.cc b/mojo/examples/sample_app/sample_app.cc
index 6c078e1..66e9df4 100644
--- a/mojo/examples/sample_app/sample_app.cc
+++ b/mojo/examples/sample_app/sample_app.cc
@@ -8,13 +8,13 @@
 #include "mojo/examples/sample_app/gles2_client_impl.h"
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/remote_ptr.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/cpp/utility/run_loop.h"
 #include "mojo/public/gles2/gles2_cpp.h"
 #include "mojo/public/shell/application.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core.h"
-#include "mojo/public/system/macros.h"
-#include "mojo/public/utility/run_loop.h"
 #include "mojo/services/native_viewport/native_viewport.mojom.h"
 
 #if defined(WIN32)
diff --git a/mojo/examples/view_manager/view_manager.cc b/mojo/examples/view_manager/view_manager.cc
index 9568bdf..7560f93 100644
--- a/mojo/examples/view_manager/view_manager.cc
+++ b/mojo/examples/view_manager/view_manager.cc
@@ -12,10 +12,9 @@
 #include "mojo/examples/view_manager/view_manager.mojom.h"
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/remote_ptr.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/shell/application.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core.h"
-#include "mojo/public/system/macros.h"
 #include "mojo/services/native_viewport/geometry_conversions.h"
 #include "mojo/services/native_viewport/native_viewport.mojom.h"
 #include "ui/events/event_constants.h"
diff --git a/mojo/gles2/command_buffer_client_impl.cc b/mojo/gles2/command_buffer_client_impl.cc
index 60bb96a..16e7193 100644
--- a/mojo/gles2/command_buffer_client_impl.cc
+++ b/mojo/gles2/command_buffer_client_impl.cc
@@ -108,20 +108,20 @@
   NOTREACHED();
 }
 
-gpu::Buffer CommandBufferClientImpl::CreateTransferBuffer(size_t size,
-                                                          int32* id) {
-  gpu::Buffer buffer;
+scoped_refptr<gpu::Buffer> CommandBufferClientImpl::CreateTransferBuffer(
+    size_t size,
+    int32* id) {
   if (size >= std::numeric_limits<uint32_t>::max())
-    return buffer;
+    return NULL;
 
   scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
   if (!shared_memory->CreateAndMapAnonymous(size))
-    return buffer;
+    return NULL;
 
   base::SharedMemoryHandle handle;
   shared_memory->ShareToProcess(base::GetCurrentProcessHandle(), &handle);
   if (!base::SharedMemory::IsHandleValid(handle))
-    return buffer;
+    return NULL;
 
   *id = ++next_transfer_buffer_id_;
   DCHECK(transfer_buffers_.find(*id) == transfer_buffers_.end());
@@ -130,9 +130,8 @@
   command_buffer_->RegisterTransferBuffer(
       *id, handle, static_cast<uint32_t>(size));
 
-  buffer.ptr = shared_memory->memory();
-  buffer.size = size;
-  buffer.shared_memory = shared_memory.release();
+  scoped_refptr<gpu::Buffer> buffer =
+      new gpu::Buffer(shared_memory.Pass(), size);
   transfer_buffers_[*id] = buffer;
 
   return buffer;
@@ -140,19 +139,18 @@
 
 void CommandBufferClientImpl::DestroyTransferBuffer(int32 id) {
   TransferBufferMap::iterator it = transfer_buffers_.find(id);
-  if (it != transfer_buffers_.end()) {
-    delete it->second.shared_memory;
+  if (it != transfer_buffers_.end())
     transfer_buffers_.erase(it);
-  }
   command_buffer_->DestroyTransferBuffer(id);
 }
 
-gpu::Buffer CommandBufferClientImpl::GetTransferBuffer(int32 id) {
+scoped_refptr<gpu::Buffer> CommandBufferClientImpl::GetTransferBuffer(
+    int32 id) {
   TransferBufferMap::iterator it = transfer_buffers_.find(id);
   if (it != transfer_buffers_.end()) {
     return it->second;
   } else {
-    return gpu::Buffer();
+    return NULL;
   }
 }
 
diff --git a/mojo/gles2/command_buffer_client_impl.h b/mojo/gles2/command_buffer_client_impl.h
index d721564..2934274 100644
--- a/mojo/gles2/command_buffer_client_impl.h
+++ b/mojo/gles2/command_buffer_client_impl.h
@@ -57,9 +57,10 @@
   virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE;
   virtual void SetGetBuffer(int32 shm_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+                                                          int32* id) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(gpu::error::Error error) OVERRIDE;
   virtual void SetContextLostReason(gpu::error::ContextLostReason reason)
@@ -87,7 +88,7 @@
   void CancelAnimationFrames();
 
  private:
-  typedef std::map<int32, gpu::Buffer> TransferBufferMap;
+  typedef std::map<int32, scoped_refptr<gpu::Buffer> > TransferBufferMap;
 
   // CommandBufferClient implementation:
   virtual void DidInitialize(bool success) OVERRIDE;
diff --git a/mojo/gles2/gles2_context.cc b/mojo/gles2/gles2_context.cc
index 1cff999..78c9ba4 100644
--- a/mojo/gles2/gles2_context.cc
+++ b/mojo/gles2/gles2_context.cc
@@ -7,8 +7,8 @@
 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
 #include "gpu/command_buffer/client/gles2_implementation.h"
 #include "gpu/command_buffer/client/transfer_buffer.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/gles2/gles2.h"
-#include "mojo/public/system/core_cpp.h"
 
 namespace mojo {
 namespace gles2 {
diff --git a/mojo/mojo.gyp b/mojo/mojo.gyp
index 6805d28..e2457fd 100644
--- a/mojo/mojo.gyp
+++ b/mojo/mojo.gyp
@@ -35,6 +35,7 @@
         'mojo_common_unittests',
         'mojo_js',
         'mojo_js_unittests',
+        'mojo_pepper_container_app',
         'mojo_public_test_utils',
         'mojo_public_bindings_unittests',
         'mojo_public_environment_unittests',
@@ -147,6 +148,12 @@
         'system/raw_channel.h',
         'system/raw_channel_posix.cc',
         'system/raw_channel_win.cc',
+        'system/raw_shared_buffer.cc',
+        'system/raw_shared_buffer.h',
+        'system/raw_shared_buffer_posix.cc',
+        'system/raw_shared_buffer_win.cc',
+        'system/shared_buffer_dispatcher.cc',
+        'system/shared_buffer_dispatcher.h',
         'system/simple_dispatcher.cc',
         'system/simple_dispatcher.h',
         'system/waiter.cc',
@@ -173,6 +180,7 @@
       ],
       'sources': [
         'embedder/embedder_unittest.cc',
+        'embedder/platform_channel_pair_posix_unittest.cc',
         'system/core_impl_unittest.cc',
         'system/core_test_base.cc',
         'system/core_test_base.h',
@@ -183,7 +191,9 @@
         'system/message_pipe_unittest.cc',
         'system/multiprocess_message_pipe_unittest.cc',
         'system/raw_channel_unittest.cc',
+        'system/raw_shared_buffer_unittest.cc',
         'system/remote_message_pipe_unittest.cc',
+        'system/shared_buffer_dispatcher_unittest.cc',
         'system/simple_dispatcher_unittest.cc',
         'system/test_utils.cc',
         'system/test_utils.h',
@@ -336,21 +346,27 @@
     },
     {
       'target_name': 'mojo_service_manager',
-      'type': 'static_library',
+      'type': '<(component)',
+      'defines': [
+        'MOJO_SERVICE_MANAGER_IMPLEMENTATION',
+      ],
       'dependencies': [
         '../base/base.gyp:base',
         '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
         '../net/net.gyp:net',
         '../url/url.gyp:url_lib',
+        'mojo_environment_chromium',
         'mojo_shell_bindings',
       ],
       'sources': [
         'service_manager/service_loader.h',
         'service_manager/service_manager.cc',
         'service_manager/service_manager.h',
+        'service_manager/service_manager_export.h',
       ],
       'export_dependent_settings': [
         '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        'mojo_shell_bindings',
       ],
     },
     {
@@ -362,12 +378,15 @@
         '../net/net.gyp:net',
         '../url/url.gyp:url_lib',
         'mojo_gles2_impl',
-        'mojo_shell_bindings',
         'mojo_service_manager',
+        'mojo_shell_bindings',
         'mojo_system',
         'mojo_system_impl',
         'mojo_native_viewport_service',
       ],
+      'variables': {
+        'mojom_base_output_dir': 'mojo',
+      },
       'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
       'sources': [
         'shell/app_child_process.cc',
@@ -419,7 +438,7 @@
         '../url/url.gyp:url_lib',
         'mojo_common_lib',
         'mojo_environment_chromium',
-        'mojo_shell_bindings',
+        'mojo_service_manager',
         'mojo_shell_lib',
         'mojo_system',
         'mojo_system_impl',
@@ -434,13 +453,17 @@
       'dependencies': [
         '../base/base.gyp:base',
         '../testing/gtest.gyp:gtest',
+        '../url/url.gyp:url_lib',
         'mojo_bindings',
-        'mojo_environment_standalone',
+        'mojo_environment_chromium',
         'mojo_run_all_unittests',
         'mojo_service_manager',
+        'mojo_shell_client',
         'mojo_system',
-        'mojo_utility',
       ],
+      'variables': {
+        'mojom_base_output_dir': 'mojo',
+      },
       'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
       'sources': [
         'service_manager/service_manager_unittest.cc',
diff --git a/mojo/mojo_examples.gypi b/mojo/mojo_examples.gypi
index 79531d8..0731887 100644
--- a/mojo/mojo_examples.gypi
+++ b/mojo/mojo_examples.gypi
@@ -12,10 +12,11 @@
         '../ui/gfx/gfx.gyp:gfx',
         '../ui/gfx/gfx.gyp:gfx_geometry',
         '../ui/gl/gl.gyp:gl',
+        'mojo_bindings',
         'mojo_environment_standalone',
         'mojo_gles2',
         'mojo_native_viewport_bindings',
-        'mojo_shell_bindings',
+        'mojo_shell_client',
         'mojo_system',
         'mojo_utility',
       ],
@@ -63,7 +64,7 @@
         'mojo_environment_chromium',
         'mojo_gles2',
         'mojo_native_viewport_bindings',
-        'mojo_shell_bindings',
+        'mojo_shell_client',
         'mojo_system',
       ],
       'sources': [
@@ -79,6 +80,97 @@
       },
       'includes': [ 'build/package_app.gypi' ],
     },
+    {
+      'target_name': 'mojo_pepper_container_app',
+      'type': 'shared_library',
+      'dependencies': [
+        '../base/base.gyp:base',
+        '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../ppapi/ppapi.gyp:ppapi_c',
+        '../ppapi/ppapi_internal.gyp:ppapi_example_gles2_spinning_cube',
+        'mojo_environment_chromium',
+        'mojo_gles2',
+        'mojo_native_viewport_bindings',
+        'mojo_shell_client',
+        'mojo_system',
+      ],
+      'defines': [
+        # We don't really want to export. We could change how
+        # ppapi_{shared,thunk}_export.h are defined to avoid this.
+        'PPAPI_SHARED_IMPLEMENTATION',
+        'PPAPI_THUNK_IMPLEMENTATION',
+      ],
+      'sources': [
+        # Source files from ppapi/.
+        # An alternative is to depend on
+        # '../ppapi/ppapi_internal.gyp:ppapi_shared', but that target includes
+        # a lot of things that we don't need.
+        # TODO(yzshen): Consider extracting these files into a separate target
+        # which mojo_pepper_container_app and ppapi_shared both depend on.
+        '../ppapi/shared_impl/api_id.h',
+        '../ppapi/shared_impl/callback_tracker.cc',
+        '../ppapi/shared_impl/callback_tracker.h',
+        '../ppapi/shared_impl/host_resource.cc',
+        '../ppapi/shared_impl/host_resource.h',
+        '../ppapi/shared_impl/id_assignment.cc',
+        '../ppapi/shared_impl/id_assignment.h',
+        '../ppapi/shared_impl/ppapi_globals.cc',
+        '../ppapi/shared_impl/ppapi_globals.h',
+        '../ppapi/shared_impl/ppapi_shared_export.h',
+        '../ppapi/shared_impl/ppb_message_loop_shared.cc',
+        '../ppapi/shared_impl/ppb_message_loop_shared.h',
+        '../ppapi/shared_impl/ppb_view_shared.cc',
+        '../ppapi/shared_impl/ppb_view_shared.h',
+        '../ppapi/shared_impl/proxy_lock.cc',
+        '../ppapi/shared_impl/proxy_lock.h',
+        '../ppapi/shared_impl/resource.cc',
+        '../ppapi/shared_impl/resource.h',
+        '../ppapi/shared_impl/resource_tracker.cc',
+        '../ppapi/shared_impl/resource_tracker.h',
+        '../ppapi/shared_impl/scoped_pp_resource.cc',
+        '../ppapi/shared_impl/scoped_pp_resource.h',
+        '../ppapi/shared_impl/singleton_resource_id.h',
+        '../ppapi/shared_impl/tracked_callback.cc',
+        '../ppapi/shared_impl/tracked_callback.h',
+        '../ppapi/thunk/enter.cc',
+        '../ppapi/thunk/enter.h',
+        '../ppapi/thunk/interfaces_ppb_private.h',
+        '../ppapi/thunk/interfaces_ppb_private_flash.h',
+        '../ppapi/thunk/interfaces_ppb_private_no_permissions.h',
+        '../ppapi/thunk/interfaces_ppb_public_dev.h',
+        '../ppapi/thunk/interfaces_ppb_public_dev_channel.h',
+        '../ppapi/thunk/interfaces_ppb_public_stable.h',
+        '../ppapi/thunk/interfaces_preamble.h',
+        '../ppapi/thunk/ppapi_thunk_export.h',
+        '../ppapi/thunk/ppb_graphics_3d_api.h',
+        '../ppapi/thunk/ppb_graphics_3d_thunk.cc',
+        '../ppapi/thunk/ppb_instance_api.h',
+        '../ppapi/thunk/ppb_instance_thunk.cc',
+        '../ppapi/thunk/ppb_message_loop_api.h',
+        '../ppapi/thunk/ppb_view_api.h',
+        '../ppapi/thunk/ppb_view_thunk.cc',
+        '../ppapi/thunk/resource_creation_api.h',
+        '../ppapi/thunk/thunk.h',
+
+        'examples/pepper_container_app/graphics_3d_resource.cc',
+        'examples/pepper_container_app/graphics_3d_resource.h',
+        'examples/pepper_container_app/interface_list.cc',
+        'examples/pepper_container_app/interface_list.h',
+        'examples/pepper_container_app/mojo_ppapi_globals.cc',
+        'examples/pepper_container_app/mojo_ppapi_globals.h',
+        'examples/pepper_container_app/pepper_container_app.cc',
+        'examples/pepper_container_app/plugin_instance.cc',
+        'examples/pepper_container_app/plugin_instance.h',
+        'examples/pepper_container_app/plugin_module.cc',
+        'examples/pepper_container_app/plugin_module.h',
+        'examples/pepper_container_app/ppb_core_thunk.cc',
+        'examples/pepper_container_app/ppb_opengles2_thunk.cc',
+        'examples/pepper_container_app/resource_creation_impl.cc',
+        'examples/pepper_container_app/resource_creation_impl.h',
+        'examples/pepper_container_app/thunk.h',
+        'examples/pepper_container_app/type_converters.h',
+      ],
+    },
   ],
   'conditions': [
     ['use_aura==1', {
@@ -120,7 +212,7 @@
             'mojo_common_lib',
             'mojo_environment_chromium',
             'mojo_gles2',
-            'mojo_shell_bindings',
+            'mojo_shell_client',
             'mojo_system',
           ],
           'sources': [
@@ -140,6 +232,9 @@
           'sources': [
             'examples/launcher/launcher.mojom',
           ],
+          'variables': {
+            'mojom_base_output_dir': 'mojo',
+          },
           'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
           'export_dependent_settings': [
             'mojo_bindings',
@@ -168,7 +263,7 @@
             'mojo_environment_chromium',
             'mojo_gles2',
             'mojo_launcher_bindings',
-            'mojo_shell_bindings',
+            'mojo_shell_client',
             'mojo_system',
           ],
           'sources': [
@@ -188,6 +283,9 @@
           'sources': [
             'examples/view_manager/view_manager.mojom',
           ],
+          'variables': {
+            'mojom_base_output_dir': 'mojo',
+          },
           'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
           'export_dependent_settings': [
             'mojo_bindings',
@@ -208,7 +306,7 @@
             'mojo_environment_chromium',
             'mojo_launcher_bindings',
             'mojo_native_viewport_bindings',
-            'mojo_shell_bindings',
+            'mojo_shell_client',
             'mojo_system',
             'mojo_view_manager_bindings',
           ],
diff --git a/mojo/mojo_public.gypi b/mojo/mojo_public.gypi
index a17d3d4..725527a 100644
--- a/mojo/mojo_public.gypi
+++ b/mojo/mojo_public.gypi
@@ -15,13 +15,14 @@
         ],
       },
       'sources': [
-        'public/system/async_waiter.h',
-        'public/system/core.h',
-        'public/system/core_cpp.h',
+        'public/c/system/async_waiter.h',
+        'public/c/system/core.h',
+        'public/c/system/macros.h',
+        'public/c/system/system_export.h',
+        'public/cpp/system/core.h',
+        'public/cpp/system/macros.h',
         'public/system/core_private.cc',
         'public/system/core_private.h',
-        'public/system/macros.h',
-        'public/system/system_export.h',
       ],
       'conditions': [
         ['OS=="mac"', {
@@ -129,6 +130,7 @@
         'public/tests/test_utils.h',
       ],
     },
+    # TODO(vtl): Reorganize the mojo_public_*_unittests.
     {
       'target_name': 'mojo_public_bindings_unittests',
       'type': 'executable',
@@ -157,6 +159,9 @@
         'public/bindings/tests/test_structs.mojom',
         'public/bindings/tests/type_conversion_unittest.cc',
       ],
+      'variables': {
+        'mojom_base_output_dir': 'mojo',
+      },
       'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
     },
     {
@@ -172,7 +177,7 @@
         'mojo_utility',
       ],
       'sources': [
-        'public/environment/tests/async_waiter_unittest.cc',
+        'public/cpp/environment/tests/async_waiter_unittest.cc',
       ],
     },
     {
@@ -187,10 +192,11 @@
         'mojo_system',
       ],
       'sources': [
-        'public/tests/system/core_cpp_unittest.cc',
-        'public/tests/system/core_unittest.cc',
-        'public/tests/system/core_unittest_pure_c.c',
-        'public/tests/system/macros_unittest.cc',
+        'public/c/system/tests/core_unittest.cc',
+        'public/c/system/tests/core_unittest_pure_c.c',
+        'public/c/system/tests/macros_unittest.cc',
+        'public/cpp/system/tests/core_unittest.cc',
+        'public/cpp/system/tests/macros_unittest.cc',
       ],
     },
     {
@@ -206,16 +212,16 @@
         'mojo_utility',
       ],
       'sources': [
-        'public/utility/tests/mutex_unittest.cc',
-        'public/utility/tests/run_loop_unittest.cc',
-        'public/utility/tests/thread_unittest.cc',
+        'public/cpp/utility/tests/mutex_unittest.cc',
+        'public/cpp/utility/tests/run_loop_unittest.cc',
+        'public/cpp/utility/tests/thread_unittest.cc',
       ],
       'conditions': [
         # See crbug.com/342893:
         ['OS=="win"', {
           'sources!': [
-            'public/utility/tests/mutex_unittest.cc',
-            'public/utility/tests/thread_unittest.cc',
+            'public/cpp/utility/tests/mutex_unittest.cc',
+            'public/cpp/utility/tests/thread_unittest.cc',
           ],
         }],
       ],
@@ -232,7 +238,7 @@
         'mojo_utility',
       ],
       'sources': [
-        'public/tests/system/core_perftest.cc',
+        'public/c/system/tests/core_perftest.cc',
       ],
     },
     {
@@ -248,6 +254,8 @@
         'public/bindings/callback.h',
         'public/bindings/error_handler.h',
         'public/bindings/interface.h',
+        'public/bindings/js/constants.cc',
+        'public/bindings/js/constants.h',
         'public/bindings/message.h',
         'public/bindings/passable.h',
         'public/bindings/remote_ptr.h',
@@ -289,6 +297,9 @@
         'public/bindings/tests/sample_import.mojom',
         'public/bindings/tests/sample_import2.mojom',
       ],
+      'variables': {
+        'mojom_base_output_dir': 'mojo',
+      },
       'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
       'export_dependent_settings': [
         'mojo_bindings',
@@ -303,13 +314,13 @@
       'target_name': 'mojo_environment_standalone',
       'type': 'static_library',
       'sources': [
-        'public/environment/buffer_tls.h',
-        'public/environment/default_async_waiter.h',
-        'public/environment/environment.h',
-        'public/environment/lib/default_async_waiter.cc',
-        'public/environment/lib/buffer_tls.cc',
-        'public/environment/lib/buffer_tls_setup.h',
-        'public/environment/lib/environment.cc',
+        'public/cpp/environment/buffer_tls.h',
+        'public/cpp/environment/default_async_waiter.h',
+        'public/cpp/environment/environment.h',
+        'public/cpp/environment/lib/default_async_waiter.cc',
+        'public/cpp/environment/lib/buffer_tls.cc',
+        'public/cpp/environment/lib/buffer_tls_setup.h',
+        'public/cpp/environment/lib/environment.cc',
       ],
       'include_dirs': [
         '..',
@@ -319,25 +330,25 @@
       'target_name': 'mojo_utility',
       'type': 'static_library',
       'sources': [
-        'public/utility/mutex.h',
-        'public/utility/run_loop.h',
-        'public/utility/run_loop_handler.h',
-        'public/utility/thread.h',
-        'public/utility/lib/mutex.cc',
-        'public/utility/lib/run_loop.cc',
-        'public/utility/lib/thread.cc',
-        'public/utility/lib/thread_local.h',
-        'public/utility/lib/thread_local_posix.cc',
-        'public/utility/lib/thread_local_win.cc',
+        'public/cpp/utility/mutex.h',
+        'public/cpp/utility/run_loop.h',
+        'public/cpp/utility/run_loop_handler.h',
+        'public/cpp/utility/thread.h',
+        'public/cpp/utility/lib/mutex.cc',
+        'public/cpp/utility/lib/run_loop.cc',
+        'public/cpp/utility/lib/thread.cc',
+        'public/cpp/utility/lib/thread_local.h',
+        'public/cpp/utility/lib/thread_local_posix.cc',
+        'public/cpp/utility/lib/thread_local_win.cc',
       ],
       'conditions': [
         # See crbug.com/342893:
         ['OS=="win"', {
           'sources!': [
-            'public/utility/mutex.h',
-            'public/utility/thread.h',
-            'public/utility/lib/mutex.cc',
-            'public/utility/lib/thread.cc',
+            'public/cpp/utility/mutex.h',
+            'public/cpp/utility/thread.h',
+            'public/cpp/utility/lib/mutex.cc',
+            'public/cpp/utility/lib/thread.cc',
           ],
         }],
       ],
@@ -349,12 +360,11 @@
       'target_name': 'mojo_shell_bindings',
       'type': 'static_library',
       'sources': [
-        'public/shell/lib/application.cc',
-        'public/shell/lib/service.cc',
-        'public/shell/application.h',
-        'public/shell/service.h',
         'public/shell/shell.mojom',
       ],
+      'variables': {
+        'mojom_base_output_dir': 'mojo',
+      },
       'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
       'dependencies': [
         'mojo_bindings',
@@ -362,7 +372,22 @@
       ],
       'export_dependent_settings': [
         'mojo_bindings',
-        'mojo_system',
+      ],
+    },
+    {
+      'target_name': 'mojo_shell_client',
+      'type': 'static_library',
+      'sources': [
+        'public/shell/lib/application.cc',
+        'public/shell/lib/service.cc',
+        'public/shell/application.h',
+        'public/shell/service.h',
+      ],
+      'dependencies': [
+        'mojo_shell_bindings',
+      ],
+      'export_dependent_settings': [
+        'mojo_shell_bindings',
       ],
     },
   ],
diff --git a/mojo/mojo_services.gypi b/mojo/mojo_services.gypi
index e3c8bb5..57176ec 100644
--- a/mojo/mojo_services.gypi
+++ b/mojo/mojo_services.gypi
@@ -8,6 +8,9 @@
         'services/gles2/command_buffer_type_conversions.cc',
         'services/gles2/command_buffer_type_conversions.h',
       ],
+      'variables': {
+        'mojom_base_output_dir': 'mojo',
+      },
       'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
       'export_dependent_settings': [
         'mojo_bindings',
@@ -43,6 +46,9 @@
       'sources': [
         'services/native_viewport/native_viewport.mojom',
       ],
+      'variables': {
+        'mojom_base_output_dir': 'mojo',
+      },
       'includes': [ 'public/bindings/mojom_bindings_generator.gypi' ],
       'export_dependent_settings': [
         'mojo_bindings',
@@ -65,7 +71,7 @@
         'mojo_environment_chromium',
         'mojo_gles2_service',
         'mojo_native_viewport_bindings',
-        'mojo_shell_bindings',
+        'mojo_shell_client',
       ],
       'defines': [
         'MOJO_NATIVE_VIEWPORT_IMPLEMENTATION',
diff --git a/mojo/public/bindings/allocation_scope.h b/mojo/public/bindings/allocation_scope.h
index 16dc426..05737b9 100644
--- a/mojo/public/bindings/allocation_scope.h
+++ b/mojo/public/bindings/allocation_scope.h
@@ -6,10 +6,25 @@
 #define MOJO_PUBLIC_BINDINGS_ALLOCATION_SCOPE_H_
 
 #include "mojo/public/bindings/lib/scratch_buffer.h"
-#include "mojo/public/system/macros.h"
+#include "mojo/public/cpp/system/macros.h"
 
 namespace mojo {
 
+// In order to allocate a Mojom-defined structure or mojo::Array<T> (including
+// mojo::String), an AllocationScope must first be allocated. Typically,
+// AllocationScope is placed on the stack before calls to build structs and
+// arrays. Such structs and arrays are valid so long as the corresponding
+// AllocationScope remains alive.
+//
+// AllocationScope instantiates a Buffer and sets it in thread local storage.
+// This Buffer instance can be retrieved using Buffer::current().
+//
+// EXAMPLE:
+//
+//   mojo::AllocationScope scope;
+//   mojo::String s = "hello world";
+//   some_interface->SomeMethod(s);
+//
 class AllocationScope {
  public:
   AllocationScope() {}
diff --git a/mojo/public/bindings/buffer.h b/mojo/public/bindings/buffer.h
index bdd3349..13a65f1 100644
--- a/mojo/public/bindings/buffer.h
+++ b/mojo/public/bindings/buffer.h
@@ -18,8 +18,11 @@
   Buffer();
   virtual ~Buffer();
 
+  // A destructor may optionally be assigned to the allocation. Destructors run
+  // (in LIFO order) when the Buffer instance is destroyed.
   virtual void* Allocate(size_t num_bytes, Destructor func = NULL) = 0;
 
+  // Returns the current Buffer from thread local storage. May be NULL.
   static Buffer* current();
 
  private:
diff --git a/mojo/public/bindings/generators/cpp_templates/interface_declaration.tmpl b/mojo/public/bindings/generators/cpp_templates/interface_declaration.tmpl
index c401a1f..5b61e17 100644
--- a/mojo/public/bindings/generators/cpp_templates/interface_declaration.tmpl
+++ b/mojo/public/bindings/generators/cpp_templates/interface_declaration.tmpl
@@ -27,5 +27,8 @@
 {%- endfor %}
 };
 
+// A typesafe variant of MessagePipeHandle.
 typedef mojo::Interface<{{interface.name}}>::Handle {{interface.name}}Handle;
+
+// A typesafe variant of ScopedMessagePipeHandle.
 typedef mojo::Interface<{{interface.name}}>::ScopedHandle Scoped{{interface.name}}Handle;
diff --git a/mojo/public/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl b/mojo/public/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
index 8d41dab..e43146e 100644
--- a/mojo/public/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
+++ b/mojo/public/bindings/generators/cpp_templates/wrapper_class_declaration.tmpl
@@ -18,8 +18,7 @@
 
   template <typename U>
   {{struct.name}}& operator=(const U& u) {
-    *this =
-        mojo::TypeConverter<{{struct.name}},U>::ConvertFrom(u, mojo::Buffer::current());
+    *this = mojo::TypeConverter<{{struct.name}},U>::ConvertFrom(u, mojo::Buffer::current());
     return *this;
   }
 
diff --git a/mojo/public/bindings/generators/js_templates/interface_definition.tmpl b/mojo/public/bindings/generators/js_templates/interface_definition.tmpl
index df1483d..fc77059 100644
--- a/mojo/public/bindings/generators/js_templates/interface_definition.tmpl
+++ b/mojo/public/bindings/generators/js_templates/interface_definition.tmpl
@@ -10,18 +10,40 @@
   {{interface.name}}Proxy.prototype.{{method.name|stylize_method}} = function(
 {%- for parameter in method.parameters -%}
 {{parameter.name}}{% if not loop.last %}, {% endif %}
-{%- endfor %}) {
+{%- endfor -%}
+{%- if method.response_parameters != None -%}
+, closure
+{%- endif -%}
+) {
     var params = new {{interface.name}}_{{method.name}}_Params();
 {%- for parameter in method.parameters %}
     params.{{parameter.name}} = {{parameter.name}};
 {%- endfor %}
 
+{%- if method.response_parameters == None %}
     var builder = new codec.MessageBuilder(
         k{{interface.name}}_{{method.name}}_Name,
         codec.align({{interface.name}}_{{method.name}}_Params.encodedSize));
     builder.encodeStruct({{interface.name}}_{{method.name}}_Params, params);
     var message = builder.finish();
     this.receiver_.accept(message);
+{%- else %}
+    var builder = new codec.MessageWithRequestIDBuilder(
+        k{{interface.name}}_{{method.name}}_Name,
+        codec.align({{interface.name}}_{{method.name}}_Params.encodedSize),
+        codec.kMessageExpectsResponse, 0);
+    builder.encodeStruct({{interface.name}}_{{method.name}}_Params, params);
+    var message = builder.finish();
+    this.receiver_.acceptWithResponder(message, { accept: function(message) {
+      var reader = new codec.MessageReader(message);
+      var responseParams =
+          reader.decodeStruct({{interface.name}}_{{method.name}}_ResponseParams);
+      closure(
+{%- for parameter in method.response_parameters -%}
+responseParams.{{parameter.name}}{% if not loop.last %}, {% endif %}
+{%- endfor -%});
+    }});
+{%- endif %}
   };
 {%- endfor %}
 
@@ -32,6 +54,7 @@
     var reader = new codec.MessageReader(message);
     switch (reader.messageName) {
 {%- for method in interface.methods %}
+{%- if method.response_parameters == None %}
     case k{{interface.name}}_{{method.name}}_Name:
       var params = reader.decodeStruct({{interface.name}}_{{method.name}}_Params);
       this.{{method.name|stylize_method}}(
@@ -39,6 +62,44 @@
 params.{{parameter.name}}{% if not loop.last %}, {% endif %}
 {%- endfor %});
       return true;
+{%- endif %}
+{%- endfor %}
+    default:
+      return false;
+    }
+  };
+
+  {{interface.name}}Stub.prototype.acceptWithResponder =
+      function(message, responder) {
+    var reader = new codec.MessageReader(message);
+    switch (reader.messageName) {
+{%- for method in interface.methods %}
+{%- if method.response_parameters != None %}
+    case k{{interface.name}}_{{method.name}}_Name:
+      var params = reader.decodeStruct({{interface.name}}_{{method.name}}_Params);
+      this.{{method.name|stylize_method}}(
+{%- for parameter in method.parameters -%}
+params.{{parameter.name}},
+{%- endfor %} function (
+{%- for parameter in method.response_parameters -%}
+{{parameter.name}}{% if not loop.last %}, {% endif -%}
+{%- endfor -%}) {
+        var responseParams =
+            new {{interface.name}}_{{method.name}}_ResponseParams();
+{%-     for parameter in method.response_parameters %}
+        responseParams.{{parameter.name}} = {{parameter.name}};
+{%-     endfor %}
+        var builder = new codec.MessageWithRequestIDBuilder(
+            k{{interface.name}}_{{method.name}}_Name,
+            codec.align({{interface.name}}_{{method.name}}_ResponseParams.encodedSize),
+            codec.kMessageIsResponse, reader.requestID);
+        builder.encodeStruct({{interface.name}}_{{method.name}}_ResponseParams,
+                             responseParams);
+        var message = builder.finish();
+        responder.accept(message);
+      });
+      return true;
+{%- endif %}
 {%- endfor %}
     default:
       return false;
diff --git a/mojo/public/bindings/generators/mojom_cpp_generator.py b/mojo/public/bindings/generators/mojom_cpp_generator.py
index 332902b..85c146e 100644
--- a/mojo/public/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/bindings/generators/mojom_cpp_generator.py
@@ -47,7 +47,7 @@
   if isinstance(kind, mojom.Array):
     return "mojo::internal::Array_Data<%s>*" % GetCppType(kind.kind)
   if isinstance(kind, mojom.Interface):
-    return "mojo::Interface<%s>::Handle" % kind.name
+    return "%sHandle" % kind.name
   if isinstance(kind, mojom.Enum):
     return "int32_t"
   if kind.spec == 's':
@@ -60,7 +60,7 @@
   if isinstance(kind, mojom.Array):
     return "mojo::Array<%s >" % GetCppArrayArgWrapperType(kind.kind)
   if isinstance(kind, mojom.Interface):
-    return "mojo::Interface<%s>::Handle" % kind.name
+    return "%sHandle" % kind.name
   if kind.spec == 's':
     return "mojo::String"
   return _kind_to_cpp_type[kind]
@@ -71,7 +71,7 @@
   if isinstance(kind, mojom.Array):
     return "mojo::Array<%s >" % GetCppArrayArgWrapperType(kind.kind)
   if isinstance(kind, mojom.Interface):
-    return "mojo::Interface<%s>::ScopedHandle" % kind.name
+    return "Scoped%sHandle" % kind.name
   if kind.spec == 's':
     return "mojo::String"
   if kind.spec == 'h':
@@ -90,7 +90,7 @@
   if isinstance(kind, mojom.Array):
     return "mojo::Array<%s >" % GetCppArrayArgWrapperType(kind.kind)
   if isinstance(kind, mojom.Interface):
-    return "mojo::Passable<typename mojo::Interface<%s>::Handle>" % kind.name
+    return "mojo::Passable<%sHandle>" % kind.name
   if kind.spec == 's':
     return "mojo::String"
   if mojom_generator.IsHandleKind(kind):
@@ -103,7 +103,7 @@
   if isinstance(kind, mojom.Array):
     return "const mojo::Array<%s >&" % GetCppArrayArgWrapperType(kind.kind)
   if isinstance(kind, mojom.Interface):
-    return "mojo::Interface<%s>::ScopedHandle" % kind.name
+    return "Scoped%sHandle" % kind.name
   if isinstance(kind, mojom.Enum):
     return GetNameForKind(kind)
   if kind.spec == 's':
@@ -127,7 +127,7 @@
   if isinstance(kind, mojom.Array):
     return "mojo::internal::ArrayPointer<%s>" % GetCppType(kind.kind)
   if isinstance(kind, mojom.Interface):
-    return "mojo::Interface<%s>::Handle" % kind.name
+    return "%sHandle" % kind.name
   if isinstance(kind, mojom.Enum):
     return GetNameForKind(kind)
   if kind.spec == 's':
diff --git a/mojo/public/bindings/interface.h b/mojo/public/bindings/interface.h
index 36d4bab..ff3f297 100644
--- a/mojo/public/bindings/interface.h
+++ b/mojo/public/bindings/interface.h
@@ -8,7 +8,7 @@
 #include <assert.h>
 
 #include "mojo/public/bindings/message.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 
diff --git a/mojo/public/bindings/js/codec.js b/mojo/public/bindings/js/codec.js
index 52357f4..9827b36 100644
--- a/mojo/public/bindings/js/codec.js
+++ b/mojo/public/bindings/js/codec.js
@@ -84,6 +84,7 @@
   var kArrayHeaderSize = 8;
   var kStructHeaderSize = 8;
   var kMessageHeaderSize = 16;
+  var kMessageWithRequestIDHeaderSize = 24;
 
   // Decoder ------------------------------------------------------------------
 
@@ -287,11 +288,24 @@
 
   // Message ------------------------------------------------------------------
 
+  var kMessageExpectsResponse = 1 << 0;
+  var kMessageIsResponse      = 1 << 1;
+
   function Message(memory, handles) {
     this.memory = memory;
     this.handles = handles;
   }
 
+  Message.prototype.setRequestID = function(requestID) {
+    // TODO(darin): Verify that space was reserved for this field!
+    store64(this.memory, 4 + 4 + 4 + 4, requestID);
+  };
+
+  Message.prototype.getFlags = function() {
+    // Skip over num_bytes, num_fields, and message_name.
+    return load32(this.memory, 4 + 4 + 4);
+  };
+
   // MessageBuilder -----------------------------------------------------------
 
   function MessageBuilder(messageName, payloadSize) {
@@ -310,7 +324,7 @@
   MessageBuilder.prototype.createEncoder = function(size) {
     var pointer = this.buffer.alloc(size);
     return new Encoder(this.buffer, this.handles, pointer);
-  }
+  };
 
   MessageBuilder.prototype.encodeStruct = function(cls, val) {
     cls.encode(this.createEncoder(cls.encodedSize), val);
@@ -327,16 +341,40 @@
     return message;
   };
 
+  // MessageWithRequestIDBuilder -----------------------------------------------
+
+  function MessageWithRequestIDBuilder(messageName, payloadSize, flags,
+                                       requestID) {
+    // Currently, we don't compute the payload size correctly ahead of time.
+    // Instead, we resize the buffer at the end.
+    var numberOfBytes = kMessageWithRequestIDHeaderSize + payloadSize;
+    this.buffer = new Buffer(numberOfBytes);
+    this.handles = [];
+    var encoder = this.createEncoder(kMessageWithRequestIDHeaderSize);
+    encoder.write32(kMessageWithRequestIDHeaderSize);
+    encoder.write32(3);  // num_fields.
+    encoder.write32(messageName);
+    encoder.write32(flags);
+    encoder.write64(requestID);
+  }
+
+  MessageWithRequestIDBuilder.prototype =
+      Object.create(MessageBuilder.prototype);
+  MessageWithRequestIDBuilder.prototype.constructor =
+      MessageWithRequestIDBuilder;
+
   // MessageReader ------------------------------------------------------------
 
   function MessageReader(message) {
     this.decoder = new Decoder(message.memory, message.handles, 0);
     var messageHeaderSize = this.decoder.read32();
     this.payloadSize = message.memory.length - messageHeaderSize;
-    var numberOfFields = this.decoder.read32();
-    // TODO: better handling of messages of different size.
+    var numFields = this.decoder.read32();
     this.messageName = this.decoder.read32();
-    var flags = this.decoder.read32();
+    this.flags = this.decoder.read32();
+    if (numFields >= 3)
+      this.requestID = this.decoder.read64();
+    this.decoder.skip(messageHeaderSize - this.decoder.next);
   }
 
   MessageReader.prototype.decodeStruct = function(cls) {
@@ -449,10 +487,13 @@
   exports.align = align;
   exports.Message = Message;
   exports.MessageBuilder = MessageBuilder;
+  exports.MessageWithRequestIDBuilder = MessageWithRequestIDBuilder;
   exports.MessageReader = MessageReader;
   exports.kArrayHeaderSize = kArrayHeaderSize;
   exports.kStructHeaderSize = kStructHeaderSize;
   exports.kMessageHeaderSize = kMessageHeaderSize;
+  exports.kMessageExpectsResponse = kMessageExpectsResponse;
+  exports.kMessageIsResponse = kMessageIsResponse;
   exports.Uint8 = Uint8;
   exports.Uint16 = Uint16;
   exports.Uint32 = Uint32;
diff --git a/mojo/public/bindings/js/connection.js b/mojo/public/bindings/js/connection.js
new file mode 100644
index 0000000..96c7419
--- /dev/null
+++ b/mojo/public/bindings/js/connection.js
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define("mojo/public/bindings/js/connection", [
+  "mojo/public/bindings/js/router",
+], function(router) {
+
+  function Connection(handle, localFactory, remoteFactory) {
+    this.router_ = new router.Router(handle);
+    this.remote = new remoteFactory(this.router_);
+    this.local = new localFactory(this.remote);
+    this.router_.setIncomingReceiver(this.local);
+  }
+
+  Connection.prototype.close = function() {
+    this.router_.close();
+    this.router_ = null;
+    this.local = null;
+    this.remote = null;
+  };
+
+  Connection.prototype.encounteredError = function() {
+    return this.router_.encounteredError();
+  };
+
+  var exports = {};
+  exports.Connection = Connection;
+  return exports;
+});
diff --git a/mojo/public/bindings/js/connector.js b/mojo/public/bindings/js/connector.js
index 9a1bfc7..2aa9a9f 100644
--- a/mojo/public/bindings/js/connector.js
+++ b/mojo/public/bindings/js/connector.js
@@ -10,9 +10,12 @@
 
   function Connector(handle) {
     this.handle_ = handle;
+    this.dropWrites_ = false;
     this.error_ = false;
     this.incomingReceiver_ = null;
     this.readWaitCookie_ = null;
+
+    this.waitToReadMore_();
   }
 
   Connector.prototype.close = function() {
@@ -29,29 +32,45 @@
   Connector.prototype.accept = function(message) {
     if (this.error_)
       return false;
-    this.write_(message);
-    return !this.error_;
-  };
 
-  Connector.prototype.setIncomingReceiver = function(receiver) {
-    this.incomingReceiver_ = receiver;
-    if (this.incomingReceiver_)
-      this.waitToReadMore_();
-  };
+    if (this.dropWrites_)
+      return true;
 
-  Connector.prototype.write_ = function(message) {
     var result = core.writeMessage(this.handle_,
                                    message.memory,
                                    message.handles,
                                    core.WRITE_MESSAGE_FLAG_NONE);
-    if (result != core.RESULT_OK) {
-      this.error_ = true
-      return;
+
+    switch (result) {
+      case core.RESULT_OK:
+        // The handles were successfully transferred, so we don't own them
+        // anymore.
+        message.handles = [];
+        break;
+      case core.RESULT_FAILED_PRECONDITION:
+        // There's no point in continuing to write to this pipe since the other
+        // end is gone. Avoid writing any future messages. Hide write failures
+        // from the caller since we'd like them to continue consuming any
+        // backlog of incoming messages before regarding the message pipe as
+        // closed.
+        this.dropWrites_ = true;
+        break;
+      default:
+        // This particular write was rejected, presumably because of bad input.
+        // The pipe is not necessarily in a bad state.
+        return false;
     }
-    // The handles were successfully transferred, so we don't own them anymore.
-    message.handles = [];
+    return true;
   };
 
+  Connector.prototype.setIncomingReceiver = function(receiver) {
+    this.incomingReceiver_ = receiver;
+  };
+
+  Connector.prototype.encounteredError = function() {
+    return this.error_;
+  }
+
   Connector.prototype.waitToReadMore_ = function() {
     this.readWaitCookie_ = support.asyncWait(this.handle_,
                                              core.WAIT_FLAG_READABLE,
@@ -73,25 +92,12 @@
       // TODO(abarth): Should core.readMessage return a Uint8Array?
       var memory = new Uint8Array(read.buffer);
       var message = new codec.Message(memory, read.handles);
-      this.incomingReceiver_.accept(message);
+      if (this.incomingReceiver_)
+        this.incomingReceiver_.accept(message);
     }
   };
 
-  function Connection(handle, localFactory, remoteFactory) {
-    this.connector_ = new Connector(handle);
-    this.remote = new remoteFactory(this.connector_);
-    this.local = new localFactory(this.remote);
-    this.connector_.setIncomingReceiver(this.local);
-  }
-
-  Connection.prototype.close = function() {
-    this.connector_.close();
-    this.connector_ = null;
-    this.local = null;
-    this.remote = null;
-  };
-
   var exports = {};
-  exports.Connection = Connection;
+  exports.Connector = Connector;
   return exports;
 });
diff --git a/mojo/public/bindings/js/constants.cc b/mojo/public/bindings/js/constants.cc
new file mode 100644
index 0000000..fef4f35
--- /dev/null
+++ b/mojo/public/bindings/js/constants.cc
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/bindings/js/constants.h"
+
+namespace mojo {
+
+const char kCodecModuleName[] = "mojo/public/bindings/js/codec";
+const char kConnectionModuleName[] = "mojo/public/bindings/js/connection";
+const char kConnectorModuleName[] = "mojo/public/bindings/js/connector";
+const char kRouterModuleName[] = "mojo/public/bindings/js/router";
+
+}  // namespace mojo
diff --git a/mojo/public/bindings/js/constants.h b/mojo/public/bindings/js/constants.h
new file mode 100644
index 0000000..f2685a6
--- /dev/null
+++ b/mojo/public/bindings/js/constants.h
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_BINDINGS_JS_CONSTANTS_H_
+#define MOJO_PUBLIC_BINDINGS_JS_CONSTANTS_H_
+
+namespace mojo {
+
+// JavaScript module names:
+extern const char kCodecModuleName[];
+extern const char kConnectionModuleName[];
+extern const char kConnectorModuleName[];
+extern const char kRouterModuleName[];
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_BINDINGS_JS_CONSTANTS_H_
diff --git a/mojo/public/bindings/js/router.js b/mojo/public/bindings/js/router.js
new file mode 100644
index 0000000..4a51674
--- /dev/null
+++ b/mojo/public/bindings/js/router.js
@@ -0,0 +1,75 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+define("mojo/public/bindings/js/router", [
+  "mojo/public/bindings/js/codec",
+  "mojo/public/bindings/js/connector",
+], function(codec, connector) {
+
+  function Router(handle) {
+    this.connector_ = new connector.Connector(handle);
+    this.incomingReceiver_ = null;
+    this.nextRequestID_ = 0;
+    this.responders_ = {};
+
+    this.connector_.setIncomingReceiver({
+        accept: this.handleIncomingMessage_.bind(this),
+    });
+  }
+
+  Router.prototype.close = function() {
+    this.responders_ = {};  // Drop any responders.
+    this.connector_.close();
+  };
+
+  Router.prototype.accept = function(message) {
+    this.connector_.accept(message);
+  };
+
+  Router.prototype.acceptWithResponder = function(message, responder) {
+    // Reserve 0 in case we want it to convey special meaning in the future.
+    var requestID = this.nextRequestID_++;
+    if (requestID == 0)
+      requestID = this.nextRequestID_++;
+
+    message.setRequestID(requestID);
+    this.connector_.accept(message);
+
+    this.responders_[requestID] = responder;
+  };
+
+  Router.prototype.setIncomingReceiver = function(receiver) {
+    this.incomingReceiver_ = receiver;
+  };
+
+  Router.prototype.encounteredError = function() {
+    return this.connector_.encounteredError();
+  };
+
+  Router.prototype.handleIncomingMessage_ = function(message) {
+    var flags = message.getFlags();
+    if (flags & codec.kMessageExpectsResponse) {
+      if (this.incomingReceiver_) {
+        this.incomingReceiver_.acceptWithResponder(message, this);
+      } else {
+        // If we receive a request expecting a response when the client is not
+        // listening, then we have no choice but to tear down the pipe.
+        this.close();
+      }
+    } else if (flags & codec.kMessageIsResponse) {
+      var reader = new codec.MessageReader(message);
+      var requestID = reader.requestID;
+      var responder = this.responders_[requestID];
+      delete this.responders_[requestID];
+      responder.accept(message);
+    } else {
+      if (this.incomingReceiver_)
+        this.incomingReceiver_.accept(message);
+    }
+  };
+
+  var exports = {};
+  exports.Router = Router;
+  return exports;
+});
diff --git a/mojo/public/bindings/lib/DEPS b/mojo/public/bindings/lib/DEPS
index 7f810b1..0a519d5 100644
--- a/mojo/public/bindings/lib/DEPS
+++ b/mojo/public/bindings/lib/DEPS
@@ -1,5 +1,6 @@
 include_rules = [
-  "-mojo"
-  "+mojo/public/environment"
-  "+mojo/public/system"
+  "-mojo",
+  "+mojo/public/bindings",
+  "+mojo/public/cpp/environment",
+  "+mojo/public/cpp/system",
 ]
diff --git a/mojo/public/bindings/lib/array_internal.h b/mojo/public/bindings/lib/array_internal.h
index 2368b87..0bc5882 100644
--- a/mojo/public/bindings/lib/array_internal.h
+++ b/mojo/public/bindings/lib/array_internal.h
@@ -11,7 +11,7 @@
 #include "mojo/public/bindings/lib/bindings_internal.h"
 #include "mojo/public/bindings/lib/bindings_serialization.h"
 #include "mojo/public/bindings/passable.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 template <typename T> class Array;
diff --git a/mojo/public/bindings/lib/bindings_internal.h b/mojo/public/bindings/lib/bindings_internal.h
index 7c2a8f1..3a167f3 100644
--- a/mojo/public/bindings/lib/bindings_internal.h
+++ b/mojo/public/bindings/lib/bindings_internal.h
@@ -5,7 +5,7 @@
 #ifndef MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_INTERNAL_H_
 #define MOJO_PUBLIC_BINDINGS_LIB_BINDINGS_INTERNAL_H_
 
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 namespace internal {
diff --git a/mojo/public/bindings/lib/buffer.cc b/mojo/public/bindings/lib/buffer.cc
index 0f1ce86..8b29169 100644
--- a/mojo/public/bindings/lib/buffer.cc
+++ b/mojo/public/bindings/lib/buffer.cc
@@ -6,8 +6,8 @@
 
 #include <assert.h>
 
-#include "mojo/public/environment/buffer_tls.h"
-#include "mojo/public/system/macros.h"
+#include "mojo/public/cpp/environment/buffer_tls.h"
+#include "mojo/public/cpp/system/macros.h"
 
 namespace mojo {
 
diff --git a/mojo/public/bindings/lib/connector.h b/mojo/public/bindings/lib/connector.h
index 9377ea5..eeb0f53 100644
--- a/mojo/public/bindings/lib/connector.h
+++ b/mojo/public/bindings/lib/connector.h
@@ -7,8 +7,8 @@
 
 #include "mojo/public/bindings/lib/message_queue.h"
 #include "mojo/public/bindings/message.h"
-#include "mojo/public/environment/default_async_waiter.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/environment/default_async_waiter.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 class ErrorHandler;
diff --git a/mojo/public/bindings/lib/fixed_buffer.cc b/mojo/public/bindings/lib/fixed_buffer.cc
index 6b20dd1..09e3094 100644
--- a/mojo/public/bindings/lib/fixed_buffer.cc
+++ b/mojo/public/bindings/lib/fixed_buffer.cc
@@ -31,11 +31,10 @@
 
   delta = internal::Align(delta);
 
-  // TODO(darin): Using <assert.h> is probably not going to cut it.
-  assert(delta > 0);
-  assert(cursor_ + delta <= size_);
-  if (cursor_ + delta > size_)
+  if (delta == 0 || delta > size_ - cursor_) {
+    assert(false);
     return NULL;
+  }
 
   char* result = ptr_ + cursor_;
   cursor_ += delta;
diff --git a/mojo/public/bindings/lib/fixed_buffer.h b/mojo/public/bindings/lib/fixed_buffer.h
index 900c84e..7f25c0e 100644
--- a/mojo/public/bindings/lib/fixed_buffer.h
+++ b/mojo/public/bindings/lib/fixed_buffer.h
@@ -6,7 +6,7 @@
 #define MOJO_PUBLIC_BINDINGS_LIB_FIXED_BUFFER_H_
 
 #include "mojo/public/bindings/buffer.h"
-#include "mojo/public/system/macros.h"
+#include "mojo/public/cpp/system/macros.h"
 
 namespace mojo {
 namespace internal {
diff --git a/mojo/public/bindings/lib/message_queue.h b/mojo/public/bindings/lib/message_queue.h
index fe88db0..d1c535b 100644
--- a/mojo/public/bindings/lib/message_queue.h
+++ b/mojo/public/bindings/lib/message_queue.h
@@ -7,7 +7,7 @@
 
 #include <queue>
 
-#include "mojo/public/system/macros.h"
+#include "mojo/public/cpp/system/macros.h"
 
 namespace mojo {
 class Message;
diff --git a/mojo/public/bindings/lib/scratch_buffer.h b/mojo/public/bindings/lib/scratch_buffer.h
index 2ab933a..337375a 100644
--- a/mojo/public/bindings/lib/scratch_buffer.h
+++ b/mojo/public/bindings/lib/scratch_buffer.h
@@ -8,7 +8,7 @@
 #include <deque>
 
 #include "mojo/public/bindings/buffer.h"
-#include "mojo/public/system/macros.h"
+#include "mojo/public/cpp/system/macros.h"
 
 namespace mojo {
 namespace internal {
diff --git a/mojo/public/bindings/message.h b/mojo/public/bindings/message.h
index 435ba5d..90a9533 100644
--- a/mojo/public/bindings/message.h
+++ b/mojo/public/bindings/message.h
@@ -15,8 +15,8 @@
 
 // Message is a holder for the data and handles to be sent over a MessagePipe.
 // Message owns its data and handles, but a consumer of Message is free to
-// mutate the data and handles members. The message's data is comprised of a
-// header followed by payload.
+// mutate the data and handles. The message's data is comprised of a header
+// followed by payload.
 class Message {
  public:
   Message();
diff --git a/mojo/public/bindings/mojom_bindings_generator.gypi b/mojo/public/bindings/mojom_bindings_generator.gypi
index 35ecc8c..865defc 100644
--- a/mojo/public/bindings/mojom_bindings_generator.gypi
+++ b/mojo/public/bindings/mojom_bindings_generator.gypi
@@ -8,8 +8,10 @@
       'rule_name': 'Generate C++ source files from mojom files',
       'extension': 'mojom',
       'variables': {
-        'mojom_base_output_dir':
-            '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))',
+        # TODO(sky): uncomment this once gyp bug fixed and remove explicit
+        # setting everywhere
+        # 'mojom_base_output_dir':
+        #      '<!(python <(DEPTH)/build/inverse_depth.py <(DEPTH))',
         'mojom_bindings_generator':
             '<(DEPTH)/mojo/public/bindings/mojom_bindings_generator.py',
       },
@@ -60,7 +62,7 @@
         '-d', '<(DEPTH)',
         '-o', '<(SHARED_INTERMEDIATE_DIR)/<(mojom_base_output_dir)/<(RULE_INPUT_DIRNAME)',
       ],
-      'message': 'Generating C++ from <(RULE_INPUT_PATH)',
+      'message': 'Generating Mojo bindings from <(RULE_INPUT_PATH)',
       'process_outputs_as_sources': 1,
     }
   ],
diff --git a/mojo/public/bindings/mojom_bindings_generator.py b/mojo/public/bindings/mojom_bindings_generator.py
index 7c05a82..a9d8b68 100755
--- a/mojo/public/bindings/mojom_bindings_generator.py
+++ b/mojo/public/bindings/mojom_bindings_generator.py
@@ -16,6 +16,7 @@
 sys.path.insert(0, os.path.join(script_dir, "pylib"))
 
 from generate import mojom_data
+from parse import mojo_lexer
 from parse import mojo_parser
 from parse import mojo_translate
 
@@ -45,18 +46,40 @@
   return generators
 
 
-def ProcessFile(args, generator_modules, filename, processed_files):
-  # Ensure we only visit each file once.
+def _PrintImportStack(imported_filename_stack):
+  """Prints a chain of imports, given by imported_filename_stack."""
+  for i in reversed(xrange(0, len(imported_filename_stack)-1)):
+    print "  %s was imported by %s" % (imported_filename_stack[i+1],
+                                       imported_filename_stack[i])
+
+def ProcessFile(args, generator_modules, filename, processed_files={},
+                imported_filename_stack=[]):
+  # Memoized results.
   if filename in processed_files:
-    if processed_files[filename] is None:
-      raise Exception("Circular dependency: " + filename)
     return processed_files[filename]
-  processed_files[filename] = None
+
+  # Ensure we only visit each file once.
+  if filename in imported_filename_stack:
+    print "%s: Error: Circular dependency" % filename
+    _PrintImportStack(imported_filename_stack + [filename])
+    sys.exit(1)
+
+  try:
+    with open(filename) as f:
+      source = f.read()
+  except IOError as e:
+    print "%s: Error: %s" % (e.filename, e.strerror)
+    _PrintImportStack(imported_filename_stack + [filename])
+    sys.exit(1)
+
+  try:
+    tree = mojo_parser.Parse(source, filename)
+  except (mojo_lexer.LexError, mojo_parser.ParseError) as e:
+    print e
+    _PrintImportStack(imported_filename_stack + [filename])
+    sys.exit(1)
 
   dirname, name = os.path.split(filename)
-  # TODO(darin): There's clearly too many layers of translation here!  We can
-  # at least avoid generating the serialized Mojom IR.
-  tree = mojo_parser.Parse(filename)
   mojom = mojo_translate.Translate(tree, name)
   if args.debug_print_intermediate:
     pprint.PrettyPrinter().pprint(mojom)
@@ -66,7 +89,9 @@
   for import_data in mojom['imports']:
     import_filename = os.path.join(dirname, import_data['filename'])
     import_data['module'] = ProcessFile(
-        args, generator_modules, import_filename, processed_files)
+        args, generator_modules, import_filename,
+        processed_files=processed_files,
+        imported_filename_stack=imported_filename_stack + [filename])
 
   module = mojom_data.OrderedModuleFromData(mojom)
 
@@ -81,6 +106,7 @@
     generator = generator_module.Generator(module, args.output_dir)
     generator.GenerateFiles()
 
+  # Save result.
   processed_files[filename] = module
   return module
 
@@ -107,7 +133,7 @@
     os.makedirs(args.output_dir)
 
   for filename in args.filename:
-    ProcessFile(args, generator_modules, filename, {})
+    ProcessFile(args, generator_modules, filename)
 
   return 0
 
diff --git a/mojo/public/bindings/passable.h b/mojo/public/bindings/passable.h
index 6fbd38e..579dcaf 100644
--- a/mojo/public/bindings/passable.h
+++ b/mojo/public/bindings/passable.h
@@ -6,7 +6,7 @@
 #define MOJO_PUBLIC_BINDINGS_PASSABLE_H_
 
 #include "mojo/public/bindings/lib/bindings_internal.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 
diff --git a/mojo/public/bindings/pylib/generate/mojom_generator.py b/mojo/public/bindings/pylib/generate/mojom_generator.py
index ebe2ea9..131c248 100644
--- a/mojo/public/bindings/pylib/generate/mojom_generator.py
+++ b/mojo/public/bindings/pylib/generate/mojom_generator.py
@@ -81,6 +81,8 @@
     for interface in self.module.interfaces:
       for method in interface.methods:
         result.append(GetStructFromMethod(interface, method))
+        if method.response_parameters != None:
+          result.append(GetResponseStructFromMethod(interface, method))
     return map(partial(GetStructInfo, False), result)
 
   def GetStructs(self):
diff --git a/mojo/public/bindings/pylib/parse/mojo_lexer.py b/mojo/public/bindings/pylib/parse/mojo_lexer.py
index 7a0fd0d..d0cbd6a 100644
--- a/mojo/public/bindings/pylib/parse/mojo_lexer.py
+++ b/mojo/public/bindings/pylib/parse/mojo_lexer.py
@@ -14,22 +14,38 @@
   from ply.lex import TOKEN
 except ImportError:
   module_path, module_name = os.path.split(__file__)
-  third_party = os.path.join(
-      module_path, os.pardir, os.pardir, os.pardir, os.pardir, 'third_party')
+  third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir,
+                             os.pardir, os.pardir, 'third_party')
   sys.path.append(third_party)
   # pylint: disable=F0401
   from ply.lex import TOKEN
 
 
+class LexError(Exception):
+  def __init__(self, filename, lineno, msg):
+    self.filename = filename
+    self.lineno = lineno
+    self.msg = msg
+
+  def __str__(self):
+    return "%s:%d: Error: %s" % (self.filename, self.lineno, self.msg)
+
+  def __repr__(self):
+    return str(self)
+
+
 class Lexer(object):
+
+  def __init__(self, filename):
+    self.filename = filename
+
   ######################--   PRIVATE   --######################
 
   ##
   ## Internal auxiliary methods
   ##
   def _error(self, msg, token):
-    print('%s at line %d' % (msg, token.lineno))
-    self.lexer.skip(1)
+    raise LexError(self.filename, token.lineno, msg)
 
   ##
   ## Reserved keywords
@@ -58,44 +74,37 @@
     # Identifiers
     'NAME',
 
-    # constants
+    # Constants
     'ORDINAL',
     'INT_CONST_DEC', 'INT_CONST_OCT', 'INT_CONST_HEX',
     'FLOAT_CONST', 'HEX_FLOAT_CONST',
     'CHAR_CONST',
-    'WCHAR_CONST',
 
     # String literals
     'STRING_LITERAL',
-    'WSTRING_LITERAL',
 
     # Operators
     'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'MOD',
     'OR', 'AND', 'NOT', 'XOR', 'LSHIFT', 'RSHIFT',
-    'LOR', 'LAND', 'LNOT',
-    'LT', 'LE', 'GT', 'GE', 'EQ', 'NE',
 
     # Assignment
     'EQUALS',
 
-    # Conditional operator (?)
-    'CONDOP',
-
     # Request / response
     'RESPONSE',
 
-    # Delimeters
+    # Delimiters
     'LPAREN', 'RPAREN',         # ( )
     'LBRACKET', 'RBRACKET',     # [ ]
     'LBRACE', 'RBRACE',         # { }
-    'SEMI', 'COLON',            # ; :
+    'LANGLE', 'RANGLE',         # < >
+    'SEMI',                     # ;
     'COMMA', 'DOT'              # , .
   )
 
   ##
   ## Regexes for use in tokens
   ##
-  ##
 
   # valid C identifiers (K&R2: A.2.3), plus '$' (supported by some compilers)
   identifier = r'[a-zA-Z_$][0-9a-zA-Z_$]*'
@@ -129,7 +138,6 @@
       r"""(\\("""+simple_escape+'|'+decimal_escape+'|'+hex_escape+'))'
   cconst_char = r"""([^'\\\n]|"""+escape_sequence+')'
   char_const = "'"+cconst_char+"'"
-  wchar_const = 'L'+char_const
   unmatched_quote = "('"+cconst_char+"*\\n)|('"+cconst_char+"*$)"
   bad_char_const = \
       r"""('"""+cconst_char+"""[^'\n]+')|('')|('"""+ \
@@ -138,7 +146,6 @@
   # string literals (K&R2: A.2.6)
   string_char = r"""([^"\\\n]|"""+escape_sequence+')'
   string_literal = '"'+string_char+'*"'
-  wstring_literal = 'L'+string_literal
   bad_string_literal = '"'+string_char+'*'+bad_escape+string_char+'*"'
 
   # floating constants (K&R2: A.2.5.3)
@@ -154,10 +161,17 @@
       '('+hex_prefix+'('+hex_digits+'|'+hex_fractional_constant+')'+ \
       binary_exponent_part+'[FfLl]?)'
 
+  # Ordinals
+  ordinal = r'@[0-9]+'
+  missing_ordinal_value = r'@'
+  # Don't allow ordinal values in octal (even invalid octal, like 09) or
+  # hexadecimal.
+  octal_or_hex_ordinal_disallowed = r'@((0[0-9]+)|('+hex_prefix+hex_digits+'))'
+
   ##
   ## Rules for the normal state
   ##
-  t_ignore = ' \t'
+  t_ignore = ' \t\r'
 
   # Newlines
   def t_NEWLINE(self, t):
@@ -176,39 +190,27 @@
   t_XOR               = r'\^'
   t_LSHIFT            = r'<<'
   t_RSHIFT            = r'>>'
-  t_LOR               = r'\|\|'
-  t_LAND              = r'&&'
-  t_LNOT              = r'!'
-  t_LT                = r'<'
-  t_GT                = r'>'
-  t_LE                = r'<='
-  t_GE                = r'>='
-  t_EQ                = r'=='
-  t_NE                = r'!='
 
   # =
   t_EQUALS            = r'='
 
-  # ?
-  t_CONDOP            = r'\?'
-
   # =>
   t_RESPONSE          = r'=>'
 
-  # Delimeters
+  # Delimiters
   t_LPAREN            = r'\('
   t_RPAREN            = r'\)'
   t_LBRACKET          = r'\['
   t_RBRACKET          = r'\]'
   t_LBRACE            = r'\{'
   t_RBRACE            = r'\}'
+  t_LANGLE            = r'<'
+  t_RANGLE            = r'>'
   t_COMMA             = r','
-  t_DOT               = r'.'
+  t_DOT               = r'\.'
   t_SEMI              = r';'
-  t_COLON             = r':'
 
   t_STRING_LITERAL    = string_literal
-  t_ORDINAL           = r'@[0-9]*'
 
   # The following floating and integer constants are defined as
   # functions to impose a strict order (otherwise, decimal
@@ -247,10 +249,6 @@
   def t_CHAR_CONST(self, t):
     return t
 
-  @TOKEN(wchar_const)
-  def t_WCHAR_CONST(self, t):
-    return t
-
   @TOKEN(unmatched_quote)
   def t_UNMATCHED_QUOTE(self, t):
     msg = "Unmatched '"
@@ -261,10 +259,6 @@
     msg = "Invalid char constant %s" % t.value
     self._error(msg, t)
 
-  @TOKEN(wstring_literal)
-  def t_WSTRING_LITERAL(self, t):
-    return t
-
   # unmatched string literals are caught by the preprocessor
 
   @TOKEN(bad_string_literal)
@@ -272,6 +266,21 @@
     msg = "String contains invalid escape code"
     self._error(msg, t)
 
+  # Handle ordinal-related tokens in the right order:
+  @TOKEN(octal_or_hex_ordinal_disallowed)
+  def t_OCTAL_OR_HEX_ORDINAL_DISALLOWED(self, t):
+    msg = "Octal and hexadecimal ordinal values not allowed"
+    self._error(msg, t)
+
+  @TOKEN(ordinal)
+  def t_ORDINAL(self, t):
+    return t
+
+  @TOKEN(missing_ordinal_value)
+  def t_BAD_ORDINAL(self, t):
+    msg = "Missing ordinal value"
+    self._error(msg, t)
+
   @TOKEN(identifier)
   def t_NAME(self, t):
     t.type = self.keyword_map.get(t.value, "NAME")
diff --git a/mojo/public/bindings/pylib/parse/mojo_parser.py b/mojo/public/bindings/pylib/parse/mojo_parser.py
index 1104048..3cf080a 100755
--- a/mojo/public/bindings/pylib/parse/mojo_parser.py
+++ b/mojo/public/bindings/pylib/parse/mojo_parser.py
@@ -28,8 +28,9 @@
 from mojo_lexer import Lexer
 
 
-def ListFromConcat(*items):
-  """Generate list by concatenating inputs"""
+def _ListFromConcat(*items):
+  """Generate list by concatenating inputs (note: only concatenates lists, not
+  tuples or other iterables)."""
   itemsout = []
   for item in items:
     if item is None:
@@ -38,20 +39,40 @@
       itemsout.append(item)
     else:
       itemsout.extend(item)
-
   return itemsout
 
 
+class ParseError(Exception):
+
+  def __init__(self, filename, lineno=None, snippet=None, bad_char=None,
+               eof=False):
+    self.filename = filename
+    self.lineno = lineno
+    self.snippet = snippet
+    self.bad_char = bad_char
+    self.eof = eof
+
+  def __str__(self):
+    return "%s: Error: Unexpected end of file" % self.filename if self.eof \
+        else "%s:%d: Error: Unexpected %r:\n%s" % (
+            self.filename, self.lineno + 1, self.bad_char, self.snippet)
+
+  def __repr__(self):
+    return str(self)
+
+
 class Parser(object):
 
-  def __init__(self, lexer):
+  def __init__(self, lexer, source, filename):
     self.tokens = lexer.tokens
+    self.source = source
+    self.filename = filename
 
   def p_root(self, p):
     """root : import root
             | module"""
     if len(p) > 2:
-      p[0] = ListFromConcat(p[1], p[2])
+      p[0] = _ListFromConcat(p[1], p[2])
     else:
       p[0] = [p[1]]
 
@@ -68,7 +89,7 @@
     """definitions : definition definitions
                    | """
     if len(p) > 1:
-      p[0] = ListFromConcat(p[1], p[2])
+      p[0] = _ListFromConcat(p[1], p[2])
 
   def p_definition(self, p):
     """definition : struct
@@ -87,9 +108,9 @@
                   | attribute COMMA attributes
                   | """
     if len(p) == 2:
-      p[0] = ListFromConcat(p[1])
+      p[0] = _ListFromConcat(p[1])
     elif len(p) > 3:
-      p[0] = ListFromConcat(p[1], p[3])
+      p[0] = _ListFromConcat(p[1], p[3])
 
   def p_attribute(self, p):
     """attribute : NAME EQUALS expression
@@ -105,7 +126,7 @@
                    | enum struct_body
                    | """
     if len(p) > 1:
-      p[0] = ListFromConcat(p[1], p[2])
+      p[0] = _ListFromConcat(p[1], p[2])
 
   def p_field(self, p):
     """field : typename NAME default ordinal SEMI"""
@@ -128,7 +149,7 @@
                       | enum interface_body
                       | """
     if len(p) > 1:
-      p[0] = ListFromConcat(p[1], p[2])
+      p[0] = _ListFromConcat(p[1], p[2])
 
   def p_response(self, p):
     """response : RESPONSE LPAREN parameters RPAREN
@@ -147,9 +168,9 @@
     if len(p) == 1:
       p[0] = []
     elif len(p) == 2:
-      p[0] = ListFromConcat(p[1])
+      p[0] = _ListFromConcat(p[1])
     elif len(p) > 3:
-      p[0] = ListFromConcat(p[1], p[3])
+      p[0] = _ListFromConcat(p[1], p[3])
 
   def p_parameter(self, p):
     """parameter : typename NAME ordinal"""
@@ -167,7 +188,7 @@
     p[0] = p[1]
 
   def p_specializedhandle(self, p):
-    """specializedhandle : HANDLE LT specializedhandlename GT"""
+    """specializedhandle : HANDLE LANGLE specializedhandlename RANGLE"""
     p[0] = "handle<" + p[3] + ">"
 
   def p_specializedhandlename(self, p):
@@ -195,9 +216,9 @@
                    | enum_field COMMA enum_fields
                    | """
     if len(p) == 2:
-      p[0] = ListFromConcat(p[1])
+      p[0] = _ListFromConcat(p[1])
     elif len(p) > 3:
-      p[0] = ListFromConcat(p[1], p[3])
+      p[0] = _ListFromConcat(p[1], p[3])
 
   def p_enum_field(self, p):
     """enum_field : NAME
@@ -222,9 +243,9 @@
                                   | expression_object COMMA expression_object_elements
                                   | """
     if len(p) == 2:
-      p[0] = ListFromConcat(p[1])
+      p[0] = _ListFromConcat(p[1])
     elif len(p) > 3:
-      p[0] = ListFromConcat(p[1], p[3])
+      p[0] = _ListFromConcat(p[1], p[3])
 
   def p_expression_array(self, p):
     """expression_array : expression
@@ -239,29 +260,23 @@
                                  | expression_object COMMA expression_array_elements
                                  | """
     if len(p) == 2:
-      p[0] = ListFromConcat(p[1])
+      p[0] = _ListFromConcat(p[1])
     elif len(p) > 3:
-      p[0] = ListFromConcat(p[1], p[3])
+      p[0] = _ListFromConcat(p[1], p[3])
 
+  # TODO(vtl): This is now largely redundant.
   def p_expression(self, p):
-    """expression : conditional_expression"""
+    """expression : binary_expression"""
     p[0] = ('EXPRESSION', p[1])
 
-  def p_conditional_expression(self, p):
-    """conditional_expression : binary_expression
-                              | binary_expression CONDOP expression COLON \
-                                    conditional_expression"""
-    # Just pass the arguments through. I don't think it's possible to preserve
-    # the spaces of the original, so just put a single space between them.
-    p[0] = ListFromConcat(*p[1:])
-
   # PLY lets us specify precedence of operators, but since we don't actually
   # evaluate them, we don't need that here.
+  # TODO(vtl): We're going to need to evaluate them.
   def p_binary_expression(self, p):
     """binary_expression : unary_expression
                          | binary_expression binary_operator \
                                binary_expression"""
-    p[0] = ListFromConcat(*p[1:])
+    p[0] = _ListFromConcat(*p[1:])
 
   def p_binary_operator(self, p):
     """binary_operator : TIMES
@@ -271,36 +286,27 @@
                        | MINUS
                        | RSHIFT
                        | LSHIFT
-                       | LT
-                       | LE
-                       | GE
-                       | GT
-                       | EQ
-                       | NE
                        | AND
                        | OR
-                       | XOR
-                       | LAND
-                       | LOR"""
+                       | XOR"""
     p[0] = p[1]
 
   def p_unary_expression(self, p):
     """unary_expression : primary_expression
                         | unary_operator expression"""
-    p[0] = ListFromConcat(*p[1:])
+    p[0] = _ListFromConcat(*p[1:])
 
   def p_unary_operator(self, p):
     """unary_operator : PLUS
                       | MINUS
-                      | NOT
-                      | LNOT"""
+                      | NOT"""
     p[0] = p[1]
 
   def p_primary_expression(self, p):
     """primary_expression : constant
                           | identifier
                           | LPAREN expression RPAREN"""
-    p[0] = ListFromConcat(*p[1:])
+    p[0] = _ListFromConcat(*p[1:])
 
   def p_identifier(self, p):
     """identifier : NAME
@@ -314,33 +320,48 @@
                 | FLOAT_CONST
                 | HEX_FLOAT_CONST
                 | CHAR_CONST
-                | WCHAR_CONST
-                | STRING_LITERAL
-                | WSTRING_LITERAL"""
-    p[0] = ListFromConcat(*p[1:])
+                | STRING_LITERAL"""
+    p[0] = _ListFromConcat(*p[1:])
 
   def p_error(self, e):
-    print('error: %s'%e)
+    if e is None:
+      # Unexpected EOF.
+      # TODO(vtl): Can we figure out what's missing?
+      raise ParseError(self.filename, eof=True)
+
+    lineno = e.lineno + 1
+    snippet = self.source.split('\n')[lineno]
+    raise ParseError(self.filename, lineno=lineno, snippet=snippet,
+                     bad_char=e.value)
 
 
-def Parse(filename):
-  lexer = Lexer()
-  parser = Parser(lexer)
+def Parse(source, filename):
+  lexer = Lexer(filename)
+  parser = Parser(lexer, source, filename)
 
   lex.lex(object=lexer)
   yacc.yacc(module=parser, debug=0, write_tables=0)
 
-  tree = yacc.parse(open(filename).read())
+  tree = yacc.parse(source)
   return tree
 
 
-def Main():
-  if len(sys.argv) < 2:
-    print("usage: %s filename" % (sys.argv[0]))
-    sys.exit(1)
-  tree = Parse(filename=sys.argv[1])
-  print(tree)
+def main(argv):
+  if len(argv) < 2:
+    print "usage: %s filename" % argv[0]
+    return 0
+
+  for filename in argv[1:]:
+    with open(filename) as f:
+      print "%s:" % filename
+      try:
+        print Parse(f.read(), filename)
+      except ParseError, e:
+        print e
+        return 1
+
+  return 0
 
 
 if __name__ == '__main__':
-  Main()
+  sys.exit(main(sys.argv))
diff --git a/mojo/public/bindings/pylib/parse/mojo_parser_unittest.py b/mojo/public/bindings/pylib/parse/mojo_parser_unittest.py
new file mode 100644
index 0000000..d9d8c0c
--- /dev/null
+++ b/mojo/public/bindings/pylib/parse/mojo_parser_unittest.py
@@ -0,0 +1,230 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import mojo_lexer
+import mojo_parser
+import unittest
+
+
+class MojoParserTest(unittest.TestCase):
+  """Tests mojo_parser (in particular, Parse())."""
+
+  def testTrivialValidSource(self):
+    """Tests a trivial, but valid, .mojom source."""
+    source = """\
+// This is a comment.
+
+module my_module {
+}
+"""
+    self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"),
+                      [("MODULE", "my_module", None)])
+
+  def testSourceWithCrLfs(self):
+    """Tests a .mojom source with CR-LFs instead of LFs."""
+    source = "// This is a comment.\r\n\r\nmodule my_module {\r\n}\r\n";
+    self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"),
+                      [("MODULE", "my_module", None)])
+
+  def testUnexpectedEOF(self):
+    """Tests a "truncated" .mojom source."""
+    source = """\
+// This is a comment.
+
+module my_module {
+"""
+    with self.assertRaisesRegexp(
+        mojo_parser.ParseError,
+        r"^my_file\.mojom: Error: Unexpected end of file$"):
+      mojo_parser.Parse(source, "my_file.mojom")
+
+  def testSimpleStruct(self):
+    """Tests a simple .mojom source that just defines a struct."""
+    source ="""\
+module my_module {
+
+struct MyStruct {
+  int32 a;
+  double b;
+};
+
+}  // module my_module
+"""
+    # Note: Output as pretty-printed on failure by the test harness.
+    expected = \
+[('MODULE',
+  'my_module',
+  [('STRUCT',
+    'MyStruct',
+    None,
+    [('FIELD', 'int32', 'a', None, None),
+     ('FIELD', 'double', 'b', None, None)])])]
+    self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected)
+
+  def testEnumExpressions(self):
+    """Tests an enum with values calculated using simple expressions."""
+    source = """\
+module my_module {
+
+enum MyEnum {
+  MY_ENUM_1 = 1,
+  MY_ENUM_2 = 1 + 1,
+  MY_ENUM_3 = 1 * 3,
+  MY_ENUM_4 = 2 * (1 + 1),
+  MY_ENUM_5 = 1 + 2 * 2,
+  MY_ENUM_6 = -6 / -2,
+  MY_ENUM_7 = 3 | (1 << 2),
+  MY_ENUM_8 = 16 >> 1,
+  MY_ENUM_9 = 1 ^ 15 & 8,
+  MY_ENUM_10 = 110 % 100,
+  MY_ENUM_MINUS_1 = ~0
+};
+
+}  // my_module
+"""
+    expected = \
+[('MODULE',
+  'my_module',
+  [('ENUM',
+    'MyEnum',
+    [('ENUM_FIELD', 'MY_ENUM_1', ('EXPRESSION', ['1'])),
+     ('ENUM_FIELD', 'MY_ENUM_2', ('EXPRESSION', ['1', '+', '1'])),
+     ('ENUM_FIELD', 'MY_ENUM_3', ('EXPRESSION', ['1', '*', '3'])),
+     ('ENUM_FIELD',
+      'MY_ENUM_4',
+      ('EXPRESSION',
+       ['2', '*', '(', ('EXPRESSION', ['1', '+', '1']), ')'])),
+     ('ENUM_FIELD',
+      'MY_ENUM_5',
+      ('EXPRESSION', ['1', '+', '2', '*', '2'])),
+     ('ENUM_FIELD',
+      'MY_ENUM_6',
+      ('EXPRESSION',
+       ['-', ('EXPRESSION', ['6', '/', '-', ('EXPRESSION', ['2'])])])),
+     ('ENUM_FIELD',
+      'MY_ENUM_7',
+      ('EXPRESSION',
+       ['3', '|', '(', ('EXPRESSION', ['1', '<<', '2']), ')'])),
+     ('ENUM_FIELD', 'MY_ENUM_8', ('EXPRESSION', ['16', '>>', '1'])),
+     ('ENUM_FIELD',
+      'MY_ENUM_9',
+      ('EXPRESSION', ['1', '^', '15', '&', '8'])),
+     ('ENUM_FIELD', 'MY_ENUM_10', ('EXPRESSION', ['110', '%', '100'])),
+     ('ENUM_FIELD',
+      'MY_ENUM_MINUS_1',
+      ('EXPRESSION', ['~', ('EXPRESSION', ['0'])]))])])]
+    self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected)
+
+  def testNoConditionals(self):
+    """Tests that ?: is not allowed."""
+    source = """\
+module my_module {
+
+enum MyEnum {
+  MY_ENUM_1 = 1 ? 2 : 3
+};
+
+}  // my_module
+"""
+    with self.assertRaisesRegexp(
+        mojo_lexer.LexError,
+        r"^my_file\.mojom:4: Error: Illegal character '\?'$"):
+      mojo_parser.Parse(source, "my_file.mojom")
+
+  def testSimpleOrdinals(self):
+    """Tests that (valid) ordinal values are scanned correctly."""
+    source = """\
+module my_module {
+
+// This isn't actually valid .mojom, but the problem (missing ordinals) should
+// be handled at a different level.
+struct MyStruct {
+  int32 a0 @0;
+  int32 a1 @1;
+  int32 a2 @2;
+  int32 a9 @9;
+  int32 a10 @10;
+  int32 a11 @11;
+  int32 a29 @29;
+  int32 a1234567890 @1234567890;
+};
+
+}  // module my_module
+"""
+    expected = \
+[('MODULE',
+  'my_module',
+  [('STRUCT',
+    'MyStruct',
+    None,
+    [('FIELD', 'int32', 'a0', '@0', None),
+     ('FIELD', 'int32', 'a1', '@1', None),
+     ('FIELD', 'int32', 'a2', '@2', None),
+     ('FIELD', 'int32', 'a9', '@9', None),
+     ('FIELD', 'int32', 'a10', '@10', None),
+     ('FIELD', 'int32', 'a11', '@11', None),
+     ('FIELD', 'int32', 'a29', '@29', None),
+     ('FIELD', 'int32', 'a1234567890', '@1234567890', None)])])]
+    self.assertEquals(mojo_parser.Parse(source, "my_file.mojom"), expected)
+
+  def testInvalidOrdinals(self):
+    """Tests that (lexically) invalid ordinals are correctly detected."""
+    source1 = """\
+module my_module {
+
+struct MyStruct {
+  int32 a_missing @;
+};
+
+}  // module my_module
+"""
+    with self.assertRaisesRegexp(
+        mojo_lexer.LexError,
+        r"^my_file\.mojom:4: Error: Missing ordinal value$"):
+      mojo_parser.Parse(source1, "my_file.mojom")
+
+    source2 = """\
+module my_module {
+
+struct MyStruct {
+  int32 a_octal @01;
+};
+
+}  // module my_module
+"""
+    with self.assertRaisesRegexp(
+        mojo_lexer.LexError,
+        r"^my_file\.mojom:4: Error: "
+            r"Octal and hexadecimal ordinal values not allowed$"):
+      mojo_parser.Parse(source2, "my_file.mojom")
+
+    source3 = """\
+module my_module { struct MyStruct { int32 a_invalid_octal @08; }; }
+"""
+    with self.assertRaisesRegexp(
+        mojo_lexer.LexError,
+        r"^my_file\.mojom:1: Error: "
+            r"Octal and hexadecimal ordinal values not allowed$"):
+      mojo_parser.Parse(source3, "my_file.mojom")
+
+    source4 = """\
+module my_module { struct MyStruct { int32 a_hex @0x1aB9; }; }
+"""
+    with self.assertRaisesRegexp(
+        mojo_lexer.LexError,
+        r"^my_file\.mojom:1: Error: "
+            r"Octal and hexadecimal ordinal values not allowed$"):
+      mojo_parser.Parse(source4, "my_file.mojom")
+
+    source5 = """\
+module my_module { struct MyStruct { int32 a_hex @0X0; }; }
+"""
+    with self.assertRaisesRegexp(
+        mojo_lexer.LexError,
+        r"^my_file\.mojom:1: Error: "
+            r"Octal and hexadecimal ordinal values not allowed$"):
+      mojo_parser.Parse(source5, "my_file.mojom")
+
+if __name__ == "__main__":
+  unittest.main()
diff --git a/mojo/public/bindings/remote_ptr.h b/mojo/public/bindings/remote_ptr.h
index efb4314..4e1ef25 100644
--- a/mojo/public/bindings/remote_ptr.h
+++ b/mojo/public/bindings/remote_ptr.h
@@ -9,7 +9,7 @@
 
 #include "mojo/public/bindings/interface.h"
 #include "mojo/public/bindings/lib/router.h"
-#include "mojo/public/system/macros.h"
+#include "mojo/public/cpp/system/macros.h"
 
 namespace mojo {
 
@@ -76,7 +76,7 @@
  public:
   RemotePtr() : state_(NULL) {}
   explicit RemotePtr(typename Interface<S>::ScopedHandle interface_handle,
-                     typename S::_Peer* peer = NULL,
+                     typename S::_Peer* peer,
                      ErrorHandler* error_handler = NULL,
                      MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter())
       : state_(new State(ScopedMessagePipeHandle(interface_handle.Pass()), peer,
@@ -113,7 +113,7 @@
   }
 
   void reset(typename Interface<S>::ScopedHandle interface_handle,
-             typename S::_Peer* peer = NULL,
+             typename S::_Peer* peer,
              ErrorHandler* error_handler = NULL,
              MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter()) {
     delete state_;
diff --git a/mojo/public/bindings/sync_dispatcher.h b/mojo/public/bindings/sync_dispatcher.h
index 096ffbd..1117e9d 100644
--- a/mojo/public/bindings/sync_dispatcher.h
+++ b/mojo/public/bindings/sync_dispatcher.h
@@ -5,7 +5,7 @@
 #ifndef MOJO_PUBLIC_BINDINGS_SYNC_DISPATCHER_H_
 #define MOJO_PUBLIC_BINDINGS_SYNC_DISPATCHER_H_
 
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 
diff --git a/mojo/public/bindings/tests/array_unittest.cc b/mojo/public/bindings/tests/array_unittest.cc
index 2df6ed7..bce99d9 100644
--- a/mojo/public/bindings/tests/array_unittest.cc
+++ b/mojo/public/bindings/tests/array_unittest.cc
@@ -6,7 +6,7 @@
 #include "mojo/public/bindings/array.h"
 #include "mojo/public/bindings/lib/fixed_buffer.h"
 #include "mojo/public/bindings/lib/scratch_buffer.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
diff --git a/mojo/public/bindings/tests/buffer_unittest.cc b/mojo/public/bindings/tests/buffer_unittest.cc
index b7d4e15..c8d2f21 100644
--- a/mojo/public/bindings/tests/buffer_unittest.cc
+++ b/mojo/public/bindings/tests/buffer_unittest.cc
@@ -2,11 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <limits>
+
 #include "mojo/public/bindings/buffer.h"
 #include "mojo/public/bindings/lib/bindings_serialization.h"
 #include "mojo/public/bindings/lib/fixed_buffer.h"
 #include "mojo/public/bindings/lib/scratch_buffer.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
@@ -111,6 +113,24 @@
   free(buf_ptr);
 }
 
+#ifdef NDEBUG
+TEST(FixedBufferTest, TooBig) {
+  Environment env;
+
+  internal::FixedBuffer buf(24);
+
+  // A little bit too large.
+  EXPECT_EQ(reinterpret_cast<void*>(0), buf.Allocate(32));
+
+  // Move the cursor forward.
+  EXPECT_NE(reinterpret_cast<void*>(0), buf.Allocate(16));
+
+  // A lot too large, leading to possible integer overflow.
+  EXPECT_EQ(reinterpret_cast<void*>(0),
+            buf.Allocate(std::numeric_limits<size_t>::max() - 8u));
+}
+#endif
+
 }  // namespace
 }  // namespace test
 }  // namespace mojo
diff --git a/mojo/public/bindings/tests/connector_unittest.cc b/mojo/public/bindings/tests/connector_unittest.cc
index b08a17f..94eb951 100644
--- a/mojo/public/bindings/tests/connector_unittest.cc
+++ b/mojo/public/bindings/tests/connector_unittest.cc
@@ -8,9 +8,9 @@
 #include "mojo/public/bindings/lib/connector.h"
 #include "mojo/public/bindings/lib/message_builder.h"
 #include "mojo/public/bindings/lib/message_queue.h"
-#include "mojo/public/environment/environment.h"
-#include "mojo/public/system/macros.h"
-#include "mojo/public/utility/run_loop.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/cpp/utility/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
diff --git a/mojo/public/bindings/tests/handle_passing_unittest.cc b/mojo/public/bindings/tests/handle_passing_unittest.cc
index 93ac875..5467996 100644
--- a/mojo/public/bindings/tests/handle_passing_unittest.cc
+++ b/mojo/public/bindings/tests/handle_passing_unittest.cc
@@ -5,9 +5,9 @@
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/remote_ptr.h"
 #include "mojo/public/bindings/tests/sample_factory.mojom.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/utility/run_loop.h"
 #include "mojo/public/tests/test_utils.h"
-#include "mojo/public/utility/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
diff --git a/mojo/public/bindings/tests/remote_ptr_unittest.cc b/mojo/public/bindings/tests/remote_ptr_unittest.cc
index 5d0cbf1..1f786a0 100644
--- a/mojo/public/bindings/tests/remote_ptr_unittest.cc
+++ b/mojo/public/bindings/tests/remote_ptr_unittest.cc
@@ -6,8 +6,8 @@
 #include "mojo/public/bindings/remote_ptr.h"
 #include "mojo/public/bindings/tests/math_calculator.mojom.h"
 #include "mojo/public/bindings/tests/sample_service.mojom.h"
-#include "mojo/public/environment/environment.h"
-#include "mojo/public/utility/run_loop.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/utility/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
@@ -222,7 +222,7 @@
   // This is a test to ensure the following compiles. The sample::Port interface
   // does not have an explicit Peer attribute.
   InterfacePipe<sample::Port, NoInterface> pipe;
-  RemotePtr<sample::Port> port(pipe.handle_to_self.Pass());
+  RemotePtr<sample::Port> port(pipe.handle_to_self.Pass(), NULL);
 }
 
 }  // namespace
diff --git a/mojo/public/bindings/tests/request_response_unittest.cc b/mojo/public/bindings/tests/request_response_unittest.cc
index 8db998b..f7d2346 100644
--- a/mojo/public/bindings/tests/request_response_unittest.cc
+++ b/mojo/public/bindings/tests/request_response_unittest.cc
@@ -6,9 +6,9 @@
 #include "mojo/public/bindings/remote_ptr.h"
 #include "mojo/public/bindings/tests/sample_import.mojom.h"
 #include "mojo/public/bindings/tests/sample_interfaces.mojom.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/utility/run_loop.h"
 #include "mojo/public/tests/test_utils.h"
-#include "mojo/public/utility/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
@@ -86,7 +86,7 @@
 TEST_F(RequestResponseTest, EchoString) {
   InterfacePipe<sample::Provider> pipe;
   ProviderImpl provider_impl(pipe.handle_to_peer.Pass());
-  RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass());
+  RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL);
 
   std::string buf;
   {
@@ -102,7 +102,7 @@
 TEST_F(RequestResponseTest, EchoStrings) {
   InterfacePipe<sample::Provider> pipe;
   ProviderImpl provider_impl(pipe.handle_to_peer.Pass());
-  RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass());
+  RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL);
 
   std::string buf;
   {
@@ -118,7 +118,7 @@
 TEST_F(RequestResponseTest, EchoMessagePipeHandle) {
   InterfacePipe<sample::Provider> pipe;
   ProviderImpl provider_impl(pipe.handle_to_peer.Pass());
-  RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass());
+  RemotePtr<sample::Provider> provider(pipe.handle_to_self.Pass(), NULL);
 
   MessagePipe pipe2;
   {
diff --git a/mojo/public/bindings/tests/router_unittest.cc b/mojo/public/bindings/tests/router_unittest.cc
index 92f5fa7..b86ede6 100644
--- a/mojo/public/bindings/tests/router_unittest.cc
+++ b/mojo/public/bindings/tests/router_unittest.cc
@@ -8,9 +8,9 @@
 #include "mojo/public/bindings/lib/message_builder.h"
 #include "mojo/public/bindings/lib/message_queue.h"
 #include "mojo/public/bindings/lib/router.h"
-#include "mojo/public/environment/environment.h"
-#include "mojo/public/system/macros.h"
-#include "mojo/public/utility/run_loop.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/cpp/utility/run_loop.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
diff --git a/mojo/public/bindings/tests/sample_interfaces.mojom b/mojo/public/bindings/tests/sample_interfaces.mojom
index 93c334d..50e2c60 100644
--- a/mojo/public/bindings/tests/sample_interfaces.mojom
+++ b/mojo/public/bindings/tests/sample_interfaces.mojom
@@ -4,20 +4,11 @@
 
 module sample {
 
-struct Coord {
-  int32 x;
-  int32 y;
-};
-
 [Peer=ProviderClient]
 interface Provider {
   EchoString(string a) => (string a);
   EchoStrings(string a, string b) => (string a, string b);
   EchoMessagePipeHandle(handle<message_pipe> a) => (handle<message_pipe> a);
-  //EchoVoid() => ();
-  //MakeCoord(int32 x, int32 y) => (Coord coord);
-  //Make2Coords(int32 x1, int32 y1, int32 x2, int32 y2) =>
-  //    (Coord coord1, Coord coord2);
 };
 
 [Peer=Provider]
diff --git a/mojo/public/bindings/tests/sample_service_unittest.cc b/mojo/public/bindings/tests/sample_service_unittest.cc
index c568bb4..72400fd 100644
--- a/mojo/public/bindings/tests/sample_service_unittest.cc
+++ b/mojo/public/bindings/tests/sample_service_unittest.cc
@@ -8,7 +8,7 @@
 
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/tests/sample_service.mojom.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
diff --git a/mojo/public/bindings/tests/type_conversion_unittest.cc b/mojo/public/bindings/tests/type_conversion_unittest.cc
index 81202e0..950199c 100644
--- a/mojo/public/bindings/tests/type_conversion_unittest.cc
+++ b/mojo/public/bindings/tests/type_conversion_unittest.cc
@@ -4,7 +4,7 @@
 
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/tests/test_structs.mojom.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
diff --git a/mojo/public/bindings/type_converter.h b/mojo/public/bindings/type_converter.h
index d89ddf6..e4bf920 100644
--- a/mojo/public/bindings/type_converter.h
+++ b/mojo/public/bindings/type_converter.h
@@ -7,7 +7,57 @@
 
 namespace mojo {
 
-// Specialize to perform type conversion.
+// Specialize to perform type conversion for Mojom-defined structs and arrays.
+// Here, T is the Mojom-defined struct or array, and U is some other non-Mojom
+// struct or array type.
+//
+// EXAMPLE:
+//
+// Suppose you have the following Mojom-defined struct:
+//
+//   module geometry {
+//   struct Point {
+//     int32 x;
+//     int32 y;
+//   };
+//   }
+//
+// Now, imagine you wanted to write a TypeConverter specialization for
+// gfx::Point. It might look like this:
+//
+//   namespace mojo {
+//   template <>
+//   class TypeConverter<geometry::Point, gfx::Point> {
+//    public:
+//     static geometry::Point ConvertFrom(const gfx::Point& input,
+//                                        Buffer* buf) {
+//       geometry::Point::Builder builder(buf);
+//       builder.set_x(input.x());
+//       builder.set_y(input.y());
+//       return builder.Finish();
+//     }
+//     static gfx::Point ConvertTo(const geometry::Point& input) {
+//       return gfx::Point(input.x(), input.y());
+//     }
+//   };
+//   }
+//
+// With the above TypeConverter defined, it is possible to write code like this:
+//
+//   void SomeFunction(const gfx::Point& pt);
+//
+//   void AcceptPoint(const geometry::Point& input) {
+//     // With an explicit cast using the .To<> method.
+//     gfx::Point pt = input.To<gfx::Point>();
+//
+//     // With an implicit copy conversion:
+//     SomeFunction(input);
+//
+//     mojo::AllocationScope scope;
+//     // With an implicit copy conversion:
+//     geometry::Point output = pt;
+//   }
+//
 template <typename T, typename U> class TypeConverter {
   // static T ConvertFrom(const U& input, Buffer* buf);
   // static U ConvertTo(const T& input);
diff --git a/mojo/public/c/DEPS b/mojo/public/c/DEPS
new file mode 100644
index 0000000..b7a363c
--- /dev/null
+++ b/mojo/public/c/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  # Require explicit dependencies in each directory.
+  "-mojo/public",
+  # But everyone can depend on the C system headers.
+  "+mojo/public/c/system",
+]
diff --git a/mojo/public/c/system/async_waiter.h b/mojo/public/c/system/async_waiter.h
new file mode 100644
index 0000000..ab999a3
--- /dev/null
+++ b/mojo/public/c/system/async_waiter.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_ASYNC_WAITER_H_
+#define MOJO_PUBLIC_C_SYSTEM_ASYNC_WAITER_H_
+
+#include "mojo/public/c/system/core.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uintptr_t MojoAsyncWaitID;
+
+typedef void (*MojoAsyncWaitCallback)(void* closure, MojoResult result);
+
+struct MojoAsyncWaiter {
+  // Asynchronously call MojoWait on a background thread, and pass the result
+  // of MojoWait to the given MojoAsyncWaitCallback on the current thread.
+  // Returns a non-zero MojoAsyncWaitID that can be used with CancelWait to
+  // stop waiting. This identifier becomes invalid once the callback runs.
+  MojoAsyncWaitID (*AsyncWait)(struct MojoAsyncWaiter* waiter,
+                               MojoHandle handle,
+                               MojoWaitFlags flags,
+                               MojoDeadline deadline,
+                               MojoAsyncWaitCallback callback,
+                               void* closure);
+
+  // Cancel an existing call to AsyncWait with the given MojoAsyncWaitID. The
+  // corresponding MojoAsyncWaitCallback will not be called in this case.
+  void (*CancelWait)(struct MojoAsyncWaiter* waiter,
+                     MojoAsyncWaitID wait_id);
+};
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // MOJO_PUBLIC_C_SYSTEM_ASYNC_WAITER_H_
diff --git a/mojo/public/c/system/core.h b/mojo/public/c/system/core.h
new file mode 100644
index 0000000..8a5116e
--- /dev/null
+++ b/mojo/public/c/system/core.h
@@ -0,0 +1,820 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_CORE_H_
+#define MOJO_PUBLIC_C_SYSTEM_CORE_H_
+
+// Note: This header should be compilable as C.
+
+#include <stdint.h>
+
+#include "mojo/public/c/system/macros.h"
+#include "mojo/public/c/system/system_export.h"
+
+// Types/constants -------------------------------------------------------------
+
+// TODO(vtl): Notes: Use of undefined flags will lead to undefined behavior
+// (typically they'll be ignored), not necessarily an error.
+
+// |MojoTimeTicks|: Used to specify time ticks. Value is in microseconds.
+
+typedef int64_t MojoTimeTicks;
+
+// |MojoHandle|: Handles to Mojo objects.
+//   |MOJO_HANDLE_INVALID| - A value that is never a valid handle.
+
+typedef uint32_t MojoHandle;
+
+#ifdef __cplusplus
+const MojoHandle MOJO_HANDLE_INVALID = 0;
+#else
+#define MOJO_HANDLE_INVALID ((MojoHandle) 0)
+#endif
+
+// |MojoResult|: Result codes for Mojo operations. Non-negative values are
+// success codes; negative values are error/failure codes.
+//   |MOJO_RESULT_OK| - Not an error; returned on success. Note that positive
+//       |MojoResult|s may also be used to indicate success.
+//   |MOJO_RESULT_CANCELLED| - Operation was cancelled, typically by the caller.
+//   |MOJO_RESULT_UNKNOWN| - Unknown error (e.g., if not enough information is
+//       available for a more specific error).
+//   |MOJO_RESULT_INVALID_ARGUMENT| - Caller specified an invalid argument. This
+//       differs from |MOJO_RESULT_FAILED_PRECONDITION| in that the former
+//       indicates arguments that are invalid regardless of the state of the
+//       system.
+//   |MOJO_RESULT_DEADLINE_EXCEEDED| - Deadline expired before the operation
+//       could complete.
+//   |MOJO_RESULT_NOT_FOUND| - Some requested entity was not found (i.e., does
+//       not exist).
+//   |MOJO_RESULT_ALREADY_EXISTS| - Some entity or condition that we attempted
+//       to create already exists.
+//   |MOJO_RESULT_PERMISSION_DENIED| - The caller does not have permission to
+//       for the operation (use |MOJO_RESULT_RESOURCE_EXHAUSTED| for rejections
+//       caused by exhausting some resource instead).
+//   |MOJO_RESULT_RESOURCE_EXHAUSTED| - Some resource required for the call
+//       (possibly some quota) has been exhausted.
+//   |MOJO_RESULT_FAILED_PRECONDITION| - The system is not in a state required
+//       for the operation (use this if the caller must do something to rectify
+//       the state before retrying).
+//   |MOJO_RESULT_ABORTED| - The operation was aborted by the system, possibly
+//       due to a concurrency issue (use this if the caller may retry at a
+//       higher level).
+//   |MOJO_RESULT_OUT_OF_RANGE| - The operation was attempted past the valid
+//       range. Unlike |MOJO_RESULT_INVALID_ARGUMENT|, this indicates that the
+//       operation may be/become valid depending on the system state. (This
+//       error is similar to |MOJO_RESULT_FAILED_PRECONDITION|, but is more
+//       specific.)
+//   |MOJO_RESULT_UNIMPLEMENTED| - The operation is not implemented, supported,
+//       or enabled.
+//   |MOJO_RESULT_INTERNAL| - Internal error: this should never happen and
+//       indicates that some invariant expected by the system has been broken.
+//   |MOJO_RESULT_UNAVAILABLE| - The operation is (temporarily) currently
+//       unavailable. The caller may simply retry the operation (possibly with a
+//       backoff).
+//   |MOJO_RESULT_DATA_LOSS| - Unrecoverable data loss or corruption.
+//   |MOJO_RESULT_BUSY| - One of the resources involved is currently being used
+//       (possibly on another thread) in a way that prevents the current
+//       operation from proceeding, e.g., if the other operation may result in
+//       the resource being invalidated.
+//   |MOJO_RESULT_SHOULD_WAIT| - The request cannot currently be completed
+//       (e.g., if the data requested is not yet available). The caller should
+//       wait for it to be feasible using |MojoWait()| or |MojoWaitMany()|.
+//
+// Note that positive values are also available as success codes.
+//
+// The codes from |MOJO_RESULT_OK| to |MOJO_RESULT_DATA_LOSS| come from
+// Google3's canonical error codes.
+//
+// TODO(vtl): Add a |MOJO_RESULT_UNSATISFIABLE|?
+
+typedef int32_t MojoResult;
+
+#ifdef __cplusplus
+const MojoResult MOJO_RESULT_OK = 0;
+const MojoResult MOJO_RESULT_CANCELLED = -1;
+const MojoResult MOJO_RESULT_UNKNOWN = -2;
+const MojoResult MOJO_RESULT_INVALID_ARGUMENT = -3;
+const MojoResult MOJO_RESULT_DEADLINE_EXCEEDED = -4;
+const MojoResult MOJO_RESULT_NOT_FOUND = -5;
+const MojoResult MOJO_RESULT_ALREADY_EXISTS = -6;
+const MojoResult MOJO_RESULT_PERMISSION_DENIED = -7;
+const MojoResult MOJO_RESULT_RESOURCE_EXHAUSTED = -8;
+const MojoResult MOJO_RESULT_FAILED_PRECONDITION = -9;
+const MojoResult MOJO_RESULT_ABORTED = -10;
+const MojoResult MOJO_RESULT_OUT_OF_RANGE = -11;
+const MojoResult MOJO_RESULT_UNIMPLEMENTED = -12;
+const MojoResult MOJO_RESULT_INTERNAL = -13;
+const MojoResult MOJO_RESULT_UNAVAILABLE = -14;
+const MojoResult MOJO_RESULT_DATA_LOSS = -15;
+const MojoResult MOJO_RESULT_BUSY = -16;
+const MojoResult MOJO_RESULT_SHOULD_WAIT = -17;
+#else
+#define MOJO_RESULT_OK ((MojoResult) 0)
+#define MOJO_RESULT_CANCELLED ((MojoResult) -1)
+#define MOJO_RESULT_UNKNOWN ((MojoResult) -2)
+#define MOJO_RESULT_INVALID_ARGUMENT ((MojoResult) -3)
+#define MOJO_RESULT_DEADLINE_EXCEEDED ((MojoResult) -4)
+#define MOJO_RESULT_NOT_FOUND ((MojoResult) -5)
+#define MOJO_RESULT_ALREADY_EXISTS ((MojoResult) -6)
+#define MOJO_RESULT_PERMISSION_DENIED ((MojoResult) -7)
+#define MOJO_RESULT_RESOURCE_EXHAUSTED ((MojoResult) -8)
+#define MOJO_RESULT_FAILED_PRECONDITION ((MojoResult) -9)
+#define MOJO_RESULT_ABORTED ((MojoResult) -10)
+#define MOJO_RESULT_OUT_OF_RANGE ((MojoResult) -11)
+#define MOJO_RESULT_UNIMPLEMENTED ((MojoResult) -12)
+#define MOJO_RESULT_INTERNAL ((MojoResult) -13)
+#define MOJO_RESULT_UNAVAILABLE ((MojoResult) -14)
+#define MOJO_RESULT_DATA_LOSS ((MojoResult) -15)
+#define MOJO_RESULT_BUSY ((MojoResult) -16)
+#define MOJO_RESULT_SHOULD_WAIT ((MojoResult) -17)
+#endif
+
+// |MojoDeadline|: Used to specify deadlines (timeouts), in microseconds (except
+// for |MOJO_DEADLINE_INDEFINITE|).
+//   |MOJO_DEADLINE_INDEFINITE| - Used to indicate "forever".
+
+typedef uint64_t MojoDeadline;
+
+#ifdef __cplusplus
+const MojoDeadline MOJO_DEADLINE_INDEFINITE = static_cast<MojoDeadline>(-1);
+#else
+#define MOJO_DEADLINE_INDEFINITE ((MojoDeadline) -1)
+#endif
+
+// |MojoWaitFlags|: Used to specify the state of a handle to wait on (e.g., the
+// ability to read or write to it).
+//   |MOJO_WAIT_FLAG_NONE| - No flags. |MojoWait()|, etc. will return
+//       |MOJO_RESULT_FAILED_PRECONDITION| if you attempt to wait on this.
+//   |MOJO_WAIT_FLAG_READABLE| - Can read (e.g., a message) from the handle.
+//   |MOJO_WAIT_FLAG_WRITABLE| - Can write (e.g., a message) to the handle.
+//   |MOJO_WAIT_FLAG_EVERYTHING| - All flags.
+
+typedef uint32_t MojoWaitFlags;
+
+#ifdef __cplusplus
+const MojoWaitFlags MOJO_WAIT_FLAG_NONE = 0;
+const MojoWaitFlags MOJO_WAIT_FLAG_READABLE = 1 << 0;
+const MojoWaitFlags MOJO_WAIT_FLAG_WRITABLE = 1 << 1;
+const MojoWaitFlags MOJO_WAIT_FLAG_EVERYTHING = ~0;
+#else
+#define MOJO_WAIT_FLAG_NONE ((MojoWaitFlags) 0)
+#define MOJO_WAIT_FLAG_READABLE ((MojoWaitFlags) 1 << 0)
+#define MOJO_WAIT_FLAG_WRITABLE ((MojoWaitFlags) 1 << 1)
+#define MOJO_WAIT_FLAG_EVERYTHING (~((MojoWaitFlags) 0))
+#endif
+
+// Message pipe:
+
+// |MojoWriteMessageFlags|: Used to specify different modes to
+// |MojoWriteMessage()|.
+//   |MOJO_WRITE_MESSAGE_FLAG_NONE| - No flags; default mode.
+
+typedef uint32_t MojoWriteMessageFlags;
+
+#ifdef __cplusplus
+const MojoWriteMessageFlags MOJO_WRITE_MESSAGE_FLAG_NONE = 0;
+#else
+#define MOJO_WRITE_MESSAGE_FLAG_NONE ((MojoWriteMessageFlags) 0)
+#endif
+
+// |MojoReadMessageFlags|: Used to specify different modes to
+// |MojoReadMessage()|.
+//   |MOJO_READ_MESSAGE_FLAG_NONE| - No flags; default mode.
+//   |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| - If the message is unable to be read
+//       for whatever reason (e.g., the caller-supplied buffer is too small),
+//       discard the message (i.e., simply dequeue it).
+
+typedef uint32_t MojoReadMessageFlags;
+
+#ifdef __cplusplus
+const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE = 0;
+const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD = 1 << 0;
+#else
+#define MOJO_READ_MESSAGE_FLAG_NONE ((MojoReadMessageFlags) 0)
+#define MOJO_READ_MESSAGE_FLAG_MAY_DISCARD ((MojoReadMessageFlags) 1 << 0)
+#endif
+
+// Data pipe:
+
+// |MojoCreateDataPipeOptions|: Used to specify creation parameters for a data
+// pipe to |MojoCreateDataPipe()|.
+//   |uint32_t struct_size|: Set to the size of the |MojoCreateDataPipeOptions|
+//       struct. (Used to allow for future extensions.)
+//   |MojoCreateDataPipeOptionsFlags flags|: Used to specify different modes of
+//       operation.
+//     |MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE|: No flags; default mode.
+//     |MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD|: May discard data for
+//         whatever reason; best-effort delivery. In particular, if the capacity
+//         is reached, old data may be discard to make room for new data.
+//   |uint32_t element_num_bytes|: The size of an element, in bytes. All
+//       transactions and buffers will consist of an integral number of
+//       elements. Must be nonzero.
+//   |uint32_t capacity_num_bytes|: The capacity of the data pipe, in number of
+//       bytes; must be a multiple of |element_num_bytes|. The data pipe will
+//       always be able to queue AT LEAST this much data. Set to zero to opt for
+//       a system-dependent automatically-calculated capacity (which will always
+//       be at least one element).
+
+typedef uint32_t MojoCreateDataPipeOptionsFlags;
+
+#ifdef __cplusplus
+const MojoCreateDataPipeOptionsFlags
+    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE = 0;
+const MojoCreateDataPipeOptionsFlags
+    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD = 1 << 0;
+#else
+#define MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE \
+    ((MojoCreateDataPipeOptionsFlags) 0)
+#define MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD \
+    ((MojoCreateDataPipeOptionsFlags) 1 << 0)
+#endif
+
+struct MojoCreateDataPipeOptions {
+  uint32_t struct_size;
+  MojoCreateDataPipeOptionsFlags flags;
+  uint32_t element_num_bytes;
+  uint32_t capacity_num_bytes;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoCreateDataPipeOptions) == 16,
+                    MojoCreateDataPipeOptions_has_wrong_size);
+
+// |MojoWriteDataFlags|: Used to specify different modes to |MojoWriteData()|
+// and |MojoBeginWriteData()|.
+//   |MOJO_WRITE_DATA_FLAG_NONE| - No flags; default mode.
+//   |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| - Write either all the elements
+//       requested or none of them.
+
+typedef uint32_t MojoWriteDataFlags;
+
+#ifdef __cplusplus
+const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_NONE = 0;
+const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_ALL_OR_NONE = 1 << 0;
+#else
+#define MOJO_WRITE_DATA_FLAG_NONE ((MojoWriteDataFlags) 0)
+#define MOJO_WRITE_DATA_FLAG_ALL_OR_NONE ((MojoWriteDataFlags) 1 << 0)
+#endif
+
+// |MojoReadDataFlags|: Used to specify different modes to |MojoReadData()| and
+// |MojoBeginReadData()|.
+//   |MOJO_READ_DATA_FLAG_NONE| - No flags; default mode.
+//   |MOJO_READ_DATA_FLAG_ALL_OR_NONE| - Read (or discard) either the requested
+//        number of elements or none.
+//   |MOJO_READ_DATA_FLAG_DISCARD| - Discard (up to) the requested number of
+//        elements.
+//   |MOJO_READ_DATA_FLAG_QUERY| - Query the number of elements available to
+//       read. For use with |MojoReadData()| only. Mutually exclusive with
+//       |MOJO_READ_DATA_FLAG_DISCARD| and |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is
+//       ignored if this flag is set.
+
+typedef uint32_t MojoReadDataFlags;
+
+#ifdef __cplusplus
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_NONE = 0;
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_ALL_OR_NONE = 1 << 0;
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_DISCARD = 1 << 1;
+const MojoReadDataFlags MOJO_READ_DATA_FLAG_QUERY = 1 << 2;
+#else
+#define MOJO_READ_DATA_FLAG_NONE ((MojoReadDataFlags) 0)
+#define MOJO_READ_DATA_FLAG_ALL_OR_NONE ((MojoReadDataFlags) 1 << 0)
+#define MOJO_READ_DATA_FLAG_DISCARD ((MojoReadDataFlags) 1 << 1)
+#define MOJO_READ_DATA_FLAG_QUERY ((MojoReadDataFlags) 1 << 2)
+#endif
+
+// Shared buffer:
+
+// |MojoCreateSharedBufferOptions|: Used to specify creation parameters for a
+// shared buffer to |MojoCreateSharedBuffer()|.
+//   |uint32_t struct_size|: Set to the size of the
+//       |MojoCreateSharedBufferOptions| struct. (Used to allow for future
+//       extensions.)
+//   |MojoCreateSharedBufferOptionsFlags flags|: Reserved for future use.
+//       |MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE|: No flags; default mode.
+//
+// TODO(vtl): Maybe add a flag to indicate whether the memory should be
+// executable or not?
+// TODO(vtl): Also a flag for discardable (ashmem-style) buffers.
+
+typedef uint32_t MojoCreateSharedBufferOptionsFlags;
+
+#ifdef __cplusplus
+const MojoCreateSharedBufferOptionsFlags
+    MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE = 0;
+#else
+#define MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE \
+    ((MojoCreateSharedBufferOptionsFlags) 0)
+#endif
+
+struct MojoCreateSharedBufferOptions {
+  uint32_t struct_size;
+  MojoCreateSharedBufferOptionsFlags flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoCreateSharedBufferOptions) == 8,
+                    MojoCreateSharedBufferOptions_has_wrong_size);
+
+// |MojoDuplicateBufferHandleOptions|: Used to specify parameters in duplicating
+// access to a shared buffer to |MojoDuplicateBufferHandle()|.
+//   |uint32_t struct_size|: Set to the size of the
+//       |MojoDuplicateBufferHandleOptions| struct. (Used to allow for future
+//       extensions.)
+//   |MojoDuplicateBufferHandleOptionsFlags flags|: Reserved for future use.
+//       |MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE|: No flags; default
+//       mode.
+//
+// TODO(vtl): Add flags to remove writability (and executability)? Also, COW?
+
+typedef uint32_t MojoDuplicateBufferHandleOptionsFlags;
+
+#ifdef __cplusplus
+const MojoDuplicateBufferHandleOptionsFlags
+    MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE = 0;
+#else
+#define MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE \
+    ((MojoDuplicateBufferHandleOptionsFlags) 0)
+#endif
+
+struct MojoDuplicateBufferHandleOptions {
+  uint32_t struct_size;
+  MojoDuplicateBufferHandleOptionsFlags flags;
+};
+MOJO_COMPILE_ASSERT(sizeof(MojoDuplicateBufferHandleOptions) == 8,
+                    MojoDuplicateBufferHandleOptions_has_wrong_size);
+
+// |MojoMapBufferFlags|: Used to specify different modes to |MojoMapBuffer()|.
+//   |MOJO_MAP_BUFFER_FLAG_NONE| - No flags; default mode.
+
+typedef uint32_t MojoMapBufferFlags;
+
+#ifdef __cplusplus
+const MojoMapBufferFlags MOJO_MAP_BUFFER_FLAG_NONE = 0;
+#else
+#define MOJO_MAP_BUFFER_FLAG_NONE ((MojoMapBufferFlags) 0)
+#endif
+
+// Functions -------------------------------------------------------------------
+
+// Note: Pointer parameters that are labeled "optional" may be null (at least
+// under some circumstances). Non-const pointer parameters are also labelled
+// "in", "out", or "in/out", to indicate how they are used. (Note that how/if
+// such a parameter is used may depend on other parameters or the requested
+// operation's success/failure. E.g., a separate |flags| parameter may control
+// whether a given "in/out" parameter is used for input, output, or both.)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Platform-dependent monotonically increasing tick count representing "right
+// now." The resolution of this clock is ~1-15ms.  Resolution varies depending
+// on hardware/operating system configuration.
+MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow();
+
+// Closes the given |handle|.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle.
+//
+// Concurrent operations on |handle| may succeed (or fail as usual) if they
+// happen before the close, be cancelled with result |MOJO_RESULT_CANCELLED| if
+// they properly overlap (this is likely the case with |MojoWait()|, etc.), or
+// fail with |MOJO_RESULT_INVALID_ARGUMENT| if they happen after.
+MOJO_SYSTEM_EXPORT MojoResult MojoClose(MojoHandle handle);
+
+// Waits on the given handle until the state indicated by |flags| is satisfied
+// or until |deadline| has passed.
+//
+// Returns:
+//   |MOJO_RESULT_OK| if some flag in |flags| was satisfied (or is already
+//        satisfied).
+//   |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle (e.g., if
+//       it has already been closed).
+//   |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of
+//       the flags being satisfied.
+//   |MOJO_RESULT_FAILED_PRECONDITION| if it is or becomes impossible that any
+//       flag in |flags| will ever be satisfied.
+//
+// If there are multiple waiters (on different threads, obviously) waiting on
+// the same handle and flag and that flag becomes set, all waiters will be
+// awoken.
+MOJO_SYSTEM_EXPORT MojoResult MojoWait(MojoHandle handle,
+                                       MojoWaitFlags flags,
+                                       MojoDeadline deadline);
+
+// Waits on |handles[0]|, ..., |handles[num_handles-1]| for at least one of them
+// to satisfy the state indicated by |flags[0]|, ..., |flags[num_handles-1]|,
+// respectively, or until |deadline| has passed.
+//
+// Returns:
+//   The index |i| (from 0 to |num_handles-1|) if |handle[i]| satisfies
+//       |flags[i]|.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some |handle[i]| is not a valid handle
+//       (e.g., if it has already been closed).
+//   |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of
+//       handles satisfying any of its flags.
+//   |MOJO_RESULT_FAILED_PRECONDITION| if it is or becomes impossible that SOME
+//       |handle[i]| will ever satisfy any of its flags |flags[i]|.
+MOJO_SYSTEM_EXPORT MojoResult MojoWaitMany(const MojoHandle* handles,
+                                           const MojoWaitFlags* flags,
+                                           uint32_t num_handles,
+                                           MojoDeadline deadline);
+
+// Message pipe:
+
+// Creates a message pipe, which is a bidirectional communication channel for
+// framed data (i.e., messages). Messages can contain plain data and/or Mojo
+// handles. On success, |*message_pipe_handle0| and |*message_pipe_handle1| are
+// set to handles for the two endpoints (ports) for the message pipe.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if |message_pipe_handle0| and/or
+//       |message_pipe_handle1| do not appear to be valid pointers.
+//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
+//       been reached.
+//
+// TODO(vtl): Add an options struct pointer argument.
+MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessagePipe(
+    MojoHandle* message_pipe_handle0,  // Out.
+    MojoHandle* message_pipe_handle1);  // Out.
+
+// Writes a message to the message pipe endpoint given by |message_pipe_handle|,
+// with message data specified by |bytes| of size |num_bytes| and attached
+// handles specified by |handles| of count |num_handles|, and options specified
+// by |flags|. If there is no message data, |bytes| may be null, in which case
+// |num_bytes| must be zero. If there are no attached handles, |handles| may be
+// null, in which case |num_handles| must be zero.
+//
+// If handles are attached, on success the handles will no longer be valid (the
+// receiver will receive equivalent, but logically different, handles). Handles
+// to be sent should not be in simultaneous use (e.g., on another thread).
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success (i.e., the message was enqueued).
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+//       |message_pipe_handle| is not a valid handle, or some of the
+//       requirements above are not satisfied).
+//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if some system limit has been reached, or
+//       the number of handles to send is too large (TODO(vtl): reconsider the
+//       latter case).
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
+//       Note that closing an endpoint is not necessarily synchronous (e.g.,
+//       across processes), so this function may be succeed even if the other
+//       endpoint has been closed (in which case the message would be dropped).
+//   |MOJO_RESULT_BUSY| if some handle to be sent is currently in use.
+//
+// TODO(vtl): Add a notion of capacity for message pipes, and return
+// |MOJO_RESULT_SHOULD_WAIT| if the message pipe is full.
+MOJO_SYSTEM_EXPORT MojoResult MojoWriteMessage(
+    MojoHandle message_pipe_handle,
+    const void* bytes,  // Optional.
+    uint32_t num_bytes,
+    const MojoHandle* handles,  // Optional.
+    uint32_t num_handles,
+    MojoWriteMessageFlags flags);
+
+// Reads a message from the message pipe endpoint given by
+// |message_pipe_handle|; also usable to query the size of the next message or
+// discard the next message. |bytes|/|*num_bytes| indicate the buffer/buffer
+// size to receive the message data (if any) and |handles|/|*num_handles|
+// indicate the buffer/maximum handle count to receive the attached handles (if
+// any).
+//
+// |num_bytes| and |num_handles| are optional "in-out" parameters. If non-null,
+// on return |*num_bytes| and |*num_handles| will usually indicate the number
+// of bytes and number of attached handles in the "next" message, respectively,
+// whether that message was read or not. (If null, the number of bytes/handles
+// is treated as zero.)
+//
+// If |bytes| is null, then |*num_bytes| must be zero, and similarly for
+// |handles| and |*num_handles|.
+//
+// Partial reads are NEVER done. Either a full read is done and |MOJO_RESULT_OK|
+// returned, or the read is NOT done and |MOJO_RESULT_RESOURCE_EXHAUSTED| is
+// returned (if |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| was set, the message is
+// also discarded in this case).
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success (i.e., a message was actually read).
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid.
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
+//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if one of the buffers to receive the
+//       message/attached handles (|bytes|/|*num_bytes| or
+//       |handles|/|*num_handles|) was too small. (TODO(vtl): Reconsider this
+//       error code; should distinguish this from the hitting-system-limits
+//       case.)
+//   |MOJO_RESULT_SHOULD_WAIT| if no message was available to be read.
+MOJO_SYSTEM_EXPORT MojoResult MojoReadMessage(
+    MojoHandle message_pipe_handle,
+    void* bytes,  // Optional out.
+    uint32_t* num_bytes,  // Optional in/out.
+    MojoHandle* handles,  // Optional out.
+    uint32_t* num_handles,  // Optional in/out.
+    MojoReadMessageFlags flags);
+
+// Data pipe:
+
+// Creates a data pipe, which is a unidirectional communication channel for
+// unframed data, with the given options. Data is unframed, but must come as
+// (multiples of) discrete elements, of the size given in |options|. See
+// |MojoCreateDataPipeOptions| for a description of the different options
+// available for data pipes.
+//
+// |options| may be set to null for a data pipe with the default options (which
+// will have an element size of one byte and have some system-dependent
+// capacity).
+//
+// On success, |*data_pipe_producer_handle| will be set to the handle for the
+// producer and |*data_pipe_consumer_handle| will be set to the handle for the
+// consumer. (On failure, they are not modified.)
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+//       |*options| is invalid or one of the pointer handles looks invalid).
+//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
+//       been reached (e.g., if the requested capacity was too large, or if the
+//       maximum number of handles was exceeded).
+MOJO_SYSTEM_EXPORT MojoResult MojoCreateDataPipe(
+    const struct MojoCreateDataPipeOptions* options,  // Optional.
+    MojoHandle* data_pipe_producer_handle,  // Out.
+    MojoHandle* data_pipe_consumer_handle);  // Out.
+
+// Writes the given data to the data pipe producer given by
+// |data_pipe_producer_handle|. |elements| points to data of size |*num_bytes|;
+// |*num_bytes| should be a multiple of the data pipe's element size. If
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| is set in |flags|, either all the data
+// will be written or none is.
+//
+// On success, |*num_bytes| is set to the amount of data that was actually
+// written.
+//
+// Note: If the data pipe has the "may discard" option flag (specified on
+// creation), this will discard as much data as required to write the given
+// data, starting with the earliest written data that has not been consumed.
+// However, even with "may discard", if |*num_bytes| is greater than the data
+// pipe's capacity (and |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| is not set), this
+// will write the maximum amount possible (namely, the data pipe's capacity) and
+// set |*num_bytes| to that amount. It will *not* discard data from |elements|.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+//       |data_pipe_producer_dispatcher| is not a handle to a data pipe
+//       producer, |elements| does not look like a valid pointer, or
+//       |*num_bytes| is not a multiple of the data pipe's element size).
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
+//       closed.
+//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has
+//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
+//       (specified by |*num_bytes|) could not be written.
+//   |MOJO_RESULT_BUSY| if there is a two-phase write ongoing with
+//       |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
+//       called, but not yet the matching |MojoEndWriteData()|).
+//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
+//       consumer is still open) and |flags| does *not* have
+//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set.
+//
+// TODO(vtl): Should there be a way of querying how much data can be written?
+MOJO_SYSTEM_EXPORT MojoResult MojoWriteData(
+    MojoHandle data_pipe_producer_handle,
+    const void* elements,
+    uint32_t* num_bytes,  // In/out.
+    MojoWriteDataFlags flags);
+
+// Begins a two-phase write to the data pipe producer given by
+// |data_pipe_producer_handle|. On success, |*buffer| will be a pointer to which
+// the caller can write |*buffer_num_bytes| bytes of data. If flags has
+// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set, then the output value
+// |*buffer_num_bytes| will be at least as large as its input value, which must
+// also be a multiple of the element size (if |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE|
+// is not set, the input value of |*buffer_num_bytes| is ignored).
+//
+// During a two-phase write, |data_pipe_producer_handle| is *not* writable.
+// E.g., if another thread tries to write to it, it will get |MOJO_RESULT_BUSY|;
+// that thread can then wait for |data_pipe_producer_handle| to become writable
+// again.
+//
+// Once the caller has finished writing data to |*buffer|, it should call
+// |MojoEndWriteData()| to specify the amount written and to complete the
+// two-phase write.
+//
+// Note: If the data pipe has the "may discard" option flag (specified on
+// creation) and |flags| has |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set, this may
+// discard some data.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+//       |data_pipe_producer_handle| is not a handle to a data pipe producer,
+//       |buffer| or |buffer_num_bytes| does not look like a valid pointer, or
+//       flags has |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and
+//       |*buffer_num_bytes| is not a multiple of the element size).
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
+//       closed.
+//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has
+//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
+//       (specified by |*buffer_num_bytes|) cannot be written contiguously at
+//       this time. (Note that there may be space available for the required
+//       amount of data, but the "next" write position may not be large enough.)
+//   |MOJO_RESULT_BUSY| if there is already a two-phase write ongoing with
+//       |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
+//       called, but not yet the matching |MojoEndWriteData()|).
+//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
+//       consumer is still open).
+MOJO_SYSTEM_EXPORT MojoResult MojoBeginWriteData(
+    MojoHandle data_pipe_producer_handle,
+    void** buffer,  // Out.
+    uint32_t* buffer_num_bytes,  // In/out.
+    MojoWriteDataFlags flags);
+
+// Ends a two-phase write to the data pipe producer given by
+// |data_pipe_producer_handle| that was begun by a call to
+// |MojoBeginWriteData()| on the same handle. |num_bytes_written| should
+// indicate the amount of data actually written; it must be less than or equal
+// to the value of |*buffer_num_bytes| output by |MojoBeginWriteData()| and must
+// be a multiple of the element size. The buffer given by |*buffer| from
+// |MojoBeginWriteData()| must have been filled with exactly |num_bytes_written|
+// bytes of data.
+//
+// On failure, the two-phase write (if any) is ended (so the handle may become
+// writable again, if there's space available) but no data written to |*buffer|
+// is "put into" the data pipe.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if |data_pipe_producer_handle| is not a
+//       handle to a data pipe producer or |num_bytes_written| is invalid
+//       (greater than the maximum value provided by |MojoBeginWriteData()| or
+//       not a multiple of the element size).
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer is not in a
+//       two-phase write (e.g., |MojoBeginWriteData()| was not called or
+//       |MojoEndWriteData()| has already been called).
+MOJO_SYSTEM_EXPORT MojoResult MojoEndWriteData(
+    MojoHandle data_pipe_producer_handle,
+    uint32_t num_bytes_written);
+
+// Reads data from the data pipe consumer given by |data_pipe_consumer_handle|.
+// May also be used to discard data or query the amount of data available.
+//
+// If |flags| has neither |MOJO_READ_DATA_FLAG_DISCARD| nor
+// |MOJO_READ_DATA_FLAG_QUERY| set, this tries to read up to |*num_bytes| (which
+// must be a multiple of the data pipe's element size) bytes of data to
+// |elements| and set |*num_bytes| to the amount actually read. If flags has
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, it will either read exactly
+// |*num_bytes| bytes of data or none.
+//
+// If flags has |MOJO_READ_DATA_FLAG_DISCARD| set, it discards up to
+// |*num_bytes| (which again be a multiple of the element size) bytes of data,
+// setting |*num_bytes| to the amount actually discarded. If flags has
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE|, it will either discard exactly
+// |*num_bytes| bytes of data or none. In this case, |MOJO_READ_DATA_FLAG_QUERY|
+// must not be set, and |elements| is ignored (and should typically be set to
+// null).
+//
+// If flags has |MOJO_READ_DATA_FLAG_QUERY| set, it queries the amount of data
+// available, setting |*num_bytes| to the number of bytes available. In this
+// case, |MOJO_READ_DATA_FLAG_DISCARD| must not be set, and
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is ignored, as are |elements| and the input
+// value of |*num_bytes|.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success (see above for a description of the different
+//       operations).
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
+//       |data_pipe_consumer_handle| is invalid, the combination of flags in
+//       |flags| is invalid, etc.).
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
+//       closed and data (or the required amount of data) was not available to
+//       be read or discarded.
+//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
+//       set and the required amount of data is not available to be read or
+//       discarded (and the producer is still open).
+//   |MOJO_RESULT_BUSY| if there is a two-phase read ongoing with
+//       |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
+//       called, but not yet the matching |MojoEndReadData()|).
+//   |MOJO_RESULT_SHOULD_WAIT| if there is no data to be read or discarded (and
+//       the producer is still open) and |flags| does *not* have
+//       |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set.
+MOJO_SYSTEM_EXPORT MojoResult MojoReadData(
+    MojoHandle data_pipe_consumer_handle,
+    void* elements,  // Out.
+    uint32_t* num_bytes,  // In/out.
+    MojoReadDataFlags flags);
+
+// Begins a two-phase read from the data pipe consumer given by
+// |data_pipe_consumer_handle|. On success, |*buffer| will be a pointer from
+// which the caller can read |*buffer_num_bytes| bytes of data. If flags has
+// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, then the output value
+// |*buffer_num_bytes| will be at least as large as its input value, which must
+// also be a multiple of the element size (if |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
+// is not set, the input value of |*buffer_num_bytes| is ignored). |flags| must
+// not have |MOJO_READ_DATA_FLAG_DISCARD| or |MOJO_READ_DATA_FLAG_QUERY| set.
+//
+// During a two-phase read, |data_pipe_consumer_handle| is *not* readable.
+// E.g., if another thread tries to read from it, it will get
+// |MOJO_RESULT_BUSY|; that thread can then wait for |data_pipe_consumer_handle|
+// to become readable again.
+//
+// Once the caller has finished reading data from |*buffer|, it should call
+// |MojoEndReadData()| to specify the amount read and to complete the two-phase
+// read.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
+//       |data_pipe_consumer_handle| is not a handle to a data pipe consumer,
+//       |buffer| or |buffer_num_bytes| does not look like a valid pointer,
+//       |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set and
+//       |*buffer_num_bytes| is not a multiple of the element size, or |flags|
+//       has invalid flags set).
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
+//       closed.
+//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
+//       set and the required amount of data (specified by |*buffer_num_bytes|)
+//       cannot be read from a contiguous buffer at this time. (Note that there
+//       may be the required amount of data, but it may not be contiguous.)
+//   |MOJO_RESULT_BUSY| if there is already a two-phase read ongoing with
+//       |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
+//       called, but not yet the matching |MojoEndReadData()|).
+//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be read (and the
+//       producer is still open).
+MOJO_SYSTEM_EXPORT MojoResult MojoBeginReadData(
+    MojoHandle data_pipe_consumer_handle,
+    const void** buffer,  // Out.
+    uint32_t* buffer_num_bytes,  // In/out.
+    MojoReadDataFlags flags);
+
+// Ends a two-phase read from the data pipe consumer given by
+// |data_pipe_consumer_handle| that was begun by a call to |MojoBeginReadData()|
+// on the same handle. |num_bytes_read| should indicate the amount of data
+// actually read; it must be less than or equal to the value of
+// |*buffer_num_bytes| output by |MojoBeginReadData()| and must be a multiple of
+// the element size.
+//
+// On failure, the two-phase read (if any) is ended (so the handle may become
+// readable again) but no data is "removed" from the data pipe.
+//
+// Returns:
+//   |MOJO_RESULT_OK| on success.
+//   |MOJO_RESULT_INVALID_ARGUMENT| if |data_pipe_consumer_handle| is not a
+//       handle to a data pipe consumer or |num_bytes_written| is invalid
+//       (greater than the maximum value provided by |MojoBeginReadData()| or
+//       not a multiple of the element size).
+//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer is not in a
+//       two-phase read (e.g., |MojoBeginReadData()| was not called or
+//       |MojoEndReadData()| has already been called).
+MOJO_SYSTEM_EXPORT MojoResult MojoEndReadData(
+    MojoHandle data_pipe_consumer_handle,
+    uint32_t num_bytes_read);
+
+// Shared buffer:
+
+// TODO(vtl): General comments.
+
+// Creates a buffer that can be shared between applications (by duplicating the
+// handle -- see |MojoDuplicateBufferHandle()| -- and passing it over a message
+// pipe). To access the buffer, one must call |MojoMapBuffer()|.
+// TODO(vtl): More.
+MOJO_SYSTEM_EXPORT MojoResult MojoCreateSharedBuffer(
+    const struct MojoCreateSharedBufferOptions* options,  // Optional.
+    uint64_t num_bytes,  // In.
+    MojoHandle* shared_buffer_handle);  // Out.
+
+// Duplicates the handle |buffer_handle| to a buffer. This creates another
+// handle (returned in |*new_buffer_handle| on success), which can then be sent
+// to another application over a message pipe, while retaining access to the
+// |buffer_handle| (and any mappings that it may have).
+//
+// Note: We may add buffer types for which this operation is not supported.
+// TODO(vtl): More.
+MOJO_SYSTEM_EXPORT MojoResult MojoDuplicateBufferHandle(
+    MojoHandle buffer_handle,
+    const struct MojoDuplicateBufferHandleOptions* options,  // Optional.
+    MojoHandle* new_buffer_handle);  // Out.
+
+// Map the part (at offset |offset| of length |num_bytes|) of the buffer given
+// by |buffer_handle| into memory. |offset + num_bytes| must be less than or
+// equal to the size of the buffer. On success, |*buffer| points to memory with
+// the requested part of the buffer.
+//
+// A single buffer handle may have multiple active mappings (possibly depending
+// on the buffer type). The permissions (e.g., writable or executable) of the
+// returned memory may depend on the properties of the buffer and properties
+// attached to the buffer handle as well as |flags|.
+// TODO(vtl): More.
+MOJO_SYSTEM_EXPORT MojoResult MojoMapBuffer(MojoHandle buffer_handle,
+                                            uint64_t offset,
+                                            uint64_t num_bytes,
+                                            void** buffer,  // Out.
+                                            MojoMapBufferFlags flags);
+
+// Unmap a buffer pointer that was mapped by |MojoMapBuffer()|.
+// TODO(vtl): More.
+MOJO_SYSTEM_EXPORT MojoResult MojoUnmapBuffer(void* buffer);  // In.
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // MOJO_PUBLIC_C_SYSTEM_CORE_H_
diff --git a/mojo/public/c/system/macros.h b/mojo/public/c/system/macros.h
new file mode 100644
index 0000000..4be0249
--- /dev/null
+++ b/mojo/public/c/system/macros.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_MACROS_H_
+#define MOJO_PUBLIC_C_SYSTEM_MACROS_H_
+
+#include <stddef.h>
+
+// Annotate a variable indicating it's okay if it's unused.
+// Use like:
+//   int x MOJO_ALLOW_UNUSED = ...;
+#if defined(__GNUC__)
+#define MOJO_ALLOW_UNUSED __attribute__((unused))
+#else
+#define MOJO_ALLOW_UNUSED
+#endif
+
+// Annotate a function indicating that the caller must examine the return value.
+// Use like:
+//   int foo() MOJO_WARN_UNUSED_RESULT;
+// Note that it can only be used on the prototype, and not the definition.
+#if defined(__GNUC__)
+#define MOJO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#else
+#define MOJO_WARN_UNUSED_RESULT
+#endif
+
+// This macro is currently C++-only, but we want to use it in the C core.h.
+#ifdef __cplusplus
+// Used to assert things at compile time.
+namespace mojo { template <bool> struct CompileAssert {}; }
+#define MOJO_COMPILE_ASSERT(expr, msg) \
+    typedef ::mojo::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
+#else
+#define MOJO_COMPILE_ASSERT(expr, msg)
+#endif
+
+#endif  // MOJO_PUBLIC_C_SYSTEM_MACROS_H_
diff --git a/mojo/public/c/system/system_export.h b/mojo/public/c/system/system_export.h
new file mode 100644
index 0000000..3bd0260
--- /dev/null
+++ b/mojo/public/c/system/system_export.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_
+#define MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_
+
+#if defined(WIN32)
+
+#if defined(MOJO_SYSTEM_IMPLEMENTATION)
+#define MOJO_SYSTEM_EXPORT __declspec(dllexport)
+#else
+#define MOJO_SYSTEM_EXPORT __declspec(dllimport)
+#endif
+
+#else  // !defined(WIN32)
+
+#if defined(MOJO_SYSTEM_IMPLEMENTATION)
+#define MOJO_SYSTEM_EXPORT __attribute__((visibility("default")))
+#else
+#define MOJO_SYSTEM_EXPORT
+#endif
+
+#endif  // defined(WIN32)
+
+#endif  // MOJO_PUBLIC_C_SYSTEM_SYSTEM_EXPORT_H_
diff --git a/mojo/public/c/system/tests/DEPS b/mojo/public/c/system/tests/DEPS
new file mode 100644
index 0000000..d7c012c
--- /dev/null
+++ b/mojo/public/c/system/tests/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+  "+testing",
+  # Our test harness is C++, so allow the use of C++:
+  "+mojo/public/cpp",
+  # TODO(vtl): Temporary until these are moved to mojo/public/cpp:
+  "+mojo/public/tests",
+]
diff --git a/mojo/public/c/system/tests/core_perftest.cc b/mojo/public/c/system/tests/core_perftest.cc
new file mode 100644
index 0000000..eee782d
--- /dev/null
+++ b/mojo/public/c/system/tests/core_perftest.cc
@@ -0,0 +1,337 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This tests the performance of the C API.
+
+#include "mojo/public/c/system/core.h"
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/tests/test_support.h"
+#include "mojo/public/tests/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+// TODO(vtl): (here and below) crbug.com/342893
+#if !defined(WIN32)
+#include <time.h>
+#include "mojo/public/cpp/utility/thread.h"
+#endif  // !defined(WIN32)
+
+namespace {
+
+#if !defined(WIN32)
+class MessagePipeWriterThread : public mojo::Thread {
+ public:
+  MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes)
+      : handle_(handle),
+        num_bytes_(num_bytes),
+        num_writes_(0) {}
+  virtual ~MessagePipeWriterThread() {}
+
+  virtual void Run() MOJO_OVERRIDE {
+    char buffer[10000];
+    assert(num_bytes_ <= sizeof(buffer));
+
+    // TODO(vtl): Should I throttle somehow?
+    for (;;) {
+      MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, NULL, 0,
+                                           MOJO_WRITE_MESSAGE_FLAG_NONE);
+      if (result == MOJO_RESULT_OK) {
+        num_writes_++;
+        continue;
+      }
+
+      // We failed to write.
+      // Either |handle_| or its peer was closed.
+      assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
+             result == MOJO_RESULT_FAILED_PRECONDITION);
+      break;
+    }
+  }
+
+  // Use only after joining the thread.
+  int64_t num_writes() const { return num_writes_; }
+
+ private:
+  const MojoHandle handle_;
+  const uint32_t num_bytes_;
+  int64_t num_writes_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread);
+};
+
+class MessagePipeReaderThread : public mojo::Thread {
+ public:
+  explicit MessagePipeReaderThread(MojoHandle handle)
+      : handle_(handle),
+        num_reads_(0) {
+  }
+  virtual ~MessagePipeReaderThread() {}
+
+  virtual void Run() MOJO_OVERRIDE {
+    char buffer[10000];
+
+    for (;;) {
+      uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
+      MojoResult result = MojoReadMessage(handle_, buffer, &num_bytes, NULL,
+                                          NULL, MOJO_READ_MESSAGE_FLAG_NONE);
+      if (result == MOJO_RESULT_OK) {
+        num_reads_++;
+        continue;
+      }
+
+      if (result == MOJO_RESULT_SHOULD_WAIT) {
+        result = MojoWait(handle_, MOJO_WAIT_FLAG_READABLE,
+                          MOJO_DEADLINE_INDEFINITE);
+        if (result == MOJO_RESULT_OK) {
+          // Go to the top of the loop to read again.
+          continue;
+        }
+      }
+
+      // We failed to read and possibly failed to wait.
+      // Either |handle_| or its peer was closed.
+      assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
+             result == MOJO_RESULT_FAILED_PRECONDITION);
+      break;
+    }
+  }
+
+  // Use only after joining the thread.
+  int64_t num_reads() const { return num_reads_; }
+
+ private:
+  const MojoHandle handle_;
+  int64_t num_reads_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread);
+};
+#endif  // !defined(WIN32)
+
+class CorePerftest : public testing::Test {
+ public:
+  CorePerftest() : buffer_(NULL), num_bytes_(0) {}
+  virtual ~CorePerftest() {}
+
+  static void NoOp(void* /*closure*/) {
+  }
+
+  static void MessagePipe_CreateAndClose(void* closure) {
+    CorePerftest* self = static_cast<CorePerftest*>(closure);
+    MojoResult result MOJO_ALLOW_UNUSED;
+    result = MojoCreateMessagePipe(&self->h0_, &self->h1_);
+    assert(result == MOJO_RESULT_OK);
+    result = MojoClose(self->h0_);
+    assert(result == MOJO_RESULT_OK);
+    result = MojoClose(self->h1_);
+    assert(result == MOJO_RESULT_OK);
+  }
+
+  static void MessagePipe_WriteAndRead(void* closure) {
+    CorePerftest* self = static_cast<CorePerftest*>(closure);
+    MojoResult result MOJO_ALLOW_UNUSED;
+    result = MojoWriteMessage(self->h0_,
+                              self->buffer_, self->num_bytes_,
+                              NULL, 0,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE);
+    assert(result == MOJO_RESULT_OK);
+    uint32_t read_bytes = self->num_bytes_;
+    result = MojoReadMessage(self->h1_,
+                             self->buffer_, &read_bytes,
+                             NULL, NULL,
+                             MOJO_READ_MESSAGE_FLAG_NONE);
+    assert(result == MOJO_RESULT_OK);
+  }
+
+  static void MessagePipe_EmptyRead(void* closure) {
+    CorePerftest* self = static_cast<CorePerftest*>(closure);
+    MojoResult result MOJO_ALLOW_UNUSED;
+    result = MojoReadMessage(self->h0_,
+                             NULL, NULL,
+                             NULL, NULL,
+                             MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
+    assert(result == MOJO_RESULT_SHOULD_WAIT);
+  }
+
+ protected:
+#if !defined(WIN32)
+  void DoMessagePipeThreadedTest(unsigned num_writers,
+                                 unsigned num_readers,
+                                 uint32_t num_bytes) {
+    static const int64_t kPerftestTimeMicroseconds = 3 * 1000000;
+
+    assert(num_writers > 0);
+    assert(num_readers > 0);
+
+    MojoResult result MOJO_ALLOW_UNUSED;
+    result = MojoCreateMessagePipe(&h0_, &h1_);
+    assert(result == MOJO_RESULT_OK);
+
+    std::vector<MessagePipeWriterThread*> writers;
+    for (unsigned i = 0; i < num_writers; i++)
+      writers.push_back(new MessagePipeWriterThread(h0_, num_bytes));
+
+    std::vector<MessagePipeReaderThread*> readers;
+    for (unsigned i = 0; i < num_readers; i++)
+      readers.push_back(new MessagePipeReaderThread(h1_));
+
+    // Start time here, just before we fire off the threads.
+    const MojoTimeTicks start_time = MojoGetTimeTicksNow();
+
+    // Interleave the starts.
+    for (unsigned i = 0; i < num_writers || i < num_readers; i++) {
+      if (i < num_writers)
+        writers[i]->Start();
+      if (i < num_readers)
+        readers[i]->Start();
+    }
+
+    Sleep(kPerftestTimeMicroseconds);
+
+    // Close both handles to make writers and readers stop immediately.
+    result = MojoClose(h0_);
+    assert(result == MOJO_RESULT_OK);
+    result = MojoClose(h1_);
+    assert(result == MOJO_RESULT_OK);
+
+    // Join everything.
+    for (unsigned i = 0; i < num_writers; i++)
+      writers[i]->Join();
+    for (unsigned i = 0; i < num_readers; i++)
+      readers[i]->Join();
+
+    // Stop time here.
+    MojoTimeTicks end_time = MojoGetTimeTicksNow();
+
+    // Add up write and read counts, and destroy the threads.
+    int64_t num_writes = 0;
+    for (unsigned i = 0; i < num_writers; i++) {
+      num_writes += writers[i]->num_writes();
+      delete writers[i];
+    }
+    writers.clear();
+    int64_t num_reads = 0;
+    for (unsigned i = 0; i < num_readers; i++) {
+      num_reads += readers[i]->num_reads();
+      delete readers[i];
+    }
+    readers.clear();
+
+    char test_name[200];
+    sprintf(test_name, "MessagePipe_Threaded_Writes_%uw_%ur_%ubytes",
+            num_writers, num_readers, static_cast<unsigned>(num_bytes));
+    mojo::test::LogPerfResult(test_name,
+                              1000000.0 * static_cast<double>(num_writes) /
+                                  (end_time - start_time),
+                              "writes/second");
+    sprintf(test_name, "MessagePipe_Threaded_Reads_%uw_%ur_%ubytes",
+            num_writers, num_readers, static_cast<unsigned>(num_bytes));
+    mojo::test::LogPerfResult(test_name,
+                              1000000.0 * static_cast<double>(num_reads) /
+                                  (end_time - start_time),
+                                  "reads/second");
+  }
+#endif  // !defined(WIN32)
+
+  MojoHandle h0_;
+  MojoHandle h1_;
+
+  void* buffer_;
+  uint32_t num_bytes_;
+
+ private:
+#if !defined(WIN32)
+  void Sleep(int64_t microseconds) {
+    struct timespec req = {
+      static_cast<time_t>(microseconds / 1000000),  // Seconds.
+      static_cast<long>(microseconds % 1000000) * 1000L  // Nanoseconds.
+    };
+    int rv MOJO_ALLOW_UNUSED;
+    rv = nanosleep(&req, NULL);
+    assert(rv == 0);
+  }
+#endif  // !defined(WIN32)
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest);
+};
+
+// A no-op test so we can compare performance.
+TEST_F(CorePerftest, NoOp) {
+  mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this);
+}
+
+TEST_F(CorePerftest, MessagePipe_CreateAndClose) {
+  mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose",
+                                   &CorePerftest::MessagePipe_CreateAndClose,
+                                   this);
+}
+
+TEST_F(CorePerftest, MessagePipe_WriteAndRead) {
+  MojoResult result MOJO_ALLOW_UNUSED;
+  result = MojoCreateMessagePipe(&h0_, &h1_);
+  assert(result == MOJO_RESULT_OK);
+  char buffer[10000] = { 0 };
+  buffer_ = buffer;
+  num_bytes_ = 10u;
+  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10bytes",
+                                   &CorePerftest::MessagePipe_WriteAndRead,
+                                   this);
+  num_bytes_ = 100u;
+  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_100bytes",
+                                   &CorePerftest::MessagePipe_WriteAndRead,
+                                   this);
+  num_bytes_ = 1000u;
+  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_1000bytes",
+                                   &CorePerftest::MessagePipe_WriteAndRead,
+                                   this);
+  num_bytes_ = 10000u;
+  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10000bytes",
+                                   &CorePerftest::MessagePipe_WriteAndRead,
+                                   this);
+  result = MojoClose(h0_);
+  assert(result == MOJO_RESULT_OK);
+  result = MojoClose(h1_);
+  assert(result == MOJO_RESULT_OK);
+}
+
+TEST_F(CorePerftest, MessagePipe_EmptyRead) {
+  MojoResult result MOJO_ALLOW_UNUSED;
+  result = MojoCreateMessagePipe(&h0_, &h1_);
+  assert(result == MOJO_RESULT_OK);
+  mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead",
+                                   &CorePerftest::MessagePipe_EmptyRead,
+                                   this);
+  result = MojoClose(h0_);
+  assert(result == MOJO_RESULT_OK);
+  result = MojoClose(h1_);
+  assert(result == MOJO_RESULT_OK);
+}
+
+#if !defined(WIN32)
+TEST_F(CorePerftest, MessagePipe_Threaded) {
+  DoMessagePipeThreadedTest(1u, 1u, 100u);
+  DoMessagePipeThreadedTest(2u, 2u, 100u);
+  DoMessagePipeThreadedTest(3u, 3u, 100u);
+  DoMessagePipeThreadedTest(10u, 10u, 100u);
+  DoMessagePipeThreadedTest(10u, 1u, 100u);
+  DoMessagePipeThreadedTest(1u, 10u, 100u);
+
+  // For comparison of overhead:
+  DoMessagePipeThreadedTest(1u, 1u, 10u);
+  // 100 was done above.
+  DoMessagePipeThreadedTest(1u, 1u, 1000u);
+  DoMessagePipeThreadedTest(1u, 1u, 10000u);
+
+  DoMessagePipeThreadedTest(3u, 3u, 10u);
+  // 100 was done above.
+  DoMessagePipeThreadedTest(3u, 3u, 1000u);
+  DoMessagePipeThreadedTest(3u, 3u, 10000u);
+}
+#endif  // !defined(WIN32)
+
+}  // namespace
diff --git a/mojo/public/c/system/tests/core_unittest.cc b/mojo/public/c/system/tests/core_unittest.cc
new file mode 100644
index 0000000..c9acd00
--- /dev/null
+++ b/mojo/public/c/system/tests/core_unittest.cc
@@ -0,0 +1,286 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests the C API.
+
+#include "mojo/public/c/system/core.h"
+
+#include <string.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+TEST(CoreTest, GetTimeTicksNow) {
+  const MojoTimeTicks start = MojoGetTimeTicksNow();
+  EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
+      << "MojoGetTimeTicksNow should return nonzero value";
+}
+
+// The only handle that's guaranteed to be invalid is |MOJO_HANDLE_INVALID|.
+// Tests that everything that takes a handle properly recognizes it.
+TEST(CoreTest, InvalidHandle) {
+  MojoHandle h0, h1;
+  MojoWaitFlags wf;
+  char buffer[10] = { 0 };
+  uint32_t buffer_size;
+  void* write_pointer;
+  const void* read_pointer;
+
+  // Close:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(MOJO_HANDLE_INVALID));
+
+  // Wait:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoWait(MOJO_HANDLE_INVALID, MOJO_WAIT_FLAG_EVERYTHING, 1000000));
+  h0 = MOJO_HANDLE_INVALID;
+  wf = MOJO_WAIT_FLAG_EVERYTHING;
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoWaitMany(&h0, &wf, 1, MOJO_DEADLINE_INDEFINITE));
+
+  // Message pipe:
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoWriteMessage(h0, buffer, 3, NULL, 0,
+                             MOJO_WRITE_MESSAGE_FLAG_NONE));
+  buffer_size = static_cast<uint32_t>(sizeof(buffer));
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoReadMessage(h0, buffer, &buffer_size, NULL, NULL,
+                            MOJO_READ_MESSAGE_FLAG_NONE));
+
+  // Data pipe:
+  buffer_size = static_cast<uint32_t>(sizeof(buffer));
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoWriteData(h0, buffer, &buffer_size, MOJO_WRITE_DATA_FLAG_NONE));
+  write_pointer = NULL;
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoBeginWriteData(h0, &write_pointer, &buffer_size,
+                               MOJO_WRITE_DATA_FLAG_NONE));
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndWriteData(h0, 1));
+  buffer_size = static_cast<uint32_t>(sizeof(buffer));
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoReadData(h0, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
+  read_pointer = NULL;
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoBeginReadData(h0, &read_pointer, &buffer_size,
+                              MOJO_READ_DATA_FLAG_NONE));
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoEndReadData(h0, 1));
+
+  // Shared buffer:
+  h1 = MOJO_HANDLE_INVALID;
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoDuplicateBufferHandle(h0, NULL, &h1));
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoMapBuffer(h0, 0, 1, &write_pointer, MOJO_MAP_BUFFER_FLAG_NONE));
+}
+
+TEST(CoreTest, BasicMessagePipe) {
+  MojoHandle h0, h1;
+  MojoWaitFlags wf;
+  char buffer[10] = { 0 };
+  uint32_t buffer_size;
+
+  h0 = MOJO_HANDLE_INVALID;
+  h1 = MOJO_HANDLE_INVALID;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(&h0, &h1));
+  EXPECT_NE(h0, MOJO_HANDLE_INVALID);
+  EXPECT_NE(h1, MOJO_HANDLE_INVALID);
+
+  // Shouldn't be readable.
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+            MojoWait(h0, MOJO_WAIT_FLAG_READABLE, 0));
+
+  // Should be writable.
+  EXPECT_EQ(MOJO_RESULT_OK, MojoWait(h0, MOJO_WAIT_FLAG_WRITABLE, 0));
+
+  // Try to read.
+  buffer_size = static_cast<uint32_t>(sizeof(buffer));
+  EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
+            MojoReadMessage(h0, buffer, &buffer_size, NULL, NULL,
+                            MOJO_READ_MESSAGE_FLAG_NONE));
+
+  // Write to |h1|.
+  static const char kHello[] = "hello";
+  buffer_size = static_cast<uint32_t>(sizeof(kHello));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoWriteMessage(h1, kHello, buffer_size, NULL, 0,
+                             MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+  // |h0| should be readable.
+  wf = MOJO_WAIT_FLAG_READABLE;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoWaitMany(&h0, &wf, 1, MOJO_DEADLINE_INDEFINITE));
+
+  // Read from |h0|.
+  buffer_size = static_cast<uint32_t>(sizeof(buffer));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoReadMessage(h0, buffer, &buffer_size, NULL, NULL,
+                            MOJO_READ_MESSAGE_FLAG_NONE));
+  EXPECT_EQ(static_cast<uint32_t>(sizeof(kHello)), buffer_size);
+  EXPECT_STREQ(kHello, buffer);
+
+  // |h0| should no longer be readable.
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+            MojoWait(h0, MOJO_WAIT_FLAG_READABLE, 10));
+
+  // Close |h0|.
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0));
+
+  // |h1| should no longer be readable or writable.
+  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+            MojoWait(h1, MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE,
+                     1000));
+
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
+}
+
+TEST(CoreTest, BasicDataPipe) {
+  MojoHandle hp, hc;
+  MojoWaitFlags wf;
+  char buffer[20] = { 0 };
+  uint32_t buffer_size;
+  void* write_pointer;
+  const void* read_pointer;
+
+  hp = MOJO_HANDLE_INVALID;
+  hc = MOJO_HANDLE_INVALID;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateDataPipe(NULL, &hp, &hc));
+  EXPECT_NE(hp, MOJO_HANDLE_INVALID);
+  EXPECT_NE(hc, MOJO_HANDLE_INVALID);
+
+  // The consumer |hc| shouldn't be readable.
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+            MojoWait(hc, MOJO_WAIT_FLAG_READABLE, 0));
+
+  // The producer |hp| should be writable.
+  EXPECT_EQ(MOJO_RESULT_OK, MojoWait(hp, MOJO_WAIT_FLAG_WRITABLE, 0));
+
+  // Try to read from |hc|.
+  buffer_size = static_cast<uint32_t>(sizeof(buffer));
+  EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
+            MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
+
+  // Try to begin a two-phase read from |hc|.
+  read_pointer = NULL;
+  EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
+            MojoBeginReadData(hc, &read_pointer, &buffer_size,
+                              MOJO_READ_DATA_FLAG_NONE));
+
+  // Write to |hp|.
+  static const char kHello[] = "hello ";
+  // Don't include terminating null.
+  buffer_size = static_cast<uint32_t>(strlen(kHello));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoWriteData(hp, kHello, &buffer_size,
+                          MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+  // |hc| should be(come) readable.
+  wf = MOJO_WAIT_FLAG_READABLE;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoWaitMany(&hc, &wf, 1, MOJO_DEADLINE_INDEFINITE));
+
+  // Do a two-phase write to |hp|.
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoBeginWriteData(hp, &write_pointer, &buffer_size,
+                               MOJO_WRITE_DATA_FLAG_NONE));
+  static const char kWorld[] = "world";
+  ASSERT_GE(buffer_size, sizeof(kWorld));
+  // Include the terminating null.
+  memcpy(write_pointer, kWorld, sizeof(kWorld));
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoEndWriteData(hp, static_cast<uint32_t>(sizeof(kWorld))));
+
+  // Read one character from |hc|.
+  memset(buffer, 0, sizeof(buffer));
+  buffer_size = 1;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoReadData(hc, buffer, &buffer_size, MOJO_READ_DATA_FLAG_NONE));
+
+  // Close |hp|.
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hp));
+
+  // |hc| should still be readable.
+  EXPECT_EQ(MOJO_RESULT_OK, MojoWait(hc, MOJO_WAIT_FLAG_READABLE, 0));
+
+  // Do a two-phase read from |hc|.
+  read_pointer = NULL;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoBeginReadData(hc, &read_pointer, &buffer_size,
+                              MOJO_READ_DATA_FLAG_NONE));
+  ASSERT_LE(buffer_size, sizeof(buffer) - 1);
+  memcpy(&buffer[1], read_pointer, buffer_size);
+  EXPECT_EQ(MOJO_RESULT_OK, MojoEndReadData(hc, buffer_size));
+  EXPECT_STREQ("hello world", buffer);
+
+  // |hc| should no longer be readable.
+  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+            MojoWait(hc, MOJO_WAIT_FLAG_READABLE, 1000));
+
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(hc));
+
+  // TODO(vtl): Test the other way around -- closing the consumer should make
+  // the producer never-writable?
+}
+
+TEST(CoreTest, BasicSharedBuffer) {
+  MojoHandle h0, h1;
+  void* pointer;
+
+  // Create a shared buffer (|h0|).
+  h0 = MOJO_HANDLE_INVALID;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateSharedBuffer(NULL, 100, &h0));
+  EXPECT_NE(h0, MOJO_HANDLE_INVALID);
+
+  // Map everything.
+  pointer = NULL;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoMapBuffer(h0, 0, 100, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
+  ASSERT_TRUE(pointer);
+  static_cast<char*>(pointer)[50] = 'x';
+
+  // Duplicate |h0| to |h1|.
+  h1 = MOJO_HANDLE_INVALID;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoDuplicateBufferHandle(h0, NULL, &h1));
+  EXPECT_NE(h1, MOJO_HANDLE_INVALID);
+
+  // Close |h0|.
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0));
+
+  // The mapping should still be good.
+  static_cast<char*>(pointer)[51] = 'y';
+
+  // Unmap it.
+  // TODO(vtl): Not yet implemented.
+  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, MojoUnmapBuffer(pointer));
+
+  // Map half of |h1|.
+  pointer = NULL;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoMapBuffer(h1, 50, 50, &pointer, MOJO_MAP_BUFFER_FLAG_NONE));
+  ASSERT_TRUE(pointer);
+
+  // It should have what we wrote.
+  EXPECT_EQ('x', static_cast<char*>(pointer)[0]);
+  EXPECT_EQ('y', static_cast<char*>(pointer)[1]);
+
+  // Unmap it.
+  // TODO(vtl): Not yet implemented.
+  EXPECT_EQ(MOJO_RESULT_UNIMPLEMENTED, MojoUnmapBuffer(pointer));
+
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
+}
+
+// Defined in core_unittest_pure_c.c.
+extern "C" const char* MinimalCTest(void);
+
+// This checks that things actually work in C (not C++).
+TEST(CoreTest, MinimalCTest) {
+  const char* failure = MinimalCTest();
+  EXPECT_TRUE(failure == NULL) << failure;
+}
+
+// TODO(vtl): Add multi-threaded tests.
+
+}  // namespace
+}  // namespace mojo
diff --git a/mojo/public/c/system/tests/core_unittest_pure_c.c b/mojo/public/c/system/tests/core_unittest_pure_c.c
new file mode 100644
index 0000000..7293ff2
--- /dev/null
+++ b/mojo/public/c/system/tests/core_unittest_pure_c.c
@@ -0,0 +1,88 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifdef __cplusplus
+#error "This file should be compiled as C, not C++."
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+// Include all the header files that are meant to be compilable as C. Start with
+// core.h, since it's the most important one.
+#include "mojo/public/c/system/core.h"
+#include "mojo/public/c/system/async_waiter.h"
+#include "mojo/public/c/system/macros.h"
+
+// The joys of the C preprocessor....
+#define STRINGIFY(x) #x
+#define STRINGIFY2(x) STRINGIFY(x)
+#define FAILURE(message) \
+  __FILE__ "(" STRINGIFY2(__LINE__) "): Failure: " message
+
+// Poor man's gtest.
+#define EXPECT_EQ(a, b) \
+  do { \
+    if ((a) != (b)) \
+      return FAILURE(STRINGIFY(a) " != " STRINGIFY(b) " (expected ==)"); \
+  } while (0)
+#define EXPECT_NE(a, b) \
+  do { \
+    if ((a) == (b)) \
+      return FAILURE(STRINGIFY(a) " == " STRINGIFY(b) " (expected !=)"); \
+  } while (0)
+
+// This function exists mainly to be compiled and linked. We do some cursory
+// checks and call it from a unit test, to make sure that link problems aren't
+// missed due to deadstripping. Returns null on success and a string on failure
+// (describing the failure).
+const char* MinimalCTest(void) {
+  // MSVS before 2013 *really* only supports C90: All variables must be declared
+  // at the top. (MSVS 2013 is more reasonable.)
+  MojoTimeTicks ticks;
+  MojoHandle handle0, handle1;
+  MojoWaitFlags wait_flags;
+  const char kHello[] = "hello";
+  char buffer[200] = { 0 };
+  uint32_t num_bytes;
+
+  ticks = MojoGetTimeTicksNow();
+  EXPECT_NE(ticks, 0);
+
+  handle0 = MOJO_HANDLE_INVALID;
+  EXPECT_NE(MOJO_RESULT_OK, MojoClose(handle0));
+
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            MojoWait(handle0, MOJO_WAIT_FLAG_EVERYTHING,
+                     MOJO_DEADLINE_INDEFINITE));
+
+  handle1 = MOJO_HANDLE_INVALID;
+  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(&handle0, &handle1));
+
+  wait_flags = MOJO_WAIT_FLAG_READABLE;
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+            MojoWaitMany(&handle0, &wait_flags, 1, 1));
+
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoWriteMessage(handle0, kHello, (uint32_t) sizeof(kHello), NULL,
+                             0u, MOJO_WRITE_DATA_FLAG_NONE));
+
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoWait(handle1, MOJO_WAIT_FLAG_READABLE,
+                     MOJO_DEADLINE_INDEFINITE));
+
+  num_bytes = (uint32_t) sizeof(buffer);
+  EXPECT_EQ(MOJO_RESULT_OK,
+            MojoReadMessage(handle1, buffer, &num_bytes, NULL, NULL,
+                            MOJO_READ_MESSAGE_FLAG_NONE));
+  EXPECT_EQ((uint32_t) sizeof(kHello), num_bytes);
+  EXPECT_EQ(0, memcmp(buffer, kHello, sizeof(kHello)));
+
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle0));
+  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle1));
+
+  // TODO(vtl): data pipe
+
+  return NULL;
+}
diff --git a/mojo/public/c/system/tests/macros_unittest.cc b/mojo/public/c/system/tests/macros_unittest.cc
new file mode 100644
index 0000000..5225b67
--- /dev/null
+++ b/mojo/public/c/system/tests/macros_unittest.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests the C Mojo system macros and consists of "positive" tests,
+// i.e., those verifying that things work (without compile errors, or even
+// warnings if warnings are treated as errors).
+// TODO(vtl): Fix no-compile tests (which are all disabled; crbug.com/105388)
+// and write some "negative" tests.
+
+#include "mojo/public/c/system/macros.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+TEST(MacrosTest, AllowUnused) {
+  // Test that no warning/error is issued even though |x| is unused.
+  int x MOJO_ALLOW_UNUSED = 123;
+}
+
+int MustUseReturnedResult() MOJO_WARN_UNUSED_RESULT;
+int MustUseReturnedResult() {
+  return 456;
+}
+
+TEST(MacrosTest, WarnUnusedResult) {
+  if (!MustUseReturnedResult())
+    abort();
+}
+
+// First test |MOJO_COMPILE_ASSERT()| in a global scope.
+MOJO_COMPILE_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t),
+                    bad_compile_assert_failure_in_global_scope);
+
+TEST(MacrosTest, CompileAssert) {
+  // Then in a local scope.
+  MOJO_COMPILE_ASSERT(sizeof(int32_t) == 2 * sizeof(int16_t),
+                      bad_compile_assert_failure);
+}
+
+}  // namespace
+}  // namespace mojo
diff --git a/mojo/public/cpp/DEPS b/mojo/public/cpp/DEPS
new file mode 100644
index 0000000..c5aa397
--- /dev/null
+++ b/mojo/public/cpp/DEPS
@@ -0,0 +1,7 @@
+include_rules = [
+  # Require explicit dependencies in each directory.
+  "-mojo/public",
+  # But everyone can depend on the C and C++ system headers.
+  "+mojo/public/c/system",
+  "+mojo/public/cpp/system",
+]
diff --git a/mojo/public/cpp/environment/buffer_tls.h b/mojo/public/cpp/environment/buffer_tls.h
new file mode 100644
index 0000000..42cf826
--- /dev/null
+++ b/mojo/public/cpp/environment/buffer_tls.h
@@ -0,0 +1,20 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_BUFFER_TLS_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_BUFFER_TLS_H_
+
+namespace mojo {
+class Buffer;
+
+namespace internal {
+
+// Get/Set the |Buffer*| associated with current thread.
+Buffer* GetCurrentBuffer();
+Buffer* SetCurrentBuffer(Buffer* buffer);
+
+}  // namespace internal
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_BUFFER_TLS_H_
diff --git a/mojo/public/cpp/environment/default_async_waiter.h b/mojo/public/cpp/environment/default_async_waiter.h
new file mode 100644
index 0000000..d7f48bf
--- /dev/null
+++ b/mojo/public/cpp/environment/default_async_waiter.h
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
+
+#include "mojo/public/c/system/async_waiter.h"
+
+namespace mojo {
+
+// Returns a default implementation of MojoAsyncWaiter.
+MojoAsyncWaiter* GetDefaultAsyncWaiter();
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
diff --git a/mojo/public/cpp/environment/environment.h b/mojo/public/cpp/environment/environment.h
new file mode 100644
index 0000000..f75e2f7
--- /dev/null
+++ b/mojo/public/cpp/environment/environment.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// This class must be instantiated before using any Mojo APIs.
+class Environment {
+ public:
+  Environment();
+  ~Environment();
+
+ private:
+  MOJO_DISALLOW_COPY_AND_ASSIGN(Environment);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_ENVIRONMENT_H_
diff --git a/mojo/public/cpp/environment/lib/DEPS b/mojo/public/cpp/environment/lib/DEPS
new file mode 100644
index 0000000..1889e1f
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+mojo/public/cpp/environment",
+  "+mojo/public/cpp/utility",
+]
diff --git a/mojo/public/cpp/environment/lib/buffer_tls.cc b/mojo/public/cpp/environment/lib/buffer_tls.cc
new file mode 100644
index 0000000..d54faba
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/buffer_tls.cc
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/environment/buffer_tls.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/environment/lib/buffer_tls_setup.h"
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+
+namespace mojo {
+namespace internal {
+
+static ThreadLocalPointer<Buffer> current_buffer;
+
+void SetUpCurrentBuffer() {
+  current_buffer.Allocate();
+}
+
+void TearDownCurrentBuffer() {
+  assert(!current_buffer.Get());
+  current_buffer.Free();
+}
+
+Buffer* GetCurrentBuffer() {
+  return current_buffer.Get();
+}
+
+Buffer* SetCurrentBuffer(Buffer* buf) {
+  Buffer* old_buf = current_buffer.Get();
+  current_buffer.Set(buf);
+  return old_buf;
+}
+
+}  // namespace internal
+}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/buffer_tls_setup.h b/mojo/public/cpp/environment/lib/buffer_tls_setup.h
new file mode 100644
index 0000000..f0ca0b1
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/buffer_tls_setup.h
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
+#define MOJO_PUBLIC_CPP_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
+
+namespace mojo {
+namespace internal {
+
+void SetUpCurrentBuffer();
+void TearDownCurrentBuffer();
+
+}  // namespace internal
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
diff --git a/mojo/public/cpp/environment/lib/default_async_waiter.cc b/mojo/public/cpp/environment/lib/default_async_waiter.cc
new file mode 100644
index 0000000..73e41de
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/default_async_waiter.cc
@@ -0,0 +1,93 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/environment/default_async_waiter.h"
+
+#include <assert.h>
+
+#include "mojo/public/cpp/utility/run_loop.h"
+#include "mojo/public/cpp/utility/run_loop_handler.h"
+
+namespace mojo {
+namespace {
+
+// RunLoopHandler implementation used for a request to AsyncWait(). There are
+// two ways RunLoopHandlerImpl is deleted:
+// . when the handle is ready (or errored).
+// . when CancelWait() is invoked.
+class RunLoopHandlerImpl : public RunLoopHandler {
+ public:
+  RunLoopHandlerImpl(const Handle& handle,
+                     MojoAsyncWaitCallback callback,
+                     void* closure)
+      : handle_(handle),
+        callback_(callback),
+        closure_(closure) {
+  }
+
+  virtual ~RunLoopHandlerImpl() {
+    RunLoop::current()->RemoveHandler(handle_);
+  }
+
+  // RunLoopHandler:
+  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
+    NotifyCallback(MOJO_RESULT_OK);
+  }
+
+  virtual void OnHandleError(const Handle& handle,
+                             MojoResult result) MOJO_OVERRIDE {
+    NotifyCallback(result);
+  }
+
+ private:
+  void NotifyCallback(MojoResult result) {
+    // Delete this to unregister the handle. That way if the callback
+    // reregisters everything is ok.
+    MojoAsyncWaitCallback callback = callback_;
+    void* closure = closure_;
+    delete this;
+
+    callback(closure, result);
+  }
+
+  const Handle handle_;
+  MojoAsyncWaitCallback callback_;
+  void* closure_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoopHandlerImpl);
+};
+
+MojoAsyncWaitID AsyncWait(MojoAsyncWaiter* waiter,
+                          MojoHandle handle,
+                          MojoWaitFlags flags,
+                          MojoDeadline deadline,
+                          MojoAsyncWaitCallback callback,
+                          void* closure) {
+  RunLoop* run_loop = RunLoop::current();
+  assert(run_loop);
+
+  // |run_loop_handler| is destroyed either when the handle is ready or if
+  // CancelWait is invoked.
+  RunLoopHandlerImpl* run_loop_handler =
+      new RunLoopHandlerImpl(Handle(handle), callback, closure);
+  run_loop->AddHandler(run_loop_handler, Handle(handle), flags, deadline);
+  return reinterpret_cast<MojoAsyncWaitID>(run_loop_handler);
+}
+
+void CancelWait(MojoAsyncWaiter* waiter, MojoAsyncWaitID wait_id) {
+  delete reinterpret_cast<RunLoopHandlerImpl*>(wait_id);
+}
+
+MojoAsyncWaiter s_default_async_waiter = {
+  AsyncWait,
+  CancelWait
+};
+
+}  // namespace
+
+MojoAsyncWaiter* GetDefaultAsyncWaiter() {
+  return &s_default_async_waiter;
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/environment/lib/environment.cc b/mojo/public/cpp/environment/lib/environment.cc
new file mode 100644
index 0000000..b3148af
--- /dev/null
+++ b/mojo/public/cpp/environment/lib/environment.cc
@@ -0,0 +1,22 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/environment/environment.h"
+
+#include "mojo/public/cpp/environment/lib/buffer_tls_setup.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+
+namespace mojo {
+
+Environment::Environment() {
+  internal::SetUpCurrentBuffer();
+  RunLoop::SetUp();
+}
+
+Environment::~Environment() {
+  RunLoop::TearDown();
+  internal::TearDownCurrentBuffer();
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/environment/tests/DEPS b/mojo/public/cpp/environment/tests/DEPS
new file mode 100644
index 0000000..9266146
--- /dev/null
+++ b/mojo/public/cpp/environment/tests/DEPS
@@ -0,0 +1,6 @@
+include_rules = [
+  "+testing",
+  "+mojo/public/cpp/utility",
+  # TODO(vtl): Temporary until these are moved to mojo/public/cpp:
+  "+mojo/public/tests",
+]
diff --git a/mojo/public/cpp/environment/tests/async_waiter_unittest.cc b/mojo/public/cpp/environment/tests/async_waiter_unittest.cc
new file mode 100644
index 0000000..444fdef
--- /dev/null
+++ b/mojo/public/cpp/environment/tests/async_waiter_unittest.cc
@@ -0,0 +1,118 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "mojo/public/cpp/environment/default_async_waiter.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+#include "mojo/public/tests/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+class TestAsyncWaitCallback {
+ public:
+  TestAsyncWaitCallback() : result_count_(0), last_result_(MOJO_RESULT_OK) {
+  }
+  virtual ~TestAsyncWaitCallback() {}
+
+  int result_count() const { return result_count_; }
+
+  MojoResult last_result() const { return last_result_; }
+
+  // MojoAsyncWaitCallback:
+  static void OnHandleReady(void* closure, MojoResult result) {
+    TestAsyncWaitCallback* self = static_cast<TestAsyncWaitCallback*>(closure);
+    self->result_count_++;
+    self->last_result_ = result;
+  }
+
+ private:
+  int result_count_;
+  MojoResult last_result_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(TestAsyncWaitCallback);
+};
+
+MojoAsyncWaitID CallAsyncWait(const Handle& handle,
+                              MojoWaitFlags flags,
+                              TestAsyncWaitCallback* callback) {
+  MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter();
+  return waiter->AsyncWait(waiter,
+                           handle.value(),
+                           flags,
+                           MOJO_DEADLINE_INDEFINITE,
+                           &TestAsyncWaitCallback::OnHandleReady,
+                           callback);
+}
+
+void CallCancelWait(MojoAsyncWaitID wait_id) {
+  MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter();
+  waiter->CancelWait(waiter, wait_id);
+}
+
+class AsyncWaiterTest : public testing::Test {
+ public:
+  AsyncWaiterTest() {}
+
+ private:
+  Environment environment_;
+  RunLoop run_loop_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterTest);
+};
+
+// Verifies AsyncWaitCallback is notified when pipe is ready.
+TEST_F(AsyncWaiterTest, CallbackNotified) {
+  TestAsyncWaitCallback callback;
+  MessagePipe test_pipe;
+  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
+
+  CallAsyncWait(test_pipe.handle0.get(),
+                MOJO_WAIT_FLAG_READABLE,
+                &callback);
+  RunLoop::current()->Run();
+  EXPECT_EQ(1, callback.result_count());
+  EXPECT_EQ(MOJO_RESULT_OK, callback.last_result());
+}
+
+// Verifies 2 AsyncWaitCallbacks are notified when there pipes are ready.
+TEST_F(AsyncWaiterTest, TwoCallbacksNotified) {
+  TestAsyncWaitCallback callback1;
+  TestAsyncWaitCallback callback2;
+  MessagePipe test_pipe1;
+  MessagePipe test_pipe2;
+  EXPECT_TRUE(test::WriteTextMessage(test_pipe1.handle1.get(), std::string()));
+  EXPECT_TRUE(test::WriteTextMessage(test_pipe2.handle1.get(), std::string()));
+
+  CallAsyncWait(test_pipe1.handle0.get(), MOJO_WAIT_FLAG_READABLE, &callback1);
+  CallAsyncWait(test_pipe2.handle0.get(), MOJO_WAIT_FLAG_READABLE, &callback2);
+
+  RunLoop::current()->Run();
+  EXPECT_EQ(1, callback1.result_count());
+  EXPECT_EQ(MOJO_RESULT_OK, callback1.last_result());
+  EXPECT_EQ(1, callback2.result_count());
+  EXPECT_EQ(MOJO_RESULT_OK, callback2.last_result());
+}
+
+// Verifies cancel works.
+TEST_F(AsyncWaiterTest, CancelCallback) {
+  TestAsyncWaitCallback callback;
+  MessagePipe test_pipe;
+  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
+
+  CallCancelWait(
+      CallAsyncWait(test_pipe.handle0.get(),
+                    MOJO_WAIT_FLAG_READABLE,
+                    &callback));
+  RunLoop::current()->Run();
+  EXPECT_EQ(0, callback.result_count());
+}
+
+}  // namespace
+}  // namespace mojo
diff --git a/mojo/public/cpp/system/core.h b/mojo/public/cpp/system/core.h
new file mode 100644
index 0000000..7022110
--- /dev/null
+++ b/mojo/public/cpp/system/core.h
@@ -0,0 +1,467 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
+#define MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
+
+#include <assert.h>
+#include <stddef.h>
+
+#include <limits>
+
+#include "mojo/public/c/system/core.h"
+#include "mojo/public/c/system/system_export.h"
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// Standalone functions --------------------------------------------------------
+
+inline MojoTimeTicks GetTimeTicksNow() {
+  return MojoGetTimeTicksNow();
+}
+
+// ScopedHandleBase ------------------------------------------------------------
+
+// Scoper for the actual handle types defined further below. It's move-only,
+// like the C++11 |unique_ptr|.
+template <class HandleType>
+class ScopedHandleBase {
+  MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue)
+
+ public:
+  ScopedHandleBase() {}
+  explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
+  ~ScopedHandleBase() { CloseIfNecessary(); }
+
+  template <class CompatibleHandleType>
+  explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other)
+      : handle_(other.release()) {
+  }
+
+  // Move-only constructor and operator=.
+  ScopedHandleBase(RValue other) : handle_(other.object->release()) {}
+  ScopedHandleBase& operator=(RValue other) {
+    handle_ = other.object->release();
+    return *this;
+  }
+
+  const HandleType& get() const { return handle_; }
+
+  void swap(ScopedHandleBase& other) {
+    handle_.swap(other.handle_);
+  }
+
+  HandleType release() MOJO_WARN_UNUSED_RESULT {
+    HandleType rv;
+    rv.swap(handle_);
+    return rv;
+  }
+
+  void reset(HandleType handle = HandleType()) {
+    CloseIfNecessary();
+    handle_ = handle;
+  }
+
+  bool is_valid() const {
+    return handle_.is_valid();
+  }
+
+ private:
+  void CloseIfNecessary() {
+    if (!handle_.is_valid())
+      return;
+    MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value());
+    assert(result == MOJO_RESULT_OK);
+  }
+
+  HandleType handle_;
+};
+
+template <typename HandleType>
+inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
+  return ScopedHandleBase<HandleType>(handle);
+}
+
+// Handle ----------------------------------------------------------------------
+
+const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
+
+// Wrapper base class for |MojoHandle|.
+class Handle {
+ public:
+  Handle() : value_(MOJO_HANDLE_INVALID) {}
+  explicit Handle(MojoHandle value) : value_(value) {}
+  ~Handle() {}
+
+  void swap(Handle& other) {
+    MojoHandle temp = value_;
+    value_ = other.value_;
+    other.value_ = temp;
+  }
+
+  bool is_valid() const {
+    return value_ != MOJO_HANDLE_INVALID;
+  }
+
+  MojoHandle value() const { return value_; }
+  MojoHandle* mutable_value() { return &value_; }
+  void set_value(MojoHandle value) { value_ = value; }
+
+ private:
+  MojoHandle value_;
+
+  // Copying and assignment allowed.
+};
+
+// Should have zero overhead.
+MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
+                    bad_size_for_cpp_Handle);
+
+// The scoper should also impose no more overhead.
+typedef ScopedHandleBase<Handle> ScopedHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle),
+                    bad_size_for_cpp_ScopedHandle);
+
+inline MojoResult Wait(const Handle& handle,
+                       MojoWaitFlags flags,
+                       MojoDeadline deadline) {
+  return MojoWait(handle.value(), flags, deadline);
+}
+
+// |HandleVectorType| and |FlagsVectorType| should be similar enough to
+// |std::vector<Handle>| and |std::vector<MojoWaitFlags>|, respectively:
+//  - They should have a (const) |size()| method that returns an unsigned type.
+//  - They must provide contiguous storage, with access via (const) reference to
+//    that storage provided by a (const) |operator[]()| (by reference).
+template <class HandleVectorType, class FlagsVectorType>
+inline MojoResult WaitMany(const HandleVectorType& handles,
+                           const FlagsVectorType& flags,
+                           MojoDeadline deadline) {
+  if (flags.size() != handles.size())
+    return MOJO_RESULT_INVALID_ARGUMENT;
+  if (handles.size() > std::numeric_limits<uint32_t>::max())
+    return MOJO_RESULT_OUT_OF_RANGE;
+
+  if (handles.size() == 0)
+    return MojoWaitMany(NULL, NULL, 0, deadline);
+
+  const Handle& first_handle = handles[0];
+  const MojoWaitFlags& first_flag = flags[0];
+  return MojoWaitMany(reinterpret_cast<const MojoHandle*>(&first_handle),
+                      reinterpret_cast<const MojoWaitFlags*>(&first_flag),
+                      static_cast<uint32_t>(handles.size()),
+                      deadline);
+}
+
+// |Close()| takes ownership of the handle, since it'll invalidate it.
+// Note: There's nothing to do, since the argument will be destroyed when it
+// goes out of scope.
+template <class HandleType>
+inline void Close(ScopedHandleBase<HandleType> /*handle*/) {}
+
+// Most users should typically use |Close()| (above) instead.
+inline MojoResult CloseRaw(Handle handle) {
+  return MojoClose(handle.value());
+}
+
+// Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s,
+// etc.
+inline bool operator<(const Handle& a, const Handle& b) {
+  return a.value() < b.value();
+}
+
+// MessagePipeHandle -----------------------------------------------------------
+
+class MessagePipeHandle : public Handle {
+ public:
+  MessagePipeHandle() {}
+  explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
+
+  // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle),
+                    bad_size_for_cpp_MessagePipeHandle);
+
+typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) ==
+                        sizeof(MessagePipeHandle),
+                    bad_size_for_cpp_ScopedMessagePipeHandle);
+
+inline MojoResult CreateMessagePipe(ScopedMessagePipeHandle* message_pipe0,
+                                    ScopedMessagePipeHandle* message_pipe1) {
+  assert(message_pipe0);
+  assert(message_pipe1);
+  MessagePipeHandle handle0;
+  MessagePipeHandle handle1;
+  MojoResult rv = MojoCreateMessagePipe(handle0.mutable_value(),
+                                        handle1.mutable_value());
+  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+  // will be used).
+  message_pipe0->reset(handle0);
+  message_pipe1->reset(handle1);
+  return rv;
+}
+
+// These "raw" versions fully expose the underlying API, but don't help with
+// ownership of handles (especially when writing messages).
+// TODO(vtl): Write "baked" versions.
+inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe,
+                                  const void* bytes,
+                                  uint32_t num_bytes,
+                                  const MojoHandle* handles,
+                                  uint32_t num_handles,
+                                  MojoWriteMessageFlags flags) {
+  return MojoWriteMessage(message_pipe.value(), bytes, num_bytes, handles,
+                          num_handles, flags);
+}
+
+inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe,
+                                 void* bytes,
+                                 uint32_t* num_bytes,
+                                 MojoHandle* handles,
+                                 uint32_t* num_handles,
+                                 MojoReadMessageFlags flags) {
+  return MojoReadMessage(message_pipe.value(), bytes, num_bytes, handles,
+                         num_handles, flags);
+}
+
+// A wrapper class that automatically creates a message pipe and owns both
+// handles.
+class MessagePipe {
+ public:
+  MessagePipe();
+  ~MessagePipe();
+
+  ScopedMessagePipeHandle handle0;
+  ScopedMessagePipeHandle handle1;
+};
+
+inline MessagePipe::MessagePipe() {
+  MojoResult result MOJO_ALLOW_UNUSED = CreateMessagePipe(&handle0, &handle1);
+  assert(result == MOJO_RESULT_OK);
+}
+
+inline MessagePipe::~MessagePipe() {
+}
+
+// DataPipeProducerHandle and DataPipeConsumerHandle ---------------------------
+
+class DataPipeProducerHandle : public Handle {
+ public:
+  DataPipeProducerHandle() {}
+  explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {}
+
+  // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle),
+                    bad_size_for_cpp_DataPipeProducerHandle);
+
+typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) ==
+                        sizeof(DataPipeProducerHandle),
+                    bad_size_for_cpp_ScopedDataPipeProducerHandle);
+
+class DataPipeConsumerHandle : public Handle {
+ public:
+  DataPipeConsumerHandle() {}
+  explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {}
+
+  // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle),
+                    bad_size_for_cpp_DataPipeConsumerHandle);
+
+typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) ==
+                        sizeof(DataPipeConsumerHandle),
+                    bad_size_for_cpp_ScopedDataPipeConsumerHandle);
+
+inline MojoResult CreateDataPipe(
+    const MojoCreateDataPipeOptions* options,
+    ScopedDataPipeProducerHandle* data_pipe_producer,
+    ScopedDataPipeConsumerHandle* data_pipe_consumer) {
+  assert(data_pipe_producer);
+  assert(data_pipe_consumer);
+  DataPipeProducerHandle producer_handle;
+  DataPipeConsumerHandle consumer_handle;
+  MojoResult rv = MojoCreateDataPipe(options, producer_handle.mutable_value(),
+                                     consumer_handle.mutable_value());
+  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+  // will be used).
+  data_pipe_producer->reset(producer_handle);
+  data_pipe_consumer->reset(consumer_handle);
+  return rv;
+}
+
+inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer,
+                               const void* elements,
+                               uint32_t* num_bytes,
+                               MojoWriteDataFlags flags) {
+  return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags);
+}
+
+inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
+                                    void** buffer,
+                                    uint32_t* buffer_num_bytes,
+                                    MojoWriteDataFlags flags) {
+  return MojoBeginWriteData(data_pipe_producer.value(), buffer,
+                            buffer_num_bytes, flags);
+}
+
+inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
+                                  uint32_t num_bytes_written) {
+  return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written);
+}
+
+inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
+                              void* elements,
+                              uint32_t* num_bytes,
+                              MojoReadDataFlags flags) {
+  return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags);
+}
+
+inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
+                                   const void** buffer,
+                                   uint32_t* buffer_num_bytes,
+                                   MojoReadDataFlags flags) {
+  return MojoBeginReadData(data_pipe_consumer.value(), buffer, buffer_num_bytes,
+                           flags);
+}
+
+inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
+                                 uint32_t num_bytes_read) {
+  return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read);
+}
+
+// A wrapper class that automatically creates a data pipe and owns both handles.
+// TODO(vtl): Make an even more friendly version? (Maybe templatized for a
+// particular type instead of some "element"? Maybe functions that take
+// vectors?)
+class DataPipe {
+ public:
+  DataPipe();
+  explicit DataPipe(const MojoCreateDataPipeOptions& options);
+  ~DataPipe();
+
+  ScopedDataPipeProducerHandle producer_handle;
+  ScopedDataPipeConsumerHandle consumer_handle;
+};
+
+inline DataPipe::DataPipe() {
+  MojoResult result MOJO_ALLOW_UNUSED =
+      CreateDataPipe(NULL, &producer_handle, &consumer_handle);
+  assert(result == MOJO_RESULT_OK);
+}
+
+inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) {
+  MojoResult result MOJO_ALLOW_UNUSED =
+      CreateDataPipe(&options, &producer_handle, &consumer_handle);
+  assert(result == MOJO_RESULT_OK);
+}
+
+inline DataPipe::~DataPipe() {
+}
+
+// SharedBufferHandle ----------------------------------------------------------
+
+class SharedBufferHandle : public Handle {
+ public:
+  SharedBufferHandle() {}
+  explicit SharedBufferHandle(MojoHandle value) : Handle(value) {}
+
+  // Copying and assignment allowed.
+};
+
+MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle),
+                    bad_size_for_cpp_SharedBufferHandle);
+
+typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
+MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) ==
+                        sizeof(SharedBufferHandle),
+                    bad_size_for_cpp_ScopedSharedBufferHandle);
+
+inline MojoResult CreateSharedBuffer(
+    const MojoCreateSharedBufferOptions* options,
+    uint64_t num_bytes,
+    ScopedSharedBufferHandle* shared_buffer) {
+  assert(shared_buffer);
+  SharedBufferHandle handle;
+  MojoResult rv = MojoCreateSharedBuffer(options, num_bytes,
+                                         handle.mutable_value());
+  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+  // will be used).
+  shared_buffer->reset(handle);
+  return rv;
+}
+
+// TODO(vtl): This (and also the functions below) are templatized to allow for
+// future/other buffer types. A bit "safer" would be to overload this function
+// manually. (The template enforces that the in and out handles to be of the
+// same type.)
+template <class BufferHandleType>
+inline MojoResult DuplicatedBuffer(
+    BufferHandleType buffer,
+    const MojoDuplicateBufferHandleOptions* options,
+    ScopedHandleBase<BufferHandleType>* new_buffer) {
+  assert(new_buffer);
+  BufferHandleType handle;
+  MojoResult rv = MojoDuplicateSharedBuffer(buffer.value(), options,
+                                            handle.mutable_value());
+  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
+  // will be used).
+  new_buffer->reset(handle);
+  return rv;
+}
+
+template <class BufferHandleType>
+inline MojoResult MapBuffer(BufferHandleType buffer,
+                            uint64_t offset,
+                            uint64_t num_bytes,
+                            void** pointer,
+                            MojoMapBufferFlags flags) {
+  assert(buffer);
+  return MojoMapBuffer(buffer.value(), offset, num_bytes, pointer, flags);
+}
+
+inline MojoResult UnmapBuffer(void* pointer) {
+  assert(pointer);
+  return MojoUnmapBuffer(pointer);
+}
+
+// A wrapper class that automatically creates a shared buffer and owns the
+// handle.
+class SharedBuffer {
+ public:
+  explicit SharedBuffer(uint64_t num_bytes);
+  SharedBuffer(uint64_t num_bytes,
+               const MojoCreateSharedBufferOptions& options);
+  ~SharedBuffer();
+
+  ScopedSharedBufferHandle handle;
+};
+
+inline SharedBuffer::SharedBuffer(uint64_t num_bytes) {
+  MojoResult result MOJO_ALLOW_UNUSED =
+      CreateSharedBuffer(NULL, num_bytes, &handle);
+  assert(result == MOJO_RESULT_OK);
+}
+
+inline SharedBuffer::SharedBuffer(
+    uint64_t num_bytes,
+    const MojoCreateSharedBufferOptions& options) {
+  MojoResult result MOJO_ALLOW_UNUSED =
+      CreateSharedBuffer(&options, num_bytes, &handle);
+  assert(result == MOJO_RESULT_OK);
+}
+
+inline SharedBuffer::~SharedBuffer() {
+}
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_SYSTEM_CORE_H_
diff --git a/mojo/public/cpp/system/macros.h b/mojo/public/cpp/system/macros.h
new file mode 100644
index 0000000..ac4f3db
--- /dev/null
+++ b/mojo/public/cpp/system/macros.h
@@ -0,0 +1,53 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_SYSTEM_MACROS_H_
+#define MOJO_PUBLIC_CPP_SYSTEM_MACROS_H_
+
+#include "mojo/public/c/system/macros.h"
+
+// Annotate a virtual method indicating it must be overriding a virtual method
+// in the parent class. Use like:
+//   virtual void foo() OVERRIDE;
+#if defined(_MSC_VER) || defined(__clang__)
+#define MOJO_OVERRIDE override
+#else
+#define MOJO_OVERRIDE
+#endif
+
+// A macro to disallow the copy constructor and operator= functions.
+// This should be used in the private: declarations for a class.
+#define MOJO_DISALLOW_COPY_AND_ASSIGN(TypeName) \
+    TypeName(const TypeName&); \
+    void operator=(const TypeName&)
+
+// Used to calculate the number of elements in an array.
+// (See |arraysize()| in Chromium's base/basictypes.h for more details.)
+namespace mojo {
+template <typename T, size_t N>
+char (&ArraySizeHelper(T (&array)[N]))[N];
+#if !defined(_MSC_VER)
+template <typename T, size_t N>
+char (&ArraySizeHelper(const T (&array)[N]))[N];
+#endif
+}  // namespace mojo
+#define MOJO_ARRAYSIZE(array) (sizeof(::mojo::ArraySizeHelper(array)))
+
+// Used to make a type move-only in C++03. See Chromium's base/move.h for more
+// details.
+#define MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
+   private: \
+    struct rvalue_type { \
+      explicit rvalue_type(type* object) : object(object) {} \
+      type* object; \
+    }; \
+    type(type&); \
+    void operator=(type&); \
+   public: \
+    operator rvalue_type() { return rvalue_type(this); } \
+    type Pass() { return type(rvalue_type(this)); } \
+    typedef void MoveOnlyTypeForCPP03; \
+   private:
+
+#endif  // MOJO_PUBLIC_CPP_SYSTEM_MACROS_H_
diff --git a/mojo/public/tests/system/DEPS b/mojo/public/cpp/system/tests/DEPS
similarity index 100%
rename from mojo/public/tests/system/DEPS
rename to mojo/public/cpp/system/tests/DEPS
diff --git a/mojo/public/cpp/system/tests/core_unittest.cc b/mojo/public/cpp/system/tests/core_unittest.cc
new file mode 100644
index 0000000..5121622
--- /dev/null
+++ b/mojo/public/cpp/system/tests/core_unittest.cc
@@ -0,0 +1,392 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests the C++ Mojo system core wrappers.
+// TODO(vtl): Maybe rename "CoreCppTest" -> "CoreTest" if/when this gets
+// compiled into a different binary from the C API tests.
+
+#include "mojo/public/cpp/system/core.h"
+
+#include <map>
+
+#include "mojo/public/cpp/system/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+TEST(CoreCppTest, GetTimeTicksNow) {
+  const MojoTimeTicks start = GetTimeTicksNow();
+  EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
+      << "GetTimeTicksNow should return nonzero value";
+}
+
+TEST(CoreCppTest, Basic) {
+  // Basic |Handle| implementation:
+  {
+    EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue);
+
+    Handle h0;
+    EXPECT_EQ(kInvalidHandleValue, h0.value());
+    EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value());
+    EXPECT_FALSE(h0.is_valid());
+
+    Handle h1(static_cast<MojoHandle>(123));
+    EXPECT_EQ(static_cast<MojoHandle>(123), h1.value());
+    EXPECT_EQ(static_cast<MojoHandle>(123), *h1.mutable_value());
+    EXPECT_TRUE(h1.is_valid());
+    *h1.mutable_value() = static_cast<MojoHandle>(456);
+    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
+    EXPECT_TRUE(h1.is_valid());
+
+    h1.swap(h0);
+    EXPECT_EQ(static_cast<MojoHandle>(456), h0.value());
+    EXPECT_TRUE(h0.is_valid());
+    EXPECT_FALSE(h1.is_valid());
+
+    h1.set_value(static_cast<MojoHandle>(789));
+    h0.swap(h1);
+    EXPECT_EQ(static_cast<MojoHandle>(789), h0.value());
+    EXPECT_TRUE(h0.is_valid());
+    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
+    EXPECT_TRUE(h1.is_valid());
+
+    // Make sure copy constructor works.
+    Handle h2(h0);
+    EXPECT_EQ(static_cast<MojoHandle>(789), h2.value());
+    // And assignment.
+    h2 = h1;
+    EXPECT_EQ(static_cast<MojoHandle>(456), h2.value());
+
+    // Make sure that we can put |Handle|s into |std::map|s.
+    h0 = Handle(static_cast<MojoHandle>(987));
+    h1 = Handle(static_cast<MojoHandle>(654));
+    h2 = Handle(static_cast<MojoHandle>(321));
+    Handle h3;
+    std::map<Handle, int> handle_to_int;
+    handle_to_int[h0] = 0;
+    handle_to_int[h1] = 1;
+    handle_to_int[h2] = 2;
+    handle_to_int[h3] = 3;
+
+    EXPECT_EQ(4u, handle_to_int.size());
+    EXPECT_FALSE(handle_to_int.find(h0) == handle_to_int.end());
+    EXPECT_EQ(0, handle_to_int[h0]);
+    EXPECT_FALSE(handle_to_int.find(h1) == handle_to_int.end());
+    EXPECT_EQ(1, handle_to_int[h1]);
+    EXPECT_FALSE(handle_to_int.find(h2) == handle_to_int.end());
+    EXPECT_EQ(2, handle_to_int[h2]);
+    EXPECT_FALSE(handle_to_int.find(h3) == handle_to_int.end());
+    EXPECT_EQ(3, handle_to_int[h3]);
+    EXPECT_TRUE(handle_to_int.find(Handle(static_cast<MojoHandle>(13579))) ==
+                    handle_to_int.end());
+
+    // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out
+    // how to support the variations of |hash_map|.)
+  }
+
+  // |Handle|/|ScopedHandle| functions:
+  {
+    ScopedHandle h;
+
+    EXPECT_EQ(kInvalidHandleValue, h.get().value());
+
+    // This should be a no-op.
+    Close(h.Pass());
+
+    // It should still be invalid.
+    EXPECT_EQ(kInvalidHandleValue, h.get().value());
+
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              Wait(h.get(), MOJO_WAIT_FLAG_EVERYTHING, 1000000));
+
+    std::vector<Handle> wh;
+    wh.push_back(h.get());
+    std::vector<MojoWaitFlags> wf;
+    wf.push_back(MOJO_WAIT_FLAG_EVERYTHING);
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              WaitMany(wh, wf, MOJO_DEADLINE_INDEFINITE));
+  }
+
+  // |MakeScopedHandle| (just compilation tests):
+  {
+    EXPECT_FALSE(MakeScopedHandle(Handle()).is_valid());
+    EXPECT_FALSE(MakeScopedHandle(MessagePipeHandle()).is_valid());
+    EXPECT_FALSE(MakeScopedHandle(DataPipeProducerHandle()).is_valid());
+    EXPECT_FALSE(MakeScopedHandle(DataPipeConsumerHandle()).is_valid());
+    EXPECT_FALSE(MakeScopedHandle(SharedBufferHandle()).is_valid());
+  }
+
+  // |MessagePipeHandle|/|ScopedMessagePipeHandle| functions:
+  {
+    MessagePipeHandle h_invalid;
+    EXPECT_FALSE(h_invalid.is_valid());
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              WriteMessageRaw(h_invalid,
+                              NULL, 0,
+                              NULL, 0,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+    char buffer[10] = { 0 };
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              WriteMessageRaw(h_invalid,
+                              buffer, sizeof(buffer),
+                              NULL, 0,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              ReadMessageRaw(h_invalid,
+                             NULL, NULL,
+                             NULL, NULL,
+                             MOJO_READ_MESSAGE_FLAG_NONE));
+    uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              ReadMessageRaw(h_invalid,
+                             buffer, &buffer_size,
+                             NULL, NULL,
+                             MOJO_READ_MESSAGE_FLAG_NONE));
+
+    // Basic tests of waiting and closing.
+    MojoHandle hv0 = kInvalidHandleValue;
+    {
+      ScopedMessagePipeHandle h0;
+      ScopedMessagePipeHandle h1;
+      EXPECT_FALSE(h0.get().is_valid());
+      EXPECT_FALSE(h1.get().is_valid());
+
+      CreateMessagePipe(&h0, &h1);
+      EXPECT_TRUE(h0.get().is_valid());
+      EXPECT_TRUE(h1.get().is_valid());
+      EXPECT_NE(h0.get().value(), h1.get().value());
+      // Save the handle values, so we can check that things got closed
+      // correctly.
+      hv0 = h0.get().value();
+      MojoHandle hv1 = h1.get().value();
+
+      EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
+                Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, 0));
+      std::vector<Handle> wh;
+      wh.push_back(h0.get());
+      wh.push_back(h1.get());
+      std::vector<MojoWaitFlags> wf;
+      wf.push_back(MOJO_WAIT_FLAG_READABLE);
+      wf.push_back(MOJO_WAIT_FLAG_WRITABLE);
+      EXPECT_EQ(1, WaitMany(wh, wf, 1000));
+
+      // Test closing |h1| explicitly.
+      Close(h1.Pass());
+      EXPECT_FALSE(h1.get().is_valid());
+
+      // Make sure |h1| is closed.
+      EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+                MojoWait(hv1, MOJO_WAIT_FLAG_EVERYTHING,
+                         MOJO_DEADLINE_INDEFINITE));
+
+      EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
+                Wait(h0.get(), MOJO_WAIT_FLAG_READABLE,
+                     MOJO_DEADLINE_INDEFINITE));
+    }
+    // |hv0| should have been closed when |h0| went out of scope, so this close
+    // should fail.
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0));
+
+    // Actually test writing/reading messages.
+    {
+      ScopedMessagePipeHandle h0;
+      ScopedMessagePipeHandle h1;
+      CreateMessagePipe(&h0, &h1);
+
+      const char kHello[] = "hello";
+      const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
+      EXPECT_EQ(MOJO_RESULT_OK,
+                WriteMessageRaw(h0.get(),
+                                kHello, kHelloSize,
+                                NULL, 0,
+                                MOJO_WRITE_MESSAGE_FLAG_NONE));
+      EXPECT_EQ(MOJO_RESULT_OK,
+                Wait(h1.get(), MOJO_WAIT_FLAG_READABLE,
+                     MOJO_DEADLINE_INDEFINITE));
+      char buffer[10] = { 0 };
+      uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
+      EXPECT_EQ(MOJO_RESULT_OK,
+                ReadMessageRaw(h1.get(),
+                               buffer, &buffer_size,
+                               NULL, NULL,
+                               MOJO_READ_MESSAGE_FLAG_NONE));
+      EXPECT_EQ(kHelloSize, buffer_size);
+      EXPECT_STREQ(kHello, buffer);
+
+      // Send a handle over the previously-establish message pipe. Use the
+      // |MessagePipe| wrapper (to test it), which automatically creates a
+      // message pipe.
+      MessagePipe mp;
+
+      // Write a message to |mp.handle0|, before we send |mp.handle1|.
+      const char kWorld[] = "world!";
+      const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
+      EXPECT_EQ(MOJO_RESULT_OK,
+                WriteMessageRaw(mp.handle0.get(),
+                                kWorld, kWorldSize,
+                                NULL, 0,
+                                MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+      // Send |mp.handle1| over |h1| to |h0|.
+      MojoHandle handles[5];
+      handles[0] = mp.handle1.release().value();
+      EXPECT_NE(kInvalidHandleValue, handles[0]);
+      EXPECT_FALSE(mp.handle1.get().is_valid());
+      uint32_t handles_count = 1;
+      EXPECT_EQ(MOJO_RESULT_OK,
+                WriteMessageRaw(h1.get(),
+                                kHello, kHelloSize,
+                                handles, handles_count,
+                                MOJO_WRITE_MESSAGE_FLAG_NONE));
+      // |handles[0]| should actually be invalid now.
+      EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handles[0]));
+
+      // Read "hello" and the sent handle.
+      EXPECT_EQ(MOJO_RESULT_OK,
+                Wait(h0.get(), MOJO_WAIT_FLAG_READABLE,
+                     MOJO_DEADLINE_INDEFINITE));
+      memset(buffer, 0, sizeof(buffer));
+      buffer_size = static_cast<uint32_t>(sizeof(buffer));
+      for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++)
+        handles[i] = kInvalidHandleValue;
+      handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles));
+      EXPECT_EQ(MOJO_RESULT_OK,
+                ReadMessageRaw(h0.get(),
+                               buffer, &buffer_size,
+                               handles, &handles_count,
+                               MOJO_READ_MESSAGE_FLAG_NONE));
+      EXPECT_EQ(kHelloSize, buffer_size);
+      EXPECT_STREQ(kHello, buffer);
+      EXPECT_EQ(1u, handles_count);
+      EXPECT_NE(kInvalidHandleValue, handles[0]);
+
+      // Read from the sent/received handle.
+      mp.handle1.reset(MessagePipeHandle(handles[0]));
+      // Save |handles[0]| to check that it gets properly closed.
+      hv0 = handles[0];
+      EXPECT_EQ(MOJO_RESULT_OK,
+                Wait(mp.handle1.get(), MOJO_WAIT_FLAG_READABLE,
+                     MOJO_DEADLINE_INDEFINITE));
+      memset(buffer, 0, sizeof(buffer));
+      buffer_size = static_cast<uint32_t>(sizeof(buffer));
+      for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++)
+        handles[i] = kInvalidHandleValue;
+      handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles));
+      EXPECT_EQ(MOJO_RESULT_OK,
+                ReadMessageRaw(mp.handle1.get(),
+                               buffer, &buffer_size,
+                               handles, &handles_count,
+                               MOJO_READ_MESSAGE_FLAG_NONE));
+      EXPECT_EQ(kWorldSize, buffer_size);
+      EXPECT_STREQ(kWorld, buffer);
+      EXPECT_EQ(0u, handles_count);
+    }
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0));
+  }
+
+  // TODO(vtl): Test |CloseRaw()|.
+  // TODO(vtl): Test |reset()| more thoroughly?
+}
+
+TEST(CoreCppTest, TearDownWithMessagesEnqueued) {
+  // Tear down a message pipe which still has a message enqueued, with the
+  // message also having a valid message pipe handle.
+  {
+    ScopedMessagePipeHandle h0;
+    ScopedMessagePipeHandle h1;
+    CreateMessagePipe(&h0, &h1);
+
+    // Send a handle over the previously-establish message pipe.
+    ScopedMessagePipeHandle h2;
+    ScopedMessagePipeHandle h3;
+    CreateMessagePipe(&h2, &h3);
+
+    // Write a message to |h2|, before we send |h3|.
+    const char kWorld[] = "world!";
+    const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
+    EXPECT_EQ(MOJO_RESULT_OK,
+              WriteMessageRaw(h2.get(),
+                              kWorld, kWorldSize,
+                              NULL, 0,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+    // And also a message to |h3|.
+    EXPECT_EQ(MOJO_RESULT_OK,
+              WriteMessageRaw(h3.get(),
+                              kWorld, kWorldSize,
+                              NULL, 0,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+    // Send |h3| over |h1| to |h0|.
+    const char kHello[] = "hello";
+    const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
+    MojoHandle h3_value;
+    h3_value = h3.release().value();
+    EXPECT_NE(kInvalidHandleValue, h3_value);
+    EXPECT_FALSE(h3.get().is_valid());
+    EXPECT_EQ(MOJO_RESULT_OK,
+              WriteMessageRaw(h1.get(),
+                              kHello, kHelloSize,
+                              &h3_value, 1,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+    // |h3_value| should actually be invalid now.
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value));
+
+    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value()));
+    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value()));
+    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value()));
+  }
+
+  // Do this in a different order: make the enqueued message pipe handle only
+  // half-alive.
+  {
+    ScopedMessagePipeHandle h0;
+    ScopedMessagePipeHandle h1;
+    CreateMessagePipe(&h0, &h1);
+
+    // Send a handle over the previously-establish message pipe.
+    ScopedMessagePipeHandle h2;
+    ScopedMessagePipeHandle h3;
+    CreateMessagePipe(&h2, &h3);
+
+    // Write a message to |h2|, before we send |h3|.
+    const char kWorld[] = "world!";
+    const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
+    EXPECT_EQ(MOJO_RESULT_OK,
+              WriteMessageRaw(h2.get(),
+                              kWorld, kWorldSize,
+                              NULL, 0,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+    // And also a message to |h3|.
+    EXPECT_EQ(MOJO_RESULT_OK,
+              WriteMessageRaw(h3.get(),
+                              kWorld, kWorldSize,
+                              NULL, 0,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+    // Send |h3| over |h1| to |h0|.
+    const char kHello[] = "hello";
+    const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
+    MojoHandle h3_value;
+    h3_value = h3.release().value();
+    EXPECT_NE(kInvalidHandleValue, h3_value);
+    EXPECT_FALSE(h3.get().is_valid());
+    EXPECT_EQ(MOJO_RESULT_OK,
+              WriteMessageRaw(h1.get(),
+                              kHello, kHelloSize,
+                              &h3_value, 1,
+                              MOJO_WRITE_MESSAGE_FLAG_NONE));
+    // |h3_value| should actually be invalid now.
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value));
+
+    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value()));
+    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value()));
+    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value()));
+  }
+}
+
+// TODO(vtl): Write data pipe tests.
+
+}  // namespace
+}  // namespace mojo
diff --git a/mojo/public/cpp/system/tests/macros_unittest.cc b/mojo/public/cpp/system/tests/macros_unittest.cc
new file mode 100644
index 0000000..2da1cd6
--- /dev/null
+++ b/mojo/public/cpp/system/tests/macros_unittest.cc
@@ -0,0 +1,125 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests the C++ Mojo system macros and consists of "positive" tests,
+// i.e., those verifying that things work (without compile errors, or even
+// warnings if warnings are treated as errors).
+// TODO(vtl): Maybe rename "MacrosCppTest" -> "MacrosTest" if/when this gets
+// compiled into a different binary from the C API tests.
+// TODO(vtl): Fix no-compile tests (which are all disabled; crbug.com/105388)
+// and write some "negative" tests.
+
+#include "mojo/public/cpp/system/macros.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+// Note: MSVS is very strict (and arguably buggy) about warnings for classes
+// defined in a local scope, so define these globally.
+struct TestOverrideBaseClass {
+  virtual ~TestOverrideBaseClass() {}
+  virtual void ToBeOverridden() {}
+  virtual void AlsoToBeOverridden() = 0;
+};
+
+struct TestOverrideSubclass : public TestOverrideBaseClass {
+  virtual ~TestOverrideSubclass() {}
+  virtual void ToBeOverridden() MOJO_OVERRIDE {}
+  virtual void AlsoToBeOverridden() MOJO_OVERRIDE {}
+};
+
+TEST(MacrosCppTest, Override) {
+  TestOverrideSubclass x;
+  x.ToBeOverridden();
+  x.AlsoToBeOverridden();
+}
+
+// Note: MSVS is very strict (and arguably buggy) about warnings for classes
+// defined in a local scope, so define these globally.
+class TestDisallowCopyAndAssignClass {
+ public:
+  TestDisallowCopyAndAssignClass() {}
+  explicit TestDisallowCopyAndAssignClass(int) {}
+  void NoOp() {}
+
+ private:
+  MOJO_DISALLOW_COPY_AND_ASSIGN(TestDisallowCopyAndAssignClass);
+};
+
+TEST(MacrosCppTest, DisallowCopyAndAssign) {
+  TestDisallowCopyAndAssignClass x;
+  x.NoOp();
+  TestDisallowCopyAndAssignClass y(789);
+  y.NoOp();
+}
+
+// Test that |MOJO_ARRAYSIZE()| works in a |MOJO_COMPILE_ASSERT()|.
+const int kGlobalArray[5] = { 1, 2, 3, 4, 5 };
+MOJO_COMPILE_ASSERT(MOJO_ARRAYSIZE(kGlobalArray) == 5u,
+                    mojo_array_size_failed_in_compile_assert);
+
+TEST(MacrosCppTest, ArraySize) {
+  double local_array[4] = { 6.7, 7.8, 8.9, 9.0 };
+  EXPECT_EQ(4u, MOJO_ARRAYSIZE(local_array));
+}
+
+// Note: MSVS is very strict (and arguably buggy) about warnings for classes
+// defined in a local scope, so define these globally.
+class MoveOnlyInt {
+  MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(MoveOnlyInt, RValue)
+
+ public:
+  MoveOnlyInt() : is_set_(false), value_() {}
+  explicit MoveOnlyInt(int value) : is_set_(true), value_(value) {}
+  ~MoveOnlyInt() {}
+
+  // Move-only constructor and operator=.
+  MoveOnlyInt(RValue other) { *this = other; }
+  MoveOnlyInt& operator=(RValue other) {
+    if (other.object != this) {
+      is_set_ = other.object->is_set_;
+      value_ = other.object->value_;
+      other.object->is_set_ = false;
+    }
+    return *this;
+  }
+
+  int value() const {
+    assert(is_set());
+    return value_;
+  }
+  bool is_set() const { return is_set_; }
+
+ private:
+  bool is_set_;
+  int value_;
+};
+
+TEST(MacrosCppTest, MoveOnlyTypeForCpp03) {
+  MoveOnlyInt x(123);
+  EXPECT_TRUE(x.is_set());
+  EXPECT_EQ(123, x.value());
+  MoveOnlyInt y;
+  EXPECT_FALSE(y.is_set());
+  y = x.Pass();
+  EXPECT_FALSE(x.is_set());
+  EXPECT_TRUE(y.is_set());
+  EXPECT_EQ(123, y.value());
+  MoveOnlyInt z(y.Pass());
+  EXPECT_FALSE(y.is_set());
+  EXPECT_TRUE(z.is_set());
+  EXPECT_EQ(123, z.value());
+  z = z.Pass();
+  EXPECT_TRUE(z.is_set());
+  EXPECT_EQ(123, z.value());
+}
+
+}  // namespace
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/lib/mutex.cc b/mojo/public/cpp/utility/lib/mutex.cc
new file mode 100644
index 0000000..23370e1
--- /dev/null
+++ b/mojo/public/cpp/utility/lib/mutex.cc
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/mutex.h"
+
+#include <assert.h>
+#include <errno.h>
+
+namespace mojo {
+
+// Release builds have inlined (non-error-checking) definitions in the header.
+#if !defined(NDEBUG)
+Mutex::Mutex() {
+  pthread_mutexattr_t mutexattr;
+  int rv = pthread_mutexattr_init(&mutexattr);
+  assert(rv == 0);
+  rv = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
+  assert(rv == 0);
+  rv = pthread_mutex_init(&mutex_, &mutexattr);
+  assert(rv == 0);
+  rv = pthread_mutexattr_destroy(&mutexattr);
+  assert(rv == 0);
+}
+
+Mutex::~Mutex() {
+  int rv = pthread_mutex_destroy(&mutex_);
+  assert(rv == 0);
+}
+
+void Mutex::Lock() {
+  int rv = pthread_mutex_lock(&mutex_);
+  assert(rv == 0);
+}
+
+void Mutex::Unlock() {
+  int rv = pthread_mutex_unlock(&mutex_);
+  assert(rv == 0);
+}
+
+bool Mutex::TryLock() {
+  int rv = pthread_mutex_trylock(&mutex_);
+  assert(rv == 0 || rv == EBUSY);
+  return rv == 0;
+}
+
+void Mutex::AssertHeld() {
+  assert(pthread_mutex_lock(&mutex_) == EDEADLK);
+}
+#endif  // !defined(NDEBUG)
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/lib/run_loop.cc b/mojo/public/cpp/utility/lib/run_loop.cc
new file mode 100644
index 0000000..2bf6a07
--- /dev/null
+++ b/mojo/public/cpp/utility/lib/run_loop.cc
@@ -0,0 +1,224 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/run_loop.h"
+
+#include <assert.h>
+
+#include <algorithm>
+#include <vector>
+
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+#include "mojo/public/cpp/utility/run_loop_handler.h"
+
+namespace mojo {
+namespace {
+
+internal::ThreadLocalPointer<RunLoop> current_run_loop;
+
+const MojoTimeTicks kInvalidTimeTicks = static_cast<MojoTimeTicks>(0);
+
+}  // namespace
+
+// State needed for one iteration of WaitMany().
+struct RunLoop::WaitState {
+  WaitState() : deadline(MOJO_DEADLINE_INDEFINITE) {}
+
+  std::vector<Handle> handles;
+  std::vector<MojoWaitFlags> wait_flags;
+  MojoDeadline deadline;
+};
+
+struct RunLoop::RunState {
+  RunState() : should_quit(false) {}
+
+  bool should_quit;
+};
+
+RunLoop::RunLoop() : run_state_(NULL), next_handler_id_(0) {
+  assert(!current());
+  current_run_loop.Set(this);
+}
+
+RunLoop::~RunLoop() {
+  assert(current() == this);
+  current_run_loop.Set(NULL);
+}
+
+// static
+void RunLoop::SetUp() {
+  current_run_loop.Allocate();
+}
+
+// static
+void RunLoop::TearDown() {
+  assert(!current());
+  current_run_loop.Free();
+}
+
+// static
+RunLoop* RunLoop::current() {
+  return current_run_loop.Get();
+}
+
+void RunLoop::AddHandler(RunLoopHandler* handler,
+                         const Handle& handle,
+                         MojoWaitFlags wait_flags,
+                         MojoDeadline deadline) {
+  assert(current() == this);
+  assert(handler);
+  assert(handle.is_valid());
+  // Assume it's an error if someone tries to reregister an existing handle.
+  assert(0u == handler_data_.count(handle));
+  HandlerData handler_data;
+  handler_data.handler = handler;
+  handler_data.wait_flags = wait_flags;
+  handler_data.deadline = (deadline == MOJO_DEADLINE_INDEFINITE) ?
+      kInvalidTimeTicks :
+      GetTimeTicksNow() + static_cast<MojoTimeTicks>(deadline);
+  handler_data.id = next_handler_id_++;
+  handler_data_[handle] = handler_data;
+}
+
+void RunLoop::RemoveHandler(const Handle& handle) {
+  assert(current() == this);
+  handler_data_.erase(handle);
+}
+
+bool RunLoop::HasHandler(const Handle& handle) const {
+  return handler_data_.find(handle) != handler_data_.end();
+}
+
+void RunLoop::Run() {
+  assert(current() == this);
+  // We don't currently support nesting.
+  assert(!run_state_);
+  RunState* old_state = run_state_;
+  RunState run_state;
+  run_state_ = &run_state;
+  while (!run_state.should_quit)
+    Wait(false);
+  run_state_ = old_state;
+}
+
+void RunLoop::RunUntilIdle() {
+  assert(current() == this);
+  // We don't currently support nesting.
+  assert(!run_state_);
+  RunState* old_state = run_state_;
+  RunState run_state;
+  run_state_ = &run_state;
+  while (!run_state.should_quit) {
+    if (!Wait(true))
+      break;
+  }
+  run_state_ = old_state;
+}
+
+void RunLoop::Quit() {
+  assert(current() == this);
+  if (run_state_)
+    run_state_->should_quit = true;
+}
+
+bool RunLoop::Wait(bool non_blocking) {
+  const WaitState wait_state = GetWaitState(non_blocking);
+  if (wait_state.handles.empty()) {
+    Quit();
+    return false;
+  }
+
+  const MojoResult result =
+      WaitMany(wait_state.handles, wait_state.wait_flags, wait_state.deadline);
+  if (result >= 0) {
+    const size_t index = static_cast<size_t>(result);
+    assert(handler_data_.find(wait_state.handles[index]) !=
+           handler_data_.end());
+    handler_data_[wait_state.handles[index]].handler->OnHandleReady(
+        wait_state.handles[index]);
+    return true;
+  }
+
+  switch (result) {
+    case MOJO_RESULT_INVALID_ARGUMENT:
+    case MOJO_RESULT_FAILED_PRECONDITION:
+      return RemoveFirstInvalidHandle(wait_state);
+    case MOJO_RESULT_DEADLINE_EXCEEDED:
+      return NotifyDeadlineExceeded();
+  }
+
+  assert(false);
+  return false;
+}
+
+bool RunLoop::NotifyDeadlineExceeded() {
+  bool notified = false;
+
+  // Make a copy in case someone tries to add/remove new handlers as part of
+  // notifying.
+  const HandleToHandlerData cloned_handlers(handler_data_);
+  const MojoTimeTicks now(GetTimeTicksNow());
+  for (HandleToHandlerData::const_iterator i = cloned_handlers.begin();
+       i != cloned_handlers.end(); ++i) {
+    // Since we're iterating over a clone of the handlers, verify the handler is
+    // still valid before notifying.
+    if (i->second.deadline != kInvalidTimeTicks &&
+        i->second.deadline < now &&
+        handler_data_.find(i->first) != handler_data_.end() &&
+        handler_data_[i->first].id == i->second.id) {
+      handler_data_.erase(i->first);
+      i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED);
+      notified = true;
+    }
+  }
+
+  return notified;
+}
+
+bool RunLoop::RemoveFirstInvalidHandle(const WaitState& wait_state) {
+  for (size_t i = 0; i < wait_state.handles.size(); ++i) {
+    const MojoResult result =
+        mojo::Wait(wait_state.handles[i], wait_state.wait_flags[i],
+                   static_cast<MojoDeadline>(0));
+    if (result == MOJO_RESULT_INVALID_ARGUMENT ||
+        result == MOJO_RESULT_FAILED_PRECONDITION) {
+      // Remove the handle first, this way if OnHandleError() tries to remove
+      // the handle our iterator isn't invalidated.
+      assert(handler_data_.find(wait_state.handles[i]) != handler_data_.end());
+      RunLoopHandler* handler =
+          handler_data_[wait_state.handles[i]].handler;
+      handler_data_.erase(wait_state.handles[i]);
+      handler->OnHandleError(wait_state.handles[i], result);
+      return true;
+    }
+    assert(MOJO_RESULT_DEADLINE_EXCEEDED == result);
+  }
+  return false;
+}
+
+RunLoop::WaitState RunLoop::GetWaitState(bool non_blocking) const {
+  WaitState wait_state;
+  MojoTimeTicks min_time = kInvalidTimeTicks;
+  for (HandleToHandlerData::const_iterator i = handler_data_.begin();
+       i != handler_data_.end(); ++i) {
+    wait_state.handles.push_back(i->first);
+    wait_state.wait_flags.push_back(i->second.wait_flags);
+    if (!non_blocking && i->second.deadline != kInvalidTimeTicks &&
+        (min_time == kInvalidTimeTicks || i->second.deadline < min_time)) {
+      min_time = i->second.deadline;
+    }
+  }
+  if (non_blocking) {
+    wait_state.deadline = static_cast<MojoDeadline>(0);
+  } else if (min_time != kInvalidTimeTicks) {
+    const MojoTimeTicks now = GetTimeTicksNow();
+    if (min_time < now)
+      wait_state.deadline = static_cast<MojoDeadline>(0);
+    else
+      wait_state.deadline = static_cast<MojoDeadline>(min_time - now);
+  }
+  return wait_state;
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/lib/thread.cc b/mojo/public/cpp/utility/lib/thread.cc
new file mode 100644
index 0000000..da33497
--- /dev/null
+++ b/mojo/public/cpp/utility/lib/thread.cc
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/thread.h"
+
+#include <assert.h>
+
+namespace mojo {
+
+Thread::Thread()
+    : options_(),
+      thread_(),
+      started_(false),
+      joined_(false) {
+}
+
+Thread::Thread(const Options& options)
+    : options_(options),
+      thread_(),
+      started_(false),
+      joined_(false) {
+}
+
+Thread::~Thread() {
+  // If it was started, it must have been joined.
+  assert(!started_ || joined_);
+}
+
+void Thread::Start() {
+  assert(!started_);
+  assert(!joined_);
+
+  pthread_attr_t attr;
+  int rv MOJO_ALLOW_UNUSED = pthread_attr_init(&attr);
+  assert(rv == 0);
+
+  // Non-default stack size?
+  if (options_.stack_size() != 0) {
+    rv = pthread_attr_setstacksize(&attr, options_.stack_size());
+    assert(rv == 0);
+  }
+
+  started_ = true;
+  rv = pthread_create(&thread_, &attr, &ThreadRunTrampoline, this);
+  assert(rv == 0);
+
+  rv = pthread_attr_destroy(&attr);
+  assert(rv == 0);
+}
+
+void Thread::Join() {
+  // Must have been started but not yet joined.
+  assert(started_);
+  assert(!joined_);
+
+  joined_ = true;
+  int rv MOJO_ALLOW_UNUSED = pthread_join(thread_, NULL);
+  assert(rv == 0);
+}
+
+// static
+void* Thread::ThreadRunTrampoline(void* arg) {
+  Thread* self = static_cast<Thread*>(arg);
+  self->Run();
+  return NULL;
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/lib/thread_local.h b/mojo/public/cpp/utility/lib/thread_local.h
new file mode 100644
index 0000000..4c3625d
--- /dev/null
+++ b/mojo/public/cpp/utility/lib/thread_local.h
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_
+#define MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_
+
+#ifndef _WIN32
+#include <pthread.h>
+#endif
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+namespace internal {
+
+// Helper functions that abstract the cross-platform APIs.
+struct ThreadLocalPlatform {
+#ifdef _WIN32
+  typedef unsigned long SlotType;
+#else
+  typedef pthread_key_t SlotType;
+#endif
+
+  static void AllocateSlot(SlotType* slot);
+  static void FreeSlot(SlotType slot);
+  static void* GetValueFromSlot(SlotType slot);
+  static void SetValueInSlot(SlotType slot, void* value);
+};
+
+// This class is intended to be statically allocated.
+template <typename P>
+class ThreadLocalPointer {
+ public:
+  ThreadLocalPointer() : slot_() {
+  }
+
+  void Allocate() {
+    ThreadLocalPlatform::AllocateSlot(&slot_);
+  }
+
+  void Free() {
+    ThreadLocalPlatform::FreeSlot(slot_);
+  }
+
+  P* Get() {
+    return static_cast<P*>(ThreadLocalPlatform::GetValueFromSlot(slot_));
+  }
+
+  void Set(P* value) {
+    ThreadLocalPlatform::SetValueInSlot(slot_, value);
+  }
+
+ private:
+  ThreadLocalPlatform::SlotType slot_;
+};
+
+}  // namespace internal
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_UTILITY_LIB_THREAD_LOCAL_H_
diff --git a/mojo/public/cpp/utility/lib/thread_local_posix.cc b/mojo/public/cpp/utility/lib/thread_local_posix.cc
new file mode 100644
index 0000000..b33dfc6
--- /dev/null
+++ b/mojo/public/cpp/utility/lib/thread_local_posix.cc
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+
+#include <assert.h>
+
+namespace mojo {
+namespace internal {
+
+// static
+void ThreadLocalPlatform::AllocateSlot(SlotType* slot) {
+  if (pthread_key_create(slot, NULL) != 0) {
+    assert(false);
+  }
+}
+
+// static
+void ThreadLocalPlatform::FreeSlot(SlotType slot) {
+  if (pthread_key_delete(slot) != 0) {
+    assert(false);
+  }
+}
+
+// static
+void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) {
+  return pthread_getspecific(slot);
+}
+
+// static
+void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) {
+  if (pthread_setspecific(slot, value) != 0) {
+    assert(false);
+  }
+}
+
+}  // namespace internal
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/lib/thread_local_win.cc b/mojo/public/cpp/utility/lib/thread_local_win.cc
new file mode 100644
index 0000000..98841f7
--- /dev/null
+++ b/mojo/public/cpp/utility/lib/thread_local_win.cc
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/lib/thread_local.h"
+
+#include <assert.h>
+#include <windows.h>
+
+namespace mojo {
+namespace internal {
+
+// static
+void ThreadLocalPlatform::AllocateSlot(SlotType* slot) {
+  *slot = TlsAlloc();
+  assert(*slot != TLS_OUT_OF_INDEXES);
+}
+
+// static
+void ThreadLocalPlatform::FreeSlot(SlotType slot) {
+  if (!TlsFree(slot)) {
+    assert(false);
+  }
+}
+
+// static
+void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) {
+  return TlsGetValue(slot);
+}
+
+// static
+void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) {
+  if (!TlsSetValue(slot, value)) {
+    assert(false);
+  }
+}
+
+}  // namespace internal
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/mutex.h b/mojo/public/cpp/utility/mutex.h
new file mode 100644
index 0000000..35611c2
--- /dev/null
+++ b/mojo/public/cpp/utility/mutex.h
@@ -0,0 +1,70 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_
+#define MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_
+
+#ifdef _WIN32
+#error "Not implemented: See crbug.com/342893."
+#endif
+
+#include <pthread.h>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+#ifdef NDEBUG
+// Note: Make a C++ constant for |PTHREAD_MUTEX_INITIALIZER|. (We can't directly
+// use the C macro in an initializer list, since it might expand to |{ ... }|.)
+namespace internal {
+const pthread_mutex_t kPthreadMutexInitializer = PTHREAD_MUTEX_INITIALIZER;
+}
+#endif
+
+class Mutex {
+ public:
+#ifdef NDEBUG
+  Mutex() : mutex_(internal::kPthreadMutexInitializer) {}
+  ~Mutex() { pthread_mutex_destroy(&mutex_); }
+
+  void Lock() { pthread_mutex_lock(&mutex_); }
+  void Unlock() { pthread_mutex_unlock(&mutex_); }
+  bool TryLock() { return pthread_mutex_trylock(&mutex_) == 0; }
+
+  void AssertHeld() {}
+#else
+  Mutex();
+  ~Mutex();
+
+  void Lock();
+  void Unlock();
+  bool TryLock();
+
+  void AssertHeld();
+#endif
+
+ private:
+  pthread_mutex_t mutex_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(Mutex);
+};
+
+class MutexLock {
+ public:
+  explicit MutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
+  ~MutexLock() { mutex_->Unlock(); }
+
+ private:
+  Mutex* const mutex_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLock);
+};
+
+// Catch bug where variable name is omitted (e.g., |MutexLock (&mu)|).
+#define MutexLock(x) MOJO_COMPILE_ASSERT(0, mutex_lock_missing_variable_name);
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_UTILITY_MUTEX_H_
diff --git a/mojo/public/cpp/utility/run_loop.h b/mojo/public/cpp/utility/run_loop.h
new file mode 100644
index 0000000..288a68e
--- /dev/null
+++ b/mojo/public/cpp/utility/run_loop.h
@@ -0,0 +1,108 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
+#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
+
+#include <map>
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+class RunLoopHandler;
+
+class RunLoop {
+ public:
+  RunLoop();
+  ~RunLoop();
+
+  // Sets up state needed for RunLoop. This must be invoked before creating a
+  // RunLoop.
+  static void SetUp();
+
+  // Cleans state created by Setup().
+  static void TearDown();
+
+  // Returns the RunLoop for the current thread. Returns NULL if not yet
+  // created.
+  static RunLoop* current();
+
+  // Registers a RunLoopHandler for the specified handle. Only one handler can
+  // be registered for a specified handle.
+  void AddHandler(RunLoopHandler* handler,
+                  const Handle& handle,
+                  MojoWaitFlags wait_flags,
+                  MojoDeadline deadline);
+  void RemoveHandler(const Handle& handle);
+  bool HasHandler(const Handle& handle) const;
+
+  // Runs the loop servicing handles as they are ready. This returns when Quit()
+  // is invoked, or there no more handles.
+  void Run();
+
+  // Runs the loop servicing any handles that are ready. Does not wait for
+  // handles to become ready before returning. Returns early if Quit() is
+  // invoked.
+  void RunUntilIdle();
+
+  void Quit();
+
+ private:
+  struct RunState;
+  struct WaitState;
+
+  // Contains the data needed to track a request to AddHandler().
+  struct HandlerData {
+    HandlerData()
+        : handler(NULL),
+          wait_flags(MOJO_WAIT_FLAG_NONE),
+          deadline(0),
+          id(0) {}
+
+    RunLoopHandler* handler;
+    MojoWaitFlags wait_flags;
+    MojoTimeTicks deadline;
+    // See description of |RunLoop::next_handler_id_| for details.
+    int id;
+  };
+
+  typedef std::map<Handle, HandlerData> HandleToHandlerData;
+
+  // Waits for a handle to be ready. Returns after servicing at least one
+  // handle (or there are no more handles) unless |non_blocking| is true,
+  // in which case it will also return if servicing at least one handle
+  // would require blocking. Returns true if a RunLoopHandler was notified.
+  bool Wait(bool non_blocking);
+
+  // Notifies any handlers whose deadline has expired. Returns true if a
+  // RunLoopHandler was notified.
+  bool NotifyDeadlineExceeded();
+
+  // Removes the first invalid handle. This is called if MojoWaitMany() finds an
+  // invalid handle. Returns true if a RunLoopHandler was notified.
+  bool RemoveFirstInvalidHandle(const WaitState& wait_state);
+
+  // Returns the state needed to pass to WaitMany().
+  WaitState GetWaitState(bool non_blocking) const;
+
+  HandleToHandlerData handler_data_;
+
+  // If non-NULL we're running (inside Run()). Member references a value on the
+  // stack.
+  RunState* run_state_;
+
+  // An ever increasing value assigned to each HandlerData::id. Used to detect
+  // uniqueness while notifying. That is, while notifying expired timers we copy
+  // |handler_data_| and only notify handlers whose id match. If the id does not
+  // match it means the handler was removed then added so that we shouldn't
+  // notify it.
+  int next_handler_id_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_H_
diff --git a/mojo/public/cpp/utility/run_loop_handler.h b/mojo/public/cpp/utility/run_loop_handler.h
new file mode 100644
index 0000000..69838d5
--- /dev/null
+++ b/mojo/public/cpp/utility/run_loop_handler.h
@@ -0,0 +1,25 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_
+#define MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+// Used by RunLoop to notify when a handle is either ready or has become
+// invalid.
+class RunLoopHandler {
+ public:
+  virtual void OnHandleReady(const Handle& handle) = 0;
+  virtual void OnHandleError(const Handle& handle, MojoResult result) = 0;
+
+ protected:
+  virtual ~RunLoopHandler() {}
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_UTILITY_RUN_LOOP_HANDLER_H_
diff --git a/mojo/public/cpp/utility/tests/DEPS b/mojo/public/cpp/utility/tests/DEPS
new file mode 100644
index 0000000..82f38c5
--- /dev/null
+++ b/mojo/public/cpp/utility/tests/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+testing",
+  # TODO(vtl): Temporary until these are moved to mojo/public/cpp:
+  "+mojo/public/tests",
+]
diff --git a/mojo/public/cpp/utility/tests/mutex_unittest.cc b/mojo/public/cpp/utility/tests/mutex_unittest.cc
new file mode 100644
index 0000000..5f75e60
--- /dev/null
+++ b/mojo/public/cpp/utility/tests/mutex_unittest.cc
@@ -0,0 +1,262 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/mutex.h"
+
+#include <stdlib.h>  // For |rand()|.
+#include <time.h>  // For |nanosleep()| (defined by POSIX).
+
+#include <vector>
+
+#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/cpp/utility/thread.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+TEST(MutexTest, TrivialSingleThreaded) {
+  Mutex mutex;
+
+  mutex.Lock();
+  mutex.AssertHeld();
+  mutex.Unlock();
+
+  EXPECT_TRUE(mutex.TryLock());
+  mutex.AssertHeld();
+  mutex.Unlock();
+
+  {
+    MutexLock lock(&mutex);
+    mutex.AssertHeld();
+  }
+
+  EXPECT_TRUE(mutex.TryLock());
+  mutex.Unlock();
+}
+
+class Fiddler {
+ public:
+  enum Type { kTypeLock, kTypeTry };
+  Fiddler(size_t times_to_lock,
+          Type type,
+          bool should_sleep,
+          Mutex* mutex,
+          int* shared_value)
+      : times_to_lock_(times_to_lock),
+        type_(type),
+        should_sleep_(should_sleep),
+        mutex_(mutex),
+        shared_value_(shared_value) {
+  }
+
+  ~Fiddler() {
+  }
+
+  void Fiddle() {
+    for (size_t i = 0; i < times_to_lock_;) {
+      switch (type_) {
+        case kTypeLock: {
+          mutex_->Lock();
+          int old_shared_value = *shared_value_;
+          if (should_sleep_)
+            SleepALittle();
+          *shared_value_ = old_shared_value + 1;
+          mutex_->Unlock();
+          i++;
+          break;
+        }
+        case kTypeTry:
+          if (mutex_->TryLock()) {
+            int old_shared_value = *shared_value_;
+            if (should_sleep_)
+              SleepALittle();
+            *shared_value_ = old_shared_value + 1;
+            mutex_->Unlock();
+            i++;
+          } else {
+            SleepALittle();  // Don't spin.
+          }
+          break;
+      }
+    }
+  }
+
+ private:
+  static void SleepALittle() {
+    static const long kNanosPerMilli = 1000000;
+    struct timespec req = {
+      0,  // Seconds.
+      (rand() % 10) * kNanosPerMilli // Nanoseconds.
+    };
+    int rv MOJO_ALLOW_UNUSED = nanosleep(&req, NULL);
+    assert(rv == 0);
+  }
+
+  const size_t times_to_lock_;
+  const Type type_;
+  const bool should_sleep_;
+  Mutex* const mutex_;
+  int* const shared_value_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(Fiddler);
+};
+
+class FiddlerThread : public Thread {
+ public:
+  // Takes ownership of |fiddler|.
+  FiddlerThread(Fiddler* fiddler)
+      : fiddler_(fiddler) {
+  }
+
+  virtual ~FiddlerThread() {
+    delete fiddler_;
+  }
+
+  virtual void Run() MOJO_OVERRIDE {
+    fiddler_->Fiddle();
+  }
+
+ private:
+  Fiddler* const fiddler_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(FiddlerThread);
+};
+
+// This does a stress test (that also checks exclusion).
+TEST(MutexTest, ThreadedStress) {
+  static const size_t kNumThreads = 20;
+  static const int kTimesToLockEach = 20;
+  assert(kNumThreads % 4 == 0);
+
+  Mutex mutex;
+  int shared_value = 0;
+
+  std::vector<FiddlerThread*> fiddler_threads;
+
+  for (size_t i = 0; i < kNumThreads; i += 4) {
+    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
+        kTimesToLockEach, Fiddler::kTypeLock, false, &mutex, &shared_value)));
+    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
+        kTimesToLockEach, Fiddler::kTypeTry, false, &mutex, &shared_value)));
+    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
+        kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value)));
+    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
+        kTimesToLockEach, Fiddler::kTypeTry, true, &mutex, &shared_value)));
+  }
+
+  for (size_t i = 0; i < kNumThreads; i++)
+    fiddler_threads[i]->Start();
+
+  // Do some fiddling ourselves.
+  Fiddler(kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value)
+      .Fiddle();
+
+  // Join.
+  for (size_t i = 0; i < kNumThreads; i++)
+    fiddler_threads[i]->Join();
+
+  EXPECT_EQ(static_cast<int>(kNumThreads + 1) * kTimesToLockEach, shared_value);
+
+  // Delete.
+  for (size_t i = 0; i < kNumThreads; i++)
+    delete fiddler_threads[i];
+  fiddler_threads.clear();
+}
+
+class TryThread : public Thread {
+ public:
+  explicit TryThread(Mutex* mutex) : mutex_(mutex), try_lock_succeeded_() {}
+  virtual ~TryThread() {}
+
+  virtual void Run() MOJO_OVERRIDE {
+    try_lock_succeeded_ = mutex_->TryLock();
+    if (try_lock_succeeded_)
+      mutex_->Unlock();
+  }
+
+  bool try_lock_succeeded() const { return try_lock_succeeded_; }
+
+ private:
+  Mutex* const mutex_;
+  bool try_lock_succeeded_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(TryThread);
+};
+
+TEST(MutexTest, TryLock) {
+  Mutex mutex;
+
+  // |TryLock()| should succeed -- we don't have the lock.
+  {
+    TryThread thread(&mutex);
+    thread.Start();
+    thread.Join();
+    EXPECT_TRUE(thread.try_lock_succeeded());
+  }
+
+  // Take the lock.
+  ASSERT_TRUE(mutex.TryLock());
+
+  // Now it should fail.
+  {
+    TryThread thread(&mutex);
+    thread.Start();
+    thread.Join();
+    EXPECT_FALSE(thread.try_lock_succeeded());
+  }
+
+  // Release the lock.
+  mutex.Unlock();
+
+  // It should succeed again.
+  {
+    TryThread thread(&mutex);
+    thread.Start();
+    thread.Join();
+    EXPECT_TRUE(thread.try_lock_succeeded());
+  }
+}
+
+
+// Tests of assertions for Debug builds.
+#if !defined(NDEBUG)
+// Test |AssertHeld()| (which is an actual user API).
+TEST(MutexTest, DebugAssertHeldFailure) {
+  Mutex mutex;
+  EXPECT_DEATH(mutex.AssertHeld(), "");
+}
+
+// Test other consistency checks.
+TEST(MutexTest, DebugAssertionFailures) {
+  // Unlock without lock held.
+  EXPECT_DEATH({
+    Mutex mutex;
+    mutex.Unlock();
+  }, "");
+
+  // Lock with lock held (on same thread).
+  EXPECT_DEATH({
+    Mutex mutex;
+    mutex.Lock();
+    mutex.Lock();
+  }, "");
+
+  // Try lock with lock held.
+  EXPECT_DEATH({
+    Mutex mutex;
+    mutex.Lock();
+    mutex.TryLock();
+  }, "");
+
+  // Destroy lock with lock held.
+  EXPECT_DEATH({
+    Mutex mutex;
+    mutex.Lock();
+  }, "");
+}
+#endif  // !defined(NDEBUG)
+
+}  // namespace
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/tests/run_loop_unittest.cc b/mojo/public/cpp/utility/tests/run_loop_unittest.cc
new file mode 100644
index 0000000..5ba59da
--- /dev/null
+++ b/mojo/public/cpp/utility/tests/run_loop_unittest.cc
@@ -0,0 +1,194 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/run_loop.h"
+
+#include <string>
+
+#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/utility/run_loop_handler.h"
+#include "mojo/public/tests/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+class TestRunLoopHandler : public RunLoopHandler {
+ public:
+  TestRunLoopHandler()
+      : ready_count_(0),
+        error_count_(0),
+        last_error_result_(MOJO_RESULT_OK) {
+  }
+  virtual ~TestRunLoopHandler() {}
+
+  void clear_ready_count() { ready_count_ = 0; }
+  int ready_count() const { return ready_count_; }
+
+  void clear_error_count() { error_count_ = 0; }
+  int error_count() const { return error_count_; }
+
+  MojoResult last_error_result() const { return last_error_result_; }
+
+  // RunLoopHandler:
+  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
+    ready_count_++;
+  }
+  virtual void OnHandleError(const Handle& handle, MojoResult result)
+      MOJO_OVERRIDE {
+    error_count_++;
+    last_error_result_ = result;
+  }
+
+ private:
+  int ready_count_;
+  int error_count_;
+  MojoResult last_error_result_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler);
+};
+
+class RunLoopTest : public testing::Test {
+ public:
+  RunLoopTest() {}
+
+  virtual void SetUp() MOJO_OVERRIDE {
+    Test::SetUp();
+    RunLoop::SetUp();
+  }
+  virtual void TearDown() MOJO_OVERRIDE {
+    RunLoop::TearDown();
+    Test::TearDown();
+  }
+
+ private:
+  MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
+};
+
+// Trivial test to verify Run() with no added handles returns.
+TEST_F(RunLoopTest, ExitsWithNoHandles) {
+  RunLoop run_loop;
+  run_loop.Run();
+}
+
+class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler {
+ public:
+  RemoveOnReadyRunLoopHandler() : run_loop_(NULL) {
+  }
+  virtual ~RemoveOnReadyRunLoopHandler() {}
+
+  void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
+
+  // RunLoopHandler:
+  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
+    run_loop_->RemoveHandler(handle);
+    TestRunLoopHandler::OnHandleReady(handle);
+  }
+
+ private:
+  RunLoop* run_loop_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler);
+};
+
+// Verifies RunLoop quits when no more handles (handle is removed when ready).
+TEST_F(RunLoopTest, HandleReady) {
+  RemoveOnReadyRunLoopHandler handler;
+  MessagePipe test_pipe;
+  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
+
+  RunLoop run_loop;
+  handler.set_run_loop(&run_loop);
+  run_loop.AddHandler(&handler, test_pipe.handle0.get(),
+                      MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE);
+  run_loop.Run();
+  EXPECT_EQ(1, handler.ready_count());
+  EXPECT_EQ(0, handler.error_count());
+  EXPECT_FALSE(run_loop.HasHandler(test_pipe.handle0.get()));
+}
+
+class QuitOnReadyRunLoopHandler : public TestRunLoopHandler {
+ public:
+  QuitOnReadyRunLoopHandler() : run_loop_(NULL) {
+  }
+  virtual ~QuitOnReadyRunLoopHandler() {}
+
+  void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
+
+  // RunLoopHandler:
+  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
+    run_loop_->Quit();
+    TestRunLoopHandler::OnHandleReady(handle);
+  }
+
+ private:
+  RunLoop* run_loop_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler);
+};
+
+// Verifies Quit() from OnHandleReady() quits the loop.
+TEST_F(RunLoopTest, QuitFromReady) {
+  QuitOnReadyRunLoopHandler handler;
+  MessagePipe test_pipe;
+  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
+
+  RunLoop run_loop;
+  handler.set_run_loop(&run_loop);
+  run_loop.AddHandler(&handler, test_pipe.handle0.get(),
+                      MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE);
+  run_loop.Run();
+  EXPECT_EQ(1, handler.ready_count());
+  EXPECT_EQ(0, handler.error_count());
+  EXPECT_TRUE(run_loop.HasHandler(test_pipe.handle0.get()));
+}
+
+class QuitOnErrorRunLoopHandler : public TestRunLoopHandler {
+ public:
+  QuitOnErrorRunLoopHandler() : run_loop_(NULL) {
+  }
+  virtual ~QuitOnErrorRunLoopHandler() {}
+
+  void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
+
+  // RunLoopHandler:
+  virtual void OnHandleError(const Handle& handle, MojoResult result)
+      MOJO_OVERRIDE {
+    run_loop_->Quit();
+    TestRunLoopHandler::OnHandleError(handle, result);
+  }
+
+ private:
+  RunLoop* run_loop_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler);
+};
+
+// Verifies Quit() when the deadline is reached works.
+TEST_F(RunLoopTest, QuitWhenDeadlineExpired) {
+  QuitOnErrorRunLoopHandler handler;
+  MessagePipe test_pipe;
+  RunLoop run_loop;
+  handler.set_run_loop(&run_loop);
+  run_loop.AddHandler(&handler, test_pipe.handle0.get(),
+                      MOJO_WAIT_FLAG_READABLE,
+                      static_cast<MojoDeadline>(10000));
+  run_loop.Run();
+  EXPECT_EQ(0, handler.ready_count());
+  EXPECT_EQ(1, handler.error_count());
+  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, handler.last_error_result());
+  EXPECT_FALSE(run_loop.HasHandler(test_pipe.handle0.get()));
+}
+
+TEST_F(RunLoopTest, Current) {
+  EXPECT_TRUE(RunLoop::current() == NULL);
+  {
+    RunLoop run_loop;
+    EXPECT_EQ(&run_loop, RunLoop::current());
+  }
+  EXPECT_TRUE(RunLoop::current() == NULL);
+}
+
+}  // namespace
+}  // namespace mojo
diff --git a/mojo/public/cpp/utility/tests/thread_unittest.cc b/mojo/public/cpp/utility/tests/thread_unittest.cc
new file mode 100644
index 0000000..7755818
--- /dev/null
+++ b/mojo/public/cpp/utility/tests/thread_unittest.cc
@@ -0,0 +1,110 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/public/cpp/utility/thread.h"
+
+#include "mojo/public/cpp/system/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace {
+
+class SetIntThread : public Thread {
+ public:
+  SetIntThread(int* int_to_set, int value)
+      : int_to_set_(int_to_set),
+        value_(value) {
+  }
+  SetIntThread(const Options& options, int* int_to_set, int value)
+      : Thread(options),
+        int_to_set_(int_to_set),
+        value_(value) {
+  }
+
+  virtual ~SetIntThread() {
+  }
+
+  virtual void Run() MOJO_OVERRIDE {
+    *int_to_set_ = value_;
+  }
+
+ private:
+  int* const int_to_set_;
+  const int value_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(SetIntThread);
+};
+
+TEST(ThreadTest, CreateAndJoin) {
+  int value = 0;
+
+  // Not starting the thread should result in a no-op.
+  {
+    SetIntThread thread(&value, 1234567);
+  }
+  EXPECT_EQ(0, value);
+
+  // Start and join.
+  {
+    SetIntThread thread(&value, 12345678);
+    thread.Start();
+    thread.Join();
+    EXPECT_EQ(12345678, value);
+  }
+
+  // Ditto, with non-default (but reasonable) stack size.
+  {
+    Thread::Options options;
+    options.set_stack_size(1024 * 1024);  // 1 MB.
+    SetIntThread thread(options, &value, 12345678);
+    thread.Start();
+    thread.Join();
+    EXPECT_EQ(12345678, value);
+  }
+}
+
+// Tests of assertions for Debug builds.
+// Note: It's okay to create threads, despite gtest having to fork. (The threads
+// are in the child process.)
+#if !defined(NDEBUG)
+TEST(ThreadTest, DebugAssertionFailures) {
+  // Can only start once.
+  EXPECT_DEATH({
+    int value = 0;
+    SetIntThread thread(&value, 1);
+    thread.Start();
+    thread.Start();
+  }, "");
+
+  // Must join (if you start).
+  EXPECT_DEATH({
+    int value = 0;
+    SetIntThread thread(&value, 2);
+    thread.Start();
+  }, "");
+
+  // Can only join once.
+  EXPECT_DEATH({
+    int value = 0;
+    SetIntThread thread(&value, 3);
+    thread.Start();
+    thread.Join();
+    thread.Join();
+  }, "");
+
+  // Stack too big (we're making certain assumptions here).
+  EXPECT_DEATH({
+    int value = 0;
+    Thread::Options options;
+    options.set_stack_size(static_cast<size_t>(-1));
+    SetIntThread thread(options, &value, 4);
+    thread.Start();
+    thread.Join();
+  }, "");
+}
+#endif  // !defined(NDEBUG)
+
+}  // namespace
+}  // namespace mojo
+
diff --git a/mojo/public/cpp/utility/thread.h b/mojo/public/cpp/utility/thread.h
new file mode 100644
index 0000000..b7d10ee
--- /dev/null
+++ b/mojo/public/cpp/utility/thread.h
@@ -0,0 +1,62 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_PUBLIC_CPP_UTILITY_THREAD_H_
+#define MOJO_PUBLIC_CPP_UTILITY_THREAD_H_
+
+#ifdef _WIN32
+#error "Not implemented: See crbug.com/342893."
+#endif
+
+#include <pthread.h>
+#include <stddef.h>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+// This class is thread-friendly, not thread-safe (e.g., you mustn't call
+// |Join()| from multiple threads and/or simultaneously try to destroy the
+// object).
+class Thread {
+ public:
+  // TODO(vtl): Support non-joinable? priority?
+  class Options {
+   public:
+    Options() : stack_size_(0) {}
+
+    // A stack size of 0 means the default.
+    size_t stack_size() const { return stack_size_; }
+    void set_stack_size(size_t stack_size) { stack_size_ = stack_size; }
+
+   private:
+    size_t stack_size_;
+
+    // Copy and assign allowed.
+  };
+
+  // TODO(vtl): Add name or name prefix?
+  Thread();
+  explicit Thread(const Options& options);
+  virtual ~Thread();
+
+  void Start();
+  void Join();
+
+  virtual void Run() = 0;
+
+ private:
+  static void* ThreadRunTrampoline(void* arg);
+
+  const Options options_;
+  pthread_t thread_;
+  bool started_;
+  bool joined_;
+
+  MOJO_DISALLOW_COPY_AND_ASSIGN(Thread);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_UTILITY_THREAD_H_
diff --git a/mojo/public/environment/DEPS b/mojo/public/environment/DEPS
deleted file mode 100644
index 7758789..0000000
--- a/mojo/public/environment/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "-mojo/public"
-  "+mojo/public/system"
-]
diff --git a/mojo/public/environment/buffer_tls.h b/mojo/public/environment/buffer_tls.h
deleted file mode 100644
index 60929e9..0000000
--- a/mojo/public/environment/buffer_tls.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_ENVIRONMENT_BUFFER_TLS_H_
-#define MOJO_PUBLIC_ENVIRONMENT_BUFFER_TLS_H_
-
-namespace mojo {
-class Buffer;
-
-namespace internal {
-
-// Get/Set the |Buffer*| associated with current thread.
-Buffer* GetCurrentBuffer();
-Buffer* SetCurrentBuffer(Buffer* buffer);
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_ENVIRONMENT_BUFFER_TLS_H_
diff --git a/mojo/public/environment/default_async_waiter.h b/mojo/public/environment/default_async_waiter.h
deleted file mode 100644
index 97cef12..0000000
--- a/mojo/public/environment/default_async_waiter.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
-#define MOJO_PUBLIC_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
-
-#include "mojo/public/system/async_waiter.h"
-
-namespace mojo {
-
-// Returns a default implementation of MojoAsyncWaiter.
-MojoAsyncWaiter* GetDefaultAsyncWaiter();
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_ENVIRONMENT_DEFAULT_ASYNC_WAITER_H_
diff --git a/mojo/public/environment/environment.h b/mojo/public/environment/environment.h
deleted file mode 100644
index ce93726..0000000
--- a/mojo/public/environment/environment.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_ENVIRONMENT_ENVIRONMENT_H_
-#define MOJO_PUBLIC_ENVIRONMENT_ENVIRONMENT_H_
-
-#include "mojo/public/system/macros.h"
-
-namespace mojo {
-
-// This class must be instantiated before using any Mojo APIs.
-class Environment {
- public:
-  Environment();
-  ~Environment();
-
- private:
-  MOJO_DISALLOW_COPY_AND_ASSIGN(Environment);
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_ENVIRONMENT_ENVIRONMENT_H_
diff --git a/mojo/public/environment/lib/DEPS b/mojo/public/environment/lib/DEPS
deleted file mode 100644
index a04b88f..0000000
--- a/mojo/public/environment/lib/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
-  "+mojo/public/environment"
-  "+mojo/public/utility"
-]
diff --git a/mojo/public/environment/lib/buffer_tls.cc b/mojo/public/environment/lib/buffer_tls.cc
deleted file mode 100644
index 8c0793b..0000000
--- a/mojo/public/environment/lib/buffer_tls.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/environment/buffer_tls.h"
-
-#include <assert.h>
-
-#include "mojo/public/environment/lib/buffer_tls_setup.h"
-#include "mojo/public/utility/lib/thread_local.h"
-
-namespace mojo {
-namespace internal {
-
-static ThreadLocalPointer<Buffer> current_buffer;
-
-void SetUpCurrentBuffer() {
-  current_buffer.Allocate();
-}
-
-void TearDownCurrentBuffer() {
-  assert(!current_buffer.Get());
-  current_buffer.Free();
-}
-
-Buffer* GetCurrentBuffer() {
-  return current_buffer.Get();
-}
-
-Buffer* SetCurrentBuffer(Buffer* buf) {
-  Buffer* old_buf = current_buffer.Get();
-  current_buffer.Set(buf);
-  return old_buf;
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/public/environment/lib/buffer_tls_setup.h b/mojo/public/environment/lib/buffer_tls_setup.h
deleted file mode 100644
index 8f5daa1..0000000
--- a/mojo/public/environment/lib/buffer_tls_setup.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
-#define MOJO_PUBLIC_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
-
-namespace mojo {
-namespace internal {
-
-void SetUpCurrentBuffer();
-void TearDownCurrentBuffer();
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_ENVIRONMENT_STANDALONE_BUFFER_TLS_SETUP_H_
diff --git a/mojo/public/environment/lib/default_async_waiter.cc b/mojo/public/environment/lib/default_async_waiter.cc
deleted file mode 100644
index ff2dfae..0000000
--- a/mojo/public/environment/lib/default_async_waiter.cc
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/environment/default_async_waiter.h"
-
-#include <assert.h>
-
-#include "mojo/public/utility/run_loop.h"
-#include "mojo/public/utility/run_loop_handler.h"
-
-namespace mojo {
-namespace {
-
-// RunLoopHandler implementation used for a request to AsyncWait(). There are
-// two ways RunLoopHandlerImpl is deleted:
-// . when the handle is ready (or errored).
-// . when CancelWait() is invoked.
-class RunLoopHandlerImpl : public RunLoopHandler {
- public:
-  RunLoopHandlerImpl(const Handle& handle,
-                     MojoAsyncWaitCallback callback,
-                     void* closure)
-      : handle_(handle),
-        callback_(callback),
-        closure_(closure) {
-  }
-
-  virtual ~RunLoopHandlerImpl() {
-    RunLoop::current()->RemoveHandler(handle_);
-  }
-
-  // RunLoopHandler:
-  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
-    NotifyCallback(MOJO_RESULT_OK);
-  }
-
-  virtual void OnHandleError(const Handle& handle,
-                             MojoResult result) MOJO_OVERRIDE {
-    NotifyCallback(result);
-  }
-
- private:
-  void NotifyCallback(MojoResult result) {
-    // Delete this to unregister the handle. That way if the callback
-    // reregisters everything is ok.
-    MojoAsyncWaitCallback callback = callback_;
-    void* closure = closure_;
-    delete this;
-
-    callback(closure, result);
-  }
-
-  const Handle handle_;
-  MojoAsyncWaitCallback callback_;
-  void* closure_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoopHandlerImpl);
-};
-
-MojoAsyncWaitID AsyncWait(MojoAsyncWaiter* waiter,
-                          MojoHandle handle,
-                          MojoWaitFlags flags,
-                          MojoDeadline deadline,
-                          MojoAsyncWaitCallback callback,
-                          void* closure) {
-  RunLoop* run_loop = RunLoop::current();
-  assert(run_loop);
-
-  // |run_loop_handler| is destroyed either when the handle is ready or if
-  // CancelWait is invoked.
-  RunLoopHandlerImpl* run_loop_handler =
-      new RunLoopHandlerImpl(Handle(handle), callback, closure);
-  run_loop->AddHandler(run_loop_handler, Handle(handle), flags, deadline);
-  return reinterpret_cast<MojoAsyncWaitID>(run_loop_handler);
-}
-
-void CancelWait(MojoAsyncWaiter* waiter, MojoAsyncWaitID wait_id) {
-  delete reinterpret_cast<RunLoopHandlerImpl*>(wait_id);
-}
-
-MojoAsyncWaiter s_default_async_waiter = {
-  AsyncWait,
-  CancelWait
-};
-
-}  // namespace
-
-MojoAsyncWaiter* GetDefaultAsyncWaiter() {
-  return &s_default_async_waiter;
-}
-
-}  // namespace mojo
diff --git a/mojo/public/environment/lib/environment.cc b/mojo/public/environment/lib/environment.cc
deleted file mode 100644
index 371cde9..0000000
--- a/mojo/public/environment/lib/environment.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/environment/environment.h"
-
-#include "mojo/public/environment/lib/buffer_tls_setup.h"
-#include "mojo/public/utility/run_loop.h"
-
-namespace mojo {
-
-Environment::Environment() {
-  internal::SetUpCurrentBuffer();
-  RunLoop::SetUp();
-}
-
-Environment::~Environment() {
-  RunLoop::TearDown();
-  internal::TearDownCurrentBuffer();
-}
-
-}  // namespace mojo
diff --git a/mojo/public/environment/tests/async_waiter_unittest.cc b/mojo/public/environment/tests/async_waiter_unittest.cc
deleted file mode 100644
index 614f132..0000000
--- a/mojo/public/environment/tests/async_waiter_unittest.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/environment/default_async_waiter.h"
-
-#include <string>
-
-#include "mojo/public/environment/environment.h"
-#include "mojo/public/system/core_cpp.h"
-#include "mojo/public/system/macros.h"
-#include "mojo/public/tests/test_utils.h"
-#include "mojo/public/utility/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-class TestAsyncWaitCallback {
- public:
-  TestAsyncWaitCallback() : result_count_(0), last_result_(MOJO_RESULT_OK) {
-  }
-  virtual ~TestAsyncWaitCallback() {}
-
-  int result_count() const { return result_count_; }
-
-  MojoResult last_result() const { return last_result_; }
-
-  // MojoAsyncWaitCallback:
-  static void OnHandleReady(void* closure, MojoResult result) {
-    TestAsyncWaitCallback* self = static_cast<TestAsyncWaitCallback*>(closure);
-    self->result_count_++;
-    self->last_result_ = result;
-  }
-
- private:
-  int result_count_;
-  MojoResult last_result_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(TestAsyncWaitCallback);
-};
-
-MojoAsyncWaitID CallAsyncWait(const Handle& handle,
-                              MojoWaitFlags flags,
-                              TestAsyncWaitCallback* callback) {
-  MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter();
-  return waiter->AsyncWait(waiter,
-                           handle.value(),
-                           flags,
-                           MOJO_DEADLINE_INDEFINITE,
-                           &TestAsyncWaitCallback::OnHandleReady,
-                           callback);
-}
-
-void CallCancelWait(MojoAsyncWaitID wait_id) {
-  MojoAsyncWaiter* waiter = GetDefaultAsyncWaiter();
-  waiter->CancelWait(waiter, wait_id);
-}
-
-class AsyncWaiterTest : public testing::Test {
- public:
-  AsyncWaiterTest() {}
-
- private:
-  Environment environment_;
-  RunLoop run_loop_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(AsyncWaiterTest);
-};
-
-// Verifies AsyncWaitCallback is notified when pipe is ready.
-TEST_F(AsyncWaiterTest, CallbackNotified) {
-  TestAsyncWaitCallback callback;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  CallAsyncWait(test_pipe.handle0.get(),
-                MOJO_WAIT_FLAG_READABLE,
-                &callback);
-  RunLoop::current()->Run();
-  EXPECT_EQ(1, callback.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback.last_result());
-}
-
-// Verifies 2 AsyncWaitCallbacks are notified when there pipes are ready.
-TEST_F(AsyncWaiterTest, TwoCallbacksNotified) {
-  TestAsyncWaitCallback callback1;
-  TestAsyncWaitCallback callback2;
-  MessagePipe test_pipe1;
-  MessagePipe test_pipe2;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe1.handle1.get(), std::string()));
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe2.handle1.get(), std::string()));
-
-  CallAsyncWait(test_pipe1.handle0.get(), MOJO_WAIT_FLAG_READABLE, &callback1);
-  CallAsyncWait(test_pipe2.handle0.get(), MOJO_WAIT_FLAG_READABLE, &callback2);
-
-  RunLoop::current()->Run();
-  EXPECT_EQ(1, callback1.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback1.last_result());
-  EXPECT_EQ(1, callback2.result_count());
-  EXPECT_EQ(MOJO_RESULT_OK, callback2.last_result());
-}
-
-// Verifies cancel works.
-TEST_F(AsyncWaiterTest, CancelCallback) {
-  TestAsyncWaitCallback callback;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  CallCancelWait(
-      CallAsyncWait(test_pipe.handle0.get(),
-                    MOJO_WAIT_FLAG_READABLE,
-                    &callback));
-  RunLoop::current()->Run();
-  EXPECT_EQ(0, callback.result_count());
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/gles2/gles2.h b/mojo/public/gles2/gles2.h
index 8effd31..f945859 100644
--- a/mojo/public/gles2/gles2.h
+++ b/mojo/public/gles2/gles2.h
@@ -10,10 +10,10 @@
 #include <stdint.h>
 #include <GLES2/gl2.h>
 
+#include "mojo/public/c/system/async_waiter.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/public/gles2/gles2_export.h"
 #include "mojo/public/gles2/gles2_types.h"
-#include "mojo/public/system/async_waiter.h"
-#include "mojo/public/system/core.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/mojo/public/gles2/gles2_cpp.h b/mojo/public/gles2/gles2_cpp.h
index 6750910..7f23835 100644
--- a/mojo/public/gles2/gles2_cpp.h
+++ b/mojo/public/gles2/gles2_cpp.h
@@ -5,7 +5,7 @@
 #ifndef MOJO_PUBLIC_GLES2_GLES2_CPP_H_
 #define MOJO_PUBLIC_GLES2_GLES2_CPP_H_
 
-#include "mojo/public/environment/default_async_waiter.h"
+#include "mojo/public/cpp/environment/default_async_waiter.h"
 #include "mojo/public/gles2/gles2.h"
 
 namespace mojo {
diff --git a/mojo/public/gles2/gles2_private.h b/mojo/public/gles2/gles2_private.h
index 8465cae..8e12b8f 100644
--- a/mojo/public/gles2/gles2_private.h
+++ b/mojo/public/gles2/gles2_private.h
@@ -7,10 +7,10 @@
 
 #include <stdint.h>
 
+#include "mojo/public/c/system/async_waiter.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/gles2/gles2_export.h"
 #include "mojo/public/gles2/gles2_types.h"
-#include "mojo/public/system/async_waiter.h"
-#include "mojo/public/system/core_cpp.h"
 
 namespace mojo {
 class GLES2Interface;
diff --git a/mojo/public/shell/application.h b/mojo/public/shell/application.h
index c4707c0..7896637 100644
--- a/mojo/public/shell/application.h
+++ b/mojo/public/shell/application.h
@@ -8,9 +8,9 @@
 #include <vector>
 
 #include "mojo/public/bindings/remote_ptr.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/shell/service.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core_cpp.h"
 
 namespace mojo {
 
diff --git a/mojo/public/shell/service.h b/mojo/public/shell/service.h
index 490eef2..100b798 100644
--- a/mojo/public/shell/service.h
+++ b/mojo/public/shell/service.h
@@ -9,8 +9,8 @@
 
 #include "mojo/public/bindings/error_handler.h"
 #include "mojo/public/bindings/remote_ptr.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core_cpp.h"
 
 // Utility classes for creating ShellClients that vend service instances.
 // To use define a class that implements your specific server api, e.g. FooImpl
diff --git a/mojo/public/system/async_waiter.h b/mojo/public/system/async_waiter.h
deleted file mode 100644
index 6726b46..0000000
--- a/mojo/public/system/async_waiter.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_SYSTEM_ASYNC_WAITER_H_
-#define MOJO_PUBLIC_SYSTEM_ASYNC_WAITER_H_
-
-#include "mojo/public/system/core.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef uintptr_t MojoAsyncWaitID;
-
-typedef void (*MojoAsyncWaitCallback)(void* closure, MojoResult result);
-
-struct MojoAsyncWaiter {
-  // Asynchronously call MojoWait on a background thread, and pass the result
-  // of MojoWait to the given MojoAsyncWaitCallback on the current thread.
-  // Returns a non-zero MojoAsyncWaitID that can be used with CancelWait to
-  // stop waiting. This identifier becomes invalid once the callback runs.
-  MojoAsyncWaitID (*AsyncWait)(struct MojoAsyncWaiter* waiter,
-                               MojoHandle handle,
-                               MojoWaitFlags flags,
-                               MojoDeadline deadline,
-                               MojoAsyncWaitCallback callback,
-                               void* closure);
-
-  // Cancel an existing call to AsyncWait with the given MojoAsyncWaitID. The
-  // corresponding MojoAsyncWaitCallback will not be called in this case.
-  void (*CancelWait)(struct MojoAsyncWaiter* waiter,
-                     MojoAsyncWaitID wait_id);
-};
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // MOJO_PUBLIC_SYSTEM_ASYNC_WAITER_H_
diff --git a/mojo/public/system/core.h b/mojo/public/system/core.h
deleted file mode 100644
index 6e155b1..0000000
--- a/mojo/public/system/core.h
+++ /dev/null
@@ -1,829 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_SYSTEM_CORE_H_
-#define MOJO_PUBLIC_SYSTEM_CORE_H_
-
-// Note: This header should be compilable as C.
-
-#include <stdint.h>
-
-#include "mojo/public/system/macros.h"
-#include "mojo/public/system/system_export.h"
-
-// Types/constants -------------------------------------------------------------
-
-// TODO(vtl): Notes: Use of undefined flags will lead to undefined behavior
-// (typically they'll be ignored), not necessarily an error.
-
-// |MojoTimeTicks|: Used to specify time ticks. Value is in microseconds.
-
-typedef int64_t MojoTimeTicks;
-
-// |MojoHandle|: Handles to Mojo objects.
-//   |MOJO_HANDLE_INVALID| - A value that is never a valid handle.
-
-typedef uint32_t MojoHandle;
-
-#ifdef __cplusplus
-const MojoHandle MOJO_HANDLE_INVALID = 0;
-#else
-#define MOJO_HANDLE_INVALID ((MojoHandle) 0)
-#endif
-
-// |MojoResult|: Result codes for Mojo operations. Non-negative values are
-// success codes; negative values are error/failure codes.
-//   |MOJO_RESULT_OK| - Not an error; returned on success. Note that positive
-//       |MojoResult|s may also be used to indicate success.
-//   |MOJO_RESULT_CANCELLED| - Operation was cancelled, typically by the caller.
-//   |MOJO_RESULT_UNKNOWN| - Unknown error (e.g., if not enough information is
-//       available for a more specific error).
-//   |MOJO_RESULT_INVALID_ARGUMENT| - Caller specified an invalid argument. This
-//       differs from |MOJO_RESULT_FAILED_PRECONDITION| in that the former
-//       indicates arguments that are invalid regardless of the state of the
-//       system.
-//   |MOJO_RESULT_DEADLINE_EXCEEDED| - Deadline expired before the operation
-//       could complete.
-//   |MOJO_RESULT_NOT_FOUND| - Some requested entity was not found (i.e., does
-//       not exist).
-//   |MOJO_RESULT_ALREADY_EXISTS| - Some entity or condition that we attempted
-//       to create already exists.
-//   |MOJO_RESULT_PERMISSION_DENIED| - The caller does not have permission to
-//       for the operation (use |MOJO_RESULT_RESOURCE_EXHAUSTED| for rejections
-//       caused by exhausting some resource instead).
-//   |MOJO_RESULT_RESOURCE_EXHAUSTED| - Some resource required for the call
-//       (possibly some quota) has been exhausted.
-//   |MOJO_RESULT_FAILED_PRECONDITION| - The system is not in a state required
-//       for the operation (use this if the caller must do something to rectify
-//       the state before retrying).
-//   |MOJO_RESULT_ABORTED| - The operation was aborted by the system, possibly
-//       due to a concurrency issue (use this if the caller may retry at a
-//       higher level).
-//   |MOJO_RESULT_OUT_OF_RANGE| - The operation was attempted past the valid
-//       range. Unlike |MOJO_RESULT_INVALID_ARGUMENT|, this indicates that the
-//       operation may be/become valid depending on the system state. (This
-//       error is similar to |MOJO_RESULT_FAILED_PRECONDITION|, but is more
-//       specific.)
-//   |MOJO_RESULT_UNIMPLEMENTED| - The operation is not implemented, supported,
-//       or enabled.
-//   |MOJO_RESULT_INTERNAL| - Internal error: this should never happen and
-//       indicates that some invariant expected by the system has been broken.
-//   |MOJO_RESULT_UNAVAILABLE| - The operation is (temporarily) currently
-//       unavailable. The caller may simply retry the operation (possibly with a
-//       backoff).
-//   |MOJO_RESULT_DATA_LOSS| - Unrecoverable data loss or corruption.
-//   |MOJO_RESULT_BUSY| - One of the resources involved is currently being used
-//       (possibly on another thread) in a way that prevents the current
-//       operation from proceeding, e.g., if the other operation may result in
-//       the resource being invalidated.
-//   |MOJO_RESULT_SHOULD_WAIT| - The request cannot currently be completed
-//       (e.g., if the data requested is not yet available). The caller should
-//       wait for it to be feasible using |MojoWait()| or |MojoWaitMany()|.
-//
-// Note that positive values are also available as success codes.
-//
-// The codes from |MOJO_RESULT_OK| to |MOJO_RESULT_DATA_LOSS| come from
-// Google3's canonical error codes.
-//
-// TODO(vtl): Add a |MOJO_RESULT_UNSATISFIABLE|?
-
-typedef int32_t MojoResult;
-
-#ifdef __cplusplus
-const MojoResult MOJO_RESULT_OK = 0;
-const MojoResult MOJO_RESULT_CANCELLED = -1;
-const MojoResult MOJO_RESULT_UNKNOWN = -2;
-const MojoResult MOJO_RESULT_INVALID_ARGUMENT = -3;
-const MojoResult MOJO_RESULT_DEADLINE_EXCEEDED = -4;
-const MojoResult MOJO_RESULT_NOT_FOUND = -5;
-const MojoResult MOJO_RESULT_ALREADY_EXISTS = -6;
-const MojoResult MOJO_RESULT_PERMISSION_DENIED = -7;
-const MojoResult MOJO_RESULT_RESOURCE_EXHAUSTED = -8;
-const MojoResult MOJO_RESULT_FAILED_PRECONDITION = -9;
-const MojoResult MOJO_RESULT_ABORTED = -10;
-const MojoResult MOJO_RESULT_OUT_OF_RANGE = -11;
-const MojoResult MOJO_RESULT_UNIMPLEMENTED = -12;
-const MojoResult MOJO_RESULT_INTERNAL = -13;
-const MojoResult MOJO_RESULT_UNAVAILABLE = -14;
-const MojoResult MOJO_RESULT_DATA_LOSS = -15;
-const MojoResult MOJO_RESULT_BUSY = -16;
-const MojoResult MOJO_RESULT_SHOULD_WAIT = -17;
-#else
-#define MOJO_RESULT_OK ((MojoResult) 0)
-#define MOJO_RESULT_CANCELLED ((MojoResult) -1)
-#define MOJO_RESULT_UNKNOWN ((MojoResult) -2)
-#define MOJO_RESULT_INVALID_ARGUMENT ((MojoResult) -3)
-#define MOJO_RESULT_DEADLINE_EXCEEDED ((MojoResult) -4)
-#define MOJO_RESULT_NOT_FOUND ((MojoResult) -5)
-#define MOJO_RESULT_ALREADY_EXISTS ((MojoResult) -6)
-#define MOJO_RESULT_PERMISSION_DENIED ((MojoResult) -7)
-#define MOJO_RESULT_RESOURCE_EXHAUSTED ((MojoResult) -8)
-#define MOJO_RESULT_FAILED_PRECONDITION ((MojoResult) -9)
-#define MOJO_RESULT_ABORTED ((MojoResult) -10)
-#define MOJO_RESULT_OUT_OF_RANGE ((MojoResult) -11)
-#define MOJO_RESULT_UNIMPLEMENTED ((MojoResult) -12)
-#define MOJO_RESULT_INTERNAL ((MojoResult) -13)
-#define MOJO_RESULT_UNAVAILABLE ((MojoResult) -14)
-#define MOJO_RESULT_DATA_LOSS ((MojoResult) -15)
-#define MOJO_RESULT_BUSY ((MojoResult) -16)
-#define MOJO_RESULT_SHOULD_WAIT ((MojoResult) -17)
-#endif
-
-// |MojoDeadline|: Used to specify deadlines (timeouts), in microseconds (except
-// for |MOJO_DEADLINE_INDEFINITE|).
-//   |MOJO_DEADLINE_INDEFINITE| - Used to indicate "forever".
-
-typedef uint64_t MojoDeadline;
-
-#ifdef __cplusplus
-const MojoDeadline MOJO_DEADLINE_INDEFINITE = static_cast<MojoDeadline>(-1);
-#else
-#define MOJO_DEADLINE_INDEFINITE ((MojoDeadline) -1)
-#endif
-
-// |MojoWaitFlags|: Used to specify the state of a handle to wait on (e.g., the
-// ability to read or write to it).
-//   |MOJO_WAIT_FLAG_NONE| - No flags. |MojoWait()|, etc. will return
-//       |MOJO_RESULT_FAILED_PRECONDITION| if you attempt to wait on this.
-//   |MOJO_WAIT_FLAG_READABLE| - Can read (e.g., a message) from the handle.
-//   |MOJO_WAIT_FLAG_WRITABLE| - Can write (e.g., a message) to the handle.
-//   |MOJO_WAIT_FLAG_EVERYTHING| - All flags.
-
-typedef uint32_t MojoWaitFlags;
-
-#ifdef __cplusplus
-const MojoWaitFlags MOJO_WAIT_FLAG_NONE = 0;
-const MojoWaitFlags MOJO_WAIT_FLAG_READABLE = 1 << 0;
-const MojoWaitFlags MOJO_WAIT_FLAG_WRITABLE = 1 << 1;
-const MojoWaitFlags MOJO_WAIT_FLAG_EVERYTHING = ~0;
-#else
-#define MOJO_WAIT_FLAG_NONE ((MojoWaitFlags) 0)
-#define MOJO_WAIT_FLAG_READABLE ((MojoWaitFlags) 1 << 0)
-#define MOJO_WAIT_FLAG_WRITABLE ((MojoWaitFlags) 1 << 1)
-#define MOJO_WAIT_FLAG_EVERYTHING (~((MojoWaitFlags) 0))
-#endif
-
-// Message pipe:
-
-// |MojoWriteMessageFlags|: Used to specify different modes to
-// |MojoWriteMessage()|.
-//   |MOJO_WRITE_MESSAGE_FLAG_NONE| - No flags; default mode.
-
-typedef uint32_t MojoWriteMessageFlags;
-
-#ifdef __cplusplus
-const MojoWriteMessageFlags MOJO_WRITE_MESSAGE_FLAG_NONE = 0;
-#else
-#define MOJO_WRITE_MESSAGE_FLAG_NONE ((MojoWriteMessageFlags) 0)
-#endif
-
-// |MojoReadMessageFlags|: Used to specify different modes to
-// |MojoReadMessage()|.
-//   |MOJO_READ_MESSAGE_FLAG_NONE| - No flags; default mode.
-//   |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| - If the message is unable to be read
-//       for whatever reason (e.g., the caller-supplied buffer is too small),
-//       discard the message (i.e., simply dequeue it).
-
-typedef uint32_t MojoReadMessageFlags;
-
-#ifdef __cplusplus
-const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_NONE = 0;
-const MojoReadMessageFlags MOJO_READ_MESSAGE_FLAG_MAY_DISCARD = 1 << 0;
-#else
-#define MOJO_READ_MESSAGE_FLAG_NONE ((MojoReadMessageFlags) 0)
-#define MOJO_READ_MESSAGE_FLAG_MAY_DISCARD ((MojoReadMessageFlags) 1 << 0)
-#endif
-
-// Data pipe:
-
-// |MojoCreateDataPipeOptions|: Used to specify creation parameters for a data
-// pipe to |MojoCreateDataPipe()|.
-//   |uint32_t struct_size|: Set to the size of the |MojoCreateDataPipeOptions|
-//       struct. (Used to allow for future extensions.)
-//   |MojoCreateDataPipeOptionsFlags flags|: Used to specify different modes of
-//       operation.
-//     |MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE|: No flags; default mode.
-//     |MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD|: May discard data for
-//         whatever reason; best-effort delivery. In particular, if the capacity
-//         is reached, old data may be discard to make room for new data.
-//   |uint32_t element_num_bytes|: The size of an element, in bytes. All
-//       transactions and buffers will consist of an integral number of
-//       elements. Must be nonzero.
-//   |uint32_t capacity_num_bytes|: The capacity of the data pipe, in number of
-//       bytes; must be a multiple of |element_num_bytes|. The data pipe will
-//       always be able to queue AT LEAST this much data. Set to zero to opt for
-//       a system-dependent automatically-calculated capacity (which will always
-//       be at least one element).
-
-typedef uint32_t MojoCreateDataPipeOptionsFlags;
-
-#ifdef __cplusplus
-const MojoCreateDataPipeOptionsFlags
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE = 0;
-const MojoCreateDataPipeOptionsFlags
-    MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD = 1 << 0;
-#else
-#define MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE \
-    ((MojoCreateDataPipeOptionsFlags) 0)
-#define MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_MAY_DISCARD \
-    ((MojoCreateDataPipeOptionsFlags) 1 << 0)
-#endif
-
-struct MojoCreateDataPipeOptions {
-  uint32_t struct_size;
-  MojoCreateDataPipeOptionsFlags flags;
-  uint32_t element_num_bytes;
-  uint32_t capacity_num_bytes;
-};
-// TODO(vtl): Can we make this assertion work in C?
-#ifdef __cplusplus
-MOJO_COMPILE_ASSERT(sizeof(MojoCreateDataPipeOptions) == 16,
-                    MojoCreateDataPipeOptions_has_wrong_size);
-#endif
-
-// |MojoWriteDataFlags|: Used to specify different modes to |MojoWriteData()|
-// and |MojoBeginWriteData()|.
-//   |MOJO_WRITE_DATA_FLAG_NONE| - No flags; default mode.
-//   |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| - Write either all the elements
-//       requested or none of them.
-
-typedef uint32_t MojoWriteDataFlags;
-
-#ifdef __cplusplus
-const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_NONE = 0;
-const MojoWriteDataFlags MOJO_WRITE_DATA_FLAG_ALL_OR_NONE = 1 << 0;
-#else
-#define MOJO_WRITE_DATA_FLAG_NONE ((MojoWriteDataFlags) 0)
-#define MOJO_WRITE_DATA_FLAG_ALL_OR_NONE ((MojoWriteDataFlags) 1 << 0)
-#endif
-
-// |MojoReadDataFlags|: Used to specify different modes to |MojoReadData()| and
-// |MojoBeginReadData()|.
-//   |MOJO_READ_DATA_FLAG_NONE| - No flags; default mode.
-//   |MOJO_READ_DATA_FLAG_ALL_OR_NONE| - Read (or discard) either the requested
-//        number of elements or none.
-//   |MOJO_READ_DATA_FLAG_DISCARD| - Discard (up to) the requested number of
-//        elements.
-//   |MOJO_READ_DATA_FLAG_QUERY| - Query the number of elements available to
-//       read. For use with |MojoReadData()| only. Mutually exclusive with
-//       |MOJO_READ_DATA_FLAG_DISCARD| and |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is
-//       ignored if this flag is set.
-
-typedef uint32_t MojoReadDataFlags;
-
-#ifdef __cplusplus
-const MojoReadDataFlags MOJO_READ_DATA_FLAG_NONE = 0;
-const MojoReadDataFlags MOJO_READ_DATA_FLAG_ALL_OR_NONE = 1 << 0;
-const MojoReadDataFlags MOJO_READ_DATA_FLAG_DISCARD = 1 << 1;
-const MojoReadDataFlags MOJO_READ_DATA_FLAG_QUERY = 1 << 2;
-#else
-#define MOJO_READ_DATA_FLAG_NONE ((MojoReadDataFlags) 0)
-#define MOJO_READ_DATA_FLAG_ALL_OR_NONE ((MojoReadDataFlags) 1 << 0)
-#define MOJO_READ_DATA_FLAG_DISCARD ((MojoReadDataFlags) 1 << 1)
-#define MOJO_READ_DATA_FLAG_QUERY ((MojoReadDataFlags) 1 << 2)
-#endif
-
-// Shared buffer:
-
-// |MojoCreateSharedBufferOptions|: Used to specify creation parameters for a
-// shared buffer to |MojoCreateSharedBuffer()|.
-//   |uint32_t struct_size|: Set to the size of the
-//       |MojoCreateSharedBufferOptions| struct. (Used to allow for future
-//       extensions.)
-//   |MojoCreateSharedBufferOptionsFlags flags|: Reserved for future use.
-//       |MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE|: No flags; default mode.
-//
-// TODO(vtl): Maybe add a flag to indicate whether the memory should be
-// executable or not?
-// TODO(vtl): Also a flag for discardable (ashmem-style) buffers.
-
-typedef uint32_t MojoCreateSharedBufferOptionsFlags;
-
-#ifdef __cplusplus
-const MojoCreateSharedBufferOptionsFlags
-    MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE = 0;
-#else
-#define MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE \
-    ((MojoCreateSharedBufferOptionsFlags) 0)
-#endif
-
-struct MojoCreateSharedBufferOptions {
-  uint32_t struct_size;
-  MojoCreateSharedBufferOptionsFlags flags;
-};
-// TODO(vtl): Can we make this assertion work in C?
-#ifdef __cplusplus
-MOJO_COMPILE_ASSERT(sizeof(MojoCreateSharedBufferOptions) == 8,
-                    MojoCreateSharedBufferOptions_has_wrong_size);
-#endif
-
-// |MojoDuplicateBufferHandleOptions|: Used to specify parameters in duplicating
-// access to a shared buffer to |MojoDuplicateBufferHandle()|.
-//   |uint32_t struct_size|: Set to the size of the
-//       |MojoDuplicateBufferHandleOptions| struct. (Used to allow for future
-//       extensions.)
-//   |MojoDuplicateBufferHandleOptionsFlags flags|: Reserved for future use.
-//       |MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE|: No flags; default
-//       mode.
-//
-// TODO(vtl): Add flags to remove writability (and executability)? Also, COW?
-
-typedef uint32_t MojoDuplicateBufferHandleOptionsFlags;
-
-#ifdef __cplusplus
-const MojoDuplicateBufferHandleOptionsFlags
-    MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE = 0;
-#else
-#define MOJO_DUPLICATE_BUFFER_HANDLE_OPTIONS_FLAG_NONE \
-    ((MojoDuplicateBufferHandleOptionsFlags) 0)
-#endif
-
-struct MojoDuplicateBufferHandleOptions {
-  uint32_t struct_size;
-  MojoDuplicateBufferHandleOptionsFlags flags;
-};
-// TODO(vtl): Can we make this assertion work in C?
-#ifdef __cplusplus
-MOJO_COMPILE_ASSERT(sizeof(MojoDuplicateBufferHandleOptions) == 8,
-                    MojoDuplicateBufferHandleOptions_has_wrong_size);
-#endif
-
-// |MojoMapBufferFlags|: Used to specify different modes to |MojoMapBuffer()|.
-//   |MOJO_MAP_BUFFER_FLAG_NONE| - No flags; default mode.
-
-typedef uint32_t MojoMapBufferFlags;
-
-#ifdef __cplusplus
-const MojoMapBufferFlags MOJO_MAP_BUFFER_FLAG_NONE = 0;
-#else
-#define MOJO_MAP_BUFFER_FLAG_NONE ((MojoMapBufferFlags) 0)
-#endif
-
-// Functions -------------------------------------------------------------------
-
-// Note: Pointer parameters that are labeled "optional" may be null (at least
-// under some circumstances). Non-const pointer parameters are also labelled
-// "in", "out", or "in/out", to indicate how they are used. (Note that how/if
-// such a parameter is used may depend on other parameters or the requested
-// operation's success/failure. E.g., a separate |flags| parameter may control
-// whether a given "in/out" parameter is used for input, output, or both.)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// Platform-dependent monotonically increasing tick count representing "right
-// now." The resolution of this clock is ~1-15ms.  Resolution varies depending
-// on hardware/operating system configuration.
-MOJO_SYSTEM_EXPORT MojoTimeTicks MojoGetTimeTicksNow();
-
-// Closes the given |handle|.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle.
-//
-// Concurrent operations on |handle| may succeed (or fail as usual) if they
-// happen before the close, be cancelled with result |MOJO_RESULT_CANCELLED| if
-// they properly overlap (this is likely the case with |MojoWait()|, etc.), or
-// fail with |MOJO_RESULT_INVALID_ARGUMENT| if they happen after.
-MOJO_SYSTEM_EXPORT MojoResult MojoClose(MojoHandle handle);
-
-// Waits on the given handle until the state indicated by |flags| is satisfied
-// or until |deadline| has passed.
-//
-// Returns:
-//   |MOJO_RESULT_OK| if some flag in |flags| was satisfied (or is already
-//        satisfied).
-//   |MOJO_RESULT_INVALID_ARGUMENT| if |handle| is not a valid handle (e.g., if
-//       it has already been closed).
-//   |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of
-//       the flags being satisfied.
-//   |MOJO_RESULT_FAILED_PRECONDITION| if it is or becomes impossible that any
-//       flag in |flags| will ever be satisfied.
-//
-// If there are multiple waiters (on different threads, obviously) waiting on
-// the same handle and flag and that flag becomes set, all waiters will be
-// awoken.
-MOJO_SYSTEM_EXPORT MojoResult MojoWait(MojoHandle handle,
-                                       MojoWaitFlags flags,
-                                       MojoDeadline deadline);
-
-// Waits on |handles[0]|, ..., |handles[num_handles-1]| for at least one of them
-// to satisfy the state indicated by |flags[0]|, ..., |flags[num_handles-1]|,
-// respectively, or until |deadline| has passed.
-//
-// Returns:
-//   The index |i| (from 0 to |num_handles-1|) if |handle[i]| satisfies
-//       |flags[i]|.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some |handle[i]| is not a valid handle
-//       (e.g., if it has already been closed).
-//   |MOJO_RESULT_DEADLINE_EXCEEDED| if the deadline has passed without any of
-//       handles satisfying any of its flags.
-//   |MOJO_RESULT_FAILED_PRECONDITION| if it is or becomes impossible that SOME
-//       |handle[i]| will ever satisfy any of its flags |flags[i]|.
-MOJO_SYSTEM_EXPORT MojoResult MojoWaitMany(const MojoHandle* handles,
-                                           const MojoWaitFlags* flags,
-                                           uint32_t num_handles,
-                                           MojoDeadline deadline);
-
-// Message pipe:
-
-// Creates a message pipe, which is a bidirectional communication channel for
-// framed data (i.e., messages). Messages can contain plain data and/or Mojo
-// handles. On success, |*message_pipe_handle0| and |*message_pipe_handle1| are
-// set to handles for the two endpoints (ports) for the message pipe.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if |message_pipe_handle0| and/or
-//       |message_pipe_handle1| do not appear to be valid pointers.
-//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
-//       been reached.
-//
-// TODO(vtl): Add an options struct pointer argument.
-MOJO_SYSTEM_EXPORT MojoResult MojoCreateMessagePipe(
-    MojoHandle* message_pipe_handle0,  // Out.
-    MojoHandle* message_pipe_handle1);  // Out.
-
-// Writes a message to the message pipe endpoint given by |message_pipe_handle|,
-// with message data specified by |bytes| of size |num_bytes| and attached
-// handles specified by |handles| of count |num_handles|, and options specified
-// by |flags|. If there is no message data, |bytes| may be null, in which case
-// |num_bytes| must be zero. If there are no attached handles, |handles| may be
-// null, in which case |num_handles| must be zero.
-//
-// If handles are attached, on success the handles will no longer be valid (the
-// receiver will receive equivalent, but logically different, handles). Handles
-// to be sent should not be in simultaneous use (e.g., on another thread).
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success (i.e., the message was enqueued).
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
-//       |message_pipe_handle| is not a valid handle, or some of the
-//       requirements above are not satisfied).
-//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if some system limit has been reached, or
-//       the number of handles to send is too large (TODO(vtl): reconsider the
-//       latter case).
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
-//       Note that closing an endpoint is not necessarily synchronous (e.g.,
-//       across processes), so this function may be succeed even if the other
-//       endpoint has been closed (in which case the message would be dropped).
-//   |MOJO_RESULT_BUSY| if some handle to be sent is currently in use.
-//
-// TODO(vtl): Add a notion of capacity for message pipes, and return
-// |MOJO_RESULT_SHOULD_WAIT| if the message pipe is full.
-MOJO_SYSTEM_EXPORT MojoResult MojoWriteMessage(
-    MojoHandle message_pipe_handle,
-    const void* bytes,  // Optional.
-    uint32_t num_bytes,
-    const MojoHandle* handles,  // Optional.
-    uint32_t num_handles,
-    MojoWriteMessageFlags flags);
-
-// Reads a message from the message pipe endpoint given by
-// |message_pipe_handle|; also usable to query the size of the next message or
-// discard the next message. |bytes|/|*num_bytes| indicate the buffer/buffer
-// size to receive the message data (if any) and |handles|/|*num_handles|
-// indicate the buffer/maximum handle count to receive the attached handles (if
-// any).
-//
-// |num_bytes| and |num_handles| are optional "in-out" parameters. If non-null,
-// on return |*num_bytes| and |*num_handles| will usually indicate the number
-// of bytes and number of attached handles in the "next" message, respectively,
-// whether that message was read or not. (If null, the number of bytes/handles
-// is treated as zero.)
-//
-// If |bytes| is null, then |*num_bytes| must be zero, and similarly for
-// |handles| and |*num_handles|.
-//
-// Partial reads are NEVER done. Either a full read is done and |MOJO_RESULT_OK|
-// returned, or the read is NOT done and |MOJO_RESULT_RESOURCE_EXHAUSTED| is
-// returned (if |MOJO_READ_MESSAGE_FLAG_MAY_DISCARD| was set, the message is
-// also discarded in this case).
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success (i.e., a message was actually read).
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid.
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the other endpoint has been closed.
-//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if one of the buffers to receive the
-//       message/attached handles (|bytes|/|*num_bytes| or
-//       |handles|/|*num_handles|) was too small. (TODO(vtl): Reconsider this
-//       error code; should distinguish this from the hitting-system-limits
-//       case.)
-//   |MOJO_RESULT_SHOULD_WAIT| if no message was available to be read.
-MOJO_SYSTEM_EXPORT MojoResult MojoReadMessage(
-    MojoHandle message_pipe_handle,
-    void* bytes,  // Optional out.
-    uint32_t* num_bytes,  // Optional in/out.
-    MojoHandle* handles,  // Optional out.
-    uint32_t* num_handles,  // Optional in/out.
-    MojoReadMessageFlags flags);
-
-// Data pipe:
-
-// Creates a data pipe, which is a unidirectional communication channel for
-// unframed data, with the given options. Data is unframed, but must come as
-// (multiples of) discrete elements, of the size given in |options|. See
-// |MojoCreateDataPipeOptions| for a description of the different options
-// available for data pipes.
-//
-// |options| may be set to null for a data pipe with the default options (which
-// will have an element size of one byte and have some system-dependent
-// capacity).
-//
-// On success, |*data_pipe_producer_handle| will be set to the handle for the
-// producer and |*data_pipe_consumer_handle| will be set to the handle for the
-// consumer. (On failure, they are not modified.)
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
-//       |*options| is invalid or one of the pointer handles looks invalid).
-//   |MOJO_RESULT_RESOURCE_EXHAUSTED| if a process/system/quota/etc. limit has
-//       been reached (e.g., if the requested capacity was too large, or if the
-//       maximum number of handles was exceeded).
-MOJO_SYSTEM_EXPORT MojoResult MojoCreateDataPipe(
-    const struct MojoCreateDataPipeOptions* options,  // Optional.
-    MojoHandle* data_pipe_producer_handle,  // Out.
-    MojoHandle* data_pipe_consumer_handle);  // Out.
-
-// Writes the given data to the data pipe producer given by
-// |data_pipe_producer_handle|. |elements| points to data of size |*num_bytes|;
-// |*num_bytes| should be a multiple of the data pipe's element size. If
-// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| is set in |flags|, either all the data
-// will be written or none is.
-//
-// On success, |*num_bytes| is set to the amount of data that was actually
-// written.
-//
-// Note: If the data pipe has the "may discard" option flag (specified on
-// creation), this will discard as much data as required to write the given
-// data, starting with the earliest written data that has not been consumed.
-// However, even with "may discard", if |*num_bytes| is greater than the data
-// pipe's capacity (and |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| is not set), this
-// will write the maximum amount possible (namely, the data pipe's capacity) and
-// set |*num_bytes| to that amount. It will *not* discard data from |elements|.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
-//       |data_pipe_producer_dispatcher| is not a handle to a data pipe
-//       producer, |elements| does not look like a valid pointer, or
-//       |*num_bytes| is not a multiple of the data pipe's element size).
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
-//       closed.
-//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has
-//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
-//       (specified by |*num_bytes|) could not be written.
-//   |MOJO_RESULT_BUSY| if there is a two-phase write ongoing with
-//       |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
-//       called, but not yet the matching |MojoEndWriteData()|).
-//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
-//       consumer is still open) and |flags| does *not* have
-//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set.
-//
-// TODO(vtl): Should there be a way of querying how much data can be written?
-MOJO_SYSTEM_EXPORT MojoResult MojoWriteData(
-    MojoHandle data_pipe_producer_handle,
-    const void* elements,
-    uint32_t* num_bytes,  // In/out.
-    MojoWriteDataFlags flags);
-
-// Begins a two-phase write to the data pipe producer given by
-// |data_pipe_producer_handle|. On success, |*buffer| will be a pointer to which
-// the caller can write |*buffer_num_bytes| bytes of data. If flags has
-// |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set, then the output value
-// |*buffer_num_bytes| will be at least as large as its input value, which must
-// also be a multiple of the element size (if |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE|
-// is not set, the input value of |*buffer_num_bytes| is ignored).
-//
-// During a two-phase write, |data_pipe_producer_handle| is *not* writable.
-// E.g., if another thread tries to write to it, it will get |MOJO_RESULT_BUSY|;
-// that thread can then wait for |data_pipe_producer_handle| to become writable
-// again.
-//
-// Once the caller has finished writing data to |*buffer|, it should call
-// |MojoEndWriteData()| to specify the amount written and to complete the
-// two-phase write.
-//
-// Note: If the data pipe has the "may discard" option flag (specified on
-// creation) and |flags| has |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set, this may
-// discard some data.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
-//       |data_pipe_producer_handle| is not a handle to a data pipe producer,
-//       |buffer| or |buffer_num_bytes| does not look like a valid pointer, or
-//       flags has |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and
-//       |*buffer_num_bytes| is not a multiple of the element size).
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer handle has been
-//       closed.
-//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has
-//       |MOJO_WRITE_DATA_FLAG_ALL_OR_NONE| set and the required amount of data
-//       (specified by |*buffer_num_bytes|) cannot be written contiguously at
-//       this time. (Note that there may be space available for the required
-//       amount of data, but the "next" write position may not be large enough.)
-//   |MOJO_RESULT_BUSY| if there is already a two-phase write ongoing with
-//       |data_pipe_producer_handle| (i.e., |MojoBeginWriteData()| has been
-//       called, but not yet the matching |MojoEndWriteData()|).
-//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be written (and the
-//       consumer is still open).
-MOJO_SYSTEM_EXPORT MojoResult MojoBeginWriteData(
-    MojoHandle data_pipe_producer_handle,
-    void** buffer,  // Out.
-    uint32_t* buffer_num_bytes,  // In/out.
-    MojoWriteDataFlags flags);
-
-// Ends a two-phase write to the data pipe producer given by
-// |data_pipe_producer_handle| that was begun by a call to
-// |MojoBeginWriteData()| on the same handle. |num_bytes_written| should
-// indicate the amount of data actually written; it must be less than or equal
-// to the value of |*buffer_num_bytes| output by |MojoBeginWriteData()| and must
-// be a multiple of the element size. The buffer given by |*buffer| from
-// |MojoBeginWriteData()| must have been filled with exactly |num_bytes_written|
-// bytes of data.
-//
-// On failure, the two-phase write (if any) is ended (so the handle may become
-// writable again, if there's space available) but no data written to |*buffer|
-// is "put into" the data pipe.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if |data_pipe_producer_handle| is not a
-//       handle to a data pipe producer or |num_bytes_written| is invalid
-//       (greater than the maximum value provided by |MojoBeginWriteData()| or
-//       not a multiple of the element size).
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer is not in a
-//       two-phase write (e.g., |MojoBeginWriteData()| was not called or
-//       |MojoEndWriteData()| has already been called).
-MOJO_SYSTEM_EXPORT MojoResult MojoEndWriteData(
-    MojoHandle data_pipe_producer_handle,
-    uint32_t num_bytes_written);
-
-// Reads data from the data pipe consumer given by |data_pipe_consumer_handle|.
-// May also be used to discard data or query the amount of data available.
-//
-// If |flags| has neither |MOJO_READ_DATA_FLAG_DISCARD| nor
-// |MOJO_READ_DATA_FLAG_QUERY| set, this tries to read up to |*num_bytes| (which
-// must be a multiple of the data pipe's element size) bytes of data to
-// |elements| and set |*num_bytes| to the amount actually read. If flags has
-// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, it will either read exactly
-// |*num_bytes| bytes of data or none.
-//
-// If flags has |MOJO_READ_DATA_FLAG_DISCARD| set, it discards up to
-// |*num_bytes| (which again be a multiple of the element size) bytes of data,
-// setting |*num_bytes| to the amount actually discarded. If flags has
-// |MOJO_READ_DATA_FLAG_ALL_OR_NONE|, it will either discard exactly
-// |*num_bytes| bytes of data or none. In this case, |MOJO_READ_DATA_FLAG_QUERY|
-// must not be set, and |elements| is ignored (and should typically be set to
-// null).
-//
-// If flags has |MOJO_READ_DATA_FLAG_QUERY| set, it queries the amount of data
-// available, setting |*num_bytes| to the number of bytes available. In this
-// case, |MOJO_READ_DATA_FLAG_DISCARD| must not be set, and
-// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| is ignored, as are |elements| and the input
-// value of |*num_bytes|.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success (see above for a description of the different
-//       operations).
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g.,
-//       |data_pipe_consumer_handle| is invalid, the combination of flags in
-//       |flags| is invalid, etc.).
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
-//       closed and data (or the required amount of data) was not available to
-//       be read or discarded.
-//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
-//       set and the required amount of data is not available to be read or
-//       discarded (and the producer is still open).
-//   |MOJO_RESULT_BUSY| if there is a two-phase read ongoing with
-//       |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
-//       called, but not yet the matching |MojoEndReadData()|).
-//   |MOJO_RESULT_SHOULD_WAIT| if there is no data to be read or discarded (and
-//       the producer is still open) and |flags| does *not* have
-//       |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set.
-MOJO_SYSTEM_EXPORT MojoResult MojoReadData(
-    MojoHandle data_pipe_consumer_handle,
-    void* elements,  // Out.
-    uint32_t* num_bytes,  // In/out.
-    MojoReadDataFlags flags);
-
-// Begins a two-phase read from the data pipe consumer given by
-// |data_pipe_consumer_handle|. On success, |*buffer| will be a pointer from
-// which the caller can read |*buffer_num_bytes| bytes of data. If flags has
-// |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set, then the output value
-// |*buffer_num_bytes| will be at least as large as its input value, which must
-// also be a multiple of the element size (if |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
-// is not set, the input value of |*buffer_num_bytes| is ignored). |flags| must
-// not have |MOJO_READ_DATA_FLAG_DISCARD| or |MOJO_READ_DATA_FLAG_QUERY| set.
-//
-// During a two-phase read, |data_pipe_consumer_handle| is *not* readable.
-// E.g., if another thread tries to read from it, it will get
-// |MOJO_RESULT_BUSY|; that thread can then wait for |data_pipe_consumer_handle|
-// to become readable again.
-//
-// Once the caller has finished reading data from |*buffer|, it should call
-// |MojoEndReadData()| to specify the amount read and to complete the two-phase
-// read.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if some argument was invalid (e.g., if
-//       |data_pipe_consumer_handle| is not a handle to a data pipe consumer,
-//       |buffer| or |buffer_num_bytes| does not look like a valid pointer,
-//       |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE| set and
-//       |*buffer_num_bytes| is not a multiple of the element size, or |flags|
-//       has invalid flags set).
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe producer handle has been
-//       closed.
-//   |MOJO_RESULT_OUT_OF_RANGE| if |flags| has |MOJO_READ_DATA_FLAG_ALL_OR_NONE|
-//       set and the required amount of data (specified by |*buffer_num_bytes|)
-//       cannot be read from a contiguous buffer at this time. (Note that there
-//       may be the required amount of data, but it may not be contiguous.)
-//   |MOJO_RESULT_BUSY| if there is already a two-phase read ongoing with
-//       |data_pipe_consumer_handle| (i.e., |MojoBeginReadData()| has been
-//       called, but not yet the matching |MojoEndReadData()|).
-//   |MOJO_RESULT_SHOULD_WAIT| if no data can currently be read (and the
-//       producer is still open).
-MOJO_SYSTEM_EXPORT MojoResult MojoBeginReadData(
-    MojoHandle data_pipe_consumer_handle,
-    const void** buffer,  // Out.
-    uint32_t* buffer_num_bytes,  // In/out.
-    MojoReadDataFlags flags);
-
-// Ends a two-phase read from the data pipe consumer given by
-// |data_pipe_consumer_handle| that was begun by a call to |MojoBeginReadData()|
-// on the same handle. |num_bytes_read| should indicate the amount of data
-// actually read; it must be less than or equal to the value of
-// |*buffer_num_bytes| output by |MojoBeginReadData()| and must be a multiple of
-// the element size.
-//
-// On failure, the two-phase read (if any) is ended (so the handle may become
-// readable again) but no data is "removed" from the data pipe.
-//
-// Returns:
-//   |MOJO_RESULT_OK| on success.
-//   |MOJO_RESULT_INVALID_ARGUMENT| if |data_pipe_consumer_handle| is not a
-//       handle to a data pipe consumer or |num_bytes_written| is invalid
-//       (greater than the maximum value provided by |MojoBeginReadData()| or
-//       not a multiple of the element size).
-//   |MOJO_RESULT_FAILED_PRECONDITION| if the data pipe consumer is not in a
-//       two-phase read (e.g., |MojoBeginReadData()| was not called or
-//       |MojoEndReadData()| has already been called).
-MOJO_SYSTEM_EXPORT MojoResult MojoEndReadData(
-    MojoHandle data_pipe_consumer_handle,
-    uint32_t num_bytes_read);
-
-// Shared buffer:
-
-// TODO(vtl): General comments.
-
-// Creates a buffer that can be shared between applications (by duplicating the
-// handle -- see |MojoDuplicateBufferHandle()| -- and passing it over a message
-// pipe). To access the buffer, one must call |MojoMapBuffer()|.
-// TODO(vtl): More.
-MOJO_SYSTEM_EXPORT MojoResult MojoCreateSharedBuffer(
-    const struct MojoCreateSharedBufferOptions* options,  // Optional.
-    uint64_t num_bytes,  // In.
-    MojoHandle* shared_buffer_handle);  // Out.
-
-// Duplicates the handle |buffer_handle| to a buffer. This creates another
-// handle (returned in |*new_buffer_handle| on success), which can then be sent
-// to another application over a message pipe, while retaining access to the
-// |buffer_handle| (and any mappings that it may have).
-//
-// Note: We may add buffer types for which this operation is not supported.
-// TODO(vtl): More.
-MOJO_SYSTEM_EXPORT MojoResult MojoDuplicateBufferHandle(
-    MojoHandle buffer_handle,
-    const struct MojoDuplicateBufferHandleOptions* options,  // Optional.
-    MojoHandle* new_buffer_handle);  // Out.
-
-// Map the part (at offset |offset| of length |num_bytes|) of the buffer given
-// by |buffer_handle| into memory. |offset + num_bytes| must be less than or
-// equal to the size of the buffer. On success, |*buffer| points to memory with
-// the requested part of the buffer.
-//
-// A single buffer handle may have multiple active mappings (possibly depending
-// on the buffer type). The permissions (e.g., writable or executable) of the
-// returned memory may depend on the properties of the buffer and properties
-// attached to the buffer handle as well as |flags|.
-// TODO(vtl): More.
-MOJO_SYSTEM_EXPORT MojoResult MojoMapBuffer(MojoHandle buffer_handle,
-                                            uint64_t offset,
-                                            uint64_t num_bytes,
-                                            void** buffer,  // Out.
-                                            MojoMapBufferFlags flags);
-
-// Unmap a buffer pointer that was mapped by |MojoMapBuffer()|.
-// TODO(vtl): More.
-MOJO_SYSTEM_EXPORT MojoResult MojoUnmapBuffer(void* buffer);  // In.
-
-#ifdef __cplusplus
-}  // extern "C"
-#endif
-
-#endif  // MOJO_PUBLIC_SYSTEM_CORE_H_
diff --git a/mojo/public/system/core_cpp.h b/mojo/public/system/core_cpp.h
deleted file mode 100644
index 535ad19..0000000
--- a/mojo/public/system/core_cpp.h
+++ /dev/null
@@ -1,467 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_SYSTEM_CORE_CPP_H_
-#define MOJO_PUBLIC_SYSTEM_CORE_CPP_H_
-
-#include <assert.h>
-#include <stddef.h>
-
-#include <limits>
-
-#include "mojo/public/system/core.h"
-#include "mojo/public/system/macros.h"
-#include "mojo/public/system/system_export.h"
-
-namespace mojo {
-
-// Standalone functions --------------------------------------------------------
-
-inline MojoTimeTicks GetTimeTicksNow() {
-  return MojoGetTimeTicksNow();
-}
-
-// ScopedHandleBase ------------------------------------------------------------
-
-// Scoper for the actual handle types defined further below. It's move-only,
-// like the C++11 |unique_ptr|.
-template <class HandleType>
-class ScopedHandleBase {
-  MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(ScopedHandleBase, RValue)
-
- public:
-  ScopedHandleBase() {}
-  explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
-  ~ScopedHandleBase() { CloseIfNecessary(); }
-
-  template <class CompatibleHandleType>
-  explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other)
-      : handle_(other.release()) {
-  }
-
-  // Move-only constructor and operator=.
-  ScopedHandleBase(RValue other) : handle_(other.object->release()) {}
-  ScopedHandleBase& operator=(RValue other) {
-    handle_ = other.object->release();
-    return *this;
-  }
-
-  const HandleType& get() const { return handle_; }
-
-  void swap(ScopedHandleBase& other) {
-    handle_.swap(other.handle_);
-  }
-
-  HandleType release() MOJO_WARN_UNUSED_RESULT {
-    HandleType rv;
-    rv.swap(handle_);
-    return rv;
-  }
-
-  void reset(HandleType handle = HandleType()) {
-    CloseIfNecessary();
-    handle_ = handle;
-  }
-
-  bool is_valid() const {
-    return handle_.is_valid();
-  }
-
- private:
-  void CloseIfNecessary() {
-    if (!handle_.is_valid())
-      return;
-    MojoResult result MOJO_ALLOW_UNUSED = MojoClose(handle_.value());
-    assert(result == MOJO_RESULT_OK);
-  }
-
-  HandleType handle_;
-};
-
-template <typename HandleType>
-inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
-  return ScopedHandleBase<HandleType>(handle);
-}
-
-// Handle ----------------------------------------------------------------------
-
-const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
-
-// Wrapper base class for |MojoHandle|.
-class Handle {
- public:
-  Handle() : value_(MOJO_HANDLE_INVALID) {}
-  explicit Handle(MojoHandle value) : value_(value) {}
-  ~Handle() {}
-
-  void swap(Handle& other) {
-    MojoHandle temp = value_;
-    value_ = other.value_;
-    other.value_ = temp;
-  }
-
-  bool is_valid() const {
-    return value_ != MOJO_HANDLE_INVALID;
-  }
-
-  MojoHandle value() const { return value_; }
-  MojoHandle* mutable_value() { return &value_; }
-  void set_value(MojoHandle value) { value_ = value; }
-
- private:
-  MojoHandle value_;
-
-  // Copying and assignment allowed.
-};
-
-// Should have zero overhead.
-MOJO_COMPILE_ASSERT(sizeof(Handle) == sizeof(MojoHandle),
-                    bad_size_for_cpp_Handle);
-
-// The scoper should also impose no more overhead.
-typedef ScopedHandleBase<Handle> ScopedHandle;
-MOJO_COMPILE_ASSERT(sizeof(ScopedHandle) == sizeof(Handle),
-                    bad_size_for_cpp_ScopedHandle);
-
-inline MojoResult Wait(const Handle& handle,
-                       MojoWaitFlags flags,
-                       MojoDeadline deadline) {
-  return MojoWait(handle.value(), flags, deadline);
-}
-
-// |HandleVectorType| and |FlagsVectorType| should be similar enough to
-// |std::vector<Handle>| and |std::vector<MojoWaitFlags>|, respectively:
-//  - They should have a (const) |size()| method that returns an unsigned type.
-//  - They must provide contiguous storage, with access via (const) reference to
-//    that storage provided by a (const) |operator[]()| (by reference).
-template <class HandleVectorType, class FlagsVectorType>
-inline MojoResult WaitMany(const HandleVectorType& handles,
-                           const FlagsVectorType& flags,
-                           MojoDeadline deadline) {
-  if (flags.size() != handles.size())
-    return MOJO_RESULT_INVALID_ARGUMENT;
-  if (handles.size() > std::numeric_limits<uint32_t>::max())
-    return MOJO_RESULT_OUT_OF_RANGE;
-
-  if (handles.size() == 0)
-    return MojoWaitMany(NULL, NULL, 0, deadline);
-
-  const Handle& first_handle = handles[0];
-  const MojoWaitFlags& first_flag = flags[0];
-  return MojoWaitMany(reinterpret_cast<const MojoHandle*>(&first_handle),
-                      reinterpret_cast<const MojoWaitFlags*>(&first_flag),
-                      static_cast<uint32_t>(handles.size()),
-                      deadline);
-}
-
-// |Close()| takes ownership of the handle, since it'll invalidate it.
-// Note: There's nothing to do, since the argument will be destroyed when it
-// goes out of scope.
-template <class HandleType>
-inline void Close(ScopedHandleBase<HandleType> /*handle*/) {}
-
-// Most users should typically use |Close()| (above) instead.
-inline MojoResult CloseRaw(Handle handle) {
-  return MojoClose(handle.value());
-}
-
-// Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s,
-// etc.
-inline bool operator<(const Handle& a, const Handle& b) {
-  return a.value() < b.value();
-}
-
-// MessagePipeHandle -----------------------------------------------------------
-
-class MessagePipeHandle : public Handle {
- public:
-  MessagePipeHandle() {}
-  explicit MessagePipeHandle(MojoHandle value) : Handle(value) {}
-
-  // Copying and assignment allowed.
-};
-
-MOJO_COMPILE_ASSERT(sizeof(MessagePipeHandle) == sizeof(Handle),
-                    bad_size_for_cpp_MessagePipeHandle);
-
-typedef ScopedHandleBase<MessagePipeHandle> ScopedMessagePipeHandle;
-MOJO_COMPILE_ASSERT(sizeof(ScopedMessagePipeHandle) ==
-                        sizeof(MessagePipeHandle),
-                    bad_size_for_cpp_ScopedMessagePipeHandle);
-
-inline MojoResult CreateMessagePipe(ScopedMessagePipeHandle* message_pipe0,
-                                    ScopedMessagePipeHandle* message_pipe1) {
-  assert(message_pipe0);
-  assert(message_pipe1);
-  MessagePipeHandle handle0;
-  MessagePipeHandle handle1;
-  MojoResult rv = MojoCreateMessagePipe(handle0.mutable_value(),
-                                        handle1.mutable_value());
-  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
-  // will be used).
-  message_pipe0->reset(handle0);
-  message_pipe1->reset(handle1);
-  return rv;
-}
-
-// These "raw" versions fully expose the underlying API, but don't help with
-// ownership of handles (especially when writing messages).
-// TODO(vtl): Write "baked" versions.
-inline MojoResult WriteMessageRaw(MessagePipeHandle message_pipe,
-                                  const void* bytes,
-                                  uint32_t num_bytes,
-                                  const MojoHandle* handles,
-                                  uint32_t num_handles,
-                                  MojoWriteMessageFlags flags) {
-  return MojoWriteMessage(message_pipe.value(), bytes, num_bytes, handles,
-                          num_handles, flags);
-}
-
-inline MojoResult ReadMessageRaw(MessagePipeHandle message_pipe,
-                                 void* bytes,
-                                 uint32_t* num_bytes,
-                                 MojoHandle* handles,
-                                 uint32_t* num_handles,
-                                 MojoReadMessageFlags flags) {
-  return MojoReadMessage(message_pipe.value(), bytes, num_bytes, handles,
-                         num_handles, flags);
-}
-
-// A wrapper class that automatically creates a message pipe and owns both
-// handles.
-class MessagePipe {
- public:
-  MessagePipe();
-  ~MessagePipe();
-
-  ScopedMessagePipeHandle handle0;
-  ScopedMessagePipeHandle handle1;
-};
-
-inline MessagePipe::MessagePipe() {
-  MojoResult result MOJO_ALLOW_UNUSED = CreateMessagePipe(&handle0, &handle1);
-  assert(result == MOJO_RESULT_OK);
-}
-
-inline MessagePipe::~MessagePipe() {
-}
-
-// DataPipeProducerHandle and DataPipeConsumerHandle ---------------------------
-
-class DataPipeProducerHandle : public Handle {
- public:
-  DataPipeProducerHandle() {}
-  explicit DataPipeProducerHandle(MojoHandle value) : Handle(value) {}
-
-  // Copying and assignment allowed.
-};
-
-MOJO_COMPILE_ASSERT(sizeof(DataPipeProducerHandle) == sizeof(Handle),
-                    bad_size_for_cpp_DataPipeProducerHandle);
-
-typedef ScopedHandleBase<DataPipeProducerHandle> ScopedDataPipeProducerHandle;
-MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeProducerHandle) ==
-                        sizeof(DataPipeProducerHandle),
-                    bad_size_for_cpp_ScopedDataPipeProducerHandle);
-
-class DataPipeConsumerHandle : public Handle {
- public:
-  DataPipeConsumerHandle() {}
-  explicit DataPipeConsumerHandle(MojoHandle value) : Handle(value) {}
-
-  // Copying and assignment allowed.
-};
-
-MOJO_COMPILE_ASSERT(sizeof(DataPipeConsumerHandle) == sizeof(Handle),
-                    bad_size_for_cpp_DataPipeConsumerHandle);
-
-typedef ScopedHandleBase<DataPipeConsumerHandle> ScopedDataPipeConsumerHandle;
-MOJO_COMPILE_ASSERT(sizeof(ScopedDataPipeConsumerHandle) ==
-                        sizeof(DataPipeConsumerHandle),
-                    bad_size_for_cpp_ScopedDataPipeConsumerHandle);
-
-inline MojoResult CreateDataPipe(
-    const MojoCreateDataPipeOptions* options,
-    ScopedDataPipeProducerHandle* data_pipe_producer,
-    ScopedDataPipeConsumerHandle* data_pipe_consumer) {
-  assert(data_pipe_producer);
-  assert(data_pipe_consumer);
-  DataPipeProducerHandle producer_handle;
-  DataPipeConsumerHandle consumer_handle;
-  MojoResult rv = MojoCreateDataPipe(options, producer_handle.mutable_value(),
-                                     consumer_handle.mutable_value());
-  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
-  // will be used).
-  data_pipe_producer->reset(producer_handle);
-  data_pipe_consumer->reset(consumer_handle);
-  return rv;
-}
-
-inline MojoResult WriteDataRaw(DataPipeProducerHandle data_pipe_producer,
-                               const void* elements,
-                               uint32_t* num_bytes,
-                               MojoWriteDataFlags flags) {
-  return MojoWriteData(data_pipe_producer.value(), elements, num_bytes, flags);
-}
-
-inline MojoResult BeginWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
-                                    void** buffer,
-                                    uint32_t* buffer_num_bytes,
-                                    MojoWriteDataFlags flags) {
-  return MojoBeginWriteData(data_pipe_producer.value(), buffer,
-                            buffer_num_bytes, flags);
-}
-
-inline MojoResult EndWriteDataRaw(DataPipeProducerHandle data_pipe_producer,
-                                  uint32_t num_bytes_written) {
-  return MojoEndWriteData(data_pipe_producer.value(), num_bytes_written);
-}
-
-inline MojoResult ReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
-                              void* elements,
-                              uint32_t* num_bytes,
-                              MojoReadDataFlags flags) {
-  return MojoReadData(data_pipe_consumer.value(), elements, num_bytes, flags);
-}
-
-inline MojoResult BeginReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
-                                   const void** buffer,
-                                   uint32_t* buffer_num_bytes,
-                                   MojoReadDataFlags flags) {
-  return MojoBeginReadData(data_pipe_consumer.value(), buffer, buffer_num_bytes,
-                           flags);
-}
-
-inline MojoResult EndReadDataRaw(DataPipeConsumerHandle data_pipe_consumer,
-                                 uint32_t num_bytes_read) {
-  return MojoEndReadData(data_pipe_consumer.value(), num_bytes_read);
-}
-
-// A wrapper class that automatically creates a data pipe and owns both handles.
-// TODO(vtl): Make an even more friendly version? (Maybe templatized for a
-// particular type instead of some "element"? Maybe functions that take
-// vectors?)
-class DataPipe {
- public:
-  DataPipe();
-  explicit DataPipe(const MojoCreateDataPipeOptions& options);
-  ~DataPipe();
-
-  ScopedDataPipeProducerHandle producer_handle;
-  ScopedDataPipeConsumerHandle consumer_handle;
-};
-
-inline DataPipe::DataPipe() {
-  MojoResult result MOJO_ALLOW_UNUSED =
-      CreateDataPipe(NULL, &producer_handle, &consumer_handle);
-  assert(result == MOJO_RESULT_OK);
-}
-
-inline DataPipe::DataPipe(const MojoCreateDataPipeOptions& options) {
-  MojoResult result MOJO_ALLOW_UNUSED =
-      CreateDataPipe(&options, &producer_handle, &consumer_handle);
-  assert(result == MOJO_RESULT_OK);
-}
-
-inline DataPipe::~DataPipe() {
-}
-
-// SharedBufferHandle ----------------------------------------------------------
-
-class SharedBufferHandle : public Handle {
- public:
-  SharedBufferHandle() {}
-  explicit SharedBufferHandle(MojoHandle value) : Handle(value) {}
-
-  // Copying and assignment allowed.
-};
-
-MOJO_COMPILE_ASSERT(sizeof(SharedBufferHandle) == sizeof(Handle),
-                    bad_size_for_cpp_SharedBufferHandle);
-
-typedef ScopedHandleBase<SharedBufferHandle> ScopedSharedBufferHandle;
-MOJO_COMPILE_ASSERT(sizeof(ScopedSharedBufferHandle) ==
-                        sizeof(SharedBufferHandle),
-                    bad_size_for_cpp_ScopedSharedBufferHandle);
-
-inline MojoResult CreateSharedBuffer(
-    const MojoCreateSharedBufferOptions* options,
-    uint64_t num_bytes,
-    ScopedSharedBufferHandle* shared_buffer) {
-  assert(shared_buffer);
-  SharedBufferHandle handle;
-  MojoResult rv = MojoCreateSharedBuffer(options, num_bytes,
-                                         handle.mutable_value());
-  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
-  // will be used).
-  shared_buffer->reset(handle);
-  return rv;
-}
-
-// TODO(vtl): This (and also the functions below) are templatized to allow for
-// future/other buffer types. A bit "safer" would be to overload this function
-// manually. (The template enforces that the in and out handles to be of the
-// same type.)
-template <class BufferHandleType>
-inline MojoResult DuplicatedBuffer(
-    BufferHandleType buffer,
-    const MojoDuplicateBufferHandleOptions* options,
-    ScopedHandleBase<BufferHandleType>* new_buffer) {
-  assert(new_buffer);
-  BufferHandleType handle;
-  MojoResult rv = MojoDuplicateSharedBuffer(buffer.value(), options,
-                                            handle.mutable_value());
-  // Reset even on failure (reduces the chances that a "stale"/incorrect handle
-  // will be used).
-  new_buffer->reset(handle);
-  return rv;
-}
-
-template <class BufferHandleType>
-inline MojoResult MapBuffer(BufferHandleType buffer,
-                            uint64_t offset,
-                            uint64_t num_bytes,
-                            void** pointer,
-                            MojoMapBufferFlags flags) {
-  assert(buffer);
-  return MojoMapBuffer(buffer.value(), offset, num_bytes, pointer, flags);
-}
-
-inline MojoResult UnmapBuffer(void* pointer) {
-  assert(pointer);
-  return MojoUnmapBuffer(pointer);
-}
-
-// A wrapper class that automatically creates a shared buffer and owns the
-// handle.
-class SharedBuffer {
- public:
-  explicit SharedBuffer(uint64_t num_bytes);
-  SharedBuffer(uint64_t num_bytes,
-               const MojoCreateSharedBufferOptions& options);
-  ~SharedBuffer();
-
-  ScopedSharedBufferHandle handle;
-};
-
-inline SharedBuffer::SharedBuffer(uint64_t num_bytes) {
-  MojoResult result MOJO_ALLOW_UNUSED =
-      CreateSharedBuffer(NULL, num_bytes, &handle);
-  assert(result == MOJO_RESULT_OK);
-}
-
-inline SharedBuffer::SharedBuffer(
-    uint64_t num_bytes,
-    const MojoCreateSharedBufferOptions& options) {
-  MojoResult result MOJO_ALLOW_UNUSED =
-      CreateSharedBuffer(&options, num_bytes, &handle);
-  assert(result == MOJO_RESULT_OK);
-}
-
-inline SharedBuffer::~SharedBuffer() {
-}
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_SYSTEM_CORE_CPP_H_
diff --git a/mojo/public/system/core_private.h b/mojo/public/system/core_private.h
index fa88a3b..057bfca 100644
--- a/mojo/public/system/core_private.h
+++ b/mojo/public/system/core_private.h
@@ -5,7 +5,7 @@
 #ifndef MOJO_PUBLIC_SYSTEM_CORE_PRIVATE_H_
 #define MOJO_PUBLIC_SYSTEM_CORE_PRIVATE_H_
 
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 
 namespace mojo {
 
diff --git a/mojo/public/system/macros.h b/mojo/public/system/macros.h
deleted file mode 100644
index b31469f..0000000
--- a/mojo/public/system/macros.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_SYSTEM_MACROS_H_
-#define MOJO_PUBLIC_SYSTEM_MACROS_H_
-
-#include <stddef.h>
-
-// Annotate a variable indicating it's okay if it's unused.
-// Use like:
-//   int x MOJO_ALLOW_UNUSED = ...;
-#if defined(__GNUC__)
-#define MOJO_ALLOW_UNUSED __attribute__((unused))
-#else
-#define MOJO_ALLOW_UNUSED
-#endif
-
-// Annotate a function indicating that the caller must examine the return value.
-// Use like:
-//   int foo() MOJO_WARN_UNUSED_RESULT;
-// Note that it can only be used on the prototype, and not the definition.
-#if defined(__GNUC__)
-#define MOJO_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-#else
-#define MOJO_WARN_UNUSED_RESULT
-#endif
-
-// C++-only macros -------------------------------------------------------------
-
-#ifdef __cplusplus
-
-// Annotate a virtual method indicating it must be overriding a virtual method
-// in the parent class. Use like:
-//   virtual void foo() OVERRIDE;
-#if defined(_MSC_VER) || defined(__clang__)
-#define MOJO_OVERRIDE override
-#else
-#define MOJO_OVERRIDE
-#endif
-
-// A macro to disallow the copy constructor and operator= functions.
-// This should be used in the private: declarations for a class.
-#define MOJO_DISALLOW_COPY_AND_ASSIGN(TypeName) \
-    TypeName(const TypeName&); \
-    void operator=(const TypeName&)
-
-// Used to assert things at compile time.
-namespace mojo { template <bool> struct CompileAssert {}; }
-#define MOJO_COMPILE_ASSERT(expr, msg) \
-    typedef ::mojo::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
-
-// Used to calculate the number of elements in an array.
-// (See |arraysize()| in Chromium's base/basictypes.h for more details.)
-namespace mojo {
-template <typename T, size_t N>
-char (&ArraySizeHelper(T (&array)[N]))[N];
-#if !defined(_MSC_VER)
-template <typename T, size_t N>
-char (&ArraySizeHelper(const T (&array)[N]))[N];
-#endif
-}  // namespace mojo
-#define MOJO_ARRAYSIZE(array) (sizeof(::mojo::ArraySizeHelper(array)))
-
-// Used to make a type move-only in C++03. See Chromium's base/move.h for more
-// details.
-#define MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(type, rvalue_type) \
- private: \
-  struct rvalue_type { \
-    explicit rvalue_type(type* object) : object(object) {} \
-    type* object; \
-  }; \
-  type(type&); \
-  void operator=(type&); \
- public: \
-  operator rvalue_type() { return rvalue_type(this); } \
-  type Pass() { return type(rvalue_type(this)); } \
-  typedef void MoveOnlyTypeForCPP03; \
- private:
-
-#endif  // __cplusplus
-
-#endif  // MOJO_PUBLIC_SYSTEM_MACROS_H_
diff --git a/mojo/public/system/system_export.h b/mojo/public/system/system_export.h
deleted file mode 100644
index 6b563ff..0000000
--- a/mojo/public/system/system_export.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_SYSTEM_SYSTEM_EXPORT_H_
-#define MOJO_PUBLIC_SYSTEM_SYSTEM_EXPORT_H_
-
-#if defined(WIN32)
-
-#if defined(MOJO_SYSTEM_IMPLEMENTATION)
-#define MOJO_SYSTEM_EXPORT __declspec(dllexport)
-#else
-#define MOJO_SYSTEM_EXPORT __declspec(dllimport)
-#endif
-
-#else  // !defined(WIN32)
-
-#if defined(MOJO_SYSTEM_IMPLEMENTATION)
-#define MOJO_SYSTEM_EXPORT __attribute__((visibility("default")))
-#else
-#define MOJO_SYSTEM_EXPORT
-#endif
-
-#endif  // defined(WIN32)
-
-#endif  // MOJO_PUBLIC_SYSTEM_SYSTEM_EXPORT_H_
diff --git a/mojo/public/tests/system/core_cpp_unittest.cc b/mojo/public/tests/system/core_cpp_unittest.cc
deleted file mode 100644
index d222164..0000000
--- a/mojo/public/tests/system/core_cpp_unittest.cc
+++ /dev/null
@@ -1,379 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/system/core_cpp.h"
-
-#include <map>
-
-#include "mojo/public/system/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-TEST(CoreCppTest, GetTimeTicksNow) {
-  const MojoTimeTicks start = GetTimeTicksNow();
-  EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
-      << "GetTimeTicksNow should return nonzero value";
-}
-
-TEST(CoreCppTest, Basic) {
-  // Basic |Handle| implementation:
-  {
-    EXPECT_EQ(MOJO_HANDLE_INVALID, kInvalidHandleValue);
-
-    Handle h0;
-    EXPECT_EQ(kInvalidHandleValue, h0.value());
-    EXPECT_EQ(kInvalidHandleValue, *h0.mutable_value());
-    EXPECT_FALSE(h0.is_valid());
-
-    Handle h1(static_cast<MojoHandle>(123));
-    EXPECT_EQ(static_cast<MojoHandle>(123), h1.value());
-    EXPECT_EQ(static_cast<MojoHandle>(123), *h1.mutable_value());
-    EXPECT_TRUE(h1.is_valid());
-    *h1.mutable_value() = static_cast<MojoHandle>(456);
-    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
-    EXPECT_TRUE(h1.is_valid());
-
-    h1.swap(h0);
-    EXPECT_EQ(static_cast<MojoHandle>(456), h0.value());
-    EXPECT_TRUE(h0.is_valid());
-    EXPECT_FALSE(h1.is_valid());
-
-    h1.set_value(static_cast<MojoHandle>(789));
-    h0.swap(h1);
-    EXPECT_EQ(static_cast<MojoHandle>(789), h0.value());
-    EXPECT_TRUE(h0.is_valid());
-    EXPECT_EQ(static_cast<MojoHandle>(456), h1.value());
-    EXPECT_TRUE(h1.is_valid());
-
-    // Make sure copy constructor works.
-    Handle h2(h0);
-    EXPECT_EQ(static_cast<MojoHandle>(789), h2.value());
-    // And assignment.
-    h2 = h1;
-    EXPECT_EQ(static_cast<MojoHandle>(456), h2.value());
-
-    // Make sure that we can put |Handle|s into |std::map|s.
-    h0 = Handle(static_cast<MojoHandle>(987));
-    h1 = Handle(static_cast<MojoHandle>(654));
-    h2 = Handle(static_cast<MojoHandle>(321));
-    Handle h3;
-    std::map<Handle, int> handle_to_int;
-    handle_to_int[h0] = 0;
-    handle_to_int[h1] = 1;
-    handle_to_int[h2] = 2;
-    handle_to_int[h3] = 3;
-
-    EXPECT_EQ(4u, handle_to_int.size());
-    EXPECT_FALSE(handle_to_int.find(h0) == handle_to_int.end());
-    EXPECT_EQ(0, handle_to_int[h0]);
-    EXPECT_FALSE(handle_to_int.find(h1) == handle_to_int.end());
-    EXPECT_EQ(1, handle_to_int[h1]);
-    EXPECT_FALSE(handle_to_int.find(h2) == handle_to_int.end());
-    EXPECT_EQ(2, handle_to_int[h2]);
-    EXPECT_FALSE(handle_to_int.find(h3) == handle_to_int.end());
-    EXPECT_EQ(3, handle_to_int[h3]);
-    EXPECT_TRUE(handle_to_int.find(Handle(static_cast<MojoHandle>(13579))) ==
-                    handle_to_int.end());
-
-    // TODO(vtl): With C++11, support |std::unordered_map|s, etc. (Or figure out
-    // how to support the variations of |hash_map|.)
-  }
-
-  // |Handle|/|ScopedHandle| functions:
-  {
-    ScopedHandle h;
-
-    EXPECT_EQ(kInvalidHandleValue, h.get().value());
-
-    // This should be a no-op.
-    Close(h.Pass());
-
-    // It should still be invalid.
-    EXPECT_EQ(kInvalidHandleValue, h.get().value());
-
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              Wait(h.get(), MOJO_WAIT_FLAG_EVERYTHING, 1000000));
-
-    std::vector<Handle> wh;
-    wh.push_back(h.get());
-    std::vector<MojoWaitFlags> wf;
-    wf.push_back(MOJO_WAIT_FLAG_EVERYTHING);
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              WaitMany(wh, wf, MOJO_DEADLINE_INDEFINITE));
-  }
-
-  // |MessagePipeHandle|/|ScopedMessagePipeHandle| functions:
-  {
-    MessagePipeHandle h_invalid;
-    EXPECT_FALSE(h_invalid.is_valid());
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              WriteMessageRaw(h_invalid,
-                              NULL, 0,
-                              NULL, 0,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-    char buffer[10] = { 0 };
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              WriteMessageRaw(h_invalid,
-                              buffer, sizeof(buffer),
-                              NULL, 0,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              ReadMessageRaw(h_invalid,
-                             NULL, NULL,
-                             NULL, NULL,
-                             MOJO_READ_MESSAGE_FLAG_NONE));
-    uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-              ReadMessageRaw(h_invalid,
-                             buffer, &buffer_size,
-                             NULL, NULL,
-                             MOJO_READ_MESSAGE_FLAG_NONE));
-
-    // Basic tests of waiting and closing.
-    MojoHandle hv0 = kInvalidHandleValue;
-    {
-      ScopedMessagePipeHandle h0;
-      ScopedMessagePipeHandle h1;
-      EXPECT_FALSE(h0.get().is_valid());
-      EXPECT_FALSE(h1.get().is_valid());
-
-      CreateMessagePipe(&h0, &h1);
-      EXPECT_TRUE(h0.get().is_valid());
-      EXPECT_TRUE(h1.get().is_valid());
-      EXPECT_NE(h0.get().value(), h1.get().value());
-      // Save the handle values, so we can check that things got closed
-      // correctly.
-      hv0 = h0.get().value();
-      MojoHandle hv1 = h1.get().value();
-
-      EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-                Wait(h0.get(), MOJO_WAIT_FLAG_READABLE, 0));
-      std::vector<Handle> wh;
-      wh.push_back(h0.get());
-      wh.push_back(h1.get());
-      std::vector<MojoWaitFlags> wf;
-      wf.push_back(MOJO_WAIT_FLAG_READABLE);
-      wf.push_back(MOJO_WAIT_FLAG_WRITABLE);
-      EXPECT_EQ(1, WaitMany(wh, wf, 1000));
-
-      // Test closing |h1| explicitly.
-      Close(h1.Pass());
-      EXPECT_FALSE(h1.get().is_valid());
-
-      // Make sure |h1| is closed.
-      EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-                MojoWait(hv1, MOJO_WAIT_FLAG_EVERYTHING,
-                         MOJO_DEADLINE_INDEFINITE));
-
-      EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-                Wait(h0.get(), MOJO_WAIT_FLAG_READABLE,
-                     MOJO_DEADLINE_INDEFINITE));
-    }
-    // |hv0| should have been closed when |h0| went out of scope, so this close
-    // should fail.
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0));
-
-    // Actually test writing/reading messages.
-    {
-      ScopedMessagePipeHandle h0;
-      ScopedMessagePipeHandle h1;
-      CreateMessagePipe(&h0, &h1);
-
-      const char kHello[] = "hello";
-      const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
-      EXPECT_EQ(MOJO_RESULT_OK,
-                WriteMessageRaw(h0.get(),
-                                kHello, kHelloSize,
-                                NULL, 0,
-                                MOJO_WRITE_MESSAGE_FLAG_NONE));
-      EXPECT_EQ(MOJO_RESULT_OK,
-                Wait(h1.get(), MOJO_WAIT_FLAG_READABLE,
-                     MOJO_DEADLINE_INDEFINITE));
-      char buffer[10] = { 0 };
-      uint32_t buffer_size = static_cast<uint32_t>(sizeof(buffer));
-      EXPECT_EQ(MOJO_RESULT_OK,
-                ReadMessageRaw(h1.get(),
-                               buffer, &buffer_size,
-                               NULL, NULL,
-                               MOJO_READ_MESSAGE_FLAG_NONE));
-      EXPECT_EQ(kHelloSize, buffer_size);
-      EXPECT_STREQ(kHello, buffer);
-
-      // Send a handle over the previously-establish message pipe. Use the
-      // |MessagePipe| wrapper (to test it), which automatically creates a
-      // message pipe.
-      MessagePipe mp;
-
-      // Write a message to |mp.handle0|, before we send |mp.handle1|.
-      const char kWorld[] = "world!";
-      const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
-      EXPECT_EQ(MOJO_RESULT_OK,
-                WriteMessageRaw(mp.handle0.get(),
-                                kWorld, kWorldSize,
-                                NULL, 0,
-                                MOJO_WRITE_MESSAGE_FLAG_NONE));
-
-      // Send |mp.handle1| over |h1| to |h0|.
-      MojoHandle handles[5];
-      handles[0] = mp.handle1.release().value();
-      EXPECT_NE(kInvalidHandleValue, handles[0]);
-      EXPECT_FALSE(mp.handle1.get().is_valid());
-      uint32_t handles_count = 1;
-      EXPECT_EQ(MOJO_RESULT_OK,
-                WriteMessageRaw(h1.get(),
-                                kHello, kHelloSize,
-                                handles, handles_count,
-                                MOJO_WRITE_MESSAGE_FLAG_NONE));
-      // |handles[0]| should actually be invalid now.
-      EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(handles[0]));
-
-      // Read "hello" and the sent handle.
-      EXPECT_EQ(MOJO_RESULT_OK,
-                Wait(h0.get(), MOJO_WAIT_FLAG_READABLE,
-                     MOJO_DEADLINE_INDEFINITE));
-      memset(buffer, 0, sizeof(buffer));
-      buffer_size = static_cast<uint32_t>(sizeof(buffer));
-      for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++)
-        handles[i] = kInvalidHandleValue;
-      handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles));
-      EXPECT_EQ(MOJO_RESULT_OK,
-                ReadMessageRaw(h0.get(),
-                               buffer, &buffer_size,
-                               handles, &handles_count,
-                               MOJO_READ_MESSAGE_FLAG_NONE));
-      EXPECT_EQ(kHelloSize, buffer_size);
-      EXPECT_STREQ(kHello, buffer);
-      EXPECT_EQ(1u, handles_count);
-      EXPECT_NE(kInvalidHandleValue, handles[0]);
-
-      // Read from the sent/received handle.
-      mp.handle1.reset(MessagePipeHandle(handles[0]));
-      // Save |handles[0]| to check that it gets properly closed.
-      hv0 = handles[0];
-      EXPECT_EQ(MOJO_RESULT_OK,
-                Wait(mp.handle1.get(), MOJO_WAIT_FLAG_READABLE,
-                     MOJO_DEADLINE_INDEFINITE));
-      memset(buffer, 0, sizeof(buffer));
-      buffer_size = static_cast<uint32_t>(sizeof(buffer));
-      for (size_t i = 0; i < MOJO_ARRAYSIZE(handles); i++)
-        handles[i] = kInvalidHandleValue;
-      handles_count = static_cast<uint32_t>(MOJO_ARRAYSIZE(handles));
-      EXPECT_EQ(MOJO_RESULT_OK,
-                ReadMessageRaw(mp.handle1.get(),
-                               buffer, &buffer_size,
-                               handles, &handles_count,
-                               MOJO_READ_MESSAGE_FLAG_NONE));
-      EXPECT_EQ(kWorldSize, buffer_size);
-      EXPECT_STREQ(kWorld, buffer);
-      EXPECT_EQ(0u, handles_count);
-    }
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(hv0));
-  }
-
-  // TODO(vtl): Test |CloseRaw()|.
-  // TODO(vtl): Test |reset()| more thoroughly?
-}
-
-TEST(CoreCppTest, TearDownWithMessagesEnqueued) {
-  // Tear down a message pipe which still has a message enqueued, with the
-  // message also having a valid message pipe handle.
-  {
-    ScopedMessagePipeHandle h0;
-    ScopedMessagePipeHandle h1;
-    CreateMessagePipe(&h0, &h1);
-
-    // Send a handle over the previously-establish message pipe.
-    ScopedMessagePipeHandle h2;
-    ScopedMessagePipeHandle h3;
-    CreateMessagePipe(&h2, &h3);
-
-    // Write a message to |h2|, before we send |h3|.
-    const char kWorld[] = "world!";
-    const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
-    EXPECT_EQ(MOJO_RESULT_OK,
-              WriteMessageRaw(h2.get(),
-                              kWorld, kWorldSize,
-                              NULL, 0,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-    // And also a message to |h3|.
-    EXPECT_EQ(MOJO_RESULT_OK,
-              WriteMessageRaw(h3.get(),
-                              kWorld, kWorldSize,
-                              NULL, 0,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-
-    // Send |h3| over |h1| to |h0|.
-    const char kHello[] = "hello";
-    const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
-    MojoHandle h3_value;
-    h3_value = h3.release().value();
-    EXPECT_NE(kInvalidHandleValue, h3_value);
-    EXPECT_FALSE(h3.get().is_valid());
-    EXPECT_EQ(MOJO_RESULT_OK,
-              WriteMessageRaw(h1.get(),
-                              kHello, kHelloSize,
-                              &h3_value, 1,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-    // |h3_value| should actually be invalid now.
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value));
-
-    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value()));
-    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value()));
-    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value()));
-  }
-
-  // Do this in a different order: make the enqueued message pipe handle only
-  // half-alive.
-  {
-    ScopedMessagePipeHandle h0;
-    ScopedMessagePipeHandle h1;
-    CreateMessagePipe(&h0, &h1);
-
-    // Send a handle over the previously-establish message pipe.
-    ScopedMessagePipeHandle h2;
-    ScopedMessagePipeHandle h3;
-    CreateMessagePipe(&h2, &h3);
-
-    // Write a message to |h2|, before we send |h3|.
-    const char kWorld[] = "world!";
-    const uint32_t kWorldSize = static_cast<uint32_t>(sizeof(kWorld));
-    EXPECT_EQ(MOJO_RESULT_OK,
-              WriteMessageRaw(h2.get(),
-                              kWorld, kWorldSize,
-                              NULL, 0,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-    // And also a message to |h3|.
-    EXPECT_EQ(MOJO_RESULT_OK,
-              WriteMessageRaw(h3.get(),
-                              kWorld, kWorldSize,
-                              NULL, 0,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-
-    // Send |h3| over |h1| to |h0|.
-    const char kHello[] = "hello";
-    const uint32_t kHelloSize = static_cast<uint32_t>(sizeof(kHello));
-    MojoHandle h3_value;
-    h3_value = h3.release().value();
-    EXPECT_NE(kInvalidHandleValue, h3_value);
-    EXPECT_FALSE(h3.get().is_valid());
-    EXPECT_EQ(MOJO_RESULT_OK,
-              WriteMessageRaw(h1.get(),
-                              kHello, kHelloSize,
-                              &h3_value, 1,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE));
-    // |h3_value| should actually be invalid now.
-    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(h3_value));
-
-    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h2.release().value()));
-    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0.release().value()));
-    EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1.release().value()));
-  }
-}
-
-// TODO(vtl): Write data pipe tests.
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/tests/system/core_perftest.cc b/mojo/public/tests/system/core_perftest.cc
deleted file mode 100644
index 6874375..0000000
--- a/mojo/public/tests/system/core_perftest.cc
+++ /dev/null
@@ -1,337 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This tests the performance of the C API.
-
-#include "mojo/public/system/core.h"
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include "mojo/public/system/macros.h"
-#include "mojo/public/tests/test_support.h"
-#include "mojo/public/tests/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// TODO(vtl): (here and below) crbug.com/342893
-#if !defined(WIN32)
-#include <time.h>
-#include "mojo/public/utility/thread.h"
-#endif  // !defined(WIN32)
-
-namespace {
-
-#if !defined(WIN32)
-class MessagePipeWriterThread : public mojo::Thread {
- public:
-  MessagePipeWriterThread(MojoHandle handle, uint32_t num_bytes)
-      : handle_(handle),
-        num_bytes_(num_bytes),
-        num_writes_(0) {}
-  virtual ~MessagePipeWriterThread() {}
-
-  virtual void Run() MOJO_OVERRIDE {
-    char buffer[10000];
-    assert(num_bytes_ <= sizeof(buffer));
-
-    // TODO(vtl): Should I throttle somehow?
-    for (;;) {
-      MojoResult result = MojoWriteMessage(handle_, buffer, num_bytes_, NULL, 0,
-                                           MOJO_WRITE_MESSAGE_FLAG_NONE);
-      if (result == MOJO_RESULT_OK) {
-        num_writes_++;
-        continue;
-      }
-
-      // We failed to write.
-      // Either |handle_| or its peer was closed.
-      assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
-             result == MOJO_RESULT_FAILED_PRECONDITION);
-      break;
-    }
-  }
-
-  // Use only after joining the thread.
-  int64_t num_writes() const { return num_writes_; }
-
- private:
-  const MojoHandle handle_;
-  const uint32_t num_bytes_;
-  int64_t num_writes_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeWriterThread);
-};
-
-class MessagePipeReaderThread : public mojo::Thread {
- public:
-  explicit MessagePipeReaderThread(MojoHandle handle)
-      : handle_(handle),
-        num_reads_(0) {
-  }
-  virtual ~MessagePipeReaderThread() {}
-
-  virtual void Run() MOJO_OVERRIDE {
-    char buffer[10000];
-
-    for (;;) {
-      uint32_t num_bytes = static_cast<uint32_t>(sizeof(buffer));
-      MojoResult result = MojoReadMessage(handle_, buffer, &num_bytes, NULL,
-                                          NULL, MOJO_READ_MESSAGE_FLAG_NONE);
-      if (result == MOJO_RESULT_OK) {
-        num_reads_++;
-        continue;
-      }
-
-      if (result == MOJO_RESULT_SHOULD_WAIT) {
-        result = MojoWait(handle_, MOJO_WAIT_FLAG_READABLE,
-                          MOJO_DEADLINE_INDEFINITE);
-        if (result == MOJO_RESULT_OK) {
-          // Go to the top of the loop to read again.
-          continue;
-        }
-      }
-
-      // We failed to read and possibly failed to wait.
-      // Either |handle_| or its peer was closed.
-      assert(result == MOJO_RESULT_INVALID_ARGUMENT ||
-             result == MOJO_RESULT_FAILED_PRECONDITION);
-      break;
-    }
-  }
-
-  // Use only after joining the thread.
-  int64_t num_reads() const { return num_reads_; }
-
- private:
-  const MojoHandle handle_;
-  int64_t num_reads_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeReaderThread);
-};
-#endif  // !defined(WIN32)
-
-class CorePerftest : public testing::Test {
- public:
-  CorePerftest() : buffer_(NULL), num_bytes_(0) {}
-  virtual ~CorePerftest() {}
-
-  static void NoOp(void* /*closure*/) {
-  }
-
-  static void MessagePipe_CreateAndClose(void* closure) {
-    CorePerftest* self = static_cast<CorePerftest*>(closure);
-    MojoResult result MOJO_ALLOW_UNUSED;
-    result = MojoCreateMessagePipe(&self->h0_, &self->h1_);
-    assert(result == MOJO_RESULT_OK);
-    result = MojoClose(self->h0_);
-    assert(result == MOJO_RESULT_OK);
-    result = MojoClose(self->h1_);
-    assert(result == MOJO_RESULT_OK);
-  }
-
-  static void MessagePipe_WriteAndRead(void* closure) {
-    CorePerftest* self = static_cast<CorePerftest*>(closure);
-    MojoResult result MOJO_ALLOW_UNUSED;
-    result = MojoWriteMessage(self->h0_,
-                              self->buffer_, self->num_bytes_,
-                              NULL, 0,
-                              MOJO_WRITE_MESSAGE_FLAG_NONE);
-    assert(result == MOJO_RESULT_OK);
-    uint32_t read_bytes = self->num_bytes_;
-    result = MojoReadMessage(self->h1_,
-                             self->buffer_, &read_bytes,
-                             NULL, NULL,
-                             MOJO_READ_MESSAGE_FLAG_NONE);
-    assert(result == MOJO_RESULT_OK);
-  }
-
-  static void MessagePipe_EmptyRead(void* closure) {
-    CorePerftest* self = static_cast<CorePerftest*>(closure);
-    MojoResult result MOJO_ALLOW_UNUSED;
-    result = MojoReadMessage(self->h0_,
-                             NULL, NULL,
-                             NULL, NULL,
-                             MOJO_READ_MESSAGE_FLAG_MAY_DISCARD);
-    assert(result == MOJO_RESULT_SHOULD_WAIT);
-  }
-
- protected:
-#if !defined(WIN32)
-  void DoMessagePipeThreadedTest(unsigned num_writers,
-                                 unsigned num_readers,
-                                 uint32_t num_bytes) {
-    static const int64_t kPerftestTimeMicroseconds = 3 * 1000000;
-
-    assert(num_writers > 0);
-    assert(num_readers > 0);
-
-    MojoResult result MOJO_ALLOW_UNUSED;
-    result = MojoCreateMessagePipe(&h0_, &h1_);
-    assert(result == MOJO_RESULT_OK);
-
-    std::vector<MessagePipeWriterThread*> writers;
-    for (unsigned i = 0; i < num_writers; i++)
-      writers.push_back(new MessagePipeWriterThread(h0_, num_bytes));
-
-    std::vector<MessagePipeReaderThread*> readers;
-    for (unsigned i = 0; i < num_readers; i++)
-      readers.push_back(new MessagePipeReaderThread(h1_));
-
-    // Start time here, just before we fire off the threads.
-    const MojoTimeTicks start_time = MojoGetTimeTicksNow();
-
-    // Interleave the starts.
-    for (unsigned i = 0; i < num_writers || i < num_readers; i++) {
-      if (i < num_writers)
-        writers[i]->Start();
-      if (i < num_readers)
-        readers[i]->Start();
-    }
-
-    Sleep(kPerftestTimeMicroseconds);
-
-    // Close both handles to make writers and readers stop immediately.
-    result = MojoClose(h0_);
-    assert(result == MOJO_RESULT_OK);
-    result = MojoClose(h1_);
-    assert(result == MOJO_RESULT_OK);
-
-    // Join everything.
-    for (unsigned i = 0; i < num_writers; i++)
-      writers[i]->Join();
-    for (unsigned i = 0; i < num_readers; i++)
-      readers[i]->Join();
-
-    // Stop time here.
-    MojoTimeTicks end_time = MojoGetTimeTicksNow();
-
-    // Add up write and read counts, and destroy the threads.
-    int64_t num_writes = 0;
-    for (unsigned i = 0; i < num_writers; i++) {
-      num_writes += writers[i]->num_writes();
-      delete writers[i];
-    }
-    writers.clear();
-    int64_t num_reads = 0;
-    for (unsigned i = 0; i < num_readers; i++) {
-      num_reads += readers[i]->num_reads();
-      delete readers[i];
-    }
-    readers.clear();
-
-    char test_name[200];
-    sprintf(test_name, "MessagePipe_Threaded_Writes_%uw_%ur_%ubytes",
-            num_writers, num_readers, static_cast<unsigned>(num_bytes));
-    mojo::test::LogPerfResult(test_name,
-                              1000000.0 * static_cast<double>(num_writes) /
-                                  (end_time - start_time),
-                              "writes/second");
-    sprintf(test_name, "MessagePipe_Threaded_Reads_%uw_%ur_%ubytes",
-            num_writers, num_readers, static_cast<unsigned>(num_bytes));
-    mojo::test::LogPerfResult(test_name,
-                              1000000.0 * static_cast<double>(num_reads) /
-                                  (end_time - start_time),
-                                  "reads/second");
-  }
-#endif  // !defined(WIN32)
-
-  MojoHandle h0_;
-  MojoHandle h1_;
-
-  void* buffer_;
-  uint32_t num_bytes_;
-
- private:
-#if !defined(WIN32)
-  void Sleep(int64_t microseconds) {
-    struct timespec req = {
-      static_cast<time_t>(microseconds / 1000000),  // Seconds.
-      static_cast<long>(microseconds % 1000000) * 1000L  // Nanoseconds.
-    };
-    int rv MOJO_ALLOW_UNUSED;
-    rv = nanosleep(&req, NULL);
-    assert(rv == 0);
-  }
-#endif  // !defined(WIN32)
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(CorePerftest);
-};
-
-// A no-op test so we can compare performance.
-TEST_F(CorePerftest, NoOp) {
-  mojo::test::IterateAndReportPerf("NoOp", &CorePerftest::NoOp, this);
-}
-
-TEST_F(CorePerftest, MessagePipe_CreateAndClose) {
-  mojo::test::IterateAndReportPerf("MessagePipe_CreateAndClose",
-                                   &CorePerftest::MessagePipe_CreateAndClose,
-                                   this);
-}
-
-TEST_F(CorePerftest, MessagePipe_WriteAndRead) {
-  MojoResult result MOJO_ALLOW_UNUSED;
-  result = MojoCreateMessagePipe(&h0_, &h1_);
-  assert(result == MOJO_RESULT_OK);
-  char buffer[10000] = { 0 };
-  buffer_ = buffer;
-  num_bytes_ = 10u;
-  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10bytes",
-                                   &CorePerftest::MessagePipe_WriteAndRead,
-                                   this);
-  num_bytes_ = 100u;
-  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_100bytes",
-                                   &CorePerftest::MessagePipe_WriteAndRead,
-                                   this);
-  num_bytes_ = 1000u;
-  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_1000bytes",
-                                   &CorePerftest::MessagePipe_WriteAndRead,
-                                   this);
-  num_bytes_ = 10000u;
-  mojo::test::IterateAndReportPerf("MessagePipe_WriteAndRead_10000bytes",
-                                   &CorePerftest::MessagePipe_WriteAndRead,
-                                   this);
-  result = MojoClose(h0_);
-  assert(result == MOJO_RESULT_OK);
-  result = MojoClose(h1_);
-  assert(result == MOJO_RESULT_OK);
-}
-
-TEST_F(CorePerftest, MessagePipe_EmptyRead) {
-  MojoResult result MOJO_ALLOW_UNUSED;
-  result = MojoCreateMessagePipe(&h0_, &h1_);
-  assert(result == MOJO_RESULT_OK);
-  mojo::test::IterateAndReportPerf("MessagePipe_EmptyRead",
-                                   &CorePerftest::MessagePipe_EmptyRead,
-                                   this);
-  result = MojoClose(h0_);
-  assert(result == MOJO_RESULT_OK);
-  result = MojoClose(h1_);
-  assert(result == MOJO_RESULT_OK);
-}
-
-#if !defined(WIN32)
-TEST_F(CorePerftest, MessagePipe_Threaded) {
-  DoMessagePipeThreadedTest(1u, 1u, 100u);
-  DoMessagePipeThreadedTest(2u, 2u, 100u);
-  DoMessagePipeThreadedTest(3u, 3u, 100u);
-  DoMessagePipeThreadedTest(10u, 10u, 100u);
-  DoMessagePipeThreadedTest(10u, 1u, 100u);
-  DoMessagePipeThreadedTest(1u, 10u, 100u);
-
-  // For comparison of overhead:
-  DoMessagePipeThreadedTest(1u, 1u, 10u);
-  // 100 was done above.
-  DoMessagePipeThreadedTest(1u, 1u, 1000u);
-  DoMessagePipeThreadedTest(1u, 1u, 10000u);
-
-  DoMessagePipeThreadedTest(3u, 3u, 10u);
-  // 100 was done above.
-  DoMessagePipeThreadedTest(3u, 3u, 1000u);
-  DoMessagePipeThreadedTest(3u, 3u, 10000u);
-}
-#endif  // !defined(WIN32)
-
-}  // namespace
diff --git a/mojo/public/tests/system/core_unittest.cc b/mojo/public/tests/system/core_unittest.cc
deleted file mode 100644
index 2c31bef..0000000
--- a/mojo/public/tests/system/core_unittest.cc
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file tests the C API.
-
-#include "mojo/public/system/core.h"
-
-#include <string.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-TEST(CoreTest, GetTimeTicksNow) {
-  const MojoTimeTicks start = MojoGetTimeTicksNow();
-  EXPECT_NE(static_cast<MojoTimeTicks>(0), start)
-      << "MojoGetTimeTicksNow should return nonzero value";
-}
-
-TEST(CoreTest, Basic) {
-  MojoHandle h0;
-  MojoWaitFlags wf;
-  char buffer[10] = { 0 };
-  uint32_t buffer_size;
-
-  // The only handle that's guaranteed to be invalid is |MOJO_HANDLE_INVALID|.
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT, MojoClose(MOJO_HANDLE_INVALID));
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            MojoWait(MOJO_HANDLE_INVALID, MOJO_WAIT_FLAG_EVERYTHING, 1000000));
-  h0 = MOJO_HANDLE_INVALID;
-  wf = MOJO_WAIT_FLAG_EVERYTHING;
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            MojoWaitMany(&h0, &wf, 1, MOJO_DEADLINE_INDEFINITE));
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            MojoWriteMessage(h0,
-                             buffer, 3,
-                             NULL, 0,
-                             MOJO_WRITE_MESSAGE_FLAG_NONE));
-  buffer_size = static_cast<uint32_t>(sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            MojoReadMessage(h0,
-                            buffer, &buffer_size,
-                            NULL, NULL,
-                            MOJO_READ_MESSAGE_FLAG_NONE));
-
-  MojoHandle h1;
-  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(&h0, &h1));
-
-  // Shouldn't be readable.
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            MojoWait(h0, MOJO_WAIT_FLAG_READABLE, 0));
-
-  // Should be writable.
-  EXPECT_EQ(MOJO_RESULT_OK,
-            MojoWait(h0, MOJO_WAIT_FLAG_WRITABLE, 0));
-
-  // Try to read.
-  EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT,
-            MojoReadMessage(h0,
-                            buffer, &buffer_size,
-                            NULL, NULL,
-                            MOJO_READ_MESSAGE_FLAG_NONE));
-
-  // Write to |h1|.
-  static const char hello[] = "hello";
-  memcpy(buffer, hello, sizeof(hello));
-  buffer_size = static_cast<uint32_t>(sizeof(hello));
-  EXPECT_EQ(MOJO_RESULT_OK,
-            MojoWriteMessage(h1,
-                             hello, buffer_size,
-                             NULL, 0,
-                             MOJO_WRITE_MESSAGE_FLAG_NONE));
-
-  // |h0| should be readable.
-  wf = MOJO_WAIT_FLAG_READABLE;
-  EXPECT_EQ(MOJO_RESULT_OK,
-            MojoWaitMany(&h0, &wf, 1, MOJO_DEADLINE_INDEFINITE));
-
-  // Read from |h0|.
-  memset(buffer, 0, sizeof(buffer));
-  buffer_size = static_cast<uint32_t>(sizeof(buffer));
-  EXPECT_EQ(MOJO_RESULT_OK,
-            MojoReadMessage(h0,
-                            buffer, &buffer_size,
-                            NULL, NULL,
-                            MOJO_READ_MESSAGE_FLAG_NONE));
-  EXPECT_EQ(static_cast<uint32_t>(sizeof(hello)), buffer_size);
-  EXPECT_EQ(0, memcmp(hello, buffer, sizeof(hello)));
-
-  // |h0| should no longer be readable.
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            MojoWait(h0, MOJO_WAIT_FLAG_READABLE, 10));
-
-  // Close |h0|.
-  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h0));
-
-  // |h1| should no longer be readable or writable.
-  EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
-            MojoWait(h1, MOJO_WAIT_FLAG_READABLE | MOJO_WAIT_FLAG_WRITABLE,
-                     1000));
-
-  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(h1));
-}
-
-// Defined in core_unittest_pure_c.c.
-extern "C" const char* MinimalCTest(void);
-
-// This checks that things actually work in C (not C++).
-TEST(CoreTest, MinimalCTest) {
-  const char* failure = MinimalCTest();
-  EXPECT_TRUE(failure == NULL) << failure;
-}
-
-// TODO(vtl): Add multi-threaded tests.
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/tests/system/core_unittest_pure_c.c b/mojo/public/tests/system/core_unittest_pure_c.c
deleted file mode 100644
index 69ab94a..0000000
--- a/mojo/public/tests/system/core_unittest_pure_c.c
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifdef __cplusplus
-#error "This file should be compiled as C, not C++."
-#endif
-
-#include <stddef.h>
-#include <string.h>
-
-// Include all the header files that are meant to be compilable as C. Start with
-// core.h, since it's the most important one.
-#include "mojo/public/system/core.h"
-#include "mojo/public/system/async_waiter.h"
-#include "mojo/public/system/macros.h"
-
-// The joys of the C preprocessor....
-#define STRINGIFY(x) #x
-#define STRINGIFY2(x) STRINGIFY(x)
-#define FAILURE(message) \
-  __FILE__ "(" STRINGIFY2(__LINE__) "): Failure: " message
-
-// Poor man's gtest.
-#define EXPECT_EQ(a, b) \
-  do { \
-    if ((a) != (b)) \
-      return FAILURE(STRINGIFY(a) " != " STRINGIFY(b) " (expected ==)"); \
-  } while (0)
-#define EXPECT_NE(a, b) \
-  do { \
-    if ((a) == (b)) \
-      return FAILURE(STRINGIFY(a) " == " STRINGIFY(b) " (expected !=)"); \
-  } while (0)
-
-// This function exists mainly to be compiled and linked. We do some cursory
-// checks and call it from a unit test, to make sure that link problems aren't
-// missed due to deadstripping. Returns null on success and a string on failure
-// (describing the failure).
-const char* MinimalCTest(void) {
-  // MSVS before 2013 *really* only supports C90: All variables must be declared
-  // at the top. (MSVS 2013 is more reasonable.)
-  MojoTimeTicks ticks;
-  MojoHandle handle0, handle1;
-  MojoWaitFlags wait_flags;
-  const char kHello[] = "hello";
-  char buffer[200] = { 0 };
-  uint32_t num_bytes;
-
-  ticks = MojoGetTimeTicksNow();
-  EXPECT_NE(ticks, 0);
-
-  handle0 = MOJO_HANDLE_INVALID;
-  EXPECT_NE(MOJO_RESULT_OK, MojoClose(handle0));
-
-  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-            MojoWait(handle0, MOJO_WAIT_FLAG_EVERYTHING,
-                     MOJO_DEADLINE_INDEFINITE));
-
-  handle1 = MOJO_HANDLE_INVALID;
-  EXPECT_EQ(MOJO_RESULT_OK, MojoCreateMessagePipe(&handle0, &handle1));
-
-  wait_flags = MOJO_WAIT_FLAG_READABLE;
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED,
-            MojoWaitMany(&handle0, &wait_flags, 1, 1));
-
-  EXPECT_EQ(MOJO_RESULT_OK,
-            MojoWriteMessage(handle0, kHello, (uint32_t) sizeof(kHello), NULL,
-                             0u, MOJO_WRITE_DATA_FLAG_NONE));
-
-  EXPECT_EQ(MOJO_RESULT_OK,
-            MojoWait(handle1, MOJO_WAIT_FLAG_READABLE,
-                     MOJO_DEADLINE_INDEFINITE));
-
-  num_bytes = (uint32_t) sizeof(buffer);
-  EXPECT_EQ(MOJO_RESULT_OK,
-            MojoReadMessage(handle1, buffer, &num_bytes, NULL, NULL,
-                            MOJO_READ_MESSAGE_FLAG_NONE));
-  EXPECT_EQ((uint32_t) sizeof(kHello), num_bytes);
-  EXPECT_EQ(0, memcmp(buffer, kHello, sizeof(kHello)));
-
-  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle0));
-  EXPECT_EQ(MOJO_RESULT_OK, MojoClose(handle1));
-
-  // TODO(vtl): data pipe
-
-  return NULL;
-}
diff --git a/mojo/public/tests/system/macros_unittest.cc b/mojo/public/tests/system/macros_unittest.cc
deleted file mode 100644
index 295703f..0000000
--- a/mojo/public/tests/system/macros_unittest.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file consists of "positive" tests, i.e., those verifying that things
-// work (without compile errors, or even warnings if warnings are treated as
-// errors).
-// TODO(vtl): Fix no-compile tests (which are all disabled; crbug.com/105388)
-// and write some "negative" tests.
-
-#include "mojo/public/system/macros.h"
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "mojo/public/system/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-TEST(MacrosTest, AllowUnused) {
-  // Test that no warning/error is issued even though |x| is unused.
-  int x MOJO_ALLOW_UNUSED = 123;
-}
-
-int MustUseReturnedResult() MOJO_WARN_UNUSED_RESULT;
-int MustUseReturnedResult() {
-  return 456;
-}
-
-TEST(MacrosTest, WarnUnusedResult) {
-  if (!MustUseReturnedResult())
-    abort();
-}
-
-// Note: MSVS is very strict (and arguably buggy) about warnings for classes
-// defined in a local scope, so define these globally.
-struct TestOverrideBaseClass {
-  virtual ~TestOverrideBaseClass() {}
-  virtual void ToBeOverridden() {}
-  virtual void AlsoToBeOverridden() = 0;
-};
-
-struct TestOverrideSubclass : public TestOverrideBaseClass {
-  virtual ~TestOverrideSubclass() {}
-  virtual void ToBeOverridden() MOJO_OVERRIDE {}
-  virtual void AlsoToBeOverridden() MOJO_OVERRIDE {}
-};
-
-TEST(MacrosTest, Override) {
-  TestOverrideSubclass x;
-  x.ToBeOverridden();
-  x.AlsoToBeOverridden();
-}
-
-// Note: MSVS is very strict (and arguably buggy) about warnings for classes
-// defined in a local scope, so define these globally.
-class TestDisallowCopyAndAssignClass {
- public:
-  TestDisallowCopyAndAssignClass() {}
-  explicit TestDisallowCopyAndAssignClass(int) {}
-  void NoOp() {}
-
- private:
-  MOJO_DISALLOW_COPY_AND_ASSIGN(TestDisallowCopyAndAssignClass);
-};
-
-TEST(MacrosTest, DisallowCopyAndAssign) {
-  TestDisallowCopyAndAssignClass x;
-  x.NoOp();
-  TestDisallowCopyAndAssignClass y(789);
-  y.NoOp();
-}
-
-// First test |MOJO_COMPILE_ASSERT()| in a global scope.
-MOJO_COMPILE_ASSERT(sizeof(int64_t) == 2 * sizeof(int32_t),
-                    bad_compile_assert_failure_in_global_scope);
-
-TEST(MacrosTest, CompileAssert) {
-  // Then in a local scope.
-  MOJO_COMPILE_ASSERT(sizeof(int32_t) == 2 * sizeof(int16_t),
-                      bad_compile_assert_failure);
-}
-
-// Test that |MOJO_ARRAYSIZE()| works in a |MOJO_COMPILE_ASSERT()|.
-const int kGlobalArray[5] = { 1, 2, 3, 4, 5 };
-MOJO_COMPILE_ASSERT(MOJO_ARRAYSIZE(kGlobalArray) == 5u,
-                    mojo_array_size_failed_in_compile_assert);
-
-TEST(MacrosTest, ArraySize) {
-  double local_array[4] = { 6.7, 7.8, 8.9, 9.0 };
-  EXPECT_EQ(4u, MOJO_ARRAYSIZE(local_array));
-}
-
-// Note: MSVS is very strict (and arguably buggy) about warnings for classes
-// defined in a local scope, so define these globally.
-class MoveOnlyInt {
-  MOJO_MOVE_ONLY_TYPE_FOR_CPP_03(MoveOnlyInt, RValue)
-
- public:
-  MoveOnlyInt() : is_set_(false), value_() {}
-  explicit MoveOnlyInt(int value) : is_set_(true), value_(value) {}
-  ~MoveOnlyInt() {}
-
-  // Move-only constructor and operator=.
-  MoveOnlyInt(RValue other) { *this = other; }
-  MoveOnlyInt& operator=(RValue other) {
-    if (other.object != this) {
-      is_set_ = other.object->is_set_;
-      value_ = other.object->value_;
-      other.object->is_set_ = false;
-    }
-    return *this;
-  }
-
-  int value() const {
-    assert(is_set());
-    return value_;
-  }
-  bool is_set() const { return is_set_; }
-
- private:
-  bool is_set_;
-  int value_;
-};
-
-TEST(MacrosTest, MoveOnlyTypeForCpp03) {
-  MoveOnlyInt x(123);
-  EXPECT_TRUE(x.is_set());
-  EXPECT_EQ(123, x.value());
-  MoveOnlyInt y;
-  EXPECT_FALSE(y.is_set());
-  y = x.Pass();
-  EXPECT_FALSE(x.is_set());
-  EXPECT_TRUE(y.is_set());
-  EXPECT_EQ(123, y.value());
-  MoveOnlyInt z(y.Pass());
-  EXPECT_FALSE(y.is_set());
-  EXPECT_TRUE(z.is_set());
-  EXPECT_EQ(123, z.value());
-  z = z.Pass();
-  EXPECT_TRUE(z.is_set());
-  EXPECT_EQ(123, z.value());
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/tests/test_utils.cc b/mojo/public/tests/test_utils.cc
index 9b6eeaa..2e9bc38 100644
--- a/mojo/public/tests/test_utils.cc
+++ b/mojo/public/tests/test_utils.cc
@@ -4,7 +4,7 @@
 
 #include "mojo/public/tests/test_utils.h"
 
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/tests/test_support.h"
 
 namespace mojo {
diff --git a/mojo/public/tests/test_utils.h b/mojo/public/tests/test_utils.h
index a8c9d16..300c1b7 100644
--- a/mojo/public/tests/test_utils.h
+++ b/mojo/public/tests/test_utils.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 
 namespace mojo {
 namespace test {
diff --git a/mojo/public/utility/DEPS b/mojo/public/utility/DEPS
deleted file mode 100644
index dd7669a..0000000
--- a/mojo/public/utility/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+mojo/public/system",
-]
diff --git a/mojo/public/utility/lib/mutex.cc b/mojo/public/utility/lib/mutex.cc
deleted file mode 100644
index b962ccc..0000000
--- a/mojo/public/utility/lib/mutex.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/mutex.h"
-
-#include <assert.h>
-#include <errno.h>
-
-namespace mojo {
-
-// Release builds have inlined (non-error-checking) definitions in the header.
-#if !defined(NDEBUG)
-Mutex::Mutex() {
-  pthread_mutexattr_t mutexattr;
-  int rv = pthread_mutexattr_init(&mutexattr);
-  assert(rv == 0);
-  rv = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
-  assert(rv == 0);
-  rv = pthread_mutex_init(&mutex_, &mutexattr);
-  assert(rv == 0);
-  rv = pthread_mutexattr_destroy(&mutexattr);
-  assert(rv == 0);
-}
-
-Mutex::~Mutex() {
-  int rv = pthread_mutex_destroy(&mutex_);
-  assert(rv == 0);
-}
-
-void Mutex::Lock() {
-  int rv = pthread_mutex_lock(&mutex_);
-  assert(rv == 0);
-}
-
-void Mutex::Unlock() {
-  int rv = pthread_mutex_unlock(&mutex_);
-  assert(rv == 0);
-}
-
-bool Mutex::TryLock() {
-  int rv = pthread_mutex_trylock(&mutex_);
-  assert(rv == 0 || rv == EBUSY);
-  return rv == 0;
-}
-
-void Mutex::AssertHeld() {
-  assert(pthread_mutex_lock(&mutex_) == EDEADLK);
-}
-#endif  // !defined(NDEBUG)
-
-}  // namespace mojo
diff --git a/mojo/public/utility/lib/run_loop.cc b/mojo/public/utility/lib/run_loop.cc
deleted file mode 100644
index 37cc1e0..0000000
--- a/mojo/public/utility/lib/run_loop.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/run_loop.h"
-
-#include <assert.h>
-
-#include <algorithm>
-#include <vector>
-
-#include "mojo/public/utility/lib/thread_local.h"
-#include "mojo/public/utility/run_loop_handler.h"
-
-namespace mojo {
-namespace {
-
-internal::ThreadLocalPointer<RunLoop> current_run_loop;
-
-const MojoTimeTicks kInvalidTimeTicks = static_cast<MojoTimeTicks>(0);
-
-}  // namespace
-
-// State needed for one iteration of WaitMany().
-struct RunLoop::WaitState {
-  WaitState() : deadline(MOJO_DEADLINE_INDEFINITE) {}
-
-  std::vector<Handle> handles;
-  std::vector<MojoWaitFlags> wait_flags;
-  MojoDeadline deadline;
-};
-
-struct RunLoop::RunState {
-  RunState() : should_quit(false) {}
-
-  bool should_quit;
-};
-
-RunLoop::RunLoop() : run_state_(NULL), next_handler_id_(0) {
-  assert(!current());
-  current_run_loop.Set(this);
-}
-
-RunLoop::~RunLoop() {
-  assert(current() == this);
-  current_run_loop.Set(NULL);
-}
-
-// static
-void RunLoop::SetUp() {
-  current_run_loop.Allocate();
-}
-
-// static
-void RunLoop::TearDown() {
-  assert(!current());
-  current_run_loop.Free();
-}
-
-// static
-RunLoop* RunLoop::current() {
-  return current_run_loop.Get();
-}
-
-void RunLoop::AddHandler(RunLoopHandler* handler,
-                         const Handle& handle,
-                         MojoWaitFlags wait_flags,
-                         MojoDeadline deadline) {
-  assert(current() == this);
-  assert(handler);
-  assert(handle.is_valid());
-  // Assume it's an error if someone tries to reregister an existing handle.
-  assert(0u == handler_data_.count(handle));
-  HandlerData handler_data;
-  handler_data.handler = handler;
-  handler_data.wait_flags = wait_flags;
-  handler_data.deadline = (deadline == MOJO_DEADLINE_INDEFINITE) ?
-      kInvalidTimeTicks :
-      GetTimeTicksNow() + static_cast<MojoTimeTicks>(deadline);
-  handler_data.id = next_handler_id_++;
-  handler_data_[handle] = handler_data;
-}
-
-void RunLoop::RemoveHandler(const Handle& handle) {
-  assert(current() == this);
-  handler_data_.erase(handle);
-}
-
-bool RunLoop::HasHandler(const Handle& handle) const {
-  return handler_data_.find(handle) != handler_data_.end();
-}
-
-void RunLoop::Run() {
-  assert(current() == this);
-  // We don't currently support nesting.
-  assert(!run_state_);
-  RunState* old_state = run_state_;
-  RunState run_state;
-  run_state_ = &run_state;
-  while (!run_state.should_quit)
-    Wait(false);
-  run_state_ = old_state;
-}
-
-void RunLoop::RunUntilIdle() {
-  assert(current() == this);
-  // We don't currently support nesting.
-  assert(!run_state_);
-  RunState* old_state = run_state_;
-  RunState run_state;
-  run_state_ = &run_state;
-  while (!run_state.should_quit) {
-    if (!Wait(true))
-      break;
-  }
-  run_state_ = old_state;
-}
-
-void RunLoop::Quit() {
-  assert(current() == this);
-  if (run_state_)
-    run_state_->should_quit = true;
-}
-
-bool RunLoop::Wait(bool non_blocking) {
-  const WaitState wait_state = GetWaitState(non_blocking);
-  if (wait_state.handles.empty()) {
-    Quit();
-    return false;
-  }
-
-  const MojoResult result =
-      WaitMany(wait_state.handles, wait_state.wait_flags, wait_state.deadline);
-  if (result >= 0) {
-    const size_t index = static_cast<size_t>(result);
-    assert(handler_data_.find(wait_state.handles[index]) !=
-           handler_data_.end());
-    handler_data_[wait_state.handles[index]].handler->OnHandleReady(
-        wait_state.handles[index]);
-    return true;
-  }
-
-  switch (result) {
-    case MOJO_RESULT_INVALID_ARGUMENT:
-    case MOJO_RESULT_FAILED_PRECONDITION:
-      return RemoveFirstInvalidHandle(wait_state);
-    case MOJO_RESULT_DEADLINE_EXCEEDED:
-      return NotifyDeadlineExceeded();
-  }
-
-  assert(false);
-  return false;
-}
-
-bool RunLoop::NotifyDeadlineExceeded() {
-  bool notified = false;
-
-  // Make a copy in case someone tries to add/remove new handlers as part of
-  // notifying.
-  const HandleToHandlerData cloned_handlers(handler_data_);
-  const MojoTimeTicks now(GetTimeTicksNow());
-  for (HandleToHandlerData::const_iterator i = cloned_handlers.begin();
-       i != cloned_handlers.end(); ++i) {
-    // Since we're iterating over a clone of the handlers, verify the handler is
-    // still valid before notifying.
-    if (i->second.deadline != kInvalidTimeTicks &&
-        i->second.deadline < now &&
-        handler_data_.find(i->first) != handler_data_.end() &&
-        handler_data_[i->first].id == i->second.id) {
-      handler_data_.erase(i->first);
-      i->second.handler->OnHandleError(i->first, MOJO_RESULT_DEADLINE_EXCEEDED);
-      notified = true;
-    }
-  }
-
-  return notified;
-}
-
-bool RunLoop::RemoveFirstInvalidHandle(const WaitState& wait_state) {
-  for (size_t i = 0; i < wait_state.handles.size(); ++i) {
-    const MojoResult result =
-        mojo::Wait(wait_state.handles[i], wait_state.wait_flags[i],
-                   static_cast<MojoDeadline>(0));
-    if (result == MOJO_RESULT_INVALID_ARGUMENT ||
-        result == MOJO_RESULT_FAILED_PRECONDITION) {
-      // Remove the handle first, this way if OnHandleError() tries to remove
-      // the handle our iterator isn't invalidated.
-      assert(handler_data_.find(wait_state.handles[i]) != handler_data_.end());
-      RunLoopHandler* handler =
-          handler_data_[wait_state.handles[i]].handler;
-      handler_data_.erase(wait_state.handles[i]);
-      handler->OnHandleError(wait_state.handles[i], result);
-      return true;
-    }
-    assert(MOJO_RESULT_DEADLINE_EXCEEDED == result);
-  }
-  return false;
-}
-
-RunLoop::WaitState RunLoop::GetWaitState(bool non_blocking) const {
-  WaitState wait_state;
-  MojoTimeTicks min_time = kInvalidTimeTicks;
-  for (HandleToHandlerData::const_iterator i = handler_data_.begin();
-       i != handler_data_.end(); ++i) {
-    wait_state.handles.push_back(i->first);
-    wait_state.wait_flags.push_back(i->second.wait_flags);
-    if (!non_blocking && i->second.deadline != kInvalidTimeTicks &&
-        (min_time == kInvalidTimeTicks || i->second.deadline < min_time)) {
-      min_time = i->second.deadline;
-    }
-  }
-  if (non_blocking) {
-    wait_state.deadline = static_cast<MojoDeadline>(0);
-  } else if (min_time != kInvalidTimeTicks) {
-    const MojoTimeTicks now = GetTimeTicksNow();
-    if (min_time < now)
-      wait_state.deadline = static_cast<MojoDeadline>(0);
-    else
-      wait_state.deadline = static_cast<MojoDeadline>(min_time - now);
-  }
-  return wait_state;
-}
-
-}  // namespace mojo
diff --git a/mojo/public/utility/lib/thread.cc b/mojo/public/utility/lib/thread.cc
deleted file mode 100644
index 3549d40..0000000
--- a/mojo/public/utility/lib/thread.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/thread.h"
-
-#include <assert.h>
-
-namespace mojo {
-
-Thread::Thread()
-    : options_(),
-      thread_(),
-      started_(false),
-      joined_(false) {
-}
-
-Thread::Thread(const Options& options)
-    : options_(options),
-      thread_(),
-      started_(false),
-      joined_(false) {
-}
-
-Thread::~Thread() {
-  // If it was started, it must have been joined.
-  assert(!started_ || joined_);
-}
-
-void Thread::Start() {
-  assert(!started_);
-  assert(!joined_);
-
-  pthread_attr_t attr;
-  int rv MOJO_ALLOW_UNUSED = pthread_attr_init(&attr);
-  assert(rv == 0);
-
-  // Non-default stack size?
-  if (options_.stack_size() != 0) {
-    rv = pthread_attr_setstacksize(&attr, options_.stack_size());
-    assert(rv == 0);
-  }
-
-  started_ = true;
-  rv = pthread_create(&thread_, &attr, &ThreadRunTrampoline, this);
-  assert(rv == 0);
-
-  rv = pthread_attr_destroy(&attr);
-  assert(rv == 0);
-}
-
-void Thread::Join() {
-  // Must have been started but not yet joined.
-  assert(started_);
-  assert(!joined_);
-
-  joined_ = true;
-  int rv MOJO_ALLOW_UNUSED = pthread_join(thread_, NULL);
-  assert(rv == 0);
-}
-
-// static
-void* Thread::ThreadRunTrampoline(void* arg) {
-  Thread* self = static_cast<Thread*>(arg);
-  self->Run();
-  return NULL;
-}
-
-}  // namespace mojo
diff --git a/mojo/public/utility/lib/thread_local.h b/mojo/public/utility/lib/thread_local.h
deleted file mode 100644
index 10cc625..0000000
--- a/mojo/public/utility/lib/thread_local.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_UTILITY_LIB_THREAD_LOCAL_H_
-#define MOJO_PUBLIC_UTILITY_LIB_THREAD_LOCAL_H_
-
-#ifndef _WIN32
-#include <pthread.h>
-#endif
-
-#include "mojo/public/system/macros.h"
-
-namespace mojo {
-namespace internal {
-
-// Helper functions that abstract the cross-platform APIs.
-struct ThreadLocalPlatform {
-#ifdef _WIN32
-  typedef unsigned long SlotType;
-#else
-  typedef pthread_key_t SlotType;
-#endif
-
-  static void AllocateSlot(SlotType* slot);
-  static void FreeSlot(SlotType slot);
-  static void* GetValueFromSlot(SlotType slot);
-  static void SetValueInSlot(SlotType slot, void* value);
-};
-
-// This class is intended to be statically allocated.
-template <typename P>
-class ThreadLocalPointer {
- public:
-  ThreadLocalPointer() : slot_() {
-  }
-
-  void Allocate() {
-    ThreadLocalPlatform::AllocateSlot(&slot_);
-  }
-
-  void Free() {
-    ThreadLocalPlatform::FreeSlot(slot_);
-  }
-
-  P* Get() {
-    return static_cast<P*>(ThreadLocalPlatform::GetValueFromSlot(slot_));
-  }
-
-  void Set(P* value) {
-    ThreadLocalPlatform::SetValueInSlot(slot_, value);
-  }
-
- private:
-  ThreadLocalPlatform::SlotType slot_;
-};
-
-}  // namespace internal
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_UTILITY_LIB_THREAD_LOCAL_H_
diff --git a/mojo/public/utility/lib/thread_local_posix.cc b/mojo/public/utility/lib/thread_local_posix.cc
deleted file mode 100644
index cd7a8a4..0000000
--- a/mojo/public/utility/lib/thread_local_posix.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/lib/thread_local.h"
-
-#include <assert.h>
-
-namespace mojo {
-namespace internal {
-
-// static
-void ThreadLocalPlatform::AllocateSlot(SlotType* slot) {
-  if (pthread_key_create(slot, NULL) != 0) {
-    assert(false);
-  }
-}
-
-// static
-void ThreadLocalPlatform::FreeSlot(SlotType slot) {
-  if (pthread_key_delete(slot) != 0) {
-    assert(false);
-  }
-}
-
-// static
-void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) {
-  return pthread_getspecific(slot);
-}
-
-// static
-void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) {
-  if (pthread_setspecific(slot, value) != 0) {
-    assert(false);
-  }
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/public/utility/lib/thread_local_win.cc b/mojo/public/utility/lib/thread_local_win.cc
deleted file mode 100644
index 3d667ea..0000000
--- a/mojo/public/utility/lib/thread_local_win.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/lib/thread_local.h"
-
-#include <assert.h>
-#include <windows.h>
-
-namespace mojo {
-namespace internal {
-
-// static
-void ThreadLocalPlatform::AllocateSlot(SlotType* slot) {
-  *slot = TlsAlloc();
-  assert(*slot != TLS_OUT_OF_INDEXES);
-}
-
-// static
-void ThreadLocalPlatform::FreeSlot(SlotType slot) {
-  if (!TlsFree(slot)) {
-    assert(false);
-  }
-}
-
-// static
-void* ThreadLocalPlatform::GetValueFromSlot(SlotType slot) {
-  return TlsGetValue(slot);
-}
-
-// static
-void ThreadLocalPlatform::SetValueInSlot(SlotType slot, void* value) {
-  if (!TlsSetValue(slot, value)) {
-    assert(false);
-  }
-}
-
-}  // namespace internal
-}  // namespace mojo
diff --git a/mojo/public/utility/mutex.h b/mojo/public/utility/mutex.h
deleted file mode 100644
index 3267759..0000000
--- a/mojo/public/utility/mutex.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_UTILITY_MUTEX_H_
-#define MOJO_PUBLIC_UTILITY_MUTEX_H_
-
-#ifdef _WIN32
-#error "Not implemented: See crbug.com/342893."
-#endif
-
-#include <pthread.h>
-
-#include "mojo/public/system/macros.h"
-
-namespace mojo {
-
-#ifdef NDEBUG
-// Note: Make a C++ constant for |PTHREAD_MUTEX_INITIALIZER|. (We can't directly
-// use the C macro in an initializer list, since it might expand to |{ ... }|.)
-namespace internal {
-const pthread_mutex_t kPthreadMutexInitializer = PTHREAD_MUTEX_INITIALIZER;
-}
-#endif
-
-class Mutex {
- public:
-#ifdef NDEBUG
-  Mutex() : mutex_(internal::kPthreadMutexInitializer) {}
-  ~Mutex() { pthread_mutex_destroy(&mutex_); }
-
-  void Lock() { pthread_mutex_lock(&mutex_); }
-  void Unlock() { pthread_mutex_unlock(&mutex_); }
-  bool TryLock() { return pthread_mutex_trylock(&mutex_) == 0; }
-
-  void AssertHeld() {}
-#else
-  Mutex();
-  ~Mutex();
-
-  void Lock();
-  void Unlock();
-  bool TryLock();
-
-  void AssertHeld();
-#endif
-
- private:
-  pthread_mutex_t mutex_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(Mutex);
-};
-
-class MutexLock {
- public:
-  explicit MutexLock(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
-  ~MutexLock() { mutex_->Unlock(); }
-
- private:
-  Mutex* const mutex_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(MutexLock);
-};
-
-// Catch bug where variable name is omitted (e.g., |MutexLock (&mu)|).
-#define MutexLock(x) MOJO_COMPILE_ASSERT(0, mutex_lock_missing_variable_name);
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_UTILITY_MUTEX_H_
diff --git a/mojo/public/utility/run_loop.h b/mojo/public/utility/run_loop.h
deleted file mode 100644
index be39edb..0000000
--- a/mojo/public/utility/run_loop.h
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_UTILITY_RUN_LOOP_H_
-#define MOJO_PUBLIC_UTILITY_RUN_LOOP_H_
-
-#include <map>
-
-#include "mojo/public/system/core_cpp.h"
-
-namespace mojo {
-
-class RunLoopHandler;
-
-class RunLoop {
- public:
-  RunLoop();
-  ~RunLoop();
-
-  // Sets up state needed for RunLoop. This must be invoked before creating a
-  // RunLoop.
-  static void SetUp();
-
-  // Cleans state created by Setup().
-  static void TearDown();
-
-  // Returns the RunLoop for the current thread. Returns NULL if not yet
-  // created.
-  static RunLoop* current();
-
-  // Registers a RunLoopHandler for the specified handle. Only one handler can
-  // be registered for a specified handle.
-  void AddHandler(RunLoopHandler* handler,
-                  const Handle& handle,
-                  MojoWaitFlags wait_flags,
-                  MojoDeadline deadline);
-  void RemoveHandler(const Handle& handle);
-  bool HasHandler(const Handle& handle) const;
-
-  // Runs the loop servicing handles as they are ready. This returns when Quit()
-  // is invoked, or there no more handles.
-  void Run();
-
-  // Runs the loop servicing any handles that are ready. Does not wait for
-  // handles to become ready before returning. Returns early if Quit() is
-  // invoked.
-  void RunUntilIdle();
-
-  void Quit();
-
- private:
-  struct RunState;
-  struct WaitState;
-
-  // Contains the data needed to track a request to AddHandler().
-  struct HandlerData {
-    HandlerData()
-        : handler(NULL),
-          wait_flags(MOJO_WAIT_FLAG_NONE),
-          deadline(0),
-          id(0) {}
-
-    RunLoopHandler* handler;
-    MojoWaitFlags wait_flags;
-    MojoTimeTicks deadline;
-    // See description of |RunLoop::next_handler_id_| for details.
-    int id;
-  };
-
-  typedef std::map<Handle, HandlerData> HandleToHandlerData;
-
-  // Waits for a handle to be ready. Returns after servicing at least one
-  // handle (or there are no more handles) unless |non_blocking| is true,
-  // in which case it will also return if servicing at least one handle
-  // would require blocking. Returns true if a RunLoopHandler was notified.
-  bool Wait(bool non_blocking);
-
-  // Notifies any handlers whose deadline has expired. Returns true if a
-  // RunLoopHandler was notified.
-  bool NotifyDeadlineExceeded();
-
-  // Removes the first invalid handle. This is called if MojoWaitMany() finds an
-  // invalid handle. Returns true if a RunLoopHandler was notified.
-  bool RemoveFirstInvalidHandle(const WaitState& wait_state);
-
-  // Returns the state needed to pass to WaitMany().
-  WaitState GetWaitState(bool non_blocking) const;
-
-  HandleToHandlerData handler_data_;
-
-  // If non-NULL we're running (inside Run()). Member references a value on the
-  // stack.
-  RunState* run_state_;
-
-  // An ever increasing value assigned to each HandlerData::id. Used to detect
-  // uniqueness while notifying. That is, while notifying expired timers we copy
-  // |handler_data_| and only notify handlers whose id match. If the id does not
-  // match it means the handler was removed then added so that we shouldn't
-  // notify it.
-  int next_handler_id_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoop);
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_UTILITY_RUN_LOOP_H_
diff --git a/mojo/public/utility/run_loop_handler.h b/mojo/public/utility/run_loop_handler.h
deleted file mode 100644
index 0a650d1..0000000
--- a/mojo/public/utility/run_loop_handler.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_UTILITY_RUN_LOOP_HANDLER_H_
-#define MOJO_PUBLIC_UTILITY_RUN_LOOP_HANDLER_H_
-
-#include "mojo/public/system/core_cpp.h"
-
-namespace mojo {
-
-// Used by RunLoop to notify when a handle is either ready or has become
-// invalid.
-class RunLoopHandler {
- public:
-  virtual void OnHandleReady(const Handle& handle) = 0;
-  virtual void OnHandleError(const Handle& handle, MojoResult result) = 0;
-
- protected:
-  virtual ~RunLoopHandler() {}
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_UTILITY_RUN_LOOP_HANDLER_H_
diff --git a/mojo/public/utility/tests/mutex_unittest.cc b/mojo/public/utility/tests/mutex_unittest.cc
deleted file mode 100644
index 7a9f8d4..0000000
--- a/mojo/public/utility/tests/mutex_unittest.cc
+++ /dev/null
@@ -1,262 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/mutex.h"
-
-#include <stdlib.h>  // For |rand()|.
-#include <time.h>  // For |nanosleep()| (defined by POSIX).
-
-#include <vector>
-
-#include "mojo/public/system/macros.h"
-#include "mojo/public/utility/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-TEST(MutexTest, TrivialSingleThreaded) {
-  Mutex mutex;
-
-  mutex.Lock();
-  mutex.AssertHeld();
-  mutex.Unlock();
-
-  EXPECT_TRUE(mutex.TryLock());
-  mutex.AssertHeld();
-  mutex.Unlock();
-
-  {
-    MutexLock lock(&mutex);
-    mutex.AssertHeld();
-  }
-
-  EXPECT_TRUE(mutex.TryLock());
-  mutex.Unlock();
-}
-
-class Fiddler {
- public:
-  enum Type { kTypeLock, kTypeTry };
-  Fiddler(size_t times_to_lock,
-          Type type,
-          bool should_sleep,
-          Mutex* mutex,
-          int* shared_value)
-      : times_to_lock_(times_to_lock),
-        type_(type),
-        should_sleep_(should_sleep),
-        mutex_(mutex),
-        shared_value_(shared_value) {
-  }
-
-  ~Fiddler() {
-  }
-
-  void Fiddle() {
-    for (size_t i = 0; i < times_to_lock_;) {
-      switch (type_) {
-        case kTypeLock: {
-          mutex_->Lock();
-          int old_shared_value = *shared_value_;
-          if (should_sleep_)
-            SleepALittle();
-          *shared_value_ = old_shared_value + 1;
-          mutex_->Unlock();
-          i++;
-          break;
-        }
-        case kTypeTry:
-          if (mutex_->TryLock()) {
-            int old_shared_value = *shared_value_;
-            if (should_sleep_)
-              SleepALittle();
-            *shared_value_ = old_shared_value + 1;
-            mutex_->Unlock();
-            i++;
-          } else {
-            SleepALittle();  // Don't spin.
-          }
-          break;
-      }
-    }
-  }
-
- private:
-  static void SleepALittle() {
-    static const long kNanosPerMilli = 1000000;
-    struct timespec req = {
-      0,  // Seconds.
-      (rand() % 10) * kNanosPerMilli // Nanoseconds.
-    };
-    int rv MOJO_ALLOW_UNUSED = nanosleep(&req, NULL);
-    assert(rv == 0);
-  }
-
-  const size_t times_to_lock_;
-  const Type type_;
-  const bool should_sleep_;
-  Mutex* const mutex_;
-  int* const shared_value_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(Fiddler);
-};
-
-class FiddlerThread : public Thread {
- public:
-  // Takes ownership of |fiddler|.
-  FiddlerThread(Fiddler* fiddler)
-      : fiddler_(fiddler) {
-  }
-
-  virtual ~FiddlerThread() {
-    delete fiddler_;
-  }
-
-  virtual void Run() MOJO_OVERRIDE {
-    fiddler_->Fiddle();
-  }
-
- private:
-  Fiddler* const fiddler_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(FiddlerThread);
-};
-
-// This does a stress test (that also checks exclusion).
-TEST(MutexTest, ThreadedStress) {
-  static const size_t kNumThreads = 20;
-  static const int kTimesToLockEach = 20;
-  assert(kNumThreads % 4 == 0);
-
-  Mutex mutex;
-  int shared_value = 0;
-
-  std::vector<FiddlerThread*> fiddler_threads;
-
-  for (size_t i = 0; i < kNumThreads; i += 4) {
-    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
-        kTimesToLockEach, Fiddler::kTypeLock, false, &mutex, &shared_value)));
-    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
-        kTimesToLockEach, Fiddler::kTypeTry, false, &mutex, &shared_value)));
-    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
-        kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value)));
-    fiddler_threads.push_back(new FiddlerThread(new Fiddler(
-        kTimesToLockEach, Fiddler::kTypeTry, true, &mutex, &shared_value)));
-  }
-
-  for (size_t i = 0; i < kNumThreads; i++)
-    fiddler_threads[i]->Start();
-
-  // Do some fiddling ourselves.
-  Fiddler(kTimesToLockEach, Fiddler::kTypeLock, true, &mutex, &shared_value)
-      .Fiddle();
-
-  // Join.
-  for (size_t i = 0; i < kNumThreads; i++)
-    fiddler_threads[i]->Join();
-
-  EXPECT_EQ(static_cast<int>(kNumThreads + 1) * kTimesToLockEach, shared_value);
-
-  // Delete.
-  for (size_t i = 0; i < kNumThreads; i++)
-    delete fiddler_threads[i];
-  fiddler_threads.clear();
-}
-
-class TryThread : public Thread {
- public:
-  explicit TryThread(Mutex* mutex) : mutex_(mutex), try_lock_succeeded_() {}
-  virtual ~TryThread() {}
-
-  virtual void Run() MOJO_OVERRIDE {
-    try_lock_succeeded_ = mutex_->TryLock();
-    if (try_lock_succeeded_)
-      mutex_->Unlock();
-  }
-
-  bool try_lock_succeeded() const { return try_lock_succeeded_; }
-
- private:
-  Mutex* const mutex_;
-  bool try_lock_succeeded_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(TryThread);
-};
-
-TEST(MutexTest, TryLock) {
-  Mutex mutex;
-
-  // |TryLock()| should succeed -- we don't have the lock.
-  {
-    TryThread thread(&mutex);
-    thread.Start();
-    thread.Join();
-    EXPECT_TRUE(thread.try_lock_succeeded());
-  }
-
-  // Take the lock.
-  ASSERT_TRUE(mutex.TryLock());
-
-  // Now it should fail.
-  {
-    TryThread thread(&mutex);
-    thread.Start();
-    thread.Join();
-    EXPECT_FALSE(thread.try_lock_succeeded());
-  }
-
-  // Release the lock.
-  mutex.Unlock();
-
-  // It should succeed again.
-  {
-    TryThread thread(&mutex);
-    thread.Start();
-    thread.Join();
-    EXPECT_TRUE(thread.try_lock_succeeded());
-  }
-}
-
-
-// Tests of assertions for Debug builds.
-#if !defined(NDEBUG)
-// Test |AssertHeld()| (which is an actual user API).
-TEST(MutexTest, DebugAssertHeldFailure) {
-  Mutex mutex;
-  EXPECT_DEATH(mutex.AssertHeld(), "");
-}
-
-// Test other consistency checks.
-TEST(MutexTest, DebugAssertionFailures) {
-  // Unlock without lock held.
-  EXPECT_DEATH({
-    Mutex mutex;
-    mutex.Unlock();
-  }, "");
-
-  // Lock with lock held (on same thread).
-  EXPECT_DEATH({
-    Mutex mutex;
-    mutex.Lock();
-    mutex.Lock();
-  }, "");
-
-  // Try lock with lock held.
-  EXPECT_DEATH({
-    Mutex mutex;
-    mutex.Lock();
-    mutex.TryLock();
-  }, "");
-
-  // Destroy lock with lock held.
-  EXPECT_DEATH({
-    Mutex mutex;
-    mutex.Lock();
-  }, "");
-}
-#endif  // !defined(NDEBUG)
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/utility/tests/run_loop_unittest.cc b/mojo/public/utility/tests/run_loop_unittest.cc
deleted file mode 100644
index 4bd4791..0000000
--- a/mojo/public/utility/tests/run_loop_unittest.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/run_loop.h"
-
-#include <string>
-
-#include "mojo/public/system/core_cpp.h"
-#include "mojo/public/tests/test_utils.h"
-#include "mojo/public/utility/run_loop_handler.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-class TestRunLoopHandler : public RunLoopHandler {
- public:
-  TestRunLoopHandler()
-      : ready_count_(0),
-        error_count_(0),
-        last_error_result_(MOJO_RESULT_OK) {
-  }
-  virtual ~TestRunLoopHandler() {}
-
-  void clear_ready_count() { ready_count_ = 0; }
-  int ready_count() const { return ready_count_; }
-
-  void clear_error_count() { error_count_ = 0; }
-  int error_count() const { return error_count_; }
-
-  MojoResult last_error_result() const { return last_error_result_; }
-
-  // RunLoopHandler:
-  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
-    ready_count_++;
-  }
-  virtual void OnHandleError(const Handle& handle, MojoResult result)
-      MOJO_OVERRIDE {
-    error_count_++;
-    last_error_result_ = result;
-  }
-
- private:
-  int ready_count_;
-  int error_count_;
-  MojoResult last_error_result_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(TestRunLoopHandler);
-};
-
-class RunLoopTest : public testing::Test {
- public:
-  RunLoopTest() {}
-
-  virtual void SetUp() MOJO_OVERRIDE {
-    Test::SetUp();
-    RunLoop::SetUp();
-  }
-  virtual void TearDown() MOJO_OVERRIDE {
-    RunLoop::TearDown();
-    Test::TearDown();
-  }
-
- private:
-  MOJO_DISALLOW_COPY_AND_ASSIGN(RunLoopTest);
-};
-
-// Trivial test to verify Run() with no added handles returns.
-TEST_F(RunLoopTest, ExitsWithNoHandles) {
-  RunLoop run_loop;
-  run_loop.Run();
-}
-
-class RemoveOnReadyRunLoopHandler : public TestRunLoopHandler {
- public:
-  RemoveOnReadyRunLoopHandler() : run_loop_(NULL) {
-  }
-  virtual ~RemoveOnReadyRunLoopHandler() {}
-
-  void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
-
-  // RunLoopHandler:
-  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
-    run_loop_->RemoveHandler(handle);
-    TestRunLoopHandler::OnHandleReady(handle);
-  }
-
- private:
-  RunLoop* run_loop_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(RemoveOnReadyRunLoopHandler);
-};
-
-// Verifies RunLoop quits when no more handles (handle is removed when ready).
-TEST_F(RunLoopTest, HandleReady) {
-  RemoveOnReadyRunLoopHandler handler;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  RunLoop run_loop;
-  handler.set_run_loop(&run_loop);
-  run_loop.AddHandler(&handler, test_pipe.handle0.get(),
-                      MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE);
-  run_loop.Run();
-  EXPECT_EQ(1, handler.ready_count());
-  EXPECT_EQ(0, handler.error_count());
-  EXPECT_FALSE(run_loop.HasHandler(test_pipe.handle0.get()));
-}
-
-class QuitOnReadyRunLoopHandler : public TestRunLoopHandler {
- public:
-  QuitOnReadyRunLoopHandler() : run_loop_(NULL) {
-  }
-  virtual ~QuitOnReadyRunLoopHandler() {}
-
-  void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
-
-  // RunLoopHandler:
-  virtual void OnHandleReady(const Handle& handle) MOJO_OVERRIDE {
-    run_loop_->Quit();
-    TestRunLoopHandler::OnHandleReady(handle);
-  }
-
- private:
-  RunLoop* run_loop_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnReadyRunLoopHandler);
-};
-
-// Verifies Quit() from OnHandleReady() quits the loop.
-TEST_F(RunLoopTest, QuitFromReady) {
-  QuitOnReadyRunLoopHandler handler;
-  MessagePipe test_pipe;
-  EXPECT_TRUE(test::WriteTextMessage(test_pipe.handle1.get(), std::string()));
-
-  RunLoop run_loop;
-  handler.set_run_loop(&run_loop);
-  run_loop.AddHandler(&handler, test_pipe.handle0.get(),
-                      MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE);
-  run_loop.Run();
-  EXPECT_EQ(1, handler.ready_count());
-  EXPECT_EQ(0, handler.error_count());
-  EXPECT_TRUE(run_loop.HasHandler(test_pipe.handle0.get()));
-}
-
-class QuitOnErrorRunLoopHandler : public TestRunLoopHandler {
- public:
-  QuitOnErrorRunLoopHandler() : run_loop_(NULL) {
-  }
-  virtual ~QuitOnErrorRunLoopHandler() {}
-
-  void set_run_loop(RunLoop* run_loop) { run_loop_ = run_loop; }
-
-  // RunLoopHandler:
-  virtual void OnHandleError(const Handle& handle, MojoResult result)
-      MOJO_OVERRIDE {
-    run_loop_->Quit();
-    TestRunLoopHandler::OnHandleError(handle, result);
-  }
-
- private:
-  RunLoop* run_loop_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(QuitOnErrorRunLoopHandler);
-};
-
-// Verifies Quit() when the deadline is reached works.
-TEST_F(RunLoopTest, QuitWhenDeadlineExpired) {
-  QuitOnErrorRunLoopHandler handler;
-  MessagePipe test_pipe;
-  RunLoop run_loop;
-  handler.set_run_loop(&run_loop);
-  run_loop.AddHandler(&handler, test_pipe.handle0.get(),
-                      MOJO_WAIT_FLAG_READABLE,
-                      static_cast<MojoDeadline>(10000));
-  run_loop.Run();
-  EXPECT_EQ(0, handler.ready_count());
-  EXPECT_EQ(1, handler.error_count());
-  EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, handler.last_error_result());
-  EXPECT_FALSE(run_loop.HasHandler(test_pipe.handle0.get()));
-}
-
-TEST_F(RunLoopTest, Current) {
-  EXPECT_TRUE(RunLoop::current() == NULL);
-  {
-    RunLoop run_loop;
-    EXPECT_EQ(&run_loop, RunLoop::current());
-  }
-  EXPECT_TRUE(RunLoop::current() == NULL);
-}
-
-}  // namespace
-}  // namespace mojo
diff --git a/mojo/public/utility/tests/thread_unittest.cc b/mojo/public/utility/tests/thread_unittest.cc
deleted file mode 100644
index 3309c0c..0000000
--- a/mojo/public/utility/tests/thread_unittest.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "mojo/public/utility/thread.h"
-
-#include "mojo/public/system/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace mojo {
-namespace {
-
-class SetIntThread : public Thread {
- public:
-  SetIntThread(int* int_to_set, int value)
-      : int_to_set_(int_to_set),
-        value_(value) {
-  }
-  SetIntThread(const Options& options, int* int_to_set, int value)
-      : Thread(options),
-        int_to_set_(int_to_set),
-        value_(value) {
-  }
-
-  virtual ~SetIntThread() {
-  }
-
-  virtual void Run() MOJO_OVERRIDE {
-    *int_to_set_ = value_;
-  }
-
- private:
-  int* const int_to_set_;
-  const int value_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(SetIntThread);
-};
-
-TEST(ThreadTest, CreateAndJoin) {
-  int value = 0;
-
-  // Not starting the thread should result in a no-op.
-  {
-    SetIntThread thread(&value, 1234567);
-  }
-  EXPECT_EQ(0, value);
-
-  // Start and join.
-  {
-    SetIntThread thread(&value, 12345678);
-    thread.Start();
-    thread.Join();
-    EXPECT_EQ(12345678, value);
-  }
-
-  // Ditto, with non-default (but reasonable) stack size.
-  {
-    Thread::Options options;
-    options.set_stack_size(1024 * 1024);  // 1 MB.
-    SetIntThread thread(options, &value, 12345678);
-    thread.Start();
-    thread.Join();
-    EXPECT_EQ(12345678, value);
-  }
-}
-
-// Tests of assertions for Debug builds.
-// Note: It's okay to create threads, despite gtest having to fork. (The threads
-// are in the child process.)
-#if !defined(NDEBUG)
-TEST(ThreadTest, DebugAssertionFailures) {
-  // Can only start once.
-  EXPECT_DEATH({
-    int value = 0;
-    SetIntThread thread(&value, 1);
-    thread.Start();
-    thread.Start();
-  }, "");
-
-  // Must join (if you start).
-  EXPECT_DEATH({
-    int value = 0;
-    SetIntThread thread(&value, 2);
-    thread.Start();
-  }, "");
-
-  // Can only join once.
-  EXPECT_DEATH({
-    int value = 0;
-    SetIntThread thread(&value, 3);
-    thread.Start();
-    thread.Join();
-    thread.Join();
-  }, "");
-
-  // Stack too big (we're making certain assumptions here).
-  EXPECT_DEATH({
-    int value = 0;
-    Thread::Options options;
-    options.set_stack_size(static_cast<size_t>(-1));
-    SetIntThread thread(options, &value, 4);
-    thread.Start();
-    thread.Join();
-  }, "");
-}
-#endif  // !defined(NDEBUG)
-
-}  // namespace
-}  // namespace mojo
-
diff --git a/mojo/public/utility/thread.h b/mojo/public/utility/thread.h
deleted file mode 100644
index 055849e..0000000
--- a/mojo/public/utility/thread.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef MOJO_PUBLIC_UTILITY_THREAD_H_
-#define MOJO_PUBLIC_UTILITY_THREAD_H_
-
-#ifdef _WIN32
-#error "Not implemented: See crbug.com/342893."
-#endif
-
-#include <pthread.h>
-#include <stddef.h>
-
-#include "mojo/public/system/macros.h"
-
-namespace mojo {
-
-// This class is thread-friendly, not thread-safe (e.g., you mustn't call
-// |Join()| from multiple threads and/or simultaneously try to destroy the
-// object).
-class Thread {
- public:
-  // TODO(vtl): Support non-joinable? priority?
-  class Options {
-   public:
-    Options() : stack_size_(0) {}
-
-    // A stack size of 0 means the default.
-    size_t stack_size() const { return stack_size_; }
-    void set_stack_size(size_t stack_size) { stack_size_ = stack_size; }
-
-   private:
-    size_t stack_size_;
-
-    // Copy and assign allowed.
-  };
-
-  // TODO(vtl): Add name or name prefix?
-  Thread();
-  explicit Thread(const Options& options);
-  virtual ~Thread();
-
-  void Start();
-  void Join();
-
-  virtual void Run() = 0;
-
- private:
-  static void* ThreadRunTrampoline(void* arg);
-
-  const Options options_;
-  pthread_t thread_;
-  bool started_;
-  bool joined_;
-
-  MOJO_DISALLOW_COPY_AND_ASSIGN(Thread);
-};
-
-}  // namespace mojo
-
-#endif  // MOJO_PUBLIC_UTILITY_THREAD_H_
diff --git a/mojo/service_manager/service_loader.h b/mojo/service_manager/service_loader.h
index 7da0540..6d5be9a 100644
--- a/mojo/service_manager/service_loader.h
+++ b/mojo/service_manager/service_loader.h
@@ -6,6 +6,7 @@
 #define MOJO_SERVICE_MANAGER_SERVICE_LOADER_H_
 
 #include "mojo/public/shell/shell.mojom.h"
+#include "mojo/service_manager/service_manager_export.h"
 #include "url/gurl.h"
 
 namespace mojo {
@@ -14,12 +15,14 @@
 
 // Interface to allowing default loading behavior to be overridden for a
 // specific url.
-class ServiceLoader {
+class MOJO_SERVICE_MANAGER_EXPORT ServiceLoader {
  public:
   virtual ~ServiceLoader() {};
   virtual void LoadService(ServiceManager* manager,
                            const GURL& url,
                            ScopedShellHandle service_handle) = 0;
+  virtual void OnServiceError(ServiceManager* manager, const GURL& url) = 0;
+
  protected:
   ServiceLoader() {}
 };
diff --git a/mojo/service_manager/service_manager.cc b/mojo/service_manager/service_manager.cc
index b5843cf..8b80825 100644
--- a/mojo/service_manager/service_manager.cc
+++ b/mojo/service_manager/service_manager.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <stdio.h>
+
 #include "mojo/service_manager/service_manager.h"
 
 #include "base/lazy_instance.h"
@@ -14,6 +16,11 @@
 
 namespace mojo {
 
+namespace {
+// Used by TestAPI.
+bool has_created_instance = false;
+}
+
 class ServiceManager::ServiceFactory : public Shell, public ErrorHandler {
  public:
   ServiceFactory(ServiceManager* manager, const GURL& url)
@@ -25,6 +32,7 @@
                                                 url,
                                                 pipe.handle_to_self.Pass());
   }
+
   virtual ~ServiceFactory() {}
 
   void ConnectToClient(ScopedMessagePipeHandle handle) {
@@ -40,7 +48,7 @@
   }
 
   virtual void OnError() OVERRIDE {
-    manager_->RemoveServiceFactory(this);
+    manager_->OnServiceFactoryError(this);
   }
 
   const GURL& url() const { return url_; }
@@ -52,6 +60,11 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceFactory);
 };
 
+// static
+bool ServiceManager::TestAPI::HasCreatedInstance() {
+  return has_created_instance;
+}
+
 bool ServiceManager::TestAPI::HasFactoryForURL(const GURL& url) const {
   return manager_->url_to_service_factory_.find(url) !=
       manager_->url_to_service_factory_.end();
@@ -61,7 +74,7 @@
 }
 
 ServiceManager::~ServiceManager() {
-  for (ServiceFactoryMap::iterator it = url_to_service_factory_.begin();
+  for (URLToServiceFactoryMap::iterator it = url_to_service_factory_.begin();
        it != url_to_service_factory_.end(); ++it) {
     delete it->second;
   }
@@ -69,28 +82,16 @@
 }
 
 // static
-ServiceManager* GetInstance() {
+ServiceManager* ServiceManager::GetInstance() {
   static base::LazyInstance<ServiceManager> instance =
       LAZY_INSTANCE_INITIALIZER;
+  has_created_instance = true;
   return &instance.Get();
 }
 
-void ServiceManager::SetLoaderForURL(ServiceLoader* loader, const GURL& gurl) {
-  DCHECK(url_to_loader_.find(gurl) == url_to_loader_.end());
-  url_to_loader_[gurl] = loader;
-}
-
-ServiceLoader* ServiceManager::GetLoaderForURL(const GURL& gurl) {
-  LoaderMap::const_iterator it = url_to_loader_.find(gurl);
-  if (it != url_to_loader_.end())
-    return it->second;
-  DCHECK(default_loader_);
-  return default_loader_;
-}
-
 void ServiceManager::Connect(const GURL& url,
                              ScopedMessagePipeHandle client_handle) {
-  ServiceFactoryMap::const_iterator service_it =
+  URLToServiceFactoryMap::const_iterator service_it =
       url_to_service_factory_.find(url);
   ServiceFactory* service_factory;
   if (service_it != url_to_service_factory_.end()) {
@@ -102,12 +103,36 @@
   service_factory->ConnectToClient(client_handle.Pass());
 }
 
-void ServiceManager::RemoveServiceFactory(ServiceFactory* service_factory) {
-  ServiceFactoryMap::iterator it =
-      url_to_service_factory_.find(service_factory->url());
+void ServiceManager::SetLoaderForURL(ServiceLoader* loader, const GURL& url) {
+  DCHECK(url_to_loader_.find(url) == url_to_loader_.end());
+  url_to_loader_[url] = loader;
+}
+
+void ServiceManager::SetLoaderForScheme(ServiceLoader* loader,
+                                        const std::string& scheme) {
+  DCHECK(scheme_to_loader_.find(scheme) == scheme_to_loader_.end());
+  scheme_to_loader_[scheme] = loader;
+}
+
+ServiceLoader* ServiceManager::GetLoaderForURL(const GURL& url) {
+  URLToLoaderMap::const_iterator url_it = url_to_loader_.find(url);
+  if (url_it != url_to_loader_.end())
+    return url_it->second;
+  SchemeToLoaderMap::const_iterator scheme_it =
+      scheme_to_loader_.find(url.scheme());
+  if (scheme_it != scheme_to_loader_.end())
+    return scheme_it->second;
+  DCHECK(default_loader_);
+  return default_loader_;
+}
+
+void ServiceManager::OnServiceFactoryError(ServiceFactory* service_factory) {
+  const GURL url = service_factory->url();
+  URLToServiceFactoryMap::iterator it = url_to_service_factory_.find(url);
   DCHECK(it != url_to_service_factory_.end());
   delete it->second;
   url_to_service_factory_.erase(it);
+  GetLoaderForURL(url)->OnServiceError(this, url);
 }
 
 }  // namespace mojo
diff --git a/mojo/service_manager/service_manager.h b/mojo/service_manager/service_manager.h
index c05e177..513c792 100644
--- a/mojo/service_manager/service_manager.h
+++ b/mojo/service_manager/service_manager.h
@@ -9,20 +9,30 @@
 
 #include "base/basictypes.h"
 #include "base/callback.h"
+#include "base/gtest_prod_util.h"
 #include "mojo/public/shell/shell.mojom.h"
+#include "mojo/service_manager/service_manager_export.h"
 #include "url/gurl.h"
 
+namespace content {
+  class MojoTest;
+}
+
 namespace mojo {
 
 class ServiceLoader;
 
-class ServiceManager {
+class MOJO_SERVICE_MANAGER_EXPORT ServiceManager {
  public:
   // API for testing.
-  class TestAPI {
+  class MOJO_SERVICE_MANAGER_EXPORT TestAPI {
    private:
     friend class ServiceManagerTest;
+    friend class content::MojoTest;
+
     explicit TestAPI(ServiceManager* manager) : manager_(manager) {}
+    // Returns true if the shared instance has been created.
+    static bool HasCreatedInstance();
     // Returns true if there is a ServiceFactory for this URL.
     bool HasFactoryForURL(const GURL& url) const;
 
@@ -35,28 +45,40 @@
   // Returns a shared instance, creating it if necessary.
   static ServiceManager* GetInstance();
 
-  // Sets the default Loader to be used if not overridden by SetLoaderForURL().
+  // Loads a service if necessary and establishes a new client connection.
+  void Connect(const GURL& url, ScopedMessagePipeHandle client_handle);
+
+  // Sets the default Loader to be used if not overridden by
+  // SetLoaderForURL() or SetLoaderForScheme().
   // Does not take ownership of |loader|.
   void set_default_loader(ServiceLoader* loader) { default_loader_ = loader; }
   // Sets a Loader to be used for a specific url.
   // Does not take ownership of |loader|.
-  void SetLoaderForURL(ServiceLoader* loader, const GURL& gurl);
-  // Returns the Loader to use for a url (using default if not overridden.)
-  ServiceLoader* GetLoaderForURL(const GURL& gurl);
-  // Loads a service if necessary and establishes a new client connection.
-  void Connect(const GURL& url, ScopedMessagePipeHandle client_handle);
+  void SetLoaderForURL(ServiceLoader* loader, const GURL& url);
+  // Sets a Loader to be used for a specific url scheme.
+  // Does not take ownership of |loader|.
+  void SetLoaderForScheme(ServiceLoader* loader, const std::string& scheme);
 
  private:
   class ServiceFactory;
+  typedef std::map<std::string, ServiceLoader*> SchemeToLoaderMap;
+  typedef std::map<GURL, ServiceLoader*> URLToLoaderMap;
+  typedef std::map<GURL, ServiceFactory*> URLToServiceFactoryMap;
+
+  // Returns the Loader to use for a url (using default if not overridden.)
+  // The preference is to use a loader that's been specified for an url first,
+  // then one that's been specified for a scheme, then the default.
+  ServiceLoader* GetLoaderForURL(const GURL& url);
 
   // Removes a ServiceFactory when it no longer has any connections.
-  void RemoveServiceFactory(ServiceFactory* service_factory);
+  void OnServiceFactoryError(ServiceFactory* service_factory);
 
+  // Loader management.
+  URLToLoaderMap url_to_loader_;
+  SchemeToLoaderMap scheme_to_loader_;
   ServiceLoader* default_loader_;
-  typedef std::map<GURL, ServiceFactory*> ServiceFactoryMap;
-  ServiceFactoryMap url_to_service_factory_;
-  typedef std::map<GURL, ServiceLoader*> LoaderMap;
-  LoaderMap url_to_loader_;
+
+  URLToServiceFactoryMap url_to_service_factory_;
   DISALLOW_COPY_AND_ASSIGN(ServiceManager);
 };
 
diff --git a/mojo/service_manager/service_manager_export.h b/mojo/service_manager/service_manager_export.h
new file mode 100644
index 0000000..251aad9
--- /dev/null
+++ b/mojo/service_manager/service_manager_export.h
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SERVICE_MANAGER_SERVICE_MANAGER_EXPORT_H_
+#define MOJO_SERVICE_MANAGER_SERVICE_MANAGER_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WIN32)
+
+#if defined(MOJO_SERVICE_MANAGER_IMPLEMENTATION)
+#define MOJO_SERVICE_MANAGER_EXPORT __declspec(dllexport)
+#else
+#define MOJO_SERVICE_MANAGER_EXPORT __declspec(dllimport)
+#endif
+
+#else  // !defined(WIN32)
+
+#if defined(MOJO_SERVICE_MANAGER_IMPLEMENTATION)
+#define MOJO_SERVICE_MANAGER_EXPORT __attribute__((visibility("default")))
+#else
+#define MOJO_SERVICE_MANAGER_EXPORT
+#endif
+
+#endif  // defined(WIN32)
+
+#else  // !defined(COMPONENT_BUILD)
+#define MOJO_SERVICE_MANAGER_EXPORT
+#endif
+
+#endif  // MOJO_SERVICE_MANAGER_SERVICE_MANAGER_EXPORT_H_
diff --git a/mojo/service_manager/service_manager_unittest.cc b/mojo/service_manager/service_manager_unittest.cc
index 6941be6..18ee25f 100644
--- a/mojo/service_manager/service_manager_unittest.cc
+++ b/mojo/service_manager/service_manager_unittest.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "mojo/public/bindings/allocation_scope.h"
 #include "mojo/public/bindings/remote_ptr.h"
-#include "mojo/public/environment/environment.h"
+#include "mojo/public/cpp/environment/environment.h"
 #include "mojo/public/shell/application.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/utility/run_loop.h"
 #include "mojo/service_manager/service_loader.h"
 #include "mojo/service_manager/service_manager.h"
 #include "mojo/service_manager/test.mojom.h"
@@ -57,7 +57,7 @@
 
   virtual void AckTest() OVERRIDE {
     if (quit_after_ack_)
-      mojo::RunLoop::current()->Quit();
+      base::MessageLoop::current()->Quit();
   }
 
   void Test(std::string test_string) {
@@ -103,6 +103,12 @@
         new ServiceFactory<TestServiceImpl, TestContext>(&context_));
   }
 
+  virtual void OnServiceError(ServiceManager* manager,
+                              const GURL& url) OVERRIDE {
+    base::MessageLoop::current()->PostTask(FROM_HERE,
+                                           base::MessageLoop::QuitClosure());
+  }
+
   bool HasFactoryForTestURL() {
     ServiceManager::TestAPI manager_test_api(service_manager_.get());
     return manager_test_api.HasFactoryForURL(GURL(kTestURLString));
@@ -110,7 +116,7 @@
 
  protected:
   mojo::Environment env_;
-  mojo::RunLoop loop_;
+  base::MessageLoop loop_;
   TestContext context_;
   scoped_ptr<Application> test_app_;
   scoped_ptr<TestClientImpl> test_client_;
@@ -118,6 +124,24 @@
   DISALLOW_COPY_AND_ASSIGN(ServiceManagerTest);
 };
 
+class TestServiceLoader : public ServiceLoader {
+ public:
+  TestServiceLoader() : num_loads_(0) {}
+  int num_loads() const { return num_loads_; }
+
+ private:
+  virtual void LoadService(ServiceManager* manager,
+                           const GURL& url,
+                           ScopedShellHandle service_handle) OVERRIDE {
+    ++num_loads_;
+  }
+  virtual void OnServiceError(ServiceManager* manager, const GURL& url)
+      OVERRIDE {}
+
+  int num_loads_;
+  DISALLOW_COPY_AND_ASSIGN(TestServiceLoader);
+};
+
 TEST_F(ServiceManagerTest, Basic) {
   test_client_->Test("test");
   loop_.Run();
@@ -134,4 +158,37 @@
   EXPECT_EQ(0, context_.num_impls);
   EXPECT_FALSE(HasFactoryForTestURL());
 }
+
+// Confirm that both urls and schemes can have their loaders explicitly set.
+TEST_F(ServiceManagerTest, SetLoaders) {
+  ServiceManager sm;
+  TestServiceLoader default_loader;
+  TestServiceLoader url_loader;
+  TestServiceLoader scheme_loader;
+  sm.set_default_loader(&default_loader);
+  sm.SetLoaderForURL(&url_loader, GURL("test:test1"));
+  sm.SetLoaderForScheme(&scheme_loader, "test");
+
+  // test::test1 should go to url_loader.
+  InterfacePipe<TestService, AnyInterface> pipe1;
+  sm.Connect(GURL("test:test1"), pipe1.handle_to_peer.Pass());
+  EXPECT_EQ(1, url_loader.num_loads());
+  EXPECT_EQ(0, scheme_loader.num_loads());
+  EXPECT_EQ(0, default_loader.num_loads());
+
+  // test::test2 should go to scheme loader.
+  InterfacePipe<TestService, AnyInterface> pipe2;
+  sm.Connect(GURL("test:test2"), pipe2.handle_to_peer.Pass());
+  EXPECT_EQ(1, url_loader.num_loads());
+  EXPECT_EQ(1, scheme_loader.num_loads());
+  EXPECT_EQ(0, default_loader.num_loads());
+
+  // http::test1 should go to default loader.
+  InterfacePipe<TestService, AnyInterface> pipe3;
+  sm.Connect(GURL("http:test1"), pipe3.handle_to_peer.Pass());
+  EXPECT_EQ(1, url_loader.num_loads());
+  EXPECT_EQ(1, scheme_loader.num_loads());
+  EXPECT_EQ(1, default_loader.num_loads());
+}
+
 }  // namespace mojo
diff --git a/mojo/services/gles2/command_buffer_impl.cc b/mojo/services/gles2/command_buffer_impl.cc
index 7a897ff..3fb9881 100644
--- a/mojo/services/gles2/command_buffer_impl.cc
+++ b/mojo/services/gles2/command_buffer_impl.cc
@@ -57,7 +57,7 @@
 void CommandBufferImpl::Initialize(
     ScopedCommandBufferSyncClientHandle sync_client,
     const ShmHandle& shared_state) {
-  sync_client_.reset(sync_client.Pass());
+  sync_client_.reset(sync_client.Pass(), NULL);
   sync_client_->DidInitialize(DoInitialize(shared_state));
 }
 
@@ -143,9 +143,16 @@
 void CommandBufferImpl::RegisterTransferBuffer(int32_t id,
                                                const ShmHandle& transfer_buffer,
                                                uint32_t size) {
-  bool read_only = false;
-  base::SharedMemory shared_memory(transfer_buffer, read_only);
-  command_buffer_->RegisterTransferBuffer(id, &shared_memory, size);
+  // Take ownership of the memory and map it into this process.
+  // This validates the size.
+  scoped_ptr<base::SharedMemory> shared_memory(
+      new base::SharedMemory(transfer_buffer, false));
+  if (!shared_memory->Map(size)) {
+    DVLOG(0) << "Failed to map shared memory.";
+    return;
+  }
+
+  command_buffer_->RegisterTransferBuffer(id, shared_memory.Pass(), size);
 }
 
 void CommandBufferImpl::DestroyTransferBuffer(int32_t id) {
diff --git a/mojo/services/gles2/command_buffer_impl.h b/mojo/services/gles2/command_buffer_impl.h
index fd3a0fa..bb17f8e 100644
--- a/mojo/services/gles2/command_buffer_impl.h
+++ b/mojo/services/gles2/command_buffer_impl.h
@@ -8,7 +8,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/timer/timer.h"
 #include "mojo/public/bindings/remote_ptr.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/services/gles2/command_buffer.mojom.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/size.h"
diff --git a/mojo/shell/android/apk/src/org/chromium/mojo_shell_apk/MojoShellActivity.java b/mojo/shell/android/apk/src/org/chromium/mojo_shell_apk/MojoShellActivity.java
index 15a5861..c697f5e 100644
--- a/mojo/shell/android/apk/src/org/chromium/mojo_shell_apk/MojoShellActivity.java
+++ b/mojo/shell/android/apk/src/org/chromium/mojo_shell_apk/MojoShellActivity.java
@@ -26,7 +26,7 @@
         super.onCreate(savedInstanceState);
 
         try {
-            LibraryLoader.ensureInitialized();
+            LibraryLoader.ensureInitialized(null);
         } catch (ProcessInitException e) {
             Log.e(TAG, "libmojo_shell initialization failed.", e);
             finish();
diff --git a/mojo/shell/android/mojo_main.cc b/mojo/shell/android/mojo_main.cc
index 8419d30..a6eb580 100644
--- a/mojo/shell/android/mojo_main.cc
+++ b/mojo/shell/android/mojo_main.cc
@@ -46,6 +46,11 @@
     app_.reset(CreateNativeViewportService(g_context.Get().get(),
                                            service_handle.Pass()));
   }
+
+  virtual void OnServiceError(ServiceManager* manager,
+                              const GURL& url) OVERRIDE {
+  }
+
   scoped_ptr<Application> app_;
 };
 
diff --git a/mojo/shell/app_child_process.cc b/mojo/shell/app_child_process.cc
index 3d07789..5e2e9b7 100644
--- a/mojo/shell/app_child_process.cc
+++ b/mojo/shell/app_child_process.cc
@@ -5,18 +5,23 @@
 #include "mojo/shell/app_child_process.h"
 
 #include "base/bind.h"
+#include "base/callback_helpers.h"
+#include "base/file_util.h"
+#include "base/files/file_path.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop/message_loop.h"
+#include "base/scoped_native_library.h"
 #include "base/single_thread_task_runner.h"
+#include "base/synchronization/waitable_event.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
 #include "mojo/common/message_pump_mojo.h"
 #include "mojo/embedder/embedder.h"
 #include "mojo/public/bindings/remote_ptr.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/shell/app_child_process.mojom.h"
 
 namespace mojo {
@@ -24,10 +29,59 @@
 
 namespace {
 
-class AppChildControllerImpl;
+// Blocker ---------------------------------------------------------------------
+
+// Blocks a thread until another thread unblocks it, at which point it unblocks
+// and runs a closure provided by that thread.
+class Blocker {
+ public:
+  class Unblocker {
+   public:
+    ~Unblocker() {}
+
+    void Unblock(base::Closure run_after) {
+      DCHECK(blocker_);
+      DCHECK(blocker_->run_after_.is_null());
+      blocker_->run_after_ = run_after;
+      blocker_->event_.Signal();
+      blocker_ = NULL;
+    }
+
+   private:
+    friend class Blocker;
+    Unblocker(Blocker* blocker) : blocker_(blocker) {
+      DCHECK(blocker_);
+    }
+
+    Blocker* blocker_;
+
+    // Copy and assign allowed.
+  };
+
+  Blocker() : event_(true, false) {}
+  ~Blocker() {}
+
+  void Block() {
+    DCHECK(run_after_.is_null());
+    event_.Wait();
+    run_after_.Run();
+  }
+
+  Unblocker GetUnblocker() {
+    return Unblocker(this);
+  }
+
+ private:
+  base::WaitableEvent event_;
+  base::Closure run_after_;
+
+  DISALLOW_COPY_AND_ASSIGN(Blocker);
+};
 
 // AppContext ------------------------------------------------------------------
 
+class AppChildControllerImpl;
+
 // Should be created and initialized on the main thread.
 class AppContext {
  public:
@@ -74,15 +128,18 @@
   }
 
  private:
+  // Accessed only on the controller thread.
+  // IMPORTANT: This must be BEFORE |controller_thread_|, so that the controller
+  // thread gets joined (and thus |controller_| reset) before |controller_| is
+  // destroyed.
+  scoped_ptr<AppChildControllerImpl> controller_;
+
   base::Thread io_thread_;
   scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
 
   base::Thread controller_thread_;
   scoped_refptr<base::SingleThreadTaskRunner> controller_runner_;
 
-  // Accessed only on the controller thread.
-  scoped_ptr<AppChildControllerImpl> controller_;
-
   DISALLOW_COPY_AND_ASSIGN(AppContext);
 };
 
@@ -99,17 +156,27 @@
   static void Init(
       AppContext* app_context,
       embedder::ScopedPlatformHandle platform_channel,
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner) {
+      const Blocker::Unblocker& unblocker) {
     DCHECK(app_context);
     DCHECK(platform_channel.is_valid());
-    DCHECK(main_thread_runner);
 
     DCHECK(!app_context->controller());
     app_context->set_controller(
-        make_scoped_ptr(new AppChildControllerImpl(app_context)));
-    app_context->controller()->CreateChannel(platform_channel.Pass(),
-                                             main_thread_runner);
+        make_scoped_ptr(new AppChildControllerImpl(app_context, unblocker)));
+    app_context->controller()->CreateChannel(platform_channel.Pass());
+  }
 
+  void Shutdown() {
+    DVLOG(2) << "AppChildControllerImpl::Shutdown()";
+    DCHECK(thread_checker_.CalledOnValidThread());
+
+    // TODO(vtl): Pass in the result from |MainMain()|.
+    controller_client_->AppCompleted(MOJO_RESULT_UNIMPLEMENTED);
+
+    // TODO(vtl): Drain then destroy the channel (on the I/O thread).
+
+    // This will destroy this object.
+    app_context_->set_controller(scoped_ptr<AppChildControllerImpl>());
   }
 
   // |AppChildController| method:
@@ -117,19 +184,23 @@
                         ScopedMessagePipeHandle service) OVERRIDE {
     DVLOG(2) << "AppChildControllerImpl::StartApp("
              << app_path.To<std::string>() << ", ...)";
+    DCHECK(thread_checker_.CalledOnValidThread());
 
-    // TODO(vtl): Load/run app.
+    unblocker_.Unblock(base::Bind(&AppChildControllerImpl::StartAppOnMainThread,
+                                  base::FilePath::FromUTF8Unsafe(
+                                      app_path.To<std::string>()),
+                                  base::Passed(&service)));
   }
 
  private:
-  AppChildControllerImpl(AppContext* app_context)
+  AppChildControllerImpl(AppContext* app_context,
+                         const Blocker::Unblocker& unblocker)
       : app_context_(app_context),
+        unblocker_(unblocker),
         channel_info_(NULL) {
   }
 
-  void CreateChannel(
-      embedder::ScopedPlatformHandle platform_channel,
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner) {
+  void CreateChannel(embedder::ScopedPlatformHandle platform_channel) {
     DVLOG(2) << "AppChildControllerImpl::CreateChannel()";
     DCHECK(thread_checker_.CalledOnValidThread());
 
@@ -137,7 +208,7 @@
         platform_channel.Pass(),
         app_context_->io_runner(),
         base::Bind(&AppChildControllerImpl::DidCreateChannel,
-                   base::Unretained(this), main_thread_runner),
+                   base::Unretained(this)),
         base::MessageLoopProxy::current()));
     controller_client_.reset(
         mojo_shell::ScopedAppChildControllerClientHandle(
@@ -146,16 +217,50 @@
   }
 
   // Callback for |embedder::CreateChannel()|.
-  void DidCreateChannel(
-      scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
-      embedder::ChannelInfo* channel_info) {
+  void DidCreateChannel(embedder::ChannelInfo* channel_info) {
     DVLOG(2) << "AppChildControllerImpl::DidCreateChannel()";
     DCHECK(thread_checker_.CalledOnValidThread());
     channel_info_ = channel_info;
   }
 
+  static void StartAppOnMainThread(const base::FilePath& app_path,
+                                   ScopedMessagePipeHandle service) {
+    // TODO(vtl): This is copied from in_process_dynamic_service_runner.cc.
+    DVLOG(2) << "Loading/running Mojo app from " << app_path.value()
+             << " out of process";
+
+    base::ScopedClosureRunner app_deleter(
+        base::Bind(base::IgnoreResult(&base::DeleteFile), app_path, false));
+
+    do {
+      base::NativeLibraryLoadError load_error;
+      base::ScopedNativeLibrary app_library(
+          base::LoadNativeLibrary(app_path, &load_error));
+      if (!app_library.is_valid()) {
+        LOG(ERROR) << "Failed to load library (error: " << load_error.ToString()
+                   << ")";
+        break;
+      }
+
+      typedef MojoResult (*MojoMainFunction)(MojoHandle);
+      MojoMainFunction main_function = reinterpret_cast<MojoMainFunction>(
+          app_library.GetFunctionPointer("MojoMain"));
+      if (!main_function) {
+        LOG(ERROR) << "Entrypoint MojoMain not found";
+        break;
+      }
+
+      // TODO(vtl): Report the result back to our parent process.
+      // |MojoMain()| takes ownership of the service handle.
+      MojoResult result = main_function(service.release().value());
+      if (result < MOJO_RESULT_OK)
+        LOG(ERROR) << "MojoMain returned an error: " << result;
+    } while (false);
+  }
+
   base::ThreadChecker thread_checker_;
   AppContext* const app_context_;
+  Blocker::Unblocker unblocker_;
 
   RemotePtr<mojo_shell::AppChildControllerClient> controller_client_;
   embedder::ChannelInfo* channel_info_;
@@ -179,21 +284,18 @@
   AppContext app_context;
   app_context.Init();
 
-  {
-    base::MessageLoop message_loop;
+  Blocker blocker;
+  app_context.controller_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&AppChildControllerImpl::Init, base::Unretained(&app_context),
+                 base::Passed(platform_channel()), blocker.GetUnblocker()));
+  // This will block, then run whatever the controller wants.
+  blocker.Block();
 
-    app_context.controller_runner()->PostTask(
-        FROM_HERE,
-        base::Bind(&AppChildControllerImpl::Init,
-                   base::Unretained(&app_context),
-                   base::Passed(platform_channel()),
-                   scoped_refptr<base::SingleThreadTaskRunner>(
-                       message_loop.message_loop_proxy())));
-
-    // Eventually, we'll get a task posted telling us to quit this message loop,
-    // which will also tell us what to do afterwards (e.g., run |MojoMain()|).
-    message_loop.Run();
-  }
+  app_context.controller_runner()->PostTask(
+      FROM_HERE,
+      base::Bind(&AppChildControllerImpl::Shutdown,
+      base::Unretained(app_context.controller())));
 }
 
 }  // namespace shell
diff --git a/mojo/shell/app_child_process.h b/mojo/shell/app_child_process.h
index 6665612..b5b1eb6 100644
--- a/mojo/shell/app_child_process.h
+++ b/mojo/shell/app_child_process.h
@@ -11,6 +11,8 @@
 namespace mojo {
 namespace shell {
 
+// An implementation of |ChildProcess| for a |TYPE_APP| child process, which
+// runs a single app (loaded from the file system) on its main thread.
 class AppChildProcess : public ChildProcess {
  public:
   AppChildProcess();
diff --git a/mojo/shell/app_child_process_host.cc b/mojo/shell/app_child_process_host.cc
index 42e5d82..d35da8e 100644
--- a/mojo/shell/app_child_process_host.cc
+++ b/mojo/shell/app_child_process_host.cc
@@ -7,7 +7,7 @@
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "mojo/embedder/embedder.h"
-#include "mojo/public/system/core_cpp.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/shell/context.h"
 #include "mojo/shell/task_runners.h"
 
diff --git a/mojo/shell/app_child_process_host.h b/mojo/shell/app_child_process_host.h
index 263b408..8ecc6e9 100644
--- a/mojo/shell/app_child_process_host.h
+++ b/mojo/shell/app_child_process_host.h
@@ -18,6 +18,9 @@
 
 namespace shell {
 
+// A subclass of |ChildProcessHost| to host a |TYPE_APP| child process, which
+// runs a single app (loaded from the file system).
+//
 // Note: After |Start()|, this object must remain alive until the controller
 // client's |AppCompleted()| is called.
 class AppChildProcessHost : public ChildProcessHost,
diff --git a/mojo/shell/child_process.h b/mojo/shell/child_process.h
index 8e4d4c6..d794a4e 100644
--- a/mojo/shell/child_process.h
+++ b/mojo/shell/child_process.h
@@ -21,7 +21,6 @@
 class ChildProcess {
  public:
   enum Type {
-    // TODO(vtl): Add real types here.
     TYPE_TEST,
     // Hosts a single app (see app_child_process(_host).*).
     TYPE_APP
diff --git a/mojo/shell/context.h b/mojo/shell/context.h
index d988ae0..3034eb7 100644
--- a/mojo/shell/context.h
+++ b/mojo/shell/context.h
@@ -20,6 +20,7 @@
 
 class DynamicServiceLoader;
 
+// The "global" context for the shell's main process.
 class Context {
  public:
   Context();
diff --git a/mojo/shell/dynamic_service_loader.cc b/mojo/shell/dynamic_service_loader.cc
index bea1496..da87453 100644
--- a/mojo/shell/dynamic_service_loader.cc
+++ b/mojo/shell/dynamic_service_loader.cc
@@ -105,6 +105,10 @@
       this, url, service_handle.Pass(), runner_factory_->Create(context_));
 }
 
+void DynamicServiceLoader::OnServiceError(ServiceManager* manager,
+                                          const GURL& url) {
+}
+
 void DynamicServiceLoader::AppCompleted(const GURL& url) {
   DCHECK(context_->task_runners()->ui_runner()->BelongsToCurrentThread());
   DVLOG(2) << "App completed (url: " << url << ")";
diff --git a/mojo/shell/dynamic_service_loader.h b/mojo/shell/dynamic_service_loader.h
index a954ba5..6b8e7dc 100644
--- a/mojo/shell/dynamic_service_loader.h
+++ b/mojo/shell/dynamic_service_loader.h
@@ -7,9 +7,9 @@
 
 #include <map>
 
-#include "base/basictypes.h"
+#include "base/macros.h"
+#include "mojo/public/cpp/system/core.h"
 #include "mojo/public/shell/shell.mojom.h"
-#include "mojo/public/system/core_cpp.h"
 #include "mojo/service_manager/service_loader.h"
 #include "mojo/shell/dynamic_service_runner.h"
 #include "mojo/shell/keep_alive.h"
@@ -21,21 +21,24 @@
 class Context;
 class DynamicServiceRunnerFactory;
 
-// A subclass of ServiceManager::Loader that loads a dynamic library containing
-// the implementation of the service.
+// An implementation of ServiceLoader that retrieves a dynamic library
+// containing the implementation of the service and loads/runs it (via a
+// DynamicServiceRunner).
 class DynamicServiceLoader : public ServiceLoader {
  public:
   DynamicServiceLoader(Context* context,
                        scoped_ptr<DynamicServiceRunnerFactory> runner_factory);
   virtual ~DynamicServiceLoader();
 
-  // Initiates the dynamic load. If the url is a mojo: scheme then the name
-  // specified will be modified to the platform's naming scheme. Also the
+  // Initiates the dynamic load. If the URL has a mojo: scheme, then the name
+  // specified will be modified to the platform's naming scheme. Also, the
   // value specified to the --origin command line argument will be used as the
-  // host / port.
+  // host/port.
   virtual void LoadService(ServiceManager* manager,
                            const GURL& url,
                            ScopedShellHandle service_handle) OVERRIDE;
+  virtual void OnServiceError(ServiceManager* manager, const GURL& url)
+      OVERRIDE;
 
  private:
   class LoadContext;
diff --git a/mojo/shell/dynamic_service_runner.h b/mojo/shell/dynamic_service_runner.h
index 00a92a5..0319531 100644
--- a/mojo/shell/dynamic_service_runner.h
+++ b/mojo/shell/dynamic_service_runner.h
@@ -19,6 +19,8 @@
 
 class Context;
 
+// Abstraction for loading a service (from the file system) and running it (on
+// another thread or in a separate process).
 class DynamicServiceRunner {
  public:
   virtual ~DynamicServiceRunner() {}
diff --git a/mojo/shell/in_process_dynamic_service_runner.cc b/mojo/shell/in_process_dynamic_service_runner.cc
index 62ca5e3..9030d59 100644
--- a/mojo/shell/in_process_dynamic_service_runner.cc
+++ b/mojo/shell/in_process_dynamic_service_runner.cc
@@ -54,11 +54,12 @@
       base::Bind(base::IgnoreResult(&base::DeleteFile), app_path_, false));
 
   do {
-    std::string load_error;
+    base::NativeLibraryLoadError error;
     base::ScopedNativeLibrary app_library(
-        base::LoadNativeLibrary(app_path_, &load_error));
+        base::LoadNativeLibrary(app_path_, &error));
     if (!app_library.is_valid()) {
-      LOG(ERROR) << "Failed to load library (error: " << load_error << ")";
+      LOG(ERROR) << "Failed to load library (error: " << error.ToString()
+                 << ")";
       break;
     }
 
diff --git a/mojo/shell/in_process_dynamic_service_runner.h b/mojo/shell/in_process_dynamic_service_runner.h
index e95eeb5..95cebb1 100644
--- a/mojo/shell/in_process_dynamic_service_runner.h
+++ b/mojo/shell/in_process_dynamic_service_runner.h
@@ -14,6 +14,8 @@
 namespace mojo {
 namespace shell {
 
+// An implementation of |DynamicServiceRunner| that loads/runs the given app
+// (from the file system) on a separate thread (in the current process).
 class InProcessDynamicServiceRunner
     : public DynamicServiceRunner,
       public base::DelegateSimpleThread::Delegate {
diff --git a/mojo/shell/init.h b/mojo/shell/init.h
index 52e6fae..c83134a 100644
--- a/mojo/shell/init.h
+++ b/mojo/shell/init.h
@@ -8,7 +8,7 @@
 namespace mojo {
 namespace shell {
 
-// Initialization routines shared by desktop and android main functions.
+// Initialization routines shared by desktop and Android main functions.
 
 void InitializeLogging();
 
diff --git a/mojo/shell/out_of_process_dynamic_service_runner.h b/mojo/shell/out_of_process_dynamic_service_runner.h
index 073cc0a..bee4e19 100644
--- a/mojo/shell/out_of_process_dynamic_service_runner.h
+++ b/mojo/shell/out_of_process_dynamic_service_runner.h
@@ -15,6 +15,8 @@
 namespace mojo {
 namespace shell {
 
+// An implementation of |DynamicServiceRunner| that loads/runs the given app
+// (from the file system) in a separate process (of its own).
 class OutOfProcessDynamicServiceRunner
     : public DynamicServiceRunner,
       public mojo_shell::AppChildControllerClient {
diff --git a/mojo/shell/storage.h b/mojo/shell/storage.h
index 08c1ea2..ac9d578 100644
--- a/mojo/shell/storage.h
+++ b/mojo/shell/storage.h
@@ -10,7 +10,7 @@
 namespace mojo {
 namespace shell {
 
-// A object that represents the persistent storage used by the shell.
+// An object that represents the persistent storage used by the shell.
 class Storage {
  public:
   Storage();
diff --git a/mojo/shell/task_runners.h b/mojo/shell/task_runners.h
index a6b59b4..17cdf89 100644
--- a/mojo/shell/task_runners.h
+++ b/mojo/shell/task_runners.h
@@ -18,7 +18,8 @@
 namespace mojo {
 namespace shell {
 
-// A context object that contains the common task runners for the shell
+// A context object that contains the common task runners for the shell's main
+// process.
 class TaskRunners {
  public:
   explicit TaskRunners(base::SingleThreadTaskRunner* ui_runner);
diff --git a/mojo/system/channel.cc b/mojo/system/channel.cc
index e668c87..d7a720e 100644
--- a/mojo/system/channel.cc
+++ b/mojo/system/channel.cc
@@ -149,6 +149,12 @@
   return raw_channel_->WriteMessage(message.Pass());
 }
 
+bool Channel::IsWriteBufferEmpty() {
+  base::AutoLock locker(lock_);
+  DCHECK(raw_channel_.get());
+  return raw_channel_->IsWriteBufferEmpty();
+}
+
 void Channel::DetachMessagePipeEndpoint(MessageInTransit::EndpointId local_id) {
   DCHECK_NE(local_id, MessageInTransit::kInvalidEndpointId);
 
@@ -166,6 +172,10 @@
 }
 
 void Channel::OnReadMessage(const MessageInTransit::View& message_view) {
+  // Note: |ValidateReadMessage()| will call |HandleRemoteError()| if necessary.
+  if (!ValidateReadMessage(message_view))
+    return;
+
   switch (message_view.type()) {
     case MessageInTransit::kTypeMessagePipeEndpoint:
     case MessageInTransit::kTypeMessagePipe:
@@ -187,6 +197,17 @@
   NOTIMPLEMENTED();
 }
 
+bool Channel::ValidateReadMessage(const MessageInTransit::View& message_view) {
+  const char* error_message = NULL;
+  if (!message_view.IsValid(&error_message)) {
+    DCHECK(error_message);
+    HandleRemoteError(error_message);
+    return false;
+  }
+
+  return true;
+}
+
 void Channel::OnReadMessageForDownstream(
     const MessageInTransit::View& message_view) {
   DCHECK(message_view.type() == MessageInTransit::kTypeMessagePipeEndpoint ||
@@ -260,7 +281,8 @@
 }
 
 void Channel::HandleRemoteError(const base::StringPiece& error_message) {
-  // TODO(vtl): Is this how we really want to handle this?
+  // TODO(vtl): Is this how we really want to handle this? Probably we want to
+  // terminate the connection, since it's spewing invalid stuff.
   LOG(WARNING) << error_message;
 }
 
diff --git a/mojo/system/channel.h b/mojo/system/channel.h
index 96c1f8c..4af6daa 100644
--- a/mojo/system/channel.h
+++ b/mojo/system/channel.h
@@ -16,7 +16,7 @@
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
 #include "mojo/embedder/scoped_platform_handle.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/message_in_transit.h"
 #include "mojo/system/message_pipe.h"
 #include "mojo/system/raw_channel.h"
@@ -92,6 +92,11 @@
   // This forwards |message| verbatim to |raw_channel_|.
   bool WriteMessage(scoped_ptr<MessageInTransit> message);
 
+  // See |RawChannel::IsWriteBufferEmpty()|.
+  // TODO(vtl): Maybe we shouldn't expose this, and instead have a
+  // |FlushWriteBufferAndShutdown()| or something like that.
+  bool IsWriteBufferEmpty();
+
   // This removes the message pipe/port's endpoint (with the given local ID,
   // returned by |AttachMessagePipeEndpoint()| from this channel. After this is
   // called, |local_id| may be reused for another message pipe.
@@ -107,6 +112,7 @@
   virtual void OnFatalError(FatalError fatal_error) OVERRIDE;
 
   // Helpers for |OnReadMessage|:
+  bool ValidateReadMessage(const MessageInTransit::View& message_view);
   void OnReadMessageForDownstream(const MessageInTransit::View& message_view);
   void OnReadMessageForChannel(const MessageInTransit::View& message_view);
 
diff --git a/mojo/system/constants.h b/mojo/system/constants.h
index 69a0759..6c287b5 100644
--- a/mojo/system/constants.h
+++ b/mojo/system/constants.h
@@ -34,6 +34,11 @@
 // alignment of elements will depend on this and the element size.)
 const size_t kDataPipeBufferAlignmentBytes = 16;
 
+// TODO(vtl): Set this hard limit appropriately (e.g., higher on 64-bit). (This
+// will also entail some auditing to make sure I'm not messing up my checks
+// anywhere.)
+const size_t kMaxSharedMemoryNumBytes = 1024 * 1024 * 1024;  // 1 GB.
+
 }  // namespace system
 }  // namespace mojo
 
diff --git a/mojo/system/core_impl.cc b/mojo/system/core_impl.cc
index 385c173..ea1ebda 100644
--- a/mojo/system/core_impl.cc
+++ b/mojo/system/core_impl.cc
@@ -17,6 +17,8 @@
 #include "mojo/system/memory.h"
 #include "mojo/system/message_pipe.h"
 #include "mojo/system/message_pipe_dispatcher.h"
+#include "mojo/system/raw_shared_buffer.h"
+#include "mojo/system/shared_buffer_dispatcher.h"
 #include "mojo/system/waiter.h"
 
 namespace mojo {
@@ -507,9 +509,44 @@
     const MojoCreateSharedBufferOptions* options,
     uint64_t num_bytes,
     MojoHandle* shared_buffer_handle) {
-  // TODO(vtl)
-  NOTIMPLEMENTED();
-  return MOJO_RESULT_UNIMPLEMENTED;
+  if (options) {
+    // The |struct_size| field must be valid to read.
+    if (!VerifyUserPointer<uint32_t>(&options->struct_size, 1))
+      return MOJO_RESULT_INVALID_ARGUMENT;
+    // And then |options| must point to at least |options->struct_size| bytes.
+    if (!VerifyUserPointer<void>(options, options->struct_size))
+      return MOJO_RESULT_INVALID_ARGUMENT;
+  }
+  if (!VerifyUserPointer<MojoHandle>(shared_buffer_handle, 1))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  MojoCreateSharedBufferOptions validated_options = { 0 };
+  MojoResult result =
+      SharedBufferDispatcher::ValidateOptions(options, &validated_options);
+  if (result != MOJO_RESULT_OK)
+    return result;
+
+  scoped_refptr<SharedBufferDispatcher> dispatcher;
+  result = SharedBufferDispatcher::Create(validated_options, num_bytes,
+                                          &dispatcher);
+  if (result != MOJO_RESULT_OK) {
+    DCHECK(!dispatcher);
+    return result;
+  }
+
+  MojoHandle h;
+  {
+    base::AutoLock locker(handle_table_lock_);
+
+    // TODO(vtl): crbug.com/345911: On failure, we should close the dispatcher
+    // (outside the table lock).
+    h = AddDispatcherNoLock(dispatcher);
+    if (h == MOJO_HANDLE_INVALID)
+      return MOJO_RESULT_RESOURCE_EXHAUSTED;
+  }
+
+  *shared_buffer_handle = h;
+  return MOJO_RESULT_OK;
 }
 
 MojoResult CoreImpl::DuplicateBufferHandle(
@@ -520,6 +557,7 @@
   if (!dispatcher.get())
     return MOJO_RESULT_INVALID_ARGUMENT;
 
+  // Don't verify |options| here; that's the dispatcher's job.
   if (!VerifyUserPointer<MojoHandle>(new_buffer_handle, 1))
     return MOJO_RESULT_INVALID_ARGUMENT;
 
@@ -553,17 +591,26 @@
   if (!dispatcher.get())
     return MOJO_RESULT_INVALID_ARGUMENT;
 
-  MojoResult result = dispatcher->MapBuffer(offset, num_bytes, buffer, flags);
+  if (!VerifyUserPointer<void*>(buffer, 1))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  scoped_ptr<RawSharedBuffer::Mapping> mapping;
+  MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping);
   if (result != MOJO_RESULT_OK)
     return result;
 
-  // TODO(vtl): Record the mapping.
+  DCHECK(mapping);
+  *buffer = mapping->base();
+
+  // TODO(vtl): FIXME -- Record the mapping somewhere, so that it can be
+  // unmapped properly. For now, just leak it.
+  ignore_result(mapping.release());
 
   return MOJO_RESULT_OK;
 }
 
 MojoResult CoreImpl::UnmapBuffer(void* buffer) {
-  // TODO(vtl)
+  // TODO(vtl): FIXME
   NOTIMPLEMENTED();
   return MOJO_RESULT_UNIMPLEMENTED;
 }
diff --git a/mojo/system/core_test_base.cc b/mojo/system/core_test_base.cc
index 40af0e0..89b8fb3 100644
--- a/mojo/system/core_test_base.cc
+++ b/mojo/system/core_test_base.cc
@@ -30,17 +30,17 @@
     info_->IncrementCtorCallCount();
   }
 
+  // |Dispatcher| private methods:
   virtual Type GetType() const OVERRIDE {
     return kTypeUnknown;
   }
 
  private:
-  friend class base::RefCountedThreadSafe<MockDispatcher>;
   virtual ~MockDispatcher() {
     info_->IncrementDtorCallCount();
   }
 
-  // |Dispatcher| implementation/overrides:
+  // |Dispatcher| protected methods:
   virtual void CloseImplNoLock() OVERRIDE {
     info_->IncrementCloseCallCount();
     lock().AssertAcquired();
diff --git a/mojo/system/core_test_base.h b/mojo/system/core_test_base.h
index 58b2045..beb985b 100644
--- a/mojo/system/core_test_base.h
+++ b/mojo/system/core_test_base.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/synchronization/lock.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace mojo {
diff --git a/mojo/system/data_pipe.h b/mojo/system/data_pipe.h
index ce4ad2d..8d6fcaf 100644
--- a/mojo/system/data_pipe.h
+++ b/mojo/system/data_pipe.h
@@ -9,7 +9,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/system_impl_export.h"
 
 namespace mojo {
diff --git a/mojo/system/data_pipe_consumer_dispatcher.h b/mojo/system/data_pipe_consumer_dispatcher.h
index 1a62afd..ef60b91 100644
--- a/mojo/system/data_pipe_consumer_dispatcher.h
+++ b/mojo/system/data_pipe_consumer_dispatcher.h
@@ -26,13 +26,13 @@
   // Must be called before any other methods.
   void Init(scoped_refptr<DataPipe> data_pipe);
 
+  // |Dispatcher| public methods:
   virtual Type GetType() const OVERRIDE;
 
  private:
-  friend class base::RefCountedThreadSafe<DataPipeConsumerDispatcher>;
   virtual ~DataPipeConsumerDispatcher();
 
-  // |Dispatcher| implementation/overrides:
+  // |Dispatcher| protected methods:
   virtual void CancelAllWaitersNoLock() OVERRIDE;
   virtual void CloseImplNoLock() OVERRIDE;
   virtual scoped_refptr<Dispatcher>
diff --git a/mojo/system/data_pipe_producer_dispatcher.h b/mojo/system/data_pipe_producer_dispatcher.h
index 4f362a7..5f7b864 100644
--- a/mojo/system/data_pipe_producer_dispatcher.h
+++ b/mojo/system/data_pipe_producer_dispatcher.h
@@ -26,13 +26,13 @@
   // Must be called before any other methods.
   void Init(scoped_refptr<DataPipe> data_pipe);
 
+  // |Dispatcher| public methods:
   virtual Type GetType() const OVERRIDE;
 
  private:
-  friend class base::RefCountedThreadSafe<DataPipeProducerDispatcher>;
   virtual ~DataPipeProducerDispatcher();
 
-  // |Dispatcher| implementation/overrides:
+  // |Dispatcher| protected methods:
   virtual void CancelAllWaitersNoLock() OVERRIDE;
   virtual void CloseImplNoLock() OVERRIDE;
   virtual scoped_refptr<Dispatcher>
diff --git a/mojo/system/dispatcher.cc b/mojo/system/dispatcher.cc
index 36efbe0..de702aa 100644
--- a/mojo/system/dispatcher.cc
+++ b/mojo/system/dispatcher.cc
@@ -187,15 +187,16 @@
   return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
 }
 
-MojoResult Dispatcher::MapBuffer(uint64_t offset,
-                                 uint64_t num_bytes,
-                                 void** buffer,
-                                 MojoMapBufferFlags flags) {
+MojoResult Dispatcher::MapBuffer(
+    uint64_t offset,
+    uint64_t num_bytes,
+    MojoMapBufferFlags flags,
+    scoped_ptr<RawSharedBuffer::Mapping>* mapping) {
   base::AutoLock locker(lock_);
   if (is_closed_)
     return MOJO_RESULT_INVALID_ARGUMENT;
 
-  return MapBufferImplNoLock(offset, num_bytes, buffer, flags);
+  return MapBufferImplNoLock(offset, num_bytes, flags, mapping);
 }
 
 MojoResult Dispatcher::AddWaiter(Waiter* waiter,
@@ -322,10 +323,11 @@
   return MOJO_RESULT_INVALID_ARGUMENT;
 }
 
-MojoResult Dispatcher::MapBufferImplNoLock(uint64_t /*offset*/,
-                                           uint64_t /*num_bytes*/,
-                                           void** /*buffer*/,
-                                           MojoMapBufferFlags /*flags*/) {
+MojoResult Dispatcher::MapBufferImplNoLock(
+    uint64_t /*offset*/,
+    uint64_t /*num_bytes*/,
+    MojoMapBufferFlags /*flags*/,
+    scoped_ptr<RawSharedBuffer::Mapping>* /*mapping*/) {
   lock_.AssertAcquired();
   DCHECK(!is_closed_);
   // By default, not supported. Only needed for buffer dispatchers.
diff --git a/mojo/system/dispatcher.h b/mojo/system/dispatcher.h
index 309e2cd..c6ef752 100644
--- a/mojo/system/dispatcher.h
+++ b/mojo/system/dispatcher.h
@@ -12,8 +12,12 @@
 
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
+// TODO(vtl): We need this since we can't forward declare
+// |RawSharedBuffer::Mapping|. Maybe fix this.
+#include "mojo/system/raw_shared_buffer.h"
 #include "mojo/system/system_impl_export.h"
 
 namespace mojo {
@@ -48,7 +52,8 @@
     kTypeUnknown = 0,
     kTypeMessagePipe,
     kTypeDataPipeProducer,
-    kTypeDataPipeConsumer
+    kTypeDataPipeConsumer,
+    kTypeSharedBuffer
   };
   virtual Type GetType() const = 0;
 
@@ -100,8 +105,8 @@
       scoped_refptr<Dispatcher>* new_dispatcher);
   MojoResult MapBuffer(uint64_t offset,
                        uint64_t num_bytes,
-                       void** buffer,
-                       MojoMapBufferFlags flags);
+                       MojoMapBufferFlags flags,
+                       scoped_ptr<RawSharedBuffer::Mapping>* mapping);
 
   // Adds a waiter to this dispatcher. The waiter will be woken up when this
   // object changes state to satisfy |flags| with result |wake_result| (which
@@ -173,9 +178,9 @@
   };
 
  protected:
-  Dispatcher();
-
   friend class base::RefCountedThreadSafe<Dispatcher>;
+
+  Dispatcher();
   virtual ~Dispatcher();
 
   // These are to be overridden by subclasses (if necessary). They are called
@@ -218,10 +223,11 @@
   virtual MojoResult DuplicateBufferHandleImplNoLock(
       const MojoDuplicateBufferHandleOptions* options,
       scoped_refptr<Dispatcher>* new_dispatcher);
-  virtual MojoResult MapBufferImplNoLock(uint64_t offset,
-                                         uint64_t num_bytes,
-                                         void** buffer,
-                                         MojoMapBufferFlags flags);
+  virtual MojoResult MapBufferImplNoLock(
+      uint64_t offset,
+      uint64_t num_bytes,
+      MojoMapBufferFlags flags,
+      scoped_ptr<RawSharedBuffer::Mapping>* mapping);
   virtual MojoResult AddWaiterImplNoLock(Waiter* waiter,
                                          MojoWaitFlags flags,
                                          MojoResult wake_result);
@@ -269,8 +275,10 @@
   // on a dispatcher attached to a |MessageInTransit| (and in particular not in
   // |CoreImpl|'s handle table).
   // Gets the maximum amount of space that'll be needed to serialize this
-  // dispatcher to the given |Channel|. Returns zero to indicate that this
-  // dispatcher cannot be serialized (to the given |Channel|).
+  // dispatcher to the given |Channel|. This amount must be no greater than
+  // |MessageInTransit::kMaxSerializedDispatcherSize| (message_in_transit.h).
+  // Returns zero to indicate that this dispatcher cannot be serialized (to the
+  // given |Channel|).
   size_t GetMaximumSerializedSize(const Channel* channel) const;
   // Serializes this dispatcher to the given |Channel| by writing to
   // |destination| and then closes this dispatcher. It may write no more than
diff --git a/mojo/system/dispatcher_unittest.cc b/mojo/system/dispatcher_unittest.cc
index 9a7bedc..08687a2 100644
--- a/mojo/system/dispatcher_unittest.cc
+++ b/mojo/system/dispatcher_unittest.cc
@@ -182,11 +182,13 @@
                   dispatcher_->DuplicateBufferHandle(NULL, &unused));
         break;
       }
-      case MAP_BUFFER:
+      case MAP_BUFFER: {
+        scoped_ptr<RawSharedBuffer::Mapping> unused;
         EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
-                  dispatcher_->MapBuffer(0u, 0u, NULL,
-                                         MOJO_MAP_BUFFER_FLAG_NONE));
+                  dispatcher_->MapBuffer(0u, 0u, MOJO_MAP_BUFFER_FLAG_NONE,
+                                         &unused));
         break;
+      }
       case ADD_WAITER: {
         MojoResult r = dispatcher_->AddWaiter(&waiter_,
                                               MOJO_WAIT_FLAG_EVERYTHING, 0);
diff --git a/mojo/system/local_message_pipe_endpoint.h b/mojo/system/local_message_pipe_endpoint.h
index bae0786..9e200f1 100644
--- a/mojo/system/local_message_pipe_endpoint.h
+++ b/mojo/system/local_message_pipe_endpoint.h
@@ -7,7 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/message_in_transit_queue.h"
 #include "mojo/system/message_pipe_endpoint.h"
 #include "mojo/system/system_impl_export.h"
diff --git a/mojo/system/message_in_transit.cc b/mojo/system/message_in_transit.cc
index 6821b48..c56f4f3 100644
--- a/mojo/system/message_in_transit.cc
+++ b/mojo/system/message_in_transit.cc
@@ -16,6 +16,11 @@
 namespace mojo {
 namespace system {
 
+namespace {
+
+
+}  // namespace
+
 struct MessageInTransit::PrivateStructForCompileAsserts {
   // The size of |Header| must be appropriate to maintain alignment of the
   // following data.
@@ -27,6 +32,14 @@
                      0x7fffffffULL,
                  kMaxMessageNumBytes_too_big);
 
+  // We assume (to avoid extra rounding code) that the maximum message (data)
+  // size is a multiple of the alignment.
+  COMPILE_ASSERT(kMaxMessageNumBytes % kMessageAlignment == 0,
+                 kMessageAlignment_not_a_multiple_of_alignment);
+
+  COMPILE_ASSERT(kMaxSerializedDispatcherSize % kMessageAlignment == 0,
+                 kMaxSerializedDispatcherSize_not_a_multiple_of_alignment);
+
   // The size of |HandleTableEntry| must be appropriate to maintain alignment.
   COMPILE_ASSERT(sizeof(HandleTableEntry) % kMessageAlignment == 0,
                  sizeof_MessageInTransit_HandleTableEntry_invalid);
@@ -45,7 +58,12 @@
 STATIC_CONST_MEMBER_DEFINITION const MessageInTransit::EndpointId
     MessageInTransit::kInvalidEndpointId;
 STATIC_CONST_MEMBER_DEFINITION const size_t MessageInTransit::kMessageAlignment;
+STATIC_CONST_MEMBER_DEFINITION const size_t
+    MessageInTransit::kMaxSerializedDispatcherSize;
 
+// static
+const size_t MessageInTransit::kMaxSecondaryBufferSize = kMaxMessageNumHandles *
+    (sizeof(HandleTableEntry) + kMaxSerializedDispatcherSize);
 
 MessageInTransit::View::View(size_t message_size, const void* buffer)
     : buffer_(buffer) {
@@ -57,6 +75,24 @@
   DCHECK_EQ(message_size, total_size());
 }
 
+bool MessageInTransit::View::IsValid(const char** error_message) const {
+  // Note: This also implies a check on the |main_buffer_size()|, which is just
+  // |RoundUpMessageAlignment(sizeof(Header) + num_bytes())|.
+  if (num_bytes() > kMaxMessageNumBytes) {
+    *error_message = "Message data payload too large";
+    return false;
+  }
+
+  if (const char* secondary_buffer_error_message =
+          ValidateSecondaryBuffer(num_handles(), secondary_buffer(),
+                                  secondary_buffer_size())) {
+    *error_message = secondary_buffer_error_message;
+    return false;
+  }
+
+  return true;
+}
+
 MessageInTransit::MessageInTransit(Type type,
                                    Subtype subtype,
                                    uint32_t num_bytes,
@@ -178,15 +214,16 @@
   size_t size = handle_table_size;
   for (size_t i = 0; i < dispatchers_->size(); i++) {
     if (Dispatcher* dispatcher = (*dispatchers_)[i].get()) {
-      size += RoundUpMessageAlignment(
+      size_t max_serialized_size =
           Dispatcher::MessageInTransitAccess::GetMaximumSerializedSize(
-              dispatcher, channel));
-      // TODO(vtl): Check for overflow?
+              dispatcher, channel);
+      DCHECK_LE(max_serialized_size, kMaxSerializedDispatcherSize);
+      size += RoundUpMessageAlignment(max_serialized_size);
+      DCHECK_LE(size, kMaxSecondaryBufferSize);
     }
   }
 
   secondary_buffer_ = base::AlignedAlloc(size, kMessageAlignment);
-  // TODO(vtl): Check for overflow?
   secondary_buffer_size_ = static_cast<uint32_t>(size);
   // Entirely clear out the secondary buffer, since then we won't have to worry
   // about clearing padding or unused space (e.g., if a dispatcher fails to
@@ -228,12 +265,12 @@
 void MessageInTransit::DeserializeDispatchers(Channel* channel) {
   DCHECK(!dispatchers_.get());
 
+  // This should have been checked by calling |IsValid()| on the |View| first.
+  DCHECK_LE(num_handles(), kMaxMessageNumHandles);
+
   if (!num_handles())
     return;
 
-  // TODO(vtl): Restrict |num_handles()| to a sane range. (Maybe this should be
-  // done earlier?)
-
   dispatchers_.reset(
       new std::vector<scoped_refptr<Dispatcher> >(num_handles()));
 
@@ -263,6 +300,50 @@
   }
 }
 
+// Validates the secondary buffer. Returns null on success, or a human-readable
+// error message on error.
+// static
+const char* MessageInTransit::ValidateSecondaryBuffer(
+    size_t num_handles,
+    const void* secondary_buffer,
+    size_t secondary_buffer_size) {
+  if (!num_handles)
+    return NULL;
+
+  if (num_handles > kMaxMessageNumHandles)
+    return "Message handle payload too large";
+
+  if (secondary_buffer_size > kMaxSecondaryBufferSize)
+    return "Message secondary buffer too large";
+
+  if (secondary_buffer_size < num_handles * sizeof(HandleTableEntry))
+    return "Message secondary buffer too small";
+
+  DCHECK(secondary_buffer);
+  const HandleTableEntry* handle_table =
+      static_cast<const HandleTableEntry*>(secondary_buffer);
+
+  static const char kInvalidSerializedDispatcher[] =
+      "Message contains invalid serialized dispatcher";
+  for (size_t i = 0; i < num_handles; i++) {
+    size_t offset = handle_table[i].offset;
+    if (offset % kMessageAlignment != 0)
+      return kInvalidSerializedDispatcher;
+
+    size_t size = handle_table[i].size;
+    if (size > kMaxSerializedDispatcherSize || size > secondary_buffer_size)
+      return kInvalidSerializedDispatcher;
+
+    // Note: This is an overflow-safe check for |offset + size >
+    // secondary_buffer_size()| (we know that |size <= secondary_buffer_size()|
+    // from the previous check).
+    if (offset > secondary_buffer_size - size)
+      return kInvalidSerializedDispatcher;
+  }
+
+  return NULL;
+}
+
 void MessageInTransit::UpdateTotalSize() {
   DCHECK_EQ(main_buffer_size_ % kMessageAlignment, 0u);
   DCHECK_EQ(secondary_buffer_size_ % kMessageAlignment, 0u);
diff --git a/mojo/system/message_in_transit.h b/mojo/system/message_in_transit.h
index 7a8475d..966f84b 100644
--- a/mojo/system/message_in_transit.h
+++ b/mojo/system/message_in_transit.h
@@ -65,6 +65,10 @@
   // quantity (which must be a power of 2).
   static const size_t kMessageAlignment = 8;
 
+  // The maximum size of a single serialized dispatcher. This must be a multiple
+  // of |kMessageAlignment|.
+  static const size_t kMaxSerializedDispatcherSize = 10000;
+
   // Forward-declare |Header| so that |View| can use it:
  private:
   struct Header;
@@ -78,6 +82,18 @@
     // |buffer| should be |kMessageAlignment|-byte aligned.
     View(size_t message_size, const void* buffer);
 
+    // Checks the following things versus pre-determined limits:
+    //   - |num_bytes()| and |main_buffer_size()|,
+    //   - |num_handles()| and |secondary_buffer_size()|,
+    //   - the entries in the handle entry table (that the sizes and offsets are
+    //     valid).
+    // Note: It does not check the serialized dispatcher data itself.
+    //
+    // It returns true (and leaves |error_message| alone) if this object appears
+    // to be a valid message (according to the above) and false, pointing
+    // |*error_message| to a suitable error message, if not.
+    bool IsValid(const char** error_message) const;
+
     // API parallel to that for |MessageInTransit| itself (mostly getters for
     // header data).
     const void* main_buffer() const { return buffer_; }
@@ -233,6 +249,16 @@
     uint32_t unused;
   };
 
+  // The maximum possible size of a valid secondary buffer: for each handle,
+  // there'll be a handle table entry and its serialized data.
+  static const size_t kMaxSecondaryBufferSize;
+
+  // Validates the secondary buffer. Returns null on success, or a
+  // human-readable error message on error.
+  static const char* ValidateSecondaryBuffer(size_t num_handles,
+                                             const void* secondary_buffer,
+                                             size_t secondary_buffer_size);
+
   const Header* header() const {
     return static_cast<const Header*>(main_buffer_);
   }
diff --git a/mojo/system/message_pipe.h b/mojo/system/message_pipe.h
index 6815dcb..de42c44 100644
--- a/mojo/system/message_pipe.h
+++ b/mojo/system/message_pipe.h
@@ -11,7 +11,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/synchronization/lock.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/dispatcher.h"
 #include "mojo/system/message_in_transit.h"
 #include "mojo/system/message_pipe_endpoint.h"
diff --git a/mojo/system/message_pipe_dispatcher.h b/mojo/system/message_pipe_dispatcher.h
index 34e4b96..ab3067c 100644
--- a/mojo/system/message_pipe_dispatcher.h
+++ b/mojo/system/message_pipe_dispatcher.h
@@ -28,6 +28,7 @@
   // Must be called before any other methods. (This method is not thread-safe.)
   void Init(scoped_refptr<MessagePipe> message_pipe, unsigned port);
 
+  // |Dispatcher| public methods:
   virtual Type GetType() const OVERRIDE;
 
   // Creates a |MessagePipe| with a local endpoint (at port 0) and a proxy
@@ -45,7 +46,6 @@
  private:
   friend class MessagePipeDispatcherTransport;
 
-  friend class base::RefCountedThreadSafe<MessagePipeDispatcher>;
   virtual ~MessagePipeDispatcher();
 
   // Gets a dumb pointer to |message_pipe_|. This must be called under the
@@ -56,7 +56,7 @@
   // Similarly for the port.
   unsigned GetPortNoLock() const;
 
-  // |Dispatcher| implementation/overrides:
+  // |Dispatcher| protected methods:
   virtual void CancelAllWaitersNoLock() OVERRIDE;
   virtual void CloseImplNoLock() OVERRIDE;
   virtual scoped_refptr<Dispatcher>
diff --git a/mojo/system/message_pipe_endpoint.h b/mojo/system/message_pipe_endpoint.h
index 2cd9c17..b7b9589 100644
--- a/mojo/system/message_pipe_endpoint.h
+++ b/mojo/system/message_pipe_endpoint.h
@@ -12,7 +12,7 @@
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/dispatcher.h"
 #include "mojo/system/message_in_transit.h"
 #include "mojo/system/system_impl_export.h"
diff --git a/mojo/system/multiprocess_message_pipe_unittest.cc b/mojo/system/multiprocess_message_pipe_unittest.cc
index e0eab3b..7e3637f 100644
--- a/mojo/system/multiprocess_message_pipe_unittest.cc
+++ b/mojo/system/multiprocess_message_pipe_unittest.cc
@@ -2,10 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// TODO(vtl): Enable this on non-POSIX once we have a non-POSIX implementation.
-#include "build/build_config.h"
-#if defined(OS_POSIX)
-
 #include <stdint.h>
 
 #include <string>
@@ -14,6 +10,7 @@
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/threading/platform_thread.h"  // For |Sleep()|.
 #include "mojo/common/test/multiprocess_test_helper.h"
 #include "mojo/embedder/scoped_platform_handle.h"
 #include "mojo/system/channel.h"
@@ -47,6 +44,12 @@
 
   void Stop() {
     if (channel_) {
+      // Hack to flush write buffers before quitting.
+      // TODO(vtl): Remove this once |Channel| has a
+      // |FlushWriteBufferAndShutdown()| (or whatever).
+      while (!channel_->IsWriteBufferEmpty())
+        base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
+
       test_io_thread_.PostTaskAndWait(
           FROM_HERE,
           base::Bind(&ChannelThread::ShutdownChannelOnIOThread,
@@ -215,13 +218,7 @@
 
 // Sends a bunch of messages to the child. Expects them "repeated" back. Waits
 // for the child to close its end before quitting.
-// TODO(yzshen): The test hangs on Mac. http://crbug.com/350575
-#if defined(OS_MACOSX)
-#define MAYBE_QueueMessages DISABLED_QueueMessages
-#else
-#define MAYBE_QueueMessages QueueMessages
-#endif
-TEST_F(MultiprocessMessagePipeTest, MAYBE_QueueMessages) {
+TEST_F(MultiprocessMessagePipeTest, QueueMessages) {
   helper()->StartChild("EchoEcho");
 
   scoped_refptr<MessagePipe> mp(new MessagePipe(
@@ -277,5 +274,3 @@
 }  // namespace
 }  // namespace system
 }  // namespace mojo
-
-#endif  // defined(OS_POSIX)
diff --git a/mojo/system/proxy_message_pipe_endpoint.h b/mojo/system/proxy_message_pipe_endpoint.h
index c1ed3c0..7d62b9b 100644
--- a/mojo/system/proxy_message_pipe_endpoint.h
+++ b/mojo/system/proxy_message_pipe_endpoint.h
@@ -10,7 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/message_in_transit.h"
 #include "mojo/system/message_in_transit_queue.h"
 #include "mojo/system/message_pipe_endpoint.h"
diff --git a/mojo/system/raw_channel.cc b/mojo/system/raw_channel.cc
index 029e18a..cfdc131 100644
--- a/mojo/system/raw_channel.cc
+++ b/mojo/system/raw_channel.cc
@@ -130,6 +130,9 @@
 
   base::AutoLock locker(write_lock_);
 
+  LOG_IF(WARNING, !write_buffer_->message_queue_.empty())
+      << "Shutting down RawChannel with write buffer nonempty";
+
   weak_ptr_factory_.InvalidateWeakPtrs();
 
   read_stopped_ = true;
@@ -172,6 +175,12 @@
   return result;
 }
 
+// Reminder: This must be thread-safe.
+bool RawChannel::IsWriteBufferEmpty() {
+  base::AutoLock locker(write_lock_);
+  return write_buffer_->message_queue_.empty();
+}
+
 RawChannel::ReadBuffer* RawChannel::read_buffer() {
   DCHECK_EQ(base::MessageLoop::current(), message_loop_for_io_);
   return read_buffer_.get();
diff --git a/mojo/system/raw_channel.h b/mojo/system/raw_channel.h
index 2eb28f6..8f760d6 100644
--- a/mojo/system/raw_channel.h
+++ b/mojo/system/raw_channel.h
@@ -85,10 +85,16 @@
   // This must be called (on the I/O thread) before this object is destroyed.
   void Shutdown();
 
-  // This is thread-safe. It takes ownership of |message| (always, even on
-  // failure). Returns true on success.
+  // Writes the given message (or schedules it to be written). This is
+  // thread-safe. Returns true on success.
   bool WriteMessage(scoped_ptr<MessageInTransit> message);
 
+  // Returns true if the write buffer is empty (i.e., all messages written using
+  // |WriteMessage()| have actually been sent.
+  // TODO(vtl): We should really also notify our delegate when the write buffer
+  // becomes empty (or something like that).
+  bool IsWriteBufferEmpty();
+
  protected:
   // Return values of |[Schedule]Read()| and |[Schedule]WriteNoLock()|.
   enum IOResult {
diff --git a/mojo/system/raw_channel_posix.cc b/mojo/system/raw_channel_posix.cc
index 5d04334..e2f453c 100644
--- a/mojo/system/raw_channel_posix.cc
+++ b/mojo/system/raw_channel_posix.cc
@@ -5,6 +5,8 @@
 #include "mojo/system/raw_channel.h"
 
 #include <errno.h>
+#include <sys/socket.h>
+#include <sys/types.h>
 #include <sys/uio.h>
 #include <unistd.h>
 
@@ -20,6 +22,7 @@
 #include "base/message_loop/message_loop.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/synchronization/lock.h"
+#include "build/build_config.h"
 #include "mojo/embedder/platform_handle.h"
 
 namespace mojo {
@@ -150,9 +153,15 @@
     write_result = HANDLE_EINTR(
         write(fd_.get().fd, buffers[0].addr, buffers[0].size));
   } else {
-    // Note that using |writev()| is measurably slower than using |write()| --
-    // at least in a microbenchmark -- but much faster than using multiple
-    // |write()|s.
+    // Note that using |writev()|/|sendmsg()| is measurably slower than using
+    // |write()| -- at least in a microbenchmark -- but much faster than using
+    // multiple |write()|s. (|sendmsg()| is also measurably slightly slower than
+    // |writev()|.)
+    //
+    // On Linux, we need to use |sendmsg()| since it's the only way to suppress
+    // |SIGPIPE| (on Mac, this is suppressed on the socket itself using
+    // |setsockopt()|, since |MSG_NOSIGNAL| is not supported -- see
+    // platform_channel_pair_posix.cc).
     const size_t kMaxBufferCount = 10;
     iovec iov[kMaxBufferCount];
     size_t buffer_count = std::min(buffers.size(), kMaxBufferCount);
@@ -162,7 +171,20 @@
       iov[i].iov_len = buffers[i].size;
     }
 
+    // On Mac, we can use |writev()|, which is slightly faster, but on Linux we
+    // need to use |sendmsg()|. See comment above.
+    // TODO(vtl): We should have an actual test that |SIGPIPE| is suppressed for
+    // |RawChannelPosix|, since it has to be suppressed at "use" time on Linux.
+    // Or maybe I should abstract out |write()|/|send()| and
+    // |writev()|/|sendmsg()|. crbug.com/356195
+#if defined(OS_MACOSX)
     write_result = HANDLE_EINTR(writev(fd_.get().fd, iov, buffer_count));
+#else
+    struct msghdr msg = {};
+    msg.msg_iov = iov;
+    msg.msg_iovlen = buffer_count;
+    write_result = HANDLE_EINTR(sendmsg(fd_.get().fd, &msg, MSG_NOSIGNAL));
+#endif
   }
 
   if (write_result >= 0) {
diff --git a/mojo/system/raw_shared_buffer.cc b/mojo/system/raw_shared_buffer.cc
new file mode 100644
index 0000000..a4bd4a6
--- /dev/null
+++ b/mojo/system/raw_shared_buffer.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/system/raw_shared_buffer.h"
+
+#include "base/logging.h"
+
+namespace mojo {
+namespace system {
+
+// static
+RawSharedBuffer* RawSharedBuffer::Create(size_t num_bytes) {
+  DCHECK_GT(num_bytes, 0u);
+
+  RawSharedBuffer* rv = new RawSharedBuffer(num_bytes);
+  // No need to take the lock since we haven't given the object to anyone yet.
+  if (!rv->InitNoLock())
+    return NULL;
+
+  return rv;
+}
+
+scoped_ptr<RawSharedBuffer::Mapping> RawSharedBuffer::Map(size_t offset,
+                                                          size_t length) {
+  if (!IsValidMap(offset, length))
+    return scoped_ptr<Mapping>();
+
+  return MapNoCheck(offset, length);
+}
+
+bool RawSharedBuffer::IsValidMap(size_t offset, size_t length) {
+  if (offset > num_bytes_ || length == 0)
+    return false;
+
+  // Note: This is an overflow-safe check of |offset + length > num_bytes_|
+  // (that |num_bytes >= offset| is verified above).
+  if (length > num_bytes_ - offset)
+    return false;
+
+  return true;
+}
+
+scoped_ptr<RawSharedBuffer::Mapping> RawSharedBuffer::MapNoCheck(
+    size_t offset,
+    size_t length) {
+  DCHECK(IsValidMap(offset, length));
+
+  base::AutoLock locker(lock_);
+  return MapImplNoLock(offset, length);
+}
+
+RawSharedBuffer::RawSharedBuffer(size_t num_bytes) : num_bytes_(num_bytes) {
+}
+
+RawSharedBuffer::~RawSharedBuffer() {
+}
+
+}  // namespace system
+}  // namespace mojo
diff --git a/mojo/system/raw_shared_buffer.h b/mojo/system/raw_shared_buffer.h
new file mode 100644
index 0000000..c7a287c
--- /dev/null
+++ b/mojo/system/raw_shared_buffer.h
@@ -0,0 +1,110 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SYSTEM_RAW_SHARED_BUFFER_H_
+#define MOJO_SYSTEM_RAW_SHARED_BUFFER_H_
+
+#include <stddef.h>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/lock.h"
+#include "mojo/embedder/scoped_platform_handle.h"
+#include "mojo/system/system_impl_export.h"
+
+namespace mojo {
+namespace system {
+
+// |RawSharedBuffer| is a thread-safe, ref-counted wrapper around OS-specific
+// shared memory. It has the following features:
+//   - A |RawSharedBuffer| simply represents a piece of shared memory that *may*
+//     be mapped and *may* be shared to another process.
+//   - A single |RawSharedBuffer| may be mapped multiple times. The lifetime of
+//     the mapping (owned by |RawSharedBuffer::Mapping|) is separate from the
+//     lifetime of the |RawSharedBuffer|.
+//   - Sizes/offsets (of the shared memory and mappings) are arbitrary, and not
+//     restricted by page size. However, more memory may actually be mapped than
+//     requested.
+//
+// It currently does NOT support the following:
+//   - Sharing read-only. (This will probably eventually be supported.)
+//
+// TODO(vtl): Rectify this with |base::SharedMemory|.
+class MOJO_SYSTEM_IMPL_EXPORT RawSharedBuffer
+    : public base::RefCountedThreadSafe<RawSharedBuffer> {
+ public:
+  // A mapping of a |RawSharedBuffer| (compararable to a "file view" in
+  // Windows); see above. Created by |RawSharedBuffer::Map()|. Automatically
+  // unmaps memory on destruction.
+  //
+  // Mappings are NOT thread-safe.
+  class MOJO_SYSTEM_IMPL_EXPORT Mapping {
+   public:
+    ~Mapping() { Unmap(); }
+
+    void* base() const { return base_; }
+    size_t length() const { return length_; }
+
+   private:
+    friend class RawSharedBuffer;
+
+    Mapping(void* base, size_t length, void* real_base, size_t real_length)
+        : base_(base), length_(length),
+          real_base_(real_base), real_length_(real_length) {}
+    void Unmap();
+
+    void* const base_;
+    const size_t length_;
+
+    void* const real_base_;
+    const size_t real_length_;
+
+    DISALLOW_COPY_AND_ASSIGN(Mapping);
+  };
+
+  // Creates a shared buffer of size |num_bytes| bytes (initially zero-filled).
+  // |num_bytes| must be nonzero. Returns null on failure.
+  static RawSharedBuffer* Create(size_t num_bytes);
+
+  // Maps (some) of the shared buffer into memory; [|offset|, |offset + length|]
+  // must be contained in [0, |num_bytes|], and |length| must be at least 1.
+  // Returns null on failure.
+  scoped_ptr<Mapping> Map(size_t offset, size_t length);
+
+  // Checks if |offset| and |length| are valid arguments.
+  bool IsValidMap(size_t offset, size_t length);
+
+  // Like |Map()|, but doesn't check its arguments (which should have been
+  // preflighted using |IsValidMap()|).
+  scoped_ptr<Mapping> MapNoCheck(size_t offset, size_t length);
+
+  size_t num_bytes() const { return num_bytes_; }
+
+ private:
+  friend class base::RefCountedThreadSafe<RawSharedBuffer>;
+
+  explicit RawSharedBuffer(size_t num_bytes);
+  ~RawSharedBuffer();
+
+  // This is called by |Create()| before this object is given to anyone (hence
+  // it doesn't need to take |lock_|).
+  bool InitNoLock();
+
+  // The platform-dependent part of |Map()|; doesn't check arguments. Called
+  // under |lock_|.
+  scoped_ptr<Mapping> MapImplNoLock(size_t offset, size_t length);
+
+  const size_t num_bytes_;
+
+  base::Lock lock_;  // Protects |handle_|.
+  embedder::ScopedPlatformHandle handle_;
+
+  DISALLOW_COPY_AND_ASSIGN(RawSharedBuffer);
+};
+
+}  // namespace system
+}  // namespace mojo
+
+#endif  // MOJO_SYSTEM_RAW_SHARED_BUFFER_H_
diff --git a/mojo/system/raw_shared_buffer_posix.cc b/mojo/system/raw_shared_buffer_posix.cc
new file mode 100644
index 0000000..bded0e4
--- /dev/null
+++ b/mojo/system/raw_shared_buffer_posix.cc
@@ -0,0 +1,120 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/system/raw_shared_buffer.h"
+
+#include <stdint.h>
+#include <stdio.h>  // For |fileno()|.
+#include <sys/mman.h>  // For |mmap()|/|munmap()|.
+#include <sys/types.h>  // For |off_t|.
+#include <unistd.h>
+
+#include <limits>
+
+#include "base/file_util.h"
+#include "base/files/file_path.h"
+#include "base/files/scoped_file.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/sys_info.h"
+#include "base/threading/thread_restrictions.h"
+#include "mojo/embedder/platform_handle.h"
+
+// We assume that |size_t| and |off_t| (type for |ftruncate()|) fits in a
+// |uint64_t|.
+COMPILE_ASSERT(sizeof(size_t) <= sizeof(uint64_t), size_t_too_big);
+COMPILE_ASSERT(sizeof(off_t) <= sizeof(uint64_t), off_t_too_big);
+
+namespace mojo {
+namespace system {
+
+// RawSharedBuffer::Mapping ----------------------------------------------------
+
+void RawSharedBuffer::Mapping::Unmap() {
+  int result = munmap(real_base_, real_length_);
+  PLOG_IF(ERROR, result != 0) << "munmap";
+}
+
+// RawSharedBuffer -------------------------------------------------------------
+
+bool RawSharedBuffer::InitNoLock() {
+  DCHECK(!handle_.is_valid());
+
+  base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+  if (static_cast<uint64_t>(num_bytes_) >
+          static_cast<uint64_t>(std::numeric_limits<off_t>::max())) {
+    return false;
+  }
+
+  // TODO(vtl): This is stupid. The implementation of
+  // |CreateAndOpenTemporaryFileInDir()| starts with an FD, |fdopen()|s to get a
+  // |FILE*|, and then we have to |dup(fileno(fp))| to get back to an FD that we
+  // can own. (base/memory/shared_memory_posix.cc does this too, with more
+  // |fstat()|s thrown in for good measure.)
+  base::FilePath shared_buffer_dir;
+  if (!base::GetShmemTempDir(false, &shared_buffer_dir)) {
+    LOG(ERROR) << "Failed to get temporary directory for shared memory";
+    return false;
+  }
+  base::FilePath shared_buffer_file;
+  base::ScopedFILE fp(base::CreateAndOpenTemporaryFileInDir(
+      shared_buffer_dir, &shared_buffer_file));
+  if (!fp) {
+    LOG(ERROR) << "Failed to create/open temporary file for shared memory";
+    return false;
+  }
+  // Note: |unlink()| is not interruptible.
+  if (unlink(shared_buffer_file.value().c_str()) != 0) {
+    PLOG(WARNING) << "unlink";
+    // This isn't "fatal" (e.g., someone else may have unlinked the file first),
+    // so we may as well continue.
+  }
+
+  // Note: |dup()| is not interruptible (but |dup2()|/|dup3()| are).
+  base::ScopedFD fd(dup(fileno(fp.get())));
+  if (!fd.is_valid()) {
+    PLOG(ERROR) << "dup";
+    return false;
+  }
+
+  if (HANDLE_EINTR(ftruncate(fd.get(), static_cast<off_t>(num_bytes_))) != 0) {
+    PLOG(ERROR) << "ftruncate";
+    return false;
+  }
+
+  handle_.reset(embedder::PlatformHandle(fd.release()));
+  return true;
+}
+
+scoped_ptr<RawSharedBuffer::Mapping> RawSharedBuffer::MapImplNoLock(
+    size_t offset,
+    size_t length) {
+  lock_.AssertAcquired();
+
+  size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
+  size_t real_offset = offset - offset_rounding;
+  size_t real_length = length + offset_rounding;
+
+  // This should hold (since we checked |num_bytes| versus the maximum value of
+  // |off_t| on creation, but it never hurts to be paranoid.
+  DCHECK_LE(static_cast<uint64_t>(real_offset),
+            static_cast<uint64_t>(std::numeric_limits<off_t>::max()));
+
+  void* real_base = mmap(NULL, real_length, PROT_READ | PROT_WRITE, MAP_SHARED,
+                         handle_.get().fd, static_cast<off_t>(real_offset));
+  // |mmap()| should return |MAP_FAILED| (a.k.a. -1) on error. But it shouldn't
+  // return null either.
+  if (real_base == MAP_FAILED || !real_base) {
+    PLOG(ERROR) << "mmap";
+    return scoped_ptr<Mapping>();
+  }
+
+  void* base = static_cast<char*>(real_base) + offset_rounding;
+  return make_scoped_ptr(new Mapping(base, length, real_base, real_length));
+}
+
+}  // namespace system
+}  // namespace mojo
diff --git a/mojo/system/raw_shared_buffer_unittest.cc b/mojo/system/raw_shared_buffer_unittest.cc
new file mode 100644
index 0000000..d9360f8
--- /dev/null
+++ b/mojo/system/raw_shared_buffer_unittest.cc
@@ -0,0 +1,181 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/system/raw_shared_buffer.h"
+
+#include <limits>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace system {
+namespace {
+
+TEST(RawSharedBufferTest, Basic) {
+  const size_t kNumInts = 100;
+  const size_t kNumBytes = kNumInts * sizeof(int);
+  // A fudge so that we're not just writing zero bytes 75% of the time.
+  const int kFudge = 1234567890;
+
+  // Make some memory.
+  scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(kNumBytes));
+  ASSERT_TRUE(buffer);
+
+  // Map it all, scribble some stuff, and then unmap it.
+  {
+    EXPECT_TRUE(buffer->IsValidMap(0, kNumBytes));
+    scoped_ptr<RawSharedBuffer::Mapping> mapping(buffer->Map(0, kNumBytes));
+    ASSERT_TRUE(mapping);
+    ASSERT_TRUE(mapping->base());
+    int* stuff = static_cast<int*>(mapping->base());
+    for (size_t i = 0; i < kNumInts; i++)
+      stuff[i] = static_cast<int>(i) + kFudge;
+  }
+
+  // Map it all again, check that our scribbling is still there, then do a
+  // partial mapping and scribble on that, check that everything is coherent,
+  // unmap the first mapping, scribble on some of the second mapping, and then
+  // unmap it.
+  {
+    ASSERT_TRUE(buffer->IsValidMap(0, kNumBytes));
+    // Use |MapNoCheck()| this time.
+    scoped_ptr<RawSharedBuffer::Mapping> mapping1(
+        buffer->MapNoCheck(0, kNumBytes));
+    ASSERT_TRUE(mapping1);
+    ASSERT_TRUE(mapping1->base());
+    int* stuff1 = static_cast<int*>(mapping1->base());
+    for (size_t i = 0; i < kNumInts; i++)
+      EXPECT_EQ(static_cast<int>(i) + kFudge, stuff1[i]) << i;
+
+    scoped_ptr<RawSharedBuffer::Mapping> mapping2(
+        buffer->Map((kNumInts / 2) * sizeof(int), 2 * sizeof(int)));
+    ASSERT_TRUE(mapping2);
+    ASSERT_TRUE(mapping2->base());
+    int* stuff2 = static_cast<int*>(mapping2->base());
+    EXPECT_EQ(static_cast<int>(kNumInts / 2) + kFudge, stuff2[0]);
+    EXPECT_EQ(static_cast<int>(kNumInts / 2) + 1 + kFudge, stuff2[1]);
+
+    stuff2[0] = 123;
+    stuff2[1] = 456;
+    EXPECT_EQ(123, stuff1[kNumInts / 2]);
+    EXPECT_EQ(456, stuff1[kNumInts / 2 + 1]);
+
+    mapping1.reset();
+
+    EXPECT_EQ(123, stuff2[0]);
+    EXPECT_EQ(456, stuff2[1]);
+    stuff2[1] = 789;
+  }
+
+  // Do another partial mapping and check that everything is the way we expect
+  // it to be.
+  {
+    EXPECT_TRUE(buffer->IsValidMap(sizeof(int), kNumBytes - sizeof(int)));
+    scoped_ptr<RawSharedBuffer::Mapping> mapping(
+        buffer->Map(sizeof(int), kNumBytes - sizeof(int)));
+    ASSERT_TRUE(mapping);
+    ASSERT_TRUE(mapping->base());
+    int* stuff = static_cast<int*>(mapping->base());
+
+    for (size_t j = 0; j < kNumInts - 1; j++) {
+      int i = static_cast<int>(j) + 1;
+      if (i == kNumInts / 2) {
+        EXPECT_EQ(123, stuff[j]);
+      } else if (i == kNumInts / 2 + 1) {
+        EXPECT_EQ(789, stuff[j]);
+      } else {
+        EXPECT_EQ(i + kFudge, stuff[j]) << i;
+      }
+    }
+  }
+}
+
+// TODO(vtl): Bigger buffers.
+
+TEST(RawSharedBufferTest, InvalidMappings) {
+  scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(100));
+  ASSERT_TRUE(buffer);
+
+  // Zero length not allowed.
+  EXPECT_FALSE(buffer->Map(0, 0));
+  EXPECT_FALSE(buffer->IsValidMap(0, 0));
+
+  // Okay:
+  EXPECT_TRUE(buffer->Map(0, 100));
+  EXPECT_TRUE(buffer->IsValidMap(0, 100));
+  // Offset + length too big.
+  EXPECT_FALSE(buffer->Map(0, 101));
+  EXPECT_FALSE(buffer->IsValidMap(0, 101));
+  EXPECT_FALSE(buffer->Map(1, 100));
+  EXPECT_FALSE(buffer->IsValidMap(1, 100));
+
+  // Okay:
+  EXPECT_TRUE(buffer->Map(50, 50));
+  EXPECT_TRUE(buffer->IsValidMap(50, 50));
+  // Offset + length too big.
+  EXPECT_FALSE(buffer->Map(50, 51));
+  EXPECT_FALSE(buffer->IsValidMap(50, 51));
+  EXPECT_FALSE(buffer->Map(51, 50));
+  EXPECT_FALSE(buffer->IsValidMap(51, 50));
+}
+
+TEST(RawSharedBufferTest, TooBig) {
+  // If |size_t| is 32-bit, it's quite possible/likely that |Create()| succeeds
+  // (since it only involves creating a 4 GB file).
+  const size_t kMaxSizeT = std::numeric_limits<size_t>::max();
+  scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(kMaxSizeT));
+  // But, assuming |sizeof(size_t) == sizeof(void*)|, mapping all of it should
+  // always fail.
+  if (buffer)
+    EXPECT_FALSE(buffer->Map(0, kMaxSizeT));
+}
+
+// Tests that separate mappings get distinct addresses.
+// Note: It's not inconceivable that the OS could ref-count identical mappings
+// and reuse the same address, in which case we'd have to be more careful about
+// using the address as the key for unmapping.
+TEST(RawSharedBufferTest, MappingsDistinct) {
+  scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(100));
+  scoped_ptr<RawSharedBuffer::Mapping> mapping1(buffer->Map(0, 100));
+  scoped_ptr<RawSharedBuffer::Mapping> mapping2(buffer->Map(0, 100));
+  EXPECT_NE(mapping1->base(), mapping2->base());
+}
+
+TEST(RawSharedBufferTest, BufferZeroInitialized) {
+  static const size_t kSizes[] = { 10, 100, 1000, 10000, 100000 };
+  for (size_t i = 0; i < arraysize(kSizes); i++) {
+    scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(kSizes[i]));
+    scoped_ptr<RawSharedBuffer::Mapping> mapping(buffer->Map(0, kSizes[i]));
+    for (size_t j = 0; j < kSizes[i]; j++) {
+      // "Assert" instead of "expect" so we don't spam the output with thousands
+      // of failures if we fail.
+      ASSERT_EQ('\0', static_cast<char*>(mapping->base())[j])
+          << "size " << kSizes[i] << ", offset " << j;
+    }
+  }
+}
+
+TEST(RawSharedBufferTest, MappingsOutliveBuffer) {
+  scoped_ptr<RawSharedBuffer::Mapping> mapping1;
+  scoped_ptr<RawSharedBuffer::Mapping> mapping2;
+
+  {
+    scoped_refptr<RawSharedBuffer> buffer(RawSharedBuffer::Create(100));
+    mapping1 = buffer->Map(0, 100).Pass();
+    mapping2 = buffer->Map(50, 50).Pass();
+    static_cast<char*>(mapping1->base())[50] = 'x';
+  }
+
+  EXPECT_EQ('x', static_cast<char*>(mapping2->base())[0]);
+
+  static_cast<char*>(mapping2->base())[1] = 'y';
+  EXPECT_EQ('y', static_cast<char*>(mapping1->base())[51]);
+}
+
+}  // namespace
+}  // namespace system
+}  // namespace mojo
diff --git a/mojo/system/raw_shared_buffer_win.cc b/mojo/system/raw_shared_buffer_win.cc
new file mode 100644
index 0000000..e67501d
--- /dev/null
+++ b/mojo/system/raw_shared_buffer_win.cc
@@ -0,0 +1,81 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/system/raw_shared_buffer.h"
+
+#include <windows.h>
+
+#include <limits>
+
+#include "base/logging.h"
+#include "base/sys_info.h"
+#include "mojo/embedder/platform_handle.h"
+#include "mojo/embedder/scoped_platform_handle.h"
+
+namespace mojo {
+namespace system {
+
+// RawSharedBuffer::Mapping ----------------------------------------------------
+
+void RawSharedBuffer::Mapping::Unmap() {
+  BOOL result = UnmapViewOfFile(real_base_);
+  PLOG_IF(ERROR, !result) << "UnmapViewOfFile";
+}
+
+// RawSharedBuffer -------------------------------------------------------------
+
+bool RawSharedBuffer::InitNoLock() {
+  DCHECK(!handle_.is_valid());
+
+  // TODO(vtl): Currently, we only support mapping up to 2^32-1 bytes.
+  if (static_cast<uint64_t>(num_bytes_) >
+          static_cast<uint64_t>(std::numeric_limits<DWORD>::max())) {
+    return false;
+  }
+
+  // IMPORTANT NOTE: Unnamed objects are NOT SECURABLE. Thus if we ever want to
+  // share read-only to other processes, we'll have to name our file mapping
+  // object.
+  // TODO(vtl): Unlike |base::SharedMemory|, we don't round up the size (to a
+  // multiple of 64 KB). This may cause problems with NaCl. Cross this bridge
+  // when we get there. crbug.com/210609
+  handle_.reset(embedder::PlatformHandle(CreateFileMapping(
+      INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
+      static_cast<DWORD>(num_bytes_), NULL)));
+  if (!handle_.is_valid()) {
+    PLOG(ERROR) << "CreateFileMapping";
+    return false;
+  }
+
+  return true;
+}
+
+scoped_ptr<RawSharedBuffer::Mapping> RawSharedBuffer::MapImplNoLock(
+    size_t offset,
+    size_t length) {
+  lock_.AssertAcquired();
+
+  size_t offset_rounding = offset % base::SysInfo::VMAllocationGranularity();
+  size_t real_offset = offset - offset_rounding;
+  size_t real_length = length + offset_rounding;
+
+  // This should hold (since we checked |num_bytes| versus the maximum value of
+  // |off_t| on creation, but it never hurts to be paranoid.
+  DCHECK_LE(static_cast<uint64_t>(real_offset),
+            static_cast<uint64_t>(std::numeric_limits<DWORD>::max()));
+
+  void* real_base = MapViewOfFile(
+      handle_.get().handle, FILE_MAP_READ | FILE_MAP_WRITE, 0,
+      static_cast<DWORD>(real_offset), real_length);
+  if (!real_base) {
+    PLOG(ERROR) << "MapViewOfFile";
+    return scoped_ptr<Mapping>();
+  }
+
+  void* base = static_cast<char*>(real_base) + offset_rounding;
+  return make_scoped_ptr(new Mapping(base, length, real_base, real_length));
+}
+
+}  // namespace system
+}  // namespace mojo
diff --git a/mojo/system/shared_buffer_dispatcher.cc b/mojo/system/shared_buffer_dispatcher.cc
new file mode 100644
index 0000000..684f993
--- /dev/null
+++ b/mojo/system/shared_buffer_dispatcher.cc
@@ -0,0 +1,141 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/system/shared_buffer_dispatcher.h"
+
+#include <limits>
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "mojo/system/constants.h"
+#include "mojo/system/memory.h"
+
+namespace mojo {
+namespace system {
+
+// static
+MojoResult SharedBufferDispatcher::ValidateOptions(
+    const MojoCreateSharedBufferOptions* in_options,
+    MojoCreateSharedBufferOptions* out_options) {
+  static const MojoCreateSharedBufferOptions kDefaultOptions = {
+    static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions)),
+    MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE
+  };
+  if (!in_options) {
+    *out_options = kDefaultOptions;
+    return MOJO_RESULT_OK;
+  }
+
+  if (in_options->struct_size < sizeof(*in_options))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+  out_options->struct_size = static_cast<uint32_t>(sizeof(*out_options));
+
+  // All flags are okay (unrecognized flags will be ignored).
+  out_options->flags = in_options->flags;
+
+  return MOJO_RESULT_OK;
+}
+
+// static
+MojoResult SharedBufferDispatcher::Create(
+    const MojoCreateSharedBufferOptions& /*validated_options*/,
+    uint64_t num_bytes,
+    scoped_refptr<SharedBufferDispatcher>* result) {
+  if (!num_bytes)
+    return MOJO_RESULT_INVALID_ARGUMENT;
+  if (num_bytes > kMaxSharedMemoryNumBytes)
+    return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+  scoped_refptr<RawSharedBuffer> shared_buffer(
+      RawSharedBuffer::Create(static_cast<size_t>(num_bytes)));
+  if (!shared_buffer)
+    return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+  *result = new SharedBufferDispatcher(shared_buffer);
+  return MOJO_RESULT_OK;
+}
+
+Dispatcher::Type SharedBufferDispatcher::GetType() const {
+  return kTypeSharedBuffer;
+}
+
+SharedBufferDispatcher::SharedBufferDispatcher(
+    scoped_refptr<RawSharedBuffer> shared_buffer)
+    : shared_buffer_(shared_buffer) {
+  DCHECK(shared_buffer_);
+}
+
+SharedBufferDispatcher::~SharedBufferDispatcher() {
+}
+
+void SharedBufferDispatcher::CloseImplNoLock() {
+  DCHECK(shared_buffer_);
+  shared_buffer_ = NULL;
+}
+
+scoped_refptr<Dispatcher>
+    SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
+  DCHECK(shared_buffer_);
+  scoped_refptr<RawSharedBuffer> shared_buffer;
+  shared_buffer.swap(shared_buffer_);
+  return scoped_refptr<Dispatcher>(new SharedBufferDispatcher(shared_buffer));
+}
+
+MojoResult SharedBufferDispatcher::DuplicateBufferHandleImplNoLock(
+    const MojoDuplicateBufferHandleOptions* options,
+    scoped_refptr<Dispatcher>* new_dispatcher) {
+  if (options) {
+    // The |struct_size| field must be valid to read.
+    if (!VerifyUserPointer<uint32_t>(&options->struct_size, 1))
+      return MOJO_RESULT_INVALID_ARGUMENT;
+    // And then |options| must point to at least |options->struct_size| bytes.
+    if (!VerifyUserPointer<void>(options, options->struct_size))
+      return MOJO_RESULT_INVALID_ARGUMENT;
+
+    if (options->struct_size < sizeof(*options))
+      return MOJO_RESULT_INVALID_ARGUMENT;
+    // We don't actually do anything with |options|.
+  }
+
+  *new_dispatcher = new SharedBufferDispatcher(shared_buffer_);
+  return MOJO_RESULT_OK;
+}
+
+MojoResult SharedBufferDispatcher::MapBufferImplNoLock(
+    uint64_t offset,
+    uint64_t num_bytes,
+    MojoMapBufferFlags flags,
+    scoped_ptr<RawSharedBuffer::Mapping>* mapping) {
+  DCHECK(shared_buffer_);
+
+  if (offset > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+  if (num_bytes > static_cast<uint64_t>(std::numeric_limits<size_t>::max()))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  if (!shared_buffer_->IsValidMap(static_cast<size_t>(offset),
+                                  static_cast<size_t>(num_bytes)))
+    return MOJO_RESULT_INVALID_ARGUMENT;
+
+  DCHECK(mapping);
+  *mapping = shared_buffer_->MapNoCheck(static_cast<size_t>(offset),
+                                        static_cast<size_t>(num_bytes));
+  if (!*mapping)
+    return MOJO_RESULT_RESOURCE_EXHAUSTED;
+
+  return MOJO_RESULT_OK;
+}
+
+MojoWaitFlags SharedBufferDispatcher::SatisfiedFlagsNoLock() const {
+  // TODO(vtl): Add transferrable flag.
+  return MOJO_WAIT_FLAG_NONE;
+}
+
+MojoWaitFlags SharedBufferDispatcher::SatisfiableFlagsNoLock() const {
+  // TODO(vtl): Add transferrable flag.
+  return MOJO_WAIT_FLAG_NONE;
+}
+
+}  // namespace system
+}  // namespace mojo
diff --git a/mojo/system/shared_buffer_dispatcher.h b/mojo/system/shared_buffer_dispatcher.h
new file mode 100644
index 0000000..0f86c1b
--- /dev/null
+++ b/mojo/system/shared_buffer_dispatcher.h
@@ -0,0 +1,68 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOJO_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
+#define MOJO_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
+
+#include "base/macros.h"
+#include "mojo/system/raw_shared_buffer.h"
+#include "mojo/system/simple_dispatcher.h"
+#include "mojo/system/system_impl_export.h"
+
+namespace mojo {
+namespace system {
+
+// TODO(vtl): We derive from SimpleDispatcher, even though we don't currently
+// have anything that's waitable. I want to add a "transferrable" wait flag.
+class MOJO_SYSTEM_IMPL_EXPORT SharedBufferDispatcher : public SimpleDispatcher {
+ public:
+  // Validates and/or sets default options. If non-null, |in_options| must point
+  // to a struct of at least |in_options->struct_size| bytes. |out_options| must
+  // point to a (current) |MojoCreateSharedBufferOptions| and will be entirely
+  // overwritten on success (it may be partly overwritten on failure).
+  static MojoResult ValidateOptions(
+      const MojoCreateSharedBufferOptions* in_options,
+      MojoCreateSharedBufferOptions* out_options);
+
+  // Static factory method: |validated_options| must be validated (obviously).
+  // On failure, |*result| will be left as-is.
+  static MojoResult Create(
+      const MojoCreateSharedBufferOptions& validated_options,
+      uint64_t num_bytes,
+      scoped_refptr<SharedBufferDispatcher>* result);
+
+  // |Dispatcher| public methods:
+  virtual Type GetType() const OVERRIDE;
+
+ private:
+  explicit SharedBufferDispatcher(
+      scoped_refptr<RawSharedBuffer> shared_buffer_);
+  virtual ~SharedBufferDispatcher();
+
+  // |Dispatcher| protected methods:
+  virtual void CloseImplNoLock() OVERRIDE;
+  virtual scoped_refptr<Dispatcher>
+      CreateEquivalentDispatcherAndCloseImplNoLock() OVERRIDE;
+  virtual MojoResult DuplicateBufferHandleImplNoLock(
+      const MojoDuplicateBufferHandleOptions* options,
+      scoped_refptr<Dispatcher>* new_dispatcher) OVERRIDE;
+  virtual MojoResult MapBufferImplNoLock(
+      uint64_t offset,
+      uint64_t num_bytes,
+      MojoMapBufferFlags flags,
+      scoped_ptr<RawSharedBuffer::Mapping>* mapping) OVERRIDE;
+
+  // |SimpleDispatcher| methods:
+  virtual MojoWaitFlags SatisfiedFlagsNoLock() const OVERRIDE;
+  virtual MojoWaitFlags SatisfiableFlagsNoLock() const OVERRIDE;
+
+  scoped_refptr<RawSharedBuffer> shared_buffer_;
+
+  DISALLOW_COPY_AND_ASSIGN(SharedBufferDispatcher);
+};
+
+}  // namespace system
+}  // namespace mojo
+
+#endif  // MOJO_SYSTEM_SHARED_BUFFER_DISPATCHER_H_
diff --git a/mojo/system/shared_buffer_dispatcher_unittest.cc b/mojo/system/shared_buffer_dispatcher_unittest.cc
new file mode 100644
index 0000000..ecd055c
--- /dev/null
+++ b/mojo/system/shared_buffer_dispatcher_unittest.cc
@@ -0,0 +1,222 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "mojo/system/shared_buffer_dispatcher.h"
+
+#include <limits>
+
+#include "base/memory/ref_counted.h"
+#include "mojo/system/dispatcher.h"
+#include "mojo/system/raw_shared_buffer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace system {
+namespace {
+
+// NOTE(vtl): There's currently not much to test for in
+// |SharedBufferDispatcher::ValidateOptions()|, but the tests should be expanded
+// if/when options are added, so I've kept the general form of the tests from
+// data_pipe_unittest.cc.
+
+const uint32_t kSizeOfOptions =
+    static_cast<uint32_t>(sizeof(MojoCreateSharedBufferOptions));
+
+// Does a cursory sanity check of |validated_options|. Calls |ValidateOptions()|
+// on already-validated options. The validated options should be valid, and the
+// revalidated copy should be the same.
+void RevalidateOptions(const MojoCreateSharedBufferOptions& validated_options) {
+  EXPECT_EQ(kSizeOfOptions, validated_options.struct_size);
+  // Nothing to check for flags.
+
+  MojoCreateSharedBufferOptions revalidated_options = { 0 };
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::ValidateOptions(&validated_options,
+                                                    &revalidated_options));
+  EXPECT_EQ(validated_options.struct_size, revalidated_options.struct_size);
+  EXPECT_EQ(validated_options.flags, revalidated_options.flags);
+}
+
+// Tests valid inputs to |ValidateOptions()|.
+TEST(SharedBufferDispatcherTest, ValidateOptionsValidInputs) {
+  // Default options.
+  {
+    MojoCreateSharedBufferOptions validated_options = { 0 };
+    EXPECT_EQ(MOJO_RESULT_OK,
+              SharedBufferDispatcher::ValidateOptions(NULL,
+                                                      &validated_options));
+    RevalidateOptions(validated_options);
+  }
+
+  // Different flags.
+  MojoCreateSharedBufferOptionsFlags flags_values[] = {
+    MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE
+  };
+  for (size_t i = 0; i < arraysize(flags_values); i++) {
+    const MojoCreateSharedBufferOptionsFlags flags = flags_values[i];
+
+    // Different capacities (size 1).
+    for (uint32_t capacity = 1; capacity <= 100 * 1000 * 1000; capacity *= 10) {
+      MojoCreateSharedBufferOptions options = {
+        kSizeOfOptions,  // |struct_size|.
+        flags  // |flags|.
+      };
+      MojoCreateSharedBufferOptions validated_options = { 0 };
+      EXPECT_EQ(MOJO_RESULT_OK,
+                SharedBufferDispatcher::ValidateOptions(&options,
+                                                        &validated_options))
+          << capacity;
+      RevalidateOptions(validated_options);
+    }
+  }
+}
+
+TEST(SharedBufferDispatcherTest, ValidateOptionsInvalidInputs) {
+  // Invalid |struct_size|.
+  // Note: If/when we extend |MojoCreateSharedBufferOptions|, this will have to
+  // be updated.
+  for (uint32_t struct_size = 0; struct_size < kSizeOfOptions; struct_size++) {
+    MojoCreateSharedBufferOptions options = {
+      struct_size,  // |struct_size|.
+      MOJO_CREATE_SHARED_BUFFER_OPTIONS_FLAG_NONE  // |flags|.
+    };
+    MojoCreateSharedBufferOptions unused = { 0 };
+    EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+              SharedBufferDispatcher::ValidateOptions(&options, &unused));
+  }
+}
+
+TEST(SharedBufferDispatcherTest, CreateAndMapBuffer) {
+  MojoCreateSharedBufferOptions validated_options = { 0 };
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::ValidateOptions(NULL,
+                                                    &validated_options));
+
+  scoped_refptr<SharedBufferDispatcher> dispatcher;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::Create(validated_options, 100,
+                                           &dispatcher));
+  ASSERT_TRUE(dispatcher);
+  EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher->GetType());
+
+  // Make a couple of mappings.
+  scoped_ptr<RawSharedBuffer::Mapping> mapping1;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dispatcher->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE,
+                                  &mapping1));
+  ASSERT_TRUE(mapping1);
+  ASSERT_TRUE(mapping1->base());
+  EXPECT_EQ(100u, mapping1->length());
+  // Write something.
+  static_cast<char*>(mapping1->base())[50] = 'x';
+
+  scoped_ptr<RawSharedBuffer::Mapping> mapping2;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dispatcher->MapBuffer(50, 50, MOJO_MAP_BUFFER_FLAG_NONE,
+                                  &mapping2));
+  ASSERT_TRUE(mapping2);
+  ASSERT_TRUE(mapping2->base());
+  EXPECT_EQ(50u, mapping2->length());
+  EXPECT_EQ('x', static_cast<char*>(mapping2->base())[0]);
+
+  EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
+
+  // Check that we can still read/write to mappings after the dispatcher has
+  // gone away.
+  static_cast<char*>(mapping2->base())[1] = 'y';
+  EXPECT_EQ('y', static_cast<char*>(mapping1->base())[51]);
+}
+
+TEST(SharedBufferDispatcher, DuplicateBufferHandle) {
+  MojoCreateSharedBufferOptions validated_options = { 0 };
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::ValidateOptions(NULL,
+                                                    &validated_options));
+
+  scoped_refptr<SharedBufferDispatcher> dispatcher1;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::Create(validated_options, 100,
+                                           &dispatcher1));
+
+  // Map and write something.
+  scoped_ptr<RawSharedBuffer::Mapping> mapping;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dispatcher1->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE,
+                                   &mapping));
+  static_cast<char*>(mapping->base())[0] = 'x';
+  mapping.reset();
+
+  // Duplicate |dispatcher1| and then close it.
+  scoped_refptr<Dispatcher> dispatcher2;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dispatcher1->DuplicateBufferHandle(NULL, &dispatcher2));
+  ASSERT_TRUE(dispatcher2);
+  EXPECT_EQ(Dispatcher::kTypeSharedBuffer, dispatcher2->GetType());
+
+  EXPECT_EQ(MOJO_RESULT_OK, dispatcher1->Close());
+
+  // Map |dispatcher2| and read something.
+  EXPECT_EQ(MOJO_RESULT_OK,
+            dispatcher2->MapBuffer(0, 100, MOJO_MAP_BUFFER_FLAG_NONE,
+                                   &mapping));
+  EXPECT_EQ('x', static_cast<char*>(mapping->base())[0]);
+
+  EXPECT_EQ(MOJO_RESULT_OK, dispatcher2->Close());
+}
+
+// TODO(vtl): Test |DuplicateBufferHandle()| with non-null (valid) |options|.
+
+TEST(SharedBufferDispatcherTest, CreateInvalidNumBytes) {
+  MojoCreateSharedBufferOptions validated_options = { 0 };
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::ValidateOptions(NULL,
+                                                    &validated_options));
+
+  // Size too big.
+  scoped_refptr<SharedBufferDispatcher> dispatcher;
+  EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
+            SharedBufferDispatcher::Create(validated_options,
+                                           std::numeric_limits<uint64_t>::max(),
+                                           &dispatcher));
+  EXPECT_FALSE(dispatcher);
+
+  // Zero size.
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            SharedBufferDispatcher::Create(validated_options, 0, &dispatcher));
+  EXPECT_FALSE(dispatcher);
+}
+
+TEST(SharedBufferDispatcherTest, MapBufferInvalidArguments) {
+  MojoCreateSharedBufferOptions validated_options = { 0 };
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::ValidateOptions(NULL,
+                                                    &validated_options));
+
+  scoped_refptr<SharedBufferDispatcher> dispatcher;
+  EXPECT_EQ(MOJO_RESULT_OK,
+            SharedBufferDispatcher::Create(validated_options, 100,
+                                           &dispatcher));
+
+  scoped_ptr<RawSharedBuffer::Mapping> mapping;
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            dispatcher->MapBuffer(0, 101, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+  EXPECT_FALSE(mapping);
+
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            dispatcher->MapBuffer(1, 100, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+  EXPECT_FALSE(mapping);
+
+  EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
+            dispatcher->MapBuffer(0, 0, MOJO_MAP_BUFFER_FLAG_NONE, &mapping));
+  EXPECT_FALSE(mapping);
+
+  EXPECT_EQ(MOJO_RESULT_OK, dispatcher->Close());
+}
+
+// TODO(vtl): Test |DuplicateBufferHandle()| with invalid |options|.
+
+}  // namespace
+}  // namespace system
+}  // namespace mojo
+
diff --git a/mojo/system/simple_dispatcher.h b/mojo/system/simple_dispatcher.h
index 0ad49ac..d2934fa 100644
--- a/mojo/system/simple_dispatcher.h
+++ b/mojo/system/simple_dispatcher.h
@@ -22,8 +22,6 @@
 class MOJO_SYSTEM_IMPL_EXPORT SimpleDispatcher : public Dispatcher {
  protected:
   SimpleDispatcher();
-
-  friend class base::RefCountedThreadSafe<SimpleDispatcher>;
   virtual ~SimpleDispatcher();
 
   // To be called by subclasses when the state changes (so
@@ -39,7 +37,7 @@
   virtual MojoWaitFlags SatisfiedFlagsNoLock() const = 0;
   virtual MojoWaitFlags SatisfiableFlagsNoLock() const = 0;
 
-  // |Dispatcher| implementation/overrides:
+  // |Dispatcher| protected methods:
   virtual void CancelAllWaitersNoLock() OVERRIDE;
   virtual MojoResult AddWaiterImplNoLock(Waiter* waiter,
                                          MojoWaitFlags flags,
diff --git a/mojo/system/waiter.h b/mojo/system/waiter.h
index 2de581b..dd5b59d 100644
--- a/mojo/system/waiter.h
+++ b/mojo/system/waiter.h
@@ -8,7 +8,7 @@
 #include "base/basictypes.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/system_impl_export.h"
 
 namespace mojo {
diff --git a/mojo/system/waiter_list.h b/mojo/system/waiter_list.h
index a14804b..1d35b94 100644
--- a/mojo/system/waiter_list.h
+++ b/mojo/system/waiter_list.h
@@ -8,7 +8,7 @@
 #include <list>
 
 #include "base/basictypes.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/system_impl_export.h"
 
 namespace mojo {
diff --git a/mojo/system/waiter_test_utils.h b/mojo/system/waiter_test_utils.h
index b1a7a33..00475ef 100644
--- a/mojo/system/waiter_test_utils.h
+++ b/mojo/system/waiter_test_utils.h
@@ -9,7 +9,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/threading/simple_thread.h"
-#include "mojo/public/system/core.h"
+#include "mojo/public/c/system/core.h"
 #include "mojo/system/dispatcher.h"
 #include "mojo/system/waiter.h"
 
diff --git a/mojo/tools/data/unittests b/mojo/tools/data/unittests
new file mode 100644
index 0000000..4ec0b29
--- /dev/null
+++ b/mojo/tools/data/unittests
@@ -0,0 +1,16 @@
+# This file contains a list of Mojo gtest unit tests.
+
+# System tests:
+mojo_system_unittests
+
+# Public tests:
+mojo_public_bindings_unittests
+mojo_public_environment_unittests
+mojo_public_system_unittests
+mojo_public_utility_unittests
+
+# Non-system, non-public tests:
+mojo_apps_js_unittests
+mojo_common_unittests
+mojo_js_unittests
+mojo_service_manager_unittests
diff --git a/mojo/tools/mojob.sh b/mojo/tools/mojob.sh
index 7d887e7..7cf4066 100755
--- a/mojo/tools/mojob.sh
+++ b/mojo/tools/mojob.sh
@@ -50,15 +50,8 @@
 
 do_unittests() {
   echo "Running unit tests in out/$1 ..."
-  "out/$1/mojo_common_unittests" || exit 1
-  "out/$1/mojo_apps_js_unittests" || exit 1
-  "out/$1/mojo_js_unittests" || exit 1
-  "out/$1/mojo_public_bindings_unittests" || exit 1
-  "out/$1/mojo_public_environment_unittests" || exit 1
-  "out/$1/mojo_public_system_unittests" || exit 1
-  "out/$1/mojo_public_utility_unittests" || exit 1
-  "out/$1/mojo_service_manager_unittests" || exit 1
-  "out/$1/mojo_system_unittests" || exit 1
+  mojo/tools/test_runner.py mojo/tools/data/unittests "out/$1" \
+      mojob_test_successes || exit 1
 }
 
 do_perftests() {
diff --git a/mojo/tools/pylib/transitive_hash.py b/mojo/tools/pylib/transitive_hash.py
new file mode 100644
index 0000000..93e8dc4
--- /dev/null
+++ b/mojo/tools/pylib/transitive_hash.py
@@ -0,0 +1,89 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import subprocess
+import sys
+
+from hashlib import sha256
+from os.path import basename, realpath
+
+_logging = logging.getLogger()
+
+# Based on/taken from
+#   http://code.activestate.com/recipes/578231-probably-the-fastest-memoization-decorator-in-the-/
+# (with cosmetic changes).
+def _memoize(f):
+  """Memoization decorator for a function taking a single argument."""
+  class Memoize(dict):
+    def __missing__(self, key):
+      rv = self[key] = f(key)
+      return rv
+  return Memoize().__getitem__
+
+@_memoize
+def _file_hash(filename):
+  """Returns a string representing the hash of the given file."""
+  _logging.debug("Hashing %s ...", filename)
+  rv = subprocess.check_output(['sha256sum', '-b', filename]).split(None, 1)[0]
+  _logging.debug("  => %s", rv)
+  return rv
+
+@_memoize
+def _get_dependencies(filename):
+  """Returns a list of filenames for files that the given file depends on."""
+  _logging.debug("Getting dependencies for %s ...", filename)
+  lines = subprocess.check_output(['ldd', filename]).splitlines()
+  rv = []
+  for line in lines:
+    i = line.find('/')
+    if i < 0:
+      _logging.debug("  => no file found in line: %s", line)
+      continue
+    rv.append(line[i:].split(None, 1)[0])
+  _logging.debug("  => %s", rv)
+  return rv
+
+def transitive_hash(filename):
+  """Returns a string that represents the "transitive" hash of the given
+  file. The transitive hash is a hash of the file and all the shared libraries
+  on which it depends (done in an order-independent way)."""
+  hashes = set()
+  to_hash = [filename]
+  while to_hash:
+    current_filename = realpath(to_hash.pop())
+    current_hash = _file_hash(current_filename)
+    if current_hash in hashes:
+      _logging.debug("Already seen %s (%s) ...", current_filename, current_hash)
+      continue
+    _logging.debug("Haven't seen %s (%s) ...", current_filename, current_hash)
+    hashes.add(current_hash)
+    to_hash.extend(_get_dependencies(current_filename))
+  return sha256('|'.join(sorted(hashes))).hexdigest()
+
+def main(argv):
+  logging.basicConfig()
+  # Uncomment to debug:
+  # _logging.setLevel(logging.DEBUG)
+
+  if len(argv) < 2:
+    print """\
+Usage: %s [file] ...
+
+Prints the \"transitive\" hash of each (executable) file. The transitive
+hash is a hash of the file and all the shared libraries on which it
+depends (done in an order-independent way).""" % basename(argv[0])
+    return 0
+
+  rv = 0
+  for filename in argv[1:]:
+    try:
+      print transitive_hash(filename), filename
+    except:
+      print "ERROR", filename
+      rv = 1
+  return rv
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/mojo/tools/test_runner.py b/mojo/tools/test_runner.py
new file mode 100755
index 0000000..4455235
--- /dev/null
+++ b/mojo/tools/test_runner.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A "smart" test runner for gtest unit tests (that caches successes)."""
+
+import logging
+import os
+import subprocess
+import sys
+
+_logging = logging.getLogger()
+
+_script_dir = os.path.dirname(os.path.realpath(__file__))
+sys.path.insert(0, os.path.join(_script_dir, "pylib"))
+
+from transitive_hash import transitive_hash
+
+def main(argv):
+  logging.basicConfig()
+  # Uncomment to debug:
+  # _logging.setLevel(logging.DEBUG)
+
+  if len(argv) < 3 or len(argv) > 4:
+    print "Usage: %s gtest_list_file root_dir [successes_cache_file]" % \
+        os.path.basename(argv[0])
+    return 0 if len(argv) < 2 else 1
+
+  _logging.debug("Test list file: %s", argv[1])
+  with open(argv[1], 'rb') as f:
+    gtest_list = [y for y in [x.strip() for x in f.readlines()] \
+                      if y and y[0] != '#']
+  _logging.debug("Test list: %s" % gtest_list)
+
+  print "Running tests in directory: %s" % argv[2]
+  os.chdir(argv[2])
+
+  if len(argv) == 4 and argv[3]:
+    successes_cache_filename = argv[3]
+    print "Successes cache file: %s" % successes_cache_filename
+  else:
+    successes_cache_filename = None
+    print "No successes cache file (will run all tests unconditionally)"
+
+  if successes_cache_filename:
+    # This file simply contains a list of transitive hashes of tests that
+    # succeeded.
+    try:
+      _logging.debug("Trying to read successes cache file: %s",
+                     successes_cache_filename)
+      with open(argv[3], 'rb') as f:
+        successes = set([x.strip() for x in f.readlines()])
+      _logging.debug("Successes: %s", successes)
+    except:
+      # Just assume that it didn't exist, or whatever.
+      print "Failed to read successes cache file %s (will create)" % argv[3]
+      successes = set()
+
+  # Run gtests with color if we're on a TTY (and we're not being told explicitly
+  # what to do).
+  if sys.stdout.isatty() and 'GTEST_COLOR' not in os.environ:
+    _logging.debug("Setting GTEST_COLOR=yes")
+    os.environ['GTEST_COLOR'] = 'yes'
+
+  # TODO(vtl): We may not close this file on failure.
+  successes_cache_file = open(successes_cache_filename, 'ab') \
+      if successes_cache_filename else None
+  for gtest in gtest_list:
+    if successes_cache_file:
+      _logging.debug("Getting transitive hash for %s ... " % gtest)
+      try:
+        gtest_hash = transitive_hash(gtest)
+      except:
+        print "Failed to get transitive hash for %s" % gtest
+        return 1
+      _logging.debug("  Transitive hash: %s" % gtest_hash)
+
+      if gtest_hash in successes:
+        print "Skipping %s (previously succeeded)" % gtest
+        continue
+
+    print "Running %s ..." % gtest
+    try:
+      subprocess.check_output(["./" + gtest], stderr=subprocess.STDOUT)
+      print "  Succeeded"
+      # Record success.
+      if successes_cache_filename:
+        successes.add(gtest_hash)
+        successes_cache_file.write(gtest_hash + '\n')
+        successes_cache_file.flush()
+    except subprocess.CalledProcessError as e:
+      print "  Failed with exit code %d and output:" % e.returncode
+      print 72 * '-'
+      print e.output
+      print 72 * '-'
+      return 1
+    except OSError as e:
+      print "  Failed to start test"
+      return 1
+  print "All tests succeeded"
+  if successes_cache_file:
+    successes_cache_file.close()
+
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/native_client_sdk/doc_generated/devguide/devcycle/debugging.html b/native_client_sdk/doc_generated/devguide/devcycle/debugging.html
index 696ca55..cdad0ee 100644
--- a/native_client_sdk/doc_generated/devguide/devcycle/debugging.html
+++ b/native_client_sdk/doc_generated/devguide/devcycle/debugging.html
@@ -7,34 +7,35 @@
 <div class="contents local" id="table-of-contents" style="display: none">
 <p class="topic-title first">Table Of Contents</p>
 <ul class="small-gap">
-<li><p class="first"><a class="reference internal" href="#diagnostic-information" id="id1">Diagnostic information</a></p>
+<li><p class="first"><a class="reference internal" href="#diagnostic-information" id="id2">Diagnostic information</a></p>
 <ul class="small-gap">
-<li><a class="reference internal" href="#viewing-process-statistics-with-the-task-manager" id="id2">Viewing process statistics with the task manager</a></li>
-<li><a class="reference internal" href="#controlling-the-level-of-native-client-error-and-warning-messages" id="id3">Controlling the level of Native Client error and warning messages</a></li>
+<li><a class="reference internal" href="#viewing-process-statistics-with-the-task-manager" id="id3">Viewing process statistics with the task manager</a></li>
+<li><a class="reference internal" href="#controlling-the-level-of-native-client-error-and-warning-messages" id="id4">Controlling the level of Native Client error and warning messages</a></li>
 </ul>
 </li>
-<li><p class="first"><a class="reference internal" href="#basic-debugging" id="id4">Basic debugging</a></p>
+<li><p class="first"><a class="reference internal" href="#basic-debugging" id="id5">Basic debugging</a></p>
 <ul class="small-gap">
-<li><a class="reference internal" href="#writing-messages-to-the-javascript-console" id="id5">Writing messages to the JavaScript console</a></li>
-<li><p class="first"><a class="reference internal" href="#debugging-with-printf" id="id6">Debugging with printf</a></p>
+<li><a class="reference internal" href="#writing-messages-to-the-javascript-console" id="id6">Writing messages to the JavaScript console</a></li>
+<li><p class="first"><a class="reference internal" href="#debugging-with-printf" id="id7">Debugging with printf</a></p>
 <ul class="small-gap">
-<li><a class="reference internal" href="#redirecting-output-to-log-files" id="id7">Redirecting output to log files</a></li>
-<li><a class="reference internal" href="#redirecting-output-to-the-javascript-console" id="id8">Redirecting output to the JavaScript console</a></li>
+<li><a class="reference internal" href="#redirecting-output-to-log-files" id="id8">Redirecting output to log files</a></li>
+<li><a class="reference internal" href="#redirecting-output-to-the-javascript-console" id="id9">Redirecting output to the JavaScript console</a></li>
 </ul>
 </li>
-<li><a class="reference internal" href="#logging-calls-to-pepper-interfaces" id="id9">Logging calls to Pepper interfaces</a></li>
-<li><a class="reference internal" href="#debugging-with-visual-studio" id="id10">Debugging with Visual Studio</a></li>
-<li><p class="first"><a class="reference internal" href="#debugging-with-nacl-gdb" id="id11">Debugging with nacl-gdb</a></p>
+<li><a class="reference internal" href="#logging-calls-to-pepper-interfaces" id="id10">Logging calls to Pepper interfaces</a></li>
+<li><a class="reference internal" href="#debugging-with-visual-studio" id="id11">Debugging with Visual Studio</a></li>
+<li><p class="first"><a class="reference internal" href="#debugging-with-nacl-gdb" id="id12">Debugging with nacl-gdb</a></p>
 <ul class="small-gap">
-<li><a class="reference internal" href="#debugging-pnacl-pexes" id="id12">Debugging PNaCl pexes</a></li>
-<li><a class="reference internal" href="#running-nacl-gdb" id="id13">Running nacl-gdb</a></li>
+<li><a class="reference internal" href="#debugging-pnacl-pexes-with-pepper-35" id="id13">Debugging PNaCl pexes (with Pepper 35+)</a></li>
+<li><a class="reference internal" href="#debugging-pnacl-pexes-with-older-pepper-toolchains" id="id14">Debugging PNaCl pexes (with older Pepper toolchains)</a></li>
+<li><a class="reference internal" href="#running-nacl-gdb" id="id15">Running nacl-gdb</a></li>
 </ul>
 </li>
 </ul>
 </li>
-<li><p class="first"><a class="reference internal" href="#debugging-with-other-tools" id="id14">Debugging with other tools</a></p>
+<li><p class="first"><a class="reference internal" href="#debugging-with-other-tools" id="id16">Debugging with other tools</a></p>
 <ul class="small-gap">
-<li><a class="reference internal" href="#open-source-profiling-tools" id="id15">Open source profiling tools</a></li>
+<li><a class="reference internal" href="#open-source-profiling-tools" id="id17">Open source profiling tools</a></li>
 </ul>
 </li>
 </ul>
@@ -209,17 +210,61 @@
 whether built using newlib or glibc for x86-32, x86-64 or ARM.  In the SDK,
 <code>i686-nacl-gdb</code> is an alias for <code>x86_64-nacl-gdb</code>, and the <code>newlib</code>
 and <code>glibc</code> toolchains both contain the same version of GDB.</p>
-<section id="debugging-pnacl-pexes">
-<h4 id="debugging-pnacl-pexes">Debugging PNaCl pexes</h4>
+<section id="debugging-pnacl-pexes-with-pepper-35">
+<h4 id="debugging-pnacl-pexes-with-pepper-35">Debugging PNaCl pexes (with Pepper 35+)</h4>
 <p>If you want to use GDB to debug a program that is compiled with the PNaCl
-toolchain, you must convert the <code>pexe</code> file to a <code>nexe</code>.  (You can skip
-this step if you are using the GCC toolchain.)</p>
-<ul class="small-gap">
-<li>Firstly, make sure you are passing the <code>-g</code> <a class="reference internal" href="/native-client/devguide/devcycle/building.html#compile-flags"><em>compile option</em></a> to <code>pnacl-clang</code> to enable generating debugging info.
+toolchain, you must have a copy of the pexe from <strong>before</strong> running
+<code>pnacl-finalize</code>. The <code>pnacl-finalize</code> tool converts LLVM bitcode
+to the stable PNaCl bitcode format, but it also strips out debug
+metadata, which we need for debugging.</p>
+<p><strong>Note</strong> unlike the finalized copy of the pexe, the non-finalized debug copy
+is not considered stable. This means that a debug copy of the PNaCl
+application created by a Pepper N SDK is only guaranteed to run
+with a matching Chrome version N. If the version of the debug bitcode pexe
+does not match that of Chrome then the translation process may fail, and
+you will see and error message in the JavaScript console.</p>
+<p>Also, make sure you are passing the <code>-g</code> <a class="reference internal" href="/native-client/devguide/devcycle/building.html#compile-flags"><em>compile option</em></a> to <code>pnacl-clang</code> to enable generating debugging info.
 You might also want to omit <code>-O2</code> from the compile-time and link-time
 options, otherwise GDB not might be able to print variables&#8217; values when
 debugging (this is more of a problem with the PNaCl/LLVM toolchain than
-with GCC).</li>
+with GCC).</p>
+<p>Once you have built a non-stable debug copy of the pexe, list the URL of
+that copy in your application&#8217;s manifest file:</p>
+<pre class="prettyprint">
+{
+  &quot;program&quot;: {
+    &quot;pnacl-translate&quot;: {
+      &quot;url&quot;: &quot;release_version.pexe&quot;,
+      &quot;optlevel&quot;: 2
+    },
+    &quot;pnacl-debug&quot;: {
+      &quot;url&quot;: &quot;debug_version.bc&quot;,
+      &quot;optlevel&quot;: 0
+    }
+  }
+}
+</pre>
+<p>Copy the <code>debug_version.bc</code> and <code>nmf</code> files to the location that
+your local web server serves files from.</p>
+<p>When you run Chrome with <code>--enable-nacl-debug</code>, Chrome will translate
+and run the <code>debug_version.bc</code> instead of <code>release_version.pexe</code>.
+Once the debug version is loaded, you are ready to <a class="reference internal" href="#running-nacl-gdb"><em>run nacl-gdb</em></a></p>
+<p>Whether you publish the NMF file containing the debug URL to the release
+web server, is up to you. One reason to avoid publishing the debug URL
+is that it is only guaranteed to work for the Chrome version that matches
+the SDK version. Developers who may have left the <code>--enable-nacl-debug</code>
+flag turned on may end up loading the debug copy of your application
+(which may or may not work, depending on their version of Chrome).</p>
+</section><section id="debugging-pnacl-pexes-with-older-pepper-toolchains">
+<h4 id="debugging-pnacl-pexes-with-older-pepper-toolchains">Debugging PNaCl pexes (with older Pepper toolchains)</h4>
+<p>If you want to use GDB to debug a program that is compiled with the PNaCl
+toolchain, you must convert the <code>pexe</code> file to a <code>nexe</code>.  (You can skip
+this step if you are using the GCC toolchain, or if you are using
+pepper 35 or later.)</p>
+<ul class="small-gap">
+<li>Firstly, make sure you are passing the <code>-g</code> <a class="reference internal" href="/native-client/devguide/devcycle/building.html#compile-flags"><em>compile option</em></a> to <code>pnacl-clang</code> to enable generating debugging info.
+You might also want to omit <code>-O2</code> from the compile-time and link-time
+options.</li>
 <li><p class="first">Secondly, use <code>pnacl-translate</code> to convert your <code>pexe</code> to one or more
 <code>nexe</code> files.  For example:</p>
 <pre>
@@ -260,7 +305,7 @@
 formats as described above.
 </aside>
 </section><section id="running-nacl-gdb">
-<h4 id="running-nacl-gdb">Running nacl-gdb</h4>
+<span id="id1"></span><h4 id="running-nacl-gdb"><span id="id1"></span>Running nacl-gdb</h4>
 <p>Before you start using nacl-gdb, make sure you can <a class="reference internal" href="/native-client/devguide/devcycle/building.html"><em>build</em></a> your
 module and <a class="reference internal" href="/native-client/devguide/devcycle/running.html"><em>run</em></a> your application normally. This will verify
 that you have created all the required <a class="reference internal" href="/native-client/devguide/coding/application-structure.html"><em>application parts</em></a> (.html, .nmf, and .nexe files, shared
@@ -312,6 +357,18 @@
 not affect your personal Chrome data (history, cookies, bookmarks, themes,
 and settings).</p>
 </dd>
+<dt><code>--nacl-debug-mask=&lt;nmf_url_mask1,nmf_url_mask2,...&gt;</code></dt>
+<dd><p class="first last">Specifies a set of debug mask patterns. This allows you to selectively
+choose to debug certain applications and not debug others. For example,
+if you only want to debug the NMF files for your applications at
+<code>https://example.com/app</code>, and no other NaCl applications found
+on the web, specify <code>--nacl-debug-mask=https://example.com/app/*.nmf</code>.
+This helps prevent accidentally debugging other NaCl applications if
+you like to leave the <code>--enable-nacl-debug</code> flag turned on.
+The pattern language for the mask follows <a class="reference external" href="http://developer.chrome.com/extensions/match_patterns">chrome extension match patterns</a>.
+The pattern set can be inverted by prefixing the pattern set with
+the <code>!</code> character.</p>
+</dd>
 <dt><code>&lt;URL&gt;</code></dt>
 <dd><p class="first last">Specifies the URL Chrome should open when it launches. The local server
 that comes with the SDK listens on port 5103 by default, so the URL when
@@ -337,33 +394,62 @@
 (gdb)
 </pre>
 </li>
-<li><p class="first">Run the following three commands from the gdb command line:</p>
+<li><p class="first">For debugging PNaCl pexes run the following gdb command lines
+(skip to the next item if you are using NaCl instead of PNaCl):</p>
 <pre class="prettyprint">
-(gdb) nacl-manifest &lt;path-to-your-.nmf-file&gt;
-(gdb) nacl-irt &lt;path-to-Chrome-NaCl-integrated-runtime&gt;
 (gdb) target remote localhost:4014
+(gdb) remote get nexe &lt;path-to-save-translated-nexe-with-debug-info&gt;
+(gdb) file &lt;path-to-save-translated-nexe-with-debug-info&gt;
+(gdb) remote get irt &lt;path-to-save-NaCl-integrated-runtime&gt;
+(gdb) nacl-irt &lt;path-to-saved-NaCl-integrated-runtime&gt;
 </pre>
-<p>These commands are described below:</p>
+</li>
+<li><p class="first">For NaCl nexes, run the following commands from the gdb command line:</p>
+<pre class="prettyprint">
+(gdb) target remote localhost:4014
+(gdb) nacl-manifest &lt;path-to-your-.nmf-file&gt;
+(gdb) remote get irt &lt;path-to-save-NaCl-integrated-runtime&gt;
+(gdb) nacl-irt &lt;path-to-saved-NaCl-integrated-runtime&gt;
+</pre>
+</li>
+<li><p class="first">The command used for PNaCl and NaCl are described below:</p>
 <dl class="docutils">
-<dt><code>nacl-manifest &lt;path&gt;</code></dt>
-<dd><p class="first last">Tells the debugger about your Native Client application by pointing it to
-the application&#8217;s manifest (.nmf) file. The manifest file lists your
-application&#8217;s executable (.nexe) files, as well as any libraries that are
-linked with the application dynamically.</p>
-</dd>
-<dt><code>nacl-irt &lt;path&gt;</code></dt>
-<dd><p class="first last">Tells the debugger where to find the Native Client Integrated Runtime
-(IRT). The IRT is located in the same directory as the Chrome executable,
-or in a subdirectory named after the Chrome version. For example, if
-you&#8217;re running Chrome canary on Windows, the path to the IRT typically
-looks something like <code>C:/Users/&lt;username&gt;/AppData/Local/Google/Chrome
-SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe</code>.</p>
-</dd>
 <dt><code>target remote localhost:4014</code></dt>
 <dd><p class="first last">Tells the debugger how to connect to the debug stub in the Native Client
 application loader. This connection occurs through TCP port 4014 (note
 that this port is distinct from the port which the local web server uses
-to listen for incoming requests, typically port 5103).</p>
+to listen for incoming requests, typically port 5103). If you are
+debugging multiple applications at the same time, the loader may choose
+a port that is different from the default 4014 port. See the Chrome
+task manager for the debug port.</p>
+</dd>
+<dt><code>remote get nexe &lt;path&gt;</code></dt>
+<dd><p class="first last">This saves the application&#8217;s main executable (nexe) to <code>&lt;path&gt;</code>.
+For PNaCl, this provides a convenient way to access the nexe that is
+a <strong>result</strong> of translating your pexe. This can then be loaded with
+the <code>file &lt;path&gt;</code> command.</p>
+</dd>
+<dt><code>nacl-manifest &lt;path&gt;</code></dt>
+<dd><p class="first last">For NaCl (not PNaCl), this tells the debugger where to find your
+application&#8217;s executable (.nexe) files. The application&#8217;s manifest
+(.nmf) file lists your application&#8217;s executable files, as well as any
+libraries that are linked with the application dynamically.</p>
+</dd>
+<dt><code>remote get irt &lt;path&gt;</code></dt>
+<dd><p class="first last">This saves the Native Client Integrated Runtime (IRT). Normally,
+the IRT is located in the same directory as the Chrome executable,
+or in a subdirectory named after the Chrome version. For example, if
+you&#8217;re running Chrome canary on Windows, the path to the IRT typically
+looks something like <code>C:/Users/&lt;username&gt;/AppData/Local/Google/Chrome
+SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe</code>.
+The <code>remote get irt &lt;path&gt;</code> saves that to the current working
+directory so that you do not need to find where exactly the IRT
+is stored alongside Chrome.</p>
+</dd>
+<dt><code>nacl-irt &lt;path&gt;</code></dt>
+<dd><p class="first last">Tells the debugger where to find the Native Client Integrated Runtime
+(IRT). <code>&lt;path&gt;</code> can either be the location of the copy saved by
+<code>remote get irt &lt;path&gt;</code> or the copy that is installed alongside Chrome.</p>
 </dd>
 </dl>
 <p>A couple of notes on how to specify path names in the nacl-gdb commands
@@ -381,9 +467,9 @@
 <p>As an example, here is a what these nacl-gdb commands might look like on
 Windows:</p>
 <pre class="prettyprint">
+target remote localhost:4014
 nacl-manifest &quot;C:/&lt;NACL_SDK_ROOT&gt;/examples/hello_world_gles/newlib/Debug/hello_world_gles.nmf&quot;
 nacl-irt &quot;C:/Users/&lt;username&gt;/AppData/Local/Google/Chrome SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe&quot;
-target remote localhost:4014
 </pre>
 <p>To save yourself some typing, you can put put these nacl-gdb commands in a
 script file, and execute the file when you run nacl-gdb, like so:</p>
diff --git a/native_client_sdk/doc_generated/reference/nacl-manifest-format.html b/native_client_sdk/doc_generated/reference/nacl-manifest-format.html
index 8165c0c..d35f416 100644
--- a/native_client_sdk/doc_generated/reference/nacl-manifest-format.html
+++ b/native_client_sdk/doc_generated/reference/nacl-manifest-format.html
@@ -63,7 +63,15 @@
   &quot;program&quot;: {
     &quot;pnacl-translate&quot;: {
       // url is required
-      &quot;url&quot;: &quot;url_to_my_pexe&quot;
+      &quot;url&quot;: &quot;url_to_my_pexe&quot;,
+
+      // optlevel is optional
+      &quot;optlevel&quot;: 2
+    },
+    // pnacl-debug is optional
+    &quot;pnacl-debug&quot;: {
+      // url is required
+      &quot;url&quot;: &quot;url_to_my_bitcode_bc&quot;,
 
       // optlevel is optional
       &quot;optlevel&quot;: 0
@@ -82,6 +90,10 @@
 of <code>0</code>. Note that <code>optlevel</code> is only a <em>hint</em>. In the future, the
 Portable Native Client translator and runtime may <em>automatically</em> choose
 an <code>optlevel</code> to best balance load time and application performance.</p>
+<p>A <code>pnacl-debug</code> section can specify an unfinalized pnacl llvm bitcode file
+for debugging. The <code>url</code> provided in this section will be used when Native
+Client debugging is enabled with either the <code>--enable-nacl-debug</code> Chrome
+command line switch, or via <code>about://flags</code>.</p>
 </section><section id="example-of-a-program-for-statically-linked-native-client-executables">
 <h4 id="example-of-a-program-for-statically-linked-native-client-executables">Example of a <code>program</code> for statically linked Native Client executables</h4>
 <pre class="prettyprint">
diff --git a/native_client_sdk/doc_generated/reference/pnacl-bitcode-abi.html b/native_client_sdk/doc_generated/reference/pnacl-bitcode-abi.html
index 8daa0a6..246154a 100644
--- a/native_client_sdk/doc_generated/reference/pnacl-bitcode-abi.html
+++ b/native_client_sdk/doc_generated/reference/pnacl-bitcode-abi.html
@@ -307,6 +307,7 @@
 <li><code>phi</code></li>
 <li><code>select</code></li>
 <li><code>call</code></li>
+<li><code>unreachable</code></li>
 </ul>
 </section><section id="alloca">
 <span id="bitcode-allocainst"></span><h3 id="alloca"><span id="bitcode-allocainst"></span><code>alloca</code></h3>
diff --git a/native_client_sdk/src/build_tools/build_sdk.py b/native_client_sdk/src/build_tools/build_sdk.py
index c4d03fa..790f062 100755
--- a/native_client_sdk/src/build_tools/build_sdk.py
+++ b/native_client_sdk/src/build_tools/build_sdk.py
@@ -889,7 +889,7 @@
 
 
 def main(args):
-  parser = optparse.OptionParser()
+  parser = optparse.OptionParser(description=__doc__)
   parser.add_option('--bionic', help='Add bionic build.',
       action='store_true')
   parser.add_option('--tar', help='Force the tar step.',
diff --git a/native_client_sdk/src/build_tools/buildbot_common.py b/native_client_sdk/src/build_tools/buildbot_common.py
index 316a348..5a08e1f 100644
--- a/native_client_sdk/src/build_tools/buildbot_common.py
+++ b/native_client_sdk/src/build_tools/buildbot_common.py
@@ -32,17 +32,6 @@
   return '-sdk-multi' in os.getenv('BUILDBOT_BUILDERNAME', '')
 
 
-def IsBuildOnlyBot():
-  """Returns True if this script is running on a build-only bot.
-
-  Build only bots are designed to be fast and non-flaky.  Currently
-  this means they don't build chrome, and don't run any browser-based
-  tests.  Currently the only build-only bots are trybots.
-
-  See IsSDKBuilder above for trybot/buildbot names."""
-  return os.getenv('BUILDBOT_BUILDERNAME', '').endswith('build')
-
-
 def IsSDKTrybot():
   """Returns True if this script is running on an SDK trybot.
 
diff --git a/native_client_sdk/src/build_tools/buildbot_run.py b/native_client_sdk/src/build_tools/buildbot_run.py
index 905f972..4a06b00 100755
--- a/native_client_sdk/src/build_tools/buildbot_run.py
+++ b/native_client_sdk/src/build_tools/buildbot_run.py
@@ -14,6 +14,7 @@
 
 import buildbot_common
 import os
+import optparse
 import subprocess
 import sys
 
@@ -22,6 +23,17 @@
 import getos
 
 
+def StepArmRunHooks():
+  if getos.GetPlatform() != 'linux':
+    return
+  # Run 'gclient runhooks' for arm, as some arm specific tools are only
+  # installed in that case.
+  buildbot_common.BuildStep('gclient runhooks for arm')
+  env = dict(os.environ)
+  env['GYP_DEFINES'] = 'target_arch=arm'
+  Run(['gclient', 'runhooks'], env=env, cwd=SDK_SRC_DIR)
+
+
 def StepRunUnittests():
   buildbot_common.BuildStep('Run unittests')
 
@@ -74,17 +86,40 @@
   Run(cmd, cwd=SCRIPT_DIR)
 
 
-def main():
+def main(args):
+  # Don't write out .pyc files in the source tree.  Without this, incremental
+  # builds can fail when .py files are moved/deleted, since python could load
+  # orphaned .pyc files generated by a previous run.
+  os.environ['PYTHONDONTWRITEBYTECODE'] = '1'
+
+  parser = optparse.OptionParser(description=__doc__)
+  parser.add_option('--build-only', action='store_true',
+      help='Only build the SDK, don\'t build or run tests.')
+  parser.add_option('--build-properties',
+      help='JSON properties passed by buildbot. Currently ignored.')
+  parser.add_option('--factory-properties',
+      help='JSON properties passed by buildbot. Currently ignored.')
+  options, args = parser.parse_args(args)
+
+  # Skip the testing phase if we are running on a build-only bots.
+  if not options.build_only:
+    # Infer build-only from bot name.
+    # TODO(sbc): Remove this once buildbot script have been updated
+    # to pass --build-only argument.
+    if os.getenv('BUILDBOT_BUILDERNAME', '').endswith('build'):
+      options.build_only = True
+
+  StepArmRunHooks()
   StepRunUnittests()
   StepBuildSDK()
-  # Skip the testing phase if we are running on a build-only bots.
-  if not buildbot_common.IsBuildOnlyBot():
+  if not options.build_only:
     StepTestSDK()
+
   return 0
 
 
 if __name__ == '__main__':
   try:
-    sys.exit(main())
+    sys.exit(main(sys.argv[1:]))
   except KeyboardInterrupt:
     buildbot_common.ErrorExit('buildbot_run: interrupted')
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list
index 00ac19e..b346b14 100644
--- a/native_client_sdk/src/build_tools/sdk_files.list
+++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -9,6 +9,7 @@
 examples/api/input_event/*
 [win]examples/api/make.bat
 examples/api/Makefile
+examples/api/media_stream_audio/*
 examples/api/media_stream_video/*
 examples/api/mouse_cursor/*
 examples/api/mouse_lock/*
diff --git a/native_client_sdk/src/build_tools/test_projects.py b/native_client_sdk/src/build_tools/test_projects.py
index 541a55a..0dd0800 100755
--- a/native_client_sdk/src/build_tools/test_projects.py
+++ b/native_client_sdk/src/build_tools/test_projects.py
@@ -60,6 +60,8 @@
     # TODO(binji): Disable 3D examples on linux/win/mac. See
     # http://crbug.com/262379.
     {'name': 'graphics_3d', 'platform': ('win', 'linux', 'mac')},
+    # media_stream_audio uses audio input devices which are not supported.
+    {'name': 'media_stream_audio', 'platform': ('win', 'linux', 'mac')},
     # media_stream_video uses 3D and webcam which are not supported.
     {'name': 'media_stream_video', 'platform': ('win', 'linux', 'mac')},
     # TODO(binji): These tests timeout on the trybots because the NEXEs take
diff --git a/native_client_sdk/src/doc/devguide/devcycle/debugging.rst b/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
index a0ad482..c46e400 100644
--- a/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
+++ b/native_client_sdk/src/doc/devguide/devcycle/debugging.rst
@@ -214,19 +214,75 @@
 ``i686-nacl-gdb`` is an alias for ``x86_64-nacl-gdb``, and the ``newlib``
 and ``glibc`` toolchains both contain the same version of GDB.
 
-Debugging PNaCl pexes
-~~~~~~~~~~~~~~~~~~~~~
+Debugging PNaCl pexes (with Pepper 35+)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you want to use GDB to debug a program that is compiled with the PNaCl
+toolchain, you must have a copy of the pexe from **before** running
+``pnacl-finalize``. The ``pnacl-finalize`` tool converts LLVM bitcode
+to the stable PNaCl bitcode format, but it also strips out debug
+metadata, which we need for debugging.
+
+**Note** unlike the finalized copy of the pexe, the non-finalized debug copy
+is not considered stable. This means that a debug copy of the PNaCl
+application created by a Pepper N SDK is only guaranteed to run
+with a matching Chrome version N. If the version of the debug bitcode pexe
+does not match that of Chrome then the translation process may fail, and
+you will see and error message in the JavaScript console.
+
+Also, make sure you are passing the ``-g`` :ref:`compile option
+<compile_flags>` to ``pnacl-clang`` to enable generating debugging info.
+You might also want to omit ``-O2`` from the compile-time and link-time
+options, otherwise GDB not might be able to print variables' values when
+debugging (this is more of a problem with the PNaCl/LLVM toolchain than
+with GCC).
+
+Once you have built a non-stable debug copy of the pexe, list the URL of
+that copy in your application's manifest file:
+
+.. naclcode::
+
+  {
+    "program": {
+      "pnacl-translate": {
+        "url": "release_version.pexe",
+        "optlevel": 2
+      },
+      "pnacl-debug": {
+        "url": "debug_version.bc",
+        "optlevel": 0
+      }
+    }
+  }
+
+Copy the ``debug_version.bc`` and ``nmf`` files to the location that
+your local web server serves files from.
+
+When you run Chrome with ``--enable-nacl-debug``, Chrome will translate
+and run the ``debug_version.bc`` instead of ``release_version.pexe``.
+Once the debug version is loaded, you are ready to :ref:`run nacl-gdb
+<running_nacl_gdb>`
+
+Whether you publish the NMF file containing the debug URL to the release
+web server, is up to you. One reason to avoid publishing the debug URL
+is that it is only guaranteed to work for the Chrome version that matches
+the SDK version. Developers who may have left the ``--enable-nacl-debug``
+flag turned on may end up loading the debug copy of your application
+(which may or may not work, depending on their version of Chrome).
+
+
+Debugging PNaCl pexes (with older Pepper toolchains)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 If you want to use GDB to debug a program that is compiled with the PNaCl
 toolchain, you must convert the ``pexe`` file to a ``nexe``.  (You can skip
-this step if you are using the GCC toolchain.)
+this step if you are using the GCC toolchain, or if you are using
+pepper 35 or later.)
 
 * Firstly, make sure you are passing the ``-g`` :ref:`compile option
   <compile_flags>` to ``pnacl-clang`` to enable generating debugging info.
   You might also want to omit ``-O2`` from the compile-time and link-time
-  options, otherwise GDB not might be able to print variables' values when
-  debugging (this is more of a problem with the PNaCl/LLVM toolchain than
-  with GCC).
+  options.
 
 * Secondly, use ``pnacl-translate`` to convert your ``pexe`` to one or more
   ``nexe`` files.  For example:
@@ -275,6 +331,8 @@
   might find it easier to translate the ``pexe`` to both ``nexe``
   formats as described above.
 
+.. _running_nacl_gdb:
+
 Running nacl-gdb
 ~~~~~~~~~~~~~~~~
 
@@ -331,6 +389,19 @@
      not affect your personal Chrome data (history, cookies, bookmarks, themes,
      and settings).
 
+   ``--nacl-debug-mask=<nmf_url_mask1,nmf_url_mask2,...>``
+     Specifies a set of debug mask patterns. This allows you to selectively
+     choose to debug certain applications and not debug others. For example,
+     if you only want to debug the NMF files for your applications at
+     ``https://example.com/app``, and no other NaCl applications found
+     on the web, specify ``--nacl-debug-mask=https://example.com/app/*.nmf``.
+     This helps prevent accidentally debugging other NaCl applications if
+     you like to leave the ``--enable-nacl-debug`` flag turned on.
+     The pattern language for the mask follows `chrome extension match patterns
+     <http://developer.chrome.com/extensions/match_patterns>`_.
+     The pattern set can be inverted by prefixing the pattern set with
+     the ``!`` character.
+
    ``<URL>``
      Specifies the URL Chrome should open when it launches. The local server
      that comes with the SDK listens on port 5103 by default, so the URL when
@@ -353,33 +424,60 @@
 
      (gdb)
 
-#. Run the following three commands from the gdb command line::
+#. For debugging PNaCl pexes run the following gdb command lines
+   (skip to the next item if you are using NaCl instead of PNaCl)::
 
-     (gdb) nacl-manifest <path-to-your-.nmf-file>
-     (gdb) nacl-irt <path-to-Chrome-NaCl-integrated-runtime>
      (gdb) target remote localhost:4014
+     (gdb) remote get nexe <path-to-save-translated-nexe-with-debug-info>
+     (gdb) file <path-to-save-translated-nexe-with-debug-info>
+     (gdb) remote get irt <path-to-save-NaCl-integrated-runtime>
+     (gdb) nacl-irt <path-to-saved-NaCl-integrated-runtime>
 
-   These commands are described below:
+#. For NaCl nexes, run the following commands from the gdb command line::
 
-   ``nacl-manifest <path>``
-     Tells the debugger about your Native Client application by pointing it to
-     the application's manifest (.nmf) file. The manifest file lists your
-     application's executable (.nexe) files, as well as any libraries that are
-     linked with the application dynamically.
+     (gdb) target remote localhost:4014
+     (gdb) nacl-manifest <path-to-your-.nmf-file>
+     (gdb) remote get irt <path-to-save-NaCl-integrated-runtime>
+     (gdb) nacl-irt <path-to-saved-NaCl-integrated-runtime>
 
-   ``nacl-irt <path>``
-     Tells the debugger where to find the Native Client Integrated Runtime
-     (IRT). The IRT is located in the same directory as the Chrome executable,
-     or in a subdirectory named after the Chrome version. For example, if
-     you're running Chrome canary on Windows, the path to the IRT typically
-     looks something like ``C:/Users/<username>/AppData/Local/Google/Chrome
-     SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe``.
+#. The command used for PNaCl and NaCl are described below:
 
    ``target remote localhost:4014``
      Tells the debugger how to connect to the debug stub in the Native Client
      application loader. This connection occurs through TCP port 4014 (note
      that this port is distinct from the port which the local web server uses
-     to listen for incoming requests, typically port 5103).
+     to listen for incoming requests, typically port 5103). If you are
+     debugging multiple applications at the same time, the loader may choose
+     a port that is different from the default 4014 port. See the Chrome
+     task manager for the debug port.
+
+   ``remote get nexe <path>``
+     This saves the application's main executable (nexe) to ``<path>``.
+     For PNaCl, this provides a convenient way to access the nexe that is
+     a **result** of translating your pexe. This can then be loaded with
+     the ``file <path>`` command.
+
+   ``nacl-manifest <path>``
+     For NaCl (not PNaCl), this tells the debugger where to find your
+     application's executable (.nexe) files. The application's manifest
+     (.nmf) file lists your application's executable files, as well as any
+     libraries that are linked with the application dynamically.
+
+   ``remote get irt <path>``
+     This saves the Native Client Integrated Runtime (IRT). Normally,
+     the IRT is located in the same directory as the Chrome executable,
+     or in a subdirectory named after the Chrome version. For example, if
+     you're running Chrome canary on Windows, the path to the IRT typically
+     looks something like ``C:/Users/<username>/AppData/Local/Google/Chrome
+     SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe``.
+     The ``remote get irt <path>`` saves that to the current working
+     directory so that you do not need to find where exactly the IRT
+     is stored alongside Chrome.
+
+   ``nacl-irt <path>``
+     Tells the debugger where to find the Native Client Integrated Runtime
+     (IRT). ``<path>`` can either be the location of the copy saved by
+     ``remote get irt <path>`` or the copy that is installed alongside Chrome.
 
    A couple of notes on how to specify path names in the nacl-gdb commands
    above:
@@ -394,9 +492,9 @@
    As an example, here is a what these nacl-gdb commands might look like on
    Windows::
 
+     target remote localhost:4014
      nacl-manifest "C:/<NACL_SDK_ROOT>/examples/hello_world_gles/newlib/Debug/hello_world_gles.nmf"
      nacl-irt "C:/Users/<username>/AppData/Local/Google/Chrome SxS/Application/23.0.1247.1/nacl_irt_x86_64.nexe"
-     target remote localhost:4014
 
    To save yourself some typing, you can put put these nacl-gdb commands in a
    script file, and execute the file when you run nacl-gdb, like so::
diff --git a/native_client_sdk/src/doc/reference/nacl-manifest-format.rst b/native_client_sdk/src/doc/reference/nacl-manifest-format.rst
index a61cf55..6f736a8 100644
--- a/native_client_sdk/src/doc/reference/nacl-manifest-format.rst
+++ b/native_client_sdk/src/doc/reference/nacl-manifest-format.rst
@@ -58,7 +58,15 @@
     "program": {
       "pnacl-translate": {
         // url is required
-        "url": "url_to_my_pexe"
+        "url": "url_to_my_pexe",
+
+        // optlevel is optional
+        "optlevel": 2
+      },
+      // pnacl-debug is optional
+      "pnacl-debug": {
+        // url is required
+        "url": "url_to_my_bitcode_bc",
 
         // optlevel is optional
         "optlevel": 0
@@ -78,6 +86,11 @@
 Portable Native Client translator and runtime may *automatically* choose
 an ``optlevel`` to best balance load time and application performance.
 
+A ``pnacl-debug`` section can specify an unfinalized pnacl llvm bitcode file
+for debugging. The ``url`` provided in this section will be used when Native
+Client debugging is enabled with either the ``--enable-nacl-debug`` Chrome
+command line switch, or via ``about://flags``.
+
 
 Example of a ``program`` for statically linked Native Client executables
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst b/native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst
index 9d52253..0f2740f 100644
--- a/native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst
+++ b/native_client_sdk/src/doc/reference/pnacl-bitcode-abi.rst
@@ -368,6 +368,7 @@
 * ``phi``
 * ``select``
 * ``call``
+* ``unreachable``
 
 .. _bitcode_allocainst:
 
diff --git a/native_client_sdk/src/examples/api/media_stream_audio/example.dsc b/native_client_sdk/src/examples/api/media_stream_audio/example.dsc
new file mode 100644
index 0000000..7c18919
--- /dev/null
+++ b/native_client_sdk/src/examples/api/media_stream_audio/example.dsc
@@ -0,0 +1,20 @@
+{
+  'TOOLS': ['newlib', 'glibc', 'pnacl', 'win', 'linux'],
+  'TARGETS': [
+    {
+      'NAME' : 'media_stream_audio',
+      'TYPE' : 'main',
+      'SOURCES' : [
+        'media_stream_audio.cc',
+      ],
+      'LIBS': ['ppapi_gles2', 'ppapi_cpp', 'ppapi', 'pthread']
+    }
+  ],
+  'DATA': [
+    'example.js'
+  ],
+  'DEST': 'examples/api',
+  'NAME': 'media_stream_audio',
+  'TITLE': 'MediaStream Audio',
+  'GROUP': 'API'
+}
diff --git a/native_client_sdk/src/examples/api/media_stream_audio/example.js b/native_client_sdk/src/examples/api/media_stream_audio/example.js
new file mode 100644
index 0000000..ab9a591
--- /dev/null
+++ b/native_client_sdk/src/examples/api/media_stream_audio/example.js
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+var stream;
+
+function success(s) {
+  stream = s;
+  common.naclModule.postMessage({track: stream.getAudioTracks()[0]});
+}
+
+function failure(e) {
+  common.logMessage("Error: " + e);
+}
+
+function moduleDidLoad() {
+  navigator.webkitGetUserMedia({'audio': true}, success, failure);
+}
diff --git a/native_client_sdk/src/examples/api/media_stream_audio/index.html b/native_client_sdk/src/examples/api/media_stream_audio/index.html
new file mode 100644
index 0000000..dafb021
--- /dev/null
+++ b/native_client_sdk/src/examples/api/media_stream_audio/index.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<head>
+  <meta http-equiv="Pragma" content="no-cache">
+  <meta http-equiv="Expires" content="-1">
+  <title>{{title}}</title>
+  <script type="text/javascript" src="common.js"></script>
+  <script type="text/javascript" src="example.js"></script>
+</head>
+<body data-width="640" data-height="480" {{attrs}}>
+  <h1>{{title}}</h1>
+  <h2>Status: <code id="statusField">NO-STATUS</code></h2>
+  <p>The MediaStream Audio example demonstrates how to capture audio data from
+  an audio input device.</p>
+  <!-- The NaCl plugin will be embedded inside the element with id "listener".
+      See common.js.-->
+  <div id="listener"></div>
+</body>
+</html>
diff --git a/native_client_sdk/src/examples/api/media_stream_audio/media_stream_audio.cc b/native_client_sdk/src/examples/api/media_stream_audio/media_stream_audio.cc
new file mode 100644
index 0000000..2811a6b
--- /dev/null
+++ b/native_client_sdk/src/examples/api/media_stream_audio/media_stream_audio.cc
@@ -0,0 +1,228 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <limits>
+#include <vector>
+
+#include "ppapi/cpp/audio_buffer.h"
+#include "ppapi/cpp/graphics_2d.h"
+#include "ppapi/cpp/image_data.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/logging.h"
+#include "ppapi/cpp/media_stream_audio_track.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/cpp/size.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+// When compiling natively on Windows, min, max and PostMessage can be #define-d
+// to something else.
+#ifdef PostMessage
+#undef min
+#undef max
+#undef PostMessage
+#endif
+
+// This example demonstrates receiving audio samples from a
+// MediaStreamAudioTrack and visualizing them.
+
+namespace {
+
+const uint32_t kColorRed = 0xFFFF0000;
+const uint32_t kColorGreen = 0xFF00FF00;
+const uint32_t kColorGrey1 = 0xFF202020;
+const uint32_t kColorGrey2 = 0xFF404040;
+const uint32_t kColorGrey3 = 0xFF606060;
+
+class MediaStreamAudioInstance : public pp::Instance {
+ public:
+  explicit MediaStreamAudioInstance(PP_Instance instance)
+      : pp::Instance(instance),
+        callback_factory_(this),
+        first_buffer_(true),
+        sample_count_(0),
+        channel_count_(0),
+        timer_interval_(0),
+        pending_paint_(false),
+        waiting_for_flush_completion_(false) {
+  }
+
+  virtual ~MediaStreamAudioInstance() {
+  }
+
+  virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
+    if (position.size() == size_)
+      return;
+
+    size_ = position.size();
+    device_context_ = pp::Graphics2D(this, size_, false);
+    if (!BindGraphics(device_context_))
+      return;
+
+    Paint();
+  }
+
+  virtual void HandleMessage(const pp::Var& var_message) {
+    if (!var_message.is_dictionary())
+      return;
+    pp::VarDictionary var_dictionary_message(var_message);
+    pp::Var var_track = var_dictionary_message.Get("track");
+    if (!var_track.is_resource())
+      return;
+
+    pp::Resource resource_track = var_track.AsResource();
+    audio_track_ = pp::MediaStreamAudioTrack(resource_track);
+    audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
+          &MediaStreamAudioInstance::OnGetBuffer));
+  }
+
+ private:
+  // Starts a timer to run Paint() in every |timer_interval_|.
+  void ScheduleNextTimer() {
+    PP_DCHECK(timer_interval_ > 0);
+    pp::Module::Get()->core()->CallOnMainThread(
+        timer_interval_,
+        callback_factory_.NewCallback(&MediaStreamAudioInstance::OnTimer),
+        0);
+  }
+
+  void OnTimer(int32_t) {
+    ScheduleNextTimer();
+    Paint();
+  }
+
+  void DidFlush(int32_t result) {
+    waiting_for_flush_completion_ = false;
+    if (pending_paint_)
+      Paint();
+  }
+
+  void Paint() {
+    if (waiting_for_flush_completion_) {
+      pending_paint_ = true;
+      return;
+    }
+
+    pending_paint_ = false;
+
+    if (size_.IsEmpty())
+      return;  // Nothing to do.
+
+    pp::ImageData image = PaintImage(size_);
+    if (!image.is_null()) {
+      device_context_.ReplaceContents(&image);
+      waiting_for_flush_completion_ = true;
+      device_context_.Flush(
+          callback_factory_.NewCallback(&MediaStreamAudioInstance::DidFlush));
+    }
+  }
+
+  pp::ImageData PaintImage(const pp::Size& size) {
+    pp::ImageData image(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL, size, false);
+    if (image.is_null())
+      return image;
+
+    // Clear to dark grey.
+    for (int y = 0; y < size.height(); y++) {
+      for (int x = 0; x < size.width(); x++)
+        *image.GetAddr32(pp::Point(x, y)) = kColorGrey1;
+    }
+
+    int mid_height = size.height() / 2;
+    int max_amplitude = size.height() * 4 / 10;
+
+    // Draw some lines.
+    for (int x = 0; x < size.width(); x++) {
+      *image.GetAddr32(pp::Point(x, mid_height)) = kColorGrey3;
+      *image.GetAddr32(pp::Point(x, mid_height + max_amplitude)) = kColorGrey2;
+      *image.GetAddr32(pp::Point(x, mid_height - max_amplitude)) = kColorGrey2;
+    }
+
+
+    // Draw our samples.
+    for (int x = 0, i = 0;
+         x < std::min(size.width(), static_cast<int>(sample_count_));
+         x++, i += channel_count_) {
+      for (uint32_t ch = 0; ch < std::min(channel_count_, 2U); ++ch) {
+        int y = samples_[i + ch] * max_amplitude /
+                (std::numeric_limits<int16_t>::max() + 1) + mid_height;
+        *image.GetAddr32(pp::Point(x, y)) = (ch == 0 ? kColorRed : kColorGreen);
+      }
+    }
+
+    return image;
+  }
+
+  // Callback that is invoked when new buffers are received.
+  void OnGetBuffer(int32_t result, pp::AudioBuffer buffer) {
+    if (result != PP_OK)
+      return;
+
+    assert(buffer.GetSampleSize() == PP_AUDIOBUFFER_SAMPLESIZE_16_BITS);
+    const char* data = static_cast<const char*>(buffer.GetDataBuffer());
+    uint32_t channels = buffer.GetNumberOfChannels();
+    uint32_t samples = buffer.GetNumberOfSamples() / channels;
+
+    if (channel_count_ != channels || sample_count_ != samples) {
+      channel_count_ = channels;
+      sample_count_ = samples;
+
+      samples_.resize(sample_count_ * channel_count_);
+      // Try (+ 5) to ensure that we pick up a new set of samples between each
+      // timer-generated repaint.
+      timer_interval_ = (sample_count_ * 1000) / buffer.GetSampleRate() + 5;
+      // Start the timer for the first buffer.
+      if (first_buffer_) {
+        first_buffer_ = false;
+        ScheduleNextTimer();
+      }
+    }
+
+    memcpy(samples_.data(), data,
+        sample_count_ * channel_count_ * sizeof(int16_t));
+
+    audio_track_.RecycleBuffer(buffer);
+    audio_track_.GetBuffer(callback_factory_.NewCallbackWithOutput(
+        &MediaStreamAudioInstance::OnGetBuffer));
+
+  }
+
+  pp::MediaStreamAudioTrack audio_track_;
+  pp::CompletionCallbackFactory<MediaStreamAudioInstance> callback_factory_;
+
+  bool first_buffer_;
+  uint32_t sample_count_;
+  uint32_t channel_count_;
+  std::vector<int16_t> samples_;
+
+  int32_t timer_interval_;
+
+  // Painting stuff.
+  pp::Size size_;
+  pp::Graphics2D device_context_;
+  bool pending_paint_;
+  bool waiting_for_flush_completion_;
+};
+
+class MediaStreamAudioModule : public pp::Module {
+ public:
+  virtual pp::Instance* CreateInstance(PP_Instance instance) {
+    return new MediaStreamAudioInstance(instance);
+  }
+};
+
+}  // namespace
+
+namespace pp {
+
+// Factory function for your specialization of the Module object.
+Module* CreateModule() {
+  return new MediaStreamAudioModule();
+}
+
+}  // namespace pp
diff --git a/native_client_sdk/src/examples/api/media_stream_video/index.html b/native_client_sdk/src/examples/api/media_stream_video/index.html
index 95f173f..b03fc50 100644
--- a/native_client_sdk/src/examples/api/media_stream_video/index.html
+++ b/native_client_sdk/src/examples/api/media_stream_video/index.html
@@ -17,8 +17,6 @@
   <h2>Status: <code id="statusField">NO-STATUS</code></h2>
   <p>The MediaStream Video example demonstrates how to capture video from
   a webcam.</p>
-  This example uses dev interfaces. It will not work on the WebStore,
-  or with PNaCL.<br>
   <!-- The NaCl plugin will be embedded inside the element with id "listener".
       See common.js.-->
   <div id="listener"></div>
diff --git a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js
index 7f26921..03b9a4e 100644
--- a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js
+++ b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/example.js
@@ -8,6 +8,17 @@
 }
 
 // Called by the common.js module.
+// nacl_io/ppapi_simple generates two different types of messages:
+// - messages from /dev/tty (prefixed with PS_TTY_PREFIX)
+// - exit message (prefixed with PS_EXIT_MESSAGE)
 function handleMessage(message) {
-  common.logMessage(message.data);
+  if (message.data.indexOf("exit:") == 0) {
+    // When we recieve the exit message we post an empty reply back to
+    // confirm, at which point the module will exit.
+    message.srcElement.postMessage({"exit" : ""});
+  } else if (message.data.indexOf("tty:") == 0) {
+    common.logMessage(message.data.slice("tty:".length));
+  } else {
+    console.log("Unhandled message: " + message.data);
+  }
 }
diff --git a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html
index 8779f49..fabbf9a 100644
--- a/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html
+++ b/native_client_sdk/src/examples/tutorial/using_ppapi_simple/index.html
@@ -12,7 +12,7 @@
   <script type="text/javascript" src="common.js"></script>
   <script type="text/javascript" src="example.js"></script>
 </head>
-<body {{attrs}} data-attrs="ps_stdout=dev/tty">
+<body {{attrs}} data-attrs="PS_STDOUT=dev/tty PS_TTY_PREFIX=tty: PS_EXIT_MESSAGE=exit">
   <h1>{{title}}</h1>
   <h2>Status: <code id="statusField">NO-STATUS</code></h2>
   <p>The Hello World Stdio example is the simplest one in the SDK.  It uses the
diff --git a/native_client_sdk/src/gonacl_appengine/src/lua/build.sh b/native_client_sdk/src/gonacl_appengine/src/lua/build.sh
index 155e88e..832a6e8 100755
--- a/native_client_sdk/src/gonacl_appengine/src/lua/build.sh
+++ b/native_client_sdk/src/gonacl_appengine/src/lua/build.sh
@@ -12,7 +12,7 @@
 
 OUT_DIR=out
 NACLPORTS_URL=http://naclports.googlecode.com/svn/trunk/src
-NACLPORTS_REV=992
+NACLPORTS_REV=1174
 NACLPORTS_DIR=${OUT_DIR}/naclports
 
 if [ -z "${NACL_SDK_ROOT:-}" ]; then
diff --git a/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.h b/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.h
index bf8ab53..17038eb 100644
--- a/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.h
+++ b/native_client_sdk/src/libraries/nacl_io/devfs/tty_node.h
@@ -38,6 +38,8 @@
   virtual Error Tcsetattr(int optional_actions,
                           const struct termios* termios_p);
 
+  virtual Error Isatty() { return 0; }
+
  private:
   ScopedEventEmitter emitter_;
 
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
index aca1ef3..ce4f170 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.cc
@@ -10,6 +10,7 @@
 
 #include "nacl_io/kernel_proxy.h"
 #include "nacl_io/kernel_wrap.h"
+#include "nacl_io/kernel_wrap_real.h"
 #include "nacl_io/osmman.h"
 #include "nacl_io/ossocket.h"
 #include "nacl_io/pepper_interface.h"
@@ -81,14 +82,6 @@
   return 0;
 }
 
-int ki_register_fs_type(const char* fs_type, struct fuse_operations* fuse_ops) {
-  return s_state.kp->RegisterFsType(fs_type, fuse_ops);
-}
-
-int ki_unregister_fs_type(const char* fs_type) {
-  return s_state.kp->UnregisterFsType(fs_type);
-}
-
 int ki_is_initialized() {
   return s_state.kp != NULL;
 }
@@ -112,11 +105,22 @@
     delete delete_kp;
 }
 
+nacl_io::KernelProxy* ki_get_proxy() {
+  return s_state.kp;
+}
+
 int ki_chdir(const char* path) {
   ON_NOSYS_RETURN(-1);
   return s_state.kp->chdir(path);
 }
 
+void ki_exit(int status) {
+  if (ki_is_initialized())
+    s_state.kp->exit(status);
+
+  _real_exit(status);
+}
+
 char* ki_getcwd(char* buf, size_t size) {
   // gtest uses getcwd in a static initializer. If we haven't initialized the
   // kernel-intercept yet, just return ".".
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
index bcf86b2..9b72f58 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_intercept.h
@@ -21,6 +21,12 @@
 
 EXTERN_C_BEGIN
 
+#ifdef __cplusplus
+namespace nacl_io {
+class KernelProxy;
+}
+#endif
+
 struct fuse_operations;
 
 /*
@@ -54,12 +60,15 @@
  */
 int ki_init_interface(void* kernel_proxy, void* pepper_interface);
 
-int ki_register_fs_type(const char* fs_type, struct fuse_operations* fuse_ops);
-int ki_unregister_fs_type(const char* fs_type);
+#ifdef __cplusplus
+nacl_io::KernelProxy* ki_get_proxy();
+#endif
+
 int ki_is_initialized();
 void ki_uninit();
 
 int ki_chdir(const char* path);
+void ki_exit(int status);
 char* ki_getcwd(char* buf, size_t size);
 char* ki_getwd(char* buf);
 int ki_dup(int oldfd);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
index 9c59b6a..680eaac 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.cc
@@ -51,6 +51,7 @@
 
 
 KernelProxy::KernelProxy() : dev_(0), ppapi_(NULL),
+                             exit_handler_(NULL),
                              signal_emitter_(new EventEmitter) {
    memset(&sigwinch_handler_, 0, sizeof(sigwinch_handler_));
    sigwinch_handler_.sa_handler = SIG_DFL;
@@ -144,6 +145,15 @@
   return true;
 }
 
+bool KernelProxy::RegisterExitHandler(nacl_io_exit_handler_t exit_handler,
+                                      void* user_data) {
+  if (exit_handler_ != NULL)
+    return false;
+  exit_handler_ = exit_handler;
+  exit_handler_user_data_ = user_data;
+  return true;
+}
+
 int KernelProxy::open_resource(const char* path) {
   ScopedFilesystem fs;
   Path rel;
@@ -268,6 +278,11 @@
   return 0;
 }
 
+void KernelProxy::exit(int status) {
+  if (exit_handler_)
+    exit_handler_(status, exit_handler_user_data_);
+}
+
 char* KernelProxy::getcwd(char* buf, size_t size) {
   if (NULL == buf) {
     errno = EFAULT;
@@ -576,16 +591,16 @@
   Error error = AcquireHandle(fd, &handle);
   if (error) {
     errno = error;
-    return -1;
+    return 0;
   }
 
-  error = handle->node()->IsaTTY();
+  error = handle->node()->Isatty();
   if (error) {
     errno = error;
-    return -1;
+    return 0;
   }
 
-  return 0;
+  return 1;
 }
 
 int KernelProxy::ioctl(int fd, int request, va_list args) {
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
index 7344d31..1cb1cc2 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_proxy.h
@@ -12,6 +12,7 @@
 #include "nacl_io/fs_factory.h"
 #include "nacl_io/host_resolver.h"
 #include "nacl_io/kernel_object.h"
+#include "nacl_io/nacl_io.h"
 #include "nacl_io/ossignal.h"
 #include "nacl_io/ossocket.h"
 #include "nacl_io/ostypes.h"
@@ -55,6 +56,9 @@
   bool RegisterFsType(const char* fs_type, fuse_operations* fuse_ops);
   bool UnregisterFsType(const char* fs_type);
 
+  bool RegisterExitHandler(nacl_io_exit_handler_t exit_handler,
+                           void* user_data);
+
   virtual int pipe(int pipefds[2]);
 
   // NaCl-only function to read resources specified in the NMF file.
@@ -66,6 +70,8 @@
   virtual int dup(int fd);
   virtual int dup2(int fd, int newfd);
 
+  virtual void exit(int status);
+
   // Path related System calls handled by KernelProxy (not filesystem-specific)
   virtual int chdir(const char* path);
   virtual char* getcwd(char* buf, size_t size);
@@ -207,6 +213,8 @@
   PepperInterface* ppapi_;
   static KernelProxy *s_instance_;
   struct sigaction sigwinch_handler_;
+  nacl_io_exit_handler_t exit_handler_;
+  void* exit_handler_user_data_;
 #ifdef PROVIDES_SOCKET_API
   HostResolver host_resolver_;
 #endif
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
index d6e44bd..f895ffb 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_glibc.cc
@@ -127,10 +127,11 @@
   OP(chdir); \
   OP(close); \
   OP(dup); \
-  OP(dup2);  \
+  OP(dup2); \
+  OP(exit); \
   OP(fstat); \
-  OP(getcwd);  \
-  OP(getdents);  \
+  OP(getcwd); \
+  OP(getdents); \
   OP(mkdir); \
   OP(open); \
   OP(poll);\
@@ -146,7 +147,7 @@
 
 EXPAND_SYMBOL_LIST_OPERATION(DECLARE_REAL_PTR);
 
-int WRAP(chdir) (const char* pathname) {
+int WRAP(chdir)(const char* pathname) {
   return (ki_chdir(pathname)) ? errno : 0;
 }
 
@@ -163,6 +164,10 @@
   return (ki_dup2(fd, newfd) < 0) ? errno : 0;
 }
 
+void WRAP(exit)(int status) {
+  ki_exit(status);
+}
+
 int WRAP(fstat)(int fd, struct nacl_abi_stat *nacl_buf) {
   struct stat buf;
   memset(&buf, 0, sizeof(struct stat));
@@ -301,6 +306,11 @@
   return REAL(close)(fd);
 }
 
+void _real_exit(int status) {
+  CHECK_REAL(exit);
+  REAL(exit)(status);
+}
+
 int _real_fstat(int fd, struct stat* buf) {
   struct nacl_abi_stat st;
   CHECK_REAL(fstat);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
index 0809866..8090123 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_newlib.cc
@@ -47,6 +47,7 @@
 
 extern void __libnacl_irt_dev_filename_init(void);
 
+extern struct nacl_irt_basic __libnacl_irt_basic;
 extern struct nacl_irt_fdio __libnacl_irt_fdio;
 extern struct nacl_irt_dev_fdio __libnacl_irt_dev_fdio;
 extern struct nacl_irt_dev_filename __libnacl_irt_dev_filename;
@@ -54,6 +55,7 @@
 
 // Create function pointers to the REAL implementation
 #define EXPAND_SYMBOL_LIST_OPERATION(OP) \
+  OP(basic, exit); \
   OP(fdio, close); \
   OP(fdio, dup); \
   OP(fdio, dup2); \
@@ -67,6 +69,7 @@
   OP(dev_fdio, fsync); \
   OP(dev_fdio, fdatasync); \
   OP(dev_fdio, ftruncate); \
+  OP(dev_fdio, isatty); \
   OP(dev_filename, open); \
   OP(dev_filename, stat); \
   OP(dev_filename, mkdir); \
@@ -103,6 +106,10 @@
   return (newfd < 0) ? errno : 0;
 }
 
+void WRAP(exit)(int status) {
+  ki_exit(status);
+}
+
 int WRAP(read)(int fd, void* buf, size_t count, size_t* nread) {
   ssize_t signed_nread = ki_read(fd, buf, count);
   *nread = static_cast<size_t>(signed_nread);
@@ -152,6 +159,13 @@
   return (ki_ftruncate(fd, length) < 0) ? errno : 0;
 }
 
+int WRAP(isatty)(int fd, int* result) {
+  *result = ki_isatty(fd);
+  if (*result == 1)
+    return errno;
+  return 0;
+}
+
 int WRAP(mmap)(void** addr, size_t length, int prot, int flags, int fd,
                off_t offset) {
   if (flags & MAP_ANONYMOUS)
@@ -261,11 +275,21 @@
   return REAL(close)(fd);
 }
 
+void _real_exit(int status) {
+  CHECK_REAL(exit);
+  REAL(exit)(status);
+}
+
 int _real_fstat(int fd, struct stat* buf) {
   CHECK_REAL(fstat);
   return REAL(fstat)(fd, buf);
 }
 
+int _real_isatty(int fd, int* result) {
+  CHECK_REAL(isatty);
+  return REAL(isatty)(fd, result);
+}
+
 int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t* nread) {
   CHECK_REAL(getdents);
   return REAL(getdents)(fd, static_cast<dirent*>(nacl_buf), nacl_count, nread);
diff --git a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
index 9a9bce6..f46f6cc 100644
--- a/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
+++ b/native_client_sdk/src/libraries/nacl_io/kernel_wrap_real.h
@@ -12,8 +12,10 @@
 EXTERN_C_BEGIN
 
 int _real_close(int fd);
+void _real_exit(int status);
 int _real_fstat(int fd, struct stat *buf);
 int _real_getdents(int fd, void* nacl_buf, size_t nacl_count, size_t *nread);
+int _real_isatty(int fd, int* result);
 int _real_lseek(int fd, off_t offset, int whence, off_t* new_offset);
 int _real_mkdir(const char* pathname, mode_t mode);
 int _real_mmap(void** addr, size_t length, int prot, int flags, int fd,
diff --git a/native_client_sdk/src/libraries/nacl_io/nacl_io.cc b/native_client_sdk/src/libraries/nacl_io/nacl_io.cc
index b4e21d3..ee61e9d 100644
--- a/native_client_sdk/src/libraries/nacl_io/nacl_io.cc
+++ b/native_client_sdk/src/libraries/nacl_io/nacl_io.cc
@@ -6,6 +6,7 @@
 
 #include <stdlib.h>
 #include "nacl_io/kernel_intercept.h"
+#include "nacl_io/kernel_proxy.h"
 
 void nacl_io_init() {
   ki_init(NULL);
@@ -16,10 +17,16 @@
   ki_init_ppapi(NULL, instance, get_interface);
 }
 
+
 int nacl_io_register_fs_type(const char* fs_type, fuse_operations* fuse_ops) {
-  return ki_register_fs_type(fs_type, fuse_ops);
+  return ki_get_proxy()->RegisterFsType(fs_type, fuse_ops);
 }
 
 int nacl_io_unregister_fs_type(const char* fs_type) {
-  return ki_unregister_fs_type(fs_type);
+  return ki_get_proxy()->UnregisterFsType(fs_type);
+}
+
+int nacl_io_register_exit_handler(nacl_io_exit_handler_t exit_handler,
+                                   void* user_data) {
+  return ki_get_proxy()->RegisterExitHandler(exit_handler, user_data);
 }
diff --git a/native_client_sdk/src/libraries/nacl_io/nacl_io.h b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
index 7c49222..5250903 100644
--- a/native_client_sdk/src/libraries/nacl_io/nacl_io.h
+++ b/native_client_sdk/src/libraries/nacl_io/nacl_io.h
@@ -12,6 +12,8 @@
 
 EXTERN_C_BEGIN
 
+typedef void (*nacl_io_exit_handler_t)(int status, void* user_data);
+
 /**
  * Initialize nacl_io.
  *
@@ -40,6 +42,9 @@
  */
 void nacl_io_init_ppapi(PP_Instance instance, PPB_GetInterface get_interface);
 
+int nacl_io_register_exit_handler(nacl_io_exit_handler_t exit_handler,
+                                  void* user_data);
+
 /**
  * Mount a new filesystem type.
  *
diff --git a/native_client_sdk/src/libraries/nacl_io/node.cc b/native_client_sdk/src/libraries/nacl_io/node.cc
index ceaad6c..b8876ed 100644
--- a/native_client_sdk/src/libraries/nacl_io/node.cc
+++ b/native_client_sdk/src/libraries/nacl_io/node.cc
@@ -184,7 +184,9 @@
 
 bool Node::IsaSock() { return (stat_.st_mode & S_IFSOCK) != 0; }
 
-bool Node::IsaTTY() { return (stat_.st_mode & S_IFCHR) != 0; }
+Error Node::Isatty() {
+  return ENOTTY;
+}
 
 Error Node::AddChild(const std::string& name, const ScopedNode& node) {
   return ENOTDIR;
diff --git a/native_client_sdk/src/libraries/nacl_io/node.h b/native_client_sdk/src/libraries/nacl_io/node.h
index 54b513a..4e4420c 100644
--- a/native_client_sdk/src/libraries/nacl_io/node.h
+++ b/native_client_sdk/src/libraries/nacl_io/node.h
@@ -95,10 +95,12 @@
   virtual void SetType(int type);
   // Assume that |out_size| is non-NULL.
   virtual Error GetSize(size_t* out_size);
+  // Returns 0 if node is a TTY
+  virtual Error Isatty();
+
   virtual bool IsaDir();
   virtual bool IsaFile();
   virtual bool IsaSock();
-  virtual bool IsaTTY();
 
   // Number of children for this node (directory)
   virtual int ChildCount();
diff --git a/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc b/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc
index 4b654f1..ebbec7d 100644
--- a/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc
+++ b/native_client_sdk/src/libraries/nacl_io/passthroughfs/passthrough_fs.cc
@@ -90,6 +90,19 @@
     return 0;
   }
 
+  virtual Error Isatty() {
+#ifdef __GLIBC__
+    // isatty is not yet hooked up to the IRT interface under glibc.
+    return ENOTTY;
+#else
+    int result = 0;
+    int err = _real_isatty(real_fd_, &result);
+    if (err)
+      return err;
+    return 0;
+#endif
+  }
+
   Error MMap(void* addr,
              size_t length,
              int prot,
diff --git a/native_client_sdk/src/libraries/nacl_io/syscalls/isatty.c b/native_client_sdk/src/libraries/nacl_io/syscalls/isatty.c
index f305f3f..8a54873 100644
--- a/native_client_sdk/src/libraries/nacl_io/syscalls/isatty.c
+++ b/native_client_sdk/src/libraries/nacl_io/syscalls/isatty.c
@@ -5,6 +5,11 @@
 #include "nacl_io/kernel_intercept.h"
 #include "nacl_io/kernel_wrap.h"
 
+#if !defined(__native_client__) || defined(__GLIBC__)
+// GLIBC-only entry point.
+// TODO(sbc): remove once this bug gets fixed:
+// https://code.google.com/p/nativeclient/issues/detail?id=3709
 int isatty(int fd) {
   return ki_isatty(fd);
 }
+#endif
diff --git a/native_client_sdk/src/libraries/ppapi/library.dsc b/native_client_sdk/src/libraries/ppapi/library.dsc
index 3f7295e..384426e 100644
--- a/native_client_sdk/src/libraries/ppapi/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi/library.dsc
@@ -94,7 +94,6 @@
         'ppb_alarms_dev.h',
         'ppb_cursor_control_dev.h',
         'ppb_file_chooser_dev.h',
-        'ppb_find_dev.h',
         'ppb_font_dev.h',
         'ppb_memory_dev.h',
         'ppb_opengles2ext_dev.h',
@@ -107,7 +106,6 @@
         'pp_cursor_type_dev.h',
         'pp_optional_structs_dev.h',
         'ppp_class_deprecated.h',
-        'ppp_find_dev.h',
         'ppp_network_state_dev.h',
         'ppp_printing_dev.h',
         'pp_print_settings_dev.h',
diff --git a/native_client_sdk/src/libraries/ppapi_cpp/library.dsc b/native_client_sdk/src/libraries/ppapi_cpp/library.dsc
index ca0c06f..c81b6c9 100644
--- a/native_client_sdk/src/libraries/ppapi_cpp/library.dsc
+++ b/native_client_sdk/src/libraries/ppapi_cpp/library.dsc
@@ -65,7 +65,6 @@
         'alarms_dev.cc',
         'cursor_control_dev.cc',
         'file_chooser_dev.cc',
-        'find_dev.cc',
         'font_dev.cc',
         'memory_dev.cc',
         'printing_dev.cc',
@@ -156,7 +155,6 @@
         'array_dev.h',
         'cursor_control_dev.h',
         'file_chooser_dev.h',
-        'find_dev.h',
         'font_dev.h',
         'may_own_ptr_dev.h',
         'memory_dev.h',
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
index a4b0d41..a9c7168 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.cc
@@ -60,21 +60,11 @@
 void* PSInstance::MainThreadThunk(void *info) {
   s_InstanceObject->Trace("Got MainThreadThunk.\n");
   StartInfo* si = static_cast<StartInfo*>(info);
-  si->inst_->main_loop_ = new pp::MessageLoop(si->inst_);
-  si->inst_->main_loop_->AttachToCurrentThread();
+  PSInstance* instance = si->inst_;
+  instance->main_loop_ = new pp::MessageLoop(si->inst_);
+  instance->main_loop_->AttachToCurrentThread();
 
-  int ret = si->inst_->MainThread(si->argc_, si->argv_);
-
-  bool should_exit = si->inst_->exit_message_ == NULL;
-
-  if (si->inst_->exit_message_) {
-    // Send the exit message to JavaScript. Don't call exit(), so the message
-    // doesn't get dropped.
-    si->inst_->Log("Posting exit message to JavaScript.\n");
-    std::stringstream ss;
-    ss << si->inst_->exit_message_ << ":" << ret;
-    si->inst_->PostMessage(ss.str());
-  }
+  int ret = instance->MainThread(si->argc_, si->argv_);
 
   // Clean up StartInfo.
   for (uint32_t i = 0; i < si->argc_; i++) {
@@ -83,16 +73,34 @@
   delete[] si->argv_;
   delete si;
 
-  if (should_exit) {
-    // Exit the entire process once the 'main' thread returns.
-    // The error code will be available to javascript via
-    // the exitcode parameter of the crash event.
-    exit(ret);
-  }
-
+  // Exit the entire process once the 'main' thread returns.
+  // The error code will be available to javascript via
+  // the exitcode parameter of the crash event.
+#ifdef __native_client__
+  exit(ret);
+#else
+  instance->ExitHandshake(ret);
+#endif
   return NULL;
 }
 
+void PSInstance::ExitHandshake(int status) {
+  if (exit_message_ == NULL)
+    return;
+
+  RegisterMessageHandler(exit_message_, MessageHandlerExitStatic, this);
+
+  // Send the exit message to JavaScript. Then wait
+  // for the reply/confirmation.
+  std::stringstream ss;
+  ss << exit_message_ << ":" << status;
+
+  pthread_mutex_lock(&exit_lock_);
+  PostMessage(ss.str());
+  pthread_cond_wait(&exit_cond_, &exit_lock_);
+  pthread_mutex_unlock(&exit_lock_);
+}
+
 // The default implementation supports running a 'C' main.
 int PSInstance::MainThread(int argc, char* argv[]) {
   if (!main_cb_) {
@@ -117,6 +125,10 @@
       tty_fd_(-1),
       tty_prefix_(NULL),
       exit_message_(NULL) {
+
+  pthread_mutex_init(&exit_lock_, NULL);
+  pthread_cond_init(&exit_cond_, NULL);
+
   // Set the single Instance object
   s_InstanceObject = this;
 
@@ -130,7 +142,9 @@
                      PP_INPUTEVENT_CLASS_TOUCH);
 }
 
-PSInstance::~PSInstance() {}
+PSInstance::~PSInstance() {
+  s_InstanceObject = NULL;
+}
 
 void PSInstance::SetMain(PSMainFunc_t main) {
   main_cb_ = main;
@@ -207,17 +221,18 @@
 // initialization macro, or via dynamically set embed attributes
 // through instance DidCreate.
 bool PSInstance::ProcessProperties() {
-  // Set default values
-  setenv("PS_STDIN", "/dev/stdin", 0);
-  setenv("PS_STDOUT", "/dev/stdout", 0);
-  setenv("PS_STDERR", "/dev/console3", 0);
-
   // Reset verbosity if passed in
   const char* verbosity = getenv("PS_VERBOSITY");
   if (verbosity) SetVerbosity(static_cast<Verbosity>(atoi(verbosity)));
 
   // Enable NaCl IO to map STDIN, STDOUT, and STDERR
   nacl_io_init_ppapi(PSGetInstanceId(), PSGetInterface);
+
+  // Set default values
+  setenv("PS_STDIN", "/dev/stdin", 0);
+  setenv("PS_STDOUT", "/dev/stdout", 0);
+  setenv("PS_STDERR", "/dev/console3", 0);
+
   int fd0 = open(getenv("PS_STDIN"), O_RDONLY);
   dup2(fd0, 0);
 
@@ -267,6 +282,11 @@
 
   exit_message_ = getenv("PS_EXIT_MESSAGE");
 
+  // If PS_EXIT_MESSAGE is set in the envionment then we perform a handshake
+  // with JavaScript when program exits.
+  if (exit_message_ != NULL)
+    nacl_io_register_exit_handler(HandleExitStatic, this);
+
   // Set line buffering on stdout and stderr
 #if !defined(WIN32)
   setvbuf(stderr, NULL, _IOLBF, 0);
@@ -370,6 +390,13 @@
   return count;
 }
 
+void PSInstance::MessageHandlerExit(const pp::Var& message) {
+  assert(message.is_string());
+  pthread_mutex_lock(&exit_lock_);
+  pthread_cond_signal(&exit_cond_);
+  pthread_mutex_unlock(&exit_lock_);
+}
+
 void PSInstance::MessageHandlerInput(const pp::Var& message) {
   // Since our message may contain null characters, we can't send it as a
   // naked C string, so we package it up in this struct before sending it
@@ -387,7 +414,12 @@
   }
 }
 
-void PSInstance::HandleResize(int width, int height){
+void PSInstance::HandleExitStatic(int status, void* user_data) {
+  PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
+  instance->ExitHandshake(status);
+}
+
+void PSInstance::HandleResize(int width, int height) {
   struct winsize size;
   memset(&size, 0, sizeof(size));
   size.ws_col = width;
@@ -412,6 +444,13 @@
   return instance->TtyOutputHandler(buf, count);
 }
 
+void PSInstance::MessageHandlerExitStatic(const pp::Var& key,
+                                          const pp::Var& value,
+                                          void* user_data) {
+  PSInstance* instance = reinterpret_cast<PSInstance*>(user_data);
+  instance->MessageHandlerExit(value);
+}
+
 void PSInstance::MessageHandlerInputStatic(const pp::Var& key,
                                            const pp::Var& value,
                                            void* user_data) {
@@ -459,7 +498,7 @@
   // If the message is a dictionary then see if it matches one
   // of the specific handlers, then call that handler rather than
   // queuing an event.
-  if (tty_fd_ >= 0 && event.is_dictionary()) {
+  if (event.is_dictionary()) {
     pp::VarDictionary dictionary(var);
     pp::VarArray keys = dictionary.GetKeys();
     if (keys.GetLength() == 1) {
diff --git a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
index 4138982..48908b0 100644
--- a/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
+++ b/native_client_sdk/src/libraries/ppapi_simple/ps_instance.h
@@ -109,6 +109,12 @@
                               MessageHandler_t handler,
                               void* user_data);
 
+
+  // Perform exit handshake with JavaScript.
+  // This is called by _exit before the process is terminated to ensure
+  // that all messages sent prior to _exit arrive at the JavaScript side.
+  void ExitHandshake(int status);
+
  protected:
   typedef std::map<std::string, MessageHandler> MessageHandlerMap;
 
@@ -148,17 +154,24 @@
   // Called by Init to processes default and embed tag arguments prior to
   // launching the 'ppapi_main' thread.
   virtual bool ProcessProperties();
-
  private:
   static void* MainThreadThunk(void *start_info);
   ssize_t TtyOutputHandler(const char* buf, size_t count);
+  void MessageHandlerExit(const pp::Var& message);
   void MessageHandlerInput(const pp::Var& message);
   void MessageHandlerResize(const pp::Var& message);
   void HandleResize(int width, int height);
 
+  static void HandleExitStatic(int status, void* user_data);
+
   static ssize_t TtyOutputHandlerStatic(const char* buf, size_t count,
                                         void* user_data);
 
+  /// Handle exit confirmation message from JavaScript.
+  static void MessageHandlerExitStatic(const pp::Var& key,
+                                       const pp::Var& value,
+                                       void* user_data);
+
   /// Handle input message from JavaScript.  The value is
   /// expected to be of type string.
   static void MessageHandlerInputStatic(const pp::Var& key,
@@ -185,15 +198,20 @@
   const char* tty_prefix_;
   MessageHandlerMap message_handlers_;
 
-  // A message to Post to JavaScript instead of exiting, or NULL if exit()
-  // should be called instead.
-  char* exit_message_;
-
   PSMainFunc_t main_cb_;
 
   const PPB_Core* ppb_core_;
   const PPB_Var* ppb_var_;
   const PPB_View* ppb_view_;
+
+  // Condition variable and lock used to wait for exit confirmation from
+  // JavaScript.
+  pthread_cond_t exit_cond_;
+  pthread_mutex_t exit_lock_;
+
+  // A message to Post to JavaScript instead of exiting, or NULL if exit()
+  // should be called instead.
+  char* exit_message_;
 };
 
 #endif  // PPAPI_MAIN_PS_INSTANCE_H_
diff --git a/native_client_sdk/src/libraries/xray/parsesymbols.c b/native_client_sdk/src/libraries/xray/parsesymbols.c
index 5d59ae4..e2afd44 100644
--- a/native_client_sdk/src/libraries/xray/parsesymbols.c
+++ b/native_client_sdk/src/libraries/xray/parsesymbols.c
@@ -15,7 +15,7 @@
 #if defined(XRAY)
 
 struct XRaySymbol* XRaySymbolTableCreateEntry(struct XRaySymbolTable* symtab,
-                                              const char* line) {
+                                              char* line) {
   uint32_t addr;
   unsigned int uiaddr;
   char symbol_text[XRAY_LINE_SIZE];
diff --git a/native_client_sdk/src/libraries/xray/report.c b/native_client_sdk/src/libraries/xray/report.c
index 4c070df..20e9e84 100644
--- a/native_client_sdk/src/libraries/xray/report.c
+++ b/native_client_sdk/src/libraries/xray/report.c
@@ -7,6 +7,7 @@
 
 #include <alloca.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <stdarg.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -48,7 +49,7 @@
     fprintf(f, "label %s\n", label);
   fprintf(f, "\n");
   fprintf(f,
-      "   Address        Ticks   Percent      Function    [annotation...]\n");
+      "   Address          Ticks   Percent      Function    [annotation...]\n");
   fprintf(f,
       "--------------------------------------------------------------------\n");
   total = XRayFrameGetTotalTicks(capture, frame);
@@ -62,8 +63,9 @@
       struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, index);
       uint32_t depth = XRAY_EXTRACT_DEPTH(e->depth_addr);
       uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr);
-      uint32_t ticks = e->end_tick - e->start_tick;
       uint32_t annotation_index = e->annotation_index;
+      uint64_t ticks =
+          e->end_tick > e->start_tick ? e->end_tick - e->start_tick : 0;
       float percent = 100.0f * (float)ticks / total;
       if (percent >= percent_cutoff && ticks >= ticks_cutoff) {
         struct XRaySymbol* symbol;
@@ -74,8 +76,8 @@
         } else {
           strcpy(annotation, "");
         }
-        fprintf(f, "0x%08X   %10lld     %5.1f     %s%s %s\n",
-                (unsigned int)addr, (int64_t)ticks, percent,
+        fprintf(f, "0x%08X   %12" PRIu64 "     %5.1f     %s%s %s\n",
+                (unsigned int)addr, ticks, percent,
                 &space[256 - depth], symbol_name, annotation);
       }
     }
@@ -88,7 +90,11 @@
 int qcompare(const void* a, const void* b) {
   struct XRayTotal* ia = (struct XRayTotal*)a;
   struct XRayTotal* ib = (struct XRayTotal*)b;
-  return ib->ticks - ia->ticks;
+  if (ib->ticks > ia->ticks)
+    return 1;
+  else if (ib->ticks < ia->ticks)
+    return -1;
+  return 0;
 }
 
 
@@ -104,20 +110,20 @@
     alloca(XRayFrameGetCount(capture) * sizeof(struct XRayTotal));
   fprintf(f, "\n");
   fprintf(f,
-      "Frame#      Total Ticks      Capture size    Annotations   Label\n");
+      "Frame#        Total Ticks      Capture size    Annotations   Label\n");
   fprintf(f,
       "--------------------------------------------------------------------\n");
   while (frame != head) {
-    int64_t total_ticks = XRayFrameGetTotalTicks(capture, frame);
+    uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame);
     int capture_size = XRayFrameGetTraceCount(capture, frame);
     int annotation_count = XRayFrameGetAnnotationCount(capture, frame);
     bool valid = XRayFrameIsValid(capture, frame);
     char label[XRAY_MAX_LABEL];
     XRayFrameMakeLabel(capture, counter, label);
-    fprintf(f, "   %3d %s     %10lld        %10d     %10d   %s\n",
+    fprintf(f, "   %3d %s     %12" PRIu64 "        %10d     %10d   %s\n",
       counter,
       valid ? " " : "*",
-      (int64_t)total_ticks,
+      total_ticks,
       capture_size,
       annotation_count,
       label);
@@ -139,20 +145,20 @@
   fprintf(f, "Sorted by total ticks (most expensive first):\n");
   fprintf(f, "\n");
   fprintf(f,
-      "Frame#      Total Ticks      Capture size    Annotations   Label\n");
+      "Frame#        Total Ticks      Capture size    Annotations   Label\n");
   fprintf(f,
       "--------------------------------------------------------------------\n");
   for (i = 0; i < counter; ++i) {
     int index = totals[i].index;
     int frame = totals[i].frame;
-    int64_t total_ticks = XRayFrameGetTotalTicks(capture, frame);
+    uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame);
     int capture_size = XRayFrameGetTraceCount(capture, frame);
     int annotation_count = XRayFrameGetAnnotationCount(capture, frame);
     char label[XRAY_MAX_LABEL];
     XRayFrameMakeLabel(capture, index, label);
-    fprintf(f, "   %3d       %10lld        %10d     %10d   %s\n",
+    fprintf(f, "   %3d       %12" PRIu64 "        %10d     %10d   %s\n",
         index,
-        (int64_t)total_ticks,
+        total_ticks,
         capture_size,
         annotation_count,
         label);
diff --git a/native_client_sdk/src/libraries/xray/xray.c b/native_client_sdk/src/libraries/xray/xray.c
index d1b8915..9e49591 100644
--- a/native_client_sdk/src/libraries/xray/xray.c
+++ b/native_client_sdk/src/libraries/xray/xray.c
@@ -18,11 +18,10 @@
 
 #if defined(XRAY)
 
-#define FORCE_INLINE  __attribute__((always_inline))
-
 /* GTSC - Get Time Stamp Counter */
 #if defined(__amd64__) && !defined(XRAY_NO_RDTSC)
-FORCE_INLINE uint64_t RDTSC64() {
+XRAY_INLINE uint64_t RDTSC64();
+uint64_t RDTSC64() {
   uint64_t a, d;
   __asm__ __volatile__("rdtsc" : "=a" (a), "=d" (d));
   return ((uint64_t)a) | (((uint64_t)d) << 32);
@@ -31,7 +30,8 @@
 #elif defined(__i386__) && !defined(XRAY_NO_RDTSC)
 #define GTSC(_x)      __asm__ __volatile__ ("rdtsc" : "=A" (_x));
 #else
-FORCE_INLINE uint64_t GTOD() {
+XRAY_INLINE uint64_t GTOD();
+uint64_t GTOD() {
   struct timeval tv;
   gettimeofday(&tv, NULL);
   return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
@@ -118,6 +118,12 @@
                                                 void* call_site);
 #endif
 
+XRAY_INLINE int XRayTraceDecrementIndexInline(
+    struct XRayTraceCapture* capture, int index);
+XRAY_INLINE int XRayTraceIncrementIndexInline(
+    struct XRayTraceCapture* capture, int index);
+
+
 XRAY_NO_INSTRUMENT void __xray_profile_append_annotation(
     struct XRayTraceCapture* capture,
     struct XRayTraceStackEntry* se,
@@ -136,7 +142,7 @@
 }
 
 /* Decrements the trace index, wrapping around if needed. */
-XRAY_FORCE_INLINE int XRayTraceDecrementIndexInline(
+int XRayTraceDecrementIndexInline(
     struct XRayTraceCapture* capture, int index) {
   --index;
   if (index < 0)
@@ -145,7 +151,7 @@
 }
 
 /* Increments the trace index, wrapping around if needed. */
-XRAY_FORCE_INLINE int XRayTraceIncrementIndexInline(
+int XRayTraceIncrementIndexInline(
     struct XRayTraceCapture* capture, int index) {
   ++index;
   if (index >= capture->buffer_size)
@@ -329,7 +335,7 @@
     uint32_t depth = capture->stack_depth;
     if (depth < capture->max_stack_depth) {
       struct XRayTraceStackEntry* se = &capture->stack[depth];
-      uint32_t addr = (uint32_t)this_fn;
+      uint32_t addr = (uint32_t)(uintptr_t)this_fn;
       se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr);
       se->dest = capture->buffer_index;
       se->annotation_index = 0;
@@ -539,7 +545,7 @@
   return capture->frame.entry[i].valid;
 }
 
-int XRayFrameGetTotalTicks(struct XRayTraceCapture* capture, int i) {
+uint64_t XRayFrameGetTotalTicks(struct XRayTraceCapture* capture, int i) {
   return capture->frame.entry[i].total_ticks;
 }
 
@@ -602,6 +608,7 @@
   capture->frame.entry[i].start = capture->buffer_index;
   capture->disabled = 0;
   capture->stack_depth = 1;
+
   /* The trace stack[0] is reserved */
   memset(&capture->stack[0], 0, sizeof(capture->stack[0]));
   /* Annotation index 0 is reserved to indicate no annotation */
@@ -616,7 +623,6 @@
 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION
   capture->frame.entry[i].start_time = XRayGenerateTimestampsNow();
 #endif
-
 }
 
 
diff --git a/native_client_sdk/src/libraries/xray/xray_priv.h b/native_client_sdk/src/libraries/xray/xray_priv.h
index 405107c..714c91d 100644
--- a/native_client_sdk/src/libraries/xray/xray_priv.h
+++ b/native_client_sdk/src/libraries/xray/xray_priv.h
@@ -21,10 +21,10 @@
 
 #if defined(XRAY)
 
-#define XRAY_FORCE_INLINE __attribute__((always_inline))
+#define XRAY_FORCE_INLINE __attribute__((always_inline, no_instrument_function))
 
 #define XRAY_TRACE_STACK_SIZE (256)
-#define XRAY_TRACE_ANNOTATION_LENGTH (1024)
+#define XRAY_TRACE_ANNOTATION_LENGTH (2048)
 #define XRAY_TRACE_BUFFER_SIZE (1048576)
 #define XRAY_ANNOTATION_STACK_SIZE ((XRAY_TRACE_STACK_SIZE) * \
                                     (XRAY_TRACE_ANNOTATION_LENGTH))
@@ -100,7 +100,7 @@
 XRAY_NO_INSTRUMENT int XRaySymbolCount(struct XRaySymbolTable* symtab);
 
 XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableCreateEntry(
-    struct XRaySymbolTable* symtab, const char* line);
+    struct XRaySymbolTable* symtab, char* line);
 XRAY_NO_INSTRUMENT void XRaySymbolTableParseMapfile(
     struct XRaySymbolTable* symbols, const char* mapfilename);
 
@@ -115,7 +115,8 @@
 XRAY_NO_INSTRUMENT struct XRaySymbolTable* XRaySymbolTableCreate(int size);
 XRAY_NO_INSTRUMENT void XRaySymbolTableFree(struct XRaySymbolTable* symbtab);
 
-XRAY_NO_INSTRUMENT struct XRaySymbolTable* XRayGetSymbolTable();
+XRAY_NO_INSTRUMENT struct XRaySymbolTable* XRayGetSymbolTable(
+    struct XRayTraceCapture* capture);
 
 XRAY_NO_INSTRUMENT void XRayCheckGuards(struct XRayTraceCapture* capture);
 
@@ -146,7 +147,7 @@
 XRAY_NO_INSTRUMENT int XRayFrameGetTail(struct XRayTraceCapture* capture);
 XRAY_NO_INSTRUMENT int XRayFrameGetNext(
     struct XRayTraceCapture* capture, int index);
-XRAY_NO_INSTRUMENT int XRayFrameGetTotalTicks(
+XRAY_NO_INSTRUMENT uint64_t XRayFrameGetTotalTicks(
     struct XRayTraceCapture* capture, int frame);
 XRAY_NO_INSTRUMENT int XRayFrameGetTraceCount(
     struct XRayTraceCapture* capture, int frame);
diff --git a/native_client_sdk/src/tests/nacl_io_socket_test/example.js b/native_client_sdk/src/tests/nacl_io_socket_test/example.js
index 24b8243..2ffb98d 100644
--- a/native_client_sdk/src/tests/nacl_io_socket_test/example.js
+++ b/native_client_sdk/src/tests/nacl_io_socket_test/example.js
@@ -63,6 +63,9 @@
   var cmdFunctionName = cmd + 'Command';
   var cmdFunction = window[cmdFunctionName];
 
+  if (cmd == 'testend')
+    event.srcElement.postMessage({'testend' : ''});
+
   if (typeof(cmdFunction) !== 'function') {
     console.log('Unknown command: ' + cmd);
     console.log('  message: ' + msg);
diff --git a/native_client_sdk/src/tests/nacl_io_test/example.dsc b/native_client_sdk/src/tests/nacl_io_test/example.dsc
index 7b2db96..48f7a54 100644
--- a/native_client_sdk/src/tests/nacl_io_test/example.dsc
+++ b/native_client_sdk/src/tests/nacl_io_test/example.dsc
@@ -47,7 +47,6 @@
         'mem_fs_node_test.cc',
         'mock_fs.cc',
         'mock_fs.h',
-        'mock_kernel_proxy.cc',
         'mock_kernel_proxy.h',
         'mock_node.cc',
         'mock_node.h',
diff --git a/native_client_sdk/src/tests/nacl_io_test/example.js b/native_client_sdk/src/tests/nacl_io_test/example.js
index 24b8243..2146595 100644
--- a/native_client_sdk/src/tests/nacl_io_test/example.js
+++ b/native_client_sdk/src/tests/nacl_io_test/example.js
@@ -60,6 +60,9 @@
   var msg = event.data;
   var firstColon = msg.indexOf(':');
   var cmd = firstColon !== -1 ? msg.substr(0, firstColon) : msg;
+  if (cmd == 'testend')
+    event.srcElement.postMessage({'testend' : ''});
+
   var cmdFunctionName = cmd + 'Command';
   var cmdFunction = window[cmdFunctionName];
 
diff --git a/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc b/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
index bacf6a8..a75246d 100644
--- a/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/fuse_fs_test.cc
@@ -321,7 +321,7 @@
   ASSERT_EQ(0, ki_init(&kp_));
 
   // Register a fuse filesystem.
-  ki_register_fs_type("flatfs", &g_fuse_operations);
+  nacl_io_register_fs_type("flatfs", &g_fuse_operations);
 
   // Unmount the passthrough FS and mount our fuse filesystem.
   EXPECT_EQ(0, kp_.umount("/"));
@@ -329,7 +329,7 @@
 }
 
 void KernelProxyFuseTest::TearDown() {
-  ki_unregister_fs_type("flatfs");
+  nacl_io_unregister_fs_type("flatfs");
   ki_uninit();
 }
 
diff --git a/native_client_sdk/src/tests/nacl_io_test/html5_fs_test.cc b/native_client_sdk/src/tests/nacl_io_test/html5_fs_test.cc
index 9a73b73..3acbaa8 100644
--- a/native_client_sdk/src/tests/nacl_io_test/html5_fs_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/html5_fs_test.cc
@@ -364,7 +364,7 @@
   EXPECT_EQ(strlen(contents), size);
   EXPECT_FALSE(node->IsaDir());
   EXPECT_TRUE(node->IsaFile());
-  EXPECT_FALSE(node->IsaTTY());
+  EXPECT_EQ(ENOTTY, node->Isatty());
 
   // GetStat on a directory...
   EXPECT_EQ(0, fs->Open(Path("/dir"), O_RDONLY, &node));
@@ -382,7 +382,7 @@
   EXPECT_EQ(0, size);
   EXPECT_TRUE(node->IsaDir());
   EXPECT_FALSE(node->IsaFile());
-  EXPECT_FALSE(node->IsaTTY());
+  EXPECT_EQ(ENOTTY, node->Isatty());
 }
 
 TEST_F(Html5FsTest, FTruncate) {
diff --git a/native_client_sdk/src/tests/nacl_io_test/main.cc b/native_client_sdk/src/tests/nacl_io_test/main.cc
index ef7b094..326c18f 100644
--- a/native_client_sdk/src/tests/nacl_io_test/main.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/main.cc
@@ -9,6 +9,7 @@
 #if defined(SEL_LDR)
 
 int main(int argc, char* argv[]) {
+  setenv("TERM", "xterm-256color", 0);
   ::testing::InitGoogleTest(&argc, argv);
   return RUN_ALL_TESTS();
 }
diff --git a/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc b/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc
index dec489b..d6d8c18 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc
+++ b/native_client_sdk/src/tests/nacl_io_test/mem_fs_node_test.cc
@@ -79,7 +79,7 @@
   EXPECT_EQ(S_IFREG, file.GetType());
   EXPECT_FALSE(file.IsaDir());
   EXPECT_TRUE(file.IsaFile());
-  EXPECT_FALSE(file.IsaTTY());
+  EXPECT_EQ(ENOTTY, file.Isatty());
   EXPECT_EQ(0, file.RefCount());
 
   // Test IO
@@ -209,7 +209,7 @@
   EXPECT_EQ(S_IFDIR, root.GetType());
   EXPECT_TRUE(root.IsaDir());
   EXPECT_FALSE(root.IsaFile());
-  EXPECT_FALSE(root.IsaTTY());
+  EXPECT_EQ(ENOTTY, root.Isatty());
   EXPECT_EQ(0, root.RefCount());
 
   // IO operations should fail
diff --git a/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h b/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
index 12d06b6..2402b76 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
+++ b/native_client_sdk/src/tests/nacl_io_test/mock_kernel_proxy.h
@@ -16,8 +16,7 @@
 
 class MockKernelProxy : public nacl_io::KernelProxy {
  public:
-  MockKernelProxy();
-  virtual ~MockKernelProxy();
+  MockKernelProxy() {}
 
   MOCK_METHOD2(access, int(const char*, int));
   MOCK_METHOD1(chdir, int(const char*));
diff --git a/native_client_sdk/src/tests/nacl_io_test/mock_node.h b/native_client_sdk/src/tests/nacl_io_test/mock_node.h
index 199f6b1..8286e3a 100644
--- a/native_client_sdk/src/tests/nacl_io_test/mock_node.h
+++ b/native_client_sdk/src/tests/nacl_io_test/mock_node.h
@@ -35,7 +35,7 @@
   MOCK_METHOD1(GetSize, Error(size_t*));
   MOCK_METHOD0(IsaDir, bool());
   MOCK_METHOD0(IsaFile, bool());
-  MOCK_METHOD0(IsaTTY, bool());
+  MOCK_METHOD0(Isatty, Error());
   MOCK_METHOD0(ChildCount, int());
   MOCK_METHOD2(AddChild, Error(const std::string&, const ScopedNode&));
   MOCK_METHOD1(RemoveChild, Error(const std::string&));
diff --git a/native_client_sdk/src/tests/sdk_util_test/example.js b/native_client_sdk/src/tests/sdk_util_test/example.js
index 24b8243..8538ccd 100644
--- a/native_client_sdk/src/tests/sdk_util_test/example.js
+++ b/native_client_sdk/src/tests/sdk_util_test/example.js
@@ -62,6 +62,8 @@
   var cmd = firstColon !== -1 ? msg.substr(0, firstColon) : msg;
   var cmdFunctionName = cmd + 'Command';
   var cmdFunction = window[cmdFunctionName];
+  if (cmd == 'testend')
+    event.srcElement.postMessage({'testend' : ''});
 
   if (typeof(cmdFunction) !== 'function') {
     console.log('Unknown command: ' + cmd);
diff --git a/native_client_sdk/src/tools/create_nmf.py b/native_client_sdk/src/tools/create_nmf.py
index b19b7d0..dc82122 100755
--- a/native_client_sdk/src/tools/create_nmf.py
+++ b/native_client_sdk/src/tools/create_nmf.py
@@ -3,7 +3,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-"""Tool for automatically creating .nmf files from .nexe/.pexe executables.
+"""Tool for automatically creating .nmf files from .nexe/.pexe/.bc executables.
 
 As well as creating the nmf file this tool can also find and stage
 any shared libraries dependencies that the executables might have.
@@ -49,6 +49,7 @@
 PNACL_OPTLEVEL_KEY = 'optlevel' # key for PNaCl optimization level
 PORTABLE_KEY = 'portable' # key for portable section of manifest
 TRANSLATE_KEY = 'pnacl-translate' # key for translatable objects
+TRANSLATE_DEBUG_KEY = 'pnacl-debug' # key for translatable debug objects
 
 
 def DebugPrint(message):
@@ -174,7 +175,8 @@
   def __init__(self, main_files=None, objdump=None,
                lib_path=None, extra_files=None, lib_prefix=None,
                nexe_prefix=None, no_arch_prefix=None, remap=None,
-               pnacl_optlevel=None, nmf_root=None):
+               pnacl_optlevel=None, pnacl_debug_optlevel=None,
+               nmf_root=None):
     """Constructor
 
     Args:
@@ -190,8 +192,9 @@
       no_arch_prefix: Don't prefix shared libraries by lib32/lib64.
       remap: Remaps the library name in the manifest.
       pnacl_optlevel: Optimization level for PNaCl translation.
+      pnacl_debug_optlevel: Optimization level for debug PNaCl translation.
       nmf_root: Directory of the NMF. All urls are relative to this directory.
-      """
+    """
     assert len(main_files) > 0
     self.objdump = objdump
     self.main_files = main_files
@@ -203,8 +206,9 @@
     self.nexe_prefix = nexe_prefix or ''
     self.no_arch_prefix = no_arch_prefix
     self.remap = remap or {}
-    self.pnacl = main_files[0].endswith('pexe')
+    self.pnacl = main_files[0].endswith(('.pexe', '.bc'))
     self.pnacl_optlevel = pnacl_optlevel
+    self.pnacl_debug_optlevel = pnacl_debug_optlevel
     if nmf_root is not None:
       self.nmf_root = nmf_root
     else:
@@ -327,12 +331,25 @@
     manifest = {}
     manifest[PROGRAM_KEY] = {}
     manifest[PROGRAM_KEY][PORTABLE_KEY] = {}
-    translate_dict =  {
-      "url": os.path.basename(self.main_files[0]),
-    }
-    if self.pnacl_optlevel is not None:
-      translate_dict[PNACL_OPTLEVEL_KEY] = self.pnacl_optlevel
-    manifest[PROGRAM_KEY][PORTABLE_KEY][TRANSLATE_KEY] = translate_dict
+    portable = manifest[PROGRAM_KEY][PORTABLE_KEY]
+    for filename in self.main_files:
+      translate_dict =  {
+          'url': os.path.basename(filename),
+      }
+      if filename.endswith('.pexe'):
+        if self.pnacl_optlevel is not None:
+          translate_dict[PNACL_OPTLEVEL_KEY] = self.pnacl_optlevel
+        if TRANSLATE_KEY in portable:
+          raise Error('Multiple .pexe files')
+        portable[TRANSLATE_KEY] = translate_dict
+      elif filename.endswith('.bc'):
+        if self.pnacl_debug_optlevel is not None:
+          translate_dict[PNACL_OPTLEVEL_KEY] = self.pnacl_debug_optlevel
+        if TRANSLATE_DEBUG_KEY in portable:
+          raise Error('Multiple .bc files')
+        portable[TRANSLATE_DEBUG_KEY] = translate_dict
+      else:
+        raise Error('Unexpected executable type: %s' % filename)
     self.manifest = manifest
 
   def _GenerateManifest(self):
@@ -562,6 +579,10 @@
   parser.add_option('-O', '--pnacl-optlevel',
                     help='Set the optimization level to N in PNaCl manifests',
                     metavar='N')
+  parser.add_option('--pnacl-debug-optlevel',
+                    help='Set the optimization level to N for debugging '
+                         'sections in PNaCl manifests',
+                    metavar='N')
   parser.add_option('-v', '--verbose',
                     help='Verbose output', action='store_true')
   parser.add_option('-d', '--debug-mode',
@@ -620,6 +641,10 @@
       sys.stderr.write(
           'warning: PNaCl optlevel %d is unsupported (< 0 or > 3)\n' %
           pnacl_optlevel)
+  if options.pnacl_debug_optlevel is not None:
+    pnacl_debug_optlevel = int(options.pnacl_debug_optlevel)
+  else:
+    pnacl_debug_optlevel = pnacl_optlevel
 
   nmf_root = None
   if options.output:
@@ -634,6 +659,7 @@
                  no_arch_prefix=options.no_arch_prefix,
                  remap=remap,
                  pnacl_optlevel=pnacl_optlevel,
+                 pnacl_debug_optlevel=pnacl_debug_optlevel,
                  nmf_root=nmf_root)
 
   if not options.output:
diff --git a/native_client_sdk/src/tools/lib/tests/data/test.bc b/native_client_sdk/src/tools/lib/tests/data/test.bc
new file mode 100644
index 0000000..8b290c9
--- /dev/null
+++ b/native_client_sdk/src/tools/lib/tests/data/test.bc
Binary files differ
diff --git a/native_client_sdk/src/tools/nacl_llvm.mk b/native_client_sdk/src/tools/nacl_llvm.mk
index c50b89c..2beb574 100644
--- a/native_client_sdk/src/tools/nacl_llvm.mk
+++ b/native_client_sdk/src/tools/nacl_llvm.mk
@@ -167,7 +167,7 @@
 ifeq ($(CONFIG),Debug)
 EXECUTABLES=$(OUTDIR)/$(1)_x86_32.nexe $(OUTDIR)/$(1)_x86_64.nexe $(OUTDIR)/$(1)_arm.nexe
 else
-EXECUTABLES=$(OUTDIR)/$(1).pexe
+EXECUTABLES=$(OUTDIR)/$(1).pexe $(OUTDIR)/$(1)_unstripped.bc
 endif
 
 define NMF_RULE
diff --git a/native_client_sdk/src/tools/tests/create_nmf_test.py b/native_client_sdk/src/tools/tests/create_nmf_test.py
index 49bc5bc..aca8fe9 100755
--- a/native_client_sdk/src/tools/tests/create_nmf_test.py
+++ b/native_client_sdk/src/tools/tests/create_nmf_test.py
@@ -214,6 +214,29 @@
 
     return nmf, pexes
 
+  def _CreateBitCode(self, **kwargs):
+    """Copy test.bc from the DATA_DIR to a temporary directory.
+
+    Args:
+      kwargs: Keyword arguments to pass through to create_nmf.NmfUtils
+          constructor.
+
+    Returns:
+      A tuple with 2 elements:
+        * The generated NMF as a dictionary (i.e. parsed by json.loads)
+        * A list of the generated .bc paths
+    """
+    bc_name = 'test.bc'
+    src_bc = os.path.join(DATA_DIR, bc_name)
+    dst_bc = os.path.join(self.tempdir, bc_name)
+    shutil.copy(src_bc, dst_bc)
+
+    bcs = [dst_bc]
+    nmf_utils = self._CreateNmfUtils(bcs, **kwargs)
+    nmf = json.loads(nmf_utils.GetJson())
+
+    return nmf, bcs
+
   def assertManifestEquals(self, manifest, expected):
     """Compare two manifest dictionaries.
 
@@ -560,6 +583,20 @@
     }
     self.assertManifestEquals(nmf, expected_manifest)
 
+  def testBitCode(self):
+    nmf, _ = self._CreateBitCode(pnacl_debug_optlevel=0)
+    expected_manifest = {
+      'program': {
+        'portable': {
+          'pnacl-debug': {
+            'url': 'test.bc',
+            'optlevel': 0,
+          }
+        }
+      }
+    }
+    self.assertManifestEquals(nmf, expected_manifest)
+
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/net/base/file_stream_context.cc b/net/base/file_stream_context.cc
index 43825e3..5d1fdbb 100644
--- a/net/base/file_stream_context.cc
+++ b/net/base/file_stream_context.cc
@@ -274,21 +274,16 @@
   DCHECK(!async_in_progress_);
 
   if (file_.IsValid()) {
-    bool posted = task_runner_.get()->PostTaskAndReply(
+    bool posted = task_runner_.get()->PostTask(
         FROM_HERE,
         base::Bind(base::IgnoreResult(&Context::CloseFileImpl),
-                   base::Unretained(this)),
-        base::Bind(&Context::OnCloseCompleted, base::Unretained(this)));
+                   base::Owned(this)));
     DCHECK(posted);
   } else {
     delete this;
   }
 }
 
-void FileStream::Context::OnCloseCompleted() {
-  delete this;
-}
-
 Int64CompletionCallback FileStream::Context::IntToInt64(
     const CompletionCallback& callback) {
   return base::Bind(&CallInt64ToInt, callback);
diff --git a/net/base/file_stream_context.h b/net/base/file_stream_context.h
index e7711c9..c70a8f6 100644
--- a/net/base/file_stream_context.h
+++ b/net/base/file_stream_context.h
@@ -168,7 +168,6 @@
                        OpenResult open_result);
 
   void CloseAndDelete();
-  void OnCloseCompleted();
 
   Int64CompletionCallback IntToInt64(const CompletionCallback& callback);
 
diff --git a/net/base/ip_mapping_rules.cc b/net/base/ip_mapping_rules.cc
deleted file mode 100644
index fbc887d..0000000
--- a/net/base/ip_mapping_rules.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/base/ip_mapping_rules.h"
-
-#include <vector>
-
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_tokenizer.h"
-#include "base/strings/string_util.h"
-#include "net/base/address_list.h"
-#include "net/base/ip_pattern.h"
-
-namespace net {
-
-class IPMappingRules::Rule {
- public:
-  Rule(const IPAddressNumber& address, IPPattern* pattern)
-      : pattern_(pattern),
-        replacement_address_(address) {
-  }
-
-  bool Match(const IPAddressNumber& address) const {
-    return pattern_->Match(address);
-  }
-
-  const IPAddressNumber& replacement_address() const {
-    return replacement_address_;
-  }
-
- private:
-  scoped_ptr<IPPattern> pattern_;        // The pattern we can match.
-  IPAddressNumber replacement_address_;  // The replacement address we provide.
-  DISALLOW_COPY_AND_ASSIGN(Rule);
-};
-
-IPMappingRules::IPMappingRules() {}
-
-IPMappingRules::~IPMappingRules() {
-  STLDeleteElements(&rules_);
-}
-
-bool IPMappingRules::RewriteAddresses(AddressList* addresses) const {
-  // Last rule pushed into the list has the highest priority, and is tested
-  // first.
-  for (RuleList::const_reverse_iterator rule_it = rules_.rbegin();
-       rule_it != rules_.rend(); ++rule_it) {
-    for (AddressList::iterator address_it = addresses->begin();
-        address_it != addresses->end(); ++address_it) {
-      if (!(*rule_it)->Match(address_it->address()))
-        continue;
-      // We have a match.
-      int port = address_it->port();
-      addresses->insert(addresses->begin(),
-                        IPEndPoint((*rule_it)->replacement_address(), port));
-      return true;
-    }
-  }
-  return false;
-}
-
-bool IPMappingRules::AddRuleFromString(const std::string& rule_string) {
-  std::string trimmed;
-  base::TrimWhitespaceASCII(rule_string, base::TRIM_ALL, &trimmed);
-  if (trimmed.empty())
-    return true;  // Allow empty rules.
-
-  std::vector<std::string> parts;
-  base::SplitString(trimmed, ' ', &parts);
-
-  if (parts.size() != 3) {
-    DVLOG(1) << "Rule has wrong number of parts: " << rule_string;
-    return false;
-  }
-
-  if (!LowerCaseEqualsASCII(parts[0], "preface")) {
-    DVLOG(1) << "Unknown directive: " << rule_string;
-    return false;
-  }
-
-  scoped_ptr<IPPattern> pattern(new IPPattern);
-  if (!pattern->ParsePattern(parts[1])) {
-    DVLOG(1) << "Unacceptable pattern: " << rule_string;
-    return false;
-  }
-
-  IPAddressNumber address;
-  if (!ParseIPLiteralToNumber(parts[2], &address)) {
-    DVLOG(1) << "Invalid replacement address: " << rule_string;
-    return false;
-  }
-
-  if (pattern->is_ipv4() != (address.size() == kIPv4AddressSize)) {
-    DVLOG(1) << "Mixture of IPv4 and IPv6: " << rule_string;
-    return false;
-  }
-  rules_.push_back(new Rule(address, pattern.release()));
-  return true;
-}
-
-bool IPMappingRules::SetRulesFromString(const std::string& rules_string) {
-  STLDeleteElements(&rules_);
-
-  base::StringTokenizer rules(rules_string, ";");
-  while (rules.GetNext()) {
-    if (!AddRuleFromString(rules.token())) {
-      DVLOG(1) << "Failed parsing rule: " << rules.token();
-      STLDeleteElements(&rules_);
-      return false;
-    }
-  }
-  return true;
-}
-
-}  // namespace net
diff --git a/net/base/ip_mapping_rules.h b/net/base/ip_mapping_rules.h
deleted file mode 100644
index 7291abf..0000000
--- a/net/base/ip_mapping_rules.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_BASE_IP_MAPPING_RULES_H_
-#define NET_BASE_IP_MAPPING_RULES_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "net/base/net_export.h"
-
-namespace net {
-
-class AddressList;
-
-// This class contains a list of rules, that can be used to process (Rewrite) a
-// set of DNS resolutions (IP addresses) in accordance with those rules.
-// Currently the only rules supported use a pattern match against some given IP
-// addresses, and may, if there is a match, place one new IP address at the
-// start of the rewritten address list (re: the "PREFACE" directive).  This
-// supports a common use case where the matching detects an address in a given
-// edge network server group, and the inserted address points to a server that
-// is expected to handle all requests that would otherwise have gone to the
-// given group of servers.
-class NET_EXPORT_PRIVATE IPMappingRules {
- public:
-  IPMappingRules();
-  ~IPMappingRules();
-
-  // Modifies |*addresses| based on the current rules. Returns true if
-  // |addresses| was modified, false otherwise.
-  bool RewriteAddresses(AddressList* addresses) const;
-
-  // Adds a rule to this mapper.
-  // Rules are evaluated against an address list until a first matching rule is
-  // found that applies, causing a modification of the address list.
-  // Each rule consists of one or more of the following pattern and action
-  // directives.
-  //
-  //   RULE: CHANGE_DIRECTIVE | EMPTY
-  //   CHANGE_DIRECTIVE: "PREFACE" SPACE IP_PATTERN SPACE IP_LITERAL
-  //   SPACE: " "
-  //   EMPTY:
-  //
-  //   IP_LITERAL: IP_V6_LITERAL | IP_V4_LITERAL
-  //
-  //   IP_V4_LITERAL: OCTET "." OCTET "." OCTET "." OCTET
-  //   OCTET: decimal number in range 0 ... 255
-  //
-  //   IP_V6_LITERAL:  HEX_COMPONENT  | IP_V6_LITERAL ":" HEX_COMPONENT
-  //   HEX_COMPONENT: hexadecimal values with no more than 4 hex digits
-  //
-  //   IP_PATTERN: IP_V6_PATTERN | IP_V4_PATTERN
-  //
-  //   IP_V6_PATTERN: HEX_PATTERN | IP_V6_PATTERN ":" HEX_PATTERN
-  //   HEX_PATTERN:  HEX_COMPONENT | "[" HEX_GROUP_PATTERN "]" | "*"
-  //   HEX_GROUP_PATTERN: HEX_RANGE | HEX_GROUP_PATTERN "," HEX_RANGE
-  //   HEX_RANGE: HEX_COMPONENT |  HEX_COMPONENT "-" HEX_COMPONENT
-  //
-  //   IP_V4_PATTERN: OCTET_PATTERN "." OCTET_PATTERN "." OCTET_PATTERN
-  //                  "." OCTET_PATTERN
-  //   OCTET_PATTERN:  OCTET | "[" OCTET_GROUP_PATTERN "]" | "*"
-  //   OCTET_GROUP_PATTERN: OCTET_RANGE | OCTET_GROUP_PATTERN "," OCTET_RANGE
-  //   OCTET_RANGE: OCTET | OCTET "-" OCTET
-  //
-  // All literals are required to have all their components specified (4
-  // components for IPv4, and 8 for IPv6).  Specifically, there is currently no
-  // support for elided compenents in an IPv6 address (e.g., "::").
-  // Returns true if the rule was successfully parsed and added.
-  bool AddRuleFromString(const std::string& rule_string);
-
-  // Sets the rules from a semicolon separated list of rules.
-  // Returns true if all the rules were successfully parsed and added.
-  bool SetRulesFromString(const std::string& rules_string);
-
- private:
-  class Rule;
-  typedef std::vector<Rule*> RuleList;
-
-  // We own all rules in this list, and are responsible for their destruction.
-  RuleList rules_;
-
-  DISALLOW_COPY_AND_ASSIGN(IPMappingRules);
-};
-
-}  // namespace net
-
-#endif  // NET_BASE_IP_MAPPING_RULES_H_
diff --git a/net/base/ip_mapping_rules_unittest.cc b/net/base/ip_mapping_rules_unittest.cc
deleted file mode 100644
index 7fd599f..0000000
--- a/net/base/ip_mapping_rules_unittest.cc
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/base/ip_mapping_rules.h"
-
-#include "net/base/address_list.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace {
-
-TEST(IPMappingRulesTest, EmptyRules) {
-  AddressList addresses;
-  // Null rule does nothing to null list.
-  EXPECT_EQ(0u, addresses.size());
-  IPMappingRules rules;
-  EXPECT_FALSE(rules.RewriteAddresses(&addresses));
-  EXPECT_EQ(0u, addresses.size());
-
-  IPAddressNumber address;
-  EXPECT_TRUE(ParseIPLiteralToNumber("1.2.3.4", &address));
-  int port = 80;
-  IPEndPoint endpoint(address, port);
-  addresses.push_back(endpoint);
-  // Null rule does nothing to a simple list.
-  ASSERT_EQ(1u, addresses.size());
-  EXPECT_EQ(addresses[0], endpoint);
-  EXPECT_FALSE(rules.RewriteAddresses(&addresses));
-  ASSERT_EQ(1u, addresses.size());
-  EXPECT_EQ(addresses[0], endpoint);
-
-  EXPECT_TRUE(ParseIPLiteralToNumber("1:2:3:4:a:b:c:def", &address));
-  IPEndPoint endpoint2(address, port);
-  addresses.push_back(endpoint2);
-  // Null rule does nothing to a simple list.
-  ASSERT_EQ(2u, addresses.size());
-  EXPECT_EQ(addresses[0], endpoint);
-  EXPECT_EQ(addresses[1], endpoint2);
-  EXPECT_FALSE(rules.RewriteAddresses(&addresses));
-  ASSERT_EQ(2u, addresses.size());
-  EXPECT_EQ(addresses[0], endpoint);
-  EXPECT_EQ(addresses[1], endpoint2);
-}
-
-// The |inserted_ip| must have a short final component, so that we can just
-// append a digit, and still be a valid (but different) ip address.
-void MatchingInsertionHelper(const std::string& matchable_ip,
-                             const std::string& matching_ip_pattern,
-                             const std::string& inserted_ip,
-                             bool should_match) {
-  AddressList addresses;
-
-  IPAddressNumber address;
-  EXPECT_TRUE(ParseIPLiteralToNumber(matchable_ip, &address));
-  int port = 80;
-  IPEndPoint endpoint(address, port);
-  addresses.push_back(endpoint);
-  // Match the string with a precisely crafted pattern.
-  std::string rule_text("Preface ");
-  rule_text += matching_ip_pattern;
-  rule_text += " ";
-  rule_text += inserted_ip;
-  IPMappingRules rules;
-  EXPECT_TRUE(rules.AddRuleFromString(rule_text));
-
-  ASSERT_EQ(1u, addresses.size());
-  EXPECT_EQ(addresses[0], endpoint);
-  EXPECT_EQ(should_match, rules.RewriteAddresses(&addresses));
-  if (!should_match) {
-    ASSERT_EQ(1u, addresses.size());
-    EXPECT_EQ(addresses[0], endpoint);
-    return;  // Don't bother with the rest of the test.
-  }
-
-  ASSERT_EQ(2u, addresses.size());
-  EXPECT_EQ(addresses[1], endpoint);
-  IPAddressNumber inserted_ip_adress_number;
-  EXPECT_TRUE(ParseIPLiteralToNumber(inserted_ip, &inserted_ip_adress_number));
-  EXPECT_EQ(inserted_ip_adress_number, addresses[0].address());
-
-  // Now we have two addresses.  We'll use new rules, to match the second
-  // address (the original address shifted over) in the list of addresses.
-  rule_text = "Preface ";  // Build up a new rule.
-  rule_text += matching_ip_pattern;
-  rule_text += " ";
-  // Change the inserted IP mildly.
-  std::string different_inserted_ip = inserted_ip + "3";
-  rule_text += different_inserted_ip;
-  // If we don't overwrite the old rule, it will fire first!
-  EXPECT_TRUE(rules.SetRulesFromString(rule_text));  // Overwrite old rules.
-
-  ASSERT_EQ(2u, addresses.size());
-  EXPECT_EQ(addresses[1], endpoint);
-  EXPECT_TRUE(rules.RewriteAddresses(&addresses));
-  ASSERT_EQ(3u, addresses.size());
-  EXPECT_EQ(addresses[2], endpoint);
-  EXPECT_TRUE(ParseIPLiteralToNumber(different_inserted_ip,
-                                     &inserted_ip_adress_number));
-  EXPECT_EQ(inserted_ip_adress_number, addresses[0].address());
-}
-
-TEST(IPMappingRulesTest, SimpleMatchingInsertionIPV4) {
-  std::string matchable_ip("1.2.3.4");
-  std::string matching_ip_pattern(matchable_ip);
-  std::string new_preface_ip("7.8.9.24");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, SimpleMatchingInsertionIPV6) {
-  std::string matchable_ip("1:2:3:4:5:6:7:8");
-  std::string matching_ip_pattern(matchable_ip);
-  std::string new_preface_ip("A:B:C:D:1:2:3:4");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, SimpleMissatchingInsertionIPV4) {
-  std::string matchable_ip("1.2.3.4");
-  std::string matching_ip_pattern(matchable_ip + "7");
-  std::string new_preface_ip("7.8.9.24");
-  bool should_match = false;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, SimpleMisatchingInsertionIPV6) {
-  std::string matchable_ip("1:2:3:4:5:6:7:8");
-  std::string matching_ip_pattern(matchable_ip + "e");
-  std::string new_preface_ip("A:B:C:D:1:2:3:4");
-  bool should_match = false;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, AlternativeMatchingInsertionIPV4) {
-  std::string matchable_ip("1.2.3.4");
-  std::string matching_ip_pattern("1.2.3.[2,4,6]");
-  std::string new_preface_ip("7.8.9.24");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, AlternativeMatchingInsertionIPV6) {
-  std::string matchable_ip("1:2:3:4:5:6:7:abcd");
-  std::string matching_ip_pattern("1:2:3:4:5:6:7:[abc2,abc9,abcd,cdef]");
-  std::string new_preface_ip("A:B:C:D:1:2:3:4");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, RangeMatchingInsertionIPV4) {
-  std::string matchable_ip("1.2.3.4");
-  std::string matching_ip_pattern("1.2.3.[2-6,22]");
-  std::string new_preface_ip("7.8.9.24");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, RandgeMatchingInsertionIPV6) {
-  std::string matchable_ip("1:2:3:4:5:6:7:abcd");
-  // Note: This test can detect confusion over high vs low-order bytes in an
-  // IPv6 component.  If the code confused them, then this range would not
-  // include the matchable_ip.
-  std::string matching_ip_pattern("1:2:3:4:5:6:7:[abc2-cdc2]");
-  std::string new_preface_ip("A:B:C:D:1:2:3:4");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, WildMatchingInsertionIPV4) {
-  std::string matchable_ip("1.2.3.4");
-  std::string matching_ip_pattern("1.2.3.*");
-  std::string new_preface_ip("7.8.9.24");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, WildMatchingInsertionIPV6) {
-  std::string matchable_ip("1:2:3:4:5:6:7:abcd");
-  // Note: This test can detect confusion over high vs low-order bytes in an
-  // IPv6 component.  If the code confused them, then this range would not
-  // include the matchable_ip.
-  std::string matching_ip_pattern("1:2:3:4:5:6:7:*");
-  std::string new_preface_ip("A:B:C:D:1:2:3:4");
-  bool should_match = true;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, WildNotMatchingInsertionIPV4) {
-  std::string matchable_ip("1.2.3.4");
-  std::string matching_ip_pattern("*.200.*.*");
-  std::string new_preface_ip("7.8.9.24");
-  bool should_match = false;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, WildNotMatchingInsertionIPV6) {
-  std::string matchable_ip("1:2:3:4:5:6:7:8");
-  // Note: This test can detect confusion over high vs low-order bytes in an
-  // IPv6 component.  If the code confused them, then this range would not
-  // include the matchable_ip.
-  std::string matching_ip_pattern("*:*:37af:*:*:*:*:*");
-  std::string new_preface_ip("A:B:C:D:1:2:3:4");
-  bool should_match = false;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-TEST(IPMappingRulesTest, IPv4NotMatchForIPV6) {
-  std::string matchable_ip("1:2:3:4:5:6:7:abcd");
-  // Note: This test can detect confusion over high vs low-order bytes in an
-  // IPv6 component.  If the code confused them, then this range would not
-  // include the matchable_ip.
-  std::string matching_ip_pattern("1.2.3.4");
-  std::string new_preface_ip("10.20.30.40");  // Compatible with pattern.
-  bool should_match = false;
-  MatchingInsertionHelper(matchable_ip, matching_ip_pattern, new_preface_ip,
-                          should_match);
-}
-
-// Parsing bad rules should silently discard the rule (and never crash).
-TEST(IPMappingRulesTest, ParseInvalidRules) {
-  IPMappingRules rules;
-
-  EXPECT_FALSE(rules.AddRuleFromString("Too short"));
-  EXPECT_FALSE(rules.AddRuleFromString("Preface much too long"));
-  EXPECT_FALSE(rules.AddRuleFromString("PrefaceNotSpelled 1.2.3.4 1.2.3.4"));
-
-  // Ipv4 problems
-  EXPECT_FALSE(rules.AddRuleFromString("Preface 1.2.a.4 1.2.3.4"));
-  EXPECT_FALSE(rules.AddRuleFromString("Preface 1.2.3.4.5 1.2.3.4"));
-  EXPECT_FALSE(rules.AddRuleFromString("Preface 1.2.3.4 1.2.3.4.5"));
-  EXPECT_FALSE(rules.AddRuleFromString("Preface 1.2.3.4 1.2.3.4-5"));
-  EXPECT_FALSE(rules.AddRuleFromString("Preface 1.2.3.4-5-6 1.2.3.4"));
-
-  // IPv6 problems
-  EXPECT_FALSE(rules.AddRuleFromString(
-      "Preface 1:2:3:4:5:6:7:g 1:2:3:4:5:6:7:8"));
-  EXPECT_FALSE(rules.AddRuleFromString(
-      "Preface 1:2:3:4:5:6:7:8 1:g:3:4:5:6:7:8"));
-  EXPECT_FALSE(rules.AddRuleFromString(
-      "Preface 1:2:3:4:5:6:7:8:9 1:2:3:4:5:6:7:8"));
-  EXPECT_FALSE(rules.AddRuleFromString(
-      "Preface 1:2:3:4:5:6:7:8 1:2:3:4:5:6:7:8:0"));
-  EXPECT_FALSE(rules.AddRuleFromString(
-      "Preface 1:2:3:4:5:6:7:8 1:2:3:4:5:6:7:8-A"));
-  EXPECT_FALSE(rules.AddRuleFromString(
-      "Preface 1:2:3:4:5:6:7:8-A-B 1:2:3:4:5:6:7:8"));
-
-  // Don't mix ipv4 and ipv6.
-  EXPECT_FALSE(rules.AddRuleFromString("Preface 1.2.3.4 1:2:3:4:5:6:7:8"));
-
-  EXPECT_FALSE(rules.SetRulesFromString("Preface 1.2.3.4 5.6.7.8; bad"));
-}
-
-
-TEST(IPMappingRulesTest, FirstRuleToMatch) {
-  std::string first_replacement("1.1.1.1");
-  IPAddressNumber first_replacement_address;
-  EXPECT_TRUE(ParseIPLiteralToNumber(first_replacement,
-              &first_replacement_address));
-
-  std::string second_replacement("2.2.2.2");
-  IPAddressNumber second_replacement_address;
-  EXPECT_TRUE(ParseIPLiteralToNumber(second_replacement,
-              &second_replacement_address));
-
-  IPMappingRules rules;
-  EXPECT_TRUE(
-      rules.SetRulesFromString("Preface *.*.*.* " + first_replacement +
-                               ";Preface *.*.*.* " + second_replacement));
-
-  IPAddressNumber address;
-  EXPECT_TRUE(ParseIPLiteralToNumber("7.7.7.7", &address));
-  int port = 80;
-  IPEndPoint endpoint(address, port);
-  AddressList addresses;
-  addresses.push_back(endpoint);
-
-  ASSERT_EQ(1u, addresses.size());
-  EXPECT_EQ(addresses[0], endpoint);
-  EXPECT_TRUE(rules.RewriteAddresses(&addresses));
-  ASSERT_EQ(2u, addresses.size());
-  EXPECT_EQ(addresses[1], endpoint);
-  // The last rule added  to the list has the highest priority (overriding
-  // previous rules, and matching first).
-  EXPECT_NE(addresses[0].address(), first_replacement_address);
-  EXPECT_EQ(addresses[0].address(), second_replacement_address);
-}
-
-}  // namespace
-
-}  // namespace net
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index b2ddd4a..37c84c7 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -313,6 +313,12 @@
 // The SSL server sent us a fatal unrecognized_name alert.
 NET_ERROR(SSL_UNRECOGNIZED_NAME_ALERT, -159)
 
+// Failed to set or change the socket's receive buffer size as requested
+NET_ERROR(SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR, -160)
+
+// Failed to set or change the socket's send buffer size as requested.
+NET_ERROR(SOCKET_SET_SEND_BUFFER_SIZE_ERROR, -161)
+
 // Certificate error codes
 //
 // The values of certificate error codes must be consecutive.
diff --git a/net/base/net_util.h b/net/base/net_util.h
index 04a9b2d..8a20a25 100644
--- a/net/base/net_util.h
+++ b/net/base/net_util.h
@@ -530,10 +530,13 @@
 
 typedef std::vector<NetworkInterface> NetworkInterfaceList;
 
-// Policy settings to include/exclude VMWare host only network interfaces.
-enum HostScopeVirtualInterfacePolicy {
-  INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES,
-  EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES,
+// Policy settings to include/exclude network interfaces.
+enum HostAddressSelectionPolicy {
+  EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES           = 0x1,
+  INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES           = 0x2,
+  // Include temp address only when interface has both permanent and
+  // temp addresses.
+  INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE      = 0x4,
 };
 
 // Returns list of network interfaces except loopback interface. If an
@@ -541,7 +544,7 @@
 // the list for each address.
 // Can be called only on a thread that allows IO.
 NET_EXPORT bool GetNetworkList(NetworkInterfaceList* networks,
-                               HostScopeVirtualInterfacePolicy policy);
+                               int policy);
 
 // General category of the IEEE 802.11 (wifi) physical layer operating mode.
 enum WifiPHYLayerProtocol {
diff --git a/net/base/net_util_posix.cc b/net/base/net_util_posix.cc
index 8b9e067..95b963e 100644
--- a/net/base/net_util_posix.cc
+++ b/net/base/net_util_posix.cc
@@ -4,6 +4,7 @@
 
 #include "net/base/net_util.h"
 
+#include <set>
 #include <sys/types.h>
 
 #include "base/files/file_path.h"
@@ -23,12 +24,67 @@
 #include <net/if.h>
 #include <netinet/in.h>
 
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+#include <netinet/in_var.h>
+#include <sys/ioctl.h>
+#endif
+
 #if defined(OS_ANDROID)
 #include "net/android/network_library.h"
 #endif
 
 namespace net {
 
+namespace {
+
+#if !defined(OS_ANDROID)
+
+struct NetworkInterfaceInfo {
+  NetworkInterfaceInfo() : permanent(true) { }
+
+  bool permanent;  // IPv6 has notion of temporary address. If the address is
+                   // IPv6 and it's temporary this field will be false.
+  NetworkInterface interface;
+};
+
+// This method will remove permanent IPv6 addresses if a temporary address
+// is available for same network interface.
+void RemovePermanentIPv6AddressesWhereTemporaryExists(
+    std::vector<NetworkInterfaceInfo>* infos) {
+  if (!infos || infos->empty())
+    return;
+
+  // Build a set containing the names of interfaces with a temp IPv6 address
+  std::set<std::string> ifaces_with_temp_addrs;
+  std::vector<NetworkInterfaceInfo>::iterator i;
+  for (i = infos->begin(); i != infos->end(); ++i) {
+    if (!i->permanent && i->interface.address.size() == kIPv6AddressSize) {
+      ifaces_with_temp_addrs.insert(i->interface.name);
+    }
+  }
+
+  // If there are no such interfaces then there's no further work.
+  if (ifaces_with_temp_addrs.empty())
+    return;
+
+  // Search for permenent addresses belonging to same network interface.
+  for (i = infos->begin(); i != infos->end(); ) {
+    // If the address is IPv6 and it's permanent and there is temporary
+    // address for it, then we can remove this address.
+    if ((i->interface.address.size() == kIPv6AddressSize) && i->permanent &&
+        (ifaces_with_temp_addrs.find(i->interface.name) !=
+            ifaces_with_temp_addrs.end())) {
+      i = infos->erase(i);
+    } else {
+      ++i;
+    }
+  }
+}
+
+#endif
+
+}  // namespace
+
 bool FileURLToFilePath(const GURL& url, base::FilePath* path) {
   *path = base::FilePath();
   std::string& file_path_str = const_cast<std::string&>(path->value());
@@ -63,8 +119,7 @@
   return !file_path_str.empty();
 }
 
-bool GetNetworkList(NetworkInterfaceList* networks,
-                    HostScopeVirtualInterfacePolicy policy) {
+bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
 #if defined(OS_ANDROID)
   std::string network_list = android::GetNetworkList();
   base::StringTokenizer network_interfaces(network_list, "\n");
@@ -94,12 +149,21 @@
   // getifaddrs() may require IO operations.
   base::ThreadRestrictions::AssertIOAllowed();
 
+  int ioctl_socket = -1;
+  if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) {
+    // we need a socket to query information about temporary address.
+    ioctl_socket = socket(AF_INET6, SOCK_DGRAM, 0);
+    DCHECK_GT(ioctl_socket, 0);
+  }
+
   ifaddrs *interfaces;
   if (getifaddrs(&interfaces) < 0) {
     PLOG(ERROR) << "getifaddrs";
     return false;
   }
 
+  std::vector<NetworkInterfaceInfo> network_infos;
+
   // Enumerate the addresses assigned to network interfaces which are up.
   for (ifaddrs *interface = interfaces;
        interface != NULL;
@@ -141,11 +205,29 @@
 
     const std::string& name = interface->ifa_name;
     // Filter out VMware interfaces, typically named vmnet1 and vmnet8.
-    if (policy == EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES &&
+    if ((policy & EXCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES) &&
         ((name.find("vmnet") != std::string::npos) ||
          (name.find("vnic") != std::string::npos))) {
       continue;
     }
+
+    NetworkInterfaceInfo network_info;
+#if defined(OS_MACOSX) && !defined(OS_IOS)
+    // Check if this is a temporary address. Currently this is only supported
+    // on Mac.
+    if ((policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) &&
+        ioctl_socket >= 0 && addr->sa_family == AF_INET6) {
+      struct in6_ifreq ifr = {};
+      strncpy(ifr.ifr_name, interface->ifa_name, sizeof(ifr.ifr_name) - 1);
+      memcpy(&ifr.ifr_ifru.ifru_addr, interface->ifa_addr,
+             interface->ifa_addr->sa_len);
+      int rv = ioctl(ioctl_socket, SIOCGIFAFLAG_IN6, &ifr);
+      if (rv >= 0) {
+        network_info.permanent = !(ifr.ifr_ifru.ifru_flags & IN6_IFF_TEMPORARY);
+      }
+    }
+#endif
+
     IPEndPoint address;
     if (address.FromSockAddr(addr, addr_size)) {
       uint8 net_mask = 0;
@@ -159,15 +241,25 @@
           net_mask = MaskPrefixLength(netmask.address());
         }
       }
+      network_info.interface = NetworkInterface(
+          name, name, if_nametoindex(name.c_str()),
+          address.address(), net_mask);
 
-      networks->push_back(
-          NetworkInterface(name, name, if_nametoindex(name.c_str()),
-                           address.address(), net_mask));
+      network_infos.push_back(NetworkInterfaceInfo(network_info));
     }
   }
-
   freeifaddrs(interfaces);
+  if (ioctl_socket >= 0) {
+    close(ioctl_socket);
+  }
 
+  if (policy & INCLUDE_ONLY_TEMP_IPV6_ADDRESS_IF_POSSIBLE) {
+    RemovePermanentIPv6AddressesWhereTemporaryExists(&network_infos);
+  }
+
+  for (size_t i = 0; i < network_infos.size(); ++i) {
+    networks->push_back(network_infos[i].interface);
+  }
   return true;
 #endif
 }
diff --git a/net/base/net_util_win.cc b/net/base/net_util_win.cc
index f415808..de85ce5 100644
--- a/net/base/net_util_win.cc
+++ b/net/base/net_util_win.cc
@@ -138,8 +138,7 @@
   return true;
 }
 
-bool GetNetworkList(NetworkInterfaceList* networks,
-                    HostScopeVirtualInterfacePolicy policy) {
+bool GetNetworkList(NetworkInterfaceList* networks, int policy) {
   // GetAdaptersAddresses() may require IO operations.
   base::ThreadRestrictions::AssertIOAllowed();
   bool is_xp = base::win::GetVersion() < base::win::VERSION_VISTA;
diff --git a/net/base/network_change_notifier_win_unittest.cc b/net/base/network_change_notifier_win_unittest.cc
index 96dcd13..878060e 100644
--- a/net/base/network_change_notifier_win_unittest.cc
+++ b/net/base/network_change_notifier_win_unittest.cc
@@ -228,12 +228,14 @@
   StartWatchingAndFail();
 }
 
-TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartOnce) {
+// https://code.google.com/p/chromium/issues/detail?id=356401
+TEST_F(NetworkChangeNotifierWinTest, FLAKY_NetChangeWinFailStartOnce) {
   StartWatchingAndFail();
   RetryAndSucceed();
 }
 
-TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailStartTwice) {
+// https://code.google.com/p/chromium/issues/detail?id=356401
+TEST_F(NetworkChangeNotifierWinTest, FLAKY_NetChangeWinFailStartTwice) {
   StartWatchingAndFail();
   RetryAndFail();
   RetryAndSucceed();
@@ -244,13 +246,15 @@
   SignalAndSucceed();
 }
 
-TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalOnce) {
+// https://code.google.com/p/chromium/issues/detail?id=356401
+TEST_F(NetworkChangeNotifierWinTest, FLAKY_NetChangeWinFailSignalOnce) {
   StartWatchingAndSucceed();
   SignalAndFail();
   RetryAndSucceed();
 }
 
-TEST_F(NetworkChangeNotifierWinTest, NetChangeWinFailSignalTwice) {
+// https://code.google.com/p/chromium/issues/detail?id=356401
+TEST_F(NetworkChangeNotifierWinTest, FLAKY_NetChangeWinFailSignalTwice) {
   StartWatchingAndSucceed();
   SignalAndFail();
   RetryAndFail();
diff --git a/net/base/network_delegate.cc b/net/base/network_delegate.cc
index 517868a..d30a4ab 100644
--- a/net/base/network_delegate.cc
+++ b/net/base/network_delegate.cc
@@ -39,12 +39,16 @@
     URLRequest* request,
     const CompletionCallback& callback,
     const HttpResponseHeaders* original_response_headers,
-    scoped_refptr<HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   DCHECK(CalledOnValidThread());
   DCHECK(original_response_headers);
   DCHECK(!callback.is_null());
-  return OnHeadersReceived(request, callback, original_response_headers,
-                           override_response_headers);
+  return OnHeadersReceived(request,
+                           callback,
+                           original_response_headers,
+                           override_response_headers,
+                           allowed_unsafe_redirect_url);
 }
 
 void NetworkDelegate::NotifyResponseStarted(URLRequest* request) {
@@ -155,7 +159,8 @@
     URLRequest* request,
     const CompletionCallback& callback,
     const HttpResponseHeaders* original_response_headers,
-    scoped_refptr<HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   return OK;
 }
 
diff --git a/net/base/network_delegate.h b/net/base/network_delegate.h
index 882701c..4f930cf 100644
--- a/net/base/network_delegate.h
+++ b/net/base/network_delegate.h
@@ -69,7 +69,8 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers);
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url);
   void NotifyBeforeRedirect(URLRequest* request,
                             const GURL& new_location);
   void NotifyResponseStarted(URLRequest* request);
@@ -140,7 +141,8 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers);
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url);
 
   // Called right after a redirect response code was received.
   // |new_location| is only valid until OnURLRequestDestroyed is called for this
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc
index 04f330f..8ee4069 100644
--- a/net/cert/cert_verify_proc.cc
+++ b/net/cert/cert_verify_proc.cc
@@ -20,7 +20,7 @@
 
 #if defined(USE_NSS) || defined(OS_IOS)
 #include "net/cert/cert_verify_proc_nss.h"
-#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
+#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
 #include "net/cert/cert_verify_proc_openssl.h"
 #elif defined(OS_ANDROID)
 #include "net/cert/cert_verify_proc_android.h"
@@ -167,7 +167,7 @@
 CertVerifyProc* CertVerifyProc::CreateDefault() {
 #if defined(USE_NSS) || defined(OS_IOS)
   return new CertVerifyProcNSS();
-#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
+#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
   return new CertVerifyProcOpenSSL();
 #elif defined(OS_ANDROID)
   return new CertVerifyProcAndroid();
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc
index 9d7e750..6567d16 100644
--- a/net/cert/cert_verify_proc_unittest.cc
+++ b/net/cert/cert_verify_proc_unittest.cc
@@ -157,7 +157,7 @@
                    &verify_result));
 }
 
-#if defined(OS_ANDROID) || defined(USE_OPENSSL)
+#if defined(OS_ANDROID) || defined(USE_OPENSSL_CERTS)
 // TODO(jnd): http://crbug.com/117478 - EV verification is not yet supported.
 #define MAYBE_EVVerification DISABLED_EVVerification
 #else
@@ -724,7 +724,7 @@
                      NULL,
                      empty_cert_list_,
                      &verify_result);
-#if defined(USE_OPENSSL) && !defined(OS_ANDROID)
+#if defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
   // This certificate has two errors: "invalid key usage" and "untrusted CA".
   // However, OpenSSL returns only one (the latter), and we can't detect
   // the other errors.
@@ -1013,6 +1013,9 @@
   EXPECT_EQ(0U, verify_result.cert_status);
   // But should not be marked as a known root.
   EXPECT_FALSE(verify_result.is_issued_by_known_root);
+
+  root_certs->Clear();
+  EXPECT_TRUE(root_certs->IsEmpty());
 }
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
@@ -1133,6 +1136,8 @@
   EXPECT_EQ(OK, error);
   EXPECT_EQ(0U, verify_result.cert_status);
 
+  TestRootCerts::GetInstance()->Clear();
+  EXPECT_TRUE(TestRootCerts::GetInstance()->IsEmpty());
 }
 #endif
 
@@ -1402,7 +1407,7 @@
 const WeakDigestTestData kVerifyRootCATestData[] = {
   { "weak_digest_md5_root.pem", "weak_digest_sha1_intermediate.pem",
     "weak_digest_sha1_ee.pem", false, false, false },
-#if defined(USE_OPENSSL) || defined(OS_WIN)
+#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
   // MD4 is not supported by OS X / NSS
   { "weak_digest_md4_root.pem", "weak_digest_sha1_intermediate.pem",
     "weak_digest_sha1_ee.pem", false, false, false },
@@ -1417,7 +1422,7 @@
 const WeakDigestTestData kVerifyIntermediateCATestData[] = {
   { "weak_digest_sha1_root.pem", "weak_digest_md5_intermediate.pem",
     "weak_digest_sha1_ee.pem", true, false, false },
-#if defined(USE_OPENSSL) || defined(OS_WIN)
+#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
   // MD4 is not supported by OS X / NSS
   { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
     "weak_digest_sha1_ee.pem", false, true, false },
@@ -1440,7 +1445,7 @@
 const WeakDigestTestData kVerifyEndEntityTestData[] = {
   { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
     "weak_digest_md5_ee.pem", true, false, false },
-#if defined(USE_OPENSSL) || defined(OS_WIN)
+#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
   // MD4 is not supported by OS X / NSS
   { "weak_digest_sha1_root.pem", "weak_digest_sha1_intermediate.pem",
     "weak_digest_md4_ee.pem", false, true, false },
@@ -1464,7 +1469,7 @@
 const WeakDigestTestData kVerifyIncompleteIntermediateTestData[] = {
   { NULL, "weak_digest_md5_intermediate.pem", "weak_digest_sha1_ee.pem",
     true, false, false },
-#if defined(USE_OPENSSL) || defined(OS_WIN)
+#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
   // MD4 is not supported by OS X / NSS
   { NULL, "weak_digest_md4_intermediate.pem", "weak_digest_sha1_ee.pem",
     false, true, false },
@@ -1489,7 +1494,7 @@
 const WeakDigestTestData kVerifyIncompleteEETestData[] = {
   { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md5_ee.pem",
     true, false, false },
-#if defined(USE_OPENSSL) || defined(OS_WIN)
+#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
   // MD4 is not supported by OS X / NSS
   { NULL, "weak_digest_sha1_intermediate.pem", "weak_digest_md4_ee.pem",
     false, true, false },
@@ -1516,7 +1521,7 @@
     "weak_digest_md2_ee.pem", true, false, true },
   { "weak_digest_sha1_root.pem", "weak_digest_md2_intermediate.pem",
     "weak_digest_md5_ee.pem", true, false, true },
-#if defined(USE_OPENSSL) || defined(OS_WIN)
+#if defined(USE_OPENSSL_CERTS) || defined(OS_WIN)
   // MD4 is not supported by OS X / NSS
   { "weak_digest_sha1_root.pem", "weak_digest_md4_intermediate.pem",
     "weak_digest_md2_ee.pem", false, true, true },
diff --git a/net/cert/test_root_certs.h b/net/cert/test_root_certs.h
index cf35a2a..84c163a 100644
--- a/net/cert/test_root_certs.h
+++ b/net/cert/test_root_certs.h
@@ -12,7 +12,7 @@
 
 #if defined(USE_NSS) || defined(OS_IOS)
 #include <list>
-#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
+#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
 #include <vector>
 #elif defined(OS_WIN)
 #include <windows.h>
@@ -25,7 +25,7 @@
 
 #if defined(USE_NSS)
 typedef struct CERTCertificateStr CERTCertificate;
-#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
+#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
 typedef struct x509_st X509;
 #endif
 
@@ -78,7 +78,7 @@
   // be trusted. By default, this is true, indicating that the TestRootCerts
   // are used in addition to OS trust store.
   void SetAllowSystemTrust(bool allow_system_trust);
-#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
+#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
   const std::vector<scoped_refptr<X509Certificate> >&
       temporary_roots() const { return temporary_roots_; }
   bool Contains(X509* cert) const;
@@ -106,7 +106,7 @@
   // settings, in order to restore them when Clear() is called.
   class TrustEntry;
   std::list<TrustEntry*> trust_cache_;
-#elif defined(USE_OPENSSL) && !defined(OS_ANDROID)
+#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
   std::vector<scoped_refptr<X509Certificate> > temporary_roots_;
 #elif defined(OS_WIN)
   HCERTSTORE temporary_roots_;
diff --git a/net/cert/test_root_certs_unittest.cc b/net/cert/test_root_certs_unittest.cc
index 81926be..a2cf695 100644
--- a/net/cert/test_root_certs_unittest.cc
+++ b/net/cert/test_root_certs_unittest.cc
@@ -135,7 +135,7 @@
   EXPECT_EQ(bad_verify_result.cert_status, restored_verify_result.cert_status);
 }
 
-#if defined(USE_NSS) || (defined(USE_OPENSSL) && !defined(OS_ANDROID))
+#if defined(USE_NSS) || (defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID))
 TEST(TestRootCertsTest, Contains) {
   // Another test root certificate.
   const char kRootCertificateFile2[] = "2048-rsa-root.pem";
diff --git a/net/cert/x509_certificate.h b/net/cert/x509_certificate.h
index 43ed014..7aa48f0 100644
--- a/net/cert/x509_certificate.h
+++ b/net/cert/x509_certificate.h
@@ -25,7 +25,7 @@
 #include <CoreFoundation/CFArray.h>
 #include <Security/SecBase.h>
 
-#elif defined(USE_OPENSSL)
+#elif defined(USE_OPENSSL_CERTS)
 // Forward declaration; real one in <x509.h>
 typedef struct x509_st X509;
 typedef struct x509_store_st X509_STORE;
@@ -58,7 +58,7 @@
   typedef PCCERT_CONTEXT OSCertHandle;
 #elif defined(OS_MACOSX)
   typedef SecCertificateRef OSCertHandle;
-#elif defined(USE_OPENSSL)
+#elif defined(USE_OPENSSL_CERTS)
   typedef X509* OSCertHandle;
 #elif defined(USE_NSS)
   typedef struct CERTCertificateStr* OSCertHandle;
@@ -304,7 +304,7 @@
   PCCERT_CONTEXT CreateOSCertChainForCert() const;
 #endif
 
-#if defined(USE_OPENSSL)
+#if defined(USE_OPENSSL_CERTS)
   // Returns a handle to a global, in-memory certificate store. We
   // use it for test code, e.g. importing the test server's certificate.
   static X509_STORE* cert_store();
@@ -413,7 +413,7 @@
   // Common object initialization code.  Called by the constructors only.
   void Initialize();
 
-#if defined(USE_OPENSSL)
+#if defined(USE_OPENSSL_CERTS)
   // Resets the store returned by cert_store() to default state. Used by
   // TestRootCerts to undo modifications.
   static void ResetCertStore();
diff --git a/net/cert/x509_certificate_mac.cc b/net/cert/x509_certificate_mac.cc
index a7f8624..ab47938 100644
--- a/net/cert/x509_certificate_mac.cc
+++ b/net/cert/x509_certificate_mac.cc
@@ -196,33 +196,6 @@
   }
 }
 
-struct CSSMOIDString {
-  const CSSM_OID* oid_;
-  std::string string_;
-};
-
-typedef std::vector<CSSMOIDString> CSSMOIDStringVector;
-
-class ScopedEncodedCertResults {
- public:
-  explicit ScopedEncodedCertResults(CSSM_TP_RESULT_SET* results)
-      : results_(results) { }
-  ~ScopedEncodedCertResults() {
-    if (results_) {
-      CSSM_ENCODED_CERT* encCert =
-          reinterpret_cast<CSSM_ENCODED_CERT*>(results_->Results);
-      for (uint32 i = 0; i < results_->NumberOfResults; i++) {
-        crypto::CSSMFree(encCert[i].CertBlob.Data);
-      }
-      crypto::CSSMFree(results_->Results);
-      crypto::CSSMFree(results_);
-    }
-  }
-
- private:
-  CSSM_TP_RESULT_SET* results_;
-};
-
 }  // namespace
 
 void X509Certificate::Initialize() {
diff --git a/net/cert_verify_status_android_java.target.darwin-arm.mk b/net/cert_verify_status_android_java.target.darwin-arm.mk
index 0ee66cf..1dfb9bd 100644
--- a/net/cert_verify_status_android_java.target.darwin-arm.mk
+++ b/net/cert_verify_status_android_java.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/cert_verify_status_android_java.target.darwin-mips.mk b/net/cert_verify_status_android_java.target.darwin-mips.mk
index 73fb42a..745c8c2 100644
--- a/net/cert_verify_status_android_java.target.darwin-mips.mk
+++ b/net/cert_verify_status_android_java.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/cert_verify_status_android_java.target.darwin-x86.mk b/net/cert_verify_status_android_java.target.darwin-x86.mk
index df708b9..492877c 100644
--- a/net/cert_verify_status_android_java.target.darwin-x86.mk
+++ b/net/cert_verify_status_android_java.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/cert_verify_status_android_java.target.darwin-x86_64.mk b/net/cert_verify_status_android_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..cdabc2b
--- /dev/null
+++ b/net/cert_verify_status_android_java.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_cert_verify_status_android_java_gyp
+LOCAL_MODULE_STEM := cert_verify_status_android_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_cert_verify_status_android_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'android/cert_verify_status_android_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/CertVerifyStatusAndroid.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: $(LOCAL_PATH)/net/android/java/CertVerifyStatusAndroid.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/android/cert_verify_status_android_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java" "--template=android/java/CertVerifyStatusAndroid.template"
+
+.PHONY: net_cert_verify_status_android_java_gyp_rule_trigger
+net_cert_verify_status_android_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_cert_verify_status_android_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_cert_verify_status_android_java_gyp
+
+# Alias gyp target name.
+.PHONY: cert_verify_status_android_java
+cert_verify_status_android_java: net_cert_verify_status_android_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/cert_verify_status_android_java.target.linux-arm.mk b/net/cert_verify_status_android_java.target.linux-arm.mk
index 0ee66cf..1dfb9bd 100644
--- a/net/cert_verify_status_android_java.target.linux-arm.mk
+++ b/net/cert_verify_status_android_java.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/cert_verify_status_android_java.target.linux-mips.mk b/net/cert_verify_status_android_java.target.linux-mips.mk
index 73fb42a..745c8c2 100644
--- a/net/cert_verify_status_android_java.target.linux-mips.mk
+++ b/net/cert_verify_status_android_java.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/cert_verify_status_android_java.target.linux-x86.mk b/net/cert_verify_status_android_java.target.linux-x86.mk
index df708b9..492877c 100644
--- a/net/cert_verify_status_android_java.target.linux-x86.mk
+++ b/net/cert_verify_status_android_java.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/cert_verify_status_android_java.target.linux-x86_64.mk b/net/cert_verify_status_android_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..cdabc2b
--- /dev/null
+++ b/net/cert_verify_status_android_java.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_cert_verify_status_android_java_gyp
+LOCAL_MODULE_STEM := cert_verify_status_android_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_cert_verify_status_android_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'android/cert_verify_status_android_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/CertVerifyStatusAndroid.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java: $(LOCAL_PATH)/net/android/java/CertVerifyStatusAndroid.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/android/cert_verify_status_android_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java" "--template=android/java/CertVerifyStatusAndroid.template"
+
+.PHONY: net_cert_verify_status_android_java_gyp_rule_trigger
+net_cert_verify_status_android_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertVerifyStatusAndroid.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_cert_verify_status_android_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_cert_verify_status_android_java_gyp
+
+# Alias gyp target name.
+.PHONY: cert_verify_status_android_java
+cert_verify_status_android_java: net_cert_verify_status_android_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/certificate_mime_types_java.target.darwin-arm.mk b/net/certificate_mime_types_java.target.darwin-arm.mk
index 65c5467..9b2ad25 100644
--- a/net/certificate_mime_types_java.target.darwin-arm.mk
+++ b/net/certificate_mime_types_java.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/certificate_mime_types_java.target.darwin-mips.mk b/net/certificate_mime_types_java.target.darwin-mips.mk
index 6cef8b5..21f56e8 100644
--- a/net/certificate_mime_types_java.target.darwin-mips.mk
+++ b/net/certificate_mime_types_java.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/certificate_mime_types_java.target.darwin-x86.mk b/net/certificate_mime_types_java.target.darwin-x86.mk
index 15771eb..3df9060 100644
--- a/net/certificate_mime_types_java.target.darwin-x86.mk
+++ b/net/certificate_mime_types_java.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/certificate_mime_types_java.target.darwin-x86_64.mk b/net/certificate_mime_types_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..b424379
--- /dev/null
+++ b/net/certificate_mime_types_java.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_certificate_mime_types_java_gyp
+LOCAL_MODULE_STEM := certificate_mime_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_certificate_mime_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'base/mime_util_certificate_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/CertificateMimeType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: $(LOCAL_PATH)/net/android/java/CertificateMimeType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/base/mime_util_certificate_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java" "--template=android/java/CertificateMimeType.template"
+
+.PHONY: net_certificate_mime_types_java_gyp_rule_trigger
+net_certificate_mime_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_certificate_mime_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_certificate_mime_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: certificate_mime_types_java
+certificate_mime_types_java: net_certificate_mime_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/certificate_mime_types_java.target.linux-arm.mk b/net/certificate_mime_types_java.target.linux-arm.mk
index 65c5467..9b2ad25 100644
--- a/net/certificate_mime_types_java.target.linux-arm.mk
+++ b/net/certificate_mime_types_java.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/certificate_mime_types_java.target.linux-mips.mk b/net/certificate_mime_types_java.target.linux-mips.mk
index 6cef8b5..21f56e8 100644
--- a/net/certificate_mime_types_java.target.linux-mips.mk
+++ b/net/certificate_mime_types_java.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/certificate_mime_types_java.target.linux-x86.mk b/net/certificate_mime_types_java.target.linux-x86.mk
index 15771eb..3df9060 100644
--- a/net/certificate_mime_types_java.target.linux-x86.mk
+++ b/net/certificate_mime_types_java.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/certificate_mime_types_java.target.linux-x86_64.mk b/net/certificate_mime_types_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..b424379
--- /dev/null
+++ b/net/certificate_mime_types_java.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_certificate_mime_types_java_gyp
+LOCAL_MODULE_STEM := certificate_mime_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_certificate_mime_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'base/mime_util_certificate_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/CertificateMimeType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java: $(LOCAL_PATH)/net/android/java/CertificateMimeType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/base/mime_util_certificate_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java" "--template=android/java/CertificateMimeType.template"
+
+.PHONY: net_certificate_mime_types_java_gyp_rule_trigger
+net_certificate_mime_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/CertificateMimeType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_certificate_mime_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_certificate_mime_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: certificate_mime_types_java
+certificate_mime_types_java: net_certificate_mime_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 455484e..5a06922 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -187,11 +187,6 @@
       const CookieOptions& options,
       const GetCookieListCallback& callback);
 
-  // Invokes GetAllCookiesForURLWithOptions with options set to include HTTP
-  // only cookies.
-  void GetAllCookiesForURLAsync(const GURL& url,
-                                const GetCookieListCallback& callback);
-
   // Deletes all of the cookies.
   void DeleteAllAsync(const DeleteCallback& callback);
 
@@ -257,6 +252,12 @@
       const CookieOptions& options,
       const GetCookiesCallback& callback) OVERRIDE;
 
+  // Invokes GetAllCookiesForURLWithOptions with options set to include HTTP
+  // only cookies.
+  virtual void GetAllCookiesForURLAsync(
+      const GURL& url,
+      const GetCookieListCallback& callback) OVERRIDE;
+
   // Deletes all cookies with that might apply to |url| that has |cookie_name|.
   virtual void DeleteCookieAsync(
       const GURL& url, const std::string& cookie_name,
diff --git a/net/cookies/cookie_store.h b/net/cookies/cookie_store.h
index 730f710..b2552a6 100644
--- a/net/cookies/cookie_store.h
+++ b/net/cookies/cookie_store.h
@@ -15,6 +15,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
+#include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_options.h"
 
 class GURL;
@@ -28,8 +29,8 @@
 class NET_EXPORT CookieStore : public base::RefCountedThreadSafe<CookieStore> {
  public:
   // Callback definitions.
-  typedef base::Callback<void(const std::string& cookie)>
-      GetCookiesCallback;
+  typedef base::Callback<void(const CookieList& cookies)> GetCookieListCallback;
+  typedef base::Callback<void(const std::string& cookie)> GetCookiesCallback;
   typedef base::Callback<void(bool success)> SetCookiesCallback;
   typedef base::Callback<void(int num_deleted)> DeleteCallback;
 
@@ -55,6 +56,12 @@
       const CookieOptions& options,
       const GetCookiesCallback& callback) = 0;
 
+  // Returns all matching cookies without marking them as accessed,
+  // including HTTP only cookies.
+  virtual void GetAllCookiesForURLAsync(
+      const GURL& url,
+      const GetCookieListCallback& callback) = 0;
+
   // Deletes the passed in cookie for the specified URL.
   virtual void DeleteCookieAsync(const GURL& url,
                                  const std::string& cookie_name,
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc
index 68086e1..fdf2c1f 100644
--- a/net/cookies/cookie_store_test_helpers.cc
+++ b/net/cookies/cookie_store_test_helpers.cc
@@ -68,6 +68,12 @@
       base::TimeDelta::FromMilliseconds(kDelayedTime));
 }
 
+void DelayedCookieMonster::GetAllCookiesForURLAsync(
+    const GURL& url,
+    const GetCookieListCallback& callback) {
+  cookie_monster_->GetAllCookiesForURLAsync(url, callback);
+}
+
 void DelayedCookieMonster::InvokeSetCookiesCallback(
     const CookieMonster::SetCookiesCallback& callback) {
   if (!callback.is_null())
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h
index 3119e03..84b83bc 100644
--- a/net/cookies/cookie_store_test_helpers.h
+++ b/net/cookies/cookie_store_test_helpers.h
@@ -34,6 +34,10 @@
       const CookieOptions& options,
       const CookieMonster::GetCookiesCallback& callback) OVERRIDE;
 
+  virtual void GetAllCookiesForURLAsync(
+      const GURL& url,
+      const GetCookieListCallback& callback) OVERRIDE;
+
   virtual bool SetCookieWithOptions(const GURL& url,
                                     const std::string& cookie_line,
                                     const CookieOptions& options);
diff --git a/net/cronet/android/url_request_context_peer.cc b/net/cronet/android/url_request_context_peer.cc
index 2c754db..e367632 100644
--- a/net/cronet/android/url_request_context_peer.cc
+++ b/net/cronet/android/url_request_context_peer.cc
@@ -44,7 +44,8 @@
       net::URLRequest* request,
       const net::CompletionCallback& callback,
       const net::HttpResponseHeaders* original_response_headers,
-      scoped_refptr<net::HttpResponseHeaders>* _response_headers) OVERRIDE {
+      scoped_refptr<net::HttpResponseHeaders>* _response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE {
     return net::OK;
   }
 
diff --git a/net/data/url_request_unittest/redirect302-to-echo-cacheable b/net/data/url_request_unittest/redirect302-to-echo-cacheable
new file mode 100644
index 0000000..7898192
--- /dev/null
+++ b/net/data/url_request_unittest/redirect302-to-echo-cacheable
@@ -0,0 +1 @@
+a
diff --git a/net/data/url_request_unittest/redirect302-to-echo-cacheable.mock-http-headers b/net/data/url_request_unittest/redirect302-to-echo-cacheable.mock-http-headers
new file mode 100644
index 0000000..fce2271
--- /dev/null
+++ b/net/data/url_request_unittest/redirect302-to-echo-cacheable.mock-http-headers
@@ -0,0 +1,4 @@
+HTTP/1.1 302 Yo
+Location: /echo
+Content-Length: 1
+Cache-control: max-age=60000
diff --git a/net/data/websocket/close-with-split-packet_wsh.py b/net/data/websocket/close-with-split-packet_wsh.py
index d5185c4..3bd5b58 100644
--- a/net/data/websocket/close-with-split-packet_wsh.py
+++ b/net/data/websocket/close-with-split-packet_wsh.py
@@ -13,17 +13,12 @@
 
 
 def web_socket_transfer_data(request):
-  line = request.ws_stream.receive_message()
-  if line is None:
-    return
-  if isinstance(line, unicode):
-    request.ws_stream.send_message(line, binary=False)
-  else:
-    request.ws_stream.send_message(line, binary=True)
+  # Just waiting...
+  request.ws_stream.receive_message()
 
 
 def web_socket_passive_closing_handshake(request):
-  code = struct.pack('!H', 1000)
+  code = struct.pack('!H', 3004)
   packet = stream.create_close_frame(code + 'split test'.encode('utf-8'))
   request.connection.write(packet[:1])
   request.connection.write(packet[1:])
diff --git a/net/data/websocket/split_packet_check.html b/net/data/websocket/split_packet_check.html
index 8e273ec..a7f4c36 100644
--- a/net/data/websocket/split_packet_check.html
+++ b/net/data/websocket/split_packet_check.html
@@ -26,7 +26,7 @@
 ws.onclose = function(event)
 {
   // Check wasClean, then set proper title.
-  if (event.wasClean)
+  if (event.wasClean && event.code === 3004 && event.reason === 'split test')
     document.title = 'PASS';
   else
     document.title = 'FAIL';
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index 68da572..e118dc6 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -668,6 +668,9 @@
 }
 #endif
 
+// Disabled on android since this test requires cache creator to create
+// blockfile caches.
+#if !defined(OS_ANDROID)
 TEST_F(DiskCacheTest, TruncatedIndex) {
   ASSERT_TRUE(CleanupCacheDir());
   base::FilePath index = cache_path_.AppendASCII("index");
@@ -693,6 +696,7 @@
 
   ASSERT_FALSE(backend);
 }
+#endif
 
 void DiskCacheBackendTest::BackendSetSize() {
   const int cache_size = 0x10000;  // 64 kB
@@ -1837,6 +1841,9 @@
 
 // Tests that the disk cache successfully joins the control group, dropping the
 // existing cache in favour of a new empty cache.
+// Disabled on android since this test requires cache creator to create
+// blockfile caches.
+#if !defined(OS_ANDROID)
 TEST_F(DiskCacheTest, SimpleCacheControlJoin) {
   base::Thread cache_thread("CacheThread");
   ASSERT_TRUE(cache_thread.StartWithOptions(
@@ -1867,6 +1874,7 @@
   ASSERT_EQ(net::OK, cb.GetResult(rv));
   EXPECT_EQ(0, base_cache->GetEntryCount());
 }
+#endif
 
 // Tests that the disk cache can restart in the control group preserving
 // existing entries.
@@ -1945,6 +1953,9 @@
 }
 
 // Tests that the cache is properly restarted on recovery error.
+// Disabled on android since this test requires cache creator to create
+// blockfile caches.
+#if !defined(OS_ANDROID)
 TEST_F(DiskCacheBackendTest, DeleteOld) {
   ASSERT_TRUE(CopyTestCache("wrong_version"));
   SetNewEviction();
@@ -1971,6 +1982,7 @@
   cache_.reset();
   EXPECT_TRUE(CheckCacheIntegrity(cache_path_, new_eviction_, mask_));
 }
+#endif
 
 // We want to be able to deal with messed up entries on disk.
 void DiskCacheBackendTest::BackendInvalidEntry2() {
diff --git a/net/disk_cache/blockfile/backend_impl_v3.h b/net/disk_cache/blockfile/backend_impl_v3.h
index adb926c..37f90aa 100644
--- a/net/disk_cache/blockfile/backend_impl_v3.h
+++ b/net/disk_cache/blockfile/backend_impl_v3.h
@@ -194,6 +194,7 @@
  private:
   friend class EvictionV3;
   typedef base::hash_map<CacheAddr, EntryImplV3*> EntriesMap;
+  class Worker;
 
   void AdjustMaxCacheSize();
   bool InitStats(void* stats_data);
diff --git a/net/disk_cache/blockfile/backend_worker_v3.cc b/net/disk_cache/blockfile/backend_worker_v3.cc
index d02eee5..ab432c4 100644
--- a/net/disk_cache/blockfile/backend_worker_v3.cc
+++ b/net/disk_cache/blockfile/backend_worker_v3.cc
@@ -8,28 +8,15 @@
 #include "base/bind_helpers.h"
 #include "base/file_util.h"
 #include "base/files/file_path.h"
-#include "base/hash.h"
 #include "base/message_loop/message_loop.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/stats_counters.h"
-#include "base/rand_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
-#include "base/threading/thread_restrictions.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "net/base/net_errors.h"
-#include "net/disk_cache/blockfile/entry_impl.h"
 #include "net/disk_cache/blockfile/errors.h"
 #include "net/disk_cache/blockfile/experiments.h"
 #include "net/disk_cache/blockfile/file.h"
-#include "net/disk_cache/blockfile/histogram_macros.h"
-#include "net/disk_cache/cache_util.h"
-
-// Provide a BackendImpl object to macros from histogram_macros.h.
-#define CACHE_UMA_BACKEND_IMPL_OBJ this
 
 using base::Time;
 using base::TimeDelta;
@@ -37,6 +24,8 @@
 
 namespace {
 
+#if defined(V3_NOT_JUST_YET_READY)
+
 const char* kIndexName = "index";
 
 // Seems like ~240 MB correspond to less than 50k entries for 99% of the people.
@@ -96,6 +85,7 @@
   header->experiment = disk_cache::NO_EXPERIMENT;
   return true;
 }
+#endif  // defined(V3_NOT_JUST_YET_READY).
 
 }  // namespace
 
@@ -103,31 +93,15 @@
 
 namespace disk_cache {
 
-BackendImpl::BackendImpl(const base::FilePath& path,
-                         base::MessageLoopProxy* cache_thread,
-                         net::NetLog* net_log)
-    : background_queue_(this, cache_thread),
-      path_(path),
-      block_files_(path),
-      mask_(0),
-      max_size_(0),
-      up_ticks_(0),
-      cache_type_(net::DISK_CACHE),
-      uma_report_(0),
-      user_flags_(0),
-      init_(false),
-      restarted_(false),
-      unit_test_(false),
-      read_only_(false),
-      disabled_(false),
-      new_eviction_(false),
-      first_timer_(true),
-      user_load_(false),
-      net_log_(net_log),
-      done_(true, false),
-      ptr_factory_(this) {
+BackendImplV3::Worker::Worker(const base::FilePath& path,
+                              base::MessageLoopProxy* main_thread)
+      : path_(path),
+        block_files_(path),
+        init_(false) {
 }
 
+#if defined(V3_NOT_JUST_YET_READY)
+
 int BackendImpl::SyncInit() {
 #if defined(NET_BUILD_STRESS_CACHE)
   // Start evictions right away.
@@ -482,4 +456,13 @@
   return true;
 }
 
+#endif  // defined(V3_NOT_JUST_YET_READY).
+
+int BackendImplV3::Worker::Init(const CompletionCallback& callback) {
+  return net::ERR_FAILED;
+}
+
+BackendImplV3::Worker::~Worker() {
+}
+
 }  // namespace disk_cache
diff --git a/net/disk_cache/blockfile/backend_worker_v3.h b/net/disk_cache/blockfile/backend_worker_v3.h
index a184d8f..d0829b9 100644
--- a/net/disk_cache/blockfile/backend_worker_v3.h
+++ b/net/disk_cache/blockfile/backend_worker_v3.h
@@ -9,30 +9,23 @@
 
 #include "base/containers/hash_tables.h"
 #include "base/files/file_path.h"
-#include "base/timer/timer.h"
+#include "net/disk_cache/blockfile/addr.h"
+#include "net/disk_cache/blockfile/backend_impl_v3.h"
 #include "net/disk_cache/blockfile/block_files.h"
-#include "net/disk_cache/blockfile/eviction.h"
-#include "net/disk_cache/blockfile/in_flight_backend_io.h"
-#include "net/disk_cache/blockfile/rankings.h"
-#include "net/disk_cache/blockfile/stats.h"
-#include "net/disk_cache/blockfile/stress_support.h"
-#include "net/disk_cache/blockfile/trace.h"
-#include "net/disk_cache/disk_cache.h"
 
 namespace disk_cache {
 
-// This class implements the Backend interface. An object of this
-// class handles the operations of the cache for a particular profile.
-class NET_EXPORT_PRIVATE BackendImpl : public Backend {
-  friend class Eviction;
+class BackendImplV3::Worker : public base::RefCountedThreadSafe<Worker> {
  public:
-  BackendImpl(const base::FilePath& path, base::MessageLoopProxy* cache_thread,
-              net::NetLog* net_log);
+  Worker(const base::FilePath& path, base::MessageLoopProxy* main_thread);
 
   // Performs general initialization for this current instance of the cache.
   int Init(const CompletionCallback& callback);
 
  private:
+  friend class base::RefCountedThreadSafe<Worker>;
+
+  ~Worker();
   void CleanupCache();
 
   // Returns the full name for an external storage file.
@@ -42,9 +35,6 @@
   bool CreateBackingStore(disk_cache::File* file);
   bool InitBackingStore(bool* file_created);
 
-  // Reports an uncommon, recoverable error.
-  void ReportError(int error);
-
   // Performs basic checks on the index file. Returns false on failure.
   bool CheckIndex();
 
@@ -52,7 +42,7 @@
   BlockFiles block_files_;  // Set of files used to store all data.
   bool init_;  // controls the initialization of the system.
 
-  DISALLOW_COPY_AND_ASSIGN(BackendImpl);
+  DISALLOW_COPY_AND_ASSIGN(Worker);
 };
 
 }  // namespace disk_cache
diff --git a/net/disk_cache/cache_creator.cc b/net/disk_cache/cache_creator.cc
index 102e102..866df10 100644
--- a/net/disk_cache/cache_creator.cc
+++ b/net/disk_cache/cache_creator.cc
@@ -79,11 +79,14 @@
 }
 
 int CacheCreator::Run() {
-  // TODO(gavinp,pasko): Turn Simple Cache on for more cache types as
-  // appropriate.
-  if (backend_type_ == net::CACHE_BACKEND_SIMPLE &&
-      (type_ == net::DISK_CACHE || type_ == net::APP_CACHE ||
-       type_ == net::MEDIA_CACHE)) {
+#if defined(OS_ANDROID)
+  static const bool kSimpleBackendIsDefault = true;
+#else
+  static const bool kSimpleBackendIsDefault = false;
+#endif
+  if (backend_type_ == net::CACHE_BACKEND_SIMPLE ||
+      (backend_type_ == net::CACHE_BACKEND_DEFAULT &&
+       kSimpleBackendIsDefault)) {
     disk_cache::SimpleBackendImpl* simple_cache =
         new disk_cache::SimpleBackendImpl(path_, max_bytes_, type_,
                                           thread_.get(), net_log_);
@@ -91,6 +94,11 @@
     return simple_cache->Init(
         base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this)));
   }
+
+  // Avoid references to blockfile functions on Android to reduce binary size.
+#if defined(OS_ANDROID)
+  return net::ERR_FAILED;
+#else
   disk_cache::BackendImpl* new_cache =
       new disk_cache::BackendImpl(path_, thread_.get(), net_log_);
   created_cache_.reset(new_cache);
@@ -101,6 +109,7 @@
       base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this)));
   DCHECK_EQ(net::ERR_IO_PENDING, rv);
   return rv;
+#endif
 }
 
 void CacheCreator::DoCallback(int result) {
diff --git a/net/disk_cache/simple/simple_histogram_macros.h b/net/disk_cache/simple/simple_histogram_macros.h
index f800a6f..39fdff7 100644
--- a/net/disk_cache/simple/simple_histogram_macros.h
+++ b/net/disk_cache/simple/simple_histogram_macros.h
@@ -16,6 +16,9 @@
 
 #define SIMPLE_CACHE_THUNK(uma_type, args) UMA_HISTOGRAM_##uma_type args
 
+// TODO(pasko): add histograms for shader cache as soon as it becomes possible
+// for a user to get shader cache with the |SimpleBackendImpl| without altering
+// any flags.
 #define SIMPLE_CACHE_UMA(uma_type, uma_name, cache_type, ...)          \
   do {                                                                 \
     switch (cache_type) {                                              \
@@ -31,6 +34,8 @@
         SIMPLE_CACHE_THUNK(                                            \
             uma_type, ("SimpleCache.Media." uma_name, ##__VA_ARGS__)); \
         break;                                                         \
+      case net::SHADER_CACHE:                                          \
+        break;                                                         \
       default:                                                         \
         NOTREACHED();                                                  \
         break;                                                         \
diff --git a/net/dns/mapped_ip_resolver.cc b/net/dns/mapped_ip_resolver.cc
deleted file mode 100644
index 58d01a3..0000000
--- a/net/dns/mapped_ip_resolver.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/dns/mapped_ip_resolver.h"
-
-#include "base/strings/string_util.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-
-namespace net {
-
-MappedIPResolver::MappedIPResolver(scoped_ptr<HostResolver> impl)
-    : impl_(impl.Pass()),
-      weak_factory_(this) {
-}
-
-MappedIPResolver::~MappedIPResolver() {}
-
-int MappedIPResolver::Resolve(const RequestInfo& info,
-                              RequestPriority priority,
-                              AddressList* addresses,
-                              const CompletionCallback& callback,
-                              RequestHandle* out_req,
-                              const BoundNetLog& net_log) {
-  CompletionCallback new_callback = base::Bind(&MappedIPResolver::ApplyRules,
-                                               weak_factory_.GetWeakPtr(),
-                                               callback, addresses);
-  int rv = impl_->Resolve(info, priority, addresses, new_callback, out_req,
-                          net_log);
-  if (rv == OK)
-    rules_.RewriteAddresses(addresses);
-  return rv;
-}
-
-int MappedIPResolver::ResolveFromCache(const RequestInfo& info,
-                                       AddressList* addresses,
-                                       const BoundNetLog& net_log) {
-  int rv = impl_->ResolveFromCache(info, addresses, net_log);
-  if (rv == OK)
-    rules_.RewriteAddresses(addresses);
-  return rv;
-}
-
-void MappedIPResolver::CancelRequest(RequestHandle req) {
-  impl_->CancelRequest(req);
-}
-
-void MappedIPResolver::SetDnsClientEnabled(bool enabled) {
-  impl_->SetDnsClientEnabled(enabled);
-}
-
-HostCache* MappedIPResolver::GetHostCache() {
-  return impl_->GetHostCache();
-}
-
-base::Value* MappedIPResolver::GetDnsConfigAsValue() const {
-  return impl_->GetDnsConfigAsValue();
-}
-
-void MappedIPResolver::ApplyRules(const CompletionCallback& original_callback,
-                                  AddressList* addresses,
-                                  int rv) const {
-  if (rv == OK)
-    rules_.RewriteAddresses(addresses);
-  original_callback.Run(rv);
-}
-
-}  // namespace net
diff --git a/net/dns/mapped_ip_resolver.h b/net/dns/mapped_ip_resolver.h
deleted file mode 100644
index a3c7aa8..0000000
--- a/net/dns/mapped_ip_resolver.h
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_DNS_MAPPED_IP_RESOLVER_H_
-#define NET_DNS_MAPPED_IP_RESOLVER_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "net/base/ip_mapping_rules.h"
-#include "net/base/net_export.h"
-#include "net/dns/host_resolver.h"
-
-namespace net {
-
-// This class wraps an existing HostResolver instance, but modifies the
-// resolution response by inserting or replacing IP addresses before returning
-// it.  Currently, the only directive suported is a "PREFACE" directive which
-// (when a match exists) inserts a single IP address at the start of a list.
-class NET_EXPORT MappedIPResolver : public HostResolver {
- public:
-  // Creates a MappedIPResolver that forwards all of its requests through
-  // |impl|.
-  explicit MappedIPResolver(scoped_ptr<HostResolver> impl);
-  virtual ~MappedIPResolver();
-
-  // Adds a rule to our IP mapper rules_.
-  // The most recently added rule "has priority" and will be used first (in
-  // preference to) any previous rules.  Once one rule is found that matches,
-  // no other rules will be considered.
-  // See ip_mapping_rules.h for syntax and semantics.
-  // Returns true if the rule was successfully parsed and added.
-  bool AddRuleFromString(const std::string& rule_string) {
-    return rules_.AddRuleFromString(rule_string);
-  }
-
-  // Takes a semicolon separated list of rules, and assigns them to this
-  // resolver, discarding any previously added or set rules.
-  void SetRulesFromString(const std::string& rules_string) {
-    rules_.SetRulesFromString(rules_string);
-  }
-
-  // HostResolver methods:
-  virtual int Resolve(const RequestInfo& info,
-                      RequestPriority priority,
-                      AddressList* addresses,
-                      const CompletionCallback& callback,
-                      RequestHandle* out_req,
-                      const BoundNetLog& net_log) OVERRIDE;
-  virtual int ResolveFromCache(const RequestInfo& info,
-                               AddressList* addresses,
-                               const BoundNetLog& net_log) OVERRIDE;
-  virtual void CancelRequest(RequestHandle req) OVERRIDE;
-  virtual void SetDnsClientEnabled(bool enabled) OVERRIDE;
-  virtual HostCache* GetHostCache() OVERRIDE;
-  virtual base::Value* GetDnsConfigAsValue() const OVERRIDE;
-
- private:
-  // Modify the list of resolution |addresses| according to |rules_|, and then
-  // calls the |original_callback| with network error code |rv|.
-  void ApplyRules(const CompletionCallback& original_callback,
-                  AddressList* addresses,
-                  int rv) const;
-
-  scoped_ptr<HostResolver> impl_;
-  IPMappingRules rules_;
-
-  base::WeakPtrFactory<MappedIPResolver> weak_factory_;
-  DISALLOW_COPY_AND_ASSIGN(MappedIPResolver);
-};
-
-}  // namespace net
-
-#endif  // NET_DNS_MAPPED_IP_RESOLVER_H_
diff --git a/net/filter/filter.cc b/net/filter/filter.cc
index 244abae..90d91e1 100644
--- a/net/filter/filter.cc
+++ b/net/filter/filter.cc
@@ -8,6 +8,7 @@
 #include "base/strings/string_util.h"
 #include "net/base/io_buffer.h"
 #include "net/base/mime_util.h"
+#include "net/base/net_util.h"
 #include "net/filter/gzip_filter.h"
 #include "net/filter/sdch_filter.h"
 
@@ -170,11 +171,14 @@
       encoding_types->clear();
 
     GURL url;
+    std::string disposition;
     success = filter_context.GetURL(&url);
     DCHECK(success);
-    base::FilePath filename =
-        base::FilePath().AppendASCII(url.ExtractFileName());
-    base::FilePath::StringType extension = filename.Extension();
+    filter_context.GetContentDisposition(&disposition);
+    // Don't supply a MIME type here, since that may cause disk IO.
+    base::FilePath filepath = GenerateFileName(url, disposition, "UTF-8", "",
+                                               "", "");
+    base::FilePath::StringType extension = filepath.Extension();
 
     if (filter_context.IsDownload()) {
       // We don't want to decompress gzipped files when the user explicitly
diff --git a/net/filter/filter.h b/net/filter/filter.h
index 1b4d2f5..8189099 100644
--- a/net/filter/filter.h
+++ b/net/filter/filter.h
@@ -74,6 +74,10 @@
   // Return false if gurl is not present.
   virtual bool GetURL(GURL* gurl) const = 0;
 
+  // What Content-Disposition header came with this data?
+  // Return false if no header was present.
+  virtual bool GetContentDisposition(std::string* disposition) const = 0;
+
   // When was this data requested from a server?
   virtual base::Time GetRequestTime() const = 0;
 
diff --git a/net/filter/filter_unittest.cc b/net/filter/filter_unittest.cc
index 3b91252..08a2861 100644
--- a/net/filter/filter_unittest.cc
+++ b/net/filter/filter_unittest.cc
@@ -82,6 +82,23 @@
   EXPECT_EQ(Filter::FILTER_TYPE_GZIP, encoding_types.front());
 }
 
+TEST(FilterTest, GzipContentDispositionFilename) {
+  MockFilterContext filter_context;
+  filter_context.SetSdchResponse(false);
+
+  const std::string kGzipMime("application/x-tar");
+  const std::string kContentDisposition("attachment; filename=\"foo.tgz\"");
+  const std::string kURL("http://foo.com/getfoo.php");
+  std::vector<Filter::FilterType> encoding_types;
+
+  encoding_types.push_back(Filter::FILTER_TYPE_GZIP);
+  filter_context.SetMimeType(kGzipMime);
+  filter_context.SetURL(GURL(kURL));
+  filter_context.SetContentDisposition(kContentDisposition);
+  Filter::FixupEncodingTypes(filter_context, &encoding_types);
+  ASSERT_EQ(0U, encoding_types.size());
+}
+
 TEST(FilterTest, SdchEncoding) {
   // Handle content encodings including SDCH.
   const std::string kTextHtmlMime("text/html");
diff --git a/net/filter/mock_filter_context.cc b/net/filter/mock_filter_context.cc
index ec6db01..06905c0 100644
--- a/net/filter/mock_filter_context.cc
+++ b/net/filter/mock_filter_context.cc
@@ -27,6 +27,13 @@
   return true;
 }
 
+bool MockFilterContext::GetContentDisposition(std::string* disposition) const {
+  if (content_disposition_.empty())
+    return false;
+  *disposition = content_disposition_;
+  return true;
+}
+
 // What was this data requested from a server?
 base::Time MockFilterContext::GetRequestTime() const {
   return request_time_;
diff --git a/net/filter/mock_filter_context.h b/net/filter/mock_filter_context.h
index 00fc8ed..21e56ac 100644
--- a/net/filter/mock_filter_context.h
+++ b/net/filter/mock_filter_context.h
@@ -19,6 +19,9 @@
 
   void SetMimeType(const std::string& mime_type) { mime_type_ = mime_type; }
   void SetURL(const GURL& gurl) { gurl_ = gurl; }
+  void SetContentDisposition(const std::string& disposition) {
+    content_disposition_ = disposition;
+  }
   void SetRequestTime(const base::Time time) { request_time_ = time; }
   void SetCached(bool is_cached) { is_cached_content_ = is_cached; }
   void SetDownload(bool is_download) { is_download_ = is_download; }
@@ -33,6 +36,10 @@
   // Return false if gurl is not present.
   virtual bool GetURL(GURL* gurl) const OVERRIDE;
 
+  // What Content-Disposition did the server supply for this data?
+  // Return false if Content-Disposition was not present.
+  virtual bool GetContentDisposition(std::string* disposition) const OVERRIDE;
+
   // What was this data requested from a server?
   virtual base::Time GetRequestTime() const OVERRIDE;
 
@@ -55,6 +62,7 @@
  private:
   int buffer_size_;
   std::string mime_type_;
+  std::string content_disposition_;
   GURL gurl_;
   base::Time request_time_;
   bool is_cached_content_;
diff --git a/net/http/disk_cache_based_quic_server_info_unittest.cc b/net/http/disk_cache_based_quic_server_info_unittest.cc
index 3321240..ed0e1b7 100644
--- a/net/http/disk_cache_based_quic_server_info_unittest.cc
+++ b/net/http/disk_cache_based_quic_server_info_unittest.cc
@@ -14,6 +14,7 @@
 #include "net/quic/quic_session_key.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace net {
 namespace {
 
 // This is an empty transaction, needed to register the URL and the test mode.
@@ -22,7 +23,7 @@
   "",
   base::Time(),
   "",
-  net::LOAD_NORMAL,
+  LOAD_NORMAL,
   "",
   "",
   base::Time(),
@@ -37,7 +38,7 @@
   "",
   base::Time(),
   "",
-  net::LOAD_NORMAL,
+  LOAD_NORMAL,
   "",
   "",
   base::Time(),
@@ -47,6 +48,8 @@
   0
 };
 
+}  // namespace
+
 // Tests that we can delete a DiskCacheBasedQuicServerInfo object in a
 // completion callback for DiskCacheBasedQuicServerInfo::WaitForDataReady.
 TEST(DiskCacheBasedQuicServerInfo, DeleteInCallback) {
@@ -54,32 +57,33 @@
   // of quic_server_info->WaitForDataReady(), so that the callback will run.
   MockBlockingBackendFactory* factory = new MockBlockingBackendFactory();
   MockHttpCache cache(factory);
-  net::QuicSessionKey server_key("www.verisign.com", 443, true);
-  scoped_ptr<net::QuicServerInfo> quic_server_info(
-      new net::DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
+  QuicSessionKey server_key("www.verisign.com", 443, true,
+                            kPrivacyModeDisabled);
+  scoped_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
   quic_server_info->Start();
-  net::TestCompletionCallback callback;
+  TestCompletionCallback callback;
   int rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::ERR_IO_PENDING, rv);
+  EXPECT_EQ(ERR_IO_PENDING, rv);
   // Now complete the backend creation and let the callback run.
   factory->FinishCreation();
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
 }
 
 // Tests the basic logic of storing, retrieving and updating data.
 TEST(DiskCacheBasedQuicServerInfo, Update) {
   MockHttpCache cache;
   AddMockTransaction(&kHostInfoTransaction1);
-  net::TestCompletionCallback callback;
+  TestCompletionCallback callback;
 
-  net::QuicSessionKey server_key("www.google.com", 443, true);
-  scoped_ptr<net::QuicServerInfo> quic_server_info(
-      new net::DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
+  QuicSessionKey server_key("www.google.com", 443, true, kPrivacyModeDisabled);
+  scoped_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
   quic_server_info->Start();
   int rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
 
-  net::QuicServerInfo::State* state = quic_server_info->mutable_state();
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
   EXPECT_TRUE(state->certs.empty());
   const string server_config_a = "server_config_a";
   const string source_address_token_a = "source_address_token_a";
@@ -98,10 +102,10 @@
 
   // Open the stored QuicServerInfo.
   quic_server_info.reset(
-      new net::DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
+      new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
   quic_server_info->Start();
   rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
 
   // And now update the data.
   state = quic_server_info->mutable_state();
@@ -114,13 +118,13 @@
 
   // Verify that the state was updated.
   quic_server_info.reset(
-      new net::DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
+      new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
   quic_server_info->Start();
   rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
   EXPECT_TRUE(quic_server_info->IsDataReady());
 
-  const net::QuicServerInfo::State& state1 = quic_server_info->state();
+  const QuicServerInfo::State& state1 = quic_server_info->state();
   EXPECT_EQ(server_config_a, state1.server_config);
   EXPECT_EQ(source_address_token_a, state1.source_address_token);
   EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
@@ -136,17 +140,17 @@
   MockHttpCache cache;
   AddMockTransaction(&kHostInfoTransaction1);
   AddMockTransaction(&kHostInfoTransaction2);
-  net::TestCompletionCallback callback;
+  TestCompletionCallback callback;
 
   // Persist data for port 443.
-  net::QuicSessionKey server_key1("www.google.com", 443, true);
-  scoped_ptr<net::QuicServerInfo> quic_server_info1(
-      new net::DiskCacheBasedQuicServerInfo(server_key1, cache.http_cache()));
+  QuicSessionKey server_key1("www.google.com", 443, true, kPrivacyModeDisabled);
+  scoped_ptr<QuicServerInfo> quic_server_info1(
+      new DiskCacheBasedQuicServerInfo(server_key1, cache.http_cache()));
   quic_server_info1->Start();
   int rv = quic_server_info1->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
 
-  net::QuicServerInfo::State* state1 = quic_server_info1->mutable_state();
+  QuicServerInfo::State* state1 = quic_server_info1->mutable_state();
   EXPECT_TRUE(state1->certs.empty());
   const string server_config_a = "server_config_a";
   const string source_address_token_a = "source_address_token_a";
@@ -163,14 +167,14 @@
   base::MessageLoop::current()->RunUntilIdle();
 
   // Persist data for port 80.
-  net::QuicSessionKey server_key2("www.google.com", 80, false);
-  scoped_ptr<net::QuicServerInfo> quic_server_info2(
-      new net::DiskCacheBasedQuicServerInfo(server_key2, cache.http_cache()));
+  QuicSessionKey server_key2("www.google.com", 80, false, kPrivacyModeDisabled);
+  scoped_ptr<QuicServerInfo> quic_server_info2(
+      new DiskCacheBasedQuicServerInfo(server_key2, cache.http_cache()));
   quic_server_info2->Start();
   rv = quic_server_info2->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
 
-  net::QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
+  QuicServerInfo::State* state2 = quic_server_info2->mutable_state();
   EXPECT_TRUE(state2->certs.empty());
   const string server_config_b = "server_config_b";
   const string source_address_token_b = "source_address_token_b";
@@ -187,14 +191,14 @@
   base::MessageLoop::current()->RunUntilIdle();
 
   // Verify the stored QuicServerInfo for port 443.
-  scoped_ptr<net::QuicServerInfo> quic_server_info(
-      new net::DiskCacheBasedQuicServerInfo(server_key1, cache.http_cache()));
+  scoped_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_key1, cache.http_cache()));
   quic_server_info->Start();
   rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
   EXPECT_TRUE(quic_server_info->IsDataReady());
 
-  const net::QuicServerInfo::State& state_a = quic_server_info->state();
+  const QuicServerInfo::State& state_a = quic_server_info->state();
   EXPECT_EQ(server_config_a, state_a.server_config);
   EXPECT_EQ(source_address_token_a, state_a.source_address_token);
   EXPECT_EQ(server_config_sig_a, state_a.server_config_sig);
@@ -203,13 +207,13 @@
 
   // Verify the stored QuicServerInfo for port 80.
   quic_server_info.reset(
-      new net::DiskCacheBasedQuicServerInfo(server_key2, cache.http_cache()));
+      new DiskCacheBasedQuicServerInfo(server_key2, cache.http_cache()));
   quic_server_info->Start();
   rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
   EXPECT_TRUE(quic_server_info->IsDataReady());
 
-  const net::QuicServerInfo::State& state_b = quic_server_info->state();
+  const QuicServerInfo::State& state_b = quic_server_info->state();
   EXPECT_EQ(server_config_b, state_b.server_config);
   EXPECT_EQ(source_address_token_b, state_b.source_address_token);
   EXPECT_EQ(server_config_sig_b, state_b.server_config_sig);
@@ -224,18 +228,18 @@
 TEST(DiskCacheBasedQuicServerInfo, IsReadyToPersist) {
   MockHttpCache cache;
   AddMockTransaction(&kHostInfoTransaction1);
-  net::TestCompletionCallback callback;
+  TestCompletionCallback callback;
 
-  net::QuicSessionKey server_key("www.google.com", 443, true);
-  scoped_ptr<net::QuicServerInfo> quic_server_info(
-      new net::DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
+  QuicSessionKey server_key("www.google.com", 443, true, kPrivacyModeDisabled);
+  scoped_ptr<QuicServerInfo> quic_server_info(
+      new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
   EXPECT_FALSE(quic_server_info->IsDataReady());
   quic_server_info->Start();
   int rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
   EXPECT_TRUE(quic_server_info->IsDataReady());
 
-  net::QuicServerInfo::State* state = quic_server_info->mutable_state();
+  QuicServerInfo::State* state = quic_server_info->mutable_state();
   EXPECT_TRUE(state->certs.empty());
   const string server_config_a = "server_config_a";
   const string source_address_token_a = "source_address_token_a";
@@ -260,13 +264,13 @@
 
   // Verify that the state was updated.
   quic_server_info.reset(
-      new net::DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
+      new DiskCacheBasedQuicServerInfo(server_key, cache.http_cache()));
   quic_server_info->Start();
   rv = quic_server_info->WaitForDataReady(callback.callback());
-  EXPECT_EQ(net::OK, callback.GetResult(rv));
+  EXPECT_EQ(OK, callback.GetResult(rv));
   EXPECT_TRUE(quic_server_info->IsDataReady());
 
-  const net::QuicServerInfo::State& state1 = quic_server_info->state();
+  const QuicServerInfo::State& state1 = quic_server_info->state();
   EXPECT_EQ(server_config_a, state1.server_config);
   EXPECT_EQ(source_address_token_a, state1.source_address_token);
   EXPECT_EQ(server_config_sig_a, state1.server_config_sig);
@@ -276,4 +280,4 @@
   RemoveMockTransaction(&kHostInfoTransaction1);
 }
 
-}  // namespace
+}  // namespace net
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 6aae971..e2d46be 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -446,6 +446,9 @@
   // entry how it is (it will be marked as truncated at destruction), and let
   // the next piece of code that executes know that we are now reading directly
   // from the net.
+  // TODO(mmenke):  This doesn't release the lock on the cache entry, so a
+  //                future request for the resource will be blocked on this one.
+  //                Fix this.
   if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() &&
       !is_sparse_ && !range_requested_) {
     mode_ = NONE;
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 73d969c..0e07653 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -113,6 +113,7 @@
                                params.client_socket_factory :
                                net::ClientSocketFactory::GetDefaultFactory(),
                            params.http_server_properties,
+                           params.cert_verifier,
                            params.quic_crypto_client_stream_factory,
                            params.quic_random ? params.quic_random :
                                QuicRandom::GetInstance(),
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index 7dda13e..ca06785 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -289,7 +289,8 @@
   // failure should cause the network transaction to resend the request, and the
   // other argument should be NULL.
   void PreconnectErrorResendRequestTest(const MockWrite* write_failure,
-                                        const MockRead* read_failure);
+                                        const MockRead* read_failure,
+                                        bool use_spdy);
 
   SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
                                                size_t data_count) {
@@ -1308,46 +1309,81 @@
 
 void HttpNetworkTransactionTest::PreconnectErrorResendRequestTest(
     const MockWrite* write_failure,
-    const MockRead* read_failure) {
+    const MockRead* read_failure,
+    bool use_spdy) {
   HttpRequestInfo request;
   request.method = "GET";
-  request.url = GURL("http://www.foo.com/");
+  request.url = GURL("https://www.foo.com/");
   request.load_flags = 0;
 
   CapturingNetLog net_log;
   session_deps_.net_log = &net_log;
   scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps_));
 
-  // Written data for successfully sending a request.
-  MockWrite data1_writes[] = {
-    MockWrite("GET / HTTP/1.1\r\n"
-              "Host: www.foo.com\r\n"
-              "Connection: keep-alive\r\n\r\n"),
-  };
+  SSLSocketDataProvider ssl1(ASYNC, OK);
+  SSLSocketDataProvider ssl2(ASYNC, OK);
+  if (use_spdy) {
+    ssl1.SetNextProto(GetParam());
+    ssl2.SetNextProto(GetParam());
+  }
+  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1);
+  session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2);
 
-  // Read results for the first request.
-  MockRead data1_reads[] = {
-    MockRead(ASYNC, OK),
-  };
+  // SPDY versions of the request and response.
+  scoped_ptr<SpdyFrame> spdy_request(spdy_util_.ConstructSpdyGet(
+      request.url.spec().c_str(), false, 1, DEFAULT_PRIORITY));
+  scoped_ptr<SpdyFrame> spdy_response(
+      spdy_util_.ConstructSpdyGetSynReply(NULL, 0, 1));
+  scoped_ptr<SpdyFrame> spdy_data(
+      spdy_util_.ConstructSpdyBodyFrame(1, "hello", 5, true));
 
+  // HTTP/1.1 versions of the request and response.
+  const char kHttpRequest[] = "GET / HTTP/1.1\r\n"
+      "Host: www.foo.com\r\n"
+      "Connection: keep-alive\r\n\r\n";
+  const char kHttpResponse[] = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n";
+  const char kHttpData[] = "hello";
+
+  std::vector<MockRead> data1_reads;
+  std::vector<MockWrite> data1_writes;
   if (write_failure) {
     ASSERT_FALSE(read_failure);
-    data1_writes[0] = *write_failure;
+    data1_writes.push_back(*write_failure);
+    data1_reads.push_back(MockRead(ASYNC, OK));
   } else {
     ASSERT_TRUE(read_failure);
-    data1_reads[0] = *read_failure;
+    if (use_spdy) {
+      data1_writes.push_back(CreateMockWrite(*spdy_request));
+    } else {
+      data1_writes.push_back(MockWrite(kHttpRequest));
+    }
+    data1_reads.push_back(*read_failure);
   }
 
-  StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
-                                 data1_writes, arraysize(data1_writes));
+  StaticSocketDataProvider data1(&data1_reads[0], data1_reads.size(),
+                                 &data1_writes[0], data1_writes.size());
   session_deps_.socket_factory->AddSocketDataProvider(&data1);
 
-  MockRead data2_reads[] = {
-    MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
-    MockRead("hello"),
-    MockRead(ASYNC, OK),
-  };
-  StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
+  std::vector<MockRead> data2_reads;
+  std::vector<MockWrite> data2_writes;
+
+  if (use_spdy) {
+    data2_writes.push_back(CreateMockWrite(*spdy_request, 0, ASYNC));
+
+    data2_reads.push_back(CreateMockRead(*spdy_response, 1, ASYNC));
+    data2_reads.push_back(CreateMockRead(*spdy_data, 2, ASYNC));
+    data2_reads.push_back(MockRead(ASYNC, OK, 3));
+  } else {
+    data2_writes.push_back(
+        MockWrite(ASYNC, kHttpRequest, strlen(kHttpRequest), 0));
+
+    data2_reads.push_back(
+        MockRead(ASYNC, kHttpResponse, strlen(kHttpResponse), 1));
+    data2_reads.push_back(MockRead(ASYNC, kHttpData, strlen(kHttpData), 2));
+    data2_reads.push_back(MockRead(ASYNC, OK, 3));
+  }
+  OrderedSocketData data2(&data2_reads[0], data2_reads.size(),
+                          &data2_writes[0], data2_writes.size());
   session_deps_.socket_factory->AddSocketDataProvider(&data2);
 
   // Preconnect a socket.
@@ -1360,7 +1396,7 @@
   // Wait for the preconnect to complete.
   // TODO(davidben): Some way to wait for an idle socket count might be handy.
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, GetIdleSocketCountInTransportSocketPool(session.get()));
+  EXPECT_EQ(1, GetIdleSocketCountInSSLSocketPool(session.get()));
 
   // Make the request.
   TestCompletionCallback callback;
@@ -1376,7 +1412,9 @@
 
   LoadTimingInfo load_timing_info;
   EXPECT_TRUE(trans->GetLoadTimingInfo(&load_timing_info));
-  TestLoadTimingNotReused(load_timing_info, CONNECT_TIMING_HAS_DNS_TIMES);
+  TestLoadTimingNotReused(
+      load_timing_info,
+      CONNECT_TIMING_HAS_DNS_TIMES|CONNECT_TIMING_HAS_SSL_TIMES);
 
   const HttpResponseInfo* response = trans->GetResponseInfo();
   ASSERT_TRUE(response != NULL);
@@ -1387,7 +1425,7 @@
   std::string response_data;
   rv = ReadTransaction(trans.get(), &response_data);
   EXPECT_EQ(OK, rv);
-  EXPECT_EQ("hello", response_data);
+  EXPECT_EQ(kHttpData, response_data);
 }
 
 TEST_P(HttpNetworkTransactionTest,
@@ -1409,17 +1447,43 @@
 TEST_P(HttpNetworkTransactionTest,
        PreconnectErrorNotConnectedOnWrite) {
   MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
-  PreconnectErrorResendRequestTest(&write_failure, NULL);
+  PreconnectErrorResendRequestTest(&write_failure, NULL, false);
 }
 
 TEST_P(HttpNetworkTransactionTest, PreconnectErrorReset) {
   MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
-  PreconnectErrorResendRequestTest(NULL, &read_failure);
+  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
 }
 
 TEST_P(HttpNetworkTransactionTest, PreconnectErrorEOF) {
   MockRead read_failure(SYNCHRONOUS, OK);  // EOF
-  PreconnectErrorResendRequestTest(NULL, &read_failure);
+  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
+}
+
+TEST_P(HttpNetworkTransactionTest, PreconnectErrorAsyncEOF) {
+  MockRead read_failure(ASYNC, OK);  // EOF
+  PreconnectErrorResendRequestTest(NULL, &read_failure, false);
+}
+
+TEST_P(HttpNetworkTransactionTest,
+       SpdyPreconnectErrorNotConnectedOnWrite) {
+  MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
+  PreconnectErrorResendRequestTest(&write_failure, NULL, true);
+}
+
+TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorReset) {
+  MockRead read_failure(ASYNC, ERR_CONNECTION_RESET);
+  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
+}
+
+TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorEOF) {
+  MockRead read_failure(SYNCHRONOUS, OK);  // EOF
+  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
+}
+
+TEST_P(HttpNetworkTransactionTest, SpdyPreconnectErrorAsyncEOF) {
+  MockRead read_failure(ASYNC, OK);  // EOF
+  PreconnectErrorResendRequestTest(NULL, &read_failure, true);
 }
 
 TEST_P(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
diff --git a/net/http/http_proxy_client_socket_pool.cc b/net/http/http_proxy_client_socket_pool.cc
index 8d691b7..e2529f8 100644
--- a/net/http/http_proxy_client_socket_pool.cc
+++ b/net/http/http_proxy_client_socket_pool.cc
@@ -315,11 +315,11 @@
     }
   } else {
     // Create a session direct to the proxy itself
-    int rv = spdy_pool->CreateAvailableSessionFromSocket(
-        key, transport_socket_handle_.Pass(),
-        net_log(), OK, &spdy_session, /*using_ssl_*/ true);
-    if (rv < 0)
-      return rv;
+    spdy_session =
+        spdy_pool->CreateAvailableSessionFromSocket(
+            key, transport_socket_handle_.Pass(),
+            net_log(), OK, /*using_ssl_*/ true);
+    DCHECK(spdy_session);
   }
 
   next_state_ = STATE_SPDY_PROXY_CREATE_STREAM_COMPLETE;
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index 960bc58..09b58d4 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -334,20 +334,23 @@
 }
 
 void HttpStreamFactoryImpl::Job::OnNewSpdySessionReadyCallback() {
-  DCHECK(!stream_.get());
+  DCHECK(stream_.get());
   DCHECK(!IsPreconnecting());
   DCHECK(using_spdy());
-  if (!new_spdy_session_)
-    return;
+  // Note: an event loop iteration has passed, so |new_spdy_session_| may be
+  // NULL at this point if the SpdySession closed immediately after creation.
   base::WeakPtr<SpdySession> spdy_session = new_spdy_session_;
   new_spdy_session_.reset();
   if (IsOrphaned()) {
-    stream_factory_->OnNewSpdySessionReady(
-        spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_,
-        was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_);
+    if (spdy_session) {
+      stream_factory_->OnNewSpdySessionReady(
+          spdy_session, spdy_session_direct_, server_ssl_config_, proxy_info_,
+          was_npn_negotiated(), protocol_negotiated(), using_spdy(), net_log_);
+    }
     stream_factory_->OnOrphanedJobComplete(this);
   } else {
-    request_->OnNewSpdySessionReady(this, spdy_session, spdy_session_direct_);
+    request_->OnNewSpdySessionReady(
+        this, stream_.Pass(), spdy_session, spdy_session_direct_);
   }
   // |this| may be deleted after this call.
 }
@@ -740,8 +743,8 @@
     next_state_ = STATE_INIT_CONNECTION_COMPLETE;
     bool secure_quic = using_ssl_ || proxy_info_.is_quic();
     int rv = quic_request_.Request(
-        destination, secure_quic, request_info_.method,
-        session_->cert_verifier(), net_log_, io_callback_);
+        destination, secure_quic, request_info_.privacy_mode,
+        request_info_.method, net_log_, io_callback_);
     if (rv != OK) {
       // OK, there's no available QUIC session. Let |waiting_job_| resume
       // if it's paused.
@@ -1104,21 +1107,27 @@
     SpdySessionPool* spdy_pool = session_->spdy_session_pool();
     spdy_session = spdy_pool->FindAvailableSession(spdy_session_key, net_log_);
     if (!spdy_session) {
-      int error =
+      new_spdy_session_ =
           spdy_pool->CreateAvailableSessionFromSocket(spdy_session_key,
                                                       connection_.Pass(),
                                                       net_log_,
                                                       spdy_certificate_error_,
-                                                      &new_spdy_session_,
                                                       using_ssl_);
-      if (error != OK)
-        return error;
       const HostPortPair& host_port_pair = spdy_session_key.host_port_pair();
       base::WeakPtr<HttpServerProperties> http_server_properties =
           session_->http_server_properties();
       if (http_server_properties)
         http_server_properties->SetSupportsSpdy(host_port_pair, true);
       spdy_session_direct_ = direct;
+
+      // Create a SpdyHttpStream attached to the session;
+      // OnNewSpdySessionReadyCallback is not called until an event loop
+      // iteration later, so if the SpdySession is closed between then, allow
+      // reuse state from the underlying socket, sampled by SpdyHttpStream,
+      // bubble up to the request.
+      bool use_relative_url = direct || request_info_.url.SchemeIs("https");
+      stream_.reset(new SpdyHttpStream(new_spdy_session_, use_relative_url));
+
       return OK;
     }
   }
diff --git a/net/http/http_stream_factory_impl_request.cc b/net/http/http_stream_factory_impl_request.cc
index ff66f14..5f129ac 100644
--- a/net/http/http_stream_factory_impl_request.cc
+++ b/net/http/http_stream_factory_impl_request.cc
@@ -291,11 +291,16 @@
 
 void HttpStreamFactoryImpl::Request::OnNewSpdySessionReady(
     Job* job,
+    scoped_ptr<HttpStream> stream,
     const base::WeakPtr<SpdySession>& spdy_session,
     bool direct) {
   DCHECK(job);
   DCHECK(job->using_spdy());
 
+  // Note: |spdy_session| may be NULL. In that case, |delegate_| should still
+  // receive |stream| so the error propogates up correctly, however there is no
+  // point in broadcasting |spdy_session| to other requests.
+
   // The first case is the usual case.
   if (!bound_job_.get()) {
     OrphanJobsExcept(job);
@@ -322,21 +327,20 @@
     // implemented.
     NOTREACHED();
   } else {
-    bool use_relative_url = direct || url().SchemeIs("https");
-    delegate_->OnStreamReady(
-        job->server_ssl_config(),
-        job->proxy_info(),
-        new SpdyHttpStream(spdy_session, use_relative_url));
+    delegate_->OnStreamReady(job->server_ssl_config(), job->proxy_info(),
+                             stream.release());
   }
   // |this| may be deleted after this point.
-  factory->OnNewSpdySessionReady(spdy_session,
-                                 direct,
-                                 used_ssl_config,
-                                 used_proxy_info,
-                                 was_npn_negotiated,
-                                 protocol_negotiated,
-                                 using_spdy,
-                                 net_log);
+  if (spdy_session) {
+    factory->OnNewSpdySessionReady(spdy_session,
+                                   direct,
+                                   used_ssl_config,
+                                   used_proxy_info,
+                                   was_npn_negotiated,
+                                   protocol_negotiated,
+                                   using_spdy,
+                                   net_log);
+  }
 }
 
 void HttpStreamFactoryImpl::Request::OrphanJobsExcept(Job* job) {
diff --git a/net/http/http_stream_factory_impl_request.h b/net/http/http_stream_factory_impl_request.h
index 3d3b2c8..22c8ff2 100644
--- a/net/http/http_stream_factory_impl_request.h
+++ b/net/http/http_stream_factory_impl_request.h
@@ -16,6 +16,7 @@
 namespace net {
 
 class ClientSocketHandle;
+class HttpStream;
 class SpdySession;
 
 class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
@@ -64,6 +65,7 @@
 
   // Called by an attached Job if it sets up a SpdySession.
   void OnNewSpdySessionReady(Job* job,
+                             scoped_ptr<HttpStream> stream,
                              const base::WeakPtr<SpdySession>& spdy_session,
                              bool direct);
 
diff --git a/net/http/http_transaction_unittest.cc b/net/http/http_transaction_unittest.cc
index fe904d9..eed3c4f 100644
--- a/net/http/http_transaction_unittest.cc
+++ b/net/http/http_transaction_unittest.cc
@@ -296,7 +296,10 @@
   return net::ERR_IO_PENDING;
 }
 
-void MockNetworkTransaction::StopCaching() {}
+void MockNetworkTransaction::StopCaching() {
+  if (transaction_factory_.get())
+    transaction_factory_->TransactionStopCaching();
+}
 
 bool MockNetworkTransaction::GetFullRequestHeaders(
     net::HttpRequestHeaders* headers) const {
@@ -439,6 +442,7 @@
 MockNetworkLayer::MockNetworkLayer()
     : transaction_count_(0),
       done_reading_called_(false),
+      stop_caching_called_(false),
       last_create_transaction_priority_(net::DEFAULT_PRIORITY) {}
 
 MockNetworkLayer::~MockNetworkLayer() {}
@@ -447,6 +451,10 @@
   done_reading_called_ = true;
 }
 
+void MockNetworkLayer::TransactionStopCaching() {
+  stop_caching_called_ = true;
+}
+
 int MockNetworkLayer::CreateTransaction(
     net::RequestPriority priority,
     scoped_ptr<net::HttpTransaction>* trans) {
diff --git a/net/http/http_transaction_unittest.h b/net/http/http_transaction_unittest.h
index 2572b1f..5116f65 100644
--- a/net/http/http_transaction_unittest.h
+++ b/net/http/http_transaction_unittest.h
@@ -256,7 +256,9 @@
 
   int transaction_count() const { return transaction_count_; }
   bool done_reading_called() const { return done_reading_called_; }
+  bool stop_caching_called() const { return stop_caching_called_; }
   void TransactionDoneReading();
+  void TransactionStopCaching();
 
   // Returns the last priority passed to CreateTransaction, or
   // DEFAULT_PRIORITY if it hasn't been called yet.
@@ -289,6 +291,7 @@
  private:
   int transaction_count_;
   bool done_reading_called_;
+  bool stop_caching_called_;
   net::RequestPriority last_create_transaction_priority_;
   base::WeakPtr<MockNetworkTransaction> last_transaction_;
 };
diff --git a/net/http/transport_security_state.cc b/net/http/transport_security_state.cc
index 8498d26..8142e09 100644
--- a/net/http/transport_security_state.cc
+++ b/net/http/transport_security_state.cc
@@ -718,8 +718,18 @@
 }
 
 // static
-const char* const* TransportSecurityState::GooglePinsForDebugging() {
-  return kGoogleAcceptableCerts;
+bool TransportSecurityState::GetPinsForDebugging(
+    const std::string& host,
+    const char* const** out_required_pins,
+    const char* const** out_excluded_pins) {
+  const std::string canonicalized_host = CanonicalizeHost(host);
+  const struct HSTSPreload* entry =
+      GetHSTSPreload(canonicalized_host, kPreloadedSTS, kNumPreloadedSTS);
+  if (!entry)
+    return false;
+  *out_required_pins = entry->pins.required_hashes;
+  *out_excluded_pins = entry->pins.excluded_hashes;
+  return true;
 }
 
 // static
diff --git a/net/http/transport_security_state.h b/net/http/transport_security_state.h
index 7696cbb..8aaecb6 100644
--- a/net/http/transport_security_state.h
+++ b/net/http/transport_security_state.h
@@ -248,11 +248,17 @@
   static bool IsGooglePinnedProperty(const std::string& host,
                                      bool sni_enabled);
 
-  // GooglePinsForDebugging returns an array of SHA-1 pins for Google
-  // properties - each 20 bytes long - with a NULL pointer signalling the end
-  // of the array. This is a temporary debugging measure to check for binary
-  // alteration / corruption.
-  static const char* const* GooglePinsForDebugging();
+  // GetPinsForDebugging finds the preloaded entry for the given host. If none
+  // exists, it returns false. Otherwise it returns true and sets |out_pins|
+  // and |out_bad_pins| to point to arrays of SHA-1 hashes, each 20 bytes long
+  // with a NULL pointer signalling the end of the array, for the required and
+  // excluded pins, respectively.
+  // This is a temporary debugging measure to check for binary alteration /
+  // corruption.
+  static bool GetPinsForDebugging(
+    const std::string& host,
+    const char* const** out_pins,
+    const char* const** out_bad_pins);
 
   // The maximum number of seconds for which we'll cache an HSTS request.
   static const long int kMaxHSTSAgeSecs;
diff --git a/net/http/transport_security_state_static.h b/net/http/transport_security_state_static.h
index e87233d..661a6a8 100644
--- a/net/http/transport_security_state_static.h
+++ b/net/http/transport_security_state_static.h
@@ -405,6 +405,7 @@
   {17, true, "\004goto\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
   {18, true, "\005cloud\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
   {18, true, "\005glass\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
+  {18, true, "\005admin\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
   {17, false, "\004play\006google\003com", true, kGooglePins, DOMAIN_GOOGLE_COM },
   {20, true, "\006market\007android\003com", true, kGooglePins, DOMAIN_ANDROID_COM },
   {26, true, "\003ssl\020google-analytics\003com", true, kGooglePins, DOMAIN_GOOGLE_ANALYTICS_COM },
@@ -922,6 +923,7 @@
   {19, false, "\003www\007banking\002co\002at", true, kNoPins, DOMAIN_NOT_PINNED },
   {19, false, "\003mbp\007banking\002co\002at", true, kNoPins, DOMAIN_NOT_PINNED },
   {13, false, "\007feedbin\003com", true, kNoPins, DOMAIN_NOT_PINNED },
+  {9, true, "\004heha\002co", true, kNoPins, DOMAIN_NOT_PINNED },
 };
 static const size_t kNumPreloadedSTS = ARRAYSIZE_UNSAFE(kPreloadedSTS);
 
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 84dcf34..2af203c 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -184,6 +184,7 @@
     { "name": "goto.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
     { "name": "cloud.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
     { "name": "glass.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
+    { "name": "admin.google.com", "include_subdomains": true, "mode": "force-https", "pins": "google" },
     // play.google.com doesn't have include_subdomains because of crbug.com/327834.
     { "name": "play.google.com", "mode": "force-https", "pins": "google" },
 
@@ -715,6 +716,7 @@
     { "name": "www.banking.co.at", "mode": "force-https" },
     { "name": "mbp.banking.co.at", "mode": "force-https" },
     { "name": "feedbin.com", "mode": "force-https" },
+    { "name": "heha.co", "include_subdomains": true, "mode": "force-https" },
 
     // Entries that are only valid if the client supports SNI.
     { "name": "gmail.com", "mode": "force-https", "pins": "google", "snionly": true },
diff --git a/net/http_server.target.darwin-arm.mk b/net/http_server.target.darwin-arm.mk
index 1dd00b6..4b86b99 100644
--- a/net/http_server.target.darwin-arm.mk
+++ b/net/http_server.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/http_server.target.darwin-mips.mk b/net/http_server.target.darwin-mips.mk
index b1abe01..8c9f4eb 100644
--- a/net/http_server.target.darwin-mips.mk
+++ b/net/http_server.target.darwin-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/http_server.target.darwin-x86.mk b/net/http_server.target.darwin-x86.mk
index 114ac61..c1ac63a 100644
--- a/net/http_server.target.darwin-x86.mk
+++ b/net/http_server.target.darwin-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/http_server.target.darwin-x86_64.mk b/net/http_server.target.darwin-x86_64.mk
new file mode 100644
index 0000000..6b87e65
--- /dev/null
+++ b/net/http_server.target.darwin-x86_64.mk
@@ -0,0 +1,269 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := net_http_server_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	net/server/http_connection.cc \
+	net/server/http_server.cc \
+	net/server/http_server_request_info.cc \
+	net/server/http_server_response_info.cc \
+	net/server/web_socket.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_http_server_gyp
+
+# Alias gyp target name.
+.PHONY: http_server
+http_server: net_http_server_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/net/http_server.target.linux-arm.mk b/net/http_server.target.linux-arm.mk
index 1dd00b6..4b86b99 100644
--- a/net/http_server.target.linux-arm.mk
+++ b/net/http_server.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/http_server.target.linux-mips.mk b/net/http_server.target.linux-mips.mk
index b1abe01..8c9f4eb 100644
--- a/net/http_server.target.linux-mips.mk
+++ b/net/http_server.target.linux-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/http_server.target.linux-x86.mk b/net/http_server.target.linux-x86.mk
index 114ac61..c1ac63a 100644
--- a/net/http_server.target.linux-x86.mk
+++ b/net/http_server.target.linux-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/http_server.target.linux-x86_64.mk b/net/http_server.target.linux-x86_64.mk
new file mode 100644
index 0000000..6b87e65
--- /dev/null
+++ b/net/http_server.target.linux-x86_64.mk
@@ -0,0 +1,269 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := net_http_server_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	net/server/http_connection.cc \
+	net/server/http_server.cc \
+	net/server/http_server_request_info.cc \
+	net/server/http_server_response_info.cc \
+	net/server/web_socket.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_http_server_gyp
+
+# Alias gyp target name.
+.PHONY: http_server
+http_server: net_http_server_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/net/net.gyp b/net/net.gyp
index bd408e2..28dcd4d 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -136,8 +136,6 @@
         'base/iovec.h',
         'base/ip_endpoint.cc',
         'base/ip_endpoint.h',
-        'base/ip_mapping_rules.cc',
-        'base/ip_mapping_rules.h',
         'base/ip_pattern.cc',
         'base/ip_pattern.h',
         'base/keygen_handler.cc',
@@ -355,6 +353,8 @@
         'disk_cache/blockfile/backend_impl.h',
         'disk_cache/blockfile/backend_impl_v3.cc',
         'disk_cache/blockfile/backend_impl_v3.h',
+        'disk_cache/blockfile/backend_worker_v3.cc',
+        'disk_cache/blockfile/backend_worker_v3.h',
         'disk_cache/blockfile/bitmap.cc',
         'disk_cache/blockfile/bitmap.h',
         'disk_cache/blockfile/block_bitmaps_v3.cc',
@@ -488,8 +488,6 @@
         'dns/host_resolver_proc.h',
         'dns/mapped_host_resolver.cc',
         'dns/mapped_host_resolver.h',
-        'dns/mapped_ip_resolver.cc',
-        'dns/mapped_ip_resolver.h',
         'dns/mdns_cache.cc',
         'dns/mdns_cache.h',
         'dns/mdns_client.cc',
@@ -843,7 +841,7 @@
         'quic/crypto/proof_source.h',
         'quic/crypto/proof_source_chromium.cc',
         'quic/crypto/proof_source_chromium.h',
-        'quic/crypto/proof_verifier.cc',
+        'quic/crypto/proof_verifier.h',
         'quic/crypto/proof_verifier_chromium.cc',
         'quic/crypto/proof_verifier_chromium.h',
         'quic/crypto/quic_crypto_client_config.cc',
@@ -882,6 +880,8 @@
         'quic/quic_blocked_writer_interface.h',
         'quic/quic_client_session.cc',
         'quic/quic_client_session.h',
+        'quic/quic_client_session_base.cc',
+        'quic/quic_client_session_base.h',
         'quic/quic_clock.cc',
         'quic/quic_clock.h',
         'quic/quic_config.cc',
@@ -1124,6 +1124,8 @@
         'ssl/ssl_client_auth_cache.cc',
         'ssl/ssl_client_auth_cache.h',
         'ssl/ssl_client_cert_type.h',
+        'ssl/ssl_config.cc',
+        'ssl/ssl_config.h',
         'ssl/ssl_config_service.cc',
         'ssl/ssl_config_service.h',
         'ssl/ssl_config_service_defaults.cc',
@@ -1409,22 +1411,17 @@
               'third_party/mozilla_security_manager/nsPKCS12Blob.cpp',
               'third_party/mozilla_security_manager/nsPKCS12Blob.h',
             ],
+            'dependencies': [
+              '../third_party/openssl/openssl.gyp:openssl',
+            ],
           },
           {  # else !use_openssl: remove the unneeded files
             'sources!': [
               'base/crypto_module_openssl.cc',
               'base/keygen_handler_openssl.cc',
-              'base/openssl_private_key_store.h',
-              'base/openssl_private_key_store_android.cc',
-              'base/openssl_private_key_store_memory.cc',
-              'cert/cert_database_openssl.cc',
-              'cert/cert_verify_proc_openssl.cc',
-              'cert/cert_verify_proc_openssl.h',
               'cert/ct_log_verifier_openssl.cc',
               'cert/ct_objects_extractor_openssl.cc',
               'cert/jwk_serializer_openssl.cc',
-              'cert/test_root_certs_openssl.cc',
-              'cert/x509_certificate_openssl.cc',
               'cert/x509_util_openssl.cc',
               'cert/x509_util_openssl.h',
               'quic/crypto/aead_base_decrypter_openssl.cc',
@@ -1442,11 +1439,23 @@
               'socket/ssl_server_socket_openssl.cc',
               'socket/ssl_session_cache_openssl.cc',
               'socket/ssl_session_cache_openssl.h',
-              'ssl/openssl_client_key_store.cc',
-              'ssl/openssl_client_key_store.h',
             ],
           },
         ],
+        [ 'use_openssl_certs == 0', {
+            'sources!': [
+              'base/openssl_private_key_store.h',
+              'base/openssl_private_key_store_android.cc',
+              'base/openssl_private_key_store_memory.cc',
+              'cert/cert_database_openssl.cc',
+              'cert/cert_verify_proc_openssl.cc',
+              'cert/cert_verify_proc_openssl.h',
+              'cert/test_root_certs_openssl.cc',
+              'cert/x509_certificate_openssl.cc',
+              'ssl/openssl_client_key_store.cc',
+              'ssl/openssl_client_key_store.h',
+            ],
+        }],
         [ 'use_glib == 1', {
             'dependencies': [
               '../build/linux/system.gyp:gconf',
@@ -1455,12 +1464,8 @@
         }],
         [ 'desktop_linux == 1 or chromeos == 1', {
             'conditions': [
-              ['use_openssl==1', {
-                'dependencies': [
-                  '../third_party/openssl/openssl.gyp:openssl',
-                ],
-              },
-              {  # else use_openssl==0, use NSS
+              ['use_openssl == 0', {
+                 # use NSS
                 'dependencies': [
                   '../build/linux/system.gyp:ssl',
                 ],
@@ -1569,10 +1574,15 @@
           },
         ],
         [ 'OS == "mac"', {
-            'dependencies': [
-              '../third_party/nss/nss.gyp:nspr',
-              '../third_party/nss/nss.gyp:nss',
-              'third_party/nss/ssl.gyp:libssl',
+            'conditions': [
+              [ 'use_openssl == 0', {
+                'dependencies': [
+                  # defaults to nss
+                  '../third_party/nss/nss.gyp:nspr',
+                  '../third_party/nss/nss.gyp:nss',
+                  'third_party/nss/ssl.gyp:libssl',
+                ],
+              }],
             ],
             'link_settings': {
               'libraries': [
@@ -1692,7 +1702,6 @@
         'base/host_mapping_rules_unittest.cc',
         'base/host_port_pair_unittest.cc',
         'base/ip_endpoint_unittest.cc',
-        'base/ip_mapping_rules_unittest.cc',
         'base/ip_pattern_unittest.cc',
         'base/keygen_handler_unittest.cc',
         'base/mime_sniffer_unittest.cc',
@@ -2175,8 +2184,8 @@
         }],
         [ 'OS == "android"', {
           'sources!': [
-            # See bug 344533.
-            'disk_cache/blockfile/index_table_v3unittest.cc',
+            # See bug http://crbug.com/344533.
+            'disk_cache/blockfile/index_table_v3_unittest.cc',
             # No res_ninit() et al on Android, so this doesn't make a lot of
             # sense.
             'dns/dns_config_service_posix_unittest.cc',
@@ -2262,10 +2271,14 @@
               'quic/test_tools/crypto_test_utils_openssl.cc',
               'socket/ssl_client_socket_openssl_unittest.cc',
               'socket/ssl_session_cache_openssl_unittest.cc',
-              'ssl/openssl_client_key_store_unittest.cc',
             ],
           },
         ],
+        [ 'use_openssl_certs == 0', {
+            'sources!': [
+              'ssl/openssl_client_key_store_unittest.cc',
+            ],
+        }],
         [ 'enable_websockets != 1', {
             'sources/': [
               ['exclude', '^socket_stream/'],
@@ -2333,7 +2346,7 @@
             'msvs_disabled_warnings': [4267, ],
           },
         ],
-        [ 'OS == "mac"', {
+        [ 'OS == "mac" and use_openssl == 0', {
             'dependencies': [
               '../third_party/nss/nss.gyp:nspr',
               '../third_party/nss/nss.gyp:nss',
@@ -2382,8 +2395,8 @@
               # OS is not "linux" or "freebsd" or "openbsd".
               'socket/unix_domain_socket_posix_unittest.cc',
 
-              # See bug 344533.
-              'disk_cache/v3/index_table_unittest.cc',
+              # See bug http://crbug.com/344533.
+              'disk_cache/blockfile/index_table_v3_unittest.cc',
             ],
         }],
         [ 'OS == "android"', {
@@ -2742,49 +2755,6 @@
           'msvs_disabled_warnings': [4267, ],
         },
         {
-          'target_name': 'fetch_client',
-          'type': 'executable',
-          'variables': { 'enable_wexit_time_destructors': 1, },
-          'dependencies': [
-            '../base/base.gyp:base',
-            '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
-            '../testing/gtest.gyp:gtest',
-            '../url/url.gyp:url_lib',
-            'net',
-            'net_with_v8',
-          ],
-          'sources': [
-            'tools/fetch/fetch_client.cc',
-          ],
-          # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-          'msvs_disabled_warnings': [4267, ],
-        },
-        {
-          'target_name': 'fetch_server',
-          'type': 'executable',
-          'variables': { 'enable_wexit_time_destructors': 1, },
-          'dependencies': [
-            '../base/base.gyp:base',
-            '../url/url.gyp:url_lib',
-            'net',
-          ],
-          'sources': [
-            'tools/fetch/fetch_server.cc',
-            'tools/fetch/http_listen_socket.cc',
-            'tools/fetch/http_listen_socket.h',
-            'tools/fetch/http_server.cc',
-            'tools/fetch/http_server.h',
-            'tools/fetch/http_server_request_info.cc',
-            'tools/fetch/http_server_request_info.h',
-            'tools/fetch/http_server_response_info.cc',
-            'tools/fetch/http_server_response_info.h',
-            'tools/fetch/http_session.cc',
-            'tools/fetch/http_session.h',
-          ],
-          # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-          'msvs_disabled_warnings': [4267, ],
-        },
-        {
           'target_name': 'gdig',
           'type': 'executable',
           'dependencies': [
diff --git a/net/net.target.darwin-arm.mk b/net/net.target.darwin-arm.mk
index 19bb3a0..eed3235 100644
--- a/net/net.target.darwin-arm.mk
+++ b/net/net.target.darwin-arm.mk
@@ -61,7 +61,6 @@
 	net/base/host_port_pair.cc \
 	net/base/io_buffer.cc \
 	net/base/ip_endpoint.cc \
-	net/base/ip_mapping_rules.cc \
 	net/base/ip_pattern.cc \
 	net/base/keygen_handler.cc \
 	net/base/keygen_handler_openssl.cc \
@@ -134,6 +133,7 @@
 	net/disk_cache/blockfile/addr.cc \
 	net/disk_cache/blockfile/backend_impl.cc \
 	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
 	net/disk_cache/blockfile/bitmap.cc \
 	net/disk_cache/blockfile/block_bitmaps_v3.cc \
 	net/disk_cache/blockfile/block_files.cc \
@@ -189,7 +189,6 @@
 	net/dns/host_resolver_impl.cc \
 	net/dns/host_resolver_proc.cc \
 	net/dns/mapped_host_resolver.cc \
-	net/dns/mapped_ip_resolver.cc \
 	net/dns/serial_worker.cc \
 	net/dns/single_request_host_resolver.cc \
 	net/filter/filter.cc \
@@ -332,7 +331,6 @@
 	net/quic/crypto/null_encrypter.cc \
 	net/quic/crypto/p256_key_exchange_openssl.cc \
 	net/quic/crypto/proof_source_chromium.cc \
-	net/quic/crypto/proof_verifier.cc \
 	net/quic/crypto/proof_verifier_chromium.cc \
 	net/quic/crypto/quic_crypto_client_config.cc \
 	net/quic/crypto/quic_crypto_server_config.cc \
@@ -351,6 +349,7 @@
 	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
 	net/quic/quic_clock.cc \
 	net/quic/quic_config.cc \
 	net/quic/quic_connection.cc \
@@ -458,6 +457,7 @@
 	net/ssl/ssl_cert_request_info.cc \
 	net/ssl/ssl_cipher_suite_names.cc \
 	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
 	net/ssl/ssl_config_service.cc \
 	net/ssl/ssl_config_service_defaults.cc \
 	net/ssl/ssl_info.cc \
@@ -581,6 +581,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -678,6 +679,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net.target.darwin-mips.mk b/net/net.target.darwin-mips.mk
index 18a34ac..31da97e 100644
--- a/net/net.target.darwin-mips.mk
+++ b/net/net.target.darwin-mips.mk
@@ -61,7 +61,6 @@
 	net/base/host_port_pair.cc \
 	net/base/io_buffer.cc \
 	net/base/ip_endpoint.cc \
-	net/base/ip_mapping_rules.cc \
 	net/base/ip_pattern.cc \
 	net/base/keygen_handler.cc \
 	net/base/keygen_handler_openssl.cc \
@@ -134,6 +133,7 @@
 	net/disk_cache/blockfile/addr.cc \
 	net/disk_cache/blockfile/backend_impl.cc \
 	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
 	net/disk_cache/blockfile/bitmap.cc \
 	net/disk_cache/blockfile/block_bitmaps_v3.cc \
 	net/disk_cache/blockfile/block_files.cc \
@@ -189,7 +189,6 @@
 	net/dns/host_resolver_impl.cc \
 	net/dns/host_resolver_proc.cc \
 	net/dns/mapped_host_resolver.cc \
-	net/dns/mapped_ip_resolver.cc \
 	net/dns/serial_worker.cc \
 	net/dns/single_request_host_resolver.cc \
 	net/filter/filter.cc \
@@ -332,7 +331,6 @@
 	net/quic/crypto/null_encrypter.cc \
 	net/quic/crypto/p256_key_exchange_openssl.cc \
 	net/quic/crypto/proof_source_chromium.cc \
-	net/quic/crypto/proof_verifier.cc \
 	net/quic/crypto/proof_verifier_chromium.cc \
 	net/quic/crypto/quic_crypto_client_config.cc \
 	net/quic/crypto/quic_crypto_server_config.cc \
@@ -351,6 +349,7 @@
 	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
 	net/quic/quic_clock.cc \
 	net/quic/quic_config.cc \
 	net/quic/quic_connection.cc \
@@ -458,6 +457,7 @@
 	net/ssl/ssl_cert_request_info.cc \
 	net/ssl/ssl_cipher_suite_names.cc \
 	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
 	net/ssl/ssl_config_service.cc \
 	net/ssl/ssl_config_service_defaults.cc \
 	net/ssl/ssl_info.cc \
@@ -580,6 +580,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -676,6 +677,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net.target.darwin-x86.mk b/net/net.target.darwin-x86.mk
index 04a91ae..071105f 100644
--- a/net/net.target.darwin-x86.mk
+++ b/net/net.target.darwin-x86.mk
@@ -61,7 +61,6 @@
 	net/base/host_port_pair.cc \
 	net/base/io_buffer.cc \
 	net/base/ip_endpoint.cc \
-	net/base/ip_mapping_rules.cc \
 	net/base/ip_pattern.cc \
 	net/base/keygen_handler.cc \
 	net/base/keygen_handler_openssl.cc \
@@ -134,6 +133,7 @@
 	net/disk_cache/blockfile/addr.cc \
 	net/disk_cache/blockfile/backend_impl.cc \
 	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
 	net/disk_cache/blockfile/bitmap.cc \
 	net/disk_cache/blockfile/block_bitmaps_v3.cc \
 	net/disk_cache/blockfile/block_files.cc \
@@ -189,7 +189,6 @@
 	net/dns/host_resolver_impl.cc \
 	net/dns/host_resolver_proc.cc \
 	net/dns/mapped_host_resolver.cc \
-	net/dns/mapped_ip_resolver.cc \
 	net/dns/serial_worker.cc \
 	net/dns/single_request_host_resolver.cc \
 	net/filter/filter.cc \
@@ -332,7 +331,6 @@
 	net/quic/crypto/null_encrypter.cc \
 	net/quic/crypto/p256_key_exchange_openssl.cc \
 	net/quic/crypto/proof_source_chromium.cc \
-	net/quic/crypto/proof_verifier.cc \
 	net/quic/crypto/proof_verifier_chromium.cc \
 	net/quic/crypto/quic_crypto_client_config.cc \
 	net/quic/crypto/quic_crypto_server_config.cc \
@@ -351,6 +349,7 @@
 	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
 	net/quic/quic_clock.cc \
 	net/quic/quic_config.cc \
 	net/quic/quic_connection.cc \
@@ -458,6 +457,7 @@
 	net/ssl/ssl_cert_request_info.cc \
 	net/ssl/ssl_cipher_suite_names.cc \
 	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
 	net/ssl/ssl_config_service.cc \
 	net/ssl/ssl_config_service_defaults.cc \
 	net/ssl/ssl_info.cc \
@@ -581,6 +581,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -677,6 +678,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net.target.darwin-x86_64.mk b/net/net.target.darwin-x86_64.mk
new file mode 100644
index 0000000..c05cd6d
--- /dev/null
+++ b/net/net.target.darwin-x86_64.mk
@@ -0,0 +1,786 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := net_net_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,net_net_resources_gyp)/net_resources.stamp \
+	$(call intermediates-dir-for,GYP,net_net_jni_headers_gyp)/net_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	net/android/cert_verify_result_android.cc \
+	net/android/gurl_utils.cc \
+	net/android/android_private_key.cc \
+	net/android/keystore.cc \
+	net/android/keystore_openssl.cc \
+	net/android/net_jni_registrar.cc \
+	net/android/network_change_notifier_android.cc \
+	net/android/network_change_notifier_delegate_android.cc \
+	net/android/network_change_notifier_factory_android.cc \
+	net/android/network_library.cc \
+	net/base/address_list.cc \
+	net/base/address_tracker_linux.cc \
+	net/base/auth.cc \
+	net/base/backoff_entry.cc \
+	net/base/bandwidth_metrics.cc \
+	net/base/connection_type_histograms.cc \
+	net/base/crypto_module_openssl.cc \
+	net/base/data_url.cc \
+	net/base/directory_lister.cc \
+	net/base/dns_reloader.cc \
+	net/base/dns_util.cc \
+	net/base/escape.cc \
+	net/base/file_stream.cc \
+	net/base/file_stream_context.cc \
+	net/base/file_stream_context_posix.cc \
+	net/base/file_stream_metrics.cc \
+	net/base/file_stream_metrics_posix.cc \
+	net/base/file_stream_net_log_parameters.cc \
+	net/base/int128.cc \
+	net/base/hash_value.cc \
+	net/base/host_mapping_rules.cc \
+	net/base/host_port_pair.cc \
+	net/base/io_buffer.cc \
+	net/base/ip_endpoint.cc \
+	net/base/ip_pattern.cc \
+	net/base/keygen_handler.cc \
+	net/base/keygen_handler_openssl.cc \
+	net/base/load_timing_info.cc \
+	net/base/mime_sniffer.cc \
+	net/base/mime_util.cc \
+	net/base/net_errors.cc \
+	net/base/net_errors_posix.cc \
+	net/base/net_log.cc \
+	net/base/net_log_logger.cc \
+	net/base/net_module.cc \
+	net/base/net_util.cc \
+	net/base/net_util_posix.cc \
+	net/base/network_change_notifier.cc \
+	net/base/network_delegate.cc \
+	net/base/network_time_notifier.cc \
+	net/base/openssl_private_key_store_android.cc \
+	net/base/platform_mime_util_linux.cc \
+	net/base/prioritized_dispatcher.cc \
+	net/base/registry_controlled_domains/registry_controlled_domain.cc \
+	net/base/request_priority.cc \
+	net/base/sdch_manager.cc \
+	net/base/static_cookie_policy.cc \
+	net/base/test_data_stream.cc \
+	net/base/upload_bytes_element_reader.cc \
+	net/base/upload_data_stream.cc \
+	net/base/upload_element.cc \
+	net/base/upload_element_reader.cc \
+	net/base/upload_file_element_reader.cc \
+	net/base/url_util.cc \
+	net/base/zap.cc \
+	net/cert/asn1_util.cc \
+	net/cert/cert_database.cc \
+	net/cert/cert_database_android.cc \
+	net/cert/cert_status_flags.cc \
+	net/cert/cert_verifier.cc \
+	net/cert/cert_verify_proc.cc \
+	net/cert/cert_verify_proc_android.cc \
+	net/cert/cert_verify_result.cc \
+	net/cert/crl_set.cc \
+	net/cert/ct_known_logs.cc \
+	net/cert/ct_log_verifier.cc \
+	net/cert/ct_log_verifier_openssl.cc \
+	net/cert/ct_objects_extractor_openssl.cc \
+	net/cert/ct_serialization.cc \
+	net/cert/ct_signed_certificate_timestamp_log_param.cc \
+	net/cert/ct_verify_result.cc \
+	net/cert/ev_root_ca_metadata.cc \
+	net/cert/jwk_serializer_openssl.cc \
+	net/cert/multi_log_ct_verifier.cc \
+	net/cert/multi_threaded_cert_verifier.cc \
+	net/cert/pem_tokenizer.cc \
+	net/cert/signed_certificate_timestamp.cc \
+	net/cert/single_request_cert_verifier.cc \
+	net/cert/test_root_certs.cc \
+	net/cert/test_root_certs_android.cc \
+	net/cert/x509_cert_types.cc \
+	net/cert/x509_certificate.cc \
+	net/cert/x509_certificate_net_log_param.cc \
+	net/cert/x509_certificate_openssl.cc \
+	net/cert/x509_util.cc \
+	net/cert/x509_util_android.cc \
+	net/cert/x509_util_openssl.cc \
+	net/cookies/canonical_cookie.cc \
+	net/cookies/cookie_constants.cc \
+	net/cookies/cookie_monster.cc \
+	net/cookies/cookie_store.cc \
+	net/cookies/cookie_util.cc \
+	net/cookies/parsed_cookie.cc \
+	net/disk_cache/blockfile/addr.cc \
+	net/disk_cache/blockfile/backend_impl.cc \
+	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
+	net/disk_cache/blockfile/bitmap.cc \
+	net/disk_cache/blockfile/block_bitmaps_v3.cc \
+	net/disk_cache/blockfile/block_files.cc \
+	net/disk_cache/blockfile/disk_format.cc \
+	net/disk_cache/blockfile/entry_impl.cc \
+	net/disk_cache/blockfile/entry_impl_v3.cc \
+	net/disk_cache/blockfile/eviction.cc \
+	net/disk_cache/blockfile/eviction_v3.cc \
+	net/disk_cache/blockfile/file.cc \
+	net/disk_cache/blockfile/file_lock.cc \
+	net/disk_cache/blockfile/file_posix.cc \
+	net/disk_cache/blockfile/in_flight_backend_io.cc \
+	net/disk_cache/blockfile/in_flight_io.cc \
+	net/disk_cache/blockfile/index_table_v3.cc \
+	net/disk_cache/blockfile/mapped_file.cc \
+	net/disk_cache/blockfile/mapped_file_avoid_mmap_posix.cc \
+	net/disk_cache/blockfile/rankings.cc \
+	net/disk_cache/blockfile/sparse_control.cc \
+	net/disk_cache/blockfile/stats.cc \
+	net/disk_cache/blockfile/stats_histogram.cc \
+	net/disk_cache/blockfile/trace.cc \
+	net/disk_cache/cache_creator.cc \
+	net/disk_cache/cache_util.cc \
+	net/disk_cache/cache_util_posix.cc \
+	net/disk_cache/memory/mem_backend_impl.cc \
+	net/disk_cache/memory/mem_entry_impl.cc \
+	net/disk_cache/memory/mem_rankings.cc \
+	net/disk_cache/net_log_parameters.cc \
+	net/disk_cache/simple/simple_backend_impl.cc \
+	net/disk_cache/simple/simple_entry_format.cc \
+	net/disk_cache/simple/simple_entry_impl.cc \
+	net/disk_cache/simple/simple_entry_operation.cc \
+	net/disk_cache/simple/simple_index.cc \
+	net/disk_cache/simple/simple_index_file.cc \
+	net/disk_cache/simple/simple_index_file_posix.cc \
+	net/disk_cache/simple/simple_net_log_parameters.cc \
+	net/disk_cache/simple/simple_synchronous_entry.cc \
+	net/disk_cache/simple/simple_util.cc \
+	net/disk_cache/simple/simple_version_upgrade.cc \
+	net/disk_cache/tracing/tracing_cache_backend.cc \
+	net/dns/address_sorter_posix.cc \
+	net/dns/dns_client.cc \
+	net/dns/dns_config_service.cc \
+	net/dns/dns_config_service_posix.cc \
+	net/dns/dns_hosts.cc \
+	net/dns/dns_query.cc \
+	net/dns/dns_response.cc \
+	net/dns/dns_session.cc \
+	net/dns/dns_socket_pool.cc \
+	net/dns/dns_transaction.cc \
+	net/dns/host_cache.cc \
+	net/dns/host_resolver.cc \
+	net/dns/host_resolver_impl.cc \
+	net/dns/host_resolver_proc.cc \
+	net/dns/mapped_host_resolver.cc \
+	net/dns/serial_worker.cc \
+	net/dns/single_request_host_resolver.cc \
+	net/filter/filter.cc \
+	net/filter/gzip_filter.cc \
+	net/filter/gzip_header.cc \
+	net/filter/sdch_filter.cc \
+	net/ftp/ftp_auth_cache.cc \
+	net/ftp/ftp_ctrl_response_buffer.cc \
+	net/ftp/ftp_directory_listing_parser.cc \
+	net/ftp/ftp_directory_listing_parser_ls.cc \
+	net/ftp/ftp_directory_listing_parser_netware.cc \
+	net/ftp/ftp_directory_listing_parser_os2.cc \
+	net/ftp/ftp_directory_listing_parser_vms.cc \
+	net/ftp/ftp_directory_listing_parser_windows.cc \
+	net/ftp/ftp_network_layer.cc \
+	net/ftp/ftp_network_session.cc \
+	net/ftp/ftp_network_transaction.cc \
+	net/ftp/ftp_response_info.cc \
+	net/ftp/ftp_server_type_histograms.cc \
+	net/ftp/ftp_util.cc \
+	net/http/des.cc \
+	net/http/disk_cache_based_quic_server_info.cc \
+	net/http/failing_http_transaction_factory.cc \
+	net/http/http_auth.cc \
+	net/http/http_auth_cache.cc \
+	net/http/http_auth_challenge_tokenizer.cc \
+	net/http/http_auth_controller.cc \
+	net/http/http_auth_filter.cc \
+	net/http/http_auth_handler.cc \
+	net/http/http_auth_handler_basic.cc \
+	net/http/http_auth_handler_digest.cc \
+	net/http/http_auth_handler_factory.cc \
+	net/http/http_auth_handler_ntlm.cc \
+	net/http/http_auth_handler_ntlm_portable.cc \
+	net/http/http_basic_state.cc \
+	net/http/http_basic_stream.cc \
+	net/http/http_byte_range.cc \
+	net/http/http_cache.cc \
+	net/http/http_cache_transaction.cc \
+	net/http/http_content_disposition.cc \
+	net/http/http_chunked_decoder.cc \
+	net/http/http_log_util.cc \
+	net/http/http_network_layer.cc \
+	net/http/http_network_session.cc \
+	net/http/http_network_session_peer.cc \
+	net/http/http_network_transaction.cc \
+	net/http/http_pipelined_connection_impl.cc \
+	net/http/http_pipelined_host.cc \
+	net/http/http_pipelined_host_forced.cc \
+	net/http/http_pipelined_host_impl.cc \
+	net/http/http_pipelined_host_pool.cc \
+	net/http/http_pipelined_stream.cc \
+	net/http/http_proxy_client_socket.cc \
+	net/http/http_proxy_client_socket_pool.cc \
+	net/http/http_request_headers.cc \
+	net/http/http_request_info.cc \
+	net/http/http_response_body_drainer.cc \
+	net/http/http_response_headers.cc \
+	net/http/http_response_info.cc \
+	net/http/http_security_headers.cc \
+	net/http/http_server_properties.cc \
+	net/http/http_server_properties_impl.cc \
+	net/http/http_status_code.cc \
+	net/http/http_stream_factory.cc \
+	net/http/http_stream_factory_impl.cc \
+	net/http/http_stream_factory_impl_job.cc \
+	net/http/http_stream_factory_impl_request.cc \
+	net/http/http_stream_parser.cc \
+	net/http/http_util.cc \
+	net/http/http_util_icu.cc \
+	net/http/http_vary_data.cc \
+	net/http/md4.cc \
+	net/http/partial_data.cc \
+	net/http/proxy_client_socket.cc \
+	net/http/proxy_connect_redirect_http_stream.cc \
+	net/http/transport_security_persister.cc \
+	net/http/transport_security_state.cc \
+	net/http/url_security_manager.cc \
+	net/http/url_security_manager_posix.cc \
+	net/proxy/dhcp_proxy_script_fetcher.cc \
+	net/proxy/dhcp_proxy_script_fetcher_factory.cc \
+	net/proxy/multi_threaded_proxy_resolver.cc \
+	net/proxy/network_delegate_error_observer.cc \
+	net/proxy/polling_proxy_config_service.cc \
+	net/proxy/proxy_bypass_rules.cc \
+	net/proxy/proxy_config.cc \
+	net/proxy/proxy_config_service_android.cc \
+	net/proxy/proxy_config_service_fixed.cc \
+	net/proxy/proxy_config_source.cc \
+	net/proxy/proxy_info.cc \
+	net/proxy/proxy_list.cc \
+	net/proxy/proxy_resolver_script_data.cc \
+	net/proxy/proxy_script_decider.cc \
+	net/proxy/proxy_script_fetcher_impl.cc \
+	net/proxy/proxy_server.cc \
+	net/proxy/proxy_service.cc \
+	net/quic/congestion_control/available_channel_estimator.cc \
+	net/quic/congestion_control/channel_estimator.cc \
+	net/quic/congestion_control/cube_root.cc \
+	net/quic/congestion_control/cubic.cc \
+	net/quic/congestion_control/fix_rate_receiver.cc \
+	net/quic/congestion_control/fix_rate_sender.cc \
+	net/quic/congestion_control/hybrid_slow_start.cc \
+	net/quic/congestion_control/inter_arrival_bitrate_ramp_up.cc \
+	net/quic/congestion_control/inter_arrival_overuse_detector.cc \
+	net/quic/congestion_control/inter_arrival_probe.cc \
+	net/quic/congestion_control/inter_arrival_receiver.cc \
+	net/quic/congestion_control/inter_arrival_sender.cc \
+	net/quic/congestion_control/inter_arrival_state_machine.cc \
+	net/quic/congestion_control/leaky_bucket.cc \
+	net/quic/congestion_control/loss_detection_interface.cc \
+	net/quic/congestion_control/paced_sender.cc \
+	net/quic/congestion_control/pacing_sender.cc \
+	net/quic/congestion_control/receive_algorithm_interface.cc \
+	net/quic/congestion_control/rtt_stats.cc \
+	net/quic/congestion_control/send_algorithm_interface.cc \
+	net/quic/congestion_control/tcp_cubic_sender.cc \
+	net/quic/congestion_control/tcp_loss_algorithm.cc \
+	net/quic/congestion_control/tcp_receiver.cc \
+	net/quic/congestion_control/time_loss_algorithm.cc \
+	net/quic/crypto/aead_base_decrypter_openssl.cc \
+	net/quic/crypto/aead_base_encrypter_openssl.cc \
+	net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc \
+	net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc \
+	net/quic/crypto/cert_compressor.cc \
+	net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc \
+	net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc \
+	net/quic/crypto/channel_id.cc \
+	net/quic/crypto/channel_id_openssl.cc \
+	net/quic/crypto/common_cert_set.cc \
+	net/quic/crypto/crypto_framer.cc \
+	net/quic/crypto/crypto_handshake.cc \
+	net/quic/crypto/crypto_handshake_message.cc \
+	net/quic/crypto/crypto_secret_boxer.cc \
+	net/quic/crypto/crypto_server_config_protobuf.cc \
+	net/quic/crypto/crypto_utils.cc \
+	net/quic/crypto/curve25519_key_exchange.cc \
+	net/quic/crypto/local_strike_register_client.cc \
+	net/quic/crypto/null_decrypter.cc \
+	net/quic/crypto/null_encrypter.cc \
+	net/quic/crypto/p256_key_exchange_openssl.cc \
+	net/quic/crypto/proof_source_chromium.cc \
+	net/quic/crypto/proof_verifier_chromium.cc \
+	net/quic/crypto/quic_crypto_client_config.cc \
+	net/quic/crypto/quic_crypto_server_config.cc \
+	net/quic/crypto/quic_decrypter.cc \
+	net/quic/crypto/quic_encrypter.cc \
+	net/quic/crypto/quic_random.cc \
+	net/quic/crypto/quic_server_info.cc \
+	net/quic/crypto/scoped_evp_aead_ctx.cc \
+	net/quic/crypto/strike_register.cc \
+	net/quic/crypto/source_address_token.cc \
+	net/quic/iovector.cc \
+	net/quic/port_suggester.cc \
+	net/quic/quic_ack_notifier.cc \
+	net/quic/quic_ack_notifier_manager.cc \
+	net/quic/quic_address_mismatch.cc \
+	net/quic/quic_alarm.cc \
+	net/quic/quic_bandwidth.cc \
+	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
+	net/quic/quic_clock.cc \
+	net/quic/quic_config.cc \
+	net/quic/quic_connection.cc \
+	net/quic/quic_connection_helper.cc \
+	net/quic/quic_connection_logger.cc \
+	net/quic/quic_connection_stats.cc \
+	net/quic/quic_crypto_client_stream.cc \
+	net/quic/quic_crypto_server_stream.cc \
+	net/quic/quic_crypto_stream.cc \
+	net/quic/quic_data_reader.cc \
+	net/quic/quic_data_stream.cc \
+	net/quic/quic_data_writer.cc \
+	net/quic/quic_default_packet_writer.cc \
+	net/quic/quic_fec_group.cc \
+	net/quic/quic_framer.cc \
+	net/quic/quic_headers_stream.cc \
+	net/quic/quic_http_stream.cc \
+	net/quic/quic_http_utils.cc \
+	net/quic/quic_packet_creator.cc \
+	net/quic/quic_packet_generator.cc \
+	net/quic/quic_protocol.cc \
+	net/quic/quic_received_packet_manager.cc \
+	net/quic/quic_reliable_client_stream.cc \
+	net/quic/quic_sent_entropy_manager.cc \
+	net/quic/quic_sent_packet_manager.cc \
+	net/quic/quic_session.cc \
+	net/quic/quic_session_key.cc \
+	net/quic/quic_socket_address_coder.cc \
+	net/quic/quic_stream_factory.cc \
+	net/quic/quic_stream_sequencer.cc \
+	net/quic/quic_time.cc \
+	net/quic/quic_unacked_packet_map.cc \
+	net/quic/quic_utils.cc \
+	net/quic/quic_write_blocked_list.cc \
+	net/quic/reliable_quic_stream.cc \
+	net/quic/spdy_utils.cc \
+	net/socket/buffered_write_stream_socket.cc \
+	net/socket/client_socket_factory.cc \
+	net/socket/client_socket_handle.cc \
+	net/socket/client_socket_pool.cc \
+	net/socket/client_socket_pool_base.cc \
+	net/socket/client_socket_pool_histograms.cc \
+	net/socket/client_socket_pool_manager.cc \
+	net/socket/client_socket_pool_manager_impl.cc \
+	net/socket/socket_descriptor.cc \
+	net/socket/socket_net_log_params.cc \
+	net/socket/socks5_client_socket.cc \
+	net/socket/socks_client_socket.cc \
+	net/socket/socks_client_socket_pool.cc \
+	net/socket/ssl_client_socket.cc \
+	net/socket/ssl_client_socket_openssl.cc \
+	net/socket/ssl_client_socket_pool.cc \
+	net/socket/ssl_error_params.cc \
+	net/socket/ssl_server_socket_openssl.cc \
+	net/socket/ssl_session_cache_openssl.cc \
+	net/socket/stream_listen_socket.cc \
+	net/socket/stream_socket.cc \
+	net/socket/tcp_client_socket.cc \
+	net/socket/tcp_listen_socket.cc \
+	net/socket/tcp_server_socket.cc \
+	net/socket/tcp_socket.cc \
+	net/socket/tcp_socket_libevent.cc \
+	net/socket/transport_client_socket_pool.cc \
+	net/socket/unix_domain_socket_posix.cc \
+	net/socket_stream/socket_stream.cc \
+	net/socket_stream/socket_stream_job.cc \
+	net/socket_stream/socket_stream_job_manager.cc \
+	net/socket_stream/socket_stream_metrics.cc \
+	net/spdy/buffered_spdy_framer.cc \
+	net/spdy/hpack_constants.cc \
+	net/spdy/hpack_decoder.cc \
+	net/spdy/hpack_encoder.cc \
+	net/spdy/hpack_encoding_context.cc \
+	net/spdy/hpack_entry.cc \
+	net/spdy/hpack_header_table.cc \
+	net/spdy/hpack_huffman_table.cc \
+	net/spdy/hpack_input_stream.cc \
+	net/spdy/hpack_output_stream.cc \
+	net/spdy/hpack_string_util.cc \
+	net/spdy/spdy_buffer.cc \
+	net/spdy/spdy_buffer_producer.cc \
+	net/spdy/spdy_frame_builder.cc \
+	net/spdy/spdy_frame_reader.cc \
+	net/spdy/spdy_framer.cc \
+	net/spdy/spdy_header_block.cc \
+	net/spdy/spdy_headers_block_parser.cc \
+	net/spdy/spdy_http_stream.cc \
+	net/spdy/spdy_http_utils.cc \
+	net/spdy/spdy_pinnable_buffer_piece.cc \
+	net/spdy/spdy_prefixed_buffer_reader.cc \
+	net/spdy/spdy_protocol.cc \
+	net/spdy/spdy_proxy_client_socket.cc \
+	net/spdy/spdy_read_queue.cc \
+	net/spdy/spdy_session.cc \
+	net/spdy/spdy_session_key.cc \
+	net/spdy/spdy_session_pool.cc \
+	net/spdy/spdy_stream.cc \
+	net/spdy/spdy_websocket_stream.cc \
+	net/spdy/spdy_write_queue.cc \
+	net/ssl/default_server_bound_cert_store.cc \
+	net/ssl/openssl_client_key_store.cc \
+	net/ssl/server_bound_cert_service.cc \
+	net/ssl/server_bound_cert_store.cc \
+	net/ssl/signed_certificate_timestamp_and_status.cc \
+	net/ssl/ssl_cert_request_info.cc \
+	net/ssl/ssl_cipher_suite_names.cc \
+	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
+	net/ssl/ssl_config_service.cc \
+	net/ssl/ssl_config_service_defaults.cc \
+	net/ssl/ssl_info.cc \
+	net/udp/udp_client_socket.cc \
+	net/udp/udp_net_log_parameters.cc \
+	net/udp/udp_server_socket.cc \
+	net/udp/udp_socket_libevent.cc \
+	net/url_request/data_protocol_handler.cc \
+	net/url_request/file_protocol_handler.cc \
+	net/url_request/ftp_protocol_handler.cc \
+	net/url_request/protocol_intercept_job_factory.cc \
+	net/url_request/static_http_user_agent_settings.cc \
+	net/url_request/url_fetcher.cc \
+	net/url_request/url_fetcher_core.cc \
+	net/url_request/url_fetcher_delegate.cc \
+	net/url_request/url_fetcher_impl.cc \
+	net/url_request/url_fetcher_response_writer.cc \
+	net/url_request/url_range_request_job.cc \
+	net/url_request/url_request.cc \
+	net/url_request/url_request_about_job.cc \
+	net/url_request/url_request_context.cc \
+	net/url_request/url_request_context_builder.cc \
+	net/url_request/url_request_context_getter.cc \
+	net/url_request/url_request_context_storage.cc \
+	net/url_request/url_request_data_job.cc \
+	net/url_request/url_request_error_job.cc \
+	net/url_request/url_request_file_dir_job.cc \
+	net/url_request/url_request_file_job.cc \
+	net/url_request/url_request_filter.cc \
+	net/url_request/url_request_ftp_job.cc \
+	net/url_request/url_request_http_job.cc \
+	net/url_request/url_request_job.cc \
+	net/url_request/url_request_job_factory.cc \
+	net/url_request/url_request_job_factory_impl.cc \
+	net/url_request/url_request_job_manager.cc \
+	net/url_request/url_request_netlog_params.cc \
+	net/url_request/url_request_redirect_job.cc \
+	net/url_request/url_request_simple_job.cc \
+	net/url_request/url_request_test_job.cc \
+	net/url_request/url_request_throttler_entry.cc \
+	net/url_request/url_request_throttler_header_adapter.cc \
+	net/url_request/url_request_throttler_manager.cc \
+	net/url_request/view_cache_helper.cc \
+	net/url_request/websocket_handshake_userdata_key.cc \
+	net/websockets/websocket_basic_handshake_stream.cc \
+	net/websockets/websocket_basic_stream.cc \
+	net/websockets/websocket_channel.cc \
+	net/websockets/websocket_deflate_predictor_impl.cc \
+	net/websockets/websocket_deflate_stream.cc \
+	net/websockets/websocket_deflater.cc \
+	net/websockets/websocket_errors.cc \
+	net/websockets/websocket_extension.cc \
+	net/websockets/websocket_extension_parser.cc \
+	net/websockets/websocket_frame.cc \
+	net/websockets/websocket_frame_parser.cc \
+	net/websockets/websocket_handshake_constants.cc \
+	net/websockets/websocket_handshake_handler.cc \
+	net/websockets/websocket_handshake_request_info.cc \
+	net/websockets/websocket_handshake_response_info.cc \
+	net/websockets/websocket_handshake_stream_create_helper.cc \
+	net/websockets/websocket_inflater.cc \
+	net/websockets/websocket_job.cc \
+	net/websockets/websocket_net_log_params.cc \
+	net/websockets/websocket_stream.cc \
+	net/websockets/websocket_throttle.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNET_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DENABLE_BUILT_IN_DNS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/openssl \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(gyp_shared_intermediate_dir)/net \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNET_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DENABLE_BUILT_IN_DNS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/openssl \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(gyp_shared_intermediate_dir)/net \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_gyp
+
+# Alias gyp target name.
+.PHONY: net
+net: net_net_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/net/net.target.linux-arm.mk b/net/net.target.linux-arm.mk
index 19bb3a0..eed3235 100644
--- a/net/net.target.linux-arm.mk
+++ b/net/net.target.linux-arm.mk
@@ -61,7 +61,6 @@
 	net/base/host_port_pair.cc \
 	net/base/io_buffer.cc \
 	net/base/ip_endpoint.cc \
-	net/base/ip_mapping_rules.cc \
 	net/base/ip_pattern.cc \
 	net/base/keygen_handler.cc \
 	net/base/keygen_handler_openssl.cc \
@@ -134,6 +133,7 @@
 	net/disk_cache/blockfile/addr.cc \
 	net/disk_cache/blockfile/backend_impl.cc \
 	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
 	net/disk_cache/blockfile/bitmap.cc \
 	net/disk_cache/blockfile/block_bitmaps_v3.cc \
 	net/disk_cache/blockfile/block_files.cc \
@@ -189,7 +189,6 @@
 	net/dns/host_resolver_impl.cc \
 	net/dns/host_resolver_proc.cc \
 	net/dns/mapped_host_resolver.cc \
-	net/dns/mapped_ip_resolver.cc \
 	net/dns/serial_worker.cc \
 	net/dns/single_request_host_resolver.cc \
 	net/filter/filter.cc \
@@ -332,7 +331,6 @@
 	net/quic/crypto/null_encrypter.cc \
 	net/quic/crypto/p256_key_exchange_openssl.cc \
 	net/quic/crypto/proof_source_chromium.cc \
-	net/quic/crypto/proof_verifier.cc \
 	net/quic/crypto/proof_verifier_chromium.cc \
 	net/quic/crypto/quic_crypto_client_config.cc \
 	net/quic/crypto/quic_crypto_server_config.cc \
@@ -351,6 +349,7 @@
 	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
 	net/quic/quic_clock.cc \
 	net/quic/quic_config.cc \
 	net/quic/quic_connection.cc \
@@ -458,6 +457,7 @@
 	net/ssl/ssl_cert_request_info.cc \
 	net/ssl/ssl_cipher_suite_names.cc \
 	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
 	net/ssl/ssl_config_service.cc \
 	net/ssl/ssl_config_service_defaults.cc \
 	net/ssl/ssl_info.cc \
@@ -581,6 +581,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -678,6 +679,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net.target.linux-mips.mk b/net/net.target.linux-mips.mk
index 18a34ac..31da97e 100644
--- a/net/net.target.linux-mips.mk
+++ b/net/net.target.linux-mips.mk
@@ -61,7 +61,6 @@
 	net/base/host_port_pair.cc \
 	net/base/io_buffer.cc \
 	net/base/ip_endpoint.cc \
-	net/base/ip_mapping_rules.cc \
 	net/base/ip_pattern.cc \
 	net/base/keygen_handler.cc \
 	net/base/keygen_handler_openssl.cc \
@@ -134,6 +133,7 @@
 	net/disk_cache/blockfile/addr.cc \
 	net/disk_cache/blockfile/backend_impl.cc \
 	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
 	net/disk_cache/blockfile/bitmap.cc \
 	net/disk_cache/blockfile/block_bitmaps_v3.cc \
 	net/disk_cache/blockfile/block_files.cc \
@@ -189,7 +189,6 @@
 	net/dns/host_resolver_impl.cc \
 	net/dns/host_resolver_proc.cc \
 	net/dns/mapped_host_resolver.cc \
-	net/dns/mapped_ip_resolver.cc \
 	net/dns/serial_worker.cc \
 	net/dns/single_request_host_resolver.cc \
 	net/filter/filter.cc \
@@ -332,7 +331,6 @@
 	net/quic/crypto/null_encrypter.cc \
 	net/quic/crypto/p256_key_exchange_openssl.cc \
 	net/quic/crypto/proof_source_chromium.cc \
-	net/quic/crypto/proof_verifier.cc \
 	net/quic/crypto/proof_verifier_chromium.cc \
 	net/quic/crypto/quic_crypto_client_config.cc \
 	net/quic/crypto/quic_crypto_server_config.cc \
@@ -351,6 +349,7 @@
 	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
 	net/quic/quic_clock.cc \
 	net/quic/quic_config.cc \
 	net/quic/quic_connection.cc \
@@ -458,6 +457,7 @@
 	net/ssl/ssl_cert_request_info.cc \
 	net/ssl/ssl_cipher_suite_names.cc \
 	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
 	net/ssl/ssl_config_service.cc \
 	net/ssl/ssl_config_service_defaults.cc \
 	net/ssl/ssl_info.cc \
@@ -580,6 +580,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -676,6 +677,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net.target.linux-x86.mk b/net/net.target.linux-x86.mk
index 04a91ae..071105f 100644
--- a/net/net.target.linux-x86.mk
+++ b/net/net.target.linux-x86.mk
@@ -61,7 +61,6 @@
 	net/base/host_port_pair.cc \
 	net/base/io_buffer.cc \
 	net/base/ip_endpoint.cc \
-	net/base/ip_mapping_rules.cc \
 	net/base/ip_pattern.cc \
 	net/base/keygen_handler.cc \
 	net/base/keygen_handler_openssl.cc \
@@ -134,6 +133,7 @@
 	net/disk_cache/blockfile/addr.cc \
 	net/disk_cache/blockfile/backend_impl.cc \
 	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
 	net/disk_cache/blockfile/bitmap.cc \
 	net/disk_cache/blockfile/block_bitmaps_v3.cc \
 	net/disk_cache/blockfile/block_files.cc \
@@ -189,7 +189,6 @@
 	net/dns/host_resolver_impl.cc \
 	net/dns/host_resolver_proc.cc \
 	net/dns/mapped_host_resolver.cc \
-	net/dns/mapped_ip_resolver.cc \
 	net/dns/serial_worker.cc \
 	net/dns/single_request_host_resolver.cc \
 	net/filter/filter.cc \
@@ -332,7 +331,6 @@
 	net/quic/crypto/null_encrypter.cc \
 	net/quic/crypto/p256_key_exchange_openssl.cc \
 	net/quic/crypto/proof_source_chromium.cc \
-	net/quic/crypto/proof_verifier.cc \
 	net/quic/crypto/proof_verifier_chromium.cc \
 	net/quic/crypto/quic_crypto_client_config.cc \
 	net/quic/crypto/quic_crypto_server_config.cc \
@@ -351,6 +349,7 @@
 	net/quic/quic_alarm.cc \
 	net/quic/quic_bandwidth.cc \
 	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
 	net/quic/quic_clock.cc \
 	net/quic/quic_config.cc \
 	net/quic/quic_connection.cc \
@@ -458,6 +457,7 @@
 	net/ssl/ssl_cert_request_info.cc \
 	net/ssl/ssl_cipher_suite_names.cc \
 	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
 	net/ssl/ssl_config_service.cc \
 	net/ssl/ssl_config_service_defaults.cc \
 	net/ssl/ssl_info.cc \
@@ -581,6 +581,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -677,6 +678,7 @@
 	'-DENABLE_BUILT_IN_DNS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net.target.linux-x86_64.mk b/net/net.target.linux-x86_64.mk
new file mode 100644
index 0000000..c05cd6d
--- /dev/null
+++ b/net/net.target.linux-x86_64.mk
@@ -0,0 +1,786 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := net_net_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,net_net_resources_gyp)/net_resources.stamp \
+	$(call intermediates-dir-for,GYP,net_net_jni_headers_gyp)/net_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	net/android/cert_verify_result_android.cc \
+	net/android/gurl_utils.cc \
+	net/android/android_private_key.cc \
+	net/android/keystore.cc \
+	net/android/keystore_openssl.cc \
+	net/android/net_jni_registrar.cc \
+	net/android/network_change_notifier_android.cc \
+	net/android/network_change_notifier_delegate_android.cc \
+	net/android/network_change_notifier_factory_android.cc \
+	net/android/network_library.cc \
+	net/base/address_list.cc \
+	net/base/address_tracker_linux.cc \
+	net/base/auth.cc \
+	net/base/backoff_entry.cc \
+	net/base/bandwidth_metrics.cc \
+	net/base/connection_type_histograms.cc \
+	net/base/crypto_module_openssl.cc \
+	net/base/data_url.cc \
+	net/base/directory_lister.cc \
+	net/base/dns_reloader.cc \
+	net/base/dns_util.cc \
+	net/base/escape.cc \
+	net/base/file_stream.cc \
+	net/base/file_stream_context.cc \
+	net/base/file_stream_context_posix.cc \
+	net/base/file_stream_metrics.cc \
+	net/base/file_stream_metrics_posix.cc \
+	net/base/file_stream_net_log_parameters.cc \
+	net/base/int128.cc \
+	net/base/hash_value.cc \
+	net/base/host_mapping_rules.cc \
+	net/base/host_port_pair.cc \
+	net/base/io_buffer.cc \
+	net/base/ip_endpoint.cc \
+	net/base/ip_pattern.cc \
+	net/base/keygen_handler.cc \
+	net/base/keygen_handler_openssl.cc \
+	net/base/load_timing_info.cc \
+	net/base/mime_sniffer.cc \
+	net/base/mime_util.cc \
+	net/base/net_errors.cc \
+	net/base/net_errors_posix.cc \
+	net/base/net_log.cc \
+	net/base/net_log_logger.cc \
+	net/base/net_module.cc \
+	net/base/net_util.cc \
+	net/base/net_util_posix.cc \
+	net/base/network_change_notifier.cc \
+	net/base/network_delegate.cc \
+	net/base/network_time_notifier.cc \
+	net/base/openssl_private_key_store_android.cc \
+	net/base/platform_mime_util_linux.cc \
+	net/base/prioritized_dispatcher.cc \
+	net/base/registry_controlled_domains/registry_controlled_domain.cc \
+	net/base/request_priority.cc \
+	net/base/sdch_manager.cc \
+	net/base/static_cookie_policy.cc \
+	net/base/test_data_stream.cc \
+	net/base/upload_bytes_element_reader.cc \
+	net/base/upload_data_stream.cc \
+	net/base/upload_element.cc \
+	net/base/upload_element_reader.cc \
+	net/base/upload_file_element_reader.cc \
+	net/base/url_util.cc \
+	net/base/zap.cc \
+	net/cert/asn1_util.cc \
+	net/cert/cert_database.cc \
+	net/cert/cert_database_android.cc \
+	net/cert/cert_status_flags.cc \
+	net/cert/cert_verifier.cc \
+	net/cert/cert_verify_proc.cc \
+	net/cert/cert_verify_proc_android.cc \
+	net/cert/cert_verify_result.cc \
+	net/cert/crl_set.cc \
+	net/cert/ct_known_logs.cc \
+	net/cert/ct_log_verifier.cc \
+	net/cert/ct_log_verifier_openssl.cc \
+	net/cert/ct_objects_extractor_openssl.cc \
+	net/cert/ct_serialization.cc \
+	net/cert/ct_signed_certificate_timestamp_log_param.cc \
+	net/cert/ct_verify_result.cc \
+	net/cert/ev_root_ca_metadata.cc \
+	net/cert/jwk_serializer_openssl.cc \
+	net/cert/multi_log_ct_verifier.cc \
+	net/cert/multi_threaded_cert_verifier.cc \
+	net/cert/pem_tokenizer.cc \
+	net/cert/signed_certificate_timestamp.cc \
+	net/cert/single_request_cert_verifier.cc \
+	net/cert/test_root_certs.cc \
+	net/cert/test_root_certs_android.cc \
+	net/cert/x509_cert_types.cc \
+	net/cert/x509_certificate.cc \
+	net/cert/x509_certificate_net_log_param.cc \
+	net/cert/x509_certificate_openssl.cc \
+	net/cert/x509_util.cc \
+	net/cert/x509_util_android.cc \
+	net/cert/x509_util_openssl.cc \
+	net/cookies/canonical_cookie.cc \
+	net/cookies/cookie_constants.cc \
+	net/cookies/cookie_monster.cc \
+	net/cookies/cookie_store.cc \
+	net/cookies/cookie_util.cc \
+	net/cookies/parsed_cookie.cc \
+	net/disk_cache/blockfile/addr.cc \
+	net/disk_cache/blockfile/backend_impl.cc \
+	net/disk_cache/blockfile/backend_impl_v3.cc \
+	net/disk_cache/blockfile/backend_worker_v3.cc \
+	net/disk_cache/blockfile/bitmap.cc \
+	net/disk_cache/blockfile/block_bitmaps_v3.cc \
+	net/disk_cache/blockfile/block_files.cc \
+	net/disk_cache/blockfile/disk_format.cc \
+	net/disk_cache/blockfile/entry_impl.cc \
+	net/disk_cache/blockfile/entry_impl_v3.cc \
+	net/disk_cache/blockfile/eviction.cc \
+	net/disk_cache/blockfile/eviction_v3.cc \
+	net/disk_cache/blockfile/file.cc \
+	net/disk_cache/blockfile/file_lock.cc \
+	net/disk_cache/blockfile/file_posix.cc \
+	net/disk_cache/blockfile/in_flight_backend_io.cc \
+	net/disk_cache/blockfile/in_flight_io.cc \
+	net/disk_cache/blockfile/index_table_v3.cc \
+	net/disk_cache/blockfile/mapped_file.cc \
+	net/disk_cache/blockfile/mapped_file_avoid_mmap_posix.cc \
+	net/disk_cache/blockfile/rankings.cc \
+	net/disk_cache/blockfile/sparse_control.cc \
+	net/disk_cache/blockfile/stats.cc \
+	net/disk_cache/blockfile/stats_histogram.cc \
+	net/disk_cache/blockfile/trace.cc \
+	net/disk_cache/cache_creator.cc \
+	net/disk_cache/cache_util.cc \
+	net/disk_cache/cache_util_posix.cc \
+	net/disk_cache/memory/mem_backend_impl.cc \
+	net/disk_cache/memory/mem_entry_impl.cc \
+	net/disk_cache/memory/mem_rankings.cc \
+	net/disk_cache/net_log_parameters.cc \
+	net/disk_cache/simple/simple_backend_impl.cc \
+	net/disk_cache/simple/simple_entry_format.cc \
+	net/disk_cache/simple/simple_entry_impl.cc \
+	net/disk_cache/simple/simple_entry_operation.cc \
+	net/disk_cache/simple/simple_index.cc \
+	net/disk_cache/simple/simple_index_file.cc \
+	net/disk_cache/simple/simple_index_file_posix.cc \
+	net/disk_cache/simple/simple_net_log_parameters.cc \
+	net/disk_cache/simple/simple_synchronous_entry.cc \
+	net/disk_cache/simple/simple_util.cc \
+	net/disk_cache/simple/simple_version_upgrade.cc \
+	net/disk_cache/tracing/tracing_cache_backend.cc \
+	net/dns/address_sorter_posix.cc \
+	net/dns/dns_client.cc \
+	net/dns/dns_config_service.cc \
+	net/dns/dns_config_service_posix.cc \
+	net/dns/dns_hosts.cc \
+	net/dns/dns_query.cc \
+	net/dns/dns_response.cc \
+	net/dns/dns_session.cc \
+	net/dns/dns_socket_pool.cc \
+	net/dns/dns_transaction.cc \
+	net/dns/host_cache.cc \
+	net/dns/host_resolver.cc \
+	net/dns/host_resolver_impl.cc \
+	net/dns/host_resolver_proc.cc \
+	net/dns/mapped_host_resolver.cc \
+	net/dns/serial_worker.cc \
+	net/dns/single_request_host_resolver.cc \
+	net/filter/filter.cc \
+	net/filter/gzip_filter.cc \
+	net/filter/gzip_header.cc \
+	net/filter/sdch_filter.cc \
+	net/ftp/ftp_auth_cache.cc \
+	net/ftp/ftp_ctrl_response_buffer.cc \
+	net/ftp/ftp_directory_listing_parser.cc \
+	net/ftp/ftp_directory_listing_parser_ls.cc \
+	net/ftp/ftp_directory_listing_parser_netware.cc \
+	net/ftp/ftp_directory_listing_parser_os2.cc \
+	net/ftp/ftp_directory_listing_parser_vms.cc \
+	net/ftp/ftp_directory_listing_parser_windows.cc \
+	net/ftp/ftp_network_layer.cc \
+	net/ftp/ftp_network_session.cc \
+	net/ftp/ftp_network_transaction.cc \
+	net/ftp/ftp_response_info.cc \
+	net/ftp/ftp_server_type_histograms.cc \
+	net/ftp/ftp_util.cc \
+	net/http/des.cc \
+	net/http/disk_cache_based_quic_server_info.cc \
+	net/http/failing_http_transaction_factory.cc \
+	net/http/http_auth.cc \
+	net/http/http_auth_cache.cc \
+	net/http/http_auth_challenge_tokenizer.cc \
+	net/http/http_auth_controller.cc \
+	net/http/http_auth_filter.cc \
+	net/http/http_auth_handler.cc \
+	net/http/http_auth_handler_basic.cc \
+	net/http/http_auth_handler_digest.cc \
+	net/http/http_auth_handler_factory.cc \
+	net/http/http_auth_handler_ntlm.cc \
+	net/http/http_auth_handler_ntlm_portable.cc \
+	net/http/http_basic_state.cc \
+	net/http/http_basic_stream.cc \
+	net/http/http_byte_range.cc \
+	net/http/http_cache.cc \
+	net/http/http_cache_transaction.cc \
+	net/http/http_content_disposition.cc \
+	net/http/http_chunked_decoder.cc \
+	net/http/http_log_util.cc \
+	net/http/http_network_layer.cc \
+	net/http/http_network_session.cc \
+	net/http/http_network_session_peer.cc \
+	net/http/http_network_transaction.cc \
+	net/http/http_pipelined_connection_impl.cc \
+	net/http/http_pipelined_host.cc \
+	net/http/http_pipelined_host_forced.cc \
+	net/http/http_pipelined_host_impl.cc \
+	net/http/http_pipelined_host_pool.cc \
+	net/http/http_pipelined_stream.cc \
+	net/http/http_proxy_client_socket.cc \
+	net/http/http_proxy_client_socket_pool.cc \
+	net/http/http_request_headers.cc \
+	net/http/http_request_info.cc \
+	net/http/http_response_body_drainer.cc \
+	net/http/http_response_headers.cc \
+	net/http/http_response_info.cc \
+	net/http/http_security_headers.cc \
+	net/http/http_server_properties.cc \
+	net/http/http_server_properties_impl.cc \
+	net/http/http_status_code.cc \
+	net/http/http_stream_factory.cc \
+	net/http/http_stream_factory_impl.cc \
+	net/http/http_stream_factory_impl_job.cc \
+	net/http/http_stream_factory_impl_request.cc \
+	net/http/http_stream_parser.cc \
+	net/http/http_util.cc \
+	net/http/http_util_icu.cc \
+	net/http/http_vary_data.cc \
+	net/http/md4.cc \
+	net/http/partial_data.cc \
+	net/http/proxy_client_socket.cc \
+	net/http/proxy_connect_redirect_http_stream.cc \
+	net/http/transport_security_persister.cc \
+	net/http/transport_security_state.cc \
+	net/http/url_security_manager.cc \
+	net/http/url_security_manager_posix.cc \
+	net/proxy/dhcp_proxy_script_fetcher.cc \
+	net/proxy/dhcp_proxy_script_fetcher_factory.cc \
+	net/proxy/multi_threaded_proxy_resolver.cc \
+	net/proxy/network_delegate_error_observer.cc \
+	net/proxy/polling_proxy_config_service.cc \
+	net/proxy/proxy_bypass_rules.cc \
+	net/proxy/proxy_config.cc \
+	net/proxy/proxy_config_service_android.cc \
+	net/proxy/proxy_config_service_fixed.cc \
+	net/proxy/proxy_config_source.cc \
+	net/proxy/proxy_info.cc \
+	net/proxy/proxy_list.cc \
+	net/proxy/proxy_resolver_script_data.cc \
+	net/proxy/proxy_script_decider.cc \
+	net/proxy/proxy_script_fetcher_impl.cc \
+	net/proxy/proxy_server.cc \
+	net/proxy/proxy_service.cc \
+	net/quic/congestion_control/available_channel_estimator.cc \
+	net/quic/congestion_control/channel_estimator.cc \
+	net/quic/congestion_control/cube_root.cc \
+	net/quic/congestion_control/cubic.cc \
+	net/quic/congestion_control/fix_rate_receiver.cc \
+	net/quic/congestion_control/fix_rate_sender.cc \
+	net/quic/congestion_control/hybrid_slow_start.cc \
+	net/quic/congestion_control/inter_arrival_bitrate_ramp_up.cc \
+	net/quic/congestion_control/inter_arrival_overuse_detector.cc \
+	net/quic/congestion_control/inter_arrival_probe.cc \
+	net/quic/congestion_control/inter_arrival_receiver.cc \
+	net/quic/congestion_control/inter_arrival_sender.cc \
+	net/quic/congestion_control/inter_arrival_state_machine.cc \
+	net/quic/congestion_control/leaky_bucket.cc \
+	net/quic/congestion_control/loss_detection_interface.cc \
+	net/quic/congestion_control/paced_sender.cc \
+	net/quic/congestion_control/pacing_sender.cc \
+	net/quic/congestion_control/receive_algorithm_interface.cc \
+	net/quic/congestion_control/rtt_stats.cc \
+	net/quic/congestion_control/send_algorithm_interface.cc \
+	net/quic/congestion_control/tcp_cubic_sender.cc \
+	net/quic/congestion_control/tcp_loss_algorithm.cc \
+	net/quic/congestion_control/tcp_receiver.cc \
+	net/quic/congestion_control/time_loss_algorithm.cc \
+	net/quic/crypto/aead_base_decrypter_openssl.cc \
+	net/quic/crypto/aead_base_encrypter_openssl.cc \
+	net/quic/crypto/aes_128_gcm_12_decrypter_openssl.cc \
+	net/quic/crypto/aes_128_gcm_12_encrypter_openssl.cc \
+	net/quic/crypto/cert_compressor.cc \
+	net/quic/crypto/chacha20_poly1305_decrypter_openssl.cc \
+	net/quic/crypto/chacha20_poly1305_encrypter_openssl.cc \
+	net/quic/crypto/channel_id.cc \
+	net/quic/crypto/channel_id_openssl.cc \
+	net/quic/crypto/common_cert_set.cc \
+	net/quic/crypto/crypto_framer.cc \
+	net/quic/crypto/crypto_handshake.cc \
+	net/quic/crypto/crypto_handshake_message.cc \
+	net/quic/crypto/crypto_secret_boxer.cc \
+	net/quic/crypto/crypto_server_config_protobuf.cc \
+	net/quic/crypto/crypto_utils.cc \
+	net/quic/crypto/curve25519_key_exchange.cc \
+	net/quic/crypto/local_strike_register_client.cc \
+	net/quic/crypto/null_decrypter.cc \
+	net/quic/crypto/null_encrypter.cc \
+	net/quic/crypto/p256_key_exchange_openssl.cc \
+	net/quic/crypto/proof_source_chromium.cc \
+	net/quic/crypto/proof_verifier_chromium.cc \
+	net/quic/crypto/quic_crypto_client_config.cc \
+	net/quic/crypto/quic_crypto_server_config.cc \
+	net/quic/crypto/quic_decrypter.cc \
+	net/quic/crypto/quic_encrypter.cc \
+	net/quic/crypto/quic_random.cc \
+	net/quic/crypto/quic_server_info.cc \
+	net/quic/crypto/scoped_evp_aead_ctx.cc \
+	net/quic/crypto/strike_register.cc \
+	net/quic/crypto/source_address_token.cc \
+	net/quic/iovector.cc \
+	net/quic/port_suggester.cc \
+	net/quic/quic_ack_notifier.cc \
+	net/quic/quic_ack_notifier_manager.cc \
+	net/quic/quic_address_mismatch.cc \
+	net/quic/quic_alarm.cc \
+	net/quic/quic_bandwidth.cc \
+	net/quic/quic_client_session.cc \
+	net/quic/quic_client_session_base.cc \
+	net/quic/quic_clock.cc \
+	net/quic/quic_config.cc \
+	net/quic/quic_connection.cc \
+	net/quic/quic_connection_helper.cc \
+	net/quic/quic_connection_logger.cc \
+	net/quic/quic_connection_stats.cc \
+	net/quic/quic_crypto_client_stream.cc \
+	net/quic/quic_crypto_server_stream.cc \
+	net/quic/quic_crypto_stream.cc \
+	net/quic/quic_data_reader.cc \
+	net/quic/quic_data_stream.cc \
+	net/quic/quic_data_writer.cc \
+	net/quic/quic_default_packet_writer.cc \
+	net/quic/quic_fec_group.cc \
+	net/quic/quic_framer.cc \
+	net/quic/quic_headers_stream.cc \
+	net/quic/quic_http_stream.cc \
+	net/quic/quic_http_utils.cc \
+	net/quic/quic_packet_creator.cc \
+	net/quic/quic_packet_generator.cc \
+	net/quic/quic_protocol.cc \
+	net/quic/quic_received_packet_manager.cc \
+	net/quic/quic_reliable_client_stream.cc \
+	net/quic/quic_sent_entropy_manager.cc \
+	net/quic/quic_sent_packet_manager.cc \
+	net/quic/quic_session.cc \
+	net/quic/quic_session_key.cc \
+	net/quic/quic_socket_address_coder.cc \
+	net/quic/quic_stream_factory.cc \
+	net/quic/quic_stream_sequencer.cc \
+	net/quic/quic_time.cc \
+	net/quic/quic_unacked_packet_map.cc \
+	net/quic/quic_utils.cc \
+	net/quic/quic_write_blocked_list.cc \
+	net/quic/reliable_quic_stream.cc \
+	net/quic/spdy_utils.cc \
+	net/socket/buffered_write_stream_socket.cc \
+	net/socket/client_socket_factory.cc \
+	net/socket/client_socket_handle.cc \
+	net/socket/client_socket_pool.cc \
+	net/socket/client_socket_pool_base.cc \
+	net/socket/client_socket_pool_histograms.cc \
+	net/socket/client_socket_pool_manager.cc \
+	net/socket/client_socket_pool_manager_impl.cc \
+	net/socket/socket_descriptor.cc \
+	net/socket/socket_net_log_params.cc \
+	net/socket/socks5_client_socket.cc \
+	net/socket/socks_client_socket.cc \
+	net/socket/socks_client_socket_pool.cc \
+	net/socket/ssl_client_socket.cc \
+	net/socket/ssl_client_socket_openssl.cc \
+	net/socket/ssl_client_socket_pool.cc \
+	net/socket/ssl_error_params.cc \
+	net/socket/ssl_server_socket_openssl.cc \
+	net/socket/ssl_session_cache_openssl.cc \
+	net/socket/stream_listen_socket.cc \
+	net/socket/stream_socket.cc \
+	net/socket/tcp_client_socket.cc \
+	net/socket/tcp_listen_socket.cc \
+	net/socket/tcp_server_socket.cc \
+	net/socket/tcp_socket.cc \
+	net/socket/tcp_socket_libevent.cc \
+	net/socket/transport_client_socket_pool.cc \
+	net/socket/unix_domain_socket_posix.cc \
+	net/socket_stream/socket_stream.cc \
+	net/socket_stream/socket_stream_job.cc \
+	net/socket_stream/socket_stream_job_manager.cc \
+	net/socket_stream/socket_stream_metrics.cc \
+	net/spdy/buffered_spdy_framer.cc \
+	net/spdy/hpack_constants.cc \
+	net/spdy/hpack_decoder.cc \
+	net/spdy/hpack_encoder.cc \
+	net/spdy/hpack_encoding_context.cc \
+	net/spdy/hpack_entry.cc \
+	net/spdy/hpack_header_table.cc \
+	net/spdy/hpack_huffman_table.cc \
+	net/spdy/hpack_input_stream.cc \
+	net/spdy/hpack_output_stream.cc \
+	net/spdy/hpack_string_util.cc \
+	net/spdy/spdy_buffer.cc \
+	net/spdy/spdy_buffer_producer.cc \
+	net/spdy/spdy_frame_builder.cc \
+	net/spdy/spdy_frame_reader.cc \
+	net/spdy/spdy_framer.cc \
+	net/spdy/spdy_header_block.cc \
+	net/spdy/spdy_headers_block_parser.cc \
+	net/spdy/spdy_http_stream.cc \
+	net/spdy/spdy_http_utils.cc \
+	net/spdy/spdy_pinnable_buffer_piece.cc \
+	net/spdy/spdy_prefixed_buffer_reader.cc \
+	net/spdy/spdy_protocol.cc \
+	net/spdy/spdy_proxy_client_socket.cc \
+	net/spdy/spdy_read_queue.cc \
+	net/spdy/spdy_session.cc \
+	net/spdy/spdy_session_key.cc \
+	net/spdy/spdy_session_pool.cc \
+	net/spdy/spdy_stream.cc \
+	net/spdy/spdy_websocket_stream.cc \
+	net/spdy/spdy_write_queue.cc \
+	net/ssl/default_server_bound_cert_store.cc \
+	net/ssl/openssl_client_key_store.cc \
+	net/ssl/server_bound_cert_service.cc \
+	net/ssl/server_bound_cert_store.cc \
+	net/ssl/signed_certificate_timestamp_and_status.cc \
+	net/ssl/ssl_cert_request_info.cc \
+	net/ssl/ssl_cipher_suite_names.cc \
+	net/ssl/ssl_client_auth_cache.cc \
+	net/ssl/ssl_config.cc \
+	net/ssl/ssl_config_service.cc \
+	net/ssl/ssl_config_service_defaults.cc \
+	net/ssl/ssl_info.cc \
+	net/udp/udp_client_socket.cc \
+	net/udp/udp_net_log_parameters.cc \
+	net/udp/udp_server_socket.cc \
+	net/udp/udp_socket_libevent.cc \
+	net/url_request/data_protocol_handler.cc \
+	net/url_request/file_protocol_handler.cc \
+	net/url_request/ftp_protocol_handler.cc \
+	net/url_request/protocol_intercept_job_factory.cc \
+	net/url_request/static_http_user_agent_settings.cc \
+	net/url_request/url_fetcher.cc \
+	net/url_request/url_fetcher_core.cc \
+	net/url_request/url_fetcher_delegate.cc \
+	net/url_request/url_fetcher_impl.cc \
+	net/url_request/url_fetcher_response_writer.cc \
+	net/url_request/url_range_request_job.cc \
+	net/url_request/url_request.cc \
+	net/url_request/url_request_about_job.cc \
+	net/url_request/url_request_context.cc \
+	net/url_request/url_request_context_builder.cc \
+	net/url_request/url_request_context_getter.cc \
+	net/url_request/url_request_context_storage.cc \
+	net/url_request/url_request_data_job.cc \
+	net/url_request/url_request_error_job.cc \
+	net/url_request/url_request_file_dir_job.cc \
+	net/url_request/url_request_file_job.cc \
+	net/url_request/url_request_filter.cc \
+	net/url_request/url_request_ftp_job.cc \
+	net/url_request/url_request_http_job.cc \
+	net/url_request/url_request_job.cc \
+	net/url_request/url_request_job_factory.cc \
+	net/url_request/url_request_job_factory_impl.cc \
+	net/url_request/url_request_job_manager.cc \
+	net/url_request/url_request_netlog_params.cc \
+	net/url_request/url_request_redirect_job.cc \
+	net/url_request/url_request_simple_job.cc \
+	net/url_request/url_request_test_job.cc \
+	net/url_request/url_request_throttler_entry.cc \
+	net/url_request/url_request_throttler_header_adapter.cc \
+	net/url_request/url_request_throttler_manager.cc \
+	net/url_request/view_cache_helper.cc \
+	net/url_request/websocket_handshake_userdata_key.cc \
+	net/websockets/websocket_basic_handshake_stream.cc \
+	net/websockets/websocket_basic_stream.cc \
+	net/websockets/websocket_channel.cc \
+	net/websockets/websocket_deflate_predictor_impl.cc \
+	net/websockets/websocket_deflate_stream.cc \
+	net/websockets/websocket_deflater.cc \
+	net/websockets/websocket_errors.cc \
+	net/websockets/websocket_extension.cc \
+	net/websockets/websocket_extension_parser.cc \
+	net/websockets/websocket_frame.cc \
+	net/websockets/websocket_frame_parser.cc \
+	net/websockets/websocket_handshake_constants.cc \
+	net/websockets/websocket_handshake_handler.cc \
+	net/websockets/websocket_handshake_request_info.cc \
+	net/websockets/websocket_handshake_response_info.cc \
+	net/websockets/websocket_handshake_stream_create_helper.cc \
+	net/websockets/websocket_inflater.cc \
+	net/websockets/websocket_job.cc \
+	net/websockets/websocket_net_log_params.cc \
+	net/websockets/websocket_stream.cc \
+	net/websockets/websocket_throttle.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNET_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DENABLE_BUILT_IN_DNS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/openssl \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(gyp_shared_intermediate_dir)/net \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNET_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DENABLE_BUILT_IN_DNS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/openssl \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(gyp_shared_intermediate_dir)/net \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_gyp
+
+# Alias gyp target name.
+.PHONY: net
+net: net_net_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/net/net_errors_java.target.darwin-arm.mk b/net/net_errors_java.target.darwin-arm.mk
index 649f932..a570cbf 100644
--- a/net/net_errors_java.target.darwin-arm.mk
+++ b/net/net_errors_java.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_errors_java.target.darwin-mips.mk b/net/net_errors_java.target.darwin-mips.mk
index 973cb6e..55a83d8 100644
--- a/net/net_errors_java.target.darwin-mips.mk
+++ b/net/net_errors_java.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_errors_java.target.darwin-x86.mk b/net/net_errors_java.target.darwin-x86.mk
index c0bd8cd..c41c6f3 100644
--- a/net/net_errors_java.target.darwin-x86.mk
+++ b/net/net_errors_java.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_errors_java.target.darwin-x86_64.mk b/net/net_errors_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..77466a9
--- /dev/null
+++ b/net/net_errors_java.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_net_errors_java_gyp
+LOCAL_MODULE_STEM := net_errors_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_net_errors_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'base/net_error_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/NetError.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: $(LOCAL_PATH)/net/android/java/NetError.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/base/net_error_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java" "--template=android/java/NetError.template"
+
+.PHONY: net_net_errors_java_gyp_rule_trigger
+net_net_errors_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_net_errors_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_errors_java_gyp
+
+# Alias gyp target name.
+.PHONY: net_errors_java
+net_errors_java: net_net_errors_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/net_errors_java.target.linux-arm.mk b/net/net_errors_java.target.linux-arm.mk
index 649f932..a570cbf 100644
--- a/net/net_errors_java.target.linux-arm.mk
+++ b/net/net_errors_java.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_errors_java.target.linux-mips.mk b/net/net_errors_java.target.linux-mips.mk
index 973cb6e..55a83d8 100644
--- a/net/net_errors_java.target.linux-mips.mk
+++ b/net/net_errors_java.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_errors_java.target.linux-x86.mk b/net/net_errors_java.target.linux-x86.mk
index c0bd8cd..c41c6f3 100644
--- a/net/net_errors_java.target.linux-x86.mk
+++ b/net/net_errors_java.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_errors_java.target.linux-x86_64.mk b/net/net_errors_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..77466a9
--- /dev/null
+++ b/net/net_errors_java.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_net_errors_java_gyp
+LOCAL_MODULE_STEM := net_errors_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_net_errors_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'base/net_error_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/NetError.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java: $(LOCAL_PATH)/net/android/java/NetError.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/base/net_error_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java" "--template=android/java/NetError.template"
+
+.PHONY: net_net_errors_java_gyp_rule_trigger
+net_net_errors_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/NetError.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_net_errors_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_errors_java_gyp
+
+# Alias gyp target name.
+.PHONY: net_errors_java
+net_errors_java: net_net_errors_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/net_jni_headers.target.darwin-arm.mk b/net/net_jni_headers.target.darwin-arm.mk
index 72efa8f..aa072be 100644
--- a/net/net_jni_headers.target.darwin-arm.mk
+++ b/net/net_jni_headers.target.darwin-arm.mk
@@ -179,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -261,6 +262,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_jni_headers.target.darwin-mips.mk b/net/net_jni_headers.target.darwin-mips.mk
index 1fc9cf3..b3d4e33 100644
--- a/net/net_jni_headers.target.darwin-mips.mk
+++ b/net/net_jni_headers.target.darwin-mips.mk
@@ -178,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -259,6 +260,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_jni_headers.target.darwin-x86.mk b/net/net_jni_headers.target.darwin-x86.mk
index 2993d90..7341032 100644
--- a/net/net_jni_headers.target.darwin-x86.mk
+++ b/net/net_jni_headers.target.darwin-x86.mk
@@ -180,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -262,6 +263,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_jni_headers.target.darwin-x86_64.mk b/net/net_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..8bf705f
--- /dev/null
+++ b/net/net_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,318 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_net_jni_headers_gyp
+LOCAL_MODULE_STEM := net_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_net_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/net/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['android/java/src/org/chromium/net/AndroidCertVerifyResult.java', 'android/java/src/org/chromium/net/AndroidKeyStore.java', 'android/java/src/org/chromium/net/AndroidNetworkLibrary.java', 'android/java/src/org/chromium/net/AndroidPrivateKey.java', 'android/java/src/org/chromium/net/GURLUtils.java', 'android/java/src/org/chromium/net/NetworkChangeNotifier.java', 'android/java/src/org/chromium/net/ProxyChangeListener.java', 'android/java/src/org/chromium/net/X509Util.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/net/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidCertVerifyResult.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidKeyStore.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidKeyStore.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidNetworkLibrary.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidPrivateKey.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidPrivateKey.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/GURLUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/GURLUtils.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/NetworkChangeNotifier.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/ProxyChangeListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/ProxyChangeListener.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/X509Util.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/X509Util.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h \
+	net_net_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: net_jni_headers
+net_jni_headers: net_net_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/net_jni_headers.target.linux-arm.mk b/net/net_jni_headers.target.linux-arm.mk
index 72efa8f..aa072be 100644
--- a/net/net_jni_headers.target.linux-arm.mk
+++ b/net/net_jni_headers.target.linux-arm.mk
@@ -179,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -261,6 +262,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_jni_headers.target.linux-mips.mk b/net/net_jni_headers.target.linux-mips.mk
index 1fc9cf3..b3d4e33 100644
--- a/net/net_jni_headers.target.linux-mips.mk
+++ b/net/net_jni_headers.target.linux-mips.mk
@@ -178,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -259,6 +260,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_jni_headers.target.linux-x86.mk b/net/net_jni_headers.target.linux-x86.mk
index 2993d90..7341032 100644
--- a/net/net_jni_headers.target.linux-x86.mk
+++ b/net/net_jni_headers.target.linux-x86.mk
@@ -180,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -262,6 +263,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/net_jni_headers.target.linux-x86_64.mk b/net/net_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..8bf705f
--- /dev/null
+++ b/net/net_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,318 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_net_jni_headers_gyp
+LOCAL_MODULE_STEM := net_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_net_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/net/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['android/java/src/org/chromium/net/AndroidCertVerifyResult.java', 'android/java/src/org/chromium/net/AndroidKeyStore.java', 'android/java/src/org/chromium/net/AndroidNetworkLibrary.java', 'android/java/src/org/chromium/net/AndroidPrivateKey.java', 'android/java/src/org/chromium/net/GURLUtils.java', 'android/java/src/org/chromium/net/NetworkChangeNotifier.java', 'android/java/src/org/chromium/net/ProxyChangeListener.java', 'android/java/src/org/chromium/net/X509Util.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/net/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidCertVerifyResult.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidCertVerifyResult.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidKeyStore.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidKeyStore.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidNetworkLibrary.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/AndroidPrivateKey.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/AndroidPrivateKey.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/GURLUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/GURLUtils.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/NetworkChangeNotifier.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/NetworkChangeNotifier.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/ProxyChangeListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/ProxyChangeListener.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h
+
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h: $(LOCAL_PATH)/net/android/java/src/org/chromium/net/X509Util.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/net/jni; cd $(gyp_local_path)/net; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/net/X509Util.java --output_dir "$(gyp_shared_intermediate_dir)/net/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: net_net_jni_headers_gyp_rule_trigger
+net_net_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidCertVerifyResult_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidKeyStore_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidNetworkLibrary_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/AndroidPrivateKey_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/GURLUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/NetworkChangeNotifier_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/ProxyChangeListener_jni.h \
+	$(gyp_shared_intermediate_dir)/net/jni/X509Util_jni.h \
+	net_net_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: net_jni_headers
+net_jni_headers: net_net_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/net_resources.target.darwin-x86.mk b/net/net_resources.target.darwin-x86.mk
index 89ede6f..80db67d 100644
--- a/net/net_resources.target.darwin-x86.mk
+++ b/net/net_resources.target.darwin-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/net/grit/net_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/net/grit/net_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/net/base/net_resources.grd $(LOCAL_PATH)/net/base/dir_header.html $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from base/net_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/net; mkdir -p $(gyp_shared_intermediate_dir)/net/grit $(gyp_shared_intermediate_dir)/net; python ../tools/grit/grit.py -i base/net_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/net" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/net; mkdir -p $(gyp_shared_intermediate_dir)/net/grit $(gyp_shared_intermediate_dir)/net; python ../tools/grit/grit.py -i base/net_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/net" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/net/net_resources.pak: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
 $(gyp_shared_intermediate_dir)/net/net_resources.rc: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
diff --git a/net/net_resources.target.darwin-x86_64.mk b/net/net_resources.target.darwin-x86_64.mk
new file mode 100644
index 0000000..80db67d
--- /dev/null
+++ b/net/net_resources.target.darwin-x86_64.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_net_resources_gyp
+LOCAL_MODULE_STEM := net_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "net_resources":
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/net/base/net_resources.grd $(LOCAL_PATH)/net/base/dir_header.html $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from base/net_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/net; mkdir -p $(gyp_shared_intermediate_dir)/net/grit $(gyp_shared_intermediate_dir)/net; python ../tools/grit/grit.py -i base/net_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/net" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/net/net_resources.pak: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
+$(gyp_shared_intermediate_dir)/net/net_resources.rc: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/net/grit/net_resources.h \
+	$(gyp_shared_intermediate_dir)/net/net_resources.pak \
+	$(gyp_shared_intermediate_dir)/net/net_resources.rc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_resources_gyp
+
+# Alias gyp target name.
+.PHONY: net_resources
+net_resources: net_net_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/net_resources.target.linux-x86.mk b/net/net_resources.target.linux-x86.mk
index 89ede6f..80db67d 100644
--- a/net/net_resources.target.linux-x86.mk
+++ b/net/net_resources.target.linux-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/net/grit/net_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/net/grit/net_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/net/base/net_resources.grd $(LOCAL_PATH)/net/base/dir_header.html $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from base/net_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/net; mkdir -p $(gyp_shared_intermediate_dir)/net/grit $(gyp_shared_intermediate_dir)/net; python ../tools/grit/grit.py -i base/net_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/net" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/net; mkdir -p $(gyp_shared_intermediate_dir)/net/grit $(gyp_shared_intermediate_dir)/net; python ../tools/grit/grit.py -i base/net_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/net" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/net/net_resources.pak: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
 $(gyp_shared_intermediate_dir)/net/net_resources.rc: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
diff --git a/net/net_resources.target.linux-x86_64.mk b/net/net_resources.target.linux-x86_64.mk
new file mode 100644
index 0000000..80db67d
--- /dev/null
+++ b/net/net_resources.target.linux-x86_64.mk
@@ -0,0 +1,54 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_net_resources_gyp
+LOCAL_MODULE_STEM := net_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "net_resources":
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/net/grit/net_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/net/base/net_resources.grd $(LOCAL_PATH)/net/base/dir_header.html $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from base/net_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/net; mkdir -p $(gyp_shared_intermediate_dir)/net/grit $(gyp_shared_intermediate_dir)/net; python ../tools/grit/grit.py -i base/net_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/net" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/net/net_resources.pak: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
+$(gyp_shared_intermediate_dir)/net/net_resources.rc: $(gyp_shared_intermediate_dir)/net/grit/net_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/net/grit/net_resources.h \
+	$(gyp_shared_intermediate_dir)/net/net_resources.pak \
+	$(gyp_shared_intermediate_dir)/net/net_resources.rc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_net_resources_gyp
+
+# Alias gyp target name.
+.PHONY: net_resources
+net_resources: net_net_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/private_key_types_java.target.darwin-arm.mk b/net/private_key_types_java.target.darwin-arm.mk
index 047e446..96c213c 100644
--- a/net/private_key_types_java.target.darwin-arm.mk
+++ b/net/private_key_types_java.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/private_key_types_java.target.darwin-mips.mk b/net/private_key_types_java.target.darwin-mips.mk
index 7911a78..9358619 100644
--- a/net/private_key_types_java.target.darwin-mips.mk
+++ b/net/private_key_types_java.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/private_key_types_java.target.darwin-x86.mk b/net/private_key_types_java.target.darwin-x86.mk
index 50c0dff..e1cd167 100644
--- a/net/private_key_types_java.target.darwin-x86.mk
+++ b/net/private_key_types_java.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/private_key_types_java.target.darwin-x86_64.mk b/net/private_key_types_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..6059d01
--- /dev/null
+++ b/net/private_key_types_java.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_private_key_types_java_gyp
+LOCAL_MODULE_STEM := private_key_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_private_key_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'android/private_key_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/PrivateKeyType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: $(LOCAL_PATH)/net/android/java/PrivateKeyType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/android/private_key_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java" "--template=android/java/PrivateKeyType.template"
+
+.PHONY: net_private_key_types_java_gyp_rule_trigger
+net_private_key_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_private_key_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_private_key_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: private_key_types_java
+private_key_types_java: net_private_key_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/private_key_types_java.target.linux-arm.mk b/net/private_key_types_java.target.linux-arm.mk
index 047e446..96c213c 100644
--- a/net/private_key_types_java.target.linux-arm.mk
+++ b/net/private_key_types_java.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/private_key_types_java.target.linux-mips.mk b/net/private_key_types_java.target.linux-mips.mk
index 7911a78..9358619 100644
--- a/net/private_key_types_java.target.linux-mips.mk
+++ b/net/private_key_types_java.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/private_key_types_java.target.linux-x86.mk b/net/private_key_types_java.target.linux-x86.mk
index 50c0dff..e1cd167 100644
--- a/net/private_key_types_java.target.linux-x86.mk
+++ b/net/private_key_types_java.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/net/private_key_types_java.target.linux-x86_64.mk b/net/private_key_types_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..6059d01
--- /dev/null
+++ b/net/private_key_types_java.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := net_private_key_types_java_gyp
+LOCAL_MODULE_STEM := private_key_types_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "net_net_gyp_private_key_types_java_target_generate_java_constants":
+# "{'inputs': ['../build/android/gyp/util/build_utils.py', '../build/android/gyp/gcc_preprocess.py', 'android/private_key_type_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['android/java/PrivateKeyType.template'], 'action': ['python', '../build/android/gyp/gcc_preprocess.py', '--include-path=..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java: $(LOCAL_PATH)/net/android/java/PrivateKeyType.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/net/android/private_key_type_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/net; cd $(gyp_local_path)/net; python ../build/android/gyp/gcc_preprocess.py "--include-path=.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java" "--template=android/java/PrivateKeyType.template"
+
+.PHONY: net_private_key_types_java_gyp_rule_trigger
+net_private_key_types_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/net/PrivateKeyType.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	net_private_key_types_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: net_private_key_types_java_gyp
+
+# Alias gyp target name.
+.PHONY: private_key_types_java
+private_key_types_java: net_private_key_types_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/net/proxy/network_delegate_error_observer_unittest.cc b/net/proxy/network_delegate_error_observer_unittest.cc
index a893cba..1f6330f 100644
--- a/net/proxy/network_delegate_error_observer_unittest.cc
+++ b/net/proxy/network_delegate_error_observer_unittest.cc
@@ -41,7 +41,8 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers) OVERRIDE {
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE {
     return net::OK;
   }
   virtual void OnBeforeRedirect(URLRequest* request,
diff --git a/net/proxy/proxy_script_fetcher_impl_unittest.cc b/net/proxy/proxy_script_fetcher_impl_unittest.cc
index 2dbcfed..f050554 100644
--- a/net/proxy/proxy_script_fetcher_impl_unittest.cc
+++ b/net/proxy/proxy_script_fetcher_impl_unittest.cc
@@ -126,8 +126,8 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers)
-      OVERRIDE {
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE {
     return OK;
   }
 
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter.h b/net/quic/crypto/chacha20_poly1305_decrypter.h
index 638fb4a..b53d64a 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter.h
+++ b/net/quic/crypto/chacha20_poly1305_decrypter.h
@@ -11,7 +11,8 @@
 
 // A ChaCha20Poly1305Decrypter is a QuicDecrypter that implements the
 // AEAD_CHACHA20_POLY1305 algorithm specified in
-// draft-agl-tls-chacha20poly1305-04. Create an instance by calling
+// draft-agl-tls-chacha20poly1305-04, except that it truncates the Poly1305
+// authenticator to 12 bytes. Create an instance by calling
 // QuicDecrypter::Create(kCC12).
 //
 // It uses an authentication tag of 16 bytes (128 bits). There is no
@@ -19,7 +20,7 @@
 class NET_EXPORT_PRIVATE ChaCha20Poly1305Decrypter : public AeadBaseDecrypter {
  public:
   enum {
-    kAuthTagSize = 16,
+    kAuthTagSize = 12,
   };
 
   ChaCha20Poly1305Decrypter();
diff --git a/net/quic/crypto/chacha20_poly1305_decrypter_test.cc b/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
index 8482e01..1825187 100644
--- a/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
+++ b/net/quic/crypto/chacha20_poly1305_decrypter_test.cc
@@ -33,7 +33,7 @@
         "0a1007",
     "cd7cf67be39c794a",
     "87e229d4500845a079c0",
-    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6",
+    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475",  // "3896e1d6" truncated.
     "86d09974840bded2a5ca"
   },
   // Modify the ciphertext (ChaCha20 encryption output).
@@ -41,7 +41,7 @@
         "0a1007",
     "cd7cf67be39c794a",
     "87e229d4500845a079c0",
-    "f3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6",
+    "f3e446f7ede9a19b62a4677dabf4e3d24b876bb28475",  // "3896e1d6" truncated.
     NULL  // FAIL
   },
   // Modify the ciphertext (Poly1305 authenticator).
@@ -49,7 +49,7 @@
         "0a1007",
     "cd7cf67be39c794a",
     "87e229d4500845a079c0",
-    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d7",
+    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28476",  // "3896e1d6" truncated.
     NULL  // FAIL
   },
   // Modify the associated data.
@@ -57,7 +57,7 @@
         "0a1007",
     "dd7cf67be39c794a",
     "87e229d4500845a079c0",
-    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6",
+    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475",  // "3896e1d6" truncated.
     NULL  // FAIL
   },
   { NULL }
diff --git a/net/quic/crypto/chacha20_poly1305_encrypter.h b/net/quic/crypto/chacha20_poly1305_encrypter.h
index 29ec3ef..ed1102c 100644
--- a/net/quic/crypto/chacha20_poly1305_encrypter.h
+++ b/net/quic/crypto/chacha20_poly1305_encrypter.h
@@ -11,7 +11,8 @@
 
 // A ChaCha20Poly1305Encrypter is a QuicEncrypter that implements the
 // AEAD_CHACHA20_POLY1305 algorithm specified in
-// draft-agl-tls-chacha20poly1305-04. Create an instance by calling
+// draft-agl-tls-chacha20poly1305-04, except that it truncates the Poly1305
+// authenticator to 12 bytes. Create an instance by calling
 // QuicEncrypter::Create(kCC12).
 //
 // It uses an authentication tag of 16 bytes (128 bits). There is no
@@ -19,7 +20,7 @@
 class NET_EXPORT_PRIVATE ChaCha20Poly1305Encrypter : public AeadBaseEncrypter {
  public:
   enum {
-    kAuthTagSize = 16,
+    kAuthTagSize = 12,
   };
 
   ChaCha20Poly1305Encrypter();
diff --git a/net/quic/crypto/chacha20_poly1305_encrypter_test.cc b/net/quic/crypto/chacha20_poly1305_encrypter_test.cc
index 6fa4259..0273b27 100644
--- a/net/quic/crypto/chacha20_poly1305_encrypter_test.cc
+++ b/net/quic/crypto/chacha20_poly1305_encrypter_test.cc
@@ -29,7 +29,7 @@
     "86d09974840bded2a5ca",
     "cd7cf67be39c794a",
     "87e229d4500845a079c0",
-    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6"
+    "e3e446f7ede9a19b62a4677dabf4e3d24b876bb28475"  // "3896e1d6" truncated.
   },
   { NULL }
 };
@@ -92,16 +92,16 @@
 
 TEST(ChaCha20Poly1305EncrypterTest, GetMaxPlaintextSize) {
   ChaCha20Poly1305Encrypter encrypter;
-  EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1016));
-  EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(116));
-  EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(26));
+  EXPECT_EQ(1000u, encrypter.GetMaxPlaintextSize(1012));
+  EXPECT_EQ(100u, encrypter.GetMaxPlaintextSize(112));
+  EXPECT_EQ(10u, encrypter.GetMaxPlaintextSize(22));
 }
 
 TEST(ChaCha20Poly1305EncrypterTest, GetCiphertextSize) {
   ChaCha20Poly1305Encrypter encrypter;
-  EXPECT_EQ(1016u, encrypter.GetCiphertextSize(1000));
-  EXPECT_EQ(116u, encrypter.GetCiphertextSize(100));
-  EXPECT_EQ(26u, encrypter.GetCiphertextSize(10));
+  EXPECT_EQ(1012u, encrypter.GetCiphertextSize(1000));
+  EXPECT_EQ(112u, encrypter.GetCiphertextSize(100));
+  EXPECT_EQ(22u, encrypter.GetCiphertextSize(10));
 }
 
 }  // namespace test
diff --git a/net/quic/crypto/proof_test.cc b/net/quic/crypto/proof_test.cc
index df68dd0..377bc80 100644
--- a/net/quic/crypto/proof_test.cc
+++ b/net/quic/crypto/proof_test.cc
@@ -24,74 +24,7 @@
 
 namespace net {
 namespace test {
-
-TEST(ProofTest, Verify) {
-  // TODO(rtenneti): Enable testing of ProofVerifier.
-#if 0
-  scoped_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
-  scoped_ptr<ProofVerifier> verifier(
-      CryptoTestUtils::ProofVerifierForTesting());
-
-  const string server_config = "server config bytes";
-  const string hostname = "test.example.com";
-  const vector<string>* certs;
-  const vector<string>* first_certs;
-  string error_details, signature, first_signature;
-  CertVerifyResult cert_verify_result;
-
-  ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
-                               &first_certs, &first_signature));
-  ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
-                               &certs, &signature));
-
-  // Check that the proof source is caching correctly:
-  ASSERT_EQ(first_certs, certs);
-  ASSERT_EQ(signature, first_signature);
-
-  int rv;
-  TestCompletionCallback callback;
-  rv = verifier->VerifyProof(hostname, server_config, *certs, signature,
-                             &error_details, &cert_verify_result,
-                             callback.callback());
-  rv = callback.GetResult(rv);
-  ASSERT_EQ(OK, rv);
-  ASSERT_EQ("", error_details);
-  ASSERT_FALSE(IsCertStatusError(cert_verify_result.cert_status));
-
-  rv = verifier->VerifyProof("foo.com", server_config, *certs, signature,
-                             &error_details, &cert_verify_result,
-                             callback.callback());
-  rv = callback.GetResult(rv);
-  ASSERT_EQ(ERR_FAILED, rv);
-  ASSERT_NE("", error_details);
-
-  rv = verifier->VerifyProof(hostname, server_config.substr(1, string::npos),
-                             *certs, signature, &error_details,
-                             &cert_verify_result, callback.callback());
-  rv = callback.GetResult(rv);
-  ASSERT_EQ(ERR_FAILED, rv);
-  ASSERT_NE("", error_details);
-
-  const string corrupt_signature = "1" + signature;
-  rv = verifier->VerifyProof(hostname, server_config, *certs,
-                             corrupt_signature, &error_details,
-                             &cert_verify_result, callback.callback());
-  rv = callback.GetResult(rv);
-  ASSERT_EQ(ERR_FAILED, rv);
-  ASSERT_NE("", error_details);
-
-  vector<string> wrong_certs;
-  for (size_t i = 1; i < certs->size(); i++) {
-    wrong_certs.push_back((*certs)[i]);
-  }
-  rv = verifier->VerifyProof("foo.com", server_config, wrong_certs, signature,
-                             &error_details, &cert_verify_result,
-                             callback.callback());
-  rv = callback.GetResult(rv);
-  ASSERT_EQ(ERR_FAILED, rv);
-  ASSERT_NE("", error_details);
-#endif  // 0
-}
+namespace {
 
 // TestProofVerifierCallback is a simple callback for a ProofVerifier that
 // signals a TestCompletionCallback when called and stores the results from the
@@ -122,22 +55,24 @@
 
 // RunVerification runs |verifier->VerifyProof| and asserts that the result
 // matches |expected_ok|.
-static void RunVerification(ProofVerifier* verifier,
-                            const string& hostname,
-                            const string& server_config,
-                            const vector<string>& certs,
-                            const string& proof,
-                            bool expected_ok) {
+void RunVerification(ProofVerifier* verifier,
+                     const string& hostname,
+                     const string& server_config,
+                     const vector<string>& certs,
+                     const string& proof,
+                     bool expected_ok) {
   scoped_ptr<ProofVerifyDetails> details;
   TestCompletionCallback comp_callback;
   bool ok;
   string error_details;
+  scoped_ptr<ProofVerifyContext> verify_context(
+      CryptoTestUtils::ProofVerifyContextForTesting());
   TestProofVerifierCallback* callback =
       new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
 
   ProofVerifier::Status status = verifier->VerifyProof(
-      hostname, server_config, certs, proof, &error_details, &details,
-      callback);
+      hostname, server_config, certs, proof, verify_context.get(),
+      &error_details, &details, callback);
 
   switch (status) {
     case ProofVerifier::FAILURE:
@@ -155,10 +90,12 @@
   }
 }
 
-static string PEMCertFileToDER(const string& file_name) {
+// Reads the certificate named "quic_" + |file_name| in the test data directory.
+// The certificate must be PEM encoded. Returns the DER-encoded certificate.
+string LoadTestCert(const string& file_name) {
   base::FilePath certs_dir = GetTestCertsDirectory();
   scoped_refptr<X509Certificate> cert =
-      ImportCertFromFile(certs_dir, file_name);
+      ImportCertFromFile(certs_dir, "quic_" + file_name);
   CHECK_NE(static_cast<X509Certificate*>(NULL), cert);
 
   string der_bytes;
@@ -166,12 +103,58 @@
   return der_bytes;
 }
 
+}  // namespace
+
+// TODO(rtenneti): Enable testing of ProofVerifier.
+TEST(ProofTest, DISABLED_Verify) {
+  scoped_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
+  scoped_ptr<ProofVerifier> verifier(
+      CryptoTestUtils::ProofVerifierForTesting());
+
+  const string server_config = "server config bytes";
+  const string hostname = "test.example.com";
+  const vector<string>* certs;
+  const vector<string>* first_certs;
+  string error_details, signature, first_signature;
+
+  ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
+                               &first_certs, &first_signature));
+  ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
+                               &certs, &signature));
+
+  // Check that the proof source is caching correctly:
+  ASSERT_EQ(first_certs, certs);
+  ASSERT_EQ(signature, first_signature);
+
+  RunVerification(
+      verifier.get(), hostname, server_config, *certs, signature, true);
+
+  RunVerification(
+      verifier.get(), "foo.com", server_config, *certs, signature, false);
+
+  RunVerification(
+      verifier.get(), server_config.substr(1, string::npos), server_config,
+      *certs, signature, false);
+
+  const string corrupt_signature = "1" + signature;
+  RunVerification(
+      verifier.get(), hostname, server_config, *certs, corrupt_signature,
+      false);
+
+  vector<string> wrong_certs;
+  for (size_t i = 1; i < certs->size(); i++) {
+    wrong_certs.push_back((*certs)[i]);
+  }
+  RunVerification(
+      verifier.get(), "foo.com", server_config, wrong_certs, corrupt_signature,
+      false);
+}
+
 // A known answer test that allows us to test ProofVerifier without a working
 // ProofSource.
 TEST(ProofTest, VerifyRSAKnownAnswerTest) {
   // These sample signatures were generated by running the Proof.Verify test
   // and dumping the bytes of the |signature| output of ProofSource::GetProof().
-  // sLen = special value -2 used by OpenSSL.
   static const unsigned char signature_data_0[] = {
     0x31, 0xd5, 0xfb, 0x40, 0x30, 0x75, 0xd2, 0x7d, 0x61, 0xf9, 0xd7, 0x54,
     0x30, 0x06, 0xaf, 0x54, 0x0d, 0xb0, 0x0a, 0xda, 0x63, 0xca, 0x7e, 0x9e,
@@ -250,11 +233,10 @@
 
   const string server_config = "server config bytes";
   const string hostname = "test.example.com";
-  CertVerifyResult cert_verify_result;
 
   vector<string> certs(2);
-  certs[0] = PEMCertFileToDER("quic_test.example.com.crt");
-  certs[1] = PEMCertFileToDER("quic_intermediate.crt");
+  certs[0] = LoadTestCert("test.example.com.crt");
+  certs[1] = LoadTestCert("intermediate.crt");
 
   // Signatures are nondeterministic, so we test multiple signatures on the
   // same server_config.
@@ -333,11 +315,10 @@
 
   const string server_config = "server config bytes";
   const string hostname = "test.example.com";
-  CertVerifyResult cert_verify_result;
 
   vector<string> certs(2);
-  certs[0] = PEMCertFileToDER("quic_test_ecc.example.com.crt");
-  certs[1] = PEMCertFileToDER("quic_intermediate.crt");
+  certs[0] = LoadTestCert("test_ecc.example.com.crt");
+  certs[1] = LoadTestCert("intermediate.crt");
 
   // Signatures are nondeterministic, so we test multiple signatures on the
   // same server_config.
diff --git a/net/quic/crypto/proof_verifier.cc b/net/quic/crypto/proof_verifier.cc
deleted file mode 100644
index 4132a31..0000000
--- a/net/quic/crypto/proof_verifier.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/quic/crypto/proof_verifier.h"
-
-namespace net {
-
-ProofVerifierCallback::~ProofVerifierCallback() {}
-
-ProofVerifier::~ProofVerifier() {}
-
-}  // namespace net
diff --git a/net/quic/crypto/proof_verifier.h b/net/quic/crypto/proof_verifier.h
index 3b47776..0cbdb6a 100644
--- a/net/quic/crypto/proof_verifier.h
+++ b/net/quic/crypto/proof_verifier.h
@@ -21,11 +21,18 @@
   virtual ~ProofVerifyDetails() {}
 };
 
+// ProofVerifyContext is an abstract class that acts as a container for any
+// implementation specific context that a ProofVerifier needs.
+class NET_EXPORT_PRIVATE ProofVerifyContext {
+ public:
+  virtual ~ProofVerifyContext() {}
+};
+
 // ProofVerifierCallback provides a generic mechanism for a ProofVerifier to
 // call back after an asynchronous verification.
 class NET_EXPORT_PRIVATE ProofVerifierCallback {
  public:
-  virtual ~ProofVerifierCallback();
+  virtual ~ProofVerifierCallback() {}
 
   // Run is called on the original thread to mark the completion of an
   // asynchonous verification. If |ok| is true then the certificate is valid
@@ -51,7 +58,7 @@
     PENDING = 2,
   };
 
-  virtual ~ProofVerifier();
+  virtual ~ProofVerifier() {}
 
   // VerifyProof checks that |signature| is a valid signature of
   // |server_config| by the public key in the leaf certificate of |certs|, and
@@ -60,6 +67,10 @@
   // description of the problem. In either case it may set |*details|, which the
   // caller takes ownership of.
   //
+  // |context| specifies an implementation specific struct (which may be NULL
+  // for some implementations) that provides useful information for the
+  // verifier, e.g. logging handles.
+  //
   // This function may also return PENDING, in which case the ProofVerifier
   // will call back, on the original thread, via |callback| when complete.
   // In this case, the ProofVerifier will take ownership of |callback|.
@@ -70,6 +81,7 @@
                              const std::string& server_config,
                              const std::vector<std::string>& certs,
                              const std::string& signature,
+                             const ProofVerifyContext* context,
                              std::string* error_details,
                              scoped_ptr<ProofVerifyDetails>* details,
                              ProofVerifierCallback* callback) = 0;
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 8584aed..fdb6a0d 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -47,7 +47,7 @@
                      const std::vector<std::string>& certs,
                      const std::string& signature,
                      std::string* error_details,
-                     scoped_ptr<ProofVerifyDetails>* details,
+                     scoped_ptr<ProofVerifyDetails>* verify_details,
                      ProofVerifierCallback* callback);
 
  private:
@@ -104,10 +104,10 @@
     const vector<string>& certs,
     const string& signature,
     std::string* error_details,
-    scoped_ptr<ProofVerifyDetails>* details,
+    scoped_ptr<ProofVerifyDetails>* verify_details,
     ProofVerifierCallback* callback) {
   DCHECK(error_details);
-  DCHECK(details);
+  DCHECK(verify_details);
   DCHECK(callback);
 
   callback_.reset(callback);
@@ -125,7 +125,7 @@
     *error_details = "Failed to create certificate chain. Certs are empty.";
     DLOG(WARNING) << *error_details;
     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
-    details->reset(verify_details_.release());
+    verify_details->reset(verify_details_.release());
     return FAILURE;
   }
 
@@ -139,7 +139,7 @@
     *error_details = "Failed to create certificate chain";
     DLOG(WARNING) << *error_details;
     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
-    details->reset(verify_details_.release());
+    verify_details->reset(verify_details_.release());
     return FAILURE;
   }
 
@@ -149,7 +149,7 @@
     *error_details = "Failed to verify signature of server config";
     DLOG(WARNING) << *error_details;
     verify_details_->cert_verify_result.cert_status = CERT_STATUS_INVALID;
-    details->reset(verify_details_.release());
+    verify_details->reset(verify_details_.release());
     return FAILURE;
   }
 
@@ -158,13 +158,13 @@
   next_state_ = STATE_VERIFY_CERT;
   switch (DoLoop(OK)) {
     case OK:
-      details->reset(verify_details_.release());
+      verify_details->reset(verify_details_.release());
       return SUCCESS;
     case ERR_IO_PENDING:
       return PENDING;
     default:
       *error_details = error_details_;
-      details->reset(verify_details_.release());
+      verify_details->reset(verify_details_.release());
       return FAILURE;
   }
 }
@@ -310,11 +310,8 @@
   return true;
 }
 
-ProofVerifierChromium::ProofVerifierChromium(CertVerifier* cert_verifier,
-                                             const BoundNetLog& net_log)
-  : cert_verifier_(cert_verifier),
-    net_log_(net_log) {
-}
+ProofVerifierChromium::ProofVerifierChromium(CertVerifier* cert_verifier)
+    : cert_verifier_(cert_verifier) {}
 
 ProofVerifierChromium::~ProofVerifierChromium() {
   STLDeleteElements(&active_jobs_);
@@ -325,12 +322,19 @@
     const std::string& server_config,
     const std::vector<std::string>& certs,
     const std::string& signature,
+    const ProofVerifyContext* verify_context,
     std::string* error_details,
-    scoped_ptr<ProofVerifyDetails>* details,
+    scoped_ptr<ProofVerifyDetails>* verify_details,
     ProofVerifierCallback* callback) {
-  scoped_ptr<Job> job(new Job(this, cert_verifier_, net_log_));
+  if (!verify_context) {
+    *error_details = "Missing context";
+    return FAILURE;
+  }
+  const ProofVerifyContextChromium* chromium_context =
+      reinterpret_cast<const ProofVerifyContextChromium*>(verify_context);
+  scoped_ptr<Job> job(new Job(this, cert_verifier_, chromium_context->net_log));
   Status status = job->VerifyProof(hostname, server_config, certs, signature,
-                                   error_details, details, callback);
+                                   error_details, verify_details, callback);
   if (status == PENDING) {
     active_jobs_.insert(job.release());
   }
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index 7f695e6..ebf9a2c 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -15,6 +15,7 @@
 #include "net/base/net_export.h"
 #include "net/base/net_log.h"
 #include "net/cert/cert_verify_result.h"
+#include "net/cert/x509_certificate.h"
 #include "net/quic/crypto/proof_verifier.h"
 
 namespace net {
@@ -29,12 +30,21 @@
   CertVerifyResult cert_verify_result;
 };
 
+// ProofVerifyContextChromium is the implementation-specific information that a
+// ProofVerifierChromium needs in order to log correctly.
+struct ProofVerifyContextChromium : public ProofVerifyContext {
+ public:
+  explicit ProofVerifyContextChromium(const BoundNetLog& net_log)
+      : net_log(net_log) {}
+
+  BoundNetLog net_log;
+};
+
 // ProofVerifierChromium implements the QUIC ProofVerifier interface.  It is
 // capable of handling multiple simultaneous requests.
 class NET_EXPORT_PRIVATE ProofVerifierChromium : public ProofVerifier {
  public:
-  ProofVerifierChromium(CertVerifier* cert_verifier,
-                        const BoundNetLog& net_log);
+  explicit ProofVerifierChromium(CertVerifier* cert_verifier);
   virtual ~ProofVerifierChromium();
 
   // ProofVerifier interface
@@ -42,8 +52,9 @@
                              const std::string& server_config,
                              const std::vector<std::string>& certs,
                              const std::string& signature,
+                             const ProofVerifyContext* verify_context,
                              std::string* error_details,
-                             scoped_ptr<ProofVerifyDetails>* details,
+                             scoped_ptr<ProofVerifyDetails>* verify_details,
                              ProofVerifierCallback* callback) OVERRIDE;
 
  private:
@@ -58,8 +69,6 @@
   // Underlying verifier used to verify certificates.
   CertVerifier* const cert_verifier_;
 
-  BoundNetLog net_log_;
-
   DISALLOW_COPY_AND_ASSIGN(ProofVerifierChromium);
 };
 
diff --git a/net/quic/crypto/quic_crypto_client_config.cc b/net/quic/crypto/quic_crypto_client_config.cc
index 0fa78a4..8f34745 100644
--- a/net/quic/crypto/quic_crypto_client_config.cc
+++ b/net/quic/crypto/quic_crypto_client_config.cc
@@ -5,7 +5,9 @@
 #include "net/quic/crypto/quic_crypto_client_config.h"
 
 #include "base/stl_util.h"
+#include "base/strings/string_util.h"
 #include "net/quic/crypto/cert_compressor.h"
+#include "net/quic/crypto/chacha20_poly1305_encrypter.h"
 #include "net/quic/crypto/channel_id.h"
 #include "net/quic/crypto/common_cert_set.h"
 #include "net/quic/crypto/crypto_framer.h"
@@ -18,11 +20,8 @@
 #include "net/quic/quic_session_key.h"
 #include "net/quic/quic_utils.h"
 
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#endif
-
 using base::StringPiece;
+using std::find;
 using std::make_pair;
 using std::map;
 using std::string;
@@ -30,7 +29,8 @@
 
 namespace net {
 
-QuicCryptoClientConfig::QuicCryptoClientConfig() {}
+QuicCryptoClientConfig::QuicCryptoClientConfig()
+    : disable_ecdsa_(false) {}
 
 QuicCryptoClientConfig::~QuicCryptoClientConfig() {
   STLDeleteValues(&cached_states_);
@@ -249,26 +249,31 @@
   kexs[0] = kC255;
   kexs[1] = kP256;
 
-  // Authenticated encryption algorithms.
-  aead.resize(1);
-  aead[0] = kAESG;
+  // Authenticated encryption algorithms. Prefer ChaCha20 by default.
+  aead.clear();
+  if (ChaCha20Poly1305Encrypter::IsSupported()) {
+    aead.push_back(kCC12);
+  }
+  aead.push_back(kAESG);
+
+  disable_ecdsa_ = false;
 }
 
 QuicCryptoClientConfig::CachedState* QuicCryptoClientConfig::LookupOrCreate(
     const QuicSessionKey& server_key) {
-  map<QuicSessionKey, CachedState*>::const_iterator it =
-      cached_states_.find(server_key);
+  CachedStateMap::const_iterator it = cached_states_.find(server_key);
   if (it != cached_states_.end()) {
     return it->second;
   }
 
   CachedState* cached = new CachedState;
   cached_states_.insert(make_pair(server_key, cached));
+  PopulateFromCanonicalConfig(server_key, cached);
   return cached;
 }
 
 void QuicCryptoClientConfig::FillInchoateClientHello(
-    const string& server_hostname,
+    const QuicSessionKey& server_key,
     const QuicVersion preferred_version,
     const CachedState* cached,
     QuicCryptoNegotiatedParameters* out_params,
@@ -278,8 +283,8 @@
 
   // Server name indication. We only send SNI if it's a valid domain name, as
   // per the spec.
-  if (CryptoUtils::IsValidSNI(server_hostname)) {
-    out->SetStringPiece(kSNI, server_hostname);
+  if (CryptoUtils::IsValidSNI(server_key.host())) {
+    out->SetStringPiece(kSNI, server_key.host());
   }
   out->SetValue(kVER, QuicVersionToQuicTag(preferred_version));
 
@@ -287,15 +292,8 @@
     out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
   }
 
-  if (proof_verifier_.get()) {
-    // Don't request ECDSA proofs on platforms that do not support ECDSA
-    // certificates.
-    bool disableECDSA = false;
-#if defined(OS_WIN)
-    if (base::win::GetVersion() < base::win::VERSION_VISTA)
-      disableECDSA = true;
-#endif
-    if (disableECDSA) {
+  if (server_key.is_https()) {
+    if (disable_ecdsa_) {
       out->SetTaglist(kPDMD, kX59R, 0);
     } else {
       out->SetTaglist(kPDMD, kX509, 0);
@@ -324,7 +322,7 @@
 }
 
 QuicErrorCode QuicCryptoClientConfig::FillClientHello(
-    const string& server_hostname,
+    const QuicSessionKey& server_key,
     QuicConnectionId connection_id,
     const QuicVersion preferred_version,
     const CachedState* cached,
@@ -335,7 +333,7 @@
     string* error_details) const {
   DCHECK(error_details != NULL);
 
-  FillInchoateClientHello(server_hostname, preferred_version, cached,
+  FillInchoateClientHello(server_key, preferred_version, cached,
                           out_params, out);
 
   const CryptoHandshakeMessage* scfg = cached->GetServerConfig();
@@ -364,13 +362,18 @@
     return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
   }
 
+  // AEAD: the work loads on the client and server are symmetric. Since the
+  // client is more likely to be CPU-constrained, break the tie by favoring
+  // the client's preference.
+  // Key exchange: the client does more work than the server, so favor the
+  // client's preference.
   size_t key_exchange_index;
   if (!QuicUtils::FindMutualTag(
-          aead, their_aeads, num_their_aeads, QuicUtils::PEER_PRIORITY,
+          aead, their_aeads, num_their_aeads, QuicUtils::LOCAL_PRIORITY,
           &out_params->aead, NULL) ||
       !QuicUtils::FindMutualTag(
           kexs, their_key_exchanges, num_their_key_exchanges,
-          QuicUtils::PEER_PRIORITY, &out_params->key_exchange,
+          QuicUtils::LOCAL_PRIORITY, &out_params->key_exchange,
           &key_exchange_index)) {
     *error_details = "Unsupported AEAD or KEXS";
     return QUIC_CRYPTO_NO_SUPPORT;
@@ -455,7 +458,7 @@
     hkdf_input.append(cached->server_config());
 
     string key, signature;
-    if (!channel_id_signer_->Sign(server_hostname, hkdf_input,
+    if (!channel_id_signer_->Sign(server_key.host(), hkdf_input,
                                   &key, &signature)) {
       *error_details = "Channel ID signature failed";
       return QUIC_INVALID_CHANNEL_ID_SIGNATURE;
@@ -680,4 +683,60 @@
   cached->InitializeFrom(*canonical_cached);
 }
 
+void QuicCryptoClientConfig::AddCanonicalSuffix(const string& suffix) {
+  canoncial_suffixes_.push_back(suffix);
+}
+
+void QuicCryptoClientConfig::PreferAesGcm() {
+  DCHECK(!aead.empty());
+  if (aead.size() <= 1) {
+    return;
+  }
+  QuicTagVector::iterator pos = find(aead.begin(), aead.end(), kAESG);
+  if (pos != aead.end()) {
+    aead.erase(pos);
+    aead.insert(aead.begin(), kAESG);
+  }
+}
+
+void QuicCryptoClientConfig::DisableEcdsa() {
+  disable_ecdsa_ = true;
+}
+
+void QuicCryptoClientConfig::PopulateFromCanonicalConfig(
+    const QuicSessionKey& server_key,
+    CachedState* server_state) {
+  DCHECK(server_state->IsEmpty());
+  unsigned i = 0;
+  for (; i < canoncial_suffixes_.size(); ++i) {
+    if (EndsWith(server_key.host(), canoncial_suffixes_[i], false)) {
+      break;
+    }
+  }
+  if (i == canoncial_suffixes_.size())
+    return;
+
+  QuicSessionKey suffix_server_key(canoncial_suffixes_[i], server_key.port(),
+                                   server_key.is_https(),
+                                   server_key.privacy_mode());
+  if (!ContainsKey(canonical_server_map_, suffix_server_key)) {
+    // This is the first host we've seen which matches the suffix, so make it
+    // canonical.
+    canonical_server_map_[suffix_server_key] = server_key;
+    return;
+  }
+
+  const QuicSessionKey& canonical_server_key =
+      canonical_server_map_[suffix_server_key];
+  CachedState* canonical_state = cached_states_[canonical_server_key];
+  if (!canonical_state->proof_valid()) {
+    return;
+  }
+
+  // Update canonical version to point at the "most recent" entry.
+  canonical_server_map_[suffix_server_key] = server_key;
+
+  server_state->InitializeFrom(*canonical_state);
+}
+
 }  // namespace net
diff --git a/net/quic/crypto/quic_crypto_client_config.h b/net/quic/crypto/quic_crypto_client_config.h
index f2e8649..d6ce2e4 100644
--- a/net/quic/crypto/quic_crypto_client_config.h
+++ b/net/quic/crypto/quic_crypto_client_config.h
@@ -143,7 +143,7 @@
   // |out_params->cached_certs|. |preferred_version| is the version of the
   // QUIC protocol that this client chose to use initially. This allows the
   // server to detect downgrade attacks.
-  void FillInchoateClientHello(const std::string& server_hostname,
+  void FillInchoateClientHello(const QuicSessionKey& server_key,
                                const QuicVersion preferred_version,
                                const CachedState* cached,
                                QuicCryptoNegotiatedParameters* out_params,
@@ -151,7 +151,7 @@
 
   // FillClientHello sets |out| to be a CHLO message based on the configuration
   // of this object. This object must have cached enough information about
-  // |server_hostname| in order to perform a handshake. This can be checked
+  // the server's hostname in order to perform a handshake. This can be checked
   // with the |IsComplete| member of |CachedState|.
   //
   // |clock| and |rand| are used to generate the nonce and |out_params| is
@@ -159,7 +159,7 @@
   // accept. |preferred_version| is the version of the QUIC protocol that this
   // client chose to use initially. This allows the server to detect downgrade
   // attacks.
-  QuicErrorCode FillClientHello(const std::string& server_hostname,
+  QuicErrorCode FillClientHello(const QuicSessionKey& server_key,
                                 QuicConnectionId connection_id,
                                 const QuicVersion preferred_version,
                                 const CachedState* cached,
@@ -218,14 +218,51 @@
                       const QuicSessionKey& canonical_server_key,
                       QuicCryptoClientConfig* canonical_crypto_config);
 
+  // Adds |suffix| as a domain suffix for which the server's crypto config
+  // is expected to be shared among servers with the domain suffix. If a server
+  // matches this suffix, then the server config from another server with the
+  // suffix will be used to initialize the cached state for this server.
+  void AddCanonicalSuffix(const std::string& suffix);
+
+  // Prefers AES-GCM (kAESG) over other AEAD algorithms. Call this method if
+  // the CPU has hardware acceleration for AES-GCM. This method can only be
+  // called after SetDefaults().
+  void PreferAesGcm();
+
+  // Disables the use of ECDSA for proof verification.
+  // Call this method on platforms that do not support ECDSA.
+  // TODO(rch): remove this method when we drop support for Windows XP.
+  void DisableEcdsa();
+
  private:
+  typedef std::map<QuicSessionKey, CachedState*> CachedStateMap;
+
+  // If the suffix of the hostname in |server_key| is in |canoncial_suffixes_|,
+  // then populate |cached| with the canonical cached state from
+  // |canonical_server_map_| for that suffix.
+  void PopulateFromCanonicalConfig(const QuicSessionKey& server_key,
+                                   CachedState* cached);
+
   // cached_states_ maps from the server_key to the cached information about
   // that server.
-  std::map<QuicSessionKey, CachedState*> cached_states_;
+  CachedStateMap cached_states_;
+
+  // Contains a map of servers which could share the same server config. Map
+  // from a canonical host suffix/port/scheme to a representative server with
+  // the canonical suffix, which has a plausible set of initial certificates
+  // (or at least server public key).
+  std::map<QuicSessionKey, QuicSessionKey> canonical_server_map_;
+
+  // Contains list of suffixes (for exmaple ".c.youtube.com",
+  // ".googlevideo.com") of canoncial hostnames.
+  std::vector<std::string> canoncial_suffixes_;
 
   scoped_ptr<ProofVerifier> proof_verifier_;
   scoped_ptr<ChannelIDSigner> channel_id_signer_;
 
+  // True if ECDSA should be disabled.
+  bool disable_ecdsa_;
+
   DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientConfig);
 };
 
diff --git a/net/quic/crypto/quic_crypto_client_config_test.cc b/net/quic/crypto/quic_crypto_client_config_test.cc
index d151e0c..b74a37a 100644
--- a/net/quic/crypto/quic_crypto_client_config_test.cc
+++ b/net/quic/crypto/quic_crypto_client_config_test.cc
@@ -56,7 +56,8 @@
   QuicCryptoClientConfig config;
   QuicCryptoNegotiatedParameters params;
   CryptoHandshakeMessage msg;
-  config.FillInchoateClientHello("www.google.com", QuicVersionMax(), &state,
+  QuicSessionKey server_key("www.google.com", 80, false, kPrivacyModeDisabled);
+  config.FillInchoateClientHello(server_key, QuicVersionMax(), &state,
                                  &params, &msg);
 
   QuicTag cver;
@@ -64,6 +65,44 @@
   EXPECT_EQ(QuicVersionToQuicTag(QuicVersionMax()), cver);
 }
 
+TEST(QuicCryptoClientConfigTest, PreferAesGcm) {
+  QuicCryptoClientConfig config;
+  config.SetDefaults();
+  if (config.aead.size() > 1)
+    EXPECT_NE(kAESG, config.aead[0]);
+  config.PreferAesGcm();
+  EXPECT_EQ(kAESG, config.aead[0]);
+}
+
+TEST(QuicCryptoClientConfigTest, InchoateChloSecure) {
+  QuicCryptoClientConfig::CachedState state;
+  QuicCryptoClientConfig config;
+  QuicCryptoNegotiatedParameters params;
+  CryptoHandshakeMessage msg;
+  QuicSessionKey server_key("www.google.com", 443, true, kPrivacyModeDisabled);
+  config.FillInchoateClientHello(server_key, QuicVersionMax(), &state,
+                                 &params, &msg);
+
+  QuicTag pdmd;
+  EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
+  EXPECT_EQ(kX509, pdmd);
+}
+
+TEST(QuicCryptoClientConfigTest, InchoateChloSecureNoEcdsa) {
+  QuicCryptoClientConfig::CachedState state;
+  QuicCryptoClientConfig config;
+  config.DisableEcdsa();
+  QuicCryptoNegotiatedParameters params;
+  CryptoHandshakeMessage msg;
+  QuicSessionKey server_key("www.google.com", 443, true, kPrivacyModeDisabled);
+  config.FillInchoateClientHello(server_key, QuicVersionMax(), &state,
+                                 &params, &msg);
+
+  QuicTag pdmd;
+  EXPECT_EQ(QUIC_NO_ERROR, msg.GetUint32(kPDMD, &pdmd));
+  EXPECT_EQ(kX59R, pdmd);
+}
+
 TEST(QuicCryptoClientConfigTest, ProcessServerDowngradeAttack) {
   QuicVersionVector supported_versions = QuicSupportedVersions();
   if (supported_versions.size() == 1) {
@@ -91,14 +130,15 @@
 
 TEST(QuicCryptoClientConfigTest, InitializeFrom) {
   QuicCryptoClientConfig config;
-  QuicSessionKey canonical_key1("www.google.com", 80, false);
+  QuicSessionKey canonical_key1("www.google.com", 80, false,
+                                kPrivacyModeDisabled);
   QuicCryptoClientConfig::CachedState* state =
       config.LookupOrCreate(canonical_key1);
   // TODO(rch): Populate other fields of |state|.
   state->set_source_address_token("TOKEN");
   state->SetProofValid();
 
-  QuicSessionKey other_key("mail.google.com", 80, false);
+  QuicSessionKey other_key("mail.google.com", 80, false, kPrivacyModeDisabled);
   config.InitializeFrom(other_key, canonical_key1, &config);
   QuicCryptoClientConfig::CachedState* other = config.LookupOrCreate(other_key);
 
diff --git a/net/quic/crypto/quic_crypto_server_config.cc b/net/quic/crypto/quic_crypto_server_config.cc
index 52e338b..9d60c5f 100644
--- a/net/quic/crypto/quic_crypto_server_config.cc
+++ b/net/quic/crypto/quic_crypto_server_config.cc
@@ -15,6 +15,7 @@
 #include "net/quic/crypto/aes_128_gcm_12_decrypter.h"
 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
 #include "net/quic/crypto/cert_compressor.h"
+#include "net/quic/crypto/chacha20_poly1305_encrypter.h"
 #include "net/quic/crypto/channel_id.h"
 #include "net/quic/crypto/crypto_framer.h"
 #include "net/quic/crypto/crypto_server_config_protobuf.h"
@@ -241,7 +242,11 @@
   } else {
     msg.SetTaglist(kKEXS, kC255, 0);
   }
-  msg.SetTaglist(kAEAD, kAESG, 0);
+  if (ChaCha20Poly1305Encrypter::IsSupported()) {
+    msg.SetTaglist(kAEAD, kAESG, kCC12, 0);
+  } else {
+    msg.SetTaglist(kAEAD, kAESG, 0);
+  }
   msg.SetStringPiece(kPUBS, encoded_public_values);
 
   if (options.expiry_time.IsZero()) {
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index 865c9b0..7dd9135 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -28,6 +28,34 @@
 
 namespace {
 
+// Histograms for tracking down the crashes from http://crbug.com/354669
+// Note: these values must be kept in sync with the corresponding values in:
+// tools/metrics/histograms/histograms.xml
+enum Location {
+  DESTRUCTOR = 0,
+  ADD_OBSERVER = 1,
+  TRY_CREATE_STREAM = 2,
+  CREATE_OUTGOING_RELIABLE_STREAM = 3,
+  NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER = 4,
+  NOTIFY_FACTORY_OF_SESSION_CLOSED = 5,
+  NUM_LOCATIONS = 6,
+};
+
+void RecordUnexpectedOpenStreams(Location location) {
+  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.UnexpectedOpenStreams", location,
+                            NUM_LOCATIONS);
+}
+
+void RecordUnexpectedObservers(Location location) {
+  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.UnexpectedObservers", location,
+                            NUM_LOCATIONS);
+}
+
+void RecordUnexpectedNotGoingAway(Location location) {
+  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.UnexpectedNotGoingAway", location,
+                            NUM_LOCATIONS);
+}
+
 // Note: these values must be kept in sync with the corresponding values in:
 // tools/metrics/histograms/histograms.xml
 enum HandshakeState {
@@ -95,7 +123,7 @@
     const QuicConfig& config,
     QuicCryptoClientConfig* crypto_config,
     NetLog* net_log)
-    : QuicSession(connection, config),
+    : QuicClientSessionBase(connection, config),
       require_confirmation_(false),
       stream_factory_(stream_factory),
       socket_(socket.Pass()),
@@ -107,12 +135,15 @@
       net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_QUIC_SESSION)),
       logger_(net_log_),
       num_packets_read_(0),
+      going_away_(false),
       weak_factory_(this) {
   crypto_stream_.reset(
       crypto_client_stream_factory ?
           crypto_client_stream_factory->CreateQuicCryptoClientStream(
               server_key, this, crypto_config) :
-          new QuicCryptoClientStream(server_key, this, this, crypto_config));
+          new QuicCryptoClientStream(server_key, this,
+                                     new ProofVerifyContextChromium(net_log_),
+                                     crypto_config));
 
   connection->set_debug_visitor(&logger_);
   // TODO(rch): pass in full host port proxy pair
@@ -122,6 +153,13 @@
 }
 
 QuicClientSession::~QuicClientSession() {
+  if (!streams()->empty())
+    RecordUnexpectedOpenStreams(DESTRUCTOR);
+  if (!observers_.empty())
+    RecordUnexpectedObservers(DESTRUCTOR);
+  if (!going_away_)
+    RecordUnexpectedNotGoingAway(DESTRUCTOR);
+
   // The session must be closed before it is destroyed.
   DCHECK(streams()->empty());
   CloseAllStreams(ERR_UNEXPECTED);
@@ -200,6 +238,9 @@
 }
 
 void QuicClientSession::AddObserver(Observer* observer) {
+  if (going_away_)
+    RecordUnexpectedObservers(ADD_OBSERVER);
+
   DCHECK(!ContainsKey(observers_, observer));
   observers_.insert(observer);
 }
@@ -226,6 +267,11 @@
     return ERR_CONNECTION_CLOSED;
   }
 
+  if (going_away_) {
+    RecordUnexpectedOpenStreams(TRY_CREATE_STREAM);
+    return ERR_CONNECTION_CLOSED;
+  }
+
   if (GetNumOpenStreams() < get_max_open_streams()) {
     *stream = CreateOutgoingReliableStreamImpl();
     return OK;
@@ -260,7 +306,10 @@
                << "Already received goaway.";
     return NULL;
   }
-
+  if (going_away_) {
+    RecordUnexpectedOpenStreams(CREATE_OUTGOING_RELIABLE_STREAM);
+    return NULL;
+  }
   return CreateOutgoingReliableStreamImpl();
 }
 
@@ -376,6 +425,7 @@
       !stream_requests_.empty() &&
       crypto_stream_->encryption_established() &&
       !goaway_received() &&
+      !going_away_ &&
       connection()->connected()) {
     StreamRequest* request = stream_requests_.front();
     stream_requests_.pop_front();
@@ -616,11 +666,19 @@
 }
 
 void QuicClientSession::NotifyFactoryOfSessionGoingAway() {
+  going_away_ = true;
   if (stream_factory_)
     stream_factory_->OnSessionGoingAway(this);
 }
 
 void QuicClientSession::NotifyFactoryOfSessionClosedLater() {
+  if (!streams()->empty())
+    RecordUnexpectedOpenStreams(NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER);
+
+  if (!going_away_)
+    RecordUnexpectedNotGoingAway(NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER);
+
+  going_away_ = true;
   DCHECK_EQ(0u, GetNumOpenStreams());
   DCHECK(!connection()->connected());
   base::MessageLoop::current()->PostTask(
@@ -630,6 +688,13 @@
 }
 
 void QuicClientSession::NotifyFactoryOfSessionClosed() {
+  if (!streams()->empty())
+    RecordUnexpectedOpenStreams(NOTIFY_FACTORY_OF_SESSION_CLOSED);
+
+  if (!going_away_)
+    RecordUnexpectedNotGoingAway(NOTIFY_FACTORY_OF_SESSION_CLOSED);
+
+  going_away_ = true;
   DCHECK_EQ(0u, GetNumOpenStreams());
   // Will delete |this|.
   if (stream_factory_)
diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h
index f9d3b7f..801ad07 100644
--- a/net/quic/quic_client_session.h
+++ b/net/quic/quic_client_session.h
@@ -17,11 +17,11 @@
 #include "base/memory/scoped_ptr.h"
 #include "net/base/completion_callback.h"
 #include "net/proxy/proxy_server.h"
+#include "net/quic/quic_client_session_base.h"
 #include "net/quic/quic_connection_logger.h"
 #include "net/quic/quic_crypto_client_stream.h"
 #include "net/quic/quic_protocol.h"
 #include "net/quic/quic_reliable_client_stream.h"
-#include "net/quic/quic_session.h"
 
 namespace net {
 
@@ -39,9 +39,7 @@
 class QuicClientSessionPeer;
 }  // namespace test
 
-class NET_EXPORT_PRIVATE QuicClientSession :
-      public QuicSession,
-      public QuicCryptoClientStream::Visitor {
+class NET_EXPORT_PRIVATE QuicClientSession : public QuicClientSessionBase {
  public:
   // An interface for observing events on a session.
   class NET_EXPORT_PRIVATE Observer {
@@ -136,7 +134,7 @@
       const CryptoHandshakeMessage& message) OVERRIDE;
   virtual bool GetSSLInfo(SSLInfo* ssl_info) const OVERRIDE;
 
-  // QuicCryptoClientStream::Visitor methods:
+  // QuicClientSessionBase methods:
   virtual void OnProofValid(
       const QuicCryptoClientConfig::CachedState& cached) OVERRIDE;
   virtual void OnProofVerifyDetailsAvailable(
@@ -232,6 +230,9 @@
   QuicConnectionLogger logger_;
   // Number of packets read in the current read loop.
   size_t num_packets_read_;
+  // True when the session is going away, and streams may no longer be created
+  // on this session. Existing stream will continue to be processed.
+  bool going_away_;
   base::WeakPtrFactory<QuicClientSession> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(QuicClientSession);
diff --git a/net/quic/quic_client_session_base.cc b/net/quic/quic_client_session_base.cc
new file mode 100644
index 0000000..b9cbaff
--- /dev/null
+++ b/net/quic/quic_client_session_base.cc
@@ -0,0 +1,15 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quic/quic_client_session_base.h"
+
+namespace net {
+
+QuicClientSessionBase::QuicClientSessionBase(QuicConnection* connection,
+                                             const QuicConfig& config)
+    : QuicSession(connection, config) {}
+
+QuicClientSessionBase::~QuicClientSessionBase() {}
+
+}  // namespace net
diff --git a/net/quic/quic_client_session_base.h b/net/quic/quic_client_session_base.h
new file mode 100644
index 0000000..eab5d08
--- /dev/null
+++ b/net/quic/quic_client_session_base.h
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
+#define NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
+
+#include "net/quic/quic_crypto_client_stream.h"
+#include "net/quic/quic_session.h"
+
+namespace net {
+
+// Base class for all client-specific QuicSession subclasses.
+class NET_EXPORT_PRIVATE QuicClientSessionBase : public QuicSession {
+ public:
+  QuicClientSessionBase(QuicConnection* connection,
+                        const QuicConfig& config);
+
+  virtual ~QuicClientSessionBase();
+
+  // Called when the proof in |cached| is marked valid.  If this is a secure
+  // QUIC session, then this will happen only after the proof verifier
+  // completes.  If this is an insecure QUIC connection, this will happen
+  // as soon as a valid config is discovered (either from the cache or
+  // from the server).
+  virtual void OnProofValid(
+      const QuicCryptoClientConfig::CachedState& cached) = 0;
+
+  // Called when proof verification details become available, either because
+  // proof verification is complete, or when cached details are used. This
+  // will only be called for secure QUIC connections.
+  virtual void OnProofVerifyDetailsAvailable(
+      const ProofVerifyDetails& verify_details) = 0;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(QuicClientSessionBase);
+};
+
+}  // namespace net
+
+#endif  // NET_QUIC_QUIC_CLIENT_SESSION_BASE_H_
diff --git a/net/quic/quic_client_session_test.cc b/net/quic/quic_client_session_test.cc
index 87e3381..3c8d933 100644
--- a/net/quic/quic_client_session_test.cc
+++ b/net/quic/quic_client_session_test.cc
@@ -70,7 +70,8 @@
             new PacketSavingConnection(false, SupportedVersions(GetParam()))),
         session_(connection_, GetSocket().Pass(), writer_.Pass(), NULL, NULL,
                  make_scoped_ptr((QuicServerInfo*)NULL),
-                 QuicSessionKey(kServerHostname, kServerPort, false),
+                 QuicSessionKey(kServerHostname, kServerPort, false,
+                                kPrivacyModeDisabled),
                  DefaultQuicConfig(), &crypto_config_, &net_log_) {
     session_.config()->SetDefaults();
     crypto_config_.SetDefaults();
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index 8c574fe..d71a097 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -8,8 +8,8 @@
 #include "net/quic/crypto/crypto_utils.h"
 #include "net/quic/crypto/null_encrypter.h"
 #include "net/quic/crypto/proof_verifier.h"
+#include "net/quic/quic_client_session_base.h"
 #include "net/quic/quic_protocol.h"
-#include "net/quic/quic_session.h"
 
 namespace net {
 
@@ -44,17 +44,17 @@
 
 QuicCryptoClientStream::QuicCryptoClientStream(
     const QuicSessionKey& server_key,
-    QuicSession* session,
-    Visitor* visitor,
+    QuicClientSessionBase* session,
+    ProofVerifyContext* verify_context,
     QuicCryptoClientConfig* crypto_config)
     : QuicCryptoStream(session),
-      visitor_(visitor),
       next_state_(STATE_IDLE),
       num_client_hellos_(0),
       crypto_config_(crypto_config),
       server_key_(server_key),
       generation_counter_(0),
-      proof_verify_callback_(NULL) {
+      proof_verify_callback_(NULL),
+      verify_context_(verify_context) {
 }
 
 QuicCryptoClientStream::~QuicCryptoClientStream() {
@@ -105,7 +105,8 @@
     switch (state) {
       case STATE_INITIALIZE: {
         if (!cached->IsEmpty() && !cached->signature().empty() &&
-            crypto_config_->proof_verifier()) {
+            server_key_.is_https()) {
+          DCHECK(crypto_config_->proof_verifier());
           // If the cached state needs to be verified, do it now.
           next_state_ = STATE_VERIFY_PROOF;
         } else {
@@ -124,7 +125,7 @@
 
         if (!cached->IsComplete(session()->connection()->clock()->WallNow())) {
           crypto_config_->FillInchoateClientHello(
-              server_key_.host(),
+              server_key_,
               session()->connection()->supported_versions().front(),
               cached, &crypto_negotiated_params_, &out);
           // Pad the inchoate client hello to fill up a packet.
@@ -150,7 +151,7 @@
         }
         session()->config()->ToHandshakeMessage(&out);
         error = crypto_config_->FillClientHello(
-            server_key_.host(),
+            server_key_,
             session()->connection()->connection_id(),
             session()->connection()->supported_versions().front(),
             cached,
@@ -166,8 +167,8 @@
           CloseConnectionWithDetails(error, error_details);
           return;
         }
-        if (visitor_ && cached->proof_verify_details()) {
-          visitor_->OnProofVerifyDetailsAvailable(
+        if (cached->proof_verify_details()) {
+          client_session()->OnProofVerifyDetailsAvailable(
               *cached->proof_verify_details());
         }
         next_state_ = STATE_RECV_SHLO;
@@ -212,10 +213,9 @@
           return;
         }
         if (!cached->proof_valid()) {
-          ProofVerifier* verifier = crypto_config_->proof_verifier();
-          if (!verifier) {
-            // If no verifier is set then we don't check the certificates.
-            SetProofValid(cached);
+          if (!server_key_.is_https()) {
+            // We don't check the certificates for insecure QUIC connections.
+            SetCachedProofValid(cached);
           } else if (!cached->signature().empty()) {
             next_state_ = STATE_VERIFY_PROOF;
             break;
@@ -239,6 +239,7 @@
             cached->server_config(),
             cached->certs(),
             cached->signature(),
+            verify_context_.get(),
             &verify_error_details_,
             &verify_details_,
             proof_verify_callback);
@@ -258,10 +259,7 @@
       }
       case STATE_VERIFY_PROOF_COMPLETE:
         if (!verify_ok_) {
-          if (visitor_) {
-            visitor_->OnProofVerifyDetailsAvailable(
-                *cached->proof_verify_details());
-          }
+          client_session()->OnProofVerifyDetailsAvailable(*verify_details_);
           CloseConnectionWithDetails(
               QUIC_PROOF_INVALID, "Proof invalid: " + verify_error_details_);
           return;
@@ -271,7 +269,7 @@
         if (generation_counter_ != cached->generation_counter()) {
           next_state_ = STATE_VERIFY_PROOF;
         } else {
-          SetProofValid(cached);
+          SetCachedProofValid(cached);
           cached->SetProofVerifyDetails(verify_details_.release());
           next_state_ = STATE_SEND_CHLO;
         }
@@ -349,12 +347,14 @@
   }
 }
 
-void QuicCryptoClientStream::SetProofValid(
+void QuicCryptoClientStream::SetCachedProofValid(
     QuicCryptoClientConfig::CachedState* cached) {
   cached->SetProofValid();
-  if (visitor_) {
-    visitor_->OnProofValid(*cached);
-  }
+  client_session()->OnProofValid(*cached);
+}
+
+QuicClientSessionBase* QuicCryptoClientStream::client_session() {
+  return reinterpret_cast<QuicClientSessionBase*>(session());
 }
 
 }  // namespace net
diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h
index 8e28360..aef96cc 100644
--- a/net/quic/quic_crypto_client_stream.h
+++ b/net/quic/quic_crypto_client_stream.h
@@ -15,7 +15,7 @@
 
 namespace net {
 
-class QuicSession;
+class QuicClientSessionBase;
 
 namespace test {
 class CryptoTestUtils;
@@ -23,28 +23,9 @@
 
 class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
  public:
-  class NET_EXPORT_PRIVATE Visitor {
-   public:
-    ~Visitor() {}
-
-    // Called when the proof in |cached| is marked valid.  If this is a secure
-    // QUIC session, then this will happen only after the proof verifier
-    // completes.  If this is an insecure QUIC connection, this will happen
-    // as soon as a valid config is discovered (either from the cache or
-    // from the server).
-    virtual void OnProofValid(
-        const QuicCryptoClientConfig::CachedState& cached) = 0;
-
-    // Called when proof verification details become available, either because
-    // proof verification is complete, or when cached details are used. This
-    // will only be called for secure QUIC connections.
-    virtual void OnProofVerifyDetailsAvailable(
-        const ProofVerifyDetails& verify_details) = 0;
-  };
-
   QuicCryptoClientStream(const QuicSessionKey& server_key,
-                         QuicSession* session,
-                         Visitor* visitor,
+                         QuicClientSessionBase* session,
+                         ProofVerifyContext* verify_context,
                          QuicCryptoClientConfig* crypto_config);
   virtual ~QuicCryptoClientStream();
 
@@ -62,8 +43,6 @@
   // than the number of round-trips needed for the handshake.
   int num_sent_client_hellos() const;
 
-  Visitor* visitor() { return visitor_; }
-
  private:
   // ProofVerifierCallbackImpl is passed as the callback method to VerifyProof.
   // The ProofVerifier calls this class with the result of proof verification
@@ -103,11 +82,11 @@
   // |in| may be NULL if the call did not result from a received message.
   void DoHandshakeLoop(const CryptoHandshakeMessage* in);
 
-  // Called to set the proof of |cache| valid.  Also invokes the visitor's
+  // Called to set the proof of |cached| valid.  Also invokes the session's
   // OnProofValid() method.
-  void SetProofValid(QuicCryptoClientConfig::CachedState* cached);
+  void SetCachedProofValid(QuicCryptoClientConfig::CachedState* cached);
 
-  Visitor* visitor_;
+  QuicClientSessionBase* client_session();
 
   State next_state_;
   // num_client_hellos_ contains the number of client hello messages that this
@@ -134,6 +113,7 @@
   bool verify_ok_;
   string verify_error_details_;
   scoped_ptr<ProofVerifyDetails> verify_details_;
+  scoped_ptr<ProofVerifyContext> verify_context_;
 
   DISALLOW_COPY_AND_ASSIGN(QuicCryptoClientStream);
 };
diff --git a/net/quic/quic_crypto_client_stream_test.cc b/net/quic/quic_crypto_client_stream_test.cc
index 1b64c9c..a69f126 100644
--- a/net/quic/quic_crypto_client_stream_test.cc
+++ b/net/quic/quic_crypto_client_stream_test.cc
@@ -27,10 +27,10 @@
  public:
   QuicCryptoClientStreamTest()
       : connection_(new PacketSavingConnection(false)),
-        session_(new TestSession(connection_, DefaultQuicConfig())),
-        server_key_(kServerHostname, kServerPort, false),
-        stream_(new QuicCryptoClientStream(server_key_, session_.get(), NULL,
-                                           &crypto_config_)) {
+        session_(new TestClientSession(connection_, DefaultQuicConfig())),
+        server_key_(kServerHostname, kServerPort, false, kPrivacyModeDisabled),
+        stream_(new QuicCryptoClientStream(
+            server_key_, session_.get(), NULL, &crypto_config_)) {
     session_->SetCryptoStream(stream_.get());
     session_->config()->SetDefaults();
     crypto_config_.SetDefaults();
@@ -47,7 +47,7 @@
   }
 
   PacketSavingConnection* connection_;
-  scoped_ptr<TestSession> session_;
+  scoped_ptr<TestClientSession> session_;
   QuicSessionKey server_key_;
   scoped_ptr<QuicCryptoClientStream> stream_;
   CryptoHandshakeMessage message_;
@@ -101,12 +101,12 @@
 
   const QuicCryptoNegotiatedParameters& crypto_params(
       stream_->crypto_negotiated_params());
-  EXPECT_EQ(kAESG, crypto_params.aead);
-  EXPECT_EQ(kC255, crypto_params.key_exchange);
+  EXPECT_EQ(crypto_config_.aead[0], crypto_params.aead);
+  EXPECT_EQ(crypto_config_.kexs[0], crypto_params.key_exchange);
 }
 
 TEST_F(QuicCryptoClientStreamTest, InvalidHostname) {
-  QuicSessionKey server_key("invalid", 80, false);
+  QuicSessionKey server_key("invalid", 80, false, kPrivacyModeDisabled);
   stream_.reset(new QuicCryptoClientStream(server_key, session_.get(), NULL,
                                            &crypto_config_));
   session_->SetCryptoStream(stream_.get());
@@ -121,7 +121,7 @@
   CompleteCryptoHandshake();
 
   connection_ = new PacketSavingConnection(true);
-  session_.reset(new TestSession(connection_, DefaultQuicConfig()));
+  session_.reset(new TestClientSession(connection_, DefaultQuicConfig()));
   stream_.reset(new QuicCryptoClientStream(server_key_, session_.get(), NULL,
                                            &crypto_config_));
 
diff --git a/net/quic/quic_crypto_server_stream_test.cc b/net/quic/quic_crypto_server_stream_test.cc
index 4135187..d0c87e8 100644
--- a/net/quic/quic_crypto_server_stream_test.cc
+++ b/net/quic/quic_crypto_server_stream_test.cc
@@ -105,7 +105,7 @@
 
  protected:
   PacketSavingConnection* connection_;
-  TestSession session_;
+  TestClientSession session_;
   QuicConfig config_;
   QuicCryptoServerConfig crypto_config_;
   QuicCryptoServerStream stream_;
@@ -140,12 +140,13 @@
 
   QuicConfig client_config;
   client_config.SetDefaults();
-  scoped_ptr<TestSession> client_session(
-      new TestSession(client_conn, client_config));
+  scoped_ptr<TestClientSession> client_session(
+      new TestClientSession(client_conn, client_config));
   QuicCryptoClientConfig client_crypto_config;
   client_crypto_config.SetDefaults();
 
-  QuicSessionKey server_key(kServerHostname, kServerPort, false);
+  QuicSessionKey server_key(kServerHostname, kServerPort, false,
+                            kPrivacyModeDisabled);
   scoped_ptr<QuicCryptoClientStream> client(new QuicCryptoClientStream(
       server_key, client_session.get(), NULL, &client_crypto_config));
   client_session->SetCryptoStream(client.get());
@@ -155,7 +156,8 @@
   CHECK(client->CryptoConnect());
   CHECK_EQ(1u, client_conn->packets_.size());
 
-  scoped_ptr<TestSession> server_session(new TestSession(server_conn, config_));
+  scoped_ptr<TestClientSession> server_session(
+      new TestClientSession(server_conn, config_));
   scoped_ptr<QuicCryptoServerStream> server(
       new QuicCryptoServerStream(crypto_config_, server_session.get()));
   server_session->SetCryptoStream(server.get());
@@ -177,8 +179,8 @@
   // This causes the client's nonce to be different and thus stops the
   // strike-register from rejecting the repeated nonce.
   reinterpret_cast<MockRandom*>(client_conn->random_generator())->ChangeValue();
-  client_session.reset(new TestSession(client_conn, client_config));
-  server_session.reset(new TestSession(server_conn, config_));
+  client_session.reset(new TestClientSession(client_conn, client_config));
+  server_session.reset(new TestClientSession(server_conn, config_));
   client.reset(new QuicCryptoClientStream(
       server_key, client_session.get(), NULL, &client_crypto_config));
   client_session->SetCryptoStream(client.get());
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 3c96fbe..77bfc8d 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -5,6 +5,7 @@
 #include "net/quic/quic_http_stream.h"
 
 #include "base/callback_helpers.h"
+#include "base/metrics/histogram.h"
 #include "base/strings/stringprintf.h"
 #include "net/base/io_buffer.h"
 #include "net/base/net_errors.h"
@@ -61,9 +62,11 @@
 
   if (request_info->url.SchemeIsSecure()) {
     SSLInfo ssl_info;
-    if (!session_->GetSSLInfo(&ssl_info) || !ssl_info.cert) {
+    bool secure_session = session_->GetSSLInfo(&ssl_info) && ssl_info.cert;
+    UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.SecureResourceSecureSession",
+                          secure_session);
+    if (!secure_session)
       return ERR_REQUEST_FOR_SECURE_RESOURCE_OVER_INSECURE_QUIC;
-    }
   }
 
   stream_net_log_ = stream_net_log;
diff --git a/net/quic/quic_http_stream_test.cc b/net/quic/quic_http_stream_test.cc
index 1eb7ebe..ac1f715 100644
--- a/net/quic/quic_http_stream_test.cc
+++ b/net/quic/quic_http_stream_test.cc
@@ -209,7 +209,7 @@
                               &crypto_client_stream_factory_,
                               make_scoped_ptr((QuicServerInfo*)NULL),
                               QuicSessionKey(kServerHostname, kServerPort,
-                                             false),
+                                             false, kPrivacyModeDisabled),
                               DefaultQuicConfig(), &crypto_config_, NULL));
     session_->GetCryptoStream()->CryptoConnect();
     EXPECT_TRUE(session_->IsCryptoHandshakeConfirmed());
diff --git a/net/quic/quic_session_key.cc b/net/quic/quic_session_key.cc
index 385a1de..8ffd524 100644
--- a/net/quic/quic_session_key.cc
+++ b/net/quic/quic_session_key.cc
@@ -11,15 +11,19 @@
 QuicSessionKey::QuicSessionKey() {}
 
 QuicSessionKey::QuicSessionKey(const HostPortPair& host_port_pair,
-                               bool is_https)
+                               bool is_https,
+                               PrivacyMode privacy_mode)
     : host_port_pair_(host_port_pair),
-      is_https_(is_https) {}
+      is_https_(is_https),
+      privacy_mode_(privacy_mode) {}
 
 QuicSessionKey::QuicSessionKey(const string& host,
                                uint16 port,
-                               bool is_https)
+                               bool is_https,
+                               PrivacyMode privacy_mode)
     : host_port_pair_(host, port),
-      is_https_(is_https) {}
+      is_https_(is_https),
+      privacy_mode_(privacy_mode) {}
 
 QuicSessionKey::~QuicSessionKey() {}
 
@@ -27,16 +31,21 @@
   if (!host_port_pair_.Equals(other.host_port_pair_)) {
     return host_port_pair_ < other.host_port_pair_;
   }
-  return is_https_ < other.is_https_;
+  if (is_https_ != other.is_https_) {
+    return is_https_ < other.is_https_;
+  }
+  return privacy_mode_ < other.privacy_mode_;
 }
 
 bool QuicSessionKey::operator==(const QuicSessionKey& other) const {
   return is_https_ == other.is_https_ &&
+      privacy_mode_ == other.privacy_mode_ &&
       host_port_pair_.Equals(other.host_port_pair_);
 }
 
 string QuicSessionKey::ToString() const {
-  return (is_https_ ? "https://" : "http://") + host_port_pair_.ToString();
+  return (is_https_ ? "https://" : "http://") + host_port_pair_.ToString() +
+      (privacy_mode_ == kPrivacyModeEnabled ? "/private" : "");
 }
 
 }  // namespace net
diff --git a/net/quic/quic_session_key.h b/net/quic/quic_session_key.h
index 12975fa..6cd43e7 100644
--- a/net/quic/quic_session_key.h
+++ b/net/quic/quic_session_key.h
@@ -9,6 +9,7 @@
 
 #include "net/base/host_port_pair.h"
 #include "net/base/net_export.h"
+#include "net/base/privacy_mode.h"
 
 namespace net {
 
@@ -16,8 +17,13 @@
 class NET_EXPORT_PRIVATE QuicSessionKey {
  public:
   QuicSessionKey();
-  QuicSessionKey(const HostPortPair& host_port_pair, bool is_https);
-  QuicSessionKey(const std::string& host, uint16 port, bool is_https);
+  QuicSessionKey(const HostPortPair& host_port_pair,
+                 bool is_https,
+                 PrivacyMode privacy_mode);
+  QuicSessionKey(const std::string& host,
+                 uint16 port,
+                 bool is_https,
+                 PrivacyMode privacy_mode);
   ~QuicSessionKey();
 
   // Needed to be an element of std::set.
@@ -38,9 +44,12 @@
 
   bool is_https() const { return is_https_; }
 
+  PrivacyMode privacy_mode() const { return privacy_mode_; }
+
  private:
   HostPortPair host_port_pair_;
   bool is_https_;
+  PrivacyMode privacy_mode_;
 };
 
 }  // namespace net
diff --git a/net/quic/quic_session_key_test.cc b/net/quic/quic_session_key_test.cc
index b07b3b7..e8fd4fd 100644
--- a/net/quic/quic_session_key_test.cc
+++ b/net/quic/quic_session_key_test.cc
@@ -15,13 +15,25 @@
 TEST(QuicSessionKeyTest, ToString) {
   HostPortPair google_host_port_pair("google.com", 10);
 
-  QuicSessionKey google_http_key(google_host_port_pair, false);
+  QuicSessionKey google_http_key(google_host_port_pair, false,
+                                 kPrivacyModeDisabled);
   string google_http_key_str = google_http_key.ToString();
   EXPECT_EQ("http://google.com:10", google_http_key_str);
 
-  QuicSessionKey google_https_key(google_host_port_pair, true);
+  QuicSessionKey google_https_key(google_host_port_pair, true,
+                                 kPrivacyModeDisabled);
   string google_https_key_str = google_https_key.ToString();
   EXPECT_EQ("https://google.com:10", google_https_key_str);
+
+  QuicSessionKey private_http_key(google_host_port_pair, false,
+                                  kPrivacyModeEnabled);
+  string private_http_key_str = private_http_key.ToString();
+  EXPECT_EQ("http://google.com:10/private", private_http_key_str);
+
+  QuicSessionKey private_https_key(google_host_port_pair, true,
+                                   kPrivacyModeEnabled);
+  string private_https_key_str = private_https_key.ToString();
+  EXPECT_EQ("https://google.com:10/private", private_https_key_str);
 }
 
 }  // namespace
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 7324511..3aec036 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -6,6 +6,7 @@
 
 #include <set>
 
+#include "base/cpu.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_loop_proxy.h"
 #include "base/metrics/histogram.h"
@@ -34,6 +35,10 @@
 #include "net/quic/quic_session_key.h"
 #include "net/socket/client_socket_factory.h"
 
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#endif
+
 using std::string;
 using std::vector;
 
@@ -41,8 +46,29 @@
 
 namespace {
 
+enum CreateSessionFailure {
+  CREATION_ERROR_CONNECTING_SOCKET,
+  CREATION_ERROR_SETTING_RECEIVE_BUFFER,
+  CREATION_ERROR_SETTING_SEND_BUFFER,
+  CREATION_ERROR_MAX
+};
+
 const uint64 kBrokenAlternateProtocolDelaySecs = 300;
 
+void HistogramCreateSessionFailure(enum CreateSessionFailure error) {
+  UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.CreationError", error,
+                            CREATION_ERROR_MAX);
+}
+
+bool IsEcdsaSupported() {
+#if defined(OS_WIN)
+  if (base::win::GetVersion() < base::win::VERSION_VISTA)
+    return false;
+#endif
+
+  return true;
+}
+
 }  // namespace
 
 QuicStreamFactory::IpAliasKey::IpAliasKey() {}
@@ -76,8 +102,8 @@
       HostResolver* host_resolver,
       const HostPortPair& host_port_pair,
       bool is_https,
+      PrivacyMode privacy_mode,
       base::StringPiece method,
-      CertVerifier* cert_verifier,
       QuicServerInfo* server_info,
       const BoundNetLog& net_log);
 
@@ -117,10 +143,8 @@
 
   QuicStreamFactory* factory_;
   SingleRequestHostResolver host_resolver_;
-  bool is_https_;
   QuicSessionKey session_key_;
   bool is_post_;
-  CertVerifier* cert_verifier_;
   scoped_ptr<QuicServerInfo> server_info_;
   const BoundNetLog net_log_;
   QuicClientSession* session_;
@@ -135,16 +159,14 @@
                             HostResolver* host_resolver,
                             const HostPortPair& host_port_pair,
                             bool is_https,
+                            PrivacyMode privacy_mode,
                             base::StringPiece method,
-                            CertVerifier* cert_verifier,
                             QuicServerInfo* server_info,
                             const BoundNetLog& net_log)
     : factory_(factory),
       host_resolver_(host_resolver),
-      is_https_(is_https),
-      session_key_(host_port_pair, is_https),
+      session_key_(host_port_pair, is_https, privacy_mode),
       is_post_(method == "POST"),
-      cert_verifier_(cert_verifier),
       server_info_(server_info),
       net_log_(net_log),
       session_(NULL),
@@ -265,8 +287,7 @@
 int QuicStreamFactory::Job::DoConnect() {
   io_state_ = STATE_CONNECT_COMPLETE;
 
-  int rv = factory_->CreateSession(session_key_.host_port_pair(), is_https_,
-                                   cert_verifier_, server_info_.Pass(),
+  int rv = factory_->CreateSession(session_key_, server_info_.Pass(),
                                    address_list_, net_log_, &session_);
   if (rv != OK) {
     DCHECK(rv != ERR_IO_PENDING);
@@ -279,7 +300,7 @@
     return ERR_QUIC_PROTOCOL_ERROR;
   }
   rv = session_->CryptoConnect(
-      factory_->require_confirmation() || is_https_,
+      factory_->require_confirmation() || session_key_.is_https() || is_post_,
       base::Bind(&QuicStreamFactory::Job::OnIOComplete,
                  base::Unretained(this)));
   return rv;
@@ -314,19 +335,18 @@
 
 int QuicStreamRequest::Request(const HostPortPair& host_port_pair,
                                bool is_https,
+                               PrivacyMode privacy_mode,
                                base::StringPiece method,
-                               CertVerifier* cert_verifier,
                                const BoundNetLog& net_log,
                                const CompletionCallback& callback) {
   DCHECK(!stream_);
   DCHECK(callback_.is_null());
   DCHECK(factory_);
-  int rv = factory_->Create(host_port_pair, is_https,
-                            method, cert_verifier, net_log, this);
+  int rv = factory_->Create(host_port_pair, is_https, privacy_mode, method,
+                            net_log, this);
   if (rv == ERR_IO_PENDING) {
     host_port_pair_ = host_port_pair;
     is_https_ = is_https;
-    cert_verifier_ = cert_verifier;
     net_log_ = net_log;
     callback_ = callback;
   } else {
@@ -356,6 +376,7 @@
     HostResolver* host_resolver,
     ClientSocketFactory* client_socket_factory,
     base::WeakPtr<HttpServerProperties> http_server_properties,
+    CertVerifier* cert_verifier,
     QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
     QuicRandom* random_generator,
     QuicClock* clock,
@@ -367,6 +388,7 @@
       host_resolver_(host_resolver),
       client_socket_factory_(client_socket_factory),
       http_server_properties_(http_server_properties),
+      cert_verifier_(cert_verifier),
       quic_server_info_factory_(NULL),
       quic_crypto_client_stream_factory_(quic_crypto_client_stream_factory),
       random_generator_(random_generator),
@@ -383,24 +405,30 @@
       QuicTime::Delta::FromSeconds(30),
       QuicTime::Delta::FromSeconds(30));
 
-  canoncial_suffixes_.push_back(string(".c.youtube.com"));
-  canoncial_suffixes_.push_back(string(".googlevideo.com"));
+  crypto_config_.SetDefaults();
+  crypto_config_.AddCanonicalSuffix(".c.youtube.com");
+  crypto_config_.AddCanonicalSuffix(".googlevideo.com");
+  crypto_config_.SetProofVerifier(new ProofVerifierChromium(cert_verifier));
+  base::CPU cpu;
+  if (cpu.has_aesni() && cpu.has_avx())
+    crypto_config_.PreferAesGcm();
+  if (!IsEcdsaSupported())
+    crypto_config_.DisableEcdsa();
 }
 
 QuicStreamFactory::~QuicStreamFactory() {
   CloseAllSessions(ERR_ABORTED);
   STLDeleteElements(&all_sessions_);
   STLDeleteValues(&active_jobs_);
-  STLDeleteValues(&all_crypto_configs_);
 }
 
 int QuicStreamFactory::Create(const HostPortPair& host_port_pair,
                               bool is_https,
+                              PrivacyMode privacy_mode,
                               base::StringPiece method,
-                              CertVerifier* cert_verifier,
                               const BoundNetLog& net_log,
                               QuicStreamRequest* request) {
-  QuicSessionKey session_key(host_port_pair, is_https);
+  QuicSessionKey session_key(host_port_pair, is_https, privacy_mode);
   if (HasActiveSession(session_key)) {
     request->set_stream(CreateIfSessionExists(session_key, net_log));
     return OK;
@@ -415,18 +443,15 @@
 
   QuicServerInfo* quic_server_info = NULL;
   if (quic_server_info_factory_) {
-    QuicCryptoClientConfig* crypto_config =
-        GetOrCreateCryptoConfig(session_key);
     QuicCryptoClientConfig::CachedState* cached =
-        crypto_config->LookupOrCreate(session_key);
+        crypto_config_.LookupOrCreate(session_key);
     DCHECK(cached);
     if (cached->IsEmpty()) {
       quic_server_info = quic_server_info_factory_->GetForServer(session_key);
     }
   }
-  scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair,
-                              is_https, method, cert_verifier,
-                              quic_server_info, net_log));
+  scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_pair, is_https,
+                              privacy_mode, method, quic_server_info, net_log));
   int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
                                base::Unretained(this), job.get()));
 
@@ -649,15 +674,12 @@
 }
 
 int QuicStreamFactory::CreateSession(
-    const HostPortPair& host_port_pair,
-    bool is_https,
-    CertVerifier* cert_verifier,
+    const QuicSessionKey& session_key,
     scoped_ptr<QuicServerInfo> server_info,
     const AddressList& address_list,
     const BoundNetLog& net_log,
     QuicClientSession** session) {
   bool enable_port_selection = enable_port_selection_;
-  QuicSessionKey session_key(host_port_pair, is_https);
   if (enable_port_selection &&
       ContainsKey(gone_away_aliases_, session_key)) {
     // Disable port selection when the server is going away.
@@ -670,7 +692,7 @@
   QuicConnectionId connection_id = random_generator_->RandUint64();
   IPEndPoint addr = *address_list.begin();
   scoped_refptr<PortSuggester> port_suggester =
-      new PortSuggester(host_port_pair, port_seed_);
+      new PortSuggester(session_key.host_port_pair(), port_seed_);
   DatagramSocket::BindType bind_type = enable_port_selection ?
       DatagramSocket::RANDOM_BIND :  // Use our callback.
       DatagramSocket::DEFAULT_BIND;  // Use OS to randomize.
@@ -680,8 +702,10 @@
           base::Bind(&PortSuggester::SuggestPort, port_suggester),
           net_log.net_log(), net_log.source()));
   int rv = socket->Connect(addr);
-  if (rv != OK)
+  if (rv != OK) {
+    HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET);
     return rv;
+  }
   UMA_HISTOGRAM_COUNTS("Net.QuicEphemeralPortsSuggested",
                        port_suggester->call_count());
   if (enable_port_selection) {
@@ -695,11 +719,17 @@
   // does not consume "too much" memory.  If we see bursty packet loss, we may
   // revisit this setting and test for its impact.
   const int32 kSocketBufferSize(TcpReceiver::kReceiveWindowTCP);
-  socket->SetReceiveBufferSize(kSocketBufferSize);
+  if (!socket->SetReceiveBufferSize(kSocketBufferSize)) {
+    HistogramCreateSessionFailure(CREATION_ERROR_SETTING_RECEIVE_BUFFER);
+    return ERR_SOCKET_SET_RECEIVE_BUFFER_SIZE_ERROR;
+  }
   // Set a buffer large enough to contain the initial CWND's worth of packet
   // to work around the problem with CHLO packets being sent out with the
   // wrong encryption level, when the send buffer is full.
-  socket->SetSendBufferSize(kMaxPacketSize * 20); // Support 20 packets.
+  if (!socket->SetSendBufferSize(kMaxPacketSize * 20)) {
+    HistogramCreateSessionFailure(CREATION_ERROR_SETTING_SEND_BUFFER);
+    return ERR_SOCKET_SET_SEND_BUFFER_SIZE_ERROR;
+  }
 
   scoped_ptr<QuicDefaultPacketWriter> writer(
       new QuicDefaultPacketWriter(socket.get()));
@@ -717,14 +747,13 @@
   writer->SetConnection(connection);
   connection->options()->max_packet_length = max_packet_length_;
 
-  QuicCryptoClientConfig* crypto_config = GetOrCreateCryptoConfig(session_key);
-  InitializeCachedState(session_key, crypto_config, server_info);
-  DCHECK(crypto_config);
+  InitializeCachedState(session_key, server_info);
 
   QuicConfig config = config_;
   if (http_server_properties_) {
     const HttpServerProperties::NetworkStats* stats =
-        http_server_properties_->GetServerNetworkStats(host_port_pair);
+        http_server_properties_->GetServerNetworkStats(
+            session_key.host_port_pair());
     if (stats != NULL) {
       config.set_initial_round_trip_time_us(stats->rtt.InMicroseconds(),
                                             stats->rtt.InMicroseconds());
@@ -734,12 +763,8 @@
   *session = new QuicClientSession(
       connection, socket.Pass(), writer.Pass(), this,
       quic_crypto_client_stream_factory_, server_info.Pass(), session_key,
-      config, crypto_config, net_log.net_log());
+      config, &crypto_config_, net_log.net_log());
   all_sessions_.insert(*session);  // owning pointer
-  if (is_https) {
-    crypto_config->SetProofVerifier(
-        new ProofVerifierChromium(cert_verifier, net_log));
-  }
   return OK;
 }
 
@@ -759,72 +784,14 @@
   ip_aliases_[ip_alias_key].insert(session);
 }
 
-QuicCryptoClientConfig* QuicStreamFactory::GetOrCreateCryptoConfig(
-    const QuicSessionKey& session_key) {
-  QuicCryptoClientConfig* crypto_config;
-
-  if (ContainsKey(all_crypto_configs_, session_key)) {
-    crypto_config = all_crypto_configs_[session_key];
-    DCHECK(crypto_config);
-  } else {
-    // TODO(rtenneti): if two quic_sessions for the same host_port_pair
-    // share the same crypto_config, will it cause issues?
-    crypto_config = new QuicCryptoClientConfig();
-    crypto_config->SetDefaults();
-    all_crypto_configs_[session_key] = crypto_config;
-    PopulateFromCanonicalConfig(session_key, crypto_config);
-  }
-  return crypto_config;
-}
-
-void QuicStreamFactory::PopulateFromCanonicalConfig(
-    const QuicSessionKey& session_key,
-    QuicCryptoClientConfig* crypto_config) {
-  const string server_hostname = session_key.host();
-  unsigned i = 0;
-  for (; i < canoncial_suffixes_.size(); ++i) {
-    if (EndsWith(server_hostname, canoncial_suffixes_[i], false)) {
-      break;
-    }
-  }
-  if (i == canoncial_suffixes_.size())
-    return;
-
-  HostPortPair suffix_host_port_pair(canoncial_suffixes_[i],
-                                     session_key.port());
-  QuicSessionKey suffix_session_key(suffix_host_port_pair,
-                                    session_key.is_https());
-  if (!ContainsKey(canonical_hostname_to_origin_map_, suffix_session_key)) {
-    // This is the first host we've seen which matches the suffix, so make it
-    // canonical.
-    canonical_hostname_to_origin_map_[suffix_session_key] = session_key;
-    return;
-  }
-
-  const QuicSessionKey& canonical_session_key =
-      canonical_hostname_to_origin_map_[suffix_session_key];
-  QuicCryptoClientConfig* canonical_crypto_config =
-      all_crypto_configs_[canonical_session_key];
-  DCHECK(canonical_crypto_config);
-
-  // Copy the CachedState for the canonical server from canonical_crypto_config
-  // as the initial CachedState for the server_hostname in crypto_config.
-  crypto_config->InitializeFrom(session_key, canonical_session_key,
-                                canonical_crypto_config);
-  // Update canonical version to point at the "most recent" crypto_config.
-  canonical_hostname_to_origin_map_[suffix_session_key] =
-      canonical_session_key;
-}
-
 void QuicStreamFactory::InitializeCachedState(
     const QuicSessionKey& session_key,
-    QuicCryptoClientConfig* crypto_config,
     const scoped_ptr<QuicServerInfo>& server_info) {
   if (!server_info)
     return;
 
   QuicCryptoClientConfig::CachedState* cached =
-      crypto_config->LookupOrCreate(session_key);
+      crypto_config_.LookupOrCreate(session_key);
   if (!cached->IsEmpty())
     return;
 
@@ -835,8 +802,8 @@
                           clock_->WallNow()))
     return;
 
-  if (!crypto_config->proof_verifier()) {
-    // If no verifier is set then we don't check the certificates.
+  if (!session_key.is_https()) {
+    // Don't check the certificates for insecure QUIC.
     cached->SetProofValid();
   }
 }
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 61806a7..1e22cdb 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -54,8 +54,8 @@
   // For http, |is_https| is false and |cert_verifier| can be null.
   int Request(const HostPortPair& host_port_pair,
               bool is_https,
+              PrivacyMode privacy_mode,
               base::StringPiece method,
-              CertVerifier* cert_verifier,
               const BoundNetLog& net_log,
               const CompletionCallback& callback);
 
@@ -73,7 +73,6 @@
   QuicStreamFactory* factory_;
   HostPortPair host_port_pair_;
   bool is_https_;
-  CertVerifier* cert_verifier_;
   BoundNetLog net_log_;
   CompletionCallback callback_;
   scoped_ptr<QuicHttpStream> stream_;
@@ -91,6 +90,7 @@
       HostResolver* host_resolver,
       ClientSocketFactory* client_socket_factory,
       base::WeakPtr<HttpServerProperties> http_server_properties,
+      CertVerifier* cert_verifier,
       QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
       QuicRandom* random_generator,
       QuicClock* clock,
@@ -109,8 +109,8 @@
   // asynchronously.
   int Create(const HostPortPair& host_port_pair,
              bool is_https,
+             PrivacyMode privacy_mode,
              base::StringPiece method,
-             CertVerifier* cert_verifier,
              const BoundNetLog& net_log,
              QuicStreamRequest* request);
 
@@ -166,7 +166,7 @@
   class Job;
   friend class test::QuicStreamFactoryPeer;
 
-  // The key used to find session by hostname. Includes
+  // The key used to find session by ip. Includes
   // the ip address, port, and scheme.
   struct NET_EXPORT_PRIVATE IpAliasKey {
     IpAliasKey();
@@ -187,7 +187,6 @@
   typedef std::set<QuicClientSession*> SessionSet;
   typedef std::map<IpAliasKey, SessionSet> IPAliasMap;
   typedef std::map<QuicSessionKey, QuicCryptoClientConfig*> CryptoConfigMap;
-  typedef std::map<QuicSessionKey, QuicSessionKey> CanonicalHostMap;
   typedef std::map<QuicSessionKey, Job*> JobMap;
   typedef std::map<QuicStreamRequest*, Job*> RequestMap;
   typedef std::set<QuicStreamRequest*> RequestSet;
@@ -203,9 +202,7 @@
   void OnJobComplete(Job* job, int rv);
   bool HasActiveSession(const QuicSessionKey& session_key) const;
   bool HasActiveJob(const QuicSessionKey& session_key) const;
-  int CreateSession(const HostPortPair& host_port_pair,
-                    bool is_https,
-                    CertVerifier* cert_verifier,
+  int CreateSession(const QuicSessionKey& session_key,
                     scoped_ptr<QuicServerInfo> quic_server_info,
                     const AddressList& address_list,
                     const BoundNetLog& net_log,
@@ -213,20 +210,9 @@
   void ActivateSession(const QuicSessionKey& key,
                        QuicClientSession* session);
 
-  QuicCryptoClientConfig* GetOrCreateCryptoConfig(
-      const QuicSessionKey& session_key);
-
-  // If the suffix of the hostname in |session_key| is in |canoncial_suffixes_|,
-  // then populate |crypto_config| with a canonical server config data from
-  // |canonical_hostname_to_origin_map_| for that suffix.
-  void PopulateFromCanonicalConfig(
-      const QuicSessionKey& session_key,
-      QuicCryptoClientConfig* crypto_config);
-
   // Initializes the cached state associated with |session_key| in
-  // |crypto_config| with the information in |server_info|.
+  // |crypto_config_| with the information in |server_info|.
   void InitializeCachedState(const QuicSessionKey& session_key,
-                             QuicCryptoClientConfig* crypto_config,
                              const scoped_ptr<QuicServerInfo>& server_info);
 
   void ExpireBrokenAlternateProtocolMappings();
@@ -236,6 +222,7 @@
   HostResolver* host_resolver_;
   ClientSocketFactory* client_socket_factory_;
   base::WeakPtr<HttpServerProperties> http_server_properties_;
+  CertVerifier* cert_verifier_;
   QuicServerInfoFactory* quic_server_info_factory_;
   QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory_;
   QuicRandom* random_generator_;
@@ -258,23 +245,6 @@
   // Origins which have gone away recently.
   AliasSet gone_away_aliases_;
 
-  // Contains owning pointers to QuicCryptoClientConfig. QuicCryptoClientConfig
-  // contains configuration and cached state about servers.
-  // TODO(rtenneti): Persist all_crypto_configs_ to disk and decide when to
-  // clear the data in the map.
-  CryptoConfigMap all_crypto_configs_;
-
-  // Contains a map of servers which could share the same server config. Map
-  // from a Canonical host/port/scheme (host is some postfix of host names) to
-  // an actual origin, which has a plausible set of initial certificates (or at
-  // least server public key).
-  CanonicalHostMap canonical_hostname_to_origin_map_;
-
-  // Contains list of suffixes (for exmaple ".c.youtube.com",
-  // ".googlevideo.com") of canoncial hostnames.
-  std::vector<std::string> canoncial_suffixes_;
-
-
   // List of broken host:ports and the times when they can be expired.
   struct BrokenAlternateProtocolEntry {
     HostPortPair origin;
@@ -290,6 +260,7 @@
   BrokenAlternateProtocolMap broken_alternate_protocol_map_;
 
   QuicConfig config_;
+  QuicCryptoClientConfig crypto_config_;
 
   JobMap active_jobs_;
   JobRequestsMap job_requests_map_;
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index f7e271c..780c5cb 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -41,18 +41,14 @@
 
 class QuicStreamFactoryPeer {
  public:
-  static QuicCryptoClientConfig* GetOrCreateCryptoConfig(
-      QuicStreamFactory* factory,
-      const HostPortPair& host_port_pair,
-      bool is_https) {
-    QuicSessionKey server_key(host_port_pair, is_https);
-    return factory->GetOrCreateCryptoConfig(server_key);
+  static QuicCryptoClientConfig* GetCryptoConfig(QuicStreamFactory* factory) {
+    return &factory->crypto_config_;
   }
 
   static bool HasActiveSession(QuicStreamFactory* factory,
                                const HostPortPair& host_port_pair,
                                bool is_https) {
-    QuicSessionKey server_key(host_port_pair, is_https);
+    QuicSessionKey server_key(host_port_pair, is_https, kPrivacyModeDisabled);
     return factory->HasActiveSession(server_key);
   }
 
@@ -60,7 +56,7 @@
       QuicStreamFactory* factory,
       const HostPortPair& host_port_pair,
       bool is_https) {
-    QuicSessionKey server_key(host_port_pair, is_https);
+    QuicSessionKey server_key(host_port_pair, is_https, kPrivacyModeDisabled);
     DCHECK(factory->HasActiveSession(server_key));
     return factory->active_sessions_[server_key];
   }
@@ -70,7 +66,7 @@
       const HostPortPair& host_port_pair,
       bool is_https,
       const BoundNetLog& net_log) {
-    QuicSessionKey server_key(host_port_pair, is_https);
+    QuicSessionKey server_key(host_port_pair, is_https, kPrivacyModeDisabled);
     return factory->CreateIfSessionExists(server_key, net_log);
   }
 
@@ -92,14 +88,16 @@
       : random_generator_(0),
         maker_(GetParam(), 0),
         clock_(new MockClock()),
+        cert_verifier_(CertVerifier::CreateDefault()),
         factory_(&host_resolver_, &socket_factory_,
                  base::WeakPtr<HttpServerProperties>(),
+                 cert_verifier_.get(),
                  &crypto_client_stream_factory_,
                  &random_generator_, clock_, kDefaultMaxPacketSize,
                  SupportedVersions(GetParam()), true, true),
         host_port_pair_(kDefaultServerHostName, kDefaultServerPort),
         is_https_(false),
-        cert_verifier_(CertVerifier::CreateDefault()) {
+        privacy_mode_(kPrivacyModeDisabled) {
     factory_.set_require_confirmation(false);
   }
 
@@ -136,8 +134,8 @@
     EXPECT_EQ(ERR_IO_PENDING,
               request.Request(destination,
                               is_https_,
+                              privacy_mode_,
                               "GET",
-                              cert_verifier_.get(),
                               net_log_,
                               callback_.callback()));
 
@@ -181,10 +179,11 @@
   MockRandom random_generator_;
   QuicTestPacketMaker maker_;
   MockClock* clock_;  // Owned by factory_.
+  scoped_ptr<CertVerifier> cert_verifier_;
   QuicStreamFactory factory_;
   HostPortPair host_port_pair_;
   bool is_https_;
-  scoped_ptr<CertVerifier> cert_verifier_;
+  PrivacyMode privacy_mode_;
   BoundNetLog net_log_;
   TestCompletionCallback callback_;
 };
@@ -208,8 +207,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -227,8 +226,8 @@
   EXPECT_EQ(OK,
             request2.Request(host_port_pair_,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
   stream = request2.ReleaseStream();  // Will reset stream 5.
@@ -238,6 +237,70 @@
   EXPECT_TRUE(socket_data.at_write_eof());
 }
 
+TEST_P(QuicStreamFactoryTest, CreateZeroRtt) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), NULL, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  EXPECT_EQ(OK,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "GET",
+                            net_log_,
+                            callback_.callback()));
+
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, CreateZeroRttPost) {
+  MockRead reads[] = {
+    MockRead(ASYNC, OK, 0)  // EOF
+  };
+  DeterministicSocketData socket_data(reads, arraysize(reads), NULL, 0);
+  socket_factory_.AddSocketDataProvider(&socket_data);
+  socket_data.StopAfter(1);
+
+  crypto_client_stream_factory_.set_handshake_mode(
+      MockCryptoClientStream::ZERO_RTT);
+  host_resolver_.set_synchronous_mode(true);
+  host_resolver_.rules()->AddIPLiteralRule(host_port_pair_.host(),
+                                           "192.168.0.1", "");
+
+  QuicStreamRequest request(&factory_);
+  // Posts require handshake confirmation, so this will return asynchronously.
+  EXPECT_EQ(ERR_IO_PENDING,
+            request.Request(host_port_pair_,
+                            is_https_,
+                            privacy_mode_,
+                            "POST",
+                            net_log_,
+                            callback_.callback()));
+
+  // Confirm the handshake and verify that the stream is created.
+  crypto_client_stream_factory_.last_stream()->SendOnCryptoHandshakeEvent(
+      QuicSession::HANDSHAKE_CONFIRMED);
+
+  EXPECT_EQ(OK, callback_.WaitForResult());
+  scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+  EXPECT_TRUE(stream.get());
+  EXPECT_TRUE(socket_data.at_read_eof());
+  EXPECT_TRUE(socket_data.at_write_eof());
+}
+
 TEST_P(QuicStreamFactoryTest, CreateHttpVsHttps) {
   MockRead reads[] = {
     MockRead(ASYNC, OK, 0)  // EOF
@@ -253,8 +316,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -266,8 +329,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request2.Request(host_port_pair_,
                              !is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
   EXPECT_EQ(OK, callback_.WaitForResult());
@@ -305,8 +368,8 @@
   EXPECT_EQ(OK,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
   scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
@@ -317,8 +380,8 @@
   EXPECT_EQ(OK,
             request2.Request(server2,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback.callback()));
   scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
@@ -355,8 +418,8 @@
   EXPECT_EQ(OK,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
   scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
@@ -367,8 +430,8 @@
   EXPECT_EQ(OK,
             request2.Request(server2,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback.callback()));
   scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
@@ -386,8 +449,8 @@
   EXPECT_EQ(OK,
             request3.Request(server2,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback3.callback()));
   scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
@@ -434,8 +497,8 @@
   EXPECT_EQ(OK,
             request.Request(server1,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
   scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
@@ -446,8 +509,8 @@
   EXPECT_EQ(OK,
             request2.Request(server2,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
   scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
@@ -499,8 +562,8 @@
   EXPECT_EQ(OK,
             request.Request(server1,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
   scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
@@ -511,8 +574,8 @@
   EXPECT_EQ(OK,
             request2.Request(server2,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
   scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
@@ -544,8 +607,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -569,8 +632,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request2.Request(host_port_pair_,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
   EXPECT_EQ(OK, callback_.WaitForResult());
@@ -617,8 +680,8 @@
     QuicStreamRequest request(&factory_);
     int rv = request.Request(host_port_pair_,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback());
     if (i == 0) {
@@ -638,8 +701,8 @@
   EXPECT_EQ(OK,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             CompletionCallback()));
   scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
@@ -669,8 +732,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -691,8 +754,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -713,8 +776,8 @@
     EXPECT_EQ(ERR_IO_PENDING,
               request.Request(host_port_pair_,
                               is_https_,
+                              privacy_mode_,
                               "GET",
-                              cert_verifier_.get(),
                               net_log_,
                               callback_.callback()));
   }
@@ -781,8 +844,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -805,8 +868,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request2.Request(host_port_pair_,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
 
@@ -845,8 +908,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -870,8 +933,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request2.Request(host_port_pair_,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
 
@@ -910,8 +973,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -935,8 +998,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request2.Request(host_port_pair_,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
 
@@ -975,8 +1038,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request.Request(host_port_pair_,
                             is_https_,
+                            privacy_mode_,
                             "GET",
-                            cert_verifier_.get(),
                             net_log_,
                             callback_.callback()));
 
@@ -1000,8 +1063,8 @@
   EXPECT_EQ(ERR_IO_PENDING,
             request2.Request(host_port_pair_,
                              is_https_,
+                             privacy_mode_,
                              "GET",
-                             cert_verifier_.get(),
                              net_log_,
                              callback_.callback()));
 
@@ -1027,13 +1090,11 @@
     r2_host_name.append(cannoncial_suffixes[i]);
 
     HostPortPair host_port_pair1(r1_host_name, 80);
-    QuicCryptoClientConfig* crypto_config1 =
-        QuicStreamFactoryPeer::GetOrCreateCryptoConfig(
-            &factory_, host_port_pair1, is_https_);
-    DCHECK(crypto_config1);
-    QuicSessionKey server_key1(host_port_pair1, is_https_);
+    QuicCryptoClientConfig* crypto_config =
+        QuicStreamFactoryPeer::GetCryptoConfig(&factory_);
+    QuicSessionKey server_key1(host_port_pair1, is_https_, privacy_mode_);
     QuicCryptoClientConfig::CachedState* cached1 =
-        crypto_config1->LookupOrCreate(server_key1);
+        crypto_config->LookupOrCreate(server_key1);
     EXPECT_FALSE(cached1->proof_valid());
     EXPECT_TRUE(cached1->source_address_token().empty());
 
@@ -1043,13 +1104,9 @@
     cached1->SetProofValid();
 
     HostPortPair host_port_pair2(r2_host_name, 80);
-    QuicCryptoClientConfig* crypto_config2 =
-        QuicStreamFactoryPeer::GetOrCreateCryptoConfig(
-            &factory_, host_port_pair2, is_https_);
-    DCHECK(crypto_config2);
-    QuicSessionKey server_key2(host_port_pair2, is_https_);
+    QuicSessionKey server_key2(host_port_pair2, is_https_, privacy_mode_);
     QuicCryptoClientConfig::CachedState* cached2 =
-        crypto_config2->LookupOrCreate(server_key2);
+        crypto_config->LookupOrCreate(server_key2);
     EXPECT_EQ(cached1->source_address_token(), cached2->source_address_token());
     EXPECT_TRUE(cached2->proof_valid());
   }
@@ -1067,13 +1124,11 @@
     r4_host_name.append(cannoncial_suffixes[i]);
 
     HostPortPair host_port_pair1(r3_host_name, 80);
-    QuicCryptoClientConfig* crypto_config1 =
-        QuicStreamFactoryPeer::GetOrCreateCryptoConfig(
-            &factory_, host_port_pair1, is_https_);
-    DCHECK(crypto_config1);
-    QuicSessionKey server_key1(host_port_pair1, is_https_);
+    QuicCryptoClientConfig* crypto_config =
+        QuicStreamFactoryPeer::GetCryptoConfig(&factory_);
+    QuicSessionKey server_key1(host_port_pair1, is_https_, privacy_mode_);
     QuicCryptoClientConfig::CachedState* cached1 =
-        crypto_config1->LookupOrCreate(server_key1);
+        crypto_config->LookupOrCreate(server_key1);
     EXPECT_FALSE(cached1->proof_valid());
     EXPECT_TRUE(cached1->source_address_token().empty());
 
@@ -1083,13 +1138,9 @@
     cached1->SetProofInvalid();
 
     HostPortPair host_port_pair2(r4_host_name, 80);
-    QuicCryptoClientConfig* crypto_config2 =
-        QuicStreamFactoryPeer::GetOrCreateCryptoConfig(
-            &factory_, host_port_pair2, is_https_);
-    DCHECK(crypto_config2);
-    QuicSessionKey server_key2(host_port_pair2, is_https_);
+    QuicSessionKey server_key2(host_port_pair2, is_https_, privacy_mode_);
     QuicCryptoClientConfig::CachedState* cached2 =
-        crypto_config2->LookupOrCreate(server_key2);
+        crypto_config->LookupOrCreate(server_key2);
     EXPECT_NE(cached1->source_address_token(), cached2->source_address_token());
     EXPECT_TRUE(cached2->source_address_token().empty());
     EXPECT_FALSE(cached2->proof_valid());
diff --git a/net/quic/test_tools/crypto_test_utils.cc b/net/quic/test_tools/crypto_test_utils.cc
index c3ccf72..45fc5a0 100644
--- a/net/quic/test_tools/crypto_test_utils.cc
+++ b/net/quic/test_tools/crypto_test_utils.cc
@@ -167,7 +167,7 @@
     QuicCryptoServerStream* server,
     const FakeClientOptions& options) {
   PacketSavingConnection* client_conn = new PacketSavingConnection(false);
-  TestSession client_session(client_conn, DefaultQuicConfig());
+  TestClientSession client_session(client_conn, DefaultQuicConfig());
   QuicCryptoClientConfig crypto_config;
 
   client_session.config()->SetDefaults();
@@ -179,7 +179,8 @@
   if (options.channel_id_enabled) {
     crypto_config.SetChannelIDSigner(ChannelIDSignerForTesting());
   }
-  QuicSessionKey server_key(kServerHostname, kServerPort, false);
+  QuicSessionKey server_key(kServerHostname, kServerPort, false,
+                            kPrivacyModeDisabled);
   QuicCryptoClientStream client(server_key, &client_session, NULL,
                                 &crypto_config);
   client_session.SetCryptoStream(&client);
diff --git a/net/quic/test_tools/crypto_test_utils.h b/net/quic/test_tools/crypto_test_utils.h
index 65ba9ee..1d26dc7 100644
--- a/net/quic/test_tools/crypto_test_utils.h
+++ b/net/quic/test_tools/crypto_test_utils.h
@@ -23,6 +23,7 @@
 class CommonCertSets;
 class ProofSource;
 class ProofVerifier;
+class ProofVerifyContext;
 class QuicClock;
 class QuicConfig;
 class QuicCryptoClientStream;
@@ -96,6 +97,10 @@
   // Returns a |ProofVerifier| that uses the QUIC testing root CA.
   static ProofVerifier* ProofVerifierForTesting();
 
+  // Returns a |ProofVerifyContext| that must be used with the verifier
+  // returned by |ProofVerifierForTesting|.
+  static ProofVerifyContext* ProofVerifyContextForTesting();
+
   // MockCommonCertSets returns a CommonCertSets that contains a single set with
   // hash |hash|, consisting of the certificate |cert| at index |index|.
   static CommonCertSets* MockCommonCertSets(base::StringPiece cert,
diff --git a/net/quic/test_tools/crypto_test_utils_chromium.cc b/net/quic/test_tools/crypto_test_utils_chromium.cc
index 8aaef42..eb4fec0 100644
--- a/net/quic/test_tools/crypto_test_utils_chromium.cc
+++ b/net/quic/test_tools/crypto_test_utils_chromium.cc
@@ -22,7 +22,7 @@
  public:
   TestProofVerifierChromium(CertVerifier* cert_verifier,
                             const std::string& cert_file)
-      : ProofVerifierChromium(cert_verifier, BoundNetLog()),
+      : ProofVerifierChromium(cert_verifier),
         cert_verifier_(cert_verifier) {
     // Load and install the root for the validated chain.
     scoped_refptr<X509Certificate> root_cert =
@@ -48,6 +48,11 @@
   return proof_verifier;
 }
 
+// static
+ProofVerifyContext* CryptoTestUtils::ProofVerifyContextForTesting() {
+  return new ProofVerifyContextChromium(BoundNetLog());
+}
+
 }  // namespace test
 
 }  // namespace net
diff --git a/net/quic/test_tools/mock_crypto_client_stream.cc b/net/quic/test_tools/mock_crypto_client_stream.cc
index b0112d5..a5ff173 100644
--- a/net/quic/test_tools/mock_crypto_client_stream.cc
+++ b/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -4,6 +4,7 @@
 
 #include "net/quic/test_tools/mock_crypto_client_stream.h"
 
+#include "net/quic/quic_client_session_base.h"
 #include "net/quic/quic_session_key.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -11,12 +12,13 @@
 
 MockCryptoClientStream::MockCryptoClientStream(
     const QuicSessionKey& server_key,
-    QuicSession* session,
-    QuicCryptoClientStream::Visitor* visitor,
+    QuicClientSessionBase* session,
+    ProofVerifyContext* verify_context,
     QuicCryptoClientConfig* crypto_config,
     HandshakeMode handshake_mode,
     const ProofVerifyDetails* proof_verify_details)
-    : QuicCryptoClientStream(server_key, session, visitor, crypto_config),
+    : QuicCryptoClientStream(server_key, session, verify_context,
+                             crypto_config),
       handshake_mode_(handshake_mode),
       proof_verify_details_(proof_verify_details) {
 }
@@ -43,7 +45,7 @@
       encryption_established_ = true;
       handshake_confirmed_ = true;
       if (proof_verify_details_) {
-        visitor()->OnProofVerifyDetailsAvailable(*proof_verify_details_);
+        client_session()->OnProofVerifyDetailsAvailable(*proof_verify_details_);
       }
       SetConfigNegotiated();
       session()->OnCryptoHandshakeEvent(QuicSession::HANDSHAKE_CONFIRMED);
@@ -90,4 +92,8 @@
   ASSERT_TRUE(session()->config()->negotiated());
 }
 
+QuicClientSessionBase* MockCryptoClientStream::client_session() {
+  return reinterpret_cast<QuicClientSessionBase*>(session());
+}
+
 }  // namespace net
diff --git a/net/quic/test_tools/mock_crypto_client_stream.h b/net/quic/test_tools/mock_crypto_client_stream.h
index 444f88d..8567945 100644
--- a/net/quic/test_tools/mock_crypto_client_stream.h
+++ b/net/quic/test_tools/mock_crypto_client_stream.h
@@ -37,8 +37,8 @@
 
   MockCryptoClientStream(
       const QuicSessionKey& server_key,
-      QuicSession* session,
-      QuicCryptoClientStream::Visitor* visitor,
+      QuicClientSessionBase* session,
+      ProofVerifyContext* verify_context,
       QuicCryptoClientConfig* crypto_config,
       HandshakeMode handshake_mode,
       const ProofVerifyDetails* proof_verify_details_);
@@ -59,6 +59,7 @@
 
  private:
   void SetConfigNegotiated();
+  QuicClientSessionBase* client_session();
 
   const ProofVerifyDetails* proof_verify_details_;
 };
diff --git a/net/quic/test_tools/mock_crypto_client_stream_factory.cc b/net/quic/test_tools/mock_crypto_client_stream_factory.cc
index 686fd56..83dac36 100644
--- a/net/quic/test_tools/mock_crypto_client_stream_factory.cc
+++ b/net/quic/test_tools/mock_crypto_client_stream_factory.cc
@@ -25,7 +25,7 @@
     QuicClientSession* session,
     QuicCryptoClientConfig* crypto_config) {
   last_stream_ = new MockCryptoClientStream(
-      server_key, session, session, crypto_config, handshake_mode_,
+      server_key, session, NULL, crypto_config, handshake_mode_,
       proof_verify_details_);
   return last_stream_;
 }
diff --git a/net/quic/test_tools/quic_test_utils.cc b/net/quic/test_tools/quic_test_utils.cc
index c3e20ae..7d24b2f 100644
--- a/net/quic/test_tools/quic_test_utils.cc
+++ b/net/quic/test_tools/quic_test_utils.cc
@@ -23,6 +23,7 @@
 using std::min;
 using std::string;
 using testing::_;
+using testing::AnyNumber;
 
 namespace net {
 namespace test {
@@ -364,6 +365,23 @@
   return crypto_stream_;
 }
 
+TestClientSession::TestClientSession(QuicConnection* connection,
+                                     const QuicConfig& config)
+    : QuicClientSessionBase(connection, config),
+      crypto_stream_(NULL) {
+    EXPECT_CALL(*this, OnProofValid(_)).Times(AnyNumber());
+}
+
+TestClientSession::~TestClientSession() {}
+
+void TestClientSession::SetCryptoStream(QuicCryptoStream* stream) {
+  crypto_stream_ = stream;
+}
+
+QuicCryptoStream* TestClientSession::GetCryptoStream() {
+  return crypto_stream_;
+}
+
 MockPacketWriter::MockPacketWriter() {
 }
 
diff --git a/net/quic/test_tools/quic_test_utils.h b/net/quic/test_tools/quic_test_utils.h
index f6e188a..1cca4e8 100644
--- a/net/quic/test_tools/quic_test_utils.h
+++ b/net/quic/test_tools/quic_test_utils.h
@@ -13,7 +13,9 @@
 #include "base/strings/string_piece.h"
 #include "net/quic/congestion_control/loss_detection_interface.h"
 #include "net/quic/congestion_control/send_algorithm_interface.h"
+#include "net/quic/crypto/quic_crypto_client_config.h"
 #include "net/quic/quic_ack_notifier.h"
+#include "net/quic/quic_client_session_base.h"
 #include "net/quic/quic_connection.h"
 #include "net/quic/quic_framer.h"
 #include "net/quic/quic_session.h"
@@ -396,13 +398,37 @@
 
   void SetCryptoStream(QuicCryptoStream* stream);
 
-  virtual QuicCryptoStream* GetCryptoStream();
+  virtual QuicCryptoStream* GetCryptoStream() OVERRIDE;
 
  private:
   QuicCryptoStream* crypto_stream_;
   DISALLOW_COPY_AND_ASSIGN(TestSession);
 };
 
+class TestClientSession : public QuicClientSessionBase {
+ public:
+  TestClientSession(QuicConnection* connection, const QuicConfig& config);
+  virtual ~TestClientSession();
+
+  // QuicClientSessionBase
+  MOCK_METHOD1(OnProofValid,
+               void(const QuicCryptoClientConfig::CachedState& cached));
+  MOCK_METHOD1(OnProofVerifyDetailsAvailable,
+               void(const ProofVerifyDetails& verify_details));
+
+  // TestClientSession
+  MOCK_METHOD1(CreateIncomingDataStream, QuicDataStream*(QuicStreamId id));
+  MOCK_METHOD0(CreateOutgoingDataStream, QuicDataStream*());
+
+  void SetCryptoStream(QuicCryptoStream* stream);
+
+  virtual QuicCryptoStream* GetCryptoStream() OVERRIDE;
+
+ private:
+  QuicCryptoStream* crypto_stream_;
+  DISALLOW_COPY_AND_ASSIGN(TestClientSession);
+};
+
 class MockPacketWriter : public QuicPacketWriter {
  public:
   MockPacketWriter();
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc
index e20b355..9e1abf4 100644
--- a/net/socket/client_socket_pool_base.cc
+++ b/net/socket/client_socket_pool_base.cc
@@ -448,7 +448,7 @@
   //   the |idle_socket_it| will be set to the newest used idle socket.
   for (std::list<IdleSocket>::iterator it = idle_sockets->begin();
        it != idle_sockets->end();) {
-    if (!it->socket->IsConnectedAndIdle()) {
+    if (!it->IsUsable()) {
       DecrementIdleCount();
       delete it->socket;
       it = idle_sockets->erase(it);
@@ -648,15 +648,19 @@
   return dict;
 }
 
+bool ClientSocketPoolBaseHelper::IdleSocket::IsUsable() const {
+  if (socket->WasEverUsed())
+    return socket->IsConnectedAndIdle();
+  return socket->IsConnected();
+}
+
 bool ClientSocketPoolBaseHelper::IdleSocket::ShouldCleanup(
     base::TimeTicks now,
     base::TimeDelta timeout) const {
   bool timed_out = (now - start_time) >= timeout;
   if (timed_out)
     return true;
-  if (socket->WasEverUsed())
-    return !socket->IsConnectedAndIdle();
-  return !socket->IsConnected();
+  return !IsUsable();
 }
 
 void ClientSocketPoolBaseHelper::CleanupIdleSockets(bool force) {
diff --git a/net/socket/client_socket_pool_base.h b/net/socket/client_socket_pool_base.h
index 8a0a1f3..8079cd4 100644
--- a/net/socket/client_socket_pool_base.h
+++ b/net/socket/client_socket_pool_base.h
@@ -339,14 +339,19 @@
   struct IdleSocket {
     IdleSocket() : socket(NULL) {}
 
+    // An idle socket can't be used if it is disconnected or has been used
+    // before and has received data unexpectedly (hence no longer idle).  The
+    // unread data would be mistaken for the beginning of the next response if
+    // we were to use the socket for a new request.
+    //
+    // Note that a socket that has never been used before (like a preconnected
+    // socket) may be used even with unread data.  This may be, e.g., a SPDY
+    // SETTINGS frame.
+    bool IsUsable() const;
+
     // An idle socket should be removed if it can't be reused, or has been idle
     // for too long. |now| is the current time value (TimeTicks::Now()).
     // |timeout| is the length of time to wait before timing out an idle socket.
-    //
-    // An idle socket can't be reused if it is disconnected or has received
-    // data unexpectedly (hence no longer idle).  The unread data would be
-    // mistaken for the beginning of the next response if we were to reuse the
-    // socket for a new request.
     bool ShouldCleanup(base::TimeTicks now, base::TimeDelta timeout) const;
 
     StreamSocket* socket;
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 46f4e40..605af72 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -116,14 +116,26 @@
  public:
   explicit MockClientSocket(net::NetLog* net_log)
       : connected_(false),
+        has_unread_data_(false),
         net_log_(BoundNetLog::Make(net_log, net::NetLog::SOURCE_SOCKET)),
         was_used_to_convey_data_(false) {
   }
 
+  // Sets whether the socket has unread data. If true, the next call to Read()
+  // will return 1 byte and IsConnectedAndIdle() will return false.
+  void set_has_unread_data(bool has_unread_data) {
+    has_unread_data_ = has_unread_data;
+  }
+
   // Socket implementation.
   virtual int Read(
       IOBuffer* /* buf */, int len,
       const CompletionCallback& /* callback */) OVERRIDE {
+    if (has_unread_data_ && len > 0) {
+      has_unread_data_ = false;
+      was_used_to_convey_data_ = true;
+      return 1;
+    }
     return ERR_UNEXPECTED;
   }
 
@@ -144,7 +156,9 @@
 
   virtual void Disconnect() OVERRIDE { connected_ = false; }
   virtual bool IsConnected() const OVERRIDE { return connected_; }
-  virtual bool IsConnectedAndIdle() const OVERRIDE { return connected_; }
+  virtual bool IsConnectedAndIdle() const OVERRIDE {
+    return connected_ && !has_unread_data_;
+  }
 
   virtual int GetPeerAddress(IPEndPoint* /* address */) const OVERRIDE {
     return ERR_UNEXPECTED;
@@ -176,6 +190,7 @@
 
  private:
   bool connected_;
+  bool has_unread_data_;
   BoundNetLog net_log_;
   bool was_used_to_convey_data_;
 
@@ -245,6 +260,7 @@
     kMockPendingRecoverableJob,
     kMockAdditionalErrorStateJob,
     kMockPendingAdditionalErrorStateJob,
+    kMockUnreadDataJob,
   };
 
   // The kMockPendingJob uses a slight delay before allowing the connect
@@ -372,6 +388,12 @@
                        false /* recoverable */),
             base::TimeDelta::FromMilliseconds(2));
         return ERR_IO_PENDING;
+      case kMockUnreadDataJob: {
+        int ret = DoConnect(true /* successful */, false /* sync */,
+                            false /* recoverable */);
+        static_cast<MockClientSocket*>(socket())->set_has_unread_data(true);
+        return ret;
+      }
       default:
         NOTREACHED();
         SetSocket(scoped_ptr<StreamSocket>());
@@ -3541,7 +3563,7 @@
 
   ASSERT_EQ(OK, callback1.WaitForResult());
 
-  // Make sure if a preconneced socket is not fully connected when a request
+  // Make sure if a preconnected socket is not fully connected when a request
   // starts, it has a connect start time.
   TestLoadTimingInfoConnectedNotReused(handle1);
   handle1.Reset();
@@ -3720,6 +3742,46 @@
   EXPECT_EQ(1, pool_->NumActiveSocketsInGroup("a"));
 }
 
+// Tests that a preconnect that starts out with unread data can still be used.
+// http://crbug.com/334467
+TEST_F(ClientSocketPoolBaseTest, PreconnectWithUnreadData) {
+  CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
+  connect_job_factory_->set_job_type(TestConnectJob::kMockUnreadDataJob);
+
+  pool_->RequestSockets("a", &params_, 1, BoundNetLog());
+
+  ASSERT_TRUE(pool_->HasGroup("a"));
+  EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
+  EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
+  EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a"));
+
+  // Fail future jobs to be sure that handle receives the preconnected socket
+  // rather than closing it and making a new one.
+  connect_job_factory_->set_job_type(TestConnectJob::kMockFailingJob);
+  ClientSocketHandle handle;
+  TestCompletionCallback callback;
+  EXPECT_EQ(OK, handle.Init("a",
+                             params_,
+                             DEFAULT_PRIORITY,
+                             callback.callback(),
+                             pool_.get(),
+                             BoundNetLog()));
+
+  ASSERT_TRUE(pool_->HasGroup("a"));
+  EXPECT_EQ(0, pool_->NumConnectJobsInGroup("a"));
+  EXPECT_EQ(0, pool_->NumUnassignedConnectJobsInGroup("a"));
+  EXPECT_EQ(0, pool_->IdleSocketCountInGroup("a"));
+
+  // Drain the pending read.
+  EXPECT_EQ(1, handle.socket()->Read(NULL, 1, CompletionCallback()));
+
+  TestLoadTimingInfoConnectedReused(handle);
+  handle.Reset();
+
+  // The socket should be usable now that it's idle again.
+  EXPECT_EQ(1, pool_->IdleSocketCountInGroup("a"));
+}
+
 class MockLayeredPool : public HigherLayeredPool {
  public:
   MockLayeredPool(TestClientSocketPool* pool,
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index 24d6b70..7ade731 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -132,8 +132,7 @@
     // should be the same for all connections, whereas version_max may
     // change for version fallbacks.
     std::string prefix = "ssl/";
-    if (ssl_config_for_origin.version_max !=
-        SSLConfigService::default_version_max()) {
+    if (ssl_config_for_origin.version_max != net::kDefaultSSLVersionMax) {
       switch (ssl_config_for_origin.version_max) {
         case SSL_PROTOCOL_VERSION_TLS1_2:
           prefix = "ssl(max:3.3)/";
diff --git a/net/socket/nss_ssl_util.cc b/net/socket/nss_ssl_util.cc
index 20911d5..7b06854 100644
--- a/net/socket/nss_ssl_util.cc
+++ b/net/socket/nss_ssl_util.cc
@@ -357,12 +357,16 @@
       return ERR_SSL_INAPPROPRIATE_FALLBACK;
 
     default: {
+      const char* err_name = PR_ErrorToName(err);
+      if (err_name == NULL)
+        err_name = "";
       if (IS_SSL_ERROR(err)) {
-        LOG(WARNING) << "Unknown SSL error " << err
+        LOG(WARNING) << "Unknown SSL error " << err << " (" << err_name << ")"
                      << " mapped to net::ERR_SSL_PROTOCOL_ERROR";
         return ERR_SSL_PROTOCOL_ERROR;
       }
-      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
+      LOG(WARNING) << "Unknown error " << err << " (" << err_name << ")"
+                   << " mapped to net::ERR_FAILED";
       return ERR_FAILED;
     }
   }
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc
index 004b67c..777ce0c 100644
--- a/net/socket/socks5_client_socket.cc
+++ b/net/socket/socks5_client_socket.cc
@@ -5,6 +5,7 @@
 #include "net/socket/socks5_client_socket.h"
 
 #include "base/basictypes.h"
+#include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/debug/trace_event.h"
 #include "base/format_macros.h"
@@ -38,6 +39,7 @@
       bytes_sent_(0),
       bytes_received_(0),
       read_header_size(kReadHeaderSize),
+      was_ever_used_(false),
       host_request_info_(req_info),
       net_log_(transport_->socket()->NetLog()) {
 }
@@ -109,11 +111,7 @@
 }
 
 bool SOCKS5ClientSocket::WasEverUsed() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->WasEverUsed();
-  }
-  NOTREACHED();
-  return false;
+  return was_ever_used_;
 }
 
 bool SOCKS5ClientSocket::UsingTCPFastOpen() const {
@@ -156,19 +154,33 @@
   DCHECK(completed_handshake_);
   DCHECK_EQ(STATE_NONE, next_state_);
   DCHECK(user_callback_.is_null());
+  DCHECK(!callback.is_null());
 
-  return transport_->socket()->Read(buf, buf_len, callback);
+  int rv = transport_->socket()->Read(
+      buf, buf_len,
+      base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete,
+                 base::Unretained(this), callback));
+  if (rv > 0)
+    was_ever_used_ = true;
+  return rv;
 }
 
 // Write is called by the transport layer. This can only be done if the
 // SOCKS handshake is complete.
 int SOCKS5ClientSocket::Write(IOBuffer* buf, int buf_len,
-                             const CompletionCallback& callback) {
+                              const CompletionCallback& callback) {
   DCHECK(completed_handshake_);
   DCHECK_EQ(STATE_NONE, next_state_);
   DCHECK(user_callback_.is_null());
+  DCHECK(!callback.is_null());
 
-  return transport_->socket()->Write(buf, buf_len, callback);
+  int rv = transport_->socket()->Write(
+      buf, buf_len,
+      base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete,
+                 base::Unretained(this), callback));
+  if (rv > 0)
+    was_ever_used_ = true;
+  return rv;
 }
 
 bool SOCKS5ClientSocket::SetReceiveBufferSize(int32 size) {
@@ -185,9 +197,7 @@
 
   // Since Run() may result in Read being called,
   // clear user_callback_ up front.
-  CompletionCallback c = user_callback_;
-  user_callback_.Reset();
-  c.Run(result);
+  base::ResetAndReturn(&user_callback_).Run(result);
 }
 
 void SOCKS5ClientSocket::OnIOComplete(int result) {
@@ -199,6 +209,16 @@
   }
 }
 
+void SOCKS5ClientSocket::OnReadWriteComplete(const CompletionCallback& callback,
+                                             int result) {
+  DCHECK_NE(ERR_IO_PENDING, result);
+  DCHECK(!callback.is_null());
+
+  if (result > 0)
+    was_ever_used_ = true;
+  callback.Run(result);
+}
+
 int SOCKS5ClientSocket::DoLoop(int last_io_result) {
   DCHECK_NE(next_state_, STATE_NONE);
   int rv = last_io_result;
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h
index 4521624..75f7531 100644
--- a/net/socket/socks5_client_socket.h
+++ b/net/socket/socks5_client_socket.h
@@ -99,6 +99,7 @@
 
   void DoCallback(int result);
   void OnIOComplete(int result);
+  void OnReadWriteComplete(const CompletionCallback& callback, int result);
 
   int DoLoop(int last_io_result);
   int DoHandshakeRead();
@@ -143,6 +144,8 @@
 
   size_t read_header_size;
 
+  bool was_ever_used_;
+
   HostResolver::RequestInfo host_request_info_;
 
   BoundNetLog net_log_;
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index 6708958..6545092 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -6,6 +6,7 @@
 
 #include "base/basictypes.h"
 #include "base/bind.h"
+#include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/sys_byteorder.h"
 #include "net/base/io_buffer.h"
@@ -65,6 +66,7 @@
       completed_handshake_(false),
       bytes_sent_(0),
       bytes_received_(0),
+      was_ever_used_(false),
       host_resolver_(host_resolver),
       host_request_info_(req_info),
       priority_(priority),
@@ -137,11 +139,7 @@
 }
 
 bool SOCKSClientSocket::WasEverUsed() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->WasEverUsed();
-  }
-  NOTREACHED();
-  return false;
+  return was_ever_used_;
 }
 
 bool SOCKSClientSocket::UsingTCPFastOpen() const {
@@ -184,8 +182,15 @@
   DCHECK(completed_handshake_);
   DCHECK_EQ(STATE_NONE, next_state_);
   DCHECK(user_callback_.is_null());
+  DCHECK(!callback.is_null());
 
-  return transport_->socket()->Read(buf, buf_len, callback);
+  int rv = transport_->socket()->Read(
+      buf, buf_len,
+      base::Bind(&SOCKSClientSocket::OnReadWriteComplete,
+                 base::Unretained(this), callback));
+  if (rv > 0)
+    was_ever_used_ = true;
+  return rv;
 }
 
 // Write is called by the transport layer. This can only be done if the
@@ -195,8 +200,15 @@
   DCHECK(completed_handshake_);
   DCHECK_EQ(STATE_NONE, next_state_);
   DCHECK(user_callback_.is_null());
+  DCHECK(!callback.is_null());
 
-  return transport_->socket()->Write(buf, buf_len, callback);
+  int rv = transport_->socket()->Write(
+      buf, buf_len,
+      base::Bind(&SOCKSClientSocket::OnReadWriteComplete,
+                 base::Unretained(this), callback));
+  if (rv > 0)
+    was_ever_used_ = true;
+  return rv;
 }
 
 bool SOCKSClientSocket::SetReceiveBufferSize(int32 size) {
@@ -213,10 +225,8 @@
 
   // Since Run() may result in Read being called,
   // clear user_callback_ up front.
-  CompletionCallback c = user_callback_;
-  user_callback_.Reset();
   DVLOG(1) << "Finished setting up SOCKS handshake";
-  c.Run(result);
+  base::ResetAndReturn(&user_callback_).Run(result);
 }
 
 void SOCKSClientSocket::OnIOComplete(int result) {
@@ -228,6 +238,16 @@
   }
 }
 
+void SOCKSClientSocket::OnReadWriteComplete(const CompletionCallback& callback,
+                                            int result) {
+  DCHECK_NE(ERR_IO_PENDING, result);
+  DCHECK(!callback.is_null());
+
+  if (result > 0)
+    was_ever_used_ = true;
+  callback.Run(result);
+}
+
 int SOCKSClientSocket::DoLoop(int last_io_result) {
   DCHECK_NE(next_state_, STATE_NONE);
   int rv = last_io_result;
diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h
index d4f058a..be05ce0 100644
--- a/net/socket/socks_client_socket.h
+++ b/net/socket/socks_client_socket.h
@@ -84,6 +84,7 @@
 
   void DoCallback(int result);
   void OnIOComplete(int result);
+  void OnReadWriteComplete(const CompletionCallback& callback, int result);
 
   int DoLoop(int last_io_result);
   int DoResolveHost();
@@ -100,7 +101,7 @@
 
   State next_state_;
 
-  // Stores the callback to the layer above, called on completing Connect().
+  // Stores the callbacks to the layer above, called on completing Connect().
   CompletionCallback user_callback_;
 
   // This IOBuffer is used by the class to read and write
@@ -120,6 +121,9 @@
   size_t bytes_sent_;
   size_t bytes_received_;
 
+  // This becomes true when the socket is used to send or receive data.
+  bool was_ever_used_;
+
   // Used to resolve the hostname to which the SOCKS proxy will connect.
   SingleRequestHostResolver host_resolver_;
   AddressList addresses_;
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index ca5a689..b3c8e0e 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -330,7 +330,6 @@
   std::vector<base::StringPiece> AsStringPieceVector() const;
 
   bool empty() const { return certs_.empty(); }
-  size_t size() const { return certs_.size(); }
 
   CERTCertificate* operator[](size_t index) const {
     DCHECK_LT(index, certs_.size());
@@ -636,9 +635,10 @@
   int Write(IOBuffer* buf, int buf_len, const CompletionCallback& callback);
 
   // Called on the network task runner.
-  bool IsConnected();
-  bool HasPendingAsyncOperation();
-  bool HasUnhandledReceivedData();
+  bool IsConnected() const;
+  bool HasPendingAsyncOperation() const;
+  bool HasUnhandledReceivedData() const;
+  bool WasEverUsed() const;
 
   // Called on the network task runner.
   // Causes the associated SSL/TLS session ID to be added to NSS's session
@@ -841,6 +841,10 @@
   bool nss_waiting_write_;
   bool nss_is_closed_;
 
+  // Set when Read() or Write() successfully reads or writes data to or from the
+  // network.
+  bool was_ever_used_;
+
   ////////////////////////////////////////////////////////////////////////////
   // Members that are ONLY accessed on the NSS task runner:
   ////////////////////////////////////////////////////////////////////////////
@@ -936,6 +940,7 @@
       nss_waiting_read_(false),
       nss_waiting_write_(false),
       nss_is_closed_(false),
+      was_ever_used_(false),
       host_and_port_(host_and_port),
       ssl_config_(ssl_config),
       nss_fd_(NULL),
@@ -1148,8 +1153,11 @@
       return ERR_IO_PENDING;
     } else {
       DCHECK(!nss_waiting_read_);
-      if (rv <= 0)
+      if (rv <= 0) {
         nss_is_closed_ = true;
+      } else {
+        was_ever_used_ = true;
+      }
     }
   }
 
@@ -1202,29 +1210,37 @@
       return ERR_IO_PENDING;
     } else {
       DCHECK(!nss_waiting_write_);
-      if (rv < 0)
+      if (rv < 0) {
         nss_is_closed_ = true;
+      } else if (rv > 0) {
+        was_ever_used_ = true;
+      }
     }
   }
 
   return rv;
 }
 
-bool SSLClientSocketNSS::Core::IsConnected() {
+bool SSLClientSocketNSS::Core::IsConnected() const {
   DCHECK(OnNetworkTaskRunner());
   return !nss_is_closed_;
 }
 
-bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() {
+bool SSLClientSocketNSS::Core::HasPendingAsyncOperation() const {
   DCHECK(OnNetworkTaskRunner());
   return nss_waiting_read_ || nss_waiting_write_;
 }
 
-bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() {
+bool SSLClientSocketNSS::Core::HasUnhandledReceivedData() const {
   DCHECK(OnNetworkTaskRunner());
   return unhandled_buffer_size_ != 0;
 }
 
+bool SSLClientSocketNSS::Core::WasEverUsed() const {
+  DCHECK(OnNetworkTaskRunner());
+  return was_ever_used_;
+}
+
 void SSLClientSocketNSS::Core::CacheSessionIfNecessary() {
   // TODO(rsleevi): This should occur on the NSS task runner, due to the use of
   // nss_fd_. However, it happens on the network task runner in order to match
@@ -2656,16 +2672,22 @@
   DCHECK(OnNetworkTaskRunner());
   DCHECK(nss_waiting_read_);
   nss_waiting_read_ = false;
-  if (result <= 0)
+  if (result <= 0) {
     nss_is_closed_ = true;
+  } else {
+    was_ever_used_ = true;
+  }
 }
 
 void SSLClientSocketNSS::Core::DidNSSWrite(int result) {
   DCHECK(OnNetworkTaskRunner());
   DCHECK(nss_waiting_write_);
   nss_waiting_write_ = false;
-  if (result < 0)
+  if (result < 0) {
     nss_is_closed_ = true;
+  } else if (result > 0) {
+    was_ever_used_ = true;
+  }
 }
 
 void SSLClientSocketNSS::Core::BufferSendComplete(int result) {
@@ -3025,11 +3047,9 @@
 }
 
 bool SSLClientSocketNSS::WasEverUsed() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->WasEverUsed();
-  }
-  NOTREACHED();
-  return false;
+  DCHECK(core_.get());
+
+  return core_->WasEverUsed();
 }
 
 bool SSLClientSocketNSS::UsingTCPFastOpen() const {
@@ -3243,7 +3263,7 @@
 
   SockaddrStorage storage;
   if (!peer_address.ToSockAddr(storage.addr, &storage.addr_len))
-    return ERR_UNEXPECTED;
+    return ERR_ADDRESS_INVALID;
 
   PRNetAddr peername;
   memset(&peername, 0, sizeof(peername));
diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc
index f97c469..ef3b130 100644
--- a/net/socket/ssl_client_socket_openssl.cc
+++ b/net/socket/ssl_client_socket_openssl.cc
@@ -389,7 +389,7 @@
   return *this;
 }
 
-#if defined(USE_OPENSSL)
+#if defined(USE_OPENSSL_CERTS)
 // When OSCertHandle is typedef'ed to X509, this implementation does a short cut
 // to avoid converting back and forth between der and X509 struct.
 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(
@@ -417,7 +417,7 @@
     CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
   }
 }
-#else  // !defined(USE_OPENSSL)
+#else  // !defined(USE_OPENSSL_CERTS)
 void SSLClientSocketOpenSSL::PeerCertificateChain::Reset(
     STACK_OF(X509)* chain) {
   openssl_chain_.reset(NULL);
@@ -455,7 +455,7 @@
     os_chain_ = NULL;
   }
 }
-#endif  // USE_OPENSSL
+#endif  // defined(USE_OPENSSL_CERTS)
 
 // static
 SSLSessionCacheOpenSSL::Config
@@ -471,7 +471,9 @@
   SSLClientSocketOpenSSL::SSLContext* context =
       SSLClientSocketOpenSSL::SSLContext::GetInstance();
   context->session_cache()->Flush();
+#if defined(USE_OPENSSL_CERTS)
   OpenSSLClientKeyStore::GetInstance()->Flush();
+#endif
 }
 
 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
@@ -487,6 +489,7 @@
       transport_write_error_(OK),
       server_cert_chain_(new PeerCertificateChain(NULL)),
       completed_handshake_(false),
+      was_ever_used_(false),
       client_auth_cert_needed_(false),
       cert_verifier_(context.cert_verifier),
       server_bound_cert_service_(context.server_bound_cert_service),
@@ -675,11 +678,7 @@
 }
 
 bool SSLClientSocketOpenSSL::WasEverUsed() const {
-  if (transport_.get() && transport_->socket())
-    return transport_->socket()->WasEverUsed();
-
-  NOTREACHED();
-  return false;
+  return was_ever_used_;
 }
 
 bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
@@ -750,6 +749,8 @@
   if (rv == ERR_IO_PENDING) {
     user_read_callback_ = callback;
   } else {
+    if (rv > 0)
+      was_ever_used_ = true;
     user_read_buf_ = NULL;
     user_read_buf_len_ = 0;
   }
@@ -768,6 +769,8 @@
   if (rv == ERR_IO_PENDING) {
     user_write_callback_ = callback;
   } else {
+    if (rv > 0)
+      was_ever_used_ = true;
     user_write_buf_ = NULL;
     user_write_buf_len_ = 0;
   }
@@ -907,6 +910,8 @@
 void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
   // Since Run may result in Read being called, clear |user_read_callback_|
   // up front.
+  if (rv > 0)
+    was_ever_used_ = true;
   user_read_buf_ = NULL;
   user_read_buf_len_ = 0;
   base::ResetAndReturn(&user_read_callback_).Run(rv);
@@ -915,6 +920,8 @@
 void SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
   // Since Run may result in Write being called, clear |user_write_callback_|
   // up front.
+  if (rv > 0)
+    was_ever_used_ = true;
   user_write_buf_ = NULL;
   user_write_buf_len_ = 0;
   base::ResetAndReturn(&user_write_callback_).Run(rv);
@@ -1414,7 +1421,7 @@
   DCHECK(ssl == ssl_);
   DCHECK(*x509 == NULL);
   DCHECK(*pkey == NULL);
-
+#if defined(USE_OPENSSL_CERTS)
   if (!ssl_config_.send_client_cert) {
     // First pass: we know that a client certificate is needed, but we do not
     // have one at hand.
@@ -1451,6 +1458,10 @@
     }
     LOG(WARNING) << "Client cert found without private key";
   }
+#else  // !defined(USE_OPENSSL_CERTS)
+  // OS handling of client certificates is not yet implemented.
+  NOTIMPLEMENTED();
+#endif  // defined(USE_OPENSSL_CERTS)
 
   // Send no client certificate.
   return 0;
diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h
index 8952fef..6187c72 100644
--- a/net/socket/ssl_client_socket_openssl.h
+++ b/net/socket/ssl_client_socket_openssl.h
@@ -187,6 +187,10 @@
   CertVerifyResult server_cert_verify_result_;
   bool completed_handshake_;
 
+  // Set when Read() or Write() successfully reads or writes data to or from the
+  // network.
+  bool was_ever_used_;
+
   // Stores client authentication information between ClientAuthHandler and
   // GetSSLCertRequestInfo calls.
   bool client_auth_cert_needed_;
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 20ba896..0c6b335 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2127,4 +2127,60 @@
   EXPECT_FALSE(sock->IsConnected());
 }
 
+// Tests that IsConnectedAndIdle and WasEverUsed behave as expected.
+TEST_F(SSLClientSocketTest, ReuseStates) {
+  SpawnedTestServer test_server(SpawnedTestServer::TYPE_HTTPS,
+                                SpawnedTestServer::kLocalhost,
+                                base::FilePath());
+  ASSERT_TRUE(test_server.Start());
+
+  AddressList addr;
+  ASSERT_TRUE(test_server.GetAddressList(&addr));
+
+  TestCompletionCallback callback;
+  scoped_ptr<StreamSocket> transport(
+      new TCPClientSocket(addr, NULL, NetLog::Source()));
+  int rv = transport->Connect(callback.callback());
+  if (rv == ERR_IO_PENDING)
+    rv = callback.WaitForResult();
+  EXPECT_EQ(OK, rv);
+
+  scoped_ptr<SSLClientSocket> sock(CreateSSLClientSocket(
+      transport.Pass(), test_server.host_port_pair(), kDefaultSSLConfig));
+
+  rv = sock->Connect(callback.callback());
+  if (rv == ERR_IO_PENDING)
+    rv = callback.WaitForResult();
+  EXPECT_EQ(OK, rv);
+
+  // The socket was just connected. It should be idle because it is speaking
+  // HTTP. Although the transport has been used for the handshake, WasEverUsed()
+  // returns false.
+  EXPECT_TRUE(sock->IsConnected());
+  EXPECT_TRUE(sock->IsConnectedAndIdle());
+  EXPECT_FALSE(sock->WasEverUsed());
+
+  const char kRequestText[] = "GET / HTTP/1.0\r\n\r\n";
+  const size_t kRequestLen = arraysize(kRequestText) - 1;
+  scoped_refptr<IOBuffer> request_buffer(new IOBuffer(kRequestLen));
+  memcpy(request_buffer->data(), kRequestText, kRequestLen);
+
+  rv = sock->Write(request_buffer.get(), kRequestLen, callback.callback());
+  EXPECT_TRUE(rv >= 0 || rv == ERR_IO_PENDING);
+
+  if (rv == ERR_IO_PENDING)
+    rv = callback.WaitForResult();
+  EXPECT_EQ(static_cast<int>(kRequestLen), rv);
+
+  // The socket has now been used.
+  EXPECT_TRUE(sock->WasEverUsed());
+
+  // TODO(davidben): Read one byte to ensure the test server has responded and
+  // then assert IsConnectedAndIdle is false. This currently doesn't work
+  // because neither SSLClientSocketNSS nor SSLClientSocketOpenSSL check their
+  // SSL implementation's internal buffers. Either call PR_Available and
+  // SSL_pending, although the former isn't actually implemented or perhaps
+  // attempt to read one byte extra.
+}
+
 }  // namespace net
diff --git a/net/socket/stream_listen_socket.cc b/net/socket/stream_listen_socket.cc
index e5232af..d17ce75 100644
--- a/net/socket/stream_listen_socket.cc
+++ b/net/socket/stream_listen_socket.cc
@@ -96,7 +96,7 @@
     return MapSystemError(err);
   }
   if (!address->FromSockAddr(storage.addr, storage.addr_len))
-    return ERR_FAILED;
+    return ERR_ADDRESS_INVALID;
   return OK;
 }
 
diff --git a/net/socket/stream_socket.h b/net/socket/stream_socket.h
index 38eec86..7208810 100644
--- a/net/socket/stream_socket.h
+++ b/net/socket/stream_socket.h
@@ -70,9 +70,9 @@
   virtual void SetSubresourceSpeculation() = 0;
   virtual void SetOmniboxSpeculation() = 0;
 
-  // Returns true if the underlying transport socket ever had any reads or
-  // writes.  StreamSockets layered on top of transport sockets should forward
-  // this call to the transport socket.
+  // Returns true if the socket ever had any reads or writes.  StreamSockets
+  // layered on top of transport sockets should return if their own Read() or
+  // Write() methods had been called, not the underlying transport's.
   virtual bool WasEverUsed() const = 0;
 
   // Returns true if the underlying transport socket is using TCP FastOpen.
diff --git a/net/socket/tcp_socket_libevent.cc b/net/socket/tcp_socket_libevent.cc
index 94d2897..a7022fd 100644
--- a/net/socket/tcp_socket_libevent.cc
+++ b/net/socket/tcp_socket_libevent.cc
@@ -611,9 +611,9 @@
     NOTREACHED();
     if (IGNORE_EINTR(close(new_socket)) < 0)
       PLOG(ERROR) << "close";
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT,
-                                      ERR_ADDRESS_INVALID);
-    return ERR_ADDRESS_INVALID;
+    int net_error = ERR_ADDRESS_INVALID;
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
+    return net_error;
   }
   scoped_ptr<TCPSocketLibevent> tcp_socket(new TCPSocketLibevent(
       net_log_.net_log(), net_log_.source()));
@@ -639,7 +639,7 @@
   if (!use_tcp_fastopen_) {
     SockaddrStorage storage;
     if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len))
-      return ERR_INVALID_ARGUMENT;
+      return ERR_ADDRESS_INVALID;
 
     if (!HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len))) {
       // Connected without waiting!
@@ -825,7 +825,9 @@
   if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
     SockaddrStorage storage;
     if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len)) {
-      errno = EINVAL;
+      // Set errno to EADDRNOTAVAIL so that MapSystemError will map it to
+      // ERR_ADDRESS_INVALID later.
+      errno = EADDRNOTAVAIL;
       return -1;
     }
 
diff --git a/net/socket/tcp_socket_win.cc b/net/socket/tcp_socket_win.cc
index 5f8cd5c..b777f21 100644
--- a/net/socket/tcp_socket_win.cc
+++ b/net/socket/tcp_socket_win.cc
@@ -711,8 +711,9 @@
     NOTREACHED();
     if (closesocket(new_socket) < 0)
       PLOG(ERROR) << "closesocket";
-    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, ERR_FAILED);
-    return ERR_FAILED;
+    int net_error = ERR_ADDRESS_INVALID;
+    net_log_.EndEventWithNetErrorCode(NetLog::TYPE_TCP_ACCEPT, net_error);
+    return net_error;
   }
   scoped_ptr<TCPSocketWin> tcp_socket(new TCPSocketWin(
       net_log_.net_log(), net_log_.source()));
@@ -767,7 +768,7 @@
 
   SockaddrStorage storage;
   if (!peer_address_->ToSockAddr(storage.addr, &storage.addr_len))
-    return ERR_INVALID_ARGUMENT;
+    return ERR_ADDRESS_INVALID;
   if (!connect(socket_, storage.addr, storage.addr_len)) {
     // Connected without waiting!
     //
diff --git a/net/spdy/spdy_http_stream_unittest.cc b/net/spdy/spdy_http_stream_unittest.cc
index 5a58703..2142d58 100644
--- a/net/spdy/spdy_http_stream_unittest.cc
+++ b/net/spdy/spdy_http_stream_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
 #include "base/stl_util.h"
 #include "crypto/ec_private_key.h"
 #include "crypto/ec_signature_creator.h"
@@ -149,6 +150,9 @@
   UploadProgress progress = stream.GetUploadProgress();
   EXPECT_EQ(0u, progress.size());
   EXPECT_EQ(0u, progress.position());
+
+  // Pump the event loop so |reads| is consumed before the function returns.
+  base::RunLoop().RunUntilIdle();
 }
 
 TEST_P(SpdyHttpStreamTest, SendRequest) {
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index c20d89e..5f0e285 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -532,7 +532,7 @@
   net_log_.EndEvent(NetLog::TYPE_SPDY_SESSION);
 }
 
-Error SpdySession::InitializeWithSocket(
+void SpdySession::InitializeWithSocket(
     scoped_ptr<ClientSocketHandle> connection,
     SpdySessionPool* pool,
     bool is_secure,
@@ -593,19 +593,17 @@
       NetLog::TYPE_SPDY_SESSION_INITIALIZED,
       connection_->socket()->NetLog().source().ToEventParametersCallback());
 
-  int error = DoReadLoop(READ_STATE_DO_READ, OK);
-  if (error == ERR_IO_PENDING)
-    error = OK;
-  if (error == OK) {
-    DCHECK_NE(availability_state_, STATE_CLOSED);
-    connection_->AddHigherLayeredPool(this);
-    if (enable_sending_initial_data_)
-      SendInitialData();
-    pool_ = pool;
-  } else {
-    DcheckClosed();
-  }
-  return static_cast<Error>(error);
+  DCHECK_NE(availability_state_, STATE_CLOSED);
+  connection_->AddHigherLayeredPool(this);
+  if (enable_sending_initial_data_)
+    SendInitialData();
+  pool_ = pool;
+
+  // Bootstrap the read loop.
+  base::MessageLoop::current()->PostTask(
+      FROM_HERE,
+      base::Bind(&SpdySession::PumpReadLoop,
+                 weak_factory_.GetWeakPtr(), READ_STATE_DO_READ, OK));
 }
 
 bool SpdySession::VerifyDomainAuthentication(const std::string& domain) {
@@ -1554,9 +1552,8 @@
   UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SpdySession.BytesRead.OtherErrors",
                               total_bytes_received_, 1, 100000000, 50);
 
-  // |pool_| will be NULL when |InitializeWithSocket()| is in the
-  // call stack.
-  if (pool_ && availability_state_ != STATE_GOING_AWAY)
+  DCHECK(pool_);
+  if (availability_state_ != STATE_GOING_AWAY)
     pool_->MakeSessionUnavailable(GetWeakPtr());
 
   availability_state_ = STATE_CLOSED;
@@ -1628,10 +1625,8 @@
 void SpdySession::MakeUnavailable() {
   if (availability_state_ < STATE_GOING_AWAY) {
     availability_state_ = STATE_GOING_AWAY;
-    // |pool_| will be NULL when |InitializeWithSocket()| is in the
-    // call stack.
-    if (pool_)
-      pool_->MakeSessionUnavailable(GetWeakPtr());
+    DCHECK(pool_);
+    pool_->MakeSessionUnavailable(GetWeakPtr());
   }
 }
 
@@ -1686,7 +1681,8 @@
 }
 
 bool SpdySession::IsReused() const {
-  return buffered_spdy_framer_->frames_received() > 0;
+  return buffered_spdy_framer_->frames_received() > 0 ||
+      connection_->reuse_type() == ClientSocketHandle::UNUSED_IDLE;
 }
 
 bool SpdySession::GetLoadTimingInfo(SpdyStreamId stream_id,
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index cbb87bf..203f1ef 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -256,13 +256,13 @@
   // |certificate_error_code| must either be OK or less than
   // ERR_IO_PENDING.
   //
-  // Returns OK on success, or an error on failure. Never returns
-  // ERR_IO_PENDING. If an error is returned, the session must be
-  // destroyed immediately.
-  Error InitializeWithSocket(scoped_ptr<ClientSocketHandle> connection,
-                             SpdySessionPool* pool,
-                             bool is_secure,
-                             int certificate_error_code);
+  // The session begins reading from |connection| on a subsequent event loop
+  // iteration, so the SpdySession may close immediately afterwards if the first
+  // read of |connection| fails.
+  void InitializeWithSocket(scoped_ptr<ClientSocketHandle> connection,
+                            SpdySessionPool* pool,
+                            bool is_secure,
+                            int certificate_error_code);
 
   // Returns the protocol used by this session. Always between
   // kProtoSPDYMinimumVersion and kProtoSPDYMaximumVersion.
@@ -367,7 +367,8 @@
   base::Value* GetInfoAsValue() const;
 
   // Indicates whether the session is being reused after having successfully
-  // used to send/receive data in the past.
+  // used to send/receive data in the past or if the underlying socket was idle
+  // before being used for a SPDY session.
   bool IsReused() const;
 
   // Returns true if the underlying transport socket ever had any reads or
@@ -617,8 +618,7 @@
   // Advance the ReadState state machine. |expected_read_state| is the
   // expected starting read state.
   //
-  // This function must always be called via PumpReadLoop() except for
-  // from InitializeWithSocket().
+  // This function must always be called via PumpReadLoop().
   int DoReadLoop(ReadState expected_read_state, int result);
   // The implementations of the states of the ReadState state machine.
   int DoRead();
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index 093db1e..6ce0a93 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -77,12 +77,11 @@
   CertDatabase::GetInstance()->RemoveObserver(this);
 }
 
-net::Error SpdySessionPool::CreateAvailableSessionFromSocket(
+base::WeakPtr<SpdySession> SpdySessionPool::CreateAvailableSessionFromSocket(
     const SpdySessionKey& key,
     scoped_ptr<ClientSocketHandle> connection,
     const BoundNetLog& net_log,
     int certificate_error_code,
-    base::WeakPtr<SpdySession>* available_session,
     bool is_secure) {
   DCHECK_GE(default_protocol_, kProtoSPDYMinimumVersion);
   DCHECK_LE(default_protocol_, kProtoSPDYMaximumVersion);
@@ -105,22 +104,16 @@
                       trusted_spdy_proxy_,
                       net_log.net_log()));
 
-  Error error =  new_session->InitializeWithSocket(
+  new_session->InitializeWithSocket(
       connection.Pass(), this, is_secure, certificate_error_code);
-  DCHECK_NE(error, ERR_IO_PENDING);
 
-  if (error != OK) {
-    available_session->reset();
-    return error;
-  }
-
-  *available_session = new_session->GetWeakPtr();
+  base::WeakPtr<SpdySession> available_session = new_session->GetWeakPtr();
   sessions_.insert(new_session.release());
-  MapKeyToAvailableSession(key, *available_session);
+  MapKeyToAvailableSession(key, available_session);
 
   net_log.AddEvent(
       NetLog::TYPE_SPDY_SESSION_POOL_IMPORTED_SESSION_FROM_SOCKET,
-      (*available_session)->net_log().source().ToEventParametersCallback());
+      available_session->net_log().source().ToEventParametersCallback());
 
   // Look up the IP address for this session so that we can match
   // future sessions (potentially to different domains) which can
@@ -129,11 +122,11 @@
   // to see if this is a direct connection.
   if (key.proxy_server().is_direct()) {
     IPEndPoint address;
-    if ((*available_session)->GetPeerAddress(&address) == OK)
+    if (available_session->GetPeerAddress(&address) == OK)
       aliases_[address] = key;
   }
 
-  return error;
+  return available_session;
 }
 
 base::WeakPtr<SpdySession> SpdySessionPool::FindAvailableSession(
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index c44e9de..0fad5d2 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -79,15 +79,14 @@
   // encountered when connecting the SSL socket, with OK meaning there
   // was no error.
   //
-  // If successful, OK is returned and |available_session| will be
-  // non-NULL and available. Otherwise, an error is returned and
-  // |available_session| will be NULL.
-  net::Error CreateAvailableSessionFromSocket(
+  // Returns the new SpdySession. Note that the SpdySession begins reading from
+  // |connection| on a subsequent event loop iteration, so it may be closed
+  // immediately afterwards if the first read of |connection| fails.
+  base::WeakPtr<SpdySession> CreateAvailableSessionFromSocket(
       const SpdySessionKey& key,
       scoped_ptr<ClientSocketHandle> connection,
       const BoundNetLog& net_log,
       int certificate_error_code,
-      base::WeakPtr<SpdySession>* available_session,
       bool is_secure);
 
   // Find an available session for the given key, or NULL if there isn't one.
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 0e8b370..a5d9292 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -190,8 +190,12 @@
 TEST_P(SpdySessionTest, InitialReadError) {
   CreateDeterministicNetworkSession();
 
-  TryCreateFakeSpdySessionExpectingFailure(
+  base::WeakPtr<SpdySession> session = TryCreateFakeSpdySessionExpectingFailure(
       spdy_session_pool_, key_, ERR_FAILED);
+  EXPECT_TRUE(session);
+  // Flush the read.
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(session);
 }
 
 namespace {
@@ -277,8 +281,6 @@
   session->CloseSessionOnError(ERR_ABORTED, "Aborting session");
 
   EXPECT_EQ(ERR_ABORTED, callback1.WaitForResult());
-
-  data.RunFor(1);
 }
 
 // A session receiving a GOAWAY frame with no active streams should
@@ -330,9 +332,12 @@
 
   data.StopAfter(1);
 
-  TryCreateInsecureSpdySessionExpectingFailure(
-      http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
+  base::WeakPtr<SpdySession> session =
+      TryCreateInsecureSpdySessionExpectingFailure(
+          http_session_, key_, ERR_CONNECTION_CLOSED, BoundNetLog());
+  base::RunLoop().RunUntilIdle();
 
+  EXPECT_FALSE(session);
   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
 }
 
@@ -1045,8 +1050,6 @@
 
   EXPECT_TRUE(session == NULL);
   EXPECT_FALSE(HasSpdySession(spdy_session_pool_, key_));
-
-  data.RunFor(1);
   EXPECT_EQ(NULL, spdy_stream1.get());
 }
 
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index ce9ddd3..3988905 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -103,7 +103,8 @@
       net_log_(net_log),
       raw_received_bytes_(0),
       send_bytes_(0),
-      recv_bytes_(0) {
+      recv_bytes_(0),
+      write_handler_guard_(false) {
   CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM ||
         type_ == SPDY_REQUEST_RESPONSE_STREAM ||
         type_ == SPDY_PUSH_STREAM);
@@ -112,6 +113,7 @@
 }
 
 SpdyStream::~SpdyStream() {
+  CHECK(!write_handler_guard_);
   UpdateHistograms();
 }
 
@@ -457,7 +459,6 @@
   // PushedStreamReplayData().
   if (io_state_ == STATE_HALF_CLOSED_LOCAL_UNCLAIMED) {
     DCHECK_EQ(type_, SPDY_PUSH_STREAM);
-    CHECK(!delegate_);
     // It should be valid for this to happen in the server push case.
     // We'll return received data when delegate gets attached to the stream.
     if (buffer) {
@@ -545,12 +546,14 @@
   CHECK(delegate_);
   {
     base::WeakPtr<SpdyStream> weak_this = GetWeakPtr();
+    write_handler_guard_ = true;
     if (frame_type == SYN_STREAM) {
       delegate_->OnRequestHeadersSent();
     } else {
       delegate_->OnDataSent();
     }
     CHECK(weak_this);
+    write_handler_guard_ = false;
   }
 
   if (io_state_ == STATE_CLOSED) {
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h
index a8cc7dc..4e3c61a 100644
--- a/net/spdy/spdy_stream.h
+++ b/net/spdy/spdy_stream.h
@@ -557,6 +557,11 @@
   std::string domain_bound_cert_;
   ServerBoundCertService::RequestHandle domain_bound_cert_request_handle_;
 
+  // Guards calls of delegate write handlers ensuring |this| is not destroyed.
+  // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked
+  // down.
+  bool write_handler_guard_;
+
   DISALLOW_COPY_AND_ASSIGN(SpdyStream);
 };
 
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 66a6f8c..22ff5f6 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -540,15 +540,12 @@
 
   EXPECT_EQ(OK, rv);
 
-  base::WeakPtr<SpdySession> spdy_session;
-  EXPECT_EQ(
-      expected_status,
+  base::WeakPtr<SpdySession> spdy_session =
       http_session->spdy_session_pool()->CreateAvailableSessionFromSocket(
-          key, connection.Pass(), net_log, OK, &spdy_session,
-          is_secure));
-  EXPECT_EQ(expected_status == OK, spdy_session != NULL);
-  EXPECT_EQ(expected_status == OK,
-            HasSpdySession(http_session->spdy_session_pool(), key));
+          key, connection.Pass(), net_log, OK, is_secure);
+  // Failure is reported asynchronously.
+  EXPECT_TRUE(spdy_session != NULL);
+  EXPECT_TRUE(HasSpdySession(http_session->spdy_session_pool(), key));
   return spdy_session;
 }
 
@@ -562,14 +559,14 @@
                                  OK, false /* is_secure */);
 }
 
-void TryCreateInsecureSpdySessionExpectingFailure(
+base::WeakPtr<SpdySession> TryCreateInsecureSpdySessionExpectingFailure(
     const scoped_refptr<HttpNetworkSession>& http_session,
     const SpdySessionKey& key,
     Error expected_error,
     const BoundNetLog& net_log) {
   DCHECK_LT(expected_error, ERR_IO_PENDING);
-  CreateSpdySessionHelper(http_session, key, net_log,
-                          expected_error, false /* is_secure */);
+  return CreateSpdySessionHelper(http_session, key, net_log,
+                                 expected_error, false /* is_secure */);
 }
 
 base::WeakPtr<SpdySession> CreateSecureSpdySession(
@@ -643,17 +640,15 @@
     Error expected_status) {
   EXPECT_NE(expected_status, ERR_IO_PENDING);
   EXPECT_FALSE(HasSpdySession(pool, key));
-  base::WeakPtr<SpdySession> spdy_session;
   scoped_ptr<ClientSocketHandle> handle(new ClientSocketHandle());
   handle->SetSocket(scoped_ptr<StreamSocket>(new FakeSpdySessionClientSocket(
       expected_status == OK ? ERR_IO_PENDING : expected_status)));
-  EXPECT_EQ(
-      expected_status,
+  base::WeakPtr<SpdySession> spdy_session =
       pool->CreateAvailableSessionFromSocket(
-          key, handle.Pass(), BoundNetLog(), OK, &spdy_session,
-          true /* is_secure */));
-  EXPECT_EQ(expected_status == OK, spdy_session != NULL);
-  EXPECT_EQ(expected_status == OK, HasSpdySession(pool, key));
+          key, handle.Pass(), BoundNetLog(), OK, true /* is_secure */);
+  // Failure is reported asynchronously.
+  EXPECT_TRUE(spdy_session != NULL);
+  EXPECT_TRUE(HasSpdySession(pool, key));
   return spdy_session;
 }
 
@@ -664,11 +659,12 @@
   return CreateFakeSpdySessionHelper(pool, key, OK);
 }
 
-void TryCreateFakeSpdySessionExpectingFailure(SpdySessionPool* pool,
-                                              const SpdySessionKey& key,
-                                              Error expected_error) {
+base::WeakPtr<SpdySession> TryCreateFakeSpdySessionExpectingFailure(
+    SpdySessionPool* pool,
+    const SpdySessionKey& key,
+    Error expected_error) {
   DCHECK_LT(expected_error, ERR_IO_PENDING);
-  CreateFakeSpdySessionHelper(pool, key, expected_error);
+  return CreateFakeSpdySessionHelper(pool, key, expected_error);
 }
 
 SpdySessionPoolPeer::SpdySessionPoolPeer(SpdySessionPool* pool) : pool_(pool) {
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index 42b595b..668a7e8 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -247,8 +247,9 @@
 
 // Tries to create a SPDY session for the given key but expects the
 // attempt to fail with the given error. A SPDY session for |key| must
-// not already exist.
-void TryCreateInsecureSpdySessionExpectingFailure(
+// not already exist. The session will be created but close in the
+// next event loop iteration.
+base::WeakPtr<SpdySession> TryCreateInsecureSpdySessionExpectingFailure(
     const scoped_refptr<HttpNetworkSession>& http_session,
     const SpdySessionKey& key,
     Error expected_error,
@@ -269,10 +270,12 @@
 // Tries to create an insecure SPDY session for the given key but
 // expects the attempt to fail with the given error. The session will
 // neither receive nor send any data. A SPDY session for |key| must
-// not already exist.
-void TryCreateFakeSpdySessionExpectingFailure(SpdySessionPool* pool,
-                                              const SpdySessionKey& key,
-                                              Error expected_error);
+// not already exist. The session will be created but close in the
+// next event loop iteration.
+base::WeakPtr<SpdySession> TryCreateFakeSpdySessionExpectingFailure(
+    SpdySessionPool* pool,
+    const SpdySessionKey& key,
+    Error expected_error);
 
 class SpdySessionPoolPeer {
  public:
diff --git a/net/ssl/server_bound_cert_service_unittest.cc b/net/ssl/server_bound_cert_service_unittest.cc
index 4df0039..2be073b 100644
--- a/net/ssl/server_bound_cert_service_unittest.cc
+++ b/net/ssl/server_bound_cert_service_unittest.cc
@@ -24,7 +24,6 @@
 
 namespace {
 
-#if !defined(USE_OPENSSL)
 void FailTest(int /* result */) {
   FAIL();
 }
@@ -117,8 +116,6 @@
                                                     cert));
 }
 
-#endif  // !defined(USE_OPENSSL)
-
 class ServerBoundCertServiceTest : public testing::Test {
  public:
   ServerBoundCertServiceTest()
@@ -150,9 +147,6 @@
             ServerBoundCertService::GetDomainForHost("127.0.0.1"));
 }
 
-// See http://crbug.com/91512 - implement OpenSSL version of CreateSelfSigned.
-#if !defined(USE_OPENSSL)
-
 TEST_F(ServerBoundCertServiceTest, GetCacheMiss) {
   std::string host("encrypted.google.com");
 
@@ -775,8 +769,6 @@
   EXPECT_FALSE(request_handle2.is_active());
 }
 
-#endif  // !defined(USE_OPENSSL)
-
 }  // namespace
 
 }  // namespace net
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc
new file mode 100644
index 0000000..0282991
--- /dev/null
+++ b/net/ssl/ssl_config.cc
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/ssl/ssl_config.h"
+
+#if defined(USE_OPENSSL)
+#include <openssl/ssl.h>
+#endif
+
+namespace net {
+
+const uint16 kDefaultSSLVersionMin = SSL_PROTOCOL_VERSION_SSL3;
+
+const uint16 kDefaultSSLVersionMax =
+#if defined(USE_OPENSSL)
+#if defined(SSL_OP_NO_TLSv1_2)
+    SSL_PROTOCOL_VERSION_TLS1_2;
+#elif defined(SSL_OP_NO_TLSv1_1)
+    SSL_PROTOCOL_VERSION_TLS1_1;
+#else
+    SSL_PROTOCOL_VERSION_TLS1;
+#endif
+#else
+    SSL_PROTOCOL_VERSION_TLS1_2;
+#endif
+
+SSLConfig::CertAndStatus::CertAndStatus() : cert_status(0) {}
+
+SSLConfig::CertAndStatus::~CertAndStatus() {}
+
+SSLConfig::SSLConfig()
+    : rev_checking_enabled(false),
+      rev_checking_required_local_anchors(false),
+      version_min(kDefaultSSLVersionMin),
+      version_max(kDefaultSSLVersionMax),
+      channel_id_enabled(true),
+      false_start_enabled(true),
+      signed_cert_timestamps_enabled(true),
+      require_forward_secrecy(false),
+      send_client_cert(false),
+      verify_ev_cert(false),
+      version_fallback(false),
+      cert_io_enabled(true) {
+}
+
+SSLConfig::~SSLConfig() {}
+
+bool SSLConfig::IsAllowedBadCert(X509Certificate* cert,
+                                 CertStatus* cert_status) const {
+  std::string der_cert;
+  if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_cert))
+    return false;
+  return IsAllowedBadCert(der_cert, cert_status);
+}
+
+bool SSLConfig::IsAllowedBadCert(const base::StringPiece& der_cert,
+                                 CertStatus* cert_status) const {
+  for (size_t i = 0; i < allowed_bad_certs.size(); ++i) {
+    if (der_cert == allowed_bad_certs[i].der_cert) {
+      if (cert_status)
+        *cert_status = allowed_bad_certs[i].cert_status;
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace net
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h
new file mode 100644
index 0000000..2731214
--- /dev/null
+++ b/net/ssl/ssl_config.h
@@ -0,0 +1,156 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_SSL_SSL_CONFIG_H_
+#define NET_SSL_SSL_CONFIG_H_
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "net/base/net_export.h"
+#include "net/cert/x509_certificate.h"
+
+namespace net {
+
+// Various TLS/SSL ProtocolVersion values encoded as uint16
+//      struct {
+//          uint8 major;
+//          uint8 minor;
+//      } ProtocolVersion;
+// The most significant byte is |major|, and the least significant byte
+// is |minor|.
+enum {
+  SSL_PROTOCOL_VERSION_SSL3 = 0x0300,
+  SSL_PROTOCOL_VERSION_TLS1 = 0x0301,
+  SSL_PROTOCOL_VERSION_TLS1_1 = 0x0302,
+  SSL_PROTOCOL_VERSION_TLS1_2 = 0x0303,
+};
+
+// Default minimum protocol version.
+NET_EXPORT extern const uint16 kDefaultSSLVersionMin;
+
+// Default maximum protocol version.
+NET_EXPORT extern const uint16 kDefaultSSLVersionMax;
+
+// A collection of SSL-related configuration settings.
+struct NET_EXPORT SSLConfig {
+  // Default to revocation checking.
+  // Default to SSL 3.0 ~ default_version_max() on.
+  SSLConfig();
+  ~SSLConfig();
+
+  // Returns true if |cert| is one of the certs in |allowed_bad_certs|.
+  // The expected cert status is written to |cert_status|. |*cert_status| can
+  // be NULL if user doesn't care about the cert status.
+  bool IsAllowedBadCert(X509Certificate* cert, CertStatus* cert_status) const;
+
+  // Same as above except works with DER encoded certificates instead
+  // of X509Certificate.
+  bool IsAllowedBadCert(const base::StringPiece& der_cert,
+                        CertStatus* cert_status) const;
+
+  // rev_checking_enabled is true if online certificate revocation checking is
+  // enabled (i.e. OCSP and CRL fetching).
+  //
+  // Regardless of this flag, CRLSet checking is always enabled and locally
+  // cached revocation information will be considered.
+  bool rev_checking_enabled;
+
+  // rev_checking_required_local_anchors is true if revocation checking is
+  // required to succeed when certificates chain to local trust anchors (that
+  // is, non-public CAs). If revocation information cannot be obtained, such
+  // certificates will be treated as revoked ("hard-fail").
+  // Note: This is distinct from rev_checking_enabled. If true, it is
+  // equivalent to also setting rev_checking_enabled, but only when the
+  // certificate chain chains to a local (non-public) trust anchor.
+  bool rev_checking_required_local_anchors;
+
+  // The minimum and maximum protocol versions that are enabled.
+  // SSL 3.0 is 0x0300, TLS 1.0 is 0x0301, TLS 1.1 is 0x0302, and so on.
+  // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined above.)
+  // SSL 2.0 is not supported. If version_max < version_min, it means no
+  // protocol versions are enabled.
+  uint16 version_min;
+  uint16 version_max;
+
+  // Presorted list of cipher suites which should be explicitly prevented from
+  // being used in addition to those disabled by the net built-in policy.
+  //
+  // By default, all cipher suites supported by the underlying SSL
+  // implementation will be enabled except for:
+  // - Null encryption cipher suites.
+  // - Weak cipher suites: < 80 bits of security strength.
+  // - FORTEZZA cipher suites (obsolete).
+  // - IDEA cipher suites (RFC 5469 explains why).
+  // - Anonymous cipher suites.
+  // - ECDSA cipher suites on platforms that do not support ECDSA signed
+  //   certificates, as servers may use the presence of such ciphersuites as a
+  //   hint to send an ECDSA certificate.
+  // The ciphers listed in |disabled_cipher_suites| will be removed in addition
+  // to the above list.
+  //
+  // Though cipher suites are sent in TLS as "uint8 CipherSuite[2]", in
+  // big-endian form, they should be declared in host byte order, with the
+  // first uint8 occupying the most significant byte.
+  // Ex: To disable TLS_RSA_WITH_RC4_128_MD5, specify 0x0004, while to
+  // disable TLS_ECDH_ECDSA_WITH_RC4_128_SHA, specify 0xC002.
+  std::vector<uint16> disabled_cipher_suites;
+
+  bool channel_id_enabled;   // True if TLS channel ID extension is enabled.
+  bool false_start_enabled;  // True if we'll use TLS False Start.
+  // True if the Certificate Transparency signed_certificate_timestamp
+  // TLS extension is enabled.
+  bool signed_cert_timestamps_enabled;
+
+  // require_forward_secrecy, if true, causes only (EC)DHE cipher suites to be
+  // enabled. NOTE: this only applies to server sockets currently, although
+  // that could be extended if needed.
+  bool require_forward_secrecy;
+
+  // TODO(wtc): move the following members to a new SSLParams structure.  They
+  // are not SSL configuration settings.
+
+  struct NET_EXPORT CertAndStatus {
+    CertAndStatus();
+    ~CertAndStatus();
+
+    std::string der_cert;
+    CertStatus cert_status;
+  };
+
+  // Add any known-bad SSL certificate (with its cert status) to
+  // |allowed_bad_certs| that should not trigger an ERR_CERT_* error when
+  // calling SSLClientSocket::Connect.  This would normally be done in
+  // response to the user explicitly accepting the bad certificate.
+  std::vector<CertAndStatus> allowed_bad_certs;
+
+  // True if we should send client_cert to the server.
+  bool send_client_cert;
+
+  bool verify_ev_cert;  // True if we should verify the certificate for EV.
+
+  bool version_fallback;  // True if we are falling back to an older protocol
+                          // version (one still needs to decrement
+                          // version_max).
+
+  // If cert_io_enabled is false, then certificate verification will not
+  // result in additional HTTP requests. (For example: to fetch missing
+  // intermediates or to perform OCSP/CRL fetches.) It also implies that online
+  // revocation checking is disabled.
+  // NOTE: Only used by NSS.
+  bool cert_io_enabled;
+
+  // The list of application level protocols supported. If set, this will
+  // enable Next Protocol Negotiation (if supported). The order of the
+  // protocols doesn't matter expect for one case: if the server supports Next
+  // Protocol Negotiation, but there is no overlap between the server's and
+  // client's protocol sets, then the first protocol in this list will be
+  // requested by the client.
+  std::vector<std::string> next_protos;
+
+  scoped_refptr<X509Certificate> client_cert;
+};
+
+}  // namespace net
+
+#endif  // NET_SSL_SSL_CONFIG_H_
diff --git a/net/ssl/ssl_config_service.cc b/net/ssl/ssl_config_service.cc
index ec9fcc3..cd2a00d 100644
--- a/net/ssl/ssl_config_service.cc
+++ b/net/ssl/ssl_config_service.cc
@@ -5,75 +5,11 @@
 #include "net/ssl/ssl_config_service.h"
 
 #include "base/lazy_instance.h"
-#include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
-#include "net/cert/crl_set.h"
 #include "net/ssl/ssl_config_service_defaults.h"
 
-#if defined(USE_OPENSSL)
-#include <openssl/ssl.h>
-#endif
-
 namespace net {
 
-static uint16 g_default_version_min = SSL_PROTOCOL_VERSION_SSL3;
-
-static uint16 g_default_version_max =
-#if defined(USE_OPENSSL)
-#if defined(SSL_OP_NO_TLSv1_2)
-    SSL_PROTOCOL_VERSION_TLS1_2;
-#elif defined(SSL_OP_NO_TLSv1_1)
-    SSL_PROTOCOL_VERSION_TLS1_1;
-#else
-    SSL_PROTOCOL_VERSION_TLS1;
-#endif
-#else
-    SSL_PROTOCOL_VERSION_TLS1_2;
-#endif
-
-SSLConfig::CertAndStatus::CertAndStatus() : cert_status(0) {}
-
-SSLConfig::CertAndStatus::~CertAndStatus() {}
-
-SSLConfig::SSLConfig()
-    : rev_checking_enabled(false),
-      rev_checking_required_local_anchors(false),
-      version_min(g_default_version_min),
-      version_max(g_default_version_max),
-      channel_id_enabled(true),
-      false_start_enabled(true),
-      signed_cert_timestamps_enabled(true),
-      require_forward_secrecy(false),
-      unrestricted_ssl3_fallback_enabled(false),
-      send_client_cert(false),
-      verify_ev_cert(false),
-      version_fallback(false),
-      cert_io_enabled(true) {
-}
-
-SSLConfig::~SSLConfig() {
-}
-
-bool SSLConfig::IsAllowedBadCert(X509Certificate* cert,
-                                 CertStatus* cert_status) const {
-  std::string der_cert;
-  if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_cert))
-    return false;
-  return IsAllowedBadCert(der_cert, cert_status);
-}
-
-bool SSLConfig::IsAllowedBadCert(const base::StringPiece& der_cert,
-                                 CertStatus* cert_status) const {
-  for (size_t i = 0; i < allowed_bad_certs.size(); ++i) {
-    if (der_cert == allowed_bad_certs[i].der_cert) {
-      if (cert_status)
-        *cert_status = allowed_bad_certs[i].cert_status;
-      return true;
-    }
-  }
-  return false;
-}
-
 SSLConfigService::SSLConfigService()
     : observer_list_(ObserverList<Observer>::NOTIFY_EXISTING_ONLY) {
 }
@@ -111,16 +47,6 @@
   return g_crl_set.Get().Get();
 }
 
-// static
-uint16 SSLConfigService::default_version_min() {
-  return g_default_version_min;
-}
-
-// static
-uint16 SSLConfigService::default_version_max() {
-  return g_default_version_max;
-}
-
 void SSLConfigService::AddObserver(Observer* observer) {
   observer_list_.AddObserver(observer);
 }
@@ -149,9 +75,7 @@
       (orig_config.channel_id_enabled != new_config.channel_id_enabled) ||
       (orig_config.false_start_enabled != new_config.false_start_enabled) ||
       (orig_config.require_forward_secrecy !=
-       new_config.require_forward_secrecy) ||
-      (orig_config.unrestricted_ssl3_fallback_enabled !=
-       new_config.unrestricted_ssl3_fallback_enabled);
+       new_config.require_forward_secrecy);
 
   if (config_changed)
     NotifySSLConfigChange();
diff --git a/net/ssl/ssl_config_service.h b/net/ssl/ssl_config_service.h
index 08a59fd..d654722 100644
--- a/net/ssl/ssl_config_service.h
+++ b/net/ssl/ssl_config_service.h
@@ -7,157 +7,14 @@
 
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/observer_list.h"
-#include "base/strings/string_piece.h"
 #include "net/base/net_export.h"
-#include "net/cert/cert_status_flags.h"
 #include "net/cert/crl_set.h"
-#include "net/cert/x509_certificate.h"
+#include "net/ssl/ssl_config.h"
 
 namespace net {
 
-// Various TLS/SSL ProtocolVersion values encoded as uint16
-//      struct {
-//          uint8 major;
-//          uint8 minor;
-//      } ProtocolVersion;
-// The most significant byte is |major|, and the least significant byte
-// is |minor|.
-enum {
-  SSL_PROTOCOL_VERSION_SSL3 = 0x0300,
-  SSL_PROTOCOL_VERSION_TLS1 = 0x0301,
-  SSL_PROTOCOL_VERSION_TLS1_1 = 0x0302,
-  SSL_PROTOCOL_VERSION_TLS1_2 = 0x0303,
-};
-
-// A collection of SSL-related configuration settings.
-struct NET_EXPORT SSLConfig {
-  // Default to revocation checking.
-  // Default to SSL 3.0 ~ default_version_max() on.
-  SSLConfig();
-  ~SSLConfig();
-
-  // Returns true if |cert| is one of the certs in |allowed_bad_certs|.
-  // The expected cert status is written to |cert_status|. |*cert_status| can
-  // be NULL if user doesn't care about the cert status.
-  bool IsAllowedBadCert(X509Certificate* cert, CertStatus* cert_status) const;
-
-  // Same as above except works with DER encoded certificates instead
-  // of X509Certificate.
-  bool IsAllowedBadCert(const base::StringPiece& der_cert,
-                        CertStatus* cert_status) const;
-
-  // rev_checking_enabled is true if online certificate revocation checking is
-  // enabled (i.e. OCSP and CRL fetching).
-  //
-  // Regardless of this flag, CRLSet checking is always enabled and locally
-  // cached revocation information will be considered.
-  bool rev_checking_enabled;
-
-  // rev_checking_required_local_anchors is true if revocation checking is
-  // required to succeed when certificates chain to local trust anchors (that
-  // is, non-public CAs). If revocation information cannot be obtained, such
-  // certificates will be treated as revoked ("hard-fail").
-  // Note: This is distinct from rev_checking_enabled. If true, it is
-  // equivalent to also setting rev_checking_enabled, but only when the
-  // certificate chain chains to a local (non-public) trust anchor.
-  bool rev_checking_required_local_anchors;
-
-  // The minimum and maximum protocol versions that are enabled.
-  // SSL 3.0 is 0x0300, TLS 1.0 is 0x0301, TLS 1.1 is 0x0302, and so on.
-  // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined above.)
-  // SSL 2.0 is not supported. If version_max < version_min, it means no
-  // protocol versions are enabled.
-  uint16 version_min;
-  uint16 version_max;
-
-  // Presorted list of cipher suites which should be explicitly prevented from
-  // being used in addition to those disabled by the net built-in policy.
-  //
-  // By default, all cipher suites supported by the underlying SSL
-  // implementation will be enabled except for:
-  // - Null encryption cipher suites.
-  // - Weak cipher suites: < 80 bits of security strength.
-  // - FORTEZZA cipher suites (obsolete).
-  // - IDEA cipher suites (RFC 5469 explains why).
-  // - Anonymous cipher suites.
-  // - ECDSA cipher suites on platforms that do not support ECDSA signed
-  //   certificates, as servers may use the presence of such ciphersuites as a
-  //   hint to send an ECDSA certificate.
-  // The ciphers listed in |disabled_cipher_suites| will be removed in addition
-  // to the above list.
-  //
-  // Though cipher suites are sent in TLS as "uint8 CipherSuite[2]", in
-  // big-endian form, they should be declared in host byte order, with the
-  // first uint8 occupying the most significant byte.
-  // Ex: To disable TLS_RSA_WITH_RC4_128_MD5, specify 0x0004, while to
-  // disable TLS_ECDH_ECDSA_WITH_RC4_128_SHA, specify 0xC002.
-  std::vector<uint16> disabled_cipher_suites;
-
-  bool channel_id_enabled;   // True if TLS channel ID extension is enabled.
-  bool false_start_enabled;  // True if we'll use TLS False Start.
-  // True if the Certificate Transparency signed_certificate_timestamp
-  // TLS extension is enabled.
-  bool signed_cert_timestamps_enabled;
-
-  // require_forward_secrecy, if true, causes only (EC)DHE cipher suites to be
-  // enabled. NOTE: this only applies to server sockets currently, although
-  // that could be extended if needed.
-  bool require_forward_secrecy;
-
-  // If |unrestricted_ssl3_fallback_enabled| is true, SSL 3.0 fallback will be
-  // enabled for all sites.
-  // If |unrestricted_ssl3_fallback_enabled| is false, SSL 3.0 fallback will be
-  // disabled for a site pinned to the Google pin list (indicating that it is a
-  // Google site).
-  bool unrestricted_ssl3_fallback_enabled;
-
-  // TODO(wtc): move the following members to a new SSLParams structure.  They
-  // are not SSL configuration settings.
-
-  struct NET_EXPORT CertAndStatus {
-    CertAndStatus();
-    ~CertAndStatus();
-
-    std::string der_cert;
-    CertStatus cert_status;
-  };
-
-  // Add any known-bad SSL certificate (with its cert status) to
-  // |allowed_bad_certs| that should not trigger an ERR_CERT_* error when
-  // calling SSLClientSocket::Connect.  This would normally be done in
-  // response to the user explicitly accepting the bad certificate.
-  std::vector<CertAndStatus> allowed_bad_certs;
-
-  // True if we should send client_cert to the server.
-  bool send_client_cert;
-
-  bool verify_ev_cert;  // True if we should verify the certificate for EV.
-
-  bool version_fallback;  // True if we are falling back to an older protocol
-                          // version (one still needs to decrement
-                          // version_max).
-
-  // If cert_io_enabled is false, then certificate verification will not
-  // result in additional HTTP requests. (For example: to fetch missing
-  // intermediates or to perform OCSP/CRL fetches.) It also implies that online
-  // revocation checking is disabled.
-  // NOTE: Only used by NSS.
-  bool cert_io_enabled;
-
-  // The list of application level protocols supported. If set, this will
-  // enable Next Protocol Negotiation (if supported). The order of the
-  // protocols doesn't matter expect for one case: if the server supports Next
-  // Protocol Negotiation, but there is no overlap between the server's and
-  // client's protocol sets, then the first protocol in this list will be
-  // requested by the client.
-  std::vector<std::string> next_protos;
-
-  scoped_refptr<X509Certificate> client_cert;
-};
-
 // The interface for retrieving the SSL configuration.  This interface
 // does not cover setting the SSL configuration, as on some systems, the
 // SSLConfigService objects may not have direct access to the configuration, or
@@ -193,12 +50,6 @@
   static void SetCRLSet(scoped_refptr<CRLSet> crl_set);
   static scoped_refptr<CRLSet> GetCRLSet();
 
-  // Gets the default minimum protocol version.
-  static uint16 default_version_min();
-
-  // Gets the default maximum protocol version.
-  static uint16 default_version_max();
-
   // Is SNI available in this configuration?
   static bool IsSNIAvailable(SSLConfigService* service);
 
diff --git a/net/ssl/ssl_config_service_unittest.cc b/net/ssl/ssl_config_service_unittest.cc
index 42c8ae4..e8a4c33 100644
--- a/net/ssl/ssl_config_service_unittest.cc
+++ b/net/ssl/ssl_config_service_unittest.cc
@@ -69,7 +69,6 @@
   SSLConfig initial_config;
   initial_config.rev_checking_enabled = true;
   initial_config.false_start_enabled = false;
-  initial_config.unrestricted_ssl3_fallback_enabled = false;
   initial_config.version_min = SSL_PROTOCOL_VERSION_SSL3;
   initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_1;
 
@@ -87,10 +86,6 @@
   EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
   mock_service->SetSSLConfig(initial_config);
 
-  initial_config.unrestricted_ssl3_fallback_enabled = true;
-  EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
-  mock_service->SetSSLConfig(initial_config);
-
   // Test that changing the SSL version range triggers updates.
   initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1;
   EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1);
diff --git a/net/test/embedded_test_server/embedded_test_server.cc b/net/test/embedded_test_server/embedded_test_server.cc
index b60cea4..75b46e2 100644
--- a/net/test/embedded_test_server/embedded_test_server.cc
+++ b/net/test/embedded_test_server/embedded_test_server.cc
@@ -20,7 +20,6 @@
 #include "net/test/embedded_test_server/http_connection.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
-#include "net/tools/fetch/http_listen_socket.h"
 
 namespace net {
 namespace test_server {
diff --git a/net/tools/dump_cache/dump_files.cc b/net/tools/dump_cache/dump_files.cc
index 6078778..796f205 100644
--- a/net/tools/dump_cache/dump_files.cc
+++ b/net/tools/dump_cache/dump_files.cc
@@ -14,10 +14,10 @@
 #include <string>
 
 #include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/files/file_enumerator.h"
 #include "base/format_macros.h"
 #include "base/message_loop/message_loop.h"
-#include "net/base/file_stream.h"
 #include "net/disk_cache/blockfile/block_files.h"
 #include "net/disk_cache/blockfile/disk_format.h"
 #include "net/disk_cache/blockfile/mapped_file.h"
@@ -31,14 +31,13 @@
 
 // Reads the |header_size| bytes from the beginning of file |name|.
 bool ReadHeader(const base::FilePath& name, char* header, int header_size) {
-  net::FileStream file(NULL);
-  file.OpenSync(name, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ);
-  if (!file.IsOpen()) {
+  base::File file(name, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!file.IsValid()) {
     printf("Unable to open file %s\n", name.MaybeAsASCII().c_str());
     return false;
   }
 
-  int read = file.ReadSync(header, header_size);
+  int read = file.Read(0, header, header_size);
   if (read != header_size) {
     printf("Unable to read file %s\n", name.MaybeAsASCII().c_str());
     return false;
diff --git a/net/tools/fetch/fetch_client.cc b/net/tools/fetch/fetch_client.cc
deleted file mode 100644
index 830622c..0000000
--- a/net/tools/fetch/fetch_client.cc
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/stats_counters.h"
-#include "base/strings/string_number_conversions.h"
-#include "build/build_config.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_request_context.h"
-#include "net/url_request/url_request_context_builder.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "url/gurl.h"
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#include "net/proxy/proxy_config.h"
-#include "net/proxy/proxy_config_service_fixed.h"
-#endif  // defined(OS_LINUX) || defined(OS_ANDROID)
-
-using net::URLFetcher;
-using net::URLFetcherDelegate;
-using net::URLRequestContextGetter;
-
-void usage(const char* program_name) {
-  printf("usage: %s --url=<url> [--n=<clients>] [--stats] [--use_cache] "
-         "[--v]\n",
-         program_name);
-  exit(1);
-}
-
-// Test Driver
-class Driver {
- public:
-  Driver()
-      : clients_(0) {}
-
-  void ClientStarted() { clients_++; }
-  void ClientStopped() {
-    if (!--clients_) {
-      base::MessageLoop::current()->Quit();
-    }
-  }
-
- private:
-  int clients_;
-};
-
-scoped_ptr<net::URLRequestContext>
-BuildURLRequestContext(bool use_cache) {
-  net::URLRequestContextBuilder builder;
-  builder.set_file_enabled(true);
-  builder.set_data_enabled(true);
-  builder.set_ftp_enabled(true);
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-  // TODO(wtc): Remove this once http://crbug.com/146421 is fixed.
-  builder.set_proxy_config_service(
-      new net::ProxyConfigServiceFixed(net::ProxyConfig::CreateDirect()));
-#endif  // defined(OS_LINUX) || defined(OS_ANDROID)
-  if (!use_cache)
-    builder.DisableHttpCache();
-  scoped_ptr<net::URLRequestContext> context(builder.Build());
-  return context.Pass();
-}
-
-// Builds a URLRequestContext assuming there's only a single message loop.
-class SingleThreadRequestContextGetter : public net::URLRequestContextGetter {
- public:
-  // Since there's only a single thread, there's no need to worry
-  // about when |context_| gets created.
-  SingleThreadRequestContextGetter(
-      bool use_cache,
-      const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
-      : context_(BuildURLRequestContext(use_cache)),
-        main_task_runner_(main_task_runner) {}
-
-  virtual net::URLRequestContext* GetURLRequestContext() OVERRIDE {
-    return context_.get();
-  }
-
-  virtual scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
-      const OVERRIDE {
-    return main_task_runner_;
-  }
-
- private:
-  virtual ~SingleThreadRequestContextGetter() {}
-
-  const scoped_ptr<net::URLRequestContext> context_;
-  const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
-};
-
-static base::LazyInstance<Driver> g_driver = LAZY_INSTANCE_INITIALIZER;
-
-// A network client
-class Client : public URLFetcherDelegate {
- public:
-  Client(const std::string& url,
-         URLRequestContextGetter* getter) :
-      url_(url), getter_(getter), last_current_(0) {
-  }
-
-  void Start() {
-    fetcher_.reset(net::URLFetcher::Create(
-        url_, net::URLFetcher::GET, this));
-    if (!fetcher_.get())
-      return;
-    g_driver.Get().ClientStarted();
-    fetcher_->SetRequestContext(getter_);
-    fetcher_->Start();
-  };
-
- private:
-
-  // URLFetcherDelegate overrides.
-  virtual void OnURLFetchComplete(const URLFetcher* source) OVERRIDE {
-    base::StatsCounter requests("FetchClient.requests");
-    requests.Increment();
-    g_driver.Get().ClientStopped();
-    printf(".");
-  }
-
-  virtual void OnURLFetchDownloadProgress(const URLFetcher* source,
-                                          int64 current, int64 total) OVERRIDE {
-    base::StatsCounter bytes_read("FetchClient.bytes_read");
-    DCHECK(current >= last_current_);
-    int64 delta = current - last_current_;
-    bytes_read.Add(delta);
-    last_current_ = current;
-  }
-
-  virtual void OnURLFetchUploadProgress(const URLFetcher* source,
-                                        int64 current, int64 total) OVERRIDE {
-    CHECK(false);
-  }
-
-  GURL url_;
-  scoped_ptr<URLFetcher> fetcher_;
-  URLRequestContextGetter* getter_;
-  int64 last_current_;
-};
-
-int main(int argc, char** argv) {
-  base::AtExitManager exit;
-  base::StatsTable table("fetchclient", 50, 1000);
-  table.set_current(&table);
-
-  CommandLine::Init(argc, argv);
-  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
-  std::string url = parsed_command_line.GetSwitchValueASCII("url");
-  if (!url.length())
-    usage(argv[0]);
-  int client_limit = 1;
-  if (parsed_command_line.HasSwitch("n")) {
-    base::StringToInt(parsed_command_line.GetSwitchValueASCII("n"),
-                      &client_limit);
-  }
-  bool use_cache = parsed_command_line.HasSwitch("use-cache");
-  if (parsed_command_line.HasSwitch("v")) {
-    logging::SetMinLogLevel(-10);
-  }
-
-  // Do work here.
-  base::MessageLoopForIO loop;
-
-  scoped_refptr<SingleThreadRequestContextGetter> context_getter(
-      new SingleThreadRequestContextGetter(use_cache,
-                                           loop.message_loop_proxy()));
-
-  {
-    base::StatsCounterTimer driver_time("FetchClient.total_time");
-    base::StatsScope<base::StatsCounterTimer> scope(driver_time);
-
-    Client** clients = new Client*[client_limit];
-    for (int i = 0; i < client_limit; i++) {
-      clients[i] = new Client(url, context_getter);
-      clients[i]->Start();
-    }
-
-    base::MessageLoop::current()->Run();
-  }
-
-  // Print Statistics here.
-  int num_clients = table.GetCounterValue("c:FetchClient.requests");
-  int test_time = table.GetCounterValue("t:FetchClient.total_time");
-  int bytes_read = table.GetCounterValue("c:FetchClient.bytes_read");
-
-  printf("\n");
-  printf("Clients     : %d\n", num_clients);
-  printf("Time        : %dms\n", test_time);
-  printf("Bytes Read  : %d\n", bytes_read);
-  if (test_time > 0) {
-    const char *units = "bps";
-    double bps = static_cast<float>(bytes_read * 8) /
-        (static_cast<float>(test_time) / 1000.0);
-
-    if (bps > (1024*1024)) {
-      bps /= (1024*1024);
-      units = "Mbps";
-    } else if (bps > 1024) {
-      bps /= 1024;
-      units = "Kbps";
-    }
-    printf("Bandwidth   : %.2f%s\n", bps, units);
-  }
-
-  if (parsed_command_line.HasSwitch("stats")) {
-    // Dump the stats table.
-    printf("<stats>\n");
-    int counter_max = table.GetMaxCounters();
-    for (int index = 0; index < counter_max; index++) {
-      std::string name(table.GetRowName(index));
-      if (name.length() > 0) {
-        int value = table.GetRowValue(index);
-        printf("%s:\t%d\n", name.c_str(), value);
-      }
-    }
-    printf("</stats>\n");
-  }
-  return 0;
-}
diff --git a/net/tools/fetch/fetch_server.cc b/net/tools/fetch/fetch_server.cc
deleted file mode 100644
index a2ffc5b..0000000
--- a/net/tools/fetch/fetch_server.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/memory/singleton.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/stats_counters.h"
-#include "net/base/completion_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/winsock_init.h"
-#include "net/http/http_network_layer.h"
-#include "net/http/http_request_info.h"
-#include "net/http/http_transaction.h"
-#include "net/proxy/proxy_service.h"
-#include "net/tools/fetch/http_server.h"
-
-void usage(const char* program_name) {
-  printf("usage: %s\n", program_name);
-  exit(-1);
-}
-
-int main(int argc, char**argv) {
-  base::AtExitManager exit;
-  base::StatsTable table("fetchserver", 50, 1000);
-  table.set_current(&table);
-
-#if defined(OS_WIN)
-  net::EnsureWinsockInit();
-#endif  // defined(OS_WIN)
-
-  CommandLine::Init(0, NULL);
-  const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
-
-  // Do work here.
-  base::MessageLoop loop;
-  HttpServer server(std::string(),
-                    80);  // TODO(mbelshe): make port configurable
-  base::MessageLoop::current()->Run();
-
-  if (parsed_command_line.HasSwitch("stats")) {
-    // Dump the stats table.
-    printf("<stats>\n");
-    int counter_max = table.GetMaxCounters();
-    for (int index=0; index < counter_max; index++) {
-      std::string name(table.GetRowName(index));
-      if (name.length() > 0) {
-        int value = table.GetRowValue(index);
-        printf("%s:\t%d\n", name.c_str(), value);
-      }
-    }
-    printf("</stats>\n");
-  }
-
-}
diff --git a/net/tools/fetch/http_listen_socket.cc b/net/tools/fetch/http_listen_socket.cc
deleted file mode 100644
index 410a0ba..0000000
--- a/net/tools/fetch/http_listen_socket.cc
+++ /dev/null
@@ -1,249 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/tools/fetch/http_listen_socket.h"
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "net/tools/fetch/http_server_request_info.h"
-#include "net/tools/fetch/http_server_response_info.h"
-
-HttpListenSocket::HttpListenSocket(net::SocketDescriptor s,
-                                   HttpListenSocket::Delegate* delegate)
-    : net::TCPListenSocket(s, this),
-      delegate_(delegate) {
-}
-
-HttpListenSocket::~HttpListenSocket() {
-  STLDeleteElements(&connections_);
-}
-
-void HttpListenSocket::Accept() {
-  net::SocketDescriptor conn = net::TCPListenSocket::AcceptSocket();
-  DCHECK_NE(conn, net::kInvalidSocket);
-  if (conn == net::kInvalidSocket) {
-    // TODO
-  } else {
-    scoped_ptr<StreamListenSocket> sock(
-        new HttpListenSocket(conn, delegate_));
-    DidAccept(this, sock.Pass());
-  }
-}
-
-// static
-scoped_ptr<HttpListenSocket> HttpListenSocket::CreateAndListen(
-    const std::string& ip,
-    int port,
-    HttpListenSocket::Delegate* delegate) {
-  net::SocketDescriptor s = net::TCPListenSocket::CreateAndBind(ip, port);
-  if (s == net::kInvalidSocket) {
-    // TODO (ibrar): error handling.
-  } else {
-    scoped_ptr<HttpListenSocket> serv(new HttpListenSocket(s, delegate));
-    serv->Listen();
-    return serv.Pass();
-  }
-  return scoped_ptr<HttpListenSocket>();
-}
-
-//
-// HTTP Request Parser
-// This HTTP request parser uses a simple state machine to quickly parse
-// through the headers.  The parser is not 100% complete, as it is designed
-// for use in this simple test driver.
-//
-// Known issues:
-//   - does not handle whitespace on first HTTP line correctly.  Expects
-//     a single space between the method/url and url/protocol.
-
-// Input character types.
-enum header_parse_inputs {
-  INPUT_SPACE,
-  INPUT_CR,
-  INPUT_LF,
-  INPUT_COLON,
-  INPUT_DEFAULT,
-  MAX_INPUTS
-};
-
-// Parser states.
-enum header_parse_states {
-  ST_METHOD,     // Receiving the method.
-  ST_URL,        // Receiving the URL.
-  ST_PROTO,      // Receiving the protocol.
-  ST_HEADER,     // Starting a Request Header.
-  ST_NAME,       // Receiving a request header name.
-  ST_SEPARATOR,  // Receiving the separator between header name and value.
-  ST_VALUE,      // Receiving a request header value.
-  ST_DONE,       // Parsing is complete and successful.
-  ST_ERR,        // Parsing encountered invalid syntax.
-  MAX_STATES
-};
-
-// State transition table.
-int parser_state[MAX_STATES][MAX_INPUTS] = {
-/* METHOD    */ { ST_URL,       ST_ERR,     ST_ERR,  ST_ERR,       ST_METHOD },
-/* URL       */ { ST_PROTO,     ST_ERR,     ST_ERR,  ST_URL,       ST_URL },
-/* PROTOCOL  */ { ST_ERR,       ST_HEADER,  ST_NAME, ST_ERR,       ST_PROTO },
-/* HEADER    */ { ST_ERR,       ST_ERR,     ST_NAME, ST_ERR,       ST_ERR },
-/* NAME      */ { ST_SEPARATOR, ST_DONE,    ST_ERR,  ST_SEPARATOR, ST_NAME },
-/* SEPARATOR */ { ST_SEPARATOR, ST_ERR,     ST_ERR,  ST_SEPARATOR, ST_VALUE },
-/* VALUE     */ { ST_VALUE,     ST_HEADER,  ST_NAME, ST_VALUE,     ST_VALUE },
-/* DONE      */ { ST_DONE,      ST_DONE,    ST_DONE, ST_DONE,      ST_DONE },
-/* ERR       */ { ST_ERR,       ST_ERR,     ST_ERR,  ST_ERR,       ST_ERR }
-};
-
-// Convert an input character to the parser's input token.
-int charToInput(char ch) {
-  switch(ch) {
-    case ' ':
-      return INPUT_SPACE;
-    case '\r':
-      return INPUT_CR;
-    case '\n':
-      return INPUT_LF;
-    case ':':
-      return INPUT_COLON;
-  }
-  return INPUT_DEFAULT;
-}
-
-HttpServerRequestInfo* HttpListenSocket::ParseHeaders() {
-  int pos = 0;
-  int data_len = recv_data_.length();
-  int state = ST_METHOD;
-  HttpServerRequestInfo* info = new HttpServerRequestInfo();
-  std::string buffer;
-  std::string header_name;
-  std::string header_value;
-  while (pos < data_len) {
-    char ch = recv_data_[pos++];
-    int input = charToInput(ch);
-    int next_state = parser_state[state][input];
-
-    bool transition = (next_state != state);
-    if (transition) {
-      // Do any actions based on state transitions.
-      switch (state) {
-        case ST_METHOD:
-          info->method = buffer;
-          buffer.clear();
-          break;
-        case ST_URL:
-          info->url = GURL(buffer);
-          buffer.clear();
-          break;
-        case ST_PROTO:
-          // TODO(mbelshe): Deal better with parsing protocol.
-          DCHECK(buffer == "HTTP/1.1");
-          buffer.clear();
-          break;
-        case ST_NAME:
-          header_name = buffer;
-          buffer.clear();
-          break;
-        case ST_VALUE:
-          header_value = buffer;
-          // TODO(mbelshe): Deal better with duplicate headers.
-          DCHECK(info->headers.find(header_name) == info->headers.end());
-          info->headers[header_name] = header_value;
-          buffer.clear();
-          break;
-      }
-      state = next_state;
-    } else {
-      // Do any actions based on current state.
-      switch (state) {
-        case ST_METHOD:
-        case ST_URL:
-        case ST_PROTO:
-        case ST_VALUE:
-        case ST_NAME:
-          buffer.append(&ch, 1);
-          break;
-        case ST_DONE:
-          recv_data_ = recv_data_.substr(pos);
-          return info;
-        case ST_ERR:
-          delete info;
-          return NULL;
-      }
-    }
-  }
-  // No more characters, but we haven't finished parsing yet.
-  delete info;
-  return NULL;
-}
-
-void HttpListenSocket::DidAccept(
-    net::StreamListenSocket* server,
-    scoped_ptr<net::StreamListenSocket> connection) {
-  connections_.insert(connection.release());
-}
-
-void HttpListenSocket::DidRead(net::StreamListenSocket* connection,
-                               const char* data,
-                               int len) {
-  recv_data_.append(data, len);
-  while (recv_data_.length()) {
-    HttpServerRequestInfo* request = ParseHeaders();
-    if (!request)
-      break;
-    delegate_->OnRequest(this, request);
-    delete request;
-  }
-}
-
-void HttpListenSocket::DidClose(net::StreamListenSocket* sock) {
-  size_t count = connections_.erase(sock);
-  DCHECK_EQ(1u, count);
-  delete sock;
-}
-
-// Convert the numeric status code to a string.
-// e.g.  200 -> "200 OK".
-std::string ServerStatus(int code) {
-  switch(code) {
-    case 200:
-      return std::string("200 OK");
-    // TODO(mbelshe): handle other codes.
-  }
-  NOTREACHED();
-  return std::string();
-}
-
-void HttpListenSocket::Respond(HttpServerResponseInfo* info,
-                               std::string& data) {
-  std::string response;
-
-  // Status line.
-  response = info->protocol + " ";
-  response += ServerStatus(info->status);
-  response += "\r\n";
-
-  // Standard headers.
-  if (info->content_type.length())
-    response += "Content-type: " + info->content_type + "\r\n";
-
-  if (info->content_length > 0)
-    response += "Content-length: " + base::IntToString(info->content_length) +
-        "\r\n";
-
-  if (info->connection_close)
-    response += "Connection: close\r\n";
-
-  // TODO(mbelshe): support additional headers.
-
-  // End of headers.
-  response += "\r\n";
-
-  // Add data.
-  response += data;
-
-  // Write it all out.
-  this->Send(response, false);
-}
diff --git a/net/tools/fetch/http_listen_socket.h b/net/tools/fetch/http_listen_socket.h
deleted file mode 100644
index e0a58c0..0000000
--- a/net/tools/fetch/http_listen_socket.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_BASE_TOOLS_HTTP_LISTEN_SOCKET_H_
-#define NET_BASE_TOOLS_HTTP_LISTEN_SOCKET_H_
-
-#include <set>
-
-#include "base/message_loop/message_loop.h"
-#include "net/socket/stream_listen_socket.h"
-#include "net/socket/tcp_listen_socket.h"
-
-class HttpServerRequestInfo;
-class HttpServerResponseInfo;
-
-// Implements a simple HTTP listen socket on top of the raw socket interface.
-class HttpListenSocket : public net::TCPListenSocket,
-                         public net::StreamListenSocket::Delegate {
- public:
-  class Delegate {
-   public:
-    virtual void OnRequest(HttpListenSocket* connection,
-                           HttpServerRequestInfo* info) = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  virtual ~HttpListenSocket();
-
-  static scoped_ptr<HttpListenSocket> CreateAndListen(
-      const std::string& ip, int port, HttpListenSocket::Delegate* delegate);
-
-  // Send a server response.
-  // TODO(mbelshe): make this capable of non-ascii data.
-  void Respond(HttpServerResponseInfo* info, std::string& data);
-
-  // StreamListenSocket::Delegate.
-  virtual void DidAccept(
-      net::StreamListenSocket* server,
-      scoped_ptr<net::StreamListenSocket> connection) OVERRIDE;
-  virtual void DidRead(net::StreamListenSocket* connection,
-                       const char* data, int len) OVERRIDE;
-  virtual void DidClose(net::StreamListenSocket* sock) OVERRIDE;
-
- protected:
-  // Overrides TCPListenSocket::Accept().
-  virtual void Accept() OVERRIDE;
-
- private:
-  static const int kReadBufSize = 16 * 1024;
-
-  // Must run in the IO thread.
-  HttpListenSocket(net::SocketDescriptor s, HttpListenSocket::Delegate* del);
-
-  // Expects the raw data to be stored in recv_data_. If parsing is successful,
-  // will remove the data parsed from recv_data_, leaving only the unused
-  // recv data.
-  HttpServerRequestInfo* ParseHeaders();
-
-  HttpListenSocket::Delegate* const delegate_;
-  std::string recv_data_;
-
-  std::set<StreamListenSocket*> connections_;
-
-  DISALLOW_COPY_AND_ASSIGN(HttpListenSocket);
-};
-
-#endif // NET_BASE_TOOLS_HTTP_LISTEN_SOCKET_H_
diff --git a/net/tools/fetch/http_server.cc b/net/tools/fetch/http_server.cc
deleted file mode 100644
index 71afb67..0000000
--- a/net/tools/fetch/http_server.cc
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/tools/fetch/http_server.h"
-
-HttpServer::HttpServer(std::string ip, int port)
-    : session_(new HttpSession(ip, port)) {
-}
-
-HttpServer::~HttpServer() {
-}
diff --git a/net/tools/fetch/http_server.h b/net/tools/fetch/http_server.h
deleted file mode 100644
index 6914130..0000000
--- a/net/tools/fetch/http_server.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_BASE_TOOLS_HTTP_SERVER_H_
-#define NET_BASE_TOOLS_HTTP_SERVER_H_
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "net/tools/fetch/http_session.h"
-
-// Implements a simple, single-threaded HttpServer.
-// Right now, this class implements no functionality above and beyond
-// the HttpSession.
-class HttpServer {
-public:
-  HttpServer(std::string ip, int port);
-  ~HttpServer();
-
-private:
-  scoped_ptr<HttpSession> session_;
-  DISALLOW_COPY_AND_ASSIGN(HttpServer);
-};
-
-#endif // NET_BASE_TOOLS_HTTP_SERVER_H_
-
diff --git a/net/tools/fetch/http_server_request_info.cc b/net/tools/fetch/http_server_request_info.cc
deleted file mode 100644
index 52b6860..0000000
--- a/net/tools/fetch/http_server_request_info.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/tools/fetch/http_server_request_info.h"
-
-HttpServerRequestInfo::HttpServerRequestInfo()
-    : net::HttpRequestInfo() {
-}
-
-HttpServerRequestInfo::~HttpServerRequestInfo() {}
diff --git a/net/tools/fetch/http_server_request_info.h b/net/tools/fetch/http_server_request_info.h
deleted file mode 100644
index 9b0fae1..0000000
--- a/net/tools/fetch/http_server_request_info.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_BASE_TOOLS_HTTP_SERVER_REQUEST_INFO_H_
-#define NET_BASE_TOOLS_HTTP_SERVER_REQUEST_INFO_H_
-
-#include <map>
-#include <string>
-
-#include "net/http/http_request_info.h"
-
-// Meta information about an HTTP request.
-// This is geared toward servers in that it keeps a map of the headers and
-// values rather than just a list of header strings (which net::HttpRequestInfo
-// does).
-class HttpServerRequestInfo : public net::HttpRequestInfo {
- public:
-  HttpServerRequestInfo();
-  virtual ~HttpServerRequestInfo();
-
-  // A map of the names -> values for HTTP headers.
-  std::map<std::string, std::string> headers;
-};
-
-#endif  // NET_BASE_TOOLS_HTTP_SERVER_REQUEST_INFO_H_
diff --git a/net/tools/fetch/http_server_response_info.cc b/net/tools/fetch/http_server_response_info.cc
deleted file mode 100644
index d9ca02a..0000000
--- a/net/tools/fetch/http_server_response_info.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/tools/fetch/http_server_response_info.h"
-
-HttpServerResponseInfo::HttpServerResponseInfo()
-    : status(200), content_length(0), connection_close(false) {
-}
-
-HttpServerResponseInfo::~HttpServerResponseInfo() {}
diff --git a/net/tools/fetch/http_server_response_info.h b/net/tools/fetch/http_server_response_info.h
deleted file mode 100644
index e01f730..0000000
--- a/net/tools/fetch/http_server_response_info.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_HTTP_HTTP_RESPONSE_INFO_H_
-#define NET_HTTP_HTTP_RESPONSE_INFO_H_
-
-#include <map>
-#include <string>
-
-// Meta information about a server response.
-class HttpServerResponseInfo {
- public:
-  HttpServerResponseInfo();
-  ~HttpServerResponseInfo();
-
-  // The response protocol.
-  std::string protocol;
-
-  // The status code.
-  int status;
-
-  // The server identifier.
-  std::string server_name;
-
-  // The content type.
-  std::string content_type;
-
-  // The content length.
-  int content_length;
-
-  // Should we close the connection.
-  bool connection_close;
-
-  // Additional response headers.
-  std::map<std::string, std::string> headers;
-};
-
-#endif  // NET_HTTP_HTTP_RESPONSE_INFO_H_
diff --git a/net/tools/fetch/http_session.cc b/net/tools/fetch/http_session.cc
deleted file mode 100644
index d9e991b..0000000
--- a/net/tools/fetch/http_session.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/tools/fetch/http_session.h"
-#include "net/tools/fetch/http_server_response_info.h"
-
-HttpSession::HttpSession(const std::string& ip, int port)
-    : socket_(HttpListenSocket::CreateAndListen(ip, port, this)) {
-}
-
-HttpSession::~HttpSession() {
-}
-
-void HttpSession::OnRequest(HttpListenSocket* connection,
-                            HttpServerRequestInfo* info) {
-  // TODO(mbelshe):  Make this function more interesting.
-
-  // Generate a 10KB sequence of data.
-  CR_DEFINE_STATIC_LOCAL(std::string, data, ());
-  if (data.length() == 0) {
-    while (data.length() < (10 * 1024))
-      data += 'a' + (rand() % 26);
-  }
-
-  HttpServerResponseInfo response_info;
-  response_info.protocol = "HTTP/1.1";
-  response_info.status = 200;
-  response_info.content_type = "text/plain";
-  response_info.content_length = data.length();
-
-  connection->Respond(&response_info, data);
-}
diff --git a/net/tools/fetch/http_session.h b/net/tools/fetch/http_session.h
deleted file mode 100644
index b0266f2..0000000
--- a/net/tools/fetch/http_session.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_BASE_TOOLS_HTTP_SESSION_H_
-#define NET_BASE_TOOLS_HTTP_SESSION_H_
-
-#include "base/basictypes.h"
-#include "net/http/http_request_info.h"
-#include "net/tools/fetch/http_listen_socket.h"
-
-// An HttpSession encapsulates a server-side HTTP listen socket.
-class HttpSession : HttpListenSocket::Delegate {
- public:
-  HttpSession(const std::string& ip, int port);
-  virtual ~HttpSession();
-
-  virtual void OnRequest(HttpListenSocket* connection,
-                         HttpServerRequestInfo* info) OVERRIDE;
-
- private:
-  scoped_ptr<HttpListenSocket> socket_;
-  DISALLOW_COPY_AND_ASSIGN(HttpSession);
-};
-
-#endif // NET_BASE_TOOLS_HTTP_SESSION_H_
-
diff --git a/net/tools/quic/end_to_end_test.cc b/net/tools/quic/end_to_end_test.cc
index 7014bab..dcba71a 100644
--- a/net/tools/quic/end_to_end_test.cc
+++ b/net/tools/quic/end_to_end_test.cc
@@ -156,7 +156,8 @@
     CHECK(net::ParseIPLiteralToNumber("127.0.0.1", &ip));
     uint port = 0;
     server_address_ = IPEndPoint(ip, port);
-    server_key_ = QuicSessionKey("example.com", port, false);
+    server_key_ = QuicSessionKey("example.com", port, false,
+                                 kPrivacyModeDisabled);
 
     client_supported_versions_ = GetParam().client_supported_versions;
     server_supported_versions_ = GetParam().server_supported_versions;
@@ -225,8 +226,8 @@
     server_thread_->Initialize();
     server_address_ = IPEndPoint(server_address_.address(),
                                  server_thread_->GetPort());
-    server_key_ = QuicSessionKey(server_key_.host(),
-                                  server_thread_->GetPort(), false);
+    server_key_ = QuicSessionKey(server_key_.host(), server_thread_->GetPort(),
+                                 false, kPrivacyModeDisabled);
 
     QuicDispatcher* dispatcher =
         QuicServerPeer::GetDispatcher(server_thread_->server());
diff --git a/net/tools/quic/quic_client_bin.cc b/net/tools/quic/quic_client_bin.cc
index db2de14..8f4ad50 100644
--- a/net/tools/quic/quic_client_bin.cc
+++ b/net/tools/quic/quic_client_bin.cc
@@ -17,6 +17,7 @@
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
 #include "net/base/ip_endpoint.h"
+#include "net/base/privacy_mode.h"
 #include "net/quic/quic_protocol.h"
 #include "net/tools/quic/quic_client.h"
 
@@ -73,7 +74,8 @@
   // TODO(rjshade): Set version on command line.
   net::tools::QuicClient client(
       net::IPEndPoint(addr, FLAGS_port),
-      net::QuicSessionKey(FLAGS_hostname, FLAGS_port, FLAGS_secure),
+      net::QuicSessionKey(FLAGS_hostname, FLAGS_port, FLAGS_secure,
+                          net::kPrivacyModeDisabled),
       net::QuicSupportedVersions(), true);
 
   client.Initialize();
diff --git a/net/tools/quic/quic_client_session.cc b/net/tools/quic/quic_client_session.cc
index 54f46e3..29b178a 100644
--- a/net/tools/quic/quic_client_session.cc
+++ b/net/tools/quic/quic_client_session.cc
@@ -19,13 +19,21 @@
     const QuicConfig& config,
     QuicConnection* connection,
     QuicCryptoClientConfig* crypto_config)
-    : QuicSession(connection, config),
+    : QuicClientSessionBase(connection, config),
       crypto_stream_(server_key, this, NULL, crypto_config) {
 }
 
 QuicClientSession::~QuicClientSession() {
 }
 
+void QuicClientSession::OnProofValid(
+    const QuicCryptoClientConfig::CachedState& /*cached*/) {
+}
+
+void QuicClientSession::OnProofVerifyDetailsAvailable(
+    const ProofVerifyDetails& /*verify_details*/) {
+}
+
 QuicSpdyClientStream* QuicClientSession::CreateOutgoingDataStream() {
   if (!crypto_stream_.encryption_established()) {
     DVLOG(1) << "Encryption not active so no outgoing stream created.";
diff --git a/net/tools/quic/quic_client_session.h b/net/tools/quic/quic_client_session.h
index f3bce29..6f7a1ba 100644
--- a/net/tools/quic/quic_client_session.h
+++ b/net/tools/quic/quic_client_session.h
@@ -10,9 +10,9 @@
 #include <string>
 
 #include "base/basictypes.h"
+#include "net/quic/quic_client_session_base.h"
 #include "net/quic/quic_crypto_client_stream.h"
 #include "net/quic/quic_protocol.h"
-#include "net/quic/quic_session.h"
 #include "net/tools/quic/quic_spdy_client_stream.h"
 
 namespace net {
@@ -23,7 +23,7 @@
 
 namespace tools {
 
-class QuicClientSession : public QuicSession {
+class QuicClientSession : public QuicClientSessionBase {
  public:
   QuicClientSession(const QuicSessionKey& server_key,
                     const QuicConfig& config,
@@ -31,6 +31,12 @@
                     QuicCryptoClientConfig* crypto_config);
   virtual ~QuicClientSession();
 
+  // QuicClientSessionBase methods:
+  virtual void OnProofValid(
+      const QuicCryptoClientConfig::CachedState& cached) OVERRIDE;
+  virtual void OnProofVerifyDetailsAvailable(
+      const ProofVerifyDetails& verify_details) OVERRIDE;
+
   // QuicSession methods:
   virtual QuicSpdyClientStream* CreateOutgoingDataStream() OVERRIDE;
   virtual QuicCryptoClientStream* GetCryptoStream() OVERRIDE;
diff --git a/net/tools/quic/quic_client_session_test.cc b/net/tools/quic/quic_client_session_test.cc
index a0b49d4..57992cd 100644
--- a/net/tools/quic/quic_client_session_test.cc
+++ b/net/tools/quic/quic_client_session_test.cc
@@ -35,7 +35,7 @@
                                                SupportedVersions(GetParam()))) {
     crypto_config_.SetDefaults();
     session_.reset(new QuicClientSession(
-        QuicSessionKey(kServerHostname, kPort, false),
+        QuicSessionKey(kServerHostname, kPort, false, kPrivacyModeDisabled),
         DefaultQuicConfig(), connection_, &crypto_config_));
     session_->config()->SetDefaults();
   }
diff --git a/net/tools/quic/quic_spdy_client_stream_test.cc b/net/tools/quic/quic_spdy_client_stream_test.cc
index 40105dd..5dd10d0 100644
--- a/net/tools/quic/quic_spdy_client_stream_test.cc
+++ b/net/tools/quic/quic_spdy_client_stream_test.cc
@@ -30,7 +30,8 @@
   QuicSpdyClientStreamTest()
       : connection_(new StrictMock<MockConnection>(
             false, SupportedVersions(GetParam()))),
-        session_(QuicSessionKey("example.com", 80, false), DefaultQuicConfig(),
+        session_(QuicSessionKey("example.com", 80, false, kPrivacyModeDisabled),
+                 DefaultQuicConfig(),
                  connection_, &crypto_config_),
         body_("hello world") {
     crypto_config_.SetDefaults();
diff --git a/net/tools/quic/test_tools/quic_test_client.cc b/net/tools/quic/test_tools/quic_test_client.cc
index d88d836..7413202 100644
--- a/net/tools/quic/test_tools/quic_test_client.cc
+++ b/net/tools/quic/test_tools/quic_test_client.cc
@@ -39,6 +39,7 @@
                              const string& server_config,
                              const vector<string>& certs,
                              const string& signature,
+                             const net::ProofVerifyContext* context,
                              string* error_details,
                              scoped_ptr<ProofVerifyDetails>* details,
                              ProofVerifierCallback* callback) OVERRIDE {
@@ -214,7 +215,7 @@
     if (!url.host().empty()) {
       client_->set_server_key(
           QuicSessionKey(url.host(), url.EffectiveIntPort(),
-                         url.SchemeIs("https") ? true : false));
+                         url.SchemeIs("https"), kPrivacyModeDisabled));
     }
   }
 
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index 0a1f59b..13aafcd 100755
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -27,6 +27,7 @@
 import select
 import socket
 import SocketServer
+import ssl
 import struct
 import sys
 import threading
@@ -51,7 +52,10 @@
 # Insert at the beginning of the path, we want this to be used
 # unconditionally.
 sys.path.insert(0, os.path.join(ROOT_DIR, 'third_party', 'pywebsocket', 'src'))
+import mod_pywebsocket.standalone
 from mod_pywebsocket.standalone import WebSocketServer
+# import manually
+mod_pywebsocket.standalone.ssl = ssl
 
 SERVER_HTTP = 0
 SERVER_FTP = 1
@@ -84,6 +88,7 @@
     self.certificate = None
     self.tls_client_auth = False
     self.tls_client_ca = None
+    self.tls_module = 'ssl'
     self.use_basic_auth = False
 
 
diff --git a/net/udp/udp_socket_libevent.cc b/net/udp/udp_socket_libevent.cc
index 9c8215c..5646276 100644
--- a/net/udp/udp_socket_libevent.cc
+++ b/net/udp/udp_socket_libevent.cc
@@ -128,7 +128,7 @@
       return MapSystemError(errno);
     scoped_ptr<IPEndPoint> address(new IPEndPoint());
     if (!address->FromSockAddr(storage.addr, storage.addr_len))
-      return ERR_FAILED;
+      return ERR_ADDRESS_INVALID;
     remote_address_.reset(address.release());
   }
 
@@ -148,7 +148,7 @@
       return MapSystemError(errno);
     scoped_ptr<IPEndPoint> address(new IPEndPoint());
     if (!address->FromSockAddr(storage.addr, storage.addr_len))
-      return ERR_FAILED;
+      return ERR_ADDRESS_INVALID;
     local_address_.reset(address.release());
     net_log_.AddEvent(NetLog::TYPE_UDP_LOCAL_ADDRESS,
                       CreateNetLogUDPConnectCallback(local_address_.get()));
@@ -476,7 +476,7 @@
   if (bytes_transferred >= 0) {
     result = bytes_transferred;
     if (address && !address->FromSockAddr(storage.addr, storage.addr_len))
-      result = ERR_FAILED;
+      result = ERR_ADDRESS_INVALID;
   } else {
     result = MapSystemError(errno);
   }
@@ -494,7 +494,7 @@
     storage.addr_len = 0;
   } else {
     if (!address->ToSockAddr(storage.addr, &storage.addr_len)) {
-      int result = ERR_FAILED;
+      int result = ERR_ADDRESS_INVALID;
       LogWrite(result, NULL, NULL);
       return result;
     }
diff --git a/net/udp/udp_socket_win.cc b/net/udp/udp_socket_win.cc
index beaf400..78f51c9 100644
--- a/net/udp/udp_socket_win.cc
+++ b/net/udp/udp_socket_win.cc
@@ -390,18 +390,42 @@
 
 bool UDPSocketWin::SetReceiveBufferSize(int32 size) {
   DCHECK(CalledOnValidThread());
-  int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
-                      reinterpret_cast<const char*>(&size), sizeof(size));
-  DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
-  return rv == 0;
+  setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
+             reinterpret_cast<const char*>(&size), sizeof(size));
+  // If the setsockopt fails, but the buffer is big enough, we will return
+  // success. It is not worth testing the return value as we still need to check
+  // via getsockopt anyway according to Windows documentation.
+  int32 actual_size = 0;
+  int option_size = sizeof(actual_size);
+  int rv = getsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
+                      reinterpret_cast<char*>(&actual_size), &option_size);
+  if (rv != 0)
+    return false;
+  if (actual_size < size) {
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketReceiveBufferUnchangeable",
+                                actual_size, 1000, 1000000, 50);
+  }
+  return actual_size >= size;
 }
 
 bool UDPSocketWin::SetSendBufferSize(int32 size) {
   DCHECK(CalledOnValidThread());
-  int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
-                      reinterpret_cast<const char*>(&size), sizeof(size));
-  DCHECK(!rv) << "Could not set socket send buffer size: " << errno;
-  return rv == 0;
+  setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
+             reinterpret_cast<const char*>(&size), sizeof(size));
+  // If the setsockopt fails, but the buffer is big enough, we will return
+  // success. It is not worth testing the return value as we still need to check
+  // via getsockopt anyway according to Windows documentation.
+  int32 actual_size = 0;
+  int option_size = sizeof(actual_size);
+  int rv = getsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
+                      reinterpret_cast<char*>(&actual_size), &option_size);
+  if (rv != 0)
+    return false;
+  if (actual_size < size) {
+    UMA_HISTOGRAM_CUSTOM_COUNTS("Net.SocketUnchangeableSendBuffer",
+                                actual_size, 1000, 1000000, 50);
+  }
+  return actual_size >= size;
 }
 
 void UDPSocketWin::AllowAddressReuse() {
@@ -529,7 +553,7 @@
       // Convert address.
       if (address && result >= 0) {
         if (!ReceiveAddressToIPEndpoint(address))
-          result = ERR_FAILED;
+          result = ERR_ADDRESS_INVALID;
       }
       LogRead(result, buf->data());
       return result;
@@ -558,7 +582,7 @@
     storage.addr_len = 0;
   } else {
     if (!address->ToSockAddr(addr, &storage.addr_len)) {
-      int result = ERR_FAILED;
+      int result = ERR_ADDRESS_INVALID;
       LogWrite(result, NULL, NULL);
       return result;
     }
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index 744dc3b..8405163 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -64,8 +64,8 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers)
-      OVERRIDE {
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE {
     return OK;
   }
 
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 7207777..41b1515 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -24,7 +24,8 @@
 #include "net/base/network_delegate.h"
 #include "net/base/sdch_manager.h"
 #include "net/cert/cert_status_flags.h"
-#include "net/cookies/cookie_monster.h"
+#include "net/cookies/cookie_store.h"
+#include "net/http/http_content_disposition.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
@@ -58,6 +59,7 @@
   // FilterContext implementation.
   virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
   virtual bool GetURL(GURL* gurl) const OVERRIDE;
+  virtual bool GetContentDisposition(std::string* disposition) const OVERRIDE;
   virtual base::Time GetRequestTime() const OVERRIDE;
   virtual bool IsCachedContent() const OVERRIDE;
   virtual bool IsDownload() const OVERRIDE;
@@ -96,6 +98,13 @@
   return true;
 }
 
+bool URLRequestHttpJob::HttpFilterContext::GetContentDisposition(
+    std::string* disposition) const {
+  HttpResponseHeaders* headers = job_->GetResponseHeaders();
+  void *iter = NULL;
+  return headers->EnumerateHeader(&iter, "Content-Disposition", disposition);
+}
+
 base::Time URLRequestHttpJob::HttpFilterContext::GetRequestTime() const {
   return job_->request() ? job_->request()->request_time() : base::Time();
 }
@@ -541,15 +550,10 @@
 
   CookieStore* cookie_store = GetCookieStore();
   if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) {
-    net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster();
-    if (cookie_monster) {
-      cookie_monster->GetAllCookiesForURLAsync(
-          request_->url(),
-          base::Bind(&URLRequestHttpJob::CheckCookiePolicyAndLoad,
-                     weak_factory_.GetWeakPtr()));
-    } else {
-      CheckCookiePolicyAndLoad(CookieList());
-    }
+    cookie_store->GetAllCookiesForURLAsync(
+        request_->url(),
+        base::Bind(&URLRequestHttpJob::CheckCookiePolicyAndLoad,
+                   weak_factory_.GetWeakPtr()));
   } else {
     DoStartTransaction();
   }
@@ -803,11 +807,13 @@
       // |on_headers_received_callback_| or
       // |NetworkDelegate::URLRequestDestroyed()| has been called.
       OnCallToDelegate();
+      allowed_unsafe_redirect_url_ = GURL();
       int error = network_delegate()->NotifyHeadersReceived(
           request_,
           on_headers_received_callback_,
           headers.get(),
-          &override_response_headers_);
+          &override_response_headers_,
+          &allowed_unsafe_redirect_url_);
       if (error != net::OK) {
         if (error == net::ERR_IO_PENDING) {
           awaiting_callback_ = true;
@@ -1035,6 +1041,15 @@
       (location.scheme() == "http" || location.scheme() == "https")) {
     return true;
   }
+  // Delegates may mark an URL as safe for redirection.
+  if (allowed_unsafe_redirect_url_.is_valid()) {
+    GURL::Replacements replacements;
+    replacements.ClearRef();
+    if (allowed_unsafe_redirect_url_.ReplaceComponents(replacements) ==
+        location.ReplaceComponents(replacements)) {
+      return true;
+    }
+  }
   // Query URLRequestJobFactory as to whether |location| would be safe to
   // redirect to.
   return request_->context()->job_factory() &&
@@ -1252,8 +1267,27 @@
 }
 
 void URLRequestHttpJob::DoneReading() {
-  if (transaction_.get())
+  if (transaction_) {
     transaction_->DoneReading();
+  }
+  DoneWithRequest(FINISHED);
+}
+
+void URLRequestHttpJob::DoneReadingRedirectResponse() {
+  if (transaction_) {
+    if (transaction_->GetResponseInfo()->headers->IsRedirect(NULL)) {
+      // If the original headers indicate a redirect, go ahead and cache the
+      // response, even if the |override_response_headers_| are a redirect to
+      // another location.
+      transaction_->DoneReading();
+    } else {
+      // Otherwise, |override_response_headers_| must be non-NULL and contain
+      // bogus headers indicating a redirect.
+      DCHECK(override_response_headers_);
+      DCHECK(override_response_headers_->IsRedirect(NULL));
+      transaction_->StopCaching();
+    }
+  }
   DoneWithRequest(FINISHED);
 }
 
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index 33014e5..95b77c9 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -122,6 +122,8 @@
       HttpRequestHeaders* headers) const OVERRIDE;
   virtual int64 GetTotalReceivedBytes() const OVERRIDE;
   virtual void DoneReading() OVERRIDE;
+  virtual void DoneReadingRedirectResponse() OVERRIDE;
+
   virtual HostPortPair GetSocketAddress() const OVERRIDE;
   virtual void NotifyURLRequestDestroyed() OVERRIDE;
 
@@ -254,6 +256,9 @@
   // layers of the network stack.
   scoped_refptr<HttpResponseHeaders> override_response_headers_;
 
+  // The network delegate can mark a URL as safe for redirection.
+  GURL allowed_unsafe_redirect_url_;
+
   // Flag used to verify that |this| is not deleted while we are awaiting
   // a callback from the NetworkDelegate. Used as a fail-fast mechanism.
   // True if we are waiting a callback and
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index aac992d..35dbbb1 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -327,6 +327,10 @@
   GURL new_location;
   int http_status_code;
   if (IsRedirectResponse(&new_location, &http_status_code)) {
+    // Redirect response bodies are not read. Notify the transaction
+    // so it does not treat being stopped as an error.
+    DoneReadingRedirectResponse();
+
     const GURL& url = request_->url();
 
     // Move the reference fragment of the old location to the new one if the
@@ -340,10 +344,6 @@
       new_location = new_location.ReplaceComponents(replacements);
     }
 
-    // Redirect response bodies are not read. Notify the transaction
-    // so it does not treat being stopped as an error.
-    DoneReading();
-
     bool defer_redirect = false;
     request_->NotifyReceivedRedirect(new_location, &defer_redirect);
 
@@ -532,6 +532,9 @@
   // Do nothing.
 }
 
+void URLRequestJob::DoneReadingRedirectResponse() {
+}
+
 void URLRequestJob::FilteredDataRead(int bytes_read) {
   DCHECK(filter_.get());  // don't add data if there is no filter
   filter_->FlushStreamBuffer(bytes_read);
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 9bb763e..c6f7ba4 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -293,6 +293,11 @@
   // the stream.
   virtual void DoneReading();
 
+  // Called to tell the job that the body won't be read because it's a redirect.
+  // This is needed so that redirect headers can be cached even though their
+  // bodies are never read.
+  virtual void DoneReadingRedirectResponse();
+
   // Informs the filter that data has been read into its buffer
   void FilteredDataRead(int bytes_read);
 
diff --git a/net/url_request/url_request_job_unittest.cc b/net/url_request/url_request_job_unittest.cc
index 99f4314..c8bbc19 100644
--- a/net/url_request/url_request_job_unittest.cc
+++ b/net/url_request/url_request_job_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "net/url_request/url_request_job.h"
 
+#include "base/run_loop.h"
 #include "net/base/request_priority.h"
 #include "net/http/http_transaction_unittest.h"
 #include "net/url_request/url_request_test_util.h"
@@ -96,7 +97,7 @@
   req.set_method("GET");
   req.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_TRUE(network_layer.done_reading_called());
 
@@ -116,11 +117,34 @@
   req.set_method("GET");
   req.Start();
 
-  base::MessageLoop::current()->Run();
+  base::RunLoop().Run();
 
   EXPECT_TRUE(network_layer.done_reading_called());
 
   RemoveMockTransaction(&kRedirect_Transaction);
 }
 
+TEST(URLRequestJob, TransactionNotCachedWhenNetworkDelegateRedirects) {
+  MockNetworkLayer network_layer;
+  TestNetworkDelegate network_delegate;
+  network_delegate.set_redirect_on_headers_received_url(GURL("http://foo"));
+  TestURLRequestContext context;
+  context.set_http_transaction_factory(&network_layer);
+  context.set_network_delegate(&network_delegate);
+
+  TestDelegate d;
+  TestURLRequest req(GURL(kGZip_Transaction.url), DEFAULT_PRIORITY, &d,
+                     &context);
+  AddMockTransaction(&kGZip_Transaction);
+
+  req.set_method("GET");
+  req.Start();
+
+  base::RunLoop().Run();
+
+  EXPECT_TRUE(network_layer.stop_caching_called());
+
+  RemoveMockTransaction(&kGZip_Transaction);
+}
+
 }  // namespace net
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 419816b..17ad311 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -13,6 +13,7 @@
 #include "net/cert/cert_verifier.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/http/http_network_session.h"
+#include "net/http/http_response_headers.h"
 #include "net/http/http_server_properties_impl.h"
 #include "net/http/transport_security_state.h"
 #include "net/ssl/default_server_bound_cert_store.h"
@@ -410,7 +411,8 @@
     URLRequest* request,
     const CompletionCallback& callback,
     const HttpResponseHeaders* original_response_headers,
-    scoped_refptr<HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   int req_id = request->identifier();
   event_order_[req_id] += "OnHeadersReceived\n";
   InitRequestStatesIfNew(req_id);
@@ -426,6 +428,20 @@
   // layer before the URLRequest reports that a response has started.
   next_states_[req_id] |= kStageBeforeSendHeaders;
 
+  if (!redirect_on_headers_received_url_.is_empty()) {
+    *override_response_headers =
+        new net::HttpResponseHeaders(original_response_headers->raw_headers());
+    (*override_response_headers)->ReplaceStatusLine("HTTP/1.1 302 Found");
+    (*override_response_headers)->RemoveHeader("Location");
+    (*override_response_headers)->AddHeader(
+        "Location: " + redirect_on_headers_received_url_.spec());
+
+    redirect_on_headers_received_url_ = GURL();
+
+    if (!allowed_unsafe_redirect_url_.is_empty())
+      *allowed_unsafe_redirect_url = allowed_unsafe_redirect_url_;
+  }
+
   return OK;
 }
 
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h
index 0d35876..0b2f48c 100644
--- a/net/url_request/url_request_test_util.h
+++ b/net/url_request/url_request_test_util.h
@@ -234,6 +234,17 @@
   bool GetLoadTimingInfoBeforeAuth(
       LoadTimingInfo* load_timing_info_before_auth) const;
 
+  // Will redirect once to the given URL when the next set of headers are
+  // received.
+  void set_redirect_on_headers_received_url(
+      GURL redirect_on_headers_received_url) {
+    redirect_on_headers_received_url_ = redirect_on_headers_received_url;
+  }
+
+  void set_allowed_unsafe_redirect_url(GURL allowed_unsafe_redirect_url) {
+    allowed_unsafe_redirect_url_ = allowed_unsafe_redirect_url;
+  }
+
   void set_cookie_options(int o) {cookie_options_bit_mask_ = o; }
 
   int last_error() const { return last_error_; }
@@ -266,7 +277,8 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers) OVERRIDE;
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE;
   virtual void OnBeforeRedirect(URLRequest* request,
                                 const GURL& new_location) OVERRIDE;
   virtual void OnResponseStarted(URLRequest* request) OVERRIDE;
@@ -296,6 +308,10 @@
 
   void InitRequestStatesIfNew(int request_id);
 
+  GURL redirect_on_headers_received_url_;
+  // URL marked as safe for redirection at the onHeadersReceived stage.
+  GURL allowed_unsafe_redirect_url_;
+
   int last_error_;
   int error_count_;
   int created_requests_;
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index b85da78..aab2b32 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -57,6 +57,7 @@
 #include "net/http/http_network_session.h"
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
+#include "net/http/http_util.h"
 #include "net/ocsp/nss_ocsp.h"
 #include "net/proxy/proxy_service.h"
 #include "net/socket/ssl_client_socket.h"
@@ -367,7 +368,8 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers) OVERRIDE;
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE;
 
   virtual NetworkDelegate::AuthRequiredResponse OnAuthRequired(
       URLRequest* request,
@@ -390,7 +392,7 @@
   int retval_;  // To be returned in non-auth stages.
   AuthRequiredResponse auth_retval_;
 
-  GURL redirect_url_;  // Used if non-empty.
+  GURL redirect_url_;  // Used if non-empty during OnBeforeURLRequest.
   int block_on_;  // Bit mask: in which stages to block.
 
   // |auth_credentials_| will be copied to |*target_auth_credential_| on
@@ -482,10 +484,13 @@
     URLRequest* request,
     const CompletionCallback& callback,
     const HttpResponseHeaders* original_response_headers,
-    scoped_refptr<HttpResponseHeaders>* override_response_headers) {
-  TestNetworkDelegate::OnHeadersReceived(
-      request, callback, original_response_headers,
-      override_response_headers);
+    scoped_refptr<HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
+  TestNetworkDelegate::OnHeadersReceived(request,
+                                         callback,
+                                         original_response_headers,
+                                         override_response_headers,
+                                         allowed_unsafe_redirect_url);
 
   return MaybeBlockStage(ON_HEADERS_RECEIVED, callback);
 }
@@ -2416,8 +2421,8 @@
       net::URLRequest* request,
       const net::CompletionCallback& callback,
       const net::HttpResponseHeaders* original_response_headers,
-      scoped_refptr<net::HttpResponseHeaders>* override_response_headers)
-      OVERRIDE;
+      scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE;
 
  private:
   std::string fixed_date_;
@@ -2429,7 +2434,8 @@
     net::URLRequest* request,
     const net::CompletionCallback& callback,
     const net::HttpResponseHeaders* original_response_headers,
-    scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
+    scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+    GURL* allowed_unsafe_redirect_url) {
   net::HttpResponseHeaders* new_response_headers =
       new net::HttpResponseHeaders(original_response_headers->raw_headers());
 
@@ -2440,7 +2446,8 @@
   return TestNetworkDelegate::OnHeadersReceived(request,
                                                 callback,
                                                 original_response_headers,
-                                                override_response_headers);
+                                                override_response_headers,
+                                                allowed_unsafe_redirect_url);
 }
 
 // Test that cookie expiration times are adjusted for server/client clock
@@ -3007,6 +3014,39 @@
   EXPECT_EQ(1, network_delegate.destroyed_requests());
 }
 
+// Tests that the network delegate can block and redirect a request to a new
+// URL during OnHeadersReceived.
+TEST_F(URLRequestTestHTTP, NetworkDelegateRedirectRequestOnHeadersReceived) {
+  ASSERT_TRUE(test_server_.Start());
+
+  TestDelegate d;
+  BlockingNetworkDelegate network_delegate(
+      BlockingNetworkDelegate::AUTO_CALLBACK);
+  network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED);
+  GURL redirect_url(test_server_.GetURL("simple.html"));
+  network_delegate.set_redirect_on_headers_received_url(redirect_url);
+
+  TestURLRequestContextWithProxy context(
+      test_server_.host_port_pair().ToString(), &network_delegate);
+
+  {
+    GURL original_url(test_server_.GetURL("empty.html"));
+    URLRequest r(original_url, DEFAULT_PRIORITY, &d, &context);
+
+    r.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+    EXPECT_EQ(net::OK, r.status().error());
+    EXPECT_EQ(redirect_url, r.url());
+    EXPECT_EQ(original_url, r.original_url());
+    EXPECT_EQ(2U, r.url_chain().size());
+    EXPECT_EQ(2, network_delegate.created_requests());
+    EXPECT_EQ(0, network_delegate.destroyed_requests());
+  }
+  EXPECT_EQ(1, network_delegate.destroyed_requests());
+}
+
 // Tests that the network delegate can synchronously complete OnAuthRequired
 // by taking no action. This indicates that the NetworkDelegate does not want to
 // handle the challenge, and is passing the buck along to the
@@ -3919,10 +3959,13 @@
       URLRequest* request,
       const CompletionCallback& callback,
       const HttpResponseHeaders* original_response_headers,
-      scoped_refptr<HttpResponseHeaders>* override_response_headers) OVERRIDE {
-    TestNetworkDelegate::OnHeadersReceived(request, callback,
+      scoped_refptr<HttpResponseHeaders>* override_response_headers,
+      GURL* allowed_unsafe_redirect_url) OVERRIDE {
+    TestNetworkDelegate::OnHeadersReceived(request,
+                                           callback,
                                            original_response_headers,
-                                           override_response_headers);
+                                           override_response_headers,
+                                           allowed_unsafe_redirect_url);
     return RunCallbackAsynchronously(request, callback);
   }
 
@@ -5163,6 +5206,213 @@
   EXPECT_EQ(ERR_INVALID_URL, req.status().error());
 }
 
+// Make sure redirects are cached, despite not reading their bodies.
+TEST_F(URLRequestTestHTTP, CacheRedirect) {
+  ASSERT_TRUE(test_server_.Start());
+  GURL redirect_url =
+      test_server_.GetURL("files/redirect302-to-echo-cacheable");
+
+  {
+    TestDelegate d;
+    URLRequest req(redirect_url, DEFAULT_PRIORITY, &d, &default_context_);
+    req.Start();
+    base::RunLoop().Run();
+    EXPECT_EQ(URLRequestStatus::SUCCESS, req.status().status());
+    EXPECT_EQ(1, d.received_redirect_count());
+    EXPECT_EQ(test_server_.GetURL("echo"), req.url());
+  }
+
+  {
+    TestDelegate d;
+    d.set_quit_on_redirect(true);
+    URLRequest req(redirect_url, DEFAULT_PRIORITY, &d, &default_context_);
+    req.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(1, d.received_redirect_count());
+    EXPECT_EQ(0, d.response_started_count());
+    EXPECT_TRUE(req.was_cached());
+
+    req.FollowDeferredRedirect();
+    base::RunLoop().Run();
+    EXPECT_EQ(1, d.received_redirect_count());
+    EXPECT_EQ(1, d.response_started_count());
+    EXPECT_EQ(URLRequestStatus::SUCCESS, req.status().status());
+    EXPECT_EQ(test_server_.GetURL("echo"), req.url());
+  }
+}
+
+// Make sure a request isn't cached when a NetworkDelegate forces a redirect
+// when the headers are read, since the body won't have been read.
+TEST_F(URLRequestTestHTTP, NoCacheOnNetworkDelegateRedirect) {
+  ASSERT_TRUE(test_server_.Start());
+  // URL that is normally cached.
+  GURL initial_url = test_server_.GetURL("cachetime");
+
+  {
+    // Set up the TestNetworkDelegate tp force a redirect.
+    GURL redirect_to_url = test_server_.GetURL("echo");
+    default_network_delegate_.set_redirect_on_headers_received_url(
+        redirect_to_url);
+
+    TestDelegate d;
+    URLRequest req(initial_url, DEFAULT_PRIORITY, &d, &default_context_);
+    req.Start();
+    base::RunLoop().Run();
+    EXPECT_EQ(URLRequestStatus::SUCCESS, req.status().status());
+    EXPECT_EQ(1, d.received_redirect_count());
+    EXPECT_EQ(redirect_to_url, req.url());
+  }
+
+  {
+    TestDelegate d;
+    URLRequest req(initial_url, DEFAULT_PRIORITY, &d, &default_context_);
+    req.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(URLRequestStatus::SUCCESS, req.status().status());
+    EXPECT_FALSE(req.was_cached());
+    EXPECT_EQ(0, d.received_redirect_count());
+    EXPECT_EQ(initial_url, req.url());
+  }
+}
+
+// Tests that redirection to an unsafe URL is allowed when it has been marked as
+// safe.
+TEST_F(URLRequestTestHTTP, UnsafeRedirectToWhitelistedUnsafeURL) {
+  ASSERT_TRUE(test_server_.Start());
+
+  GURL unsafe_url("data:text/html,this-is-considered-an-unsafe-url");
+  default_network_delegate_.set_redirect_on_headers_received_url(unsafe_url);
+  default_network_delegate_.set_allowed_unsafe_redirect_url(unsafe_url);
+
+  TestDelegate d;
+  {
+    URLRequest r(test_server_.GetURL("whatever"),
+                 DEFAULT_PRIORITY,
+                 &d,
+                 &default_context_);
+
+    r.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+
+    EXPECT_EQ(2U, r.url_chain().size());
+    EXPECT_EQ(net::OK, r.status().error());
+    EXPECT_EQ(unsafe_url, r.url());
+    EXPECT_EQ("this-is-considered-an-unsafe-url", d.data_received());
+  }
+}
+
+// Tests that a redirect to a different unsafe URL is blocked, even after adding
+// some other URL to the whitelist.
+TEST_F(URLRequestTestHTTP, UnsafeRedirectToDifferentUnsafeURL) {
+  ASSERT_TRUE(test_server_.Start());
+
+  GURL unsafe_url("data:text/html,something");
+  GURL different_unsafe_url("data:text/html,something-else");
+  default_network_delegate_.set_redirect_on_headers_received_url(unsafe_url);
+  default_network_delegate_.set_allowed_unsafe_redirect_url(
+      different_unsafe_url);
+
+  TestDelegate d;
+  {
+    URLRequest r(test_server_.GetURL("whatever"),
+                 DEFAULT_PRIORITY,
+                 &d,
+                 &default_context_);
+
+    r.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(URLRequestStatus::FAILED, r.status().status());
+    EXPECT_EQ(ERR_UNSAFE_REDIRECT, r.status().error());
+  }
+}
+
+// Redirects from an URL with fragment to an unsafe URL without fragment should
+// be allowed.
+TEST_F(URLRequestTestHTTP, UnsafeRedirectWithReferenceFragment) {
+  ASSERT_TRUE(test_server_.Start());
+
+  GURL original_url(test_server_.GetURL("original#fragment"));
+  GURL unsafe_url("data:,url-marked-safe-and-used-in-redirect");
+  GURL expected_url("data:,url-marked-safe-and-used-in-redirect#fragment");
+
+  default_network_delegate_.set_redirect_on_headers_received_url(unsafe_url);
+  default_network_delegate_.set_allowed_unsafe_redirect_url(unsafe_url);
+
+  TestDelegate d;
+  {
+    URLRequest r(original_url, DEFAULT_PRIORITY, &d, &default_context_);
+
+    r.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(2U, r.url_chain().size());
+    EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+    EXPECT_EQ(net::OK, r.status().error());
+    EXPECT_EQ(original_url, r.original_url());
+    EXPECT_EQ(expected_url, r.url());
+  }
+}
+
+// Redirects from an URL with fragment to an unsafe URL with fragment should
+// be allowed, and the reference fragment of the target URL should be preserved.
+TEST_F(URLRequestTestHTTP, UnsafeRedirectWithDifferentReferenceFragment) {
+  ASSERT_TRUE(test_server_.Start());
+
+  GURL original_url(test_server_.GetURL("original#fragment1"));
+  GURL unsafe_url("data:,url-marked-safe-and-used-in-redirect#fragment2");
+  GURL expected_url("data:,url-marked-safe-and-used-in-redirect#fragment2");
+
+  default_network_delegate_.set_redirect_on_headers_received_url(unsafe_url);
+  default_network_delegate_.set_allowed_unsafe_redirect_url(unsafe_url);
+
+  TestDelegate d;
+  {
+    URLRequest r(original_url, DEFAULT_PRIORITY, &d, &default_context_);
+
+    r.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(2U, r.url_chain().size());
+    EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+    EXPECT_EQ(net::OK, r.status().error());
+    EXPECT_EQ(original_url, r.original_url());
+    EXPECT_EQ(expected_url, r.url());
+  }
+}
+
+// When a delegate has specified a safe redirect URL, but it does not match the
+// redirect target, then do not prevent the reference fragment from being added.
+TEST_F(URLRequestTestHTTP, RedirectWithReferenceFragment) {
+  ASSERT_TRUE(test_server_.Start());
+
+  GURL original_url(test_server_.GetURL("original#expected-fragment"));
+  GURL unsafe_url("data:text/html,this-url-does-not-match-redirect-url");
+  GURL redirect_url(test_server_.GetURL("target"));
+  GURL expected_redirect_url(test_server_.GetURL("target#expected-fragment"));
+
+  default_network_delegate_.set_redirect_on_headers_received_url(redirect_url);
+  default_network_delegate_.set_allowed_unsafe_redirect_url(unsafe_url);
+
+  TestDelegate d;
+  {
+    URLRequest r(original_url, DEFAULT_PRIORITY, &d, &default_context_);
+
+    r.Start();
+    base::RunLoop().Run();
+
+    EXPECT_EQ(2U, r.url_chain().size());
+    EXPECT_EQ(URLRequestStatus::SUCCESS, r.status().status());
+    EXPECT_EQ(net::OK, r.status().error());
+    EXPECT_EQ(original_url, r.original_url());
+    EXPECT_EQ(expected_redirect_url, r.url());
+  }
+}
+
 TEST_F(URLRequestTestHTTP, NoUserPassInReferrer) {
   ASSERT_TRUE(test_server_.Start());
 
@@ -6204,12 +6454,11 @@
 // Tests TLSv1.1 -> TLSv1 fallback. Verifies that we don't fall back more
 // than necessary.
 TEST_F(HTTPSRequestTest, TLSv1Fallback) {
-  uint16 default_version_max = SSLConfigService::default_version_max();
   // The OpenSSL library in use may not support TLS 1.1.
 #if !defined(USE_OPENSSL)
-  EXPECT_GT(default_version_max, SSL_PROTOCOL_VERSION_TLS1);
+  EXPECT_GT(kDefaultSSLVersionMax, SSL_PROTOCOL_VERSION_TLS1);
 #endif
-  if (default_version_max <= SSL_PROTOCOL_VERSION_TLS1)
+  if (kDefaultSSLVersionMax <= SSL_PROTOCOL_VERSION_TLS1)
     return;
 
   SpawnedTestServer::SSLOptions ssl_options(
@@ -6944,12 +7193,12 @@
 // several tests are effected because our testing EV certificate won't be
 // recognised as EV.
 static bool SystemUsesChromiumEVMetadata() {
-#if defined(USE_OPENSSL)
+#if defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID)
   // http://crbug.com/117478 - OpenSSL does not support EV validation.
   return false;
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
-  // On OS X, we use the system to tell us whether a certificate is EV or not
-  // and the system won't recognise our testing root.
+#elif (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_ANDROID)
+  // On OS X and Android, we use the system to tell us whether a certificate is
+  // EV or not and the system won't recognise our testing root.
   return false;
 #else
   return true;
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc
index ed8a92b..25df3a4 100644
--- a/net/websockets/websocket_channel.cc
+++ b/net/websockets/websocket_channel.cc
@@ -4,12 +4,16 @@
 
 #include "net/websockets/websocket_channel.h"
 
+#include <limits.h>  // for INT_MAX
+
 #include <algorithm>
+#include <deque>
 
 #include "base/basictypes.h"  // for size_t
 #include "base/big_endian.h"
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "base/numerics/safe_conversions.h"
@@ -167,8 +171,7 @@
   }
 
   virtual void OnFinishOpeningHandshake(
-      scoped_ptr<WebSocketHandshakeResponseInfo> response)
-      OVERRIDE {
+      scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE {
     creator_->OnFinishOpeningHandshake(response.Pass());
   }
 
@@ -217,7 +220,8 @@
 };
 
 WebSocketChannel::HandshakeNotificationSender::HandshakeNotificationSender(
-    WebSocketChannel* channel) : owner_(channel) {}
+    WebSocketChannel* channel)
+    : owner_(channel) {}
 
 WebSocketChannel::HandshakeNotificationSender::~HandshakeNotificationSender() {}
 
@@ -235,13 +239,13 @@
 
   if (handshake_request_info_.get()) {
     if (CHANNEL_DELETED == event_interface->OnStartOpeningHandshake(
-            handshake_request_info_.Pass()))
+                               handshake_request_info_.Pass()))
       return CHANNEL_DELETED;
   }
 
   if (handshake_response_info_.get()) {
     if (CHANNEL_DELETED == event_interface->OnFinishOpeningHandshake(
-            handshake_response_info_.Pass()))
+                               handshake_response_info_.Pass()))
       return CHANNEL_DELETED;
 
     // TODO(yhirano): We can release |this| to save memory because
@@ -251,6 +255,31 @@
   return CHANNEL_ALIVE;
 }
 
+WebSocketChannel::PendingReceivedFrame::PendingReceivedFrame(
+    bool final,
+    WebSocketFrameHeader::OpCode opcode,
+    const scoped_refptr<IOBuffer>& data,
+    size_t offset,
+    size_t size)
+    : final_(final),
+      opcode_(opcode),
+      data_(data),
+      offset_(offset),
+      size_(size) {}
+
+WebSocketChannel::PendingReceivedFrame::~PendingReceivedFrame() {}
+
+void WebSocketChannel::PendingReceivedFrame::ResetOpcode() {
+  DCHECK(WebSocketFrameHeader::IsKnownDataOpCode(opcode_));
+  opcode_ = WebSocketFrameHeader::kOpCodeContinuation;
+}
+
+void WebSocketChannel::PendingReceivedFrame::DidConsume(size_t bytes) {
+  DCHECK_LE(offset_, size_);
+  DCHECK_LE(bytes, size_ - offset_);
+  offset_ += bytes;
+}
+
 WebSocketChannel::WebSocketChannel(
     scoped_ptr<WebSocketEventInterface> event_interface,
     URLRequestContext* url_request_context)
@@ -259,6 +288,7 @@
       send_quota_low_water_mark_(kDefaultSendQuotaLowWaterMark),
       send_quota_high_water_mark_(kDefaultSendQuotaHighWaterMark),
       current_send_quota_(0),
+      current_receive_quota_(0),
       timeout_(base::TimeDelta::FromSeconds(kClosingHandshakeTimeoutSeconds)),
       received_close_code_(0),
       state_(FRESHLY_CONSTRUCTED),
@@ -357,15 +387,54 @@
   // server is not saturated.
   scoped_refptr<IOBuffer> buffer(new IOBuffer(data.size()));
   std::copy(data.begin(), data.end(), buffer->data());
-  AllowUnused(SendIOBuffer(fin, op_code, buffer, data.size()));
+  AllowUnused(SendFrameFromIOBuffer(fin, op_code, buffer, data.size()));
   // |this| may have been deleted.
 }
 
 void WebSocketChannel::SendFlowControl(int64 quota) {
   DCHECK(state_ == CONNECTING || state_ == CONNECTED || state_ == SEND_CLOSED ||
          state_ == CLOSE_WAIT);
-  // TODO(ricea): Add interface to WebSocketStream and implement.
-  // stream_->SendFlowControl(quota);
+  // TODO(ricea): Kill the renderer if it tries to send us a negative quota
+  // value or > INT_MAX.
+  DCHECK_GE(quota, 0);
+  DCHECK_LE(quota, INT_MAX);
+  if (!pending_received_frames_.empty()) {
+    DCHECK_EQ(0, current_receive_quota_);
+  }
+  while (!pending_received_frames_.empty() && quota > 0) {
+    PendingReceivedFrame& front = pending_received_frames_.front();
+    const size_t data_size = front.size() - front.offset();
+    const size_t bytes_to_send =
+        std::min(base::checked_cast<size_t>(quota), data_size);
+    const bool final = front.final() && data_size == bytes_to_send;
+    const char* data = front.data()->data() + front.offset();
+    const std::vector<char> data_vector(data, data + bytes_to_send);
+    DVLOG(3) << "Sending frame previously split due to quota to the "
+             << "renderer: quota=" << quota << " data_size=" << data_size
+             << " bytes_to_send=" << bytes_to_send;
+    if (event_interface_->OnDataFrame(final, front.opcode(), data_vector) ==
+        CHANNEL_DELETED)
+      return;
+    if (bytes_to_send < data_size) {
+      front.DidConsume(bytes_to_send);
+      front.ResetOpcode();
+      return;
+    }
+    const int64 signed_bytes_to_send = base::checked_cast<int64>(bytes_to_send);
+    DCHECK_GE(quota, signed_bytes_to_send);
+    quota -= signed_bytes_to_send;
+
+    pending_received_frames_.pop();
+  }
+  // If current_receive_quota_ == 0 then there is no pending ReadFrames()
+  // operation.
+  const bool start_read =
+      current_receive_quota_ == 0 && quota > 0 &&
+      (state_ == CONNECTED || state_ == SEND_CLOSED || state_ == CLOSE_WAIT);
+  current_receive_quota_ += base::checked_cast<int>(quota);
+  if (start_read)
+    AllowUnused(ReadFrames());
+  // |this| may have been deleted.
 }
 
 void WebSocketChannel::StartClosingHandshake(uint16 code,
@@ -465,6 +534,7 @@
 
   // |stream_request_| is not used once the connection has succeeded.
   stream_request_.reset();
+
   AllowUnused(ReadFrames());
   // |this| may have been deleted.
 }
@@ -574,7 +644,7 @@
 
 ChannelState WebSocketChannel::ReadFrames() {
   int result = OK;
-  do {
+  while (result == OK && current_receive_quota_ > 0) {
     // This use of base::Unretained is safe because this object owns the
     // WebSocketStream, and any pending reads will be cancelled when it is
     // destroyed.
@@ -588,7 +658,7 @@
         return CHANNEL_DELETED;
     }
     DCHECK_NE(CLOSED, state_);
-  } while (result == OK);
+  }
   return CHANNEL_ALIVE;
 }
 
@@ -642,8 +712,7 @@
   }
 }
 
-ChannelState WebSocketChannel::HandleFrame(
-    scoped_ptr<WebSocketFrame> frame) {
+ChannelState WebSocketChannel::HandleFrame(scoped_ptr<WebSocketFrame> frame) {
   if (frame->header.masked) {
     // RFC6455 Section 5.1 "A client MUST close a connection if it detects a
     // masked frame."
@@ -691,7 +760,7 @@
         frame_name + " received after close", kWebSocketErrorProtocolError, "");
   }
   switch (opcode) {
-    case WebSocketFrameHeader::kOpCodeText:    // fall-thru
+    case WebSocketFrameHeader::kOpCodeText:  // fall-thru
     case WebSocketFrameHeader::kOpCodeBinary:
     case WebSocketFrameHeader::kOpCodeContinuation:
       return HandleDataFrame(opcode, final, data_buffer, size);
@@ -699,7 +768,7 @@
     case WebSocketFrameHeader::kOpCodePing:
       VLOG(1) << "Got Ping of size " << size;
       if (state_ == CONNECTED)
-        return SendIOBuffer(
+        return SendFrameFromIOBuffer(
             true, WebSocketFrameHeader::kOpCodePong, data_buffer, size);
       VLOG(3) << "Ignored ping in state " << state_;
       return CHANNEL_ALIVE;
@@ -710,6 +779,10 @@
       return CHANNEL_ALIVE;
 
     case WebSocketFrameHeader::kOpCodeClose: {
+      // TODO(ricea): If there is a message which is queued for transmission to
+      // the renderer, then the renderer should not receive an
+      // OnClosingHandshake or OnDropChannel IPC until the queued message has
+      // been completedly transmitted.
       uint16 code = kWebSocketNormalClosure;
       std::string reason;
       std::string message;
@@ -807,20 +880,34 @@
     return CHANNEL_ALIVE;
 
   initial_frame_forwarded_ = !final;
+  if (size > base::checked_cast<size_t>(current_receive_quota_) ||
+      !pending_received_frames_.empty()) {
+    const bool no_quota = (current_receive_quota_ == 0);
+    DCHECK(no_quota || pending_received_frames_.empty());
+    DVLOG(3) << "Queueing frame to renderer due to quota. quota="
+             << current_receive_quota_ << " size=" << size;
+    WebSocketFrameHeader::OpCode opcode_to_queue =
+        no_quota ? opcode_to_send : WebSocketFrameHeader::kOpCodeContinuation;
+    pending_received_frames_.push(PendingReceivedFrame(
+        final, opcode_to_queue, data_buffer, current_receive_quota_, size));
+    if (no_quota)
+      return CHANNEL_ALIVE;
+    size = current_receive_quota_;
+    final = false;
+  }
+
   // TODO(ricea): Can this copy be eliminated?
   const char* const data_begin = size ? data_buffer->data() : NULL;
   const char* const data_end = data_begin + size;
   const std::vector<char> data(data_begin, data_end);
-  // TODO(ricea): Handle the case when ReadFrames returns far
-  // more data at once than should be sent in a single IPC. This needs to
-  // be handled carefully, as an overloaded IO thread is one possible
-  // cause of receiving very large chunks.
+  current_receive_quota_ -= size;
+  DCHECK_GE(current_receive_quota_, 0);
 
   // Sends the received frame to the renderer process.
   return event_interface_->OnDataFrame(final, opcode_to_send, data);
 }
 
-ChannelState WebSocketChannel::SendIOBuffer(
+ChannelState WebSocketChannel::SendFrameFromIOBuffer(
     bool fin,
     WebSocketFrameHeader::OpCode op_code,
     const scoped_refptr<IOBuffer>& buffer,
@@ -898,7 +985,8 @@
       FROM_HERE,
       timeout_,
       base::Bind(&WebSocketChannel::CloseTimeout, base::Unretained(this)));
-  if (SendIOBuffer(true, WebSocketFrameHeader::kOpCodeClose, body, size) ==
+  if (SendFrameFromIOBuffer(
+          true, WebSocketFrameHeader::kOpCodeClose, body, size) ==
       CHANNEL_DELETED)
     return CHANNEL_DELETED;
   return CHANNEL_ALIVE;
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h
index 183f2be..80c4290 100644
--- a/net/websockets/websocket_channel.h
+++ b/net/websockets/websocket_channel.h
@@ -5,6 +5,7 @@
 #ifndef NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
 #define NET_WEBSOCKETS_WEBSOCKET_CHANNEL_H_
 
+#include <queue>
 #include <string>
 #include <vector>
 
@@ -12,6 +13,7 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"  // for WARN_UNUSED_RESULT
 #include "base/i18n/streaming_utf8_validator.h"
+#include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/scoped_vector.h"
 #include "base/time/time.h"
@@ -121,6 +123,42 @@
  private:
   class HandshakeNotificationSender;
 
+  // The Windows implementation of std::queue requires that this declaration be
+  // visible in the header.
+  class PendingReceivedFrame {
+   public:
+    PendingReceivedFrame(bool final,
+                         WebSocketFrameHeader::OpCode opcode,
+                         const scoped_refptr<IOBuffer>& data,
+                         size_t offset,
+                         size_t size);
+    ~PendingReceivedFrame();
+
+    bool final() const { return final_; }
+    WebSocketFrameHeader::OpCode opcode() const { return opcode_; }
+    // ResetOpcode() to Continuation.
+    void ResetOpcode();
+    const scoped_refptr<IOBuffer>& data() const { return data_; }
+    size_t offset() const { return offset_; }
+    size_t size() const { return size_; }
+    // Increase |offset_| by |bytes|.
+    void DidConsume(size_t bytes);
+
+    // This object needs to be copyable and assignable, since it will be placed
+    // in a std::queue. The compiler-generated copy constructor and assignment
+    // operator will do the right thing.
+
+   private:
+    bool final_;
+    WebSocketFrameHeader::OpCode opcode_;
+    scoped_refptr<IOBuffer> data_;
+    // Where to start reading from data_. Everything prior to offset_ has
+    // already been sent to the browser.
+    size_t offset_;
+    // The size of data_.
+    size_t size_;
+  };
+
   // Methods which return a value of type ChannelState may delete |this|. If the
   // return value is CHANNEL_DELETED, then the caller must return without making
   // any further access to member variables or methods.
@@ -183,7 +221,8 @@
   // WriteFrames() itself.
   ChannelState OnWriteDone(bool synchronous, int result) WARN_UNUSED_RESULT;
 
-  // Calls WebSocketStream::ReadFrames() with the appropriate arguments.
+  // Calls WebSocketStream::ReadFrames() with the appropriate arguments. Stops
+  // calling ReadFrames if current_receive_quota_ is 0.
   ChannelState ReadFrames() WARN_UNUSED_RESULT;
 
   // Callback from WebSocketStream::ReadFrames. Handles any errors and processes
@@ -223,10 +262,10 @@
   // when the current write finishes. |fin| and |op_code| are defined as for
   // SendFrame() above, except that |op_code| may also be a control frame
   // opcode.
-  ChannelState SendIOBuffer(bool fin,
-                            WebSocketFrameHeader::OpCode op_code,
-                            const scoped_refptr<IOBuffer>& buffer,
-                            size_t size) WARN_UNUSED_RESULT;
+  ChannelState SendFrameFromIOBuffer(bool fin,
+                                     WebSocketFrameHeader::OpCode op_code,
+                                     const scoped_refptr<IOBuffer>& buffer,
+                                     size_t size) WARN_UNUSED_RESULT;
 
   // Performs the "Fail the WebSocket Connection" operation as defined in
   // RFC6455. A NotifyFailure message is sent to the renderer with |message|.
@@ -297,6 +336,10 @@
   // Destination for the current call to WebSocketStream::ReadFrames
   ScopedVector<WebSocketFrame> read_frames_;
 
+  // Frames that have been read but not yet forwarded to the renderer due to
+  // lack of quota.
+  std::queue<PendingReceivedFrame> pending_received_frames_;
+
   // Handle to an in-progress WebSocketStream creation request. Only non-NULL
   // during the connection process.
   scoped_ptr<WebSocketStreamRequest> stream_request_;
@@ -311,6 +354,9 @@
   // The current amount of quota that the renderer has available for sending
   // on this logical channel (quota units).
   int current_send_quota_;
+  // The remaining amount of quota that the renderer will allow us to send on
+  // this logical channel (quota units).
+  int current_receive_quota_;
 
   // Timer for the closing handshake.
   base::OneShotTimer<WebSocketChannel> timer_;
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc
index 8d8686d..82078cb 100644
--- a/net/websockets/websocket_channel_test.cc
+++ b/net/websockets/websocket_channel_test.cc
@@ -4,6 +4,7 @@
 
 #include "net/websockets/websocket_channel.h"
 
+#include <limits.h>
 #include <string.h>
 
 #include <iostream>
@@ -129,13 +130,16 @@
 // in that time! I would like my tests to run a bit quicker.
 const int kVeryTinyTimeoutMillis = 1;
 
+// Enough quota to pass any test.
+const int64 kPlentyOfQuota = INT_MAX;
+
 typedef WebSocketEventInterface::ChannelState ChannelState;
 const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE;
 const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED;
 
 // This typedef mainly exists to avoid having to repeat the "NOLINT" incantation
 // all over the place.
-typedef MockFunction<void(int)> Checkpoint;  // NOLINT
+typedef StrictMock< MockFunction<void(int)> > Checkpoint;  // NOLINT
 
 // This mock is for testing expectations about how the EventInterface is used.
 class MockWebSocketEventInterface : public WebSocketEventInterface {
@@ -731,6 +735,9 @@
   // well. This method is virtual so that subclasses can also set the stream.
   virtual void CreateChannelAndConnectSuccessfully() {
     CreateChannelAndConnect();
+    // Most tests aren't concerned with flow control from the renderer, so allow
+    // MAX_INT quota units.
+    channel_->SendFlowControl(kPlentyOfQuota);
     connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
   }
 
@@ -944,6 +951,21 @@
   }
 };
 
+// Fixture for tests which test use of receive quota from the renderer.
+class WebSocketChannelFlowControlTest
+    : public WebSocketChannelEventInterfaceTest {
+ protected:
+  // Tests using this fixture should use CreateChannelAndConnectWithQuota()
+  // instead of CreateChannelAndConnectSuccessfully().
+  void CreateChannelAndConnectWithQuota(int64 quota) {
+    CreateChannelAndConnect();
+    channel_->SendFlowControl(quota);
+    connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
+  }
+
+  virtual void CreateChannelAndConnectSuccesfully() { NOTREACHED(); }
+};
+
 // Fixture for tests which test UTF-8 validation of received Text frames using a
 // mock WebSocketStream.
 class WebSocketChannelReceiveUtf8Test : public WebSocketChannelStreamTest {
@@ -2141,6 +2163,280 @@
   completion.WaitForResult();
 }
 
+// The renderer should provide us with some quota immediately, and then
+// WebSocketChannel calls ReadFrames as soon as the stream is available.
+TEST_F(WebSocketChannelStreamTest, FlowControlEarly) {
+  Checkpoint checkpoint;
+  EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+  EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
+  {
+    InSequence s;
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+        .WillOnce(Return(ERR_IO_PENDING));
+    EXPECT_CALL(checkpoint, Call(2));
+  }
+
+  set_stream(mock_stream_.Pass());
+  CreateChannelAndConnect();
+  channel_->SendFlowControl(kPlentyOfQuota);
+  checkpoint.Call(1);
+  connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
+  checkpoint.Call(2);
+}
+
+// If for some reason the connect succeeds before the renderer sends us quota,
+// we shouldn't call ReadFrames() immediately.
+// TODO(ricea): Actually we should call ReadFrames() with a small limit so we
+// can still handle control frames. This should be done once we have any API to
+// expose quota to the lower levels.
+TEST_F(WebSocketChannelStreamTest, FlowControlLate) {
+  Checkpoint checkpoint;
+  EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+  EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
+  {
+    InSequence s;
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+        .WillOnce(Return(ERR_IO_PENDING));
+    EXPECT_CALL(checkpoint, Call(2));
+  }
+
+  set_stream(mock_stream_.Pass());
+  CreateChannelAndConnect();
+  connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
+  checkpoint.Call(1);
+  channel_->SendFlowControl(kPlentyOfQuota);
+  checkpoint.Call(2);
+}
+
+// We should stop calling ReadFrames() when all quota is used.
+TEST_F(WebSocketChannelStreamTest, FlowControlStopsReadFrames) {
+  static const InitFrame frames[] = {
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
+
+  EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+  EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
+  EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+      .WillOnce(ReturnFrames(&frames));
+
+  set_stream(mock_stream_.Pass());
+  CreateChannelAndConnect();
+  channel_->SendFlowControl(4);
+  connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
+}
+
+// Providing extra quota causes ReadFrames() to be called again.
+TEST_F(WebSocketChannelStreamTest, FlowControlStartsWithMoreQuota) {
+  static const InitFrame frames[] = {
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
+  Checkpoint checkpoint;
+
+  EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+  EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
+  {
+    InSequence s;
+    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+        .WillOnce(ReturnFrames(&frames));
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+        .WillOnce(Return(ERR_IO_PENDING));
+  }
+
+  set_stream(mock_stream_.Pass());
+  CreateChannelAndConnect();
+  channel_->SendFlowControl(4);
+  connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
+  checkpoint.Call(1);
+  channel_->SendFlowControl(4);
+}
+
+// ReadFrames() isn't called again until all pending data has been passed to
+// the renderer.
+TEST_F(WebSocketChannelStreamTest, ReadFramesNotCalledUntilQuotaAvailable) {
+  static const InitFrame frames[] = {
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
+  Checkpoint checkpoint;
+
+  EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
+  EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
+  {
+    InSequence s;
+    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+        .WillOnce(ReturnFrames(&frames));
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(checkpoint, Call(2));
+    EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+        .WillOnce(Return(ERR_IO_PENDING));
+  }
+
+  set_stream(mock_stream_.Pass());
+  CreateChannelAndConnect();
+  channel_->SendFlowControl(2);
+  connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
+  checkpoint.Call(1);
+  channel_->SendFlowControl(2);
+  checkpoint.Call(2);
+  channel_->SendFlowControl(2);
+}
+
+// A message that needs to be split into frames to fit within quota should
+// maintain correct semantics.
+TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitSync) {
+  scoped_ptr<ReadableFakeWebSocketStream> stream(
+      new ReadableFakeWebSocketStream);
+  static const InitFrame frames[] = {
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
+  stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+  set_stream(stream.Pass());
+  {
+    InSequence s;
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
+    EXPECT_CALL(*event_interface_, OnFlowControl(_));
+    EXPECT_CALL(
+        *event_interface_,
+        OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
+    EXPECT_CALL(
+        *event_interface_,
+        OnDataFrame(
+            false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
+    EXPECT_CALL(
+        *event_interface_,
+        OnDataFrame(
+            true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
+  }
+
+  CreateChannelAndConnectWithQuota(2);
+  channel_->SendFlowControl(1);
+  channel_->SendFlowControl(1);
+}
+
+// The code path for async messages is slightly different, so test it
+// separately.
+TEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitAsync) {
+  scoped_ptr<ReadableFakeWebSocketStream> stream(
+      new ReadableFakeWebSocketStream);
+  static const InitFrame frames[] = {
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}};
+  stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
+  set_stream(stream.Pass());
+  Checkpoint checkpoint;
+  {
+    InSequence s;
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
+    EXPECT_CALL(*event_interface_, OnFlowControl(_));
+    EXPECT_CALL(checkpoint, Call(1));
+    EXPECT_CALL(
+        *event_interface_,
+        OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO")));
+    EXPECT_CALL(checkpoint, Call(2));
+    EXPECT_CALL(
+        *event_interface_,
+        OnDataFrame(
+            false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U")));
+    EXPECT_CALL(checkpoint, Call(3));
+    EXPECT_CALL(
+        *event_interface_,
+        OnDataFrame(
+            true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R")));
+  }
+
+  CreateChannelAndConnectWithQuota(2);
+  checkpoint.Call(1);
+  base::MessageLoop::current()->RunUntilIdle();
+  checkpoint.Call(2);
+  channel_->SendFlowControl(1);
+  checkpoint.Call(3);
+  channel_->SendFlowControl(1);
+}
+
+// A message split into multiple frames which is further split due to quota
+// restrictions should stil be correct.
+// TODO(ricea): The message ends up split into more frames than are strictly
+// necessary. The complexity/performance tradeoffs here need further
+// examination.
+TEST_F(WebSocketChannelFlowControlTest, MultipleFrameSplit) {
+  scoped_ptr<ReadableFakeWebSocketStream> stream(
+      new ReadableFakeWebSocketStream);
+  static const InitFrame frames[] = {
+      {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
+       NOT_MASKED,      "FIRST FRAME IS 25 BYTES. "},
+      {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
+       NOT_MASKED,      "SECOND FRAME IS 26 BYTES. "},
+      {FINAL_FRAME,     WebSocketFrameHeader::kOpCodeContinuation,
+       NOT_MASKED,      "FINAL FRAME IS 24 BYTES."}};
+  stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+  set_stream(stream.Pass());
+  {
+    InSequence s;
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
+    EXPECT_CALL(*event_interface_, OnFlowControl(_));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(false,
+                            WebSocketFrameHeader::kOpCodeText,
+                            AsVector("FIRST FRAME IS")));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(false,
+                            WebSocketFrameHeader::kOpCodeContinuation,
+                            AsVector(" 25 BYTES. ")));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(false,
+                            WebSocketFrameHeader::kOpCodeContinuation,
+                            AsVector("SECOND FRAME IS 26 BYTES. ")));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(false,
+                            WebSocketFrameHeader::kOpCodeContinuation,
+                            AsVector("FINAL ")));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(true,
+                            WebSocketFrameHeader::kOpCodeContinuation,
+                            AsVector("FRAME IS 24 BYTES.")));
+  }
+  CreateChannelAndConnectWithQuota(14);
+  channel_->SendFlowControl(43);
+  channel_->SendFlowControl(32);
+}
+
+// An empty message handled when we are out of quota must not be delivered
+// out-of-order with respect to other messages.
+TEST_F(WebSocketChannelFlowControlTest, EmptyMessageNoQuota) {
+  scoped_ptr<ReadableFakeWebSocketStream> stream(
+      new ReadableFakeWebSocketStream);
+  static const InitFrame frames[] = {
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
+       NOT_MASKED,  "FIRST MESSAGE"},
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
+       NOT_MASKED,  ""},
+      {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
+       NOT_MASKED,  "THIRD MESSAGE"}};
+  stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
+  set_stream(stream.Pass());
+  {
+    InSequence s;
+    EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _));
+    EXPECT_CALL(*event_interface_, OnFlowControl(_));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(false,
+                            WebSocketFrameHeader::kOpCodeText,
+                            AsVector("FIRST ")));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(true,
+                            WebSocketFrameHeader::kOpCodeContinuation,
+                            AsVector("MESSAGE")));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(true,
+                            WebSocketFrameHeader::kOpCodeText,
+                            AsVector("")));
+    EXPECT_CALL(*event_interface_,
+                OnDataFrame(true,
+                            WebSocketFrameHeader::kOpCodeText,
+                            AsVector("THIRD MESSAGE")));
+  }
+
+  CreateChannelAndConnectWithQuota(6);
+  channel_->SendFlowControl(128);
+}
+
 // RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
 // WebSocketChannel actually only sets the mask bit in the header, it doesn't
 // perform masking itself (not all transports actually use masking).
@@ -2490,13 +2786,9 @@
   write_callback.Run(OK);
 }
 
-// When the renderer sends more on a channel than it has quota for, then we send
-// a kWebSocketMuxErrorSendQuotaViolation status code (from the draft websocket
-// mux specification) back to the renderer. This should not be sent to the
-// remote server, which may not even implement the mux specification, and could
-// even be using a different extension which uses that code to mean something
-// else.
-TEST_F(WebSocketChannelStreamTest, MuxErrorIsNotSentToStream) {
+// When the renderer sends more on a channel than it has quota for, we send the
+// remote server a kWebSocketErrorGoingAway error code.
+TEST_F(WebSocketChannelStreamTest, SendGoingAwayOnRendererQuotaExceeded) {
   static const InitFrame expected[] = {
       {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
        MASKED,      CLOSE_DATA(GOING_AWAY, "")}};
@@ -2974,6 +3266,7 @@
   virtual void CreateChannelAndConnectSuccessfully() OVERRIDE {
     set_stream(mock_stream_.Pass());
     CreateChannelAndConnect();
+    channel_->SendFlowControl(kPlentyOfQuota);
     channel_->SetClosingHandshakeTimeoutForTesting(
         TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis));
     connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass());
diff --git a/net/websockets/websocket_job_test.cc b/net/websockets/websocket_job_test.cc
index 3d7d424..e12ddae 100644
--- a/net/websockets/websocket_job_test.cc
+++ b/net/websockets/websocket_job_test.cc
@@ -204,6 +204,12 @@
       callback.Run(GetCookiesWithOptions(url, options));
   }
 
+  virtual void GetAllCookiesForURLAsync(
+      const GURL& url,
+      const GetCookieListCallback& callback) OVERRIDE {
+    ADD_FAILURE();
+  }
+
   virtual void DeleteCookieAsync(const GURL& url,
                                  const std::string& cookie_name,
                                  const base::Closure& callback) OVERRIDE {
diff --git a/ppapi/api/dev/ppb_find_dev.idl b/ppapi/api/dev/ppb_find_dev.idl
deleted file mode 100644
index d43e62b..0000000
--- a/ppapi/api/dev/ppb_find_dev.idl
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**
- * This file defines the <code>PPB_Find_Dev</code> interface.
- */
-
-[generate_thunk]
-
-label Chrome {
-  M14 = 0.3
-};
-
-// TODO(raymes): Make PPP/PPB_Find_Dev a private interface. It's only used by
-// PDF currently and it's restrictive in the way it can be used.
-interface PPB_Find_Dev {
-  /**
-   * Sets the instance of this plugin as the mechanism that will be used to
-   * handle find requests in the renderer. This will only succeed if the plugin
-   * is embedded within the content of the top level frame. Note that this will
-   * result in the renderer handing over all responsibility for doing find to
-   * the plugin and content from the rest of the page will not be searched.
-   *
-   *
-   * In the case that the plugin is loaded directly as the top level document,
-   * this function does not need to be called. In that case the plugin is
-   * assumed to handle find requests.
-   *
-   * There can only be one plugin which handles find requests. If a plugin calls
-   * this while an existing plugin is registered, the existing plugin will be
-   * de-registered and will no longer receive any requests.
-   */
-  void SetPluginToHandleFindRequests(
-      [in] PP_Instance instance);
-
-  /**
-   * Updates the number of find results for the current search term.  If
-   * there are no matches 0 should be passed in.  Only when the plugin has
-   * finished searching should it pass in the final count with final_result set
-   * to PP_TRUE.
-   */
-  void NumberOfFindResultsChanged(
-      [in] PP_Instance instance,
-      [in] int32_t total,
-      [in] PP_Bool final_result);
-
-  /**
-   * Updates the index of the currently selected search item.
-   */
-  void SelectedFindResultChanged(
-      [in] PP_Instance instance,
-      [in] int32_t index);
-};
-
diff --git a/ppapi/api/dev/ppp_find_dev.idl b/ppapi/api/dev/ppp_find_dev.idl
deleted file mode 100644
index d277d95..0000000
--- a/ppapi/api/dev/ppp_find_dev.idl
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (c) 2014 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-label Chrome {
-  M14 = 0.3
-};
-
-/**
- * TODO(raymes): Make PPP/PPB_Find_Dev a private interface.
- */
-interface PPP_Find_Dev {
-  /**
-   * Finds the given UTF-8 text starting at the current selection. The number of
-   * results will be updated asynchronously via NumberOfFindResultsChanged in
-   * PPB_Find. Note that multiple StartFind calls can happen before StopFind is
-   * called in the case of the search term changing.
-   *
-   * Return PP_FALSE if the plugin doesn't support find in page. Consequently,
-   * it won't call any callbacks.
-   */
-  PP_Bool StartFind([in] PP_Instance instance,
-                    [in] str_t text,
-                    [in] PP_Bool case_sensitive);
-
-  /**
-   * Go to the next/previous result.
-   */
-  void SelectFindResult([in] PP_Instance instance,
-                        [in] PP_Bool forward);
-
-  /**
-   * Tells the plugin that the find operation has stopped, so it should clear
-   * any highlighting.
-   */
-  void StopFind([in] PP_Instance instance);
-};
diff --git a/ppapi/api/ppb_audio_buffer.idl b/ppapi/api/ppb_audio_buffer.idl
index 1083e0d..8640f00 100644
--- a/ppapi/api/ppb_audio_buffer.idl
+++ b/ppapi/api/ppb_audio_buffer.idl
@@ -10,7 +10,8 @@
 [generate_thunk]
 
 label Chrome {
-  [channel=dev] M34 = 0.1
+  [channel=dev] M34 = 0.1,
+  M35 = 0.1
 };
 
 /**
@@ -38,6 +39,7 @@
   PP_AUDIOBUFFER_SAMPLESIZE_16_BITS = 2
 };
 
+[version=0.1]
 interface PPB_AudioBuffer {
   /**
    * Determines if a resource is an AudioBuffer resource.
diff --git a/ppapi/api/ppb_media_stream_audio_track.idl b/ppapi/api/ppb_media_stream_audio_track.idl
index e1c2718..0f7aa72 100644
--- a/ppapi/api/ppb_media_stream_audio_track.idl
+++ b/ppapi/api/ppb_media_stream_audio_track.idl
@@ -6,13 +6,13 @@
 /**
  * Defines the <code>PPB_MediaStreamAudioTrack</code> interface. Used for
  * receiving audio samples from a MediaStream audio track in the browser.
- * This interface is still in development (Dev API status) and may change.
  */
 
 [generate_thunk]
 
 label Chrome {
-  [channel=dev] M34 = 0.1
+  [channel=dev] M34 = 0.1,
+  M35 = 0.1
 };
 
 /**
@@ -62,6 +62,7 @@
   PP_MEDIASTREAMAUDIOTRACK_ATTRIB_DURATION = 5
 };
 
+[version=0.1]
 interface PPB_MediaStreamAudioTrack {
   /**
    * Determines if a resource is a MediaStream audio track resource.
diff --git a/ppapi/api/ppb_media_stream_video_track.idl b/ppapi/api/ppb_media_stream_video_track.idl
index 199ebb2..91e9502 100644
--- a/ppapi/api/ppb_media_stream_video_track.idl
+++ b/ppapi/api/ppb_media_stream_video_track.idl
@@ -6,13 +6,13 @@
 /**
  * Defines the <code>PPB_MediaStreamVideoTrack</code> interface. Used for
  * receiving video frames from a MediaStream video track in the browser.
- * This interface is still in development (Dev API status) and may change.
  */
 
 [generate_thunk]
 
 label Chrome {
-  [channel=dev] M34 = 0.1
+  [channel=dev] M34 = 0.1,
+  M35 = 0.1
 };
 
 /**
@@ -71,6 +71,7 @@
   PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT = 4
 };
 
+[version=0.1]
 interface PPB_MediaStreamVideoTrack {
   /**
    * Determines if a resource is a MediaStream video track resource.
diff --git a/ppapi/api/ppb_video_frame.idl b/ppapi/api/ppb_video_frame.idl
index fc2d523..5737892 100644
--- a/ppapi/api/ppb_video_frame.idl
+++ b/ppapi/api/ppb_video_frame.idl
@@ -10,7 +10,8 @@
 [generate_thunk]
 
 label Chrome {
-  [channel=dev] M34 = 0.1
+  [channel=dev] M34 = 0.1,
+  M35 = 0.1
 };
 
 enum PP_VideoFrame_Format {
@@ -40,6 +41,7 @@
   PP_VIDEOFRAME_FORMAT_LAST = PP_VIDEOFRAME_FORMAT_BGRA
 };
 
+[version=0.1]
 interface PPB_VideoFrame {
   /**
    * Determines if a resource is a VideoFrame resource.
diff --git a/ppapi/api/private/ppb_find_private.idl b/ppapi/api/private/ppb_find_private.idl
new file mode 100644
index 0000000..e6f7cfa
--- /dev/null
+++ b/ppapi/api/private/ppb_find_private.idl
@@ -0,0 +1,66 @@
+/* Copyright 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**
+ * This file defines the <code>PPB_Find_Private</code> interface.
+ */
+
+[generate_thunk]
+
+label Chrome {
+  M14 = 0.3
+};
+
+/**
+ * This is a private interface for doing browser Find in the PDF plugin.
+ */
+interface PPB_Find_Private {
+  /**
+   * Sets the instance of this plugin as the mechanism that will be used to
+   * handle find requests in the renderer. This will only succeed if the plugin
+   * is embedded within the content of the top level frame. Note that this will
+   * result in the renderer handing over all responsibility for doing find to
+   * the plugin and content from the rest of the page will not be searched.
+   *
+   *
+   * In the case that the plugin is loaded directly as the top level document,
+   * this function does not need to be called. In that case the plugin is
+   * assumed to handle find requests.
+   *
+   * There can only be one plugin which handles find requests. If a plugin calls
+   * this while an existing plugin is registered, the existing plugin will be
+   * de-registered and will no longer receive any requests.
+   */
+  void SetPluginToHandleFindRequests(
+      [in] PP_Instance instance);
+
+  /**
+   * Updates the number of find results for the current search term.  If
+   * there are no matches 0 should be passed in.  Only when the plugin has
+   * finished searching should it pass in the final count with final_result set
+   * to PP_TRUE.
+   */
+  void NumberOfFindResultsChanged(
+      [in] PP_Instance instance,
+      [in] int32_t total,
+      [in] PP_Bool final_result);
+
+  /**
+   * Updates the index of the currently selected search item.
+   */
+  void SelectedFindResultChanged(
+      [in] PP_Instance instance,
+      [in] int32_t index);
+
+  /**
+   * Updates the tickmarks on the scrollbar for the find request. |tickmarks|
+   * contains |count| PP_Rects indicating the tickmark ranges.
+   */
+  void SetTickmarks(
+      [in] PP_Instance instance,
+      [in, size_as=count] PP_Rect[] tickmarks,
+      [in] uint32_t count);
+};
+
diff --git a/ppapi/api/private/ppb_nacl_private.idl b/ppapi/api/private/ppb_nacl_private.idl
index c17ab8b..9e321f6 100644
--- a/ppapi/api/private/ppb_nacl_private.idl
+++ b/ppapi/api/private/ppb_nacl_private.idl
@@ -121,6 +121,18 @@
   PP_SCHEME_OTHER
 };
 
+enum PP_NaClReadyState {
+  /* The trusted plugin begins in this ready state. */
+  PP_NACL_READY_STATE_UNSENT = 0,
+  /* The manifest file has been requested, but not yet received. */
+  PP_NACL_READY_STATE_OPENED = 1,
+  /* The manifest file has been received and the nexe successfully requested. */
+  PP_NACL_READY_STATE_LOADING = 3,
+  /* The nexe has been loaded and the proxy started, so it is ready for
+     interaction with the page. */
+  PP_NACL_READY_STATE_DONE = 4
+};
+
 /* PPB_NaCl_Private */
 interface PPB_NaCl_Private {
   /* Launches NaCl's sel_ldr process.  Returns PP_EXTERNAL_PLUGIN_OK on success
@@ -275,16 +287,18 @@
   void ReportLoadError([in] PP_Instance instance,
                        [in] PP_NaClError error,
                        [in] str_t error_message,
-                       [in] str_t console_message,
-                       [in] PP_Bool is_installed);
+                       [in] str_t console_message);
+
+  /* Performs internal setup when an instance is created. */
+  void InstanceCreated([in] PP_Instance instance);
 
   /* Performs internal cleanup when an instance is destroyed. */
   void InstanceDestroyed([in] PP_Instance instance);
 
-  /* Return true if the NaCl debug stub is enabled and the loaded app
-   * will be attached to a debugger.
+  /* Return true if the NaCl debug stub is enabled and the app loaded from
+   * alleged_nmf_url will be attached to a debugger.
    */
-  PP_Bool NaClDebugStubEnabled();
+  PP_Bool NaClDebugEnabledForURL([in] str_t alleged_nmf_url);
 
   /* Returns the kind of SFI sandbox implemented by NaCl on this
   /* platform.
@@ -297,4 +311,25 @@
   /* Logs the message to the console. */
   void LogToConsole([in] PP_Instance instance,
                     [in] str_t message);
+
+  /* Returns PP_TRUE if an error has been reported loading the nexe. */
+  PP_Bool GetNexeErrorReported([in] PP_Instance instance);
+
+  /* Sets the nexe error reported state for this instance. */
+  void SetNexeErrorReported([in] PP_Instance instance,
+                            [in] PP_Bool error_reported);
+
+  /* Returns the NaCl readiness status for this instance. */
+  PP_NaClReadyState GetNaClReadyState([in] PP_Instance instance);
+
+  /* Sets the NaCl readiness status for this instance. */
+  void SetNaClReadyState([in] PP_Instance instance,
+                         [in] PP_NaClReadyState ready_state);
+
+  /* Returns true if the plugin is an installed app. */
+  PP_Bool GetIsInstalled([in] PP_Instance instance);
+
+  /* Sets whether the plugin is an installed app. */
+  void SetIsInstalled([in] PP_Instance instance,
+                      [in] PP_Bool is_installed);
 };
diff --git a/ppapi/api/private/ppb_uma_private.idl b/ppapi/api/private/ppb_uma_private.idl
index a115cee..2d9b950 100644
--- a/ppapi/api/private/ppb_uma_private.idl
+++ b/ppapi/api/private/ppb_uma_private.idl
@@ -10,7 +10,7 @@
 [generate_thunk,thunk_include="ppapi/thunk/ppb_uma_singleton_api.h"]
 
 label Chrome {
-  M33 = 0.2
+  M35 = 0.3
 };
 
 /**
@@ -54,4 +54,14 @@
                             [in] PP_Var name,
                             [in] int32_t sample,
                             [in] int32_t boundary_value);
+
+  /**
+   * IsCrashReportingEnabled returns PP_OK to the completion callback to
+   * indicate that the current user has opted-in to crash reporting, or
+   * PP_ERROR_* on failure or when a user has not opted-in.  This can be used to
+   * gate other reporting processes such as analytics and crash reporting.
+   */
+   [singleton,api=PPB_UMA_Singleton_API]
+   int32_t IsCrashReportingEnabled([in] PP_Instance instance,
+                                   [in] PP_CompletionCallback callback);
 };
diff --git a/ppapi/api/private/ppp_find_private.idl b/ppapi/api/private/ppp_find_private.idl
new file mode 100644
index 0000000..bb6580c
--- /dev/null
+++ b/ppapi/api/private/ppp_find_private.idl
@@ -0,0 +1,35 @@
+/* Copyright 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+label Chrome {
+  M14 = 0.3
+};
+
+interface PPP_Find_Private {
+  /**
+   * Finds the given UTF-8 text starting at the current selection. The number of
+   * results will be updated asynchronously via NumberOfFindResultsChanged in
+   * PPB_Find. Note that multiple StartFind calls can happen before StopFind is
+   * called in the case of the search term changing.
+   *
+   * Return PP_FALSE if the plugin doesn't support find in page. Consequently,
+   * it won't call any callbacks.
+   */
+  PP_Bool StartFind([in] PP_Instance instance,
+                    [in] str_t text,
+                    [in] PP_Bool case_sensitive);
+
+  /**
+   * Go to the next/previous result.
+   */
+  void SelectFindResult([in] PP_Instance instance,
+                        [in] PP_Bool forward);
+
+  /**
+   * Tells the plugin that the find operation has stopped, so it should clear
+   * any highlighting.
+   */
+  void StopFind([in] PP_Instance instance);
+};
diff --git a/ppapi/c/dev/ppb_find_dev.h b/ppapi/c/dev/ppb_find_dev.h
deleted file mode 100644
index 15b8f27..0000000
--- a/ppapi/c/dev/ppb_find_dev.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (c) 2012 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* From dev/ppb_find_dev.idl modified Thu Mar 13 11:05:53 2014. */
-
-#ifndef PPAPI_C_DEV_PPB_FIND_DEV_H_
-#define PPAPI_C_DEV_PPB_FIND_DEV_H_
-
-#include "ppapi/c/pp_bool.h"
-#include "ppapi/c/pp_instance.h"
-#include "ppapi/c/pp_macros.h"
-#include "ppapi/c/pp_stdint.h"
-
-#define PPB_FIND_DEV_INTERFACE_0_3 "PPB_Find(Dev);0.3"
-#define PPB_FIND_DEV_INTERFACE PPB_FIND_DEV_INTERFACE_0_3
-
-/**
- * @file
- * This file defines the <code>PPB_Find_Dev</code> interface.
- */
-
-
-/**
- * @addtogroup Interfaces
- * @{
- */
-/* TODO(raymes): Make PPP/PPB_Find_Dev a private interface. It's only used by
- * PDF currently and it's restrictive in the way it can be used. */
-struct PPB_Find_Dev_0_3 {
-  /**
-   * Sets the instance of this plugin as the mechanism that will be used to
-   * handle find requests in the renderer. This will only succeed if the plugin
-   * is embedded within the content of the top level frame. Note that this will
-   * result in the renderer handing over all responsibility for doing find to
-   * the plugin and content from the rest of the page will not be searched.
-   *
-   *
-   * In the case that the plugin is loaded directly as the top level document,
-   * this function does not need to be called. In that case the plugin is
-   * assumed to handle find requests.
-   *
-   * There can only be one plugin which handles find requests. If a plugin calls
-   * this while an existing plugin is registered, the existing plugin will be
-   * de-registered and will no longer receive any requests.
-   */
-  void (*SetPluginToHandleFindRequests)(PP_Instance instance);
-  /**
-   * Updates the number of find results for the current search term.  If
-   * there are no matches 0 should be passed in.  Only when the plugin has
-   * finished searching should it pass in the final count with final_result set
-   * to PP_TRUE.
-   */
-  void (*NumberOfFindResultsChanged)(PP_Instance instance,
-                                     int32_t total,
-                                     PP_Bool final_result);
-  /**
-   * Updates the index of the currently selected search item.
-   */
-  void (*SelectedFindResultChanged)(PP_Instance instance, int32_t index);
-};
-
-typedef struct PPB_Find_Dev_0_3 PPB_Find_Dev;
-/**
- * @}
- */
-
-#endif  /* PPAPI_C_DEV_PPB_FIND_DEV_H_ */
-
diff --git a/ppapi/c/dev/ppp_find_dev.h b/ppapi/c/dev/ppp_find_dev.h
deleted file mode 100644
index 6d9a4cc..0000000
--- a/ppapi/c/dev/ppp_find_dev.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (c) 2014 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* From dev/ppp_find_dev.idl modified Wed Mar 19 14:02:22 2014. */
-
-#ifndef PPAPI_C_DEV_PPP_FIND_DEV_H_
-#define PPAPI_C_DEV_PPP_FIND_DEV_H_
-
-#include "ppapi/c/pp_bool.h"
-#include "ppapi/c/pp_instance.h"
-#include "ppapi/c/pp_macros.h"
-#include "ppapi/c/pp_stdint.h"
-
-#define PPP_FIND_DEV_INTERFACE_0_3 "PPP_Find(Dev);0.3"
-#define PPP_FIND_DEV_INTERFACE PPP_FIND_DEV_INTERFACE_0_3
-
-/**
- * @file
- */
-
-
-/**
- * @addtogroup Interfaces
- * @{
- */
-/**
- * TODO(raymes): Make PPP/PPB_Find_Dev a private interface.
- */
-struct PPP_Find_Dev_0_3 {
-  /**
-   * Finds the given UTF-8 text starting at the current selection. The number of
-   * results will be updated asynchronously via NumberOfFindResultsChanged in
-   * PPB_Find. Note that multiple StartFind calls can happen before StopFind is
-   * called in the case of the search term changing.
-   *
-   * Return PP_FALSE if the plugin doesn't support find in page. Consequently,
-   * it won't call any callbacks.
-   */
-  PP_Bool (*StartFind)(PP_Instance instance,
-                       const char* text,
-                       PP_Bool case_sensitive);
-  /**
-   * Go to the next/previous result.
-   */
-  void (*SelectFindResult)(PP_Instance instance, PP_Bool forward);
-  /**
-   * Tells the plugin that the find operation has stopped, so it should clear
-   * any highlighting.
-   */
-  void (*StopFind)(PP_Instance instance);
-};
-
-typedef struct PPP_Find_Dev_0_3 PPP_Find_Dev;
-/**
- * @}
- */
-
-#endif  /* PPAPI_C_DEV_PPP_FIND_DEV_H_ */
-
diff --git a/ppapi/c/ppb_audio_buffer.h b/ppapi/c/ppb_audio_buffer.h
index 6424cba..fe728a3 100644
--- a/ppapi/c/ppb_audio_buffer.h
+++ b/ppapi/c/ppb_audio_buffer.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From ppb_audio_buffer.idl modified Mon Mar 10 20:21:25 2014. */
+/* From ppb_audio_buffer.idl modified Tue Mar 25 18:29:27 2014. */
 
 #ifndef PPAPI_C_PPB_AUDIO_BUFFER_H_
 #define PPAPI_C_PPB_AUDIO_BUFFER_H_
@@ -14,7 +14,9 @@
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_time.h"
 
-#define PPB_AUDIOBUFFER_INTERFACE_0_1 "PPB_AudioBuffer;0.1" /* dev */
+#define PPB_AUDIOBUFFER_INTERFACE_0_1 "PPB_AudioBuffer;0.1"
+#define PPB_AUDIOBUFFER_INTERFACE PPB_AUDIOBUFFER_INTERFACE_0_1
+
 /**
  * @file
  * Defines the <code>PPB_AudioBuffer</code> interface.
@@ -57,7 +59,7 @@
  * @addtogroup Interfaces
  * @{
  */
-struct PPB_AudioBuffer_0_1 { /* dev */
+struct PPB_AudioBuffer_0_1 {
   /**
    * Determines if a resource is an AudioBuffer resource.
    *
@@ -144,6 +146,8 @@
    */
   uint32_t (*GetDataBufferSize)(PP_Resource buffer);
 };
+
+typedef struct PPB_AudioBuffer_0_1 PPB_AudioBuffer;
 /**
  * @}
  */
diff --git a/ppapi/c/ppb_media_stream_audio_track.h b/ppapi/c/ppb_media_stream_audio_track.h
index 7edb60d..7eae9f3 100644
--- a/ppapi/c/ppb_media_stream_audio_track.h
+++ b/ppapi/c/ppb_media_stream_audio_track.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From ppb_media_stream_audio_track.idl modified Fri Feb  7 14:38:28 2014. */
+/* From ppb_media_stream_audio_track.idl modified Fri Mar 28 10:13:34 2014. */
 
 #ifndef PPAPI_C_PPB_MEDIA_STREAM_AUDIO_TRACK_H_
 #define PPAPI_C_PPB_MEDIA_STREAM_AUDIO_TRACK_H_
@@ -15,13 +15,14 @@
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_var.h"
 
-#define PPB_MEDIASTREAMAUDIOTRACK_INTERFACE_0_1 \
-    "PPB_MediaStreamAudioTrack;0.1" /* dev */
+#define PPB_MEDIASTREAMAUDIOTRACK_INTERFACE_0_1 "PPB_MediaStreamAudioTrack;0.1"
+#define PPB_MEDIASTREAMAUDIOTRACK_INTERFACE \
+    PPB_MEDIASTREAMAUDIOTRACK_INTERFACE_0_1
+
 /**
  * @file
  * Defines the <code>PPB_MediaStreamAudioTrack</code> interface. Used for
  * receiving audio samples from a MediaStream audio track in the browser.
- * This interface is still in development (Dev API status) and may change.
  */
 
 
@@ -78,7 +79,7 @@
  * @addtogroup Interfaces
  * @{
  */
-struct PPB_MediaStreamAudioTrack_0_1 { /* dev */
+struct PPB_MediaStreamAudioTrack_0_1 {
   /**
    * Determines if a resource is a MediaStream audio track resource.
    *
@@ -203,6 +204,8 @@
    */
   void (*Close)(PP_Resource audio_track);
 };
+
+typedef struct PPB_MediaStreamAudioTrack_0_1 PPB_MediaStreamAudioTrack;
 /**
  * @}
  */
diff --git a/ppapi/c/ppb_media_stream_video_track.h b/ppapi/c/ppb_media_stream_video_track.h
index ce4f9c8..1580041 100644
--- a/ppapi/c/ppb_media_stream_video_track.h
+++ b/ppapi/c/ppb_media_stream_video_track.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From ppb_media_stream_video_track.idl modified Wed Feb 19 11:06:48 2014. */
+/* From ppb_media_stream_video_track.idl modified Fri Mar 28 10:13:52 2014. */
 
 #ifndef PPAPI_C_PPB_MEDIA_STREAM_VIDEO_TRACK_H_
 #define PPAPI_C_PPB_MEDIA_STREAM_VIDEO_TRACK_H_
@@ -15,13 +15,14 @@
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_var.h"
 
-#define PPB_MEDIASTREAMVIDEOTRACK_INTERFACE_0_1 \
-    "PPB_MediaStreamVideoTrack;0.1" /* dev */
+#define PPB_MEDIASTREAMVIDEOTRACK_INTERFACE_0_1 "PPB_MediaStreamVideoTrack;0.1"
+#define PPB_MEDIASTREAMVIDEOTRACK_INTERFACE \
+    PPB_MEDIASTREAMVIDEOTRACK_INTERFACE_0_1
+
 /**
  * @file
  * Defines the <code>PPB_MediaStreamVideoTrack</code> interface. Used for
  * receiving video frames from a MediaStream video track in the browser.
- * This interface is still in development (Dev API status) and may change.
  */
 
 
@@ -88,7 +89,7 @@
  * @addtogroup Interfaces
  * @{
  */
-struct PPB_MediaStreamVideoTrack_0_1 { /* dev */
+struct PPB_MediaStreamVideoTrack_0_1 {
   /**
    * Determines if a resource is a MediaStream video track resource.
    *
@@ -219,6 +220,8 @@
    */
   void (*Close)(PP_Resource video_track);
 };
+
+typedef struct PPB_MediaStreamVideoTrack_0_1 PPB_MediaStreamVideoTrack;
 /**
  * @}
  */
diff --git a/ppapi/c/ppb_video_frame.h b/ppapi/c/ppb_video_frame.h
index 6dafc0c..3efe392 100644
--- a/ppapi/c/ppb_video_frame.h
+++ b/ppapi/c/ppb_video_frame.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From ppb_video_frame.idl modified Tue Feb 11 14:41:52 2014. */
+/* From ppb_video_frame.idl modified Tue Mar 25 18:28:57 2014. */
 
 #ifndef PPAPI_C_PPB_VIDEO_FRAME_H_
 #define PPAPI_C_PPB_VIDEO_FRAME_H_
@@ -15,7 +15,9 @@
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_time.h"
 
-#define PPB_VIDEOFRAME_INTERFACE_0_1 "PPB_VideoFrame;0.1" /* dev */
+#define PPB_VIDEOFRAME_INTERFACE_0_1 "PPB_VideoFrame;0.1"
+#define PPB_VIDEOFRAME_INTERFACE PPB_VIDEOFRAME_INTERFACE_0_1
+
 /**
  * @file
  * Defines the <code>PPB_VideoFrame</code> interface.
@@ -56,7 +58,7 @@
  * @addtogroup Interfaces
  * @{
  */
-struct PPB_VideoFrame_0_1 { /* dev */
+struct PPB_VideoFrame_0_1 {
   /**
    * Determines if a resource is a VideoFrame resource.
    *
@@ -127,6 +129,8 @@
    */
   uint32_t (*GetDataBufferSize)(PP_Resource frame);
 };
+
+typedef struct PPB_VideoFrame_0_1 PPB_VideoFrame;
 /**
  * @}
  */
diff --git a/ppapi/c/private/ppb_find_private.h b/ppapi/c/private/ppb_find_private.h
new file mode 100644
index 0000000..09ebab0
--- /dev/null
+++ b/ppapi/c/private/ppb_find_private.h
@@ -0,0 +1,81 @@
+/* Copyright 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* From private/ppb_find_private.idl modified Wed Mar 19 13:42:13 2014. */
+
+#ifndef PPAPI_C_PRIVATE_PPB_FIND_PRIVATE_H_
+#define PPAPI_C_PRIVATE_PPB_FIND_PRIVATE_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_macros.h"
+#include "ppapi/c/pp_point.h"
+#include "ppapi/c/pp_rect.h"
+#include "ppapi/c/pp_size.h"
+#include "ppapi/c/pp_stdint.h"
+
+#define PPB_FIND_PRIVATE_INTERFACE_0_3 "PPB_Find_Private;0.3"
+#define PPB_FIND_PRIVATE_INTERFACE PPB_FIND_PRIVATE_INTERFACE_0_3
+
+/**
+ * @file
+ * This file defines the <code>PPB_Find_Private</code> interface.
+ */
+
+
+/**
+ * @addtogroup Interfaces
+ * @{
+ */
+/**
+ * This is a private interface for doing browser Find in the PDF plugin.
+ */
+struct PPB_Find_Private_0_3 {
+  /**
+   * Sets the instance of this plugin as the mechanism that will be used to
+   * handle find requests in the renderer. This will only succeed if the plugin
+   * is embedded within the content of the top level frame. Note that this will
+   * result in the renderer handing over all responsibility for doing find to
+   * the plugin and content from the rest of the page will not be searched.
+   *
+   *
+   * In the case that the plugin is loaded directly as the top level document,
+   * this function does not need to be called. In that case the plugin is
+   * assumed to handle find requests.
+   *
+   * There can only be one plugin which handles find requests. If a plugin calls
+   * this while an existing plugin is registered, the existing plugin will be
+   * de-registered and will no longer receive any requests.
+   */
+  void (*SetPluginToHandleFindRequests)(PP_Instance instance);
+  /**
+   * Updates the number of find results for the current search term.  If
+   * there are no matches 0 should be passed in.  Only when the plugin has
+   * finished searching should it pass in the final count with final_result set
+   * to PP_TRUE.
+   */
+  void (*NumberOfFindResultsChanged)(PP_Instance instance,
+                                     int32_t total,
+                                     PP_Bool final_result);
+  /**
+   * Updates the index of the currently selected search item.
+   */
+  void (*SelectedFindResultChanged)(PP_Instance instance, int32_t index);
+  /**
+   * Updates the tickmarks on the scrollbar for the find request. |tickmarks|
+   * contains |count| PP_Rects indicating the tickmark ranges.
+   */
+  void (*SetTickmarks)(PP_Instance instance,
+                       const struct PP_Rect tickmarks[],
+                       uint32_t count);
+};
+
+typedef struct PPB_Find_Private_0_3 PPB_Find_Private;
+/**
+ * @}
+ */
+
+#endif  /* PPAPI_C_PRIVATE_PPB_FIND_PRIVATE_H_ */
+
diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h
index e5032fc..c389c84 100644
--- a/ppapi/c/private/ppb_nacl_private.h
+++ b/ppapi/c/private/ppb_nacl_private.h
@@ -3,7 +3,7 @@
  * found in the LICENSE file.
  */
 
-/* From private/ppb_nacl_private.idl modified Thu Mar 20 14:02:02 2014. */
+/* From private/ppb_nacl_private.idl modified Thu Mar 27 14:44:04 2014. */
 
 #ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
 #define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
@@ -136,6 +136,18 @@
   PP_SCHEME_DATA,
   PP_SCHEME_OTHER
 } PP_UrlSchemeType;
+
+typedef enum {
+  /* The trusted plugin begins in this ready state. */
+  PP_NACL_READY_STATE_UNSENT = 0,
+  /* The manifest file has been requested, but not yet received. */
+  PP_NACL_READY_STATE_OPENED = 1,
+  /* The manifest file has been received and the nexe successfully requested. */
+  PP_NACL_READY_STATE_LOADING = 3,
+  /* The nexe has been loaded and the proxy started, so it is ready for
+   */
+  PP_NACL_READY_STATE_DONE = 4
+} PP_NaClReadyState;
 /**
  * @}
  */
@@ -282,14 +294,15 @@
   void (*ReportLoadError)(PP_Instance instance,
                           PP_NaClError error,
                           const char* error_message,
-                          const char* console_message,
-                          PP_Bool is_installed);
+                          const char* console_message);
+  /* Performs internal setup when an instance is created. */
+  void (*InstanceCreated)(PP_Instance instance);
   /* Performs internal cleanup when an instance is destroyed. */
   void (*InstanceDestroyed)(PP_Instance instance);
-  /* Return true if the NaCl debug stub is enabled and the loaded app
-   * will be attached to a debugger.
+  /* Return true if the NaCl debug stub is enabled and the app loaded from
+   * alleged_nmf_url will be attached to a debugger.
    */
-  PP_Bool (*NaClDebugStubEnabled)(void);
+  PP_Bool (*NaClDebugEnabledForURL)(const char* alleged_nmf_url);
   /* Returns the kind of SFI sandbox implemented by NaCl on this
    * platform.
    */
@@ -298,6 +311,19 @@
   PP_UrlSchemeType (*GetUrlScheme)(struct PP_Var url);
   /* Logs the message to the console. */
   void (*LogToConsole)(PP_Instance instance, const char* message);
+  /* Returns PP_TRUE if an error has been reported loading the nexe. */
+  PP_Bool (*GetNexeErrorReported)(PP_Instance instance);
+  /* Sets the nexe error reported state for this instance. */
+  void (*SetNexeErrorReported)(PP_Instance instance, PP_Bool error_reported);
+  /* Returns the NaCl readiness status for this instance. */
+  PP_NaClReadyState (*GetNaClReadyState)(PP_Instance instance);
+  /* Sets the NaCl readiness status for this instance. */
+  void (*SetNaClReadyState)(PP_Instance instance,
+                            PP_NaClReadyState ready_state);
+  /* Returns true if the plugin is an installed app. */
+  PP_Bool (*GetIsInstalled)(PP_Instance instance);
+  /* Sets whether the plugin is an installed app. */
+  void (*SetIsInstalled)(PP_Instance instance, PP_Bool is_installed);
 };
 
 typedef struct PPB_NaCl_Private_1_0 PPB_NaCl_Private;
diff --git a/ppapi/c/private/ppb_uma_private.h b/ppapi/c/private/ppb_uma_private.h
index c23ba99..04cad42 100644
--- a/ppapi/c/private/ppb_uma_private.h
+++ b/ppapi/c/private/ppb_uma_private.h
@@ -3,19 +3,20 @@
  * found in the LICENSE file.
  */
 
-/* From private/ppb_uma_private.idl modified Mon Nov 18 14:39:43 2013. */
+/* From private/ppb_uma_private.idl modified Fri Mar 14 16:59:33 2014. */
 
 #ifndef PPAPI_C_PRIVATE_PPB_UMA_PRIVATE_H_
 #define PPAPI_C_PRIVATE_PPB_UMA_PRIVATE_H_
 
 #include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_macros.h"
 #include "ppapi/c/pp_stdint.h"
 #include "ppapi/c/pp_var.h"
 
-#define PPB_UMA_PRIVATE_INTERFACE_0_2 "PPB_UMA_Private;0.2"
-#define PPB_UMA_PRIVATE_INTERFACE PPB_UMA_PRIVATE_INTERFACE_0_2
+#define PPB_UMA_PRIVATE_INTERFACE_0_3 "PPB_UMA_Private;0.3"
+#define PPB_UMA_PRIVATE_INTERFACE PPB_UMA_PRIVATE_INTERFACE_0_3
 
 /**
  * @file
@@ -30,7 +31,7 @@
 /**
  * Contains functions for plugins to report UMA usage stats.
  */
-struct PPB_UMA_Private_0_2 {
+struct PPB_UMA_Private_0_3 {
   /**
    * HistogramCustomTimes is a pointer to a function which records a time
    * sample given in milliseconds in the histogram given by |name|, possibly
@@ -63,9 +64,17 @@
                                struct PP_Var name,
                                int32_t sample,
                                int32_t boundary_value);
+  /**
+   * IsCrashReportingEnabled returns PP_OK to the completion callback to
+   * indicate that the current user has opted-in to crash reporting, or
+   * PP_ERROR_* on failure or when a user has not opted-in.  This can be used to
+   * gate other reporting processes such as analytics and crash reporting.
+   */
+  int32_t (*IsCrashReportingEnabled)(PP_Instance instance,
+                                     struct PP_CompletionCallback callback);
 };
 
-typedef struct PPB_UMA_Private_0_2 PPB_UMA_Private;
+typedef struct PPB_UMA_Private_0_3 PPB_UMA_Private;
 /**
  * @}
  */
diff --git a/ppapi/c/private/ppp_find_private.h b/ppapi/c/private/ppp_find_private.h
new file mode 100644
index 0000000..00b26de
--- /dev/null
+++ b/ppapi/c/private/ppp_find_private.h
@@ -0,0 +1,58 @@
+/* Copyright 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* From private/ppp_find_private.idl modified Thu Mar 20 11:34:17 2014. */
+
+#ifndef PPAPI_C_PRIVATE_PPP_FIND_PRIVATE_H_
+#define PPAPI_C_PRIVATE_PPP_FIND_PRIVATE_H_
+
+#include "ppapi/c/pp_bool.h"
+#include "ppapi/c/pp_instance.h"
+#include "ppapi/c/pp_macros.h"
+#include "ppapi/c/pp_stdint.h"
+
+#define PPP_FIND_PRIVATE_INTERFACE_0_3 "PPP_Find_Private;0.3"
+#define PPP_FIND_PRIVATE_INTERFACE PPP_FIND_PRIVATE_INTERFACE_0_3
+
+/**
+ * @file
+ */
+
+
+/**
+ * @addtogroup Interfaces
+ * @{
+ */
+struct PPP_Find_Private_0_3 {
+  /**
+   * Finds the given UTF-8 text starting at the current selection. The number of
+   * results will be updated asynchronously via NumberOfFindResultsChanged in
+   * PPB_Find. Note that multiple StartFind calls can happen before StopFind is
+   * called in the case of the search term changing.
+   *
+   * Return PP_FALSE if the plugin doesn't support find in page. Consequently,
+   * it won't call any callbacks.
+   */
+  PP_Bool (*StartFind)(PP_Instance instance,
+                       const char* text,
+                       PP_Bool case_sensitive);
+  /**
+   * Go to the next/previous result.
+   */
+  void (*SelectFindResult)(PP_Instance instance, PP_Bool forward);
+  /**
+   * Tells the plugin that the find operation has stopped, so it should clear
+   * any highlighting.
+   */
+  void (*StopFind)(PP_Instance instance);
+};
+
+typedef struct PPP_Find_Private_0_3 PPP_Find_Private;
+/**
+ * @}
+ */
+
+#endif  /* PPAPI_C_PRIVATE_PPP_FIND_PRIVATE_H_ */
+
diff --git a/ppapi/cpp/dev/find_dev.cc b/ppapi/cpp/dev/find_dev.cc
deleted file mode 100644
index 1004b49..0000000
--- a/ppapi/cpp/dev/find_dev.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ppapi/cpp/dev/find_dev.h"
-
-#include "ppapi/c/dev/ppb_find_dev.h"
-#include "ppapi/cpp/instance.h"
-#include "ppapi/cpp/module.h"
-#include "ppapi/cpp/module_impl.h"
-
-namespace pp {
-
-namespace {
-
-template <> const char* interface_name<PPB_Find_Dev>() {
-  return PPB_FIND_DEV_INTERFACE;
-}
-
-static const char kPPPFindInterface[] = PPP_FIND_DEV_INTERFACE;
-
-PP_Bool StartFind(PP_Instance instance,
-                  const char* text,
-                  PP_Bool case_sensitive) {
-  void* object = Instance::GetPerInstanceObject(instance, kPPPFindInterface);
-  if (!object)
-    return PP_FALSE;
-  bool return_value = static_cast<Find_Dev*>(object)->StartFind(
-      text, PP_ToBool(case_sensitive));
-  return PP_FromBool(return_value);
-}
-
-void SelectFindResult(PP_Instance instance, PP_Bool forward) {
-  void* object = Instance::GetPerInstanceObject(instance, kPPPFindInterface);
-  if (object)
-    static_cast<Find_Dev*>(object)->SelectFindResult(PP_ToBool(forward));
-}
-
-void StopFind(PP_Instance instance) {
-  void* object = Instance::GetPerInstanceObject(instance, kPPPFindInterface);
-  if (object)
-    static_cast<Find_Dev*>(object)->StopFind();
-}
-
-const PPP_Find_Dev ppp_find = {
-  &StartFind,
-  &SelectFindResult,
-  &StopFind
-};
-
-}  // namespace
-
-Find_Dev::Find_Dev(Instance* instance) : associated_instance_(instance) {
-  Module::Get()->AddPluginInterface(kPPPFindInterface, &ppp_find);
-  instance->AddPerInstanceObject(kPPPFindInterface, this);
-}
-
-Find_Dev::~Find_Dev() {
-  Instance::RemovePerInstanceObject(associated_instance_,
-                                    kPPPFindInterface, this);
-}
-
-void Find_Dev::SetPluginToHandleFindRequests() {
-  if (has_interface<PPB_Find_Dev>()) {
-    get_interface<PPB_Find_Dev>()->SetPluginToHandleFindRequests(
-        associated_instance_.pp_instance());
-  }
-}
-
-void Find_Dev::NumberOfFindResultsChanged(int32_t total, bool final_result) {
-  if (has_interface<PPB_Find_Dev>()) {
-    get_interface<PPB_Find_Dev>()->NumberOfFindResultsChanged(
-        associated_instance_.pp_instance(), total, PP_FromBool(final_result));
-  }
-}
-
-void Find_Dev::SelectedFindResultChanged(int32_t index) {
-  if (has_interface<PPB_Find_Dev>()) {
-    get_interface<PPB_Find_Dev>()->SelectedFindResultChanged(
-        associated_instance_.pp_instance(), index);
-  }
-}
-
-}  // namespace pp
diff --git a/ppapi/cpp/dev/find_dev.h b/ppapi/cpp/dev/find_dev.h
deleted file mode 100644
index a3170eb..0000000
--- a/ppapi/cpp/dev/find_dev.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PPAPI_CPP_DEV_FIND_DEV_H_
-#define PPAPI_CPP_DEV_FIND_DEV_H_
-
-#include <string>
-
-#include "ppapi/c/dev/ppp_find_dev.h"
-#include "ppapi/cpp/instance_handle.h"
-
-namespace pp {
-
-class Instance;
-
-// This class allows you to associate the PPP_Find and PPB_Find C-based
-// interfaces with an object. It associates itself with the given instance, and
-// registers as the global handler for handling the PPP_Find interface that the
-// browser calls.
-//
-// You would typically use this either via inheritance on your instance:
-//   class MyInstance : public pp::Instance, public pp::Find_Dev {
-//     class MyInstance() : pp::Find_Dev(this) {
-//     }
-//     ...
-//   };
-//
-// or by composition:
-//   class MyFinder : public pp::Find {
-//     ...
-//   };
-//
-//   class MyInstance : public pp::Instance {
-//     MyInstance() : finder_(this) {
-//     }
-//
-//     MyFinder finder_;
-//   };
-class Find_Dev {
- public:
-  // The instance parameter must outlive this class.
-  Find_Dev(Instance* instance);
-  virtual ~Find_Dev();
-
-  // PPP_Find_Dev functions exposed as virtual functions for you to
-  // override.
-  virtual bool StartFind(const std::string& text, bool case_sensitive) = 0;
-  virtual void SelectFindResult(bool forward) = 0;
-  virtual void StopFind() = 0;
-
-  // PPB_Find_Dev functions for you to call to report find results.
-  void SetPluginToHandleFindRequests();
-  void NumberOfFindResultsChanged(int32_t total, bool final_result);
-  void SelectedFindResultChanged(int32_t index);
-
- private:
-  InstanceHandle associated_instance_;
-};
-
-}  // namespace pp
-
-#endif  // PPAPI_CPP_DEV_FIND_DEV_H_
diff --git a/ppapi/cpp/dev/printing_dev.h b/ppapi/cpp/dev/printing_dev.h
index b219b13..869dbac 100644
--- a/ppapi/cpp/dev/printing_dev.h
+++ b/ppapi/cpp/dev/printing_dev.h
@@ -15,7 +15,7 @@
 class Instance;
 
 // You would typically use this either via inheritance on your instance or
-// by composition: see find_dev.h for an example.
+// by composition: see find_private.h for an example.
 class Printing_Dev : public Resource {
  public:
   // The instance parameter must outlive this class.
diff --git a/ppapi/cpp/private/find_private.cc b/ppapi/cpp/private/find_private.cc
new file mode 100644
index 0000000..440bc74
--- /dev/null
+++ b/ppapi/cpp/private/find_private.cc
@@ -0,0 +1,99 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/cpp/private/find_private.h"
+
+#include "ppapi/c/private/ppb_find_private.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/module_impl.h"
+#include "ppapi/cpp/rect.h"
+
+namespace pp {
+
+namespace {
+
+template <> const char* interface_name<PPB_Find_Private>() {
+  return PPB_FIND_PRIVATE_INTERFACE;
+}
+
+static const char kPPPFindInterface[] = PPP_FIND_PRIVATE_INTERFACE;
+
+PP_Bool StartFind(PP_Instance instance,
+                  const char* text,
+                  PP_Bool case_sensitive) {
+  void* object = Instance::GetPerInstanceObject(instance, kPPPFindInterface);
+  if (!object)
+    return PP_FALSE;
+  bool return_value = static_cast<Find_Private*>(object)->StartFind(
+      text, PP_ToBool(case_sensitive));
+  return PP_FromBool(return_value);
+}
+
+void SelectFindResult(PP_Instance instance, PP_Bool forward) {
+  void* object = Instance::GetPerInstanceObject(instance, kPPPFindInterface);
+  if (object)
+    static_cast<Find_Private*>(object)->SelectFindResult(PP_ToBool(forward));
+}
+
+void StopFind(PP_Instance instance) {
+  void* object = Instance::GetPerInstanceObject(instance, kPPPFindInterface);
+  if (object)
+    static_cast<Find_Private*>(object)->StopFind();
+}
+
+const PPP_Find_Private ppp_find = {
+  &StartFind,
+  &SelectFindResult,
+  &StopFind
+};
+
+}  // namespace
+
+Find_Private::Find_Private(Instance* instance)
+      : associated_instance_(instance) {
+  Module::Get()->AddPluginInterface(kPPPFindInterface, &ppp_find);
+  instance->AddPerInstanceObject(kPPPFindInterface, this);
+}
+
+Find_Private::~Find_Private() {
+  Instance::RemovePerInstanceObject(associated_instance_,
+                                    kPPPFindInterface, this);
+}
+
+void Find_Private::SetPluginToHandleFindRequests() {
+  if (has_interface<PPB_Find_Private>()) {
+    get_interface<PPB_Find_Private>()->SetPluginToHandleFindRequests(
+        associated_instance_.pp_instance());
+  }
+}
+
+void Find_Private::NumberOfFindResultsChanged(int32_t total,
+                                              bool final_result) {
+  if (has_interface<PPB_Find_Private>()) {
+    get_interface<PPB_Find_Private>()->NumberOfFindResultsChanged(
+        associated_instance_.pp_instance(), total, PP_FromBool(final_result));
+  }
+}
+
+void Find_Private::SelectedFindResultChanged(int32_t index) {
+  if (has_interface<PPB_Find_Private>()) {
+    get_interface<PPB_Find_Private>()->SelectedFindResultChanged(
+        associated_instance_.pp_instance(), index);
+  }
+}
+
+void Find_Private::SetTickmarks(const std::vector<pp::Rect>& tickmarks) {
+  if (has_interface<PPB_Find_Private>()) {
+    if (tickmarks.empty())
+      return;
+    std::vector<PP_Rect> tickmarks_converted(tickmarks.begin(),
+                                             tickmarks.end());
+    get_interface<PPB_Find_Private>()->SetTickmarks(
+        associated_instance_.pp_instance(), &tickmarks_converted[0],
+        static_cast<uint32_t>(tickmarks.size()));
+  }
+}
+
+}  // namespace pp
diff --git a/ppapi/cpp/private/find_private.h b/ppapi/cpp/private/find_private.h
new file mode 100644
index 0000000..268033b
--- /dev/null
+++ b/ppapi/cpp/private/find_private.h
@@ -0,0 +1,66 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_CPP_PRIVATE_FIND_PRIVATE_H_
+#define PPAPI_CPP_PRIVATE_FIND_PRIVATE_H_
+
+#include <string>
+#include <vector>
+
+#include "ppapi/c/private/ppp_find_private.h"
+#include "ppapi/cpp/instance_handle.h"
+
+namespace pp {
+
+class Instance;
+class Rect;
+
+// This class allows you to associate the PPP_Find and PPB_Find C-based
+// interfaces with an object. It associates itself with the given instance, and
+// registers as the global handler for handling the PPP_Find interface that the
+// browser calls.
+//
+// You would typically use this either via inheritance on your instance:
+//   class MyInstance : public pp::Instance, public pp::Find_Private {
+//     class MyInstance() : pp::Find_Private(this) {
+//     }
+//     ...
+//   };
+//
+// or by composition:
+//   class MyFinder : public pp::Find {
+//     ...
+//   };
+//
+//   class MyInstance : public pp::Instance {
+//     MyInstance() : finder_(this) {
+//     }
+//
+//     MyFinder finder_;
+//   };
+class Find_Private {
+ public:
+  // The instance parameter must outlive this class.
+  Find_Private(Instance* instance);
+  virtual ~Find_Private();
+
+  // PPP_Find_Private functions exposed as virtual functions for you to
+  // override.
+  virtual bool StartFind(const std::string& text, bool case_sensitive) = 0;
+  virtual void SelectFindResult(bool forward) = 0;
+  virtual void StopFind() = 0;
+
+  // PPB_Find_Private functions for you to call to report find results.
+  void SetPluginToHandleFindRequests();
+  void NumberOfFindResultsChanged(int32_t total, bool final_result);
+  void SelectedFindResultChanged(int32_t index);
+  void SetTickmarks(const std::vector<pp::Rect>& tickmarks);
+
+ private:
+  InstanceHandle associated_instance_;
+};
+
+}  // namespace pp
+
+#endif  // PPAPI_CPP_PRIVATE_FIND_PRIVATE_H_
diff --git a/ppapi/cpp/private/uma_private.cc b/ppapi/cpp/private/uma_private.cc
index ed8b6e9..3ec0872 100644
--- a/ppapi/cpp/private/uma_private.cc
+++ b/ppapi/cpp/private/uma_private.cc
@@ -6,6 +6,7 @@
 
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_uma_private.h"
+#include "ppapi/cpp/completion_callback.h"
 #include "ppapi/cpp/module_impl.h"
 #include "ppapi/cpp/var.h"
 
@@ -13,8 +14,8 @@
 
 namespace {
 
-template <> const char* interface_name<PPB_UMA_Private_0_2>() {
-  return PPB_UMA_PRIVATE_INTERFACE_0_2;
+template <> const char* interface_name<PPB_UMA_Private_0_3>() {
+  return PPB_UMA_PRIVATE_INTERFACE_0_3;
 }
 
 }  // namespace
@@ -30,7 +31,7 @@
 }
 
 bool UMAPrivate::IsAvailable() {
-  return has_interface<PPB_UMA_Private_0_2>();
+  return has_interface<PPB_UMA_Private_0_3>();
 }
 
 void UMAPrivate::HistogramCustomTimes(const std::string& name,
@@ -40,7 +41,7 @@
                                       uint32_t bucket_count) {
   if (!IsAvailable())
     return;
-  get_interface<PPB_UMA_Private_0_2>()->
+  get_interface<PPB_UMA_Private_0_3>()->
       HistogramCustomTimes(instance_, pp::Var(name).pp_var(),
                            sample, min, max, bucket_count);
 }
@@ -52,7 +53,7 @@
                                        uint32_t bucket_count) {
   if (!IsAvailable())
     return;
-  get_interface<PPB_UMA_Private_0_2>()->
+  get_interface<PPB_UMA_Private_0_3>()->
       HistogramCustomCounts(instance_, pp::Var(name).pp_var(),
                             sample, min, max, bucket_count);
 }
@@ -62,9 +63,17 @@
                                       int32_t boundary_value) {
   if (!IsAvailable())
     return;
-  get_interface<PPB_UMA_Private_0_2>()->
+  get_interface<PPB_UMA_Private_0_3>()->
       HistogramEnumeration(instance_, pp::Var(name).pp_var(),
                            sample, boundary_value);
 }
 
+int32_t UMAPrivate::IsCrashReportingEnabled(const CompletionCallback& cc) {
+  if (!IsAvailable())
+    return PP_ERROR_NOINTERFACE;
+
+  return get_interface<PPB_UMA_Private_0_3>()->
+      IsCrashReportingEnabled(instance_, cc.pp_completion_callback());
+}
+
 }  // namespace pp
diff --git a/ppapi/cpp/private/uma_private.h b/ppapi/cpp/private/uma_private.h
index 23de400..78d526d 100644
--- a/ppapi/cpp/private/uma_private.h
+++ b/ppapi/cpp/private/uma_private.h
@@ -12,6 +12,8 @@
 
 namespace pp {
 
+class CompletionCallback;
+
 class UMAPrivate {
  public:
   UMAPrivate();
@@ -36,6 +38,8 @@
                             int32_t sample,
                             int32_t boundary_value);
 
+  int32_t IsCrashReportingEnabled(const CompletionCallback& cc);
+
  private:
   PP_Instance instance_;
 };
diff --git a/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.cc b/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.cc
new file mode 100644
index 0000000..de1ccba
--- /dev/null
+++ b/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.cc
@@ -0,0 +1,150 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/cpp/core.h"
+#include "ppapi/cpp/graphics_3d.h"
+#include "ppapi/cpp/graphics_3d_client.h"
+#include "ppapi/cpp/input_event.h"
+#include "ppapi/cpp/instance.h"
+#include "ppapi/cpp/module.h"
+#include "ppapi/cpp/rect.h"
+#include "ppapi/examples/gles2_spinning_cube/spinning_cube.h"
+#include "ppapi/lib/gl/gles2/gl2ext_ppapi.h"
+#include "ppapi/utility/completion_callback_factory.h"
+
+// Use assert as a poor-man's CHECK, even in non-debug mode.
+// Since <assert.h> redefines assert on every inclusion (it doesn't use
+// include-guards), make sure this is the last file #include'd in this file.
+#undef NDEBUG
+#include <assert.h>
+
+namespace {
+
+class DemoInstance : public pp::Instance, public pp::Graphics3DClient {
+ public:
+  DemoInstance(PP_Instance instance);
+  virtual ~DemoInstance();
+
+  // pp::Instance implementation (see PPP_Instance).
+  virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]);
+  virtual void DidChangeView(const pp::Rect& position,
+                             const pp::Rect& clip);
+  virtual bool HandleInputEvent(const pp::InputEvent& event) {
+    // TODO(yzshen): Handle input events.
+    return true;
+  }
+
+  // pp::Graphics3DClient implementation.
+  virtual void Graphics3DContextLost();
+
+ private:
+  // GL-related functions.
+  void InitGL(int32_t result);
+  void Paint(int32_t result);
+
+  pp::Size plugin_size_;
+  pp::CompletionCallbackFactory<DemoInstance> callback_factory_;
+
+  // Owned data.
+  pp::Graphics3D* context_;
+
+  SpinningCube cube_;
+};
+
+DemoInstance::DemoInstance(PP_Instance instance)
+    : pp::Instance(instance),
+      pp::Graphics3DClient(this),
+      callback_factory_(this),
+      context_(NULL) {}
+
+DemoInstance::~DemoInstance() {
+  assert(glTerminatePPAPI());
+  delete context_;
+}
+
+bool DemoInstance::Init(uint32_t /*argc*/,
+                        const char* /*argn*/[],
+                        const char* /*argv*/[]) {
+  RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
+  return !!glInitializePPAPI(pp::Module::Get()->get_browser_interface());
+}
+
+void DemoInstance::DidChangeView(
+    const pp::Rect& position, const pp::Rect& /*clip*/) {
+  if (position.width() == 0 || position.height() == 0)
+    return;
+  plugin_size_ = position.size();
+
+  // Initialize graphics.
+  InitGL(0);
+}
+
+void DemoInstance::Graphics3DContextLost() {
+  delete context_;
+  context_ = NULL;
+  pp::CompletionCallback cb = callback_factory_.NewCallback(
+      &DemoInstance::InitGL);
+  pp::Module::Get()->core()->CallOnMainThread(0, cb, 0);
+}
+
+void DemoInstance::InitGL(int32_t /*result*/) {
+  assert(plugin_size_.width() && plugin_size_.height());
+
+  if (context_) {
+    context_->ResizeBuffers(plugin_size_.width(), plugin_size_.height());
+    return;
+  }
+  int32_t context_attributes[] = {
+    PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
+    PP_GRAPHICS3DATTRIB_BLUE_SIZE, 8,
+    PP_GRAPHICS3DATTRIB_GREEN_SIZE, 8,
+    PP_GRAPHICS3DATTRIB_RED_SIZE, 8,
+    PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 0,
+    PP_GRAPHICS3DATTRIB_STENCIL_SIZE, 0,
+    PP_GRAPHICS3DATTRIB_SAMPLES, 0,
+    PP_GRAPHICS3DATTRIB_SAMPLE_BUFFERS, 0,
+    PP_GRAPHICS3DATTRIB_WIDTH, plugin_size_.width(),
+    PP_GRAPHICS3DATTRIB_HEIGHT, plugin_size_.height(),
+    PP_GRAPHICS3DATTRIB_NONE,
+  };
+  context_ = new pp::Graphics3D(this, context_attributes);
+  assert(!context_->is_null());
+  assert(BindGraphics(*context_));
+
+  glSetCurrentContextPPAPI(context_->pp_resource());
+  cube_.Init(plugin_size_.width(), plugin_size_.height());
+  Paint(PP_OK);
+}
+
+void DemoInstance::Paint(int32_t result) {
+  if (result != PP_OK || !context_)
+    return;
+
+  cube_.UpdateForTimeDelta(0.02f);
+  cube_.Draw();
+
+  context_->SwapBuffers(callback_factory_.NewCallback(&DemoInstance::Paint));
+}
+
+// This object is the global object representing this plugin library as long
+// as it is loaded.
+class DemoModule : public pp::Module {
+ public:
+  DemoModule() : Module() {}
+  virtual ~DemoModule() {}
+
+  virtual pp::Instance* CreateInstance(PP_Instance instance) {
+    return new DemoInstance(instance);
+  }
+};
+
+}  // anonymous namespace
+
+namespace pp {
+// Factory function for your specialization of the Module object.
+Module* CreateModule() {
+  return new DemoModule();
+}
+}  // namespace pp
diff --git a/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.html b/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.html
new file mode 100644
index 0000000..73ee8ee
--- /dev/null
+++ b/ppapi/examples/gles2_spinning_cube/gles2_spinning_cube.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+  <!--
+  Copyright 2014 The Chromium Authors. All rights reserved.
+  Use of this source code is governed by a BSD-style license that can be
+  found in the LICENSE file.
+  -->
+<head>
+  <title>GLES2 Spinning Cube Example</title>
+</head>
+
+<body>
+
+<embed id="plugin" type="application/x-ppapi-example-gles2-spinning-cube"
+       width="800" height="600"/>
+
+</body>
+</html>
diff --git a/ppapi/examples/gles2_spinning_cube/spinning_cube.cc b/ppapi/examples/gles2_spinning_cube/spinning_cube.cc
new file mode 100644
index 0000000..c4d33dd
--- /dev/null
+++ b/ppapi/examples/gles2_spinning_cube/spinning_cube.cc
@@ -0,0 +1,466 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This example program is based on Simple_VertexShader.c from:
+
+//
+// Book:      OpenGL(R) ES 2.0 Programming Guide
+// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
+// ISBN-10:   0321502795
+// ISBN-13:   9780321502797
+// Publisher: Addison-Wesley Professional
+// URLs:      http://safari.informit.com/9780321563835
+//            http://www.opengles-book.com
+//
+
+#include "ppapi/examples/gles2_spinning_cube/spinning_cube.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include "ppapi/lib/gl/include/GLES2/gl2.h"
+
+namespace {
+
+const float kPi = 3.14159265359f;
+
+int GenerateCube(GLuint *vbo_vertices,
+                 GLuint *vbo_indices) {
+  const int num_indices = 36;
+
+  const GLfloat cube_vertices[] = {
+    -0.5f, -0.5f, -0.5f,
+    -0.5f, -0.5f,  0.5f,
+    0.5f, -0.5f,  0.5f,
+    0.5f, -0.5f, -0.5f,
+    -0.5f,  0.5f, -0.5f,
+    -0.5f,  0.5f,  0.5f,
+    0.5f,  0.5f,  0.5f,
+    0.5f,  0.5f, -0.5f,
+    -0.5f, -0.5f, -0.5f,
+    -0.5f,  0.5f, -0.5f,
+    0.5f,  0.5f, -0.5f,
+    0.5f, -0.5f, -0.5f,
+    -0.5f, -0.5f, 0.5f,
+    -0.5f,  0.5f, 0.5f,
+    0.5f,  0.5f, 0.5f,
+    0.5f, -0.5f, 0.5f,
+    -0.5f, -0.5f, -0.5f,
+    -0.5f, -0.5f,  0.5f,
+    -0.5f,  0.5f,  0.5f,
+    -0.5f,  0.5f, -0.5f,
+    0.5f, -0.5f, -0.5f,
+    0.5f, -0.5f,  0.5f,
+    0.5f,  0.5f,  0.5f,
+    0.5f,  0.5f, -0.5f,
+  };
+
+  const GLushort cube_indices[] = {
+    0, 2, 1,
+    0, 3, 2,
+    4, 5, 6,
+    4, 6, 7,
+    8, 9, 10,
+    8, 10, 11,
+    12, 15, 14,
+    12, 14, 13,
+    16, 17, 18,
+    16, 18, 19,
+    20, 23, 22,
+    20, 22, 21
+  };
+
+  if (vbo_vertices) {
+    glGenBuffers(1, vbo_vertices);
+    glBindBuffer(GL_ARRAY_BUFFER, *vbo_vertices);
+    glBufferData(GL_ARRAY_BUFFER,
+                 sizeof(cube_vertices),
+                 cube_vertices,
+                 GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER, 0);
+  }
+
+  if (vbo_indices) {
+    glGenBuffers(1, vbo_indices);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *vbo_indices);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER,
+                 sizeof(cube_indices),
+                 cube_indices,
+                 GL_STATIC_DRAW);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
+  }
+
+  return num_indices;
+}
+
+GLuint LoadShader(GLenum type,
+                  const char* shader_source) {
+  GLuint shader = glCreateShader(type);
+  glShaderSource(shader, 1, &shader_source, NULL);
+  glCompileShader(shader);
+
+  GLint compiled = 0;
+  glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+
+  if (!compiled) {
+    glDeleteShader(shader);
+    return 0;
+  }
+
+  return shader;
+}
+
+GLuint LoadProgram(const char* vertext_shader_source,
+                   const char* fragment_shader_source) {
+  GLuint vertex_shader = LoadShader(GL_VERTEX_SHADER,
+                                    vertext_shader_source);
+  if (!vertex_shader)
+    return 0;
+
+  GLuint fragment_shader = LoadShader(GL_FRAGMENT_SHADER,
+                                      fragment_shader_source);
+  if (!fragment_shader) {
+    glDeleteShader(vertex_shader);
+    return 0;
+  }
+
+  GLuint program_object = glCreateProgram();
+  glAttachShader(program_object, vertex_shader);
+  glAttachShader(program_object, fragment_shader);
+
+  glLinkProgram(program_object);
+
+  glDeleteShader(vertex_shader);
+  glDeleteShader(fragment_shader);
+
+  GLint linked = 0;
+  glGetProgramiv(program_object, GL_LINK_STATUS, &linked);
+
+  if (!linked) {
+    glDeleteProgram(program_object);
+    return 0;
+  }
+
+  return program_object;
+}
+
+class ESMatrix {
+ public:
+  GLfloat m[4][4];
+
+  ESMatrix() {
+    LoadZero();
+  }
+
+  void LoadZero() {
+    memset(this, 0x0, sizeof(ESMatrix));
+  }
+
+  void LoadIdentity() {
+    LoadZero();
+    m[0][0] = 1.0f;
+    m[1][1] = 1.0f;
+    m[2][2] = 1.0f;
+    m[3][3] = 1.0f;
+  }
+
+  void Multiply(ESMatrix* a, ESMatrix* b) {
+    ESMatrix result;
+    for (int i = 0; i < 4; ++i) {
+      result.m[i][0] = (a->m[i][0] * b->m[0][0]) +
+                       (a->m[i][1] * b->m[1][0]) +
+                       (a->m[i][2] * b->m[2][0]) +
+                       (a->m[i][3] * b->m[3][0]);
+
+      result.m[i][1] = (a->m[i][0] * b->m[0][1]) +
+                       (a->m[i][1] * b->m[1][1]) +
+                       (a->m[i][2] * b->m[2][1]) +
+                       (a->m[i][3] * b->m[3][1]);
+
+      result.m[i][2] = (a->m[i][0] * b->m[0][2]) +
+                       (a->m[i][1] * b->m[1][2]) +
+                       (a->m[i][2] * b->m[2][2]) +
+                       (a->m[i][3] * b->m[3][2]);
+
+      result.m[i][3] = (a->m[i][0] * b->m[0][3]) +
+                       (a->m[i][1] * b->m[1][3]) +
+                       (a->m[i][2] * b->m[2][3]) +
+                       (a->m[i][3] * b->m[3][3]);
+    }
+    *this = result;
+  }
+
+  void Frustum(float left,
+               float right,
+               float bottom,
+               float top,
+               float near_z,
+               float far_z) {
+    float delta_x = right - left;
+    float delta_y = top - bottom;
+    float delta_z = far_z - near_z;
+
+    if ((near_z <= 0.0f) ||
+        (far_z <= 0.0f) ||
+        (delta_z <= 0.0f) ||
+        (delta_y <= 0.0f) ||
+        (delta_y <= 0.0f))
+      return;
+
+    ESMatrix frust;
+    frust.m[0][0] = 2.0f * near_z / delta_x;
+    frust.m[0][1] = frust.m[0][2] = frust.m[0][3] = 0.0f;
+
+    frust.m[1][1] = 2.0f * near_z / delta_y;
+    frust.m[1][0] = frust.m[1][2] = frust.m[1][3] = 0.0f;
+
+    frust.m[2][0] = (right + left) / delta_x;
+    frust.m[2][1] = (top + bottom) / delta_y;
+    frust.m[2][2] = -(near_z + far_z) / delta_z;
+    frust.m[2][3] = -1.0f;
+
+    frust.m[3][2] = -2.0f * near_z * far_z / delta_z;
+    frust.m[3][0] = frust.m[3][1] = frust.m[3][3] = 0.0f;
+
+    Multiply(&frust, this);
+  }
+
+  void Perspective(float fov_y, float aspect, float near_z, float far_z) {
+    GLfloat frustum_h = tanf(fov_y / 360.0f * kPi) * near_z;
+    GLfloat frustum_w = frustum_h * aspect;
+    Frustum(-frustum_w, frustum_w, -frustum_h, frustum_h, near_z, far_z);
+  }
+
+  void Translate(GLfloat tx, GLfloat ty, GLfloat tz) {
+    m[3][0] += m[0][0] * tx + m[1][0] * ty + m[2][0] * tz;
+    m[3][1] += m[0][1] * tx + m[1][1] * ty + m[2][1] * tz;
+    m[3][2] += m[0][2] * tx + m[1][2] * ty + m[2][2] * tz;
+    m[3][3] += m[0][3] * tx + m[1][3] * ty + m[2][3] * tz;
+  }
+
+  void Rotate(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
+    GLfloat mag = sqrtf(x * x + y * y + z * z);
+
+    GLfloat sin_angle = sinf(angle * kPi / 180.0f);
+    GLfloat cos_angle = cosf(angle * kPi / 180.0f);
+    if (mag > 0.0f) {
+      GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs;
+      GLfloat one_minus_cos;
+      ESMatrix rotation;
+
+      x /= mag;
+      y /= mag;
+      z /= mag;
+
+      xx = x * x;
+      yy = y * y;
+      zz = z * z;
+      xy = x * y;
+      yz = y * z;
+      zx = z * x;
+      xs = x * sin_angle;
+      ys = y * sin_angle;
+      zs = z * sin_angle;
+      one_minus_cos = 1.0f - cos_angle;
+
+      rotation.m[0][0] = (one_minus_cos * xx) + cos_angle;
+      rotation.m[0][1] = (one_minus_cos * xy) - zs;
+      rotation.m[0][2] = (one_minus_cos * zx) + ys;
+      rotation.m[0][3] = 0.0F;
+
+      rotation.m[1][0] = (one_minus_cos * xy) + zs;
+      rotation.m[1][1] = (one_minus_cos * yy) + cos_angle;
+      rotation.m[1][2] = (one_minus_cos * yz) - xs;
+      rotation.m[1][3] = 0.0F;
+
+      rotation.m[2][0] = (one_minus_cos * zx) - ys;
+      rotation.m[2][1] = (one_minus_cos * yz) + xs;
+      rotation.m[2][2] = (one_minus_cos * zz) + cos_angle;
+      rotation.m[2][3] = 0.0F;
+
+      rotation.m[3][0] = 0.0F;
+      rotation.m[3][1] = 0.0F;
+      rotation.m[3][2] = 0.0F;
+      rotation.m[3][3] = 1.0F;
+
+      Multiply(&rotation, this);
+    }
+  }
+};
+
+float RotationForTimeDelta(float delta_time) {
+  return delta_time * 40.0f;
+}
+
+float RotationForDragDistance(float drag_distance) {
+  return drag_distance / 5; // Arbitrary damping.
+}
+
+}  // namespace
+
+class SpinningCube::GLState {
+ public:
+  GLState();
+
+  void OnGLContextLost();
+
+  GLfloat angle_;  // Survives losing the GL context.
+
+  GLuint program_object_;
+  GLint position_location_;
+  GLint mvp_location_;
+  GLuint vbo_vertices_;
+  GLuint vbo_indices_;
+  int num_indices_;
+  ESMatrix mvp_matrix_;
+};
+
+SpinningCube::GLState::GLState()
+    : angle_(0) {
+  OnGLContextLost();
+}
+
+void SpinningCube::GLState::OnGLContextLost() {
+  program_object_ = 0;
+  position_location_ = 0;
+  mvp_location_ = 0;
+  vbo_vertices_ = 0;
+  vbo_indices_ = 0;
+  num_indices_ = 0;
+}
+
+SpinningCube::SpinningCube()
+    : initialized_(false),
+      width_(0),
+      height_(0),
+      state_(new GLState()),
+      fling_multiplier_(1.0f),
+      direction_(1) {
+  state_->angle_ = 45.0f;
+}
+
+SpinningCube::~SpinningCube() {
+  if (!initialized_)
+    return;
+  if (state_->vbo_vertices_)
+    glDeleteBuffers(1, &state_->vbo_vertices_);
+  if (state_->vbo_indices_)
+    glDeleteBuffers(1, &state_->vbo_indices_);
+  if (state_->program_object_)
+    glDeleteProgram(state_->program_object_);
+
+  delete state_;
+}
+
+void SpinningCube::Init(uint32_t width, uint32_t height) {
+  width_ = width;
+  height_ = height;
+
+  if (!initialized_) {
+    initialized_ = true;
+    const char vertext_shader_source[] =
+        "uniform mat4 u_mvpMatrix;                   \n"
+        "attribute vec4 a_position;                  \n"
+        "void main()                                 \n"
+        "{                                           \n"
+        "   gl_Position = u_mvpMatrix * a_position;  \n"
+        "}                                           \n";
+
+    const char fragment_shader_source[] =
+        "precision mediump float;                            \n"
+        "void main()                                         \n"
+        "{                                                   \n"
+        "  gl_FragColor = vec4( 0.0, 0.0, 1.0, 1.0 );        \n"
+        "}                                                   \n";
+
+    state_->program_object_ = LoadProgram(
+        vertext_shader_source, fragment_shader_source);
+    state_->position_location_ = glGetAttribLocation(
+        state_->program_object_, "a_position");
+    state_->mvp_location_ = glGetUniformLocation(
+        state_->program_object_, "u_mvpMatrix");
+    state_->num_indices_ = GenerateCube(
+        &state_->vbo_vertices_, &state_->vbo_indices_);
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+  }
+}
+
+void SpinningCube::OnGLContextLost() {
+  // TODO(yzshen): Is it correct that in this case we don't need to do cleanup
+  // for program and buffers?
+  initialized_ = false;
+  height_ = 0;
+  width_ = 0;
+  state_->OnGLContextLost();
+}
+
+void SpinningCube::SetFlingMultiplier(float drag_distance,
+                                      float drag_time) {
+  fling_multiplier_ = RotationForDragDistance(drag_distance) /
+      RotationForTimeDelta(drag_time);
+
+}
+
+void SpinningCube::UpdateForTimeDelta(float delta_time) {
+  state_->angle_ += RotationForTimeDelta(delta_time) * fling_multiplier_;
+  if (state_->angle_ >= 360.0f)
+    state_->angle_ -= 360.0f;
+
+  // Arbitrary 50-step linear reduction in spin speed.
+  if (fling_multiplier_ > 1.0f) {
+    fling_multiplier_ =
+        std::max(1.0f, fling_multiplier_ - (fling_multiplier_ - 1.0f) / 50);
+  }
+
+  Update();
+}
+
+void SpinningCube::UpdateForDragDistance(float distance) {
+  state_->angle_ += RotationForDragDistance(distance);
+  if (state_->angle_ >= 360.0f )
+    state_->angle_ -= 360.0f;
+
+  Update();
+}
+
+void SpinningCube::Draw() {
+  glViewport(0, 0, width_, height_);
+  glClear(GL_COLOR_BUFFER_BIT);
+  glUseProgram(state_->program_object_);
+  glBindBuffer(GL_ARRAY_BUFFER, state_->vbo_vertices_);
+  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, state_->vbo_indices_);
+  glVertexAttribPointer(state_->position_location_,
+                           3,
+                           GL_FLOAT,
+                           GL_FALSE, 3 * sizeof(GLfloat),
+                           0);
+  glEnableVertexAttribArray(state_->position_location_);
+  glUniformMatrix4fv(state_->mvp_location_,
+                        1,
+                        GL_FALSE,
+                        (GLfloat*) &state_->mvp_matrix_.m[0][0]);
+  glDrawElements(GL_TRIANGLES,
+                    state_->num_indices_,
+                    GL_UNSIGNED_SHORT,
+                    0);
+}
+
+void SpinningCube::Update() {
+  float aspect = static_cast<GLfloat>(width_) / static_cast<GLfloat>(height_);
+
+  ESMatrix perspective;
+  perspective.LoadIdentity();
+  perspective.Perspective(60.0f, aspect, 1.0f, 20.0f );
+
+  ESMatrix modelview;
+  modelview.LoadIdentity();
+  modelview.Translate(0.0, 0.0, -2.0);
+  modelview.Rotate(state_->angle_ * direction_, 1.0, 0.0, 1.0);
+
+  state_->mvp_matrix_.Multiply(&modelview, &perspective);
+}
diff --git a/ppapi/examples/gles2_spinning_cube/spinning_cube.h b/ppapi/examples/gles2_spinning_cube/spinning_cube.h
new file mode 100644
index 0000000..84a302c
--- /dev/null
+++ b/ppapi/examples/gles2_spinning_cube/spinning_cube.h
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_EXAMPLES_GLES2_SPINNING_CUBE_SPINNING_CUBE_H_
+#define PPAPI_EXAMPLES_GLES2_SPINNING_CUBE_SPINNING_CUBE_H_
+
+#include "ppapi/c/pp_stdint.h"
+
+class SpinningCube {
+ public:
+  SpinningCube();
+  ~SpinningCube();
+
+  void Init(uint32_t width, uint32_t height);
+  void set_direction(int direction) { direction_ = direction; }
+  void SetFlingMultiplier(float drag_distance, float drag_time);
+  void UpdateForTimeDelta(float delta_time);
+  void UpdateForDragDistance(float distance);
+  void Draw();
+
+  void OnGLContextLost();
+
+ private:
+  class GLState;
+
+  // Disallow copy and assign.
+  SpinningCube(const SpinningCube& other);
+  SpinningCube& operator=(const SpinningCube& other);
+
+  void Update();
+
+  bool initialized_;
+  uint32_t width_;
+  uint32_t height_;
+  // Owned ptr.
+  GLState* state_;
+  float fling_multiplier_;
+  int direction_;
+};
+
+#endif  // PPAPI_EXAMPLES_GLES2_SPINNING_CUBE_SPINNING_CUBE_H_
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc
index 931bfe2..e98c4c8 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.cc
+++ b/ppapi/native_client/src/trusted/plugin/plugin.cc
@@ -230,25 +230,25 @@
   HistogramEnumerate("NaCl.Client.OSArch", os_arch, kNaClOSArchMax, -1);
 }
 
-void Plugin::HistogramEnumerateLoadStatus(PP_NaClError error_code,
-                                          bool is_installed) {
+void Plugin::HistogramEnumerateLoadStatus(PP_NaClError error_code) {
   HistogramEnumerate("NaCl.LoadStatus.Plugin", error_code, PP_NACL_ERROR_MAX,
                      PP_NACL_ERROR_UNKNOWN);
 
   // Gather data to see if being installed changes load outcomes.
-  const char* name = is_installed ? "NaCl.LoadStatus.Plugin.InstalledApp" :
+  const char* name = nacl_interface_->GetIsInstalled(pp_instance()) ?
+      "NaCl.LoadStatus.Plugin.InstalledApp" :
       "NaCl.LoadStatus.Plugin.NotInstalledApp";
   HistogramEnumerate(name, error_code, PP_NACL_ERROR_MAX,
                      PP_NACL_ERROR_UNKNOWN);
 }
 
-void Plugin::HistogramEnumerateSelLdrLoadStatus(NaClErrorCode error_code,
-                                                bool is_installed) {
+void Plugin::HistogramEnumerateSelLdrLoadStatus(NaClErrorCode error_code) {
   HistogramEnumerate("NaCl.LoadStatus.SelLdr", error_code,
                      NACL_ERROR_CODE_MAX, LOAD_STATUS_UNKNOWN);
 
   // Gather data to see if being installed changes load outcomes.
-  const char* name = is_installed ? "NaCl.LoadStatus.SelLdr.InstalledApp" :
+  const char* name = nacl_interface_->GetIsInstalled(pp_instance()) ?
+      "NaCl.LoadStatus.SelLdr.InstalledApp" :
       "NaCl.LoadStatus.SelLdr.NotInstalledApp";
   HistogramEnumerate(name, error_code, NACL_ERROR_CODE_MAX,
                      LOAD_STATUS_UNKNOWN);
@@ -589,10 +589,8 @@
     : pp::Instance(pp_instance),
       main_subprocess_("main subprocess", NULL, NULL),
       uses_nonsfi_mode_(false),
-      nexe_error_reported_(false),
       wrapper_factory_(NULL),
       enable_dev_interfaces_(false),
-      is_installed_(false),
       init_time_(0),
       ready_time_(0),
       nexe_size_(0),
@@ -606,7 +604,10 @@
   nexe_downloader_.Initialize(this);
   nacl_interface_ = GetNaClInterface();
   CHECK(nacl_interface_ != NULL);
-  set_nacl_ready_state(UNSENT);
+
+  // Notify PPB_NaCl_Private that the instance is created before altering any
+  // state that it tracks.
+  nacl_interface_->InstanceCreated(pp_instance);
   set_last_error_string("");
   // We call set_exit_status() here to ensure that the 'exitStatus' property is
   // set. This can only be called when nacl_interface_ is not NULL.
@@ -622,7 +623,7 @@
   // Destroy the coordinator while the rest of the data is still there
   pnacl_coordinator_.reset(NULL);
 
-  if (!nexe_error_reported()) {
+  if (!nacl_interface_->GetNexeErrorReported(pp_instance())) {
     HistogramTimeLarge(
         "NaCl.ModuleUptime.Normal",
         (shutdown_start - ready_time_) / NACL_MICROS_PER_MILLI);
@@ -708,7 +709,7 @@
   PLUGIN_PRINTF(("Plugin::NexeFileDidOpen (file_desc=%" NACL_PRId32 ")\n",
                  info.get_desc()));
   HistogramHTTPStatusCode(
-      is_installed_ ?
+      nacl_interface_->GetIsInstalled(pp_instance()) ?
           "NaCl.HttpStatusCodeClass.Nexe.InstalledApp" :
           "NaCl.HttpStatusCodeClass.Nexe.NotInstalledApp",
       nexe_downloader_.status_code());
@@ -842,11 +843,12 @@
   // that fits into our load progress event grammar.  If the crash
   // occurs after loaded/loadend, then we use ReportDeadNexe to send a
   // "crash" event.
-  if (nexe_error_reported()) {
+  if (nacl_interface_->GetNexeErrorReported(pp_instance())) {
     PLUGIN_PRINTF(("Plugin::NexeDidCrash: error already reported;"
                    " suppressing\n"));
   } else {
-    if (nacl_ready_state_ == DONE) {
+    if (nacl_interface_->GetNaClReadyState(pp_instance()) ==
+        PP_NACL_READY_STATE_DONE) {
       ReportDeadNexe();
     } else {
       ErrorInfo error_info;
@@ -909,7 +911,10 @@
 void Plugin::ReportDeadNexe() {
   PLUGIN_PRINTF(("Plugin::ReportDeadNexe\n"));
 
-  if (nacl_ready_state_ == DONE && !nexe_error_reported()) {  // After loadEnd.
+  PP_NaClReadyState ready_state =
+      nacl_interface_->GetNaClReadyState(pp_instance());
+  if (ready_state == PP_NACL_READY_STATE_DONE &&  // After loadEnd
+      !nacl_interface_->GetNexeErrorReported(pp_instance())) {
     int64_t crash_time = NaClGetTimeOfDayMicroseconds();
     // Crashes will be more likely near startup, so use a medium histogram
     // instead of a large one.
@@ -922,7 +927,7 @@
     nacl_interface()->LogToConsole(pp_instance(), message.c_str());
 
     EnqueueProgressEvent(PP_NACL_EVENT_CRASH);
-    set_nexe_error_reported(true);
+    nacl_interface_->SetNexeErrorReported(pp_instance(), PP_TRUE);
   }
   // else ReportLoadError() and ReportAbortError() will be used by loading code
   // to provide error handling.
@@ -970,7 +975,7 @@
   HistogramTimeSmall("NaCl.Perf.StartupTime.ManifestDownload",
                      nexe_downloader_.TimeSinceOpenMilliseconds());
   HistogramHTTPStatusCode(
-      is_installed_ ?
+      nacl_interface_->GetIsInstalled(pp_instance()) ?
           "NaCl.HttpStatusCodeClass.Manifest.InstalledApp" :
           "NaCl.HttpStatusCodeClass.Manifest.NotInstalledApp",
       nexe_downloader_.status_code());
@@ -1048,10 +1053,14 @@
   if (manifest_->GetProgramURL(
           &program_url, &pnacl_options, &uses_nonsfi_mode, &error_info)) {
     pp::Var program_url_var(program_url);
-    is_installed_ = (nacl_interface_->GetUrlScheme(program_url_var.pp_var()) ==
-                     PP_SCHEME_CHROME_EXTENSION);
+    nacl_interface_->SetIsInstalled(
+        pp_instance(),
+        PP_FromBool(
+            nacl_interface_->GetUrlScheme(program_url_var.pp_var()) ==
+            PP_SCHEME_CHROME_EXTENSION));
     uses_nonsfi_mode_ = uses_nonsfi_mode;
-    set_nacl_ready_state(LOADING);
+    nacl_interface_->SetNaClReadyState(pp_instance(),
+                                       PP_NACL_READY_STATE_LOADING);
     // Inform JavaScript that we found a nexe URL to load.
     EnqueueProgressEvent(PP_NACL_EVENT_PROGRESS);
     if (pnacl_options.translate()) {
@@ -1105,11 +1114,14 @@
   }
   PLUGIN_PRINTF(("Plugin::RequestNaClManifest (resolved url='%s')\n",
                  nmf_resolved_url.AsString().c_str()));
-  is_installed_ = (nacl_interface_->GetUrlScheme(nmf_resolved_url.pp_var()) ==
-                   PP_SCHEME_CHROME_EXTENSION);
+  nacl_interface_->SetIsInstalled(
+      pp_instance(),
+      PP_FromBool(
+          nacl_interface_->GetUrlScheme(nmf_resolved_url.pp_var()) ==
+          PP_SCHEME_CHROME_EXTENSION));
   set_manifest_base_url(nmf_resolved_url.AsString());
   // Inform JavaScript that a load is starting.
-  set_nacl_ready_state(OPENED);
+  nacl_interface_->SetNaClReadyState(pp_instance(), PP_NACL_READY_STATE_OPENED);
   EnqueueProgressEvent(PP_NACL_EVENT_LOADSTART);
   bool is_data_uri =
       (nacl_interface_->GetUrlScheme(nmf_resolved_url.pp_var()) ==
@@ -1148,7 +1160,8 @@
   bool is_pnacl = (mime_type() == kPnaclMIMEType);
   bool nonsfi_mode_enabled =
       PP_ToBool(nacl_interface_->IsNonSFIModeEnabled());
-  bool pnacl_debug = GetNaClInterface()->NaClDebugStubEnabled();
+  bool pnacl_debug = GetNaClInterface()->NaClDebugEnabledForURL(
+      manifest_base_url().c_str());
   const char* sandbox_isa = nacl_interface_->GetSandboxArch();
   nacl::scoped_ptr<JsonManifest> json_manifest(
       new JsonManifest(url_util_,
@@ -1163,9 +1176,10 @@
   return true;
 }
 
-void Plugin::UrlDidOpenForStreamAsFile(int32_t pp_error,
-                                       FileDownloader*& url_downloader,
-                                       PP_CompletionCallback callback) {
+void Plugin::UrlDidOpenForStreamAsFile(
+    int32_t pp_error,
+    FileDownloader* url_downloader,
+    pp::CompletionCallback callback) {
   PLUGIN_PRINTF(("Plugin::UrlDidOpen (pp_error=%" NACL_PRId32
                  ", url_downloader=%p)\n", pp_error,
                  static_cast<void*>(url_downloader)));
@@ -1175,7 +1189,7 @@
   NaClFileInfoAutoCloser *info = new NaClFileInfoAutoCloser(&tmp_info);
 
   if (pp_error != PP_OK) {
-    PP_RunCompletionCallback(&callback, pp_error);
+    callback.Run(pp_error);
     delete info;
   } else if (info->get_desc() > NACL_NO_FILE_DESC) {
     std::map<nacl::string, NaClFileInfoAutoCloser*>::iterator it =
@@ -1184,9 +1198,9 @@
       delete it->second;
     }
     url_file_info_map_[url_downloader->url()] = info;
-    PP_RunCompletionCallback(&callback, PP_OK);
+    callback.Run(PP_OK);
   } else {
-    PP_RunCompletionCallback(&callback, PP_ERROR_FAILED);
+    callback.Run(PP_ERROR_FAILED);
     delete info;
   }
 }
@@ -1206,7 +1220,7 @@
 }
 
 bool Plugin::StreamAsFile(const nacl::string& url,
-                          PP_CompletionCallback callback) {
+                          const pp::CompletionCallback& callback) {
   PLUGIN_PRINTF(("Plugin::StreamAsFile (url='%s')\n", url.c_str()));
   FileDownloader* downloader = new FileDownloader();
   downloader->Initialize(this);
@@ -1244,7 +1258,7 @@
                                uint64_t loaded_bytes,
                                uint64_t total_bytes) {
   // Set the readyState attribute to indicate loaded.
-  set_nacl_ready_state(DONE);
+  nacl_interface_->SetNaClReadyState(pp_instance(), PP_NACL_READY_STATE_DONE);
   // Inform JavaScript that loading was successful and is complete.
   const nacl::string& url = nexe_downloader_.url();
   EnqueueProgressEvent(
@@ -1253,7 +1267,7 @@
       PP_NACL_EVENT_LOADEND, url, length_computable, loaded_bytes, total_bytes);
 
   // UMA
-  HistogramEnumerateLoadStatus(PP_NACL_ERROR_LOAD_SUCCESS, is_installed_);
+  HistogramEnumerateLoadStatus(PP_NACL_ERROR_LOAD_SUCCESS);
 }
 
 
@@ -1263,20 +1277,15 @@
   nacl_interface_->ReportLoadError(pp_instance(),
                                    error_info.error_code(),
                                    error_info.message().c_str(),
-                                   error_info.console_message().c_str(),
-                                   PP_FromBool(is_installed_));
-
-  // Set the readyState attribute to indicate we need to start over.
-  set_nacl_ready_state(DONE);
-  set_nexe_error_reported(true);
+                                   error_info.console_message().c_str());
 }
 
 
 void Plugin::ReportLoadAbort() {
   PLUGIN_PRINTF(("Plugin::ReportLoadAbort\n"));
   // Set the readyState attribute to indicate we need to start over.
-  set_nacl_ready_state(DONE);
-  set_nexe_error_reported(true);
+  nacl_interface()->SetNaClReadyState(pp_instance(), PP_NACL_READY_STATE_DONE);
+  nacl_interface()->SetNexeErrorReported(pp_instance(), PP_TRUE);
   // Report an error in lastError and on the JavaScript console.
   nacl::string error_string("NaCl module load failed: user aborted");
   set_last_error_string(error_string);
@@ -1286,7 +1295,7 @@
   EnqueueProgressEvent(PP_NACL_EVENT_LOADEND);
 
   // UMA
-  HistogramEnumerateLoadStatus(PP_NACL_ERROR_LOAD_ABORTED, is_installed_);
+  HistogramEnumerateLoadStatus(PP_NACL_ERROR_LOAD_ABORTED);
 }
 
 void Plugin::UpdateDownloadProgress(
@@ -1344,8 +1353,7 @@
 }
 
 void Plugin::ReportSelLdrLoadStatus(int status) {
-  HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status),
-                                     is_installed_);
+  HistogramEnumerateSelLdrLoadStatus(static_cast<NaClErrorCode>(status));
 }
 
 void Plugin::EnqueueProgressEvent(PP_NaClEventType event_type) {
@@ -1420,14 +1428,6 @@
                                        pp::Var(error).pp_var());
 }
 
-void Plugin::set_nacl_ready_state(ReadyState state) {
-  nacl_ready_state_ = state;
-  DCHECK(nacl_interface_);
-  nacl_interface_->SetReadOnlyProperty(pp_instance(),
-                                       pp::Var("readyState").pp_var(),
-                                       pp::Var(state).pp_var());
-}
-
 void Plugin::set_exit_status(int exit_status) {
   pp::Core* core = pp::Module::Get()->core();
   if (core->IsMainThread()) {
diff --git a/ppapi/native_client/src/trusted/plugin/plugin.h b/ppapi/native_client/src/trusted/plugin/plugin.h
index 0fe9762..d7a5962 100644
--- a/ppapi/native_client/src/trusted/plugin/plugin.h
+++ b/ppapi/native_client/src/trusted/plugin/plugin.h
@@ -40,6 +40,7 @@
 }  // namespace nacl
 
 namespace pp {
+class CompletionCallback;
 class URLLoader;
 class URLUtil_Dev;
 }
@@ -160,26 +161,6 @@
     manifest_base_url_ = url;
   }
 
-  // The state of readiness of the plugin.
-  enum ReadyState {
-    // The trusted plugin begins in this ready state.
-    UNSENT = 0,
-    // The manifest file has been requested, but not yet received.
-    OPENED = 1,
-    // This state is unused.
-    HEADERS_RECEIVED = 2,
-    // The manifest file has been received and the nexe successfully requested.
-    LOADING = 3,
-    // The nexe has been loaded and the proxy started, so it is ready for
-    // interaction with the page.
-    DONE = 4
-  };
-
-  bool nexe_error_reported() const { return nexe_error_reported_; }
-  void set_nexe_error_reported(bool val) {
-    nexe_error_reported_ = val;
-  }
-
   nacl::DescWrapperFactory* wrapper_factory() const { return wrapper_factory_; }
 
   // Requests a NaCl manifest download from a |url| relative to the page origin.
@@ -198,7 +179,7 @@
   // a PP_Error indicating status. On success an open file descriptor
   // corresponding to the url body is recorded for further lookup.
   bool StreamAsFile(const nacl::string& url,
-                    PP_CompletionCallback pp_callback);
+                    const pp::CompletionCallback& callback);
 
   // Returns rich information for a file retrieved by StreamAsFile(). This info
   // contains a file descriptor. The caller must take ownership of this
@@ -264,10 +245,8 @@
                           int maximum,
                           int out_of_range_replacement);
   void HistogramEnumerateOsArch(const std::string& sandbox_isa);
-  void HistogramEnumerateLoadStatus(PP_NaClError error_code,
-                                    bool is_installed);
-  void HistogramEnumerateSelLdrLoadStatus(NaClErrorCode error_code,
-                                          bool is_installed);
+  void HistogramEnumerateLoadStatus(PP_NaClError error_code);
+  void HistogramEnumerateSelLdrLoadStatus(NaClErrorCode error_code);
   void HistogramEnumerateManifestIsDataURI(bool is_data_uri);
   void HistogramHTTPStatusCode(const std::string& name, int status);
 
@@ -354,8 +333,8 @@
 
   // Callback used when loading a URL for SRPC-based StreamAsFile().
   void UrlDidOpenForStreamAsFile(int32_t pp_error,
-                                 FileDownloader*& url_downloader,
-                                 PP_CompletionCallback pp_callback);
+                                 FileDownloader* url_downloader,
+                                 pp::CompletionCallback pp_callback);
 
   // Copy the main service runtime's most recent NaClLog output to the
   // JavaScript console.  Valid to use only after a crash, e.g., via a
@@ -368,8 +347,6 @@
   // request so it won't slow down non-installed file downloads.
   bool OpenURLFast(const nacl::string& url, FileDownloader* downloader);
 
-  void set_nacl_ready_state(ReadyState state);
-
   void SetExitStatusOnMainThread(int32_t pp_error, int exit_status);
 
   std::map<std::string, std::string> args_;
@@ -381,7 +358,6 @@
   nacl::string manifest_base_url_;
   nacl::string manifest_url_;
   bool uses_nonsfi_mode_;
-  ReadyState nacl_ready_state_;
   bool nexe_error_reported_;  // error or crash reported
 
   nacl::DescWrapperFactory* wrapper_factory_;
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
index 00322ba..40a2060 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
@@ -128,7 +128,7 @@
 const uint32_t kKBPSBuckets = 100;
 
 void HistogramTime(pp::UMAPrivate& uma,
-                   const std::string& name, int64_t ms) {
+                   const nacl::string& name, int64_t ms) {
   if (ms < 0) return;
   uma.HistogramCustomTimes(name,
                            ms,
@@ -137,7 +137,7 @@
 }
 
 void HistogramSizeKB(pp::UMAPrivate& uma,
-                     const std::string& name, int32_t kb) {
+                     const nacl::string& name, int32_t kb) {
   if (kb < 0) return;
   uma.HistogramCustomCounts(name,
                             kb,
@@ -146,7 +146,7 @@
 }
 
 void HistogramRatio(pp::UMAPrivate& uma,
-                    const std::string& name, int64_t a, int64_t b) {
+                    const nacl::string& name, int64_t a, int64_t b) {
   if (a < 0 || b <= 0) return;
   uma.HistogramCustomCounts(name,
                             100 * a / b,
@@ -155,7 +155,7 @@
 }
 
 void HistogramKBPerSec(pp::UMAPrivate& uma,
-                       const std::string& name, double kb, double s) {
+                       const nacl::string& name, double kb, double s) {
   if (kb < 0.0 || s <= 0.0) return;
   uma.HistogramCustomCounts(name,
                             static_cast<int64_t>(kb / s),
@@ -339,20 +339,10 @@
 
   // If there are no errors, report stats from this thread (the main thread).
   HistogramOptLevel(plugin_->uma_interface(), pnacl_options_.opt_level());
-  const plugin::PnaclTimeStats& time_stats = translate_thread_->GetTimeStats();
-  HistogramTime(plugin_->uma_interface(),
-                "NaCl.Perf.PNaClLoadTime.LoadCompiler",
-                time_stats.pnacl_llc_load_time / NACL_MICROS_PER_MILLI);
-  HistogramTime(plugin_->uma_interface(), "NaCl.Perf.PNaClLoadTime.CompileTime",
-                time_stats.pnacl_compile_time / NACL_MICROS_PER_MILLI);
   HistogramKBPerSec(plugin_->uma_interface(),
                     "NaCl.Perf.PNaClLoadTime.CompileKBPerSec",
                     pexe_size_ / 1024.0,
-                    time_stats.pnacl_compile_time / 1000000.0);
-  HistogramTime(plugin_->uma_interface(), "NaCl.Perf.PNaClLoadTime.LoadLinker",
-                time_stats.pnacl_ld_load_time / NACL_MICROS_PER_MILLI);
-  HistogramTime(plugin_->uma_interface(), "NaCl.Perf.PNaClLoadTime.LinkTime",
-                time_stats.pnacl_link_time / NACL_MICROS_PER_MILLI);
+                    translate_thread_->GetCompileTime() / 1000000.0);
   HistogramSizeKB(plugin_->uma_interface(), "NaCl.Perf.Size.Pexe",
                   static_cast<int64_t>(pexe_size_ / 1024));
 
@@ -621,6 +611,7 @@
 
 void PnaclCoordinator::BitcodeGotCompiled(int32_t pp_error,
                                           int64_t bytes_compiled) {
+  DCHECK(pp_error == PP_OK);
   pexe_bytes_compiled_ += bytes_compiled;
   // If we don't know the expected total yet, ask.
   if (!ExpectedProgressKnown()) {
@@ -654,6 +645,21 @@
                                        bytes_compiled);
 }
 
+void PnaclCoordinator::DoUMATimeMeasure(int32_t pp_error,
+                                        const nacl::string& event_name,
+                                        int64_t microsecs) {
+  DCHECK(pp_error == PP_OK);
+  HistogramTime(
+      plugin_->uma_interface(), event_name, microsecs / NACL_MICROS_PER_MILLI);
+}
+
+pp::CompletionCallback PnaclCoordinator::GetUMATimeCallback(
+    const nacl::string& event_name, int64_t microsecs) {
+  return callback_factory_.NewCallback(&PnaclCoordinator::DoUMATimeMeasure,
+                                       event_name,
+                                       microsecs);
+}
+
 void PnaclCoordinator::GetCurrentProgress(int64_t* bytes_loaded,
                                           int64_t* bytes_total) {
   *bytes_loaded = pexe_bytes_compiled_;
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
index 321878b..20b3d85 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h
@@ -116,6 +116,11 @@
   // have been compiled.
   pp::CompletionCallback GetCompileProgressCallback(int64_t bytes_compiled);
 
+  // Return a callback that should be notified when an interesting UMA timing
+  // is ready to be reported.
+  pp::CompletionCallback GetUMATimeCallback(const nacl::string& event_name,
+                                            int64_t microsecs);
+
   // Get the last known load progress.
   void GetCurrentProgress(int64_t* bytes_loaded, int64_t* bytes_total);
 
@@ -175,6 +180,10 @@
   // Invoked when the read descriptor for nexe_file_ is created.
   void NexeReadDidOpen(int32_t pp_error);
 
+  // Invoked when a UMA timing measurement from the translate thread is ready.
+  void DoUMATimeMeasure(
+      int32_t pp_error, const nacl::string& event_name, int64_t microsecs);
+
   // Keeps track of the pp_error upon entry to TranslateFinished,
   // for inspection after cleanup.
   int32_t translate_finish_error_;
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
index 8d29739..7cb98b8 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc
@@ -19,7 +19,7 @@
 PnaclTranslateThread::PnaclTranslateThread() : llc_subprocess_active_(false),
                                                ld_subprocess_active_(false),
                                                done_(false),
-                                               time_stats_(),
+                                               compile_time_(0),
                                                manifest_(NULL),
                                                obj_files_(NULL),
                                                nexe_file_(NULL),
@@ -149,6 +149,7 @@
     llc_out_files.push_back(invalid_desc_wrapper_);
   }
 
+  pp::Core* core = pp::Module::Get()->core();
   {
     nacl::MutexLocker ml(&subprocess_mu_);
     int64_t llc_start_time = NaClGetTimeOfDayMicroseconds();
@@ -161,8 +162,11 @@
       return;
     }
     llc_subprocess_active_ = true;
-    time_stats_.pnacl_llc_load_time =
-        (NaClGetTimeOfDayMicroseconds() - llc_start_time);
+    core->CallOnMainThread(0,
+                           coordinator_->GetUMATimeCallback(
+                               "NaCl.Perf.PNaClLoadTime.LoadCompiler",
+                               NaClGetTimeOfDayMicroseconds() - llc_start_time),
+                           PP_OK);
     // Run LLC.
     PluginReverseInterface* llc_reverse =
         llc_subprocess_->service_runtime()->rev_interface();
@@ -221,9 +225,7 @@
     }
     return;
   }
-
   PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n"));
-  pp::Core* core = pp::Module::Get()->core();
 
   // llc process is started.
   while(!done_ || data_buffers_.size() > 0) {
@@ -283,8 +285,12 @@
     }
     return;
   }
-  time_stats_.pnacl_compile_time =
-      (NaClGetTimeOfDayMicroseconds() - compile_start_time);
+  compile_time_ = NaClGetTimeOfDayMicroseconds() - compile_start_time;
+  core->CallOnMainThread(0,
+                         coordinator_->GetUMATimeCallback(
+                             "NaCl.Perf.PNaClLoadTime.CompileTime",
+                             compile_time_),
+                         PP_OK);
 
   // Shut down the llc subprocess.
   NaClXMutexLock(&subprocess_mu_);
@@ -318,7 +324,7 @@
   }
 
   nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper();
-
+  pp::Core* core = pp::Module::Get()->core();
   {
     // Create LD process
     nacl::MutexLocker ml(&subprocess_mu_);
@@ -332,8 +338,11 @@
       return false;
     }
     ld_subprocess_active_ = true;
-    time_stats_.pnacl_ld_load_time =
-        (NaClGetTimeOfDayMicroseconds() - ld_start_time);
+    core->CallOnMainThread(0,
+                           coordinator_->GetUMATimeCallback(
+                               "NaCl.Perf.PNaClLoadTime.LoadLinker",
+                               NaClGetTimeOfDayMicroseconds() - ld_start_time),
+                           PP_OK);
     PluginReverseInterface* ld_reverse =
         ld_subprocess_->service_runtime()->rev_interface();
     ld_reverse->AddTempQuotaManagedFile(nexe_file_->identifier());
@@ -368,8 +377,11 @@
                     "link failed.");
     return false;
   }
-  time_stats_.pnacl_link_time =
-      NaClGetTimeOfDayMicroseconds() - link_start_time;
+  core->CallOnMainThread(0,
+                         coordinator_->GetUMATimeCallback(
+                             "NaCl.Perf.PNaClLoadTime.LinkTime",
+                             NaClGetTimeOfDayMicroseconds() - link_start_time),
+                         PP_OK);
   PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n",
                  this));
   // Shut down the ld subprocess.
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h
index 5a20181..4de0963 100644
--- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h
+++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h
@@ -34,13 +34,6 @@
 class PnaclResources;
 class TempFile;
 
-struct PnaclTimeStats {
-  int64_t pnacl_llc_load_time;
-  int64_t pnacl_compile_time;
-  int64_t pnacl_ld_load_time;
-  int64_t pnacl_link_time;
-};
-
 class PnaclTranslateThread {
  public:
   PnaclTranslateThread();
@@ -70,7 +63,7 @@
   // Send bitcode bytes to the translator. Called from the main thread.
   void PutBytes(std::vector<char>* data, int count);
 
-  const PnaclTimeStats& GetTimeStats() const { return time_stats_; }
+  int64_t GetCompileTime() const { return compile_time_; }
 
  private:
   // Starts an individual llc or ld subprocess used for translation.
@@ -117,7 +110,7 @@
   // Associated with buffer_cond_
   bool done_;
 
-  PnaclTimeStats time_stats_;
+  int64_t compile_time_;
 
   // Data about the translation files, owned by the coordinator
   const Manifest* manifest_;
diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.cc b/ppapi/native_client/src/trusted/plugin/service_runtime.cc
index 9bb7ff4..acf14c7 100644
--- a/ppapi/native_client/src/trusted/plugin/service_runtime.cc
+++ b/ppapi/native_client/src/trusted/plugin/service_runtime.cc
@@ -210,7 +210,6 @@
 void PluginReverseInterface::OpenManifestEntry_MainThreadContinuation(
     OpenManifestEntryResource* p,
     int32_t err) {
-  OpenManifestEntryResource *open_cont;
   UNREFERENCED_PARAMETER(err);
   // CallOnMainThread continuations always called with err == PP_OK.
 
@@ -239,54 +238,7 @@
           "ResolveKey: %s -> %s (pnacl_translate(%d))\n",
           p->url.c_str(), mapped_url.c_str(), pnacl_options.translate());
 
-  open_cont = new OpenManifestEntryResource(*p);  // copy ctor!
-  CHECK(open_cont != NULL);
-  open_cont->url = mapped_url;
-  if (!pnacl_options.translate()) {
-    pp::CompletionCallback stream_cc = WeakRefNewCallback(
-        anchor_,
-        this,
-        &PluginReverseInterface::StreamAsFile_MainThreadContinuation,
-        open_cont);
-    // Normal files.
-    if (!PnaclUrls::IsPnaclComponent(mapped_url)) {
-      if (!plugin_->StreamAsFile(mapped_url,
-                                 stream_cc.pp_completion_callback())) {
-        NaClLog(4,
-                "OpenManifestEntry_MainThreadContinuation: "
-                "StreamAsFile failed\n");
-        nacl::MutexLocker take(&mu_);
-        *p->op_complete_ptr = true;  // done...
-        p->file_info->desc = -1;       // but failed.
-        NaClXCondVarBroadcast(&cv_);
-        return;
-      }
-      NaClLog(4,
-              "OpenManifestEntry_MainThreadContinuation: StreamAsFile okay\n");
-    } else {
-      // Special PNaCl support files, that are installed on the
-      // user machine.
-      int32_t fd = PnaclResources::GetPnaclFD(
-          plugin_,
-          PnaclUrls::PnaclComponentURLToFilename(mapped_url).c_str());
-      if (fd < 0) {
-        // We checked earlier if the pnacl component wasn't installed
-        // yet, so this shouldn't happen. At this point, we can't do much
-        // anymore, so just continue with an invalid fd.
-        NaClLog(4,
-                "OpenManifestEntry_MainThreadContinuation: "
-                "GetReadonlyPnaclFd failed\n");
-      }
-      nacl::MutexLocker take(&mu_);
-      *p->op_complete_ptr = true;  // done!
-      // TODO(ncbray): enable the fast loading and validation paths for this
-      // type of file.
-      p->file_info->desc = fd;
-      NaClXCondVarBroadcast(&cv_);
-      NaClLog(4,
-              "OpenManifestEntry_MainThreadContinuation: GetPnaclFd okay\n");
-    }
-  } else {
+  if (pnacl_options.translate()) {
     // Requires PNaCl translation, but that's not supported.
     NaClLog(4,
             "OpenManifestEntry_MainThreadContinuation: "
@@ -297,6 +249,56 @@
     NaClXCondVarBroadcast(&cv_);
     return;
   }
+
+  if (PnaclUrls::IsPnaclComponent(mapped_url)) {
+    // Special PNaCl support files, that are installed on the
+    // user machine.
+    int32_t fd = PnaclResources::GetPnaclFD(
+        plugin_,
+        PnaclUrls::PnaclComponentURLToFilename(mapped_url).c_str());
+    if (fd < 0) {
+      // We checked earlier if the pnacl component wasn't installed
+      // yet, so this shouldn't happen. At this point, we can't do much
+      // anymore, so just continue with an invalid fd.
+      NaClLog(4,
+              "OpenManifestEntry_MainThreadContinuation: "
+              "GetReadonlyPnaclFd failed\n");
+    }
+    nacl::MutexLocker take(&mu_);
+    *p->op_complete_ptr = true;  // done!
+    // TODO(ncbray): enable the fast loading and validation paths for this
+    // type of file.
+    p->file_info->desc = fd;
+    NaClXCondVarBroadcast(&cv_);
+    NaClLog(4,
+            "OpenManifestEntry_MainThreadContinuation: GetPnaclFd okay\n");
+    return;
+  }
+
+  // Hereafter, normal files.
+
+  // Because p is owned by the callback of this invocation, so it is necessary
+  // to create another instance.
+  OpenManifestEntryResource* open_cont = new OpenManifestEntryResource(*p);
+  open_cont->url = mapped_url;
+  pp::CompletionCallback stream_cc = WeakRefNewCallback(
+      anchor_,
+      this,
+      &PluginReverseInterface::StreamAsFile_MainThreadContinuation,
+      open_cont);
+
+  if (!plugin_->StreamAsFile(mapped_url, stream_cc)) {
+    NaClLog(4,
+            "OpenManifestEntry_MainThreadContinuation: "
+            "StreamAsFile failed\n");
+    // Here, StreamAsFile is failed and stream_cc is not called.
+    // However, open_cont will be released only by the invocation.
+    // So, we manually call it here with error.
+    stream_cc.Run(PP_ERROR_FAILED);
+    return;
+  }
+
+  NaClLog(4, "OpenManifestEntry_MainThreadContinuation: StreamAsFile okay\n");
   // p is deleted automatically
 }
 
diff --git a/ppapi/native_client/src/trusted/plugin/utility.cc b/ppapi/native_client/src/trusted/plugin/utility.cc
index 1458e18..d800424 100644
--- a/ppapi/native_client/src/trusted/plugin/utility.cc
+++ b/ppapi/native_client/src/trusted/plugin/utility.cc
@@ -8,6 +8,8 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "native_client/src/include/portability_io.h"
+#include "native_client/src/include/portability_process.h"
 #include "ppapi/native_client/src/trusted/plugin/utility.h"
 
 namespace plugin {
@@ -33,14 +35,26 @@
 
 /*
  * Opens file where plugin log should be written. The file name is
- * taken from NACL_PLUGIN_LOG environment variable.
+ * taken from NACL_PLUGIN_LOG environment variable and process pid.
  * If environment variable doesn't exist or file can't be opened,
  * the function returns stdout.
  */
 FILE* NaClPluginLogFileEnv() {
   char* file = getenv("NACL_PLUGIN_LOG");
   if (NULL != file) {
-    FILE* log_file = fopen(file, "w+");
+    int pid = GETPID();
+    /*
+     * 11 characters for pid, 5 for a glue string and 1 for null terminator.
+     */
+    size_t filename_length = strlen(file) + 32;
+    char* filename = new char[filename_length];
+    int ret = SNPRINTF(filename, filename_length, "%s.%d.log", file, pid);
+    if (ret <= 0 || static_cast<size_t>(ret) >= filename_length) {
+      delete[] filename;
+      return stdout;
+    }
+    FILE* log_file = fopen(filename, "w+");
+    delete[] filename;
     if (NULL == log_file) {
         return stdout;
     }
diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
index 1a6fbb7..ce83fba 100644
--- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
+++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c
@@ -190,7 +190,7 @@
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UDPSocket_Private_0_2;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UDPSocket_Private_0_3;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UDPSocket_Private_0_4;
-static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UMA_Private_0_2;
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UMA_Private_0_3;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VideoDestination_Private_0_1;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_VideoSource_Private_0_1;
 static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_X509Certificate_Private_0_1;
@@ -992,42 +992,42 @@
 
 /* Begin wrapper methods for PPB_MediaStreamAudioTrack_0_1 */
 
-static PP_Bool Pnacl_M34_PPB_MediaStreamAudioTrack_IsMediaStreamAudioTrack(PP_Resource resource) {
+static PP_Bool Pnacl_M35_PPB_MediaStreamAudioTrack_IsMediaStreamAudioTrack(PP_Resource resource) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   return iface->IsMediaStreamAudioTrack(resource);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamAudioTrack_Configure(PP_Resource audio_track, const int32_t attrib_list[], struct PP_CompletionCallback* callback) {
+static int32_t Pnacl_M35_PPB_MediaStreamAudioTrack_Configure(PP_Resource audio_track, const int32_t attrib_list[], struct PP_CompletionCallback* callback) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   return iface->Configure(audio_track, attrib_list, *callback);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamAudioTrack_GetAttrib(PP_Resource audio_track, PP_MediaStreamAudioTrack_Attrib attrib, int32_t* value) {
+static int32_t Pnacl_M35_PPB_MediaStreamAudioTrack_GetAttrib(PP_Resource audio_track, PP_MediaStreamAudioTrack_Attrib attrib, int32_t* value) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   return iface->GetAttrib(audio_track, attrib, value);
 }
 
-static void Pnacl_M34_PPB_MediaStreamAudioTrack_GetId(struct PP_Var* _struct_result, PP_Resource audio_track) {
+static void Pnacl_M35_PPB_MediaStreamAudioTrack_GetId(struct PP_Var* _struct_result, PP_Resource audio_track) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   *_struct_result = iface->GetId(audio_track);
 }
 
-static PP_Bool Pnacl_M34_PPB_MediaStreamAudioTrack_HasEnded(PP_Resource audio_track) {
+static PP_Bool Pnacl_M35_PPB_MediaStreamAudioTrack_HasEnded(PP_Resource audio_track) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   return iface->HasEnded(audio_track);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamAudioTrack_GetBuffer(PP_Resource audio_track, PP_Resource* buffer, struct PP_CompletionCallback* callback) {
+static int32_t Pnacl_M35_PPB_MediaStreamAudioTrack_GetBuffer(PP_Resource audio_track, PP_Resource* buffer, struct PP_CompletionCallback* callback) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   return iface->GetBuffer(audio_track, buffer, *callback);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamAudioTrack_RecycleBuffer(PP_Resource audio_track, PP_Resource buffer) {
+static int32_t Pnacl_M35_PPB_MediaStreamAudioTrack_RecycleBuffer(PP_Resource audio_track, PP_Resource buffer) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   return iface->RecycleBuffer(audio_track, buffer);
 }
 
-static void Pnacl_M34_PPB_MediaStreamAudioTrack_Close(PP_Resource audio_track) {
+static void Pnacl_M35_PPB_MediaStreamAudioTrack_Close(PP_Resource audio_track) {
   const struct PPB_MediaStreamAudioTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamAudioTrack_0_1.real_iface;
   iface->Close(audio_track);
 }
@@ -1036,42 +1036,42 @@
 
 /* Begin wrapper methods for PPB_MediaStreamVideoTrack_0_1 */
 
-static PP_Bool Pnacl_M34_PPB_MediaStreamVideoTrack_IsMediaStreamVideoTrack(PP_Resource resource) {
+static PP_Bool Pnacl_M35_PPB_MediaStreamVideoTrack_IsMediaStreamVideoTrack(PP_Resource resource) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   return iface->IsMediaStreamVideoTrack(resource);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamVideoTrack_Configure(PP_Resource video_track, const int32_t attrib_list[], struct PP_CompletionCallback* callback) {
+static int32_t Pnacl_M35_PPB_MediaStreamVideoTrack_Configure(PP_Resource video_track, const int32_t attrib_list[], struct PP_CompletionCallback* callback) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   return iface->Configure(video_track, attrib_list, *callback);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamVideoTrack_GetAttrib(PP_Resource video_track, PP_MediaStreamVideoTrack_Attrib attrib, int32_t* value) {
+static int32_t Pnacl_M35_PPB_MediaStreamVideoTrack_GetAttrib(PP_Resource video_track, PP_MediaStreamVideoTrack_Attrib attrib, int32_t* value) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   return iface->GetAttrib(video_track, attrib, value);
 }
 
-static void Pnacl_M34_PPB_MediaStreamVideoTrack_GetId(struct PP_Var* _struct_result, PP_Resource video_track) {
+static void Pnacl_M35_PPB_MediaStreamVideoTrack_GetId(struct PP_Var* _struct_result, PP_Resource video_track) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   *_struct_result = iface->GetId(video_track);
 }
 
-static PP_Bool Pnacl_M34_PPB_MediaStreamVideoTrack_HasEnded(PP_Resource video_track) {
+static PP_Bool Pnacl_M35_PPB_MediaStreamVideoTrack_HasEnded(PP_Resource video_track) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   return iface->HasEnded(video_track);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamVideoTrack_GetFrame(PP_Resource video_track, PP_Resource* frame, struct PP_CompletionCallback* callback) {
+static int32_t Pnacl_M35_PPB_MediaStreamVideoTrack_GetFrame(PP_Resource video_track, PP_Resource* frame, struct PP_CompletionCallback* callback) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   return iface->GetFrame(video_track, frame, *callback);
 }
 
-static int32_t Pnacl_M34_PPB_MediaStreamVideoTrack_RecycleFrame(PP_Resource video_track, PP_Resource frame) {
+static int32_t Pnacl_M35_PPB_MediaStreamVideoTrack_RecycleFrame(PP_Resource video_track, PP_Resource frame) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   return iface->RecycleFrame(video_track, frame);
 }
 
-static void Pnacl_M34_PPB_MediaStreamVideoTrack_Close(PP_Resource video_track) {
+static void Pnacl_M35_PPB_MediaStreamVideoTrack_Close(PP_Resource video_track) {
   const struct PPB_MediaStreamVideoTrack_0_1 *iface = Pnacl_WrapperInfo_PPB_MediaStreamVideoTrack_0_1.real_iface;
   iface->Close(video_track);
 }
@@ -2020,8 +2020,6 @@
 
 /* End wrapper methods for PPB_FileChooser_Dev_0_6 */
 
-/* Not generating wrapper methods for PPB_Find_Dev_0_3 */
-
 /* Begin wrapper methods for PPB_Font_Dev_0_6 */
 
 static void Pnacl_M14_PPB_Font_Dev_GetFontFamilies(struct PP_Var* _struct_result, PP_Instance instance) {
@@ -2402,8 +2400,6 @@
 
 /* Not generating wrapper methods for PPB_Zoom_Dev_0_2 */
 
-/* Not generating wrapper methods for PPP_Find_Dev_0_3 */
-
 /* Not generating wrapper methods for PPP_NetworkState_Dev_0_1 */
 
 /* Not generating wrapper methods for PPP_Printing_Dev_0_6 */
@@ -2545,6 +2541,8 @@
 
 /* End wrapper methods for PPB_FileRefPrivate_0_1 */
 
+/* Not generating wrapper methods for PPB_Find_Private_0_3 */
+
 /* Begin wrapper methods for PPB_Flash_12_4 */
 
 static void Pnacl_M21_PPB_Flash_SetInstanceAlwaysOnTop(PP_Instance instance, PP_Bool on_top) {
@@ -3163,9 +3161,14 @@
   iface->SetReadOnlyProperty(instance, *key, *value);
 }
 
-static void Pnacl_M25_PPB_NaCl_Private_ReportLoadError(PP_Instance instance, PP_NaClError error, const char* error_message, const char* console_message, PP_Bool is_installed) {
+static void Pnacl_M25_PPB_NaCl_Private_ReportLoadError(PP_Instance instance, PP_NaClError error, const char* error_message, const char* console_message) {
   const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
-  iface->ReportLoadError(instance, error, error_message, console_message, is_installed);
+  iface->ReportLoadError(instance, error, error_message, console_message);
+}
+
+static void Pnacl_M25_PPB_NaCl_Private_InstanceCreated(PP_Instance instance) {
+  const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
+  iface->InstanceCreated(instance);
 }
 
 static void Pnacl_M25_PPB_NaCl_Private_InstanceDestroyed(PP_Instance instance) {
@@ -3173,9 +3176,9 @@
   iface->InstanceDestroyed(instance);
 }
 
-static PP_Bool Pnacl_M25_PPB_NaCl_Private_NaClDebugStubEnabled(void) {
+static PP_Bool Pnacl_M25_PPB_NaCl_Private_NaClDebugEnabledForURL(const char* alleged_nmf_url) {
   const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
-  return iface->NaClDebugStubEnabled();
+  return iface->NaClDebugEnabledForURL(alleged_nmf_url);
 }
 
 static const char* Pnacl_M25_PPB_NaCl_Private_GetSandboxArch(void) {
@@ -3193,6 +3196,36 @@
   iface->LogToConsole(instance, message);
 }
 
+static PP_Bool Pnacl_M25_PPB_NaCl_Private_GetNexeErrorReported(PP_Instance instance) {
+  const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
+  return iface->GetNexeErrorReported(instance);
+}
+
+static void Pnacl_M25_PPB_NaCl_Private_SetNexeErrorReported(PP_Instance instance, PP_Bool error_reported) {
+  const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
+  iface->SetNexeErrorReported(instance, error_reported);
+}
+
+static PP_NaClReadyState Pnacl_M25_PPB_NaCl_Private_GetNaClReadyState(PP_Instance instance) {
+  const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
+  return iface->GetNaClReadyState(instance);
+}
+
+static void Pnacl_M25_PPB_NaCl_Private_SetNaClReadyState(PP_Instance instance, PP_NaClReadyState ready_state) {
+  const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
+  iface->SetNaClReadyState(instance, ready_state);
+}
+
+static PP_Bool Pnacl_M25_PPB_NaCl_Private_GetIsInstalled(PP_Instance instance) {
+  const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
+  return iface->GetIsInstalled(instance);
+}
+
+static void Pnacl_M25_PPB_NaCl_Private_SetIsInstalled(PP_Instance instance, PP_Bool is_installed) {
+  const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface;
+  iface->SetIsInstalled(instance, is_installed);
+}
+
 /* End wrapper methods for PPB_NaCl_Private_1_0 */
 
 /* Begin wrapper methods for PPB_NetAddress_Private_0_1 */
@@ -3839,24 +3872,29 @@
 
 /* End wrapper methods for PPB_UDPSocket_Private_0_4 */
 
-/* Begin wrapper methods for PPB_UMA_Private_0_2 */
+/* Begin wrapper methods for PPB_UMA_Private_0_3 */
 
-static void Pnacl_M33_PPB_UMA_Private_HistogramCustomTimes(PP_Instance instance, struct PP_Var* name, int64_t sample, int64_t min, int64_t max, uint32_t bucket_count) {
-  const struct PPB_UMA_Private_0_2 *iface = Pnacl_WrapperInfo_PPB_UMA_Private_0_2.real_iface;
+static void Pnacl_M35_PPB_UMA_Private_HistogramCustomTimes(PP_Instance instance, struct PP_Var* name, int64_t sample, int64_t min, int64_t max, uint32_t bucket_count) {
+  const struct PPB_UMA_Private_0_3 *iface = Pnacl_WrapperInfo_PPB_UMA_Private_0_3.real_iface;
   iface->HistogramCustomTimes(instance, *name, sample, min, max, bucket_count);
 }
 
-static void Pnacl_M33_PPB_UMA_Private_HistogramCustomCounts(PP_Instance instance, struct PP_Var* name, int32_t sample, int32_t min, int32_t max, uint32_t bucket_count) {
-  const struct PPB_UMA_Private_0_2 *iface = Pnacl_WrapperInfo_PPB_UMA_Private_0_2.real_iface;
+static void Pnacl_M35_PPB_UMA_Private_HistogramCustomCounts(PP_Instance instance, struct PP_Var* name, int32_t sample, int32_t min, int32_t max, uint32_t bucket_count) {
+  const struct PPB_UMA_Private_0_3 *iface = Pnacl_WrapperInfo_PPB_UMA_Private_0_3.real_iface;
   iface->HistogramCustomCounts(instance, *name, sample, min, max, bucket_count);
 }
 
-static void Pnacl_M33_PPB_UMA_Private_HistogramEnumeration(PP_Instance instance, struct PP_Var* name, int32_t sample, int32_t boundary_value) {
-  const struct PPB_UMA_Private_0_2 *iface = Pnacl_WrapperInfo_PPB_UMA_Private_0_2.real_iface;
+static void Pnacl_M35_PPB_UMA_Private_HistogramEnumeration(PP_Instance instance, struct PP_Var* name, int32_t sample, int32_t boundary_value) {
+  const struct PPB_UMA_Private_0_3 *iface = Pnacl_WrapperInfo_PPB_UMA_Private_0_3.real_iface;
   iface->HistogramEnumeration(instance, *name, sample, boundary_value);
 }
 
-/* End wrapper methods for PPB_UMA_Private_0_2 */
+static int32_t Pnacl_M35_PPB_UMA_Private_IsCrashReportingEnabled(PP_Instance instance, struct PP_CompletionCallback* callback) {
+  const struct PPB_UMA_Private_0_3 *iface = Pnacl_WrapperInfo_PPB_UMA_Private_0_3.real_iface;
+  return iface->IsCrashReportingEnabled(instance, *callback);
+}
+
+/* End wrapper methods for PPB_UMA_Private_0_3 */
 
 /* Begin wrapper methods for PPB_VideoDestination_Private_0_1 */
 
@@ -4021,6 +4059,8 @@
 
 /* End wrapper methods for PPP_ContentDecryptor_Private_0_11 */
 
+/* Not generating wrapper methods for PPP_Find_Private_0_3 */
+
 /* Not generating wrapper methods for PPP_Flash_BrowserOperations_1_0 */
 
 /* Not generating wrapper methods for PPP_Flash_BrowserOperations_1_2 */
@@ -4442,25 +4482,25 @@
 /* Not generating wrapper interface for PPB_Instance_1_0 */
 
 static const struct PPB_MediaStreamAudioTrack_0_1 Pnacl_Wrappers_PPB_MediaStreamAudioTrack_0_1 = {
-    .IsMediaStreamAudioTrack = (PP_Bool (*)(PP_Resource resource))&Pnacl_M34_PPB_MediaStreamAudioTrack_IsMediaStreamAudioTrack,
-    .Configure = (int32_t (*)(PP_Resource audio_track, const int32_t attrib_list[], struct PP_CompletionCallback callback))&Pnacl_M34_PPB_MediaStreamAudioTrack_Configure,
-    .GetAttrib = (int32_t (*)(PP_Resource audio_track, PP_MediaStreamAudioTrack_Attrib attrib, int32_t* value))&Pnacl_M34_PPB_MediaStreamAudioTrack_GetAttrib,
-    .GetId = (struct PP_Var (*)(PP_Resource audio_track))&Pnacl_M34_PPB_MediaStreamAudioTrack_GetId,
-    .HasEnded = (PP_Bool (*)(PP_Resource audio_track))&Pnacl_M34_PPB_MediaStreamAudioTrack_HasEnded,
-    .GetBuffer = (int32_t (*)(PP_Resource audio_track, PP_Resource* buffer, struct PP_CompletionCallback callback))&Pnacl_M34_PPB_MediaStreamAudioTrack_GetBuffer,
-    .RecycleBuffer = (int32_t (*)(PP_Resource audio_track, PP_Resource buffer))&Pnacl_M34_PPB_MediaStreamAudioTrack_RecycleBuffer,
-    .Close = (void (*)(PP_Resource audio_track))&Pnacl_M34_PPB_MediaStreamAudioTrack_Close
+    .IsMediaStreamAudioTrack = (PP_Bool (*)(PP_Resource resource))&Pnacl_M35_PPB_MediaStreamAudioTrack_IsMediaStreamAudioTrack,
+    .Configure = (int32_t (*)(PP_Resource audio_track, const int32_t attrib_list[], struct PP_CompletionCallback callback))&Pnacl_M35_PPB_MediaStreamAudioTrack_Configure,
+    .GetAttrib = (int32_t (*)(PP_Resource audio_track, PP_MediaStreamAudioTrack_Attrib attrib, int32_t* value))&Pnacl_M35_PPB_MediaStreamAudioTrack_GetAttrib,
+    .GetId = (struct PP_Var (*)(PP_Resource audio_track))&Pnacl_M35_PPB_MediaStreamAudioTrack_GetId,
+    .HasEnded = (PP_Bool (*)(PP_Resource audio_track))&Pnacl_M35_PPB_MediaStreamAudioTrack_HasEnded,
+    .GetBuffer = (int32_t (*)(PP_Resource audio_track, PP_Resource* buffer, struct PP_CompletionCallback callback))&Pnacl_M35_PPB_MediaStreamAudioTrack_GetBuffer,
+    .RecycleBuffer = (int32_t (*)(PP_Resource audio_track, PP_Resource buffer))&Pnacl_M35_PPB_MediaStreamAudioTrack_RecycleBuffer,
+    .Close = (void (*)(PP_Resource audio_track))&Pnacl_M35_PPB_MediaStreamAudioTrack_Close
 };
 
 static const struct PPB_MediaStreamVideoTrack_0_1 Pnacl_Wrappers_PPB_MediaStreamVideoTrack_0_1 = {
-    .IsMediaStreamVideoTrack = (PP_Bool (*)(PP_Resource resource))&Pnacl_M34_PPB_MediaStreamVideoTrack_IsMediaStreamVideoTrack,
-    .Configure = (int32_t (*)(PP_Resource video_track, const int32_t attrib_list[], struct PP_CompletionCallback callback))&Pnacl_M34_PPB_MediaStreamVideoTrack_Configure,
-    .GetAttrib = (int32_t (*)(PP_Resource video_track, PP_MediaStreamVideoTrack_Attrib attrib, int32_t* value))&Pnacl_M34_PPB_MediaStreamVideoTrack_GetAttrib,
-    .GetId = (struct PP_Var (*)(PP_Resource video_track))&Pnacl_M34_PPB_MediaStreamVideoTrack_GetId,
-    .HasEnded = (PP_Bool (*)(PP_Resource video_track))&Pnacl_M34_PPB_MediaStreamVideoTrack_HasEnded,
-    .GetFrame = (int32_t (*)(PP_Resource video_track, PP_Resource* frame, struct PP_CompletionCallback callback))&Pnacl_M34_PPB_MediaStreamVideoTrack_GetFrame,
-    .RecycleFrame = (int32_t (*)(PP_Resource video_track, PP_Resource frame))&Pnacl_M34_PPB_MediaStreamVideoTrack_RecycleFrame,
-    .Close = (void (*)(PP_Resource video_track))&Pnacl_M34_PPB_MediaStreamVideoTrack_Close
+    .IsMediaStreamVideoTrack = (PP_Bool (*)(PP_Resource resource))&Pnacl_M35_PPB_MediaStreamVideoTrack_IsMediaStreamVideoTrack,
+    .Configure = (int32_t (*)(PP_Resource video_track, const int32_t attrib_list[], struct PP_CompletionCallback callback))&Pnacl_M35_PPB_MediaStreamVideoTrack_Configure,
+    .GetAttrib = (int32_t (*)(PP_Resource video_track, PP_MediaStreamVideoTrack_Attrib attrib, int32_t* value))&Pnacl_M35_PPB_MediaStreamVideoTrack_GetAttrib,
+    .GetId = (struct PP_Var (*)(PP_Resource video_track))&Pnacl_M35_PPB_MediaStreamVideoTrack_GetId,
+    .HasEnded = (PP_Bool (*)(PP_Resource video_track))&Pnacl_M35_PPB_MediaStreamVideoTrack_HasEnded,
+    .GetFrame = (int32_t (*)(PP_Resource video_track, PP_Resource* frame, struct PP_CompletionCallback callback))&Pnacl_M35_PPB_MediaStreamVideoTrack_GetFrame,
+    .RecycleFrame = (int32_t (*)(PP_Resource video_track, PP_Resource frame))&Pnacl_M35_PPB_MediaStreamVideoTrack_RecycleFrame,
+    .Close = (void (*)(PP_Resource video_track))&Pnacl_M35_PPB_MediaStreamVideoTrack_Close
 };
 
 static const struct PPB_MessageLoop_1_0 Pnacl_Wrappers_PPB_MessageLoop_1_0 = {
@@ -4743,8 +4783,6 @@
     .Show = (int32_t (*)(PP_Resource chooser, struct PP_ArrayOutput output, struct PP_CompletionCallback callback))&Pnacl_M19_PPB_FileChooser_Dev_Show
 };
 
-/* Not generating wrapper interface for PPB_Find_Dev_0_3 */
-
 static const struct PPB_Font_Dev_0_6 Pnacl_Wrappers_PPB_Font_Dev_0_6 = {
     .GetFontFamilies = (struct PP_Var (*)(PP_Instance instance))&Pnacl_M14_PPB_Font_Dev_GetFontFamilies,
     .Create = (PP_Resource (*)(PP_Instance instance, const struct PP_FontDescription_Dev* description))&Pnacl_M14_PPB_Font_Dev_Create,
@@ -4860,8 +4898,6 @@
 
 /* Not generating wrapper interface for PPB_Zoom_Dev_0_2 */
 
-/* Not generating wrapper interface for PPP_Find_Dev_0_3 */
-
 /* Not generating wrapper interface for PPP_NetworkState_Dev_0_1 */
 
 /* Not generating wrapper interface for PPP_Printing_Dev_0_6 */
@@ -4917,6 +4953,8 @@
     .GetAbsolutePath = (struct PP_Var (*)(PP_Resource file_ref))&Pnacl_M15_PPB_FileRefPrivate_GetAbsolutePath
 };
 
+/* Not generating wrapper interface for PPB_Find_Private_0_3 */
+
 static const struct PPB_Flash_12_4 Pnacl_Wrappers_PPB_Flash_12_4 = {
     .SetInstanceAlwaysOnTop = (void (*)(PP_Instance instance, PP_Bool on_top))&Pnacl_M21_PPB_Flash_SetInstanceAlwaysOnTop,
     .DrawGlyphs = (PP_Bool (*)(PP_Instance instance, PP_Resource pp_image_data, const struct PP_BrowserFont_Trusted_Description* font_desc, uint32_t color, const struct PP_Point* position, const struct PP_Rect* clip, const float transformation[3][3], PP_Bool allow_subpixel_aa, uint32_t glyph_count, const uint16_t glyph_indices[], const struct PP_Point glyph_advances[]))&Pnacl_M21_PPB_Flash_DrawGlyphs,
@@ -5080,12 +5118,19 @@
     .OpenNaClExecutable = (PP_FileHandle (*)(PP_Instance instance, const char* file_url, uint64_t* file_token_lo, uint64_t* file_token_hi))&Pnacl_M25_PPB_NaCl_Private_OpenNaClExecutable,
     .DispatchEvent = (void (*)(PP_Instance instance, PP_NaClEventType event_type, const char* resource_url, PP_Bool length_is_computable, uint64_t loaded_bytes, uint64_t total_bytes))&Pnacl_M25_PPB_NaCl_Private_DispatchEvent,
     .SetReadOnlyProperty = (void (*)(PP_Instance instance, struct PP_Var key, struct PP_Var value))&Pnacl_M25_PPB_NaCl_Private_SetReadOnlyProperty,
-    .ReportLoadError = (void (*)(PP_Instance instance, PP_NaClError error, const char* error_message, const char* console_message, PP_Bool is_installed))&Pnacl_M25_PPB_NaCl_Private_ReportLoadError,
+    .ReportLoadError = (void (*)(PP_Instance instance, PP_NaClError error, const char* error_message, const char* console_message))&Pnacl_M25_PPB_NaCl_Private_ReportLoadError,
+    .InstanceCreated = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_InstanceCreated,
     .InstanceDestroyed = (void (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_InstanceDestroyed,
-    .NaClDebugStubEnabled = (PP_Bool (*)(void))&Pnacl_M25_PPB_NaCl_Private_NaClDebugStubEnabled,
+    .NaClDebugEnabledForURL = (PP_Bool (*)(const char* alleged_nmf_url))&Pnacl_M25_PPB_NaCl_Private_NaClDebugEnabledForURL,
     .GetSandboxArch = (const char* (*)(void))&Pnacl_M25_PPB_NaCl_Private_GetSandboxArch,
     .GetUrlScheme = (PP_UrlSchemeType (*)(struct PP_Var url))&Pnacl_M25_PPB_NaCl_Private_GetUrlScheme,
-    .LogToConsole = (void (*)(PP_Instance instance, const char* message))&Pnacl_M25_PPB_NaCl_Private_LogToConsole
+    .LogToConsole = (void (*)(PP_Instance instance, const char* message))&Pnacl_M25_PPB_NaCl_Private_LogToConsole,
+    .GetNexeErrorReported = (PP_Bool (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetNexeErrorReported,
+    .SetNexeErrorReported = (void (*)(PP_Instance instance, PP_Bool error_reported))&Pnacl_M25_PPB_NaCl_Private_SetNexeErrorReported,
+    .GetNaClReadyState = (PP_NaClReadyState (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetNaClReadyState,
+    .SetNaClReadyState = (void (*)(PP_Instance instance, PP_NaClReadyState ready_state))&Pnacl_M25_PPB_NaCl_Private_SetNaClReadyState,
+    .GetIsInstalled = (PP_Bool (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_GetIsInstalled,
+    .SetIsInstalled = (void (*)(PP_Instance instance, PP_Bool is_installed))&Pnacl_M25_PPB_NaCl_Private_SetIsInstalled
 };
 
 static const struct PPB_NetAddress_Private_0_1 Pnacl_Wrappers_PPB_NetAddress_Private_0_1 = {
@@ -5252,10 +5297,11 @@
     .Close = (void (*)(PP_Resource udp_socket))&Pnacl_M23_PPB_UDPSocket_Private_Close
 };
 
-static const struct PPB_UMA_Private_0_2 Pnacl_Wrappers_PPB_UMA_Private_0_2 = {
-    .HistogramCustomTimes = (void (*)(PP_Instance instance, struct PP_Var name, int64_t sample, int64_t min, int64_t max, uint32_t bucket_count))&Pnacl_M33_PPB_UMA_Private_HistogramCustomTimes,
-    .HistogramCustomCounts = (void (*)(PP_Instance instance, struct PP_Var name, int32_t sample, int32_t min, int32_t max, uint32_t bucket_count))&Pnacl_M33_PPB_UMA_Private_HistogramCustomCounts,
-    .HistogramEnumeration = (void (*)(PP_Instance instance, struct PP_Var name, int32_t sample, int32_t boundary_value))&Pnacl_M33_PPB_UMA_Private_HistogramEnumeration
+static const struct PPB_UMA_Private_0_3 Pnacl_Wrappers_PPB_UMA_Private_0_3 = {
+    .HistogramCustomTimes = (void (*)(PP_Instance instance, struct PP_Var name, int64_t sample, int64_t min, int64_t max, uint32_t bucket_count))&Pnacl_M35_PPB_UMA_Private_HistogramCustomTimes,
+    .HistogramCustomCounts = (void (*)(PP_Instance instance, struct PP_Var name, int32_t sample, int32_t min, int32_t max, uint32_t bucket_count))&Pnacl_M35_PPB_UMA_Private_HistogramCustomCounts,
+    .HistogramEnumeration = (void (*)(PP_Instance instance, struct PP_Var name, int32_t sample, int32_t boundary_value))&Pnacl_M35_PPB_UMA_Private_HistogramEnumeration,
+    .IsCrashReportingEnabled = (int32_t (*)(PP_Instance instance, struct PP_CompletionCallback callback))&Pnacl_M35_PPB_UMA_Private_IsCrashReportingEnabled
 };
 
 static const struct PPB_VideoDestination_Private_0_1 Pnacl_Wrappers_PPB_VideoDestination_Private_0_1 = {
@@ -5295,6 +5341,8 @@
     .DecryptAndDecode = &Pnacl_M34_PPP_ContentDecryptor_Private_DecryptAndDecode
 };
 
+/* Not generating wrapper interface for PPP_Find_Private_0_3 */
+
 /* Not generating wrapper interface for PPP_Flash_BrowserOperations_1_0 */
 
 /* Not generating wrapper interface for PPP_Flash_BrowserOperations_1_2 */
@@ -5922,9 +5970,9 @@
   .real_iface = NULL
 };
 
-static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UMA_Private_0_2 = {
-  .iface_macro = PPB_UMA_PRIVATE_INTERFACE_0_2,
-  .wrapped_iface = (const void *) &Pnacl_Wrappers_PPB_UMA_Private_0_2,
+static struct __PnaclWrapperInfo Pnacl_WrapperInfo_PPB_UMA_Private_0_3 = {
+  .iface_macro = PPB_UMA_PRIVATE_INTERFACE_0_3,
+  .wrapped_iface = (const void *) &Pnacl_Wrappers_PPB_UMA_Private_0_3,
   .real_iface = NULL
 };
 
@@ -6065,7 +6113,7 @@
   &Pnacl_WrapperInfo_PPB_UDPSocket_Private_0_2,
   &Pnacl_WrapperInfo_PPB_UDPSocket_Private_0_3,
   &Pnacl_WrapperInfo_PPB_UDPSocket_Private_0_4,
-  &Pnacl_WrapperInfo_PPB_UMA_Private_0_2,
+  &Pnacl_WrapperInfo_PPB_UMA_Private_0_3,
   &Pnacl_WrapperInfo_PPB_VideoDestination_Private_0_1,
   &Pnacl_WrapperInfo_PPB_VideoSource_Private_0_1,
   &Pnacl_WrapperInfo_PPB_X509Certificate_Private_0_1,
diff --git a/ppapi/ppapi_shared.gypi b/ppapi/ppapi_shared.gypi
index 620a6eb..1a96e12 100644
--- a/ppapi/ppapi_shared.gypi
+++ b/ppapi/ppapi_shared.gypi
@@ -46,6 +46,7 @@
           'shared_impl/media_stream_video_track_shared.cc',
           'shared_impl/platform_file.cc',
           'shared_impl/platform_file.h',
+          'shared_impl/ppapi_constants.h',
           'shared_impl/ppapi_globals.cc',
           'shared_impl/ppapi_globals.h',
           'shared_impl/ppapi_nacl_plugin_args.cc',
@@ -170,7 +171,7 @@
           'thunk/ppb_file_ref_thunk.cc',
           'thunk/ppb_file_system_api.h',
           'thunk/ppb_file_system_thunk.cc',
-          'thunk/ppb_find_dev_thunk.cc',
+          'thunk/ppb_find_private_thunk.cc',
           'thunk/ppb_flash_clipboard_api.h',
           'thunk/ppb_flash_clipboard_thunk.cc',
           'thunk/ppb_flash_device_id_thunk.cc',
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index cfb16fc..600f36b 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -82,7 +82,6 @@
       'c/dev/ppb_cursor_control_dev.h',
       'c/dev/ppb_device_ref_dev.h',
       'c/dev/ppb_file_chooser_dev.h',
-      'c/dev/ppb_find_dev.h',
       'c/dev/ppb_font_dev.h',
       'c/dev/ppb_ime_input_event_dev.h',
       'c/dev/ppb_memory_dev.h',
@@ -94,7 +93,6 @@
       'c/dev/ppb_video_decoder_dev.h',
       'c/dev/ppb_widget_dev.h',
       'c/dev/ppb_zoom_dev.h',
-      'c/dev/ppp_find_dev.h',
       'c/dev/ppp_network_state_dev.h',
       'c/dev/ppp_scrollbar_dev.h',
       'c/dev/ppp_selection_dev.h',
@@ -109,6 +107,7 @@
       'c/private/pp_video_frame_private.h',
       'c/private/ppb_content_decryptor_private.h',
       'c/private/ppb_ext_crx_file_system_private.h',
+      'c/private/ppb_find_private.h',
       'c/private/ppb_flash.h',
       'c/private/ppb_flash_clipboard.h',
       'c/private/ppb_flash_file.h',
@@ -134,6 +133,7 @@
       'c/private/ppb_video_source_private.h',
       'c/private/ppb_x509_certificate_private.h',
       'c/private/ppp_content_decryptor_private.h',
+      'c/private/ppp_find_private.h',
       'c/private/ppp_instance_private.h',
 
       # Deprecated interfaces.
@@ -262,8 +262,6 @@
       'cpp/dev/device_ref_dev.h',
       'cpp/dev/file_chooser_dev.cc',
       'cpp/dev/file_chooser_dev.h',
-      'cpp/dev/find_dev.cc',
-      'cpp/dev/find_dev.h',
       'cpp/dev/font_dev.cc',
       'cpp/dev/font_dev.h',
       'cpp/dev/graphics_2d_dev.cc',
@@ -318,6 +316,8 @@
       'cpp/private/ext_crx_file_system_private.h',
       'cpp/private/file_io_private.cc',
       'cpp/private/file_io_private.h',
+      'cpp/private/find_private.cc',
+      'cpp/private/find_private.h',
       'cpp/private/flash.cc',
       'cpp/private/flash.h',
       'cpp/private/flash_clipboard.cc',
diff --git a/ppapi/ppapi_tests.gypi b/ppapi/ppapi_tests.gypi
index f9447d4..e56a191 100644
--- a/ppapi/ppapi_tests.gypi
+++ b/ppapi/ppapi_tests.gypi
@@ -551,5 +551,21 @@
         'examples/media_stream_video/media_stream_video.cc',
       ],
     },
+    {
+      'target_name': 'ppapi_example_gles2_spinning_cube',
+      'dependencies': [
+        'ppapi_example_skeleton',
+        'ppapi.gyp:ppapi_cpp',
+        'ppapi.gyp:ppapi_gles2',
+      ],
+      'include_dirs': [
+        'lib/gl/include',
+      ],
+      'sources': [
+        'examples/gles2_spinning_cube/gles2_spinning_cube.cc',
+        'examples/gles2_spinning_cube/spinning_cube.cc',
+        'examples/gles2_spinning_cube/spinning_cube.h',
+      ],
+    },
   ],
 }
diff --git a/ppapi/proxy/interface_list.cc b/ppapi/proxy/interface_list.cc
index 3a6d988..a5f58d3 100644
--- a/ppapi/proxy/interface_list.cc
+++ b/ppapi/proxy/interface_list.cc
@@ -14,7 +14,6 @@
 #include "ppapi/c/dev/ppb_crypto_dev.h"
 #include "ppapi/c/dev/ppb_cursor_control_dev.h"
 #include "ppapi/c/dev/ppb_device_ref_dev.h"
-#include "ppapi/c/dev/ppb_find_dev.h"
 #include "ppapi/c/dev/ppb_font_dev.h"
 #include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
 #include "ppapi/c/dev/ppb_graphics_2d_dev.h"
@@ -76,6 +75,7 @@
 #include "ppapi/c/private/ppb_ext_crx_file_system_private.h"
 #include "ppapi/c/private/ppb_file_io_private.h"
 #include "ppapi/c/private/ppb_file_ref_private.h"
+#include "ppapi/c/private/ppb_find_private.h"
 #include "ppapi/c/private/ppb_flash_clipboard.h"
 #include "ppapi/c/private/ppb_flash_file.h"
 #include "ppapi/c/private/ppb_flash_font_file.h"
@@ -303,8 +303,8 @@
 #if !defined(OS_NACL)
   AddProxy(API_ID_PPP_PDF, &ProxyFactory<PPP_Pdf_Proxy>);
   AddPPP(PPP_PDF_INTERFACE, PPP_Pdf_Proxy::GetProxyInterface());
-  AddProxy(API_ID_PPP_FIND_DEV, &ProxyFactory<PPP_Find_Proxy>);
-  AddPPP(PPP_FIND_DEV_INTERFACE, PPP_Find_Proxy::GetProxyInterface());
+  AddProxy(API_ID_PPP_FIND_PRIVATE, &ProxyFactory<PPP_Find_Proxy>);
+  AddPPP(PPP_FIND_PRIVATE_INTERFACE, PPP_Find_Proxy::GetProxyInterface());
   AddProxy(API_ID_PPP_VIDEO_DECODER_DEV, &ProxyFactory<PPP_VideoDecoder_Proxy>);
   AddPPP(PPP_VIDEODECODER_DEV_INTERFACE,
          PPP_VideoDecoder_Proxy::GetProxyInterface());
diff --git a/ppapi/proxy/plugin_globals.cc b/ppapi/proxy/plugin_globals.cc
index d34adf1..d361ae1 100644
--- a/ppapi/proxy/plugin_globals.cc
+++ b/ppapi/proxy/plugin_globals.cc
@@ -13,15 +13,10 @@
 #include "ppapi/proxy/ppapi_messages.h"
 #include "ppapi/proxy/ppb_message_loop_proxy.h"
 #include "ppapi/proxy/resource_reply_thread_registrar.h"
+#include "ppapi/shared_impl/ppapi_constants.h"
 #include "ppapi/shared_impl/proxy_lock.h"
 #include "ppapi/thunk/enter.h"
 
-namespace {
-
-const int kKeepaliveThrottleIntervalDefault = 5000;
-
-}  // namespace
-
 namespace ppapi {
 namespace proxy {
 
@@ -64,7 +59,7 @@
           new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
       plugin_recently_active_(false),
       keepalive_throttle_interval_milliseconds_(
-          kKeepaliveThrottleIntervalDefault),
+          ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds),
       weak_factory_(this) {
   DCHECK(!plugin_globals_);
   plugin_globals_ = this;
@@ -85,7 +80,7 @@
           new ResourceReplyThreadRegistrar(GetMainThreadMessageLoop())),
       plugin_recently_active_(false),
       keepalive_throttle_interval_milliseconds_(
-          kKeepaliveThrottleIntervalDefault),
+          kKeepaliveThrottleIntervalDefaultMilliseconds),
       weak_factory_(this) {
   DCHECK(!plugin_globals_);
 }
@@ -186,12 +181,13 @@
     if (!GetBrowserSender() || !base::MessageLoop::current())
       return;
     GetBrowserSender()->Send(new PpapiHostMsg_Keepalive());
-
-    GetMainThreadMessageLoop()->PostDelayedTask(FROM_HERE,
+    DCHECK(keepalive_throttle_interval_milliseconds_);
+    GetMainThreadMessageLoop()->PostDelayedTask(
+        FROM_HERE,
         RunWhileLocked(base::Bind(&PluginGlobals::OnReleaseKeepaliveThrottle,
                                   weak_factory_.GetWeakPtr())),
         base::TimeDelta::FromMilliseconds(
-            keepalive_throttle_interval_milliseconds()));
+            keepalive_throttle_interval_milliseconds_));
   }
 }
 
@@ -225,11 +221,7 @@
   return loop_for_main_thread_.get();
 }
 
-int PluginGlobals::keepalive_throttle_interval_milliseconds() const {
-  return keepalive_throttle_interval_milliseconds_;
-}
-
-void PluginGlobals::set_keepalive_throttle_interval_milliseconds(int i) {
+void PluginGlobals::set_keepalive_throttle_interval_milliseconds(unsigned i) {
   keepalive_throttle_interval_milliseconds_ = i;
 }
 
diff --git a/ppapi/proxy/plugin_globals.h b/ppapi/proxy/plugin_globals.h
index dac33b6..5dc614d 100644
--- a/ppapi/proxy/plugin_globals.h
+++ b/ppapi/proxy/plugin_globals.h
@@ -137,8 +137,7 @@
   // Interval to limit how many IPC messages are sent indicating that the plugin
   // is active and should be kept alive. The value must be smaller than any
   // threshold used to kill inactive plugins by the embedder host.
-  int keepalive_throttle_interval_milliseconds() const;
-  void set_keepalive_throttle_interval_milliseconds(int i);
+  void set_keepalive_throttle_interval_milliseconds(unsigned i);
 
  private:
   class BrowserSender;
@@ -183,7 +182,7 @@
   // all considered active.
   bool plugin_recently_active_;
 
-  int keepalive_throttle_interval_milliseconds_;
+  unsigned keepalive_throttle_interval_milliseconds_;
 
   // Member variables should appear before the WeakPtrFactory, see weak_ptr.h.
   base::WeakPtrFactory<PluginGlobals> weak_factory_;
diff --git a/ppapi/proxy/plugin_main_irt.cc b/ppapi/proxy/plugin_main_irt.cc
index ae03884..34e7923 100644
--- a/ppapi/proxy/plugin_main_irt.cc
+++ b/ppapi/proxy/plugin_main_irt.cc
@@ -31,7 +31,6 @@
 #include "ppapi/proxy/plugin_message_filter.h"
 #include "ppapi/proxy/plugin_proxy_delegate.h"
 #include "ppapi/proxy/resource_reply_thread_registrar.h"
-#include "ppapi/shared_impl/ppapi_switches.h"
 #include "ppapi/shared_impl/ppb_audio_shared.h"
 
 #if defined(__native_client__)
@@ -116,8 +115,6 @@
   void OnMsgInitializeNaClDispatcher(const ppapi::PpapiNaClPluginArgs& args);
   void OnPluginDispatcherMessageReceived(const IPC::Message& msg);
 
-  void SetPpapiKeepAliveThrottleFromCommandLine();
-
   std::set<PP_Instance> instances_;
   std::map<uint32, PluginDispatcher*> plugin_dispatchers_;
   uint32 next_plugin_dispatcher_id_;
@@ -249,7 +246,10 @@
   logging::LoggingSettings settings;
   settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
   logging::InitLogging(settings);
-  SetPpapiKeepAliveThrottleFromCommandLine();
+
+  ppapi::proxy::PluginGlobals::Get()
+      ->set_keepalive_throttle_interval_milliseconds(
+          args.keepalive_throttle_interval_milliseconds);
 
   // Tell the process-global GetInterface which interfaces it can return to the
   // plugin.
@@ -294,18 +294,6 @@
     dispatcher->second->OnMessageReceived(msg);
 }
 
-void PpapiDispatcher::SetPpapiKeepAliveThrottleFromCommandLine() {
-  unsigned keepalive_throttle_interval_milliseconds = 0;
-  if (base::StringToUint(
-          CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
-              switches::kPpapiKeepAliveThrottle),
-          &keepalive_throttle_interval_milliseconds)) {
-    ppapi::proxy::PluginGlobals::Get()->
-        set_keepalive_throttle_interval_milliseconds(
-            keepalive_throttle_interval_milliseconds);
-  }
-}
-
 }  // namespace
 
 void SetIPCFileDescriptors(int ipc_browser_fd, int ipc_renderer_fd) {
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.cc b/ppapi/proxy/ppapi_command_buffer_proxy.cc
index 81bc442..4d140f2 100644
--- a/ppapi/proxy/ppapi_command_buffer_proxy.cc
+++ b/ppapi/proxy/ppapi_command_buffer_proxy.cc
@@ -21,13 +21,8 @@
 }
 
 PpapiCommandBufferProxy::~PpapiCommandBufferProxy() {
-  // Delete all the locally cached shared memory objects, closing the handle
-  // in this process.
-  for (TransferBufferMap::iterator it = transfer_buffers_.begin();
-       it != transfer_buffers_.end(); ++it) {
-    delete it->second.shared_memory;
-    it->second.shared_memory = NULL;
-  }
+  // gpu::Buffers are no longer referenced, allowing shared memory objects to be
+  // deleted, closing the handle in this process.
 }
 
 bool PpapiCommandBufferProxy::Initialize() {
@@ -116,20 +111,21 @@
   NOTREACHED();
 }
 
-gpu::Buffer PpapiCommandBufferProxy::CreateTransferBuffer(size_t size,
-                                                          int32* id) {
+scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::CreateTransferBuffer(
+    size_t size,
+    int32* id) {
   *id = -1;
 
   if (last_state_.error != gpu::error::kNoError)
-    return gpu::Buffer();
+    return NULL;
 
   if (!Send(new PpapiHostMsg_PPBGraphics3D_CreateTransferBuffer(
             ppapi::API_ID_PPB_GRAPHICS_3D, resource_, size, id))) {
-    return gpu::Buffer();
+    return NULL;
   }
 
   if ((*id) <= 0)
-    return gpu::Buffer();
+    return NULL;
 
   return GetTransferBuffer(*id);
 }
@@ -141,12 +137,10 @@
   // Remove the transfer buffer from the client side4 cache.
   TransferBufferMap::iterator it = transfer_buffers_.find(id);
 
-  if (it != transfer_buffers_.end()) {
-    // Delete the shared memory object, closing the handle in this process.
-    delete it->second.shared_memory;
-
+  // Remove reference to buffer, allowing the shared memory object to be
+  // deleted, closing the handle in the process.
+  if (it != transfer_buffers_.end())
     transfer_buffers_.erase(it);
-  }
 
   Send(new PpapiHostMsg_PPBGraphics3D_DestroyTransferBuffer(
       ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id));
@@ -161,9 +155,10 @@
   return 0;
 }
 
-gpu::Buffer PpapiCommandBufferProxy::GetTransferBuffer(int32 id) {
+scoped_refptr<gpu::Buffer> PpapiCommandBufferProxy::GetTransferBuffer(
+    int32 id) {
   if (last_state_.error != gpu::error::kNoError)
-    return gpu::Buffer();
+    return NULL;
 
   // Check local cache to see if there is already a client side shared memory
   // object for this id.
@@ -178,10 +173,10 @@
       ppapi::proxy::SerializedHandle::SHARED_MEMORY);
   if (!Send(new PpapiHostMsg_PPBGraphics3D_GetTransferBuffer(
             ppapi::API_ID_PPB_GRAPHICS_3D, resource_, id, &handle))) {
-    return gpu::Buffer();
+    return NULL;
   }
   if (!handle.is_shmem())
-    return gpu::Buffer();
+    return NULL;
 
   // Cache the transfer buffer shared memory object client side.
   scoped_ptr<base::SharedMemory> shared_memory(
@@ -190,16 +185,13 @@
   // Map the shared memory on demand.
   if (!shared_memory->memory()) {
     if (!shared_memory->Map(handle.size())) {
-      return gpu::Buffer();
+      return NULL;
     }
   }
 
-  gpu::Buffer buffer;
-  buffer.ptr = shared_memory->memory();
-  buffer.size = handle.size();
-  buffer.shared_memory = shared_memory.release();
+  scoped_refptr<gpu::Buffer> buffer =
+      new gpu::Buffer(shared_memory.Pass(), handle.size());
   transfer_buffers_[id] = buffer;
-
   return buffer;
 }
 
diff --git a/ppapi/proxy/ppapi_command_buffer_proxy.h b/ppapi/proxy/ppapi_command_buffer_proxy.h
index c875f89..3116306 100644
--- a/ppapi/proxy/ppapi_command_buffer_proxy.h
+++ b/ppapi/proxy/ppapi_command_buffer_proxy.h
@@ -38,9 +38,10 @@
   virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE;
   virtual void SetGetBuffer(int32 transfer_buffer_id) OVERRIDE;
   virtual void SetGetOffset(int32 get_offset) OVERRIDE;
-  virtual gpu::Buffer CreateTransferBuffer(size_t size, int32* id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
+                                                          int32* id) OVERRIDE;
   virtual void DestroyTransferBuffer(int32 id) OVERRIDE;
-  virtual gpu::Buffer GetTransferBuffer(int32 id) OVERRIDE;
+  virtual scoped_refptr<gpu::Buffer> GetTransferBuffer(int32 id) OVERRIDE;
   virtual void SetToken(int32 token) OVERRIDE;
   virtual void SetParseError(gpu::error::Error error) OVERRIDE;
   virtual void SetContextLostReason(gpu::error::ContextLostReason reason)
@@ -69,7 +70,7 @@
   bool Send(IPC::Message* msg);
   void UpdateState(const gpu::CommandBuffer::State& state, bool success);
 
-  typedef base::hash_map<int32, gpu::Buffer> TransferBufferMap;
+  typedef base::hash_map<int32, scoped_refptr<gpu::Buffer> > TransferBufferMap;
   TransferBufferMap transfer_buffers_;
 
   State last_state_;
diff --git a/ppapi/proxy/ppapi_messages.h b/ppapi/proxy/ppapi_messages.h
index ead5680..4366773 100644
--- a/ppapi/proxy/ppapi_messages.h
+++ b/ppapi/proxy/ppapi_messages.h
@@ -364,6 +364,7 @@
 IPC_STRUCT_TRAITS_BEGIN(ppapi::PpapiNaClPluginArgs)
   IPC_STRUCT_TRAITS_MEMBER(off_the_record)
   IPC_STRUCT_TRAITS_MEMBER(permissions)
+  IPC_STRUCT_TRAITS_MEMBER(keepalive_throttle_interval_milliseconds)
   IPC_STRUCT_TRAITS_MEMBER(switch_names)
   IPC_STRUCT_TRAITS_MEMBER(switch_values)
 IPC_STRUCT_TRAITS_END()
@@ -652,6 +653,9 @@
 IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_SelectFindResultChanged,
                     PP_Instance /* instance */,
                     int32_t /* index */)
+IPC_MESSAGE_ROUTED2(PpapiHostMsg_PPBInstance_SetTickmarks,
+                    PP_Instance /* instance */,
+                    std::vector<PP_Rect> /* tickmarks */)
 
 // PPP_Printing
 IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPPrinting_QuerySupportedFormats,
@@ -731,42 +735,12 @@
                     PP_DecryptorStreamType /* decoder_type */,
                     ppapi::proxy::PPPDecryptor_Buffer /* buffer */,
                     std::string /* serialized_block_info */)
-#endif  // !defined(OS_NACL) && !defined(NACL_WIN64)
 
-#if !defined(OS_NACL) && !defined(NACL_WIN64)
 // PPP_Instance_Private.
 IPC_SYNC_MESSAGE_ROUTED1_1(PpapiMsg_PPPInstancePrivate_GetInstanceObject,
                            PP_Instance /* instance */,
                            ppapi::proxy::SerializedVar /* result */)
 
-// PPB_VideoDecoder_Dev.
-// (Messages from renderer to plugin to notify it to run callbacks.)
-IPC_MESSAGE_ROUTED3(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK,
-                    ppapi::HostResource /* video_decoder */,
-                    int32_t /* bitstream buffer id */,
-                    int32_t /* PP_CompletionCallback result */)
-IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_FlushACK,
-                    ppapi::HostResource /* video_decoder */,
-                    int32_t /* PP_CompletionCallback result  */)
-IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_ResetACK,
-                    ppapi::HostResource /* video_decoder */,
-                    int32_t /* PP_CompletionCallback result */)
-
-// PPP_VideoDecoder_Dev.
-IPC_MESSAGE_ROUTED4(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers,
-                    ppapi::HostResource /* video_decoder */,
-                    uint32_t /* requested number of buffers */,
-                    PP_Size /* dimensions of buffers */,
-                    uint32_t /* texture_target */)
-IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer,
-                    ppapi::HostResource /* video_decoder */,
-                    int32_t /* picture buffer id */)
-IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_PictureReady,
-                    ppapi::HostResource /* video_decoder */,
-                    PP_Picture_Dev /* output picture */)
-IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError,
-                    ppapi::HostResource /* video_decoder */,
-                    PP_VideoDecodeError_Dev /* error */)
 #endif  // !defined(OS_NACL) && !defined(NACL_WIN64)
 
 // Reports to the browser that a plugin has been active.
@@ -1101,7 +1075,8 @@
 
 #if !defined(OS_NACL) && !defined(NACL_WIN64)
 
-// PPB_VideoDecoder.
+// PPB_VideoDecoder_Dev.
+// (Messages from plugin to renderer.)
 IPC_SYNC_MESSAGE_ROUTED3_1(PpapiHostMsg_PPBVideoDecoder_Create,
                            PP_Instance /* instance */,
                            ppapi::HostResource /* context */,
@@ -1125,15 +1100,34 @@
 IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBVideoDecoder_Destroy,
                            ppapi::HostResource /* video_decoder */)
 
-// PPB_Flash_MessageLoop.
-IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Create,
-                           PP_Instance /* instance */,
-                           ppapi::HostResource /* result */)
-IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Run,
-                           ppapi::HostResource /* flash_message_loop */,
-                           int32_t /* result */)
-IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBFlashMessageLoop_Quit,
-                           ppapi::HostResource /* flash_message_loop */)
+// PPB_VideoDecoder_Dev.
+// (Messages from renderer to plugin to notify it to run callbacks.)
+IPC_MESSAGE_ROUTED3(PpapiMsg_PPBVideoDecoder_EndOfBitstreamACK,
+                    ppapi::HostResource /* video_decoder */,
+                    int32_t /* bitstream buffer id */,
+                    int32_t /* PP_CompletionCallback result */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_FlushACK,
+                    ppapi::HostResource /* video_decoder */,
+                    int32_t /* PP_CompletionCallback result  */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPBVideoDecoder_ResetACK,
+                    ppapi::HostResource /* video_decoder */,
+                    int32_t /* PP_CompletionCallback result */)
+
+// PPP_VideoDecoder_Dev.
+IPC_MESSAGE_ROUTED4(PpapiMsg_PPPVideoDecoder_ProvidePictureBuffers,
+                    ppapi::HostResource /* video_decoder */,
+                    uint32_t /* requested number of buffers */,
+                    PP_Size /* dimensions of buffers */,
+                    uint32_t /* texture_target */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_DismissPictureBuffer,
+                    ppapi::HostResource /* video_decoder */,
+                    int32_t /* picture buffer id */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_PictureReady,
+                    ppapi::HostResource /* video_decoder */,
+                    PP_Picture_Dev /* output picture */)
+IPC_MESSAGE_ROUTED2(PpapiMsg_PPPVideoDecoder_NotifyError,
+                    ppapi::HostResource /* video_decoder */,
+                    PP_VideoDecodeError_Dev /* error */)
 #endif  // !defined(OS_NACL) && !defined(NACL_WIN64)
 
 // PPB_X509Certificate_Private
@@ -1277,6 +1271,8 @@
                      std::string /* name */,
                      int32_t /* sample */,
                      int32_t /* boundary_value */)
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_UMA_IsCrashReportingEnabled);
+IPC_MESSAGE_CONTROL0(PpapiPluginMsg_UMA_IsCrashReportingEnabledReply);
 
 // File chooser.
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_FileChooser_Create)
@@ -1393,38 +1389,6 @@
                      int64_t /* amount */,
                      ppapi::FileSizeMap /* file_sizes */)
 
-// Flash DRM ------------------------------------------------------------------
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_Create)
-
-// Requests the device ID.
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetDeviceID)
-// Reply for GetDeviceID which includes the device ID as a string.
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetDeviceIDReply,
-                     std::string /* id */)
-
-// Requests the HMONITOR corresponding to the monitor on which the instance is
-// displayed.
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetHmonitor)
-// Reply message for GetHmonitor which contains the HMONITOR as an int64_t.
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetHmonitorReply,
-                     int64_t /* hmonitor */)
-
-// Requests the voucher file which is used to verify the integrity of the Flash
-// module. A PPB_FileRef resource will be created.
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetVoucherFile)
-// Reply message for GetVoucherFile which contains the CreateInfo for a
-// PPB_FileRef which points to the voucher file.
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetVoucherFileReply,
-                     ppapi::FileRefCreateInfo /* file_info */)
-
-// Requests a value indicating whether the monitor on which the instance is
-// displayed is external.
-IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_MonitorIsExternal)
-// Reply message for MonitorIsExternal which contains the value indicating if
-// the monitor is external.
-IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_MonitorIsExternalReply,
-                     PP_Bool /* is_external */)
-
 // Gamepad.
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_Gamepad_Create)
 
@@ -1968,6 +1932,38 @@
 IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashClipboard_GetSequenceNumberReply,
                      uint64_t /* sequence_number */)
 
+// Flash DRM.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_Create)
+
+// Requests the device ID.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetDeviceID)
+// Reply for GetDeviceID which includes the device ID as a string.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetDeviceIDReply,
+                     std::string /* id */)
+
+// Requests the HMONITOR corresponding to the monitor on which the instance is
+// displayed.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetHmonitor)
+// Reply message for GetHmonitor which contains the HMONITOR as an int64_t.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetHmonitorReply,
+                     int64_t /* hmonitor */)
+
+// Requests the voucher file which is used to verify the integrity of the Flash
+// module. A PPB_FileRef resource will be created.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_GetVoucherFile)
+// Reply message for GetVoucherFile which contains the CreateInfo for a
+// PPB_FileRef which points to the voucher file.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_GetVoucherFileReply,
+                     ppapi::FileRefCreateInfo /* file_info */)
+
+// Requests a value indicating whether the monitor on which the instance is
+// displayed is external.
+IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashDRM_MonitorIsExternal)
+// Reply message for MonitorIsExternal which contains the value indicating if
+// the monitor is external.
+IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashDRM_MonitorIsExternalReply,
+                     PP_Bool /* is_external */)
+
 // Flash file.
 IPC_MESSAGE_CONTROL0(PpapiHostMsg_FlashFile_Create)
 IPC_MESSAGE_CONTROL2(PpapiHostMsg_FlashFile_OpenFile,
@@ -2005,7 +2001,7 @@
 IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashFullscreen_SetFullscreen,
                      bool /* fullscreen */)
 
-// FlashMenu ------------------------------------------------------------------
+// FlashMenu.
 
 // Creates the flash menu with the given data.
 IPC_MESSAGE_CONTROL1(PpapiHostMsg_FlashMenu_Create,
@@ -2020,6 +2016,16 @@
 IPC_MESSAGE_CONTROL1(PpapiPluginMsg_FlashMenu_ShowReply,
                      int32_t /* selected_id */)
 
+// PPB_Flash_MessageLoop.
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Create,
+                           PP_Instance /* instance */,
+                           ppapi::HostResource /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_1(PpapiHostMsg_PPBFlashMessageLoop_Run,
+                           ppapi::HostResource /* flash_message_loop */,
+                           int32_t /* result */)
+IPC_SYNC_MESSAGE_ROUTED1_0(PpapiHostMsg_PPBFlashMessageLoop_Quit,
+                           ppapi::HostResource /* flash_message_loop */)
+
 // PDF ------------------------------------------------------------------------
 
 // Creates the PDF resource.
diff --git a/ppapi/proxy/ppb_instance_proxy.cc b/ppapi/proxy/ppb_instance_proxy.cc
index 3dda61b..257d0d2 100644
--- a/ppapi/proxy/ppb_instance_proxy.cc
+++ b/ppapi/proxy/ppb_instance_proxy.cc
@@ -133,6 +133,8 @@
                         OnHostMsgNumberOfFindResultsChanged)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SelectFindResultChanged,
                         OnHostMsgSelectFindResultChanged)
+    IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetTickmarks,
+                        OnHostMsgSetTickmarks)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_PostMessage,
                         OnHostMsgPostMessage)
     IPC_MESSAGE_HANDLER(PpapiHostMsg_PPBInstance_SetFullscreen,
@@ -335,6 +337,14 @@
       API_ID_PPB_INSTANCE, instance, index));
 }
 
+void PPB_Instance_Proxy::SetTickmarks(PP_Instance instance,
+                                      const PP_Rect* tickmarks,
+                                      uint32_t count) {
+  dispatcher()->Send(new PpapiHostMsg_PPBInstance_SetTickmarks(
+      API_ID_PPB_INSTANCE, instance,
+      std::vector<PP_Rect>(tickmarks, tickmarks + count)));
+}
+
 PP_Bool PPB_Instance_Proxy::IsFullscreen(PP_Instance instance) {
   InstanceData* data = static_cast<PluginDispatcher*>(dispatcher())->
       GetInstanceData(instance);
@@ -944,6 +954,21 @@
     enter.functions()->SelectedFindResultChanged(instance, index);
 }
 
+void PPB_Instance_Proxy::OnHostMsgSetTickmarks(
+    PP_Instance instance,
+    const std::vector<PP_Rect>& tickmarks) {
+  if (!dispatcher()->permissions().HasPermission(PERMISSION_PRIVATE))
+    return;
+  if (tickmarks.empty())
+    return;
+  EnterInstanceNoLock enter(instance);
+  if (enter.succeeded()) {
+    enter.functions()->SetTickmarks(instance,
+                                    &tickmarks[0],
+                                    static_cast<uint32_t>(tickmarks.size()));
+  }
+}
+
 void PPB_Instance_Proxy::OnHostMsgSetFullscreen(PP_Instance instance,
                                                 PP_Bool fullscreen,
                                                 PP_Bool* result) {
diff --git a/ppapi/proxy/ppb_instance_proxy.h b/ppapi/proxy/ppb_instance_proxy.h
index 2304ae6..40bb3f1 100644
--- a/ppapi/proxy/ppb_instance_proxy.h
+++ b/ppapi/proxy/ppb_instance_proxy.h
@@ -64,6 +64,9 @@
                                           PP_Bool final_result) OVERRIDE;
   virtual void SelectedFindResultChanged(PP_Instance instance,
                                          int32_t index) OVERRIDE;
+  virtual void SetTickmarks(PP_Instance instance,
+                            const PP_Rect* tickmarks,
+                            uint32_t count) OVERRIDE;
   virtual PP_Bool IsFullscreen(PP_Instance instance) OVERRIDE;
   virtual PP_Bool SetFullscreen(PP_Instance instance,
                                 PP_Bool fullscreen) OVERRIDE;
@@ -179,6 +182,8 @@
                                            PP_Bool final_result);
   void OnHostMsgSelectFindResultChanged(PP_Instance instance,
                                         int32_t index);
+  void OnHostMsgSetTickmarks(PP_Instance instance,
+                             const std::vector<PP_Rect>& tickmarks);
   void OnHostMsgSetFullscreen(PP_Instance instance,
                               PP_Bool fullscreen,
                               PP_Bool* result);
diff --git a/ppapi/proxy/ppp_find_proxy.cc b/ppapi/proxy/ppp_find_proxy.cc
index 0547e61..abd5663 100644
--- a/ppapi/proxy/ppp_find_proxy.cc
+++ b/ppapi/proxy/ppp_find_proxy.cc
@@ -20,7 +20,7 @@
                   PP_Bool case_sensitive) {
   DCHECK(case_sensitive == PP_FALSE);
   HostDispatcher::GetForInstance(instance)->Send(
-      new PpapiPluginMsg_PPPFind_StartFind(API_ID_PPP_FIND_DEV,
+      new PpapiPluginMsg_PPPFind_StartFind(API_ID_PPP_FIND_PRIVATE,
                                            instance,
                                            text));
   return PP_TRUE;
@@ -29,23 +29,23 @@
 void SelectFindResult(PP_Instance instance,
                       PP_Bool forward) {
   HostDispatcher::GetForInstance(instance)->Send(
-      new PpapiPluginMsg_PPPFind_SelectFindResult(API_ID_PPP_FIND_DEV,
+      new PpapiPluginMsg_PPPFind_SelectFindResult(API_ID_PPP_FIND_PRIVATE,
                                                   instance, forward));
 }
 
 void StopFind(PP_Instance instance) {
   HostDispatcher::GetForInstance(instance)->Send(
-      new PpapiPluginMsg_PPPFind_StopFind(API_ID_PPP_FIND_DEV, instance));
+      new PpapiPluginMsg_PPPFind_StopFind(API_ID_PPP_FIND_PRIVATE, instance));
 }
 
-const PPP_Find_Dev ppp_find_interface = {
+const PPP_Find_Private ppp_find_interface = {
   &StartFind,
   &SelectFindResult,
   &StopFind
 };
 #else
 // The NaCl plugin doesn't need the host side interface - stub it out.
-const PPP_Find_Dev ppp_find_interface = {};
+const PPP_Find_Private ppp_find_interface = {};
 #endif
 
 }  // namespace
@@ -54,8 +54,8 @@
     : InterfaceProxy(dispatcher),
       ppp_find_(NULL) {
   if (dispatcher->IsPlugin()) {
-    ppp_find_ = static_cast<const PPP_Find_Dev*>(
-        dispatcher->local_get_interface()(PPP_FIND_DEV_INTERFACE));
+    ppp_find_ = static_cast<const PPP_Find_Private*>(
+        dispatcher->local_get_interface()(PPP_FIND_PRIVATE_INTERFACE));
   }
 }
 
@@ -63,7 +63,7 @@
 }
 
 // static
-const PPP_Find_Dev* PPP_Find_Proxy::GetProxyInterface() {
+const PPP_Find_Private* PPP_Find_Proxy::GetProxyInterface() {
   return &ppp_find_interface;
 }
 
diff --git a/ppapi/proxy/ppp_find_proxy.h b/ppapi/proxy/ppp_find_proxy.h
index fa0961e..6d22304 100644
--- a/ppapi/proxy/ppp_find_proxy.h
+++ b/ppapi/proxy/ppp_find_proxy.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "ppapi/c/dev/ppp_find_dev.h"
+#include "ppapi/c/private/ppp_find_private.h"
 #include "ppapi/proxy/interface_proxy.h"
 
 namespace ppapi {
@@ -19,7 +19,7 @@
   explicit PPP_Find_Proxy(Dispatcher* dispatcher);
   virtual ~PPP_Find_Proxy();
 
-  static const PPP_Find_Dev* GetProxyInterface();
+  static const PPP_Find_Private* GetProxyInterface();
 
   // InterfaceProxy implementation.
   virtual bool OnMessageReceived(const IPC::Message& msg);
@@ -35,7 +35,7 @@
   // When this proxy is in the plugin side, this value caches the interface
   // pointer so we don't have to retrieve it from the dispatcher each time.
   // In the host, this value is always NULL.
-  const PPP_Find_Dev* ppp_find_;
+  const PPP_Find_Private* ppp_find_;
 
   DISALLOW_COPY_AND_ASSIGN(PPP_Find_Proxy);
 };
diff --git a/ppapi/proxy/raw_var_data_unittest.cc b/ppapi/proxy/raw_var_data_unittest.cc
index 0340892..e1c56a3 100644
--- a/ppapi/proxy/raw_var_data_unittest.cc
+++ b/ppapi/proxy/raw_var_data_unittest.cc
@@ -72,7 +72,7 @@
   if (!success)
     return false;
   ScopedPPVar actual(ScopedPPVar::PassRef(), result);
-  return TestEqual(expected.get(), actual.get());
+  return TestEqual(expected.get(), actual.get(), true);
 }
 
 }  // namespace
diff --git a/ppapi/proxy/uma_private_resource.cc b/ppapi/proxy/uma_private_resource.cc
index d17a005..2932e6c 100644
--- a/ppapi/proxy/uma_private_resource.cc
+++ b/ppapi/proxy/uma_private_resource.cc
@@ -84,6 +84,27 @@
                                                        boundary_value));
 }
 
+int32_t UMAPrivateResource::IsCrashReportingEnabled(
+    PP_Instance instance,
+    scoped_refptr<TrackedCallback> callback) {
+  if (pending_callback_ != NULL)
+    return PP_ERROR_INPROGRESS;
+  pending_callback_ = callback;
+  Call<PpapiPluginMsg_UMA_IsCrashReportingEnabledReply>(
+      RENDERER,
+      PpapiHostMsg_UMA_IsCrashReportingEnabled(),
+      base::Bind(&UMAPrivateResource::OnPluginMsgIsCrashReportingEnabled,
+          this));
+  return PP_OK_COMPLETIONPENDING;
+}
+
+void UMAPrivateResource::OnPluginMsgIsCrashReportingEnabled(
+    const ResourceMessageReplyParams& params) {
+  if (TrackedCallback::IsPending(pending_callback_))
+    pending_callback_->Run(params.result());
+  pending_callback_ = NULL;
+}
+
 }  // namespace proxy
 }  // namespace ppapi
 
diff --git a/ppapi/proxy/uma_private_resource.h b/ppapi/proxy/uma_private_resource.h
index 94c7d3c..93328e8 100644
--- a/ppapi/proxy/uma_private_resource.h
+++ b/ppapi/proxy/uma_private_resource.h
@@ -44,7 +44,15 @@
                                     int32_t sample,
                                     int32_t boundary_value) OVERRIDE;
 
+  virtual int32_t IsCrashReportingEnabled(
+      PP_Instance instance,
+      scoped_refptr<TrackedCallback> callback) OVERRIDE;
+
  private:
+  void OnPluginMsgIsCrashReportingEnabled(
+      const ResourceMessageReplyParams& params);
+  scoped_refptr<TrackedCallback> pending_callback_;
+
   DISALLOW_COPY_AND_ASSIGN(UMAPrivateResource);
 };
 
diff --git a/ppapi/shared_impl/api_id.h b/ppapi/shared_impl/api_id.h
index 2f18a85..a049948 100644
--- a/ppapi/shared_impl/api_id.h
+++ b/ppapi/shared_impl/api_id.h
@@ -50,7 +50,7 @@
   // TODO(tomfinegan): Remove this after we refactor things to load the PPP
   // interface struct from the PPB interface.
   API_ID_PPP_CONTENT_DECRYPTOR_PRIVATE,
-  API_ID_PPP_FIND_DEV,
+  API_ID_PPP_FIND_PRIVATE,
   API_ID_PPP_GRAPHICS_3D,
   API_ID_PPP_INPUT_EVENT,
   API_ID_PPP_INSTANCE,
diff --git a/ppapi/shared_impl/ppapi_constants.h b/ppapi/shared_impl/ppapi_constants.h
new file mode 100644
index 0000000..dcc9b29
--- /dev/null
+++ b/ppapi/shared_impl/ppapi_constants.h
@@ -0,0 +1,19 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PPAPI_SHARED_IMPL_PPAPI_CONSTANTS_H_
+#define PPAPI_SHARED_IMPL_PPAPI_CONSTANTS_H_
+
+#include "ppapi/shared_impl/ppapi_shared_export.h"
+
+namespace ppapi {
+
+// Default interval to space out IPC messages sent indicating that a plugin is
+// active and should be kept alive. The value must be smaller than any threshold
+// used to kill inactive plugins by the embedder host.
+const unsigned kKeepaliveThrottleIntervalDefaultMilliseconds = 5000;
+
+}  // namespace ppapi
+
+#endif  // PPAPI_SHARED_IMPL_PPAPI_CONSTANTS_H_
diff --git a/ppapi/shared_impl/ppapi_nacl_plugin_args.cc b/ppapi/shared_impl/ppapi_nacl_plugin_args.cc
index 92df690..4dd5110 100644
--- a/ppapi/shared_impl/ppapi_nacl_plugin_args.cc
+++ b/ppapi/shared_impl/ppapi_nacl_plugin_args.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "ppapi/shared_impl/ppapi_constants.h"
 #include "ppapi/shared_impl/ppapi_nacl_plugin_args.h"
 
 namespace ppapi {
@@ -9,7 +10,10 @@
 // We must provide explicit definitions of these functions for builds on
 // Windows.
 PpapiNaClPluginArgs::PpapiNaClPluginArgs()
-    : off_the_record(false), supports_dev_channel(false) {}
+    : off_the_record(false),
+      supports_dev_channel(false),
+      keepalive_throttle_interval_milliseconds(
+          kKeepaliveThrottleIntervalDefaultMilliseconds) {}
 
 PpapiNaClPluginArgs::~PpapiNaClPluginArgs() {}
 
diff --git a/ppapi/shared_impl/ppapi_nacl_plugin_args.h b/ppapi/shared_impl/ppapi_nacl_plugin_args.h
index 2f18c8e..993131d 100644
--- a/ppapi/shared_impl/ppapi_nacl_plugin_args.h
+++ b/ppapi/shared_impl/ppapi_nacl_plugin_args.h
@@ -20,6 +20,7 @@
   bool off_the_record;
   PpapiPermissions permissions;
   bool supports_dev_channel;
+  unsigned keepalive_throttle_interval_milliseconds;
 
   // Switches from the command-line.
   std::vector<std::string> switch_names;
diff --git a/ppapi/shared_impl/ppapi_switches.cc b/ppapi/shared_impl/ppapi_switches.cc
index 2a3f1c2..84ba250 100644
--- a/ppapi/shared_impl/ppapi_switches.cc
+++ b/ppapi/shared_impl/ppapi_switches.cc
@@ -9,7 +9,4 @@
 // Enables the testing interface for PPAPI.
 const char kEnablePepperTesting[] = "enable-pepper-testing";
 
-// Specifies throttling time in milliseconds for PpapiHostMsg_Keepalive IPCs.
-const char kPpapiKeepAliveThrottle[] = "ppapi-keep-alive-throttle";
-
 }  // namespace switches
diff --git a/ppapi/shared_impl/ppapi_switches.h b/ppapi/shared_impl/ppapi_switches.h
index 4fb9c34..a5c8e9d 100644
--- a/ppapi/shared_impl/ppapi_switches.h
+++ b/ppapi/shared_impl/ppapi_switches.h
@@ -10,7 +10,6 @@
 namespace switches {
 
 PPAPI_SHARED_EXPORT extern const char kEnablePepperTesting[];
-PPAPI_SHARED_EXPORT extern const char kPpapiKeepAliveThrottle[];
 
 }  // namespace switches
 
diff --git a/ppapi/shared_impl/unittest_utils.cc b/ppapi/shared_impl/unittest_utils.cc
index a52db34..af90432 100644
--- a/ppapi/shared_impl/unittest_utils.cc
+++ b/ppapi/shared_impl/unittest_utils.cc
@@ -25,6 +25,7 @@
 // nodes in |actual| and check whether the graphs have equivalent topology.
 bool Equals(const PP_Var& expected,
             const PP_Var& actual,
+            bool test_string_references,
             base::hash_map<int64_t, int64_t>* visited_map) {
   if (expected.type != actual.type) {
     LOG(ERROR) << "expected type: " << expected.type
@@ -43,7 +44,8 @@
         return true;
       }
     } else {
-      (*visited_map)[expected.value.as_id] = actual.value.as_id;
+      if (expected.type != PP_VARTYPE_STRING || test_string_references)
+        (*visited_map)[expected.value.as_id] = actual.value.as_id;
     }
   }
   switch (expected.type) {
@@ -119,6 +121,7 @@
       for (size_t i = 0; i < expected_var->elements().size(); ++i) {
         if (!Equals(expected_var->elements()[i].get(),
                     actual_var->elements()[i].get(),
+                    test_string_references,
                     visited_map)) {
           return false;
         }
@@ -148,6 +151,7 @@
         }
         if (!Equals(expected_iter->second.get(),
                     actual_iter->second.get(),
+                    test_string_references,
                     visited_map)) {
           return false;
         }
@@ -198,9 +202,11 @@
 
 }  // namespace
 
-bool TestEqual(const PP_Var& expected, const PP_Var& actual) {
+bool TestEqual(const PP_Var& expected,
+               const PP_Var& actual,
+               bool test_string_references) {
   base::hash_map<int64_t, int64_t> visited_map;
-  return Equals(expected, actual, &visited_map);
+  return Equals(expected, actual, test_string_references, &visited_map);
 }
 
 }  // namespace ppapi
diff --git a/ppapi/shared_impl/unittest_utils.h b/ppapi/shared_impl/unittest_utils.h
index e07d8a8..a6fb296 100644
--- a/ppapi/shared_impl/unittest_utils.h
+++ b/ppapi/shared_impl/unittest_utils.h
@@ -12,7 +12,12 @@
 // Compares two vars for equality. This is a deep comparison (the entire graph
 // is traversed recursively). The function guarantees that the topology of the
 // two PP_Var graphs being compared is identical, including graphs with cycles.
-bool TestEqual(const PP_Var& expected, const PP_Var& actual);
+// If |test_string_references| is set to true, then incoming references to
+// string vars in the two graphs must be isomorphic. Otherwise only the content
+// of the strings is tested for equality.
+bool TestEqual(const PP_Var& expected,
+               const PP_Var& actual,
+               bool test_string_references);
 
 }  // namespace ppapi
 
diff --git a/ppapi/tests/all_c_includes.h b/ppapi/tests/all_c_includes.h
index ddaa8a8..b74675c 100644
--- a/ppapi/tests/all_c_includes.h
+++ b/ppapi/tests/all_c_includes.h
@@ -19,7 +19,6 @@
 #include "ppapi/c/dev/ppb_cursor_control_dev.h"
 #include "ppapi/c/dev/ppb_device_ref_dev.h"
 #include "ppapi/c/dev/ppb_file_chooser_dev.h"
-#include "ppapi/c/dev/ppb_find_dev.h"
 #include "ppapi/c/dev/ppb_font_dev.h"
 #include "ppapi/c/dev/ppb_graphics_2d_dev.h"
 #include "ppapi/c/dev/ppb_ime_input_event_dev.h"
@@ -36,7 +35,6 @@
 #include "ppapi/c/dev/ppb_widget_dev.h"
 #include "ppapi/c/dev/ppb_zoom_dev.h"
 #include "ppapi/c/dev/ppp_class_deprecated.h"
-#include "ppapi/c/dev/ppp_find_dev.h"
 #include "ppapi/c/dev/ppp_printing_dev.h"
 #include "ppapi/c/dev/ppp_scrollbar_dev.h"
 #include "ppapi/c/dev/ppp_selection_dev.h"
@@ -112,6 +110,7 @@
 #include "ppapi/c/private/ppb_display_color_profile_private.h"
 #include "ppapi/c/private/ppb_ext_crx_file_system_private.h"
 #include "ppapi/c/private/ppb_file_io_private.h"
+#include "ppapi/c/private/ppb_find_private.h"
 #include "ppapi/c/private/ppb_flash.h"
 #include "ppapi/c/private/ppb_flash_clipboard.h"
 #include "ppapi/c/private/ppb_flash_font_file.h"
@@ -133,6 +132,7 @@
 #include "ppapi/c/private/ppb_video_source_private.h"
 #include "ppapi/c/private/ppb_x509_certificate_private.h"
 #include "ppapi/c/private/ppp_content_decryptor_private.h"
+#include "ppapi/c/private/ppp_find_private.h"
 #include "ppapi/c/private/ppp_instance_private.h"
 #include "ppapi/c/trusted/ppb_url_loader_trusted.h"
 
diff --git a/ppapi/tests/all_cpp_includes.h b/ppapi/tests/all_cpp_includes.h
index aa66777..dcb907c 100644
--- a/ppapi/tests/all_cpp_includes.h
+++ b/ppapi/tests/all_cpp_includes.h
@@ -18,7 +18,6 @@
 #include "ppapi/cpp/dev/buffer_dev.h"
 #include "ppapi/cpp/dev/device_ref_dev.h"
 #include "ppapi/cpp/dev/file_chooser_dev.h"
-#include "ppapi/cpp/dev/find_dev.h"
 #include "ppapi/cpp/dev/font_dev.h"
 #include "ppapi/cpp/dev/graphics_2d_dev.h"
 #include "ppapi/cpp/dev/ime_input_event_dev.h"
@@ -61,6 +60,7 @@
 #include "ppapi/cpp/network_proxy.h"
 #include "ppapi/cpp/point.h"
 #include "ppapi/cpp/private/content_decryptor_private.h"
+#include "ppapi/cpp/private/find_private.h"
 #include "ppapi/cpp/private/flash_font_file.h"
 #include "ppapi/cpp/private/flash_fullscreen.h"
 #include "ppapi/cpp/private/instance_private.h"
diff --git a/ppapi/tests/arch_dependent_sizes_64.h b/ppapi/tests/arch_dependent_sizes_64.h
index 2ac1740..bd30300 100644
--- a/ppapi/tests/arch_dependent_sizes_64.h
+++ b/ppapi/tests/arch_dependent_sizes_64.h
@@ -11,11 +11,8 @@
 
 #include "ppapi/tests/test_struct_sizes.c"
 
-// TODO(jschuh): Resolve ILP64 to LLP64 issue. crbug.com/177779
-#if !defined(_WIN64)
 PP_COMPILE_ASSERT_SIZE_IN_BYTES(GLintptr, 8);
 PP_COMPILE_ASSERT_SIZE_IN_BYTES(GLsizeiptr, 8);
-#endif
 PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_CompletionCallback_Func, 8);
 PP_COMPILE_ASSERT_SIZE_IN_BYTES(PP_URLLoaderTrusted_StatusCallback, 8);
 PP_COMPILE_ASSERT_STRUCT_SIZE_IN_BYTES(PP_CompletionCallback, 24);
diff --git a/ppapi/tests/test_post_message.cc b/ppapi/tests/test_post_message.cc
index a44eba0..f51cf4e 100644
--- a/ppapi/tests/test_post_message.cc
+++ b/ppapi/tests/test_post_message.cc
@@ -83,7 +83,13 @@
         return true;
       return false;
     }
-    (*visited_ids)[expected.pp_var().value.as_id] = actual.pp_var().value.as_id;
+    // Round-tripping reference graphs with strings will not necessarily
+    // result in isomorphic graphs. This is because string vars are converted
+    // to string primitives in JS which cannot be referenced.
+    if (!expected.is_string()) {
+      (*visited_ids)[expected.pp_var().value.as_id] =
+          actual.pp_var().value.as_id;
+    }
   }
 
   if (expected.is_number()) {
@@ -203,6 +209,7 @@
   // that was sent in Init above.
   RUN_TEST(SendInInit, filter);
   RUN_TEST(SendingData, filter);
+  RUN_TEST(SendingString, filter);
   RUN_TEST(SendingArrayBuffer, filter);
   RUN_TEST(SendingArray, filter);
   RUN_TEST(SendingDictionary, filter);
@@ -319,21 +326,14 @@
   // should start with these.
   WaitForMessages();
   ASSERT_TRUE(ClearListeners());
+
   // Set up the JavaScript message event listener to echo the data part of the
   // message event back to us.
   ASSERT_TRUE(AddEchoingListener("message_event.data"));
 
-  // Test sending a message to JavaScript for each supported type.  The JS sends
+  // Test sending a message to JavaScript for each supported type. The JS sends
   // the data back to us, and we check that they match.
   message_data_.clear();
-  instance_->PostMessage(pp::Var(kTestString));
-  // PostMessage is asynchronous, so we should not receive a response yet.
-  ASSERT_EQ(0, message_data_.size());
-  ASSERT_EQ(1, WaitForMessages());
-  ASSERT_TRUE(message_data_.back().is_string());
-  ASSERT_EQ(message_data_.back().AsString(), kTestString);
-
-  message_data_.clear();
   instance_->PostMessage(pp::Var(kTestBool));
   ASSERT_EQ(0, message_data_.size());
   ASSERT_EQ(1, WaitForMessages());
@@ -373,6 +373,36 @@
   PASS();
 }
 
+std::string TestPostMessage::TestSendingString() {
+  // Clean up after previous tests. This also swallows the message sent by Init
+  // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
+  // should start with these.
+  WaitForMessages();
+  ASSERT_TRUE(ClearListeners());
+
+  // Test that a string var is converted to a primitive JS string.
+  message_data_.clear();
+  std::vector<std::string> properties_to_check;
+  properties_to_check.push_back(
+      "typeof message_event.data === 'string'");
+  ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(kTestString,
+                                                properties_to_check));
+
+  ASSERT_TRUE(AddEchoingListener("message_event.data"));
+  message_data_.clear();
+  instance_->PostMessage(pp::Var(kTestString));
+  // PostMessage is asynchronous, so we should not receive a response yet.
+  ASSERT_EQ(0, message_data_.size());
+  ASSERT_EQ(1, WaitForMessages());
+  ASSERT_TRUE(message_data_.back().is_string());
+  ASSERT_EQ(message_data_.back().AsString(), kTestString);
+
+  message_data_.clear();
+  ASSERT_TRUE(ClearListeners());
+
+  PASS();
+}
+
 std::string TestPostMessage::TestSendingArrayBuffer() {
   // Clean up after previous tests. This also swallows the message sent by Init
   // if we didn't run the 'SendInInit' test. All tests other than 'SendInInit'
@@ -476,6 +506,9 @@
       "message_event.data.constructor.name === 'Array'");
   properties_to_check.push_back(
       std::string("message_event.data.length === ") + length_as_string);
+  // Check that the string is converted to a primitive JS string.
+  properties_to_check.push_back(
+      std::string("typeof message_event.data[1] === 'string'"));
   ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(array, properties_to_check));
 
   // Set up the JavaScript message event listener to echo the data part of the
@@ -519,6 +552,9 @@
   properties_to_check.push_back(
       std::string("Object.keys(message_event.data).length === ") +
       length_as_string);
+  // Check that the string is converted to a primitive JS string.
+  properties_to_check.push_back(
+      std::string("typeof message_event.data['bar'] === 'string'"));
   ASSERT_SUBTEST_SUCCESS(CheckMessageProperties(dictionary,
                                                 properties_to_check));
 
diff --git a/ppapi/tests/test_post_message.h b/ppapi/tests/test_post_message.h
index 7332bac..3fa8595 100644
--- a/ppapi/tests/test_post_message.h
+++ b/ppapi/tests/test_post_message.h
@@ -69,6 +69,9 @@
   // in both directions.
   std::string TestSendingData();
 
+  // Test sending string vars in both directions.
+  std::string TestSendingString();
+
   // Test sending ArrayBuffer vars in both directions.
   std::string TestSendingArrayBuffer();
 
diff --git a/ppapi/thunk/interfaces_ppb_private_no_permissions.h b/ppapi/thunk/interfaces_ppb_private_no_permissions.h
index 83e8243..6c224fe 100644
--- a/ppapi/thunk/interfaces_ppb_private_no_permissions.h
+++ b/ppapi/thunk/interfaces_ppb_private_no_permissions.h
@@ -48,7 +48,7 @@
 PROXIED_IFACE(PPB_VIDEOSOURCE_PRIVATE_INTERFACE_0_1,
               PPB_VideoSource_Private_0_1)
 
-PROXIED_IFACE(PPB_UMA_PRIVATE_INTERFACE_0_2,
-              PPB_UMA_Private_0_2)
+PROXIED_IFACE(PPB_UMA_PRIVATE_INTERFACE_0_3,
+              PPB_UMA_Private_0_3)
 
 #include "ppapi/thunk/interfaces_postamble.h"
diff --git a/ppapi/thunk/interfaces_ppb_public_dev.h b/ppapi/thunk/interfaces_ppb_public_dev.h
index cbff2d4..39855b9 100644
--- a/ppapi/thunk/interfaces_ppb_public_dev.h
+++ b/ppapi/thunk/interfaces_ppb_public_dev.h
@@ -16,7 +16,6 @@
 PROXIED_IFACE(PPB_EXT_SOCKET_DEV_INTERFACE_0_2, PPB_Ext_Socket_Dev_0_2)
 PROXIED_IFACE(PPB_FILECHOOSER_DEV_INTERFACE_0_5, PPB_FileChooser_Dev_0_5)
 PROXIED_IFACE(PPB_FILECHOOSER_DEV_INTERFACE_0_6, PPB_FileChooser_Dev_0_6)
-PROXIED_IFACE(PPB_FIND_DEV_INTERFACE_0_3, PPB_Find_Dev_0_3)
 PROXIED_IFACE(PPB_IME_INPUT_EVENT_DEV_INTERFACE_0_2, PPB_IMEInputEvent_Dev_0_2)
 PROXIED_IFACE(PPB_MEMORY_DEV_INTERFACE_0_1, PPB_Memory_Dev_0_1)
 PROXIED_IFACE(PPB_PRINTING_DEV_INTERFACE_0_7, PPB_Printing_Dev_0_7)
diff --git a/ppapi/thunk/interfaces_ppb_public_dev_channel.h b/ppapi/thunk/interfaces_ppb_public_dev_channel.h
index 97a2fe8..c2b6448 100644
--- a/ppapi/thunk/interfaces_ppb_public_dev_channel.h
+++ b/ppapi/thunk/interfaces_ppb_public_dev_channel.h
@@ -8,12 +8,6 @@
 #include "ppapi/thunk/interfaces_preamble.h"
 
 // Interfaces go here.
-PROXIED_IFACE(PPB_AUDIOBUFFER_INTERFACE_0_1, PPB_AudioBuffer_0_1)
 PROXIED_IFACE(PPB_FILEMAPPING_INTERFACE_0_1, PPB_FileMapping_0_1)
-PROXIED_IFACE(PPB_MEDIASTREAMAUDIOTRACK_INTERFACE_0_1,
-              PPB_MediaStreamAudioTrack_0_1)
-PROXIED_IFACE(PPB_MEDIASTREAMVIDEOTRACK_INTERFACE_0_1,
-              PPB_MediaStreamVideoTrack_0_1)
-PROXIED_IFACE(PPB_VIDEOFRAME_INTERFACE_0_1, PPB_VideoFrame_0_1)
 
 #include "ppapi/thunk/interfaces_postamble.h"
diff --git a/ppapi/thunk/interfaces_ppb_public_stable.h b/ppapi/thunk/interfaces_ppb_public_stable.h
index 722344b..d0eb2c7 100644
--- a/ppapi/thunk/interfaces_ppb_public_stable.h
+++ b/ppapi/thunk/interfaces_ppb_public_stable.h
@@ -30,7 +30,7 @@
 
 // Interfaces
 // ----------
-// Enumerates interfaces as (api_name, interface_name, interface_struct).
+// Enumerates interfaces as (interface_name, interface_struct).
 //
 // The api_name corresponds to the class in the list above for the object
 // that implements the API. Some things may be special and aren't implemented
@@ -46,6 +46,7 @@
 // Note: Core is special and is registered manually.
 PROXIED_IFACE(PPB_AUDIO_INTERFACE_1_0, PPB_Audio_1_0)
 PROXIED_IFACE(PPB_AUDIO_INTERFACE_1_1, PPB_Audio_1_1)
+PROXIED_IFACE(PPB_AUDIOBUFFER_INTERFACE_0_1, PPB_AudioBuffer_0_1)
 PROXIED_IFACE(PPB_FILEREF_INTERFACE_1_0, PPB_FileRef_1_0)
 PROXIED_IFACE(PPB_FILEREF_INTERFACE_1_1, PPB_FileRef_1_1)
 PROXIED_IFACE(PPB_FILEREF_INTERFACE_1_2, PPB_FileRef_1_2)
@@ -71,6 +72,10 @@
 PROXIED_IFACE(PPB_WHEEL_INPUT_EVENT_INTERFACE_1_0, PPB_WheelInputEvent_1_0)
 PROXIED_IFACE(PPB_TOUCH_INPUT_EVENT_INTERFACE_1_0, PPB_TouchInputEvent_1_0)
 PROXIED_IFACE(PPB_FULLSCREEN_INTERFACE_1_0, PPB_Fullscreen_1_0)
+PROXIED_IFACE(PPB_MEDIASTREAMAUDIOTRACK_INTERFACE_0_1,
+              PPB_MediaStreamAudioTrack_0_1)
+PROXIED_IFACE(PPB_MEDIASTREAMVIDEOTRACK_INTERFACE_0_1,
+              PPB_MediaStreamVideoTrack_0_1)
 PROXIED_IFACE(PPB_MESSAGING_INTERFACE_1_0, PPB_Messaging_1_0)
 PROXIED_IFACE(PPB_MOUSECURSOR_INTERFACE_1_0, PPB_MouseCursor_1_0)
 PROXIED_IFACE(PPB_MOUSELOCK_INTERFACE_1_0, PPB_MouseLock_1_0)
@@ -88,6 +93,7 @@
 PROXIED_IFACE(PPB_URLRESPONSEINFO_INTERFACE_1_0, PPB_URLResponseInfo_1_0)
 PROXIED_IFACE(PPB_VAR_ARRAY_INTERFACE_1_0, PPB_VarArray_1_0)
 PROXIED_IFACE(PPB_VAR_DICTIONARY_INTERFACE_1_0, PPB_VarDictionary_1_0)
+PROXIED_IFACE(PPB_VIDEOFRAME_INTERFACE_0_1, PPB_VideoFrame_0_1)
 PROXIED_IFACE(PPB_WEBSOCKET_INTERFACE_1_0, PPB_WebSocket_1_0)
 
 // Note: PPB_Var and PPB_VarArrayBuffer are special and registered manually.
diff --git a/ppapi/thunk/ppb_find_dev_thunk.cc b/ppapi/thunk/ppb_find_dev_thunk.cc
deleted file mode 100644
index 91224f9..0000000
--- a/ppapi/thunk/ppb_find_dev_thunk.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// From dev/ppb_find_dev.idl modified Thu Mar 13 11:05:53 2014.
-
-#include "ppapi/c/dev/ppb_find_dev.h"
-#include "ppapi/c/pp_errors.h"
-#include "ppapi/shared_impl/tracked_callback.h"
-#include "ppapi/thunk/enter.h"
-#include "ppapi/thunk/ppapi_thunk_export.h"
-
-namespace ppapi {
-namespace thunk {
-
-namespace {
-
-void SetPluginToHandleFindRequests(PP_Instance instance) {
-  VLOG(4) << "PPB_Find_Dev::SetPluginToHandleFindRequests()";
-  EnterInstance enter(instance);
-  if (enter.failed())
-    return;
-  enter.functions()->SetPluginToHandleFindRequests(instance);
-}
-
-void NumberOfFindResultsChanged(PP_Instance instance,
-                                int32_t total,
-                                PP_Bool final_result) {
-  VLOG(4) << "PPB_Find_Dev::NumberOfFindResultsChanged()";
-  EnterInstance enter(instance);
-  if (enter.failed())
-    return;
-  enter.functions()->NumberOfFindResultsChanged(instance, total, final_result);
-}
-
-void SelectedFindResultChanged(PP_Instance instance, int32_t index) {
-  VLOG(4) << "PPB_Find_Dev::SelectedFindResultChanged()";
-  EnterInstance enter(instance);
-  if (enter.failed())
-    return;
-  enter.functions()->SelectedFindResultChanged(instance, index);
-}
-
-const PPB_Find_Dev_0_3 g_ppb_find_dev_thunk_0_3 = {
-  &SetPluginToHandleFindRequests,
-  &NumberOfFindResultsChanged,
-  &SelectedFindResultChanged
-};
-
-}  // namespace
-
-PPAPI_THUNK_EXPORT const PPB_Find_Dev_0_3* GetPPB_Find_Dev_0_3_Thunk() {
-  return &g_ppb_find_dev_thunk_0_3;
-}
-
-}  // namespace thunk
-}  // namespace ppapi
diff --git a/ppapi/thunk/ppb_find_private_thunk.cc b/ppapi/thunk/ppb_find_private_thunk.cc
new file mode 100644
index 0000000..ffa50af
--- /dev/null
+++ b/ppapi/thunk/ppb_find_private_thunk.cc
@@ -0,0 +1,69 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// From private/ppb_find_private.idl modified Wed Mar 19 13:42:13 2014.
+
+#include "ppapi/c/pp_errors.h"
+#include "ppapi/c/private/ppb_find_private.h"
+#include "ppapi/shared_impl/tracked_callback.h"
+#include "ppapi/thunk/enter.h"
+#include "ppapi/thunk/ppapi_thunk_export.h"
+
+namespace ppapi {
+namespace thunk {
+
+namespace {
+
+void SetPluginToHandleFindRequests(PP_Instance instance) {
+  VLOG(4) << "PPB_Find_Private::SetPluginToHandleFindRequests()";
+  EnterInstance enter(instance);
+  if (enter.failed())
+    return;
+  enter.functions()->SetPluginToHandleFindRequests(instance);
+}
+
+void NumberOfFindResultsChanged(PP_Instance instance,
+                                int32_t total,
+                                PP_Bool final_result) {
+  VLOG(4) << "PPB_Find_Private::NumberOfFindResultsChanged()";
+  EnterInstance enter(instance);
+  if (enter.failed())
+    return;
+  enter.functions()->NumberOfFindResultsChanged(instance, total, final_result);
+}
+
+void SelectedFindResultChanged(PP_Instance instance, int32_t index) {
+  VLOG(4) << "PPB_Find_Private::SelectedFindResultChanged()";
+  EnterInstance enter(instance);
+  if (enter.failed())
+    return;
+  enter.functions()->SelectedFindResultChanged(instance, index);
+}
+
+void SetTickmarks(PP_Instance instance,
+                  const struct PP_Rect tickmarks[],
+                  uint32_t count) {
+  VLOG(4) << "PPB_Find_Private::SetTickmarks()";
+  EnterInstance enter(instance);
+  if (enter.failed())
+    return;
+  enter.functions()->SetTickmarks(instance, tickmarks, count);
+}
+
+const PPB_Find_Private_0_3 g_ppb_find_private_thunk_0_3 = {
+  &SetPluginToHandleFindRequests,
+  &NumberOfFindResultsChanged,
+  &SelectedFindResultChanged,
+  &SetTickmarks
+};
+
+}  // namespace
+
+PPAPI_THUNK_EXPORT const PPB_Find_Private_0_3*
+    GetPPB_Find_Private_0_3_Thunk() {
+  return &g_ppb_find_private_thunk_0_3;
+}
+
+}  // namespace thunk
+}  // namespace ppapi
diff --git a/ppapi/thunk/ppb_instance_api.h b/ppapi/thunk/ppb_instance_api.h
index 377b3a8..23bf18c 100644
--- a/ppapi/thunk/ppb_instance_api.h
+++ b/ppapi/thunk/ppb_instance_api.h
@@ -84,6 +84,9 @@
                                           PP_Bool final_result) = 0;
   virtual void SelectedFindResultChanged(PP_Instance instance,
                                          int32_t index) = 0;
+  virtual void SetTickmarks(PP_Instance instance,
+                            const PP_Rect* tickmarks,
+                            uint32_t count) = 0;
 
   // Fullscreen.
   virtual PP_Bool IsFullscreen(PP_Instance instance) = 0;
diff --git a/ppapi/thunk/ppb_media_stream_video_track_thunk.cc b/ppapi/thunk/ppb_media_stream_video_track_thunk.cc
index d55ed38..c39ee1c 100644
--- a/ppapi/thunk/ppb_media_stream_video_track_thunk.cc
+++ b/ppapi/thunk/ppb_media_stream_video_track_thunk.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From ppb_media_stream_video_track.idl modified Thu Jan 23 08:56:57 2014.
+// From ppb_media_stream_video_track.idl modified Tue Mar 25 18:18:10 2014.
 
 #include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/pp_errors.h"
diff --git a/ppapi/thunk/ppb_uma_private_thunk.cc b/ppapi/thunk/ppb_uma_private_thunk.cc
index 1171d19..299b643 100644
--- a/ppapi/thunk/ppb_uma_private_thunk.cc
+++ b/ppapi/thunk/ppb_uma_private_thunk.cc
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// From private/ppb_uma_private.idl modified Fri Jan 24 13:23:21 2014.
+// From private/ppb_uma_private.idl modified Thu Mar 13 11:54:51 2014.
 
+#include "ppapi/c/pp_completion_callback.h"
 #include "ppapi/c/pp_errors.h"
 #include "ppapi/c/private/ppb_uma_private.h"
 #include "ppapi/shared_impl/tracked_callback.h"
@@ -66,16 +67,28 @@
                                           boundary_value);
 }
 
-const PPB_UMA_Private_0_2 g_ppb_uma_private_thunk_0_2 = {
+int32_t IsCrashReportingEnabled(PP_Instance instance,
+                                struct PP_CompletionCallback callback) {
+  VLOG(4) << "PPB_UMA_Private::IsCrashReportingEnabled()";
+  EnterInstanceAPI<PPB_UMA_Singleton_API> enter(instance, callback);
+  if (enter.failed())
+    return enter.retval();
+  return enter.SetResult(enter.functions()->IsCrashReportingEnabled(
+      instance,
+      enter.callback()));
+}
+
+const PPB_UMA_Private_0_3 g_ppb_uma_private_thunk_0_3 = {
   &HistogramCustomTimes,
   &HistogramCustomCounts,
-  &HistogramEnumeration
+  &HistogramEnumeration,
+  &IsCrashReportingEnabled
 };
 
 }  // namespace
 
-PPAPI_THUNK_EXPORT const PPB_UMA_Private_0_2* GetPPB_UMA_Private_0_2_Thunk() {
-  return &g_ppb_uma_private_thunk_0_2;
+PPAPI_THUNK_EXPORT const PPB_UMA_Private_0_3* GetPPB_UMA_Private_0_3_Thunk() {
+  return &g_ppb_uma_private_thunk_0_3;
 }
 
 }  // namespace thunk
diff --git a/ppapi/thunk/ppb_uma_singleton_api.h b/ppapi/thunk/ppb_uma_singleton_api.h
index efb6736..f8414b9 100644
--- a/ppapi/thunk/ppb_uma_singleton_api.h
+++ b/ppapi/thunk/ppb_uma_singleton_api.h
@@ -34,6 +34,10 @@
                                     int32_t sample,
                                     int32_t boundary_value) = 0;
 
+  virtual int32_t IsCrashReportingEnabled(
+      PP_Instance instance,
+      scoped_refptr<TrackedCallback> cc) = 0;
+
   static const SingletonResourceID kSingletonResourceID = UMA_SINGLETON_ID;
 };
 
diff --git a/printing/cups_config_helper.py b/printing/cups_config_helper.py
index 3fe5fe0..976054f 100755
--- a/printing/cups_config_helper.py
+++ b/printing/cups_config_helper.py
@@ -46,6 +46,11 @@
     if flag_mode is None or flag_mode == mode:
       flags_subset.append(flag)
 
+  # Note: cross build is confused by the option, and may trigger linker
+  # warning causing build error.
+  if '-lgnutls' in flags_subset:
+    flags_subset.remove('-lgnutls')
+
   return flags_subset
 
 
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc
index 9a28ddb..6bc5941 100644
--- a/printing/print_job_constants.cc
+++ b/printing/print_job_constants.cc
@@ -15,6 +15,9 @@
 // Unique ID to identify a print preview UI.
 const char kPreviewUIID[] = "previewUIID";
 
+// Capabilities option. Contains the capabilities in CDD format.
+const char kSettingCapabilities[] = "capabilities";
+
 // Print using cloud print: true if selected, false if not.
 const char kSettingCloudPrintId[] = "cloudPrintID";
 
@@ -120,6 +123,12 @@
 // Printer name.
 const char kSettingPrinterName[] = "printerName";
 
+// Printer description.
+const char kSettingPrinterDescription[] = "printerDescription";
+
+// Additional printer options.
+const char kSettingPrinterOptions[] = "printerOptions";
+
 // Print to PDF option: true if selected, false if not.
 const char kSettingPrintToPDF[] = "printToPDF";
 
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h
index 7912349..260c161 100644
--- a/printing/print_job_constants.h
+++ b/printing/print_job_constants.h
@@ -13,6 +13,7 @@
 PRINTING_EXPORT extern const char kIsFirstRequest[];
 PRINTING_EXPORT extern const char kPreviewRequestID[];
 PRINTING_EXPORT extern const char kPreviewUIID[];
+PRINTING_EXPORT extern const char kSettingCapabilities[];
 PRINTING_EXPORT extern const char kSettingCloudPrintId[];
 PRINTING_EXPORT extern const char kSettingCloudPrintDialog[];
 PRINTING_EXPORT extern const char kSettingCollate[];
@@ -44,13 +45,15 @@
 PRINTING_EXPORT extern const char kSettingPageWidth[];
 PRINTING_EXPORT extern const char kSettingPageHeight[];
 PRINTING_EXPORT extern const char kSettingPreviewModifiable[];
-PRINTING_EXPORT extern const char kSettingPrintableAreaX[];
-PRINTING_EXPORT extern const char kSettingPrintableAreaY[];
-PRINTING_EXPORT extern const char kSettingPrintableAreaWidth[];
-PRINTING_EXPORT extern const char kSettingPrintableAreaHeight[];
-PRINTING_EXPORT extern const char kSettingPrinterName[];
 PRINTING_EXPORT extern const char kSettingPrintToPDF[];
 PRINTING_EXPORT extern const char kSettingPrintWithPrivet[];
+PRINTING_EXPORT extern const char kSettingPrintableAreaHeight[];
+PRINTING_EXPORT extern const char kSettingPrintableAreaWidth[];
+PRINTING_EXPORT extern const char kSettingPrintableAreaX[];
+PRINTING_EXPORT extern const char kSettingPrintableAreaY[];
+PRINTING_EXPORT extern const char kSettingPrinterDescription[];
+PRINTING_EXPORT extern const char kSettingPrinterName[];
+PRINTING_EXPORT extern const char kSettingPrinterOptions[];
 PRINTING_EXPORT extern const char kSettingTicket[];
 PRINTING_EXPORT extern const char kSettingShouldPrintBackgrounds[];
 PRINTING_EXPORT extern const char kSettingShouldPrintSelectionOnly[];
diff --git a/printing/printing.target.darwin-arm.mk b/printing/printing.target.darwin-arm.mk
index 54e13e3..33b025a 100644
--- a/printing/printing.target.darwin-arm.mk
+++ b/printing/printing.target.darwin-arm.mk
@@ -111,9 +111,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -122,6 +120,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -231,9 +230,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -242,6 +239,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing.target.darwin-mips.mk b/printing/printing.target.darwin-mips.mk
index a11958d..b91c206 100644
--- a/printing/printing.target.darwin-mips.mk
+++ b/printing/printing.target.darwin-mips.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -121,6 +119,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -229,9 +228,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -240,6 +237,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing.target.darwin-x86.mk b/printing/printing.target.darwin-x86.mk
index c2e8d3b..40c3028 100644
--- a/printing/printing.target.darwin-x86.mk
+++ b/printing/printing.target.darwin-x86.mk
@@ -112,9 +112,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -123,6 +121,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -232,9 +231,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -243,6 +240,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing.target.darwin-x86_64.mk b/printing/printing.target.darwin-x86_64.mk
new file mode 100644
index 0000000..3434e04
--- /dev/null
+++ b/printing/printing.target.darwin-x86_64.mk
@@ -0,0 +1,353 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := printing_printing_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,printing_printing_jni_headers_gyp)/printing_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	printing/backend/print_backend.cc \
+	printing/backend/print_backend_consts.cc \
+	printing/backend/print_backend_dummy.cc \
+	printing/image.cc \
+	printing/image_android.cc \
+	printing/metafile_skia_wrapper.cc \
+	printing/page_number.cc \
+	printing/page_range.cc \
+	printing/page_setup.cc \
+	printing/page_size_margins.cc \
+	printing/pdf_metafile_skia.cc \
+	printing/print_destination_none.cc \
+	printing/print_job_constants.cc \
+	printing/print_settings.cc \
+	printing/print_settings_initializer.cc \
+	printing/printed_document.cc \
+	printing/printed_page.cc \
+	printing/printing_context.cc \
+	printing/printing_utils.cc \
+	printing/units.cc \
+	printing/printing_context_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPRINTING_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/printing \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPRINTING_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/printing \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: printing_printing_gyp
+
+# Alias gyp target name.
+.PHONY: printing
+printing: printing_printing_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/printing/printing.target.linux-arm.mk b/printing/printing.target.linux-arm.mk
index 54e13e3..33b025a 100644
--- a/printing/printing.target.linux-arm.mk
+++ b/printing/printing.target.linux-arm.mk
@@ -111,9 +111,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -122,6 +120,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -231,9 +230,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -242,6 +239,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing.target.linux-mips.mk b/printing/printing.target.linux-mips.mk
index a11958d..b91c206 100644
--- a/printing/printing.target.linux-mips.mk
+++ b/printing/printing.target.linux-mips.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -121,6 +119,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -229,9 +228,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -240,6 +237,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing.target.linux-x86.mk b/printing/printing.target.linux-x86.mk
index c2e8d3b..40c3028 100644
--- a/printing/printing.target.linux-x86.mk
+++ b/printing/printing.target.linux-x86.mk
@@ -112,9 +112,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -123,6 +121,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -232,9 +231,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -243,6 +240,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing.target.linux-x86_64.mk b/printing/printing.target.linux-x86_64.mk
new file mode 100644
index 0000000..3434e04
--- /dev/null
+++ b/printing/printing.target.linux-x86_64.mk
@@ -0,0 +1,353 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := printing_printing_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,printing_printing_jni_headers_gyp)/printing_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	printing/backend/print_backend.cc \
+	printing/backend/print_backend_consts.cc \
+	printing/backend/print_backend_dummy.cc \
+	printing/image.cc \
+	printing/image_android.cc \
+	printing/metafile_skia_wrapper.cc \
+	printing/page_number.cc \
+	printing/page_range.cc \
+	printing/page_setup.cc \
+	printing/page_size_margins.cc \
+	printing/pdf_metafile_skia.cc \
+	printing/print_destination_none.cc \
+	printing/print_job_constants.cc \
+	printing/print_settings.cc \
+	printing/print_settings_initializer.cc \
+	printing/printed_document.cc \
+	printing/printed_page.cc \
+	printing/printing_context.cc \
+	printing/printing_utils.cc \
+	printing/units.cc \
+	printing/printing_context_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPRINTING_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/printing \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPRINTING_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/printing \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: printing_printing_gyp
+
+# Alias gyp target name.
+.PHONY: printing
+printing: printing_printing_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/printing/printing_context.cc b/printing/printing_context.cc
index c8e8e87..8451463 100644
--- a/printing/printing_context.cc
+++ b/printing/printing_context.cc
@@ -85,7 +85,6 @@
           kCloudPrintMarginInch * settings_.device_units_per_inch(),
           kCloudPrintMarginInch * settings_.device_units_per_inch());
     }
-    DCHECK_EQ(settings_.device_units_per_inch(), kDefaultPdfDpi);
     settings_.SetPrinterPrintableArea(paper_size, paper_rect, true);
     return OK;
   }
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index 547bf83..a2e3434 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -165,11 +165,7 @@
 }
 
 PrintingContextWin::PrintingContextWin(const std::string& app_locale)
-    : PrintingContext(app_locale),
-      context_(NULL),
-      dialog_box_(NULL),
-      print_dialog_func_(&PrintDlgEx) {
-}
+    : PrintingContext(app_locale), context_(NULL), dialog_box_(NULL) {}
 
 PrintingContextWin::~PrintingContextWin() {
   ReleaseContext();
@@ -237,16 +233,7 @@
     dialog_options.Flags |= PD_NOPAGENUMS;
   }
 
-  // Note that this cannot use ui::BaseShellDialog as the print dialog is
-  // system modal: opening it from a background thread can cause Windows to
-  // get the wrong Z-order which will make the print dialog appear behind the
-  // browser frame (but still being modal) so neither the browser frame nor
-  // the print dialog will get any input. See http://crbug.com/342697
-  // http://crbug.com/180997 for details.
-  base::MessageLoop::ScopedNestableTaskAllower allow(
-      base::MessageLoop::current());
-  HRESULT hr = (*print_dialog_func_)(&dialog_options);
-  if (hr != S_OK) {
+  if (ShowPrintDialog(&dialog_options) != S_OK) {
     ResetSettings();
     callback.Run(FAILED);
   }
@@ -688,6 +675,19 @@
   }
 }
 
+HRESULT PrintingContextWin::ShowPrintDialog(PRINTDLGEX* options) {
+  // Note that this cannot use ui::BaseShellDialog as the print dialog is
+  // system modal: opening it from a background thread can cause Windows to
+  // get the wrong Z-order which will make the print dialog appear behind the
+  // browser frame (but still being modal) so neither the browser frame nor
+  // the print dialog will get any input. See http://crbug.com/342697
+  // http://crbug.com/180997 for details.
+  base::MessageLoop::ScopedNestableTaskAllower allow(
+      base::MessageLoop::current());
+
+  return PrintDlgEx(options);
+}
+
 PrintingContext::Result PrintingContextWin::ParseDialogResult(
     const PRINTDLG& dialog_options) {
   // If the user clicked OK or Apply then Cancel, but not only Cancel.
diff --git a/printing/printing_context_win.h b/printing/printing_context_win.h
index d0cd2fb..6c1e420 100644
--- a/printing/printing_context_win.h
+++ b/printing/printing_context_win.h
@@ -40,18 +40,14 @@
   virtual void ReleaseContext() OVERRIDE;
   virtual gfx::NativeDrawingContext context() const OVERRIDE;
 
-#if defined(UNIT_TEST) || defined(PRINTING_IMPLEMENTATION)
-  // Sets a fake PrintDlgEx function pointer in tests.
-  void SetPrintDialog(HRESULT (__stdcall *print_dialog_func)(LPPRINTDLGEX)) {
-    print_dialog_func_ = print_dialog_func;
-  }
-#endif  // defined(UNIT_TEST)
-
   // Allocates the HDC for a specific DEVMODE.
   static bool AllocateContext(const std::wstring& printer_name,
                               const DEVMODE* dev_mode,
                               gfx::NativeDrawingContext* context);
 
+ protected:
+  virtual HRESULT ShowPrintDialog(PRINTDLGEX* options);
+
  private:
   // Class that manages the PrintDlgEx() callbacks. This is meant to be a
   // temporary object used during the Print... dialog display.
@@ -83,10 +79,6 @@
   // The dialog box for the time it is shown.
   volatile HWND dialog_box_;
 
-  // Function pointer that defaults to PrintDlgEx. It can be changed using
-  // SetPrintDialog() in tests.
-  HRESULT (__stdcall *print_dialog_func_)(LPPRINTDLGEX);
-
   DISALLOW_COPY_AND_ASSIGN(PrintingContextWin);
 };
 
diff --git a/printing/printing_context_win_unittest.cc b/printing/printing_context_win_unittest.cc
index 79e7637..c9facc9 100644
--- a/printing/printing_context_win_unittest.cc
+++ b/printing/printing_context_win_unittest.cc
@@ -35,112 +35,122 @@
   PrintingContext::Result result_;
 };
 
-// This is a fake PrintDlgEx implementation that sets the right fields in
-// |lppd| to trigger a bug in older revisions of PrintingContext.
-HRESULT WINAPI PrintDlgExMock(LPPRINTDLGEX lppd) {
-  // The interesting bits:
-  // Pretend the user hit print
-  lppd->dwResultAction = PD_RESULT_PRINT;
+class MockPrintingContextWin : public PrintingContextWin {
+ public:
+  MockPrintingContextWin() : PrintingContextWin("") {}
 
-  // Pretend the page range is 1-5, but since lppd->Flags does not have
-  // PD_SELECTION set, this really shouldn't matter.
-  lppd->nPageRanges = 1;
-  lppd->lpPageRanges[0].nFromPage = 1;
-  lppd->lpPageRanges[0].nToPage = 5;
+ protected:
+  // This is a fake PrintDlgEx implementation that sets the right fields in
+  // |lppd| to trigger a bug in older revisions of PrintingContext.
+  HRESULT ShowPrintDialog(PRINTDLGEX* lppd) OVERRIDE {
+    // The interesting bits:
+    // Pretend the user hit print
+    lppd->dwResultAction = PD_RESULT_PRINT;
 
-  base::string16 printer_name = PrintingContextTest::GetDefaultPrinter();
-  ScopedPrinterHandle printer;
-  if (!printer.OpenPrinter(printer_name.c_str()))
-    return E_FAIL;
+    // Pretend the page range is 1-5, but since lppd->Flags does not have
+    // PD_SELECTION set, this really shouldn't matter.
+    lppd->nPageRanges = 1;
+    lppd->lpPageRanges[0].nFromPage = 1;
+    lppd->lpPageRanges[0].nToPage = 5;
 
-  scoped_ptr<uint8[]> buffer;
-  const DEVMODE* dev_mode = NULL;
-  HRESULT result = S_OK;
-  lppd->hDC = NULL;
-  lppd->hDevMode = NULL;
-  lppd->hDevNames = NULL;
+    base::string16 printer_name = PrintingContextTest::GetDefaultPrinter();
+    ScopedPrinterHandle printer;
+    if (!printer.OpenPrinter(printer_name.c_str()))
+      return E_FAIL;
 
-  PrinterInfo2 info_2;
-  if (info_2.Init(printer)) {
-    dev_mode = info_2.get()->pDevMode;
-  }
-  if (!dev_mode) {
-    result = E_FAIL;
-    goto Cleanup;
-  }
+    scoped_ptr<uint8[]> buffer;
+    const DEVMODE* dev_mode = NULL;
+    HRESULT result = S_OK;
+    lppd->hDC = NULL;
+    lppd->hDevMode = NULL;
+    lppd->hDevNames = NULL;
 
-  if (!PrintingContextWin::AllocateContext(printer_name, dev_mode,
-                                           &lppd->hDC)) {
-    result = E_FAIL;
-    goto Cleanup;
-  }
-
-  size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra;
-  lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dev_mode_size);
-  if (!lppd->hDevMode) {
-    result = E_FAIL;
-    goto Cleanup;
-  }
-  void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
-  if (!dev_mode_ptr) {
-    result = E_FAIL;
-    goto Cleanup;
-  }
-  memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
-  GlobalUnlock(lppd->hDevMode);
-  dev_mode_ptr = NULL;
-
-  size_t driver_size = 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pDriverName);
-  size_t printer_size = 2 + sizeof(wchar_t) *
-                            lstrlen(info_2.get()->pPrinterName);
-  size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPortName);
-  size_t dev_names_size = sizeof(DEVNAMES) + driver_size + printer_size +
-                          port_size;
-  lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
-  if (!lppd->hDevNames) {
-    result = E_FAIL;
-    goto Cleanup;
-  }
-  void* dev_names_ptr = GlobalLock(lppd->hDevNames);
-  if (!dev_names_ptr) {
-    result = E_FAIL;
-    goto Cleanup;
-  }
-  DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
-  dev_names->wDefault = 1;
-  dev_names->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
-  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset,
-         info_2.get()->pDriverName, driver_size);
-  dev_names->wDeviceOffset = dev_names->wDriverOffset +
-                             driver_size / sizeof(wchar_t);
-  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset,
-         info_2.get()->pPrinterName, printer_size);
-  dev_names->wOutputOffset = dev_names->wDeviceOffset +
-                             printer_size / sizeof(wchar_t);
-  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset,
-         info_2.get()->pPortName, port_size);
-  GlobalUnlock(lppd->hDevNames);
-  dev_names_ptr = NULL;
-
-Cleanup:
-  // Note: This section does proper deallocation/free of DC/global handles.  We
-  //       did not use ScopedHGlobal or ScopedHandle because they did not
-  //       perform what we need.  Goto's are used based on Windows programming
-  //       idiom, to avoid deeply nested if's, and try-catch-finally is not
-  //       allowed in Chromium.
-  if (FAILED(result)) {
-    if (lppd->hDC) {
-      DeleteDC(lppd->hDC);
+    PrinterInfo2 info_2;
+    if (info_2.Init(printer)) {
+      dev_mode = info_2.get()->pDevMode;
     }
-    if (lppd->hDevMode) {
-      GlobalFree(lppd->hDevMode);
+    if (!dev_mode) {
+      result = E_FAIL;
+      goto Cleanup;
     }
-    if (lppd->hDevNames) {
-      GlobalFree(lppd->hDevNames);
+
+    if (!PrintingContextWin::AllocateContext(
+            printer_name, dev_mode, &lppd->hDC)) {
+      result = E_FAIL;
+      goto Cleanup;
     }
+
+    size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra;
+    lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dev_mode_size);
+    if (!lppd->hDevMode) {
+      result = E_FAIL;
+      goto Cleanup;
+    }
+    void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
+    if (!dev_mode_ptr) {
+      result = E_FAIL;
+      goto Cleanup;
+    }
+    memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
+    GlobalUnlock(lppd->hDevMode);
+    dev_mode_ptr = NULL;
+
+    size_t driver_size =
+        2 + sizeof(wchar_t) * lstrlen(info_2.get()->pDriverName);
+    size_t printer_size =
+        2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPrinterName);
+    size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPortName);
+    size_t dev_names_size =
+        sizeof(DEVNAMES) + driver_size + printer_size + port_size;
+    lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
+    if (!lppd->hDevNames) {
+      result = E_FAIL;
+      goto Cleanup;
+    }
+    void* dev_names_ptr = GlobalLock(lppd->hDevNames);
+    if (!dev_names_ptr) {
+      result = E_FAIL;
+      goto Cleanup;
+    }
+    DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
+    dev_names->wDefault = 1;
+    dev_names->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
+    memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset,
+           info_2.get()->pDriverName,
+           driver_size);
+    dev_names->wDeviceOffset =
+        dev_names->wDriverOffset + driver_size / sizeof(wchar_t);
+    memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset,
+           info_2.get()->pPrinterName,
+           printer_size);
+    dev_names->wOutputOffset =
+        dev_names->wDeviceOffset + printer_size / sizeof(wchar_t);
+    memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset,
+           info_2.get()->pPortName,
+           port_size);
+    GlobalUnlock(lppd->hDevNames);
+    dev_names_ptr = NULL;
+
+  Cleanup:
+    // Note: This section does proper deallocation/free of DC/global handles. We
+    //       did not use ScopedHGlobal or ScopedHandle because they did not
+    //       perform what we need.  Goto's are used based on Windows programming
+    //       idiom, to avoid deeply nested if's, and try-catch-finally is not
+    //       allowed in Chromium.
+    if (FAILED(result)) {
+      if (lppd->hDC) {
+        DeleteDC(lppd->hDC);
+      }
+      if (lppd->hDevMode) {
+        GlobalFree(lppd->hDevMode);
+      }
+      if (lppd->hDevNames) {
+        GlobalFree(lppd->hDevNames);
+      }
+    }
+    return result;
   }
-  return result;
-}
+};
 
 TEST_F(PrintingContextTest, Base) {
   if (IsTestCaseDisabled())
@@ -164,9 +174,7 @@
   if (IsTestCaseDisabled())
     return;
 
-  std::string dummy_locale;
-  PrintingContextWin context(dummy_locale);
-  context.SetPrintDialog(&PrintDlgExMock);
+  MockPrintingContextWin context;
   context.AskUserForSettings(
       NULL, 123, false, base::Bind(&PrintingContextTest::PrintSettingsCallback,
                                    base::Unretained(this)));
diff --git a/printing/printing_jni_headers.target.darwin-arm.mk b/printing/printing_jni_headers.target.darwin-arm.mk
index f09bf47..8cc646a 100644
--- a/printing/printing_jni_headers.target.darwin-arm.mk
+++ b/printing/printing_jni_headers.target.darwin-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing_jni_headers.target.darwin-mips.mk b/printing/printing_jni_headers.target.darwin-mips.mk
index ffaaeae..a0f5100 100644
--- a/printing/printing_jni_headers.target.darwin-mips.mk
+++ b/printing/printing_jni_headers.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing_jni_headers.target.darwin-x86.mk b/printing/printing_jni_headers.target.darwin-x86.mk
index 1c3517b..d9db09b 100644
--- a/printing/printing_jni_headers.target.darwin-x86.mk
+++ b/printing/printing_jni_headers.target.darwin-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing_jni_headers.target.darwin-x86_64.mk b/printing/printing_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d58d727
--- /dev/null
+++ b/printing/printing_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,234 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := printing_printing_jni_headers_gyp
+LOCAL_MODULE_STEM := printing_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "printing_printing_gyp_printing_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/printing/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['android/java/src/org/chromium/printing/PrintingContext.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/printing/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: $(LOCAL_PATH)/printing/android/java/src/org/chromium/printing/PrintingContext.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/printing/jni; cd $(gyp_local_path)/printing; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/printing/PrintingContext.java --output_dir "$(gyp_shared_intermediate_dir)/printing/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: printing_printing_jni_headers_gyp_rule_trigger
+printing_printing_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h \
+	printing_printing_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: printing_printing_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: printing_jni_headers
+printing_jni_headers: printing_printing_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/printing/printing_jni_headers.target.linux-arm.mk b/printing/printing_jni_headers.target.linux-arm.mk
index f09bf47..8cc646a 100644
--- a/printing/printing_jni_headers.target.linux-arm.mk
+++ b/printing/printing_jni_headers.target.linux-arm.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing_jni_headers.target.linux-mips.mk b/printing/printing_jni_headers.target.linux-mips.mk
index ffaaeae..a0f5100 100644
--- a/printing/printing_jni_headers.target.linux-mips.mk
+++ b/printing/printing_jni_headers.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing_jni_headers.target.linux-x86.mk b/printing/printing_jni_headers.target.linux-x86.mk
index 1c3517b..d9db09b 100644
--- a/printing/printing_jni_headers.target.linux-x86.mk
+++ b/printing/printing_jni_headers.target.linux-x86.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/printing/printing_jni_headers.target.linux-x86_64.mk b/printing/printing_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..d58d727
--- /dev/null
+++ b/printing/printing_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,234 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := printing_printing_jni_headers_gyp
+LOCAL_MODULE_STEM := printing_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "printing_printing_gyp_printing_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../base/android/jni_generator/jni_generator.py', '../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/printing/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['android/java/src/org/chromium/printing/PrintingContext.java'], 'action': ['../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/printing/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h: $(LOCAL_PATH)/printing/android/java/src/org/chromium/printing/PrintingContext.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/printing/jni; cd $(gyp_local_path)/printing; ../base/android/jni_generator/jni_generator.py --input_file android/java/src/org/chromium/printing/PrintingContext.java --output_dir "$(gyp_shared_intermediate_dir)/printing/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: printing_printing_jni_headers_gyp_rule_trigger
+printing_printing_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/printing/jni/PrintingContext_jni.h \
+	printing_printing_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: printing_printing_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: printing_jni_headers
+printing_jni_headers: printing_printing_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/printing/pwg_raster_settings.h b/printing/pwg_raster_settings.h
new file mode 100644
index 0000000..dc87b93
--- /dev/null
+++ b/printing/pwg_raster_settings.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef PRINTING_BITMAP_TRANSFORM_SETTINGS_H_
+#define PRINTING_BITMAP_TRANSFORM_SETTINGS_H_
+
+#include "base/tuple.h"
+#include "ipc/ipc_param_traits.h"
+#include "printing/printing_export.h"
+#include "ui/gfx/rect.h"
+
+namespace printing {
+
+enum PwgRasterTransformType {
+  TRANSFORM_NORMAL,
+  TRANSFORM_ROTATE_180,
+  TRANSFORM_FLIP_HORIZONTAL,
+  TRANSFORM_FLIP_VERTICAL
+};
+
+struct PwgRasterSettings {
+  // How to transform odd-numbered pages.
+  PwgRasterTransformType odd_page_transform;
+  // Rotate all pages (on top of odd-numbered page transform).
+  bool rotate_all_pages;
+  // Rasterize pages in reverse order.
+  bool reverse_page_order;
+};
+
+}  // namespace printing
+
+#endif  // PRINTING_BITMAP_TRANSFORM_SETTINGS_H_
diff --git a/remoting/android/java/AndroidManifest.xml.jinja2 b/remoting/android/java/AndroidManifest.xml.jinja2
index a163721..7521f52 100644
--- a/remoting/android/java/AndroidManifest.xml.jinja2
+++ b/remoting/android/java/AndroidManifest.xml.jinja2
@@ -7,7 +7,7 @@
     <uses-permission android:name="android.permission.INTERNET"/>
     <uses-permission android:name="android.permission.MANAGE_ACCOUNTS"/>
     <uses-permission android:name="android.permission.USE_CREDENTIALS"/>
-    <application android:label="@string/product_name"
+    <application android:label="@string/product_name_android"
             android:icon="@drawable/chromoting128"
             android:theme="@android:style/Theme.Holo">
         <activity android:name="org.chromium.chromoting.Chromoting"
diff --git a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
index ebf826c..1e8b489 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Chromoting.java
@@ -26,7 +26,6 @@
 import android.view.View;
 import android.widget.ArrayAdapter;
 import android.widget.ListView;
-import android.widget.TextView;
 import android.widget.Toast;
 
 import org.chromium.chromoting.jni.JniInterface;
@@ -39,8 +38,8 @@
  * also requests and renews authentication tokens using the system account manager.
  */
 public class Chromoting extends Activity implements JniInterface.ConnectionListener,
-        AccountManagerCallback<Bundle>, ActionBar.OnNavigationListener,
-        HostListLoader.Callback {
+        AccountManagerCallback<Bundle>, ActionBar.OnNavigationListener, HostListLoader.Callback,
+        View.OnClickListener {
     /** Only accounts of this type will be selectable for authentication. */
     private static final String ACCOUNT_TYPE = "com.google";
 
@@ -52,12 +51,19 @@
     private static final String HELP_URL =
             "http://support.google.com/chrome/?p=mobile_crd_hostslist";
 
+    /** Web page to be displayed when user triggers the hyperlink for setting up hosts. */
+    private static final String HOST_SETUP_URL =
+            "https://support.google.com/chrome/answer/1649523";
+
     /** User's account details. */
     private Account mAccount;
 
     /** List of accounts on the system. */
     private Account[] mAccounts;
 
+    /** SpinnerAdapter used in the action bar for selecting accounts. */
+    private AccountsAdapter mAccountsAdapter;
+
     /** Account auth token. */
     private String mToken;
 
@@ -70,17 +76,11 @@
     /** Refresh button. */
     private MenuItem mRefreshButton;
 
-    /** Main view of this activity */
-    private View mMainView;
-
-    /** Progress view shown instead of the main view when the host list is loading. */
-    private View mProgressView;
-
-    /** Greeting at the top of the displayed list. */
-    private TextView mGreeting;
-
     /** Host list as it appears to the user. */
-    private ListView mList;
+    private ListView mHostListView;
+
+    /** Progress view shown instead of the host list when the host list is loading. */
+    private View mProgressView;
 
     /** Dialog for reporting connection progress. */
     private ProgressDialog mProgressIndicator;
@@ -128,8 +128,13 @@
 
     /** Shows or hides the progress indicator for loading the host list. */
     private void setHostListProgressVisible(boolean visible) {
-        mMainView.setVisibility(visible ? View.GONE : View.VISIBLE);
+        mHostListView.setVisibility(visible ? View.GONE : View.VISIBLE);
         mProgressView.setVisibility(visible ? View.VISIBLE : View.GONE);
+
+        // Hiding the host-list does not automatically hide the empty view, so do that here.
+        if (visible) {
+            mHostListView.getEmptyView().setVisibility(View.GONE);
+        }
     }
 
     /**
@@ -145,13 +150,24 @@
         mHostListLoader = new HostListLoader();
 
         // Get ahold of our view widgets.
-        mMainView = findViewById(R.id.hostList_main);
+        mHostListView = (ListView)findViewById(R.id.hostList_chooser);
+        mHostListView.setEmptyView(findViewById(R.id.hostList_empty));
         mProgressView = findViewById(R.id.hostList_progress);
-        mGreeting = (TextView)findViewById(R.id.hostList_greeting);
-        mList = (ListView)findViewById(R.id.hostList_chooser);
+
+        findViewById(R.id.host_setup_link_android).setOnClickListener(this);
 
         // Bring native components online.
         JniInterface.loadLibrary(this);
+    }
+
+    /**
+     * Called when the activity becomes visible. This happens on initial launch and whenever the
+     * user switches to the activity, for example, by using the window-switcher or when coming from
+     * the device's lock screen.
+     */
+    @Override
+    public void onStart() {
+        super.onStart();
 
         mAccounts = AccountManager.get(this).getAccountsByType(ACCOUNT_TYPE);
         if (mAccounts.length == 0) {
@@ -175,11 +191,14 @@
 
         if (mAccounts.length == 1) {
             getActionBar().setDisplayShowTitleEnabled(true);
+            getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
+            getActionBar().setTitle(R.string.mode_me2me);
             getActionBar().setSubtitle(mAccount.name);
         } else {
-            AccountsAdapter adapter = new AccountsAdapter(this, mAccounts);
+            mAccountsAdapter = new AccountsAdapter(this, mAccounts);
+            getActionBar().setDisplayShowTitleEnabled(false);
             getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
-            getActionBar().setListNavigationCallbacks(adapter, this);
+            getActionBar().setListNavigationCallbacks(mAccountsAdapter, this);
             getActionBar().setSelectedNavigationItem(index);
         }
 
@@ -201,8 +220,7 @@
         // Reload the spinner resources, since the font sizes are dependent on the screen
         // orientation.
         if (mAccounts.length != 1) {
-            AccountsAdapter adapter = new AccountsAdapter(this, mAccounts);
-            getActionBar().setListNavigationCallbacks(adapter, this);
+            mAccountsAdapter.notifyDataSetChanged();
         }
     }
 
@@ -237,6 +255,12 @@
         }
     }
 
+    /** Called when the user touches hyperlinked text. */
+    @Override
+    public void onClick(View view) {
+        HelpActivity.launch(this, HOST_SETUP_URL);
+    }
+
     /** Called when the user taps on a host entry. */
     public void connectToHost(HostInfo host) {
         mProgressIndicator = ProgressDialog.show(this,
@@ -374,17 +398,9 @@
     private void updateUi() {
         mRefreshButton.setEnabled(mAccount != null);
 
-        if (mHosts.length == 0) {
-            mGreeting.setText(getString(R.string.host_list_empty_android));
-            mList.setAdapter(null);
-            return;
-        }
-
-        mGreeting.setText(getString(R.string.mode_me2me));
-
         ArrayAdapter<HostInfo> displayer = new HostListAdapter(this, R.layout.host, mHosts);
         Log.i("hostlist", "About to populate host list display");
-        mList.setAdapter(displayer);
+        mHostListView.setAdapter(displayer);
     }
 
     @Override
diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
index b75d97d..570fd80 100644
--- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java
+++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
@@ -103,10 +103,10 @@
                         KeyEvent.KEYCODE_FORWARD_DEL,
                     };
                     for (int key : keys) {
-                        JniInterface.keyboardAction(key, true);
+                        JniInterface.sendKeyEvent(key, true);
                     }
                     for (int key : keys) {
-                        JniInterface.keyboardAction(key, false);
+                        JniInterface.sendKeyEvent(key, false);
                     }
                 }
                 return true;
@@ -127,32 +127,48 @@
      */
     @Override
     public boolean dispatchKeyEvent(KeyEvent event) {
+        // Send ACTION_MULTIPLE event as TextEvent.
+        //
+        // TODO(sergeyu): For all keys on English keyboard Android generates
+        // ACTION_DOWN/ACTION_UP events, so they are sent as KeyEvent instead of
+        // TextEvent. As result the host may handle them as non-English chars
+        // when it has non-English layout selected, which might be confusing for
+        // the user. This code should be fixed to send all text input events as
+        // TextEvent, but it cannot be done now because not all hosts support
+        // TextEvent. Also, to handle keyboard shortcuts properly this code will
+        // need to track the state of modifier keys (such as Ctrl or Alt) and
+        // send KeyEvents in the case any of the modifier keys are pressed.
+        if (event.getAction() == KeyEvent.ACTION_MULTIPLE) {
+            JniInterface.sendTextEvent(event.getCharacters());
+            return super.dispatchKeyEvent(event);
+        }
+
         boolean depressed = event.getAction() == KeyEvent.ACTION_DOWN;
 
         switch (event.getKeyCode()) {
             case KeyEvent.KEYCODE_AT:
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_2, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_2, depressed);
                 break;
 
             case KeyEvent.KEYCODE_POUND:
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_3, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_3, depressed);
                 break;
 
             case KeyEvent.KEYCODE_STAR:
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_8, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_8, depressed);
                 break;
 
             case KeyEvent.KEYCODE_PLUS:
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
-                JniInterface.keyboardAction(KeyEvent.KEYCODE_EQUALS, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_SHIFT_LEFT, depressed);
+                JniInterface.sendKeyEvent(KeyEvent.KEYCODE_EQUALS, depressed);
                 break;
 
             default:
                 // We try to send all other key codes to the host directly.
-                JniInterface.keyboardAction(event.getKeyCode(), depressed);
+                JniInterface.sendKeyEvent(event.getKeyCode(), depressed);
         }
 
         return super.dispatchKeyEvent(event);
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
index 53741c1..94f19a8 100644
--- a/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
+++ b/remoting/android/java/src/org/chromium/chromoting/DesktopView.java
@@ -344,7 +344,7 @@
             return;
         }
 
-        JniInterface.mouseAction(x, y, button, pressed);
+        JniInterface.sendMouseEvent(x, y, button, pressed);
         if (cursorMoved) {
             // TODO(lambroslambrou): Optimize this by only repainting the affected areas.
             requestRepaint();
@@ -353,7 +353,7 @@
 
     @Override
     public void injectMouseWheelDeltaEvent(int deltaX, int deltaY) {
-        JniInterface.mouseWheelDeltaAction(deltaX, deltaY);
+        JniInterface.sendMouseWheelEvent(deltaX, deltaY);
     }
 
     @Override
diff --git a/remoting/android/java/src/org/chromium/chromoting/HostListAdapter.java b/remoting/android/java/src/org/chromium/chromoting/HostListAdapter.java
index 28c6e43..1d38ec8 100644
--- a/remoting/android/java/src/org/chromium/chromoting/HostListAdapter.java
+++ b/remoting/android/java/src/org/chromium/chromoting/HostListAdapter.java
@@ -4,11 +4,11 @@
 
 package org.chromium.chromoting;
 
-import android.text.Html;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.ArrayAdapter;
 import android.widget.TextView;
+import android.widget.Toast;
 
 /** Describes the appearance and behavior of each host list entry. */
 class HostListAdapter extends ArrayAdapter<HostInfo> {
@@ -33,11 +33,9 @@
 
         final HostInfo host = getItem(position);
 
-        // TODO(lambroslambrou): Don't use hardcoded ONLINE/OFFLINE strings here.
-        // See http://crbug.com/331103
-        target.setText(Html.fromHtml(host.name + " (<font color=\"" +
-                (host.isOnline ? HOST_COLOR_ONLINE : HOST_COLOR_OFFLINE) + "\">" +
-                (host.isOnline ? "ONLINE" : "OFFLINE") + "</font>)"));
+        target.setText(host.name);
+        target.setCompoundDrawablesWithIntrinsicBounds(
+                host.isOnline ? R.drawable.icon_host : R.drawable.icon_host_offline, 0, 0, 0);
 
         if (host.isOnline) {
             target.setOnClickListener(new View.OnClickListener() {
@@ -47,8 +45,16 @@
                     }
             });
         } else {
-            // Disallow interaction with this entry.
-            target.setEnabled(false);
+            target.setTextColor(mChromoting.getResources().getColor(R.color.host_offline_text));
+            target.setBackgroundResource(R.drawable.list_item_disabled_selector);
+            target.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        Toast.makeText(mChromoting,
+                                mChromoting.getString(R.string.host_offline_tooltip),
+                                Toast.LENGTH_SHORT).show();
+                    }
+            });
         }
 
         return target;
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
index 79533a3..472c19c 100644
--- a/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
+++ b/remoting/android/java/src/org/chromium/chromoting/jni/JniInterface.java
@@ -281,7 +281,7 @@
      *                   is true.
      */
     private static native void nativeAuthenticationResponse(String pin, boolean createPair,
-                                                            String deviceName);
+            String deviceName);
 
     /** Saves newly-received pairing credentials to permanent storage. Called on the UI thread. */
     @CalledByNative
@@ -296,40 +296,53 @@
      * Moves the mouse cursor, possibly while clicking the specified (nonnegative) button. Called
      * on the UI thread.
      */
-    public static void mouseAction(int x, int y, int whichButton, boolean buttonDown) {
+    public static void sendMouseEvent(int x, int y, int whichButton, boolean buttonDown) {
         if (!sConnected) {
             return;
         }
 
-        nativeMouseAction(x, y, whichButton, buttonDown);
+        nativeSendMouseEvent(x, y, whichButton, buttonDown);
     }
 
     /** Passes mouse information to the native handling code. */
-    private static native void nativeMouseAction(int x, int y, int whichButton, boolean buttonDown);
+    private static native void nativeSendMouseEvent(int x, int y, int whichButton,
+            boolean buttonDown);
 
     /** Injects a mouse-wheel event with delta values. Called on the UI thread. */
-    public static void mouseWheelDeltaAction(int deltaX, int deltaY) {
+    public static void sendMouseWheelEvent(int deltaX, int deltaY) {
         if (!sConnected) {
             return;
         }
 
-        nativeMouseWheelDeltaAction(deltaX, deltaY);
+        nativeSendMouseWheelEvent(deltaX, deltaY);
     }
 
     /** Passes mouse-wheel information to the native handling code. */
-    private static native void nativeMouseWheelDeltaAction(int deltaX, int deltaY);
+    private static native void nativeSendMouseWheelEvent(int deltaX, int deltaY);
 
-    /** Presses and releases the specified (nonnegative) key. Called on the UI thread. */
-    public static void keyboardAction(int keyCode, boolean keyDown) {
+    /** Presses or releases the specified (nonnegative) key. Called on the UI thread. */
+    public static void sendKeyEvent(int keyCode, boolean keyDown) {
         if (!sConnected) {
             return;
         }
 
-        nativeKeyboardAction(keyCode, keyDown);
+        nativeSendKeyEvent(keyCode, keyDown);
     }
 
     /** Passes key press information to the native handling code. */
-    private static native void nativeKeyboardAction(int keyCode, boolean keyDown);
+    private static native void nativeSendKeyEvent(int keyCode, boolean keyDown);
+
+    /** Sends TextEvent to the host. Called on the UI thread. */
+    public static void sendTextEvent(String text) {
+        if (!sConnected) {
+            return;
+        }
+
+        nativeSendTextEvent(text);
+    }
+
+    /** Passes text event information to the native handling code. */
+    private static native void nativeSendTextEvent(String text);
 
     /**
      * Sets the redraw callback to the provided functor. Provide a value of null whenever the
diff --git a/remoting/branding_Chrome b/remoting/branding_Chrome
index 478d7f3..83f3d8e 100644
--- a/remoting/branding_Chrome
+++ b/remoting/branding_Chrome
@@ -6,7 +6,13 @@
 MAC_BUNDLE_ID=com.google.Chrome
 MAC_CREATOR=rimZ
 MAC_HOST_BUNDLE_ID=com.google.chromeremotedesktop.me2me-host
+MAC_HOST_BUNDLE_NAME=ChromeRemoteDesktopHost.bundle
+MAC_NATIVE_MESSAGING_HOST_BUNDLE_ID=com.google.chrome.remote_desktop.native-messaging-host
+MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME=NativeMessagingHost.bundle
 MAC_PREFPANE_BUNDLE_ID=com.google.chromeremotedesktop.preferences
+MAC_PREFPANE_BUNDLE_NAME=ChromeRemoteDesktop.prefPane
+MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID=com.google.chrome.remote_desktop.remote-assistance-host
+MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=RemoteAssistanceHost.bundle
 MAC_UNINSTALLER_BUNDLE_ID=com.google.chromeremotedesktop.me2me-host-uninstaller
 MAC_UNINSTALLER_BUNDLE_PREFIX=com.google.pkg
 MAC_UNINSTALLER_NAME=Chrome Remote Desktop Host Uninstaller
diff --git a/remoting/branding_Chromium b/remoting/branding_Chromium
index dc945e2..8be8b75 100644
--- a/remoting/branding_Chromium
+++ b/remoting/branding_Chromium
@@ -6,7 +6,13 @@
 MAC_BUNDLE_ID=org.chromium.Chromium
 MAC_CREATOR=Cr24
 MAC_HOST_BUNDLE_ID=org.chromium.chromoting.me2me-host
+MAC_HOST_BUNDLE_NAME=ChromotingHost.bundle
+MAC_NATIVE_MESSAGING_HOST_BUNDLE_ID=org.chromium.chromoting.native-messaging-host
+MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME=NativeMessagingHost.bundle
 MAC_PREFPANE_BUNDLE_ID=org.chromium.remoting.preferences
+MAC_PREFPANE_BUNDLE_NAME=Chromoting.prefPane
+MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID=org.chromium.chromoting.remote-assistance-host
+MAC_REMOTE_ASSISTANCE_HOST_NAME=RemoteAssistanceHost.bundle
 MAC_UNINSTALLER_BUNDLE_ID=org.chromium.chromoting.me2me-host-uninstaller
 MAC_UNINSTALLER_BUNDLE_PREFIX=org.chromium.pkg
 MAC_UNINSTALLER_NAME=Chromoting Host Uninstaller
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc
index 92b7615..883df5a 100644
--- a/remoting/client/jni/chromoting_jni_instance.cc
+++ b/remoting/client/jni/chromoting_jni_instance.cc
@@ -128,62 +128,74 @@
   jni_runtime_->RedrawCanvas();
 }
 
-void ChromotingJniInstance::PerformMouseAction(
+void ChromotingJniInstance::SendMouseEvent(
     int x, int y,
     protocol::MouseEvent_MouseButton button,
     bool button_down) {
   if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) {
     jni_runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::Bind(&ChromotingJniInstance::PerformMouseAction,
+        FROM_HERE, base::Bind(&ChromotingJniInstance::SendMouseEvent,
                               this, x, y, button, button_down));
     return;
   }
 
-  protocol::MouseEvent action;
-  action.set_x(x);
-  action.set_y(y);
-  action.set_button(button);
+  protocol::MouseEvent event;
+  event.set_x(x);
+  event.set_y(y);
+  event.set_button(button);
   if (button != protocol::MouseEvent::BUTTON_UNDEFINED)
-    action.set_button_down(button_down);
+    event.set_button_down(button_down);
 
-  connection_->input_stub()->InjectMouseEvent(action);
+  connection_->input_stub()->InjectMouseEvent(event);
 }
 
-void ChromotingJniInstance::PerformMouseWheelDeltaAction(int delta_x,
-                                                         int delta_y) {
+void ChromotingJniInstance::SendMouseWheelEvent(int delta_x, int delta_y) {
   if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) {
     jni_runtime_->network_task_runner()->PostTask(
         FROM_HERE,
-        base::Bind(&ChromotingJniInstance::PerformMouseWheelDeltaAction, this,
+        base::Bind(&ChromotingJniInstance::SendMouseWheelEvent, this,
                    delta_x, delta_y));
     return;
   }
 
-  protocol::MouseEvent action;
-  action.set_wheel_delta_x(delta_x);
-  action.set_wheel_delta_y(delta_y);
-  connection_->input_stub()->InjectMouseEvent(action);
+  protocol::MouseEvent event;
+  event.set_wheel_delta_x(delta_x);
+  event.set_wheel_delta_y(delta_y);
+  connection_->input_stub()->InjectMouseEvent(event);
 }
 
-void ChromotingJniInstance::PerformKeyboardAction(int key_code, bool key_down) {
+void ChromotingJniInstance::SendKeyEvent(int key_code, bool key_down) {
   if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) {
     jni_runtime_->network_task_runner()->PostTask(
-        FROM_HERE, base::Bind(&ChromotingJniInstance::PerformKeyboardAction,
+        FROM_HERE, base::Bind(&ChromotingJniInstance::SendKeyEvent,
                               this, key_code, key_down));
     return;
   }
 
   uint32 usb_code = AndroidKeycodeToUsbKeycode(key_code);
   if (usb_code) {
-    protocol::KeyEvent action;
-    action.set_usb_keycode(usb_code);
-    action.set_pressed(key_down);
-    connection_->input_stub()->InjectKeyEvent(action);
+    protocol::KeyEvent event;
+    event.set_usb_keycode(usb_code);
+    event.set_pressed(key_down);
+    connection_->input_stub()->InjectKeyEvent(event);
   } else {
     LOG(WARNING) << "Ignoring unknown keycode: " << key_code;
   }
 }
 
+void ChromotingJniInstance::SendTextEvent(const std::string& text) {
+  if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) {
+    jni_runtime_->network_task_runner()->PostTask(
+        FROM_HERE,
+        base::Bind(&ChromotingJniInstance::SendTextEvent, this, text));
+    return;
+  }
+
+  protocol::TextEvent event;
+  event.set_text(text);
+  connection_->input_stub()->InjectTextEvent(event);
+}
+
 void ChromotingJniInstance::RecordPaintTime(int64 paint_time_ms) {
   if (!jni_runtime_->network_task_runner()->BelongsToCurrentThread()) {
     jni_runtime_->network_task_runner()->PostTask(
diff --git a/remoting/client/jni/chromoting_jni_instance.h b/remoting/client/jni/chromoting_jni_instance.h
index 64be741..edb8b4a 100644
--- a/remoting/client/jni/chromoting_jni_instance.h
+++ b/remoting/client/jni/chromoting_jni_instance.h
@@ -65,14 +65,15 @@
 
   // Moves the host's cursor to the specified coordinates, optionally with some
   // mouse button depressed. If |button| is BUTTON_UNDEFINED, no click is made.
-  void PerformMouseAction(int x, int y,
-                          protocol::MouseEvent_MouseButton button,
-                          bool button_down);
-
-  void PerformMouseWheelDeltaAction(int delta_x, int delta_y);
+  void SendMouseEvent(int x, int y,
+                      protocol::MouseEvent_MouseButton button,
+                      bool button_down);
+  void SendMouseWheelEvent(int delta_x, int delta_y);
 
   // Sends the provided keyboard scan code to the host.
-  void PerformKeyboardAction(int key_code, bool key_down);
+  void SendKeyEvent(int key_code, bool key_down);
+
+  void SendTextEvent(const std::string& text);
 
   // Records paint time for statistics logging, if enabled. May be called from
   // any thread.
diff --git a/remoting/client/jni/chromoting_jni_runtime.cc b/remoting/client/jni/chromoting_jni_runtime.cc
index 7a23487..06cd7ff 100644
--- a/remoting/client/jni/chromoting_jni_runtime.cc
+++ b/remoting/client/jni/chromoting_jni_runtime.cc
@@ -103,38 +103,42 @@
   remoting::ChromotingJniRuntime::GetInstance()->session()->RedrawDesktop();
 }
 
-static void MouseAction(JNIEnv* env,
-                        jclass clazz,
-                        jint x,
-                        jint y,
-                        jint whichButton,
-                        jboolean buttonDown) {
+static void SendMouseEvent(JNIEnv* env,
+                           jclass clazz,
+                           jint x,
+                           jint y,
+                           jint whichButton,
+                           jboolean buttonDown) {
   // Button must be within the bounds of the MouseEvent_MouseButton enum.
   DCHECK(whichButton >= 0 && whichButton < 5);
 
-  remoting::ChromotingJniRuntime::GetInstance()->session()->PerformMouseAction(
-      x,
-      y,
+  remoting::ChromotingJniRuntime::GetInstance()->session()->SendMouseEvent(
+      x, y,
       static_cast<remoting::protocol::MouseEvent_MouseButton>(whichButton),
       buttonDown);
 }
 
-static void MouseWheelDeltaAction(JNIEnv* env,
-                                  jclass clazz,
-                                  jint delta_x,
-                                  jint delta_y) {
-  remoting::ChromotingJniRuntime::GetInstance()
-      ->session()
-      ->PerformMouseWheelDeltaAction(delta_x, delta_y);
+static void SendMouseWheelEvent(JNIEnv* env,
+                                jclass clazz,
+                                jint delta_x,
+                                jint delta_y) {
+  remoting::ChromotingJniRuntime::GetInstance()->session()->SendMouseWheelEvent(
+      delta_x, delta_y);
 }
 
-static void KeyboardAction(JNIEnv* env,
-                           jclass clazz,
-                           jint keyCode,
-                           jboolean keyDown) {
-  remoting::ChromotingJniRuntime::GetInstance()
-      ->session()
-      ->PerformKeyboardAction(keyCode, keyDown);
+static void SendKeyEvent(JNIEnv* env,
+                         jclass clazz,
+                         jint keyCode,
+                         jboolean keyDown) {
+  remoting::ChromotingJniRuntime::GetInstance()->session()->SendKeyEvent(
+      keyCode, keyDown);
+}
+
+static void SendTextEvent(JNIEnv* env,
+                          jclass clazz,
+                          jstring text) {
+  remoting::ChromotingJniRuntime::GetInstance()->session()->SendTextEvent(
+      ConvertJavaStringToUTF8(env, text));
 }
 
 // ChromotingJniRuntime implementation.
diff --git a/remoting/host/chromoting_messages.h b/remoting/host/chromoting_messages.h
index f83e308..f28feaa 100644
--- a/remoting/host/chromoting_messages.h
+++ b/remoting/host/chromoting_messages.h
@@ -217,6 +217,11 @@
 IPC_MESSAGE_CONTROL1(ChromotingNetworkDesktopMsg_InjectKeyEvent,
                      std::string /* serialized_event */ )
 
+// Carries a keyboard event from the client to the desktop session agent.
+// |serialized_event| is a serialized protocol::TextEvent.
+IPC_MESSAGE_CONTROL1(ChromotingNetworkDesktopMsg_InjectTextEvent,
+                     std::string /* serialized_event */ )
+
 // Carries a mouse event from the client to the desktop session agent.
 // |serialized_event| is a serialized protocol::MouseEvent.
 IPC_MESSAGE_CONTROL1(ChromotingNetworkDesktopMsg_InjectMouseEvent,
diff --git a/remoting/host/constants_mac.cc b/remoting/host/constants_mac.cc
index 7491414..2d98723 100644
--- a/remoting/host/constants_mac.cc
+++ b/remoting/host/constants_mac.cc
@@ -7,6 +7,8 @@
 namespace remoting {
 
 #define SERVICE_NAME "org.chromium.chromoting"
+#define PREFPANE_BUNDLE_NAME "ChromeRemoteDesktop.prefPane"
+#define HOST_BUNDLE_NAME "ChromeRemoteDesktopHost.bundle"
 
 #define APPLICATIONS_DIR "/Applications/"
 #define HELPER_TOOLS_DIR "/Library/PrivilegedHelperTools/"
@@ -17,14 +19,14 @@
 
 const char kServiceName[] = SERVICE_NAME;
 
-const char kPrefPaneFileName[] = SERVICE_NAME ".prefPane";
-const char kPrefPaneFilePath[] = PREFERENCE_PANES_DIR SERVICE_NAME ".prefPane";
+const char kPrefPaneFileName[] = PREFPANE_BUNDLE_NAME;
+const char kPrefPaneFilePath[] = PREFERENCE_PANES_DIR PREFPANE_BUNDLE_NAME;
 
 const char kHostConfigFileName[] = SERVICE_NAME ".json";
 const char kHostConfigFilePath[] = HELPER_TOOLS_DIR SERVICE_NAME ".json";
 
 const char kHostHelperScriptPath[] = HELPER_TOOLS_DIR SERVICE_NAME ".me2me.sh";
-const char kHostBinaryPath[] = HELPER_TOOLS_DIR SERVICE_NAME ".me2me_host.app";
+const char kHostBinaryPath[] = HELPER_TOOLS_DIR HOST_BUNDLE_NAME;
 const char kHostEnabledPath[] = HELPER_TOOLS_DIR SERVICE_NAME ".me2me_enabled";
 
 const char kServicePlistPath[] = LAUNCH_AGENTS_DIR SERVICE_NAME ".plist";
diff --git a/remoting/host/desktop_session_agent.cc b/remoting/host/desktop_session_agent.cc
index 1597765..4f023a6 100644
--- a/remoting/host/desktop_session_agent.cc
+++ b/remoting/host/desktop_session_agent.cc
@@ -139,6 +139,8 @@
                           OnInjectClipboardEvent)
       IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InjectKeyEvent,
                           OnInjectKeyEvent)
+      IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InjectTextEvent,
+                          OnInjectTextEvent)
       IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_InjectMouseEvent,
                           OnInjectMouseEvent)
       IPC_MESSAGE_HANDLER(ChromotingNetworkDesktopMsg_SetScreenResolution,
@@ -459,6 +461,26 @@
   remote_input_filter_->InjectKeyEvent(event);
 }
 
+void DesktopSessionAgent::OnInjectTextEvent(
+    const std::string& serialized_event) {
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
+
+  protocol::TextEvent event;
+  if (!event.ParseFromString(serialized_event)) {
+    LOG(ERROR) << "Failed to parse protocol::TextEvent.";
+    return;
+  }
+
+  // InputStub implementations must verify events themselves, so we need only
+  // basic verification here. This matches HostEventDispatcher.
+  if (!event.has_text()) {
+    LOG(ERROR) << "Received invalid TextEvent.";
+    return;
+  }
+
+  remote_input_filter_->InjectTextEvent(event);
+}
+
 void DesktopSessionAgent::OnInjectMouseEvent(
     const std::string& serialized_event) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
diff --git a/remoting/host/desktop_session_agent.h b/remoting/host/desktop_session_agent.h
index 0421eeb..82c02fd 100644
--- a/remoting/host/desktop_session_agent.h
+++ b/remoting/host/desktop_session_agent.h
@@ -124,6 +124,7 @@
   // Handles event executor requests from the client.
   void OnInjectClipboardEvent(const std::string& serialized_event);
   void OnInjectKeyEvent(const std::string& serialized_event);
+  void OnInjectTextEvent(const std::string& serialized_event);
   void OnInjectMouseEvent(const std::string& serialized_event);
 
   // Handles ChromotingNetworkDesktopMsg_SetScreenResolution request from
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc
index 058a2f4..d077d5a 100644
--- a/remoting/host/desktop_session_proxy.cc
+++ b/remoting/host/desktop_session_proxy.cc
@@ -353,6 +353,19 @@
       new ChromotingNetworkDesktopMsg_InjectKeyEvent(serialized_event));
 }
 
+void DesktopSessionProxy::InjectTextEvent(const protocol::TextEvent& event) {
+  DCHECK(caller_task_runner_->BelongsToCurrentThread());
+
+  std::string serialized_event;
+  if (!event.SerializeToString(&serialized_event)) {
+    LOG(ERROR) << "Failed to serialize protocol::TextEvent.";
+    return;
+  }
+
+  SendToDesktop(
+      new ChromotingNetworkDesktopMsg_InjectTextEvent(serialized_event));
+}
+
 void DesktopSessionProxy::InjectMouseEvent(const protocol::MouseEvent& event) {
   DCHECK(caller_task_runner_->BelongsToCurrentThread());
 
diff --git a/remoting/host/desktop_session_proxy.h b/remoting/host/desktop_session_proxy.h
index 14f3ff7..1414c61 100644
--- a/remoting/host/desktop_session_proxy.h
+++ b/remoting/host/desktop_session_proxy.h
@@ -112,6 +112,7 @@
   // APIs used to implement the InputInjector interface.
   void InjectClipboardEvent(const protocol::ClipboardEvent& event);
   void InjectKeyEvent(const protocol::KeyEvent& event);
+  void InjectTextEvent(const protocol::TextEvent& event);
   void InjectMouseEvent(const protocol::MouseEvent& event);
   void StartInputInjector(scoped_ptr<protocol::ClipboardStub> client_clipboard);
 
diff --git a/remoting/host/gnubby_auth_handler_posix.cc b/remoting/host/gnubby_auth_handler_posix.cc
index c797cce..77938e0 100644
--- a/remoting/host/gnubby_auth_handler_posix.cc
+++ b/remoting/host/gnubby_auth_handler_posix.cc
@@ -6,7 +6,6 @@
 
 #include <unistd.h>
 #include <utility>
-#include <vector>
 
 #include "base/bind.h"
 #include "base/file_util.h"
@@ -17,7 +16,7 @@
 #include "base/values.h"
 #include "net/socket/unix_domain_socket_posix.h"
 #include "remoting/base/logging.h"
-#include "remoting/host/gnubby_util.h"
+#include "remoting/host/gnubby_socket.h"
 #include "remoting/proto/control.pb.h"
 #include "remoting/protocol/client_stub.h"
 
@@ -25,15 +24,14 @@
 
 namespace {
 
-const int kMaxRequestLength = 4096;
-
 const char kConnectionId[] = "connectionId";
 const char kControlMessage[] = "control";
 const char kControlOption[] = "option";
 const char kDataMessage[] = "data";
+const char kDataPayload[] = "data";
+const char kErrorMessage[] = "error";
 const char kGnubbyAuthMessage[] = "gnubby-auth";
 const char kGnubbyAuthV1[] = "auth-v1";
-const char kJSONMessage[] = "jsonMessage";
 const char kMessageType[] = "type";
 
 // The name of the socket to listen for gnubby requests on.
@@ -45,9 +43,8 @@
  public:
   explicit CompareSocket(net::StreamListenSocket* socket) : socket_(socket) {}
 
-  bool operator()(const std::pair<int, net::StreamListenSocket*> element)
-      const {
-    return socket_ == element.second;
+  bool operator()(const std::pair<int, GnubbySocket*> element) const {
+    return element.second->IsSocket(socket_);
   }
 
  private:
@@ -63,25 +60,28 @@
   return allowed;
 }
 
-// Returns the request data length from the first four data bytes.
-int GetRequestLength(const char* data) {
-  return ((data[0] & 255) << 24) + ((data[1] & 255) << 16) +
-         ((data[2] & 255) << 8) + (data[3] & 255) + 4;
+// Returns the command code (the first byte of the data) if it exists, or -1 if
+// the data is empty.
+unsigned int GetCommandCode(const std::string& data) {
+  return data.empty() ? -1 : static_cast<unsigned int>(data[0]);
 }
 
-// Returns true if the request data is complete (has at least as many bytes as
-// indicated by the size in the first four bytes plus four for the first bytes).
-bool IsRequestComplete(const char* data, int data_len) {
-  if (data_len < 4)
-    return false;
-  return GetRequestLength(data) <= data_len;
-}
+// Creates a string of byte data from a ListValue of numbers. Returns true if
+// all of the list elements are numbers.
+bool ConvertListValueToString(base::ListValue* bytes, std::string* out) {
+  out->clear();
 
-// Returns true if the request data size is bigger than the threshold.
-bool IsRequestTooLarge(const char* data, int data_len, int max_len) {
-  if (data_len < 4)
-    return false;
-  return GetRequestLength(data) > max_len;
+  unsigned int byte_count = bytes->GetSize();
+  if (byte_count != 0) {
+    out->reserve(byte_count);
+    for (unsigned int i = 0; i < byte_count; i++) {
+      int value;
+      if (!bytes->GetInteger(i, &value))
+        return false;
+      out->push_back(static_cast<char>(value));
+    }
+  }
+  return true;
 }
 
 }  // namespace
@@ -129,22 +129,28 @@
         LOG(ERROR) << "Invalid gnubby-auth control option";
       }
     } else if (type == kDataMessage) {
-      int connection_id;
-      std::string json_message;
-      if (client_message->GetInteger(kConnectionId, &connection_id) &&
-          client_message->GetString(kJSONMessage, &json_message)) {
-        ActiveSockets::iterator iter = active_sockets_.find(connection_id);
-        if (iter != active_sockets_.end()) {
-          HOST_LOG << "Sending gnubby response";
-
-          std::string response;
-          GetGnubbyResponseFromJson(json_message, &response);
-          iter->second->Send(response);
+      ActiveSockets::iterator iter = GetSocketForMessage(client_message);
+      if (iter != active_sockets_.end()) {
+        base::ListValue* bytes;
+        std::string response;
+        if (client_message->GetList(kDataPayload, &bytes) &&
+            ConvertListValueToString(bytes, &response)) {
+          HOST_LOG << "Sending gnubby response: " << GetCommandCode(response);
+          iter->second->SendResponse(response);
         } else {
-          LOG(ERROR) << "Received gnubby-auth data for unknown connection";
+          LOG(ERROR) << "Invalid gnubby data";
+          SendErrorAndCloseActiveSocket(iter);
         }
       } else {
-        LOG(ERROR) << "Invalid gnubby-auth data message";
+        LOG(ERROR) << "Unknown gnubby-auth data connection";
+      }
+    } else if (type == kErrorMessage) {
+      ActiveSockets::iterator iter = GetSocketForMessage(client_message);
+      if (iter != active_sockets_.end()) {
+        HOST_LOG << "Sending gnubby error";
+        SendErrorAndCloseActiveSocket(iter);
+      } else {
+        LOG(ERROR) << "Unknown gnubby-auth error connection";
       }
     } else {
       LOG(ERROR) << "Unknown gnubby-auth message type: " << type;
@@ -152,15 +158,20 @@
   }
 }
 
-void GnubbyAuthHandlerPosix::DeliverHostDataMessage(int connection_id,
-                                                    const std::string& data)
-    const {
+void GnubbyAuthHandlerPosix::DeliverHostDataMessage(
+    int connection_id,
+    const std::string& data) const {
   DCHECK(CalledOnValidThread());
 
   base::DictionaryValue request;
   request.SetString(kMessageType, kDataMessage);
   request.SetInteger(kConnectionId, connection_id);
-  request.SetString(kJSONMessage, data);
+
+  base::ListValue* bytes = new base::ListValue();
+  for (std::string::const_iterator i = data.begin(); i != data.end(); ++i) {
+    bytes->AppendInteger(static_cast<unsigned char>(*i));
+  }
+  request.Set(kDataPayload, bytes);
 
   std::string request_json;
   if (!base::JSONWriter::Write(&request, &request_json)) {
@@ -182,12 +193,31 @@
                       CompareSocket(socket)) != active_sockets_.end();
 }
 
+int GnubbyAuthHandlerPosix::GetConnectionIdForTesting(
+    net::StreamListenSocket* socket) const {
+  ActiveSockets::const_iterator iter = std::find_if(
+      active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket));
+  return iter->first;
+}
+
+GnubbySocket* GnubbyAuthHandlerPosix::GetGnubbySocketForTesting(
+    net::StreamListenSocket* socket) const {
+  ActiveSockets::const_iterator iter = std::find_if(
+      active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket));
+  return iter->second;
+}
+
 void GnubbyAuthHandlerPosix::DidAccept(
     net::StreamListenSocket* server,
     scoped_ptr<net::StreamListenSocket> socket) {
   DCHECK(CalledOnValidThread());
 
-  active_sockets_[++last_connection_id_] = socket.release();
+  int connection_id = ++last_connection_id_;
+  active_sockets_[connection_id] =
+      new GnubbySocket(socket.Pass(),
+                       base::Bind(&GnubbyAuthHandlerPosix::RequestTimedOut,
+                                  base::Unretained(this),
+                                  connection_id));
 }
 
 void GnubbyAuthHandlerPosix::DidRead(net::StreamListenSocket* socket,
@@ -195,39 +225,20 @@
                                      int len) {
   DCHECK(CalledOnValidThread());
 
-  ActiveSockets::iterator socket_iter = std::find_if(
+  ActiveSockets::iterator iter = std::find_if(
       active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket));
-  if (socket_iter != active_sockets_.end()) {
-    int connection_id = socket_iter->first;
-
-    ActiveRequests::iterator request_iter =
-        active_requests_.find(connection_id);
-    if (request_iter != active_requests_.end()) {
-      std::vector<char>& saved_vector = request_iter->second;
-      if (IsRequestTooLarge(
-              saved_vector.data(), saved_vector.size(), kMaxRequestLength)) {
-        // We can't close a StreamListenSocket; throw away everything but the
-        // size bytes.
-        saved_vector.resize(4);
-        return;
-      }
-      saved_vector.insert(saved_vector.end(), data, data + len);
-
-      if (IsRequestComplete(saved_vector.data(), saved_vector.size())) {
-        ProcessGnubbyRequest(
-            connection_id, saved_vector.data(), saved_vector.size());
-        active_requests_.erase(request_iter);
-      }
-    } else if (IsRequestComplete(data, len)) {
-      ProcessGnubbyRequest(connection_id, data, len);
-    } else {
-      if (IsRequestTooLarge(data, len, kMaxRequestLength)) {
-        // Only save the size bytes.
-        active_requests_[connection_id] = std::vector<char>(data, data + 4);
-      } else {
-        active_requests_[connection_id] = std::vector<char>(data, data + len);
-      }
+  if (iter != active_sockets_.end()) {
+    GnubbySocket* gnubby_socket = iter->second;
+    gnubby_socket->AddRequestData(data, len);
+    if (gnubby_socket->IsRequestTooLarge()) {
+      SendErrorAndCloseActiveSocket(iter);
+    } else if (gnubby_socket->IsRequestComplete()) {
+      std::string request_data;
+      gnubby_socket->GetAndClearRequestData(&request_data);
+      ProcessGnubbyRequest(iter->first, request_data);
     }
+  } else {
+    LOG(ERROR) << "Received data for unknown connection";
   }
 }
 
@@ -237,8 +248,6 @@
   ActiveSockets::iterator iter = std::find_if(
       active_sockets_.begin(), active_sockets_.end(), CompareSocket(socket));
   if (iter != active_sockets_.end()) {
-    active_requests_.erase(iter->first);
-
     delete iter->second;
     active_sockets_.erase(iter);
   }
@@ -264,16 +273,35 @@
   }
 }
 
-void GnubbyAuthHandlerPosix::ProcessGnubbyRequest(int connection_id,
-                                                  const char* data,
-                                                  int data_len) {
-  std::string json;
-  if (GetJsonFromGnubbyRequest(data, data_len, &json)) {
-    HOST_LOG << "Received gnubby request";
-    DeliverHostDataMessage(connection_id, json);
-  } else {
-    LOG(ERROR) << "Could not decode gnubby request";
+void GnubbyAuthHandlerPosix::ProcessGnubbyRequest(
+    int connection_id,
+    const std::string& request_data) {
+  HOST_LOG << "Received gnubby request: " << GetCommandCode(request_data);
+  DeliverHostDataMessage(connection_id, request_data);
+}
+
+GnubbyAuthHandlerPosix::ActiveSockets::iterator
+GnubbyAuthHandlerPosix::GetSocketForMessage(base::DictionaryValue* message) {
+  int connection_id;
+  if (message->GetInteger(kConnectionId, &connection_id)) {
+    return active_sockets_.find(connection_id);
   }
+  return active_sockets_.end();
+}
+
+void GnubbyAuthHandlerPosix::SendErrorAndCloseActiveSocket(
+    const ActiveSockets::iterator& iter) {
+  iter->second->SendSshError();
+
+  delete iter->second;
+  active_sockets_.erase(iter);
+}
+
+void GnubbyAuthHandlerPosix::RequestTimedOut(int connection_id) {
+  HOST_LOG << "Gnubby request timed out";
+  ActiveSockets::iterator iter = active_sockets_.find(connection_id);
+  if (iter != active_sockets_.end())
+    SendErrorAndCloseActiveSocket(iter);
 }
 
 }  // namespace remoting
diff --git a/remoting/host/gnubby_auth_handler_posix.h b/remoting/host/gnubby_auth_handler_posix.h
index ea0e3b61..db38886 100644
--- a/remoting/host/gnubby_auth_handler_posix.h
+++ b/remoting/host/gnubby_auth_handler_posix.h
@@ -7,19 +7,24 @@
 
 #include <map>
 #include <string>
-#include <vector>
 
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
 #include "net/socket/stream_listen_socket.h"
 #include "remoting/host/gnubby_auth_handler.h"
 
+namespace base {
+class DictionaryValue;
+}  // namespace base
+
 namespace remoting {
 
 namespace protocol {
 class ClientStub;
 }  // namespace protocol
 
+class GnubbySocket;
+
 class GnubbyAuthHandlerPosix : public GnubbyAuthHandler,
                                public base::NonThreadSafe,
                                public net::StreamListenSocket::Delegate {
@@ -28,8 +33,13 @@
   virtual ~GnubbyAuthHandlerPosix();
 
   bool HasActiveSocketForTesting(net::StreamListenSocket* socket) const;
+  int GetConnectionIdForTesting(net::StreamListenSocket* socket) const;
+  GnubbySocket* GetGnubbySocketForTesting(
+      net::StreamListenSocket* socket) const;
 
  private:
+  typedef std::map<int, GnubbySocket*> ActiveSockets;
+
   // GnubbyAuthHandler interface.
   virtual void DeliverClientMessage(const std::string& message) OVERRIDE;
   virtual void DeliverHostDataMessage(int connection_id,
@@ -47,7 +57,16 @@
   void CreateAuthorizationSocket();
 
   // Process a gnubby request.
-  void ProcessGnubbyRequest(int connection_id, const char* data, int data_len);
+  void ProcessGnubbyRequest(int connection_id, const std::string& request_data);
+
+  // Gets an active socket iterator for the connection id in |message|.
+  ActiveSockets::iterator GetSocketForMessage(base::DictionaryValue* message);
+
+  // Send an error and close an active socket.
+  void SendErrorAndCloseActiveSocket(const ActiveSockets::iterator& iter);
+
+  // A request timed out.
+  void RequestTimedOut(int connection_id);
 
   // Interface through which communication with the client occurs.
   protocol::ClientStub* client_stub_;
@@ -59,13 +78,8 @@
   int last_connection_id_;
 
   // Sockets by connection id used to process gnubbyd requests.
-  typedef std::map<int, net::StreamListenSocket*> ActiveSockets;
   ActiveSockets active_sockets_;
 
-  // Partial gnubbyd request data by connection id.
-  typedef std::map<int, std::vector<char> > ActiveRequests;
-  ActiveRequests active_requests_;
-
   DISALLOW_COPY_AND_ASSIGN(GnubbyAuthHandlerPosix);
 };
 
diff --git a/remoting/host/gnubby_auth_handler_posix_unittest.cc b/remoting/host/gnubby_auth_handler_posix_unittest.cc
index c3a8c9f..1c9bd86 100644
--- a/remoting/host/gnubby_auth_handler_posix_unittest.cc
+++ b/remoting/host/gnubby_auth_handler_posix_unittest.cc
@@ -2,9 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/message_loop/message_loop.h"
 #include "base/strings/stringprintf.h"
+#include "base/timer/mock_timer.h"
 #include "net/socket/stream_listen_socket.h"
 #include "remoting/host/gnubby_auth_handler_posix.h"
+#include "remoting/host/gnubby_socket.h"
 #include "remoting/protocol/protocol_mock_objects.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -66,6 +69,8 @@
   // Mock client stub.
   MockClientStub client_stub_;
 
+  base::MessageLoop message_loop_;
+
  private:
   void OnConnect(int result);
 };
@@ -78,17 +83,19 @@
 
 MATCHER_P2(EqualsDataMessage, id, data, "") {
   std::string connection_id = base::StringPrintf("\"connectionId\":%d", id);
-  std::string json_message = base::StringPrintf("\"jsonMessage\":\"%s\"", data);
+  std::string data_message = base::StringPrintf("\"data\":%s", data);
 
   return (arg.type() == "gnubby-auth" &&
           arg.data().find("\"type\":\"data\"") != std::string::npos &&
           arg.data().find(connection_id) != std::string::npos &&
-          arg.data().find(json_message) != std::string::npos);
+          arg.data().find(data_message) != std::string::npos);
 }
 
 TEST_F(GnubbyAuthHandlerPosixTest, HostDataMessageDelivered) {
+  // Expects a JSON array of the ASCII character codes for "test_msg".
   EXPECT_CALL(client_stub_,
-              DeliverHostMessage(EqualsDataMessage(42, "test_msg")));
+              DeliverHostMessage(
+                  EqualsDataMessage(42, "[116,101,115,116,95,109,115,103]")));
 
   auth_handler_->DeliverHostDataMessage(42, "test_msg");
 }
@@ -109,7 +116,8 @@
   net::StreamListenSocket* socket = new MockStreamListenSocket(delegate_);
 
   delegate_->DidAccept(NULL, make_scoped_ptr(socket));
-  delegate_->DidRead(socket, reinterpret_cast<const char*>(request_data),
+  delegate_->DidRead(socket,
+                     reinterpret_cast<const char*>(request_data),
                      sizeof(request_data));
 }
 
@@ -120,9 +128,38 @@
 
   delegate_->DidAccept(NULL, make_scoped_ptr(socket));
   for (unsigned int i = 0; i < sizeof(request_data); ++i) {
-    delegate_->DidRead(socket,
-                       reinterpret_cast<const char *>(request_data + i), 1);
+    delegate_->DidRead(
+        socket, reinterpret_cast<const char*>(request_data + i), 1);
   }
 }
 
+TEST_F(GnubbyAuthHandlerPosixTest, DidReadTimeout) {
+  net::StreamListenSocket* socket = new MockStreamListenSocket(delegate_);
+
+  delegate_->DidAccept(NULL, make_scoped_ptr(socket));
+  ASSERT_TRUE(auth_handler_posix_->HasActiveSocketForTesting(socket));
+
+  base::MockTimer* mock_timer = new base::MockTimer(false, false);
+  auth_handler_posix_->GetGnubbySocketForTesting(socket)
+      ->SetTimerForTesting(scoped_ptr<base::Timer>(mock_timer));
+  delegate_->DidRead(socket, reinterpret_cast<const char*>(request_data), 1);
+  mock_timer->Fire();
+
+  ASSERT_FALSE(auth_handler_posix_->HasActiveSocketForTesting(socket));
+}
+
+TEST_F(GnubbyAuthHandlerPosixTest, ClientErrorMessageDelivered) {
+  net::StreamListenSocket* socket = new MockStreamListenSocket(delegate_);
+
+  delegate_->DidAccept(NULL, make_scoped_ptr(socket));
+
+  std::string error_json = base::StringPrintf(
+      "{\"type\":\"error\",\"connectionId\":%d}",
+      auth_handler_posix_->GetConnectionIdForTesting(socket));
+
+  ASSERT_TRUE(auth_handler_posix_->HasActiveSocketForTesting(socket));
+  auth_handler_->DeliverClientMessage(error_json);
+  ASSERT_FALSE(auth_handler_posix_->HasActiveSocketForTesting(socket));
+}
+
 }  // namespace remoting
diff --git a/remoting/host/gnubby_socket.cc b/remoting/host/gnubby_socket.cc
new file mode 100644
index 0000000..40cb7d4
--- /dev/null
+++ b/remoting/host/gnubby_socket.cc
@@ -0,0 +1,117 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "remoting/host/gnubby_socket.h"
+
+#include "base/macros.h"
+#include "base/timer/timer.h"
+#include "net/socket/stream_listen_socket.h"
+
+namespace remoting {
+
+namespace {
+
+const size_t kRequestSizeBytes = 4;
+const size_t kMaxRequestLength = 16384;
+const unsigned int kRequestTimeoutSeconds = 60;
+
+// SSH Failure Code
+const char kSshError[] = {0x05};
+
+}  // namespace
+
+GnubbySocket::GnubbySocket(scoped_ptr<net::StreamListenSocket> socket,
+                           const base::Closure& timeout_callback)
+    : socket_(socket.Pass()) {
+  timer_.reset(new base::Timer(false, false));
+  timer_->Start(FROM_HERE,
+                base::TimeDelta::FromSeconds(kRequestTimeoutSeconds),
+                timeout_callback);
+}
+
+GnubbySocket::~GnubbySocket() {}
+
+void GnubbySocket::AddRequestData(const char* data, int data_len) {
+  DCHECK(CalledOnValidThread());
+
+  request_data_.insert(request_data_.end(), data, data + data_len);
+  ResetTimer();
+}
+
+void GnubbySocket::GetAndClearRequestData(std::string* data_out) {
+  DCHECK(CalledOnValidThread());
+  DCHECK(IsRequestComplete() && !IsRequestTooLarge());
+
+  // The request size is not part of the data; don't send it.
+  data_out->assign(request_data_.begin() + kRequestSizeBytes,
+                   request_data_.end());
+  request_data_.clear();
+}
+
+bool GnubbySocket::IsRequestComplete() const {
+  DCHECK(CalledOnValidThread());
+
+  if (request_data_.size() < kRequestSizeBytes)
+    return false;
+  return GetRequestLength() <= request_data_.size();
+}
+
+bool GnubbySocket::IsRequestTooLarge() const {
+  DCHECK(CalledOnValidThread());
+
+  if (request_data_.size() < kRequestSizeBytes)
+    return false;
+  return GetRequestLength() > kMaxRequestLength;
+}
+
+void GnubbySocket::SendResponse(const std::string& response_data) {
+  DCHECK(CalledOnValidThread());
+
+  socket_->Send(GetResponseLengthAsBytes(response_data));
+  socket_->Send(response_data);
+  ResetTimer();
+}
+
+void GnubbySocket::SendSshError() {
+  DCHECK(CalledOnValidThread());
+
+  SendResponse(std::string(kSshError, arraysize(kSshError)));
+}
+
+bool GnubbySocket::IsSocket(net::StreamListenSocket* socket) const {
+  return socket == socket_.get();
+}
+
+void GnubbySocket::SetTimerForTesting(scoped_ptr<base::Timer> timer) {
+  timer->Start(FROM_HERE, timer_->GetCurrentDelay(), timer_->user_task());
+  timer_ = timer.Pass();
+}
+
+size_t GnubbySocket::GetRequestLength() const {
+  DCHECK(request_data_.size() >= kRequestSizeBytes);
+
+  return ((request_data_[0] & 255) << 24) + ((request_data_[1] & 255) << 16) +
+         ((request_data_[2] & 255) << 8) + (request_data_[3] & 255) +
+         kRequestSizeBytes;
+}
+
+std::string GnubbySocket::GetResponseLengthAsBytes(
+    const std::string& response) const {
+  std::string response_len;
+  int len = response.size();
+
+  response_len.push_back((len >> 24) & 255);
+  response_len.push_back((len >> 16) & 255);
+  response_len.push_back((len >> 8) & 255);
+  response_len.push_back(len & 255);
+
+  return response_len;
+}
+
+void GnubbySocket::ResetTimer() {
+  if (timer_->IsRunning())
+    timer_->Reset();
+}
+
+}  // namespace remoting
diff --git a/remoting/host/gnubby_socket.h b/remoting/host/gnubby_socket.h
new file mode 100644
index 0000000..d119762
--- /dev/null
+++ b/remoting/host/gnubby_socket.h
@@ -0,0 +1,80 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef REMOTING_HOST_GNUBBY_SOCKET_H_
+#define REMOTING_HOST_GNUBBY_SOCKET_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+
+namespace base {
+class Timer;
+}  // namespace base
+
+namespace net {
+class StreamListenSocket;
+}  // namespace net
+
+namespace remoting {
+
+// Class that manages a socket used for gnubby requests.
+class GnubbySocket : public base::NonThreadSafe {
+ public:
+  GnubbySocket(scoped_ptr<net::StreamListenSocket> socket,
+               const base::Closure& timeout_callback);
+  ~GnubbySocket();
+
+  // Adds data to the current request.
+  void AddRequestData(const char* data, int data_len);
+
+  // Gets the current request data and clears it.
+  void GetAndClearRequestData(std::string* data_out);
+
+  // Returns true if the current request is complete.
+  bool IsRequestComplete() const;
+
+  // Returns true if the stated request size is larger than the allowed maximum.
+  bool IsRequestTooLarge() const;
+
+  // Sends response data to the socket.
+  void SendResponse(const std::string& data);
+
+  // Sends an SSH error code to the socket.
+  void SendSshError();
+
+  // Returns true if |socket| is the same one owned by this object.
+  bool IsSocket(net::StreamListenSocket* socket) const;
+
+  // Sets a timer for testing.
+  void SetTimerForTesting(scoped_ptr<base::Timer> timer);
+
+ private:
+  // Returns the stated request length.
+  size_t GetRequestLength() const;
+
+  // Returns the response length bytes.
+  std::string GetResponseLengthAsBytes(const std::string& response) const;
+
+  // Resets the socket activity timer.
+  void ResetTimer();
+
+  // The socket.
+  scoped_ptr<net::StreamListenSocket> socket_;
+
+  // Request data.
+  std::vector<char> request_data_;
+
+  // The activity timer.
+  scoped_ptr<base::Timer> timer_;
+
+  DISALLOW_COPY_AND_ASSIGN(GnubbySocket);
+};
+
+}  // namespace remoting
+
+#endif  // REMOTING_HOST_GNUBBY_SOCKET_H_
diff --git a/remoting/host/gnubby_util.cc b/remoting/host/gnubby_util.cc
deleted file mode 100644
index 126584b..0000000
--- a/remoting/host/gnubby_util.cc
+++ /dev/null
@@ -1,347 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/host/gnubby_util.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_writer.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/values.h"
-#include "remoting/base/logging.h"
-
-namespace remoting {
-
-namespace {
-
-// Failure code to use when the code from the webapp response isn't available.
-const int kGnubbyResponseFail = 1;
-
-const int kSsh2AgentcGnubbySignRequest = 101;   // 0x65
-const int kSsh2AgentcGnubbySignResponse = 102;  // 0x66
-
-const char kAppIdHash[] = "appIdHash";
-const char kChallengeHash[] = "challengeHash";
-const char kCode[] = "code";
-const char kKeyHandle[] = "keyHandle";
-const char kResponseData[] = "responseData";
-const char kSignData[] = "signData";
-const char kSignReply[] = "sign_helper_reply";
-const char kSignRequest[] = "sign_helper_request";
-const char kSignatureData[] = "signatureData";
-const char kTimeout[] = "timeout";
-const char kType[] = "type";
-const char kVersion[] = "version";
-
-void WebSafeBase64Encode(const std::string& data, std::string* encoded_data) {
-  base::Base64Encode(data, encoded_data);
-
-  std::replace(encoded_data->begin(), encoded_data->end(), '+', '-');
-  std::replace(encoded_data->begin(), encoded_data->end(), '/', '_');
-  encoded_data->erase(
-      std::remove(encoded_data->begin(), encoded_data->end(), '='),
-      encoded_data->end());
-}
-
-void WebSafeBase64Decode(const std::string& encoded_data, std::string* data) {
-  std::string temp(encoded_data);
-  std::replace(temp.begin(), temp.end(), '-', '+');
-  std::replace(temp.begin(), temp.end(), '_', '/');
-
-  int num_equals = temp.length() % 3;
-  temp.append(num_equals, '=');
-
-  base::Base64Decode(temp, data);
-}
-
-bool DecodeDataFromDictionary(const base::DictionaryValue& dictionary,
-                              const std::string& path,
-                              std::string* data) {
-  std::string encoded_data;
-  bool result = dictionary.GetString(path, &encoded_data);
-  if (result) {
-    WebSafeBase64Decode(encoded_data, data);
-  } else {
-    LOG(ERROR) << "Failed to get dictionary value " << path;
-    data->erase();
-  }
-  return result;
-}
-
-// Class to read gnubby blob data.
-class BlobReader {
- public:
-  // Create a blob with the given data. Does not take ownership of the memory.
-  BlobReader(const uint8_t* data, size_t data_len);
-  virtual ~BlobReader();
-
-  // Read a byte from the blob. Returns true on success.
-  bool ReadByte(uint8_t* value);
-
-  // Read a four byte size from the blob. Returns true on success.
-  bool ReadSize(size_t* value);
-
-  // Read a size-prefixed blob. Returns true on success.
-  bool ReadBlobReader(scoped_ptr<BlobReader>* value);
-
-  // Read a size-prefixed string from the blob. Returns true on success.
-  bool ReadString(std::string* value);
-
- private:
-  // The blob data.
-  const uint8_t* data_;
-
-  // The length of the blob data.
-  size_t data_len_;
-
-  // The current read index.
-  size_t index_;
-
-  DISALLOW_COPY_AND_ASSIGN(BlobReader);
-};
-
-// Class to write gnubby blob data.
-class BlobWriter {
- public:
-  BlobWriter();
-  virtual ~BlobWriter();
-
-  // Write a byte to the blob.
-  void WriteByte(uint8_t value);
-
-  // Write a four byte size to the blob.
-  void WriteSize(size_t value);
-
-  // Write a size-prefixed blob to the blob.
-  void WriteBlobWriter(const BlobWriter& value);
-
-  // Write a size-prefixed string to the blob.
-  void WriteString(const std::string& value);
-
-  // Returns the blob data.
-  std::string GetData() const;
-
- private:
-  // The blob data.
-  std::vector<uint8_t> data_;
-
-  DISALLOW_COPY_AND_ASSIGN(BlobWriter);
-};
-
-BlobReader::BlobReader(const uint8_t* data, size_t data_len)
-    : data_(data), data_len_(data_len), index_(0) {}
-
-BlobReader::~BlobReader() {}
-
-bool BlobReader::ReadByte(uint8_t* value) {
-  if (data_len_ < index_) {
-    *value = 0;
-    return false;
-  }
-  *value = data_[index_++];
-  return true;
-}
-
-bool BlobReader::ReadSize(size_t* value) {
-  if (data_len_ < (index_ + 4)) {
-    *value = 0;
-    return false;
-  }
-  *value = ((data_[index_] & 255) << 24) + ((data_[index_ + 1] & 255) << 16) +
-           ((data_[index_ + 2] & 255) << 8) + (data_[index_ + 3] & 255);
-  index_ += 4;
-  return true;
-}
-
-bool BlobReader::ReadBlobReader(scoped_ptr<BlobReader>* value) {
-  size_t blob_size;
-  if (!ReadSize(&blob_size) || data_len_ < (index_ + blob_size)) {
-    value->reset();
-    return 0;
-  }
-  value->reset(new BlobReader(data_ + index_, blob_size));
-  index_ += blob_size;
-  return true;
-}
-
-bool BlobReader::ReadString(std::string* value) {
-  size_t length;
-  if (!ReadSize(&length) || data_len_ < (index_ + length)) {
-    value->erase();
-    return 0;
-  }
-  value->assign(reinterpret_cast<const char*>(data_ + index_), length);
-  index_ += length;
-  return true;
-}
-
-BlobWriter::BlobWriter() {}
-
-BlobWriter::~BlobWriter() {}
-
-void BlobWriter::WriteByte(uint8_t value) { data_.push_back(value); }
-
-void BlobWriter::WriteSize(size_t value) {
-  data_.push_back((value & 0xff000000) >> 24);
-  data_.push_back((value & 0xff0000) >> 16);
-  data_.push_back((value & 0xff00) >> 8);
-  data_.push_back(value & 0xff);
-}
-
-void BlobWriter::WriteBlobWriter(const BlobWriter& value) {
-  WriteString(value.GetData());
-}
-
-void BlobWriter::WriteString(const std::string& value) {
-  WriteSize(value.length());
-  data_.insert(data_.end(), value.begin(), value.end());
-}
-
-std::string BlobWriter::GetData() const {
-  return std::string(reinterpret_cast<const char*>(data_.data()), data_.size());
-}
-
-}  // namespace
-
-bool GetJsonFromGnubbyRequest(const char* data,
-                              int data_len,
-                              std::string* json) {
-  json->empty();
-
-  BlobReader ssh_request(reinterpret_cast<const uint8_t*>(data), data_len);
-  scoped_ptr<BlobReader> blob;
-  if (!ssh_request.ReadBlobReader(&blob))
-    return false;
-
-  uint8_t cmd = 0;
-  uint8_t timeout = 0;
-  size_t request_count = 0;
-  bool result = blob->ReadByte(&cmd);
-  result = result && blob->ReadByte(&timeout);
-  result = result && blob->ReadSize(&request_count);
-  if (!result || cmd != kSsh2AgentcGnubbySignRequest)
-    return false;
-
-  base::DictionaryValue request;
-  request.SetString(kType, kSignRequest);
-  request.SetInteger(kTimeout, timeout);
-
-  base::ListValue* sign_requests = new base::ListValue();
-  request.Set(kSignData, sign_requests);
-
-  for (unsigned int i = 0; i < request_count; ++i) {
-    scoped_ptr<BlobReader> sign_request;
-    std::string version;
-    std::string challenge_hash;
-    std::string origin_hash;
-    std::string key_handle;
-
-    if (!(blob->ReadBlobReader(&sign_request) &&
-          sign_request->ReadString(&version) &&
-          sign_request->ReadString(&challenge_hash) &&
-          sign_request->ReadString(&origin_hash) &&
-          sign_request->ReadString(&key_handle)))
-      return false;
-
-    std::string encoded_origin_hash;
-    std::string encoded_challenge_hash;
-    std::string encoded_key_handle;
-
-    WebSafeBase64Encode(origin_hash, &encoded_origin_hash);
-    WebSafeBase64Encode(challenge_hash, &encoded_challenge_hash);
-    WebSafeBase64Encode(key_handle, &encoded_key_handle);
-
-    base::DictionaryValue* request = new base::DictionaryValue();
-    request->SetString(kAppIdHash, encoded_origin_hash);
-    request->SetString(kChallengeHash, encoded_challenge_hash);
-    request->SetString(kKeyHandle, encoded_key_handle);
-    request->SetString(kVersion, version);
-    sign_requests->Append(request);
-  }
-
-  base::JSONWriter::Write(&request, json);
-  return true;
-}
-
-void GetGnubbyResponseFromJson(const std::string& json, std::string* data) {
-  data->erase();
-
-  scoped_ptr<base::Value> json_value(base::JSONReader::Read(json));
-  base::DictionaryValue* reply;
-  if (json_value && json_value->GetAsDictionary(&reply)) {
-    BlobWriter response;
-    response.WriteByte(kSsh2AgentcGnubbySignResponse);
-
-    int code;
-    if (reply->GetInteger(kCode, &code) && code == 0) {
-      response.WriteSize(code);
-
-      std::string type;
-      if (!(reply->GetString(kType, &type) && type == kSignReply)) {
-        LOG(ERROR) << "Invalid type";
-        return;
-      }
-
-      base::DictionaryValue* reply_data;
-      if (!reply->GetDictionary(kResponseData, &reply_data)) {
-        LOG(ERROR) << "Invalid response data";
-        return;
-      }
-
-      BlobWriter tmp;
-      std::string version;
-      if (reply_data->GetString(kVersion, &version)) {
-        tmp.WriteString(version);
-      } else {
-        tmp.WriteSize(0);
-      }
-
-      std::string challenge_hash;
-      if (!DecodeDataFromDictionary(
-               *reply_data, kChallengeHash, &challenge_hash)) {
-        LOG(ERROR) << "Invalid challenge hash";
-        return;
-      }
-      tmp.WriteString(challenge_hash);
-
-      std::string app_id_hash;
-      if (!DecodeDataFromDictionary(*reply_data, kAppIdHash, &app_id_hash)) {
-        LOG(ERROR) << "Invalid app id hash";
-        return;
-      }
-      tmp.WriteString(app_id_hash);
-
-      std::string key_handle;
-      if (!DecodeDataFromDictionary(*reply_data, kKeyHandle, &key_handle)) {
-        LOG(ERROR) << "Invalid key handle";
-        return;
-      }
-      tmp.WriteString(key_handle);
-
-      std::string signature_data;
-      if (!DecodeDataFromDictionary(
-               *reply_data, kSignatureData, &signature_data)) {
-        LOG(ERROR) << "Invalid signature data";
-        return;
-      }
-      tmp.WriteString(signature_data);
-
-      response.WriteBlobWriter(tmp);
-    } else {
-      response.WriteSize(kGnubbyResponseFail);
-    }
-
-    BlobWriter ssh_response;
-    ssh_response.WriteBlobWriter(response);
-    data->assign(ssh_response.GetData());
-  } else {
-    LOG(ERROR) << "Could not parse json: " << json;
-  }
-}
-
-}  // namespace remoting
diff --git a/remoting/host/gnubby_util.h b/remoting/host/gnubby_util.h
deleted file mode 100644
index 0d888d6..0000000
--- a/remoting/host/gnubby_util.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef REMOTING_HOST_GNUBBY_UTIL_H_
-#define REMOTING_HOST_GNUBBY_UTIL_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-
-namespace base {
-
-class DictionaryValue;
-
-}  // namespace base
-
-namespace remoting {
-
-// Get a gnubbyd sign request json string from a request blob.
-bool GetJsonFromGnubbyRequest(const char* data,
-                              int data_len,
-                              std::string* json);
-
-// Get response blob data from a gnubbyd sign reply json string.
-void GetGnubbyResponseFromJson(const std::string& json, std::string* data);
-
-}  // namespace remoting
-
-#endif  // REMOTING_HOST_GNUBBY_UTIL_H_
diff --git a/remoting/host/gnubby_util_unittest.cc b/remoting/host/gnubby_util_unittest.cc
deleted file mode 100644
index e788788..0000000
--- a/remoting/host/gnubby_util_unittest.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "remoting/host/gnubby_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace remoting {
-
-namespace {
-
-// Test gnubby request data.
-const unsigned char request_data[] = {
-    0x00, 0x00, 0x00, 0x9a, 0x65, 0x1e, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-    0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x90,
-    0x24, 0x71, 0xf8, 0xf2, 0xe5, 0xdf, 0x7f, 0x81, 0xc7, 0x49, 0xc4, 0xa3,
-    0x58, 0x5c, 0xf6, 0xcc, 0x40, 0x14, 0x28, 0x0c, 0xa0, 0xfa, 0x03, 0x18,
-    0x38, 0xd8, 0x7d, 0x77, 0x2b, 0x3a, 0x00, 0x00, 0x00, 0x20, 0x64, 0x46,
-    0x47, 0x2f, 0xdf, 0x6e, 0xed, 0x7b, 0xf3, 0xc3, 0x37, 0x20, 0xf2, 0x36,
-    0x67, 0x6c, 0x36, 0xe1, 0xb4, 0x5e, 0xbe, 0x04, 0x85, 0xdb, 0x89, 0xa3,
-    0xcd, 0xfd, 0xd2, 0x4b, 0xd6, 0x9f, 0x00, 0x00, 0x00, 0x40, 0x38, 0x35,
-    0x05, 0x75, 0x1d, 0x13, 0x6e, 0xb3, 0x6b, 0x1d, 0x29, 0xae, 0xd3, 0x43,
-    0xe6, 0x84, 0x8f, 0xa3, 0x9d, 0x65, 0x4e, 0x2f, 0x57, 0xe3, 0xf6, 0xe6,
-    0x20, 0x3c, 0x00, 0xc6, 0xe1, 0x73, 0x34, 0xe2, 0x23, 0x99, 0xc4, 0xfa,
-    0x91, 0xc2, 0xd5, 0x97, 0xc1, 0x8b, 0xd0, 0x3c, 0x13, 0xba, 0xf0, 0xd7,
-    0x5e, 0xa3, 0xbc, 0x02, 0x5b, 0xec, 0xe4, 0x4b, 0xae, 0x0e, 0xf2, 0xbd,
-    0xc8, 0xaa};
-
-// Expected json for gnubby request data.
-const char expected_json[] =
-    "{\"signData\":[{\"appIdHash\":\"ZEZHL99u7Xvzwzcg8jZnbDbhtF6-BIXbiaPN_dJL1p"
-    "8\",\"challengeHash\":\"YJAkcfjy5d9_gcdJxKNYXPbMQBQoDKD6Axg42H13Kzo\",\"ke"
-    "yHandle\":\"ODUFdR0TbrNrHSmu00PmhI-jnWVOL1fj9uYgPADG4XM04iOZxPqRwtWXwYvQPB"
-    "O68Ndeo7wCW-zkS64O8r3Iqg\",\"version\":\"\"}],\"timeout\":30,\"type\":\"si"
-    "gn_helper_request\"}";
-
-// Test json response.
-const char response_json[] =
-    "{\"type\":\"sign_helper_reply\",\"code\":0,\"responseData\":{\"appIdHash\""
-    ":\"ZEZHL99u7Xvzwzcg8jZnbDbhtF6-BIXbiaPN_dJL1p8\",\"challengeHash\":\"YJAkc"
-    "fjy5d9_gcdJxKNYXPbMQBQoDKD6Axg42H13Kzo\",\"keyHandle\":\"ODUFdR0TbrNrHSmu0"
-    "0PmhI-jnWVOL1fj9uYgPADG4XM04iOZxPqRwtWXwYvQPBO68Ndeo7wCW-zkS64O8r3Iqg\",\""
-    "signatureData\":\"AeW_wWGxdN0LGtX_E7s5CsMAH95-my58SN1HW8qrCygF257EWRzbsOpO"
-    "mTtM9N71lGd3B3hTVPASkcpQZzhQcQNIObY_vjO-aliOHb937DWU\"}}";
-
-// Expected data for json response.
-const unsigned char expected_data[] = {
-    0x00, 0x00, 0x00, 0xee, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0xe5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x60, 0x90, 0x24,
-    0x71, 0xf8, 0xf2, 0xe5, 0xdf, 0x7f, 0x81, 0xc7, 0x49, 0xc4, 0xa3, 0x58,
-    0x5c, 0xf6, 0xcc, 0x40, 0x14, 0x28, 0x0c, 0xa0, 0xfa, 0x03, 0x18, 0x38,
-    0xd8, 0x7d, 0x77, 0x2b, 0x3a, 0x00, 0x00, 0x00, 0x20, 0x64, 0x46, 0x47,
-    0x2f, 0xdf, 0x6e, 0xed, 0x7b, 0xf3, 0xc3, 0x37, 0x20, 0xf2, 0x36, 0x67,
-    0x6c, 0x36, 0xe1, 0xb4, 0x5e, 0xbe, 0x04, 0x85, 0xdb, 0x89, 0xa3, 0xcd,
-    0xfd, 0xd2, 0x4b, 0xd6, 0x9f, 0x00, 0x00, 0x00, 0x40, 0x38, 0x35, 0x05,
-    0x75, 0x1d, 0x13, 0x6e, 0xb3, 0x6b, 0x1d, 0x29, 0xae, 0xd3, 0x43, 0xe6,
-    0x84, 0x8f, 0xa3, 0x9d, 0x65, 0x4e, 0x2f, 0x57, 0xe3, 0xf6, 0xe6, 0x20,
-    0x3c, 0x00, 0xc6, 0xe1, 0x73, 0x34, 0xe2, 0x23, 0x99, 0xc4, 0xfa, 0x91,
-    0xc2, 0xd5, 0x97, 0xc1, 0x8b, 0xd0, 0x3c, 0x13, 0xba, 0xf0, 0xd7, 0x5e,
-    0xa3, 0xbc, 0x02, 0x5b, 0xec, 0xe4, 0x4b, 0xae, 0x0e, 0xf2, 0xbd, 0xc8,
-    0xaa, 0x00, 0x00, 0x00, 0x51, 0x01, 0xe5, 0xbf, 0xc1, 0x61, 0xb1, 0x74,
-    0xdd, 0x0b, 0x1a, 0xd5, 0xff, 0x13, 0xbb, 0x39, 0x0a, 0xc3, 0x00, 0x1f,
-    0xde, 0x7e, 0x9b, 0x2e, 0x7c, 0x48, 0xdd, 0x47, 0x5b, 0xca, 0xab, 0x0b,
-    0x28, 0x05, 0xdb, 0x9e, 0xc4, 0x59, 0x1c, 0xdb, 0xb0, 0xea, 0x4e, 0x99,
-    0x3b, 0x4c, 0xf4, 0xde, 0xf5, 0x94, 0x67, 0x77, 0x07, 0x78, 0x53, 0x54,
-    0xf0, 0x12, 0x91, 0xca, 0x50, 0x67, 0x38, 0x50, 0x71, 0x03, 0x48, 0x39,
-    0xb6, 0x3f, 0xbe, 0x33, 0xbe, 0x6a, 0x58, 0x8e, 0x1d, 0xbf, 0x77, 0xec,
-    0x35, 0x94};
-
-}  // namespace
-
-class GnubbyUtilsTest : public testing::Test {
- public:
-  GnubbyUtilsTest() {}
-};
-
-TEST_F(GnubbyUtilsTest, DataToJson) {
-  std::string actual_json;
-  GetJsonFromGnubbyRequest(reinterpret_cast<const char*>(request_data),
-                           sizeof(request_data),
-                           &actual_json);
-
-  EXPECT_EQ(expected_json, actual_json);
-}
-
-TEST_F(GnubbyUtilsTest, JsonToData) {
-  std::string actual_data;
-  GetGnubbyResponseFromJson(response_json, &actual_data);
-
-  EXPECT_EQ(std::string(reinterpret_cast<const char*>(expected_data),
-                        sizeof(expected_data)),
-            actual_data);
-}
-
-}  // namespace remoting
diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h
index e8bad3e..d365695 100644
--- a/remoting/host/host_mock_objects.h
+++ b/remoting/host/host_mock_objects.h
@@ -106,6 +106,7 @@
   MOCK_METHOD1(InjectClipboardEvent,
                void(const protocol::ClipboardEvent& event));
   MOCK_METHOD1(InjectKeyEvent, void(const protocol::KeyEvent& event));
+  MOCK_METHOD1(InjectTextEvent, void(const protocol::TextEvent& event));
   MOCK_METHOD1(InjectMouseEvent, void(const protocol::MouseEvent& event));
   MOCK_METHOD1(StartPtr,
                void(protocol::ClipboardStub* client_clipboard));
diff --git a/remoting/host/input_injector_linux.cc b/remoting/host/input_injector_linux.cc
index f6f80a2..c9763b2 100644
--- a/remoting/host/input_injector_linux.cc
+++ b/remoting/host/input_injector_linux.cc
@@ -27,6 +27,7 @@
 
 using protocol::ClipboardEvent;
 using protocol::KeyEvent;
+using protocol::TextEvent;
 using protocol::MouseEvent;
 
 // Pixel-to-wheel-ticks conversion ratio used by GTK.
@@ -47,6 +48,7 @@
 
   // InputStub interface.
   virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
 
   // InputInjector interface.
@@ -66,6 +68,7 @@
 
     // Mirrors the InputStub interface.
     void InjectKeyEvent(const KeyEvent& event);
+    void InjectTextEvent(const TextEvent& event);
     void InjectMouseEvent(const MouseEvent& event);
 
     // Mirrors the InputInjector interface.
@@ -148,6 +151,10 @@
   core_->InjectKeyEvent(event);
 }
 
+void InputInjectorLinux::InjectTextEvent(const TextEvent& event) {
+  core_->InjectTextEvent(event);
+}
+
 void InputInjectorLinux::InjectMouseEvent(const MouseEvent& event) {
   core_->InjectMouseEvent(event);
 }
@@ -253,6 +260,10 @@
   XFlush(display_);
 }
 
+void InputInjectorLinux::Core::InjectTextEvent(const TextEvent& event) {
+  NOTIMPLEMENTED();
+}
+
 InputInjectorLinux::Core::~Core() {
   CHECK(pressed_keys_.empty());
 }
diff --git a/remoting/host/input_injector_mac.cc b/remoting/host/input_injector_mac.cc
index 51fb09c..30ea580 100644
--- a/remoting/host/input_injector_mac.cc
+++ b/remoting/host/input_injector_mac.cc
@@ -15,6 +15,7 @@
 #include "base/mac/scoped_cftyperef.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
 #include "remoting/host/clipboard.h"
 #include "remoting/proto/internal.pb.h"
 #include "remoting/protocol/message_decoder.h"
@@ -30,6 +31,20 @@
   value = set_bit ? (value | bit) : (value & ~bit);
 }
 
+void CreateAndPostKeyEvent(int keycode,
+                           bool pressed,
+                           int flags,
+                           const base::string16& unicode) {
+  base::ScopedCFTypeRef<CGEventRef> eventRef(
+      CGEventCreateKeyboardEvent(NULL, keycode, pressed));
+  if (eventRef) {
+    CGEventSetFlags(eventRef, flags);
+    if (!unicode.empty())
+      CGEventKeyboardSetUnicodeString(eventRef, unicode.size(), &(unicode[0]));
+    CGEventPost(kCGSessionEventTap, eventRef);
+  }
+}
+
 // This value is not defined. Give it the obvious name so that if it is ever
 // added there will be a handy compilation error to remind us to remove this
 // definition.
@@ -37,6 +52,7 @@
 
 using protocol::ClipboardEvent;
 using protocol::KeyEvent;
+using protocol::TextEvent;
 using protocol::MouseEvent;
 
 // A class to generate events on Mac.
@@ -51,6 +67,7 @@
 
   // InputStub interface.
   virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
 
   // InputInjector interface.
@@ -68,6 +85,7 @@
 
     // Mirrors the InputStub interface.
     void InjectKeyEvent(const KeyEvent& event);
+    void InjectTextEvent(const TextEvent& event);
     void InjectMouseEvent(const MouseEvent& event);
 
     // Mirrors the InputInjector interface.
@@ -111,6 +129,10 @@
   core_->InjectKeyEvent(event);
 }
 
+void InputInjectorMac::InjectTextEvent(const TextEvent& event) {
+  core_->InjectTextEvent(event);
+}
+
 void InputInjectorMac::InjectMouseEvent(const MouseEvent& event) {
   core_->InjectMouseEvent(event);
 }
@@ -187,20 +209,23 @@
     SetOrClearBit(right_modifiers_, kCGEventFlagMaskAlternate, event.pressed());
   }
 
-  base::ScopedCFTypeRef<CGEventRef> eventRef(
-      CGEventCreateKeyboardEvent(NULL, keycode, event.pressed()));
+  // In addition to the modifier keys pressed right now, we also need to set
+  // AlphaShift if caps lock was active at the client (Mac ignores NumLock).
+  uint64_t flags = left_modifiers_ | right_modifiers_;
+  if (event.lock_states() & protocol::KeyEvent::LOCK_STATES_CAPSLOCK)
+    flags |= kCGEventFlagMaskAlphaShift;
 
-  if (eventRef) {
-    // In addition to the modifier keys pressed right now, we also need to set
-    // AlphaShift if caps lock was active at the client (Mac ignores NumLock).
-    uint64_t flags = left_modifiers_ | right_modifiers_;
-    if (event.lock_states() & protocol::KeyEvent::LOCK_STATES_CAPSLOCK)
-      flags |= kCGEventFlagMaskAlphaShift;
-    CGEventSetFlags(eventRef, flags);
+  CreateAndPostKeyEvent(keycode, event.pressed(), flags, base::string16());
+}
 
-    // Post the event to the current session.
-    CGEventPost(kCGSessionEventTap, eventRef);
-  }
+void InputInjectorMac::Core::InjectTextEvent(const TextEvent& event) {
+  DCHECK(event.has_text());
+  base::string16 text = base::UTF8ToUTF16(event.text());
+
+  // Applications that ignore UnicodeString field will see the text event as
+  // Space key.
+  CreateAndPostKeyEvent(kVK_Space, true, 0, text);
+  CreateAndPostKeyEvent(kVK_Space, false, 0, text);
 }
 
 void InputInjectorMac::Core::InjectMouseEvent(const MouseEvent& event) {
@@ -305,8 +330,7 @@
   clipboard_->Stop();
 }
 
-InputInjectorMac::Core::~Core() {
-}
+InputInjectorMac::Core::~Core() {}
 
 }  // namespace
 
diff --git a/remoting/host/input_injector_win.cc b/remoting/host/input_injector_win.cc
index ebdf8ef..235f45e 100644
--- a/remoting/host/input_injector_win.cc
+++ b/remoting/host/input_injector_win.cc
@@ -11,6 +11,8 @@
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
 #include "remoting/base/util.h"
 #include "remoting/host/clipboard.h"
 #include "remoting/proto/event.pb.h"
@@ -20,8 +22,34 @@
 
 namespace {
 
+// Helper used to call SendInput() API.
+void SendKeyboardInput(uint32_t flags, uint16_t scancode) {
+  // Populate a Windows INPUT structure for the event.
+  INPUT input;
+  memset(&input, 0, sizeof(input));
+  input.type = INPUT_KEYBOARD;
+  input.ki.time = 0;
+  input.ki.dwFlags = flags;
+  input.ki.wScan = scancode;
+
+  if ((flags & KEYEVENTF_UNICODE) == 0) {
+    // Windows scancodes are only 8-bit, so store the low-order byte into the
+    // event and set the extended flag if any high-order bits are set. The only
+    // high-order values we should see are 0xE0 or 0xE1. The extended bit
+    // usually distinguishes keys with the same meaning, e.g. left & right
+    // shift.
+    input.ki.wScan &= 0xFF;
+    if ((scancode & 0xFF00) != 0x0000)
+      input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
+  }
+
+  if (SendInput(1, &input, sizeof(INPUT)) == 0)
+    LOG_GETLASTERROR(ERROR) << "Failed to inject a key event";
+}
+
 using protocol::ClipboardEvent;
 using protocol::KeyEvent;
+using protocol::TextEvent;
 using protocol::MouseEvent;
 
 // A class to generate events on Windows.
@@ -36,6 +64,7 @@
 
   // InputStub interface.
   virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
 
   // InputInjector interface.
@@ -54,6 +83,7 @@
 
     // Mirrors the InputStub interface.
     void InjectKeyEvent(const KeyEvent& event);
+    void InjectTextEvent(const TextEvent& event);
     void InjectMouseEvent(const MouseEvent& event);
 
     // Mirrors the InputInjector interface.
@@ -66,6 +96,7 @@
     virtual ~Core();
 
     void HandleKey(const KeyEvent& event);
+    void HandleText(const TextEvent& event);
     void HandleMouse(const MouseEvent& event);
 
     scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
@@ -98,6 +129,10 @@
   core_->InjectKeyEvent(event);
 }
 
+void InputInjectorWin::InjectTextEvent(const TextEvent& event) {
+  core_->InjectTextEvent(event);
+}
+
 void InputInjectorWin::InjectMouseEvent(const MouseEvent& event) {
   core_->InjectMouseEvent(event);
 }
@@ -136,6 +171,16 @@
   HandleKey(event);
 }
 
+void InputInjectorWin::Core::InjectTextEvent(const TextEvent& event) {
+  if (!main_task_runner_->BelongsToCurrentThread()) {
+    main_task_runner_->PostTask(
+        FROM_HERE, base::Bind(&Core::InjectTextEvent, this, event));
+    return;
+  }
+
+  HandleText(event);
+}
+
 void InputInjectorWin::Core::InjectMouseEvent(const MouseEvent& event) {
   if (!main_task_runner_->BelongsToCurrentThread()) {
     main_task_runner_->PostTask(
@@ -167,13 +212,11 @@
   clipboard_->Stop();
 }
 
-InputInjectorWin::Core::~Core() {
-}
+InputInjectorWin::Core::~Core() {}
 
 void InputInjectorWin::Core::HandleKey(const KeyEvent& event) {
   // HostEventDispatcher should filter events missing the pressed field.
-  if (!event.has_pressed() || !event.has_usb_keycode())
-    return;
+  DCHECK(event.has_pressed() && event.has_usb_keycode());
 
   // Reset the system idle suspend timeout.
   SetThreadExecutionState(ES_SYSTEM_REQUIRED);
@@ -187,25 +230,20 @@
   if (scancode == key_converter->InvalidNativeKeycode())
     return;
 
-  // Populate the a Windows INPUT structure for the event.
-  INPUT input;
-  memset(&input, 0, sizeof(input));
-  input.type = INPUT_KEYBOARD;
-  input.ki.time = 0;
-  input.ki.dwFlags = KEYEVENTF_SCANCODE;
-  if (!event.pressed())
-    input.ki.dwFlags |= KEYEVENTF_KEYUP;
+  uint32_t flags = KEYEVENTF_SCANCODE | (event.pressed() ? 0 : KEYEVENTF_KEYUP);
+  SendKeyboardInput(flags, scancode);
+}
 
-  // Windows scancodes are only 8-bit, so store the low-order byte into the
-  // event and set the extended flag if any high-order bits are set. The only
-  // high-order values we should see are 0xE0 or 0xE1. The extended bit usually
-  // distinguishes keys with the same meaning, e.g. left & right shift.
-  input.ki.wScan = scancode & 0xFF;
-  if ((scancode & 0xFF00) != 0x0000)
-    input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
+void InputInjectorWin::Core::HandleText(const TextEvent& event) {
+  // HostEventDispatcher should filter events missing the pressed field.
+  DCHECK(event.has_text());
 
-  if (SendInput(1, &input, sizeof(INPUT)) == 0)
-    LOG_GETLASTERROR(ERROR) << "Failed to inject a key event";
+  base::string16 text = base::UTF8ToUTF16(event.text());
+  for (base::string16::const_iterator it = text.begin();
+       it != text.end(); ++it)  {
+    SendKeyboardInput(KEYEVENTF_UNICODE, *it);
+    SendKeyboardInput(KEYEVENTF_UNICODE | KEYEVENTF_KEYUP, *it);
+  }
 }
 
 void InputInjectorWin::Core::HandleMouse(const MouseEvent& event) {
diff --git a/remoting/host/installer/linux/Makefile b/remoting/host/installer/linux/Makefile
index ee29505..f136621 100644
--- a/remoting/host/installer/linux/Makefile
+++ b/remoting/host/installer/linux/Makefile
@@ -16,9 +16,9 @@
 ME2ME_DEBUGFILE = $(ME2ME_PROGNAME).debug
 START_PROGNAME = $(BUILD_DIR)/remoting_start_host
 START_DEBUGFILE = $(START_PROGNAME).debug
-ME2ME_NM_PROGNAME = $(BUILD_DIR)/remoting_native_messaging_host
+ME2ME_NM_PROGNAME = $(BUILD_DIR)/native_messaging_host
 ME2ME_NM_DEBUGFILE = $(ME2ME_NM_PROGNAME).debug
-REMOTE_ASSISTANCE_PROGNAME = $(BUILD_DIR)/remoting_it2me_native_messaging_host
+REMOTE_ASSISTANCE_PROGNAME = $(BUILD_DIR)/remote_assistance_host
 REMOTE_ASSISTANCE_DEBUGFILE = $(REMOTE_ASSISTANCE_PROGNAME).debug
 
 all:
diff --git a/remoting/host/installer/mac/ChromotingHostService.pkgproj b/remoting/host/installer/mac/ChromotingHostService.pkgproj
index 4da41aa..06fec05 100644
--- a/remoting/host/installer/mac/ChromotingHostService.pkgproj
+++ b/remoting/host/installer/mac/ChromotingHostService.pkgproj
@@ -321,7 +321,7 @@
 										<key>GID</key>
 										<integer>0</integer>
 										<key>PATH</key>
-										<string>PreferencePanes/org.chromium.chromoting.prefPane</string>
+										<string>PreferencePanes/@@PREFPANE_BUNDLE_NAME@@</string>
 										<key>PATH_TYPE</key>
 										<integer>1</integer>
 										<key>PERMISSIONS</key>
@@ -404,7 +404,7 @@
 										<key>GID</key>
 										<integer>0</integer>
 										<key>PATH</key>
-										<string>PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app</string>
+										<string>PrivilegedHelperTools/@@HOST_BUNDLE_NAME@@</string>
 										<key>PATH_TYPE</key>
 										<integer>1</integer>
 										<key>PERMISSIONS</key>
diff --git a/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh b/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh
index bc3ceec..24a229e 100755
--- a/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh
+++ b/remoting/host/installer/mac/PrivilegedHelperTools/org.chromium.chromoting.me2me.sh
@@ -7,12 +7,14 @@
 # Version = @@VERSION@@
 
 NAME=org.chromium.chromoting
+HOST_BUNDLE_NAME=ChromeRemoteDesktopHost.bundle
+PREFPANE_BUNDLE_NAME=ChromeRemoteDesktop.prefPane
 CONFIG_DIR=/Library/PrivilegedHelperTools
-HOST_EXE=$CONFIG_DIR/$NAME.me2me_host.app/Contents/MacOS/remoting_me2me_host
-PLIST_FILE=$CONFIG_DIR/$NAME.me2me_host.app/Contents/Info.plist
 ENABLED_FILE=$CONFIG_DIR/$NAME.me2me_enabled
 CONFIG_FILE=$CONFIG_DIR/$NAME.json
-PREF_PANE_BUNDLE=/Library/PreferencePanes/$NAME.prefPane
+HOST_EXE=$CONFIG_DIR/$HOST_BUNDLE_NAME/Contents/MacOS/remoting_me2me_host
+PLIST_FILE=$CONFIG_DIR/$HOST_BUNDLE_NAME/Contents/Info.plist
+PREF_PANE_BUNDLE=/Library/PreferencePanes/$PREFPANE_BUNDLE_NAME
 
 # The exit code returned by 'wait' when a process is terminated by SIGTERM.
 SIGTERM_EXIT_CODE=143
diff --git a/remoting/host/installer/mac/do_signing.props b/remoting/host/installer/mac/do_signing.props
index ac6b07c..d5ecce8 100644
--- a/remoting/host/installer/mac/do_signing.props
+++ b/remoting/host/installer/mac/do_signing.props
@@ -1,4 +1,8 @@
-HOST_UNINSTALLER_NAME=@@HOST_UNINSTALLER_NAME@@
-HOST_PKG=@@HOST_PKG@@
-DMG_VOLUME_NAME=@@DMG_VOLUME_NAME@@
 DMG_FILE_NAME=@@DMG_FILE_NAME@@
+DMG_VOLUME_NAME=@@DMG_VOLUME_NAME@@
+HOST_BUNDLE_NAME=@@HOST_BUNDLE_NAME@@
+HOST_PKG=@@HOST_PKG@@
+HOST_UNINSTALLER_NAME=@@HOST_UNINSTALLER_NAME@@
+NATIVE_MESSAGING_HOST_BUNDLE_NAME=@@NATIVE_MESSAGING_HOST_BUNDLE_NAME@@
+PREFPANE_BUNDLE_NAME=@@PREFPANE_BUNDLE_NAME@@
+REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=@@REMOTE_ASSISTANCE_HOST_BUNDLE_NAME@@
diff --git a/remoting/host/installer/mac/do_signing.sh b/remoting/host/installer/mac/do_signing.sh
index ef9b85d..2e756f9 100755
--- a/remoting/host/installer/mac/do_signing.sh
+++ b/remoting/host/installer/mac/do_signing.sh
@@ -30,26 +30,36 @@
 
   # Individually load the properties for this build. Don't 'source' the file
   # to guard against code accidentally being added to the props file.
-  HOST_UNINSTALLER_NAME=$(read_property "HOST_UNINSTALLER_NAME")
-  HOST_PKG=$(read_property "HOST_PKG")
   DMG_VOLUME_NAME=$(read_property "DMG_VOLUME_NAME")
   DMG_FILE_NAME=$(read_property "DMG_FILE_NAME")
+  HOST_BUNDLE_NAME=$(read_property "HOST_BUNDLE_NAME")
+  HOST_PKG=$(read_property "HOST_PKG")
+  HOST_UNINSTALLER_NAME=$(read_property "HOST_UNINSTALLER_NAME")
+  NATIVE_MESSAGING_HOST_BUNDLE_NAME=$(read_property\
+    "NATIVE_MESSAGING_HOST_BUNDLE_NAME")
+  PREFPANE_BUNDLE_NAME=$(read_property "PREFPANE_BUNDLE_NAME")
+  REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=$(read_property\
+    "REMOTE_ASSISTANCE_HOST_BUNDLE_NAME")
 
   # Binaries to sign.
-  ME2ME_HOST='PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app'
-  ME2ME_NM_HOST="${ME2ME_HOST}/Contents/MacOS/native_messaging_host"
-  IT2ME_NM_HOST="${ME2ME_HOST}/Contents/MacOS/remote_assistance_host"
+  ME2ME_HOST="PrivilegedHelperTools/${HOST_BUNDLE_NAME}"
+  ME2ME_NM_HOST="PrivilegedHelperTools/${HOST_BUNDLE_NAME}/Contents/MacOS/"`
+                `"${NATIVE_MESSAGING_HOST_BUNDLE_NAME}/Contents/MacOS/"`
+                `"native_messaging_host"
+  IT2ME_NM_HOST="PrivilegedHelperTools/${HOST_BUNDLE_NAME}/Contents/MacOS/"`
+                `"${REMOTE_ASSISTANCE_HOST_BUNDLE_NAME}/Contents/MacOS/"`
+                `"remote_assistance_host"
   UNINSTALLER="Applications/${HOST_UNINSTALLER_NAME}.app"
-  PREFPANE='PreferencePanes/org.chromium.chromoting.prefPane'
+  PREFPANE="PreferencePanes/${PREFPANE_BUNDLE_NAME}"
 
   # The Chromoting Host installer is a meta-package that consists of 3
   # components:
   #  * Chromoting Host Service package
   #  * Chromoting Host Uninstaller package
   #  * Keystone package (GoogleSoftwareUpdate - for Official builds only)
-  PKGPROJ_HOST='ChromotingHost.pkgproj'
-  PKGPROJ_HOST_SERVICE='ChromotingHostService.pkgproj'
-  PKGPROJ_HOST_UNINSTALLER='ChromotingHostUninstaller.pkgproj'
+  PKGPROJ_HOST="ChromotingHost.pkgproj"
+  PKGPROJ_HOST_SERVICE="ChromotingHostService.pkgproj"
+  PKGPROJ_HOST_UNINSTALLER="ChromotingHostUninstaller.pkgproj"
 
   # Final (user-visible) pkg name.
   PKG_FINAL="${HOST_PKG}.pkg"
@@ -93,7 +103,7 @@
 read_property() {
   local property="${1}"
   local filename="${PROPS_FILENAME}"
-  echo `grep "${property}" "${filename}" | tail -n 1 | cut -d "=" -f2-`
+  echo `grep "\<${property}\>=" "${filename}" | tail -n 1 | cut -d "=" -f2-`
 }
 
 verify_clean_dir() {
diff --git a/remoting/host/ipc_desktop_environment_unittest.cc b/remoting/host/ipc_desktop_environment_unittest.cc
index 5bea812..7e31688 100644
--- a/remoting/host/ipc_desktop_environment_unittest.cc
+++ b/remoting/host/ipc_desktop_environment_unittest.cc
@@ -337,7 +337,7 @@
 
 InputInjector* IpcDesktopEnvironmentTest::CreateInputInjector() {
   EXPECT_TRUE(remote_input_injector_ == NULL);
-  remote_input_injector_ = new MockInputInjector();
+  remote_input_injector_ = new testing::StrictMock<MockInputInjector>();
 
   EXPECT_CALL(*remote_input_injector_, StartPtr(_));
   return remote_input_injector_;
@@ -426,14 +426,6 @@
   // Run the message loop until the desktop is attached.
   setup_run_loop_->Run();
 
-  // Input injector should receive no events.
-  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
-      .Times(0);
-
   // Stop the test.
   DeleteDesktopEnvironment();
 
@@ -456,14 +448,6 @@
   // Run the message loop until the desktop is attached.
   setup_run_loop_->Run();
 
-  // Input injector should receive no events.
-  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
-      .Times(0);
-
   // Stop the test when the first frame is captured.
   EXPECT_CALL(screen_capturer_callback_, OnCaptureCompleted(_))
       .WillOnce(DoAll(
@@ -499,14 +483,6 @@
   CreateDesktopProcess();
   setup_run_loop_->Run();
 
-  // Input injector should receive no events.
-  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
-      .Times(0);
-
   // Stop the test.
   DeleteDesktopEnvironment();
 
@@ -539,10 +515,6 @@
       .Times(1)
       .WillOnce(Invoke(this,
                        &IpcDesktopEnvironmentTest::ReflectClipboardEvent));
-  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
-      .Times(0);
 
   // Send a clipboard event.
   protocol::ClipboardEvent event;
@@ -570,14 +542,10 @@
   setup_run_loop_->Run();
 
   // Expect a single key event.
-  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
-      .Times(0);
   EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
       .Times(AtLeast(1))
       .WillRepeatedly(InvokeWithoutArgs(
           this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
-  EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
-      .Times(0);
 
   // Send a key event.
   protocol::KeyEvent event;
@@ -590,6 +558,36 @@
   main_run_loop_.Run();
 }
 
+// Tests injection of text events.
+TEST_F(IpcDesktopEnvironmentTest, InjectTextEvent) {
+  scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
+      new protocol::MockClipboardStub());
+  EXPECT_CALL(*clipboard_stub, InjectClipboardEvent(_))
+      .Times(0);
+
+  // Start the input injector and screen capturer.
+  input_injector_->Start(clipboard_stub.PassAs<protocol::ClipboardStub>());
+  video_capturer_->Start(&screen_capturer_callback_);
+
+  // Run the message loop until the desktop is attached.
+  setup_run_loop_->Run();
+
+  // Expect a single text event.
+  EXPECT_CALL(*remote_input_injector_, InjectTextEvent(_))
+      .Times(AtLeast(1))
+      .WillRepeatedly(InvokeWithoutArgs(
+          this, &IpcDesktopEnvironmentTest::DeleteDesktopEnvironment));
+
+  // Send a text event.
+  protocol::TextEvent event;
+  event.set_text("hello");
+  input_injector_->InjectTextEvent(event);
+
+  task_runner_ = NULL;
+  io_task_runner_ = NULL;
+  main_run_loop_.Run();
+}
+
 // Tests injection of mouse events.
 TEST_F(IpcDesktopEnvironmentTest, InjectMouseEvent) {
   scoped_ptr<protocol::MockClipboardStub> clipboard_stub(
@@ -605,10 +603,6 @@
   setup_run_loop_->Run();
 
   // Expect a single mouse event.
-  EXPECT_CALL(*remote_input_injector_, InjectClipboardEvent(_))
-      .Times(0);
-  EXPECT_CALL(*remote_input_injector_, InjectKeyEvent(_))
-      .Times(0);
   EXPECT_CALL(*remote_input_injector_, InjectMouseEvent(_))
       .Times(1)
       .WillOnce(InvokeWithoutArgs(
diff --git a/remoting/host/ipc_input_injector.cc b/remoting/host/ipc_input_injector.cc
index 7e63a4e..fd347e7 100644
--- a/remoting/host/ipc_input_injector.cc
+++ b/remoting/host/ipc_input_injector.cc
@@ -25,6 +25,10 @@
   desktop_session_proxy_->InjectKeyEvent(event);
 }
 
+void IpcInputInjector::InjectTextEvent(const protocol::TextEvent& event) {
+  desktop_session_proxy_->InjectTextEvent(event);
+}
+
 void IpcInputInjector::InjectMouseEvent(const protocol::MouseEvent& event) {
   desktop_session_proxy_->InjectMouseEvent(event);
 }
diff --git a/remoting/host/ipc_input_injector.h b/remoting/host/ipc_input_injector.h
index 1bfdd3c..9174ca3 100644
--- a/remoting/host/ipc_input_injector.h
+++ b/remoting/host/ipc_input_injector.h
@@ -27,6 +27,7 @@
 
   // InputStub interface.
   virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const protocol::TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE;
 
   // InputInjector interface.
diff --git a/remoting/host/it2me/remote_assistance_host-Info.plist b/remoting/host/it2me/remote_assistance_host-Info.plist
new file mode 100644
index 0000000..f714913
--- /dev/null
+++ b/remoting/host/it2me/remote_assistance_host-Info.plist
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>English</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIconFile</key>
+  <string>remote_assistance_host</string>
+  <key>CFBundleIdentifier</key>
+  <string>BUNDLE_ID</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>remote_assistance_host</string>
+  <key>CFBundlePackageType</key>
+  <string>APPL</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>VERSION_FULL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>VERSION_SHORT</string>
+  <key>LSMinimumSystemVersion</key>
+  <string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
+  <key>NSPrincipalClass</key>
+  <string>CrApplication</string>
+  <key>LSUIElement</key>
+  <string>1</string>
+  <key>BreakpadProduct</key>
+  <string>Chromoting_Mac</string>
+  <key>BreakpadVersion</key>
+  <string>VERSION_FULL</string>
+</dict>
+</plist>
diff --git a/remoting/host/it2me/remote_assistance_host-InfoPlist.strings.jinja2 b/remoting/host/it2me/remote_assistance_host-InfoPlist.strings.jinja2
new file mode 100644
index 0000000..4a650d8
--- /dev/null
+++ b/remoting/host/it2me/remote_assistance_host-InfoPlist.strings.jinja2
@@ -0,0 +1 @@
+NSHumanReadableCopyright = "{% trans %}COPYRIGHT{% endtrans %}";
diff --git a/remoting/host/remote_input_filter.cc b/remoting/host/remote_input_filter.cc
index 73e9898..2b28334 100644
--- a/remoting/host/remote_input_filter.cc
+++ b/remoting/host/remote_input_filter.cc
@@ -75,6 +75,12 @@
   event_tracker_->InjectKeyEvent(event);
 }
 
+void RemoteInputFilter::InjectTextEvent(const protocol::TextEvent& event) {
+  if (ShouldIgnoreInput())
+    return;
+  event_tracker_->InjectTextEvent(event);
+}
+
 void RemoteInputFilter::InjectMouseEvent(const protocol::MouseEvent& event) {
   if (ShouldIgnoreInput())
     return;
diff --git a/remoting/host/remote_input_filter.h b/remoting/host/remote_input_filter.h
index 20b5db6..0c26af6 100644
--- a/remoting/host/remote_input_filter.h
+++ b/remoting/host/remote_input_filter.h
@@ -34,6 +34,7 @@
 
   // InputStub overrides.
   virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const protocol::TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE;
 
  private:
diff --git a/remoting/host/setup/me2me_native_messaging_host_main.cc b/remoting/host/setup/me2me_native_messaging_host_main.cc
index 59f198b..5e0e0e2 100644
--- a/remoting/host/setup/me2me_native_messaging_host_main.cc
+++ b/remoting/host/setup/me2me_native_messaging_host_main.cc
@@ -10,10 +10,16 @@
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "net/url_request/url_fetcher.h"
+#include "remoting/base/breakpad.h"
 #include "remoting/host/host_exit_codes.h"
 #include "remoting/host/logging.h"
 #include "remoting/host/pairing_registry_delegate.h"
 #include "remoting/host/setup/me2me_native_messaging_host.h"
+#include "remoting/host/usage_stats_consent.h"
+
+#if defined(OS_MACOSX)
+#include "base/mac/scoped_nsautorelease_pool.h"
+#endif  // defined(OS_MACOSX)
 
 #if defined(OS_WIN)
 #include "base/win/registry.h"
@@ -54,6 +60,20 @@
 #endif  // defined(OS_WIN)
 
 int StartMe2MeNativeMessagingHost() {
+#if defined(OS_MACOSX)
+  // Needed so we don't leak objects when threads are created.
+  base::mac::ScopedNSAutoreleasePool pool;
+#endif  // defined(OS_MACOSX)
+
+#if defined(REMOTING_ENABLE_BREAKPAD)
+  // Initialize Breakpad as early as possible. On Mac the command-line needs to
+  // be initialized first, so that the preference for crash-reporting can be
+  // looked up in the config file.
+  if (IsUsageStatsAllowed()) {
+    InitializeCrashReporting();
+  }
+#endif  // defined(REMOTING_ENABLE_BREAKPAD)
+
   // Mac OS X requires that the main thread be a UI message loop in order to
   // receive distributed notifications from the System Preferences pane. An
   // IO thread is needed for the pairing registry and URL context getter.
diff --git a/remoting/host/setup/native_messaging_host-Info.plist b/remoting/host/setup/native_messaging_host-Info.plist
new file mode 100644
index 0000000..fe01256
--- /dev/null
+++ b/remoting/host/setup/native_messaging_host-Info.plist
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>English</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIconFile</key>
+  <string>native_messaging_host</string>
+  <key>CFBundleIdentifier</key>
+  <string>BUNDLE_ID</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>native_messaging_host</string>
+  <key>CFBundlePackageType</key>
+  <string>APPL</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>VERSION_FULL</string>
+  <key>CFBundleShortVersionString</key>
+  <string>VERSION_SHORT</string>
+  <key>LSMinimumSystemVersion</key>
+  <string>${MACOSX_DEPLOYMENT_TARGET}.0</string>
+  <key>NSPrincipalClass</key>
+  <string>CrApplication</string>
+  <key>LSUIElement</key>
+  <string>1</string>
+  <key>BreakpadProduct</key>
+  <string>Chromoting_Mac</string>
+  <key>BreakpadVersion</key>
+  <string>VERSION_FULL</string>
+</dict>
+</plist>
diff --git a/remoting/host/setup/native_messaging_host-InfoPlist.strings.jinja2 b/remoting/host/setup/native_messaging_host-InfoPlist.strings.jinja2
new file mode 100644
index 0000000..4a650d8
--- /dev/null
+++ b/remoting/host/setup/native_messaging_host-InfoPlist.strings.jinja2
@@ -0,0 +1 @@
+NSHumanReadableCopyright = "{% trans %}COPYRIGHT{% endtrans %}";
diff --git a/remoting/host/win/session_input_injector.cc b/remoting/host/win/session_input_injector.cc
index 8f7a366..2c4ee23 100644
--- a/remoting/host/win/session_input_injector.cc
+++ b/remoting/host/win/session_input_injector.cc
@@ -40,8 +40,9 @@
 namespace remoting {
 
 using protocol::ClipboardEvent;
-using protocol::MouseEvent;
 using protocol::KeyEvent;
+using protocol::MouseEvent;
+using protocol::TextEvent;
 
 class SessionInputInjectorWin::Core
     : public base::RefCountedThreadSafe<SessionInputInjectorWin::Core>,
@@ -63,6 +64,7 @@
 
   // protocol::InputStub implementation.
   virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const protocol::TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE;
 
  private:
@@ -165,6 +167,17 @@
   nested_executor_->InjectKeyEvent(event);
 }
 
+void SessionInputInjectorWin::Core::InjectTextEvent(const TextEvent& event) {
+  if (!input_task_runner_->BelongsToCurrentThread()) {
+    input_task_runner_->PostTask(
+        FROM_HERE, base::Bind(&Core::InjectTextEvent, this, event));
+    return;
+  }
+
+  SwitchToInputDesktop();
+  nested_executor_->InjectTextEvent(event);
+}
+
 void SessionInputInjectorWin::Core::InjectMouseEvent(const MouseEvent& event) {
   if (!input_task_runner_->BelongsToCurrentThread()) {
     input_task_runner_->PostTask(
@@ -217,6 +230,11 @@
   core_->InjectKeyEvent(event);
 }
 
+void SessionInputInjectorWin::InjectTextEvent(
+    const protocol::TextEvent& event) {
+  core_->InjectTextEvent(event);
+}
+
 void SessionInputInjectorWin::InjectMouseEvent(
     const protocol::MouseEvent& event) {
   core_->InjectMouseEvent(event);
diff --git a/remoting/host/win/session_input_injector.h b/remoting/host/win/session_input_injector.h
index 9fcff40..9c9443c 100644
--- a/remoting/host/win/session_input_injector.h
+++ b/remoting/host/win/session_input_injector.h
@@ -41,6 +41,7 @@
 
   // protocol::InputStub implementation.
   virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const protocol::TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE;
 
  private:
diff --git a/remoting/proto/event.proto b/remoting/proto/event.proto
index 5c774b5..dd15094 100644
--- a/remoting/proto/event.proto
+++ b/remoting/proto/event.proto
@@ -19,8 +19,7 @@
     LOCK_STATES_NUMLOCK = 2;
   }
 
-  // The Windows Virtual Key code.
-  //optional int32 keycode = 1;
+  // True for key press events, and false for key release.
   optional bool pressed = 2;
 
   // The USB key code.
@@ -32,7 +31,14 @@
   optional uint32 lock_states = 4 [default = 0];
 }
 
-// Defines a mouse event message on the event channel. 
+// Text input event for input method different from physical keyboards,
+// including software keyboard, gesture typing, voice input, etc.
+message TextEvent {
+  // Unicode sequence for the event in UTF-8.
+  optional string text = 1;
+}
+
+// Defines a mouse event message on the event channel.
 message MouseEvent {
 
   enum MouseButton {
diff --git a/remoting/proto/internal.proto b/remoting/proto/internal.proto
index 6ae35f4..89c39e7 100644
--- a/remoting/proto/internal.proto
+++ b/remoting/proto/internal.proto
@@ -33,4 +33,5 @@
 
   optional KeyEvent key_event = 3;
   optional MouseEvent mouse_event = 4;
+  optional TextEvent text_event = 5;
 }
diff --git a/remoting/protocol/client_event_dispatcher.cc b/remoting/protocol/client_event_dispatcher.cc
index e940f93..639231e 100644
--- a/remoting/protocol/client_event_dispatcher.cc
+++ b/remoting/protocol/client_event_dispatcher.cc
@@ -38,6 +38,14 @@
   writer_.Write(SerializeAndFrameMessage(message), base::Closure());
 }
 
+void ClientEventDispatcher::InjectTextEvent(const TextEvent& event) {
+  DCHECK(event.has_text());
+  EventMessage message;
+  message.set_sequence_number(base::Time::Now().ToInternalValue());
+  message.mutable_text_event()->CopyFrom(event);
+  writer_.Write(SerializeAndFrameMessage(message), base::Closure());
+}
+
 void ClientEventDispatcher::InjectMouseEvent(const MouseEvent& event) {
   EventMessage message;
   message.set_sequence_number(base::Time::Now().ToInternalValue());
diff --git a/remoting/protocol/client_event_dispatcher.h b/remoting/protocol/client_event_dispatcher.h
index ab742f2..6e5f8fe 100644
--- a/remoting/protocol/client_event_dispatcher.h
+++ b/remoting/protocol/client_event_dispatcher.h
@@ -22,6 +22,7 @@
 
   // InputStub implementation.
   virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
 
  protected:
diff --git a/remoting/protocol/host_event_dispatcher.cc b/remoting/protocol/host_event_dispatcher.cc
index c5206f4..2dbca9e 100644
--- a/remoting/protocol/host_event_dispatcher.cc
+++ b/remoting/protocol/host_event_dispatcher.cc
@@ -43,6 +43,13 @@
     } else {
       LOG(WARNING) << "Received invalid key event.";
     }
+  } else if (message->has_text_event()) {
+    const TextEvent& event = message->text_event();
+    if (event.has_text()) {
+      input_stub_->InjectTextEvent(event);
+    } else {
+      LOG(WARNING) << "Received invalid text event.";
+    }
   } else if (message->has_mouse_event()) {
     input_stub_->InjectMouseEvent(message->mouse_event());
   } else {
diff --git a/remoting/protocol/input_event_tracker.cc b/remoting/protocol/input_event_tracker.cc
index 331546a..446a4b6 100644
--- a/remoting/protocol/input_event_tracker.cc
+++ b/remoting/protocol/input_event_tracker.cc
@@ -15,8 +15,7 @@
       mouse_button_state_(0) {
 }
 
-InputEventTracker::~InputEventTracker() {
-}
+InputEventTracker::~InputEventTracker() {}
 
 bool InputEventTracker::IsKeyPressed(uint32 usb_keycode) const {
   return pressed_keys_.find(usb_keycode) != pressed_keys_.end();
@@ -71,6 +70,10 @@
   input_stub_->InjectKeyEvent(event);
 }
 
+void InputEventTracker::InjectTextEvent(const TextEvent& event) {
+  input_stub_->InjectTextEvent(event);
+}
+
 void InputEventTracker::InjectMouseEvent(const MouseEvent& event) {
   if (event.has_x() && event.has_y()) {
     mouse_pos_ = webrtc::DesktopVector(event.x(), event.y());
diff --git a/remoting/protocol/input_event_tracker.h b/remoting/protocol/input_event_tracker.h
index 8e0bda7..f357583 100644
--- a/remoting/protocol/input_event_tracker.h
+++ b/remoting/protocol/input_event_tracker.h
@@ -35,6 +35,7 @@
 
   // InputStub interface.
   virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
 
  private:
diff --git a/remoting/protocol/input_filter.cc b/remoting/protocol/input_filter.cc
index 178fde7..66ea2d1 100644
--- a/remoting/protocol/input_filter.cc
+++ b/remoting/protocol/input_filter.cc
@@ -22,6 +22,11 @@
     input_stub_->InjectKeyEvent(event);
 }
 
+void InputFilter::InjectTextEvent(const TextEvent& event) {
+  if (enabled_ && input_stub_ != NULL)
+    input_stub_->InjectTextEvent(event);
+}
+
 void InputFilter::InjectMouseEvent(const MouseEvent& event) {
   if (enabled_ && input_stub_ != NULL)
     input_stub_->InjectMouseEvent(event);
diff --git a/remoting/protocol/input_filter.h b/remoting/protocol/input_filter.h
index 1255637..5384ade 100644
--- a/remoting/protocol/input_filter.h
+++ b/remoting/protocol/input_filter.h
@@ -36,6 +36,7 @@
 
   // InputStub interface.
   virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE;
+  virtual void InjectTextEvent(const TextEvent& event) OVERRIDE;
   virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE;
 
  private:
diff --git a/remoting/protocol/input_filter_unittest.cc b/remoting/protocol/input_filter_unittest.cc
index 97db37d..8059cee 100644
--- a/remoting/protocol/input_filter_unittest.cc
+++ b/remoting/protocol/input_filter_unittest.cc
@@ -19,6 +19,10 @@
          arg.pressed() == pressed;
 }
 
+MATCHER_P(EqualsTextEvent, text, "") {
+  return arg.text() == text;
+}
+
 MATCHER_P2(EqualsMouseMoveEvent, x, y, "") {
   return arg.x() == x && arg.y() == y;
 }
@@ -30,6 +34,12 @@
   return event;
 }
 
+static TextEvent NewTextEvent(const std::string& text) {
+  TextEvent event;
+  event.set_text(text);
+  return event;
+}
+
 static MouseEvent MouseMoveEvent(int x, int y) {
   MouseEvent event;
   event.set_x(x);
@@ -42,17 +52,21 @@
   input_stub->InjectKeyEvent(NewKeyEvent(0, true));
   input_stub->InjectKeyEvent(NewKeyEvent(0, false));
 
+  // Inject a text event
+  input_stub->InjectTextEvent(NewTextEvent("test"));
+
   // Inject mouse movemement.
   input_stub->InjectMouseEvent(MouseMoveEvent(10, 20));
 }
 
 // Verify that the filter passes events on correctly to a configured stub.
 TEST(InputFilterTest, EventsPassThroughFilter) {
-  MockInputStub input_stub;
+  testing::StrictMock<MockInputStub> input_stub;
   InputFilter input_filter(&input_stub);
 
   EXPECT_CALL(input_stub, InjectKeyEvent(EqualsKeyEvent(0, true)));
   EXPECT_CALL(input_stub, InjectKeyEvent(EqualsKeyEvent(0, false)));
+  EXPECT_CALL(input_stub, InjectTextEvent(EqualsTextEvent("test")));
   EXPECT_CALL(input_stub, InjectMouseEvent(EqualsMouseMoveEvent(10, 20)));
 
   InjectTestSequence(&input_filter);
@@ -60,14 +74,10 @@
 
 // Verify that the filter ignores events if disabled.
 TEST(InputFilterTest, IgnoreEventsIfDisabled) {
-  MockInputStub input_stub;
+  testing::StrictMock<MockInputStub> input_stub;
   InputFilter input_filter(&input_stub);
 
   input_filter.set_enabled(false);
-
-  EXPECT_CALL(input_stub, InjectKeyEvent(_)).Times(0);
-  EXPECT_CALL(input_stub, InjectMouseEvent(_)).Times(0);
-
   InjectTestSequence(&input_filter);
 }
 
diff --git a/remoting/protocol/input_stub.h b/remoting/protocol/input_stub.h
index 9183ae0..b60dacf 100644
--- a/remoting/protocol/input_stub.h
+++ b/remoting/protocol/input_stub.h
@@ -14,6 +14,7 @@
 namespace protocol {
 
 class KeyEvent;
+class TextEvent;
 class MouseEvent;
 
 class InputStub {
@@ -24,6 +25,7 @@
   // Implementations must never assume the presence of any |event| fields,
   // nor assume that their contents are valid.
   virtual void InjectKeyEvent(const KeyEvent& event) = 0;
+  virtual void InjectTextEvent(const TextEvent& event) = 0;
   virtual void InjectMouseEvent(const MouseEvent& event) = 0;
 
  private:
diff --git a/remoting/protocol/protocol_mock_objects.h b/remoting/protocol/protocol_mock_objects.h
index 16bb866..fecf1d8 100644
--- a/remoting/protocol/protocol_mock_objects.h
+++ b/remoting/protocol/protocol_mock_objects.h
@@ -96,6 +96,7 @@
   virtual ~MockInputStub();
 
   MOCK_METHOD1(InjectKeyEvent, void(const KeyEvent& event));
+  MOCK_METHOD1(InjectTextEvent, void(const TextEvent& event));
   MOCK_METHOD1(InjectMouseEvent, void(const MouseEvent& event));
 
  private:
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index edde852..49cf630 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -191,6 +191,7 @@
           'host/win/core.rc.jinja2',
           'host/win/host_messages.mc.jinja2',
           'host/win/version.rc.jinja2',
+          'resources/play_store_resources.cc',
           'webapp/background.js',
           'webapp/butter_bar.js',
           'webapp/client_screen.js',
diff --git a/remoting/remoting_host.gypi b/remoting/remoting_host.gypi
index cc68f3f..5add1d4 100644
--- a/remoting/remoting_host.gypi
+++ b/remoting/remoting_host.gypi
@@ -116,8 +116,8 @@
             'host/gnubby_auth_handler_posix.h',
             'host/gnubby_auth_handler_win.cc',
             'host/gnubby_auth_handler.h',
-            'host/gnubby_util.cc',
-            'host/gnubby_util.h',
+            'host/gnubby_socket.cc',
+            'host/gnubby_socket.h',
             'host/heartbeat_sender.cc',
             'host/heartbeat_sender.h',
             'host/host_change_notification_listener.cc',
@@ -576,10 +576,13 @@
             }],
             [ 'OS == "mac"', {
               'variables': {
+                'me2me_host_bundle_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_HOST_BUNDLE_NAME@")',
+                'native_messaging_host_bundle_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME@")',
+                'remote_assistance_host_bundle_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME@")',
                 'me2me_host_path':
-                    '/Library/PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app/Contents/MacOS/native_messaging_host',
+                    '/Library/PrivilegedHelperTools/<(me2me_host_bundle_name)/Contents/MacOS/<(native_messaging_host_bundle_name)/Contents/MacOS/native_messaging_host',
                 'it2me_host_path':
-                    '/Library/PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app/Contents/MacOS/remote_assistance_host',
+                    '/Library/PrivilegedHelperTools/<(me2me_host_bundle_name)/Contents/MacOS/<(remote_assistance_host_bundle_name)/Contents/MacOS/remote_assistance_host',
               },
             }],
             [ 'OS != "mac" and OS != "win"', {
@@ -628,6 +631,8 @@
             'host/remoting_me2me_host-InfoPlist.strings.jinja2',
             'host/mac/me2me_preference_pane-InfoPlist.strings.jinja2',
             'host/installer/mac/uninstaller/remoting_uninstaller-InfoPlist.strings.jinja2',
+            'host/setup/native_messaging_host-InfoPlist.strings.jinja2',
+            'host/it2me/remote_assistance_host-InfoPlist.strings.jinja2',
           ],
           'rules': [{
             'rule_name': 'generate_strings',
@@ -751,14 +756,19 @@
         {
           'target_name': 'remoting_me2me_native_messaging_host',
           'type': 'executable',
-          'product_name': 'remoting_native_messaging_host',
+          'product_name': 'native_messaging_host',
           'variables': { 'enable_wexit_time_destructors': 1, },
           'dependencies': [
             '../base/base.gyp:base',
+            'remoting_breakpad',
             'remoting_host',
             'remoting_host_setup_base',
+            'remoting_infoplist_strings',
             'remoting_native_messaging_base',
           ],
+          'defines': [
+            'VERSION=<(version_full)',
+          ],
           'sources': [
             'host/setup/me2me_native_messaging_host.cc',
             'host/setup/me2me_native_messaging_host.h',
@@ -773,11 +783,68 @@
                 '../base/allocator/allocator.gyp:allocator',
               ],
             }],
+            ['OS=="mac"', {
+              'mac_bundle': 1,
+              'variables': {
+                 'host_bundle_id': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_NATIVE_MESSAGING_HOST_BUNDLE_ID@")',
+              },
+              'xcode_settings': {
+                'INFOPLIST_FILE': 'host/setup/native_messaging_host-Info.plist',
+                'INFOPLIST_PREPROCESS': 'YES',
+                'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'VERSION_FULL="<(version_full)" VERSION_SHORT="<(version_short)" BUNDLE_ID="<(host_bundle_id)"',
+              },
+              'mac_bundle_resources': [
+                'host/setup/native_messaging_host-Info.plist',
+                '<!@pymod_do_main(remoting_copy_locales -o -p <(OS) -x <(PRODUCT_DIR) <(remoting_locales))',
+
+                # Localized strings for 'Info.plist'
+                '<!@pymod_do_main(remoting_localize --locale_output '
+                    '"<(SHARED_INTERMEDIATE_DIR)/remoting/native_messaging_host-InfoPlist.strings/@{json_suffix}.lproj/InfoPlist.strings" '
+                    '--print_only <(remoting_locales))',
+              ],
+              'mac_bundle_resources!': [
+                'host/setup/native_messaging_host-Info.plist',
+              ],
+              'conditions': [
+                ['mac_breakpad==1', {
+                  'variables': {
+                    # A real .dSYM is needed for dump_syms to operate on.
+                    'mac_real_dsym': 1,
+                  },
+                  'copies': [
+                    {
+                      'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Resources',
+                      'files': [
+                        '<(PRODUCT_DIR)/crash_inspector',
+                        '<(PRODUCT_DIR)/crash_report_sender.app'
+                      ],
+                    },
+                  ],
+                  'dependencies': [
+                    '../breakpad/breakpad.gyp:dump_syms',
+                  ],
+                  'postbuilds': [
+                    {
+                      'postbuild_name': 'Dump Symbols',
+                      'variables': {
+                        'dump_product_syms_path':
+                            'scripts/mac/dump_product_syms',
+                      },
+                      'action': [
+                        '<(dump_product_syms_path)',
+                        '<(version_full)',
+                      ],
+                    },  # end of postbuild 'dump_symbols'
+                  ],  # end of 'postbuilds'
+                }],  # mac_breakpad==1
+              ],  # conditions
+            }],  # OS=mac
           ],
         },  # end of target 'remoting_me2me_native_messaging_host'
         {
           'target_name': 'remoting_it2me_native_messaging_host',
           'type': 'executable',
+          'product_name': 'remote_assistance_host',
           'variables': { 'enable_wexit_time_destructors': 1, },
           'dependencies': [
             '../base/base.gyp:base',
@@ -788,6 +855,9 @@
             'remoting_native_messaging_base',
             'remoting_protocol',
           ],
+          'defines': [
+            'VERSION=<(version_full)',
+          ],
           'sources': [
             'host/it2me/it2me_native_messaging_host_entry_point.cc',
             'host/it2me/it2me_native_messaging_host_main.cc',
@@ -806,6 +876,63 @@
                 '../base/allocator/allocator.gyp:allocator',
               ],
             }],
+            ['OS=="mac"', {
+              'mac_bundle': 1,
+              'variables': {
+                 'host_bundle_id': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_ID@")',
+              },
+              'xcode_settings': {
+                'INFOPLIST_FILE': 'host/it2me/remote_assistance_host-Info.plist',
+                'INFOPLIST_PREPROCESS': 'YES',
+                'INFOPLIST_PREPROCESSOR_DEFINITIONS': 'VERSION_FULL="<(version_full)" VERSION_SHORT="<(version_short)" BUNDLE_ID="<(host_bundle_id)"',
+              },
+              'mac_bundle_resources': [
+                '<(PRODUCT_DIR)/icudtl.dat',
+                'host/it2me/remote_assistance_host-Info.plist',
+                '<!@pymod_do_main(remoting_copy_locales -o -p <(OS) -x <(PRODUCT_DIR) <(remoting_locales))',
+
+                # Localized strings for 'Info.plist'
+                '<!@pymod_do_main(remoting_localize --locale_output '
+                    '"<(SHARED_INTERMEDIATE_DIR)/remoting/remote_assistance_host-InfoPlist.strings/@{json_suffix}.lproj/InfoPlist.strings" '
+                    '--print_only <(remoting_locales))',
+              ],
+              'mac_bundle_resources!': [
+                'host/it2me/remote_assistance_host-Info.plist',
+              ],
+              'conditions': [
+                ['mac_breakpad==1', {
+                  'variables': {
+                    # A real .dSYM is needed for dump_syms to operate on.
+                    'mac_real_dsym': 1,
+                  },
+                  'copies': [
+                    {
+                      'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)/Resources',
+                      'files': [
+                        '<(PRODUCT_DIR)/crash_inspector',
+                        '<(PRODUCT_DIR)/crash_report_sender.app'
+                      ],
+                    },
+                  ],
+                  'dependencies': [
+                    '../breakpad/breakpad.gyp:dump_syms',
+                  ],
+                  'postbuilds': [
+                    {
+                      'postbuild_name': 'Dump Symbols',
+                      'variables': {
+                        'dump_product_syms_path':
+                            'scripts/mac/dump_product_syms',
+                      },
+                      'action': [
+                        '<(dump_product_syms_path)',
+                        '<(version_full)',
+                      ],
+                    },  # end of postbuild 'dump_symbols'
+                  ],  # end of 'postbuilds'
+                }],  # mac_breakpad==1
+              ],  # conditions
+            }],  # OS=mac
           ],
         },  # end of target 'remoting_it2me_native_messaging_host'
       ],  # end of 'targets'
diff --git a/remoting/remoting_host_linux.gypi b/remoting/remoting_host_linux.gypi
index e27faf8..770e764 100644
--- a/remoting/remoting_host_linux.gypi
+++ b/remoting/remoting_host_linux.gypi
@@ -13,7 +13,8 @@
           '<!(echo <(deb_filename) | sed -e "s/.deb$/.changes/")',
           '<(PRODUCT_DIR)/remoting_me2me_host.debug',
           '<(PRODUCT_DIR)/remoting_start_host.debug',
-          '<(PRODUCT_DIR)/remoting_native_messaging_host.debug',
+          '<(PRODUCT_DIR)/native_messaging_host.debug',
+          '<(PRODUCT_DIR)/remote_assistance_host.debug',
         ]
       },
       'targets': [
diff --git a/remoting/remoting_host_mac.gypi b/remoting/remoting_host_mac.gypi
index 79a93bb..61d4a8c 100644
--- a/remoting/remoting_host_mac.gypi
+++ b/remoting/remoting_host_mac.gypi
@@ -86,6 +86,10 @@
             'host_service_name': '<!(python <(version_py_path) -f <(branding_path) -t "@DAEMON_FILE_NAME@")',
             'host_uninstaller_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_UNINSTALLER_NAME@")',
             'bundle_prefix': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_UNINSTALLER_BUNDLE_PREFIX@")',
+            'me2me_host_bundle_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_HOST_BUNDLE_NAME@")',
+            'prefpane_bundle_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_PREFPANE_BUNDLE_NAME@")',
+            'native_messaging_host_bundle_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_NATIVE_MESSAGING_HOST_BUNDLE_NAME@")',
+            'remote_assistance_host_bundle_name': '<!(python <(version_py_path) -f <(branding_path) -t "@MAC_REMOTE_ASSISTANCE_HOST_BUNDLE_NAME@")',
           },
           'actions': [
             {
@@ -100,20 +104,17 @@
               'generated_files': [
                 '<(PRODUCT_DIR)/remoting_host_prefpane.prefPane',
                 '<(PRODUCT_DIR)/remoting_me2me_host.app',
-                '<(PRODUCT_DIR)/remoting_native_messaging_host',
-                '<(PRODUCT_DIR)/remoting_it2me_native_messaging_host',
+                '<(PRODUCT_DIR)/native_messaging_host.app',
+                '<(PRODUCT_DIR)/remote_assistance_host.app',
                 '<(PRODUCT_DIR)/remoting_host_uninstaller.app',
                 '<(PRODUCT_DIR)/remoting/com.google.chrome.remote_desktop.json',
                 '<(PRODUCT_DIR)/remoting/com.google.chrome.remote_assistance.json',
               ],
               'generated_files_dst': [
-                'PreferencePanes/org.chromium.chromoting.prefPane',
-
-                # TODO(sergeyu): Rename org.chromium.chromoting.me2me_host. e.g.
-                # to com.google.chrome.remote-desktop .
-                'PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app',
-                'PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app/Contents/MacOS/native_messaging_host',
-                'PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app/Contents/MacOS/remote_assistance_host',
+                'PreferencePanes/<(prefpane_bundle_name)',
+                'PrivilegedHelperTools/<(me2me_host_bundle_name)',
+                'PrivilegedHelperTools/<(me2me_host_bundle_name)/Contents/MacOS/<(native_messaging_host_bundle_name)',
+                'PrivilegedHelperTools/<(me2me_host_bundle_name)/Contents/MacOS/<(remote_assistance_host_bundle_name)',
                 'Applications/<(host_uninstaller_name).app',
                 'Config/com.google.chrome.remote_desktop.json',
                 'Config/com.google.chrome.remote_assistance.json',
@@ -127,6 +128,7 @@
                 'VERSION_MAJOR=<(version_major)',
                 'VERSION_MINOR=<(version_minor)',
                 'HOST_NAME=<(host_name)',
+                'HOST_BUNDLE_NAME=<(me2me_host_bundle_name)',
                 'HOST_SERVICE_NAME=<(host_service_name)',
                 'HOST_UNINSTALLER_NAME=<(host_uninstaller_name)',
                 'HOST_PKG=<(host_name)',
@@ -137,6 +139,9 @@
                 'BUNDLE_ID_HOST_UNINSTALLER=<(bundle_prefix).<(host_uninstaller_name_nospace)',
                 'DMG_VOLUME_NAME=<(host_name) <(version_full)',
                 'DMG_FILE_NAME=<!(echo <(host_name) | sed "s/ //g")-<(version_full)',
+                'NATIVE_MESSAGING_HOST_BUNDLE_NAME=<(native_messaging_host_bundle_name)',
+                'REMOTE_ASSISTANCE_HOST_BUNDLE_NAME=<(remote_assistance_host_bundle_name)',
+                'PREFPANE_BUNDLE_NAME=<(prefpane_bundle_name)',
               ],
               'inputs': [
                 'host/installer/build-installer-archive.py',
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi
index ecfe60b..f70456f 100644
--- a/remoting/remoting_test.gypi
+++ b/remoting/remoting_test.gypi
@@ -75,7 +75,6 @@
         'host/desktop_process_unittest.cc',
         'host/desktop_shape_tracker_unittest.cc',
         'host/gnubby_auth_handler_posix_unittest.cc',
-        'host/gnubby_util_unittest.cc',
         'host/heartbeat_sender_unittest.cc',
         'host/host_change_notification_listener_unittest.cc',
         'host/host_mock_objects.cc',
diff --git a/remoting/resources/android/drawable/empty_host_list.png b/remoting/resources/android/drawable/empty_host_list.png
new file mode 100644
index 0000000..3188cdb
--- /dev/null
+++ b/remoting/resources/android/drawable/empty_host_list.png
Binary files differ
diff --git a/remoting/resources/android/drawable/icon_host_offline.png b/remoting/resources/android/drawable/icon_host_offline.png
new file mode 100644
index 0000000..8c1802c
--- /dev/null
+++ b/remoting/resources/android/drawable/icon_host_offline.png
Binary files differ
diff --git a/remoting/resources/android/drawable/list_item_disabled_selector.xml b/remoting/resources/android/drawable/list_item_disabled_selector.xml
new file mode 100644
index 0000000..3f991bd
--- /dev/null
+++ b/remoting/resources/android/drawable/list_item_disabled_selector.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Copyright 2014 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@color/list_item_disabled_pressed"
+            android:state_pressed="true"/>
+
+    <!-- Default used for all other states. -->
+    <item android:drawable="@android:color/transparent"/>
+</selector>
diff --git a/remoting/resources/android/drawable/list_item_selector.xml b/remoting/resources/android/drawable/list_item_selector.xml
index 5e93ecc..c4b17a8 100644
--- a/remoting/resources/android/drawable/list_item_selector.xml
+++ b/remoting/resources/android/drawable/list_item_selector.xml
@@ -6,11 +6,7 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:drawable="@color/list_item_disabled_pressed"
-            android:state_enabled="false"
-            android:state_pressed="true"/>
     <item android:drawable="@color/list_item_pressed"
-            android:state_enabled="true"
             android:state_pressed="true"/>
 
     <!-- Default used for all other states. -->
diff --git a/remoting/resources/android/layout/account_selected.xml b/remoting/resources/android/layout/account_selected.xml
index cbf523a..5eae097 100644
--- a/remoting/resources/android/layout/account_selected.xml
+++ b/remoting/resources/android/layout/account_selected.xml
@@ -15,7 +15,7 @@
             android:layout_marginTop="@dimen/action_bar_title_top_margin"
             android:singleLine="true"
             android:ellipsize="end"
-            android:text="@string/product_name"
+            android:text="@string/mode_me2me"
             android:textAppearance="?android:attr/textAppearanceMedium"
             android:textSize="@dimen/action_bar_title_text_size"/>
     <TextView android:id="@+id/account_name"
diff --git a/remoting/resources/android/layout/host.xml b/remoting/resources/android/layout/host.xml
index f1b1f4f..1a37741 100644
--- a/remoting/resources/android/layout/host.xml
+++ b/remoting/resources/android/layout/host.xml
@@ -6,11 +6,14 @@
 -->
 
 <TextView xmlns:android="http://schemas.android.com/apk/res/android"
-        android:id="@+id/host_label"
         android:background="@drawable/list_item_selector"
+        android:drawablePadding="16sp"
+        android:gravity="center_vertical"
+        android:id="@+id/host_label"
         android:layout_height="wrap_content"
         android:layout_width="match_parent"
-        android:drawableLeft="@drawable/icon_host"
-        android:drawablePadding="15sp"
-        android:padding="15sp"
-        android:gravity="center_vertical"/>
+        android:paddingBottom="20sp"
+        android:paddingLeft="16sp"
+        android:paddingRight="16sp"
+        android:paddingTop="20sp"
+        style="@android:style/TextAppearance.Holo.Medium"/>
diff --git a/remoting/resources/android/layout/main.xml b/remoting/resources/android/layout/main.xml
index 25a958b..975cd6b 100644
--- a/remoting/resources/android/layout/main.xml
+++ b/remoting/resources/android/layout/main.xml
@@ -8,16 +8,29 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:layout_height="match_parent"
         android:layout_width="match_parent">
-    <LinearLayout android:id="@+id/hostList_main"
-            android:orientation="vertical"
+    <ListView android:id="@+id/hostList_chooser"
             android:layout_height="match_parent"
-            android:layout_width="match_parent">
-        <TextView android:id="@+id/hostList_greeting"
+            android:layout_width="match_parent"/>
+    <LinearLayout android:id="@+id/hostList_empty"
+            android:gravity="center"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent"
+            android:orientation="vertical"
+            android:visibility="gone">
+        <ImageView android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:src="@drawable/empty_host_list"/>
+        <TextView android:gravity="center"
                 android:layout_height="wrap_content"
-                android:layout_width="match_parent"/>
-        <ListView android:id="@+id/hostList_chooser"
-                android:layout_height="match_parent"
-                android:layout_width="match_parent"/>
+                android:layout_width="match_parent"
+                android:text="@string/host_list_empty_android"
+                style="@style/EmptyStateText"/>
+        <TextView android:id="@+id/host_setup_link_android"
+                android:gravity="center"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:text="@string/host_setup_link_android"
+                style="@style/EmptyStateText.Hyperlink"/>
     </LinearLayout>
     <ProgressBar android:id="@+id/hostList_progress"
             android:layout_height="wrap_content"
diff --git a/remoting/resources/android/values/colors.xml b/remoting/resources/android/values/colors.xml
index 4e70228..0d7b817 100644
--- a/remoting/resources/android/values/colors.xml
+++ b/remoting/resources/android/values/colors.xml
@@ -8,4 +8,5 @@
 <resources>
     <color name="list_item_disabled_pressed">#171717</color>
     <color name="list_item_pressed">#444444</color>
+    <color name="host_offline_text">#636363</color>
 </resources>
diff --git a/remoting/resources/android/values/styles.xml b/remoting/resources/android/values/styles.xml
index a78a6d9..881d2bb 100644
--- a/remoting/resources/android/values/styles.xml
+++ b/remoting/resources/android/values/styles.xml
@@ -12,4 +12,11 @@
     <style name="MainActionBar" parent="@android:style/Widget.Holo.ActionBar">
         <item name="android:displayOptions">showHome</item>
     </style>
+    <style name="EmptyStateText" parent="@android:style/TextAppearance.Holo.Large">
+        <item name="android:textColor">#888</item>
+    </style>
+    <style name="EmptyStateText.Hyperlink">
+        <item name="android:textColor">@android:color/holo_blue_light</item>
+        <item name="android:textStyle">italic</item>
+    </style>
 </resources>
diff --git a/remoting/resources/play_store_resources.cc b/remoting/resources/play_store_resources.cc
new file mode 100644
index 0000000..976f51e
--- /dev/null
+++ b/remoting/resources/play_store_resources.cc
@@ -0,0 +1,10 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file exists only to mark the Play Store string resources as used.
+IDS_PLAY_STORE_TITLE
+IDS_PLAY_STORE_TAGLINE
+IDS_PLAY_STORE_DESCRIPTION
+IDS_PLAY_STORE_DESCRIPTION_ALTERNATE
+IDS_PLAY_STORE_CHANGES
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd
index d30476b..1afc37f 100644
--- a/remoting/resources/remoting_strings.grd
+++ b/remoting/resources/remoting_strings.grd
@@ -190,6 +190,9 @@
           <message desc="Message shown in popup dialog on Android when there are no Google accounts on the device" name="IDS_NOACCOUNTS_MESSAGE" formatter_data="android_java">
           To use Chrome Remote Desktop, you'll need to add a Google Account to your device.
           </message>
+          <message desc="The product name, as displayed on Android devices. Ideally this would be 'Chrome Remote Desktop', but that name is too long to be displayed in the Android Launcher. Try to keep the translation below 16 characters if possible." name="IDS_PRODUCT_NAME_ANDROID" formatter_data="android_java">
+            Remote Desktop
+          </message>
         </if>
 
         <message desc="Message shown when the Chrome Remote Desktop client tab is closed while a connection is active." name="IDS_CLOSE_PROMPT">
@@ -243,7 +246,7 @@
         <message desc="Message displayed when the client or host has disconnected." name="IDS_MESSAGE_SESSION_FINISHED">
           Your Chrome Remote Desktop session has ended.
         </message>
-        <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME" formatter_data="android_java">
+        <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME">
           Chrome Remote Desktop
         </message>
         <message desc="Message displayed at the bottom of the client connect dialog if Chrome Remote Desktop is running in the wrong start-up mode." name="IDS_WARNING_NOT_WINDOWED">
@@ -290,7 +293,10 @@
       <if expr="not _google_chrome">
         <if expr="is_android">
           <message desc="Message shown in popup dialog on Android when there are no Google accounts on the device" name="IDS_NOACCOUNTS_MESSAGE" formatter_data="android_java">
-          To use Chromoting, you'll need to add a Google Account to your device.
+            To use Chromoting, you'll need to add a Google Account to your device.
+          </message>
+          <message desc="The product name, as displayed on Android devices. Try to keep the translation below 16 characters if possible." name="IDS_PRODUCT_NAME_ANDROID" formatter_data="android_java">
+            Chromoting
           </message>
         </if>
 
@@ -345,7 +351,7 @@
         <message desc="Message displayed when the client or host has disconnected." name="IDS_MESSAGE_SESSION_FINISHED">
           Your Chromoting session has ended.
         </message>
-        <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME" formatter_data="android_java">
+        <message desc="The product name. Displayed in various Chrome pages, including the New Tab page, and displayed prominently on the app's main page." name="IDS_PRODUCT_NAME">
           Chromoting
         </message>
         <message desc="Message displayed at the bottom of the client connect dialog if Chromoting is running in the wrong start-up mode." name="IDS_WARNING_NOT_WINDOWED">
@@ -396,6 +402,9 @@
         <message desc="Message displayed to the user if there are no hosts registered to their account" name="IDS_HOST_LIST_EMPTY_ANDROID" formatter_data="android_java">
           You have no computers registered.
         </message>
+        <message desc="Message displayed to the user if there are no hosts registered to their account. This is styled to look like a hyperlink. When a user activates the link, they are taken to a web page that explains how to set up a Chromoting host." name="IDS_HOST_SETUP_LINK_ANDROID" formatter_data="android_java">
+          Learn how to set up a computer for remote access.
+        </message>
         <message desc="Title of the authentication dialog" name="IDS_TITLE_AUTHENTICATE" formatter_data="android_java">
           Authenticate to host
         </message>
@@ -417,6 +426,41 @@
         <message desc="Error that is shown if a network error occurs, including the case where the device is off-line." name="IDS_ERROR_NETWORK_ERROR" formatter_data="android_java">
           A network error occurred. Please check that your device is on-line and try again.
         </message>
+        <message desc="Text shown in tooltip when user touches an offline host on the device." name="IDS_HOST_OFFLINE_TOOLTIP" formatter_data="android_java">
+          Host is offline.
+        </message>
+
+<!-- Play Store listings text. These Android-specific strings are not marked
+     with formatter_data="android_java" since they are used only for the Play
+     Store listings, and should not be bundled in the APK.
+-->
+        <message name="IDS_PLAY_STORE_TITLE" desc="Play Store title of the Chrome Remote Desktop app for Android. [CHAR-LIMIT=30] [NAME=play_store_title]">
+          Chrome Remote Desktop
+        </message>
+        <message name="IDS_PLAY_STORE_TAGLINE" desc="Play Store tagline for the Chrome Remote Desktop app for Android. [CHAR-LIMIT=80] [NAME=play_store_tagline]">
+          Securely access your computers from your Android device.
+        </message>
+        <message name="IDS_PLAY_STORE_DESCRIPTION" desc="Play Store description of the Chrome Remote Desktop app for Android. [CHAR-LIMIT=4000] [NAME=play_store_description]">
+Securely access your computers from your Android device.
+
+• On each of your computers, set up remote access using the Chrome Remote Desktop app from Chrome Web Store: https://chrome.google.com/remotedesktop
+• On your Android device, open the app and tap on any of your online computers to connect.
+
+For information about privacy, please see the Google Privacy Policy (http://goo.gl/SyrVzj) and the Chrome Privacy Policy (http://goo.gl/0uXE5d).
+        </message>
+        <message name="IDS_PLAY_STORE_DESCRIPTION_ALTERNATE" desc="Play Store description of the Chrome Remote Desktop app for Android. [CHAR-LIMIT=4000] [NAME=play_store_description_alternate]">
+Securely access your computers from your Android device.
+
+• On each of your computers, set up remote access using the Chrome Remote Desktop app from Chrome Web Store: https://chrome.google.com/remotedesktop
+• On your Android device, open the app and tap on any of your online computers to connect.
+
+Remote computers with non US-English keyboards may receive incorrect text input. Support for other keyboard layouts is coming soon!
+
+For information about privacy, please see the Google Privacy Policy (http://goo.gl/SyrVzj) and the Chrome Privacy Policy (http://goo.gl/0uXE5d).
+        </message>
+        <message name="IDS_PLAY_STORE_CHANGES" desc="List of what's changed in this release of Chrome Remote Desktop for Android. [CHAR-LIMIT=500] [NAME=play_store_changes]">
+First release of Chrome Remote Desktop for Android.
+        </message>
       </if>
 
       <message desc="Label for the access code entry box. This is where the client user enters the code that permits access to the host." name="IDS_ACCESS_CODE">
@@ -708,7 +752,7 @@
         Why is this safe?
       </message>
       <message desc="Check-box displayed when the user enters their PIN to connect to a host allowing them to 'pair' the client and host, avoiding the need to enter the PIN each time." name="IDS_REMEMBER_PIN" formatter_data="android_java">
-        Don't ask for a PIN again when connecting to this host from this computer.
+        Don't ask for a PIN again when connecting to this host from this device.
       </message>
       <message name="IDS_HANGOUTS_INVITATION" desc="Text for the invitation to try Remote Desktop app in Hangouts.">
         Want to help someone while having a video chat with them too? Try <ph name="LINK_BEGIN">$1<ex>&lt;a href=https://plus.google.com/hangouts&gt;</ex></ph> Remote Desktop in Google Hangouts<ph name="LINK_END">$2<ex>&lt;/a&gt;</ex></ph>.
diff --git a/remoting/resources/remoting_strings_da.xtb b/remoting/resources/remoting_strings_da.xtb
index 6b3429f..ffaaff4 100644
--- a/remoting/resources/remoting_strings_da.xtb
+++ b/remoting/resources/remoting_strings_da.xtb
@@ -31,7 +31,7 @@
 <translation id="8864965950780407789">Hvis du vil bruge Chromoting, skal du give udvidet adgangstilladelse til din computer. Du skal kun gøre dette én gang.</translation>
 <translation id="8355326866731426344">Denne adgangskode udløber om <ph name="TIMEOUT"/></translation>
 <translation id="985602178874221306">Forfatterne til Chromium</translation>
-<translation id="6198252989419008588">Skift PIN-kode</translation>
+<translation id="6198252989419008588">Skift pinkode</translation>
 <translation id="170207782578677537">Denne computer kunne ikke registreres.</translation>
 <translation id="4804818685124855865">Afbryd</translation>
 <translation id="5708869785009007625">Dit skrivebord deles i øjeblikket med <ph name="USER"/>.</translation>
diff --git a/remoting/resources/remoting_strings_el.xtb b/remoting/resources/remoting_strings_el.xtb
index 862a290..1924add 100644
--- a/remoting/resources/remoting_strings_el.xtb
+++ b/remoting/resources/remoting_strings_el.xtb
@@ -127,13 +127,13 @@
 <translation id="1643640058022401035">Εάν απομακρυνθείτε από αυτήν τη σελίδα, η περίοδος σύνδεσης του Chromoting θα τερματιστεί.</translation>
 <translation id="8261506727792406068">Διαγραφή</translation>
 <translation id="2235518894410572517">Πραγματοποιήστε κοινή χρήση αυτού του υπολογιστή ώστε ένας άλλος χρήστης να έχει τη δυνατότητα να βλέπει και να ελέγχει τον υπολογιστή σας.</translation>
-<translation id="1023096696228309145">Ζητήστε από τον χρήστη στον υπολογιστή του οποίου θέλετε να αποκτήσετε πρόσβαση να κάνει κλικ στην επιλογή &quot;Κοινή χρήση τώρα&quot; και να σας δώσει τον κωδικό πρόσβασης.</translation>
+<translation id="1023096696228309145">Ζητήστε από το χρήστη στον υπολογιστή του οποίου θέλετε να αποκτήσετε πρόσβαση να κάνει κλικ στην επιλογή &quot;Κοινή χρήση τώρα&quot; και να σας δώσει τον κωδικό πρόσβασης.</translation>
 <translation id="4240294130679914010">Πρόγραμμα απεγκατάστασης κεντρικού υπολογιστή Chromoting</translation>
 <translation id="80739703311984697">Ο απομακρυσμένος κεντρικός υπολογιστής ζήτησε τον έλεγχο της ταυτότητάς σας στον ιστότοπο ενός τρίτου μέρους. Για να συνεχίσετε, θα πρέπει να παραχωρήσετε στο Chromoting επιπλέον άδειες για πρόσβαση σε αυτήν τη διεύθυνση:</translation>
 <translation id="4006787130661126000">Θα πρέπει να ενεργοποιήσετε τις απομακρυσμένες συνδέσεις εάν επιθυμείτε να χρησιμοποιήσετε την Απομακρυσμένη επιφάνεια εργασίας Chrome για πρόσβαση σε αυτόν τον υπολογιστή.</translation>
 <translation id="177096447311351977">Διεύθυνση IP καναλιού για υπολογιστή-πελάτη: <ph name="CLIENT_GAIA_IDENTIFIER"/> ip='<ph name="CLIENT_IP_ADDRESS_AND_PORT"/>' host_ip='<ph name="HOST_IP_ADDRESS_AND_PORT"/>' channel='<ph name="CHANNEL_TYPE"/>' connection='<ph name="CONNECTION_TYPE"/>'.</translation>
 <translation id="6930242544192836755">Διάρκεια</translation>
-<translation id="6527303717912515753">Κοινή χρήση</translation>
+<translation id="6527303717912515753">Κοινοποίηση</translation>
 <translation id="2926340305933667314">Αποτυχία απενεργοποίησης απομακρυσμένης πρόσβασης σε αυτόν τον υπολογιστή. Προσπαθήστε ξανά αργότερα.</translation>
 <translation id="6865175692670882333">Προβολή/επεξεργασία</translation>
 <translation id="5859141382851488196">Νέο παράθυρο…</translation>
diff --git a/remoting/tools/get_mac_crd_version.sh b/remoting/tools/get_mac_crd_version.sh
index dbddb9c..89661c1 100755
--- a/remoting/tools/get_mac_crd_version.sh
+++ b/remoting/tools/get_mac_crd_version.sh
@@ -4,10 +4,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-ME2ME_HOST="/Library/PrivilegedHelperTools/org.chromium.chromoting.me2me_host.app"
+ME2ME_HOST="/Library/PrivilegedHelperTools/ChromeRemoteDesktopHost.bundle"
 UNINSTALLER_CHROME="/Applications/Chrome Remote Desktop Host Uninstaller.app"
 UNINSTALLER_CHROMIUM="/Applications/Chromoting Host Uninstaller.app"
-PREFPANE="/Library/PreferencePanes/org.chromium.chromoting.prefPane"
+PREFPANE="/Library/PreferencePanes/ChromeRemoteDesktop.prefPane"
 KEYSTONE="/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle"
 
 INFO_PLIST="Contents/Info.plist"
diff --git a/remoting/tools/register_local_nm_hosts.sh b/remoting/tools/register_local_nm_hosts.sh
index b59bf21..8a0b253 100755
--- a/remoting/tools/register_local_nm_hosts.sh
+++ b/remoting/tools/register_local_nm_hosts.sh
@@ -34,12 +34,12 @@
 
   install_manifest \
      "${SRC_DIR}/remoting/host/setup/${ME2ME_HOST_NAME}.json.jinja2" \
-     "${build_dir}/remoting_native_messaging_host" \
+     "${build_dir}/native_messaging_host" \
      ME2ME_HOST_PATH "${chrome_data_dir}"
 
   install_manifest \
      "${SRC_DIR}/remoting/host/it2me/${IT2ME_HOST_NAME}.json.jinja2" \
-     "${build_dir}/remoting_it2me_native_messaging_host" \
+     "${build_dir}/remote_assistance_host" \
      IT2ME_HOST_PATH "${chrome_data_dir}"
 }
 
diff --git a/remoting/webapp/client_plugin.js b/remoting/webapp/client_plugin.js
index 65db925..4252b40 100644
--- a/remoting/webapp/client_plugin.js
+++ b/remoting/webapp/client_plugin.js
@@ -169,8 +169,8 @@
 
   if (message.method == 'hello') {
     // Reset the size in case we had to enlarge it to support click-to-play.
-    this.plugin.width = 0;
-    this.plugin.height = 0;
+    this.plugin.style.width = '0px';
+    this.plugin.style.height = '0px';
     this.pluginApiVersion_ = getNumberAttr(message.data, 'apiVersion');
     this.pluginApiMinVersion_ = getNumberAttr(message.data, 'apiMinVersion');
 
@@ -660,8 +660,8 @@
   if (!this.helloReceived_) {
     var width = 200;
     var height = 200;
-    this.plugin.width = width;
-    this.plugin.height = height;
+    this.plugin.style.width = width + 'px';
+    this.plugin.style.height = height + 'px';
     // Center the plugin just underneath the "Connnecting..." dialog.
     var parentNode = this.plugin.parentNode;
     var dialog = document.getElementById('client-dialog');
diff --git a/remoting/webapp/gnubby_auth_handler.js b/remoting/webapp/gnubby_auth_handler.js
index 848ab1e..52fd495 100644
--- a/remoting/webapp/gnubby_auth_handler.js
+++ b/remoting/webapp/gnubby_auth_handler.js
@@ -30,9 +30,10 @@
   var message = getJsonObjectFromString(data);
   var messageType = getStringAttr(message, 'type');
   if (messageType == 'data') {
-    this.sendMessageToGnubbyd_(
-        getJsonObjectFromString(getStringAttr(message, 'jsonMessage')),
-        this.callback_.bind(this, getNumberAttr(message, 'connectionId')));
+    this.sendMessageToGnubbyd_({
+      'type': 'auth-agent@openssh.com',
+      'data': getArrayAttr(message, 'data')
+    }, this.callback_.bind(this, getNumberAttr(message, 'connectionId')));
   } else {
     console.error('Invalid gnubby-auth message: ' + messageType);
   }
@@ -41,15 +42,25 @@
 /**
  * Callback invoked with data to be returned to the host.
  * @param {number} connectionId The connection id.
- * @param {Object} data The JSON object to send to the host.
+ * @param {Object} response The JSON response with the data to send to the host.
  * @private
  */
 remoting.GnubbyAuthHandler.prototype.callback_ =
-    function(connectionId, data) {
-  var json_data = JSON.stringify(data);
-  this.clientSession_.sendGnubbyAuthMessage({'type': 'data',
-    'connectionId': connectionId,
-    'jsonMessage': json_data});
+    function(connectionId, response) {
+  try {
+    this.clientSession_.sendGnubbyAuthMessage({
+      'type': 'data',
+      'connectionId': connectionId,
+      'data': getArrayAttr(response, 'data')
+    });
+  } catch (err) {
+    console.error('gnubby callback failed: ', /** @type {*} */ (err));
+    this.clientSession_.sendGnubbyAuthMessage({
+      'type': 'error',
+      'connectionId': connectionId
+    });
+    return;
+  }
 };
 
 /**
@@ -86,4 +97,4 @@
   } else {
     chrome.runtime.sendMessage(kGnubbydStableExtensionId, jsonObject, callback);
   }
-};
+}
diff --git a/remoting/webapp/html/client_plugin.html b/remoting/webapp/html/client_plugin.html
index 628c6fa..af375ae 100644
--- a/remoting/webapp/html/client_plugin.html
+++ b/remoting/webapp/html/client_plugin.html
@@ -4,10 +4,8 @@
 found in the LICENSE file.
 -->
 <div class="vertically-centered">
-  <div class="horizontally-centered">
     <div id="video-container">
       <video id="mediasource-video-output"></video>
-      <div id="client-plugin-container"></div>
+      <div id="client-plugin-container" class="horizontally-centered"></div>
     </div>
-  </div>
 </div>
diff --git a/remoting/webapp/main.css b/remoting/webapp/main.css
index 7b50dbb..2eb0948 100644
--- a/remoting/webapp/main.css
+++ b/remoting/webapp/main.css
@@ -743,6 +743,7 @@
 /* video-container needs relative position so that mediasource-video-output can
  * be positioned relative to the parent with position:absolute. */
 #video-container {
+  width: 100%;
   position: relative;
 }
 
diff --git a/sandbox/linux/seccomp-bpf/bpf_tests.h b/sandbox/linux/seccomp-bpf/bpf_tests.h
index 7095c23..dd30b15 100644
--- a/sandbox/linux/seccomp-bpf/bpf_tests.h
+++ b/sandbox/linux/seccomp-bpf/bpf_tests.h
@@ -89,10 +89,9 @@
       arg->test()(arg->aux_);
     } else {
       printf("This BPF test is not fully running in this configuration!\n");
-      // Android, ARM and Valgrind are the three only configurations where we
-      // accept not having kernel BPF support.
-      // TODO(jln): remote ARM from this list when possible (crbug.com/243478).
-      if (!IsAndroid() && !IsRunningOnValgrind() && !IsArchitectureArm()) {
+      // Android and Valgrind are the only configurations where we accept not
+      // having kernel BPF support.
+      if (!IsAndroid() && !IsRunningOnValgrind()) {
         const bool seccomp_bpf_is_supported = false;
         BPF_ASSERT(seccomp_bpf_is_supported);
       }
diff --git a/sandbox/linux/seccomp-bpf/codegen.cc b/sandbox/linux/seccomp-bpf/codegen.cc
index 8fb1701..c05eb5e 100644
--- a/sandbox/linux/seccomp-bpf/codegen.cc
+++ b/sandbox/linux/seccomp-bpf/codegen.cc
@@ -4,6 +4,7 @@
 
 #include <stdio.h>
 
+#include "base/logging.h"
 #include "sandbox/linux/seccomp-bpf/codegen.h"
 
 namespace {
@@ -432,6 +433,10 @@
   // We compare the sequence of instructions in both basic blocks.
   const Instructions& insns1 = block1->instructions;
   const Instructions& insns2 = block2->instructions;
+  // Basic blocks should never be empty.
+  CHECK(!insns1.empty());
+  CHECK(!insns2.empty());
+
   Instructions::const_iterator iter1 = insns1.begin();
   Instructions::const_iterator iter2 = insns2.begin();
   for (;; ++iter1, ++iter2) {
@@ -439,7 +444,26 @@
     // both basic blocks, we know the relative ordering between the two blocks
     // and can return.
     if (iter1 == insns1.end()) {
-      return iter2 == insns2.end() ? 0 : -1;
+      if (iter2 == insns2.end()) {
+        // If the two blocks are the same length (and have elementwise-equal
+        // code and k fields, which is the only way we can reach this point),
+        // and the last instruction isn't a JMP or a RET, then we must compare
+        // their successors.
+        Instruction* const insns1_last = insns1.back();
+        Instruction* const insns2_last = insns2.back();
+        if (BPF_CLASS(insns1_last->code) != BPF_JMP &&
+            BPF_CLASS(insns1_last->code) != BPF_RET) {
+          // Non jumping instructions will always have a valid next instruction.
+          CHECK(insns1_last->next);
+          CHECK(insns2_last->next);
+          return PointerCompare(blocks.find(insns1_last->next)->second,
+                                blocks.find(insns2_last->next)->second,
+                                blocks);
+        } else {
+          return 0;
+        }
+      }
+      return -1;
     } else if (iter2 == insns2.end()) {
       return 1;
     }
diff --git a/sandbox/linux/seccomp-bpf/codegen_unittest.cc b/sandbox/linux/seccomp-bpf/codegen_unittest.cc
index 0539a0d..e4cf6bb 100644
--- a/sandbox/linux/seccomp-bpf/codegen_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/codegen_unittest.cc
@@ -143,12 +143,108 @@
   return insn6;
 }
 
+Instruction* SampleProgramConfusingTails(CodeGen* codegen, int* flags) {
+  // This simple program demonstrates https://crbug.com/351103/
+  // The two "LOAD 0" instructions are blocks of their own. MergeTails() could
+  // be tempted to merge them since they are the same. However, they are
+  // not mergeable because they fall-through to non semantically equivalent
+  // blocks.
+  // Without the fix for this bug, this program should trigger the check in
+  // CompileAndCompare: the serialized graphs from the program and its compiled
+  // version will differ.
+  //
+  //  0) LOAD 1  // ???
+  //  1) if A == 0x1; then JMP 2 else JMP 3
+  //  2) LOAD 0  // System call number
+  //  3) if A == 0x2; then JMP 4 else JMP 5
+  //  4) LOAD 0  // System call number
+  //  5) if A == 0x1; then JMP 6 else JMP 7
+  //  6) RET 0x50000  // errno = 0
+  //  7) RET 0x50001  // errno = 1
+  *flags = NO_FLAGS;
+
+  Instruction* i7 = codegen->MakeInstruction(BPF_RET, ErrorCode(1));
+  Instruction* i6 = codegen->MakeInstruction(BPF_RET, ErrorCode(0));
+  Instruction* i5 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7);
+  Instruction* i4 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i5);
+  Instruction* i3 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5);
+  Instruction* i2 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i3);
+  Instruction* i1 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3);
+  Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1);
+
+  return i0;
+}
+
+Instruction* SampleProgramConfusingTailsBasic(CodeGen* codegen, int* flags) {
+  // Without the fix for https://crbug.com/351103/, (see
+  // SampleProgramConfusingTails()), this would generate a cyclic graph and
+  // crash as the two "LOAD 0" instructions would get merged.
+  //
+  // 0) LOAD 1  // ???
+  // 1) if A == 0x1; then JMP 2 else JMP 3
+  // 2) LOAD 0  // System call number
+  // 3) if A == 0x2; then JMP 4 else JMP 5
+  // 4) LOAD 0  // System call number
+  // 5) RET 0x50001  // errno = 1
+  *flags = NO_FLAGS;
+
+  Instruction* i5 = codegen->MakeInstruction(BPF_RET, ErrorCode(1));
+  Instruction* i4 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i5);
+  Instruction* i3 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5);
+  Instruction* i2 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 0, i3);
+  Instruction* i1 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3);
+  Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1);
+
+  return i0;
+}
+
+Instruction* SampleProgramConfusingTailsMergeable(CodeGen* codegen,
+                                                  int* flags) {
+  // This is similar to SampleProgramConfusingTails(), except that
+  // instructions 2 and 4 are now RET instructions.
+  // In PointerCompare(), this exercises the path where two blocks are of the
+  // same length and identical and the last instruction is a JMP or RET, so the
+  // following blocks don't need to be looked at and the blocks are mergeable.
+  //
+  // 0) LOAD 1  // ???
+  // 1) if A == 0x1; then JMP 2 else JMP 3
+  // 2) RET 0x5002a  // errno = 42
+  // 3) if A == 0x2; then JMP 4 else JMP 5
+  // 4) RET 0x5002a  // errno = 42
+  // 5) if A == 0x1; then JMP 6 else JMP 7
+  // 6) RET 0x50000  // errno = 0
+  // 7) RET 0x50001  // errno = 1
+  *flags = HAS_MERGEABLE_TAILS;
+
+  Instruction* i7 = codegen->MakeInstruction(BPF_RET, ErrorCode(1));
+  Instruction* i6 = codegen->MakeInstruction(BPF_RET, ErrorCode(0));
+  Instruction* i5 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i6, i7);
+  Instruction* i4 = codegen->MakeInstruction(BPF_RET, ErrorCode(42));
+  Instruction* i3 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 2, i4, i5);
+  Instruction* i2 = codegen->MakeInstruction(BPF_RET, ErrorCode(42));
+  Instruction* i1 =
+      codegen->MakeInstruction(BPF_JMP + BPF_JEQ + BPF_K, 1, i2, i3);
+  Instruction* i0 = codegen->MakeInstruction(BPF_LD + BPF_W + BPF_ABS, 1, i1);
+
+  return i0;
+}
+
 void ForAllPrograms(void (*test)(CodeGenUnittestHelper *, Instruction *, int)){
   Instruction *(*function_table[])(CodeGen *codegen, int *flags) = {
     SampleProgramOneInstruction,
     SampleProgramSimpleBranch,
     SampleProgramAtypicalBranch,
     SampleProgramComplex,
+    SampleProgramConfusingTails,
+    SampleProgramConfusingTailsBasic,
+    SampleProgramConfusingTailsMergeable,
   };
 
   for (size_t i = 0; i < arraysize(function_table); ++i) {
diff --git a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
index d05878c..17df1d5 100644
--- a/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
+++ b/sandbox/linux/seccomp-bpf/sandbox_bpf_unittest.cc
@@ -50,7 +50,7 @@
 
 // This test should execute no matter whether we have kernel support. So,
 // we make it a TEST() instead of a BPF_TEST().
-TEST(SandboxBPF, CallSupports) {
+TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupports)) {
   // We check that we don't crash, but it's ok if the kernel doesn't
   // support it.
   bool seccomp_bpf_supported =
@@ -65,7 +65,7 @@
   std::cout << "Pointer size: " << sizeof(void*) << "\n";
 }
 
-SANDBOX_TEST(SandboxBPF, CallSupportsTwice) {
+SANDBOX_TEST(SandboxBPF, DISABLE_ON_TSAN(CallSupportsTwice)) {
   SandboxBPF::SupportsSeccompSandbox(-1);
   SandboxBPF::SupportsSeccompSandbox(-1);
 }
diff --git a/sandbox/linux/seccomp-bpf/trap.cc b/sandbox/linux/seccomp-bpf/trap.cc
index 553a904..f8b64c9 100644
--- a/sandbox/linux/seccomp-bpf/trap.cc
+++ b/sandbox/linux/seccomp-bpf/trap.cc
@@ -82,8 +82,11 @@
   }
 
   if (!IsDefaultSignalAction(old_sa)) {
-    // TODO(jln): make this FATAL, at least in DEBUG mode.
-    LOG(ERROR) << "Existing signal handler when trying to install SIGSYS";
+    static const char kExistingSIGSYSMsg[] =
+        "Existing signal handler when trying to install SIGSYS. SIGSYS needs "
+        "to be reserved for seccomp-bpf.";
+    DLOG(FATAL) << kExistingSIGSYSMsg;
+    LOG(ERROR) << kExistingSIGSYSMsg;
   }
 
   // Unmask SIGSYS
diff --git a/sandbox/linux/services/android_ucontext.h b/sandbox/linux/services/android_ucontext.h
index 437bbab..caabaf5 100644
--- a/sandbox/linux/services/android_ucontext.h
+++ b/sandbox/linux/services/android_ucontext.h
@@ -11,6 +11,8 @@
 #include "sandbox/linux/services/android_arm_ucontext.h"
 #elif defined(__i386__)
 #include "sandbox/linux/services/android_i386_ucontext.h"
+#elif defined(__x86_64__)
+#include "sandbox/linux/services/android_x86_64_ucontext.h"
 #else
 #error "No support for your architecture in Android header"
 #endif
diff --git a/sandbox/linux/services/android_x86_64_ucontext.h b/sandbox/linux/services/android_x86_64_ucontext.h
new file mode 100644
index 0000000..ef328e5
--- /dev/null
+++ b/sandbox/linux/services/android_x86_64_ucontext.h
@@ -0,0 +1,88 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SANDBOX_LINUX_SERVICES_ANDROID_X86_64_UCONTEXT_H_
+#define SANDBOX_LINUX_SERVICES_ANDROID_X86_64_UCONTEXT_H_
+
+// We do something compatible with glibc. Hopefully, at some point Android will
+// provide that for us, and __BIONIC_HAVE_UCONTEXT_T should be defined.
+// Spec:
+// http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-AMD64/LSB-Core-AMD64/libc-ddefs.html#AEN5668
+
+#if !defined(__BIONIC_HAVE_UCONTEXT_T)
+#include <asm/sigcontext.h>
+
+struct _libc_fpxreg {
+  unsigned short significand[4];
+  unsigned short exponent;
+  unsigned short padding[3];
+};
+
+struct _libc_xmmreg {
+  uint32_t element[4];
+};
+
+struct _libc_fpstate {
+  uint16_t cwd;
+  uint16_t swd;
+  uint16_t twd;
+  uint16_t fop;
+  uint64_t rip;
+  uint64_t rdp;
+  uint32_t mxcsr;
+  uint32_t mxcsr_mask;
+  struct _libc_fpxreg _st[8];
+  struct _libc_xmmreg _xmm[16];
+  uint32_t padding[24];
+};
+
+typedef uint64_t greg_t;
+
+typedef struct {
+  greg_t gregs[23];
+  struct _libc_fpstate* fpregs;
+  unsigned long __reserved1[8];
+} mcontext_t;
+
+enum {
+  REG_R8 = 0,
+  REG_R9,
+  REG_R10,
+  REG_R11,
+  REG_R12,
+  REG_R13,
+  REG_R14,
+  REG_R15,
+  REG_RDI,
+  REG_RSI,
+  REG_RBP,
+  REG_RBX,
+  REG_RDX,
+  REG_RAX,
+  REG_RCX,
+  REG_RSP,
+  REG_RIP,
+  REG_EFL,
+  REG_CSGSFS,
+  REG_ERR,
+  REG_TRAPNO,
+  REG_OLDMASK,
+  REG_CR2,
+  NGREG,
+};
+
+typedef struct ucontext {
+  unsigned long uc_flags;
+  struct ucontext* uc_link;
+  stack_t uc_stack;
+  mcontext_t uc_mcontext;
+  sigset_t uc_sigmask;
+  struct _libc_fpstate __fpregs_mem;
+} ucontext_t;
+
+#else
+#include <sys/ucontext.h>
+#endif  // __BIONIC_HAVE_UCONTEXT_T
+
+#endif  // SANDBOX_LINUX_SERVICES_ANDROID_X86_64_UCONTEXT_H_
diff --git a/sandbox/linux/services/broker_process.cc b/sandbox/linux/services/broker_process.cc
index 2956cf9..47aec25 100644
--- a/sandbox/linux/services/broker_process.cc
+++ b/sandbox/linux/services/broker_process.cc
@@ -25,6 +25,7 @@
 #include "base/posix/eintr_wrapper.h"
 #include "base/posix/unix_domain_socket_linux.h"
 #include "base/process/process_metrics.h"
+#include "base/third_party/valgrind/valgrind.h"
 #include "build/build_config.h"
 #include "sandbox/linux/services/linux_syscalls.h"
 
@@ -34,6 +35,22 @@
 
 namespace {
 
+bool IsRunningOnValgrind() { return RUNNING_ON_VALGRIND; }
+
+// A little open(2) wrapper to handle some oddities for us. In the general case
+// make a direct system call since we want to keep in control of the broker
+// process' system calls profile to be able to loosely sandbox it.
+int sys_open(const char* pathname, int flags) {
+  // Always pass a defined |mode| in case flags mistakenly contains O_CREAT.
+  const int mode = 0;
+  if (IsRunningOnValgrind()) {
+    // Valgrind does not support AT_FDCWD, just use libc's open() in this case.
+    return open(pathname, flags, mode);
+  } else {
+    return syscall(__NR_openat, AT_FDCWD, pathname, flags, mode);
+  }
+}
+
 static const size_t kMaxMessageLength = 4096;
 
 // Some flags are local to the current process and cannot be sent over a Unix
@@ -433,9 +450,7 @@
 
   if (safe_to_open_file) {
     CHECK(file_to_open);
-    // We're doing a 2-parameter open, so we don't support O_CREAT. It doesn't
-    // hurt to always pass a third argument though.
-    int opened_fd = syscall(__NR_open, file_to_open, flags, 0);
+    int opened_fd = sys_open(file_to_open, flags);
     if (opened_fd < 0) {
       write_pickle->WriteInt(-errno);
     } else {
diff --git a/sandbox/linux/services/yama.cc b/sandbox/linux/services/yama.cc
index 773f670..49e1b36 100644
--- a/sandbox/linux/services/yama.cc
+++ b/sandbox/linux/services/yama.cc
@@ -79,7 +79,7 @@
 
   static const char kPtraceScopePath[] = "/proc/sys/kernel/yama/ptrace_scope";
 
-  base::ScopedFD yama_scope(open(kPtraceScopePath, O_RDONLY));
+  base::ScopedFD yama_scope(HANDLE_EINTR(open(kPtraceScopePath, O_RDONLY)));
 
   if (!yama_scope.is_valid()) {
     const int open_errno = errno;
diff --git a/sandbox/sandbox.target.darwin-x86_64.mk b/sandbox/sandbox.target.darwin-x86_64.mk
new file mode 100644
index 0000000..6a0b9d5
--- /dev/null
+++ b/sandbox/sandbox.target.darwin-x86_64.mk
@@ -0,0 +1,41 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := sandbox_sandbox_gyp
+LOCAL_MODULE_STEM := sandbox
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_helpers_gyp)/sandbox_seccomp_bpf_helpers_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_sandbox_gyp
+
+# Alias gyp target name.
+.PHONY: sandbox
+sandbox: sandbox_sandbox_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/sandbox/sandbox.target.linux-x86_64.mk b/sandbox/sandbox.target.linux-x86_64.mk
new file mode 100644
index 0000000..6a0b9d5
--- /dev/null
+++ b/sandbox/sandbox.target.linux-x86_64.mk
@@ -0,0 +1,41 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := sandbox_sandbox_gyp
+LOCAL_MODULE_STEM := sandbox
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_sandbox_services_gyp)/sandbox_sandbox_services_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_gyp)/sandbox_seccomp_bpf_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,sandbox_seccomp_bpf_helpers_gyp)/sandbox_seccomp_bpf_helpers_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_sandbox_gyp
+
+# Alias gyp target name.
+.PHONY: sandbox
+sandbox: sandbox_sandbox_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/sandbox/sandbox_services.target.darwin-arm.mk b/sandbox/sandbox_services.target.darwin-arm.mk
index 3a35021..b28f494 100644
--- a/sandbox/sandbox_services.target.darwin-arm.mk
+++ b/sandbox/sandbox_services.target.darwin-arm.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services.target.darwin-mips.mk b/sandbox/sandbox_services.target.darwin-mips.mk
index 3c1ba8f..0b366bf 100644
--- a/sandbox/sandbox_services.target.darwin-mips.mk
+++ b/sandbox/sandbox_services.target.darwin-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services.target.darwin-x86.mk b/sandbox/sandbox_services.target.darwin-x86.mk
index 821a3b4..4606de6 100644
--- a/sandbox/sandbox_services.target.darwin-x86.mk
+++ b/sandbox/sandbox_services.target.darwin-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services.target.darwin-x86_64.mk b/sandbox/sandbox_services.target.darwin-x86_64.mk
new file mode 100644
index 0000000..9cddbca
--- /dev/null
+++ b/sandbox/sandbox_services.target.darwin-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sandbox_sandbox_services_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sandbox/linux/services/broker_process.cc \
+	sandbox/linux/services/init_process_reaper.cc \
+	sandbox/linux/services/scoped_process.cc \
+	sandbox/linux/services/thread_helpers.cc \
+	sandbox/linux/services/yama.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sandbox \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sandbox \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_sandbox_services_gyp
+
+# Alias gyp target name.
+.PHONY: sandbox_services
+sandbox_services: sandbox_sandbox_services_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sandbox/sandbox_services.target.linux-arm.mk b/sandbox/sandbox_services.target.linux-arm.mk
index 3a35021..b28f494 100644
--- a/sandbox/sandbox_services.target.linux-arm.mk
+++ b/sandbox/sandbox_services.target.linux-arm.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services.target.linux-mips.mk b/sandbox/sandbox_services.target.linux-mips.mk
index 3c1ba8f..0b366bf 100644
--- a/sandbox/sandbox_services.target.linux-mips.mk
+++ b/sandbox/sandbox_services.target.linux-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services.target.linux-x86.mk b/sandbox/sandbox_services.target.linux-x86.mk
index 821a3b4..4606de6 100644
--- a/sandbox/sandbox_services.target.linux-x86.mk
+++ b/sandbox/sandbox_services.target.linux-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services.target.linux-x86_64.mk b/sandbox/sandbox_services.target.linux-x86_64.mk
new file mode 100644
index 0000000..9cddbca
--- /dev/null
+++ b/sandbox/sandbox_services.target.linux-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sandbox_sandbox_services_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sandbox/linux/services/broker_process.cc \
+	sandbox/linux/services/init_process_reaper.cc \
+	sandbox/linux/services/scoped_process.cc \
+	sandbox/linux/services/thread_helpers.cc \
+	sandbox/linux/services/yama.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sandbox \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sandbox \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_sandbox_services_gyp
+
+# Alias gyp target name.
+.PHONY: sandbox_services
+sandbox_services: sandbox_sandbox_services_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sandbox/sandbox_services_headers.target.darwin-arm.mk b/sandbox/sandbox_services_headers.target.darwin-arm.mk
index cca5b2f..14b7924 100644
--- a/sandbox/sandbox_services_headers.target.darwin-arm.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-arm.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -160,6 +161,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services_headers.target.darwin-x86.mk b/sandbox/sandbox_services_headers.target.darwin-x86.mk
index 872d1e5..2d33593 100644
--- a/sandbox/sandbox_services_headers.target.darwin-x86.mk
+++ b/sandbox/sandbox_services_headers.target.darwin-x86.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services_headers.target.darwin-x86_64.mk b/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..999df35
--- /dev/null
+++ b/sandbox/sandbox_services_headers.target.darwin-x86_64.mk
@@ -0,0 +1,218 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := sandbox_sandbox_services_headers_gyp
+LOCAL_MODULE_STEM := sandbox_services_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/sandbox \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/sandbox \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_sandbox_services_headers_gyp
+
+# Alias gyp target name.
+.PHONY: sandbox_services_headers
+sandbox_services_headers: sandbox_sandbox_services_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/sandbox/sandbox_services_headers.target.linux-arm.mk b/sandbox/sandbox_services_headers.target.linux-arm.mk
index cca5b2f..14b7924 100644
--- a/sandbox/sandbox_services_headers.target.linux-arm.mk
+++ b/sandbox/sandbox_services_headers.target.linux-arm.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -160,6 +161,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services_headers.target.linux-x86.mk b/sandbox/sandbox_services_headers.target.linux-x86.mk
index 872d1e5..2d33593 100644
--- a/sandbox/sandbox_services_headers.target.linux-x86.mk
+++ b/sandbox/sandbox_services_headers.target.linux-x86.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -161,6 +162,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/sandbox_services_headers.target.linux-x86_64.mk b/sandbox/sandbox_services_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..999df35
--- /dev/null
+++ b/sandbox/sandbox_services_headers.target.linux-x86_64.mk
@@ -0,0 +1,218 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := sandbox_sandbox_services_headers_gyp
+LOCAL_MODULE_STEM := sandbox_services_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/sandbox \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/sandbox \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_sandbox_services_headers_gyp
+
+# Alias gyp target name.
+.PHONY: sandbox_services_headers
+sandbox_services_headers: sandbox_sandbox_services_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/sandbox/seccomp_bpf.target.darwin-arm.mk b/sandbox/seccomp_bpf.target.darwin-arm.mk
index 096ad95..1989cb8 100644
--- a/sandbox/seccomp_bpf.target.darwin-arm.mk
+++ b/sandbox/seccomp_bpf.target.darwin-arm.mk
@@ -87,6 +87,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +172,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf.target.darwin-x86.mk b/sandbox/seccomp_bpf.target.darwin-x86.mk
index 36c5af9..b45e8f8 100644
--- a/sandbox/seccomp_bpf.target.darwin-x86.mk
+++ b/sandbox/seccomp_bpf.target.darwin-x86.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf.target.darwin-x86_64.mk b/sandbox/seccomp_bpf.target.darwin-x86_64.mk
new file mode 100644
index 0000000..fe2546e
--- /dev/null
+++ b/sandbox/seccomp_bpf.target.darwin-x86_64.mk
@@ -0,0 +1,268 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sandbox_seccomp_bpf_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_services_headers_gyp)/sandbox_services_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sandbox/linux/seccomp-bpf/basicblock.cc \
+	sandbox/linux/seccomp-bpf/codegen.cc \
+	sandbox/linux/seccomp-bpf/die.cc \
+	sandbox/linux/seccomp-bpf/errorcode.cc \
+	sandbox/linux/seccomp-bpf/sandbox_bpf.cc \
+	sandbox/linux/seccomp-bpf/syscall.cc \
+	sandbox/linux/seccomp-bpf/syscall_iterator.cc \
+	sandbox/linux/seccomp-bpf/trap.cc \
+	sandbox/linux/seccomp-bpf/verifier.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_seccomp_bpf_gyp
+
+# Alias gyp target name.
+.PHONY: seccomp_bpf
+seccomp_bpf: sandbox_seccomp_bpf_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sandbox/seccomp_bpf.target.linux-arm.mk b/sandbox/seccomp_bpf.target.linux-arm.mk
index 096ad95..1989cb8 100644
--- a/sandbox/seccomp_bpf.target.linux-arm.mk
+++ b/sandbox/seccomp_bpf.target.linux-arm.mk
@@ -87,6 +87,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -171,6 +172,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf.target.linux-x86.mk b/sandbox/seccomp_bpf.target.linux-x86.mk
index 36c5af9..b45e8f8 100644
--- a/sandbox/seccomp_bpf.target.linux-x86.mk
+++ b/sandbox/seccomp_bpf.target.linux-x86.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf.target.linux-x86_64.mk b/sandbox/seccomp_bpf.target.linux-x86_64.mk
new file mode 100644
index 0000000..fe2546e
--- /dev/null
+++ b/sandbox/seccomp_bpf.target.linux-x86_64.mk
@@ -0,0 +1,268 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sandbox_seccomp_bpf_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,sandbox_sandbox_services_headers_gyp)/sandbox_services_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sandbox/linux/seccomp-bpf/basicblock.cc \
+	sandbox/linux/seccomp-bpf/codegen.cc \
+	sandbox/linux/seccomp-bpf/die.cc \
+	sandbox/linux/seccomp-bpf/errorcode.cc \
+	sandbox/linux/seccomp-bpf/sandbox_bpf.cc \
+	sandbox/linux/seccomp-bpf/syscall.cc \
+	sandbox/linux/seccomp-bpf/syscall_iterator.cc \
+	sandbox/linux/seccomp-bpf/trap.cc \
+	sandbox/linux/seccomp-bpf/verifier.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_seccomp_bpf_gyp
+
+# Alias gyp target name.
+.PHONY: seccomp_bpf
+seccomp_bpf: sandbox_seccomp_bpf_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk b/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
index cc3b7a8..b44977c 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-arm.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk b/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
index 3666889..3244003 100644
--- a/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk b/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..08ea756
--- /dev/null
+++ b/sandbox/seccomp_bpf_helpers.target.darwin-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sandbox_seccomp_bpf_helpers_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc \
+	sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc \
+	sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc \
+	sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_seccomp_bpf_helpers_gyp
+
+# Alias gyp target name.
+.PHONY: seccomp_bpf_helpers
+seccomp_bpf_helpers: sandbox_seccomp_bpf_helpers_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-arm.mk b/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
index cc3b7a8..b44977c 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-arm.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-x86.mk b/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
index 3666889..3244003 100644
--- a/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
+++ b/sandbox/seccomp_bpf_helpers.target.linux-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk b/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
new file mode 100644
index 0000000..08ea756
--- /dev/null
+++ b/sandbox/seccomp_bpf_helpers.target.linux-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sandbox_seccomp_bpf_helpers_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc \
+	sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.cc \
+	sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc \
+	sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sandbox_seccomp_bpf_helpers_gyp
+
+# Alias gyp target name.
+.PHONY: seccomp_bpf_helpers
+seccomp_bpf_helpers: sandbox_seccomp_bpf_helpers_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sandbox/win/src/interception.cc b/sandbox/win/src/interception.cc
index dde5857..597b937 100644
--- a/sandbox/win/src/interception.cc
+++ b/sandbox/win/src/interception.cc
@@ -399,7 +399,7 @@
   thunk_offset &= kPageSize - 1;
 
   // Make an aligned, padded allocation, and move the pointer to our chunk.
-  size_t thunk_bytes_padded = (thunk_bytes + kPageSize - 1) & kPageSize;
+  size_t thunk_bytes_padded = (thunk_bytes + kPageSize - 1) & ~(kPageSize - 1);
   thunk_base = reinterpret_cast<BYTE*>(
                    ::VirtualAllocEx(child, thunk_base, thunk_bytes_padded,
                                     MEM_COMMIT, PAGE_EXECUTE_READWRITE));
diff --git a/sdch/sdch.gyp b/sdch/sdch.gyp
index af65409..ff2c077 100644
--- a/sdch/sdch.gyp
+++ b/sdch/sdch.gyp
@@ -58,8 +58,6 @@
         [ 'OS == "ios"', { 'include_dirs': [ 'ios' ] } ],
         [ 'OS == "mac"', { 'include_dirs': [ 'mac' ] } ],
         [ 'OS == "win"', { 'include_dirs': [ 'win' ] } ],
-        # TODO(mark): Remove usage of the deprecated auto_ptr.
-        [ 'clang == 1', { 'cflags': [ '-Wno-deprecated-declarations' ] } ],
       ],
       # open-vcdiff's logging.h introduces static initializers. This was
       # reported upstream years ago (
@@ -96,7 +94,11 @@
           ]
         }
       },
-      'cflags': [ '-include', '<(logging_dir)/sdch/<(logging_path)' ],
+      'cflags': [
+        '-include', '<(logging_dir)/sdch/<(logging_path)',
+        # TODO(mostynb): remove this if open-vcdiff is ever updated for c++11:
+        '-Wno-deprecated-declarations',
+      ],
     },
   ],
 }
diff --git a/sdch/sdch.target.darwin-arm.mk b/sdch/sdch.target.darwin-arm.mk
index e592276..c5557d0 100644
--- a/sdch/sdch.target.darwin-arm.mk
+++ b/sdch/sdch.target.darwin-arm.mk
@@ -50,6 +50,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-fno-tree-sra \
 	-fuse-ld=gold \
 	-Wno-psabi \
@@ -89,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -139,6 +141,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-fno-tree-sra \
 	-fuse-ld=gold \
 	-Wno-psabi \
@@ -178,6 +181,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sdch/sdch.target.darwin-mips.mk b/sdch/sdch.target.darwin-mips.mk
index af993c8..a158c9f 100644
--- a/sdch/sdch.target.darwin-mips.mk
+++ b/sdch/sdch.target.darwin-mips.mk
@@ -50,6 +50,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-EL \
 	-mhard-float \
 	-ffunction-sections \
@@ -88,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -138,6 +140,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-EL \
 	-mhard-float \
 	-ffunction-sections \
@@ -176,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sdch/sdch.target.darwin-x86.mk b/sdch/sdch.target.darwin-x86.mk
index 2ea9056..6b67084 100644
--- a/sdch/sdch.target.darwin-x86.mk
+++ b/sdch/sdch.target.darwin-x86.mk
@@ -49,6 +49,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-msse2 \
 	-mfpmath=sse \
 	-mmmx \
@@ -90,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -138,6 +140,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-msse2 \
 	-mfpmath=sse \
 	-mmmx \
@@ -179,6 +182,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sdch/sdch.target.darwin-x86_64.mk b/sdch/sdch.target.darwin-x86_64.mk
new file mode 100644
index 0000000..fbf73d7
--- /dev/null
+++ b/sdch/sdch.target.darwin-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sdch_sdch_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sdch/open-vcdiff/src/addrcache.cc \
+	sdch/open-vcdiff/src/blockhash.cc \
+	sdch/open-vcdiff/src/codetable.cc \
+	sdch/open-vcdiff/src/decodetable.cc \
+	sdch/open-vcdiff/src/encodetable.cc \
+	sdch/open-vcdiff/src/headerparser.cc \
+	sdch/open-vcdiff/src/instruction_map.cc \
+	sdch/open-vcdiff/src/varint_bigendian.cc \
+	sdch/open-vcdiff/src/vcdecoder.cc \
+	sdch/open-vcdiff/src/vcdiffengine.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-include \
+	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(LOCAL_PATH)/sdch/linux \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-include \
+	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(LOCAL_PATH)/sdch/linux \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sdch_sdch_gyp
+
+# Alias gyp target name.
+.PHONY: sdch
+sdch: sdch_sdch_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sdch/sdch.target.linux-arm.mk b/sdch/sdch.target.linux-arm.mk
index e592276..c5557d0 100644
--- a/sdch/sdch.target.linux-arm.mk
+++ b/sdch/sdch.target.linux-arm.mk
@@ -50,6 +50,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-fno-tree-sra \
 	-fuse-ld=gold \
 	-Wno-psabi \
@@ -89,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -139,6 +141,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-fno-tree-sra \
 	-fuse-ld=gold \
 	-Wno-psabi \
@@ -178,6 +181,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sdch/sdch.target.linux-mips.mk b/sdch/sdch.target.linux-mips.mk
index af993c8..a158c9f 100644
--- a/sdch/sdch.target.linux-mips.mk
+++ b/sdch/sdch.target.linux-mips.mk
@@ -50,6 +50,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-EL \
 	-mhard-float \
 	-ffunction-sections \
@@ -88,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -138,6 +140,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-EL \
 	-mhard-float \
 	-ffunction-sections \
@@ -176,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sdch/sdch.target.linux-x86.mk b/sdch/sdch.target.linux-x86.mk
index 2ea9056..6b67084 100644
--- a/sdch/sdch.target.linux-x86.mk
+++ b/sdch/sdch.target.linux-x86.mk
@@ -49,6 +49,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-msse2 \
 	-mfpmath=sse \
 	-mmmx \
@@ -90,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -138,6 +140,7 @@
 	-fPIC \
 	-include \
 	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
 	-msse2 \
 	-mfpmath=sse \
 	-mmmx \
@@ -179,6 +182,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sdch/sdch.target.linux-x86_64.mk b/sdch/sdch.target.linux-x86_64.mk
new file mode 100644
index 0000000..fbf73d7
--- /dev/null
+++ b/sdch/sdch.target.linux-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sdch_sdch_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sdch/open-vcdiff/src/addrcache.cc \
+	sdch/open-vcdiff/src/blockhash.cc \
+	sdch/open-vcdiff/src/codetable.cc \
+	sdch/open-vcdiff/src/decodetable.cc \
+	sdch/open-vcdiff/src/encodetable.cc \
+	sdch/open-vcdiff/src/headerparser.cc \
+	sdch/open-vcdiff/src/instruction_map.cc \
+	sdch/open-vcdiff/src/varint_bigendian.cc \
+	sdch/open-vcdiff/src/vcdecoder.cc \
+	sdch/open-vcdiff/src/vcdiffengine.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-include \
+	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(LOCAL_PATH)/sdch/linux \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-include \
+	./sdch/logging_forward.h \
+	-Wno-deprecated-declarations \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/sdch/open-vcdiff/src \
+	$(LOCAL_PATH)/sdch/linux \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sdch_sdch_gyp
+
+# Alias gyp target name.
+.PHONY: sdch
+sdch: sdch_sdch_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/ext/analysis_canvas.cc b/skia/ext/analysis_canvas.cc
index 2cd74d8..524fd18 100644
--- a/skia/ext/analysis_canvas.cc
+++ b/skia/ext/analysis_canvas.cc
@@ -40,7 +40,7 @@
 // Returns true if the specified drawn_rect will cover the entire canvas, and
 // that the canvas is not clipped (i.e. it covers ALL of the canvas).
 bool IsFullQuad(SkCanvas* canvas, const SkRect& drawn_rect) {
-  if (SkCanvas::kRect_ClipType != canvas->getClipType())
+  if (!canvas->isClipRect())
     return false;
 
   SkIRect clip_irect;
diff --git a/skia/ext/analysis_canvas_unittest.cc b/skia/ext/analysis_canvas_unittest.cc
index bc74053..2b668c5 100644
--- a/skia/ext/analysis_canvas_unittest.cc
+++ b/skia/ext/analysis_canvas_unittest.cc
@@ -235,7 +235,7 @@
   paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
 
   // This should force non-transparency
-  canvas.saveLayer(&bounds, &paint, SkCanvas::kMatrix_SaveFlag);
+  canvas.saveLayer(&bounds, &paint);
   EXPECT_TRUE(canvas.GetColorIfSolid(&outputColor));
   EXPECT_NE(static_cast<SkColor>(SK_ColorTRANSPARENT), outputColor);
 
@@ -249,7 +249,7 @@
   paint.setXfermodeMode(SkXfermode::kDst_Mode);
 
   // This should force non-solid color
-  canvas.saveLayer(&bounds, &paint, SkCanvas::kMatrix_SaveFlag);
+  canvas.saveLayer(&bounds, &paint);
   EXPECT_FALSE(canvas.GetColorIfSolid(&outputColor));
 
   TransparentFill(canvas);
diff --git a/skia/ext/pixel_ref_utils.cc b/skia/ext/pixel_ref_utils.cc
index 26aef37..22d42e7 100644
--- a/skia/ext/pixel_ref_utils.cc
+++ b/skia/ext/pixel_ref_utils.cc
@@ -14,6 +14,7 @@
 #include "third_party/skia/include/core/SkRRect.h"
 #include "third_party/skia/include/core/SkRect.h"
 #include "third_party/skia/include/core/SkShader.h"
+#include "third_party/skia/include/utils/SkNoSaveLayerCanvas.h"
 #include "third_party/skia/src/core/SkRasterClip.h"
 
 namespace skia {
@@ -313,12 +314,23 @@
                           const SkPaint&) SK_OVERRIDE {}
 
  protected:
+#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
   virtual bool onReadPixels(const SkBitmap& bitmap,
                             int x,
                             int y,
                             SkCanvas::Config8888 config8888) SK_OVERRIDE {
     return false;
   }
+#endif
+
+  virtual bool onReadPixels(const SkImageInfo& info,
+                            void* pixels,
+                            size_t rowBytes,
+                            int x,
+                            int y) SK_OVERRIDE {
+    return false;
+  }
+
   virtual bool onWritePixels(const SkImageInfo& info,
                              const void* pixels,
                              size_t rowBytes,
@@ -349,42 +361,6 @@
   }
 };
 
-class NoSaveLayerCanvas : public SkCanvas {
- public:
-  NoSaveLayerCanvas(SkBaseDevice* device) : INHERITED(device) {}
-
- protected:
-  // Turn saveLayer() into save() for speed, should not affect correctness.
-  virtual SaveLayerStrategy willSaveLayer(const SkRect* bounds,
-                                          const SkPaint* paint,
-                                          SaveFlags flags) SK_OVERRIDE {
-      this->INHERITED::willSaveLayer(bounds, paint, flags);
-      return kNoLayer_SaveLayerStrategy;
-  }
-
-  // Disable aa for speed.
-  virtual void onClipRect(const SkRect& rect, 
-                          SkRegion::Op op,
-                          ClipEdgeStyle edge_style) SK_OVERRIDE {
-    this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle);
-  }
-
-  virtual void onClipPath(const SkPath& path, 
-                          SkRegion::Op op,
-                          ClipEdgeStyle edge_style) SK_OVERRIDE {
-    this->updateClipConservativelyUsingBounds(path.getBounds(), op, 
-                                              path.isInverseFillType());
-  }
-  virtual void onClipRRect(const SkRRect& rrect, 
-                           SkRegion::Op op,
-                           ClipEdgeStyle edge_style) SK_OVERRIDE {
-    this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
-  }
-
- private:
-  typedef SkCanvas INHERITED;
-};
-
 }  // namespace
 
 void PixelRefUtils::GatherDiscardablePixelRefs(
@@ -398,7 +374,7 @@
       SkBitmap::kNo_Config, picture->width(), picture->height());
 
   GatherPixelRefDevice device(empty_bitmap, &pixel_ref_set);
-  NoSaveLayerCanvas canvas(&device);
+  SkNoSaveLayerCanvas canvas(&device);
 
   canvas.clipRect(SkRect::MakeWH(picture->width(), picture->height()),
                   SkRegion::kIntersect_Op,
diff --git a/skia/ext/vector_platform_device_emf_win.cc b/skia/ext/vector_platform_device_emf_win.cc
index fed54ac..20680a2 100644
--- a/skia/ext/vector_platform_device_emf_win.cc
+++ b/skia/ext/vector_platform_device_emf_win.cc
@@ -696,12 +696,21 @@
   LoadClippingRegionToDC(hdc_, clip_region_, t);
 }
 
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
 SkBaseDevice* VectorPlatformDeviceEmf::onCreateCompatibleDevice(
     SkBitmap::Config config, int width, int height, bool isOpaque,
     Usage /*usage*/) {
   SkASSERT(config == SkBitmap::kARGB_8888_Config);
   return VectorPlatformDeviceEmf::CreateDevice(width, height, isOpaque, NULL);
 }
+#endif
+
+SkBaseDevice* VectorPlatformDeviceEmf::onCreateDevice(const SkImageInfo& info,
+                                                      Usage /*usage*/) {
+  SkASSERT(info.colorType() == kPMColor_SkColorType);
+  return VectorPlatformDeviceEmf::CreateDevice(
+      info.width(), info.height(), info.isOpaque(), NULL);
+}
 
 bool VectorPlatformDeviceEmf::CreateBrush(bool use_brush, COLORREF color) {
   SkASSERT(previous_brush_ == NULL);
diff --git a/skia/ext/vector_platform_device_emf_win.h b/skia/ext/vector_platform_device_emf_win.h
index 6f50d07..844624f 100644
--- a/skia/ext/vector_platform_device_emf_win.h
+++ b/skia/ext/vector_platform_device_emf_win.h
@@ -79,9 +79,13 @@
   void LoadClipRegion();
 
  protected:
+#ifdef SK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG
   virtual SkBaseDevice* onCreateCompatibleDevice(SkBitmap::Config, int width,
                                                  int height, bool isOpaque,
                                                  Usage usage) OVERRIDE;
+#endif
+  virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info,
+                                       Usage usage) OVERRIDE;
 
  private:
   // Applies the SkPaint's painting properties in the current GDI context, if
diff --git a/skia/skia.target.darwin-x86_64.mk b/skia/skia.target.darwin-x86_64.mk
new file mode 100644
index 0000000..96515a8
--- /dev/null
+++ b/skia/skia.target.darwin-x86_64.mk
@@ -0,0 +1,40 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := skia_skia_gyp
+LOCAL_MODULE_STEM := skia
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_gyp
+
+# Alias gyp target name.
+.PHONY: skia
+skia: skia_skia_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/skia/skia.target.linux-x86_64.mk b/skia/skia.target.linux-x86_64.mk
new file mode 100644
index 0000000..96515a8
--- /dev/null
+++ b/skia/skia.target.linux-x86_64.mk
@@ -0,0 +1,40 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := skia_skia_gyp
+LOCAL_MODULE_STEM := skia
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_chrome_gyp)/skia_skia_chrome_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_gyp
+
+# Alias gyp target name.
+.PHONY: skia
+skia: skia_skia_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/skia/skia_chrome.target.darwin-arm.mk b/skia/skia_chrome.target.darwin-arm.mk
index 9f47e91..012a994 100644
--- a/skia/skia_chrome.target.darwin-arm.mk
+++ b/skia/skia_chrome.target.darwin-arm.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -134,6 +132,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -239,9 +238,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -263,6 +260,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.darwin-mips.mk b/skia/skia_chrome.target.darwin-mips.mk
index a7f2314..0f1b05a 100644
--- a/skia/skia_chrome.target.darwin-mips.mk
+++ b/skia/skia_chrome.target.darwin-mips.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -133,6 +131,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -238,9 +237,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -261,6 +258,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.darwin-x86.mk b/skia/skia_chrome.target.darwin-x86.mk
index 6b439ad..61cb3b7 100644
--- a/skia/skia_chrome.target.darwin-x86.mk
+++ b/skia/skia_chrome.target.darwin-x86.mk
@@ -111,9 +111,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -134,6 +132,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -239,9 +238,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -262,6 +259,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.darwin-x86_64.mk b/skia/skia_chrome.target.darwin-x86_64.mk
new file mode 100644
index 0000000..8e31f79
--- /dev/null
+++ b/skia/skia_chrome.target.darwin-x86_64.mk
@@ -0,0 +1,365 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_chrome_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/SkMemory_new_handler.cc: $(LOCAL_PATH)/skia/ext/SkMemory_new_handler.cpp
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/SkMemory_new_handler.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(LOCAL_PATH)/skia/ext
+
+LOCAL_SRC_FILES := \
+	skia/ext/analysis_canvas.cc \
+	skia/ext/benchmarking_canvas.cc \
+	skia/ext/bitmap_platform_device_skia.cc \
+	skia/ext/convolver.cc \
+	skia/ext/event_tracer_impl.cc \
+	skia/ext/google_logging.cc \
+	skia/ext/image_operations.cc \
+	skia/ext/lazy_pixel_ref.cc \
+	skia/ext/opacity_draw_filter.cc \
+	skia/ext/paint_simplifier.cc \
+	skia/ext/pixel_ref_utils.cc \
+	skia/ext/platform_canvas.cc \
+	skia/ext/platform_device.cc \
+	skia/ext/platform_device_linux.cc \
+	skia/ext/recursive_gaussian_convolution.cc \
+	skia/ext/SkDiscardableMemory_chrome.cc \
+	skia/ext/skia_utils_base.cc \
+	skia/ext/vector_platform_device_skia.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_chrome_gyp
+
+# Alias gyp target name.
+.PHONY: skia_chrome
+skia_chrome: skia_skia_chrome_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_chrome.target.linux-arm.mk b/skia/skia_chrome.target.linux-arm.mk
index 9f47e91..012a994 100644
--- a/skia/skia_chrome.target.linux-arm.mk
+++ b/skia/skia_chrome.target.linux-arm.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -134,6 +132,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -239,9 +238,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -263,6 +260,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.linux-mips.mk b/skia/skia_chrome.target.linux-mips.mk
index a7f2314..0f1b05a 100644
--- a/skia/skia_chrome.target.linux-mips.mk
+++ b/skia/skia_chrome.target.linux-mips.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -133,6 +131,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -238,9 +237,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -261,6 +258,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.linux-x86.mk b/skia/skia_chrome.target.linux-x86.mk
index 6b439ad..61cb3b7 100644
--- a/skia/skia_chrome.target.linux-x86.mk
+++ b/skia/skia_chrome.target.linux-x86.mk
@@ -111,9 +111,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -134,6 +132,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -239,9 +238,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -262,6 +259,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome.target.linux-x86_64.mk b/skia/skia_chrome.target.linux-x86_64.mk
new file mode 100644
index 0000000..8e31f79
--- /dev/null
+++ b/skia/skia_chrome.target.linux-x86_64.mk
@@ -0,0 +1,365 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_chrome_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/SkMemory_new_handler.cc: $(LOCAL_PATH)/skia/ext/SkMemory_new_handler.cpp
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/SkMemory_new_handler.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(LOCAL_PATH)/skia/ext
+
+LOCAL_SRC_FILES := \
+	skia/ext/analysis_canvas.cc \
+	skia/ext/benchmarking_canvas.cc \
+	skia/ext/bitmap_platform_device_skia.cc \
+	skia/ext/convolver.cc \
+	skia/ext/event_tracer_impl.cc \
+	skia/ext/google_logging.cc \
+	skia/ext/image_operations.cc \
+	skia/ext/lazy_pixel_ref.cc \
+	skia/ext/opacity_draw_filter.cc \
+	skia/ext/paint_simplifier.cc \
+	skia/ext/pixel_ref_utils.cc \
+	skia/ext/platform_canvas.cc \
+	skia/ext/platform_device.cc \
+	skia/ext/platform_device_linux.cc \
+	skia/ext/recursive_gaussian_convolution.cc \
+	skia/ext/SkDiscardableMemory_chrome.cc \
+	skia/ext/skia_utils_base.cc \
+	skia/ext/vector_platform_device_skia.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_chrome_gyp
+
+# Alias gyp target name.
+.PHONY: skia_chrome
+skia_chrome: skia_skia_chrome_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_chrome_opts.target.darwin-mips.mk b/skia/skia_chrome_opts.target.darwin-mips.mk
index f9bf013..299450e 100644
--- a/skia/skia_chrome_opts.target.darwin-mips.mk
+++ b/skia/skia_chrome_opts.target.darwin-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome_opts.target.darwin-x86.mk b/skia/skia_chrome_opts.target.darwin-x86.mk
index 0c5e7be..c8d9c0a 100644
--- a/skia/skia_chrome_opts.target.darwin-x86.mk
+++ b/skia/skia_chrome_opts.target.darwin-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome_opts.target.darwin-x86_64.mk b/skia/skia_chrome_opts.target.darwin-x86_64.mk
new file mode 100644
index 0000000..850e11a
--- /dev/null
+++ b/skia/skia_chrome_opts.target.darwin-x86_64.mk
@@ -0,0 +1,264 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_chrome_opts_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	skia/ext/convolver_SSE2.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_chrome_opts_gyp
+
+# Alias gyp target name.
+.PHONY: skia_chrome_opts
+skia_chrome_opts: skia_skia_chrome_opts_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_chrome_opts.target.linux-mips.mk b/skia/skia_chrome_opts.target.linux-mips.mk
index f9bf013..299450e 100644
--- a/skia/skia_chrome_opts.target.linux-mips.mk
+++ b/skia/skia_chrome_opts.target.linux-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome_opts.target.linux-x86.mk b/skia/skia_chrome_opts.target.linux-x86.mk
index 0c5e7be..c8d9c0a 100644
--- a/skia/skia_chrome_opts.target.linux-x86.mk
+++ b/skia/skia_chrome_opts.target.linux-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_chrome_opts.target.linux-x86_64.mk b/skia/skia_chrome_opts.target.linux-x86_64.mk
new file mode 100644
index 0000000..850e11a
--- /dev/null
+++ b/skia/skia_chrome_opts.target.linux-x86_64.mk
@@ -0,0 +1,264 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_chrome_opts_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	skia/ext/convolver_SSE2.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_chrome_opts_gyp
+
+# Alias gyp target name.
+.PHONY: skia_chrome_opts
+skia_chrome_opts: skia_skia_chrome_opts_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi
index fa4c9db..05f1933 100644
--- a/skia/skia_library.gypi
+++ b/skia/skia_library.gypi
@@ -42,6 +42,10 @@
     '../third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp',
     '../third_party/skia/src/ports/SkFontHost_fontconfig.cpp',
 
+    '../third_party/skia/src/fonts/SkFontMgr_indirect.cpp',
+    '../third_party/skia/src/fonts/SkRemotableFontMgr.cpp',
+    '../third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp',
+
     '../third_party/skia/src/ports/SkFontHost_FreeType.cpp',
     '../third_party/skia/src/ports/SkFontHost_FreeType_common.cpp',
     '../third_party/skia/src/ports/SkFontHost_FreeType_common.h',
@@ -66,6 +70,7 @@
     '../third_party/skia/include/utils/mac/SkCGUtils.h',
     '../third_party/skia/include/utils/SkDeferredCanvas.h',
     '../third_party/skia/include/utils/SkMatrix44.h',
+    '../third_party/skia/include/utils/SkNoSaveLayerCanvas.h',
     '../third_party/skia/src/utils/debugger/SkDebugCanvas.cpp',
     '../third_party/skia/src/utils/debugger/SkDebugCanvas.h',
     '../third_party/skia/src/utils/debugger/SkDrawCommand.cpp',
@@ -89,19 +94,26 @@
     '../third_party/skia/src/utils/SkProxyCanvas.cpp',
     '../third_party/skia/src/utils/SkRTConf.cpp',
     '../third_party/skia/include/utils/SkRTConf.h',
+    '../third_party/skia/src/utils/win/SkDWrite.h',
+    '../third_party/skia/src/utils/win/SkDWrite.cpp',
     '../third_party/skia/src/utils/win/SkDWriteFontFileStream.cpp',
     '../third_party/skia/src/utils/win/SkDWriteFontFileStream.h',
     '../third_party/skia/src/utils/win/SkDWriteGeometrySink.cpp',
     '../third_party/skia/src/utils/win/SkDWriteGeometrySink.h',
     '../third_party/skia/src/utils/win/SkHRESULT.cpp',
 
-    '../third_party/skia/include/ports/SkTypeface_win.h',
-
     '../third_party/skia/include/images/SkImageRef.h',
     '../third_party/skia/include/images/SkImageRef_GlobalPool.h',
     '../third_party/skia/include/images/SkMovie.h',
     '../third_party/skia/include/images/SkPageFlipper.h',
 
+    '../third_party/skia/include/ports/SkFontConfigInterface.h',
+    '../third_party/skia/include/ports/SkFontMgr.h',
+    '../third_party/skia/include/ports/SkFontMgr_indirect.h',
+    '../third_party/skia/include/ports/SkFontStyle.h',
+    '../third_party/skia/include/ports/SkRemotableFontMgr.h',
+    '../third_party/skia/include/ports/SkTypeface_win.h',
+
     '../third_party/skia/include/utils/SkNullCanvas.h',
     '../third_party/skia/include/utils/SkPictureUtils.h',
     '../third_party/skia/include/utils/SkProxyCanvas.h',
@@ -282,7 +294,10 @@
       'sources!': [
         '../third_party/skia/src/ports/SkFontHost_win_dw.cpp',
         '../third_party/skia/src/ports/SkFontMgr_default_gdi.cpp',
+        '../third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp',
 
+        '../third_party/skia/src/utils/win/SkDWrite.h',
+        '../third_party/skia/src/utils/win/SkDWrite.cpp',
         '../third_party/skia/src/utils/win/SkDWriteFontFileStream.cpp',
         '../third_party/skia/src/utils/win/SkDWriteFontFileStream.h',
         '../third_party/skia/src/utils/win/SkDWriteGeometrySink.cpp',
diff --git a/skia/skia_library.target.darwin-arm.mk b/skia/skia_library.target.darwin-arm.mk
index 41a8bf2..738b49a 100644
--- a/skia/skia_library.target.darwin-arm.mk
+++ b/skia/skia_library.target.darwin-arm.mk
@@ -31,6 +31,8 @@
 	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
 	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
 	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
 	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
@@ -277,6 +279,7 @@
 	third_party/skia/src/effects/SkTableMaskFilter.cpp \
 	third_party/skia/src/effects/SkTestImageFilters.cpp \
 	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
 	third_party/skia/src/effects/SkTransparentShader.cpp \
 	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
 	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
@@ -341,6 +344,7 @@
 	third_party/skia/src/gpu/GrStencil.cpp \
 	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
 	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
 	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
 	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
 	third_party/skia/src/gpu/GrSurface.cpp \
@@ -457,9 +461,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -481,6 +483,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -597,9 +600,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -621,6 +622,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.darwin-mips.mk b/skia/skia_library.target.darwin-mips.mk
index 3ef7430..e72da4b 100644
--- a/skia/skia_library.target.darwin-mips.mk
+++ b/skia/skia_library.target.darwin-mips.mk
@@ -31,6 +31,8 @@
 	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
 	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
 	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
 	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
@@ -277,6 +279,7 @@
 	third_party/skia/src/effects/SkTableMaskFilter.cpp \
 	third_party/skia/src/effects/SkTestImageFilters.cpp \
 	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
 	third_party/skia/src/effects/SkTransparentShader.cpp \
 	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
 	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
@@ -341,6 +344,7 @@
 	third_party/skia/src/gpu/GrStencil.cpp \
 	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
 	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
 	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
 	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
 	third_party/skia/src/gpu/GrSurface.cpp \
@@ -456,9 +460,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -479,6 +481,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -595,9 +598,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -618,6 +619,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.darwin-x86.mk b/skia/skia_library.target.darwin-x86.mk
index 8b8be1c..e8aeef1 100644
--- a/skia/skia_library.target.darwin-x86.mk
+++ b/skia/skia_library.target.darwin-x86.mk
@@ -32,6 +32,8 @@
 	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
 	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
 	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
 	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
@@ -278,6 +280,7 @@
 	third_party/skia/src/effects/SkTableMaskFilter.cpp \
 	third_party/skia/src/effects/SkTestImageFilters.cpp \
 	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
 	third_party/skia/src/effects/SkTransparentShader.cpp \
 	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
 	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
@@ -342,6 +345,7 @@
 	third_party/skia/src/gpu/GrStencil.cpp \
 	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
 	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
 	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
 	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
 	third_party/skia/src/gpu/GrSurface.cpp \
@@ -458,9 +462,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -481,6 +483,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -597,9 +600,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -620,6 +621,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.darwin-x86_64.mk b/skia/skia_library.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d475696
--- /dev/null
+++ b/skia/skia_library.target.darwin-x86_64.mk
@@ -0,0 +1,737 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_library_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/skia/src/core/SkFlate.cpp \
+	third_party/skia/src/core/SkPaintOptionsAndroid.cpp \
+	third_party/skia/src/ports/SkImageDecoder_empty.cpp \
+	third_party/skia/src/images/SkScaledBitmapSampler.cpp \
+	third_party/skia/src/opts/opts_check_SSE2.cpp \
+	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
+	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
+	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
+	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
+	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
+	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
+	third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp \
+	third_party/skia/src/ports/SkOSFile_posix.cpp \
+	third_party/skia/src/ports/SkOSFile_stdio.cpp \
+	third_party/skia/src/ports/SkTime_Unix.cpp \
+	third_party/skia/src/ports/SkTLS_pthread.cpp \
+	third_party/skia/src/sfnt/SkOTTable_name.cpp \
+	third_party/skia/src/sfnt/SkOTUtils.cpp \
+	third_party/skia/src/utils/debugger/SkDebugCanvas.cpp \
+	third_party/skia/src/utils/debugger/SkDrawCommand.cpp \
+	third_party/skia/src/utils/debugger/SkObjectParser.cpp \
+	third_party/skia/src/utils/SkBase64.cpp \
+	third_party/skia/src/utils/SkBitSet.cpp \
+	third_party/skia/src/utils/SkCanvasStack.cpp \
+	third_party/skia/src/utils/SkCanvasStateUtils.cpp \
+	third_party/skia/src/utils/SkEventTracer.cpp \
+	third_party/skia/src/utils/SkDeferredCanvas.cpp \
+	third_party/skia/src/utils/SkMatrix44.cpp \
+	third_party/skia/src/utils/SkNullCanvas.cpp \
+	third_party/skia/src/utils/SkNWayCanvas.cpp \
+	third_party/skia/src/utils/SkPictureUtils.cpp \
+	third_party/skia/src/utils/SkProxyCanvas.cpp \
+	third_party/skia/src/utils/SkRTConf.cpp \
+	third_party/skia/src/core/SkAAClip.cpp \
+	third_party/skia/src/core/SkAnnotation.cpp \
+	third_party/skia/src/core/SkAdvancedTypefaceMetrics.cpp \
+	third_party/skia/src/core/SkAlphaRuns.cpp \
+	third_party/skia/src/core/SkBBoxRecord.cpp \
+	third_party/skia/src/core/SkBBoxHierarchyRecord.cpp \
+	third_party/skia/src/core/SkBitmap.cpp \
+	third_party/skia/src/core/SkBitmapDevice.cpp \
+	third_party/skia/src/core/SkBitmapFilter.cpp \
+	third_party/skia/src/core/SkBitmapHeap.cpp \
+	third_party/skia/src/core/SkBitmapProcShader.cpp \
+	third_party/skia/src/core/SkBitmapProcState.cpp \
+	third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp \
+	third_party/skia/src/core/SkBitmapScaler.cpp \
+	third_party/skia/src/core/SkBitmap_scroll.cpp \
+	third_party/skia/src/core/SkBlitMask_D32.cpp \
+	third_party/skia/src/core/SkBlitRow_D16.cpp \
+	third_party/skia/src/core/SkBlitRow_D32.cpp \
+	third_party/skia/src/core/SkBlitter.cpp \
+	third_party/skia/src/core/SkBlitter_A8.cpp \
+	third_party/skia/src/core/SkBlitter_ARGB32.cpp \
+	third_party/skia/src/core/SkBlitter_RGB16.cpp \
+	third_party/skia/src/core/SkBlitter_Sprite.cpp \
+	third_party/skia/src/core/SkBuffer.cpp \
+	third_party/skia/src/core/SkCanvas.cpp \
+	third_party/skia/src/core/SkChunkAlloc.cpp \
+	third_party/skia/src/core/SkClipStack.cpp \
+	third_party/skia/src/core/SkColor.cpp \
+	third_party/skia/src/core/SkColorFilter.cpp \
+	third_party/skia/src/core/SkColorTable.cpp \
+	third_party/skia/src/core/SkComposeShader.cpp \
+	third_party/skia/src/core/SkConfig8888.cpp \
+	third_party/skia/src/core/SkConvolver.cpp \
+	third_party/skia/src/core/SkCubicClipper.cpp \
+	third_party/skia/src/core/SkData.cpp \
+	third_party/skia/src/core/SkDataTable.cpp \
+	third_party/skia/src/core/SkDebug.cpp \
+	third_party/skia/src/core/SkDeque.cpp \
+	third_party/skia/src/core/SkDevice.cpp \
+	third_party/skia/src/core/SkDeviceLooper.cpp \
+	third_party/skia/src/core/SkDeviceProfile.cpp \
+	third_party/skia/src/lazy/SkDiscardableMemoryPool.cpp \
+	third_party/skia/src/lazy/SkDiscardablePixelRef.cpp \
+	third_party/skia/src/core/SkDistanceFieldGen.cpp \
+	third_party/skia/src/core/SkDither.cpp \
+	third_party/skia/src/core/SkDraw.cpp \
+	third_party/skia/src/core/SkDrawLooper.cpp \
+	third_party/skia/src/core/SkEdgeBuilder.cpp \
+	third_party/skia/src/core/SkEdgeClipper.cpp \
+	third_party/skia/src/core/SkEdge.cpp \
+	third_party/skia/src/core/SkError.cpp \
+	third_party/skia/src/core/SkFilterProc.cpp \
+	third_party/skia/src/core/SkFilterShader.cpp \
+	third_party/skia/src/core/SkFlattenable.cpp \
+	third_party/skia/src/core/SkFlattenableSerialization.cpp \
+	third_party/skia/src/core/SkFloat.cpp \
+	third_party/skia/src/core/SkFloatBits.cpp \
+	third_party/skia/src/core/SkFontHost.cpp \
+	third_party/skia/src/core/SkFontDescriptor.cpp \
+	third_party/skia/src/core/SkFontStream.cpp \
+	third_party/skia/src/core/SkGeometry.cpp \
+	third_party/skia/src/core/SkGlyphCache.cpp \
+	third_party/skia/src/core/SkGraphics.cpp \
+	third_party/skia/src/core/SkInstCnt.cpp \
+	third_party/skia/src/core/SkImageFilter.cpp \
+	third_party/skia/src/core/SkImageInfo.cpp \
+	third_party/skia/src/core/SkLineClipper.cpp \
+	third_party/skia/src/core/SkMallocPixelRef.cpp \
+	third_party/skia/src/core/SkMask.cpp \
+	third_party/skia/src/core/SkMaskFilter.cpp \
+	third_party/skia/src/core/SkMaskGamma.cpp \
+	third_party/skia/src/core/SkMath.cpp \
+	third_party/skia/src/core/SkMatrix.cpp \
+	third_party/skia/src/core/SkMatrixClipStateMgr.cpp \
+	third_party/skia/src/core/SkMetaData.cpp \
+	third_party/skia/src/core/SkMipMap.cpp \
+	third_party/skia/src/core/SkPackBits.cpp \
+	third_party/skia/src/core/SkPaint.cpp \
+	third_party/skia/src/core/SkPaintPriv.cpp \
+	third_party/skia/src/core/SkPath.cpp \
+	third_party/skia/src/core/SkPathEffect.cpp \
+	third_party/skia/src/core/SkPathHeap.cpp \
+	third_party/skia/src/core/SkPathMeasure.cpp \
+	third_party/skia/src/core/SkPathRef.cpp \
+	third_party/skia/src/core/SkPicture.cpp \
+	third_party/skia/src/core/SkPictureFlat.cpp \
+	third_party/skia/src/core/SkPicturePlayback.cpp \
+	third_party/skia/src/core/SkPictureRecord.cpp \
+	third_party/skia/src/core/SkPictureStateTree.cpp \
+	third_party/skia/src/core/SkPixelRef.cpp \
+	third_party/skia/src/core/SkPoint.cpp \
+	third_party/skia/src/core/SkProcSpriteBlitter.cpp \
+	third_party/skia/src/core/SkPtrRecorder.cpp \
+	third_party/skia/src/core/SkQuadClipper.cpp \
+	third_party/skia/src/core/SkQuadTree.cpp \
+	third_party/skia/src/core/SkQuadTreePicture.cpp \
+	third_party/skia/src/core/SkRasterClip.cpp \
+	third_party/skia/src/core/SkRasterizer.cpp \
+	third_party/skia/src/core/SkReadBuffer.cpp \
+	third_party/skia/src/core/SkRect.cpp \
+	third_party/skia/src/core/SkRefDict.cpp \
+	third_party/skia/src/core/SkRegion.cpp \
+	third_party/skia/src/core/SkRegion_path.cpp \
+	third_party/skia/src/core/SkRRect.cpp \
+	third_party/skia/src/core/SkRTree.cpp \
+	third_party/skia/src/core/SkScaledImageCache.cpp \
+	third_party/skia/src/core/SkScalar.cpp \
+	third_party/skia/src/core/SkScalerContext.cpp \
+	third_party/skia/src/core/SkScan.cpp \
+	third_party/skia/src/core/SkScan_AntiPath.cpp \
+	third_party/skia/src/core/SkScan_Antihair.cpp \
+	third_party/skia/src/core/SkScan_Hairline.cpp \
+	third_party/skia/src/core/SkScan_Path.cpp \
+	third_party/skia/src/core/SkShader.cpp \
+	third_party/skia/src/core/SkSpriteBlitter_ARGB32.cpp \
+	third_party/skia/src/core/SkSpriteBlitter_RGB16.cpp \
+	third_party/skia/src/core/SkStream.cpp \
+	third_party/skia/src/core/SkString.cpp \
+	third_party/skia/src/core/SkStringUtils.cpp \
+	third_party/skia/src/core/SkStroke.cpp \
+	third_party/skia/src/core/SkStrokeRec.cpp \
+	third_party/skia/src/core/SkStrokerPriv.cpp \
+	third_party/skia/src/core/SkTileGrid.cpp \
+	third_party/skia/src/core/SkTileGridPicture.cpp \
+	third_party/skia/src/core/SkTLS.cpp \
+	third_party/skia/src/core/SkTSearch.cpp \
+	third_party/skia/src/core/SkTypeface.cpp \
+	third_party/skia/src/core/SkTypefaceCache.cpp \
+	third_party/skia/src/core/SkUnPreMultiply.cpp \
+	third_party/skia/src/core/SkUtils.cpp \
+	third_party/skia/src/core/SkValidatingReadBuffer.cpp \
+	third_party/skia/src/core/SkWriteBuffer.cpp \
+	third_party/skia/src/core/SkWriter32.cpp \
+	third_party/skia/src/core/SkXfermode.cpp \
+	third_party/skia/src/doc/SkDocument.cpp \
+	third_party/skia/src/image/SkImage.cpp \
+	third_party/skia/src/image/SkImagePriv.cpp \
+	third_party/skia/src/image/SkImage_Codec.cpp \
+	third_party/skia/src/image/SkImage_Picture.cpp \
+	third_party/skia/src/image/SkImage_Raster.cpp \
+	third_party/skia/src/image/SkSurface.cpp \
+	third_party/skia/src/image/SkSurface_Picture.cpp \
+	third_party/skia/src/image/SkSurface_Raster.cpp \
+	third_party/skia/src/pipe/SkGPipeRead.cpp \
+	third_party/skia/src/pipe/SkGPipeWrite.cpp \
+	third_party/skia/src/lazy/SkCachingPixelRef.cpp \
+	third_party/skia/src/pathops/SkAddIntersections.cpp \
+	third_party/skia/src/pathops/SkDCubicIntersection.cpp \
+	third_party/skia/src/pathops/SkDCubicLineIntersection.cpp \
+	third_party/skia/src/pathops/SkDCubicToQuads.cpp \
+	third_party/skia/src/pathops/SkDLineIntersection.cpp \
+	third_party/skia/src/pathops/SkDQuadImplicit.cpp \
+	third_party/skia/src/pathops/SkDQuadIntersection.cpp \
+	third_party/skia/src/pathops/SkDQuadLineIntersection.cpp \
+	third_party/skia/src/pathops/SkIntersections.cpp \
+	third_party/skia/src/pathops/SkOpAngle.cpp \
+	third_party/skia/src/pathops/SkOpContour.cpp \
+	third_party/skia/src/pathops/SkOpEdgeBuilder.cpp \
+	third_party/skia/src/pathops/SkOpSegment.cpp \
+	third_party/skia/src/pathops/SkPathOpsBounds.cpp \
+	third_party/skia/src/pathops/SkPathOpsCommon.cpp \
+	third_party/skia/src/pathops/SkPathOpsCubic.cpp \
+	third_party/skia/src/pathops/SkPathOpsDebug.cpp \
+	third_party/skia/src/pathops/SkPathOpsLine.cpp \
+	third_party/skia/src/pathops/SkPathOpsOp.cpp \
+	third_party/skia/src/pathops/SkPathOpsPoint.cpp \
+	third_party/skia/src/pathops/SkPathOpsQuad.cpp \
+	third_party/skia/src/pathops/SkPathOpsRect.cpp \
+	third_party/skia/src/pathops/SkPathOpsSimplify.cpp \
+	third_party/skia/src/pathops/SkPathOpsTriangle.cpp \
+	third_party/skia/src/pathops/SkPathOpsTypes.cpp \
+	third_party/skia/src/pathops/SkPathWriter.cpp \
+	third_party/skia/src/pathops/SkQuarticRoot.cpp \
+	third_party/skia/src/pathops/SkReduceOrder.cpp \
+	third_party/skia/src/effects/Sk1DPathEffect.cpp \
+	third_party/skia/src/effects/Sk2DPathEffect.cpp \
+	third_party/skia/src/effects/SkAlphaThresholdFilter.cpp \
+	third_party/skia/src/effects/SkArithmeticMode.cpp \
+	third_party/skia/src/effects/SkAvoidXfermode.cpp \
+	third_party/skia/src/effects/SkBicubicImageFilter.cpp \
+	third_party/skia/src/effects/SkBitmapSource.cpp \
+	third_party/skia/src/effects/SkBlurDrawLooper.cpp \
+	third_party/skia/src/effects/SkBlurMask.cpp \
+	third_party/skia/src/effects/SkBlurImageFilter.cpp \
+	third_party/skia/src/effects/SkBlurMaskFilter.cpp \
+	third_party/skia/src/effects/SkColorFilters.cpp \
+	third_party/skia/src/effects/SkColorFilterImageFilter.cpp \
+	third_party/skia/src/effects/SkColorMatrix.cpp \
+	third_party/skia/src/effects/SkColorMatrixFilter.cpp \
+	third_party/skia/src/effects/SkComposeImageFilter.cpp \
+	third_party/skia/src/effects/SkCornerPathEffect.cpp \
+	third_party/skia/src/effects/SkDashPathEffect.cpp \
+	third_party/skia/src/effects/SkDiscretePathEffect.cpp \
+	third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+	third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
+	third_party/skia/src/effects/SkEmbossMask.cpp \
+	third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
+	third_party/skia/src/effects/SkGpuBlurUtils.cpp \
+	third_party/skia/src/effects/SkKernel33MaskFilter.cpp \
+	third_party/skia/src/effects/SkLayerDrawLooper.cpp \
+	third_party/skia/src/effects/SkLayerRasterizer.cpp \
+	third_party/skia/src/effects/SkLerpXfermode.cpp \
+	third_party/skia/src/effects/SkLightingImageFilter.cpp \
+	third_party/skia/src/effects/SkLumaColorFilter.cpp \
+	third_party/skia/src/effects/SkMagnifierImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixConvolutionImageFilter.cpp \
+	third_party/skia/src/effects/SkMergeImageFilter.cpp \
+	third_party/skia/src/effects/SkMorphologyImageFilter.cpp \
+	third_party/skia/src/effects/SkOffsetImageFilter.cpp \
+	third_party/skia/src/effects/SkPaintFlagsDrawFilter.cpp \
+	third_party/skia/src/effects/SkPerlinNoiseShader.cpp \
+	third_party/skia/src/effects/SkPictureImageFilter.cpp \
+	third_party/skia/src/effects/SkPixelXorXfermode.cpp \
+	third_party/skia/src/effects/SkPorterDuff.cpp \
+	third_party/skia/src/effects/SkRectShaderImageFilter.cpp \
+	third_party/skia/src/effects/SkResizeImageFilter.cpp \
+	third_party/skia/src/effects/SkStippleMaskFilter.cpp \
+	third_party/skia/src/effects/SkTableColorFilter.cpp \
+	third_party/skia/src/effects/SkTableMaskFilter.cpp \
+	third_party/skia/src/effects/SkTestImageFilters.cpp \
+	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
+	third_party/skia/src/effects/SkTransparentShader.cpp \
+	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
+	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
+	third_party/skia/src/effects/gradients/SkClampRange.cpp \
+	third_party/skia/src/effects/gradients/SkGradientShader.cpp \
+	third_party/skia/src/effects/gradients/SkLinearGradient.cpp \
+	third_party/skia/src/effects/gradients/SkRadialGradient.cpp \
+	third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp \
+	third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp \
+	third_party/skia/src/effects/gradients/SkSweepGradient.cpp \
+	third_party/skia/src/pdf/SkPDFCatalog.cpp \
+	third_party/skia/src/pdf/SkPDFDevice.cpp \
+	third_party/skia/src/pdf/SkPDFDeviceFlattener.cpp \
+	third_party/skia/src/pdf/SkPDFDocument.cpp \
+	third_party/skia/src/pdf/SkPDFFont.cpp \
+	third_party/skia/src/pdf/SkPDFFormXObject.cpp \
+	third_party/skia/src/pdf/SkPDFGraphicState.cpp \
+	third_party/skia/src/pdf/SkPDFImage.cpp \
+	third_party/skia/src/pdf/SkPDFPage.cpp \
+	third_party/skia/src/pdf/SkPDFResourceDict.cpp \
+	third_party/skia/src/pdf/SkPDFShader.cpp \
+	third_party/skia/src/pdf/SkPDFStream.cpp \
+	third_party/skia/src/pdf/SkPDFTypes.cpp \
+	third_party/skia/src/pdf/SkPDFUtils.cpp \
+	third_party/skia/src/gpu/gl/GrGLCreateNullInterface.cpp \
+	third_party/skia/src/gpu/gl/SkNullGLContext.cpp \
+	third_party/skia/src/gpu/GrAAHairLinePathRenderer.cpp \
+	third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp \
+	third_party/skia/src/gpu/GrAARectRenderer.cpp \
+	third_party/skia/src/gpu/GrAddPathRenderers_default.cpp \
+	third_party/skia/src/gpu/GrAllocPool.cpp \
+	third_party/skia/src/gpu/GrAtlas.cpp \
+	third_party/skia/src/gpu/GrBitmapTextContext.cpp \
+	third_party/skia/src/gpu/GrBlend.cpp \
+	third_party/skia/src/gpu/GrBufferAllocPool.cpp \
+	third_party/skia/src/gpu/GrCacheID.cpp \
+	third_party/skia/src/gpu/GrClipData.cpp \
+	third_party/skia/src/gpu/GrContext.cpp \
+	third_party/skia/src/gpu/GrDefaultPathRenderer.cpp \
+	third_party/skia/src/gpu/GrDistanceFieldTextContext.cpp \
+	third_party/skia/src/gpu/GrDrawState.cpp \
+	third_party/skia/src/gpu/GrDrawTarget.cpp \
+	third_party/skia/src/gpu/GrEffect.cpp \
+	third_party/skia/src/gpu/GrClipMaskCache.cpp \
+	third_party/skia/src/gpu/GrClipMaskManager.cpp \
+	third_party/skia/src/gpu/GrGpu.cpp \
+	third_party/skia/src/gpu/GrGpuFactory.cpp \
+	third_party/skia/src/gpu/GrInOrderDrawBuffer.cpp \
+	third_party/skia/src/gpu/GrMemoryPool.cpp \
+	third_party/skia/src/gpu/GrOvalRenderer.cpp \
+	third_party/skia/src/gpu/GrPaint.cpp \
+	third_party/skia/src/gpu/GrPath.cpp \
+	third_party/skia/src/gpu/GrPathRendererChain.cpp \
+	third_party/skia/src/gpu/GrPathRenderer.cpp \
+	third_party/skia/src/gpu/GrPathUtils.cpp \
+	third_party/skia/src/gpu/GrRectanizer.cpp \
+	third_party/skia/src/gpu/GrRectanizer_skyline.cpp \
+	third_party/skia/src/gpu/GrRenderTarget.cpp \
+	third_party/skia/src/gpu/GrReducedClip.cpp \
+	third_party/skia/src/gpu/GrResource.cpp \
+	third_party/skia/src/gpu/GrResourceCache.cpp \
+	third_party/skia/src/gpu/GrStencil.cpp \
+	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
+	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
+	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
+	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
+	third_party/skia/src/gpu/GrSurface.cpp \
+	third_party/skia/src/gpu/GrTextContext.cpp \
+	third_party/skia/src/gpu/GrTextStrike.cpp \
+	third_party/skia/src/gpu/GrTexture.cpp \
+	third_party/skia/src/gpu/GrTextureAccess.cpp \
+	third_party/skia/src/gpu/effects/GrConfigConversionEffect.cpp \
+	third_party/skia/src/gpu/effects/GrBezierEffect.cpp \
+	third_party/skia/src/gpu/effects/GrConvolutionEffect.cpp \
+	third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp \
+	third_party/skia/src/gpu/effects/GrBicubicEffect.cpp \
+	third_party/skia/src/gpu/effects/GrCustomCoordsTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrRRectEffect.cpp \
+	third_party/skia/src/gpu/effects/GrSimpleTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrSingleTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrTextureDomain.cpp \
+	third_party/skia/src/gpu/effects/GrTextureStripAtlas.cpp \
+	third_party/skia/src/gpu/gl/GrGLBufferImpl.cpp \
+	third_party/skia/src/gpu/gl/GrGLCaps.cpp \
+	third_party/skia/src/gpu/gl/GrGLContext.cpp \
+	third_party/skia/src/gpu/gl/GrGLCreateNativeInterface_none.cpp \
+	third_party/skia/src/gpu/gl/GrGLDefaultInterface_none.cpp \
+	third_party/skia/src/gpu/gl/GrGLExtensions.cpp \
+	third_party/skia/src/gpu/gl/GrGLIndexBuffer.cpp \
+	third_party/skia/src/gpu/gl/GrGLInterface.cpp \
+	third_party/skia/src/gpu/gl/GrGLNoOpInterface.cpp \
+	third_party/skia/src/gpu/gl/GrGLPath.cpp \
+	third_party/skia/src/gpu/gl/GrGLProgram.cpp \
+	third_party/skia/src/gpu/gl/GrGLProgramDesc.cpp \
+	third_party/skia/src/gpu/gl/GrGLProgramEffects.cpp \
+	third_party/skia/src/gpu/gl/GrGLRenderTarget.cpp \
+	third_party/skia/src/gpu/gl/GrGLShaderBuilder.cpp \
+	third_party/skia/src/gpu/gl/GrGLSL.cpp \
+	third_party/skia/src/gpu/gl/GrGLStencilBuffer.cpp \
+	third_party/skia/src/gpu/gl/GrGLTexture.cpp \
+	third_party/skia/src/gpu/gl/GrGLUtil.cpp \
+	third_party/skia/src/gpu/gl/GrGLUniformManager.cpp \
+	third_party/skia/src/gpu/gl/GrGLVertexArray.cpp \
+	third_party/skia/src/gpu/gl/GrGLVertexBuffer.cpp \
+	third_party/skia/src/gpu/gl/GrGpuGL.cpp \
+	third_party/skia/src/gpu/gl/GrGpuGL_program.cpp \
+	third_party/skia/src/gpu/SkGpuDevice.cpp \
+	third_party/skia/src/gpu/SkGr.cpp \
+	third_party/skia/src/gpu/SkGrFontScaler.cpp \
+	third_party/skia/src/gpu/SkGrPixelRef.cpp \
+	third_party/skia/src/gpu/SkGrTexturePixelRef.cpp \
+	third_party/skia/src/image/SkImage_Gpu.cpp \
+	third_party/skia/src/image/SkSurface_Gpu.cpp \
+	third_party/skia/src/gpu/gl/SkGLContextHelper.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/images \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH)/third_party/skia/src/image \
+	$(LOCAL_PATH)/third_party/skia/src/ports \
+	$(LOCAL_PATH)/third_party/skia/src/sfnt \
+	$(LOCAL_PATH)/third_party/skia/src/utils \
+	$(LOCAL_PATH)/third_party/skia/src/lazy \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/gpu \
+	$(LOCAL_PATH)/third_party/expat/files/lib \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/freetype/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/images \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH)/third_party/skia/src/image \
+	$(LOCAL_PATH)/third_party/skia/src/ports \
+	$(LOCAL_PATH)/third_party/skia/src/sfnt \
+	$(LOCAL_PATH)/third_party/skia/src/utils \
+	$(LOCAL_PATH)/third_party/skia/src/lazy \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/gpu \
+	$(LOCAL_PATH)/third_party/expat/files/lib \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/freetype/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_library_gyp
+
+# Alias gyp target name.
+.PHONY: skia_library
+skia_library: skia_skia_library_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_library.target.linux-arm.mk b/skia/skia_library.target.linux-arm.mk
index 41a8bf2..738b49a 100644
--- a/skia/skia_library.target.linux-arm.mk
+++ b/skia/skia_library.target.linux-arm.mk
@@ -31,6 +31,8 @@
 	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
 	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
 	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
 	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
@@ -277,6 +279,7 @@
 	third_party/skia/src/effects/SkTableMaskFilter.cpp \
 	third_party/skia/src/effects/SkTestImageFilters.cpp \
 	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
 	third_party/skia/src/effects/SkTransparentShader.cpp \
 	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
 	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
@@ -341,6 +344,7 @@
 	third_party/skia/src/gpu/GrStencil.cpp \
 	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
 	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
 	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
 	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
 	third_party/skia/src/gpu/GrSurface.cpp \
@@ -457,9 +461,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -481,6 +483,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -597,9 +600,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -621,6 +622,7 @@
 	'-D__ARM_HAVE_OPTIONAL_NEON_SUPPORT' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.linux-mips.mk b/skia/skia_library.target.linux-mips.mk
index 3ef7430..e72da4b 100644
--- a/skia/skia_library.target.linux-mips.mk
+++ b/skia/skia_library.target.linux-mips.mk
@@ -31,6 +31,8 @@
 	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
 	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
 	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
 	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
@@ -277,6 +279,7 @@
 	third_party/skia/src/effects/SkTableMaskFilter.cpp \
 	third_party/skia/src/effects/SkTestImageFilters.cpp \
 	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
 	third_party/skia/src/effects/SkTransparentShader.cpp \
 	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
 	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
@@ -341,6 +344,7 @@
 	third_party/skia/src/gpu/GrStencil.cpp \
 	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
 	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
 	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
 	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
 	third_party/skia/src/gpu/GrSurface.cpp \
@@ -456,9 +460,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -479,6 +481,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -595,9 +598,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -618,6 +619,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.linux-x86.mk b/skia/skia_library.target.linux-x86.mk
index 8b8be1c..e8aeef1 100644
--- a/skia/skia_library.target.linux-x86.mk
+++ b/skia/skia_library.target.linux-x86.mk
@@ -32,6 +32,8 @@
 	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
 	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
 	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
 	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
 	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
@@ -278,6 +280,7 @@
 	third_party/skia/src/effects/SkTableMaskFilter.cpp \
 	third_party/skia/src/effects/SkTestImageFilters.cpp \
 	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
 	third_party/skia/src/effects/SkTransparentShader.cpp \
 	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
 	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
@@ -342,6 +345,7 @@
 	third_party/skia/src/gpu/GrStencil.cpp \
 	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
 	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
 	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
 	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
 	third_party/skia/src/gpu/GrSurface.cpp \
@@ -458,9 +462,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -481,6 +483,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -597,9 +600,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -620,6 +621,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_library.target.linux-x86_64.mk b/skia/skia_library.target.linux-x86_64.mk
new file mode 100644
index 0000000..d475696
--- /dev/null
+++ b/skia/skia_library.target.linux-x86_64.mk
@@ -0,0 +1,737 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_library_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_skia_config_gyp)/blink_skia_config.stamp \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/skia/src/core/SkFlate.cpp \
+	third_party/skia/src/core/SkPaintOptionsAndroid.cpp \
+	third_party/skia/src/ports/SkImageDecoder_empty.cpp \
+	third_party/skia/src/images/SkScaledBitmapSampler.cpp \
+	third_party/skia/src/opts/opts_check_SSE2.cpp \
+	third_party/skia/src/ports/SkPurgeableMemoryBlock_none.cpp \
+	third_party/skia/src/ports/SkFontConfigInterface_android.cpp \
+	third_party/skia/src/ports/SkFontHost_fontconfig.cpp \
+	third_party/skia/src/fonts/SkFontMgr_indirect.cpp \
+	third_party/skia/src/fonts/SkRemotableFontMgr.cpp \
+	third_party/skia/src/ports/SkFontHost_FreeType.cpp \
+	third_party/skia/src/ports/SkFontHost_FreeType_common.cpp \
+	third_party/skia/src/ports/SkFontConfigParser_android.cpp \
+	third_party/skia/src/ports/SkGlobalInitialization_chromium.cpp \
+	third_party/skia/src/ports/SkOSFile_posix.cpp \
+	third_party/skia/src/ports/SkOSFile_stdio.cpp \
+	third_party/skia/src/ports/SkTime_Unix.cpp \
+	third_party/skia/src/ports/SkTLS_pthread.cpp \
+	third_party/skia/src/sfnt/SkOTTable_name.cpp \
+	third_party/skia/src/sfnt/SkOTUtils.cpp \
+	third_party/skia/src/utils/debugger/SkDebugCanvas.cpp \
+	third_party/skia/src/utils/debugger/SkDrawCommand.cpp \
+	third_party/skia/src/utils/debugger/SkObjectParser.cpp \
+	third_party/skia/src/utils/SkBase64.cpp \
+	third_party/skia/src/utils/SkBitSet.cpp \
+	third_party/skia/src/utils/SkCanvasStack.cpp \
+	third_party/skia/src/utils/SkCanvasStateUtils.cpp \
+	third_party/skia/src/utils/SkEventTracer.cpp \
+	third_party/skia/src/utils/SkDeferredCanvas.cpp \
+	third_party/skia/src/utils/SkMatrix44.cpp \
+	third_party/skia/src/utils/SkNullCanvas.cpp \
+	third_party/skia/src/utils/SkNWayCanvas.cpp \
+	third_party/skia/src/utils/SkPictureUtils.cpp \
+	third_party/skia/src/utils/SkProxyCanvas.cpp \
+	third_party/skia/src/utils/SkRTConf.cpp \
+	third_party/skia/src/core/SkAAClip.cpp \
+	third_party/skia/src/core/SkAnnotation.cpp \
+	third_party/skia/src/core/SkAdvancedTypefaceMetrics.cpp \
+	third_party/skia/src/core/SkAlphaRuns.cpp \
+	third_party/skia/src/core/SkBBoxRecord.cpp \
+	third_party/skia/src/core/SkBBoxHierarchyRecord.cpp \
+	third_party/skia/src/core/SkBitmap.cpp \
+	third_party/skia/src/core/SkBitmapDevice.cpp \
+	third_party/skia/src/core/SkBitmapFilter.cpp \
+	third_party/skia/src/core/SkBitmapHeap.cpp \
+	third_party/skia/src/core/SkBitmapProcShader.cpp \
+	third_party/skia/src/core/SkBitmapProcState.cpp \
+	third_party/skia/src/core/SkBitmapProcState_matrixProcs.cpp \
+	third_party/skia/src/core/SkBitmapScaler.cpp \
+	third_party/skia/src/core/SkBitmap_scroll.cpp \
+	third_party/skia/src/core/SkBlitMask_D32.cpp \
+	third_party/skia/src/core/SkBlitRow_D16.cpp \
+	third_party/skia/src/core/SkBlitRow_D32.cpp \
+	third_party/skia/src/core/SkBlitter.cpp \
+	third_party/skia/src/core/SkBlitter_A8.cpp \
+	third_party/skia/src/core/SkBlitter_ARGB32.cpp \
+	third_party/skia/src/core/SkBlitter_RGB16.cpp \
+	third_party/skia/src/core/SkBlitter_Sprite.cpp \
+	third_party/skia/src/core/SkBuffer.cpp \
+	third_party/skia/src/core/SkCanvas.cpp \
+	third_party/skia/src/core/SkChunkAlloc.cpp \
+	third_party/skia/src/core/SkClipStack.cpp \
+	third_party/skia/src/core/SkColor.cpp \
+	third_party/skia/src/core/SkColorFilter.cpp \
+	third_party/skia/src/core/SkColorTable.cpp \
+	third_party/skia/src/core/SkComposeShader.cpp \
+	third_party/skia/src/core/SkConfig8888.cpp \
+	third_party/skia/src/core/SkConvolver.cpp \
+	third_party/skia/src/core/SkCubicClipper.cpp \
+	third_party/skia/src/core/SkData.cpp \
+	third_party/skia/src/core/SkDataTable.cpp \
+	third_party/skia/src/core/SkDebug.cpp \
+	third_party/skia/src/core/SkDeque.cpp \
+	third_party/skia/src/core/SkDevice.cpp \
+	third_party/skia/src/core/SkDeviceLooper.cpp \
+	third_party/skia/src/core/SkDeviceProfile.cpp \
+	third_party/skia/src/lazy/SkDiscardableMemoryPool.cpp \
+	third_party/skia/src/lazy/SkDiscardablePixelRef.cpp \
+	third_party/skia/src/core/SkDistanceFieldGen.cpp \
+	third_party/skia/src/core/SkDither.cpp \
+	third_party/skia/src/core/SkDraw.cpp \
+	third_party/skia/src/core/SkDrawLooper.cpp \
+	third_party/skia/src/core/SkEdgeBuilder.cpp \
+	third_party/skia/src/core/SkEdgeClipper.cpp \
+	third_party/skia/src/core/SkEdge.cpp \
+	third_party/skia/src/core/SkError.cpp \
+	third_party/skia/src/core/SkFilterProc.cpp \
+	third_party/skia/src/core/SkFilterShader.cpp \
+	third_party/skia/src/core/SkFlattenable.cpp \
+	third_party/skia/src/core/SkFlattenableSerialization.cpp \
+	third_party/skia/src/core/SkFloat.cpp \
+	third_party/skia/src/core/SkFloatBits.cpp \
+	third_party/skia/src/core/SkFontHost.cpp \
+	third_party/skia/src/core/SkFontDescriptor.cpp \
+	third_party/skia/src/core/SkFontStream.cpp \
+	third_party/skia/src/core/SkGeometry.cpp \
+	third_party/skia/src/core/SkGlyphCache.cpp \
+	third_party/skia/src/core/SkGraphics.cpp \
+	third_party/skia/src/core/SkInstCnt.cpp \
+	third_party/skia/src/core/SkImageFilter.cpp \
+	third_party/skia/src/core/SkImageInfo.cpp \
+	third_party/skia/src/core/SkLineClipper.cpp \
+	third_party/skia/src/core/SkMallocPixelRef.cpp \
+	third_party/skia/src/core/SkMask.cpp \
+	third_party/skia/src/core/SkMaskFilter.cpp \
+	third_party/skia/src/core/SkMaskGamma.cpp \
+	third_party/skia/src/core/SkMath.cpp \
+	third_party/skia/src/core/SkMatrix.cpp \
+	third_party/skia/src/core/SkMatrixClipStateMgr.cpp \
+	third_party/skia/src/core/SkMetaData.cpp \
+	third_party/skia/src/core/SkMipMap.cpp \
+	third_party/skia/src/core/SkPackBits.cpp \
+	third_party/skia/src/core/SkPaint.cpp \
+	third_party/skia/src/core/SkPaintPriv.cpp \
+	third_party/skia/src/core/SkPath.cpp \
+	third_party/skia/src/core/SkPathEffect.cpp \
+	third_party/skia/src/core/SkPathHeap.cpp \
+	third_party/skia/src/core/SkPathMeasure.cpp \
+	third_party/skia/src/core/SkPathRef.cpp \
+	third_party/skia/src/core/SkPicture.cpp \
+	third_party/skia/src/core/SkPictureFlat.cpp \
+	third_party/skia/src/core/SkPicturePlayback.cpp \
+	third_party/skia/src/core/SkPictureRecord.cpp \
+	third_party/skia/src/core/SkPictureStateTree.cpp \
+	third_party/skia/src/core/SkPixelRef.cpp \
+	third_party/skia/src/core/SkPoint.cpp \
+	third_party/skia/src/core/SkProcSpriteBlitter.cpp \
+	third_party/skia/src/core/SkPtrRecorder.cpp \
+	third_party/skia/src/core/SkQuadClipper.cpp \
+	third_party/skia/src/core/SkQuadTree.cpp \
+	third_party/skia/src/core/SkQuadTreePicture.cpp \
+	third_party/skia/src/core/SkRasterClip.cpp \
+	third_party/skia/src/core/SkRasterizer.cpp \
+	third_party/skia/src/core/SkReadBuffer.cpp \
+	third_party/skia/src/core/SkRect.cpp \
+	third_party/skia/src/core/SkRefDict.cpp \
+	third_party/skia/src/core/SkRegion.cpp \
+	third_party/skia/src/core/SkRegion_path.cpp \
+	third_party/skia/src/core/SkRRect.cpp \
+	third_party/skia/src/core/SkRTree.cpp \
+	third_party/skia/src/core/SkScaledImageCache.cpp \
+	third_party/skia/src/core/SkScalar.cpp \
+	third_party/skia/src/core/SkScalerContext.cpp \
+	third_party/skia/src/core/SkScan.cpp \
+	third_party/skia/src/core/SkScan_AntiPath.cpp \
+	third_party/skia/src/core/SkScan_Antihair.cpp \
+	third_party/skia/src/core/SkScan_Hairline.cpp \
+	third_party/skia/src/core/SkScan_Path.cpp \
+	third_party/skia/src/core/SkShader.cpp \
+	third_party/skia/src/core/SkSpriteBlitter_ARGB32.cpp \
+	third_party/skia/src/core/SkSpriteBlitter_RGB16.cpp \
+	third_party/skia/src/core/SkStream.cpp \
+	third_party/skia/src/core/SkString.cpp \
+	third_party/skia/src/core/SkStringUtils.cpp \
+	third_party/skia/src/core/SkStroke.cpp \
+	third_party/skia/src/core/SkStrokeRec.cpp \
+	third_party/skia/src/core/SkStrokerPriv.cpp \
+	third_party/skia/src/core/SkTileGrid.cpp \
+	third_party/skia/src/core/SkTileGridPicture.cpp \
+	third_party/skia/src/core/SkTLS.cpp \
+	third_party/skia/src/core/SkTSearch.cpp \
+	third_party/skia/src/core/SkTypeface.cpp \
+	third_party/skia/src/core/SkTypefaceCache.cpp \
+	third_party/skia/src/core/SkUnPreMultiply.cpp \
+	third_party/skia/src/core/SkUtils.cpp \
+	third_party/skia/src/core/SkValidatingReadBuffer.cpp \
+	third_party/skia/src/core/SkWriteBuffer.cpp \
+	third_party/skia/src/core/SkWriter32.cpp \
+	third_party/skia/src/core/SkXfermode.cpp \
+	third_party/skia/src/doc/SkDocument.cpp \
+	third_party/skia/src/image/SkImage.cpp \
+	third_party/skia/src/image/SkImagePriv.cpp \
+	third_party/skia/src/image/SkImage_Codec.cpp \
+	third_party/skia/src/image/SkImage_Picture.cpp \
+	third_party/skia/src/image/SkImage_Raster.cpp \
+	third_party/skia/src/image/SkSurface.cpp \
+	third_party/skia/src/image/SkSurface_Picture.cpp \
+	third_party/skia/src/image/SkSurface_Raster.cpp \
+	third_party/skia/src/pipe/SkGPipeRead.cpp \
+	third_party/skia/src/pipe/SkGPipeWrite.cpp \
+	third_party/skia/src/lazy/SkCachingPixelRef.cpp \
+	third_party/skia/src/pathops/SkAddIntersections.cpp \
+	third_party/skia/src/pathops/SkDCubicIntersection.cpp \
+	third_party/skia/src/pathops/SkDCubicLineIntersection.cpp \
+	third_party/skia/src/pathops/SkDCubicToQuads.cpp \
+	third_party/skia/src/pathops/SkDLineIntersection.cpp \
+	third_party/skia/src/pathops/SkDQuadImplicit.cpp \
+	third_party/skia/src/pathops/SkDQuadIntersection.cpp \
+	third_party/skia/src/pathops/SkDQuadLineIntersection.cpp \
+	third_party/skia/src/pathops/SkIntersections.cpp \
+	third_party/skia/src/pathops/SkOpAngle.cpp \
+	third_party/skia/src/pathops/SkOpContour.cpp \
+	third_party/skia/src/pathops/SkOpEdgeBuilder.cpp \
+	third_party/skia/src/pathops/SkOpSegment.cpp \
+	third_party/skia/src/pathops/SkPathOpsBounds.cpp \
+	third_party/skia/src/pathops/SkPathOpsCommon.cpp \
+	third_party/skia/src/pathops/SkPathOpsCubic.cpp \
+	third_party/skia/src/pathops/SkPathOpsDebug.cpp \
+	third_party/skia/src/pathops/SkPathOpsLine.cpp \
+	third_party/skia/src/pathops/SkPathOpsOp.cpp \
+	third_party/skia/src/pathops/SkPathOpsPoint.cpp \
+	third_party/skia/src/pathops/SkPathOpsQuad.cpp \
+	third_party/skia/src/pathops/SkPathOpsRect.cpp \
+	third_party/skia/src/pathops/SkPathOpsSimplify.cpp \
+	third_party/skia/src/pathops/SkPathOpsTriangle.cpp \
+	third_party/skia/src/pathops/SkPathOpsTypes.cpp \
+	third_party/skia/src/pathops/SkPathWriter.cpp \
+	third_party/skia/src/pathops/SkQuarticRoot.cpp \
+	third_party/skia/src/pathops/SkReduceOrder.cpp \
+	third_party/skia/src/effects/Sk1DPathEffect.cpp \
+	third_party/skia/src/effects/Sk2DPathEffect.cpp \
+	third_party/skia/src/effects/SkAlphaThresholdFilter.cpp \
+	third_party/skia/src/effects/SkArithmeticMode.cpp \
+	third_party/skia/src/effects/SkAvoidXfermode.cpp \
+	third_party/skia/src/effects/SkBicubicImageFilter.cpp \
+	third_party/skia/src/effects/SkBitmapSource.cpp \
+	third_party/skia/src/effects/SkBlurDrawLooper.cpp \
+	third_party/skia/src/effects/SkBlurMask.cpp \
+	third_party/skia/src/effects/SkBlurImageFilter.cpp \
+	third_party/skia/src/effects/SkBlurMaskFilter.cpp \
+	third_party/skia/src/effects/SkColorFilters.cpp \
+	third_party/skia/src/effects/SkColorFilterImageFilter.cpp \
+	third_party/skia/src/effects/SkColorMatrix.cpp \
+	third_party/skia/src/effects/SkColorMatrixFilter.cpp \
+	third_party/skia/src/effects/SkComposeImageFilter.cpp \
+	third_party/skia/src/effects/SkCornerPathEffect.cpp \
+	third_party/skia/src/effects/SkDashPathEffect.cpp \
+	third_party/skia/src/effects/SkDiscretePathEffect.cpp \
+	third_party/skia/src/effects/SkDisplacementMapEffect.cpp \
+	third_party/skia/src/effects/SkDropShadowImageFilter.cpp \
+	third_party/skia/src/effects/SkEmbossMask.cpp \
+	third_party/skia/src/effects/SkEmbossMaskFilter.cpp \
+	third_party/skia/src/effects/SkGpuBlurUtils.cpp \
+	third_party/skia/src/effects/SkKernel33MaskFilter.cpp \
+	third_party/skia/src/effects/SkLayerDrawLooper.cpp \
+	third_party/skia/src/effects/SkLayerRasterizer.cpp \
+	third_party/skia/src/effects/SkLerpXfermode.cpp \
+	third_party/skia/src/effects/SkLightingImageFilter.cpp \
+	third_party/skia/src/effects/SkLumaColorFilter.cpp \
+	third_party/skia/src/effects/SkMagnifierImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixConvolutionImageFilter.cpp \
+	third_party/skia/src/effects/SkMergeImageFilter.cpp \
+	third_party/skia/src/effects/SkMorphologyImageFilter.cpp \
+	third_party/skia/src/effects/SkOffsetImageFilter.cpp \
+	third_party/skia/src/effects/SkPaintFlagsDrawFilter.cpp \
+	third_party/skia/src/effects/SkPerlinNoiseShader.cpp \
+	third_party/skia/src/effects/SkPictureImageFilter.cpp \
+	third_party/skia/src/effects/SkPixelXorXfermode.cpp \
+	third_party/skia/src/effects/SkPorterDuff.cpp \
+	third_party/skia/src/effects/SkRectShaderImageFilter.cpp \
+	third_party/skia/src/effects/SkResizeImageFilter.cpp \
+	third_party/skia/src/effects/SkStippleMaskFilter.cpp \
+	third_party/skia/src/effects/SkTableColorFilter.cpp \
+	third_party/skia/src/effects/SkTableMaskFilter.cpp \
+	third_party/skia/src/effects/SkTestImageFilters.cpp \
+	third_party/skia/src/effects/SkTileImageFilter.cpp \
+	third_party/skia/src/effects/SkMatrixImageFilter.cpp \
+	third_party/skia/src/effects/SkTransparentShader.cpp \
+	third_party/skia/src/effects/SkXfermodeImageFilter.cpp \
+	third_party/skia/src/effects/gradients/SkBitmapCache.cpp \
+	third_party/skia/src/effects/gradients/SkClampRange.cpp \
+	third_party/skia/src/effects/gradients/SkGradientShader.cpp \
+	third_party/skia/src/effects/gradients/SkLinearGradient.cpp \
+	third_party/skia/src/effects/gradients/SkRadialGradient.cpp \
+	third_party/skia/src/effects/gradients/SkTwoPointRadialGradient.cpp \
+	third_party/skia/src/effects/gradients/SkTwoPointConicalGradient.cpp \
+	third_party/skia/src/effects/gradients/SkSweepGradient.cpp \
+	third_party/skia/src/pdf/SkPDFCatalog.cpp \
+	third_party/skia/src/pdf/SkPDFDevice.cpp \
+	third_party/skia/src/pdf/SkPDFDeviceFlattener.cpp \
+	third_party/skia/src/pdf/SkPDFDocument.cpp \
+	third_party/skia/src/pdf/SkPDFFont.cpp \
+	third_party/skia/src/pdf/SkPDFFormXObject.cpp \
+	third_party/skia/src/pdf/SkPDFGraphicState.cpp \
+	third_party/skia/src/pdf/SkPDFImage.cpp \
+	third_party/skia/src/pdf/SkPDFPage.cpp \
+	third_party/skia/src/pdf/SkPDFResourceDict.cpp \
+	third_party/skia/src/pdf/SkPDFShader.cpp \
+	third_party/skia/src/pdf/SkPDFStream.cpp \
+	third_party/skia/src/pdf/SkPDFTypes.cpp \
+	third_party/skia/src/pdf/SkPDFUtils.cpp \
+	third_party/skia/src/gpu/gl/GrGLCreateNullInterface.cpp \
+	third_party/skia/src/gpu/gl/SkNullGLContext.cpp \
+	third_party/skia/src/gpu/GrAAHairLinePathRenderer.cpp \
+	third_party/skia/src/gpu/GrAAConvexPathRenderer.cpp \
+	third_party/skia/src/gpu/GrAARectRenderer.cpp \
+	third_party/skia/src/gpu/GrAddPathRenderers_default.cpp \
+	third_party/skia/src/gpu/GrAllocPool.cpp \
+	third_party/skia/src/gpu/GrAtlas.cpp \
+	third_party/skia/src/gpu/GrBitmapTextContext.cpp \
+	third_party/skia/src/gpu/GrBlend.cpp \
+	third_party/skia/src/gpu/GrBufferAllocPool.cpp \
+	third_party/skia/src/gpu/GrCacheID.cpp \
+	third_party/skia/src/gpu/GrClipData.cpp \
+	third_party/skia/src/gpu/GrContext.cpp \
+	third_party/skia/src/gpu/GrDefaultPathRenderer.cpp \
+	third_party/skia/src/gpu/GrDistanceFieldTextContext.cpp \
+	third_party/skia/src/gpu/GrDrawState.cpp \
+	third_party/skia/src/gpu/GrDrawTarget.cpp \
+	third_party/skia/src/gpu/GrEffect.cpp \
+	third_party/skia/src/gpu/GrClipMaskCache.cpp \
+	third_party/skia/src/gpu/GrClipMaskManager.cpp \
+	third_party/skia/src/gpu/GrGpu.cpp \
+	third_party/skia/src/gpu/GrGpuFactory.cpp \
+	third_party/skia/src/gpu/GrInOrderDrawBuffer.cpp \
+	third_party/skia/src/gpu/GrMemoryPool.cpp \
+	third_party/skia/src/gpu/GrOvalRenderer.cpp \
+	third_party/skia/src/gpu/GrPaint.cpp \
+	third_party/skia/src/gpu/GrPath.cpp \
+	third_party/skia/src/gpu/GrPathRendererChain.cpp \
+	third_party/skia/src/gpu/GrPathRenderer.cpp \
+	third_party/skia/src/gpu/GrPathUtils.cpp \
+	third_party/skia/src/gpu/GrRectanizer.cpp \
+	third_party/skia/src/gpu/GrRectanizer_skyline.cpp \
+	third_party/skia/src/gpu/GrRenderTarget.cpp \
+	third_party/skia/src/gpu/GrReducedClip.cpp \
+	third_party/skia/src/gpu/GrResource.cpp \
+	third_party/skia/src/gpu/GrResourceCache.cpp \
+	third_party/skia/src/gpu/GrStencil.cpp \
+	third_party/skia/src/gpu/GrStencilAndCoverPathRenderer.cpp \
+	third_party/skia/src/gpu/GrStencilBuffer.cpp \
+	third_party/skia/src/gpu/GrTraceMarker.cpp \
+	third_party/skia/src/gpu/GrSWMaskHelper.cpp \
+	third_party/skia/src/gpu/GrSoftwarePathRenderer.cpp \
+	third_party/skia/src/gpu/GrSurface.cpp \
+	third_party/skia/src/gpu/GrTextContext.cpp \
+	third_party/skia/src/gpu/GrTextStrike.cpp \
+	third_party/skia/src/gpu/GrTexture.cpp \
+	third_party/skia/src/gpu/GrTextureAccess.cpp \
+	third_party/skia/src/gpu/effects/GrConfigConversionEffect.cpp \
+	third_party/skia/src/gpu/effects/GrBezierEffect.cpp \
+	third_party/skia/src/gpu/effects/GrConvolutionEffect.cpp \
+	third_party/skia/src/gpu/effects/GrConvexPolyEffect.cpp \
+	third_party/skia/src/gpu/effects/GrBicubicEffect.cpp \
+	third_party/skia/src/gpu/effects/GrCustomCoordsTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrDistanceFieldTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrRRectEffect.cpp \
+	third_party/skia/src/gpu/effects/GrSimpleTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrSingleTextureEffect.cpp \
+	third_party/skia/src/gpu/effects/GrTextureDomain.cpp \
+	third_party/skia/src/gpu/effects/GrTextureStripAtlas.cpp \
+	third_party/skia/src/gpu/gl/GrGLBufferImpl.cpp \
+	third_party/skia/src/gpu/gl/GrGLCaps.cpp \
+	third_party/skia/src/gpu/gl/GrGLContext.cpp \
+	third_party/skia/src/gpu/gl/GrGLCreateNativeInterface_none.cpp \
+	third_party/skia/src/gpu/gl/GrGLDefaultInterface_none.cpp \
+	third_party/skia/src/gpu/gl/GrGLExtensions.cpp \
+	third_party/skia/src/gpu/gl/GrGLIndexBuffer.cpp \
+	third_party/skia/src/gpu/gl/GrGLInterface.cpp \
+	third_party/skia/src/gpu/gl/GrGLNoOpInterface.cpp \
+	third_party/skia/src/gpu/gl/GrGLPath.cpp \
+	third_party/skia/src/gpu/gl/GrGLProgram.cpp \
+	third_party/skia/src/gpu/gl/GrGLProgramDesc.cpp \
+	third_party/skia/src/gpu/gl/GrGLProgramEffects.cpp \
+	third_party/skia/src/gpu/gl/GrGLRenderTarget.cpp \
+	third_party/skia/src/gpu/gl/GrGLShaderBuilder.cpp \
+	third_party/skia/src/gpu/gl/GrGLSL.cpp \
+	third_party/skia/src/gpu/gl/GrGLStencilBuffer.cpp \
+	third_party/skia/src/gpu/gl/GrGLTexture.cpp \
+	third_party/skia/src/gpu/gl/GrGLUtil.cpp \
+	third_party/skia/src/gpu/gl/GrGLUniformManager.cpp \
+	third_party/skia/src/gpu/gl/GrGLVertexArray.cpp \
+	third_party/skia/src/gpu/gl/GrGLVertexBuffer.cpp \
+	third_party/skia/src/gpu/gl/GrGpuGL.cpp \
+	third_party/skia/src/gpu/gl/GrGpuGL_program.cpp \
+	third_party/skia/src/gpu/SkGpuDevice.cpp \
+	third_party/skia/src/gpu/SkGr.cpp \
+	third_party/skia/src/gpu/SkGrFontScaler.cpp \
+	third_party/skia/src/gpu/SkGrPixelRef.cpp \
+	third_party/skia/src/gpu/SkGrTexturePixelRef.cpp \
+	third_party/skia/src/image/SkImage_Gpu.cpp \
+	third_party/skia/src/image/SkSurface_Gpu.cpp \
+	third_party/skia/src/gpu/gl/SkGLContextHelper.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/images \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH)/third_party/skia/src/image \
+	$(LOCAL_PATH)/third_party/skia/src/ports \
+	$(LOCAL_PATH)/third_party/skia/src/sfnt \
+	$(LOCAL_PATH)/third_party/skia/src/utils \
+	$(LOCAL_PATH)/third_party/skia/src/lazy \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/gpu \
+	$(LOCAL_PATH)/third_party/expat/files/lib \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/freetype/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/images \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH)/third_party/skia/src/image \
+	$(LOCAL_PATH)/third_party/skia/src/ports \
+	$(LOCAL_PATH)/third_party/skia/src/sfnt \
+	$(LOCAL_PATH)/third_party/skia/src/utils \
+	$(LOCAL_PATH)/third_party/skia/src/lazy \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/gpu \
+	$(LOCAL_PATH)/third_party/expat/files/lib \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/freetype/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_library_gyp
+
+# Alias gyp target name.
+.PHONY: skia_library
+skia_library: skia_skia_library_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_library_opts.gyp b/skia/skia_library_opts.gyp
index f463c76..f719075 100644
--- a/skia/skia_library_opts.gyp
+++ b/skia/skia_library_opts.gyp
@@ -142,6 +142,18 @@
             '../third_party/skia/src/opts/SkBlurImage_opts_none.cpp',
           ],
         }],
+        [ 'target_arch == "arm64"',{
+          # TODO(rmcilroy): Update this once http://crrev.com/143423004/ lands.
+          'sources': [
+            '../third_party/skia/src/opts/SkBitmapProcState_opts_none.cpp',
+            '../third_party/skia/src/opts/SkBlitMask_opts_none.cpp',
+            '../third_party/skia/src/opts/SkBlitRow_opts_none.cpp',
+            '../third_party/skia/src/opts/SkUtils_opts_none.cpp',
+            '../third_party/skia/src/opts/SkXfermode_opts_none.cpp',
+            '../third_party/skia/src/opts/SkMorphology_opts_none.cpp',
+            '../third_party/skia/src/opts/SkBlurImage_opts_none.cpp',
+          ],
+        }],
       ],
     },
     # For the same lame reasons as what is done for skia_opts, we have to
diff --git a/skia/skia_opts.target.darwin-arm.mk b/skia/skia_opts.target.darwin-arm.mk
index f4dd864..9b962d6 100644
--- a/skia/skia_opts.target.darwin-arm.mk
+++ b/skia/skia_opts.target.darwin-arm.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -119,6 +117,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -241,6 +238,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts.target.darwin-mips.mk b/skia/skia_opts.target.darwin-mips.mk
index de2454d..2512ddd 100644
--- a/skia/skia_opts.target.darwin-mips.mk
+++ b/skia/skia_opts.target.darwin-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -116,6 +114,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts.target.darwin-x86.mk b/skia/skia_opts.target.darwin-x86.mk
index b8d4568..09094ac 100644
--- a/skia/skia_opts.target.darwin-x86.mk
+++ b/skia/skia_opts.target.darwin-x86.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -117,6 +115,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts.target.darwin-x86_64.mk b/skia/skia_opts.target.darwin-x86_64.mk
new file mode 100644
index 0000000..87bd859
--- /dev/null
+++ b/skia/skia_opts.target.darwin-x86_64.mk
@@ -0,0 +1,330 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_opts_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkBlitRect_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkBlitRow_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkUtils_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkXfermode_opts_none.cpp \
+	third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkMorphology_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkBlurImage_opts_SSE2.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_opts_gyp
+
+# Alias gyp target name.
+.PHONY: skia_opts
+skia_opts: skia_skia_opts_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_opts.target.linux-arm.mk b/skia/skia_opts.target.linux-arm.mk
index f4dd864..9b962d6 100644
--- a/skia/skia_opts.target.linux-arm.mk
+++ b/skia/skia_opts.target.linux-arm.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -119,6 +117,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -241,6 +238,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts.target.linux-mips.mk b/skia/skia_opts.target.linux-mips.mk
index de2454d..2512ddd 100644
--- a/skia/skia_opts.target.linux-mips.mk
+++ b/skia/skia_opts.target.linux-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -116,6 +114,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts.target.linux-x86.mk b/skia/skia_opts.target.linux-x86.mk
index b8d4568..09094ac 100644
--- a/skia/skia_opts.target.linux-x86.mk
+++ b/skia/skia_opts.target.linux-x86.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -117,6 +115,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts.target.linux-x86_64.mk b/skia/skia_opts.target.linux-x86_64.mk
new file mode 100644
index 0000000..87bd859
--- /dev/null
+++ b/skia/skia_opts.target.linux-x86_64.mk
@@ -0,0 +1,330 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_opts_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/skia/src/opts/SkBitmapProcState_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkBlitRect_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkBlitRow_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkUtils_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkXfermode_opts_none.cpp \
+	third_party/skia/src/opts/SkBitmapFilter_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkMorphology_opts_SSE2.cpp \
+	third_party/skia/src/opts/SkBlurImage_opts_SSE2.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/src/opts \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_opts_gyp
+
+# Alias gyp target name.
+.PHONY: skia_opts
+skia_opts: skia_skia_opts_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_opts_neon.target.darwin-arm.mk b/skia/skia_opts_neon.target.darwin-arm.mk
index dceddb5..028caba 100644
--- a/skia/skia_opts_neon.target.darwin-arm.mk
+++ b/skia/skia_opts_neon.target.darwin-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -120,6 +118,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -242,6 +239,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts_neon.target.linux-arm.mk b/skia/skia_opts_neon.target.linux-arm.mk
index dceddb5..028caba 100644
--- a/skia/skia_opts_neon.target.linux-arm.mk
+++ b/skia/skia_opts_neon.target.linux-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -120,6 +118,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -242,6 +239,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts_ssse3.target.darwin-x86.mk b/skia/skia_opts_ssse3.target.darwin-x86.mk
index 6f02abd..7c08f62 100644
--- a/skia/skia_opts_ssse3.target.darwin-x86.mk
+++ b/skia/skia_opts_ssse3.target.darwin-x86.mk
@@ -89,9 +89,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +109,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -208,9 +207,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts_ssse3.target.darwin-x86_64.mk b/skia/skia_opts_ssse3.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d1c49a1
--- /dev/null
+++ b/skia/skia_opts_ssse3.target.darwin-x86_64.mk
@@ -0,0 +1,323 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_opts_ssse3_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mssse3 \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mssse3 \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_opts_ssse3_gyp
+
+# Alias gyp target name.
+.PHONY: skia_opts_ssse3
+skia_opts_ssse3: skia_skia_opts_ssse3_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_opts_ssse3.target.linux-x86.mk b/skia/skia_opts_ssse3.target.linux-x86.mk
index 6f02abd..7c08f62 100644
--- a/skia/skia_opts_ssse3.target.linux-x86.mk
+++ b/skia/skia_opts_ssse3.target.linux-x86.mk
@@ -89,9 +89,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +109,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -208,9 +207,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +227,7 @@
 	'-DSK_GAMMA_CONTRAST=0.0' \
 	'-DSK_USE_POSIX_THREADS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/skia/skia_opts_ssse3.target.linux-x86_64.mk b/skia/skia_opts_ssse3.target.linux-x86_64.mk
new file mode 100644
index 0000000..d1c49a1
--- /dev/null
+++ b/skia/skia_opts_ssse3.target.linux-x86_64.mk
@@ -0,0 +1,323 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := skia_skia_opts_ssse3_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/skia/src/opts/SkBitmapProcState_opts_SSSE3.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mssse3 \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-mssse3 \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=0' \
+	'-DSK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION' \
+	'-DSK_DISABLE_PIXELREF_LOCKCOUNT_BALANCE_CHECK' \
+	'-DIGNORE_ROT_AA_RECT_OPT' \
+	'-DSK_IGNORE_BLURRED_RRECT_OPT' \
+	'-DSK_IGNORE_QUAD_RR_CORNERS_OPT' \
+	'-DSK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS' \
+	'-DSK_DEFAULT_FONT_CACHE_LIMIT=(1*1024*1024)' \
+	'-DSK_USE_DISCARDABLE_SCALEDIMAGECACHE' \
+	'-DSK_FONTHOST_DOES_NOT_USE_FONTMGR' \
+	'-DSK_GAMMA_APPLY_TO_A8' \
+	'-DSK_GAMMA_EXPONENT=1.4' \
+	'-DSK_GAMMA_CONTRAST=0.0' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: skia_skia_opts_ssse3_gyp
+
+# Alias gyp target name.
+.PHONY: skia_opts_ssse3
+skia_opts_ssse3: skia_skia_opts_ssse3_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/skia/skia_test_expectations.txt b/skia/skia_test_expectations.txt
index c5cd81e..edb6b9d 100644
--- a/skia/skia_test_expectations.txt
+++ b/skia/skia_test_expectations.txt
@@ -51,8 +51,8 @@
 # The Skia roll to r13482 altered the following layout tests:
 crbug.com/344497 [ Win ] virtual/deferred/fast/images/webp-color-profile-lossy.html [ ImageOnlyFailure ]
 
-# Skia 13798 change to spot lights
-crbug.com/352628 css3/filters/effect-combined-hw.html [ ImageOnlyFailure ]
-crbug.com/352628 css3/filters/effect-reference-ordering-hw.html [ ImageOnlyFailure ]
+# Roll to 13948 caused negligible changes to transformations to be rebaselined (fmalita):
+crbug.com/356644 fast/canvas/image-pattern-rotate.html [ ImageOnlyFailure ]
+crbug.com/356644 virtual/gpu/fast/canvas/image-object-in-canvas.html [ ImageOnlyFailure ]
 
 # END OVERRIDES HERE (this line ensures that the file is newline-terminated)
diff --git a/sql/sql.target.darwin-arm.mk b/sql/sql.target.darwin-arm.mk
index f1e7cdb..453ad68 100644
--- a/sql/sql.target.darwin-arm.mk
+++ b/sql/sql.target.darwin-arm.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sql/sql.target.darwin-mips.mk b/sql/sql.target.darwin-mips.mk
index 6ac09e2..6af45e7 100644
--- a/sql/sql.target.darwin-mips.mk
+++ b/sql/sql.target.darwin-mips.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sql/sql.target.darwin-x86.mk b/sql/sql.target.darwin-x86.mk
index 711f77a..cdea0a2 100644
--- a/sql/sql.target.darwin-x86.mk
+++ b/sql/sql.target.darwin-x86.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sql/sql.target.darwin-x86_64.mk b/sql/sql.target.darwin-x86_64.mk
new file mode 100644
index 0000000..1e48e3b
--- /dev/null
+++ b/sql/sql.target.darwin-x86_64.mk
@@ -0,0 +1,272 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sql_sql_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sql/connection.cc \
+	sql/error_delegate_util.cc \
+	sql/meta_table.cc \
+	sql/recovery.cc \
+	sql/statement.cc \
+	sql/transaction.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSQL_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSQL_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sql_sql_gyp
+
+# Alias gyp target name.
+.PHONY: sql
+sql: sql_sql_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sql/sql.target.linux-arm.mk b/sql/sql.target.linux-arm.mk
index f1e7cdb..453ad68 100644
--- a/sql/sql.target.linux-arm.mk
+++ b/sql/sql.target.linux-arm.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sql/sql.target.linux-mips.mk b/sql/sql.target.linux-mips.mk
index 6ac09e2..6af45e7 100644
--- a/sql/sql.target.linux-mips.mk
+++ b/sql/sql.target.linux-mips.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sql/sql.target.linux-x86.mk b/sql/sql.target.linux-x86.mk
index 711f77a..cdea0a2 100644
--- a/sql/sql.target.linux-x86.mk
+++ b/sql/sql.target.linux-x86.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSQL_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/sql/sql.target.linux-x86_64.mk b/sql/sql.target.linux-x86_64.mk
new file mode 100644
index 0000000..1e48e3b
--- /dev/null
+++ b/sql/sql.target.linux-x86_64.mk
@@ -0,0 +1,272 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := sql_sql_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	sql/connection.cc \
+	sql/error_delegate_util.cc \
+	sql/meta_table.cc \
+	sql/recovery.cc \
+	sql/statement.cc \
+	sql/transaction.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSQL_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSQL_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: sql_sql_gyp
+
+# Alias gyp target name.
+.PHONY: sql
+sql: sql_sql_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/sync/engine/DEPS b/sync/engine/DEPS
index b43d31c..0978697 100644
--- a/sync/engine/DEPS
+++ b/sync/engine/DEPS
@@ -2,6 +2,7 @@
   "+sync/base",
   "+sync/internal_api/public/base",
   "+sync/internal_api/public/engine",
+  "+sync/internal_api/public/events",
   "+sync/internal_api/public/sessions",
   "+sync/internal_api/public/test",
   "+sync/internal_api/public/util",
diff --git a/sync/engine/all_status.cc b/sync/engine/all_status.cc
index 6fa98d3..d73f206 100644
--- a/sync/engine/all_status.cc
+++ b/sync/engine/all_status.cc
@@ -124,6 +124,8 @@
 
 void AllStatus::OnMigrationRequested(ModelTypeSet) {}
 
+void AllStatus::OnProtocolEvent(const ProtocolEvent&) {}
+
 SyncStatus AllStatus::status() const {
   base::AutoLock lock(mutex_);
   return status_;
diff --git a/sync/engine/all_status.h b/sync/engine/all_status.h
index add42e5..999f2f3 100644
--- a/sync/engine/all_status.h
+++ b/sync/engine/all_status.h
@@ -46,6 +46,7 @@
   virtual void OnRetryTimeChanged(base::Time retry_time) OVERRIDE;
   virtual void OnThrottledTypesChanged(ModelTypeSet throttled_types) OVERRIDE;
   virtual void OnMigrationRequested(ModelTypeSet types) OVERRIDE;
+  virtual void OnProtocolEvent(const ProtocolEvent& event) OVERRIDE;
 
   SyncStatus status() const;
 
diff --git a/sync/engine/commit.cc b/sync/engine/commit.cc
index 90b9742..92cf4d2 100644
--- a/sync/engine/commit.cc
+++ b/sync/engine/commit.cc
@@ -10,6 +10,8 @@
 #include "sync/engine/commit_util.h"
 #include "sync/engine/syncer.h"
 #include "sync/engine/syncer_proto_util.h"
+#include "sync/internal_api/public/events/commit_request_event.h"
+#include "sync/internal_api/public/events/commit_response_event.h"
 #include "sync/sessions/sync_session.h"
 
 namespace syncer {
@@ -97,11 +99,26 @@
   }
 
   DVLOG(1) << "Sending commit message.";
+
+  CommitRequestEvent request_event(
+      base::Time::Now(),
+      message_.commit().entries_size(),
+      request_types,
+      message_);
+  session->SendProtocolEvent(request_event);
+
   TRACE_EVENT_BEGIN0("sync", "PostCommit");
   const SyncerError post_result = SyncerProtoUtil::PostClientToServerMessage(
       &message_, &response_, session);
   TRACE_EVENT_END0("sync", "PostCommit");
 
+  // TODO(rlarocque): Use result that includes errors captured later?
+  CommitResponseEvent response_event(
+      base::Time::Now(),
+      post_result,
+      response_);
+  session->SendProtocolEvent(response_event);
+
   if (post_result != SYNCER_OK) {
     LOG(WARNING) << "Post commit failed";
     return post_result;
diff --git a/sync/engine/get_updates_delegate.cc b/sync/engine/get_updates_delegate.cc
index 4697485..ac66eef 100644
--- a/sync/engine/get_updates_delegate.cc
+++ b/sync/engine/get_updates_delegate.cc
@@ -6,26 +6,33 @@
 
 #include "sync/engine/directory_update_handler.h"
 #include "sync/engine/get_updates_processor.h"
+#include "sync/internal_api/public/events/configure_get_updates_request_event.h"
+#include "sync/internal_api/public/events/normal_get_updates_request_event.h"
+#include "sync/internal_api/public/events/poll_get_updates_request_event.h"
 
 namespace syncer {
 
 namespace {
 
 void NonPassiveApplyUpdates(
+    ModelTypeSet gu_types,
     sessions::StatusController* status_controller,
     UpdateHandlerMap* update_handler_map) {
   for (UpdateHandlerMap::iterator it = update_handler_map->begin();
        it != update_handler_map->end(); ++it) {
-    it->second->ApplyUpdates(status_controller);
+    if (gu_types.Has(it->first))
+      it->second->ApplyUpdates(status_controller);
   }
 }
 
 void PassiveApplyUpdates(
+    ModelTypeSet gu_types,
     sessions::StatusController* status_controller,
     UpdateHandlerMap* update_handler_map) {
   for (UpdateHandlerMap::iterator it = update_handler_map->begin();
        it != update_handler_map->end(); ++it) {
-    it->second->PassiveApplyUpdates(status_controller);
+    if (gu_types.Has(it->first))
+      it->second->PassiveApplyUpdates(status_controller);
   }
 }
 
@@ -75,9 +82,17 @@
 }
 
 void NormalGetUpdatesDelegate::ApplyUpdates(
+    ModelTypeSet gu_types,
     sessions::StatusController* status_controller,
     UpdateHandlerMap* update_handler_map) const {
-  NonPassiveApplyUpdates(status_controller, update_handler_map);
+  NonPassiveApplyUpdates(gu_types, status_controller, update_handler_map);
+}
+
+scoped_ptr<ProtocolEvent> NormalGetUpdatesDelegate::GetNetworkRequestEvent(
+    base::Time timestamp,
+    const sync_pb::ClientToServerMessage& request) const {
+  return scoped_ptr<ProtocolEvent>(
+      new NormalGetUpdatesRequestEvent(timestamp, nudge_tracker_, request));
 }
 
 ConfigureGetUpdatesDelegate::ConfigureGetUpdatesDelegate(
@@ -92,9 +107,20 @@
 }
 
 void ConfigureGetUpdatesDelegate::ApplyUpdates(
+    ModelTypeSet gu_types,
     sessions::StatusController* status_controller,
     UpdateHandlerMap* update_handler_map) const {
-  PassiveApplyUpdates(status_controller, update_handler_map);
+  PassiveApplyUpdates(gu_types, status_controller, update_handler_map);
+}
+
+scoped_ptr<ProtocolEvent> ConfigureGetUpdatesDelegate::GetNetworkRequestEvent(
+    base::Time timestamp,
+    const sync_pb::ClientToServerMessage& request) const {
+  return scoped_ptr<ProtocolEvent>(
+      new ConfigureGetUpdatesRequestEvent(
+          timestamp,
+          ConvertConfigureSourceToOrigin(source_),
+          request));
 }
 
 sync_pb::SyncEnums::GetUpdatesOrigin
@@ -131,9 +157,17 @@
 }
 
 void PollGetUpdatesDelegate::ApplyUpdates(
+    ModelTypeSet gu_types,
     sessions::StatusController* status_controller,
     UpdateHandlerMap* update_handler_map) const {
-  NonPassiveApplyUpdates(status_controller, update_handler_map);
+  NonPassiveApplyUpdates(gu_types, status_controller, update_handler_map);
+}
+
+scoped_ptr<ProtocolEvent> PollGetUpdatesDelegate::GetNetworkRequestEvent(
+    base::Time timestamp,
+    const sync_pb::ClientToServerMessage& request) const {
+  return scoped_ptr<ProtocolEvent>(
+      new PollGetUpdatesRequestEvent(timestamp, request));
 }
 
 }  // namespace syncer
diff --git a/sync/engine/get_updates_delegate.h b/sync/engine/get_updates_delegate.h
index 9ebc6d8..d61f39a 100644
--- a/sync/engine/get_updates_delegate.h
+++ b/sync/engine/get_updates_delegate.h
@@ -5,6 +5,7 @@
 #ifndef SYNC_ENGINE_GET_UPDATES_DELEGATE_H_
 #define SYNC_ENGINE_GET_UPDATES_DELEGATE_H_
 
+#include "sync/internal_api/public/events/protocol_event.h"
 #include "sync/protocol/sync.pb.h"
 #include "sync/sessions/model_type_registry.h"
 #include "sync/sessions/nudge_tracker.h"
@@ -29,8 +30,13 @@
 
   // Applies pending updates to non-control types.
   virtual void ApplyUpdates(
-      sessions::StatusController* session,
+      ModelTypeSet gu_types,
+      sessions::StatusController* status,
       UpdateHandlerMap* update_handler_map) const = 0;
+
+  virtual scoped_ptr<ProtocolEvent> GetNetworkRequestEvent(
+      base::Time timestamp,
+      const sync_pb::ClientToServerMessage& request) const = 0;
 };
 
 // Functionality specific to the normal GetUpdate request.
@@ -45,9 +51,13 @@
 
   // Applies pending updates on the appropriate data type threads.
   virtual void ApplyUpdates(
+      ModelTypeSet gu_types,
       sessions::StatusController* status,
       UpdateHandlerMap* update_handler_map) const OVERRIDE;
 
+  virtual scoped_ptr<ProtocolEvent> GetNetworkRequestEvent(
+      base::Time timestamp,
+      const sync_pb::ClientToServerMessage& request) const OVERRIDE;
  private:
   DISALLOW_COPY_AND_ASSIGN(NormalGetUpdatesDelegate);
 
@@ -71,9 +81,13 @@
   // This is safe only if the ChangeProcessor is not listening to changes at
   // this time.
   virtual void ApplyUpdates(
+      ModelTypeSet gu_types,
       sessions::StatusController* status,
       UpdateHandlerMap* update_handler_map) const OVERRIDE;
 
+  virtual scoped_ptr<ProtocolEvent> GetNetworkRequestEvent(
+      base::Time timestamp,
+      const sync_pb::ClientToServerMessage& request) const OVERRIDE;
  private:
   DISALLOW_COPY_AND_ASSIGN(ConfigureGetUpdatesDelegate);
 
@@ -95,9 +109,13 @@
 
   // Applies updates on the appropriate data type thread.
   virtual void ApplyUpdates(
+      ModelTypeSet gu_types,
       sessions::StatusController* status,
       UpdateHandlerMap* update_handler_map) const OVERRIDE;
 
+  virtual scoped_ptr<ProtocolEvent> GetNetworkRequestEvent(
+      base::Time timestamp,
+      const sync_pb::ClientToServerMessage& request) const OVERRIDE;
  private:
   DISALLOW_COPY_AND_ASSIGN(PollGetUpdatesDelegate);
 };
diff --git a/sync/engine/get_updates_processor.cc b/sync/engine/get_updates_processor.cc
index 399c78c..eb1d7be 100644
--- a/sync/engine/get_updates_processor.cc
+++ b/sync/engine/get_updates_processor.cc
@@ -10,6 +10,7 @@
 #include "sync/engine/get_updates_delegate.h"
 #include "sync/engine/syncer_proto_util.h"
 #include "sync/engine/update_handler.h"
+#include "sync/internal_api/public/events/get_updates_response_event.h"
 #include "sync/protocol/sync.pb.h"
 #include "sync/sessions/status_controller.h"
 #include "sync/sessions/sync_session.h"
@@ -171,7 +172,8 @@
 
   for (ModelTypeSet::Iterator it = gu_types.First(); it.Good(); it.Inc()) {
     UpdateHandlerMap::iterator handler_it = update_handler_map_->find(it.Get());
-    DCHECK(handler_it != update_handler_map_->end());
+    DCHECK(handler_it != update_handler_map_->end())
+        << "Failed to look up handler for " << ModelTypeToString(it.Get());
     sync_pb::DataTypeProgressMarker* progress_marker =
         get_updates->add_from_progress_marker();
     handler_it->second->GetDownloadProgress(progress_marker);
@@ -193,6 +195,9 @@
     CopyClientDebugInfo(session->context()->debug_info_getter(), debug_info);
   }
 
+  session->SendProtocolEvent(
+      *(delegate_.GetNetworkRequestEvent(base::Time::Now(), *msg)));
+
   SyncerError result = SyncerProtoUtil::PostClientToServerMessage(
       msg,
       &update_response,
@@ -202,6 +207,10 @@
       update_response);
 
   if (result != SYNCER_OK) {
+    GetUpdatesResponseEvent response_event(
+        base::Time::Now(), update_response, result);
+    session->SendProtocolEvent(response_event);
+
     LOG(ERROR) << "PostClientToServerMessage() failed during GetUpdates";
     return result;
   }
@@ -225,9 +234,15 @@
         HandleGetEncryptionKeyResponse(update_response, dir));
   }
 
-  return ProcessResponse(update_response.get_updates(),
-                         request_types,
-                         status);
+  SyncerError process_result = ProcessResponse(update_response.get_updates(),
+                                              request_types,
+                                              status);
+
+  GetUpdatesResponseEvent response_event(
+      base::Time::Now(), update_response, process_result);
+  session->SendProtocolEvent(response_event);
+
+  return process_result;
 }
 
 SyncerError GetUpdatesProcessor::ProcessResponse(
@@ -303,8 +318,9 @@
 }
 
 void GetUpdatesProcessor::ApplyUpdates(
+    ModelTypeSet gu_types,
     sessions::StatusController* status_controller) {
-  delegate_.ApplyUpdates(status_controller, update_handler_map_);
+  delegate_.ApplyUpdates(gu_types, status_controller, update_handler_map_);
 }
 
 void GetUpdatesProcessor::CopyClientDebugInfo(
diff --git a/sync/engine/get_updates_processor.h b/sync/engine/get_updates_processor.h
index 787f267..40a5c3a 100644
--- a/sync/engine/get_updates_processor.h
+++ b/sync/engine/get_updates_processor.h
@@ -59,7 +59,9 @@
       bool create_mobile_bookmarks_folder);
 
   // Applies any downloaded and processed updates.
-  void ApplyUpdates(sessions::StatusController* status_controller);
+  void ApplyUpdates(
+      ModelTypeSet gu_types,
+      sessions::StatusController* status_controller);
 
  private:
   // Populates a GetUpdates request message with per-type information.
diff --git a/sync/engine/get_updates_processor_unittest.cc b/sync/engine/get_updates_processor_unittest.cc
index c494289..b8ea889 100644
--- a/sync/engine/get_updates_processor_unittest.cc
+++ b/sync/engine/get_updates_processor_unittest.cc
@@ -35,8 +35,8 @@
     AddUpdateHandler(PREFERENCES);
   }
 
-  ModelTypeSet request_types() {
-    return request_types_;
+  ModelTypeSet enabled_types() {
+    return enabled_types_;
   }
 
   scoped_ptr<GetUpdatesProcessor> BuildGetUpdatesProcessor(
@@ -46,7 +46,7 @@
   }
 
   void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse* response) {
-    ModelTypeSet types = request_types();
+    ModelTypeSet types = enabled_types();
 
     for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) {
       sync_pb::DataTypeProgressMarker* marker =
@@ -58,17 +58,27 @@
     response->set_changes_remaining(0);
   }
 
-  const base::TimeTicks kTestStartTime;
-
- private:
-  void AddUpdateHandler(ModelType type) {
-    request_types_.Put(type);
-
-    UpdateHandler* handler = new MockUpdateHandler(type);
-    update_handler_map_.insert(std::make_pair(type, handler));
+  const UpdateHandler* GetHandler(ModelType type) {
+    UpdateHandlerMap::iterator it = update_handler_map_.find(type);
+    if (it == update_handler_map_.end())
+      return NULL;
+    return it->second;
   }
 
-  ModelTypeSet request_types_;
+  const base::TimeTicks kTestStartTime;
+
+ protected:
+  MockUpdateHandler* AddUpdateHandler(ModelType type) {
+    enabled_types_.Put(type);
+
+    MockUpdateHandler* handler = new MockUpdateHandler(type);
+    update_handler_map_.insert(std::make_pair(type, handler));
+
+    return handler;
+  }
+
+ private:
+  ModelTypeSet enabled_types_;
   UpdateHandlerMap update_handler_map_;
   STLValueDeleter<UpdateHandlerMap> update_handler_deleter_;
   scoped_ptr<GetUpdatesProcessor> get_updates_processor_;
@@ -85,7 +95,7 @@
   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(normal_delegate));
-  processor->PrepareGetUpdates(request_types(), &message);
+  processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::LOCAL,
@@ -133,7 +143,7 @@
   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(normal_delegate));
-  processor->PrepareGetUpdates(request_types(), &message);
+  processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::GetUpdatesCallerInfo::NOTIFICATION,
@@ -167,7 +177,7 @@
       sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(configure_delegate));
-  processor->PrepareGetUpdates(request_types(), &message);
+  processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::SyncEnums::RECONFIGURATION, gu_msg.get_updates_origin());
@@ -180,7 +190,7 @@
         gu_msg.from_progress_marker(i).data_type_id());
     progress_types.Put(type);
   }
-  EXPECT_TRUE(request_types().Equals(progress_types));
+  EXPECT_TRUE(enabled_types().Equals(progress_types));
 }
 
 TEST_F(GetUpdatesProcessorTest, PollTest) {
@@ -188,7 +198,7 @@
   PollGetUpdatesDelegate poll_delegate;
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(poll_delegate));
-  processor->PrepareGetUpdates(request_types(), &message);
+  processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::SyncEnums::PERIODIC, gu_msg.get_updates_origin());
@@ -201,7 +211,7 @@
         gu_msg.from_progress_marker(i).data_type_id());
     progress_types.Put(type);
   }
-  EXPECT_TRUE(request_types().Equals(progress_types));
+  EXPECT_TRUE(enabled_types().Equals(progress_types));
 }
 
 TEST_F(GetUpdatesProcessorTest, RetryTest) {
@@ -218,7 +228,7 @@
   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(normal_delegate));
-  processor->PrepareGetUpdates(request_types(), &message);
+  processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_EQ(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
@@ -232,7 +242,7 @@
         gu_msg.from_progress_marker(i).data_type_id());
     progress_types.Put(type);
   }
-  EXPECT_TRUE(request_types().Equals(progress_types));
+  EXPECT_TRUE(enabled_types().Equals(progress_types));
 }
 
 TEST_F(GetUpdatesProcessorTest, NudgeWithRetryTest) {
@@ -252,7 +262,7 @@
   NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(normal_delegate));
-  processor->PrepareGetUpdates(request_types(), &message);
+  processor->PrepareGetUpdates(enabled_types(), &message);
 
   const sync_pb::GetUpdatesMessage& gu_msg = message.get_updates();
   EXPECT_NE(sync_pb::SyncEnums::RETRY, gu_msg.get_updates_origin());
@@ -277,7 +287,7 @@
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(normal_delegate));
   SyncerError error = processor->ProcessResponse(gu_response,
-                                                 request_types(),
+                                                 enabled_types(),
                                                  &status);
   EXPECT_EQ(error, SERVER_RESPONSE_VALIDATION_FAILED);
 }
@@ -294,7 +304,7 @@
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(normal_delegate));
   SyncerError error = processor->ProcessResponse(gu_response,
-                                                 request_types(),
+                                                 enabled_types(),
                                                  &status);
   EXPECT_EQ(error, SERVER_MORE_TO_DOWNLOAD);
 }
@@ -311,11 +321,104 @@
   scoped_ptr<GetUpdatesProcessor> processor(
       BuildGetUpdatesProcessor(normal_delegate));
   SyncerError error = processor->ProcessResponse(gu_response,
-                                                 request_types(),
+                                                 enabled_types(),
                                                  &status);
   EXPECT_EQ(error, SYNCER_OK);
 }
 
+// Variant of GetUpdatesProcessor test designed to test update application.
+//
+// Maintains two enabled types, but requests that updates be applied for only
+// one of them.
+class GetUpdatesProcessorApplyUpdatesTest : public GetUpdatesProcessorTest {
+ public:
+  GetUpdatesProcessorApplyUpdatesTest() {}
+  virtual ~GetUpdatesProcessorApplyUpdatesTest() {}
+
+  virtual void SetUp() OVERRIDE {
+    bookmarks_handler_ = AddUpdateHandler(BOOKMARKS);
+    autofill_handler_ = AddUpdateHandler(AUTOFILL);
+  }
+
+  ModelTypeSet GetGuTypes() {
+    return ModelTypeSet(AUTOFILL);
+  }
+
+  MockUpdateHandler* GetNonAppliedHandler() {
+    return bookmarks_handler_;
+  }
+
+  MockUpdateHandler* GetAppliedHandler() {
+    return autofill_handler_;
+  }
+
+ private:
+  MockUpdateHandler* bookmarks_handler_;
+  MockUpdateHandler* autofill_handler_;
+};
+
+// Verify that a normal cycle applies updates non-passively to the specified
+// types.
+TEST_F(GetUpdatesProcessorApplyUpdatesTest, Normal) {
+  sessions::NudgeTracker nudge_tracker;
+  NormalGetUpdatesDelegate normal_delegate(nudge_tracker);
+  scoped_ptr<GetUpdatesProcessor> processor(
+      BuildGetUpdatesProcessor(normal_delegate));
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
+  EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
+
+  sessions::StatusController status;
+  processor->ApplyUpdates(GetGuTypes(), &status);
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
+  EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
+  EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
+}
+
+// Verify that a configure cycle applies updates passively to the specified
+// types.
+TEST_F(GetUpdatesProcessorApplyUpdatesTest, Configure) {
+  ConfigureGetUpdatesDelegate configure_delegate(
+      sync_pb::GetUpdatesCallerInfo::RECONFIGURATION);
+  scoped_ptr<GetUpdatesProcessor> processor(
+      BuildGetUpdatesProcessor(configure_delegate));
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
+  EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
+
+  sessions::StatusController status;
+  processor->ApplyUpdates(GetGuTypes(), &status);
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
+  EXPECT_EQ(1, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
+  EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
+}
+
+// Verify that a poll cycle applies updates non-passively to the specified
+// types.
+TEST_F(GetUpdatesProcessorApplyUpdatesTest, Poll) {
+  PollGetUpdatesDelegate poll_delegate;
+  scoped_ptr<GetUpdatesProcessor> processor(
+      BuildGetUpdatesProcessor(poll_delegate));
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
+  EXPECT_EQ(0, GetAppliedHandler()->GetApplyUpdatesCount());
+
+  sessions::StatusController status;
+  processor->ApplyUpdates(GetGuTypes(), &status);
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetApplyUpdatesCount());
+  EXPECT_EQ(1, GetAppliedHandler()->GetApplyUpdatesCount());
+
+  EXPECT_EQ(0, GetNonAppliedHandler()->GetPassiveApplyUpdatesCount());
+  EXPECT_EQ(0, GetAppliedHandler()->GetPassiveApplyUpdatesCount());
+}
+
 class DownloadUpdatesDebugInfoTest : public ::testing::Test {
  public:
   DownloadUpdatesDebugInfoTest() {}
@@ -338,7 +441,6 @@
   MockDebugInfoGetter debug_info_getter_;
 };
 
-
 // Verify CopyClientDebugInfo when there are no events to upload.
 TEST_F(DownloadUpdatesDebugInfoTest, VerifyCopyClientDebugInfo_Empty) {
   sync_pb::DebugInfo debug_info;
diff --git a/sync/engine/non_blocking_type_processor_core.cc b/sync/engine/non_blocking_type_processor_core.cc
index 6d6abc4..fdb9e10 100644
--- a/sync/engine/non_blocking_type_processor_core.cc
+++ b/sync/engine/non_blocking_type_processor_core.cc
@@ -10,7 +10,13 @@
 namespace syncer {
 
 NonBlockingTypeProcessorCore::NonBlockingTypeProcessorCore(
-    ModelType type) : type_(type), weak_ptr_factory_(this) {
+      ModelType type,
+      scoped_refptr<base::SequencedTaskRunner> processor_task_runner,
+      base::WeakPtr<NonBlockingTypeProcessor> processor)
+    : type_(type),
+      processor_task_runner_(processor_task_runner),
+      processor_(processor),
+      weak_ptr_factory_(this) {
   progress_marker_.set_data_type_id(GetSpecificsFieldNumberFromModelType(type));
 }
 
diff --git a/sync/engine/non_blocking_type_processor_core.h b/sync/engine/non_blocking_type_processor_core.h
index 028bb3a..412d2dd 100644
--- a/sync/engine/non_blocking_type_processor_core.h
+++ b/sync/engine/non_blocking_type_processor_core.h
@@ -13,8 +13,14 @@
 #include "sync/internal_api/public/base/model_type.h"
 #include "sync/protocol/sync.pb.h"
 
+namespace base {
+class SingleThreadTaskRunner;
+}
+
 namespace syncer {
 
+class NonBlockingTypeProcessor;
+
 // A smart cache for sync types that use message passing (rather than
 // transactions and the syncable::Directory) to communicate with the sync
 // thread.
@@ -35,12 +41,15 @@
 // example, if the sync server sends down an update for a sync entity that is
 // currently pending for commit, this object will detect this condition and
 // cancel the pending commit.
-class SYNC_EXPORT_PRIVATE NonBlockingTypeProcessorCore
+class SYNC_EXPORT NonBlockingTypeProcessorCore
     : public UpdateHandler,
       public CommitContributor,
       public base::NonThreadSafe {
  public:
-  explicit NonBlockingTypeProcessorCore(ModelType type);
+  NonBlockingTypeProcessorCore(
+      ModelType type,
+      scoped_refptr<base::SequencedTaskRunner> processor_task_runner,
+      base::WeakPtr<NonBlockingTypeProcessor> processor);
   virtual ~NonBlockingTypeProcessorCore();
 
   ModelType GetModelType() const;
@@ -65,6 +74,9 @@
   ModelType type_;
   sync_pb::DataTypeProgressMarker progress_marker_;
 
+  scoped_refptr<base::SequencedTaskRunner> processor_task_runner_;
+  base::WeakPtr<NonBlockingTypeProcessor> processor_;
+
   base::WeakPtrFactory<NonBlockingTypeProcessorCore> weak_ptr_factory_;
 };
 
diff --git a/sync/engine/sync_engine_event_listener.h b/sync/engine/sync_engine_event_listener.h
index 35fc05e..d5678a9 100644
--- a/sync/engine/sync_engine_event_listener.h
+++ b/sync/engine/sync_engine_event_listener.h
@@ -13,6 +13,7 @@
 
 struct SyncProtocolError;
 struct SyncCycleEvent;
+class ProtocolEvent;
 
 class SYNC_EXPORT_PRIVATE SyncEngineEventListener {
  public:
@@ -36,6 +37,9 @@
   // This event is sent when the server requests a migration.
   virtual void OnMigrationRequested(ModelTypeSet migration_types) = 0;
 
+  // Emits events when sync communicates with the server.
+  virtual void OnProtocolEvent(const ProtocolEvent& event) = 0;
+
  protected:
   virtual ~SyncEngineEventListener();
 };
diff --git a/sync/engine/sync_scheduler_impl.cc b/sync/engine/sync_scheduler_impl.cc
index a9c6359..b2774e7 100644
--- a/sync/engine/sync_scheduler_impl.cc
+++ b/sync/engine/sync_scheduler_impl.cc
@@ -504,7 +504,7 @@
             << ModelTypeSetToString(session_context_->GetEnabledTypes());
   scoped_ptr<SyncSession> session(SyncSession::Build(session_context_, this));
   bool premature_exit = !syncer_->ConfigureSyncShare(
-      session_context_->GetEnabledTypes(),
+      pending_configure_params_->types_to_download,
       pending_configure_params_->source,
       session.get());
   AdjustPolling(FORCE_RESET);
@@ -744,6 +744,7 @@
   // We're no longer throttled, so clear the wait interval.
   wait_interval_.reset();
   NotifyRetryTime(base::Time());
+  NotifyThrottledTypesChanged(nudge_tracker_.GetThrottledTypes());
 
   // We treat this as a 'canary' in the sense that it was originally scheduled
   // to run some time ago, failed, and we now want to retry, versus a job that
@@ -815,6 +816,7 @@
   wait_interval_.reset(new WaitInterval(WaitInterval::THROTTLED,
                                         throttle_duration));
   NotifyRetryTime(base::Time::Now() + wait_interval_->length);
+  NotifyThrottledTypesChanged(ModelTypeSet::All());
 }
 
 void SyncSchedulerImpl::OnTypesThrottled(
diff --git a/sync/engine/syncer.cc b/sync/engine/syncer.cc
index 508a2d9..a9f1ece 100644
--- a/sync/engine/syncer.cc
+++ b/sync/engine/syncer.cc
@@ -146,7 +146,8 @@
     // Apply upates to the other types.  May or may not involve cross-thread
     // traffic, depending on the underlying update handlers and the GU type's
     // delegate.
-    get_updates_processor->ApplyUpdates(session->mutable_status_controller());
+    get_updates_processor->ApplyUpdates(request_types,
+                                        session->mutable_status_controller());
 
     session->context()->set_hierarchy_conflict_detected(
         session->status_controller().num_hierarchy_conflicts() > 0);
diff --git a/sync/engine/syncer_proto_util_unittest.cc b/sync/engine/syncer_proto_util_unittest.cc
index d43b350..93f9088 100644
--- a/sync/engine/syncer_proto_util_unittest.cc
+++ b/sync/engine/syncer_proto_util_unittest.cc
@@ -39,13 +39,11 @@
    MockDelegate() {}
    ~MockDelegate() {}
 
-  MOCK_METHOD0(IsSyncingCurrentlySilenced, bool());
   MOCK_METHOD1(OnReceivedShortPollIntervalUpdate, void(const base::TimeDelta&));
   MOCK_METHOD1(OnReceivedLongPollIntervalUpdate ,void(const base::TimeDelta&));
   MOCK_METHOD1(OnReceivedSessionsCommitDelay, void(const base::TimeDelta&));
   MOCK_METHOD1(OnReceivedClientInvalidationHintBufferSize, void(int));
   MOCK_METHOD1(OnSyncProtocolError, void(const SyncProtocolError&));
-  MOCK_METHOD1(OnSilencedUntil, void(const base::TimeTicks&));
 };
 
 // Builds a ClientToServerResponse with some data type ids, including
diff --git a/sync/engine/syncer_unittest.cc b/sync/engine/syncer_unittest.cc
index d0a2ab4..7a3afe3 100644
--- a/sync/engine/syncer_unittest.cc
+++ b/sync/engine/syncer_unittest.cc
@@ -152,6 +152,7 @@
   }
   virtual void OnReceivedGuRetryDelay(const base::TimeDelta& delay) OVERRIDE {}
   virtual void OnReceivedMigrationRequest(ModelTypeSet types) OVERRIDE {}
+  virtual void OnProtocolEvent(const ProtocolEvent& event) OVERRIDE {}
   virtual void OnSyncProtocolError(const SyncProtocolError& error) OVERRIDE {}
 
   void GetModelSafeRoutingInfo(ModelSafeRoutingInfo* out) {
diff --git a/sync/internal_api/debug_info_event_listener.cc b/sync/internal_api/debug_info_event_listener.cc
index 6319a03..b3d5505 100644
--- a/sync/internal_api/debug_info_event_listener.cc
+++ b/sync/internal_api/debug_info_event_listener.cc
@@ -118,6 +118,8 @@
 
 void DebugInfoEventListener::OnMigrationRequested(ModelTypeSet types) {}
 
+void DebugInfoEventListener::OnProtocolEvent(const ProtocolEvent& event) {}
+
 void DebugInfoEventListener::OnNudgeFromDatatype(ModelType datatype) {
   DCHECK(thread_checker_.CalledOnValidThread());
   sync_pb::DebugEventInfo event_info;
diff --git a/sync/internal_api/debug_info_event_listener.h b/sync/internal_api/debug_info_event_listener.h
index d9a77c7..1f71682 100644
--- a/sync/internal_api/debug_info_event_listener.h
+++ b/sync/internal_api/debug_info_event_listener.h
@@ -51,6 +51,7 @@
   virtual void OnActionableError(
       const SyncProtocolError& sync_error) OVERRIDE;
   virtual void OnMigrationRequested(ModelTypeSet types) OVERRIDE;
+  virtual void OnProtocolEvent(const ProtocolEvent& event) OVERRIDE;
 
   // SyncEncryptionHandler::Observer implementation.
   virtual void OnPassphraseRequired(
diff --git a/sync/internal_api/events/commit_request_event.cc b/sync/internal_api/events/commit_request_event.cc
index bed23d3..0a1de1f 100644
--- a/sync/internal_api/events/commit_request_event.cc
+++ b/sync/internal_api/events/commit_request_event.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "sync/internal_api/events/commit_request_event.h"
+#include "sync/internal_api/public/events/commit_request_event.h"
 
 #include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
diff --git a/sync/internal_api/events/commit_response_event.cc b/sync/internal_api/events/commit_response_event.cc
index ec51f5e..c263e94 100644
--- a/sync/internal_api/events/commit_response_event.cc
+++ b/sync/internal_api/events/commit_response_event.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "sync/internal_api/events/commit_response_event.h"
+#include "sync/internal_api/public/events/commit_response_event.h"
 
 #include "base/strings/stringprintf.h"
 #include "sync/protocol/proto_value_conversions.h"
diff --git a/sync/internal_api/events/configure_get_updates_request_event.cc b/sync/internal_api/events/configure_get_updates_request_event.cc
index 252ae0a..8b487b6 100644
--- a/sync/internal_api/events/configure_get_updates_request_event.cc
+++ b/sync/internal_api/events/configure_get_updates_request_event.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "sync/internal_api/events/configure_get_updates_request_event.h"
+#include "sync/internal_api/public/events/configure_get_updates_request_event.h"
 
 #include "base/strings/stringprintf.h"
 #include "sync/protocol/proto_enum_conversions.h"
diff --git a/sync/internal_api/events/get_updates_response_event.cc b/sync/internal_api/events/get_updates_response_event.cc
index 17c0e8e..50bc551 100644
--- a/sync/internal_api/events/get_updates_response_event.cc
+++ b/sync/internal_api/events/get_updates_response_event.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "sync/internal_api/events/get_updates_response_event.h"
+#include "sync/internal_api/public/events/get_updates_response_event.h"
 
 #include "base/strings/stringprintf.h"
 #include "sync/protocol/proto_value_conversions.h"
diff --git a/sync/internal_api/events/normal_get_updates_request_event.cc b/sync/internal_api/events/normal_get_updates_request_event.cc
index d6a2f88..f5d6cd4 100644
--- a/sync/internal_api/events/normal_get_updates_request_event.cc
+++ b/sync/internal_api/events/normal_get_updates_request_event.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "sync/internal_api/events/normal_get_updates_request_event.h"
+#include "sync/internal_api/public/events/normal_get_updates_request_event.h"
 
 #include "base/strings/stringprintf.h"
 #include "sync/protocol/proto_value_conversions.h"
diff --git a/sync/internal_api/events/poll_get_updates_request_event.cc b/sync/internal_api/events/poll_get_updates_request_event.cc
index 802d4cb..c6eecb9 100644
--- a/sync/internal_api/events/poll_get_updates_request_event.cc
+++ b/sync/internal_api/events/poll_get_updates_request_event.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "sync/internal_api/events/poll_get_updates_request_event.h"
+#include "sync/internal_api/public/events/poll_get_updates_request_event.h"
 
 #include "sync/protocol/proto_value_conversions.h"
 
diff --git a/sync/internal_api/js_sync_manager_observer.cc b/sync/internal_api/js_sync_manager_observer.cc
index 57df9d3..b5f8452 100644
--- a/sync/internal_api/js_sync_manager_observer.cc
+++ b/sync/internal_api/js_sync_manager_observer.cc
@@ -60,6 +60,9 @@
                 JsEventDetails(&details));
 }
 
+void JsSyncManagerObserver::OnProtocolEvent(
+    const ProtocolEvent& event) { }
+
 void JsSyncManagerObserver::OnMigrationRequested(ModelTypeSet types) { }
 
 void JsSyncManagerObserver::OnInitializationComplete(
diff --git a/sync/internal_api/js_sync_manager_observer.h b/sync/internal_api/js_sync_manager_observer.h
index a30a40b..6f22005 100644
--- a/sync/internal_api/js_sync_manager_observer.h
+++ b/sync/internal_api/js_sync_manager_observer.h
@@ -42,6 +42,7 @@
       syncer::ModelTypeSet restored_types) OVERRIDE;
   virtual void OnActionableError(
       const SyncProtocolError& sync_protocol_error) OVERRIDE;
+  virtual void OnProtocolEvent(const ProtocolEvent& event) OVERRIDE;
   virtual void OnMigrationRequested(
       syncer::ModelTypeSet types) OVERRIDE;
 
diff --git a/sync/internal_api/non_blocking_type_processor.cc b/sync/internal_api/non_blocking_type_processor.cc
new file mode 100644
index 0000000..242c42f
--- /dev/null
+++ b/sync/internal_api/non_blocking_type_processor.cc
@@ -0,0 +1,57 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/internal_api/public/non_blocking_type_processor.h"
+
+#include "base/message_loop/message_loop_proxy.h"
+#include "sync/engine/non_blocking_type_processor_core.h"
+
+namespace syncer {
+
+NonBlockingTypeProcessor::NonBlockingTypeProcessor(ModelType type)
+  : type_(type), enabled_(false), weak_ptr_factory_(this) {}
+
+NonBlockingTypeProcessor::~NonBlockingTypeProcessor() {
+}
+
+bool NonBlockingTypeProcessor::IsEnabled() const {
+  DCHECK(CalledOnValidThread());
+  return enabled_;
+}
+
+ModelType NonBlockingTypeProcessor::GetModelType() const {
+  DCHECK(CalledOnValidThread());
+  return type_;
+}
+
+void NonBlockingTypeProcessor::Enable(SyncCoreProxy core_proxy_) {
+  DCHECK(CalledOnValidThread());
+  core_proxy_.ConnectTypeToCore(
+      GetModelType(),
+      AsWeakPtr());
+}
+
+void NonBlockingTypeProcessor::Disable() {
+  DCHECK(CalledOnValidThread());
+  enabled_ = false;
+  weak_ptr_factory_.InvalidateWeakPtrs();
+  core_ = base::WeakPtr<NonBlockingTypeProcessorCore>();
+  sync_thread_ = scoped_refptr<base::SequencedTaskRunner>();
+}
+
+base::WeakPtr<NonBlockingTypeProcessor> NonBlockingTypeProcessor::AsWeakPtr() {
+  DCHECK(CalledOnValidThread());
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+void NonBlockingTypeProcessor::OnConnect(
+    base::WeakPtr<NonBlockingTypeProcessorCore> core,
+    scoped_refptr<base::SequencedTaskRunner> sync_thread) {
+  DCHECK(CalledOnValidThread());
+  enabled_ = true;
+  core_ = core;
+  sync_thread_ = sync_thread;
+}
+
+}  // namespace syncer
diff --git a/sync/internal_api/events/commit_request_event.h b/sync/internal_api/public/events/commit_request_event.h
similarity index 100%
rename from sync/internal_api/events/commit_request_event.h
rename to sync/internal_api/public/events/commit_request_event.h
diff --git a/sync/internal_api/events/commit_response_event.h b/sync/internal_api/public/events/commit_response_event.h
similarity index 100%
rename from sync/internal_api/events/commit_response_event.h
rename to sync/internal_api/public/events/commit_response_event.h
diff --git a/sync/internal_api/events/configure_get_updates_request_event.h b/sync/internal_api/public/events/configure_get_updates_request_event.h
similarity index 100%
rename from sync/internal_api/events/configure_get_updates_request_event.h
rename to sync/internal_api/public/events/configure_get_updates_request_event.h
diff --git a/sync/internal_api/events/get_updates_response_event.h b/sync/internal_api/public/events/get_updates_response_event.h
similarity index 100%
rename from sync/internal_api/events/get_updates_response_event.h
rename to sync/internal_api/public/events/get_updates_response_event.h
diff --git a/sync/internal_api/events/normal_get_updates_request_event.h b/sync/internal_api/public/events/normal_get_updates_request_event.h
similarity index 100%
rename from sync/internal_api/events/normal_get_updates_request_event.h
rename to sync/internal_api/public/events/normal_get_updates_request_event.h
diff --git a/sync/internal_api/events/poll_get_updates_request_event.h b/sync/internal_api/public/events/poll_get_updates_request_event.h
similarity index 100%
rename from sync/internal_api/events/poll_get_updates_request_event.h
rename to sync/internal_api/public/events/poll_get_updates_request_event.h
diff --git a/sync/internal_api/public/non_blocking_type_processor.h b/sync/internal_api/public/non_blocking_type_processor.h
new file mode 100644
index 0000000..a9079d5
--- /dev/null
+++ b/sync/internal_api/public/non_blocking_type_processor.h
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_ENGINE_NON_BLOCKING_TYPE_PROCESSOR_H_
+#define SYNC_ENGINE_NON_BLOCKING_TYPE_PROCESSOR_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "base/threading/non_thread_safe.h"
+#include "sync/base/sync_export.h"
+#include "sync/internal_api/public/base/model_type.h"
+#include "sync/internal_api/public/sync_core_proxy.h"
+#include "sync/protocol/sync.pb.h"
+
+namespace syncer {
+
+class NonBlockingTypeProcessorCore;
+
+// A sync component embedded on the synced type's thread that helps to handle
+// communication between sync and model type threads.
+class SYNC_EXPORT_PRIVATE NonBlockingTypeProcessor : base::NonThreadSafe {
+ public:
+  NonBlockingTypeProcessor(ModelType type);
+  virtual ~NonBlockingTypeProcessor();
+
+  // Returns true if the handshake with sync thread is complete.
+  bool IsEnabled() const;
+
+  // Returns the model type handled by this processor.
+  ModelType GetModelType() const;
+
+  // Starts the handshake with the sync thread.
+  void Enable(SyncCoreProxy core_proxy_);
+
+  // Severs all ties to the sync thread.
+  // Another call to Enable() can be used to re-establish this connection.
+  void Disable();
+
+  // Callback used to process the handshake response.
+  void OnConnect(base::WeakPtr<NonBlockingTypeProcessorCore> core,
+                 scoped_refptr<base::SequencedTaskRunner> sync_thread);
+
+  base::WeakPtr<NonBlockingTypeProcessor> AsWeakPtr();
+
+ private:
+  ModelType type_;
+  sync_pb::DataTypeProgressMarker progress_marker_;
+  bool enabled_;
+
+  base::WeakPtr<NonBlockingTypeProcessorCore> core_;
+  scoped_refptr<base::SequencedTaskRunner> sync_thread_;
+
+  base::WeakPtrFactory<NonBlockingTypeProcessor> weak_ptr_factory_;
+};
+
+}  // namespace syncer
+
+#endif  // SYNC_ENGINE_NON_BLOCKING_TYPE_PROCESSOR_H_
diff --git a/sync/internal_api/public/sync_core_proxy.h b/sync/internal_api/public/sync_core_proxy.h
new file mode 100644
index 0000000..dd5a4ac
--- /dev/null
+++ b/sync/internal_api/public/sync_core_proxy.h
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_PROXY_H_
+#define SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_PROXY_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "sync/base/sync_export.h"
+#include "sync/internal_api/public/base/model_type.h"
+
+namespace syncer {
+
+class SyncCore;
+class NonBlockingTypeProcessor;
+
+// Encapsulates a reference to the sync core and the thread it's running on.
+// Used by sync's data types to connect with the sync core.
+//
+// It is epxected that this object will be copied to and used on many different
+// threads.  It is small and safe to pass by value.
+class SYNC_EXPORT_PRIVATE SyncCoreProxy {
+ public:
+  SyncCoreProxy(
+      scoped_refptr<base::SequencedTaskRunner> sync_task_runner,
+      base::WeakPtr<SyncCore> sync_core);
+  ~SyncCoreProxy();
+
+  // Attempts to connect a non-blocking type to the sync core.
+  //
+  // This may fail under some unusual circumstances, like shutdown.  Due to the
+  // nature of WeakPtrs and cross-thread communication, the caller will be
+  // unable to distinguish a slow success from failure.
+  //
+  // Must be called from the thread where the data type lives.
+  void ConnectTypeToCore(
+      syncer::ModelType type,
+      base::WeakPtr<NonBlockingTypeProcessor> type_processor);
+
+  // Constructs and returns a useless instance of this object.
+  static SyncCoreProxy GetInvalidSyncCoreProxyForTest();
+
+ private:
+  // A SequencedTaskRunner representing the thread where the SyncCore lives.
+  scoped_refptr<base::SequencedTaskRunner> sync_task_runner_;
+
+  // The SyncCore this object is wrapping.
+  base::WeakPtr<SyncCore> sync_core_;
+};
+
+}  // namespace syncer
+
+#endif  // SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_PROXY_H_
diff --git a/sync/internal_api/public/sync_manager.h b/sync/internal_api/public/sync_manager.h
index fa2e585..38bad07 100644
--- a/sync/internal_api/public/sync_manager.h
+++ b/sync/internal_api/public/sync_manager.h
@@ -20,6 +20,7 @@
 #include "sync/internal_api/public/configure_reason.h"
 #include "sync/internal_api/public/engine/model_safe_worker.h"
 #include "sync/internal_api/public/engine/sync_status.h"
+#include "sync/internal_api/public/events/protocol_event.h"
 #include "sync/internal_api/public/sync_encryption_handler.h"
 #include "sync/internal_api/public/util/report_unrecoverable_error_function.h"
 #include "sync/internal_api/public/util/unrecoverable_error_handler.h"
@@ -34,18 +35,20 @@
 namespace syncer {
 
 class BaseTransaction;
+class CancelationSignal;
 class DataTypeDebugInfoListener;
 class Encryptor;
-struct Experiments;
 class ExtensionsActivity;
 class HttpPostProviderFactory;
 class InternalComponentsFactory;
 class JsBackend;
 class JsEventHandler;
+class SyncCore;
 class SyncEncryptionHandler;
+class ProtocolEvent;
 class SyncScheduler;
+struct Experiments;
 struct UserShare;
-class CancelationSignal;
 
 namespace sessions {
 class SyncSessionSnapshot;
@@ -196,6 +199,8 @@
 
     virtual void OnMigrationRequested(ModelTypeSet types) = 0;
 
+    virtual void OnProtocolEvent(const ProtocolEvent& event) = 0;
+
    protected:
     virtual ~Observer();
   };
@@ -327,6 +332,9 @@
   // May be called from any thread.
   virtual UserShare* GetUserShare() = 0;
 
+  // Returns an instance of the main interface for non-blocking sync types.
+  virtual syncer::SyncCore* GetSyncCore() = 0;
+
   // Returns the cache_guid of the currently open database.
   // Requires that the SyncManager be initialized.
   virtual const std::string cache_guid() = 0;
diff --git a/sync/internal_api/public/test/fake_sync_manager.h b/sync/internal_api/public/test/fake_sync_manager.h
index 1194399..81b7160 100644
--- a/sync/internal_api/public/test/fake_sync_manager.h
+++ b/sync/internal_api/public/test/fake_sync_manager.h
@@ -119,6 +119,7 @@
   virtual void SaveChanges() OVERRIDE;
   virtual void ShutdownOnSyncThread() OVERRIDE;
   virtual UserShare* GetUserShare() OVERRIDE;
+  virtual syncer::SyncCore* GetSyncCore() OVERRIDE;
   virtual const std::string cache_guid() OVERRIDE;
   virtual bool ReceivedExperiment(Experiments* experiments) OVERRIDE;
   virtual bool HasUnsyncedItems() OVERRIDE;
diff --git a/sync/internal_api/public/util/experiments.h b/sync/internal_api/public/util/experiments.h
index 18a0887..9063cbb 100644
--- a/sync/internal_api/public/util/experiments.h
+++ b/sync/internal_api/public/util/experiments.h
@@ -15,6 +15,7 @@
 const char kPreCommitUpdateAvoidanceTag[] = "pre_commit_update_avoidance";
 const char kGCMChannelTag[] = "gcm_channel";
 const char kEnhancedBookmarksTag[] = "enhanced_bookmarks";
+const char kGCMInvalidationsTag[] = "gcm_invalidations";
 
 // A structure to hold the enable status of experimental sync features.
 struct Experiments {
@@ -27,13 +28,15 @@
   Experiments()
       : favicon_sync_limit(200),
         gcm_channel_state(UNSET),
-        enhanced_bookmarks_enabled(false) {}
+        enhanced_bookmarks_enabled(false),
+        gcm_invalidations_enabled(false) {}
 
   bool Matches(const Experiments& rhs) {
     return (favicon_sync_limit == rhs.favicon_sync_limit &&
             gcm_channel_state == rhs.gcm_channel_state &&
             enhanced_bookmarks_enabled == rhs.enhanced_bookmarks_enabled &&
-            enhanced_bookmarks_ext_id == rhs.enhanced_bookmarks_ext_id);
+            enhanced_bookmarks_ext_id == rhs.enhanced_bookmarks_ext_id &&
+            gcm_invalidations_enabled == rhs.gcm_invalidations_enabled);
   }
 
   // The number of favicons that a client is permitted to sync.
@@ -45,6 +48,9 @@
   // Enable the enhanced bookmarks sync datatype.
   bool enhanced_bookmarks_enabled;
 
+  // Enable invalidations over GCM channel.
+  bool gcm_invalidations_enabled;
+
   // Enhanced bookmarks extension id.
   std::string enhanced_bookmarks_ext_id;
 };
diff --git a/sync/internal_api/sync_core.cc b/sync/internal_api/sync_core.cc
new file mode 100644
index 0000000..9c26095
--- /dev/null
+++ b/sync/internal_api/sync_core.cc
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/internal_api/sync_core.h"
+
+#include "sync/engine/non_blocking_type_processor_core.h"
+#include "sync/sessions/model_type_registry.h"
+
+namespace syncer {
+
+SyncCore::SyncCore(ModelTypeRegistry* model_type_registry)
+    : model_type_registry_(model_type_registry), weak_ptr_factory_(this) {}
+
+SyncCore::~SyncCore() {}
+
+void SyncCore::ConnectSyncTypeToCore(
+    ModelType type,
+    scoped_refptr<base::SequencedTaskRunner> task_runner,
+    base::WeakPtr<NonBlockingTypeProcessor> processor) {
+
+  // Initialize the processor's sync-thread sibling and the
+  // processor <-> processor_core (ie. model thread <-> sync thread)
+  // communication channel.
+  model_type_registry_->InitializeNonBlockingType(type, task_runner, processor);
+}
+
+base::WeakPtr<SyncCore> SyncCore::AsWeakPtr() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+}  // namespace syncer
diff --git a/sync/internal_api/sync_core.h b/sync/internal_api/sync_core.h
new file mode 100644
index 0000000..504304c
--- /dev/null
+++ b/sync/internal_api/sync_core.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_H_
+#define SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_H_
+
+#include "base/basictypes.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequenced_task_runner.h"
+#include "sync/base/sync_export.h"
+#include "sync/internal_api/public/base/model_type.h"
+
+namespace syncer {
+
+class ModelTypeRegistry;
+class NonBlockingTypeProcessor;
+
+// An interface of the core parts of sync.
+//
+// In theory, this is the component that provides off-thread sync types with
+// functionality to schedule and execute communication with the sync server.  In
+// practice, this class delegates most of the responsibilty of implemeting this
+// functionality to other classes, and most of the interface is exposed not
+// directly here but instead through a per-ModelType class that this class helps
+// instantiate.
+class SYNC_EXPORT_PRIVATE SyncCore {
+ public:
+  explicit SyncCore(ModelTypeRegistry* model_type_registry);
+  ~SyncCore();
+
+  // Initializes the connection between the sync core and its delegate on the
+  // sync client's thread.
+  void ConnectSyncTypeToCore(
+    syncer::ModelType type,
+    scoped_refptr<base::SequencedTaskRunner> datatype_task_runner,
+    base::WeakPtr<NonBlockingTypeProcessor> sync_client);
+
+  base::WeakPtr<SyncCore> AsWeakPtr();
+
+ private:
+  ModelTypeRegistry* model_type_registry_;
+  base::WeakPtrFactory<SyncCore> weak_ptr_factory_;
+
+  DISALLOW_COPY_AND_ASSIGN(SyncCore);
+};
+
+}  // namespace syncer
+
+#endif  // SYNC_INTERNAL_API_PUBLIC_SYNC_CORE_H_
+
diff --git a/sync/internal_api/sync_core_proxy.cc b/sync/internal_api/sync_core_proxy.cc
new file mode 100644
index 0000000..5ba3135
--- /dev/null
+++ b/sync/internal_api/sync_core_proxy.cc
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/internal_api/public/sync_core_proxy.h"
+
+#include "base/bind.h"
+#include "base/location.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "sync/internal_api/sync_core.h"
+
+namespace syncer {
+
+SyncCoreProxy::SyncCoreProxy(
+    scoped_refptr<base::SequencedTaskRunner> sync_task_runner,
+    base::WeakPtr<SyncCore> sync_core)
+    : sync_task_runner_(sync_task_runner),
+      sync_core_(sync_core) {}
+
+SyncCoreProxy::~SyncCoreProxy() {}
+
+void SyncCoreProxy::ConnectTypeToCore(
+    ModelType type,
+    base::WeakPtr<NonBlockingTypeProcessor> type_processor) {
+  VLOG(1) << "ConnectSyncTypeToCore: " << ModelTypeToString(type);
+  sync_task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&SyncCore::ConnectSyncTypeToCore,
+                 sync_core_,
+                 type,
+                 base::MessageLoopProxy::current(),
+                 type_processor));
+}
+
+SyncCoreProxy SyncCoreProxy::GetInvalidSyncCoreProxyForTest() {
+  return SyncCoreProxy(scoped_refptr<base::SequencedTaskRunner>(),
+                       base::WeakPtr<SyncCore>());
+}
+
+}  // namespace syncer
diff --git a/sync/internal_api/sync_core_proxy_unittest.cc b/sync/internal_api/sync_core_proxy_unittest.cc
new file mode 100644
index 0000000..d6885bf
--- /dev/null
+++ b/sync/internal_api/sync_core_proxy_unittest.cc
@@ -0,0 +1,95 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_loop.h"
+#include "base/message_loop/message_loop_proxy.h"
+#include "base/run_loop.h"
+#include "base/sequenced_task_runner.h"
+#include "sync/internal_api/public/base/model_type.h"
+#include "sync/internal_api/public/non_blocking_type_processor.h"
+#include "sync/internal_api/public/sync_core_proxy.h"
+#include "sync/internal_api/sync_core.h"
+#include "sync/sessions/model_type_registry.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace syncer {
+
+class SyncCoreProxyTest : public ::testing::Test {
+ public:
+  SyncCoreProxyTest()
+      : sync_task_runner_(base::MessageLoopProxy::current()),
+        type_task_runner_(base::MessageLoopProxy::current()),
+        core_(new SyncCore(&registry_)),
+        core_proxy_(
+            sync_task_runner_,
+            core_->AsWeakPtr()) {}
+
+  // The sync thread could be shut down at any time without warning.  This
+  // function simulates such an event.
+  void DisableSync() {
+    core_.reset();
+  }
+
+  SyncCoreProxy GetProxy() {
+    return core_proxy_;
+  }
+
+ private:
+  base::MessageLoop loop_;
+  scoped_refptr<base::SequencedTaskRunner> sync_task_runner_;
+  scoped_refptr<base::SequencedTaskRunner> type_task_runner_;
+  ModelTypeRegistry registry_;
+  scoped_ptr<SyncCore> core_;
+  SyncCoreProxy core_proxy_;
+};
+
+// Try to connect a type to a SyncCore that has already shut down.
+TEST_F(SyncCoreProxyTest, FailToConnect1) {
+  NonBlockingTypeProcessor themes_processor(syncer::THEMES);
+  DisableSync();
+  themes_processor.Enable(GetProxy());
+
+  base::RunLoop run_loop_;
+  run_loop_.RunUntilIdle();
+  EXPECT_FALSE(themes_processor.IsEnabled());
+}
+
+// Try to connect a type to a SyncCore as it shuts down.
+TEST_F(SyncCoreProxyTest, FailToConnect2) {
+  NonBlockingTypeProcessor themes_processor(syncer::THEMES);
+  themes_processor.Enable(GetProxy());
+  DisableSync();
+
+  base::RunLoop run_loop_;
+  run_loop_.RunUntilIdle();
+  EXPECT_FALSE(themes_processor.IsEnabled());
+}
+
+// Tests the case where the type's processor shuts down first.
+TEST_F(SyncCoreProxyTest, TypeDisconnectsFirst) {
+  scoped_ptr<NonBlockingTypeProcessor> themes_processor
+      (new NonBlockingTypeProcessor(syncer::THEMES));
+  themes_processor->Enable(GetProxy());
+
+  base::RunLoop run_loop_;
+  run_loop_.RunUntilIdle();
+
+  EXPECT_TRUE(themes_processor->IsEnabled());
+  themes_processor.reset();
+}
+
+// Tests the case where the sync thread shuts down first.
+TEST_F(SyncCoreProxyTest, SyncDisconnectsFirst) {
+  scoped_ptr<NonBlockingTypeProcessor> themes_processor
+      (new NonBlockingTypeProcessor(syncer::THEMES));
+  themes_processor->Enable(GetProxy());
+
+  base::RunLoop run_loop_;
+  run_loop_.RunUntilIdle();
+
+  EXPECT_TRUE(themes_processor->IsEnabled());
+  DisableSync();
+}
+
+}  // namespace syncer
diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc
index 501f887..224b38b 100644
--- a/sync/internal_api/sync_manager_impl.cc
+++ b/sync/internal_api/sync_manager_impl.cc
@@ -32,6 +32,7 @@
 #include "sync/internal_api/public/util/experiments.h"
 #include "sync/internal_api/public/write_node.h"
 #include "sync/internal_api/public/write_transaction.h"
+#include "sync/internal_api/sync_core.h"
 #include "sync/internal_api/syncapi_internal.h"
 #include "sync/internal_api/syncapi_server_connection_manager.h"
 #include "sync/js/js_arg_list.h"
@@ -410,6 +411,8 @@
 
   model_type_registry_.reset(new ModelTypeRegistry(workers, directory()));
 
+  sync_core_.reset(new SyncCore(model_type_registry_.get()));
+
   // Build a SyncSessionContext and store the worker in it.
   DVLOG(1) << "Sync is bringing up SyncSessionContext.";
   std::vector<SyncEngineEventListener*> listeners;
@@ -899,7 +902,6 @@
   base::TimeDelta nudge_delay = NudgeStrategy::GetNudgeDelayTimeDelta(
       types.First().Get(),
       this);
-  allstatus_.IncrementNudgeCounter(NUDGE_SOURCE_LOCAL);
   scheduler_->ScheduleLocalNudge(nudge_delay,
                                  types,
                                  nudge_location);
@@ -943,6 +945,11 @@
       OnMigrationRequested(types));
 }
 
+void SyncManagerImpl::OnProtocolEvent(const ProtocolEvent& event) {
+  FOR_EACH_OBSERVER(SyncManager::Observer, observers_,
+                    OnProtocolEvent(event));
+}
+
 void SyncManagerImpl::SetJsEventHandler(
     const WeakHandle<JsEventHandler>& event_handler) {
   js_sync_manager_observer_.SetJsEventHandler(event_handler);
@@ -1029,11 +1036,9 @@
   if (invalidation_map.Empty()) {
     LOG(WARNING) << "Sync received invalidation without any type information.";
   } else {
-    allstatus_.IncrementNudgeCounter(NUDGE_SOURCE_NOTIFICATION);
     scheduler_->ScheduleInvalidationNudge(
         TimeDelta::FromMilliseconds(kSyncSchedulerDelayMsec),
         invalidation_map, FROM_HERE);
-    allstatus_.IncrementNotificationsReceived();
     debug_info_event_listener_.OnIncomingNotification(invalidation_map);
   }
 }
@@ -1045,7 +1050,6 @@
   if (types.Empty()) {
     LOG(WARNING) << "Sync received refresh request with no types specified.";
   } else {
-    allstatus_.IncrementNudgeCounter(NUDGE_SOURCE_LOCAL_REFRESH);
     scheduler_->ScheduleLocalRefreshRequest(
         TimeDelta::FromMilliseconds(kSyncRefreshDelayMsec),
         types, FROM_HERE);
@@ -1065,6 +1069,11 @@
   return &share_;
 }
 
+syncer::SyncCore* SyncManagerImpl::GetSyncCore() {
+  DCHECK(initialized_);
+  return sync_core_.get();
+}
+
 const std::string SyncManagerImpl::cache_guid() {
   DCHECK(initialized_);
   return directory()->cache_guid();
@@ -1128,6 +1137,18 @@
     found_experiment = true;
   }
 
+  ReadNode gcm_invalidations_node(&trans);
+  if (gcm_invalidations_node.InitByClientTagLookup(
+          syncer::EXPERIMENTS, syncer::kGCMInvalidationsTag) ==
+      BaseNode::INIT_OK) {
+    const sync_pb::GcmInvalidationsFlags& gcm_invalidations =
+        gcm_invalidations_node.GetExperimentsSpecifics().gcm_invalidations();
+    if (gcm_invalidations.has_enabled()) {
+      experiments->gcm_invalidations_enabled = gcm_invalidations.enabled();
+      found_experiment = true;
+    }
+  }
+
   return found_experiment;
 }
 
diff --git a/sync/internal_api/sync_manager_impl.h b/sync/internal_api/sync_manager_impl.h
index e2b3fb4..5cb3908 100644
--- a/sync/internal_api/sync_manager_impl.h
+++ b/sync/internal_api/sync_manager_impl.h
@@ -110,6 +110,7 @@
   virtual void SaveChanges() OVERRIDE;
   virtual void ShutdownOnSyncThread() OVERRIDE;
   virtual UserShare* GetUserShare() OVERRIDE;
+  virtual syncer::SyncCore* GetSyncCore() OVERRIDE;
   virtual const std::string cache_guid() OVERRIDE;
   virtual bool ReceivedExperiment(Experiments* experiments) OVERRIDE;
   virtual bool HasUnsyncedItems() OVERRIDE;
@@ -142,6 +143,7 @@
   virtual void OnRetryTimeChanged(base::Time retry_time) OVERRIDE;
   virtual void OnThrottledTypesChanged(ModelTypeSet throttled_types) OVERRIDE;
   virtual void OnMigrationRequested(ModelTypeSet types) OVERRIDE;
+  virtual void OnProtocolEvent(const ProtocolEvent& event) OVERRIDE;
 
   // ServerConnectionEventListener implementation.
   virtual void OnServerConnectionEvent(
@@ -310,6 +312,9 @@
   // This state changes when entering or exiting a configuration cycle.
   scoped_ptr<ModelTypeRegistry> model_type_registry_;
 
+  // The main interface for non-blocking sync types.
+  scoped_ptr<SyncCore> sync_core_;
+
   // A container of various bits of information used by the SyncScheduler to
   // create SyncSessions.  Must outlive the SyncScheduler.
   scoped_ptr<sessions::SyncSessionContext> session_context_;
diff --git a/sync/internal_api/sync_manager_impl_unittest.cc b/sync/internal_api/sync_manager_impl_unittest.cc
index 064db9e..7da7070 100644
--- a/sync/internal_api/sync_manager_impl_unittest.cc
+++ b/sync/internal_api/sync_manager_impl_unittest.cc
@@ -29,6 +29,7 @@
 #include "sync/internal_api/public/change_record.h"
 #include "sync/internal_api/public/engine/model_safe_worker.h"
 #include "sync/internal_api/public/engine/polling_constants.h"
+#include "sync/internal_api/public/events/protocol_event.h"
 #include "sync/internal_api/public/http_post_provider_factory.h"
 #include "sync/internal_api/public/http_post_provider_interface.h"
 #include "sync/internal_api/public/read_node.h"
@@ -646,10 +647,9 @@
                     syncer::ModelTypeSet));  // NOLINT
   MOCK_METHOD1(OnConnectionStatusChange, void(ConnectionStatus));  // NOLINT
   MOCK_METHOD1(OnUpdatedToken, void(const std::string&));  // NOLINT
-  MOCK_METHOD1(OnActionableError,
-               void(const SyncProtocolError&));  // NOLINT
-  MOCK_METHOD1(OnMigrationRequested,
-               void(syncer::ModelTypeSet));  // NOLINT
+  MOCK_METHOD1(OnActionableError, void(const SyncProtocolError&));  // NOLINT
+  MOCK_METHOD1(OnMigrationRequested, void(syncer::ModelTypeSet));  // NOLINT
+  MOCK_METHOD1(OnProtocolEvent, void(const ProtocolEvent&));  // NOLINT
 };
 
 class SyncEncryptionHandlerObserverMock
diff --git a/sync/internal_api/test/fake_sync_manager.cc b/sync/internal_api/test/fake_sync_manager.cc
index d6b538f..883da74 100644
--- a/sync/internal_api/test/fake_sync_manager.cc
+++ b/sync/internal_api/test/fake_sync_manager.cc
@@ -218,6 +218,10 @@
   return test_user_share_.user_share();
 }
 
+syncer::SyncCore* FakeSyncManager::GetSyncCore() {
+  return NULL;
+}
+
 const std::string FakeSyncManager::cache_guid() {
   return test_user_share_.user_share()->directory->cache_guid();
 }
diff --git a/sync/notifier/DEPS b/sync/notifier/DEPS
index 4469705..c16c291 100644
--- a/sync/notifier/DEPS
+++ b/sync/notifier/DEPS
@@ -3,6 +3,7 @@
   "+jingle/notifier",
   "+net/base/backoff_entry.h",
   "+net/base/mock_host_resolver.h",
+  "+net/base/network_change_notifier.h",
   "+net/http/http_status_code.h",
   "+net/url_request",
 
diff --git a/sync/notifier/fake_invalidator.cc b/sync/notifier/fake_invalidator.cc
index 2a321f1..dc41518 100644
--- a/sync/notifier/fake_invalidator.cc
+++ b/sync/notifier/fake_invalidator.cc
@@ -62,7 +62,7 @@
 }
 
 void FakeInvalidator::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> callback) {
+    base::Callback<void(const base::DictionaryValue&)> callback) const {
   base::DictionaryValue value;
   callback.Run(value);
 }
diff --git a/sync/notifier/fake_invalidator.h b/sync/notifier/fake_invalidator.h
index 43b9956..c94f82f 100644
--- a/sync/notifier/fake_invalidator.h
+++ b/sync/notifier/fake_invalidator.h
@@ -38,7 +38,8 @@
   virtual void UpdateCredentials(
       const std::string& email, const std::string& token) OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> callback) OVERRIDE;
+    base::Callback<void(const base::DictionaryValue&)> callback) const
+    OVERRIDE;
 
  private:
   InvalidatorRegistrar registrar_;
diff --git a/sync/notifier/gcm_network_channel.cc b/sync/notifier/gcm_network_channel.cc
index e194d9a..484ea05 100644
--- a/sync/notifier/gcm_network_channel.cc
+++ b/sync/notifier/gcm_network_channel.cc
@@ -4,9 +4,11 @@
 
 #include "base/base64.h"
 #include "base/i18n/time_formatting.h"
+#include "base/metrics/histogram.h"
 #include "base/sha1.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
-#if !defined(ANDROID)
+#if !defined(OS_ANDROID)
 // channel_common.proto defines ANDROID constant that conflicts with Android
 // build. At the same time TiclInvalidationService is not used on Android so it
 // is safe to exclude these protos from Android build.
@@ -55,54 +57,49 @@
   false,
 };
 
+// Incoming message status values for UMA_HISTOGRAM.
+enum IncomingMessageStatus {
+  INCOMING_MESSAGE_SUCCESS,
+  MESSAGE_EMPTY,     // GCM message's content is missing or empty.
+  INVALID_ENCODING,  // Base64Decode failed.
+  INVALID_PROTO,     // Parsing protobuf failed.
+
+  // This enum is used in UMA_HISTOGRAM_ENUMERATION. Insert new values above
+  // this line.
+  INCOMING_MESSAGE_STATUS_COUNT
+};
+
+// Outgoing message status values for UMA_HISTOGRAM.
+enum OutgoingMessageStatus {
+  OUTGOING_MESSAGE_SUCCESS,
+  MESSAGE_DISCARDED,     // New message started before old one was sent.
+  ACCESS_TOKEN_FAILURE,  // Requeting access token failed.
+  POST_FAILURE,          // HTTP Post failed.
+
+  // This enum is used in UMA_HISTOGRAM_ENUMERATION. Insert new values above
+  // this line.
+  OUTGOING_MESSAGE_STATUS_COUNT
+};
+
+const char kIncomingMessageStatusHistogram[] =
+    "GCMInvalidations.IncomingMessageStatus";
+const char kOutgoingMessageStatusHistogram[] =
+    "GCMInvalidations.OutgoingMessageStatus";
+
+void RecordIncomingMessageStatus(IncomingMessageStatus status) {
+  UMA_HISTOGRAM_ENUMERATION(kIncomingMessageStatusHistogram,
+                            status,
+                            INCOMING_MESSAGE_STATUS_COUNT);
+}
+
+void RecordOutgoingMessageStatus(OutgoingMessageStatus status) {
+  UMA_HISTOGRAM_ENUMERATION(kOutgoingMessageStatusHistogram,
+                            MESSAGE_DISCARDED,
+                            OUTGOING_MESSAGE_STATUS_COUNT);
+}
+
 }  // namespace
 
-GCMNetworkChannelDiagnostic::GCMNetworkChannelDiagnostic(
-    GCMNetworkChannel* parent)
-    : parent_(parent),
-      last_message_empty_echo_token_(false),
-      last_post_response_code_(0),
-      registration_result_(gcm::GCMClient::UNKNOWN_ERROR),
-      sent_messages_count_(0) {}
-
-scoped_ptr<base::DictionaryValue>
-GCMNetworkChannelDiagnostic::CollectDebugData() const {
-  scoped_ptr<base::DictionaryValue> status(new base::DictionaryValue);
-  status->SetString("GCMNetworkChannel.Channel", "GCM");
-  status->SetString("GCMNetworkChannel.HashedRegistrationID",
-                    base::SHA1HashString(registration_id_));
-  status->SetString("GCMNetworkChannel.RegistrationResult",
-                    GCMClientResultToString(registration_result_));
-  status->SetBoolean("GCMNetworkChannel.HadLastMessageEmptyEchoToken",
-                     last_message_empty_echo_token_);
-  status->SetString(
-      "GCMNetworkChannel.LastMessageReceivedTime",
-      base::TimeFormatShortDateAndTime(last_message_received_time_));
-  status->SetInteger("GCMNetworkChannel.LastPostResponseCode",
-                     last_post_response_code_);
-  status->SetInteger("GCMNetworkChannel.SentMessages", sent_messages_count_);
-  status->SetInteger("GCMNetworkChannel.ReceivedMessages",
-                     parent_->GetReceivedMessagesCount());
-  return status.Pass();
-}
-
-std::string GCMNetworkChannelDiagnostic::GCMClientResultToString(
-    const gcm::GCMClient::Result result) const {
-#define ENUM_CASE(x) case x: return #x; break;
-  switch (result) {
-    ENUM_CASE(gcm::GCMClient::SUCCESS);
-    ENUM_CASE(gcm::GCMClient::NETWORK_ERROR);
-    ENUM_CASE(gcm::GCMClient::SERVER_ERROR);
-    ENUM_CASE(gcm::GCMClient::TTL_EXCEEDED);
-    ENUM_CASE(gcm::GCMClient::UNKNOWN_ERROR);
-    ENUM_CASE(gcm::GCMClient::NOT_SIGNED_IN);
-    ENUM_CASE(gcm::GCMClient::INVALID_PARAMETER);
-    ENUM_CASE(gcm::GCMClient::ASYNC_OPERATION_PENDING);
-  }
-  NOTREACHED();
-  return "";
-}
-
 GCMNetworkChannel::GCMNetworkChannel(
     scoped_refptr<net::URLRequestContextGetter> request_context_getter,
     scoped_ptr<GCMNetworkChannelDelegate> delegate)
@@ -111,27 +108,13 @@
       register_backoff_entry_(new net::BackoffEntry(&kRegisterBackoffPolicy)),
       diagnostic_info_(this),
       weak_factory_(this) {
+  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
   delegate_->Initialize();
   Register();
 }
 
 GCMNetworkChannel::~GCMNetworkChannel() {
-}
-
-void GCMNetworkChannel::UpdateCredentials(
-    const std::string& email,
-    const std::string& token) {
-  // Do nothing. We get access token by requesting it for every message.
-}
-
-void GCMNetworkChannel::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> callback) {
-  callback.Run(*diagnostic_info_.CollectDebugData());
-}
-
-void GCMNetworkChannel::ResetRegisterBackoffEntryForTest(
-    const net::BackoffEntry::Policy* policy) {
-  register_backoff_entry_.reset(new net::BackoffEntry(policy));
+  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
 }
 
 void GCMNetworkChannel::Register() {
@@ -179,6 +162,9 @@
   DCHECK(!message.empty());
   DVLOG(2) << "SendMessage";
   diagnostic_info_.sent_messages_count_++;
+  if (!cached_message_.empty()) {
+    RecordOutgoingMessageStatus(MESSAGE_DISCARDED);
+  }
   cached_message_ = message;
 
   if (!registration_id_.empty()) {
@@ -186,13 +172,6 @@
   }
 }
 
-void GCMNetworkChannel::SetMessageReceiver(
-    invalidation::MessageCallback* incoming_receiver) {
-  delegate_->SetMessageReceiver(base::Bind(
-      &GCMNetworkChannel::OnIncomingMessage, weak_factory_.GetWeakPtr()));
-  SyncNetworkChannel::SetMessageReceiver(incoming_receiver);
-}
-
 void GCMNetworkChannel::RequestAccessToken() {
   DCHECK(CalledOnValidThread());
   delegate_->RequestToken(base::Bind(&GCMNetworkChannel::OnGetTokenComplete,
@@ -213,6 +192,12 @@
     // token service. Just drop this request, cacheinvalidations will retry
     // sending message and at that time we'll retry requesting access token.
     DVLOG(1) << "RequestAccessToken failed: " << error.ToString();
+    RecordOutgoingMessageStatus(ACCESS_TOKEN_FAILURE);
+    // Message won't get sent because of connection failure. Let's retry once
+    // connection is restored.
+    if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED)
+      NotifyStateChange(TRANSIENT_INVALIDATION_ERROR);
+    cached_message_.clear();
     return;
   }
   DCHECK(!token.empty());
@@ -235,30 +220,6 @@
   cached_message_.clear();
 }
 
-void GCMNetworkChannel::OnIncomingMessage(const std::string& message,
-                                          const std::string& echo_token) {
-#if !defined(ANDROID)
-  DCHECK(!message.empty());
-  if (!echo_token.empty())
-    echo_token_ = echo_token;
-  diagnostic_info_.last_message_empty_echo_token_ = echo_token.empty();
-  std::string data;
-  if (!Base64DecodeURLSafe(message, &data))
-    return;
-  ipc::invalidation::AddressedAndroidMessage android_message;
-  if (!android_message.ParseFromString(data))
-    return;
-  if (!android_message.has_message())
-    return;
-  diagnostic_info_.last_message_received_time_ = base::Time::Now();
-  DVLOG(2) << "Deliver incoming message";
-  DeliverIncomingMessage(android_message.message());
-#else
-  // This code shouldn't be invoked on Android.
-  NOTREACHED();
-#endif
-}
-
 void GCMNetworkChannel::OnURLFetchComplete(const net::URLFetcher* source) {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(fetcher_, source);
@@ -268,23 +229,71 @@
   net::URLRequestStatus status = fetcher->GetStatus();
   diagnostic_info_.last_post_response_code_ =
       status.is_success() ? source->GetResponseCode() : status.error();
-  if (!status.is_success()) {
+
+  if (status.is_success() &&
+      fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) {
+    DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED";
+    delegate_->InvalidateToken(access_token_);
+  }
+
+  if (!status.is_success() ||
+      (fetcher->GetResponseCode() != net::HTTP_OK &&
+       fetcher->GetResponseCode() != net::HTTP_NO_CONTENT)) {
     DVLOG(1) << "URLFetcher failure";
+    RecordOutgoingMessageStatus(POST_FAILURE);
+    NotifyStateChange(TRANSIENT_INVALIDATION_ERROR);
     return;
   }
 
-  if (fetcher->GetResponseCode() == net::HTTP_UNAUTHORIZED) {
-    DVLOG(1) << "URLFetcher failure: HTTP_UNAUTHORIZED";
-    delegate_->InvalidateToken(access_token_);
+  RecordOutgoingMessageStatus(OUTGOING_MESSAGE_SUCCESS);
+  NotifyStateChange(INVALIDATIONS_ENABLED);
+  DVLOG(2) << "URLFetcher success";
+}
+
+void GCMNetworkChannel::OnIncomingMessage(const std::string& message,
+                                          const std::string& echo_token) {
+#if !defined(OS_ANDROID)
+  if (!echo_token.empty())
+    echo_token_ = echo_token;
+  diagnostic_info_.last_message_empty_echo_token_ = echo_token.empty();
+  diagnostic_info_.last_message_received_time_ = base::Time::Now();
+
+  if (message.empty()) {
+    RecordIncomingMessageStatus(MESSAGE_EMPTY);
     return;
   }
-  DVLOG(2) << "URLFetcher success";
+  std::string data;
+  if (!Base64DecodeURLSafe(message, &data)) {
+    RecordIncomingMessageStatus(INVALID_ENCODING);
+    return;
+  }
+  ipc::invalidation::AddressedAndroidMessage android_message;
+  if (!android_message.ParseFromString(data) ||
+      !android_message.has_message()) {
+    RecordIncomingMessageStatus(INVALID_PROTO);
+    return;
+  }
+  DVLOG(2) << "Deliver incoming message";
+  RecordIncomingMessageStatus(INCOMING_MESSAGE_SUCCESS);
+  DeliverIncomingMessage(android_message.message());
+#else
+  // This code shouldn't be invoked on Android.
+  NOTREACHED();
+#endif
+}
+
+void GCMNetworkChannel::OnNetworkChanged(
+    net::NetworkChangeNotifier::ConnectionType connection_type) {
+  // Network connection is restored. Let's notify cacheinvalidations so it has
+  // chance to retry.
+  if (connection_type != net::NetworkChangeNotifier::CONNECTION_NONE)
+    NotifyStateChange(INVALIDATIONS_ENABLED);
 }
 
 GURL GCMNetworkChannel::BuildUrl(const std::string& registration_id) {
   DCHECK(!registration_id.empty());
 
-#if !defined(ANDROID)
+#if !defined(OS_ANDROID)
   ipc::invalidation::EndpointId endpoint_id;
   endpoint_id.set_c2dm_registration_id(registration_id);
   endpoint_id.set_client_key(std::string());
@@ -339,4 +348,73 @@
   return base::Base64Decode(padded_input, output);
 }
 
+void GCMNetworkChannel::SetMessageReceiver(
+    invalidation::MessageCallback* incoming_receiver) {
+  delegate_->SetMessageReceiver(base::Bind(
+      &GCMNetworkChannel::OnIncomingMessage, weak_factory_.GetWeakPtr()));
+  SyncNetworkChannel::SetMessageReceiver(incoming_receiver);
+}
+
+void GCMNetworkChannel::RequestDetailedStatus(
+    base::Callback<void(const base::DictionaryValue&)> callback) {
+  callback.Run(*diagnostic_info_.CollectDebugData());
+}
+
+void GCMNetworkChannel::UpdateCredentials(const std::string& email,
+                                          const std::string& token) {
+  // Do nothing. We get access token by requesting it for every message.
+}
+
+void GCMNetworkChannel::ResetRegisterBackoffEntryForTest(
+    const net::BackoffEntry::Policy* policy) {
+  register_backoff_entry_.reset(new net::BackoffEntry(policy));
+}
+
+GCMNetworkChannelDiagnostic::GCMNetworkChannelDiagnostic(
+    GCMNetworkChannel* parent)
+    : parent_(parent),
+      last_message_empty_echo_token_(false),
+      last_post_response_code_(0),
+      registration_result_(gcm::GCMClient::UNKNOWN_ERROR),
+      sent_messages_count_(0) {}
+
+scoped_ptr<base::DictionaryValue>
+GCMNetworkChannelDiagnostic::CollectDebugData() const {
+  scoped_ptr<base::DictionaryValue> status(new base::DictionaryValue);
+  status->SetString("GCMNetworkChannel.Channel", "GCM");
+  std::string reg_id_hash = base::SHA1HashString(registration_id_);
+  status->SetString("GCMNetworkChannel.HashedRegistrationID",
+                    base::HexEncode(reg_id_hash.c_str(), reg_id_hash.size()));
+  status->SetString("GCMNetworkChannel.RegistrationResult",
+                    GCMClientResultToString(registration_result_));
+  status->SetBoolean("GCMNetworkChannel.HadLastMessageEmptyEchoToken",
+                     last_message_empty_echo_token_);
+  status->SetString(
+      "GCMNetworkChannel.LastMessageReceivedTime",
+      base::TimeFormatShortDateAndTime(last_message_received_time_));
+  status->SetInteger("GCMNetworkChannel.LastPostResponseCode",
+                     last_post_response_code_);
+  status->SetInteger("GCMNetworkChannel.SentMessages", sent_messages_count_);
+  status->SetInteger("GCMNetworkChannel.ReceivedMessages",
+                     parent_->GetReceivedMessagesCount());
+  return status.Pass();
+}
+
+std::string GCMNetworkChannelDiagnostic::GCMClientResultToString(
+    const gcm::GCMClient::Result result) const {
+#define ENUM_CASE(x) case x: return #x; break;
+  switch (result) {
+    ENUM_CASE(gcm::GCMClient::SUCCESS);
+    ENUM_CASE(gcm::GCMClient::NETWORK_ERROR);
+    ENUM_CASE(gcm::GCMClient::SERVER_ERROR);
+    ENUM_CASE(gcm::GCMClient::TTL_EXCEEDED);
+    ENUM_CASE(gcm::GCMClient::UNKNOWN_ERROR);
+    ENUM_CASE(gcm::GCMClient::NOT_SIGNED_IN);
+    ENUM_CASE(gcm::GCMClient::INVALID_PARAMETER);
+    ENUM_CASE(gcm::GCMClient::ASYNC_OPERATION_PENDING);
+  }
+  NOTREACHED();
+  return "";
+}
+
 }  // namespace syncer
diff --git a/sync/notifier/gcm_network_channel.h b/sync/notifier/gcm_network_channel.h
index 9fc6364..b2b8d6c 100644
--- a/sync/notifier/gcm_network_channel.h
+++ b/sync/notifier/gcm_network_channel.h
@@ -12,6 +12,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/threading/non_thread_safe.h"
 #include "net/base/backoff_entry.h"
+#include "net/base/network_change_notifier.h"
 #include "net/url_request/url_fetcher_delegate.h"
 #include "sync/base/sync_export.h"
 #include "sync/notifier/gcm_network_channel_delegate.h"
@@ -48,6 +49,7 @@
 class SYNC_EXPORT_PRIVATE GCMNetworkChannel
     : public SyncNetworkChannel,
       public net::URLFetcherDelegate,
+      public net::NetworkChangeNotifier::NetworkChangeObserver,
       public base::NonThreadSafe {
  public:
   GCMNetworkChannel(
@@ -70,6 +72,10 @@
   // URLFetcherDelegate implementation.
   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
 
+  // NetworkChangeObserver implementation.
+  virtual void OnNetworkChanged(
+      net::NetworkChangeNotifier::ConnectionType connection_type) OVERRIDE;
+
  protected:
   void ResetRegisterBackoffEntryForTest(
       const net::BackoffEntry::Policy* policy);
diff --git a/sync/notifier/gcm_network_channel_unittest.cc b/sync/notifier/gcm_network_channel_unittest.cc
index e648c58..2564d0b 100644
--- a/sync/notifier/gcm_network_channel_unittest.cc
+++ b/sync/notifier/gcm_network_channel_unittest.cc
@@ -118,8 +118,8 @@
  public:
   GCMNetworkChannelTest()
       : delegate_(NULL),
-        url_fetchers_created_count_(0) {
-  }
+        url_fetchers_created_count_(0),
+        last_invalidator_state_(TRANSIENT_INVALIDATION_ERROR) {}
 
   virtual ~GCMNetworkChannelTest() {
   }
@@ -164,6 +164,7 @@
 
   virtual void OnNetworkChannelStateChanged(
       InvalidatorState invalidator_state) OVERRIDE {
+    last_invalidator_state_ = invalidator_state;
   }
 
   void OnIncomingMessage(std::string incoming_message) {
@@ -204,6 +205,10 @@
     return last_echo_token_;
   }
 
+  InvalidatorState get_last_invalidator_state() {
+    return last_invalidator_state_;
+  }
+
   void RunLoopUntilIdle() {
     base::RunLoop run_loop;
     run_loop.RunUntilIdle();
@@ -217,6 +222,7 @@
   scoped_ptr<net::FakeURLFetcherFactory> url_fetcher_factory_;
   int url_fetchers_created_count_;
   std::string last_echo_token_;
+  InvalidatorState last_invalidator_state_;
 };
 
 void TestNetworkChannelURLFetcher::AddExtraRequestHeader(
@@ -233,10 +239,11 @@
 }
 
 TEST_F(GCMNetworkChannelTest, HappyCase) {
+  EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state());
   EXPECT_FALSE(delegate()->message_callback.is_null());
   url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
                                          std::string(),
-                                         net::HTTP_OK,
+                                         net::HTTP_NO_CONTENT,
                                          net::URLRequestStatus::SUCCESS);
 
   // After construction GCMNetworkChannel should have called Register.
@@ -261,6 +268,7 @@
       GoogleServiceAuthError::AuthErrorNone(), "access.token2");
   RunLoopUntilIdle();
   EXPECT_EQ(url_fetchers_created_count(), 1);
+  EXPECT_EQ(INVALIDATIONS_ENABLED, get_last_invalidator_state());
 }
 
 TEST_F(GCMNetworkChannelTest, FailedRegister) {
@@ -287,7 +295,7 @@
 TEST_F(GCMNetworkChannelTest, RegisterFinishesAfterSendMessage) {
   url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
                                          "",
-                                         net::HTTP_OK,
+                                         net::HTTP_NO_CONTENT,
                                          net::URLRequestStatus::SUCCESS);
 
   // After construction GCMNetworkChannel should have called Register.
@@ -371,19 +379,6 @@
   EXPECT_FALSE(delegate()->request_token_callback.is_null());
 }
 
-#if !defined(ANDROID)
-TEST_F(GCMNetworkChannelTest, BuildUrl) {
-  GURL url = BuildUrl("registration.id");
-  EXPECT_TRUE(url.SchemeIsHTTPOrHTTPS());
-  EXPECT_FALSE(url.host().empty());
-  EXPECT_FALSE(url.path().empty());
-  std::vector<std::string> parts;
-  Tokenize(url.path(), "/", &parts);
-  std::string buffer;
-  EXPECT_TRUE(Base64DecodeURLSafe(parts[parts.size() - 1], &buffer));
-}
-#endif
-
 TEST_F(GCMNetworkChannelTest, Base64EncodeDecode) {
   std::string input;
   std::string plain;
@@ -411,7 +406,49 @@
   EXPECT_EQ(input, plain);
 }
 
-#if !defined(ANDROID)
+TEST_F(GCMNetworkChannelTest, TransientError) {
+  EXPECT_FALSE(delegate()->message_callback.is_null());
+  // POST will fail.
+  url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
+                                         std::string(),
+                                         net::HTTP_SERVICE_UNAVAILABLE,
+                                         net::URLRequestStatus::SUCCESS);
+
+  delegate()->register_callback.Run("registration.id", gcm::GCMClient::SUCCESS);
+
+  network_channel()->SendMessage("abra.cadabra");
+  EXPECT_FALSE(delegate()->request_token_callback.is_null());
+  delegate()->request_token_callback.Run(
+      GoogleServiceAuthError::AuthErrorNone(), "access.token");
+  RunLoopUntilIdle();
+  EXPECT_EQ(url_fetchers_created_count(), 1);
+  // Failing HTTP POST should cause TRANSIENT_INVALIDATION_ERROR.
+  EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state());
+  // Network change to CONNECTION_NONE shouldn't affect invalidator state.
+  network_channel()->OnNetworkChanged(
+      net::NetworkChangeNotifier::CONNECTION_NONE);
+  EXPECT_EQ(TRANSIENT_INVALIDATION_ERROR, get_last_invalidator_state());
+  // Network change to something else should trigger retry.
+  network_channel()->OnNetworkChanged(
+      net::NetworkChangeNotifier::CONNECTION_WIFI);
+  EXPECT_EQ(INVALIDATIONS_ENABLED, get_last_invalidator_state());
+  network_channel()->OnNetworkChanged(
+      net::NetworkChangeNotifier::CONNECTION_NONE);
+  EXPECT_EQ(INVALIDATIONS_ENABLED, get_last_invalidator_state());
+}
+
+#if !defined(OS_ANDROID)
+TEST_F(GCMNetworkChannelTest, BuildUrl) {
+  GURL url = BuildUrl("registration.id");
+  EXPECT_TRUE(url.SchemeIsHTTPOrHTTPS());
+  EXPECT_FALSE(url.host().empty());
+  EXPECT_FALSE(url.path().empty());
+  std::vector<std::string> parts;
+  Tokenize(url.path(), "/", &parts);
+  std::string buffer;
+  EXPECT_TRUE(Base64DecodeURLSafe(parts[parts.size() - 1], &buffer));
+}
+
 TEST_F(GCMNetworkChannelTest, EchoToken) {
   url_fetcher_factory()->SetFakeResponse(GURL("http://test.url.com"),
                                          std::string(),
diff --git a/sync/notifier/invalidation_notifier.cc b/sync/notifier/invalidation_notifier.cc
index 0f2f4b7..2ae6079 100644
--- a/sync/notifier/invalidation_notifier.cc
+++ b/sync/notifier/invalidation_notifier.cc
@@ -74,7 +74,7 @@
 }
 
 void InvalidationNotifier::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> callback) {
+    base::Callback<void(const base::DictionaryValue&)> callback) const {
   DCHECK(CalledOnValidThread());
   invalidation_listener_.RequestDetailedStatus(callback);
 }
diff --git a/sync/notifier/invalidation_notifier.h b/sync/notifier/invalidation_notifier.h
index 444b952..3add4a8 100644
--- a/sync/notifier/invalidation_notifier.h
+++ b/sync/notifier/invalidation_notifier.h
@@ -59,7 +59,8 @@
   virtual void UpdateCredentials(
       const std::string& email, const std::string& token) OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> callback) OVERRIDE;
+      base::Callback<void(const base::DictionaryValue&)> callback) const
+      OVERRIDE;
 
   // SyncInvalidationListener::Delegate implementation.
   virtual void OnInvalidate(
diff --git a/sync/notifier/invalidator.h b/sync/notifier/invalidator.h
index f934727..3c50fe6 100644
--- a/sync/notifier/invalidator.h
+++ b/sync/notifier/invalidator.h
@@ -81,7 +81,7 @@
 
   // Requests internal detailed status to be posted back to the callback.
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> callback) = 0;
+      base::Callback<void(const base::DictionaryValue&)> callback) const = 0;
 };
 }  // namespace syncer
 
diff --git a/sync/notifier/invalidator_registrar_unittest.cc b/sync/notifier/invalidator_registrar_unittest.cc
index efd11d0..6614f96 100644
--- a/sync/notifier/invalidator_registrar_unittest.cc
+++ b/sync/notifier/invalidator_registrar_unittest.cc
@@ -52,7 +52,7 @@
   }
 
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> call) OVERRIDE {
+      base::Callback<void(const base::DictionaryValue&)> call) const OVERRIDE {
     // Do nothing.
   }
 
diff --git a/sync/notifier/non_blocking_invalidator.cc b/sync/notifier/non_blocking_invalidator.cc
index d0a5a35..db8d018 100644
--- a/sync/notifier/non_blocking_invalidator.cc
+++ b/sync/notifier/non_blocking_invalidator.cc
@@ -107,7 +107,7 @@
   void UpdateRegisteredIds(const ObjectIdSet& ids);
   void UpdateCredentials(const std::string& email, const std::string& token);
   void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> callback);
+      base::Callback<void(const base::DictionaryValue&)> callback) const;
 
   // InvalidationHandler implementation (all called on I/O thread by
   // InvalidationNotifier).
@@ -177,7 +177,7 @@
 }
 
 void NonBlockingInvalidator::Core::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> callback) {
+    base::Callback<void(const base::DictionaryValue&)> callback) const {
   DCHECK(network_task_runner_->BelongsToCurrentThread());
   invalidation_notifier_->RequestDetailedStatus(callback);
 }
@@ -285,7 +285,7 @@
 }
 
 void NonBlockingInvalidator::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> callback) {
+    base::Callback<void(const base::DictionaryValue&)> callback) const {
   DCHECK(parent_task_runner_->BelongsToCurrentThread());
   base::Callback<void(const base::DictionaryValue&)> proxy_callback =
       base::Bind(&CallbackProxy::Run, base::Owned(new CallbackProxy(callback)));
diff --git a/sync/notifier/non_blocking_invalidator.h b/sync/notifier/non_blocking_invalidator.h
index d32b4e3..47bd216 100644
--- a/sync/notifier/non_blocking_invalidator.h
+++ b/sync/notifier/non_blocking_invalidator.h
@@ -64,7 +64,8 @@
   virtual void UpdateCredentials(
       const std::string& email, const std::string& token) OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> callback) OVERRIDE;
+      base::Callback<void(const base::DictionaryValue&)> callback) const
+      OVERRIDE;
 
   // InvalidationHandler implementation.
   virtual void OnInvalidatorStateChange(InvalidatorState state) OVERRIDE;
diff --git a/sync/notifier/p2p_invalidator.cc b/sync/notifier/p2p_invalidator.cc
index 2e11e24..f84f34e 100644
--- a/sync/notifier/p2p_invalidator.cc
+++ b/sync/notifier/p2p_invalidator.cc
@@ -203,7 +203,7 @@
 }
 
 void P2PInvalidator::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> callback) {
+    base::Callback<void(const base::DictionaryValue&)> callback) const {
   DCHECK(thread_checker_.CalledOnValidThread());
   // TODO(mferreria): Make the P2P Invalidator work.
   scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
diff --git a/sync/notifier/p2p_invalidator.h b/sync/notifier/p2p_invalidator.h
index 4e95747..07f46e7 100644
--- a/sync/notifier/p2p_invalidator.h
+++ b/sync/notifier/p2p_invalidator.h
@@ -110,7 +110,8 @@
   virtual void UpdateCredentials(
       const std::string& email, const std::string& token) OVERRIDE;
   virtual void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> callback) OVERRIDE;
+      base::Callback<void(const base::DictionaryValue&)> callback) const
+      OVERRIDE;
 
   // PushClientObserver implementation.
   virtual void OnNotificationsEnabled() OVERRIDE;
diff --git a/sync/notifier/registration_manager.cc b/sync/notifier/registration_manager.cc
index 4c59e01..cb852e3 100644
--- a/sync/notifier/registration_manager.cc
+++ b/sync/notifier/registration_manager.cc
@@ -101,8 +101,8 @@
   DCHECK(CalledOnValidThread());
   RegistrationStatusMap::const_iterator it = registration_statuses_.find(id);
   if (it == registration_statuses_.end()) {
-    DLOG(WARNING) << "Attempt to mark non-existent registration for "
-                  << ObjectIdToString(id) << " as lost";
+    DVLOG(1) << "Attempt to mark non-existent registration for "
+             << ObjectIdToString(id) << " as lost";
     return;
   }
   if (!it->second->enabled) {
@@ -128,8 +128,8 @@
   DCHECK(CalledOnValidThread());
   RegistrationStatusMap::const_iterator it = registration_statuses_.find(id);
   if (it == registration_statuses_.end()) {
-    DLOG(WARNING) << "Attempt to disable non-existent registration for "
-                  << ObjectIdToString(id);
+    DVLOG(1) << "Attempt to disable non-existent registration for "
+             << ObjectIdToString(id);
     return;
   }
   it->second->Disable();
@@ -204,8 +204,8 @@
   DCHECK(CalledOnValidThread());
   RegistrationStatusMap::const_iterator it = registration_statuses_.find(id);
   if (it == registration_statuses_.end()) {
-    DLOG(FATAL) << "TryRegisterId called on " << ObjectIdToString(id)
-                << " which is not in the registration map";
+    NOTREACHED() << "TryRegisterId called on " << ObjectIdToString(id)
+                 << " which is not in the registration map";
     return;
   }
   RegistrationStatus* status = it->second;
@@ -258,8 +258,8 @@
   invalidation_client_->Register(id);
   RegistrationStatusMap::const_iterator it = registration_statuses_.find(id);
   if (it == registration_statuses_.end()) {
-    DLOG(FATAL) << "DoRegisterId called on " << ObjectIdToString(id)
-                << " which is not in the registration map";
+    NOTREACHED() << "DoRegisterId called on " << ObjectIdToString(id)
+                 << " which is not in the registration map";
     return;
   }
   it->second->state = invalidation::InvalidationListener::REGISTERED;
@@ -271,8 +271,8 @@
   invalidation_client_->Unregister(id);
   RegistrationStatusMap::iterator it = registration_statuses_.find(id);
   if (it == registration_statuses_.end()) {
-    DLOG(FATAL) << "UnregisterId called on " << ObjectIdToString(id)
-                << " which is not in the registration map";
+    NOTREACHED() << "UnregisterId called on " << ObjectIdToString(id)
+                 << " which is not in the registration map";
     return;
   }
   delete it->second;
diff --git a/sync/notifier/sync_invalidation_listener.cc b/sync/notifier/sync_invalidation_listener.cc
index c5dc8e3..231a5b7 100644
--- a/sync/notifier/sync_invalidation_listener.cc
+++ b/sync/notifier/sync_invalidation_listener.cc
@@ -361,7 +361,7 @@
 }
 
 void SyncInvalidationListener::RequestDetailedStatus(
-    base::Callback<void(const base::DictionaryValue&)> callback) {
+    base::Callback<void(const base::DictionaryValue&)> callback) const {
   DCHECK(CalledOnValidThread());
   sync_network_channel_->RequestDetailedStatus(callback);
   callback.Run(*CollectDebugData());
diff --git a/sync/notifier/sync_invalidation_listener.h b/sync/notifier/sync_invalidation_listener.h
index fddc208..aa332fb 100644
--- a/sync/notifier/sync_invalidation_listener.h
+++ b/sync/notifier/sync_invalidation_listener.h
@@ -137,7 +137,7 @@
   void DoRegistrationUpdate();
 
   void RequestDetailedStatus(
-      base::Callback<void(const base::DictionaryValue&)> callback);
+      base::Callback<void(const base::DictionaryValue&)> callback) const;
 
   void StopForTest();
 
diff --git a/sync/protocol/experiments_specifics.proto b/sync/protocol/experiments_specifics.proto
index 790cf02..723fe55 100644
--- a/sync/protocol/experiments_specifics.proto
+++ b/sync/protocol/experiments_specifics.proto
@@ -50,6 +50,11 @@
   optional string extension_id = 2;
 }
 
+// Flags for enabling GCM channel for invalidations.
+message GcmInvalidationsFlags {
+  optional bool enabled = 1;
+}
+
 // Contains one flag or set of related flags.  Each node of the experiments type
 // will have a unique_client_tag identifying which flags it contains.  By
 // convention, the tag name should match the sub-message name.
@@ -61,4 +66,5 @@
   optional PreCommitUpdateAvoidanceFlags pre_commit_update_avoidance = 5;
   optional GcmChannelFlags gcm_channel = 6;
   optional EnhancedBookmarksFlags enhanced_bookmarks = 7;
+  optional GcmInvalidationsFlags gcm_invalidations = 8;
 }
diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc
index 83748fa..496a35d 100644
--- a/sync/protocol/proto_value_conversions.cc
+++ b/sync/protocol/proto_value_conversions.cc
@@ -503,6 +503,7 @@
   SET(favicon_sync, FaviconSyncFlagsToValue);
   SET_EXPERIMENT_ENABLED_FIELD(gcm_channel);
   SET_EXPERIMENT_ENABLED_FIELD(enhanced_bookmarks);
+  SET_EXPERIMENT_ENABLED_FIELD(gcm_invalidations);
   return value;
 }
 
diff --git a/sync/sessions/DEPS b/sync/sessions/DEPS
index b4042e3..36fed20 100644
--- a/sync/sessions/DEPS
+++ b/sync/sessions/DEPS
@@ -1,9 +1,7 @@
 include_rules = [
   "+sync/base",
   "+sync/engine",
-  "+sync/internal_api/public/base",
-  "+sync/internal_api/public/engine",
-  "+sync/internal_api/public/sessions",
+  "+sync/internal_api/public",
   "+sync/notifier",
   "+sync/protocol",
   "+sync/syncable",
diff --git a/sync/sessions/model_type_registry.cc b/sync/sessions/model_type_registry.cc
index ab93c68..f93cba3 100644
--- a/sync/sessions/model_type_registry.cc
+++ b/sync/sessions/model_type_registry.cc
@@ -4,12 +4,17 @@
 
 #include "sync/sessions/model_type_registry.h"
 
+#include "base/bind.h"
+#include "base/message_loop/message_loop_proxy.h"
 #include "sync/engine/directory_commit_contributor.h"
 #include "sync/engine/directory_update_handler.h"
 #include "sync/engine/non_blocking_type_processor_core.h"
+#include "sync/internal_api/public/non_blocking_type_processor.h"
 
 namespace syncer {
 
+ModelTypeRegistry::ModelTypeRegistry() : directory_(NULL) {}
+
 ModelTypeRegistry::ModelTypeRegistry(
     const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
     syncable::Directory* directory)
@@ -67,13 +72,28 @@
   }
 
   enabled_directory_types_ = GetRoutingInfoTypes(routing_info);
+  DCHECK(Intersection(GetEnabledDirectoryTypes(),
+                      GetEnabledNonBlockingTypes()).Empty());
 }
 
-void ModelTypeRegistry::InitializeNonBlockingType(syncer::ModelType type) {
+void ModelTypeRegistry::InitializeNonBlockingType(
+    ModelType type,
+    scoped_refptr<base::SequencedTaskRunner> type_task_runner,
+    base::WeakPtr<NonBlockingTypeProcessor> processor) {
   DVLOG(1) << "Enabling an off-thread sync type: " << ModelTypeToString(type);
 
+  // Initialize CoreProcessor -> Processor communication channel.
   scoped_ptr<NonBlockingTypeProcessorCore> core(
-      new NonBlockingTypeProcessorCore(type));
+      new NonBlockingTypeProcessorCore(type, type_task_runner, processor));
+
+  // Initialize Processor -> CoreProcessor communication channel.
+  type_task_runner->PostTask(
+      FROM_HERE,
+      base::Bind(&NonBlockingTypeProcessor::OnConnect,
+                 processor->AsWeakPtr(),
+                 core->AsWeakPtr(),
+                 scoped_refptr<base::SequencedTaskRunner>(
+                     base::MessageLoopProxy::current())));
 
   DCHECK(update_handler_map_.find(type) == update_handler_map_.end());
   DCHECK(commit_contributor_map_.find(type) == commit_contributor_map_.end());
@@ -83,6 +103,9 @@
 
   // The container takes ownership.
   non_blocking_type_processor_cores_.push_back(core.release());
+
+  DCHECK(Intersection(GetEnabledDirectoryTypes(),
+                      GetEnabledNonBlockingTypes()).Empty());
 }
 
 void ModelTypeRegistry::RemoveNonBlockingType(ModelType type) {
diff --git a/sync/sessions/model_type_registry.h b/sync/sessions/model_type_registry.h
index 65445d4..1317a6a 100644
--- a/sync/sessions/model_type_registry.h
+++ b/sync/sessions/model_type_registry.h
@@ -24,6 +24,7 @@
 class DirectoryCommitContributor;
 class DirectoryUpdateHandler;
 class NonBlockingTypeProcessorCore;
+class NonBlockingTypeProcessor;
 class UpdateHandler;
 
 typedef std::map<ModelType, UpdateHandler*> UpdateHandlerMap;
@@ -32,6 +33,11 @@
 // Keeps track of the sets of active update handlers and commit contributors.
 class SYNC_EXPORT_PRIVATE ModelTypeRegistry {
  public:
+  // This alternative constructor does not support any directory types.
+  // It is used only in tests.
+  ModelTypeRegistry();
+
+  // Constructs a ModelTypeRegistry that supports directory types.
   ModelTypeRegistry(
       const std::vector<scoped_refptr<ModelSafeWorker> >& workers,
       syncable::Directory* directory);
@@ -40,10 +46,14 @@
   // Sets the set of enabled types.
   void SetEnabledDirectoryTypes(const ModelSafeRoutingInfo& routing_info);
 
-  // Enables an off-thread type for syncing.
+  // Enables an off-thread type for syncing.  Connects the given processor
+  // and its task_runner to the newly created processor core.
   //
-  // Expects that the type is not currently enabled.
-  void InitializeNonBlockingType(syncer::ModelType type);
+  // Expects that the processor's ModelType is not currently enabled.
+  void InitializeNonBlockingType(
+      syncer::ModelType type,
+      scoped_refptr<base::SequencedTaskRunner> type_task_runner,
+      base::WeakPtr<NonBlockingTypeProcessor> processor);
 
   // Disables the syncing of an off-thread type.
   //
diff --git a/sync/sessions/model_type_registry_unittest.cc b/sync/sessions/model_type_registry_unittest.cc
index 7f174e5..0248e8d 100644
--- a/sync/sessions/model_type_registry_unittest.cc
+++ b/sync/sessions/model_type_registry_unittest.cc
@@ -4,9 +4,10 @@
 
 #include <vector>
 
+#include "base/deferred_sequenced_task_runner.h"
 #include "base/message_loop/message_loop.h"
-#include "sync/engine/non_blocking_type_processor_core.h"
 #include "sync/internal_api/public/base/model_type.h"
+#include "sync/internal_api/public/non_blocking_type_processor.h"
 #include "sync/sessions/model_type_registry.h"
 #include "sync/test/engine/fake_model_worker.h"
 #include "sync/test/engine/test_directory_setter_upper.h"
@@ -113,13 +114,24 @@
 }
 
 TEST_F(ModelTypeRegistryTest, NonBlockingTypes) {
+  NonBlockingTypeProcessor themes_processor(syncer::THEMES);
+  NonBlockingTypeProcessor sessions_processor(syncer::SESSIONS);
+  scoped_refptr<base::DeferredSequencedTaskRunner> task_runner =
+      new base::DeferredSequencedTaskRunner(base::MessageLoopProxy::current());
+
   EXPECT_TRUE(registry()->GetEnabledTypes().Empty());
 
-  registry()->InitializeNonBlockingType(syncer::THEMES);
+  registry()->InitializeNonBlockingType(
+      syncer::THEMES,
+      task_runner,
+      themes_processor.AsWeakPtr());
   EXPECT_TRUE(registry()->GetEnabledTypes().Equals(
       ModelTypeSet(syncer::THEMES)));
 
-  registry()->InitializeNonBlockingType(syncer::SESSIONS);
+  registry()->InitializeNonBlockingType(
+      syncer::SESSIONS,
+      task_runner,
+      sessions_processor.AsWeakPtr());
   EXPECT_TRUE(registry()->GetEnabledTypes().Equals(
       ModelTypeSet(syncer::THEMES, syncer::SESSIONS)));
 
@@ -132,6 +144,11 @@
 }
 
 TEST_F(ModelTypeRegistryTest, NonBlockingTypesWithDirectoryTypes) {
+  NonBlockingTypeProcessor themes_processor(syncer::THEMES);
+  NonBlockingTypeProcessor sessions_processor(syncer::SESSIONS);
+  scoped_refptr<base::DeferredSequencedTaskRunner> task_runner =
+      new base::DeferredSequencedTaskRunner(base::MessageLoopProxy::current());
+
   ModelSafeRoutingInfo routing_info1;
   routing_info1.insert(std::make_pair(NIGORI, GROUP_PASSIVE));
   routing_info1.insert(std::make_pair(BOOKMARKS, GROUP_UI));
@@ -141,7 +158,10 @@
   EXPECT_TRUE(registry()->GetEnabledTypes().Empty());
 
   // Add the themes non-blocking type.
-  registry()->InitializeNonBlockingType(syncer::THEMES);
+  registry()->InitializeNonBlockingType(
+      syncer::THEMES,
+      task_runner,
+      themes_processor.AsWeakPtr());
   current_types.Put(syncer::THEMES);
   EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types));
 
@@ -151,7 +171,10 @@
   EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types));
 
   // Add sessions non-blocking type.
-  registry()->InitializeNonBlockingType(syncer::SESSIONS);
+  registry()->InitializeNonBlockingType(
+      syncer::SESSIONS,
+      task_runner,
+      sessions_processor.AsWeakPtr());
   current_types.Put(syncer::SESSIONS);
   EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types));
 
@@ -167,4 +190,36 @@
   EXPECT_TRUE(registry()->GetEnabledTypes().Equals(current_types));
 }
 
+TEST_F(ModelTypeRegistryTest, DeletionOrdering) {
+  scoped_ptr<NonBlockingTypeProcessor> themes_processor(
+      new NonBlockingTypeProcessor(syncer::THEMES));
+  scoped_ptr<NonBlockingTypeProcessor> sessions_processor(
+      new NonBlockingTypeProcessor(syncer::SESSIONS));
+  scoped_refptr<base::DeferredSequencedTaskRunner> task_runner =
+      new base::DeferredSequencedTaskRunner(base::MessageLoopProxy::current());
+
+  EXPECT_TRUE(registry()->GetEnabledTypes().Empty());
+
+  registry()->InitializeNonBlockingType(
+      syncer::THEMES,
+      task_runner,
+      themes_processor->AsWeakPtr());
+  registry()->InitializeNonBlockingType(
+      syncer::SESSIONS,
+      task_runner,
+      sessions_processor->AsWeakPtr());
+  EXPECT_TRUE(registry()->GetEnabledTypes().Equals(
+      ModelTypeSet(syncer::THEMES, syncer::SESSIONS)));
+
+  // Tear down themes processing, starting with the ProcessorCore.
+  registry()->RemoveNonBlockingType(syncer::THEMES);
+  themes_processor.reset();
+
+  // Tear down sessions processing, starting with the Processor.
+  sessions_processor.reset();
+  registry()->RemoveNonBlockingType(syncer::SESSIONS);
+
+  EXPECT_TRUE(registry()->GetEnabledTypes().Empty());
+}
+
 }  // namespace syncer
diff --git a/sync/sessions/sync_session.cc b/sync/sessions/sync_session.cc
index 957cfbf..e352e70 100644
--- a/sync/sessions/sync_session.cc
+++ b/sync/sessions/sync_session.cc
@@ -89,5 +89,11 @@
                     OnSyncCycleEvent(event));
 }
 
+void SyncSession::SendProtocolEvent(const ProtocolEvent& event) {
+  FOR_EACH_OBSERVER(SyncEngineEventListener,
+                    *(context_->listeners()),
+                    OnProtocolEvent(event));
+}
+
 }  // namespace sessions
 }  // namespace syncer
diff --git a/sync/sessions/sync_session.h b/sync/sessions/sync_session.h
index 2a96fbc..d61a792 100644
--- a/sync/sessions/sync_session.h
+++ b/sync/sessions/sync_session.h
@@ -30,6 +30,7 @@
 
 namespace syncer {
 class ModelSafeWorker;
+class ProtocolEvent;
 
 namespace sessions {
 
@@ -110,6 +111,8 @@
       sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source);
   void SendEventNotification(SyncCycleEvent::EventCause cause);
 
+  void SendProtocolEvent(const ProtocolEvent& event);
+
   // TODO(akalin): Split this into context() and mutable_context().
   SyncSessionContext* context() const { return context_; }
   Delegate* delegate() const { return delegate_; }
diff --git a/sync/sync_internal_api.gypi b/sync/sync_internal_api.gypi
index 77416eb..20ac6a5 100644
--- a/sync/sync_internal_api.gypi
+++ b/sync/sync_internal_api.gypi
@@ -25,17 +25,11 @@
     'internal_api/debug_info_event_listener.h',
     'internal_api/delete_journal.cc',
     'internal_api/events/commit_request_event.cc',
-    'internal_api/events/commit_request_event.h',
     'internal_api/events/commit_response_event.cc',
-    'internal_api/events/commit_response_event.h',
     'internal_api/events/configure_get_updates_request_event.cc',
-    'internal_api/events/configure_get_updates_request_event.h',
     'internal_api/events/get_updates_response_event.cc',
-    'internal_api/events/get_updates_response_event.h',
     'internal_api/events/normal_get_updates_request_event.cc',
-    'internal_api/events/normal_get_updates_request_event.h',
     'internal_api/events/poll_get_updates_request_event.cc',
-    'internal_api/events/poll_get_updates_request_event.h',
     'internal_api/events/protocol_event.cc',
     'internal_api/http_bridge.cc',
     'internal_api/http_bridge_network_resources.cc',
@@ -46,6 +40,7 @@
     'internal_api/js_sync_encryption_handler_observer.h',
     'internal_api/js_sync_manager_observer.cc',
     'internal_api/js_sync_manager_observer.h',
+    'internal_api/non_blocking_type_processor.cc',
     'internal_api/public/base/ack_handle.cc',
     'internal_api/public/base/ack_handle.h',
     'internal_api/public/base/cancelation_observer.cc',
@@ -81,6 +76,12 @@
     'internal_api/public/engine/polling_constants.h',
     'internal_api/public/engine/sync_status.cc',
     'internal_api/public/engine/sync_status.h',
+    'internal_api/public/events/commit_request_event.h',
+    'internal_api/public/events/commit_response_event.h',
+    'internal_api/public/events/configure_get_updates_request_event.h',
+    'internal_api/public/events/get_updates_response_event.h',
+    'internal_api/public/events/normal_get_updates_request_event.h',
+    'internal_api/public/events/poll_get_updates_request_event.h',
     'internal_api/public/events/protocol_event.h',
     'internal_api/public/http_bridge.h',
     'internal_api/public/http_bridge_network_resources.h',
@@ -89,12 +90,14 @@
     'internal_api/public/internal_components_factory.h',
     'internal_api/public/internal_components_factory_impl.h',
     'internal_api/public/network_resources.h',
+    'internal_api/public/non_blocking_type_processor.h',
     'internal_api/public/read_node.h',
     'internal_api/public/read_transaction.h',
     'internal_api/public/sessions/model_neutral_state.cc',
     'internal_api/public/sessions/model_neutral_state.h',
     'internal_api/public/sessions/sync_session_snapshot.cc',
     'internal_api/public/sessions/sync_session_snapshot.h',
+    'internal_api/public/sync_core_proxy.h',
     'internal_api/public/sync_encryption_handler.cc',
     'internal_api/public/sync_encryption_handler.h',
     'internal_api/public/sync_manager.cc',
@@ -117,6 +120,9 @@
     'internal_api/public/write_transaction.h',
     'internal_api/read_node.cc',
     'internal_api/read_transaction.cc',
+    'internal_api/sync_core.cc',
+    'internal_api/sync_core.h',
+    'internal_api/sync_core_proxy.cc',
     'internal_api/sync_encryption_handler_impl.cc',
     'internal_api/sync_encryption_handler_impl.h',
     'internal_api/sync_manager_factory.cc',
diff --git a/sync/sync_tests.gypi b/sync/sync_tests.gypi
index 7c89c99..a8ac4a0 100644
--- a/sync/sync_tests.gypi
+++ b/sync/sync_tests.gypi
@@ -419,9 +419,10 @@
           'internal_api/js_sync_manager_observer_unittest.cc',
           'internal_api/public/change_record_unittest.cc',
           'internal_api/public/sessions/sync_session_snapshot_unittest.cc',
-          'internal_api/syncapi_server_connection_manager_unittest.cc',
+          'internal_api/sync_core_proxy_unittest.cc',
           'internal_api/sync_encryption_handler_impl_unittest.cc',
           'internal_api/sync_manager_impl_unittest.cc',
+          'internal_api/syncapi_server_connection_manager_unittest.cc',
         ],
         'conditions': [
           ['OS == "ios"', {
diff --git a/sync/test/engine/mock_update_handler.cc b/sync/test/engine/mock_update_handler.cc
index 41c6d29..098086e 100644
--- a/sync/test/engine/mock_update_handler.cc
+++ b/sync/test/engine/mock_update_handler.cc
@@ -8,7 +8,9 @@
 
 namespace syncer {
 
-MockUpdateHandler::MockUpdateHandler(ModelType type) {
+MockUpdateHandler::MockUpdateHandler(ModelType type)
+    : apply_updates_count_(0),
+      passive_apply_updates_count_(0) {
   progress_marker_.set_data_type_id(GetSpecificsFieldNumberFromModelType(type));
   const std::string& token_str =
       std::string("Mock token: ") + std::string(ModelTypeToString(type));
@@ -29,9 +31,21 @@
   progress_marker_.CopyFrom(progress_marker);
 }
 
-void MockUpdateHandler::ApplyUpdates(sessions::StatusController* status) {}
+void MockUpdateHandler::ApplyUpdates(sessions::StatusController* status) {
+  apply_updates_count_++;
+}
 
 void MockUpdateHandler::PassiveApplyUpdates(
-    sessions::StatusController* status) {}
+    sessions::StatusController* status) {
+  passive_apply_updates_count_++;
+}
+
+int MockUpdateHandler::GetApplyUpdatesCount() {
+  return apply_updates_count_;
+}
+
+int MockUpdateHandler::GetPassiveApplyUpdatesCount() {
+  return passive_apply_updates_count_;
+}
 
 }  // namespace syncer
diff --git a/sync/test/engine/mock_update_handler.h b/sync/test/engine/mock_update_handler.h
index 7ee0c37..8d11f96 100644
--- a/sync/test/engine/mock_update_handler.h
+++ b/sync/test/engine/mock_update_handler.h
@@ -27,8 +27,17 @@
   virtual void ApplyUpdates(sessions::StatusController* status) OVERRIDE;
   virtual void PassiveApplyUpdates(sessions::StatusController* status) OVERRIDE;
 
+  // Returns the number of times ApplyUpdates() was invoked.
+  int GetApplyUpdatesCount();
+
+  // Returns the number of times PassiveApplyUpdates() was invoked.
+  int GetPassiveApplyUpdatesCount();
+
  private:
   sync_pb::DataTypeProgressMarker progress_marker_;
+
+  int apply_updates_count_;
+  int passive_apply_updates_count_;
 };
 
 }  // namespace syncer
diff --git a/testing/gtest_prod.target.darwin-arm.mk b/testing/gtest_prod.target.darwin-arm.mk
index 9f2f96e..73810d5 100644
--- a/testing/gtest_prod.target.darwin-arm.mk
+++ b/testing/gtest_prod.target.darwin-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/testing/gtest_prod.target.darwin-mips.mk b/testing/gtest_prod.target.darwin-mips.mk
index 5d4314e..7638328 100644
--- a/testing/gtest_prod.target.darwin-mips.mk
+++ b/testing/gtest_prod.target.darwin-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/testing/gtest_prod.target.darwin-x86.mk b/testing/gtest_prod.target.darwin-x86.mk
index f2ad3fe..b150e48 100644
--- a/testing/gtest_prod.target.darwin-x86.mk
+++ b/testing/gtest_prod.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/testing/gtest_prod.target.darwin-x86_64.mk b/testing/gtest_prod.target.darwin-x86_64.mk
new file mode 100644
index 0000000..f1aa1d6
--- /dev/null
+++ b/testing/gtest_prod.target.darwin-x86_64.mk
@@ -0,0 +1,219 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := testing_gtest_prod_gyp
+LOCAL_MODULE_STEM := gtest_prod
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: testing_gtest_prod_gyp
+
+# Alias gyp target name.
+.PHONY: gtest_prod
+gtest_prod: testing_gtest_prod_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/testing/gtest_prod.target.linux-arm.mk b/testing/gtest_prod.target.linux-arm.mk
index 9f2f96e..73810d5 100644
--- a/testing/gtest_prod.target.linux-arm.mk
+++ b/testing/gtest_prod.target.linux-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/testing/gtest_prod.target.linux-mips.mk b/testing/gtest_prod.target.linux-mips.mk
index 5d4314e..7638328 100644
--- a/testing/gtest_prod.target.linux-mips.mk
+++ b/testing/gtest_prod.target.linux-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/testing/gtest_prod.target.linux-x86.mk b/testing/gtest_prod.target.linux-x86.mk
index f2ad3fe..b150e48 100644
--- a/testing/gtest_prod.target.linux-x86.mk
+++ b/testing/gtest_prod.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/testing/gtest_prod.target.linux-x86_64.mk b/testing/gtest_prod.target.linux-x86_64.mk
new file mode 100644
index 0000000..f1aa1d6
--- /dev/null
+++ b/testing/gtest_prod.target.linux-x86_64.mk
@@ -0,0 +1,219 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := testing_gtest_prod_gyp
+LOCAL_MODULE_STEM := gtest_prod
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: testing_gtest_prod_gyp
+
+# Alias gyp target name.
+.PHONY: gtest_prod
+gtest_prod: testing_gtest_prod_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/ashmem/ashmem.target.darwin-x86_64.mk b/third_party/ashmem/ashmem.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a8be569
--- /dev/null
+++ b/third_party/ashmem/ashmem.target.darwin-x86_64.mk
@@ -0,0 +1,50 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_ashmem_ashmem_gyp
+LOCAL_MODULE_STEM := ashmem
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_ashmem_shim_headers":
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: $(LOCAL_PATH)/tools/generate_shim_headers/generate_shim_headers.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating ashmem shim headers ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/ashmem; mkdir -p $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem; python ../../tools/generate_shim_headers/generate_shim_headers.py --headers-root . --output-directory "$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target" --prefix cutils/ ashmem.h --generate
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_ashmem_ashmem_gyp
+
+# Alias gyp target name.
+.PHONY: ashmem
+ashmem: third_party_ashmem_ashmem_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/ashmem/ashmem.target.linux-x86_64.mk b/third_party/ashmem/ashmem.target.linux-x86_64.mk
new file mode 100644
index 0000000..a8be569
--- /dev/null
+++ b/third_party/ashmem/ashmem.target.linux-x86_64.mk
@@ -0,0 +1,50 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_ashmem_ashmem_gyp
+LOCAL_MODULE_STEM := ashmem
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_ashmem_shim_headers":
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h: $(LOCAL_PATH)/tools/generate_shim_headers/generate_shim_headers.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating ashmem shim headers ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/ashmem; mkdir -p $(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem; python ../../tools/generate_shim_headers/generate_shim_headers.py --headers-root . --output-directory "$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target" --prefix cutils/ ashmem.h --generate
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target/third_party/ashmem/ashmem.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_ashmem_ashmem_gyp
+
+# Alias gyp target name.
+.PHONY: ashmem
+ashmem: third_party_ashmem_ashmem_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/binutils/.gitignore b/third_party/binutils/.gitignore
new file mode 100644
index 0000000..4dfd3b6
--- /dev/null
+++ b/third_party/binutils/.gitignore
@@ -0,0 +1,3 @@
+binutils-*
+*-chroot-*
+output-*
diff --git a/third_party/binutils/LICENSE b/third_party/binutils/LICENSE
new file mode 100644
index 0000000..4a1bd6f
--- /dev/null
+++ b/third_party/binutils/LICENSE
@@ -0,0 +1,340 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year  name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/third_party/binutils/OWNERS b/third_party/binutils/OWNERS
new file mode 100644
index 0000000..41edd86
--- /dev/null
+++ b/third_party/binutils/OWNERS
@@ -0,0 +1,3 @@
+thakis@chromium.org
+thestig@chromium.org
+mithro@mithis.com
diff --git a/third_party/binutils/README.chromium b/third_party/binutils/README.chromium
new file mode 100644
index 0000000..b681b07
--- /dev/null
+++ b/third_party/binutils/README.chromium
@@ -0,0 +1,22 @@
+Name: binutils
+URL: http://www.gnu.org/software/binutils/
+Version: 2.24
+License: GPL v2
+License File: NOT_SHIPPED
+Security Critical: no
+
+Description:
+This directory contains i386 and amd64 binaries of the binutils tools
+(including gold linker).
+
+They were built from binutils-2.24 using the "build-all.sh" script on a Ubuntu
+Precise.
+
+The script creates chroots for 32bit and 64bit Ubuntu Lucid and then builds
+binutils inside the roots.
+
+Local patches:
+ * ehframe.patch for http://crbug.com/161942
+
+ * (build-all.sh|build-one.sh|upload.sh) scripts for building the binutils
+   binaries and uploading them to Google storage.
diff --git a/third_party/binutils/build-all.sh b/third_party/binutils/build-all.sh
new file mode 100755
index 0000000..fe49e6d
--- /dev/null
+++ b/third_party/binutils/build-all.sh
@@ -0,0 +1,117 @@
+#!/bin/sh
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to build binutils for both i386 and AMD64 Linux architectures.
+# Must be run on an AMD64 supporting machine which has debootstrap and sudo
+# installed.
+# Uses Ubuntu Lucid chroots as build environment.
+
+set -e
+
+if [ x"$(whoami)" = x"root" ]; then
+  echo "Script must not be run as root."
+  exit 1
+fi
+sudo -v
+
+OUTPUTDIR="${1:-$PWD/output-$(date +%Y%m%d-%H%M%S)}"
+if [ ! -d "$OUTPUTDIR" ]; then
+  mkdir -p "$OUTPUTDIR"
+fi
+
+# Download the source
+VERSION=2.24
+wget -c http://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.bz2
+
+# Verify the signature
+wget -c -q http://ftp.gnu.org/gnu/binutils/binutils-$VERSION.tar.bz2.sig
+if ! gpg --verify binutils-$VERSION.tar.bz2.sig; then
+  echo "GPG Signature failed to verify."
+  echo ""
+  echo "You may need to import the vendor GPG key with:"
+  echo "# gpg --keyserver pgp.mit.edu --recv-key 4AE55E93"
+  exit 1
+fi
+
+
+if [ ! -d binutils-$VERSION ]; then
+  # Extract the source
+  tar jxf binutils-$VERSION.tar.bz2
+
+  # Patch the source
+  (
+    cd binutils-$VERSION
+    patch -p1 < ../ehframe.patch
+  )
+fi
+
+for ARCH in i386 amd64; do
+  if [ ! -d lucid-chroot-$ARCH ]; then
+    # Refresh sudo credentials
+    sudo -v
+
+    # Create the chroot
+    echo ""
+    echo "Building chroot for $ARCH"
+    echo "============================="
+    sudo debootstrap \
+        --arch=$ARCH \
+        --include=build-essential,flex,bison \
+        lucid lucid-chroot-$ARCH
+    echo "============================="
+  fi
+
+  BUILDDIR=lucid-chroot-$ARCH/build
+
+  # Clean up any previous failed build attempts inside chroot
+  if [ -d "$BUILDDIR" ]; then
+    sudo rm -rf "$BUILDDIR"
+  fi
+
+  # Copy data into the chroot
+  sudo mkdir -p "$BUILDDIR"
+  sudo cp -a binutils-$VERSION "$BUILDDIR"
+  sudo cp -a build-one.sh "$BUILDDIR"
+
+  # Do the build
+  PREFIX=
+  case $ARCH in
+   i386)
+     PREFIX="setarch linux32"
+     ARCHNAME=i686-pc-linux-gnu
+   ;;
+   amd64)
+     PREFIX="setarch linux64"
+     ARCHNAME=x86_64-unknown-linux-gnu
+   ;;
+  esac
+  echo ""
+  echo "Building binutils for $ARCH"
+  LOGFILE="$OUTPUTDIR/build-$ARCH.log"
+  if ! sudo $PREFIX chroot lucid-chroot-$ARCH /build/build-one.sh /build/binutils-$VERSION > $LOGFILE 2>&1; then
+    echo "Build failed! See $LOGFILE for details."
+    exit 1
+  fi
+
+  # Copy data out of the chroot
+  sudo chown -R $(whoami) "$BUILDDIR/output/"
+
+  # Strip the output binaries
+  for i in "$BUILDDIR/output/$ARCHNAME/bin/*"; do
+     strip $i
+  done
+
+  # Copy them out of the chroot
+  cp -a "$BUILDDIR/output/$ARCHNAME" "$OUTPUTDIR"
+
+  # Clean up chroot
+  sudo rm -rf "$BUILDDIR"
+done
+
+echo "Check you are happy with the binaries in"
+echo "  $OUTPUTDIR"
+echo "Then"
+echo " * upload to Google Storage using the upload.sh script"
+echo " * roll dependencies"
diff --git a/third_party/binutils/build-one.sh b/third_party/binutils/build-one.sh
new file mode 100755
index 0000000..191a88d
--- /dev/null
+++ b/third_party/binutils/build-one.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Script to build binutils found in /build/binutils-XXXX when inside a chroot.
+# Don't call this script yourself, instead use the build-all.sh script.
+
+set -e
+
+if [ -z "$1" ]; then
+ echo "Directory of binutils not given."
+ exit 1
+fi
+
+cd "$1"
+./configure --enable-gold=default --enable-threads --prefix=/build/output
+make -j8 all
+make install
diff --git a/third_party/binutils/ehframe.patch b/third_party/binutils/ehframe.patch
new file mode 100644
index 0000000..428a623
--- /dev/null
+++ b/third_party/binutils/ehframe.patch
@@ -0,0 +1,49 @@
+diff --git a/gold/ehframe.cc b/gold/ehframe.cc
+index 08a9ec6..be262bf 100644
+--- a/gold/ehframe.cc
++++ b/gold/ehframe.cc
+@@ -84,7 +84,8 @@ Eh_frame_hdr::Eh_frame_hdr(Output_section* eh_frame_section,
+     eh_frame_section_(eh_frame_section),
+     eh_frame_data_(eh_frame_data),
+     fde_offsets_(),
+-    any_unrecognized_eh_frame_sections_(false)
++    any_unrecognized_eh_frame_sections_(false),
++    lock_(NULL)
+ {
+ }
+ 
+@@ -102,6 +103,9 @@ Eh_frame_hdr::set_final_data_size()
+       this->fde_offsets_.reserve(fde_count);
+     }
+   this->set_data_size(data_size);
++  // We need a lock for updating the fde_offsets_ vector while writing
++  // the FDEs.
++  this->lock_ = new Lock();
+ }
+ 
+ // Write the data to the file.
+diff --git a/gold/ehframe.h b/gold/ehframe.h
+index 8aab8b8..d5ac668 100644
+--- a/gold/ehframe.h
++++ b/gold/ehframe.h
+@@ -60,7 +60,10 @@ class Eh_frame_hdr : public Output_section_data
+   record_fde(section_offset_type fde_offset, unsigned char fde_encoding)
+   {
+     if (!this->any_unrecognized_eh_frame_sections_)
+-      this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
++      {
++	Hold_lock(*this->lock_);
++	this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
++      }
+   }
+ 
+  protected:
+@@ -157,6 +160,8 @@ class Eh_frame_hdr : public Output_section_data
+   // Whether we found any .eh_frame sections which we could not
+   // process.
+   bool any_unrecognized_eh_frame_sections_;
++  // Lock held while updating fde_offsets_.
++  Lock* lock_;
+ };
+ 
+ // This class holds an FDE.
diff --git a/third_party/binutils/linux/.keepme b/third_party/binutils/linux/.keepme
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/binutils/linux/.keepme
diff --git a/third_party/binutils/upload.sh b/third_party/binutils/upload.sh
new file mode 100755
index 0000000..27c11ce
--- /dev/null
+++ b/third_party/binutils/upload.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Upload the generated output to Google storage.
+
+if [ ! -d $1 ]; then
+  echo "update.sh <output directory from build-all.sh>"
+  exit 1
+fi
+
+if [ ! -f ~/.boto ]; then
+  echo "You need to run 'gsutil config' to set up authentication before running this script."
+  exit 1
+fi
+
+BINUTILS_TAR_BZ2=linux/binutils.tar.bz2
+if [ -f ${BINUTILS_TAR_BZ2}.sha1 ]; then
+  echo "Please remove ${BINUTILS_TAR_BZ2}.sha1 before starting..."
+  exit 1
+fi
+
+(cd $1/; tar -jcvf ../$BINUTILS_TAR_BZ2 .)
+../depot_tools/upload_to_google_storage.py --bucket chromium-binutils $BINUTILS_TAR_BZ2
diff --git a/third_party/brotli/brotli.target.darwin-arm.mk b/third_party/brotli/brotli.target.darwin-arm.mk
index 042bc07..3cc514e 100644
--- a/third_party/brotli/brotli.target.darwin-arm.mk
+++ b/third_party/brotli/brotli.target.darwin-arm.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/brotli/brotli.target.darwin-mips.mk b/third_party/brotli/brotli.target.darwin-mips.mk
index b37330f..e6e31f4 100644
--- a/third_party/brotli/brotli.target.darwin-mips.mk
+++ b/third_party/brotli/brotli.target.darwin-mips.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/brotli/brotli.target.darwin-x86.mk b/third_party/brotli/brotli.target.darwin-x86.mk
index 8efa21d..034dd17 100644
--- a/third_party/brotli/brotli.target.darwin-x86.mk
+++ b/third_party/brotli/brotli.target.darwin-x86.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/brotli/brotli.target.darwin-x86_64.mk b/third_party/brotli/brotli.target.darwin-x86_64.mk
new file mode 100644
index 0000000..b533ece
--- /dev/null
+++ b/third_party/brotli/brotli.target.darwin-x86_64.mk
@@ -0,0 +1,263 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_brotli_brotli_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/brotli/src/brotli/dec/bit_reader.c \
+	third_party/brotli/src/brotli/dec/decode.c \
+	third_party/brotli/src/brotli/dec/huffman.c \
+	third_party/brotli/src/brotli/dec/safe_malloc.c \
+	third_party/brotli/src/brotli/dec/streams.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/brotli/src/brotli/dec \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/brotli/src/brotli/dec \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_brotli_brotli_gyp
+
+# Alias gyp target name.
+.PHONY: brotli
+brotli: third_party_brotli_brotli_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/brotli/brotli.target.linux-arm.mk b/third_party/brotli/brotli.target.linux-arm.mk
index 042bc07..3cc514e 100644
--- a/third_party/brotli/brotli.target.linux-arm.mk
+++ b/third_party/brotli/brotli.target.linux-arm.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/brotli/brotli.target.linux-mips.mk b/third_party/brotli/brotli.target.linux-mips.mk
index b37330f..e6e31f4 100644
--- a/third_party/brotli/brotli.target.linux-mips.mk
+++ b/third_party/brotli/brotli.target.linux-mips.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/brotli/brotli.target.linux-x86.mk b/third_party/brotli/brotli.target.linux-x86.mk
index 8efa21d..034dd17 100644
--- a/third_party/brotli/brotli.target.linux-x86.mk
+++ b/third_party/brotli/brotli.target.linux-x86.mk
@@ -85,6 +85,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/brotli/brotli.target.linux-x86_64.mk b/third_party/brotli/brotli.target.linux-x86_64.mk
new file mode 100644
index 0000000..b533ece
--- /dev/null
+++ b/third_party/brotli/brotli.target.linux-x86_64.mk
@@ -0,0 +1,263 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_brotli_brotli_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/brotli/src/brotli/dec/bit_reader.c \
+	third_party/brotli/src/brotli/dec/decode.c \
+	third_party/brotli/src/brotli/dec/huffman.c \
+	third_party/brotli/src/brotli/dec/safe_malloc.c \
+	third_party/brotli/src/brotli/dec/streams.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/brotli/src/brotli/dec \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/brotli/src/brotli/dec \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_brotli_brotli_gyp
+
+# Alias gyp target name.
+.PHONY: brotli
+brotli: third_party_brotli_brotli_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/cld_2/README.chromium b/third_party/cld_2/README.chromium
index b203255..7db3163 100644
--- a/third_party/cld_2/README.chromium
+++ b/third_party/cld_2/README.chromium
@@ -8,3 +8,42 @@
 Description:
 The CLD is used to determine the language of text. In Chromium, this is used
 to determine if Chrome should offer Translate UX to the user.
+
+
+Dynamic Mode
+============
+Prior to CLD2's trunk@155, Chromium has always built CLD2 statically. The data
+needed for CLD2 to perform its language detection has been compiled straight
+into the binary. This contributes around 1.5 megabytes to the size of Chrome
+and embeds one or more large rodata sections to the executable.
+
+Starting with CLD2's trunk@r155, there is a new option available: dynamic mode.
+In dynamic mode, CLD2 is built without its data; only the code is compiled, and
+the data must be supplied at runtime via a file or a pointer to a (presumably
+mmap'ed) read-only region of memory.
+
+Tradeoffs to consider before enabling dynamic mode:
+
+  Pros:
+    * Reduces the size of the Chromium binary by a bit over a megabyte.
+    * As the data file rarely changes, it can be updated independently.
+    * Depending upon the update process on your platform, this may also reduce
+      the size of Chromium updates.
+    * It is possible to run Chromium without CLD2 data at all (language
+      detection will always fail, but fails gracefully).
+    * Different types of CLD2 data files (larger and more accurate or smaller
+      and less accurate) can be dynamically downloaded or chosen depending
+      on runtime choices.
+
+  Cons:
+    * Data files must be generated and checked into source control by hand.
+    * At runtime a data file must be opened and its headers parsed before CLD2
+      can be used in any given process (this time should be negligible in most
+      circumstances). This will prevent language detection from working until
+      a data file has been loaded.
+
+To enable dynamic mode, set 'cld_dynamic' to '1' in ../../build/common.gypi.
+
+For more information on the changes required to use dynamic mode, see:
+  https://codereview.chromium.org/187393005
+
diff --git a/third_party/cld_2/cld_2.gyp b/third_party/cld_2/cld_2.gyp
index 9b7fbdf..377cd96 100644
--- a/third_party/cld_2/cld_2.gyp
+++ b/third_party/cld_2/cld_2.gyp
@@ -17,13 +17,20 @@
 {
   'targets': [
     {
-      'target_name': 'cld_2',
-      'type': 'static_library',
+      'target_name': 'cld_2_dynamic_data_tool',
+      'type': 'executable',
       'include_dirs': [
         'src/internal',
         'src/public',
       ],
       'sources': [
+        'src/internal/cld2_dynamic_data.h',
+        'src/internal/cld2_dynamic_data.cc',
+        'src/internal/cld2_dynamic_data_extractor.h',
+        'src/internal/cld2_dynamic_data_extractor.cc',
+        'src/internal/cld2_dynamic_data_loader.h',
+        'src/internal/cld2_dynamic_data_loader.cc',
+        'src/internal/cld2_dynamic_data_tool.cc',
         'src/internal/cld2_generated_cjk_compatible.cc',
         'src/internal/cld2_generated_deltaoctachrome0122.cc',
         'src/internal/cld2_generated_distinctoctachrome0122.cc',
@@ -96,5 +103,109 @@
         }],
       ],
     },
+    {
+      'target_name': 'cld_2',
+      'type': 'static_library',
+      'include_dirs': [
+        'src/internal',
+        'src/public',
+      ],
+      'sources': [
+        'src/internal/cld2tablesummary.h',
+        'src/internal/cldutil.cc',
+        'src/internal/cldutil.h',
+        'src/internal/cldutil_shared.cc',
+        'src/internal/cldutil_shared.h',
+        'src/internal/compact_lang_det.cc',
+        'src/internal/compact_lang_det_hint_code.cc',
+        'src/internal/compact_lang_det_hint_code.h',
+        'src/internal/compact_lang_det_impl.cc',
+        'src/internal/compact_lang_det_impl.h',
+        'src/internal/debug.h',
+        'src/internal/debug_empty.cc',
+        'src/internal/fixunicodevalue.cc',
+        'src/internal/fixunicodevalue.h',
+        'src/internal/generated_distinct_bi_0.cc',
+        'src/internal/generated_entities.cc',
+        'src/internal/generated_language.cc',
+        'src/internal/generated_language.h',
+        'src/internal/generated_ulscript.cc',
+        'src/internal/generated_ulscript.h',
+        'src/internal/getonescriptspan.cc',
+        'src/internal/getonescriptspan.h',
+        'src/internal/integral_types.h',
+        'src/internal/lang_script.cc',
+        'src/internal/lang_script.h',
+        'src/internal/langspan.h',
+        'src/internal/offsetmap.cc',
+        'src/internal/offsetmap.h',
+        'src/internal/port.h',
+        'src/internal/scoreonescriptspan.cc',
+        'src/internal/scoreonescriptspan.h',
+        'src/internal/stringpiece.h',
+        'src/internal/tote.cc',
+        'src/internal/tote.h',
+        'src/internal/utf8prop_lettermarkscriptnum.h',
+        'src/internal/utf8repl_lettermarklower.h',
+        'src/internal/utf8scannot_lettermarkspecial.h',
+        'src/internal/utf8statetable.cc',
+        'src/internal/utf8statetable.h',
+        'src/public/compact_lang_det.h',
+        'src/public/encodings.h',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'msvs_disabled_warnings': [4267],
+        }],
+        # Dynamic or vanilla mode
+        ['cld2_dynamic==1',
+          {
+            # Enable dynamic mode, which allows CLD to read its data from a file
+            # instead of requiring the data to be linked into the library.
+            # You must generate the data file and check it in using the
+            # cld2_dynamic_data_tool.
+            # build/common.gypi takes care of setting -D CLD2_MODE_DYNAMIC
+            'sources+': [
+              'src/internal/cld2_dynamic_data.h',
+              'src/internal/cld2_dynamic_data.cc',
+              'src/internal/cld2_dynamic_data_loader.h',
+              'src/internal/cld2_dynamic_data_loader.cc',
+            ],
+          },
+          {
+            # Else it's regular mode, so link in all the data blobs directly.
+            'sources+': [
+              'src/internal/cld2_generated_cjk_compatible.cc',
+              'src/internal/cld2_generated_deltaoctachrome0122.cc',
+              'src/internal/cld2_generated_distinctoctachrome0122.cc',
+              'src/internal/cld_generated_cjk_delta_bi_4.cc',
+              'src/internal/cld_generated_cjk_uni_prop_80.cc',
+              'src/internal/cld_generated_score_quad_octa_0122_2.cc',
+              'src/internal/generated_distinct_bi_0.cc',
+            ],
+            'conditions': [
+              ['cld2_table_size==0', {
+                # Small table sizes
+                'sources+': [
+                  'src/internal/cld2_generated_quadchrome0122_16.cc',
+                 ],
+              }],
+              ['cld2_table_size==1', {
+                # Medium table sizes
+                'sources+': [
+                  'src/internal/cld2_generated_quadchrome0122_19.cc',
+                 ],
+              }],
+              ['cld2_table_size==2', {
+                # Large table sizes
+                'sources+': [
+                  'src/internal/cld2_generated_quadchrome0122_2.cc',
+                 ],
+              }],
+            ],
+          },
+        ],
+      ],
+    },
   ],
 }
diff --git a/third_party/d3/OWNERS b/third_party/d3/OWNERS
new file mode 100644
index 0000000..a7d929a
--- /dev/null
+++ b/third_party/d3/OWNERS
@@ -0,0 +1 @@
+bulach@chromium.org
diff --git a/third_party/d3/README.chromium b/third_party/d3/README.chromium
new file mode 100644
index 0000000..0b36d87
--- /dev/null
+++ b/third_party/d3/README.chromium
@@ -0,0 +1,23 @@
+Name: d3
+Short Name: d3
+URL: https://github.com/mbostock/d3
+Version: 3.4.4
+Date: Mon Mar 24 20:45:44 2014 -0700
+Revision: fa55eead411a3c1b01703cb1ddfd59ccc0b23124
+License: BSD 3-Clause
+License File: src/LICENSE
+Security Critical: No
+License Android Compatible: Yes
+
+Description:
+A JavaScript library for manipulating documents based on data.
+
+IMPORTANT:
+This library is currently used only for internal tools, and has not been
+security reviewed for use in any shipping or web-facing code.
+
+Local Modifications:
+Deleted everything except for:
+* d3.js         the standalone non-minified library
+* LICENSE       the BSD-style 3-Clause license
+* README.md     the readme file from github, for basic information
diff --git a/third_party/d3/src/LICENSE b/third_party/d3/src/LICENSE
new file mode 100644
index 0000000..8301346
--- /dev/null
+++ b/third_party/d3/src/LICENSE
@@ -0,0 +1,26 @@
+Copyright (c) 2010-2014, Michael Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* The name Michael Bostock may not be used to endorse or promote products
+  derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/d3/src/README.md b/third_party/d3/src/README.md
new file mode 100644
index 0000000..eb334e2
--- /dev/null
+++ b/third_party/d3/src/README.md
@@ -0,0 +1,9 @@
+# Data-Driven Documents
+
+<a href="http://d3js.org"><img src="http://d3js.org/logo.svg" align="left" hspace="10" vspace="6"></a>
+
+**D3.js** is a JavaScript library for manipulating documents based on data. **D3** helps you bring data to life using HTML, SVG and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
+
+Want to learn more? [See the wiki.](https://github.com/mbostock/d3/wiki)
+
+For examples, [see the gallery](https://github.com/mbostock/d3/wiki/Gallery) and [mbostock’s bl.ocks](http://bl.ocks.org/mbostock).
diff --git a/third_party/d3/src/d3.js b/third_party/d3/src/d3.js
new file mode 100644
index 0000000..a3e4b95
--- /dev/null
+++ b/third_party/d3/src/d3.js
@@ -0,0 +1,9294 @@
+!function() {
+  var d3 = {
+    version: "3.4.4"
+  };
+  if (!Date.now) Date.now = function() {
+    return +new Date();
+  };
+  var d3_arraySlice = [].slice, d3_array = function(list) {
+    return d3_arraySlice.call(list);
+  };
+  var d3_document = document, d3_documentElement = d3_document.documentElement, d3_window = window;
+  try {
+    d3_array(d3_documentElement.childNodes)[0].nodeType;
+  } catch (e) {
+    d3_array = function(list) {
+      var i = list.length, array = new Array(i);
+      while (i--) array[i] = list[i];
+      return array;
+    };
+  }
+  try {
+    d3_document.createElement("div").style.setProperty("opacity", 0, "");
+  } catch (error) {
+    var d3_element_prototype = d3_window.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = d3_window.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
+    d3_element_prototype.setAttribute = function(name, value) {
+      d3_element_setAttribute.call(this, name, value + "");
+    };
+    d3_element_prototype.setAttributeNS = function(space, local, value) {
+      d3_element_setAttributeNS.call(this, space, local, value + "");
+    };
+    d3_style_prototype.setProperty = function(name, value, priority) {
+      d3_style_setProperty.call(this, name, value + "", priority);
+    };
+  }
+  d3.ascending = d3_ascending;
+  function d3_ascending(a, b) {
+    return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
+  }
+  d3.descending = function(a, b) {
+    return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
+  };
+  d3.min = function(array, f) {
+    var i = -1, n = array.length, a, b;
+    if (arguments.length === 1) {
+      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = array[i]) != null && a > b) a = b;
+    } else {
+      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
+    }
+    return a;
+  };
+  d3.max = function(array, f) {
+    var i = -1, n = array.length, a, b;
+    if (arguments.length === 1) {
+      while (++i < n && !((a = array[i]) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = array[i]) != null && b > a) a = b;
+    } else {
+      while (++i < n && !((a = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
+    }
+    return a;
+  };
+  d3.extent = function(array, f) {
+    var i = -1, n = array.length, a, b, c;
+    if (arguments.length === 1) {
+      while (++i < n && !((a = c = array[i]) != null && a <= a)) a = c = undefined;
+      while (++i < n) if ((b = array[i]) != null) {
+        if (a > b) a = b;
+        if (c < b) c = b;
+      }
+    } else {
+      while (++i < n && !((a = c = f.call(array, array[i], i)) != null && a <= a)) a = undefined;
+      while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
+        if (a > b) a = b;
+        if (c < b) c = b;
+      }
+    }
+    return [ a, c ];
+  };
+  d3.sum = function(array, f) {
+    var s = 0, n = array.length, a, i = -1;
+    if (arguments.length === 1) {
+      while (++i < n) if (!isNaN(a = +array[i])) s += a;
+    } else {
+      while (++i < n) if (!isNaN(a = +f.call(array, array[i], i))) s += a;
+    }
+    return s;
+  };
+  function d3_number(x) {
+    return x != null && !isNaN(x);
+  }
+  d3.mean = function(array, f) {
+    var n = array.length, a, m = 0, i = -1, j = 0;
+    if (arguments.length === 1) {
+      while (++i < n) if (d3_number(a = array[i])) m += (a - m) / ++j;
+    } else {
+      while (++i < n) if (d3_number(a = f.call(array, array[i], i))) m += (a - m) / ++j;
+    }
+    return j ? m : undefined;
+  };
+  d3.quantile = function(values, p) {
+    var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
+    return e ? v + e * (values[h] - v) : v;
+  };
+  d3.median = function(array, f) {
+    if (arguments.length > 1) array = array.map(f);
+    array = array.filter(d3_number);
+    return array.length ? d3.quantile(array.sort(d3_ascending), .5) : undefined;
+  };
+  function d3_bisector(compare) {
+    return {
+      left: function(a, x, lo, hi) {
+        if (arguments.length < 3) lo = 0;
+        if (arguments.length < 4) hi = a.length;
+        while (lo < hi) {
+          var mid = lo + hi >>> 1;
+          if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
+        }
+        return lo;
+      },
+      right: function(a, x, lo, hi) {
+        if (arguments.length < 3) lo = 0;
+        if (arguments.length < 4) hi = a.length;
+        while (lo < hi) {
+          var mid = lo + hi >>> 1;
+          if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
+        }
+        return lo;
+      }
+    };
+  }
+  var d3_bisect = d3_bisector(d3_ascending);
+  d3.bisectLeft = d3_bisect.left;
+  d3.bisect = d3.bisectRight = d3_bisect.right;
+  d3.bisector = function(f) {
+    return d3_bisector(f.length === 1 ? function(d, x) {
+      return d3_ascending(f(d), x);
+    } : f);
+  };
+  d3.shuffle = function(array) {
+    var m = array.length, t, i;
+    while (m) {
+      i = Math.random() * m-- | 0;
+      t = array[m], array[m] = array[i], array[i] = t;
+    }
+    return array;
+  };
+  d3.permute = function(array, indexes) {
+    var i = indexes.length, permutes = new Array(i);
+    while (i--) permutes[i] = array[indexes[i]];
+    return permutes;
+  };
+  d3.pairs = function(array) {
+    var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
+    while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
+    return pairs;
+  };
+  d3.zip = function() {
+    if (!(n = arguments.length)) return [];
+    for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
+      for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
+        zip[j] = arguments[j][i];
+      }
+    }
+    return zips;
+  };
+  function d3_zipLength(d) {
+    return d.length;
+  }
+  d3.transpose = function(matrix) {
+    return d3.zip.apply(d3, matrix);
+  };
+  d3.keys = function(map) {
+    var keys = [];
+    for (var key in map) keys.push(key);
+    return keys;
+  };
+  d3.values = function(map) {
+    var values = [];
+    for (var key in map) values.push(map[key]);
+    return values;
+  };
+  d3.entries = function(map) {
+    var entries = [];
+    for (var key in map) entries.push({
+      key: key,
+      value: map[key]
+    });
+    return entries;
+  };
+  d3.merge = function(arrays) {
+    var n = arrays.length, m, i = -1, j = 0, merged, array;
+    while (++i < n) j += arrays[i].length;
+    merged = new Array(j);
+    while (--n >= 0) {
+      array = arrays[n];
+      m = array.length;
+      while (--m >= 0) {
+        merged[--j] = array[m];
+      }
+    }
+    return merged;
+  };
+  var abs = Math.abs;
+  d3.range = function(start, stop, step) {
+    if (arguments.length < 3) {
+      step = 1;
+      if (arguments.length < 2) {
+        stop = start;
+        start = 0;
+      }
+    }
+    if ((stop - start) / step === Infinity) throw new Error("infinite range");
+    var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
+    start *= k, stop *= k, step *= k;
+    if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
+    return range;
+  };
+  function d3_range_integerScale(x) {
+    var k = 1;
+    while (x * k % 1) k *= 10;
+    return k;
+  }
+  function d3_class(ctor, properties) {
+    try {
+      for (var key in properties) {
+        Object.defineProperty(ctor.prototype, key, {
+          value: properties[key],
+          enumerable: false
+        });
+      }
+    } catch (e) {
+      ctor.prototype = properties;
+    }
+  }
+  d3.map = function(object) {
+    var map = new d3_Map();
+    if (object instanceof d3_Map) object.forEach(function(key, value) {
+      map.set(key, value);
+    }); else for (var key in object) map.set(key, object[key]);
+    return map;
+  };
+  function d3_Map() {}
+  d3_class(d3_Map, {
+    has: d3_map_has,
+    get: function(key) {
+      return this[d3_map_prefix + key];
+    },
+    set: function(key, value) {
+      return this[d3_map_prefix + key] = value;
+    },
+    remove: d3_map_remove,
+    keys: d3_map_keys,
+    values: function() {
+      var values = [];
+      this.forEach(function(key, value) {
+        values.push(value);
+      });
+      return values;
+    },
+    entries: function() {
+      var entries = [];
+      this.forEach(function(key, value) {
+        entries.push({
+          key: key,
+          value: value
+        });
+      });
+      return entries;
+    },
+    size: d3_map_size,
+    empty: d3_map_empty,
+    forEach: function(f) {
+      for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) f.call(this, key.substring(1), this[key]);
+    }
+  });
+  var d3_map_prefix = "\x00", d3_map_prefixCode = d3_map_prefix.charCodeAt(0);
+  function d3_map_has(key) {
+    return d3_map_prefix + key in this;
+  }
+  function d3_map_remove(key) {
+    key = d3_map_prefix + key;
+    return key in this && delete this[key];
+  }
+  function d3_map_keys() {
+    var keys = [];
+    this.forEach(function(key) {
+      keys.push(key);
+    });
+    return keys;
+  }
+  function d3_map_size() {
+    var size = 0;
+    for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) ++size;
+    return size;
+  }
+  function d3_map_empty() {
+    for (var key in this) if (key.charCodeAt(0) === d3_map_prefixCode) return false;
+    return true;
+  }
+  d3.nest = function() {
+    var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
+    function map(mapType, array, depth) {
+      if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
+      var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
+      while (++i < n) {
+        if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
+          values.push(object);
+        } else {
+          valuesByKey.set(keyValue, [ object ]);
+        }
+      }
+      if (mapType) {
+        object = mapType();
+        setter = function(keyValue, values) {
+          object.set(keyValue, map(mapType, values, depth));
+        };
+      } else {
+        object = {};
+        setter = function(keyValue, values) {
+          object[keyValue] = map(mapType, values, depth);
+        };
+      }
+      valuesByKey.forEach(setter);
+      return object;
+    }
+    function entries(map, depth) {
+      if (depth >= keys.length) return map;
+      var array = [], sortKey = sortKeys[depth++];
+      map.forEach(function(key, keyMap) {
+        array.push({
+          key: key,
+          values: entries(keyMap, depth)
+        });
+      });
+      return sortKey ? array.sort(function(a, b) {
+        return sortKey(a.key, b.key);
+      }) : array;
+    }
+    nest.map = function(array, mapType) {
+      return map(mapType, array, 0);
+    };
+    nest.entries = function(array) {
+      return entries(map(d3.map, array, 0), 0);
+    };
+    nest.key = function(d) {
+      keys.push(d);
+      return nest;
+    };
+    nest.sortKeys = function(order) {
+      sortKeys[keys.length - 1] = order;
+      return nest;
+    };
+    nest.sortValues = function(order) {
+      sortValues = order;
+      return nest;
+    };
+    nest.rollup = function(f) {
+      rollup = f;
+      return nest;
+    };
+    return nest;
+  };
+  d3.set = function(array) {
+    var set = new d3_Set();
+    if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
+    return set;
+  };
+  function d3_Set() {}
+  d3_class(d3_Set, {
+    has: d3_map_has,
+    add: function(value) {
+      this[d3_map_prefix + value] = true;
+      return value;
+    },
+    remove: function(value) {
+      value = d3_map_prefix + value;
+      return value in this && delete this[value];
+    },
+    values: d3_map_keys,
+    size: d3_map_size,
+    empty: d3_map_empty,
+    forEach: function(f) {
+      for (var value in this) if (value.charCodeAt(0) === d3_map_prefixCode) f.call(this, value.substring(1));
+    }
+  });
+  d3.behavior = {};
+  d3.rebind = function(target, source) {
+    var i = 1, n = arguments.length, method;
+    while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
+    return target;
+  };
+  function d3_rebind(target, source, method) {
+    return function() {
+      var value = method.apply(source, arguments);
+      return value === source ? target : value;
+    };
+  }
+  function d3_vendorSymbol(object, name) {
+    if (name in object) return name;
+    name = name.charAt(0).toUpperCase() + name.substring(1);
+    for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
+      var prefixName = d3_vendorPrefixes[i] + name;
+      if (prefixName in object) return prefixName;
+    }
+  }
+  var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
+  function d3_noop() {}
+  d3.dispatch = function() {
+    var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
+    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+    return dispatch;
+  };
+  function d3_dispatch() {}
+  d3_dispatch.prototype.on = function(type, listener) {
+    var i = type.indexOf("."), name = "";
+    if (i >= 0) {
+      name = type.substring(i + 1);
+      type = type.substring(0, i);
+    }
+    if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
+    if (arguments.length === 2) {
+      if (listener == null) for (type in this) {
+        if (this.hasOwnProperty(type)) this[type].on(name, null);
+      }
+      return this;
+    }
+  };
+  function d3_dispatch_event(dispatch) {
+    var listeners = [], listenerByName = new d3_Map();
+    function event() {
+      var z = listeners, i = -1, n = z.length, l;
+      while (++i < n) if (l = z[i].on) l.apply(this, arguments);
+      return dispatch;
+    }
+    event.on = function(name, listener) {
+      var l = listenerByName.get(name), i;
+      if (arguments.length < 2) return l && l.on;
+      if (l) {
+        l.on = null;
+        listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
+        listenerByName.remove(name);
+      }
+      if (listener) listeners.push(listenerByName.set(name, {
+        on: listener
+      }));
+      return dispatch;
+    };
+    return event;
+  }
+  d3.event = null;
+  function d3_eventPreventDefault() {
+    d3.event.preventDefault();
+  }
+  function d3_eventSource() {
+    var e = d3.event, s;
+    while (s = e.sourceEvent) e = s;
+    return e;
+  }
+  function d3_eventDispatch(target) {
+    var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
+    while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
+    dispatch.of = function(thiz, argumentz) {
+      return function(e1) {
+        try {
+          var e0 = e1.sourceEvent = d3.event;
+          e1.target = target;
+          d3.event = e1;
+          dispatch[e1.type].apply(thiz, argumentz);
+        } finally {
+          d3.event = e0;
+        }
+      };
+    };
+    return dispatch;
+  }
+  d3.requote = function(s) {
+    return s.replace(d3_requote_re, "\\$&");
+  };
+  var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
+  var d3_subclass = {}.__proto__ ? function(object, prototype) {
+    object.__proto__ = prototype;
+  } : function(object, prototype) {
+    for (var property in prototype) object[property] = prototype[property];
+  };
+  function d3_selection(groups) {
+    d3_subclass(groups, d3_selectionPrototype);
+    return groups;
+  }
+  var d3_select = function(s, n) {
+    return n.querySelector(s);
+  }, d3_selectAll = function(s, n) {
+    return n.querySelectorAll(s);
+  }, d3_selectMatcher = d3_documentElement[d3_vendorSymbol(d3_documentElement, "matchesSelector")], d3_selectMatches = function(n, s) {
+    return d3_selectMatcher.call(n, s);
+  };
+  if (typeof Sizzle === "function") {
+    d3_select = function(s, n) {
+      return Sizzle(s, n)[0] || null;
+    };
+    d3_selectAll = Sizzle;
+    d3_selectMatches = Sizzle.matchesSelector;
+  }
+  d3.selection = function() {
+    return d3_selectionRoot;
+  };
+  var d3_selectionPrototype = d3.selection.prototype = [];
+  d3_selectionPrototype.select = function(selector) {
+    var subgroups = [], subgroup, subnode, group, node;
+    selector = d3_selection_selector(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = (group = this[j]).parentNode;
+      for (var i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          subgroup.push(subnode = selector.call(node, node.__data__, i, j));
+          if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_selector(selector) {
+    return typeof selector === "function" ? selector : function() {
+      return d3_select(selector, this);
+    };
+  }
+  d3_selectionPrototype.selectAll = function(selector) {
+    var subgroups = [], subgroup, node;
+    selector = d3_selection_selectorAll(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
+          subgroup.parentNode = node;
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_selectorAll(selector) {
+    return typeof selector === "function" ? selector : function() {
+      return d3_selectAll(selector, this);
+    };
+  }
+  var d3_nsPrefix = {
+    svg: "http://www.w3.org/2000/svg",
+    xhtml: "http://www.w3.org/1999/xhtml",
+    xlink: "http://www.w3.org/1999/xlink",
+    xml: "http://www.w3.org/XML/1998/namespace",
+    xmlns: "http://www.w3.org/2000/xmlns/"
+  };
+  d3.ns = {
+    prefix: d3_nsPrefix,
+    qualify: function(name) {
+      var i = name.indexOf(":"), prefix = name;
+      if (i >= 0) {
+        prefix = name.substring(0, i);
+        name = name.substring(i + 1);
+      }
+      return d3_nsPrefix.hasOwnProperty(prefix) ? {
+        space: d3_nsPrefix[prefix],
+        local: name
+      } : name;
+    }
+  };
+  d3_selectionPrototype.attr = function(name, value) {
+    if (arguments.length < 2) {
+      if (typeof name === "string") {
+        var node = this.node();
+        name = d3.ns.qualify(name);
+        return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
+      }
+      for (value in name) this.each(d3_selection_attr(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_attr(name, value));
+  };
+  function d3_selection_attr(name, value) {
+    name = d3.ns.qualify(name);
+    function attrNull() {
+      this.removeAttribute(name);
+    }
+    function attrNullNS() {
+      this.removeAttributeNS(name.space, name.local);
+    }
+    function attrConstant() {
+      this.setAttribute(name, value);
+    }
+    function attrConstantNS() {
+      this.setAttributeNS(name.space, name.local, value);
+    }
+    function attrFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
+    }
+    function attrFunctionNS() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
+    }
+    return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
+  }
+  function d3_collapse(s) {
+    return s.trim().replace(/\s+/g, " ");
+  }
+  d3_selectionPrototype.classed = function(name, value) {
+    if (arguments.length < 2) {
+      if (typeof name === "string") {
+        var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
+        if (value = node.classList) {
+          while (++i < n) if (!value.contains(name[i])) return false;
+        } else {
+          value = node.getAttribute("class");
+          while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
+        }
+        return true;
+      }
+      for (value in name) this.each(d3_selection_classed(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_classed(name, value));
+  };
+  function d3_selection_classedRe(name) {
+    return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
+  }
+  function d3_selection_classes(name) {
+    return name.trim().split(/^|\s+/);
+  }
+  function d3_selection_classed(name, value) {
+    name = d3_selection_classes(name).map(d3_selection_classedName);
+    var n = name.length;
+    function classedConstant() {
+      var i = -1;
+      while (++i < n) name[i](this, value);
+    }
+    function classedFunction() {
+      var i = -1, x = value.apply(this, arguments);
+      while (++i < n) name[i](this, x);
+    }
+    return typeof value === "function" ? classedFunction : classedConstant;
+  }
+  function d3_selection_classedName(name) {
+    var re = d3_selection_classedRe(name);
+    return function(node, value) {
+      if (c = node.classList) return value ? c.add(name) : c.remove(name);
+      var c = node.getAttribute("class") || "";
+      if (value) {
+        re.lastIndex = 0;
+        if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
+      } else {
+        node.setAttribute("class", d3_collapse(c.replace(re, " ")));
+      }
+    };
+  }
+  d3_selectionPrototype.style = function(name, value, priority) {
+    var n = arguments.length;
+    if (n < 3) {
+      if (typeof name !== "string") {
+        if (n < 2) value = "";
+        for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
+        return this;
+      }
+      if (n < 2) return d3_window.getComputedStyle(this.node(), null).getPropertyValue(name);
+      priority = "";
+    }
+    return this.each(d3_selection_style(name, value, priority));
+  };
+  function d3_selection_style(name, value, priority) {
+    function styleNull() {
+      this.style.removeProperty(name);
+    }
+    function styleConstant() {
+      this.style.setProperty(name, value, priority);
+    }
+    function styleFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
+    }
+    return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
+  }
+  d3_selectionPrototype.property = function(name, value) {
+    if (arguments.length < 2) {
+      if (typeof name === "string") return this.node()[name];
+      for (value in name) this.each(d3_selection_property(value, name[value]));
+      return this;
+    }
+    return this.each(d3_selection_property(name, value));
+  };
+  function d3_selection_property(name, value) {
+    function propertyNull() {
+      delete this[name];
+    }
+    function propertyConstant() {
+      this[name] = value;
+    }
+    function propertyFunction() {
+      var x = value.apply(this, arguments);
+      if (x == null) delete this[name]; else this[name] = x;
+    }
+    return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
+  }
+  d3_selectionPrototype.text = function(value) {
+    return arguments.length ? this.each(typeof value === "function" ? function() {
+      var v = value.apply(this, arguments);
+      this.textContent = v == null ? "" : v;
+    } : value == null ? function() {
+      this.textContent = "";
+    } : function() {
+      this.textContent = value;
+    }) : this.node().textContent;
+  };
+  d3_selectionPrototype.html = function(value) {
+    return arguments.length ? this.each(typeof value === "function" ? function() {
+      var v = value.apply(this, arguments);
+      this.innerHTML = v == null ? "" : v;
+    } : value == null ? function() {
+      this.innerHTML = "";
+    } : function() {
+      this.innerHTML = value;
+    }) : this.node().innerHTML;
+  };
+  d3_selectionPrototype.append = function(name) {
+    name = d3_selection_creator(name);
+    return this.select(function() {
+      return this.appendChild(name.apply(this, arguments));
+    });
+  };
+  function d3_selection_creator(name) {
+    return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? function() {
+      return this.ownerDocument.createElementNS(name.space, name.local);
+    } : function() {
+      return this.ownerDocument.createElementNS(this.namespaceURI, name);
+    };
+  }
+  d3_selectionPrototype.insert = function(name, before) {
+    name = d3_selection_creator(name);
+    before = d3_selection_selector(before);
+    return this.select(function() {
+      return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
+    });
+  };
+  d3_selectionPrototype.remove = function() {
+    return this.each(function() {
+      var parent = this.parentNode;
+      if (parent) parent.removeChild(this);
+    });
+  };
+  d3_selectionPrototype.data = function(value, key) {
+    var i = -1, n = this.length, group, node;
+    if (!arguments.length) {
+      value = new Array(n = (group = this[0]).length);
+      while (++i < n) {
+        if (node = group[i]) {
+          value[i] = node.__data__;
+        }
+      }
+      return value;
+    }
+    function bind(group, groupData) {
+      var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
+      if (key) {
+        var nodeByKeyValue = new d3_Map(), dataByKeyValue = new d3_Map(), keyValues = [], keyValue;
+        for (i = -1; ++i < n; ) {
+          keyValue = key.call(node = group[i], node.__data__, i);
+          if (nodeByKeyValue.has(keyValue)) {
+            exitNodes[i] = node;
+          } else {
+            nodeByKeyValue.set(keyValue, node);
+          }
+          keyValues.push(keyValue);
+        }
+        for (i = -1; ++i < m; ) {
+          keyValue = key.call(groupData, nodeData = groupData[i], i);
+          if (node = nodeByKeyValue.get(keyValue)) {
+            updateNodes[i] = node;
+            node.__data__ = nodeData;
+          } else if (!dataByKeyValue.has(keyValue)) {
+            enterNodes[i] = d3_selection_dataNode(nodeData);
+          }
+          dataByKeyValue.set(keyValue, nodeData);
+          nodeByKeyValue.remove(keyValue);
+        }
+        for (i = -1; ++i < n; ) {
+          if (nodeByKeyValue.has(keyValues[i])) {
+            exitNodes[i] = group[i];
+          }
+        }
+      } else {
+        for (i = -1; ++i < n0; ) {
+          node = group[i];
+          nodeData = groupData[i];
+          if (node) {
+            node.__data__ = nodeData;
+            updateNodes[i] = node;
+          } else {
+            enterNodes[i] = d3_selection_dataNode(nodeData);
+          }
+        }
+        for (;i < m; ++i) {
+          enterNodes[i] = d3_selection_dataNode(groupData[i]);
+        }
+        for (;i < n; ++i) {
+          exitNodes[i] = group[i];
+        }
+      }
+      enterNodes.update = updateNodes;
+      enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
+      enter.push(enterNodes);
+      update.push(updateNodes);
+      exit.push(exitNodes);
+    }
+    var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
+    if (typeof value === "function") {
+      while (++i < n) {
+        bind(group = this[i], value.call(group, group.parentNode.__data__, i));
+      }
+    } else {
+      while (++i < n) {
+        bind(group = this[i], value);
+      }
+    }
+    update.enter = function() {
+      return enter;
+    };
+    update.exit = function() {
+      return exit;
+    };
+    return update;
+  };
+  function d3_selection_dataNode(data) {
+    return {
+      __data__: data
+    };
+  }
+  d3_selectionPrototype.datum = function(value) {
+    return arguments.length ? this.property("__data__", value) : this.property("__data__");
+  };
+  d3_selectionPrototype.filter = function(filter) {
+    var subgroups = [], subgroup, group, node;
+    if (typeof filter !== "function") filter = d3_selection_filter(filter);
+    for (var j = 0, m = this.length; j < m; j++) {
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = (group = this[j]).parentNode;
+      for (var i = 0, n = group.length; i < n; i++) {
+        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
+          subgroup.push(node);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  function d3_selection_filter(selector) {
+    return function() {
+      return d3_selectMatches(this, selector);
+    };
+  }
+  d3_selectionPrototype.order = function() {
+    for (var j = -1, m = this.length; ++j < m; ) {
+      for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
+        if (node = group[i]) {
+          if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
+          next = node;
+        }
+      }
+    }
+    return this;
+  };
+  d3_selectionPrototype.sort = function(comparator) {
+    comparator = d3_selection_sortComparator.apply(this, arguments);
+    for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
+    return this.order();
+  };
+  function d3_selection_sortComparator(comparator) {
+    if (!arguments.length) comparator = d3_ascending;
+    return function(a, b) {
+      return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
+    };
+  }
+  d3_selectionPrototype.each = function(callback) {
+    return d3_selection_each(this, function(node, i, j) {
+      callback.call(node, node.__data__, i, j);
+    });
+  };
+  function d3_selection_each(groups, callback) {
+    for (var j = 0, m = groups.length; j < m; j++) {
+      for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
+        if (node = group[i]) callback(node, i, j);
+      }
+    }
+    return groups;
+  }
+  d3_selectionPrototype.call = function(callback) {
+    var args = d3_array(arguments);
+    callback.apply(args[0] = this, args);
+    return this;
+  };
+  d3_selectionPrototype.empty = function() {
+    return !this.node();
+  };
+  d3_selectionPrototype.node = function() {
+    for (var j = 0, m = this.length; j < m; j++) {
+      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+        var node = group[i];
+        if (node) return node;
+      }
+    }
+    return null;
+  };
+  d3_selectionPrototype.size = function() {
+    var n = 0;
+    this.each(function() {
+      ++n;
+    });
+    return n;
+  };
+  function d3_selection_enter(selection) {
+    d3_subclass(selection, d3_selection_enterPrototype);
+    return selection;
+  }
+  var d3_selection_enterPrototype = [];
+  d3.selection.enter = d3_selection_enter;
+  d3.selection.enter.prototype = d3_selection_enterPrototype;
+  d3_selection_enterPrototype.append = d3_selectionPrototype.append;
+  d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
+  d3_selection_enterPrototype.node = d3_selectionPrototype.node;
+  d3_selection_enterPrototype.call = d3_selectionPrototype.call;
+  d3_selection_enterPrototype.size = d3_selectionPrototype.size;
+  d3_selection_enterPrototype.select = function(selector) {
+    var subgroups = [], subgroup, subnode, upgroup, group, node;
+    for (var j = -1, m = this.length; ++j < m; ) {
+      upgroup = (group = this[j]).update;
+      subgroups.push(subgroup = []);
+      subgroup.parentNode = group.parentNode;
+      for (var i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
+          subnode.__data__ = node.__data__;
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_selection(subgroups);
+  };
+  d3_selection_enterPrototype.insert = function(name, before) {
+    if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
+    return d3_selectionPrototype.insert.call(this, name, before);
+  };
+  function d3_selection_enterInsertBefore(enter) {
+    var i0, j0;
+    return function(d, i, j) {
+      var group = enter[j].update, n = group.length, node;
+      if (j != j0) j0 = j, i0 = 0;
+      if (i >= i0) i0 = i + 1;
+      while (!(node = group[i0]) && ++i0 < n) ;
+      return node;
+    };
+  }
+  d3_selectionPrototype.transition = function() {
+    var id = d3_transitionInheritId || ++d3_transitionId, subgroups = [], subgroup, node, transition = d3_transitionInherit || {
+      time: Date.now(),
+      ease: d3_ease_cubicInOut,
+      delay: 0,
+      duration: 250
+    };
+    for (var j = -1, m = this.length; ++j < m; ) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) d3_transitionNode(node, i, id, transition);
+        subgroup.push(node);
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_selectionPrototype.interrupt = function() {
+    return this.each(d3_selection_interrupt);
+  };
+  function d3_selection_interrupt() {
+    var lock = this.__transition__;
+    if (lock) ++lock.active;
+  }
+  d3.select = function(node) {
+    var group = [ typeof node === "string" ? d3_select(node, d3_document) : node ];
+    group.parentNode = d3_documentElement;
+    return d3_selection([ group ]);
+  };
+  d3.selectAll = function(nodes) {
+    var group = d3_array(typeof nodes === "string" ? d3_selectAll(nodes, d3_document) : nodes);
+    group.parentNode = d3_documentElement;
+    return d3_selection([ group ]);
+  };
+  var d3_selectionRoot = d3.select(d3_documentElement);
+  d3_selectionPrototype.on = function(type, listener, capture) {
+    var n = arguments.length;
+    if (n < 3) {
+      if (typeof type !== "string") {
+        if (n < 2) listener = false;
+        for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
+        return this;
+      }
+      if (n < 2) return (n = this.node()["__on" + type]) && n._;
+      capture = false;
+    }
+    return this.each(d3_selection_on(type, listener, capture));
+  };
+  function d3_selection_on(type, listener, capture) {
+    var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
+    if (i > 0) type = type.substring(0, i);
+    var filter = d3_selection_onFilters.get(type);
+    if (filter) type = filter, wrap = d3_selection_onFilter;
+    function onRemove() {
+      var l = this[name];
+      if (l) {
+        this.removeEventListener(type, l, l.$);
+        delete this[name];
+      }
+    }
+    function onAdd() {
+      var l = wrap(listener, d3_array(arguments));
+      onRemove.call(this);
+      this.addEventListener(type, this[name] = l, l.$ = capture);
+      l._ = listener;
+    }
+    function removeAll() {
+      var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
+      for (var name in this) {
+        if (match = name.match(re)) {
+          var l = this[name];
+          this.removeEventListener(match[1], l, l.$);
+          delete this[name];
+        }
+      }
+    }
+    return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
+  }
+  var d3_selection_onFilters = d3.map({
+    mouseenter: "mouseover",
+    mouseleave: "mouseout"
+  });
+  d3_selection_onFilters.forEach(function(k) {
+    if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
+  });
+  function d3_selection_onListener(listener, argumentz) {
+    return function(e) {
+      var o = d3.event;
+      d3.event = e;
+      argumentz[0] = this.__data__;
+      try {
+        listener.apply(this, argumentz);
+      } finally {
+        d3.event = o;
+      }
+    };
+  }
+  function d3_selection_onFilter(listener, argumentz) {
+    var l = d3_selection_onListener(listener, argumentz);
+    return function(e) {
+      var target = this, related = e.relatedTarget;
+      if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
+        l.call(target, e);
+      }
+    };
+  }
+  var d3_event_dragSelect = "onselectstart" in d3_document ? null : d3_vendorSymbol(d3_documentElement.style, "userSelect"), d3_event_dragId = 0;
+  function d3_event_dragSuppress() {
+    var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
+    if (d3_event_dragSelect) {
+      var style = d3_documentElement.style, select = style[d3_event_dragSelect];
+      style[d3_event_dragSelect] = "none";
+    }
+    return function(suppressClick) {
+      w.on(name, null);
+      if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
+      if (suppressClick) {
+        function off() {
+          w.on(click, null);
+        }
+        w.on(click, function() {
+          d3_eventPreventDefault();
+          off();
+        }, true);
+        setTimeout(off, 0);
+      }
+    };
+  }
+  d3.mouse = function(container) {
+    return d3_mousePoint(container, d3_eventSource());
+  };
+  function d3_mousePoint(container, e) {
+    if (e.changedTouches) e = e.changedTouches[0];
+    var svg = container.ownerSVGElement || container;
+    if (svg.createSVGPoint) {
+      var point = svg.createSVGPoint();
+      point.x = e.clientX, point.y = e.clientY;
+      point = point.matrixTransform(container.getScreenCTM().inverse());
+      return [ point.x, point.y ];
+    }
+    var rect = container.getBoundingClientRect();
+    return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
+  }
+  d3.touches = function(container, touches) {
+    if (arguments.length < 2) touches = d3_eventSource().touches;
+    return touches ? d3_array(touches).map(function(touch) {
+      var point = d3_mousePoint(container, touch);
+      point.identifier = touch.identifier;
+      return point;
+    }) : [];
+  };
+  d3.behavior.drag = function() {
+    var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_behavior_dragMouseSubject, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_behavior_dragTouchSubject, "touchmove", "touchend");
+    function drag() {
+      this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
+    }
+    function dragstart(id, position, subject, move, end) {
+      return function() {
+        var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject()).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(), position0 = position(parent, dragId);
+        if (origin) {
+          dragOffset = origin.apply(that, arguments);
+          dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
+        } else {
+          dragOffset = [ 0, 0 ];
+        }
+        dispatch({
+          type: "dragstart"
+        });
+        function moved() {
+          var position1 = position(parent, dragId), dx, dy;
+          if (!position1) return;
+          dx = position1[0] - position0[0];
+          dy = position1[1] - position0[1];
+          dragged |= dx | dy;
+          position0 = position1;
+          dispatch({
+            type: "drag",
+            x: position1[0] + dragOffset[0],
+            y: position1[1] + dragOffset[1],
+            dx: dx,
+            dy: dy
+          });
+        }
+        function ended() {
+          if (!position(parent, dragId)) return;
+          dragSubject.on(move + dragName, null).on(end + dragName, null);
+          dragRestore(dragged && d3.event.target === target);
+          dispatch({
+            type: "dragend"
+          });
+        }
+      };
+    }
+    drag.origin = function(x) {
+      if (!arguments.length) return origin;
+      origin = x;
+      return drag;
+    };
+    return d3.rebind(drag, event, "on");
+  };
+  function d3_behavior_dragTouchId() {
+    return d3.event.changedTouches[0].identifier;
+  }
+  function d3_behavior_dragTouchSubject() {
+    return d3.event.target;
+  }
+  function d3_behavior_dragMouseSubject() {
+    return d3_window;
+  }
+  var π = Math.PI, τ = 2 * π, halfπ = π / 2, ε = 1e-6, ε2 = ε * ε, d3_radians = π / 180, d3_degrees = 180 / π;
+  function d3_sgn(x) {
+    return x > 0 ? 1 : x < 0 ? -1 : 0;
+  }
+  function d3_cross2d(a, b, c) {
+    return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
+  }
+  function d3_acos(x) {
+    return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
+  }
+  function d3_asin(x) {
+    return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
+  }
+  function d3_sinh(x) {
+    return ((x = Math.exp(x)) - 1 / x) / 2;
+  }
+  function d3_cosh(x) {
+    return ((x = Math.exp(x)) + 1 / x) / 2;
+  }
+  function d3_tanh(x) {
+    return ((x = Math.exp(2 * x)) - 1) / (x + 1);
+  }
+  function d3_haversin(x) {
+    return (x = Math.sin(x / 2)) * x;
+  }
+  var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
+  d3.interpolateZoom = function(p0, p1) {
+    var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
+    var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;
+    function interpolate(t) {
+      var s = t * S;
+      if (dr) {
+        var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
+        return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
+      }
+      return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];
+    }
+    interpolate.duration = S * 1e3;
+    return interpolate;
+  };
+  d3.behavior.zoom = function() {
+    var view = {
+      x: 0,
+      y: 0,
+      k: 1
+    }, translate0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
+    function zoom(g) {
+      g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on(mousemove, mousewheelreset).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
+    }
+    zoom.event = function(g) {
+      g.each(function() {
+        var dispatch = event.of(this, arguments), view1 = view;
+        if (d3_transitionInheritId) {
+          d3.select(this).transition().each("start.zoom", function() {
+            view = this.__chart__ || {
+              x: 0,
+              y: 0,
+              k: 1
+            };
+            zoomstarted(dispatch);
+          }).tween("zoom:zoom", function() {
+            var dx = size[0], dy = size[1], cx = dx / 2, cy = dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
+            return function(t) {
+              var l = i(t), k = dx / l[2];
+              this.__chart__ = view = {
+                x: cx - l[0] * k,
+                y: cy - l[1] * k,
+                k: k
+              };
+              zoomed(dispatch);
+            };
+          }).each("end.zoom", function() {
+            zoomended(dispatch);
+          });
+        } else {
+          this.__chart__ = view;
+          zoomstarted(dispatch);
+          zoomed(dispatch);
+          zoomended(dispatch);
+        }
+      });
+    };
+    zoom.translate = function(_) {
+      if (!arguments.length) return [ view.x, view.y ];
+      view = {
+        x: +_[0],
+        y: +_[1],
+        k: view.k
+      };
+      rescale();
+      return zoom;
+    };
+    zoom.scale = function(_) {
+      if (!arguments.length) return view.k;
+      view = {
+        x: view.x,
+        y: view.y,
+        k: +_
+      };
+      rescale();
+      return zoom;
+    };
+    zoom.scaleExtent = function(_) {
+      if (!arguments.length) return scaleExtent;
+      scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.center = function(_) {
+      if (!arguments.length) return center;
+      center = _ && [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.size = function(_) {
+      if (!arguments.length) return size;
+      size = _ && [ +_[0], +_[1] ];
+      return zoom;
+    };
+    zoom.x = function(z) {
+      if (!arguments.length) return x1;
+      x1 = z;
+      x0 = z.copy();
+      view = {
+        x: 0,
+        y: 0,
+        k: 1
+      };
+      return zoom;
+    };
+    zoom.y = function(z) {
+      if (!arguments.length) return y1;
+      y1 = z;
+      y0 = z.copy();
+      view = {
+        x: 0,
+        y: 0,
+        k: 1
+      };
+      return zoom;
+    };
+    function location(p) {
+      return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
+    }
+    function point(l) {
+      return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
+    }
+    function scaleTo(s) {
+      view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
+    }
+    function translateTo(p, l) {
+      l = point(l);
+      view.x += p[0] - l[0];
+      view.y += p[1] - l[1];
+    }
+    function rescale() {
+      if (x1) x1.domain(x0.range().map(function(x) {
+        return (x - view.x) / view.k;
+      }).map(x0.invert));
+      if (y1) y1.domain(y0.range().map(function(y) {
+        return (y - view.y) / view.k;
+      }).map(y0.invert));
+    }
+    function zoomstarted(dispatch) {
+      dispatch({
+        type: "zoomstart"
+      });
+    }
+    function zoomed(dispatch) {
+      rescale();
+      dispatch({
+        type: "zoom",
+        scale: view.k,
+        translate: [ view.x, view.y ]
+      });
+    }
+    function zoomended(dispatch) {
+      dispatch({
+        type: "zoomend"
+      });
+    }
+    function mousedowned() {
+      var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
+      zoomstarted(dispatch);
+      function moved() {
+        dragged = 1;
+        translateTo(d3.mouse(that), location0);
+        zoomed(dispatch);
+      }
+      function ended() {
+        subject.on(mousemove, d3_window === that ? mousewheelreset : null).on(mouseup, null);
+        dragRestore(dragged && d3.event.target === target);
+        zoomended(dispatch);
+      }
+    }
+    function touchstarted() {
+      var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, target = d3.select(d3.event.target).on(touchmove, moved).on(touchend, ended), subject = d3.select(that).on(mousedown, null).on(touchstart, started), dragRestore = d3_event_dragSuppress();
+      d3_selection_interrupt.call(that);
+      started();
+      zoomstarted(dispatch);
+      function relocate() {
+        var touches = d3.touches(that);
+        scale0 = view.k;
+        touches.forEach(function(t) {
+          if (t.identifier in locations0) locations0[t.identifier] = location(t);
+        });
+        return touches;
+      }
+      function started() {
+        var changed = d3.event.changedTouches;
+        for (var i = 0, n = changed.length; i < n; ++i) {
+          locations0[changed[i].identifier] = null;
+        }
+        var touches = relocate(), now = Date.now();
+        if (touches.length === 1) {
+          if (now - touchtime < 500) {
+            var p = touches[0], l = locations0[p.identifier];
+            scaleTo(view.k * 2);
+            translateTo(p, l);
+            d3_eventPreventDefault();
+            zoomed(dispatch);
+          }
+          touchtime = now;
+        } else if (touches.length > 1) {
+          var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
+          distance0 = dx * dx + dy * dy;
+        }
+      }
+      function moved() {
+        var touches = d3.touches(that), p0, l0, p1, l1;
+        for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
+          p1 = touches[i];
+          if (l1 = locations0[p1.identifier]) {
+            if (l0) break;
+            p0 = p1, l0 = l1;
+          }
+        }
+        if (l1) {
+          var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
+          p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
+          l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
+          scaleTo(scale1 * scale0);
+        }
+        touchtime = null;
+        translateTo(p0, l0);
+        zoomed(dispatch);
+      }
+      function ended() {
+        if (d3.event.touches.length) {
+          var changed = d3.event.changedTouches;
+          for (var i = 0, n = changed.length; i < n; ++i) {
+            delete locations0[changed[i].identifier];
+          }
+          for (var identifier in locations0) {
+            return void relocate();
+          }
+        }
+        target.on(zoomName, null);
+        subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
+        dragRestore();
+        zoomended(dispatch);
+      }
+    }
+    function mousewheeled() {
+      var dispatch = event.of(this, arguments);
+      if (mousewheelTimer) clearTimeout(mousewheelTimer); else d3_selection_interrupt.call(this), 
+      zoomstarted(dispatch);
+      mousewheelTimer = setTimeout(function() {
+        mousewheelTimer = null;
+        zoomended(dispatch);
+      }, 50);
+      d3_eventPreventDefault();
+      var point = center || d3.mouse(this);
+      if (!translate0) translate0 = location(point);
+      scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
+      translateTo(point, translate0);
+      zoomed(dispatch);
+    }
+    function mousewheelreset() {
+      translate0 = null;
+    }
+    function dblclicked() {
+      var dispatch = event.of(this, arguments), p = d3.mouse(this), l = location(p), k = Math.log(view.k) / Math.LN2;
+      zoomstarted(dispatch);
+      scaleTo(Math.pow(2, d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1));
+      translateTo(p, l);
+      zoomed(dispatch);
+      zoomended(dispatch);
+    }
+    return d3.rebind(zoom, event, "on");
+  };
+  var d3_behavior_zoomInfinity = [ 0, Infinity ];
+  var d3_behavior_zoomDelta, d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+    return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
+  }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
+    return d3.event.wheelDelta;
+  }, "mousewheel") : (d3_behavior_zoomDelta = function() {
+    return -d3.event.detail;
+  }, "MozMousePixelScroll");
+  function d3_Color() {}
+  d3_Color.prototype.toString = function() {
+    return this.rgb() + "";
+  };
+  d3.hsl = function(h, s, l) {
+    return arguments.length === 1 ? h instanceof d3_Hsl ? d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : d3_hsl(+h, +s, +l);
+  };
+  function d3_hsl(h, s, l) {
+    return new d3_Hsl(h, s, l);
+  }
+  function d3_Hsl(h, s, l) {
+    this.h = h;
+    this.s = s;
+    this.l = l;
+  }
+  var d3_hslPrototype = d3_Hsl.prototype = new d3_Color();
+  d3_hslPrototype.brighter = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return d3_hsl(this.h, this.s, this.l / k);
+  };
+  d3_hslPrototype.darker = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return d3_hsl(this.h, this.s, k * this.l);
+  };
+  d3_hslPrototype.rgb = function() {
+    return d3_hsl_rgb(this.h, this.s, this.l);
+  };
+  function d3_hsl_rgb(h, s, l) {
+    var m1, m2;
+    h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
+    s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
+    l = l < 0 ? 0 : l > 1 ? 1 : l;
+    m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
+    m1 = 2 * l - m2;
+    function v(h) {
+      if (h > 360) h -= 360; else if (h < 0) h += 360;
+      if (h < 60) return m1 + (m2 - m1) * h / 60;
+      if (h < 180) return m2;
+      if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
+      return m1;
+    }
+    function vv(h) {
+      return Math.round(v(h) * 255);
+    }
+    return d3_rgb(vv(h + 120), vv(h), vv(h - 120));
+  }
+  d3.hcl = function(h, c, l) {
+    return arguments.length === 1 ? h instanceof d3_Hcl ? d3_hcl(h.h, h.c, h.l) : h instanceof d3_Lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : d3_hcl(+h, +c, +l);
+  };
+  function d3_hcl(h, c, l) {
+    return new d3_Hcl(h, c, l);
+  }
+  function d3_Hcl(h, c, l) {
+    this.h = h;
+    this.c = c;
+    this.l = l;
+  }
+  var d3_hclPrototype = d3_Hcl.prototype = new d3_Color();
+  d3_hclPrototype.brighter = function(k) {
+    return d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
+  };
+  d3_hclPrototype.darker = function(k) {
+    return d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
+  };
+  d3_hclPrototype.rgb = function() {
+    return d3_hcl_lab(this.h, this.c, this.l).rgb();
+  };
+  function d3_hcl_lab(h, c, l) {
+    if (isNaN(h)) h = 0;
+    if (isNaN(c)) c = 0;
+    return d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
+  }
+  d3.lab = function(l, a, b) {
+    return arguments.length === 1 ? l instanceof d3_Lab ? d3_lab(l.l, l.a, l.b) : l instanceof d3_Hcl ? d3_hcl_lab(l.l, l.c, l.h) : d3_rgb_lab((l = d3.rgb(l)).r, l.g, l.b) : d3_lab(+l, +a, +b);
+  };
+  function d3_lab(l, a, b) {
+    return new d3_Lab(l, a, b);
+  }
+  function d3_Lab(l, a, b) {
+    this.l = l;
+    this.a = a;
+    this.b = b;
+  }
+  var d3_lab_K = 18;
+  var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
+  var d3_labPrototype = d3_Lab.prototype = new d3_Color();
+  d3_labPrototype.brighter = function(k) {
+    return d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+  };
+  d3_labPrototype.darker = function(k) {
+    return d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
+  };
+  d3_labPrototype.rgb = function() {
+    return d3_lab_rgb(this.l, this.a, this.b);
+  };
+  function d3_lab_rgb(l, a, b) {
+    var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
+    x = d3_lab_xyz(x) * d3_lab_X;
+    y = d3_lab_xyz(y) * d3_lab_Y;
+    z = d3_lab_xyz(z) * d3_lab_Z;
+    return d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
+  }
+  function d3_lab_hcl(l, a, b) {
+    return l > 0 ? d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : d3_hcl(NaN, NaN, l);
+  }
+  function d3_lab_xyz(x) {
+    return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
+  }
+  function d3_xyz_lab(x) {
+    return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
+  }
+  function d3_xyz_rgb(r) {
+    return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
+  }
+  d3.rgb = function(r, g, b) {
+    return arguments.length === 1 ? r instanceof d3_Rgb ? d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : d3_rgb(~~r, ~~g, ~~b);
+  };
+  function d3_rgbNumber(value) {
+    return d3_rgb(value >> 16, value >> 8 & 255, value & 255);
+  }
+  function d3_rgbString(value) {
+    return d3_rgbNumber(value) + "";
+  }
+  function d3_rgb(r, g, b) {
+    return new d3_Rgb(r, g, b);
+  }
+  function d3_Rgb(r, g, b) {
+    this.r = r;
+    this.g = g;
+    this.b = b;
+  }
+  var d3_rgbPrototype = d3_Rgb.prototype = new d3_Color();
+  d3_rgbPrototype.brighter = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    var r = this.r, g = this.g, b = this.b, i = 30;
+    if (!r && !g && !b) return d3_rgb(i, i, i);
+    if (r && r < i) r = i;
+    if (g && g < i) g = i;
+    if (b && b < i) b = i;
+    return d3_rgb(Math.min(255, ~~(r / k)), Math.min(255, ~~(g / k)), Math.min(255, ~~(b / k)));
+  };
+  d3_rgbPrototype.darker = function(k) {
+    k = Math.pow(.7, arguments.length ? k : 1);
+    return d3_rgb(~~(k * this.r), ~~(k * this.g), ~~(k * this.b));
+  };
+  d3_rgbPrototype.hsl = function() {
+    return d3_rgb_hsl(this.r, this.g, this.b);
+  };
+  d3_rgbPrototype.toString = function() {
+    return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
+  };
+  function d3_rgb_hex(v) {
+    return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
+  }
+  function d3_rgb_parse(format, rgb, hsl) {
+    var r = 0, g = 0, b = 0, m1, m2, color;
+    m1 = /([a-z]+)\((.*)\)/i.exec(format);
+    if (m1) {
+      m2 = m1[2].split(",");
+      switch (m1[1]) {
+       case "hsl":
+        {
+          return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
+        }
+
+       case "rgb":
+        {
+          return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
+        }
+      }
+    }
+    if (color = d3_rgb_names.get(format)) return rgb(color.r, color.g, color.b);
+    if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.substring(1), 16))) {
+      if (format.length === 4) {
+        r = (color & 3840) >> 4;
+        r = r >> 4 | r;
+        g = color & 240;
+        g = g >> 4 | g;
+        b = color & 15;
+        b = b << 4 | b;
+      } else if (format.length === 7) {
+        r = (color & 16711680) >> 16;
+        g = (color & 65280) >> 8;
+        b = color & 255;
+      }
+    }
+    return rgb(r, g, b);
+  }
+  function d3_rgb_hsl(r, g, b) {
+    var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
+    if (d) {
+      s = l < .5 ? d / (max + min) : d / (2 - max - min);
+      if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
+      h *= 60;
+    } else {
+      h = NaN;
+      s = l > 0 && l < 1 ? 0 : h;
+    }
+    return d3_hsl(h, s, l);
+  }
+  function d3_rgb_lab(r, g, b) {
+    r = d3_rgb_xyz(r);
+    g = d3_rgb_xyz(g);
+    b = d3_rgb_xyz(b);
+    var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
+    return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
+  }
+  function d3_rgb_xyz(r) {
+    return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
+  }
+  function d3_rgb_parseNumber(c) {
+    var f = parseFloat(c);
+    return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
+  }
+  var d3_rgb_names = d3.map({
+    aliceblue: 15792383,
+    antiquewhite: 16444375,
+    aqua: 65535,
+    aquamarine: 8388564,
+    azure: 15794175,
+    beige: 16119260,
+    bisque: 16770244,
+    black: 0,
+    blanchedalmond: 16772045,
+    blue: 255,
+    blueviolet: 9055202,
+    brown: 10824234,
+    burlywood: 14596231,
+    cadetblue: 6266528,
+    chartreuse: 8388352,
+    chocolate: 13789470,
+    coral: 16744272,
+    cornflowerblue: 6591981,
+    cornsilk: 16775388,
+    crimson: 14423100,
+    cyan: 65535,
+    darkblue: 139,
+    darkcyan: 35723,
+    darkgoldenrod: 12092939,
+    darkgray: 11119017,
+    darkgreen: 25600,
+    darkgrey: 11119017,
+    darkkhaki: 12433259,
+    darkmagenta: 9109643,
+    darkolivegreen: 5597999,
+    darkorange: 16747520,
+    darkorchid: 10040012,
+    darkred: 9109504,
+    darksalmon: 15308410,
+    darkseagreen: 9419919,
+    darkslateblue: 4734347,
+    darkslategray: 3100495,
+    darkslategrey: 3100495,
+    darkturquoise: 52945,
+    darkviolet: 9699539,
+    deeppink: 16716947,
+    deepskyblue: 49151,
+    dimgray: 6908265,
+    dimgrey: 6908265,
+    dodgerblue: 2003199,
+    firebrick: 11674146,
+    floralwhite: 16775920,
+    forestgreen: 2263842,
+    fuchsia: 16711935,
+    gainsboro: 14474460,
+    ghostwhite: 16316671,
+    gold: 16766720,
+    goldenrod: 14329120,
+    gray: 8421504,
+    green: 32768,
+    greenyellow: 11403055,
+    grey: 8421504,
+    honeydew: 15794160,
+    hotpink: 16738740,
+    indianred: 13458524,
+    indigo: 4915330,
+    ivory: 16777200,
+    khaki: 15787660,
+    lavender: 15132410,
+    lavenderblush: 16773365,
+    lawngreen: 8190976,
+    lemonchiffon: 16775885,
+    lightblue: 11393254,
+    lightcoral: 15761536,
+    lightcyan: 14745599,
+    lightgoldenrodyellow: 16448210,
+    lightgray: 13882323,
+    lightgreen: 9498256,
+    lightgrey: 13882323,
+    lightpink: 16758465,
+    lightsalmon: 16752762,
+    lightseagreen: 2142890,
+    lightskyblue: 8900346,
+    lightslategray: 7833753,
+    lightslategrey: 7833753,
+    lightsteelblue: 11584734,
+    lightyellow: 16777184,
+    lime: 65280,
+    limegreen: 3329330,
+    linen: 16445670,
+    magenta: 16711935,
+    maroon: 8388608,
+    mediumaquamarine: 6737322,
+    mediumblue: 205,
+    mediumorchid: 12211667,
+    mediumpurple: 9662683,
+    mediumseagreen: 3978097,
+    mediumslateblue: 8087790,
+    mediumspringgreen: 64154,
+    mediumturquoise: 4772300,
+    mediumvioletred: 13047173,
+    midnightblue: 1644912,
+    mintcream: 16121850,
+    mistyrose: 16770273,
+    moccasin: 16770229,
+    navajowhite: 16768685,
+    navy: 128,
+    oldlace: 16643558,
+    olive: 8421376,
+    olivedrab: 7048739,
+    orange: 16753920,
+    orangered: 16729344,
+    orchid: 14315734,
+    palegoldenrod: 15657130,
+    palegreen: 10025880,
+    paleturquoise: 11529966,
+    palevioletred: 14381203,
+    papayawhip: 16773077,
+    peachpuff: 16767673,
+    peru: 13468991,
+    pink: 16761035,
+    plum: 14524637,
+    powderblue: 11591910,
+    purple: 8388736,
+    red: 16711680,
+    rosybrown: 12357519,
+    royalblue: 4286945,
+    saddlebrown: 9127187,
+    salmon: 16416882,
+    sandybrown: 16032864,
+    seagreen: 3050327,
+    seashell: 16774638,
+    sienna: 10506797,
+    silver: 12632256,
+    skyblue: 8900331,
+    slateblue: 6970061,
+    slategray: 7372944,
+    slategrey: 7372944,
+    snow: 16775930,
+    springgreen: 65407,
+    steelblue: 4620980,
+    tan: 13808780,
+    teal: 32896,
+    thistle: 14204888,
+    tomato: 16737095,
+    turquoise: 4251856,
+    violet: 15631086,
+    wheat: 16113331,
+    white: 16777215,
+    whitesmoke: 16119285,
+    yellow: 16776960,
+    yellowgreen: 10145074
+  });
+  d3_rgb_names.forEach(function(key, value) {
+    d3_rgb_names.set(key, d3_rgbNumber(value));
+  });
+  function d3_functor(v) {
+    return typeof v === "function" ? v : function() {
+      return v;
+    };
+  }
+  d3.functor = d3_functor;
+  function d3_identity(d) {
+    return d;
+  }
+  d3.xhr = d3_xhrType(d3_identity);
+  function d3_xhrType(response) {
+    return function(url, mimeType, callback) {
+      if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, 
+      mimeType = null;
+      return d3_xhr(url, mimeType, response, callback);
+    };
+  }
+  function d3_xhr(url, mimeType, response, callback) {
+    var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
+    if (d3_window.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
+    "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
+      request.readyState > 3 && respond();
+    };
+    function respond() {
+      var status = request.status, result;
+      if (!status && request.responseText || status >= 200 && status < 300 || status === 304) {
+        try {
+          result = response.call(xhr, request);
+        } catch (e) {
+          dispatch.error.call(xhr, e);
+          return;
+        }
+        dispatch.load.call(xhr, result);
+      } else {
+        dispatch.error.call(xhr, request);
+      }
+    }
+    request.onprogress = function(event) {
+      var o = d3.event;
+      d3.event = event;
+      try {
+        dispatch.progress.call(xhr, request);
+      } finally {
+        d3.event = o;
+      }
+    };
+    xhr.header = function(name, value) {
+      name = (name + "").toLowerCase();
+      if (arguments.length < 2) return headers[name];
+      if (value == null) delete headers[name]; else headers[name] = value + "";
+      return xhr;
+    };
+    xhr.mimeType = function(value) {
+      if (!arguments.length) return mimeType;
+      mimeType = value == null ? null : value + "";
+      return xhr;
+    };
+    xhr.responseType = function(value) {
+      if (!arguments.length) return responseType;
+      responseType = value;
+      return xhr;
+    };
+    xhr.response = function(value) {
+      response = value;
+      return xhr;
+    };
+    [ "get", "post" ].forEach(function(method) {
+      xhr[method] = function() {
+        return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
+      };
+    });
+    xhr.send = function(method, data, callback) {
+      if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
+      request.open(method, url, true);
+      if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
+      if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
+      if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
+      if (responseType != null) request.responseType = responseType;
+      if (callback != null) xhr.on("error", callback).on("load", function(request) {
+        callback(null, request);
+      });
+      dispatch.beforesend.call(xhr, request);
+      request.send(data == null ? null : data);
+      return xhr;
+    };
+    xhr.abort = function() {
+      request.abort();
+      return xhr;
+    };
+    d3.rebind(xhr, dispatch, "on");
+    return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
+  }
+  function d3_xhr_fixCallback(callback) {
+    return callback.length === 1 ? function(error, request) {
+      callback(error == null ? request : null);
+    } : callback;
+  }
+  d3.dsv = function(delimiter, mimeType) {
+    var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
+    function dsv(url, row, callback) {
+      if (arguments.length < 3) callback = row, row = null;
+      var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
+      xhr.row = function(_) {
+        return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
+      };
+      return xhr;
+    }
+    function response(request) {
+      return dsv.parse(request.responseText);
+    }
+    function typedResponse(f) {
+      return function(request) {
+        return dsv.parse(request.responseText, f);
+      };
+    }
+    dsv.parse = function(text, f) {
+      var o;
+      return dsv.parseRows(text, function(row, i) {
+        if (o) return o(row, i - 1);
+        var a = new Function("d", "return {" + row.map(function(name, i) {
+          return JSON.stringify(name) + ": d[" + i + "]";
+        }).join(",") + "}");
+        o = f ? function(row, i) {
+          return f(a(row), i);
+        } : a;
+      });
+    };
+    dsv.parseRows = function(text, f) {
+      var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
+      function token() {
+        if (I >= N) return EOF;
+        if (eol) return eol = false, EOL;
+        var j = I;
+        if (text.charCodeAt(j) === 34) {
+          var i = j;
+          while (i++ < N) {
+            if (text.charCodeAt(i) === 34) {
+              if (text.charCodeAt(i + 1) !== 34) break;
+              ++i;
+            }
+          }
+          I = i + 2;
+          var c = text.charCodeAt(i + 1);
+          if (c === 13) {
+            eol = true;
+            if (text.charCodeAt(i + 2) === 10) ++I;
+          } else if (c === 10) {
+            eol = true;
+          }
+          return text.substring(j + 1, i).replace(/""/g, '"');
+        }
+        while (I < N) {
+          var c = text.charCodeAt(I++), k = 1;
+          if (c === 10) eol = true; else if (c === 13) {
+            eol = true;
+            if (text.charCodeAt(I) === 10) ++I, ++k;
+          } else if (c !== delimiterCode) continue;
+          return text.substring(j, I - k);
+        }
+        return text.substring(j);
+      }
+      while ((t = token()) !== EOF) {
+        var a = [];
+        while (t !== EOL && t !== EOF) {
+          a.push(t);
+          t = token();
+        }
+        if (f && !(a = f(a, n++))) continue;
+        rows.push(a);
+      }
+      return rows;
+    };
+    dsv.format = function(rows) {
+      if (Array.isArray(rows[0])) return dsv.formatRows(rows);
+      var fieldSet = new d3_Set(), fields = [];
+      rows.forEach(function(row) {
+        for (var field in row) {
+          if (!fieldSet.has(field)) {
+            fields.push(fieldSet.add(field));
+          }
+        }
+      });
+      return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
+        return fields.map(function(field) {
+          return formatValue(row[field]);
+        }).join(delimiter);
+      })).join("\n");
+    };
+    dsv.formatRows = function(rows) {
+      return rows.map(formatRow).join("\n");
+    };
+    function formatRow(row) {
+      return row.map(formatValue).join(delimiter);
+    }
+    function formatValue(text) {
+      return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
+    }
+    return dsv;
+  };
+  d3.csv = d3.dsv(",", "text/csv");
+  d3.tsv = d3.dsv("	", "text/tab-separated-values");
+  d3.touch = function(container, touches, identifier) {
+    if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
+    if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
+      if ((touch = touches[i]).identifier === identifier) {
+        return d3_mousePoint(container, touch);
+      }
+    }
+  };
+  var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = d3_window[d3_vendorSymbol(d3_window, "requestAnimationFrame")] || function(callback) {
+    setTimeout(callback, 17);
+  };
+  d3.timer = function(callback, delay, then) {
+    var n = arguments.length;
+    if (n < 2) delay = 0;
+    if (n < 3) then = Date.now();
+    var time = then + delay, timer = {
+      c: callback,
+      t: time,
+      f: false,
+      n: null
+    };
+    if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
+    d3_timer_queueTail = timer;
+    if (!d3_timer_interval) {
+      d3_timer_timeout = clearTimeout(d3_timer_timeout);
+      d3_timer_interval = 1;
+      d3_timer_frame(d3_timer_step);
+    }
+  };
+  function d3_timer_step() {
+    var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
+    if (delay > 24) {
+      if (isFinite(delay)) {
+        clearTimeout(d3_timer_timeout);
+        d3_timer_timeout = setTimeout(d3_timer_step, delay);
+      }
+      d3_timer_interval = 0;
+    } else {
+      d3_timer_interval = 1;
+      d3_timer_frame(d3_timer_step);
+    }
+  }
+  d3.timer.flush = function() {
+    d3_timer_mark();
+    d3_timer_sweep();
+  };
+  function d3_timer_mark() {
+    var now = Date.now();
+    d3_timer_active = d3_timer_queueHead;
+    while (d3_timer_active) {
+      if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
+      d3_timer_active = d3_timer_active.n;
+    }
+    return now;
+  }
+  function d3_timer_sweep() {
+    var t0, t1 = d3_timer_queueHead, time = Infinity;
+    while (t1) {
+      if (t1.f) {
+        t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
+      } else {
+        if (t1.t < time) time = t1.t;
+        t1 = (t0 = t1).n;
+      }
+    }
+    d3_timer_queueTail = t0;
+    return time;
+  }
+  function d3_format_precision(x, p) {
+    return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
+  }
+  d3.round = function(x, n) {
+    return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
+  };
+  var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
+  d3.formatPrefix = function(value, precision) {
+    var i = 0;
+    if (value) {
+      if (value < 0) value *= -1;
+      if (precision) value = d3.round(value, d3_format_precision(value, precision));
+      i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
+      i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
+    }
+    return d3_formatPrefixes[8 + i / 3];
+  };
+  function d3_formatPrefix(d, i) {
+    var k = Math.pow(10, abs(8 - i) * 3);
+    return {
+      scale: i > 8 ? function(d) {
+        return d / k;
+      } : function(d) {
+        return d * k;
+      },
+      symbol: d
+    };
+  }
+  function d3_locale_numberFormat(locale) {
+    var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping ? function(value) {
+      var i = value.length, t = [], j = 0, g = locale_grouping[0];
+      while (i > 0 && g > 0) {
+        t.push(value.substring(i -= g, i + g));
+        g = locale_grouping[j = (j + 1) % locale_grouping.length];
+      }
+      return t.reverse().join(locale_thousands);
+    } : d3_identity;
+    return function(specifier) {
+      var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false;
+      if (precision) precision = +precision.substring(1);
+      if (zfill || fill === "0" && align === "=") {
+        zfill = fill = "0";
+        align = "=";
+        if (comma) width -= Math.floor((width - 1) / 4);
+      }
+      switch (type) {
+       case "n":
+        comma = true;
+        type = "g";
+        break;
+
+       case "%":
+        scale = 100;
+        suffix = "%";
+        type = "f";
+        break;
+
+       case "p":
+        scale = 100;
+        suffix = "%";
+        type = "r";
+        break;
+
+       case "b":
+       case "o":
+       case "x":
+       case "X":
+        if (symbol === "#") prefix = "0" + type.toLowerCase();
+
+       case "c":
+       case "d":
+        integer = true;
+        precision = 0;
+        break;
+
+       case "s":
+        scale = -1;
+        type = "r";
+        break;
+      }
+      if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
+      if (type == "r" && !precision) type = "g";
+      if (precision != null) {
+        if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
+      }
+      type = d3_format_types.get(type) || d3_format_typeDefault;
+      var zcomma = zfill && comma;
+      return function(value) {
+        var fullSuffix = suffix;
+        if (integer && value % 1) return "";
+        var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, "-") : sign;
+        if (scale < 0) {
+          var unit = d3.formatPrefix(value, precision);
+          value = unit.scale(value);
+          fullSuffix = unit.symbol + suffix;
+        } else {
+          value *= scale;
+        }
+        value = type(value, precision);
+        var i = value.lastIndexOf("."), before = i < 0 ? value : value.substring(0, i), after = i < 0 ? "" : locale_decimal + value.substring(i + 1);
+        if (!zfill && comma) before = formatGroup(before);
+        var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
+        if (zcomma) before = formatGroup(padding + before);
+        negative += prefix;
+        value = before + after;
+        return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
+      };
+    };
+  }
+  var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
+  var d3_format_types = d3.map({
+    b: function(x) {
+      return x.toString(2);
+    },
+    c: function(x) {
+      return String.fromCharCode(x);
+    },
+    o: function(x) {
+      return x.toString(8);
+    },
+    x: function(x) {
+      return x.toString(16);
+    },
+    X: function(x) {
+      return x.toString(16).toUpperCase();
+    },
+    g: function(x, p) {
+      return x.toPrecision(p);
+    },
+    e: function(x, p) {
+      return x.toExponential(p);
+    },
+    f: function(x, p) {
+      return x.toFixed(p);
+    },
+    r: function(x, p) {
+      return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
+    }
+  });
+  function d3_format_typeDefault(x) {
+    return x + "";
+  }
+  var d3_time = d3.time = {}, d3_date = Date;
+  function d3_date_utc() {
+    this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
+  }
+  d3_date_utc.prototype = {
+    getDate: function() {
+      return this._.getUTCDate();
+    },
+    getDay: function() {
+      return this._.getUTCDay();
+    },
+    getFullYear: function() {
+      return this._.getUTCFullYear();
+    },
+    getHours: function() {
+      return this._.getUTCHours();
+    },
+    getMilliseconds: function() {
+      return this._.getUTCMilliseconds();
+    },
+    getMinutes: function() {
+      return this._.getUTCMinutes();
+    },
+    getMonth: function() {
+      return this._.getUTCMonth();
+    },
+    getSeconds: function() {
+      return this._.getUTCSeconds();
+    },
+    getTime: function() {
+      return this._.getTime();
+    },
+    getTimezoneOffset: function() {
+      return 0;
+    },
+    valueOf: function() {
+      return this._.valueOf();
+    },
+    setDate: function() {
+      d3_time_prototype.setUTCDate.apply(this._, arguments);
+    },
+    setDay: function() {
+      d3_time_prototype.setUTCDay.apply(this._, arguments);
+    },
+    setFullYear: function() {
+      d3_time_prototype.setUTCFullYear.apply(this._, arguments);
+    },
+    setHours: function() {
+      d3_time_prototype.setUTCHours.apply(this._, arguments);
+    },
+    setMilliseconds: function() {
+      d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
+    },
+    setMinutes: function() {
+      d3_time_prototype.setUTCMinutes.apply(this._, arguments);
+    },
+    setMonth: function() {
+      d3_time_prototype.setUTCMonth.apply(this._, arguments);
+    },
+    setSeconds: function() {
+      d3_time_prototype.setUTCSeconds.apply(this._, arguments);
+    },
+    setTime: function() {
+      d3_time_prototype.setTime.apply(this._, arguments);
+    }
+  };
+  var d3_time_prototype = Date.prototype;
+  function d3_time_interval(local, step, number) {
+    function round(date) {
+      var d0 = local(date), d1 = offset(d0, 1);
+      return date - d0 < d1 - date ? d0 : d1;
+    }
+    function ceil(date) {
+      step(date = local(new d3_date(date - 1)), 1);
+      return date;
+    }
+    function offset(date, k) {
+      step(date = new d3_date(+date), k);
+      return date;
+    }
+    function range(t0, t1, dt) {
+      var time = ceil(t0), times = [];
+      if (dt > 1) {
+        while (time < t1) {
+          if (!(number(time) % dt)) times.push(new Date(+time));
+          step(time, 1);
+        }
+      } else {
+        while (time < t1) times.push(new Date(+time)), step(time, 1);
+      }
+      return times;
+    }
+    function range_utc(t0, t1, dt) {
+      try {
+        d3_date = d3_date_utc;
+        var utc = new d3_date_utc();
+        utc._ = t0;
+        return range(utc, t1, dt);
+      } finally {
+        d3_date = Date;
+      }
+    }
+    local.floor = local;
+    local.round = round;
+    local.ceil = ceil;
+    local.offset = offset;
+    local.range = range;
+    var utc = local.utc = d3_time_interval_utc(local);
+    utc.floor = utc;
+    utc.round = d3_time_interval_utc(round);
+    utc.ceil = d3_time_interval_utc(ceil);
+    utc.offset = d3_time_interval_utc(offset);
+    utc.range = range_utc;
+    return local;
+  }
+  function d3_time_interval_utc(method) {
+    return function(date, k) {
+      try {
+        d3_date = d3_date_utc;
+        var utc = new d3_date_utc();
+        utc._ = date;
+        return method(utc, k)._;
+      } finally {
+        d3_date = Date;
+      }
+    };
+  }
+  d3_time.year = d3_time_interval(function(date) {
+    date = d3_time.day(date);
+    date.setMonth(0, 1);
+    return date;
+  }, function(date, offset) {
+    date.setFullYear(date.getFullYear() + offset);
+  }, function(date) {
+    return date.getFullYear();
+  });
+  d3_time.years = d3_time.year.range;
+  d3_time.years.utc = d3_time.year.utc.range;
+  d3_time.day = d3_time_interval(function(date) {
+    var day = new d3_date(2e3, 0);
+    day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
+    return day;
+  }, function(date, offset) {
+    date.setDate(date.getDate() + offset);
+  }, function(date) {
+    return date.getDate() - 1;
+  });
+  d3_time.days = d3_time.day.range;
+  d3_time.days.utc = d3_time.day.utc.range;
+  d3_time.dayOfYear = function(date) {
+    var year = d3_time.year(date);
+    return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
+  };
+  [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
+    i = 7 - i;
+    var interval = d3_time[day] = d3_time_interval(function(date) {
+      (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
+      return date;
+    }, function(date, offset) {
+      date.setDate(date.getDate() + Math.floor(offset) * 7);
+    }, function(date) {
+      var day = d3_time.year(date).getDay();
+      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
+    });
+    d3_time[day + "s"] = interval.range;
+    d3_time[day + "s"].utc = interval.utc.range;
+    d3_time[day + "OfYear"] = function(date) {
+      var day = d3_time.year(date).getDay();
+      return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
+    };
+  });
+  d3_time.week = d3_time.sunday;
+  d3_time.weeks = d3_time.sunday.range;
+  d3_time.weeks.utc = d3_time.sunday.utc.range;
+  d3_time.weekOfYear = d3_time.sundayOfYear;
+  function d3_locale_timeFormat(locale) {
+    var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
+    function d3_time_format(template) {
+      var n = template.length;
+      function format(date) {
+        var string = [], i = -1, j = 0, c, p, f;
+        while (++i < n) {
+          if (template.charCodeAt(i) === 37) {
+            string.push(template.substring(j, i));
+            if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
+            if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
+            string.push(c);
+            j = i + 1;
+          }
+        }
+        string.push(template.substring(j, i));
+        return string.join("");
+      }
+      format.parse = function(string) {
+        var d = {
+          y: 1900,
+          m: 0,
+          d: 1,
+          H: 0,
+          M: 0,
+          S: 0,
+          L: 0,
+          Z: null
+        }, i = d3_time_parse(d, template, string, 0);
+        if (i != string.length) return null;
+        if ("p" in d) d.H = d.H % 12 + d.p * 12;
+        var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
+        if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) {
+          date.setFullYear(d.y, 0, 1);
+          date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
+        } else date.setFullYear(d.y, d.m, d.d);
+        date.setHours(d.H + Math.floor(d.Z / 100), d.M + d.Z % 100, d.S, d.L);
+        return localZ ? date._ : date;
+      };
+      format.toString = function() {
+        return template;
+      };
+      return format;
+    }
+    function d3_time_parse(date, template, string, j) {
+      var c, p, t, i = 0, n = template.length, m = string.length;
+      while (i < n) {
+        if (j >= m) return -1;
+        c = template.charCodeAt(i++);
+        if (c === 37) {
+          t = template.charAt(i++);
+          p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
+          if (!p || (j = p(date, string, j)) < 0) return -1;
+        } else if (c != string.charCodeAt(j++)) {
+          return -1;
+        }
+      }
+      return j;
+    }
+    d3_time_format.utc = function(template) {
+      var local = d3_time_format(template);
+      function format(date) {
+        try {
+          d3_date = d3_date_utc;
+          var utc = new d3_date();
+          utc._ = date;
+          return local(utc);
+        } finally {
+          d3_date = Date;
+        }
+      }
+      format.parse = function(string) {
+        try {
+          d3_date = d3_date_utc;
+          var date = local.parse(string);
+          return date && date._;
+        } finally {
+          d3_date = Date;
+        }
+      };
+      format.toString = local.toString;
+      return format;
+    };
+    d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
+    var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
+    locale_periods.forEach(function(p, i) {
+      d3_time_periodLookup.set(p.toLowerCase(), i);
+    });
+    var d3_time_formats = {
+      a: function(d) {
+        return locale_shortDays[d.getDay()];
+      },
+      A: function(d) {
+        return locale_days[d.getDay()];
+      },
+      b: function(d) {
+        return locale_shortMonths[d.getMonth()];
+      },
+      B: function(d) {
+        return locale_months[d.getMonth()];
+      },
+      c: d3_time_format(locale_dateTime),
+      d: function(d, p) {
+        return d3_time_formatPad(d.getDate(), p, 2);
+      },
+      e: function(d, p) {
+        return d3_time_formatPad(d.getDate(), p, 2);
+      },
+      H: function(d, p) {
+        return d3_time_formatPad(d.getHours(), p, 2);
+      },
+      I: function(d, p) {
+        return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
+      },
+      j: function(d, p) {
+        return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
+      },
+      L: function(d, p) {
+        return d3_time_formatPad(d.getMilliseconds(), p, 3);
+      },
+      m: function(d, p) {
+        return d3_time_formatPad(d.getMonth() + 1, p, 2);
+      },
+      M: function(d, p) {
+        return d3_time_formatPad(d.getMinutes(), p, 2);
+      },
+      p: function(d) {
+        return locale_periods[+(d.getHours() >= 12)];
+      },
+      S: function(d, p) {
+        return d3_time_formatPad(d.getSeconds(), p, 2);
+      },
+      U: function(d, p) {
+        return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
+      },
+      w: function(d) {
+        return d.getDay();
+      },
+      W: function(d, p) {
+        return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
+      },
+      x: d3_time_format(locale_date),
+      X: d3_time_format(locale_time),
+      y: function(d, p) {
+        return d3_time_formatPad(d.getFullYear() % 100, p, 2);
+      },
+      Y: function(d, p) {
+        return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
+      },
+      Z: d3_time_zone,
+      "%": function() {
+        return "%";
+      }
+    };
+    var d3_time_parsers = {
+      a: d3_time_parseWeekdayAbbrev,
+      A: d3_time_parseWeekday,
+      b: d3_time_parseMonthAbbrev,
+      B: d3_time_parseMonth,
+      c: d3_time_parseLocaleFull,
+      d: d3_time_parseDay,
+      e: d3_time_parseDay,
+      H: d3_time_parseHour24,
+      I: d3_time_parseHour24,
+      j: d3_time_parseDayOfYear,
+      L: d3_time_parseMilliseconds,
+      m: d3_time_parseMonthNumber,
+      M: d3_time_parseMinutes,
+      p: d3_time_parseAmPm,
+      S: d3_time_parseSeconds,
+      U: d3_time_parseWeekNumberSunday,
+      w: d3_time_parseWeekdayNumber,
+      W: d3_time_parseWeekNumberMonday,
+      x: d3_time_parseLocaleDate,
+      X: d3_time_parseLocaleTime,
+      y: d3_time_parseYear,
+      Y: d3_time_parseFullYear,
+      Z: d3_time_parseZone,
+      "%": d3_time_parseLiteralPercent
+    };
+    function d3_time_parseWeekdayAbbrev(date, string, i) {
+      d3_time_dayAbbrevRe.lastIndex = 0;
+      var n = d3_time_dayAbbrevRe.exec(string.substring(i));
+      return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseWeekday(date, string, i) {
+      d3_time_dayRe.lastIndex = 0;
+      var n = d3_time_dayRe.exec(string.substring(i));
+      return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseMonthAbbrev(date, string, i) {
+      d3_time_monthAbbrevRe.lastIndex = 0;
+      var n = d3_time_monthAbbrevRe.exec(string.substring(i));
+      return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseMonth(date, string, i) {
+      d3_time_monthRe.lastIndex = 0;
+      var n = d3_time_monthRe.exec(string.substring(i));
+      return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
+    }
+    function d3_time_parseLocaleFull(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
+    }
+    function d3_time_parseLocaleDate(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
+    }
+    function d3_time_parseLocaleTime(date, string, i) {
+      return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
+    }
+    function d3_time_parseAmPm(date, string, i) {
+      var n = d3_time_periodLookup.get(string.substring(i, i += 2).toLowerCase());
+      return n == null ? -1 : (date.p = n, i);
+    }
+    return d3_time_format;
+  }
+  var d3_time_formatPads = {
+    "-": "",
+    _: " ",
+    "0": "0"
+  }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
+  function d3_time_formatPad(value, fill, width) {
+    var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length;
+    return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
+  }
+  function d3_time_formatRe(names) {
+    return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
+  }
+  function d3_time_formatLookup(names) {
+    var map = new d3_Map(), i = -1, n = names.length;
+    while (++i < n) map.set(names[i].toLowerCase(), i);
+    return map;
+  }
+  function d3_time_parseWeekdayNumber(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 1));
+    return n ? (date.w = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseWeekNumberSunday(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i));
+    return n ? (date.U = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseWeekNumberMonday(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i));
+    return n ? (date.W = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseFullYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 4));
+    return n ? (date.y = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
+  }
+  function d3_time_parseZone(date, string, i) {
+    return /^[+-]\d{4}$/.test(string = string.substring(i, i + 5)) ? (date.Z = +string, 
+    i + 5) : -1;
+  }
+  function d3_time_expandYear(d) {
+    return d + (d > 68 ? 1900 : 2e3);
+  }
+  function d3_time_parseMonthNumber(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
+  }
+  function d3_time_parseDay(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.d = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseDayOfYear(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 3));
+    return n ? (date.j = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseHour24(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.H = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseMinutes(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.M = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseSeconds(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 2));
+    return n ? (date.S = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_parseMilliseconds(date, string, i) {
+    d3_time_numberRe.lastIndex = 0;
+    var n = d3_time_numberRe.exec(string.substring(i, i + 3));
+    return n ? (date.L = +n[0], i + n[0].length) : -1;
+  }
+  function d3_time_zone(d) {
+    var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = ~~(abs(z) / 60), zm = abs(z) % 60;
+    return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
+  }
+  function d3_time_parseLiteralPercent(date, string, i) {
+    d3_time_percentRe.lastIndex = 0;
+    var n = d3_time_percentRe.exec(string.substring(i, i + 1));
+    return n ? i + n[0].length : -1;
+  }
+  function d3_time_formatMulti(formats) {
+    var n = formats.length, i = -1;
+    while (++i < n) formats[i][0] = this(formats[i][0]);
+    return function(date) {
+      var i = 0, f = formats[i];
+      while (!f[1](date)) f = formats[++i];
+      return f[0](date);
+    };
+  }
+  d3.locale = function(locale) {
+    return {
+      numberFormat: d3_locale_numberFormat(locale),
+      timeFormat: d3_locale_timeFormat(locale)
+    };
+  };
+  var d3_locale_enUS = d3.locale({
+    decimal: ".",
+    thousands: ",",
+    grouping: [ 3 ],
+    currency: [ "$", "" ],
+    dateTime: "%a %b %e %X %Y",
+    date: "%m/%d/%Y",
+    time: "%H:%M:%S",
+    periods: [ "AM", "PM" ],
+    days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
+    shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
+    months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
+    shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
+  });
+  d3.format = d3_locale_enUS.numberFormat;
+  d3.geo = {};
+  function d3_adder() {}
+  d3_adder.prototype = {
+    s: 0,
+    t: 0,
+    add: function(y) {
+      d3_adderSum(y, this.t, d3_adderTemp);
+      d3_adderSum(d3_adderTemp.s, this.s, this);
+      if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
+    },
+    reset: function() {
+      this.s = this.t = 0;
+    },
+    valueOf: function() {
+      return this.s;
+    }
+  };
+  var d3_adderTemp = new d3_adder();
+  function d3_adderSum(a, b, o) {
+    var x = o.s = a + b, bv = x - a, av = x - bv;
+    o.t = a - av + (b - bv);
+  }
+  d3.geo.stream = function(object, listener) {
+    if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
+      d3_geo_streamObjectType[object.type](object, listener);
+    } else {
+      d3_geo_streamGeometry(object, listener);
+    }
+  };
+  function d3_geo_streamGeometry(geometry, listener) {
+    if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
+      d3_geo_streamGeometryType[geometry.type](geometry, listener);
+    }
+  }
+  var d3_geo_streamObjectType = {
+    Feature: function(feature, listener) {
+      d3_geo_streamGeometry(feature.geometry, listener);
+    },
+    FeatureCollection: function(object, listener) {
+      var features = object.features, i = -1, n = features.length;
+      while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
+    }
+  };
+  var d3_geo_streamGeometryType = {
+    Sphere: function(object, listener) {
+      listener.sphere();
+    },
+    Point: function(object, listener) {
+      object = object.coordinates;
+      listener.point(object[0], object[1], object[2]);
+    },
+    MultiPoint: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
+    },
+    LineString: function(object, listener) {
+      d3_geo_streamLine(object.coordinates, listener, 0);
+    },
+    MultiLineString: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
+    },
+    Polygon: function(object, listener) {
+      d3_geo_streamPolygon(object.coordinates, listener);
+    },
+    MultiPolygon: function(object, listener) {
+      var coordinates = object.coordinates, i = -1, n = coordinates.length;
+      while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
+    },
+    GeometryCollection: function(object, listener) {
+      var geometries = object.geometries, i = -1, n = geometries.length;
+      while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
+    }
+  };
+  function d3_geo_streamLine(coordinates, listener, closed) {
+    var i = -1, n = coordinates.length - closed, coordinate;
+    listener.lineStart();
+    while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
+    listener.lineEnd();
+  }
+  function d3_geo_streamPolygon(coordinates, listener) {
+    var i = -1, n = coordinates.length;
+    listener.polygonStart();
+    while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
+    listener.polygonEnd();
+  }
+  d3.geo.area = function(object) {
+    d3_geo_areaSum = 0;
+    d3.geo.stream(object, d3_geo_area);
+    return d3_geo_areaSum;
+  };
+  var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
+  var d3_geo_area = {
+    sphere: function() {
+      d3_geo_areaSum += 4 * π;
+    },
+    point: d3_noop,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: function() {
+      d3_geo_areaRingSum.reset();
+      d3_geo_area.lineStart = d3_geo_areaRingStart;
+    },
+    polygonEnd: function() {
+      var area = 2 * d3_geo_areaRingSum;
+      d3_geo_areaSum += area < 0 ? 4 * π + area : area;
+      d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
+    }
+  };
+  function d3_geo_areaRingStart() {
+    var λ00, φ00, λ0, cosφ0, sinφ0;
+    d3_geo_area.point = function(λ, φ) {
+      d3_geo_area.point = nextPoint;
+      λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), 
+      sinφ0 = Math.sin(φ);
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      φ = φ * d3_radians / 2 + π / 4;
+      var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
+      d3_geo_areaRingSum.add(Math.atan2(v, u));
+      λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
+    }
+    d3_geo_area.lineEnd = function() {
+      nextPoint(λ00, φ00);
+    };
+  }
+  function d3_geo_cartesian(spherical) {
+    var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
+    return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
+  }
+  function d3_geo_cartesianDot(a, b) {
+    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+  }
+  function d3_geo_cartesianCross(a, b) {
+    return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
+  }
+  function d3_geo_cartesianAdd(a, b) {
+    a[0] += b[0];
+    a[1] += b[1];
+    a[2] += b[2];
+  }
+  function d3_geo_cartesianScale(vector, k) {
+    return [ vector[0] * k, vector[1] * k, vector[2] * k ];
+  }
+  function d3_geo_cartesianNormalize(d) {
+    var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
+    d[0] /= l;
+    d[1] /= l;
+    d[2] /= l;
+  }
+  function d3_geo_spherical(cartesian) {
+    return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
+  }
+  function d3_geo_sphericalEqual(a, b) {
+    return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
+  }
+  d3.geo.bounds = function() {
+    var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
+    var bound = {
+      point: point,
+      lineStart: lineStart,
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        bound.point = ringPoint;
+        bound.lineStart = ringStart;
+        bound.lineEnd = ringEnd;
+        dλSum = 0;
+        d3_geo_area.polygonStart();
+      },
+      polygonEnd: function() {
+        d3_geo_area.polygonEnd();
+        bound.point = point;
+        bound.lineStart = lineStart;
+        bound.lineEnd = lineEnd;
+        if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
+        range[0] = λ0, range[1] = λ1;
+      }
+    };
+    function point(λ, φ) {
+      ranges.push(range = [ λ0 = λ, λ1 = λ ]);
+      if (φ < φ0) φ0 = φ;
+      if (φ > φ1) φ1 = φ;
+    }
+    function linePoint(λ, φ) {
+      var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
+      if (p0) {
+        var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
+        d3_geo_cartesianNormalize(inflection);
+        inflection = d3_geo_spherical(inflection);
+        var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
+        if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+          var φi = inflection[1] * d3_degrees;
+          if (φi > φ1) φ1 = φi;
+        } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
+          var φi = -inflection[1] * d3_degrees;
+          if (φi < φ0) φ0 = φi;
+        } else {
+          if (φ < φ0) φ0 = φ;
+          if (φ > φ1) φ1 = φ;
+        }
+        if (antimeridian) {
+          if (λ < λ_) {
+            if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+          } else {
+            if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+          }
+        } else {
+          if (λ1 >= λ0) {
+            if (λ < λ0) λ0 = λ;
+            if (λ > λ1) λ1 = λ;
+          } else {
+            if (λ > λ_) {
+              if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
+            } else {
+              if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
+            }
+          }
+        }
+      } else {
+        point(λ, φ);
+      }
+      p0 = p, λ_ = λ;
+    }
+    function lineStart() {
+      bound.point = linePoint;
+    }
+    function lineEnd() {
+      range[0] = λ0, range[1] = λ1;
+      bound.point = point;
+      p0 = null;
+    }
+    function ringPoint(λ, φ) {
+      if (p0) {
+        var dλ = λ - λ_;
+        dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
+      } else λ__ = λ, φ__ = φ;
+      d3_geo_area.point(λ, φ);
+      linePoint(λ, φ);
+    }
+    function ringStart() {
+      d3_geo_area.lineStart();
+    }
+    function ringEnd() {
+      ringPoint(λ__, φ__);
+      d3_geo_area.lineEnd();
+      if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
+      range[0] = λ0, range[1] = λ1;
+      p0 = null;
+    }
+    function angle(λ0, λ1) {
+      return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
+    }
+    function compareRanges(a, b) {
+      return a[0] - b[0];
+    }
+    function withinRange(x, range) {
+      return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
+    }
+    return function(feature) {
+      φ1 = λ1 = -(λ0 = φ0 = Infinity);
+      ranges = [];
+      d3.geo.stream(feature, bound);
+      var n = ranges.length;
+      if (n) {
+        ranges.sort(compareRanges);
+        for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
+          b = ranges[i];
+          if (withinRange(b[0], a) || withinRange(b[1], a)) {
+            if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
+            if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
+          } else {
+            merged.push(a = b);
+          }
+        }
+        var best = -Infinity, dλ;
+        for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
+          b = merged[i];
+          if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
+        }
+      }
+      ranges = range = null;
+      return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
+    };
+  }();
+  d3.geo.centroid = function(object) {
+    d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+    d3.geo.stream(object, d3_geo_centroid);
+    var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
+    if (m < ε2) {
+      x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
+      if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
+      m = x * x + y * y + z * z;
+      if (m < ε2) return [ NaN, NaN ];
+    }
+    return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
+  };
+  var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
+  var d3_geo_centroid = {
+    sphere: d3_noop,
+    point: d3_geo_centroidPoint,
+    lineStart: d3_geo_centroidLineStart,
+    lineEnd: d3_geo_centroidLineEnd,
+    polygonStart: function() {
+      d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
+    }
+  };
+  function d3_geo_centroidPoint(λ, φ) {
+    λ *= d3_radians;
+    var cosφ = Math.cos(φ *= d3_radians);
+    d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
+  }
+  function d3_geo_centroidPointXYZ(x, y, z) {
+    ++d3_geo_centroidW0;
+    d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
+    d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
+    d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
+  }
+  function d3_geo_centroidLineStart() {
+    var x0, y0, z0;
+    d3_geo_centroid.point = function(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians);
+      x0 = cosφ * Math.cos(λ);
+      y0 = cosφ * Math.sin(λ);
+      z0 = Math.sin(φ);
+      d3_geo_centroid.point = nextPoint;
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
+      d3_geo_centroidW1 += w;
+      d3_geo_centroidX1 += w * (x0 + (x0 = x));
+      d3_geo_centroidY1 += w * (y0 + (y0 = y));
+      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    }
+  }
+  function d3_geo_centroidLineEnd() {
+    d3_geo_centroid.point = d3_geo_centroidPoint;
+  }
+  function d3_geo_centroidRingStart() {
+    var λ00, φ00, x0, y0, z0;
+    d3_geo_centroid.point = function(λ, φ) {
+      λ00 = λ, φ00 = φ;
+      d3_geo_centroid.point = nextPoint;
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians);
+      x0 = cosφ * Math.cos(λ);
+      y0 = cosφ * Math.sin(λ);
+      z0 = Math.sin(φ);
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    };
+    d3_geo_centroid.lineEnd = function() {
+      nextPoint(λ00, φ00);
+      d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
+      d3_geo_centroid.point = d3_geo_centroidPoint;
+    };
+    function nextPoint(λ, φ) {
+      λ *= d3_radians;
+      var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
+      d3_geo_centroidX2 += v * cx;
+      d3_geo_centroidY2 += v * cy;
+      d3_geo_centroidZ2 += v * cz;
+      d3_geo_centroidW1 += w;
+      d3_geo_centroidX1 += w * (x0 + (x0 = x));
+      d3_geo_centroidY1 += w * (y0 + (y0 = y));
+      d3_geo_centroidZ1 += w * (z0 + (z0 = z));
+      d3_geo_centroidPointXYZ(x0, y0, z0);
+    }
+  }
+  function d3_true() {
+    return true;
+  }
+  function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
+    var subject = [], clip = [];
+    segments.forEach(function(segment) {
+      if ((n = segment.length - 1) <= 0) return;
+      var n, p0 = segment[0], p1 = segment[n];
+      if (d3_geo_sphericalEqual(p0, p1)) {
+        listener.lineStart();
+        for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
+        listener.lineEnd();
+        return;
+      }
+      var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
+      a.o = b;
+      subject.push(a);
+      clip.push(b);
+      a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
+      b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
+      a.o = b;
+      subject.push(a);
+      clip.push(b);
+    });
+    clip.sort(compare);
+    d3_geo_clipPolygonLinkCircular(subject);
+    d3_geo_clipPolygonLinkCircular(clip);
+    if (!subject.length) return;
+    for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
+      clip[i].e = entry = !entry;
+    }
+    var start = subject[0], points, point;
+    while (1) {
+      var current = start, isSubject = true;
+      while (current.v) if ((current = current.n) === start) return;
+      points = current.z;
+      listener.lineStart();
+      do {
+        current.v = current.o.v = true;
+        if (current.e) {
+          if (isSubject) {
+            for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
+          } else {
+            interpolate(current.x, current.n.x, 1, listener);
+          }
+          current = current.n;
+        } else {
+          if (isSubject) {
+            points = current.p.z;
+            for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
+          } else {
+            interpolate(current.x, current.p.x, -1, listener);
+          }
+          current = current.p;
+        }
+        current = current.o;
+        points = current.z;
+        isSubject = !isSubject;
+      } while (!current.v);
+      listener.lineEnd();
+    }
+  }
+  function d3_geo_clipPolygonLinkCircular(array) {
+    if (!(n = array.length)) return;
+    var n, i = 0, a = array[0], b;
+    while (++i < n) {
+      a.n = b = array[i];
+      b.p = a;
+      a = b;
+    }
+    a.n = b = array[0];
+    b.p = a;
+  }
+  function d3_geo_clipPolygonIntersection(point, points, other, entry) {
+    this.x = point;
+    this.z = points;
+    this.o = other;
+    this.e = entry;
+    this.v = false;
+    this.n = this.p = null;
+  }
+  function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
+    return function(rotate, listener) {
+      var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
+      var clip = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          clip.point = pointRing;
+          clip.lineStart = ringStart;
+          clip.lineEnd = ringEnd;
+          segments = [];
+          polygon = [];
+          listener.polygonStart();
+        },
+        polygonEnd: function() {
+          clip.point = point;
+          clip.lineStart = lineStart;
+          clip.lineEnd = lineEnd;
+          segments = d3.merge(segments);
+          var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
+          if (segments.length) {
+            d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
+          } else if (clipStartInside) {
+            listener.lineStart();
+            interpolate(null, null, 1, listener);
+            listener.lineEnd();
+          }
+          listener.polygonEnd();
+          segments = polygon = null;
+        },
+        sphere: function() {
+          listener.polygonStart();
+          listener.lineStart();
+          interpolate(null, null, 1, listener);
+          listener.lineEnd();
+          listener.polygonEnd();
+        }
+      };
+      function point(λ, φ) {
+        var point = rotate(λ, φ);
+        if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
+      }
+      function pointLine(λ, φ) {
+        var point = rotate(λ, φ);
+        line.point(point[0], point[1]);
+      }
+      function lineStart() {
+        clip.point = pointLine;
+        line.lineStart();
+      }
+      function lineEnd() {
+        clip.point = point;
+        line.lineEnd();
+      }
+      var segments;
+      var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygon, ring;
+      function pointRing(λ, φ) {
+        ring.push([ λ, φ ]);
+        var point = rotate(λ, φ);
+        ringListener.point(point[0], point[1]);
+      }
+      function ringStart() {
+        ringListener.lineStart();
+        ring = [];
+      }
+      function ringEnd() {
+        pointRing(ring[0][0], ring[0][1]);
+        ringListener.lineEnd();
+        var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
+        ring.pop();
+        polygon.push(ring);
+        ring = null;
+        if (!n) return;
+        if (clean & 1) {
+          segment = ringSegments[0];
+          var n = segment.length - 1, i = -1, point;
+          listener.lineStart();
+          while (++i < n) listener.point((point = segment[i])[0], point[1]);
+          listener.lineEnd();
+          return;
+        }
+        if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
+        segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
+      }
+      return clip;
+    };
+  }
+  function d3_geo_clipSegmentLength1(segment) {
+    return segment.length > 1;
+  }
+  function d3_geo_clipBufferListener() {
+    var lines = [], line;
+    return {
+      lineStart: function() {
+        lines.push(line = []);
+      },
+      point: function(λ, φ) {
+        line.push([ λ, φ ]);
+      },
+      lineEnd: d3_noop,
+      buffer: function() {
+        var buffer = lines;
+        lines = [];
+        line = null;
+        return buffer;
+      },
+      rejoin: function() {
+        if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
+      }
+    };
+  }
+  function d3_geo_clipSort(a, b) {
+    return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
+  }
+  function d3_geo_pointInPolygon(point, polygon) {
+    var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
+    d3_geo_areaRingSum.reset();
+    for (var i = 0, n = polygon.length; i < n; ++i) {
+      var ring = polygon[i], m = ring.length;
+      if (!m) continue;
+      var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
+      while (true) {
+        if (j === m) j = 0;
+        point = ring[j];
+        var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
+        d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
+        polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
+        if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
+          var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
+          d3_geo_cartesianNormalize(arc);
+          var intersection = d3_geo_cartesianCross(meridianNormal, arc);
+          d3_geo_cartesianNormalize(intersection);
+          var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
+          if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
+            winding += antimeridian ^ dλ >= 0 ? 1 : -1;
+          }
+        }
+        if (!j++) break;
+        λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
+      }
+    }
+    return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1;
+  }
+  var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
+  function d3_geo_clipAntimeridianLine(listener) {
+    var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
+    return {
+      lineStart: function() {
+        listener.lineStart();
+        clean = 1;
+      },
+      point: function(λ1, φ1) {
+        var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
+        if (abs(dλ - π) < ε) {
+          listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
+          listener.point(sλ0, φ0);
+          listener.lineEnd();
+          listener.lineStart();
+          listener.point(sλ1, φ0);
+          listener.point(λ1, φ0);
+          clean = 0;
+        } else if (sλ0 !== sλ1 && dλ >= π) {
+          if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
+          if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
+          φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
+          listener.point(sλ0, φ0);
+          listener.lineEnd();
+          listener.lineStart();
+          listener.point(sλ1, φ0);
+          clean = 0;
+        }
+        listener.point(λ0 = λ1, φ0 = φ1);
+        sλ0 = sλ1;
+      },
+      lineEnd: function() {
+        listener.lineEnd();
+        λ0 = φ0 = NaN;
+      },
+      clean: function() {
+        return 2 - clean;
+      }
+    };
+  }
+  function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
+    var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
+    return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
+  }
+  function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
+    var φ;
+    if (from == null) {
+      φ = direction * halfπ;
+      listener.point(-π, φ);
+      listener.point(0, φ);
+      listener.point(π, φ);
+      listener.point(π, 0);
+      listener.point(π, -φ);
+      listener.point(0, -φ);
+      listener.point(-π, -φ);
+      listener.point(-π, 0);
+      listener.point(-π, φ);
+    } else if (abs(from[0] - to[0]) > ε) {
+      var s = from[0] < to[0] ? π : -π;
+      φ = direction * s / 2;
+      listener.point(-s, φ);
+      listener.point(0, φ);
+      listener.point(s, φ);
+    } else {
+      listener.point(to[0], to[1]);
+    }
+  }
+  function d3_geo_clipCircle(radius) {
+    var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
+    return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
+    function visible(λ, φ) {
+      return Math.cos(λ) * Math.cos(φ) > cr;
+    }
+    function clipLine(listener) {
+      var point0, c0, v0, v00, clean;
+      return {
+        lineStart: function() {
+          v00 = v0 = false;
+          clean = 1;
+        },
+        point: function(λ, φ) {
+          var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
+          if (!point0 && (v00 = v0 = v)) listener.lineStart();
+          if (v !== v0) {
+            point2 = intersect(point0, point1);
+            if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
+              point1[0] += ε;
+              point1[1] += ε;
+              v = visible(point1[0], point1[1]);
+            }
+          }
+          if (v !== v0) {
+            clean = 0;
+            if (v) {
+              listener.lineStart();
+              point2 = intersect(point1, point0);
+              listener.point(point2[0], point2[1]);
+            } else {
+              point2 = intersect(point0, point1);
+              listener.point(point2[0], point2[1]);
+              listener.lineEnd();
+            }
+            point0 = point2;
+          } else if (notHemisphere && point0 && smallRadius ^ v) {
+            var t;
+            if (!(c & c0) && (t = intersect(point1, point0, true))) {
+              clean = 0;
+              if (smallRadius) {
+                listener.lineStart();
+                listener.point(t[0][0], t[0][1]);
+                listener.point(t[1][0], t[1][1]);
+                listener.lineEnd();
+              } else {
+                listener.point(t[1][0], t[1][1]);
+                listener.lineEnd();
+                listener.lineStart();
+                listener.point(t[0][0], t[0][1]);
+              }
+            }
+          }
+          if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
+            listener.point(point1[0], point1[1]);
+          }
+          point0 = point1, v0 = v, c0 = c;
+        },
+        lineEnd: function() {
+          if (v0) listener.lineEnd();
+          point0 = null;
+        },
+        clean: function() {
+          return clean | (v00 && v0) << 1;
+        }
+      };
+    }
+    function intersect(a, b, two) {
+      var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
+      var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
+      if (!determinant) return !two && a;
+      var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
+      d3_geo_cartesianAdd(A, B);
+      var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
+      if (t2 < 0) return;
+      var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
+      d3_geo_cartesianAdd(q, A);
+      q = d3_geo_spherical(q);
+      if (!two) return q;
+      var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
+      if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
+      var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
+      if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
+      if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
+        var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
+        d3_geo_cartesianAdd(q1, A);
+        return [ q, d3_geo_spherical(q1) ];
+      }
+    }
+    function code(λ, φ) {
+      var r = smallRadius ? radius : π - radius, code = 0;
+      if (λ < -r) code |= 1; else if (λ > r) code |= 2;
+      if (φ < -r) code |= 4; else if (φ > r) code |= 8;
+      return code;
+    }
+  }
+  function d3_geom_clipLine(x0, y0, x1, y1) {
+    return function(line) {
+      var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
+      r = x0 - ax;
+      if (!dx && r > 0) return;
+      r /= dx;
+      if (dx < 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      } else if (dx > 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      }
+      r = x1 - ax;
+      if (!dx && r < 0) return;
+      r /= dx;
+      if (dx < 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      } else if (dx > 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      }
+      r = y0 - ay;
+      if (!dy && r > 0) return;
+      r /= dy;
+      if (dy < 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      } else if (dy > 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      }
+      r = y1 - ay;
+      if (!dy && r < 0) return;
+      r /= dy;
+      if (dy < 0) {
+        if (r > t1) return;
+        if (r > t0) t0 = r;
+      } else if (dy > 0) {
+        if (r < t0) return;
+        if (r < t1) t1 = r;
+      }
+      if (t0 > 0) line.a = {
+        x: ax + t0 * dx,
+        y: ay + t0 * dy
+      };
+      if (t1 < 1) line.b = {
+        x: ax + t1 * dx,
+        y: ay + t1 * dy
+      };
+      return line;
+    };
+  }
+  var d3_geo_clipExtentMAX = 1e9;
+  d3.geo.clipExtent = function() {
+    var x0, y0, x1, y1, stream, clip, clipExtent = {
+      stream: function(output) {
+        if (stream) stream.valid = false;
+        stream = clip(output);
+        stream.valid = true;
+        return stream;
+      },
+      extent: function(_) {
+        if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+        clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
+        if (stream) stream.valid = false, stream = null;
+        return clipExtent;
+      }
+    };
+    return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
+  };
+  function d3_geo_clipExtent(x0, y0, x1, y1) {
+    return function(listener) {
+      var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
+      var clip = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          listener = bufferListener;
+          segments = [];
+          polygon = [];
+          clean = true;
+        },
+        polygonEnd: function() {
+          listener = listener_;
+          segments = d3.merge(segments);
+          var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
+          if (inside || visible) {
+            listener.polygonStart();
+            if (inside) {
+              listener.lineStart();
+              interpolate(null, null, 1, listener);
+              listener.lineEnd();
+            }
+            if (visible) {
+              d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
+            }
+            listener.polygonEnd();
+          }
+          segments = polygon = ring = null;
+        }
+      };
+      function insidePolygon(p) {
+        var wn = 0, n = polygon.length, y = p[1];
+        for (var i = 0; i < n; ++i) {
+          for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
+            b = v[j];
+            if (a[1] <= y) {
+              if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
+            } else {
+              if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
+            }
+            a = b;
+          }
+        }
+        return wn !== 0;
+      }
+      function interpolate(from, to, direction, listener) {
+        var a = 0, a1 = 0;
+        if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
+          do {
+            listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
+          } while ((a = (a + direction + 4) % 4) !== a1);
+        } else {
+          listener.point(to[0], to[1]);
+        }
+      }
+      function pointVisible(x, y) {
+        return x0 <= x && x <= x1 && y0 <= y && y <= y1;
+      }
+      function point(x, y) {
+        if (pointVisible(x, y)) listener.point(x, y);
+      }
+      var x__, y__, v__, x_, y_, v_, first, clean;
+      function lineStart() {
+        clip.point = linePoint;
+        if (polygon) polygon.push(ring = []);
+        first = true;
+        v_ = false;
+        x_ = y_ = NaN;
+      }
+      function lineEnd() {
+        if (segments) {
+          linePoint(x__, y__);
+          if (v__ && v_) bufferListener.rejoin();
+          segments.push(bufferListener.buffer());
+        }
+        clip.point = point;
+        if (v_) listener.lineEnd();
+      }
+      function linePoint(x, y) {
+        x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
+        y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
+        var v = pointVisible(x, y);
+        if (polygon) ring.push([ x, y ]);
+        if (first) {
+          x__ = x, y__ = y, v__ = v;
+          first = false;
+          if (v) {
+            listener.lineStart();
+            listener.point(x, y);
+          }
+        } else {
+          if (v && v_) listener.point(x, y); else {
+            var l = {
+              a: {
+                x: x_,
+                y: y_
+              },
+              b: {
+                x: x,
+                y: y
+              }
+            };
+            if (clipLine(l)) {
+              if (!v_) {
+                listener.lineStart();
+                listener.point(l.a.x, l.a.y);
+              }
+              listener.point(l.b.x, l.b.y);
+              if (!v) listener.lineEnd();
+              clean = false;
+            } else if (v) {
+              listener.lineStart();
+              listener.point(x, y);
+              clean = false;
+            }
+          }
+        }
+        x_ = x, y_ = y, v_ = v;
+      }
+      return clip;
+    };
+    function corner(p, direction) {
+      return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
+    }
+    function compare(a, b) {
+      return comparePoints(a.x, b.x);
+    }
+    function comparePoints(a, b) {
+      var ca = corner(a, 1), cb = corner(b, 1);
+      return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
+    }
+  }
+  function d3_geo_compose(a, b) {
+    function compose(x, y) {
+      return x = a(x, y), b(x[0], x[1]);
+    }
+    if (a.invert && b.invert) compose.invert = function(x, y) {
+      return x = b.invert(x, y), x && a.invert(x[0], x[1]);
+    };
+    return compose;
+  }
+  function d3_geo_conic(projectAt) {
+    var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
+    p.parallels = function(_) {
+      if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
+      return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
+    };
+    return p;
+  }
+  function d3_geo_conicEqualArea(φ0, φ1) {
+    var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
+    function forward(λ, φ) {
+      var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
+      return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = ρ0 - y;
+      return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
+    };
+    return forward;
+  }
+  (d3.geo.conicEqualArea = function() {
+    return d3_geo_conic(d3_geo_conicEqualArea);
+  }).raw = d3_geo_conicEqualArea;
+  d3.geo.albers = function() {
+    return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
+  };
+  d3.geo.albersUsa = function() {
+    var lower48 = d3.geo.albers();
+    var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
+    var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
+    var point, pointStream = {
+      point: function(x, y) {
+        point = [ x, y ];
+      }
+    }, lower48Point, alaskaPoint, hawaiiPoint;
+    function albersUsa(coordinates) {
+      var x = coordinates[0], y = coordinates[1];
+      point = null;
+      (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
+      return point;
+    }
+    albersUsa.invert = function(coordinates) {
+      var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
+      return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
+    };
+    albersUsa.stream = function(stream) {
+      var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
+      return {
+        point: function(x, y) {
+          lower48Stream.point(x, y);
+          alaskaStream.point(x, y);
+          hawaiiStream.point(x, y);
+        },
+        sphere: function() {
+          lower48Stream.sphere();
+          alaskaStream.sphere();
+          hawaiiStream.sphere();
+        },
+        lineStart: function() {
+          lower48Stream.lineStart();
+          alaskaStream.lineStart();
+          hawaiiStream.lineStart();
+        },
+        lineEnd: function() {
+          lower48Stream.lineEnd();
+          alaskaStream.lineEnd();
+          hawaiiStream.lineEnd();
+        },
+        polygonStart: function() {
+          lower48Stream.polygonStart();
+          alaskaStream.polygonStart();
+          hawaiiStream.polygonStart();
+        },
+        polygonEnd: function() {
+          lower48Stream.polygonEnd();
+          alaskaStream.polygonEnd();
+          hawaiiStream.polygonEnd();
+        }
+      };
+    };
+    albersUsa.precision = function(_) {
+      if (!arguments.length) return lower48.precision();
+      lower48.precision(_);
+      alaska.precision(_);
+      hawaii.precision(_);
+      return albersUsa;
+    };
+    albersUsa.scale = function(_) {
+      if (!arguments.length) return lower48.scale();
+      lower48.scale(_);
+      alaska.scale(_ * .35);
+      hawaii.scale(_);
+      return albersUsa.translate(lower48.translate());
+    };
+    albersUsa.translate = function(_) {
+      if (!arguments.length) return lower48.translate();
+      var k = lower48.scale(), x = +_[0], y = +_[1];
+      lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
+      alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+      hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
+      return albersUsa;
+    };
+    return albersUsa.scale(1070);
+  };
+  var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
+    point: d3_noop,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: function() {
+      d3_geo_pathAreaPolygon = 0;
+      d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
+      d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
+    }
+  };
+  function d3_geo_pathAreaRingStart() {
+    var x00, y00, x0, y0;
+    d3_geo_pathArea.point = function(x, y) {
+      d3_geo_pathArea.point = nextPoint;
+      x00 = x0 = x, y00 = y0 = y;
+    };
+    function nextPoint(x, y) {
+      d3_geo_pathAreaPolygon += y0 * x - x0 * y;
+      x0 = x, y0 = y;
+    }
+    d3_geo_pathArea.lineEnd = function() {
+      nextPoint(x00, y00);
+    };
+  }
+  var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
+  var d3_geo_pathBounds = {
+    point: d3_geo_pathBoundsPoint,
+    lineStart: d3_noop,
+    lineEnd: d3_noop,
+    polygonStart: d3_noop,
+    polygonEnd: d3_noop
+  };
+  function d3_geo_pathBoundsPoint(x, y) {
+    if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
+    if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
+    if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
+    if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
+  }
+  function d3_geo_pathBuffer() {
+    var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
+    var stream = {
+      point: point,
+      lineStart: function() {
+        stream.point = pointLineStart;
+      },
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        stream.lineEnd = lineEndPolygon;
+      },
+      polygonEnd: function() {
+        stream.lineEnd = lineEnd;
+        stream.point = point;
+      },
+      pointRadius: function(_) {
+        pointCircle = d3_geo_pathBufferCircle(_);
+        return stream;
+      },
+      result: function() {
+        if (buffer.length) {
+          var result = buffer.join("");
+          buffer = [];
+          return result;
+        }
+      }
+    };
+    function point(x, y) {
+      buffer.push("M", x, ",", y, pointCircle);
+    }
+    function pointLineStart(x, y) {
+      buffer.push("M", x, ",", y);
+      stream.point = pointLine;
+    }
+    function pointLine(x, y) {
+      buffer.push("L", x, ",", y);
+    }
+    function lineEnd() {
+      stream.point = point;
+    }
+    function lineEndPolygon() {
+      buffer.push("Z");
+    }
+    return stream;
+  }
+  function d3_geo_pathBufferCircle(radius) {
+    return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
+  }
+  var d3_geo_pathCentroid = {
+    point: d3_geo_pathCentroidPoint,
+    lineStart: d3_geo_pathCentroidLineStart,
+    lineEnd: d3_geo_pathCentroidLineEnd,
+    polygonStart: function() {
+      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
+    },
+    polygonEnd: function() {
+      d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+      d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
+      d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
+    }
+  };
+  function d3_geo_pathCentroidPoint(x, y) {
+    d3_geo_centroidX0 += x;
+    d3_geo_centroidY0 += y;
+    ++d3_geo_centroidZ0;
+  }
+  function d3_geo_pathCentroidLineStart() {
+    var x0, y0;
+    d3_geo_pathCentroid.point = function(x, y) {
+      d3_geo_pathCentroid.point = nextPoint;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    };
+    function nextPoint(x, y) {
+      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+      d3_geo_centroidX1 += z * (x0 + x) / 2;
+      d3_geo_centroidY1 += z * (y0 + y) / 2;
+      d3_geo_centroidZ1 += z;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    }
+  }
+  function d3_geo_pathCentroidLineEnd() {
+    d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
+  }
+  function d3_geo_pathCentroidRingStart() {
+    var x00, y00, x0, y0;
+    d3_geo_pathCentroid.point = function(x, y) {
+      d3_geo_pathCentroid.point = nextPoint;
+      d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
+    };
+    function nextPoint(x, y) {
+      var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
+      d3_geo_centroidX1 += z * (x0 + x) / 2;
+      d3_geo_centroidY1 += z * (y0 + y) / 2;
+      d3_geo_centroidZ1 += z;
+      z = y0 * x - x0 * y;
+      d3_geo_centroidX2 += z * (x0 + x);
+      d3_geo_centroidY2 += z * (y0 + y);
+      d3_geo_centroidZ2 += z * 3;
+      d3_geo_pathCentroidPoint(x0 = x, y0 = y);
+    }
+    d3_geo_pathCentroid.lineEnd = function() {
+      nextPoint(x00, y00);
+    };
+  }
+  function d3_geo_pathContext(context) {
+    var pointRadius = 4.5;
+    var stream = {
+      point: point,
+      lineStart: function() {
+        stream.point = pointLineStart;
+      },
+      lineEnd: lineEnd,
+      polygonStart: function() {
+        stream.lineEnd = lineEndPolygon;
+      },
+      polygonEnd: function() {
+        stream.lineEnd = lineEnd;
+        stream.point = point;
+      },
+      pointRadius: function(_) {
+        pointRadius = _;
+        return stream;
+      },
+      result: d3_noop
+    };
+    function point(x, y) {
+      context.moveTo(x, y);
+      context.arc(x, y, pointRadius, 0, τ);
+    }
+    function pointLineStart(x, y) {
+      context.moveTo(x, y);
+      stream.point = pointLine;
+    }
+    function pointLine(x, y) {
+      context.lineTo(x, y);
+    }
+    function lineEnd() {
+      stream.point = point;
+    }
+    function lineEndPolygon() {
+      context.closePath();
+    }
+    return stream;
+  }
+  function d3_geo_resample(project) {
+    var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
+    function resample(stream) {
+      return (maxDepth ? resampleRecursive : resampleNone)(stream);
+    }
+    function resampleNone(stream) {
+      return d3_geo_transformPoint(stream, function(x, y) {
+        x = project(x, y);
+        stream.point(x[0], x[1]);
+      });
+    }
+    function resampleRecursive(stream) {
+      var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
+      var resample = {
+        point: point,
+        lineStart: lineStart,
+        lineEnd: lineEnd,
+        polygonStart: function() {
+          stream.polygonStart();
+          resample.lineStart = ringStart;
+        },
+        polygonEnd: function() {
+          stream.polygonEnd();
+          resample.lineStart = lineStart;
+        }
+      };
+      function point(x, y) {
+        x = project(x, y);
+        stream.point(x[0], x[1]);
+      }
+      function lineStart() {
+        x0 = NaN;
+        resample.point = linePoint;
+        stream.lineStart();
+      }
+      function linePoint(λ, φ) {
+        var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
+        resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
+        stream.point(x0, y0);
+      }
+      function lineEnd() {
+        resample.point = point;
+        stream.lineEnd();
+      }
+      function ringStart() {
+        lineStart();
+        resample.point = ringPoint;
+        resample.lineEnd = ringEnd;
+      }
+      function ringPoint(λ, φ) {
+        linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
+        resample.point = linePoint;
+      }
+      function ringEnd() {
+        resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
+        resample.lineEnd = lineEnd;
+        lineEnd();
+      }
+      return resample;
+    }
+    function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
+      var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
+      if (d2 > 4 * δ2 && depth--) {
+        var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
+        if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
+          resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
+          stream.point(x2, y2);
+          resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
+        }
+      }
+    }
+    resample.precision = function(_) {
+      if (!arguments.length) return Math.sqrt(δ2);
+      maxDepth = (δ2 = _ * _) > 0 && 16;
+      return resample;
+    };
+    return resample;
+  }
+  d3.geo.path = function() {
+    var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
+    function path(object) {
+      if (object) {
+        if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
+        if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
+        d3.geo.stream(object, cacheStream);
+      }
+      return contextStream.result();
+    }
+    path.area = function(object) {
+      d3_geo_pathAreaSum = 0;
+      d3.geo.stream(object, projectStream(d3_geo_pathArea));
+      return d3_geo_pathAreaSum;
+    };
+    path.centroid = function(object) {
+      d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
+      d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
+      return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
+    };
+    path.bounds = function(object) {
+      d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
+      d3.geo.stream(object, projectStream(d3_geo_pathBounds));
+      return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
+    };
+    path.projection = function(_) {
+      if (!arguments.length) return projection;
+      projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
+      return reset();
+    };
+    path.context = function(_) {
+      if (!arguments.length) return context;
+      contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
+      if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
+      return reset();
+    };
+    path.pointRadius = function(_) {
+      if (!arguments.length) return pointRadius;
+      pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
+      return path;
+    };
+    function reset() {
+      cacheStream = null;
+      return path;
+    }
+    return path.projection(d3.geo.albersUsa()).context(null);
+  };
+  function d3_geo_pathProjectStream(project) {
+    var resample = d3_geo_resample(function(x, y) {
+      return project([ x * d3_degrees, y * d3_degrees ]);
+    });
+    return function(stream) {
+      return d3_geo_projectionRadians(resample(stream));
+    };
+  }
+  d3.geo.transform = function(methods) {
+    return {
+      stream: function(stream) {
+        var transform = new d3_geo_transform(stream);
+        for (var k in methods) transform[k] = methods[k];
+        return transform;
+      }
+    };
+  };
+  function d3_geo_transform(stream) {
+    this.stream = stream;
+  }
+  d3_geo_transform.prototype = {
+    point: function(x, y) {
+      this.stream.point(x, y);
+    },
+    sphere: function() {
+      this.stream.sphere();
+    },
+    lineStart: function() {
+      this.stream.lineStart();
+    },
+    lineEnd: function() {
+      this.stream.lineEnd();
+    },
+    polygonStart: function() {
+      this.stream.polygonStart();
+    },
+    polygonEnd: function() {
+      this.stream.polygonEnd();
+    }
+  };
+  function d3_geo_transformPoint(stream, point) {
+    return {
+      point: point,
+      sphere: function() {
+        stream.sphere();
+      },
+      lineStart: function() {
+        stream.lineStart();
+      },
+      lineEnd: function() {
+        stream.lineEnd();
+      },
+      polygonStart: function() {
+        stream.polygonStart();
+      },
+      polygonEnd: function() {
+        stream.polygonEnd();
+      }
+    };
+  }
+  d3.geo.projection = d3_geo_projection;
+  d3.geo.projectionMutator = d3_geo_projectionMutator;
+  function d3_geo_projection(project) {
+    return d3_geo_projectionMutator(function() {
+      return project;
+    })();
+  }
+  function d3_geo_projectionMutator(projectAt) {
+    var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
+      x = project(x, y);
+      return [ x[0] * k + δx, δy - x[1] * k ];
+    }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
+    function projection(point) {
+      point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
+      return [ point[0] * k + δx, δy - point[1] * k ];
+    }
+    function invert(point) {
+      point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
+      return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
+    }
+    projection.stream = function(output) {
+      if (stream) stream.valid = false;
+      stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
+      stream.valid = true;
+      return stream;
+    };
+    projection.clipAngle = function(_) {
+      if (!arguments.length) return clipAngle;
+      preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
+      return invalidate();
+    };
+    projection.clipExtent = function(_) {
+      if (!arguments.length) return clipExtent;
+      clipExtent = _;
+      postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
+      return invalidate();
+    };
+    projection.scale = function(_) {
+      if (!arguments.length) return k;
+      k = +_;
+      return reset();
+    };
+    projection.translate = function(_) {
+      if (!arguments.length) return [ x, y ];
+      x = +_[0];
+      y = +_[1];
+      return reset();
+    };
+    projection.center = function(_) {
+      if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
+      λ = _[0] % 360 * d3_radians;
+      φ = _[1] % 360 * d3_radians;
+      return reset();
+    };
+    projection.rotate = function(_) {
+      if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
+      δλ = _[0] % 360 * d3_radians;
+      δφ = _[1] % 360 * d3_radians;
+      δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
+      return reset();
+    };
+    d3.rebind(projection, projectResample, "precision");
+    function reset() {
+      projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
+      var center = project(λ, φ);
+      δx = x - center[0] * k;
+      δy = y + center[1] * k;
+      return invalidate();
+    }
+    function invalidate() {
+      if (stream) stream.valid = false, stream = null;
+      return projection;
+    }
+    return function() {
+      project = projectAt.apply(this, arguments);
+      projection.invert = project.invert && invert;
+      return reset();
+    };
+  }
+  function d3_geo_projectionRadians(stream) {
+    return d3_geo_transformPoint(stream, function(x, y) {
+      stream.point(x * d3_radians, y * d3_radians);
+    });
+  }
+  function d3_geo_equirectangular(λ, φ) {
+    return [ λ, φ ];
+  }
+  (d3.geo.equirectangular = function() {
+    return d3_geo_projection(d3_geo_equirectangular);
+  }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
+  d3.geo.rotation = function(rotate) {
+    rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
+    function forward(coordinates) {
+      coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+    }
+    forward.invert = function(coordinates) {
+      coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
+      return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
+    };
+    return forward;
+  };
+  function d3_geo_identityRotation(λ, φ) {
+    return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
+  }
+  d3_geo_identityRotation.invert = d3_geo_equirectangular;
+  function d3_geo_rotation(δλ, δφ, δγ) {
+    return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
+  }
+  function d3_geo_forwardRotationλ(δλ) {
+    return function(λ, φ) {
+      return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
+    };
+  }
+  function d3_geo_rotationλ(δλ) {
+    var rotation = d3_geo_forwardRotationλ(δλ);
+    rotation.invert = d3_geo_forwardRotationλ(-δλ);
+    return rotation;
+  }
+  function d3_geo_rotationφγ(δφ, δγ) {
+    var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
+    function rotation(λ, φ) {
+      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
+      return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
+    }
+    rotation.invert = function(λ, φ) {
+      var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
+      return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
+    };
+    return rotation;
+  }
+  d3.geo.circle = function() {
+    var origin = [ 0, 0 ], angle, precision = 6, interpolate;
+    function circle() {
+      var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
+      interpolate(null, null, 1, {
+        point: function(x, y) {
+          ring.push(x = rotate(x, y));
+          x[0] *= d3_degrees, x[1] *= d3_degrees;
+        }
+      });
+      return {
+        type: "Polygon",
+        coordinates: [ ring ]
+      };
+    }
+    circle.origin = function(x) {
+      if (!arguments.length) return origin;
+      origin = x;
+      return circle;
+    };
+    circle.angle = function(x) {
+      if (!arguments.length) return angle;
+      interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
+      return circle;
+    };
+    circle.precision = function(_) {
+      if (!arguments.length) return precision;
+      interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
+      return circle;
+    };
+    return circle.angle(90);
+  };
+  function d3_geo_circleInterpolate(radius, precision) {
+    var cr = Math.cos(radius), sr = Math.sin(radius);
+    return function(from, to, direction, listener) {
+      var step = direction * precision;
+      if (from != null) {
+        from = d3_geo_circleAngle(cr, from);
+        to = d3_geo_circleAngle(cr, to);
+        if (direction > 0 ? from < to : from > to) from += direction * τ;
+      } else {
+        from = radius + direction * τ;
+        to = radius - .5 * step;
+      }
+      for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
+        listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
+      }
+    };
+  }
+  function d3_geo_circleAngle(cr, point) {
+    var a = d3_geo_cartesian(point);
+    a[0] -= cr;
+    d3_geo_cartesianNormalize(a);
+    var angle = d3_acos(-a[1]);
+    return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
+  }
+  d3.geo.distance = function(a, b) {
+    var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
+    return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
+  };
+  d3.geo.graticule = function() {
+    var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
+    function graticule() {
+      return {
+        type: "MultiLineString",
+        coordinates: lines()
+      };
+    }
+    function lines() {
+      return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
+        return abs(x % DX) > ε;
+      }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
+        return abs(y % DY) > ε;
+      }).map(y));
+    }
+    graticule.lines = function() {
+      return lines().map(function(coordinates) {
+        return {
+          type: "LineString",
+          coordinates: coordinates
+        };
+      });
+    };
+    graticule.outline = function() {
+      return {
+        type: "Polygon",
+        coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
+      };
+    };
+    graticule.extent = function(_) {
+      if (!arguments.length) return graticule.minorExtent();
+      return graticule.majorExtent(_).minorExtent(_);
+    };
+    graticule.majorExtent = function(_) {
+      if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
+      X0 = +_[0][0], X1 = +_[1][0];
+      Y0 = +_[0][1], Y1 = +_[1][1];
+      if (X0 > X1) _ = X0, X0 = X1, X1 = _;
+      if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
+      return graticule.precision(precision);
+    };
+    graticule.minorExtent = function(_) {
+      if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
+      x0 = +_[0][0], x1 = +_[1][0];
+      y0 = +_[0][1], y1 = +_[1][1];
+      if (x0 > x1) _ = x0, x0 = x1, x1 = _;
+      if (y0 > y1) _ = y0, y0 = y1, y1 = _;
+      return graticule.precision(precision);
+    };
+    graticule.step = function(_) {
+      if (!arguments.length) return graticule.minorStep();
+      return graticule.majorStep(_).minorStep(_);
+    };
+    graticule.majorStep = function(_) {
+      if (!arguments.length) return [ DX, DY ];
+      DX = +_[0], DY = +_[1];
+      return graticule;
+    };
+    graticule.minorStep = function(_) {
+      if (!arguments.length) return [ dx, dy ];
+      dx = +_[0], dy = +_[1];
+      return graticule;
+    };
+    graticule.precision = function(_) {
+      if (!arguments.length) return precision;
+      precision = +_;
+      x = d3_geo_graticuleX(y0, y1, 90);
+      y = d3_geo_graticuleY(x0, x1, precision);
+      X = d3_geo_graticuleX(Y0, Y1, 90);
+      Y = d3_geo_graticuleY(X0, X1, precision);
+      return graticule;
+    };
+    return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
+  };
+  function d3_geo_graticuleX(y0, y1, dy) {
+    var y = d3.range(y0, y1 - ε, dy).concat(y1);
+    return function(x) {
+      return y.map(function(y) {
+        return [ x, y ];
+      });
+    };
+  }
+  function d3_geo_graticuleY(x0, x1, dx) {
+    var x = d3.range(x0, x1 - ε, dx).concat(x1);
+    return function(y) {
+      return x.map(function(x) {
+        return [ x, y ];
+      });
+    };
+  }
+  function d3_source(d) {
+    return d.source;
+  }
+  function d3_target(d) {
+    return d.target;
+  }
+  d3.geo.greatArc = function() {
+    var source = d3_source, source_, target = d3_target, target_;
+    function greatArc() {
+      return {
+        type: "LineString",
+        coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
+      };
+    }
+    greatArc.distance = function() {
+      return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
+    };
+    greatArc.source = function(_) {
+      if (!arguments.length) return source;
+      source = _, source_ = typeof _ === "function" ? null : _;
+      return greatArc;
+    };
+    greatArc.target = function(_) {
+      if (!arguments.length) return target;
+      target = _, target_ = typeof _ === "function" ? null : _;
+      return greatArc;
+    };
+    greatArc.precision = function() {
+      return arguments.length ? greatArc : 0;
+    };
+    return greatArc;
+  };
+  d3.geo.interpolate = function(source, target) {
+    return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
+  };
+  function d3_geo_interpolate(x0, y0, x1, y1) {
+    var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
+    var interpolate = d ? function(t) {
+      var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
+      return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
+    } : function() {
+      return [ x0 * d3_degrees, y0 * d3_degrees ];
+    };
+    interpolate.distance = d;
+    return interpolate;
+  }
+  d3.geo.length = function(object) {
+    d3_geo_lengthSum = 0;
+    d3.geo.stream(object, d3_geo_length);
+    return d3_geo_lengthSum;
+  };
+  var d3_geo_lengthSum;
+  var d3_geo_length = {
+    sphere: d3_noop,
+    point: d3_noop,
+    lineStart: d3_geo_lengthLineStart,
+    lineEnd: d3_noop,
+    polygonStart: d3_noop,
+    polygonEnd: d3_noop
+  };
+  function d3_geo_lengthLineStart() {
+    var λ0, sinφ0, cosφ0;
+    d3_geo_length.point = function(λ, φ) {
+      λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
+      d3_geo_length.point = nextPoint;
+    };
+    d3_geo_length.lineEnd = function() {
+      d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
+    };
+    function nextPoint(λ, φ) {
+      var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
+      d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
+      λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
+    }
+  }
+  function d3_geo_azimuthal(scale, angle) {
+    function azimuthal(λ, φ) {
+      var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
+      return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
+    }
+    azimuthal.invert = function(x, y) {
+      var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
+      return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
+    };
+    return azimuthal;
+  }
+  var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
+    return Math.sqrt(2 / (1 + cosλcosφ));
+  }, function(ρ) {
+    return 2 * Math.asin(ρ / 2);
+  });
+  (d3.geo.azimuthalEqualArea = function() {
+    return d3_geo_projection(d3_geo_azimuthalEqualArea);
+  }).raw = d3_geo_azimuthalEqualArea;
+  var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
+    var c = Math.acos(cosλcosφ);
+    return c && c / Math.sin(c);
+  }, d3_identity);
+  (d3.geo.azimuthalEquidistant = function() {
+    return d3_geo_projection(d3_geo_azimuthalEquidistant);
+  }).raw = d3_geo_azimuthalEquidistant;
+  function d3_geo_conicConformal(φ0, φ1) {
+    var cosφ0 = Math.cos(φ0), t = function(φ) {
+      return Math.tan(π / 4 + φ / 2);
+    }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
+    if (!n) return d3_geo_mercator;
+    function forward(λ, φ) {
+      if (F > 0) {
+        if (φ < -halfπ + ε) φ = -halfπ + ε;
+      } else {
+        if (φ > halfπ - ε) φ = halfπ - ε;
+      }
+      var ρ = F / Math.pow(t(φ), n);
+      return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
+      return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
+    };
+    return forward;
+  }
+  (d3.geo.conicConformal = function() {
+    return d3_geo_conic(d3_geo_conicConformal);
+  }).raw = d3_geo_conicConformal;
+  function d3_geo_conicEquidistant(φ0, φ1) {
+    var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
+    if (abs(n) < ε) return d3_geo_equirectangular;
+    function forward(λ, φ) {
+      var ρ = G - φ;
+      return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
+    }
+    forward.invert = function(x, y) {
+      var ρ0_y = G - y;
+      return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
+    };
+    return forward;
+  }
+  (d3.geo.conicEquidistant = function() {
+    return d3_geo_conic(d3_geo_conicEquidistant);
+  }).raw = d3_geo_conicEquidistant;
+  var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
+    return 1 / cosλcosφ;
+  }, Math.atan);
+  (d3.geo.gnomonic = function() {
+    return d3_geo_projection(d3_geo_gnomonic);
+  }).raw = d3_geo_gnomonic;
+  function d3_geo_mercator(λ, φ) {
+    return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
+  }
+  d3_geo_mercator.invert = function(x, y) {
+    return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
+  };
+  function d3_geo_mercatorProjection(project) {
+    var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
+    m.scale = function() {
+      var v = scale.apply(m, arguments);
+      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+    };
+    m.translate = function() {
+      var v = translate.apply(m, arguments);
+      return v === m ? clipAuto ? m.clipExtent(null) : m : v;
+    };
+    m.clipExtent = function(_) {
+      var v = clipExtent.apply(m, arguments);
+      if (v === m) {
+        if (clipAuto = _ == null) {
+          var k = π * scale(), t = translate();
+          clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
+        }
+      } else if (clipAuto) {
+        v = null;
+      }
+      return v;
+    };
+    return m.clipExtent(null);
+  }
+  (d3.geo.mercator = function() {
+    return d3_geo_mercatorProjection(d3_geo_mercator);
+  }).raw = d3_geo_mercator;
+  var d3_geo_orthographic = d3_geo_azimuthal(function() {
+    return 1;
+  }, Math.asin);
+  (d3.geo.orthographic = function() {
+    return d3_geo_projection(d3_geo_orthographic);
+  }).raw = d3_geo_orthographic;
+  var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
+    return 1 / (1 + cosλcosφ);
+  }, function(ρ) {
+    return 2 * Math.atan(ρ);
+  });
+  (d3.geo.stereographic = function() {
+    return d3_geo_projection(d3_geo_stereographic);
+  }).raw = d3_geo_stereographic;
+  function d3_geo_transverseMercator(λ, φ) {
+    return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
+  }
+  d3_geo_transverseMercator.invert = function(x, y) {
+    return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
+  };
+  (d3.geo.transverseMercator = function() {
+    var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
+    projection.center = function(_) {
+      return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ -_[1], _[0] ]);
+    };
+    projection.rotate = function(_) {
+      return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
+      [ _[0], _[1], _[2] - 90 ]);
+    };
+    return projection.rotate([ 0, 0 ]);
+  }).raw = d3_geo_transverseMercator;
+  d3.geom = {};
+  function d3_geom_pointX(d) {
+    return d[0];
+  }
+  function d3_geom_pointY(d) {
+    return d[1];
+  }
+  d3.geom.hull = function(vertices) {
+    var x = d3_geom_pointX, y = d3_geom_pointY;
+    if (arguments.length) return hull(vertices);
+    function hull(data) {
+      if (data.length < 3) return [];
+      var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
+      for (i = 0; i < n; i++) {
+        points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
+      }
+      points.sort(d3_geom_hullOrder);
+      for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
+      var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
+      var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
+      for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
+      for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
+      return polygon;
+    }
+    hull.x = function(_) {
+      return arguments.length ? (x = _, hull) : x;
+    };
+    hull.y = function(_) {
+      return arguments.length ? (y = _, hull) : y;
+    };
+    return hull;
+  };
+  function d3_geom_hullUpper(points) {
+    var n = points.length, hull = [ 0, 1 ], hs = 2;
+    for (var i = 2; i < n; i++) {
+      while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
+      hull[hs++] = i;
+    }
+    return hull.slice(0, hs);
+  }
+  function d3_geom_hullOrder(a, b) {
+    return a[0] - b[0] || a[1] - b[1];
+  }
+  d3.geom.polygon = function(coordinates) {
+    d3_subclass(coordinates, d3_geom_polygonPrototype);
+    return coordinates;
+  };
+  var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
+  d3_geom_polygonPrototype.area = function() {
+    var i = -1, n = this.length, a, b = this[n - 1], area = 0;
+    while (++i < n) {
+      a = b;
+      b = this[i];
+      area += a[1] * b[0] - a[0] * b[1];
+    }
+    return area * .5;
+  };
+  d3_geom_polygonPrototype.centroid = function(k) {
+    var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
+    if (!arguments.length) k = -1 / (6 * this.area());
+    while (++i < n) {
+      a = b;
+      b = this[i];
+      c = a[0] * b[1] - b[0] * a[1];
+      x += (a[0] + b[0]) * c;
+      y += (a[1] + b[1]) * c;
+    }
+    return [ x * k, y * k ];
+  };
+  d3_geom_polygonPrototype.clip = function(subject) {
+    var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
+    while (++i < n) {
+      input = subject.slice();
+      subject.length = 0;
+      b = this[i];
+      c = input[(m = input.length - closed) - 1];
+      j = -1;
+      while (++j < m) {
+        d = input[j];
+        if (d3_geom_polygonInside(d, a, b)) {
+          if (!d3_geom_polygonInside(c, a, b)) {
+            subject.push(d3_geom_polygonIntersect(c, d, a, b));
+          }
+          subject.push(d);
+        } else if (d3_geom_polygonInside(c, a, b)) {
+          subject.push(d3_geom_polygonIntersect(c, d, a, b));
+        }
+        c = d;
+      }
+      if (closed) subject.push(subject[0]);
+      a = b;
+    }
+    return subject;
+  };
+  function d3_geom_polygonInside(p, a, b) {
+    return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
+  }
+  function d3_geom_polygonIntersect(c, d, a, b) {
+    var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
+    return [ x1 + ua * x21, y1 + ua * y21 ];
+  }
+  function d3_geom_polygonClosed(coordinates) {
+    var a = coordinates[0], b = coordinates[coordinates.length - 1];
+    return !(a[0] - b[0] || a[1] - b[1]);
+  }
+  var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
+  function d3_geom_voronoiBeach() {
+    d3_geom_voronoiRedBlackNode(this);
+    this.edge = this.site = this.circle = null;
+  }
+  function d3_geom_voronoiCreateBeach(site) {
+    var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
+    beach.site = site;
+    return beach;
+  }
+  function d3_geom_voronoiDetachBeach(beach) {
+    d3_geom_voronoiDetachCircle(beach);
+    d3_geom_voronoiBeaches.remove(beach);
+    d3_geom_voronoiBeachPool.push(beach);
+    d3_geom_voronoiRedBlackNode(beach);
+  }
+  function d3_geom_voronoiRemoveBeach(beach) {
+    var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
+      x: x,
+      y: y
+    }, previous = beach.P, next = beach.N, disappearing = [ beach ];
+    d3_geom_voronoiDetachBeach(beach);
+    var lArc = previous;
+    while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
+      previous = lArc.P;
+      disappearing.unshift(lArc);
+      d3_geom_voronoiDetachBeach(lArc);
+      lArc = previous;
+    }
+    disappearing.unshift(lArc);
+    d3_geom_voronoiDetachCircle(lArc);
+    var rArc = next;
+    while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
+      next = rArc.N;
+      disappearing.push(rArc);
+      d3_geom_voronoiDetachBeach(rArc);
+      rArc = next;
+    }
+    disappearing.push(rArc);
+    d3_geom_voronoiDetachCircle(rArc);
+    var nArcs = disappearing.length, iArc;
+    for (iArc = 1; iArc < nArcs; ++iArc) {
+      rArc = disappearing[iArc];
+      lArc = disappearing[iArc - 1];
+      d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
+    }
+    lArc = disappearing[0];
+    rArc = disappearing[nArcs - 1];
+    rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
+    d3_geom_voronoiAttachCircle(lArc);
+    d3_geom_voronoiAttachCircle(rArc);
+  }
+  function d3_geom_voronoiAddBeach(site) {
+    var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
+    while (node) {
+      dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
+      if (dxl > ε) node = node.L; else {
+        dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
+        if (dxr > ε) {
+          if (!node.R) {
+            lArc = node;
+            break;
+          }
+          node = node.R;
+        } else {
+          if (dxl > -ε) {
+            lArc = node.P;
+            rArc = node;
+          } else if (dxr > -ε) {
+            lArc = node;
+            rArc = node.N;
+          } else {
+            lArc = rArc = node;
+          }
+          break;
+        }
+      }
+    }
+    var newArc = d3_geom_voronoiCreateBeach(site);
+    d3_geom_voronoiBeaches.insert(lArc, newArc);
+    if (!lArc && !rArc) return;
+    if (lArc === rArc) {
+      d3_geom_voronoiDetachCircle(lArc);
+      rArc = d3_geom_voronoiCreateBeach(lArc.site);
+      d3_geom_voronoiBeaches.insert(newArc, rArc);
+      newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+      d3_geom_voronoiAttachCircle(lArc);
+      d3_geom_voronoiAttachCircle(rArc);
+      return;
+    }
+    if (!rArc) {
+      newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
+      return;
+    }
+    d3_geom_voronoiDetachCircle(lArc);
+    d3_geom_voronoiDetachCircle(rArc);
+    var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
+      x: (cy * hb - by * hc) / d + ax,
+      y: (bx * hc - cx * hb) / d + ay
+    };
+    d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
+    newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
+    rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
+    d3_geom_voronoiAttachCircle(lArc);
+    d3_geom_voronoiAttachCircle(rArc);
+  }
+  function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
+    var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
+    if (!pby2) return rfocx;
+    var lArc = arc.P;
+    if (!lArc) return -Infinity;
+    site = lArc.site;
+    var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
+    if (!plby2) return lfocx;
+    var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
+    if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
+    return (rfocx + lfocx) / 2;
+  }
+  function d3_geom_voronoiRightBreakPoint(arc, directrix) {
+    var rArc = arc.N;
+    if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
+    var site = arc.site;
+    return site.y === directrix ? site.x : Infinity;
+  }
+  function d3_geom_voronoiCell(site) {
+    this.site = site;
+    this.edges = [];
+  }
+  d3_geom_voronoiCell.prototype.prepare = function() {
+    var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
+    while (iHalfEdge--) {
+      edge = halfEdges[iHalfEdge].edge;
+      if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
+    }
+    halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
+    return halfEdges.length;
+  };
+  function d3_geom_voronoiCloseCells(extent) {
+    var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
+    while (iCell--) {
+      cell = cells[iCell];
+      if (!cell || !cell.prepare()) continue;
+      halfEdges = cell.edges;
+      nHalfEdges = halfEdges.length;
+      iHalfEdge = 0;
+      while (iHalfEdge < nHalfEdges) {
+        end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
+        start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, y2 = start.y;
+        if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
+          halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
+            x: x0,
+            y: abs(x2 - x0) < ε ? y2 : y1
+          } : abs(y3 - y1) < ε && x1 - x3 > ε ? {
+            x: abs(y2 - y1) < ε ? x2 : x1,
+            y: y1
+          } : abs(x3 - x1) < ε && y3 - y0 > ε ? {
+            x: x1,
+            y: abs(x2 - x1) < ε ? y2 : y0
+          } : abs(y3 - y0) < ε && x3 - x0 > ε ? {
+            x: abs(y2 - y0) < ε ? x2 : x0,
+            y: y0
+          } : null), cell.site, null));
+          ++nHalfEdges;
+        }
+      }
+    }
+  }
+  function d3_geom_voronoiHalfEdgeOrder(a, b) {
+    return b.angle - a.angle;
+  }
+  function d3_geom_voronoiCircle() {
+    d3_geom_voronoiRedBlackNode(this);
+    this.x = this.y = this.arc = this.site = this.cy = null;
+  }
+  function d3_geom_voronoiAttachCircle(arc) {
+    var lArc = arc.P, rArc = arc.N;
+    if (!lArc || !rArc) return;
+    var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
+    if (lSite === rSite) return;
+    var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
+    var d = 2 * (ax * cy - ay * cx);
+    if (d >= -ε2) return;
+    var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
+    var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
+    circle.arc = arc;
+    circle.site = cSite;
+    circle.x = x + bx;
+    circle.y = cy + Math.sqrt(x * x + y * y);
+    circle.cy = cy;
+    arc.circle = circle;
+    var before = null, node = d3_geom_voronoiCircles._;
+    while (node) {
+      if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
+        if (node.L) node = node.L; else {
+          before = node.P;
+          break;
+        }
+      } else {
+        if (node.R) node = node.R; else {
+          before = node;
+          break;
+        }
+      }
+    }
+    d3_geom_voronoiCircles.insert(before, circle);
+    if (!before) d3_geom_voronoiFirstCircle = circle;
+  }
+  function d3_geom_voronoiDetachCircle(arc) {
+    var circle = arc.circle;
+    if (circle) {
+      if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
+      d3_geom_voronoiCircles.remove(circle);
+      d3_geom_voronoiCirclePool.push(circle);
+      d3_geom_voronoiRedBlackNode(circle);
+      arc.circle = null;
+    }
+  }
+  function d3_geom_voronoiClipEdges(extent) {
+    var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
+    while (i--) {
+      e = edges[i];
+      if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
+        e.a = e.b = null;
+        edges.splice(i, 1);
+      }
+    }
+  }
+  function d3_geom_voronoiConnectEdge(edge, extent) {
+    var vb = edge.b;
+    if (vb) return true;
+    var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
+    if (ry === ly) {
+      if (fx < x0 || fx >= x1) return;
+      if (lx > rx) {
+        if (!va) va = {
+          x: fx,
+          y: y0
+        }; else if (va.y >= y1) return;
+        vb = {
+          x: fx,
+          y: y1
+        };
+      } else {
+        if (!va) va = {
+          x: fx,
+          y: y1
+        }; else if (va.y < y0) return;
+        vb = {
+          x: fx,
+          y: y0
+        };
+      }
+    } else {
+      fm = (lx - rx) / (ry - ly);
+      fb = fy - fm * fx;
+      if (fm < -1 || fm > 1) {
+        if (lx > rx) {
+          if (!va) va = {
+            x: (y0 - fb) / fm,
+            y: y0
+          }; else if (va.y >= y1) return;
+          vb = {
+            x: (y1 - fb) / fm,
+            y: y1
+          };
+        } else {
+          if (!va) va = {
+            x: (y1 - fb) / fm,
+            y: y1
+          }; else if (va.y < y0) return;
+          vb = {
+            x: (y0 - fb) / fm,
+            y: y0
+          };
+        }
+      } else {
+        if (ly < ry) {
+          if (!va) va = {
+            x: x0,
+            y: fm * x0 + fb
+          }; else if (va.x >= x1) return;
+          vb = {
+            x: x1,
+            y: fm * x1 + fb
+          };
+        } else {
+          if (!va) va = {
+            x: x1,
+            y: fm * x1 + fb
+          }; else if (va.x < x0) return;
+          vb = {
+            x: x0,
+            y: fm * x0 + fb
+          };
+        }
+      }
+    }
+    edge.a = va;
+    edge.b = vb;
+    return true;
+  }
+  function d3_geom_voronoiEdge(lSite, rSite) {
+    this.l = lSite;
+    this.r = rSite;
+    this.a = this.b = null;
+  }
+  function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
+    var edge = new d3_geom_voronoiEdge(lSite, rSite);
+    d3_geom_voronoiEdges.push(edge);
+    if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
+    if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
+    d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
+    d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
+    return edge;
+  }
+  function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
+    var edge = new d3_geom_voronoiEdge(lSite, null);
+    edge.a = va;
+    edge.b = vb;
+    d3_geom_voronoiEdges.push(edge);
+    return edge;
+  }
+  function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
+    if (!edge.a && !edge.b) {
+      edge.a = vertex;
+      edge.l = lSite;
+      edge.r = rSite;
+    } else if (edge.l === rSite) {
+      edge.b = vertex;
+    } else {
+      edge.a = vertex;
+    }
+  }
+  function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
+    var va = edge.a, vb = edge.b;
+    this.edge = edge;
+    this.site = lSite;
+    this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
+  }
+  d3_geom_voronoiHalfEdge.prototype = {
+    start: function() {
+      return this.edge.l === this.site ? this.edge.a : this.edge.b;
+    },
+    end: function() {
+      return this.edge.l === this.site ? this.edge.b : this.edge.a;
+    }
+  };
+  function d3_geom_voronoiRedBlackTree() {
+    this._ = null;
+  }
+  function d3_geom_voronoiRedBlackNode(node) {
+    node.U = node.C = node.L = node.R = node.P = node.N = null;
+  }
+  d3_geom_voronoiRedBlackTree.prototype = {
+    insert: function(after, node) {
+      var parent, grandpa, uncle;
+      if (after) {
+        node.P = after;
+        node.N = after.N;
+        if (after.N) after.N.P = node;
+        after.N = node;
+        if (after.R) {
+          after = after.R;
+          while (after.L) after = after.L;
+          after.L = node;
+        } else {
+          after.R = node;
+        }
+        parent = after;
+      } else if (this._) {
+        after = d3_geom_voronoiRedBlackFirst(this._);
+        node.P = null;
+        node.N = after;
+        after.P = after.L = node;
+        parent = after;
+      } else {
+        node.P = node.N = null;
+        this._ = node;
+        parent = null;
+      }
+      node.L = node.R = null;
+      node.U = parent;
+      node.C = true;
+      after = node;
+      while (parent && parent.C) {
+        grandpa = parent.U;
+        if (parent === grandpa.L) {
+          uncle = grandpa.R;
+          if (uncle && uncle.C) {
+            parent.C = uncle.C = false;
+            grandpa.C = true;
+            after = grandpa;
+          } else {
+            if (after === parent.R) {
+              d3_geom_voronoiRedBlackRotateLeft(this, parent);
+              after = parent;
+              parent = after.U;
+            }
+            parent.C = false;
+            grandpa.C = true;
+            d3_geom_voronoiRedBlackRotateRight(this, grandpa);
+          }
+        } else {
+          uncle = grandpa.L;
+          if (uncle && uncle.C) {
+            parent.C = uncle.C = false;
+            grandpa.C = true;
+            after = grandpa;
+          } else {
+            if (after === parent.L) {
+              d3_geom_voronoiRedBlackRotateRight(this, parent);
+              after = parent;
+              parent = after.U;
+            }
+            parent.C = false;
+            grandpa.C = true;
+            d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
+          }
+        }
+        parent = after.U;
+      }
+      this._.C = false;
+    },
+    remove: function(node) {
+      if (node.N) node.N.P = node.P;
+      if (node.P) node.P.N = node.N;
+      node.N = node.P = null;
+      var parent = node.U, sibling, left = node.L, right = node.R, next, red;
+      if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
+      if (parent) {
+        if (parent.L === node) parent.L = next; else parent.R = next;
+      } else {
+        this._ = next;
+      }
+      if (left && right) {
+        red = next.C;
+        next.C = node.C;
+        next.L = left;
+        left.U = next;
+        if (next !== right) {
+          parent = next.U;
+          next.U = node.U;
+          node = next.R;
+          parent.L = node;
+          next.R = right;
+          right.U = next;
+        } else {
+          next.U = parent;
+          parent = next;
+          node = next.R;
+        }
+      } else {
+        red = node.C;
+        node = next;
+      }
+      if (node) node.U = parent;
+      if (red) return;
+      if (node && node.C) {
+        node.C = false;
+        return;
+      }
+      do {
+        if (node === this._) break;
+        if (node === parent.L) {
+          sibling = parent.R;
+          if (sibling.C) {
+            sibling.C = false;
+            parent.C = true;
+            d3_geom_voronoiRedBlackRotateLeft(this, parent);
+            sibling = parent.R;
+          }
+          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
+            if (!sibling.R || !sibling.R.C) {
+              sibling.L.C = false;
+              sibling.C = true;
+              d3_geom_voronoiRedBlackRotateRight(this, sibling);
+              sibling = parent.R;
+            }
+            sibling.C = parent.C;
+            parent.C = sibling.R.C = false;
+            d3_geom_voronoiRedBlackRotateLeft(this, parent);
+            node = this._;
+            break;
+          }
+        } else {
+          sibling = parent.L;
+          if (sibling.C) {
+            sibling.C = false;
+            parent.C = true;
+            d3_geom_voronoiRedBlackRotateRight(this, parent);
+            sibling = parent.L;
+          }
+          if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
+            if (!sibling.L || !sibling.L.C) {
+              sibling.R.C = false;
+              sibling.C = true;
+              d3_geom_voronoiRedBlackRotateLeft(this, sibling);
+              sibling = parent.L;
+            }
+            sibling.C = parent.C;
+            parent.C = sibling.L.C = false;
+            d3_geom_voronoiRedBlackRotateRight(this, parent);
+            node = this._;
+            break;
+          }
+        }
+        sibling.C = true;
+        node = parent;
+        parent = parent.U;
+      } while (!node.C);
+      if (node) node.C = false;
+    }
+  };
+  function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
+    var p = node, q = node.R, parent = p.U;
+    if (parent) {
+      if (parent.L === p) parent.L = q; else parent.R = q;
+    } else {
+      tree._ = q;
+    }
+    q.U = parent;
+    p.U = q;
+    p.R = q.L;
+    if (p.R) p.R.U = p;
+    q.L = p;
+  }
+  function d3_geom_voronoiRedBlackRotateRight(tree, node) {
+    var p = node, q = node.L, parent = p.U;
+    if (parent) {
+      if (parent.L === p) parent.L = q; else parent.R = q;
+    } else {
+      tree._ = q;
+    }
+    q.U = parent;
+    p.U = q;
+    p.L = q.R;
+    if (p.L) p.L.U = p;
+    q.R = p;
+  }
+  function d3_geom_voronoiRedBlackFirst(node) {
+    while (node.L) node = node.L;
+    return node;
+  }
+  function d3_geom_voronoi(sites, bbox) {
+    var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
+    d3_geom_voronoiEdges = [];
+    d3_geom_voronoiCells = new Array(sites.length);
+    d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
+    d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
+    while (true) {
+      circle = d3_geom_voronoiFirstCircle;
+      if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
+        if (site.x !== x0 || site.y !== y0) {
+          d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
+          d3_geom_voronoiAddBeach(site);
+          x0 = site.x, y0 = site.y;
+        }
+        site = sites.pop();
+      } else if (circle) {
+        d3_geom_voronoiRemoveBeach(circle.arc);
+      } else {
+        break;
+      }
+    }
+    if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
+    var diagram = {
+      cells: d3_geom_voronoiCells,
+      edges: d3_geom_voronoiEdges
+    };
+    d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
+    return diagram;
+  }
+  function d3_geom_voronoiVertexOrder(a, b) {
+    return b.y - a.y || b.x - a.x;
+  }
+  d3.geom.voronoi = function(points) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
+    if (points) return voronoi(points);
+    function voronoi(data) {
+      var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
+      d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
+        var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
+          var s = e.start();
+          return [ s.x, s.y ];
+        }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
+        polygon.point = data[i];
+      });
+      return polygons;
+    }
+    function sites(data) {
+      return data.map(function(d, i) {
+        return {
+          x: Math.round(fx(d, i) / ε) * ε,
+          y: Math.round(fy(d, i) / ε) * ε,
+          i: i
+        };
+      });
+    }
+    voronoi.links = function(data) {
+      return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
+        return edge.l && edge.r;
+      }).map(function(edge) {
+        return {
+          source: data[edge.l.i],
+          target: data[edge.r.i]
+        };
+      });
+    };
+    voronoi.triangles = function(data) {
+      var triangles = [];
+      d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
+        var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
+        while (++j < m) {
+          e0 = e1;
+          s0 = s1;
+          e1 = edges[j].edge;
+          s1 = e1.l === site ? e1.r : e1.l;
+          if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
+            triangles.push([ data[i], data[s0.i], data[s1.i] ]);
+          }
+        }
+      });
+      return triangles;
+    };
+    voronoi.x = function(_) {
+      return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
+    };
+    voronoi.y = function(_) {
+      return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
+    };
+    voronoi.clipExtent = function(_) {
+      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
+      clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
+      return voronoi;
+    };
+    voronoi.size = function(_) {
+      if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
+      return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
+    };
+    return voronoi;
+  };
+  var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
+  function d3_geom_voronoiTriangleArea(a, b, c) {
+    return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
+  }
+  d3.geom.delaunay = function(vertices) {
+    return d3.geom.voronoi().triangles(vertices);
+  };
+  d3.geom.quadtree = function(points, x1, y1, x2, y2) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, compat;
+    if (compat = arguments.length) {
+      x = d3_geom_quadtreeCompatX;
+      y = d3_geom_quadtreeCompatY;
+      if (compat === 3) {
+        y2 = y1;
+        x2 = x1;
+        y1 = x1 = 0;
+      }
+      return quadtree(points);
+    }
+    function quadtree(data) {
+      var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
+      if (x1 != null) {
+        x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
+      } else {
+        x2_ = y2_ = -(x1_ = y1_ = Infinity);
+        xs = [], ys = [];
+        n = data.length;
+        if (compat) for (i = 0; i < n; ++i) {
+          d = data[i];
+          if (d.x < x1_) x1_ = d.x;
+          if (d.y < y1_) y1_ = d.y;
+          if (d.x > x2_) x2_ = d.x;
+          if (d.y > y2_) y2_ = d.y;
+          xs.push(d.x);
+          ys.push(d.y);
+        } else for (i = 0; i < n; ++i) {
+          var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
+          if (x_ < x1_) x1_ = x_;
+          if (y_ < y1_) y1_ = y_;
+          if (x_ > x2_) x2_ = x_;
+          if (y_ > y2_) y2_ = y_;
+          xs.push(x_);
+          ys.push(y_);
+        }
+      }
+      var dx = x2_ - x1_, dy = y2_ - y1_;
+      if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
+      function insert(n, d, x, y, x1, y1, x2, y2) {
+        if (isNaN(x) || isNaN(y)) return;
+        if (n.leaf) {
+          var nx = n.x, ny = n.y;
+          if (nx != null) {
+            if (abs(nx - x) + abs(ny - y) < .01) {
+              insertChild(n, d, x, y, x1, y1, x2, y2);
+            } else {
+              var nPoint = n.point;
+              n.x = n.y = n.point = null;
+              insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
+              insertChild(n, d, x, y, x1, y1, x2, y2);
+            }
+          } else {
+            n.x = x, n.y = y, n.point = d;
+          }
+        } else {
+          insertChild(n, d, x, y, x1, y1, x2, y2);
+        }
+      }
+      function insertChild(n, d, x, y, x1, y1, x2, y2) {
+        var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, right = x >= sx, bottom = y >= sy, i = (bottom << 1) + right;
+        n.leaf = false;
+        n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
+        if (right) x1 = sx; else x2 = sx;
+        if (bottom) y1 = sy; else y2 = sy;
+        insert(n, d, x, y, x1, y1, x2, y2);
+      }
+      var root = d3_geom_quadtreeNode();
+      root.add = function(d) {
+        insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
+      };
+      root.visit = function(f) {
+        d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
+      };
+      i = -1;
+      if (x1 == null) {
+        while (++i < n) {
+          insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
+        }
+        --i;
+      } else data.forEach(root.add);
+      xs = ys = data = d = null;
+      return root;
+    }
+    quadtree.x = function(_) {
+      return arguments.length ? (x = _, quadtree) : x;
+    };
+    quadtree.y = function(_) {
+      return arguments.length ? (y = _, quadtree) : y;
+    };
+    quadtree.extent = function(_) {
+      if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
+      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], x2 = +_[1][0], 
+      y2 = +_[1][1];
+      return quadtree;
+    };
+    quadtree.size = function(_) {
+      if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
+      if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], y2 = +_[1];
+      return quadtree;
+    };
+    return quadtree;
+  };
+  function d3_geom_quadtreeCompatX(d) {
+    return d.x;
+  }
+  function d3_geom_quadtreeCompatY(d) {
+    return d.y;
+  }
+  function d3_geom_quadtreeNode() {
+    return {
+      leaf: true,
+      nodes: [],
+      point: null,
+      x: null,
+      y: null
+    };
+  }
+  function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
+    if (!f(node, x1, y1, x2, y2)) {
+      var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
+      if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
+      if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
+      if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
+      if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
+    }
+  }
+  d3.interpolateRgb = d3_interpolateRgb;
+  function d3_interpolateRgb(a, b) {
+    a = d3.rgb(a);
+    b = d3.rgb(b);
+    var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
+    return function(t) {
+      return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
+    };
+  }
+  d3.interpolateObject = d3_interpolateObject;
+  function d3_interpolateObject(a, b) {
+    var i = {}, c = {}, k;
+    for (k in a) {
+      if (k in b) {
+        i[k] = d3_interpolate(a[k], b[k]);
+      } else {
+        c[k] = a[k];
+      }
+    }
+    for (k in b) {
+      if (!(k in a)) {
+        c[k] = b[k];
+      }
+    }
+    return function(t) {
+      for (k in i) c[k] = i[k](t);
+      return c;
+    };
+  }
+  d3.interpolateNumber = d3_interpolateNumber;
+  function d3_interpolateNumber(a, b) {
+    b -= a = +a;
+    return function(t) {
+      return a + b * t;
+    };
+  }
+  d3.interpolateString = d3_interpolateString;
+  function d3_interpolateString(a, b) {
+    var m, i, j, s0 = 0, s1 = 0, s = [], q = [], n, o;
+    a = a + "", b = b + "";
+    d3_interpolate_number.lastIndex = 0;
+    for (i = 0; m = d3_interpolate_number.exec(b); ++i) {
+      if (m.index) s.push(b.substring(s0, s1 = m.index));
+      q.push({
+        i: s.length,
+        x: m[0]
+      });
+      s.push(null);
+      s0 = d3_interpolate_number.lastIndex;
+    }
+    if (s0 < b.length) s.push(b.substring(s0));
+    for (i = 0, n = q.length; (m = d3_interpolate_number.exec(a)) && i < n; ++i) {
+      o = q[i];
+      if (o.x == m[0]) {
+        if (o.i) {
+          if (s[o.i + 1] == null) {
+            s[o.i - 1] += o.x;
+            s.splice(o.i, 1);
+            for (j = i + 1; j < n; ++j) q[j].i--;
+          } else {
+            s[o.i - 1] += o.x + s[o.i + 1];
+            s.splice(o.i, 2);
+            for (j = i + 1; j < n; ++j) q[j].i -= 2;
+          }
+        } else {
+          if (s[o.i + 1] == null) {
+            s[o.i] = o.x;
+          } else {
+            s[o.i] = o.x + s[o.i + 1];
+            s.splice(o.i + 1, 1);
+            for (j = i + 1; j < n; ++j) q[j].i--;
+          }
+        }
+        q.splice(i, 1);
+        n--;
+        i--;
+      } else {
+        o.x = d3_interpolateNumber(parseFloat(m[0]), parseFloat(o.x));
+      }
+    }
+    while (i < n) {
+      o = q.pop();
+      if (s[o.i + 1] == null) {
+        s[o.i] = o.x;
+      } else {
+        s[o.i] = o.x + s[o.i + 1];
+        s.splice(o.i + 1, 1);
+      }
+      n--;
+    }
+    if (s.length === 1) {
+      return s[0] == null ? (o = q[0].x, function(t) {
+        return o(t) + "";
+      }) : function() {
+        return b;
+      };
+    }
+    return function(t) {
+      for (i = 0; i < n; ++i) s[(o = q[i]).i] = o.x(t);
+      return s.join("");
+    };
+  }
+  var d3_interpolate_number = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
+  d3.interpolate = d3_interpolate;
+  function d3_interpolate(a, b) {
+    var i = d3.interpolators.length, f;
+    while (--i >= 0 && !(f = d3.interpolators[i](a, b))) ;
+    return f;
+  }
+  d3.interpolators = [ function(a, b) {
+    var t = typeof b;
+    return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_Color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
+  } ];
+  d3.interpolateArray = d3_interpolateArray;
+  function d3_interpolateArray(a, b) {
+    var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
+    for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
+    for (;i < na; ++i) c[i] = a[i];
+    for (;i < nb; ++i) c[i] = b[i];
+    return function(t) {
+      for (i = 0; i < n0; ++i) c[i] = x[i](t);
+      return c;
+    };
+  }
+  var d3_ease_default = function() {
+    return d3_identity;
+  };
+  var d3_ease = d3.map({
+    linear: d3_ease_default,
+    poly: d3_ease_poly,
+    quad: function() {
+      return d3_ease_quad;
+    },
+    cubic: function() {
+      return d3_ease_cubic;
+    },
+    sin: function() {
+      return d3_ease_sin;
+    },
+    exp: function() {
+      return d3_ease_exp;
+    },
+    circle: function() {
+      return d3_ease_circle;
+    },
+    elastic: d3_ease_elastic,
+    back: d3_ease_back,
+    bounce: function() {
+      return d3_ease_bounce;
+    }
+  });
+  var d3_ease_mode = d3.map({
+    "in": d3_identity,
+    out: d3_ease_reverse,
+    "in-out": d3_ease_reflect,
+    "out-in": function(f) {
+      return d3_ease_reflect(d3_ease_reverse(f));
+    }
+  });
+  d3.ease = function(name) {
+    var i = name.indexOf("-"), t = i >= 0 ? name.substring(0, i) : name, m = i >= 0 ? name.substring(i + 1) : "in";
+    t = d3_ease.get(t) || d3_ease_default;
+    m = d3_ease_mode.get(m) || d3_identity;
+    return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
+  };
+  function d3_ease_clamp(f) {
+    return function(t) {
+      return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
+    };
+  }
+  function d3_ease_reverse(f) {
+    return function(t) {
+      return 1 - f(1 - t);
+    };
+  }
+  function d3_ease_reflect(f) {
+    return function(t) {
+      return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
+    };
+  }
+  function d3_ease_quad(t) {
+    return t * t;
+  }
+  function d3_ease_cubic(t) {
+    return t * t * t;
+  }
+  function d3_ease_cubicInOut(t) {
+    if (t <= 0) return 0;
+    if (t >= 1) return 1;
+    var t2 = t * t, t3 = t2 * t;
+    return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
+  }
+  function d3_ease_poly(e) {
+    return function(t) {
+      return Math.pow(t, e);
+    };
+  }
+  function d3_ease_sin(t) {
+    return 1 - Math.cos(t * halfπ);
+  }
+  function d3_ease_exp(t) {
+    return Math.pow(2, 10 * (t - 1));
+  }
+  function d3_ease_circle(t) {
+    return 1 - Math.sqrt(1 - t * t);
+  }
+  function d3_ease_elastic(a, p) {
+    var s;
+    if (arguments.length < 2) p = .45;
+    if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
+    return function(t) {
+      return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
+    };
+  }
+  function d3_ease_back(s) {
+    if (!s) s = 1.70158;
+    return function(t) {
+      return t * t * ((s + 1) * t - s);
+    };
+  }
+  function d3_ease_bounce(t) {
+    return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
+  }
+  d3.interpolateHcl = d3_interpolateHcl;
+  function d3_interpolateHcl(a, b) {
+    a = d3.hcl(a);
+    b = d3.hcl(b);
+    var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
+    if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
+    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+    return function(t) {
+      return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
+    };
+  }
+  d3.interpolateHsl = d3_interpolateHsl;
+  function d3_interpolateHsl(a, b) {
+    a = d3.hsl(a);
+    b = d3.hsl(b);
+    var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
+    if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
+    if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
+    return function(t) {
+      return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
+    };
+  }
+  d3.interpolateLab = d3_interpolateLab;
+  function d3_interpolateLab(a, b) {
+    a = d3.lab(a);
+    b = d3.lab(b);
+    var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
+    return function(t) {
+      return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
+    };
+  }
+  d3.interpolateRound = d3_interpolateRound;
+  function d3_interpolateRound(a, b) {
+    b -= a;
+    return function(t) {
+      return Math.round(a + b * t);
+    };
+  }
+  d3.transform = function(string) {
+    var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
+    return (d3.transform = function(string) {
+      if (string != null) {
+        g.setAttribute("transform", string);
+        var t = g.transform.baseVal.consolidate();
+      }
+      return new d3_transform(t ? t.matrix : d3_transformIdentity);
+    })(string);
+  };
+  function d3_transform(m) {
+    var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
+    if (r0[0] * r1[1] < r1[0] * r0[1]) {
+      r0[0] *= -1;
+      r0[1] *= -1;
+      kx *= -1;
+      kz *= -1;
+    }
+    this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
+    this.translate = [ m.e, m.f ];
+    this.scale = [ kx, ky ];
+    this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
+  }
+  d3_transform.prototype.toString = function() {
+    return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
+  };
+  function d3_transformDot(a, b) {
+    return a[0] * b[0] + a[1] * b[1];
+  }
+  function d3_transformNormalize(a) {
+    var k = Math.sqrt(d3_transformDot(a, a));
+    if (k) {
+      a[0] /= k;
+      a[1] /= k;
+    }
+    return k;
+  }
+  function d3_transformCombine(a, b, k) {
+    a[0] += k * b[0];
+    a[1] += k * b[1];
+    return a;
+  }
+  var d3_transformIdentity = {
+    a: 1,
+    b: 0,
+    c: 0,
+    d: 1,
+    e: 0,
+    f: 0
+  };
+  d3.interpolateTransform = d3_interpolateTransform;
+  function d3_interpolateTransform(a, b) {
+    var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
+    if (ta[0] != tb[0] || ta[1] != tb[1]) {
+      s.push("translate(", null, ",", null, ")");
+      q.push({
+        i: 1,
+        x: d3_interpolateNumber(ta[0], tb[0])
+      }, {
+        i: 3,
+        x: d3_interpolateNumber(ta[1], tb[1])
+      });
+    } else if (tb[0] || tb[1]) {
+      s.push("translate(" + tb + ")");
+    } else {
+      s.push("");
+    }
+    if (ra != rb) {
+      if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
+      q.push({
+        i: s.push(s.pop() + "rotate(", null, ")") - 2,
+        x: d3_interpolateNumber(ra, rb)
+      });
+    } else if (rb) {
+      s.push(s.pop() + "rotate(" + rb + ")");
+    }
+    if (wa != wb) {
+      q.push({
+        i: s.push(s.pop() + "skewX(", null, ")") - 2,
+        x: d3_interpolateNumber(wa, wb)
+      });
+    } else if (wb) {
+      s.push(s.pop() + "skewX(" + wb + ")");
+    }
+    if (ka[0] != kb[0] || ka[1] != kb[1]) {
+      n = s.push(s.pop() + "scale(", null, ",", null, ")");
+      q.push({
+        i: n - 4,
+        x: d3_interpolateNumber(ka[0], kb[0])
+      }, {
+        i: n - 2,
+        x: d3_interpolateNumber(ka[1], kb[1])
+      });
+    } else if (kb[0] != 1 || kb[1] != 1) {
+      s.push(s.pop() + "scale(" + kb + ")");
+    }
+    n = q.length;
+    return function(t) {
+      var i = -1, o;
+      while (++i < n) s[(o = q[i]).i] = o.x(t);
+      return s.join("");
+    };
+  }
+  function d3_uninterpolateNumber(a, b) {
+    b = b - (a = +a) ? 1 / (b - a) : 0;
+    return function(x) {
+      return (x - a) * b;
+    };
+  }
+  function d3_uninterpolateClamp(a, b) {
+    b = b - (a = +a) ? 1 / (b - a) : 0;
+    return function(x) {
+      return Math.max(0, Math.min(1, (x - a) * b));
+    };
+  }
+  d3.layout = {};
+  d3.layout.bundle = function() {
+    return function(links) {
+      var paths = [], i = -1, n = links.length;
+      while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
+      return paths;
+    };
+  };
+  function d3_layout_bundlePath(link) {
+    var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
+    while (start !== lca) {
+      start = start.parent;
+      points.push(start);
+    }
+    var k = points.length;
+    while (end !== lca) {
+      points.splice(k, 0, end);
+      end = end.parent;
+    }
+    return points;
+  }
+  function d3_layout_bundleAncestors(node) {
+    var ancestors = [], parent = node.parent;
+    while (parent != null) {
+      ancestors.push(node);
+      node = parent;
+      parent = parent.parent;
+    }
+    ancestors.push(node);
+    return ancestors;
+  }
+  function d3_layout_bundleLeastCommonAncestor(a, b) {
+    if (a === b) return a;
+    var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
+    while (aNode === bNode) {
+      sharedNode = aNode;
+      aNode = aNodes.pop();
+      bNode = bNodes.pop();
+    }
+    return sharedNode;
+  }
+  d3.layout.chord = function() {
+    var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
+    function relayout() {
+      var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
+      chords = [];
+      groups = [];
+      k = 0, i = -1;
+      while (++i < n) {
+        x = 0, j = -1;
+        while (++j < n) {
+          x += matrix[i][j];
+        }
+        groupSums.push(x);
+        subgroupIndex.push(d3.range(n));
+        k += x;
+      }
+      if (sortGroups) {
+        groupIndex.sort(function(a, b) {
+          return sortGroups(groupSums[a], groupSums[b]);
+        });
+      }
+      if (sortSubgroups) {
+        subgroupIndex.forEach(function(d, i) {
+          d.sort(function(a, b) {
+            return sortSubgroups(matrix[i][a], matrix[i][b]);
+          });
+        });
+      }
+      k = (τ - padding * n) / k;
+      x = 0, i = -1;
+      while (++i < n) {
+        x0 = x, j = -1;
+        while (++j < n) {
+          var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
+          subgroups[di + "-" + dj] = {
+            index: di,
+            subindex: dj,
+            startAngle: a0,
+            endAngle: a1,
+            value: v
+          };
+        }
+        groups[di] = {
+          index: di,
+          startAngle: x0,
+          endAngle: x,
+          value: (x - x0) / k
+        };
+        x += padding;
+      }
+      i = -1;
+      while (++i < n) {
+        j = i - 1;
+        while (++j < n) {
+          var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
+          if (source.value || target.value) {
+            chords.push(source.value < target.value ? {
+              source: target,
+              target: source
+            } : {
+              source: source,
+              target: target
+            });
+          }
+        }
+      }
+      if (sortChords) resort();
+    }
+    function resort() {
+      chords.sort(function(a, b) {
+        return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
+      });
+    }
+    chord.matrix = function(x) {
+      if (!arguments.length) return matrix;
+      n = (matrix = x) && matrix.length;
+      chords = groups = null;
+      return chord;
+    };
+    chord.padding = function(x) {
+      if (!arguments.length) return padding;
+      padding = x;
+      chords = groups = null;
+      return chord;
+    };
+    chord.sortGroups = function(x) {
+      if (!arguments.length) return sortGroups;
+      sortGroups = x;
+      chords = groups = null;
+      return chord;
+    };
+    chord.sortSubgroups = function(x) {
+      if (!arguments.length) return sortSubgroups;
+      sortSubgroups = x;
+      chords = null;
+      return chord;
+    };
+    chord.sortChords = function(x) {
+      if (!arguments.length) return sortChords;
+      sortChords = x;
+      if (chords) resort();
+      return chord;
+    };
+    chord.chords = function() {
+      if (!chords) relayout();
+      return chords;
+    };
+    chord.groups = function() {
+      if (!groups) relayout();
+      return groups;
+    };
+    return chord;
+  };
+  d3.layout.force = function() {
+    var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
+    function repulse(node) {
+      return function(quad, x1, _, x2) {
+        if (quad.point !== node) {
+          var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
+          if (dw * dw / theta2 < dn) {
+            if (dn < chargeDistance2) {
+              var k = quad.charge / dn;
+              node.px -= dx * k;
+              node.py -= dy * k;
+            }
+            return true;
+          }
+          if (quad.point && dn && dn < chargeDistance2) {
+            var k = quad.pointCharge / dn;
+            node.px -= dx * k;
+            node.py -= dy * k;
+          }
+        }
+        return !quad.charge;
+      };
+    }
+    force.tick = function() {
+      if ((alpha *= .99) < .005) {
+        event.end({
+          type: "end",
+          alpha: alpha = 0
+        });
+        return true;
+      }
+      var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
+      for (i = 0; i < m; ++i) {
+        o = links[i];
+        s = o.source;
+        t = o.target;
+        x = t.x - s.x;
+        y = t.y - s.y;
+        if (l = x * x + y * y) {
+          l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
+          x *= l;
+          y *= l;
+          t.x -= x * (k = s.weight / (t.weight + s.weight));
+          t.y -= y * k;
+          s.x += x * (k = 1 - k);
+          s.y += y * k;
+        }
+      }
+      if (k = alpha * gravity) {
+        x = size[0] / 2;
+        y = size[1] / 2;
+        i = -1;
+        if (k) while (++i < n) {
+          o = nodes[i];
+          o.x += (x - o.x) * k;
+          o.y += (y - o.y) * k;
+        }
+      }
+      if (charge) {
+        d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
+        i = -1;
+        while (++i < n) {
+          if (!(o = nodes[i]).fixed) {
+            q.visit(repulse(o));
+          }
+        }
+      }
+      i = -1;
+      while (++i < n) {
+        o = nodes[i];
+        if (o.fixed) {
+          o.x = o.px;
+          o.y = o.py;
+        } else {
+          o.x -= (o.px - (o.px = o.x)) * friction;
+          o.y -= (o.py - (o.py = o.y)) * friction;
+        }
+      }
+      event.tick({
+        type: "tick",
+        alpha: alpha
+      });
+    };
+    force.nodes = function(x) {
+      if (!arguments.length) return nodes;
+      nodes = x;
+      return force;
+    };
+    force.links = function(x) {
+      if (!arguments.length) return links;
+      links = x;
+      return force;
+    };
+    force.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return force;
+    };
+    force.linkDistance = function(x) {
+      if (!arguments.length) return linkDistance;
+      linkDistance = typeof x === "function" ? x : +x;
+      return force;
+    };
+    force.distance = force.linkDistance;
+    force.linkStrength = function(x) {
+      if (!arguments.length) return linkStrength;
+      linkStrength = typeof x === "function" ? x : +x;
+      return force;
+    };
+    force.friction = function(x) {
+      if (!arguments.length) return friction;
+      friction = +x;
+      return force;
+    };
+    force.charge = function(x) {
+      if (!arguments.length) return charge;
+      charge = typeof x === "function" ? x : +x;
+      return force;
+    };
+    force.chargeDistance = function(x) {
+      if (!arguments.length) return Math.sqrt(chargeDistance2);
+      chargeDistance2 = x * x;
+      return force;
+    };
+    force.gravity = function(x) {
+      if (!arguments.length) return gravity;
+      gravity = +x;
+      return force;
+    };
+    force.theta = function(x) {
+      if (!arguments.length) return Math.sqrt(theta2);
+      theta2 = x * x;
+      return force;
+    };
+    force.alpha = function(x) {
+      if (!arguments.length) return alpha;
+      x = +x;
+      if (alpha) {
+        if (x > 0) alpha = x; else alpha = 0;
+      } else if (x > 0) {
+        event.start({
+          type: "start",
+          alpha: alpha = x
+        });
+        d3.timer(force.tick);
+      }
+      return force;
+    };
+    force.start = function() {
+      var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
+      for (i = 0; i < n; ++i) {
+        (o = nodes[i]).index = i;
+        o.weight = 0;
+      }
+      for (i = 0; i < m; ++i) {
+        o = links[i];
+        if (typeof o.source == "number") o.source = nodes[o.source];
+        if (typeof o.target == "number") o.target = nodes[o.target];
+        ++o.source.weight;
+        ++o.target.weight;
+      }
+      for (i = 0; i < n; ++i) {
+        o = nodes[i];
+        if (isNaN(o.x)) o.x = position("x", w);
+        if (isNaN(o.y)) o.y = position("y", h);
+        if (isNaN(o.px)) o.px = o.x;
+        if (isNaN(o.py)) o.py = o.y;
+      }
+      distances = [];
+      if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
+      strengths = [];
+      if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
+      charges = [];
+      if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
+      function position(dimension, size) {
+        if (!neighbors) {
+          neighbors = new Array(n);
+          for (j = 0; j < n; ++j) {
+            neighbors[j] = [];
+          }
+          for (j = 0; j < m; ++j) {
+            var o = links[j];
+            neighbors[o.source.index].push(o.target);
+            neighbors[o.target.index].push(o.source);
+          }
+        }
+        var candidates = neighbors[i], j = -1, m = candidates.length, x;
+        while (++j < m) if (!isNaN(x = candidates[j][dimension])) return x;
+        return Math.random() * size;
+      }
+      return force.resume();
+    };
+    force.resume = function() {
+      return force.alpha(.1);
+    };
+    force.stop = function() {
+      return force.alpha(0);
+    };
+    force.drag = function() {
+      if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
+      if (!arguments.length) return drag;
+      this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
+    };
+    function dragmove(d) {
+      d.px = d3.event.x, d.py = d3.event.y;
+      force.resume();
+    }
+    return d3.rebind(force, event, "on");
+  };
+  function d3_layout_forceDragstart(d) {
+    d.fixed |= 2;
+  }
+  function d3_layout_forceDragend(d) {
+    d.fixed &= ~6;
+  }
+  function d3_layout_forceMouseover(d) {
+    d.fixed |= 4;
+    d.px = d.x, d.py = d.y;
+  }
+  function d3_layout_forceMouseout(d) {
+    d.fixed &= ~4;
+  }
+  function d3_layout_forceAccumulate(quad, alpha, charges) {
+    var cx = 0, cy = 0;
+    quad.charge = 0;
+    if (!quad.leaf) {
+      var nodes = quad.nodes, n = nodes.length, i = -1, c;
+      while (++i < n) {
+        c = nodes[i];
+        if (c == null) continue;
+        d3_layout_forceAccumulate(c, alpha, charges);
+        quad.charge += c.charge;
+        cx += c.charge * c.cx;
+        cy += c.charge * c.cy;
+      }
+    }
+    if (quad.point) {
+      if (!quad.leaf) {
+        quad.point.x += Math.random() - .5;
+        quad.point.y += Math.random() - .5;
+      }
+      var k = alpha * charges[quad.point.index];
+      quad.charge += quad.pointCharge = k;
+      cx += k * quad.point.x;
+      cy += k * quad.point.y;
+    }
+    quad.cx = cx / quad.charge;
+    quad.cy = cy / quad.charge;
+  }
+  var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
+  d3.layout.hierarchy = function() {
+    var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
+    function recurse(node, depth, nodes) {
+      var childs = children.call(hierarchy, node, depth);
+      node.depth = depth;
+      nodes.push(node);
+      if (childs && (n = childs.length)) {
+        var i = -1, n, c = node.children = new Array(n), v = 0, j = depth + 1, d;
+        while (++i < n) {
+          d = c[i] = recurse(childs[i], j, nodes);
+          d.parent = node;
+          v += d.value;
+        }
+        if (sort) c.sort(sort);
+        if (value) node.value = v;
+      } else {
+        delete node.children;
+        if (value) {
+          node.value = +value.call(hierarchy, node, depth) || 0;
+        }
+      }
+      return node;
+    }
+    function revalue(node, depth) {
+      var children = node.children, v = 0;
+      if (children && (n = children.length)) {
+        var i = -1, n, j = depth + 1;
+        while (++i < n) v += revalue(children[i], j);
+      } else if (value) {
+        v = +value.call(hierarchy, node, depth) || 0;
+      }
+      if (value) node.value = v;
+      return v;
+    }
+    function hierarchy(d) {
+      var nodes = [];
+      recurse(d, 0, nodes);
+      return nodes;
+    }
+    hierarchy.sort = function(x) {
+      if (!arguments.length) return sort;
+      sort = x;
+      return hierarchy;
+    };
+    hierarchy.children = function(x) {
+      if (!arguments.length) return children;
+      children = x;
+      return hierarchy;
+    };
+    hierarchy.value = function(x) {
+      if (!arguments.length) return value;
+      value = x;
+      return hierarchy;
+    };
+    hierarchy.revalue = function(root) {
+      revalue(root, 0);
+      return root;
+    };
+    return hierarchy;
+  };
+  function d3_layout_hierarchyRebind(object, hierarchy) {
+    d3.rebind(object, hierarchy, "sort", "children", "value");
+    object.nodes = object;
+    object.links = d3_layout_hierarchyLinks;
+    return object;
+  }
+  function d3_layout_hierarchyChildren(d) {
+    return d.children;
+  }
+  function d3_layout_hierarchyValue(d) {
+    return d.value;
+  }
+  function d3_layout_hierarchySort(a, b) {
+    return b.value - a.value;
+  }
+  function d3_layout_hierarchyLinks(nodes) {
+    return d3.merge(nodes.map(function(parent) {
+      return (parent.children || []).map(function(child) {
+        return {
+          source: parent,
+          target: child
+        };
+      });
+    }));
+  }
+  d3.layout.partition = function() {
+    var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
+    function position(node, x, dx, dy) {
+      var children = node.children;
+      node.x = x;
+      node.y = node.depth * dy;
+      node.dx = dx;
+      node.dy = dy;
+      if (children && (n = children.length)) {
+        var i = -1, n, c, d;
+        dx = node.value ? dx / node.value : 0;
+        while (++i < n) {
+          position(c = children[i], x, d = c.value * dx, dy);
+          x += d;
+        }
+      }
+    }
+    function depth(node) {
+      var children = node.children, d = 0;
+      if (children && (n = children.length)) {
+        var i = -1, n;
+        while (++i < n) d = Math.max(d, depth(children[i]));
+      }
+      return 1 + d;
+    }
+    function partition(d, i) {
+      var nodes = hierarchy.call(this, d, i);
+      position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
+      return nodes;
+    }
+    partition.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return partition;
+    };
+    return d3_layout_hierarchyRebind(partition, hierarchy);
+  };
+  d3.layout.pie = function() {
+    var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ;
+    function pie(data) {
+      var values = data.map(function(d, i) {
+        return +value.call(pie, d, i);
+      });
+      var a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle);
+      var k = ((typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a) / d3.sum(values);
+      var index = d3.range(data.length);
+      if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
+        return values[j] - values[i];
+      } : function(i, j) {
+        return sort(data[i], data[j]);
+      });
+      var arcs = [];
+      index.forEach(function(i) {
+        var d;
+        arcs[i] = {
+          data: data[i],
+          value: d = values[i],
+          startAngle: a,
+          endAngle: a += d * k
+        };
+      });
+      return arcs;
+    }
+    pie.value = function(x) {
+      if (!arguments.length) return value;
+      value = x;
+      return pie;
+    };
+    pie.sort = function(x) {
+      if (!arguments.length) return sort;
+      sort = x;
+      return pie;
+    };
+    pie.startAngle = function(x) {
+      if (!arguments.length) return startAngle;
+      startAngle = x;
+      return pie;
+    };
+    pie.endAngle = function(x) {
+      if (!arguments.length) return endAngle;
+      endAngle = x;
+      return pie;
+    };
+    return pie;
+  };
+  var d3_layout_pieSortByValue = {};
+  d3.layout.stack = function() {
+    var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
+    function stack(data, index) {
+      var series = data.map(function(d, i) {
+        return values.call(stack, d, i);
+      });
+      var points = series.map(function(d) {
+        return d.map(function(v, i) {
+          return [ x.call(stack, v, i), y.call(stack, v, i) ];
+        });
+      });
+      var orders = order.call(stack, points, index);
+      series = d3.permute(series, orders);
+      points = d3.permute(points, orders);
+      var offsets = offset.call(stack, points, index);
+      var n = series.length, m = series[0].length, i, j, o;
+      for (j = 0; j < m; ++j) {
+        out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
+        for (i = 1; i < n; ++i) {
+          out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
+        }
+      }
+      return data;
+    }
+    stack.values = function(x) {
+      if (!arguments.length) return values;
+      values = x;
+      return stack;
+    };
+    stack.order = function(x) {
+      if (!arguments.length) return order;
+      order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
+      return stack;
+    };
+    stack.offset = function(x) {
+      if (!arguments.length) return offset;
+      offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
+      return stack;
+    };
+    stack.x = function(z) {
+      if (!arguments.length) return x;
+      x = z;
+      return stack;
+    };
+    stack.y = function(z) {
+      if (!arguments.length) return y;
+      y = z;
+      return stack;
+    };
+    stack.out = function(z) {
+      if (!arguments.length) return out;
+      out = z;
+      return stack;
+    };
+    return stack;
+  };
+  function d3_layout_stackX(d) {
+    return d.x;
+  }
+  function d3_layout_stackY(d) {
+    return d.y;
+  }
+  function d3_layout_stackOut(d, y0, y) {
+    d.y0 = y0;
+    d.y = y;
+  }
+  var d3_layout_stackOrders = d3.map({
+    "inside-out": function(data) {
+      var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
+        return max[a] - max[b];
+      }), top = 0, bottom = 0, tops = [], bottoms = [];
+      for (i = 0; i < n; ++i) {
+        j = index[i];
+        if (top < bottom) {
+          top += sums[j];
+          tops.push(j);
+        } else {
+          bottom += sums[j];
+          bottoms.push(j);
+        }
+      }
+      return bottoms.reverse().concat(tops);
+    },
+    reverse: function(data) {
+      return d3.range(data.length).reverse();
+    },
+    "default": d3_layout_stackOrderDefault
+  });
+  var d3_layout_stackOffsets = d3.map({
+    silhouette: function(data) {
+      var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
+      for (j = 0; j < m; ++j) {
+        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+        if (o > max) max = o;
+        sums.push(o);
+      }
+      for (j = 0; j < m; ++j) {
+        y0[j] = (max - sums[j]) / 2;
+      }
+      return y0;
+    },
+    wiggle: function(data) {
+      var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
+      y0[0] = o = o0 = 0;
+      for (j = 1; j < m; ++j) {
+        for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
+        for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
+          for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
+            s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
+          }
+          s2 += s3 * data[i][j][1];
+        }
+        y0[j] = o -= s1 ? s2 / s1 * dx : 0;
+        if (o < o0) o0 = o;
+      }
+      for (j = 0; j < m; ++j) y0[j] -= o0;
+      return y0;
+    },
+    expand: function(data) {
+      var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
+      for (j = 0; j < m; ++j) {
+        for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
+        if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
+      }
+      for (j = 0; j < m; ++j) y0[j] = 0;
+      return y0;
+    },
+    zero: d3_layout_stackOffsetZero
+  });
+  function d3_layout_stackOrderDefault(data) {
+    return d3.range(data.length);
+  }
+  function d3_layout_stackOffsetZero(data) {
+    var j = -1, m = data[0].length, y0 = [];
+    while (++j < m) y0[j] = 0;
+    return y0;
+  }
+  function d3_layout_stackMaxIndex(array) {
+    var i = 1, j = 0, v = array[0][1], k, n = array.length;
+    for (;i < n; ++i) {
+      if ((k = array[i][1]) > v) {
+        j = i;
+        v = k;
+      }
+    }
+    return j;
+  }
+  function d3_layout_stackReduceSum(d) {
+    return d.reduce(d3_layout_stackSum, 0);
+  }
+  function d3_layout_stackSum(p, d) {
+    return p + d[1];
+  }
+  d3.layout.histogram = function() {
+    var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
+    function histogram(data, i) {
+      var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
+      while (++i < m) {
+        bin = bins[i] = [];
+        bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
+        bin.y = 0;
+      }
+      if (m > 0) {
+        i = -1;
+        while (++i < n) {
+          x = values[i];
+          if (x >= range[0] && x <= range[1]) {
+            bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
+            bin.y += k;
+            bin.push(data[i]);
+          }
+        }
+      }
+      return bins;
+    }
+    histogram.value = function(x) {
+      if (!arguments.length) return valuer;
+      valuer = x;
+      return histogram;
+    };
+    histogram.range = function(x) {
+      if (!arguments.length) return ranger;
+      ranger = d3_functor(x);
+      return histogram;
+    };
+    histogram.bins = function(x) {
+      if (!arguments.length) return binner;
+      binner = typeof x === "number" ? function(range) {
+        return d3_layout_histogramBinFixed(range, x);
+      } : d3_functor(x);
+      return histogram;
+    };
+    histogram.frequency = function(x) {
+      if (!arguments.length) return frequency;
+      frequency = !!x;
+      return histogram;
+    };
+    return histogram;
+  };
+  function d3_layout_histogramBinSturges(range, values) {
+    return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
+  }
+  function d3_layout_histogramBinFixed(range, n) {
+    var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
+    while (++x <= n) f[x] = m * x + b;
+    return f;
+  }
+  function d3_layout_histogramRange(values) {
+    return [ d3.min(values), d3.max(values) ];
+  }
+  d3.layout.tree = function() {
+    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
+    function tree(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0];
+      function firstWalk(node, previousSibling) {
+        var children = node.children, layout = node._tree;
+        if (children && (n = children.length)) {
+          var n, firstChild = children[0], previousChild, ancestor = firstChild, child, i = -1;
+          while (++i < n) {
+            child = children[i];
+            firstWalk(child, previousChild);
+            ancestor = apportion(child, previousChild, ancestor);
+            previousChild = child;
+          }
+          d3_layout_treeShift(node);
+          var midpoint = .5 * (firstChild._tree.prelim + child._tree.prelim);
+          if (previousSibling) {
+            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
+            layout.mod = layout.prelim - midpoint;
+          } else {
+            layout.prelim = midpoint;
+          }
+        } else {
+          if (previousSibling) {
+            layout.prelim = previousSibling._tree.prelim + separation(node, previousSibling);
+          }
+        }
+      }
+      function secondWalk(node, x) {
+        node.x = node._tree.prelim + x;
+        var children = node.children;
+        if (children && (n = children.length)) {
+          var i = -1, n;
+          x += node._tree.mod;
+          while (++i < n) {
+            secondWalk(children[i], x);
+          }
+        }
+      }
+      function apportion(node, previousSibling, ancestor) {
+        if (previousSibling) {
+          var vip = node, vop = node, vim = previousSibling, vom = node.parent.children[0], sip = vip._tree.mod, sop = vop._tree.mod, sim = vim._tree.mod, som = vom._tree.mod, shift;
+          while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), vim && vip) {
+            vom = d3_layout_treeLeft(vom);
+            vop = d3_layout_treeRight(vop);
+            vop._tree.ancestor = node;
+            shift = vim._tree.prelim + sim - vip._tree.prelim - sip + separation(vim, vip);
+            if (shift > 0) {
+              d3_layout_treeMove(d3_layout_treeAncestor(vim, node, ancestor), node, shift);
+              sip += shift;
+              sop += shift;
+            }
+            sim += vim._tree.mod;
+            sip += vip._tree.mod;
+            som += vom._tree.mod;
+            sop += vop._tree.mod;
+          }
+          if (vim && !d3_layout_treeRight(vop)) {
+            vop._tree.thread = vim;
+            vop._tree.mod += sim - sop;
+          }
+          if (vip && !d3_layout_treeLeft(vom)) {
+            vom._tree.thread = vip;
+            vom._tree.mod += sip - som;
+            ancestor = node;
+          }
+        }
+        return ancestor;
+      }
+      d3_layout_treeVisitAfter(root, function(node, previousSibling) {
+        node._tree = {
+          ancestor: node,
+          prelim: 0,
+          mod: 0,
+          change: 0,
+          shift: 0,
+          number: previousSibling ? previousSibling._tree.number + 1 : 0
+        };
+      });
+      firstWalk(root);
+      secondWalk(root, -root._tree.prelim);
+      var left = d3_layout_treeSearch(root, d3_layout_treeLeftmost), right = d3_layout_treeSearch(root, d3_layout_treeRightmost), deep = d3_layout_treeSearch(root, d3_layout_treeDeepest), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2, y1 = deep.depth || 1;
+      d3_layout_treeVisitAfter(root, nodeSize ? function(node) {
+        node.x *= size[0];
+        node.y = node.depth * size[1];
+        delete node._tree;
+      } : function(node) {
+        node.x = (node.x - x0) / (x1 - x0) * size[0];
+        node.y = node.depth / y1 * size[1];
+        delete node._tree;
+      });
+      return nodes;
+    }
+    tree.separation = function(x) {
+      if (!arguments.length) return separation;
+      separation = x;
+      return tree;
+    };
+    tree.size = function(x) {
+      if (!arguments.length) return nodeSize ? null : size;
+      nodeSize = (size = x) == null;
+      return tree;
+    };
+    tree.nodeSize = function(x) {
+      if (!arguments.length) return nodeSize ? size : null;
+      nodeSize = (size = x) != null;
+      return tree;
+    };
+    return d3_layout_hierarchyRebind(tree, hierarchy);
+  };
+  function d3_layout_treeSeparation(a, b) {
+    return a.parent == b.parent ? 1 : 2;
+  }
+  function d3_layout_treeLeft(node) {
+    var children = node.children;
+    return children && children.length ? children[0] : node._tree.thread;
+  }
+  function d3_layout_treeRight(node) {
+    var children = node.children, n;
+    return children && (n = children.length) ? children[n - 1] : node._tree.thread;
+  }
+  function d3_layout_treeSearch(node, compare) {
+    var children = node.children;
+    if (children && (n = children.length)) {
+      var child, n, i = -1;
+      while (++i < n) {
+        if (compare(child = d3_layout_treeSearch(children[i], compare), node) > 0) {
+          node = child;
+        }
+      }
+    }
+    return node;
+  }
+  function d3_layout_treeRightmost(a, b) {
+    return a.x - b.x;
+  }
+  function d3_layout_treeLeftmost(a, b) {
+    return b.x - a.x;
+  }
+  function d3_layout_treeDeepest(a, b) {
+    return a.depth - b.depth;
+  }
+  function d3_layout_treeVisitAfter(node, callback) {
+    function visit(node, previousSibling) {
+      var children = node.children;
+      if (children && (n = children.length)) {
+        var child, previousChild = null, i = -1, n;
+        while (++i < n) {
+          child = children[i];
+          visit(child, previousChild);
+          previousChild = child;
+        }
+      }
+      callback(node, previousSibling);
+    }
+    visit(node, null);
+  }
+  function d3_layout_treeShift(node) {
+    var shift = 0, change = 0, children = node.children, i = children.length, child;
+    while (--i >= 0) {
+      child = children[i]._tree;
+      child.prelim += shift;
+      child.mod += shift;
+      shift += child.shift + (change += child.change);
+    }
+  }
+  function d3_layout_treeMove(ancestor, node, shift) {
+    ancestor = ancestor._tree;
+    node = node._tree;
+    var change = shift / (node.number - ancestor.number);
+    ancestor.change += change;
+    node.change -= change;
+    node.shift += shift;
+    node.prelim += shift;
+    node.mod += shift;
+  }
+  function d3_layout_treeAncestor(vim, node, ancestor) {
+    return vim._tree.ancestor.parent == node.parent ? vim._tree.ancestor : ancestor;
+  }
+  d3.layout.pack = function() {
+    var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
+    function pack(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
+        return radius;
+      };
+      root.x = root.y = 0;
+      d3_layout_treeVisitAfter(root, function(d) {
+        d.r = +r(d.value);
+      });
+      d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+      if (padding) {
+        var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
+        d3_layout_treeVisitAfter(root, function(d) {
+          d.r += dr;
+        });
+        d3_layout_treeVisitAfter(root, d3_layout_packSiblings);
+        d3_layout_treeVisitAfter(root, function(d) {
+          d.r -= dr;
+        });
+      }
+      d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
+      return nodes;
+    }
+    pack.size = function(_) {
+      if (!arguments.length) return size;
+      size = _;
+      return pack;
+    };
+    pack.radius = function(_) {
+      if (!arguments.length) return radius;
+      radius = _ == null || typeof _ === "function" ? _ : +_;
+      return pack;
+    };
+    pack.padding = function(_) {
+      if (!arguments.length) return padding;
+      padding = +_;
+      return pack;
+    };
+    return d3_layout_hierarchyRebind(pack, hierarchy);
+  };
+  function d3_layout_packSort(a, b) {
+    return a.value - b.value;
+  }
+  function d3_layout_packInsert(a, b) {
+    var c = a._pack_next;
+    a._pack_next = b;
+    b._pack_prev = a;
+    b._pack_next = c;
+    c._pack_prev = b;
+  }
+  function d3_layout_packSplice(a, b) {
+    a._pack_next = b;
+    b._pack_prev = a;
+  }
+  function d3_layout_packIntersects(a, b) {
+    var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
+    return .999 * dr * dr > dx * dx + dy * dy;
+  }
+  function d3_layout_packSiblings(node) {
+    if (!(nodes = node.children) || !(n = nodes.length)) return;
+    var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
+    function bound(node) {
+      xMin = Math.min(node.x - node.r, xMin);
+      xMax = Math.max(node.x + node.r, xMax);
+      yMin = Math.min(node.y - node.r, yMin);
+      yMax = Math.max(node.y + node.r, yMax);
+    }
+    nodes.forEach(d3_layout_packLink);
+    a = nodes[0];
+    a.x = -a.r;
+    a.y = 0;
+    bound(a);
+    if (n > 1) {
+      b = nodes[1];
+      b.x = b.r;
+      b.y = 0;
+      bound(b);
+      if (n > 2) {
+        c = nodes[2];
+        d3_layout_packPlace(a, b, c);
+        bound(c);
+        d3_layout_packInsert(a, c);
+        a._pack_prev = c;
+        d3_layout_packInsert(c, b);
+        b = a._pack_next;
+        for (i = 3; i < n; i++) {
+          d3_layout_packPlace(a, b, c = nodes[i]);
+          var isect = 0, s1 = 1, s2 = 1;
+          for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
+            if (d3_layout_packIntersects(j, c)) {
+              isect = 1;
+              break;
+            }
+          }
+          if (isect == 1) {
+            for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, s2++) {
+              if (d3_layout_packIntersects(k, c)) {
+                break;
+              }
+            }
+          }
+          if (isect) {
+            if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
+            i--;
+          } else {
+            d3_layout_packInsert(a, c);
+            b = c;
+            bound(c);
+          }
+        }
+      }
+    }
+    var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
+    for (i = 0; i < n; i++) {
+      c = nodes[i];
+      c.x -= cx;
+      c.y -= cy;
+      cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
+    }
+    node.r = cr;
+    nodes.forEach(d3_layout_packUnlink);
+  }
+  function d3_layout_packLink(node) {
+    node._pack_next = node._pack_prev = node;
+  }
+  function d3_layout_packUnlink(node) {
+    delete node._pack_next;
+    delete node._pack_prev;
+  }
+  function d3_layout_packTransform(node, x, y, k) {
+    var children = node.children;
+    node.x = x += k * node.x;
+    node.y = y += k * node.y;
+    node.r *= k;
+    if (children) {
+      var i = -1, n = children.length;
+      while (++i < n) d3_layout_packTransform(children[i], x, y, k);
+    }
+  }
+  function d3_layout_packPlace(a, b, c) {
+    var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
+    if (db && (dx || dy)) {
+      var da = b.r + c.r, dc = dx * dx + dy * dy;
+      da *= da;
+      db *= db;
+      var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
+      c.x = a.x + x * dx + y * dy;
+      c.y = a.y + x * dy - y * dx;
+    } else {
+      c.x = a.x + db;
+      c.y = a.y;
+    }
+  }
+  d3.layout.cluster = function() {
+    var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
+    function cluster(d, i) {
+      var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
+      d3_layout_treeVisitAfter(root, function(node) {
+        var children = node.children;
+        if (children && children.length) {
+          node.x = d3_layout_clusterX(children);
+          node.y = d3_layout_clusterY(children);
+        } else {
+          node.x = previousNode ? x += separation(node, previousNode) : 0;
+          node.y = 0;
+          previousNode = node;
+        }
+      });
+      var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
+      d3_layout_treeVisitAfter(root, nodeSize ? function(node) {
+        node.x = (node.x - root.x) * size[0];
+        node.y = (root.y - node.y) * size[1];
+      } : function(node) {
+        node.x = (node.x - x0) / (x1 - x0) * size[0];
+        node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
+      });
+      return nodes;
+    }
+    cluster.separation = function(x) {
+      if (!arguments.length) return separation;
+      separation = x;
+      return cluster;
+    };
+    cluster.size = function(x) {
+      if (!arguments.length) return nodeSize ? null : size;
+      nodeSize = (size = x) == null;
+      return cluster;
+    };
+    cluster.nodeSize = function(x) {
+      if (!arguments.length) return nodeSize ? size : null;
+      nodeSize = (size = x) != null;
+      return cluster;
+    };
+    return d3_layout_hierarchyRebind(cluster, hierarchy);
+  };
+  function d3_layout_clusterY(children) {
+    return 1 + d3.max(children, function(child) {
+      return child.y;
+    });
+  }
+  function d3_layout_clusterX(children) {
+    return children.reduce(function(x, child) {
+      return x + child.x;
+    }, 0) / children.length;
+  }
+  function d3_layout_clusterLeft(node) {
+    var children = node.children;
+    return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
+  }
+  function d3_layout_clusterRight(node) {
+    var children = node.children, n;
+    return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
+  }
+  d3.layout.treemap = function() {
+    var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
+    function scale(children, k) {
+      var i = -1, n = children.length, child, area;
+      while (++i < n) {
+        area = (child = children[i]).value * (k < 0 ? 0 : k);
+        child.area = isNaN(area) || area <= 0 ? 0 : area;
+      }
+    }
+    function squarify(node) {
+      var children = node.children;
+      if (children && children.length) {
+        var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
+        scale(remaining, rect.dx * rect.dy / node.value);
+        row.area = 0;
+        while ((n = remaining.length) > 0) {
+          row.push(child = remaining[n - 1]);
+          row.area += child.area;
+          if (mode !== "squarify" || (score = worst(row, u)) <= best) {
+            remaining.pop();
+            best = score;
+          } else {
+            row.area -= row.pop().area;
+            position(row, u, rect, false);
+            u = Math.min(rect.dx, rect.dy);
+            row.length = row.area = 0;
+            best = Infinity;
+          }
+        }
+        if (row.length) {
+          position(row, u, rect, true);
+          row.length = row.area = 0;
+        }
+        children.forEach(squarify);
+      }
+    }
+    function stickify(node) {
+      var children = node.children;
+      if (children && children.length) {
+        var rect = pad(node), remaining = children.slice(), child, row = [];
+        scale(remaining, rect.dx * rect.dy / node.value);
+        row.area = 0;
+        while (child = remaining.pop()) {
+          row.push(child);
+          row.area += child.area;
+          if (child.z != null) {
+            position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
+            row.length = row.area = 0;
+          }
+        }
+        children.forEach(stickify);
+      }
+    }
+    function worst(row, u) {
+      var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
+      while (++i < n) {
+        if (!(r = row[i].area)) continue;
+        if (r < rmin) rmin = r;
+        if (r > rmax) rmax = r;
+      }
+      s *= s;
+      u *= u;
+      return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
+    }
+    function position(row, u, rect, flush) {
+      var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
+      if (u == rect.dx) {
+        if (flush || v > rect.dy) v = rect.dy;
+        while (++i < n) {
+          o = row[i];
+          o.x = x;
+          o.y = y;
+          o.dy = v;
+          x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
+        }
+        o.z = true;
+        o.dx += rect.x + rect.dx - x;
+        rect.y += v;
+        rect.dy -= v;
+      } else {
+        if (flush || v > rect.dx) v = rect.dx;
+        while (++i < n) {
+          o = row[i];
+          o.x = x;
+          o.y = y;
+          o.dx = v;
+          y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
+        }
+        o.z = false;
+        o.dy += rect.y + rect.dy - y;
+        rect.x += v;
+        rect.dx -= v;
+      }
+    }
+    function treemap(d) {
+      var nodes = stickies || hierarchy(d), root = nodes[0];
+      root.x = 0;
+      root.y = 0;
+      root.dx = size[0];
+      root.dy = size[1];
+      if (stickies) hierarchy.revalue(root);
+      scale([ root ], root.dx * root.dy / root.value);
+      (stickies ? stickify : squarify)(root);
+      if (sticky) stickies = nodes;
+      return nodes;
+    }
+    treemap.size = function(x) {
+      if (!arguments.length) return size;
+      size = x;
+      return treemap;
+    };
+    treemap.padding = function(x) {
+      if (!arguments.length) return padding;
+      function padFunction(node) {
+        var p = x.call(treemap, node, node.depth);
+        return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
+      }
+      function padConstant(node) {
+        return d3_layout_treemapPad(node, x);
+      }
+      var type;
+      pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], 
+      padConstant) : padConstant;
+      return treemap;
+    };
+    treemap.round = function(x) {
+      if (!arguments.length) return round != Number;
+      round = x ? Math.round : Number;
+      return treemap;
+    };
+    treemap.sticky = function(x) {
+      if (!arguments.length) return sticky;
+      sticky = x;
+      stickies = null;
+      return treemap;
+    };
+    treemap.ratio = function(x) {
+      if (!arguments.length) return ratio;
+      ratio = x;
+      return treemap;
+    };
+    treemap.mode = function(x) {
+      if (!arguments.length) return mode;
+      mode = x + "";
+      return treemap;
+    };
+    return d3_layout_hierarchyRebind(treemap, hierarchy);
+  };
+  function d3_layout_treemapPadNull(node) {
+    return {
+      x: node.x,
+      y: node.y,
+      dx: node.dx,
+      dy: node.dy
+    };
+  }
+  function d3_layout_treemapPad(node, padding) {
+    var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
+    if (dx < 0) {
+      x += dx / 2;
+      dx = 0;
+    }
+    if (dy < 0) {
+      y += dy / 2;
+      dy = 0;
+    }
+    return {
+      x: x,
+      y: y,
+      dx: dx,
+      dy: dy
+    };
+  }
+  d3.random = {
+    normal: function(µ, σ) {
+      var n = arguments.length;
+      if (n < 2) σ = 1;
+      if (n < 1) µ = 0;
+      return function() {
+        var x, y, r;
+        do {
+          x = Math.random() * 2 - 1;
+          y = Math.random() * 2 - 1;
+          r = x * x + y * y;
+        } while (!r || r > 1);
+        return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
+      };
+    },
+    logNormal: function() {
+      var random = d3.random.normal.apply(d3, arguments);
+      return function() {
+        return Math.exp(random());
+      };
+    },
+    bates: function(m) {
+      var random = d3.random.irwinHall(m);
+      return function() {
+        return random() / m;
+      };
+    },
+    irwinHall: function(m) {
+      return function() {
+        for (var s = 0, j = 0; j < m; j++) s += Math.random();
+        return s;
+      };
+    }
+  };
+  d3.scale = {};
+  function d3_scaleExtent(domain) {
+    var start = domain[0], stop = domain[domain.length - 1];
+    return start < stop ? [ start, stop ] : [ stop, start ];
+  }
+  function d3_scaleRange(scale) {
+    return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
+  }
+  function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
+    var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
+    return function(x) {
+      return i(u(x));
+    };
+  }
+  function d3_scale_nice(domain, nice) {
+    var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
+    if (x1 < x0) {
+      dx = i0, i0 = i1, i1 = dx;
+      dx = x0, x0 = x1, x1 = dx;
+    }
+    domain[i0] = nice.floor(x0);
+    domain[i1] = nice.ceil(x1);
+    return domain;
+  }
+  function d3_scale_niceStep(step) {
+    return step ? {
+      floor: function(x) {
+        return Math.floor(x / step) * step;
+      },
+      ceil: function(x) {
+        return Math.ceil(x / step) * step;
+      }
+    } : d3_scale_niceIdentity;
+  }
+  var d3_scale_niceIdentity = {
+    floor: d3_identity,
+    ceil: d3_identity
+  };
+  function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
+    var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
+    if (domain[k] < domain[0]) {
+      domain = domain.slice().reverse();
+      range = range.slice().reverse();
+    }
+    while (++j <= k) {
+      u.push(uninterpolate(domain[j - 1], domain[j]));
+      i.push(interpolate(range[j - 1], range[j]));
+    }
+    return function(x) {
+      var j = d3.bisect(domain, x, 1, k) - 1;
+      return i[j](u[j](x));
+    };
+  }
+  d3.scale.linear = function() {
+    return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
+  };
+  function d3_scale_linear(domain, range, interpolate, clamp) {
+    var output, input;
+    function rescale() {
+      var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
+      output = linear(domain, range, uninterpolate, interpolate);
+      input = linear(range, domain, uninterpolate, d3_interpolate);
+      return scale;
+    }
+    function scale(x) {
+      return output(x);
+    }
+    scale.invert = function(y) {
+      return input(y);
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.map(Number);
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.rangeRound = function(x) {
+      return scale.range(x).interpolate(d3_interpolateRound);
+    };
+    scale.clamp = function(x) {
+      if (!arguments.length) return clamp;
+      clamp = x;
+      return rescale();
+    };
+    scale.interpolate = function(x) {
+      if (!arguments.length) return interpolate;
+      interpolate = x;
+      return rescale();
+    };
+    scale.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    scale.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    scale.nice = function(m) {
+      d3_scale_linearNice(domain, m);
+      return rescale();
+    };
+    scale.copy = function() {
+      return d3_scale_linear(domain, range, interpolate, clamp);
+    };
+    return rescale();
+  }
+  function d3_scale_linearRebind(scale, linear) {
+    return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
+  }
+  function d3_scale_linearNice(domain, m) {
+    return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
+  }
+  function d3_scale_linearTickRange(domain, m) {
+    if (m == null) m = 10;
+    var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
+    if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
+    extent[0] = Math.ceil(extent[0] / step) * step;
+    extent[1] = Math.floor(extent[1] / step) * step + step * .5;
+    extent[2] = step;
+    return extent;
+  }
+  function d3_scale_linearTicks(domain, m) {
+    return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
+  }
+  function d3_scale_linearTickFormat(domain, m, format) {
+    var range = d3_scale_linearTickRange(domain, m);
+    if (format) {
+      var match = d3_format_re.exec(format);
+      match.shift();
+      if (match[8] === "s") {
+        var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
+        if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
+        match[8] = "f";
+        format = d3.format(match.join(""));
+        return function(d) {
+          return format(prefix.scale(d)) + prefix.symbol;
+        };
+      }
+      if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
+      format = match.join("");
+    } else {
+      format = ",." + d3_scale_linearPrecision(range[2]) + "f";
+    }
+    return d3.format(format);
+  }
+  var d3_scale_linearFormatSignificant = {
+    s: 1,
+    g: 1,
+    p: 1,
+    r: 1,
+    e: 1
+  };
+  function d3_scale_linearPrecision(value) {
+    return -Math.floor(Math.log(value) / Math.LN10 + .01);
+  }
+  function d3_scale_linearFormatPrecision(type, range) {
+    var p = d3_scale_linearPrecision(range[2]);
+    return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
+  }
+  d3.scale.log = function() {
+    return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
+  };
+  function d3_scale_log(linear, base, positive, domain) {
+    function log(x) {
+      return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
+    }
+    function pow(x) {
+      return positive ? Math.pow(base, x) : -Math.pow(base, -x);
+    }
+    function scale(x) {
+      return linear(log(x));
+    }
+    scale.invert = function(x) {
+      return pow(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      positive = x[0] >= 0;
+      linear.domain((domain = x.map(Number)).map(log));
+      return scale;
+    };
+    scale.base = function(_) {
+      if (!arguments.length) return base;
+      base = +_;
+      linear.domain(domain.map(log));
+      return scale;
+    };
+    scale.nice = function() {
+      var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
+      linear.domain(niced);
+      domain = niced.map(pow);
+      return scale;
+    };
+    scale.ticks = function() {
+      var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
+      if (isFinite(j - i)) {
+        if (positive) {
+          for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
+          ticks.push(pow(i));
+        } else {
+          ticks.push(pow(i));
+          for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
+        }
+        for (i = 0; ticks[i] < u; i++) {}
+        for (j = ticks.length; ticks[j - 1] > v; j--) {}
+        ticks = ticks.slice(i, j);
+      }
+      return ticks;
+    };
+    scale.tickFormat = function(n, format) {
+      if (!arguments.length) return d3_scale_logFormat;
+      if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
+      var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, Math.ceil) : (e = -1e-12, 
+      Math.floor), e;
+      return function(d) {
+        return d / pow(f(log(d) + e)) <= k ? format(d) : "";
+      };
+    };
+    scale.copy = function() {
+      return d3_scale_log(linear.copy(), base, positive, domain);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
+    floor: function(x) {
+      return -Math.ceil(-x);
+    },
+    ceil: function(x) {
+      return -Math.floor(-x);
+    }
+  };
+  d3.scale.pow = function() {
+    return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
+  };
+  function d3_scale_pow(linear, exponent, domain) {
+    var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
+    function scale(x) {
+      return linear(powp(x));
+    }
+    scale.invert = function(x) {
+      return powb(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      linear.domain((domain = x.map(Number)).map(powp));
+      return scale;
+    };
+    scale.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    scale.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    scale.nice = function(m) {
+      return scale.domain(d3_scale_linearNice(domain, m));
+    };
+    scale.exponent = function(x) {
+      if (!arguments.length) return exponent;
+      powp = d3_scale_powPow(exponent = x);
+      powb = d3_scale_powPow(1 / exponent);
+      linear.domain(domain.map(powp));
+      return scale;
+    };
+    scale.copy = function() {
+      return d3_scale_pow(linear.copy(), exponent, domain);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  function d3_scale_powPow(e) {
+    return function(x) {
+      return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
+    };
+  }
+  d3.scale.sqrt = function() {
+    return d3.scale.pow().exponent(.5);
+  };
+  d3.scale.ordinal = function() {
+    return d3_scale_ordinal([], {
+      t: "range",
+      a: [ [] ]
+    });
+  };
+  function d3_scale_ordinal(domain, ranger) {
+    var index, range, rangeBand;
+    function scale(x) {
+      return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
+    }
+    function steps(start, step) {
+      return d3.range(domain.length).map(function(i) {
+        return start + step * i;
+      });
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = [];
+      index = new d3_Map();
+      var i = -1, n = x.length, xi;
+      while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
+      return scale[ranger.t].apply(scale, ranger.a);
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      rangeBand = 0;
+      ranger = {
+        t: "range",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangePoints = function(x, padding) {
+      if (arguments.length < 2) padding = 0;
+      var start = x[0], stop = x[1], step = (stop - start) / (Math.max(1, domain.length - 1) + padding);
+      range = steps(domain.length < 2 ? (start + stop) / 2 : start + step * padding / 2, step);
+      rangeBand = 0;
+      ranger = {
+        t: "rangePoints",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeBands = function(x, padding, outerPadding) {
+      if (arguments.length < 2) padding = 0;
+      if (arguments.length < 3) outerPadding = padding;
+      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
+      range = steps(start + step * outerPadding, step);
+      if (reverse) range.reverse();
+      rangeBand = step * (1 - padding);
+      ranger = {
+        t: "rangeBands",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeRoundBands = function(x, padding, outerPadding) {
+      if (arguments.length < 2) padding = 0;
+      if (arguments.length < 3) outerPadding = padding;
+      var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding)), error = stop - start - (domain.length - padding) * step;
+      range = steps(start + Math.round(error / 2), step);
+      if (reverse) range.reverse();
+      rangeBand = Math.round(step * (1 - padding));
+      ranger = {
+        t: "rangeRoundBands",
+        a: arguments
+      };
+      return scale;
+    };
+    scale.rangeBand = function() {
+      return rangeBand;
+    };
+    scale.rangeExtent = function() {
+      return d3_scaleExtent(ranger.a[0]);
+    };
+    scale.copy = function() {
+      return d3_scale_ordinal(domain, ranger);
+    };
+    return scale.domain(domain);
+  }
+  d3.scale.category10 = function() {
+    return d3.scale.ordinal().range(d3_category10);
+  };
+  d3.scale.category20 = function() {
+    return d3.scale.ordinal().range(d3_category20);
+  };
+  d3.scale.category20b = function() {
+    return d3.scale.ordinal().range(d3_category20b);
+  };
+  d3.scale.category20c = function() {
+    return d3.scale.ordinal().range(d3_category20c);
+  };
+  var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
+  var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
+  var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
+  var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
+  d3.scale.quantile = function() {
+    return d3_scale_quantile([], []);
+  };
+  function d3_scale_quantile(domain, range) {
+    var thresholds;
+    function rescale() {
+      var k = 0, q = range.length;
+      thresholds = [];
+      while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
+      return scale;
+    }
+    function scale(x) {
+      if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.filter(function(d) {
+        return !isNaN(d);
+      }).sort(d3_ascending);
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.quantiles = function() {
+      return thresholds;
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
+    };
+    scale.copy = function() {
+      return d3_scale_quantile(domain, range);
+    };
+    return rescale();
+  }
+  d3.scale.quantize = function() {
+    return d3_scale_quantize(0, 1, [ 0, 1 ]);
+  };
+  function d3_scale_quantize(x0, x1, range) {
+    var kx, i;
+    function scale(x) {
+      return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
+    }
+    function rescale() {
+      kx = range.length / (x1 - x0);
+      i = range.length - 1;
+      return scale;
+    }
+    scale.domain = function(x) {
+      if (!arguments.length) return [ x0, x1 ];
+      x0 = +x[0];
+      x1 = +x[x.length - 1];
+      return rescale();
+    };
+    scale.range = function(x) {
+      if (!arguments.length) return range;
+      range = x;
+      return rescale();
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      y = y < 0 ? NaN : y / kx + x0;
+      return [ y, y + 1 / kx ];
+    };
+    scale.copy = function() {
+      return d3_scale_quantize(x0, x1, range);
+    };
+    return rescale();
+  }
+  d3.scale.threshold = function() {
+    return d3_scale_threshold([ .5 ], [ 0, 1 ]);
+  };
+  function d3_scale_threshold(domain, range) {
+    function scale(x) {
+      if (x <= x) return range[d3.bisect(domain, x)];
+    }
+    scale.domain = function(_) {
+      if (!arguments.length) return domain;
+      domain = _;
+      return scale;
+    };
+    scale.range = function(_) {
+      if (!arguments.length) return range;
+      range = _;
+      return scale;
+    };
+    scale.invertExtent = function(y) {
+      y = range.indexOf(y);
+      return [ domain[y - 1], domain[y] ];
+    };
+    scale.copy = function() {
+      return d3_scale_threshold(domain, range);
+    };
+    return scale;
+  }
+  d3.scale.identity = function() {
+    return d3_scale_identity([ 0, 1 ]);
+  };
+  function d3_scale_identity(domain) {
+    function identity(x) {
+      return +x;
+    }
+    identity.invert = identity;
+    identity.domain = identity.range = function(x) {
+      if (!arguments.length) return domain;
+      domain = x.map(identity);
+      return identity;
+    };
+    identity.ticks = function(m) {
+      return d3_scale_linearTicks(domain, m);
+    };
+    identity.tickFormat = function(m, format) {
+      return d3_scale_linearTickFormat(domain, m, format);
+    };
+    identity.copy = function() {
+      return d3_scale_identity(domain);
+    };
+    return identity;
+  }
+  d3.svg = {};
+  d3.svg.arc = function() {
+    var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+    function arc() {
+      var r0 = innerRadius.apply(this, arguments), r1 = outerRadius.apply(this, arguments), a0 = startAngle.apply(this, arguments) + d3_svg_arcOffset, a1 = endAngle.apply(this, arguments) + d3_svg_arcOffset, da = (a1 < a0 && (da = a0, 
+      a0 = a1, a1 = da), a1 - a0), df = da < π ? "0" : "1", c0 = Math.cos(a0), s0 = Math.sin(a0), c1 = Math.cos(a1), s1 = Math.sin(a1);
+      return da >= d3_svg_arcMax ? r0 ? "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "M0," + r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + -r0 + "A" + r0 + "," + r0 + " 0 1,0 0," + r0 + "Z" : "M0," + r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + -r1 + "A" + r1 + "," + r1 + " 0 1,1 0," + r1 + "Z" : r0 ? "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L" + r0 * c1 + "," + r0 * s1 + "A" + r0 + "," + r0 + " 0 " + df + ",0 " + r0 * c0 + "," + r0 * s0 + "Z" : "M" + r1 * c0 + "," + r1 * s0 + "A" + r1 + "," + r1 + " 0 " + df + ",1 " + r1 * c1 + "," + r1 * s1 + "L0,0" + "Z";
+    }
+    arc.innerRadius = function(v) {
+      if (!arguments.length) return innerRadius;
+      innerRadius = d3_functor(v);
+      return arc;
+    };
+    arc.outerRadius = function(v) {
+      if (!arguments.length) return outerRadius;
+      outerRadius = d3_functor(v);
+      return arc;
+    };
+    arc.startAngle = function(v) {
+      if (!arguments.length) return startAngle;
+      startAngle = d3_functor(v);
+      return arc;
+    };
+    arc.endAngle = function(v) {
+      if (!arguments.length) return endAngle;
+      endAngle = d3_functor(v);
+      return arc;
+    };
+    arc.centroid = function() {
+      var r = (innerRadius.apply(this, arguments) + outerRadius.apply(this, arguments)) / 2, a = (startAngle.apply(this, arguments) + endAngle.apply(this, arguments)) / 2 + d3_svg_arcOffset;
+      return [ Math.cos(a) * r, Math.sin(a) * r ];
+    };
+    return arc;
+  };
+  var d3_svg_arcOffset = -halfπ, d3_svg_arcMax = τ - ε;
+  function d3_svg_arcInnerRadius(d) {
+    return d.innerRadius;
+  }
+  function d3_svg_arcOuterRadius(d) {
+    return d.outerRadius;
+  }
+  function d3_svg_arcStartAngle(d) {
+    return d.startAngle;
+  }
+  function d3_svg_arcEndAngle(d) {
+    return d.endAngle;
+  }
+  function d3_svg_line(projection) {
+    var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
+    function line(data) {
+      var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
+      function segment() {
+        segments.push("M", interpolate(projection(points), tension));
+      }
+      while (++i < n) {
+        if (defined.call(this, d = data[i], i)) {
+          points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
+        } else if (points.length) {
+          segment();
+          points = [];
+        }
+      }
+      if (points.length) segment();
+      return segments.length ? segments.join("") : null;
+    }
+    line.x = function(_) {
+      if (!arguments.length) return x;
+      x = _;
+      return line;
+    };
+    line.y = function(_) {
+      if (!arguments.length) return y;
+      y = _;
+      return line;
+    };
+    line.defined = function(_) {
+      if (!arguments.length) return defined;
+      defined = _;
+      return line;
+    };
+    line.interpolate = function(_) {
+      if (!arguments.length) return interpolateKey;
+      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+      return line;
+    };
+    line.tension = function(_) {
+      if (!arguments.length) return tension;
+      tension = _;
+      return line;
+    };
+    return line;
+  }
+  d3.svg.line = function() {
+    return d3_svg_line(d3_identity);
+  };
+  var d3_svg_lineInterpolators = d3.map({
+    linear: d3_svg_lineLinear,
+    "linear-closed": d3_svg_lineLinearClosed,
+    step: d3_svg_lineStep,
+    "step-before": d3_svg_lineStepBefore,
+    "step-after": d3_svg_lineStepAfter,
+    basis: d3_svg_lineBasis,
+    "basis-open": d3_svg_lineBasisOpen,
+    "basis-closed": d3_svg_lineBasisClosed,
+    bundle: d3_svg_lineBundle,
+    cardinal: d3_svg_lineCardinal,
+    "cardinal-open": d3_svg_lineCardinalOpen,
+    "cardinal-closed": d3_svg_lineCardinalClosed,
+    monotone: d3_svg_lineMonotone
+  });
+  d3_svg_lineInterpolators.forEach(function(key, value) {
+    value.key = key;
+    value.closed = /-closed$/.test(key);
+  });
+  function d3_svg_lineLinear(points) {
+    return points.join("L");
+  }
+  function d3_svg_lineLinearClosed(points) {
+    return d3_svg_lineLinear(points) + "Z";
+  }
+  function d3_svg_lineStep(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+    while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
+    if (n > 1) path.push("H", p[0]);
+    return path.join("");
+  }
+  function d3_svg_lineStepBefore(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+    while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
+    return path.join("");
+  }
+  function d3_svg_lineStepAfter(points) {
+    var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
+    while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
+    return path.join("");
+  }
+  function d3_svg_lineCardinalOpen(points, tension) {
+    return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, points.length - 1), d3_svg_lineCardinalTangents(points, tension));
+  }
+  function d3_svg_lineCardinalClosed(points, tension) {
+    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 
+    points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
+  }
+  function d3_svg_lineCardinal(points, tension) {
+    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
+  }
+  function d3_svg_lineHermite(points, tangents) {
+    if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
+      return d3_svg_lineLinear(points);
+    }
+    var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
+    if (quad) {
+      path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
+      p0 = points[1];
+      pi = 2;
+    }
+    if (tangents.length > 1) {
+      t = tangents[1];
+      p = points[pi];
+      pi++;
+      path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+      for (var i = 2; i < tangents.length; i++, pi++) {
+        p = points[pi];
+        t = tangents[i];
+        path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
+      }
+    }
+    if (quad) {
+      var lp = points[pi];
+      path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
+    }
+    return path;
+  }
+  function d3_svg_lineCardinalTangents(points, tension) {
+    var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
+    while (++i < n) {
+      p0 = p1;
+      p1 = p2;
+      p2 = points[i];
+      tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
+    }
+    return tangents;
+  }
+  function d3_svg_lineBasis(points) {
+    if (points.length < 3) return d3_svg_lineLinear(points);
+    var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+    points.push(points[n - 1]);
+    while (++i <= n) {
+      pi = points[i];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    points.pop();
+    path.push("L", pi);
+    return path.join("");
+  }
+  function d3_svg_lineBasisOpen(points) {
+    if (points.length < 4) return d3_svg_lineLinear(points);
+    var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
+    while (++i < 3) {
+      pi = points[i];
+      px.push(pi[0]);
+      py.push(pi[1]);
+    }
+    path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
+    --i;
+    while (++i < n) {
+      pi = points[i];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    return path.join("");
+  }
+  function d3_svg_lineBasisClosed(points) {
+    var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
+    while (++i < 4) {
+      pi = points[i % n];
+      px.push(pi[0]);
+      py.push(pi[1]);
+    }
+    path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
+    --i;
+    while (++i < m) {
+      pi = points[i % n];
+      px.shift();
+      px.push(pi[0]);
+      py.shift();
+      py.push(pi[1]);
+      d3_svg_lineBasisBezier(path, px, py);
+    }
+    return path.join("");
+  }
+  function d3_svg_lineBundle(points, tension) {
+    var n = points.length - 1;
+    if (n) {
+      var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
+      while (++i <= n) {
+        p = points[i];
+        t = i / n;
+        p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
+        p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
+      }
+    }
+    return d3_svg_lineBasis(points);
+  }
+  function d3_svg_lineDot4(a, b) {
+    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+  }
+  var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
+  function d3_svg_lineBasisBezier(path, x, y) {
+    path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
+  }
+  function d3_svg_lineSlope(p0, p1) {
+    return (p1[1] - p0[1]) / (p1[0] - p0[0]);
+  }
+  function d3_svg_lineFiniteDifferences(points) {
+    var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
+    while (++i < j) {
+      m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
+    }
+    m[i] = d;
+    return m;
+  }
+  function d3_svg_lineMonotoneTangents(points) {
+    var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
+    while (++i < j) {
+      d = d3_svg_lineSlope(points[i], points[i + 1]);
+      if (abs(d) < ε) {
+        m[i] = m[i + 1] = 0;
+      } else {
+        a = m[i] / d;
+        b = m[i + 1] / d;
+        s = a * a + b * b;
+        if (s > 9) {
+          s = d * 3 / Math.sqrt(s);
+          m[i] = s * a;
+          m[i + 1] = s * b;
+        }
+      }
+    }
+    i = -1;
+    while (++i <= j) {
+      s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
+      tangents.push([ s || 0, m[i] * s || 0 ]);
+    }
+    return tangents;
+  }
+  function d3_svg_lineMonotone(points) {
+    return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
+  }
+  d3.svg.line.radial = function() {
+    var line = d3_svg_line(d3_svg_lineRadial);
+    line.radius = line.x, delete line.x;
+    line.angle = line.y, delete line.y;
+    return line;
+  };
+  function d3_svg_lineRadial(points) {
+    var point, i = -1, n = points.length, r, a;
+    while (++i < n) {
+      point = points[i];
+      r = point[0];
+      a = point[1] + d3_svg_arcOffset;
+      point[0] = r * Math.cos(a);
+      point[1] = r * Math.sin(a);
+    }
+    return points;
+  }
+  function d3_svg_area(projection) {
+    var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
+    function area(data) {
+      var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
+        return x;
+      } : d3_functor(x1), fy1 = y0 === y1 ? function() {
+        return y;
+      } : d3_functor(y1), x, y;
+      function segment() {
+        segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
+      }
+      while (++i < n) {
+        if (defined.call(this, d = data[i], i)) {
+          points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
+          points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
+        } else if (points0.length) {
+          segment();
+          points0 = [];
+          points1 = [];
+        }
+      }
+      if (points0.length) segment();
+      return segments.length ? segments.join("") : null;
+    }
+    area.x = function(_) {
+      if (!arguments.length) return x1;
+      x0 = x1 = _;
+      return area;
+    };
+    area.x0 = function(_) {
+      if (!arguments.length) return x0;
+      x0 = _;
+      return area;
+    };
+    area.x1 = function(_) {
+      if (!arguments.length) return x1;
+      x1 = _;
+      return area;
+    };
+    area.y = function(_) {
+      if (!arguments.length) return y1;
+      y0 = y1 = _;
+      return area;
+    };
+    area.y0 = function(_) {
+      if (!arguments.length) return y0;
+      y0 = _;
+      return area;
+    };
+    area.y1 = function(_) {
+      if (!arguments.length) return y1;
+      y1 = _;
+      return area;
+    };
+    area.defined = function(_) {
+      if (!arguments.length) return defined;
+      defined = _;
+      return area;
+    };
+    area.interpolate = function(_) {
+      if (!arguments.length) return interpolateKey;
+      if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
+      interpolateReverse = interpolate.reverse || interpolate;
+      L = interpolate.closed ? "M" : "L";
+      return area;
+    };
+    area.tension = function(_) {
+      if (!arguments.length) return tension;
+      tension = _;
+      return area;
+    };
+    return area;
+  }
+  d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
+  d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
+  d3.svg.area = function() {
+    return d3_svg_area(d3_identity);
+  };
+  d3.svg.area.radial = function() {
+    var area = d3_svg_area(d3_svg_lineRadial);
+    area.radius = area.x, delete area.x;
+    area.innerRadius = area.x0, delete area.x0;
+    area.outerRadius = area.x1, delete area.x1;
+    area.angle = area.y, delete area.y;
+    area.startAngle = area.y0, delete area.y0;
+    area.endAngle = area.y1, delete area.y1;
+    return area;
+  };
+  d3.svg.chord = function() {
+    var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
+    function chord(d, i) {
+      var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
+      return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
+    }
+    function subgroup(self, f, d, i) {
+      var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) + d3_svg_arcOffset, a1 = endAngle.call(self, subgroup, i) + d3_svg_arcOffset;
+      return {
+        r: r,
+        a0: a0,
+        a1: a1,
+        p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
+        p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
+      };
+    }
+    function equals(a, b) {
+      return a.a0 == b.a0 && a.a1 == b.a1;
+    }
+    function arc(r, p, a) {
+      return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
+    }
+    function curve(r0, p0, r1, p1) {
+      return "Q 0,0 " + p1;
+    }
+    chord.radius = function(v) {
+      if (!arguments.length) return radius;
+      radius = d3_functor(v);
+      return chord;
+    };
+    chord.source = function(v) {
+      if (!arguments.length) return source;
+      source = d3_functor(v);
+      return chord;
+    };
+    chord.target = function(v) {
+      if (!arguments.length) return target;
+      target = d3_functor(v);
+      return chord;
+    };
+    chord.startAngle = function(v) {
+      if (!arguments.length) return startAngle;
+      startAngle = d3_functor(v);
+      return chord;
+    };
+    chord.endAngle = function(v) {
+      if (!arguments.length) return endAngle;
+      endAngle = d3_functor(v);
+      return chord;
+    };
+    return chord;
+  };
+  function d3_svg_chordRadius(d) {
+    return d.radius;
+  }
+  d3.svg.diagonal = function() {
+    var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
+    function diagonal(d, i) {
+      var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
+        x: p0.x,
+        y: m
+      }, {
+        x: p3.x,
+        y: m
+      }, p3 ];
+      p = p.map(projection);
+      return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
+    }
+    diagonal.source = function(x) {
+      if (!arguments.length) return source;
+      source = d3_functor(x);
+      return diagonal;
+    };
+    diagonal.target = function(x) {
+      if (!arguments.length) return target;
+      target = d3_functor(x);
+      return diagonal;
+    };
+    diagonal.projection = function(x) {
+      if (!arguments.length) return projection;
+      projection = x;
+      return diagonal;
+    };
+    return diagonal;
+  };
+  function d3_svg_diagonalProjection(d) {
+    return [ d.x, d.y ];
+  }
+  d3.svg.diagonal.radial = function() {
+    var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
+    diagonal.projection = function(x) {
+      return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
+    };
+    return diagonal;
+  };
+  function d3_svg_diagonalRadialProjection(projection) {
+    return function() {
+      var d = projection.apply(this, arguments), r = d[0], a = d[1] + d3_svg_arcOffset;
+      return [ r * Math.cos(a), r * Math.sin(a) ];
+    };
+  }
+  d3.svg.symbol = function() {
+    var type = d3_svg_symbolType, size = d3_svg_symbolSize;
+    function symbol(d, i) {
+      return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
+    }
+    symbol.type = function(x) {
+      if (!arguments.length) return type;
+      type = d3_functor(x);
+      return symbol;
+    };
+    symbol.size = function(x) {
+      if (!arguments.length) return size;
+      size = d3_functor(x);
+      return symbol;
+    };
+    return symbol;
+  };
+  function d3_svg_symbolSize() {
+    return 64;
+  }
+  function d3_svg_symbolType() {
+    return "circle";
+  }
+  function d3_svg_symbolCircle(size) {
+    var r = Math.sqrt(size / π);
+    return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
+  }
+  var d3_svg_symbols = d3.map({
+    circle: d3_svg_symbolCircle,
+    cross: function(size) {
+      var r = Math.sqrt(size / 5) / 2;
+      return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
+    },
+    diamond: function(size) {
+      var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
+      return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
+    },
+    square: function(size) {
+      var r = Math.sqrt(size) / 2;
+      return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
+    },
+    "triangle-down": function(size) {
+      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+      return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
+    },
+    "triangle-up": function(size) {
+      var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
+      return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
+    }
+  });
+  d3.svg.symbolTypes = d3_svg_symbols.keys();
+  var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
+  function d3_transition(groups, id) {
+    d3_subclass(groups, d3_transitionPrototype);
+    groups.id = id;
+    return groups;
+  }
+  var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
+  d3_transitionPrototype.call = d3_selectionPrototype.call;
+  d3_transitionPrototype.empty = d3_selectionPrototype.empty;
+  d3_transitionPrototype.node = d3_selectionPrototype.node;
+  d3_transitionPrototype.size = d3_selectionPrototype.size;
+  d3.transition = function(selection) {
+    return arguments.length ? d3_transitionInheritId ? selection.transition() : selection : d3_selectionRoot.transition();
+  };
+  d3.transition.prototype = d3_transitionPrototype;
+  d3_transitionPrototype.select = function(selector) {
+    var id = this.id, subgroups = [], subgroup, subnode, node;
+    selector = d3_selection_selector(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
+          if ("__data__" in node) subnode.__data__ = node.__data__;
+          d3_transitionNode(subnode, i, id, node.__transition__[id]);
+          subgroup.push(subnode);
+        } else {
+          subgroup.push(null);
+        }
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_transitionPrototype.selectAll = function(selector) {
+    var id = this.id, subgroups = [], subgroup, subnodes, node, subnode, transition;
+    selector = d3_selection_selectorAll(selector);
+    for (var j = -1, m = this.length; ++j < m; ) {
+      for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
+        if (node = group[i]) {
+          transition = node.__transition__[id];
+          subnodes = selector.call(node, node.__data__, i, j);
+          subgroups.push(subgroup = []);
+          for (var k = -1, o = subnodes.length; ++k < o; ) {
+            if (subnode = subnodes[k]) d3_transitionNode(subnode, k, id, transition);
+            subgroup.push(subnode);
+          }
+        }
+      }
+    }
+    return d3_transition(subgroups, id);
+  };
+  d3_transitionPrototype.filter = function(filter) {
+    var subgroups = [], subgroup, group, node;
+    if (typeof filter !== "function") filter = d3_selection_filter(filter);
+    for (var j = 0, m = this.length; j < m; j++) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+        if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
+          subgroup.push(node);
+        }
+      }
+    }
+    return d3_transition(subgroups, this.id);
+  };
+  d3_transitionPrototype.tween = function(name, tween) {
+    var id = this.id;
+    if (arguments.length < 2) return this.node().__transition__[id].tween.get(name);
+    return d3_selection_each(this, tween == null ? function(node) {
+      node.__transition__[id].tween.remove(name);
+    } : function(node) {
+      node.__transition__[id].tween.set(name, tween);
+    });
+  };
+  function d3_transition_tween(groups, name, value, tween) {
+    var id = groups.id;
+    return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
+      node.__transition__[id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
+    } : (value = tween(value), function(node) {
+      node.__transition__[id].tween.set(name, value);
+    }));
+  }
+  d3_transitionPrototype.attr = function(nameNS, value) {
+    if (arguments.length < 2) {
+      for (value in nameNS) this.attr(value, nameNS[value]);
+      return this;
+    }
+    var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
+    function attrNull() {
+      this.removeAttribute(name);
+    }
+    function attrNullNS() {
+      this.removeAttributeNS(name.space, name.local);
+    }
+    function attrTween(b) {
+      return b == null ? attrNull : (b += "", function() {
+        var a = this.getAttribute(name), i;
+        return a !== b && (i = interpolate(a, b), function(t) {
+          this.setAttribute(name, i(t));
+        });
+      });
+    }
+    function attrTweenNS(b) {
+      return b == null ? attrNullNS : (b += "", function() {
+        var a = this.getAttributeNS(name.space, name.local), i;
+        return a !== b && (i = interpolate(a, b), function(t) {
+          this.setAttributeNS(name.space, name.local, i(t));
+        });
+      });
+    }
+    return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
+  };
+  d3_transitionPrototype.attrTween = function(nameNS, tween) {
+    var name = d3.ns.qualify(nameNS);
+    function attrTween(d, i) {
+      var f = tween.call(this, d, i, this.getAttribute(name));
+      return f && function(t) {
+        this.setAttribute(name, f(t));
+      };
+    }
+    function attrTweenNS(d, i) {
+      var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
+      return f && function(t) {
+        this.setAttributeNS(name.space, name.local, f(t));
+      };
+    }
+    return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
+  };
+  d3_transitionPrototype.style = function(name, value, priority) {
+    var n = arguments.length;
+    if (n < 3) {
+      if (typeof name !== "string") {
+        if (n < 2) value = "";
+        for (priority in name) this.style(priority, name[priority], value);
+        return this;
+      }
+      priority = "";
+    }
+    function styleNull() {
+      this.style.removeProperty(name);
+    }
+    function styleString(b) {
+      return b == null ? styleNull : (b += "", function() {
+        var a = d3_window.getComputedStyle(this, null).getPropertyValue(name), i;
+        return a !== b && (i = d3_interpolate(a, b), function(t) {
+          this.style.setProperty(name, i(t), priority);
+        });
+      });
+    }
+    return d3_transition_tween(this, "style." + name, value, styleString);
+  };
+  d3_transitionPrototype.styleTween = function(name, tween, priority) {
+    if (arguments.length < 3) priority = "";
+    function styleTween(d, i) {
+      var f = tween.call(this, d, i, d3_window.getComputedStyle(this, null).getPropertyValue(name));
+      return f && function(t) {
+        this.style.setProperty(name, f(t), priority);
+      };
+    }
+    return this.tween("style." + name, styleTween);
+  };
+  d3_transitionPrototype.text = function(value) {
+    return d3_transition_tween(this, "text", value, d3_transition_text);
+  };
+  function d3_transition_text(b) {
+    if (b == null) b = "";
+    return function() {
+      this.textContent = b;
+    };
+  }
+  d3_transitionPrototype.remove = function() {
+    return this.each("end.transition", function() {
+      var p;
+      if (this.__transition__.count < 2 && (p = this.parentNode)) p.removeChild(this);
+    });
+  };
+  d3_transitionPrototype.ease = function(value) {
+    var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].ease;
+    if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
+    return d3_selection_each(this, function(node) {
+      node.__transition__[id].ease = value;
+    });
+  };
+  d3_transitionPrototype.delay = function(value) {
+    var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].delay;
+    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+      node.__transition__[id].delay = +value.call(node, node.__data__, i, j);
+    } : (value = +value, function(node) {
+      node.__transition__[id].delay = value;
+    }));
+  };
+  d3_transitionPrototype.duration = function(value) {
+    var id = this.id;
+    if (arguments.length < 1) return this.node().__transition__[id].duration;
+    return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
+      node.__transition__[id].duration = Math.max(1, value.call(node, node.__data__, i, j));
+    } : (value = Math.max(1, value), function(node) {
+      node.__transition__[id].duration = value;
+    }));
+  };
+  d3_transitionPrototype.each = function(type, listener) {
+    var id = this.id;
+    if (arguments.length < 2) {
+      var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
+      d3_transitionInheritId = id;
+      d3_selection_each(this, function(node, i, j) {
+        d3_transitionInherit = node.__transition__[id];
+        type.call(node, node.__data__, i, j);
+      });
+      d3_transitionInherit = inherit;
+      d3_transitionInheritId = inheritId;
+    } else {
+      d3_selection_each(this, function(node) {
+        var transition = node.__transition__[id];
+        (transition.event || (transition.event = d3.dispatch("start", "end"))).on(type, listener);
+      });
+    }
+    return this;
+  };
+  d3_transitionPrototype.transition = function() {
+    var id0 = this.id, id1 = ++d3_transitionId, subgroups = [], subgroup, group, node, transition;
+    for (var j = 0, m = this.length; j < m; j++) {
+      subgroups.push(subgroup = []);
+      for (var group = this[j], i = 0, n = group.length; i < n; i++) {
+        if (node = group[i]) {
+          transition = Object.create(node.__transition__[id0]);
+          transition.delay += transition.duration;
+          d3_transitionNode(node, i, id1, transition);
+        }
+        subgroup.push(node);
+      }
+    }
+    return d3_transition(subgroups, id1);
+  };
+  function d3_transitionNode(node, i, id, inherit) {
+    var lock = node.__transition__ || (node.__transition__ = {
+      active: 0,
+      count: 0
+    }), transition = lock[id];
+    if (!transition) {
+      var time = inherit.time;
+      transition = lock[id] = {
+        tween: new d3_Map(),
+        time: time,
+        ease: inherit.ease,
+        delay: inherit.delay,
+        duration: inherit.duration
+      };
+      ++lock.count;
+      d3.timer(function(elapsed) {
+        var d = node.__data__, ease = transition.ease, delay = transition.delay, duration = transition.duration, timer = d3_timer_active, tweened = [];
+        timer.t = delay + time;
+        if (delay <= elapsed) return start(elapsed - delay);
+        timer.c = start;
+        function start(elapsed) {
+          if (lock.active > id) return stop();
+          lock.active = id;
+          transition.event && transition.event.start.call(node, d, i);
+          transition.tween.forEach(function(key, value) {
+            if (value = value.call(node, d, i)) {
+              tweened.push(value);
+            }
+          });
+          d3.timer(function() {
+            timer.c = tick(elapsed || 1) ? d3_true : tick;
+            return 1;
+          }, 0, time);
+        }
+        function tick(elapsed) {
+          if (lock.active !== id) return stop();
+          var t = elapsed / duration, e = ease(t), n = tweened.length;
+          while (n > 0) {
+            tweened[--n].call(node, e);
+          }
+          if (t >= 1) {
+            transition.event && transition.event.end.call(node, d, i);
+            return stop();
+          }
+        }
+        function stop() {
+          if (--lock.count) delete lock[id]; else delete node.__transition__;
+          return 1;
+        }
+      }, 0, time);
+    }
+  }
+  d3.svg.axis = function() {
+    var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
+    function axis(g) {
+      g.each(function() {
+        var g = d3.select(this);
+        var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
+        var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickTransform;
+        var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
+        d3.transition(path));
+        tickEnter.append("line");
+        tickEnter.append("text");
+        var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text");
+        switch (orient) {
+         case "bottom":
+          {
+            tickTransform = d3_svg_axisX;
+            lineEnter.attr("y2", innerTickSize);
+            textEnter.attr("y", Math.max(innerTickSize, 0) + tickPadding);
+            lineUpdate.attr("x2", 0).attr("y2", innerTickSize);
+            textUpdate.attr("x", 0).attr("y", Math.max(innerTickSize, 0) + tickPadding);
+            text.attr("dy", ".71em").style("text-anchor", "middle");
+            pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize);
+            break;
+          }
+
+         case "top":
+          {
+            tickTransform = d3_svg_axisX;
+            lineEnter.attr("y2", -innerTickSize);
+            textEnter.attr("y", -(Math.max(innerTickSize, 0) + tickPadding));
+            lineUpdate.attr("x2", 0).attr("y2", -innerTickSize);
+            textUpdate.attr("x", 0).attr("y", -(Math.max(innerTickSize, 0) + tickPadding));
+            text.attr("dy", "0em").style("text-anchor", "middle");
+            pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize);
+            break;
+          }
+
+         case "left":
+          {
+            tickTransform = d3_svg_axisY;
+            lineEnter.attr("x2", -innerTickSize);
+            textEnter.attr("x", -(Math.max(innerTickSize, 0) + tickPadding));
+            lineUpdate.attr("x2", -innerTickSize).attr("y2", 0);
+            textUpdate.attr("x", -(Math.max(innerTickSize, 0) + tickPadding)).attr("y", 0);
+            text.attr("dy", ".32em").style("text-anchor", "end");
+            pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize);
+            break;
+          }
+
+         case "right":
+          {
+            tickTransform = d3_svg_axisY;
+            lineEnter.attr("x2", innerTickSize);
+            textEnter.attr("x", Math.max(innerTickSize, 0) + tickPadding);
+            lineUpdate.attr("x2", innerTickSize).attr("y2", 0);
+            textUpdate.attr("x", Math.max(innerTickSize, 0) + tickPadding).attr("y", 0);
+            text.attr("dy", ".32em").style("text-anchor", "start");
+            pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize);
+            break;
+          }
+        }
+        if (scale1.rangeBand) {
+          var x = scale1, dx = x.rangeBand() / 2;
+          scale0 = scale1 = function(d) {
+            return x(d) + dx;
+          };
+        } else if (scale0.rangeBand) {
+          scale0 = scale1;
+        } else {
+          tickExit.call(tickTransform, scale1);
+        }
+        tickEnter.call(tickTransform, scale0);
+        tickUpdate.call(tickTransform, scale1);
+      });
+    }
+    axis.scale = function(x) {
+      if (!arguments.length) return scale;
+      scale = x;
+      return axis;
+    };
+    axis.orient = function(x) {
+      if (!arguments.length) return orient;
+      orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
+      return axis;
+    };
+    axis.ticks = function() {
+      if (!arguments.length) return tickArguments_;
+      tickArguments_ = arguments;
+      return axis;
+    };
+    axis.tickValues = function(x) {
+      if (!arguments.length) return tickValues;
+      tickValues = x;
+      return axis;
+    };
+    axis.tickFormat = function(x) {
+      if (!arguments.length) return tickFormat_;
+      tickFormat_ = x;
+      return axis;
+    };
+    axis.tickSize = function(x) {
+      var n = arguments.length;
+      if (!n) return innerTickSize;
+      innerTickSize = +x;
+      outerTickSize = +arguments[n - 1];
+      return axis;
+    };
+    axis.innerTickSize = function(x) {
+      if (!arguments.length) return innerTickSize;
+      innerTickSize = +x;
+      return axis;
+    };
+    axis.outerTickSize = function(x) {
+      if (!arguments.length) return outerTickSize;
+      outerTickSize = +x;
+      return axis;
+    };
+    axis.tickPadding = function(x) {
+      if (!arguments.length) return tickPadding;
+      tickPadding = +x;
+      return axis;
+    };
+    axis.tickSubdivide = function() {
+      return arguments.length && axis;
+    };
+    return axis;
+  };
+  var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
+    top: 1,
+    right: 1,
+    bottom: 1,
+    left: 1
+  };
+  function d3_svg_axisX(selection, x) {
+    selection.attr("transform", function(d) {
+      return "translate(" + x(d) + ",0)";
+    });
+  }
+  function d3_svg_axisY(selection, y) {
+    selection.attr("transform", function(d) {
+      return "translate(0," + y(d) + ")";
+    });
+  }
+  d3.svg.brush = function() {
+    var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
+    function brush(g) {
+      g.each(function() {
+        var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
+        var background = g.selectAll(".background").data([ 0 ]);
+        background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
+        g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
+        var resize = g.selectAll(".resize").data(resizes, d3_identity);
+        resize.exit().remove();
+        resize.enter().append("g").attr("class", function(d) {
+          return "resize " + d;
+        }).style("cursor", function(d) {
+          return d3_svg_brushCursor[d];
+        }).append("rect").attr("x", function(d) {
+          return /[ew]$/.test(d) ? -3 : null;
+        }).attr("y", function(d) {
+          return /^[ns]/.test(d) ? -3 : null;
+        }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
+        resize.style("display", brush.empty() ? "none" : null);
+        var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
+        if (x) {
+          range = d3_scaleRange(x);
+          backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
+          redrawX(gUpdate);
+        }
+        if (y) {
+          range = d3_scaleRange(y);
+          backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
+          redrawY(gUpdate);
+        }
+        redraw(gUpdate);
+      });
+    }
+    brush.event = function(g) {
+      g.each(function() {
+        var event_ = event.of(this, arguments), extent1 = {
+          x: xExtent,
+          y: yExtent,
+          i: xExtentDomain,
+          j: yExtentDomain
+        }, extent0 = this.__chart__ || extent1;
+        this.__chart__ = extent1;
+        if (d3_transitionInheritId) {
+          d3.select(this).transition().each("start.brush", function() {
+            xExtentDomain = extent0.i;
+            yExtentDomain = extent0.j;
+            xExtent = extent0.x;
+            yExtent = extent0.y;
+            event_({
+              type: "brushstart"
+            });
+          }).tween("brush:brush", function() {
+            var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
+            xExtentDomain = yExtentDomain = null;
+            return function(t) {
+              xExtent = extent1.x = xi(t);
+              yExtent = extent1.y = yi(t);
+              event_({
+                type: "brush",
+                mode: "resize"
+              });
+            };
+          }).each("end.brush", function() {
+            xExtentDomain = extent1.i;
+            yExtentDomain = extent1.j;
+            event_({
+              type: "brush",
+              mode: "resize"
+            });
+            event_({
+              type: "brushend"
+            });
+          });
+        } else {
+          event_({
+            type: "brushstart"
+          });
+          event_({
+            type: "brush",
+            mode: "resize"
+          });
+          event_({
+            type: "brushend"
+          });
+        }
+      });
+    };
+    function redraw(g) {
+      g.selectAll(".resize").attr("transform", function(d) {
+        return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
+      });
+    }
+    function redrawX(g) {
+      g.select(".extent").attr("x", xExtent[0]);
+      g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
+    }
+    function redrawY(g) {
+      g.select(".extent").attr("y", yExtent[0]);
+      g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
+    }
+    function brushstart() {
+      var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(), center, origin = d3.mouse(target), offset;
+      var w = d3.select(d3_window).on("keydown.brush", keydown).on("keyup.brush", keyup);
+      if (d3.event.changedTouches) {
+        w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
+      } else {
+        w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
+      }
+      g.interrupt().selectAll("*").interrupt();
+      if (dragging) {
+        origin[0] = xExtent[0] - origin[0];
+        origin[1] = yExtent[0] - origin[1];
+      } else if (resizing) {
+        var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
+        offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
+        origin[0] = xExtent[ex];
+        origin[1] = yExtent[ey];
+      } else if (d3.event.altKey) center = origin.slice();
+      g.style("pointer-events", "none").selectAll(".resize").style("display", null);
+      d3.select("body").style("cursor", eventTarget.style("cursor"));
+      event_({
+        type: "brushstart"
+      });
+      brushmove();
+      function keydown() {
+        if (d3.event.keyCode == 32) {
+          if (!dragging) {
+            center = null;
+            origin[0] -= xExtent[1];
+            origin[1] -= yExtent[1];
+            dragging = 2;
+          }
+          d3_eventPreventDefault();
+        }
+      }
+      function keyup() {
+        if (d3.event.keyCode == 32 && dragging == 2) {
+          origin[0] += xExtent[1];
+          origin[1] += yExtent[1];
+          dragging = 0;
+          d3_eventPreventDefault();
+        }
+      }
+      function brushmove() {
+        var point = d3.mouse(target), moved = false;
+        if (offset) {
+          point[0] += offset[0];
+          point[1] += offset[1];
+        }
+        if (!dragging) {
+          if (d3.event.altKey) {
+            if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
+            origin[0] = xExtent[+(point[0] < center[0])];
+            origin[1] = yExtent[+(point[1] < center[1])];
+          } else center = null;
+        }
+        if (resizingX && move1(point, x, 0)) {
+          redrawX(g);
+          moved = true;
+        }
+        if (resizingY && move1(point, y, 1)) {
+          redrawY(g);
+          moved = true;
+        }
+        if (moved) {
+          redraw(g);
+          event_({
+            type: "brush",
+            mode: dragging ? "move" : "resize"
+          });
+        }
+      }
+      function move1(point, scale, i) {
+        var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
+        if (dragging) {
+          r0 -= position;
+          r1 -= size + position;
+        }
+        min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
+        if (dragging) {
+          max = (min += position) + size;
+        } else {
+          if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
+          if (position < min) {
+            max = min;
+            min = position;
+          } else {
+            max = position;
+          }
+        }
+        if (extent[0] != min || extent[1] != max) {
+          if (i) yExtentDomain = null; else xExtentDomain = null;
+          extent[0] = min;
+          extent[1] = max;
+          return true;
+        }
+      }
+      function brushend() {
+        brushmove();
+        g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
+        d3.select("body").style("cursor", null);
+        w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
+        dragRestore();
+        event_({
+          type: "brushend"
+        });
+      }
+    }
+    brush.x = function(z) {
+      if (!arguments.length) return x;
+      x = z;
+      resizes = d3_svg_brushResizes[!x << 1 | !y];
+      return brush;
+    };
+    brush.y = function(z) {
+      if (!arguments.length) return y;
+      y = z;
+      resizes = d3_svg_brushResizes[!x << 1 | !y];
+      return brush;
+    };
+    brush.clamp = function(z) {
+      if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
+      if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
+      return brush;
+    };
+    brush.extent = function(z) {
+      var x0, x1, y0, y1, t;
+      if (!arguments.length) {
+        if (x) {
+          if (xExtentDomain) {
+            x0 = xExtentDomain[0], x1 = xExtentDomain[1];
+          } else {
+            x0 = xExtent[0], x1 = xExtent[1];
+            if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
+            if (x1 < x0) t = x0, x0 = x1, x1 = t;
+          }
+        }
+        if (y) {
+          if (yExtentDomain) {
+            y0 = yExtentDomain[0], y1 = yExtentDomain[1];
+          } else {
+            y0 = yExtent[0], y1 = yExtent[1];
+            if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
+            if (y1 < y0) t = y0, y0 = y1, y1 = t;
+          }
+        }
+        return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
+      }
+      if (x) {
+        x0 = z[0], x1 = z[1];
+        if (y) x0 = x0[0], x1 = x1[0];
+        xExtentDomain = [ x0, x1 ];
+        if (x.invert) x0 = x(x0), x1 = x(x1);
+        if (x1 < x0) t = x0, x0 = x1, x1 = t;
+        if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
+      }
+      if (y) {
+        y0 = z[0], y1 = z[1];
+        if (x) y0 = y0[1], y1 = y1[1];
+        yExtentDomain = [ y0, y1 ];
+        if (y.invert) y0 = y(y0), y1 = y(y1);
+        if (y1 < y0) t = y0, y0 = y1, y1 = t;
+        if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
+      }
+      return brush;
+    };
+    brush.clear = function() {
+      if (!brush.empty()) {
+        xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
+        xExtentDomain = yExtentDomain = null;
+      }
+      return brush;
+    };
+    brush.empty = function() {
+      return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
+    };
+    return d3.rebind(brush, event, "on");
+  };
+  var d3_svg_brushCursor = {
+    n: "ns-resize",
+    e: "ew-resize",
+    s: "ns-resize",
+    w: "ew-resize",
+    nw: "nwse-resize",
+    ne: "nesw-resize",
+    se: "nwse-resize",
+    sw: "nesw-resize"
+  };
+  var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
+  var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
+  var d3_time_formatUtc = d3_time_format.utc;
+  var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
+  d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
+  function d3_time_formatIsoNative(date) {
+    return date.toISOString();
+  }
+  d3_time_formatIsoNative.parse = function(string) {
+    var date = new Date(string);
+    return isNaN(date) ? null : date;
+  };
+  d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
+  d3_time.second = d3_time_interval(function(date) {
+    return new d3_date(Math.floor(date / 1e3) * 1e3);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 1e3);
+  }, function(date) {
+    return date.getSeconds();
+  });
+  d3_time.seconds = d3_time.second.range;
+  d3_time.seconds.utc = d3_time.second.utc.range;
+  d3_time.minute = d3_time_interval(function(date) {
+    return new d3_date(Math.floor(date / 6e4) * 6e4);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 6e4);
+  }, function(date) {
+    return date.getMinutes();
+  });
+  d3_time.minutes = d3_time.minute.range;
+  d3_time.minutes.utc = d3_time.minute.utc.range;
+  d3_time.hour = d3_time_interval(function(date) {
+    var timezone = date.getTimezoneOffset() / 60;
+    return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
+  }, function(date, offset) {
+    date.setTime(date.getTime() + Math.floor(offset) * 36e5);
+  }, function(date) {
+    return date.getHours();
+  });
+  d3_time.hours = d3_time.hour.range;
+  d3_time.hours.utc = d3_time.hour.utc.range;
+  d3_time.month = d3_time_interval(function(date) {
+    date = d3_time.day(date);
+    date.setDate(1);
+    return date;
+  }, function(date, offset) {
+    date.setMonth(date.getMonth() + offset);
+  }, function(date) {
+    return date.getMonth();
+  });
+  d3_time.months = d3_time.month.range;
+  d3_time.months.utc = d3_time.month.utc.range;
+  function d3_time_scale(linear, methods, format) {
+    function scale(x) {
+      return linear(x);
+    }
+    scale.invert = function(x) {
+      return d3_time_scaleDate(linear.invert(x));
+    };
+    scale.domain = function(x) {
+      if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
+      linear.domain(x);
+      return scale;
+    };
+    function tickMethod(extent, count) {
+      var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
+      return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
+        return d / 31536e6;
+      }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
+    }
+    scale.nice = function(interval, skip) {
+      var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
+      if (method) interval = method[0], skip = method[1];
+      function skipped(date) {
+        return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
+      }
+      return scale.domain(d3_scale_nice(domain, skip > 1 ? {
+        floor: function(date) {
+          while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
+          return date;
+        },
+        ceil: function(date) {
+          while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
+          return date;
+        }
+      } : interval));
+    };
+    scale.ticks = function(interval, skip) {
+      var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
+        range: interval
+      }, skip ];
+      if (method) interval = method[0], skip = method[1];
+      return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
+    };
+    scale.tickFormat = function() {
+      return format;
+    };
+    scale.copy = function() {
+      return d3_time_scale(linear.copy(), methods, format);
+    };
+    return d3_scale_linearRebind(scale, linear);
+  }
+  function d3_time_scaleDate(t) {
+    return new Date(t);
+  }
+  var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
+  var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
+  var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
+    return d.getMilliseconds();
+  } ], [ ":%S", function(d) {
+    return d.getSeconds();
+  } ], [ "%I:%M", function(d) {
+    return d.getMinutes();
+  } ], [ "%I %p", function(d) {
+    return d.getHours();
+  } ], [ "%a %d", function(d) {
+    return d.getDay() && d.getDate() != 1;
+  } ], [ "%b %d", function(d) {
+    return d.getDate() != 1;
+  } ], [ "%B", function(d) {
+    return d.getMonth();
+  } ], [ "%Y", d3_true ] ]);
+  var d3_time_scaleMilliseconds = {
+    range: function(start, stop, step) {
+      return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
+    },
+    floor: d3_identity,
+    ceil: d3_identity
+  };
+  d3_time_scaleLocalMethods.year = d3_time.year;
+  d3_time.scale = function() {
+    return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
+  };
+  var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
+    return [ m[0].utc, m[1] ];
+  });
+  var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
+    return d.getUTCMilliseconds();
+  } ], [ ":%S", function(d) {
+    return d.getUTCSeconds();
+  } ], [ "%I:%M", function(d) {
+    return d.getUTCMinutes();
+  } ], [ "%I %p", function(d) {
+    return d.getUTCHours();
+  } ], [ "%a %d", function(d) {
+    return d.getUTCDay() && d.getUTCDate() != 1;
+  } ], [ "%b %d", function(d) {
+    return d.getUTCDate() != 1;
+  } ], [ "%B", function(d) {
+    return d.getUTCMonth();
+  } ], [ "%Y", d3_true ] ]);
+  d3_time_scaleUtcMethods.year = d3_time.year.utc;
+  d3_time.scale.utc = function() {
+    return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
+  };
+  d3.text = d3_xhrType(function(request) {
+    return request.responseText;
+  });
+  d3.json = function(url, callback) {
+    return d3_xhr(url, "application/json", d3_json, callback);
+  };
+  function d3_json(request) {
+    return JSON.parse(request.responseText);
+  }
+  d3.html = function(url, callback) {
+    return d3_xhr(url, "text/html", d3_html, callback);
+  };
+  function d3_html(request) {
+    var range = d3_document.createRange();
+    range.selectNode(d3_document.body);
+    return range.createContextualFragment(request.responseText);
+  }
+  d3.xml = d3_xhrType(function(request) {
+    return request.responseXML;
+  });
+  if (typeof define === "function" && define.amd) {
+    define(d3);
+  } else if (typeof module === "object" && module.exports) {
+    module.exports = d3;
+  } else {
+    this.d3 = d3;
+  }
+}();
\ No newline at end of file
diff --git a/third_party/dom_distiller_js/README.chromium b/third_party/dom_distiller_js/README.chromium
index 33bfdca..8624807 100644
--- a/third_party/dom_distiller_js/README.chromium
+++ b/third_party/dom_distiller_js/README.chromium
@@ -1,6 +1,6 @@
 Name: dom-distiller-js
 URL: https://code.google.com/p/dom-distiller
-Version: 3e2f6f6132
+Version: d690d4a859
 License: BSD
 Security Critical: yes
 
diff --git a/third_party/dom_distiller_js/js/domdistiller.js b/third_party/dom_distiller_js/js/domdistiller.js
index 4ec8b14..9500c16 100644
--- a/third_party/dom_distiller_js/js/domdistiller.js
+++ b/third_party/dom_distiller_js/js/domdistiller.js
@@ -1,385 +1,392 @@
-var $gwt_version = "2.5.1";var $wnd = window;var $doc = $wnd.document;var $moduleName, $moduleBase;var $strongName = '784023040D0A953E845B47403FDFC0D1';var $stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent(a);} : null,$sessionId = $wnd.__gwtStatsSessionId ? $wnd.__gwtStatsSessionId : null;$stats && $stats({moduleName:'domdistiller',sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalStart'});
-function R(){}
-function mp(){}
-function xb(){}
-function Bc(){}
-function Lc(){}
-function ld(){}
-function od(){}
-function yh(){}
-function Eh(){}
-function Jh(){}
-function Oh(){}
-function Th(){}
-function sj(){}
-function lp(){}
-function I(){H()}
-function ed(){Vc()}
-function Yb(){Yc(Vc())}
-function Hb(){Fb(this)}
-function O(){M(this)}
-function X(){V(this)}
-function Ki(){pi(this)}
-function bl(){Wk(this)}
-function dn(){Xm(this)}
-function Xf(){new dn}
-function Wf(a,b){a.b=b}
-function mg(a,b){a.q=b}
-function hd(a,b){a.b+=b}
-function id(a,b){a.b+=b}
-function jd(a,b){a.b+=b}
-function hb(a){this.b=a}
-function wg(a){this.b=a}
-function ah(a){this.b=a}
-function ch(a){this.b=a}
-function Yh(a){this.b=a}
-function bj(a){this.b=a}
-function ij(a){this.b=a}
-function Gj(a){this.b=a}
-function Uj(a){this.b=a}
-function xl(a){this.b=a}
-function Kl(a){this.b=a}
-function Bm(a){this.b=a}
-function Mm(a){this.b=a}
-function gm(a){this.e=a}
-function An(a){this.b=a}
-function Mn(){this.b=new Ki}
-function Tk(){this.b=new ld}
-function Wk(a){a.b=new ld}
-function $f(){$f=mp;new Xf}
-function yc(){yc=mp;xc=new Bc}
-function Qi(){Qi=mp;Pi=new Ri}
-function cp(){cp=mp;bp=new Xo}
-function H(){H=mp;$f();Vf(Cp)}
-function Z(){Z=mp;$f();Vf(Cp)}
-function Xi(){Yb.call(this)}
-function Bj(){Yb.call(this)}
-function Pj(){Yb.call(this)}
-function ek(){Yb.call(this)}
-function uo(){Yb.call(this)}
-function Nj(a){Zb.call(this,a)}
-function Rj(a){Zb.call(this,a)}
-function il(a){Zb.call(this,a)}
-function ik(a){Nj.call(this,a)}
-function Li(a){Di.call(this,a)}
-function Zb(a){Yc(Vc());this.f=a}
-function qb(a,b){Vn(a.b,b)}
-function Po(a,b,c){zi(a.c,b,c)}
-function pn(a,b,c){a.splice(b,c)}
-function nn(a,b){a.length=b}
-function hj(a,b){return a.b-b.b}
-function bk(a,b){return a>b?a:b}
-function ck(a,b){return a<b?a:b}
-function Ln(a,b){return ri(a.b,b)}
-function bg(b,a){return b.exec(a)}
-function wi(b,a){return b.f[Rp+a]}
-function Sf(a){return new Qf[a]}
-function dm(a){return a.c<a.e.M()}
-function Fc(a){return Jc((Vc(),a))}
-function Ag(a){return a>=48&&a<=57}
-function dp(a){cp();return Ro(a)}
-function Nn(){this.b=new Li(2)}
-function mo(){this.b=this.c=this}
-function Lo(a){this.c=a;this.b=Bq}
-function qg(a,b){this.c=a;this.b=b}
-function Pl(a,b){this.c=a;this.b=b}
-function Ug(a,b){this.b=a;this.c=b}
-function wm(a,b){this.b=a;this.c=b}
-function Gm(a,b){this.b=a;this.c=b}
-function po(a,b){this.b=a;this.c=b}
-function Yk(a,b){hd(a.b,b);return a}
-function Zk(a,b){id(a.b,b);return a}
-function Yn(a){_n(a);return a.b.c.d}
-function Fj(a,b){return Hj(a.b,b.b)}
-function yi(b,a){return Rp+a in b.f}
-function rk(b,a){return b.indexOf(a)}
-function Id(a){return a==null?null:a}
-function ag(a){$f();_f.call(this,a)}
-function Eo(){$f();_f.call(this,Ep)}
-function cl(a){dl.call(this,a.tS())}
-function uc(a){$wnd.clearTimeout(a)}
-function Xm(a){a.b=td(Kf,qp,0,0,0)}
-function ep(a,b,c){cp();To(bp,a,b,c)}
-function qn(a,b,c,d){a.splice(b,c,d)}
-function Wn(a,b,c){new no(b,c);++a.c}
-function Xn(a,b){new no(b,a.b);++a.c}
-function Cd(a,b){return a.cM&&a.cM[b]}
-function Ck(a){return td(Mf,qp,1,a,0)}
-function Gc(a){return parseInt(a)||-1}
-function Yo(a){return a&&a.g?a.g:null}
-function pd(a){return qd(a,0,a.length)}
-function tc(a){return a.$H||(a.$H=++lc)}
-function Bd(a,b){return a.cM&&!!a.cM[b]}
-function Hd(a){return a.tM==mp||Bd(a,1)}
-function xj(a){return typeof a==yq&&a>0}
-function nk(b,a){return b.charCodeAt(a)}
-function dl(a){Wk(this);id(this.b,a)}
-function en(a){Xm(this);nn(this.b,a)}
-function sb(a){this.c=a;this.b=new ao}
-function cb(a){this.b=a;this.c=new dn}
-function ao(){this.b=new mo;this.c=0}
-function Ok(){Ok=mp;Lk={};Nk={}}
-function $o(a,b){for(p in b){a[p]=b[p]}}
-function Xl(a,b){(a<0||a>=b)&&$l(a,b)}
-function Fd(a,b){return a!=null&&Bd(a,b)}
-function cg(c,a,b){return a.replace(c,b)}
-function Ao(a,b){return Dd(ui(a.b,b),30)}
-function dc(a){return Gd(a)?Fc(Ed(a)):Ep}
-function cc(a){return a==null?null:a.name}
-function md(b,a){return b.appendChild(a)}
-function sk(b,a){return b.lastIndexOf(a)}
-function zk(c,a,b){return c.substr(a,b-a)}
-function _m(a,b){Xl(b,a.c);return a.b[b]}
-function go(a){if(!a.d){throw new Pj}}
-function _n(a){if(a.c==0){throw new uo}}
-function jp(){this.b=new dn;this.c=new Ki}
-function Cb(a,b){this.d=0;this.c=a;this.b=b}
-function Hg(a,b){this.c=1;this.b=a;this.d=b}
-function gp(a,b){cp();a['__gwtex_wrap']=b}
-function Yc(){var a;a=Wc(new ed);$c(a)}
-function qj(){qj=mp;pj=td(If,qp,14,128,0)}
-function ak(){ak=mp;_j=td(Jf,qp,18,256,0)}
-function $(){$=mp;$f();Vf('DomToSaxParser')}
-function ph(){gh();qh.call(this,(Qi(),Pi))}
-function _b(a){return Gd(a)?ac(Ed(a)):a+Ep}
-function oc(a,b,c){return a.apply(b,c);var d}
-function aj(a,b){return a.b==b.b?0:a.b?1:-1}
-function ac(a){return a==null?null:a.message}
-function Kk(a){return String.fromCharCode(a)}
-function tk(c,a,b){return c.lastIndexOf(a,b)}
-function hc(a){var b;return b=a,Hd(b)?b.cZ:Yd}
-function wj(a){var b=Qf[a.c];a=null;return b}
-function Go(a){a.b=bg(a.d,a.c);return !!a.b}
-function Zm(a,b){vd(a.b,a.c++,b);return true}
-function Kc(){try{null.a()}catch(a){return a}}
-function Vc(){Vc=mp;Error.stackTraceLimit=128}
-function ug(){ug=mp;tg=new wg(60);new wg(200)}
-function $g(){$g=mp;new ah(null);Zg=new ah(Dp)}
-function yd(){yd=mp;wd=[];xd=[];zd(new od,wd,xd)}
-function _f(a){$f();this.b=new Xf;Wf(this.b,a)}
-function On(a){this.b=new Li(a.b.e);kl(this,a)}
-function Mo(a){this.c=a;this.b=Bq;this.b+='i'}
-function ho(a,b,c){this.e=a;this.c=c;this.b=b}
-function lo(a){a.b.c=a.c;a.c.b=a.b;a.b=a.c=a}
-function Tj(a,b){return a.b<b.b?-1:a.b>b.b?1:0}
-function Ko(a,b){return new Io(a.c,a.b,b.tS())}
-function yk(b,a){return b.substr(a,b.length-a)}
-function kd(a,b){a.b=a.b.substr(0,0-0)+Ep+yk(a.b,b)}
-function wn(a,b,c){var d;d=qd(a,b,c);xn(d,a,b,c,-b)}
-function Kn(a,b){var c;c=zi(a.b,b,a);return c==null}
-function Vn(a,b){new no(b,a.b);++a.c;return true}
-function Cc(a,b){!a&&(a=[]);a[a.length]=b;return a}
-function Hc(a,b){a.length>=b&&a.splice(0,b);return a}
-function Lm(a){var b;b=Dd(em(a.b.b),27).Z();return b}
-function ic(a){var b;return b=a,Hd(b)?b.hC():tc(b)}
-function gc(a,b){var c;return c=a,Hd(c)?c.eQ(b):c===b}
-function gi(a){var b;b=new xl(a);return new wm(a,b)}
-function vm(a){var b;b=new Cl(a.c.b);return new Bm(b)}
-function Fm(a){var b;b=new Cl(a.c.b);return new Mm(b)}
-function Of(a){if(Fd(a,23)){return a}return new $b(a)}
-function nh(a,b){if(b==null||b.length==0){return}a.w=b}
-function kk(a,b){this.b=cq;this.e=a;this.c=b;this.d=-1}
-function pi(a){a.b=[];a.f={};a.d=false;a.c=null;a.e=0}
-function _i(){_i=mp;Zi=new bj(false);$i=new bj(true)}
-function Kg(){Kg=mp;Jg=new Lo('[\\?\\!\\.\\-\\:]+')}
-function $l(a,b){throw new Rj('Index: '+a+', Size: '+b)}
-function Ji(a,b){return Id(a)===Id(b)||a!=null&&gc(a,b)}
-function vo(a,b){return Id(a)===Id(b)||a!=null&&gc(a,b)}
-function Gd(a){return a!=null&&a.tM!=mp&&!Bd(a,1)}
-function M(a){if(!L){L=true;cp();Po(bp,Ld,a);N(a)}}
-function V(a){if(!U){U=true;cp();Po(bp,Nd,a);W(a)}}
-function Fb(a){if(!Eb){Eb=true;cp();Po(bp,Vd,a);Gb(a)}}
-function jh(a){if(!a.q){Xk(a.x,32);Xk(a.u,32);a.q=true}}
-function Rk(){if(Mk==256){Lk=Nk;Nk={};Mk=0}++Mk}
-function lm(a,b){if(a.d==-1){throw new Pj}a.b.cb(a.d,b)}
-function fp(a,b,c,d,e,f){cp();return Uo(bp,a,b,c,d,e,f)}
-function td(a,b,c,d,e){var f;f=sd(e,d);ud(a,b,c,f);return f}
-function Xk(a,b){jd(a.b,String.fromCharCode(b));return a}
-function Dd(a,b){if(a!=null&&!Cd(a,b)){throw new Bj}return a}
-function Jb(a,b){var c;c=new Lb(a);gb(new hb(c),b);return c.b}
-function $n(a){var b;_n(a);--a.c;b=a.b.c;lo(b);return b.d}
-function Xc(a,b){var c;c=Zc(a,Gd(b.c)?Ed(b.c):null);$c(c)}
-function ip(a,b){var c;zi(a.c,b,$j(a.b.c));c=new lp;Zm(a.b,c)}
-function Hn(a,b){var c,d;d=a.c;for(c=0;c<d;++c){cn(a,c,b[c])}}
-function wk(c,a,b){b=Dk(b);return c.replace(RegExp(a),b)}
-function vk(c,a,b){b=Dk(b);return c.replace(RegExp(a,Bq),b)}
-function ok(a,b){if(!Fd(b,1)){return false}return String(a)==b}
-function Gk(a,b){a=String(a);if(a==b){return 0}return a<b?-1:1}
-function Ho(a,b){a.b=null;a.d.lastIndex=0;return cg(a.d,a.c,b)}
-function gl(a){Zb.call(this,'String index out of range: '+a)}
-function $b(a){Yb.call(this);this.c=a;this.b=Ep;Xc(new ed,this)}
-function Lb(a){this.c=false;this.d=new vb(a);this.b=new dn}
-function mb(a){this.c=new vb(a);this.b=new dn;this.e=new dn}
-function Xo(){this.c=new Ki;this.b=new Ki;this.d=new Ki}
-function Co(){this.b=new Ki;this.c=new Eo;zi(this.b,Ep,this.c)}
-function vb(a){this.c=new gm(a);a.c==0||(this.b=Ed(em(this.c)))}
-function Io(a,b,c){this.d=new RegExp(a,b);this.c=c;this.b=null}
-function no(a,b){this.d=a;this.b=b;this.c=b.c;b.c.b=this;b.c=this}
-function lg(a,b){if(b!=a.c){a.c=b;return true}else{return false}}
-function yo(a,b){if(Ao(a,b.b.b)){return false}zo(a,b);return true}
-function jb(a,b){while(a.b.c==1&&a.c!=b){a=Dd(Qm(a.b,0),4)}return a}
-function cn(a,b,c){var d;d=(Xl(b,a.c),a.b[b]);vd(a.b,b,c);return d}
-function Ym(a,b,c){(b<0||b>a.c)&&$l(b,a.c);qn(a.b,b,0,c);++a.c}
-function km(a){if(a.c<=0){throw new uo}return a.b.ab(a.d=--a.c)}
-function fm(a){if(a.d<0){throw new Pj}a.e.bb(a.d);a.c=a.d;a.d=-1}
-function Bi(a,b){var c;c=a.c;a.c=b;if(!a.d){a.d=true;++a.e}return c}
-function rd(a,b){var c,d;c=a;d=sd(0,b);ud(c.cZ,c.cM,c.qI,d);return d}
-function ud(a,b,c,d){yd();Ad(d,wd,xd);d.cZ=a;d.cM=b;d.qI=c;return d}
-function Ad(a,b,c){yd();for(var d=0,e=b.length;d<e;++d){a[b[d]]=c[d]}}
-function qk(a,b,c,d){var e;for(e=0;e<b;++e){c[d++]=a.charCodeAt(e)}}
-function rc(a,b,c){var d;d=pc();try{return oc(a,b,c)}finally{sc(d)}}
-function rn(a,b,c,d){Array.prototype.splice.apply(a,[b,c].concat(d))}
-function $k(a,b){jd(a.b,String.fromCharCode.apply(null,b));return a}
-function vj(a,b){var c;c=new sj;c.e=a+b;xj(0)&&yj(0,c);c.b=2;return c}
-function bn(a,b){var c;c=(Xl(b,a.c),a.b[b]);pn(a.b,b,1);--a.c;return c}
-function zn(a,b,c){var d;Xl(b,a.b.length);d=a.b[b];vd(a.b,b,c);return d}
-function Wo(a,b){var c=[a];for(i=0;i<b.length;i++)c.push(b[i]);return c}
-function So(a,b){var c=a[b];var d=0;for(k in c)d=Math.max(d,k);return d}
-function nd(a){var b=a.parentNode;(!b||b.nodeType!=1)&&(b=null);return b}
-function Ed(a){if(a!=null&&(a.tM==mp||Bd(a,1))){throw new Bj}return a}
-function em(a){if(a.c>=a.e.M()){throw new uo}return a.e.ab(a.d=a.c++)}
-function kg(a){if(a.k==0){a.k=a.i;a.n=1}a.s=a.k/a.n;a.e=a.i==0?0:a.j/a.i}
-function bc(a){return a==null?Yp:Gd(a)?cc(Ed(a)):Fd(a,1)?Zp:hc(a).e}
-function ri(a,b){return b==null?a.d:Fd(b,1)?yi(a,Dd(b,1)):xi(a,b,a.P(b))}
-function ui(a,b){return b==null?a.c:Fd(b,1)?wi(a,Dd(b,1)):vi(a,b,a.P(b))}
-function Jd(a){return ~~Math.max(Math.min(a,2147483647),-2147483648)}
-function vc(){return $wnd.setTimeout(function(){kc!=0&&(kc=0);nc=-1},10)}
-function sc(a){a&&Ac((yc(),xc));--kc;if(a){if(nc!=-1){uc(nc);nc=-1}}}
-function Zc(a,b){var c;c=Rc(a,b);return c.length==0?(new Lc).E(b):Hc(c,1)}
-function Ek(a,b,c){a=a.slice(b,c);return String.fromCharCode.apply(null,a)}
-function qd(a,b,c){var d,e;d=a;e=d.slice(b,c);ud(d.cZ,d.cM,d.qI,e);return e}
-function Ob(a,b,c){var d,e;e=new Mo(b);d=new Io(e.c,e.b,a);return Ho(d,c)}
-function uj(a,b,c,d){var e;e=new sj;e.e=a+b;xj(c)&&yj(c,e);e.d=d;return e}
-function _k(a,b,c,d){var e;jd(a.b,(e=c+d,Bk(b.length,c,e),Ek(b,c,e)));return a}
-function an(a,b,c){for(;c<a.c;++c){if(vo(b,a.b[c])){return c}}return -1}
-function Ci(e,a,b){var c,d=e.f;a=Rp+a;a in d?(c=d[a]):++e.e;d[a]=b;return c}
-function zd(a,b,c){var d=0,e;for(var f in a){if(e=a[f]){b[d]=f;c[d]=e;++d}}}
-function mm(a,b){var c;this.b=a;this.e=a;c=a.M();(b<0||b>c)&&$l(b,c);this.c=b}
-function Ac(a){var b,c;if(a.c){c=null;do{b=a.c;a.c=null;c=Dc(b,c)}while(a.c);a.c=c}}
-function zc(a){var b,c;if(a.b){c=null;do{b=a.b;a.b=null;c=Dc(b,c)}while(a.b);a.b=c}}
-function fo(a){if(a.c==a.e.b){throw new uo}a.d=a.c;a.c=a.c.b;++a.b;return a.d.d}
-function ub(a,b){if(b!=a.b)return false;a.b=dm(a.c)?Ed(em(a.c)):null;return true}
-function kl(a,b){var c,d;d=b.T();c=false;while(d.W()){a.Q(d.X())&&(c=true)}return c}
-function Qb(a,b){var c,d;d=new Mo(b);c=new Io(d.c,d.b,a);return c.b=bg(c.d,c.c),!!c.b}
-function hh(a,b){var c;c=Dd(Yn(a.n),24);if(!c){c=new ao;$n(a.n);Xn(a.n,c)}Xn(c,b)}
-function zo(a,b){var c,d;c=b.b.b;d=zk(c,0,bk(0,sk(c,Ik(46))));Bo(a,d);zi(a.b,b.b.b,b)}
-function Bo(a,b){var c,d;c=Dd(ui(a.b,b),30);if(!c){d=new _f(b);zo(a,d);return d}return c}
-function Wc(a){var b;b=Hc(Zc(a,Kc()),3);b.length==0&&(b=Hc((new Lc).C(),1));return b}
-function ib(a){var b;for(b=a.parentNode;!!b&&b.nodeType!=9;a=b,b=b.parentNode){}return a}
-function al(a){var b;b=a.b.b.length;0<b?(kd(a.b,b),a):0>b&&$k(a,td(Hf,qp,-1,-b,1))}
-function Cl(a){var b;b=new dn;a.d&&Zm(b,new Kl(a));oi(a,b);ni(a,b);this.b=new gm(b)}
-function Sg(){Sg=mp;new Ug(false,0);new Ug(true,0);Rg=new Ug(true,150)}
-function gh(){gh=mp;fh=new Lo('[\\p{L}\\p{Nd}\\p{Nl}\\p{No}]')}
-function qc(b){return function(){try{return rc(b,this,arguments)}catch(a){throw a}}}
-function pk(b,a){if(a==null)return false;return b==a||b.toLowerCase()==a.toLowerCase()}
-function Bk(a,b,c){if(b<0){throw new gl(b)}if(c<b){throw new gl(c-b)}if(c>a){throw new gl(c)}}
-function zi(a,b,c){return b==null?Bi(a,c):Fd(b,1)?Ci(a,Dd(b,1),c):Ai(a,b,c,~~ic(b))}
-function Vi(a){Ui();return xk(Ak(vk(Ho(Ko(Si,Ho(Ko(Ti,a),'\u2063')),Gp),'[ \u2063]+',Sp)),'[ ]+',0)}
-function ig(){ig=mp;gg=new Mn;hg=new ng(Ep,gg,0,0,0,0,-1);new ng(Ep,gg,0,0,0,0,2147483647)}
-function wh(){wh=mp;th=new yh;rh=new Eh;sh=new Jh;vh=new Oh;uh=new Th;new Lo('([\\+\\-]?)([0-9])')}
-function Fg(){Fg=mp;Dg=new Hg(false,false);new Hg(false,true);new Hg(true,false);Eg=new Hg(true,true)}
-function Dh(a){if(--a.f==0){if(a.k==0){jh(a);Zk(a.x,vq);Xk(a.x,32);a.q=true}}return false}
-function ll(a,b){var c;while(a.W()){c=a.X();if(b==null?c==null:gc(b,c)){return a}}return null}
-function oj(a){var b;if(a<128){b=(qj(),pj)[a];!b&&(b=pj[a]=new ij(a));return b}return new ij(a)}
-function Hj(a,b){if(isNaN(a)){return isNaN(b)?0:1}else if(isNaN(b)){return -1}return a<b?-1:a>b?1:0}
-function gb(a,b){var c,d;if(!a.b.A(b))return;c=b.childNodes;for(d=0;d<c.length;++d){gb(a,c[d])}a.b.z(b)}
-function jg(a,b){var c,d,e;if(b==null){return}!a.d&&(a.d=new Mn);for(d=0,e=b.length;d<e;++d){c=b[d];Kn(a.d,c)}}
-function $m(a,b){var c,d;c=b.U();d=c.length;if(d==0){return false}rn(a.b,a.c,0,c);a.c+=d;return true}
-function tj(a,b,c){var d;d=new sj;d.e=a+b;xj(c!=0?-c:0)&&yj(c!=0?-c:0,d);d.b=4;d.d=Oe;return d}
-function Ab(a){var b,c;c=Ep;for(b=a.c-1;b>=0;--b){c+=(Xl(b,a.c),Dd(a.b[b],1));b>0&&(c+=Lp)}return c}
-function Pb(a){var b;for(b=0;b<a.length;++b){if(rk(Xp,Ik(oj(a.charCodeAt(b)).b))==-1)return false}return true}
-function Vf(a){var b,c,d;c=(!xo&&(xo=new Co),xo);b=Dd(ui(c.b,a),30);if(!b){d=new ag(a);yo(c,d);return d}return b}
-function rb(a){var b,c,d;d=a.c.cloneNode(false);for(c=Zn(a.b,0);c.c!=c.e.b;){b=Dd(fo(c),4);md(d,rb(b))}return d}
-function Rc(a,b){var c,d,e;e=b&&b.stack?b.stack.split(aq):[];for(c=0,d=e.length;c<d;++c){e[c]=a.D(e[c])}return e}
-function Vb(a){var b,c,d;c=td(Lf,qp,21,a.length,0);for(d=0,b=a.length;d<b;++d){if(!a[d]){throw new ek}c[d]=a[d]}}
-function gwtOnLoad(b,c,d,e){$moduleName=c;$moduleBase=d;if(b)try{Ap(Nf)()}catch(a){b(c)}else{Ap(Nf)()}}
-function oi(e,a){var b=e.f;for(var c in b){if(c.charCodeAt(0)==58){var d=new Pl(e,c.substring(1));a.Q(d)}}}
-function si(e,a){var b=e.f;for(var c in b){if(c.charCodeAt(0)==58){var d=b[c];if(e.O(a,d)){return true}}}return false}
-function $j(a){var b,c;if(a>-129&&a<128){b=a+128;c=(ak(),_j)[b];!c&&(c=_j[b]=new Uj(a));return c}return new Uj(a)}
-function Qk(a){Ok();var b=Rp+a;var c=Nk[b];if(c!=null){return c}c=Lk[b];c==null&&(c=Pk(a));Rk();return Nk[b]=c}
-function kj(a){if(a>=48&&a<58){return a-48}if(a>=97&&a<97){return a-97+10}if(a>=65&&a<65){return a-65+10}return -1}
-function ti(a,b){if(a.d&&Ji(a.c,b)){return true}else if(si(a,b)){return true}else if(qi(a,b)){return true}return false}
-function Di(a){pi(this);if(a<0){throw new Nj('initial capacity was negative or load factor was non-positive')}}
-function qh(a){this.x=new bl;this.u=new bl;this.t=new dn;this.c=new Mn;this.n=new ao;this.e=new ao;this.r=a}
-function ng(a,b,c,d,e,f,g){ig();this.r=a;this.b=b;this.i=c;this.j=d;this.k=e;this.n=f;this.p=g;this.o=g;kg(this)}
-function vn(a,b,c,d,e,f,g){var h;h=c;while(f<g){h>=d||b<c&&Dd(a[b],16).cT(a[h])<=0?vd(e,f++,a[b++]):vd(e,f++,a[h++])}}
-function un(a,b,c){var d,e,f;for(d=b+1;d<c;++d){for(e=d;e>b&&Dd(a[e-1],16).cT(a[e])>0;--e){f=a[e];vd(a,e,a[e-1]);vd(a,e-1,f)}}}
-function lh(a,b,c){var d;d=Dd(ui(a.r,b),10);d?(a.d=d.H(a,b,c)|a.d):(a.d=true);(!d||d.G())&&--a.s;a.d&&mh(a);$n(a.n)}
-function oh(a,b,c,d){var e;Xn(a.n,null);e=Dd(ui(a.r,b),10);if(e){e.G()&&++a.s;a.d=e.I(a,b,c,d)|a.d}else{++a.s;a.d=true}a.o=b}
-function To(a,b,c,d){var e,f;f=d?a.d:a.b;e=Ed(!b?f.c:vi(f,b,~~tc(b)));!e?(e=c):$o(e,c);!b?Bi(f,e):Ai(f,b,e,~~tc(b))}
-function Oi(a,b,c){zi(a,b.toUpperCase(),c);zi(a,b.toLowerCase(),c);b==null?Bi(a,c):b!=null?Ci(a,b,c):Ai(a,null,c,~~Qk(null))}
-function fi(a,b){var c,d,e;for(d=new Cl(a.K().b);dm(d.b);){c=Dd(em(d.b),27);e=c.Y();if(b==null?e==null:gc(b,e)){return c}}return null}
-function vi(h,a,b){var c=h.b[b];if(c){for(var d=0,e=c.length;d<e;++d){var f=c[d];var g=f.Y();if(h.O(a,g)){return f.Z()}}}return null}
-function xi(h,a,b){var c=h.b[b];if(c){for(var d=0,e=c.length;d<e;++d){var f=c[d];var g=f.Y();if(h.O(a,g)){return true}}}return false}
-function pc(){var a;if(kc!=0){a=(new Date).getTime();if(a-mc>2000){mc=a;nc=vc()}}if(kc++==0){zc((yc(),xc));return true}return false}
-function Ui(){Ui=mp;Ti=new Lo('\\b');Si=new Lo('[\u2063]*([\\"\'\\.,\\!\\@\\-\\:\\;\\$\\?\\(\\)/])[\u2063]*')}
-function ni(h,a){var b=h.b;for(var c in b){var d=parseInt(c,10);if(c==d){var e=b[d];for(var f=0,g=e.length;f<g;++f){a.Q(e[f])}}}}
-function Qm(b,c){var d;d=Zn(b,c);try{return fo(d)}catch(a){a=Of(a);if(Fd(a,28)){throw new Rj("Can't get element "+c)}else throw a}}
-function Ak(c){if(c.length==0||c[0]>Sp&&c[c.length-1]>Sp){return c}var a=c.replace(/^(\s*)/,Ep);var b=a.replace(/\s*$/,Ep);return b}
-function lb(a){var b;for(b=0;b<a.b.c;++b){if(_m(a.e,b)==null){cn(a.e,b,new sb(Ed(_m(a.b,b))));qb(Dd(_m(a.e,b-1),4),Dd(_m(a.e,b),4))}}}
-function ab(a){$();var b,c,d,e;b=new jp;e=a.attributes;for(c=0;c<e.length;++c){d=e[c];ip(b,(d.nodeName,d.nodeName),d.nodeValue)}return b}
-function Xg(a){var b,c,d,e;b=false;d=a.b;for(c=new mm(d,d.c);c.c>0;){e=Dd(km(c),8);if(e.c){if(!!e.d&&Ln(e.d,rq)){lg(e,false);b=true}else{break}}}return b}
-function _g(a,b){var c,d,e,f;f=b.b;c=false;for(d=new gm(f);d.c<d.e.M();){e=Dd(em(d),8);if(!e.c&&(a.b==null||!(!!e.d&&Ln(e.d,Dp)))){fm(d);c=true}}return c}
-function Jc(b){var c=Ep;try{for(var d in b){if(d!='name'&&d!='message'&&d!='toString'){try{c+='\n '+d+Ip+b[d]}catch(a){}}}}catch(a){}return c}
-function ap(a,b){var c=a[b];var d=c==null?Yp:typeof c;if(d==Kp){return Object.prototype.toString.call(c)==Dq||typeof c.length==yq?'array':d}return d}
-function Ul(a,b){var c,d;for(c=0,d=a.b.length;c<d;++c){if(b==null?(Xl(c,a.b.length),a.b[c])==null:gc(b,(Xl(c,a.b.length),a.b[c]))){return c}}return -1}
-function Dc(b,c){var d,e,f;for(d=0,e=b.length;d<e;++d){f=b[d];try{f[1]?f[0].db()&&(c=Cc(c,f)):f[0].db()}catch(a){a=Of(a);if(!Fd(a,23))throw a}}return c}
-function Dk(a){var b;b=0;while(0<=(b=a.indexOf('\\',b))){a.charCodeAt(b+1)==36?(a=a.substr(0,b-0)+'$'+yk(a,++b)):(a=a.substr(0,b-0)+yk(a,++b))}return a}
-function Zn(a,b){var c,d;(b<0||b>a.c)&&$l(b,a.c);if(b>=~~a.c>>1){d=a.b;for(c=a.c;c>b;--c){d=d.c}}else{d=a.b.b;for(c=0;c<b;++c){d=d.b}}return new ho(a,b,d)}
-function Zo(a,b){var c;if(Oe==b){return true}if(Cf==b&&Fd(a,31)){return true}if(a!=null){for(c=hc(a);!!c&&c!=Oe;c=c.d){if(c==b){return true}}}return false}
-function uk(d,a,b){var c;if(a<256){c=Yj(a);c='\\x'+'00'.substring(c.length)+c}else{c=String.fromCharCode(a)}return d.replace(RegExp(c,Bq),String.fromCharCode(b))}
-function Lg(a,b,c){var d,e,f,g;g=xk(b,c,0);if(g.length==1){return}for(d=0;d<g.length;++d){f=g[d];if(f.indexOf(lq)!=-1){continue}e=xk(f,mq,0).length;e>=4&&Kn(a,f)}}
-function yj(a,b){var c;b.c=a;if(a==2){c=String.prototype}else{if(a>0){var d=wj(b);if(d){c=d.prototype}else{d=Qf[a]=function(){};d.cZ=b;return}}else{return}}c.cZ=b}
-function gk(){gk=mp;fk=ud(Hf,qp,-1,[48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122])}
-function Yj(a){var b,c,d;b=td(Hf,qp,-1,8,1);c=(gk(),fk);d=7;if(a>=0){while(a>15){b[d--]=c[a&15];a>>=4}}else{while(d>0){b[d--]=c[a&15];a>>=4}}b[d]=c[a&15];return Ek(b,d,8)}
-function ml(a){var b,c,d,e;d=new Tk;b=null;d.b.b+=dq;c=a.T();while(c.W()){b!=null?(id(d.b,b),d):(b=wq);e=c.X();id(d.b,e===a?'(this Collection)':Ep+e)}d.b.b+=eq;return d.b.b}
-function sd(a,b){var c=new Array(b);if(a==3){for(var d=0;d<b;++d){var e=new Object;e.l=e.m=e.h=0;c[d]=e}}else if(a>0){var e=[null,0,false][a];for(var d=0;d<b;++d){c[d]=e}}return c}
-function qi(l,a){var b=l.b;for(var c in b){var d=parseInt(c,10);if(c==d){var e=b[d];for(var f=0,g=e.length;f<g;++f){var h=e[f];var j=h.Z();if(l.O(a,j)){return true}}}}return false}
-function xg(a,b,c){var d;b.e<=0.333333?a.e<=0.555556?b.i<=16?c.i<=15?a.i<=4?(d=false):(d=true):(d=true):(d=true):b.i<=40?c.i<=17?(d=false):(d=true):(d=true):(d=false);return lg(b,d)}
-function Ro(a){var b,c,d,e,f;f=xk(a,'\\.',0);e=$wnd;b=0;for(c=f.length-1;b<c;++b){if(!ok(f[b],'client')){e[f[b]]||(e[f[b]]={});e=e!=null?e[f[b]]:null}}d=e!=null?e[f[b]]:null;return d}
-function Bg(a,b,c){var d,e,f,g;d=0;while(d<b&&Ag(a.charCodeAt(d))){++d}if(d!=0){for(f=0,g=c.length;f<g;++f){e=c[f];if(!(d<0||d>=a.length)&&a.indexOf(e,d)==d){return true}}}return false}
-function Tf(a){return $stats({moduleName:$moduleName,sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date).getTime(),type:'onModuleLoadStart',className:a})}
-function om(a,b,c){this.d=a;this.b=b;this.c=c-b;if(b>c){throw new Nj(Cq+b+' > toIndex: '+c)}if(b<0){throw new Rj(Cq+b+' < 0')}if(c>a.c){throw new Rj('toIndex: '+c+' > wrapped.size() '+a.c)}}
-function Ec(a){var b,c,d;d=Ep;a=Ak(a);b=a.indexOf($p);c=a.indexOf('function')==0?8:0;if(b==-1){b=rk(a,Ik(64));c=a.indexOf('function ')==0?9:0}b!=-1&&(d=Ak(a.substr(c,b-c)));return d.length>0?d:_p}
-function vg(a,b){var c,d,e,f,g,h;d=false;h=0;f=false;for(g=new gm(b.b);g.c<g.e.M();){c=Dd(em(g),8);e=!!c.d&&Ln(c.d,kq);c.c&&(h+=c.s>=9?c.i:0);e&&h>=a.b&&(f=true);if(f){d=true;lg(c,false)}}return d}
-function Ik(a){var b,c;if(a>=65536){b=55296+(~~(a-65536)>>10&1023)&65535;c=56320+(a-65536&1023)&65535;return String.fromCharCode(b)+String.fromCharCode(c)}else{return String.fromCharCode(a&65535)}}
-function Ai(l,a,b,c){var d=l.b[c];if(d){for(var e=0,f=d.length;e<f;++e){var g=d[e];var h=g.Y();if(l.O(a,h)){var j=g.Z();g.$(b);return j}}}else{d=l.b[c]=[]}var g=new po(a,b);d.push(g);++l.e;return null}
-function Pk(a){var b,c,d,e;b=0;d=a.length;e=d-4;c=0;while(c<e){b=a.charCodeAt(c+3)+31*(a.charCodeAt(c+2)+31*(a.charCodeAt(c+1)+31*(a.charCodeAt(c)+31*b)))|0;c+=4}while(c<d){b=b*31+nk(a,c++)}return b|0}
-function vd(a,b,c){if(c!=null){if(a.qI>0&&!Cd(c,a.qI)){throw new Xi}else if(a.qI==-1&&(c.tM==mp||Bd(c,1))){throw new Xi}else if(a.qI<-1&&!(c.tM!=mp&&!Bd(c,1))&&!Cd(c,-a.qI)){throw new Xi}}return a[b]=c}
-function xn(a,b,c,d,e){var f,g,h,j;f=d-c;if(f<7){un(b,c,d);return}h=c+e;g=d+e;j=h+(~~(g-h)>>1);xn(b,a,h,j,-e);xn(b,a,j,g,-e);if(Dd(a[j-1],16).cT(a[j])<=0){while(c<d){vd(b,c++,a[h++])}return}vn(a,h,j,g,b,c,d)}
-function Qo(a,b){var c=[];for(i=0;i<a-1;i++)c.push(b[i]);var d=b.length;var e=a-1;if(d>=a&&Object.prototype.toString.apply(b[e])===Dq){c.push(b[e])}else{var f=[];for(i=e;i<d;i++)f.push(b[i]);c.push(f)}return c}
-function Rf(a,b,c){var d=Qf[a];if(d&&!d.cZ){_=d.prototype}else{!d&&(d=Qf[a]=function(){});_=d.prototype=b<0?{}:Sf(b);_.cM=c}for(var e=3;e<arguments.length;++e){arguments[e].prototype=_}if(d.cZ){_.cZ=d.cZ;d.cZ=null}}
-function Mg(a,b){var c,d,e,f,g,h;h=xk(a,b,0);if(h.length==1){return null}d=0;e=Ep;for(c=0;c<h.length;++c){g=h[c];if(g.indexOf(lq)!=-1){continue}f=xk(g,mq,0).length;if(f>d||g.length>e.length){d=f;e=g}}return e.length==0?null:Ak(e)}
-function Wg(a){var b,c,d,e;b=false;c=2147483647;for(e=new gm(a.b);e.c<e.e.M();){d=Dd(em(e),8);if(d.c&&!!d.d&&Ln(d.d,pq)){c=d.q}else{if(d.q>c&&!!d.d&&Ln(d.d,oq)&&!!d.d&&Ln(d.d,qq)&&d.e==0){lg(d,true);b=true}else{c=2147483647}}}return b}
-function In(a){var b,c,d,e,f,g,h;if(a){for(e=0,d=a.b.length-1;e<d;++e,--d){h=(Xl(e,a.b.length),a.b[e]);zn(a,e,(Xl(d,a.b.length),a.b[d]));zn(a,d,h)}}else{b=new mm(null,0);f=new mm(null,null.b.length);while(b.c<f.c-1){c=em(b);g=km(f);lm(b,g);lm(f,c)}}}
-function Vg(a){var b,c,d,e;b=false;c=-1;for(e=new gm(a.b);e.c<e.e.M();){d=Dd(em(e),8);if(d.c&&!!d.d&&Ln(d.d,pq)){c=d.q;break}}if(c==-1){return false}for(e=new gm(a.b);e.c<e.e.M();){d=Dd(em(e),8);if(!d.c){if(d.i>=100&&d.q==c){lg(d,true);b=true}}}return b}
-function yg(a){var b,c,d,e,f,g;g=a.b;d=new mm(g,0);if(d.c>=d.e.M()){return false}f=(ig(),hg);b=Dd(em(d),8);e=d.c<d.e.M()?Dd(em(d),8):hg;c=xg(f,b,e)|false;if(e!=hg){while(d.c<d.e.M()){f=b;b=e;e=Dd(em(d),8);c=xg(f,b,e)|c}f=b;b=e;e=hg;c=xg(f,b,e)|c}return c}
-function ih(a,b){var c,d,e,f,g,h;for(d=Zn(a.e,0);d.c!=d.e.b;){c=Dd(fo(d),18);if(c){!b.d&&(b.d=new Nn);Kn(b.d,'font-'+c);break}}for(f=Zn(a.n,0);f.c!=f.e.b;){e=Dd(fo(f),24);if(e){for(h=Zn(e,0);h.c!=h.e.b;){g=Dd(fo(h),9);!!g&&(jg(b,g.b),undefined)}}}Zm(a.t,b)}
-function Vo(a,b,c,d,e){var f,g,h,j,l,m,n,o,q;n=Ed(!c?b.c:vi(b,c,~~tc(c)))[d][e.length];h=null;o=null;f=null;for(g=0,j=!n?0:n.length;g<j;++g){m=n[g];if(_o(m,e)){h=m[0];o=m[1];f=m[2];break}}if(!h){return null}else{e=f?f(a,e):e;l=(q=h.apply(a,e),[o?o(q):q]);return l}}
-function Ej(a){var b,c,d,e;if(a==null){throw new ik(Yp)}c=a.length;d=c>0&&a.charCodeAt(0)==45?1:0;for(b=d;b<c;++b){if(kj(a.charCodeAt(b))==-1){throw new ik(zq+a+Aq)}}e=parseInt(a,10);if(isNaN(e)){throw new ik(zq+a+Aq)}else if(e<-2147483648||e>2147483647){throw new ik(zq+a+Aq)}return e}
-function Pg(a){var b,c,d,e,f,g;d=0;g=-1;c=-1;for(f=new gm(a.b);f.c<f.e.M();){e=Dd(em(f),8);if(c==-1&&!!e.d&&Ln(e.d,Dp)){g=d;c=-1}c==-1&&e.c&&(c=d);++d}if(c<=g||g==-1){return false}b=false;for(f=new gm(new om(a.b,g,c));f.c<f.e.M();){e=Dd(em(f),8);!!e.d&&Ln(e.d,oq)&&(b=lg(e,true)|b)}return b}
-function $c(a){var b,c,d,e,f,g,h,j,l;l=td(Lf,qp,21,a.length,0);for(e=0,f=l.length;e<f;++e){j=xk(a[e],bq,0);b=-1;d=cq;if(j.length==2&&j[1]!=null){h=j[1];g=sk(h,Ik(58));c=tk(h,Ik(58),g-1);d=h.substr(0,c-0);if(g!=-1&&c!=-1){Gc(h.substr(c+1,g-(c+1)));b=Gc(yk(h,g+1))}}l[e]=new kk(j[0],d+Bp+b)}Vb(l)}
-function Ng(a,b){var c,d,e,f;if(!a.b){return false}c=false;for(e=new gm(b.b);e.c<e.e.M();){d=Dd(em(e),8);f=d.r.tS();f=uk(f,160,32);f=vk(f,nq,Ep);f=Ak(f).toLowerCase();if(Ln(a.b,f)){!d.d&&(d.d=new Nn);Kn(d.d,Dp);c=true;break}f=Ak(Ho(Ko(Jg,f),Ep));if(Ln(a.b,f)){!d.d&&(d.d=new Nn);Kn(d.d,Dp);c=true;break}}return c}
-function Uo(a,b,c,d,e,f,g){var h,j,l,m,n;j=f?a.d:a.b;if(g){for(m=So(Ed(!c?j.c:vi(j,c,~~tc(c))),d),l=m;l>=1;--l){h=Qo(l,e);n=Vo(b,j,c,d,h);if(!n){h=Wo(b,h);n=Vo(b,j,c,d,h)}if(n){return n}}}else{n=Vo(b,j,c,d,e);if(!n){e=Wo(b,e);n=Vo(b,j,c,d,e)}if(n){return n}}throw new Zb("Can't find exported method for given arguments: "+d+Rp+e.length+aq)}
-function Nf(){var a;!!$stats&&Tf('com.google.gwt.useragent.client.UserAgentAsserter');a=eg();ok(gq,a)||($wnd.alert('ERROR: Possible problem with your *.gwt.xml module file.\nThe compile time user.agent value (safari) does not match the runtime user.agent value ('+a+'). Expect more errors.\n'),undefined);!!$stats&&Tf('com.google.gwt.user.client.DocumentModeAsserter');dg();!!$stats&&Tf('com.dom_distiller.client.DomDistiller');Z();cp();new O;new X;new Hb}
-function xk(n,a,b){var c=new RegExp(a,Bq);var d=[];var e=0;var f=n;var g=null;while(true){var h=c.exec(f);if(h==null||f==Ep||e==b-1&&b>0){d[e]=f;break}else{d[e]=f.substring(0,h.index);f=f.substring(h.index+h[0].length,f.length);c.lastIndex=0;if(g==f){d[e]=f.substring(0,1);f=f.substring(1)}g=f;e++}}if(b==0&&n.length>0){var j=d.length;while(j>0&&d[j-1]==Ep){--j}j<d.length&&d.splice(j,d.length-j)}var l=Ck(d.length);for(var m=0;m<d.length;++m){l[m]=d[m]}return l}
-function _o(a,b){var c,d,e,f,g,h,j,l,m,n;for(e=0,m=b.length;e<m;++e){l=a[e+3];c=ap(b,e);if(ok(c,l)){continue}if(ok('string',l)&&ok(Yp,c)){continue}h=ok(yq,c);f=ok('boolean',c);if(Oe===l){h&&(b[e]=new Gj(b[e]),undefined);f&&(b[e]=(_i(),b[e]?$i:Zi),undefined);continue}j=h||f;g=!j&&l!=null&&hc(l)==Ee;if(g){n=b[e];if(n==null||Zo(n,Dd(l,15))){continue}if(Gd(n)){d=Yo(Ed(n));if(d!=null){if(Zo(d,Dd(l,15))){b[e]=d;continue}}}}if(ok(Kp,l)&&!h&&!f){continue}return false}return true}
-function yb(){var a,b,c,d,e,f;c=$wnd.location.pathname;f=xk(c,Lp,0);In(new An(f));a=new dn;for(b=0;b<f.length;++b){e=f[b];if(e.indexOf(Mp)!=-1){d=xk(e,Np,0)[1];Qb(d,'[^a-zA-Z]')||(e=xk(e,Np,0)[0])}e=Ob(e,',00',Ep);b<2&&(e=Ob(e,'((_|-)?p[a-z]*|(_|-))[0-9]{1,2}$',Ep));if(!e.length)continue;if(b<2&&Qb(e,'^\\d{1,2}$'))continue;if(b==0&&pk(e,'index'))continue;if(b<2&&e.length<3&&!Qb(f[0],'[a-z]')){continue}vd(a.b,a.c++,e)}return $wnd.location.protocol+'//'+$wnd.location.host+Lp+Ab(a)}
-function N(g){var d=dp('com.dom_distiller.ContentExtractor');var e,f=g;$wnd.com.dom_distiller.ContentExtractor=Ap(function(){var a,b=this,c=arguments;c.length==1&&f.y(c[0])?(a=c[0]):c.length==0&&(a=new I);b.g=a;gp(a,b);return b});e=$wnd.com.dom_distiller.ContentExtractor.prototype=new Object;$wnd.com.dom_distiller.ContentExtractor.extractContent=Ap(function(){return J()});if(d)for(p in d)$wnd.com.dom_distiller.ContentExtractor[p]===undefined&&($wnd.com.dom_distiller.ContentExtractor[p]=d[p])}
-function kh(a,b,c,d){var e,f,g,h,j;++a.v;if(a.d){mh(a);a.d=false}if(a.k!=0){return}j=false;g=false;if(d==0){return}f=c+d;for(h=c;h<f;++h){rk(Xp,Ik(oj(b[h]).b))!=-1&&(b[h]=32)}while(c<f){e=b[c];if(e==32){j=true;++c;--d}else{break}}while(d>0){e=b[c+d-1];if(e==32){g=true;--d}else{break}}if(d==0){if(j||g){if(!a.q){Xk(a.u,32);Xk(a.x,32)}a.q=true}else{a.q=false}return}if(j){if(!a.q){Xk(a.u,32);Xk(a.x,32)}}a.b==-1&&(a.b=a.s);_k(a.u,b,c,d);_k(a.x,b,c,d);if(g){Xk(a.u,32);Xk(a.x,32)}a.q=g;Kn(a.c,$j(a.v))}
+var $gwt_version = "2.5.1";var $wnd = window;var $doc = $wnd.document;var $moduleName, $moduleBase;var $strongName = 'A3E72C9BA7989CB6DCC7DDB00D2BFB9F';var $stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent(a);} : null,$sessionId = $wnd.__gwtStatsSessionId ? $wnd.__gwtStatsSessionId : null;$stats && $stats({moduleName:'domdistiller',sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalStart'});
+function U(){}
+function sp(){}
+function Ab(){}
+function Gc(){}
+function Qc(){}
+function Qh(){}
+function Fh(){}
+function Lh(){}
+function Vh(){}
+function $h(){}
+function qd(){}
+function vd(){}
+function yj(){}
+function rp(){}
+function K(){J()}
+function jd(){$c()}
+function bc(){bd($c())}
+function kn(){bn(this)}
+function R(){P(this)}
+function $(){Y(this)}
+function Kb(){Ib(this)}
+function Ri(){wi(this)}
+function hl(){al(this)}
+function hh(a){this.b=a}
+function jh(a){this.b=a}
+function kb(a){this.b=a}
+function Dg(a){this.b=a}
+function di(a){this.b=a}
+function hj(a){this.b=a}
+function oj(a){this.b=a}
+function Mj(a){this.b=a}
+function $j(a){this.b=a}
+function Dl(a){this.b=a}
+function Ql(a){this.b=a}
+function Hm(a){this.b=a}
+function Sm(a){this.b=a}
+function mm(a){this.e=a}
+function Gn(a){this.b=a}
+function bg(a,b){a.b=b}
+function tg(a,b){a.q=b}
+function md(a,b){a.b+=b}
+function nd(a,b){a.b+=b}
+function od(a,b){a.b+=b}
+function ud(a,b){a.src=b}
+function sd(b,a){b.href=a}
+function al(a){a.b=new qd}
+function Zk(){this.b=new qd}
+function Sn(){this.b=new Ri}
+function fg(){fg=sp;new cg}
+function cg(){new kn}
+function tb(a,b){_n(a.b,b)}
+function tn(a,b){a.length=b}
+function bj(){bc.call(this)}
+function Hj(){bc.call(this)}
+function Vj(){bc.call(this)}
+function kk(){bc.call(this)}
+function Ao(){bc.call(this)}
+function Tj(a){cc.call(this,a)}
+function Xj(a){cc.call(this,a)}
+function ol(a){cc.call(this,a)}
+function ok(a){Tj.call(this,a)}
+function Si(a){Ki.call(this,a)}
+function Xi(){Xi=sp;Wi=new Yi}
+function Dc(){Dc=sp;Cc=new Gc}
+function ip(){ip=sp;hp=new bp}
+function J(){J=sp;fg();ag(Ip)}
+function bb(){bb=sp;fg();ag(Ip)}
+function Uk(){Uk=sp;Rk={};Tk={}}
+function Tn(){this.b=new Si(2)}
+function so(){this.b=this.c=this}
+function cc(a){bd($c());this.f=a}
+function Zf(a){return new Xf[a]}
+function Di(b,a){return b.f[Yp+a]}
+function ig(b,a){return b.exec(a)}
+function nj(a,b){return a.b-b.b}
+function hk(a,b){return a>b?a:b}
+function ik(a,b){return a<b?a:b}
+function Rn(a,b){return yi(a.b,b)}
+function jm(a){return a.c<a.e.M()}
+function Kc(a){return Oc(($c(),a))}
+function Hg(a){return a>=48&&a<=57}
+function jp(a){ip();return Xo(a)}
+function Vo(a,b,c){Gi(a.c,b,c)}
+function vn(a,b,c){a.splice(b,c)}
+function vo(a,b){this.b=a;this.c=b}
+function _g(a,b){this.b=a;this.c=b}
+function Cm(a,b){this.b=a;this.c=b}
+function Mm(a,b){this.b=a;this.c=b}
+function xg(a,b){this.c=a;this.b=b}
+function Vl(a,b){this.c=a;this.b=b}
+function Ro(a){this.c=a;this.b=Hq}
+function il(a){jl.call(this,a.tS())}
+function hg(a){fg();gg.call(this,a)}
+function Ko(){fg();gg.call(this,Kp)}
+function jl(a){al(this);nd(this.b,a)}
+function ln(a){bn(this);tn(this.b,a)}
+function bn(a){a.b=Ad(Rf,wp,0,0,0)}
+function zc(a){$wnd.clearTimeout(a)}
+function dl(a,b){nd(a.b,b);return a}
+function cl(a,b){md(a.b,b);return a}
+function co(a){go(a);return a.b.c.d}
+function Lj(a,b){return Nj(a.b,b.b)}
+function Fi(b,a){return Yp+a in b.f}
+function xk(b,a){return b.indexOf(a)}
+function Lc(a){return parseInt(a)||-1}
+function Pd(a){return a==null?null:a}
+function Jd(a,b){return a.cM&&a.cM[b]}
+function bo(a,b){new to(b,a.b);++a.c}
+function ao(a,b,c){new to(b,c);++a.c}
+function kp(a,b,c){ip();Zo(hp,a,b,c)}
+function wn(a,b,c,d){a.splice(b,c,d)}
+function bm(a,b){(a<0||a>=b)&&em(a,b)}
+function Id(a,b){return a.cM&&!!a.cM[b]}
+function cp(a){return a&&a.g?a.g:null}
+function wd(a){return xd(a,0,a.length)}
+function Ik(a){return Ad(Tf,wp,1,a,0)}
+function Od(a){return a.tM==sp||Id(a,1)}
+function yc(a){return a.$H||(a.$H=++qc)}
+function Dj(a){return typeof a==Eq&&a>0}
+function tk(b,a){return b.charCodeAt(a)}
+function rd(b,a){return b.appendChild(a)}
+function Md(a,b){return a!=null&&Id(a,b)}
+function jg(c,a,b){return a.replace(c,b)}
+function yk(b,a){return b.lastIndexOf(a)}
+function Go(a,b){return Kd(Bi(a.b,b),30)}
+function ic(a){return Nd(a)?Kc(Ld(a)):Kp}
+function hc(a){return a==null?null:a.name}
+function ho(){this.b=new so;this.c=0}
+function fb(a){this.b=a;this.c=new kn}
+function vb(a){this.c=a;this.b=new ho}
+function pp(){this.b=new kn;this.c=new Ri}
+function go(a){if(a.c==0){throw new Ao}}
+function mo(a){if(!a.d){throw new Vj}}
+function fn(a,b){bm(b,a.c);return a.b[b]}
+function mp(a,b){ip();a['__gwtex_wrap']=b}
+function ep(a,b){for(p in b){a[p]=b[p]}}
+function Fk(c,a,b){return c.substr(a,b-a)}
+function gj(a,b){return a.b==b.b?0:a.b?1:-1}
+function fc(a){return a==null?null:a.message}
+function ec(a){return Nd(a)?fc(Ld(a)):a+Kp}
+function tc(a,b,c){return a.apply(b,c);var d}
+function zk(c,a,b){return c.lastIndexOf(a,b)}
+function Qk(a){return String.fromCharCode(a)}
+function bd(){var a;a=_c(new jd);dd(a)}
+function wj(){wj=sp;vj=Ad(Pf,wp,14,128,0)}
+function gk(){gk=sp;fk=Ad(Qf,wp,18,256,0)}
+function cb(){cb=sp;fg();ag('DomToSaxParser')}
+function $c(){$c=sp;Error.stackTraceLimit=128}
+function Bg(){Bg=sp;Ag=new Dg(60);new Dg(200)}
+function wh(){nh();xh.call(this,(Xi(),Wi))}
+function Og(a,b){this.c=1;this.b=a;this.d=b}
+function Fb(a,b){this.d=0;this.c=a;this.b=b}
+function no(a,b,c){this.e=a;this.c=c;this.b=b}
+function So(a){this.c=a;this.b=Hq;this.b+='i'}
+function ro(a){a.b.c=a.c;a.c.b=a.b;a.b=a.c=a}
+function Mo(a){a.b=ig(a.d,a.c);return !!a.b}
+function Cj(a){var b=Xf[a.c];a=null;return b}
+function dn(a,b){Cd(a.b,a.c++,b);return true}
+function Pc(){try{null.a()}catch(a){return a}}
+function _n(a,b){new to(b,a.b);++a.c;return true}
+function Zj(a,b){return a.b<b.b?-1:a.b>b.b?1:0}
+function Qo(a,b){return new Oo(a.c,a.b,b.tS())}
+function Ek(b,a){return b.substr(a,b.length-a)}
+function Un(a){this.b=new Si(a.b.e);ql(this,a)}
+function gg(a){fg();this.b=new cg;bg(this.b,a)}
+function mc(a){var b;return b=a,Od(b)?b.cZ:de}
+function nc(a){var b;return b=a,Od(b)?b.hC():yc(b)}
+function ni(a){var b;b=new Dl(a);return new Cm(a,b)}
+function fh(){fh=sp;new hh(null);eh=new hh(Jp)}
+function Fd(){Fd=sp;Dd=[];Ed=[];Gd(new vd,Dd,Ed)}
+function Rg(){Rg=sp;Qg=new Ro('[\\?\\!\\.\\-\\:]+')}
+function fj(){fj=sp;dj=new hj(false);ej=new hj(true)}
+function Rm(a){var b;b=Kd(km(a.b.b),27).Z();return b}
+function Qn(a,b){var c;c=Gi(a.b,b,a);return c==null}
+function Cn(a,b,c){var d;d=xd(a,b,c);Dn(d,a,b,c,-b)}
+function lc(a,b){var c;return c=a,Od(c)?c.eQ(b):c===b}
+function Mc(a,b){a.length>=b&&a.splice(0,b);return a}
+function Hc(a,b){!a&&(a=[]);a[a.length]=b;return a}
+function Vf(a){if(Md(a,23)){return a}return new dc(a)}
+function Bm(a){var b;b=new Il(a.c.b);return new Hm(b)}
+function Lm(a){var b;b=new Il(a.c.b);return new Sm(b)}
+function uh(a,b){if(b==null||b.length==0){return}a.w=b}
+function pd(a,b){a.b=a.b.substr(0,0-0)+Kp+Ek(a.b,b)}
+function Nd(a){return a!=null&&a.tM!=sp&&!Id(a,1)}
+function Qi(a,b){return Pd(a)===Pd(b)||a!=null&&lc(a,b)}
+function Bo(a,b){return Pd(a)===Pd(b)||a!=null&&lc(a,b)}
+function em(a,b){throw new Xj('Index: '+a+', Size: '+b)}
+function rm(a,b){if(a.d==-1){throw new Vj}a.b.cb(a.d,b)}
+function qk(a,b){this.b=iq;this.e=a;this.c=b;this.d=-1}
+function bp(){this.c=new Ri;this.b=new Ri;this.d=new Ri}
+function Xk(){if(Sk==256){Rk=Tk;Tk={};Sk=0}++Sk}
+function P(a){if(!O){O=true;ip();Vo(hp,Sd,a);Q(a)}}
+function Y(a){if(!X){X=true;ip();Vo(hp,Ud,a);Z(a)}}
+function Ib(a){if(!Hb){Hb=true;ip();Vo(hp,ae,a);Jb(a)}}
+function qh(a){if(!a.q){bl(a.x,32);bl(a.u,32);a.q=true}}
+function wi(a){a.b=[];a.f={};a.d=false;a.c=null;a.e=0}
+function ad(a,b){var c;c=cd(a,Nd(b.c)?Ld(b.c):null);dd(c)}
+function Ad(a,b,c,d,e){var f;f=zd(e,d);Bd(a,b,c,f);return f}
+function Mb(a,b){var c;c=new Ob(a);jb(new kb(c),b);return c.b}
+function fo(a){var b;go(a);--a.c;b=a.b.c;ro(b);return b.d}
+function bl(a,b){od(a.b,String.fromCharCode(b));return a}
+function Kd(a,b){if(a!=null&&!Jd(a,b)){throw new Hj}return a}
+function uk(a,b){if(!Md(b,1)){return false}return String(a)==b}
+function Ck(c,a,b){b=Jk(b);return c.replace(RegExp(a),b)}
+function Bk(c,a,b){b=Jk(b);return c.replace(RegExp(a,Hq),b)}
+function lp(a,b,c,d,e,f){ip();return $o(hp,a,b,c,d,e,f)}
+function Mk(a,b){a=String(a);if(a==b){return 0}return a<b?-1:1}
+function No(a,b){a.b=null;a.d.lastIndex=0;return jg(a.d,a.c,b)}
+function Nn(a,b){var c,d;d=a.c;for(c=0;c<d;++c){jn(a,c,b[c])}}
+function op(a,b){var c;Gi(a.c,b,ek(a.b.c));c=new rp;dn(a.b,c)}
+function cn(a,b,c){(b<0||b>a.c)&&em(b,a.c);wn(a.b,b,0,c);++a.c}
+function Oo(a,b,c){this.d=new RegExp(a,b);this.c=c;this.b=null}
+function pb(a){this.c=new yb(a);this.b=new kn;this.e=new kn}
+function Ob(a){this.c=false;this.d=new yb(a);this.b=new kn}
+function Io(){this.b=new Ri;this.c=new Ko;Gi(this.b,Kp,this.c)}
+function yb(a){this.c=new mm(a);a.c==0||(this.b=Ld(km(this.c)))}
+function dc(a){bc.call(this);this.c=a;this.b=Kp;ad(new jd,this)}
+function ml(a){cc.call(this,'String index out of range: '+a)}
+function qm(a){if(a.c<=0){throw new Ao}return a.b.ab(a.d=--a.c)}
+function lm(a){if(a.d<0){throw new Vj}a.e.bb(a.d);a.c=a.d;a.d=-1}
+function to(a,b){this.d=a;this.b=b;this.c=b.c;b.c.b=this;b.c=this}
+function Ii(a,b){var c;c=a.c;a.c=b;if(!a.d){a.d=true;++a.e}return c}
+function sg(a,b){if(b!=a.c){a.c=b;return true}else{return false}}
+function Eo(a,b){if(Go(a,b.b.b)){return false}Fo(a,b);return true}
+function mb(a,b){while(a.b.c==1&&a.c!=b){a=Kd(Wm(a.b,0),4)}return a}
+function jn(a,b,c){var d;d=(bm(b,a.c),a.b[b]);Cd(a.b,b,c);return d}
+function yd(a,b){var c,d;c=a;d=zd(0,b);Bd(c.cZ,c.cM,c.qI,d);return d}
+function Bd(a,b,c,d){Fd();Hd(d,Dd,Ed);d.cZ=a;d.cM=b;d.qI=c;return d}
+function Hd(a,b,c){Fd();for(var d=0,e=b.length;d<e;++d){a[b[d]]=c[d]}}
+function wk(a,b,c,d){var e;for(e=0;e<b;++e){c[d++]=a.charCodeAt(e)}}
+function wc(a,b,c){var d;d=uc();try{return tc(a,b,c)}finally{xc(d)}}
+function xn(a,b,c,d){Array.prototype.splice.apply(a,[b,c].concat(d))}
+function el(a,b){od(a.b,String.fromCharCode.apply(null,b));return a}
+function Fn(a,b,c){var d;bm(b,a.b.length);d=a.b[b];Cd(a.b,b,c);return d}
+function hn(a,b){var c;c=(bm(b,a.c),a.b[b]);vn(a.b,b,1);--a.c;return c}
+function Bj(a,b){var c;c=new yj;c.e=a+b;Dj(0)&&Ej(0,c);c.b=2;return c}
+function ap(a,b){var c=[a];for(i=0;i<b.length;i++)c.push(b[i]);return c}
+function Yo(a,b){var c=a[b];var d=0;for(k in c)d=Math.max(d,k);return d}
+function td(a){var b=a.parentNode;(!b||b.nodeType!=1)&&(b=null);return b}
+function Ld(a){if(a!=null&&(a.tM==sp||Id(a,1))){throw new Hj}return a}
+function km(a){if(a.c>=a.e.M()){throw new Ao}return a.e.ab(a.d=a.c++)}
+function rg(a){if(a.k==0){a.k=a.i;a.n=1}a.s=a.k/a.n;a.e=a.i==0?0:a.j/a.i}
+function gc(a){return a==null?cq:Nd(a)?hc(Ld(a)):Md(a,1)?dq:mc(a).e}
+function yi(a,b){return b==null?a.d:Md(b,1)?Fi(a,Kd(b,1)):Ei(a,b,a.P(b))}
+function Bi(a,b){return b==null?a.c:Md(b,1)?Di(a,Kd(b,1)):Ci(a,b,a.P(b))}
+function Qd(a){return ~~Math.max(Math.min(a,2147483647),-2147483648)}
+function Ac(){return $wnd.setTimeout(function(){pc!=0&&(pc=0);sc=-1},10)}
+function xc(a){a&&Fc((Dc(),Cc));--pc;if(a){if(sc!=-1){zc(sc);sc=-1}}}
+function Gd(a,b,c){var d=0,e;for(var f in a){if(e=a[f]){b[d]=f;c[d]=e;++d}}}
+function Ji(e,a,b){var c,d=e.f;a=Yp+a;a in d?(c=d[a]):++e.e;d[a]=b;return c}
+function Aj(a,b,c,d){var e;e=new yj;e.e=a+b;Dj(c)&&Ej(c,e);e.d=d;return e}
+function xd(a,b,c){var d,e;d=a;e=d.slice(b,c);Bd(d.cZ,d.cM,d.qI,e);return e}
+function Rb(a,b,c){var d,e;e=new So(b);d=new Oo(e.c,e.b,a);return No(d,c)}
+function fl(a,b,c,d){var e;od(a.b,(e=c+d,Hk(b.length,c,e),Kk(b,c,e)));return a}
+function gn(a,b,c){for(;c<a.c;++c){if(Bo(b,a.b[c])){return c}}return -1}
+function Kk(a,b,c){a=a.slice(b,c);return String.fromCharCode.apply(null,a)}
+function cd(a,b){var c;c=Wc(a,b);return c.length==0?(new Qc).E(b):Mc(c,1)}
+function oh(a,b){var c;c=Kd(co(a.n),24);if(!c){c=new ho;fo(a.n);bo(a.n,c)}bo(c,b)}
+function sm(a,b){var c;this.b=a;this.e=a;c=a.M();(b<0||b>c)&&em(b,c);this.c=b}
+function Fc(a){var b,c;if(a.c){c=null;do{b=a.c;a.c=null;c=Ic(b,c)}while(a.c);a.c=c}}
+function Ec(a){var b,c;if(a.b){c=null;do{b=a.b;a.b=null;c=Ic(b,c)}while(a.b);a.b=c}}
+function lo(a){if(a.c==a.e.b){throw new Ao}a.d=a.c;a.c=a.c.b;++a.b;return a.d.d}
+function xb(a,b){if(b!=a.b)return false;a.b=jm(a.c)?Ld(km(a.c)):null;return true}
+function vk(b,a){if(a==null)return false;return b==a||b.toLowerCase()==a.toLowerCase()}
+function vc(b){return function(){try{return wc(b,this,arguments)}catch(a){throw a}}}
+function Gi(a,b,c){return b==null?Ii(a,c):Md(b,1)?Ji(a,Kd(b,1),c):Hi(a,b,c,~~nc(b))}
+function Il(a){var b;b=new kn;a.d&&dn(b,new Ql(a));vi(a,b);ui(a,b);this.b=new mm(b)}
+function gl(a){var b;b=a.b.b.length;0<b?(pd(a.b,b),a):0>b&&el(a,Ad(Of,wp,-1,-b,1))}
+function Fo(a,b){var c,d;c=b.b.b;d=Fk(c,0,hk(0,yk(c,Ok(46))));Ho(a,d);Gi(a.b,b.b.b,b)}
+function Ho(a,b){var c,d;c=Kd(Bi(a.b,b),30);if(!c){d=new gg(b);Fo(a,d);return d}return c}
+function ql(a,b){var c,d;d=b.T();c=false;while(d.W()){a.Q(d.X())&&(c=true)}return c}
+function Vb(a,b){var c,d;d=new So(b);c=new Oo(d.c,d.b,a);return c.b=ig(c.d,c.c),!!c.b}
+function Zg(){Zg=sp;new _g(false,0);new _g(true,0);Yg=new _g(true,150)}
+function pg(){pg=sp;ng=new Sn;og=new ug(Kp,ng,0,0,0,0,-1);new ug(Kp,ng,0,0,0,0,2147483647)}
+function Dh(){Dh=sp;Ah=new Fh;yh=new Lh;zh=new Qh;Ch=new Vh;Bh=new $h;new Ro('([\\+\\-]?)([0-9])')}
+function _c(a){var b;b=Mc(cd(a,Pc()),3);b.length==0&&(b=Mc((new Qc).C(),1));return b}
+function lb(a){var b;for(b=a.parentNode;!!b&&b.nodeType!=9;a=b,b=b.parentNode){}return a}
+function Sb(a){var b;for(b=0;b<a.length;++b){if(!Tb(uj(a.charCodeAt(b))))return false}return true}
+function rl(a,b){var c;while(a.W()){c=a.X();if(b==null?c==null:lc(b,c)){return a}}return null}
+function uj(a){var b;if(a<128){b=(wj(),vj)[a];!b&&(b=vj[a]=new oj(a));return b}return new oj(a)}
+function Hk(a,b,c){if(b<0){throw new ml(b)}if(c<b){throw new ml(c-b)}if(c>a){throw new ml(c)}}
+function Kh(a){if(--a.f==0){if(a.k==0){qh(a);dl(a.x,Bq);bl(a.x,32);a.q=true}}return false}
+function en(a,b){var c,d;c=b.U();d=c.length;if(d==0){return false}xn(a.b,a.c,0,c);a.c+=d;return true}
+function zj(a,b,c){var d;d=new yj;d.e=a+b;Dj(c!=0?-c:0)&&Ej(c!=0?-c:0,d);d.b=4;d.d=Ve;return d}
+function Db(a){var b,c;c=Kp;for(b=a.c-1;b>=0;--b){c+=(bm(b,a.c),Kd(a.b[b],1));b>0&&(c+=Tp)}return c}
+function jb(a,b){var c,d;if(!a.b.A(b))return;c=b.childNodes;for(d=0;d<c.length;++d){jb(a,c[d])}a.b.z(b)}
+function qg(a,b){var c,d,e;if(b==null){return}!a.d&&(a.d=new Sn);for(d=0,e=b.length;d<e;++d){c=b[d];Qn(a.d,c)}}
+function Nj(a,b){if(isNaN(a)){return isNaN(b)?0:1}else if(isNaN(b)){return -1}return a<b?-1:a>b?1:0}
+function _i(a){$i();var b;b=No(Qo(Zi,a),'\u2063');b=Bk(b,'[ \u2063]+',Zp);b=Ub(b);return Dk(b,'[ ]+',0)}
+function Wk(a){Uk();var b=Yp+a;var c=Tk[b];if(c!=null){return c}c=Rk[b];c==null&&(c=Vk(a));Xk();return Tk[b]=c}
+function vi(e,a){var b=e.f;for(var c in b){if(c.charCodeAt(0)==58){var d=new Vl(e,c.substring(1));a.Q(d)}}}
+function ag(a){var b,c,d;c=(!Do&&(Do=new Io),Do);b=Kd(Bi(c.b,a),30);if(!b){d=new hg(a);Eo(c,d);return d}return b}
+function ub(a){var b,c,d;d=a.c.cloneNode(false);for(c=eo(a.b,0);c.c!=c.e.b;){b=Kd(lo(c),4);rd(d,ub(b))}return d}
+function $b(a){var b,c,d;c=Ad(Sf,wp,21,a.length,0);for(d=0,b=a.length;d<b;++d){if(!a[d]){throw new kk}c[d]=a[d]}}
+function Wc(a,b){var c,d,e;e=b&&b.stack?b.stack.split(gq):[];for(c=0,d=e.length;c<d;++c){e[c]=a.D(e[c])}return e}
+function ek(a){var b,c;if(a>-129&&a<128){b=a+128;c=(gk(),fk)[b];!c&&(c=fk[b]=new $j(a));return c}return new $j(a)}
+function zi(e,a){var b=e.f;for(var c in b){if(c.charCodeAt(0)==58){var d=b[c];if(e.O(a,d)){return true}}}return false}
+function qj(a){if(a>=48&&a<58){return a-48}if(a>=97&&a<97){return a-97+10}if(a>=65&&a<65){return a-65+10}return -1}
+function Ai(a,b){if(a.d&&Qi(a.c,b)){return true}else if(zi(a,b)){return true}else if(xi(a,b)){return true}return false}
+function Mg(){Mg=sp;Kg=new Og(false,false);new Og(false,true);new Og(true,false);Lg=new Og(true,true)}
+function xh(a){this.x=new hl;this.u=new hl;this.t=new kn;this.c=new Sn;this.n=new ho;this.e=new ho;this.r=a}
+function ug(a,b,c,d,e,f,g){pg();this.r=a;this.b=b;this.i=c;this.j=d;this.k=e;this.n=f;this.p=g;this.o=g;rg(this)}
+function Bn(a,b,c,d,e,f,g){var h;h=c;while(f<g){h>=d||b<c&&Kd(a[b],16).cT(a[h])<=0?Cd(e,f++,a[b++]):Cd(e,f++,a[h++])}}
+function An(a,b,c){var d,e,f;for(d=b+1;d<c;++d){for(e=d;e>b&&Kd(a[e-1],16).cT(a[e])>0;--e){f=a[e];Cd(a,e,a[e-1]);Cd(a,e-1,f)}}}
+function Zo(a,b,c,d){var e,f;f=d?a.d:a.b;e=Ld(!b?f.c:Ci(f,b,~~yc(b)));!e?(e=c):ep(e,c);!b?Ii(f,e):Hi(f,b,e,~~yc(b))}
+function sh(a,b,c){var d;d=Kd(Bi(a.r,b),10);d?(a.d=d.H(a,b,c)|a.d):(a.d=true);(!d||d.G())&&--a.s;a.d&&th(a);fo(a.n)}
+function vh(a,b,c,d){var e;bo(a.n,null);e=Kd(Bi(a.r,b),10);if(e){e.G()&&++a.s;a.d=e.I(a,b,c,d)|a.d}else{++a.s;a.d=true}a.o=b}
+function gwtOnLoad(b,c,d,e){$moduleName=c;$moduleBase=d;if(b)try{Gp(Uf)()}catch(a){b(c)}else{Gp(Uf)()}}
+function Ki(a){wi(this);if(a<0){throw new Tj('initial capacity was negative or load factor was non-positive')}}
+function $i(){$i=sp;Zi=new Ro('\\b');new Ro('[\u2063]*([\\"\'\\.,\\!\\@\\-\\:\\;\\$\\?\\(\\)/])[\u2063]*')}
+function Vi(a,b,c){Gi(a,b.toUpperCase(),c);Gi(a,b.toLowerCase(),c);b==null?Ii(a,c):b!=null?Ji(a,b,c):Hi(a,null,c,~~Wk(null))}
+function mi(a,b){var c,d,e;for(d=new Il(a.K().b);jm(d.b);){c=Kd(km(d.b),27);e=c.Y();if(b==null?e==null:lc(b,e)){return c}}return null}
+function Ci(h,a,b){var c=h.b[b];if(c){for(var d=0,e=c.length;d<e;++d){var f=c[d];var g=f.Y();if(h.O(a,g)){return f.Z()}}}return null}
+function Ei(h,a,b){var c=h.b[b];if(c){for(var d=0,e=c.length;d<e;++d){var f=c[d];var g=f.Y();if(h.O(a,g)){return true}}}return false}
+function uc(){var a;if(pc!=0){a=(new Date).getTime();if(a-rc>2000){rc=a;sc=Ac()}}if(pc++==0){Ec((Dc(),Cc));return true}return false}
+function Ub(a){if(a.length==0||a[0]>Zp&&a[a.length-1]>Zp){return a}return a.replace(/^[\u0000-\u0020]*|[\u0000-\u0020]*$/g,Kp)}
+function Gk(c){if(c.length==0||c[0]>Zp&&c[c.length-1]>Zp){return c}var a=c.replace(/^(\s*)/,Kp);var b=a.replace(/\s*$/,Kp);return b}
+function ui(h,a){var b=h.b;for(var c in b){var d=parseInt(c,10);if(c==d){var e=b[d];for(var f=0,g=e.length;f<g;++f){a.Q(e[f])}}}}
+function Wm(b,c){var d;d=eo(b,c);try{return lo(d)}catch(a){a=Vf(a);if(Md(a,28)){throw new Xj("Can't get element "+c)}else throw a}}
+function Tb(a){var b;b=a.b;return 9<=b&&b<=13||28<=b&&b<=32||b==5760||b==6158||8192<=b&&b<=8198||8232<=b&&b<=8233||b==8287||b==12288}
+function ob(a){var b;for(b=0;b<a.b.c;++b){if(fn(a.e,b)==null){jn(a.e,b,new vb(Ld(fn(a.b,b))));tb(Kd(fn(a.e,b-1),4),Kd(fn(a.e,b),4))}}}
+function db(a){cb();var b,c,d,e;b=new pp;e=a.attributes;for(c=0;c<e.length;++c){d=e[c];op(b,(d.nodeName,d.nodeName),d.nodeValue)}return b}
+function ch(a){var b,c,d,e;b=false;d=a.b;for(c=new sm(d,d.c);c.c>0;){e=Kd(qm(c),8);if(e.c){if(!!e.d&&Rn(e.d,xq)){sg(e,false);b=true}else{break}}}return b}
+function gh(a,b){var c,d,e,f;f=b.b;c=false;for(d=new mm(f);d.c<d.e.M();){e=Kd(km(d),8);if(!e.c&&(a.b==null||!(!!e.d&&Rn(e.d,Jp)))){lm(d);c=true}}return c}
+function Oc(b){var c=Kp;try{for(var d in b){if(d!='name'&&d!='message'&&d!='toString'){try{c+='\n '+d+Qp+b[d]}catch(a){}}}}catch(a){}return c}
+function gp(a,b){var c=a[b];var d=c==null?cq:typeof c;if(d==Sp){return Object.prototype.toString.call(c)==Jq||typeof c.length==Eq?'array':d}return d}
+function $l(a,b){var c,d;for(c=0,d=a.b.length;c<d;++c){if(b==null?(bm(c,a.b.length),a.b[c])==null:lc(b,(bm(c,a.b.length),a.b[c]))){return c}}return -1}
+function Ic(b,c){var d,e,f;for(d=0,e=b.length;d<e;++d){f=b[d];try{f[1]?f[0].db()&&(c=Hc(c,f)):f[0].db()}catch(a){a=Vf(a);if(!Md(a,23))throw a}}return c}
+function Jk(a){var b;b=0;while(0<=(b=a.indexOf('\\',b))){a.charCodeAt(b+1)==36?(a=a.substr(0,b-0)+'$'+Ek(a,++b)):(a=a.substr(0,b-0)+Ek(a,++b))}return a}
+function eo(a,b){var c,d;(b<0||b>a.c)&&em(b,a.c);if(b>=~~a.c>>1){d=a.b;for(c=a.c;c>b;--c){d=d.c}}else{d=a.b.b;for(c=0;c<b;++c){d=d.b}}return new no(a,b,d)}
+function dp(a,b){var c;if(Ve==b){return true}if(Jf==b&&Md(a,31)){return true}if(a!=null){for(c=mc(a);!!c&&c!=Ve;c=c.d){if(c==b){return true}}}return false}
+function Ak(d,a,b){var c;if(a<256){c=ck(a);c='\\x'+'00'.substring(c.length)+c}else{c=String.fromCharCode(a)}return d.replace(RegExp(c,Hq),String.fromCharCode(b))}
+function Sg(a,b,c){var d,e,f,g;g=Dk(b,c,0);if(g.length==1){return}for(d=0;d<g.length;++d){f=g[d];if(f.indexOf(rq)!=-1){continue}e=Dk(f,sq,0).length;e>=4&&Qn(a,f)}}
+function Ej(a,b){var c;b.c=a;if(a==2){c=String.prototype}else{if(a>0){var d=Cj(b);if(d){c=d.prototype}else{d=Xf[a]=function(){};d.cZ=b;return}}else{return}}c.cZ=b}
+function mk(){mk=sp;lk=Bd(Of,wp,-1,[48,49,50,51,52,53,54,55,56,57,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122])}
+function ck(a){var b,c,d;b=Ad(Of,wp,-1,8,1);c=(mk(),lk);d=7;if(a>=0){while(a>15){b[d--]=c[a&15];a>>=4}}else{while(d>0){b[d--]=c[a&15];a>>=4}}b[d]=c[a&15];return Kk(b,d,8)}
+function sl(a){var b,c,d,e;d=new Zk;b=null;d.b.b+=jq;c=a.T();while(c.W()){b!=null?(nd(d.b,b),d):(b=Cq);e=c.X();nd(d.b,e===a?'(this Collection)':Kp+e)}d.b.b+=kq;return d.b.b}
+function M(a){var b,c,d,e,f,g;g=a;c=g.getElementsByTagName(Lp);for(d=0;d<c.length;++d){f=c[d];sd(f,f.href)}b=g.getElementsByTagName(Mp);for(d=0;d<b.length;++d){e=b[d];ud(e,e.src)}}
+function zd(a,b){var c=new Array(b);if(a==3){for(var d=0;d<b;++d){var e=new Object;e.l=e.m=e.h=0;c[d]=e}}else if(a>0){var e=[null,0,false][a];for(var d=0;d<b;++d){c[d]=e}}return c}
+function xi(l,a){var b=l.b;for(var c in b){var d=parseInt(c,10);if(c==d){var e=b[d];for(var f=0,g=e.length;f<g;++f){var h=e[f];var j=h.Z();if(l.O(a,j)){return true}}}}return false}
+function Eg(a,b,c){var d;b.e<=0.333333?a.e<=0.555556?b.i<=16?c.i<=15?a.i<=4?(d=false):(d=true):(d=true):(d=true):b.i<=40?c.i<=17?(d=false):(d=true):(d=true):(d=false);return sg(b,d)}
+function Xo(a){var b,c,d,e,f;f=Dk(a,'\\.',0);e=$wnd;b=0;for(c=f.length-1;b<c;++b){if(!uk(f[b],'client')){e[f[b]]||(e[f[b]]={});e=e!=null?e[f[b]]:null}}d=e!=null?e[f[b]]:null;return d}
+function Ig(a,b,c){var d,e,f,g;d=0;while(d<b&&Hg(a.charCodeAt(d))){++d}if(d!=0){for(f=0,g=c.length;f<g;++f){e=c[f];if(!(d<0||d>=a.length)&&a.indexOf(e,d)==d){return true}}}return false}
+function $f(a){return $stats({moduleName:$moduleName,sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date).getTime(),type:'onModuleLoadStart',className:a})}
+function um(a,b,c){this.d=a;this.b=b;this.c=c-b;if(b>c){throw new Tj(Iq+b+' > toIndex: '+c)}if(b<0){throw new Xj(Iq+b+' < 0')}if(c>a.c){throw new Xj('toIndex: '+c+' > wrapped.size() '+a.c)}}
+function Jc(a){var b,c,d;d=Kp;a=Gk(a);b=a.indexOf(eq);c=a.indexOf('function')==0?8:0;if(b==-1){b=xk(a,Ok(64));c=a.indexOf('function ')==0?9:0}b!=-1&&(d=Gk(a.substr(c,b-c)));return d.length>0?d:fq}
+function Cg(a,b){var c,d,e,f,g,h;d=false;h=0;f=false;for(g=new mm(b.b);g.c<g.e.M();){c=Kd(km(g),8);e=!!c.d&&Rn(c.d,qq);c.c&&(h+=c.s>=9?c.i:0);e&&h>=a.b&&(f=true);if(f){d=true;sg(c,false)}}return d}
+function Ok(a){var b,c;if(a>=65536){b=55296+(~~(a-65536)>>10&1023)&65535;c=56320+(a-65536&1023)&65535;return String.fromCharCode(b)+String.fromCharCode(c)}else{return String.fromCharCode(a&65535)}}
+function Hi(l,a,b,c){var d=l.b[c];if(d){for(var e=0,f=d.length;e<f;++e){var g=d[e];var h=g.Y();if(l.O(a,h)){var j=g.Z();g.$(b);return j}}}else{d=l.b[c]=[]}var g=new vo(a,b);d.push(g);++l.e;return null}
+function Vk(a){var b,c,d,e;b=0;d=a.length;e=d-4;c=0;while(c<e){b=a.charCodeAt(c+3)+31*(a.charCodeAt(c+2)+31*(a.charCodeAt(c+1)+31*(a.charCodeAt(c)+31*b)))|0;c+=4}while(c<d){b=b*31+tk(a,c++)}return b|0}
+function Cd(a,b,c){if(c!=null){if(a.qI>0&&!Jd(c,a.qI)){throw new bj}else if(a.qI==-1&&(c.tM==sp||Id(c,1))){throw new bj}else if(a.qI<-1&&!(c.tM!=sp&&!Id(c,1))&&!Jd(c,-a.qI)){throw new bj}}return a[b]=c}
+function Dn(a,b,c,d,e){var f,g,h,j;f=d-c;if(f<7){An(b,c,d);return}h=c+e;g=d+e;j=h+(~~(g-h)>>1);Dn(b,a,h,j,-e);Dn(b,a,j,g,-e);if(Kd(a[j-1],16).cT(a[j])<=0){while(c<d){Cd(b,c++,a[h++])}return}Bn(a,h,j,g,b,c,d)}
+function Wo(a,b){var c=[];for(i=0;i<a-1;i++)c.push(b[i]);var d=b.length;var e=a-1;if(d>=a&&Object.prototype.toString.apply(b[e])===Jq){c.push(b[e])}else{var f=[];for(i=e;i<d;i++)f.push(b[i]);c.push(f)}return c}
+function Yf(a,b,c){var d=Xf[a];if(d&&!d.cZ){_=d.prototype}else{!d&&(d=Xf[a]=function(){});_=d.prototype=b<0?{}:Zf(b);_.cM=c}for(var e=3;e<arguments.length;++e){arguments[e].prototype=_}if(d.cZ){_.cZ=d.cZ;d.cZ=null}}
+function Tg(a,b){var c,d,e,f,g,h;h=Dk(a,b,0);if(h.length==1){return null}d=0;e=Kp;for(c=0;c<h.length;++c){g=h[c];if(g.indexOf(rq)!=-1){continue}f=Dk(g,sq,0).length;if(f>d||g.length>e.length){d=f;e=g}}return e.length==0?null:Gk(e)}
+function bh(a){var b,c,d,e;b=false;c=2147483647;for(e=new mm(a.b);e.c<e.e.M();){d=Kd(km(e),8);if(d.c&&!!d.d&&Rn(d.d,vq)){c=d.q}else{if(d.q>c&&!!d.d&&Rn(d.d,uq)&&!!d.d&&Rn(d.d,wq)&&d.e==0){sg(d,true);b=true}else{c=2147483647}}}return b}
+function On(a){var b,c,d,e,f,g,h;if(a){for(e=0,d=a.b.length-1;e<d;++e,--d){h=(bm(e,a.b.length),a.b[e]);Fn(a,e,(bm(d,a.b.length),a.b[d]));Fn(a,d,h)}}else{b=new sm(null,0);f=new sm(null,null.b.length);while(b.c<f.c-1){c=km(b);g=qm(f);rm(b,g);rm(f,c)}}}
+function ah(a){var b,c,d,e;b=false;c=-1;for(e=new mm(a.b);e.c<e.e.M();){d=Kd(km(e),8);if(d.c&&!!d.d&&Rn(d.d,vq)){c=d.q;break}}if(c==-1){return false}for(e=new mm(a.b);e.c<e.e.M();){d=Kd(km(e),8);if(!d.c){if(d.i>=100&&d.q==c){sg(d,true);b=true}}}return b}
+function Fg(a){var b,c,d,e,f,g;g=a.b;d=new sm(g,0);if(d.c>=d.e.M()){return false}f=(pg(),og);b=Kd(km(d),8);e=d.c<d.e.M()?Kd(km(d),8):og;c=Eg(f,b,e)|false;if(e!=og){while(d.c<d.e.M()){f=b;b=e;e=Kd(km(d),8);c=Eg(f,b,e)|c}f=b;b=e;e=og;c=Eg(f,b,e)|c}return c}
+function ph(a,b){var c,d,e,f,g,h;for(d=eo(a.e,0);d.c!=d.e.b;){c=Kd(lo(d),18);if(c){!b.d&&(b.d=new Tn);Qn(b.d,'font-'+c);break}}for(f=eo(a.n,0);f.c!=f.e.b;){e=Kd(lo(f),24);if(e){for(h=eo(e,0);h.c!=h.e.b;){g=Kd(lo(h),9);!!g&&(qg(b,g.b),undefined)}}}dn(a.t,b)}
+function _o(a,b,c,d,e){var f,g,h,j,l,m,n,o,q;n=Ld(!c?b.c:Ci(b,c,~~yc(c)))[d][e.length];h=null;o=null;f=null;for(g=0,j=!n?0:n.length;g<j;++g){m=n[g];if(fp(m,e)){h=m[0];o=m[1];f=m[2];break}}if(!h){return null}else{e=f?f(a,e):e;l=(q=h.apply(a,e),[o?o(q):q]);return l}}
+function Kj(a){var b,c,d,e;if(a==null){throw new ok(cq)}c=a.length;d=c>0&&a.charCodeAt(0)==45?1:0;for(b=d;b<c;++b){if(qj(a.charCodeAt(b))==-1){throw new ok(Fq+a+Gq)}}e=parseInt(a,10);if(isNaN(e)){throw new ok(Fq+a+Gq)}else if(e<-2147483648||e>2147483647){throw new ok(Fq+a+Gq)}return e}
+function Wg(a){var b,c,d,e,f,g;d=0;g=-1;c=-1;for(f=new mm(a.b);f.c<f.e.M();){e=Kd(km(f),8);if(c==-1&&!!e.d&&Rn(e.d,Jp)){g=d;c=-1}c==-1&&e.c&&(c=d);++d}if(c<=g||g==-1){return false}b=false;for(f=new mm(new um(a.b,g,c));f.c<f.e.M();){e=Kd(km(f),8);!!e.d&&Rn(e.d,uq)&&(b=sg(e,true)|b)}return b}
+function dd(a){var b,c,d,e,f,g,h,j,l;l=Ad(Sf,wp,21,a.length,0);for(e=0,f=l.length;e<f;++e){j=Dk(a[e],hq,0);b=-1;d=iq;if(j.length==2&&j[1]!=null){h=j[1];g=yk(h,Ok(58));c=zk(h,Ok(58),g-1);d=h.substr(0,c-0);if(g!=-1&&c!=-1){Lc(h.substr(c+1,g-(c+1)));b=Lc(Ek(h,g+1))}}l[e]=new qk(j[0],d+Hp+b)}$b(l)}
+function Ug(a,b){var c,d,e,f;if(!a.b){return false}c=false;for(e=new mm(b.b);e.c<e.e.M();){d=Kd(km(e),8);f=d.r.tS();f=Ak(f,160,32);f=Bk(f,tq,Kp);f=Gk(f).toLowerCase();if(Rn(a.b,f)){!d.d&&(d.d=new Tn);Qn(d.d,Jp);c=true;break}f=Gk(No(Qo(Qg,f),Kp));if(Rn(a.b,f)){!d.d&&(d.d=new Tn);Qn(d.d,Jp);c=true;break}}return c}
+function $o(a,b,c,d,e,f,g){var h,j,l,m,n;j=f?a.d:a.b;if(g){for(m=Yo(Ld(!c?j.c:Ci(j,c,~~yc(c))),d),l=m;l>=1;--l){h=Wo(l,e);n=_o(b,j,c,d,h);if(!n){h=ap(b,h);n=_o(b,j,c,d,h)}if(n){return n}}}else{n=_o(b,j,c,d,e);if(!n){e=ap(b,e);n=_o(b,j,c,d,e)}if(n){return n}}throw new cc("Can't find exported method for given arguments: "+d+Yp+e.length+gq)}
+function Uf(){var a;!!$stats&&$f('com.google.gwt.useragent.client.UserAgentAsserter');a=lg();uk(mq,a)||($wnd.alert('ERROR: Possible problem with your *.gwt.xml module file.\nThe compile time user.agent value (safari) does not match the runtime user.agent value ('+a+'). Expect more errors.\n'),undefined);!!$stats&&$f('com.google.gwt.user.client.DocumentModeAsserter');kg();!!$stats&&$f('com.dom_distiller.client.DomDistiller');bb();ip();new R;new $;new Kb}
+function Dk(n,a,b){var c=new RegExp(a,Hq);var d=[];var e=0;var f=n;var g=null;while(true){var h=c.exec(f);if(h==null||f==Kp||e==b-1&&b>0){d[e]=f;break}else{d[e]=f.substring(0,h.index);f=f.substring(h.index+h[0].length,f.length);c.lastIndex=0;if(g==f){d[e]=f.substring(0,1);f=f.substring(1)}g=f;e++}}if(b==0&&n.length>0){var j=d.length;while(j>0&&d[j-1]==Kp){--j}j<d.length&&d.splice(j,d.length-j)}var l=Ik(d.length);for(var m=0;m<d.length;++m){l[m]=d[m]}return l}
+function fp(a,b){var c,d,e,f,g,h,j,l,m,n;for(e=0,m=b.length;e<m;++e){l=a[e+3];c=gp(b,e);if(uk(c,l)){continue}if(uk('string',l)&&uk(cq,c)){continue}h=uk(Eq,c);f=uk('boolean',c);if(Ve===l){h&&(b[e]=new Mj(b[e]),undefined);f&&(b[e]=(fj(),b[e]?ej:dj),undefined);continue}j=h||f;g=!j&&l!=null&&mc(l)==Le;if(g){n=b[e];if(n==null||dp(n,Kd(l,15))){continue}if(Nd(n)){d=cp(Ld(n));if(d!=null){if(dp(d,Kd(l,15))){b[e]=d;continue}}}}if(uk(Sp,l)&&!h&&!f){continue}return false}return true}
+function Bb(){var a,b,c,d,e,f;c=$wnd.location.pathname;f=Dk(c,Tp,0);On(new Gn(f));a=new kn;for(b=0;b<f.length;++b){e=f[b];if(e.indexOf(Up)!=-1){d=Dk(e,Vp,0)[1];Vb(d,'[^a-zA-Z]')||(e=Dk(e,Vp,0)[0])}e=Rb(e,',00',Kp);b<2&&(e=Rb(e,'((_|-)?p[a-z]*|(_|-))[0-9]{1,2}$',Kp));if(!e.length)continue;if(b<2&&Vb(e,'^\\d{1,2}$'))continue;if(b==0&&vk(e,'index'))continue;if(b<2&&e.length<3&&!Vb(f[0],'[a-z]')){continue}Cd(a.b,a.c++,e)}return $wnd.location.protocol+'//'+$wnd.location.host+Tp+Db(a)}
+function rh(a,b,c,d){var e,f,g,h,j;++a.v;if(a.d){th(a);a.d=false}if(a.k!=0){return}j=false;g=false;if(d==0){return}f=c+d;for(h=c;h<f;++h){Tb(uj(b[h]))&&(b[h]=32)}while(c<f){e=b[c];if(e==32){j=true;++c;--d}else{break}}while(d>0){e=b[c+d-1];if(e==32){g=true;--d}else{break}}if(d==0){if(j||g){if(!a.q){bl(a.u,32);bl(a.x,32)}a.q=true}else{a.q=false}return}if(j){if(!a.q){bl(a.u,32);bl(a.x,32)}}a.b==-1&&(a.b=a.s);fl(a.u,b,c,d);fl(a.x,b,c,d);if(g){bl(a.u,32);bl(a.x,32)}a.q=g;Qn(a.c,ek(a.v))}
 
-function mh(a){var b,c,d,e,f,g,h,j,l,m,n,o,q,r;if(a.j==0){pk(Fp,a.o)&&a.j==0&&nh(a,Ak(a.x.b.b));al(a.u);al(a.x);return}c=a.x.b.b.length;switch(c){case 0:return;case 1:if(a.q){al(a.u);al(a.x);return}}r=Vi(a.x);f=0;d=0;j=0;b=-1;e=0;g=0;for(n=0,o=r.length;n<o;++n){m=r[n];if(ok(uq,m)){a.i=true}else if(ok(vq,m)){a.i=false}else if(Go(Ko(fh,m))){++e;++f;++g;a.i&&++d;q=m.length;b+=q+1;if(b>80){++j;b=q;g=1}}else{++e}}if(e==0){return}if(j==0){h=f;j=1}else{h=f-g}l=new ng(Ak(a.u.b.b),a.c,f,d,h,j,a.p);a.c=new Mn;++a.p;al(a.u);al(a.x);mg(l,a.b);ih(a,l);a.b=-1}
-function Tg(a,b){var c,d,e,f,g,h,j,l,m,n,o;n=b.b;if(n.c<2){return false}g=-1;e=null;f=-1;c=0;h=-1;for(m=new gm(n);m.c<m.e.M();){l=Dd(em(m),8);if(l.c){j=l.i;if(j>g){e=l;g=j;h=c;a.b&&(f=l.q)}}++c}for(m=new gm(n);m.c<m.e.M();){l=Dd(em(m),8);if(l==e){lg(l,true);!l.d&&(l.d=new Nn);Kn(l.d,pq)}else{lg(l,false);!l.d&&(l.d=new Nn);Kn(l.d,oq)}}if(a.b&&h!=-1){for(d=new mm(n,h);d.c>0;){l=Dd(km(d),8);o=l.q;if(o<f){break}else o==f&&l.i>=a.c&&lg(l,true)}for(d=new mm(n,h);d.c<d.e.M();){l=Dd(em(d),8);o=l.q;if(o<f){break}else o==f&&l.i>=a.c&&lg(l,true)}}return true}
-function eg(){var b=navigator.userAgent.toLowerCase();var c=function(a){return parseInt(a[1])*1000+parseInt(a[2])};if(function(){return b.indexOf(iq)!=-1}())return iq;if(function(){return b.indexOf('webkit')!=-1}())return gq;if(function(){return b.indexOf(jq)!=-1&&$doc.documentMode>=9}())return 'ie9';if(function(){return b.indexOf(jq)!=-1&&$doc.documentMode>=8}())return 'ie8';if(function(){var a=/msie ([0-9]+)\.([0-9]+)/.exec(b);if(a&&a.length==3)return c(a)>=6000}())return 'ie6';if(function(){return b.indexOf('gecko')!=-1}())return 'gecko1_8';return 'unknown'}
-function Gb(g){var d=dp('com.dom_distiller.PagingLinksFinder');var e,f=g;$wnd.com.dom_distiller.PagingLinksFinder=Ap(function(){var a,b=this,c=arguments;c.length==1&&f.y(c[0])?(a=c[0]):c.length==0&&(a=new xb);b.g=a;gp(a,b);return b});e=$wnd.com.dom_distiller.PagingLinksFinder.prototype=new Object;$wnd.com.dom_distiller.PagingLinksFinder.findNext=Ap(function(a){return zb(a,0)});$wnd.com.dom_distiller.PagingLinksFinder.findPrevious=Ap(function(a){return zb(a,1)});if(d)for(p in d)$wnd.com.dom_distiller.PagingLinksFinder[p]===undefined&&($wnd.com.dom_distiller.PagingLinksFinder[p]=d[p])}
-function W(g){var d=dp('com.dom_distiller.DocumentTitleGetter');var e,f=g;$wnd.com.dom_distiller.DocumentTitleGetter=Ap(function(){var a,b=this,c=arguments;c.length==1&&f.y(c[0])?(a=c[0]):c.length==0&&(a=new R);b.g=a;gp(a,b);return b});e=$wnd.com.dom_distiller.DocumentTitleGetter.prototype=new Object;$wnd.com.dom_distiller.DocumentTitleGetter.getDocumentTitle=Ap(function(a,b){return fp(null,Nd,0,arguments,true,false)[0]});ep(Nd,{0:{2:[[S,null,undefined,Oe,Kp]]}},true);if(d)for(p in d)$wnd.com.dom_distiller.DocumentTitleGetter[p]===undefined&&($wnd.com.dom_distiller.DocumentTitleGetter[p]=d[p])}
-function S(a,b){var c,d,e,f,g,h,j;c=Ep;d=Ep;if(hc(a)==Ue){c=d=(f=a,Hd(f)?f.tS():f.toString?f.toString():'[JavaScriptObject]')}else if(b){e=b.getElementsByTagName(Fp);e.length>0&&(c=d=e[0].textContent)}if(c==Ep)return Ep;if(Qb(c,' [\\|\\-] ')){c=Ob(d,'(.*)[\\|\\-] .*',Gp);xk(c,Hp,0).length<3&&(c=Ob(d,'[^\\|\\-]*[\\|\\-](.*)',Gp))}else if(c.indexOf(Ip)!=-1){c=Ob(d,'.*:(.*)',Gp);xk(c,Hp,0).length<3&&(c=Ob(d,'[^:]*[:](.*)',Gp))}else if(!!b&&(c.length>150||c.length<15)){c=(g=b.getElementsByTagName(Jp),g.length==1?g[0].textContent:null);c==null&&(c=d)}c=(h=new Mo('^\\s+|\\s+$'),j=new Io(h.c,h.b,c),Ho(j,Ep));xk(c,Hp,0).length<=4&&(c=d);return c}
-function Og(a){Kg();var b;if(a==null){this.b=null}else{a=uk(a,160,32);a=vk(a,nq,Ep);a=Ak(a).toLowerCase();if(a.length==0){this.b=null}else{this.b=new Mn;Kn(this.b,a);b=Mg(a,'[ ]*[\\|\xBB|-][ ]*');b!=null&&Kn(this.b,b);b=Mg(a,'[ ]*[\\|\xBB|:][ ]*');b!=null&&Kn(this.b,b);b=Mg(a,'[ ]*[\\|\xBB|:\\(\\)][ ]*');b!=null&&Kn(this.b,b);b=Mg(a,'[ ]*[\\|\xBB|:\\(\\)\\-][ ]*');b!=null&&Kn(this.b,b);b=Mg(a,'[ ]*[\\|\xBB|,|:\\(\\)\\-][ ]*');b!=null&&Kn(this.b,b);b=Mg(a,'[ ]*[\\|\xBB|,|:\\(\\)\\-\xA0][ ]*');b!=null&&Kn(this.b,b);Lg(this.b,a,'[ ]+[\\|][ ]+');Lg(this.b,a,'[ ]+[\\-][ ]+');Kn(this.b,wk(a,' - [^\\-]+$',Ep));Kn(this.b,wk(a,'^[^\\-]+ - ',Ep))}}}
-function J(){var o,q,r,s;H();var a,b,c,d,e,f,g,h,j,l,m,n;g=new ph;f=$doc.documentElement;n=($(),o=new cb(g),gb(new hb(o),f),o.c);mh(g);e=(mh(g),new qg(g.w,g.t));true|zg(e)|Ng(new Og(e.c),e)|yg(e)|vg((ug(),tg),e)|Xg(e)|Gg((Fg(),Dg),e)|_g(($g(),Zg),e)|Gg(Eg,e)|Tg((Sg(),Rg),e)|Pg(e)|Vg(e)|Wg(e);d=new dn;for(m=new gm(e.b);m.c<m.e.M();){l=Dd(em(m),8);!!l.d&&Ln(l.d,Dp)||$m(d,l.b)}q=qd(d.b,0,d.c);wn(q,0,q.length);Hn(d,q);c=new en(d.c);for(j=new gm(d);j.c<j.e.M();){h=Dd(em(j),18);Zm(c,Ed(_m(n,h.b-1)))}b=Jb(c,$doc.documentElement);a=rb((r=new mb(b),s=ib((Xl(0,b.c),Ed(b.b[0]))),gb(new hb(r),s),jb(r.d,(Xl(0,b.c),Ed(b.b[0])))));if(a.nodeType!=1){return Ep}return a.innerHTML}
-function Gg(a,b){var c,d,e,f,g,h,j,l,m,n,o;n=b.b;if(n.c<2){return false}d=false;if(a.b){j=null;g=0;for(m=new gm(n);m.c<m.e.M();){l=Dd(em(m),8);++g;if(l.c){j=l;break}}if(!j){return false}}else{j=(Xl(0,n.c),Dd(n.b[0],8));g=1}for(f=new mm(n,g);f.c<f.e.M();){c=Dd(em(f),8);if(!c.c){j=c;continue}e=c.p-j.o-1;if(e<=a.c){h=true;a.b&&(!j.c||!c.c)&&(h=false);h&&a.d&&j.q!=c.q&&(h=false);if(h){Fd(j.r,22)||(j.r=new cl(j.r));o=Dd(j.r,22);o.b.b+=aq;Yk(o,c.r);j.i+=c.i;j.j+=c.j;j.k+=c.k;j.n+=c.n;j.p=ck(j.p,c.p);j.o=bk(j.o,c.o);kg(j);j.c=j.c|c.c;!j.b&&(j.b=new Mn);kl(j.b,c.b);j.f+=c.f;!!c.d&&(!j.d?(j.d=new On(c.d)):j.d.R(c.d));j.q=ck(j.q,c.q);fm(f);d=true}else{j=c}}else{j=c}}return d}
-function zg(a){var b,c,d,e,f,g,h;b=false;for(f=new gm(a.b);f.c<f.e.M();){e=Dd(em(f),8);d=e.i;if(d<15){g=Ak(e.r.tS());c=g.length;if(c>=8){h=g.toLowerCase();if(h.indexOf('comments')==0||Bg(h,c,ud(Mf,qp,1,[' comments',' users responded in']))||h.indexOf('\xA9 reuters')==0||h.indexOf('please rate this')==0||h.indexOf('post a comment')==0||h.indexOf('what you think...')!=-1||h.indexOf('add your comment')!=-1||h.indexOf('add comment')!=-1||h.indexOf('reader views')!=-1||h.indexOf('have your say')!=-1||h.indexOf('reader comments')!=-1||h.indexOf('r\xE4tta artikeln')!=-1||ok(h,'thanks for your comments - this feedback is now closed')){!e.d&&(e.d=new Nn);Kn(e.d,kq);b=true}}else e.e==1&&ok(g,'Comment')&&(!e.d&&(e.d=new Nn),Kn(e.d,kq))}}return b}
-function Ri(){pi(this);Oi(this,'STYLE',(wh(),th));Oi(this,'SCRIPT',th);Oi(this,'OPTION',th);Oi(this,'OBJECT',th);Oi(this,'EMBED',th);Oi(this,'APPLET',th);Oi(this,'LINK',th);Oi(this,Op,rh);Oi(this,'BODY',sh);Oi(this,'STRIKE',uh);Oi(this,'U',uh);Oi(this,'B',uh);Oi(this,'I',uh);Oi(this,'EM',uh);Oi(this,'STRONG',uh);Oi(this,'SPAN',uh);Oi(this,'SUP',uh);Oi(this,'CODE',uh);Oi(this,'TT',uh);Oi(this,'SUB',uh);Oi(this,'VAR',uh);Oi(this,'ABBR',vh);Oi(this,'ACRONYM',vh);Oi(this,'FONT',uh);Oi(this,'NOSCRIPT',th);Oi(this,'LI',new Yh(new ch(ud(Mf,qp,1,[qq]))));Oi(this,Jp,new Yh(new ch(ud(Mf,qp,1,['de.l3s.boilerpipe/H1',rq]))));Oi(this,'H2',new Yh(new ch(ud(Mf,qp,1,['de.l3s.boilerpipe/H2',rq]))));Oi(this,'H3',new Yh(new ch(ud(Mf,qp,1,['de.l3s.boilerpipe/H3',rq]))))}
-function dg(){var a,b,c;b=$doc.compatMode;a=ud(Mf,qp,1,[hq]);for(c=0;c<a.length;++c){if(ok(a[c],b)){return}}a.length==1&&ok(hq,a[0])&&ok('BackCompat',b)?"GWT no longer supports Quirks Mode (document.compatMode=' BackCompat').<br>Make sure your application's host HTML page has a Standards Mode (document.compatMode=' CSS1Compat') doctype,<br>e.g. by using &lt;!doctype html&gt; at the start of your application's HTML page.<br><br>To continue using this unsupported rendering mode and risk layout problems, suppress this message by adding<br>the following line to your*.gwt.xml module file:<br>&nbsp;&nbsp;&lt;extend-configuration-property name=\"document.compatMode\" value=\""+b+'"/&gt;':"Your *.gwt.xml module configuration prohibits the use of the current doucment rendering mode (document.compatMode=' "+b+"').<br>Modify your application's host HTML page doctype, or update your custom 'document.compatMode' configuration property settings."}
-function zb(b,c){var d,e,f,g,h,j,l,m,n,o,q,r,s,t,u,v,w,x,y,z,A;e=yb();d=b.getElementsByTagName(Op);y=new Ki;for(f=0;f<d.length;++f){h=d[f];l=Ob(Ob(h.href,'#.*$',Ep),Pp,Ep);if(!l.length||pk(l,$wnd.location.href)||c==0&&pk(l,e)){continue}if(!pk($wnd.location.host,xk(l,'\\/+',0)[1])){continue}o=h.textContent;if(Qb(o,Qp)||o.length>25){continue}if(c==0){m=Ob(l,e,Ep);if(!Qb(m,'\\d'))continue}n=null;if(l==null?y.d:l!=null?Rp+l in y.f:xi(y,null,~~Qk(null))){n=Dd(l==null?y.c:l!=null?y.f[Rp+l]:vi(y,null,~~Qk(null)),6);n.c+=' | '+o}else{n=new Cb(o,l);l==null?Bi(y,n):l!=null?Ci(y,l,n):Ai(y,null,n,~~Qk(null))}l.indexOf(e)!=0&&(n.d-=25);j=o+Sp+h.className+Sp+h.id;Qb(j,c==0?Tp:Up)&&(n.d+=50);Qb(j,Vp)&&(n.d+=25);Qb(j,'(first|last)')&&(c==0&&!Qb(n.c,Tp)||c==1&&!Qb(n.c,Up))&&(n.d-=65);(Qb(j,Wp)||Qb(j,Qp))&&(n.d-=50);Qb(j,c==0?Up:Tp)&&(n.d-=200);w=false;r=false;u=nd(h);while(!!u&&(!w||!r)){v=u.className+Sp+u.id;if(!w&&Qb(v,Vp)){n.d+=25;w=true}if(!r&&Qb(v,Wp)){if(!Qb(v,'article|body|content|entry|hentry|main|page|pagination|post|text|blog|story')){n.d-=25;r=true}}u=nd(u)}(Qb(l,'p(a|g|ag)?(e|ing|ination)?(=|\\/)[0-9]{1,2}')||Qb(l,'(page|paging)'))&&(n.d+=25);Qb(l,Qp)&&(n.d-=15);q=0;try{q=Ej(o)}catch(a){a=Of(a);if(!Fd(a,20))throw a}q>0&&(q==1?(n.d-=10):(n.d+=0>10-q?0:10-q))}z=null;if(y.e!=0){x=(A=new xl(y),new Gm(y,A));g=Fm(x);while(dm(g.b.b)){t=Dd(Lm(g),6);t.d>=50&&(!z||z.d<t.d)&&(z=t)}}if(z){s=Ob(z.b,Pp,Ep);return s}return null}
-var Ep='',aq='\n',Sp=' ',Xp=' \t\n\r',Aq='"',Gp='$1',uq='$\uE00A<',nq="'",$p='(',Tp='(next|weiter|continue|>([^\\|]|$)|\xBB([^\\|]|$))',Up='(prev|early|old|new|<|\xAB)',fq=')',wq=', ',Mp='.',lq='.com',Lp='/',Rp=':',Ip=': ',xq='=',vq='>\uE00A$',Bp='@',bq='@@',Op='A',hq='CSS1Compat',Cp='DomDistiller',zq='For input string: "',Jp='H1',Zp='String',Fp='TITLE',cq='Unknown',dq='[',mq='[\b ]+',Np='[.]',Gq='[Ljava.lang.',Dq='[object Array]',Pp='\\/$',Hp='\\s+',eq=']',_p='anonymous',Mq='com.dom_distiller.client.',Fq='com.google.gwt.core.client.',Hq='com.google.gwt.core.client.impl.',Kq='com.google.gwt.logging.impl.',Wp='combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget',Oq='de.l3s.boilerpipe.document.',Rq='de.l3s.boilerpipe.filters.english.',Qq='de.l3s.boilerpipe.filters.heuristics.',Nq='de.l3s.boilerpipe.sax.',rq='de.l3s.boilerpipe/HEADING',kq='de.l3s.boilerpipe/INDICATES_END_OF_TEXT',qq='de.l3s.boilerpipe/LI',oq='de.l3s.boilerpipe/MIGHT_BE_CONTENT',Dp='de.l3s.boilerpipe/TITLE',pq='de.l3s.boilerpipe/VERY_LIKELY_CONTENT',Cq='fromIndex: ',Bq='g',Eq='java.lang.',Lq='java.util.',Iq='java.util.logging.',Pq='java.util.regex.',jq='msie',Yp='null',yq='number',Kp='object',iq='opera',Jq='org.timepedia.exporter.client.',Sq='org.xml.sax.',Vp='pag(e|ing|inat)',Qp='print|archive|comment|discuss|e[\\-]?mail|share|reply|all|login|sign|single',gq='safari',sq='{',tq='}';var _,Qf={},rp={11:1,23:1},vp={11:1,26:1},up={26:1},xp={27:1},wp={29:1},sp={30:1},zp={11:1,25:1},yp={25:1},pp={},tp={10:1},qp={11:1};Rf(1,-1,pp);_.eQ=function D(a){return this===a};_.gC=function E(){return this.cZ};_.hC=function F(){return tc(this)};_.tS=function G(){return this.cZ.e+Bp+Yj(this.hC())};_.toString=function(){return this.tS()};_.tM=mp;Rf(3,1,{2:1,31:1},I);Rf(4,1,{},O);_.y=function P(a){return a!=null&&Fd(a,2)};var L=false;Rf(5,1,{3:1,31:1},R);Rf(6,1,{},X);_.y=function Y(a){return a!=null&&Fd(a,3)};var U=false;Rf(9,1,{},cb);_.z=function db(a){var b;b=a;lh(this.b,b.tagName,b.tagName)};_.A=function eb(a){var b,c,d,e,f;switch(a.nodeType){case 3:Zm(this.c,a);d=a.data;kh(this.b,(e=d.length,f=td(Hf,qp,-1,e,1),qk(d,e,f,0),f),0,d.length);return false;case 1:c=a;b=ab(c);oh(this.b,c.tagName,c.tagName,b);return true;case 9:default:return false;}};_.b=null;_.c=null;Rf(10,1,{},hb);_.b=null;Rf(12,1,{},mb);_.z=function nb(a){bn(this.b,this.b.c-1);bn(this.e,this.e.c-1)};_.A=function ob(a){if(!this.c.b)return false;Zm(this.b,a);Zm(this.e,null);if(this.e.c==1){this.d=new sb(a);cn(this.e,0,this.d)}ub(this.c,a)&&lb(this);return true};_.b=null;_.c=null;_.d=null;_.e=null;Rf(13,1,{4:1},sb);_.b=null;_.c=null;Rf(14,1,{},vb);_.b=null;_.c=null;Rf(15,1,{5:1,31:1},xb);Rf(16,1,{6:1},Cb);_.b=null;_.c=null;_.d=0;Rf(17,1,{},Hb);_.y=function Ib(a){return a!=null&&Fd(a,5)};var Eb=false;Rf(19,1,{},Lb);_.z=function Mb(a){};_.A=function Nb(a){if(!this.d.b&&!this.c){return false}if(ub(this.d,a)){this.c=true;Zm(this.b,a)}else a.nodeType==3&&!Pb(a.nodeValue)&&(this.c=false);switch(a.nodeType){case 3:return true;case 1:this.c&&a.nodeType==1&&ok('IMG',a.tagName)&&Zm(this.b,a);return true;case 9:default:return false;}};_.b=null;_.c=false;_.d=null;Rf(26,1,rp);_.B=function Wb(){return this.f};_.tS=function Xb(){var a,b;a=this.cZ.e;b=this.B();return b!=null?a+Ip+b:a};_.f=null;Rf(25,26,rp);Rf(24,25,rp,Zb);Rf(23,24,rp,$b);_.B=function ec(){this.d==null&&(this.e=bc(this.c),this.b=this.b+Ip+_b(this.c),this.d=$p+this.e+') '+dc(this.c)+this.b,undefined);return this.d};_.b=Ep;_.c=null;_.d=null;_.e=null;Rf(30,1,{});var kc=0,lc=0,mc=0,nc=-1;Rf(32,30,{},Bc);_.b=null;_.c=null;var xc;Rf(35,1,{},Lc);_.C=function Mc(){var a={};var b=[];var c=arguments.callee.caller.caller;while(c){var d=this.D(c.toString());b.push(d);var e=Rp+d;var f=a[e];if(f){var g,h;for(g=0,h=f.length;g<h;g++){if(f[g]===c){return b}}}(f||(a[e]=[])).push(c);c=c.caller}return b};_.D=function Nc(a){return Ec(a)};_.E=function Oc(a){return []};Rf(37,35,{});_.C=function Sc(){return Hc(this.E(Kc()),this.F())};_.E=function Tc(a){return Rc(this,a)};_.F=function Uc(){return 2};Rf(36,37,{});_.C=function _c(){return Wc(this)};_.D=function ad(a){var b,c,d,e;if(a.length==0){return _p}e=Ak(a);e.indexOf('at ')==0&&(e=yk(e,3));c=e.indexOf(dq);c!=-1&&(e=Ak(e.substr(0,c-0))+Ak(yk(e,e.indexOf(eq,c)+1)));c=e.indexOf($p);if(c==-1){c=e.indexOf(Bp);if(c==-1){d=e;e=Ep}else{d=Ak(yk(e,c+1));e=Ak(e.substr(0,c-0))}}else{b=e.indexOf(fq,c);d=e.substr(c+1,b-(c+1));e=Ak(e.substr(0,c-0))}c=rk(e,Ik(46));c!=-1&&(e=yk(e,c+1));return (e.length>0?e:_p)+bq+d};_.E=function bd(a){return Zc(this,a)};_.F=function cd(){return 3};Rf(38,36,{},ed);Rf(39,1,{});Rf(40,39,{},ld);_.b=Ep;Rf(49,1,{},od);_.qI=0;var wd,xd;Rf(58,1,{},Xf);_.b=null;Rf(60,1,sp,_f);_.b=null;Rf(59,60,sp,ag);Rf(67,1,{8:1},ng);_.tS=function og(){return dq+this.p+'-'+this.o+';tl='+this.q+'; nw='+this.i+';nwl='+this.n+';ld='+this.e+']\t'+(this.c?'CONTENT':'boilerplate')+','+this.d+aq+this.r.tS()};_.b=null;_.c=false;_.d=null;_.e=0;_.f=0;_.i=0;_.j=0;_.k=0;_.n=0;_.o=0;_.p=0;_.q=0;_.r=null;_.s=0;var gg,hg;Rf(68,1,{},qg);_.b=null;_.c=null;Rf(69,1,{});Rf(70,69,{},wg);_.b=0;var tg;Rf(73,1,{},Hg);_.b=false;_.c=0;_.d=false;var Dg,Eg;Rf(74,1,{},Og);_.b=null;var Jg;Rf(76,1,{},Ug);_.b=false;_.c=0;var Rg;Rf(80,1,{},ah);_.b=null;var Zg;Rf(81,1,{9:1},ch);_.tS=function dh(){return qe.e+Bp+Yj(tc(this))+sq+new An(this.b)+tq};_.b=null;Rf(82,1,{},ph);_.b=-1;_.d=false;_.f=0;_.i=false;_.j=0;_.k=0;_.o=null;_.p=0;_.q=false;_.r=null;_.s=0;_.v=0;_.w=null;var fh;var rh,sh,th,uh,vh;Rf(84,1,tp,yh);_.G=function zh(){return true};_.H=function Ah(a,b,c){--a.k;return true};_.I=function Bh(a,b,c,d){++a.k;return true};Rf(85,1,tp,Eh);_.G=function Fh(){return true};_.H=function Gh(a,b,c){return Dh(a)};_.I=function Hh(a,b,c,d){a.f++>0&&Dh(a);if(a.k==0){jh(a);Zk(a.x,uq);Xk(a.x,32);a.q=true}return false};Rf(86,1,tp,Jh);_.G=function Kh(){return true};_.H=function Lh(a,b,c){mh(a);--a.j;return false};_.I=function Mh(a,b,c,d){mh(a);++a.j;return false};Rf(87,1,tp,Oh);_.G=function Ph(){return false};_.H=function Qh(a,b,c){jh(a);return false};_.I=function Rh(a,b,c,d){jh(a);return false};Rf(88,1,tp,Th);_.G=function Uh(){return false};_.H=function Vh(a,b,c){return false};_.I=function Wh(a,b,c,d){return false};Rf(89,1,tp,Yh);_.G=function Zh(){return true};_.H=function $h(a,b,c){return true};_.I=function _h(a,b,c,d){hh(a,this.b);return true};_.b=null;Rf(94,1,up);_.J=function hi(a){return !!fi(this,a)};_.eQ=function ii(a){var b,c,d,e,f;if(a===this){return true}if(!Fd(a,26)){return false}e=Dd(a,26);if(this.M()!=e.M()){return false}for(c=new Cl(e.K().b);dm(c.b);){b=Dd(em(c.b),27);d=b.Y();f=b.Z();if(!this.J(d)){return false}if(!vo(f,this.L(d))){return false}}return true};_.L=function ji(a){var b;b=fi(this,a);return !b?null:b.Z()};_.hC=function ki(){var a,b,c;c=0;for(b=new Cl(this.K().b);dm(b.b);){a=Dd(em(b.b),27);c+=a.hC();c=~~c}return c};_.M=function li(){return this.K().b.e};_.tS=function mi(){var a,b,c,d;d=sq;a=false;for(c=new Cl(this.K().b);dm(c.b);){b=Dd(em(c.b),27);a?(d+=wq):(a=true);d+=Ep+b.Y();d+=xq;d+=Ep+b.Z()}return d+tq};Rf(93,94,up);_.J=function Ei(a){return ri(this,a)};_.K=function Fi(){return new xl(this)};_.O=function Gi(a,b){return this.N(a,b)};_.L=function Hi(a){return ui(this,a)};_.M=function Ii(){return this.e};_.b=null;_.c=null;_.d=false;_.e=0;_.f=null;Rf(92,93,vp,Ki,Li);_.N=function Mi(a,b){return Ji(a,b)};_.P=function Ni(a){return ~~ic(a)};Rf(91,92,vp);Rf(90,91,vp,Ri);var Pi;var Si,Ti;Rf(96,24,rp,Xi);Rf(97,1,{11:1,12:1,16:1},bj);_.cT=function cj(a){return aj(this,Dd(a,12))};_.eQ=function dj(a){return Fd(a,12)&&Dd(a,12).b==this.b};_.hC=function ej(){return this.b?1231:1237};_.tS=function fj(){return this.b?'true':'false'};_.b=false;var Zi,$i;Rf(98,1,{11:1,14:1,16:1},ij);_.cT=function jj(a){return hj(this,Dd(a,14))};_.eQ=function lj(a){return Fd(a,14)&&Dd(a,14).b==this.b};_.hC=function mj(){return this.b};_.tS=function nj(){return Kk(this.b)};_.b=0;var pj;Rf(100,1,{15:1},sj);_.tS=function zj(){return ((this.b&2)!=0?'interface ':(this.b&1)!=0?Ep:'class ')+this.e};_.b=0;_.c=0;_.d=null;_.e=null;Rf(101,24,rp,Bj);Rf(103,1,{11:1,19:1});Rf(102,103,{11:1,16:1,17:1,19:1},Gj);_.cT=function Ij(a){return Fj(this,Dd(a,17))};_.eQ=function Jj(a){return Fd(a,17)&&Dd(a,17).b==this.b};_.hC=function Kj(){return Jd(this.b)};_.tS=function Lj(){return Ep+this.b};_.b=0;Rf(104,24,rp,Nj);Rf(105,24,rp,Pj);Rf(106,24,rp,Rj);Rf(107,103,{11:1,16:1,18:1,19:1},Uj);_.cT=function Vj(a){return Tj(this,Dd(a,18))};_.eQ=function Wj(a){return Fd(a,18)&&Dd(a,18).b==this.b};_.hC=function Xj(){return this.b};_.tS=function Zj(){return Ep+this.b};_.b=0;var _j;Rf(110,24,rp,ek);var fk;Rf(112,104,{11:1,20:1,23:1},ik);Rf(113,1,{11:1,21:1},kk);_.tS=function lk(){return this.b+Mp+this.e+$p+(this.c!=null?this.c:'Unknown Source')+(this.d>=0?Rp+this.d:Ep)+fq};_.b=null;_.c=null;_.d=0;_.e=null;_=String.prototype;_.cM={1:1,11:1,13:1,16:1};_.cT=function Fk(a){return Gk(this,Dd(a,1))};_.eQ=function Hk(a){return ok(this,a)};_.hC=function Jk(){return Qk(this)};_.tS=_.toString;var Lk,Mk=0,Nk;Rf(115,1,{13:1},Tk);_.tS=function Uk(){return this.b.b};Rf(116,1,{13:1,22:1},bl,cl);_.tS=function el(){return this.b.b};Rf(117,106,rp,gl);Rf(118,24,rp,il);Rf(119,1,{});_.Q=function nl(a){throw new il('Add not supported on this collection')};_.R=function ol(a){return kl(this,a)};_.S=function pl(a){var b;b=ll(this.T(),a);return !!b};_.U=function ql(){return this.V(td(Kf,qp,0,this.M(),0))};_.V=function rl(a){var b,c,d;d=this.M();a.length<d&&(a=rd(a,d));c=this.T();for(b=0;b<d;++b){vd(a,b,c.X())}a.length>d&&vd(a,d,null);return a};_.tS=function sl(){return ml(this)};Rf(121,119,wp);_.eQ=function vl(a){var b,c,d;if(a===this){return true}if(!Fd(a,29)){return false}c=Dd(a,29);if(c.M()!=this.M()){return false}for(b=c.T();b.W();){d=b.X();if(!this.S(d)){return false}}return true};_.hC=function wl(){var a,b,c;a=0;for(b=this.T();b.W();){c=b.X();if(c!=null){a+=ic(c);a=~~a}}return a};Rf(120,121,wp,xl);_.S=function yl(a){var b,c,d;if(Fd(a,27)){b=Dd(a,27);c=b.Y();if(ri(this.b,c)){d=ui(this.b,c);return this.b.N(b.Z(),d)}}return false};_.T=function zl(){return new Cl(this.b)};_.M=function Al(){return this.b.e};_.b=null;Rf(122,1,{},Cl);_.W=function Dl(){return dm(this.b)};_.X=function El(){return Dd(em(this.b),27)};_.b=null;Rf(124,1,xp);_.eQ=function Hl(a){var b;if(Fd(a,27)){b=Dd(a,27);if(vo(this.Y(),b.Y())&&vo(this.Z(),b.Z())){return true}}return false};_.hC=function Il(){var a,b;a=0;b=0;this.Y()!=null&&(a=ic(this.Y()));this.Z()!=null&&(b=ic(this.Z()));return a^b};_.tS=function Jl(){return this.Y()+xq+this.Z()};Rf(123,124,xp,Kl);_.Y=function Ll(){return null};_.Z=function Ml(){return this.b.c};_.$=function Nl(a){return Bi(this.b,a)};_.b=null;Rf(125,124,xp,Pl);_.Y=function Ql(){return this.b};_.Z=function Rl(){return wi(this.c,this.b)};_.$=function Sl(a){return Ci(this.c,this.b,a)};_.b=null;_.c=null;Rf(126,119,yp);_._=function Vl(a,b){throw new il('Add not supported on this list')};_.Q=function Wl(a){this._(this.M(),a);return true};_.eQ=function Yl(a){var b,c,d,e,f;if(a===this){return true}if(!Fd(a,25)){return false}f=Dd(a,25);if(this.M()!=f.M()){return false}d=this.T();e=f.T();while(d.W()){b=d.X();c=e.X();if(!(b==null?c==null:gc(b,c))){return false}}return true};_.hC=function Zl(){var a,b,c;b=1;a=this.T();while(a.W()){c=a.X();b=31*b+(c==null?0:ic(c));b=~~b}return b};_.T=function _l(){return new gm(this)};_.bb=function am(a){throw new il('Remove not supported on this list')};_.cb=function bm(a,b){throw new il('Set not supported on this list')};Rf(127,1,{},gm);_.W=function hm(){return dm(this)};_.X=function im(){return em(this)};_.c=0;_.d=-1;_.e=null;Rf(128,127,{},mm);_.b=null;Rf(129,126,yp,om);_._=function pm(a,b){Xl(a,this.c+1);++this.c;Ym(this.d,this.b+a,b)};_.ab=function qm(a){Xl(a,this.c);return _m(this.d,this.b+a)};_.bb=function rm(a){var b;Xl(a,this.c);b=bn(this.d,this.b+a);--this.c;return b};_.cb=function sm(a,b){Xl(a,this.c);return cn(this.d,this.b+a,b)};_.M=function tm(){return this.c};_.b=0;_.c=0;_.d=null;Rf(130,121,wp,wm);_.S=function xm(a){return ri(this.b,a)};_.T=function ym(){return vm(this)};_.M=function zm(){return this.c.b.e};_.b=null;_.c=null;Rf(131,1,{},Bm);_.W=function Cm(){return dm(this.b.b)};_.X=function Dm(){var a;a=Dd(em(this.b.b),27);return a.Y()};_.b=null;Rf(132,119,{},Gm);_.S=function Hm(a){return ti(this.b,a)};_.T=function Im(){return Fm(this)};_.M=function Jm(){return this.c.b.e};_.b=null;_.c=null;Rf(133,1,{},Mm);_.W=function Nm(){return dm(this.b.b)};_.X=function Om(){return Lm(this)};_.b=null;Rf(134,126,yp);_._=function Rm(a,b){var c;c=Zn(this,a);Wn(c.e,b,c.c);++c.b;c.d=null};_.ab=function Sm(a){return Qm(this,a)};_.T=function Tm(){return Zn(this,0)};_.bb=function Um(b){var c,d;c=Zn(this,b);try{d=fo(c)}catch(a){a=Of(a);if(Fd(a,28)){throw new Rj("Can't remove element "+b)}else throw a}go(c);c.c==c.d?(c.c=c.d.b):--c.b;lo(c.d);c.d=null;--c.e.c;return d};_.cb=function Vm(b,c){var d,e;d=Zn(this,b);try{e=fo(d);go(d);d.d.d=c;return e}catch(a){a=Of(a);if(Fd(a,28)){throw new Rj("Can't set element "+b)}else throw a}};Rf(135,126,zp,dn,en);_._=function fn(a,b){Ym(this,a,b)};_.Q=function gn(a){return Zm(this,a)};_.R=function hn(a){return $m(this,a)};_.S=function jn(a){return an(this,a,0)!=-1};_.ab=function kn(a){return _m(this,a)};_.bb=function ln(a){return bn(this,a)};_.cb=function mn(a,b){return cn(this,a,b)};_.M=function on(){return this.c};_.U=function sn(){return qd(this.b,0,this.c)};_.V=function tn(a){var b;a.length<this.c&&(a=rd(a,this.c));for(b=0;b<this.c;++b){vd(a,b,this.b[b])}a.length>this.c&&vd(a,this.c,null);return a};_.c=0;Rf(137,126,zp,An);_.S=function Bn(a){return Ul(this,a)!=-1};_.ab=function Cn(a){return Xl(a,this.b.length),this.b[a]};_.cb=function Dn(a,b){return zn(this,a,b)};_.M=function En(){return this.b.length};_.U=function Fn(){return pd(this.b)};_.V=function Gn(a){var b,c;c=this.b.length;a.length<c&&(a=rd(a,c));for(b=0;b<c;++b){vd(a,b,this.b[b])}a.length>c&&vd(a,c,null);return a};_.b=null;Rf(140,121,{11:1,29:1},Mn,Nn,On);_.Q=function Pn(a){return Kn(this,a)};_.S=function Qn(a){return ri(this.b,a)};_.T=function Rn(){return vm(gi(this.b))};_.M=function Sn(){return this.b.e};_.tS=function Tn(){return ml(gi(this.b))};_.b=null;Rf(141,134,{11:1,24:1,25:1},ao);_.Q=function bo(a){return Vn(this,a)};_.M=function co(){return this.c};_.b=null;_.c=0;Rf(142,1,{},ho);_.W=function io(){return this.c!=this.e.b};_.X=function jo(){return fo(this)};_.b=0;_.c=null;_.d=null;_.e=null;Rf(143,1,{},mo,no);_.b=null;_.c=null;_.d=null;Rf(144,124,xp,po);_.Y=function qo(){return this.b};_.Z=function ro(){return this.c};_.$=function so(a){var b;b=this.c;this.c=a;return b};_.b=null;_.c=null;Rf(145,24,{11:1,23:1,28:1},uo);Rf(147,1,{},Co);_.b=null;_.c=null;var xo=null;Rf(148,60,sp,Eo);Rf(149,1,{},Io);_.b=null;_.c=null;_.d=null;Rf(150,1,{},Lo,Mo);_.b=null;_.c=null;Rf(152,1,{});Rf(151,152,{},Xo);var bp;Rf(158,1,{},jp);_.b=null;_.c=null;Rf(159,1,{},lp);var Ap=qc;var Oe=uj(Eq,'Object',1,null),Yd=uj(Fq,'JavaScriptObject$',27,Oe),Kf=tj(Gq,'Object;',163),Ve=uj(Eq,'Throwable',26,Oe),Ge=uj(Eq,'Exception',25,Ve),Pe=uj(Eq,'RuntimeException',24,Ge),Qe=uj(Eq,'StackTraceElement',113,Oe),Lf=tj(Gq,'StackTraceElement;',166),fe=uj('com.google.gwt.lang.','SeedUtil',55,Oe),Be=uj(Eq,'Boolean',97,Oe),Ne=uj(Eq,'Number',103,Oe),Hf=tj(Ep,'[C',167),Ce=uj(Eq,'Character',98,Oe),If=tj(Gq,'Character;',168),Ee=uj(Eq,'Class',100,Oe),Fe=uj(Eq,'Double',102,Ne),Ke=uj(Eq,'Integer',107,Ne),Jf=tj(Gq,'Integer;',169),Ue=uj(Eq,Zp,2,Oe),Mf=tj(Gq,'String;',164),De=uj(Eq,'ClassCastException',101,Pe),Se=uj(Eq,'StringBuilder',116,Oe),Ae=uj(Eq,'ArrayStoreException',96,Pe),Xd=uj(Fq,'JavaScriptException',23,Pe),ee=uj(Hq,'StringBufferImpl',39,Oe),zf=uj(Iq,'Logger',60,Oe),Ef=uj(Jq,'ExporterBaseImpl',152,Oe),Df=uj(Jq,'ExporterBaseActual',151,Ef),Cf=vj(Jq,'Exportable'),ce=uj(Hq,'StackTraceCreator$Collector',35,Oe),be=uj(Hq,'StackTraceCreator$CollectorMoz',37,ce),ae=uj(Hq,'StackTraceCreator$CollectorChrome',36,be),_d=uj(Hq,'StackTraceCreator$CollectorChromeNoSourceMap',38,ae),de=uj(Hq,'StringBufferImplAppend',40,ee),Zd=uj(Fq,'Scheduler',30,Oe),$d=uj(Hq,'SchedulerImpl',32,Zd),ge=uj(Kq,'LoggerImplRegular',58,Oe),lf=uj(Lq,'AbstractMap',94,Oe),af=uj(Lq,'AbstractHashMap',93,lf),Xe=uj(Lq,'AbstractCollection',119,Oe),nf=uj(Lq,'AbstractSet',121,Xe),Ze=uj(Lq,'AbstractHashMap$EntrySet',120,nf),Ye=uj(Lq,'AbstractHashMap$EntrySetIterator',122,Oe),kf=uj(Lq,'AbstractMapEntry',124,Oe),$e=uj(Lq,'AbstractHashMap$MapEntryNull',123,kf),_e=uj(Lq,'AbstractHashMap$MapEntryString',125,kf),gf=uj(Lq,'AbstractMap$1',130,nf),ff=uj(Lq,'AbstractMap$1$1',131,Oe),jf=uj(Lq,'AbstractMap$2',132,Xe),hf=uj(Lq,'AbstractMap$2$1',133,Oe),Le=uj(Eq,'NullPointerException',110,Pe),He=uj(Eq,'IllegalArgumentException',104,Pe),ef=uj(Lq,'AbstractList',126,Xe),of=uj(Lq,'ArrayList',135,ef),bf=uj(Lq,'AbstractList$IteratorImpl',127,Oe),cf=uj(Lq,'AbstractList$ListIteratorImpl',128,bf),df=uj(Lq,'AbstractList$SubList',129,ef),qf=uj(Lq,'HashMap',92,af),yf=uj(Iq,'LogManager',147,Oe),xf=uj(Iq,'LogManager$RootLogger',148,zf),he=uj(Kq,'LoggerWithExposedConstructor',59,zf),Kd=uj(Mq,'ContentExtractor_ExporterImpl',4,Oe),Ld=uj(Mq,'ContentExtractor',3,Oe),Md=uj(Mq,'DocumentTitleGetter_ExporterImpl',6,Oe),Nd=uj(Mq,'DocumentTitleGetter',5,Oe),Ud=uj(Mq,'PagingLinksFinder_ExporterImpl',17,Oe),Vd=uj(Mq,'PagingLinksFinder',15,Oe),Re=uj(Eq,'StringBuffer',115,Oe),vf=uj(Lq,'MapEntryImpl',144,kf),Td=uj(Mq,'PagingLinksFinder$PagingLinkObj',16,Oe),We=uj(Eq,'UnsupportedOperationException',118,Pe),wf=uj(Lq,'NoSuchElementException',145,Pe),Ie=uj(Eq,'IllegalStateException',105,Pe),re=uj(Nq,'BoilerpipeHTMLContentHandler',82,Oe),je=uj(Oq,'TextDocument',68,Oe),ie=uj(Oq,'TextBlock',67,Oe),Od=uj(Mq,'DomToSaxParser$DomToSaxVisitor',9,Oe),Pd=uj(Mq,'DomWalker',10,Oe),rf=uj(Lq,'HashSet',140,nf),Wd=uj(Mq,'RelevantImageFinder$Visitor',19,Oe),Rd=uj(Mq,'NodeTree',13,Oe),Qd=uj(Mq,'NodeListExpander$Visitor',12,Oe),Bf=uj(Pq,'Pattern',150,Oe),Af=uj(Pq,'Matcher',149,Oe),Me=uj(Eq,'NumberFormatException',112,He),ze=uj(Nq,'TagActionMap',91,qf),ye=uj(Nq,'DefaultTagActionMap',90,ze),ne=uj(Qq,'DocumentTitleMatchClassifier',74,Oe),ke=uj(Rq,'HeuristicFilterBase',69,Oe),le=uj(Rq,'IgnoreBlocksAfterContentFilter',70,ke),me=uj(Qq,'BlockProximityFusion',73,Oe),pe=uj('de.l3s.boilerpipe.filters.simple.','BoilerplateBlockFilter',80,Oe),oe=uj(Qq,'KeepLargestBlockFilter',76,Oe),pf=uj(Lq,'Arrays$ArrayList',137,ef),Je=uj(Eq,'IndexOutOfBoundsException',106,Pe),Sd=uj(Mq,'OrderedNodeMatcher',14,Oe),xe=uj(Nq,'CommonTagActions$BlockTagLabelAction',89,Oe),se=uj(Nq,'CommonTagActions$1',84,Oe),te=uj(Nq,'CommonTagActions$2',85,Oe),ue=uj(Nq,'CommonTagActions$3',86,Oe),ve=uj(Nq,'CommonTagActions$4',87,Oe),we=uj(Nq,'CommonTagActions$5',88,Oe),qe=uj('de.l3s.boilerpipe.labels.','LabelAction',81,Oe),mf=uj(Lq,'AbstractSequentialList',134,ef),uf=uj(Lq,'LinkedList',141,mf),sf=uj(Lq,'LinkedList$ListIteratorImpl',142,Oe),tf=uj(Lq,'LinkedList$Node',143,Oe),Gf=uj(Sq,'AttributesImpl',158,Oe),Ff=uj(Sq,'AttributesImpl$AttributeData',159,Oe),Te=uj(Eq,'StringIndexOutOfBoundsException',117,Je);$stats && $stats({moduleName:'domdistiller',sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalEnd'});if ($wnd.domdistiller) $wnd.domdistiller.onScriptLoad();
+function Q(g){var d=jp('com.dom_distiller.ContentExtractor');var e,f=g;$wnd.com.dom_distiller.ContentExtractor=Gp(function(){var a,b=this,c=arguments;c.length==1&&f.y(c[0])?(a=c[0]):c.length==0&&(a=new K);b.g=a;mp(a,b);return b});e=$wnd.com.dom_distiller.ContentExtractor.prototype=new Object;$wnd.com.dom_distiller.ContentExtractor.extractContent=Gp(function(){return L()});if(d)for(p in d)$wnd.com.dom_distiller.ContentExtractor[p]===undefined&&($wnd.com.dom_distiller.ContentExtractor[p]=d[p])}
+function th(a){var b,c,d,e,f,g,h,j,l,m,n,o,q,r;if(a.j==0){vk(Np,a.o)&&a.j==0&&uh(a,Gk(a.x.b.b));gl(a.u);gl(a.x);return}c=a.x.b.b.length;switch(c){case 0:return;case 1:if(a.q){gl(a.u);gl(a.x);return}}r=_i(a.x);f=0;d=0;j=0;b=-1;e=0;g=0;for(n=0,o=r.length;n<o;++n){m=r[n];if(uk(Aq,m)){a.i=true}else if(uk(Bq,m)){a.i=false}else if(Mo(Qo(mh,m))){++e;++f;++g;a.i&&++d;q=m.length;b+=q+1;if(b>80){++j;b=q;g=1}}else{++e}}if(e==0){return}if(j==0){h=f;j=1}else{h=f-g}l=new ug(Ub(a.u.b.b),a.c,f,d,h,j,a.p);a.c=new Sn;++a.p;gl(a.u);gl(a.x);tg(l,a.b);ph(a,l);a.b=-1}
+function $g(a,b){var c,d,e,f,g,h,j,l,m,n,o;n=b.b;if(n.c<2){return false}g=-1;e=null;f=-1;c=0;h=-1;for(m=new mm(n);m.c<m.e.M();){l=Kd(km(m),8);if(l.c){j=l.i;if(j>g){e=l;g=j;h=c;a.b&&(f=l.q)}}++c}for(m=new mm(n);m.c<m.e.M();){l=Kd(km(m),8);if(l==e){sg(l,true);!l.d&&(l.d=new Tn);Qn(l.d,vq)}else{sg(l,false);!l.d&&(l.d=new Tn);Qn(l.d,uq)}}if(a.b&&h!=-1){for(d=new sm(n,h);d.c>0;){l=Kd(qm(d),8);o=l.q;if(o<f){break}else o==f&&l.i>=a.c&&sg(l,true)}for(d=new sm(n,h);d.c<d.e.M();){l=Kd(km(d),8);o=l.q;if(o<f){break}else o==f&&l.i>=a.c&&sg(l,true)}}return true}
+function lg(){var b=navigator.userAgent.toLowerCase();var c=function(a){return parseInt(a[1])*1000+parseInt(a[2])};if(function(){return b.indexOf(oq)!=-1}())return oq;if(function(){return b.indexOf('webkit')!=-1}())return mq;if(function(){return b.indexOf(pq)!=-1&&$doc.documentMode>=9}())return 'ie9';if(function(){return b.indexOf(pq)!=-1&&$doc.documentMode>=8}())return 'ie8';if(function(){var a=/msie ([0-9]+)\.([0-9]+)/.exec(b);if(a&&a.length==3)return c(a)>=6000}())return 'ie6';if(function(){return b.indexOf('gecko')!=-1}())return 'gecko1_8';return 'unknown'}
+function Jb(g){var d=jp('com.dom_distiller.PagingLinksFinder');var e,f=g;$wnd.com.dom_distiller.PagingLinksFinder=Gp(function(){var a,b=this,c=arguments;c.length==1&&f.y(c[0])?(a=c[0]):c.length==0&&(a=new Ab);b.g=a;mp(a,b);return b});e=$wnd.com.dom_distiller.PagingLinksFinder.prototype=new Object;$wnd.com.dom_distiller.PagingLinksFinder.findNext=Gp(function(a){return Cb(a,0)});$wnd.com.dom_distiller.PagingLinksFinder.findPrevious=Gp(function(a){return Cb(a,1)});if(d)for(p in d)$wnd.com.dom_distiller.PagingLinksFinder[p]===undefined&&($wnd.com.dom_distiller.PagingLinksFinder[p]=d[p])}
+function Z(g){var d=jp('com.dom_distiller.DocumentTitleGetter');var e,f=g;$wnd.com.dom_distiller.DocumentTitleGetter=Gp(function(){var a,b=this,c=arguments;c.length==1&&f.y(c[0])?(a=c[0]):c.length==0&&(a=new U);b.g=a;mp(a,b);return b});e=$wnd.com.dom_distiller.DocumentTitleGetter.prototype=new Object;$wnd.com.dom_distiller.DocumentTitleGetter.getDocumentTitle=Gp(function(a,b){return lp(null,Ud,0,arguments,true,false)[0]});kp(Ud,{0:{2:[[V,null,undefined,Ve,Sp]]}},true);if(d)for(p in d)$wnd.com.dom_distiller.DocumentTitleGetter[p]===undefined&&($wnd.com.dom_distiller.DocumentTitleGetter[p]=d[p])}
+function V(a,b){var c,d,e,f,g,h,j;c=Kp;d=Kp;if(mc(a)==_e){c=d=(f=a,Od(f)?f.tS():f.toString?f.toString():'[JavaScriptObject]')}else if(b){e=b.getElementsByTagName(Np);e.length>0&&(c=d=e[0].textContent)}if(c==Kp)return Kp;if(Vb(c,' [\\|\\-] ')){c=Rb(d,'(.*)[\\|\\-] .*',Op);Dk(c,Pp,0).length<3&&(c=Rb(d,'[^\\|\\-]*[\\|\\-](.*)',Op))}else if(c.indexOf(Qp)!=-1){c=Rb(d,'.*:(.*)',Op);Dk(c,Pp,0).length<3&&(c=Rb(d,'[^:]*[:](.*)',Op))}else if(!!b&&(c.length>150||c.length<15)){c=(g=b.getElementsByTagName(Rp),g.length==1?g[0].textContent:null);c==null&&(c=d)}c=(h=new So('^\\s+|\\s+$'),j=new Oo(h.c,h.b,c),No(j,Kp));Dk(c,Pp,0).length<=4&&(c=d);return c}
+function Vg(a){Rg();var b;if(a==null){this.b=null}else{a=Ak(a,160,32);a=Bk(a,tq,Kp);a=Gk(a).toLowerCase();if(a.length==0){this.b=null}else{this.b=new Sn;Qn(this.b,a);b=Tg(a,'[ ]*[\\|\xBB|-][ ]*');b!=null&&Qn(this.b,b);b=Tg(a,'[ ]*[\\|\xBB|:][ ]*');b!=null&&Qn(this.b,b);b=Tg(a,'[ ]*[\\|\xBB|:\\(\\)][ ]*');b!=null&&Qn(this.b,b);b=Tg(a,'[ ]*[\\|\xBB|:\\(\\)\\-][ ]*');b!=null&&Qn(this.b,b);b=Tg(a,'[ ]*[\\|\xBB|,|:\\(\\)\\-][ ]*');b!=null&&Qn(this.b,b);b=Tg(a,'[ ]*[\\|\xBB|,|:\\(\\)\\-\xA0][ ]*');b!=null&&Qn(this.b,b);Sg(this.b,a,'[ ]+[\\|][ ]+');Sg(this.b,a,'[ ]+[\\-][ ]+');Qn(this.b,Ck(a,' - [^\\-]+$',Kp));Qn(this.b,Ck(a,'^[^\\-]+ - ',Kp))}}}
+function Ng(a,b){var c,d,e,f,g,h,j,l,m,n,o;n=b.b;if(n.c<2){return false}d=false;if(a.b){j=null;g=0;for(m=new mm(n);m.c<m.e.M();){l=Kd(km(m),8);++g;if(l.c){j=l;break}}if(!j){return false}}else{j=(bm(0,n.c),Kd(n.b[0],8));g=1}for(f=new sm(n,g);f.c<f.e.M();){c=Kd(km(f),8);if(!c.c){j=c;continue}e=c.p-j.o-1;if(e<=a.c){h=true;a.b&&(!j.c||!c.c)&&(h=false);h&&a.d&&j.q!=c.q&&(h=false);if(h){Md(j.r,22)||(j.r=new il(j.r));o=Kd(j.r,22);o.b.b+=gq;cl(o,c.r);j.i+=c.i;j.j+=c.j;j.k+=c.k;j.n+=c.n;j.p=ik(j.p,c.p);j.o=hk(j.o,c.o);rg(j);j.c=j.c|c.c;!j.b&&(j.b=new Sn);ql(j.b,c.b);j.f+=c.f;!!c.d&&(!j.d?(j.d=new Un(c.d)):j.d.R(c.d));j.q=ik(j.q,c.q);lm(f);d=true}else{j=c}}else{j=c}}return d}
+function L(){var o,q,r,s;J();var a,b,c,d,e,f,g,h,j,l,m,n;g=new wh;f=$doc.documentElement;n=(cb(),o=new fb(g),jb(new kb(o),f),o.c);th(g);e=(th(g),new xg(g.w,g.t));true|Gg(e)|Ug(new Vg(e.c),e)|Fg(e)|Cg((Bg(),Ag),e)|ch(e)|Ng((Mg(),Kg),e)|gh((fh(),eh),e)|Ng(Lg,e)|$g((Zg(),Yg),e)|Wg(e)|ah(e)|bh(e);d=new kn;for(m=new mm(e.b);m.c<m.e.M();){l=Kd(km(m),8);!!l.d&&Rn(l.d,Jp)||en(d,l.b)}q=xd(d.b,0,d.c);Cn(q,0,q.length);Nn(d,q);c=new ln(d.c);for(j=new mm(d);j.c<j.e.M();){h=Kd(km(j),18);dn(c,Ld(fn(n,h.b-1)))}b=Mb(c,$doc.documentElement);a=ub((r=new pb(b),s=lb((bm(0,b.c),Ld(b.b[0]))),jb(new kb(r),s),mb(r.d,(bm(0,b.c),Ld(b.b[0])))));if(a.nodeType!=1){return Kp}M(a);return a.innerHTML}
+function Gg(a){var b,c,d,e,f,g,h;b=false;for(f=new mm(a.b);f.c<f.e.M();){e=Kd(km(f),8);d=e.i;if(d<15){g=Gk(e.r.tS());c=g.length;if(c>=8){h=g.toLowerCase();if(h.indexOf('comments')==0||Ig(h,c,Bd(Tf,wp,1,[' comments',' users responded in']))||h.indexOf('\xA9 reuters')==0||h.indexOf('please rate this')==0||h.indexOf('post a comment')==0||h.indexOf('what you think...')!=-1||h.indexOf('add your comment')!=-1||h.indexOf('add comment')!=-1||h.indexOf('reader views')!=-1||h.indexOf('have your say')!=-1||h.indexOf('reader comments')!=-1||h.indexOf('r\xE4tta artikeln')!=-1||uk(h,'thanks for your comments - this feedback is now closed')){!e.d&&(e.d=new Tn);Qn(e.d,qq);b=true}}else e.e==1&&uk(g,'Comment')&&(!e.d&&(e.d=new Tn),Qn(e.d,qq))}}return b}
+function Yi(){wi(this);Vi(this,'STYLE',(Dh(),Ah));Vi(this,'SCRIPT',Ah);Vi(this,'OPTION',Ah);Vi(this,'OBJECT',Ah);Vi(this,'EMBED',Ah);Vi(this,'APPLET',Ah);Vi(this,'LINK',Ah);Vi(this,Lp,yh);Vi(this,'BODY',zh);Vi(this,'STRIKE',Bh);Vi(this,'U',Bh);Vi(this,'B',Bh);Vi(this,'I',Bh);Vi(this,'EM',Bh);Vi(this,'STRONG',Bh);Vi(this,'SPAN',Bh);Vi(this,'SUP',Bh);Vi(this,'CODE',Bh);Vi(this,'TT',Bh);Vi(this,'SUB',Bh);Vi(this,'VAR',Bh);Vi(this,'ABBR',Ch);Vi(this,'ACRONYM',Ch);Vi(this,'FONT',Bh);Vi(this,'NOSCRIPT',Ah);Vi(this,'LI',new di(new jh(Bd(Tf,wp,1,[wq]))));Vi(this,Rp,new di(new jh(Bd(Tf,wp,1,['de.l3s.boilerpipe/H1',xq]))));Vi(this,'H2',new di(new jh(Bd(Tf,wp,1,['de.l3s.boilerpipe/H2',xq]))));Vi(this,'H3',new di(new jh(Bd(Tf,wp,1,['de.l3s.boilerpipe/H3',xq]))))}
+function kg(){var a,b,c;b=$doc.compatMode;a=Bd(Tf,wp,1,[nq]);for(c=0;c<a.length;++c){if(uk(a[c],b)){return}}a.length==1&&uk(nq,a[0])&&uk('BackCompat',b)?"GWT no longer supports Quirks Mode (document.compatMode=' BackCompat').<br>Make sure your application's host HTML page has a Standards Mode (document.compatMode=' CSS1Compat') doctype,<br>e.g. by using &lt;!doctype html&gt; at the start of your application's HTML page.<br><br>To continue using this unsupported rendering mode and risk layout problems, suppress this message by adding<br>the following line to your*.gwt.xml module file:<br>&nbsp;&nbsp;&lt;extend-configuration-property name=\"document.compatMode\" value=\""+b+'"/&gt;':"Your *.gwt.xml module configuration prohibits the use of the current doucment rendering mode (document.compatMode=' "+b+"').<br>Modify your application's host HTML page doctype, or update your custom 'document.compatMode' configuration property settings."}
+function Cb(b,c){var d,e,f,g,h,j,l,m,n,o,q,r,s,t,u,v,w,x,y,z,A,B,C;e=Bb();B=Rb($wnd.location.href,Wp,Kp);d=b.getElementsByTagName(Lp);y=new Ri;for(f=0;f<d.length;++f){h=d[f];l=Rb(Rb(h.href,'#.*$',Kp),Wp,Kp);if(!l.length||!Vb(l,'^https?://')||vk(l,B)||c==0&&vk(l,e)){continue}A=Dk(l,'\\/+',0);if(A.length<3||!vk($wnd.location.host,A[1])){continue}o=h.textContent;if(Vb(o,Xp)||o.length>25){continue}if(c==0){m=Rb(l,e,Kp);if(!Vb(m,'\\d'))continue}n=null;if(l==null?y.d:l!=null?Yp+l in y.f:Ei(y,null,~~Wk(null))){n=Kd(l==null?y.c:l!=null?y.f[Yp+l]:Ci(y,null,~~Wk(null)),6);n.c+=' | '+o}else{n=new Fb(o,l);l==null?Ii(y,n):l!=null?Ji(y,l,n):Hi(y,null,n,~~Wk(null))}l.indexOf(e)!=0&&(n.d-=25);j=o+Zp+h.className+Zp+h.id;Vb(j,c==0?$p:_p)&&(n.d+=50);Vb(j,aq)&&(n.d+=25);Vb(j,'(first|last)')&&(c==0&&!Vb(n.c,$p)||c==1&&!Vb(n.c,_p))&&(n.d-=65);(Vb(j,bq)||Vb(j,Xp))&&(n.d-=50);Vb(j,c==0?_p:$p)&&(n.d-=200);w=false;r=false;u=td(h);while(!!u&&(!w||!r)){v=u.className+Zp+u.id;if(!w&&Vb(v,aq)){n.d+=25;w=true}if(!r&&Vb(v,bq)){if(!Vb(v,'article|body|content|entry|hentry|main|page|pagination|post|text|blog|story')){n.d-=25;r=true}}u=td(u)}(Vb(l,'p(a|g|ag)?(e|ing|ination)?(=|\\/)[0-9]{1,2}')||Vb(l,'(page|paging)'))&&(n.d+=25);Vb(l,Xp)&&(n.d-=15);q=0;try{q=Kj(o)}catch(a){a=Vf(a);if(!Md(a,20))throw a}q>0&&(q==1?(n.d-=10):(n.d+=0>10-q?0:10-q))}z=null;if(y.e!=0){x=(C=new Dl(y),new Mm(y,C));g=Lm(x);while(jm(g.b.b)){t=Kd(Rm(g),6);t.d>=50&&(!z||z.d<t.d)&&(z=t)}}if(z){s=Rb(z.b,Wp,Kp);return s}return null}
+function nh(){nh=sp;mh=new Ro('[0-9A-Za-z\xAA\xB2-\xB3\xB5\xB9-\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u0236\u0250-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EE\u037A\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03CE\u03D0-\u03F5\u03F7-\u03FB\u0400-\u0481\u048A-\u04CE\u04D0-\u04F5\u04F8-\u04F9\u0500-\u050F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0621-\u063A\u0640-\u064A\u0660-\u0669\u066E-\u066F\u0671-\u06D3\u06D5\u06E5-\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u074F\u0780-\u07A5\u07B1\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0985-\u098C\u098F-\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09DC-\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u0A05-\u0A0A\u0A0F-\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32-\u0A33\u0A35-\u0A36\u0A38-\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2-\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0-\u0AE1\u0AE6-\u0AEF\u0B05-\u0B0C\u0B0F-\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32-\u0B33\u0B35-\u0B39\u0B3D\u0B5C-\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99-\u0B9A\u0B9C\u0B9E-\u0B9F\u0BA3-\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB5\u0BB7-\u0BB9\u0BE7-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C60-\u0C61\u0C66-\u0C6F\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0-\u0CE1\u0CE6-\u0CEF\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D28\u0D2A-\u0D39\u0D60-\u0D61\u0D66-\u0D6F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32-\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81-\u0E82\u0E84\u0E87-\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA-\u0EAB\u0EAD-\u0EB0\u0EB2-\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDD\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6A\u0F88-\u0F8B\u1000-\u1021\u1023-\u1027\u1029-\u102A\u1040-\u1049\u1050-\u1055\u10A0-\u10C5\u10D0-\u10F8\u1100-\u1159\u115F-\u11A2\u11A8-\u11F9\u1200-\u1206\u1208-\u1246\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1286\u1288\u128A-\u128D\u1290-\u12AE\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12CE\u12D0-\u12D6\u12D8-\u12EE\u12F0-\u130E\u1310\u1312-\u1315\u1318-\u131E\u1320-\u1346\u1348-\u135A\u1369-\u137C\u13A0-\u13F4\u1401-\u166C\u166F-\u1676\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F0\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1877\u1880-\u18A8\u1900-\u191C\u1946-\u196D\u1970-\u1974\u1D00-\u1D6B\u1E00-\u1E9B\u1EA0-\u1EF9\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070-\u2071\u2074-\u2079\u207F-\u2089\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2131\u2133-\u2139\u213D-\u213F\u2145-\u2149\u2153-\u2183\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312C\u3131-\u318E\u3192-\u3195\u31A0-\u31B7\u31F0-\u31FF\u3220-\u3229\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DB5\u4E00-\u9FA5\uA000-\uA48C\uAC00-\uD7A3\uF900-\uFA2D\uFA30-\uFA6A\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40-\uFB41\uFB43-\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]')}
+var Kp='',gq='\n',Zp=' ',Gq='"',Op='$1',Aq='$\uE00A<',tq="'",eq='(',$p='(next|weiter|continue|>([^\\|]|$)|\xBB([^\\|]|$))',_p='(prev|early|old|new|<|\xAB)',lq=')',Cq=', ',Up='.',rq='.com',Tp='/',Yp=':',Qp=': ',Dq='=',Bq='>\uE00A$',Hp='@',hq='@@',Lp='A',nq='CSS1Compat',Ip='DomDistiller',Fq='For input string: "',Rp='H1',Mp='IMG',dq='String',Np='TITLE',iq='Unknown',jq='[',sq='[\b ]+',Vp='[.]',Mq='[Ljava.lang.',Jq='[object Array]',Wp='\\/$',Pp='\\s+',kq=']',fq='anonymous',Sq='com.dom_distiller.client.',Lq='com.google.gwt.core.client.',Nq='com.google.gwt.core.client.impl.',Qq='com.google.gwt.logging.impl.',bq='combx|comment|com-|contact|foot|footer|footnote|masthead|media|meta|outbrain|promo|related|scroll|shoutbox|sidebar|sponsor|shopping|tags|tool|widget',Uq='de.l3s.boilerpipe.document.',Xq='de.l3s.boilerpipe.filters.english.',Wq='de.l3s.boilerpipe.filters.heuristics.',Tq='de.l3s.boilerpipe.sax.',xq='de.l3s.boilerpipe/HEADING',qq='de.l3s.boilerpipe/INDICATES_END_OF_TEXT',wq='de.l3s.boilerpipe/LI',uq='de.l3s.boilerpipe/MIGHT_BE_CONTENT',Jp='de.l3s.boilerpipe/TITLE',vq='de.l3s.boilerpipe/VERY_LIKELY_CONTENT',Iq='fromIndex: ',Hq='g',Kq='java.lang.',Rq='java.util.',Oq='java.util.logging.',Vq='java.util.regex.',pq='msie',cq='null',Eq='number',Sp='object',oq='opera',Pq='org.timepedia.exporter.client.',Yq='org.xml.sax.',aq='pag(e|ing|inat)',Xp='print|archive|comment|discuss|e[\\-]?mail|share|reply|all|login|sign|single',mq='safari',yq='{',zq='}';var _,Xf={},xp={11:1,23:1},Bp={11:1,26:1},Ap={26:1},Dp={27:1},Cp={29:1},yp={30:1},Fp={11:1,25:1},Ep={25:1},vp={},zp={10:1},wp={11:1};Yf(1,-1,vp);_.eQ=function F(a){return this===a};_.gC=function G(){return this.cZ};_.hC=function H(){return yc(this)};_.tS=function I(){return this.cZ.e+Hp+ck(this.hC())};_.toString=function(){return this.tS()};_.tM=sp;Yf(3,1,{2:1,31:1},K);Yf(4,1,{},R);_.y=function S(a){return a!=null&&Md(a,2)};var O=false;Yf(5,1,{3:1,31:1},U);Yf(6,1,{},$);_.y=function ab(a){return a!=null&&Md(a,3)};var X=false;Yf(9,1,{},fb);_.z=function gb(a){var b;b=a;sh(this.b,b.tagName,b.tagName)};_.A=function hb(a){var b,c,d,e,f;switch(a.nodeType){case 3:dn(this.c,a);d=a.data;rh(this.b,(e=d.length,f=Ad(Of,wp,-1,e,1),wk(d,e,f,0),f),0,d.length);return false;case 1:c=a;b=db(c);vh(this.b,c.tagName,c.tagName,b);return true;case 9:default:return false;}};_.b=null;_.c=null;Yf(10,1,{},kb);_.b=null;Yf(12,1,{},pb);_.z=function qb(a){hn(this.b,this.b.c-1);hn(this.e,this.e.c-1)};_.A=function rb(a){if(!this.c.b)return false;dn(this.b,a);dn(this.e,null);if(this.e.c==1){this.d=new vb(a);jn(this.e,0,this.d)}xb(this.c,a)&&ob(this);return true};_.b=null;_.c=null;_.d=null;_.e=null;Yf(13,1,{4:1},vb);_.b=null;_.c=null;Yf(14,1,{},yb);_.b=null;_.c=null;Yf(15,1,{5:1,31:1},Ab);Yf(16,1,{6:1},Fb);_.b=null;_.c=null;_.d=0;Yf(17,1,{},Kb);_.y=function Lb(a){return a!=null&&Md(a,5)};var Hb=false;Yf(19,1,{},Ob);_.z=function Pb(a){};_.A=function Qb(a){if(!this.d.b&&!this.c){return false}if(xb(this.d,a)){this.c=true;dn(this.b,a)}else a.nodeType==3&&!Sb(a.nodeValue)&&(this.c=false);switch(a.nodeType){case 3:return true;case 1:this.c&&a.nodeType==1&&uk(Mp,a.tagName)&&dn(this.b,a);return true;case 9:default:return false;}};_.b=null;_.c=false;_.d=null;Yf(26,1,xp);_.B=function _b(){return this.f};_.tS=function ac(){var a,b;a=this.cZ.e;b=this.B();return b!=null?a+Qp+b:a};_.f=null;Yf(25,26,xp);Yf(24,25,xp,cc);Yf(23,24,xp,dc);_.B=function jc(){this.d==null&&(this.e=gc(this.c),this.b=this.b+Qp+ec(this.c),this.d=eq+this.e+') '+ic(this.c)+this.b,undefined);return this.d};_.b=Kp;_.c=null;_.d=null;_.e=null;Yf(30,1,{});var pc=0,qc=0,rc=0,sc=-1;Yf(32,30,{},Gc);_.b=null;_.c=null;var Cc;Yf(35,1,{},Qc);_.C=function Rc(){var a={};var b=[];var c=arguments.callee.caller.caller;while(c){var d=this.D(c.toString());b.push(d);var e=Yp+d;var f=a[e];if(f){var g,h;for(g=0,h=f.length;g<h;g++){if(f[g]===c){return b}}}(f||(a[e]=[])).push(c);c=c.caller}return b};_.D=function Sc(a){return Jc(a)};_.E=function Tc(a){return []};Yf(37,35,{});_.C=function Xc(){return Mc(this.E(Pc()),this.F())};_.E=function Yc(a){return Wc(this,a)};_.F=function Zc(){return 2};Yf(36,37,{});_.C=function ed(){return _c(this)};_.D=function fd(a){var b,c,d,e;if(a.length==0){return fq}e=Gk(a);e.indexOf('at ')==0&&(e=Ek(e,3));c=e.indexOf(jq);c!=-1&&(e=Gk(e.substr(0,c-0))+Gk(Ek(e,e.indexOf(kq,c)+1)));c=e.indexOf(eq);if(c==-1){c=e.indexOf(Hp);if(c==-1){d=e;e=Kp}else{d=Gk(Ek(e,c+1));e=Gk(e.substr(0,c-0))}}else{b=e.indexOf(lq,c);d=e.substr(c+1,b-(c+1));e=Gk(e.substr(0,c-0))}c=xk(e,Ok(46));c!=-1&&(e=Ek(e,c+1));return (e.length>0?e:fq)+hq+d};_.E=function gd(a){return cd(this,a)};_.F=function hd(){return 3};Yf(38,36,{},jd);Yf(39,1,{});Yf(40,39,{},qd);_.b=Kp;Yf(49,1,{},vd);_.qI=0;var Dd,Ed;Yf(58,1,{},cg);_.b=null;Yf(60,1,yp,gg);_.b=null;Yf(59,60,yp,hg);Yf(67,1,{8:1},ug);_.tS=function vg(){return jq+this.p+'-'+this.o+';tl='+this.q+'; nw='+this.i+';nwl='+this.n+';ld='+this.e+']\t'+(this.c?'CONTENT':'boilerplate')+','+this.d+gq+this.r.tS()};_.b=null;_.c=false;_.d=null;_.e=0;_.f=0;_.i=0;_.j=0;_.k=0;_.n=0;_.o=0;_.p=0;_.q=0;_.r=null;_.s=0;var ng,og;Yf(68,1,{},xg);_.b=null;_.c=null;Yf(69,1,{});Yf(70,69,{},Dg);_.b=0;var Ag;Yf(73,1,{},Og);_.b=false;_.c=0;_.d=false;var Kg,Lg;Yf(74,1,{},Vg);_.b=null;var Qg;Yf(76,1,{},_g);_.b=false;_.c=0;var Yg;Yf(80,1,{},hh);_.b=null;var eh;Yf(81,1,{9:1},jh);_.tS=function kh(){return xe.e+Hp+ck(yc(this))+yq+new Gn(this.b)+zq};_.b=null;Yf(82,1,{},wh);_.b=-1;_.d=false;_.f=0;_.i=false;_.j=0;_.k=0;_.o=null;_.p=0;_.q=false;_.r=null;_.s=0;_.v=0;_.w=null;var mh;var yh,zh,Ah,Bh,Ch;Yf(84,1,zp,Fh);_.G=function Gh(){return true};_.H=function Hh(a,b,c){--a.k;return true};_.I=function Ih(a,b,c,d){++a.k;return true};Yf(85,1,zp,Lh);_.G=function Mh(){return true};_.H=function Nh(a,b,c){return Kh(a)};_.I=function Oh(a,b,c,d){a.f++>0&&Kh(a);if(a.k==0){qh(a);dl(a.x,Aq);bl(a.x,32);a.q=true}return false};Yf(86,1,zp,Qh);_.G=function Rh(){return true};_.H=function Sh(a,b,c){th(a);--a.j;return false};_.I=function Th(a,b,c,d){th(a);++a.j;return false};Yf(87,1,zp,Vh);_.G=function Wh(){return false};_.H=function Xh(a,b,c){qh(a);return false};_.I=function Yh(a,b,c,d){qh(a);return false};Yf(88,1,zp,$h);_.G=function _h(){return false};_.H=function ai(a,b,c){return false};_.I=function bi(a,b,c,d){return false};Yf(89,1,zp,di);_.G=function ei(){return true};_.H=function fi(a,b,c){return true};_.I=function gi(a,b,c,d){oh(a,this.b);return true};_.b=null;Yf(94,1,Ap);_.J=function oi(a){return !!mi(this,a)};_.eQ=function pi(a){var b,c,d,e,f;if(a===this){return true}if(!Md(a,26)){return false}e=Kd(a,26);if(this.M()!=e.M()){return false}for(c=new Il(e.K().b);jm(c.b);){b=Kd(km(c.b),27);d=b.Y();f=b.Z();if(!this.J(d)){return false}if(!Bo(f,this.L(d))){return false}}return true};_.L=function qi(a){var b;b=mi(this,a);return !b?null:b.Z()};_.hC=function ri(){var a,b,c;c=0;for(b=new Il(this.K().b);jm(b.b);){a=Kd(km(b.b),27);c+=a.hC();c=~~c}return c};_.M=function si(){return this.K().b.e};_.tS=function ti(){var a,b,c,d;d=yq;a=false;for(c=new Il(this.K().b);jm(c.b);){b=Kd(km(c.b),27);a?(d+=Cq):(a=true);d+=Kp+b.Y();d+=Dq;d+=Kp+b.Z()}return d+zq};Yf(93,94,Ap);_.J=function Li(a){return yi(this,a)};_.K=function Mi(){return new Dl(this)};_.O=function Ni(a,b){return this.N(a,b)};_.L=function Oi(a){return Bi(this,a)};_.M=function Pi(){return this.e};_.b=null;_.c=null;_.d=false;_.e=0;_.f=null;Yf(92,93,Bp,Ri,Si);_.N=function Ti(a,b){return Qi(a,b)};_.P=function Ui(a){return ~~nc(a)};Yf(91,92,Bp);Yf(90,91,Bp,Yi);var Wi;var Zi;Yf(96,24,xp,bj);Yf(97,1,{11:1,12:1,16:1},hj);_.cT=function ij(a){return gj(this,Kd(a,12))};_.eQ=function jj(a){return Md(a,12)&&Kd(a,12).b==this.b};_.hC=function kj(){return this.b?1231:1237};_.tS=function lj(){return this.b?'true':'false'};_.b=false;var dj,ej;Yf(98,1,{11:1,14:1,16:1},oj);_.cT=function pj(a){return nj(this,Kd(a,14))};_.eQ=function rj(a){return Md(a,14)&&Kd(a,14).b==this.b};_.hC=function sj(){return this.b};_.tS=function tj(){return Qk(this.b)};_.b=0;var vj;Yf(100,1,{15:1},yj);_.tS=function Fj(){return ((this.b&2)!=0?'interface ':(this.b&1)!=0?Kp:'class ')+this.e};_.b=0;_.c=0;_.d=null;_.e=null;Yf(101,24,xp,Hj);Yf(103,1,{11:1,19:1});Yf(102,103,{11:1,16:1,17:1,19:1},Mj);_.cT=function Oj(a){return Lj(this,Kd(a,17))};_.eQ=function Pj(a){return Md(a,17)&&Kd(a,17).b==this.b};_.hC=function Qj(){return Qd(this.b)};_.tS=function Rj(){return Kp+this.b};_.b=0;Yf(104,24,xp,Tj);Yf(105,24,xp,Vj);Yf(106,24,xp,Xj);Yf(107,103,{11:1,16:1,18:1,19:1},$j);_.cT=function _j(a){return Zj(this,Kd(a,18))};_.eQ=function ak(a){return Md(a,18)&&Kd(a,18).b==this.b};_.hC=function bk(){return this.b};_.tS=function dk(){return Kp+this.b};_.b=0;var fk;Yf(110,24,xp,kk);var lk;Yf(112,104,{11:1,20:1,23:1},ok);Yf(113,1,{11:1,21:1},qk);_.tS=function rk(){return this.b+Up+this.e+eq+(this.c!=null?this.c:'Unknown Source')+(this.d>=0?Yp+this.d:Kp)+lq};_.b=null;_.c=null;_.d=0;_.e=null;_=String.prototype;_.cM={1:1,11:1,13:1,16:1};_.cT=function Lk(a){return Mk(this,Kd(a,1))};_.eQ=function Nk(a){return uk(this,a)};_.hC=function Pk(){return Wk(this)};_.tS=_.toString;var Rk,Sk=0,Tk;Yf(115,1,{13:1},Zk);_.tS=function $k(){return this.b.b};Yf(116,1,{13:1,22:1},hl,il);_.tS=function kl(){return this.b.b};Yf(117,106,xp,ml);Yf(118,24,xp,ol);Yf(119,1,{});_.Q=function tl(a){throw new ol('Add not supported on this collection')};_.R=function ul(a){return ql(this,a)};_.S=function vl(a){var b;b=rl(this.T(),a);return !!b};_.U=function wl(){return this.V(Ad(Rf,wp,0,this.M(),0))};_.V=function xl(a){var b,c,d;d=this.M();a.length<d&&(a=yd(a,d));c=this.T();for(b=0;b<d;++b){Cd(a,b,c.X())}a.length>d&&Cd(a,d,null);return a};_.tS=function yl(){return sl(this)};Yf(121,119,Cp);_.eQ=function Bl(a){var b,c,d;if(a===this){return true}if(!Md(a,29)){return false}c=Kd(a,29);if(c.M()!=this.M()){return false}for(b=c.T();b.W();){d=b.X();if(!this.S(d)){return false}}return true};_.hC=function Cl(){var a,b,c;a=0;for(b=this.T();b.W();){c=b.X();if(c!=null){a+=nc(c);a=~~a}}return a};Yf(120,121,Cp,Dl);_.S=function El(a){var b,c,d;if(Md(a,27)){b=Kd(a,27);c=b.Y();if(yi(this.b,c)){d=Bi(this.b,c);return this.b.N(b.Z(),d)}}return false};_.T=function Fl(){return new Il(this.b)};_.M=function Gl(){return this.b.e};_.b=null;Yf(122,1,{},Il);_.W=function Jl(){return jm(this.b)};_.X=function Kl(){return Kd(km(this.b),27)};_.b=null;Yf(124,1,Dp);_.eQ=function Nl(a){var b;if(Md(a,27)){b=Kd(a,27);if(Bo(this.Y(),b.Y())&&Bo(this.Z(),b.Z())){return true}}return false};_.hC=function Ol(){var a,b;a=0;b=0;this.Y()!=null&&(a=nc(this.Y()));this.Z()!=null&&(b=nc(this.Z()));return a^b};_.tS=function Pl(){return this.Y()+Dq+this.Z()};Yf(123,124,Dp,Ql);_.Y=function Rl(){return null};_.Z=function Sl(){return this.b.c};_.$=function Tl(a){return Ii(this.b,a)};_.b=null;Yf(125,124,Dp,Vl);_.Y=function Wl(){return this.b};_.Z=function Xl(){return Di(this.c,this.b)};_.$=function Yl(a){return Ji(this.c,this.b,a)};_.b=null;_.c=null;Yf(126,119,Ep);_._=function _l(a,b){throw new ol('Add not supported on this list')};_.Q=function am(a){this._(this.M(),a);return true};_.eQ=function cm(a){var b,c,d,e,f;if(a===this){return true}if(!Md(a,25)){return false}f=Kd(a,25);if(this.M()!=f.M()){return false}d=this.T();e=f.T();while(d.W()){b=d.X();c=e.X();if(!(b==null?c==null:lc(b,c))){return false}}return true};_.hC=function dm(){var a,b,c;b=1;a=this.T();while(a.W()){c=a.X();b=31*b+(c==null?0:nc(c));b=~~b}return b};_.T=function fm(){return new mm(this)};_.bb=function gm(a){throw new ol('Remove not supported on this list')};_.cb=function hm(a,b){throw new ol('Set not supported on this list')};Yf(127,1,{},mm);_.W=function nm(){return jm(this)};_.X=function om(){return km(this)};_.c=0;_.d=-1;_.e=null;Yf(128,127,{},sm);_.b=null;Yf(129,126,Ep,um);_._=function vm(a,b){bm(a,this.c+1);++this.c;cn(this.d,this.b+a,b)};_.ab=function wm(a){bm(a,this.c);return fn(this.d,this.b+a)};_.bb=function xm(a){var b;bm(a,this.c);b=hn(this.d,this.b+a);--this.c;return b};_.cb=function ym(a,b){bm(a,this.c);return jn(this.d,this.b+a,b)};_.M=function zm(){return this.c};_.b=0;_.c=0;_.d=null;Yf(130,121,Cp,Cm);_.S=function Dm(a){return yi(this.b,a)};_.T=function Em(){return Bm(this)};_.M=function Fm(){return this.c.b.e};_.b=null;_.c=null;Yf(131,1,{},Hm);_.W=function Im(){return jm(this.b.b)};_.X=function Jm(){var a;a=Kd(km(this.b.b),27);return a.Y()};_.b=null;Yf(132,119,{},Mm);_.S=function Nm(a){return Ai(this.b,a)};_.T=function Om(){return Lm(this)};_.M=function Pm(){return this.c.b.e};_.b=null;_.c=null;Yf(133,1,{},Sm);_.W=function Tm(){return jm(this.b.b)};_.X=function Um(){return Rm(this)};_.b=null;Yf(134,126,Ep);_._=function Xm(a,b){var c;c=eo(this,a);ao(c.e,b,c.c);++c.b;c.d=null};_.ab=function Ym(a){return Wm(this,a)};_.T=function Zm(){return eo(this,0)};_.bb=function $m(b){var c,d;c=eo(this,b);try{d=lo(c)}catch(a){a=Vf(a);if(Md(a,28)){throw new Xj("Can't remove element "+b)}else throw a}mo(c);c.c==c.d?(c.c=c.d.b):--c.b;ro(c.d);c.d=null;--c.e.c;return d};_.cb=function _m(b,c){var d,e;d=eo(this,b);try{e=lo(d);mo(d);d.d.d=c;return e}catch(a){a=Vf(a);if(Md(a,28)){throw new Xj("Can't set element "+b)}else throw a}};Yf(135,126,Fp,kn,ln);_._=function mn(a,b){cn(this,a,b)};_.Q=function nn(a){return dn(this,a)};_.R=function on(a){return en(this,a)};_.S=function pn(a){return gn(this,a,0)!=-1};_.ab=function qn(a){return fn(this,a)};_.bb=function rn(a){return hn(this,a)};_.cb=function sn(a,b){return jn(this,a,b)};_.M=function un(){return this.c};_.U=function yn(){return xd(this.b,0,this.c)};_.V=function zn(a){var b;a.length<this.c&&(a=yd(a,this.c));for(b=0;b<this.c;++b){Cd(a,b,this.b[b])}a.length>this.c&&Cd(a,this.c,null);return a};_.c=0;Yf(137,126,Fp,Gn);_.S=function Hn(a){return $l(this,a)!=-1};_.ab=function In(a){return bm(a,this.b.length),this.b[a]};_.cb=function Jn(a,b){return Fn(this,a,b)};_.M=function Kn(){return this.b.length};_.U=function Ln(){return wd(this.b)};_.V=function Mn(a){var b,c;c=this.b.length;a.length<c&&(a=yd(a,c));for(b=0;b<c;++b){Cd(a,b,this.b[b])}a.length>c&&Cd(a,c,null);return a};_.b=null;Yf(140,121,{11:1,29:1},Sn,Tn,Un);_.Q=function Vn(a){return Qn(this,a)};_.S=function Wn(a){return yi(this.b,a)};_.T=function Xn(){return Bm(ni(this.b))};_.M=function Yn(){return this.b.e};_.tS=function Zn(){return sl(ni(this.b))};_.b=null;Yf(141,134,{11:1,24:1,25:1},ho);_.Q=function io(a){return _n(this,a)};_.M=function jo(){return this.c};_.b=null;_.c=0;Yf(142,1,{},no);_.W=function oo(){return this.c!=this.e.b};_.X=function po(){return lo(this)};_.b=0;_.c=null;_.d=null;_.e=null;Yf(143,1,{},so,to);_.b=null;_.c=null;_.d=null;Yf(144,124,Dp,vo);_.Y=function wo(){return this.b};_.Z=function xo(){return this.c};_.$=function yo(a){var b;b=this.c;this.c=a;return b};_.b=null;_.c=null;Yf(145,24,{11:1,23:1,28:1},Ao);Yf(147,1,{},Io);_.b=null;_.c=null;var Do=null;Yf(148,60,yp,Ko);Yf(149,1,{},Oo);_.b=null;_.c=null;_.d=null;Yf(150,1,{},Ro,So);_.b=null;_.c=null;Yf(152,1,{});Yf(151,152,{},bp);var hp;Yf(158,1,{},pp);_.b=null;_.c=null;Yf(159,1,{},rp);var Gp=vc;
+
+var Ve=Aj(Kq,'Object',1,null),de=Aj(Lq,'JavaScriptObject$',27,Ve),Rf=zj(Mq,'Object;',163),af=Aj(Kq,'Throwable',26,Ve),Ne=Aj(Kq,'Exception',25,af),We=Aj(Kq,'RuntimeException',24,Ne),Xe=Aj(Kq,'StackTraceElement',113,Ve),Sf=zj(Mq,'StackTraceElement;',166),me=Aj('com.google.gwt.lang.','SeedUtil',55,Ve),Ie=Aj(Kq,'Boolean',97,Ve),Ue=Aj(Kq,'Number',103,Ve),Of=zj(Kp,'[C',167),Je=Aj(Kq,'Character',98,Ve),Pf=zj(Mq,'Character;',168),Le=Aj(Kq,'Class',100,Ve),Me=Aj(Kq,'Double',102,Ue),Re=Aj(Kq,'Integer',107,Ue),Qf=zj(Mq,'Integer;',169),_e=Aj(Kq,dq,2,Ve),Tf=zj(Mq,'String;',164),Ke=Aj(Kq,'ClassCastException',101,We),Ze=Aj(Kq,'StringBuilder',116,Ve),He=Aj(Kq,'ArrayStoreException',96,We),ce=Aj(Lq,'JavaScriptException',23,We),le=Aj(Nq,'StringBufferImpl',39,Ve),Gf=Aj(Oq,'Logger',60,Ve),Lf=Aj(Pq,'ExporterBaseImpl',152,Ve),Kf=Aj(Pq,'ExporterBaseActual',151,Lf),Jf=Bj(Pq,'Exportable'),je=Aj(Nq,'StackTraceCreator$Collector',35,Ve),ie=Aj(Nq,'StackTraceCreator$CollectorMoz',37,je),he=Aj(Nq,'StackTraceCreator$CollectorChrome',36,ie),ge=Aj(Nq,'StackTraceCreator$CollectorChromeNoSourceMap',38,he),ke=Aj(Nq,'StringBufferImplAppend',40,le),ee=Aj(Lq,'Scheduler',30,Ve),fe=Aj(Nq,'SchedulerImpl',32,ee),ne=Aj(Qq,'LoggerImplRegular',58,Ve),sf=Aj(Rq,'AbstractMap',94,Ve),hf=Aj(Rq,'AbstractHashMap',93,sf),cf=Aj(Rq,'AbstractCollection',119,Ve),uf=Aj(Rq,'AbstractSet',121,cf),ef=Aj(Rq,'AbstractHashMap$EntrySet',120,uf),df=Aj(Rq,'AbstractHashMap$EntrySetIterator',122,Ve),rf=Aj(Rq,'AbstractMapEntry',124,Ve),ff=Aj(Rq,'AbstractHashMap$MapEntryNull',123,rf),gf=Aj(Rq,'AbstractHashMap$MapEntryString',125,rf),of=Aj(Rq,'AbstractMap$1',130,uf),nf=Aj(Rq,'AbstractMap$1$1',131,Ve),qf=Aj(Rq,'AbstractMap$2',132,cf),pf=Aj(Rq,'AbstractMap$2$1',133,Ve),Se=Aj(Kq,'NullPointerException',110,We),Oe=Aj(Kq,'IllegalArgumentException',104,We),mf=Aj(Rq,'AbstractList',126,cf),vf=Aj(Rq,'ArrayList',135,mf),jf=Aj(Rq,'AbstractList$IteratorImpl',127,Ve),kf=Aj(Rq,'AbstractList$ListIteratorImpl',128,jf),lf=Aj(Rq,'AbstractList$SubList',129,mf),xf=Aj(Rq,'HashMap',92,hf),Ff=Aj(Oq,'LogManager',147,Ve),Ef=Aj(Oq,'LogManager$RootLogger',148,Gf),oe=Aj(Qq,'LoggerWithExposedConstructor',59,Gf),Rd=Aj(Sq,'ContentExtractor_ExporterImpl',4,Ve),Sd=Aj(Sq,'ContentExtractor',3,Ve),Td=Aj(Sq,'DocumentTitleGetter_ExporterImpl',6,Ve),Ud=Aj(Sq,'DocumentTitleGetter',5,Ve),_d=Aj(Sq,'PagingLinksFinder_ExporterImpl',17,Ve),ae=Aj(Sq,'PagingLinksFinder',15,Ve),Ye=Aj(Kq,'StringBuffer',115,Ve),Cf=Aj(Rq,'MapEntryImpl',144,rf),$d=Aj(Sq,'PagingLinksFinder$PagingLinkObj',16,Ve),bf=Aj(Kq,'UnsupportedOperationException',118,We),Df=Aj(Rq,'NoSuchElementException',145,We),Pe=Aj(Kq,'IllegalStateException',105,We),ye=Aj(Tq,'BoilerpipeHTMLContentHandler',82,Ve),qe=Aj(Uq,'TextDocument',68,Ve),pe=Aj(Uq,'TextBlock',67,Ve),Vd=Aj(Sq,'DomToSaxParser$DomToSaxVisitor',9,Ve),Wd=Aj(Sq,'DomWalker',10,Ve),yf=Aj(Rq,'HashSet',140,uf),be=Aj(Sq,'RelevantImageFinder$Visitor',19,Ve),Yd=Aj(Sq,'NodeTree',13,Ve),Xd=Aj(Sq,'NodeListExpander$Visitor',12,Ve),If=Aj(Vq,'Pattern',150,Ve),Hf=Aj(Vq,'Matcher',149,Ve),Te=Aj(Kq,'NumberFormatException',112,Oe),Ge=Aj(Tq,'TagActionMap',91,xf),Fe=Aj(Tq,'DefaultTagActionMap',90,Ge),ue=Aj(Wq,'DocumentTitleMatchClassifier',74,Ve),re=Aj(Xq,'HeuristicFilterBase',69,Ve),se=Aj(Xq,'IgnoreBlocksAfterContentFilter',70,re),te=Aj(Wq,'BlockProximityFusion',73,Ve),we=Aj('de.l3s.boilerpipe.filters.simple.','BoilerplateBlockFilter',80,Ve),ve=Aj(Wq,'KeepLargestBlockFilter',76,Ve),wf=Aj(Rq,'Arrays$ArrayList',137,mf),Qe=Aj(Kq,'IndexOutOfBoundsException',106,We),Zd=Aj(Sq,'OrderedNodeMatcher',14,Ve),Ee=Aj(Tq,'CommonTagActions$BlockTagLabelAction',89,Ve),ze=Aj(Tq,'CommonTagActions$1',84,Ve),Ae=Aj(Tq,'CommonTagActions$2',85,Ve),Be=Aj(Tq,'CommonTagActions$3',86,Ve),Ce=Aj(Tq,'CommonTagActions$4',87,Ve),De=Aj(Tq,'CommonTagActions$5',88,Ve),xe=Aj('de.l3s.boilerpipe.labels.','LabelAction',81,Ve),tf=Aj(Rq,'AbstractSequentialList',134,mf),Bf=Aj(Rq,'LinkedList',141,tf),zf=Aj(Rq,'LinkedList$ListIteratorImpl',142,Ve),Af=Aj(Rq,'LinkedList$Node',143,Ve),Nf=Aj(Yq,'AttributesImpl',158,Ve),Mf=Aj(Yq,'AttributesImpl$AttributeData',159,Ve),$e=Aj(Kq,'StringIndexOutOfBoundsException',117,Qe);$stats && $stats({moduleName:'domdistiller',sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalEnd'});if ($wnd.domdistiller) $wnd.domdistiller.onScriptLoad();
 gwtOnLoad(undefined,"domdistiller","",0);
diff --git a/third_party/expat/expat.target.darwin-x86_64.mk b/third_party/expat/expat.target.darwin-x86_64.mk
new file mode 100644
index 0000000..bbdfeb9
--- /dev/null
+++ b/third_party/expat/expat.target.darwin-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_expat_expat_gyp
+LOCAL_MODULE_STEM := expat
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_expat_expat_gyp
+
+# Alias gyp target name.
+.PHONY: expat
+expat: third_party_expat_expat_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/expat/expat.target.linux-x86_64.mk b/third_party/expat/expat.target.linux-x86_64.mk
new file mode 100644
index 0000000..bbdfeb9
--- /dev/null
+++ b/third_party/expat/expat.target.linux-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_expat_expat_gyp
+LOCAL_MODULE_STEM := expat
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_expat_expat_gyp
+
+# Alias gyp target name.
+.PHONY: expat
+expat: third_party_expat_expat_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-arm.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-arm.mk
index 5ebe569..d1ba690 100644
--- a/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-arm.mk
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-arm.mk
@@ -116,6 +116,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -209,6 +210,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-mips.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-mips.mk
index 052636d..8bc7078 100644
--- a/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-mips.mk
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-mips.mk
@@ -116,6 +116,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -209,6 +210,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86.mk
index cd9fb6b..679a769 100644
--- a/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86.mk
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86.mk
@@ -117,6 +117,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -210,6 +211,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86_64.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86_64.mk
new file mode 100644
index 0000000..eadddcd
--- /dev/null
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.darwin-x86_64.mk
@@ -0,0 +1,306 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_harfbuzz_ng_harfbuzz_ng_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/harfbuzz-ng/src/hb-blob.cc \
+	third_party/harfbuzz-ng/src/hb-buffer.cc \
+	third_party/harfbuzz-ng/src/hb-buffer-serialize.cc \
+	third_party/harfbuzz-ng/src/hb-common.cc \
+	third_party/harfbuzz-ng/src/hb-face.cc \
+	third_party/harfbuzz-ng/src/hb-fallback-shape.cc \
+	third_party/harfbuzz-ng/src/hb-font.cc \
+	third_party/harfbuzz-ng/src/hb-icu.cc \
+	third_party/harfbuzz-ng/src/hb-ot-layout.cc \
+	third_party/harfbuzz-ng/src/hb-ot-map.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc \
+	third_party/harfbuzz-ng/src/hb-ot-tag.cc \
+	third_party/harfbuzz-ng/src/hb-set.cc \
+	third_party/harfbuzz-ng/src/hb-shape.cc \
+	third_party/harfbuzz-ng/src/hb-shape-plan.cc \
+	third_party/harfbuzz-ng/src/hb-shaper.cc \
+	third_party/harfbuzz-ng/src/hb-unicode.cc \
+	third_party/harfbuzz-ng/src/hb-warning.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_OT' \
+	'-DHAVE_ICU' \
+	'-DHAVE_ICU_BUILTIN' \
+	'-DHB_NO_MT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/harfbuzz-ng/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_OT' \
+	'-DHAVE_ICU' \
+	'-DHAVE_ICU_BUILTIN' \
+	'-DHB_NO_MT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/harfbuzz-ng/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_harfbuzz_ng_harfbuzz_ng_gyp
+
+# Alias gyp target name.
+.PHONY: harfbuzz-ng
+harfbuzz-ng: third_party_harfbuzz_ng_harfbuzz_ng_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-arm.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-arm.mk
index 5ebe569..d1ba690 100644
--- a/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-arm.mk
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-arm.mk
@@ -116,6 +116,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -209,6 +210,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-mips.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-mips.mk
index 052636d..8bc7078 100644
--- a/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-mips.mk
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-mips.mk
@@ -116,6 +116,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -209,6 +210,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86.mk
index cd9fb6b..679a769 100644
--- a/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86.mk
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86.mk
@@ -117,6 +117,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -210,6 +211,7 @@
 	'-DHB_NO_MT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86_64.mk b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86_64.mk
new file mode 100644
index 0000000..eadddcd
--- /dev/null
+++ b/third_party/harfbuzz-ng/harfbuzz-ng.target.linux-x86_64.mk
@@ -0,0 +1,306 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_harfbuzz_ng_harfbuzz_ng_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/harfbuzz-ng/src/hb-blob.cc \
+	third_party/harfbuzz-ng/src/hb-buffer.cc \
+	third_party/harfbuzz-ng/src/hb-buffer-serialize.cc \
+	third_party/harfbuzz-ng/src/hb-common.cc \
+	third_party/harfbuzz-ng/src/hb-face.cc \
+	third_party/harfbuzz-ng/src/hb-fallback-shape.cc \
+	third_party/harfbuzz-ng/src/hb-font.cc \
+	third_party/harfbuzz-ng/src/hb-icu.cc \
+	third_party/harfbuzz-ng/src/hb-ot-layout.cc \
+	third_party/harfbuzz-ng/src/hb-ot-map.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-arabic.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-default.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-hangul.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-hebrew.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-indic-table.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-myanmar.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-sea.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-thai.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-complex-tibetan.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-fallback.cc \
+	third_party/harfbuzz-ng/src/hb-ot-shape-normalize.cc \
+	third_party/harfbuzz-ng/src/hb-ot-tag.cc \
+	third_party/harfbuzz-ng/src/hb-set.cc \
+	third_party/harfbuzz-ng/src/hb-shape.cc \
+	third_party/harfbuzz-ng/src/hb-shape-plan.cc \
+	third_party/harfbuzz-ng/src/hb-shaper.cc \
+	third_party/harfbuzz-ng/src/hb-unicode.cc \
+	third_party/harfbuzz-ng/src/hb-warning.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_OT' \
+	'-DHAVE_ICU' \
+	'-DHAVE_ICU_BUILTIN' \
+	'-DHB_NO_MT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/harfbuzz-ng/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_OT' \
+	'-DHAVE_ICU' \
+	'-DHAVE_ICU_BUILTIN' \
+	'-DHB_NO_MT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/harfbuzz-ng/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_harfbuzz_ng_harfbuzz_ng_gyp
+
+# Alias gyp target name.
+.PHONY: harfbuzz-ng
+harfbuzz-ng: third_party_harfbuzz_ng_harfbuzz_ng_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/harfbuzz-ng/harfbuzz.gyp b/third_party/harfbuzz-ng/harfbuzz.gyp
index ec2b12a..7bd7d1d 100644
--- a/third_party/harfbuzz-ng/harfbuzz.gyp
+++ b/third_party/harfbuzz-ng/harfbuzz.gyp
@@ -6,142 +6,195 @@
   'includes': [
     '../../build/win_precompile.gypi',
   ],
-  'targets': [
-    {
-      'target_name': 'harfbuzz-ng',
-      'type': 'static_library',
-      'defines': [
-        'HAVE_OT',
-        'HAVE_ICU',
-        'HAVE_ICU_BUILTIN',
-        'HB_NO_MT',
-      ],
-      'sources': [
-        'src/hb-atomic-private.hh',
-        'src/hb-blob.cc',
-        'src/hb-blob.h',
-        'src/hb-buffer.cc',
-        'src/hb-buffer-deserialize-json.hh',
-        'src/hb-buffer-deserialize-text.hh',
-        'src/hb-buffer.h',
-        'src/hb-buffer-private.hh',
-        'src/hb-buffer-serialize.cc',
-        'src/hb-cache-private.hh',
-        'src/hb-common.cc',
-        'src/hb-common.h',
-        'src/hb-deprecated.h',
-        'src/hb-face.cc',
-        'src/hb-face.h',
-        'src/hb-face-private.hh',
-        'src/hb-fallback-shape.cc',
-        'src/hb-font.cc',
-        'src/hb-font.h',
-        'src/hb-font-private.hh',
-        'src/hb.h',
-        'src/hb-icu.cc',
-        'src/hb-icu.h',
-        'src/hb-mutex-private.hh',
-        'src/hb-object-private.hh',
-        'src/hb-open-file-private.hh',
-        'src/hb-open-type-private.hh',
-        'src/hb-ot.h',
-        'src/hb-ot-head-table.hh',
-        'src/hb-ot-hhea-table.hh',
-        'src/hb-ot-hmtx-table.hh',
-        'src/hb-ot-layout.cc',
-        'src/hb-ot-layout-common-private.hh',
-        'src/hb-ot-layout-gdef-table.hh',
-        'src/hb-ot-layout-gpos-table.hh',
-        'src/hb-ot-layout-gsubgpos-private.hh',
-        'src/hb-ot-layout-gsub-table.hh',
-        'src/hb-ot-layout.h',
-        'src/hb-ot-layout-private.hh',
-        'src/hb-ot-map.cc',
-        'src/hb-ot-map-private.hh',
-        'src/hb-ot-maxp-table.hh',
-        'src/hb-ot-name-table.hh',
-        'src/hb-ot-shape.cc',
-        'src/hb-ot-shape-complex-arabic.cc',
-        'src/hb-ot-shape-complex-arabic-fallback.hh',
-        'src/hb-ot-shape-complex-arabic-table.hh',
-        'src/hb-ot-shape-complex-default.cc',
-        'src/hb-ot-shape-complex-hangul.cc',
-        'src/hb-ot-shape-complex-hebrew.cc',
-        'src/hb-ot-shape-complex-indic.cc',
-        'src/hb-ot-shape-complex-indic-machine.hh',
-        'src/hb-ot-shape-complex-indic-private.hh',
-        'src/hb-ot-shape-complex-indic-table.cc',
-        'src/hb-ot-shape-complex-myanmar.cc',
-        'src/hb-ot-shape-complex-myanmar-machine.hh',
-        'src/hb-ot-shape-complex-private.hh',
-        'src/hb-ot-shape-complex-sea.cc',
-        'src/hb-ot-shape-complex-sea-machine.hh',
-        'src/hb-ot-shape-complex-thai.cc',
-        'src/hb-ot-shape-complex-tibetan.cc',
-        'src/hb-ot-shape-fallback.cc',
-        'src/hb-ot-shape-fallback-private.hh',
-        'src/hb-ot-shape.h',
-        'src/hb-ot-shape-normalize.cc',
-        'src/hb-ot-shape-normalize-private.hh',
-        'src/hb-ot-shape-private.hh',
-        'src/hb-ot-tag.cc',
-        'src/hb-ot-tag.h',
-        'src/hb-private.hh',
-        'src/hb-set.cc',
-        'src/hb-set.h',
-        'src/hb-set-private.hh',
-        'src/hb-shape.cc',
-        'src/hb-shape.h',
-        'src/hb-shape-plan.cc',
-        'src/hb-shape-plan.h',
-        'src/hb-shape-plan-private.hh',
-        'src/hb-shaper.cc',
-        'src/hb-shaper-impl-private.hh',
-        'src/hb-shaper-list.hh',
-        'src/hb-shaper-private.hh',
-        'src/hb-unicode.cc',
-        'src/hb-unicode.h',
-        'src/hb-unicode-private.hh',
-        'src/hb-utf-private.hh',
-        'src/hb-version.h',
-        'src/hb-warning.cc',
-      ],
-      'include_dirs': [
-        'src',
-      ],
-      'direct_dependent_settings': {
-        'include_dirs': [
-          'src',
-        ],
-      },
-      'dependencies': [
-        '../../third_party/icu/icu.gyp:icuuc',
-      ],
+  'variables': {
+    'variables': {
       'conditions': [
-        ['clang==1', {
-          'xcode_settings': {
-            'WARNING_CFLAGS': [
-              '-Wno-unused-value',
-            ],
-          },
-          'cflags': [
-            '-Wno-unused-value',
-          ]
-        }],
-        ['OS=="win"', {
-          # TODO(eae): C4267 on amd64. size_t -> int, size_t -> unsigned int
-          'msvs_disabled_warnings': [4267, 4334],
-        }],
-        ['OS=="mac"', {
-          'defines': [
-            'HAVE_CORETEXT',
-          ],
-          'sources': [
-            'src/hb-coretext.cc',
-            'src/hb-coretext.h',
-          ],
+        ['sysroot!=""', {
+          'pkg-config': '<(chroot_cmd) ../../build/linux/pkg-config-wrapper "<(sysroot)" "<(target_arch)"',
+        }, {
+          'pkg-config': 'pkg-config'
         }],
       ],
     },
+
+    'pkg-config': '<(pkg-config)',
+
+    'conditions': [
+      ['OS=="linux" and (buildtype!="Official" or chromeos==1)', {
+        # Since version 1.31.0, pangoft2 which we depend on pulls in harfbuzz
+        # anyways. However, we want to have control of the version of harfbuzz
+        # we use, so don't use system harfbuzz for official builds, unless we
+        # are building for chrome os, where we have the system harfbuzz under
+        # control as well.
+        'use_system_harfbuzz': '<!(python ../../build/check_return_value.py <(pkg-config) --atleast-version=1.31.0 pangoft2)',
+      }, {
+        'use_system_harfbuzz': 0,
+      }],
+    ],
+  },
+  'conditions': [
+    ['use_system_harfbuzz==0', {
+      'targets': [
+        {
+          'target_name': 'harfbuzz-ng',
+          'type': 'static_library',
+          'defines': [
+            'HAVE_OT',
+            'HAVE_ICU',
+            'HAVE_ICU_BUILTIN',
+            'HB_NO_MT',
+          ],
+          'sources': [
+            'src/hb-atomic-private.hh',
+            'src/hb-blob.cc',
+            'src/hb-blob.h',
+            'src/hb-buffer.cc',
+            'src/hb-buffer-deserialize-json.hh',
+            'src/hb-buffer-deserialize-text.hh',
+            'src/hb-buffer.h',
+            'src/hb-buffer-private.hh',
+            'src/hb-buffer-serialize.cc',
+            'src/hb-cache-private.hh',
+            'src/hb-common.cc',
+            'src/hb-common.h',
+            'src/hb-deprecated.h',
+            'src/hb-face.cc',
+            'src/hb-face.h',
+            'src/hb-face-private.hh',
+            'src/hb-fallback-shape.cc',
+            'src/hb-font.cc',
+            'src/hb-font.h',
+            'src/hb-font-private.hh',
+            'src/hb.h',
+            'src/hb-icu.cc',
+            'src/hb-icu.h',
+            'src/hb-mutex-private.hh',
+            'src/hb-object-private.hh',
+            'src/hb-open-file-private.hh',
+            'src/hb-open-type-private.hh',
+            'src/hb-ot.h',
+            'src/hb-ot-head-table.hh',
+            'src/hb-ot-hhea-table.hh',
+            'src/hb-ot-hmtx-table.hh',
+            'src/hb-ot-layout.cc',
+            'src/hb-ot-layout-common-private.hh',
+            'src/hb-ot-layout-gdef-table.hh',
+            'src/hb-ot-layout-gpos-table.hh',
+            'src/hb-ot-layout-gsubgpos-private.hh',
+            'src/hb-ot-layout-gsub-table.hh',
+            'src/hb-ot-layout.h',
+            'src/hb-ot-layout-private.hh',
+            'src/hb-ot-map.cc',
+            'src/hb-ot-map-private.hh',
+            'src/hb-ot-maxp-table.hh',
+            'src/hb-ot-name-table.hh',
+            'src/hb-ot-shape.cc',
+            'src/hb-ot-shape-complex-arabic.cc',
+            'src/hb-ot-shape-complex-arabic-fallback.hh',
+            'src/hb-ot-shape-complex-arabic-table.hh',
+            'src/hb-ot-shape-complex-default.cc',
+            'src/hb-ot-shape-complex-hangul.cc',
+            'src/hb-ot-shape-complex-hebrew.cc',
+            'src/hb-ot-shape-complex-indic.cc',
+            'src/hb-ot-shape-complex-indic-machine.hh',
+            'src/hb-ot-shape-complex-indic-private.hh',
+            'src/hb-ot-shape-complex-indic-table.cc',
+            'src/hb-ot-shape-complex-myanmar.cc',
+            'src/hb-ot-shape-complex-myanmar-machine.hh',
+            'src/hb-ot-shape-complex-private.hh',
+            'src/hb-ot-shape-complex-sea.cc',
+            'src/hb-ot-shape-complex-sea-machine.hh',
+            'src/hb-ot-shape-complex-thai.cc',
+            'src/hb-ot-shape-complex-tibetan.cc',
+            'src/hb-ot-shape-fallback.cc',
+            'src/hb-ot-shape-fallback-private.hh',
+            'src/hb-ot-shape.h',
+            'src/hb-ot-shape-normalize.cc',
+            'src/hb-ot-shape-normalize-private.hh',
+            'src/hb-ot-shape-private.hh',
+            'src/hb-ot-tag.cc',
+            'src/hb-ot-tag.h',
+            'src/hb-private.hh',
+            'src/hb-set.cc',
+            'src/hb-set.h',
+            'src/hb-set-private.hh',
+            'src/hb-shape.cc',
+            'src/hb-shape.h',
+            'src/hb-shape-plan.cc',
+            'src/hb-shape-plan.h',
+            'src/hb-shape-plan-private.hh',
+            'src/hb-shaper.cc',
+            'src/hb-shaper-impl-private.hh',
+            'src/hb-shaper-list.hh',
+            'src/hb-shaper-private.hh',
+            'src/hb-unicode.cc',
+            'src/hb-unicode.h',
+            'src/hb-unicode-private.hh',
+            'src/hb-utf-private.hh',
+            'src/hb-version.h',
+            'src/hb-warning.cc',
+          ],
+          'include_dirs': [
+            'src',
+          ],
+          'direct_dependent_settings': {
+            'include_dirs': [
+              'src',
+            ],
+          },
+          'dependencies': [
+            '../../third_party/icu/icu.gyp:icuuc',
+          ],
+          'conditions': [
+            ['clang==1', {
+              'xcode_settings': {
+                'WARNING_CFLAGS': [
+                  '-Wno-unused-value',
+                ],
+              },
+              'cflags': [
+                '-Wno-unused-value',
+              ]
+            }],
+            ['OS=="win"', {
+              # TODO(eae): C4267 on amd64. size_t -> int, size_t -> unsigned int
+              'msvs_disabled_warnings': [4267, 4334],
+            }],
+            ['OS=="mac"', {
+              'defines': [
+                'HAVE_CORETEXT',
+              ],
+              'sources': [
+                'src/hb-coretext.cc',
+                'src/hb-coretext.h',
+              ],
+            }],
+          ],
+        },
+      ],
+    }, {  # use_system_harfbuzz==1
+      'targets': [
+        {
+          'target_name': 'harfbuzz-ng',
+          'type': 'none',
+          'cflags': [
+            '<!@(<(pkg-config) --cflags harfbuzz)',
+          ],
+          'direct_dependent_settings': {
+            'cflags': [
+              '<!@(<(pkg-config) --cflags harfbuzz)',
+            ],
+          },
+          'link_settings': {
+            'ldflags': [
+              '<!@(<(pkg-config) --libs-only-L --libs-only-other harfbuzz)',
+            ],
+            'libraries': [
+              '<!@(<(pkg-config) --libs-only-l harfbuzz)',
+            ],
+          },
+        },
+      ],
+    }],
   ],
 }
diff --git a/third_party/iccjpeg/iccjpeg.target.darwin-arm.mk b/third_party/iccjpeg/iccjpeg.target.darwin-arm.mk
index 8dfa809..9b9fdf4 100644
--- a/third_party/iccjpeg/iccjpeg.target.darwin-arm.mk
+++ b/third_party/iccjpeg/iccjpeg.target.darwin-arm.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/iccjpeg/iccjpeg.target.darwin-mips.mk b/third_party/iccjpeg/iccjpeg.target.darwin-mips.mk
index 6eb4457..62c34a7 100644
--- a/third_party/iccjpeg/iccjpeg.target.darwin-mips.mk
+++ b/third_party/iccjpeg/iccjpeg.target.darwin-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/iccjpeg/iccjpeg.target.darwin-x86.mk b/third_party/iccjpeg/iccjpeg.target.darwin-x86.mk
index 55a2cb7..49760b5 100644
--- a/third_party/iccjpeg/iccjpeg.target.darwin-x86.mk
+++ b/third_party/iccjpeg/iccjpeg.target.darwin-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/iccjpeg/iccjpeg.target.darwin-x86_64.mk b/third_party/iccjpeg/iccjpeg.target.darwin-x86_64.mk
new file mode 100644
index 0000000..c8697a1
--- /dev/null
+++ b/third_party/iccjpeg/iccjpeg.target.darwin-x86_64.mk
@@ -0,0 +1,262 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_iccjpeg_iccjpeg_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_libjpeg_libjpeg_gyp)/libjpeg.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/iccjpeg/iccjpeg.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_iccjpeg_iccjpeg_gyp
+
+# Alias gyp target name.
+.PHONY: iccjpeg
+iccjpeg: third_party_iccjpeg_iccjpeg_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/iccjpeg/iccjpeg.target.linux-arm.mk b/third_party/iccjpeg/iccjpeg.target.linux-arm.mk
index 8dfa809..9b9fdf4 100644
--- a/third_party/iccjpeg/iccjpeg.target.linux-arm.mk
+++ b/third_party/iccjpeg/iccjpeg.target.linux-arm.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/iccjpeg/iccjpeg.target.linux-mips.mk b/third_party/iccjpeg/iccjpeg.target.linux-mips.mk
index 6eb4457..62c34a7 100644
--- a/third_party/iccjpeg/iccjpeg.target.linux-mips.mk
+++ b/third_party/iccjpeg/iccjpeg.target.linux-mips.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/iccjpeg/iccjpeg.target.linux-x86.mk b/third_party/iccjpeg/iccjpeg.target.linux-x86.mk
index 55a2cb7..49760b5 100644
--- a/third_party/iccjpeg/iccjpeg.target.linux-x86.mk
+++ b/third_party/iccjpeg/iccjpeg.target.linux-x86.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/iccjpeg/iccjpeg.target.linux-x86_64.mk b/third_party/iccjpeg/iccjpeg.target.linux-x86_64.mk
new file mode 100644
index 0000000..c8697a1
--- /dev/null
+++ b/third_party/iccjpeg/iccjpeg.target.linux-x86_64.mk
@@ -0,0 +1,262 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_iccjpeg_iccjpeg_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_libjpeg_libjpeg_gyp)/libjpeg.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/iccjpeg/iccjpeg.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_iccjpeg_iccjpeg_gyp
+
+# Alias gyp target name.
+.PHONY: iccjpeg
+iccjpeg: third_party_iccjpeg_iccjpeg_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/khronos/khronos_headers.target.darwin-x86_64.mk b/third_party/khronos/khronos_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..31ade71
--- /dev/null
+++ b/third_party/khronos/khronos_headers.target.darwin-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_khronos_khronos_headers_gyp
+LOCAL_MODULE_STEM := khronos_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_khronos_khronos_headers_gyp
+
+# Alias gyp target name.
+.PHONY: khronos_headers
+khronos_headers: third_party_khronos_khronos_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/khronos/khronos_headers.target.linux-x86_64.mk b/third_party/khronos/khronos_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..31ade71
--- /dev/null
+++ b/third_party/khronos/khronos_headers.target.linux-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_khronos_khronos_headers_gyp
+LOCAL_MODULE_STEM := khronos_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_khronos_khronos_headers_gyp
+
+# Alias gyp target name.
+.PHONY: khronos_headers
+khronos_headers: third_party_khronos_khronos_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/leveldatabase/README.chromium b/third_party/leveldatabase/README.chromium
index a96f4be..3d7b021 100644
--- a/third_party/leveldatabase/README.chromium
+++ b/third_party/leveldatabase/README.chromium
@@ -24,3 +24,4 @@
   HANDLE_EINTR macro that retries the call.
 * TRACE macros/thread name for chrome://tracing diagnostics
 * Handle in-process exclusive file locks, based on src/util/env_posix.cc
+* Unit tests for the Chromium environment.
diff --git a/third_party/leveldatabase/env_chromium_unittest.cc b/third_party/leveldatabase/env_chromium_unittest.cc
index 66e498b..092ddfb 100644
--- a/third_party/leveldatabase/env_chromium_unittest.cc
+++ b/third_party/leveldatabase/env_chromium_unittest.cc
@@ -113,7 +113,7 @@
   MyEnv<TypeParam> env;
 
   base::ScopedTempDir dir;
-  dir.CreateUniqueTempDir();
+  ASSERT_TRUE(dir.CreateUniqueTempDir());
   base::FilePath dir_path = dir.path();
   std::string some_data = "some data";
   Slice data = some_data;
@@ -176,7 +176,7 @@
   options.env = IDBEnv();
 
   base::ScopedTempDir scoped_temp_dir;
-  scoped_temp_dir.CreateUniqueTempDir();
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
   base::FilePath dir = scoped_temp_dir.path();
 
   DB* db;
@@ -221,7 +221,7 @@
 
 TEST(ChromiumEnv, GetChildrenEmptyDir) {
   base::ScopedTempDir scoped_temp_dir;
-  scoped_temp_dir.CreateUniqueTempDir();
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
   base::FilePath dir = scoped_temp_dir.path();
 
   Env* env = IDBEnv();
@@ -233,7 +233,7 @@
 
 TEST(ChromiumEnv, GetChildrenPriorResults) {
   base::ScopedTempDir scoped_temp_dir;
-  scoped_temp_dir.CreateUniqueTempDir();
+  ASSERT_TRUE(scoped_temp_dir.CreateUniqueTempDir());
   base::FilePath dir = scoped_temp_dir.path();
 
   base::FilePath new_file_dir = dir.Append(FPL("tmp_file"));
diff --git a/third_party/leveldatabase/leveldatabase.gyp b/third_party/leveldatabase/leveldatabase.gyp
index 3cb8869..f6956ed 100644
--- a/third_party/leveldatabase/leveldatabase.gyp
+++ b/third_party/leveldatabase/leveldatabase.gyp
@@ -14,6 +14,22 @@
         'use_snappy': 0,
       },
     }],
+    ['OS=="android" and gtest_target_type == "shared_library"', {
+      # Wrap env_chromium_unittests into an android apk for execution.
+      'targets': [{
+        'target_name': 'env_chromium_unittests_apk',
+        'type': 'none',
+        'dependencies': [
+          '<(DEPTH)/base/base.gyp:base_java',
+          'env_chromium_unittests',
+        ],
+        'variables': {
+          'test_suite_name': 'env_chromium_unittests',
+          'input_shlib_path': '<(SHARED_LIB_DIR)/<(SHARED_LIB_PREFIX)env_chromium_unittests<(SHARED_LIB_SUFFIX)',
+        },
+        'includes': [ '../../build/apk_test.gypi' ],
+      }],
+    }],
   ],
   'target_defaults': {
     'defines': [
@@ -180,6 +196,15 @@
       'sources': [
         'env_chromium_unittest.cc',
       ],
+      'conditions': [
+        ['OS=="android" and gtest_target_type == "shared_library"', {
+          'type': 'shared_library',
+          'dependencies': [
+            '../../testing/android/native_test.gyp:native_test_native_code',
+            '../../tools/android/forwarder2/forwarder.gyp:forwarder2',
+          ],
+        }],
+      ],
     },
     {
       'target_name': 'leveldb_testutil',
diff --git a/third_party/leveldatabase/leveldatabase.target.darwin-arm.mk b/third_party/leveldatabase/leveldatabase.target.darwin-arm.mk
index 8db2654..3f0b019 100644
--- a/third_party/leveldatabase/leveldatabase.target.darwin-arm.mk
+++ b/third_party/leveldatabase/leveldatabase.target.darwin-arm.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -210,6 +211,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/leveldatabase/leveldatabase.target.darwin-mips.mk b/third_party/leveldatabase/leveldatabase.target.darwin-mips.mk
index 30a197b..8ef672e 100644
--- a/third_party/leveldatabase/leveldatabase.target.darwin-mips.mk
+++ b/third_party/leveldatabase/leveldatabase.target.darwin-mips.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -210,6 +211,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/leveldatabase/leveldatabase.target.darwin-x86.mk b/third_party/leveldatabase/leveldatabase.target.darwin-x86.mk
index 3fe28cc..a0d5286 100644
--- a/third_party/leveldatabase/leveldatabase.target.darwin-x86.mk
+++ b/third_party/leveldatabase/leveldatabase.target.darwin-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -211,6 +212,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/leveldatabase/leveldatabase.target.darwin-x86_64.mk b/third_party/leveldatabase/leveldatabase.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d62c28e
--- /dev/null
+++ b/third_party/leveldatabase/leveldatabase.target.darwin-x86_64.mk
@@ -0,0 +1,309 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_leveldatabase_leveldatabase_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/leveldatabase/env_chromium.cc \
+	third_party/leveldatabase/env_chromium_stdio.cc \
+	third_party/leveldatabase/port/port_chromium.cc \
+	third_party/leveldatabase/src/db/builder.cc \
+	third_party/leveldatabase/src/db/db_impl.cc \
+	third_party/leveldatabase/src/db/db_iter.cc \
+	third_party/leveldatabase/src/db/filename.cc \
+	third_party/leveldatabase/src/db/dbformat.cc \
+	third_party/leveldatabase/src/db/log_reader.cc \
+	third_party/leveldatabase/src/db/log_writer.cc \
+	third_party/leveldatabase/src/db/memtable.cc \
+	third_party/leveldatabase/src/db/repair.cc \
+	third_party/leveldatabase/src/db/table_cache.cc \
+	third_party/leveldatabase/src/db/version_edit.cc \
+	third_party/leveldatabase/src/db/version_set.cc \
+	third_party/leveldatabase/src/db/write_batch.cc \
+	third_party/leveldatabase/src/helpers/memenv/memenv.cc \
+	third_party/leveldatabase/src/table/block.cc \
+	third_party/leveldatabase/src/table/block_builder.cc \
+	third_party/leveldatabase/src/table/filter_block.cc \
+	third_party/leveldatabase/src/table/format.cc \
+	third_party/leveldatabase/src/table/iterator.cc \
+	third_party/leveldatabase/src/table/merger.cc \
+	third_party/leveldatabase/src/table/table.cc \
+	third_party/leveldatabase/src/table/table_builder.cc \
+	third_party/leveldatabase/src/table/two_level_iterator.cc \
+	third_party/leveldatabase/src/util/arena.cc \
+	third_party/leveldatabase/src/util/bloom.cc \
+	third_party/leveldatabase/src/util/cache.cc \
+	third_party/leveldatabase/src/util/coding.cc \
+	third_party/leveldatabase/src/util/comparator.cc \
+	third_party/leveldatabase/src/util/crc32c.cc \
+	third_party/leveldatabase/src/util/env.cc \
+	third_party/leveldatabase/src/util/filter_policy.cc \
+	third_party/leveldatabase/src/util/hash.cc \
+	third_party/leveldatabase/src/util/logging.cc \
+	third_party/leveldatabase/src/util/options.cc \
+	third_party/leveldatabase/src/util/status.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DLEVELDB_PLATFORM_CHROMIUM=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DLEVELDB_PLATFORM_CHROMIUM=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_leveldatabase_leveldatabase_gyp
+
+# Alias gyp target name.
+.PHONY: leveldatabase
+leveldatabase: third_party_leveldatabase_leveldatabase_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/leveldatabase/leveldatabase.target.linux-arm.mk b/third_party/leveldatabase/leveldatabase.target.linux-arm.mk
index 8db2654..3f0b019 100644
--- a/third_party/leveldatabase/leveldatabase.target.linux-arm.mk
+++ b/third_party/leveldatabase/leveldatabase.target.linux-arm.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -210,6 +211,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/leveldatabase/leveldatabase.target.linux-mips.mk b/third_party/leveldatabase/leveldatabase.target.linux-mips.mk
index 30a197b..8ef672e 100644
--- a/third_party/leveldatabase/leveldatabase.target.linux-mips.mk
+++ b/third_party/leveldatabase/leveldatabase.target.linux-mips.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -210,6 +211,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/leveldatabase/leveldatabase.target.linux-x86.mk b/third_party/leveldatabase/leveldatabase.target.linux-x86.mk
index 3fe28cc..a0d5286 100644
--- a/third_party/leveldatabase/leveldatabase.target.linux-x86.mk
+++ b/third_party/leveldatabase/leveldatabase.target.linux-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -211,6 +212,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/leveldatabase/leveldatabase.target.linux-x86_64.mk b/third_party/leveldatabase/leveldatabase.target.linux-x86_64.mk
new file mode 100644
index 0000000..d62c28e
--- /dev/null
+++ b/third_party/leveldatabase/leveldatabase.target.linux-x86_64.mk
@@ -0,0 +1,309 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_leveldatabase_leveldatabase_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/leveldatabase/env_chromium.cc \
+	third_party/leveldatabase/env_chromium_stdio.cc \
+	third_party/leveldatabase/port/port_chromium.cc \
+	third_party/leveldatabase/src/db/builder.cc \
+	third_party/leveldatabase/src/db/db_impl.cc \
+	third_party/leveldatabase/src/db/db_iter.cc \
+	third_party/leveldatabase/src/db/filename.cc \
+	third_party/leveldatabase/src/db/dbformat.cc \
+	third_party/leveldatabase/src/db/log_reader.cc \
+	third_party/leveldatabase/src/db/log_writer.cc \
+	third_party/leveldatabase/src/db/memtable.cc \
+	third_party/leveldatabase/src/db/repair.cc \
+	third_party/leveldatabase/src/db/table_cache.cc \
+	third_party/leveldatabase/src/db/version_edit.cc \
+	third_party/leveldatabase/src/db/version_set.cc \
+	third_party/leveldatabase/src/db/write_batch.cc \
+	third_party/leveldatabase/src/helpers/memenv/memenv.cc \
+	third_party/leveldatabase/src/table/block.cc \
+	third_party/leveldatabase/src/table/block_builder.cc \
+	third_party/leveldatabase/src/table/filter_block.cc \
+	third_party/leveldatabase/src/table/format.cc \
+	third_party/leveldatabase/src/table/iterator.cc \
+	third_party/leveldatabase/src/table/merger.cc \
+	third_party/leveldatabase/src/table/table.cc \
+	third_party/leveldatabase/src/table/table_builder.cc \
+	third_party/leveldatabase/src/table/two_level_iterator.cc \
+	third_party/leveldatabase/src/util/arena.cc \
+	third_party/leveldatabase/src/util/bloom.cc \
+	third_party/leveldatabase/src/util/cache.cc \
+	third_party/leveldatabase/src/util/coding.cc \
+	third_party/leveldatabase/src/util/comparator.cc \
+	third_party/leveldatabase/src/util/crc32c.cc \
+	third_party/leveldatabase/src/util/env.cc \
+	third_party/leveldatabase/src/util/filter_policy.cc \
+	third_party/leveldatabase/src/util/hash.cc \
+	third_party/leveldatabase/src/util/logging.cc \
+	third_party/leveldatabase/src/util/options.cc \
+	third_party/leveldatabase/src/util/status.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DLEVELDB_PLATFORM_CHROMIUM=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DLEVELDB_PLATFORM_CHROMIUM=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_leveldatabase_leveldatabase_gyp
+
+# Alias gyp target name.
+.PHONY: leveldatabase
+leveldatabase: third_party_leveldatabase_leveldatabase_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h
index e9ca7a4..e101877 100644
--- a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h
+++ b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_data.h
@@ -56,11 +56,6 @@
   // which comprises multiple fields.
   void SetFieldValue(AddressField field, const std::string& value);
 
-  // Guesses the BCP 47 language code to be used for formatting the address for
-  // display. For example, guesses "en" if the |country_code| is "US". Can
-  // return an empty string.
-  const std::string& GuessLanguageCode() const;
-
   // The BCP 47 language code used to guide how the address is formatted for
   // display. The same address may have different representations in different
   // languages.
diff --git a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h
index 91d917b..eecbcd8 100644
--- a/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h
+++ b/third_party/libaddressinput/chromium/cpp/include/libaddressinput/address_ui.h
@@ -28,9 +28,26 @@
 // Returns the list of supported CLDR region codes.
 const std::vector<std::string>& GetRegionCodes();
 
-// Returns the UI components for the CLDR |region_code|. Returns an empty vector
-// on error.
-std::vector<AddressUiComponent> BuildComponents(const std::string& region_code);
+// Returns the UI components for the CLDR |region_code|. These components
+// represent the address input and formatting rules for |region_code|.
+//
+// Sets the |components_language_code| to the BCP 47 language code that should
+// be used to format the address that the user entered via the UI components.
+// The |components_language_code| parameter can be NULL.
+//
+// If |region_code| has rules for latinized address format and the BCP 47
+// |ui_language_code| is not the primary language code used in the region, then
+// returns the latinized version of the UI components.
+//
+// If the UI language has a variation, then the function ignores the variation.
+// For example, the function does not distinguish among zh-hans, zh-hant, and
+// zh.
+//
+// Returns an empty vector on error.
+std::vector<AddressUiComponent> BuildComponents(
+    const std::string& region_code,
+    const std::string& ui_language_code,
+    std::string* components_language_code);
 
 // Returns the fields which are required for the CLDR |region_code|. Returns an
 // empty vector on error.
diff --git a/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp b/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp
index 6215898..8c44188 100644
--- a/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp
+++ b/third_party/libaddressinput/chromium/cpp/libaddressinput.gyp
@@ -42,12 +42,10 @@
         'src/retriever.cc',
         'src/rule.cc',
         'src/ruleset.cc',
-        'src/time_to_string.cc',
         'src/util/canonicalize_string.cc',
         'src/util/json.cc',
         'src/util/md5.cc',
-        'src/util/string_compare.cc',
-        'src/util/string_split.cc',
+        'src/util/string_util.cc',
         'src/util/trie.cc',
       ],
       'defines': [
@@ -76,12 +74,11 @@
         'test/retriever_test.cc',
         'test/rule_test.cc',
         'test/storage_test_runner.cc',
-        'test/time_to_string.cc',
         'test/util/json_test.cc',
         'test/util/md5_unittest.cc',
         'test/util/scoped_ptr_unittest.cc',
         'test/util/stl_util_unittest.cc',
-        'test/util/string_split_unittest.cc',
+        'test/util/string_util_test.cc',
         'test/util/trie_test.cc',
       ],
       'defines': [
diff --git a/third_party/libaddressinput/chromium/cpp/src/address_data.cc b/third_party/libaddressinput/chromium/cpp/src/address_data.cc
index 51d36c6..08da6ca 100644
--- a/third_party/libaddressinput/chromium/cpp/src/address_data.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/address_data.cc
@@ -24,6 +24,7 @@
 
 #include "region_data_constants.h"
 #include "rule.h"
+#include "util/string_util.h"
 
 namespace i18n {
 namespace addressinput {
@@ -65,7 +66,16 @@
   rule.CopyFrom(Rule::GetDefault());
   rule.ParseSerializedRule(RegionDataConstants::GetRegionData(country_code));
 
-  const std::vector<std::vector<FormatElement> >& format = rule.GetFormat();
+  // If latinized rules are available and the |language_code| of this address is
+  // not the primary language code for the region, then use the latinized
+  // formatting rules.
+  const std::vector<std::vector<FormatElement> >& format =
+      rule.GetLatinFormat().empty() ||
+      language_code.empty() ||
+      NormalizeLanguageCode(language_code) ==
+          NormalizeLanguageCode(rule.GetLanguage())
+              ? rule.GetFormat() : rule.GetLatinFormat();
+
   for (size_t i = 0; i < format.size(); ++i) {
     std::string line;
     for (size_t j = 0; j < format[i].size(); ++j) {
@@ -107,28 +117,5 @@
   }
 }
 
-const std::string& AddressData::GuessLanguageCode() const {
-  Rule rule;
-  rule.CopyFrom(Rule::GetDefault());
-  if (!rule.ParseSerializedRule(
-          RegionDataConstants::GetRegionData(country_code))) {
-    return language_code;
-  }
-
-  std::vector<std::string>::const_iterator lang_it =
-      std::find(rule.GetLanguages().begin(),
-                rule.GetLanguages().end(),
-                language_code);
-  if (lang_it != rule.GetLanguages().end()) {
-    return *lang_it;
-  }
-
-  if (!rule.GetLanguage().empty()) {
-    return rule.GetLanguage();
-  }
-
-  return language_code;
-}
-
 }  // namespace addressinput
 }  // namespace i18n
diff --git a/third_party/libaddressinput/chromium/cpp/src/address_ui.cc b/third_party/libaddressinput/chromium/cpp/src/address_ui.cc
index c4eeb99..b4337fd 100644
--- a/third_party/libaddressinput/chromium/cpp/src/address_ui.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/address_ui.cc
@@ -17,6 +17,9 @@
 #include <libaddressinput/address_field.h>
 #include <libaddressinput/address_ui_component.h>
 
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
 #include <set>
 #include <string>
 #include <vector>
@@ -25,6 +28,7 @@
 #include "grit/libaddressinput_strings.h"
 #include "region_data_constants.h"
 #include "rule.h"
+#include "util/string_util.h"
 
 namespace i18n {
 namespace addressinput {
@@ -58,6 +62,74 @@
   }
 }
 
+// Returns the BCP 47 language code that should be used to format the address
+// that the user entered.
+//
+// If the rule does not contain information about languages, then returns the
+// UI language.
+//
+// If the UI language is either the default language for the country, one of the
+// languages for rules, or one of the languages for address input, then returns
+// this UI language. If there're no matches, then picks one of the languages in
+// the rule and returns it.
+//
+// If latinized rules are available and the UI language code is not the primary
+// language code for this region, then returns the primary language with "-latn"
+// appended.
+std::string GetComponentsLanguageCode(const Rule& rule,
+                                      const std::string& ui_language_code) {
+  // Select the default language code for the region.
+  std::string default_language_code;
+  if (!rule.GetLanguage().empty()) {
+    default_language_code = rule.GetLanguage();
+  } else if (!rule.GetLanguages().empty()) {
+    default_language_code = rule.GetLanguages()[0];
+  } else if (!rule.GetInputLanguages().empty()) {
+    default_language_code = rule.GetInputLanguages()[0];
+  } else {
+    // Region does not have any language information (e.g. Antarctica). Use the
+    // UI language code as is.
+    return ui_language_code;
+  }
+
+  // If the UI language code is not set, then use default language code.
+  if (ui_language_code.empty()) {
+    return default_language_code;
+  }
+
+  const std::string& normalized_ui_language_code =
+      NormalizeLanguageCode(ui_language_code);
+  const std::string& normalized_default_language_code =
+      NormalizeLanguageCode(default_language_code);
+
+  // Check whether UI language code matches any language codes in the rule,
+  // normalized or as is.
+  if (normalized_default_language_code == normalized_ui_language_code ||
+      std::find(
+          rule.GetLanguages().begin(),
+          rule.GetLanguages().end(),
+          ui_language_code) != rule.GetLanguages().end() ||
+      std::find(
+          rule.GetLanguages().begin(),
+          rule.GetLanguages().end(),
+          normalized_ui_language_code) != rule.GetLanguages().end() ||
+      std::find(
+          rule.GetInputLanguages().begin(),
+          rule.GetInputLanguages().end(),
+          ui_language_code) != rule.GetInputLanguages().end() ||
+      std::find(
+          rule.GetInputLanguages().begin(),
+          rule.GetInputLanguages().end(),
+          normalized_ui_language_code) != rule.GetInputLanguages().end()) {
+    return ui_language_code;
+  }
+
+  // The UI language code does not match any language information in the rule.
+  return rule.GetLatinFormat().empty()
+             ? default_language_code
+             : normalized_default_language_code + "-latn";
+}
+
 }  // namespace
 
 const std::vector<std::string>& GetRegionCodes() {
@@ -65,7 +137,9 @@
 }
 
 std::vector<AddressUiComponent> BuildComponents(
-    const std::string& region_code) {
+    const std::string& region_code,
+    const std::string& ui_language_code,
+    std::string* components_language_code) {
   std::vector<AddressUiComponent> result;
 
   Rule rule;
@@ -75,13 +149,28 @@
     return result;
   }
 
+  if (components_language_code != NULL) {
+    *components_language_code =
+        GetComponentsLanguageCode(rule, ui_language_code);
+  }
+
   // For avoiding showing an input field twice, when the field is displayed
   // twice on an envelope.
   std::set<AddressField> fields;
 
+  // If latinized rules are available and the |ui_language_code| is not the
+  // primary language code for the region, then use the latinized formatting
+  // rules.
+  const std::vector<std::vector<FormatElement> >& format =
+      rule.GetLatinFormat().empty() ||
+      ui_language_code.empty() ||
+      NormalizeLanguageCode(ui_language_code) ==
+          NormalizeLanguageCode(rule.GetLanguage())
+              ? rule.GetFormat() : rule.GetLatinFormat();
+
   for (std::vector<std::vector<FormatElement> >::const_iterator
-           line_it = rule.GetFormat().begin();
-       line_it != rule.GetFormat().end();
+           line_it = format.begin();
+       line_it != format.end();
        ++line_it) {
     int num_fields_this_row = 0;
     for (std::vector<FormatElement>::const_iterator element_it =
diff --git a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc
index 39df55b..435f75d 100644
--- a/third_party/libaddressinput/chromium/cpp/src/address_validator.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/address_validator.cc
@@ -40,7 +40,7 @@
 #include "rule.h"
 #include "ruleset.h"
 #include "util/stl_util.h"
-#include "util/string_compare.h"
+#include "util/string_util.h"
 
 namespace i18n {
 namespace addressinput {
@@ -271,9 +271,16 @@
 
     assert(ruleset_it->second != NULL);
 
-    // Initialize the prefix search index lazily.
-    if (!ruleset_it->second->prefix_search_index_ready()) {
-      ruleset_it->second->BuildPrefixSearchIndex();
+    // Do not suggest anything if the user is typing in the field for which
+    // there's no validation data.
+    if (focused_field != POSTAL_CODE &&
+        (focused_field < ADMIN_AREA || focused_field > DEPENDENT_LOCALITY)) {
+      return SUCCESS;
+    }
+
+    // Do not suggest anything if the user input is empty.
+    if (user_input.GetFieldValue(focused_field).empty()) {
+      return SUCCESS;
     }
 
     const Ruleset& country_ruleset = *ruleset_it->second;
@@ -290,6 +297,16 @@
       return SUCCESS;
     }
 
+    // Initialize the prefix search index lazily.
+    if (!ruleset_it->second->prefix_search_index_ready()) {
+      ruleset_it->second->BuildPrefixSearchIndex();
+    }
+
+    if (focused_field != POSTAL_CODE &&
+        focused_field > country_ruleset.deepest_ruleset_level()) {
+      return SUCCESS;
+    }
+
     // Determine the most specific address field that can be suggested.
     AddressField suggestion_field = focused_field != POSTAL_CODE
         ? focused_field : DEPENDENT_LOCALITY;
@@ -394,6 +411,7 @@
       }
 
       AddressData suggestion;
+      suggestion.country_code = user_input.country_code;
       suggestion.postal_code = user_input.postal_code;
 
       // Traverse the tree of rulesets from the most specific |ruleset| to the
diff --git a/third_party/libaddressinput/chromium/cpp/src/region_data_constants.cc b/third_party/libaddressinput/chromium/cpp/src/region_data_constants.cc
index be60e54..9b80464 100644
--- a/third_party/libaddressinput/chromium/cpp/src/region_data_constants.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/region_data_constants.cc
@@ -17,8 +17,8 @@
 //
 // https://code.google.com/p/libaddressinput/source/browse/trunk/java/src/com/android/i18n/addressinput/RegionDataConstants.java?r=137
 //
-// The language-to-separator and country-to-language mapping is loosely based
-// on:
+// The language-to-separator mapping and primary input languages are loosely
+// based on:
 //
 // http://unicode.org/cldr/trac/browser/tags/release-24/common/supplemental/supplementalData.xml
 
@@ -41,39 +41,48 @@
       "\"name\":\"ANDORRA\","
       "\"lang\":\"ca\","
       "\"languages\":\"ca\","
+      "\"input_languages\":\"ca\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %S\","
       "\"require\":\"AS\","
       "\"state_name_type\":\"parish\""
       "}"));
   region_data.insert(std::make_pair("AE", "{"
       "\"name\":\"UNITED ARAB EMIRATES\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%C\","
       "\"require\":\"AC\""
       "}"));
   region_data.insert(std::make_pair("AF", "{"
-      "\"name\":\"AFGHANISTAN\""
+      "\"name\":\"AFGHANISTAN\","
+      "\"input_languages\":\"fa~ps\""
       "}"));
   region_data.insert(std::make_pair("AG", "{"
       "\"name\":\"ANTIGUA AND BARBUDA\","
+      "\"input_languages\":\"en\","
       "\"require\":\"A\""
       "}"));
   region_data.insert(std::make_pair("AI", "{"
-      "\"name\":\"ANGUILLA\""
+      "\"name\":\"ANGUILLA\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("AL", "{"
-      "\"name\":\"ALBANIA\""
+      "\"name\":\"ALBANIA\","
+      "\"input_languages\":\"sq\""
       "}"));
   region_data.insert(std::make_pair("AM", "{"
       "\"name\":\"ARMENIA\","
       "\"lang\":\"hy\","
       "\"languages\":\"hy\","
-      "\"fmt\":\"%N%n%O%n%A%n%Z%n%C%n%S\""
+      "\"input_languages\":\"hy\","
+      "\"fmt\":\"%N%n%O%n%A%n%Z%n%C%n%S\","
+      "\"lfmt\":\"%N%n%O%n%A%n%Z%n%C%n%S\""
       "}"));
   region_data.insert(std::make_pair("AN", "{"
       "\"name\":\"NETHERLANDS ANTILLES\""
       "}"));
   region_data.insert(std::make_pair("AO", "{"
-      "\"name\":\"ANGOLA\""
+      "\"name\":\"ANGOLA\","
+      "\"input_languages\":\"pt\""
       "}"));
   region_data.insert(std::make_pair("AQ", "{"
       "\"name\":\"ANTARCTICA\""
@@ -82,11 +91,13 @@
       "\"name\":\"ARGENTINA\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C%n%S\","
       "\"state_name_type\":\"state\""
       "}"));
   region_data.insert(std::make_pair("AS", "{"
       "\"name\":\"AMERICAN SAMOA\","
+      "\"input_languages\":\"en~sm\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -94,6 +105,7 @@
       "}"));
   region_data.insert(std::make_pair("AT", "{"
       "\"name\":\"AUSTRIA\","
+      "\"input_languages\":\"de\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
@@ -101,77 +113,95 @@
       "\"name\":\"AUSTRALIA\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%O%n%N%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"state_name_type\":\"state\""
       "}"));
   region_data.insert(std::make_pair("AW", "{"
-      "\"name\":\"ARUBA\""
+      "\"name\":\"ARUBA\","
+      "\"input_languages\":\"nl~pap\""
       "}"));
   region_data.insert(std::make_pair("AX", "{"
       "\"name\":\"FINLAND\","
+      "\"input_languages\":\"sv\","
       "\"fmt\":\"%O%n%N%n%A%nAX-%Z %C%n\xC3\x85LAND\","  // \xC3\x85 is Å.
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("AZ", "{"
       "\"name\":\"AZERBAIJAN\","
+      "\"input_languages\":\"az\","
       "\"fmt\":\"%N%n%O%n%A%nAZ %Z %C\""
       "}"));
   region_data.insert(std::make_pair("BA", "{"
       "\"name\":\"BOSNIA AND HERZEGOVINA\","
+      "\"input_languages\":\"bs~hr~sr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("BB", "{"
       "\"name\":\"BARBADOS\","
+      "\"input_languages\":\"en\","
       "\"state_name_type\":\"parish\""
       "}"));
   region_data.insert(std::make_pair("BD", "{"
       "\"name\":\"BANGLADESH\","
+      "\"input_languages\":\"bn\","
       "\"fmt\":\"%N%n%O%n%A%n%C - %Z\""
       "}"));
   region_data.insert(std::make_pair("BE", "{"
       "\"name\":\"BELGIUM\","
+      "\"input_languages\":\"de~fr~nl\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("BF", "{"
       "\"name\":\"BURKINA FASO\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%N%n%O%n%A%n%C %X\""
       "}"));
   region_data.insert(std::make_pair("BG", "{"
       "\"name\":\"BULGARIA (REP.)\","
+      "\"input_languages\":\"bg\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("BH", "{"
       "\"name\":\"BAHRAIN\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("BI", "{"
-      "\"name\":\"BURUNDI\""
+      "\"name\":\"BURUNDI\","
+      "\"input_languages\":\"fr~rn\""
       "}"));
   region_data.insert(std::make_pair("BJ", "{"
-      "\"name\":\"BENIN\""
+      "\"name\":\"BENIN\","
+      "\"input_languages\":\"fr\""
       "}"));
   region_data.insert(std::make_pair("BL", "{"
       "\"name\":\"SAINT BARTHELEMY\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("BM", "{"
       "\"name\":\"BERMUDA\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("BN", "{"
       "\"name\":\"BRUNEI DARUSSALAM\","
+      "\"input_languages\":\"ms\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("BO", "{"
-      "\"name\":\"BOLIVIA\""
+      "\"name\":\"BOLIVIA\","
+      "\"input_languages\":\"ay~es~qu\""
       "}"));
   region_data.insert(std::make_pair("BR", "{"
       "\"name\":\"BRAZIL\","
       "\"lang\":\"pt\","
       "\"languages\":\"pt\","
+      "\"input_languages\":\"pt\","
       "\"fmt\":\"%O%n%N%n%A%n%C-%S%n%Z\","
       "\"require\":\"ASCZ\","
       "\"state_name_type\":\"state\""
@@ -180,84 +210,103 @@
       "\"name\":\"BAHAMAS\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %S\","
       "\"state_name_type\":\"island\""
       "}"));
   region_data.insert(std::make_pair("BT", "{"
-      "\"name\":\"BHUTAN\""
+      "\"name\":\"BHUTAN\","
+      "\"input_languages\":\"dz\""
       "}"));
   region_data.insert(std::make_pair("BV", "{"
       "\"name\":\"BOUVET ISLAND\""
       "}"));
   region_data.insert(std::make_pair("BW", "{"
-      "\"name\":\"BOTSWANA\""
+      "\"name\":\"BOTSWANA\","
+      "\"input_languages\":\"en~tn\""
       "}"));
   region_data.insert(std::make_pair("BY", "{"
       "\"name\":\"BELARUS\","
+      "\"input_languages\":\"be~ru\","
       "\"fmt\":\"%S%n%Z %C %X%n%A%n%O%n%N\""
       "}"));
   region_data.insert(std::make_pair("BZ", "{"
-      "\"name\":\"BELIZE\""
+      "\"name\":\"BELIZE\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("CA", "{"
       "\"name\":\"CANADA\","
       "\"lang\":\"en\","
       "\"languages\":\"en~fr\","
+      "\"input_languages\":\"en~fr\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\""
       "}"));
   region_data.insert(std::make_pair("CC", "{"
       "\"name\":\"COCOS (KEELING) ISLANDS\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%O%n%N%n%A%n%C %S %Z\""
       "}"));
   region_data.insert(std::make_pair("CD", "{"
       "\"name\":\"CONGO (DEM. REP.)\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%N%n%O%n%A%n%C %X\""
       "}"));
   region_data.insert(std::make_pair("CF", "{"
-      "\"name\":\"CENTRAL AFRICAN REPUBLIC\""
+      "\"name\":\"CENTRAL AFRICAN REPUBLIC\","
+      "\"input_languages\":\"fr~sg\""
       "}"));
   region_data.insert(std::make_pair("CG", "{"
-      "\"name\":\"CONGO (REP.)\""
+      "\"name\":\"CONGO (REP.)\","
+      "\"input_languages\":\"fr~ln\""
       "}"));
   region_data.insert(std::make_pair("CH", "{"
       "\"name\":\"SWITZERLAND\","
       "\"lang\":\"de\","
       "\"languages\":\"de~fr~it\","
+      "\"input_languages\":\"de~fr~gsw~it\","
       "\"fmt\":\"%O%n%N%n%A%nCH-%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("CI", "{"
       "\"name\":\"COTE D'IVOIRE\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%N%n%O%n%X %A %C %X\""
       "}"));
   region_data.insert(std::make_pair("CK", "{"
       "\"name\":\"COOK ISLANDS\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("CL", "{"
       "\"name\":\"CHILE\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C%n%S\","
       "\"state_name_type\":\"state\""
       "}"));
   region_data.insert(std::make_pair("CM", "{"
-      "\"name\":\"CAMEROON\""
+      "\"name\":\"CAMEROON\","
+      "\"input_languages\":\"en~fr\""
       "}"));
   region_data.insert(std::make_pair("CN", "{"
       "\"name\":\"P.R. CHINA\","
       "\"lang\":\"zh-hans\","
       "\"languages\":\"zh-hans\","
+      "\"input_languages\":\"zh\","
       "\"fmt\":\"%Z%n%S%C%D%n%A%n%O%n%N\","
+      "\"lfmt\":\"%N%n%O%n%A, %D%n%C%n%S, %Z\","
       "\"require\":\"ACSZ\""
       "}"));
   region_data.insert(std::make_pair("CO", "{"
       "\"name\":\"COLOMBIA\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %S\""
       "}"));
   region_data.insert(std::make_pair("CR", "{"
       "\"name\":\"COSTA RICA\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("CS", "{"
@@ -268,89 +317,110 @@
       "\"name\":\"CAPE VERDE\","
       "\"lang\":\"pt\","
       "\"languages\":\"pt\","
+      "\"input_languages\":\"pt\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C%n%S\","
       "\"state_name_type\":\"island\""
       "}"));
   region_data.insert(std::make_pair("CX", "{"
       "\"name\":\"CHRISTMAS ISLAND\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%O%n%N%n%A%n%C %S %Z\""
       "}"));
   region_data.insert(std::make_pair("CY", "{"
       "\"name\":\"CYPRUS\","
+      "\"input_languages\":\"el~tr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("CZ", "{"
       "\"name\":\"CZECH REP.\","
+      "\"input_languages\":\"cs\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("DE", "{"
       "\"name\":\"GERMANY\","
+      "\"input_languages\":\"de\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("DJ", "{"
-      "\"name\":\"DJIBOUTI\""
+      "\"name\":\"DJIBOUTI\","
+      "\"input_languages\":\"ar~fr\""
       "}"));
   region_data.insert(std::make_pair("DK", "{"
       "\"name\":\"DENMARK\","
+      "\"input_languages\":\"da\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("DM", "{"
-      "\"name\":\"DOMINICA\""
+      "\"name\":\"DOMINICA\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("DO", "{"
       "\"name\":\"DOMINICAN REP.\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("DZ", "{"
       "\"name\":\"ALGERIA\","
+      "\"input_languages\":\"ar~fr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("EC", "{"
       "\"name\":\"ECUADOR\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z%n%C\""
       "}"));
   region_data.insert(std::make_pair("EE", "{"
       "\"name\":\"ESTONIA\","
+      "\"input_languages\":\"et\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("EG", "{"
       "\"name\":\"EGYPT\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%S%n%Z\""
       "}"));
   region_data.insert(std::make_pair("EH", "{"
-      "\"name\":\"WESTERN SAHARA\""
+      "\"name\":\"WESTERN SAHARA\","
+      "\"input_languages\":\"ar\""
       "}"));
   region_data.insert(std::make_pair("ER", "{"
-      "\"name\":\"ERITREA\""
+      "\"name\":\"ERITREA\","
+      "\"input_languages\":\"ar~en~ti\""
       "}"));
   region_data.insert(std::make_pair("ES", "{"
       "\"name\":\"SPAIN\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C %S\","
       "\"require\":\"ACSZ\""
       "}"));
   region_data.insert(std::make_pair("ET", "{"
       "\"name\":\"ETHIOPIA\","
+      "\"input_languages\":\"am\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("FI", "{"
       "\"name\":\"FINLAND\","
+      "\"input_languages\":\"fi~sv\","
       "\"fmt\":\"%O%n%N%n%A%nFI-%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("FJ", "{"
-      "\"name\":\"FIJI\""
+      "\"name\":\"FIJI\","
+      "\"input_languages\":\"en~fj\""
       "}"));
   region_data.insert(std::make_pair("FK", "{"
       "\"name\":\"FALKLAND ISLANDS (MALVINAS)\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("FM", "{"
       "\"name\":\"MICRONESIA (Federated State of)\","
+      "\"input_languages\":\"chk~en~kos~pon~uli~yap\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -358,69 +428,85 @@
       "}"));
   region_data.insert(std::make_pair("FO", "{"
       "\"name\":\"FAROE ISLANDS\","
+      "\"input_languages\":\"fo\","
       "\"fmt\":\"%N%n%O%n%A%nFO%Z %C\""
       "}"));
   region_data.insert(std::make_pair("FR", "{"
       "\"name\":\"FRANCE\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("GA", "{"
-      "\"name\":\"GABON\""
+      "\"name\":\"GABON\","
+      "\"input_languages\":\"fr\""
       "}"));
   region_data.insert(std::make_pair("GB", "{"
       "\"name\":\"UNITED KINGDOM\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%S%n%Z\","
       "\"require\":\"ACZ\","
       "\"state_name_type\":\"county\""
       "}"));
   region_data.insert(std::make_pair("GD", "{"
-      "\"name\":\"GRENADA (WEST INDIES)\""
+      "\"name\":\"GRENADA (WEST INDIES)\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("GE", "{"
       "\"name\":\"GEORGIA\","
+      "\"input_languages\":\"ka\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("GF", "{"
       "\"name\":\"FRENCH GUIANA\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("GG", "{"
       "\"name\":\"CHANNEL ISLANDS\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%nGUERNSEY%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("GH", "{"
-      "\"name\":\"GHANA\""
+      "\"name\":\"GHANA\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("GI", "{"
       "\"name\":\"GIBRALTAR\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A\","
       "\"require\":\"A\""
       "}"));
   region_data.insert(std::make_pair("GL", "{"
       "\"name\":\"GREENLAND\","
+      "\"input_languages\":\"da~kl\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("GM", "{"
-      "\"name\":\"GAMBIA\""
+      "\"name\":\"GAMBIA\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("GN", "{"
       "\"name\":\"GUINEA\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%N%n%O%n%Z %A %C\""
       "}"));
   region_data.insert(std::make_pair("GP", "{"
       "\"name\":\"GUADELOUPE\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("GQ", "{"
-      "\"name\":\"EQUATORIAL GUINEA\""
+      "\"name\":\"EQUATORIAL GUINEA\","
+      "\"input_languages\":\"es~fr\""
       "}"));
   region_data.insert(std::make_pair("GR", "{"
       "\"name\":\"GREECE\","
+      "\"input_languages\":\"el\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
@@ -431,10 +517,12 @@
       "}"));
   region_data.insert(std::make_pair("GT", "{"
       "\"name\":\"GUATEMALA\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z- %C\""
       "}"));
   region_data.insert(std::make_pair("GU", "{"
       "\"name\":\"GUAM\","
+      "\"input_languages\":\"ch~en\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -442,16 +530,20 @@
       "}"));
   region_data.insert(std::make_pair("GW", "{"
       "\"name\":\"GUINEA-BISSAU\","
+      "\"input_languages\":\"pt\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("GY", "{"
-      "\"name\":\"GUYANA\""
+      "\"name\":\"GUYANA\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("HK", "{"
       "\"name\":\"HONG KONG\","
       "\"lang\":\"zh\","
       "\"languages\":\"zh\","
+      "\"input_languages\":\"en~zh\","
       "\"fmt\":\"%S%n%A%n%O%n%N\","
+      "\"lfmt\":\"%N%n%O%n%A%n%S\","
       "\"require\":\"AS\","
       "\"state_name_type\":\"area\""
       "}"));
@@ -461,38 +553,46 @@
       "}"));
   region_data.insert(std::make_pair("HN", "{"
       "\"name\":\"HONDURAS\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %S%n%Z\","
       "\"require\":\"ACS\""
       "}"));
   region_data.insert(std::make_pair("HR", "{"
       "\"name\":\"CROATIA\","
+      "\"input_languages\":\"hr\","
       "\"fmt\":\"%N%n%O%n%A%nHR-%Z %C\""
       "}"));
   region_data.insert(std::make_pair("HT", "{"
       "\"name\":\"HAITI\","
+      "\"input_languages\":\"fr~ht\","
       "\"fmt\":\"%N%n%O%n%A%nHT%Z %C %X\""
       "}"));
   region_data.insert(std::make_pair("HU", "{"
       "\"name\":\"HUNGARY (Rep.)\","
+      "\"input_languages\":\"hu\","
       "\"fmt\":\"%N%n%O%n%C%n%A%n%Z\""
       "}"));
   region_data.insert(std::make_pair("ID", "{"
       "\"name\":\"INDONESIA\","
+      "\"input_languages\":\"id~su\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z%n%S\""
       "}"));
   region_data.insert(std::make_pair("IE", "{"
       "\"name\":\"IRELAND\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en~ga\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%S\","
       "\"state_name_type\":\"county\""
       "}"));
   region_data.insert(std::make_pair("IL", "{"
       "\"name\":\"ISRAEL\","
+      "\"input_languages\":\"ar~he\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("IM", "{"
       "\"name\":\"ISLE OF MAN\","
+      "\"input_languages\":\"en~gv\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
@@ -500,33 +600,39 @@
       "\"name\":\"INDIA\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en~hi\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z%n%S\","
       "\"require\":\"ACSZ\","
       "\"state_name_type\":\"state\""
       "}"));
   region_data.insert(std::make_pair("IO", "{"
       "\"name\":\"BRITISH INDIAN OCEAN TERRITORY\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("IQ", "{"
       "\"name\":\"IRAQ\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%O%n%N%n%A%n%C, %S%n%Z\","
       "\"require\":\"ACS\""
       "}"));
   region_data.insert(std::make_pair("IS", "{"
       "\"name\":\"ICELAND\","
+      "\"input_languages\":\"is\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("IT", "{"
       "\"name\":\"ITALY\","
       "\"lang\":\"it\","
       "\"languages\":\"it\","
+      "\"input_languages\":\"it\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C %S\","
       "\"require\":\"ACSZ\""
       "}"));
   region_data.insert(std::make_pair("JE", "{"
       "\"name\":\"CHANNEL ISLANDS\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%nJERSEY%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
@@ -534,46 +640,56 @@
       "\"name\":\"JAMAICA\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%S %X\","
       "\"require\":\"ACS\","
       "\"state_name_type\":\"parish\""
       "}"));
   region_data.insert(std::make_pair("JO", "{"
       "\"name\":\"JORDAN\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("JP", "{"
       "\"name\":\"JAPAN\","
       "\"lang\":\"ja\","
       "\"languages\":\"ja\","
+      "\"input_languages\":\"ja\","
       "\"fmt\":\"\xE3\x80\x92%Z%n%S%C%n%A%n%O%n%N\","  // \xE3\x80\x92 is 〒.
+      "\"lfmt\":\"%N%n%O%n%A%n%C, %S%n%Z\","
       "\"require\":\"ACSZ\","
       "\"state_name_type\":\"prefecture\""
       "}"));
   region_data.insert(std::make_pair("KE", "{"
       "\"name\":\"KENYA\","
+      "\"input_languages\":\"en~sw\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%Z\""
       "}"));
   region_data.insert(std::make_pair("KG", "{"
       "\"name\":\"KYRGYZSTAN\","
+      "\"input_languages\":\"ky~ru\","
       "\"fmt\":\"%Z %C %X%n%A%n%O%n%N\""
       "}"));
   region_data.insert(std::make_pair("KH", "{"
       "\"name\":\"CAMBODIA\","
+      "\"input_languages\":\"km\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("KI", "{"
       "\"name\":\"KIRIBATI\","
+      "\"input_languages\":\"en~gil\","
       "\"fmt\":\"%N%n%O%n%A%n%S%n%C\","
       "\"state_name_type\":\"island\""
       "}"));
   region_data.insert(std::make_pair("KM", "{"
-      "\"name\":\"COMOROS\""
+      "\"name\":\"COMOROS\","
+      "\"input_languages\":\"ar~fr~zdj\""
       "}"));
   region_data.insert(std::make_pair("KN", "{"
       "\"name\":\"SAINT KITTS AND NEVIS\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %S\","
       "\"require\":\"ACS\","
       "\"state_name_type\":\"island\""
@@ -582,97 +698,120 @@
       "\"name\":\"KOREA (REP.)\","
       "\"lang\":\"ko\","
       "\"languages\":\"ko\","
+      "\"input_languages\":\"ko\","
       "\"fmt\":\"%S %C%D%n%A%n%O%n%N%nSEOUL %Z\","
+      "\"lfmt\":\"%N%n%O%n%A%n%D%n%C%n%S%nSEOUL %Z\","
       "\"require\":\"ACSZ\","
       "\"state_name_type\":\"do_si\""
       "}"));
   region_data.insert(std::make_pair("KW", "{"
       "\"name\":\"KUWAIT\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("KY", "{"
       "\"name\":\"CAYMAN ISLANDS\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%S\","
       "\"require\":\"AS\","
       "\"state_name_type\":\"island\""
       "}"));
   region_data.insert(std::make_pair("KZ", "{"
       "\"name\":\"KAZAKHSTAN\","
+      "\"input_languages\":\"kk~ru\","
       "\"fmt\":\"%Z%n%S%n%C%n%A%n%O%n%N\""
       "}"));
   region_data.insert(std::make_pair("LA", "{"
       "\"name\":\"LAO (PEOPLE'S DEM. REP.)\","
+      "\"input_languages\":\"lo\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("LB", "{"
       "\"name\":\"LEBANON\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("LC", "{"
-      "\"name\":\"SAINT LUCIA\""
+      "\"name\":\"SAINT LUCIA\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("LI", "{"
       "\"name\":\"LIECHTENSTEIN\","
+      "\"input_languages\":\"de~gsw\","
       "\"fmt\":\"%O%n%N%n%A%nFL-%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("LK", "{"
       "\"name\":\"SRI LANKA\","
+      "\"input_languages\":\"si~ta\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%Z\""
       "}"));
   region_data.insert(std::make_pair("LR", "{"
       "\"name\":\"LIBERIA\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C %X\""
       "}"));
   region_data.insert(std::make_pair("LS", "{"
       "\"name\":\"LESOTHO\","
+      "\"input_languages\":\"en~st\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("LT", "{"
       "\"name\":\"LITHUANIA\","
+      "\"input_languages\":\"lt\","
       "\"fmt\":\"%O%n%N%n%A%nLT-%Z %C\""
       "}"));
   region_data.insert(std::make_pair("LU", "{"
       "\"name\":\"LUXEMBOURG\","
+      "\"input_languages\":\"de~fr~lb\","
       "\"fmt\":\"%O%n%N%n%A%nL-%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("LV", "{"
       "\"name\":\"LATVIA\","
+      "\"input_languages\":\"lv\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %Z\""
       "}"));
   region_data.insert(std::make_pair("LY", "{"
-      "\"name\":\"LIBYA\""
+      "\"name\":\"LIBYA\","
+      "\"input_languages\":\"ar\""
       "}"));
   region_data.insert(std::make_pair("MA", "{"
       "\"name\":\"MOROCCO\","
+      "\"input_languages\":\"ar~fr~tzm\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("MC", "{"
       "\"name\":\"MONACO\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%N%n%O%n%A%nMC-%Z %C %X\""
       "}"));
   region_data.insert(std::make_pair("MD", "{"
       "\"name\":\"Rep. MOLDOVA\","
+      "\"input_languages\":\"ro\","
       "\"fmt\":\"%N%n%O%n%A%nMD-%Z %C\""
       "}"));
   region_data.insert(std::make_pair("ME", "{"
       "\"name\":\"MONTENEGRO\","
+      "\"input_languages\":\"sr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("MF", "{"
       "\"name\":\"SAINT MARTIN\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("MG", "{"
       "\"name\":\"MADAGASCAR\","
+      "\"input_languages\":\"en~fr~mg\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("MH", "{"
       "\"name\":\"MARSHALL ISLANDS\","
+      "\"input_languages\":\"en~mh\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -680,24 +819,30 @@
       "}"));
   region_data.insert(std::make_pair("MK", "{"
       "\"name\":\"MACEDONIA\","
+      "\"input_languages\":\"mk~sq\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("ML", "{"
-      "\"name\":\"MALI\""
+      "\"name\":\"MALI\","
+      "\"input_languages\":\"fr\""
       "}"));
   region_data.insert(std::make_pair("MN", "{"
       "\"name\":\"MONGOLIA\","
+      "\"input_languages\":\"mn\","
       "\"fmt\":\"%N%n%O%n%A%n%S %C-%X%n%Z\""
       "}"));
   region_data.insert(std::make_pair("MO", "{"
       "\"name\":\"MACAO\","
       "\"lang\":\"zh-hant\","
       "\"languages\":\"zh-hant\","
+      "\"input_languages\":\"pt~zh\","
       "\"fmt\":\"%A%n%O%n%N\","
+      "\"lfmt\":\"%N%n%O%n%A\","
       "\"require\":\"A\""
       "}"));
   region_data.insert(std::make_pair("MP", "{"
       "\"name\":\"NORTHERN MARIANA ISLANDS\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -705,35 +850,43 @@
       "}"));
   region_data.insert(std::make_pair("MQ", "{"
       "\"name\":\"MARTINIQUE\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("MR", "{"
-      "\"name\":\"MAURITANIA\""
+      "\"name\":\"MAURITANIA\","
+      "\"input_languages\":\"ar\""
       "}"));
   region_data.insert(std::make_pair("MS", "{"
-      "\"name\":\"MONTSERRAT\""
+      "\"name\":\"MONTSERRAT\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("MT", "{"
       "\"name\":\"MALTA\","
+      "\"input_languages\":\"en~mt\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("MU", "{"
       "\"name\":\"MAURITIUS\","
+      "\"input_languages\":\"en~fr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z%n%C\""
       "}"));
   region_data.insert(std::make_pair("MV", "{"
       "\"name\":\"MALDIVES\","
+      "\"input_languages\":\"dv\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("MW", "{"
       "\"name\":\"MALAWI\","
+      "\"input_languages\":\"en~ny\","
       "\"fmt\":\"%N%n%O%n%A%n%C %X\""
       "}"));
   region_data.insert(std::make_pair("MX", "{"
       "\"name\":\"MEXICO\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C, %S\","
       "\"require\":\"ACZ\","
       "\"state_name_type\":\"state\""
@@ -742,34 +895,41 @@
       "\"name\":\"MALAYSIA\","
       "\"lang\":\"ms\","
       "\"languages\":\"ms\","
+      "\"input_languages\":\"ms\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C, %S\","
       "\"require\":\"ACZ\","
       "\"state_name_type\":\"state\""
       "}"));
   region_data.insert(std::make_pair("MZ", "{"
       "\"name\":\"MOZAMBIQUE\","
+      "\"input_languages\":\"pt\","
       "\"fmt\":\"%N%n%O%n%A%n%C\""
       "}"));
   region_data.insert(std::make_pair("NA", "{"
-      "\"name\":\"NAMIBIA\""
+      "\"name\":\"NAMIBIA\","
+      "\"input_languages\":\"af~en\""
       "}"));
   region_data.insert(std::make_pair("NC", "{"
       "\"name\":\"NEW CALEDONIA\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("NE", "{"
       "\"name\":\"NIGER\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("NF", "{"
       "\"name\":\"NORFOLK ISLAND\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%O%n%N%n%A%n%C %S %Z\""
       "}"));
   region_data.insert(std::make_pair("NG", "{"
       "\"name\":\"NIGERIA\","
       "\"lang\":\"fr\","
       "\"languages\":\"fr\","
+      "\"input_languages\":\"efi~en~ha~ig~yo\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z%n%S\","
       "\"state_name_type\":\"state\""
       "}"));
@@ -777,101 +937,122 @@
       "\"name\":\"NICARAGUA\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z%n%C, %S\","
       "\"state_name_type\":\"department\""
       "}"));
   region_data.insert(std::make_pair("NL", "{"
       "\"name\":\"NETHERLANDS\","
+      "\"input_languages\":\"nl\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("NO", "{"
       "\"name\":\"NORWAY\","
+      "\"input_languages\":\"nb~nn\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("NP", "{"
       "\"name\":\"NEPAL\","
+      "\"input_languages\":\"ne\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("NR", "{"
       "\"name\":\"NAURU CENTRAL PACIFIC\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en~na\","
       "\"fmt\":\"%N%n%O%n%A%n%S\","
       "\"require\":\"AS\","
       "\"state_name_type\":\"district\""
       "}"));
   region_data.insert(std::make_pair("NU", "{"
-      "\"name\":\"NIUE\""
+      "\"name\":\"NIUE\","
+      "\"input_languages\":\"en~niu\""
       "}"));
   region_data.insert(std::make_pair("NZ", "{"
       "\"name\":\"NEW ZEALAND\","
+      "\"input_languages\":\"en~mi\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("OM", "{"
       "\"name\":\"OMAN\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%Z%n%C\""
       "}"));
   region_data.insert(std::make_pair("PA", "{"
       "\"name\":\"PANAMA (REP.)\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%S\""
       "}"));
   region_data.insert(std::make_pair("PE", "{"
-      "\"name\":\"PERU\""
+      "\"name\":\"PERU\","
+      "\"input_languages\":\"es~qu\""
       "}"));
   region_data.insert(std::make_pair("PF", "{"
       "\"name\":\"FRENCH POLYNESIA\","
+      "\"input_languages\":\"fr~ty\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C %S\","
       "\"require\":\"ACSZ\","
       "\"state_name_type\":\"island\""
       "}"));
   region_data.insert(std::make_pair("PG", "{"
       "\"name\":\"PAPUA NEW GUINEA\","
+      "\"input_languages\":\"en~ho~tpi\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z %S\","
       "\"require\":\"ACS\""
       "}"));
   region_data.insert(std::make_pair("PH", "{"
       "\"name\":\"PHILIPPINES\","
+      "\"input_languages\":\"en~fil\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C%n%S\","
       "\"require\":\"AC\""
       "}"));
   region_data.insert(std::make_pair("PK", "{"
       "\"name\":\"PAKISTAN\","
+      "\"input_languages\":\"en~ur\","
       "\"fmt\":\"%N%n%O%n%A%n%C-%Z\""
       "}"));
   region_data.insert(std::make_pair("PL", "{"
       "\"name\":\"POLAND\","
+      "\"input_languages\":\"pl\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("PM", "{"
       "\"name\":\"ST. PIERRE AND MIQUELON\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("PN", "{"
       "\"name\":\"PITCAIRN\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("PR", "{"
       "\"name\":\"PUERTO RICO\","
+      "\"input_languages\":\"en~es\","
       "\"fmt\":\"%N%n%O%n%A%n%C PR %Z\","
       "\"require\":\"ACZ\","
       "\"zip_name_type\":\"zip\""
       "}"));
   region_data.insert(std::make_pair("PS", "{"
-      "\"name\":\"PALESTINIAN TERRITORY\""
+      "\"name\":\"PALESTINIAN TERRITORY\","
+      "\"input_languages\":\"ar\""
       "}"));
   region_data.insert(std::make_pair("PT", "{"
       "\"name\":\"PORTUGAL\","
+      "\"input_languages\":\"pt\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("PW", "{"
       "\"name\":\"PALAU\","
+      "\"input_languages\":\"en~pau\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -879,88 +1060,108 @@
       "}"));
   region_data.insert(std::make_pair("PY", "{"
       "\"name\":\"PARAGUAY\","
+      "\"input_languages\":\"es~gn\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("QA", "{"
-      "\"name\":\"QATAR\""
+      "\"name\":\"QATAR\","
+      "\"input_languages\":\"ar\""
       "}"));
   region_data.insert(std::make_pair("RE", "{"
       "\"name\":\"REUNION\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("RO", "{"
       "\"name\":\"ROMANIA\","
+      "\"input_languages\":\"ro\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("RS", "{"
       "\"name\":\"REPUBLIC OF SERBIA\","
+      "\"input_languages\":\"sr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("RU", "{"
       "\"name\":\"RUSSIAN FEDERATION\","
+      "\"input_languages\":\"ru\","
       "\"fmt\":\"%Z %C  %n%A%n%O%n%N\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("RW", "{"
-      "\"name\":\"RWANDA\""
+      "\"name\":\"RWANDA\","
+      "\"input_languages\":\"en~fr~rw\""
       "}"));
   region_data.insert(std::make_pair("SA", "{"
       "\"name\":\"SAUDI ARABIA\","
+      "\"input_languages\":\"ar\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z\""
       "}"));
   region_data.insert(std::make_pair("SB", "{"
-      "\"name\":\"SOLOMON ISLANDS\""
+      "\"name\":\"SOLOMON ISLANDS\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("SC", "{"
       "\"name\":\"SEYCHELLES\","
+      "\"input_languages\":\"en~fr\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%S\","
       "\"state_name_type\":\"island\""
       "}"));
   region_data.insert(std::make_pair("SE", "{"
       "\"name\":\"SWEDEN\","
+      "\"input_languages\":\"sv\","
       "\"fmt\":\"%O%n%N%n%A%nSE-%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("SG", "{"
       "\"name\":\"REP. OF SINGAPORE\","
+      "\"input_languages\":\"en~ms~ta~zh\","
       "\"fmt\":\"%N%n%O%n%A%nSINGAPORE %Z\","
       "\"require\":\"AZ\""
       "}"));
   region_data.insert(std::make_pair("SH", "{"
       "\"name\":\"SAINT HELENA\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("SI", "{"
       "\"name\":\"SLOVENIA\","
+      "\"input_languages\":\"sl\","
       "\"fmt\":\"%N%n%O%n%A%nSI- %Z %C\""
       "}"));
   region_data.insert(std::make_pair("SJ", "{"
       "\"name\":\"SVALBARD AND JAN MAYEN ISLANDS\","
+      "\"input_languages\":\"nb\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("SK", "{"
       "\"name\":\"SLOVAKIA\","
+      "\"input_languages\":\"sk\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("SL", "{"
-      "\"name\":\"SIERRA LEONE\""
+      "\"name\":\"SIERRA LEONE\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("SM", "{"
       "\"name\":\"SAN MARINO\","
+      "\"input_languages\":\"it\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"AZ\""
       "}"));
   region_data.insert(std::make_pair("SN", "{"
       "\"name\":\"SENEGAL\","
+      "\"input_languages\":\"fr~wo\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("SO", "{"
       "\"name\":\"SOMALIA\","
       "\"lang\":\"so\","
       "\"languages\":\"so\","
+      "\"input_languages\":\"ar~so\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %S %Z\","
       "\"require\":\"ACS\""
       "}"));
@@ -968,76 +1169,94 @@
       "\"name\":\"SURINAME\","
       "\"lang\":\"nl\","
       "\"languages\":\"nl\","
+      "\"input_languages\":\"nl\","
       "\"fmt\":\"%N%n%O%n%A%n%C %X%n%S\""
       "}"));
   region_data.insert(std::make_pair("ST", "{"
       "\"name\":\"SAO TOME AND PRINCIPE\","
+      "\"input_languages\":\"pt\","
       "\"fmt\":\"%N%n%O%n%A%n%C %X\""
       "}"));
   region_data.insert(std::make_pair("SV", "{"
       "\"name\":\"EL SALVADOR\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z-%C%n%S\","
       "\"require\":\"ACS\""
       "}"));
   region_data.insert(std::make_pair("SZ", "{"
       "\"name\":\"SWAZILAND\","
+      "\"input_languages\":\"en~ss\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%Z\""
       "}"));
   region_data.insert(std::make_pair("TC", "{"
       "\"name\":\"TURKS AND CAICOS ISLANDS\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("TD", "{"
-      "\"name\":\"CHAD\""
+      "\"name\":\"CHAD\","
+      "\"input_languages\":\"ar~fr\""
       "}"));
   region_data.insert(std::make_pair("TF", "{"
       "\"name\":\"FRENCH SOUTHERN TERRITORIES\""
       "}"));
   region_data.insert(std::make_pair("TG", "{"
-      "\"name\":\"TOGO\""
+      "\"name\":\"TOGO\","
+      "\"input_languages\":\"fr\""
       "}"));
   region_data.insert(std::make_pair("TH", "{"
       "\"name\":\"THAILAND\","
       "\"lang\":\"th\","
       "\"languages\":\"th\","
-      "\"fmt\":\"%N%n%O%n%A%n%C%n%S %Z\""
+      "\"input_languages\":\"th\","
+      "\"fmt\":\"%N%n%O%n%A%n%C%n%S %Z\","
+      "\"lfmt\":\"%N%n%O%n%A%n%C%n%S %Z\""
       "}"));
   region_data.insert(std::make_pair("TJ", "{"
       "\"name\":\"TAJIKISTAN\","
+      "\"input_languages\":\"tg\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("TK", "{"
-      "\"name\":\"TOKELAU\""
+      "\"name\":\"TOKELAU\","
+      "\"input_languages\":\"en~tkl\""
       "}"));
   region_data.insert(std::make_pair("TL", "{"
-      "\"name\":\"TIMOR-LESTE\""
+      "\"name\":\"TIMOR-LESTE\","
+      "\"input_languages\":\"pt~tet\""
       "}"));
   region_data.insert(std::make_pair("TM", "{"
       "\"name\":\"TURKMENISTAN\","
+      "\"input_languages\":\"tk\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("TN", "{"
       "\"name\":\"TUNISIA\","
+      "\"input_languages\":\"ar~fr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("TO", "{"
-      "\"name\":\"TONGA\""
+      "\"name\":\"TONGA\","
+      "\"input_languages\":\"en~to\""
       "}"));
   region_data.insert(std::make_pair("TR", "{"
       "\"name\":\"TURKEY\","
+      "\"input_languages\":\"tr\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C/%S\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("TT", "{"
-      "\"name\":\"TRINIDAD AND TOBAGO\""
+      "\"name\":\"TRINIDAD AND TOBAGO\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("TV", "{"
       "\"name\":\"TUVALU\","
       "\"lang\":\"tyv\","
       "\"languages\":\"tyv\","
+      "\"input_languages\":\"en~tvl\","
       "\"fmt\":\"%N%n%O%n%A%n%X%n%C%n%S\","
       "\"state_name_type\":\"island\""
       "}"));
@@ -1045,24 +1264,30 @@
       "\"name\":\"TAIWAN\","
       "\"lang\":\"zh-hant\","
       "\"languages\":\"zh-hant\","
+      "\"input_languages\":\"zh\","
       "\"fmt\":\"%Z%n%S%C%n%A%n%O%n%N\","
+      "\"lfmt\":\"%N%n%O%n%A%n%C, %S %Z\","
       "\"require\":\"ACSZ\","
       "\"state_name_type\":\"county\""
       "}"));
   region_data.insert(std::make_pair("TZ", "{"
-      "\"name\":\"TANZANIA (UNITED REP.)\""
+      "\"name\":\"TANZANIA (UNITED REP.)\","
+      "\"input_languages\":\"en~sw\""
       "}"));
   region_data.insert(std::make_pair("UA", "{"
       "\"name\":\"UKRAINE\","
+      "\"input_languages\":\"ru~uk\","
       "\"fmt\":\"%Z %C%n%A%n%O%n%N\""
       "}"));
   region_data.insert(std::make_pair("UG", "{"
-      "\"name\":\"UGANDA\""
+      "\"name\":\"UGANDA\","
+      "\"input_languages\":\"en~sw\""
       "}"));
   // NOTE: The fmt value for UM and US differs from the i18napis fmt by the
   // insertion of a comma separating city and state.
   region_data.insert(std::make_pair("UM", "{"
       "\"name\":\"UNITED STATES MINOR OUTLYING ISLANDS\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %S %Z\","
       "\"require\":\"ACS\","
       "\"zip_name_type\":\"zip\","
@@ -1072,6 +1297,7 @@
       "\"name\":\"UNITED STATES\","
       "\"lang\":\"en\","
       "\"languages\":\"en\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C, %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -1081,32 +1307,39 @@
       "\"name\":\"URUGUAY\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C %S\""
       "}"));
   region_data.insert(std::make_pair("UZ", "{"
       "\"name\":\"UZBEKISTAN\","
+      "\"input_languages\":\"uz\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C%n%S\""
       "}"));
   region_data.insert(std::make_pair("VA", "{"
       "\"name\":\"VATICAN\","
+      "\"input_languages\":\"la\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\""
       "}"));
   region_data.insert(std::make_pair("VC", "{"
-      "\"name\":\"SAINT VINCENT AND THE GRENADINES (ANTILLES)\""
+      "\"name\":\"SAINT VINCENT AND THE GRENADINES (ANTILLES)\","
+      "\"input_languages\":\"en\""
       "}"));
   region_data.insert(std::make_pair("VE", "{"
       "\"name\":\"VENEZUELA\","
       "\"lang\":\"es\","
       "\"languages\":\"es\","
+      "\"input_languages\":\"es\","
       "\"fmt\":\"%N%n%O%n%A%n%C %Z, %S\","
       "\"require\":\"ACS\""
       "}"));
   region_data.insert(std::make_pair("VG", "{"
       "\"name\":\"VIRGIN ISLANDS (BRITISH)\","
+      "\"input_languages\":\"en\","
       "\"require\":\"A\""
       "}"));
   region_data.insert(std::make_pair("VI", "{"
       "\"name\":\"VIRGIN ISLANDS (U.S.)\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%C %S %Z\","
       "\"require\":\"ACSZ\","
       "\"zip_name_type\":\"zip\","
@@ -1116,41 +1349,51 @@
       "\"name\":\"VIET NAM\","
       "\"lang\":\"vi\","
       "\"languages\":\"vi\","
+      "\"input_languages\":\"vi\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%S\","
+      "\"lfmt\":\"%N%n%O%n%A%n%C%n%S\","
       "\"require\":\"AC\""
       "}"));
   region_data.insert(std::make_pair("VU", "{"
-      "\"name\":\"VANUATU\""
+      "\"name\":\"VANUATU\","
+      "\"input_languages\":\"bi~en~fr\""
       "}"));
   region_data.insert(std::make_pair("WF", "{"
       "\"name\":\"WALLIS AND FUTUNA ISLANDS\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("WS", "{"
-      "\"name\":\"SAMOA\""
+      "\"name\":\"SAMOA\","
+      "\"input_languages\":\"en~sm\""
       "}"));
   region_data.insert(std::make_pair("YE", "{"
       "\"name\":\"YEMEN\","
+      "\"input_languages\":\"ar\","
       "\"require\":\"AC\""
       "}"));
   region_data.insert(std::make_pair("YT", "{"
       "\"name\":\"MAYOTTE\","
+      "\"input_languages\":\"fr\","
       "\"fmt\":\"%O%n%N%n%A%n%Z %C %X\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("ZA", "{"
       "\"name\":\"SOUTH AFRICA\","
+      "\"input_languages\":\"af~en~nr~nso~ss~st~tn~ts~ve~xh~zu\","
       "\"fmt\":\"%N%n%O%n%A%n%C%n%Z\","
       "\"require\":\"ACZ\""
       "}"));
   region_data.insert(std::make_pair("ZM", "{"
       "\"name\":\"ZAMBIA\","
+      "\"input_languages\":\"en\","
       "\"fmt\":\"%N%n%O%n%A%n%Z %C\","
       "\"require\":\"AC\""
       "}"));
   region_data.insert(std::make_pair("ZW", "{"
-      "\"name\":\"ZIMBABWE\""
+      "\"name\":\"ZIMBABWE\","
+      "\"input_languages\":\"en~nd~sn\""
       "}"));
   return region_data;
 }
diff --git a/third_party/libaddressinput/chromium/cpp/src/retriever.cc b/third_party/libaddressinput/chromium/cpp/src/retriever.cc
index 7722ef2..90dfc24 100644
--- a/third_party/libaddressinput/chromium/cpp/src/retriever.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/retriever.cc
@@ -28,9 +28,9 @@
 #include <string>
 
 #include "fallback_data_store.h"
-#include "time_to_string.h"
 #include "util/md5.h"
 #include "util/stl_util.h"
+#include "util/string_util.h"
 
 namespace i18n {
 namespace addressinput {
diff --git a/third_party/libaddressinput/chromium/cpp/src/rule.cc b/third_party/libaddressinput/chromium/cpp/src/rule.cc
index a94e44d..791ac9e 100644
--- a/third_party/libaddressinput/chromium/cpp/src/rule.cc
+++ b/third_party/libaddressinput/chromium/cpp/src/rule.cc
@@ -26,8 +26,7 @@
 #include "grit/libaddressinput_strings.h"
 #include "region_data_constants.h"
 #include "util/json.h"
-#include "util/string_compare.h"
-#include "util/string_split.h"
+#include "util/string_util.h"
 
 namespace i18n {
 namespace addressinput {
@@ -219,11 +218,13 @@
       name_(),
       latin_name_(),
       format_(),
+      latin_format_(),
       required_(),
       sub_keys_(),
       sub_names_(),
       sub_lnames_(),
       languages_(),
+      input_languages_(),
       language_(),
       postal_code_format_(),
       admin_area_name_message_id_(INVALID_MESSAGE_ID),
@@ -250,9 +251,11 @@
   name_ = rule.name_;
   latin_name_ = rule.latin_name_;
   format_ = rule.format_;
+  latin_format_ = rule.latin_format_;
   required_ = rule.required_;
   sub_keys_ = rule.sub_keys_;
   languages_ = rule.languages_;
+  input_languages_ = rule.input_languages_;
   language_ = rule.language_;
   sub_keys_ = rule.sub_keys_;
   sub_names_ = rule.sub_names_;
@@ -291,6 +294,10 @@
     ParseAddressFieldsFormat(value, &format_);
   }
 
+  if (json_rule.GetStringValueForKey("lfmt", &value)) {
+    ParseAddressFieldsFormat(value, &latin_format_);
+  }
+
   if (json_rule.GetStringValueForKey("require", &value)) {
     ParseAddressFieldsRequired(value, &required_);
   }
@@ -316,6 +323,10 @@
     SplitString(value, kSeparator, &languages_);
   }
 
+  if (json_rule.GetStringValueForKey("input_languages", &value)) {
+    SplitString(value, kSeparator, &input_languages_);
+  }
+
   if (json_rule.GetStringValueForKey("lang", &value)) {
     language_.swap(value);
   }
diff --git a/third_party/libaddressinput/chromium/cpp/src/rule.h b/third_party/libaddressinput/chromium/cpp/src/rule.h
index 80cc830..cc0a3d7 100644
--- a/third_party/libaddressinput/chromium/cpp/src/rule.h
+++ b/third_party/libaddressinput/chromium/cpp/src/rule.h
@@ -108,6 +108,12 @@
     return format_;
   }
 
+  // Returns the latinized format of the address as it should appear on an
+  // envelope.
+  const std::vector<std::vector<FormatElement> >& GetLatinFormat() const {
+    return latin_format_;
+  }
+
   // Returns the required fields for this rule.
   const std::vector<AddressField>& GetRequired() const { return required_; }
 
@@ -121,6 +127,12 @@
   // example ["de", "fr", "it"].
   const std::vector<std::string>& GetLanguages() const { return languages_; }
 
+  // Returns all of the languages codes for addresses that adhere to this rule,
+  // for example ["de", "fr", "gsw", "it"].
+  const std::vector<std::string>& GetInputLanguages() const {
+    return input_languages_;
+  }
+
   // Returns the language code of this rule, for example "de".
   const std::string& GetLanguage() const { return language_; }
 
@@ -168,12 +180,14 @@
   std::string name_;
   std::string latin_name_;
   std::vector<std::vector<FormatElement> > format_;
+  std::vector<std::vector<FormatElement> > latin_format_;
   std::vector<AddressField> required_;
   std::vector<std::string> sub_keys_;
   std::vector<std::string> sub_names_;
   // The Latin names (when |sub_names_| is not in Latin characters).
   std::vector<std::string> sub_lnames_;
   std::vector<std::string> languages_;
+  std::vector<std::string> input_languages_;
   std::string language_;
   std::string postal_code_format_;
   int admin_area_name_message_id_;
diff --git a/third_party/libaddressinput/chromium/cpp/src/time_to_string.cc b/third_party/libaddressinput/chromium/cpp/src/time_to_string.cc
deleted file mode 100644
index f1c2097..0000000
--- a/third_party/libaddressinput/chromium/cpp/src/time_to_string.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2014 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "time_to_string.h"
-
-#include <cstdio>
-#include <ctime>
-#include <string>
-
-#ifdef _MSC_VER
-// http://msdn.microsoft.com/en-us/library/2ts7cx93%28v=vs.110%29.aspx
-#define snprintf _snprintf
-#endif  // _MSC_VER
-
-namespace i18n {
-namespace addressinput {
-
-std::string TimeToString(time_t time) {
-  char time_string[2 + 3 * sizeof time];
-  snprintf(time_string, sizeof time_string, "%ld", time);
-  return time_string;
-}
-
-}  // namespace addressinput
-}  // namespace i18n
diff --git a/third_party/libaddressinput/chromium/cpp/src/time_to_string.h b/third_party/libaddressinput/chromium/cpp/src/time_to_string.h
deleted file mode 100644
index ccd7ad9..0000000
--- a/third_party/libaddressinput/chromium/cpp/src/time_to_string.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2014 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef I18N_ADDRESSINPUT_TIME_TO_STRING_H_
-#define I18N_ADDRESSINPUT_TIME_TO_STRING_H_
-
-#include <ctime>
-#include <string>
-
-namespace i18n {
-namespace addressinput {
-
-// Returns |time| serialized into a string.
-std::string TimeToString(time_t time);
-
-}  // namespace addressinput
-}  // namespace i18n
-
-#endif  // I18N_ADDRESSINPUT_TIME_TO_STRING_H_
diff --git a/third_party/libaddressinput/chromium/cpp/src/util/string_compare.cc b/third_party/libaddressinput/chromium/cpp/src/util/string_compare.cc
deleted file mode 100644
index d5f6a18..0000000
--- a/third_party/libaddressinput/chromium/cpp/src/util/string_compare.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2014 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#include "string_compare.h"
-
-#include <libaddressinput/util/scoped_ptr.h>
-
-#include "canonicalize_string.h"
-
-namespace i18n {
-namespace addressinput {
-
-bool LooseStringCompare(const std::string& a, const std::string& b) {
-  scoped_ptr<StringCanonicalizer> canonicalizer(StringCanonicalizer::Build());
-  return canonicalizer->CanonicalizeString(a) ==
-         canonicalizer->CanonicalizeString(b);
-}
-
-}  // namespace addressinput
-}  // namespace i18n
diff --git a/third_party/libaddressinput/chromium/cpp/src/util/string_compare.h b/third_party/libaddressinput/chromium/cpp/src/util/string_compare.h
deleted file mode 100644
index 4e0ecf7..0000000
--- a/third_party/libaddressinput/chromium/cpp/src/util/string_compare.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2014 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-#ifndef I18N_ADDRESSINPUT_UTIL_STRING_COMPARE_H_
-#define I18N_ADDRESSINPUT_UTIL_STRING_COMPARE_H_
-
-#include <string>
-
-namespace i18n {
-namespace addressinput {
-
-// Unicode (UTF-8) approximate string comparison. Designed for matching user
-// input against canonical data. Returns true for a match.
-bool LooseStringCompare(const std::string& a, const std::string& b);
-
-}  // namespace addressinput
-}  // namespace i18n
-
-#endif  // I18N_ADDRESSINPUT_UTIL_STRING_COMPARE_H_
diff --git a/third_party/libaddressinput/chromium/cpp/src/util/string_split.cc b/third_party/libaddressinput/chromium/cpp/src/util/string_split.cc
deleted file mode 100644
index 114cd92..0000000
--- a/third_party/libaddressinput/chromium/cpp/src/util/string_split.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The original source code is from:
-// http://src.chromium.org/viewvc/chrome/trunk/src/base/strings/string_split.cc?revision=216633
-
-#include "string_split.h"
-
-#include <cassert>
-#include <cstddef>
-#include <string>
-#include <vector>
-
-namespace i18n {
-namespace addressinput {
-
-void SplitString(const std::string& str, char s, std::vector<std::string>* r) {
-  assert(r != NULL);
-  r->clear();
-  size_t last = 0;
-  size_t c = str.size();
-  for (size_t i = 0; i <= c; ++i) {
-    if (i == c || str[i] == s) {
-      std::string tmp(str, last, i - last);
-      // Avoid converting an empty or all-whitespace source string into a vector
-      // of one empty string.
-      if (i != c || !r->empty() || !tmp.empty()) {
-        r->push_back(tmp);
-      }
-      last = i + 1;
-    }
-  }
-}
-
-}  // namespace addressinput
-}  // namespace i18n
diff --git a/third_party/libaddressinput/chromium/cpp/src/util/string_split.h b/third_party/libaddressinput/chromium/cpp/src/util/string_split.h
deleted file mode 100644
index 6809296..0000000
--- a/third_party/libaddressinput/chromium/cpp/src/util/string_split.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The original source code is from:
-// http://src.chromium.org/viewvc/chrome/trunk/src/base/strings/string_split.h?revision=236210
-//
-// Modifications from original:
-//   1) Supports only std::string type.
-//   2) Does not trim whitespace.
-
-#ifndef I18N_ADDRESSINPUT_UTIL_STRING_SPLIT_H_
-#define I18N_ADDRESSINPUT_UTIL_STRING_SPLIT_H_
-
-#include <string>
-#include <vector>
-
-namespace i18n {
-namespace addressinput {
-
-// Splits |str| into a vector of strings delimited by |c|, placing the results
-// in |r|. If several instances of |c| are contiguous, or if |str| begins with
-// or ends with |c|, then an empty string is inserted.
-//
-// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which
-// the trailing byte of a multi-byte character can be in the ASCII range.
-// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK.
-// Note: |c| must be in the ASCII range.
-void SplitString(const std::string& str, char c, std::vector<std::string>* r);
-
-}  // namespace addressinput
-}  // namespace i18n
-
-#endif  // I18N_ADDRESSINPUT_UTIL_STRING_SPLIT_H_
diff --git a/third_party/libaddressinput/chromium/cpp/src/util/string_util.cc b/third_party/libaddressinput/chromium/cpp/src/util/string_util.cc
new file mode 100644
index 0000000..ac10b10
--- /dev/null
+++ b/third_party/libaddressinput/chromium/cpp/src/util/string_util.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2014 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "string_util.h"
+
+#include <libaddressinput/util/scoped_ptr.h>
+
+#include <cassert>
+#include <cstddef>
+#include <cstdio>
+#include <ctime>
+#include <string>
+#include <vector>
+
+#include "canonicalize_string.h"
+
+#ifdef _MSC_VER
+// http://msdn.microsoft.com/en-us/library/2ts7cx93%28v=vs.110%29.aspx
+#define snprintf _snprintf
+#endif  // _MSC_VER
+
+namespace i18n {
+namespace addressinput {
+
+std::string NormalizeLanguageCode(const std::string& language_code) {
+  std::string::size_type pos = language_code.find('-');
+  if (pos == std::string::npos) {
+    return language_code;
+  }
+  if (language_code.substr(pos) == "-latn") {
+    return language_code;
+  }
+  return language_code.substr(0, pos);
+}
+
+std::string TimeToString(time_t time) {
+  char time_string[2 + 3 * sizeof time];
+  snprintf(time_string, sizeof time_string, "%ld", time);
+  return time_string;
+}
+
+bool LooseStringCompare(const std::string& a, const std::string& b) {
+  scoped_ptr<StringCanonicalizer> canonicalizer(StringCanonicalizer::Build());
+  return canonicalizer->CanonicalizeString(a) ==
+         canonicalizer->CanonicalizeString(b);
+}
+
+// The original source code is from:
+// http://src.chromium.org/viewvc/chrome/trunk/src/base/strings/string_split.cc?revision=216633
+void SplitString(const std::string& str, char s, std::vector<std::string>* r) {
+  assert(r != NULL);
+  r->clear();
+  size_t last = 0;
+  size_t c = str.size();
+  for (size_t i = 0; i <= c; ++i) {
+    if (i == c || str[i] == s) {
+      std::string tmp(str, last, i - last);
+      // Avoid converting an empty or all-whitespace source string into a vector
+      // of one empty string.
+      if (i != c || !r->empty() || !tmp.empty()) {
+        r->push_back(tmp);
+      }
+      last = i + 1;
+    }
+  }
+}
+
+}  // namespace addressinput
+}  // namespace i18n
diff --git a/third_party/libaddressinput/chromium/cpp/src/util/string_util.h b/third_party/libaddressinput/chromium/cpp/src/util/string_util.h
new file mode 100644
index 0000000..c16636e
--- /dev/null
+++ b/third_party/libaddressinput/chromium/cpp/src/util/string_util.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2014 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef I18N_ADDRESSINPUT_UTIL_STRING_UTIL_H_
+#define I18N_ADDRESSINPUT_UTIL_STRING_UTIL_H_
+
+#include <ctime>
+#include <string>
+#include <vector>
+
+namespace i18n {
+namespace addressinput {
+
+// Removes the language variation from |language_code|, unless the variation is
+// "latn". For example, returns "zh" for "zh-hans". Returns "zh-latn" for
+// "zh-latn".
+std::string NormalizeLanguageCode(const std::string& language_code);
+
+// Returns |time| serialized into a string.
+std::string TimeToString(time_t time);
+
+// Unicode (UTF-8) approximate string comparison. Designed for matching user
+// input against canonical data. Returns true for a match.
+bool LooseStringCompare(const std::string& a, const std::string& b);
+
+// Splits |str| into a vector of strings delimited by |c|, placing the results
+// in |r|. If several instances of |c| are contiguous, or if |str| begins with
+// or ends with |c|, then an empty string is inserted.
+//
+// |str| should not be in a multi-byte encoding like Shift-JIS or GBK in which
+// the trailing byte of a multi-byte character can be in the ASCII range.
+// UTF-8, and other single/multi-byte ASCII-compatible encodings are OK.
+// Note: |c| must be in the ASCII range.
+//
+// The original source code is from:
+// http://src.chromium.org/viewvc/chrome/trunk/src/base/strings/string_split.h?revision=236210
+//
+// Modifications from original:
+//   1) Supports only std::string type.
+//   2) Does not trim whitespace.
+void SplitString(const std::string& str, char c, std::vector<std::string>* r);
+
+}  // namespace addressinput
+}  // namespace i18n
+
+#endif  // I18N_ADDRESSINPUT_UTIL_STRING_UTIL_H_
diff --git a/third_party/libaddressinput/chromium/cpp/test/address_data_test.cc b/third_party/libaddressinput/chromium/cpp/test/address_data_test.cc
index a4d61c3..26659fa 100644
--- a/third_party/libaddressinput/chromium/cpp/test/address_data_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/address_data_test.cc
@@ -85,6 +85,7 @@
 TEST(AddressDataTest, FormatForDisplayJp) {
   AddressData address;
   address.country_code = "JP";
+  address.language_code = "ja";
   address.administrative_area = "東京都";
   address.locality = "渋谷区";
   address.postal_code = "150-8512";
@@ -108,6 +109,33 @@
   EXPECT_EQ(expected, actual);
 }
 
+TEST(AddressDataTest, FormatForDisplayJpLatn) {
+  AddressData address;
+  address.country_code = "JP";
+  address.language_code = "ja-latn";
+  address.administrative_area = "Tokyo";
+  address.locality = "Shibuya-ku";
+  address.postal_code = "150-8512";
+  address.address_lines.push_back("26-1 Sakuragaoka-cho");
+  address.address_lines.push_back("Cerulean Tower 6F");
+  address.organization = "Google Japan Inc.";
+  address.recipient = "Miki Murakami";
+
+  std::vector<std::string> actual;
+  address.FormatForDisplay(&actual);
+
+  std::vector<std::string> expected;
+  expected.push_back(address.recipient);
+  expected.push_back(address.organization);
+  expected.insert(expected.end(),
+                  address.address_lines.begin(),
+                  address.address_lines.end());
+  expected.push_back(address.locality + ", "+ address.administrative_area);
+  expected.push_back(address.postal_code);
+
+  EXPECT_EQ(expected, actual);
+}
+
 TEST(AddressDataTest, FormatForDisplayWithStreetCi) {
   AddressData address;
   address.country_code = "CI";
diff --git a/third_party/libaddressinput/chromium/cpp/test/address_ui_test.cc b/third_party/libaddressinput/chromium/cpp/test/address_ui_test.cc
index 8fa508a..dadd8e7 100644
--- a/third_party/libaddressinput/chromium/cpp/test/address_ui_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/address_ui_test.cc
@@ -75,7 +75,8 @@
   for (size_t i = 0; i < region_codes.size(); ++i) {
     SCOPED_TRACE("Region code: " + region_codes[i]);
     EXPECT_EQ(2U, region_codes[i].size());
-    EXPECT_TRUE(ComponentsAreValid(BuildComponents(region_codes[i])));
+    EXPECT_TRUE(ComponentsAreValid(
+        BuildComponents(region_codes[i], std::string(), NULL)));
     EXPECT_FALSE(GetRequiredFields(region_codes[i]).empty());
   }
 }
@@ -83,7 +84,8 @@
 // Verifies that BuildComponents() and GetRequiredFields() return an empty
 // vector for an invalid region code.
 TEST(AddressUiTest, InvalidRegionCodeReturnsEmptyVector) {
-  EXPECT_TRUE(BuildComponents("INVALID-REGION-CODE").empty());
+  EXPECT_TRUE(
+      BuildComponents("INVALID-REGION-CODE", std::string(), NULL).empty());
   EXPECT_TRUE(GetRequiredFields("INVALID-REGION-CODE").empty());
 }
 
@@ -119,6 +121,53 @@
         SeparatorData("th", " "),
         SeparatorData("en", ", ")));
 
+TEST(AddressUiTest, ComponentLanguageCodeTest) {
+  static const struct LanguageCodeData {
+    const char* region_code;
+    const char* ui_language_code;
+    const char* components_language_code;
+  } kLangugeCodes[] = {
+    {"AM", "", "hy"},
+    {"AM", "hy", "hy"},
+    {"AM", "en", "hy-latn"},
+    {"CN", "zh-hans", "zh-hans"},
+    {"CN", "zh-hant", "zh-hant"},
+    {"CN", "zh", "zh"},
+    {"CN", "zh-latn", "zh-latn"},
+    {"CN", "en", "zh-latn"},
+    {"CN", "ja", "zh-latn"},
+    {"CN", "ko", "zh-latn"},
+    {"HK", "zh", "zh"},
+    {"HK", "zh-hans", "zh-hans"},
+    {"HK", "zh-hant", "zh-hant"},
+    {"HK", "zh-latn", "zh-latn"},
+    {"HK", "en", "en"},
+    {"HK", "fr", "zh-latn"},
+    {"HK", "ja", "zh-latn"},
+    {"HK", "ko", "zh-latn"},
+    {"MO", "zh", "zh"},
+    {"MO", "pt", "pt"},
+    {"MO", "en", "zh-latn"},
+    {"AQ", "en", "en"},
+    {"AQ", "fr", "fr"},
+    {"AQ", "es", "es"},
+    {"AQ", "zh", "zh"}
+  };
+  static const size_t kArraySize =
+      sizeof kLangugeCodes / sizeof (LanguageCodeData);
+  for (size_t i = 0; i < kArraySize; ++i) {
+    SCOPED_TRACE(std::string("region code = ") +
+        kLangugeCodes[i].region_code + ", ui language code = " +
+        kLangugeCodes[i].ui_language_code + ", components language code = " +
+        kLangugeCodes[i].components_language_code);
+    std::string components_language_code;
+    EXPECT_FALSE(BuildComponents(kLangugeCodes[i].region_code,
+                                 kLangugeCodes[i].ui_language_code,
+                                 &components_language_code).empty());
+    EXPECT_EQ(
+        kLangugeCodes[i].components_language_code, components_language_code);
+  }
+}
 
 }  // namespace
 
diff --git a/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc b/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc
index 7b30818..f0d2095 100644
--- a/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/address_validator_test.cc
@@ -242,7 +242,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("CA", suggestions[0].administrative_area);
   EXPECT_EQ("90291", suggestions[0].postal_code);
 }
@@ -257,7 +257,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("Dacun Township", suggestions[0].locality);
   EXPECT_EQ("Changhua County", suggestions[0].administrative_area);
   EXPECT_EQ("515", suggestions[0].postal_code);
@@ -273,7 +273,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("Dacun Township", suggestions[0].locality);
   EXPECT_EQ("Changhua County", suggestions[0].administrative_area);
   EXPECT_EQ("515", suggestions[0].postal_code);
@@ -300,7 +300,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, LOCALITY, 10, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("Anqing Shi", suggestions[0].locality);
   EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
 }
@@ -315,7 +315,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, LOCALITY, 10, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_TRUE(suggestions[0].dependent_locality.empty());
   EXPECT_EQ("Anqing Shi", suggestions[0].locality);
   EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
@@ -331,7 +331,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_TRUE(suggestions[0].dependent_locality.empty());
   EXPECT_TRUE(suggestions[0].locality.empty());
   EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
@@ -347,7 +347,7 @@
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(
                 address, DEPENDENT_LOCALITY, 10, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("Zongyang Xian", suggestions[0].dependent_locality);
   EXPECT_EQ("Anqing Shi", suggestions[0].locality);
   EXPECT_EQ("ANHUI SHENG", suggestions[0].administrative_area);
@@ -387,7 +387,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("CA", suggestions[0].administrative_area);
 }
 
@@ -399,7 +399,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("Texas", suggestions[0].administrative_area);
 }
 
@@ -411,7 +411,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, ADMIN_AREA, 10, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("California", suggestions[0].administrative_area);
 }
 
@@ -449,7 +449,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("강원도", suggestions[0].administrative_area);
   EXPECT_EQ("210-210", suggestions[0].postal_code);
 }
@@ -464,7 +464,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("강원도", suggestions[0].administrative_area);
 }
 
@@ -479,7 +479,7 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("Gangwon", suggestions[0].administrative_area);
   EXPECT_EQ("210-210", suggestions[0].postal_code);
 }
@@ -494,9 +494,67 @@
   std::vector<AddressData> suggestions;
   EXPECT_EQ(AddressValidator::SUCCESS,
             validator_->GetSuggestions(address, ADMIN_AREA, 1, &suggestions));
-  ASSERT_EQ(1, suggestions.size());
+  ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ("Gangwon", suggestions[0].administrative_area);
 }
 
+TEST_F(AddressValidatorTest, NoSuggestionsForEmptyAddress) {
+  AddressData address;
+  address.country_code = "US";
+
+  std::vector<AddressData> suggestions;
+  EXPECT_EQ(
+      AddressValidator::SUCCESS,
+      validator_->GetSuggestions(address, POSTAL_CODE, 999, &suggestions));
+  EXPECT_TRUE(suggestions.empty());
+}
+
+TEST_F(AddressValidatorTest, SuggestionIncludesCountry) {
+  AddressData address;
+  address.country_code = "US";
+  address.postal_code = "90291";
+
+  std::vector<AddressData> suggestions;
+  EXPECT_EQ(AddressValidator::SUCCESS,
+            validator_->GetSuggestions(address, POSTAL_CODE, 1, &suggestions));
+  ASSERT_EQ(1U, suggestions.size());
+  EXPECT_EQ("US", suggestions[0].country_code);
+}
+
+TEST_F(AddressValidatorTest, SuggestOnlyForAdministrativeAreasAndPostalCode) {
+  AddressData address;
+  address.country_code = "US";
+  address.administrative_area = "CA";
+  address.locality = "Los Angeles";
+  address.dependent_locality = "Venice";
+  address.postal_code = "90291";
+  address.sorting_code = "123";
+  address.address_lines.push_back("123 Main St");
+  address.organization = "Google";
+  address.recipient = "Jon Smith";
+
+  // Fields that should not have suggestions in US.
+  static const AddressField kNoSugestFields[] = {
+    COUNTRY,
+    LOCALITY,
+    DEPENDENT_LOCALITY,
+    SORTING_CODE,
+    STREET_ADDRESS,
+    ORGANIZATION,
+    RECIPIENT
+  };
+
+  static const size_t kNumNoSuggestFields =
+      sizeof kNoSugestFields / sizeof (AddressField);
+
+  for (size_t i = 0; i < kNumNoSuggestFields; ++i) {
+    std::vector<AddressData> suggestions;
+    EXPECT_EQ(AddressValidator::SUCCESS,
+              validator_->GetSuggestions(
+                  address, kNoSugestFields[i], 999, &suggestions));
+    EXPECT_TRUE(suggestions.empty());
+  }
+}
+
 }  // namespace addressinput
 }  // namespace i18n
diff --git a/third_party/libaddressinput/chromium/cpp/test/countryinfo_example_addresses_test.cc b/third_party/libaddressinput/chromium/cpp/test/countryinfo_example_addresses_test.cc
index 32a2deb..31ffefd 100644
--- a/third_party/libaddressinput/chromium/cpp/test/countryinfo_example_addresses_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/countryinfo_example_addresses_test.cc
@@ -32,7 +32,7 @@
 #include "fake_downloader.h"
 #include "fake_storage.h"
 #include "util/json.h"
-#include "util/string_split.h"
+#include "util/string_util.h"
 
 namespace i18n {
 namespace addressinput {
diff --git a/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc b/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc
index 5caff83..90c9099 100644
--- a/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc
+++ b/third_party/libaddressinput/chromium/cpp/test/retriever_test.cc
@@ -28,7 +28,7 @@
 #include "fake_downloader.h"
 #include "fake_storage.h"
 #include "region_data_constants.h"
-#include "time_to_string.h"
+#include "util/string_util.h"
 
 namespace i18n {
 namespace addressinput {
diff --git a/third_party/libaddressinput/chromium/cpp/test/util/string_split_unittest.cc b/third_party/libaddressinput/chromium/cpp/test/util/string_split_unittest.cc
deleted file mode 100644
index 73ca595..0000000
--- a/third_party/libaddressinput/chromium/cpp/test/util/string_split_unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The original source code is from:
-// http://src.chromium.org/viewvc/chrome/trunk/src/base/strings/string_split_unittest.cc?revision=216633
-
-#include "util/string_split.h"
-
-#include <string>
-#include <vector>
-
-#include <gtest/gtest.h>
-
-namespace {
-
-using i18n::addressinput::SplitString;
-
-TEST(StringSplitTest, SplitString) {
-  std::vector<std::string> r;
-
-  SplitString(std::string(), ',', &r);
-  EXPECT_EQ(0U, r.size());
-
-  SplitString("a,b,c", ',', &r);
-  ASSERT_EQ(3U, r.size());
-  EXPECT_EQ(r[0], "a");
-  EXPECT_EQ(r[1], "b");
-  EXPECT_EQ(r[2], "c");
-
-  SplitString("a, b, c", ',', &r);
-  ASSERT_EQ(3U, r.size());
-  EXPECT_EQ(r[0], "a");
-  EXPECT_EQ(r[1], " b");
-  EXPECT_EQ(r[2], " c");
-
-  SplitString("a,,c", ',', &r);
-  ASSERT_EQ(3U, r.size());
-  EXPECT_EQ(r[0], "a");
-  EXPECT_EQ(r[1], "");
-  EXPECT_EQ(r[2], "c");
-
-  SplitString("   ", '*', &r);
-  EXPECT_EQ(1U, r.size());
-
-  SplitString("foo", '*', &r);
-  ASSERT_EQ(1U, r.size());
-  EXPECT_EQ(r[0], "foo");
-
-  SplitString("foo ,", ',', &r);
-  ASSERT_EQ(2U, r.size());
-  EXPECT_EQ(r[0], "foo ");
-  EXPECT_EQ(r[1], "");
-
-  SplitString(",", ',', &r);
-  ASSERT_EQ(2U, r.size());
-  EXPECT_EQ(r[0], "");
-  EXPECT_EQ(r[1], "");
-
-  SplitString("\t\ta\t", '\t', &r);
-  ASSERT_EQ(4U, r.size());
-  EXPECT_EQ(r[0], "");
-  EXPECT_EQ(r[1], "");
-  EXPECT_EQ(r[2], "a");
-  EXPECT_EQ(r[3], "");
-
-  SplitString("\ta\t\nb\tcc", '\n', &r);
-  ASSERT_EQ(2U, r.size());
-  EXPECT_EQ(r[0], "\ta\t");
-  EXPECT_EQ(r[1], "b\tcc");
-
-  SplitString("   ", '*', &r);
-  ASSERT_EQ(1U, r.size());
-  EXPECT_EQ(r[0], "   ");
-
-  SplitString("\t  \ta\t ", '\t', &r);
-  ASSERT_EQ(4U, r.size());
-  EXPECT_EQ(r[0], "");
-  EXPECT_EQ(r[1], "  ");
-  EXPECT_EQ(r[2], "a");
-  EXPECT_EQ(r[3], " ");
-
-  SplitString("\ta\t\nb\tcc", '\n', &r);
-  ASSERT_EQ(2U, r.size());
-  EXPECT_EQ(r[0], "\ta\t");
-  EXPECT_EQ(r[1], "b\tcc");
-}
-
-}  // namespace
diff --git a/third_party/libaddressinput/chromium/cpp/test/util/string_util_test.cc b/third_party/libaddressinput/chromium/cpp/test/util/string_util_test.cc
new file mode 100644
index 0000000..e5d4a1a
--- /dev/null
+++ b/third_party/libaddressinput/chromium/cpp/test/util/string_util_test.cc
@@ -0,0 +1,89 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// The original source code is from:
+// http://src.chromium.org/viewvc/chrome/trunk/src/base/strings/string_split_unittest.cc?revision=216633
+
+#include "util/string_util.h"
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace {
+
+using i18n::addressinput::SplitString;
+
+TEST(StringSplitTest, SplitString) {
+  std::vector<std::string> r;
+
+  SplitString(std::string(), ',', &r);
+  EXPECT_EQ(0U, r.size());
+
+  SplitString("a,b,c", ',', &r);
+  ASSERT_EQ(3U, r.size());
+  EXPECT_EQ(r[0], "a");
+  EXPECT_EQ(r[1], "b");
+  EXPECT_EQ(r[2], "c");
+
+  SplitString("a, b, c", ',', &r);
+  ASSERT_EQ(3U, r.size());
+  EXPECT_EQ(r[0], "a");
+  EXPECT_EQ(r[1], " b");
+  EXPECT_EQ(r[2], " c");
+
+  SplitString("a,,c", ',', &r);
+  ASSERT_EQ(3U, r.size());
+  EXPECT_EQ(r[0], "a");
+  EXPECT_EQ(r[1], "");
+  EXPECT_EQ(r[2], "c");
+
+  SplitString("   ", '*', &r);
+  EXPECT_EQ(1U, r.size());
+
+  SplitString("foo", '*', &r);
+  ASSERT_EQ(1U, r.size());
+  EXPECT_EQ(r[0], "foo");
+
+  SplitString("foo ,", ',', &r);
+  ASSERT_EQ(2U, r.size());
+  EXPECT_EQ(r[0], "foo ");
+  EXPECT_EQ(r[1], "");
+
+  SplitString(",", ',', &r);
+  ASSERT_EQ(2U, r.size());
+  EXPECT_EQ(r[0], "");
+  EXPECT_EQ(r[1], "");
+
+  SplitString("\t\ta\t", '\t', &r);
+  ASSERT_EQ(4U, r.size());
+  EXPECT_EQ(r[0], "");
+  EXPECT_EQ(r[1], "");
+  EXPECT_EQ(r[2], "a");
+  EXPECT_EQ(r[3], "");
+
+  SplitString("\ta\t\nb\tcc", '\n', &r);
+  ASSERT_EQ(2U, r.size());
+  EXPECT_EQ(r[0], "\ta\t");
+  EXPECT_EQ(r[1], "b\tcc");
+
+  SplitString("   ", '*', &r);
+  ASSERT_EQ(1U, r.size());
+  EXPECT_EQ(r[0], "   ");
+
+  SplitString("\t  \ta\t ", '\t', &r);
+  ASSERT_EQ(4U, r.size());
+  EXPECT_EQ(r[0], "");
+  EXPECT_EQ(r[1], "  ");
+  EXPECT_EQ(r[2], "a");
+  EXPECT_EQ(r[3], " ");
+
+  SplitString("\ta\t\nb\tcc", '\n', &r);
+  ASSERT_EQ(2U, r.size());
+  EXPECT_EQ(r[0], "\ta\t");
+  EXPECT_EQ(r[1], "b\tcc");
+}
+
+}  // namespace
diff --git a/third_party/libaddressinput/libaddressinput.gyp b/third_party/libaddressinput/libaddressinput.gyp
index b0dfee2..3c89615 100644
--- a/third_party/libaddressinput/libaddressinput.gyp
+++ b/third_party/libaddressinput/libaddressinput.gyp
@@ -86,17 +86,13 @@
         '<(libaddressinput_dir)/cpp/src/rule.h',
         '<(libaddressinput_dir)/cpp/src/ruleset.cc',
         '<(libaddressinput_dir)/cpp/src/ruleset.h',
-        '<(libaddressinput_dir)/cpp/src/time_to_string.cc',
-        '<(libaddressinput_dir)/cpp/src/time_to_string.h',
+        '<(libaddressinput_dir)/cpp/src/util/canonicalize_string.h',
         '<(libaddressinput_dir)/cpp/src/util/json.h',
         '<(libaddressinput_dir)/cpp/src/util/md5.cc',
         '<(libaddressinput_dir)/cpp/src/util/md5.h',
         '<(libaddressinput_dir)/cpp/src/util/stl_util.h',
-        '<(libaddressinput_dir)/cpp/src/util/canonicalize_string.h',
-        '<(libaddressinput_dir)/cpp/src/util/string_compare.cc',
-        '<(libaddressinput_dir)/cpp/src/util/string_compare.h',
-        '<(libaddressinput_dir)/cpp/src/util/string_split.cc',
-        '<(libaddressinput_dir)/cpp/src/util/string_split.h',
+        '<(libaddressinput_dir)/cpp/src/util/string_util.cc',
+        '<(libaddressinput_dir)/cpp/src/util/string_util.h',
         '<(libaddressinput_dir)/cpp/src/util/trie.cc',
         '<(libaddressinput_dir)/cpp/src/util/trie.h',
       ],
@@ -155,7 +151,7 @@
         '<(libaddressinput_dir)/cpp/test/util/md5_unittest.cc',
         '<(libaddressinput_dir)/cpp/test/util/scoped_ptr_unittest.cc',
         '<(libaddressinput_dir)/cpp/test/util/stl_util_unittest.cc',
-        '<(libaddressinput_dir)/cpp/test/util/string_split_unittest.cc',
+        '<(libaddressinput_dir)/cpp/test/util/string_util_test.cc',
         '<(libaddressinput_dir)/cpp/test/util/trie_test.cc',
       ],
       'defines': [
diff --git a/third_party/libc++/libc++.gyp b/third_party/libc++/libc++.gyp
index 16448bf..b5f14f8 100644
--- a/third_party/libc++/libc++.gyp
+++ b/third_party/libc++/libc++.gyp
@@ -12,7 +12,9 @@
         # Don't add this target to the dependencies of targets with type=none.
         'link_dependency': 1,
       },
-      'dependencies=': [],
+      'dependencies=': [
+        '../libc++abi/libc++abi.gyp:libc++abi',
+      ],
       'sources': [
         'trunk/src/algorithm.cpp',
         'trunk/src/bind.cpp',
@@ -85,13 +87,19 @@
       ],
       'ldflags': [
         '-nodefaultlibs',
+        '<(PRODUCT_DIR)/lib/libc++abi.so',
       ],
       'ldflags!': [
+        # This somehow causes a warning from clang about an unused compilation
+        # option. Use '-lpthread' instead.
+        # TODO(earthdok): find out what's causing the warning.
         '-pthread',
       ],
       'libraries': [
-        '-lrt',
         '-lc',
+        '-lgcc_s',
+        '-lpthread',
+        '-lrt',
       ],
     },
   ]
diff --git a/third_party/libevent/libevent.target.darwin-arm.mk b/third_party/libevent/libevent.target.darwin-arm.mk
index 6559415..6c045c4 100644
--- a/third_party/libevent/libevent.target.darwin-arm.mk
+++ b/third_party/libevent/libevent.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -180,6 +181,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libevent/libevent.target.darwin-mips.mk b/third_party/libevent/libevent.target.darwin-mips.mk
index 5cb5dda..8072120 100644
--- a/third_party/libevent/libevent.target.darwin-mips.mk
+++ b/third_party/libevent/libevent.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -180,6 +181,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libevent/libevent.target.darwin-x86.mk b/third_party/libevent/libevent.target.darwin-x86.mk
index a425b3e..215d917 100644
--- a/third_party/libevent/libevent.target.darwin-x86.mk
+++ b/third_party/libevent/libevent.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -181,6 +182,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libevent/libevent.target.darwin-x86_64.mk b/third_party/libevent/libevent.target.darwin-x86_64.mk
new file mode 100644
index 0000000..5bae9cc
--- /dev/null
+++ b/third_party/libevent/libevent.target.darwin-x86_64.mk
@@ -0,0 +1,274 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libevent_libevent_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libevent/buffer.c \
+	third_party/libevent/evbuffer.c \
+	third_party/libevent/evdns.c \
+	third_party/libevent/event.c \
+	third_party/libevent/event_tagging.c \
+	third_party/libevent/evrpc.c \
+	third_party/libevent/evutil.c \
+	third_party/libevent/http.c \
+	third_party/libevent/log.c \
+	third_party/libevent/poll.c \
+	third_party/libevent/select.c \
+	third_party/libevent/signal.c \
+	third_party/libevent/strlcpy.c \
+	third_party/libevent/epoll.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libevent/android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libevent/android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libevent_libevent_gyp
+
+# Alias gyp target name.
+.PHONY: libevent
+libevent: third_party_libevent_libevent_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libevent/libevent.target.linux-arm.mk b/third_party/libevent/libevent.target.linux-arm.mk
index 6559415..6c045c4 100644
--- a/third_party/libevent/libevent.target.linux-arm.mk
+++ b/third_party/libevent/libevent.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -180,6 +181,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libevent/libevent.target.linux-mips.mk b/third_party/libevent/libevent.target.linux-mips.mk
index 5cb5dda..8072120 100644
--- a/third_party/libevent/libevent.target.linux-mips.mk
+++ b/third_party/libevent/libevent.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -180,6 +181,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libevent/libevent.target.linux-x86.mk b/third_party/libevent/libevent.target.linux-x86.mk
index a425b3e..215d917 100644
--- a/third_party/libevent/libevent.target.linux-x86.mk
+++ b/third_party/libevent/libevent.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -181,6 +182,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libevent/libevent.target.linux-x86_64.mk b/third_party/libevent/libevent.target.linux-x86_64.mk
new file mode 100644
index 0000000..5bae9cc
--- /dev/null
+++ b/third_party/libevent/libevent.target.linux-x86_64.mk
@@ -0,0 +1,274 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libevent_libevent_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libevent/buffer.c \
+	third_party/libevent/evbuffer.c \
+	third_party/libevent/evdns.c \
+	third_party/libevent/event.c \
+	third_party/libevent/event_tagging.c \
+	third_party/libevent/evrpc.c \
+	third_party/libevent/evutil.c \
+	third_party/libevent/http.c \
+	third_party/libevent/log.c \
+	third_party/libevent/poll.c \
+	third_party/libevent/select.c \
+	third_party/libevent/signal.c \
+	third_party/libevent/strlcpy.c \
+	third_party/libevent/epoll.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libevent/android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libevent/android \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libevent_libevent_gyp
+
+# Alias gyp target name.
+.PHONY: libevent
+libevent: third_party_libevent_libevent_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libjingle/README.chromium b/third_party/libjingle/README.chromium
index c9ae048..b079e3a 100644
--- a/third_party/libjingle/README.chromium
+++ b/third_party/libjingle/README.chromium
@@ -1,7 +1,7 @@
 Name: libjingle
 URL: http://code.google.com/p/webrtc/
 Version: unknown
-Revision: 5721
+Revision: 5807
 License: BSD
 License File: source/talk/COPYING
 Security Critical: yes
diff --git a/third_party/libjingle/libjingle.target.darwin-arm.mk b/third_party/libjingle/libjingle.target.darwin-arm.mk
index 05d59a3..4f4711d 100644
--- a/third_party/libjingle/libjingle.target.darwin-arm.mk
+++ b/third_party/libjingle/libjingle.target.darwin-arm.mk
@@ -217,6 +217,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
@@ -332,6 +333,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
diff --git a/third_party/libjingle/libjingle.target.darwin-mips.mk b/third_party/libjingle/libjingle.target.darwin-mips.mk
index 944db84..f4b114b 100644
--- a/third_party/libjingle/libjingle.target.darwin-mips.mk
+++ b/third_party/libjingle/libjingle.target.darwin-mips.mk
@@ -217,6 +217,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
@@ -332,6 +333,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
diff --git a/third_party/libjingle/libjingle.target.darwin-x86.mk b/third_party/libjingle/libjingle.target.darwin-x86.mk
index 8de3792..1c17912 100644
--- a/third_party/libjingle/libjingle.target.darwin-x86.mk
+++ b/third_party/libjingle/libjingle.target.darwin-x86.mk
@@ -217,6 +217,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
@@ -331,6 +332,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
diff --git a/third_party/libjingle/libjingle.target.darwin-x86_64.mk b/third_party/libjingle/libjingle.target.darwin-x86_64.mk
new file mode 100644
index 0000000..f3a5d66
--- /dev/null
+++ b/third_party/libjingle/libjingle.target.darwin-x86_64.mk
@@ -0,0 +1,439 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libjingle_libjingle_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libjingle/overrides/talk/base/logging.cc \
+	third_party/libjingle/source/talk/base/asyncfile.cc \
+	third_party/libjingle/source/talk/base/asynchttprequest.cc \
+	third_party/libjingle/source/talk/base/asyncsocket.cc \
+	third_party/libjingle/source/talk/base/asynctcpsocket.cc \
+	third_party/libjingle/source/talk/base/asyncudpsocket.cc \
+	third_party/libjingle/source/talk/base/autodetectproxy.cc \
+	third_party/libjingle/source/talk/base/base64.cc \
+	third_party/libjingle/source/talk/base/bytebuffer.cc \
+	third_party/libjingle/source/talk/base/checks.cc \
+	third_party/libjingle/source/talk/base/common.cc \
+	third_party/libjingle/source/talk/base/cpumonitor.cc \
+	third_party/libjingle/source/talk/base/crc32.cc \
+	third_party/libjingle/source/talk/base/diskcache.cc \
+	third_party/libjingle/source/talk/base/event.cc \
+	third_party/libjingle/source/talk/base/fileutils.cc \
+	third_party/libjingle/source/talk/base/firewallsocketserver.cc \
+	third_party/libjingle/source/talk/base/flags.cc \
+	third_party/libjingle/source/talk/base/helpers.cc \
+	third_party/libjingle/source/talk/base/httpbase.cc \
+	third_party/libjingle/source/talk/base/httpclient.cc \
+	third_party/libjingle/source/talk/base/httpcommon.cc \
+	third_party/libjingle/source/talk/base/httprequest.cc \
+	third_party/libjingle/source/talk/base/ifaddrs-android.cc \
+	third_party/libjingle/source/talk/base/ipaddress.cc \
+	third_party/libjingle/source/talk/base/linux.cc \
+	third_party/libjingle/source/talk/base/md5.cc \
+	third_party/libjingle/source/talk/base/messagedigest.cc \
+	third_party/libjingle/source/talk/base/messagehandler.cc \
+	third_party/libjingle/source/talk/base/messagequeue.cc \
+	third_party/libjingle/source/talk/base/nethelpers.cc \
+	third_party/libjingle/source/talk/base/network.cc \
+	third_party/libjingle/source/talk/base/nssidentity.cc \
+	third_party/libjingle/source/talk/base/nssstreamadapter.cc \
+	third_party/libjingle/source/talk/base/openssladapter.cc \
+	third_party/libjingle/source/talk/base/openssldigest.cc \
+	third_party/libjingle/source/talk/base/opensslidentity.cc \
+	third_party/libjingle/source/talk/base/opensslstreamadapter.cc \
+	third_party/libjingle/source/talk/base/pathutils.cc \
+	third_party/libjingle/source/talk/base/physicalsocketserver.cc \
+	third_party/libjingle/source/talk/base/proxydetect.cc \
+	third_party/libjingle/source/talk/base/proxyinfo.cc \
+	third_party/libjingle/source/talk/base/ratelimiter.cc \
+	third_party/libjingle/source/talk/base/ratetracker.cc \
+	third_party/libjingle/source/talk/base/sha1.cc \
+	third_party/libjingle/source/talk/base/signalthread.cc \
+	third_party/libjingle/source/talk/base/socketadapters.cc \
+	third_party/libjingle/source/talk/base/socketaddress.cc \
+	third_party/libjingle/source/talk/base/socketaddresspair.cc \
+	third_party/libjingle/source/talk/base/socketpool.cc \
+	third_party/libjingle/source/talk/base/socketstream.cc \
+	third_party/libjingle/source/talk/base/ssladapter.cc \
+	third_party/libjingle/source/talk/base/sslfingerprint.cc \
+	third_party/libjingle/source/talk/base/sslidentity.cc \
+	third_party/libjingle/source/talk/base/sslsocketfactory.cc \
+	third_party/libjingle/source/talk/base/sslstreamadapter.cc \
+	third_party/libjingle/source/talk/base/sslstreamadapterhelper.cc \
+	third_party/libjingle/source/talk/base/stream.cc \
+	third_party/libjingle/source/talk/base/stringencode.cc \
+	third_party/libjingle/source/talk/base/stringutils.cc \
+	third_party/libjingle/source/talk/base/systeminfo.cc \
+	third_party/libjingle/source/talk/base/task.cc \
+	third_party/libjingle/source/talk/base/taskparent.cc \
+	third_party/libjingle/source/talk/base/taskrunner.cc \
+	third_party/libjingle/source/talk/base/thread.cc \
+	third_party/libjingle/source/talk/base/timeutils.cc \
+	third_party/libjingle/source/talk/base/timing.cc \
+	third_party/libjingle/source/talk/base/unixfilesystem.cc \
+	third_party/libjingle/source/talk/base/urlencode.cc \
+	third_party/libjingle/source/talk/base/worker.cc \
+	third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket.cc \
+	third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.cc \
+	third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/p2ptransport.cc \
+	third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/parsing.cc \
+	third_party/libjingle/source/talk/p2p/base/port.cc \
+	third_party/libjingle/source/talk/p2p/base/portallocator.cc \
+	third_party/libjingle/source/talk/p2p/base/portallocatorsessionproxy.cc \
+	third_party/libjingle/source/talk/p2p/base/portproxy.cc \
+	third_party/libjingle/source/talk/p2p/base/pseudotcp.cc \
+	third_party/libjingle/source/talk/p2p/base/rawtransport.cc \
+	third_party/libjingle/source/talk/p2p/base/rawtransportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/relayport.cc \
+	third_party/libjingle/source/talk/p2p/base/session.cc \
+	third_party/libjingle/source/talk/p2p/base/sessiondescription.cc \
+	third_party/libjingle/source/talk/p2p/base/sessionmanager.cc \
+	third_party/libjingle/source/talk/p2p/base/sessionmessages.cc \
+	third_party/libjingle/source/talk/p2p/base/stun.cc \
+	third_party/libjingle/source/talk/p2p/base/stunport.cc \
+	third_party/libjingle/source/talk/p2p/base/stunrequest.cc \
+	third_party/libjingle/source/talk/p2p/base/tcpport.cc \
+	third_party/libjingle/source/talk/p2p/base/transport.cc \
+	third_party/libjingle/source/talk/p2p/base/transportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/transportchannelproxy.cc \
+	third_party/libjingle/source/talk/p2p/base/transportdescription.cc \
+	third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.cc \
+	third_party/libjingle/source/talk/p2p/base/turnport.cc \
+	third_party/libjingle/source/talk/p2p/client/basicportallocator.cc \
+	third_party/libjingle/source/talk/p2p/client/httpportallocator.cc \
+	third_party/libjingle/source/talk/p2p/client/socketmonitor.cc \
+	third_party/libjingle/source/talk/xmllite/qname.cc \
+	third_party/libjingle/source/talk/xmllite/xmlbuilder.cc \
+	third_party/libjingle/source/talk/xmllite/xmlconstants.cc \
+	third_party/libjingle/source/talk/xmllite/xmlelement.cc \
+	third_party/libjingle/source/talk/xmllite/xmlnsstack.cc \
+	third_party/libjingle/source/talk/xmllite/xmlparser.cc \
+	third_party/libjingle/source/talk/xmllite/xmlprinter.cc \
+	third_party/libjingle/source/talk/xmpp/constants.cc \
+	third_party/libjingle/source/talk/xmpp/jid.cc \
+	third_party/libjingle/source/talk/xmpp/saslmechanism.cc \
+	third_party/libjingle/source/talk/xmpp/xmppclient.cc \
+	third_party/libjingle/source/talk/xmpp/xmppengineimpl.cc \
+	third_party/libjingle/source/talk/xmpp/xmppengineimpl_iq.cc \
+	third_party/libjingle/source/talk/xmpp/xmpplogintask.cc \
+	third_party/libjingle/source/talk/xmpp/xmppstanzaparser.cc \
+	third_party/libjingle/source/talk/xmpp/xmpptask.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DANDROID' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DANDROID' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libjingle_libjingle_gyp
+
+# Alias gyp target name.
+.PHONY: libjingle
+libjingle: third_party_libjingle_libjingle_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libjingle/libjingle.target.linux-arm.mk b/third_party/libjingle/libjingle.target.linux-arm.mk
index 05d59a3..4f4711d 100644
--- a/third_party/libjingle/libjingle.target.linux-arm.mk
+++ b/third_party/libjingle/libjingle.target.linux-arm.mk
@@ -217,6 +217,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
@@ -332,6 +333,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
diff --git a/third_party/libjingle/libjingle.target.linux-mips.mk b/third_party/libjingle/libjingle.target.linux-mips.mk
index 944db84..f4b114b 100644
--- a/third_party/libjingle/libjingle.target.linux-mips.mk
+++ b/third_party/libjingle/libjingle.target.linux-mips.mk
@@ -217,6 +217,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
@@ -332,6 +333,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
diff --git a/third_party/libjingle/libjingle.target.linux-x86.mk b/third_party/libjingle/libjingle.target.linux-x86.mk
index 8de3792..1c17912 100644
--- a/third_party/libjingle/libjingle.target.linux-x86.mk
+++ b/third_party/libjingle/libjingle.target.linux-x86.mk
@@ -217,6 +217,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
@@ -331,6 +332,7 @@
 	'-DFEATURE_ENABLE_VOICEMAIL' \
 	'-DANDROID' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
 	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
diff --git a/third_party/libjingle/libjingle.target.linux-x86_64.mk b/third_party/libjingle/libjingle.target.linux-x86_64.mk
new file mode 100644
index 0000000..f3a5d66
--- /dev/null
+++ b/third_party/libjingle/libjingle.target.linux-x86_64.mk
@@ -0,0 +1,439 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libjingle_libjingle_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libjingle/overrides/talk/base/logging.cc \
+	third_party/libjingle/source/talk/base/asyncfile.cc \
+	third_party/libjingle/source/talk/base/asynchttprequest.cc \
+	third_party/libjingle/source/talk/base/asyncsocket.cc \
+	third_party/libjingle/source/talk/base/asynctcpsocket.cc \
+	third_party/libjingle/source/talk/base/asyncudpsocket.cc \
+	third_party/libjingle/source/talk/base/autodetectproxy.cc \
+	third_party/libjingle/source/talk/base/base64.cc \
+	third_party/libjingle/source/talk/base/bytebuffer.cc \
+	third_party/libjingle/source/talk/base/checks.cc \
+	third_party/libjingle/source/talk/base/common.cc \
+	third_party/libjingle/source/talk/base/cpumonitor.cc \
+	third_party/libjingle/source/talk/base/crc32.cc \
+	third_party/libjingle/source/talk/base/diskcache.cc \
+	third_party/libjingle/source/talk/base/event.cc \
+	third_party/libjingle/source/talk/base/fileutils.cc \
+	third_party/libjingle/source/talk/base/firewallsocketserver.cc \
+	third_party/libjingle/source/talk/base/flags.cc \
+	third_party/libjingle/source/talk/base/helpers.cc \
+	third_party/libjingle/source/talk/base/httpbase.cc \
+	third_party/libjingle/source/talk/base/httpclient.cc \
+	third_party/libjingle/source/talk/base/httpcommon.cc \
+	third_party/libjingle/source/talk/base/httprequest.cc \
+	third_party/libjingle/source/talk/base/ifaddrs-android.cc \
+	third_party/libjingle/source/talk/base/ipaddress.cc \
+	third_party/libjingle/source/talk/base/linux.cc \
+	third_party/libjingle/source/talk/base/md5.cc \
+	third_party/libjingle/source/talk/base/messagedigest.cc \
+	third_party/libjingle/source/talk/base/messagehandler.cc \
+	third_party/libjingle/source/talk/base/messagequeue.cc \
+	third_party/libjingle/source/talk/base/nethelpers.cc \
+	third_party/libjingle/source/talk/base/network.cc \
+	third_party/libjingle/source/talk/base/nssidentity.cc \
+	third_party/libjingle/source/talk/base/nssstreamadapter.cc \
+	third_party/libjingle/source/talk/base/openssladapter.cc \
+	third_party/libjingle/source/talk/base/openssldigest.cc \
+	third_party/libjingle/source/talk/base/opensslidentity.cc \
+	third_party/libjingle/source/talk/base/opensslstreamadapter.cc \
+	third_party/libjingle/source/talk/base/pathutils.cc \
+	third_party/libjingle/source/talk/base/physicalsocketserver.cc \
+	third_party/libjingle/source/talk/base/proxydetect.cc \
+	third_party/libjingle/source/talk/base/proxyinfo.cc \
+	third_party/libjingle/source/talk/base/ratelimiter.cc \
+	third_party/libjingle/source/talk/base/ratetracker.cc \
+	third_party/libjingle/source/talk/base/sha1.cc \
+	third_party/libjingle/source/talk/base/signalthread.cc \
+	third_party/libjingle/source/talk/base/socketadapters.cc \
+	third_party/libjingle/source/talk/base/socketaddress.cc \
+	third_party/libjingle/source/talk/base/socketaddresspair.cc \
+	third_party/libjingle/source/talk/base/socketpool.cc \
+	third_party/libjingle/source/talk/base/socketstream.cc \
+	third_party/libjingle/source/talk/base/ssladapter.cc \
+	third_party/libjingle/source/talk/base/sslfingerprint.cc \
+	third_party/libjingle/source/talk/base/sslidentity.cc \
+	third_party/libjingle/source/talk/base/sslsocketfactory.cc \
+	third_party/libjingle/source/talk/base/sslstreamadapter.cc \
+	third_party/libjingle/source/talk/base/sslstreamadapterhelper.cc \
+	third_party/libjingle/source/talk/base/stream.cc \
+	third_party/libjingle/source/talk/base/stringencode.cc \
+	third_party/libjingle/source/talk/base/stringutils.cc \
+	third_party/libjingle/source/talk/base/systeminfo.cc \
+	third_party/libjingle/source/talk/base/task.cc \
+	third_party/libjingle/source/talk/base/taskparent.cc \
+	third_party/libjingle/source/talk/base/taskrunner.cc \
+	third_party/libjingle/source/talk/base/thread.cc \
+	third_party/libjingle/source/talk/base/timeutils.cc \
+	third_party/libjingle/source/talk/base/timing.cc \
+	third_party/libjingle/source/talk/base/unixfilesystem.cc \
+	third_party/libjingle/source/talk/base/urlencode.cc \
+	third_party/libjingle/source/talk/base/worker.cc \
+	third_party/libjingle/source/talk/p2p/base/asyncstuntcpsocket.cc \
+	third_party/libjingle/source/talk/p2p/base/basicpacketsocketfactory.cc \
+	third_party/libjingle/source/talk/p2p/base/dtlstransportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/p2ptransport.cc \
+	third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/parsing.cc \
+	third_party/libjingle/source/talk/p2p/base/port.cc \
+	third_party/libjingle/source/talk/p2p/base/portallocator.cc \
+	third_party/libjingle/source/talk/p2p/base/portallocatorsessionproxy.cc \
+	third_party/libjingle/source/talk/p2p/base/portproxy.cc \
+	third_party/libjingle/source/talk/p2p/base/pseudotcp.cc \
+	third_party/libjingle/source/talk/p2p/base/rawtransport.cc \
+	third_party/libjingle/source/talk/p2p/base/rawtransportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/relayport.cc \
+	third_party/libjingle/source/talk/p2p/base/session.cc \
+	third_party/libjingle/source/talk/p2p/base/sessiondescription.cc \
+	third_party/libjingle/source/talk/p2p/base/sessionmanager.cc \
+	third_party/libjingle/source/talk/p2p/base/sessionmessages.cc \
+	third_party/libjingle/source/talk/p2p/base/stun.cc \
+	third_party/libjingle/source/talk/p2p/base/stunport.cc \
+	third_party/libjingle/source/talk/p2p/base/stunrequest.cc \
+	third_party/libjingle/source/talk/p2p/base/tcpport.cc \
+	third_party/libjingle/source/talk/p2p/base/transport.cc \
+	third_party/libjingle/source/talk/p2p/base/transportchannel.cc \
+	third_party/libjingle/source/talk/p2p/base/transportchannelproxy.cc \
+	third_party/libjingle/source/talk/p2p/base/transportdescription.cc \
+	third_party/libjingle/source/talk/p2p/base/transportdescriptionfactory.cc \
+	third_party/libjingle/source/talk/p2p/base/turnport.cc \
+	third_party/libjingle/source/talk/p2p/client/basicportallocator.cc \
+	third_party/libjingle/source/talk/p2p/client/httpportallocator.cc \
+	third_party/libjingle/source/talk/p2p/client/socketmonitor.cc \
+	third_party/libjingle/source/talk/xmllite/qname.cc \
+	third_party/libjingle/source/talk/xmllite/xmlbuilder.cc \
+	third_party/libjingle/source/talk/xmllite/xmlconstants.cc \
+	third_party/libjingle/source/talk/xmllite/xmlelement.cc \
+	third_party/libjingle/source/talk/xmllite/xmlnsstack.cc \
+	third_party/libjingle/source/talk/xmllite/xmlparser.cc \
+	third_party/libjingle/source/talk/xmllite/xmlprinter.cc \
+	third_party/libjingle/source/talk/xmpp/constants.cc \
+	third_party/libjingle/source/talk/xmpp/jid.cc \
+	third_party/libjingle/source/talk/xmpp/saslmechanism.cc \
+	third_party/libjingle/source/talk/xmpp/xmppclient.cc \
+	third_party/libjingle/source/talk/xmpp/xmppengineimpl.cc \
+	third_party/libjingle/source/talk/xmpp/xmppengineimpl_iq.cc \
+	third_party/libjingle/source/talk/xmpp/xmpplogintask.cc \
+	third_party/libjingle/source/talk/xmpp/xmppstanzaparser.cc \
+	third_party/libjingle/source/talk/xmpp/xmpptask.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DANDROID' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DFEATURE_ENABLE_VOICEMAIL' \
+	'-DANDROID' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libjingle_libjingle_gyp
+
+# Alias gyp target name.
+.PHONY: libjingle
+libjingle: third_party_libjingle_libjingle_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.darwin-arm.mk b/third_party/libjingle/libjingle_p2p_constants.target.darwin-arm.mk
index b71974e..ff59ca0 100644
--- a/third_party/libjingle/libjingle_p2p_constants.target.darwin-arm.mk
+++ b/third_party/libjingle/libjingle_p2p_constants.target.darwin-arm.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -213,6 +214,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.darwin-mips.mk b/third_party/libjingle/libjingle_p2p_constants.target.darwin-mips.mk
index 182b4ef..45289fa 100644
--- a/third_party/libjingle/libjingle_p2p_constants.target.darwin-mips.mk
+++ b/third_party/libjingle/libjingle_p2p_constants.target.darwin-mips.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -213,6 +214,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86.mk b/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86.mk
index ae113b2..2399c5c 100644
--- a/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86.mk
+++ b/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -212,6 +213,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86_64.mk b/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86_64.mk
new file mode 100644
index 0000000..46db7fa
--- /dev/null
+++ b/third_party/libjingle/libjingle_p2p_constants.target.darwin-x86_64.mk
@@ -0,0 +1,321 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libjingle_libjingle_p2p_constants_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libjingle/source/talk/p2p/base/constants.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libjingle_libjingle_p2p_constants_gyp
+
+# Alias gyp target name.
+.PHONY: libjingle_p2p_constants
+libjingle_p2p_constants: third_party_libjingle_libjingle_p2p_constants_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.linux-arm.mk b/third_party/libjingle/libjingle_p2p_constants.target.linux-arm.mk
index b71974e..ff59ca0 100644
--- a/third_party/libjingle/libjingle_p2p_constants.target.linux-arm.mk
+++ b/third_party/libjingle/libjingle_p2p_constants.target.linux-arm.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -213,6 +214,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.linux-mips.mk b/third_party/libjingle/libjingle_p2p_constants.target.linux-mips.mk
index 182b4ef..45289fa 100644
--- a/third_party/libjingle/libjingle_p2p_constants.target.linux-mips.mk
+++ b/third_party/libjingle/libjingle_p2p_constants.target.linux-mips.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -213,6 +214,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.linux-x86.mk b/third_party/libjingle/libjingle_p2p_constants.target.linux-x86.mk
index ae113b2..2399c5c 100644
--- a/third_party/libjingle/libjingle_p2p_constants.target.linux-x86.mk
+++ b/third_party/libjingle/libjingle_p2p_constants.target.linux-x86.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -212,6 +213,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libjingle/libjingle_p2p_constants.target.linux-x86_64.mk b/third_party/libjingle/libjingle_p2p_constants.target.linux-x86_64.mk
new file mode 100644
index 0000000..46db7fa
--- /dev/null
+++ b/third_party/libjingle/libjingle_p2p_constants.target.linux-x86_64.mk
@@ -0,0 +1,321 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libjingle_libjingle_p2p_constants_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_expat_expat_gyp)/expat.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libjingle/source/talk/p2p/base/constants.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DEXPAT_RELATIVE_PATH' \
+	'-DFEATURE_ENABLE_SSL' \
+	'-DGTEST_RELATIVE_PATH' \
+	'-DHAVE_SRTP' \
+	'-DHAVE_WEBRTC_VIDEO' \
+	'-DHAVE_WEBRTC_VOICE' \
+	'-DLOGGING_INSIDE_LIBJINGLE' \
+	'-DNO_MAIN_THREAD_WRAPPING' \
+	'-DNO_SOUND_SYSTEM' \
+	'-DSRTP_RELATIVE_PATH' \
+	'-DUSE_WEBRTC_DEV_BRANCH' \
+	'-DENABLE_EXTERNAL_AUTH' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DLIBPEERCONNECTION_LIB=1' \
+	'-DSSL_USE_OPENSSL' \
+	'-DHAVE_OPENSSL_SSL_H' \
+	'-DPOSIX' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/libjingle/overrides \
+	$(LOCAL_PATH)/third_party/libjingle/source \
+	$(LOCAL_PATH)/testing/gtest/include \
+	$(LOCAL_PATH)/third_party \
+	$(LOCAL_PATH)/third_party/libyuv/include \
+	$(LOCAL_PATH)/third_party/usrsctp \
+	$(LOCAL_PATH)/third_party/webrtc \
+	$(LOCAL_PATH) \
+	$(PWD)/external/expat/lib \
+	$(LOCAL_PATH)/third_party/openssl/config/x64 \
+	$(LOCAL_PATH)/third_party/openssl/openssl/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libjingle_libjingle_p2p_constants_gyp
+
+# Alias gyp target name.
+.PHONY: libjingle_p2p_constants
+libjingle_p2p_constants: third_party_libjingle_libjingle_p2p_constants_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libjingle/overrides/init_webrtc.cc b/third_party/libjingle/overrides/init_webrtc.cc
index e0e0532..b25f31a 100644
--- a/third_party/libjingle/overrides/init_webrtc.cc
+++ b/third_party/libjingle/overrides/init_webrtc.cc
@@ -80,10 +80,9 @@
   base::FilePath path(GetLibPeerConnectionPath());
   DVLOG(1) << "Loading WebRTC module: " << path.value();
 
-  std::string error;
-  static base::NativeLibrary lib =
-      base::LoadNativeLibrary(path, &error);
-  CHECK(lib) << error;
+  base::NativeLibraryLoadError error;
+  static base::NativeLibrary lib = base::LoadNativeLibrary(path, &error);
+  CHECK(lib) << error.ToString();
 
   InitializeModuleFunction initialize_module =
       reinterpret_cast<InitializeModuleFunction>(
diff --git a/third_party/libjpeg/libjpeg.target.darwin-x86_64.mk b/third_party/libjpeg/libjpeg.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7c76dfc
--- /dev/null
+++ b/third_party/libjpeg/libjpeg.target.darwin-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_libjpeg_libjpeg_gyp
+LOCAL_MODULE_STEM := libjpeg
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libjpeg_libjpeg_gyp
+
+# Alias gyp target name.
+.PHONY: libjpeg
+libjpeg: third_party_libjpeg_libjpeg_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/libjpeg/libjpeg.target.linux-x86_64.mk b/third_party/libjpeg/libjpeg.target.linux-x86_64.mk
new file mode 100644
index 0000000..7c76dfc
--- /dev/null
+++ b/third_party/libjpeg/libjpeg.target.linux-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_libjpeg_libjpeg_gyp
+LOCAL_MODULE_STEM := libjpeg
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libjpeg_libjpeg_gyp
+
+# Alias gyp target name.
+.PHONY: libjpeg
+libjpeg: third_party_libjpeg_libjpeg_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/libphonenumber/libphonenumber.target.darwin-arm.mk b/third_party/libphonenumber/libphonenumber.target.darwin-arm.mk
index 76e8a30..395066a 100644
--- a/third_party/libphonenumber/libphonenumber.target.darwin-arm.mk
+++ b/third_party/libphonenumber/libphonenumber.target.darwin-arm.mk
@@ -86,6 +86,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -183,6 +184,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber.target.darwin-mips.mk b/third_party/libphonenumber/libphonenumber.target.darwin-mips.mk
index 74062eb..6ef579e 100644
--- a/third_party/libphonenumber/libphonenumber.target.darwin-mips.mk
+++ b/third_party/libphonenumber/libphonenumber.target.darwin-mips.mk
@@ -86,6 +86,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -183,6 +184,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber.target.darwin-x86.mk b/third_party/libphonenumber/libphonenumber.target.darwin-x86.mk
index 8d42f98..1591f1d 100644
--- a/third_party/libphonenumber/libphonenumber.target.darwin-x86.mk
+++ b/third_party/libphonenumber/libphonenumber.target.darwin-x86.mk
@@ -87,6 +87,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -184,6 +185,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber.target.darwin-x86_64.mk b/third_party/libphonenumber/libphonenumber.target.darwin-x86_64.mk
new file mode 100644
index 0000000..163c5e4
--- /dev/null
+++ b/third_party/libphonenumber/libphonenumber.target.darwin-x86_64.mk
@@ -0,0 +1,286 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libphonenumber_libphonenumber_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libphonenumber/src/phonenumbers/lite_metadata.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libphonenumber_libphonenumber_gyp
+
+# Alias gyp target name.
+.PHONY: libphonenumber
+libphonenumber: third_party_libphonenumber_libphonenumber_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libphonenumber/libphonenumber.target.linux-arm.mk b/third_party/libphonenumber/libphonenumber.target.linux-arm.mk
index 76e8a30..395066a 100644
--- a/third_party/libphonenumber/libphonenumber.target.linux-arm.mk
+++ b/third_party/libphonenumber/libphonenumber.target.linux-arm.mk
@@ -86,6 +86,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -183,6 +184,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber.target.linux-mips.mk b/third_party/libphonenumber/libphonenumber.target.linux-mips.mk
index 74062eb..6ef579e 100644
--- a/third_party/libphonenumber/libphonenumber.target.linux-mips.mk
+++ b/third_party/libphonenumber/libphonenumber.target.linux-mips.mk
@@ -86,6 +86,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -183,6 +184,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber.target.linux-x86.mk b/third_party/libphonenumber/libphonenumber.target.linux-x86.mk
index 8d42f98..1591f1d 100644
--- a/third_party/libphonenumber/libphonenumber.target.linux-x86.mk
+++ b/third_party/libphonenumber/libphonenumber.target.linux-x86.mk
@@ -87,6 +87,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -184,6 +185,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber.target.linux-x86_64.mk b/third_party/libphonenumber/libphonenumber.target.linux-x86_64.mk
new file mode 100644
index 0000000..163c5e4
--- /dev/null
+++ b/third_party/libphonenumber/libphonenumber.target.linux-x86_64.mk
@@ -0,0 +1,286 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libphonenumber_libphonenumber_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libphonenumber_libphonenumber_without_metadata_gyp)/third_party_libphonenumber_libphonenumber_without_metadata_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libphonenumber/src/phonenumbers/lite_metadata.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libphonenumber_libphonenumber_gyp
+
+# Alias gyp target name.
+.PHONY: libphonenumber
+libphonenumber: third_party_libphonenumber_libphonenumber_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-arm.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-arm.mk
index 64781c7..4778f02 100644
--- a/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-arm.mk
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-arm.mk
@@ -151,6 +151,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -251,6 +252,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-mips.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-mips.mk
index 02f53ff..6346994 100644
--- a/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-mips.mk
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-mips.mk
@@ -151,6 +151,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -251,6 +252,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86.mk
index 75d3170..aeabc19 100644
--- a/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86.mk
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86.mk
@@ -152,6 +152,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -252,6 +253,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86_64.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86_64.mk
new file mode 100644
index 0000000..b85a398
--- /dev/null
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.darwin-x86_64.mk
@@ -0,0 +1,355 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libphonenumber_libphonenumber_without_metadata_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "third_party_libphonenumber_libphonenumber_gyp_libphonenumber_without_metadata_target_genproto":
+# "{'inputs': ['../../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['src/resources/phonemetadata.proto', 'src/resources/phonenumber.proto'], 'action': ['python', '../../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'src/resources', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: $(LOCAL_PATH)/third_party/libphonenumber/src/resources/phonemetadata.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers; cd $(gyp_local_path)/third_party/libphonenumber; python ../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h" --proto-in-dir src/resources --proto-in-file "phonemetadata$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers" --python_out "$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers"
+
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py ;
+.PHONY: third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger
+third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py
+
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: $(LOCAL_PATH)/third_party/libphonenumber/src/resources/phonenumber.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers; cd $(gyp_local_path)/third_party/libphonenumber; python ../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h" --proto-in-dir src/resources --proto-in-file "phonenumber$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers" --python_out "$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers"
+
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py ;
+.PHONY: third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger
+third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/phonemetadata.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/phonenumber.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/phonemetadata.pb.cc \
+	$(gyp_intermediate_dir)/phonenumber.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers
+
+LOCAL_SRC_FILES := \
+	third_party/libphonenumber/src/phonenumbers/asyoutypeformatter.cc \
+	third_party/libphonenumber/src/phonenumbers/base/strings/string_piece.cc \
+	third_party/libphonenumber/src/phonenumbers/default_logger.cc \
+	third_party/libphonenumber/src/phonenumbers/logger.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumber.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumbermatch.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumbermatcher.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumberutil.cc \
+	third_party/libphonenumber/src/phonenumbers/regexp_adapter_icu.cc \
+	third_party/libphonenumber/src/phonenumbers/regexp_cache.cc \
+	third_party/libphonenumber/src/phonenumbers/string_byte_sink.cc \
+	third_party/libphonenumber/src/phonenumbers/stringutil.cc \
+	third_party/libphonenumber/src/phonenumbers/unicodestring.cc \
+	third_party/libphonenumber/src/phonenumbers/utf/rune.c \
+	third_party/libphonenumber/src/phonenumbers/utf/unicodetext.cc \
+	third_party/libphonenumber/src/phonenumbers/utf/unilib.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Alias gyp target name.
+.PHONY: libphonenumber_without_metadata
+libphonenumber_without_metadata: third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-arm.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-arm.mk
index 64781c7..4778f02 100644
--- a/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-arm.mk
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-arm.mk
@@ -151,6 +151,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -251,6 +252,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-mips.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-mips.mk
index 02f53ff..6346994 100644
--- a/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-mips.mk
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-mips.mk
@@ -151,6 +151,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -251,6 +252,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86.mk
index 75d3170..aeabc19 100644
--- a/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86.mk
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86.mk
@@ -152,6 +152,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -252,6 +253,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86_64.mk b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86_64.mk
new file mode 100644
index 0000000..b85a398
--- /dev/null
+++ b/third_party/libphonenumber/libphonenumber_without_metadata.target.linux-x86_64.mk
@@ -0,0 +1,355 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libphonenumber_libphonenumber_without_metadata_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(gyp_shared_intermediate_dir)/protoc
+
+
+### Generated for rule "third_party_libphonenumber_libphonenumber_gyp_libphonenumber_without_metadata_target_genproto":
+# "{'inputs': ['../../tools/protoc_wrapper/protoc_wrapper.py', '$(gyp_shared_intermediate_dir)/protoc'], 'process_outputs_as_sources': '1', 'extension': 'proto', 'outputs': ['$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s_pb2.py', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s.pb.cc', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s.pb.h'], 'rule_name': 'genproto', 'rule_sources': ['src/resources/phonemetadata.proto', 'src/resources/phonenumber.proto'], 'action': ['python', '../../tools/protoc_wrapper/protoc_wrapper.py', '--include', '', '--protobuf', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/%(INPUT_ROOT)s.pb.h', '--proto-in-dir', 'src/resources', '--proto-in-file', '%(INPUT_ROOT)s$(suffix $<)', '--use-system-protobuf=0', '--', '$(gyp_shared_intermediate_dir)/protoc', '--cpp_out', '$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers', '--python_out', '$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers'], 'message': 'Generating C++ and Python code from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py: $(LOCAL_PATH)/third_party/libphonenumber/src/resources/phonemetadata.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers; cd $(gyp_local_path)/third_party/libphonenumber; python ../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h" --proto-in-dir src/resources --proto-in-file "phonemetadata$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers" --python_out "$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers"
+
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py ;
+.PHONY: third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger
+third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py
+
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py: $(LOCAL_PATH)/third_party/libphonenumber/src/resources/phonenumber.proto $(LOCAL_PATH)/tools/protoc_wrapper/protoc_wrapper.py $(gyp_shared_intermediate_dir)/protoc $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers; cd $(gyp_local_path)/third_party/libphonenumber; python ../../tools/protoc_wrapper/protoc_wrapper.py --include "" --protobuf "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h" --proto-in-dir src/resources --proto-in-file "phonenumber$(suffix $<)" "--use-system-protobuf=0" -- "$(gyp_shared_intermediate_dir)/protoc" --cpp_out "$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers" --python_out "$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers"
+
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.cc: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py ;
+$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py ;
+.PHONY: third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger
+third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.cc \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/phonemetadata.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/phonenumber.pb.cc: $(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/phonemetadata.pb.cc \
+	$(gyp_intermediate_dir)/phonenumber.pb.cc \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonemetadata_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonemetadata.pb.h \
+	$(gyp_shared_intermediate_dir)/pyproto/third_party/libphonenumber/phonenumbers/phonenumber_pb2.py \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers/phonenumber.pb.h \
+	third_party_libphonenumber_libphonenumber_without_metadata_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber/phonenumbers
+
+LOCAL_SRC_FILES := \
+	third_party/libphonenumber/src/phonenumbers/asyoutypeformatter.cc \
+	third_party/libphonenumber/src/phonenumbers/base/strings/string_piece.cc \
+	third_party/libphonenumber/src/phonenumbers/default_logger.cc \
+	third_party/libphonenumber/src/phonenumbers/logger.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumber.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumbermatch.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumbermatcher.cc \
+	third_party/libphonenumber/src/phonenumbers/phonenumberutil.cc \
+	third_party/libphonenumber/src/phonenumbers/regexp_adapter_icu.cc \
+	third_party/libphonenumber/src/phonenumbers/regexp_cache.cc \
+	third_party/libphonenumber/src/phonenumbers/string_byte_sink.cc \
+	third_party/libphonenumber/src/phonenumbers/stringutil.cc \
+	third_party/libphonenumber/src/phonenumbers/unicodestring.cc \
+	third_party/libphonenumber/src/phonenumbers/utf/rune.c \
+	third_party/libphonenumber/src/phonenumbers/utf/unicodetext.cc \
+	third_party/libphonenumber/src/phonenumbers/utf/unilib.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DI18N_PHONENUMBERS_USE_ICU_REGEXP=1' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/libphonenumber/src \
+	$(LOCAL_PATH)/third_party/libphonenumber/src/test \
+	$(gyp_shared_intermediate_dir)/protoc_out/third_party/libphonenumber \
+	$(gyp_shared_intermediate_dir)/protoc_out \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+# Alias gyp target name.
+.PHONY: libphonenumber_without_metadata
+libphonenumber_without_metadata: third_party_libphonenumber_libphonenumber_without_metadata_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libpng/libpng.target.darwin-arm.mk b/third_party/libpng/libpng.target.darwin-arm.mk
index a6086c2..23d31c5 100644
--- a/third_party/libpng/libpng.target.darwin-arm.mk
+++ b/third_party/libpng/libpng.target.darwin-arm.mk
@@ -99,6 +99,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libpng/libpng.target.darwin-mips.mk b/third_party/libpng/libpng.target.darwin-mips.mk
index b41782c..b601187 100644
--- a/third_party/libpng/libpng.target.darwin-mips.mk
+++ b/third_party/libpng/libpng.target.darwin-mips.mk
@@ -99,6 +99,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libpng/libpng.target.darwin-x86.mk b/third_party/libpng/libpng.target.darwin-x86.mk
index 8d93d2d..34c487b 100644
--- a/third_party/libpng/libpng.target.darwin-x86.mk
+++ b/third_party/libpng/libpng.target.darwin-x86.mk
@@ -100,6 +100,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -188,6 +189,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libpng/libpng.target.darwin-x86_64.mk b/third_party/libpng/libpng.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d9e6dd9
--- /dev/null
+++ b/third_party/libpng/libpng.target.darwin-x86_64.mk
@@ -0,0 +1,281 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libpng_libpng_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libpng/png.c \
+	third_party/libpng/pngerror.c \
+	third_party/libpng/pnggccrd.c \
+	third_party/libpng/pngget.c \
+	third_party/libpng/pngmem.c \
+	third_party/libpng/pngpread.c \
+	third_party/libpng/pngread.c \
+	third_party/libpng/pngrio.c \
+	third_party/libpng/pngrtran.c \
+	third_party/libpng/pngrutil.c \
+	third_party/libpng/pngset.c \
+	third_party/libpng/pngtrans.c \
+	third_party/libpng/pngvcrd.c \
+	third_party/libpng/pngwio.c \
+	third_party/libpng/pngwrite.c \
+	third_party/libpng/pngwtran.c \
+	third_party/libpng/pngwutil.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libpng_libpng_gyp
+
+# Alias gyp target name.
+.PHONY: libpng
+libpng: third_party_libpng_libpng_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libpng/libpng.target.linux-arm.mk b/third_party/libpng/libpng.target.linux-arm.mk
index a6086c2..23d31c5 100644
--- a/third_party/libpng/libpng.target.linux-arm.mk
+++ b/third_party/libpng/libpng.target.linux-arm.mk
@@ -99,6 +99,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libpng/libpng.target.linux-mips.mk b/third_party/libpng/libpng.target.linux-mips.mk
index b41782c..b601187 100644
--- a/third_party/libpng/libpng.target.linux-mips.mk
+++ b/third_party/libpng/libpng.target.linux-mips.mk
@@ -99,6 +99,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libpng/libpng.target.linux-x86.mk b/third_party/libpng/libpng.target.linux-x86.mk
index 8d93d2d..34c487b 100644
--- a/third_party/libpng/libpng.target.linux-x86.mk
+++ b/third_party/libpng/libpng.target.linux-x86.mk
@@ -100,6 +100,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -188,6 +189,7 @@
 	'-DPNG_USER_CONFIG' \
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libpng/libpng.target.linux-x86_64.mk b/third_party/libpng/libpng.target.linux-x86_64.mk
new file mode 100644
index 0000000..d9e6dd9
--- /dev/null
+++ b/third_party/libpng/libpng.target.linux-x86_64.mk
@@ -0,0 +1,281 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libpng_libpng_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libpng/png.c \
+	third_party/libpng/pngerror.c \
+	third_party/libpng/pnggccrd.c \
+	third_party/libpng/pngget.c \
+	third_party/libpng/pngmem.c \
+	third_party/libpng/pngpread.c \
+	third_party/libpng/pngread.c \
+	third_party/libpng/pngrio.c \
+	third_party/libpng/pngrtran.c \
+	third_party/libpng/pngrutil.c \
+	third_party/libpng/pngset.c \
+	third_party/libpng/pngtrans.c \
+	third_party/libpng/pngvcrd.c \
+	third_party/libpng/pngwio.c \
+	third_party/libpng/pngwrite.c \
+	third_party/libpng/pngwtran.c \
+	third_party/libpng/pngwutil.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libpng_libpng_gyp
+
+# Alias gyp target name.
+.PHONY: libpng
+libpng: third_party_libpng_libpng_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp.target.darwin-x86_64.mk b/third_party/libwebp/libwebp.target.darwin-x86_64.mk
new file mode 100644
index 0000000..2a4d2a9
--- /dev/null
+++ b/third_party/libwebp/libwebp.target.darwin-x86_64.mk
@@ -0,0 +1,44 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_libwebp_libwebp_gyp
+LOCAL_MODULE_STEM := webp
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dec_gyp)/third_party_libwebp_libwebp_dec_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_demux_gyp)/third_party_libwebp_libwebp_demux_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dsp_gyp)/third_party_libwebp_libwebp_dsp_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_dsp_neon_gyp)/libwebp_dsp_neon.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_enc_gyp)/third_party_libwebp_libwebp_enc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_utils_gyp)/third_party_libwebp_libwebp_utils_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp
+libwebp: third_party_libwebp_libwebp_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/libwebp/libwebp.target.linux-x86_64.mk b/third_party/libwebp/libwebp.target.linux-x86_64.mk
new file mode 100644
index 0000000..2a4d2a9
--- /dev/null
+++ b/third_party/libwebp/libwebp.target.linux-x86_64.mk
@@ -0,0 +1,44 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_libwebp_libwebp_gyp
+LOCAL_MODULE_STEM := webp
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dec_gyp)/third_party_libwebp_libwebp_dec_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_demux_gyp)/third_party_libwebp_libwebp_demux_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_dsp_gyp)/third_party_libwebp_libwebp_dsp_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_dsp_neon_gyp)/libwebp_dsp_neon.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_enc_gyp)/third_party_libwebp_libwebp_enc_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_libwebp_libwebp_utils_gyp)/third_party_libwebp_libwebp_utils_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp
+libwebp: third_party_libwebp_libwebp_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/libwebp/libwebp_dec.target.darwin-arm.mk b/third_party/libwebp/libwebp_dec.target.darwin-arm.mk
index 11bfd9d..1cf48a7 100644
--- a/third_party/libwebp/libwebp_dec.target.darwin-arm.mk
+++ b/third_party/libwebp/libwebp_dec.target.darwin-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dec.target.darwin-mips.mk b/third_party/libwebp/libwebp_dec.target.darwin-mips.mk
index 0ecf4f4..d8c0497 100644
--- a/third_party/libwebp/libwebp_dec.target.darwin-mips.mk
+++ b/third_party/libwebp/libwebp_dec.target.darwin-mips.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dec.target.darwin-x86.mk b/third_party/libwebp/libwebp_dec.target.darwin-x86.mk
index bb699de..bb2c697 100644
--- a/third_party/libwebp/libwebp_dec.target.darwin-x86.mk
+++ b/third_party/libwebp/libwebp_dec.target.darwin-x86.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dec.target.darwin-x86_64.mk b/third_party/libwebp/libwebp_dec.target.darwin-x86_64.mk
new file mode 100644
index 0000000..f41aea7
--- /dev/null
+++ b/third_party/libwebp/libwebp_dec.target.darwin-x86_64.mk
@@ -0,0 +1,270 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_dec_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_dsp_neon_gyp)/libwebp_dsp_neon.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/dec/alpha.c \
+	third_party/libwebp/dec/buffer.c \
+	third_party/libwebp/dec/frame.c \
+	third_party/libwebp/dec/idec.c \
+	third_party/libwebp/dec/io.c \
+	third_party/libwebp/dec/layer.c \
+	third_party/libwebp/dec/quant.c \
+	third_party/libwebp/dec/tree.c \
+	third_party/libwebp/dec/vp8.c \
+	third_party/libwebp/dec/vp8l.c \
+	third_party/libwebp/dec/webp.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_dec_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_dec
+libwebp_dec: third_party_libwebp_libwebp_dec_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_dec.target.linux-arm.mk b/third_party/libwebp/libwebp_dec.target.linux-arm.mk
index 11bfd9d..1cf48a7 100644
--- a/third_party/libwebp/libwebp_dec.target.linux-arm.mk
+++ b/third_party/libwebp/libwebp_dec.target.linux-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -175,6 +176,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dec.target.linux-mips.mk b/third_party/libwebp/libwebp_dec.target.linux-mips.mk
index 0ecf4f4..d8c0497 100644
--- a/third_party/libwebp/libwebp_dec.target.linux-mips.mk
+++ b/third_party/libwebp/libwebp_dec.target.linux-mips.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dec.target.linux-x86.mk b/third_party/libwebp/libwebp_dec.target.linux-x86.mk
index bb699de..bb2c697 100644
--- a/third_party/libwebp/libwebp_dec.target.linux-x86.mk
+++ b/third_party/libwebp/libwebp_dec.target.linux-x86.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dec.target.linux-x86_64.mk b/third_party/libwebp/libwebp_dec.target.linux-x86_64.mk
new file mode 100644
index 0000000..f41aea7
--- /dev/null
+++ b/third_party/libwebp/libwebp_dec.target.linux-x86_64.mk
@@ -0,0 +1,270 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_dec_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_libwebp_libwebp_dsp_neon_gyp)/libwebp_dsp_neon.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/dec/alpha.c \
+	third_party/libwebp/dec/buffer.c \
+	third_party/libwebp/dec/frame.c \
+	third_party/libwebp/dec/idec.c \
+	third_party/libwebp/dec/io.c \
+	third_party/libwebp/dec/layer.c \
+	third_party/libwebp/dec/quant.c \
+	third_party/libwebp/dec/tree.c \
+	third_party/libwebp/dec/vp8.c \
+	third_party/libwebp/dec/vp8l.c \
+	third_party/libwebp/dec/webp.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_dec_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_dec
+libwebp_dec: third_party_libwebp_libwebp_dec_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_demux.target.darwin-arm.mk b/third_party/libwebp/libwebp_demux.target.darwin-arm.mk
index 0b04deb..82e2618 100644
--- a/third_party/libwebp/libwebp_demux.target.darwin-arm.mk
+++ b/third_party/libwebp/libwebp_demux.target.darwin-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_demux.target.darwin-mips.mk b/third_party/libwebp/libwebp_demux.target.darwin-mips.mk
index 5be4cfb..53da476 100644
--- a/third_party/libwebp/libwebp_demux.target.darwin-mips.mk
+++ b/third_party/libwebp/libwebp_demux.target.darwin-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_demux.target.darwin-x86.mk b/third_party/libwebp/libwebp_demux.target.darwin-x86.mk
index 4eb7b59..4a6603b 100644
--- a/third_party/libwebp/libwebp_demux.target.darwin-x86.mk
+++ b/third_party/libwebp/libwebp_demux.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_demux.target.darwin-x86_64.mk b/third_party/libwebp/libwebp_demux.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a04f531
--- /dev/null
+++ b/third_party/libwebp/libwebp_demux.target.darwin-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_demux_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/demux/demux.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_demux_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_demux
+libwebp_demux: third_party_libwebp_libwebp_demux_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_demux.target.linux-arm.mk b/third_party/libwebp/libwebp_demux.target.linux-arm.mk
index 0b04deb..82e2618 100644
--- a/third_party/libwebp/libwebp_demux.target.linux-arm.mk
+++ b/third_party/libwebp/libwebp_demux.target.linux-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_demux.target.linux-mips.mk b/third_party/libwebp/libwebp_demux.target.linux-mips.mk
index 5be4cfb..53da476 100644
--- a/third_party/libwebp/libwebp_demux.target.linux-mips.mk
+++ b/third_party/libwebp/libwebp_demux.target.linux-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_demux.target.linux-x86.mk b/third_party/libwebp/libwebp_demux.target.linux-x86.mk
index 4eb7b59..4a6603b 100644
--- a/third_party/libwebp/libwebp_demux.target.linux-x86.mk
+++ b/third_party/libwebp/libwebp_demux.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_demux.target.linux-x86_64.mk b/third_party/libwebp/libwebp_demux.target.linux-x86_64.mk
new file mode 100644
index 0000000..a04f531
--- /dev/null
+++ b/third_party/libwebp/libwebp_demux.target.linux-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_demux_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/demux/demux.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_demux_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_demux
+libwebp_demux: third_party_libwebp_libwebp_demux_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_dsp.target.darwin-arm.mk b/third_party/libwebp/libwebp_dsp.target.darwin-arm.mk
index 0225c0b..ea6f647 100644
--- a/third_party/libwebp/libwebp_dsp.target.darwin-arm.mk
+++ b/third_party/libwebp/libwebp_dsp.target.darwin-arm.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp.target.darwin-mips.mk b/third_party/libwebp/libwebp_dsp.target.darwin-mips.mk
index b1dcc67..ada697c 100644
--- a/third_party/libwebp/libwebp_dsp.target.darwin-mips.mk
+++ b/third_party/libwebp/libwebp_dsp.target.darwin-mips.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp.target.darwin-x86.mk b/third_party/libwebp/libwebp_dsp.target.darwin-x86.mk
index 5503238..2b284cd 100644
--- a/third_party/libwebp/libwebp_dsp.target.darwin-x86.mk
+++ b/third_party/libwebp/libwebp_dsp.target.darwin-x86.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp.target.darwin-x86_64.mk b/third_party/libwebp/libwebp_dsp.target.darwin-x86_64.mk
new file mode 100644
index 0000000..cd57bd1
--- /dev/null
+++ b/third_party/libwebp/libwebp_dsp.target.darwin-x86_64.mk
@@ -0,0 +1,268 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_dsp_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/dsp/cpu.c \
+	third_party/libwebp/dsp/dec.c \
+	third_party/libwebp/dsp/dec_sse2.c \
+	third_party/libwebp/dsp/enc.c \
+	third_party/libwebp/dsp/enc_sse2.c \
+	third_party/libwebp/dsp/lossless.c \
+	third_party/libwebp/dsp/upsampling.c \
+	third_party/libwebp/dsp/upsampling_sse2.c \
+	third_party/libwebp/dsp/yuv.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_dsp_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_dsp
+libwebp_dsp: third_party_libwebp_libwebp_dsp_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_dsp.target.linux-arm.mk b/third_party/libwebp/libwebp_dsp.target.linux-arm.mk
index 0225c0b..ea6f647 100644
--- a/third_party/libwebp/libwebp_dsp.target.linux-arm.mk
+++ b/third_party/libwebp/libwebp_dsp.target.linux-arm.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp.target.linux-mips.mk b/third_party/libwebp/libwebp_dsp.target.linux-mips.mk
index b1dcc67..ada697c 100644
--- a/third_party/libwebp/libwebp_dsp.target.linux-mips.mk
+++ b/third_party/libwebp/libwebp_dsp.target.linux-mips.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp.target.linux-x86.mk b/third_party/libwebp/libwebp_dsp.target.linux-x86.mk
index 5503238..2b284cd 100644
--- a/third_party/libwebp/libwebp_dsp.target.linux-x86.mk
+++ b/third_party/libwebp/libwebp_dsp.target.linux-x86.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp.target.linux-x86_64.mk b/third_party/libwebp/libwebp_dsp.target.linux-x86_64.mk
new file mode 100644
index 0000000..cd57bd1
--- /dev/null
+++ b/third_party/libwebp/libwebp_dsp.target.linux-x86_64.mk
@@ -0,0 +1,268 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_dsp_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/dsp/cpu.c \
+	third_party/libwebp/dsp/dec.c \
+	third_party/libwebp/dsp/dec_sse2.c \
+	third_party/libwebp/dsp/enc.c \
+	third_party/libwebp/dsp/enc_sse2.c \
+	third_party/libwebp/dsp/lossless.c \
+	third_party/libwebp/dsp/upsampling.c \
+	third_party/libwebp/dsp/upsampling_sse2.c \
+	third_party/libwebp/dsp/yuv.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	cpufeatures
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_dsp_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_dsp
+libwebp_dsp: third_party_libwebp_libwebp_dsp_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_dsp_neon.target.darwin-arm.mk b/third_party/libwebp/libwebp_dsp_neon.target.darwin-arm.mk
index baabe40..23b4ad6 100644
--- a/third_party/libwebp/libwebp_dsp_neon.target.darwin-arm.mk
+++ b/third_party/libwebp/libwebp_dsp_neon.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp_neon.target.darwin-x86_64.mk b/third_party/libwebp/libwebp_dsp_neon.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a3635cd
--- /dev/null
+++ b/third_party/libwebp/libwebp_dsp_neon.target.darwin-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_libwebp_libwebp_dsp_neon_gyp
+LOCAL_MODULE_STEM := libwebp_dsp_neon
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_dsp_neon_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_dsp_neon
+libwebp_dsp_neon: third_party_libwebp_libwebp_dsp_neon_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/libwebp/libwebp_dsp_neon.target.linux-arm.mk b/third_party/libwebp/libwebp_dsp_neon.target.linux-arm.mk
index baabe40..23b4ad6 100644
--- a/third_party/libwebp/libwebp_dsp_neon.target.linux-arm.mk
+++ b/third_party/libwebp/libwebp_dsp_neon.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -169,6 +170,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_dsp_neon.target.linux-x86_64.mk b/third_party/libwebp/libwebp_dsp_neon.target.linux-x86_64.mk
new file mode 100644
index 0000000..a3635cd
--- /dev/null
+++ b/third_party/libwebp/libwebp_dsp_neon.target.linux-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_libwebp_libwebp_dsp_neon_gyp
+LOCAL_MODULE_STEM := libwebp_dsp_neon
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_dsp_neon_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_dsp_neon
+libwebp_dsp_neon: third_party_libwebp_libwebp_dsp_neon_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/libwebp/libwebp_enc.target.darwin-arm.mk b/third_party/libwebp/libwebp_enc.target.darwin-arm.mk
index 055426b..e57a7d5 100644
--- a/third_party/libwebp/libwebp_enc.target.darwin-arm.mk
+++ b/third_party/libwebp/libwebp_enc.target.darwin-arm.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -181,6 +182,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_enc.target.darwin-mips.mk b/third_party/libwebp/libwebp_enc.target.darwin-mips.mk
index 89cf8a6..282ae09 100644
--- a/third_party/libwebp/libwebp_enc.target.darwin-mips.mk
+++ b/third_party/libwebp/libwebp_enc.target.darwin-mips.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -181,6 +182,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_enc.target.darwin-x86.mk b/third_party/libwebp/libwebp_enc.target.darwin-x86.mk
index 281a07c..9e376f9 100644
--- a/third_party/libwebp/libwebp_enc.target.darwin-x86.mk
+++ b/third_party/libwebp/libwebp_enc.target.darwin-x86.mk
@@ -97,6 +97,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -182,6 +183,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_enc.target.darwin-x86_64.mk b/third_party/libwebp/libwebp_enc.target.darwin-x86_64.mk
new file mode 100644
index 0000000..e0df7d0
--- /dev/null
+++ b/third_party/libwebp/libwebp_enc.target.darwin-x86_64.mk
@@ -0,0 +1,275 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_enc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/enc/alpha.c \
+	third_party/libwebp/enc/analysis.c \
+	third_party/libwebp/enc/backward_references.c \
+	third_party/libwebp/enc/config.c \
+	third_party/libwebp/enc/cost.c \
+	third_party/libwebp/enc/filter.c \
+	third_party/libwebp/enc/frame.c \
+	third_party/libwebp/enc/histogram.c \
+	third_party/libwebp/enc/iterator.c \
+	third_party/libwebp/enc/layer.c \
+	third_party/libwebp/enc/picture.c \
+	third_party/libwebp/enc/quant.c \
+	third_party/libwebp/enc/syntax.c \
+	third_party/libwebp/enc/token.c \
+	third_party/libwebp/enc/tree.c \
+	third_party/libwebp/enc/vp8l.c \
+	third_party/libwebp/enc/webpenc.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_enc_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_enc
+libwebp_enc: third_party_libwebp_libwebp_enc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_enc.target.linux-arm.mk b/third_party/libwebp/libwebp_enc.target.linux-arm.mk
index 055426b..e57a7d5 100644
--- a/third_party/libwebp/libwebp_enc.target.linux-arm.mk
+++ b/third_party/libwebp/libwebp_enc.target.linux-arm.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -181,6 +182,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_enc.target.linux-mips.mk b/third_party/libwebp/libwebp_enc.target.linux-mips.mk
index 89cf8a6..282ae09 100644
--- a/third_party/libwebp/libwebp_enc.target.linux-mips.mk
+++ b/third_party/libwebp/libwebp_enc.target.linux-mips.mk
@@ -96,6 +96,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -181,6 +182,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_enc.target.linux-x86.mk b/third_party/libwebp/libwebp_enc.target.linux-x86.mk
index 281a07c..9e376f9 100644
--- a/third_party/libwebp/libwebp_enc.target.linux-x86.mk
+++ b/third_party/libwebp/libwebp_enc.target.linux-x86.mk
@@ -97,6 +97,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -182,6 +183,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_enc.target.linux-x86_64.mk b/third_party/libwebp/libwebp_enc.target.linux-x86_64.mk
new file mode 100644
index 0000000..e0df7d0
--- /dev/null
+++ b/third_party/libwebp/libwebp_enc.target.linux-x86_64.mk
@@ -0,0 +1,275 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_enc_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/enc/alpha.c \
+	third_party/libwebp/enc/analysis.c \
+	third_party/libwebp/enc/backward_references.c \
+	third_party/libwebp/enc/config.c \
+	third_party/libwebp/enc/cost.c \
+	third_party/libwebp/enc/filter.c \
+	third_party/libwebp/enc/frame.c \
+	third_party/libwebp/enc/histogram.c \
+	third_party/libwebp/enc/iterator.c \
+	third_party/libwebp/enc/layer.c \
+	third_party/libwebp/enc/picture.c \
+	third_party/libwebp/enc/quant.c \
+	third_party/libwebp/enc/syntax.c \
+	third_party/libwebp/enc/token.c \
+	third_party/libwebp/enc/tree.c \
+	third_party/libwebp/enc/vp8l.c \
+	third_party/libwebp/enc/webpenc.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_enc_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_enc
+libwebp_enc: third_party_libwebp_libwebp_enc_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_utils.target.darwin-arm.mk b/third_party/libwebp/libwebp_utils.target.darwin-arm.mk
index 0e8aa57..d5ce248 100644
--- a/third_party/libwebp/libwebp_utils.target.darwin-arm.mk
+++ b/third_party/libwebp/libwebp_utils.target.darwin-arm.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_utils.target.darwin-mips.mk b/third_party/libwebp/libwebp_utils.target.darwin-mips.mk
index dcfb31e..fab7cef 100644
--- a/third_party/libwebp/libwebp_utils.target.darwin-mips.mk
+++ b/third_party/libwebp/libwebp_utils.target.darwin-mips.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_utils.target.darwin-x86.mk b/third_party/libwebp/libwebp_utils.target.darwin-x86.mk
index 9541aa5..31de9ee 100644
--- a/third_party/libwebp/libwebp_utils.target.darwin-x86.mk
+++ b/third_party/libwebp/libwebp_utils.target.darwin-x86.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_utils.target.darwin-x86_64.mk b/third_party/libwebp/libwebp_utils.target.darwin-x86_64.mk
new file mode 100644
index 0000000..592d9c2
--- /dev/null
+++ b/third_party/libwebp/libwebp_utils.target.darwin-x86_64.mk
@@ -0,0 +1,271 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_utils_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/utils/alpha_processing.c \
+	third_party/libwebp/utils/bit_reader.c \
+	third_party/libwebp/utils/bit_writer.c \
+	third_party/libwebp/utils/color_cache.c \
+	third_party/libwebp/utils/filters.c \
+	third_party/libwebp/utils/huffman.c \
+	third_party/libwebp/utils/huffman_encode.c \
+	third_party/libwebp/utils/quant_levels.c \
+	third_party/libwebp/utils/quant_levels_dec.c \
+	third_party/libwebp/utils/random.c \
+	third_party/libwebp/utils/rescaler.c \
+	third_party/libwebp/utils/thread.c \
+	third_party/libwebp/utils/utils.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_utils_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_utils
+libwebp_utils: third_party_libwebp_libwebp_utils_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libwebp/libwebp_utils.target.linux-arm.mk b/third_party/libwebp/libwebp_utils.target.linux-arm.mk
index 0e8aa57..d5ce248 100644
--- a/third_party/libwebp/libwebp_utils.target.linux-arm.mk
+++ b/third_party/libwebp/libwebp_utils.target.linux-arm.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_utils.target.linux-mips.mk b/third_party/libwebp/libwebp_utils.target.linux-mips.mk
index dcfb31e..fab7cef 100644
--- a/third_party/libwebp/libwebp_utils.target.linux-mips.mk
+++ b/third_party/libwebp/libwebp_utils.target.linux-mips.mk
@@ -92,6 +92,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_utils.target.linux-x86.mk b/third_party/libwebp/libwebp_utils.target.linux-x86.mk
index 9541aa5..31de9ee 100644
--- a/third_party/libwebp/libwebp_utils.target.linux-x86.mk
+++ b/third_party/libwebp/libwebp_utils.target.linux-x86.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -178,6 +179,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libwebp/libwebp_utils.target.linux-x86_64.mk b/third_party/libwebp/libwebp_utils.target.linux-x86_64.mk
new file mode 100644
index 0000000..592d9c2
--- /dev/null
+++ b/third_party/libwebp/libwebp_utils.target.linux-x86_64.mk
@@ -0,0 +1,271 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libwebp_libwebp_utils_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libwebp/utils/alpha_processing.c \
+	third_party/libwebp/utils/bit_reader.c \
+	third_party/libwebp/utils/bit_writer.c \
+	third_party/libwebp/utils/color_cache.c \
+	third_party/libwebp/utils/filters.c \
+	third_party/libwebp/utils/huffman.c \
+	third_party/libwebp/utils/huffman_encode.c \
+	third_party/libwebp/utils/quant_levels.c \
+	third_party/libwebp/utils/quant_levels_dec.c \
+	third_party/libwebp/utils/random.c \
+	third_party/libwebp/utils/rescaler.c \
+	third_party/libwebp/utils/thread.c \
+	third_party/libwebp/utils/utils.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libwebp_libwebp_utils_gyp
+
+# Alias gyp target name.
+.PHONY: libwebp_utils
+libwebp_utils: third_party_libwebp_libwebp_utils_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libxml/libxml.gyp b/third_party/libxml/libxml.gyp
index a9343fd..c005f6a 100644
--- a/third_party/libxml/libxml.gyp
+++ b/third_party/libxml/libxml.gyp
@@ -243,11 +243,14 @@
                   # move the `'` to its own line, but until that's landed
                   # suppress the warning:
                   '-Wno-empty-body',
+                  # debugXML.c compares array 'arg' to NULL.
+                  '-Wno-tautological-pointer-compare',
                 ],
               },
               'cflags': [
                 '-Wno-pointer-sign',
                 '-Wno-empty-body',
+                '-Wno-tautological-pointer-compare',
 
                 # See http://crbug.com/138571#c8
                 '-Wno-ignored-attributes',
diff --git a/third_party/libxml/libxml.target.darwin-arm.mk b/third_party/libxml/libxml.target.darwin-arm.mk
index f87dda0..5a8054a 100644
--- a/third_party/libxml/libxml.target.darwin-arm.mk
+++ b/third_party/libxml/libxml.target.darwin-arm.mk
@@ -128,6 +128,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -222,6 +223,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxml/libxml.target.darwin-mips.mk b/third_party/libxml/libxml.target.darwin-mips.mk
index e1dd155..e9adeb8 100644
--- a/third_party/libxml/libxml.target.darwin-mips.mk
+++ b/third_party/libxml/libxml.target.darwin-mips.mk
@@ -128,6 +128,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -222,6 +223,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxml/libxml.target.darwin-x86.mk b/third_party/libxml/libxml.target.darwin-x86.mk
index 7eeeeca..15d8298 100644
--- a/third_party/libxml/libxml.target.darwin-x86.mk
+++ b/third_party/libxml/libxml.target.darwin-x86.mk
@@ -129,6 +129,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -223,6 +224,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxml/libxml.target.darwin-x86_64.mk b/third_party/libxml/libxml.target.darwin-x86_64.mk
new file mode 100644
index 0000000..34be18a
--- /dev/null
+++ b/third_party/libxml/libxml.target.darwin-x86_64.mk
@@ -0,0 +1,322 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libxml_libxml_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libxml/chromium/libxml_utils.cc \
+	third_party/libxml/src/c14n.c \
+	third_party/libxml/src/catalog.c \
+	third_party/libxml/src/chvalid.c \
+	third_party/libxml/src/debugXML.c \
+	third_party/libxml/src/dict.c \
+	third_party/libxml/src/DOCBparser.c \
+	third_party/libxml/src/encoding.c \
+	third_party/libxml/src/entities.c \
+	third_party/libxml/src/error.c \
+	third_party/libxml/src/globals.c \
+	third_party/libxml/src/hash.c \
+	third_party/libxml/src/HTMLparser.c \
+	third_party/libxml/src/HTMLtree.c \
+	third_party/libxml/src/legacy.c \
+	third_party/libxml/src/list.c \
+	third_party/libxml/src/nanoftp.c \
+	third_party/libxml/src/nanohttp.c \
+	third_party/libxml/src/parser.c \
+	third_party/libxml/src/parserInternals.c \
+	third_party/libxml/src/pattern.c \
+	third_party/libxml/src/relaxng.c \
+	third_party/libxml/src/SAX.c \
+	third_party/libxml/src/SAX2.c \
+	third_party/libxml/src/schematron.c \
+	third_party/libxml/src/threads.c \
+	third_party/libxml/src/tree.c \
+	third_party/libxml/src/uri.c \
+	third_party/libxml/src/valid.c \
+	third_party/libxml/src/xinclude.c \
+	third_party/libxml/src/xlink.c \
+	third_party/libxml/src/xmlIO.c \
+	third_party/libxml/src/xmlmemory.c \
+	third_party/libxml/src/xmlmodule.c \
+	third_party/libxml/src/xmlreader.c \
+	third_party/libxml/src/xmlregexp.c \
+	third_party/libxml/src/xmlsave.c \
+	third_party/libxml/src/xmlschemas.c \
+	third_party/libxml/src/xmlschemastypes.c \
+	third_party/libxml/src/xmlstring.c \
+	third_party/libxml/src/xmlunicode.c \
+	third_party/libxml/src/xmlwriter.c \
+	third_party/libxml/src/xpath.c \
+	third_party/libxml/src/xpointer.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXML_STATIC=' \
+	'-D_REENTRANT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxml/linux \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXML_STATIC=' \
+	'-D_REENTRANT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxml/linux \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libxml_libxml_gyp
+
+# Alias gyp target name.
+.PHONY: libxml
+libxml: third_party_libxml_libxml_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libxml/libxml.target.linux-arm.mk b/third_party/libxml/libxml.target.linux-arm.mk
index f87dda0..5a8054a 100644
--- a/third_party/libxml/libxml.target.linux-arm.mk
+++ b/third_party/libxml/libxml.target.linux-arm.mk
@@ -128,6 +128,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -222,6 +223,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxml/libxml.target.linux-mips.mk b/third_party/libxml/libxml.target.linux-mips.mk
index e1dd155..e9adeb8 100644
--- a/third_party/libxml/libxml.target.linux-mips.mk
+++ b/third_party/libxml/libxml.target.linux-mips.mk
@@ -128,6 +128,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -222,6 +223,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxml/libxml.target.linux-x86.mk b/third_party/libxml/libxml.target.linux-x86.mk
index 7eeeeca..15d8298 100644
--- a/third_party/libxml/libxml.target.linux-x86.mk
+++ b/third_party/libxml/libxml.target.linux-x86.mk
@@ -129,6 +129,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -223,6 +224,7 @@
 	'-D_REENTRANT' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxml/libxml.target.linux-x86_64.mk b/third_party/libxml/libxml.target.linux-x86_64.mk
new file mode 100644
index 0000000..34be18a
--- /dev/null
+++ b/third_party/libxml/libxml.target.linux-x86_64.mk
@@ -0,0 +1,322 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libxml_libxml_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libxml/chromium/libxml_utils.cc \
+	third_party/libxml/src/c14n.c \
+	third_party/libxml/src/catalog.c \
+	third_party/libxml/src/chvalid.c \
+	third_party/libxml/src/debugXML.c \
+	third_party/libxml/src/dict.c \
+	third_party/libxml/src/DOCBparser.c \
+	third_party/libxml/src/encoding.c \
+	third_party/libxml/src/entities.c \
+	third_party/libxml/src/error.c \
+	third_party/libxml/src/globals.c \
+	third_party/libxml/src/hash.c \
+	third_party/libxml/src/HTMLparser.c \
+	third_party/libxml/src/HTMLtree.c \
+	third_party/libxml/src/legacy.c \
+	third_party/libxml/src/list.c \
+	third_party/libxml/src/nanoftp.c \
+	third_party/libxml/src/nanohttp.c \
+	third_party/libxml/src/parser.c \
+	third_party/libxml/src/parserInternals.c \
+	third_party/libxml/src/pattern.c \
+	third_party/libxml/src/relaxng.c \
+	third_party/libxml/src/SAX.c \
+	third_party/libxml/src/SAX2.c \
+	third_party/libxml/src/schematron.c \
+	third_party/libxml/src/threads.c \
+	third_party/libxml/src/tree.c \
+	third_party/libxml/src/uri.c \
+	third_party/libxml/src/valid.c \
+	third_party/libxml/src/xinclude.c \
+	third_party/libxml/src/xlink.c \
+	third_party/libxml/src/xmlIO.c \
+	third_party/libxml/src/xmlmemory.c \
+	third_party/libxml/src/xmlmodule.c \
+	third_party/libxml/src/xmlreader.c \
+	third_party/libxml/src/xmlregexp.c \
+	third_party/libxml/src/xmlsave.c \
+	third_party/libxml/src/xmlschemas.c \
+	third_party/libxml/src/xmlschemastypes.c \
+	third_party/libxml/src/xmlstring.c \
+	third_party/libxml/src/xmlunicode.c \
+	third_party/libxml/src/xmlwriter.c \
+	third_party/libxml/src/xpath.c \
+	third_party/libxml/src/xpointer.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXML_STATIC=' \
+	'-D_REENTRANT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxml/linux \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXML_STATIC=' \
+	'-D_REENTRANT' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxml/linux \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libxml_libxml_gyp
+
+# Alias gyp target name.
+.PHONY: libxml
+libxml: third_party_libxml_libxml_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libxslt/libxslt.target.darwin-arm.mk b/third_party/libxslt/libxslt.target.darwin-arm.mk
index 6c2656e..9c7d391 100644
--- a/third_party/libxslt/libxslt.target.darwin-arm.mk
+++ b/third_party/libxslt/libxslt.target.darwin-arm.mk
@@ -101,6 +101,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -195,6 +196,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxslt/libxslt.target.darwin-mips.mk b/third_party/libxslt/libxslt.target.darwin-mips.mk
index ea6a648..a1511f4 100644
--- a/third_party/libxslt/libxslt.target.darwin-mips.mk
+++ b/third_party/libxslt/libxslt.target.darwin-mips.mk
@@ -101,6 +101,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -195,6 +196,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxslt/libxslt.target.darwin-x86.mk b/third_party/libxslt/libxslt.target.darwin-x86.mk
index ea0bc76..b1faae8 100644
--- a/third_party/libxslt/libxslt.target.darwin-x86.mk
+++ b/third_party/libxslt/libxslt.target.darwin-x86.mk
@@ -102,6 +102,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -196,6 +197,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxslt/libxslt.target.darwin-x86_64.mk b/third_party/libxslt/libxslt.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7617f96
--- /dev/null
+++ b/third_party/libxslt/libxslt.target.darwin-x86_64.mk
@@ -0,0 +1,295 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libxslt_libxslt_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libxslt/libxslt/attributes.c \
+	third_party/libxslt/libxslt/attrvt.c \
+	third_party/libxslt/libxslt/documents.c \
+	third_party/libxslt/libxslt/extensions.c \
+	third_party/libxslt/libxslt/extra.c \
+	third_party/libxslt/libxslt/functions.c \
+	third_party/libxslt/libxslt/imports.c \
+	third_party/libxslt/libxslt/keys.c \
+	third_party/libxslt/libxslt/namespaces.c \
+	third_party/libxslt/libxslt/numbers.c \
+	third_party/libxslt/libxslt/pattern.c \
+	third_party/libxslt/libxslt/preproc.c \
+	third_party/libxslt/libxslt/security.c \
+	third_party/libxslt/libxslt/templates.c \
+	third_party/libxslt/libxslt/transform.c \
+	third_party/libxslt/libxslt/variables.c \
+	third_party/libxslt/libxslt/xslt.c \
+	third_party/libxslt/libxslt/xsltlocale.c \
+	third_party/libxslt/libxslt/xsltutils.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXSLT_STATIC' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxslt/linux \
+	$(LOCAL_PATH)/third_party/libxslt \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXSLT_STATIC' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxslt/linux \
+	$(LOCAL_PATH)/third_party/libxslt \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libxslt_libxslt_gyp
+
+# Alias gyp target name.
+.PHONY: libxslt
+libxslt: third_party_libxslt_libxslt_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/libxslt/libxslt.target.linux-arm.mk b/third_party/libxslt/libxslt.target.linux-arm.mk
index 6c2656e..9c7d391 100644
--- a/third_party/libxslt/libxslt.target.linux-arm.mk
+++ b/third_party/libxslt/libxslt.target.linux-arm.mk
@@ -101,6 +101,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -195,6 +196,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxslt/libxslt.target.linux-mips.mk b/third_party/libxslt/libxslt.target.linux-mips.mk
index ea6a648..a1511f4 100644
--- a/third_party/libxslt/libxslt.target.linux-mips.mk
+++ b/third_party/libxslt/libxslt.target.linux-mips.mk
@@ -101,6 +101,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -195,6 +196,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxslt/libxslt.target.linux-x86.mk b/third_party/libxslt/libxslt.target.linux-x86.mk
index ea0bc76..b1faae8 100644
--- a/third_party/libxslt/libxslt.target.linux-x86.mk
+++ b/third_party/libxslt/libxslt.target.linux-x86.mk
@@ -102,6 +102,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -196,6 +197,7 @@
 	'-DLIBXML_STATIC' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/libxslt/libxslt.target.linux-x86_64.mk b/third_party/libxslt/libxslt.target.linux-x86_64.mk
new file mode 100644
index 0000000..7617f96
--- /dev/null
+++ b/third_party/libxslt/libxslt.target.linux-x86_64.mk
@@ -0,0 +1,295 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_libxslt_libxslt_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/libxslt/libxslt/attributes.c \
+	third_party/libxslt/libxslt/attrvt.c \
+	third_party/libxslt/libxslt/documents.c \
+	third_party/libxslt/libxslt/extensions.c \
+	third_party/libxslt/libxslt/extra.c \
+	third_party/libxslt/libxslt/functions.c \
+	third_party/libxslt/libxslt/imports.c \
+	third_party/libxslt/libxslt/keys.c \
+	third_party/libxslt/libxslt/namespaces.c \
+	third_party/libxslt/libxslt/numbers.c \
+	third_party/libxslt/libxslt/pattern.c \
+	third_party/libxslt/libxslt/preproc.c \
+	third_party/libxslt/libxslt/security.c \
+	third_party/libxslt/libxslt/templates.c \
+	third_party/libxslt/libxslt/transform.c \
+	third_party/libxslt/libxslt/variables.c \
+	third_party/libxslt/libxslt/xslt.c \
+	third_party/libxslt/libxslt/xsltlocale.c \
+	third_party/libxslt/libxslt/xsltutils.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXSLT_STATIC' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxslt/linux \
+	$(LOCAL_PATH)/third_party/libxslt \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBXSLT_STATIC' \
+	'-DLIBXML_STATIC' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/libxslt/linux \
+	$(LOCAL_PATH)/third_party/libxslt \
+	$(LOCAL_PATH)/third_party/libxml/linux/include \
+	$(LOCAL_PATH)/third_party/libxml/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_libxslt_libxslt_gyp
+
+# Alias gyp target name.
+.PHONY: libxslt
+libxslt: third_party_libxslt_libxslt_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.darwin-arm.mk b/third_party/lzma_sdk/lzma_sdk.target.darwin-arm.mk
new file mode 100644
index 0000000..cbc1a9c
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.darwin-arm.mk
@@ -0,0 +1,284 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.darwin-mips.mk b/third_party/lzma_sdk/lzma_sdk.target.darwin-mips.mk
new file mode 100644
index 0000000..bcf3a1b
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.darwin-mips.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.darwin-x86.mk b/third_party/lzma_sdk/lzma_sdk.target.darwin-x86.mk
new file mode 100644
index 0000000..a2c1899
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.darwin-x86.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.darwin-x86_64.mk b/third_party/lzma_sdk/lzma_sdk.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4ad978c
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.darwin-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.linux-arm.mk b/third_party/lzma_sdk/lzma_sdk.target.linux-arm.mk
new file mode 100644
index 0000000..cbc1a9c
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.linux-arm.mk
@@ -0,0 +1,284 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-fno-tree-sra \
+	-fuse-ld=gold \
+	-Wno-psabi \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-abi \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-Wl,-z,relro \
+	-Wl,-z,now \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--icf=safe \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.linux-mips.mk b/third_party/lzma_sdk/lzma_sdk.target.linux-mips.mk
new file mode 100644
index 0000000..bcf3a1b
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.linux-mips.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-EL \
+	-mhard-float \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-uninitialized \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-EL \
+	-Wl,--no-keep-memory \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.linux-x86.mk b/third_party/lzma_sdk/lzma_sdk.target.linux-x86.mk
new file mode 100644
index 0000000..a2c1899
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.linux-x86.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-format \
+	-msse2 \
+	-mfpmath=sse \
+	-mmmx \
+	-m32 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-fno-stack-protector \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m32 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/lzma_sdk/lzma_sdk.target.linux-x86_64.mk b/third_party/lzma_sdk/lzma_sdk.target.linux-x86_64.mk
new file mode 100644
index 0000000..4ad978c
--- /dev/null
+++ b/third_party/lzma_sdk/lzma_sdk.target.linux-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_lzma_sdk_lzma_sdk_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/lzma_sdk/7zAlloc.c \
+	third_party/lzma_sdk/7zBuf.c \
+	third_party/lzma_sdk/7zCrc.c \
+	third_party/lzma_sdk/7zCrcOpt.c \
+	third_party/lzma_sdk/7zDec.c \
+	third_party/lzma_sdk/7zFile.c \
+	third_party/lzma_sdk/7zIn.c \
+	third_party/lzma_sdk/7zStream.c \
+	third_party/lzma_sdk/Alloc.c \
+	third_party/lzma_sdk/Bcj2.c \
+	third_party/lzma_sdk/Bra.c \
+	third_party/lzma_sdk/Bra86.c \
+	third_party/lzma_sdk/CpuArch.c \
+	third_party/lzma_sdk/LzFind.c \
+	third_party/lzma_sdk/Lzma2Dec.c \
+	third_party/lzma_sdk/LzmaEnc.c \
+	third_party/lzma_sdk/LzmaDec.c \
+	third_party/lzma_sdk/LzmaLib.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-D_7ZIP_ST' \
+	'-D_LZMA_PROB32' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/lzma_sdk \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_lzma_sdk_lzma_sdk_gyp
+
+# Alias gyp target name.
+.PHONY: lzma_sdk
+lzma_sdk: third_party_lzma_sdk_lzma_sdk_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/mesa/mesa_headers.target.darwin-x86_64.mk b/third_party/mesa/mesa_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7738cff
--- /dev/null
+++ b/third_party/mesa/mesa_headers.target.darwin-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_mesa_mesa_headers_gyp
+LOCAL_MODULE_STEM := mesa_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_mesa_mesa_headers_gyp
+
+# Alias gyp target name.
+.PHONY: mesa_headers
+mesa_headers: third_party_mesa_mesa_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/mesa/mesa_headers.target.linux-x86_64.mk b/third_party/mesa/mesa_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..7738cff
--- /dev/null
+++ b/third_party/mesa/mesa_headers.target.linux-x86_64.mk
@@ -0,0 +1,38 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_mesa_mesa_headers_gyp
+LOCAL_MODULE_STEM := mesa_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_mesa_mesa_headers_gyp
+
+# Alias gyp target name.
+.PHONY: mesa_headers
+mesa_headers: third_party_mesa_mesa_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/modp_b64/modp_b64.target.darwin-arm.mk b/third_party/modp_b64/modp_b64.target.darwin-arm.mk
index b8b211e..c261c8f 100644
--- a/third_party/modp_b64/modp_b64.target.darwin-arm.mk
+++ b/third_party/modp_b64/modp_b64.target.darwin-arm.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/modp_b64/modp_b64.target.darwin-mips.mk b/third_party/modp_b64/modp_b64.target.darwin-mips.mk
index 82857d5..548c8c1 100644
--- a/third_party/modp_b64/modp_b64.target.darwin-mips.mk
+++ b/third_party/modp_b64/modp_b64.target.darwin-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/modp_b64/modp_b64.target.darwin-x86.mk b/third_party/modp_b64/modp_b64.target.darwin-x86.mk
index bd95396..d26f325 100644
--- a/third_party/modp_b64/modp_b64.target.darwin-x86.mk
+++ b/third_party/modp_b64/modp_b64.target.darwin-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/modp_b64/modp_b64.target.darwin-x86_64.mk b/third_party/modp_b64/modp_b64.target.darwin-x86_64.mk
new file mode 100644
index 0000000..265c4ad
--- /dev/null
+++ b/third_party/modp_b64/modp_b64.target.darwin-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_modp_b64_modp_b64_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/modp_b64/modp_b64.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_modp_b64_modp_b64_gyp
+
+# Alias gyp target name.
+.PHONY: modp_b64
+modp_b64: third_party_modp_b64_modp_b64_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/modp_b64/modp_b64.target.linux-arm.mk b/third_party/modp_b64/modp_b64.target.linux-arm.mk
index b8b211e..c261c8f 100644
--- a/third_party/modp_b64/modp_b64.target.linux-arm.mk
+++ b/third_party/modp_b64/modp_b64.target.linux-arm.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/modp_b64/modp_b64.target.linux-mips.mk b/third_party/modp_b64/modp_b64.target.linux-mips.mk
index 82857d5..548c8c1 100644
--- a/third_party/modp_b64/modp_b64.target.linux-mips.mk
+++ b/third_party/modp_b64/modp_b64.target.linux-mips.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -166,6 +167,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/modp_b64/modp_b64.target.linux-x86.mk b/third_party/modp_b64/modp_b64.target.linux-x86.mk
index bd95396..d26f325 100644
--- a/third_party/modp_b64/modp_b64.target.linux-x86.mk
+++ b/third_party/modp_b64/modp_b64.target.linux-x86.mk
@@ -82,6 +82,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -167,6 +168,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/modp_b64/modp_b64.target.linux-x86_64.mk b/third_party/modp_b64/modp_b64.target.linux-x86_64.mk
new file mode 100644
index 0000000..265c4ad
--- /dev/null
+++ b/third_party/modp_b64/modp_b64.target.linux-x86_64.mk
@@ -0,0 +1,260 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_modp_b64_modp_b64_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/modp_b64/modp_b64.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_modp_b64_modp_b64_gyp
+
+# Alias gyp target name.
+.PHONY: modp_b64
+modp_b64: third_party_modp_b64_modp_b64_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/npapi/npapi.target.darwin-arm.mk b/third_party/npapi/npapi.target.darwin-arm.mk
index 83d0075..ada1087 100644
--- a/third_party/npapi/npapi.target.darwin-arm.mk
+++ b/third_party/npapi/npapi.target.darwin-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/npapi/npapi.target.darwin-mips.mk b/third_party/npapi/npapi.target.darwin-mips.mk
index c743548..7f107db 100644
--- a/third_party/npapi/npapi.target.darwin-mips.mk
+++ b/third_party/npapi/npapi.target.darwin-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/npapi/npapi.target.darwin-x86.mk b/third_party/npapi/npapi.target.darwin-x86.mk
index 94c6355..1ad62e6 100644
--- a/third_party/npapi/npapi.target.darwin-x86.mk
+++ b/third_party/npapi/npapi.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/npapi/npapi.target.darwin-x86_64.mk b/third_party/npapi/npapi.target.darwin-x86_64.mk
new file mode 100644
index 0000000..f57d5fd
--- /dev/null
+++ b/third_party/npapi/npapi.target.darwin-x86_64.mk
@@ -0,0 +1,219 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_npapi_npapi_gyp
+LOCAL_MODULE_STEM := npapi
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_npapi_npapi_gyp
+
+# Alias gyp target name.
+.PHONY: npapi
+npapi: third_party_npapi_npapi_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/npapi/npapi.target.linux-arm.mk b/third_party/npapi/npapi.target.linux-arm.mk
index 83d0075..ada1087 100644
--- a/third_party/npapi/npapi.target.linux-arm.mk
+++ b/third_party/npapi/npapi.target.linux-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/npapi/npapi.target.linux-mips.mk b/third_party/npapi/npapi.target.linux-mips.mk
index c743548..7f107db 100644
--- a/third_party/npapi/npapi.target.linux-mips.mk
+++ b/third_party/npapi/npapi.target.linux-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/npapi/npapi.target.linux-x86.mk b/third_party/npapi/npapi.target.linux-x86.mk
index 94c6355..1ad62e6 100644
--- a/third_party/npapi/npapi.target.linux-x86.mk
+++ b/third_party/npapi/npapi.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/npapi/npapi.target.linux-x86_64.mk b/third_party/npapi/npapi.target.linux-x86_64.mk
new file mode 100644
index 0000000..f57d5fd
--- /dev/null
+++ b/third_party/npapi/npapi.target.linux-x86_64.mk
@@ -0,0 +1,219 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_npapi_npapi_gyp
+LOCAL_MODULE_STEM := npapi
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_npapi_npapi_gyp
+
+# Alias gyp target name.
+.PHONY: npapi
+npapi: third_party_npapi_npapi_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/opus/opus.gyp b/third_party/opus/opus.gyp
index be0ae4e..7747c97 100644
--- a/third_party/opus/opus.gyp
+++ b/third_party/opus/opus.gyp
@@ -5,10 +5,12 @@
 {
   'variables': {
     'conditions': [
-      ['OS=="android"', {
+      ['(OS=="android" or chromeos==1) and target_arch=="arm"', {
         'use_opus_fixed_point%': 1,
+        'use_opus_arm_optimization%': 1,
       }, {
         'use_opus_fixed_point%': 0,
+        'use_opus_arm_optimization%': 0,
       }],
     ],
   },
@@ -48,6 +50,13 @@
             4334,  # Disable 32-bit shift warning in src/opus_encoder.c .
           ],
         }],
+        [ 'os_posix==1 and OS!="android"', {
+          'cflags': [
+            # Suppress a warning given by opus_decoder.c that tells us
+            # optimizations are turned off.
+            '-Wno-#pragma-messages',
+          ],
+        }],
         ['use_opus_fixed_point==0', {
           'include_dirs': [
             'src/silk/float',
@@ -65,6 +74,22 @@
           'sources/': [
             ['exclude', '/float/[^/]*_FLP.(h|c)$'],
           ],
+          'conditions': [
+            ['use_opus_arm_optimization==1', {
+              'defines': [
+                'OPUS_ARM_ASM',
+                'OPUS_ARM_INLINE_ASM',
+                'OPUS_ARM_INLINE_EDSP',
+                'OPUS_ARM_MAY_HAVE_EDSP',
+                'OPUS_ARM_MAY_HAVE_MEDIA',
+                'OPUS_ARM_MAY_HAVE_NEON',
+                'OPUS_HAVE_RTCD',
+              ],
+              'includes': [
+                'opus_srcs_arm.gypi',
+              ],
+            }],
+          ],
         }],
       ],
     },  # target opus
diff --git a/third_party/opus/opus.target.darwin-arm.mk b/third_party/opus/opus.target.darwin-arm.mk
index 7e3c4c8..0e9aaf3 100644
--- a/third_party/opus/opus.target.darwin-arm.mk
+++ b/third_party/opus/opus.target.darwin-arm.mk
@@ -12,12 +12,25 @@
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES :=
 
-GYP_GENERATED_OUTPUTS :=
+### Rules for action "convert_assembler":
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: $(LOCAL_PATH)/third_party/opus/src/celt/arm/arm2gnu.pl $(LOCAL_PATH)/third_party/opus/src/celt/arm/celt_pitch_xcorr_arm.s $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Convert Opus assembler for ARM. ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/opus; mkdir -p $(gyp_intermediate_dir); bash -c "perl src/celt/arm/arm2gnu.pl src/celt/arm/celt_pitch_xcorr_arm.s | sed \"s/OPUS_ARM_MAY_HAVE_[A-Z]*/1/g\" | sed \"/.include/d\" > $(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S"
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S
 
 # Make sure our deps and generated files are built first.
 LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
 
-LOCAL_GENERATED_SOURCES :=
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S
 
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
@@ -150,7 +163,9 @@
 	third_party/opus/src/src/opus_multistream.c \
 	third_party/opus/src/src/opus_multistream_decoder.c \
 	third_party/opus/src/src/opus_multistream_encoder.c \
-	third_party/opus/src/src/repacketizer.c
+	third_party/opus/src/src/repacketizer.c \
+	third_party/opus/src/celt/arm/arm_celt_map.c \
+	third_party/opus/src/celt/arm/armcpu.c
 
 
 # Flags passed to both C and C++ files.
@@ -213,7 +228,15 @@
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
 	'-DFIXED_POINT' \
+	'-DOPUS_ARM_ASM' \
+	'-DOPUS_ARM_INLINE_ASM' \
+	'-DOPUS_ARM_INLINE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_MEDIA' \
+	'-DOPUS_ARM_MAY_HAVE_NEON' \
+	'-DOPUS_HAVE_RTCD' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -307,7 +330,15 @@
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
 	'-DFIXED_POINT' \
+	'-DOPUS_ARM_ASM' \
+	'-DOPUS_ARM_INLINE_ASM' \
+	'-DOPUS_ARM_INLINE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_MEDIA' \
+	'-DOPUS_ARM_MAY_HAVE_NEON' \
+	'-DOPUS_HAVE_RTCD' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/opus/opus.target.darwin-mips.mk b/third_party/opus/opus.target.darwin-mips.mk
index 03ebe39..1ebcc77 100644
--- a/third_party/opus/opus.target.darwin-mips.mk
+++ b/third_party/opus/opus.target.darwin-mips.mk
@@ -63,31 +63,37 @@
 	third_party/opus/src/silk/enc_API.c \
 	third_party/opus/src/silk/encode_indices.c \
 	third_party/opus/src/silk/encode_pulses.c \
-	third_party/opus/src/silk/fixed/apply_sine_window_FIX.c \
-	third_party/opus/src/silk/fixed/autocorr_FIX.c \
-	third_party/opus/src/silk/fixed/burg_modified_FIX.c \
-	third_party/opus/src/silk/fixed/corrMatrix_FIX.c \
-	third_party/opus/src/silk/fixed/encode_frame_FIX.c \
-	third_party/opus/src/silk/fixed/find_LPC_FIX.c \
-	third_party/opus/src/silk/fixed/find_LTP_FIX.c \
-	third_party/opus/src/silk/fixed/find_pitch_lags_FIX.c \
-	third_party/opus/src/silk/fixed/find_pred_coefs_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_Q16_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_analysis_filter_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_scale_ctrl_FIX.c \
-	third_party/opus/src/silk/fixed/noise_shape_analysis_FIX.c \
-	third_party/opus/src/silk/fixed/pitch_analysis_core_FIX.c \
-	third_party/opus/src/silk/fixed/prefilter_FIX.c \
-	third_party/opus/src/silk/fixed/process_gains_FIX.c \
-	third_party/opus/src/silk/fixed/regularize_correlations_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy16_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy_FIX.c \
-	third_party/opus/src/silk/fixed/schur64_FIX.c \
-	third_party/opus/src/silk/fixed/schur_FIX.c \
-	third_party/opus/src/silk/fixed/solve_LS_FIX.c \
-	third_party/opus/src/silk/fixed/vector_ops_FIX.c \
-	third_party/opus/src/silk/fixed/warped_autocorrelation_FIX.c \
+	third_party/opus/src/silk/float/apply_sine_window_FLP.c \
+	third_party/opus/src/silk/float/autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/burg_modified_FLP.c \
+	third_party/opus/src/silk/float/bwexpander_FLP.c \
+	third_party/opus/src/silk/float/corrMatrix_FLP.c \
+	third_party/opus/src/silk/float/encode_frame_FLP.c \
+	third_party/opus/src/silk/float/energy_FLP.c \
+	third_party/opus/src/silk/float/find_LPC_FLP.c \
+	third_party/opus/src/silk/float/find_LTP_FLP.c \
+	third_party/opus/src/silk/float/find_pitch_lags_FLP.c \
+	third_party/opus/src/silk/float/find_pred_coefs_FLP.c \
+	third_party/opus/src/silk/float/inner_product_FLP.c \
+	third_party/opus/src/silk/float/k2a_FLP.c \
+	third_party/opus/src/silk/float/levinsondurbin_FLP.c \
+	third_party/opus/src/silk/float/LPC_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LPC_inv_pred_gain_FLP.c \
+	third_party/opus/src/silk/float/LTP_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LTP_scale_ctrl_FLP.c \
+	third_party/opus/src/silk/float/noise_shape_analysis_FLP.c \
+	third_party/opus/src/silk/float/pitch_analysis_core_FLP.c \
+	third_party/opus/src/silk/float/prefilter_FLP.c \
+	third_party/opus/src/silk/float/process_gains_FLP.c \
+	third_party/opus/src/silk/float/regularize_correlations_FLP.c \
+	third_party/opus/src/silk/float/residual_energy_FLP.c \
+	third_party/opus/src/silk/float/scale_copy_vector_FLP.c \
+	third_party/opus/src/silk/float/scale_vector_FLP.c \
+	third_party/opus/src/silk/float/schur_FLP.c \
+	third_party/opus/src/silk/float/solve_LS_FLP.c \
+	third_party/opus/src/silk/float/sort_FLP.c \
+	third_party/opus/src/silk/float/warped_autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/wrappers_FLP.c \
 	third_party/opus/src/silk/gain_quant.c \
 	third_party/opus/src/silk/HP_variable_cutoff.c \
 	third_party/opus/src/silk/init_decoder.c \
@@ -212,8 +218,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -229,7 +235,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -306,8 +312,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -323,7 +329,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
diff --git a/third_party/opus/opus.target.darwin-x86.mk b/third_party/opus/opus.target.darwin-x86.mk
index 7373baf..4f71e1e 100644
--- a/third_party/opus/opus.target.darwin-x86.mk
+++ b/third_party/opus/opus.target.darwin-x86.mk
@@ -63,31 +63,37 @@
 	third_party/opus/src/silk/enc_API.c \
 	third_party/opus/src/silk/encode_indices.c \
 	third_party/opus/src/silk/encode_pulses.c \
-	third_party/opus/src/silk/fixed/apply_sine_window_FIX.c \
-	third_party/opus/src/silk/fixed/autocorr_FIX.c \
-	third_party/opus/src/silk/fixed/burg_modified_FIX.c \
-	third_party/opus/src/silk/fixed/corrMatrix_FIX.c \
-	third_party/opus/src/silk/fixed/encode_frame_FIX.c \
-	third_party/opus/src/silk/fixed/find_LPC_FIX.c \
-	third_party/opus/src/silk/fixed/find_LTP_FIX.c \
-	third_party/opus/src/silk/fixed/find_pitch_lags_FIX.c \
-	third_party/opus/src/silk/fixed/find_pred_coefs_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_Q16_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_analysis_filter_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_scale_ctrl_FIX.c \
-	third_party/opus/src/silk/fixed/noise_shape_analysis_FIX.c \
-	third_party/opus/src/silk/fixed/pitch_analysis_core_FIX.c \
-	third_party/opus/src/silk/fixed/prefilter_FIX.c \
-	third_party/opus/src/silk/fixed/process_gains_FIX.c \
-	third_party/opus/src/silk/fixed/regularize_correlations_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy16_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy_FIX.c \
-	third_party/opus/src/silk/fixed/schur64_FIX.c \
-	third_party/opus/src/silk/fixed/schur_FIX.c \
-	third_party/opus/src/silk/fixed/solve_LS_FIX.c \
-	third_party/opus/src/silk/fixed/vector_ops_FIX.c \
-	third_party/opus/src/silk/fixed/warped_autocorrelation_FIX.c \
+	third_party/opus/src/silk/float/apply_sine_window_FLP.c \
+	third_party/opus/src/silk/float/autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/burg_modified_FLP.c \
+	third_party/opus/src/silk/float/bwexpander_FLP.c \
+	third_party/opus/src/silk/float/corrMatrix_FLP.c \
+	third_party/opus/src/silk/float/encode_frame_FLP.c \
+	third_party/opus/src/silk/float/energy_FLP.c \
+	third_party/opus/src/silk/float/find_LPC_FLP.c \
+	third_party/opus/src/silk/float/find_LTP_FLP.c \
+	third_party/opus/src/silk/float/find_pitch_lags_FLP.c \
+	third_party/opus/src/silk/float/find_pred_coefs_FLP.c \
+	third_party/opus/src/silk/float/inner_product_FLP.c \
+	third_party/opus/src/silk/float/k2a_FLP.c \
+	third_party/opus/src/silk/float/levinsondurbin_FLP.c \
+	third_party/opus/src/silk/float/LPC_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LPC_inv_pred_gain_FLP.c \
+	third_party/opus/src/silk/float/LTP_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LTP_scale_ctrl_FLP.c \
+	third_party/opus/src/silk/float/noise_shape_analysis_FLP.c \
+	third_party/opus/src/silk/float/pitch_analysis_core_FLP.c \
+	third_party/opus/src/silk/float/prefilter_FLP.c \
+	third_party/opus/src/silk/float/process_gains_FLP.c \
+	third_party/opus/src/silk/float/regularize_correlations_FLP.c \
+	third_party/opus/src/silk/float/residual_energy_FLP.c \
+	third_party/opus/src/silk/float/scale_copy_vector_FLP.c \
+	third_party/opus/src/silk/float/scale_vector_FLP.c \
+	third_party/opus/src/silk/float/schur_FLP.c \
+	third_party/opus/src/silk/float/solve_LS_FLP.c \
+	third_party/opus/src/silk/float/sort_FLP.c \
+	third_party/opus/src/silk/float/warped_autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/wrappers_FLP.c \
 	third_party/opus/src/silk/gain_quant.c \
 	third_party/opus/src/silk/HP_variable_cutoff.c \
 	third_party/opus/src/silk/init_decoder.c \
@@ -213,8 +219,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -230,7 +236,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -307,8 +313,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -324,7 +330,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
diff --git a/third_party/opus/opus.target.darwin-x86_64.mk b/third_party/opus/opus.target.darwin-x86_64.mk
new file mode 100644
index 0000000..71b04c8
--- /dev/null
+++ b/third_party/opus/opus.target.darwin-x86_64.mk
@@ -0,0 +1,409 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_opus_opus_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/opus/src/celt/bands.c \
+	third_party/opus/src/celt/celt.c \
+	third_party/opus/src/celt/celt_decoder.c \
+	third_party/opus/src/celt/celt_encoder.c \
+	third_party/opus/src/celt/celt_lpc.c \
+	third_party/opus/src/celt/cwrs.c \
+	third_party/opus/src/celt/entcode.c \
+	third_party/opus/src/celt/entdec.c \
+	third_party/opus/src/celt/entenc.c \
+	third_party/opus/src/celt/kiss_fft.c \
+	third_party/opus/src/celt/laplace.c \
+	third_party/opus/src/celt/mathops.c \
+	third_party/opus/src/celt/mdct.c \
+	third_party/opus/src/celt/modes.c \
+	third_party/opus/src/celt/pitch.c \
+	third_party/opus/src/celt/quant_bands.c \
+	third_party/opus/src/celt/rate.c \
+	third_party/opus/src/celt/vq.c \
+	third_party/opus/src/silk/A2NLSF.c \
+	third_party/opus/src/silk/ana_filt_bank_1.c \
+	third_party/opus/src/silk/biquad_alt.c \
+	third_party/opus/src/silk/bwexpander.c \
+	third_party/opus/src/silk/bwexpander_32.c \
+	third_party/opus/src/silk/check_control_input.c \
+	third_party/opus/src/silk/CNG.c \
+	third_party/opus/src/silk/code_signs.c \
+	third_party/opus/src/silk/control_audio_bandwidth.c \
+	third_party/opus/src/silk/control_codec.c \
+	third_party/opus/src/silk/control_SNR.c \
+	third_party/opus/src/silk/debug.c \
+	third_party/opus/src/silk/dec_API.c \
+	third_party/opus/src/silk/decode_core.c \
+	third_party/opus/src/silk/decode_frame.c \
+	third_party/opus/src/silk/decode_indices.c \
+	third_party/opus/src/silk/decode_parameters.c \
+	third_party/opus/src/silk/decode_pitch.c \
+	third_party/opus/src/silk/decode_pulses.c \
+	third_party/opus/src/silk/decoder_set_fs.c \
+	third_party/opus/src/silk/enc_API.c \
+	third_party/opus/src/silk/encode_indices.c \
+	third_party/opus/src/silk/encode_pulses.c \
+	third_party/opus/src/silk/float/apply_sine_window_FLP.c \
+	third_party/opus/src/silk/float/autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/burg_modified_FLP.c \
+	third_party/opus/src/silk/float/bwexpander_FLP.c \
+	third_party/opus/src/silk/float/corrMatrix_FLP.c \
+	third_party/opus/src/silk/float/encode_frame_FLP.c \
+	third_party/opus/src/silk/float/energy_FLP.c \
+	third_party/opus/src/silk/float/find_LPC_FLP.c \
+	third_party/opus/src/silk/float/find_LTP_FLP.c \
+	third_party/opus/src/silk/float/find_pitch_lags_FLP.c \
+	third_party/opus/src/silk/float/find_pred_coefs_FLP.c \
+	third_party/opus/src/silk/float/inner_product_FLP.c \
+	third_party/opus/src/silk/float/k2a_FLP.c \
+	third_party/opus/src/silk/float/levinsondurbin_FLP.c \
+	third_party/opus/src/silk/float/LPC_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LPC_inv_pred_gain_FLP.c \
+	third_party/opus/src/silk/float/LTP_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LTP_scale_ctrl_FLP.c \
+	third_party/opus/src/silk/float/noise_shape_analysis_FLP.c \
+	third_party/opus/src/silk/float/pitch_analysis_core_FLP.c \
+	third_party/opus/src/silk/float/prefilter_FLP.c \
+	third_party/opus/src/silk/float/process_gains_FLP.c \
+	third_party/opus/src/silk/float/regularize_correlations_FLP.c \
+	third_party/opus/src/silk/float/residual_energy_FLP.c \
+	third_party/opus/src/silk/float/scale_copy_vector_FLP.c \
+	third_party/opus/src/silk/float/scale_vector_FLP.c \
+	third_party/opus/src/silk/float/schur_FLP.c \
+	third_party/opus/src/silk/float/solve_LS_FLP.c \
+	third_party/opus/src/silk/float/sort_FLP.c \
+	third_party/opus/src/silk/float/warped_autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/wrappers_FLP.c \
+	third_party/opus/src/silk/gain_quant.c \
+	third_party/opus/src/silk/HP_variable_cutoff.c \
+	third_party/opus/src/silk/init_decoder.c \
+	third_party/opus/src/silk/init_encoder.c \
+	third_party/opus/src/silk/inner_prod_aligned.c \
+	third_party/opus/src/silk/interpolate.c \
+	third_party/opus/src/silk/lin2log.c \
+	third_party/opus/src/silk/log2lin.c \
+	third_party/opus/src/silk/LP_variable_cutoff.c \
+	third_party/opus/src/silk/LPC_analysis_filter.c \
+	third_party/opus/src/silk/LPC_inv_pred_gain.c \
+	third_party/opus/src/silk/NLSF2A.c \
+	third_party/opus/src/silk/NLSF_decode.c \
+	third_party/opus/src/silk/NLSF_del_dec_quant.c \
+	third_party/opus/src/silk/NLSF_encode.c \
+	third_party/opus/src/silk/NLSF_stabilize.c \
+	third_party/opus/src/silk/NLSF_unpack.c \
+	third_party/opus/src/silk/NLSF_VQ.c \
+	third_party/opus/src/silk/NLSF_VQ_weights_laroia.c \
+	third_party/opus/src/silk/NSQ.c \
+	third_party/opus/src/silk/NSQ_del_dec.c \
+	third_party/opus/src/silk/pitch_est_tables.c \
+	third_party/opus/src/silk/PLC.c \
+	third_party/opus/src/silk/process_NLSFs.c \
+	third_party/opus/src/silk/quant_LTP_gains.c \
+	third_party/opus/src/silk/resampler.c \
+	third_party/opus/src/silk/resampler_down2.c \
+	third_party/opus/src/silk/resampler_down2_3.c \
+	third_party/opus/src/silk/resampler_private_AR2.c \
+	third_party/opus/src/silk/resampler_private_down_FIR.c \
+	third_party/opus/src/silk/resampler_private_IIR_FIR.c \
+	third_party/opus/src/silk/resampler_private_up2_HQ.c \
+	third_party/opus/src/silk/resampler_rom.c \
+	third_party/opus/src/silk/shell_coder.c \
+	third_party/opus/src/silk/sigm_Q15.c \
+	third_party/opus/src/silk/sort.c \
+	third_party/opus/src/silk/stereo_decode_pred.c \
+	third_party/opus/src/silk/stereo_encode_pred.c \
+	third_party/opus/src/silk/stereo_find_predictor.c \
+	third_party/opus/src/silk/stereo_LR_to_MS.c \
+	third_party/opus/src/silk/stereo_MS_to_LR.c \
+	third_party/opus/src/silk/stereo_quant_pred.c \
+	third_party/opus/src/silk/sum_sqr_shift.c \
+	third_party/opus/src/silk/table_LSF_cos.c \
+	third_party/opus/src/silk/tables_gain.c \
+	third_party/opus/src/silk/tables_LTP.c \
+	third_party/opus/src/silk/tables_NLSF_CB_NB_MB.c \
+	third_party/opus/src/silk/tables_NLSF_CB_WB.c \
+	third_party/opus/src/silk/tables_other.c \
+	third_party/opus/src/silk/tables_pitch_lag.c \
+	third_party/opus/src/silk/tables_pulses_per_block.c \
+	third_party/opus/src/silk/VAD.c \
+	third_party/opus/src/silk/VQ_WMat_EC.c \
+	third_party/opus/src/src/analysis.c \
+	third_party/opus/src/src/mlp.c \
+	third_party/opus/src/src/mlp_data.c \
+	third_party/opus/src/src/opus.c \
+	third_party/opus/src/src/opus_decoder.c \
+	third_party/opus/src/src/opus_encoder.c \
+	third_party/opus/src/src/opus_multistream.c \
+	third_party/opus/src/src/opus_multistream_decoder.c \
+	third_party/opus/src/src/opus_multistream_encoder.c \
+	third_party/opus/src/src/repacketizer.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DOPUS_BUILD' \
+	'-DOPUS_EXPORT=' \
+	'-DHAVE_LRINT' \
+	'-DHAVE_LRINTF' \
+	'-DVAR_ARRAYS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/opus/src/celt \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(LOCAL_PATH)/third_party/opus/src/silk \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DOPUS_BUILD' \
+	'-DOPUS_EXPORT=' \
+	'-DHAVE_LRINT' \
+	'-DHAVE_LRINTF' \
+	'-DVAR_ARRAYS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/opus/src/celt \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(LOCAL_PATH)/third_party/opus/src/silk \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_opus_opus_gyp
+
+# Alias gyp target name.
+.PHONY: opus
+opus: third_party_opus_opus_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/opus/opus.target.linux-arm.mk b/third_party/opus/opus.target.linux-arm.mk
index 7e3c4c8..0e9aaf3 100644
--- a/third_party/opus/opus.target.linux-arm.mk
+++ b/third_party/opus/opus.target.linux-arm.mk
@@ -12,12 +12,25 @@
 # Make sure our deps are built first.
 GYP_TARGET_DEPENDENCIES :=
 
-GYP_GENERATED_OUTPUTS :=
+### Rules for action "convert_assembler":
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S: $(LOCAL_PATH)/third_party/opus/src/celt/arm/arm2gnu.pl $(LOCAL_PATH)/third_party/opus/src/celt/arm/celt_pitch_xcorr_arm.s $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Convert Opus assembler for ARM. ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/opus; mkdir -p $(gyp_intermediate_dir); bash -c "perl src/celt/arm/arm2gnu.pl src/celt/arm/celt_pitch_xcorr_arm.s | sed \"s/OPUS_ARM_MAY_HAVE_[A-Z]*/1/g\" | sed \"/.include/d\" > $(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S"
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S
 
 # Make sure our deps and generated files are built first.
 LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
 
-LOCAL_GENERATED_SOURCES :=
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/celt_pitch_xcorr_arm_gnu.S
 
 GYP_COPIED_SOURCE_ORIGIN_DIRS :=
 
@@ -150,7 +163,9 @@
 	third_party/opus/src/src/opus_multistream.c \
 	third_party/opus/src/src/opus_multistream_decoder.c \
 	third_party/opus/src/src/opus_multistream_encoder.c \
-	third_party/opus/src/src/repacketizer.c
+	third_party/opus/src/src/repacketizer.c \
+	third_party/opus/src/celt/arm/arm_celt_map.c \
+	third_party/opus/src/celt/arm/armcpu.c
 
 
 # Flags passed to both C and C++ files.
@@ -213,7 +228,15 @@
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
 	'-DFIXED_POINT' \
+	'-DOPUS_ARM_ASM' \
+	'-DOPUS_ARM_INLINE_ASM' \
+	'-DOPUS_ARM_INLINE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_MEDIA' \
+	'-DOPUS_ARM_MAY_HAVE_NEON' \
+	'-DOPUS_HAVE_RTCD' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -307,7 +330,15 @@
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
 	'-DFIXED_POINT' \
+	'-DOPUS_ARM_ASM' \
+	'-DOPUS_ARM_INLINE_ASM' \
+	'-DOPUS_ARM_INLINE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_EDSP' \
+	'-DOPUS_ARM_MAY_HAVE_MEDIA' \
+	'-DOPUS_ARM_MAY_HAVE_NEON' \
+	'-DOPUS_HAVE_RTCD' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/opus/opus.target.linux-mips.mk b/third_party/opus/opus.target.linux-mips.mk
index 03ebe39..1ebcc77 100644
--- a/third_party/opus/opus.target.linux-mips.mk
+++ b/third_party/opus/opus.target.linux-mips.mk
@@ -63,31 +63,37 @@
 	third_party/opus/src/silk/enc_API.c \
 	third_party/opus/src/silk/encode_indices.c \
 	third_party/opus/src/silk/encode_pulses.c \
-	third_party/opus/src/silk/fixed/apply_sine_window_FIX.c \
-	third_party/opus/src/silk/fixed/autocorr_FIX.c \
-	third_party/opus/src/silk/fixed/burg_modified_FIX.c \
-	third_party/opus/src/silk/fixed/corrMatrix_FIX.c \
-	third_party/opus/src/silk/fixed/encode_frame_FIX.c \
-	third_party/opus/src/silk/fixed/find_LPC_FIX.c \
-	third_party/opus/src/silk/fixed/find_LTP_FIX.c \
-	third_party/opus/src/silk/fixed/find_pitch_lags_FIX.c \
-	third_party/opus/src/silk/fixed/find_pred_coefs_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_Q16_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_analysis_filter_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_scale_ctrl_FIX.c \
-	third_party/opus/src/silk/fixed/noise_shape_analysis_FIX.c \
-	third_party/opus/src/silk/fixed/pitch_analysis_core_FIX.c \
-	third_party/opus/src/silk/fixed/prefilter_FIX.c \
-	third_party/opus/src/silk/fixed/process_gains_FIX.c \
-	third_party/opus/src/silk/fixed/regularize_correlations_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy16_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy_FIX.c \
-	third_party/opus/src/silk/fixed/schur64_FIX.c \
-	third_party/opus/src/silk/fixed/schur_FIX.c \
-	third_party/opus/src/silk/fixed/solve_LS_FIX.c \
-	third_party/opus/src/silk/fixed/vector_ops_FIX.c \
-	third_party/opus/src/silk/fixed/warped_autocorrelation_FIX.c \
+	third_party/opus/src/silk/float/apply_sine_window_FLP.c \
+	third_party/opus/src/silk/float/autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/burg_modified_FLP.c \
+	third_party/opus/src/silk/float/bwexpander_FLP.c \
+	third_party/opus/src/silk/float/corrMatrix_FLP.c \
+	third_party/opus/src/silk/float/encode_frame_FLP.c \
+	third_party/opus/src/silk/float/energy_FLP.c \
+	third_party/opus/src/silk/float/find_LPC_FLP.c \
+	third_party/opus/src/silk/float/find_LTP_FLP.c \
+	third_party/opus/src/silk/float/find_pitch_lags_FLP.c \
+	third_party/opus/src/silk/float/find_pred_coefs_FLP.c \
+	third_party/opus/src/silk/float/inner_product_FLP.c \
+	third_party/opus/src/silk/float/k2a_FLP.c \
+	third_party/opus/src/silk/float/levinsondurbin_FLP.c \
+	third_party/opus/src/silk/float/LPC_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LPC_inv_pred_gain_FLP.c \
+	third_party/opus/src/silk/float/LTP_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LTP_scale_ctrl_FLP.c \
+	third_party/opus/src/silk/float/noise_shape_analysis_FLP.c \
+	third_party/opus/src/silk/float/pitch_analysis_core_FLP.c \
+	third_party/opus/src/silk/float/prefilter_FLP.c \
+	third_party/opus/src/silk/float/process_gains_FLP.c \
+	third_party/opus/src/silk/float/regularize_correlations_FLP.c \
+	third_party/opus/src/silk/float/residual_energy_FLP.c \
+	third_party/opus/src/silk/float/scale_copy_vector_FLP.c \
+	third_party/opus/src/silk/float/scale_vector_FLP.c \
+	third_party/opus/src/silk/float/schur_FLP.c \
+	third_party/opus/src/silk/float/solve_LS_FLP.c \
+	third_party/opus/src/silk/float/sort_FLP.c \
+	third_party/opus/src/silk/float/warped_autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/wrappers_FLP.c \
 	third_party/opus/src/silk/gain_quant.c \
 	third_party/opus/src/silk/HP_variable_cutoff.c \
 	third_party/opus/src/silk/init_decoder.c \
@@ -212,8 +218,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -229,7 +235,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -306,8 +312,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -323,7 +329,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
diff --git a/third_party/opus/opus.target.linux-x86.mk b/third_party/opus/opus.target.linux-x86.mk
index 7373baf..4f71e1e 100644
--- a/third_party/opus/opus.target.linux-x86.mk
+++ b/third_party/opus/opus.target.linux-x86.mk
@@ -63,31 +63,37 @@
 	third_party/opus/src/silk/enc_API.c \
 	third_party/opus/src/silk/encode_indices.c \
 	third_party/opus/src/silk/encode_pulses.c \
-	third_party/opus/src/silk/fixed/apply_sine_window_FIX.c \
-	third_party/opus/src/silk/fixed/autocorr_FIX.c \
-	third_party/opus/src/silk/fixed/burg_modified_FIX.c \
-	third_party/opus/src/silk/fixed/corrMatrix_FIX.c \
-	third_party/opus/src/silk/fixed/encode_frame_FIX.c \
-	third_party/opus/src/silk/fixed/find_LPC_FIX.c \
-	third_party/opus/src/silk/fixed/find_LTP_FIX.c \
-	third_party/opus/src/silk/fixed/find_pitch_lags_FIX.c \
-	third_party/opus/src/silk/fixed/find_pred_coefs_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_FIX.c \
-	third_party/opus/src/silk/fixed/k2a_Q16_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_analysis_filter_FIX.c \
-	third_party/opus/src/silk/fixed/LTP_scale_ctrl_FIX.c \
-	third_party/opus/src/silk/fixed/noise_shape_analysis_FIX.c \
-	third_party/opus/src/silk/fixed/pitch_analysis_core_FIX.c \
-	third_party/opus/src/silk/fixed/prefilter_FIX.c \
-	third_party/opus/src/silk/fixed/process_gains_FIX.c \
-	third_party/opus/src/silk/fixed/regularize_correlations_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy16_FIX.c \
-	third_party/opus/src/silk/fixed/residual_energy_FIX.c \
-	third_party/opus/src/silk/fixed/schur64_FIX.c \
-	third_party/opus/src/silk/fixed/schur_FIX.c \
-	third_party/opus/src/silk/fixed/solve_LS_FIX.c \
-	third_party/opus/src/silk/fixed/vector_ops_FIX.c \
-	third_party/opus/src/silk/fixed/warped_autocorrelation_FIX.c \
+	third_party/opus/src/silk/float/apply_sine_window_FLP.c \
+	third_party/opus/src/silk/float/autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/burg_modified_FLP.c \
+	third_party/opus/src/silk/float/bwexpander_FLP.c \
+	third_party/opus/src/silk/float/corrMatrix_FLP.c \
+	third_party/opus/src/silk/float/encode_frame_FLP.c \
+	third_party/opus/src/silk/float/energy_FLP.c \
+	third_party/opus/src/silk/float/find_LPC_FLP.c \
+	third_party/opus/src/silk/float/find_LTP_FLP.c \
+	third_party/opus/src/silk/float/find_pitch_lags_FLP.c \
+	third_party/opus/src/silk/float/find_pred_coefs_FLP.c \
+	third_party/opus/src/silk/float/inner_product_FLP.c \
+	third_party/opus/src/silk/float/k2a_FLP.c \
+	third_party/opus/src/silk/float/levinsondurbin_FLP.c \
+	third_party/opus/src/silk/float/LPC_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LPC_inv_pred_gain_FLP.c \
+	third_party/opus/src/silk/float/LTP_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LTP_scale_ctrl_FLP.c \
+	third_party/opus/src/silk/float/noise_shape_analysis_FLP.c \
+	third_party/opus/src/silk/float/pitch_analysis_core_FLP.c \
+	third_party/opus/src/silk/float/prefilter_FLP.c \
+	third_party/opus/src/silk/float/process_gains_FLP.c \
+	third_party/opus/src/silk/float/regularize_correlations_FLP.c \
+	third_party/opus/src/silk/float/residual_energy_FLP.c \
+	third_party/opus/src/silk/float/scale_copy_vector_FLP.c \
+	third_party/opus/src/silk/float/scale_vector_FLP.c \
+	third_party/opus/src/silk/float/schur_FLP.c \
+	third_party/opus/src/silk/float/solve_LS_FLP.c \
+	third_party/opus/src/silk/float/sort_FLP.c \
+	third_party/opus/src/silk/float/warped_autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/wrappers_FLP.c \
 	third_party/opus/src/silk/gain_quant.c \
 	third_party/opus/src/silk/HP_variable_cutoff.c \
 	third_party/opus/src/silk/init_decoder.c \
@@ -213,8 +219,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -230,7 +236,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -307,8 +313,8 @@
 	'-DHAVE_LRINT' \
 	'-DHAVE_LRINTF' \
 	'-DVAR_ARRAYS' \
-	'-DFIXED_POINT' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -324,7 +330,7 @@
 	$(LOCAL_PATH)/third_party/opus/src/celt \
 	$(LOCAL_PATH)/third_party/opus/src/include \
 	$(LOCAL_PATH)/third_party/opus/src/silk \
-	$(LOCAL_PATH)/third_party/opus/src/silk/fixed \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
diff --git a/third_party/opus/opus.target.linux-x86_64.mk b/third_party/opus/opus.target.linux-x86_64.mk
new file mode 100644
index 0000000..71b04c8
--- /dev/null
+++ b/third_party/opus/opus.target.linux-x86_64.mk
@@ -0,0 +1,409 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_opus_opus_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/opus/src/celt/bands.c \
+	third_party/opus/src/celt/celt.c \
+	third_party/opus/src/celt/celt_decoder.c \
+	third_party/opus/src/celt/celt_encoder.c \
+	third_party/opus/src/celt/celt_lpc.c \
+	third_party/opus/src/celt/cwrs.c \
+	third_party/opus/src/celt/entcode.c \
+	third_party/opus/src/celt/entdec.c \
+	third_party/opus/src/celt/entenc.c \
+	third_party/opus/src/celt/kiss_fft.c \
+	third_party/opus/src/celt/laplace.c \
+	third_party/opus/src/celt/mathops.c \
+	third_party/opus/src/celt/mdct.c \
+	third_party/opus/src/celt/modes.c \
+	third_party/opus/src/celt/pitch.c \
+	third_party/opus/src/celt/quant_bands.c \
+	third_party/opus/src/celt/rate.c \
+	third_party/opus/src/celt/vq.c \
+	third_party/opus/src/silk/A2NLSF.c \
+	third_party/opus/src/silk/ana_filt_bank_1.c \
+	third_party/opus/src/silk/biquad_alt.c \
+	third_party/opus/src/silk/bwexpander.c \
+	third_party/opus/src/silk/bwexpander_32.c \
+	third_party/opus/src/silk/check_control_input.c \
+	third_party/opus/src/silk/CNG.c \
+	third_party/opus/src/silk/code_signs.c \
+	third_party/opus/src/silk/control_audio_bandwidth.c \
+	third_party/opus/src/silk/control_codec.c \
+	third_party/opus/src/silk/control_SNR.c \
+	third_party/opus/src/silk/debug.c \
+	third_party/opus/src/silk/dec_API.c \
+	third_party/opus/src/silk/decode_core.c \
+	third_party/opus/src/silk/decode_frame.c \
+	third_party/opus/src/silk/decode_indices.c \
+	third_party/opus/src/silk/decode_parameters.c \
+	third_party/opus/src/silk/decode_pitch.c \
+	third_party/opus/src/silk/decode_pulses.c \
+	third_party/opus/src/silk/decoder_set_fs.c \
+	third_party/opus/src/silk/enc_API.c \
+	third_party/opus/src/silk/encode_indices.c \
+	third_party/opus/src/silk/encode_pulses.c \
+	third_party/opus/src/silk/float/apply_sine_window_FLP.c \
+	third_party/opus/src/silk/float/autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/burg_modified_FLP.c \
+	third_party/opus/src/silk/float/bwexpander_FLP.c \
+	third_party/opus/src/silk/float/corrMatrix_FLP.c \
+	third_party/opus/src/silk/float/encode_frame_FLP.c \
+	third_party/opus/src/silk/float/energy_FLP.c \
+	third_party/opus/src/silk/float/find_LPC_FLP.c \
+	third_party/opus/src/silk/float/find_LTP_FLP.c \
+	third_party/opus/src/silk/float/find_pitch_lags_FLP.c \
+	third_party/opus/src/silk/float/find_pred_coefs_FLP.c \
+	third_party/opus/src/silk/float/inner_product_FLP.c \
+	third_party/opus/src/silk/float/k2a_FLP.c \
+	third_party/opus/src/silk/float/levinsondurbin_FLP.c \
+	third_party/opus/src/silk/float/LPC_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LPC_inv_pred_gain_FLP.c \
+	third_party/opus/src/silk/float/LTP_analysis_filter_FLP.c \
+	third_party/opus/src/silk/float/LTP_scale_ctrl_FLP.c \
+	third_party/opus/src/silk/float/noise_shape_analysis_FLP.c \
+	third_party/opus/src/silk/float/pitch_analysis_core_FLP.c \
+	third_party/opus/src/silk/float/prefilter_FLP.c \
+	third_party/opus/src/silk/float/process_gains_FLP.c \
+	third_party/opus/src/silk/float/regularize_correlations_FLP.c \
+	third_party/opus/src/silk/float/residual_energy_FLP.c \
+	third_party/opus/src/silk/float/scale_copy_vector_FLP.c \
+	third_party/opus/src/silk/float/scale_vector_FLP.c \
+	third_party/opus/src/silk/float/schur_FLP.c \
+	third_party/opus/src/silk/float/solve_LS_FLP.c \
+	third_party/opus/src/silk/float/sort_FLP.c \
+	third_party/opus/src/silk/float/warped_autocorrelation_FLP.c \
+	third_party/opus/src/silk/float/wrappers_FLP.c \
+	third_party/opus/src/silk/gain_quant.c \
+	third_party/opus/src/silk/HP_variable_cutoff.c \
+	third_party/opus/src/silk/init_decoder.c \
+	third_party/opus/src/silk/init_encoder.c \
+	third_party/opus/src/silk/inner_prod_aligned.c \
+	third_party/opus/src/silk/interpolate.c \
+	third_party/opus/src/silk/lin2log.c \
+	third_party/opus/src/silk/log2lin.c \
+	third_party/opus/src/silk/LP_variable_cutoff.c \
+	third_party/opus/src/silk/LPC_analysis_filter.c \
+	third_party/opus/src/silk/LPC_inv_pred_gain.c \
+	third_party/opus/src/silk/NLSF2A.c \
+	third_party/opus/src/silk/NLSF_decode.c \
+	third_party/opus/src/silk/NLSF_del_dec_quant.c \
+	third_party/opus/src/silk/NLSF_encode.c \
+	third_party/opus/src/silk/NLSF_stabilize.c \
+	third_party/opus/src/silk/NLSF_unpack.c \
+	third_party/opus/src/silk/NLSF_VQ.c \
+	third_party/opus/src/silk/NLSF_VQ_weights_laroia.c \
+	third_party/opus/src/silk/NSQ.c \
+	third_party/opus/src/silk/NSQ_del_dec.c \
+	third_party/opus/src/silk/pitch_est_tables.c \
+	third_party/opus/src/silk/PLC.c \
+	third_party/opus/src/silk/process_NLSFs.c \
+	third_party/opus/src/silk/quant_LTP_gains.c \
+	third_party/opus/src/silk/resampler.c \
+	third_party/opus/src/silk/resampler_down2.c \
+	third_party/opus/src/silk/resampler_down2_3.c \
+	third_party/opus/src/silk/resampler_private_AR2.c \
+	third_party/opus/src/silk/resampler_private_down_FIR.c \
+	third_party/opus/src/silk/resampler_private_IIR_FIR.c \
+	third_party/opus/src/silk/resampler_private_up2_HQ.c \
+	third_party/opus/src/silk/resampler_rom.c \
+	third_party/opus/src/silk/shell_coder.c \
+	third_party/opus/src/silk/sigm_Q15.c \
+	third_party/opus/src/silk/sort.c \
+	third_party/opus/src/silk/stereo_decode_pred.c \
+	third_party/opus/src/silk/stereo_encode_pred.c \
+	third_party/opus/src/silk/stereo_find_predictor.c \
+	third_party/opus/src/silk/stereo_LR_to_MS.c \
+	third_party/opus/src/silk/stereo_MS_to_LR.c \
+	third_party/opus/src/silk/stereo_quant_pred.c \
+	third_party/opus/src/silk/sum_sqr_shift.c \
+	third_party/opus/src/silk/table_LSF_cos.c \
+	third_party/opus/src/silk/tables_gain.c \
+	third_party/opus/src/silk/tables_LTP.c \
+	third_party/opus/src/silk/tables_NLSF_CB_NB_MB.c \
+	third_party/opus/src/silk/tables_NLSF_CB_WB.c \
+	third_party/opus/src/silk/tables_other.c \
+	third_party/opus/src/silk/tables_pitch_lag.c \
+	third_party/opus/src/silk/tables_pulses_per_block.c \
+	third_party/opus/src/silk/VAD.c \
+	third_party/opus/src/silk/VQ_WMat_EC.c \
+	third_party/opus/src/src/analysis.c \
+	third_party/opus/src/src/mlp.c \
+	third_party/opus/src/src/mlp_data.c \
+	third_party/opus/src/src/opus.c \
+	third_party/opus/src/src/opus_decoder.c \
+	third_party/opus/src/src/opus_encoder.c \
+	third_party/opus/src/src/opus_multistream.c \
+	third_party/opus/src/src/opus_multistream_decoder.c \
+	third_party/opus/src/src/opus_multistream_encoder.c \
+	third_party/opus/src/src/repacketizer.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DOPUS_BUILD' \
+	'-DOPUS_EXPORT=' \
+	'-DHAVE_LRINT' \
+	'-DHAVE_LRINTF' \
+	'-DVAR_ARRAYS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/opus/src/celt \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(LOCAL_PATH)/third_party/opus/src/silk \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DOPUS_BUILD' \
+	'-DOPUS_EXPORT=' \
+	'-DHAVE_LRINT' \
+	'-DHAVE_LRINTF' \
+	'-DVAR_ARRAYS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/opus/src/celt \
+	$(LOCAL_PATH)/third_party/opus/src/include \
+	$(LOCAL_PATH)/third_party/opus/src/silk \
+	$(LOCAL_PATH)/third_party/opus/src/silk/float \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_opus_opus_gyp
+
+# Alias gyp target name.
+.PHONY: opus
+opus: third_party_opus_opus_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/opus/opus_srcs_arm.gypi b/third_party/opus/opus_srcs_arm.gypi
new file mode 100644
index 0000000..9727d36
--- /dev/null
+++ b/third_party/opus/opus_srcs_arm.gypi
@@ -0,0 +1,39 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'sources': [
+    'src/celt/arm/arm_celt_map.c',
+    'src/celt/arm/armcpu.c',
+    'src/celt/arm/armcpu.h',
+    'src/celt/arm/fixed_armv4.h',
+    'src/celt/arm/fixed_armv5e.h',
+    'src/celt/arm/kiss_fft_armv4.h',
+    'src/celt/arm/kiss_fft_armv5e.h',
+    'src/celt/pitch_arm.h',
+    'src/silk/arm/macro_armv4.h',
+    'src/silk/arm/macro_armv5e.h',
+    'src/silk/arm/SigProc_FIX_armv4.h',
+    'src/silk/arm/SigProc_FIX_armv5e.h',
+    '<(INTERMEDIATE_DIR)/celt_pitch_xcorr_arm_gnu.S',
+  ],
+  'actions': [
+    {
+      'action_name': 'convert_assembler',
+      'inputs': [
+        'src/celt/arm/arm2gnu.pl',
+        'src/celt/arm/celt_pitch_xcorr_arm.s',
+      ],
+      'outputs': [
+        '<(INTERMEDIATE_DIR)/celt_pitch_xcorr_arm_gnu.S',
+      ],
+      'action': [
+        'bash',
+        '-c',
+        'perl src/celt/arm/arm2gnu.pl src/celt/arm/celt_pitch_xcorr_arm.s | sed "s/OPUS_ARM_MAY_HAVE_[A-Z]*/1/g" | sed "/.include/d" > <(INTERMEDIATE_DIR)/celt_pitch_xcorr_arm_gnu.S',
+      ],
+      'message': 'Convert Opus assembler for ARM.'
+    },
+  ],
+}
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium
index 4831090..ab2cff4 100644
--- a/third_party/protobuf/README.chromium
+++ b/third_party/protobuf/README.chromium
@@ -30,6 +30,7 @@
 Revision 512 was cherry-picked from upstream.
 Revision 516 was cherry-picked from upstream.
 Revision 517 was cherry-picked from upstream.
+Revision 522 was cherry-picked from upstream.
 
 Notes about Java:
 We have not forked the Java version of protobuf-lite, so the Java version does
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk
index 2dcb430..b1c0746 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-arm.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -157,6 +158,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk
index ba4616f..0e3e46a 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-mips.mk
@@ -100,6 +100,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -159,6 +160,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk
index 2dcb430..b1c0746 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -157,6 +158,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86_64.mk b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86_64.mk
new file mode 100644
index 0000000..e0e95c4
--- /dev/null
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.darwin-x86_64.mk
@@ -0,0 +1,218 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_protobuf_protobuf_full_do_not_use_host_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
+	third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
+	third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+	third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
+	third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
+	third_party/protobuf/src/google/protobuf/descriptor.cc \
+	third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
+	third_party/protobuf/src/google/protobuf/descriptor_database.cc \
+	third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+	third_party/protobuf/src/google/protobuf/extension_set.cc \
+	third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
+	third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
+	third_party/protobuf/src/google/protobuf/message.cc \
+	third_party/protobuf/src/google/protobuf/reflection_ops.cc \
+	third_party/protobuf/src/google/protobuf/service.cc \
+	third_party/protobuf/src/google/protobuf/text_format.cc \
+	third_party/protobuf/src/google/protobuf/wire_format.cc \
+	third_party/protobuf/src/google/protobuf/io/printer.cc \
+	third_party/protobuf/src/google/protobuf/io/tokenizer.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc \
+	third_party/protobuf/src/google/protobuf/compiler/importer.cc \
+	third_party/protobuf/src/google/protobuf/compiler/parser.cc \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
+	third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
+	third_party/protobuf/src/google/protobuf/stubs/common.cc \
+	third_party/protobuf/src/google/protobuf/stubs/once.cc \
+	third_party/protobuf/src/google/protobuf/generated_message_util.cc \
+	third_party/protobuf/src/google/protobuf/message_lite.cc \
+	third_party/protobuf/src/google/protobuf/repeated_field.cc \
+	third_party/protobuf/src/google/protobuf/wire_format_lite.cc \
+	third_party/protobuf/src/google/protobuf/io/coded_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_protobuf_protobuf_full_do_not_use_host_gyp
+
+# Alias gyp target name.
+.PHONY: protobuf_full_do_not_use
+protobuf_full_do_not_use: third_party_protobuf_protobuf_full_do_not_use_host_gyp
+
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk b/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk
index 921718e..2d4a708 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.linux-arm.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -157,6 +158,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk b/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk
index 54ce8cc..7863ee3 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.linux-mips.mk
@@ -100,6 +100,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -159,6 +160,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk b/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk
index 921718e..2d4a708 100644
--- a/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -157,6 +158,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86_64.mk b/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86_64.mk
new file mode 100644
index 0000000..562a246
--- /dev/null
+++ b/third_party/protobuf/protobuf_full_do_not_use.host.linux-x86_64.mk
@@ -0,0 +1,222 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_protobuf_protobuf_full_do_not_use_host_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_doc_comment.cc \
+	third_party/protobuf/src/google/protobuf/stubs/strutil.cc \
+	third_party/protobuf/src/google/protobuf/stubs/substitute.cc \
+	third_party/protobuf/src/google/protobuf/stubs/stringprintf.cc \
+	third_party/protobuf/src/google/protobuf/stubs/structurally_valid.cc \
+	third_party/protobuf/src/google/protobuf/descriptor.cc \
+	third_party/protobuf/src/google/protobuf/descriptor.pb.cc \
+	third_party/protobuf/src/google/protobuf/descriptor_database.cc \
+	third_party/protobuf/src/google/protobuf/dynamic_message.cc \
+	third_party/protobuf/src/google/protobuf/extension_set.cc \
+	third_party/protobuf/src/google/protobuf/extension_set_heavy.cc \
+	third_party/protobuf/src/google/protobuf/generated_message_reflection.cc \
+	third_party/protobuf/src/google/protobuf/message.cc \
+	third_party/protobuf/src/google/protobuf/reflection_ops.cc \
+	third_party/protobuf/src/google/protobuf/service.cc \
+	third_party/protobuf/src/google/protobuf/text_format.cc \
+	third_party/protobuf/src/google/protobuf/wire_format.cc \
+	third_party/protobuf/src/google/protobuf/io/printer.cc \
+	third_party/protobuf/src/google/protobuf/io/tokenizer.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.cc \
+	third_party/protobuf/src/google/protobuf/compiler/importer.cc \
+	third_party/protobuf/src/google/protobuf/compiler/parser.cc \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
+	third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
+	third_party/protobuf/src/google/protobuf/stubs/common.cc \
+	third_party/protobuf/src/google/protobuf/stubs/once.cc \
+	third_party/protobuf/src/google/protobuf/generated_message_util.cc \
+	third_party/protobuf/src/google/protobuf/message_lite.cc \
+	third_party/protobuf/src/google/protobuf/repeated_field.cc \
+	third_party/protobuf/src/google/protobuf/wire_format_lite.cc \
+	third_party/protobuf/src/google/protobuf/io/coded_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_protobuf_protobuf_full_do_not_use_host_gyp
+
+# Alias gyp target name.
+.PHONY: protobuf_full_do_not_use
+protobuf_full_do_not_use: third_party_protobuf_protobuf_full_do_not_use_host_gyp
+
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/third_party/protobuf/protobuf_lite.target.darwin-arm.mk b/third_party/protobuf/protobuf_lite.target.darwin-arm.mk
index 1413a59..d4da1ba 100644
--- a/third_party/protobuf/protobuf_lite.target.darwin-arm.mk
+++ b/third_party/protobuf/protobuf_lite.target.darwin-arm.mk
@@ -97,6 +97,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/protobuf/protobuf_lite.target.darwin-mips.mk b/third_party/protobuf/protobuf_lite.target.darwin-mips.mk
index 2d84907..0c909f0 100644
--- a/third_party/protobuf/protobuf_lite.target.darwin-mips.mk
+++ b/third_party/protobuf/protobuf_lite.target.darwin-mips.mk
@@ -97,6 +97,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/protobuf/protobuf_lite.target.darwin-x86.mk b/third_party/protobuf/protobuf_lite.target.darwin-x86.mk
index c036ad2..fa18dd6 100644
--- a/third_party/protobuf/protobuf_lite.target.darwin-x86.mk
+++ b/third_party/protobuf/protobuf_lite.target.darwin-x86.mk
@@ -98,6 +98,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -188,6 +189,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/protobuf/protobuf_lite.target.darwin-x86_64.mk b/third_party/protobuf/protobuf_lite.target.darwin-x86_64.mk
new file mode 100644
index 0000000..332b10f
--- /dev/null
+++ b/third_party/protobuf/protobuf_lite.target.darwin-x86_64.mk
@@ -0,0 +1,282 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_protobuf_protobuf_lite_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
+	third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
+	third_party/protobuf/src/google/protobuf/stubs/common.cc \
+	third_party/protobuf/src/google/protobuf/stubs/once.cc \
+	third_party/protobuf/src/google/protobuf/extension_set.cc \
+	third_party/protobuf/src/google/protobuf/generated_message_util.cc \
+	third_party/protobuf/src/google/protobuf/message_lite.cc \
+	third_party/protobuf/src/google/protobuf/repeated_field.cc \
+	third_party/protobuf/src/google/protobuf/wire_format_lite.cc \
+	third_party/protobuf/src/google/protobuf/io/coded_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBPROTOBUF_EXPORTS' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBPROTOBUF_EXPORTS' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_protobuf_protobuf_lite_gyp
+
+# Alias gyp target name.
+.PHONY: protobuf_lite
+protobuf_lite: third_party_protobuf_protobuf_lite_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/protobuf/protobuf_lite.target.linux-arm.mk b/third_party/protobuf/protobuf_lite.target.linux-arm.mk
index 1413a59..d4da1ba 100644
--- a/third_party/protobuf/protobuf_lite.target.linux-arm.mk
+++ b/third_party/protobuf/protobuf_lite.target.linux-arm.mk
@@ -97,6 +97,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/protobuf/protobuf_lite.target.linux-mips.mk b/third_party/protobuf/protobuf_lite.target.linux-mips.mk
index 2d84907..0c909f0 100644
--- a/third_party/protobuf/protobuf_lite.target.linux-mips.mk
+++ b/third_party/protobuf/protobuf_lite.target.linux-mips.mk
@@ -97,6 +97,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -187,6 +188,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/protobuf/protobuf_lite.target.linux-x86.mk b/third_party/protobuf/protobuf_lite.target.linux-x86.mk
index c036ad2..fa18dd6 100644
--- a/third_party/protobuf/protobuf_lite.target.linux-x86.mk
+++ b/third_party/protobuf/protobuf_lite.target.linux-x86.mk
@@ -98,6 +98,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -188,6 +189,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/protobuf/protobuf_lite.target.linux-x86_64.mk b/third_party/protobuf/protobuf_lite.target.linux-x86_64.mk
new file mode 100644
index 0000000..332b10f
--- /dev/null
+++ b/third_party/protobuf/protobuf_lite.target.linux-x86_64.mk
@@ -0,0 +1,282 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_protobuf_protobuf_lite_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc \
+	third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc \
+	third_party/protobuf/src/google/protobuf/unknown_field_set.cc \
+	third_party/protobuf/src/google/protobuf/stubs/common.cc \
+	third_party/protobuf/src/google/protobuf/stubs/once.cc \
+	third_party/protobuf/src/google/protobuf/extension_set.cc \
+	third_party/protobuf/src/google/protobuf/generated_message_util.cc \
+	third_party/protobuf/src/google/protobuf/message_lite.cc \
+	third_party/protobuf/src/google/protobuf/repeated_field.cc \
+	third_party/protobuf/src/google/protobuf/wire_format_lite.cc \
+	third_party/protobuf/src/google/protobuf/io/coded_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream.cc \
+	third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBPROTOBUF_EXPORTS' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DLIBPROTOBUF_EXPORTS' \
+	'-DPROTOBUF_USE_DLLS' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_protobuf_protobuf_lite_gyp
+
+# Alias gyp target name.
+.PHONY: protobuf_lite
+protobuf_lite: third_party_protobuf_protobuf_lite_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/protobuf/protoc.host.darwin-arm.mk b/third_party/protobuf/protoc.host.darwin-arm.mk
index b319329..f0d06ce 100644
--- a/third_party/protobuf/protoc.host.darwin-arm.mk
+++ b/third_party/protobuf/protoc.host.darwin-arm.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -158,6 +159,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protoc.host.darwin-mips.mk b/third_party/protobuf/protoc.host.darwin-mips.mk
index ff6a20d..574e5e9 100644
--- a/third_party/protobuf/protoc.host.darwin-mips.mk
+++ b/third_party/protobuf/protoc.host.darwin-mips.mk
@@ -100,6 +100,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -160,6 +161,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protoc.host.darwin-x86.mk b/third_party/protobuf/protoc.host.darwin-x86.mk
index b319329..f0d06ce 100644
--- a/third_party/protobuf/protoc.host.darwin-x86.mk
+++ b/third_party/protobuf/protoc.host.darwin-x86.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -158,6 +159,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protoc.host.darwin-x86_64.mk b/third_party/protobuf/protoc.host.darwin-x86_64.mk
new file mode 100644
index 0000000..126bc42
--- /dev/null
+++ b/third_party/protobuf/protoc.host.darwin-x86_64.mk
@@ -0,0 +1,222 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_protobuf_protoc_host_gyp
+LOCAL_MODULE_STEM := protoc
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_protobuf_protobuf_full_do_not_use_host_gyp,true)/third_party_protobuf_protobuf_full_do_not_use_host_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/protobuf/src/google/protobuf/compiler/code_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc \
+	third_party/protobuf/src/google/protobuf/compiler/plugin.cc \
+	third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc \
+	third_party/protobuf/src/google/protobuf/compiler/subprocess.cc \
+	third_party/protobuf/src/google/protobuf/compiler/zip_writer.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/main.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src/src \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src/src \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_protobuf_protobuf_full_do_not_use_host_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_protobuf_protoc_host_gyp
+
+# Alias gyp target name.
+.PHONY: protoc
+protoc: third_party_protobuf_protoc_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/protobuf/protoc.host.linux-arm.mk b/third_party/protobuf/protoc.host.linux-arm.mk
index 998a74a..195171e 100644
--- a/third_party/protobuf/protoc.host.linux-arm.mk
+++ b/third_party/protobuf/protoc.host.linux-arm.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -158,6 +159,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protoc.host.linux-mips.mk b/third_party/protobuf/protoc.host.linux-mips.mk
index 79537f1..4900183 100644
--- a/third_party/protobuf/protoc.host.linux-mips.mk
+++ b/third_party/protobuf/protoc.host.linux-mips.mk
@@ -100,6 +100,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -160,6 +161,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protoc.host.linux-x86.mk b/third_party/protobuf/protoc.host.linux-x86.mk
index 998a74a..195171e 100644
--- a/third_party/protobuf/protoc.host.linux-x86.mk
+++ b/third_party/protobuf/protoc.host.linux-x86.mk
@@ -99,6 +99,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -158,6 +159,7 @@
 	'-DGOOGLE_PROTOBUF_NO_RTTI' \
 	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/protobuf/protoc.host.linux-x86_64.mk b/third_party/protobuf/protoc.host.linux-x86_64.mk
new file mode 100644
index 0000000..7b577ab
--- /dev/null
+++ b/third_party/protobuf/protoc.host.linux-x86_64.mk
@@ -0,0 +1,226 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_protobuf_protoc_host_gyp
+LOCAL_MODULE_STEM := protoc
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_protobuf_protobuf_full_do_not_use_host_gyp,true)/third_party_protobuf_protobuf_full_do_not_use_host_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/protobuf/src/google/protobuf/compiler/code_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc \
+	third_party/protobuf/src/google/protobuf/compiler/plugin.cc \
+	third_party/protobuf/src/google/protobuf/compiler/plugin.pb.cc \
+	third_party/protobuf/src/google/protobuf/compiler/subprocess.cc \
+	third_party/protobuf/src/google/protobuf/compiler/zip_writer.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_enum_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_extension.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_file.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_helpers.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_message_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_service.cc \
+	third_party/protobuf/src/google/protobuf/compiler/cpp/cpp_string_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_enum.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_enum_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_extension.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_file.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_helpers.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_message.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_message_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_primitive_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_service.cc \
+	third_party/protobuf/src/google/protobuf/compiler/java/java_string_field.cc \
+	third_party/protobuf/src/google/protobuf/compiler/python/python_generator.cc \
+	third_party/protobuf/src/google/protobuf/compiler/main.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src/src \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGOOGLE_PROTOBUF_NO_RTTI' \
+	'-DGOOGLE_PROTOBUF_NO_STATIC_INITIALIZER' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/protobuf \
+	$(LOCAL_PATH)/third_party/protobuf/src/src \
+	$(LOCAL_PATH)/third_party/protobuf/src
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_protobuf_protobuf_full_do_not_use_host_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_protobuf_protoc_host_gyp
+
+# Alias gyp target name.
+.PHONY: protoc
+protoc: third_party_protobuf_protoc_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/protobuf/src/google/protobuf/stubs/atomicops.h b/third_party/protobuf/src/google/protobuf/stubs/atomicops.h
index ab935b0..f389a36 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/atomicops.h
+++ b/third_party/protobuf/src/google/protobuf/stubs/atomicops.h
@@ -181,6 +181,8 @@
 #include <google/protobuf/stubs/atomicops_internals_x86_gcc.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_ARM)
 #include <google/protobuf/stubs/atomicops_internals_arm_gcc.h>
+#elif defined(GOOGLE_PROTOBUF_ARCH_AARCH64)
+#include <google/protobuf/stubs/atomicops_internals_arm64_gcc.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_ARM_QNX)
 #include <google/protobuf/stubs/atomicops_internals_arm_qnx.h>
 #elif defined(GOOGLE_PROTOBUF_ARCH_MIPS)
diff --git a/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
new file mode 100644
index 0000000..c13cddb
--- /dev/null
+++ b/third_party/protobuf/src/google/protobuf/stubs/atomicops_internals_arm64_gcc.h
@@ -0,0 +1,378 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2012 Google Inc.  All rights reserved.
+// http://code.google.com/p/protobuf/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+inline void MemoryBarrier() {
+  __asm__ __volatile__ (  // NOLINT
+    "dmb ish                                  \n\t"  // Data memory barrier.
+    ::: "memory"
+  );  // NOLINT
+}
+
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+                                         Atomic32 old_value,
+                                         Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "1:                                    \n\t"
+    "clrex                                 \n\t"  // In case we didn't swap.
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+                                         Atomic32 new_value) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[result], %[ptr]               \n\t"  // Load the previous value.
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+                                          Atomic32 increment) {
+  Atomic32 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                       \n\t"
+    "ldxr %w[result], %[ptr]                  \n\t"  // Load the previous value.
+    "add %w[result], %w[result], %w[increment]\n\t"
+    "stxr %w[temp], %w[result], %[ptr]        \n\t"  // Try to store the result.
+    "cbnz %w[temp], 0b                        \n\t"  // Retry on failure.
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"r" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+                                        Atomic32 increment) {
+  MemoryBarrier();
+  Atomic32 result = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+
+  return result;
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "dmb ish                               \n\t"  // Data memory barrier.
+    "1:                                    \n\t"
+    // If the compare failed the 'dmb' is unnecessary, but we still need a
+    // 'clrex'.
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+                                       Atomic32 old_value,
+                                       Atomic32 new_value) {
+  Atomic32 prev;
+  int32_t temp;
+
+  MemoryBarrier();
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %w[prev], %[ptr]                 \n\t"  // Load the previous value.
+    "cmp %w[prev], %w[old_value]           \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %w[new_value], %[ptr]  \n\t"  // Try to store the new value.
+    "cbnz %w[temp], 0b                     \n\t"  // Retry if it did not work.
+    "1:                                    \n\t"
+    // If the compare failed the we still need a 'clrex'.
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+  return *ptr;
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+  Atomic32 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+// 64-bit versions of the operations.
+// See the 32-bit versions for comments.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+                                         Atomic64 old_value,
+                                         Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "1:                                    \n\t"
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+                                         Atomic64 new_value) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[result], %[ptr]                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [new_value]"r" (new_value)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+                                          Atomic64 increment) {
+  Atomic64 result;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                     \n\t"
+    "ldxr %[result], %[ptr]                 \n\t"
+    "add %[result], %[result], %[increment] \n\t"
+    "stxr %w[temp], %[result], %[ptr]       \n\t"
+    "cbnz %w[temp], 0b                      \n\t"
+    : [result]"=&r" (result),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [increment]"r" (increment)
+    : "memory"
+  );  // NOLINT
+
+  return result;
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+                                        Atomic64 increment) {
+  MemoryBarrier();
+  Atomic64 result = NoBarrier_AtomicIncrement(ptr, increment);
+  MemoryBarrier();
+
+  return result;
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "dmb ish                               \n\t"
+    "1:                                    \n\t"
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+                                       Atomic64 old_value,
+                                       Atomic64 new_value) {
+  Atomic64 prev;
+  int32_t temp;
+
+  MemoryBarrier();
+
+  __asm__ __volatile__ (  // NOLINT
+    "0:                                    \n\t"
+    "ldxr %[prev], %[ptr]                  \n\t"
+    "cmp %[prev], %[old_value]             \n\t"
+    "bne 1f                                \n\t"
+    "stxr %w[temp], %[new_value], %[ptr]   \n\t"
+    "cbnz %w[temp], 0b                     \n\t"
+    "1:                                    \n\t"
+    "clrex                                 \n\t"
+    : [prev]"=&r" (prev),
+      [temp]"=&r" (temp),
+      [ptr]"+Q" (*ptr)
+    : [old_value]"r" (old_value),
+      [new_value]"r" (new_value)
+    : "memory", "cc"
+  );  // NOLINT
+
+  return prev;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+  *ptr = value;
+  MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+  MemoryBarrier();
+  *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+  return *ptr;
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+  Atomic64 value = *ptr;
+  MemoryBarrier();
+  return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+  MemoryBarrier();
+  return *ptr;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_ARM64_GCC_H_
diff --git a/third_party/qcms/qcms.target.darwin-arm.mk b/third_party/qcms/qcms.target.darwin-arm.mk
index b67be9a..fb1d34e 100644
--- a/third_party/qcms/qcms.target.darwin-arm.mk
+++ b/third_party/qcms/qcms.target.darwin-arm.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/qcms/qcms.target.darwin-mips.mk b/third_party/qcms/qcms.target.darwin-mips.mk
index 6c1abc6..7dc3f21 100644
--- a/third_party/qcms/qcms.target.darwin-mips.mk
+++ b/third_party/qcms/qcms.target.darwin-mips.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/qcms/qcms.target.darwin-x86.mk b/third_party/qcms/qcms.target.darwin-x86.mk
index 8371b5e..3988093 100644
--- a/third_party/qcms/qcms.target.darwin-x86.mk
+++ b/third_party/qcms/qcms.target.darwin-x86.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSSE2_ENABLE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -173,6 +174,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSSE2_ENABLE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/qcms/qcms.target.darwin-x86_64.mk b/third_party/qcms/qcms.target.darwin-x86_64.mk
new file mode 100644
index 0000000..064d431
--- /dev/null
+++ b/third_party/qcms/qcms.target.darwin-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_qcms_qcms_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/qcms/src/chain.c \
+	third_party/qcms/src/iccread.c \
+	third_party/qcms/src/matrix.c \
+	third_party/qcms/src/transform.c \
+	third_party/qcms/src/transform_util.c \
+	third_party/qcms/src/transform-sse1.c \
+	third_party/qcms/src/transform-sse2.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSSE2_ENABLE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSSE2_ENABLE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_qcms_qcms_gyp
+
+# Alias gyp target name.
+.PHONY: qcms
+qcms: third_party_qcms_qcms_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/qcms/qcms.target.linux-arm.mk b/third_party/qcms/qcms.target.linux-arm.mk
index b67be9a..fb1d34e 100644
--- a/third_party/qcms/qcms.target.linux-arm.mk
+++ b/third_party/qcms/qcms.target.linux-arm.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/qcms/qcms.target.linux-mips.mk b/third_party/qcms/qcms.target.linux-mips.mk
index 6c1abc6..7dc3f21 100644
--- a/third_party/qcms/qcms.target.linux-mips.mk
+++ b/third_party/qcms/qcms.target.linux-mips.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -168,6 +169,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/qcms/qcms.target.linux-x86.mk b/third_party/qcms/qcms.target.linux-x86.mk
index 8371b5e..3988093 100644
--- a/third_party/qcms/qcms.target.linux-x86.mk
+++ b/third_party/qcms/qcms.target.linux-x86.mk
@@ -88,6 +88,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSSE2_ENABLE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -173,6 +174,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DSSE2_ENABLE' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/qcms/qcms.target.linux-x86_64.mk b/third_party/qcms/qcms.target.linux-x86_64.mk
new file mode 100644
index 0000000..064d431
--- /dev/null
+++ b/third_party/qcms/qcms.target.linux-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_qcms_qcms_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/qcms/src/chain.c \
+	third_party/qcms/src/iccread.c \
+	third_party/qcms/src/matrix.c \
+	third_party/qcms/src/transform.c \
+	third_party/qcms/src/transform_util.c \
+	third_party/qcms/src/transform-sse1.c \
+	third_party/qcms/src/transform-sse2.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSSE2_ENABLE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSSE2_ENABLE' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_qcms_qcms_gyp
+
+# Alias gyp target name.
+.PHONY: qcms
+qcms: third_party_qcms_qcms_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/re2/re2.target.darwin-arm.mk b/third_party/re2/re2.target.darwin-arm.mk
index 58271d4..425fb48 100644
--- a/third_party/re2/re2.target.darwin-arm.mk
+++ b/third_party/re2/re2.target.darwin-arm.mk
@@ -105,6 +105,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -191,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/re2/re2.target.darwin-mips.mk b/third_party/re2/re2.target.darwin-mips.mk
index c87e8be..dded925 100644
--- a/third_party/re2/re2.target.darwin-mips.mk
+++ b/third_party/re2/re2.target.darwin-mips.mk
@@ -105,6 +105,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -191,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/re2/re2.target.darwin-x86.mk b/third_party/re2/re2.target.darwin-x86.mk
index fddd6ba..cf12dcf 100644
--- a/third_party/re2/re2.target.darwin-x86.mk
+++ b/third_party/re2/re2.target.darwin-x86.mk
@@ -106,6 +106,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -192,6 +193,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/re2/re2.target.darwin-x86_64.mk b/third_party/re2/re2.target.darwin-x86_64.mk
new file mode 100644
index 0000000..365d69f
--- /dev/null
+++ b/third_party/re2/re2.target.darwin-x86_64.mk
@@ -0,0 +1,286 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_re2_re2_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/re2/re2/bitstate.cc \
+	third_party/re2/re2/compile.cc \
+	third_party/re2/re2/dfa.cc \
+	third_party/re2/re2/filtered_re2.cc \
+	third_party/re2/re2/mimics_pcre.cc \
+	third_party/re2/re2/nfa.cc \
+	third_party/re2/re2/onepass.cc \
+	third_party/re2/re2/parse.cc \
+	third_party/re2/re2/perl_groups.cc \
+	third_party/re2/re2/prefilter.cc \
+	third_party/re2/re2/prefilter_tree.cc \
+	third_party/re2/re2/prog.cc \
+	third_party/re2/re2/re2.cc \
+	third_party/re2/re2/regexp.cc \
+	third_party/re2/re2/set.cc \
+	third_party/re2/re2/simplify.cc \
+	third_party/re2/re2/tostring.cc \
+	third_party/re2/re2/unicode_casefold.cc \
+	third_party/re2/re2/unicode_groups.cc \
+	third_party/re2/util/arena.cc \
+	third_party/re2/util/hash.cc \
+	third_party/re2/util/rune.cc \
+	third_party/re2/util/stringpiece.cc \
+	third_party/re2/util/stringprintf.cc \
+	third_party/re2/util/strutil.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_re2_re2_gyp
+
+# Alias gyp target name.
+.PHONY: re2
+re2: third_party_re2_re2_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/re2/re2.target.linux-arm.mk b/third_party/re2/re2.target.linux-arm.mk
index 58271d4..425fb48 100644
--- a/third_party/re2/re2.target.linux-arm.mk
+++ b/third_party/re2/re2.target.linux-arm.mk
@@ -105,6 +105,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -191,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/re2/re2.target.linux-mips.mk b/third_party/re2/re2.target.linux-mips.mk
index c87e8be..dded925 100644
--- a/third_party/re2/re2.target.linux-mips.mk
+++ b/third_party/re2/re2.target.linux-mips.mk
@@ -105,6 +105,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -191,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/re2/re2.target.linux-x86.mk b/third_party/re2/re2.target.linux-x86.mk
index fddd6ba..cf12dcf 100644
--- a/third_party/re2/re2.target.linux-x86.mk
+++ b/third_party/re2/re2.target.linux-x86.mk
@@ -106,6 +106,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -192,6 +193,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/re2/re2.target.linux-x86_64.mk b/third_party/re2/re2.target.linux-x86_64.mk
new file mode 100644
index 0000000..365d69f
--- /dev/null
+++ b/third_party/re2/re2.target.linux-x86_64.mk
@@ -0,0 +1,286 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_re2_re2_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/re2/re2/bitstate.cc \
+	third_party/re2/re2/compile.cc \
+	third_party/re2/re2/dfa.cc \
+	third_party/re2/re2/filtered_re2.cc \
+	third_party/re2/re2/mimics_pcre.cc \
+	third_party/re2/re2/nfa.cc \
+	third_party/re2/re2/onepass.cc \
+	third_party/re2/re2/parse.cc \
+	third_party/re2/re2/perl_groups.cc \
+	third_party/re2/re2/prefilter.cc \
+	third_party/re2/re2/prefilter_tree.cc \
+	third_party/re2/re2/prog.cc \
+	third_party/re2/re2/re2.cc \
+	third_party/re2/re2/regexp.cc \
+	third_party/re2/re2/set.cc \
+	third_party/re2/re2/simplify.cc \
+	third_party/re2/re2/tostring.cc \
+	third_party/re2/re2/unicode_casefold.cc \
+	third_party/re2/re2/unicode_groups.cc \
+	third_party/re2/util/arena.cc \
+	third_party/re2/util/hash.cc \
+	third_party/re2/util/rune.cc \
+	third_party/re2/util/stringpiece.cc \
+	third_party/re2/util/stringprintf.cc \
+	third_party/re2/util/strutil.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/re2 \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_re2_re2_gyp
+
+# Alias gyp target name.
+.PHONY: re2
+re2: third_party_re2_re2_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/sfntly/sfntly.target.darwin-arm.mk b/third_party/sfntly/sfntly.target.darwin-arm.mk
index 6889e27..cbc3775 100644
--- a/third_party/sfntly/sfntly.target.darwin-arm.mk
+++ b/third_party/sfntly/sfntly.target.darwin-arm.mk
@@ -131,6 +131,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,6 +221,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/third_party/sfntly/sfntly.target.darwin-mips.mk b/third_party/sfntly/sfntly.target.darwin-mips.mk
index 0676387..258f8d8 100644
--- a/third_party/sfntly/sfntly.target.darwin-mips.mk
+++ b/third_party/sfntly/sfntly.target.darwin-mips.mk
@@ -130,6 +130,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,6 +219,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/third_party/sfntly/sfntly.target.darwin-x86.mk b/third_party/sfntly/sfntly.target.darwin-x86.mk
index 0a431af..d65181a 100644
--- a/third_party/sfntly/sfntly.target.darwin-x86.mk
+++ b/third_party/sfntly/sfntly.target.darwin-x86.mk
@@ -132,6 +132,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,6 +222,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/third_party/sfntly/sfntly.target.darwin-x86_64.mk b/third_party/sfntly/sfntly.target.darwin-x86_64.mk
new file mode 100644
index 0000000..c2bbcae
--- /dev/null
+++ b/third_party/sfntly/sfntly.target.darwin-x86_64.mk
@@ -0,0 +1,320 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_sfntly_sfntly_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/sfntly/cpp/src/sfntly/data/byte_array.cc \
+	third_party/sfntly/cpp/src/sfntly/data/font_data.cc \
+	third_party/sfntly/cpp/src/sfntly/data/font_input_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/data/font_output_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/data/growable_memory_byte_array.cc \
+	third_party/sfntly/cpp/src/sfntly/data/memory_byte_array.cc \
+	third_party/sfntly/cpp/src/sfntly/data/readable_font_data.cc \
+	third_party/sfntly/cpp/src/sfntly/data/writable_font_data.cc \
+	third_party/sfntly/cpp/src/sfntly/font.cc \
+	third_party/sfntly/cpp/src/sfntly/font_factory.cc \
+	third_party/sfntly/cpp/src/sfntly/port/file_input_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/port/lock.cc \
+	third_party/sfntly/cpp/src/sfntly/port/memory_input_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/port/memory_output_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/bitmap_glyph.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/bitmap_size_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/ebdt_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/eblc_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/ebsc_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/glyph_metrics.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc \
+	third_party/sfntly/cpp/src/sfntly/table/byte_array_table_builder.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/cmap_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/font_header_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/horizontal_header_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/horizontal_metrics_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/maximum_profile_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/name_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/os2_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/font_data_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/generic_table_builder.cc \
+	third_party/sfntly/cpp/src/sfntly/table/header.cc \
+	third_party/sfntly/cpp/src/sfntly/table/subtable.cc \
+	third_party/sfntly/cpp/src/sfntly/table/table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/table_based_table_builder.cc \
+	third_party/sfntly/cpp/src/sfntly/table/truetype/glyph_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/truetype/loca_table.cc \
+	third_party/sfntly/cpp/src/sfntly/tag.cc \
+	third_party/sfntly/cpp/src/sample/chromium/font_subsetter.cc \
+	third_party/sfntly/cpp/src/sample/chromium/subsetter_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSFNTLY_NO_EXCEPTION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/sfntly/cpp/src \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSFNTLY_NO_EXCEPTION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/sfntly/cpp/src \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_sfntly_sfntly_gyp
+
+# Alias gyp target name.
+.PHONY: sfntly
+sfntly: third_party_sfntly_sfntly_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/sfntly/sfntly.target.linux-arm.mk b/third_party/sfntly/sfntly.target.linux-arm.mk
index 6889e27..cbc3775 100644
--- a/third_party/sfntly/sfntly.target.linux-arm.mk
+++ b/third_party/sfntly/sfntly.target.linux-arm.mk
@@ -131,6 +131,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,6 +221,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/third_party/sfntly/sfntly.target.linux-mips.mk b/third_party/sfntly/sfntly.target.linux-mips.mk
index 0676387..258f8d8 100644
--- a/third_party/sfntly/sfntly.target.linux-mips.mk
+++ b/third_party/sfntly/sfntly.target.linux-mips.mk
@@ -130,6 +130,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,6 +219,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/third_party/sfntly/sfntly.target.linux-x86.mk b/third_party/sfntly/sfntly.target.linux-x86.mk
index 0a431af..d65181a 100644
--- a/third_party/sfntly/sfntly.target.linux-x86.mk
+++ b/third_party/sfntly/sfntly.target.linux-x86.mk
@@ -132,6 +132,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,6 +222,7 @@
 	'-DSFNTLY_NO_EXCEPTION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/third_party/sfntly/sfntly.target.linux-x86_64.mk b/third_party/sfntly/sfntly.target.linux-x86_64.mk
new file mode 100644
index 0000000..c2bbcae
--- /dev/null
+++ b/third_party/sfntly/sfntly.target.linux-x86_64.mk
@@ -0,0 +1,320 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_sfntly_sfntly_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/sfntly/cpp/src/sfntly/data/byte_array.cc \
+	third_party/sfntly/cpp/src/sfntly/data/font_data.cc \
+	third_party/sfntly/cpp/src/sfntly/data/font_input_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/data/font_output_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/data/growable_memory_byte_array.cc \
+	third_party/sfntly/cpp/src/sfntly/data/memory_byte_array.cc \
+	third_party/sfntly/cpp/src/sfntly/data/readable_font_data.cc \
+	third_party/sfntly/cpp/src/sfntly/data/writable_font_data.cc \
+	third_party/sfntly/cpp/src/sfntly/font.cc \
+	third_party/sfntly/cpp/src/sfntly/font_factory.cc \
+	third_party/sfntly/cpp/src/sfntly/port/file_input_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/port/lock.cc \
+	third_party/sfntly/cpp/src/sfntly/port/memory_input_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/port/memory_output_stream.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/big_glyph_metrics.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/bitmap_glyph.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/bitmap_glyph_info.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/bitmap_size_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/composite_bitmap_glyph.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/ebdt_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/eblc_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/ebsc_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/glyph_metrics.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format1.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format2.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format3.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format4.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/index_sub_table_format5.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/simple_bitmap_glyph.cc \
+	third_party/sfntly/cpp/src/sfntly/table/bitmap/small_glyph_metrics.cc \
+	third_party/sfntly/cpp/src/sfntly/table/byte_array_table_builder.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/cmap_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/font_header_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/horizontal_device_metrics_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/horizontal_header_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/horizontal_metrics_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/maximum_profile_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/name_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/core/os2_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/font_data_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/generic_table_builder.cc \
+	third_party/sfntly/cpp/src/sfntly/table/header.cc \
+	third_party/sfntly/cpp/src/sfntly/table/subtable.cc \
+	third_party/sfntly/cpp/src/sfntly/table/table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/table_based_table_builder.cc \
+	third_party/sfntly/cpp/src/sfntly/table/truetype/glyph_table.cc \
+	third_party/sfntly/cpp/src/sfntly/table/truetype/loca_table.cc \
+	third_party/sfntly/cpp/src/sfntly/tag.cc \
+	third_party/sfntly/cpp/src/sample/chromium/font_subsetter.cc \
+	third_party/sfntly/cpp/src/sample/chromium/subsetter_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSFNTLY_NO_EXCEPTION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/sfntly/cpp/src \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSFNTLY_NO_EXCEPTION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/third_party/sfntly/cpp/src \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_sfntly_sfntly_gyp
+
+# Alias gyp target name.
+.PHONY: sfntly
+sfntly: third_party_sfntly_sfntly_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/smhasher/cityhash.target.darwin-arm.mk b/third_party/smhasher/cityhash.target.darwin-arm.mk
index ab9ece4..7929202 100644
--- a/third_party/smhasher/cityhash.target.darwin-arm.mk
+++ b/third_party/smhasher/cityhash.target.darwin-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/smhasher/cityhash.target.darwin-mips.mk b/third_party/smhasher/cityhash.target.darwin-mips.mk
index 41456df..2442404 100644
--- a/third_party/smhasher/cityhash.target.darwin-mips.mk
+++ b/third_party/smhasher/cityhash.target.darwin-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/smhasher/cityhash.target.darwin-x86.mk b/third_party/smhasher/cityhash.target.darwin-x86.mk
index 66a6729..a725826 100644
--- a/third_party/smhasher/cityhash.target.darwin-x86.mk
+++ b/third_party/smhasher/cityhash.target.darwin-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/smhasher/cityhash.target.darwin-x86_64.mk b/third_party/smhasher/cityhash.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d68f82a
--- /dev/null
+++ b/third_party/smhasher/cityhash.target.darwin-x86_64.mk
@@ -0,0 +1,257 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_smhasher_cityhash_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/smhasher/src/City.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_smhasher_cityhash_gyp
+
+# Alias gyp target name.
+.PHONY: cityhash
+cityhash: third_party_smhasher_cityhash_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/smhasher/cityhash.target.linux-arm.mk b/third_party/smhasher/cityhash.target.linux-arm.mk
index ab9ece4..7929202 100644
--- a/third_party/smhasher/cityhash.target.linux-arm.mk
+++ b/third_party/smhasher/cityhash.target.linux-arm.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/smhasher/cityhash.target.linux-mips.mk b/third_party/smhasher/cityhash.target.linux-mips.mk
index 41456df..2442404 100644
--- a/third_party/smhasher/cityhash.target.linux-mips.mk
+++ b/third_party/smhasher/cityhash.target.linux-mips.mk
@@ -80,6 +80,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -164,6 +165,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/smhasher/cityhash.target.linux-x86.mk b/third_party/smhasher/cityhash.target.linux-x86.mk
index 66a6729..a725826 100644
--- a/third_party/smhasher/cityhash.target.linux-x86.mk
+++ b/third_party/smhasher/cityhash.target.linux-x86.mk
@@ -81,6 +81,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -165,6 +166,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/smhasher/cityhash.target.linux-x86_64.mk b/third_party/smhasher/cityhash.target.linux-x86_64.mk
new file mode 100644
index 0000000..d68f82a
--- /dev/null
+++ b/third_party/smhasher/cityhash.target.linux-x86_64.mk
@@ -0,0 +1,257 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_smhasher_cityhash_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/smhasher/src/City.cpp
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_smhasher_cityhash_gyp
+
+# Alias gyp target name.
+.PHONY: cityhash
+cityhash: third_party_smhasher_cityhash_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/sqlite/sqlite.target.darwin-arm.mk b/third_party/sqlite/sqlite.target.darwin-arm.mk
index c16c97a..5e0a8d1 100644
--- a/third_party/sqlite/sqlite.target.darwin-arm.mk
+++ b/third_party/sqlite/sqlite.target.darwin-arm.mk
@@ -105,6 +105,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -212,6 +213,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/sqlite/sqlite.target.darwin-mips.mk b/third_party/sqlite/sqlite.target.darwin-mips.mk
index 9559f4b..43b3558 100644
--- a/third_party/sqlite/sqlite.target.darwin-mips.mk
+++ b/third_party/sqlite/sqlite.target.darwin-mips.mk
@@ -105,6 +105,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -212,6 +213,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/sqlite/sqlite.target.darwin-x86.mk b/third_party/sqlite/sqlite.target.darwin-x86.mk
index e6b3e45..ef72e18 100644
--- a/third_party/sqlite/sqlite.target.darwin-x86.mk
+++ b/third_party/sqlite/sqlite.target.darwin-x86.mk
@@ -106,6 +106,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -213,6 +214,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/sqlite/sqlite.target.darwin-x86_64.mk b/third_party/sqlite/sqlite.target.darwin-x86_64.mk
new file mode 100644
index 0000000..c03d734
--- /dev/null
+++ b/third_party/sqlite/sqlite.target.darwin-x86_64.mk
@@ -0,0 +1,311 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_sqlite_sqlite_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/sqlite/amalgamation/sqlite3.c \
+	third_party/sqlite/src/ext/fts2/fts2.c \
+	third_party/sqlite/src/ext/fts2/fts2_hash.c \
+	third_party/sqlite/src/ext/fts2/fts2_icu.c \
+	third_party/sqlite/src/ext/fts2/fts2_porter.c \
+	third_party/sqlite/src/ext/fts2/fts2_tokenizer.c \
+	third_party/sqlite/src/ext/fts2/fts2_tokenizer1.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DSQLITE_CORE' \
+	'-DSQLITE_ENABLE_BROKEN_FTS2' \
+	'-DSQLITE_ENABLE_FTS2' \
+	'-DSQLITE_ENABLE_FTS3' \
+	'-DSQLITE_ENABLE_ICU' \
+	'-DSQLITE_ENABLE_MEMORY_MANAGEMENT' \
+	'-DSQLITE_SECURE_DELETE' \
+	'-DSQLITE_SEPARATE_CACHE_POOLS' \
+	'-DTHREADSAFE' \
+	'-D_HAS_EXCEPTIONS=0' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_USLEEP=1' \
+	'-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576' \
+	'-DSQLITE_DEFAULT_AUTOVACUUM=1' \
+	'-DSQLITE_TEMP_STORE=3' \
+	'-DSQLITE_ENABLE_FTS3_BACKWARDS' \
+	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/sqlite/amalgamation \
+	$(LOCAL_PATH)/third_party/sqlite/src/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DSQLITE_CORE' \
+	'-DSQLITE_ENABLE_BROKEN_FTS2' \
+	'-DSQLITE_ENABLE_FTS2' \
+	'-DSQLITE_ENABLE_FTS3' \
+	'-DSQLITE_ENABLE_ICU' \
+	'-DSQLITE_ENABLE_MEMORY_MANAGEMENT' \
+	'-DSQLITE_SECURE_DELETE' \
+	'-DSQLITE_SEPARATE_CACHE_POOLS' \
+	'-DTHREADSAFE' \
+	'-D_HAS_EXCEPTIONS=0' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_USLEEP=1' \
+	'-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576' \
+	'-DSQLITE_DEFAULT_AUTOVACUUM=1' \
+	'-DSQLITE_TEMP_STORE=3' \
+	'-DSQLITE_ENABLE_FTS3_BACKWARDS' \
+	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/sqlite/amalgamation \
+	$(LOCAL_PATH)/third_party/sqlite/src/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_sqlite_sqlite_gyp
+
+# Alias gyp target name.
+.PHONY: sqlite
+sqlite: third_party_sqlite_sqlite_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/sqlite/sqlite.target.linux-arm.mk b/third_party/sqlite/sqlite.target.linux-arm.mk
index c16c97a..5e0a8d1 100644
--- a/third_party/sqlite/sqlite.target.linux-arm.mk
+++ b/third_party/sqlite/sqlite.target.linux-arm.mk
@@ -105,6 +105,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -212,6 +213,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/sqlite/sqlite.target.linux-mips.mk b/third_party/sqlite/sqlite.target.linux-mips.mk
index 9559f4b..43b3558 100644
--- a/third_party/sqlite/sqlite.target.linux-mips.mk
+++ b/third_party/sqlite/sqlite.target.linux-mips.mk
@@ -105,6 +105,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -212,6 +213,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/sqlite/sqlite.target.linux-x86.mk b/third_party/sqlite/sqlite.target.linux-x86.mk
index e6b3e45..ef72e18 100644
--- a/third_party/sqlite/sqlite.target.linux-x86.mk
+++ b/third_party/sqlite/sqlite.target.linux-x86.mk
@@ -106,6 +106,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -213,6 +214,7 @@
 	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/sqlite/sqlite.target.linux-x86_64.mk b/third_party/sqlite/sqlite.target.linux-x86_64.mk
new file mode 100644
index 0000000..c03d734
--- /dev/null
+++ b/third_party/sqlite/sqlite.target.linux-x86_64.mk
@@ -0,0 +1,311 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_sqlite_sqlite_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/sqlite/amalgamation/sqlite3.c \
+	third_party/sqlite/src/ext/fts2/fts2.c \
+	third_party/sqlite/src/ext/fts2/fts2_hash.c \
+	third_party/sqlite/src/ext/fts2/fts2_icu.c \
+	third_party/sqlite/src/ext/fts2/fts2_porter.c \
+	third_party/sqlite/src/ext/fts2/fts2_tokenizer.c \
+	third_party/sqlite/src/ext/fts2/fts2_tokenizer1.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DSQLITE_CORE' \
+	'-DSQLITE_ENABLE_BROKEN_FTS2' \
+	'-DSQLITE_ENABLE_FTS2' \
+	'-DSQLITE_ENABLE_FTS3' \
+	'-DSQLITE_ENABLE_ICU' \
+	'-DSQLITE_ENABLE_MEMORY_MANAGEMENT' \
+	'-DSQLITE_SECURE_DELETE' \
+	'-DSQLITE_SEPARATE_CACHE_POOLS' \
+	'-DTHREADSAFE' \
+	'-D_HAS_EXCEPTIONS=0' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_USLEEP=1' \
+	'-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576' \
+	'-DSQLITE_DEFAULT_AUTOVACUUM=1' \
+	'-DSQLITE_TEMP_STORE=3' \
+	'-DSQLITE_ENABLE_FTS3_BACKWARDS' \
+	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/sqlite/amalgamation \
+	$(LOCAL_PATH)/third_party/sqlite/src/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DSQLITE_CORE' \
+	'-DSQLITE_ENABLE_BROKEN_FTS2' \
+	'-DSQLITE_ENABLE_FTS2' \
+	'-DSQLITE_ENABLE_FTS3' \
+	'-DSQLITE_ENABLE_ICU' \
+	'-DSQLITE_ENABLE_MEMORY_MANAGEMENT' \
+	'-DSQLITE_SECURE_DELETE' \
+	'-DSQLITE_SEPARATE_CACHE_POOLS' \
+	'-DTHREADSAFE' \
+	'-D_HAS_EXCEPTIONS=0' \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_USLEEP=1' \
+	'-DSQLITE_DEFAULT_JOURNAL_SIZE_LIMIT=1048576' \
+	'-DSQLITE_DEFAULT_AUTOVACUUM=1' \
+	'-DSQLITE_TEMP_STORE=3' \
+	'-DSQLITE_ENABLE_FTS3_BACKWARDS' \
+	'-DDSQLITE_DEFAULT_FILE_FORMAT=4' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(LOCAL_PATH)/third_party/sqlite/amalgamation \
+	$(LOCAL_PATH)/third_party/sqlite/src/src \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_sqlite_sqlite_gyp
+
+# Alias gyp target name.
+.PHONY: sqlite
+sqlite: third_party_sqlite_sqlite_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/tcmalloc/README.chromium b/third_party/tcmalloc/README.chromium
index 92fbf75..c5f40b1 100644
--- a/third_party/tcmalloc/README.chromium
+++ b/third_party/tcmalloc/README.chromium
@@ -93,3 +93,4 @@
   simulated stack from the embedding application.
 - Inserted spaces around PRIx64, SCNx64 and friends, for c++11 compatibility.
 - Fix sprintf formatting warning in MaybeDumpProfileLocked
+- Added tc_malloc_skip_new_handler.
diff --git a/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h b/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h
index ac1e797..bdbc4b7 100644
--- a/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h
+++ b/third_party/tcmalloc/chromium/src/base/linux_syscall_support.h
@@ -157,9 +157,7 @@
 #include <sys/types.h>
 #if defined(__ANDROID__)
 #include <sys/syscall.h>
-#ifndef ANDROID_NON_SDK_BUILD
 #include <sys/linux-syscalls.h>
-#endif
 #else
 #include <syscall.h>
 #endif
diff --git a/third_party/tcmalloc/chromium/src/debugallocation.cc b/third_party/tcmalloc/chromium/src/debugallocation.cc
index 7b09e41..6a4f286 100644
--- a/third_party/tcmalloc/chromium/src/debugallocation.cc
+++ b/third_party/tcmalloc/chromium/src/debugallocation.cc
@@ -1430,3 +1430,11 @@
 extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
   return MallocExtension::instance()->GetAllocatedSize(ptr);
 }
+
+#if defined(OS_LINUX)
+extern "C" PERFTOOLS_DLL_DECL void* tc_malloc_skip_new_handler(size_t size) {
+  void* result = DebugAllocate(size, MallocBlock::kMallocType);
+  MallocHook::InvokeNewHook(result, size);
+  return result;
+}
+#endif
diff --git a/third_party/tcmalloc/chromium/src/heap-profiler.cc b/third_party/tcmalloc/chromium/src/heap-profiler.cc
index d27e0b3..da4ed49 100644
--- a/third_party/tcmalloc/chromium/src/heap-profiler.cc
+++ b/third_party/tcmalloc/chromium/src/heap-profiler.cc
@@ -671,7 +671,7 @@
     return;
   }
   // We do a uid check so we don't write out files in a setuid executable.
-#if !defined(__ANDROID__) && defined(HAVE_GETEUID)
+#ifdef HAVE_GETEUID
   if (getuid() != geteuid()) {
     RAW_LOG(WARNING, ("HeapProfiler: ignoring " HEAPPROFILE " because "
                       "program seems to be setuid\n"));
diff --git a/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h b/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h
index feefe0c..3b858ca 100644
--- a/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h
+++ b/third_party/tcmalloc/chromium/src/libc_override_gcc_and_weak.h
@@ -94,12 +94,7 @@
   struct mallinfo mallinfo(void) __THROW          ALIAS(tc_mallinfo);
 #endif
   size_t malloc_size(void* p) __THROW             ALIAS(tc_malloc_size);
-#if defined(__ANDROID__) && defined(ANDROID_NON_SDK_BUILD)
-  // In Android tree this function is defined differently than in the NDK.
-  size_t malloc_usable_size(const void* p) __THROW      ALIAS(tc_malloc_size);
-#else
   size_t malloc_usable_size(void* p) __THROW      ALIAS(tc_malloc_size);
-#endif
 }   // extern "C"
 
 #undef ALIAS
diff --git a/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h b/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h
index 8b8b4ad..715c045 100644
--- a/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h
+++ b/third_party/tcmalloc/chromium/src/malloc_hook_mmap_linux.h
@@ -42,9 +42,7 @@
 #include <unistd.h>
 #if defined(__ANDROID__)
 #include <sys/syscall.h>
-#ifndef ANDROID_NON_SDK_BUILD
 #include <sys/linux-syscalls.h>
-#endif
 #else
 #include <syscall.h>
 #endif
diff --git a/third_party/tcmalloc/chromium/src/tcmalloc.cc b/third_party/tcmalloc/chromium/src/tcmalloc.cc
index 118e40a..018bd8e 100644
--- a/third_party/tcmalloc/chromium/src/tcmalloc.cc
+++ b/third_party/tcmalloc/chromium/src/tcmalloc.cc
@@ -1719,8 +1719,22 @@
   return MallocExtension::instance()->GetAllocatedSize(ptr);
 }
 
+#if defined(OS_LINUX)
+extern "C" void* PERFTOOLS_DLL_DECL tc_malloc_skip_new_handler(size_t size) {
+  void* result = do_malloc(size);
+  MallocHook::InvokeNewHook(result, size);
+  return result;
+}
+#endif
+
 #endif  // TCMALLOC_USING_DEBUGALLOCATION
 
+#if defined(OS_LINUX)
+// Alias the weak symbol in chromium to our implementation.
+extern "C" __attribute__((visibility("default"), alias("tc_malloc_skip_new_handler")))
+void* tc_malloc_skip_new_handler_weak(size_t size);
+#endif
+
 // --- Validation implementation with an extra mark ----------------------------
 // We will put a mark at the extreme end of each allocation block.  We make
 // sure that we always allocate enough "extra memory" that we can fit in the
diff --git a/third_party/widevine/cdm/widevine_cdm_version_h.target.darwin-x86_64.mk b/third_party/widevine/cdm/widevine_cdm_version_h.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d3aac26
--- /dev/null
+++ b/third_party/widevine/cdm/widevine_cdm_version_h.target.darwin-x86_64.mk
@@ -0,0 +1,47 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_widevine_cdm_widevine_cdm_version_h_gyp
+LOCAL_MODULE_STEM := widevine_cdm_version_h
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Generated for copy rule.
+$(gyp_shared_intermediate_dir)/widevine_cdm_version.h: $(LOCAL_PATH)/third_party/widevine/cdm/android/widevine_cdm_version.h $(GYP_TARGET_DEPENDENCIES) | $(ACP)
+	@echo Copying: $@
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(ACP) -rpf $< $@
+
+third_party_widevine_cdm_widevine_cdm_gyp_widevine_cdm_version_h_target_copies = $(gyp_shared_intermediate_dir)/widevine_cdm_version.h
+
+GYP_GENERATED_OUTPUTS := \
+	$(third_party_widevine_cdm_widevine_cdm_gyp_widevine_cdm_version_h_target_copies)
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_widevine_cdm_widevine_cdm_version_h_gyp
+
+# Alias gyp target name.
+.PHONY: widevine_cdm_version_h
+widevine_cdm_version_h: third_party_widevine_cdm_widevine_cdm_version_h_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/widevine/cdm/widevine_cdm_version_h.target.linux-x86_64.mk b/third_party/widevine/cdm/widevine_cdm_version_h.target.linux-x86_64.mk
new file mode 100644
index 0000000..d3aac26
--- /dev/null
+++ b/third_party/widevine/cdm/widevine_cdm_version_h.target.linux-x86_64.mk
@@ -0,0 +1,47 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_widevine_cdm_widevine_cdm_version_h_gyp
+LOCAL_MODULE_STEM := widevine_cdm_version_h
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Generated for copy rule.
+$(gyp_shared_intermediate_dir)/widevine_cdm_version.h: $(LOCAL_PATH)/third_party/widevine/cdm/android/widevine_cdm_version.h $(GYP_TARGET_DEPENDENCIES) | $(ACP)
+	@echo Copying: $@
+	$(hide) mkdir -p $(dir $@)
+	$(hide) $(ACP) -rpf $< $@
+
+third_party_widevine_cdm_widevine_cdm_gyp_widevine_cdm_version_h_target_copies = $(gyp_shared_intermediate_dir)/widevine_cdm_version.h
+
+GYP_GENERATED_OUTPUTS := \
+	$(third_party_widevine_cdm_widevine_cdm_gyp_widevine_cdm_version_h_target_copies)
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_widevine_cdm_widevine_cdm_version_h_gyp
+
+# Alias gyp target name.
+.PHONY: widevine_cdm_version_h
+widevine_cdm_version_h: third_party_widevine_cdm_widevine_cdm_version_h_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/yasm/config_sources.host.darwin-x86.mk b/third_party/yasm/config_sources.host.darwin-x86.mk
index b6c3130..0e1b855 100644
--- a/third_party/yasm/config_sources.host.darwin-x86.mk
+++ b/third_party/yasm/config_sources.host.darwin-x86.mk
@@ -63,6 +63,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -117,6 +118,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/config_sources.host.darwin-x86_64.mk b/third_party/yasm/config_sources.host.darwin-x86_64.mk
new file mode 100644
index 0000000..771bfa8
--- /dev/null
+++ b/third_party/yasm/config_sources.host.darwin-x86_64.mk
@@ -0,0 +1,164 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_yasm_config_sources_host_gyp
+LOCAL_MODULE_STEM := config_sources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_config_sources_host_gyp
+
+# Alias gyp target name.
+.PHONY: config_sources
+config_sources: third_party_yasm_config_sources_host_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/yasm/config_sources.host.linux-x86.mk b/third_party/yasm/config_sources.host.linux-x86.mk
index b6c3130..0e1b855 100644
--- a/third_party/yasm/config_sources.host.linux-x86.mk
+++ b/third_party/yasm/config_sources.host.linux-x86.mk
@@ -63,6 +63,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -117,6 +118,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/config_sources.host.linux-x86_64.mk b/third_party/yasm/config_sources.host.linux-x86_64.mk
new file mode 100644
index 0000000..771bfa8
--- /dev/null
+++ b/third_party/yasm/config_sources.host.linux-x86_64.mk
@@ -0,0 +1,164 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_yasm_config_sources_host_gyp
+LOCAL_MODULE_STEM := config_sources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_config_sources_host_gyp
+
+# Alias gyp target name.
+.PHONY: config_sources
+config_sources: third_party_yasm_config_sources_host_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/yasm/generate_files.host.darwin-x86.mk b/third_party/yasm/generate_files.host.darwin-x86.mk
index f008940..6d39d83 100644
--- a/third_party/yasm/generate_files.host.darwin-x86.mk
+++ b/third_party/yasm/generate_files.host.darwin-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/generate_files.host.darwin-x86_64.mk b/third_party/yasm/generate_files.host.darwin-x86_64.mk
new file mode 100644
index 0000000..c5f6d50
--- /dev/null
+++ b/third_party/yasm/generate_files.host.darwin-x86_64.mk
@@ -0,0 +1,221 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_yasm_generate_files_host_gyp
+LOCAL_MODULE_STEM := generate_files
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/genperf \
+	$(gyp_shared_intermediate_dir)/genversion
+
+### Rules for action "generate_x86_insn":
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/x86/gen_x86_insn.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Running source/patched-yasm/modules/arch/x86/gen_x86_insn.py ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; python source/patched-yasm/modules/arch/x86/gen_x86_insn.py "$(gyp_shared_intermediate_dir)/third_party/yasm"
+
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c ;
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c ;
+
+### Rules for action "generate_version":
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: $(gyp_shared_intermediate_dir)/genversion $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm version file: $(gyp_shared_intermediate_dir)/third_party/yasm/version.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genversion" "$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac"
+
+
+
+
+### Generated for rule "third_party_yasm_yasm_gyp_generate_files_host_generate_gperf":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/genperf'], 'extension': 'gperf', 'process_outputs_as_sources': '0', 'outputs': ['$(gyp_shared_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'rule_name': 'generate_gperf', 'rule_sources': ['source/patched-yasm/modules/arch/x86/x86cpu.gperf', 'source/patched-yasm/modules/arch/x86/x86regtmod.gperf'], 'action': ['$(gyp_shared_intermediate_dir)/genperf', '$(RULE_SOURCES)', '$(gyp_shared_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'message': 'yasm genperf for $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/x86/x86cpu.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" source/patched-yasm/modules/arch/x86/x86cpu.gperf "$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c"
+
+.PHONY: third_party_yasm_generate_files_host_gyp_rule_trigger
+third_party_yasm_generate_files_host_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c
+
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/x86/x86regtmod.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" source/patched-yasm/modules/arch/x86/x86regtmod.gperf "$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c"
+
+.PHONY: third_party_yasm_generate_files_host_gyp_rule_trigger
+third_party_yasm_generate_files_host_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	third_party_yasm_generate_files_host_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_generate_files_host_gyp
+
+# Alias gyp target name.
+.PHONY: generate_files
+generate_files: third_party_yasm_generate_files_host_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/yasm/generate_files.host.linux-x86.mk b/third_party/yasm/generate_files.host.linux-x86.mk
index f008940..6d39d83 100644
--- a/third_party/yasm/generate_files.host.linux-x86.mk
+++ b/third_party/yasm/generate_files.host.linux-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/generate_files.host.linux-x86_64.mk b/third_party/yasm/generate_files.host.linux-x86_64.mk
new file mode 100644
index 0000000..c5f6d50
--- /dev/null
+++ b/third_party/yasm/generate_files.host.linux-x86_64.mk
@@ -0,0 +1,221 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := third_party_yasm_generate_files_host_gyp
+LOCAL_MODULE_STEM := generate_files
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(gyp_shared_intermediate_dir)/genperf \
+	$(gyp_shared_intermediate_dir)/genversion
+
+### Rules for action "generate_x86_insn":
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/x86/gen_x86_insn.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Running source/patched-yasm/modules/arch/x86/gen_x86_insn.py ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; python source/patched-yasm/modules/arch/x86/gen_x86_insn.py "$(gyp_shared_intermediate_dir)/third_party/yasm"
+
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c ;
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c ;
+
+### Rules for action "generate_version":
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac: $(gyp_shared_intermediate_dir)/genversion $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm version file: $(gyp_shared_intermediate_dir)/third_party/yasm/version.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genversion" "$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac"
+
+
+
+
+### Generated for rule "third_party_yasm_yasm_gyp_generate_files_host_generate_gperf":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/genperf'], 'extension': 'gperf', 'process_outputs_as_sources': '0', 'outputs': ['$(gyp_shared_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'rule_name': 'generate_gperf', 'rule_sources': ['source/patched-yasm/modules/arch/x86/x86cpu.gperf', 'source/patched-yasm/modules/arch/x86/x86regtmod.gperf'], 'action': ['$(gyp_shared_intermediate_dir)/genperf', '$(RULE_SOURCES)', '$(gyp_shared_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'message': 'yasm genperf for $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/x86/x86cpu.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" source/patched-yasm/modules/arch/x86/x86cpu.gperf "$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c"
+
+.PHONY: third_party_yasm_generate_files_host_gyp_rule_trigger
+third_party_yasm_generate_files_host_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c
+
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/x86/x86regtmod.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" source/patched-yasm/modules/arch/x86/x86regtmod.gperf "$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c"
+
+.PHONY: third_party_yasm_generate_files_host_gyp_rule_trigger
+third_party_yasm_generate_files_host_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86insns.c \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c \
+	$(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	third_party_yasm_generate_files_host_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release :=
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_generate_files_host_gyp
+
+# Alias gyp target name.
+.PHONY: generate_files
+generate_files: third_party_yasm_generate_files_host_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/third_party/yasm/genmacro.host.darwin-x86.mk b/third_party/yasm/genmacro.host.darwin-x86.mk
index 1f12f1b..f98ba97 100644
--- a/third_party/yasm/genmacro.host.darwin-x86.mk
+++ b/third_party/yasm/genmacro.host.darwin-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genmacro.host.darwin-x86_64.mk b/third_party/yasm/genmacro.host.darwin-x86_64.mk
new file mode 100644
index 0000000..e110a30
--- /dev/null
+++ b/third_party/yasm/genmacro.host.darwin-x86_64.mk
@@ -0,0 +1,185 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genmacro_host_gyp
+LOCAL_MODULE_STEM := genmacro
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/tools/genmacro/genmacro.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genmacro_host_gyp
+
+# Alias gyp target name.
+.PHONY: genmacro
+genmacro: third_party_yasm_genmacro_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genmacro.host.linux-x86.mk b/third_party/yasm/genmacro.host.linux-x86.mk
index 1374cc7..9d6d669 100644
--- a/third_party/yasm/genmacro.host.linux-x86.mk
+++ b/third_party/yasm/genmacro.host.linux-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genmacro.host.linux-x86_64.mk b/third_party/yasm/genmacro.host.linux-x86_64.mk
new file mode 100644
index 0000000..3c903f2
--- /dev/null
+++ b/third_party/yasm/genmacro.host.linux-x86_64.mk
@@ -0,0 +1,189 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genmacro_host_gyp
+LOCAL_MODULE_STEM := genmacro
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/tools/genmacro/genmacro.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genmacro_host_gyp
+
+# Alias gyp target name.
+.PHONY: genmacro
+genmacro: third_party_yasm_genmacro_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genmodule.host.darwin-x86.mk b/third_party/yasm/genmodule.host.darwin-x86.mk
index 02aba4f..f1111d4 100644
--- a/third_party/yasm/genmodule.host.darwin-x86.mk
+++ b/third_party/yasm/genmodule.host.darwin-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genmodule.host.darwin-x86_64.mk b/third_party/yasm/genmodule.host.darwin-x86_64.mk
new file mode 100644
index 0000000..a2d2453
--- /dev/null
+++ b/third_party/yasm/genmodule.host.darwin-x86_64.mk
@@ -0,0 +1,185 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genmodule_host_gyp
+LOCAL_MODULE_STEM := genmodule
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/libyasm/genmodule.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genmodule_host_gyp
+
+# Alias gyp target name.
+.PHONY: genmodule
+genmodule: third_party_yasm_genmodule_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genmodule.host.linux-x86.mk b/third_party/yasm/genmodule.host.linux-x86.mk
index 6c8f901..ee0555c 100644
--- a/third_party/yasm/genmodule.host.linux-x86.mk
+++ b/third_party/yasm/genmodule.host.linux-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genmodule.host.linux-x86_64.mk b/third_party/yasm/genmodule.host.linux-x86_64.mk
new file mode 100644
index 0000000..6c190fc
--- /dev/null
+++ b/third_party/yasm/genmodule.host.linux-x86_64.mk
@@ -0,0 +1,189 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genmodule_host_gyp
+LOCAL_MODULE_STEM := genmodule
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/libyasm/genmodule.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genmodule_host_gyp
+
+# Alias gyp target name.
+.PHONY: genmodule
+genmodule: third_party_yasm_genmodule_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genperf.host.darwin-x86.mk b/third_party/yasm/genperf.host.darwin-x86.mk
index 71183c3..327d053 100644
--- a/third_party/yasm/genperf.host.darwin-x86.mk
+++ b/third_party/yasm/genperf.host.darwin-x86.mk
@@ -68,6 +68,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -125,6 +126,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genperf.host.darwin-x86_64.mk b/third_party/yasm/genperf.host.darwin-x86_64.mk
new file mode 100644
index 0000000..186f6e0
--- /dev/null
+++ b/third_party/yasm/genperf.host.darwin-x86_64.mk
@@ -0,0 +1,188 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genperf_host_gyp
+LOCAL_MODULE_STEM := genperf
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_yasm_genperf_libs_host_gyp,true)/third_party_yasm_genperf_libs_host_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/tools/genperf/genperf.c \
+	third_party/yasm/source/patched-yasm/tools/genperf/perfect.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_yasm_genperf_libs_host_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genperf_host_gyp
+
+# Alias gyp target name.
+.PHONY: genperf
+genperf: third_party_yasm_genperf_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genperf.host.linux-x86.mk b/third_party/yasm/genperf.host.linux-x86.mk
index 4350127..3bd167f 100644
--- a/third_party/yasm/genperf.host.linux-x86.mk
+++ b/third_party/yasm/genperf.host.linux-x86.mk
@@ -68,6 +68,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -125,6 +126,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genperf.host.linux-x86_64.mk b/third_party/yasm/genperf.host.linux-x86_64.mk
new file mode 100644
index 0000000..e560f45
--- /dev/null
+++ b/third_party/yasm/genperf.host.linux-x86_64.mk
@@ -0,0 +1,192 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genperf_host_gyp
+LOCAL_MODULE_STEM := genperf
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_yasm_genperf_libs_host_gyp,true)/third_party_yasm_genperf_libs_host_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/tools/genperf/genperf.c \
+	third_party/yasm/source/patched-yasm/tools/genperf/perfect.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_yasm_genperf_libs_host_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genperf_host_gyp
+
+# Alias gyp target name.
+.PHONY: genperf
+genperf: third_party_yasm_genperf_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genperf_libs.host.darwin-x86.mk b/third_party/yasm/genperf_libs.host.darwin-x86.mk
index 935b4e4..625198d 100644
--- a/third_party/yasm/genperf_libs.host.darwin-x86.mk
+++ b/third_party/yasm/genperf_libs.host.darwin-x86.mk
@@ -70,6 +70,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -130,6 +131,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genperf_libs.host.darwin-x86_64.mk b/third_party/yasm/genperf_libs.host.darwin-x86_64.mk
new file mode 100644
index 0000000..0628916
--- /dev/null
+++ b/third_party/yasm/genperf_libs.host.darwin-x86_64.mk
@@ -0,0 +1,191 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_yasm_genperf_libs_host_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/libyasm/phash.c \
+	third_party/yasm/source/patched-yasm/libyasm/xmalloc.c \
+	third_party/yasm/source/patched-yasm/libyasm/xstrdup.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genperf_libs_host_gyp
+
+# Alias gyp target name.
+.PHONY: genperf_libs
+genperf_libs: third_party_yasm_genperf_libs_host_gyp
+
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/third_party/yasm/genperf_libs.host.linux-x86.mk b/third_party/yasm/genperf_libs.host.linux-x86.mk
index bde8362..bd2391d 100644
--- a/third_party/yasm/genperf_libs.host.linux-x86.mk
+++ b/third_party/yasm/genperf_libs.host.linux-x86.mk
@@ -70,6 +70,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -130,6 +131,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genperf_libs.host.linux-x86_64.mk b/third_party/yasm/genperf_libs.host.linux-x86_64.mk
new file mode 100644
index 0000000..d01e37a
--- /dev/null
+++ b/third_party/yasm/genperf_libs.host.linux-x86_64.mk
@@ -0,0 +1,195 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_yasm_genperf_libs_host_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/libyasm/phash.c \
+	third_party/yasm/source/patched-yasm/libyasm/xmalloc.c \
+	third_party/yasm/source/patched-yasm/libyasm/xstrdup.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genperf_libs_host_gyp
+
+# Alias gyp target name.
+.PHONY: genperf_libs
+genperf_libs: third_party_yasm_genperf_libs_host_gyp
+
+include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/third_party/yasm/genstring.host.darwin-x86.mk b/third_party/yasm/genstring.host.darwin-x86.mk
index 6faa62c..70e3caf 100644
--- a/third_party/yasm/genstring.host.darwin-x86.mk
+++ b/third_party/yasm/genstring.host.darwin-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genstring.host.darwin-x86_64.mk b/third_party/yasm/genstring.host.darwin-x86_64.mk
new file mode 100644
index 0000000..b107c6b
--- /dev/null
+++ b/third_party/yasm/genstring.host.darwin-x86_64.mk
@@ -0,0 +1,185 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genstring_host_gyp
+LOCAL_MODULE_STEM := genstring
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/genstring.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genstring_host_gyp
+
+# Alias gyp target name.
+.PHONY: genstring
+genstring: third_party_yasm_genstring_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genstring.host.linux-x86.mk b/third_party/yasm/genstring.host.linux-x86.mk
index 2eb1273..36900f2 100644
--- a/third_party/yasm/genstring.host.linux-x86.mk
+++ b/third_party/yasm/genstring.host.linux-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genstring.host.linux-x86_64.mk b/third_party/yasm/genstring.host.linux-x86_64.mk
new file mode 100644
index 0000000..fcb1091
--- /dev/null
+++ b/third_party/yasm/genstring.host.linux-x86_64.mk
@@ -0,0 +1,189 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genstring_host_gyp
+LOCAL_MODULE_STEM := genstring
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/genstring.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genstring_host_gyp
+
+# Alias gyp target name.
+.PHONY: genstring
+genstring: third_party_yasm_genstring_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genversion.host.darwin-x86.mk b/third_party/yasm/genversion.host.darwin-x86.mk
index 923de7c..4a923cd 100644
--- a/third_party/yasm/genversion.host.darwin-x86.mk
+++ b/third_party/yasm/genversion.host.darwin-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genversion.host.darwin-x86_64.mk b/third_party/yasm/genversion.host.darwin-x86_64.mk
new file mode 100644
index 0000000..7a48afe
--- /dev/null
+++ b/third_party/yasm/genversion.host.darwin-x86_64.mk
@@ -0,0 +1,185 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genversion_host_gyp
+LOCAL_MODULE_STEM := genversion
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/genversion.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genversion_host_gyp
+
+# Alias gyp target name.
+.PHONY: genversion
+genversion: third_party_yasm_genversion_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/genversion.host.linux-x86.mk b/third_party/yasm/genversion.host.linux-x86.mk
index 9594901..e0c1344 100644
--- a/third_party/yasm/genversion.host.linux-x86.mk
+++ b/third_party/yasm/genversion.host.linux-x86.mk
@@ -66,6 +66,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -123,6 +124,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/genversion.host.linux-x86_64.mk b/third_party/yasm/genversion.host.linux-x86_64.mk
new file mode 100644
index 0000000..09d18dd
--- /dev/null
+++ b/third_party/yasm/genversion.host.linux-x86_64.mk
@@ -0,0 +1,189 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_genversion_host_gyp
+LOCAL_MODULE_STEM := genversion
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/genversion.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_genversion_host_gyp
+
+# Alias gyp target name.
+.PHONY: genversion
+genversion: third_party_yasm_genversion_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/re2c.host.darwin-x86.mk b/third_party/yasm/re2c.host.darwin-x86.mk
index d119cc2..0e27b78 100644
--- a/third_party/yasm/re2c.host.darwin-x86.mk
+++ b/third_party/yasm/re2c.host.darwin-x86.mk
@@ -74,6 +74,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -131,6 +132,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/re2c.host.darwin-x86_64.mk b/third_party/yasm/re2c.host.darwin-x86_64.mk
new file mode 100644
index 0000000..b7ad5f7
--- /dev/null
+++ b/third_party/yasm/re2c.host.darwin-x86_64.mk
@@ -0,0 +1,193 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_re2c_host_gyp
+LOCAL_MODULE_STEM := re2c
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/tools/re2c/main.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/code.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/dfa.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/parser.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/actions.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/scanner.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/mbo_getopt.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/substr.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/translate.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_re2c_host_gyp
+
+# Alias gyp target name.
+.PHONY: re2c
+re2c: third_party_yasm_re2c_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/re2c.host.linux-x86.mk b/third_party/yasm/re2c.host.linux-x86.mk
index 1e3ec13..6a32e48 100644
--- a/third_party/yasm/re2c.host.linux-x86.mk
+++ b/third_party/yasm/re2c.host.linux-x86.mk
@@ -74,6 +74,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -131,6 +132,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/re2c.host.linux-x86_64.mk b/third_party/yasm/re2c.host.linux-x86_64.mk
new file mode 100644
index 0000000..9fff171
--- /dev/null
+++ b/third_party/yasm/re2c.host.linux-x86_64.mk
@@ -0,0 +1,197 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_re2c_host_gyp
+LOCAL_MODULE_STEM := re2c
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/tools/re2c/main.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/code.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/dfa.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/parser.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/actions.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/scanner.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/mbo_getopt.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/substr.c \
+	third_party/yasm/source/patched-yasm/tools/re2c/translate.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_re2c_host_gyp
+
+# Alias gyp target name.
+.PHONY: re2c
+re2c: third_party_yasm_re2c_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/yasm.host.darwin-x86.mk b/third_party/yasm/yasm.host.darwin-x86.mk
index 59947c8..bb18f72 100644
--- a/third_party/yasm/yasm.host.darwin-x86.mk
+++ b/third_party/yasm/yasm.host.darwin-x86.mk
@@ -283,6 +283,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -345,6 +346,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/yasm.host.darwin-x86_64.mk b/third_party/yasm/yasm.host.darwin-x86_64.mk
new file mode 100644
index 0000000..a81270a
--- /dev/null
+++ b/third_party/yasm/yasm.host.darwin-x86_64.mk
@@ -0,0 +1,410 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_yasm_host_gyp
+LOCAL_MODULE_STEM := yasm
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp \
+	$(gyp_shared_intermediate_dir)/genmacro \
+	$(gyp_shared_intermediate_dir)/genmodule \
+	$(gyp_shared_intermediate_dir)/genperf \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_yasm_genperf_libs_host_gyp,true)/third_party_yasm_genperf_libs_host_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_yasm_generate_files_host_gyp,true)/generate_files.stamp \
+	$(gyp_shared_intermediate_dir)/genstring \
+	$(gyp_shared_intermediate_dir)/re2c
+
+### Rules for action "generate_nasm_macros":
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: $(gyp_shared_intermediate_dir)/genmacro $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-std.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for source/patched-yasm/modules/parsers/nasm/nasm-std.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c" nasm_standard_mac source/patched-yasm/modules/parsers/nasm/nasm-std.mac
+
+
+### Rules for action "generate_nasm_version":
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: $(gyp_shared_intermediate_dir)/genmacro $(gyp_shared_intermediate_dir)/third_party/yasm/version.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for $(gyp_shared_intermediate_dir)/third_party/yasm/version.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c" nasm_version_mac "$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac"
+
+
+### Rules for action "generate_win64_gas":
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: $(gyp_shared_intermediate_dir)/genmacro $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/objfmts/coff/win64-gas.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for source/patched-yasm/modules/objfmts/coff/win64-gas.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c" win64_gas_stdmac source/patched-yasm/modules/objfmts/coff/win64-gas.mac
+
+
+### Rules for action "generate_win64_nasm":
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: $(gyp_shared_intermediate_dir)/genmacro $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/objfmts/coff/win64-nasm.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for source/patched-yasm/modules/objfmts/coff/win64-nasm.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c" win64_nasm_stdmac source/patched-yasm/modules/objfmts/coff/win64-nasm.mac
+
+
+### Rules for action "generate_license":
+$(gyp_intermediate_dir)/third_party/yasm/license.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/license.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/license.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/license.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/license.c: $(gyp_shared_intermediate_dir)/genstring $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/COPYING $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm embeddable license ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genstring" license_msg "$(gyp_intermediate_dir)/third_party/yasm/license.c" source/patched-yasm/COPYING
+
+
+### Rules for action "generate_lc3b_token":
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: $(gyp_shared_intermediate_dir)/re2c $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/lc3b/lc3bid.re $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm tokens for lc3b ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/re2c" -s -o "$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c" source/patched-yasm/modules/arch/lc3b/lc3bid.re
+
+
+### Rules for action "generate_module":
+$(gyp_intermediate_dir)/third_party/yasm/module.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/module.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/module.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/module.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/module.c: $(gyp_shared_intermediate_dir)/genmodule $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/libyasm/module.in $(LOCAL_PATH)/third_party/yasm/source/config/android/Makefile $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm module information ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmodule" source/patched-yasm/libyasm/module.in source/config/android/Makefile "$(gyp_intermediate_dir)/third_party/yasm/module.c"
+
+
+
+
+### Generated for rule "third_party_yasm_yasm_gyp_yasm_host_generate_gperf":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/genperf'], 'extension': 'gperf', 'process_outputs_as_sources': '0', 'outputs': ['$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'rule_name': 'generate_gperf', 'rule_sources': ['$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf', '$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf'], 'action': ['$(gyp_shared_intermediate_dir)/genperf', '$(RULE_SOURCES)', '$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'message': 'yasm gperf for $(RULE_SOURCES)'}":
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" "$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf" "$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c"
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c
+
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" "$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf" "$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c"
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c
+
+
+### Generated for rule "third_party_yasm_yasm_gyp_yasm_host_generate_re2c":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/re2c'], 'extension': 're', 'process_outputs_as_sources': '1', 'outputs': ['$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'rule_name': 'generate_re2c', 'rule_sources': ['source/patched-yasm/modules/parsers/gas/gas-token.re', 'source/patched-yasm/modules/parsers/nasm/nasm-token.re'], 'action': ['$(gyp_shared_intermediate_dir)/re2c', '-b', '-o', '$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c', '$(RULE_SOURCES)'], 'message': 'yasm re2c for $(RULE_SOURCES)'}":
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-token.re $(gyp_shared_intermediate_dir)/re2c $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/re2c" -b -o "$(gyp_intermediate_dir)/third_party/yasm/gas-token.c" source/patched-yasm/modules/parsers/gas/gas-token.re
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/gas-token.c
+
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-token.re $(gyp_shared_intermediate_dir)/re2c $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/re2c" -b -o "$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c" source/patched-yasm/modules/parsers/nasm/nasm-token.re
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/nasm-token.c
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c \
+	$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c \
+	$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c \
+	$(gyp_intermediate_dir)/third_party/yasm/license.c \
+	$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c \
+	$(gyp_intermediate_dir)/third_party/yasm/module.c \
+	$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c \
+	$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c \
+	$(gyp_intermediate_dir)/third_party/yasm/gas-token.c \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+$(gyp_intermediate_dir)/x86cpu.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/x86regtmod.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c \
+	$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c \
+	$(gyp_intermediate_dir)/third_party/yasm/module.c \
+	$(gyp_intermediate_dir)/third_party/yasm/gas-token.c \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c \
+	$(gyp_intermediate_dir)/x86cpu.c \
+	$(gyp_intermediate_dir)/x86regtmod.c \
+	third_party_yasm_yasm_host_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/third_party/yasm
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/frontends/yasm/yasm-options.c \
+	third_party/yasm/source/patched-yasm/frontends/yasm/yasm.c \
+	third_party/yasm/source/patched-yasm/libyasm/assocdat.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-align.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-data.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-incbin.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-org.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-reserve.c \
+	third_party/yasm/source/patched-yasm/libyasm/bitvect.c \
+	third_party/yasm/source/patched-yasm/libyasm/bytecode.c \
+	third_party/yasm/source/patched-yasm/libyasm/errwarn.c \
+	third_party/yasm/source/patched-yasm/libyasm/expr.c \
+	third_party/yasm/source/patched-yasm/libyasm/file.c \
+	third_party/yasm/source/patched-yasm/libyasm/floatnum.c \
+	third_party/yasm/source/patched-yasm/libyasm/hamt.c \
+	third_party/yasm/source/patched-yasm/libyasm/insn.c \
+	third_party/yasm/source/patched-yasm/libyasm/intnum.c \
+	third_party/yasm/source/patched-yasm/libyasm/inttree.c \
+	third_party/yasm/source/patched-yasm/libyasm/linemap.c \
+	third_party/yasm/source/patched-yasm/libyasm/md5.c \
+	third_party/yasm/source/patched-yasm/libyasm/mergesort.c \
+	third_party/yasm/source/patched-yasm/libyasm/section.c \
+	third_party/yasm/source/patched-yasm/libyasm/strcasecmp.c \
+	third_party/yasm/source/patched-yasm/libyasm/strsep.c \
+	third_party/yasm/source/patched-yasm/libyasm/symrec.c \
+	third_party/yasm/source/patched-yasm/libyasm/valparam.c \
+	third_party/yasm/source/patched-yasm/libyasm/value.c \
+	third_party/yasm/source/patched-yasm/modules/arch/lc3b/lc3barch.c \
+	third_party/yasm/source/patched-yasm/modules/arch/lc3b/lc3bbc.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86arch.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86bc.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86expr.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86id.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/codeview/cv-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/codeview/cv-symline.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/codeview/cv-type.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-aranges.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-info.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-line.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/null/null-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/stabs/stabs-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/listfmts/nasm/nasm-listfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/bin/bin-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/coff/coff-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/coff/win64-except.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/dbg/dbg-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf-x86-amd64.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf-x86-x86.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/macho/macho-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/rdf/rdf-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/xdf/xdf-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-parse.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-parse-intel.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-parser.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-parse.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-parser.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/cpp/cpp-preproc.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasm-eval.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasm-pp.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasm-preproc.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasmlib.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/raw/raw-preproc.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm \
+	$(gyp_shared_intermediate_dir)/third_party/yasm \
+	$(gyp_intermediate_dir)/third_party/yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm \
+	$(gyp_shared_intermediate_dir)/third_party/yasm \
+	$(gyp_intermediate_dir)/third_party/yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_yasm_genperf_libs_host_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_yasm_host_gyp
+
+# Alias gyp target name.
+.PHONY: yasm
+yasm: third_party_yasm_yasm_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/yasm/yasm.host.linux-x86.mk b/third_party/yasm/yasm.host.linux-x86.mk
index 1c241f3..e0c20d6 100644
--- a/third_party/yasm/yasm.host.linux-x86.mk
+++ b/third_party/yasm/yasm.host.linux-x86.mk
@@ -283,6 +283,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
 	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
 	'-D_DEBUG'
@@ -345,6 +346,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DHAVE_CONFIG_H' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DNDEBUG' \
 	'-DNVALGRIND' \
 	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
diff --git a/third_party/yasm/yasm.host.linux-x86_64.mk b/third_party/yasm/yasm.host.linux-x86_64.mk
new file mode 100644
index 0000000..fdaa725
--- /dev/null
+++ b/third_party/yasm/yasm.host.linux-x86_64.mk
@@ -0,0 +1,414 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := EXECUTABLES
+LOCAL_MODULE := third_party_yasm_yasm_host_gyp
+LOCAL_MODULE_STEM := yasm
+LOCAL_MODULE_SUFFIX := 
+LOCAL_MODULE_TAGS := optional
+LOCAL_IS_HOST_MODULE := true
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_yasm_config_sources_host_gyp,true)/config_sources.stamp \
+	$(gyp_shared_intermediate_dir)/genmacro \
+	$(gyp_shared_intermediate_dir)/genmodule \
+	$(gyp_shared_intermediate_dir)/genperf \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,third_party_yasm_genperf_libs_host_gyp,true)/third_party_yasm_genperf_libs_host_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_yasm_generate_files_host_gyp,true)/generate_files.stamp \
+	$(gyp_shared_intermediate_dir)/genstring \
+	$(gyp_shared_intermediate_dir)/re2c
+
+### Rules for action "generate_nasm_macros":
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c: $(gyp_shared_intermediate_dir)/genmacro $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-std.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for source/patched-yasm/modules/parsers/nasm/nasm-std.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c" nasm_standard_mac source/patched-yasm/modules/parsers/nasm/nasm-std.mac
+
+
+### Rules for action "generate_nasm_version":
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c: $(gyp_shared_intermediate_dir)/genmacro $(gyp_shared_intermediate_dir)/third_party/yasm/version.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for $(gyp_shared_intermediate_dir)/third_party/yasm/version.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c" nasm_version_mac "$(gyp_shared_intermediate_dir)/third_party/yasm/version.mac"
+
+
+### Rules for action "generate_win64_gas":
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c: $(gyp_shared_intermediate_dir)/genmacro $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/objfmts/coff/win64-gas.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for source/patched-yasm/modules/objfmts/coff/win64-gas.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c" win64_gas_stdmac source/patched-yasm/modules/objfmts/coff/win64-gas.mac
+
+
+### Rules for action "generate_win64_nasm":
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c: $(gyp_shared_intermediate_dir)/genmacro $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/objfmts/coff/win64-nasm.mac $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: yasm genmacro for source/patched-yasm/modules/objfmts/coff/win64-nasm.mac ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmacro" "$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c" win64_nasm_stdmac source/patched-yasm/modules/objfmts/coff/win64-nasm.mac
+
+
+### Rules for action "generate_license":
+$(gyp_intermediate_dir)/third_party/yasm/license.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/license.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/license.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/license.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/license.c: $(gyp_shared_intermediate_dir)/genstring $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/COPYING $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm embeddable license ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genstring" license_msg "$(gyp_intermediate_dir)/third_party/yasm/license.c" source/patched-yasm/COPYING
+
+
+### Rules for action "generate_lc3b_token":
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c: $(gyp_shared_intermediate_dir)/re2c $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/arch/lc3b/lc3bid.re $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm tokens for lc3b ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/re2c" -s -o "$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c" source/patched-yasm/modules/arch/lc3b/lc3bid.re
+
+
+### Rules for action "generate_module":
+$(gyp_intermediate_dir)/third_party/yasm/module.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/module.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/module.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/module.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/module.c: $(gyp_shared_intermediate_dir)/genmodule $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/libyasm/module.in $(LOCAL_PATH)/third_party/yasm/source/config/android/Makefile $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating yasm module information ($@)"
+	$(hide)cd $(gyp_local_path)/third_party/yasm; mkdir -p $(gyp_intermediate_dir)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genmodule" source/patched-yasm/libyasm/module.in source/config/android/Makefile "$(gyp_intermediate_dir)/third_party/yasm/module.c"
+
+
+
+
+### Generated for rule "third_party_yasm_yasm_gyp_yasm_host_generate_gperf":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/genperf'], 'extension': 'gperf', 'process_outputs_as_sources': '0', 'outputs': ['$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'rule_name': 'generate_gperf', 'rule_sources': ['$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf', '$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf'], 'action': ['$(gyp_shared_intermediate_dir)/genperf', '$(RULE_SOURCES)', '$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'message': 'yasm gperf for $(RULE_SOURCES)'}":
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" "$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_nasm.gperf" "$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c"
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c
+
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf $(gyp_shared_intermediate_dir)/genperf $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/genperf" "$(gyp_shared_intermediate_dir)/third_party/yasm/x86insn_gas.gperf" "$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c"
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c
+
+
+### Generated for rule "third_party_yasm_yasm_gyp_yasm_host_generate_re2c":
+# "{'inputs': ['$(gyp_shared_intermediate_dir)/re2c'], 'extension': 're', 'process_outputs_as_sources': '1', 'outputs': ['$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c'], 'rule_name': 'generate_re2c', 'rule_sources': ['source/patched-yasm/modules/parsers/gas/gas-token.re', 'source/patched-yasm/modules/parsers/nasm/nasm-token.re'], 'action': ['$(gyp_shared_intermediate_dir)/re2c', '-b', '-o', '$(gyp_intermediate_dir)/third_party/yasm/%(INPUT_ROOT)s.c', '$(RULE_SOURCES)'], 'message': 'yasm re2c for $(RULE_SOURCES)'}":
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/gas-token.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-token.re $(gyp_shared_intermediate_dir)/re2c $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/re2c" -b -o "$(gyp_intermediate_dir)/third_party/yasm/gas-token.c" source/patched-yasm/modules/parsers/gas/gas-token.re
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/gas-token.c
+
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: gyp_local_path := $(LOCAL_PATH)
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c: $(LOCAL_PATH)/third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-token.re $(gyp_shared_intermediate_dir)/re2c $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_intermediate_dir)/third_party/yasm; cd $(gyp_local_path)/third_party/yasm; "$(gyp_shared_intermediate_dir)/re2c" -b -o "$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c" source/patched-yasm/modules/parsers/nasm/nasm-token.re
+
+.PHONY: third_party_yasm_yasm_host_gyp_rule_trigger
+third_party_yasm_yasm_host_gyp_rule_trigger: $(gyp_intermediate_dir)/third_party/yasm/nasm-token.c
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-version.c \
+	$(gyp_intermediate_dir)/third_party/yasm/win64-gas.c \
+	$(gyp_intermediate_dir)/third_party/yasm/win64-nasm.c \
+	$(gyp_intermediate_dir)/third_party/yasm/license.c \
+	$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c \
+	$(gyp_intermediate_dir)/third_party/yasm/module.c \
+	$(gyp_intermediate_dir)/third_party/yasm/x86insn_nasm.c \
+	$(gyp_intermediate_dir)/third_party/yasm/x86insn_gas.c \
+	$(gyp_intermediate_dir)/third_party/yasm/gas-token.c \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+$(gyp_intermediate_dir)/x86cpu.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86cpu.c
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/x86regtmod.c: $(gyp_shared_intermediate_dir)/third_party/yasm/x86regtmod.c
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-macros.c \
+	$(gyp_intermediate_dir)/third_party/yasm/lc3bid.c \
+	$(gyp_intermediate_dir)/third_party/yasm/module.c \
+	$(gyp_intermediate_dir)/third_party/yasm/gas-token.c \
+	$(gyp_intermediate_dir)/third_party/yasm/nasm-token.c \
+	$(gyp_intermediate_dir)/x86cpu.c \
+	$(gyp_intermediate_dir)/x86regtmod.c \
+	third_party_yasm_yasm_host_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/third_party/yasm
+
+LOCAL_SRC_FILES := \
+	third_party/yasm/source/patched-yasm/frontends/yasm/yasm-options.c \
+	third_party/yasm/source/patched-yasm/frontends/yasm/yasm.c \
+	third_party/yasm/source/patched-yasm/libyasm/assocdat.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-align.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-data.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-incbin.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-org.c \
+	third_party/yasm/source/patched-yasm/libyasm/bc-reserve.c \
+	third_party/yasm/source/patched-yasm/libyasm/bitvect.c \
+	third_party/yasm/source/patched-yasm/libyasm/bytecode.c \
+	third_party/yasm/source/patched-yasm/libyasm/errwarn.c \
+	third_party/yasm/source/patched-yasm/libyasm/expr.c \
+	third_party/yasm/source/patched-yasm/libyasm/file.c \
+	third_party/yasm/source/patched-yasm/libyasm/floatnum.c \
+	third_party/yasm/source/patched-yasm/libyasm/hamt.c \
+	third_party/yasm/source/patched-yasm/libyasm/insn.c \
+	third_party/yasm/source/patched-yasm/libyasm/intnum.c \
+	third_party/yasm/source/patched-yasm/libyasm/inttree.c \
+	third_party/yasm/source/patched-yasm/libyasm/linemap.c \
+	third_party/yasm/source/patched-yasm/libyasm/md5.c \
+	third_party/yasm/source/patched-yasm/libyasm/mergesort.c \
+	third_party/yasm/source/patched-yasm/libyasm/section.c \
+	third_party/yasm/source/patched-yasm/libyasm/strcasecmp.c \
+	third_party/yasm/source/patched-yasm/libyasm/strsep.c \
+	third_party/yasm/source/patched-yasm/libyasm/symrec.c \
+	third_party/yasm/source/patched-yasm/libyasm/valparam.c \
+	third_party/yasm/source/patched-yasm/libyasm/value.c \
+	third_party/yasm/source/patched-yasm/modules/arch/lc3b/lc3barch.c \
+	third_party/yasm/source/patched-yasm/modules/arch/lc3b/lc3bbc.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86arch.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86bc.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86expr.c \
+	third_party/yasm/source/patched-yasm/modules/arch/x86/x86id.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/codeview/cv-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/codeview/cv-symline.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/codeview/cv-type.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-aranges.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-info.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/dwarf2-line.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/null/null-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/dbgfmts/stabs/stabs-dbgfmt.c \
+	third_party/yasm/source/patched-yasm/modules/listfmts/nasm/nasm-listfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/bin/bin-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/coff/coff-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/coff/win64-except.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/dbg/dbg-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf-x86-amd64.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf-x86-x86.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/elf/elf.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/macho/macho-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/rdf/rdf-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/objfmts/xdf/xdf-objfmt.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-parse.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-parse-intel.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/gas/gas-parser.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-parse.c \
+	third_party/yasm/source/patched-yasm/modules/parsers/nasm/nasm-parser.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/cpp/cpp-preproc.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasm-eval.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasm-pp.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasm-preproc.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/nasm/nasmlib.c \
+	third_party/yasm/source/patched-yasm/modules/preprocs/raw/raw-preproc.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm \
+	$(gyp_shared_intermediate_dir)/third_party/yasm \
+	$(gyp_intermediate_dir)/third_party/yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-pthread \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-std=gnu99 \
+	-ansi \
+	-pedantic \
+	-Wno-format \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DHAVE_CONFIG_H' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/yasm/source/config/android \
+	$(LOCAL_PATH)/third_party/yasm/source/patched-yasm \
+	$(gyp_shared_intermediate_dir)/third_party/yasm \
+	$(gyp_intermediate_dir)/third_party/yasm
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+# Undefine ANDROID for host modules
+LOCAL_CFLAGS += -UANDROID
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-pthread \
+	-fPIC
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	third_party_yasm_genperf_libs_host_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES :=
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_yasm_yasm_host_gyp
+
+# Alias gyp target name.
+.PHONY: yasm
+yasm: third_party_yasm_yasm_host_gyp
+
+LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)
+include $(BUILD_HOST_EXECUTABLE)
diff --git a/third_party/zlib/google/DEPS b/third_party/zlib/google/DEPS
deleted file mode 100644
index 6a2f02e..0000000
--- a/third_party/zlib/google/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+net/base",
-]
diff --git a/third_party/zlib/google/zip.cc b/third_party/zlib/google/zip.cc
index 52fc694..5fbfca9 100644
--- a/third_party/zlib/google/zip.cc
+++ b/third_party/zlib/google/zip.cc
@@ -8,12 +8,11 @@
 #include <vector>
 
 #include "base/bind.h"
-#include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/files/file_enumerator.h"
 #include "base/logging.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
-#include "net/base/file_stream.h"
 #include "third_party/zlib/google/zip_internal.h"
 #include "third_party/zlib/google/zip_reader.h"
 
@@ -60,18 +59,16 @@
 }
 
 bool AddFileToZip(zipFile zip_file, const base::FilePath& src_dir) {
-  net::FileStream stream(NULL);
-  int flags = base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ;
-  if (stream.OpenSync(src_dir, flags) != 0) {
-    DLOG(ERROR) << "Could not open stream for path "
-                << src_dir.value();
+  base::File file(src_dir, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!file.IsValid()) {
+    DLOG(ERROR) << "Could not open file for path " << src_dir.value();
     return false;
   }
 
   int num_bytes;
   char buf[zip::internal::kZipBufSize];
   do {
-    num_bytes = stream.ReadSync(buf, zip::internal::kZipBufSize);
+    num_bytes = file.ReadAtCurrentPos(buf, zip::internal::kZipBufSize);
     if (num_bytes > 0) {
       if (ZIP_OK != zipWriteInFileInZip(zip_file, buf, num_bytes)) {
         DLOG(ERROR) << "Could not write data to zip for path "
diff --git a/third_party/zlib/google/zip.target.darwin-arm.mk b/third_party/zlib/google/zip.target.darwin-arm.mk
index f42de51..a0067ed 100644
--- a/third_party/zlib/google/zip.target.darwin-arm.mk
+++ b/third_party/zlib/google/zip.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/google/zip.target.darwin-mips.mk b/third_party/zlib/google/zip.target.darwin-mips.mk
index 8796c33..3bf4a07 100644
--- a/third_party/zlib/google/zip.target.darwin-mips.mk
+++ b/third_party/zlib/google/zip.target.darwin-mips.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/google/zip.target.darwin-x86.mk b/third_party/zlib/google/zip.target.darwin-x86.mk
index 37a49bc..dc66f74 100644
--- a/third_party/zlib/google/zip.target.darwin-x86.mk
+++ b/third_party/zlib/google/zip.target.darwin-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -171,6 +172,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/google/zip.target.darwin-x86_64.mk b/third_party/zlib/google/zip.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a7c0c05
--- /dev/null
+++ b/third_party/zlib/google/zip.target.darwin-x86_64.mk
@@ -0,0 +1,266 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_zlib_google_zip_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/zlib/google/zip.cc \
+	third_party/zlib/google/zip_internal.cc \
+	third_party/zlib/google/zip_reader.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_zlib_google_zip_gyp
+
+# Alias gyp target name.
+.PHONY: zip
+zip: third_party_zlib_google_zip_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/zlib/google/zip.target.linux-arm.mk b/third_party/zlib/google/zip.target.linux-arm.mk
index f42de51..a0067ed 100644
--- a/third_party/zlib/google/zip.target.linux-arm.mk
+++ b/third_party/zlib/google/zip.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/google/zip.target.linux-mips.mk b/third_party/zlib/google/zip.target.linux-mips.mk
index 8796c33..3bf4a07 100644
--- a/third_party/zlib/google/zip.target.linux-mips.mk
+++ b/third_party/zlib/google/zip.target.linux-mips.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/google/zip.target.linux-x86.mk b/third_party/zlib/google/zip.target.linux-x86.mk
index 37a49bc..dc66f74 100644
--- a/third_party/zlib/google/zip.target.linux-x86.mk
+++ b/third_party/zlib/google/zip.target.linux-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -171,6 +172,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/google/zip.target.linux-x86_64.mk b/third_party/zlib/google/zip.target.linux-x86_64.mk
new file mode 100644
index 0000000..a7c0c05
--- /dev/null
+++ b/third_party/zlib/google/zip.target.linux-x86_64.mk
@@ -0,0 +1,266 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_zlib_google_zip_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/zlib/google/zip.cc \
+	third_party/zlib/google/zip_internal.cc \
+	third_party/zlib/google/zip_reader.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_zlib_google_zip_gyp
+
+# Alias gyp target name.
+.PHONY: zip
+zip: third_party_zlib_google_zip_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/zlib/google/zip_reader.cc b/third_party/zlib/google/zip_reader.cc
index 915dbbc..f34f4f7 100644
--- a/third_party/zlib/google/zip_reader.cc
+++ b/third_party/zlib/google/zip_reader.cc
@@ -4,12 +4,12 @@
 
 #include "third_party/zlib/google/zip_reader.h"
 
-#include "base/file_util.h"
+#include "base/bind.h"
+#include "base/files/file.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "net/base/file_stream.h"
 #include "third_party/zlib/google/zip_internal.h"
 
 #if defined(USE_SYSTEM_MINIZIP)
@@ -205,10 +205,9 @@
   if (!base::CreateDirectory(output_dir_path))
     return false;
 
-  net::FileStream stream(NULL);
-  const int flags = (base::PLATFORM_FILE_CREATE_ALWAYS |
-                     base::PLATFORM_FILE_WRITE);
-  if (stream.OpenSync(output_file_path, flags) != 0)
+  base::File file(output_file_path,
+                  base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+  if (!file.IsValid())
     return false;
 
   bool success = true;  // This becomes false when something bad happens.
@@ -225,14 +224,14 @@
       break;
     } else if (num_bytes_read > 0) {
       // Some data is read. Write it to the output file.
-      if (num_bytes_read != stream.WriteSync(buf, num_bytes_read)) {
+      if (num_bytes_read != file.WriteAtCurrentPos(buf, num_bytes_read)) {
         success = false;
         break;
       }
     }
   }
 
-  stream.CloseSync();
+  file.Close();
   unzCloseCurrentFile(zip_file_);
 
   if (current_entry_info()->last_modified() != base::Time::UnixEpoch())
diff --git a/third_party/zlib/minizip.target.darwin-arm.mk b/third_party/zlib/minizip.target.darwin-arm.mk
index f2ac763..2c4a97e 100644
--- a/third_party/zlib/minizip.target.darwin-arm.mk
+++ b/third_party/zlib/minizip.target.darwin-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/minizip.target.darwin-mips.mk b/third_party/zlib/minizip.target.darwin-mips.mk
index 68a5e6e..20c845c 100644
--- a/third_party/zlib/minizip.target.darwin-mips.mk
+++ b/third_party/zlib/minizip.target.darwin-mips.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/minizip.target.darwin-x86.mk b/third_party/zlib/minizip.target.darwin-x86.mk
index 0234580..764fb13 100644
--- a/third_party/zlib/minizip.target.darwin-x86.mk
+++ b/third_party/zlib/minizip.target.darwin-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -171,6 +172,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/minizip.target.darwin-x86_64.mk b/third_party/zlib/minizip.target.darwin-x86_64.mk
new file mode 100644
index 0000000..0252a81
--- /dev/null
+++ b/third_party/zlib/minizip.target.darwin-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_zlib_minizip_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/zlib/contrib/minizip/ioapi.c \
+	third_party/zlib/contrib/minizip/unzip.c \
+	third_party/zlib/contrib/minizip/zip.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_FILE32API' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_FILE32API' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_zlib_minizip_gyp
+
+# Alias gyp target name.
+.PHONY: minizip
+minizip: third_party_zlib_minizip_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/zlib/minizip.target.linux-arm.mk b/third_party/zlib/minizip.target.linux-arm.mk
index f2ac763..2c4a97e 100644
--- a/third_party/zlib/minizip.target.linux-arm.mk
+++ b/third_party/zlib/minizip.target.linux-arm.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/minizip.target.linux-mips.mk b/third_party/zlib/minizip.target.linux-mips.mk
index 68a5e6e..20c845c 100644
--- a/third_party/zlib/minizip.target.linux-mips.mk
+++ b/third_party/zlib/minizip.target.linux-mips.mk
@@ -83,6 +83,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -170,6 +171,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/minizip.target.linux-x86.mk b/third_party/zlib/minizip.target.linux-x86.mk
index 0234580..764fb13 100644
--- a/third_party/zlib/minizip.target.linux-x86.mk
+++ b/third_party/zlib/minizip.target.linux-x86.mk
@@ -84,6 +84,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -171,6 +172,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_FILE32API' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/minizip.target.linux-x86_64.mk b/third_party/zlib/minizip.target.linux-x86_64.mk
new file mode 100644
index 0000000..0252a81
--- /dev/null
+++ b/third_party/zlib/minizip.target.linux-x86_64.mk
@@ -0,0 +1,265 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_zlib_minizip_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/zlib/contrib/minizip/ioapi.c \
+	third_party/zlib/contrib/minizip/unzip.c \
+	third_party/zlib/contrib/minizip/zip.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_FILE32API' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_FILE32API' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_zlib_minizip_gyp
+
+# Alias gyp target name.
+.PHONY: minizip
+minizip: third_party_zlib_minizip_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/zlib/zlib.target.darwin-arm.mk b/third_party/zlib/zlib.target.darwin-arm.mk
index 768adf6..1c70d02 100644
--- a/third_party/zlib/zlib.target.darwin-arm.mk
+++ b/third_party/zlib/zlib.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/zlib.target.darwin-mips.mk b/third_party/zlib/zlib.target.darwin-mips.mk
index 7dabaec..904c0b0 100644
--- a/third_party/zlib/zlib.target.darwin-mips.mk
+++ b/third_party/zlib/zlib.target.darwin-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/zlib.target.darwin-x86.mk b/third_party/zlib/zlib.target.darwin-x86.mk
index 20daa54..1cce309 100644
--- a/third_party/zlib/zlib.target.darwin-x86.mk
+++ b/third_party/zlib/zlib.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -180,6 +181,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/zlib.target.darwin-x86_64.mk b/third_party/zlib/zlib.target.darwin-x86_64.mk
new file mode 100644
index 0000000..b85f6ba
--- /dev/null
+++ b/third_party/zlib/zlib.target.darwin-x86_64.mk
@@ -0,0 +1,273 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_zlib_zlib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/zlib/adler32.c \
+	third_party/zlib/compress.c \
+	third_party/zlib/crc32.c \
+	third_party/zlib/deflate.c \
+	third_party/zlib/gzclose.c \
+	third_party/zlib/gzlib.c \
+	third_party/zlib/gzread.c \
+	third_party/zlib/gzwrite.c \
+	third_party/zlib/infback.c \
+	third_party/zlib/inffast.c \
+	third_party/zlib/inflate.c \
+	third_party/zlib/inftrees.c \
+	third_party/zlib/trees.c \
+	third_party/zlib/uncompr.c \
+	third_party/zlib/zutil.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_zlib_zlib_gyp
+
+# Alias gyp target name.
+.PHONY: zlib
+zlib: third_party_zlib_zlib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/third_party/zlib/zlib.target.linux-arm.mk b/third_party/zlib/zlib.target.linux-arm.mk
index 768adf6..1c70d02 100644
--- a/third_party/zlib/zlib.target.linux-arm.mk
+++ b/third_party/zlib/zlib.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/zlib.target.linux-mips.mk b/third_party/zlib/zlib.target.linux-mips.mk
index 7dabaec..904c0b0 100644
--- a/third_party/zlib/zlib.target.linux-mips.mk
+++ b/third_party/zlib/zlib.target.linux-mips.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -179,6 +180,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/zlib.target.linux-x86.mk b/third_party/zlib/zlib.target.linux-x86.mk
index 20daa54..1cce309 100644
--- a/third_party/zlib/zlib.target.linux-x86.mk
+++ b/third_party/zlib/zlib.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -180,6 +181,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/third_party/zlib/zlib.target.linux-x86_64.mk b/third_party/zlib/zlib.target.linux-x86_64.mk
new file mode 100644
index 0000000..b85f6ba
--- /dev/null
+++ b/third_party/zlib/zlib.target.linux-x86_64.mk
@@ -0,0 +1,273 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := third_party_zlib_zlib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	third_party/zlib/adler32.c \
+	third_party/zlib/compress.c \
+	third_party/zlib/crc32.c \
+	third_party/zlib/deflate.c \
+	third_party/zlib/gzclose.c \
+	third_party/zlib/gzlib.c \
+	third_party/zlib/gzread.c \
+	third_party/zlib/gzwrite.c \
+	third_party/zlib/infback.c \
+	third_party/zlib/inffast.c \
+	third_party/zlib/inflate.c \
+	third_party/zlib/inftrees.c \
+	third_party/zlib/trees.c \
+	third_party/zlib/uncompr.c \
+	third_party/zlib/zutil.c
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: third_party_zlib_zlib_gyp
+
+# Alias gyp target name.
+.PHONY: zlib
+zlib: third_party_zlib_zlib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/tools/android/file_poller/file_poller.cc b/tools/android/file_poller/file_poller.cc
index fc354f5..c73db8b 100644
--- a/tools/android/file_poller/file_poller.cc
+++ b/tools/android/file_poller/file_poller.cc
@@ -103,7 +103,7 @@
   socket_info.sin_port = htons(0);
   if (bind(sockfd, (struct sockaddr*)&socket_info, sizeof(socket_info)) < 0)
     PLOG(FATAL);
-  int size = sizeof(socket_info);
+  socklen_t size = sizeof(socket_info);
   getsockname(sockfd, (struct sockaddr*)&socket_info, &size);
   printf("%d\n", ntohs(socket_info.sin_port));
   // Using a pipe to ensure child is diconnected from the terminal before
diff --git a/tools/android/memdump/memdump.cc b/tools/android/memdump/memdump.cc
index 4f4dd14..56b4771 100644
--- a/tools/android/memdump/memdump.cc
+++ b/tools/android/memdump/memdump.cc
@@ -437,8 +437,8 @@
                                      int page_flags_fd,
                                      ProcessMemory* process_memory) {
   const pid_t pid = process_memory->pid;
-  base::ScopedFD pagemap_fd(open(
-      base::StringPrintf("/proc/%d/pagemap", pid).c_str(), O_RDONLY));
+  base::ScopedFD pagemap_fd(HANDLE_EINTR(open(
+      base::StringPrintf("/proc/%d/pagemap", pid).c_str(), O_RDONLY)));
   if (!pagemap_fd.is_valid()) {
     PLOG(ERROR) << "open";
     return false;
@@ -489,7 +489,8 @@
 
   std::vector<ProcessMemory> processes_memory(pids.size());
   {
-    base::ScopedFD page_count_fd(open("/proc/kpagecount", O_RDONLY));
+    base::ScopedFD page_count_fd(
+        HANDLE_EINTR(open("/proc/kpagecount", O_RDONLY)));
     if (!page_count_fd.is_valid()) {
       PLOG(ERROR) << "open /proc/kpagecount";
       return EXIT_FAILURE;
diff --git a/tools/bisect-perf-regression.py b/tools/bisect-perf-regression.py
index e15cabe..a4b88fd 100755
--- a/tools/bisect-perf-regression.py
+++ b/tools/bisect-perf-regression.py
@@ -1375,7 +1375,7 @@
         return True
       raise IOError('Missing extracted folder %s ' % output_dir)
     except e:
-      print 'Somewthing went wrong while extracting archive file: %s' % e
+      print 'Something went wrong while extracting archive file: %s' % e
       self.BackupOrRestoreOutputdirectory(restore=True)
       # Cleanup any leftovers from unzipping.
       if os.path.exists(output_dir):
@@ -2788,35 +2788,61 @@
     return other_regressions
 
   def _CalculateConfidence(self, working_means, broken_means):
-    bounds_working = []
-    bounds_broken = []
-    for m in working_means:
-      current_mean = CalculateTruncatedMean(m, 0)
-      if bounds_working:
-        bounds_working[0] = min(current_mean, bounds_working[0])
-        bounds_working[1] = max(current_mean, bounds_working[0])
-      else:
-        bounds_working = [current_mean, current_mean]
-    for m in broken_means:
-      current_mean = CalculateTruncatedMean(m, 0)
-      if bounds_broken:
-        bounds_broken[0] = min(current_mean, bounds_broken[0])
-        bounds_broken[1] = max(current_mean, bounds_broken[0])
-      else:
-        bounds_broken = [current_mean, current_mean]
+    """Calculates the confidence percentage.
+
+    This is calculated based on how distinct the values are before and after
+    the last broken revision, and how noisy the results are.
+
+    Args:
+      working_means: A list of lists of "good" result numbers.
+      broken means: A list of lists of "bad" result numbers.
+
+    Returns:
+      A number between in the range [0, 100].
+    """
+    bounds_working = self._CalculateBounds(working_means)
+    bounds_broken = self._CalculateBounds(broken_means)
     dist_between_groups = min(math.fabs(bounds_broken[1] - bounds_working[0]),
-        math.fabs(bounds_broken[0] - bounds_working[1]))
+                              math.fabs(bounds_broken[0] - bounds_working[1]))
     working_mean = sum(working_means, [])
     broken_mean = sum(broken_means, [])
     len_working_group = CalculateStandardDeviation(working_mean)
     len_broken_group = CalculateStandardDeviation(broken_mean)
-
-    confidence = (dist_between_groups / (
-        max(0.0001, (len_broken_group + len_working_group ))))
+    confidence = (dist_between_groups /
+                  (max(0.0001, (len_broken_group + len_working_group))))
     confidence = int(min(1.0, max(confidence, 0.0)) * 100.0)
     return confidence
 
+  def _CalculateBounds(self, values_list):
+    """Returns the lower/upper bounds for the means of the given value lists.
+
+    Args:
+      values_list: A non-empty list of lists of numbers.
+
+    Returns:
+      A (lower, upper) pair of bounds.
+    """
+    bounds = None
+    for values in values_list:
+      mean = CalculateTruncatedMean(values, 0)
+      if bounds:
+        bounds[0] = min(mean, bounds[0])
+        bounds[1] = max(mean, bounds[1])
+      else:
+        bounds = (mean, mean)
+    return bounds
+
   def _GetResultsDict(self, revision_data, revision_data_sorted):
+    """Makes and returns a dictionary of overall results from the bisect.
+
+    Args:
+      revision_data: The revisions_data dict as returned by the Run method.
+      revision_data_sorted: A list of pairs from the above dictionary, sorted
+          in order of commits.
+
+    Returns:
+      A dictionary containing results from the bisect.
+    """
     # Find range where it possibly broke.
     first_working_revision = None
     first_working_revision_index = -1
diff --git a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index 89f0bd4..b6d7ddb 100644
--- a/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -9,6 +9,7 @@
 // http://www.chromium.org/developers/blink-gc-plugin-errors
 
 #include "Config.h"
+#include "JsonWriter.h"
 #include "RecordInfo.h"
 
 #include "clang/AST/AST.h"
@@ -59,6 +60,9 @@
 const char kStackAllocatedFieldNote[] =
     "[blink-gc] Stack-allocated field %0 declared here:";
 
+const char kMemberInUnmanagedClassNote[] =
+    "[blink-gc] Member field %0 in unmanaged class declared here:";
+
 const char kPartObjectContainsGCRoot[] =
     "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
 
@@ -110,8 +114,9 @@
     " which is not stack allocated.";
 
 struct BlinkGCPluginOptions {
-  BlinkGCPluginOptions() : enable_oilpan(false) {}
+  BlinkGCPluginOptions() : enable_oilpan(false), dump_graph(false) {}
   bool enable_oilpan;
+  bool dump_graph;
   std::set<std::string> ignored_classes;
   std::set<std::string> checked_namespaces;
   std::vector<std::string> ignored_directories;
@@ -136,9 +141,8 @@
     // TODO: unsupported cases.
     case TSK_ExplicitInstantiationDeclaration:
       return false;
-    default:
-      assert(false && "Unknown template specialization kind");
   }
+  assert(false && "Unknown template specialization kind");
 }
 
 // This visitor collects the entry points for the checker.
@@ -184,8 +188,8 @@
    public:
     MightBeCollectedVisitor() : might_be_collected_(false) {}
     bool might_be_collected() { return might_be_collected_; }
-    void VisitMember(Member* edge) { might_be_collected_ = true; }
-    void VisitCollection(Collection* edge) {
+    void VisitMember(Member* edge) override { might_be_collected_ = true; }
+    void VisitCollection(Collection* edge) override {
       if (edge->on_heap()) {
         might_be_collected_ = !edge->is_root();
       } else {
@@ -262,7 +266,7 @@
 class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> {
  public:
   CheckDispatchVisitor(RecordInfo* receiver)
-      : receiver_(receiver), dispatched_to_receiver_(false) { }
+      : receiver_(receiver), dispatched_to_receiver_(false) {}
 
   bool dispatched_to_receiver() { return dispatched_to_receiver_; }
 
@@ -394,7 +398,7 @@
     return !gc_roots_.empty();
   }
 
-  void VisitValue(Value* edge) {
+  void VisitValue(Value* edge) override {
     // TODO: what should we do to check unions?
     if (edge->value()->record()->isUnion())
       return;
@@ -409,11 +413,11 @@
     ContainsGCRoots(edge->value());
   }
 
-  void VisitPersistent(Persistent* edge) {
+  void VisitPersistent(Persistent* edge) override {
     gc_roots_.push_back(current_);
   }
 
-  void AtCollection(Collection* edge) {
+  void AtCollection(Collection* edge) override {
     if (edge->is_root())
       gc_roots_.push_back(current_);
   }
@@ -437,6 +441,10 @@
 
   bool ContainsInvalidFields(RecordInfo* info) {
     stack_allocated_host_ = info->IsStackAllocated();
+    managed_host_ = stack_allocated_host_ ||
+                    info->IsGCAllocated() ||
+                    info->IsNonNewable() ||
+                    info->IsOnlyPlacementNewable();
     for (RecordInfo::Fields::iterator it = info->GetFields().begin();
          it != info->GetFields().end();
          ++it) {
@@ -447,26 +455,43 @@
     return !invalid_fields_.empty();
   }
 
-  void VisitValue(Value* edge) {
+  void VisitMember(Member* edge) override {
+    if (managed_host_)
+      return;
+    // A member is allowed to appear in the context of a root.
+    for (Context::iterator it = context().begin();
+         it != context().end();
+         ++it) {
+      if ((*it)->Kind() == Edge::kRoot)
+        return;
+    }
+    invalid_fields_.push_back(std::make_pair(current_, edge));
+  }
+
+  void VisitValue(Value* edge) override {
     // TODO: what should we do to check unions?
     if (edge->value()->record()->isUnion())
       return;
 
-    if (!stack_allocated_host_ && edge->value()->IsStackAllocated())
+    if (!stack_allocated_host_ && edge->value()->IsStackAllocated()) {
       invalid_fields_.push_back(std::make_pair(current_, edge));
+      return;
+    }
 
     if (!Parent() || !edge->value()->IsGCAllocated())
       return;
 
-    if (Parent()->IsOwnPtr())
+    if (Parent()->IsOwnPtr() ||
+        (stack_allocated_host_ && Parent()->IsRawPtr())) {
       invalid_fields_.push_back(std::make_pair(current_, Parent()));
+      return;
+    }
 
     // Don't check raw and ref pointers in transition mode.
     if (options_.enable_oilpan)
       return;
 
-    if ((!stack_allocated_host_ && Parent()->IsRawPtr()) ||
-        Parent()->IsRefPtr())
+    if (Parent()->IsRawPtr() || Parent()->IsRefPtr())
       invalid_fields_.push_back(std::make_pair(current_, Parent()));
   }
 
@@ -474,6 +499,7 @@
   const BlinkGCPluginOptions& options_;
   FieldPoint* current_;
   bool stack_allocated_host_;
+  bool managed_host_;
   Errors invalid_fields_;
 };
 
@@ -485,7 +511,8 @@
                         const BlinkGCPluginOptions& options)
       : instance_(instance),
         diagnostic_(instance.getDiagnostics()),
-        options_(options) {
+        options_(options),
+        json_(0) {
 
     // Only check structures in the blink, WebCore and WebKit namespaces.
     options_.checked_namespaces.insert("blink");
@@ -502,9 +529,8 @@
         diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
     diag_fields_require_tracing_ =
         diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
-    diag_class_contains_invalid_fields_ =
-        diagnostic_.getCustomDiagID(getErrorLevel(),
-                                    kClassContainsInvalidFields);
+    diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
+        getErrorLevel(), kClassContainsInvalidFields);
     diag_class_contains_gc_root_ =
         diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
     diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
@@ -517,14 +543,14 @@
         getErrorLevel(), kMissingTraceDispatchMethod);
     diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
         getErrorLevel(), kMissingFinalizeDispatchMethod);
-    diag_virtual_and_manual_dispatch_ = diagnostic_.getCustomDiagID(
-        getErrorLevel(), kVirtualAndManualDispatch);
-    diag_missing_trace_dispatch_ = diagnostic_.getCustomDiagID(
-        getErrorLevel(), kMissingTraceDispatch);
-    diag_missing_finalize_dispatch_ = diagnostic_.getCustomDiagID(
-        getErrorLevel(), kMissingFinalizeDispatch);
-    diag_derives_non_stack_allocated_ = diagnostic_.getCustomDiagID(
-        getErrorLevel(), kDerivesNonStackAllocated);
+    diag_virtual_and_manual_dispatch_ =
+        diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
+    diag_missing_trace_dispatch_ =
+        diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
+    diag_missing_finalize_dispatch_ =
+        diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
+    diag_derives_non_stack_allocated_ =
+        diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated);
 
     // Register note messages.
     diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
@@ -537,6 +563,8 @@
         DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
     diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
         DiagnosticsEngine::Note, kStackAllocatedFieldNote);
+    diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
+        DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
     diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
         DiagnosticsEngine::Note, kPartObjectContainsGCRoot);
     diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
@@ -557,10 +585,34 @@
         DiagnosticsEngine::Note, kManualDispatchMethodNote);
   }
 
-  virtual void HandleTranslationUnit(ASTContext& context) {
+  void HandleTranslationUnit(ASTContext& context) override {
     CollectVisitor visitor;
     visitor.TraverseDecl(context.getTranslationUnitDecl());
 
+    if (options_.dump_graph) {
+      string err;
+      // TODO: Make createDefaultOutputFile or a shorter createOutputFile work.
+      json_ = JsonWriter::from(instance_.createOutputFile(
+          "",                                      // OutputPath
+          err,                                     // Errors
+          true,                                    // Binary
+          true,                                    // RemoveFileOnSignal
+          instance_.getFrontendOpts().OutputFile,  // BaseInput
+          "graph.json",                            // Extension
+          false,                                   // UseTemporary
+          false,                                   // CreateMissingDirectories
+          0,                                       // ResultPathName
+          0));                                     // TempPathName
+      if (err.empty() && json_) {
+        json_->OpenList();
+      } else {
+        json_ = 0;
+        llvm::errs()
+            << "[blink-gc] "
+            << "Failed to create an output file for the object graph.\n";
+      }
+    }
+
     for (RecordVector::iterator it = visitor.record_decls().begin();
          it != visitor.record_decls().end();
          ++it) {
@@ -572,6 +624,12 @@
          ++it) {
       CheckTracingMethod(*it);
     }
+
+    if (json_) {
+      json_->CloseList();
+      delete json_;
+      json_ = 0;
+    }
   }
 
   // Main entry for checking a record declaration.
@@ -618,8 +676,6 @@
     if (info->RequiresTraceMethod() && !info->GetTraceMethod())
       ReportClassRequiresTraceMethod(info);
 
-    CheckDispatch(info);
-
     {
       CheckFieldsVisitor visitor(options_);
       if (visitor.ContainsInvalidFields(info))
@@ -627,6 +683,8 @@
     }
 
     if (info->IsGCDerived()) {
+      CheckDispatch(info);
+
       CheckGCRootsVisitor visitor;
       if (visitor.ContainsGCRoots(info))
         ReportClassContainsGCRoots(info, &visitor.gc_roots());
@@ -634,6 +692,8 @@
       if (info->NeedsFinalization())
         CheckFinalization(info);
     }
+
+    DumpClass(info);
   }
 
   void CheckDispatch(RecordInfo* info) {
@@ -643,9 +703,8 @@
     if (!trace_dispatch && !finalize_dispatch)
       return;
 
-    CXXRecordDecl* base = trace_dispatch ?
-                          trace_dispatch->getParent() :
-                          finalize_dispatch->getParent();
+    CXXRecordDecl* base = trace_dispatch ? trace_dispatch->getParent()
+                                         : finalize_dispatch->getParent();
 
     // Check that dispatch methods are defined at the base.
     if (base == info->record()) {
@@ -804,12 +863,109 @@
     }
   }
 
+  void DumpClass(RecordInfo* info) {
+    if (!json_)
+      return;
+
+    json_->OpenObject();
+    json_->Write("name", info->record()->getQualifiedNameAsString());
+    json_->Write("loc", GetLocString(info->record()->getLocStart()));
+    json_->CloseObject();
+
+    class DumpEdgeVisitor : public RecursiveEdgeVisitor {
+     public:
+      DumpEdgeVisitor(JsonWriter* json) : json_(json) {}
+      void DumpEdge(RecordInfo* src,
+                    RecordInfo* dst,
+                    const string& lbl,
+                    const Edge::LivenessKind& kind,
+                    const string& loc) {
+        json_->OpenObject();
+        json_->Write("src", src->record()->getQualifiedNameAsString());
+        json_->Write("dst", dst->record()->getQualifiedNameAsString());
+        json_->Write("lbl", lbl);
+        json_->Write("kind", kind);
+        json_->Write("loc", loc);
+        json_->CloseObject();
+      }
+
+      void DumpField(RecordInfo* src, FieldPoint* point, const string& loc) {
+        src_ = src;
+        point_ = point;
+        loc_ = loc;
+        point_->edge()->Accept(this);
+      }
+
+      void AtValue(Value* e) override {
+        // The liveness kind of a path from the point to this value
+        // is given by the innermost place that is non-strong.
+        Edge::LivenessKind kind = Edge::kStrong;
+        if (Config::IsIgnoreCycleAnnotated(point_->field())) {
+          kind = Edge::kWeak;
+        } else {
+          for (Context::iterator it = context().begin();
+               it != context().end();
+               ++it) {
+            Edge::LivenessKind pointer_kind = (*it)->Kind();
+            if (pointer_kind != Edge::kStrong) {
+              kind = pointer_kind;
+              break;
+            }
+          }
+        }
+        DumpEdge(
+            src_, e->value(), point_->field()->getNameAsString(), kind, loc_);
+      }
+
+     private:
+      JsonWriter* json_;
+      RecordInfo* src_;
+      FieldPoint* point_;
+      string loc_;
+    };
+
+    DumpEdgeVisitor visitor(json_);
+
+    RecordInfo::Bases& bases = info->GetBases();
+    for (RecordInfo::Bases::iterator it = bases.begin();
+         it != bases.end();
+         ++it) {
+      visitor.DumpEdge(info,
+                       it->second.info(),
+                       "<super>",
+                       Edge::kStrong,
+                       GetLocString(it->second.spec().getLocStart()));
+    }
+
+    RecordInfo::Fields& fields = info->GetFields();
+    for (RecordInfo::Fields::iterator it = fields.begin();
+         it != fields.end();
+         ++it) {
+      visitor.DumpField(info,
+                        &it->second,
+                        GetLocString(it->second.field()->getLocStart()));
+    }
+  }
+
   // Adds either a warning or error, based on the current handling of -Werror.
   DiagnosticsEngine::Level getErrorLevel() {
     return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
                                              : DiagnosticsEngine::Warning;
   }
 
+  const string GetLocString(SourceLocation loc) {
+    const SourceManager& source_manager = instance_.getSourceManager();
+    PresumedLoc ploc = source_manager.getPresumedLoc(loc);
+    if (ploc.isInvalid())
+      return "";
+    string loc_str;
+    llvm::raw_string_ostream OS(loc_str);
+    OS << ploc.getFilename()
+       << ":" << ploc.getLine()
+       << ":" << ploc.getColumn();
+    return OS.str();
+  }
+
   bool IsIgnored(RecordInfo* record) {
     return !record ||
            !InCheckedNamespace(record) ||
@@ -839,18 +995,19 @@
   }
 
   bool InCheckedNamespace(RecordInfo* info) {
+    if (!info)
+      return false;
     DeclContext* context = info->record()->getDeclContext();
-    switch (context->getDeclKind()) {
-      case Decl::Namespace: {
-        const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
-        if (decl->isAnonymousNamespace())
-          return false;
-        return options_.checked_namespaces.find(decl->getNameAsString()) !=
-               options_.checked_namespaces.end();
-      }
-      default:
+    if (context->isRecord())
+      return InCheckedNamespace(cache_.Lookup(context));
+    if (context->isNamespace()) {
+      const NamespaceDecl* decl = dyn_cast<NamespaceDecl>(context);
+      if (decl->isAnonymousNamespace())
         return false;
+      return options_.checked_namespaces.find(decl->getNameAsString()) !=
+          options_.checked_namespaces.end();
     }
+    return false;
   }
 
   bool GetFilename(SourceLocation loc, string* filename) {
@@ -920,6 +1077,8 @@
         NoteField(it->first, diag_ref_ptr_to_gc_managed_class_note_);
       } else if (it->second->IsOwnPtr()) {
         NoteField(it->first, diag_own_ptr_to_gc_managed_class_note_);
+      } else if (it->second->IsMember()) {
+        NoteField(it->first, diag_member_in_unmanaged_class_note_);
       } else if (it->second->IsValue()) {
         NoteField(it->first, diag_stack_allocated_field_note_);
       }
@@ -976,8 +1135,7 @@
     SourceManager& manager = instance_.getSourceManager();
     FullSourceLoc full_loc(loc, manager);
     diagnostic_.Report(full_loc, diag_overridden_non_virtual_trace_)
-        << info->record()
-        << overridden->getParent();
+        << info->record() << overridden->getParent();
     NoteOverriddenNonVirtualTrace(overridden);
   }
 
@@ -1017,8 +1175,8 @@
   }
 
   void ReportMissingDispatch(const FunctionDecl* dispatch,
-                               RecordInfo* receiver,
-                               unsigned error) {
+                             RecordInfo* receiver,
+                             unsigned error) {
     SourceLocation loc = dispatch->getLocStart();
     SourceManager& manager = instance_.getSourceManager();
     FullSourceLoc full_loc(loc, manager);
@@ -1118,6 +1276,7 @@
   unsigned diag_ref_ptr_to_gc_managed_class_note_;
   unsigned diag_own_ptr_to_gc_managed_class_note_;
   unsigned diag_stack_allocated_field_note_;
+  unsigned diag_member_in_unmanaged_class_note_;
   unsigned diag_part_object_contains_gc_root_note_;
   unsigned diag_field_contains_gc_root_note_;
   unsigned diag_finalized_field_note_;
@@ -1132,6 +1291,7 @@
   DiagnosticsEngine& diagnostic_;
   BlinkGCPluginOptions options_;
   RecordCache cache_;
+  JsonWriter* json_;
 };
 
 class BlinkGCPluginAction : public PluginASTAction {
@@ -1152,6 +1312,8 @@
     for (size_t i = 0; i < args.size() && parsed; ++i) {
       if (args[i] == "enable-oilpan") {
         options_.enable_oilpan = true;
+      } else if (args[i] == "dump-graph") {
+        options_.dump_graph = true;
       } else {
         parsed = false;
         llvm::errs() << "Unknown blink-gc-plugin argument: " << args[i] << "\n";
diff --git a/tools/clang/blink_gc_plugin/Config.h b/tools/clang/blink_gc_plugin/Config.h
index 7354549..5339470 100644
--- a/tools/clang/blink_gc_plugin/Config.h
+++ b/tools/clang/blink_gc_plugin/Config.h
@@ -8,6 +8,7 @@
 #define TOOLS_BLINK_GC_PLUGIN_CONFIG_H_
 
 #include "clang/AST/AST.h"
+#include "clang/AST/Attr.h"
 
 const char kNewOperatorName[] = "operator new";
 const char kCreateName[] = "create";
@@ -101,6 +102,24 @@
            IsGCMixinBase(name);
   }
 
+  static bool IsAnnotated(clang::Decl* decl, const std::string& anno) {
+    clang::AnnotateAttr* attr = decl->getAttr<clang::AnnotateAttr>();
+    return attr && (attr->getAnnotation() == anno);
+  }
+
+  static bool IsStackAnnotated(clang::Decl* decl) {
+    return IsAnnotated(decl, "blink_stack_allocated");
+  }
+
+  static bool IsIgnoreAnnotated(clang::Decl* decl) {
+    return IsAnnotated(decl, "blink_gc_plugin_ignore");
+  }
+
+  static bool IsIgnoreCycleAnnotated(clang::Decl* decl) {
+    return IsAnnotated(decl, "blink_gc_plugin_ignore_cycle") ||
+           IsIgnoreAnnotated(decl);
+  }
+
   static bool IsVisitor(const std::string& name) { return name == "Visitor"; }
 
   static bool IsTraceMethod(clang::CXXMethodDecl* method,
diff --git a/tools/clang/blink_gc_plugin/Edge.h b/tools/clang/blink_gc_plugin/Edge.h
index 36ff1e8..2db8d3f 100644
--- a/tools/clang/blink_gc_plugin/Edge.h
+++ b/tools/clang/blink_gc_plugin/Edge.h
@@ -38,14 +38,14 @@
 class RecursiveEdgeVisitor : public EdgeVisitor {
  public:
   // Overrides that recursively walk the edges and record the path.
-  virtual void VisitValue(Value*);
-  virtual void VisitRawPtr(RawPtr*);
-  virtual void VisitRefPtr(RefPtr*);
-  virtual void VisitOwnPtr(OwnPtr*);
-  virtual void VisitMember(Member*);
-  virtual void VisitWeakMember(WeakMember*);
-  virtual void VisitPersistent(Persistent*);
-  virtual void VisitCollection(Collection*);
+  virtual void VisitValue(Value*) override;
+  virtual void VisitRawPtr(RawPtr*) override;
+  virtual void VisitRefPtr(RefPtr*) override;
+  virtual void VisitOwnPtr(OwnPtr*) override;
+  virtual void VisitMember(Member*) override;
+  virtual void VisitWeakMember(WeakMember*) override;
+  virtual void VisitPersistent(Persistent*) override;
+  virtual void VisitCollection(Collection*) override;
 
  protected:
   typedef std::deque<Edge*> Context;
@@ -72,8 +72,10 @@
 class Edge {
  public:
   enum NeedsTracingOption { kRecursive, kNonRecursive };
+  enum LivenessKind { kWeak, kStrong, kRoot };
 
-  virtual ~Edge() { }
+  virtual ~Edge() {}
+  virtual LivenessKind Kind() = 0;
   virtual void Accept(EdgeVisitor*) = 0;
   virtual bool NeedsFinalization() = 0;
   virtual TracingStatus NeedsTracing(NeedsTracingOption) {
@@ -94,11 +96,13 @@
 class Value : public Edge {
  public:
   explicit Value(RecordInfo* value) : value_(value) {};
-  bool IsValue() { return true; }
-  bool NeedsFinalization();
-  TracingStatus NeedsTracing(NeedsTracingOption);
-  void Accept(EdgeVisitor* visitor) { visitor->VisitValue(this); }
+  bool IsValue() override { return true; }
+  LivenessKind Kind() override { return kStrong; }
+  bool NeedsFinalization() override;
+  TracingStatus NeedsTracing(NeedsTracingOption) override;
+  void Accept(EdgeVisitor* visitor) override { visitor->VisitValue(this); }
   RecordInfo* value() { return value_; }
+
  private:
   RecordInfo* value_;
 };
@@ -120,6 +124,7 @@
  public:
   explicit RawPtr(Edge* ptr) : PtrEdge(ptr) { }
   bool IsRawPtr() { return true; }
+  LivenessKind Kind() { return kWeak; }
   bool NeedsFinalization() { return false; }
   TracingStatus NeedsTracing(NeedsTracingOption) {
     return TracingStatus::Unneeded();
@@ -131,6 +136,7 @@
  public:
   explicit RefPtr(Edge* ptr) : PtrEdge(ptr) { }
   bool IsRefPtr() { return true; }
+  LivenessKind Kind() { return kStrong; }
   bool NeedsFinalization() { return true; }
   TracingStatus NeedsTracing(NeedsTracingOption) {
     return TracingStatus::Unneeded();
@@ -142,6 +148,7 @@
  public:
   explicit OwnPtr(Edge* ptr) : PtrEdge(ptr) { }
   bool IsOwnPtr() { return true; }
+  LivenessKind Kind() { return kStrong; }
   bool NeedsFinalization() { return true; }
   TracingStatus NeedsTracing(NeedsTracingOption) {
     return TracingStatus::Unneeded();
@@ -153,6 +160,7 @@
  public:
   explicit Member(Edge* ptr) : PtrEdge(ptr) { }
   bool IsMember() { return true; }
+  LivenessKind Kind() { return kStrong; }
   bool NeedsFinalization() { return false; }
   TracingStatus NeedsTracing(NeedsTracingOption) {
     return TracingStatus::Needed();
@@ -164,6 +172,7 @@
  public:
   explicit WeakMember(Edge* ptr) : PtrEdge(ptr) { }
   bool IsWeakMember() { return true; }
+  LivenessKind Kind() { return kWeak; }
   bool NeedsFinalization() { return false; }
   TracingStatus NeedsTracing(NeedsTracingOption) {
     return TracingStatus::Needed();
@@ -175,6 +184,7 @@
  public:
   explicit Persistent(Edge* ptr) : PtrEdge(ptr) { }
   bool IsPersistent() { return true; }
+  LivenessKind Kind() { return kRoot; }
   bool NeedsFinalization() { return true; }
   TracingStatus NeedsTracing(NeedsTracingOption) {
     return TracingStatus::Unneeded();
@@ -196,6 +206,7 @@
     }
   }
   bool IsCollection() { return true; }
+  LivenessKind Kind() { return is_root_ ? kRoot : kStrong; }
   bool on_heap() { return on_heap_; }
   bool is_root() { return is_root_; }
   Members& members() { return members_; }
@@ -218,6 +229,7 @@
     }
     return status;
   }
+
  private:
   RecordInfo* info_;
   Members members_;
@@ -225,4 +237,4 @@
   bool is_root_;
 };
 
-#endif // TOOLS_BLINK_GC_PLUGIN_EDGE_H_
+#endif  // TOOLS_BLINK_GC_PLUGIN_EDGE_H_
diff --git a/tools/clang/blink_gc_plugin/JsonWriter.h b/tools/clang/blink_gc_plugin/JsonWriter.h
new file mode 100644
index 0000000..54a87aa
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/JsonWriter.h
@@ -0,0 +1,73 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_BLINK_GC_PLUGIN_JSON_WRITER_H_
+#define TOOLS_BLINK_GC_PLUGIN_JSON_WRITER_H_
+
+#include "llvm/Support/raw_ostream.h"
+
+// Helper to write information for the points-to graph.
+class JsonWriter {
+ public:
+  static JsonWriter* from(llvm::raw_fd_ostream* os) {
+    return os ? new JsonWriter(os) : 0;
+  }
+  ~JsonWriter() {
+    os_.close();
+  }
+  void OpenList() {
+    Separator();
+    os_ << "[";
+    state_.push(false);
+  }
+  void OpenList(const std::string key) {
+    Write(key);
+    os_ << ":";
+    OpenList();
+  }
+  void CloseList() {
+    os_ << "]";
+    state_.pop();
+  }
+  void OpenObject() {
+    Separator();
+    os_ << "{";
+    state_.push(false);
+  }
+  void CloseObject() {
+    os_ << "}\n";
+    state_.pop();
+  }
+  void Write(const size_t val) {
+    Separator();
+    os_ << val;
+  }
+  void Write(const std::string val) {
+    Separator();
+    os_ << "\"" << val << "\"";
+  }
+  void Write(const std::string key, const size_t val) {
+    Separator();
+    os_ << "\"" << key << "\":" << val;
+  }
+  void Write(const std::string key, const std::string val) {
+    Separator();
+    os_ << "\"" << key << "\":\"" << val << "\"";
+  }
+ private:
+  JsonWriter(llvm::raw_fd_ostream* os) : os_(*os) {}
+  void Separator() {
+    if (state_.empty())
+      return;
+    if (state_.top()) {
+      os_ << ",";
+      return;
+    }
+    state_.top() = true;
+  }
+  llvm::raw_fd_ostream& os_;
+  std::stack<bool> state_;
+};
+
+#endif // TOOLS_BLINK_GC_PLUGIN_JSON_WRITER_H_
diff --git a/tools/clang/blink_gc_plugin/Makefile b/tools/clang/blink_gc_plugin/Makefile
index 85e422b..d6e7da9 100644
--- a/tools/clang/blink_gc_plugin/Makefile
+++ b/tools/clang/blink_gc_plugin/Makefile
@@ -9,7 +9,7 @@
 CLANG_LEVEL := ../..
 
 # This line is read by update.sh and other scripts in tools/clang/scripts
-LIBRARYNAME = BlinkGCPlugin_2
+LIBRARYNAME = BlinkGCPlugin_3
 
 LINK_LIBS_IN_SHARED = 0
 SHARED_LIBRARY = 1
diff --git a/tools/clang/blink_gc_plugin/RecordInfo.cpp b/tools/clang/blink_gc_plugin/RecordInfo.cpp
index 1a82206..24eec2a 100644
--- a/tools/clang/blink_gc_plugin/RecordInfo.cpp
+++ b/tools/clang/blink_gc_plugin/RecordInfo.cpp
@@ -5,8 +5,6 @@
 #include "Config.h"
 #include "RecordInfo.h"
 
-#include "clang/AST/Attr.h"
-
 using namespace clang;
 using std::string;
 
@@ -18,6 +16,8 @@
       bases_(0),
       fields_(0),
       is_stack_allocated_(kNotComputed),
+      is_non_newable_(kNotComputed),
+      is_only_placement_newable_(kNotComputed),
       determined_trace_methods_(false),
       trace_method_(0),
       trace_dispatch_method_(0),
@@ -136,20 +136,15 @@
   return IsGCDerived() || IsHeapAllocatedCollection();
 }
 
-static bool IsAnnotated(Decl* decl, const string& anno) {
-  AnnotateAttr* attr = decl->getAttr<AnnotateAttr>();
-  return attr && (attr->getAnnotation() == anno);
-}
-
 RecordInfo* RecordCache::Lookup(CXXRecordDecl* record) {
   // Ignore classes annotated with the GC_PLUGIN_IGNORE macro.
-  if (!record || IsAnnotated(record, "blink_gc_plugin_ignore"))
+  if (!record || Config::IsIgnoreAnnotated(record))
     return 0;
   Cache::iterator it = cache_.find(record);
   if (it != cache_.end())
     return &it->second;
   return &cache_.insert(std::make_pair(record, RecordInfo(record, this)))
-      .first->second;
+              .first->second;
 }
 
 bool RecordInfo::IsStackAllocated() {
@@ -160,23 +155,60 @@
          ++it) {
       if (it->second.info()->IsStackAllocated()) {
         is_stack_allocated_ = kTrue;
-        break;
+        return is_stack_allocated_;
       }
     }
     for (CXXRecordDecl::method_iterator it = record_->method_begin();
          it != record_->method_end();
          ++it) {
-      if (it->getNameAsString() == kNewOperatorName) {
-        if (it->isDeleted() && IsAnnotated(*it, "blink_stack_allocated")) {
-          is_stack_allocated_ = kTrue;
-          break;
-        }
+      if (it->getNameAsString() == kNewOperatorName &&
+          it->isDeleted() &&
+          Config::IsStackAnnotated(*it)) {
+        is_stack_allocated_ = kTrue;
+        return is_stack_allocated_;
       }
     }
   }
   return is_stack_allocated_;
 }
 
+bool RecordInfo::IsNonNewable() {
+  if (is_non_newable_ == kNotComputed) {
+    bool deleted = false;
+    bool all_deleted = true;
+    for (CXXRecordDecl::method_iterator it = record_->method_begin();
+         it != record_->method_end();
+         ++it) {
+      if (it->getNameAsString() == kNewOperatorName) {
+        deleted = it->isDeleted();
+        all_deleted = all_deleted && deleted;
+      }
+    }
+    is_non_newable_ = (deleted && all_deleted) ? kTrue : kFalse;
+  }
+  return is_non_newable_;
+}
+
+bool RecordInfo::IsOnlyPlacementNewable() {
+  if (is_only_placement_newable_ == kNotComputed) {
+    bool placement = false;
+    bool new_deleted = false;
+    for (CXXRecordDecl::method_iterator it = record_->method_begin();
+         it != record_->method_end();
+         ++it) {
+      if (it->getNameAsString() == kNewOperatorName) {
+        if (it->getNumParams() == 1) {
+          new_deleted = it->isDeleted();
+        } else if (it->getNumParams() == 2) {
+          placement = !it->isDeleted();
+        }
+      }
+    }
+    is_only_placement_newable_ = (placement && new_deleted) ? kTrue : kFalse;
+  }
+  return is_only_placement_newable_;
+}
+
 // An object requires a tracing method if it has any fields that need tracing.
 bool RecordInfo::RequiresTraceMethod() {
   if (IsStackAllocated())
@@ -285,11 +317,11 @@
        ++it) {
     FieldDecl* field = *it;
     // Ignore fields annotated with the GC_PLUGIN_IGNORE macro.
-    if (IsAnnotated(field, "blink_gc_plugin_ignore"))
+    if (Config::IsIgnoreAnnotated(field))
       continue;
     if (Edge* edge = CreateEdge(field->getType().getTypePtrOrNull())) {
-      fields->insert(std::make_pair(field, FieldPoint(field, edge)));
       fields_status = fields_status.LUB(edge->NeedsTracing(Edge::kRecursive));
+      fields->insert(std::make_pair(field, FieldPoint(field, edge)));
     }
   }
   fields_need_tracing_ = fields_status;
@@ -315,7 +347,7 @@
         trace = *it;
       }
     } else if (it->getNameAsString() == kFinalizeName) {
-        finalize_dispatch_method_ = *it;
+      finalize_dispatch_method_ = *it;
     }
   }
   if (traceAfterDispatch) {
@@ -337,7 +369,7 @@
       trace_dispatch_method_ = dispatch;
     }
     if (CXXMethodDecl* dispatch =
-        it->second.info()->GetFinalizeDispatchMethod()) {
+            it->second.info()->GetFinalizeDispatchMethod()) {
       assert(!finalize_dispatch_method_ &&
              "Multiple finalize dispatching methods");
       finalize_dispatch_method_ = dispatch;
@@ -362,6 +394,9 @@
   if (IsGCAllocated())
     return TracingStatus::Needed();
 
+  if (IsStackAllocated())
+    return TracingStatus::Unneeded();
+
   for (Bases::iterator it = GetBases().begin(); it != GetBases().end(); ++it) {
     if (it->second.info()->NeedsTracing(option).IsNeeded())
       return TracingStatus::Needed();
diff --git a/tools/clang/blink_gc_plugin/RecordInfo.h b/tools/clang/blink_gc_plugin/RecordInfo.h
index f86e948..bab9143 100644
--- a/tools/clang/blink_gc_plugin/RecordInfo.h
+++ b/tools/clang/blink_gc_plugin/RecordInfo.h
@@ -26,6 +26,7 @@
   void MarkTraced() { traced_ = true; }
   bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); }
   virtual const TracingStatus NeedsTracing() = 0;
+
  private:
   bool traced_;
 };
@@ -41,6 +42,7 @@
   void MarkUnneeded() { status_ = TracingStatus::Unneeded(); }
   const clang::CXXBaseSpecifier& spec() { return spec_; }
   RecordInfo* info() { return info_; }
+
  private:
   const clang::CXXBaseSpecifier& spec_;
   RecordInfo* info_;
@@ -49,17 +51,18 @@
 
 class FieldPoint : public GraphPoint {
  public:
-  FieldPoint(clang::FieldDecl* field, Edge* edge) : field_(field), edge_(edge) {
-    assert(edge && "FieldPoint edge must be non-null");
-  }
+  FieldPoint(clang::FieldDecl* field, Edge* edge)
+      : field_(field), edge_(edge) {}
   const TracingStatus NeedsTracing() {
     return edge_->NeedsTracing(Edge::kRecursive);
   }
   clang::FieldDecl* field() { return field_; }
   Edge* edge() { return edge_; }
+
  private:
   clang::FieldDecl* field_;
   Edge* edge_;
+
   friend class RecordCache;
   void deleteEdge() { delete edge_; }
 };
@@ -88,8 +91,10 @@
   bool IsGCAllocated();
   bool IsGCFinalized();
   bool IsGCMixin();
-
   bool IsStackAllocated();
+  bool IsNonNewable();
+  bool IsOnlyPlacementNewable();
+
   bool RequiresTraceMethod();
   bool NeedsFinalization();
   TracingStatus NeedsTracing(Edge::NeedsTracingOption);
@@ -115,6 +120,8 @@
 
   enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 };
   CachedBool is_stack_allocated_;
+  CachedBool is_non_newable_;
+  CachedBool is_only_placement_newable_;
 
   bool determined_trace_methods_;
   clang::CXXMethodDecl* trace_method_;
@@ -135,7 +142,7 @@
     return Lookup(const_cast<clang::CXXRecordDecl*>(record));
   }
 
-  RecordInfo* Lookup(clang::Decl* decl) {
+  RecordInfo* Lookup(clang::DeclContext* decl) {
     return Lookup(clang::dyn_cast<clang::CXXRecordDecl>(decl));
   }
 
diff --git a/tools/clang/blink_gc_plugin/process-graph.py b/tools/clang/blink_gc_plugin/process-graph.py
new file mode 100755
index 0000000..ebeb105
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/process-graph.py
@@ -0,0 +1,348 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse, os, sys, json, subprocess, pickle, StringIO
+
+parser = argparse.ArgumentParser(
+  description =
+    "Process the Blink points-to graph generated by the Blink GC plugin.")
+
+parser.add_argument(
+  '-', dest='use_stdin', action='store_true',
+  help='Read JSON graph files from stdin')
+
+parser.add_argument(
+  '-v', '--verbose', action='store_true',
+  help='Verbose output')
+
+parser.add_argument(
+  '-c', '--detect-cycles', action='store_true', default=True,
+  help='Detect cycles containing GC roots')
+
+parser.add_argument(
+  '-i', '--ignored-cycles', default=None,
+  help='File with cycles to ignore')
+
+parser.add_argument(
+  '-p', '--pickle-graph', default=None,
+  help='File to read/save the graph from/to')
+
+parser.add_argument(
+  'files', metavar='FILE', nargs='*', default=[],
+  help='JSON graph files or directories containing them')
+
+# Command line args after parsing.
+args = None
+
+# Map from node labels to nodes.
+graph = {}
+
+# Set of root nodes.
+roots = []
+
+# List of cycles to ignore.
+ignored_cycles = []
+
+# Global flag to determine exit code.
+global_reported_error = False
+
+def set_reported_error(value):
+  global global_reported_error
+  global_reported_error = value
+
+def reported_error():
+  return global_reported_error
+
+def log(msg):
+  if args.verbose:
+    print msg
+
+global_inc_copy = 0
+def inc_copy():
+  global global_inc_copy
+  global_inc_copy += 1
+
+def get_node(name):
+  return graph.setdefault(name, Node(name))
+
+# Representation of graph nodes. Basically a map of directed edges.
+class Node:
+  def __init__(self, name):
+    self.name = name
+    self.edges = {}
+    self.reset()
+  def __repr__(self):
+    return "%s(%s) %s" % (self.name, self.visited, self.edges)
+  def update_node(self, decl):
+    # Currently we don't track any node info besides its edges.
+    pass
+  def update_edge(self, e):
+    new_edge = Edge(**e)
+    edge = self.edges.get(new_edge.key)
+    if edge:
+      # If an edge exist, its kind is the strongest of the two.
+      edge.kind = max(edge.kind, new_edge.kind)
+    else:
+      self.edges[new_edge.key] = new_edge
+  def super_edges(self):
+    return [ e for e in self.edges.itervalues() if e.is_super() ]
+  def reset(self):
+    self.cost = sys.maxint
+    self.visited = False
+    self.path = None
+
+# Representation of directed graph edges.
+class Edge:
+  def __init__(self, **decl):
+    self.src = decl['src']
+    self.dst = decl['dst']
+    self.lbl = decl['lbl']
+    self.kind = decl['kind'] # 0 = weak, 1 = strong, 2 = root
+    self.loc = decl['loc']
+    # The label does not uniquely determine an edge from a node. We
+    # define the semi-unique key to be the concatenation of the
+    # label and dst name. This is sufficient to track the strongest
+    # edge to a particular type. For example, if the field A::m_f
+    # has type HashMap<WeakMember<B>, Member<B>> we will have a
+    # strong edge with key m_f#B from A to B.
+    self.key = '%s#%s' % (self.lbl, self.dst)
+  def copy(self):
+    return Edge(
+      lbl = self.lbl,
+      kind = self.kind,
+      src = self.src,
+      dst = self.dst,
+      loc = self.loc)
+  def __repr__(self):
+    return '%s (%s) => %s' % (self.src, self.lbl, self.dst)
+  def is_root(self):
+    return self.kind == 2
+  def is_weak(self):
+    return self.kind == 0
+  def keeps_alive(self):
+    return self.kind > 0
+  def is_subclass(self):
+    return self.lbl.startswith('<subclass>')
+  def is_super(self):
+    return self.lbl.startswith('<super>')
+
+def parse_file(filename):
+  obj = json.load(open(filename))
+  return obj
+
+def build_graphs_in_dir(dirname):
+  # TODO: Use plateform independent code, eg, os.walk
+  files = subprocess.check_output(
+    ['find', dirname, '-name', '*.graph.json']).split('\n')
+  log("Found %d files" % len(files))
+  for f in files:
+    f.strip()
+    if len(f) < 1:
+      continue
+    build_graph(f)
+
+def build_graph(filename):
+  for decl in parse_file(filename):
+    if decl.has_key('name'):
+      # Add/update a node entry
+      name = decl['name']
+      node = get_node(name)
+      node.update_node(decl)
+    else:
+      # Add/update an edge entry
+      name = decl['src']
+      node = get_node(name)
+      node.update_edge(decl)
+
+# Copy all non-weak edges from super classes to their subclasses.
+# This causes all fields of a super to be considered fields of a
+# derived class without tranitively relating derived classes with
+# each other. For example, if B <: A, C <: A, and for some D, D => B,
+# we don't want that to entail that D => C.
+def copy_super_edges(edge):
+  if edge.is_weak() or not edge.is_super():
+    return
+  inc_copy()
+  # Make the super-class edge weak (prohibits processing twice).
+  edge.kind = 0
+  # If the super class is not in our graph exit early.
+  super_node = graph.get(edge.dst)
+  if super_node is None: return
+  # Recursively copy all super-class edges.
+  for e in super_node.super_edges():
+    copy_super_edges(e)
+  # Copy strong super-class edges (ignoring sub-class edges) to the sub class.
+  sub_node = graph[edge.src]
+  for e in super_node.edges.itervalues():
+    if e.keeps_alive() and not e.is_subclass():
+      new_edge = e.copy()
+      new_edge.src = sub_node.name
+      new_edge.lbl = '%s <: %s' % (super_node.name, e.lbl)
+      sub_node.edges[new_edge.key] = new_edge
+  # Add a strong sub-class edge.
+  sub_edge = edge.copy()
+  sub_edge.kind = 1
+  sub_edge.lbl = '<subclass>'
+  sub_edge.src = super_node.name
+  sub_edge.dst = sub_node.name
+  super_node.edges[sub_edge.key] = sub_edge
+
+def complete_graph():
+  for node in graph.itervalues():
+    for edge in node.super_edges():
+      copy_super_edges(edge)
+    for edge in node.edges.itervalues():
+      if edge.is_root():
+        roots.append(edge)
+  log("Copied edges down <super> edges for %d graph nodes" % global_inc_copy)
+
+def reset_graph():
+  for n in graph.itervalues():
+    n.reset()
+
+def shortest_path(start, end):
+  start.cost = 0
+  minlist = [start]
+  while len(minlist) > 0:
+    minlist.sort(key=lambda n: -n.cost)
+    current = minlist.pop()
+    current.visited = True
+    if current == end or current.cost >= end.cost + 1:
+      return
+    for e in current.edges.itervalues():
+      if not e.keeps_alive():
+        continue
+      dst = graph.get(e.dst)
+      if dst is None or dst.visited:
+        continue
+      if current.cost < dst.cost:
+        dst.cost = current.cost + 1
+        dst.path = e
+      minlist.append(dst)
+
+def detect_cycles():
+  for root_edge in roots:
+    reset_graph()
+    src = graph[root_edge.src]
+    dst = graph.get(root_edge.dst)
+    if root_edge.dst == "WTF::String":
+      continue
+    if dst is None:
+      print "\nPersistent root to incomplete destination object:"
+      print root_edge
+      set_reported_error(True)
+      continue
+    # Find the shortest path from the root target (dst) to its host (src)
+    shortest_path(dst, src)
+    if src.cost < sys.maxint:
+      report_cycle(root_edge)
+
+def is_ignored_cycle(cycle):
+  for block in ignored_cycles:
+    if block_match(cycle, block):
+      return True
+
+def block_match(b1, b2):
+  if len(b1) != len(b2):
+    return False
+  for (l1, l2) in zip(b1, b2):
+    if l1 != l2:
+      return False
+  return True
+
+def report_cycle(root_edge):
+  dst = graph[root_edge.dst]
+  path = []
+  edge = root_edge
+  dst.path = None
+  while edge:
+    path.append(edge)
+    edge = graph[edge.src].path
+  path.append(root_edge)
+  path.reverse()
+  # Find the max loc length for pretty printing.
+  max_loc = 0
+  for p in path:
+    if len(p.loc) > max_loc:
+      max_loc = len(p.loc)
+  out = StringIO.StringIO()
+  for p in path[:-1]:
+    print >>out, (p.loc + ':').ljust(max_loc + 1), p
+  sout = out.getvalue()
+  if not is_ignored_cycle(sout):
+    print "\nFound a potentially leaking cycle starting from a GC root:\n", sout
+    set_reported_error(True)
+
+def load_graph():
+  global graph
+  global roots
+  log("Reading graph from pickled file: " + args.pickle_graph)
+  dump = pickle.load(open(args.pickle_graph, 'rb'))
+  graph = dump[0]
+  roots = dump[1]
+
+def save_graph():
+  log("Saving graph to pickle file: " + args.pickle_graph)
+  dump = (graph, roots)
+  pickle.dump(dump, open(args.pickle_graph, 'wb'))
+
+def read_ignored_cycles():
+  global ignored_cycles
+  if not args.ignored_cycles:
+    return
+  log("Reading ignored cycles from file: " + args.ignored_cycles)
+  block = []
+  for l in open(args.ignored_cycles):
+    line = l.strip()
+    if not line:
+      if len(block) > 0:
+        ignored_cycles.append(block)
+      block = []
+    else:
+      block += l
+  if len(block) > 0:
+    ignored_cycles.append(block)
+
+def main():
+  global args
+  args = parser.parse_args()
+  if not args.detect_cycles:
+    print "Please select an operation to perform (eg, -c to detect cycles)"
+    parser.print_help()
+    return 1
+  if args.pickle_graph and os.path.isfile(args.pickle_graph):
+    load_graph()
+  else:
+    if args.use_stdin:
+      log("Reading files from stdin")
+      for f in sys.stdin:
+        build_graph(f.strip())
+    else:
+      log("Reading files and directories from command line")
+      if len(args.files) == 0:
+        print "Please provide files or directores for building the graph"
+        parser.print_help()
+        return 1
+      for f in args.files:
+        if os.path.isdir(f):
+          log("Building graph from files in directory: " + f)
+          build_graphs_in_dir(f)
+        else:
+          log("Building graph from file: " + f)
+          build_graph(f)
+    log("Completing graph construction (%d graph nodes)" % len(graph))
+    complete_graph()
+    if args.pickle_graph:
+      save_graph()
+  if args.detect_cycles:
+    read_ignored_cycles()
+    log("Detecting cycles containg GC roots")
+    detect_cycles()
+  if reported_error():
+    return 1
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_ptrs.cpp b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.cpp
new file mode 100644
index 0000000..8fe7b95
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.cpp
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cycle_ptrs.h"
+
+namespace WebCore {
+
+void A::trace(Visitor* visitor) {
+    visitor->trace(m_b);
+}
+
+void B::trace(Visitor* visitor) {
+    visitor->trace(m_a);
+}
+
+}
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_ptrs.flags b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.flags
new file mode 100644
index 0000000..a55c2f0
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-blink-gc-plugin -Xclang dump-graph
\ No newline at end of file
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_ptrs.h b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.h
new file mode 100644
index 0000000..a4299ba
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.h
@@ -0,0 +1,54 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CYCLE_PTRS_H_
+#define CYCLE_PTRS_H_
+
+#include "heap/stubs.h"
+
+namespace WebCore {
+
+class B;
+class C;
+class D;
+class E;
+
+// This contains a leaking cycle:
+// E -per-> A -mem-> B -ref-> C -own-> D -own-vec-> E
+
+// The traced cycle from A -> B -> A does not leak.
+
+class A : public GarbageCollected<A> {
+public:
+    virtual void trace(Visitor*);
+private:
+    Member<B> m_b;
+};
+
+class B : public GarbageCollectedFinalized<B> {
+public:
+    virtual void trace(Visitor*);
+private:
+    Member<A> m_a;
+    RefPtr<C> m_c;
+};
+
+class C : public RefCounted<C> {
+private:
+    OwnPtr<D> m_d;
+};
+
+class D {
+private:
+    Vector<OwnPtr<E> > m_es;
+};
+
+class E {
+private:
+    Persistent<A> m_a;
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_ptrs.txt b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.txt
new file mode 100644
index 0000000..39695fb
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_ptrs.txt
@@ -0,0 +1,7 @@
+
+Found a potentially leaking cycle starting from a GC root:
+./cycle_ptrs.h:49:5: WebCore::E (m_a) => WebCore::A
+./cycle_ptrs.h:26:5: WebCore::A (m_b) => WebCore::B
+./cycle_ptrs.h:34:5: WebCore::B (m_c) => WebCore::C
+./cycle_ptrs.h:39:5: WebCore::C (m_d) => WebCore::D
+./cycle_ptrs.h:44:5: WebCore::D (m_es) => WebCore::E
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_sub.cpp b/tools/clang/blink_gc_plugin/tests/cycle_sub.cpp
new file mode 100644
index 0000000..5c0d9e6
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_sub.cpp
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cycle_sub.h"
+
+namespace WebCore {
+
+void B::trace(Visitor* visitor) {
+    visitor->trace(m_c);
+    A::trace(visitor);
+}
+
+}
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_sub.flags b/tools/clang/blink_gc_plugin/tests/cycle_sub.flags
new file mode 100644
index 0000000..a55c2f0
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_sub.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-blink-gc-plugin -Xclang dump-graph
\ No newline at end of file
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_sub.h b/tools/clang/blink_gc_plugin/tests/cycle_sub.h
new file mode 100644
index 0000000..5137e49
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_sub.h
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CYCLE_SUB_H_
+#define CYCLE_SUB_H_
+
+#include "heap/stubs.h"
+
+namespace WebCore {
+
+class C;
+
+// This contains a leaking cycle:
+// C -per-> A -sub-> B -ref-> C
+
+class A : public GarbageCollectedFinalized<A> {
+public:
+    virtual void trace(Visitor*) {}
+};
+
+class B : public A {
+public:
+    virtual void trace(Visitor*);
+private:
+    RefPtr<C> m_c;
+};
+
+class C : public RefCounted<C> {
+private:
+    Persistent<A> m_a;
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_sub.txt b/tools/clang/blink_gc_plugin/tests/cycle_sub.txt
new file mode 100644
index 0000000..94227f0
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_sub.txt
@@ -0,0 +1,5 @@
+
+Found a potentially leaking cycle starting from a GC root:
+./cycle_sub.h:31:5:  WebCore::C (m_a) => WebCore::A
+./cycle_sub.h:22:11: WebCore::A (<subclass>) => WebCore::B
+./cycle_sub.h:26:5:  WebCore::B (m_c) => WebCore::C
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super.cpp b/tools/clang/blink_gc_plugin/tests/cycle_super.cpp
new file mode 100644
index 0000000..41359ed
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super.cpp
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cycle_super.h"
+
+namespace WebCore {
+
+void A::trace(Visitor* visitor) {
+    visitor->trace(m_d);
+}
+
+void B::trace(Visitor* visitor) {
+    A::trace(visitor);
+}
+
+void C::trace(Visitor* visitor) {
+    B::trace(visitor);
+}
+
+}
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super.flags b/tools/clang/blink_gc_plugin/tests/cycle_super.flags
new file mode 100644
index 0000000..a55c2f0
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-blink-gc-plugin -Xclang dump-graph
\ No newline at end of file
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super.h b/tools/clang/blink_gc_plugin/tests/cycle_super.h
new file mode 100644
index 0000000..9e0a0aa
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super.h
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CYCLE_SUPER_H_
+#define CYCLE_SUPER_H_
+
+#include "heap/stubs.h"
+
+namespace WebCore {
+
+class D;
+
+// This contains a leaking cycle:
+// D -per-> C -sup-> B -sup-> A -ref-> D
+
+class A : public GarbageCollectedFinalized<A> {
+public:
+    virtual void trace(Visitor*);
+private:
+    RefPtr<D> m_d;
+};
+
+class B : public A {
+public:
+    virtual void trace(Visitor*);
+};
+
+class C : public B {
+public:
+    virtual void trace(Visitor*);
+};
+
+class D : public RefCounted<C> {
+private:
+    Persistent<C> m_c;
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super.txt b/tools/clang/blink_gc_plugin/tests/cycle_super.txt
new file mode 100644
index 0000000..bda8be7
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super.txt
@@ -0,0 +1,4 @@
+
+Found a potentially leaking cycle starting from a GC root:
+./cycle_super.h:36:5: WebCore::D (m_c) => WebCore::C
+./cycle_super.h:21:5: WebCore::C (WebCore::B <: WebCore::A <: m_d) => WebCore::D
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super_neg.cpp b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.cpp
new file mode 100644
index 0000000..755bf25
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.cpp
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cycle_super_neg.h"
+
+namespace WebCore {
+
+void B::trace(Visitor* visitor) {
+    A::trace(visitor);
+}
+
+void D::trace(Visitor* visitor) {
+    visitor->trace(m_c);
+    A::trace(visitor);
+}
+
+}
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super_neg.flags b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.flags
new file mode 100644
index 0000000..a55c2f0
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-blink-gc-plugin -Xclang dump-graph
\ No newline at end of file
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super_neg.h b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.h
new file mode 100644
index 0000000..c43453d
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.h
@@ -0,0 +1,44 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CYCLE_SUPER_NEG_H_
+#define CYCLE_SUPER_NEG_H_
+
+#include "heap/stubs.h"
+
+namespace WebCore {
+
+class C;
+
+// The chain:
+//   C -per-> B -sup-> A -sub-> D -ref-> C
+// is not a leaking cycle, because the super-class relationship
+// should not transitively imply sub-class relationships.
+// I.e. B -/-> D
+
+class A : public GarbageCollectedFinalized<A> {
+public:
+    virtual void trace(Visitor*) {}
+};
+
+class B : public A {
+public:
+    virtual void trace(Visitor*);
+};
+
+class C : public RefCounted<C> {
+private:
+    Persistent<B> m_b;
+};
+
+class D : public A {
+public:
+    virtual void trace(Visitor*);
+private:
+    RefPtr<C> m_c;
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/cycle_super_neg.txt b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/cycle_super_neg.txt
@@ -0,0 +1 @@
+
diff --git a/tools/clang/blink_gc_plugin/tests/heap/stubs.h b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
index 6914b4a..41bf6ba 100644
--- a/tools/clang/blink_gc_plugin/tests/heap/stubs.h
+++ b/tools/clang/blink_gc_plugin/tests/heap/stubs.h
@@ -81,6 +81,12 @@
     void* operator new(size_t) = delete;                    \
     void* operator new(size_t, void*) = delete;
 
+#define ALLOW_ONLY_INLINE_ALLOCATION()    \
+    public:                               \
+    void* operator new(size_t, void*);    \
+    private:                              \
+    void* operator new(size_t) = delete;
+
 #define GC_PLUGIN_IGNORE(bug)                           \
     __attribute__((annotate("blink_gc_plugin_ignore")))
 
diff --git a/tools/clang/blink_gc_plugin/tests/inner_class.cpp b/tools/clang/blink_gc_plugin/tests/inner_class.cpp
new file mode 100644
index 0000000..49c2460
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/inner_class.cpp
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "inner_class.h"
+
+namespace WebCore {
+
+void SomeObject::InnerObject::trace(Visitor* visitor)
+{
+    // Missing: visitor->trace(m_obj);
+}
+
+}
diff --git a/tools/clang/blink_gc_plugin/tests/inner_class.h b/tools/clang/blink_gc_plugin/tests/inner_class.h
new file mode 100644
index 0000000..0f8ca70
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/inner_class.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef INNER_CLASS_H_
+#define INNER_CLASS_H_
+
+#include "heap/stubs.h"
+
+namespace WebCore {
+
+class SomeObject {
+private:
+    class InnerObject : public GarbageCollected<InnerObject> {
+    public:
+        void trace(Visitor*);
+    private:
+        Member<InnerObject> m_obj;
+    };
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/inner_class.txt b/tools/clang/blink_gc_plugin/tests/inner_class.txt
new file mode 100644
index 0000000..acdef6e
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/inner_class.txt
@@ -0,0 +1,7 @@
+inner_class.cpp:9:1: warning: [blink-gc] Class 'InnerObject' has untraced fields that require tracing.
+void SomeObject::InnerObject::trace(Visitor* visitor)
+^
+./inner_class.h:18:9: note: [blink-gc] Untraced field 'm_obj' declared here:
+        Member<InnerObject> m_obj;
+        ^
+1 warning generated.
diff --git a/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.cpp b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.cpp
new file mode 100644
index 0000000..2e8c01d
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.cpp
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "member_in_offheap_class.h"
+
+namespace WebCore {
+
+void OffHeapObject::trace(Visitor* visitor)
+{
+    visitor->trace(m_obj);
+}
+
+void PartObject::trace(Visitor* visitor)
+{
+    visitor->trace(m_obj);
+}
+
+void InlineObject::trace(Visitor* visitor)
+{
+    visitor->trace(m_obj);
+}
+
+}
diff --git a/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.h b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.h
new file mode 100644
index 0000000..d897826
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.h
@@ -0,0 +1,46 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEMBER_IN_OFFHEAP_CLASS_H_
+#define MEMBER_IN_OFFHEAP_CLASS_H_
+
+#include "heap/stubs.h"
+
+namespace WebCore {
+
+class HeapObject : public GarbageCollected<HeapObject> { };
+
+class OffHeapObject {
+public:
+    void trace(Visitor*);
+private:
+    Member<HeapObject> m_obj; // Must not contain Member.
+    Persistent<HeapVector<Member<HeapObject> > > m_objs; // OK
+};
+
+class StackObject {
+    STACK_ALLOCATED();
+private:
+    Member<HeapObject> m_obj; // OK
+};
+
+class PartObject {
+    DISALLOW_ALLOCATION();
+public:
+    void trace(Visitor*);
+private:
+    Member<HeapObject> m_obj; // OK
+};
+
+class InlineObject {
+    ALLOW_ONLY_INLINE_ALLOCATION();
+public:
+    void trace(Visitor*);
+private:
+    Member<HeapObject> m_obj; // OK
+};
+
+}
+
+#endif
diff --git a/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.txt b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.txt
new file mode 100644
index 0000000..6aada91
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/tests/member_in_offheap_class.txt
@@ -0,0 +1,8 @@
+In file included from member_in_offheap_class.cpp:5:
+./member_in_offheap_class.h:14:1: warning: [blink-gc] Class 'OffHeapObject' contains invalid fields.
+class OffHeapObject {
+^
+./member_in_offheap_class.h:18:5: note: [blink-gc] Member field 'm_obj' in unmanaged class declared here:
+    Member<HeapObject> m_obj; // Must not contain Member.
+    ^
+1 warning generated.
diff --git a/tools/clang/blink_gc_plugin/tests/stack_allocated.h b/tools/clang/blink_gc_plugin/tests/stack_allocated.h
index b1839b7..5edcde2 100644
--- a/tools/clang/blink_gc_plugin/tests/stack_allocated.h
+++ b/tools/clang/blink_gc_plugin/tests/stack_allocated.h
@@ -20,7 +20,7 @@
 class StackObject {
     STACK_ALLOCATED();
 private:
-    HeapObject* m_obj; // Does not need tracing.
+    Member<HeapObject> m_obj; // Does not need tracing.
 };
 
 class AnotherStackObject : public PartObject { // Invalid base.
diff --git a/tools/clang/blink_gc_plugin/tests/test.sh b/tools/clang/blink_gc_plugin/tests/test.sh
index cb3b5c0..d337bca 100755
--- a/tools/clang/blink_gc_plugin/tests/test.sh
+++ b/tools/clang/blink_gc_plugin/tests/test.sh
@@ -30,6 +30,10 @@
   local output="$("${CLANG_DIR}"/bin/clang -c -Wno-c++11-extensions \
       -Xclang -load -Xclang "${CLANG_DIR}"/lib/lib${LIBNAME}.${LIB} \
       -Xclang -add-plugin -Xclang blink-gc-plugin ${flags} ${1} 2>&1)"
+  local json="${input%cpp}graph.json"
+  if [ -f "$json" ]; then
+    output="$(python ../process-graph.py -c ${json} 2>&1)"
+  fi
   local diffout="$(echo "${output}" | diff - "${2}")"
   if [ "${diffout}" = "" ]; then
     echo "PASS: ${1}"
diff --git a/tools/clang/plugins/ChromeClassTester.cpp b/tools/clang/plugins/ChromeClassTester.cpp
index 1fbd42a..5ce04e5 100644
--- a/tools/clang/plugins/ChromeClassTester.cpp
+++ b/tools/clang/plugins/ChromeClassTester.cpp
@@ -110,11 +110,11 @@
   std::string err;
   err = "[chromium-style] ";
   err += raw_error;
-  DiagnosticsEngine::Level level =
+  DiagnosticIDs::Level level =
       diagnostic().getWarningsAsErrors() ?
-      DiagnosticsEngine::Error :
-      DiagnosticsEngine::Warning;
-  unsigned id = diagnostic().getCustomDiagID(level, err);
+      DiagnosticIDs::Error :
+      DiagnosticIDs::Warning;
+  unsigned id = diagnostic().getDiagnosticIDs()->getCustomDiagID(level, err);
   DiagnosticBuilder builder = diagnostic().Report(full, id);
 }
 
diff --git a/tools/clang/plugins/FindBadConstructs.cpp b/tools/clang/plugins/FindBadConstructs.cpp
index 1b37cd0..4b74fbe 100644
--- a/tools/clang/plugins/FindBadConstructs.cpp
+++ b/tools/clang/plugins/FindBadConstructs.cpp
@@ -83,11 +83,13 @@
 struct FindBadConstructsOptions {
   FindBadConstructsOptions() : check_base_classes(false),
                                check_virtuals_in_implementations(true),
-                               check_weak_ptr_factory_order(false) {
+                               check_weak_ptr_factory_order(false),
+                               check_enum_last_value(false) {
   }
   bool check_base_classes;
   bool check_virtuals_in_implementations;
   bool check_weak_ptr_factory_order;
+  bool check_enum_last_value;
 };
 
 // Searches for constructs that we know we don't want in the Chromium code base.
@@ -150,16 +152,29 @@
 
   virtual void CheckChromeEnum(SourceLocation enum_location,
                                EnumDecl* enum_decl) {
+    if (!options_.check_enum_last_value)
+      return;
+
     bool got_one = false;
+    bool is_signed = false;
     llvm::APSInt max_so_far;
     EnumDecl::enumerator_iterator iter;
     for (iter = enum_decl->enumerator_begin();
          iter != enum_decl->enumerator_end(); ++iter) {
+          llvm::APSInt current_value = iter->getInitVal();
       if (!got_one) {
-        max_so_far = iter->getInitVal();
+        max_so_far = current_value;
+        is_signed = current_value.isSigned();
         got_one = true;
-      } else if (iter->getInitVal() > max_so_far)
-        max_so_far = iter->getInitVal();
+      } else {
+        if (is_signed != current_value.isSigned()) {
+          // This only happens in some cases when compiling C (not C++) files,
+          // so it is OK to bail out here.
+          return;
+        }
+        if (current_value > max_so_far)
+          max_so_far = current_value;
+      }
     }
     for (iter = enum_decl->enumerator_begin();
          iter != enum_decl->enumerator_end(); ++iter) {
@@ -741,6 +756,10 @@
       } else if (args[i] == "check-weak-ptr-factory-order") {
         // TODO(dmichael): Remove this once http://crbug.com/303818 is fixed.
         options_.check_weak_ptr_factory_order = true;
+      } else if (args[i] == "check-enum-last-value") {
+        // TODO(tsepez): Enable this by default once http://crbug.com/356815
+        // and http://crbug.com/356816 are fixed.
+        options_.check_enum_last_value = true;
       } else {
         parsed = false;
         llvm::errs() << "Unknown clang plugin argument: " << args[i] << "\n";
diff --git a/tools/clang/plugins/tests/enum_last_value.cpp b/tools/clang/plugins/tests/enum_last_value.cpp
new file mode 100644
index 0000000..c189f23
--- /dev/null
+++ b/tools/clang/plugins/tests/enum_last_value.cpp
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// We warn when xxxLAST constants aren't last.
+enum BadOne {
+  kBadOneInvalid = -1,
+  kBadOneRed,
+  kBadOneGreen,
+  kBadOneBlue,
+  kBadOneLast = kBadOneGreen
+};
+
+// We warn when xxx_LAST constants aren't last.
+enum BadTwo {
+  BAD_TWO_INVALID,
+  BAD_TWO_RED,
+  BAD_TWO_GREEN,
+  BAD_TWO_BLUE = 0xfffffffc,
+  BAD_TWO_LAST = BAD_TWO_GREEN
+};
+
+// We don't warn when xxxLAST constants are last.
+enum GoodOne {
+  kGoodOneInvalid = -1,
+  kGoodOneRed,
+  kGoodOneGreen,
+  kGoodOneBlue,
+  kGoodOneLast = kGoodOneBlue
+};
+
+// We don't warn when xxx_LAST constants are last.
+enum GoodTwo {
+  GOOD_TWO_INVALID,
+  GOOD_TWO_RED,
+  GOOD_TWO_GREEN,
+  GOOD_TWO_BLUE = 0xfffffffc,
+  GOOD_TWO_LAST = GOOD_TWO_BLUE
+};
diff --git a/tools/clang/plugins/tests/enum_last_value.flags b/tools/clang/plugins/tests/enum_last_value.flags
new file mode 100644
index 0000000..ee2ef7e
--- /dev/null
+++ b/tools/clang/plugins/tests/enum_last_value.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-find-bad-constructs -Xclang check-enum-last-value
diff --git a/tools/clang/plugins/tests/enum_last_value.txt b/tools/clang/plugins/tests/enum_last_value.txt
new file mode 100644
index 0000000..2d9e51d
--- /dev/null
+++ b/tools/clang/plugins/tests/enum_last_value.txt
@@ -0,0 +1,7 @@
+enum_last_value.cpp:11:3: warning: [chromium-style] _LAST/Last constants of enum types must have the maximal value for any constant of that type.
+  kBadOneLast = kBadOneGreen
+  ^
+enum_last_value.cpp:20:3: warning: [chromium-style] _LAST/Last constants of enum types must have the maximal value for any constant of that type.
+  BAD_TWO_LAST = BAD_TWO_GREEN
+  ^
+2 warnings generated.
diff --git a/tools/clang/plugins/tests/enum_last_value_from_c.c b/tools/clang/plugins/tests/enum_last_value_from_c.c
new file mode 100644
index 0000000..7fecbc0
--- /dev/null
+++ b/tools/clang/plugins/tests/enum_last_value_from_c.c
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// We warn when xxxLAST constants aren't last.
+enum BadOne {
+  kBadOneInvalid = -1,
+  kBadOneRed,
+  kBadOneGreen,
+  kBadOneBlue,
+  kBadOneLast = kBadOneGreen
+};
+
+// We don't handle this case when called from C due to sign mismatch issues.
+// No matter; we're not looking for this issue outside of C++.
+enum FailOne {
+  FAIL_ONE_INVALID,
+  FAIL_ONE_RED,
+  FAIL_ONE_GREEN,
+  FAIL_ONE_BLUE = 0xfffffffc,
+  FAIL_ONE_LAST = FAIL_ONE_GREEN
+};
+
+// We don't warn when xxxLAST constants are last.
+enum GoodOne {
+  kGoodOneInvalid = -1,
+  kGoodOneRed,
+  kGoodOneGreen,
+  kGoodOneBlue,
+  kGoodOneLast = kGoodOneBlue
+};
+
+// We don't warn when xxx_LAST constants are last.
+enum GoodTwo {
+  GOOD_TWO_INVALID,
+  GOOD_TWO_RED,
+  GOOD_TWO_GREEN,
+  GOOD_TWO_BLUE = 0xfffffffc,
+  GOOD_TWO_LAST = GOOD_TWO_BLUE
+};
diff --git a/tools/clang/plugins/tests/enum_last_value_from_c.flags b/tools/clang/plugins/tests/enum_last_value_from_c.flags
new file mode 100644
index 0000000..ee2ef7e
--- /dev/null
+++ b/tools/clang/plugins/tests/enum_last_value_from_c.flags
@@ -0,0 +1 @@
+-Xclang -plugin-arg-find-bad-constructs -Xclang check-enum-last-value
diff --git a/tools/clang/plugins/tests/enum_last_value_from_c.txt b/tools/clang/plugins/tests/enum_last_value_from_c.txt
new file mode 100644
index 0000000..3aa1d16
--- /dev/null
+++ b/tools/clang/plugins/tests/enum_last_value_from_c.txt
@@ -0,0 +1,4 @@
+enum_last_value_from_c.c:11:3: warning: [chromium-style] _LAST/Last constants of enum types must have the maximal value for any constant of that type.
+  kBadOneLast = kBadOneGreen
+  ^
+1 warning generated.
diff --git a/tools/clang/plugins/tests/test.sh b/tools/clang/plugins/tests/test.sh
index cf3acc3..1a27f48 100755
--- a/tools/clang/plugins/tests/test.sh
+++ b/tools/clang/plugins/tests/test.sh
@@ -71,6 +71,10 @@
   do_testcase "${input}" "${input%cpp}txt" "${input%cpp}flags"
 done
 
+for input in *.c; do
+  do_testcase "${input}" "${input%c}txt" "${input%c}flags"
+done
+
 if [[ "${failed_any_test}" ]]; then
   exit ${E_FAILEDTEST}
 fi
diff --git a/tools/clang/scripts/blink_gc_plugin_flags.sh b/tools/clang/scripts/blink_gc_plugin_flags.sh
index 7d41c97..25c5872 100755
--- a/tools/clang/scripts/blink_gc_plugin_flags.sh
+++ b/tools/clang/scripts/blink_gc_plugin_flags.sh
@@ -19,9 +19,13 @@
     | cut -d ' ' -f 3)
 
 FLAGS=""
-if [[ "$1" = "enable-oilpan=1" ]]; then
+for arg in "$@"; do
+  if [[ "$arg" = "enable-oilpan=1" ]]; then
     FLAGS="$FLAGS -Xclang -plugin-arg-blink-gc-plugin -Xclang enable-oilpan"
-fi
+  elif [[ "$arg" = "dump-graph=1" ]]; then
+    FLAGS="$FLAGS -Xclang -plugin-arg-blink-gc-plugin -Xclang dump-graph"
+  fi
+done
 
 echo -Xclang -load -Xclang $CLANG_LIB_PATH/lib$LIBNAME.$LIBSUFFIX \
   -Xclang -add-plugin -Xclang blink-gc-plugin $FLAGS
diff --git a/tools/clang/scripts/package.sh b/tools/clang/scripts/package.sh
index 504ec2b..ba9d744 100755
--- a/tools/clang/scripts/package.sh
+++ b/tools/clang/scripts/package.sh
@@ -48,6 +48,7 @@
 THIS_DIR="$(dirname "${0}")"
 LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
 LLVM_BOOTSTRAP_DIR="${THIS_DIR}/../../../third_party/llvm-bootstrap"
+LLVM_BOOTSTRAP_INSTALL_DIR="${LLVM_DIR}/../llvm-bootstrap-install"
 LLVM_BUILD_DIR="${THIS_DIR}/../../../third_party/llvm-build"
 LLVM_BIN_DIR="${LLVM_BUILD_DIR}/Release+Asserts/bin"
 LLVM_LIB_DIR="${LLVM_BUILD_DIR}/Release+Asserts/lib"
@@ -68,6 +69,7 @@
 
 # Do a clobber build.
 rm -rf "${LLVM_BOOTSTRAP_DIR}"
+rm -rf "${LLVM_BOOTSTRAP_INSTALL_DIR}"
 rm -rf "${LLVM_BUILD_DIR}"
 extra_flags=
 if [[ -n "${gcc_toolchain}" ]]; then
diff --git a/tools/clang/scripts/plugin_flags.sh b/tools/clang/scripts/plugin_flags.sh
index 320fd16..ac941d7 100755
--- a/tools/clang/scripts/plugin_flags.sh
+++ b/tools/clang/scripts/plugin_flags.sh
@@ -17,6 +17,4 @@
 fi
 
 echo -Xclang -load -Xclang $CLANG_LIB_PATH/libFindBadConstructs.$LIBSUFFIX \
-  -Xclang -add-plugin -Xclang find-bad-constructs \
-  -Xclang -plugin-arg-find-bad-constructs \
-  -Xclang check-url-directory
+  -Xclang -add-plugin -Xclang find-bad-constructs
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 162b5eb..a311f88 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -186,6 +186,10 @@
     print 'Skipping Clang update (clang=1 was not set in GYP_DEFINES).'
     return 0
 
+  if re.search(r'\b(make_clang_dir)=\b', os.environ.get('GYP_DEFINES', '')):
+    print 'Skipping Clang update (make_clang_dir= was set in GYP_DEFINES).'
+    return 0
+
   return UpdateClang()
 
 
diff --git a/tools/clang/scripts/update.sh b/tools/clang/scripts/update.sh
index 3a70e74..113905c 100755
--- a/tools/clang/scripts/update.sh
+++ b/tools/clang/scripts/update.sh
@@ -8,15 +8,17 @@
 # Do NOT CHANGE this if you don't know what you're doing -- see
 # https://code.google.com/p/chromium/wiki/UpdatingClang
 # Reverting problematic clang rolls is safe, though.
-CLANG_REVISION=198389
+CLANG_REVISION=202554
 
 THIS_DIR="$(dirname "${0}")"
 LLVM_DIR="${THIS_DIR}/../../../third_party/llvm"
 LLVM_BUILD_DIR="${LLVM_DIR}/../llvm-build"
 LLVM_BOOTSTRAP_DIR="${LLVM_DIR}/../llvm-bootstrap"
+LLVM_BOOTSTRAP_INSTALL_DIR="${LLVM_DIR}/../llvm-bootstrap-install"
 CLANG_DIR="${LLVM_DIR}/tools/clang"
 CLANG_TOOLS_EXTRA_DIR="${CLANG_DIR}/tools/extra"
 COMPILER_RT_DIR="${LLVM_DIR}/projects/compiler-rt"
+LIBCXX_DIR="${LLVM_DIR}/projects/libcxx"
 ANDROID_NDK_DIR="${LLVM_DIR}/../android_tools/ndk"
 STAMP_FILE="${LLVM_BUILD_DIR}/cr_build_revision"
 
@@ -43,8 +45,8 @@
 OS="$(uname -s)"
 
 # Parse command line options.
+if_needed=
 force_local_build=
-mac_only=
 run_tests=
 bootstrap=
 with_android=yes
@@ -65,12 +67,12 @@
     --bootstrap)
       bootstrap=yes
       ;;
+    --if-needed)
+      if_needed=yes
+      ;;
     --force-local-build)
       force_local_build=yes
       ;;
-    --mac-only)
-      mac_only=yes
-      ;;
     --run-tests)
       run_tests=yes
       ;;
@@ -101,10 +103,10 @@
       ;;
 
     --help)
-      echo "usage: $0 [--force-local-build] [--mac-only] [--run-tests] "
+      echo "usage: $0 [--force-local-build] [--if-needed] [--run-tests] "
       echo "--bootstrap: First build clang with CC, then with itself."
       echo "--force-local-build: Don't try to download prebuilt binaries."
-      echo "--mac-only: Do initial download only on Mac systems."
+      echo "--if-needed: Download clang only if the script thinks it is needed."
       echo "--run-tests: Run tests after building. Only for local builds."
       echo "--without-android: Don't build ASan Android runtime library."
       echo "--with-chrome-tools: Select which chrome tools to build." \
@@ -125,14 +127,21 @@
   shift
 done
 
-# --mac-only prevents the initial download on non-mac systems, but if clang has
-# already been downloaded in the past, this script keeps it up to date even if
-# --mac-only is passed in and the system isn't a mac. People who don't like this
-# can just delete their third_party/llvm-build directory.
-if [[ -n "$mac_only" ]] && [[ "${OS}" != "Darwin" ]] &&
-    [[ ! ( "$GYP_DEFINES" =~ .*(clang|tsan|asan|lsan|msan)=1.* ) ]] &&
-    ! [[ -d "${LLVM_BUILD_DIR}" ]]; then
-  exit 0
+if [[ -n "$if_needed" ]]; then
+  if [[ "${OS}" == "Darwin" ]]; then
+    # clang is used on Mac.
+    true
+  elif [[ "$GYP_DEFINES" =~ .*(clang|tsan|asan|lsan|msan)=1.* ]]; then
+    # clang requested via $GYP_DEFINES.
+    true
+  elif [[ -d "${LLVM_BUILD_DIR}" ]]; then
+    # clang previously downloaded, remove third_party/llvm-build to prevent
+    # updating.
+    true
+  else
+    # clang wasn't needed, not doing anything.
+    exit 0
+  fi
 fi
 
 # Xcode and clang don't get along when predictive compilation is enabled.
@@ -259,6 +268,673 @@
 svn co --force "${LLVM_REPO_URL}/compiler-rt/trunk@${CLANG_REVISION}" \
                "${COMPILER_RT_DIR}"
 
+# clang needs a libc++ checkout, else -stdlib=libc++ won't find includes
+# (i.e. this is needed for bootstrap builds).
+if [ "${OS}" = "Darwin" ]; then
+  echo Getting libc++ r"${CLANG_REVISION}" in "${LIBCXX_DIR}"
+  svn co --force "${LLVM_REPO_URL}/libcxx/trunk@${CLANG_REVISION}" \
+                 "${LIBCXX_DIR}"
+fi
+
+# Apply patch for test failing with --disable-pthreads (llvm.org/PR11974)
+cd "${CLANG_DIR}"
+svn revert test/Index/crash-recovery-modules.m
+cat << 'EOF' |
+--- third_party/llvm/tools/clang/test/Index/crash-recovery-modules.m	(revision 202554)
++++ third_party/llvm/tools/clang/test/Index/crash-recovery-modules.m	(working copy)
+@@ -12,6 +12,8 @@
+ 
+ // REQUIRES: crash-recovery
+ // REQUIRES: shell
++// XFAIL: *
++//    (PR11974)
+ 
+ @import Crash;
+EOF
+patch -p4
+cd -
+
+# Temporary patches to make build on android work.
+# Merge LLVM r202793, r203601
+cd "${COMPILER_RT_DIR}"
+svn revert lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+svn revert make/platform/clang_linux.mk
+cat << 'EOF' |
+Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc
+===================================================================
+--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc (original)
++++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_symbolizer_posix_libcdep.cc Tue Mar 11 15:23:59 2014
+@@ -32,18 +32,10 @@
+ // C++ demangling function, as required by Itanium C++ ABI. This is weak,
+ // because we do not require a C++ ABI library to be linked to a program
+ // using sanitizers; if it's not present, we'll just use the mangled name.
+-//
+-// On Android, this is not weak, because we are using shared runtime library
+-// AND static libstdc++, and there is no good way to conditionally export
+-// __cxa_demangle. By making this a non-weak symbol, we statically link
+-// __cxa_demangle into ASan runtime library.
+ namespace __cxxabiv1 {
+-  extern "C"
+-#if !SANITIZER_ANDROID
+-  SANITIZER_WEAK_ATTRIBUTE
+-#endif
+-  char *__cxa_demangle(const char *mangled, char *buffer, size_t *length,
+-                       int *status);
++  extern "C" SANITIZER_WEAK_ATTRIBUTE
++  char *__cxa_demangle(const char *mangled, char *buffer,
++                                  size_t *length, int *status);
+ }
+
+ namespace __sanitizer {
+@@ -55,7 +47,7 @@ static const char *DemangleCXXABI(const
+   // own demangler (libc++abi's implementation could be adapted so that
+   // it does not allocate). For now, we just call it anyway, and we leak
+   // the returned value.
+-  if (SANITIZER_ANDROID || &__cxxabiv1::__cxa_demangle)
++  if (__cxxabiv1::__cxa_demangle)
+     if (const char *demangled_name =
+           __cxxabiv1::__cxa_demangle(name, 0, 0, 0))
+       return demangled_name;
+
+Index: compiler-rt/trunk/make/platform/clang_linux.mk
+===================================================================
+--- compiler-rt/trunk/make/platform/clang_linux.mk (original)
++++ compiler-rt/trunk/make/platform/clang_linux.mk Tue Mar  4 01:17:38 2014
+@@ -110,9 +110,10 @@ ANDROID_COMMON_FLAGS := -target arm-linu
+ 	--sysroot=$(LLVM_ANDROID_TOOLCHAIN_DIR)/sysroot \
+ 	-B$(LLVM_ANDROID_TOOLCHAIN_DIR)
+ CFLAGS.asan-arm-android := $(CFLAGS) -fPIC -fno-builtin \
+-	$(ANDROID_COMMON_FLAGS) -fno-rtti
++	$(ANDROID_COMMON_FLAGS) -fno-rtti \
++	-I$(ProjSrcRoot)/third_party/android/include
+ LDFLAGS.asan-arm-android := $(LDFLAGS) $(ANDROID_COMMON_FLAGS) -ldl -lm -llog \
+-	-Wl,-soname=libclang_rt.asan-arm-android.so -Wl,-z,defs
++	-lstdc++ -Wl,-soname=libclang_rt.asan-arm-android.so -Wl,-z,defs
+ 
+ # Use our stub SDK as the sysroot to support more portable building. For now we
+ # just do this for the core module, because the stub SDK doesn't have
+EOF
+patch -p2
+cd -
+
+# Merge LLVM r203635
+cd "${LLVM_DIR}"
+svn revert lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
+svn revert test/CodeGen/ARM/debug-frame-large-stack.ll
+svn revert test/CodeGen/ARM/debug-frame-vararg.ll
+svn revert test/CodeGen/ARM/debug-frame.ll
+cat << 'EOF' |
+Index: lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
+===================================================================
+--- lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
++++ lib/Target/ARM/MCTargetDesc/ARMMCAsmInfo.cpp
+@@ -54,4 +54,7 @@
+   UseParensForSymbolVariant = true;
+ 
+   UseIntegratedAssembler = true;
++
++  // gas doesn't handle VFP register names in cfi directives.
++  DwarfRegNumForCFI = true;
+ }
+Index: test/CodeGen/ARM/debug-frame-large-stack.ll
+===================================================================
+--- test/CodeGen/ARM/debug-frame-large-stack.ll
++++ test/CodeGen/ARM/debug-frame-large-stack.ll
+@@ -42,8 +42,8 @@
+ ; CHECK-ARM: .cfi_startproc
+ ; CHECK-ARM: push    {r4, r5}
+ ; CHECK-ARM: .cfi_def_cfa_offset 8
+-; CHECK-ARM: .cfi_offset r5, -4
+-; CHECK-ARM: .cfi_offset r4, -8
++; CHECK-ARM: .cfi_offset 5, -4
++; CHECK-ARM: .cfi_offset 4, -8
+ ; CHECK-ARM: sub    sp, sp, #72
+ ; CHECK-ARM: sub    sp, sp, #4096
+ ; CHECK-ARM: .cfi_def_cfa_offset 4176
+@@ -54,7 +54,7 @@
+ ; CHECK-ARM-FP_ELIM: push    {r4, r5}
+ ; CHECK-ARM-FP_ELIM: .cfi_def_cfa_offset 8
+ ; CHECK-ARM-FP_ELIM: .cfi_offset 54, -4
+-; CHECK-ARM-FP_ELIM: .cfi_offset r4, -8
++; CHECK-ARM-FP_ELIM: .cfi_offset 4, -8
+ ; CHECK-ARM-FP_ELIM: sub    sp, sp, #72
+ ; CHECK-ARM-FP_ELIM: sub    sp, sp, #4096
+ ; CHECK-ARM-FP_ELIM: .cfi_def_cfa_offset 4176
+@@ -73,11 +73,11 @@
+ ; CHECK-ARM: .cfi_startproc
+ ; CHECK-ARM: push    {r4, r5, r11}
+ ; CHECK-ARM: .cfi_def_cfa_offset 12
+-; CHECK-ARM: .cfi_offset r11, -4
+-; CHECK-ARM: .cfi_offset r5, -8
+-; CHECK-ARM: .cfi_offset r4, -12
++; CHECK-ARM: .cfi_offset 11, -4
++; CHECK-ARM: .cfi_offset 5, -8
++; CHECK-ARM: .cfi_offset 4, -12
+ ; CHECK-ARM: add    r11, sp, #8
+-; CHECK-ARM: .cfi_def_cfa r11, 4
++; CHECK-ARM: .cfi_def_cfa 11, 4
+ ; CHECK-ARM: sub    sp, sp, #20
+ ; CHECK-ARM: sub    sp, sp, #805306368
+ ; CHECK-ARM: bic    sp, sp, #15
+@@ -87,11 +87,11 @@
+ ; CHECK-ARM-FP-ELIM: .cfi_startproc
+ ; CHECK-ARM-FP-ELIM: push    {r4, r5, r11}
+ ; CHECK-ARM-FP-ELIM: .cfi_def_cfa_offset 12
+-; CHECK-ARM-FP-ELIM: .cfi_offset r11, -4
+-; CHECK-ARM-FP-ELIM: .cfi_offset r5, -8
+-; CHECK-ARM-FP-ELIM: .cfi_offset r4, -12
++; CHECK-ARM-FP-ELIM: .cfi_offset 11, -4
++; CHECK-ARM-FP-ELIM: .cfi_offset 5, -8
++; CHECK-ARM-FP-ELIM: .cfi_offset 4, -12
+ ; CHECK-ARM-FP-ELIM: add    r11, sp, #8
+-; CHECK-ARM-FP-ELIM: .cfi_def_cfa r11, 4
++; CHECK-ARM-FP-ELIM: .cfi_def_cfa 11, 4
+ ; CHECK-ARM-FP-ELIM: sub    sp, sp, #20
+ ; CHECK-ARM-FP-ELIM: sub    sp, sp, #805306368
+ ; CHECK-ARM-FP-ELIM: bic    sp, sp, #15
+Index: test/CodeGen/ARM/debug-frame-vararg.ll
+===================================================================
+--- test/CodeGen/ARM/debug-frame-vararg.ll
++++ test/CodeGen/ARM/debug-frame-vararg.ll
+@@ -66,8 +66,8 @@
+ ; CHECK-FP: .cfi_def_cfa_offset 16
+ ; CHECK-FP: push   {r4, lr}
+ ; CHECK-FP: .cfi_def_cfa_offset 24
+-; CHECK-FP: .cfi_offset lr, -20
+-; CHECK-FP: .cfi_offset r4, -24
++; CHECK-FP: .cfi_offset 14, -20
++; CHECK-FP: .cfi_offset 4, -24
+ ; CHECK-FP: sub    sp, sp, #8
+ ; CHECK-FP: .cfi_def_cfa_offset 32
+ 
+@@ -77,22 +77,22 @@
+ ; CHECK-FP-ELIM: .cfi_def_cfa_offset 16
+ ; CHECK-FP-ELIM: push   {r4, r11, lr}
+ ; CHECK-FP-ELIM: .cfi_def_cfa_offset 28
+-; CHECK-FP-ELIM: .cfi_offset lr, -20
+-; CHECK-FP-ELIM: .cfi_offset r11, -24
+-; CHECK-FP-ELIM: .cfi_offset r4, -28
++; CHECK-FP-ELIM: .cfi_offset 14, -20
++; CHECK-FP-ELIM: .cfi_offset 11, -24
++; CHECK-FP-ELIM: .cfi_offset 4, -28
+ ; CHECK-FP-ELIM: add    r11, sp, #4
+-; CHECK-FP-ELIM: .cfi_def_cfa r11, 24
++; CHECK-FP-ELIM: .cfi_def_cfa 11, 24
+ 
+ ; CHECK-THUMB-FP-LABEL: sum
+ ; CHECK-THUMB-FP: .cfi_startproc
+ ; CHECK-THUMB-FP: sub    sp, #16
+ ; CHECK-THUMB-FP: .cfi_def_cfa_offset 16
+ ; CHECK-THUMB-FP: push   {r4, r5, r7, lr}
+ ; CHECK-THUMB-FP: .cfi_def_cfa_offset 32
+-; CHECK-THUMB-FP: .cfi_offset lr, -20
+-; CHECK-THUMB-FP: .cfi_offset r7, -24
+-; CHECK-THUMB-FP: .cfi_offset r5, -28
+-; CHECK-THUMB-FP: .cfi_offset r4, -32
++; CHECK-THUMB-FP: .cfi_offset 14, -20
++; CHECK-THUMB-FP: .cfi_offset 7, -24
++; CHECK-THUMB-FP: .cfi_offset 5, -28
++; CHECK-THUMB-FP: .cfi_offset 4, -32
+ ; CHECK-THUMB-FP: sub    sp, #8
+ ; CHECK-THUMB-FP: .cfi_def_cfa_offset 40
+ 
+@@ -102,12 +102,12 @@
+ ; CHECK-THUMB-FP-ELIM: .cfi_def_cfa_offset 16
+ ; CHECK-THUMB-FP-ELIM: push   {r4, r5, r7, lr}
+ ; CHECK-THUMB-FP-ELIM: .cfi_def_cfa_offset 32
+-; CHECK-THUMB-FP-ELIM: .cfi_offset lr, -20
+-; CHECK-THUMB-FP-ELIM: .cfi_offset r7, -24
+-; CHECK-THUMB-FP-ELIM: .cfi_offset r5, -28
+-; CHECK-THUMB-FP-ELIM: .cfi_offset r4, -32
++; CHECK-THUMB-FP-ELIM: .cfi_offset 14, -20
++; CHECK-THUMB-FP-ELIM: .cfi_offset 7, -24
++; CHECK-THUMB-FP-ELIM: .cfi_offset 5, -28
++; CHECK-THUMB-FP-ELIM: .cfi_offset 4, -32
+ ; CHECK-THUMB-FP-ELIM: add    r7, sp, #8
+-; CHECK-THUMB-FP-ELIM: .cfi_def_cfa r7, 24
++; CHECK-THUMB-FP-ELIM: .cfi_def_cfa 7, 24
+ 
+ define i32 @sum(i32 %count, ...) {
+ entry:
+Index: test/CodeGen/ARM/debug-frame.ll
+===================================================================
+--- test/CodeGen/ARM/debug-frame.ll
++++ test/CodeGen/ARM/debug-frame.ll
+@@ -163,131 +163,131 @@
+ ; CHECK-FP:   .cfi_startproc
+ ; CHECK-FP:   push   {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+ ; CHECK-FP:   .cfi_def_cfa_offset 36
+-; CHECK-FP:   .cfi_offset lr, -4
+-; CHECK-FP:   .cfi_offset r11, -8
+-; CHECK-FP:   .cfi_offset r10, -12
+-; CHECK-FP:   .cfi_offset r9, -16
+-; CHECK-FP:   .cfi_offset r8, -20
+-; CHECK-FP:   .cfi_offset r7, -24
+-; CHECK-FP:   .cfi_offset r6, -28
+-; CHECK-FP:   .cfi_offset r5, -32
+-; CHECK-FP:   .cfi_offset r4, -36
++; CHECK-FP:   .cfi_offset 14, -4
++; CHECK-FP:   .cfi_offset 11, -8
++; CHECK-FP:   .cfi_offset 10, -12
++; CHECK-FP:   .cfi_offset 9, -16
++; CHECK-FP:   .cfi_offset 8, -20
++; CHECK-FP:   .cfi_offset 7, -24
++; CHECK-FP:   .cfi_offset 6, -28
++; CHECK-FP:   .cfi_offset 5, -32
++; CHECK-FP:   .cfi_offset 4, -36
+ ; CHECK-FP:   add    r11, sp, #28
+-; CHECK-FP:   .cfi_def_cfa r11, 8
++; CHECK-FP:   .cfi_def_cfa 11, 8
+ ; CHECK-FP:   sub    sp, sp, #28
+ ; CHECK-FP:   .cfi_endproc
+ 
+ ; CHECK-FP-ELIM-LABEL: _Z4testiiiiiddddd:
+ ; CHECK-FP-ELIM:   .cfi_startproc
+ ; CHECK-FP-ELIM:   push  {r4, r5, r6, r7, r8, r9, r10, r11, lr}
+ ; CHECK-FP-ELIM:   .cfi_def_cfa_offset 36
+-; CHECK-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-FP-ELIM:   .cfi_offset r11, -8
+-; CHECK-FP-ELIM:   .cfi_offset r10, -12
+-; CHECK-FP-ELIM:   .cfi_offset r9, -16
+-; CHECK-FP-ELIM:   .cfi_offset r8, -20
+-; CHECK-FP-ELIM:   .cfi_offset r7, -24
+-; CHECK-FP-ELIM:   .cfi_offset r6, -28
+-; CHECK-FP-ELIM:   .cfi_offset r5, -32
+-; CHECK-FP-ELIM:   .cfi_offset r4, -36
++; CHECK-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-FP-ELIM:   .cfi_offset 11, -8
++; CHECK-FP-ELIM:   .cfi_offset 10, -12
++; CHECK-FP-ELIM:   .cfi_offset 9, -16
++; CHECK-FP-ELIM:   .cfi_offset 8, -20
++; CHECK-FP-ELIM:   .cfi_offset 7, -24
++; CHECK-FP-ELIM:   .cfi_offset 6, -28
++; CHECK-FP-ELIM:   .cfi_offset 5, -32
++; CHECK-FP-ELIM:   .cfi_offset 4, -36
+ ; CHECK-FP-ELIM:   sub   sp, sp, #28
+ ; CHECK-FP-ELIM:   .cfi_def_cfa_offset 64
+ ; CHECK-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd:
+ ; CHECK-V7-FP:   .cfi_startproc
+ ; CHECK-V7-FP:   push   {r4, r11, lr}
+ ; CHECK-V7-FP:   .cfi_def_cfa_offset 12
+-; CHECK-V7-FP:   .cfi_offset lr, -4
+-; CHECK-V7-FP:   .cfi_offset r11, -8
+-; CHECK-V7-FP:   .cfi_offset r4, -12
++; CHECK-V7-FP:   .cfi_offset 14, -4
++; CHECK-V7-FP:   .cfi_offset 11, -8
++; CHECK-V7-FP:   .cfi_offset 4, -12
+ ; CHECK-V7-FP:   add    r11, sp, #4
+-; CHECK-V7-FP:   .cfi_def_cfa r11, 8
++; CHECK-V7-FP:   .cfi_def_cfa 11, 8
+ ; CHECK-V7-FP:   vpush  {d8, d9, d10, d11, d12}
+-; CHECK-V7-FP:   .cfi_offset d12, -24
+-; CHECK-V7-FP:   .cfi_offset d11, -32
+-; CHECK-V7-FP:   .cfi_offset d10, -40
+-; CHECK-V7-FP:   .cfi_offset d9, -48
+-; CHECK-V7-FP:   .cfi_offset d8, -56
++; CHECK-V7-FP:   .cfi_offset 268, -24
++; CHECK-V7-FP:   .cfi_offset 267, -32
++; CHECK-V7-FP:   .cfi_offset 266, -40
++; CHECK-V7-FP:   .cfi_offset 265, -48
++; CHECK-V7-FP:   .cfi_offset 264, -56
+ ; CHECK-V7-FP:   sub    sp, sp, #28
+ ; CHECK-V7-FP:   .cfi_endproc
+ 
+ ; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd:
+ ; CHECK-V7-FP-ELIM:   .cfi_startproc
+ ; CHECK-V7-FP-ELIM:   push   {r4, lr}
+ ; CHECK-V7-FP-ELIM:   .cfi_def_cfa_offset 8
+-; CHECK-V7-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-V7-FP-ELIM:   .cfi_offset r4, -8
++; CHECK-V7-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-V7-FP-ELIM:   .cfi_offset 4, -8
+ ; CHECK-V7-FP-ELIM:   vpush  {d8, d9, d10, d11, d12}
+ ; CHECK-V7-FP-ELIM:   .cfi_def_cfa_offset 48
+-; CHECK-V7-FP-ELIM:   .cfi_offset d12, -16
+-; CHECK-V7-FP-ELIM:   .cfi_offset d11, -24
+-; CHECK-V7-FP-ELIM:   .cfi_offset d10, -32
+-; CHECK-V7-FP-ELIM:   .cfi_offset d9, -40
+-; CHECK-V7-FP-ELIM:   .cfi_offset d8, -48
++; CHECK-V7-FP-ELIM:   .cfi_offset 268, -16
++; CHECK-V7-FP-ELIM:   .cfi_offset 267, -24
++; CHECK-V7-FP-ELIM:   .cfi_offset 266, -32
++; CHECK-V7-FP-ELIM:   .cfi_offset 265, -40
++; CHECK-V7-FP-ELIM:   .cfi_offset 264, -48
+ ; CHECK-V7-FP-ELIM:   sub    sp, sp, #24
+ ; CHECK-V7-FP-ELIM:   .cfi_def_cfa_offset 72
+ ; CHECK-V7-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-THUMB-FP-LABEL: _Z4testiiiiiddddd:
+ ; CHECK-THUMB-FP:   .cfi_startproc
+ ; CHECK-THUMB-FP:   push   {r4, r5, r6, r7, lr}
+ ; CHECK-THUMB-FP:   .cfi_def_cfa_offset 20
+-; CHECK-THUMB-FP:   .cfi_offset lr, -4
+-; CHECK-THUMB-FP:   .cfi_offset r7, -8
+-; CHECK-THUMB-FP:   .cfi_offset r6, -12
+-; CHECK-THUMB-FP:   .cfi_offset r5, -16
+-; CHECK-THUMB-FP:   .cfi_offset r4, -20
++; CHECK-THUMB-FP:   .cfi_offset 14, -4
++; CHECK-THUMB-FP:   .cfi_offset 7, -8
++; CHECK-THUMB-FP:   .cfi_offset 6, -12
++; CHECK-THUMB-FP:   .cfi_offset 5, -16
++; CHECK-THUMB-FP:   .cfi_offset 4, -20
+ ; CHECK-THUMB-FP:   add    r7, sp, #12
+-; CHECK-THUMB-FP:   .cfi_def_cfa r7, 8
++; CHECK-THUMB-FP:   .cfi_def_cfa 7, 8
+ ; CHECK-THUMB-FP:   sub    sp, #60
+ ; CHECK-THUMB-FP:   .cfi_endproc
+ 
+ ; CHECK-THUMB-FP-ELIM-LABEL: _Z4testiiiiiddddd:
+ ; CHECK-THUMB-FP-ELIM:   .cfi_startproc
+ ; CHECK-THUMB-FP-ELIM:   push   {r4, r5, r6, r7, lr}
+ ; CHECK-THUMB-FP-ELIM:   .cfi_def_cfa_offset 20
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r7, -8
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r6, -12
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r5, -16
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r4, -20
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 7, -8
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 6, -12
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 5, -16
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 4, -20
+ ; CHECK-THUMB-FP-ELIM:   sub    sp, #60
+ ; CHECK-THUMB-FP-ELIM:   .cfi_def_cfa_offset 80
+ ; CHECK-THUMB-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-THUMB-V7-FP-LABEL: _Z4testiiiiiddddd:
+ ; CHECK-THUMB-V7-FP:   .cfi_startproc
+ ; CHECK-THUMB-V7-FP:   push.w   {r4, r7, r11, lr}
+ ; CHECK-THUMB-V7-FP:   .cfi_def_cfa_offset 16
+-; CHECK-THUMB-V7-FP:   .cfi_offset lr, -4
+-; CHECK-THUMB-V7-FP:   .cfi_offset r11, -8
+-; CHECK-THUMB-V7-FP:   .cfi_offset r7, -12
+-; CHECK-THUMB-V7-FP:   .cfi_offset r4, -16
++; CHECK-THUMB-V7-FP:   .cfi_offset 14, -4
++; CHECK-THUMB-V7-FP:   .cfi_offset 11, -8
++; CHECK-THUMB-V7-FP:   .cfi_offset 7, -12
++; CHECK-THUMB-V7-FP:   .cfi_offset 4, -16
+ ; CHECK-THUMB-V7-FP:   add    r7, sp, #4
+-; CHECK-THUMB-V7-FP:   .cfi_def_cfa r7, 12
++; CHECK-THUMB-V7-FP:   .cfi_def_cfa 7, 12
+ ; CHECK-THUMB-V7-FP:   vpush  {d8, d9, d10, d11, d12}
+-; CHECK-THUMB-V7-FP:   .cfi_offset d12, -24
+-; CHECK-THUMB-V7-FP:   .cfi_offset d11, -32
+-; CHECK-THUMB-V7-FP:   .cfi_offset d10, -40
+-; CHECK-THUMB-V7-FP:   .cfi_offset d9, -48
+-; CHECK-THUMB-V7-FP:   .cfi_offset d8, -56
++; CHECK-THUMB-V7-FP:   .cfi_offset 268, -24
++; CHECK-THUMB-V7-FP:   .cfi_offset 267, -32
++; CHECK-THUMB-V7-FP:   .cfi_offset 266, -40
++; CHECK-THUMB-V7-FP:   .cfi_offset 265, -48
++; CHECK-THUMB-V7-FP:   .cfi_offset 264, -56
+ ; CHECK-THUMB-V7-FP:   sub    sp, #24
+ ; CHECK-THUMB-V7-FP:   .cfi_endproc
+ 
+ ; CHECK-THUMB-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd:
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_startproc
+ ; CHECK-THUMB-V7-FP-ELIM:   push   {r4, lr}
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_def_cfa_offset 8
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset r4, -8
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 4, -8
+ ; CHECK-THUMB-V7-FP-ELIM:   vpush  {d8, d9, d10, d11, d12}
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_def_cfa_offset 48
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset d12, -16
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset d11, -24
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset d10, -32
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset d9, -40
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset d8, -48
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 268, -16
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 267, -24
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 266, -32
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 265, -40
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 264, -48
+ ; CHECK-THUMB-V7-FP-ELIM:   sub    sp, #24
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_def_cfa_offset 72
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_endproc
+@@ -309,81 +309,81 @@
+ ; CHECK-FP:   .cfi_startproc
+ ; CHECK-FP:   push   {r11, lr}
+ ; CHECK-FP:   .cfi_def_cfa_offset 8
+-; CHECK-FP:   .cfi_offset lr, -4
+-; CHECK-FP:   .cfi_offset r11, -8
++; CHECK-FP:   .cfi_offset 14, -4
++; CHECK-FP:   .cfi_offset 11, -8
+ ; CHECK-FP:   mov    r11, sp
+-; CHECK-FP:   .cfi_def_cfa_register r11
++; CHECK-FP:   .cfi_def_cfa_register 11
+ ; CHECK-FP:   pop    {r11, lr}
+ ; CHECK-FP:   mov    pc, lr
+ ; CHECK-FP:   .cfi_endproc
+ 
+ ; CHECK-FP-ELIM-LABEL: test2:
+ ; CHECK-FP-ELIM:   .cfi_startproc
+ ; CHECK-FP-ELIM:   push  {r11, lr}
+ ; CHECK-FP-ELIM:   .cfi_def_cfa_offset 8
+-; CHECK-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-FP-ELIM:   .cfi_offset r11, -8
++; CHECK-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-FP-ELIM:   .cfi_offset 11, -8
+ ; CHECK-FP-ELIM:   pop   {r11, lr}
+ ; CHECK-FP-ELIM:   mov   pc, lr
+ ; CHECK-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-V7-FP-LABEL: test2:
+ ; CHECK-V7-FP:   .cfi_startproc
+ ; CHECK-V7-FP:   push   {r11, lr}
+ ; CHECK-V7-FP:   .cfi_def_cfa_offset 8
+-; CHECK-V7-FP:   .cfi_offset lr, -4
+-; CHECK-V7-FP:   .cfi_offset r11, -8
++; CHECK-V7-FP:   .cfi_offset 14, -4
++; CHECK-V7-FP:   .cfi_offset 11, -8
+ ; CHECK-V7-FP:   mov    r11, sp
+-; CHECK-V7-FP:   .cfi_def_cfa_register r11
++; CHECK-V7-FP:   .cfi_def_cfa_register 11
+ ; CHECK-V7-FP:   pop    {r11, pc}
+ ; CHECK-V7-FP:   .cfi_endproc
+ 
+ ; CHECK-V7-FP-ELIM-LABEL: test2:
+ ; CHECK-V7-FP-ELIM:   .cfi_startproc
+ ; CHECK-V7-FP-ELIM:   push  {r11, lr}
+ ; CHECK-V7-FP-ELIM:   .cfi_def_cfa_offset 8
+-; CHECK-V7-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-V7-FP-ELIM:   .cfi_offset r11, -8
++; CHECK-V7-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-V7-FP-ELIM:   .cfi_offset 11, -8
+ ; CHECK-V7-FP-ELIM:   pop   {r11, pc}
+ ; CHECK-V7-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-THUMB-FP-LABEL: test2:
+ ; CHECK-THUMB-FP:   .cfi_startproc
+ ; CHECK-THUMB-FP:   push   {r7, lr}
+ ; CHECK-THUMB-FP:   .cfi_def_cfa_offset 8
+-; CHECK-THUMB-FP:   .cfi_offset lr, -4
+-; CHECK-THUMB-FP:   .cfi_offset r7, -8
++; CHECK-THUMB-FP:   .cfi_offset 14, -4
++; CHECK-THUMB-FP:   .cfi_offset 7, -8
+ ; CHECK-THUMB-FP:   add    r7, sp, #0
+-; CHECK-THUMB-FP:   .cfi_def_cfa_register r7
++; CHECK-THUMB-FP:   .cfi_def_cfa_register 7
+ ; CHECK-THUMB-FP:   pop    {r7, pc}
+ ; CHECK-THUMB-FP:   .cfi_endproc
+ 
+ ; CHECK-THUMB-FP-ELIM-LABEL: test2:
+ ; CHECK-THUMB-FP-ELIM:   .cfi_startproc
+ ; CHECK-THUMB-FP-ELIM:   push  {r7, lr}
+ ; CHECK-THUMB-FP-ELIM:   .cfi_def_cfa_offset 8
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r7, -8
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 7, -8
+ ; CHECK-THUMB-FP-ELIM:   pop   {r7, pc}
+ ; CHECK-THUMB-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-THUMB-V7-FP-LABEL: test2:
+ ; CHECK-THUMB-V7-FP:   .cfi_startproc
+ ; CHECK-THUMB-V7-FP:   push   {r7, lr}
+ ; CHECK-THUMB-V7-FP:   .cfi_def_cfa_offset 8
+-; CHECK-THUMB-V7-FP:   .cfi_offset lr, -4
+-; CHECK-THUMB-V7-FP:   .cfi_offset r7, -8
++; CHECK-THUMB-V7-FP:   .cfi_offset 14, -4
++; CHECK-THUMB-V7-FP:   .cfi_offset 7, -8
+ ; CHECK-THUMB-V7-FP:   mov    r7, sp
+-; CHECK-THUMB-V7-FP:   .cfi_def_cfa_register r7
++; CHECK-THUMB-V7-FP:   .cfi_def_cfa_register 7
+ ; CHECK-THUMB-V7-FP:   pop    {r7, pc}
+ ; CHECK-THUMB-V7-FP:   .cfi_endproc
+ 
+ ; CHECK-THUMB-V7-FP-ELIM-LABEL: test2:
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_startproc
+ ; CHECK-THUMB-V7-FP-ELIM:   push.w  {r11, lr}
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_def_cfa_offset 8
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset r11, -8
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 11, -8
+ ; CHECK-THUMB-V7-FP-ELIM:   pop.w   {r11, pc}
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_endproc
+ 
+@@ -413,97 +413,97 @@
+ ; CHECK-FP:   .cfi_startproc
+ ; CHECK-FP:   push   {r4, r5, r11, lr}
+ ; CHECK-FP:   .cfi_def_cfa_offset 16
+-; CHECK-FP:   .cfi_offset lr, -4
+-; CHECK-FP:   .cfi_offset r11, -8
+-; CHECK-FP:   .cfi_offset r5, -12
+-; CHECK-FP:   .cfi_offset r4, -16
++; CHECK-FP:   .cfi_offset 14, -4
++; CHECK-FP:   .cfi_offset 11, -8
++; CHECK-FP:   .cfi_offset 5, -12
++; CHECK-FP:   .cfi_offset 4, -16
+ ; CHECK-FP:   add    r11, sp, #8
+-; CHECK-FP:   .cfi_def_cfa r11, 8
++; CHECK-FP:   .cfi_def_cfa 11, 8
+ ; CHECK-FP:   pop    {r4, r5, r11, lr}
+ ; CHECK-FP:   mov    pc, lr
+ ; CHECK-FP:   .cfi_endproc
+ 
+ ; CHECK-FP-ELIM-LABEL: test3:
+ ; CHECK-FP-ELIM:   .cfi_startproc
+ ; CHECK-FP-ELIM:   push  {r4, r5, r11, lr}
+ ; CHECK-FP-ELIM:   .cfi_def_cfa_offset 16
+-; CHECK-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-FP-ELIM:   .cfi_offset r11, -8
+-; CHECK-FP-ELIM:   .cfi_offset r5, -12
+-; CHECK-FP-ELIM:   .cfi_offset r4, -16
++; CHECK-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-FP-ELIM:   .cfi_offset 11, -8
++; CHECK-FP-ELIM:   .cfi_offset 5, -12
++; CHECK-FP-ELIM:   .cfi_offset 4, -16
+ ; CHECK-FP-ELIM:   pop   {r4, r5, r11, lr}
+ ; CHECK-FP-ELIM:   mov   pc, lr
+ ; CHECK-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-V7-FP-LABEL: test3:
+ ; CHECK-V7-FP:   .cfi_startproc
+ ; CHECK-V7-FP:   push   {r4, r5, r11, lr}
+ ; CHECK-V7-FP:   .cfi_def_cfa_offset 16
+-; CHECK-V7-FP:   .cfi_offset lr, -4
+-; CHECK-V7-FP:   .cfi_offset r11, -8
+-; CHECK-V7-FP:   .cfi_offset r5, -12
+-; CHECK-V7-FP:   .cfi_offset r4, -16
++; CHECK-V7-FP:   .cfi_offset 14, -4
++; CHECK-V7-FP:   .cfi_offset 11, -8
++; CHECK-V7-FP:   .cfi_offset 5, -12
++; CHECK-V7-FP:   .cfi_offset 4, -16
+ ; CHECK-V7-FP:   add    r11, sp, #8
+-; CHECK-V7-FP:   .cfi_def_cfa r11, 8
++; CHECK-V7-FP:   .cfi_def_cfa 11, 8
+ ; CHECK-V7-FP:   pop    {r4, r5, r11, pc}
+ ; CHECK-V7-FP:   .cfi_endproc
+ 
+ ; CHECK-V7-FP-ELIM-LABEL: test3:
+ ; CHECK-V7-FP-ELIM:   .cfi_startproc
+ ; CHECK-V7-FP-ELIM:   push  {r4, r5, r11, lr}
+ ; CHECK-V7-FP-ELIM:   .cfi_def_cfa_offset 16
+-; CHECK-V7-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-V7-FP-ELIM:   .cfi_offset r11, -8
+-; CHECK-V7-FP-ELIM:   .cfi_offset r5, -12
+-; CHECK-V7-FP-ELIM:   .cfi_offset r4, -16
++; CHECK-V7-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-V7-FP-ELIM:   .cfi_offset 11, -8
++; CHECK-V7-FP-ELIM:   .cfi_offset 5, -12
++; CHECK-V7-FP-ELIM:   .cfi_offset 4, -16
+ ; CHECK-V7-FP-ELIM:   pop   {r4, r5, r11, pc}
+ ; CHECK-V7-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-THUMB-FP-LABEL: test3:
+ ; CHECK-THUMB-FP:   .cfi_startproc
+ ; CHECK-THUMB-FP:   push   {r4, r5, r7, lr}
+ ; CHECK-THUMB-FP:   .cfi_def_cfa_offset 16
+-; CHECK-THUMB-FP:   .cfi_offset lr, -4
+-; CHECK-THUMB-FP:   .cfi_offset r7, -8
+-; CHECK-THUMB-FP:   .cfi_offset r5, -12
+-; CHECK-THUMB-FP:   .cfi_offset r4, -16
++; CHECK-THUMB-FP:   .cfi_offset 14, -4
++; CHECK-THUMB-FP:   .cfi_offset 7, -8
++; CHECK-THUMB-FP:   .cfi_offset 5, -12
++; CHECK-THUMB-FP:   .cfi_offset 4, -16
+ ; CHECK-THUMB-FP:   add    r7, sp, #8
+-; CHECK-THUMB-FP:   .cfi_def_cfa r7, 8
++; CHECK-THUMB-FP:   .cfi_def_cfa 7, 8
+ ; CHECK-THUMB-FP:   pop    {r4, r5, r7, pc}
+ ; CHECK-THUMB-FP:   .cfi_endproc
+ 
+ ; CHECK-THUMB-FP-ELIM-LABEL: test3:
+ ; CHECK-THUMB-FP-ELIM:   .cfi_startproc
+ ; CHECK-THUMB-FP-ELIM:   push  {r4, r5, r7, lr}
+ ; CHECK-THUMB-FP-ELIM:   .cfi_def_cfa_offset 16
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r7, -8
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r5, -12
+-; CHECK-THUMB-FP-ELIM:   .cfi_offset r4, -16
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 7, -8
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 5, -12
++; CHECK-THUMB-FP-ELIM:   .cfi_offset 4, -16
+ ; CHECK-THUMB-FP-ELIM:   pop   {r4, r5, r7, pc}
+ ; CHECK-THUMB-FP-ELIM:   .cfi_endproc
+ 
+ ; CHECK-THUMB-V7-FP-LABEL: test3:
+ ; CHECK-THUMB-V7-FP:   .cfi_startproc
+ ; CHECK-THUMB-V7-FP:   push   {r4, r5, r7, lr}
+ ; CHECK-THUMB-V7-FP:   .cfi_def_cfa_offset 16
+-; CHECK-THUMB-V7-FP:   .cfi_offset lr, -4
+-; CHECK-THUMB-V7-FP:   .cfi_offset r7, -8
+-; CHECK-THUMB-V7-FP:   .cfi_offset r5, -12
+-; CHECK-THUMB-V7-FP:   .cfi_offset r4, -16
++; CHECK-THUMB-V7-FP:   .cfi_offset 14, -4
++; CHECK-THUMB-V7-FP:   .cfi_offset 7, -8
++; CHECK-THUMB-V7-FP:   .cfi_offset 5, -12
++; CHECK-THUMB-V7-FP:   .cfi_offset 4, -16
+ ; CHECK-THUMB-V7-FP:   add    r7, sp, #8
+-; CHECK-THUMB-V7-FP:   .cfi_def_cfa r7, 8
++; CHECK-THUMB-V7-FP:   .cfi_def_cfa 7, 8
+ ; CHECK-THUMB-V7-FP:   pop    {r4, r5, r7, pc}
+ ; CHECK-THUMB-V7-FP:   .cfi_endproc
+ 
+ ; CHECK-THUMB-V7-FP-ELIM-LABEL: test3:
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_startproc
+ ; CHECK-THUMB-V7-FP-ELIM:   push.w  {r4, r5, r11, lr}
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_def_cfa_offset 16
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset lr, -4
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset r11, -8
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset r5, -12
+-; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset r4, -16
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 14, -4
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 11, -8
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 5, -12
++; CHECK-THUMB-V7-FP-ELIM:   .cfi_offset 4, -16
+ ; CHECK-THUMB-V7-FP-ELIM:   pop.w   {r4, r5, r11, pc}
+ ; CHECK-THUMB-V7-FP-ELIM:   .cfi_endproc
+ 
+EOF
+patch -p0
+cd -
+
 # Echo all commands.
 set -x
 
@@ -277,9 +953,21 @@
 
 export CFLAGS=""
 export CXXFLAGS=""
+# LLVM uses C++11 starting in llvm 3.5. On Linux, this means libstdc++4.7+ is
+# needed, on OS X it requires libc++. clang only automatically links to libc++
+# when targeting OS X 10.9+, so add stdlib=libc++ explicitly so clang can run on
+# OS X versions as old as 10.7.
+# TODO(thakis): Enable this once all bots are on 10.7, and remove the
+# --disable-compiler-version-checks flags below, and change all
+# MACOSX_DEPLOYMENT_TARGET values to 10.7.
+if [ "${OS}" = "Darwin" ]; then
+  #CXXFLAGS="-stdlib=libc++"
+  CXXFLAGS="-std=gnu++98"
+fi
 
 # Build bootstrap clang if requested.
 if [[ -n "${bootstrap}" ]]; then
+  ABS_INSTALL_DIR="${PWD}/${LLVM_BOOTSTRAP_INSTALL_DIR}"
   echo "Building bootstrap compiler"
   mkdir -p "${LLVM_BOOTSTRAP_DIR}"
   cd "${LLVM_BOOTSTRAP_DIR}"
@@ -289,30 +977,33 @@
     # compiler should be as similar to the final compiler as possible, so do
     # keep --disable-threads & co.
     ../llvm/configure \
+        --disable-compiler-version-checks \
         --enable-optimized \
         --enable-targets=host-only \
+        --enable-libedit=no \
         --disable-threads \
         --disable-pthreads \
         --without-llvmgcc \
-        --without-llvmgxx
+        --without-llvmgxx \
+        --prefix="${ABS_INSTALL_DIR}"
   fi
 
-  if [[ -n "${gcc_toolchain}" ]]; then
-    # Copy that gcc's stdlibc++.so.6 to the build dir, so the bootstrap
-    # compiler can start.
-    mkdir -p Release+Asserts/lib
-    cp -v "$(${CXX} -print-file-name=libstdc++.so.6)" \
-      "Release+Asserts/lib/"
-  fi
-
-
   MACOSX_DEPLOYMENT_TARGET=10.5 ${MAKE} -j"${NUM_JOBS}"
   if [[ -n "${run_tests}" ]]; then
     ${MAKE} check-all
   fi
+
+  MACOSX_DEPLOYMENT_TARGET=10.5 ${MAKE} install
+  if [[ -n "${gcc_toolchain}" ]]; then
+    # Copy that gcc's stdlibc++.so.6 to the build dir, so the bootstrap
+    # compiler can start.
+    cp -v "$(${CXX} -print-file-name=libstdc++.so.6)" \
+      "${ABS_INSTALL_DIR}/lib/"
+  fi
+
   cd -
-  export CC="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang"
-  export CXX="${PWD}/${LLVM_BOOTSTRAP_DIR}/Release+Asserts/bin/clang++"
+  export CC="${ABS_INSTALL_DIR}/bin/clang"
+  export CXX="${ABS_INSTALL_DIR}/bin/clang++"
 
   if [[ -n "${gcc_toolchain}" ]]; then
     # Tell the bootstrap compiler to use a specific gcc prefix to search
@@ -331,7 +1022,9 @@
 cd "${LLVM_BUILD_DIR}"
 if [[ ! -f ./config.status ]]; then
   ../llvm/configure \
+      --disable-compiler-version-checks \
       --enable-optimized \
+      --enable-libedit=no \
       --disable-threads \
       --disable-pthreads \
       --without-llvmgcc \
diff --git a/tools/cr/cr/actions/action.py b/tools/cr/cr/actions/action.py
index b812aae..e2f966a 100644
--- a/tools/cr/cr/actions/action.py
+++ b/tools/cr/cr/actions/action.py
@@ -29,7 +29,7 @@
     )
 
   @cr.Plugin.activemethod
-  def Skipping(self, context):
+  def Skipping(self):
     """A method that is used to detect void or skip implementations.
 
     Most actions have a skip version that you can select to indicate that you
@@ -39,8 +39,6 @@
     performing actions that were only there to produce the inputs of an action
     that is being skipped).
 
-    Args:
-      context: the cr context to test within.
     Returns:
       True if this implementation is a skip action.
     """
diff --git a/tools/cr/cr/actions/adb.py b/tools/cr/cr/actions/adb.py
index e55d503..7e14120 100644
--- a/tools/cr/cr/actions/adb.py
+++ b/tools/cr/cr/actions/adb.py
@@ -24,7 +24,8 @@
   def GetPids(cls, target):
     """Gets the set of running PIDs that match the specified target."""
     pids = []
-    output = cr.Host.Capture(target, '{CR_ADB}', 'shell', 'ps')
+    with target:
+      output = cr.Host.Capture('{CR_ADB}', 'shell', 'ps')
     pattern = re.compile(r'\S+\s+(\d+)\s+.*{CR_PROCESS}')
     for line in output.split('\n'):
       match = re.match(pattern, line)
@@ -35,13 +36,13 @@
   @classmethod
   def Run(cls, target, arguments):
     """Invoke a target binary on the device."""
-    cr.Host.Execute(
-        target,
-        '{CR_ADB}', 'shell', 'am', 'start',
-        '-a', '{CR_ACTION}',
-        '-n', '{CR_INTENT}',
-        '{CR_RUN_ARGUMENTS}',
-        *arguments
+    with target:
+      cr.Host.Execute(
+          '{CR_ADB}', 'shell', 'am', 'start',
+          '-a', '{CR_ACTION}',
+          '-n', '{CR_INTENT}',
+          '{CR_RUN_ARGUMENTS}',
+          *arguments
     )
 
   @classmethod
@@ -53,49 +54,50 @@
       return
     pids = cls.GetPids(target)
     if pids:
-      cr.Host.Execute(target, '{CR_ADB}', 'shell', 'kill', *pids)
+      with target:
+        cr.Host.Execute('{CR_ADB}', 'shell', 'kill', *pids)
     elif target.verbose:
       print target.Substitute('{CR_TARGET_NAME} not running')
     cls._kills[target_name] = True
 
   @classmethod
   def Uninstall(cls, target, arguments):
-    cr.Host.Execute(
-        target,
-        '{CR_ADB}', 'uninstall',
-        '{CR_PACKAGE}',
-        *arguments
+    with target:
+      cr.Host.Execute(
+          '{CR_ADB}', 'uninstall',
+          '{CR_PACKAGE}',
+          *arguments
     )
 
   @classmethod
   def Install(cls, target, arguments):
-    cr.Host.Execute(
-        target,
-        '{CR_ADB}', 'install',
-        '{CR_BINARY}',
-        *arguments
+    with target:
+      cr.Host.Execute(
+          '{CR_ADB}', 'install',
+          '{CR_BINARY}',
+          *arguments
     )
 
   @classmethod
   def Reinstall(cls, target, arguments):
-    cr.Host.Execute(
-        target,
-        '{CR_ADB}', 'install',
-        '-r',
-        '{CR_BINARY}',
-        *arguments
+    with target:
+      cr.Host.Execute(
+          '{CR_ADB}', 'install',
+          '-r',
+          '{CR_BINARY}',
+          *arguments
     )
 
   @classmethod
   def AttachGdb(cls, target, arguments):
-    cr.Host.Execute(
-        target,
-        '{CR_ADB_GDB}',
-        '--adb={CR_ADB}',
-        '--symbol-dir=${CR_BUILD_DIR}/lib',
-        '--program-name={CR_TARGET_NAME}',
-        '--package-name={CR_PACKAGE}',
-        *arguments
+    with target:
+      cr.Host.Execute(
+          '{CR_ADB_GDB}',
+          '--adb={CR_ADB}',
+          '--symbol-dir=${CR_BUILD_DIR}/lib',
+          '--program-name={CR_TARGET_NAME}',
+          '--package-name={CR_PACKAGE}',
+          *arguments
     )
 
 
@@ -106,16 +108,16 @@
   def enabled(self):
     return cr.AndroidPlatform.GetInstance().is_active
 
-  def Kill(self, context, targets, arguments):
+  def Kill(self, targets, arguments):
     for target in targets:
       Adb.Kill(target, arguments)
 
-  def Run(self, context, target, arguments):
+  def Run(self, target, arguments):
     Adb.Run(target, arguments)
 
-  def Test(self, context, target, arguments):
-    cr.Host.Execute(
-        target,
+  def Test(self, target, arguments):
+    with target:
+      cr.Host.Execute(
         '{CR_TEST_RUNNER}', '{CR_TEST_TYPE}',
         '-s', '{CR_TARGET_NAME}',
         '--{CR_TEST_MODE}',
@@ -130,14 +132,14 @@
   def enabled(self):
     return cr.AndroidPlatform.GetInstance().is_active
 
-  def Uninstall(self, context, targets, arguments):
+  def Uninstall(self, targets, arguments):
     for target in targets:
       Adb.Uninstall(target, arguments)
 
-  def Install(self, context, targets, arguments):
+  def Install(self, targets, arguments):
     for target in targets:
       Adb.Install(target, arguments)
 
-  def Reinstall(self, context, targets, arguments):
+  def Reinstall(self, targets, arguments):
     for target in targets:
       Adb.Reinstall(target, arguments)
diff --git a/tools/cr/cr/actions/builder.py b/tools/cr/cr/actions/builder.py
index 286d2ec..b3ff2bf 100644
--- a/tools/cr/cr/actions/builder.py
+++ b/tools/cr/cr/actions/builder.py
@@ -26,26 +26,26 @@
   SELECTOR_HELP = 'Sets the builder to use to update dependencies.'
 
   @cr.Plugin.activemethod
-  def Build(self, context, targets, arguments):
+  def Build(self, targets, arguments):
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Clean(self, context, targets, arguments):
+  def Clean(self, targets, arguments):
     """Clean temporary files built by a target."""
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Rebuild(self, context, targets, arguments):
+  def Rebuild(self, targets, arguments):
     """Make a target build even if it is up to date.
 
     Default implementation is to do a Clean and Build sequence.
     Do not call the base version if you implement a more efficient one.
     """
-    self.Clean(context, targets, [])
-    self.Build(context, targets, arguments)
+    self.Clean(targets, [])
+    self.Build(targets, arguments)
 
   @cr.Plugin.activemethod
-  def GetTargets(self, context):
+  def GetTargets(self):
     """Gets the full set of targets supported by this builder.
 
     Used in automatic target name transformations, and also in offering the
@@ -54,14 +54,14 @@
     return []
 
   @cr.Plugin.activemethod
-  def IsTarget(self, context, target_name):
+  def IsTarget(self, target_name):
     """Check if a target name is on the builder knows about."""
-    return target_name in self.GetTargets(context)
+    return target_name in self.GetTargets()
 
   @cr.Plugin.activemethod
-  def GuessTargets(self, context, target_name):
+  def GuessTargets(self, target_name):
     """Returns a list of closest matching targets for a named target."""
-    return difflib.get_close_matches(target_name, self.GetTargets(context))
+    return difflib.get_close_matches(target_name, self.GetTargets(), 10, 0.4)
 
 
 class SkipBuilder(Builder):
@@ -71,9 +71,9 @@
   def priority(self):
     return super(SkipBuilder, self).priority - 1
 
-  def Build(self, context, targets, arguments):
+  def Build(self, targets, arguments):
     pass
 
-  def Clean(self, context, targets, arguments):
+  def Clean(self, targets, arguments):
     pass
 
diff --git a/tools/cr/cr/actions/debugger.py b/tools/cr/cr/actions/debugger.py
index a634ab2..1db3d81 100644
--- a/tools/cr/cr/actions/debugger.py
+++ b/tools/cr/cr/actions/debugger.py
@@ -22,30 +22,30 @@
     cr.Runner.AddSelectorArg(command, parser)
 
   @classmethod
-  def ShouldInvoke(cls, context):
+  def ShouldInvoke(cls):
     """Checks if the debugger is attaching or launching."""
-    return not cr.Runner.Skipping(context)
+    return not cr.Runner.Skipping()
 
   @cr.Plugin.activemethod
-  def Restart(self, context, targets, arguments):
+  def Restart(self, targets, arguments):
     """Ask the debugger to restart.
 
     Defaults to a Kill Invoke sequence.
     """
-    self.Kill(context, targets, [])
-    self.Invoke(context, targets, arguments)
+    self.Kill(targets, [])
+    self.Invoke(targets, arguments)
 
   @cr.Plugin.activemethod
-  def Kill(self, context, targets, arguments):
+  def Kill(self, targets, arguments):
     """Kill the running debugger."""
-    cr.Runner.Kill(context, targets, arguments)
+    cr.Runner.Kill(targets, arguments)
 
   @cr.Plugin.activemethod
-  def Invoke(self, context, targets, arguments):
+  def Invoke(self, targets, arguments):
     """Invoke the program within a debugger."""
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Attach(self, context, targets, arguments):
+  def Attach(self, targets, arguments):
     """Attach a debugger to a running program."""
     raise NotImplementedError('Must be overridden.')
diff --git a/tools/cr/cr/actions/gdb.py b/tools/cr/cr/actions/gdb.py
index 64386db..cdbb1bf 100644
--- a/tools/cr/cr/actions/gdb.py
+++ b/tools/cr/cr/actions/gdb.py
@@ -17,17 +17,17 @@
     return (cr.LinuxPlatform.GetInstance().is_active and
             self.DETECTED.Find('CR_GDB'))
 
-  def Invoke(self, context, targets, arguments):
+  def Invoke(self, targets, arguments):
     for target in targets:
-      cr.Host.Execute(
-          target,
-          '{CR_GDB}', '--eval-command=run', '--args',
-          '{CR_BINARY}',
-          '{CR_RUN_ARGUMENTS}',
-          *arguments
+      with target:
+        cr.Host.Execute(
+            '{CR_GDB}', '--eval-command=run', '--args',
+            '{CR_BINARY}',
+            '{CR_RUN_ARGUMENTS}',
+            *arguments
       )
 
-  def Attach(self, context, targets, arguments):
+  def Attach(self, targets, arguments):
     raise NotImplementedError('Attach not currently supported for gdb.')
 
   @classmethod
diff --git a/tools/cr/cr/actions/gyp.py b/tools/cr/cr/actions/gyp.py
index b3492bb..b50e893 100644
--- a/tools/cr/cr/actions/gyp.py
+++ b/tools/cr/cr/actions/gyp.py
@@ -5,7 +5,9 @@
 """A module to add gyp support to cr."""
 
 import cr
+import os
 
+GYP_DEFINE_PREFIX = 'GYP_DEF_'
 
 class GypPrepareOut(cr.PrepareOut):
   """A prepare action that runs gyp whenever you select an output directory."""
@@ -13,13 +15,22 @@
   ENABLED = cr.Config.From(
       GYP_GENERATORS='ninja',
       GYP_GENERATOR_FLAGS='output_dir={CR_OUT_BASE} config={CR_BUILDTYPE}',
+      GPP_DEF_target_arch='{CR_ENVSETUP_ARCH}',
   )
 
-  def Prepare(self, context):
-    if context.verbose >= 1:
-      print context.Substitute('Invoking gyp with {GYP_GENERATOR_FLAGS}')
+  def Prepare(self):
+    # Collapse GYP_DEFINES from all GYP_DEF prefixes
+    gyp_defines = cr.context.Find('GYP_DEFINES') or ''
+    for key, value in cr.context.exported.items():
+      if key.startswith(GYP_DEFINE_PREFIX):
+        gyp_defines += ' %s=%s' % (key[len(GYP_DEFINE_PREFIX):], value)
+    cr.context['GYP_DEFINES'] = gyp_defines.strip()
+
+    if cr.context.verbose >= 1:
+      print cr.context.Substitute('Invoking gyp with {GYP_GENERATOR_FLAGS}')
+      print cr.context.Substitute('GYP_DEFINES = {GYP_DEFINES}')
+
     cr.Host.Execute(
-        context,
         '{CR_SRC}/build/gyp_chromium',
         '--depth={CR_SRC}',
         '--check'
diff --git a/tools/cr/cr/actions/installer.py b/tools/cr/cr/actions/installer.py
index 0dd432d..064b4d0 100644
--- a/tools/cr/cr/actions/installer.py
+++ b/tools/cr/cr/actions/installer.py
@@ -20,25 +20,25 @@
   SELECTOR_HELP = 'Sets the installer to use.'
 
   @cr.Plugin.activemethod
-  def Uninstall(self, context, targets, arguments):
+  def Uninstall(self, targets, arguments):
     """Removes a target from it's installed location."""
 
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Install(self, context, targets, arguments):
+  def Install(self, targets, arguments):
     """Installs a target somewhere so that it is ready to run."""
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Reinstall(self, context, targets, arguments):
+  def Reinstall(self, targets, arguments):
     """Force a target to install even if already installed.
 
     Default implementation is to do an Uninstall Install sequence.
     Do not call the base version if you implement a more efficient one.
     """
-    self.Uninstall(context, targets, [])
-    self.Install(context, targets, arguments)
+    self.Uninstall(targets, [])
+    self.Install(targets, arguments)
 
 
 class SkipInstaller(Installer):
@@ -48,8 +48,8 @@
   def priority(self):
     return super(SkipInstaller, self).priority - 1
 
-  def Uninstall(self, context, targets, arguments):
+  def Uninstall(self, targets, arguments):
     pass
 
-  def Install(self, context, targets, arguments):
+  def Install(self, targets, arguments):
     pass
diff --git a/tools/cr/cr/actions/linux.py b/tools/cr/cr/actions/linux.py
index adcdb31..0e869ee 100644
--- a/tools/cr/cr/actions/linux.py
+++ b/tools/cr/cr/actions/linux.py
@@ -17,15 +17,16 @@
   def enabled(self):
     return cr.LinuxPlatform.GetInstance().is_active
 
-  def Kill(self, context, targets, arguments):
+  def Kill(self, targets, arguments):
     # TODO(iancottrell): Think about how to implement this, or even if we should
     print '**WARNING** Kill not yet implemented on linux'
 
-  def Run(self, context, target, arguments):
-    cr.Host.Execute(target, '{CR_BINARY}', '{CR_RUN_ARGUMENTS}', *arguments)
+  def Run(self, target, arguments):
+    with target:
+      cr.Host.Execute('{CR_BINARY}', '{CR_RUN_ARGUMENTS}', *arguments)
 
-  def Test(self, context, target, arguments):
-    self.Run(context, target, arguments)
+  def Test(self, target, arguments):
+    self.Run(target, arguments)
 
 
 class LinuxInstaller(cr.Installer):
@@ -39,12 +40,12 @@
   def enabled(self):
     return cr.LinuxPlatform.GetInstance().is_active
 
-  def Uninstall(self, context, targets, arguments):
+  def Uninstall(self, targets, arguments):
     pass
 
-  def Install(self, context, targets, arguments):
+  def Install(self, targets, arguments):
     pass
 
-  def Reinstall(self, context, targets, arguments):
+  def Reinstall(self, targets, arguments):
     pass
 
diff --git a/tools/cr/cr/actions/ninja.py b/tools/cr/cr/actions/ninja.py
index afd2d1f..d2e77b0 100644
--- a/tools/cr/cr/actions/ninja.py
+++ b/tools/cr/cr/actions/ninja.py
@@ -12,20 +12,31 @@
 _LINK_SUFFIX = ': link'
 
 
+DEFAULT = cr.Config.From(
+    GOMA_DIR=os.path.expanduser('~/goma'),
+)
+
 class NinjaBuilder(cr.Builder):
   """An implementation of Builder that uses ninja to do the actual build."""
 
   # Some basic configuration installed if we are enabled.
   ENABLED = cr.Config.From(
       NINJA_BINARY=os.path.join('{DEPOT_TOOLS}', 'ninja'),
+      NINJA_JOBS=10,
+      NINJA_PROCESSORS=4,
+      NINJA_BUILD_FILE=os.path.join('{CR_BUILD_DIR}', 'build.ninja'),
+      # Don't rename to GOMA_* or Goma will complain: "unkown GOMA_ parameter".
+      NINJA_GOMA_LINE='cc = {CR_GOMA_CC} $',
+  )
+  # A config block only included if goma is detected.
+  GOMA = cr.Config.From(
+      CR_GOMA_CC=os.path.join('{GOMA_DIR}', 'gomacc'),
+      CR_GOMA_CTL=os.path.join('{GOMA_DIR}', 'goma_ctl.py'),
+      GOMA_DIR='{CR_GOMA_DIR}',
+      GYP_DEF_gomadir='{CR_GOMA_DIR}',
+      GYP_DEF_use_goma=1,
       NINJA_JOBS=200,
       NINJA_PROCESSORS=12,
-      NINJA_BUILD_FILE=os.path.join('{CR_BUILD_DIR}', 'build.ninja'),
-      GOMA_DIR=os.path.join('{GOOGLE_CODE}', 'goma'),
-      # Don't rename to GOMA_* or Goma will complain: "unkown GOMA_ parameter".
-      NINJA_GOMA_CTL=os.path.join('{GOMA_DIR}', 'goma_ctl.py'),
-      NINJA_GOMA_CC=os.path.join('{GOMA_DIR}', 'gomacc'),
-      NINJA_GOMA_LINE='cc = {NINJA_GOMA_CC} $',
   )
   # A placeholder for the system detected configuration
   DETECTED = cr.Config('DETECTED')
@@ -34,16 +45,15 @@
     super(NinjaBuilder, self).__init__()
     self._targets = []
 
-  def Build(self, context, targets, arguments):
+  def Build(self, targets, arguments):
     # Make sure Goma is started if Ninja is set to use it.
     # This may be redundant, but it currently improves reliability.
     try:
-      with open(context.Get('NINJA_BUILD_FILE'), 'r') as f:
-        if f.readline().rstrip('\n') == context.Get('NINJA_GOMA_LINE'):
+      with open(cr.context.Get('NINJA_BUILD_FILE'), 'r') as f:
+        if f.readline().rstrip('\n') == cr.context.Get('NINJA_GOMA_LINE'):
           # Goma is active, so make sure it's started.
           cr.Host.ExecuteSilently(
-              context,
-              '{NINJA_GOMA_CTL}',
+              '{CR_GOMA_CTL}',
               'ensure_start'
           )
     except IOError:
@@ -52,7 +62,6 @@
     build_arguments = [target.build_target for target in targets]
     build_arguments.extend(arguments)
     cr.Host.Execute(
-        context,
         '{NINJA_BINARY}',
         '-C{CR_BUILD_DIR}',
         '-j{NINJA_JOBS}',
@@ -60,26 +69,24 @@
         *build_arguments
     )
 
-  def Clean(self, context, targets, arguments):
+  def Clean(self, targets, arguments):
     build_arguments = [target.build_target for target in targets]
     build_arguments.extend(arguments)
     cr.Host.Execute(
-        context,
         '{NINJA_BINARY}',
         '-C{CR_BUILD_DIR}',
         '-tclean',
         *build_arguments
     )
 
-  def GetTargets(self, context):
+  def GetTargets(self):
     """Overridden from Builder.GetTargets."""
     if not self._targets:
       try:
-        context.Get('CR_BUILD_DIR', raise_errors=True)
+        cr.context.Get('CR_BUILD_DIR', raise_errors=True)
       except KeyError:
         return self._targets
       output = cr.Host.Capture(
-          context,
           '{NINJA_BINARY}',
           '-C{CR_BUILD_DIR}',
           '-ttargets',
@@ -101,3 +108,12 @@
     ninja_binaries = cr.Host.SearchPath('ninja')
     if ninja_binaries:
       cls.DETECTED.Set(NINJA_BINARY=ninja_binaries[0])
+
+    goma_binaries = cr.Host.SearchPath('gomacc', [
+      '{GOMA_DIR}',
+      '/usr/local/google/code/goma',
+      os.path.expanduser('~/goma')
+    ])
+    if goma_binaries:
+      cls.DETECTED.Set(CR_GOMA_DIR=os.path.dirname(goma_binaries[0]))
+      cls.DETECTED.AddChildren(cls.GOMA)
diff --git a/tools/cr/cr/actions/runner.py b/tools/cr/cr/actions/runner.py
index 72590fc..0886174 100644
--- a/tools/cr/cr/actions/runner.py
+++ b/tools/cr/cr/actions/runner.py
@@ -32,41 +32,41 @@
     )
 
   @cr.Plugin.activemethod
-  def Kill(self, context, targets, arguments):
+  def Kill(self, targets, arguments):
     """Stops all running processes that match a target."""
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Run(self, context, target, arguments):
+  def Run(self, target, arguments):
     """Run a new copy of a runnable target."""
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Test(self, context, target, arguments):
+  def Test(self, target, arguments):
     """Run a test target."""
     raise NotImplementedError('Must be overridden.')
 
   @cr.Plugin.activemethod
-  def Invoke(self, context, targets, arguments):
+  def Invoke(self, targets, arguments):
     """Invoke a target.
 
     This dispatches to either Test or Run depending on the target type.
     """
     for target in targets:
       if target.is_test:
-        self.Test(context, target, arguments)
+        self.Test(target, arguments)
       else:
-        self.Run(context, target, arguments)
+        self.Run(target, arguments)
 
   @cr.Plugin.activemethod
-  def Restart(self, context, targets, arguments):
+  def Restart(self, targets, arguments):
     """Force a target to restart if it is already running.
 
     Default implementation is to do a Kill Invoke sequence.
     Do not call the base version if you implement a more efficient one.
     """
-    self.Kill(context, targets, [])
-    self.Invoke(context, targets, arguments)
+    self.Kill(targets, [])
+    self.Invoke(targets, arguments)
 
 
 class SkipRunner(Runner):
@@ -76,12 +76,12 @@
   def priority(self):
     return super(SkipRunner, self).priority - 1
 
-  def Kill(self, context, targets, arguments):
+  def Kill(self, targets, arguments):
     pass
 
-  def Run(self, context, target, arguments):
+  def Run(self, target, arguments):
     pass
 
-  def Test(self, context, target, arguments):
+  def Test(self, target, arguments):
     pass
 
diff --git a/tools/cr/cr/autocomplete.py b/tools/cr/cr/autocomplete.py
index ab9ce2f..f03b821 100644
--- a/tools/cr/cr/autocomplete.py
+++ b/tools/cr/cr/autocomplete.py
@@ -11,17 +11,13 @@
 import cr
 
 
-def Complete(context):
+def Complete():
   """Attempts to build a completion list for the current command line.
 
   COMP_WORD contains the word that is being completed, and COMP_CWORD has
   the index of that word on the command line.
-
-  Args:
-    context: The cr context object, of type cr.context.Context.
   """
 
-  _ = context
   # TODO(iancottrell): support auto complete of more than just the command
   # try to parse the command line using parser
   print ' '.join(command.name for command in cr.Command.Plugins())
diff --git a/tools/cr/cr/base/android.py b/tools/cr/cr/base/android.py
index 027a697..248e4d0 100644
--- a/tools/cr/cr/base/android.py
+++ b/tools/cr/cr/base/android.py
@@ -38,6 +38,7 @@
       CR_ADB_GDB=os.path.join('{CR_SRC}', 'build', 'android', 'adb_gdb'),
       CHROMIUM_OUT_DIR='{CR_OUT_BASE}',
       CR_DEFAULT_TARGET='chrome_shell',
+      GYP_DEF_OS='android'
   )
 
   def __init__(self):
@@ -51,19 +52,17 @@
   def priority(self):
     return super(AndroidPlatform, self).priority + 1
 
-  def Prepare(self, context):
+  def Prepare(self):
     """Override Prepare from cr.Platform."""
-    super(AndroidPlatform, self).Prepare(context)
+    super(AndroidPlatform, self).Prepare()
     try:
       # capture the result of env setup if we have not already done so
       if not self._env_ready:
         # See what the env would be without env setup
-        before = context.exported
-        before['GYP_DEFINES'] = before.get(
-            'GYP_DEFINES', '') + ' target_arch={CR_ENVSETUP_ARCH}'
+        before = cr.context.exported
         # Run env setup and capture/parse its output
         envsetup = 'source {CR_ENVSETUP}'
-        output = cr.Host.CaptureShell(context, envsetup + ' > /dev/null && env')
+        output = cr.Host.CaptureShell(envsetup + ' > /dev/null && env')
         env_setup = cr.Config('envsetup', literal=True, export=True)
         for line in output.split('\n'):
           (key, op, value) = line.partition('=')
@@ -73,11 +72,6 @@
               env_setup[key] = env_setup.ParseValue(value.strip())
             if key == 'PATH':
               self._env_paths = value.strip().split(os.path.pathsep)
-            if key == 'GYP_DEFINES':
-              # Make a version of GYP_DEFINES that is the combination of base
-              # setting and envsetup, needs to override the overrides
-              # Note: Forcing it into the top level scope - sledge-hammer
-              context[key] = value.strip() + ' ' + before.get(key, '')
         items = env_setup.exported.items()
         if not items:
           # Because of the way envsetup is run, the exit code does not make it
@@ -109,13 +103,13 @@
   def enabled(self):
     return cr.AndroidPlatform.GetInstance().is_active
 
-  def Run(self, context, old_version, config):
+  def Run(self, old_version, config):
     _ = old_version, config  # unused
     # Check we are an android capable client
-    target_os = context.gclient.get('target_os', [])
+    target_os = cr.context.gclient.get('target_os', [])
     if 'android' in target_os:
       return
-    url = context.gclient.get('solutions', [{}])[0].get('url')
+    url = cr.context.gclient.get('solutions', [{}])[0].get('url')
     if (url.startswith('https://chrome-internal.googlesource.com/') and
         url.endswith('/internal/apps.git')):
       return
@@ -126,10 +120,10 @@
       print 'Abandoning the creation of and android output directory.'
       exit(1)
     target_os.append('android')
-    context.gclient['target_os'] = target_os
-    context.WriteGClient()
+    cr.context.gclient['target_os'] = target_os
+    cr.base.client.WriteGClient()
     print 'Client updated.'
     print 'You may need to sync before an output directory can be made.'
     if cr.Host.YesNo('Would you like to sync this client now?'):
-      cr.SyncCommand.Sync(context, ["--nohooks"])
+      cr.SyncCommand.Sync(["--nohooks"])
 
diff --git a/tools/cr/cr/base/arch.py b/tools/cr/cr/base/arch.py
index dfc9e16..4973b44 100644
--- a/tools/cr/cr/base/arch.py
+++ b/tools/cr/cr/base/arch.py
@@ -68,3 +68,14 @@
   @property
   def enabled(self):
     return cr.AndroidPlatform.GetInstance().is_active
+
+
+class Arm64Arch(Arch):
+
+  ACTIVE = cr.Config.From(
+      CR_ENVSETUP_ARCH='arm64',
+  )
+
+  @property
+  def enabled(self):
+    return cr.AndroidPlatform.GetInstance().is_active
diff --git a/tools/cr/cr/base/client.py b/tools/cr/cr/base/client.py
index 0b679ce..9ab52f9 100644
--- a/tools/cr/cr/base/client.py
+++ b/tools/cr/cr/base/client.py
@@ -50,7 +50,7 @@
 )
 
 
-def DetectClient(context):
+def DetectClient():
   # Attempt to detect the current client from the cwd
   # See if we can detect the source tree root
   client_path = os.getcwd()
@@ -66,11 +66,11 @@
       # we have the src path, base is one level up
       client_path = dirname
   if client_path is not None:
-    context.derived['CR_CLIENT_PATH'] = client_path
-  # now get the value from context, it may be different
-  client_path = context.Get('CR_CLIENT_PATH')
+    cr.context.derived['CR_CLIENT_PATH'] = client_path
+  # now get the value from it may be different
+  client_path = cr.context.Get('CR_CLIENT_PATH')
   if client_path is not None:
-    context.derived['CR_CLIENT_NAME'] = os.path.basename(client_path)
+    cr.context.derived['CR_CLIENT_NAME'] = os.path.basename(client_path)
 
 
 def _GetConfigFilename(path):
@@ -96,24 +96,22 @@
   )
 
 
-def GetOutArgument(context):
-  return getattr(context.args, '_out', None)
+def GetOutArgument():
+  return getattr(cr.context.args, '_out', None)
 
 
-def ApplyOutArgument(context):
+def ApplyOutArgument():
   # TODO(iancottrell): be flexible, allow out to do approximate match...
-  out = GetOutArgument(context)
+  out = GetOutArgument()
   if out:
-    context.derived.Set(CR_OUT_FULL=out)
+    cr.context.derived.Set(CR_OUT_FULL=out)
 
 
-def ReadGClient(context):
+def ReadGClient():
   """Loads the .gclient configuration for the current client.
 
   This will load from CR_CLIENT_PATH.
 
-  Args:
-    context: The active context to load configuration for.
   Returns:
     The dict of values set in the .gclient file.
 
@@ -121,7 +119,7 @@
   # Now attempt to load and parse the .gclient file
   result = {}
   try:
-    gclient_file = context.Substitute(
+    gclient_file = cr.context.Substitute(
         os.path.join('{CR_CLIENT_PATH}', GCLIENT_FILENAME))
     with open(gclient_file, 'r') as spec_file:
       # matching the behaviour of gclient, so pylint: disable=exec-used
@@ -132,46 +130,41 @@
   return result
 
 
-def WriteGClient(context):
+def WriteGClient():
   """Writes the .gclient configuration for the current client.
 
   This will write to CR_CLIENT_PATH.
 
-  Args:
-    context: The active context to write the configuration for.
-
   """
-  gclient_file = context.Substitute(
+  gclient_file = cr.context.Substitute(
       os.path.join('{CR_CLIENT_PATH}', GCLIENT_FILENAME))
   spec = '\n'.join('%s = %s' % (key, pprint.pformat(value))
-      for key,value in context.gclient.items())
-  if context.dry_run:
+      for key,value in cr.context.gclient.items())
+  if cr.context.dry_run:
     print 'Write the following spec to', gclient_file
     print spec
   else:
     with open(gclient_file, 'w') as spec_file:
       spec_file.write(spec)
 
-def LoadConfig(context):
+def LoadConfig():
   """Loads the client configuration for the given context.
 
   This will load configuration if present from CR_CLIENT_PATH and then
   CR_BUILD_DIR.
 
-  Args:
-    context: The active context to load configuratin for.
   Returns:
     True if configuration was fully loaded.
 
   """
   # Load the root config, will help set default build dir
-  client_path = context.Find('CR_CLIENT_PATH')
+  client_path = cr.context.Find('CR_CLIENT_PATH')
   if not client_path:
     return False
   cr.auto.client.__path__.append(os.path.join(client_path, CLIENT_CONFIG_PATH))
   cr.loader.Scan()
   # Now load build dir config
-  build_dir = context.Find('CR_BUILD_DIR')
+  build_dir = cr.context.Find('CR_BUILD_DIR')
   if not build_dir:
     return False
   cr.auto.build.__path__.append(os.path.join(build_dir, CLIENT_CONFIG_PATH))
@@ -179,19 +172,18 @@
   return hasattr(cr.auto.build, 'config')
 
 
-def WriteConfig(context, path, data):
+def WriteConfig(path, data):
   """Writes a configuration out to a file.
 
   This writes all the key value pairs in data out to a config file below path.
 
   Args:
-    context: The context to run under.
     path: The base path to write the config plugin into.
     data: The key value pairs to write.
   """
   filename = _GetConfigFilename(path)
   config_dir = os.path.dirname(filename)
-  if context.dry_run:
+  if cr.context.dry_run:
     print 'makedirs', config_dir
     print 'Write config to', filename
     _WriteConfig(sys.stdout, data)
@@ -205,10 +197,10 @@
       _WriteConfig(writer, data)
 
 
-def PrintInfo(context):
-  print 'Selected output directory is', context.Find('CR_BUILD_DIR')
+def PrintInfo():
+  print 'Selected output directory is', cr.context.Find('CR_BUILD_DIR')
   try:
     for name in cr.auto.build.config.OVERRIDES.exported.keys():
-      print ' ', name, '=', context.Get(name)
+      print ' ', name, '=', cr.context.Get(name)
   except AttributeError:
     pass
diff --git a/tools/cr/cr/base/context.py b/tools/cr/cr/base/context.py
new file mode 100644
index 0000000..1081fd1
--- /dev/null
+++ b/tools/cr/cr/base/context.py
@@ -0,0 +1,245 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Application context management for the cr tool.
+
+Contains all the support code to enable the shared context used by the cr tool.
+This includes the configuration variables and command line handling.
+"""
+
+import argparse
+import os
+import cr
+
+class _DumpVisitor(cr.visitor.ExportVisitor):
+  """A visitor that prints all variables in a config hierarchy."""
+
+  def __init__(self, with_source):
+    super(_DumpVisitor, self).__init__({})
+    self.to_dump = {}
+    self.with_source = with_source
+
+  def StartNode(self):
+    if self.with_source:
+      self._DumpNow()
+    super(_DumpVisitor, self).StartNode()
+
+  def EndNode(self):
+    if self.with_source or not self.stack:
+      self._DumpNow()
+    super(_DumpVisitor, self).EndNode()
+    if not self.stack:
+      self._DumpNow()
+
+  def Visit(self, key, value):
+    super(_DumpVisitor, self).Visit(key, value)
+    if key in self.store:
+      str_value = str(self.store[key])
+      if str_value != str(os.environ.get(key, None)):
+        self.to_dump[key] = str_value
+
+  def _DumpNow(self):
+    if self.to_dump:
+      if self.with_source:
+        print 'From', self.Where()
+      for key in sorted(self.to_dump.keys()):
+        print '  ', key, '=', self.to_dump[key]
+      self.to_dump = {}
+
+
+class _ShowHelp(argparse.Action):
+  """An argparse action to print the help text.
+
+  This is like the built in help text printing action, except it knows to do
+  nothing when we are just doing the early speculative parse of the args.
+  """
+
+  def __call__(self, parser, namespace, values, option_string=None):
+    if cr.context.speculative:
+      return
+    command = cr.Command.GetActivePlugin()
+    if command:
+      command.parser.print_help()
+    else:
+      parser.print_help()
+    exit(1)
+
+
+class _ArgumentParser(argparse.ArgumentParser):
+  """An extension of an ArgumentParser to enable speculative parsing.
+
+  It supports doing an early parse that never produces errors or output, to do
+  early collection of arguments that may affect what other arguments are
+  allowed.
+  """
+
+  def error(self, message):
+    if cr.context.speculative:
+      return
+    super(_ArgumentParser, self).error(message)
+
+  def parse_args(self):
+    if cr.context.speculative:
+      result = self.parse_known_args()
+      if result:
+        return result[0]
+      return None
+    return super(_ArgumentParser, self).parse_args()
+
+  def parse_known_args(self, args=None, namespace=None):
+    result = super(_ArgumentParser, self).parse_known_args(args, namespace)
+    if result is None:
+      return namespace, None
+    return result
+
+
+# The context stack
+_stack = []
+
+
+class _ContextData:
+  pass
+
+
+class Context(cr.config.Config):
+  """The base context holder for the cr system.
+
+  This holds the common context shared throughout cr.
+  Mostly this is stored in the Config structure of variables.
+  """
+
+  def __init__(self, name='Context'):
+    super(Context, self).__init__(name)
+    self._data = _ContextData()
+
+  def CreateData(self, description='', epilog=''):
+    self._data.args = None
+    self._data.arguments = cr.config.Config('ARGS')
+    self._data.derived = cr.config.Config('DERIVED')
+    self.AddChildren(*cr.config.GLOBALS)
+    self.AddChildren(
+        cr.config.Config('ENVIRONMENT', literal=True, export=True).Set(
+            {k: self.ParseValue(v) for k, v in os.environ.items()}),
+        self._data.arguments,
+        self._data.derived,
+    )
+    # Build the command line argument parser
+    self._data.parser = _ArgumentParser(add_help=False, description=description,
+                                        epilog=epilog)
+    self._data.subparsers = self.parser.add_subparsers()
+    # Add the global arguments
+    self.AddCommonArguments(self._data.parser)
+    self._data.gclient = {}
+
+  @property
+  def data(self):
+    return self._data
+
+  def __enter__(self):
+    """ To support using 'with cr.base.context.Create():'"""
+    _stack.append(self)
+    cr.context = self
+    return self
+
+  def __exit__(self, *_):
+    _stack.pop()
+    if _stack:
+      cr.context = _stack[-1]
+    return False
+
+  def AddSubParser(self, source):
+    parser = source.AddArguments(self._data.subparsers)
+
+  @classmethod
+  def AddCommonArguments(cls, parser):
+    """Adds the command line arguments common to all commands in cr."""
+    parser.add_argument(
+        '-h', '--help',
+        action=_ShowHelp, nargs=0,
+        help='show the help message and exit.'
+    )
+    parser.add_argument(
+        '--dry-run', dest='CR_DRY_RUN',
+        action='store_true', default=None,
+        help="""
+          Don't execute commands, just print them. Implies verbose.
+          Overrides CR_DRY_RUN
+          """
+    )
+    parser.add_argument(
+        '-v', '--verbose', dest='CR_VERBOSE',
+        action='count', default=None,
+        help="""
+          Print information about commands being performed.
+          Repeating multiple times increases the verbosity level.
+          Overrides CR_VERBOSE
+          """
+    )
+
+  @property
+  def args(self):
+    return self._data.args
+
+  @property
+  def arguments(self):
+    return self._data.arguments
+
+  @property
+  def speculative(self):
+    return self._data.speculative
+
+  @property
+  def derived(self):
+    return self._data.derived
+
+  @property
+  def parser(self):
+    return self._data.parser
+
+  @property
+  def remains(self):
+    remains = getattr(self._data.args, '_remains', None)
+    if remains and remains[0] == '--':
+      remains = remains[1:]
+    return remains
+
+  @property
+  def verbose(self):
+    if self.autocompleting:
+      return False
+    return self.Find('CR_VERBOSE') or self.dry_run
+
+  @property
+  def dry_run(self):
+    if self.autocompleting:
+      return True
+    return self.Find('CR_DRY_RUN')
+
+  @property
+  def autocompleting(self):
+    return 'COMP_WORD' in os.environ
+
+  @property
+  def gclient(self):
+    if not self._data.gclient:
+      self._data.gclient = cr.base.client.ReadGClient()
+    return self._data.gclient
+
+  def ParseArgs(self, speculative=False):
+    cr.plugin.DynamicChoices.only_active = not speculative
+    self._data.speculative = speculative
+    self._data.args = self._data.parser.parse_args()
+    self._data.arguments.Wipe()
+    if self._data.args:
+      self._data.arguments.Set(
+          {k: v for k, v in vars(self._data.args).items() if v is not None})
+
+  def DumpValues(self, with_source):
+    _DumpVisitor(with_source).VisitNode(self)
+
+
+def Create(description='', epilog=''):
+  context = Context()
+  context.CreateData(description=description, epilog=epilog)
+  return context
diff --git a/tools/cr/cr/base/host.py b/tools/cr/cr/base/host.py
index b8fb296..f60b55b 100644
--- a/tools/cr/cr/base/host.py
+++ b/tools/cr/cr/base/host.py
@@ -36,22 +36,21 @@
     return False
 
   @classmethod
-  def Select(cls, context):
+  def Select(cls):
     for host in cls.Plugins():
       if host.Matches():
         return host
 
-  def _Execute(self, context, command,
+  def _Execute(self, command,
                shell=False, capture=False, silent=False,
                ignore_dry_run=False, return_status=False,
                ignore_interrupt_signal=False):
     """This is the only method that launches external programs.
 
     It is a thin wrapper around subprocess.Popen that handles cr specific
-    issues. The command is expanded in the context, so that context variables
+    issues. The command is expanded in the active context so that variables
     are substituted.
     Args:
-      context: the cr context to run under.
       command: the command to run.
       shell: whether to run the command using the shell.
       capture: controls wether the output of the command is captured.
@@ -67,19 +66,19 @@
       the status if return_status is true, or the output if capture is true,
       otherwise nothing.
     """
-    with context.Trace():
-      command = [context.Substitute(arg) for arg in command if arg]
-    trail = context.trail
+    with cr.context.Trace():
+      command = [cr.context.Substitute(arg) for arg in command if arg]
+    trail = cr.context.trail
     if not command:
       print 'Empty command passed to execute'
       exit(1)
-    if context.verbose:
+    if cr.context.verbose:
       print ' '.join(command)
-      if context.verbose >= _TRAIL_VERBOSITY:
+      if cr.context.verbose >= _TRAIL_VERBOSITY:
         print 'Command expanded the following variables:'
         for key, value in trail:
           print '   ', key, '=', value
-    if ignore_dry_run or not context.dry_run:
+    if ignore_dry_run or not cr.context.dry_run:
       out = None
       if capture:
         out = subprocess.PIPE
@@ -88,12 +87,12 @@
       try:
         p = subprocess.Popen(
             command, shell=shell,
-            env={k: str(v) for k, v in context.exported.items()},
+            env={k: str(v) for k, v in cr.context.exported.items()},
             stdout=out)
       except OSError:
         print 'Failed to exec', command
         # Don't log the trail if we already have
-        if context.verbose < _TRAIL_VERBOSITY:
+        if cr.context.verbose < _TRAIL_VERBOSITY:
           print 'Variables used to build the command were:'
           for key, value in trail:
             print '   ', key, '=', value
@@ -116,31 +115,30 @@
     return ''
 
   @cr.Plugin.activemethod
-  def Shell(self, context, *command):
+  def Shell(self, *command):
     command = ' '.join([pipes.quote(arg) for arg in command])
-    return self._Execute(context, [command], shell=True,
-                         ignore_interrupt_signal=True)
+    return self._Execute([command], shell=True, ignore_interrupt_signal=True)
 
   @cr.Plugin.activemethod
-  def Execute(self, context, *command):
-    return self._Execute(context, command, shell=False)
+  def Execute(self, *command):
+    return self._Execute(command, shell=False)
 
   @cr.Plugin.activemethod
-  def ExecuteSilently(self, context, *command):
-    return self._Execute(context, command, shell=False, silent=True)
+  def ExecuteSilently(self, *command):
+    return self._Execute(command, shell=False, silent=True)
 
   @cr.Plugin.activemethod
-  def CaptureShell(self, context, *command):
-    return self._Execute(context, command,
+  def CaptureShell(self, *command):
+    return self._Execute(command,
                          shell=True, capture=True, ignore_dry_run=True)
 
   @cr.Plugin.activemethod
-  def Capture(self, context, *command):
-    return self._Execute(context, command, capture=True, ignore_dry_run=True)
+  def Capture(self, *command):
+    return self._Execute(command, capture=True, ignore_dry_run=True)
 
   @cr.Plugin.activemethod
-  def ExecuteStatus(self, context, *command):
-    return self._Execute(context, command,
+  def ExecuteStatus(self, *command):
+    return self._Execute(command,
                          ignore_dry_run=True, return_status=True)
 
   @cr.Plugin.activemethod
@@ -161,7 +159,7 @@
     return result in ['y', 'yes']
 
   @classmethod
-  def SearchPath(cls, name):
+  def SearchPath(cls, name, paths=[]):
     """Searches the PATH for an executable.
 
     Args:
@@ -172,7 +170,9 @@
     result = []
     extensions = ['']
     extensions.extend(os.environ.get('PATHEXT', '').split(os.pathsep))
-    for path in os.environ.get('PATH', '').split(os.pathsep):
+    paths = [cr.context.Substitute(path) for path in paths if path]
+    paths = paths + os.environ.get('PATH', '').split(os.pathsep)
+    for path in paths:
       partial = os.path.join(path, name)
       for extension in extensions:
         filename = partial + extension
diff --git a/tools/cr/cr/base/platform.py b/tools/cr/cr/base/platform.py
index db6f66d..0220d9f 100644
--- a/tools/cr/cr/base/platform.py
+++ b/tools/cr/cr/base/platform.py
@@ -39,13 +39,13 @@
   def __init__(self):
     super(Platform, self).__init__()
 
-  def Activate(self, context):
-    super(Platform, self).Activate(context)
-    if _PathFixup not in context.fixup_hooks:
-      context.fixup_hooks.append(_PathFixup)
+  def Activate(self):
+    super(Platform, self).Activate()
+    if _PathFixup not in cr.context.fixup_hooks:
+      cr.context.fixup_hooks.append(_PathFixup)
 
   @cr.Plugin.activemethod
-  def Prepare(self, context):
+  def Prepare(self):
     pass
 
   @property
@@ -53,12 +53,12 @@
     return []
 
 
-def _PathFixup(context, key, value):
+def _PathFixup(base, key, value):
   """A context fixup that does platform specific modifications to the PATH."""
   if key == 'PATH':
     paths = []
-    for entry in Platform.GetActivePlugin(context).paths:
-      entry = context.Substitute(entry)
+    for entry in Platform.GetActivePlugin().paths:
+      entry = base.Substitute(entry)
       if entry not in paths:
         paths.append(entry)
     for entry in value.split(os.path.pathsep):
diff --git a/tools/cr/cr/commands/build.py b/tools/cr/cr/commands/build.py
index 2d2c27f..1d33130 100644
--- a/tools/cr/cr/commands/build.py
+++ b/tools/cr/cr/commands/build.py
@@ -28,9 +28,9 @@
     self.ConsumeArgs(parser, 'the builder')
     return parser
 
-  def Run(self, context):
+  def Run(self):
     return cr.Builder.Build(
-        context, cr.Target.GetTargets(context), context.remains)
+        cr.Target.GetTargets(), cr.context.remains)
 
 
 class CleanCommand(cr.Command):
@@ -52,9 +52,9 @@
     self.ConsumeArgs(parser, 'the builder')
     return parser
 
-  def Run(self, context):
+  def Run(self):
     return cr.Builder.Clean(
-        context, cr.Target.GetTargets(context), context.remains)
+        cr.Target.GetTargets(), cr.context.remains)
 
 
 class RebuildCommand(cr.Command):
@@ -76,6 +76,6 @@
     self.ConsumeArgs(parser, 'the builder')
     return parser
 
-  def Run(self, context):
+  def Run(self):
     return cr.Builder.Rebuild(
-        context, cr.Target.GetTargets(context), context.remains)
+        cr.Target.GetTargets(), cr.context.remains)
diff --git a/tools/cr/cr/commands/command.py b/tools/cr/cr/commands/command.py
index d2e65a2..d42a688 100644
--- a/tools/cr/cr/commands/command.py
+++ b/tools/cr/cr/commands/command.py
@@ -18,18 +18,16 @@
   """
 
   @classmethod
-  def Select(cls, context):
+  def Select(cls):
     """Called to select which command is active.
 
     This picks a command based on the first non - argument on the command
     line.
-    Args:
-      context: The context to select the command for.
     Returns:
       the selected command, or None if not specified on the command line.
     """
-    if context.args:
-      return getattr(context.args, '_command', None)
+    if cr.context.args:
+      return getattr(cr.context.args, '_command', None)
     return None
 
   def __init__(self):
@@ -59,7 +57,7 @@
         epilog=self.epilog,
     )
     self.parser.set_defaults(_command=self)
-    cr.Context.AddCommonArguments(self.parser)
+    cr.context.AddCommonArguments(self.parser)
     cr.base.client.AddArguments(self.parser)
     return self.parser
 
@@ -78,27 +76,21 @@
         help='The additional arguments to {0}.'.format(reason)
     )
 
-  def EarlyArgProcessing(self, context):
+  def EarlyArgProcessing(self):
     """Called to make decisions based on speculative argument parsing.
 
     When this method is called, enough of the command line parsing has been
     done that the command is selected. This allows the command to make any
     modifications needed before the final argument parsing is done.
-
-    Args:
-      context: The context that is parsing the arguments.
     """
-    cr.base.client.ApplyOutArgument(context)
+    cr.base.client.ApplyOutArgument()
 
   @cr.Plugin.activemethod
-  def Run(self, context):
+  def Run(self):
     """The main method of the command.
 
     This is the only thing that a command has to implement, and it should not
     call this base version.
-    Args:
-      context: The context to run the command in.
     """
-    _ = context
     raise NotImplementedError('Must be overridden.')
 
diff --git a/tools/cr/cr/commands/debug.py b/tools/cr/cr/commands/debug.py
index 48fb513..f113691 100644
--- a/tools/cr/cr/commands/debug.py
+++ b/tools/cr/cr/commands/debug.py
@@ -27,14 +27,14 @@
     self.ConsumeArgs(parser, 'the binary')
     return parser
 
-  def Run(self, context):
-    targets = cr.Target.GetTargets(context)
-    if not cr.Debugger.ShouldInvoke(context):
-      cr.Debugger.Attach(context, targets, context.remains)
-    elif cr.Installer.Skipping(context):
-      cr.Debugger.Restart(context, targets, context.remains)
+  def Run(self):
+    targets = cr.Target.GetTargets()
+    if not cr.Debugger.ShouldInvoke():
+      cr.Debugger.Attach(targets, cr.context.remains)
+    elif cr.Installer.Skipping():
+      cr.Debugger.Restart(targets, cr.context.remains)
     else:
-      cr.Builder.Build(context, targets, [])
-      cr.Debugger.Kill(context, targets, [])
-      cr.Installer.Reinstall(context, targets, [])
-      cr.Debugger.Invoke(context, targets, context.remains)
+      cr.Builder.Build(targets, [])
+      cr.Debugger.Kill(targets, [])
+      cr.Installer.Reinstall(targets, [])
+      cr.Debugger.Invoke(targets, cr.context.remains)
diff --git a/tools/cr/cr/commands/info.py b/tools/cr/cr/commands/info.py
index 88af0f5..fcd7307 100644
--- a/tools/cr/cr/commands/info.py
+++ b/tools/cr/cr/commands/info.py
@@ -24,20 +24,20 @@
     self.ConsumeArgs(parser, 'the environment')
     return parser
 
-  def EarlyArgProcessing(self, context):
-    if getattr(context.args, '_short', False):
+  def EarlyArgProcessing(self):
+    if getattr(cr.context.args, '_short', False):
       self.requires_build_dir = False
 
-  def Run(self, context):
-    if context.remains:
-      for var in context.remains:
-        if getattr(context.args, '_short', False):
-          val = context.Find(var)
+  def Run(self):
+    if cr.context.remains:
+      for var in cr.context.remains:
+        if getattr(cr.context.args, '_short', False):
+          val = cr.context.Find(var)
           if val is None:
             val = ''
           print val
         else:
-          print var, '=', context.Find(var)
+          print var, '=', cr.context.Find(var)
     else:
-      cr.base.client.PrintInfo(context)
+      cr.base.client.PrintInfo()
 
diff --git a/tools/cr/cr/commands/init.py b/tools/cr/cr/commands/init.py
index adcb4a1..5991825 100644
--- a/tools/cr/cr/commands/init.py
+++ b/tools/cr/cr/commands/init.py
@@ -50,13 +50,13 @@
     )
     return parser
 
-  def EarlyArgProcessing(self, context):
-    base_settings = getattr(context.args, '_settings', None)
+  def EarlyArgProcessing(self):
+    base_settings = getattr(cr.context.args, '_settings', None)
     if base_settings:
       self._settings.extend(base_settings)
     # Do not call super early processing, we do not want to apply
     # the output arg...
-    out = cr.base.client.GetOutArgument(context)
+    out = cr.base.client.GetOutArgument()
     if out:
       # Output directory is fully specified
       # We need to deduce other settings from it's name
@@ -68,11 +68,12 @@
         print 'Specified build type', buildtype, 'is not valid'
         print 'Must be one of', ','.join(p.name for p in cr.BuildType.Plugins())
         exit(1)
-      if context.args.CR_BUILDTYPE and context.args.CR_BUILDTYPE != buildtype:
+      if (cr.context.args.CR_BUILDTYPE and
+          cr.context.args.CR_BUILDTYPE != buildtype):
         print 'If --type and --out are both specified, they must match'
-        print 'Got', context.args.CR_BUILDTYPE, 'and', buildtype
+        print 'Got', cr.context.args.CR_BUILDTYPE, 'and', buildtype
         exit(1)
-      platform = context.args.CR_PLATFORM
+      platform = cr.context.args.CR_PLATFORM
       if not platform:
         # Try to guess platform based on output name
         platforms = [p.name for p in cr.Platform.AllPlugins()]
@@ -84,23 +85,23 @@
             print 'Matched all of', ','.join(matches)
           exit(1)
         platform = matches[0]
-      context.derived.Set(
+      cr.context.derived.Set(
           CR_OUT_FULL=out,
           CR_OUT_BASE=base,
           CR_PLATFORM=platform,
           CR_BUILDTYPE=buildtype,
       )
-    if not 'CR_OUT_BASE' in context:
-      context.derived['CR_OUT_BASE'] = 'out_{CR_PLATFORM}'
-    if not 'CR_OUT_FULL' in context:
-      context.derived['CR_OUT_FULL'] = os.path.join(
+    if not 'CR_OUT_BASE' in cr.context:
+      cr.context.derived['CR_OUT_BASE'] = 'out_{CR_PLATFORM}'
+    if not 'CR_OUT_FULL' in cr.context:
+      cr.context.derived['CR_OUT_FULL'] = os.path.join(
           '{CR_OUT_BASE}', '{CR_BUILDTYPE}')
 
-  def Run(self, context):
+  def Run(self):
     """Overridden from cr.Command."""
-    src_path = context.Get('CR_SRC')
+    src_path = cr.context.Get('CR_SRC')
     if not os.path.isdir(src_path):
-      print context.Substitute('Path {CR_SRC} is not a valid client')
+      print cr.context.Substitute('Path {CR_SRC} is not a valid client')
       exit(1)
 
     # Ensure we have an output directory override ready to fill in
@@ -109,7 +110,7 @@
     build_package = cr.auto.build
 
     # Collect the old version (and float convert)
-    old_version = context.Find('CR_VERSION')
+    old_version = cr.context.Find('CR_VERSION')
     try:
       old_version = float(old_version)
     except (ValueError, TypeError):
@@ -132,7 +133,7 @@
     build_package.config.OVERRIDES.Set(CR_VERSION=cr.base.client.VERSION)
     # Add all the variables that we always want to have
     for name in OUT_CONFIG_VARS:
-      value = context.Find(name)
+      value = cr.context.Find(name)
       build_package.config.OVERRIDES[name] = value
     # Apply the settings from the command line
     for setting in self._settings:
@@ -146,16 +147,16 @@
 
     # Run all the output directory init hooks
     for hook in InitHook.Plugins():
-      hook.Run(context, old_version, build_package.config)
+      hook.Run(old_version, build_package.config)
     # Redo activations, they might have changed
-    cr.plugin.Activate(context)
+    cr.plugin.Activate()
 
     # Write out the new configuration, and select it as the default
-    cr.base.client.WriteConfig(context, context.Get('CR_BUILD_DIR'),
+    cr.base.client.WriteConfig(cr.context.Get('CR_BUILD_DIR'),
                                build_package.config.OVERRIDES.exported)
     # Prepare the platform in here, using the updated config
-    cr.Platform.Prepare(context)
-    cr.SelectCommand.Select(context)
+    cr.Platform.Prepare()
+    cr.SelectCommand.Select()
 
 
 class InitHook(cr.Plugin, cr.Plugin.Type):
@@ -165,12 +166,11 @@
   cr.fixups package.
   """
 
-  def Run(self, context, old_version, config):
+  def Run(self, old_version, config):
     """Run the initialization hook.
 
     This is invoked once per init invocation.
     Args:
-      context: The context of the init command.
       old_version: The old version,
           0.0 if the old version was bad or missing,
           None if building a new output direcory.
diff --git a/tools/cr/cr/commands/install.py b/tools/cr/cr/commands/install.py
index 51a02b3..20e1dff 100644
--- a/tools/cr/cr/commands/install.py
+++ b/tools/cr/cr/commands/install.py
@@ -29,8 +29,8 @@
     self.ConsumeArgs(parser, 'the installer')
     return parser
 
-  def Run(self, context):
-    targets = cr.Target.GetTargets(context)
-    if not cr.Installer.Skipping(context):
-      cr.Builder.Build(context, targets, [])
-    cr.Installer.Reinstall(context, targets, context.remains)
+  def Run(self):
+    targets = cr.Target.GetTargets()
+    if not cr.Installer.Skipping():
+      cr.Builder.Build(targets, [])
+    cr.Installer.Reinstall(targets, cr.context.remains)
diff --git a/tools/cr/cr/commands/prepare.py b/tools/cr/cr/commands/prepare.py
index 57abcce..a9418d9 100644
--- a/tools/cr/cr/commands/prepare.py
+++ b/tools/cr/cr/commands/prepare.py
@@ -26,13 +26,13 @@
         running gyp.
         """)
 
-  def Run(self, context):
-    self.Prepare(context)
+  def Run(self):
+    self.Prepare()
 
   @classmethod
-  def Prepare(cls, context):
+  def Prepare(cls):
     for preparation in PrepareOut.Plugins():
-      preparation.Prepare(context)
+      preparation.Prepare()
 
 
 class PrepareOut(cr.Plugin, cr.Plugin.Type):
@@ -41,8 +41,7 @@
   See PrepareCommand for details.
   """
 
-  def Prepare(self, context):
+  def Prepare(self):
     """All PrepareOut plugins must override this method to do their work."""
-    _ = context
     raise NotImplementedError('Must be overridden.')
 
diff --git a/tools/cr/cr/commands/run.py b/tools/cr/cr/commands/run.py
index 9b57d94..cbfc421 100644
--- a/tools/cr/cr/commands/run.py
+++ b/tools/cr/cr/commands/run.py
@@ -29,22 +29,22 @@
     self.ConsumeArgs(parser, 'the binary')
     return parser
 
-  def Run(self, context):
-    targets = cr.Target.GetTargets(context)
+  def Run(self):
+    targets = cr.Target.GetTargets()
     test_targets = [target for target in targets if target.is_test]
     run_targets = [target for target in targets if not target.is_test]
-    if cr.Installer.Skipping(context):
+    if cr.Installer.Skipping():
       # No installer, only build test targets
       build_targets = test_targets
     else:
       build_targets = targets
     if build_targets:
-      cr.Builder.Build(context, build_targets, [])
+      cr.Builder.Build(build_targets, [])
     # See if we can use restart when not installing
-    if cr.Installer.Skipping(context):
-      cr.Runner.Restart(context, targets, context.remains)
+    if cr.Installer.Skipping():
+      cr.Runner.Restart(targets, cr.context.remains)
     else:
-      cr.Runner.Kill(context, run_targets, [])
-      cr.Installer.Reinstall(context, run_targets, [])
-      cr.Runner.Invoke(context, targets, context.remains)
+      cr.Runner.Kill(run_targets, [])
+      cr.Installer.Reinstall(run_targets, [])
+      cr.Runner.Invoke(targets, cr.context.remains)
 
diff --git a/tools/cr/cr/commands/select.py b/tools/cr/cr/commands/select.py
index 58cebdd..eadd109 100644
--- a/tools/cr/cr/commands/select.py
+++ b/tools/cr/cr/commands/select.py
@@ -40,22 +40,20 @@
         help='Don\'t prepare the output directory.'
     )
 
-  def Run(self, context):
-    self.Select(context)
+  def Run(self):
+    self.Select()
 
   @classmethod
-  def Select(cls, context):
+  def Select(cls):
     """Performs the select.
 
     This is also called by the init command to auto select the new output
     directory.
-    Args:
-      context: The cr Context to select in.
     """
     cr.base.client.WriteConfig(
-        context, context.Get('CR_CLIENT_PATH'), dict(
-            CR_OUT_FULL=context.Get('CR_OUT_FULL')))
-    cr.base.client.PrintInfo(context)
+        cr.context.Get('CR_CLIENT_PATH'), dict(
+            CR_OUT_FULL=cr.context.Get('CR_OUT_FULL')))
+    cr.base.client.PrintInfo()
     # Now we run the post select actions
-    if not getattr(context.args, '_no_prepare', None):
-      cr.PrepareCommand.Prepare(context)
+    if not getattr(cr.context.args, '_no_prepare', None):
+      cr.PrepareCommand.Prepare()
diff --git a/tools/cr/cr/commands/shell.py b/tools/cr/cr/commands/shell.py
index 452ebb7..2cd338d 100644
--- a/tools/cr/cr/commands/shell.py
+++ b/tools/cr/cr/commands/shell.py
@@ -35,9 +35,9 @@
     self.ConsumeArgs(parser, 'the shell')
     return parser
 
-  def Run(self, context):
-    if context.remains:
-      cr.Host.Shell(context, *context.remains)
+  def Run(self):
+    if cr.context.remains:
+      cr.Host.Shell(*cr.context.remains)
       return
     # If we get here, we are trying to launch an interactive shell
     shell = os.environ.get('SHELL', None)
@@ -48,6 +48,6 @@
       with tempfile.NamedTemporaryFile() as rcfile:
         rcfile.write('source ~/.bashrc\nPS1="'+ps1+'"')
         rcfile.flush()
-        cr.Host.Execute(context, shell, '--rcfile', rcfile.name)
+        cr.Host.Execute(shell, '--rcfile', rcfile.name)
     else:
-      cr.Host.Execute(context, shell)
+      cr.Host.Execute(shell)
diff --git a/tools/cr/cr/commands/sync.py b/tools/cr/cr/commands/sync.py
index c18187f..c7e6e70 100644
--- a/tools/cr/cr/commands/sync.py
+++ b/tools/cr/cr/commands/sync.py
@@ -36,17 +36,16 @@
     # TODO(iancottrell): clean no-hooks support would be nice.
     return parser
 
-  def Run(self, context):
-    self.Sync(context, context.remains)
+  def Run(self):
+    self.Sync(cr.context.remains)
 
   @staticmethod
-  def Sync(context, args):
+  def Sync(args):
     # TODO(iancottrell): we should probably run the python directly,
     # rather than the shell wrapper
     # TODO(iancottrell): try to help out when the local state is not a good
     # one to do a sync in
-    cr.Host.Execute(context, '{GCLIENT_BINARY}', 'sync', *args)
-
+    cr.Host.Execute('{GCLIENT_BINARY}', 'sync', *args)
 
   @classmethod
   def ClassInit(cls):
diff --git a/tools/cr/cr/config.py b/tools/cr/cr/config.py
index a19b837..5b4ca8e 100644
--- a/tools/cr/cr/config.py
+++ b/tools/cr/cr/config.py
@@ -97,13 +97,13 @@
     Returns:
         A dynamic value.
     """
-    def Resolve(context):
-      test = context.Get(condition)
+    def Resolve(base):
+      test = base.Get(condition)
       if test:
         value = true_value
       else:
         value = false_value
-      return context.Substitute(value)
+      return base.Substitute(value)
     return Resolve
 
   @classmethod
@@ -116,11 +116,11 @@
     Returns:
         value if it resolves, alternate otherwise.
     """
-    def Resolve(context):
+    def Resolve(base):
       try:
-        return context.Substitute(value)
+        return base.Substitute(value)
       except KeyError:
-        return context.Substitute(alternate)
+        return base.Substitute(alternate)
     return Resolve
 
   def __init__(self, name='--', literal=False, export=None, enabled=True):
diff --git a/tools/cr/cr/context.py b/tools/cr/cr/context.py
deleted file mode 100644
index 176961e..0000000
--- a/tools/cr/cr/context.py
+++ /dev/null
@@ -1,223 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Application context management for the cr tool.
-
-Contains all the support code to enable the shared context used by the cr tool.
-This includes the configuration variables and command line handling.
-"""
-
-import argparse
-import os
-import cr
-
-
-class _DumpVisitor(cr.visitor.ExportVisitor):
-  """A visitor that prints all variables in a config hierarchy."""
-
-  def __init__(self, with_source):
-    super(_DumpVisitor, self).__init__({})
-    self.to_dump = {}
-    self.with_source = with_source
-
-  def StartNode(self):
-    if self.with_source:
-      self._DumpNow()
-    super(_DumpVisitor, self).StartNode()
-
-  def EndNode(self):
-    if self.with_source or not self.stack:
-      self._DumpNow()
-    super(_DumpVisitor, self).EndNode()
-    if not self.stack:
-      self._DumpNow()
-
-  def Visit(self, key, value):
-    super(_DumpVisitor, self).Visit(key, value)
-    if key in self.store:
-      str_value = str(self.store[key])
-      if str_value != str(os.environ.get(key, None)):
-        self.to_dump[key] = str_value
-
-  def _DumpNow(self):
-    if self.to_dump:
-      if self.with_source:
-        print 'From', self.Where()
-      for key in sorted(self.to_dump.keys()):
-        print '  ', key, '=', self.to_dump[key]
-      self.to_dump = {}
-
-
-class _ShowHelp(argparse.Action):
-  """An argparse action to print the help text.
-
-  This is like the built in help text printing action, except it knows to do
-  nothing when we are just doing the early speculative parse of the args.
-  """
-
-  def __call__(self, parser, namespace, values, option_string=None):
-    if parser.context.speculative:
-      return
-    command = cr.Command.GetActivePlugin(parser.context)
-    if command:
-      command.parser.print_help()
-    else:
-      parser.print_help()
-    exit(1)
-
-
-class _ArgumentParser(argparse.ArgumentParser):
-  """An extension of an ArgumentParser to enable speculative parsing.
-
-  It supports doing an early parse that never produces errors or output, to do
-  early collection of arguments that may affect what other arguments are
-  allowed.
-  """
-
-  def error(self, message):
-    if self.context.speculative:
-      return
-    super(_ArgumentParser, self).error(message)
-
-  def parse_args(self):
-    if self.context.speculative:
-      result = self.parse_known_args()
-      if result:
-        return result[0]
-      return None
-    return super(_ArgumentParser, self).parse_args()
-
-  def parse_known_args(self, args=None, namespace=None):
-    result = super(_ArgumentParser, self).parse_known_args(args, namespace)
-    if result is None:
-      return namespace, None
-    return result
-
-
-class Context(cr.config.Config, cr.loader.AutoExport):
-  """The base context holder for the cr system.
-
-  This is passed to almost all methods in the cr system, and holds the common
-  context they all shared. Mostly this is stored in the Config structure of
-  variables.
-  """
-
-  def __init__(self, description='', epilog=''):
-    super(Context, self).__init__('Context')
-    self._args = None
-    self._arguments = cr.config.Config('ARGS')
-    self._derived = cr.config.Config('DERIVED')
-    self.AddChildren(*cr.config.GLOBALS)
-    self.AddChildren(
-        cr.config.Config('ENVIRONMENT', literal=True, export=True).Set(
-            {k: self.ParseValue(v) for k, v in os.environ.items()}),
-        self._arguments,
-        self._derived,
-    )
-    # Build the command line argument parser
-    self._parser = _ArgumentParser(add_help=False, description=description,
-                                   epilog=epilog)
-    self._parser.context = self
-    self._subparsers = self.parser.add_subparsers()
-    # Add the global arguments
-    self.AddCommonArguments(self._parser)
-    self._gclient = {}
-    # Try to detect the current client information
-    cr.base.client.DetectClient(self)
-
-  def AddSubParser(self, source):
-    parser = source.AddArguments(self._subparsers)
-    parser.context = self
-
-  @classmethod
-  def AddCommonArguments(cls, parser):
-    """Adds the command line arguments common to all commands in cr."""
-    parser.add_argument(
-        '-h', '--help',
-        action=_ShowHelp, nargs=0,
-        help='show the help message and exit.'
-    )
-    parser.add_argument(
-        '--dry-run', dest='CR_DRY_RUN',
-        action='store_true', default=None,
-        help="""
-          Don't execute commands, just print them. Implies verbose.
-          Overrides CR_DRY_RUN
-          """
-    )
-    parser.add_argument(
-        '-v', '--verbose', dest='CR_VERBOSE',
-        action='count', default=None,
-        help="""
-          Print information about commands being performed.
-          Repeating multiple times increases the verbosity level.
-          Overrides CR_VERBOSE
-          """
-    )
-
-  @property
-  def args(self):
-    return self._args
-
-  @property
-  def arguments(self):
-    return self._arguments
-
-  @property
-  def speculative(self):
-    return self._speculative
-
-  @property
-  def derived(self):
-    return self._derived
-
-  @property
-  def parser(self):
-    return self._parser
-
-  @property
-  def remains(self):
-    remains = getattr(self._args, '_remains', None)
-    if remains and remains[0] == '--':
-      remains = remains[1:]
-    return remains
-
-  @property
-  def verbose(self):
-    if self.autocompleting:
-      return False
-    return self.Find('CR_VERBOSE') or self.dry_run
-
-  @property
-  def dry_run(self):
-    if self.autocompleting:
-      return True
-    return self.Find('CR_DRY_RUN')
-
-  @property
-  def autocompleting(self):
-    return 'COMP_WORD' in os.environ
-
-  @property
-  def gclient(self):
-    if not self._gclient:
-      self._gclient = cr.base.client.ReadGClient(self)
-    return self._gclient
-
-  def WriteGClient(self):
-    if self._gclient:
-      cr.base.client.WriteGClient(self)
-
-  def ParseArgs(self, speculative=False):
-    cr.plugin.DynamicChoices.only_active = not speculative
-    self._speculative = speculative
-    self._args = self._parser.parse_args()
-    self._arguments.Wipe()
-    if self._args:
-      self._arguments.Set(
-          {k: v for k, v in vars(self._args).items() if v is not None})
-
-  def DumpValues(self, with_source):
-    _DumpVisitor(with_source).VisitNode(self)
-
diff --git a/tools/cr/cr/fixups/arch.py b/tools/cr/cr/fixups/arch.py
index e6ac81c..a756272 100644
--- a/tools/cr/cr/fixups/arch.py
+++ b/tools/cr/cr/fixups/arch.py
@@ -17,7 +17,7 @@
   def _ArchConvert(self, old_arch):
     return old_arch
 
-  def Run(self, context, old_version, config):
+  def Run(self, old_version, config):
     if old_version is None or not self._VersionTest(old_version):
       return
     old_arch = config.OVERRIDES.Find(cr.Arch.SELECTOR)
diff --git a/tools/cr/cr/loader.py b/tools/cr/cr/loader.py
index 51dc940..9a5aaca 100644
--- a/tools/cr/cr/loader.py
+++ b/tools/cr/cr/loader.py
@@ -109,6 +109,7 @@
         # Try this one again, if progress was made on a possible dependency
         remains.append(name)
   if remains:
+    print "Cannot load all of", remains
     # There are modules that won't import in any order.
     # Print all the errors as we can't determine root cause.
     for name in remains:
diff --git a/tools/cr/cr/plugin.py b/tools/cr/cr/plugin.py
index 824d2c5..1dbf9f5 100644
--- a/tools/cr/cr/plugin.py
+++ b/tools/cr/cr/plugin.py
@@ -104,8 +104,8 @@
       self.method = method
 
     def __get__(self, instance, owner):
-      def unbound(context, *args, **kwargs):
-        active = owner.GetActivePlugin(context)
+      def unbound(*args, **kwargs):
+        active = owner.GetActivePlugin()
         if not active:
           print 'No active', owner.__name__
           exit(1)
@@ -113,10 +113,10 @@
         if not method:
           print owner.__name__, 'does not support', self.method.__name__
           exit(1)
-        return method(context, *args, **kwargs)
+        return method(*args, **kwargs)
 
-      def bound(context, *args, **kwargs):
-        return self.method(instance, context, *args, **kwargs)
+      def bound(*args, **kwargs):
+        return self.method(instance, *args, **kwargs)
 
       if instance is None:
         return unbound
@@ -167,7 +167,7 @@
   def is_active(self):
     return self._is_active
 
-  def Activate(self, unused_context):
+  def Activate(self):
     assert not self._is_active
     self._is_active = True
     for config_root in CONFIG_TYPES:
@@ -265,17 +265,15 @@
     return [plugin for plugin in cls.UnorderedPlugins() if plugin.is_active]
 
   @classmethod
-  def GetActivePlugin(cls, context):
+  def GetActivePlugin(cls):
     """Gets the active plugin of type cls.
 
     This method will select a plugin to be the active one, and will activate
     the plugin if needed.
-    Args:
-      context: The context to select the active plugin for.
     Returns:
       the plugin that is currently active.
     """
-    plugin, _ = _GetActivePlugin(cls, context)
+    plugin, _ = _GetActivePlugin(cls)
     return plugin
 
   @classproperty
@@ -288,14 +286,14 @@
     return result
 
   @classmethod
-  def Select(cls, context):
+  def Select(cls):
     """Called to determine which plugin should be the active one."""
     plugin = cls.default
     selector = getattr(cls, 'SELECTOR', None)
     if selector:
       if plugin is not None:
         _selectors[selector] = plugin.name
-      name = context.Find(selector)
+      name = cr.context.Find(selector)
       if name is not None:
         plugin = cls.FindPlugin(name)
     return plugin
@@ -313,26 +311,26 @@
 cr.loader.scan_hooks.append(ChainModuleConfigs)
 
 
-def _GetActivePlugin(cls, context):
+def _GetActivePlugin(cls):
   activated = False
   actives = cls.GetAllActive()
-  plugin = cls.Select(context)
+  plugin = cls.Select()
   for active in actives:
     if active != plugin:
       active.Deactivate()
   if plugin and not plugin.is_active:
     activated = True
-    plugin.Activate(context)
+    plugin.Activate()
   return plugin, activated
 
 
-def Activate(context):
+def Activate():
   """Activates a plugin for all known plugin types."""
   types = Plugin.Type.__subclasses__()
   modified = True
   while modified:
     modified = False
     for child in types:
-      _, activated = _GetActivePlugin(child, context)
+      _, activated = _GetActivePlugin(child)
       if activated:
         modified = True
diff --git a/tools/cr/cr/targets/target.py b/tools/cr/cr/targets/target.py
index 0780ae9..cef67f2 100644
--- a/tools/cr/cr/targets/target.py
+++ b/tools/cr/cr/targets/target.py
@@ -7,13 +7,14 @@
 import re
 
 import cr
+import cr.base.context
 
 DEFAULT = cr.Config.From(
     CR_DEFAULT_TARGET='chrome',
 )
 
 
-class Target(cr.Config, cr.AutoExport):
+class Target(cr.base.context.Context, cr.AutoExport):
   """Base class for implementing cr targets.
 
   A target is something that can be built and run.
@@ -31,9 +32,8 @@
   # TODO(iancottrell): support the other test types
   TEST_TYPES = [NOT_A_TEST, NORMAL_TEST]
 
-  def  __init__(self, context, target_name):
+  def  __init__(self, target_name):
     super(Target, self).__init__(target_name)
-    self.context = context
     test_type = None
     if self.TEST_PATTERN.search(target_name):
       test_type = self.NORMAL_TEST
@@ -45,7 +45,8 @@
         CR_RUN_ARGUMENTS='',
         CR_TEST_TYPE=test_type,
     )
-    self.AddChildren(config, context)
+    self._data = cr.context.data
+    self.AddChildren(config, cr.context)
     if hasattr(self, 'CONFIG'):
       self.AddChild(self.CONFIG)
     if not self.valid:
@@ -58,16 +59,8 @@
     return self.Get('CR_BUILD_TARGET')
 
   @property
-  def verbose(self):
-    return self.context.verbose
-
-  @property
-  def dry_run(self):
-    return self.context.dry_run
-
-  @property
   def valid(self):
-    return cr.Builder.IsTarget(self.context, self.build_target)
+    return cr.Builder.IsTarget(self.build_target)
 
   @property
   def is_test(self):
@@ -94,14 +87,13 @@
         yield t
 
   @classmethod
-  def CreateTarget(cls, context, target_name):
+  def CreateTarget(cls, target_name):
     """Attempts to build a target by name.
 
     This searches the set of installed targets in priority order to see if any
     of them are willing to handle the supplied name.
     If a target cannot be found, the program will be aborted.
     Args:
-      context: The context to run in.
       target_name: The name of the target we are searching for.
     Returns:
       The target that matched.
@@ -112,12 +104,12 @@
         reverse=True
     )
     for handler in target_clses:
-      target = handler.Build(context, target_name)
+      target = handler.Build(target_name)
       if target:
         if not target.valid:
           print 'Invalid target {0} as {1}'.format(
               target_name, target.build_target)
-          guesses = cr.Builder.GuessTargets(context, target_name)
+          guesses = cr.Builder.GuessTargets(target_name)
           if guesses:
             print 'Did you mean {0}?'.format(
                 ', '.join(guesses[:-1]) + ' or ' + guesses[-1]
@@ -128,19 +120,19 @@
     exit(1)
 
   @classmethod
-  def GetTargets(cls, context):
-    target_names = getattr(context.args, '_targets', None)
+  def GetTargets(cls):
+    target_names = getattr(cr.context.args, '_targets', None)
     if not target_names:
-      target_names = [context.Get('CR_DEFAULT_TARGET')]
+      target_names = [cr.context.Get('CR_DEFAULT_TARGET')]
     elif hasattr(target_names, 'swapcase'):
       # deal with the single target case
       target_names = [target_names]
-    return [cls.CreateTarget(context, target_name)
+    return [cls.CreateTarget(target_name)
             for target_name in target_names]
 
   @classmethod
-  def Build(cls, context, target_name):
-    return cls(context, target_name)
+  def Build(cls, target_name):
+    return cls(target_name)
 
 
 class NamedTarget(Target):
@@ -153,10 +145,10 @@
   PRIORITY = Target.PRIORITY + 1
 
   @classmethod
-  def Build(cls, context, target_name):
+  def Build(cls, target_name):
     try:
       if target_name == cls.NAME:
-        return cls(context, target_name)
+        return cls(target_name)
     except AttributeError:
       pass
     return None
diff --git a/tools/cr/main.py b/tools/cr/main.py
index dced8cd..3dd63bd 100644
--- a/tools/cr/main.py
+++ b/tools/cr/main.py
@@ -13,6 +13,7 @@
 import cr.auto.user
 import cr.autocomplete
 import cr.loader
+import cr.base.context
 
 _CONTACT = 'iancottrell@chromium.org'
 
@@ -32,63 +33,67 @@
   cr.loader.Scan()
 
   # Build the command context
-  context = cr.Context(
+  with cr.base.context.Create(
       description='The chrome dev build tool.',
       epilog='Contact ' + _CONTACT + ' if you have issues with this tool.',
-  )
-  # Install the sub-commands
-  for command in cr.Command.Plugins():
-    context.AddSubParser(command)
+      ) as context:
 
-  # test for the special autocomplete command
-  if context.autocompleting:
-    # After plugins are loaded so pylint: disable=g-import-not-at-top
-    cr.autocomplete.Complete(context)
-    return
-  # Speculative argument processing to add config specific args
-  context.ParseArgs(True)
-  cr.plugin.Activate(context)
-  # At this point we should know what command we are going to use
-  command = cr.Command.GetActivePlugin(context)
-  # Do some early processing, in case it changes the build dir
-  if command:
-    command.EarlyArgProcessing(context)
-  # Update the activated set again, in case the early processing changed it
-  cr.plugin.Activate(context)
-  # Load the build specific configuration
-  found_build_dir = cr.base.client.LoadConfig(context)
-  # Final processing or arguments
-  context.ParseArgs()
-  cr.plugin.Activate(context)
-  # If we did not get a command before, it might have been fixed.
-  if command is None:
-    command = cr.Command.GetActivePlugin(context)
-  # If the verbosity level is 3 or greater, then print the environment here
-  if context.verbose >= 3:
-    context.DumpValues(context.verbose > 3)
-  if command is None:
-    print context.Substitute('No command specified.')
-    exit(1)
-  if command.requires_build_dir:
-    if not found_build_dir:
-      if not context.Find('CR_OUT_FULL'):
-        print context.Substitute(
-            'No build directory specified. Please use cr init to make one.')
-      else:
-        print context.Substitute(
-            'Build {CR_BUILD_DIR} not a valid build directory')
+    # Try to detect the current client information
+    cr.base.client.DetectClient()
+
+    # Install the sub-commands
+    for command in cr.Command.Plugins():
+      cr.context.AddSubParser(command)
+
+    # test for the special autocomplete command
+    if cr.context.autocompleting:
+      # After plugins are loaded so pylint: disable=g-import-not-at-top
+      cr.autocomplete.Complete()
+      return
+    # Speculative argument processing to add config specific args
+    cr.context.ParseArgs(True)
+    cr.plugin.Activate()
+    # At this point we should know what command we are going to use
+    command = cr.Command.GetActivePlugin()
+    # Do some early processing, in case it changes the build dir
+    if command:
+      command.EarlyArgProcessing()
+    # Update the activated set again, in case the early processing changed it
+    cr.plugin.Activate()
+    # Load the build specific configuration
+    found_build_dir = cr.base.client.LoadConfig()
+    # Final processing or arguments
+    cr.context.ParseArgs()
+    cr.plugin.Activate()
+    # If we did not get a command before, it might have been fixed.
+    if command is None:
+      command = cr.Command.GetActivePlugin()
+    # If the verbosity level is 3 or greater, then print the environment here
+    if cr.context.verbose >= 3:
+      cr.context.DumpValues(cr.context.verbose > 3)
+    if command is None:
+      print cr.context.Substitute('No command specified.')
       exit(1)
-    if context.Find('CR_VERSION') != cr.base.client.VERSION:
-      print context.Substitute(
-          'Build {CR_BUILD_DIR} is for the wrong version of cr')
-      print 'Please run cr init to reset it'
-      exit(1)
-    cr.Platform.Prepare(context)
-  if context.verbose >= 1:
-    print context.Substitute(
-        'Running cr ' + command.name + ' for {CR_BUILD_DIR}')
-  # Invoke the given command
-  command.Run(context)
+    if command.requires_build_dir:
+      if not found_build_dir:
+        if not cr.context.Find('CR_OUT_FULL'):
+          print cr.context.Substitute(
+              'No build directory specified. Please use cr init to make one.')
+        else:
+          print cr.context.Substitute(
+              'Build {CR_BUILD_DIR} not a valid build directory')
+        exit(1)
+      if cr.context.Find('CR_VERSION') != cr.base.client.VERSION:
+        print cr.context.Substitute(
+            'Build {CR_BUILD_DIR} is for the wrong version of cr')
+        print 'Please run cr init to reset it'
+        exit(1)
+      cr.Platform.Prepare()
+    if cr.context.verbose >= 1:
+      print cr.context.Substitute(
+          'Running cr ' + command.name + ' for {CR_BUILD_DIR}')
+    # Invoke the given command
+    command.Run()
 
 if __name__ == '__main__':
   sys.exit(Main())
diff --git a/tools/gn/BUILD.gn b/tools/gn/BUILD.gn
index badfb0b..8665bbf 100644
--- a/tools/gn/BUILD.gn
+++ b/tools/gn/BUILD.gn
@@ -2,16 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-gyp_file = "gn.gyp"
-external = true
-
-# Not defined when doing a GYP build, this lets the code key off of GN-specific
-# features (the last change target). This can be removed when the last change
-# target is supported by the GN->GYP converter (see is_gyp conditional for that
-# below).
-if (!is_gyp) {
-  defines = [ "GN_BUILD" ]
-}
+defines = [ "GN_BUILD" ]
 
 static_library("gn_lib") {
   sources = [
@@ -32,7 +23,6 @@
     "command_args.cc",
     "command_desc.cc",
     "command_gen.cc",
-    "command_gyp.cc",
     "command_help.cc",
     "command_refs.cc",
     "commands.cc",
@@ -69,14 +59,6 @@
     "function_write_file.cc",
     "group_target_generator.cc",
     "group_target_generator.h",
-    "gyp_binary_target_writer.cc",
-    "gyp_binary_target_writer.h",
-    "gyp_helper.cc",
-    "gyp_helper.h",
-    "gyp_action_target_writer.cc",
-    "gyp_action_target_writer.h",
-    "gyp_target_writer.cc",
-    "gyp_target_writer.h",
     "import_manager.cc",
     "import_manager.h",
     "input_conversion.cc",
@@ -145,6 +127,8 @@
     "target.h",
     "target_generator.cc",
     "target_generator.h",
+    "template.cc",
+    "template.h",
     "token.cc",
     "token.h",
     "tokenizer.cc",
@@ -174,11 +158,8 @@
 
   deps = [
     ":gn_lib",
+    "//build/util:last_change",
   ]
-  if (!is_gyp) {
-    # Currently this only works in GYP (see GN_BUILD above).
-    deps += [ "//build/util:last_change" ]
-  }
 }
 
 test("gn_unittests") {
@@ -188,8 +169,7 @@
     "filesystem_utils_unittest.cc",
     "file_template_unittest.cc",
     "function_rebase_path_unittest.cc",
-    "gyp_action_target_writer_unittest.cc",
-    "gyp_binary_target_writer_unittest.cc",
+    "functions_unittest.cc",
     "input_conversion_unittest.cc",
     "label_unittest.cc",
     "loader_unittest.cc",
@@ -198,6 +178,7 @@
     "ninja_copy_target_writer_unittest.cc",
     "ninja_helper_unittest.cc",
     "operators_unittest.cc",
+    "parse_tree_unittest.cc",
     "parser_unittest.cc",
     "path_output_unittest.cc",
     "pattern_unittest.cc",
diff --git a/tools/gn/action_target_generator.cc b/tools/gn/action_target_generator.cc
index 5f8f959..c51910c 100644
--- a/tools/gn/action_target_generator.cc
+++ b/tools/gn/action_target_generator.cc
@@ -44,10 +44,6 @@
 void ActionTargetGenerator::DoRun() {
   target_->set_output_type(output_type_);
 
-  FillExternal();
-  if (err_->has_error())
-    return;
-
   FillSources();
   if (err_->has_error())
     return;
diff --git a/tools/gn/bin/linux/gn.sha1 b/tools/gn/bin/linux/gn.sha1
index 7ab9462..06beae3 100644
--- a/tools/gn/bin/linux/gn.sha1
+++ b/tools/gn/bin/linux/gn.sha1
@@ -1 +1 @@
-5e091a30ac05dbbf99977d253ab51eaf4959e1a5
\ No newline at end of file
+19d0fda98eff41476d011f24ccc40e9740d8eb5c
\ No newline at end of file
diff --git a/tools/gn/bin/linux/gn32.sha1 b/tools/gn/bin/linux/gn32.sha1
index 66cd7a2..a0ee6b0 100644
--- a/tools/gn/bin/linux/gn32.sha1
+++ b/tools/gn/bin/linux/gn32.sha1
@@ -1 +1 @@
-b37f3698a39fc4ed4306d1562b25b9e1b59c89fc
\ No newline at end of file
+fdbb87e903677c6aeb66ba0e0edf1e7ffaef32bc
\ No newline at end of file
diff --git a/tools/gn/bin/mac/gn.sha1 b/tools/gn/bin/mac/gn.sha1
index da41a2b..6c7c4fc 100644
--- a/tools/gn/bin/mac/gn.sha1
+++ b/tools/gn/bin/mac/gn.sha1
@@ -1 +1 @@
-f2a693592b8d143ed698f1cdf9d71316b248d087
+21ac865cd8d426cf46c1061190c7bd5e98d5fe3f
diff --git a/tools/gn/bin/win/gn.exe.sha1 b/tools/gn/bin/win/gn.exe.sha1
index 1bb1ea0..e56a968 100644
--- a/tools/gn/bin/win/gn.exe.sha1
+++ b/tools/gn/bin/win/gn.exe.sha1
@@ -1 +1 @@
-2e3f8dbc942cac53fbec61d3a8f46a1ebd60d9a7
+a6e110ec959cd56c82e0c8d03546209f85ff2ac8
diff --git a/tools/gn/binary_target_generator.cc b/tools/gn/binary_target_generator.cc
index b287fe9..3e36297 100644
--- a/tools/gn/binary_target_generator.cc
+++ b/tools/gn/binary_target_generator.cc
@@ -33,10 +33,6 @@
   if (err_->has_error())
     return;
 
-  FillExternal();
-  if (err_->has_error())
-    return;
-
   FillSources();
   if (err_->has_error())
     return;
diff --git a/tools/gn/builder_unittest.cc b/tools/gn/builder_unittest.cc
index e605b9e..34824ba 100644
--- a/tools/gn/builder_unittest.cc
+++ b/tools/gn/builder_unittest.cc
@@ -35,20 +35,8 @@
     return files_.empty();
   }
 
-  // Returns true if one load has been requested and it matches the given
+  // Returns true if two loads have been requested and they match the given
   // file. This will clear the records so it will be empty for the next call.
-  bool HasLoadedOne(const SourceFile& f) {
-    if (files_.size() != 1u) {
-      files_.clear();
-      return false;
-    }
-
-    bool match = (files_[0] == f);
-    files_.clear();
-    return match;
-  }
-
-  // Like HasLoadedOne above. Accepts any ordering.
   bool HasLoadedTwo(const SourceFile& a, const SourceFile& b) {
     if (files_.size() != 2u) {
       files_.clear();
diff --git a/tools/gn/command_desc.cc b/tools/gn/command_desc.cc
index 4917dcf..a4a7fd0 100644
--- a/tools/gn/command_desc.cc
+++ b/tools/gn/command_desc.cc
@@ -186,11 +186,6 @@
     out << "    " << str << "\n";
   }
 };
-template<> struct DescValueWriter<SourceFile> {
-  void operator()(const SourceFile& file, std::ostream& out) const {
-    out << "    " << file.value() << "\n";
-  }
-};
 template<> struct DescValueWriter<SourceDir> {
   void operator()(const SourceDir& dir, std::ostream& out) const {
     out << "    " << FormatSourceDir(dir) << "\n";
diff --git a/tools/gn/command_gyp.cc b/tools/gn/command_gyp.cc
deleted file mode 100644
index 011f158..0000000
--- a/tools/gn/command_gyp.cc
+++ /dev/null
@@ -1,553 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <iostream>
-#include <map>
-#include <utility>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/environment.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/timer/elapsed_timer.h"
-#include "build/build_config.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/commands.h"
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/gyp_helper.h"
-#include "tools/gn/gyp_target_writer.h"
-#include "tools/gn/location.h"
-#include "tools/gn/parser.h"
-#include "tools/gn/setup.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/standard_out.h"
-#include "tools/gn/target.h"
-#include "tools/gn/tokenizer.h"
-
-namespace commands {
-
-namespace {
-
-typedef GypTargetWriter::TargetGroup TargetGroup;
-typedef std::map<Label, TargetGroup> CorrelatedTargetsMap;
-typedef std::map<SourceFile, std::vector<TargetGroup> > GroupedTargetsMap;
-typedef std::map<std::string, std::string> StringStringMap;
-typedef std::vector<const BuilderRecord*> RecordVector;
-
-struct Setups {
-  Setups()
-      : debug(NULL),
-        release(NULL),
-        debug64(NULL),
-        release64(NULL),
-        xcode_debug(NULL),
-        xcode_release(NULL) {
-  }
-
-  Setup* debug;
-  DependentSetup* release;
-  DependentSetup* debug64;
-  DependentSetup* release64;
-  DependentSetup* xcode_debug;
-  DependentSetup* xcode_release;
-};
-
-struct TargetVectors {
-  RecordVector debug;
-  RecordVector release;
-  RecordVector host_debug;
-  RecordVector host_release;
-  RecordVector debug64;
-  RecordVector release64;
-  RecordVector xcode_debug;
-  RecordVector xcode_release;
-  RecordVector xcode_host_debug;
-  RecordVector xcode_host_release;
-};
-
-// This function appends a suffix to the given source directory name. We append
-// a suffix to the last directory component rather than adding a new level so
-// that the relative location of the files don't change (i.e. a file
-// relative to the build dir might be "../../foo/bar.cc") and we want these to
-// be the same in all builds, and in particular the GYP build directories.
-SourceDir AppendDirSuffix(const SourceDir& base, const std::string& suffix) {
-  return SourceDir(DirectoryWithNoLastSlash(base) + suffix + "/");
-}
-
-// Returns the empty label if there is no separate host build.
-Label GetHostToolchain(const Setups& setups) {
-  const Loader* loader = setups.debug->loader();
-  const Settings* default_settings =
-      loader->GetToolchainSettings(loader->GetDefaultToolchain());
-
-  // Chrome's master build config file puts the host toolchain label into the
-  // variable "host_toolchain".
-  const Value* host_value =
-      default_settings->base_config()->GetValue("host_toolchain");
-  if (!host_value || host_value->type() != Value::STRING)
-    return Label();
-
-  Err err;
-  Label host_label = Label::Resolve(SourceDir(), Label(), *host_value, &err);
-  if (host_label == loader->GetDefaultToolchain())
-    return Label();  // Host and target matches, there is no host build.
-  return host_label;
-}
-
-std::vector<const BuilderRecord*> GetAllResolvedTargetRecords(
-    const Builder* builder) {
-  std::vector<const BuilderRecord*> all = builder->GetAllRecords();
-  std::vector<const BuilderRecord*> result;
-  result.reserve(all.size());
-  for (size_t i = 0; i < all.size(); i++) {
-    if (all[i]->type() == BuilderRecord::ITEM_TARGET &&
-        all[i]->should_generate() &&
-        all[i]->item())
-      result.push_back(all[i]);
-  }
-  return result;
-}
-
-// Adds all targets to the map that match the given toolchain, writing them to
-// the given destiation vector of the record group. If toolchain is empty, it
-// indicates the default toolchain should be matched.
-void CorrelateRecordVector(const RecordVector& records,
-                           const Label& toolchain,
-                           CorrelatedTargetsMap* correlated,
-                           const BuilderRecord* TargetGroup::* record_ptr) {
-  if (records.empty())
-    return;
-
-  Label search_toolchain = toolchain;
-  if (search_toolchain.is_null()) {
-    // Find the default toolchain.
-    search_toolchain =
-        records[0]->item()->settings()->default_toolchain_label();
-  }
-
-  for (size_t i = 0; i < records.size(); i++) {
-    const BuilderRecord* record = records[i];
-    if (record->label().GetToolchainLabel() == search_toolchain)
-      (*correlated)[record->label().GetWithNoToolchain()].*record_ptr = record;
-  }
-}
-
-// Groups targets sharing the same label between debug and release.
-//
-// If the host toolchain is nonempty, we'll search for targets with this
-// alternate toolchain and assign them to the corresponding "host" groups.
-//
-// TODO(brettw) this doesn't handle any toolchains other than the target or
-// host ones. To support nacl, we'll need to differentiate the 32-vs-64-bit
-// case and the default-toolchain-vs-not case. When we find a target not using
-// hte default toolchain, we should probably just shell out to ninja.
-void CorrelateTargets(const TargetVectors& targets,
-                      const Label& host_toolchain,
-                      CorrelatedTargetsMap* correlated) {
-  // Normal.
-  CorrelateRecordVector(targets.debug, Label(), correlated,
-                        &TargetGroup::debug);
-  CorrelateRecordVector(targets.release, Label(), correlated,
-                        &TargetGroup::release);
-
-  // 64-bit build.
-  CorrelateRecordVector(targets.debug64, Label(), correlated,
-                        &TargetGroup::debug64);
-  CorrelateRecordVector(targets.release64, Label(), correlated,
-                        &TargetGroup::release64);
-
-  // XCode build.
-  CorrelateRecordVector(targets.xcode_debug, Label(), correlated,
-                        &TargetGroup::xcode_debug);
-  CorrelateRecordVector(targets.xcode_release, Label(), correlated,
-                        &TargetGroup::xcode_release);
-
-  if (!host_toolchain.is_null()) {
-    // Normal host build.
-    CorrelateRecordVector(targets.debug, host_toolchain, correlated,
-                          &TargetGroup::host_debug);
-    CorrelateRecordVector(targets.release, host_toolchain, correlated,
-                          &TargetGroup::host_release);
-
-    // XCode build.
-    CorrelateRecordVector(targets.xcode_debug, host_toolchain, correlated,
-                          &TargetGroup::xcode_host_debug);
-    CorrelateRecordVector(targets.xcode_release, host_toolchain, correlated,
-                          &TargetGroup::xcode_host_release);
-  }
-}
-
-// Verifies that both debug and release variants match. They can differ only
-// by flags.
-bool EnsureTargetsMatch(const TargetGroup& group, Err* err) {
-  if (!group.debug && !group.release)
-    return true;
-
-  // Check that both debug and release made this target.
-  if (!group.debug || !group.release) {
-    const BuilderRecord* non_null_one =
-        group.debug ? group.debug : group.release;
-    *err = Err(Location(), "The debug and release builds did not both generate "
-        "a target with the name\n" +
-        non_null_one->label().GetUserVisibleName(true));
-    return false;
-  }
-
-  const Target* debug_target = group.debug->item()->AsTarget();
-  const Target* release_target = group.release->item()->AsTarget();
-
-  // Check the flags that determine if and where we write the GYP file.
-  if (group.debug->should_generate() != group.release->should_generate() ||
-      debug_target->external() != release_target->external() ||
-      debug_target->gyp_file() != release_target->gyp_file()) {
-    *err = Err(Location(), "The metadata for the target\n" +
-        group.debug->label().GetUserVisibleName(true) +
-        "\ndoesn't match between the debug and release builds.");
-    return false;
-  }
-
-  // Check that the sources match.
-  if (debug_target->sources().size() != release_target->sources().size()) {
-    *err = Err(Location(), "The source file count for the target\n" +
-        group.debug->label().GetUserVisibleName(true) +
-        "\ndoesn't have the same number of files between the debug and "
-        "release builds.");
-    return false;
-  }
-  for (size_t i = 0; i < debug_target->sources().size(); i++) {
-    if (debug_target->sources()[i] != release_target->sources()[i]) {
-      *err = Err(Location(), "The debug and release version of the target \n" +
-          group.debug->label().GetUserVisibleName(true) +
-          "\ndon't agree on the file\n" +
-          debug_target->sources()[i].value());
-      return false;
-    }
-  }
-
-  // Check that the deps match.
-  if (debug_target->deps().size() != release_target->deps().size()) {
-    *err = Err(Location(), "The source file count for the target\n" +
-        group.debug->label().GetUserVisibleName(true) +
-        "\ndoesn't have the same number of deps between the debug and "
-        "release builds.");
-    return false;
-  }
-  for (size_t i = 0; i < debug_target->deps().size(); i++) {
-    if (debug_target->deps()[i].label != release_target->deps()[i].label) {
-      *err = Err(Location(), "The debug and release version of the target \n" +
-          group.debug->label().GetUserVisibleName(true) +
-          "\ndon't agree on the dep\n" +
-          debug_target->deps()[i].label.GetUserVisibleName(true));
-      return false;
-    }
-  }
-  return true;
-}
-
-// Returns the (number of targets, number of GYP files).
-std::pair<int, int> WriteGypFiles(Setups& setups, Err* err) {
-  TargetVectors targets;
-
-  targets.debug = GetAllResolvedTargetRecords(setups.debug->builder());
-  targets.release = GetAllResolvedTargetRecords(setups.release->builder());
-
-  // 64-bit build is optional.
-  if (setups.debug64 && setups.release64) {
-    targets.debug64 =
-        GetAllResolvedTargetRecords(setups.debug64->builder());
-    targets.release64 =
-        GetAllResolvedTargetRecords(setups.release64->builder());
-  }
-
-  // Xcode build is optional.
-  if (setups.xcode_debug && setups.xcode_release) {
-    targets.xcode_debug =
-        GetAllResolvedTargetRecords(setups.xcode_debug->builder());
-    targets.xcode_release =
-        GetAllResolvedTargetRecords(setups.xcode_release->builder());
-  }
-
-  // Match up the debug and release version of each target by label.
-  CorrelatedTargetsMap correlated;
-  CorrelateTargets(targets, GetHostToolchain(setups), &correlated);
-
-  GypHelper helper;
-  GroupedTargetsMap grouped_targets;
-  int target_count = 0;
-  for (CorrelatedTargetsMap::iterator i = correlated.begin();
-       i != correlated.end(); ++i) {
-    const TargetGroup& group = i->second;
-    if (!group.get()->should_generate())
-      continue;  // Skip non-generated ones.
-    if (group.get()->item()->AsTarget()->external())
-      continue;  // Skip external ones.
-    if (group.get()->item()->AsTarget()->gyp_file().is_null())
-      continue;  // Skip ones without GYP files.
-
-    if (!EnsureTargetsMatch(group, err))
-      return std::make_pair(0, 0);
-
-    target_count++;
-    grouped_targets[
-            helper.GetGypFileForTarget(group.debug->item()->AsTarget(), err)]
-        .push_back(group);
-    if (err->has_error())
-      return std::make_pair(0, 0);
-  }
-
-  // Extract the toolchain for the debug targets.
-  const Toolchain* debug_toolchain = NULL;
-  if (!grouped_targets.empty()) {
-    debug_toolchain = setups.debug->builder()->GetToolchain(
-        grouped_targets.begin()->second[0].debug->item()->settings()->
-        default_toolchain_label());
-  }
-
-  // Write each GYP file.
-  for (GroupedTargetsMap::iterator i = grouped_targets.begin();
-       i != grouped_targets.end(); ++i) {
-    GypTargetWriter::WriteFile(i->first, i->second, debug_toolchain, err);
-    if (err->has_error())
-      return std::make_pair(0, 0);
-  }
-
-  return std::make_pair(target_count,
-                        static_cast<int>(grouped_targets.size()));
-}
-
-// Verifies that all build argument overrides are used by at least one of the
-// build types.
-void VerifyAllOverridesUsed(const Setups& setups) {
-  // Collect all declared args from all builds.
-  Scope::KeyValueMap declared;
-  setups.debug->build_settings().build_args().MergeDeclaredArguments(
-      &declared);
-  setups.release->build_settings().build_args().MergeDeclaredArguments(
-      &declared);
-  if (setups.debug64 && setups.release64) {
-    setups.debug64->build_settings().build_args().MergeDeclaredArguments(
-        &declared);
-    setups.release64->build_settings().build_args().MergeDeclaredArguments(
-        &declared);
-  }
-  if (setups.xcode_debug && setups.xcode_release) {
-    setups.xcode_debug->build_settings().build_args().MergeDeclaredArguments(
-        &declared);
-    setups.xcode_release->build_settings().build_args().MergeDeclaredArguments(
-        &declared);
-  }
-
-  Scope::KeyValueMap used =
-      setups.debug->build_settings().build_args().GetAllOverrides();
-
-  Err err;
-  if (!Args::VerifyAllOverridesUsed(used, declared, &err)) {
-    // TODO(brettw) implement a system of warnings. Until we have a better
-    // system, print the error but don't cause a failure.
-    err.PrintToStdout();
-  }
-}
-
-}  // namespace
-
-// Suppress output on success.
-const char kSwitchQuiet[] = "q";
-
-const char kGyp[] = "gyp";
-const char kGyp_HelpShort[] =
-    "gyp: Make GYP files from GN.";
-const char kGyp_Help[] =
-    "gyp: Make GYP files from GN.\n"
-    "\n"
-    "  This command will generate GYP files from GN sources. You can then run\n"
-    "  GYP over the result to produce a build. Native GYP targets can depend\n"
-    "  on any GN target except source sets. GN targets can depend on native\n"
-    "  GYP targets, but all/direct dependent settings will NOT be pushed\n"
-    "  across the boundary.\n"
-    "\n"
-    "  To make this work you first need to manually run GN, then GYP, then\n"
-    "  do the build. Because GN doesn't generate the final .ninja files,\n"
-    "  there will be no rules to regenerate the .ninja files if the inputs\n"
-    "  change, so you will have to manually repeat these steps each time\n"
-    "  something changes:\n"
-    "\n"
-    "    out/Debug/gn gyp\n"
-    "    python build/gyp_chromiunm\n"
-    "    ninja -C out/Debug foo_target\n"
-    "\n"
-    "  Two variables are used to control how a target relates to GYP:\n"
-    "\n"
-    "  - \"external != true\" and \"gyp_file\" is set: This target will be\n"
-    "    written to the named GYP file in the source tree (not restricted to\n"
-    "    an output or generated files directory).\n"
-    "\n"
-    "  - \"external == true\" and \"gyp_file\" is set: The target will not\n"
-    "    be written to a GYP file. But other targets being written to GYP\n"
-    "    files can depend on it, and they will reference the given GYP file\n"
-    "    name for GYP to use. This allows you to specify how GN->GYP\n"
-    "    dependencies and named, and provides a place to manually set the\n"
-    "    dependent configs from GYP to GN.\n"
-    "\n"
-    "  - \"gyp_file\" is unset: Like the previous case, but if a GN target is\n"
-    "    being written to a GYP file that depends on this one, the default\n"
-    "    GYP file name will be assumed. The default name will match the name\n"
-    "    of the current directory, so \"//foo/bar:baz\" would be\n"
-    "    \"<(DEPTH)/foo/bar/bar.gyp:baz\".\n"
-    "\n"
-    "Switches\n"
-    "  --gyp_vars\n"
-    "      The GYP variables converted to a GN-style string lookup.\n"
-    "      For example:\n"
-    "      --gyp_vars=\"component=\\\"shared_library\\\" use_aura=\\\"1\\\"\"\n"
-    "\n"
-    "Example:\n"
-    "  # This target is assumed to be in the GYP build in the file\n"
-    "  # \"foo/foo.gyp\". This declaration tells GN where to find the GYP\n"
-    "  # equivalent, and gives it some direct dependent settings that targets\n"
-    "  # depending on it should receive (since these don't flow from GYP to\n"
-    "  # GN-generated targets).\n"
-    "  shared_library(\"gyp_target\") {\n"
-    "    gyp_file = \"//foo/foo.gyp\"\n"
-    "    external = true\n"
-    "    direct_dependen_configs = [ \":gyp_target_config\" ]\n"
-    "  }\n"
-    "\n"
-    "  executable(\"my_app\") {\n"
-    "    deps = [ \":gyp_target\" ]\n"
-    "    gyp_file = \"//foo/myapp.gyp\"\n"
-    "    sources = ...\n"
-    "  }\n";
-
-int RunGyp(const std::vector<std::string>& args) {
-  base::ElapsedTimer timer;
-  Setups setups;
-
-  const CommandLine* cmdline = CommandLine::ForCurrentProcess();
-
-  // Compute output directory.
-  std::string build_dir;
-  if (args.size() == 1) {
-    build_dir = args[0];
-  } else {
-    // Backwards-compat code for the old invocation that uses
-    // "gn gyp --output=foo"
-    // TODO(brettw) This should be removed when gyp_chromium has been updated.
-
-    // Switch to set the build output directory.
-    const char kSwitchBuildOutput[] = "output";
-    build_dir = cmdline->GetSwitchValueASCII(kSwitchBuildOutput);
-    if (build_dir.empty())
-      build_dir = "//out/Default/";
-  }
-
-  // Deliberately leaked to avoid expensive process teardown. We also turn off
-  // unused override checking since we want to merge all declared arguments and
-  // check those, rather than check each build individually. Otherwise, you
-  // couldn't have an arg that was used in only one build type. This comes up
-  // because some args are build-type specific.
-  setups.debug = new Setup;
-  setups.debug->set_check_for_unused_overrides(false);
-  if (!setups.debug->DoSetup(build_dir))
-    return 1;
-  const char kIsDebug[] = "is_debug";
-
-  SourceDir base_build_dir = setups.debug->build_settings().build_dir();
-  setups.debug->build_settings().SetBuildDir(
-      AppendDirSuffix(base_build_dir, ".Debug"));
-
-  // Make a release build based on the debug one. We use a new directory for
-  // the build output so that they don't stomp on each other.
-  setups.release = new DependentSetup(setups.debug);
-  setups.release->build_settings().build_args().AddArgOverride(
-      kIsDebug, Value(NULL, false));
-  setups.release->build_settings().SetBuildDir(
-      AppendDirSuffix(base_build_dir, ".Release"));
-
-  // 64-bit build (Windows only).
-#if defined(OS_WIN)
-  static const char kForceWin64[] = "force_win64";
-  setups.debug64 = new DependentSetup(setups.debug);
-  setups.debug64->build_settings().build_args().AddArgOverride(
-      kForceWin64, Value(NULL, true));
-  setups.debug64->build_settings().SetBuildDir(
-      AppendDirSuffix(base_build_dir, ".Debug64"));
-
-  setups.release64 = new DependentSetup(setups.release);
-  setups.release64->build_settings().build_args().AddArgOverride(
-      kForceWin64, Value(NULL, true));
-  setups.release64->build_settings().SetBuildDir(
-      AppendDirSuffix(base_build_dir, ".Release64"));
-#endif
-
-  // XCode build (Mac only).
-#if defined(OS_MACOSX)
-  static const char kGypXCode[] = "is_gyp_xcode_generator";
-  setups.xcode_debug = new DependentSetup(setups.debug);
-  setups.xcode_debug->build_settings().build_args().AddArgOverride(
-      kGypXCode, Value(NULL, true));
-  setups.xcode_debug->build_settings().SetBuildDir(
-      AppendDirSuffix(base_build_dir, ".XCodeDebug"));
-
-  setups.xcode_release = new DependentSetup(setups.release);
-  setups.xcode_release->build_settings().build_args().AddArgOverride(
-      kGypXCode, Value(NULL, true));
-  setups.xcode_release->build_settings().SetBuildDir(
-      AppendDirSuffix(base_build_dir, ".XCodeRelease"));
-#endif
-
-  // Run all the builds in parellel.
-  setups.release->RunPreMessageLoop();
-  if (setups.debug64 && setups.release64) {
-    setups.debug64->RunPreMessageLoop();
-    setups.release64->RunPreMessageLoop();
-  }
-  if (setups.xcode_debug && setups.xcode_release) {
-    setups.xcode_debug->RunPreMessageLoop();
-    setups.xcode_release->RunPreMessageLoop();
-  }
-
-  if (!setups.debug->Run())
-    return 1;
-
-  if (!setups.release->RunPostMessageLoop())
-    return 1;
-  if (setups.debug64 && !setups.debug64->RunPostMessageLoop())
-    return 1;
-  if (setups.release64 && !setups.release64->RunPostMessageLoop())
-    return 1;
-  if (setups.xcode_debug && !setups.xcode_debug->RunPostMessageLoop())
-    return 1;
-  if (setups.xcode_release && !setups.xcode_release->RunPostMessageLoop())
-    return 1;
-
-  VerifyAllOverridesUsed(setups);
-
-  Err err;
-  std::pair<int, int> counts = WriteGypFiles(setups, &err);
-  if (err.has_error()) {
-    err.PrintToStdout();
-    return 1;
-  }
-
-  base::TimeDelta elapsed_time = timer.Elapsed();
-
-  if (!cmdline->HasSwitch(kSwitchQuiet)) {
-    OutputString("Done. ", DECORATION_GREEN);
-
-    std::string stats = "Wrote " +
-        base::IntToString(counts.first) + " targets to " +
-        base::IntToString(counts.second) + " GYP files read from " +
-        base::IntToString(
-            setups.debug->scheduler().input_file_manager()->GetInputFileCount())
-        + " GN files in " +
-        base::IntToString(elapsed_time.InMilliseconds()) + "ms\n";
-
-    OutputString(stats);
-  }
-
-  return 0;
-}
-
-}  // namespace commands
diff --git a/tools/gn/commands.cc b/tools/gn/commands.cc
index 66bd70d..963b4e8 100644
--- a/tools/gn/commands.cc
+++ b/tools/gn/commands.cc
@@ -37,7 +37,6 @@
     INSERT_COMMAND(Args)
     INSERT_COMMAND(Desc)
     INSERT_COMMAND(Gen)
-    INSERT_COMMAND(Gyp)
     INSERT_COMMAND(Help)
     INSERT_COMMAND(Refs)
 
diff --git a/tools/gn/commands.h b/tools/gn/commands.h
index bcd0c2e..1900820 100644
--- a/tools/gn/commands.h
+++ b/tools/gn/commands.h
@@ -34,11 +34,6 @@
 extern const char kGen_Help[];
 int RunGen(const std::vector<std::string>& args);
 
-extern const char kGyp[];
-extern const char kGyp_HelpShort[];
-extern const char kGyp_Help[];
-int RunGyp(const std::vector<std::string>& args);
-
 extern const char kHelp[];
 extern const char kHelp_HelpShort[];
 extern const char kHelp_Help[];
diff --git a/tools/gn/copy_target_generator.cc b/tools/gn/copy_target_generator.cc
index c88b0c4..edd6f14 100644
--- a/tools/gn/copy_target_generator.cc
+++ b/tools/gn/copy_target_generator.cc
@@ -23,9 +23,6 @@
 void CopyTargetGenerator::DoRun() {
   target_->set_output_type(Target::COPY_FILES);
 
-  FillExternal();
-  if (err_->has_error())
-    return;
   FillSources();
   if (err_->has_error())
     return;
diff --git a/tools/gn/function_set_defaults.cc b/tools/gn/function_set_defaults.cc
index 94e9ff3..17d1103 100644
--- a/tools/gn/function_set_defaults.cc
+++ b/tools/gn/function_set_defaults.cc
@@ -82,7 +82,8 @@
   // Now copy the values set on the scope we made into the free-floating one
   // (with no containing scope) used to hold the target defaults.
   Scope* dest = scope->MakeTargetDefaults(target_type);
-  block_scope.NonRecursiveMergeTo(dest, function, "<SHOULD NOT FAIL>", err);
+  block_scope.NonRecursiveMergeTo(dest, false, function,
+                                  "<SHOULD NOT FAIL>", err);
   return Value();
 }
 
diff --git a/tools/gn/function_template.cc b/tools/gn/function_template.cc
index f726529..46a2fec 100644
--- a/tools/gn/function_template.cc
+++ b/tools/gn/function_template.cc
@@ -6,6 +6,7 @@
 
 #include "tools/gn/parse_tree.h"
 #include "tools/gn/scope.h"
+#include "tools/gn/template.h"
 #include "tools/gn/value.h"
 
 namespace functions {
@@ -14,71 +15,129 @@
 const char kTemplate_Help[] =
     "template: Define a template rule.\n"
     "\n"
-    "  A template defines a custom rule name that can expand to one or more\n"
-    "  other rules (typically built-in rules like \"static_library\"). It\n"
+    "  A template defines a custom name that acts like a function. It\n"
     "  provides a way to add to the built-in target types.\n"
     "\n"
     "  The template() function is used to declare a template. To invoke the\n"
     "  template, just use the name of the template like any other target\n"
     "  type.\n"
     "\n"
-    "More details:\n"
-    "\n"
-    "  Semantically, the code in the template is stored. When a function\n"
-    "  with the name is called, the block following the invocation is\n"
-    "  executed, *then* your template code is executed. So if the invocation\n"
-    "  sets the |source| variable, for example, that variable will be\n"
-    "  accessible to you when the template code runs.\n"
-    "\n"
-    "  The template() function does not generate a closure, so the\n"
-    "  environment, current directory, etc. will all be the same as from\n"
-    "  the template is invoked.\n"
-    "\n"
-    "Hints:\n"
-    "\n"
-    "  If your template expands to more than one target, be sure to name\n"
-    "  the intermediate targets based on the name of the template\n"
-    "  instantiation so that the names are globally unique. The variable\n"
-    "  |target_name| will be this name.\n"
-    "\n"
-    "  Likewise, you will always want to generate a target in your template\n"
-    "  with the original |target_name|. Otherwise, invoking your template\n"
-    "  will not actually generate a node in the dependency graph that other\n"
-    "  targets can reference.\n"
-    "\n"
     "  Often you will want to declare your template in a special file that\n"
     "  other files will import (see \"gn help import\") so your template\n"
     "  rule can be shared across build files.\n"
     "\n"
+    "More details:\n"
+    "\n"
+    "  When you call template() it creates a closure around all variables\n"
+    "  currently in scope with the code in the template block. When the\n"
+    "  template is invoked, the closure will be executed.\n"
+    "\n"
+    "  When the template is invoked, the code in the caller is executed and\n"
+    "  passed to the template code as an implicit \"invoker\" variable. The\n"
+    "  template uses this to read state out of the invoking code.\n"
+    "\n"
+    "  One thing explicitly excluded from the closure is the \"current\n"
+    "  directory\" against which relative file names are resolved. The\n"
+    "  current directory will be that of the invoking code, since typically\n"
+    "  that code specifies the file names. This means all files internal\n"
+    "  to the template should use absolute names.\n"
+    "\n"
+    "Target naming:\n"
+    "\n"
+    "  Your template should almost always define a built-in target with the\n"
+    "  name the template invoker specified. For example, if you have an IDL\n"
+    "  template and somebody does:\n"
+    "    idl(\"foo\") {...\n"
+    "  you will normally want this to expand to something defining a\n"
+    "  source_set or static_library named \"foo\" (among other things you may\n"
+    "  need). This way, when another target specifies a dependency on\n"
+    "  \"foo\", the static_library or source_set will be linked.\n"
+    "\n"
+    "  It is also important that any other targets your template expands to\n"
+    "  have globally unique names, or you will get collisions.\n"
+    "\n"
+    "  Access the invoking name in your template via the implicit\n"
+    "  \"target_name\" variable. This should also be the basis of how other\n"
+    "  targets that a template expands to to ensure uniquness.\n"
+    "\n"
+    "  A typical example would be a template that defines an action to\n"
+    "  generate some source files, and a source_set to compile that source.\n"
+    "  Your template would name the source_set \"target_name\" because\n"
+    "  that's what you want external targets to depend on to link your code.\n"
+    "  And you would name the action something like \"${target_name}_action\"\n"
+    "  to make it unique. The source set would have a dependency on the\n"
+    "  action to make it run.\n"
+    "\n"
     "Example of defining a template:\n"
     "\n"
     "  template(\"my_idl\") {\n"
-    "    # Maps input files to output files, used in both targets below.\n"
+    "    # Be nice and help callers debug problems by checking that the\n"
+    "    # variables the template requires are defined. This gives a nice\n"
+    "    # message rather than giving the user an error about an\n"
+    "    # undefined variable in the file defining the template\n"
+    "    #\n"
+    "    # You can also use defined() to give default values to variables\n"
+    "    # unspecified by the invoker.\n"
+    "    assert(defined(invoker.sources),\n"
+    "           \"Need sources in $target_name listing the idl files.\")\n"
+    "\n"
+    "    # Define a variable containing a source expansion\n"
+    "    # (see \"gn help source_expansion\") that maps input files to\n"
+    "    # output files. It is used in both targets below.\n"
     "    filter = [ \"$target_gen_dir/{{source_name_part}}.cc\",\n"
     "               \"$target_gen_dir/{{source_name_part}}.h\" ]\n"
     "\n"
-    "    # Intermediate target to compile IDL to C source.\n"
+    "    # Intermediate target to convert IDL to C source. Note that the name\n"
+    "    # is based on the name the invoker of the template specified. This\n"
+    "    # way, each time the template is invoked we get a unique\n"
+    "    # intermediate action name (since all target names are in the global\n"
+    "    # scope).\n"
     "    action_foreach(\"${target_name}_code_gen\") {\n"
-    "      # The |sources| will be inherited from the surrounding scope so\n"
-    "      # we don't need to redefine it.\n"
-    "      script = \"foo.py\"\n"
+    "      # Access the scope defined by the invoker via the implicit\n"
+    "      # \"invoker\" variable.\n"
+    "      sources = invoker.sources\n"
+    "\n"
+    "      # Note that we need an absolute path for our script file name.\n"
+    "      # The current directory when executing this code will be that of\n"
+    "      # the invoker (this is why we can use the \"sources\" directly\n"
+    "      # above without having to rebase all of the paths). But if we need\n"
+    "      # to reference a script relative to the template file, we'll need\n"
+    "      # to use an absolute path instead.\n"
+    "      script = \"//tools/idl/idl_code_generator.py\"\n"
     "      outputs = filter  # Variable from above.\n"
     "    }\n"
     "\n"
-    "    # Name the static library the same as the template invocation so\n"
+    "    # Name the source set the same as the template invocation so\n"
     "    # instancing this template produces something that other targets\n"
     "    # can link to in their deps.\n"
-    "    static_library(target_name) {\n"
+    "    source_set(target_name) {\n"
     "      # Generates the list of sources.\n"
     "      # See \"gn help process_file_template\"\n"
-    "      sources = process_file_template(sources, filter)\n"
+    "      sources = process_file_template(invoker.sources, filter)\n"
+    "\n"
+    "      # This target depends on the files produced by the above code gen\n"
+    "      # target.\n"
+    "      deps = [ \":${target_name}_code_gen\" ]\n"
     "    }\n"
     "  }\n"
     "\n"
     "Example of invoking the resulting template:\n"
     "\n"
+    "  # This calls the template code above, defining target_name to be\n"
+    "  # \"foo_idl_files\" and \"invoker\" to be the set of stuff defined in\n"
+    "  # the curly brackets.\n"
     "  my_idl(\"foo_idl_files\") {\n"
+    "    # Goes into the template as \"invoker.sources\".\n"
     "    sources = [ \"foo.idl\", \"bar.idl\" ]\n"
+    "  }\n"
+    "\n"
+    "  # Here is a target that depends on our template.\n"
+    "  executable(\"my_exe\") {\n"
+    "    # Depend on the name we gave the template call above. Internally,\n"
+    "    # this will produce a dependency from executable to the source_set\n"
+    "    # inside the template (since it has this name), which will in turn\n"
+    "    # depend on the code gen action.\n"
+    "    deps = [ \":foo_idl_files\" ]\n"
     "  }\n";
 
 Value RunTemplate(Scope* scope,
@@ -97,16 +156,17 @@
     return Value();
   std::string template_name = args[0].string_value();
 
-  const FunctionCallNode* existing_template = scope->GetTemplate(template_name);
+  const Template* existing_template = scope->GetTemplate(template_name);
   if (existing_template) {
     *err = Err(function, "Duplicate template definition.",
                "A template with this name was already defined.");
-    err->AppendSubErr(Err(existing_template->function(),
+    err->AppendSubErr(Err(existing_template->GetDefinitionRange(),
                           "Previous definition."));
     return Value();
   }
 
-  scope->AddTemplate(template_name, function);
+  scope->AddTemplate(template_name,
+                     scoped_ptr<Template>(new Template(scope, function)));
   return Value();
 }
 
diff --git a/tools/gn/function_toolchain.cc b/tools/gn/function_toolchain.cc
index c05f3b2..3d1a655 100644
--- a/tools/gn/function_toolchain.cc
+++ b/tools/gn/function_toolchain.cc
@@ -113,15 +113,6 @@
   if (err->has_error())
     return Value();
 
-  // Extract the gyp_header contents, if any.
-  const Value* gyp_header_value =
-      block_scope.GetValue(variables::kGypHeader, true);
-  if (gyp_header_value) {
-    if (!gyp_header_value->VerifyTypeIs(Value::STRING, err))
-      return Value();
-    toolchain->set_gyp_header(gyp_header_value->string_value());
-  }
-
   if (!block_scope.CheckForUnusedVars(err))
     return Value();
 
diff --git a/tools/gn/functions.cc b/tools/gn/functions.cc
index 8d146b2..43cdcd3 100644
--- a/tools/gn/functions.cc
+++ b/tools/gn/functions.cc
@@ -16,46 +16,10 @@
 #include "tools/gn/scheduler.h"
 #include "tools/gn/scope.h"
 #include "tools/gn/settings.h"
+#include "tools/gn/template.h"
 #include "tools/gn/token.h"
 #include "tools/gn/value.h"
 
-namespace {
-
-// This is called when a template is invoked. When we see a template
-// declaration, that funciton is RunTemplate.
-Value RunTemplateInvocation(Scope* scope,
-                            const FunctionCallNode* invocation,
-                            const std::vector<Value>& args,
-                            BlockNode* block,
-                            const FunctionCallNode* rule,
-                            Err* err) {
-  if (!EnsureNotProcessingImport(invocation, scope, err))
-    return Value();
-
-  Scope block_scope(scope);
-  if (!FillTargetBlockScope(scope, invocation,
-                            invocation->function().value().as_string(),
-                            block, args, &block_scope, err))
-    return Value();
-
-  // Run the block for the rule invocation.
-  block->ExecuteBlockInScope(&block_scope, err);
-  if (err->has_error())
-    return Value();
-
-  // Now run the rule itself with that block as the current scope.
-  rule->block()->ExecuteBlockInScope(&block_scope, err);
-  if (err->has_error())
-    return Value();
-
-  block_scope.CheckForUnusedVars(err);
-  return Value();
-}
-
-}  // namespace
-
-// ----------------------------------------------------------------------------
-
 bool EnsureNotProcessingImport(const ParseNode* node,
                                const Scope* scope,
                                Err* err) {
@@ -97,7 +61,7 @@
   // the block in.
   const Scope* default_scope = scope->GetTargetDefaults(target_type);
   if (default_scope) {
-    if (!default_scope->NonRecursiveMergeTo(block_scope, function,
+    if (!default_scope->NonRecursiveMergeTo(block_scope, false, function,
                                             "target defaults", err))
       return false;
   }
@@ -331,16 +295,29 @@
     "  Returns true if the given argument is defined. This is most useful in\n"
     "  templates to assert that the caller set things up properly.\n"
     "\n"
+    "  You can pass an identifier:\n"
+    "    defined(foo)\n"
+    "  which will return true or false depending on whether foo is defined in\n"
+    "  the current scope.\n"
+    "\n"
+    "  You can also check a named scope:\n"
+    "    defined(foo.bar)\n"
+    "  which returns true if both foo is defined and bar is defined on the\n"
+    "  named scope foo. It will throw an error if foo is defined but is not\n"
+    "  a scope.\n"
+    "\n"
     "Example:\n"
     "\n"
     "  template(\"mytemplate\") {\n"
     "    # To help users call this template properly...\n"
-    "    assert(defined(sources), \"Sources must be defined\")\n"
+    "    assert(defined(invoker.sources), \"Sources must be defined\")\n"
     "\n"
     "    # If we want to accept an optional \"values\" argument, we don't\n"
     "    # want to dereference something that may not be defined.\n"
-    "    if (!defined(outputs)) {\n"
-    "      outputs = []\n"
+    "    if (defined(invoker.values)) {\n"
+    "      values = invoker.values\n"
+    "    } else {\n"
+    "      values = \"some default value\"\n"
     "    }\n"
     "  }\n";
 
@@ -349,17 +326,42 @@
                  const ListNode* args_list,
                  Err* err) {
   const std::vector<const ParseNode*>& args_vector = args_list->contents();
-  const IdentifierNode* identifier = NULL;
-  if (args_vector.size() != 1 ||
-      !(identifier = args_vector[0]->AsIdentifier())) {
-    *err = Err(function, "Bad argument to defined().",
-        "defined() takes one argument which should be an identifier.");
+  if (args_vector.size() != 1) {
+    *err = Err(function, "Wrong number of arguments to defined().",
+               "Expecting exactly one.");
     return Value();
   }
 
-  if (scope->GetValue(identifier->value().value()))
-    return Value(function, true);
-  return Value(function, false);
+  const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
+  if (identifier) {
+    // Passed an identifier "defined(foo)".
+    if (scope->GetValue(identifier->value().value()))
+      return Value(function, true);
+    return Value(function, false);
+  }
+
+  const AccessorNode* accessor = args_vector[0]->AsAccessor();
+  if (accessor) {
+    // Passed an accessor "defined(foo.bar)".
+    if (accessor->member()) {
+      // The base of the accessor must be a scope if it's defined.
+      const Value* base = scope->GetValue(accessor->base().value());
+      if (!base)
+        return Value(function, false);
+      if (!base->VerifyTypeIs(Value::SCOPE, err))
+        return Value();
+
+      // Check the member inside the scope to see if its defined.
+      if (base->scope_value()->GetValue(accessor->member()->value().value()))
+        return Value(function, true);
+      return Value(function, false);
+    }
+  }
+
+  // Argument is invalid.
+  *err = Err(function, "Bad thing passed to defined().",
+      "It should be of the form defined(foo) or defined(foo.bar).");
+  return Value();
 }
 
 // getenv ----------------------------------------------------------------------
@@ -625,14 +627,13 @@
       function_map.find(name.value());
   if (found_function == function_map.end()) {
     // No built-in function matching this, check for a template.
-    const FunctionCallNode* rule =
+    const Template* templ =
         scope->GetTemplate(function->function().value().as_string());
-    if (rule) {
+    if (templ) {
       Value args = args_list->Execute(scope, err);
       if (err->has_error())
         return Value();
-      return RunTemplateInvocation(scope, function, args.list_value(), block,
-                                   rule, err);
+      return templ->Invoke(scope, function, args.list_value(), block, err);
     }
 
     *err = Err(name, "Unknown function.");
diff --git a/tools/gn/functions_target.cc b/tools/gn/functions_target.cc
index 9b47cf7..50f940b 100644
--- a/tools/gn/functions_target.cc
+++ b/tools/gn/functions_target.cc
@@ -17,7 +17,7 @@
 #define DEPS_VARS \
     "  Deps: data, datadeps, deps, forward_dependent_configs_from, hard_dep\n"
 #define GENERAL_TARGET_VARS \
-    "  General: configs, external, source_prereqs, sources\n"
+    "  General: configs, source_prereqs, sources\n"
 
 namespace functions {
 
@@ -350,7 +350,6 @@
     "\n"
     DEPS_VARS
     DEPENDENT_CONFIG_VARS
-    "  Other variables: external\n"
     "\n"
     "Example\n"
     "\n"
diff --git a/tools/gn/functions_unittest.cc b/tools/gn/functions_unittest.cc
new file mode 100644
index 0000000..74ca605
--- /dev/null
+++ b/tools/gn/functions_unittest.cc
@@ -0,0 +1,55 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/test_with_scope.h"
+#include "tools/gn/value.h"
+
+TEST(Functions, Defined) {
+  TestWithScope setup;
+
+  //InputFile input_file(SourceFile("//foo"));
+  FunctionCallNode function_call;
+  Err err;
+
+  // Test an undefined identifier.
+  Token undefined_token(Location(), Token::IDENTIFIER, "undef");
+  ListNode args_list_identifier_undefined;
+  args_list_identifier_undefined.append_item(
+      scoped_ptr<ParseNode>(new IdentifierNode(undefined_token)));
+  Value result = functions::RunDefined(setup.scope(), &function_call,
+                                       &args_list_identifier_undefined, &err);
+  ASSERT_EQ(Value::BOOLEAN, result.type());
+  EXPECT_FALSE(result.boolean_value());
+
+  // Define a value that's itself a scope value.
+  const char kDef[] = "def";  // Defined variable name.
+  Scope nested(setup.scope());
+  setup.scope()->SetValue(kDef, Value(NULL, &nested), NULL);
+
+  // Test the defined identifier.
+  Token defined_token(Location(), Token::IDENTIFIER, kDef);
+  ListNode args_list_identifier_defined;
+  args_list_identifier_defined.append_item(
+      scoped_ptr<ParseNode>(new IdentifierNode(defined_token)));
+  result = functions::RunDefined(setup.scope(), &function_call,
+                                 &args_list_identifier_defined, &err);
+  ASSERT_EQ(Value::BOOLEAN, result.type());
+  EXPECT_TRUE(result.boolean_value());
+
+  // Should also work by passing an accessor node so you can do
+  // "defined(def.foo)" to see if foo is defined on the def scope.
+  scoped_ptr<AccessorNode> undef_accessor(new AccessorNode);
+  undef_accessor->set_base(defined_token);
+  undef_accessor->set_member(scoped_ptr<IdentifierNode>(
+      new IdentifierNode(undefined_token)));
+  ListNode args_list_accessor_defined;
+  args_list_accessor_defined.append_item(undef_accessor.PassAs<ParseNode>());
+  result = functions::RunDefined(setup.scope(), &function_call,
+                                 &args_list_accessor_defined, &err);
+  ASSERT_EQ(Value::BOOLEAN, result.type());
+  EXPECT_FALSE(result.boolean_value());
+}
diff --git a/tools/gn/gn.gyp b/tools/gn/gn.gyp
index fe305c1..1c9c1c6 100644
--- a/tools/gn/gn.gyp
+++ b/tools/gn/gn.gyp
@@ -27,7 +27,6 @@
         'command_args.cc',
         'command_desc.cc',
         'command_gen.cc',
-        'command_gyp.cc',
         'command_help.cc',
         'command_refs.cc',
         'commands.cc',
@@ -64,14 +63,6 @@
         'function_write_file.cc',
         'group_target_generator.cc',
         'group_target_generator.h',
-        'gyp_action_target_writer.cc',
-        'gyp_action_target_writer.h',
-        'gyp_binary_target_writer.cc',
-        'gyp_binary_target_writer.h',
-        'gyp_helper.cc',
-        'gyp_helper.h',
-        'gyp_target_writer.cc',
-        'gyp_target_writer.h',
         'import_manager.cc',
         'import_manager.h',
         'input_conversion.cc',
@@ -140,6 +131,8 @@
         'target.h',
         'target_generator.cc',
         'target_generator.h',
+        'template.cc',
+        'template.h',
         'token.cc',
         'token.h',
         'tokenizer.cc',
@@ -177,8 +170,7 @@
         'filesystem_utils_unittest.cc',
         'file_template_unittest.cc',
         'function_rebase_path_unittest.cc',
-        'gyp_action_target_writer_unittest.cc',
-        'gyp_binary_target_writer_unittest.cc',
+        'functions_unittest.cc',
         'input_conversion_unittest.cc',
         'label_unittest.cc',
         'loader_unittest.cc',
@@ -187,6 +179,7 @@
         'ninja_copy_target_writer_unittest.cc',
         'ninja_helper_unittest.cc',
         'operators_unittest.cc',
+        'parse_tree_unittest.cc',
         'parser_unittest.cc',
         'path_output_unittest.cc',
         'pattern_unittest.cc',
diff --git a/tools/gn/group_target_generator.cc b/tools/gn/group_target_generator.cc
index d52eb90..b2a73d6 100644
--- a/tools/gn/group_target_generator.cc
+++ b/tools/gn/group_target_generator.cc
@@ -19,5 +19,4 @@
   target_->set_output_type(Target::GROUP);
   // Groups only have the default types filled in by the target generator
   // base class.
-  FillExternal();
 }
diff --git a/tools/gn/gyp_action_target_writer.cc b/tools/gn/gyp_action_target_writer.cc
deleted file mode 100644
index 7df2b9d..0000000
--- a/tools/gn/gyp_action_target_writer.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/gyp_action_target_writer.h"
-
-#include "tools/gn/builder_record.h"
-#include "tools/gn/err.h"
-#include "tools/gn/file_template.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-
-// Write action targets as GYP actions that just invoke Ninja. This allows us
-// to not have to worry about duplicating the precise GN action execution
-// semantices in GYP for each platform (GYP varies a bit).
-
-GypActionTargetWriter::GypActionTargetWriter(const TargetGroup& group,
-                                             const Toolchain* toolchain,
-                                             const SourceDir& gyp_dir,
-                                             std::ostream& out)
-    : GypTargetWriter(group.debug->item()->AsTarget(), toolchain,
-                      gyp_dir, out) {
-}
-
-GypActionTargetWriter::~GypActionTargetWriter() {
-}
-
-void GypActionTargetWriter::Run() {
-  int indent = 4;
-  std::string name = helper_.GetNameForTarget(target_);
-
-  // Put the ninja build for this action target in this directory.
-  SourceDir ninja_dir(GetTargetOutputDir(target_).value() + name + "_ninja/");
-
-  Indent(indent) << "{\n";
-
-  Indent(indent + kExtraIndent) << "'target_name': '" << name << "',\n";
-  Indent(indent + kExtraIndent) << "'type': 'none',\n";
-  Indent(indent + kExtraIndent) << "'actions': [{\n";
-
-  Indent(indent + kExtraIndent * 2) << "'action_name': '" << name
-                                    << " action',\n";
-
-  Indent(indent + kExtraIndent * 2) << "'action': [\n";
-  Indent(indent + kExtraIndent * 3) << "'ninja',\n";
-  Indent(indent + kExtraIndent * 3) << "'-C', '";
-  path_output_.WriteDir(out_, ninja_dir, PathOutput::DIR_NO_LAST_SLASH);
-  out_ << "',\n";
-  Indent(indent + kExtraIndent * 3) << "'" << name << "',\n";
-  Indent(indent + kExtraIndent * 2) << "],\n";
-
-  WriteActionInputs(indent + kExtraIndent * 2);
-  WriteActionOutputs(indent + kExtraIndent * 2);
-
-  Indent(indent + kExtraIndent) << "}],\n";
-  Indent(indent) << "},\n";
-}
-
-void GypActionTargetWriter::WriteActionInputs(int indent) {
-  Indent(indent) << "'inputs': [\n";
-
-  // Write everything that should be considered an input for dependency
-  // purposes, which is all sources as well as the prereqs.
-  const Target::FileList& sources = target_->sources();
-  for (size_t i = 0; i < sources.size(); i++) {
-    Indent(indent + kExtraIndent) << "'";
-    path_output_.WriteFile(out_, sources[i]);
-    out_ << "',\n";
-  }
-
-  const Target::FileList& prereqs = target_->source_prereqs();
-  for (size_t i = 0; i < prereqs.size(); i++) {
-    Indent(indent + kExtraIndent) << "'";
-    path_output_.WriteFile(out_, prereqs[i]);
-    out_ << "',\n";
-  }
-
-  Indent(indent) << "],\n";
-}
-
-void GypActionTargetWriter::WriteActionOutputs(int indent) {
-  Indent(indent) << "'outputs': [\n";
-
-  const Target::FileList& sources = target_->sources();
-  if (sources.empty()) {
-    // Just write outputs directly if there are no sources.
-    const Target::FileList& output = target_->action_values().outputs();
-    for (size_t output_i = 0; output_i < output.size(); output_i++) {
-      Indent(indent + kExtraIndent) << "'";
-      path_output_.WriteFile(out_, output[output_i]);
-      out_ << "',\n";
-    }
-  } else {
-    // There are sources, the outputs should be a template to apply to each.
-    FileTemplate output_template = FileTemplate::GetForTargetOutputs(target_);
-
-    std::vector<std::string> output;
-    for (size_t source_i = 0; source_i < sources.size(); source_i++) {
-      output_template.ApplyString(sources[source_i].value(), &output);
-      for (size_t output_i = 0; output_i < output.size(); output_i++) {
-        Indent(indent + kExtraIndent) << "'";
-        path_output_.WriteFile(out_, SourceFile(output[output_i]));
-        out_ << "',\n";
-      }
-    }
-  }
-
-  Indent(indent) << "],\n";
-}
diff --git a/tools/gn/gyp_action_target_writer.h b/tools/gn/gyp_action_target_writer.h
deleted file mode 100644
index 1ef3a7c..0000000
--- a/tools/gn/gyp_action_target_writer.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_GYP_ACTION_TARGET_WRITER_H_
-#define TOOLS_GN_GYP_ACTION_TARGET_WRITER_H_
-
-#include "base/compiler_specific.h"
-#include "tools/gn/gyp_target_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/toolchain.h"
-
-class GypActionTargetWriter : public GypTargetWriter {
- public:
-  GypActionTargetWriter(const TargetGroup& group,
-                        const Toolchain* toolchain,
-                        const SourceDir& gyp_dir,
-                        std::ostream& out);
-  virtual ~GypActionTargetWriter();
-
-  virtual void Run() OVERRIDE;
-
- private:
-  void WriteActionInputs(int indent);
-  void WriteActionOutputs(int indent);
-
-  DISALLOW_COPY_AND_ASSIGN(GypActionTargetWriter);
-};
-
-#endif  // TOOLS_GN_GYP_ACTION_TARGET_WRITER_H_
diff --git a/tools/gn/gyp_action_target_writer_unittest.cc b/tools/gn/gyp_action_target_writer_unittest.cc
deleted file mode 100644
index 14c2930..0000000
--- a/tools/gn/gyp_action_target_writer_unittest.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/builder_record.h"
-#include "tools/gn/gyp_action_target_writer.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(GypActionTargetWriter, Run) {
-  TestWithScope setup;
-  setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
-  scoped_ptr<Target> target(
-      new Target(setup.settings(), Label(SourceDir("//foo/"), "bar")));
-  target->set_output_type(Target::ACTION);
-
-  target->sources().push_back(SourceFile("//foo/input1.txt"));
-  target->sources().push_back(SourceFile("//foo/input2.txt"));
-
-  target->action_values().outputs().push_back(
-      SourceFile("//out/Debug/{{source_file_part}}.out"));
-
-  BuilderRecord record(BuilderRecord::ITEM_TARGET, target->label());
-  record.set_item(target.PassAs<Item>());
-  GypTargetWriter::TargetGroup group;
-  group.debug = &record;
-
-  setup.settings()->set_target_os(Settings::WIN);
-
-  std::ostringstream out;
-  GypActionTargetWriter writer(group, setup.toolchain(),
-                               SourceDir("//out/gn_gyp/"), out);
-  writer.Run();
-
-  const char expected[] =
-      "    {\n"
-      "      'target_name': 'bar',\n"
-      "      'type': 'none',\n"
-      "      'actions': [{\n"
-      "        'action_name': 'bar action',\n"
-      "        'action': [\n"
-      "          'ninja',\n"
-      "          '-C', '../../out/Debug/obj/foo/bar_ninja',\n"
-      "          'bar',\n"
-      "        ],\n"
-      "        'inputs': [\n"
-      "          '../../foo/input1.txt',\n"
-      "          '../../foo/input2.txt',\n"
-      "        ],\n"
-      "        'outputs': [\n"
-      "          '../../out/Debug/input1.txt.out',\n"
-      "          '../../out/Debug/input2.txt.out',\n"
-      "        ],\n"
-      "      }],\n"
-      "    },\n";
-  std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
-}
diff --git a/tools/gn/gyp_binary_target_writer.cc b/tools/gn/gyp_binary_target_writer.cc
deleted file mode 100644
index ca0f340..0000000
--- a/tools/gn/gyp_binary_target_writer.cc
+++ /dev/null
@@ -1,773 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/gyp_binary_target_writer.h"
-
-#include <set>
-
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "tools/gn/builder_record.h"
-#include "tools/gn/config_values_extractors.h"
-#include "tools/gn/err.h"
-#include "tools/gn/escape.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-
-namespace {
-
-// This functor is used to capture the output of RecursiveTargetConfigToStream
-// in an vector.
-template<typename T>
-struct Accumulator {
-  Accumulator(std::vector<T>* result_in) : result(result_in) {}
-
-  void operator()(const T& s, std::ostream&) const {
-    result->push_back(s);
-  }
-
-  std::vector<T>* result;
-};
-
-// Writes the given array values. The array should already be declared with the
-// opening "[" written to the output. The function will not write the
-// terminating "]" either.
-void WriteArrayValues(std::ostream& out,
-                      const std::vector<std::string>& values) {
-  EscapeOptions options;
-  options.mode = ESCAPE_JSON;
-  for (size_t i = 0; i < values.size(); i++) {
-    out << " '";
-    EscapeStringToStream(out, values[i], options);
-    out << "',";
-  }
-}
-
-// Returns the value from the already-filled in cflags_* for the optimization
-// level to set in the GYP file. Additionally, this removes the flag from the
-// given vector so we don't get duplicates.
-std::string GetVCOptimization(std::vector<std::string>* cflags) {
-  // Searches for the "/O?" option and returns the corresponding GYP value.
-  for (size_t i = 0; i < cflags->size(); i++) {
-    const std::string& cur = (*cflags)[i];
-    if (cur.size() == 3 && cur[0] == '/' && cur[1] == 'O') {
-      char level = cur[2];
-      cflags->erase(cflags->begin() + i);  // Invalidates |cur|!
-      switch (level) {
-        case 'd': return "'0'";
-        case '1': return "'1'";
-        case '2': return "'2'";
-        case 'x': return "'3'";
-        default:  return "'2'";
-      }
-    }
-  }
-  return "'2'";  // Default value.
-}
-
-// Returns the value from the already-filled in cflags for the processor
-// architecture to set in the GYP file. Additionally, this removes the flag
-// from the given vector so we don't get duplicates.
-std::string GetMacArch(std::vector<std::string>* cflags) {
-  // Searches for the "-arch" option and returns the corresponding GYP value.
-  for (size_t i = 0; i < cflags->size(); i++) {
-    const std::string& cur = (*cflags)[i];
-    if (cur == "-arch") {
-      // This is the first part of a list with ["-arch", "i386"], return the
-      // following item, and delete both of them.
-      if (i < cflags->size() - 1) {
-        std::string ret = (*cflags)[i + 1];
-        cflags->erase(cflags->begin() + i, cflags->begin() + i + 2);
-        return ret;
-      }
-    } else if (StartsWithASCII(cur, "-arch ", true)) {
-      // The arch was passed as one GN string value, e.g. "-arch i386". Return
-      // the stuff following the space and delete the item.
-      std::string ret = cur.substr(6);
-      cflags->erase(cflags->begin() + i);
-      return ret;
-    }
-  }
-  return std::string();
-}
-
-// Searches for -miphoneos-version-min, returns the resulting value, and
-// removes it from the list. Returns the empty string if it's not found.
-std::string GetIPhoneVersionMin(std::vector<std::string>* cflags) {
-  // Searches for the "-arch" option and returns the corresponding GYP value.
-  const char prefix[] = "-miphoneos-version-min=";
-  for (size_t i = 0; i < cflags->size(); i++) {
-    const std::string& cur = (*cflags)[i];
-    if (StartsWithASCII(cur, prefix, true)) {
-      std::string result = cur.substr(arraysize(prefix) - 1);
-      cflags->erase(cflags->begin() + i);
-      return result;
-    }
-  }
-  return std::string();
-}
-
-// Finds all values from the given getter from all configs in the given list,
-// and adds them to the given result vector.
-template<typename T>
-void FillConfigListValues(
-    const LabelConfigVector& configs,
-    const std::vector<T>& (ConfigValues::* getter)() const,
-    std::vector<T>* result) {
-  for (size_t config_i = 0; config_i < configs.size(); config_i++) {
-    const std::vector<T>& values =
-        (configs[config_i].ptr->config_values().*getter)();
-    for (size_t val_i = 0; val_i < values.size(); val_i++)
-      result->push_back(values[val_i]);
-  }
-}
-
-bool IsClang(const Target* target) {
-  const Value* is_clang =
-      target->settings()->base_config()->GetValue("is_clang");
-  return is_clang && is_clang->type() == Value::BOOLEAN &&
-      is_clang->boolean_value();
-}
-
-bool IsIOS(const Target* target) {
-  const Value* is_ios = target->settings()->base_config()->GetValue("is_ios");
-  return is_ios && is_ios->type() == Value::BOOLEAN && is_ios->boolean_value();
-}
-
-// Returns true if the current target is an iOS simulator build.
-bool IsIOSSimulator(const std::vector<std::string>& cflags) {
-  // Search for the sysroot flag. We expect one flag to be the
-  // switch, and the following one to be the value.
-  const char sysroot[] = "-isysroot";
-  for (size_t i = 0; i < cflags.size(); i++) {
-    const std::string& cur = cflags[i];
-    if (cur == sysroot) {
-      if (i == cflags.size() - 1)
-        return false;  // No following value.
-
-      // The argument is a file path, we check the prefix of the file name.
-      base::FilePath path(UTF8ToFilePath(cflags[i + 1]));
-      std::string path_file_part = FilePathToUTF8(path.BaseName());
-      return StartsWithASCII(path_file_part, "iphonesimulator", false);
-    }
-  }
-  return false;
-}
-
-}  // namespace
-
-GypBinaryTargetWriter::Flags::Flags() {}
-GypBinaryTargetWriter::Flags::~Flags() {}
-
-GypBinaryTargetWriter::GypBinaryTargetWriter(const TargetGroup& group,
-                                             const Toolchain* debug_toolchain,
-                                             const SourceDir& gyp_dir,
-                                             std::ostream& out)
-    : GypTargetWriter(group.get()->item()->AsTarget(), debug_toolchain,
-                      gyp_dir, out),
-      group_(group) {
-}
-
-GypBinaryTargetWriter::~GypBinaryTargetWriter() {
-}
-
-void GypBinaryTargetWriter::Run() {
-  int indent = 4;
-
-  Indent(indent) << "{\n";
-
-  WriteName(indent + kExtraIndent);
-  WriteType(indent + kExtraIndent);
-
-  if (target_->settings()->IsLinux())
-    WriteLinuxConfiguration(indent + kExtraIndent);
-  else if (target_->settings()->IsWin())
-    WriteVCConfiguration(indent + kExtraIndent);
-  else if (target_->settings()->IsMac())
-    WriteMacConfiguration(indent + kExtraIndent);
-  WriteDirectDependentSettings(indent + kExtraIndent);
-  WriteAllDependentSettings(indent + kExtraIndent);
-
-  Indent(indent) << "},\n";
-}
-
-void GypBinaryTargetWriter::WriteName(int indent) {
-  std::string name = helper_.GetNameForTarget(target_);
-  Indent(indent) << "'target_name': '" << name << "',\n";
-
-  std::string product_name;
-  if (target_->output_name().empty())
-    product_name = target_->label().name();
-  else
-    product_name = name;
-
-  // TODO(brettw) GN knows not to prefix targets starting with "lib" with
-  // another "lib" on Linux, but GYP doesn't. We need to rename applicable
-  // targets here.
-
-  Indent(indent) << "'product_name': '" << product_name << "',\n";
-
-  std::string product_extension = target_->output_extension();
-  if (!product_extension.empty())
-    Indent(indent) << "'product_extension': '" << product_extension << "',\n";
-}
-
-void GypBinaryTargetWriter::WriteType(int indent) {
-  Indent(indent) << "'type': ";
-  switch (target_->output_type()) {
-    case Target::EXECUTABLE:
-      out_ << "'executable',\n";
-      break;
-    case Target::STATIC_LIBRARY:
-      out_ << "'static_library',\n";
-      break;
-    case Target::SHARED_LIBRARY:
-      out_ << "'shared_library',\n";
-      break;
-    case Target::SOURCE_SET:
-      out_ << "'static_library',\n";  // TODO(brettw) fixme.
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  if (target_->hard_dep())
-    Indent(indent) << "'hard_dependency': 1,\n";
-
-  // Write out the toolsets depending on whether there is a host build. If no
-  // toolset is specified, GYP assumes a target build.
-  if (group_.debug && group_.host_debug)
-    Indent(indent) << "'toolsets': ['target', 'host'],\n";
-  else if (group_.host_debug)
-    Indent(indent) << "'toolsets': ['host'],\n";
-}
-
-void GypBinaryTargetWriter::WriteVCConfiguration(int indent) {
-  Indent(indent) << "'configurations': {\n";
-
-  Indent(indent + kExtraIndent) << "'Debug': {\n";
-  Indent(indent + kExtraIndent * 2) <<
-      "'msvs_configuration_platform': 'Win32',\n";
-  Flags debug_flags(FlagsFromTarget(group_.debug->item()->AsTarget()));
-  WriteVCFlags(debug_flags, indent + kExtraIndent * 2);
-  Indent(indent + kExtraIndent) << "},\n";
-
-  Indent(indent + kExtraIndent) << "'Release': {\n";
-  Indent(indent + kExtraIndent * 2) <<
-      "'msvs_configuration_platform': 'Win32',\n";
-  Flags release_flags(FlagsFromTarget(group_.release->item()->AsTarget()));
-  WriteVCFlags(release_flags, indent + kExtraIndent * 2);
-  Indent(indent + kExtraIndent) << "},\n";
-
-  // Note that we always need Debug_x64 and Release_x64 defined or GYP will get
-  // confused, but we ca leave them empty if there's no 64-bit target.
-  Indent(indent + kExtraIndent) << "'Debug_x64': {\n";
-  if (group_.debug64) {
-    Indent(indent + kExtraIndent * 2) <<
-        "'msvs_configuration_platform': 'x64',\n";
-    Flags flags(FlagsFromTarget(group_.debug64->item()->AsTarget()));
-    WriteVCFlags(flags, indent + kExtraIndent * 2);
-  }
-  Indent(indent + kExtraIndent) << "},\n";
-
-  Indent(indent + kExtraIndent) << "'Release_x64': {\n";
-  if (group_.release64) {
-    Indent(indent + kExtraIndent * 2) <<
-        "'msvs_configuration_platform': 'x64',\n";
-    Flags flags(FlagsFromTarget(group_.release64->item()->AsTarget()));
-    WriteVCFlags(flags, indent + kExtraIndent * 2);
-  }
-  Indent(indent + kExtraIndent) << "},\n";
-
-  Indent(indent) << "},\n";
-
-  WriteSources(target_, indent);
-  WriteDeps(target_, indent);
-}
-
-void GypBinaryTargetWriter::WriteLinuxConfiguration(int indent) {
-  // The Linux stuff works differently. On Linux we support cross-compiles and
-  // all ninja generators know to look for target conditions. Other platforms'
-  // generators don't all do this, so we can't have the same GYP structure.
-  Indent(indent) << "'target_conditions': [\n";
-  // The host toolset is configured for the current computer, we will only have
-  // this when doing cross-compiles.
-  if (group_.host_debug && group_.host_release) {
-    Indent(indent + kExtraIndent) << "['_toolset == \"host\"', {\n";
-    Indent(indent + kExtraIndent * 2) << "'configurations': {\n";
-    Indent(indent + kExtraIndent * 3) << "'Debug': {\n";
-    WriteLinuxFlagsForTarget(group_.host_debug->item()->AsTarget(),
-                             indent + kExtraIndent * 4);
-    Indent(indent + kExtraIndent * 3) << "},\n";
-    Indent(indent + kExtraIndent * 3) << "'Release': {\n";
-    WriteLinuxFlagsForTarget(group_.host_release->item()->AsTarget(),
-                             indent + kExtraIndent * 4);
-    Indent(indent + kExtraIndent * 3) << "},\n";
-    Indent(indent + kExtraIndent * 2) << "}\n";
-
-    // The sources are per-toolset but shared between debug & release.
-    WriteSources(group_.host_debug->item()->AsTarget(),
-                 indent + kExtraIndent * 2);
-
-    Indent(indent + kExtraIndent) << "],\n";
-  }
-
-  // The target toolset is the "regular" one.
-  Indent(indent + kExtraIndent) << "['_toolset == \"target\"', {\n";
-  Indent(indent + kExtraIndent * 2) << "'configurations': {\n";
-  Indent(indent + kExtraIndent * 3) << "'Debug': {\n";
-  WriteLinuxFlagsForTarget(group_.debug->item()->AsTarget(),
-                           indent + kExtraIndent * 4);
-  Indent(indent + kExtraIndent * 3) << "},\n";
-  Indent(indent + kExtraIndent * 3) << "'Release': {\n";
-  WriteLinuxFlagsForTarget(group_.release->item()->AsTarget(),
-                           indent + kExtraIndent * 4);
-  Indent(indent + kExtraIndent * 3) << "},\n";
-  Indent(indent + kExtraIndent * 2) << "},\n";
-
-  WriteSources(target_, indent + kExtraIndent * 2);
-
-  Indent(indent + kExtraIndent) << "},],\n";
-  Indent(indent) << "],\n";
-
-  // Deps in GYP can not vary based on the toolset.
-  WriteDeps(target_, indent);
-}
-
-void GypBinaryTargetWriter::WriteMacConfiguration(int indent) {
-  // The Mac flags are parameterized by the GYP generator (Ninja vs. XCode).
-  const char kNinjaGeneratorCondition[] =
-      "'conditions': [['\"<(GENERATOR)\"==\"ninja\"', {\n";
-  const char kNinjaGeneratorElse[] = "}, {\n";
-  const char kNinjaGeneratorEnd[] = "}]],\n";
-
-  Indent(indent) << "'configurations': {\n";
-
-  // Debug.
-  Indent(indent + kExtraIndent) << "'Debug': {\n";
-  Indent(indent + kExtraIndent * 2) << kNinjaGeneratorCondition;
-  {
-    // Ninja generator.
-    WriteMacTargetAndHostFlags(group_.debug, group_.host_debug,
-                               indent + kExtraIndent * 3);
-  }
-  Indent(indent + kExtraIndent * 2) << kNinjaGeneratorElse;
-  if (group_.xcode_debug) {
-    // XCode generator.
-    WriteMacTargetAndHostFlags(group_.xcode_debug, group_.xcode_host_debug,
-                               indent + kExtraIndent * 3);
-  }
-  Indent(indent + kExtraIndent * 2) << kNinjaGeneratorEnd;
-  Indent(indent + kExtraIndent) << "},\n";
-
-  // Release.
-  Indent(indent + kExtraIndent) << "'Release': {\n";
-  Indent(indent + kExtraIndent * 2) << kNinjaGeneratorCondition;
-  {
-    // Ninja generator.
-    WriteMacTargetAndHostFlags(group_.release, group_.host_release,
-                               indent + kExtraIndent * 3);
-  }
-  Indent(indent + kExtraIndent * 2) << kNinjaGeneratorElse;
-  if (group_.xcode_release) {
-    // XCode generator.
-    WriteMacTargetAndHostFlags(group_.xcode_release, group_.xcode_host_release,
-                               indent + kExtraIndent * 3);
-  }
-  Indent(indent + kExtraIndent * 2) << kNinjaGeneratorEnd;
-  Indent(indent + kExtraIndent) << "},\n";
-
-  Indent(indent) << "},\n";
-
-  WriteSources(target_, indent);
-  WriteDeps(target_, indent);
-}
-
-void GypBinaryTargetWriter::WriteVCFlags(Flags& flags, int indent) {
-  // Defines and includes go outside of the msvs settings.
-  WriteNamedArray("defines", flags.defines, indent);
-  WriteIncludeDirs(flags, indent);
-
-  // C flags.
-  Indent(indent) << "'msvs_settings': {\n";
-  Indent(indent + kExtraIndent) << "'VCCLCompilerTool': {\n";
-
-  // GYP always uses the VC optimization flag to add a /O? on Visual Studio.
-  // This can produce duplicate values. So look up the GYP value corresponding
-  // to the flags used, and set the same one.
-  std::string optimization = GetVCOptimization(&flags.cflags);
-  WriteNamedArray("AdditionalOptions", flags.cflags, indent + kExtraIndent * 2);
-  // TODO(brettw) cflags_c and cflags_cc!
-  Indent(indent + kExtraIndent * 2) << "'Optimization': "
-                                    << optimization << ",\n";
-  Indent(indent + kExtraIndent) << "},\n";
-
-  // Linker tool stuff.
-  Indent(indent + kExtraIndent) << "'VCLinkerTool': {\n";
-
-  // ...Library dirs.
-  EscapeOptions escape_options;
-  escape_options.mode = ESCAPE_JSON;
-  if (!flags.lib_dirs.empty()) {
-    Indent(indent + kExtraIndent * 2) << "'AdditionalLibraryDirectories': [";
-    for (size_t i = 0; i < flags.lib_dirs.size(); i++) {
-      out_ << " '";
-      EscapeStringToStream(out_,
-                           helper_.GetDirReference(flags.lib_dirs[i], false),
-                           escape_options);
-      out_ << "',";
-    }
-    out_ << " ],\n";
-  }
-
-  // ...Libraries.
-  WriteNamedArray("AdditionalDependencies", flags.libs,
-                  indent + kExtraIndent * 2);
-
-  // ...LD flags.
-  // TODO(brettw) EnableUAC defaults to on and needs to be set. Also
-  // UACExecutionLevel and UACUIAccess depends on that and defaults to 0/false.
-  WriteNamedArray("AdditionalOptions", flags.ldflags, 14);
-  Indent(indent + kExtraIndent) << "},\n";
-  Indent(indent) << "},\n";
-}
-
-void GypBinaryTargetWriter::WriteMacFlags(const Target* target,
-                                          Flags& flags,
-                                          int indent) {
-  WriteNamedArray("defines", flags.defines, indent);
-  WriteIncludeDirs(flags, indent);
-
-  // Libraries and library directories.
-  EscapeOptions escape_options;
-  escape_options.mode = ESCAPE_JSON;
-  if (!flags.lib_dirs.empty()) {
-    Indent(indent + kExtraIndent) << "'library_dirs': [";
-    for (size_t i = 0; i < flags.lib_dirs.size(); i++) {
-      out_ << " '";
-      EscapeStringToStream(out_,
-                           helper_.GetDirReference(flags.lib_dirs[i], false),
-                           escape_options);
-      out_ << "',";
-    }
-    out_ << " ],\n";
-  }
-  if (!flags.libs.empty()) {
-    Indent(indent) << "'link_settings': {\n";
-    Indent(indent + kExtraIndent) << "'libraries': [";
-    for (size_t i = 0; i < flags.libs.size(); i++) {
-      out_ << " '-l";
-      EscapeStringToStream(out_, flags.libs[i], escape_options);
-      out_ << "',";
-    }
-    out_ << " ],\n";
-    Indent(indent) << "},\n";
-  }
-
-  Indent(indent) << "'xcode_settings': {\n";
-
-  // Architecture. GYP reads this value and uses it to generate the -arch
-  // flag, so we always want to remove it from the cflags (which is a side
-  // effect of what GetMacArch does), even in cases where we don't use the
-  // value (in the iOS arm below).
-  std::string arch = GetMacArch(&flags.cflags);
-  if (IsIOS(target)) {
-    // When writing an iOS "target" (not host) target, we set VALID_ARCHS
-    // instead of ARCHS and always use this hardcoded value. This matches the
-    // GYP build.
-    Indent(indent + kExtraIndent) << "'VALID_ARCHS': ['armv7', 'i386'],\n";
-
-    // Tell XCode to target both iPhone and iPad. GN has no such concept.
-    Indent(indent + kExtraIndent) << "'TARGETED_DEVICE_FAMILY': '1,2',\n";
-
-    if (IsIOSSimulator(flags.cflags)) {
-      Indent(indent + kExtraIndent) << "'SDKROOT': 'iphonesimulator',\n";
-    } else {
-      Indent(indent + kExtraIndent) << "'SDKROOT': 'iphoneos',\n";
-      std::string min_ver = GetIPhoneVersionMin(&flags.cflags);
-      if (!min_ver.empty()) {
-        Indent(indent + kExtraIndent) << "'IPHONEOS_DEPLOYMENT_TARGET': '"
-                                      << min_ver << "',\n";
-      }
-    }
-  } else {
-    // When doing regular Mac and "host" iOS (which look like regular Mac)
-    // builds, we can set the ARCHS value to what's specified in the build.
-    if (arch == "i386")
-      Indent(indent + kExtraIndent) << "'ARCHS': [ 'i386' ],\n";
-    else if (arch == "x86_64")
-      Indent(indent + kExtraIndent) << "'ARCHS': [ 'x86_64' ],\n";
-  }
-
-  // C/C++ flags.
-  if (!flags.cflags.empty() || !flags.cflags_c.empty() ||
-      !flags.cflags_objc.empty()) {
-    Indent(indent + kExtraIndent) << "'OTHER_CFLAGS': [";
-    WriteArrayValues(out_, flags.cflags);
-    WriteArrayValues(out_, flags.cflags_c);
-    WriteArrayValues(out_, flags.cflags_objc);
-    out_ << " ],\n";
-  }
-  if (!flags.cflags.empty() || !flags.cflags_cc.empty() ||
-      !flags.cflags_objcc.empty()) {
-    Indent(indent + kExtraIndent) << "'OTHER_CPLUSPLUSFLAGS': [";
-    WriteArrayValues(out_, flags.cflags);
-    WriteArrayValues(out_, flags.cflags_cc);
-    WriteArrayValues(out_, flags.cflags_objcc);
-    out_ << " ],\n";
-  }
-
-  // Ld flags. Don't write these for static libraries. Otherwise, they'll be
-  // passed to the library tool which doesn't expect it (the toolchain does
-  // not use ldflags so these are ignored in the normal build).
-  if (target->output_type() != Target::STATIC_LIBRARY)
-    WriteNamedArray("OTHER_LDFLAGS", flags.ldflags, indent + kExtraIndent);
-
-  // Write the compiler that XCode should use. When we're using clang, we want
-  // the custom one, otherwise don't add this and the default compiler will be
-  // used.
-  //
-  // TODO(brettw) this is a hack. We could add a way for the GN build to set
-  // these values but as far as I can see this is the only use for them, so
-  // currently we manually check the build config's is_clang value.
-  if (IsClang(target)) {
-    base::FilePath clang_path =
-        target_->settings()->build_settings()->GetFullPath(SourceFile(
-            "//third_party/llvm-build/Release+Asserts/bin/clang"));
-    base::FilePath clang_pp_path =
-        target_->settings()->build_settings()->GetFullPath(SourceFile(
-            "//third_party/llvm-build/Release+Asserts/bin/clang++"));
-
-    Indent(indent + kExtraIndent)
-        << "'CC': '" << FilePathToUTF8(clang_path) << "',\n";
-    Indent(indent + kExtraIndent)
-        << "'LDPLUSPLUS': '" << FilePathToUTF8(clang_pp_path) << "',\n";
-  }
-
-  Indent(indent) << "},\n";
-}
-
-void GypBinaryTargetWriter::WriteLinuxFlagsForTarget(const Target* target,
-                                                     int indent) {
-  Flags flags(FlagsFromTarget(target));
-  WriteLinuxFlags(flags, indent);
-}
-
-void GypBinaryTargetWriter::WriteLinuxFlags(const Flags& flags, int indent) {
-  WriteIncludeDirs(flags, indent);
-  WriteNamedArray("defines",      flags.defines,      indent);
-  WriteNamedArray("cflags",       flags.cflags,       indent);
-  WriteNamedArray("cflags_c",     flags.cflags_c,     indent);
-  WriteNamedArray("cflags_cc",    flags.cflags_cc,    indent);
-  WriteNamedArray("cflags_objc",  flags.cflags_objc,  indent);
-  WriteNamedArray("cflags_objcc", flags.cflags_objcc, indent);
-
-  // Put libraries and library directories in with ldflags.
-  Indent(indent) << "'ldflags': ["; \
-  WriteArrayValues(out_, flags.ldflags);
-
-  EscapeOptions escape_options;
-  escape_options.mode = ESCAPE_JSON;
-  for (size_t i = 0; i < flags.lib_dirs.size(); i++) {
-    out_ << " '-L";
-    EscapeStringToStream(out_,
-                         helper_.GetDirReference(flags.lib_dirs[i], false),
-                         escape_options);
-    out_ << "',";
-  }
-
-  for (size_t i = 0; i < flags.libs.size(); i++) {
-    out_ << " '-l";
-    EscapeStringToStream(out_, flags.libs[i], escape_options);
-    out_ << "',";
-  }
-  out_ << " ],\n";
-}
-
-void GypBinaryTargetWriter::WriteMacTargetAndHostFlags(
-    const BuilderRecord* target,
-    const BuilderRecord* host,
-    int indent) {
-  // The Mac flags are sometimes (when cross-compiling) also parameterized on
-  // the toolset.
-  const char kToolsetTargetCondition[] =
-      "'target_conditions': [['_toolset==\"target\"', {\n";
-  const char kToolsetTargetElse[] = "}, {\n";
-  const char kToolsetTargetEnd[] = "}]],\n";
-
-  int extra_indent = 0;
-  if (host) {
-    // Write out the first part of the conditional.
-    Indent(indent) << kToolsetTargetCondition;
-    extra_indent = kExtraIndent;
-  }
-
-  // Always write the target flags (may or may not be inside a target
-  // conditional).
-  {
-    Flags flags(FlagsFromTarget(target->item()->AsTarget()));
-    WriteMacFlags(target->item()->AsTarget(), flags, indent + extra_indent);
-  }
-
-  // Now optionally write the host conditional arm.
-  if (host) {
-    Indent(indent) << kToolsetTargetElse;
-    Flags flags(FlagsFromTarget(host->item()->AsTarget()));
-    WriteMacFlags(host->item()->AsTarget(), flags, indent + kExtraIndent);
-    Indent(indent) << kToolsetTargetEnd;
-  }
-}
-
-void GypBinaryTargetWriter::WriteSources(const Target* target, int indent) {
-  Indent(indent) << "'sources': [\n";
-
-  const Target::FileList& sources = target->sources();
-  for (size_t i = 0; i < sources.size(); i++) {
-    const SourceFile& input_file = sources[i];
-    Indent(indent + kExtraIndent) << "'" << helper_.GetFileReference(input_file)
-                                  << "',\n";
-  }
-
-  Indent(indent) << "],\n";
-}
-
-void GypBinaryTargetWriter::WriteDeps(const Target* target, int indent) {
-  const LabelTargetVector& deps = target->deps();
-  if (deps.empty())
-    return;
-
-  EscapeOptions escape_options;
-  escape_options.mode = ESCAPE_JSON;
-
-  Indent(indent) << "'dependencies': [\n";
-  for (size_t i = 0; i < deps.size(); i++) {
-    Indent(indent + kExtraIndent) << "'";
-    EscapeStringToStream(out_, helper_.GetFullRefForTarget(deps[i].ptr),
-                         escape_options);
-    out_ << "',\n";
-  }
-  Indent(indent) << "],\n";
-}
-
-void GypBinaryTargetWriter::WriteIncludeDirs(const Flags& flags, int indent) {
-  if (flags.include_dirs.empty())
-    return;
-
-  EscapeOptions options;
-  options.mode = ESCAPE_JSON;
-
-  Indent(indent) << "'include_dirs': [";
-  for (size_t i = 0; i < flags.include_dirs.size(); i++) {
-    out_ << " '";
-    EscapeStringToStream(out_,
-                         helper_.GetDirReference(flags.include_dirs[i], false),
-                         options);
-    out_ << "',";
-  }
-  out_ << " ],\n";
-}
-
-void GypBinaryTargetWriter::WriteDirectDependentSettings(int indent) {
-  if (target_->direct_dependent_configs().empty())
-    return;
-  Indent(indent) << "'direct_dependent_settings': {\n";
-
-  Flags flags(FlagsFromConfigList(target_->direct_dependent_configs()));
-  if (target_->settings()->IsLinux())
-    WriteLinuxFlags(flags, indent + kExtraIndent);
-  else if (target_->settings()->IsWin())
-    WriteVCFlags(flags, indent + kExtraIndent);
-  else if (target_->settings()->IsMac())
-    WriteMacFlags(target_, flags, indent + kExtraIndent);
-  Indent(indent) << "},\n";
-}
-
-void GypBinaryTargetWriter::WriteAllDependentSettings(int indent) {
-  if (target_->all_dependent_configs().empty())
-    return;
-  Indent(indent) << "'all_dependent_settings': {\n";
-
-  Flags flags(FlagsFromConfigList(target_->all_dependent_configs()));
-  if (target_->settings()->IsLinux())
-    WriteLinuxFlags(flags, indent + kExtraIndent);
-  else if (target_->settings()->IsWin())
-    WriteVCFlags(flags, indent + kExtraIndent);
-  else if (target_->settings()->IsMac())
-    WriteMacFlags(target_, flags, indent + kExtraIndent);
-  Indent(indent) << "},\n";
-}
-
-GypBinaryTargetWriter::Flags GypBinaryTargetWriter::FlagsFromTarget(
-    const Target* target) const {
-  Flags ret;
-
-  // Extracts a vector of the given type and name from the config values.
-  #define EXTRACT(type, name) \
-      { \
-        Accumulator<type> acc(&ret.name); \
-        RecursiveTargetConfigToStream<type>(target, &ConfigValues::name, \
-                                            acc, out_); \
-      }
-
-  EXTRACT(std::string, defines);
-  EXTRACT(SourceDir,   include_dirs);
-  EXTRACT(std::string, cflags);
-  EXTRACT(std::string, cflags_c);
-  EXTRACT(std::string, cflags_cc);
-  EXTRACT(std::string, cflags_objc);
-  EXTRACT(std::string, cflags_objcc);
-  EXTRACT(std::string, ldflags);
-
-  #undef EXTRACT
-
-  const OrderedSet<SourceDir>& all_lib_dirs = target->all_lib_dirs();
-  for (size_t i = 0; i < all_lib_dirs.size(); i++)
-    ret.lib_dirs.push_back(all_lib_dirs[i]);
-
-  const OrderedSet<std::string> all_libs = target->all_libs();
-  for (size_t i = 0; i < all_libs.size(); i++)
-    ret.libs.push_back(all_libs[i]);
-
-  return ret;
-}
-
-GypBinaryTargetWriter::Flags GypBinaryTargetWriter::FlagsFromConfigList(
-    const LabelConfigVector& configs) const {
-  Flags ret;
-
-  #define EXTRACT(type, name) \
-      FillConfigListValues<type>(configs, &ConfigValues::name, &ret.name);
-
-  EXTRACT(std::string, defines);
-  EXTRACT(SourceDir,   include_dirs);
-  EXTRACT(std::string, cflags);
-  EXTRACT(std::string, cflags_c);
-  EXTRACT(std::string, cflags_cc);
-  EXTRACT(std::string, cflags_objc);
-  EXTRACT(std::string, cflags_objcc);
-  EXTRACT(std::string, ldflags);
-  EXTRACT(SourceDir,   lib_dirs);
-  EXTRACT(std::string, libs);
-
-  #undef EXTRACT
-
-  return ret;
-}
-
-void GypBinaryTargetWriter::WriteNamedArray(
-    const char* name,
-    const std::vector<std::string>& values,
-    int indent) {
-  if (values.empty())
-    return;
-
-  EscapeOptions options;
-  options.mode = ESCAPE_JSON;
-
-  Indent(indent) << "'" << name << "': [";
-  WriteArrayValues(out_, values);
-  out_ << " ],\n";
-}
-
diff --git a/tools/gn/gyp_binary_target_writer.h b/tools/gn/gyp_binary_target_writer.h
deleted file mode 100644
index fe15a9b..0000000
--- a/tools/gn/gyp_binary_target_writer.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_GYP_BINARY_TARGET_WRITER_H_
-#define TOOLS_GN_GYP_BINARY_TARGET_WRITER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "tools/gn/gyp_target_writer.h"
-#include "tools/gn/target.h"
-#include "tools/gn/toolchain.h"
-
-// Writes a portion of a .gyp file for a binary target type (an executable, a
-// shared library, or a static library).
-class GypBinaryTargetWriter : public GypTargetWriter {
- public:
-  GypBinaryTargetWriter(const TargetGroup& group,
-                        const Toolchain* debug_toolchain,
-                        const SourceDir& gyp_dir,
-                        std::ostream& out);
-  virtual ~GypBinaryTargetWriter();
-
-  virtual void Run() OVERRIDE;
-
- private:
-  struct Flags {
-    Flags();
-    ~Flags();
-
-    std::vector<std::string> defines;
-    std::vector<SourceDir> include_dirs;
-
-    std::vector<std::string> cflags;
-    std::vector<std::string> cflags_c;
-    std::vector<std::string> cflags_cc;
-    std::vector<std::string> cflags_objc;
-    std::vector<std::string> cflags_objcc;
-    std::vector<std::string> ldflags;
-    std::vector<SourceDir> lib_dirs;
-    std::vector<std::string> libs;
-  };
-
-  void WriteName(int indent);
-  void WriteType(int indent);
-
-  // Writes the flags, sources, and deps.
-  void WriteVCConfiguration(int indent);
-  void WriteLinuxConfiguration(int indent);
-  void WriteMacConfiguration(int indent);
-
-  // Writes the flags, defines, etc. The flags input is non-const because the
-  // cflags will be fixed up to account for things converted to VC settings
-  // (rather than compiler flags).
-  void WriteVCFlags(Flags& flags, int indent);
-  void WriteMacFlags(const Target* target, Flags& flags, int indent);
-
-  // Writes the Linux compiler and linker flags. The first version does the
-  // flags for the given target, the second version takes a pregenerted list of
-  // flags.
-  void WriteLinuxFlagsForTarget(const Target* target, int indent);
-  void WriteLinuxFlags(const Flags& flags, int indent);
-
-  // Writes out the given target and optional host flags. This will insert a
-  // target conditionn if there is a host build.
-  void WriteMacTargetAndHostFlags(const BuilderRecord* target,
-                                  const BuilderRecord* host,
-                                  int indent);
-
-  // Shared helpers for writing specific parts of GYP files.
-  void WriteSources(const Target* target, int indent);
-  void WriteDeps(const Target* target, int indent);
-  void WriteIncludeDirs(const Flags& flags, int indent);
-  void WriteDirectDependentSettings(int indent);
-  void WriteAllDependentSettings(int indent);
-
-  // Writes out the given flags and such from all configs in the given list.
-  void WriteSettingsFromConfigList(const std::vector<const Config*>& configs,
-                                   int indent);
-
-  // Fills the given flags structure.
-  Flags FlagsFromTarget(const Target* target) const;
-  Flags FlagsFromConfigList(const LabelConfigVector& configs) const;
-
-  // Writes the given array with the given name. The indent should be the
-  // indenting for the name, the values will be indented 2 spaces from there.
-  // Writes nothing if there is nothing in the array.
-  void WriteNamedArray(const char* name,
-                       const std::vector<std::string>& values,
-                       int indent);
-
-  // All associated targets.
-  TargetGroup group_;
-
-  DISALLOW_COPY_AND_ASSIGN(GypBinaryTargetWriter);
-};
-
-#endif  // TOOLS_GN_GYP_BINARY_TARGET_WRITER_H_
-
diff --git a/tools/gn/gyp_binary_target_writer_unittest.cc b/tools/gn/gyp_binary_target_writer_unittest.cc
deleted file mode 100644
index 4903ab9..0000000
--- a/tools/gn/gyp_binary_target_writer_unittest.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "tools/gn/builder_record.h"
-#include "tools/gn/gyp_binary_target_writer.h"
-#include "tools/gn/test_with_scope.h"
-
-TEST(GypBinaryTargetWriter, ProductExtension) {
-  TestWithScope setup;
-  setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
-
-  // A shared library w/ the product_extension set to a custom value.
-  scoped_ptr<Target> target(
-      new Target(setup.settings(), Label(SourceDir("//foo/"), "bar")));
-  target->set_output_type(Target::SHARED_LIBRARY);
-  target->set_output_extension(std::string("so.6"));
-  target->sources().push_back(SourceFile("//foo/input1.cc"));
-  target->sources().push_back(SourceFile("//foo/input2.cc"));
-
-  BuilderRecord record(BuilderRecord::ITEM_TARGET, target->label());
-  record.set_item(target.PassAs<Item>());
-  GypTargetWriter::TargetGroup group;
-  group.debug = &record;
-  group.release = &record;
-
-  setup.settings()->set_target_os(Settings::LINUX);
-
-  std::ostringstream out;
-  GypBinaryTargetWriter writer(group, setup.toolchain(),
-                               SourceDir("//out/gn_gyp/"), out);
-  writer.Run();
-
-  const char expected[] =
-      "    {\n"
-      "      'target_name': 'bar',\n"
-      "      'product_name': 'bar',\n"
-      "      'product_extension': 'so.6',\n"
-      "      'type': 'shared_library',\n"
-      "      'target_conditions': [\n"
-      "        ['_toolset == \"target\"', {\n"
-      "          'configurations': {\n"
-      "            'Debug': {\n"
-      "              'ldflags': [ ],\n"
-      "            },\n"
-      "            'Release': {\n"
-      "              'ldflags': [ ],\n"
-      "            },\n"
-      "          },\n"
-      "          'sources': [\n"
-      "            '<(DEPTH)/foo/input1.cc',\n"
-      "            '<(DEPTH)/foo/input2.cc',\n"
-      "          ],\n"
-      "        },],\n"
-      "      ],\n"
-      "    },\n";
-  std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
-}
-
-TEST(GypBinaryTargetWriter, EmptyProductExtension) {
-  TestWithScope setup;
-  setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
-
-  // This test is the same as ProductExtension, except that
-  // we call set_output_extension("") and ensure that we still get the default.
-  scoped_ptr<Target> target(
-      new Target(setup.settings(), Label(SourceDir("//foo/"), "bar")));
-  target->set_output_type(Target::SHARED_LIBRARY);
-
-  target->sources().push_back(SourceFile("//foo/input1.cc"));
-  target->sources().push_back(SourceFile("//foo/input2.cc"));
-  target->set_output_extension(std::string());
-
-  BuilderRecord record(BuilderRecord::ITEM_TARGET, target->label());
-  record.set_item(target.PassAs<Item>());
-  GypTargetWriter::TargetGroup group;
-  group.debug = &record;
-  group.release = &record;
-
-  setup.settings()->set_target_os(Settings::LINUX);
-
-  std::ostringstream out;
-  GypBinaryTargetWriter writer(group, setup.toolchain(),
-                               SourceDir("//out/gn_gyp/"), out);
-  writer.Run();
-
-  const char expected[] =
-      "    {\n"
-      "      'target_name': 'bar',\n"
-      "      'product_name': 'bar',\n"
-      "      'type': 'shared_library',\n"
-      "      'target_conditions': [\n"
-      "        ['_toolset == \"target\"', {\n"
-      "          'configurations': {\n"
-      "            'Debug': {\n"
-      "              'ldflags': [ ],\n"
-      "            },\n"
-      "            'Release': {\n"
-      "              'ldflags': [ ],\n"
-      "            },\n"
-      "          },\n"
-      "          'sources': [\n"
-      "            '<(DEPTH)/foo/input1.cc',\n"
-      "            '<(DEPTH)/foo/input2.cc',\n"
-      "          ],\n"
-      "        },],\n"
-      "      ],\n"
-      "    },\n";
-  std::string out_str = out.str();
-  EXPECT_EQ(expected, out_str);
-}
diff --git a/tools/gn/gyp_helper.cc b/tools/gn/gyp_helper.cc
deleted file mode 100644
index fb669af..0000000
--- a/tools/gn/gyp_helper.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/gyp_helper.h"
-
-#include "tools/gn/err.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/source_file.h"
-#include "tools/gn/target.h"
-#include "tools/gn/toolchain.h"
-
-GypHelper::GypHelper() {
-}
-
-GypHelper::~GypHelper() {
-}
-
-SourceFile GypHelper::GetGypFileForTarget(const Target* target,
-                                          Err* err) const {
-  // Use the manually specified one if its there.
-  if (!target->gyp_file().is_null())
-    return target->gyp_file();
-
-  // Otherwise inherit the directory name.
-  const std::string& dir = target->label().dir().value();
-  size_t last_slash = dir.size() - 1;
-  std::string dir_name;
-  if (last_slash > 0) {
-    size_t next_to_last_slash = dir.rfind('/', last_slash - 1);
-    if (next_to_last_slash != std::string::npos) {
-      dir_name = dir.substr(next_to_last_slash + 1,
-                            last_slash - next_to_last_slash - 1);
-    }
-  }
-  if (dir_name.empty()) {
-    *err = Err(Location(), "Need to specify a gyp_file value for " +
-        target->label().GetUserVisibleName(false) + "\n"
-        "since I can't make up one with no name.");
-    return SourceFile();
-  }
-
-  return SourceFile(dir + dir_name + ".gyp");
-}
-
-std::string GypHelper::GetNameForTarget(const Target* target) const {
-  if (target->settings()->is_default())
-    return target->label().name();  // Default toolchain has no suffix.
-  return target->label().name() + "_" +
-         target->settings()->toolchain_label().name();
-}
-
-std::string GypHelper::GetFullRefForTarget(const Target* target) const {
-  Err err;
-  SourceFile gypfile = GetGypFileForTarget(target, &err);
-  CHECK(gypfile.is_source_absolute()) <<
-      "GYP files should not be system-absolute: " << gypfile.value();
-
-  std::string ret("<(DEPTH)/");
-  // Trim off the leading double-slash.
-  ret.append(&gypfile.value()[2], gypfile.value().size() - 2);
-  ret.push_back(':');
-  ret.append(GetNameForTarget(target));
-
-  return ret;
-}
-
-std::string GypHelper::GetFileReference(const SourceFile& file) const {
-  std::string ret;
-  if (file.is_null())
-    return ret;
-
-  // Use FilePath's resolver to get the system paths out (on Windows this
-  // requires special handling). Since it's absolute, it doesn't matter what
-  // we pass in as the source root.
-  if (file.is_system_absolute())
-    return FilePathToUTF8(file.Resolve(base::FilePath()));
-
-  // Source root relative, strip the "//".
-  ret.assign("<(DEPTH)/");
-  ret.append(&file.value()[2], file.value().size() - 2);
-  return ret;
-}
-
-std::string GypHelper::GetDirReference(const SourceDir& dir,
-                                       bool include_slash) const {
-  std::string ret;
-  if (dir.is_null())
-    return ret;
-
-  if (dir.is_system_absolute()) {
-    ret = FilePathToUTF8(dir.Resolve(base::FilePath()));
-  } else {
-    ret.assign("<(DEPTH)/");
-    ret.append(&dir.value()[2], dir.value().size() - 2);
-  }
-
-  // Optionally trim the slash off the end.
-  if (!ret.empty() && !include_slash &&
-      (ret[ret.size() - 1] == '/' || ret[ret.size() - 1] == '\\'))
-    ret.resize(ret.size() - 1);
-
-  return ret;
-}
diff --git a/tools/gn/gyp_helper.h b/tools/gn/gyp_helper.h
deleted file mode 100644
index d3b15ec..0000000
--- a/tools/gn/gyp_helper.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_GYP_HELPER_H_
-#define TOOLS_GN_GYP_HELPER_H_
-
-#include <string>
-
-#include "base/basictypes.h"
-
-class Err;
-class SourceDir;
-class SourceFile;
-class Target;
-
-// Danger this class is NOT threadsafe and reads the targets in a
-// non-threadsafe way, so this should only be used in single-threaded mode.
-class GypHelper {
- public:
-  GypHelper();
-  ~GypHelper();
-
-  SourceFile GetGypFileForTarget(const Target* target, Err* err) const;
-
-  // Returns the name part of the given target. Example "base". This will
-  // include toolchain info for non-default toolchains.
-  std::string GetNameForTarget(const Target* target) const;
-
-  // Returns a full reference to the given target, including the GYP file
-  // and name. Example "<(DEPTH)/base/base.gyp:base".
-  std::string GetFullRefForTarget(const Target* target) const;
-
-  std::string GetFileReference(const SourceFile& file) const;
-  std::string GetDirReference(const SourceDir& dir, bool include_slash) const;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GypHelper);
-};
-
-#endif  // TOOLS_GN_GYP_HELPER_H_
diff --git a/tools/gn/gyp_target_writer.cc b/tools/gn/gyp_target_writer.cc
deleted file mode 100644
index 789b6b0..0000000
--- a/tools/gn/gyp_target_writer.cc
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "tools/gn/gyp_target_writer.h"
-
-#include <iostream>
-
-#include "base/file_util.h"
-#include "base/files/file_path.h"
-#include "tools/gn/build_settings.h"
-#include "tools/gn/builder_record.h"
-#include "tools/gn/filesystem_utils.h"
-#include "tools/gn/gyp_action_target_writer.h"
-#include "tools/gn/gyp_binary_target_writer.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/settings.h"
-#include "tools/gn/target.h"
-#include "tools/gn/toolchain.h"
-
-GypTargetWriter::TargetGroup::TargetGroup()
-    : debug(NULL),
-      release(NULL),
-      host_debug(NULL),
-      host_release(NULL),
-      debug64(NULL),
-      release64(NULL),
-      xcode_debug(NULL),
-      xcode_release(NULL),
-      xcode_host_debug(NULL),
-      xcode_host_release(NULL) {
-}
-
-GypTargetWriter::GypTargetWriter(const Target* target,
-                                 const Toolchain* toolchain,
-                                 const SourceDir& gyp_dir,
-                                 std::ostream& out)
-    : settings_(target->settings()),
-      target_(target),
-      toolchain_(toolchain),
-      gyp_dir_(gyp_dir),
-      out_(out),
-      // All GYP paths are relative to GYP file.
-      path_output_(gyp_dir, ESCAPE_JSON, false) {
-}
-
-GypTargetWriter::~GypTargetWriter() {
-}
-
-// static
-void GypTargetWriter::WriteFile(const SourceFile& gyp_file,
-                                const std::vector<TargetGroup>& targets,
-                                const Toolchain* debug_toolchain,
-                                Err* err) {
-  if (targets.empty())
-    return;
-  const Settings* debug_settings =
-      targets[0].debug->item()->AsTarget()->settings();
-  const BuildSettings* debug_build_settings = debug_settings->build_settings();
-
-  base::FilePath gyp_file_path = debug_build_settings->GetFullPath(gyp_file);
-  base::CreateDirectory(gyp_file_path.DirName());
-
-  std::stringstream file;
-  file << "# Generated by GN. Do not edit.\n\n";
-  file << "{\n";
-
-  // Optional GYP header specified in the default debug toolchain.
-  if (!debug_toolchain->gyp_header().empty())
-    file << debug_toolchain->gyp_header() << std::endl;
-
-  file << "  'skip_includes': 1,\n";
-  file << "  'targets': [\n";
-
-  for (size_t i = 0; i < targets.size(); i++) {
-    const Target* cur = targets[i].debug->item()->AsTarget();
-    switch (cur->output_type()) {
-      case Target::COPY_FILES:
-        break;  // TODO(brettw)
-      case Target::ACTION:
-      case Target::ACTION_FOREACH: {
-        GypActionTargetWriter writer(targets[i], debug_toolchain,
-                                     gyp_file.GetDir(), file);
-        writer.Run();
-        break;
-      }
-      case Target::GROUP:
-        break;  // TODO(brettw)
-      case Target::EXECUTABLE:
-      case Target::STATIC_LIBRARY:
-      case Target::SHARED_LIBRARY:
-      case Target::SOURCE_SET: {
-        GypBinaryTargetWriter writer(targets[i], debug_toolchain,
-                                     gyp_file.GetDir(), file);
-        writer.Run();
-        break;
-      }
-      default:
-        CHECK(0);
-    }
-  }
-
-  file << "  ],\n}\n";
-
-  std::string contents = file.str();
-  base::WriteFile(gyp_file_path, contents.c_str(),
-                       static_cast<int>(contents.size()));
-}
-
-std::ostream& GypTargetWriter::Indent(int spaces) {
-  return Indent(out_, spaces);
-}
-
-// static
-std::ostream& GypTargetWriter::Indent(std::ostream& out, int spaces) {
-  const char kSpaces[81] =
-      "                                        "
-      "                                        ";
-  CHECK(static_cast<size_t>(spaces) <= arraysize(kSpaces) - 1);
-  out.write(kSpaces, spaces);
-  return out;
-}
diff --git a/tools/gn/gyp_target_writer.h b/tools/gn/gyp_target_writer.h
deleted file mode 100644
index 09bb820..0000000
--- a/tools/gn/gyp_target_writer.h
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef TOOLS_GN_GYP_TARGET_WRITER_H_
-#define TOOLS_GN_GYP_TARGET_WRITER_H_
-
-#include <iosfwd>
-#include <vector>
-
-#include "base/basictypes.h"
-#include "tools/gn/gyp_helper.h"
-#include "tools/gn/path_output.h"
-
-class BuilderRecord;
-class Err;
-class Settings;
-class SourceFile;
-class Target;
-class Toolchain;
-
-class GypTargetWriter {
- public:
-  struct TargetGroup {
-    TargetGroup();
-
-    // Returns "a" record associated with this group. This is used when getting
-    // general things like the sources list that should be the same across all
-    // records in a group.
-    const BuilderRecord* get() const {
-      // We assume we always have either a host or a target debug build.
-      return debug ? debug : host_debug;
-    }
-
-    const BuilderRecord* debug;
-    const BuilderRecord* release;
-
-    // When the main compile is targeting a different architecture, these will
-    // contain the builds with the host system's toolchain. Only supported on
-    // Linux.
-    const BuilderRecord* host_debug;
-    const BuilderRecord* host_release;
-
-    // On Windows, we do both 32-bit and 64-bit builds. Null on non-Windows.
-    const BuilderRecord* debug64;
-    const BuilderRecord* release64;
-
-    // On Mac/iOS, there are some nontrivial differences between the GYP Ninja
-    // build and the GYP XCode build. In GYP, these are parameterized as
-    // conditions using the generator flag. To emulate this, we have different
-    // builds for the XCode and Ninja versions of the GYP file, and the
-    // generator wraps everything in a big condition so that GYP does the right
-    // thing.
-    //
-    // These refer to the GYP-XCode build. The "regular" debug and release
-    // targets above refer to the GYP-Ninja build.
-    const BuilderRecord* xcode_debug;
-    const BuilderRecord* xcode_release;
-
-    // Optional host versions of the xcode config when cross-compiling to iOS.
-    const BuilderRecord* xcode_host_debug;
-    const BuilderRecord* xcode_host_release;
-  };
-
-  GypTargetWriter(const Target* target,
-                  const Toolchain* toolchain,
-                  const SourceDir& gyp_dir,
-                  std::ostream& out);
-  virtual ~GypTargetWriter();
-
-  static void WriteFile(const SourceFile& gyp_file,
-                        const std::vector<TargetGroup>& targets,
-                        const Toolchain* debug_toolchain,
-                        Err* err);
-
-  virtual void Run() = 0;
-
- protected:
-  // Writes the given number of spaces to the output stream and returns it.
-  std::ostream& Indent(int spaces);
-  static std::ostream& Indent(std::ostream& out, int spaces);
-
-  static const int kExtraIndent = 2;
-
-  const Settings* settings_;  // Non-owning.
-  const Target* target_;  // Non-owning.
-  const Toolchain* toolchain_;  // Toolchain corresponding to target_.
-  SourceDir gyp_dir_;  // Dir of GYP file.
-  std::ostream& out_;
-
-  GypHelper helper_;
-  PathOutput path_output_;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GypTargetWriter);
-};
-
-#endif  // TOOLS_GN_GYP_TARGET_WRITER_H_
diff --git a/tools/gn/import_manager.cc b/tools/gn/import_manager.cc
index 0d87942..2e8293e 100644
--- a/tools/gn/import_manager.cc
+++ b/tools/gn/import_manager.cc
@@ -81,6 +81,6 @@
     }
   }
 
-  return imported_scope->NonRecursiveMergeTo(scope, node_for_err,
+  return imported_scope->NonRecursiveMergeTo(scope, false, node_for_err,
                                              "import", err);
 }
diff --git a/tools/gn/parse_tree.cc b/tools/gn/parse_tree.cc
index bc50f20..4015fd1 100644
--- a/tools/gn/parse_tree.cc
+++ b/tools/gn/parse_tree.cc
@@ -53,6 +53,38 @@
 }
 
 Value AccessorNode::Execute(Scope* scope, Err* err) const {
+  if (index_)
+    return ExecuteArrayAccess(scope, err);
+  else if (member_)
+    return ExecuteScopeAccess(scope, err);
+  NOTREACHED();
+  return Value();
+}
+
+LocationRange AccessorNode::GetRange() const {
+  if (index_)
+    return LocationRange(base_.location(), index_->GetRange().end());
+  else if (member_)
+    return LocationRange(base_.location(), member_->GetRange().end());
+  NOTREACHED();
+  return LocationRange();
+}
+
+Err AccessorNode::MakeErrorDescribing(const std::string& msg,
+                                      const std::string& help) const {
+  return Err(GetRange(), msg, help);
+}
+
+void AccessorNode::Print(std::ostream& out, int indent) const {
+  out << IndentFor(indent) << "ACCESSOR\n";
+  out << IndentFor(indent + 1) << base_.value() << "\n";
+  if (index_)
+    index_->Print(out, indent + 1);
+  else if (member_)
+    member_->Print(out, indent + 1);
+}
+
+Value AccessorNode::ExecuteArrayAccess(Scope* scope, Err* err) const {
   Value index_value = index_->Execute(scope, err);
   if (err->has_error())
     return Value();
@@ -91,19 +123,46 @@
   return base_value->list_value()[index_sizet];
 }
 
-LocationRange AccessorNode::GetRange() const {
-  return LocationRange(base_.location(), index_->GetRange().end());
-}
+Value AccessorNode::ExecuteScopeAccess(Scope* scope, Err* err) const {
+  // We jump through some hoops here since ideally a.b will count "b" as
+  // accessed in the given scope. The value "a" might be in some normal nested
+  // scope and we can modify it, but it might also be inherited from the
+  // readonly root scope and we can't do used variable tracking on it. (It's
+  // not legal to const cast it away since the root scope will be in readonly
+  // mode and being accessed from multiple threads without locking.) So this
+  // code handles both cases.
+  const Value* result = NULL;
 
-Err AccessorNode::MakeErrorDescribing(const std::string& msg,
-                                      const std::string& help) const {
-  return Err(GetRange(), msg, help);
-}
+  // Look up the value in the scope named by "base_".
+  Value* mutable_base_value = scope->GetMutableValue(base_.value(), true);
+  if (mutable_base_value) {
+    // Common case: base value is mutable so we can track variable accesses
+    // for unused value warnings.
+    if (!mutable_base_value->VerifyTypeIs(Value::SCOPE, err))
+      return Value();
+    result = mutable_base_value->scope_value()->GetValue(
+        member_->value().value(), true);
+  } else {
+    // Fall back to see if the value is on a read-only scope.
+    const Value* const_base_value = scope->GetValue(base_.value(), true);
+    if (const_base_value) {
+      // Read only value, don't try to mark the value access as a "used" one.
+      if (!const_base_value->VerifyTypeIs(Value::SCOPE, err))
+        return Value();
+      result =
+          const_base_value->scope_value()->GetValue(member_->value().value());
+    } else {
+      *err = Err(base_, "Undefined identifier.");
+      return Value();
+    }
+  }
 
-void AccessorNode::Print(std::ostream& out, int indent) const {
-  out << IndentFor(indent) << "ACCESSOR\n";
-  out << IndentFor(indent + 1) << base_.value() << "\n";
-  index_->Print(out, indent + 1);
+  if (!result) {
+    *err = Err(member_.get(), "No value named \"" +
+        member_->value().value() + "\" in scope \"" + base_.value() + "\"");
+    return Value();
+  }
+  return *result;
 }
 
 // BinaryOpNode ---------------------------------------------------------------
diff --git a/tools/gn/parse_tree.h b/tools/gn/parse_tree.h
index cc3550f..f9ec543 100644
--- a/tools/gn/parse_tree.h
+++ b/tools/gn/parse_tree.h
@@ -63,10 +63,29 @@
 
 // AccessorNode ----------------------------------------------------------------
 
-// Access an array element.
+// Access an array or scope element.
 //
-// If we need to add support for member variables like "variable.len" I was
-// thinking this would also handle that case.
+// Currently, such values are only read-only. In that you can do:
+//   a = obj1.a
+//   b = obj2[0]
+// But not
+//   obj1.a = 5
+//   obj2[0] = 6
+//
+// In the current design where the dot operator is used only for templates, we
+// explicitly don't want to allow you to do "invoker.foo = 5", so if we added
+// support for accessors to be lvalues, we would also need to add some concept
+// of a constant scope. Supporting this would also add a lot of complications
+// to the operator= implementation, since some accessors might return values
+// in the const root scope that shouldn't be modified. Without a strong
+// use-case for this, it seems simpler to just disallow it.
+//
+// Additionally, the left-hand-side of the accessor must currently be an
+// identifier. So you can't do things like:
+//   function_call()[1]
+//   a = b.c.d
+// These are easier to implement if we needed them but given the very limited
+// use cases for this, it hasn't seemed worth the bother.
 class AccessorNode : public ParseNode {
  public:
   AccessorNode();
@@ -80,18 +99,30 @@
       const std::string& help = std::string()) const OVERRIDE;
   virtual void Print(std::ostream& out, int indent) const OVERRIDE;
 
-  // Base is the thing on the left of the [], currently always required to be
-  // an identifier token.
+  // Base is the thing on the left of the [] or dot, currently always required
+  // to be an identifier token.
   const Token& base() const { return base_; }
   void set_base(const Token& b) { base_ = b; }
 
-  // Index is the expression inside the [].
+  // Index is the expression inside the []. Will be null if member is set.
   const ParseNode* index() const { return index_.get(); }
   void set_index(scoped_ptr<ParseNode> i) { index_ = i.Pass(); }
 
+  // The member is the identifier on the right hand side of the dot. Will be
+  // null if the index is set.
+  const IdentifierNode* member() const { return member_.get(); }
+  void set_member(scoped_ptr<IdentifierNode> i) { member_ = i.Pass(); }
+
  private:
+  Value ExecuteArrayAccess(Scope* scope, Err* err) const;
+  Value ExecuteScopeAccess(Scope* scope, Err* err) const;
+
   Token base_;
+
+  // Either index or member will be set according to what type of access this
+  // is.
   scoped_ptr<ParseNode> index_;
+  scoped_ptr<IdentifierNode> member_;
 
   DISALLOW_COPY_AND_ASSIGN(AccessorNode);
 };
diff --git a/tools/gn/parse_tree_unittest.cc b/tools/gn/parse_tree_unittest.cc
new file mode 100644
index 0000000..8120e22
--- /dev/null
+++ b/tools/gn/parse_tree_unittest.cc
@@ -0,0 +1,49 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/gn/input_file.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/test_with_scope.h"
+
+TEST(ParseTree, Accessor) {
+  TestWithScope setup;
+
+  // Make a pretend parse node with proper tracking that we can blame for the
+  // given value.
+  InputFile input_file(SourceFile("//foo"));
+  Token base_token(Location(&input_file, 1, 1), Token::IDENTIFIER, "a");
+  Token member_token(Location(&input_file, 1, 1), Token::IDENTIFIER, "b");
+
+  AccessorNode accessor;
+  accessor.set_base(base_token);
+
+  scoped_ptr<IdentifierNode> member_identifier(
+      new IdentifierNode(member_token));
+  accessor.set_member(member_identifier.Pass());
+
+  // The access should fail because a is not defined.
+  Err err;
+  Value result = accessor.Execute(setup.scope(), &err);
+  EXPECT_TRUE(err.has_error());
+  EXPECT_EQ(Value::NONE, result.type());
+
+  // Define a as a Scope. It should still fail because b isn't defined.
+  Scope a_scope(setup.scope());
+  err = Err();
+  setup.scope()->SetValue("a", Value(NULL, &a_scope), NULL);
+  result = accessor.Execute(setup.scope(), &err);
+  EXPECT_TRUE(err.has_error());
+  EXPECT_EQ(Value::NONE, result.type());
+
+  // Define b, accessor should succeed now.
+  const int64 kBValue = 42;
+  err = Err();
+  a_scope.SetValue("b", Value(NULL, kBValue), NULL);
+  result = accessor.Execute(setup.scope(), &err);
+  EXPECT_FALSE(err.has_error());
+  ASSERT_EQ(Value::INTEGER, result.type());
+  EXPECT_EQ(kBValue, result.int_value());
+}
diff --git a/tools/gn/parser.cc b/tools/gn/parser.cc
index 6392eed..f533542 100644
--- a/tools/gn/parser.cc
+++ b/tools/gn/parser.cc
@@ -19,7 +19,7 @@
 // assignment := ident {'=' | '+=' | '-='} expr
 
 enum Precedence {
-  PRECEDENCE_ASSIGNMENT = 1,
+  PRECEDENCE_ASSIGNMENT = 1,  // Lowest precedence.
   PRECEDENCE_OR = 2,
   PRECEDENCE_AND = 3,
   PRECEDENCE_EQUALITY = 4,
@@ -27,15 +27,16 @@
   PRECEDENCE_SUM = 6,
   PRECEDENCE_PREFIX = 7,
   PRECEDENCE_CALL = 8,
+  PRECEDENCE_DOT = 9,         // Highest precedence.
 };
 
-// The top-level for blocks/ifs is still recursive descent, the expression
-// parser is a Pratt parser. The basic idea there is to have the precedences
-// (and associativities) encoded relative to each other and only parse up
-// until you hit something of that precedence. There's a dispatch table in
-// expressions_ at the top of parser.cc that describes how each token
-// dispatches if it's seen as either a prefix or infix operator, and if it's
-// infix, what its precedence is.
+// The top-level for blocks/ifs is recursive descent, the expression parser is
+// a Pratt parser. The basic idea there is to have the precedences (and
+// associativities) encoded relative to each other and only parse up until you
+// hit something of that precedence. There's a dispatch table in expressions_
+// at the top of parser.cc that describes how each token dispatches if it's
+// seen as either a prefix or infix operator, and if it's infix, what its
+// precedence is.
 //
 // Refs:
 // - http://javascript.crockford.com/tdop/tdop.html
@@ -62,6 +63,7 @@
   {NULL, &Parser::BinaryOperator, PRECEDENCE_AND},              // BOOLEAN_AND
   {NULL, &Parser::BinaryOperator, PRECEDENCE_OR},               // BOOLEAN_OR
   {&Parser::Not, NULL, -1},                                     // BANG
+  {NULL, &Parser::DotOperator, PRECEDENCE_DOT},                 // DOT
   {&Parser::Group, NULL, -1},                                   // LEFT_PAREN
   {NULL, NULL, -1},                                             // RIGHT_PAREN
   {&Parser::List, &Parser::Subscript, PRECEDENCE_CALL},         // LEFT_BRACKET
@@ -311,7 +313,10 @@
   // TODO: Maybe support more complex expressions like a[0][0]. This would
   // require work on the evaluator too.
   if (left->AsIdentifier() == NULL) {
-    *err_ = Err(left.get(), "May only subscript simple identifiers");
+    *err_ = Err(left.get(), "May only subscript identifiers.",
+        "The thing on the left hand side of the [] must be an identifier\n"
+        "and not an expression. If you need this, you'll have to assign the\n"
+        "value to a temporary before subscripting. Sorry.");
     return scoped_ptr<ParseNode>();
   }
   scoped_ptr<ParseNode> value = ParseExpression();
@@ -322,6 +327,30 @@
   return accessor.PassAs<ParseNode>();
 }
 
+scoped_ptr<ParseNode> Parser::DotOperator(scoped_ptr<ParseNode> left,
+                                          Token token) {
+  if (left->AsIdentifier() == NULL) {
+    *err_ = Err(left.get(), "May only use \".\" for identifiers.",
+        "The thing on the left hand side of the dot must be an identifier\n"
+        "and not an expression. If you need this, you'll have to assign the\n"
+        "value to a temporary first. Sorry.");
+    return scoped_ptr<ParseNode>();
+  }
+
+  scoped_ptr<ParseNode> right = ParseExpression(PRECEDENCE_DOT);
+  if (!right || !right->AsIdentifier()) {
+    *err_ = Err(token, "Expected identifier for right-hand-side of \".\"",
+        "Good: a.cookies\nBad: a.42\nLooks good but still bad: a.cookies()");
+    return scoped_ptr<ParseNode>();
+  }
+
+  scoped_ptr<AccessorNode> accessor(new AccessorNode);
+  accessor->set_base(left->AsIdentifier()->value());
+  accessor->set_member(scoped_ptr<IdentifierNode>(
+      static_cast<IdentifierNode*>(right.release())));
+  return accessor.PassAs<ParseNode>();
+}
+
 // Does not Consume the start or end token.
 scoped_ptr<ListNode> Parser::ParseList(Token::Type stop_before,
                                        bool allow_trailing_comma) {
diff --git a/tools/gn/parser.h b/tools/gn/parser.h
index 76cc71a..407b472 100644
--- a/tools/gn/parser.h
+++ b/tools/gn/parser.h
@@ -61,6 +61,7 @@
                                          Token token);
   scoped_ptr<ParseNode> Assignment(scoped_ptr<ParseNode> left, Token token);
   scoped_ptr<ParseNode> Subscript(scoped_ptr<ParseNode> left, Token token);
+  scoped_ptr<ParseNode> DotOperator(scoped_ptr<ParseNode> left, Token token);
 
   // Helper to parse a comma separated list, optionally allowing trailing
   // commas (allowed in [] lists, not in function calls).
diff --git a/tools/gn/parser_unittest.cc b/tools/gn/parser_unittest.cc
index 7ef5ff6..adb8fdb 100644
--- a/tools/gn/parser_unittest.cc
+++ b/tools/gn/parser_unittest.cc
@@ -27,6 +27,8 @@
 
   Err err;
   scoped_ptr<ParseNode> result = Parser::Parse(tokens, &err);
+  if (!result)
+    err.PrintToStdout();
   ASSERT_TRUE(result);
 
   std::ostringstream collector;
@@ -215,15 +217,31 @@
 }
 
 TEST(Parser, Accessor) {
-  DoParserPrintTest("a=b[2]",
+  // Accessor indexing.
+  DoParserPrintTest("a=b[c+2]",
                     "BLOCK\n"
                     " BINARY(=)\n"
                     "  IDENTIFIER(a)\n"
                     "  ACCESSOR\n"
                     "   b\n"  // AccessorNode is a bit weird in that it holds
                               // a Token, not a ParseNode for the base.
-                    "   LITERAL(2)\n");
+                    "   BINARY(+)\n"
+                    "    IDENTIFIER(c)\n"
+                    "    LITERAL(2)\n");
   DoParserErrorTest("a = b[1][0]", 1, 5);
+
+  // Member accessors.
+  DoParserPrintTest("a=b.c+2",
+                    "BLOCK\n"
+                    " BINARY(=)\n"
+                    "  IDENTIFIER(a)\n"
+                    "  BINARY(+)\n"
+                    "   ACCESSOR\n"
+                    "    b\n"
+                    "    IDENTIFIER(c)\n"
+                    "   LITERAL(2)\n");
+  DoParserErrorTest("a = b.c.d", 1, 6);  // Can't nest accessors (currently).
+  DoParserErrorTest("a.b = 5", 1, 1);  // Can't assign to accessors (currently).
 }
 
 TEST(Parser, Condition) {
diff --git a/tools/gn/scope.cc b/tools/gn/scope.cc
index 3f714ec..78612f2 100644
--- a/tools/gn/scope.cc
+++ b/tools/gn/scope.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "tools/gn/parse_tree.h"
+#include "tools/gn/template.h"
 
 namespace {
 
@@ -41,6 +42,7 @@
 Scope::~Scope() {
   STLDeleteContainerPairSecondPointers(target_defaults_.begin(),
                                        target_defaults_.end());
+  STLDeleteContainerPairSecondPointers(templates_.begin(), templates_.end());
 }
 
 const Value* Scope::GetValue(const base::StringPiece& ident,
@@ -68,6 +70,22 @@
   return NULL;
 }
 
+Value* Scope::GetMutableValue(const base::StringPiece& ident,
+                              bool counts_as_used) {
+  // Don't do programatic values, which are not mutable.
+  RecordMap::iterator found = values_.find(ident);
+  if (found != values_.end()) {
+    if (counts_as_used)
+      found->second.used = true;
+    return &found->second.value;
+  }
+
+  // Search in the parent mutable scope, but not const one.
+  if (mutable_containing_)
+    return mutable_containing_->GetMutableValue(ident, counts_as_used);
+  return NULL;
+}
+
 Value* Scope::GetValueForcedToCurrentScope(const base::StringPiece& ident,
                                            const ParseNode* set_node) {
   RecordMap::iterator found = values_.find(ident);
@@ -103,14 +121,14 @@
   return &r.value;
 }
 
-bool Scope::AddTemplate(const std::string& name, const FunctionCallNode* decl) {
+bool Scope::AddTemplate(const std::string& name, scoped_ptr<Template> templ) {
   if (GetTemplate(name))
     return false;
-  templates_[name] = decl;
+  templates_[name] = templ.release();
   return true;
 }
 
-const FunctionCallNode* Scope::GetTemplate(const std::string& name) const {
+const Template* Scope::GetTemplate(const std::string& name) const {
   TemplateMap::const_iterator found = templates_.find(name);
   if (found != templates_.end())
     return found->second;
@@ -175,24 +193,28 @@
 }
 
 bool Scope::NonRecursiveMergeTo(Scope* dest,
+                                bool clobber_existing,
                                 const ParseNode* node_for_err,
                                 const char* desc_for_err,
                                 Err* err) const {
   // Values.
   for (RecordMap::const_iterator i = values_.begin(); i != values_.end(); ++i) {
     const Value& new_value = i->second.value;
-    const Value* existing_value = dest->GetValue(i->first);
-    if (existing_value && new_value != *existing_value) {
-      // Value present in both the source and the dest.
-      std::string desc_string(desc_for_err);
-      *err = Err(node_for_err, "Value collision.",
-          "This " + desc_string + " contains \"" + i->first.as_string() + "\"");
-      err->AppendSubErr(Err(i->second.value, "defined here.",
-          "Which would clobber the one in your current scope"));
-      err->AppendSubErr(Err(*existing_value, "defined here.",
-          "Executing " + desc_string + " should not conflict with anything "
-          "in the current\nscope unless the values are identical."));
-      return false;
+    if (!clobber_existing) {
+      const Value* existing_value = dest->GetValue(i->first);
+      if (existing_value && new_value != *existing_value) {
+        // Value present in both the source and the dest.
+        std::string desc_string(desc_for_err);
+        *err = Err(node_for_err, "Value collision.",
+            "This " + desc_string + " contains \"" + i->first.as_string() +
+            "\"");
+        err->AppendSubErr(Err(i->second.value, "defined here.",
+            "Which would clobber the one in your current scope"));
+        err->AppendSubErr(Err(*existing_value, "defined here.",
+            "Executing " + desc_string + " should not conflict with anything "
+            "in the current\nscope unless the values are identical."));
+        return false;
+      }
     }
     dest->values_[i->first] = i->second;
   }
@@ -200,34 +222,42 @@
   // Target defaults are owning pointers.
   for (NamedScopeMap::const_iterator i = target_defaults_.begin();
        i != target_defaults_.end(); ++i) {
-    if (dest->GetTargetDefaults(i->first)) {
-      // TODO(brettw) it would be nice to know the origin of a
-      // set_target_defaults so we can give locations for the colliding target
-      // defaults.
-      std::string desc_string(desc_for_err);
-      *err = Err(node_for_err, "Target defaults collision.",
-          "This " + desc_string + " contains target defaults for\n"
-          "\"" + i->first + "\" which would clobber one for the\n"
-          "same target type in your current scope. It's unfortunate that I'm "
-          "too stupid\nto tell you the location of where the target defaults "
-          "were set. Usually\nthis happens in the BUILDCONFIG.gn file.");
-      return false;
+    if (!clobber_existing) {
+      if (dest->GetTargetDefaults(i->first)) {
+        // TODO(brettw) it would be nice to know the origin of a
+        // set_target_defaults so we can give locations for the colliding target
+        // defaults.
+        std::string desc_string(desc_for_err);
+        *err = Err(node_for_err, "Target defaults collision.",
+            "This " + desc_string + " contains target defaults for\n"
+            "\"" + i->first + "\" which would clobber one for the\n"
+            "same target type in your current scope. It's unfortunate that I'm "
+            "too stupid\nto tell you the location of where the target defaults "
+            "were set. Usually\nthis happens in the BUILDCONFIG.gn file.");
+        return false;
+      }
     }
 
-    Scope* s = new Scope(settings_);
-    i->second->NonRecursiveMergeTo(s, node_for_err, "<SHOULDN'T HAPPEN>", err);
-    dest->target_defaults_[i->first] = s;
+    // Be careful to delete any pointer we're about to clobber.
+    Scope** dest_scope = &dest->target_defaults_[i->first];
+    if (*dest_scope)
+      delete *dest_scope;
+    *dest_scope = new Scope(settings_);
+    i->second->NonRecursiveMergeTo(*dest_scope, clobber_existing, node_for_err,
+                                   "<SHOULDN'T HAPPEN>", err);
   }
 
   // Sources assignment filter.
   if (sources_assignment_filter_) {
-    if (dest->GetSourcesAssignmentFilter()) {
-      // Sources assignment filter present in both the source and the dest.
-      std::string desc_string(desc_for_err);
-      *err = Err(node_for_err, "Assignment filter collision.",
-          "The " + desc_string + " contains a sources_assignment_filter which\n"
-          "would clobber the one in your current scope.");
-      return false;
+    if (!clobber_existing) {
+      if (dest->GetSourcesAssignmentFilter()) {
+        // Sources assignment filter present in both the source and the dest.
+        std::string desc_string(desc_for_err);
+        *err = Err(node_for_err, "Assignment filter collision.",
+            "The " + desc_string + " contains a sources_assignment_filter "
+            "which\nwould clobber the one in your current scope.");
+        return false;
+      }
     }
     dest->sources_assignment_filter_.reset(
         new PatternList(*sources_assignment_filter_));
@@ -236,25 +266,56 @@
   // Templates.
   for (TemplateMap::const_iterator i = templates_.begin();
        i != templates_.end(); ++i) {
-    const FunctionCallNode* existing_template = dest->GetTemplate(i->first);
-    if (existing_template) {
-      // Rule present in both the source and the dest.
-      std::string desc_string(desc_for_err);
-      *err = Err(node_for_err, "Template collision.",
-          "This " + desc_string + " contains a template \"" + i->first + "\"");
-      err->AppendSubErr(Err(i->second->function(), "defined here.",
-          "Which would clobber the one in your current scope"));
-      err->AppendSubErr(Err(existing_template->function(), "defined here.",
-          "Executing " + desc_string + " should not conflict with anything "
-          "in the current\nscope."));
-      return false;
+    if (!clobber_existing) {
+      const Template* existing_template = dest->GetTemplate(i->first);
+      if (existing_template) {
+        // Rule present in both the source and the dest.
+        std::string desc_string(desc_for_err);
+        *err = Err(node_for_err, "Template collision.",
+            "This " + desc_string + " contains a template \"" +
+            i->first + "\"");
+        err->AppendSubErr(Err(i->second->GetDefinitionRange(), "defined here.",
+            "Which would clobber the one in your current scope"));
+        err->AppendSubErr(Err(existing_template->GetDefinitionRange(),
+            "defined here.",
+            "Executing " + desc_string + " should not conflict with anything "
+            "in the current\nscope."));
+        return false;
+      }
     }
-    dest->templates_.insert(*i);
+
+    // Be careful to delete any pointer we're about to clobber.
+    const Template** dest_template = &dest->templates_[i->first];
+    if (*dest_template)
+      delete *dest_template;
+    *dest_template = i->second;
   }
 
   return true;
 }
 
+scoped_ptr<Scope> Scope::MakeClosure() const {
+  scoped_ptr<Scope> result;
+  if (const_containing_) {
+    // We reached the top of the mutable scope stack. The result scope just
+    // references the const scope (which will never change).
+    result.reset(new Scope(const_containing_));
+  } else if (mutable_containing_) {
+    // There are more nested mutable scopes. Recursively go up the stack to
+    // get the closure.
+    result = mutable_containing_->MakeClosure();
+  } else {
+    // This is a standalone scope, just copy it.
+    result.reset(new Scope(settings_));
+  }
+
+  // Add in our variables and we're done.
+  Err err;
+  NonRecursiveMergeTo(result.get(), true, NULL, "<SHOULDN'T HAPPEN>", &err);
+  DCHECK(!err.has_error());
+  return result.Pass();
+}
+
 Scope* Scope::MakeTargetDefaults(const std::string& target_type) {
   if (GetTargetDefaults(target_type))
     return NULL;
diff --git a/tools/gn/scope.h b/tools/gn/scope.h
index d4a35ff..82e037f 100644
--- a/tools/gn/scope.h
+++ b/tools/gn/scope.h
@@ -21,6 +21,7 @@
 class ParseNode;
 class Settings;
 class TargetManager;
+class Template;
 
 // Scope for the script execution.
 //
@@ -86,6 +87,30 @@
                         bool counts_as_used);
   const Value* GetValue(const base::StringPiece& ident) const;
 
+  // Returns the requested value as a mutable one if possible. If the value
+  // is not found in a mutable scope, then returns null. Note that the value
+  // could still exist in a const scope, so GetValue() could still return
+  // non-null in this case.
+  //
+  // Say you have a local scope that then refers to the const root scope from
+  // the master build config. You can't change the values from the master
+  // build config (it's read-only so it can be read from multiple threads
+  // without locking). Read-only operations would work on values from the root
+  // scope, but write operations would only work on values in the derived
+  // scope(s).
+  //
+  // Be careful when calling this. It's not normally correct to modify values,
+  // but you should instead do a new Set each time.
+  //
+  // Consider this code:
+  //   a = 5
+  //    {
+  //       a = 6
+  //    }
+  // The 6 should get set on the nested scope rather than modify the value
+  // in the outer one.
+  Value* GetMutableValue(const base::StringPiece& ident, bool counts_as_used);
+
   // Same as GetValue, but if the value exists in a parent scope, we'll copy
   // it to the current scope. If the return value is non-null, the value is
   // guaranteed to be set in the current scope. Generatlly this will be used
@@ -104,11 +129,11 @@
                   const ParseNode* set_node);
 
   // Templates associated with this scope. A template can only be set once, so
-  // AddTemplate will fail and return NULL if a rule with that name already
+  // AddTemplate will fail and return false if a rule with that name already
   // exists. GetTemplate returns NULL if the rule doesn't exist, and it will
   // check all containing scoped rescursively.
-  bool AddTemplate(const std::string& name, const FunctionCallNode* decl);
-  const FunctionCallNode* GetTemplate(const std::string& name) const;
+  bool AddTemplate(const std::string& name, scoped_ptr<Template> templ);
+  const Template* GetTemplate(const std::string& name) const;
 
   // Marks the given identifier as (un)used in the current scope.
   void MarkUsed(const base::StringPiece& ident);
@@ -134,10 +159,13 @@
   // copied, neither will the reference to the containing scope (this is why
   // it's "non-recursive").
   //
-  // It is an error to merge a variable into a scope that already has something
-  // with that name in scope (meaning in that scope or in any of its containing
-  // scopes). If this happens, the error will be set and the function will
-  // return false.
+  // If clobber_existing is true, any existing values will be overwritten. In
+  // this mode, this function will never fail.
+  //
+  // If clobber_existing is false, it will be an error to merge a variable into
+  // a scope that already has something with that name in scope (meaning in
+  // that scope or in any of its containing scopes). If this happens, the error
+  // will be set and the function will return false.
   //
   // This is used in different contexts. When generating the error, the given
   // parse node will be blamed, and the given desc will be used to describe
@@ -145,10 +173,18 @@
   // would be "import" when doing an import, and the error string would say
   // something like "The import contains...".
   bool NonRecursiveMergeTo(Scope* dest,
+                           bool clobber_existing,
                            const ParseNode* node_for_err,
                            const char* desc_for_err,
                            Err* err) const;
 
+  // Constructs a scope that is a copy of the current one. Nested scopes will
+  // be collapsed until we reach a const containing scope. The resulting
+  // closure will reference the const containing scope as its containing scope
+  // (since we assume the const scope won't change, we don't have to copy its
+  // values).
+  scoped_ptr<Scope> MakeClosure() const;
+
   // Makes an empty scope with the given name. Returns NULL if the name is
   // already set.
   Scope* MakeTargetDefaults(const std::string& target_type);
@@ -243,9 +279,8 @@
   // scope's filter.
   scoped_ptr<PatternList> sources_assignment_filter_;
 
-  // Non-owning pointers, the function calls are owned by the input file which
-  // should be kept around by the input file manager.
-  typedef std::map<std::string, const FunctionCallNode*> TemplateMap;
+  // Owning pointers, must be deleted.
+  typedef std::map<std::string, const Template*> TemplateMap;
   TemplateMap templates_;
 
   // Opaque pointers. See SetProperty() above.
diff --git a/tools/gn/scope_unittest.cc b/tools/gn/scope_unittest.cc
index a693957..5585e50 100644
--- a/tools/gn/scope_unittest.cc
+++ b/tools/gn/scope_unittest.cc
@@ -8,6 +8,21 @@
 #include "tools/gn/scope.h"
 #include "tools/gn/test_with_scope.h"
 
+namespace {
+
+bool HasStringValueEqualTo(const Scope* scope,
+                           const char* name,
+                           const char* expected_value) {
+  const Value* value = scope->GetValue(name);
+  if (!value)
+    return false;
+  if (value->type() != Value::STRING)
+    return false;
+  return value->string_value() == expected_value;
+}
+
+}  // namespace
+
 TEST(Scope, NonRecursiveMergeTo) {
   TestWithScope setup;
 
@@ -29,11 +44,27 @@
     new_scope.SetValue("v", new_value, &assignment);
 
     Err err;
-    EXPECT_FALSE(new_scope.NonRecursiveMergeTo(
-        setup.scope(), &assignment, "error", &err));
+    EXPECT_FALSE(setup.scope()->NonRecursiveMergeTo(
+        &new_scope, false, &assignment, "error", &err));
     EXPECT_TRUE(err.has_error());
   }
 
+  // The clobber flag should just overwrite colliding values.
+  {
+    Scope new_scope(setup.settings());
+    Value new_value(&assignment, "goodbye");
+    new_scope.SetValue("v", new_value, &assignment);
+
+    Err err;
+    EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
+        &new_scope, true, &assignment, "error", &err));
+    EXPECT_FALSE(err.has_error());
+
+    const Value* found_value = new_scope.GetValue("v");
+    ASSERT_TRUE(found_value);
+    EXPECT_TRUE(old_value == *found_value);
+  }
+
   // Don't flag values that technically collide but have the same value.
   {
     Scope new_scope(setup.settings());
@@ -41,8 +72,98 @@
     new_scope.SetValue("v", new_value, &assignment);
 
     Err err;
-    EXPECT_TRUE(new_scope.NonRecursiveMergeTo(
-        setup.scope(), &assignment, "error", &err));
+    EXPECT_TRUE(setup.scope()->NonRecursiveMergeTo(
+        &new_scope, false, &assignment, "error", &err));
     EXPECT_FALSE(err.has_error());
   }
 }
+
+TEST(Scope, MakeClosure) {
+  // Create 3 nested scopes [const root from setup] <- nested1 <- nested2.
+  TestWithScope setup;
+
+  // Make a pretend parse node with proper tracking that we can blame for the
+  // given value.
+  InputFile input_file(SourceFile("//foo"));
+  Token assignment_token(Location(&input_file, 1, 1), Token::STRING,
+      "\"hello\"");
+  LiteralNode assignment;
+  assignment.set_value(assignment_token);
+  setup.scope()->SetValue("on_root", Value(&assignment, "on_root"),
+                           &assignment);
+
+  // Root scope should be const from the nested caller's perspective.
+  Scope nested1(static_cast<const Scope*>(setup.scope()));
+  nested1.SetValue("on_one", Value(&assignment, "on_one"), &assignment);
+
+  Scope nested2(&nested1);
+  nested2.SetValue("on_one", Value(&assignment, "on_two"), &assignment);
+  nested2.SetValue("on_two", Value(&assignment, "on_two2"), &assignment);
+
+  // Making a closure from the root scope.
+  scoped_ptr<Scope> result = setup.scope()->MakeClosure();
+  EXPECT_FALSE(result->containing());  // Should have no containing scope.
+  EXPECT_TRUE(result->GetValue("on_root"));  // Value should be copied.
+
+  // Making a closure from the second nested scope.
+  result = nested2.MakeClosure();
+  EXPECT_EQ(setup.scope(),
+            result->containing());  // Containing scope should be the root.
+  EXPECT_TRUE(HasStringValueEqualTo(result.get(), "on_root", "on_root"));
+  EXPECT_TRUE(HasStringValueEqualTo(result.get(), "on_one", "on_two"));
+  EXPECT_TRUE(HasStringValueEqualTo(result.get(), "on_two", "on_two2"));
+}
+
+TEST(Scope, GetMutableValue) {
+  TestWithScope setup;
+
+  // Make a pretend parse node with proper tracking that we can blame for the
+  // given value.
+  InputFile input_file(SourceFile("//foo"));
+  Token assignment_token(Location(&input_file, 1, 1), Token::STRING,
+      "\"hello\"");
+  LiteralNode assignment;
+  assignment.set_value(assignment_token);
+
+  const char kOnConst[] = "on_const";
+  const char kOnMutable1[] = "on_mutable1";
+  const char kOnMutable2[] = "on_mutable2";
+
+  Value value(&assignment, "hello");
+
+  // Create a root scope with one value.
+  Scope root_scope(setup.settings());
+  root_scope.SetValue(kOnConst, value, &assignment);
+
+  // Create a first nested scope with a different value.
+  const Scope* const_root_scope = &root_scope;
+  Scope mutable_scope1(const_root_scope);
+  mutable_scope1.SetValue(kOnMutable1, value, &assignment);
+
+  // Create a second nested scope with a different value.
+  Scope mutable_scope2(&mutable_scope1);
+  mutable_scope2.SetValue(kOnMutable2, value, &assignment);
+
+  // Check getting root scope values.
+  EXPECT_TRUE(mutable_scope2.GetValue(kOnConst, true));
+  EXPECT_FALSE(mutable_scope2.GetMutableValue(kOnConst, true));
+
+  // Test reading a value from scope 1.
+  Value* mutable1_result = mutable_scope2.GetMutableValue(kOnMutable1, false);
+  ASSERT_TRUE(mutable1_result);
+  EXPECT_TRUE(*mutable1_result == value);
+
+  // Make sure CheckForUnusedVars works on scope1 (we didn't mark the value as
+  // used in the previous step).
+  Err err;
+  EXPECT_FALSE(mutable_scope1.CheckForUnusedVars(&err));
+  mutable1_result = mutable_scope2.GetMutableValue(kOnMutable1, true);
+  EXPECT_TRUE(mutable1_result);
+  err = Err();
+  EXPECT_TRUE(mutable_scope1.CheckForUnusedVars(&err));
+
+  // Test reading a value from scope 2.
+  Value* mutable2_result = mutable_scope2.GetMutableValue(kOnMutable2, true);
+  ASSERT_TRUE(mutable2_result);
+  EXPECT_TRUE(*mutable2_result == value);
+}
diff --git a/tools/gn/secondary/chrome/BUILD.gn b/tools/gn/secondary/chrome/BUILD.gn
index 1728a83..57c9350 100644
--- a/tools/gn/secondary/chrome/BUILD.gn
+++ b/tools/gn/secondary/chrome/BUILD.gn
@@ -64,8 +64,6 @@
 }
 
 static_library("browser") {
-  external = true
-
   if (is_linux) {
     if (toolkit_uses_gtk) {
       libs = [ "gconf-2" ]
@@ -83,8 +81,6 @@
 }
 
 static_library("common") {
-  external = true
-
   if (use_nss && is_linux) {
     # common/net uses NSS.
     # TODO(brettw) have a better way to express this without having to do
@@ -170,15 +166,12 @@
 }
 
 source_set("plugin") {
-  external = true
 }
 
 source_set("renderer") {
-  external = true
 }
 
 source_set("utility") {
-  external = true
 }
 
 
@@ -188,7 +181,7 @@
 build_relative_about_credits_file =
   rebase_path(about_credits_file, root_build_dir)
 
-custom("about_credits") {
+action("about_credits") {
   script = "//tools/licenses.py"
   outputs = [ about_credits_file ]
 
diff --git a/tools/gn/secondary/components/language_usage_metrics/BUILD.gn b/tools/gn/secondary/components/language_usage_metrics/BUILD.gn
index 6d30575..a3e26be 100644
--- a/tools/gn/secondary/components/language_usage_metrics/BUILD.gn
+++ b/tools/gn/secondary/components/language_usage_metrics/BUILD.gn
@@ -3,8 +3,6 @@
 # found in the LICENSE file.
 
 static_library("language_usage_metrics") {
-  external = true
-
   sources = [
     "language_usage_metrics.cc",
     "language_usage_metrics.h",
diff --git a/tools/gn/secondary/components/navigation_metrics/BUILD.gn b/tools/gn/secondary/components/navigation_metrics/BUILD.gn
index 4a80bf9..ae78ee0 100644
--- a/tools/gn/secondary/components/navigation_metrics/BUILD.gn
+++ b/tools/gn/secondary/components/navigation_metrics/BUILD.gn
@@ -3,8 +3,6 @@
 # found in the LICENSE file.
 
 static_library("navigation_metrics") {
-  external = true
-
   sources = [
     "navigation_metrics.cc",
     "navigation_metrics.h",
diff --git a/tools/gn/secondary/components/onc/BUILD.gn b/tools/gn/secondary/components/onc/BUILD.gn
index 423d560..2b3aa66 100644
--- a/tools/gn/secondary/components/onc/BUILD.gn
+++ b/tools/gn/secondary/components/onc/BUILD.gn
@@ -3,8 +3,6 @@
 # found in the LICENSE file.
 
 component("onc_component") {
-  external = true
-
   sources = [
     "onc_constants.cc",
     "onc_constants.h",
diff --git a/tools/gn/secondary/components/startup_metric_utils/BUILD.gn b/tools/gn/secondary/components/startup_metric_utils/BUILD.gn
index ca6fae7..31d249f 100644
--- a/tools/gn/secondary/components/startup_metric_utils/BUILD.gn
+++ b/tools/gn/secondary/components/startup_metric_utils/BUILD.gn
@@ -3,8 +3,6 @@
 # found in the LICENSE file.
 
 static_library("startup_metric_utils") {
-  external = true
-
   sources = [
     "startup_metric_utils.cc",
     "startup_metric_utils.h",
diff --git a/tools/gn/secondary/components/translate/BUILD.gn b/tools/gn/secondary/components/translate/BUILD.gn
index 04467b2..251315a 100644
--- a/tools/gn/secondary/components/translate/BUILD.gn
+++ b/tools/gn/secondary/components/translate/BUILD.gn
@@ -3,8 +3,6 @@
 # found in the LICENSE file.
 
 static_library("translate_core_browser") {
-  external = true
-
   sources = [
     "core/browser/language_state.cc",
     "core/browser/language_state.h",
@@ -40,8 +38,6 @@
 }
 
 static_library("translate_core_common") {
-  external = true
-
   sources = [
     "core/common/language_detection_details.cc",
     "core/common/language_detection_details.h",
diff --git a/tools/gn/secondary/crypto/BUILD.gn b/tools/gn/secondary/crypto/BUILD.gn
index 2ce5b38..b9ea117 100644
--- a/tools/gn/secondary/crypto/BUILD.gn
+++ b/tools/gn/secondary/crypto/BUILD.gn
@@ -17,7 +17,6 @@
 ]
 
 component("crypto") {
-  external = true
   output_name = "crcrypto"  # Avoid colliding with OpenSSL's libcrypto.
   sources = [
     "apple_keychain.h",
@@ -186,7 +185,6 @@
 # A minimal crypto subset for core features that small standalone targets can
 # use to reduce code size.
 static_library("crypto_minimal") {
-  external = true
   sources = crypto_minimal_sources
 
   deps = [
@@ -198,7 +196,6 @@
 }
 
 test("crypto_unittests") {
-  external = true
   sources = [
     # Tests.
     "curve25519_unittest.cc",
diff --git a/tools/gn/secondary/device/usb/BUILD.gn b/tools/gn/secondary/device/usb/BUILD.gn
index 2d0c7d8..36d499b 100644
--- a/tools/gn/secondary/device/usb/BUILD.gn
+++ b/tools/gn/secondary/device/usb/BUILD.gn
@@ -14,7 +14,7 @@
   deps = [ ":device_usb_ids" ]

 }

 

-custom("device_usb_ids") {

+action("device_usb_ids") {

   script = "//tools/usb_ids/usb_ids.py"

   source_prereqs = [ source_ids ]

   outputs = [ generated_ids ]

diff --git a/tools/gn/secondary/ipc/BUILD.gn b/tools/gn/secondary/ipc/BUILD.gn
index ae3897a..15143a7 100644
--- a/tools/gn/secondary/ipc/BUILD.gn
+++ b/tools/gn/secondary/ipc/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 component("ipc") {
-  external = true
   sources = [
     "file_descriptor_set_posix.cc",
     "file_descriptor_set_posix.h",
@@ -80,7 +79,6 @@
 }
 
 test("ipc_tests") {
-  external = true
   sources = [
     "file_descriptor_set_posix_unittest.cc",
     "ipc_channel_posix_unittest.cc",
@@ -123,7 +121,6 @@
 }
 
 test("ipc_perftests") {
-  external = true
   sources = [
     "ipc_perftests.cc",
     "ipc_test_base.cc",
@@ -152,7 +149,6 @@
 }
 
 static_library("test_support_ipc") {
-  external = true
   sources = [
     "ipc_multiprocess_test.cc",
     "ipc_multiprocess_test.h",
diff --git a/tools/gn/secondary/net/BUILD.gn b/tools/gn/secondary/net/BUILD.gn
index f8b56a9..81ca9af 100644
--- a/tools/gn/secondary/net/BUILD.gn
+++ b/tools/gn/secondary/net/BUILD.gn
@@ -6,7 +6,6 @@
 import("//tools/grit/grit_rule.gni")
 
 component("net") {
-  external = true
   sources = [
     "android/cert_verify_result_android.h",
     "android/cert_verify_result_android_list.h",
@@ -1198,12 +1197,10 @@
 }
 
 #grit("net_resources") {
-#  external = true
 #  source = "base/net_resources.grd"
 #}
 
 static_library("http_server") {
-  external = true
   sources = [
     "server/http_connection.cc",
     "server/http_connection.h",
diff --git a/tools/gn/secondary/net/third_party/nss/BUILD.gn b/tools/gn/secondary/net/third_party/nss/BUILD.gn
index 0815df7..b0c9669 100644
--- a/tools/gn/secondary/net/third_party/nss/BUILD.gn
+++ b/tools/gn/secondary/net/third_party/nss/BUILD.gn
@@ -11,7 +11,6 @@
 # TODO(brettw) move this to net/third_party/nss/ssl once GYP backwards-compat
 # is no longer needed.
 component("ssl") {
-  external = true
   # Not named "ssl" so the lib doesn't conflict with OpenSSL's libssl
   output_name = "crssl"
 
diff --git a/tools/gn/secondary/sdch/BUILD.gn b/tools/gn/secondary/sdch/BUILD.gn
index c8f20c7..5e13403 100644
--- a/tools/gn/secondary/sdch/BUILD.gn
+++ b/tools/gn/secondary/sdch/BUILD.gn
@@ -7,7 +7,6 @@
 }
 
 static_library("sdch") {
-  external = true
   sources = [
     "open-vcdiff/src/addrcache.cc",
     "open-vcdiff/src/blockhash.cc",
diff --git a/tools/gn/secondary/skia/BUILD.gn b/tools/gn/secondary/skia/BUILD.gn
index e13bb5f..e5765f1 100644
--- a/tools/gn/secondary/skia/BUILD.gn
+++ b/tools/gn/secondary/skia/BUILD.gn
@@ -1113,7 +1113,6 @@
   }
 
   static_library("skia_library") {
-    external = true
     sources = skia_library_sources
 
     deps = [
@@ -1151,7 +1150,6 @@
   }
 
   static_library("skia_chrome") {
-    external = true
     sources = skia_chrome_sources
 
     configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/tools/gn/secondary/testing/gmock/BUILD.gn b/tools/gn/secondary/testing/gmock/BUILD.gn
index 3d70a1e..907d117 100644
--- a/tools/gn/secondary/testing/gmock/BUILD.gn
+++ b/tools/gn/secondary/testing/gmock/BUILD.gn
@@ -8,8 +8,6 @@
 }
 
 static_library("gmock") {
-  gyp_file = "gmock.gyp"
-  external = true
   sources = [
     # Sources based on files in r173 of gmock.
     "include/gmock/gmock-actions.h",
@@ -43,8 +41,6 @@
 }
 
 static_library("gmock_main") {
-  external = true
-  gyp_file = "gmock.gyp"
   sources = [ "src/gmock_main.cc" ]
   deps = [ ":gmock" ]
 }
diff --git a/tools/gn/secondary/testing/gtest/BUILD.gn b/tools/gn/secondary/testing/gtest/BUILD.gn
index 82de0a6..b77d178 100644
--- a/tools/gn/secondary/testing/gtest/BUILD.gn
+++ b/tools/gn/secondary/testing/gtest/BUILD.gn
@@ -33,8 +33,6 @@
 }
 
 static_library("gtest") {
-  external = true
-  gyp_file = "gtest.gyp"
   sources = [
     "include/gtest/gtest-death-test.h",
     "include/gtest/gtest-message.h",
diff --git a/tools/gn/secondary/third_party/icu/BUILD.gn b/tools/gn/secondary/third_party/icu/BUILD.gn
index cbe7335..587f099 100644
--- a/tools/gn/secondary/third_party/icu/BUILD.gn
+++ b/tools/gn/secondary/third_party/icu/BUILD.gn
@@ -45,7 +45,6 @@
 }
 
 component("icui18n") {
-  external = true
   sources = [
     "source/i18n/anytrans.cpp",
     "source/i18n/astro.cpp",
@@ -218,7 +217,6 @@
 }
 
 component("icuuc") {
-  external = true
   sources = [
     "source/common/bmpset.cpp",
     "source/common/brkeng.cpp",
@@ -402,13 +400,11 @@
 if (is_win) {
   # On Windows the target DLL is pre-built so just use a copy rule.
   copy("icudata") {
-    external = true
     sources = [ "windows/icudt.dll" ]
     outputs = [ "$root_out_dir/icudt.dll" ]
   }
 } else {
   static_library("icudata") {
-    external = true
     sources = [
       # These are hand-generated, but will do for now.  The linux version is an
       # identical copy of the (mac) icudt46l_dat.S file, modulo removal of the
diff --git a/tools/gn/secondary/third_party/leveldatabase/BUILD.gn b/tools/gn/secondary/third_party/leveldatabase/BUILD.gn
index d113aa5..74b5c60 100644
--- a/tools/gn/secondary/third_party/leveldatabase/BUILD.gn
+++ b/tools/gn/secondary/third_party/leveldatabase/BUILD.gn
@@ -20,7 +20,6 @@
 }
 
 static_library("leveldatabase") {
-  external = true
   sources = [
     "env_chromium.cc",
     "env_chromium.h",
diff --git a/tools/gn/secondary/third_party/libevent/BUILD.gn b/tools/gn/secondary/third_party/libevent/BUILD.gn
index 6896141..3b2eec1 100644
--- a/tools/gn/secondary/third_party/libevent/BUILD.gn
+++ b/tools/gn/secondary/third_party/libevent/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 static_library("libevent") {
-  external = true
   sources = [
     "buffer.c",
     "epoll.c",
diff --git a/tools/gn/secondary/third_party/libusb/BUILD.gn b/tools/gn/secondary/third_party/libusb/BUILD.gn
index d4d6f6f..b374316 100644
--- a/tools/gn/secondary/third_party/libusb/BUILD.gn
+++ b/tools/gn/secondary/third_party/libusb/BUILD.gn
@@ -9,7 +9,6 @@
 }
 
 static_library("libusb") {
-  external = true
   sources = [
     "src/config.h",
     "src/libusb/core.c",
diff --git a/tools/gn/secondary/third_party/libxml/BUILD.gn b/tools/gn/secondary/third_party/libxml/BUILD.gn
index aa6936e..16fe1b3 100644
--- a/tools/gn/secondary/third_party/libxml/BUILD.gn
+++ b/tools/gn/secondary/third_party/libxml/BUILD.gn
@@ -25,7 +25,6 @@
 }
 
 static_library("libxml") {
-  external = true
   output_name = "libxml2"
   sources = [
     "chromium/libxml_utils.h",
diff --git a/tools/gn/secondary/third_party/mach_override/BUILD.gn b/tools/gn/secondary/third_party/mach_override/BUILD.gn
index c176218..f50d3cc 100644
--- a/tools/gn/secondary/third_party/mach_override/BUILD.gn
+++ b/tools/gn/secondary/third_party/mach_override/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 static_library("libudis86") {
-  external = true
   sources = [
     "libudis86/decode.c",
     "libudis86/decode.h",
@@ -28,7 +27,6 @@
 }
 
 static_library("mach_override") {
-  external = true
   sources = [
     "mach_override.c",
     "mach_override.h",
diff --git a/tools/gn/secondary/third_party/modp_b64/BUILD.gn b/tools/gn/secondary/third_party/modp_b64/BUILD.gn
index bfa7479..539abe1 100644
--- a/tools/gn/secondary/third_party/modp_b64/BUILD.gn
+++ b/tools/gn/secondary/third_party/modp_b64/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 static_library("modp_b64") {
-  external = true
   sources = [
     "modp_b64.cc",
     "modp_b64.h",
diff --git a/tools/gn/secondary/third_party/wtl/BUILD.gn b/tools/gn/secondary/third_party/wtl/BUILD.gn
index 67b7595..7ebe9d9 100644
--- a/tools/gn/secondary/third_party/wtl/BUILD.gn
+++ b/tools/gn/secondary/third_party/wtl/BUILD.gn
@@ -10,6 +10,5 @@
 # actually generate anything linkable, and inject the required config for
 # making the include directories work.
 group("wtl") {
-  external = true
   all_dependent_configs = ":wtl_includes"
 }
diff --git a/tools/gn/secondary/third_party/zlib/BUILD.gn b/tools/gn/secondary/third_party/zlib/BUILD.gn
index 0e257f1..033d462 100644
--- a/tools/gn/secondary/third_party/zlib/BUILD.gn
+++ b/tools/gn/secondary/third_party/zlib/BUILD.gn
@@ -7,8 +7,6 @@
 }
 
 static_library("zlib") {
-  external = true
-
   if (!is_win) {
     # Don't stomp on "libzlib" on other platforms.
     output_name = "chrome_zlib"
@@ -51,7 +49,6 @@
 }
 
 static_library("minizip") {
-  external = true
   sources = [
     "contrib/minizip/ioapi.c",
     "contrib/minizip/ioapi.h",
@@ -87,7 +84,6 @@
 }
 
 static_library("zip") {
-  external = true
   sources = [
     "google/zip.cc",
     "google/zip.h",
diff --git a/tools/gn/secondary/tools/grit/grit_rule.gni b/tools/gn/secondary/tools/grit/grit_rule.gni
index 06cee4a..d658cbc 100644
--- a/tools/gn/secondary/tools/grit/grit_rule.gni
+++ b/tools/gn/secondary/tools/grit/grit_rule.gni
@@ -13,9 +13,9 @@
 #     # files.
 #   }
 template("grit") {
-  assert(defined(source),
+  assert(defined(invoker.source),
          "\"source\" must be defined for the grit template $target_name")
-  assert(!defined(sources) && !defined(outputs),
+  assert(!defined(invoker.sources) && !defined(invoker.outputs),
          "Neither \"sources\" nor \"outputs\" can be defined for the grit " +
          "template $target_name")
 
@@ -26,9 +26,11 @@
   resource_ids =
     rebase_path("//tools/gritsettings/resource_ids", root_build_dir)
   output_dir = rebase_path(target_gen_dir, root_build_dir)
-  source_path = rebase_path(source, root_build_dir)
+  source_path = rebase_path(invoker.source, root_build_dir)
 
-  if (!defined(grit_flags)) {
+  if (defined(invoker.grit_flags)) {
+    grit_flags = invoker.grit_flags
+  } else {
     grit_flags = []  # These are optional so default to empty list.
   }
 
@@ -56,7 +58,7 @@
   }
 
   grit_custom_target = target_name + "_grit"
-  custom(grit_custom_target) {
+  action(grit_custom_target) {
     script = "//tools/grit/grit.py"
     source_prereqs = grit_inputs
     outputs = grit_outputs
diff --git a/tools/gn/secondary/ui/BUILD.gn b/tools/gn/secondary/ui/BUILD.gn
index 251393e..4a7595f 100644
--- a/tools/gn/secondary/ui/BUILD.gn
+++ b/tools/gn/secondary/ui/BUILD.gn
@@ -3,8 +3,6 @@
 # found in the LICENSE file.
 
 component("ui") {
-  external = true
-
   # TODO(brettw) do this target, this current stuff is only to make Chrome
   # link.
 
diff --git a/tools/gn/target.cc b/tools/gn/target.cc
index 56b140f..7a2b625 100644
--- a/tools/gn/target.cc
+++ b/tools/gn/target.cc
@@ -54,8 +54,7 @@
 Target::Target(const Settings* settings, const Label& label)
     : Item(settings, label),
       output_type_(UNKNOWN),
-      hard_dep_(false),
-      external_(false) {
+      hard_dep_(false) {
 }
 
 Target::~Target() {
diff --git a/tools/gn/target.h b/tools/gn/target.h
index 2cf0409..5e257ec 100644
--- a/tools/gn/target.h
+++ b/tools/gn/target.h
@@ -121,9 +121,6 @@
     return forward_dependent_configs_;
   }
 
-  bool external() const { return external_; }
-  void set_external(bool e) { external_ = e; }
-
   const std::set<const Target*>& inherited_libraries() const {
     return inherited_libraries_;
   }
@@ -138,9 +135,6 @@
   const OrderedSet<SourceDir>& all_lib_dirs() const { return all_lib_dirs_; }
   const OrderedSet<std::string>& all_libs() const { return all_libs_; }
 
-  const SourceFile& gyp_file() const { return gyp_file_; }
-  void set_gyp_file(const SourceFile& gf) { gyp_file_ = gf; }
-
  private:
   // Pulls necessary information from dependents to this one when all
   // dependencies have been resolved.
@@ -190,8 +184,6 @@
   ConfigValues config_values_;  // Used for all binary targets.
   ActionValues action_values_;  // Used for action[_foreach] targets.
 
-  SourceFile gyp_file_;
-
   DISALLOW_COPY_AND_ASSIGN(Target);
 };
 
diff --git a/tools/gn/target_generator.cc b/tools/gn/target_generator.cc
index 2fb178a..a763a31 100644
--- a/tools/gn/target_generator.cc
+++ b/tools/gn/target_generator.cc
@@ -39,7 +39,6 @@
   FillDependentConfigs();
   FillData();
   FillDependencies();
-  FillGypFile();
 
   // Do type-specific generation.
   DoRun();
@@ -173,17 +172,6 @@
   FillHardDep();
 }
 
-void TargetGenerator::FillGypFile() {
-  const Value* gyp_file_value = scope_->GetValue(variables::kGypFile, true);
-  if (!gyp_file_value)
-    return;
-  if (!gyp_file_value->VerifyTypeIs(Value::STRING, err_))
-    return;
-
-  target_->set_gyp_file(scope_->GetSourceDir().ResolveRelativeFile(
-      gyp_file_value->string_value()));
-}
-
 void TargetGenerator::FillHardDep() {
   const Value* hard_dep_value = scope_->GetValue(variables::kHardDep, true);
   if (!hard_dep_value)
@@ -193,15 +181,6 @@
   target_->set_hard_dep(hard_dep_value->boolean_value());
 }
 
-void TargetGenerator::FillExternal() {
-  const Value* value = scope_->GetValue(variables::kExternal, true);
-  if (!value)
-    return;
-  if (!value->VerifyTypeIs(Value::BOOLEAN, err_))
-    return;
-  target_->set_external(value->boolean_value());
-}
-
 void TargetGenerator::FillOutputs() {
   const Value* value = scope_->GetValue(variables::kOutputs, true);
   if (!value)
diff --git a/tools/gn/target_generator.h b/tools/gn/target_generator.h
index 6fa39b1..bcfc728 100644
--- a/tools/gn/target_generator.h
+++ b/tools/gn/target_generator.h
@@ -51,7 +51,6 @@
   void FillSources();
   void FillSourcePrereqs();
   void FillConfigs();
-  void FillExternal();
   void FillOutputs();
 
   Target* target_;
@@ -63,7 +62,6 @@
   void FillDependentConfigs();  // Includes all types of dependent configs.
   void FillData();
   void FillDependencies();  // Includes data dependencies.
-  void FillGypFile();
   void FillHardDep();
 
   // Reads configs/deps from the given var name, and uses the given setting on
diff --git a/tools/gn/template.cc b/tools/gn/template.cc
new file mode 100644
index 0000000..cae5e0c
--- /dev/null
+++ b/tools/gn/template.cc
@@ -0,0 +1,73 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tools/gn/template.h"
+
+#include "tools/gn/err.h"
+#include "tools/gn/functions.h"
+#include "tools/gn/parse_tree.h"
+#include "tools/gn/scope.h"
+#include "tools/gn/value.h"
+
+Template::Template(const Scope* scope, const FunctionCallNode* def)
+    : closure_(scope->MakeClosure()),
+      definition_(def) {
+}
+
+Template::Template(scoped_ptr<Scope> scope, const FunctionCallNode* def)
+    : closure_(scope.Pass()),
+      definition_(def) {
+}
+
+Template::~Template() {
+}
+
+scoped_ptr<Template> Template::Clone() const {
+  // We can make a new closure from our closure to copy it.
+  return scoped_ptr<Template>(
+      new Template(closure_->MakeClosure(), definition_));
+}
+
+Value Template::Invoke(Scope* scope,
+                       const FunctionCallNode* invocation,
+                       const std::vector<Value>& args,
+                       BlockNode* block,
+                       Err* err) const {
+  // Don't allow templates to be executed from imported files. Imports are for
+  // simple values only.
+  if (!EnsureNotProcessingImport(invocation, scope, err))
+    return Value();
+
+  // First run the invocation's block.
+  Scope invocation_scope(scope);
+  if (!FillTargetBlockScope(scope, invocation,
+                            invocation->function().value().as_string(),
+                            block, args, &invocation_scope, err))
+    return Value();
+  block->ExecuteBlockInScope(&invocation_scope, err);
+  if (err->has_error())
+    return Value();
+
+  // Set up the scope to run the template. This should be dependent on the
+  // closure, but have the "invoker" and "target_name" values injected, and the
+  // current dir matching the invoker.
+  Scope template_scope(closure_.get());
+  template_scope.SetValue("invoker", Value(NULL, &invocation_scope),
+                          invocation);
+  template_scope.set_source_dir(scope->GetSourceDir());
+
+  const base::StringPiece target_name("target_name");
+  template_scope.SetValue(target_name,
+                          Value(invocation, args[0].string_value()),
+                          invocation);
+
+  // Run the template code. Don't check for unused variables since the
+  // template could be executed in many different ways and it could be that
+  // not all executions use all values in the closure.
+  return definition_->block()->ExecuteBlockInScope(&template_scope, err);
+}
+
+LocationRange Template::GetDefinitionRange() const {
+  return definition_->GetRange();
+}
diff --git a/tools/gn/template.h b/tools/gn/template.h
new file mode 100644
index 0000000..0176862
--- /dev/null
+++ b/tools/gn/template.h
@@ -0,0 +1,53 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TOOLS_GN_TEMPLATE_H_
+#define TOOLS_GN_TEMPLATE_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+
+class BlockNode;
+class Err;
+class FunctionCallNode;
+class LocationRange;
+class Scope;
+class Value;
+
+class Template {
+ public:
+  // Makes a new closure based on the given scope.
+  Template(const Scope* scope, const FunctionCallNode* def);
+
+  // Takes ownership of a previously-constructed closure.
+  Template(scoped_ptr<Scope> closure, const FunctionCallNode* def);
+
+  ~Template();
+
+  // Makes a copy of this template.
+  scoped_ptr<Template> Clone() const;
+
+  // Invoke the template. The values correspond to the state of the code
+  // invoking the template.
+  Value Invoke(Scope* scope,
+               const FunctionCallNode* invocation,
+               const std::vector<Value>& args,
+               BlockNode* block,
+               Err* err) const;
+
+  // Returns the location range where this template was defined.
+  LocationRange GetDefinitionRange() const;
+
+ private:
+  Template();
+
+  scoped_ptr<Scope> closure_;
+  const FunctionCallNode* definition_;
+
+  DISALLOW_COPY_AND_ASSIGN(Template);
+};
+
+#endif  // TOOLS_GN_TEMPLATE_H_
diff --git a/tools/gn/token.cc b/tools/gn/token.cc
index ba59526..70ce2a1 100644
--- a/tools/gn/token.cc
+++ b/tools/gn/token.cc
@@ -6,25 +6,6 @@
 
 #include "base/logging.h"
 
-namespace {
-
-std::string UnescapeString(const base::StringPiece& input) {
-  std::string result;
-  result.reserve(input.size());
-
-  for (size_t i = 0; i < input.size(); i++) {
-    if (input[i] == '\\') {
-      DCHECK(i < input.size() - 1);  // Last char shouldn't be a backslash or
-                                     // it would have escaped the terminator.
-      i++;  // Skip backslash, next char is a literal.
-    }
-    result.push_back(input[i]);
-  }
-  return result;
-}
-
-}  // namespace
-
 Token::Token() : type_(INVALID), value_() {
 }
 
@@ -43,10 +24,3 @@
 bool Token::IsStringEqualTo(const char* v) const {
   return type_ == STRING && value_ == v;
 }
-
-std::string Token::StringValue() const {
-  DCHECK(type() == STRING);
-
-  // Trim off the string terminators at the end.
-  return UnescapeString(value_.substr(1, value_.size() - 2));
-}
diff --git a/tools/gn/token.h b/tools/gn/token.h
index 25f176b..8c7cd58 100644
--- a/tools/gn/token.h
+++ b/tools/gn/token.h
@@ -32,6 +32,7 @@
     BOOLEAN_AND,
     BOOLEAN_OR,
     BANG,
+    DOT,
 
     LEFT_PAREN,
     RIGHT_PAREN,
@@ -68,10 +69,6 @@
   bool IsIdentifierEqualTo(const char* v) const;
   bool IsStringEqualTo(const char* v) const;
 
-  // For STRING tokens, returns the string value (no quotes at end, does
-  // unescaping).
-  std::string StringValue() const;
-
  private:
   Type type_;
   base::StringPiece value_;
diff --git a/tools/gn/tokenizer.cc b/tools/gn/tokenizer.cc
index 8acabdb..36c9691 100644
--- a/tools/gn/tokenizer.cc
+++ b/tools/gn/tokenizer.cc
@@ -64,6 +64,8 @@
     return Token::BOOLEAN_OR;
   if (value == "!")
     return Token::BANG;
+  if (value == ".")
+    return Token::DOT;
   return Token::INVALID;
 }
 
@@ -196,6 +198,8 @@
   if (next_char == '}')
     return Token::RIGHT_BRACE;
 
+  if (next_char == '.')
+    return Token::DOT;
   if (next_char == ',')
     return Token::COMMA;
 
@@ -283,6 +287,7 @@
     case Token::RIGHT_BRACE:
     case Token::LEFT_PAREN:
     case Token::RIGHT_PAREN:
+    case Token::DOT:
     case Token::COMMA:
       Advance();  // All are one char.
       break;
diff --git a/tools/gn/tokenizer_unittest.cc b/tools/gn/tokenizer_unittest.cc
index b02db90..45fd744 100644
--- a/tools/gn/tokenizer_unittest.cc
+++ b/tools/gn/tokenizer_unittest.cc
@@ -99,8 +99,10 @@
     { Token::BANG, "!" },
     { Token::BOOLEAN_OR, "||" },
     { Token::BOOLEAN_AND, "&&" },
+    { Token::DOT, "." },
+    { Token::COMMA, "," },
   };
-  EXPECT_TRUE(CheckTokenizer("- + = += -= != ==  < > <= >= ! || &&",
+  EXPECT_TRUE(CheckTokenizer("- + = += -= != ==  < > <= >= ! || && . ,",
               operators));
 }
 
@@ -131,17 +133,6 @@
   EXPECT_TRUE(CheckTokenizer("fun(\"foo\") {\nfoo = 12}", fn));
 }
 
-TEST(Tokenizer, StringUnescaping) {
-  InputFile input(SourceFile("/test"));
-  input.SetContents("\"asd\\\"f\" \"\"");
-  Err err;
-  std::vector<Token> results = Tokenizer::Tokenize(&input, &err);
-
-  ASSERT_EQ(2u, results.size());
-  EXPECT_EQ("asd\"f", results[0].StringValue());
-  EXPECT_EQ("", results[1].StringValue());
-}
-
 TEST(Tokenizer, Locations) {
   InputFile input(SourceFile("/test"));
   input.SetContents("1 2 \"three\"\n  4");
diff --git a/tools/gn/toolchain.h b/tools/gn/toolchain.h
index 3b37a7a..eba396d 100644
--- a/tools/gn/toolchain.h
+++ b/tools/gn/toolchain.h
@@ -84,11 +84,6 @@
   const Tool& GetTool(ToolType type) const;
   void SetTool(ToolType type, const Tool& t);
 
-  // This extra stuff is specified by the build and will be added to the top
-  // of a generated GYP file (right after the opening "{").
-  std::string gyp_header() const { return gyp_header_; }
-  void set_gyp_header(const std::string& gh) { gyp_header_ = gh; }
-
   // Specifies build argument overrides that will be set on the base scope. It
   // will be as if these arguments were passed in on the command line. This
   // allows a toolchain to override the OS type of the default toolchain or
@@ -100,8 +95,6 @@
   Tool tools_[TYPE_NUMTYPES];
 
   Scope::KeyValueMap args_;
-
-  std::string gyp_header_;
 };
 
 #endif  // TOOLS_GN_TOOLCHAIN_H_
diff --git a/tools/gn/trace.cc b/tools/gn/trace.cc
index 26fb276..a2f34a3 100644
--- a/tools/gn/trace.cc
+++ b/tools/gn/trace.cc
@@ -24,9 +24,7 @@
   TraceLog() {
     events_.reserve(16384);
   }
-  ~TraceLog() {
-    // Trace items leanked intentionally.
-  }
+  // Trace items leaked intentionally.
 
   void Add(TraceItem* item) {
     base::AutoLock lock(lock_);
diff --git a/tools/gn/value.cc b/tools/gn/value.cc
index 659ebb9..6bf78da 100644
--- a/tools/gn/value.cc
+++ b/tools/gn/value.cc
@@ -10,6 +10,7 @@
     : type_(NONE),
       boolean_value_(false),
       int_value_(0),
+      scope_value_(NULL),
       origin_(NULL) {
 }
 
@@ -17,6 +18,7 @@
     : type_(t),
       boolean_value_(false),
       int_value_(0),
+      scope_value_(NULL),
       origin_(origin) {
 }
 
@@ -24,6 +26,7 @@
     : type_(BOOLEAN),
       boolean_value_(bool_val),
       int_value_(0),
+      scope_value_(NULL),
       origin_(origin) {
 }
 
@@ -31,6 +34,7 @@
     : type_(INTEGER),
       boolean_value_(false),
       int_value_(int_val),
+      scope_value_(NULL),
       origin_(origin) {
 }
 
@@ -39,6 +43,7 @@
       string_value_(),
       boolean_value_(false),
       int_value_(0),
+      scope_value_(NULL),
       origin_(origin) {
   string_value_.swap(str_val);
 }
@@ -48,6 +53,16 @@
       string_value_(str_val),
       boolean_value_(false),
       int_value_(0),
+      scope_value_(NULL),
+      origin_(origin) {
+}
+
+Value::Value(const ParseNode* origin, Scope* scope)
+    : type_(SCOPE),
+      string_value_(),
+      boolean_value_(false),
+      int_value_(0),
+      scope_value_(scope),
       origin_(origin) {
 }
 
@@ -75,6 +90,8 @@
       return "string";
     case LIST:
       return "list";
+    case SCOPE:
+      return "scope";
     default:
       NOTREACHED();
       return "UNKNOWN";
@@ -103,6 +120,8 @@
       result.push_back(']');
       return result;
     }
+    case SCOPE:
+      return std::string("<scope>");
   }
   return std::string();
 }
@@ -134,6 +153,10 @@
           return false;
       }
       return true;
+    case Value::SCOPE:
+      // Its not clear what people mean when comparing scope values, so we test
+      // for scope identity and not contents equality.
+      return scope_value() == other.scope_value();
     default:
       return false;
   }
diff --git a/tools/gn/value.h b/tools/gn/value.h
index 092b852..ee201c4 100644
--- a/tools/gn/value.h
+++ b/tools/gn/value.h
@@ -11,6 +11,7 @@
 #include "tools/gn/err.h"
 
 class ParseNode;
+class Scope;
 
 // Represents a variable value in the interpreter.
 class Value {
@@ -20,7 +21,8 @@
     BOOLEAN,
     INTEGER,
     STRING,
-    LIST
+    LIST,
+    SCOPE
   };
 
   Value();
@@ -29,6 +31,8 @@
   Value(const ParseNode* origin, int64 int_val);
   Value(const ParseNode* origin, std::string str_val);
   Value(const ParseNode* origin, const char* str_val);
+  Value(const ParseNode* origin, Scope* scope);  // Non-owning ptr.
+                                                 // (must outlive Value.)
   ~Value();
 
   Type type() const { return type_; }
@@ -80,6 +84,15 @@
     return list_value_;
   }
 
+  Scope* scope_value() {
+    DCHECK(type_ == SCOPE);
+    return scope_value_;
+  }
+  const Scope* scope_value() const {
+    DCHECK(type_ == SCOPE);
+    return scope_value_;
+  }
+
   // Converts the given value to a string. Returns true if strings should be
   // quoted or the ToString of a string should be the string itself.
   std::string ToString(bool quote_strings) const;
@@ -98,6 +111,8 @@
   bool boolean_value_;
   int64 int_value_;
   std::vector<Value> list_value_;
+  Scope* scope_value_;  // Non-owning.
+
   const ParseNode* origin_;
 };
 
diff --git a/tools/gn/variables.cc b/tools/gn/variables.cc
index 8fac840..be75593 100644
--- a/tools/gn/variables.cc
+++ b/tools/gn/variables.cc
@@ -466,24 +466,6 @@
     "\n"
     "  See also \"all_dependent_configs\".\n";
 
-const char kExternal[] = "external";
-const char kExternal_HelpShort[] =
-    "external: [boolean] Declares a target as externally generated.";
-const char kExternal_Help[] =
-    "external: Declares a target as externally generated.\n"
-    "\n"
-    "  External targets are treated like normal targets as far as dependent\n"
-    "  targets are concerned, but do not actually have their .ninja file\n"
-    "  written to disk. This allows them to be generated by an external\n"
-    "  program (e.g. GYP).\n"
-    "\n"
-    "  See also \"gn help gyp\".\n"
-    "\n"
-    "Example:\n"
-    "  static_library(\"foo\") {\n"
-    "    external = true\n"
-    "  }\n";
-
 const char kForwardDependentConfigsFrom[] = "forward_dependent_configs_from";
 const char kForwardDependentConfigsFrom_HelpShort[] =
     "forward_dependent_configs_from: [label list] Forward dependent's configs.";
@@ -523,31 +505,6 @@
     "      forward_dependent_configs_from = deps\n"
     "    }\n";
 
-const char kGypFile[] = "gyp_file";
-const char kGypFile_HelpShort[] =
-    "gyp_file: [file name] Name of GYP file to write to in GYP mode.";
-const char kGypFile_Help[] =
-    "gyp_file: Name of GYP file to write to in GYP mode.\n"
-    "\n"
-    "  See \"gn help gyp\" for an overview of how this works.\n"
-    "\n"
-    "  Tip: If all targets in a given BUILD.gn file should go in the same\n"
-    "  GYP file, just put gyp_file = \"foo\" at the top of the file and\n"
-    "  the variable will be in scope for all targets.\n";
-
-const char kGypHeader[] = "gyp_header";
-const char kGypHeader_HelpShort[] =
-    "gyp_header: [string] Extra stuff to prepend to GYP files.";
-const char kGypHeader_Help[] =
-    "gyp_header: Extra stuff to prepend to GYP files.\n"
-    "\n"
-    "  A Python dictionary string. This will be inserted after the initial\n"
-    "  \"{\" in the GYP file. It is expected this is used to define the\n"
-    "  make_global_settings.\n"
-    "\n"
-    "  This string should end in a comma to keep the python dictionary syntax\n"
-    "  valid when everything is concatenated.\n";
-
 const char kHardDep[] = "hard_dep";
 const char kHardDep_HelpShort[] =
     "hard_dep: [boolean] Indicates a target should be built before dependees.";
@@ -837,10 +794,7 @@
     INSERT_VARIABLE(Depfile)
     INSERT_VARIABLE(Deps)
     INSERT_VARIABLE(DirectDependentConfigs)
-    INSERT_VARIABLE(External)
     INSERT_VARIABLE(ForwardDependentConfigsFrom)
-    INSERT_VARIABLE(GypFile)
-    INSERT_VARIABLE(GypHeader)
     INSERT_VARIABLE(HardDep)
     INSERT_VARIABLE(IncludeDirs)
     INSERT_VARIABLE(Ldflags)
diff --git a/tools/gn/variables.h b/tools/gn/variables.h
index 94208db..85fbb96 100644
--- a/tools/gn/variables.h
+++ b/tools/gn/variables.h
@@ -123,22 +123,10 @@
 extern const char kDirectDependentConfigs_HelpShort[];
 extern const char kDirectDependentConfigs_Help[];
 
-extern const char kExternal[];
-extern const char kExternal_HelpShort[];
-extern const char kExternal_Help[];
-
 extern const char kForwardDependentConfigsFrom[];
 extern const char kForwardDependentConfigsFrom_HelpShort[];
 extern const char kForwardDependentConfigsFrom_Help[];
 
-extern const char kGypFile[];
-extern const char kGypFile_HelpShort[];
-extern const char kGypFile_Help[];
-
-extern const char kGypHeader[];
-extern const char kGypHeader_HelpShort[];
-extern const char kGypHeader_Help[];
-
 extern const char kHardDep[];
 extern const char kHardDep_HelpShort[];
 extern const char kHardDep_Help[];
diff --git a/tools/imagediff/image_diff_png.cc b/tools/imagediff/image_diff_png.cc
index a34a799..7524026 100644
--- a/tools/imagediff/image_diff_png.cc
+++ b/tools/imagediff/image_diff_png.cc
@@ -37,13 +37,6 @@
 
 // Represents a comment in the tEXt ancillary chunk of the png.
 struct Comment {
-  Comment(const std::string& k, const std::string& t)
-    : key(k), text(t) {
-  }
-
-  ~Comment() {
-  };
-
   std::string key;
   std::string text;
 };
diff --git a/tools/json_schema_compiler/api_gen_util.target.darwin-arm.mk b/tools/json_schema_compiler/api_gen_util.target.darwin-arm.mk
index 8d44a2b..107c6b1 100644
--- a/tools/json_schema_compiler/api_gen_util.target.darwin-arm.mk
+++ b/tools/json_schema_compiler/api_gen_util.target.darwin-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/tools/json_schema_compiler/api_gen_util.target.darwin-mips.mk b/tools/json_schema_compiler/api_gen_util.target.darwin-mips.mk
index 13d9c05..e0f74c0 100644
--- a/tools/json_schema_compiler/api_gen_util.target.darwin-mips.mk
+++ b/tools/json_schema_compiler/api_gen_util.target.darwin-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -160,6 +161,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/tools/json_schema_compiler/api_gen_util.target.darwin-x86.mk b/tools/json_schema_compiler/api_gen_util.target.darwin-x86.mk
index bd594f1..971c93e 100644
--- a/tools/json_schema_compiler/api_gen_util.target.darwin-x86.mk
+++ b/tools/json_schema_compiler/api_gen_util.target.darwin-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/tools/json_schema_compiler/api_gen_util.target.darwin-x86_64.mk b/tools/json_schema_compiler/api_gen_util.target.darwin-x86_64.mk
new file mode 100644
index 0000000..cb30d8d
--- /dev/null
+++ b/tools/json_schema_compiler/api_gen_util.target.darwin-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := tools_json_schema_compiler_api_gen_util_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	tools/json_schema_compiler/util.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: tools_json_schema_compiler_api_gen_util_gyp
+
+# Alias gyp target name.
+.PHONY: api_gen_util
+api_gen_util: tools_json_schema_compiler_api_gen_util_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/tools/json_schema_compiler/api_gen_util.target.linux-arm.mk b/tools/json_schema_compiler/api_gen_util.target.linux-arm.mk
index 8d44a2b..107c6b1 100644
--- a/tools/json_schema_compiler/api_gen_util.target.linux-arm.mk
+++ b/tools/json_schema_compiler/api_gen_util.target.linux-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/tools/json_schema_compiler/api_gen_util.target.linux-mips.mk b/tools/json_schema_compiler/api_gen_util.target.linux-mips.mk
index 13d9c05..e0f74c0 100644
--- a/tools/json_schema_compiler/api_gen_util.target.linux-mips.mk
+++ b/tools/json_schema_compiler/api_gen_util.target.linux-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -160,6 +161,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/tools/json_schema_compiler/api_gen_util.target.linux-x86.mk b/tools/json_schema_compiler/api_gen_util.target.linux-x86.mk
index bd594f1..971c93e 100644
--- a/tools/json_schema_compiler/api_gen_util.target.linux-x86.mk
+++ b/tools/json_schema_compiler/api_gen_util.target.linux-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/tools/json_schema_compiler/api_gen_util.target.linux-x86_64.mk b/tools/json_schema_compiler/api_gen_util.target.linux-x86_64.mk
new file mode 100644
index 0000000..cb30d8d
--- /dev/null
+++ b/tools/json_schema_compiler/api_gen_util.target.linux-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := tools_json_schema_compiler_api_gen_util_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	tools/json_schema_compiler/util.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: tools_json_schema_compiler_api_gen_util_gyp
+
+# Alias gyp target name.
+.PHONY: api_gen_util
+api_gen_util: tools_json_schema_compiler_api_gen_util_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/tools/lsan/suppressions.txt b/tools/lsan/suppressions.txt
index c2eb058..f4e8593 100644
--- a/tools/lsan/suppressions.txt
+++ b/tools/lsan/suppressions.txt
@@ -61,6 +61,12 @@
 leak:WebCore::*::*GetterCallback
 leak:WebCore::CSSComputedStyleDeclaration::create
 
+# crbug.com/358014
+leak:WebCore::V8PerIsolateData::ensureDomInJSContext
+
+# http://crbug.com/356785
+leak:content::RenderViewImplTest_DecideNavigationPolicyForWebUI_Test::TestBody
+
 #### Actual bugs in Chromium code ####
 # PLEASE DO NOT ADD SUPPRESSIONS FOR NEW LEAKS.
 # Instead, commits that introduce memory leaks should be reverted. Suppressing
@@ -94,4 +100,7 @@
 # http://crbug.com/322671
 leak:content::SpeechRecognitionBrowserTest::SetUpOnMainThread
 
+# http://crbug.com/355641
+leak:TrayAccessibilityTest
+
 # PLEASE READ ABOVE BEFORE ADDING NEW SUPPRESSIONS.
diff --git a/tools/memory_inspector/PRESUBMIT.py b/tools/memory_inspector/PRESUBMIT.py
index 9508ae6..7bfe22a 100644
--- a/tools/memory_inspector/PRESUBMIT.py
+++ b/tools/memory_inspector/PRESUBMIT.py
@@ -11,7 +11,9 @@
 
 def CommonChecks(input_api, output_api):
   output = []
-  output.extend(input_api.canned_checks.RunPylint(input_api, output_api))
+  blacklist = [r'classification_rules.*']
+  output.extend(input_api.canned_checks.RunPylint(
+      input_api, output_api, black_list=blacklist))
   output.extend(input_api.canned_checks.RunUnitTests(
       input_api,
       output_api,
diff --git a/tools/memory_inspector/classification_rules/default/mmap-android.py b/tools/memory_inspector/classification_rules/default/mmap-android.py
new file mode 100644
index 0000000..1a8d0d0
--- /dev/null
+++ b/tools/memory_inspector/classification_rules/default/mmap-android.py
@@ -0,0 +1,83 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is a generic rule-tree for classifying memory maps on Android. It is a
+# simple hierarchical python data structure (list of dictionaries). Some rules:
+# - Order matters: what is caught by a node is not caught by its siblings.
+# - Hierarchy matters: what is caught by a node is propagated to its children
+#   (if any). Only one of its children, though, will get the data.
+# - Non leaf nodes have an extra implicit node called {node-name}-other: if
+#   something is caught by a non leaf node, but none of its children, it is
+#   appended to implicit {node-name}-other catch-all children.
+#
+# See memory_inspector/classification/mmap_classifier.py for more docs.
+
+[
+{
+  'name': 'Anon',
+  'mmap_file': r'(^$)|(^\[)',
+  'children': [
+    {
+      'name': 'stack',
+      'mmap_file': r'\[stack',
+    },
+    {
+      'name': 'libc malloc',
+      'mmap_file': 'libc_malloc',
+    },
+    {
+      'name': 'JIT',
+      'mmap_prot': 'r.x',
+    },
+  ],
+},
+{
+  'name': 'Ashmem',
+  'mmap_file': r'^/dev/ashmem',
+  'children': [
+    {
+      'name': 'Dalvik',
+      'mmap_file': r'^/dev/ashmem/dalvik',
+      'children': [
+        {
+          'name': 'Java Heap',
+          'mmap_file': r'dalvik-heap',
+        },
+        {
+          'name': 'JIT',
+          'mmap_prot': 'r.x',
+        },
+      ],
+    },
+  ],
+},
+{
+  'name': 'Libs',
+  'mmap_file': r'(\.so)|(\.apk)|(\.jar)',
+  'children': [
+    {
+      'name': 'Native',
+      'mmap_file': r'\.so',
+    },
+    {
+      'name': 'APKs',
+      'mmap_file': r'\.apk',
+    },
+    {
+      'name': 'JARs',
+      'mmap_file': r'\.jar',
+    },
+  ],
+},
+{
+  'name': 'Devices',
+  'mmap_file': r'^/dev/',
+  'children': [
+    {
+      'name': 'GPU',
+      'mmap_file': r'(nv)|(mali)',
+    },
+  ],
+},
+]
diff --git a/tools/memory_inspector/memory_inspector/data/serialization.py b/tools/memory_inspector/memory_inspector/data/serialization.py
index d842228..b28b6c7 100644
--- a/tools/memory_inspector/memory_inspector/data/serialization.py
+++ b/tools/memory_inspector/memory_inspector/data/serialization.py
@@ -14,6 +14,7 @@
 
 import json
 
+from memory_inspector.classification import results
 from memory_inspector.core import backends
 from memory_inspector.core import memory_map
 from memory_inspector.core import native_heap
@@ -59,6 +60,12 @@
     if isinstance(obj, (backends.DeviceStats, backends.ProcessStats)):
       return obj.__dict__
 
+    if isinstance(obj, results.AggreatedResults):
+      return {'keys': obj.keys, 'buckets': obj.total}
+
+    if isinstance(obj, results.Bucket):
+      return {obj.rule.name : {'values': obj.values, 'children': obj.children}}
+
     return json.JSONEncoder.default(self, obj)
 
 
diff --git a/tools/memory_inspector/memory_inspector/frontends/background_tasks.py b/tools/memory_inspector/memory_inspector/frontends/background_tasks.py
new file mode 100644
index 0000000..09323ba
--- /dev/null
+++ b/tools/memory_inspector/memory_inspector/frontends/background_tasks.py
@@ -0,0 +1,125 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Background tasks for the www_server module.
+
+This module has the logic for handling background tasks for the www frontend.
+Long term actions (like periodic tracing), cannot be served synchronously in the
+context of a /ajax/endpoint request (would timeout HTTP). Instead, for such long
+operations, an instance of |BackgroundTask| is created here and the server
+returns just its id. The client can later poll the status of the asynchronous
+task to check for its progress.
+
+From a technical viewpoint, each background task is just a python subprocess
+which communicates its progress updates through a Queue. The messages enqueued
+are tuples with the following format: (completion_ratio%, 'message string').
+"""
+
+import datetime
+import multiprocessing
+import Queue
+import time
+
+from memory_inspector.core import backends
+from memory_inspector.data import file_storage
+
+
+_tasks = {}  #id (int) -> |BackgroundTask| instance.
+
+
+def StartTracer(process, storage_path, interval, count, trace_native_heap):
+  assert(isinstance(process, backends.Process))
+  task = BackgroundTask(
+      TracerMain_,
+      storage_path=storage_path,
+      backend_name=process.device.backend.name,
+      device_id=process.device.id,
+      pid=process.pid,
+      interval=interval,
+      count=count,
+      trace_native_heap=trace_native_heap)
+  task.start()
+  _tasks[task.pid] = task
+  return task.pid
+
+
+def Get(task_id):
+  return _tasks.get(task_id)
+
+
+def TerminateAll():
+  for proc in _tasks.itervalues():
+    if proc.is_alive():
+      proc.terminate()
+  _tasks.clear()
+
+
+def TracerMain_(log, storage_path, backend_name, device_id, pid, interval,
+    count, trace_native_heap):
+  """Entry point for the background periodic tracer task."""
+  # Initialize storage.
+  storage = file_storage.Storage(storage_path)
+
+  # Initialize the backend.
+  backend = backends.GetBackend(backend_name)
+  for k, v in storage.LoadSettings(backend_name).iteritems():
+    backend.settings[k] = v
+
+  # Initialize the device.
+  device = backends.GetDevice(backend_name, device_id)
+  for k, v in storage.LoadSettings(device_id).iteritems():
+    device.settings[k] = v
+
+  # Start periodic tracing.
+  process = device.GetProcess(pid)
+  log.put((1, 'Starting trace (%d dumps x %s s.). Device: %s, process: %s' % (
+      count, interval, device.name, process.name)))
+  datetime_str = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M')
+  archive_name = '%s - %s - %s' % (datetime_str, device.name, process.name)
+  archive = storage.OpenArchive(archive_name, create=True)
+
+  for i in xrange(1, count + 1):  # [1, count] range is easier to handle.
+    process = device.GetProcess(pid)
+    if not process:
+      log.put((100, 'Process %d died.' % pid))
+      return 1
+    # Calculate the completion rate proportionally to 80%. We keep the remaining
+    # 20% for the final symbolization step (just an approximate estimation).
+    completion = 80 * i / count
+    log.put((completion, 'Dumping trace %d of %d' % (i, count)))
+    archive.StartNewSnapshot()
+    mmaps = process.DumpMemoryMaps()
+    log.put((completion, 'Dumped %d memory maps' % len(mmaps)))
+    archive.StoreMemMaps(mmaps)
+    if trace_native_heap:
+      nheap = process.DumpNativeHeap()
+      log.put((completion, 'Dumped %d native allocs' % len(nheap.allocations)))
+      archive.StoreNativeHeap(nheap)
+
+    if i < count:
+      time.sleep(interval)
+
+  log.put((100, 'Trace complete.'))
+  return 0
+
+
+class BackgroundTask(multiprocessing.Process):
+  def __init__(self, entry_point, *args, **kwargs):
+    self._log_queue = multiprocessing.Queue()
+    self._progress_log = []  # A list of tuples [(50%, 'msg1'), (100%, 'msg2')].
+    super(BackgroundTask, self).__init__(
+        target=entry_point,
+        args=((self._log_queue,) + args),  # Just propagate all args.
+        kwargs=kwargs)
+
+  def GetProgress(self):
+    """ Returns a tuple (completion_rate, message). """
+    while True:
+      try:
+        self._progress_log += [self._log_queue.get(block=False)]
+      except Queue.Empty:
+        break
+    if not self.is_alive() and self.exitcode != 0:
+      return self._progress_log + [(100, 'Failed with code %d' % self.exitcode)]
+    return self._progress_log
\ No newline at end of file
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/css/processes.css b/tools/memory_inspector/memory_inspector/frontends/www_content/css/processes.css
index a95713e..f8d99b2 100644
--- a/tools/memory_inspector/memory_inspector/frontends/www_content/css/processes.css
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/css/processes.css
@@ -9,4 +9,10 @@
   margin: 0;
   display: inline-block;
   height: 20em;
+}
+
+#ps-tracer-dialog > div {
+  clear: both;
+  font-size: 0.9em;
+  margin-bottom: 1em;
 }
\ No newline at end of file
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/css/profiler.css b/tools/memory_inspector/memory_inspector/frontends/www_content/css/profiler.css
new file mode 100644
index 0000000..51859c9
--- /dev/null
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/css/profiler.css
@@ -0,0 +1,22 @@
+/* Copyright 2014 The Chromium Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+#prof-options > span {
+  margin-right: 0.5em;
+}
+
+#prof-time {
+  display: inline-block;
+  width: 15em;
+  margin: 0 1em;
+}
+
+#prof-tree_chart dt {
+  display: block;
+  font-weight: bold;
+}
+
+#prof-time_chart {
+  min-height: 20em;
+}
\ No newline at end of file
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/index.html b/tools/memory_inspector/memory_inspector/frontends/www_content/index.html
index 2c9e880..e1df30c 100644
--- a/tools/memory_inspector/memory_inspector/frontends/www_content/index.html
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/index.html
@@ -12,6 +12,7 @@
   <link href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/flick/jquery-ui.css" rel="stylesheet">
   <link href="/css/mmap.css" rel="stylesheet" type="text/css">
   <link href="/css/processes.css" rel="stylesheet" type="text/css">
+  <link href="/css/profiler.css" rel="stylesheet" type="text/css">
   <link href="/css/rootUi.css" rel="stylesheet" type="text/css">
   <link href="/css/settings.css" rel="stylesheet" type="text/css">
   <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
@@ -24,8 +25,10 @@
   <script src="/js/devices.js"></script>
   <script src="/js/mmap.js"></script>
   <script src="/js/processes.js"></script>
+  <script src="/js/profiler.js"></script>
   <script src="/js/rootUi.js"></script>
   <script src="/js/settings.js"></script>
+  <script src="/js/storage.js"></script>
   <script src="/js/timers.js"></script>
   <script src="/js/webservice.js"></script>
 </head>
@@ -64,15 +67,49 @@
 
         <div id="ps-table-wrapper">
           <div id="ps-toolbar" class="ui-widget-header ui-corner-all">
+            <button id="ps-quick_snapshot">Quick snapshot</button>
             <button id="ps-dump_mmaps">Dump mmaps</button>
+            <button id="ps-full_profile">Full profile</button>
             <input type="checkbox" id="ps-show_all">
             <label for="ps-show_all">Show all processes</label>
           </div>
           <div id="ps-table"></div>
         </div>
+
+        <div id="ps-tracer-dialog" title="Trace process">
+          <div>
+            <label for="ps-tracer-process">Process</label>
+            <input type="text" id="ps-tracer-process" readonly class="text ui-widget-content">
+          </div>
+          <div>
+            <label for="ps-tracer-period">Period [s.]</label>
+            <input type="text" id="ps-tracer-period" value="20">
+          </div>
+          <div>
+            <label for="ps-tracer-snapshots">Num snapshots</label>
+            <input type="text" id="ps-tracer-snapshots" value="1">
+          </div>
+        </div>
       </div>
 
       <div id="tabs-prof">
+        <header id="prof-options">
+          <span>
+            Rules:
+            <select id="prof-ruleset"></select>
+          </span>
+          <span>
+            Metric:
+            <select id="prof-metric"></select>
+          </span>
+          <span>
+            Snapshot:
+            <div id="prof-time"></div>
+            T = <span id="prof-time_label">0</span> s.
+          </span>
+        </header>
+        <div id="prof-tree_chart"></div>
+        <div id="prof-time_chart"></div>
       </div>
 
       <div id="tabs-mm">
@@ -123,6 +160,13 @@
       </div>
 
       <div id="tabs-storage">
+        <div id="storage-toolbar" class="ui-widget-header ui-corner-all">
+          <label>Group:</label>
+          <button id="storage-profile-mmaps">Profile memory maps</button>
+          <label>Single snapshot:</label>
+          <button id="storage-dump-mmaps">Show memory maps</button>
+        </div>
+        <div id="storage-table"></div>
       </div>
 
       <div id="tabs-settings">
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js
index ff2ae18..9d3ac04 100644
--- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/devices.js
@@ -18,6 +18,12 @@
   return this.selDeviceUri_;
 };
 
+this.getSelectedDevice = function() {
+  if (!this.selDeviceUri_)
+    return null;
+  return this.devices_[this.selDeviceUri_];
+};
+
 this.getAllBackends = function() {
   // Returns a list of the registered backends, e.g., ['Android', 'Linux'].
   return this.backends_;
@@ -69,9 +75,12 @@
   if (!this.selDeviceUri_)
     return;
 
-  // Initialize device and start processes / OS stats.
-  webservice.ajaxRequest('/initialize/' + this.selDeviceUri_,
-                         this.onDeviceInitializationComplete_.bind(this));
+  // Initialize device and start processes / OS stats (it is a POST request).
+  webservice.ajaxRequest(
+      '/initialize/' + this.selDeviceUri_,
+      this.onDeviceInitializationComplete_.bind(this),
+      null,  // default error handler.
+      {});
 };
 
 this.onDeviceInitializationComplete_ = function() {
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/mmap.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/mmap.js
index a9d53f0..5113fc1 100644
--- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/mmap.js
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/mmap.js
@@ -20,6 +20,7 @@
 this.mapsData_ = null;
 this.mapsTable_ = null;
 this.mapsFilter_ = null;
+this.shouldUpdateProfileAfterDump_ = false;
 
 this.onDomReady_ = function() {
   $('#mm-lookup-addr').on('change', this.lookupAddress.bind(this));
@@ -34,22 +35,32 @@
   $('#mm-table').on('dblclick', this.onMmapTableDblClick_.bind(this));
 };
 
-this.dumpMmaps = function(targetProcUri) {
+this.dumpMmaps = function(targetProcUri, updateProfile) {
   if (!targetProcUri)
     return;
+  this.shouldUpdateProfileAfterDump_ = !!updateProfile;
   webservice.ajaxRequest('/dump/mmap/' + targetProcUri,
                          this.onDumpAjaxResponse_.bind(this));
   rootUi.showDialog('Dumping memory maps for ' + targetProcUri + '...');
 };
 
+this.dumpMmapsFromStorage = function(archiveName, snapshot) {
+  webservice.ajaxRequest('/storage/' + archiveName + '/' + snapshot + '/mmaps',
+                         this.onDumpAjaxResponse_.bind(this));
+  rootUi.showDialog('Loading memory maps from archive ...');
+};
+
 this.onDumpAjaxResponse_ = function(data) {
   $('#mm-filter-file').val('');
   $('#mm-filter-prot').val('');
-  this.mapsData_ = new google.visualization.DataTable(data);
+  this.mapsData_ = new google.visualization.DataTable(data.table);
   this.mapsFilter_ = new google.visualization.DataView(this.mapsData_);
   this.mapsFilter_.setColumns(this.SHOW_COLUMNS);
   this.applyMapsTableFilters_();
   rootUi.hideDialog();
+  if (this.shouldUpdateProfileAfterDump_)
+    profiler.profileCachedMmapDump(data.id);
+  shouldUpdateProfileAfterDump_ = false;
 };
 
 this.applyMapsTableFilters_ = function() {
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js
index 343857f..4c38c03 100644
--- a/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/processes.js
@@ -7,6 +7,7 @@
 this.PS_INTERVAL_SEC_ = 2;
 this.DEV_STATS_INTERVAL_SEC_ = 2;
 this.PROC_STATS_INTERVAL_SEC_ = 1;
+this.TRACER_POLL_INTERVAL_SEC_ = 2;
 
 this.selProcUri_ = null;
 this.selProcName_ = null;
@@ -20,6 +21,7 @@
 this.procCpuChartData_ = null;
 this.procMemChart_ = null;
 this.procMemChartData_ = null;
+this.tracerTaskId_ = null;
 
 this.onDomReady_ = function() {
   $('#device_tabs').tabs();
@@ -27,13 +29,24 @@
   $('#device_tabs').on('tabsactivate', this.redrawDevStats_.bind(this));
 
   // Initialize the toolbar.
+  $('#ps-quick_snapshot').button({icons:{primary: 'ui-icon-image'}})
+      .click(this.snapshotSelectedProcess_.bind(this));
   $('#ps-dump_mmaps').button({icons:{primary: 'ui-icon-calculator'}})
       .click(this.dumpSelectedProcessMmaps_.bind(this));
+  $('#ps-full_profile').button({icons:{primary: 'ui-icon-clock'}})
+      .click(this.showTracingDialog_.bind(this));
+
+  // Set-up the tracer dialog.
+  $('#ps-tracer-dialog').dialog({autoOpen: false, modal: true, width: 400,
+      buttons: {'Start': this.startTracingSelectedProcess_.bind(this)}});
+  $('#ps-tracer-period').spinner({min: 0, step: 20});
+  $('#ps-tracer-snapshots').spinner({min: 1, max: 100});
 
   // Create the process table.
   this.psTable_ = new google.visualization.Table($('#ps-table')[0]);
   google.visualization.events.addListener(
       this.psTable_, 'select', this.onPsTableRowSelect_.bind(this));
+  $('#ps-table').on('dblclick', this.snapshotSelectedProcess_.bind(this));
 
   // Create the device stats charts.
   this.memChart_ = new google.visualization.PieChart($('#os-mem_chart')[0]);
@@ -50,6 +63,13 @@
   return this.selProcUri_;
 };
 
+this.snapshotSelectedProcess_ = function() {
+  if (!this.selProcUri_)
+    return alert('Must select a process!');
+  mmap.dumpMmaps(this.selProcUri_, true);
+  rootUi.showTab('prof');
+};
+
 this.dumpSelectedProcessMmaps_ = function() {
   if (!this.selProcUri_)
     return alert('Must select a process!');
@@ -57,6 +77,61 @@
   rootUi.showTab('mm');
 };
 
+this.showTracingDialog_ = function() {
+  if (!this.selProcUri_)
+    return alert('Must select a process!');
+  $('#ps-tracer-process').val(this.selProcName_);
+  $('#ps-tracer-dialog').dialog('open');
+};
+
+this.startTracingSelectedProcess_ = function() {
+  if (!this.selProcUri_)
+    return alert('The process ' + this.selProcUri_ + ' died.');
+
+  $('#ps-tracer-dialog').dialog('close');
+
+  var postArgs = {interval: $('#ps-tracer-period').val(),
+                  count: $('#ps-tracer-snapshots').val(),
+                  traceNativeHeap: false};
+
+  webservice.ajaxRequest('/tracer/start/' + this.selProcUri_,
+                         this.onStartTracerAjaxResponse_.bind(this),
+                         null,  // Use default error handler
+                         postArgs);
+};
+
+this.onStartTracerAjaxResponse_ = function(data) {
+  this.tracerTaskId_ = data;
+  timers.start('tracer',
+               this.pollTracerStatus_.bind(this),
+               this.TRACER_POLL_INTERVAL_SEC_);
+};
+
+this.pollTracerStatus_ = function() {
+  if (!this.tracerTaskId_) {
+    timers.stop('tracer');
+    return;
+  }
+  webservice.ajaxRequest('/tracer/status/' + this.tracerTaskId_,
+                         this.onTracerStatusAjaxResponse_.bind(this));
+};
+
+this.onTracerStatusAjaxResponse_ = function(data) {
+  var logMessages = '';
+  var completionRate = 0;
+  data.forEach(function(progress) {
+    completionRate = progress[0];
+    logMessages += '\n' + progress[1];
+  }, this);
+  rootUi.setProgress(completionRate);
+  rootUi.setStatusMessage(logMessages);
+
+  if (completionRate >= 100) {
+    tracerTaskId_ = null;
+    timers.stop('tracer');
+  }
+};
+
 this.refreshPsTable = function() {
   var targetDevUri = devices.getSelectedURI();
   if (!targetDevUri)
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/profiler.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/profiler.js
new file mode 100644
index 0000000..ea8841d
--- /dev/null
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/profiler.js
@@ -0,0 +1,180 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This module handles the UI for the profiling. A memory profile is obtained
+// asking the webservice to profile some data sources (through /profile/create)
+// as, for instance, some mmaps dumps or some heap traces.
+// Regardless of the data source, a profile consists of three main concepts:
+// 1. A tree of buckets, each one having a name and a set of 1+ values (see
+//    /classification/rules.py,results.py), one value per metric (see below).
+// 2. A set of snapshots, identifying the times when the dump was taken. All the
+//    snapshots have the same shape and the same nodes (but their values can
+//    obviously differ).
+// 3. A set of metrics, identifying the cardinality (how many) and the semantic
+//    (what do they mean) of the values of the nodes in the results tree.
+//
+// From a graphical viewpoint a profile is displayed using two charts:
+// - A tree (organizational) chart which shows, for a given snapshot and metric,
+//   the taxonomy of the buckets and their corresponding value.
+// - A time series (scattered area) chart which shows, for a given metric and a
+//   given bucket, its evolution over time (and of its direct children).
+
+profiler = new (function() {
+
+this.treeData_ = null;
+this.treeChart_ = null;
+this.timeSeriesData_ = null;
+this.timeSeriesChart_ = null;
+this.isRedrawing_ = false;
+this.profileId_ = null;  // The profile id retrieved on /ajax/profile/create.
+this.times_ = [];  // Snapshot times: [0,4,8] -> 3 snapshots x 4 sec.
+this.metrics_ = [];  // Keys in the result tree, e.g., ['RSS', 'PSS'].
+this.curTime_ = null;  // Time of the snapshot currently displayed.
+this.curMetric_ = null;  // Index (rel. to |metrics_|) currently displayed.
+this.curBucket_ = null;  // Index (rel. to the tree) currently displayed.
+
+this.onDomReady_ = function() {
+  this.treeChart_ = new google.visualization.OrgChart($('#prof-tree_chart')[0]);
+  this.timeSeriesChart_ = new google.visualization.SteppedAreaChart(
+      $('#prof-time_chart')[0]);
+
+  // TODO(primiano): De-hardcodify the ruleset and list/load from the server.
+  $('#prof-ruleset').append(
+      $('<option>').val('default/mmap-android.py').text('mmap-Android'));
+
+  // Setup the UI event listeners to trigger the onUiParamsChange_ event.
+  google.visualization.events.addListener(this.treeChart_, 'select',
+                                          this.onUiParamsChange_.bind(this));
+  $('#prof-metric').on('change', this.onUiParamsChange_.bind(this));
+  $('#prof-time').slider({range: 'max', min: 0, max: 0, value: 0,
+                          change: this.onUiParamsChange_.bind(this)});
+};
+
+this.profileCachedMmapDump = function(mmapDumpId) {
+  // Creates a profile using the data grabbed during a recent mmap dump.
+  // This is used to get a quick overview (only one snapshot), of the memory
+  // without doing a full periodic trace first.
+  webservice.ajaxRequest('/profile/create',  // This is a POST request.
+                         this.onProfileAjaxResponse_.bind(this),
+                         null,  // use the default error handler.
+                         {type: 'mmap',
+                          source: 'cache',
+                          id: mmapDumpId,
+                          ruleset: $('#prof-ruleset').val()});
+};
+
+this.profileArchivedMmaps = function(archiveName, snapshots) {
+  // Creates a profile using the data from the storage.
+  webservice.ajaxRequest('/profile/create',  // This is a POST request.
+                         this.onProfileAjaxResponse_.bind(this),
+                         null,  // use the default error handler.
+                         {type: 'mmap',
+                          source: 'archive',
+                          archive: archiveName,
+                          snapshots: snapshots,
+                          ruleset: $('#prof-ruleset').val()});
+};
+
+this.onProfileAjaxResponse_ = function(data) {
+  // This AJAX response contains a summary of the profile requested via the
+  // /profile endpoint, which consists of:
+  // - The number of snapshots (and their corresponding time) in an array.
+  //   e.g., [0, 3 ,6] indicates that the profile contains three snapshots taken
+  //   respectively at T=0, T=3 and T=6 sec.
+  // - A list of profile metrics, e.g., ['RSS', 'P. Dirty'] indicates that every
+  //   node in the result tree is a 2-tuple.
+  // After this response, the concrete data for the charts can be fetched using
+  // the /ajax/profile/{ID}/tree and /ajax/profile/{ID}/time_serie endpoints.
+  this.profileId_ = data.id;
+  this.times_ = data.times;  // An array of integers.
+  this.metrics_ = data.metrics;  // An array of strings.
+  this.curBucket_ = data.rootBucket;  // URI of the bucket, e.g., Total/Libs/.
+  this.curTime_ = data.times[0];
+  this.curMetric_ = 0;
+
+  // Populate the "metrics" select box.
+  $('#prof-metric').empty();
+  this.metrics_.forEach(function(metric) {
+    $('#prof-metric').append($('<option/>').text(metric));
+  }, this);
+
+  // Setup the bounds of the snapshots slider.
+  $('#prof-time').slider('option', 'max', this.times_.length - 1);
+
+  // Fetch the actual chart data (via /profile/{ID}/...) and redraw the charts.
+  this.updateCharts();
+};
+
+this.onUiParamsChange_ = function() {
+  // Triggered whenever any of the UI params (the metric select, the snapshot
+  // slider or the selected bucket in the tree) changes.
+  this.curMetric_ = $('#prof-metric').prop('selectedIndex');
+  this.curTime_ = this.times_[$('#prof-time').slider('value')];
+  $('#prof-time_label').text(this.curTime_);
+  var selBucket = this.treeChart_.getSelection();
+  if (selBucket.length)
+    this.curBucket_ = this.treeData_.getValue(selBucket[0].row, 0);
+  this.updateCharts();
+};
+
+this.updateCharts = function() {
+  if (!this.profileId_)
+    return;
+
+  var profileUri = '/profile/' + this.profileId_;
+  webservice.ajaxRequest(
+      profileUri +'/tree/' + this.curMetric_ + '/' + this.curTime_,
+      this.onTreeAjaxResponse_.bind(this));
+  webservice.ajaxRequest(
+      profileUri +'/time_serie/' + this.curMetric_ + '/' + this.curBucket_,
+      this.onTimeSerieAjaxResponse_.bind(this));
+};
+
+this.onTreeAjaxResponse_ = function(data) {
+  this.treeData_ = new google.visualization.DataTable(data);
+  this.redrawTree_();
+};
+
+this.onTimeSerieAjaxResponse_ = function(data) {
+  this.timeSeriesData_ = new google.visualization.DataTable(data);
+  this.redrawTimeSerie_();
+};
+
+this.redrawTree_ = function() {
+  // isRedrawing_ is used here to break the avalanche chain that would be caused
+  // by redraw changing the node selection, triggering in turn another redraw.
+  if (!this.treeData_ || this.isRedrawing_)
+    return;
+
+  this.isRedrawing_ = true;
+  var savedSelection = this.treeChart_.getSelection();
+  this.treeChart_.draw(this.treeData_, {allowHtml: true});
+
+  // "If we want things to stay as they are, things will have to change."
+  // (work around GChart bug, as if we didn't have enough problems on our own).
+  this.treeChart_.setSelection([{row: null, column: null}]);
+  this.treeChart_.setSelection(savedSelection);
+  this.isRedrawing_ = false;
+};
+
+this.redrawTimeSerie_ = function() {
+  if (!this.timeSeriesData_)
+    return;
+
+  var metric = this.metrics_[this.curMetric_];
+  this.timeSeriesChart_.draw(this.timeSeriesData_, {
+      title: metric + ' over time for ' + this.curBucket_,
+      isStacked: true,
+      hAxis: {title: 'Time [sec.]'},
+      vAxis: {title: this.metrics_[this.curMetric_] + ' [KB]'}});
+};
+
+this.redraw = function() {
+  this.redrawTree_();
+  this.redrawTimeSerie_();
+};
+
+$(document).ready(this.onDomReady_.bind(this));
+
+})();
\ No newline at end of file
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_content/js/storage.js b/tools/memory_inspector/memory_inspector/frontends/www_content/js/storage.js
new file mode 100644
index 0000000..f67af86
--- /dev/null
+++ b/tools/memory_inspector/memory_inspector/frontends/www_content/js/storage.js
@@ -0,0 +1,79 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+storage = new (function() {
+
+this.table_ = null;
+this.tableData_ = null;
+
+this.onDomReady_ = function() {
+  // Initialize the toolbar.
+  $('#storage-profile-mmaps').button({icons:{primary: 'ui-icon-image'}})
+      .click(this.profileMmapForSelectedSnapshots.bind(this));
+  $('#storage-dump-mmaps').button({icons:{primary: 'ui-icon-calculator'}})
+      .click(this.dumpMmapForSelectedSnapshot_.bind(this));
+  $('#storage-profile-native').button({icons:{primary: 'ui-icon-image'}})
+      .click(this.profileNativeForSelectedSnapshots.bind(this));
+
+  // Create the table.
+  this.table_ = new google.visualization.Table($('#storage-table')[0]);
+};
+
+this.reload = function() {
+  webservice.ajaxRequest('/storage/list', this.onListAjaxResponse_.bind(this));
+}
+
+this.onListAjaxResponse_ = function(data) {
+  this.tableData_ = new google.visualization.DataTable(data);
+  this.redraw();
+};
+
+this.profileMmapForSelectedSnapshots = function() {
+  // Generates a mmap profile for the selected snapshots.
+  var sel = this.table_.getSelection();
+  if (!sel.length || !this.tableData_)
+    return;
+  var archiveName = null;
+  var snapshots = [];
+
+  for (var i = 0; i < sel.length; ++i) {
+    var row = sel[i].row;
+    var curArchive = this.tableData_.getValue(row, 0);
+    if (archiveName && curArchive != archiveName){
+      alert('All the selected snapshots must belong to the same archive!');
+      return;
+    }
+    archiveName = curArchive;
+    snapshots.push(this.tableData_.getValue(row, 1));
+  }
+  profiler.profileArchivedMmaps(archiveName, snapshots);
+  rootUi.showTab('prof');
+};
+
+this.dumpMmapForSelectedSnapshot_ = function() {
+  var sel = this.table_.getSelection();
+  if (sel.length != 1) {
+    alert('Please select only one snapshot.')
+    return;
+  }
+
+  var row = sel[0].row;
+  mmap.dumpMmapsFromStorage(this.tableData_.getValue(row, 0),
+                            this.tableData_.getValue(row, 1))
+  rootUi.showTab('mm');
+};
+
+this.profileNativeForSelectedSnapshots = function() {
+
+};
+
+this.redraw = function() {
+  if (!this.tableData_)
+    return;
+  this.table_.draw(this.tableData_);
+};
+
+$(document).ready(this.onDomReady_.bind(this));
+
+})();
\ No newline at end of file
diff --git a/tools/memory_inspector/memory_inspector/frontends/www_server.py b/tools/memory_inspector/memory_inspector/frontends/www_server.py
index 9d3ce36..d1a54ae 100644
--- a/tools/memory_inspector/memory_inspector/frontends/www_server.py
+++ b/tools/memory_inspector/memory_inspector/frontends/www_server.py
@@ -20,16 +20,22 @@
 
 import collections
 import datetime
+import dateutil.parser
 import os
+import memory_inspector
 import mimetypes
 import json
 import re
 import urlparse
+import uuid
 import wsgiref.simple_server
 
 from memory_inspector.core import backends
+from memory_inspector.core import memory_map
+from memory_inspector.classification import mmap_classifier
 from memory_inspector.data import serialization
 from memory_inspector.data import file_storage
+from memory_inspector.frontends import background_tasks
 
 
 _HTTP_OK = '200 - OK'
@@ -41,7 +47,11 @@
     os.path.dirname(__file__), 'www_content'))
 _APP_PROCESS_RE = r'^[\w.:]+$'  # Regex for matching app processes.
 _STATS_HIST_SIZE = 120  # Keep at most 120 samples of stats per process.
+_CACHE_LEN = 10  # Max length of |_cached_objs|.
 
+# |_cached_objs| keeps the state of short-lived objects that the client needs to
+# _cached_objs subsequent AJAX calls.
+_cached_objs = collections.OrderedDict()
 _persistent_storage = file_storage.Storage(_PERSISTENT_STORAGE_PATH)
 _proc_stats_history = {}  # /Android/device/PID -> deque([stats@T=0, stats@T=1])
 
@@ -131,39 +141,14 @@
   if not process:
     return _HTTP_GONE, [], 'Device not found or process died'
   mmap = process.DumpMemoryMaps()
-  resp = {
-      'cols': [
-          {'label': 'Start', 'type':'string'},
-          {'label': 'End', 'type':'string'},
-          {'label': 'Length Kb', 'type':'number'},
-          {'label': 'Prot', 'type':'string'},
-          {'label': 'Priv. Dirty Kb', 'type':'number'},
-          {'label': 'Priv. Clean Kb', 'type':'number'},
-          {'label': 'Shared Dirty Kb', 'type':'number'},
-          {'label': 'Shared Clean Kb', 'type':'number'},
-          {'label': 'File', 'type':'string'},
-          {'label': 'Offset', 'type':'number'},
-          {'label': 'Resident Pages', 'type':'string'},
-        ],
-      'rows': []}
-  for entry in mmap.entries:
-    resp['rows'] += [{'c': [
-        {'v': '%08x' % entry.start, 'f': None},
-        {'v': '%08x' % entry.end, 'f': None},
-        {'v': entry.len / 1024, 'f': None},
-        {'v': entry.prot_flags, 'f': None},
-        {'v': entry.priv_dirty_bytes / 1024, 'f': None},
-        {'v': entry.priv_clean_bytes / 1024, 'f': None},
-        {'v': entry.shared_dirty_bytes / 1024, 'f': None},
-        {'v': entry.shared_clean_bytes / 1024, 'f': None},
-        {'v': entry.mapped_file, 'f': None},
-        {'v': entry.mapped_offset, 'f': None},
-        {'v': '[%s]' % (','.join(map(str, entry.resident_pages))), 'f': None},
-    ]}]
-  return _HTTP_OK, [], resp
+  table = _ConvertMmapToGTable(mmap)
+
+  # Store the dump in the cache. The client might need it later for profiling.
+  cache_id = _CacheObject(mmap)
+  return _HTTP_OK, [], {'table': table, 'id': cache_id}
 
 
-@AjaxHandler('/ajax/initialize/(\w+)/(\w+)$')  # /ajax/initialize/Android/a0b1c2
+@AjaxHandler('/ajax/initialize/(\w+)/(\w+)$', 'POST')
 def _InitializeDevice(args, req_vars):  # pylint: disable=W0613
   device = _GetDevice(args)
   if not device:
@@ -173,6 +158,171 @@
     'isNativeTracingEnabled': device.IsNativeTracingEnabled()}
 
 
+@AjaxHandler(r'/ajax/profile/create', 'POST')
+def _CreateProfile(args, req_vars):  # pylint: disable=W0613
+  """Creates (and caches) a profile from a set of dumps.
+
+  The profiling data can be retrieved afterwards using the /profile/{PROFILE_ID}
+  endpoints (below).
+  """
+  classifier = None  # A classifier module (/classification/*_classifier.py).
+  dumps = {}  # dump-time -> obj. to classify (e.g., |memory_map.Map|).
+  for arg in 'type', 'source', 'ruleset':
+    assert(arg in req_vars), 'Expecting %s argument in POST data' % arg
+
+  # Step 1: collect the memory dumps, according to what the client specified in
+  # the 'type' and 'source' POST arguments.
+
+  # Case 1: Generate a profile from a set of mmap dumps.
+  if req_vars['type'] == 'mmap':
+    classifier = mmap_classifier
+    # Case 1a: Use a cached mmap dumps.
+    if req_vars['source'] == 'cache':
+      dumps[0] = _GetCacheObject(req_vars['id'])
+    # Case 1b: Load mem dumps from an archive.
+    elif req_vars['source'] == 'archive':
+      archive = _persistent_storage.OpenArchive(req_vars['archive'])
+      if not archive:
+        return _HTTP_GONE, [], 'Cannot open archive %s' % req_vars['archive']
+      first_timestamp = None
+      for timestamp_str in req_vars['snapshots']:
+        timestamp = dateutil.parser.parse(timestamp_str)
+        first_timestamp = timestamp if not first_timestamp else first_timestamp
+        time_delta = int((timestamp - first_timestamp).total_seconds())
+        dumps[time_delta] = archive.LoadMemMaps(timestamp)
+
+  # TODO(primiano): Add support for native_heap types.
+
+  # Step 2: Load the rule-set specified by the client in the 'ruleset' POST arg.
+  # Also, perform some basic sanity checking.
+  rules_path = os.path.join(memory_inspector.ROOT_DIR, 'classification_rules',
+                            req_vars['ruleset'])
+  if not classifier:
+    return _HTTP_GONE, [], 'Classifier %s not supported.' % req_vars['type']
+  if not dumps:
+    return _HTTP_GONE, [], 'No memory dumps could be retrieved'
+  if not os.path.isfile(rules_path):
+    return _HTTP_GONE, [], 'Cannot find the rule-set %s' % rules_path
+  with open(rules_path) as f:
+    rules = mmap_classifier.LoadRules(f.read())
+
+  # Step 3: Aggregate the data using the desired classifier and generate the
+  # profile dictionary (which will be kept cached here in the server).
+  # The resulting profile will consist of 1+ snapshots (depending on the number
+  # dumps the client has requested to process) and a number of 1+ metrics
+  # (depending on the buckets' keys returned by the classifier).
+
+  # Converts the {time: dump_obj} dict into a {time: |AggregatedResult|} dict.
+  # using the classifier.
+  snapshots = collections.OrderedDict((time, classifier.Classify(dump, rules))
+     for time, dump in sorted(dumps.iteritems()))
+
+  # Add the profile to the cache (and eventually discard old items).
+  # |profile_id| is the key that the client will use in subsequent requests
+  # (to the /ajax/profile/{ID}/ endpoints) to refer to this particular profile.
+  profile_id = _CacheObject(snapshots)
+
+  first_snapshot = next(snapshots.itervalues())
+
+  # |metrics| is the key set of any of the aggregated result
+  return _HTTP_OK, [], {'id': profile_id,
+                        'times': snapshots.keys(),
+                        'metrics': first_snapshot.keys,
+                        'rootBucket': first_snapshot.total.name + '/'}
+
+
+@AjaxHandler(r'/ajax/profile/(\w+)/tree/(\d+)/(\d+)')
+def _GetProfileTreeDataForSnapshot(args, req_vars):  # pylint: disable=W0613
+  """Gets the data for the tree chart for a given time and metric.
+
+  The response is formatted according to the Google Charts DataTable format.
+  """
+  snapshot_id = args[0]
+  metric_index = int(args[1])
+  time = int(args[2])
+  snapshots = _GetCacheObject(snapshot_id)
+  if not snapshots:
+    return _HTTP_GONE, [], 'Cannot find the selected profile.'
+  if time not in snapshots:
+    return _HTTP_GONE, [], 'Cannot find snapshot at T=%d.' % time
+  snapshot = snapshots[time]
+  if metric_index >= len(snapshot.keys):
+    return _HTTP_GONE, [], 'Invalid metric id %d' % metric_index
+
+  resp = {'cols': [{'label': 'bucket', 'type': 'string'},
+                   {'label': 'parent', 'type': 'string'}],
+          'rows': []}
+
+  def VisitBucketAndAddRows(bucket, parent_id=''):
+    """Recursively creates the (node, parent) visiting |ResultTree| in DFS."""
+    node_id = parent_id + bucket.name + '/'
+    node_label = '<dl><dt>%s</dt><dd>%s</dd></dl>' % (
+        bucket.name, _StrMem(bucket.values[metric_index]))
+    resp['rows'] += [{'c': [
+        {'v': node_id, 'f': node_label},
+        {'v': parent_id, 'f': None},
+    ]}]
+    for child in bucket.children:
+      VisitBucketAndAddRows(child, node_id)
+
+  VisitBucketAndAddRows(snapshot.total)
+  return _HTTP_OK, [], resp
+
+
+@AjaxHandler(r'/ajax/profile/(\w+)/time_serie/(\d+)/(.*)$')
+def _GetTimeSerieForSnapshot(args, req_vars):  # pylint: disable=W0613
+  """Gets the data for the area chart for a given metric and bucket.
+
+  The response is formatted according to the Google Charts DataTable format.
+  """
+  snapshot_id = args[0]
+  metric_index = int(args[1])
+  bucket_path = args[2]
+  snapshots = _GetCacheObject(snapshot_id)
+  if not snapshots:
+    return _HTTP_GONE, [], 'Cannot find the selected profile.'
+  if metric_index >= len(next(snapshots.itervalues()).keys):
+    return _HTTP_GONE, [], 'Invalid metric id %d' % metric_index
+
+  def FindBucketByPath(bucket, path, parent_path=''):  # Essentially a DFS.
+    cur_path = parent_path + bucket.name + '/'
+    if cur_path == path:
+      return bucket
+    for child in bucket.children:
+      res = FindBucketByPath(child, path, cur_path)
+      if res:
+        return res
+    return None
+
+  # The resulting data table will look like this (assuming len(metrics) == 2):
+  # Time  Ashmem      Dalvik     Other
+  # 0    (1024,0)  (4096,1024)  (0,0)
+  # 30   (512,512) (1024,1024)  (0,512)
+  # 60   (0,512)   (1024,0)     (512,0)
+  resp = {'cols': [], 'rows': []}
+  for time, aggregated_result in snapshots.iteritems():
+    bucket = FindBucketByPath(aggregated_result.total, bucket_path)
+    if not bucket:
+      return _HTTP_GONE, [], 'Bucket %s not found' % bucket_path
+
+    # If the user selected a non-leaf bucket, display the breakdown of its
+    # direct children. Otherwise just the leaf bucket.
+    children_buckets = bucket.children if bucket.children else [bucket]
+
+    # Create the columns (form the buckets) when processing the first snapshot.
+    if not resp['cols']:
+      resp['cols'] += [{'label': 'Time', 'type': 'string'}]
+      for child_bucket in children_buckets:
+        resp['cols'] += [{'label': child_bucket.name, 'type': 'number'}]
+
+    row = [{'v': str(time), 'f': None}]
+    for child_bucket in children_buckets:
+      row += [{'v': child_bucket.values[metric_index] / 1024, 'f': None}]
+    resp['rows'] += [{'c': row}]
+
+  return _HTTP_OK, [], resp
+
+
 @AjaxHandler(r'/ajax/ps/(\w+)/(\w+)$')  # /ajax/ps/Android/a0b1c2[?all=1]
 def _ListProcesses(args, req_vars):  # pylint: disable=W0613
   """Lists processes and their CPU / mem stats.
@@ -343,6 +493,69 @@
   return _HTTP_OK, [], ''
 
 
+@AjaxHandler(r'/ajax/storage/list')
+def _ListStorage(args, req_vars):  # pylint: disable=W0613
+  resp = {
+      'cols': [
+          {'label': 'Archive', 'type':'string'},
+          {'label': 'Snapshot', 'type':'string'},
+          {'label': 'Mem maps', 'type':'boolean'},
+          {'label': 'N. Heap', 'type':'boolean'},
+        ],
+      'rows': []}
+  for archive_name in _persistent_storage.ListArchives():
+    archive = _persistent_storage.OpenArchive(archive_name)
+    first_timestamp = None
+    for timestamp in archive.ListSnapshots():
+      first_timestamp = timestamp if not first_timestamp else first_timestamp
+      time_delta = '%d s.' % (timestamp - first_timestamp).total_seconds()
+      resp['rows'] += [{'c': [
+          {'v': archive_name, 'f': None},
+          {'v': timestamp.isoformat(), 'f': time_delta},
+          {'v': archive.HasMemMaps(timestamp), 'f': None},
+          {'v': archive.HasNativeHeap(timestamp), 'f': None},
+      ]}]
+  return _HTTP_OK, [], resp
+
+
+@AjaxHandler(r'/ajax/storage/(.+)/(.+)/mmaps')
+def _LoadMmapsFromStorage(args, req_vars):  # pylint: disable=W0613
+  archive = _persistent_storage.OpenArchive(args[0])
+  if not archive:
+    return _HTTP_GONE, [], 'Cannot open archive %s' % req_vars['archive']
+
+  timestamp = dateutil.parser.parse(args[1])
+  if not archive.HasMemMaps(timestamp):
+    return _HTTP_GONE, [], 'No mmaps for snapshot %s' % timestamp
+  mmap = archive.LoadMemMaps(timestamp)
+  return _HTTP_OK, [], {'table': _ConvertMmapToGTable(mmap)}
+
+
+# /ajax/tracer/start/Android/device-id/pid
+@AjaxHandler(r'/ajax/tracer/start/(\w+)/(\w+)/(\d+)', 'POST')
+def _StartTracer(args, req_vars):
+  for arg in 'interval', 'count', 'traceNativeHeap':
+    assert(arg in req_vars), 'Expecting %s argument in POST data' % arg
+  process = _GetProcess(args)
+  if not process:
+    return _HTTP_GONE, [], 'Device not found or process died'
+  task_id = background_tasks.StartTracer(
+      storage_path=_PERSISTENT_STORAGE_PATH,
+      process=process,
+      interval=int(req_vars['interval']),
+      count=int(req_vars['count']),
+      trace_native_heap=req_vars['traceNativeHeap'])
+  return _HTTP_OK, [], task_id
+
+
+@AjaxHandler(r'/ajax/tracer/status/(\d+)')  # /ajax/tracer/status/{task_id}
+def _GetTracerStatus(args, req_vars):  # pylint: disable=W0613
+  task = background_tasks.Get(int(args[0]))
+  if not task:
+    return _HTTP_GONE, [], 'Task not found'
+  return _HTTP_OK, [], task.GetProgress()
+
+
 @UriHandler(r'^(?!/ajax)/(.*)$')
 def _StaticContent(args, req_vars):  # pylint: disable=W0613
   # Give the browser a 1-day TTL cache to minimize the start-up time.
@@ -376,6 +589,62 @@
     return None
   return device.GetProcess(int(args[2]))
 
+def _ConvertMmapToGTable(mmap):
+  """Returns a Google Charts DataTable dictionary for the given mmap."""
+  assert(isinstance(mmap, memory_map.Map))
+  table = {
+      'cols': [
+          {'label': 'Start', 'type':'string'},
+          {'label': 'End', 'type':'string'},
+          {'label': 'Length Kb', 'type':'number'},
+          {'label': 'Prot', 'type':'string'},
+          {'label': 'Priv. Dirty Kb', 'type':'number'},
+          {'label': 'Priv. Clean Kb', 'type':'number'},
+          {'label': 'Shared Dirty Kb', 'type':'number'},
+          {'label': 'Shared Clean Kb', 'type':'number'},
+          {'label': 'File', 'type':'string'},
+          {'label': 'Offset', 'type':'number'},
+          {'label': 'Resident Pages', 'type':'string'},
+        ],
+      'rows': []}
+  for entry in mmap.entries:
+    table['rows'] += [{'c': [
+        {'v': '%08x' % entry.start, 'f': None},
+        {'v': '%08x' % entry.end, 'f': None},
+        {'v': entry.len / 1024, 'f': None},
+        {'v': entry.prot_flags, 'f': None},
+        {'v': entry.priv_dirty_bytes / 1024, 'f': None},
+        {'v': entry.priv_clean_bytes / 1024, 'f': None},
+        {'v': entry.shared_dirty_bytes / 1024, 'f': None},
+        {'v': entry.shared_clean_bytes / 1024, 'f': None},
+        {'v': entry.mapped_file, 'f': None},
+        {'v': entry.mapped_offset, 'f': None},
+        {'v': '[%s]' % (','.join(map(str, entry.resident_pages))), 'f': None},
+    ]}]
+  return table
+
+def _CacheObject(obj_to_store):
+  """Stores an object in the server-side cache and returns its unique id."""
+  if len(_cached_objs) >= _CACHE_LEN:
+    _cached_objs.popitem(last=False)
+  obj_id = uuid.uuid4().hex
+  _cached_objs[obj_id] = obj_to_store
+  return str(obj_id)
+
+
+def _GetCacheObject(obj_id):
+  """Retrieves an object in the server-side cache by its id."""
+  return _cached_objs.get(obj_id)
+
+
+def _StrMem(nbytes):
+  """Converts a number (of bytes) into a human readable string (kb, mb)."""
+  if nbytes < 2**10:
+    return '%d B' % nbytes
+  if nbytes < 2**20:
+    return '%.1f KB' % round(nbytes / 1024.0)
+  return '%.1f MB' % (nbytes / 1048576.0)
+
 
 def _HttpRequestHandler(environ, start_response):
   """Parses a single HTTP request and delegates the handling through UriHandler.
@@ -403,4 +672,8 @@
       backend.settings[k] = v
 
   httpd = wsgiref.simple_server.make_server('', http_port, _HttpRequestHandler)
-  httpd.serve_forever()
\ No newline at end of file
+  try:
+    httpd.serve_forever()
+  except KeyboardInterrupt:
+    pass  # Don't print useless stack traces when the user hits CTRL-C.
+  background_tasks.TerminateAll()
\ No newline at end of file
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index dc3a037..b424cfa 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -1166,6 +1166,15 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="BadMessageTerminate_RWH7">
+  <owner>jdduke@chromium.org</owner>
+  <owner>dominikg@chromium.org</owner>
+  <description>
+    Emitted when a InputHostMsg_QueueSyntheticGesture message is received while
+    the --enable-gpu-benchmarking flag is not present.
+  </description>
+</action>
+
 <action name="BadMessageTerminate_RWHVA1">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
@@ -2416,6 +2425,16 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="EasyUnlock_Enabled_Disable">
+  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <description>Please enter the description of the metric.</description>
+</action>
+
+<action name="EasyUnlock_Enabled_Enable">
+  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <description>Please enter the description of the metric.</description>
+</action>
+
 <action name="EditApplicationSettings">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
@@ -4405,22 +4424,22 @@
 </action>
 
 <action name="KeySystemSupport.Widevine.Queried">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>xhwang@chromium.org</owner>
   <description>Please enter the description of this user action.</description>
 </action>
 
 <action name="KeySystemSupport.Widevine.Supported">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>xhwang@chromium.org</owner>
   <description>Please enter the description of this user action.</description>
 </action>
 
 <action name="KeySystemSupport.WidevineWithType.Queried">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>xhwang@chromium.org</owner>
   <description>Please enter the description of this user action.</description>
 </action>
 
 <action name="KeySystemSupport.WidevineWithType.Supported">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>xhwang@chromium.org</owner>
   <description>Please enter the description of this user action.</description>
 </action>
 
@@ -7055,7 +7074,7 @@
 </action>
 
 <action name="MobileContextMenuSearchByImage">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>bdibello@chromium.org</owner>
   <description>Please enter the description of this user action.</description>
 </action>
 
@@ -7120,88 +7139,120 @@
 </action>
 
 <action name="MobileMenuAddToBookmarks">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>
+    User pressed the star icon in the app menu to add or remove a bookmark for
+    the current page.
+  </description>
+</action>
+
+<action name="MobileMenuAddToHomescreen">
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Add to homescreen' in the app menu.</description>
 </action>
 
 <action name="MobileMenuAllBookmarks">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Bookmarks' in the app menu.</description>
 </action>
 
 <action name="MobileMenuBack">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed the back icon in the app menu.</description>
 </action>
 
 <action name="MobileMenuCloseAllTabs">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Close all tabs' in the app menu.</description>
 </action>
 
 <action name="MobileMenuCloseTab">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Close tab' in the app menu.</description>
+  <obsolete>This menu item was never added to the app menu.</obsolete>
+</action>
+
+<action name="MobileMenuDirectShare">
+  <owner>aurimas@chromium.org</owner>
+  <description>
+    User pressed the application icon next to 'Share' to share directly with the
+    most recently used application.
+  </description>
 </action>
 
 <action name="MobileMenuFeedback">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Help and Feedback' in the app menu.</description>
 </action>
 
 <action name="MobileMenuFindInPage">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Find in page' in the app menu.</description>
 </action>
 
 <action name="MobileMenuForward">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed the forward icon in the app menu.</description>
 </action>
 
 <action name="MobileMenuFullscreen">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Fullscreen' in the app menu.</description>
+  <obsolete>This menu item was never added to the app menu.</obsolete>
 </action>
 
 <action name="MobileMenuNewIncognitoTab">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'New incognito tab' in the app menu.</description>
 </action>
 
 <action name="MobileMenuNewTab">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'New tab' in the app menu.</description>
 </action>
 
 <action name="MobileMenuOpenTabs">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Recent tabs' in the app menu.</description>
+</action>
+
+<action name="MobileMenuPrint">
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Print' in the app menu.</description>
 </action>
 
 <action name="MobileMenuQuit">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Quit' in the app menu.</description>
+  <obsolete>This menu item was never added to the app menu.</obsolete>
 </action>
 
 <action name="MobileMenuReload">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Reload' in the app menu.</description>
+  <obsolete>This menu item was never added to the app menu.</obsolete>
+</action>
+
+<action name="MobileMenuRequestDesktopSite">
+  <owner>aurimas@chromium.org</owner>
+  <description>
+    User pressed 'Request Desktop Site' in the app menu.
+  </description>
 </action>
 
 <action name="MobileMenuSettings">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Settings' in the app menu.</description>
 </action>
 
 <action name="MobileMenuShare">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User pressed 'Share' in the app menu.</description>
 </action>
 
 <action name="MobileMenuShow">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>aurimas@chromium.org</owner>
+  <description>User opened the app menu.</description>
 </action>
 
 <action name="MobileNTPBookmark">
@@ -8180,6 +8231,16 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="Options_Hotword_AudioLogging_Checkbox_Disable">
+  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <description>Please enter the description of the metric.</description>
+</action>
+
+<action name="Options_Hotword_AudioLogging_Checkbox_Enable">
+  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <description>Please enter the description of the metric.</description>
+</action>
+
 <action name="Options_ImagesCheckbox_Disable">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <description>Please enter the description of this user action.</description>
@@ -8551,7 +8612,7 @@
 </action>
 
 <action name="OriginChipPress">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>macourteau@chromium.org</owner>
   <description>Please enter the description of this user action.</description>
 </action>
 
@@ -8615,19 +8676,40 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="OutdatedUpgradeBubble.EnableAU">
+  <owner>mad@chromium.org</owner>
+  <description>
+    When the user clicks on the Enable updates button of the outdated upgrade
+    bubble.
+  </description>
+</action>
+
 <action name="OutdatedUpgradeBubble.Later">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>mad@chromium.org</owner>
+  <description>
+    When the user clicks on the Later button of the outdated upgrade bubble.
+  </description>
 </action>
 
 <action name="OutdatedUpgradeBubble.Reinstall">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>mad@chromium.org</owner>
+  <description>
+    When the user clicks on the Reinstall button of the outdated upgrade bubble.
+  </description>
 </action>
 
 <action name="OutdatedUpgradeBubble.Show">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <description>Please enter the description of this user action.</description>
+  <owner>mad@chromium.org</owner>
+  <description>
+    When the outdated upgrade bubble is shown for a user with auto-update on.
+  </description>
+</action>
+
+<action name="OutdatedUpgradeBubble.ShowNoAU">
+  <owner>mad@chromium.org</owner>
+  <description>
+    When the outdated upgrade bubble is shown for a user with auto-update off.
+  </description>
 </action>
 
 <action name="Outdent">
@@ -9911,7 +9993,7 @@
 </action>
 
 <action name="SuspiciousExtensionBubbleDismissed">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>finnur@chromium.org</owner>
   <description>Please enter the description of this user action.</description>
 </action>
 
diff --git a/tools/metrics/actions/extract_actions.py b/tools/metrics/actions/extract_actions.py
index a5d26cb..964de36 100755
--- a/tools/metrics/actions/extract_actions.py
+++ b/tools/metrics/actions/extract_actions.py
@@ -258,10 +258,12 @@
   actions.add('MobileFreSignInSuccessful')
   actions.add('MobileFreSkipSignIn')
   actions.add('MobileMenuAddToBookmarks')
+  actions.add('MobileMenuAddToHomescreen')
   actions.add('MobileMenuAllBookmarks')
   actions.add('MobileMenuBack')
   actions.add('MobileMenuCloseAllTabs')
   actions.add('MobileMenuCloseTab')
+  actions.add('MobileMenuDirectShare')
   actions.add('MobileMenuFeedback')
   actions.add('MobileMenuFindInPage')
   actions.add('MobileMenuForward')
@@ -269,8 +271,10 @@
   actions.add('MobileMenuNewIncognitoTab')
   actions.add('MobileMenuNewTab')
   actions.add('MobileMenuOpenTabs')
+  actions.add('MobileMenuPrint')
   actions.add('MobileMenuQuit')
   actions.add('MobileMenuReload')
+  actions.add('MobileMenuRequestDesktopSite')
   actions.add('MobileMenuSettings')
   actions.add('MobileMenuShare')
   actions.add('MobileMenuShow')
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 768c4a1..3dd8b49 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -233,6 +233,21 @@
   </summary>
 </histogram>
 
+<histogram name="AndroidTabCloseUndo.Toast"
+    enum="AndroidTabCloseUndoToastEvent">
+  <owner>dtrainor@chromium.org</owner>
+  <summary>
+    When a user closes a tab an undo toast will popup on certain devices giving
+    the user the chance to undo closing that tab.  This stat tracks how the user
+    interacts with that UI and what actions they take.  A cold start means that
+    the undo bar wasn't showing when it was triggered to show again.  A warm
+    start means that it was.  Warm starts can happen when the user closes
+    multiple tabs close together.  When the undo bar is dismissed, all closes
+    that were queued up to be undone are committed.  This can happen either by a
+    timeout or by an action by the user to move to another part of the UI.
+  </summary>
+</histogram>
+
 <histogram name="AppBanners.DismissEvent" enum="AppBannersDismissEvent">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -316,6 +331,13 @@
   </summary>
 </histogram>
 
+<histogram name="appcache.MainResourceResponseRetrieval" enum="BooleanSuccess">
+  <owner>michaeln@chromium.org</owner>
+  <summary>
+    Tracks the success rate of retrieving a main resource from the appcache.
+  </summary>
+</histogram>
+
 <histogram name="appcache.MissingManifestDetectedAtCallsite"
     enum="AppCacheErrorSite">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
@@ -339,6 +361,13 @@
   </summary>
 </histogram>
 
+<histogram name="appcache.SubResourceResponseRetrieval" enum="BooleanSuccess">
+  <owner>michaeln@chromium.org</owner>
+  <summary>
+    Tracks the success rate of retrieving a sub resource from the appcache.
+  </summary>
+</histogram>
+
 <histogram name="appcache.TaskQueueTime" units="milliseconds">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -356,9 +385,23 @@
   <summary>AppCache update job result code.</summary>
 </histogram>
 
-<histogram name="appcache.UpdateJobResult.Docs" enum="AppCacheUpdateJobResult">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
-  <summary>AppCache update job result code, only for docs.google.com.</summary>
+<histogram name="appcache.UpdateProgressAtPointOfFaliure" units="percent">
+  <owner>michaeln@chromium.org</owner>
+  <summary>Percent completion at point of failure of an update job.</summary>
+</histogram>
+
+<histogram name="appcache.UpdateWasOffOriginAtPointOfFailure" enum="Boolean">
+  <owner>michaeln@chromium.org</owner>
+  <summary>
+    Whether the resource causing the failure was from a different origin.
+  </summary>
+</histogram>
+
+<histogram name="appcache.UpdateWasStalledAtPointOfFailure" enum="Boolean">
+  <owner>michaeln@chromium.org</owner>
+  <summary>
+    Whether any progresss had been made in the 5 minutes preceeding failure.
+  </summary>
 </histogram>
 
 <histogram name="Apps.AppLaunch" enum="AppLaunch">
@@ -1444,6 +1487,23 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.AddressBookAvailable" enum="BooleanAvailable">
+  <owner>isherman@chromium.org</owner>
+  <summary>
+    Whether the Mac AddressBook was available on an attempt to read data from
+    it.
+  </summary>
+</histogram>
+
+<histogram name="Autofill.AddressBookAvailableOnFirstAttempt"
+    enum="BooleanAvailable">
+  <owner>isherman@chromium.org</owner>
+  <summary>
+    Whether the Mac AddressBook was available on the *first* attempt to read
+    data from it.  This is only recorded once per Chrome profile.
+  </summary>
+</histogram>
+
 <histogram name="Autofill.AddressSuggestionsCount">
   <owner>isherman@chromium.org</owner>
   <summary>
@@ -1668,7 +1728,7 @@
 </histogram>
 
 <histogram name="Blacklist.Blocked" enum="DllHash">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>csharp@chromium.org</owner>
   <summary>
     Records the name hashes of all the dlls that are blocked from the browser
     process.
@@ -1676,7 +1736,7 @@
 </histogram>
 
 <histogram name="Blacklist.PatchedInRenderer" enum="BooleanHit">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>csharp@chromium.org</owner>
   <summary>
     Counts the number of times a renderer process is started with the browser
     blacklist patch. This should never be hit.
@@ -1684,7 +1744,7 @@
 </histogram>
 
 <histogram name="Blacklist.Setup" enum="BlacklistSetup">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>csharp@chromium.org</owner>
   <summary>
     Records the successes and failures when running the browser blacklist setup
     code. Used to determine if the blacklist is working as intended during
@@ -1736,6 +1796,86 @@
   </summary>
 </histogram>
 
+<histogram name="CaptivePortal.DetectResult" enum="CaptivePortalDetectResult">
+  <owner>meacer@chromium.org</owner>
+  <summary>Records the result of a captive portal probe.</summary>
+</histogram>
+
+<histogram name="CaptivePortal.Notification.Status"
+    enum="CaptivePortalNotificationStatus">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    Count of displayed and not displayed due to errors notifications about
+    captive portal.
+  </summary>
+</histogram>
+
+<histogram name="CaptivePortal.Notification.UserAction"
+    enum="CaptivePortalNotificationUserAction">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    Count of clicked, closed and ignored captive portal notifications.
+  </summary>
+</histogram>
+
+<histogram name="CaptivePortal.OOBE.DetectionDuration" units="milliseconds">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    Duration of the captive portal detection process for a particular network at
+    OOBE. Detection duration is recorded each time portal detection is completed
+    for an active network.
+  </summary>
+</histogram>
+
+<histogram name="CaptivePortal.OOBE.DetectionResult" enum="CaptivePortalStatus">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    The result of captive portal detection attempts performed at OOBE. Detection
+    result is recorded when portal detection is completed for an active network
+    and when it differs from the previous result for the same network.
+  </summary>
+</histogram>
+
+<histogram name="CaptivePortal.OOBE.DiscrepancyWithShill"
+    enum="CaptivePortalStatus">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    The result of captive portal detection attempts at OOBE if it diverges from
+    network manager results. Detection result is recorded each time portal
+    detection is completed for an active network.
+  </summary>
+</histogram>
+
+<histogram name="CaptivePortal.Session.DetectionDuration" units="milliseconds">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    Duration of the captive portal detection process for a particular network in
+    user session. Detection duration is recorded each time portal detection is
+    completed for an active network.
+  </summary>
+</histogram>
+
+<histogram name="CaptivePortal.Session.DetectionResult"
+    enum="CaptivePortalStatus">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    The result of captive portal detection attempts performed in user session.
+    Detection result is recorded when portal detection is completed for an
+    active network and when it differs from the previous result for the same
+    network.
+  </summary>
+</histogram>
+
+<histogram name="CaptivePortal.Session.DiscrepancyWithShill"
+    enum="CaptivePortalStatus">
+  <owner>ygorshenin@chromium.org</owner>
+  <summary>
+    The result of captive portal detection attempts in session if it diverges
+    from network manager results. Detection result is recorded each time portal
+    detection is completed for an active network.
+  </summary>
+</histogram>
+
 <histogram name="Cast.Sender.CastButtonShown" enum="BooleanEnabled">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -2003,6 +2143,15 @@
   </summary>
 </histogram>
 
+<histogram name="ChromeOS.Display.ColorProfile" enum="ChromeOSColorProfile">
+  <owner>xiaowenx@chromium.org</owner>
+  <owner>mukai@chromium.org</owner>
+  <summary>
+    The name of the current color calibration of the display on ChromeOS. This
+    value is sent when the color calibration is changed by the user.
+  </summary>
+</histogram>
+
 <histogram name="ChromeOS.SAML.APIUsed" enum="BooleanUsage">
   <owner>bartfab@chromium.org</owner>
   <summary>
@@ -2087,6 +2236,153 @@
   </summary>
 </histogram>
 
+<histogram name="CloudPrint.AuthEvent" enum="CloudPrintAuthEventType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Event counts in CloudPrintAuth.</summary>
+</histogram>
+
+<histogram name="CloudPrint.AvailablePrinters">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The number of printers availible for registration.</summary>
+</histogram>
+
+<histogram name="CloudPrint.AvailablePrintersList">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The number of printers availible for registration in Windows Service.
+  </summary>
+</histogram>
+
+<histogram name="CloudPrint.JobHandlerEvent"
+    enum="CloudPrintJobHandlerEventType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Event counts in PrinterJobHandler.</summary>
+</histogram>
+
+<histogram name="CloudPrint.JobsDonePerInterval">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The number of jobs successfully completed per hour.</summary>
+</histogram>
+
+<histogram name="CloudPrint.JobsStartedPerInterval">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The number of jobs started per hour.</summary>
+</histogram>
+
+<histogram name="CloudPrint.JobStatus" enum="CloudPrintJobStatusType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Then number of job completion statuses.</summary>
+</histogram>
+
+<histogram name="CloudPrint.NativeJobStatus"
+    enum="CloudPrintNativeJobStatusType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Event counts in PrintSystem.</summary>
+</histogram>
+
+<histogram name="CloudPrint.PrepareTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of time needed to prepare job for spooling.</summary>
+</histogram>
+
+<histogram name="CloudPrint.PrinterBlacklistSize">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The number of printers user has blacklisted.</summary>
+</histogram>
+
+<histogram name="CloudPrint.PrinterWhitelistSize">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The number of printers user has whitelisted.</summary>
+</histogram>
+
+<histogram name="CloudPrint.PrintingTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of time needed to finish print job.</summary>
+</histogram>
+
+<histogram name="CloudPrint.ServiceEvents" enum="ServiceProcessEventType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Event counts in ServiceProcessControl.</summary>
+</histogram>
+
+<histogram name="CloudPrint.ServiceUtilityCapsFailTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The amount of time used to fail to collect printer capabilities.
+  </summary>
+</histogram>
+
+<histogram name="CloudPrint.ServiceUtilityCapsTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of time used to collect printer capabilities.</summary>
+</histogram>
+
+<histogram name="CloudPrint.ServiceUtilityDisconnectTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The amount of time the utility process runs before disconnect.
+  </summary>
+</histogram>
+
+<histogram name="CloudPrint.ServiceUtilityMetafileFailTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of time used to fail to generate metafile.</summary>
+</histogram>
+
+<histogram name="CloudPrint.ServiceUtilityMetafileTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of time used to generate metafile.</summary>
+</histogram>
+
+<histogram name="CloudPrint.ServiceUtilityProcessHostEvent"
+    enum="ServiceUtilityProcessHostEventType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Event counts in ServiceUtilityProcessHost.</summary>
+</histogram>
+
+<histogram name="CloudPrint.SpoolingTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of time needed to spool print job.</summary>
+</histogram>
+
+<histogram name="CloudPrint.UnregisterPrinters">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The number of printers to unregister.</summary>
+</histogram>
+
+<histogram name="CloudPrint.UrlFetcherDownloadSize" units="KB">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of data downloaded on cloud print request.</summary>
+</histogram>
+
+<histogram name="CloudPrint.UrlFetcherRequestTime" units="ms">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of time needed for cloud print request.</summary>
+</histogram>
+
+<histogram name="CloudPrint.UrlFetcherRequestType"
+    enum="CloudPrintUrlFetcherRequestType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Request counts to cloud print service.</summary>
+</histogram>
+
+<histogram name="CloudPrint.UrlFetcherRetries">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The number of retries used to complete cloud print request.</summary>
+</histogram>
+
+<histogram name="CloudPrint.UrlFetcherUploadSize" units="KB">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>The amount of data uploaded with cloud print request.</summary>
+</histogram>
+
+<histogram name="CloudPrint.XmppPingTry">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Number of tries before successfull ping. 99 means giving up.
+  </summary>
+</histogram>
+
 <histogram name="Compositing.CopyFromSurfaceTime" units="ms">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -6561,11 +6857,21 @@
   <summary>Status code of the outcome of a GCM checkin request.</summary>
 </histogram>
 
+<histogram name="GCM.ConnectedViaProxy" enum="Boolean">
+  <owner>zea@chromium.org</owner>
+  <summary>Whether the GCM connection was made via a proxy or not.</summary>
+</histogram>
+
 <histogram name="GCM.ConnectionDisconnectErrorCode" enum="NetErrorCodes">
   <owner>zea@chromium.org</owner>
   <summary>Net error results from GCM disconnect events.</summary>
 </histogram>
 
+<histogram name="GCM.ConnectionEndpoint" enum="GCMEndpoints">
+  <owner>zea@chromium.org</owner>
+  <summary>Number of connections made to each specific MCS endpoint.</summary>
+</histogram>
+
 <histogram name="GCM.ConnectionFailureErrorCode" enum="NetErrorCodes">
   <owner>zea@chromium.org</owner>
   <summary>Net error results from GCM connection attempts.</summary>
@@ -6576,7 +6882,7 @@
   <summary>Reasons for GCM connection resets.</summary>
 </histogram>
 
-<histogram name="GCM.ConnectionSuccessRate">
+<histogram name="GCM.ConnectionSuccessRate" enum="BooleanSuccess">
   <owner>zea@chromium.org</owner>
   <summary>
     GCM connection success rate. Does not take into account login success. See
@@ -6601,6 +6907,9 @@
 </histogram>
 
 <histogram name="GCM.NumUsers">
+  <obsolete>
+    Deprecated as of 3/2014.
+  </obsolete>
   <owner>zea@chromium.org</owner>
   <summary>
     Number of GCM users associated with this client at startup time.
@@ -6629,6 +6938,13 @@
   </summary>
 </histogram>
 
+<histogram name="GCM.RestoredRegistrations">
+  <owner>jianli@chromium.org</owner>
+  <summary>
+    Number of registrations restored from the persistent store at startup.
+  </summary>
+</histogram>
+
 <histogram name="GCM.StoreDestroySucceeded" enum="BooleanSuccess">
   <owner>zea@chromium.org</owner>
   <summary>
@@ -6665,6 +6981,22 @@
   <summary>Status code of the outcome of a GCM unregistration request.</summary>
 </histogram>
 
+<histogram name="GCMInvalidations.IncomingMessageStatus"
+    enum="GCMInvalidationsIncomingMessageStatus">
+  <owner>pavely@chromium.org</owner>
+  <summary>
+    Status of parsing incoming invalidations message from GCM channel.
+  </summary>
+</histogram>
+
+<histogram name="GCMInvalidations.OutgoingMessageStatus"
+    enum="GCMInvalidationsOutgoingMessageStatus">
+  <owner>pavely@chromium.org</owner>
+  <summary>
+    Status of sending outgoing invalidations message through GCM.
+  </summary>
+</histogram>
+
 <histogram name="GData.AuthSuccess" enum="GDataAuthResult">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>Result of the authentication for Drive.</summary>
@@ -6773,6 +7105,24 @@
   <summary>Http response codes in NetworkLocationRequest.</summary>
 </histogram>
 
+<histogram name="GoogleNow.Card.Button.Clicked0" enum="GoogleNowCardTypeId">
+  <owner>robliao@chromium.org</owner>
+  <owner>skare@chromium.org</owner>
+  <summary>Types of cards which received an index 0 button click.</summary>
+</histogram>
+
+<histogram name="GoogleNow.Card.Button.Clicked1" enum="GoogleNowCardTypeId">
+  <owner>robliao@chromium.org</owner>
+  <owner>skare@chromium.org</owner>
+  <summary>Types of cards which received an index 1 button click.</summary>
+</histogram>
+
+<histogram name="GoogleNow.Card.Clicked" enum="GoogleNowCardTypeId">
+  <owner>robliao@chromium.org</owner>
+  <owner>skare@chromium.org</owner>
+  <summary>Types of cards which received a notification click.</summary>
+</histogram>
+
 <histogram name="GoogleNow.Event" enum="GoogleNowEvent">
   <owner>robliao@chromium.org</owner>
   <owner>skare@chromium.org</owner>
@@ -6958,6 +7308,15 @@
   </summary>
 </histogram>
 
+<histogram name="Hotword.AudioLoggingEnabled" enum="BooleanEnabled">
+  <summary>
+    The state of the hotword audio logging preference. This value is emitted
+    each time the hotword availability is requested by the extension if the user
+    is also opted in to hotword voice search. This check typically happens each
+    time a hotword search is initiated.
+  </summary>
+</histogram>
+
 <histogram name="Hotword.Enabled" enum="HotwordPrefState">
   <owner>rlp@chromium.org</owner>
   <summary>
@@ -7718,6 +8077,12 @@
   </summary>
 </histogram>
 
+<histogram name="Invalidations.NetworkChannel"
+    enum="InvalidationNetworkChannel">
+  <owner>pavely@chromium.org</owner>
+  <summary>Network channel used for invalidations.</summary>
+</histogram>
+
 <histogram name="Keyboard.KeystrokeDeltas" units="milliseconds">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -7961,6 +8326,37 @@
   <summary>The version of glibc used. (Linux only)</summary>
 </histogram>
 
+<histogram name="LocalDiscovery.ClientRestartAttempts">
+  <owner>noamsml@chromium.org</owner>
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Records number of attempts to start local discovery.</summary>
+</histogram>
+
+<histogram name="LocalDiscovery.DetectorRestartTime" units="milliseconds">
+  <owner>noamsml@chromium.org</owner>
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Time between detector restarts.</summary>
+</histogram>
+
+<histogram name="LocalDiscovery.DetectorTriggerTime" units="milliseconds">
+  <owner>noamsml@chromium.org</owner>
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Time before detector trigger notifications.</summary>
+</histogram>
+
+<histogram name="LocalDiscovery.DevicesPage" enum="DevicesPageEvents">
+  <owner>noamsml@chromium.org</owner>
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Records events related to devices page.</summary>
+</histogram>
+
+<histogram name="LocalDiscovery.PrivetNotificationsEvent"
+    enum="PrivetNotificationsEvent">
+  <owner>noamsml@chromium.org</owner>
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Records events related to local discovery notifications.</summary>
+</histogram>
+
 <histogram name="Login.ConsumerNewUsersAllowed" enum="LoginConsumerWhitelist">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -8103,6 +8499,14 @@
   </summary>
 </histogram>
 
+<histogram name="Media.AudioTrackProcessingStates"
+    enum="AudioTrackProcessingStates">
+  <summary>
+    State of the media stream audio track processing, sampled once during the
+    life time of a MediaStreamAudioProcessor.
+  </summary>
+</histogram>
+
 <histogram name="Media.CacheUseful" enum="BooleanSuccess">
   <owner>scherkus@chromium.org</owner>
   <summary>
@@ -9278,6 +9682,19 @@
   </summary>
 </histogram>
 
+<histogram name="MobileStartup.MobileMultiWindowInstances">
+  <owner>dtrainor@chromium.org</owner>
+  <summary>
+    Android: Number of instances of Chrome currently open during a MultiWindow
+    session.  Emitted every time Chrome is paused.  Only emitted on Android
+    MultiWindow devices.
+
+    A MultiWindow session is any period of time that Chrome was not used in a
+    full screen mode but together with another Activity that is visible at the
+    same time. This is only supported in a few Android models.
+  </summary>
+</histogram>
+
 <histogram name="MobileStartup.MobileMultiWindowSession" units="percent">
   <owner>miguelg@chromium.org</owner>
   <summary>
@@ -9997,6 +10414,57 @@
   <summary>The time to generate an NTLM HTTP authentication token.</summary>
 </histogram>
 
+<histogram name="Net.AutoReload.CountAtStop">
+  <owner>ellyjones@chromium.org</owner>
+  <owner>rdsmith@chromium.org</owner>
+  <owner>cbentzel@chromium.org</owner>
+  <summary>
+    Number of times auto-reload has been attempted before auto-reload stopped
+    without succeeding, either because the stop button was pressed or because
+    the renderer was destroyed.
+  </summary>
+</histogram>
+
+<histogram name="Net.AutoReload.CountAtSuccess">
+  <owner>ellyjones@chromium.org</owner>
+  <owner>rdsmith@chromium.org</owner>
+  <owner>cbentzel@chromium.org</owner>
+  <summary>
+    Number of times auto-reload had to attempt to reload a page before
+    succeeding.
+  </summary>
+</histogram>
+
+<histogram name="Net.AutoReload.ErrorAtFirstSuccess" enum="NetErrorCodes">
+  <owner>ellyjones@chromium.org</owner>
+  <owner>rdsmith@chromium.org</owner>
+  <owner>cbentzel@chromium.org</owner>
+  <summary>
+    Original error code that started an auto-reload which then succeeded on the
+    first attempt.
+  </summary>
+</histogram>
+
+<histogram name="Net.AutoReload.ErrorAtStop" enum="NetErrorCodes">
+  <owner>ellyjones@chromium.org</owner>
+  <owner>rdsmith@chromium.org</owner>
+  <owner>cbentzel@chromium.org</owner>
+  <summary>
+    Error code, if any, when auto-reload stopped without succeeding, either
+    because the stop button was pressed or because the renderer was destroyed.
+  </summary>
+</histogram>
+
+<histogram name="Net.AutoReload.ErrorAtSuccess" enum="NetErrorCodes">
+  <owner>ellyjones@chromium.org</owner>
+  <owner>rdsmith@chromium.org</owner>
+  <owner>cbentzel@chromium.org</owner>
+  <summary>
+    Original error code that started an auto-reload which then eventually
+    succeeded.
+  </summary>
+</histogram>
+
 <histogram name="Net.CertCommonNameFallback" enum="BooleanCommonNameMatch">
   <owner>rsleevi@chromium.org</owner>
   <summary>
@@ -10868,7 +11336,8 @@
 </histogram>
 
 <histogram name="Net.ErrorCodesForImages" enum="NetErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>skonig@chromium.org</owner>
+  <owner>hbengali@chromium.org</owner>
   <summary>
     Net error codes that requests for images end with, including net::OK and
     net:ERR_ABORTED.
@@ -11967,7 +12436,7 @@
 </histogram>
 
 <histogram name="Net.QuicHandshakeNotConfirmedNumPacketsReceived">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of QUIC packets received by a QUIC connection whose handshake was
     not confirmed when that connection is closed.
@@ -11975,7 +12444,7 @@
 </histogram>
 
 <histogram name="Net.QuicHandshakeState" enum="QuicHandshakeState">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The state of a QUIC connection's crypto hanshake as it progresses from
     starting to confirmation or failure.
@@ -11983,7 +12452,7 @@
 </histogram>
 
 <histogram name="Net.QuicNumSentClientHellos">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>The number of client hello messages sent.</summary>
 </histogram>
 
@@ -11991,7 +12460,7 @@
   <obsolete>
     see Net.QuicSession.Connect*PortForHTTP*
   </obsolete>
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of client hello messages sent when the crypto handshake was
     confirmed.
@@ -11999,21 +12468,21 @@
 </histogram>
 
 <histogram name="Net.QuicNumStreamFramesInPacket">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of stream frames bundled within a received packet.
   </summary>
 </histogram>
 
 <histogram name="Net.QuicNumStreamFramesPerStreamInPacket">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of stream frames per stream ID within a received packet.
   </summary>
 </histogram>
 
 <histogram name="Net.QuicServerInfo.DiskCacheReadTime" units="milliseconds">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>Time spent to load QUIC server information from disk cache.</summary>
 </histogram>
 
@@ -12049,14 +12518,14 @@
 </histogram>
 
 <histogram name="Net.QuicSession.CloseSessionOnError" enum="NetErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The network error code which resulted in the session being closed.
   </summary>
 </histogram>
 
 <histogram name="Net.QuicSession.Connect" units="RTTs">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     Samples of the number of round-trips needed by a QUIC connection before a
     request could be sent by the client.
@@ -12064,13 +12533,13 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ConnectionClose.NumOpenStreams.TimedOut">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>The number of streams open when a QUIC session timed out.</summary>
 </histogram>
 
 <histogram
     name="Net.QuicSession.ConnectionClose.NumTotalStreams.HandshakeTimedOut">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of total streams created when a QUIC session crypto handshake
     timed out.
@@ -12079,7 +12548,7 @@
 
 <histogram name="Net.QuicSession.ConnectionCloseErrorCode"
     enum="QuicErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The QUIC error code which resulted in the connection being closed.
   </summary>
@@ -12087,7 +12556,7 @@
 
 <histogram name="Net.QuicSession.ConnectionCloseErrorCodeClient"
     enum="QuicErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The QUIC error code which resulted in the connection being closed by the
     client.
@@ -12096,15 +12565,23 @@
 
 <histogram name="Net.QuicSession.ConnectionCloseErrorCodeServer"
     enum="QuicErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The QUIC error code which resulted in the connection being closed by the
     server.
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.CreationError" enum="QuicSessionErrorCodes">
+  <owner>jar@chromium.org</owner>
+  <summary>
+    Count of errors during attempts to create a QUIC session (before even using
+    the session).
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.FinalTcpCwnd">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The value of the TCP cubic sender's CWND when the session is closed.
   </summary>
@@ -12114,7 +12591,7 @@
   <obsolete>
     see Net.QuicSession.Connect*PortForHTTP*
   </obsolete>
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     Samples of the number of round-trips needed by a QUIC connection before a
     request could be sent by the client.
@@ -12122,14 +12599,14 @@
 </histogram>
 
 <histogram name="Net.QuicSession.NumOpenStreams">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of QUIC streams opened when a new QUIC stream is created.
   </summary>
 </histogram>
 
 <histogram name="Net.QuicSession.NumTotalStreams">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The total number of streams created by the client when the session is
     closed.
@@ -12137,7 +12614,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.OutOfOrderGapReceived">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of missing packets between the current received packet and the
     previously largest received packet sequence number, when the current
@@ -12147,7 +12624,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.OutOfOrderPacketsReceived">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of times the current received packet had a lower sequence number
     than the previously received packet sequence number.
@@ -12155,7 +12632,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PacketGapReceived">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of missing packets between the current received packet and the
     previously largest received packet sequence number.
@@ -12163,7 +12640,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PacketGapSent">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The number of missing packets between the current received packet and the
     previously largest received packet sequence number, as reported by the
@@ -12180,7 +12657,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PacketReceived" units="SequenceNumber">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     Each bucket corresponds to a specific packet sequence number that was sent
     by a server to Chrome at the start of a QUIC connection. This histogram is
@@ -12201,12 +12678,12 @@
 </histogram>
 
 <histogram name="Net.QuicSession.QuicVersion">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>Version of the QUIC protocol used for this connection.</summary>
 </histogram>
 
 <histogram name="Net.QuicSession.ReadError" enum="NetErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The network error code returned when attempting to read to a QUIC
     connection.
@@ -12215,7 +12692,7 @@
 
 <histogram name="Net.QuicSession.RstStreamErrorCodeClient"
     enum="QuicRstStreamErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The QUIC error code which resulted in a stream being reset by the client.
   </summary>
@@ -12223,24 +12700,59 @@
 
 <histogram name="Net.QuicSession.RstStreamErrorCodeServer"
     enum="QuicRstStreamErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The QUIC error code which resulted in a stream being reset by the server.
   </summary>
 </histogram>
 
+<histogram name="Net.QuicSession.SecureResourceSecureSession">
+  <owner>rch@chromium.org.</owner>
+  <summary>
+    The number of request for secure resources over QUIC sessions. True if the
+    session is secure, false if it is not.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.TruncatedAcksReceived">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>The number of truncated ACK frames received.</summary>
 </histogram>
 
 <histogram name="Net.QuicSession.TruncatedAcksSent">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>The number of truncated ACK frames sent.</summary>
 </histogram>
 
+<histogram name="Net.QuicSession.UnexpectedNotGoingAway"
+    enum="QuicSessionLocations">
+  <owner>rch@chromium.org</owner>
+  <summary>
+        The location in quic_client_session.cc where a session is unexpectedly
+    not going away.
+  </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.UnexpectedObservers"
+    enum="QuicSessionLocations">
+  <owner>rch@chromium.org</owner>
+  <summary>
+    The location in quic_client_session.cc where there were unexpected
+    observers.
+  </summary>
+</histogram>
+
+<histogram name="Net.QuicSession.UnexpectedOpenStreams"
+    enum="QuicSessionLocations">
+  <owner>rch@chromium.org</owner>
+  <summary>
+    The location in quic_client_session.cc where there were unexpected open
+    streams.
+  </summary>
+</histogram>
+
 <histogram name="Net.QuicSession.WriteError" enum="NetErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>rch@chromium.org</owner>
   <summary>
     The network error code returned when attempting to write to a QUIC
     connection.
@@ -12300,6 +12812,14 @@
   </summary>
 </histogram>
 
+<histogram name="Net.SocketReceiveBufferUnchangeable" units="Bytes">
+  <owner>jar@chromium.org</owner>
+  <summary>
+    The size of a socket's receive buffer when the attempt to change it via
+    setsockopt failed.
+  </summary>
+</histogram>
+
 <histogram name="Net.SocketRequestTime">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -12365,6 +12885,14 @@
   </summary>
 </histogram>
 
+<histogram name="Net.SocketUnchangeableSendBuffer" units="Bytes">
+  <owner>jar@chromium.org</owner>
+  <summary>
+    The size of a socket's send buffer when the attempt to change it via
+    setsockopt failed.
+  </summary>
+</histogram>
+
 <histogram name="Net.SOCKSSocketIdleTimeBeforeNextUse_ReusedSocket">
   <obsolete>
     see SocketIdleTimeBeforeNextUse_ReusedSocket_SOCK
@@ -15496,6 +16024,23 @@
   </summary>
 </histogram>
 
+<histogram name="Omnibox.UserTextCleared" enum="OmniboxUserTextCleared">
+  <owner>mpearson@chromium.org</owner>
+  <summary>
+    Counts the number of times that the user text is cleared.  IME users are
+    sometimes in the situation that IME was unintentionally turned on and failed
+    to input latin alphabets (ASCII characters) or the opposite case.  In that
+    case, users may delete all the text and the user text gets cleared.  This
+    histogram helps us estimate how often this scenario happens.
+
+    Note that since we don't currently correlate &quot;text cleared&quot; events
+    with IME usage, this also captures many other cases where users clear the
+    text; though it explicitly doesn't log deleting all the permanent text as
+    the first action of an editing sequence (see comments in
+    OnAfterPossibleChange()).
+  </summary>
+</histogram>
+
 <histogram name="Omnibox.ZeroSuggest.MostVisitedResultsCounterfactual">
   <owner>hfung@chromium.org</owner>
   <summary>
@@ -15529,6 +16074,15 @@
   <summary>Events seen by the OSX NSException swizzle.</summary>
 </histogram>
 
+<histogram name="OutdatedUpgradeBubble.NumLaterPerEnableAU">
+  <owner>mad@chromium.org</owner>
+  <summary>
+    Counts the number of times the user clicked on the later button of the
+    outdated upgrade bubble, before clicking on the enable updates button in the
+    same Chrome session.
+  </summary>
+</histogram>
+
 <histogram name="OutdatedUpgradeBubble.NumLaterPerReinstall">
   <owner>mad@chromium.org</owner>
   <summary>
@@ -15764,8 +16318,22 @@
   </summary>
 </histogram>
 
+<histogram name="PasswordManager.ActionsTakenV3"
+    enum="PasswordManagerActionsTakenV3">
+  <owner>dubroy@chromium.org</owner>
+  <owner>vabr@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
+  <summary>
+    Stats documenting how we handle every form containing a password, bucketed
+    by the actions taken.
+  </summary>
+</histogram>
+
 <histogram name="PasswordManager.ActionsTakenWithPsl"
     enum="PasswordManagerActionsTakenWithPsl">
+  <obsolete>
+    Deprecated as of 3/18/2014. See PasswordManagerActionsTakenV3.
+  </obsolete>
   <owner>dubroy@chromium.org</owner>
   <owner>vabr@chromium.org</owner>
   <owner>yfriedman@chromium.org</owner>
@@ -17710,11 +18278,21 @@
   <summary>Record usage of PPB_Flash.Navigate() Pepper API.</summary>
 </histogram>
 
+<histogram name="Plugin.PpapiBrokerLoadErrorCode" units="code">
+  <owner>xhwang@chromium.org</owner>
+  <summary>The error code of a PPAPI broker load failure.</summary>
+</histogram>
+
 <histogram name="Plugin.PpapiBrokerLoadResult" enum="PluginLoadResult">
   <owner>xhwang@chromium.org</owner>
   <summary>The result from an attempt to load a PPAPI broker.</summary>
 </histogram>
 
+<histogram name="Plugin.PpapiPluginLoadErrorCode" units="code">
+  <owner>xhwang@chromium.org</owner>
+  <summary>The error code of a PPAPI plugin load failure.</summary>
+</histogram>
+
 <histogram name="Plugin.PpapiPluginLoadResult" enum="PluginLoadResult">
   <owner>xhwang@chromium.org</owner>
   <summary>The result from an attempt to load a PPAPI plugin.</summary>
@@ -18263,6 +18841,16 @@
   </summary>
 </histogram>
 
+<histogram name="Prerender.AbandonTimeUntilUsed" units="milliseconds">
+  <owner>davidben@chromium.org</owner>
+  <owner>tburkard@chromium.org</owner>
+  <summary>
+    Time from when a prerendered page is abandoned to when it is first used due
+    to user navigation. If the page is swapped before begin abandoned, a zero is
+    recorded.
+  </summary>
+</histogram>
+
 <histogram name="Prerender.CookieSendType" enum="PrerenderCookieSendType">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -19005,6 +19593,197 @@
   </summary>
 </histogram>
 
+<histogram name="PrinterService.PrinterServiceEvent"
+    enum="PrinterServiceEventType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Count of events in PrinterService on ChromeOS related to USB printers.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.DestinationAction"
+    enum="PrintPreviewPrintDestinationBuckets">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Actions performed by the user when the print destination search widget is
+    shown to the user.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.FontType" enum="PrintPreviewFontTypeType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Count of font file formats embeeded in print preview PDFs. These numbers are
+    biased by what the platforms supports in terms of detection.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.GcpPromo" enum="PrintPreviewGcpPromoBuckets">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Actions performed by the user when the Google Cloud Print add-printers
+    promotion is shown to the user.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.InitialDisplayTime" units="milliseconds">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Time from when print preview is intiated until the intial preview is sent to
+    the preview tab for rendering.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.InitializationTime" units="milliseconds">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Time from when print preview is intiated until the preview PDF generation is
+    started.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.ManagePrinters">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Count the number of requests received to show the manage printers dialog.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.NumberOfPrinters">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Count the total number of printers shown in destination drop down list.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.PageCount.Initial">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The page count of the initial print preview, a.k.a. the total number of
+    pages in documents to be printed.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.PageCount.PrintToCloudPrint">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The final page count (after page selection) of documents printed to a cloud
+    printer.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.PageCount.PrintToCloudPrintWebDialog">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The final page count (after page selection) of documents printed to a cloud
+    printer using web dialog.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.PageCount.PrintToPDF">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The final page count (after page selection) of documents printed to PDF.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.PageCount.PrintToPrinter">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The final page count (after page selection) of documents printed to a
+    printer.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.PageCount.SystemDialog">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The final page count (after page selection) of documents printed using
+    system dialog.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.PreviewEvent" enum="PrintPreviewHelperEvents">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Print preview events.</summary>
+</histogram>
+
+<histogram name="PrintPreview.PrintSettings" enum="PrintSettings">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Track the popularity of print settings. (Settings when printing to PDF are
+    excluded from this statistic.)
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.RegeneratePreviewRequest.BeforeCancel">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The number of times regenerate preview requests received before the user
+    clicked the cancel button.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.RegeneratePreviewRequest.BeforeFirstData">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The number of times regenerate preview requests received before the first
+    preview data is availible.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.RegeneratePreviewRequest.BeforePrint">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    The number of times regenerate preview requests received before the user
+    clicked the print button.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.RenderAndGeneratePDFTime" units="milliseconds">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Time taken to render and generate PDF for print preview. (Includes time to
+    reflow the page back to normal, but not the time to reflow the page to
+    prepare for printing.)
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.RenderAndGeneratePDFTimeAvgPerPage"
+    units="milliseconds">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Time taken to render and generate PDF for print preview divided by the
+    number of pages. (Includes time to reflow the page back to normal, but not
+    the time to reflow the page to prepare for printing.)
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.RendererError" enum="PrintPreviewFailureType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Count how frequently a set of pre-defined print preview errors occur.
+  </summary>
+</histogram>
+
+<histogram name="PrintPreview.RenderPDFPageTime" units="milliseconds">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Time taken to render each PDF page for print preview.</summary>
+</histogram>
+
+<histogram name="PrintPreview.RenderToPDFTime" units="milliseconds">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Time taken to render to PDF for print preview.</summary>
+</histogram>
+
+<histogram name="PrintPreview.UserAction" enum="PrintPreviewUserActionType">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Action taken by the user in the preview tab such as print, cancel, print to
+    pdf and show advanced print settings dialog.
+  </summary>
+</histogram>
+
 <histogram name="Profile.AddNewUser" enum="ProfileAddNewUser">
   <owner>bcwhite@chromium.org</owner>
   <owner>rlp@chromium.org</owner>
@@ -20107,6 +20886,18 @@
   </summary>
 </histogram>
 
+<histogram name="RenderViewContextMenu.Shown" enum="RenderViewContextMenuItem">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>Count of renderer view context menu items shown.</summary>
+</histogram>
+
+<histogram name="RenderViewContextMenu.Used" enum="RenderViewContextMenuItem">
+  <owner>vitalybuka@chromium.org</owner>
+  <summary>
+    Count of renderer view context menu items (Only commands now) used.
+  </summary>
+</histogram>
+
 <histogram name="RequestAutocomplete.DismissalState"
     enum="AutofillDialogDismissalState">
   <owner>estade@chromium.org</owner>
@@ -20196,6 +20987,15 @@
   </summary>
 </histogram>
 
+<histogram name="Reset.ChromeOS.PowerwashDialogShown"
+    enum="PowerwashDialogViewType">
+  <owner>merkulova@chromium.org</owner>
+  <summary>
+    Records the number of times the factory reset dialog was shown. Grouped by
+    the viewtype.
+  </summary>
+</histogram>
+
 <histogram name="SB.BloomFilter" units="milliseconds">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
@@ -21031,6 +21831,14 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientDownload.ExtractImageHeadersTime" units="milliseconds">
+  <owner>grt@chromium.org</owner>
+  <summary>
+    Records the time it takes for the SafeBrowsing download service to extract
+    image headers from a downloaded binary.
+  </summary>
+</histogram>
+
 <histogram name="SBClientDownload.ExtractSignatureFeaturesTime"
     units="milliseconds">
   <owner>mattm@chromium.org</owner>
@@ -21083,31 +21891,50 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientMalware.ClassificationStart" enum="BooleanHit">
+  <owner>noelutz@chromium.org</owner>
+  <summary>
+    The number of pages that we could have possibly classified (essentially the
+    number of top page navigations by users with SBClientMalware enabled). The
+    name is slightly misleading as it is recorded before
+    &quot;Preclassification&quot; happens.
+  </summary>
+</histogram>
+
 <histogram name="SBClientMalware.IPBlacklistRequestNetError"
     enum="NetErrorCodes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>noelutz@chromium.org</owner>
   <summary>
     The net error code for all ClientMalwareRequest URLFetchers.
   </summary>
 </histogram>
 
 <histogram name="SBClientMalware.IPBlacklistRequestPayloadSize" units="bytes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>noelutz@chromium.org</owner>
   <summary>
     The size of the upload data for ClientMalwareRequest URLFetchers.
   </summary>
 </histogram>
 
 <histogram name="SBClientMalware.IPBlacklistRequestResponseCode">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>noelutz@chromium.org</owner>
   <summary>
     For ClientMalwareRequest URLFetchers with successful status, the HTTP
     response code that was received.
   </summary>
 </histogram>
 
+<histogram name="SBClientMalware.PreClassificationCheckFail"
+    enum="SBClientDetectionPreClassificationCheckFail">
+  <owner>noelutz@chromium.org</owner>
+  <summary>
+    Records the number of malware classifications that were skipped because a
+    pre-classification check failed.
+  </summary>
+</histogram>
+
 <histogram name="SBClientMalware.SentReports" enum="SBClientMalwareSentReports">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>noelutz@chromium.org</owner>
   <summary>
     Measures the success rate of sending malware reports.  Sending a report can
     fail due to a client reaching the limit on the number of reports it can send
@@ -21115,6 +21942,14 @@
   </summary>
 </histogram>
 
+<histogram name="SBClientMalware.UnexpectedPageId" enum="BooleanHit">
+  <owner>noelutz@chromium.org</owner>
+  <summary>
+    Counts the number of times the page ID that completed the page load does not
+    match the browse info page ID.  We expect that number to be zero.
+  </summary>
+</histogram>
+
 <histogram name="SBClientPhishing.CancelClassificationReason"
     enum="SBClientPhishingCancelClassificationReason">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
@@ -21132,7 +21967,7 @@
   </summary>
 </histogram>
 
-<histogram name="SBClientPhishing.ClassificationStart">
+<histogram name="SBClientPhishing.ClassificationStart" enum="BooleanHit">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of pages that we could have possibly classified (essentially the
@@ -21234,15 +22069,15 @@
 </histogram>
 
 <histogram name="SBClientPhishing.PreClassificationCheckFail"
-    enum="SBClientPhishingPreClassificationCheckFail">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+    enum="SBClientDetectionPreClassificationCheckFail">
+  <owner>noelutz@chromium.org</owner>
   <summary>
     Records the number of phishing classifications that were skipped because a
     pre-classification check failed.
   </summary>
 </histogram>
 
-<histogram name="SBClientPhishing.ReportLimitSkipped">
+<histogram name="SBClientPhishing.ReportLimitSkipped" enum="BooleanHit">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of phishing classifications that were previously cached as being
@@ -21258,7 +22093,7 @@
   </summary>
 </histogram>
 
-<histogram name="SBClientPhishing.RequestSatisfiedFromCache">
+<histogram name="SBClientPhishing.RequestSatisfiedFromCache" enum="BooleanHit">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>
     The number of times that a cached phishing classification result was used,
@@ -21450,6 +22285,15 @@
   </summary>
 </histogram>
 
+<histogram name="ServicesCustomization.LoadResult"
+    enum="ServicesCustomizationLoadResult">
+  <owner>dpolukhin@chromium.org</owner>
+  <summary>
+    Records result of fetching and parsing OEM customization manifest. See
+    ServicesCustomizationDocument class for more info. Used only on Chrome OS.
+  </summary>
+</histogram>
+
 <histogram name="Settings.DefaultSearchProvider" enum="OmniboxSearchEngine">
   <obsolete>
     Deprecated in Chrome 30.  Use Search.DefaultSearchProviderType instead.
@@ -26462,6 +27306,38 @@
   </summary>
 </histogram>
 
+<histogram name="TimeZone.TimeZoneRequest.Event" enum="TimeZoneRequestEvent">
+  <summary>Events in TimeZoneRequest.</summary>
+</histogram>
+
+<histogram name="TimeZone.TimeZoneRequest.ResponseCode" enum="HttpResponseCode">
+  <summary>Http response codes in TimeZoneRequest.</summary>
+</histogram>
+
+<histogram name="TimeZone.TimeZoneRequest.ResponseFailureTime"
+    units="milliseconds">
+  <summary>
+    The time elapsed between the sending of the first API request and the time
+    the final (failed) response was recorded. Includes all retries.
+  </summary>
+</histogram>
+
+<histogram name="TimeZone.TimeZoneRequest.ResponseSuccessTime"
+    units="milliseconds">
+  <summary>
+    The time elapsed between the sending of the first API request and the time
+    the final (successfull) response was recorded. Includes all retries.
+  </summary>
+</histogram>
+
+<histogram name="TimeZone.TimeZoneRequest.Result" enum="TimeZoneRequestResult">
+  <summary>Result of TimeZoneRequest.</summary>
+</histogram>
+
+<histogram name="TimeZone.TimeZoneRequest.Retries">
+  <summary>Number of retries until the final response was recorded.</summary>
+</histogram>
+
 <histogram name="TopSites.NumberOfApplyBlacklist">
   <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
   <summary>The number of times TopSitesImpl::ApplyBlacklist is called.</summary>
@@ -26839,6 +27715,14 @@
   <summary>Whether the scroll is executed on main thread.</summary>
 </histogram>
 
+<histogram name="UMA.ClientIdMigrated" enum="BooleanMigrated">
+  <owner>asvitkine@chromium.org</owner>
+  <summary>
+    Recorded when the one-time UMA client id reset was performed (and the client
+    id of this user was migrated).
+  </summary>
+</histogram>
+
 <histogram name="UMA.CollectExternalEventsTime" units="milliseconds">
   <owner>asvitkine@chromium.org</owner>
   <summary>
@@ -26920,6 +27804,24 @@
   </summary>
 </histogram>
 
+<histogram name="UMA.MachineIdState" enum="UmaMachineIdState">
+  <owner>jwd@chromium.org</owner>
+  <summary>
+    Tracks if the machine ID is generated successfully and if it changes from
+    one run to the next. The machine ID is a 24-bit hash of machine
+    characteristics. It is expected to change if an install of Chrome is copied
+    to multiple machines. This check happens once per browser startup.
+  </summary>
+</histogram>
+
+<histogram name="UMA.MetricsIDsReset" enum="BooleanHit">
+  <owner>jwd@chromium.org</owner>
+  <summary>
+    A count of the number of times the metrics ids (client id and low entropy
+    source) have been reset due to a cloned install being detected.
+  </summary>
+</histogram>
+
 <histogram name="UMA.Perf.GetData" enum="GetPerfDataOutcome">
   <owner>asvitkine@chromium.org</owner>
   <summary>
@@ -27253,7 +28155,7 @@
 </histogram>
 
 <histogram name="Variations.SeedDateChange" enum="VariationsSeedDateChange">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>jwd@chromium.org</owner>
   <summary>
     Counts if a response from the variations server is the first response of the
     day or not. This is counted when a new valid seed or a 304 is received. The
@@ -28219,40 +29121,43 @@
 </histogram>
 
 <histogram name="WebRTC.DataChannelCounters" enum="DataChannelCounters">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>tommi@chromium.org</owner>
   <summary>
     Counters on creation, opening, and a few main attributes of data channels.
   </summary>
 </histogram>
 
 <histogram name="WebRTC.NumDataChannelsPerPeerConnection">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>tommi@chromium.org</owner>
   <summary>
     Number of data channels created per PeerConnection. Sample added to the
-    histogram when the PeerConnection is destroyed.
+    histogram when the PeerConnection is destroyed. Note that this is done
+    purely on the renderer side, so no sample will be generated when the
+    renderer process is destroyed (as in the fast shutdown path for the
+    renderer) before the PeerConnection is destroyed.
   </summary>
 </histogram>
 
 <histogram name="WebRTC.ReceivedAudioTrackDuration" units="milliseconds">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>perkj@chromium.org</owner>
   <summary>
-    Durations of audio tracks received over a PeerConnection. This metric is
-    generated based on the lifetime of an observer added for all received tracks
-    by content::RemoteMediaStreamImpl.
+    Durations of audio tracks received over a PeerConnection. The stopwatch
+    starts when the track first becomes connected, and ends when it is
+    disconnected or very soon thereafter.
   </summary>
 </histogram>
 
 <histogram name="WebRTC.ReceivedVideoTrackDuration" units="milliseconds">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>perkj@chromium.org</owner>
   <summary>
-    Durations of video tracks received over a PeerConnection. This metric is
-    generated based on the lifetime of an observer added for all received tracks
-    by content::RemoteMediaStreamImpl.
+    Durations of video tracks received over a PeerConnection. The stopwatch
+    starts when the track first becomes connected, and ends when it is
+    disconnected or very soon thereafter.
   </summary>
 </histogram>
 
 <histogram name="WebRTC.ReliableDataChannelMessageSize" units="bytes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>tommi@chromium.org</owner>
   <summary>
     Sizes of messages sent over reliable data channels. The size of an
     individual message is added to the histogram as a sample immediately when a
@@ -28260,8 +29165,26 @@
   </summary>
 </histogram>
 
+<histogram name="WebRTC.SentAudioTrackDuration" units="milliseconds">
+  <owner>perkj@chromium.org</owner>
+  <summary>
+    Durations of audio tracks sent over a PeerConnection. The stopwatch starts
+    when the track first becomes connected, and ends when it is disconnected or
+    very soon thereafter.
+  </summary>
+</histogram>
+
+<histogram name="WebRTC.SentVideoTrackDuration" units="milliseconds">
+  <owner>perkj@chromium.org</owner>
+  <summary>
+    Durations of video tracks sent over a PeerConnection. The stopwatch starts
+    when the track first becomes connected, and ends when it is disconnected or
+    very soon thereafter.
+  </summary>
+</histogram>
+
 <histogram name="WebRTC.UnreliableDataChannelMessageSize" units="bytes">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>perkj@chromium.org</owner>
   <summary>
     Sizes of messages sent over unreliable data channels. The size of an
     individual message is added to the histogram as a sample immediately when a
@@ -28270,10 +29193,31 @@
 </histogram>
 
 <histogram name="WebRTC.webkitApiCount" enum="JavaScriptAPIName">
-  <owner>Please list the metric's owners. Add more owner tags as needed.</owner>
+  <owner>tommi@chromium.org</owner>
   <summary>Counts number of calls to WebRTC APIs from JavaScript.</summary>
 </histogram>
 
+<histogram name="WebRTC.webkitApiCountPerSession" enum="JavaScriptAPIName">
+  <owner>tommi@chromium.org</owner>
+  <summary>
+    Counts number of calls to WebRTC APIs from JavaScript, once   per
+    &quot;session&quot; which is demarcated by the total number of MediaStreams
+    within a renderer process that are being sent over a PeerConnection
+    transitioning from or to 0.
+  </summary>
+</histogram>
+
+<histogram name="WebRTC.webkitApiCountUniqueByOrigin" enum="JavaScriptAPIName">
+  <obsolete>
+    Deprecated as of r253828 (27 Feb 2014).
+  </obsolete>
+  <owner>tommi@chromium.org</owner>
+  <summary>
+    Counts number of calls to WebRTC APIs from JavaScript, once per origin per
+    renderer process.
+  </summary>
+</histogram>
+
 <histogram name="Webstore.ExtensionInstallResult" enum="BooleanSuccess">
   <owner>jackhou@chromium.org</owner>
   <summary>
@@ -28441,6 +29385,14 @@
   <int value="3" label="LowMemory"/>
 </enum>
 
+<enum name="AndroidTabCloseUndoToastEvent" type="int">
+  <int value="0" label="Undo Shown (Cold)"/>
+  <int value="1" label="Undo Shown (Warm)"/>
+  <int value="2" label="Undo Pressed"/>
+  <int value="3" label="Undos Dismissed (Timeout)"/>
+  <int value="4" label="Undos Dismissed (Action)"/>
+</enum>
+
 <enum name="AppBannersDismissEvent" type="int">
   <int value="41" label="Error/unknown reason for dismissal"/>
   <int value="42" label="User opened the application after installing it"/>
@@ -28494,6 +29446,7 @@
   <int value="5" label="Manifest Error"/>
   <int value="6" label="Network Error"/>
   <int value="7" label="Server Error"/>
+  <int value="8" label="Cancelled"/>
 </enum>
 
 <enum name="AppLaunch" type="int">
@@ -28719,6 +29672,12 @@
   <int value="10" label="k192000Hz"/>
 </enum>
 
+<enum name="AudioTrackProcessingStates" type="int">
+  <int value="0" label="Enabled"/>
+  <int value="1" label="Disabled"/>
+  <int value="2" label="Processing in WebRTC"/>
+</enum>
+
 <enum name="AutocheckoutBubble" type="int">
   <obsolete>
     Deprecated as of 8/2013.
@@ -29071,6 +30030,11 @@
   <int value="1" label="Matched"/>
 </enum>
 
+<enum name="BooleanMigrated" type="int">
+  <int value="0" label="Not migrated"/>
+  <int value="1" label="Migrated"/>
+</enum>
+
 <enum name="BooleanOrphan" type="int">
   <int value="0" label="Non-orphan"/>
   <int value="1" label="Orphan"/>
@@ -29133,6 +30097,36 @@
   <int value="3" label="webgl"/>
 </enum>
 
+<enum name="CaptivePortalDetectResult" type="int">
+  <int value="0" label="INTERNET_CONNECTED"/>
+  <int value="1" label="NO_RESPONSE"/>
+  <int value="2" label="BEHIND_CAPTIVE_PORTAL"/>
+  <int value="3" label="NO_RESPONSE_HTTPS_LANDING_URL"/>
+  <int value="4" label="BEHIND_CAPTIVE_PORTAL_HTTPS_LANDING_URL"/>
+</enum>
+
+<enum name="CaptivePortalNotificationStatus" type="int">
+  <int value="0" label="UNKNOWN"/>
+  <int value="1" label="OFFLINE"/>
+  <int value="2" label="ONLINE"/>
+  <int value="3" label="PORTAL"/>
+  <int value="4" label="PROXY_AUTH_REQUIRED"/>
+</enum>
+
+<enum name="CaptivePortalNotificationUserAction" type="int">
+  <int value="0" label="CLICKED"/>
+  <int value="1" label="CLOSED"/>
+  <int value="2" label="IGNORED"/>
+</enum>
+
+<enum name="CaptivePortalStatus" type="int">
+  <int value="0" label="UNKNOWN"/>
+  <int value="1" label="OFFLINE"/>
+  <int value="2" label="ONLINE"/>
+  <int value="3" label="PORTAL"/>
+  <int value="4" label="PROXY_AUTH_REQUIRED"/>
+</enum>
+
 <enum name="CapturePixelFormat" type="int">
   <int value="0" label="UNKNOWN"/>
   <int value="1" label="I420"/>
@@ -29228,6 +30222,14 @@
   <int value="2" label="First service disabled"/>
 </enum>
 
+<enum name="ChromeOSColorProfile" type="int">
+  <summary>See ui/display/display_constants.h for the variation.</summary>
+  <int value="0" label="Standard"/>
+  <int value="1" label="Dynamic"/>
+  <int value="2" label="Movie"/>
+  <int value="3" label="Reading"/>
+</enum>
+
 <enum name="ChromeOSUserImageId" type="int">
   <summary>
     Indices of the default images as defined in
@@ -29265,6 +30267,65 @@
   <int value="2" label="Read Text"/>
 </enum>
 
+<enum name="CloudPrintAuthEventType" type="int">
+  <int value="0" label="AUTH_EVENT_ROBO_CREATE"/>
+  <int value="1" label="AUTH_EVENT_ROBO_SUCCEEDED"/>
+  <int value="2" label="AUTH_EVENT_ROBO_FAILED"/>
+  <int value="3" label="AUTH_EVENT_ROBO_JSON_ERROR"/>
+  <int value="4" label="AUTH_EVENT_ROBO_AUTH_ERROR"/>
+  <int value="5" label="AUTH_EVENT_AUTH_WITH_TOKEN"/>
+  <int value="6" label="AUTH_EVENT_AUTH_WITH_CODE"/>
+  <int value="7" label="AUTH_EVENT_TOKEN_RESPONSE"/>
+  <int value="8" label="AUTH_EVENT_REFRESH_REQUEST"/>
+  <int value="9" label="AUTH_EVENT_REFRESH_RESPONSE"/>
+  <int value="10" label="AUTH_EVENT_AUTH_ERROR"/>
+  <int value="11" label="AUTH_EVENT_NET_ERROR"/>
+</enum>
+
+<enum name="CloudPrintJobHandlerEventType" type="int">
+  <int value="0" label="JOB_HANDLER_CHECK_FOR_JOBS"/>
+  <int value="1" label="JOB_HANDLER_START"/>
+  <int value="2" label="JOB_HANDLER_PENDING_TASK"/>
+  <int value="3" label="JOB_HANDLER_PRINTER_UPDATE"/>
+  <int value="4" label="JOB_HANDLER_JOB_CHECK"/>
+  <int value="5" label="JOB_HANDLER_JOB_STARTED"/>
+  <int value="6" label="JOB_HANDLER_VALID_TICKET"/>
+  <int value="7" label="JOB_HANDLER_DATA"/>
+  <int value="8" label="JOB_HANDLER_SET_IN_PROGRESS"/>
+  <int value="9" label="JOB_HANDLER_SET_START_PRINTING"/>
+  <int value="10" label="JOB_HANDLER_START_SPOOLING"/>
+  <int value="11" label="JOB_HANDLER_SPOOLED"/>
+  <int value="12" label="JOB_HANDLER_JOB_COMPLETED"/>
+  <int value="13" label="JOB_HANDLER_INVALID_TICKET"/>
+  <int value="14" label="JOB_HANDLER_INVALID_DATA"/>
+</enum>
+
+<enum name="CloudPrintJobStatusType" type="int">
+  <int value="0" label="JOB_SUCCESS"/>
+  <int value="1" label="JOB_DOWNLOAD_FAILED"/>
+  <int value="2" label="JOB_VALIDATE_TICKET_FAILED"/>
+  <int value="3" label="JOB_FAILED"/>
+</enum>
+
+<enum name="CloudPrintNativeJobStatusType" type="int">
+  <int value="0" label="PRINT_JOB_STATUS_INVALID"/>
+  <int value="1" label="PRINT_JOB_STATUS_IN_PROGRESS"/>
+  <int value="2" label="PRINT_JOB_STATUS_ERROR"/>
+  <int value="3" label="PRINT_JOB_STATUS_COMPLETED"/>
+</enum>
+
+<enum name="CloudPrintUrlFetcherRequestType" type="int">
+  <int value="0" label="REQUEST_AUTH_CODE"/>
+  <int value="1" label="REQUEST_REGISTER"/>
+  <int value="2" label="REQUEST_UNREGISTER"/>
+  <int value="3" label="REQUEST_UPDATE_PRINTER"/>
+  <int value="4" label="REQUEST_UPDATE_JOB"/>
+  <int value="5" label="REQUEST_USER_MESSAGE"/>
+  <int value="6" label="REQUEST_TICKET"/>
+  <int value="7" label="REQUEST_DATA"/>
+  <int value="8" label="REQUEST_JOB_FETCH"/>
+</enum>
+
 <enum name="CoalescePotentialPackets" type="int">
   <int value="0" label="No Advantage"/>
   <int value="1" label="Header packets Only"/>
@@ -29519,6 +30580,22 @@
   <int value="3" label="Cancel"/>
 </enum>
 
+<enum name="DevicesPageEvents" type="int">
+  <int value="0" label="OPENED"/>
+  <int value="1" label="LOG_IN_STARTED_FROM_REGISTER_PROMO"/>
+  <int value="2" label="LOG_IN_STARTED_FROM_DEVICE_LIST_PROMO"/>
+  <int value="3" label="ADD_PRINTER_CLICKED"/>
+  <int value="4" label="REGISTER_CLICKED"/>
+  <int value="5" label="REGISTER_CONFIRMED"/>
+  <int value="6" label="REGISTER_SUCCESS"/>
+  <int value="7" label="REGISTER_CANCEL"/>
+  <int value="8" label="REGISTER_FAILURE"/>
+  <int value="9" label="MANAGE_CLICKED"/>
+  <int value="10" label="REGISTER_CANCEL_ON_PRINTER"/>
+  <int value="11" label="REGISTER_TIMEOUT"/>
+  <int value="12" label="LOG_IN_STARTED_FROM_REGISTER_OVERLAY_PROMO"/>
+</enum>
+
 <enum name="DiagnosticsRecoveryRun" type="int">
   <int value="0" label="Recovery not run"/>
   <int value="1" label="Recovery run because of crash"/>
@@ -30170,6 +31247,9 @@
   <int value="22" label="Deprovisioned device">
     Enrollment failed because the administrator has deprovisioned the device.
   </int>
+  <int value="23" label="Domain mismatch">
+    Enrollment failed because the device belongs to a different domain.
+  </int>
 </enum>
 
 <enum name="EnterprisePolicies" type="int">
@@ -31446,6 +32526,7 @@
   <int value="701" label="BLUETOOTH_GETDEVICE"/>
   <int value="702" label="GCM_UNREGISTER"/>
   <int value="703" label="FILEBROWSERPRIVATE_REQUESTDRIVESHARE"/>
+  <int value="704" label="METRICSPRIVATE_RECORDSPARSEVALUE"/>
 </enum>
 
 <enum name="ExtensionInstallCause" type="int">
@@ -31556,6 +32637,71 @@
   <int value="28" label="SOCKET_SPECIFIC_HOSTS"/>
 </enum>
 
+<enum name="ExtensionPermission2" type="int">
+<!-- Generated from ../../../extensions/common/permissions/permission_message.h -->
+
+  <int value="0" label="kUnknown"/>
+  <int value="1" label="kNone"/>
+  <int value="2" label="kBookmarks"/>
+  <int value="3" label="kGeolocation"/>
+  <int value="4" label="kBrowsingHistory"/>
+  <int value="5" label="kTabs"/>
+  <int value="6" label="kManagement"/>
+  <int value="7" label="kDebugger"/>
+  <int value="8" label="kDesktopCapture"/>
+  <int value="9" label="kHid"/>
+  <int value="10" label="kHosts1"/>
+  <int value="11" label="kHosts2"/>
+  <int value="12" label="kHosts3"/>
+  <int value="13" label="kHosts4OrMore"/>
+  <int value="14" label="kHostsAll"/>
+  <int value="15" label="kFullAccess"/>
+  <int value="16" label="kClipboard"/>
+  <int value="17" label="kTtsEngine"/>
+  <int value="18" label="kContentSettings"/>
+  <int value="19" label="kPrivacy"/>
+  <int value="20" label="kManagedMode"/>
+  <int value="21" label="kInput"/>
+  <int value="22" label="kAudioCapture"/>
+  <int value="23" label="kVideoCapture"/>
+  <int value="24" label="kDownloads"/>
+  <int value="25" label="kFileSystemWrite"/>
+  <int value="26" label="kMediaGalleriesAllGalleriesRead"/>
+  <int value="27" label="kSerial"/>
+  <int value="28" label="kSocketAnyHost"/>
+  <int value="29" label="kSocketDomainHosts"/>
+  <int value="30" label="kSocketSpecificHosts"/>
+  <int value="31" label="kBluetooth"/>
+  <int value="32" label="kUsb"/>
+  <int value="33" label="kSystemIndicator"/>
+  <int value="34" label="kUsbDevice"/>
+  <int value="35" label="kMediaGalleriesAllGalleriesCopyTo"/>
+  <int value="36" label="kSystemInfoDisplay"/>
+  <int value="37" label="kNativeMessaging"/>
+  <int value="38" label="kSyncFileSystem"/>
+  <int value="39" label="kAudio"/>
+  <int value="40" label="kFavicon"/>
+  <int value="41" label="kMusicManagerPrivate"/>
+  <int value="42" label="kWebConnectable"/>
+  <int value="43" label="kActivityLogPrivate"/>
+  <int value="44" label="kBluetoothDevices"/>
+  <int value="45" label="kDownloadsOpen"/>
+  <int value="46" label="kNetworkingPrivate"/>
+  <int value="47" label="kDeclarativeWebRequest"/>
+  <int value="48" label="kFileSystemDirectory"/>
+  <int value="49" label="kFileSystemWriteDirectory"/>
+  <int value="50" label="kSignedInDevices"/>
+  <int value="51" label="kWallpaper"/>
+  <int value="52" label="kNetworkState"/>
+  <int value="53" label="kHomepage"/>
+  <int value="54" label="kSearchProvider"/>
+  <int value="55" label="kStartupPages"/>
+  <int value="56" label="kMediaGalleriesAllGalleriesDelete"/>
+  <int value="57" label="kScreenlockPrivate"/>
+  <int value="58" label="kOverrideBookmarksUI"/>
+  <int value="59" label="kAutomation"/>
+</enum>
+
 <enum name="ExtensionServiceVerifyAllSuccess" type="int">
   <int value="0" label="VERIFY_ALL_BOOTSTRAP_SUCCESS"/>
   <int value="1" label="VERIFY_ALL_BOOTSTRAP_FAILURE"/>
@@ -31638,6 +32784,7 @@
   <int value="5" label="Bad command code in message"/>
   <int value="6" label="Bad result code in message"/>
   <int value="7" label="Bad feature index in message"/>
+  <int value="8" label="Maximum value of 0 in message"/>
 </enum>
 
 <enum name="ExternalDisplaySendResult" type="int">
@@ -32453,6 +33600,26 @@
   <int value="1" label="Close command"/>
   <int value="2" label="Heartbeat failure"/>
   <int value="3" label="Socket failure"/>
+  <int value="4" label="Network change"/>
+</enum>
+
+<enum name="GCMEndpoints" type="int">
+  <int value="0" label="mtalk.google.com:5228"/>
+  <int value="1" label="mtalk.google.com:443"/>
+</enum>
+
+<enum name="GCMInvalidationsIncomingMessageStatus" type="int">
+  <int value="0" label="Success"/>
+  <int value="1" label="GCM message's content missing or empty"/>
+  <int value="2" label="Base64Decode failed"/>
+  <int value="3" label="Parsing protobuf failed"/>
+</enum>
+
+<enum name="GCMInvalidationsOutgoingMessageStatus" type="int">
+  <int value="0" label="Success"/>
+  <int value="1" label="Message was discarded"/>
+  <int value="2" label="Access token request failed"/>
+  <int value="3" label="HTTP Post failed"/>
 </enum>
 
 <enum name="GCMRegistrationRequestStatus" type="int">
@@ -32583,6 +33750,13 @@
   <int value="6" label="UNSET"/>
 </enum>
 
+<enum name="GoogleNowCardTypeId" type="int">
+  <summary>
+    Represents a card type ID. See cardTypeId in
+    chrome/browser/resources/google_now/background.js.
+  </summary>
+</enum>
+
 <enum name="GoogleNowEvent" type="int">
   <summary>
     Events in Google Now component extension. See GoogleNowEvent in
@@ -32599,6 +33773,9 @@
   <int value="8" label="DELETED_SHOW_WELCOME_TOAST"/>
   <int value="9" label="STOPPED"/>
   <int value="10" label="DELETED_USER_SUPPRESSED"/>
+  <int value="11" label="SIGNED_OUT"/>
+  <int value="12" label="NOTIFICATION_DISABLED"/>
+  <int value="13" label="GOOGLE_NOW_DISABLED"/>
 </enum>
 
 <enum name="GoogleServiceAuthError" type="int">
@@ -33077,6 +34254,11 @@
   <int value="50" label="CRASH"/>
 </enum>
 
+<enum name="InvalidationNetworkChannel" type="int">
+  <int value="0" label="PushClientChannel"/>
+  <int value="1" label="GCMNetworkChannel"/>
+</enum>
+
 <enum name="IPV6ProbeResult" type="int">
   <int value="0" label="IPV6_CANNOT_CREATE_SOCKETS"/>
   <int value="1" label="IPV6_CAN_CREATE_SOCKETS"/>
@@ -33845,13 +35027,28 @@
 
 <enum name="ManagedUserPasswordChange" type="int">
   <int value="0" label="OK_MANAGER">Changed in manager session</int>
-  <int value="1" label="OK_MANGED">Changed in managed user session</int>
+  <int value="1" label="OK_MANGED">Changed in supervised user session</int>
   <int value="2" label="FAILED_NO_MASTER_KEY">Master key not found</int>
-  <int value="3" label="FAILED_NO_SIGNATURE_KEY">Signature key not found</int>
+  <int value="3" label="FAILED_NO_SIGNATURE_KEY">
+    Signature or encryption key not found
+  </int>
   <int value="4" label="FAILED_NO_PASSWORD_DATA">Password data not found</int>
   <int value="5" label="FAILED_MASTER_KEY_FAILURE">
     Manager key authorization failed
   </int>
+  <int value="6" label="FAILED_LOAD_DATA_FAILURE">
+    Could not load new password data upon supervised user signin
+  </int>
+  <int value="7" label="FAILED_INCOMPLETE_DATA_FAILURE">
+    Incomplete password data loaded upon supervised user signin.
+  </int>
+  <int value="8" label="FAILED_AUTHENTICATION_FAILURE">
+    Authentication failure while changing password during supervised user
+    signin.
+  </int>
+  <int value="9" label="FAILED_STORE_DATA">
+    Could not store new password data for supervised user.
+  </int>
 </enum>
 
 <enum name="MappedCSSProperties" type="int">
@@ -35514,6 +36711,11 @@
   <int value="3" label="(non-invalidated) replies received"/>
 </enum>
 
+<enum name="OmniboxUserTextCleared" type="int">
+  <int value="0" label="cleared by editing"/>
+  <int value="1" label="cleared with escape"/>
+</enum>
+
 <enum name="OmniboxZeroSuggestRequests" type="int">
   <int value="1" label="requests sent"/>
   <int value="2" label="requests invalidated"/>
@@ -35876,7 +37078,149 @@
              / form submit succeeded"/>
 </enum>
 
+<enum name="PasswordManagerActionsTakenV3" type="int">
+  <summary>
+    The value is a combination of three different options - what did the
+    password manager do, what did the user do, and was the form submitted (and
+    submitted successfully or not). The meaning of each value can be determined
+    from the values in chrome/browser/password_manager/password_form_manager.h
+  </summary>
+  <int value="0"
+      label="manager did nothing / user did nothing / form not submitted"/>
+  <int value="1"
+      label="manager did nothing / user chose a value / form not submitted"/>
+  <int value="2"
+      label="manager did nothing / user chose a value from PSL / form not
+             submitted"/>
+  <int value="3"
+      label="manager did nothing / user typed in password / form not
+             submitted"/>
+  <int value="4"
+      label="manager did nothing / user typed in username and password / form
+             not submitted"/>
+  <int value="5"
+      label="manager filled the fields / user did nothing / form not
+             submitted"/>
+  <int value="6"
+      label="manager filled the fields / user chose a value / form not
+             submitted"/>
+  <int value="7"
+      label="manager filled the fields / user chose a value from PSL / form
+             not submitted"/>
+  <int value="8"
+      label="manager filled the fields / user typed in password / form not
+             submitted"/>
+  <int value="9"
+      label="manager filled the fields / user typed in username and password
+             / form not submitted"/>
+  <int value="10"
+      label="manager did nothing (site was blacklisted) / user did nothing /
+             form not submitted"/>
+  <int value="11"
+      label="manager did nothing (site was blacklisted) / user chose a value
+             / form not submitted (this value shouldn't be possible)"/>
+  <int value="12"
+      label="manager did nothing (site was blacklisted) / user chose a value
+             from PSL / form not submitted (this value shouldn't be possible)"/>
+  <int value="13"
+      label="manager did nothing (site was blacklisted) / user typed in
+             password / form not submitted"/>
+  <int value="14"
+      label="manager did nothing (site was blacklisted) / user typed in
+             username and password / form not submitted"/>
+  <int value="15"
+      label="manager did nothing / user did nothing / form submit failed"/>
+  <int value="16"
+      label="manager did nothing / user chose a value / form submit failed"/>
+  <int value="17"
+      label="manager did nothing / user chose a value from psl / form submit
+             failed"/>
+  <int value="18"
+      label="manager did nothing / user typed in password / form submit
+             failed"/>
+  <int value="19"
+      label="manager did nothing / user typed in username and password / form
+             submit failed"/>
+  <int value="20"
+      label="manager filled the fields / user did nothing / form submit
+             failed"/>
+  <int value="21"
+      label="manager filled the fields / user chose a value / form submit
+             failed"/>
+  <int value="22"
+      label="manager filled the fields / user chose a value from psl / form
+             submit failed"/>
+  <int value="23"
+      label="manager filled the fields / user typed in pasword / form submit
+             failed"/>
+  <int value="24"
+      label="manager filled the fields / user typed in username and pasword /
+             form submit failed"/>
+  <int value="25"
+      label="manager did nothing (site was blacklisted) / user did nothing /
+             form submit failed"/>
+  <int value="26"
+      label="manager did nothing (site was blacklisted) / user chose a value
+             / form submit failed (this value shouldn't be possible)"/>
+  <int value="27"
+      label="manager did nothing (site was blacklisted) / user chose a value
+             from psl / form submit failed (this value shouldn't be possible)"/>
+  <int value="28"
+      label="manager did nothing (site was blacklisted) / user typed in
+             password / form submit failed"/>
+  <int value="29"
+      label="manager did nothing (site was blacklisted) / user typed in
+             username and password / form submit failed"/>
+  <int value="30"
+      label="manager did nothing / user did nothing / form submit succeeded"/>
+  <int value="31"
+      label="manager did nothing / user chose a value / form submit succeeded"/>
+  <int value="32"
+      label="manager did nothing / user chose a value from psl / form submit
+             succeeded"/>
+  <int value="33"
+      label="manager did nothing / user typed in password / form submit
+             succeeded"/>
+  <int value="34"
+      label="manager did nothing / user typed in username and password / form
+             submit succeeded"/>
+  <int value="35"
+      label="manager filled the fields / user did nothing / form submit
+             succeeded"/>
+  <int value="36"
+      label="manager filled the fields / user chose a value / form submit
+             succeeded"/>
+  <int value="37"
+      label="manager filled the fields / user chose a value from psl / form
+             submit succeeded"/>
+  <int value="38"
+      label="manager filled the fields / user typed in password / form submit
+             succeeded"/>
+  <int value="39"
+      label="manager filled the fields / user typed in username and password
+             / form submit succeeded"/>
+  <int value="40"
+      label="manager did nothing (site was blacklisted) / user did nothing /
+             form submit succeeded"/>
+  <int value="41"
+      label="manager did nothing (site was blacklisted) / user chose a value
+             / form submit succeeded (this value shouldn't be possible)"/>
+  <int value="42"
+      label="manager did nothing (site was blacklisted) / user chose a value
+             from psl / form submit succeeded (this value shouldn't be
+             possible)"/>
+  <int value="43"
+      label="manager did nothing (site was blacklisted) / user typed in
+             password / form submit succeeded"/>
+  <int value="44"
+      label="manager did nothing (site was blacklisted) / user typed in
+             username and password / form submit succeeded"/>
+</enum>
+
 <enum name="PasswordManagerActionsTakenWithPsl" type="int">
+  <obsolete>
+    Deprecated as of 3/18/2014. See PasswordManagerActionsTakenV3.
+  </obsolete>
   <summary>
     The value is a combination of three different options - what did the
     password manager do, what did the user do, and was the form submitted (and
@@ -36059,9 +37403,11 @@
   <int value="138418890" label="PPB_Memory(Dev);0.1"/>
   <int value="153443470" label="PPB_URLResponseInfo;1.0"/>
   <int value="153532707" label="PPB_Buffer(Dev);0.4"/>
+  <int value="156766028" label="PPB_UMA_Private;0.3"/>
   <int value="162107265" label="PPB_NetworkMonitor;1.0"/>
   <int value="180906214" label="PPB_Instance_Private;0.1"/>
   <int value="221802429" label="PPB_URLUtil(Dev);0.7"/>
+  <int value="225125520" label="PPB_Find(Private);0.3"/>
   <int value="226206264" label="PPB_FileRef;1.1"/>
   <int value="229560990" label="PPB_Var(Deprecated);0.3"/>
   <int value="250764663" label="PPB_Graphics2D(Dev);0.2"/>
@@ -36345,6 +37691,14 @@
   <int value="4" label="Safe Spring Charger"/>
 </enum>
 
+<enum name="PowerwashDialogViewType" type="int">
+  <int value="0" label="Invoked on settings page"/>
+  <int value="1" label="Shortcut. Confirmation for powerwash only."/>
+  <int value="2" label="Shortcut. Confirmation for powerwash and rollback."/>
+  <int value="3" label="Shortcut. Offer. Rollback unavailable."/>
+  <int value="4" label="Shortcut. Offer. Rollback available."/>
+</enum>
+
 <enum name="PreconnectedNavigation" type="int">
   <int value="0" label="No recent pre-connect to the page"/>
   <int value="1" label="Page nav. preceded by a pre-connect"/>
@@ -36691,6 +38045,95 @@
   <int value="3" label="tapdown + tapunconfirmed"/>
 </enum>
 
+<enum name="PrinterServiceEventType" type="int">
+  <int value="0" label="Printer added"/>
+  <int value="1" label="Page displayed"/>
+</enum>
+
+<enum name="PrintPreviewFailureType" type="int">
+  <int value="0" label="No error"/>
+  <int value="1" label="Bad settings from print preview tab"/>
+  <int value="2" label="Copy metadata failed"/>
+  <int value="3" label="Metafile init failed"/>
+  <int value="4" label="0-page preview"/>
+  <int value="5" label="Mac draft metafile init failed"/>
+  <int value="6" label="PreviewPageRendered with no metafile"/>
+  <int value="7" label="UpdatePrintSettings failed"/>
+  <int value="8" label="Received bad printer settings"/>
+</enum>
+
+<enum name="PrintPreviewFontTypeType" type="int">
+  <int value="0" label="TYPE1"/>
+  <int value="1" label="TYPE1_CID"/>
+  <int value="2" label="CFF"/>
+  <int value="3" label="TRUETYPE"/>
+  <int value="4" label="OTHER"/>
+  <int value="5" label="NOT_EMBEDDABLE"/>
+</enum>
+
+<enum name="PrintPreviewGcpPromoBuckets" type="int">
+  <int value="0" label="PROMO_SHOWN"/>
+  <int value="1" label="PROMO_CLOSED"/>
+  <int value="2" label="GCP_PROMO_BUCKET_BOUNDARY"/>
+</enum>
+
+<enum name="PrintPreviewHelperEvents" type="int">
+  <int value="0" label="PREVIEW_EVENT_REQUESTED"/>
+  <int value="1" label="PREVIEW_EVENT_CACHE_HIT"/>
+  <int value="2" label="PREVIEW_EVENT_CREATE_DOCUMENT"/>
+  <int value="3" label="PREVIEW_EVENT_NEW_SETTINGS"/>
+</enum>
+
+<enum name="PrintPreviewPrintDestinationBuckets" type="int">
+  <int value="0" label="DESTINATION_SHOWN"/>
+  <int value="1" label="DESTINATION_CLOSED_CHANGED"/>
+  <int value="2" label="DESTINATION_CLOSED_UNCHANGED"/>
+  <int value="3" label="SIGNIN_PROMPT"/>
+  <int value="4" label="SIGNIN_TRIGGERED"/>
+  <int value="5" label="PRIVET_DUPLICATE_SELECTED"/>
+  <int value="6" label="CLOUD_DUPLICATE_SELECTED"/>
+  <int value="7" label="REGISTER_PROMO_SHOWN"/>
+  <int value="8" label="REGISTER_PROMO_SELECTED"/>
+</enum>
+
+<enum name="PrintPreviewUserActionType" type="int">
+  <int value="0" label="PRINT_TO_PRINTER"/>
+  <int value="1" label="PRINT_TO_PDF"/>
+  <int value="2" label="CANCEL"/>
+  <int value="3" label="FALLBACK_TO_ADVANCED_SETTINGS_DIALOG"/>
+  <int value="4" label="PREVIEW_FAILED"/>
+  <int value="5" label="PREVIEW_STARTED"/>
+  <int value="6" label="INITIATOR_TAB_CRASHED"/>
+  <int value="7" label="INITIATOR_TAB_CLOSED"/>
+  <int value="8" label="PRINT_WITH_CLOUD_PRINT"/>
+  <int value="9" label="PRINT_WITH_PRIVET"/>
+</enum>
+
+<enum name="PrintSettings" type="int">
+  <int value="0" label="LANDSCAPE"/>
+  <int value="1" label="PORTRAIT"/>
+  <int value="2" label="COLOR"/>
+  <int value="3" label="BLACK_AND_WHITE"/>
+  <int value="4" label="COLLATE"/>
+  <int value="5" label="SIMPLEX"/>
+  <int value="6" label="DUPLEX"/>
+  <int value="7" label="TOTAL"/>
+  <int value="8" label="HEADERS_AND_FOOTERS"/>
+  <int value="9" label="CSS_BACKGROUND"/>
+  <int value="10" label="SELECTION_ONLY"/>
+</enum>
+
+<enum name="PrivetNotificationsEvent" type="int">
+  <int value="0" label="PRIVET_SERVICE_STARTED"/>
+  <int value="1" label="PRIVET_LISTER_STARTED"/>
+  <int value="2" label="PRIVET_DEVICE_CHANGED"/>
+  <int value="3" label="PRIVET_INFO_DONE"/>
+  <int value="4" label="PRIVET_NOTIFICATION_SHOWN"/>
+  <int value="5" label="PRIVET_NOTIFICATION_CANCELED"/>
+  <int value="6" label="PRIVET_NOTIFICATION_CLICKED"/>
+  <int value="7" label="PRIVET_DISABLE_NOTIFICATIONS_CLICKED"/>
+</enum>
+
 <enum name="ProfileAddNewUser" type="int">
   <int value="0" label="Add new user from icon menu"/>
   <int value="1" label="Add new user from title bar menu"/>
@@ -37088,6 +38531,21 @@
   <int value="6" label="CANCELLED"/>
 </enum>
 
+<enum name="QuicSessionErrorCodes" type="int">
+  <int value="0" label="CONNECTING_SOCKET"/>
+  <int value="1" label="SETTING_RECEIVE_BUFFER"/>
+  <int value="2" label="SETTING_SEND_BUFFER"/>
+</enum>
+
+<enum name="QuicSessionLocations" type="int">
+  <int value="0" label="DESTRUCTOR"/>
+  <int value="1" label="ADD_OBSERVER"/>
+  <int value="2" label="TRY_CREATE_STREAM"/>
+  <int value="3" label="CREATE_OUTGOING_RELIABLE_STREAM"/>
+  <int value="4" label="NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER"/>
+  <int value="5" label="NOTIFY_FACTORY_OF_SESSION_CLOSED"/>
+</enum>
+
 <enum name="RapporDiscardReason" type="int">
   <int value="0" label="Upload Success"/>
   <int value="1" label="Upload Rejected"/>
@@ -37101,6 +38559,67 @@
   <int value="3" label="Show More"/>
 </enum>
 
+<enum name="RenderViewContextMenuItem" type="int">
+  <int value="0" label="IDC_CONTENT_CONTEXT_CUSTOM_FIRST"/>
+  <int value="1" label="IDC_EXTENSIONS_CONTEXT_CUSTOM_FIRST"/>
+  <int value="2" label="IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_FIRST"/>
+  <int value="3" label="IDC_CONTENT_CONTEXT_OPENLINKNEWTAB"/>
+  <int value="4" label="IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW"/>
+  <int value="5" label="IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD"/>
+  <int value="6" label="IDC_CONTENT_CONTEXT_SAVELINKAS"/>
+  <int value="7" label="IDC_CONTENT_CONTEXT_SAVEAVAS"/>
+  <int value="8" label="IDC_CONTENT_CONTEXT_SAVEIMAGEAS"/>
+  <int value="9" label="IDC_CONTENT_CONTEXT_COPYLINKLOCATION"/>
+  <int value="10" label="IDC_CONTENT_CONTEXT_COPYIMAGELOCATION"/>
+  <int value="11" label="IDC_CONTENT_CONTEXT_COPYAVLOCATION"/>
+  <int value="12" label="IDC_CONTENT_CONTEXT_COPYIMAGE"/>
+  <int value="13" label="IDC_CONTENT_CONTEXT_OPENIMAGENEWTAB"/>
+  <int value="14" label="IDC_CONTENT_CONTEXT_OPENAVNEWTAB"/>
+  <int value="15" label="IDC_CONTENT_CONTEXT_PLAYPAUSE"/>
+  <int value="16" label="IDC_CONTENT_CONTEXT_MUTE"/>
+  <int value="17" label="IDC_CONTENT_CONTEXT_LOOP"/>
+  <int value="18" label="IDC_CONTENT_CONTEXT_CONTROLS"/>
+  <int value="19" label="IDC_CONTENT_CONTEXT_ROTATECW"/>
+  <int value="20" label="IDC_CONTENT_CONTEXT_ROTATECCW"/>
+  <int value="21" label="IDC_BACK"/>
+  <int value="22" label="IDC_FORWARD"/>
+  <int value="23" label="IDC_SAVE_PAGE"/>
+  <int value="24" label="IDC_RELOAD"/>
+  <int value="25" label="IDC_CONTENT_CONTEXT_RELOAD_PACKAGED_APP"/>
+  <int value="26" label="IDC_CONTENT_CONTEXT_RESTART_PACKAGED_APP"/>
+  <int value="27" label="IDC_PRINT"/>
+  <int value="28" label="IDC_VIEW_SOURCE"/>
+  <int value="29" label="IDC_CONTENT_CONTEXT_INSPECTELEMENT"/>
+  <int value="30" label="IDC_CONTENT_CONTEXT_INSPECTBACKGROUNDPAGE"/>
+  <int value="31" label="IDC_CONTENT_CONTEXT_VIEWPAGEINFO"/>
+  <int value="32" label="IDC_CONTENT_CONTEXT_TRANSLATE"/>
+  <int value="33" label="IDC_CONTENT_CONTEXT_RELOADFRAME"/>
+  <int value="34" label="IDC_CONTENT_CONTEXT_VIEWFRAMESOURCE"/>
+  <int value="35" label="IDC_CONTENT_CONTEXT_VIEWFRAMEINFO"/>
+  <int value="36" label="IDC_CONTENT_CONTEXT_UNDO"/>
+  <int value="37" label="IDC_CONTENT_CONTEXT_REDO"/>
+  <int value="38" label="IDC_CONTENT_CONTEXT_CUT"/>
+  <int value="39" label="IDC_CONTENT_CONTEXT_COPY"/>
+  <int value="40" label="IDC_CONTENT_CONTEXT_PASTE"/>
+  <int value="41" label="IDC_CONTENT_CONTEXT_PASTE_AND_MATCH_STYLE"/>
+  <int value="42" label="IDC_CONTENT_CONTEXT_DELETE"/>
+  <int value="43" label="IDC_CONTENT_CONTEXT_SELECTALL"/>
+  <int value="44" label="IDC_CONTENT_CONTEXT_SEARCHWEBFOR"/>
+  <int value="45" label="IDC_CONTENT_CONTEXT_GOTOURL"/>
+  <int value="46" label="IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS"/>
+  <int value="47" label="IDC_CONTENT_CONTEXT_PROTOCOL_HANDLER_SETTINGS"/>
+  <int value="48" label="IDC_CONTENT_CONTEXT_ADDSEARCHENGINE"/>
+  <int value="49" label="IDC_CONTENT_CONTEXT_SPEECH_INPUT_FILTER_PROFANITIES"/>
+  <int value="50" label="IDC_CONTENT_CONTEXT_SPEECH_INPUT_ABOUT"/>
+  <int value="51" label="IDC_SPEECH_INPUT_MENU"/>
+  <int value="52" label="IDC_CONTENT_CONTEXT_OPENLINKWITH"/>
+  <int value="53" label="IDC_CHECK_SPELLING_WHILE_TYPING"/>
+  <int value="54" label="IDC_SPELLCHECK_MENU"/>
+  <int value="55" label="IDC_CONTENT_CONTEXT_SPELLING_TOGGLE"/>
+  <int value="56" label="IDC_SPELLCHECK_LANGUAGES_FIRST"/>
+  <int value="57" label="IDC_CONTENT_CONTEXT_SEARCHWEBFORIMAGE"/>
+</enum>
+
 <enum name="ResolutionCategory" type="int">
   <int value="0" label="RESOLVE_SUCCESS"/>
   <int value="1" label="RESOLVE_FAIL"/>
@@ -37309,6 +38828,20 @@
   <int value="7" label="BACKUP_NETWORK_SUCCESS"/>
 </enum>
 
+<enum name="SBClientDetectionPreClassificationCheckFail" type="int">
+  <int value="0" label="PROXY_FETCH"/>
+  <int value="1" label="PRIVATE_IP"/>
+  <int value="2" label="OFF_THE_RECORD"/>
+  <int value="3" label="MATCH_CSD_WHITELIST"/>
+  <int value="4" label="TOO_MANY_REPORTS"/>
+  <int value="5" label="UNSUPPORTED_MIME_TYPE"/>
+  <int value="6" label="NO_DATABASE_MANAGER"/>
+  <int value="7" label="KILLSWITCH"/>
+  <int value="8" label="CANCEL"/>
+  <int value="9" label="RESULT_FROM_CACHE"/>
+  <int value="10" label="NOT_HTTP_URL"/>
+</enum>
+
 <enum name="SBClientDownloadCheckDownloadStats" type="int">
   <int value="0" label="INVALID_URL"/>
   <int value="1" label="SB_DISABLED"/>
@@ -37388,15 +38921,6 @@
   <int value="7" label="MODEL_INVALID_VERSION_NUMBER"/>
 </enum>
 
-<enum name="SBClientPhishingPreClassificationCheckFail" type="int">
-  <int value="0" label="PROXY_FETCH"/>
-  <int value="1" label="PRIVATE_IP"/>
-  <int value="2" label="OFF_THE_RECORD"/>
-  <int value="3" label="MATCH_CSD_WHITELIST"/>
-  <int value="4" label="TOO_MANY_REPORTS"/>
-  <int value="5" label="UNSUPPORTED_MIME_TYPE"/>
-</enum>
-
 <enum name="SBClientPhishingScorerCreationStatus" type="int">
   <int value="0" label="SUCCESS"/>
   <int value="1" label="MODEL_OPEN_FAIL"/>
@@ -37479,6 +39003,46 @@
   <int value="33" label="NONE"/>
 </enum>
 
+<enum name="ServiceProcessEventType" type="int">
+  <int value="0" label="SERVICE_EVENT_INITIALIZE"/>
+  <int value="1" label="SERVICE_EVENT_ENABLED_ON_LAUNCH"/>
+  <int value="2" label="SERVICE_EVENT_ENABLE"/>
+  <int value="3" label="SERVICE_EVENT_DISABLE"/>
+  <int value="4" label="SERVICE_EVENT_DISABLE_BY_POLICY"/>
+  <int value="5" label="SERVICE_EVENT_LAUNCH"/>
+  <int value="6" label="SERVICE_EVENT_LAUNCHED"/>
+  <int value="7" label="SERVICE_EVENT_LAUNCH_FAILED"/>
+  <int value="8" label="SERVICE_EVENT_CHANNEL_CONNECTED"/>
+  <int value="9" label="SERVICE_EVENT_CHANNEL_ERROR"/>
+  <int value="10" label="SERVICE_EVENT_INFO_REQUEST"/>
+  <int value="11" label="SERVICE_EVENT_INFO_REPLY"/>
+  <int value="12" label="SERVICE_EVENT_HISTOGRAMS_REQUEST"/>
+  <int value="13" label="SERVICE_EVENT_HISTOGRAMS_REPLY"/>
+  <int value="14" label="SERVICE_PRINTERS_REQUEST"/>
+  <int value="15" label="SERVICE_PRINTERS_REPLY"/>
+</enum>
+
+<enum name="ServicesCustomizationLoadResult" type="int">
+  <int value="0" label="Manifest loaded successfully"/>
+  <int value="1" label="Manifest not found on server"/>
+  <int value="2" label="Manifest parsing error"/>
+  <int value="3" label="Failed to load manifest after N retries"/>
+</enum>
+
+<enum name="ServiceUtilityProcessHostEventType" type="int">
+  <int value="0" label="SERVICE_UTILITY_STARTED"/>
+  <int value="1" label="SERVICE_UTILITY_DISCONNECTED"/>
+  <int value="2" label="SERVICE_UTILITY_METAFILE_REQUEST"/>
+  <int value="3" label="SERVICE_UTILITY_METAFILE_SUCCEEDED"/>
+  <int value="4" label="SERVICE_UTILITY_METAFILE_FAILED"/>
+  <int value="5" label="SERVICE_UTILITY_CAPS_REQUEST"/>
+  <int value="6" label="SERVICE_UTILITY_CAPS_SUCCEEDED"/>
+  <int value="7" label="SERVICE_UTILITY_CAPS_FAILED"/>
+  <int value="8" label="SERVICE_UTILITY_SEMANTIC_CAPS_REQUEST"/>
+  <int value="9" label="SERVICE_UTILITY_SEMANTIC_CAPS_SUCCEEDED"/>
+  <int value="10" label="SERVICE_UTILITY_SEMANTIC_CAPS_FAILED"/>
+</enum>
+
 <enum name="SessionStartupPref" type="int">
   <int value="0" label="Open home page (unused)"/>
   <int value="1" label="Continue from last opened pages"/>
@@ -38765,6 +40329,21 @@
   <int value="9" label="No syn data + probe failed"/>
 </enum>
 
+<enum name="TimeZoneRequestEvent" type="int">
+  <int value="0" label="Request start"/>
+  <int value="1" label="Response success"/>
+  <int value="2" label="Response not OK"/>
+  <int value="3" label="Response empty"/>
+  <int value="4" label="Response malformed"/>
+</enum>
+
+<enum name="TimeZoneRequestResult" type="int">
+  <int value="0" label="Success"/>
+  <int value="1" label="Failure"/>
+  <int value="2" label="Server error"/>
+  <int value="3" label="Request is cancelled."/>
+</enum>
+
 <enum name="TLSRenegotiationPatched" type="int">
   <int value="0" label="Not renegotiation patched"/>
   <int value="1" label="Renegotiation patched"/>
@@ -38909,6 +40488,13 @@
   <int value="1" label="Init task completed first"/>
 </enum>
 
+<enum name="UmaMachineIdState" type="int">
+  <int value="0" label="ID generation failed"/>
+  <int value="1" label="No stored value"/>
+  <int value="2" label="Machine ID changed"/>
+  <int value="3" label="Machine ID unchanged"/>
+</enum>
+
 <enum name="UmaUploadResponseStatus" type="int">
   <int value="0" label="Unknown failure"/>
   <int value="1" label="Success"/>
@@ -39383,6 +40969,17 @@
 
 <fieldtrials>
 
+<fieldtrial name="ActiveNetworkState">
+  <group name="Offline"
+      label="network manager thinks that the active network is offline"/>
+  <group name="Online"
+      label="network manager thinks that the active network is online"/>
+  <group name="RestrictedPool"
+      label="network manager thinks that the active network is behind portal"/>
+  <affected-histogram name="CaptivePortal.OOBE.DiscrepancyWithShill"/>
+  <affected-histogram name="CaptivePortal.Session.DiscrepancyWithShill"/>
+</fieldtrial>
+
 <fieldtrial name="AsyncSlowStart">
   <group name="AsyncSlowStart" label="Async Slow Start on"/>
   <group name="AsyncSlowStart_off" label="Async Slow Start off"/>
@@ -39545,6 +41142,17 @@
   <affected-histogram name="CertificateType2.NonBR"/>
 </fieldtrial>
 
+<fieldtrial name="CloudPrintRequests" separator=".">
+  <group name="Register" label="Register request"/>
+  <group name="UpdatePrinter" label="Update printer request"/>
+  <group name="DownloadData" label="Download data request"/>
+  <group name="Other" label="Other requests"/>
+  <affected-histogram name="CloudPrint.UrlFetcherDownloadSize"/>
+  <affected-histogram name="CloudPrint.UrlFetcherRequestTime"/>
+  <affected-histogram name="CloudPrint.UrlFetcherRetries"/>
+  <affected-histogram name="CloudPrint.UrlFetcherUploadSize"/>
+</fieldtrial>
+
 <fieldtrial name="ConnCountImpact">
   <group name="conn_count_16" label="with 16 persistent connections per host"/>
   <group name="conn_count_4" label="with 4 persistent connections per host"/>
@@ -39770,6 +41378,16 @@
   <affected-histogram name="DNS.ResolveSuccess"/>
 </fieldtrial>
 
+<fieldtrial name="DocsSpecific" separator="">
+  <group name="Docs" label="Only for docs.google.com"/>
+  <affected-histogram name="appcache.MainResourceResponseRetrieval"/>
+  <affected-histogram name="appcache.SubResourceResponseRetrieval"/>
+  <affected-histogram name="appcache.UpdateJobResult"/>
+  <affected-histogram name="appcache.UpdateProgressAtPointOfFaliure"/>
+  <affected-histogram name="appcache.UpdateWasOffOriginAtPointOfFailure"/>
+  <affected-histogram name="appcache.UpdateWasStalledAtPointOfFailure"/>
+</fieldtrial>
+
 <fieldtrial name="DomainGoogle" separator="">
   <group name="Google" label="only Google cookies are recorded."/>
   <group name="Other" label="only NON-Google cookies are recorded."/>
@@ -41596,7 +43214,9 @@
   <group name="PepperFlashPlayer.plugin" label="Flash player on Mac"/>
   <group name="widevinecdmadapter.dll" label="Widevine CDM on Windows"/>
   <group name="widevinecdmadapter.plugin" label="Widevine CDM on Mac"/>
+  <affected-histogram name="Plugin.PpapiBrokerLoadErrorCode"/>
   <affected-histogram name="Plugin.PpapiBrokerLoadResult"/>
+  <affected-histogram name="Plugin.PpapiPluginLoadErrorCode"/>
   <affected-histogram name="Plugin.PpapiPluginLoadResult"/>
 </fieldtrial>
 
@@ -41717,6 +43337,7 @@
   <group name="websame"
       label="Link triggered prerender, rel=prerender, same domain."/>
   <group name="webnext" label="Link triggered prerender, rel=next."/>
+  <affected-histogram name="Prerender.AbandonTimeUntilUsed"/>
   <affected-histogram name="Prerender.CookieSendType"/>
   <affected-histogram name="Prerender.CookieStatus"/>
   <affected-histogram name="Prerender.Event"/>
diff --git a/tools/metrics/histograms/update_extension_functions.py b/tools/metrics/histograms/update_extension_functions.py
index 0783f32..dd390a2 100644
--- a/tools/metrics/histograms/update_extension_functions.py
+++ b/tools/metrics/histograms/update_extension_functions.py
@@ -8,145 +8,15 @@
 If the file was pretty-printed, the updated version is pretty-printed too.
 """
 
-import logging
 import os
-import re
-import sys
 
-from xml.dom import minidom
-import print_style
-
-# Import the metrics/common module.
-sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'common'))
-from diff_util import PromptUserToAcceptDiff
-
-HISTOGRAMS_PATH = 'histograms.xml'
-ENUM_NAME = 'ExtensionFunctions'
-
-EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH = \
-  '../../../extensions/browser/extension_function_histogram_value.h'
-ENUM_START_MARKER = "^enum HistogramValue {"
-ENUM_END_MARKER = "^ENUM_BOUNDARY"
-
-
-class UserError(Exception):
-  def __init__(self, message):
-    Exception.__init__(self, message)
-
-  @property
-  def message(self):
-    return self.args[0]
-
-def ExtractRegexGroup(line, regex):
-    m = re.match(regex, line)
-    if m:
-      return m.group(1)
-    else:
-      return None
-
-
-def ReadHistogramValues(filename):
-  """Returns a list of pairs (label, value) corresponding to HistogramValue.
-
-  Reads the extension_function_histogram_value.h file, locates the
-  HistogramValue enum definition and returns a pair for each entry.
-  """
-
-  # Read the file as a list of lines
-  with open(filename) as f:
-    content = f.readlines()
-
-  # Locate the enum definition and collect all entries in it
-  inside_enum = False # We haven't found the enum definition yet
-  result = []
-  for line in content:
-    line = line.strip()
-    if inside_enum:
-      # Exit condition: we reached last enum value
-      if re.match(ENUM_END_MARKER, line):
-        inside_enum = False
-      else:
-        # Inside enum: generate new xml entry
-        label = ExtractRegexGroup(line.strip(), "^([\w]+)")
-        if label:
-          result.append((label, enum_value))
-          enum_value += 1
-    else:
-      if re.match(ENUM_START_MARKER, line):
-        inside_enum = True
-        enum_value = 0 # Start at 'UNKNOWN'
-  return result
-
-
-def UpdateHistogramDefinitions(histogram_values, document):
-  """Sets the children of <enum name="ExtensionFunctions" ...> node in
-  |document| to values generated from policy ids contained in
-  |policy_templates|.
-
-  Args:
-    histogram_values: A list of pairs (label, value) defining each extension
-                      function
-    document: A minidom.Document object representing parsed histogram
-              definitions XML file.
-
-  """
-  # Find ExtensionFunctions enum.
-  for enum_node in document.getElementsByTagName('enum'):
-    if enum_node.attributes['name'].value == ENUM_NAME:
-        extension_functions_enum_node = enum_node
-        break
-  else:
-    raise UserError('No policy enum node found')
-
-  # Remove existing values.
-  while extension_functions_enum_node.hasChildNodes():
-    extension_functions_enum_node.removeChild(
-      extension_functions_enum_node.lastChild)
-
-  # Add a "Generated from (...)" comment
-  comment = ' Generated from {0} '.format(
-    EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH)
-  extension_functions_enum_node.appendChild(document.createComment(comment))
-
-  # Add values generated from policy templates.
-  for (label, value) in histogram_values:
-    node = document.createElement('int')
-    node.attributes['value'] = str(value)
-    node.attributes['label'] = label
-    extension_functions_enum_node.appendChild(node)
-
-def Log(message):
-  logging.info(message)
-
-def main():
-  if len(sys.argv) > 1:
-    print >>sys.stderr, 'No arguments expected!'
-    sys.stderr.write(__doc__)
-    sys.exit(1)
-
-  Log('Reading histogram enum definition from "%s".'
-      % (EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH))
-  histogram_values = ReadHistogramValues(
-    EXTENSION_FUNCTIONS_HISTOGRAM_VALUE_PATH)
-
-  Log('Reading existing histograms from "%s".' % (HISTOGRAMS_PATH))
-  with open(HISTOGRAMS_PATH, 'rb') as f:
-    histograms_doc = minidom.parse(f)
-    f.seek(0)
-    xml = f.read()
-
-  Log('Comparing histograms enum with new enum definition.')
-  UpdateHistogramDefinitions(histogram_values, histograms_doc)
-
-  Log('Writing out new histograms file.')
-  new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc)
-
-  if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
-    with open(HISTOGRAMS_PATH, 'wb') as f:
-      f.write(new_xml)
-
-  Log('Done.')
-
+from update_histogram_enum import UpdateHistogramEnum
 
 if __name__ == '__main__':
-  main()
+  UpdateHistogramEnum(histogram_enum_name='ExtensionFunctions',
+                      source_enum_path=
+                          os.path.join('..', '..', '..', 'extensions',
+                                       'browser',
+                                       'extension_function_histogram_value.h'),
+                      start_marker='^enum HistogramValue {',
+                      end_marker='^ENUM_BOUNDARY')
diff --git a/tools/metrics/histograms/update_extension_permission.py b/tools/metrics/histograms/update_extension_permission.py
new file mode 100644
index 0000000..1672841
--- /dev/null
+++ b/tools/metrics/histograms/update_extension_permission.py
@@ -0,0 +1,22 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Updates ExtensionPermission2 enum in histograms.xml file with values read
+from permission_message.h.
+
+If the file was pretty-printed, the updated version is pretty-printed too.
+"""
+
+import os
+
+from update_histogram_enum import UpdateHistogramEnum
+
+if __name__ == '__main__':
+  UpdateHistogramEnum(histogram_enum_name='ExtensionPermission2',
+                      source_enum_path=os.path.join('..', '..', '..',
+                                                    'extensions', 'common',
+                                                    'permissions',
+                                                    'permission_message.h'),
+                      start_marker='^enum ID {',
+                      end_marker='^kEnumBoundary')
diff --git a/tools/metrics/histograms/update_histogram_enum.py b/tools/metrics/histograms/update_histogram_enum.py
new file mode 100644
index 0000000..ea43a35
--- /dev/null
+++ b/tools/metrics/histograms/update_histogram_enum.py
@@ -0,0 +1,136 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Updates enums in histograms.xml file with values read from provided C++ enum.
+
+If the file was pretty-printed, the updated version is pretty-printed too.
+"""
+
+import logging
+import print_style
+import re
+import sys
+
+from xml.dom import minidom
+from diffutil import PromptUserToAcceptDiff
+
+class UserError(Exception):
+  def __init__(self, message):
+    Exception.__init__(self, message)
+
+  @property
+  def message(self):
+    return self.args[0]
+
+
+def Log(message):
+  logging.info(message)
+
+
+def ExtractRegexGroup(line, regex):
+  m = re.match(regex, line)
+  if m:
+    # TODO(ahernandez.miralles): This can throw an IndexError
+    # if no groups are present; enclose in try catch block
+    return m.group(1)
+  else:
+    return None
+
+
+def ReadHistogramValues(filename, start_marker, end_marker):
+  """Reads in values from |filename|, returning a list of (label, value) pairs
+  corresponding to the enum framed by |start_marker| and |end_marker|.
+  """
+  # Read the file as a list of lines
+  with open(filename) as f:
+    content = f.readlines()
+
+  # Locate the enum definition and collect all entries in it
+  inside_enum = False # We haven't found the enum definition yet
+  result = []
+  for line in content:
+    line = line.strip()
+    if inside_enum:
+      # Exit condition: we reached last enum value
+      if re.match(end_marker, line):
+        inside_enum = False
+      else:
+        # Inside enum: generate new xml entry
+        label = ExtractRegexGroup(line.strip(), "^([\w]+)")
+        if label:
+          result.append((label, enum_value))
+          enum_value += 1
+    else:
+      if re.match(start_marker, line):
+        inside_enum = True
+        enum_value = 0 # Start at 'UNKNOWN'
+  return result
+
+
+def UpdateHistogramDefinitions(histogram_enum_name, source_enum_values,
+                               source_enum_path, document):
+  """Sets the children of <enum name=|histogram_enum_name| ...> node in
+  |document| to values generated from (label, value) pairs contained in
+  |source_enum_values|.
+  """
+  # Find ExtensionFunctions enum.
+  for enum_node in document.getElementsByTagName('enum'):
+    if enum_node.attributes['name'].value == histogram_enum_name:
+      histogram_enum_node = enum_node
+      break
+  else:
+    raise UserError('No {0} enum node found'.format(histogram_enum_name))
+
+  # Remove existing values.
+  while histogram_enum_node.hasChildNodes():
+    histogram_enum_node.removeChild(histogram_enum_node.lastChild)
+
+  # Add a "Generated from (...)" comment
+  comment = ' Generated from {0} '.format(source_enum_path)
+  histogram_enum_node.appendChild(document.createComment(comment))
+
+  # Add values generated from policy templates.
+  for (label, value) in source_enum_values:
+    node = document.createElement('int')
+    node.attributes['value'] = str(value)
+    node.attributes['label'] = label
+    histogram_enum_node.appendChild(node)
+
+
+def UpdateHistogramEnum(histogram_enum_name, source_enum_path,
+                        start_marker, end_marker):
+  """Updates |histogram_enum_name| enum in histograms.xml file with values
+  read from |source_enum_path|, where |start_marker| and |end_marker| indicate
+  the beginning and end of the source enum definition, respectively.
+  """
+  # TODO(ahernandez.miralles): The line below is present in nearly every
+  # file in this directory; factor out into a central location
+  HISTOGRAMS_PATH = 'histograms.xml'
+
+  if len(sys.argv) > 1:
+    print >>sys.stderr, 'No arguments expected!'
+    sys.stderr.write(__doc__)
+    sys.exit(1)
+
+  Log('Reading histogram enum definition from "{0}".'.format(source_enum_path))
+  source_enum_values = ReadHistogramValues(source_enum_path, start_marker,
+                                           end_marker)
+
+  Log('Reading existing histograms from "{0}".'.format(HISTOGRAMS_PATH))
+  with open(HISTOGRAMS_PATH, 'rb') as f:
+    histograms_doc = minidom.parse(f)
+    f.seek(0)
+    xml = f.read()
+
+  Log('Comparing histograms enum with new enum definition.')
+  UpdateHistogramDefinitions(histogram_enum_name, source_enum_values,
+                             source_enum_path, histograms_doc)
+
+  Log('Writing out new histograms file.')
+  new_xml = print_style.GetPrintStyle().PrettyPrintNode(histograms_doc)
+  if PromptUserToAcceptDiff(xml, new_xml, 'Is the updated version acceptable?'):
+    with open(HISTOGRAMS_PATH, 'wb') as f:
+      f.write(new_xml)
+
+  Log('Done.')
diff --git a/tools/msan/blacklist.txt b/tools/msan/blacklist.txt
index 5389f55..e46dc9f 100644
--- a/tools/msan/blacklist.txt
+++ b/tools/msan/blacklist.txt
@@ -21,3 +21,6 @@
 # False positives in SSE intrinsics. To be fixed in Clang.
 # http://://code.google.com/p/memory-sanitizer/issues/detail?id=48
 fun:*S32A_Opaque_BlitRow32_SSE2*
+
+# Uninit in zlib. http://crbug.com/116277
+fun:*MOZ_Z_deflate*
diff --git a/tools/perf/PRESUBMIT.py b/tools/perf/PRESUBMIT.py
index 9bb8eb1..e5ec0ec 100644
--- a/tools/perf/PRESUBMIT.py
+++ b/tools/perf/PRESUBMIT.py
@@ -1,28 +1,53 @@
 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
+
+"""Presubmit script for changes affecting tools/perf/.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into gcl (and git-cl).
+"""
+
 import os
 import sys
 
-
 PYLINT_BLACKLIST = []
-PYLINT_DISABLED_WARNINGS = ['R0923', 'R0201', 'E1101']
+PYLINT_DISABLED_WARNINGS = [
+    'R0923',  # Interface not implemented
+    'R0201',  # Method could be a function
+    'E1101',  # Non-existent member is accessed.
+]
 
 
 def _CommonChecks(input_api, output_api):
+  """Performs common checks, which includes running pylint."""
   results = []
   old_sys_path = sys.path
   try:
+    # Modules in tools/perf depend on telemetry.
     sys.path = [os.path.join(os.pardir, 'telemetry')] + sys.path
     results.extend(input_api.canned_checks.RunPylint(
         input_api, output_api,
         black_list=PYLINT_BLACKLIST,
         disabled_warnings=PYLINT_DISABLED_WARNINGS))
+    results.extend(_CheckJson(input_api, output_api))
   finally:
     sys.path = old_sys_path
   return results
 
 
+def _CheckJson(input_api, output_api):
+  """Checks whether JSON files in this change can be parsed."""
+  affected_paths = input_api.change.AbsoluteLocalPaths()
+  json_filenames = [name for name in affected_paths if name.endswith('.json')]
+  for filename in json_filenames:
+    try:
+      input_api.json.load(open(filename))
+    except ValueError:
+      return [output_api.PresubmitError('Error parsing JSON in %s!' % filename)]
+  return []
+
+
 def CheckChangeOnUpload(input_api, output_api):
   report = []
   report.extend(_CommonChecks(input_api, output_api))
diff --git a/tools/perf/benchmarks/chrome_proxy.py b/tools/perf/benchmarks/chrome_proxy.py
new file mode 100644
index 0000000..0f78eac
--- /dev/null
+++ b/tools/perf/benchmarks/chrome_proxy.py
@@ -0,0 +1,79 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry import test
+from measurements import chrome_proxy
+
+
+class ChromeProxyLatency(test.Test):
+  tag = 'latency'
+  test = chrome_proxy.ChromeProxyLatency
+  page_set = 'page_sets/chrome_proxy/top_20.json'
+  options = {'pageset_repeat_iters': 2}
+
+  def CustomizeBrowserOptions(self, options):
+    options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
+
+
+class ChromeProxyLatencyDirect(test.Test):
+  tag = 'latency_direct'
+  test = chrome_proxy.ChromeProxyLatency
+  page_set = 'page_sets/chrome_proxy/top_20.json'
+  options = {'pageset_repeat_iters': 2}
+
+
+class ChromeProxyLatencySynthetic(ChromeProxyLatency):
+  page_set = 'page_sets/chrome_proxy/synthetic.json'
+
+
+class ChromeProxyLatencySyntheticDirect(ChromeProxyLatencyDirect):
+  page_set = 'page_sets/chrome_proxy/synthetic.json'
+
+
+class ChromeProxyDataSaving(test.Test):
+  tag = 'data_saving'
+  test = chrome_proxy.ChromeProxyDataSaving
+  page_set = 'page_sets/chrome_proxy/top_20.json'
+  options = {'pageset_repeat_iters': 1}
+  def CustomizeBrowserOptions(self, options):
+    options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
+
+
+class ChromeProxyDataSavingDirect(test.Test):
+  tag = 'data_saving_direct'
+  test = chrome_proxy.ChromeProxyDataSaving
+  options = {'pageset_repeat_iters': 2}
+  page_set = 'page_sets/chrome_proxy/top_20.json'
+
+
+class ChromeProxyDataSavingSynthetic(ChromeProxyDataSaving):
+  page_set = 'page_sets/chrome_proxy/synthetic.json'
+
+
+class ChromeProxyDataSavingSyntheticDirect(ChromeProxyDataSavingDirect):
+  page_set = 'page_sets/chrome_proxy/synthetic.json'
+
+
+class ChromeProxyHeaderValidation(test.Test):
+  tag = 'header_validation'
+  test = chrome_proxy.ChromeProxyHeaders
+  page_set = 'page_sets/chrome_proxy/top_20.json'
+
+
+class ChromeProxyBypass(test.Test):
+  tag = 'bypass'
+  test = chrome_proxy.ChromeProxyBypass
+  page_set = 'page_sets/chrome_proxy/bypass.json'
+
+
+class ChromeProxySafeBrowsing(test.Test):
+  tag = 'safebrowsing'
+  test = chrome_proxy.ChromeProxySafebrowsing
+  page_set = 'page_sets/chrome_proxy/safebrowsing.json'
+
+
+class ChromeProxySmoke(test.Test):
+  tag = 'smoke'
+  test = chrome_proxy.ChromeProxySmoke
+  page_set = 'page_sets/chrome_proxy/smoke.json'
diff --git a/tools/perf/benchmarks/endure.py b/tools/perf/benchmarks/endure.py
index 389977e..2ec90dd 100644
--- a/tools/perf/benchmarks/endure.py
+++ b/tools/perf/benchmarks/endure.py
@@ -20,12 +20,11 @@
   test = endure.Endure
   # Default options for endure benchmarks. Could be overridden in subclasses.
   options = {
-      'skip_navigate_on_repeat': True,
       # Depending on the page and the actions performed on the page,
       # 2000 iterations should be between 1 and 2 hours.
       'page_repeat': 2000,
       # One sample per 10 iterations -> 200 points per run.
-      'perf_stats_interval': '10'
+      'perf_stats_interval': 10
   }
 
 
@@ -65,8 +64,7 @@
   test = endure.Endure
   # Options for endure gmail page refresh benchmark test.
   options = {
-      'skip_navigate_on_repeat': True,
       'page_repeat': 20,
-      'perf_stats_interval': '1'
+      'perf_stats_interval': 1
   }
   page_set = 'page_sets/endure_gmail_refresh.json'
diff --git a/tools/perf/benchmarks/jsgamebench.py b/tools/perf/benchmarks/jsgamebench.py
index 6e3b176..d91313d 100644
--- a/tools/perf/benchmarks/jsgamebench.py
+++ b/tools/perf/benchmarks/jsgamebench.py
@@ -6,6 +6,7 @@
 
 import os
 
+from metrics import power
 from telemetry import test
 from telemetry.page import page_measurement
 from telemetry.page import page_set
@@ -14,12 +15,22 @@
 class _JsgamebenchMeasurement(page_measurement.PageMeasurement):
   def __init__(self):
     super(_JsgamebenchMeasurement, self).__init__()
+    self._power_metric = power.PowerMetric()
+
+  def CustomizeBrowserOptions(self, options):
+    power.PowerMetric.CustomizeBrowserOptions(options)
+
+  def DidNavigateToPage(self, page, tab):
+    self._power_metric.Start(page, tab)
 
   def MeasurePage(self, page, tab, results):
     tab.ExecuteJavaScript('UI.call({}, "perftest")')
     tab.WaitForJavaScriptExpression(
         'document.getElementById("perfscore0") != null', 1800)
 
+    self._power_metric.Stop(page, tab)
+    self._power_metric.AddResults(tab, results)
+
     js_get_results = 'document.getElementById("perfscore0").innerHTML'
     result = int(tab.EvaluateJavaScript(js_get_results))
     results.Add('Score', 'score (bigger is better)', result)
diff --git a/tools/perf/benchmarks/kraken.py b/tools/perf/benchmarks/kraken.py
index 96a78d9..cc1ba48 100644
--- a/tools/perf/benchmarks/kraken.py
+++ b/tools/perf/benchmarks/kraken.py
@@ -30,7 +30,7 @@
   def MeasurePage(self, page, tab, results):
     tab.WaitForDocumentReadyStateToBeComplete()
     tab.WaitForJavaScriptExpression(
-        'document.title.indexOf("Results") != -1', 500)
+        'document.title.indexOf("Results") != -1', 700)
 
     self._power_metric.Stop(page, tab)
     self._power_metric.AddResults(tab, results)
diff --git a/tools/perf/benchmarks/media.py b/tools/perf/benchmarks/media.py
index 1d12aca..dba1b2f 100644
--- a/tools/perf/benchmarks/media.py
+++ b/tools/perf/benchmarks/media.py
@@ -39,8 +39,7 @@
   tag = 'android'
   page_set = 'page_sets/tough_video_cases.json'
   # Exclude 4k and 50 fps media files (garden* & crowd*).
-  options = {
-      'page_label_filter_exclude': '4k,50fps'}
+  options = {'page_label_filter_exclude': '4k,50fps'}
 
 
 class MediaChromeOS4kOnly(test.Test):
@@ -48,9 +47,11 @@
   test = media.Media
   tag = 'chromeOS4kOnly'
   page_set = 'page_sets/tough_video_cases.json'
-  options = {'page_label_filter': '4k',
-             # Exclude 50fps test files: crbug/331816
-             'page_label_filter_exclude': '50fps'}
+  options = {
+      'page_label_filter': '4k',
+      # Exclude 50fps test files: crbug/331816
+      'page_label_filter_exclude': '50fps'
+  }
 
 
 class MediaChromeOS(test.Test):
diff --git a/tools/perf/benchmarks/memory_pressure.py b/tools/perf/benchmarks/memory_pressure.py
index a14171b..316f55f 100644
--- a/tools/perf/benchmarks/memory_pressure.py
+++ b/tools/perf/benchmarks/memory_pressure.py
@@ -8,5 +8,4 @@
 class MemoryPressure(test.Test):
   test = memory_pressure.MemoryPressure
   page_set = 'page_sets/typical_25.json'
-  options = {'cold': True,
-             'pageset_repeat': 6}
+  options = {'pageset_repeat': 6}
diff --git a/tools/perf/benchmarks/page_cycler.py b/tools/perf/benchmarks/page_cycler.py
index cb404a7..b5801a1 100644
--- a/tools/perf/benchmarks/page_cycler.py
+++ b/tools/perf/benchmarks/page_cycler.py
@@ -65,15 +65,15 @@
   """Measures load time of the top 10 sites under simulated cable network."""
   tag = 'netsim'
   test = page_cycler.PageCycler
-  page_set = 'page_sets/top_10.json'
+  page_set = 'page_sets/top_10.py'
   options = {
-    'cold_load_percent': 100,
-    'extra_wpr_args': [
-      '--shaping_type=proxy',
-      '--net=cable'
+      'cold_load_percent': 100,
+      'extra_wpr_args': [
+          '--shaping_type=proxy',
+          '--net=cable'
       ],
-    'pageset_repeat': 5,
-    }
+      'pageset_repeat': 5,
+  }
 
   def __init__(self):
     super(PageCyclerNetsimTop10, self).__init__()
diff --git a/tools/perf/benchmarks/robohornet_pro.py b/tools/perf/benchmarks/robohornet_pro.py
index a12f503..da0a7b5 100644
--- a/tools/perf/benchmarks/robohornet_pro.py
+++ b/tools/perf/benchmarks/robohornet_pro.py
@@ -27,7 +27,7 @@
     tab.ExecuteJavaScript('ToggleRoboHornet()')
     tab.WaitForJavaScriptExpression(
         'document.getElementById("results").innerHTML.indexOf("Total") != -1',
-        120)
+        600)
 
     self._power_metric.Stop(page, tab)
     self._power_metric.AddResults(tab, results)
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py
index 3052ca3..58fefe8 100644
--- a/tools/perf/benchmarks/smoothness.py
+++ b/tools/perf/benchmarks/smoothness.py
@@ -78,7 +78,7 @@
     options.AppendExtraBrowserArgs('--enable-threaded-compositing')
     options.AppendExtraBrowserArgs('--force-compositing-mode')
     options.AppendExtraBrowserArgs('--enable-impl-side-painting')
-    options.AppendExtraBrowserArgs('--enable-gpu-rasterization')
+    options.AppendExtraBrowserArgs('--force-gpu-rasterization')
 
 
 class SmoothnessGpuRasterizationKeySilkCases(test.Test):
@@ -91,7 +91,7 @@
     options.AppendExtraBrowserArgs('--enable-threaded-compositing')
     options.AppendExtraBrowserArgs('--force-compositing-mode')
     options.AppendExtraBrowserArgs('--enable-impl-side-painting')
-    options.AppendExtraBrowserArgs('--enable-gpu-rasterization')
+    options.AppendExtraBrowserArgs('--force-gpu-rasterization')
 
 
 class SmoothnessFastPathGpuRasterizationKeySilkCases(
diff --git a/tools/perf/benchmarks/tab_switching.py b/tools/perf/benchmarks/tab_switching.py
index ada13cf..8df88c1 100644
--- a/tools/perf/benchmarks/tab_switching.py
+++ b/tools/perf/benchmarks/tab_switching.py
@@ -9,7 +9,7 @@
 
 class TabSwitchingTop10(test.Test):
   test = tab_switching.TabSwitching
-  page_set = 'page_sets/top_10.json'
+  page_set = 'page_sets/top_10.py'
 
 class TabSwitchingFiveBlankTabs(test.Test):
   test = tab_switching.TabSwitching
diff --git a/tools/perf/measurements/chrome_proxy.py b/tools/perf/measurements/chrome_proxy.py
new file mode 100644
index 0000000..7a2b441
--- /dev/null
+++ b/tools/perf/measurements/chrome_proxy.py
@@ -0,0 +1,161 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import logging
+
+from metrics import chrome_proxy
+from metrics import loading
+from telemetry.core import util
+from telemetry.page import page_measurement
+
+
+class ChromeProxyLatency(page_measurement.PageMeasurement):
+  """Chrome proxy latency measurement."""
+
+  def __init__(self, *args, **kwargs):
+    super(ChromeProxyLatency, self).__init__(*args, **kwargs)
+
+  def WillNavigateToPage(self, page, tab):
+    tab.ClearCache(force=True)
+
+  def MeasurePage(self, page, tab, results):
+    # Wait for the load event.
+    tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
+    loading.LoadingMetric().AddResults(tab, results)
+
+
+class ChromeProxyDataSaving(page_measurement.PageMeasurement):
+  """Chrome proxy data daving measurement."""
+  def __init__(self, *args, **kwargs):
+    super(ChromeProxyDataSaving, self).__init__(*args, **kwargs)
+    self._metrics = chrome_proxy.ChromeProxyMetric()
+
+  def WillNavigateToPage(self, page, tab):
+    tab.ClearCache(force=True)
+    self._metrics.Start(page, tab)
+
+  def MeasurePage(self, page, tab, results):
+    # Wait for the load event.
+    tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
+    self._metrics.Stop(page, tab)
+    self._metrics.AddResultsForDataSaving(tab, results)
+
+
+class ChromeProxyValidation(page_measurement.PageMeasurement):
+  """Base class for all chrome proxy correctness measurements."""
+
+  def __init__(self, restart_after_each_page=False):
+    super(ChromeProxyValidation, self).__init__(
+        needs_browser_restart_after_each_page=restart_after_each_page)
+    self._metrics = chrome_proxy.ChromeProxyMetric()
+    self._page = None
+    # Whether a timeout exception is expected during the test.
+    self._expect_timeout = False
+
+  def CustomizeBrowserOptions(self, options):
+    # Enable the chrome proxy (data reduction proxy).
+    options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
+
+  def WillNavigateToPage(self, page, tab):
+    tab.ClearCache(force=True)
+    assert self._metrics
+    self._metrics.Start(page, tab)
+
+  def MeasurePage(self, page, tab, results):
+    self._page = page
+    # Wait for the load event.
+    tab.WaitForJavaScriptExpression('performance.timing.loadEventStart', 300)
+    assert self._metrics
+    self._metrics.Stop(page, tab)
+    self.AddResults(tab, results)
+
+  def AddResults(self, tab, results):
+    raise NotImplementedError
+
+  def StopBrowserAfterPage(self, browser, page):  # pylint: disable=W0613
+    if hasattr(page, 'restart_after') and page.restart_after:
+      return True
+    return False
+
+  def RunNavigateSteps(self, page, tab):
+    # The redirect from safebrowsing causes a timeout. Ignore that.
+    try:
+      super(ChromeProxyValidation, self).RunNavigateSteps(page, tab)
+    except util.TimeoutException, e:
+      if self._expect_timeout:
+        logging.warning('Navigation timeout on page %s',
+                        page.name if page.name else page.url)
+      else:
+        raise e
+
+
+class ChromeProxyHeaders(ChromeProxyValidation):
+  """Correctness measurement for response headers."""
+
+  def __init__(self):
+    super(ChromeProxyHeaders, self).__init__()
+
+  def AddResults(self, tab, results):
+    self._metrics.AddResultsForHeaderValidation(tab, results)
+
+
+class ChromeProxyBypass(ChromeProxyValidation):
+  """Correctness measurement for bypass responses."""
+
+  def __init__(self):
+    super(ChromeProxyBypass, self).__init__(restart_after_each_page=True)
+
+  def AddResults(self, tab, results):
+    self._metrics.AddResultsForBypass(tab, results)
+
+
+class ChromeProxySafebrowsing(ChromeProxyValidation):
+  """Correctness measurement for safebrowsing."""
+
+  def __init__(self):
+    super(ChromeProxySafebrowsing, self).__init__()
+
+  def WillNavigateToPage(self, page, tab):
+    super(ChromeProxySafebrowsing, self).WillNavigateToPage(page, tab)
+    self._expect_timeout = True
+
+  def AddResults(self, tab, results):
+    self._metrics.AddResultsForSafebrowsing(tab, results)
+
+
+class ChromeProxySmoke(ChromeProxyValidation):
+  """Smoke measurement for basic chrome proxy correctness."""
+
+  def __init__(self):
+    super(ChromeProxySmoke, self).__init__()
+
+  def WillNavigateToPage(self, page, tab):
+    super(ChromeProxySmoke, self).WillNavigateToPage(page, tab)
+    if page.name == 'safebrowsing':
+      self._expect_timeout = True
+
+  def AddResults(self, tab, results):
+    # Map a page name to its AddResults func.
+    page_to_metrics = {
+        'header validation': [self._metrics.AddResultsForHeaderValidation],
+        'compression: image': [
+            self._metrics.AddResultsForHeaderValidation,
+            self._metrics.AddResultsForDataSaving,
+            ],
+        'compression: javascript': [
+            self._metrics.AddResultsForHeaderValidation,
+            self._metrics.AddResultsForDataSaving,
+            ],
+        'compression: css': [
+            self._metrics.AddResultsForHeaderValidation,
+            self._metrics.AddResultsForDataSaving,
+            ],
+        'bypass': [self._metrics.AddResultsForBypass],
+        'safebrowsing': [self._metrics.AddResultsForSafebrowsing],
+        }
+    if not self._page.name in page_to_metrics:
+      raise page_measurement.MeasurementFailure(
+          'Invalid page name (%s) in smoke. Page name must be one of:\n%s' % (
+          self._page.name, page_to_metrics.keys()))
+    for add_result in page_to_metrics[self._page.name]:
+      add_result(tab, results)
diff --git a/tools/perf/measurements/endure.py b/tools/perf/measurements/endure.py
index c8408a3..a7b809b 100644
--- a/tools/perf/measurements/endure.py
+++ b/tools/perf/measurements/endure.py
@@ -37,6 +37,8 @@
 
 
 class Endure(page_measurement.PageMeasurement):
+  options = {'skip_navigate_on_repeat': True}
+
   def __init__(self):
     super(Endure, self).__init__('RunEndure')
     # Browser object, saved so that browser.memory_stats can be accessed.
diff --git a/tools/perf/measurements/image_decoding.py b/tools/perf/measurements/image_decoding.py
index bb116d6..867459c 100644
--- a/tools/perf/measurements/image_decoding.py
+++ b/tools/perf/measurements/image_decoding.py
@@ -62,3 +62,7 @@
     results.Add('ImageDecoding_avg', 'ms', image_decoding_avg)
     results.Add('ImageLoading_avg', 'ms',
                 tab.EvaluateJavaScript('averageLoadingTimeMs()'))
+
+  def CleanUpAfterPage(self, page, tab):
+    if tab.browser.is_tracing_running:
+      tab.browser.StopTracing()
diff --git a/tools/perf/measurements/loading_profile.py b/tools/perf/measurements/loading_profile.py
index 06ddc5e..359f43e 100644
--- a/tools/perf/measurements/loading_profile.py
+++ b/tools/perf/measurements/loading_profile.py
@@ -10,6 +10,8 @@
 from telemetry.page import page_measurement
 
 class LoadingProfile(page_measurement.PageMeasurement):
+  options = {'page_repeat': 2}
+
   def __init__(self):
     super(LoadingProfile, self).__init__(discard_first_result=True)
 
@@ -17,10 +19,6 @@
   def results_are_the_same_on_every_page(self):
     return False
 
-  @classmethod
-  def AddCommandLineArgs(cls, parser):
-    parser.set_default('page_repeat', 2)
-
   def CustomizeBrowserOptions(self, options):
     if not perf_profiler.PerfProfiler.is_supported(browser_type='any'):
       raise Exception('This measurement is not supported on this platform')
diff --git a/tools/perf/measurements/loading_trace.py b/tools/perf/measurements/loading_trace.py
index 54af934..02a7109 100644
--- a/tools/perf/measurements/loading_trace.py
+++ b/tools/perf/measurements/loading_trace.py
@@ -1,6 +1,7 @@
 # Copyright 2013 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
+from measurements import timeline_controller
 from metrics import loading
 from metrics import timeline
 from telemetry.page import page_measurement
@@ -8,14 +9,14 @@
 class LoadingTrace(page_measurement.PageMeasurement):
   def __init__(self, *args, **kwargs):
     super(LoadingTrace, self).__init__(*args, **kwargs)
-    self._timeline_metric = timeline.LoadTimesTimelineMetric()
+    self._timeline_controller = timeline_controller.TimelineController()
 
   @property
   def results_are_the_same_on_every_page(self):
     return False
 
   def WillNavigateToPage(self, page, tab):
-    self._timeline_metric.Start(page, tab)
+    self._timeline_controller.Start(page, tab)
 
   def MeasurePage(self, page, tab, results):
     # In current telemetry tests, all tests wait for DocumentComplete state,
@@ -24,7 +25,14 @@
 
     # TODO(nduca): when crbug.com/168431 is fixed, modify the page sets to
     # recognize loading as a toplevel action.
-    self._timeline_metric.Stop(page, tab)
+    self._timeline_controller.Stop(tab)
 
     loading.LoadingMetric().AddResults(tab, results)
-    self._timeline_metric.AddResults(tab, results)
+    timeline_metric = timeline.LoadTimesTimelineMetric(
+      self._timeline_controller.model,
+      self._timeline_controller.renderer_process,
+      self._timeline_controller.action_ranges)
+    timeline_metric.AddResults(tab, results)
+
+  def CleanUpAfterPage(self, _, tab):
+    self._timeline_controller.CleanUp(tab)
diff --git a/tools/perf/measurements/loading_trace_unittest.py b/tools/perf/measurements/loading_trace_unittest.py
index 12c61b4..b83d2be 100644
--- a/tools/perf/measurements/loading_trace_unittest.py
+++ b/tools/perf/measurements/loading_trace_unittest.py
@@ -18,3 +18,6 @@
     trace_options = self._options
     results = self.RunMeasurement(measurement, ps, options = trace_options)
     self.assertEquals(0, len(results.failures))
+
+  def testCleanUpTrace(self):
+    self.TestTracingCleanedUp(loading_trace.LoadingTrace, self._options)
diff --git a/tools/perf/measurements/measurement_unittest.py b/tools/perf/measurements/measurement_unittest.py
index 35f9462..fe40a90 100644
--- a/tools/perf/measurements/measurement_unittest.py
+++ b/tools/perf/measurements/measurement_unittest.py
@@ -63,6 +63,7 @@
 
       benchmark.AddCommandLineArgs(parser)
       test.AddCommandLineArgs(parser)
+      benchmark.SetArgumentDefaults(parser)
       options.MergeDefaultValues(parser.get_default_values())
 
       benchmark.ProcessCommandLineArgs(None, options)
diff --git a/tools/perf/measurements/page_cycler.py b/tools/perf/measurements/page_cycler.py
index 87b56ab..e4893cf 100644
--- a/tools/perf/measurements/page_cycler.py
+++ b/tools/perf/measurements/page_cycler.py
@@ -28,6 +28,8 @@
 from telemetry.page import page_measurement
 
 class PageCycler(page_measurement.PageMeasurement):
+  options = {'pageset_repeat': 10}
+
   def __init__(self, *args, **kwargs):
     super(PageCycler, self).__init__(*args, **kwargs)
 
@@ -45,8 +47,6 @@
 
   @classmethod
   def AddCommandLineArgs(cls, parser):
-    parser.set_default('pageset_repeat', 10)
-
     parser.add_option('--v8-object-stats',
         action='store_true',
         help='Enable detailed V8 object statistics.')
diff --git a/tools/perf/measurements/page_cycler_unittest.py b/tools/perf/measurements/page_cycler_unittest.py
index 8854257..e83eb10 100644
--- a/tools/perf/measurements/page_cycler_unittest.py
+++ b/tools/perf/measurements/page_cycler_unittest.py
@@ -59,6 +59,7 @@
     options = browser_options.BrowserFinderOptions()
     parser = options.CreateParser()
     cycler.AddCommandLineArgs(parser)
+    cycler.SetArgumentDefaults(parser)
     parser.parse_args(args)
     cycler.ProcessCommandLineArgs(parser, options)
     cycler.CustomizeBrowserOptions(options)
diff --git a/tools/perf/measurements/rasterize_and_record.py b/tools/perf/measurements/rasterize_and_record.py
index b621ead..80ffff9 100644
--- a/tools/perf/measurements/rasterize_and_record.py
+++ b/tools/perf/measurements/rasterize_and_record.py
@@ -121,3 +121,7 @@
                 max(FlattenList(stats.rasterized_pixel_counts)))
     results.Add('recorded_pixels', 'pixels',
                 max(FlattenList(stats.recorded_pixel_counts)))
+
+  def CleanUpAfterPage(self, page, tab):
+    if tab.browser.is_tracing_running:
+      tab.browser.StopTracing()
diff --git a/tools/perf/measurements/rasterize_and_record_unittest.py b/tools/perf/measurements/rasterize_and_record_unittest.py
index 4a62849..cc50b43 100644
--- a/tools/perf/measurements/rasterize_and_record_unittest.py
+++ b/tools/perf/measurements/rasterize_and_record_unittest.py
@@ -48,3 +48,7 @@
     recorded_pixels = results.FindAllPageSpecificValuesNamed('recorded_pixels')
     self.assertEquals(len(recorded_pixels), 1)
     self.assertGreater(recorded_pixels[0].GetRepresentativeNumber(), 0)
+
+  def testCleanUpTrace(self):
+    self.TestTracingCleanedUp(rasterize_and_record.RasterizeAndRecord,
+                              self._options)
diff --git a/tools/perf/measurements/repaint.py b/tools/perf/measurements/repaint.py
index d1cfa19..5cf0877 100644
--- a/tools/perf/measurements/repaint.py
+++ b/tools/perf/measurements/repaint.py
@@ -27,3 +27,6 @@
 
   def MeasurePage(self, page, tab, results):
     self._smoothness_controller.AddResults(tab, results)
+
+  def CleanUpAfterPage(self, _, tab):
+    self._smoothness_controller.CleanUp(tab)
diff --git a/tools/perf/measurements/repaint_unittest.py b/tools/perf/measurements/repaint_unittest.py
index b79d896..69f0520 100644
--- a/tools/perf/measurements/repaint_unittest.py
+++ b/tools/perf/measurements/repaint_unittest.py
@@ -42,3 +42,6 @@
     mostly_smooth = results.FindAllPageSpecificValuesNamed('mostly_smooth')
     self.assertEquals(len(mostly_smooth), 1)
     self.assertGreaterEqual(mostly_smooth[0].GetRepresentativeNumber(), 0)
+
+  def testCleanUpTrace(self):
+    self.TestTracingCleanedUp(repaint.Repaint, self._options)
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py
index fd609ec..24386a6 100644
--- a/tools/perf/measurements/smoothness.py
+++ b/tools/perf/measurements/smoothness.py
@@ -33,3 +33,6 @@
   def MeasurePage(self, page, tab, results):
     self._power_metric.AddResults(tab, results)
     self._smoothness_controller.AddResults(tab, results)
+
+  def CleanUpAfterPage(self, _, tab):
+    self._smoothness_controller.CleanUp(tab)
diff --git a/tools/perf/measurements/smoothness_controller.py b/tools/perf/measurements/smoothness_controller.py
index d8b804d..791f0ad 100644
--- a/tools/perf/measurements/smoothness_controller.py
+++ b/tools/perf/measurements/smoothness_controller.py
@@ -63,3 +63,9 @@
         if r.value is None:
           raise MissingDisplayFrameRateError(r.name)
         results.Add(r.name, r.unit, r.value)
+
+  def CleanUp(self, tab):
+    if tab.browser.platform.IsRawDisplayFrameRateSupported():
+      tab.browser.platform.StopRawDisplayFrameRateMeasurement()
+    if tab.browser.is_tracing_running:
+      tab.browser.StopTracing()
diff --git a/tools/perf/measurements/smoothness_unittest.py b/tools/perf/measurements/smoothness_unittest.py
index def8141..363b3f1 100644
--- a/tools/perf/measurements/smoothness_unittest.py
+++ b/tools/perf/measurements/smoothness_unittest.py
@@ -37,14 +37,12 @@
      i.e. it only checks if the metrics are present and non-zero.
   """
   def testSyntheticDelayConfiguration(self):
-    attributes = {
-      'synthetic_delays': {
+    test_page = page.Page('http://dummy', None)
+    test_page.synthetic_delays = {
         'cc.BeginMainFrame': { 'target_duration': 0.012 },
         'cc.DrawAndSwap': { 'target_duration': 0.012, 'mode': 'alternating' },
         'gpu.SwapBuffers': { 'target_duration': 0.012 }
-      }
     }
-    test_page = page.Page('http://dummy', None, attributes=attributes)
 
     tab = FakeTab()
     measurement = smoothness.Smoothness()
@@ -99,3 +97,6 @@
       self.assertEquals(len(mean_touch_scroll_latency), 1)
       self.assertGreater(
           mean_touch_scroll_latency[0].GetRepresentativeNumber(), 0)
+
+  def testCleanUpTrace(self):
+    self.TestTracingCleanedUp(smoothness.Smoothness, self._options)
diff --git a/tools/perf/measurements/thread_times.py b/tools/perf/measurements/thread_times.py
index 13a9075..ba29fbb 100644
--- a/tools/perf/measurements/thread_times.py
+++ b/tools/perf/measurements/thread_times.py
@@ -1,14 +1,14 @@
 # Copyright 2014 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
-
+from measurements import timeline_controller
 from metrics import timeline
 from telemetry.page import page_measurement
 
 class ThreadTimes(page_measurement.PageMeasurement):
   def __init__(self):
     super(ThreadTimes, self).__init__('RunSmoothness')
-    self._metric = None
+    self._timeline_controller = None
 
   @classmethod
   def AddCommandLineArgs(cls, parser):
@@ -22,18 +22,32 @@
     return False
 
   def WillRunActions(self, page, tab):
-    self._metric = timeline.ThreadTimesTimelineMetric()
-    if self.options.report_silk_results:
-      self._metric.results_to_report = timeline.ReportSilkResults
+    self._timeline_controller = timeline_controller.TimelineController()
     if self.options.report_silk_details:
-      self._metric.details_to_report = timeline.ReportSilkDetails
-    self._metric.Start(page, tab)
+      # We need the other traces in order to have any details to report.
+      self.timeline_controller.trace_categories = \
+          timeline_controller.DEFAULT_TRACE_CATEGORIES
+    else:
+      self._timeline_controller.trace_categories = \
+          timeline_controller.MINIMAL_TRACE_CATEGORIES
+    self._timeline_controller.Start(page, tab)
 
   def DidRunAction(self, page, tab, action):
-    self._metric.AddActionToIncludeInMetric(action)
+    self._timeline_controller.AddActionToIncludeInMetric(action)
 
   def DidRunActions(self, page, tab):
-    self._metric.Stop(page, tab)
+    self._timeline_controller.Stop(tab)
 
   def MeasurePage(self, page, tab, results):
-    self._metric.AddResults(tab, results)
+    metric = timeline.ThreadTimesTimelineMetric(
+      self._timeline_controller.model,
+      self._timeline_controller.renderer_process,
+      self._timeline_controller.action_ranges)
+    if self.options.report_silk_results:
+      metric.results_to_report = timeline.ReportSilkResults
+    if self.options.report_silk_details:
+      metric.details_to_report = timeline.ReportSilkDetails
+    metric.AddResults(tab, results)
+
+  def CleanUpAfterPage(self, _, tab):
+    self._timeline_controller.CleanUp(tab)
diff --git a/tools/perf/measurements/thread_times_unittest.py b/tools/perf/measurements/thread_times_unittest.py
index 130feb5..e893c67 100644
--- a/tools/perf/measurements/thread_times_unittest.py
+++ b/tools/perf/measurements/thread_times_unittest.py
@@ -24,3 +24,6 @@
       cpu_time_name = timeline.ThreadCpuTimeResultName(category)
       cpu_time = results.FindAllPageSpecificValuesNamed(cpu_time_name)
       self.assertEquals(len(cpu_time), 1)
+
+  def testCleanUpTrace(self):
+    self.TestTracingCleanedUp(thread_times.ThreadTimes, self._options)
diff --git a/tools/perf/measurements/timeline_based_measurement.py b/tools/perf/measurements/timeline_based_measurement.py
index 4c4f67f..cbeb8ef 100644
--- a/tools/perf/measurements/timeline_based_measurement.py
+++ b/tools/perf/measurements/timeline_based_measurement.py
@@ -2,7 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from metrics import timeline as timeline_module
+from measurements import timeline_controller
 from metrics import timeline_interaction_record as tir_module
 from metrics import smoothness
 from telemetry.page import page_measurement
@@ -40,9 +40,12 @@
 
 
 class _TimelineBasedMetrics(object):
-  def __init__(self, model, renderer_thread):
+  def __init__(self, model, renderer_thread,
+               create_metrics_for_interaction_record_callback):
     self._model = model
     self._renderer_thread = renderer_thread
+    self._create_metrics_for_interaction_record_callback = \
+        create_metrics_for_interaction_record_callback
 
   def FindTimelineInteractionRecords(self):
     # TODO(nduca): Add support for page-load interaction record.
@@ -50,18 +53,14 @@
             event in self._renderer_thread.IterAllAsyncSlices()
             if tir_module.IsTimelineInteractionRecord(event.name)]
 
-  def CreateMetricsForTimelineInteractionRecord(self, interaction):
-    res = []
-    if interaction.is_smooth:
-      res.append(smoothness.SmoothnessMetric())
-    return res
 
   def AddResults(self, results):
     interactions = self.FindTimelineInteractionRecords()
     if len(interactions) == 0:
       raise Exception('Expected at least one Interaction on the page')
     for interaction in interactions:
-      metrics = self.CreateMetricsForTimelineInteractionRecord(interaction)
+      metrics = \
+          self._create_metrics_for_interaction_record_callback(interaction)
       wrapped_results = _ResultsWrapper(results, interaction)
       for m in metrics:
         m.AddResults(self._model, self._renderer_thread,
@@ -107,7 +106,7 @@
       raise Exception('Not supported')
     assert self.options.overhead_level in ALL_OVERHEAD_LEVELS
     if self.options.overhead_level == NO_OVERHEAD_LEVEL:
-      categories = timeline_module.MINIMAL_TRACE_CATEGORIES
+      categories = timeline_controller.MINIMAL_TRACE_CATEGORIES
     elif self.options.overhead_level == \
         MINIMAL_OVERHEAD_LEVEL:
       categories = ''
@@ -116,10 +115,24 @@
     categories = ','.join([categories] + page.GetSyntheticDelayCategories())
     tab.browser.StartTracing(categories)
 
+  def CreateMetricsForTimelineInteractionRecord(self, interaction):
+    """ Subclass of TimelineBasedMeasurement overrides this method to customize
+    the binding of interaction's flags to metrics.
+    """
+    res = []
+    if interaction.is_smooth:
+      res.append(smoothness.SmoothnessMetric())
+    return res
+
   def MeasurePage(self, page, tab, results):
     """ Collect all possible metrics and added them to results. """
     trace_result = tab.browser.StopTracing()
     model = model_module.TimelineModel(trace_result)
     renderer_thread = model.GetRendererThreadFromTab(tab)
-    meta_metrics = _TimelineBasedMetrics(model, renderer_thread)
+    meta_metrics = _TimelineBasedMetrics(
+      model, renderer_thread, self.CreateMetricsForTimelineInteractionRecord)
     meta_metrics.AddResults(results)
+
+  def CleanUpAfterPage(self, page, tab):
+    if tab.browser.is_tracing_running:
+      tab.browser.StopTracing()
diff --git a/tools/perf/measurements/timeline_based_measurement_unittest.py b/tools/perf/measurements/timeline_based_measurement_unittest.py
index 24abf1b..636ae45 100644
--- a/tools/perf/measurements/timeline_based_measurement_unittest.py
+++ b/tools/perf/measurements/timeline_based_measurement_unittest.py
@@ -41,7 +41,7 @@
 
   def testFindTimelineInteractionRecords(self):
     metric = tbm_module._TimelineBasedMetrics( # pylint: disable=W0212
-        self.model, self.renderer_thread)
+      self.model, self.renderer_thread, lambda _: [] )
     interactions = metric.FindTimelineInteractionRecords()
     self.assertEquals(2, len(interactions))
     self.assertTrue(interactions[0].is_smooth)
@@ -65,18 +65,17 @@
         assert interaction_record.logical_name == 'LogicalName2'
         results.Add('FakeLoadingMetric', 'ms', 2)
 
-    class TimelineBasedMetricsWithFakeMetricHandler(
-        tbm_module._TimelineBasedMetrics): # pylint: disable=W0212
-      def CreateMetricsForTimelineInteractionRecord(self, interaction):
-        res = []
-        if interaction.is_smooth:
-          res.append(FakeSmoothMetric())
-        if interaction.is_loading_resources:
-          res.append(FakeLoadingMetric())
-        return res
+    def CreateMetricsForTimelineInteractionRecord(interaction):
+      res = []
+      if interaction.is_smooth:
+        res.append(FakeSmoothMetric())
+      if interaction.is_loading_resources:
+        res.append(FakeLoadingMetric())
+      return res
 
-    metric = TimelineBasedMetricsWithFakeMetricHandler(
-        self.model, self.renderer_thread)
+    metric = tbm_module._TimelineBasedMetrics( # pylint: disable=W0212
+        self.model, self.renderer_thread,
+        CreateMetricsForTimelineInteractionRecord)
     ps = page_set.PageSet.FromDict({
       "description": "hello",
       "archive_path": "foo.wpr",
diff --git a/tools/perf/measurements/timeline_controller.py b/tools/perf/measurements/timeline_controller.py
new file mode 100644
index 0000000..17236e9
--- /dev/null
+++ b/tools/perf/measurements/timeline_controller.py
@@ -0,0 +1,74 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import itertools
+
+from telemetry.core.timeline.model import TimelineModel
+
+# All tracing categories not disabled-by-default
+DEFAULT_TRACE_CATEGORIES = None
+
+# Categories for absolute minimum overhead tracing. This contains no
+# sub-traces of thread tasks, so it's only useful for capturing the
+# cpu-time spent on threads (as well as needed benchmark traces)
+MINIMAL_TRACE_CATEGORIES = ("toplevel,"
+                            "benchmark,"
+                            "webkit.console,"
+                            "trace_event_overhead")
+
+
+class TimelineController(object):
+  def __init__(self):
+    super(TimelineController, self).__init__()
+    self.trace_categories = DEFAULT_TRACE_CATEGORIES
+    self._model = None
+    self._renderer_process = None
+    self._actions = []
+    self._action_ranges = []
+
+  def Start(self, page, tab):
+    """Starts gathering timeline data.
+
+    """
+    # Resets these member variables incase this object is reused.
+    self._model = None
+    self._renderer_process = None
+    self._actions = []
+    self._action_ranges = []
+    if not tab.browser.supports_tracing:
+      raise Exception('Not supported')
+    if self.trace_categories:
+      categories = [self.trace_categories] + \
+          page.GetSyntheticDelayCategories()
+    else:
+      categories = page.GetSyntheticDelayCategories()
+    tab.browser.StartTracing(','.join(categories))
+
+  def Stop(self, tab):
+    timeline_data = tab.browser.StopTracing()
+    self._model = TimelineModel(timeline_data)
+    self._renderer_process = self._model.GetRendererProcessFromTab(tab)
+    self._action_ranges = [ action.GetActiveRangeOnTimeline(self._model)
+                            for action in self._actions ]
+    # Make sure no action ranges overlap
+    for combo in itertools.combinations(self._action_ranges, 2):
+      assert not combo[0].Intersects(combo[1])
+
+  def CleanUp(self, tab):
+    if tab.browser.is_tracing_running:
+      tab.browser.StopTracing()
+
+  def AddActionToIncludeInMetric(self, action):
+    self._actions.append(action)
+
+  @property
+  def model(self):
+    return self._model
+
+  @property
+  def renderer_process(self):
+    return self._renderer_process
+
+  @property
+  def action_ranges(self):
+    return self._action_ranges
diff --git a/tools/perf/metrics/chrome_proxy.py b/tools/perf/metrics/chrome_proxy.py
new file mode 100644
index 0000000..9c319d1
--- /dev/null
+++ b/tools/perf/metrics/chrome_proxy.py
@@ -0,0 +1,132 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page import page_measurement
+from metrics import network
+
+
+class ChromeProxyMetricException(page_measurement.MeasurementFailure):
+  pass
+
+
+CHROME_PROXY_VIA_HEADER = 'Chrome-Compression-Proxy'
+CHROME_PROXY_VIA_HEADER_DEPRECATED = '1.1 Chrome Compression Proxy'
+
+
+class ChromeProxyResponse(network.HTTPResponse):
+  """ Represents an HTTP response from a timeleine event."""
+  def __init__(self, event):
+    super(ChromeProxyResponse, self).__init__(event)
+
+  def ShouldHaveChromeProxyViaHeader(self):
+    resp = self.response
+    # Ignore https and data url
+    if resp.url.startswith('https') or resp.url.startswith('data:'):
+      return False
+    # Ignore 304 Not Modified.
+    if resp.status == 304:
+      return False
+    return True
+
+  def HasChromeProxyViaHeader(self):
+    via_header = self.response.GetHeader('Via')
+    if not via_header:
+      return False
+    vias = [v.strip(' ') for v in via_header.split(',')]
+    # The Via header is valid if it is the old format or the new format
+    # with 4-character version prefix, for example,
+    # "1.1 Chrome-Compression-Proxy".
+    return (CHROME_PROXY_VIA_HEADER_DEPRECATED in vias or
+            any(v[4:] == CHROME_PROXY_VIA_HEADER for v in vias))
+
+  def IsValidByViaHeader(self):
+    return (not self.ShouldHaveChromeProxyViaHeader() or
+            self.HasChromeProxyViaHeader())
+
+  def IsSafebrowsingResponse(self):
+    if (self.response.status == 307 and
+        self.response.GetHeader('X-Malware-Url') == '1' and
+        self.IsValidByViaHeader() and
+        self.response.GetHeader('Location') == self.response.url):
+      return True
+    return False
+
+
+class ChromeProxyMetric(network.NetworkMetric):
+  """A Chrome proxy timeline metric."""
+
+  def __init__(self):
+    super(ChromeProxyMetric, self).__init__()
+    self.compute_data_saving = True
+
+  def SetEvents(self, events):
+    """Used for unittest."""
+    self._events = events
+
+  def ResponseFromEvent(self, event):
+    return ChromeProxyResponse(event)
+
+  def AddResults(self, tab, results):
+    raise NotImplementedError
+
+  def AddResultsForDataSaving(self, tab, results):
+    resources_via_proxy = 0
+    resources_from_cache = 0
+    resources_direct = 0
+
+    super(ChromeProxyMetric, self).AddResults(tab, results)
+    for resp in self.IterResponses(tab):
+      if resp.response.served_from_cache:
+        resources_from_cache += 1
+      if resp.HasChromeProxyViaHeader():
+        resources_via_proxy += 1
+      else:
+        resources_direct += 1
+
+    results.Add('resources_via_proxy', 'count', resources_via_proxy)
+    results.Add('resources_from_cache', 'count', resources_from_cache)
+    results.Add('resources_direct', 'count', resources_direct)
+
+  def AddResultsForHeaderValidation(self, tab, results):
+    via_count = 0
+    for resp in self.IterResponses(tab):
+      if resp.IsValidByViaHeader():
+        via_count += 1
+      else:
+        r = resp.response
+        raise ChromeProxyMetricException, (
+            '%s: Via header (%s) is not valid (refer=%s, status=%d)' % (
+                r.url, r.GetHeader('Via'), r.GetHeader('Referer'), r.status))
+    results.Add('checked_via_header', 'count', via_count)
+
+  def AddResultsForBypass(self, tab, results):
+    bypass_count = 0
+    for resp in self.IterResponses(tab):
+      if resp.HasChromeProxyViaHeader():
+        r = resp.response
+        raise ChromeProxyMetricException, (
+            '%s: Should not have Via header (%s) (refer=%s, status=%d)' % (
+                r.url, r.GetHeader('Via'), r.GetHeader('Referer'), r.status))
+      bypass_count += 1
+    results.Add('bypass', 'count', bypass_count)
+
+  def AddResultsForSafebrowsing(self, tab, results):
+    count = 0
+    safebrowsing_count = 0
+    for resp in self.IterResponses(tab):
+      count += 1
+      if resp.IsSafebrowsingResponse():
+        safebrowsing_count += 1
+      else:
+        r = resp.response
+        raise ChromeProxyMetricException, (
+            '%s: Not a valid safe browsing response.\n'
+            'Reponse: status=(%d, %s)\nHeaders:\n %s' % (
+                r.url, r.status, r.status_text, r.headers))
+    if count == safebrowsing_count:
+      results.Add('safebrowsing', 'boolean', True)
+    else:
+      raise ChromeProxyMetricException, (
+          'Safebrowsing failed (count=%d, safebrowsing_count=%d)\n' % (
+              count, safebrowsing_count))
diff --git a/tools/perf/metrics/chrome_proxy_unittest.py b/tools/perf/metrics/chrome_proxy_unittest.py
new file mode 100644
index 0000000..01f8f5f
--- /dev/null
+++ b/tools/perf/metrics/chrome_proxy_unittest.py
@@ -0,0 +1,181 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import base64
+import unittest
+
+from metrics import chrome_proxy
+from metrics import network_unittest
+from metrics import test_page_measurement_results
+
+
+# Timeline events used in tests.
+# An HTML not via proxy.
+EVENT_HTML_PROXY = network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent(
+    url='http://test.html1',
+    response_headers={
+        'Content-Type': 'text/html',
+        'Content-Length': str(len(network_unittest.HTML_BODY)),
+        },
+    body=network_unittest.HTML_BODY)
+
+# An HTML via proxy with the deprecated Via header.
+EVENT_HTML_PROXY_DEPRECATED_VIA = (
+    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent(
+    url='http://test.html2',
+    response_headers={
+        'Content-Type': 'text/html',
+        'Content-Encoding': 'gzip',
+        'X-Original-Content-Length': str(len(network_unittest.HTML_BODY)),
+        'Via': (chrome_proxy.CHROME_PROXY_VIA_HEADER_DEPRECATED +
+                ',other-via'),
+        },
+    body=network_unittest.HTML_BODY))
+
+# An image via proxy with Via header and it is cached.
+EVENT_IMAGE_PROXY_CACHED = (
+    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent(
+    url='http://test.image',
+    response_headers={
+        'Content-Type': 'image/jpeg',
+        'Content-Encoding': 'gzip',
+        'X-Original-Content-Length': str(network_unittest.IMAGE_OCL),
+        'Via': '1.1 ' + chrome_proxy.CHROME_PROXY_VIA_HEADER,
+        },
+    body=base64.b64encode(network_unittest.IMAGE_BODY),
+    base64_encoded_body=True,
+    served_from_cache=True))
+
+# An image fetched directly.
+EVENT_IMAGE_DIRECT = (
+    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent(
+    url='http://test.image',
+    response_headers={
+        'Content-Type': 'image/jpeg',
+        'Content-Encoding': 'gzip',
+        },
+    body=base64.b64encode(network_unittest.IMAGE_BODY),
+    base64_encoded_body=True))
+
+# A safe-browsing malware response.
+EVENT_MALWARE_PROXY = (
+    network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent(
+    url='http://test.malware',
+    response_headers={
+        'X-Malware-Url': '1',
+        'Via': '1.1 ' + chrome_proxy.CHROME_PROXY_VIA_HEADER,
+        'Location': 'http://test.malware',
+        },
+    status=307))
+
+
+class ChromeProxyMetricTest(unittest.TestCase):
+  def testChromeProxyResponse(self):
+    # An https non-proxy response.
+    resp = chrome_proxy.ChromeProxyResponse(
+        network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent(
+            url='https://test.url',
+            response_headers={
+                'Content-Type': 'text/html',
+                'Content-Length': str(len(network_unittest.HTML_BODY)),
+                'Via': 'some other via',
+                },
+            body=network_unittest.HTML_BODY))
+    self.assertFalse(resp.ShouldHaveChromeProxyViaHeader())
+    self.assertFalse(resp.HasChromeProxyViaHeader())
+    self.assertTrue(resp.IsValidByViaHeader())
+
+    # A proxied JPEG image response
+    resp = chrome_proxy.ChromeProxyResponse(
+        network_unittest.NetworkMetricTest.MakeNetworkTimelineEvent(
+            url='http://test.image',
+            response_headers={
+                'Content-Type': 'image/jpeg',
+                'Content-Encoding': 'gzip',
+                'Via': '1.1 ' + chrome_proxy.CHROME_PROXY_VIA_HEADER,
+                'X-Original-Content-Length': str(network_unittest.IMAGE_OCL),
+                },
+            body=base64.b64encode(network_unittest.IMAGE_BODY),
+            base64_encoded_body=True))
+    self.assertTrue(resp.ShouldHaveChromeProxyViaHeader())
+    self.assertTrue(resp.HasChromeProxyViaHeader())
+    self.assertTrue(resp.IsValidByViaHeader())
+
+  def testChromeProxyMetricForDataSaving(self):
+    metric = chrome_proxy.ChromeProxyMetric()
+    events = [
+        EVENT_HTML_PROXY,
+        EVENT_HTML_PROXY_DEPRECATED_VIA,
+        EVENT_IMAGE_PROXY_CACHED,
+        EVENT_IMAGE_DIRECT]
+    metric.SetEvents(events)
+
+    self.assertTrue(len(events), len(list(metric.IterResponses(None))))
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
+
+    metric.AddResultsForDataSaving(None, results)
+    results.AssertHasPageSpecificScalarValue('resources_via_proxy', 'count', 2)
+    results.AssertHasPageSpecificScalarValue('resources_from_cache', 'count', 1)
+    results.AssertHasPageSpecificScalarValue('resources_direct', 'count', 2)
+
+  def testChromeProxyMetricForHeaderValidation(self):
+    metric = chrome_proxy.ChromeProxyMetric()
+    metric.SetEvents([
+        EVENT_HTML_PROXY,
+        EVENT_HTML_PROXY_DEPRECATED_VIA,
+        EVENT_IMAGE_PROXY_CACHED,
+        EVENT_IMAGE_DIRECT])
+
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
+
+    missing_via_exception = False
+    try:
+      metric.AddResultsForHeaderValidation(None, results)
+    except chrome_proxy.ChromeProxyMetricException:
+      missing_via_exception = True
+    # Only the HTTP image response does not have a valid Via header.
+    self.assertTrue(missing_via_exception)
+
+    # Two events with valid Via headers.
+    metric.SetEvents([
+        EVENT_HTML_PROXY_DEPRECATED_VIA,
+        EVENT_IMAGE_PROXY_CACHED])
+    metric.AddResultsForHeaderValidation(None, results)
+    results.AssertHasPageSpecificScalarValue('checked_via_header', 'count', 2)
+
+  def testChromeProxyMetricForBypass(self):
+    metric = chrome_proxy.ChromeProxyMetric()
+    metric.SetEvents([
+        EVENT_HTML_PROXY,
+        EVENT_HTML_PROXY_DEPRECATED_VIA,
+        EVENT_IMAGE_PROXY_CACHED,
+        EVENT_IMAGE_DIRECT])
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
+
+    bypass_exception = False
+    try:
+      metric.AddResultsForBypass(None, results)
+    except chrome_proxy.ChromeProxyMetricException:
+      bypass_exception = True
+    # Two of the first three events have Via headers.
+    self.assertTrue(bypass_exception)
+
+    # Use directly fetched image only. It is treated as bypassed.
+    metric.SetEvents([EVENT_IMAGE_DIRECT])
+    metric.AddResultsForBypass(None, results)
+    results.AssertHasPageSpecificScalarValue('bypass', 'count', 1)
+
+  def testChromeProxyMetricForSafebrowsing(self):
+    metric = chrome_proxy.ChromeProxyMetric()
+    metric.SetEvents([EVENT_MALWARE_PROXY])
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
+
+    metric.AddResultsForSafebrowsing(None, results)
+    results.AssertHasPageSpecificScalarValue('safebrowsing', 'boolean', True)
+
+    # Clear results and metrics to test no response for safebrowsing
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
+    metric.SetEvents([])
+    metric.AddResultsForSafebrowsing(None, results)
+    results.AssertHasPageSpecificScalarValue('safebrowsing', 'boolean', True)
diff --git a/tools/perf/metrics/loading.py b/tools/perf/metrics/loading.py
index c1d4360..8495835 100644
--- a/tools/perf/metrics/loading.py
+++ b/tools/perf/metrics/loading.py
@@ -15,12 +15,43 @@
 
   def AddResults(self, tab, results):
     load_timings = tab.EvaluateJavaScript('window.performance.timing')
-    load_time_ms = (
-      float(load_timings['loadEventStart']) -
-      load_timings['navigationStart'])
-    dom_content_loaded_time_ms = (
+
+    # NavigationStart relative markers in milliseconds.
+    load_start = (
+      float(load_timings['loadEventStart']) - load_timings['navigationStart'])
+    results.Add('load_start', 'ms', load_start)
+
+    dom_content_loaded_start = (
       float(load_timings['domContentLoadedEventStart']) -
       load_timings['navigationStart'])
-    results.Add('load_time', 'ms', load_time_ms)
-    results.Add('dom_content_loaded_time', 'ms',
-                dom_content_loaded_time_ms)
+    results.Add('dom_content_loaded_start', 'ms', dom_content_loaded_start)
+
+    fetch_start = (
+        float(load_timings['fetchStart']) - load_timings['navigationStart'])
+    results.Add('fetch_start', 'ms', fetch_start, data_type='unimportant')
+
+    request_start = (
+        float(load_timings['requestStart']) - load_timings['navigationStart'])
+    results.Add('request_start', 'ms', request_start, data_type='unimportant')
+
+    # Phase measurements in milliseconds.
+    domain_lookup_duration = (
+        float(load_timings['domainLookupEnd']) -
+        load_timings['domainLookupStart'])
+    results.Add('domain_lookup_duration', 'ms', domain_lookup_duration,
+                data_type='unimportant')
+
+    connect_duration = (
+        float(load_timings['connectEnd']) - load_timings['connectStart'])
+    results.Add('connect_duration', 'ms', connect_duration,
+                data_type='unimportant')
+
+    request_duration = (
+        float(load_timings['responseStart']) - load_timings['requestStart'])
+    results.Add('request_duration', 'ms', request_duration,
+                data_type='unimportant')
+
+    response_duration = (
+        float(load_timings['responseEnd']) - load_timings['responseStart'])
+    results.Add('response_duration', 'ms', response_duration,
+                data_type='unimportant')
diff --git a/tools/perf/metrics/network.py b/tools/perf/metrics/network.py
new file mode 100644
index 0000000..bd84c4f
--- /dev/null
+++ b/tools/perf/metrics/network.py
@@ -0,0 +1,191 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import base64
+import gzip
+import hashlib
+import io
+import logging
+import zlib
+
+from metrics import Metric
+from telemetry.page import page_measurement
+# All network metrics are Chrome only for now.
+from telemetry.core.backends.chrome import inspector_network
+from telemetry.core.timeline import recording_options
+
+
+class NetworkMetricException(page_measurement.MeasurementFailure):
+  pass
+
+
+class HTTPResponse(object):
+  """ Represents an HTTP response from a timeline event."""
+  def __init__(self, event):
+    self._response = (
+        inspector_network.InspectorNetworkResponseData.FromTimelineEvent(event))
+    self._content_length = None
+
+  @property
+  def response(self):
+    return self._response
+
+  @property
+  def url_signature(self):
+    return hashlib.md5(self.response.url).hexdigest()
+
+  @property
+  def content_length(self):
+    if self._content_length is None:
+      self._content_length = self.GetContentLength()
+    return self._content_length
+
+  @property
+  def has_original_content_length(self):
+    return 'X-Original-Content-Length' in self.response.headers
+
+  @property
+  def original_content_length(self):
+    if self.has_original_content_length:
+      return int(self.response.GetHeader('X-Original-Content-Length'))
+    return 0
+
+  @property
+  def data_saving_rate(self):
+    if (self.response.served_from_cache or
+        not self.has_original_content_length or
+        self.original_content_length <= 0):
+      return 0.0
+    return (float(self.original_content_length - self.content_length) /
+            self.original_content_length)
+
+  def GetContentLengthFromBody(self):
+    resp = self.response
+    body, base64_encoded = resp.GetBody()
+    if not body:
+      return 0
+    # The binary data like images, etc is base64_encoded. Decode it to get
+    # the actualy content length.
+    if base64_encoded:
+      decoded = base64.b64decode(body)
+      return len(decoded)
+
+    encoding = resp.GetHeader('Content-Encoding')
+    if not encoding:
+      return len(body)
+    # The response body returned from a timeline event is always decompressed.
+    # So, we need to compress it to get the actual content length if headers
+    # say so.
+    encoding = encoding.lower()
+    if encoding == 'gzip':
+      return self.GetGizppedBodyLength(body)
+    elif encoding == 'deflate':
+      return len(zlib.compress(body, 9))
+    else:
+      raise NetworkMetricException, (
+          'Unknown Content-Encoding %s for %s' % (encoding, resp.url))
+
+  def GetContentLength(self):
+    cl = 0
+    try:
+      cl = self.GetContentLengthFromBody()
+    except Exception, e:
+      resp = self.response
+      logging.warning('Fail to get content length for %s from body: %s',
+                      resp.url[:100], e)
+      cl_header = resp.GetHeader('Content-Length')
+      if cl_header:
+        cl = int(cl_header)
+      else:
+        body, _ = resp.GetBody()
+        if body:
+          cl = len(body)
+    return cl
+
+  @staticmethod
+  def GetGizppedBodyLength(body):
+    if not body:
+      return 0
+    bio = io.BytesIO()
+    try:
+      with gzip.GzipFile(fileobj=bio, mode="wb", compresslevel=9) as f:
+        f.write(body.encode('utf-8'))
+    except Exception, e:
+      logging.warning('Fail to gzip response body: %s', e)
+      raise e
+    return len(bio.getvalue())
+
+
+class NetworkMetric(Metric):
+  """A network metric based on timeline events."""
+
+  def __init__(self):
+    super(NetworkMetric, self).__init__()
+
+    # Whether to add detailed result for each sub-resource in a page.
+    self.add_result_for_resource = False
+    self.compute_data_saving = False
+    self._events = None
+
+  def Start(self, page, tab):
+    self._events = None
+    opts = recording_options.TimelineRecordingOptions()
+    opts.record_network = True
+    tab.StartTimelineRecording(opts)
+
+  def Stop(self, page, tab):
+    assert self._events is None
+    tab.StopTimelineRecording()
+
+  def IterResponses(self, tab):
+    if self._events is None:
+      self._events = tab.timeline_model.GetAllEventsOfName('HTTPResponse')
+    if len(self._events) == 0:
+      return
+    for e in self._events:
+      yield self.ResponseFromEvent(e)
+
+  def ResponseFromEvent(self, event):
+    return HTTPResponse(event)
+
+  def AddResults(self, tab, results):
+    content_length = 0
+    original_content_length = 0
+
+    for resp in self.IterResponses(tab):
+      # Ignore content length calculation for cache hit.
+      if resp.response.served_from_cache:
+        continue
+
+      resource = resp.response.url
+      resource_signature = resp.url_signature
+      cl = resp.content_length
+      if resp.has_original_content_length:
+        ocl = resp.original_content_length
+        if ocl < cl:
+          logging.warning('original content length (%d) is less than content '
+                        'lenght(%d) for resource %s', ocl, cl, resource)
+        if self.add_result_for_resource:
+          results.Add('resource_data_saving_' + resource_signature,
+                      'percent', resp.data_saving_rate * 100)
+          results.Add('resource_original_content_length_' + resource_signature,
+                      'bytes', ocl)
+        original_content_length += ocl
+      else:
+        original_content_length += cl
+      if self.add_result_for_resource:
+        results.Add(
+            'resource_content_length_' + resource_signature, 'bytes', cl)
+      content_length += cl
+
+    results.Add('content_length', 'bytes', content_length)
+    results.Add('original_content_length', 'bytes', original_content_length)
+    if self.compute_data_saving:
+      if (original_content_length > 0 and
+          original_content_length >= content_length):
+        saving = (float(original_content_length-content_length) * 100 /
+                  original_content_length)
+        results.Add('data_saving', 'percent', saving)
+      else:
+        results.Add('data_saving', 'percent', 0.0)
diff --git a/tools/perf/metrics/network_unittest.py b/tools/perf/metrics/network_unittest.py
new file mode 100644
index 0000000..316f7c0
--- /dev/null
+++ b/tools/perf/metrics/network_unittest.py
@@ -0,0 +1,174 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import base64
+import unittest
+
+from metrics import test_page_measurement_results
+from metrics import network
+from telemetry.core.timeline import event
+
+
+HTML_BODY = """<!DOCTYPE HTML>
+  <html>
+  <head> </head>
+ <body>
+ <div id="test"> TEST HTML</div>
+ </body>
+ </html>"""
+IMAGE_BODY = """fake image data"""
+GZIPPED_HTML_LEN = network.HTTPResponse.GetGizppedBodyLength(HTML_BODY)
+# Make up original content length for the image.
+IMAGE_OCL = 3 * len(IMAGE_BODY)
+
+
+class NetworkMetricTest(unittest.TestCase):
+  @staticmethod
+  def MakeNetworkTimelineEvent(
+      url, response_headers, body=None, base64_encoded_body=False,
+      served_from_cache=False, request_headers=None, status=200):
+    if not request_headers:
+      request_headers = {}
+    e = event.TimelineEvent('network', 'HTTPResponse', 0, 0)
+    e.args = {}
+    e.args['requestId'] = 0
+    e.args['response'] = {
+        'status': status,
+        'url': url,
+        'headers': response_headers,
+        'requestHeaders': request_headers,
+        }
+    e.args['body'] = body
+    e.args['base64_encoded_body'] = base64_encoded_body
+    e.args['served_from_cache'] = served_from_cache
+    return e
+
+  def testHTTPResponse(self):
+    url = 'http://test.url'
+    self.assertLess(GZIPPED_HTML_LEN, len(HTML_BODY))
+
+    # A plain text HTML response
+    resp = network.HTTPResponse(self.MakeNetworkTimelineEvent(
+        url=url,
+        response_headers={
+            'Content-Type': 'text/html',
+            'Content-Length': str(len(HTML_BODY)),
+            },
+        body=HTML_BODY))
+    self.assertEqual(url, resp.response.url)
+    body, base64_encoded = resp.response.GetBody()
+    self.assertEqual(HTML_BODY, body)
+    self.assertFalse(base64_encoded)
+    self.assertEqual('text/html', resp.response.GetHeader('Content-Type'))
+
+    self.assertEqual(len(HTML_BODY), resp.content_length)
+    self.assertEqual(None, resp.response.GetHeader('Content-Encoding'))
+    self.assertFalse(resp.has_original_content_length)
+    self.assertEqual(0.0, resp.data_saving_rate)
+
+    # A gzipped HTML response
+    resp = network.HTTPResponse(self.MakeNetworkTimelineEvent(
+        url=url,
+        response_headers={
+            'Content-Type': 'text/html',
+            'Content-Encoding': 'gzip',
+            'X-Original-Content-Length': str(len(HTML_BODY)),
+            },
+        body=HTML_BODY))
+    body, base64_encoded = resp.response.GetBody()
+    self.assertFalse(base64_encoded)
+    self.assertEqual(GZIPPED_HTML_LEN, resp.content_length)
+    self.assertEqual('gzip', resp.response.GetHeader('Content-Encoding'))
+    self.assertTrue(resp.has_original_content_length)
+    self.assertEqual(len(HTML_BODY), resp.original_content_length)
+    self.assertEqual(
+        float(len(HTML_BODY) - GZIPPED_HTML_LEN) / len(HTML_BODY),
+        resp.data_saving_rate)
+
+    # A JPEG image response.
+    resp = network.HTTPResponse(self.MakeNetworkTimelineEvent(
+        url='http://test.image',
+        response_headers={
+            'Content-Type': 'image/jpeg',
+            'Content-Encoding': 'gzip',
+            'X-Original-Content-Length': str(IMAGE_OCL),
+            },
+        body=base64.b64encode(IMAGE_BODY),
+        base64_encoded_body=True))
+    body, base64_encoded = resp.response.GetBody()
+    self.assertTrue(base64_encoded)
+    self.assertEqual(IMAGE_BODY, base64.b64decode(body))
+    self.assertEqual(len(IMAGE_BODY), resp.content_length)
+    self.assertTrue(resp.has_original_content_length)
+    self.assertEqual(IMAGE_OCL, resp.original_content_length)
+    self.assertFalse(resp.response.served_from_cache)
+    self.assertEqual(float(IMAGE_OCL - len(IMAGE_BODY)) / IMAGE_OCL,
+                     resp.data_saving_rate)
+
+    # A JPEG image response from cache.
+    resp = network.HTTPResponse(self.MakeNetworkTimelineEvent(
+        url='http://test.image',
+        response_headers={
+            'Content-Type': 'image/jpeg',
+            'Content-Encoding': 'gzip',
+            'X-Original-Content-Length': str(IMAGE_OCL),
+            },
+        body=base64.b64encode(IMAGE_BODY),
+        base64_encoded_body=True,
+        served_from_cache=True))
+    self.assertEqual(len(IMAGE_BODY), resp.content_length)
+    self.assertTrue(resp.has_original_content_length)
+    self.assertEqual(IMAGE_OCL, resp.original_content_length)
+    # Cached resource has zero saving.
+    self.assertTrue(resp.response.served_from_cache)
+    self.assertEqual(0.0, resp.data_saving_rate)
+
+  def testNetworkMetricResults(self):
+    events = [
+        # A plain text HTML.
+        self.MakeNetworkTimelineEvent(
+            url='http://test.html1',
+            response_headers={
+                'Content-Type': 'text/html',
+                'Content-Length': str(len(HTML_BODY)),
+                },
+            body=HTML_BODY),
+        # A compressed HTML.
+        self.MakeNetworkTimelineEvent(
+            url='http://test.html2',
+            response_headers={
+                'Content-Type': 'text/html',
+                'Content-Encoding': 'gzip',
+                'X-Original-Content-Length': str(len(HTML_BODY)),
+                },
+            body=HTML_BODY),
+        # A base64 encoded image.
+        self.MakeNetworkTimelineEvent(
+            url='http://test.image',
+            response_headers={
+                'Content-Type': 'image/jpeg',
+                'Content-Encoding': 'gzip',
+                'X-Original-Content-Length': str(IMAGE_OCL),
+                },
+            body=base64.b64encode(IMAGE_BODY),
+            base64_encoded_body=True),
+        ]
+    metric = network.NetworkMetric()
+    metric._events = events
+    metric.compute_data_saving = True
+
+    self.assertTrue(len(events), len(list(metric.IterResponses(None))))
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
+    metric.AddResults(None, results)
+
+    cl = len(HTML_BODY) + GZIPPED_HTML_LEN + len(IMAGE_BODY)
+    results.AssertHasPageSpecificScalarValue('content_length', 'bytes', cl)
+
+    ocl = len(HTML_BODY) + len(HTML_BODY) + IMAGE_OCL
+    results.AssertHasPageSpecificScalarValue(
+        'original_content_length', 'bytes', ocl)
+
+    saving_percent = float(ocl - cl) * 100/ ocl
+    results.AssertHasPageSpecificScalarValue(
+        'data_saving', 'percent', saving_percent)
diff --git a/tools/perf/metrics/power.py b/tools/perf/metrics/power.py
index c115d02..1196dbf 100644
--- a/tools/perf/metrics/power.py
+++ b/tools/perf/metrics/power.py
@@ -35,8 +35,9 @@
       return
     self._running = False
     self._results = self._browser.platform.StopMonitoringPowerAsync()
-    self._results['cpu_stats'] = (
-        _SubtractCpuStats(self._browser.cpu_stats, self._starting_cpu_stats))
+    if self._results: # StopMonitoringPowerAsync() can return None.
+      self._results['cpu_stats'] = (
+          _SubtractCpuStats(self._browser.cpu_stats, self._starting_cpu_stats))
 
   @classmethod
   def CustomizeBrowserOptions(cls, options):
diff --git a/tools/perf/metrics/rendering_stats.py b/tools/perf/metrics/rendering_stats.py
index 0c176b4..ba98732 100644
--- a/tools/perf/metrics/rendering_stats.py
+++ b/tools/perf/metrics/rendering_stats.py
@@ -15,6 +15,7 @@
 # This is when the input event has reached swap buffer.
 END_COMP_NAME = 'INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT'
 
+
 def GetScrollInputLatencyEvents(scroll_type, browser_process, timeline_range):
   """Get scroll events' LatencyInfo from the browser process's trace buffer
      that are within the timeline_range.
@@ -39,6 +40,7 @@
           scroll_events.append(ss)
   return scroll_events
 
+
 def ComputeMouseWheelScrollLatency(mouse_wheel_events):
   """ Compute the mouse wheel scroll latency.
 
@@ -57,6 +59,7 @@
       mouse_wheel_latency.append(latency / 1000.0)
   return mouse_wheel_latency
 
+
 def ComputeTouchScrollLatency(touch_scroll_events):
   """ Compute the touch scroll latency.
 
@@ -83,6 +86,24 @@
         touch_scroll_latency.append(latency / 1000.0)
   return touch_scroll_latency
 
+
+def HasRenderingStats(process):
+  """ Returns True if the process contains at least one
+      BenchmarkInstrumentation::*RenderingStats event with a frame.
+  """
+  if not process:
+    return False
+  for event in process.IterAllSlicesOfName(
+      'BenchmarkInstrumentation::MainThreadRenderingStats'):
+    if 'data' in event.args and event.args['data']['frame_count'] == 1:
+      return True
+  for event in process.IterAllSlicesOfName(
+      'BenchmarkInstrumentation::ImplThreadRenderingStats'):
+    if 'data' in event.args and event.args['data']['frame_count'] == 1:
+      return True
+  return False
+
+
 class RenderingStats(object):
   def __init__(self, renderer_process, browser_process, timeline_ranges):
     """
@@ -96,7 +117,11 @@
     All *_time values are measured in milliseconds.
     """
     assert(len(timeline_ranges) > 0)
-    self.renderer_process = renderer_process
+    # Find the top level process with rendering stats (browser or renderer).
+    if HasRenderingStats(browser_process):
+      self.top_level_process = browser_process
+    else:
+      self.top_level_process  = renderer_process
 
     self.frame_timestamps = []
     self.frame_times = []
@@ -153,7 +178,7 @@
   def initMainThreadStatsFromTimeline(self, timeline_range):
     event_name = 'BenchmarkInstrumentation::MainThreadRenderingStats'
     events = []
-    for event in self.renderer_process.IterAllSlicesOfName(event_name):
+    for event in self.top_level_process.IterAllSlicesOfName(event_name):
       if event.start >= timeline_range.min and event.end <= timeline_range.max:
         if 'data' not in event.args:
           continue
@@ -184,7 +209,7 @@
   def initImplThreadStatsFromTimeline(self, timeline_range):
     event_name = 'BenchmarkInstrumentation::ImplThreadRenderingStats'
     events = []
-    for event in self.renderer_process.IterAllSlicesOfName(event_name):
+    for event in self.top_level_process.IterAllSlicesOfName(event_name):
       if event.start >= timeline_range.min and event.end <= timeline_range.max:
         if 'data' not in event.args:
           continue
diff --git a/tools/perf/metrics/rendering_stats_unittest.py b/tools/perf/metrics/rendering_stats_unittest.py
index 11f82b5..4f00542 100644
--- a/tools/perf/metrics/rendering_stats_unittest.py
+++ b/tools/perf/metrics/rendering_stats_unittest.py
@@ -9,6 +9,7 @@
 from metrics.rendering_stats import GetScrollInputLatencyEvents
 from metrics.rendering_stats import ComputeMouseWheelScrollLatency
 from metrics.rendering_stats import ComputeTouchScrollLatency
+from metrics.rendering_stats import HasRenderingStats
 from metrics.rendering_stats import RenderingStats
 import telemetry.core.timeline.bounds as timeline_bounds
 from telemetry.core.timeline import model
@@ -199,6 +200,30 @@
         (data[END_COMP_NAME]['time'] - data[UI_COMP_NAME]['time']) / 1000.0)
 
 class RenderingStatsUnitTest(unittest.TestCase):
+  def testHasRenderingStats(self):
+    timeline = model.TimelineModel()
+    timer = MockTimer()
+
+    # A process without rendering stats
+    process_without_stats = timeline.GetOrCreateProcess(pid = 1)
+    thread_without_stats = process_without_stats.GetOrCreateThread(tid = 11)
+    process_without_stats.FinalizeImport()
+    self.assertFalse(HasRenderingStats(thread_without_stats))
+
+    # A process with rendering stats, but no frames in them
+    process_without_frames = timeline.GetOrCreateProcess(pid = 2)
+    thread_without_frames = process_without_frames.GetOrCreateThread(tid = 21)
+    AddMainThreadRenderingStats(timer, thread_without_frames, True, None)
+    process_without_frames.FinalizeImport()
+    self.assertFalse(HasRenderingStats(thread_without_frames))
+
+    # A process with rendering stats and frames in them
+    process_with_frames = timeline.GetOrCreateProcess(pid = 3)
+    thread_with_frames = process_with_frames.GetOrCreateThread(tid = 31)
+    AddImplThreadRenderingStats(timer, thread_with_frames, True, None)
+    process_with_frames.FinalizeImport()
+    self.assertTrue(HasRenderingStats(thread_with_frames))
+
   def testFromTimeline(self):
     timeline = model.TimelineModel()
 
@@ -220,10 +245,10 @@
     ref_stats.AppendNewRange()
     for i in xrange(0, 10):
       first = (i == 0)
-      AddMainThreadRenderingStats(timer, renderer_main, first, ref_stats)
-      AddImplThreadRenderingStats(timer, renderer_compositor, first, ref_stats)
-      AddMainThreadRenderingStats(timer, browser_main, first, None)
-      AddImplThreadRenderingStats(timer, browser_compositor, first, None)
+      AddMainThreadRenderingStats(timer, renderer_main, first, None)
+      AddImplThreadRenderingStats(timer, renderer_compositor, first, None)
+      AddMainThreadRenderingStats(timer, browser_main, first, ref_stats)
+      AddImplThreadRenderingStats(timer, browser_compositor, first, ref_stats)
     renderer_main.EndSlice(timer.Get())
 
     # Create 5 main and impl rendering stats events not within any action.
@@ -240,10 +265,10 @@
     ref_stats.AppendNewRange()
     for i in xrange(0, 10):
       first = (i == 0)
-      AddMainThreadRenderingStats(timer, renderer_main, first, ref_stats)
-      AddImplThreadRenderingStats(timer, renderer_compositor, first, ref_stats)
-      AddMainThreadRenderingStats(timer, browser_main, first, None)
-      AddImplThreadRenderingStats(timer, browser_compositor, first, None)
+      AddMainThreadRenderingStats(timer, renderer_main, first, None)
+      AddImplThreadRenderingStats(timer, renderer_compositor, first, None)
+      AddMainThreadRenderingStats(timer, browser_main, first, ref_stats)
+      AddImplThreadRenderingStats(timer, browser_compositor, first, ref_stats)
     renderer_main.EndSlice(timer.Get())
 
     # Create 10 main and impl rendering stats events for Action A.
@@ -252,14 +277,14 @@
     ref_stats.AppendNewRange()
     for i in xrange(0, 10):
       first = (i == 0)
-      AddMainThreadRenderingStats(timer, renderer_main, first, ref_stats)
-      AddImplThreadRenderingStats(timer, renderer_compositor, first, ref_stats)
-      AddMainThreadRenderingStats(timer, browser_main, first, None)
-      AddImplThreadRenderingStats(timer, browser_compositor, first, None)
+      AddMainThreadRenderingStats(timer, renderer_main, first, None)
+      AddImplThreadRenderingStats(timer, renderer_compositor, first, None)
+      AddMainThreadRenderingStats(timer, browser_main, first, ref_stats)
+      AddImplThreadRenderingStats(timer, browser_compositor, first, ref_stats)
     renderer_main.EndSlice(timer.Get())
 
-    renderer_main.FinalizeImport()
-    renderer_compositor.FinalizeImport()
+    browser.FinalizeImport()
+    renderer.FinalizeImport()
 
     timeline_markers = timeline.FindTimelineMarkers(
         ['ActionA', 'ActionB', 'ActionA'])
@@ -267,6 +292,9 @@
                         for marker in timeline_markers ]
     stats = RenderingStats(renderer, browser, timeline_ranges)
 
+    # Check if we are using the browser compositor's stats
+    self.assertEquals(stats.top_level_process, browser)
+
     # Compare rendering stats to reference.
     self.assertEquals(stats.frame_timestamps, ref_stats.frame_timestamps)
     self.assertEquals(stats.frame_times, ref_stats.frame_times)
@@ -337,8 +365,8 @@
                                   renderer_main, ref_latency_stats)
     renderer_main.EndSlice(timer.Get())
 
-    browser_main.FinalizeImport()
-    renderer_main.FinalizeImport()
+    browser.FinalizeImport()
+    renderer.FinalizeImport()
 
     mouse_wheel_scroll_events = []
     touch_scroll_events = []
diff --git a/tools/perf/metrics/test_page_measurement_results.py b/tools/perf/metrics/test_page_measurement_results.py
new file mode 100644
index 0000000..e1df8bd
--- /dev/null
+++ b/tools/perf/metrics/test_page_measurement_results.py
@@ -0,0 +1,30 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page import page_measurement_results
+from telemetry.page import page as page_module
+from telemetry.value import scalar
+
+class TestPageMeasurementResults(
+    page_measurement_results.PageMeasurementResults):
+  def __init__(self, test):
+    super(TestPageMeasurementResults, self).__init__()
+    self.test = test
+    page = page_module.Page("http://www.google.com", {})
+    self.WillMeasurePage(page)
+
+  def GetPageSpecificValueNamed(self, name):
+    values = [value for value in self.all_page_specific_values
+         if value.name == name]
+    assert len(values) == 1, 'Could not find value named %s' % name
+    return values[0]
+
+  def AssertHasPageSpecificScalarValue(self, name, units, expected_value):
+    value = self.GetPageSpecificValueNamed(name)
+    self.test.assertEquals(units, value.units)
+    self.test.assertTrue(isinstance(value, scalar.ScalarValue))
+    self.test.assertEquals(expected_value, value.value)
+
+  def __str__(self):
+    return '\n'.join([repr(x) for x in self.all_page_specific_values])
diff --git a/tools/perf/metrics/timeline.py b/tools/perf/metrics/timeline.py
index 9d95455..e6bdaa2 100644
--- a/tools/perf/metrics/timeline.py
+++ b/tools/perf/metrics/timeline.py
@@ -2,91 +2,28 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 import collections
-import itertools
 
 from metrics import Metric
-from telemetry.core.timeline.model import TimelineModel
 from telemetry.core.timeline import bounds
-from telemetry.page import page_measurement
-
-# All tracing categories not disabled-by-default
-DEFAULT_TRACE_CATEGORIES = None
-
-# Categories for absolute minimum overhead tracing. This contains no
-# sub-traces of thread tasks, so it's only useful for capturing the
-# cpu-time spent on threads (as well as needed benchmark traces)
-MINIMAL_TRACE_CATEGORIES = ("toplevel,"
-                            "benchmark,"
-                            "webkit.console,"
-                            "trace_event_overhead")
-
-class MissingFramesError(page_measurement.MeasurementFailure):
-  def __init__(self):
-    super(MissingFramesError, self).__init__(
-        'No frames found in trace. Unable to normalize results.')
 
 
 class TimelineMetric(Metric):
-  def __init__(self):
+  def __init__(self, model=None, renderer_process=None, action_ranges=None):
     """ Initializes a TimelineMetric object.
     """
     super(TimelineMetric, self).__init__()
-    self.trace_categories = DEFAULT_TRACE_CATEGORIES
-    self._model = None
-    self._renderer_process = None
-    self._actions = []
-    self._action_ranges = []
-
-  def Start(self, page, tab):
-    """Starts gathering timeline data.
-
-    """
-    self._model = None
-    if not tab.browser.supports_tracing:
-      raise Exception('Not supported')
-    if self.trace_categories:
-      categories = [self.trace_categories] + \
-          page.GetSyntheticDelayCategories()
-    else:
-      categories = page.GetSyntheticDelayCategories()
-    tab.browser.StartTracing(','.join(categories))
-
-  def Stop(self, page, tab):
-    timeline_data = tab.browser.StopTracing()
-    self._model = TimelineModel(timeline_data)
-    self._renderer_process = self._model.GetRendererProcessFromTab(tab)
-    self._action_ranges = [ action.GetActiveRangeOnTimeline(self._model)
-                            for action in self._actions ]
-    # Make sure no action ranges overlap
-    for combo in itertools.combinations(self._action_ranges, 2):
-      assert not combo[0].Intersects(combo[1])
-
-  def AddActionToIncludeInMetric(self, action):
-    self._actions.append(action)
-
-  @property
-  def model(self):
-    return self._model
-
-  @model.setter
-  def model(self, model):
     self._model = model
-
-  @property
-  def renderer_process(self):
-    return self._renderer_process
-
-  @renderer_process.setter
-  def renderer_process(self, p):
-    self._renderer_process = p
+    self._renderer_process = renderer_process
+    self._action_ranges = action_ranges if action_ranges else []
 
   def AddResults(self, tab, results):
     return
 
 
 class LoadTimesTimelineMetric(TimelineMetric):
-  def __init__(self):
-    super(LoadTimesTimelineMetric, self).__init__()
+  def __init__(self, model=None, renderer_process=None, action_ranges=None):
+    super(LoadTimesTimelineMetric, self).__init__(model, renderer_process,
+                                                  action_ranges)
     self.report_main_thread_only = True
 
   def AddResults(self, _, results):
@@ -98,7 +35,7 @@
 
     events_by_name = collections.defaultdict(list)
 
-    for thread in self.renderer_process.threads.itervalues():
+    for thread in self._renderer_process.threads.itervalues():
 
       if thread_filter and not thread.name in thread_filter:
         continue
@@ -122,7 +59,7 @@
         results.Add(full_name + '_max', 'ms', biggest_jank)
         results.Add(full_name + '_avg', 'ms', total / len(times))
 
-    for counter_name, counter in self.renderer_process.counters.iteritems():
+    for counter_name, counter in self._renderer_process.counters.iteritems():
       total = sum(counter.totals)
 
       # Results objects cannot contain the '.' character, so remove that here.
@@ -275,19 +212,13 @@
 
 
 class ThreadTimesTimelineMetric(TimelineMetric):
-  def __init__(self):
-    super(ThreadTimesTimelineMetric, self).__init__()
+  def __init__(self, model=None, renderer_process=None, action_ranges=None):
+    super(ThreadTimesTimelineMetric, self).__init__(model, renderer_process,
+                                                    action_ranges)
     # Minimal traces, for minimum noise in CPU-time measurements.
-    self.trace_categories = MINIMAL_TRACE_CATEGORIES
     self.results_to_report = AllThreads
     self.details_to_report = NoThreads
 
-  def Start(self, page, tab):
-    # We need the other traces in order to have any details to report.
-    if not self.details_to_report == NoThreads:
-      self.trace_categories = DEFAULT_TRACE_CATEGORIES
-    super(ThreadTimesTimelineMetric, self).Start(page, tab)
-
   def CountSlices(self, slices, substring):
     count = 0
     for event in slices:
diff --git a/tools/perf/metrics/timeline_unittest.py b/tools/perf/metrics/timeline_unittest.py
index 6ed9b00..6d19606 100644
--- a/tools/perf/metrics/timeline_unittest.py
+++ b/tools/perf/metrics/timeline_unittest.py
@@ -4,40 +4,15 @@
 
 import unittest
 
+from metrics import test_page_measurement_results
 from metrics import timeline
 from telemetry.core.timeline import bounds
 from telemetry.core.timeline import model as model_module
-from telemetry.page import page as page_module
-from telemetry.page import page_measurement_results
-from telemetry.value import scalar
 
-class TestPageMeasurementResults(
-    page_measurement_results.PageMeasurementResults):
-  def __init__(self, test):
-    super(TestPageMeasurementResults, self).__init__()
-    self.test = test
-    page = page_module.Page("http://www.google.com", {})
-    self.WillMeasurePage(page)
-
-  def GetPageSpecificValueNamed(self, name):
-    values = [value for value in self.all_page_specific_values
-         if value.name == name]
-    assert len(values) == 1, 'Could not find value named %s' % name
-    return values[0]
-
-  def AssertHasPageSpecificScalarValue(self, name, units, expected_value):
-    value = self.GetPageSpecificValueNamed(name)
-    self.test.assertEquals(units, value.units)
-    self.test.assertTrue(isinstance(value, scalar.ScalarValue))
-    self.test.assertEquals(expected_value, value.value)
-
-  def __str__(self):
-    return '\n'.join([repr(x) for x in self.all_page_specific_values])
 
 class LoadTimesTimelineMetric(unittest.TestCase):
-  def GetResultsForModel(self, metric, model):
-    metric.model = model
-    results = TestPageMeasurementResults(self)
+  def GetResults(self, metric):
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
     tab = None
     metric.AddResults(tab, results)
     return results
@@ -53,9 +28,8 @@
     renderer_main.EndSlice(20, 20)
     model.FinalizeImport()
 
-    metric = timeline.LoadTimesTimelineMetric()
-    metric.renderer_process = renderer_main.parent
-    results = self.GetResultsForModel(metric, model)
+    metric = timeline.LoadTimesTimelineMetric(model, renderer_main.parent)
+    results = self.GetResults(metric)
     results.AssertHasPageSpecificScalarValue(
       'CrRendererMain|x_y', 'ms', 10)
     results.AssertHasPageSpecificScalarValue(
@@ -74,9 +48,8 @@
     x_counter.timestamps += [0, 1]
     model.FinalizeImport()
 
-    metric = timeline.LoadTimesTimelineMetric()
-    metric.renderer_process = renderer_main.parent
-    results = self.GetResultsForModel(metric, model)
+    metric = timeline.LoadTimesTimelineMetric(model, renderer_main.parent)
+    results = self.GetResults(metric)
     results.AssertHasPageSpecificScalarValue(
       'cat_x_y', 'count', 3)
     results.AssertHasPageSpecificScalarValue(
@@ -84,9 +57,8 @@
 
 
 class ThreadTimesTimelineMetricUnittest(unittest.TestCase):
-  def GetResultsForModel(self, metric, model):
-    metric.model = model
-    results = TestPageMeasurementResults(self)
+  def GetResults(self, metric):
+    results = test_page_measurement_results.TestPageMeasurementResults(self)
     tab = None
     metric.AddResults(tab, results)
     return results
@@ -102,10 +74,10 @@
     renderer_main = model.GetOrCreateProcess(1).GetOrCreateThread(2)
     renderer_main.name = 'CrRendererMain'
 
-    metric = timeline.ThreadTimesTimelineMetric()
-    metric._action_ranges = [self.GetActionRange(1, 2)]
+    metric = timeline.ThreadTimesTimelineMetric(model, renderer_main.parent,
+                                                [self.GetActionRange(1, 2)])
     metric.details_to_report = timeline.ReportMainThreadOnly
-    results = self.GetResultsForModel(metric, model)
+    results = self.GetResults(metric)
 
     # Test that all result thread categories exist
     for name in timeline.TimelineThreadCategories.values():
@@ -135,10 +107,10 @@
     model.FinalizeImport()
 
     # Exclude 'Z' using an action-range.
-    metric = timeline.ThreadTimesTimelineMetric()
-    metric._action_ranges = [self.GetActionRange(10, 30)]
+    metric = timeline.ThreadTimesTimelineMetric(
+      model, renderer_main.parent, action_ranges=[self.GetActionRange(10, 30)])
     metric.details_to_report = timeline.ReportMainThreadOnly
-    results = self.GetResultsForModel(metric, model)
+    results = self.GetResults(metric)
 
     # Test a couple specific results.
     assert_results = {
@@ -172,10 +144,10 @@
     model.FinalizeImport()
 
     # Include everything in an action-range.
-    metric = timeline.ThreadTimesTimelineMetric()
-    metric._action_ranges = [self.GetActionRange(10, 30)]
+    metric = timeline.ThreadTimesTimelineMetric(
+      model, renderer_main.parent, action_ranges=[self.GetActionRange(10, 30)])
     metric.details_to_report = timeline.ReportMainThreadOnly
-    results = self.GetResultsForModel(metric, model)
+    results = self.GetResults(metric)
 
     # Test a couple specific results.
     assert_results = {
diff --git a/tools/perf/page_sets/chrome_proxy/bypass.json b/tools/perf/page_sets/chrome_proxy/bypass.json
new file mode 100644
index 0000000..e42be63
--- /dev/null
+++ b/tools/perf/page_sets/chrome_proxy/bypass.json
@@ -0,0 +1,14 @@
+{
+  "description": "Chrome proxy test sites",
+  "archive_data_file": "../data/chrome_proxy_bypass.json",
+  "pages": [
+    {
+      "url": "http://aws1.mdw.la/bypass/",
+      "why": ""
+    },
+    {
+      "url": "http://aws1.mdw.la/piatek/bypass-demo",
+      "why": ""
+    }
+  ]
+}
diff --git a/tools/perf/page_sets/chrome_proxy/safebrowsing.json b/tools/perf/page_sets/chrome_proxy/safebrowsing.json
new file mode 100644
index 0000000..9fa1688
--- /dev/null
+++ b/tools/perf/page_sets/chrome_proxy/safebrowsing.json
@@ -0,0 +1,13 @@
+{
+  "description": "Chrome proxy test sites",
+  "archive_data_file": "../data/chrome_proxy_safebrowsing.json",
+  "pages": [
+    {
+      "url": "http://www.ianfette.org/",
+      "why": "Expect 'malware ahead' page. Use a short navigation timeout because no response will be received.",
+      "navigate_steps" : [
+        { "action": "navigate", "timeout_seconds": 5 }
+      ]
+    }
+  ]
+}
diff --git a/tools/perf/page_sets/chrome_proxy/smoke.json b/tools/perf/page_sets/chrome_proxy/smoke.json
new file mode 100644
index 0000000..b55e343
--- /dev/null
+++ b/tools/perf/page_sets/chrome_proxy/smoke.json
@@ -0,0 +1,40 @@
+{
+  "description": "Chrome proxy test sites",
+  "archive_data_file": "../data/chrome_proxy_smoke.json",
+  "pages": [
+    {
+      "name": "header validation",
+      "url": "http://aws1.mdw.la/fw/",
+      "why": "Check chrome proxy response headers."
+    },
+    {
+      "name": "compression: image",
+      "url": "http://aws1.mdw.la/static/",
+      "why": "Check data compression"
+    },
+    {
+      "name": "bypass",
+      "url": "http://aws1.mdw.la/bypass/",
+      "why": "Check bypass",
+      "restart_after": true
+    },
+    {
+      "name": "compression: javascript",
+      "url": "http://aws1.mdw.la/static/",
+      "why": "Check data compression"
+    },
+    {
+      "name": "compression: css",
+      "url": "http://aws1.mdw.la/static/",
+      "why": "Check data compression"
+    },
+    {
+      "name": "safebrowsing",
+      "url": "http://www.ianfette.org/",
+      "why": "Expect 'malware ahead' page. Use a short navigation timeout because no response will be received.",
+      "navigate_steps" : [
+        { "action": "navigate", "timeout_seconds": 5 }
+      ]
+    }
+  ]
+}
diff --git a/tools/perf/page_sets/chrome_proxy/synthetic.json b/tools/perf/page_sets/chrome_proxy/synthetic.json
new file mode 100644
index 0000000..3f42d18
--- /dev/null
+++ b/tools/perf/page_sets/chrome_proxy/synthetic.json
@@ -0,0 +1,14 @@
+{
+  "description": "Chrome proxy synthetic test pages.",
+  "archive_data_file": "../data/chrome_proxy_synthetic.json",
+  "pages": [
+    {
+      "url": "http://aws1.mdw.la/fw",
+      "why": ""
+    },
+    {
+      "url": "http://aws1.mdw.la/static",
+      "why": ""
+    }
+  ]
+}
diff --git a/tools/perf/page_sets/chrome_proxy/top_20.json b/tools/perf/page_sets/chrome_proxy/top_20.json
new file mode 100644
index 0000000..d049ab9
--- /dev/null
+++ b/tools/perf/page_sets/chrome_proxy/top_20.json
@@ -0,0 +1,94 @@
+{
+  "description": "Pages hand-picked for Chrome Proxy tests.",
+  "archive_data_file": "../data/chrome_proxy_top_20.json",
+  "pages": [
+    {
+      "url": "https://www.google.com/#hl=en&q=barack+obama",
+      "why": "top google property; a google tab is often open"
+    },
+    {
+      "url": "http://www.youtube.com",
+      "why": "#3 (Alexa global)"
+    },
+    {
+      "name": "Wordpress",
+      "url": "http://en.blog.wordpress.com/2012/09/04/freshly-pressed-editors-picks-for-august-2012/",
+      "why": "#18 (Alexa global), Picked an interesting post"
+    },
+    {
+      "name": "Facebook",
+      "url": "http://www.facebook.com/barackobama",
+      "why": "top social,Public profile"
+    },
+    {
+      "name": "LinkedIn",
+      "url": "http://www.linkedin.com/in/linustorvalds",
+      "why": "#12 (Alexa global),Public profile"
+    },
+    {
+      "name": "Wikipedia (1 tab)",
+      "url": "http://en.wikipedia.org/wiki/Wikipedia",
+      "why": "#6 (Alexa) most visited worldwide,Picked an interesting page"
+    },
+    {
+      "name": "Twitter",
+      "url": "https://twitter.com/katyperry",
+      "why": "#8 (Alexa global),Picked an interesting page"
+    },
+    {
+      "name": "Pinterest",
+      "url": "http://pinterest.com",
+      "why": "#37 (Alexa global)"
+    },
+    {
+      "name": "ESPN",
+      "url": "http://espn.go.com",
+      "why": "#1 sports"
+    },
+    {
+      "url": "http://news.yahoo.com",
+      "why": "#1 news worldwide (Alexa global)"
+    },
+    {
+      "url": "http://www.cnn.com",
+      "why": "#2 news worldwide"
+    },
+    {
+      "name": "Weather.com",
+      "url": "http://www.weather.com/weather/right-now/Mountain+View+CA+94043",
+      "why": "#7 (Alexa news); #27 total time spent,Picked interesting page"
+    },
+    {
+      "url": "http://www.amazon.com",
+      "why": "#1 world commerce website by visits; #3 commerce in the US by time spent"
+    },
+    {
+      "url": "http://www.ebay.com",
+      "why": "#1 commerce website by time spent by users in US"
+    },
+    {
+      "url": "http://games.yahoo.com",
+      "why": "#1 games according to Alexa (with actual games in it)"
+    },
+    {
+      "url": "http://booking.com",
+      "why": "#1 Alexa recreation"
+    },
+    {
+      "url": "http://answers.yahoo.com",
+      "why": "#1 Alexa reference"
+    },
+    {
+      "url": "http://sports.yahoo.com/",
+      "why": "#1 Alexa sports"
+    },
+    {
+      "url": "http://techcrunch.com",
+      "why": "top tech blog"
+    },
+    {
+      "url": "http://www.nytimes.com",
+      "why": ""
+    }
+  ]
+}
diff --git a/tools/perf/page_sets/data/chrome_proxy_bypass.json b/tools/perf/page_sets/data/chrome_proxy_bypass.json
new file mode 100644
index 0000000..c423c2d
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_bypass.json
@@ -0,0 +1,9 @@
+{
+    "description": "Describes the Web Page Replay archives for a page set. Don't edit by hand! Use record_wpr for updating.", 
+    "archives": {
+        "chrome_proxy_bypass_000.wpr": [
+            "http://aws1.mdw.la/bypass/", 
+            "http://aws1.mdw.la/piatek/bypass-demo"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_bypass_000.wpr.sha1 b/tools/perf/page_sets/data/chrome_proxy_bypass_000.wpr.sha1
new file mode 100644
index 0000000..b9a9f39
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_bypass_000.wpr.sha1
@@ -0,0 +1 @@
+ff4418fccf62dd0f9ca0b738917d836964dde801
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_safebrowsing.json b/tools/perf/page_sets/data/chrome_proxy_safebrowsing.json
new file mode 100644
index 0000000..729ff78
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_safebrowsing.json
@@ -0,0 +1,8 @@
+{
+    "description": "Describes the Web Page Replay archives for a page set. Don't edit by hand! Use record_wpr for updating.", 
+    "archives": {
+        "chrome_proxy_safebrowsing_000.wpr": [
+            "http://www.ianfette.org/"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_safebrowsing_000.wpr.sha1 b/tools/perf/page_sets/data/chrome_proxy_safebrowsing_000.wpr.sha1
new file mode 100644
index 0000000..b9a9f39
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_safebrowsing_000.wpr.sha1
@@ -0,0 +1 @@
+ff4418fccf62dd0f9ca0b738917d836964dde801
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_smoke.json b/tools/perf/page_sets/data/chrome_proxy_smoke.json
new file mode 100644
index 0000000..9bd0690
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_smoke.json
@@ -0,0 +1,13 @@
+{
+    "description": "Describes the Web Page Replay archives for a page set. Don't edit by hand! Use record_wpr for updating.", 
+    "archives": {
+        "chrome_proxy_smoke_000.wpr": [
+            "header validation", 
+            "compression: image", 
+            "bypass", 
+            "compression: javascript", 
+            "compression: css", 
+            "safebrowsing"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_smoke_000.wpr.sha1 b/tools/perf/page_sets/data/chrome_proxy_smoke_000.wpr.sha1
new file mode 100644
index 0000000..b9a9f39
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_smoke_000.wpr.sha1
@@ -0,0 +1 @@
+ff4418fccf62dd0f9ca0b738917d836964dde801
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_synthetic.json b/tools/perf/page_sets/data/chrome_proxy_synthetic.json
new file mode 100644
index 0000000..af3151c
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_synthetic.json
@@ -0,0 +1,9 @@
+{
+    "description": "Describes the Web Page Replay archives for a page set. Don't edit by hand! Use record_wpr for updating.", 
+    "archives": {
+        "chrome_proxy_synthetic_000.wpr": [
+            "http://aws1.mdw.la/fw", 
+            "http://aws1.mdw.la/static"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_synthetic_000.wpr.sha1 b/tools/perf/page_sets/data/chrome_proxy_synthetic_000.wpr.sha1
new file mode 100644
index 0000000..b9a9f39
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_synthetic_000.wpr.sha1
@@ -0,0 +1 @@
+ff4418fccf62dd0f9ca0b738917d836964dde801
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_top_20.json b/tools/perf/page_sets/data/chrome_proxy_top_20.json
new file mode 100644
index 0000000..7fdb557
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_top_20.json
@@ -0,0 +1,27 @@
+{
+    "description": "Describes the Web Page Replay archives for a page set. Don't edit by hand! Use record_wpr for updating.", 
+    "archives": {
+        "chrome_proxy_top_20_000.wpr": [
+            "https://www.google.com/#hl=en&q=barack+obama", 
+            "http://www.youtube.com", 
+            "Wordpress", 
+            "Facebook", 
+            "LinkedIn", 
+            "Wikipedia (1 tab)", 
+            "Twitter", 
+            "Pinterest", 
+            "ESPN", 
+            "http://news.yahoo.com", 
+            "http://www.cnn.com", 
+            "Weather.com", 
+            "http://www.amazon.com", 
+            "http://www.ebay.com", 
+            "http://games.yahoo.com", 
+            "http://booking.com", 
+            "http://answers.yahoo.com", 
+            "http://sports.yahoo.com/", 
+            "http://techcrunch.com", 
+            "http://www.nytimes.com"
+        ]
+    }
+}
\ No newline at end of file
diff --git a/tools/perf/page_sets/data/chrome_proxy_top_20_000.wpr.sha1 b/tools/perf/page_sets/data/chrome_proxy_top_20_000.wpr.sha1
new file mode 100644
index 0000000..b9a9f39
--- /dev/null
+++ b/tools/perf/page_sets/data/chrome_proxy_top_20_000.wpr.sha1
@@ -0,0 +1 @@
+ff4418fccf62dd0f9ca0b738917d836964dde801
\ No newline at end of file
diff --git a/tools/perf/page_sets/key_silk_cases.json b/tools/perf/page_sets/key_silk_cases.json
index d1c21fa..e8f9ec6 100644
--- a/tools/perf/page_sets/key_silk_cases.json
+++ b/tools/perf/page_sets/key_silk_cases.json
@@ -178,7 +178,7 @@
       "slide_drawer": [
         {
           "action": "swipe",
-          "element_function": "function(callback) { callback(document.getElementById('content')); }",
+          "element_function": "function(callback) { callback(document.getElementById('nav-drawer').children[0]); }",
           "distance": 200,
           "direction": "left",
           "left_start_percentage": 0.8,
diff --git a/tools/perf/page_sets/key_silk_cases/inbox_app.html b/tools/perf/page_sets/key_silk_cases/inbox_app.html
index 305d935..c379c79 100644
--- a/tools/perf/page_sets/key_silk_cases/inbox_app.html
+++ b/tools/perf/page_sets/key_silk_cases/inbox_app.html
@@ -7,40 +7,44 @@
 <html>
   <head>
     <title>app-widgets</title>
-    <script>// Copyright (c) 2012 The Polymer Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-function PointerGestureEvent(a,b){var c=b||{},d=document.createEvent("Event"),e={bubbles:Boolean(c.bubbles)===c.bubbles||!0,cancelable:Boolean(c.cancelable)===c.cancelable||!0};d.initEvent(a,e.bubbles,e.cancelable);for(var f,g=Object.keys(c),h=0;h<g.length;h++)f=g[h],d[f]=c[f];return d.preventTap=this.preventTap,d}"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),function(a){"use strict";function b(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={};if(Object.observe(c,a),c.id=1,c.id=2,delete c.id,Object.deliverChangeRecords(a),3!==b.length)return!1;if("new"==b[0].type&&"updated"==b[1].type&&"deleted"==b[2].type)F="new",G="updated",H="reconfigured",I="deleted";else if("add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type)return console.error("Unexpected change record names for Object.observe. Using dirty-checking instead"),!1;return Object.unobserve(c,a),c=[0],Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),2!=b.length?!1:b[0].type!=J||b[1].type!=J?!1:(Array.unobserve(c,a),!0)}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:M(a)&&M(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:U.test(a))}function i(a,b){if(b!==V)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),L&&!K&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=W[a];if(b)return b;if(!h(a))return X;var b=new i(a,V);return W[a]=b,b}function k(b){for(var c=0;Y>c&&b.check_();)b.report_(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c){if(this.closed_=!1,this.object_=a,this.callback=b,this.target=c,this.reporting_=!0,K){var d=this;this.boundInternalCallback_=function(a){d.internalCallback_(a)}}q(this)}function q(a){$&&(Z.push(a),p._allObserversCount++)}function r(a,b,c){p.call(this,a,b,c),this.connect_(),this.sync_(!0)}function s(a,b,c){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g){var b=b instanceof i?b:j(b);return b.valid&&b.length&&f(a)?(p.call(this,a,c,d),this.transformFn_=e,this.setValueFn_=g,this.path_=b,this.connect_(),this.sync_(!0),void 0):(this.value_=b.getValueFrom(a),this.value=e?e(this.value_):this.value_,this.closed_=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b),this.transformFn_=c,this.setValueFn_=d,this.observed_=[],this.values_=[],this.value=void 0,this.oldValue=void 0,this.oldValues_=void 0,this.changeFlags_=void 0,this.started_=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];db[g.type]?(g.name in c||(c[g.name]=g.oldValue),g.type!=G&&(g.type!=F?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return ib.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case J:C(c,g.index,g.removed.slice(),g.addedCount);break;case F:case G:case I:if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F="add",G="update",H="reconfigure",I="delete",J="splice",K=b(),L=c(),M=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},N="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},O="[$_a-zA-Z]",P="[$_a-zA-Z0-9]",Q=O+"+"+P+"*",R="(?:[0-9]|[1-9]+[0-9]+)",S="(?:"+Q+"|"+R+")",T="(?:"+S+")(?:\\s*\\.\\s*"+S+")*",U=new RegExp("^"+T+"$"),V={},W={};i.get=j,i.prototype=N({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++){{this[e]}c+=a[e],b+=" &&\n     "+c+" != null"}return b+=")\n",c+=a[e],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var X=new i("",V);X.valid=!1,X.getValueFrom=X.setValueFrom=function(){};var Y=1e3;p.prototype={internalCallback_:function(a){this.closed_||this.reporting_&&this.check_(a)&&(this.report_(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed_||(this.object_&&"function"==typeof this.object_.close&&this.object_.close(),this.disconnect_(),this.object_=void 0,this.closed_=!0)},deliver:function(a){this.closed_||(K?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback_),this.testingResults=void 0):k(this))},report_:function(){this.reporting_&&(this.sync_(!1),this.callback&&this.invokeCallback_(this.reportArgs),this.reportArgs=void 0)},invokeCallback_:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed_||(K&&(this.reporting_=!1,Object.deliverChangeRecords(this.boundInternalCallback_),this.reporting_=!0),this.sync_(!0))}};var Z,$=!K||a.forceCollectObservers;p._allObserversCount=0,$&&(Z=[]);var _=!1,ab="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!_){if(ab)return Object.deliverAllChangeRecords(),void 0;if($){_=!0;var b=0,c={};do{b++;var d=Z;Z=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed_||(K?f.deliver(c):f.check_()&&(c.anyChanged=!0,f.report_()),Z.push(f))}}while(Y>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=Z.length,_=!1}}},$&&(a.Platform.clearObservers=function(){Z=[]}),r.prototype=N({__proto__:p.prototype,connect_:function(){K&&Object.observe(this.object_,this.boundInternalCallback_)},sync_:function(){K||(this.oldObject=o(this.object_))},check_:function(a){var b,c;if(K){if(!a)return!1;c={},b=x(this.object_,a,c)}else c=this.oldObject,b=n(this.object_,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect_:function(){K?this.object_&&Object.unobserve(this.object_,this.boundInternalCallback_):this.oldObject=void 0}}),s.prototype=N({__proto__:r.prototype,connect_:function(){K&&Array.observe(this.object_,this.boundInternalCallback_)},sync_:function(){K||(this.oldObject=this.object_.slice())},check_:function(a){var b;if(K){if(!a)return!1;b=E(this.object_,a)}else b=A(this.object_,0,this.object_.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var bb=Object.getPrototypeOf({}),cb=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==bb&&a!==cb){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=N({__proto__:p.prototype,connect_:function(){K&&(this.observedSet_=new t(this.boundInternalCallback_))},disconnect_:function(){this.value=void 0,this.value_=void 0,this.observedSet_&&(this.observedSet_.reset(),this.observedSet_.cleanup(),this.observedSet_=void 0)},check_:function(){return this.observedSet_&&this.observedSet_.reset(),this.value_=this.path_.getValueFrom(this.object_,this.observedSet_),this.observedSet_&&this.observedSet_.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.transformFn_?this.transformFn_(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync_:function(a){a&&(this.observedSet_&&this.observedSet_.reset(),this.value_=this.path_.getValueFrom(this.object_,this.observedSet_),this.value=this.transformFn_?this.transformFn_(this.value_):this.value_,this.observedSet_&&this.observedSet_.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.setValueFn_?this.setValueFn_(a):this.path_&&this.path_.setValueFrom(this.object_,a)}}),v.prototype=N({__proto__:u.prototype,addPath:function(a,b){if(this.started_)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b.getValueFrom(a);this.observed_.push(a,b),this.values_.push(c)},start:function(){this.started_=!0,this.connect_(),this.sync_(!0)},getValues_:function(){this.observedSet_&&this.observedSet_.reset();for(var a=!1,b=0;b<this.observed_.length;b+=2){var c=this.observed_[b+1],d=this.observed_[b],e=c.getValueFrom(d,this.observedSet_),f=this.values_[b/2];if(!g(e,f)){if(!a&&!this.transformFn_){this.oldValues_=this.oldValues_||[],this.changeFlags_=this.changeFlags_||[];for(var h=0;h<this.values_.length;h++)this.oldValues_[h]=this.values_[h],this.changeFlags_[h]=!1}this.transformFn_||(this.changeFlags_[b/2]=!0),this.values_[b/2]=e,a=!0}}return this.observedSet_&&this.observedSet_.cleanup(),a},check_:function(){if(this.getValues_()){if(this.transformFn_){if(this.value=this.transformFn_(this.values_),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values_,this.oldValues_,this.changeFlags_,this.observed_];return!0}},sync_:function(a){a&&(this.getValues_(),this.transformFn_&&(this.value=this.transformFn_(this.values_))),this.transformFn_&&(this.oldValue=this.value)},close:function(){if(this.observed_){for(var a=0;a<this.observed_.length;a+=2){var b=this.observed_[a];b&&"function"==typeof b.close&&b.close()}this.observed_=void 0,this.values_=void 0}p.prototype.close.call(this)}});var db={};db[F]=!0,db[G]=!0,db[I]=!0,u.defineProperty=function(a,b,c,d){d=j(d);var e=w(a,b),f=new u(c,d,function(a,b){e&&e(G,b)});return Object.defineProperty(a,b,{get:function(){return d.getValueFrom(c)},set:function(a){d.setValueFrom(c,a)},configurable:!0}),{close:function(){var g=d.getValueFrom(c);e&&f.deliver(),f.close(),Object.defineProperty(a,b,{value:g,writable:!0,configurable:!0})}}};var eb=0,fb=1,gb=2,hb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(eb):(e.push(fb),d=g),b--,c--):f==h?(e.push(hb),b--,d=h):(e.push(gb),c--,d=i)}else e.push(hb),b--;else e.push(gb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,c-b==0&&f-e==0)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case eb:j&&(l.push(j),j=void 0),m++,n++;break;case fb:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case gb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case hb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var ib=new z;a.Observer=p,a.Observer.hasObjectObserve=K,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return ib.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i,a.Observer.changeRecordTypes={add:F,update:G,reconfigure:H,"delete":I,splice:J}}("undefined"!=typeof global&&global?global:this||window),window.Platform=window.Platform||{},window.logFlags=window.logFlags||{},function(a){var b=a.flags||{};location.search.slice(1).split("&").forEach(function(a){a=a.split("="),a[0]&&(b[a[0]]=a[1]||!0)}),b.shadow=b.shadow||b.shadowdom||b.polyfill,b.shadow="native"===b.shadow?!1:b.shadow||!HTMLElement.prototype.createShadowRoot&&"polyfill",a.flags=b}(Platform),"polyfill"===Platform.flags.shadow?(window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return L(b).forEach(function(c){K(a,c,M(b,c))}),a}function d(a,b){return L(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}K(a,c,M(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=E.get(b);if(c)return c;var d=f(b),e=t(d);return q(b,e,a),e}function g(a,b){o(a,b,!0)}function h(a,b){o(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return H&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return H&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return H&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(a,b){try{return Object.getOwnPropertyDescriptor(a,b)}catch(c){return O}}function o(b,c,d){for(var e=L(b),f=0;f<e.length;f++){var g=e[f];if("polymerBlackList_"!==g&&!(g in c||b.polymerBlackList_&&b.polymerBlackList_[g])){N&&b.__lookupGetter__(g);var h,j,o=n(b,g);if(d&&"function"==typeof o.value)c[g]=m(g);else{var p=i(g);h=p?a.getEventHandlerGetter(g):k(g),(o.writable||o.set)&&(j=p?a.getEventHandlerSetter(g):l(g)),K(c,g,{get:h,set:j,configurable:o.configurable,enumerable:o.enumerable})}}}}function p(a,b,c){var e=a.prototype;q(e,b,c),d(b,a)}function q(a,c,d){var e=c.prototype;b(void 0===E.get(a)),E.set(a,c),F.set(e,a),g(a,e),d&&h(e,d),K(e,"constructor",{value:c,configurable:!0,enumerable:!1,writable:!0})}function r(a,b){return E.get(b.prototype)===a}function s(a){var b=Object.getPrototypeOf(a),c=f(b),d=t(c);return q(b,d,a),d}function t(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function u(a){return a instanceof G.EventTarget||a instanceof G.Event||a instanceof G.Range||a instanceof G.DOMImplementation||a instanceof G.CanvasRenderingContext2D||G.WebGLRenderingContext&&a instanceof G.WebGLRenderingContext}function v(a){return a instanceof R||a instanceof Q||a instanceof S||a instanceof T||a instanceof P||a instanceof U||V&&a instanceof V}function w(a){return null===a?null:(b(v(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function x(a){return null===a?null:(b(u(a)),a.impl)}function y(a){return a&&u(a)?x(a):a}function z(a){return a&&!u(a)?w(a):a}function A(a,c){null!==c&&(b(v(a)),b(void 0===c||u(c)),a.polymerWrapper_=c)}function B(a,b,c){K(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function C(a,b){B(a,b,function(){return w(this.impl[b])})}function D(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=z(this);return a[b].apply(a,arguments)}})})}var E=new WeakMap,F=new WeakMap,G=Object.create(null),H=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(H)try{var I=new Function("","return true;");H=I()}catch(J){H=!1}var K=Object.defineProperty,L=Object.getOwnPropertyNames,M=Object.getOwnPropertyDescriptor;L(window);var N=/Firefox/.test(navigator.userAgent),O={get:function(){},set:function(){},configurable:!0,enumerable:!0},P=window.DOMImplementation,Q=window.Event,R=window.Node,S=window.Window,T=window.Range,U=window.CanvasRenderingContext2D,V=window.WebGLRenderingContext;a.assert=b,a.constructorTable=E,a.defineGetter=B,a.defineWrapGetter=C,a.forwardMethodsToWrapper=D,a.isWrapper=u,a.isWrapperFor=r,a.mixin=c,a.nativePrototypeTable=F,a.oneOf=e,a.registerObject=s,a.registerWrapper=p,a.rewrap=A,a.unwrap=x,a.unwrapIfNeeded=y,a.wrap=w,a.wrapIfNeeded=z,a.wrappers=G}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if((h===a||l.subtree)&&!("attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var l=null;if(g.length){if(c(i)&&(l=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(m(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,l,e)}a=b(a)?a.host:a.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(a,b){return a===b?!0:a instanceof O.ShadowRoot?n(l(a.host),b):!1}function o(a){return Q.get(a)?void 0:(Q.set(a,!0),p(N(a),N(a.target)))}function p(b,c){if(R.get(b))throw new Error("InvalidStateError");R.set(b,!0),a.renderAllPending();var d=g(c);return"load"===b.type&&2===d.length&&d[0].target instanceof O.Document&&d.shift(),Z.set(b,d),q(b,d)&&r(b,d)&&s(b,d),V.set(b,v.NONE),T.delete(b,null),R.delete(b),b.defaultPrevented}function q(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=v.CAPTURING_PHASE,!t(b[d],a,c)))return!1}return!0}function r(a,b){var c=v.AT_TARGET;return t(b[0],a,c)}function s(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=v.AT_TARGET;else{if(!d||X.get(a))continue;c=v.BUBBLING_PHASE}if(!t(b[e],a,c))return}}function t(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;U.set(b,j)}}V.set(b,c);var k=b.type,l=!1;S.set(b,d),T.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===v.CAPTURING_PHASE||n.capture&&c===v.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),X.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!W.get(b)}function u(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function v(a,b){return a instanceof $?(this.impl=a,void 0):N(z($,"Event",a,b))}function w(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function x(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(z(d,a,b,c))};if(e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d)try{L(d,e,new d("temp"))}catch(f){L(d,e,document.createEvent(a))}return e}function y(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function z(a,b,c,d){if(hb)return new a(c,w(d));var e=M(document.createEvent(b)),f=gb[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function A(){v.call(this)}function B(a){return"function"==typeof a?!0:a&&a.handleEvent}function C(a){switch(a){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function D(a){this.impl=a}function E(a){return a instanceof O.ShadowRoot&&(a=a.host),M(a)}function F(a){J(a,kb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(lb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=Y.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=Y.get(this);d||(d=Object.create(null),Y.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers,P=(new WeakMap,new WeakMap),Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap;u.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var $=window.Event;$.prototype.polymerBlackList_={returnValue:!0},v.prototype={get target(){return S.get(this)},get currentTarget(){return T.get(this)},get eventPhase(){return V.get(this)},get path(){var a=new O.NodeList,b=Z.get(this);if(b){for(var c=0,d=b.length-1,e=l(T.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){W.set(this,!0)},stopImmediatePropagation:function(){W.set(this,!0),X.set(this,!0)}},L($,v,document.createEvent("Event"));var _=x("UIEvent",v),ab=x("CustomEvent",v),bb={get relatedTarget(){return U.get(this)||N(M(this).relatedTarget)}},cb=K({initMouseEvent:y("initMouseEvent",14)},bb),db=K({initFocusEvent:y("initFocusEvent",5)},bb),eb=x("MouseEvent",_,cb),fb=x("FocusEvent",_,db),gb=Object.create(null),hb=function(){try{new window.FocusEvent("focus")}catch(a){return!1}return!0}();if(!hb){var ib=function(a,b,c){if(c){var d=gb[c];b=K(K({},d),b)}gb[a]=b};ib("Event",{bubbles:!1,cancelable:!1}),ib("CustomEvent",{detail:null},"Event"),ib("UIEvent",{view:null,detail:0},"Event"),ib("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),ib("FocusEvent",{relatedTarget:null},"UIEvent")}A.prototype=Object.create(v.prototype),K(A.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}});var jb=window.EventTarget,kb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;kb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(B(b)&&!C(a)){var d=new u(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,o,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,o,!0)}}},dispatchEvent:function(a){p(a,this)}},jb&&L(jb,D);var lb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.wrapEventTargetMethods=F,a.wrappers.BeforeUnloadEvent=A,a.wrappers.CustomEvent=ab,a.wrappers.Event=v,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=fb,a.wrappers.MouseEvent=eb,a.wrappers.UIEvent=_}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d
-}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){v(a instanceof s)}function c(a){var b=new u;return b[0]=a,b.length=1,b}function d(a,b,c){x(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){x(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);F=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;F=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new u,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b.length=c,e(a,b),b}function i(a){return a}function j(a){a.nodeIsInserted_()}function k(a){for(var b=0;b<a.length;b++)j(a[b])}function l(){}function m(){}function n(a,b){var c=a.nodeType===s.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function p(a,b){o(a,b);var c=b.length;if(1===c)return C(b[0]);for(var d=C(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(C(b[e]));return d}function q(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){v(b.parentNode===a);var c=b.nextSibling,d=C(b),e=d.parentNode;e&&K.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=C(a),g=f.firstChild;g;)c=g.nextSibling,K.call(f,g),g=c}function r(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function s(a){v(a instanceof G),t.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var t=a.wrappers.EventTarget,u=a.wrappers.NodeList,v=a.assert,w=a.defineWrapGetter,x=a.enqueueMutation,y=a.isWrapper,z=a.mixin,A=a.registerTransientObservers,B=a.registerWrapper,C=a.unwrap,D=a.wrap,E=a.wrapIfNeeded,F=!1,G=window.Node,H=window.DocumentFragment,I=(G.prototype.appendChild,G.prototype.compareDocumentPosition),J=G.prototype.insertBefore,K=G.prototype.removeChild,L=G.prototype.replaceChild,M=/Trident/.test(navigator.userAgent),N=M?function(a,b){try{K.call(a,b)}catch(c){if(!(a instanceof H))throw c}}:function(a,b){K.call(a,b)};s.prototype=Object.create(t.prototype),z(s.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a);var d;c?y(c)?d=C(c):(d=c,c=D(d)):(c=null,d=null),c&&v(c.parentNode===this);var e,h=c?c.previousSibling:this.lastChild,i=!this.invalidateShadowRenderer()&&!r(a);if(e=i?g(a):f(a,this,h,c),i)n(this,a),J.call(this.impl,C(a),d);else{h||(this.firstChild_=e[0]),c||(this.lastChild_=e[e.length-1]);var j=d?d.parentNode:this.impl;j?J.call(j,p(this,e),d):o(this,e)}return x(this,"childList",{addedNodes:e,nextSibling:c,previousSibling:h}),k(e),a},removeChild:function(a){if(b(a),a.parentNode!==this){for(var d=!1,e=(this.childNodes,this.firstChild);e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=C(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&N(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else N(this.impl,f);return F||x(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),A(this,a),a},replaceChild:function(a,d){b(a);var e;if(y(d)?e=C(d):(e=d,d=D(e)),d.parentNode!==this)throw new Error("NotFoundError");var h,i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!r(a);return m?h=g(a):(i===a&&(i=a.nextSibling),h=f(a,this,j,i)),m?(n(this,a),L.call(this.impl,C(a),e)):(this.firstChild===d&&(this.firstChild_=h[0]),this.lastChild===d&&(this.lastChild_=h[h.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,e.parentNode&&L.call(e.parentNode,p(this,h),e)),x(this,"childList",{addedNodes:h,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(h),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:D(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:D(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:D(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:D(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:D(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==s.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(q(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else this.impl.textContent=a;var d=i(this.childNodes);x(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d)},get childNodes(){for(var a=new u,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){var b=D(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=E(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return I.call(this.impl,C(a))}}),w(s,"ownerDocument"),B(G,s,document.createDocumentFragment()),delete s.prototype.querySelector,delete s.prototype.querySelectorAll,s.prototype=z(Object.create(t.prototype),s.prototype),a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=s}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=a.oneOf,n=a.registerWrapper,o=a.wrappers,p=window.Element,q=m(p.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),r=p.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new o.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),"matches"!=q&&(d.prototype[q]=function(a){return this.matches(a)}),p.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),n(p,d),a.matchesName=q,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case'"':return"&quot;"}}function c(a){return a.replace(w,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",x[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=u(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(v(f))}function g(a){m.call(this,a)}function h(a,b){var c=u(a.cloneNode(!1));c.innerHTML=b;for(var d,e=u(document.createDocumentFragment());d=c.firstChild;)e.appendChild(d);return v(e)}function i(b){return function(){return a.renderAllPending(),this.impl[b]}}function j(a){n(g,a,i(a))}function k(b){Object.defineProperty(g.prototype,b,{get:i(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function l(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var m=a.wrappers.Element,n=a.defineGetter,o=a.enqueueMutation,p=a.mixin,q=a.nodesWereAdded,r=a.nodesWereRemoved,s=a.registerWrapper,t=a.snapshotNodeList,u=a.unwrap,v=a.wrap,w=/&|<|"/g,x={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},y=window.HTMLElement;g.prototype=Object.create(m.prototype),p(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){var b=t(this.childNodes);this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a;var c=t(this.childNodes);o(this,"childList",{addedNodes:c,removedNodes:b}),r(b),q(c)},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;if(b){b.invalidateShadowRenderer();var c=h(b,a);b.replaceChild(c,this)}},insertAdjacentHTML:function(a,b){var c,d;switch(String(a).toLowerCase()){case"beforebegin":c=this.parentNode,d=this;break;case"afterend":c=this.parentNode,d=this.nextSibling;break;case"afterbegin":c=this,d=this.firstChild;break;case"beforeend":c=this,d=null;break;default:return}var e=h(c,b);c.insertBefore(e,d)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(j),["scrollLeft","scrollTop"].forEach(k),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(l),s(y,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=m.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);m.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=j(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!n){var b=c(a);l.set(this,k(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.registerWrapper,i=a.setInnerHTML,j=a.unwrap,k=a.wrap,l=new WeakMap,m=new WeakMap,n=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return n?k(this.impl.content):l.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){i(this.content,a)}}),n&&h(n,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(g){c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},get host(){return j.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=F(a),g=F(c),h=e?F(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=G(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=F(a),d=c.parentNode;if(d){var e=G(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=I.get(a);c||I.set(a,c=[]),c.push(b)}function f(a){H.set(a,[])}function g(a){return H.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof z))return!1;if(!L.test(c))return!1;if(":"===c[0]&&!M.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<O.length;a++)O[a].render();O=[]}function l(){y=null,k()}function m(a){var b=K.get(a);return b||(b=new q(a),K.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof D)return a;return null}function o(a){return m(a.host)}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof A}function s(a){return a instanceof A}function t(a){return a instanceof B}function u(a){return a instanceof B}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){J.set(a,b)}var y,z=a.wrappers.Element,A=a.wrappers.HTMLContentElement,B=a.wrappers.HTMLShadowElement,C=a.wrappers.Node,D=a.wrappers.ShadowRoot,E=(a.assert,a.mixin,a.oneOf),F=a.unwrap,G=a.wrap,H=new WeakMap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=/^[*.:#[a-zA-Z_|]/,M=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),N=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),O=[],P=new ArraySplice;P.equals=function(a,b){return F(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(F(b)),g=a||new WeakMap,i=P.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=G(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&G(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,O.push(this),y)return;y=window[N](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},C.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},A.prototype.getDistributedNodes=function(){return k(),g(this)},B.prototype.nodeIsInserted_=A.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=I,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=J,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){z.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.rewrap,x=a.wrapEventTargetMethods,y=(a.wrapNodeList,new WeakMap);b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var z=document.adoptNode,A=document.importNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)},importNode:function(a,b){var c=v(A.call(this.impl,u(a),!1));if(b)for(var d=a.firstChild;d;d=d.nextSibling)c.appendChild(this.importNode(d,!0));return c}}),document.register){var B=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):c.extends?document.createElement(c.extends,b):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){v(this)instanceof d||w(this),b.apply(v(this),arguments)})});var k={prototype:i};c.extends&&(k.extends=c.extends),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i);B.call(u(this),b,k);return d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=y.get(this);return a?a:(a=new g(u(this).implementation),y.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),x([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)
-},delete window.getComputedStyle,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)},delete window[a]}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(window.ShadowDOMPolyfill),function(){window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded,Object.defineProperty(Element.prototype,"webkitShadowRoot",Object.getOwnPropertyDescriptor(Element.prototype,"shadowRoot"));var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b},Element.prototype.webkitCreateShadowRoot=Element.prototype.createShadowRoot}(),function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim",""),h.shadowCssShim=!0),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b);var h=this.stylesToShimmedCssText(g.rootStyles,g.scopeStyles,b,e);g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},stylesToShimmedCssText:function(a,b,c,d){c=c||"",this.insertPolyfillDirectives(a),this.insertPolyfillRules(a);var e=this.shimAtHost(b,c,d)+this.shimScoping(b,c,d);return e+=this.extractPolyfillUnscopedRules(a)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),this.makeScopeMatcher(c,f)))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n	"})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return c&&(f=this.scopeRules(g,c,e)),f},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(u,function(a,b,c,d){if(b=y,c){for(var e,f=c.split(","),g=[],h=0,i=f.length;i>h&&(e=f[h]);h++)e=e.trim(),e.match(t)?g.push(b+e.replace(t,"")+d):g.push(b+e+d+", "+e+" "+b+d);return g.join(",")}return b+d})},convertCombinators:function(a){return a.replace(/\^\^/g," ").replace(/\^/g," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n	",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b,c),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d&&!a.match(y)?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=this.makeScopeMatcher(b,c);return!a.match(d)},makeScopeMatcher:function(a,b){var c=b?"\\[is=['\"]?"+a+"['\"]?\\]":a;return new RegExp("^("+c+")"+v,"m")},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(w,t).replace(x,t)},propertiesFromRule:function(a){return a.style.cssText}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t="-shadowcsshost",u=new RegExp("("+t+")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)","gim"),v="([>\\s~+[.,{:][\\s\\S]*)?$",w=/@host/gim,x=/\:host/gim,y=t+"-no-combinator",z=new RegExp(t,"gim");if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=wrap(document),B=A.querySelector("head");B.insertBefore(g(),B.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){window.HTMLImports&&(HTMLImports.importer.preloadSelectors+=", link[rel=stylesheet]:not([nopolyfill])",HTMLImports.parser.parseGeneric=function(a){if(!a.shadowCssShim){var b=a;if(!a.hasAttribute("nopolyfill")){a.__resource&&(b=A.createElement("style"),b.textContent=a.__resource,a.ownerDocument===A&&a.parentNode.removeChild(a));var c=[b];b.textContent=i.stylesToShimmedCssText(c,c),b.shadowCssShim=!0}b.parentNode!==B&&B.appendChild(b)}})})}a.ShadowCSS=i}(window.Platform)):!function(){window.templateContent=window.templateContent||function(a){return a.content},window.wrap=window.unwrap=function(a){return a};var a=Element.prototype.webkitCreateShadowRoot;Element.prototype.webkitCreateShadowRoot=function(){var b=this.webkitShadowRoot,c=a.call(this);return c.olderShadowRoot=b,c.host=this,CustomElements.watchShadow(this),c},Object.defineProperties(Element.prototype,{shadowRoot:{get:function(){return this.webkitShadowRoot}},createShadowRoot:{value:function(){return this.webkitCreateShadowRoot()}}}),window.templateContent=function(a){if(window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(a),!a.content&&!a._content){for(var b=document.createDocumentFragment();a.firstChild;)b.appendChild(a.firstChild);a._content=b}return a.content||a._content}}(),function(a){function b(a){for(var b=a||{},d=1;d<arguments.length;d++){var e=arguments[d];try{for(var f in e)c(f,e,b)}catch(g){}}return b}function c(a,b,c){var e=d(b,a);Object.defineProperty(c,a,e)}function d(a,b){if(a){var c=Object.getOwnPropertyDescriptor(a,b);return c||d(Object.getPrototypeOf(a),b)}}Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();return d.push.apply(d,arguments),b.apply(a,d)}}),a.mixin=b}(window.Platform),function(a){"use strict";function b(a,b,c){var d="string"==typeof a?document.createElement(a):a.cloneNode(!0);if(d.innerHTML=b,c)for(var e in c)d.setAttribute(e,c[e]);return d}var c=DOMTokenList.prototype.add,d=DOMTokenList.prototype.remove;DOMTokenList.prototype.add=function(){for(var a=0;a<arguments.length;a++)c.call(this,arguments[a])},DOMTokenList.prototype.remove=function(){for(var a=0;a<arguments.length;a++)d.call(this,arguments[a])},DOMTokenList.prototype.toggle=function(a,b){1==arguments.length&&(b=!this.contains(a)),b?this.add(a):this.remove(a)},DOMTokenList.prototype.switch=function(a,b){a&&this.remove(a),b&&this.add(b)};var e=function(){return Array.prototype.slice.call(this)},f=window.NamedNodeMap||window.MozNamedAttrMap||{};if(NodeList.prototype.array=e,f.prototype.array=e,HTMLCollection.prototype.array=e,!window.performance){var g=Date.now();window.performance={now:function(){return Date.now()-g}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var a=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return a?function(b){return a(function(){b(performance.now())})}:function(a){return window.setTimeout(a,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(a){clearTimeout(a)}}());var h=document.createElement("template"),i=document.createElement("base");i.href=document.baseURI,h.content.ownerDocument.appendChild(i);var j=function(a,b){window.addEventListener("WebComponentsReady",function(){window.Polymer!==j?Polymer(a,b):console.warn('You tried to use polymer without loading it first. To load polymer, <link rel="import" href="components/polymer/plymer.html">')})};window.Polymer=j,a.createDOM=b}(window.Platform),window.templateContent=window.templateContent||function(a){return a.content},function(a){a=a||(window.Inspector={});var b;window.sinspect=function(a,d){b||(b=window.open("","ShadowDOM Inspector",null,!0),b.document.write(c),b.api={shadowize:shadowize}),f(a||wrap(document.body),d)};var c=["<!DOCTYPE html>","<html>","  <head>","    <title>ShadowDOM Inspector</title>","    <style>","      body {","      }","      pre {",'        font: 9pt "Courier New", monospace;',"        line-height: 1.5em;","      }","      tag {","        color: purple;","      }","      ul {","         margin: 0;","         padding: 0;","         list-style: none;","      }","      li {","         display: inline-block;","         background-color: #f1f1f1;","         padding: 4px 6px;","         border-radius: 4px;","         margin-right: 4px;","      }","    </style>","  </head>","  <body>",'    <ul id="crumbs">',"    </ul>",'    <div id="tree"></div>',"  </body>","</html>"].join("\n"),d=[],e=function(){var a=b.document,c=a.querySelector("#crumbs");c.textContent="";for(var e,g=0;e=d[g];g++){var h=a.createElement("a");h.href="#",h.textContent=e.localName,h.idx=g,h.onclick=function(a){for(var b;d.length>this.idx;)b=d.pop();f(b.shadow||b,b),a.preventDefault()},c.appendChild(a.createElement("li")).appendChild(h)}},f=function(a,c){var f=b.document;k=[];var g=c||a;d.push(g),e(),f.body.querySelector("#tree").innerHTML="<pre>"+j(a,a.childNodes)+"</pre>"},g=Array.prototype.forEach.call.bind(Array.prototype.forEach),h={STYLE:1,SCRIPT:1,"#comment":1,TEMPLATE:1},i=function(a){return h[a.nodeName]},j=function(a,b,c){if(i(a))return"";var d=c||"";if(a.localName||11==a.nodeType){var e=a.localName||"shadow-root",f=d+l(a);"content"==e&&(b=a.getDistributedNodes()),f+="<br/>";var h=d+"&nbsp;&nbsp;";g(b,function(a){f+=j(a,a.childNodes,h)}),f+=d,{br:1}[e]||(f+="<tag>&lt;/"+e+"&gt;</tag>",f+="<br/>")}else{var k=a.textContent.trim();f=k?d+'"'+k+'"<br/>':""}return f},k=[],l=function(a){var b="<tag>&lt;",c=a.localName||"shadow-root";return a.webkitShadowRoot||a.shadowRoot?(b+=' <button idx="'+k.length+'" onclick="api.shadowize.call(this)">'+c+"</button>",k.push(a)):b+=c||"shadow-root",a.attributes&&g(a.attributes,function(a){b+=" "+a.name+(a.value?'="'+a.value+'"':"")}),b+="&gt;</tag>"};shadowize=function(){var a=Number(this.attributes.idx.value),b=k[a];b?f(b.webkitShadowRoot||b.shadowRoot,b):(console.log("bad shadowize node"),console.dir(this))},a.output=j}(window.Inspector),function(){function a(){requestAnimationFrame(function(){for(var a,b=document.querySelectorAll(e),f=0,g=b.length;g>f&&(a=b[f]);f++)a.removeAttribute(c),a.setAttribute(d,"");if(b.length){var h=function(){for(var a,c=0,e=b.length;e>c&&(a=b[c]);c++)a.removeAttribute(d);document.body.removeEventListener(i,h,!1)};document.body.addEventListener(i,h,!1)}})}var b=.2,c="unresolved",d="resolved",e="["+c+"]",f="["+d+"]",g=document.createElement("style");g.textContent=e+" { opacity: 0; display: block; overflow: hidden; } \n"+f+"{ display: block; overflow: hidden;\n-webkit-transition: opacity "+b+"s; transition: opacity "+b+"s; }\n";var h=document.querySelector("head");h.insertBefore(g,h.firstChild);var i=void 0!==document.documentElement.style.webkitTransition?"webkitTransitionEnd":"transitionend";window.addEventListener("WebComponentsReady",a)}(Platform),function(a){function b(a){return d(a,i)}function c(a){return d(a,j)}function d(a,b){return"link"===a.localName&&a.getAttribute("rel")===b}function e(a){return"script"===a.localName}function f(a,b){var c=a;c instanceof Document||(c=document.implementation.createHTMLDocument(i)),c._URL=b;var d=c.createElement("base");return d.setAttribute("href",document.baseURI||document.URL),c.head.appendChild(d),a instanceof Document||(c.body.innerHTML=a),window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(c),c}a||(a=window.HTMLImports={flags:{}});var g,h=a.xhr,i="import",j="stylesheet",k={documents:{},cache:{},preloadSelectors:["link[rel="+i+"]","element link[rel="+j+"]","template","script[src]:not([type])",'script[src][type="text/javascript"]'].join(","),loader:function(a){return g=new l(k.loaded,a),g.cache=k.cache,g},load:function(a,b){g=k.loader(b),k.preload(a)},preload:function(a){var b=a.querySelectorAll(k.preloadSelectors);b=this.filterMainDocumentNodes(a,b),b=this.extractTemplateNodes(b),g.addNodes(b)},filterMainDocumentNodes:function(a,b){return a===document&&(b=Array.prototype.filter.call(b,function(a){return!e(a)})),b},extractTemplateNodes:function(a){var b=[];return a=Array.prototype.filter.call(a,function(a){if("template"===a.localName){if(a.content){var c=a.content.querySelectorAll("link[rel="+j+"]");c.length&&(b=b.concat(Array.prototype.slice.call(c,0)))}return!1}return!0}),b.length&&(a=a.concat(b)),a},loaded:function(a,d,e){if(b(d)){var g=k.documents[a];g||(g=f(e,a),p.resolvePathsInHTML(g),k.documents[a]=g,k.preload(g)),d.import=g,d.import.href=a,d.import.ownerNode=d,d.content=e=g}d.__resource=e,c(d)&&p.resolvePathsInStylesheet(d)}},l=function(a,b){this.onload=a,this.oncomplete=b,this.inflight=0,this.pending={},this.cache={}};l.prototype={addNodes:function(a){this.inflight+=a.length,q(a,this.require,this),this.checkDone()},require:function(a){var b=p.nodeUrl(a);b=p.makeAbsUrl(b),a.__nodeUrl=b,this.dedupe(b,a)||this.fetch(b,a)},dedupe:function(a,b){return this.pending[a]?(this.pending[a].push(b),!0):this.cache[a]?(this.onload(a,b,g.cache[a]),this.tail(),!0):(this.pending[a]=[b],!1)},fetch:function(a,b){var c=function(c,d){this.receive(a,b,c,d)}.bind(this);h.load(a,c)},receive:function(a,b,c,d){c||(g.cache[a]=d),g.pending[a].forEach(function(b){c||this.onload(a,b,d),this.tail()},this),g.pending[a]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}};var m=["href","src","action"],n="["+m.join("],[")+"]",o="{{.*}}",p={nodeUrl:function(a){return p.resolveUrl(p.documentURL,p.hrefOrSrc(a))},hrefOrSrc:function(a){return a.getAttribute("href")||a.getAttribute("src")},documentUrlFromNode:function(a){return p.getDocumentUrl(a.ownerDocument||a)},getDocumentUrl:function(a){var b=a&&(a._URL||a.impl&&a.impl._URL||a.baseURI||a.URL)||"";return b.split("#")[0]},resolveUrl:function(a,b){return this.isAbsUrl(b)?b:this.compressUrl(this.urlToPath(a)+b)},resolveRelativeUrl:function(a,b){return this.isAbsUrl(b)?b:this.makeDocumentRelPath(this.resolveUrl(a,b))},isAbsUrl:function(a){return/(^data:)|(^http[s]?:)|(^\/)/.test(a)},urlToPath:function(a){var b=a.split("/");return b.pop(),b.push(""),b.join("/")},compressUrl:function(a){var b="",c=a.indexOf("?");c>-1&&(b=a.substring(c),a=a.substring(c,0));for(var d,e=a.split("/"),f=0;f<e.length;f++)d=e[f],".."===d&&(e.splice(f-1,2),f-=2);return e.join("/")+b},makeDocumentRelPath:function(a){return p.urlElt.href=a,!p.urlElt.host||p.urlElt.host===window.location.host&&p.urlElt.protocol===window.location.protocol?this.makeRelPath(p.documentURL,p.urlElt.href):a},makeRelPath:function(a,b){for(var c=a.split("/"),d=b.split("/");c.length&&c[0]===d[0];)c.shift(),d.shift();for(var e=0,f=c.length-1;f>e;e++)d.unshift("..");var g=d.join("/");return g},makeAbsUrl:function(a){return p.urlElt.href=a,p.urlElt.href},resolvePathsInHTML:function(a,b){b=b||p.documentUrlFromNode(a),p.resolveAttributes(a,b),p.resolveStyleElts(a,b);var c=a.querySelectorAll("template");c&&q(c,function(a){a.content&&p.resolvePathsInHTML(a.content,b)})},resolvePathsInStylesheet:function(a){var b=p.nodeUrl(a);a.__resource=p.resolveCssText(a.__resource,b)},resolveStyleElts:function(a,b){var c=a.querySelectorAll("style");c&&q(c,function(a){a.textContent=p.resolveCssText(a.textContent,b)})},resolveCssText:function(a,b){return a.replace(/url\([^)]*\)/g,function(a){var c=a.replace(/["']/g,"").slice(4,-1);return c=p.resolveRelativeUrl(b,c),"url("+c+")"})},resolveAttributes:function(a,b){var c=a&&a.querySelectorAll(n);c&&q(c,function(a){this.resolveNodeAttributes(a,b)},this)},resolveNodeAttributes:function(a,b){m.forEach(function(c){var d=a.attributes[c];if(d&&d.value&&d.value.search(o)<0){var e=p.resolveRelativeUrl(b,d.value);d.value=e}})}};p.documentURL=p.getDocumentUrl(document),p.urlElt=document.createElement("a"),h=h||{async:!0,ok:function(a){return a.status>=200&&a.status<300||304===a.status||0===a.status},load:function(b,c,d){var e=new XMLHttpRequest;return(a.flags.debug||a.flags.bust)&&(b+="?"+Math.random()),e.open("GET",b,h.async),e.addEventListener("readystatechange",function(){4===e.readyState&&c.call(d,!h.ok(e)&&e,e.response||e.responseText,b)}),e.send(),e},loadDocument:function(a,b,c){this.load(a,b,c).responseType="document"}};var q=Array.prototype.forEach.call.bind(Array.prototype.forEach);Object.defineProperty(document,"_currentScript",{get:function(){return HTMLImports.currentScript||document.currentScript},writeable:!0,configurable:!0}),a.path=p,a.xhr=h,a.importer=k,a.getDocumentUrl=p.getDocumentUrl,a.IMPORT_LINK_TYPE=i}(window.HTMLImports),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===f}function c(a){return a.parentNode&&!d(a)&&!e(a)}function d(a){return a.ownerDocument===document||a.ownerDocument.impl===document}function e(a){return a.parentNode&&"element"===a.parentNode.localName}{var f="import",g={selectors:["link[rel="+f+"]","link[rel=stylesheet]","style","script:not([type])",'script[type="text/javascript"]'],map:{link:"parseLink",script:"parseScript",style:"parseGeneric"},parse:function(a){if(!a.__importParsed){a.__importParsed=!0;for(var b,c=a.querySelectorAll(g.selectors),d=a.scripts?a.scripts.length:0,e=0;e<c.length&&(b=c[e]);e++)g[g.map[b.localName]](b),a.scripts&&d!==a.scripts.length&&(d=a.scripts.length,c=a.querySelectorAll(g.selectors))}},parseLink:function(a){b(a)?a.import&&(g.parse(a.import),a.dispatchEvent(new CustomEvent("load"))):this.parseGeneric(a)},parseGeneric:function(a){c(a)&&document.head.appendChild(a)},parseScript:function(b){if(c(b)){var d=(b.__resource||b.textContent).trim();if(d){var e=b.__nodeUrl;if(!e){var e=a.path.documentUrlFromNode(b),f="["+Math.floor(1e3*(Math.random()+1))+"]",g=d.match(/Polymer\(['"]([^'"]*)/);f=g&&g[1]||f,e+="/"+f+".js"}d+="\n//# sourceURL="+e+"\n",a.currentScript=b,eval.call(window,d),a.currentScript=null}}}};Array.prototype.forEach.call.bind(Array.prototype.forEach)}a.parser=g}(HTMLImports),function(){function a(){HTMLImports.importer.load(document,function(){HTMLImports.parser.parse(document),HTMLImports.ready=!0,HTMLImports.readyTime=(new Date).getTime(),document.dispatchEvent(new CustomEvent("HTMLImportsLoaded",{bubbles:!0}))})}"function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?a():window.addEventListener("DOMContentLoaded",a)}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new WeakMap,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g,!a.MutationObserver&&a.WebKitMutationObserver&&(a.MutationObserver=a.WebKitMutationObserver),a.MutationObserver||(a.MutationObserver=g)}(this),window.CustomElements=window.CustomElements||{flags:{}},function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),q(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),q(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){p(a)}):p(a)}function p(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),q(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function q(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function r(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)s(b),b=b.olderShadowRoot}}function s(a){a.__watched||(v(a),a.__watched=!0)}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){a.localName&&g(a)}),D(a.removedNodes,function(a){a.localName&&n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=r,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");
-if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeAll(document),g.ctor}function c(a){var b=m(a);return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(x(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){if(!a.setAttribute._polyfilled){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?w[a.toLowerCase()]:void 0}function n(a,b){w[a]=b}function o(a){return function(){return f(a)}}function p(a,b){var c=m(b||a);return c?new c.ctor:x(a)}function q(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is")||a.localName,c=m(b);return c&&g(a,c)}}function r(b){var c=y.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var s=a.flags,t=Boolean(document.register),u=!s.register&&t;if(u){var v=function(){};a.registry={},a.upgradeElement=v,a.watchShadow=v,a.upgrade=v,a.upgradeAll=v,a.upgradeSubtree=v,a.observeDocument=v,a.upgradeDocument=v,a.takeRecords=v}else{var w={},x=document.createElement.bind(document),y=Node.prototype.cloneNode;document.register=b,document.createElement=p,Node.prototype.cloneNode=r,a.registry=w,a.upgrade=q}a.hasNative=t,a.useNative=u}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(a){function b(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||a.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){var a=document.createElement("style");a.textContent="element {display: none !important;} /* injected by platform.js */";var b=document.querySelector("head");if(b.insertBefore(a,b.firstChild),window.ShadowDOMPolyfill){var c=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],d={};c.forEach(function(a){d[a]=CustomElements[a]}),c.forEach(function(a){CustomElements[a]=function(b){return d[a](wrap(b))}})}}(),function(a){function b(a){f.textContent=d++,e.push(a)}function c(){for(;e.length;)e.shift()()}var d=0,e=[],f=document.createTextNode("");new(window.MutationObserver||JsMutationObserver)(c).observe(f,{characterData:!0}),a.endOfMicrotask=b}(Platform),function(a){a=a||{},a.external=a.external||{};var b={shadow:function(a){return a?a.shadowRoot||a.webkitShadowRoot:void 0},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);return this.canTarget(b)?b:void 0},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d}e=this.olderShadow(e)}return f}},owner:function(a){for(var b=a;b.parentNode;)b=b.parentNode;return b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}};a.targetFinding=b,a.findTarget=b.findTarget.bind(b),window.PointerEventsPolyfill=a}(window.PointerEventsPolyfill),function(){function a(a){return"body ^^ "+b(a)}function b(a){return'[touch-action="'+a+'"]'}function c(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; touch-action-delay: none; }"}var d=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],e="";d.forEach(function(d){String(d)===d?(e+=b(d)+c(d)+"\n",e+=a(d)+c(d)+"\n"):(e+=d.selectors.map(b)+c(d.rule)+"\n",e+=d.selectors.map(a)+c(d.rule)+"\n")});var f=document.createElement("style");f.textContent=e,document.head.appendChild(f)}(),function(a){function b(a,e){e=e||{};var f=e.buttons;if(void 0===f)switch(e.which){case 1:f=1;break;case 2:f=4;break;case 3:f=2;break;default:f=0}var i;if(c)i=new MouseEvent(a,e);else{i=document.createEvent("MouseEvent");for(var j,k={},l=0;l<g.length;l++)j=g[l],k[j]=e[j]||h[l];i.initMouseEvent(a,k.bubbles,k.cancelable,k.view,k.detail,k.screenX,k.screenY,k.clientX,k.clientY,k.ctrlKey,k.altKey,k.shiftKey,k.metaKey,k.button,k.relatedTarget)}i.__proto__=b.prototype,d||Object.defineProperty(i,"buttons",{get:function(){return f},enumerable:!0});var m=0;return m=e.pressure?e.pressure:f?.5:0,Object.defineProperties(i,{pointerId:{value:e.pointerId||0,enumerable:!0},width:{value:e.width||0,enumerable:!0},height:{value:e.height||0,enumerable:!0},pressure:{value:m,enumerable:!0},tiltX:{value:e.tiltX||0,enumerable:!0},tiltY:{value:e.tiltY||0,enumerable:!0},pointerType:{value:e.pointerType||"",enumerable:!0},hwTimestamp:{value:e.hwTimestamp||0,enumerable:!0},isPrimary:{value:e.isPrimary||!1,enumerable:!0}}),i}var c=!1,d=!1;try{var e=new MouseEvent("click",{buttons:1});c=!0,d=1===e.buttons}catch(f){}var g=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget"],h=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null];b.prototype=Object.create(MouseEvent.prototype),a.PointerEvent||(a.PointerEvent=b)}(window),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerEventsPolyfill),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,void 0,0,0,0,0,0,0,"",0,!1,"",null,null,0],d={targets:new WeakMap,handledEvents:new WeakMap,pointermap:new a.PointerMap,eventMap:{},eventSources:{},eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.unregister.call(b,a)},contains:a.external.contains||function(a,b){return a.contains(b)},down:function(a){this.fireEvent("pointerdown",a)},move:function(a){this.fireEvent("pointermove",a)},up:function(a){this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){this.fireEvent("pointercancel",a)},leaveOut:function(a){this.contains(a.target,a.relatedTarget)||this.leave(a),this.out(a)},enterOver:function(a){this.contains(a.target,a.relatedTarget)||this.enter(a),this.over(a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),this.handledEvents.set(a,!0)}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:a.external.addEvent||function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:a.external.removeEvent||function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(a,b){this.captureInfo&&(b.relatedTarget=null);var c=new PointerEvent(a,b);return b.preventDefault&&(c.preventDefault=b.preventDefault),this.targets.set(c,this.targets.get(b)||b.target),c},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var d,e={},f=0;f<b.length;f++)d=b[f],e[d]=a[d]||c[f];return a.preventDefault&&(e.preventDefault=function(){a.preventDefault()}),e},getTarget:function(a){return this.captureInfo&&this.captureInfo.id===a.pointerId?this.captureInfo.target:this.targets.get(a)},setCapture:function(a,b){this.captureInfo&&this.releaseCapture(this.captureInfo.id),this.captureInfo={id:a,target:b};var c=new PointerEvent("gotpointercapture",{bubbles:!0});this.implicitRelease=this.releaseCapture.bind(this,a),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease),this.targets.set(c,b),this.asyncDispatchEvent(c)},releaseCapture:function(a){if(this.captureInfo&&this.captureInfo.id===a){var b=new PointerEvent("lostpointercapture",{bubbles:!0}),c=this.captureInfo.target;this.captureInfo=null,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease),this.targets.set(b,c),this.asyncDispatchEvent(b)}},dispatchEvent:a.external.dispatchEvent||function(a){var b=this.getTarget(a);return b?b.dispatchEvent(a):void 0},asyncDispatchEvent:function(a){setTimeout(this.dispatchEvent.bind(this,a),0)}};d.boundHandler=d.eventHandler.bind(d),a.dispatcher=d,a.register=d.register.bind(d),a.unregister=d.unregister.bind(d)}(window.PointerEventsPolyfill),function(a){function b(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),g&&(this.observer=new g(this.mutationWatcher.bind(this)))}var c=Array.prototype.forEach.call.bind(Array.prototype.forEach),d=Array.prototype.map.call.bind(Array.prototype.map),e=Array.prototype.slice.call.bind(Array.prototype.slice),f=Array.prototype.filter.call.bind(Array.prototype.filter),g=window.MutationObserver||window.WebKitMutationObserver,h="[touch-action]",i={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};b.prototype={watchSubtree:function(b){a.targetFinding.canTarget(b)&&this.observer.observe(b,i)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){c(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(h):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(e(b))},installOnLoad:function(){document.addEventListener("DOMContentLoaded",this.installNewSubtree.bind(this,document))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){var b=d(a,this.findElements,this);return b.push(f(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}},g||(b.prototype.watchSubtree=function(){console.warn("PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected")}),a.Installer=b}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=25,e={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},lastTouches:[],isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,e=a.clientX,f=a.clientY,g=0,h=c.length;h>g&&(b=c[g]);g++){var i=Math.abs(e-b.x),j=Math.abs(f-b.y);if(d>=i&&d>=j)return!0}},prepareEvent:function(a){var c=b.cloneEvent(a),d=c.preventDefault;return c.preventDefault=function(){a.preventDefault(),d()},c.pointerId=this.POINTER_ID,c.isPrimary=!0,c.pointerType=this.POINTER_TYPE,c},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.has(this.POINTER_ID);d&&this.cancel(a);var e=this.prepareEvent(a);c.set(this.POINTER_ID,a),b.down(e)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.move(c)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.get(this.POINTER_ID);if(d&&d.button===a.button){var e=this.prepareEvent(a);b.up(e),this.cleanupMouse()}}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.enterOver(c)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.leaveOut(c)}},cancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanupMouse()},cleanupMouse:function(){c["delete"](this.POINTER_ID)}};a.mouseEvents=e}(window.PointerEventsPolyfill),function(a){var b,c=a.dispatcher,d=a.findTarget,e=a.targetFinding.allShadows.bind(a.targetFinding),f=c.pointermap,g=Array.prototype.map.call.bind(Array.prototype.map),h=2500,i=200,j="touch-action",k="string"==typeof document.head.style.touchAction,l={scrollType:new WeakMap,events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){k?c.listen(a,this.events):b.enableOnSubtree(a)},unregister:function(a){k&&c.unlisten(a,this.events)},elementAdded:function(a){var b=a.getAttribute(j),d=this.touchActionToScrollType(b);d&&(this.scrollType.set(a,d),c.listen(a,this.events),e(a).forEach(function(a){this.scrollType.set(a,d),c.listen(a,this.events)},this))},elementRemoved:function(a){this.scrollType["delete"](a),c.unlisten(a,this.events),e(a).forEach(function(a){this.scrollType["delete"](a),c.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(j),d=this.touchActionToScrollType(c),f=this.touchActionToScrollType(b);d&&f?(this.scrollType.set(a,d),e(a).forEach(function(a){this.scrollType.set(a,d)},this)):f?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){(0===f.pointers()||1===f.pointers()&&f.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,i)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},touchToPointer:function(a){var b=c.cloneEvent(a);return b.pointerId=a.identifier+2,b.target=d(b),b.bubbles=!0,b.cancelable=!0,b.detail=this.clickCount,b.button=0,b.buttons=1,b.width=a.webkitRadiusX||a.radiusX||0,b.height=a.webkitRadiusY||a.radiusY||0,b.pressure=a.webkitForce||a.force||.5,b.isPrimary=this.isPrimaryTouch(a),b.pointerType=this.POINTER_TYPE,b},processTouches:function(a,b){var c=a.changedTouches,d=g(c,this.touchToPointer,this);d.forEach(function(b){b.preventDefault=function(){this.scrolling=!1,this.firstXY=null,a.preventDefault()}},this),d.forEach(b,this)},shouldScroll:function(a){if(this.firstXY){var b,c=this.scrollType.get(a.currentTarget);if("none"===c)b=!1;else if("XY"===c)b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)if(c.identifier===b)return!0},vacuumTouches:function(a){var b=a.touches;if(f.pointers()>=b.length){var c=[];f.forEach(function(a,d){if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(this.touchToPointer(e))}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){f.set(a.pointerId,{target:a.target,out:a,outTarget:a.target});c.over(a),c.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,d=f.get(b.pointerId);if(d){var e=d.out,g=d.outTarget;c.move(b),e&&g!==b.target&&(e.relatedTarget=b.target,b.relatedTarget=g,e.target=g,b.target?(c.leaveOut(e),c.enterOver(b)):(b.target=g,b.relatedTarget=null,this.cancelOut(b))),d.out=b,d.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(c.up(a),c.out(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){c.cancel(a),c.out(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){f["delete"](a.pointerId),this.removePrimaryPointer(a)},dedupSynthMouse:function(b){var c=a.mouseEvents.lastTouches,d=b.changedTouches[0];if(this.isPrimaryTouch(d)){var e={x:d.clientX,y:d.clientY};c.push(e);var f=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,c,e);setTimeout(f,h)}}};k||(b=new a.Installer(l.elementAdded,l.elementRemoved,l.elementChanged,l)),a.touchEvents=l}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,e={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var c=a;return d&&(c=b.cloneEvent(a),c.pointerType=this.POINTER_TYPES[a.pointerType]),c},cleanup:function(a){c["delete"](a)},MSPointerDown:function(a){c.set(a.pointerId,a);var d=this.prepareEvent(a);b.down(d)},MSPointerMove:function(a){var c=this.prepareEvent(a);b.move(c)},MSPointerUp:function(a){var c=this.prepareEvent(a);b.up(c),this.cleanup(a.pointerId)},MSPointerOut:function(a){var c=this.prepareEvent(a);b.leaveOut(c)},MSPointerOver:function(a){var c=this.prepareEvent(a);b.enterOver(c)},MSPointerCancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var c=b.makeEvent("lostpointercapture",a);b.dispatchEvent(c)},MSGotPointerCapture:function(a){var c=b.makeEvent("gotpointercapture",a);b.dispatchEvent(c)}};a.msEvents=e}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher;if(void 0===window.navigator.pointerEnabled){if(Object.defineProperty(window.navigator,"pointerEnabled",{value:!0,enumerable:!0}),window.navigator.msPointerEnabled){var c=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:c,enumerable:!0}),b.registerSource("ms",a.msEvents)}else b.registerSource("mouse",a.mouseEvents),void 0!==window.ontouchstart&&b.registerSource("touch",a.touchEvents);b.register(document)}}(window.PointerEventsPolyfill),function(a){function b(a){if(!e.pointermap.has(a))throw new Error("InvalidPointerId")}var c,d,e=a.dispatcher,f=window.navigator;f.msPointerEnabled?(c=function(a){b(a),this.msSetPointerCapture(a)},d=function(a){b(a),this.msReleasePointerCapture(a)}):(c=function(a){b(a),e.setCapture(a,this)},d=function(a){b(a),e.releaseCapture(a,this)}),window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:c},releasePointerCapture:{value:d}})}(window.PointerEventsPolyfill),PointerGestureEvent.prototype.preventTap=function(){this.tapPrevented=!0},function(a){a=a||{},a.utils={LCA:{find:function(a,b){if(a===b)return a;if(a.contains){if(a.contains(b))return a;if(b.contains(a))return b}var c=this.depth(a),d=this.depth(b),e=c-d;for(e>0?a=this.walk(a,e):b=this.walk(b,-e);a&&b&&a!==b;)a=this.walk(a,1),b=this.walk(b,1);return a},walk:function(a,b){for(var c=0;b>c;c++)a=a.parentNode;return a},depth:function(a){for(var b=0;a;)b++,a=a.parentNode;return b}}},a.findLCA=function(b,c){return a.utils.LCA.find(b,c)},window.PointerGestures=a}(window.PointerGestures),function(a){function b(){this.ids=[],this.pointers=[]}b.prototype={set:function(a,b){var c=this.ids.indexOf(a);c>-1?this.pointers[c]=b:(this.ids.push(a),this.pointers.push(b))},has:function(a){return this.ids.indexOf(a)>-1},"delete":function(a){var b=this.ids.indexOf(a);b>-1&&(this.ids.splice(b,1),this.pointers.splice(b,1))},get:function(a){var b=this.ids.indexOf(a);return this.pointers[b]},get size(){return this.pointers.length},clear:function(){this.ids.length=0,this.pointers.length=0}},window.Map&&(b=window.Map),a.PointerMap=b}(window.PointerGestures),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","screenX","screenY","pageX","pageY","tapPrevented"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],d={handledEvents:new WeakMap,targets:new WeakMap,handlers:{},recognizers:{},events:{},registerRecognizer:function(a,b){var c=b;this.recognizers[a]=c,c.events.forEach(function(a){if(c[a]){this.events[a]=!0;var b=c[a].bind(c);this.addHandler(a,b)}},this)},addHandler:function(a,b){var c=a;this.handlers[c]||(this.handlers[c]=[]),this.handlers[c].push(b)},registerTarget:function(a){this.listen(Object.keys(this.events),a)},unregisterTarget:function(a){this.unlisten(Object.keys(this.events),a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.handlers[b];c&&this.makeQueue(c,a),this.handledEvents.set(a,!0)}},makeQueue:function(a,b){var c=this.cloneEvent(b);setTimeout(this.runQueue.bind(this,a,c),0)},runQueue:function(a,b){this.currentPointerId=b.pointerId;for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)c(b);this.currentPointerId=0},listen:function(a,b){a.forEach(function(a){this.addEvent(a,this.boundHandler,!1,b)},this)},unlisten:function(a){a.forEach(function(a){this.removeEvent(a,this.boundHandler,!1,inTarget)},this)},addEvent:function(a,b,c,d){d.addEventListener(a,b,c)},removeEvent:function(a,b,c,d){d.removeEventListener(a,b,c)},makeEvent:function(a,b){return new PointerGestureEvent(a,b)},cloneEvent:function(a){for(var d,e={},f=0;f<b.length;f++)d=b[f],e[d]=a[d]||c[f];return e},dispatchEvent:function(a,b){var c=b||this.targets.get(a);c&&(c.dispatchEvent(a),a.tapPrevented&&this.preventTap(this.currentPointerId))},asyncDispatchEvent:function(a,b){var c=function(){this.dispatchEvent(a,b)}.bind(this);setTimeout(c,0)},preventTap:function(a){var b=this.recognizers.tap;b&&b.preventTap(a)}};d.boundHandler=d.eventHandler.bind(d),a.dispatcher=d;var e=[],f=!1;a.register=function(b){if(f){var c=window.PointerEventsPolyfill;c&&c.register(b),a.dispatcher.registerTarget(b)}else e.push(b)},document.addEventListener("DOMContentLoaded",function(){f=!0,e.push(document),e.forEach(a.register)})}(window.PointerGestures),function(a){var b=a.dispatcher,c={HOLD_DELAY:200,WIGGLE_THRESHOLD:16,events:["pointerdown","pointermove","pointerup","pointercancel"],heldPointer:null,holdJob:null,pulse:function(){var a=Date.now()-this.heldPointer.timeStamp,b=this.held?"holdpulse":"hold";this.fireHold(b,a),this.held=!0},cancel:function(){clearInterval(this.holdJob),this.held&&this.fireHold("release"),this.held=!1,this.heldPointer=null,this.target=null,this.holdJob=null},pointerdown:function(a){a.isPrimary&&!this.heldPointer&&(this.heldPointer=a,this.target=a.target,this.holdJob=setInterval(this.pulse.bind(this),this.HOLD_DELAY))},pointerup:function(a){this.heldPointer&&this.heldPointer.pointerId===a.pointerId&&this.cancel()},pointercancel:function(){this.cancel()},pointermove:function(a){if(this.heldPointer&&this.heldPointer.pointerId===a.pointerId){var b=a.clientX-this.heldPointer.clientX,c=a.clientY-this.heldPointer.clientY;b*b+c*c>this.WIGGLE_THRESHOLD&&this.cancel()}},fireHold:function(a,c){var d={pointerType:this.heldPointer.pointerType};c&&(d.holdTime=c);var e=b.makeEvent(a,d);b.dispatchEvent(e,this.target),e.tapPrevented&&b.preventTap(this.heldPointer.pointerId)}};b.registerRecognizer("hold",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel"],WIGGLE_THRESHOLD:4,clampDir:function(a){return a>0?1:-1},calcPositionDelta:function(a,b){var c=0,d=0;return a&&b&&(c=b.pageX-a.pageX,d=b.pageY-a.pageY),{x:c,y:d}},fireTrack:function(a,c,d){var e=d,f=this.calcPositionDelta(e.downEvent,c),g=this.calcPositionDelta(e.lastMoveEvent,c);g.x&&(e.xDirection=this.clampDir(g.x)),g.y&&(e.yDirection=this.clampDir(g.y));var h={dx:f.x,dy:f.y,ddx:g.x,ddy:g.y,clientX:c.clientX,clientY:c.clientY,pageX:c.pageX,pageY:c.pageY,screenX:c.screenX,screenY:c.screenY,xDirection:e.xDirection,yDirection:e.yDirection,trackInfo:e.trackInfo,relatedTarget:c.target,pointerType:c.pointerType},i=b.makeEvent(a,h);e.lastMoveEvent=c,b.dispatchEvent(i,e.downTarget)},pointerdown:function(a){if(a.isPrimary&&("mouse"===a.pointerType?1===a.buttons:!0)){var b={downEvent:a,downTarget:a.target,trackInfo:{},lastMoveEvent:null,xDirection:0,yDirection:0,tracking:!1};c.set(a.pointerId,b)}},pointermove:function(a){var b=c.get(a.pointerId);if(b)if(b.tracking)this.fireTrack("track",a,b);else{var d=this.calcPositionDelta(b.downEvent,a),e=d.x*d.x+d.y*d.y;e>this.WIGGLE_THRESHOLD&&(b.tracking=!0,this.fireTrack("trackstart",b.downEvent,b),this.fireTrack("track",a,b))}},pointerup:function(a){var b=c.get(a.pointerId);b&&(b.tracking&&this.fireTrack("trackend",a,b),c.delete(a.pointerId))},pointercancel:function(a){this.pointerup(a)}};b.registerRecognizer("track",d)}(window.PointerGestures),function(a){var b=a.dispatcher,c={MIN_VELOCITY:.5,MAX_QUEUE:4,moveQueue:[],target:null,pointerId:null,events:["pointerdown","pointermove","pointerup","pointercancel"],pointerdown:function(a){a.isPrimary&&!this.pointerId&&(this.pointerId=a.pointerId,this.target=a.target,this.addMove(a))},pointermove:function(a){a.pointerId===this.pointerId&&this.addMove(a)},pointerup:function(a){a.pointerId===this.pointerId&&this.fireFlick(a),this.cleanup()},pointercancel:function(){this.cleanup()},cleanup:function(){this.moveQueue=[],this.target=null,this.pointerId=null},addMove:function(a){this.moveQueue.length>=this.MAX_QUEUE&&this.moveQueue.shift(),this.moveQueue.push(a)},fireFlick:function(a){for(var c,d,e,f,g,h,i,j=a,k=this.moveQueue.length,l=0,m=0,n=0,o=0;k>o&&(i=this.moveQueue[o]);o++)c=j.timeStamp-i.timeStamp,d=j.clientX-i.clientX,e=j.clientY-i.clientY,f=d/c,g=e/c,h=Math.sqrt(f*f+g*g),h>n&&(l=f,m=g,n=h);var p=Math.abs(l)>Math.abs(m)?"x":"y",q=this.calcAngle(l,m);if(Math.abs(n)>=this.MIN_VELOCITY){var r=b.makeEvent("flick",{xVelocity:l,yVelocity:m,velocity:n,angle:q,majorAxis:p,pointerType:a.pointerType});b.dispatchEvent(r,this.target)}},calcAngle:function(a,b){return 180*Math.atan2(b,a)/Math.PI}};b.registerRecognizer("flick",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel","keyup"],pointerdown:function(a){a.isPrimary&&!a.tapPrevented&&c.set(a.pointerId,{target:a.target,x:a.clientX,y:a.clientY})},pointermove:function(a){if(a.isPrimary){var b=c.get(a.pointerId);b&&a.tapPrevented&&c.delete(a.pointerId)}},pointerup:function(d){var e=c.get(d.pointerId);if(e&&!d.tapPrevented){var f=a.findLCA(e.target,d.target);if(f){var g=b.makeEvent("tap",{x:d.clientX,y:d.clientY,detail:d.detail,pointerType:d.pointerType});b.dispatchEvent(g,f)}}c.delete(d.pointerId)},pointercancel:function(a){c.delete(a.pointerId)},keyup:function(a){var c=a.keyCode;if(32===c){var d=a.target;d instanceof HTMLInputElement||d instanceof HTMLTextAreaElement||b.dispatchEvent(b.makeEvent("tap",{x:0,y:0,detail:0,pointerType:"unavailable"}),d)}},preventTap:function(a){c.delete(a)}};b.registerRecognizer("tap",d)}(window.PointerGestures),function(){"use strict";function a(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function b(a,b,c,d){this.closed=!1,this.node=a,this.property=b,this.model=c,this.path=Path.get(d),(this.model instanceof PathObserver||this.model instanceof CompoundPathObserver)&&this.path===l?(this.observer=this.model,this.observer.target=this,this.observer.callback=this.valueChanged):this.observer=new PathObserver(this.model,this.path,this.valueChanged,this),this.valueChanged(this.value)}function c(a,c,d,e){this.conditional="?"==c[c.length-1],this.conditional&&(a.removeAttribute(c),c=c.slice(0,-1)),b.call(this,a,c,d,e)}function d(a){switch(a.type){case"checkbox":return m;
-case"radio":case"select-multiple":case"select-one":return"change";default:return"input"}}function e(a,c,e,f){b.call(this,a,c,e,f),this.eventType=d(this.node),this.boundNodeValueChanged=this.nodeValueChanged.bind(this),this.node.addEventListener(this.eventType,this.boundNodeValueChanged,!0)}function f(b){if(b.form)return j(b.form.elements,function(a){return a!=b&&"INPUT"==a.tagName&&"radio"==a.type&&a.name==b.name});var c=a(b);if(!c)return[];var d=c.querySelectorAll('input[type="radio"][name="'+b.name+'"]');return j(d,function(a){return a!=b&&!a.form})}function g(a,b,c){e.call(this,a,"checked",b,c)}function h(a,b,c){e.call(this,a,"value",b,c)}function i(a,b,c,d){e.call(this,a,b,c,d)}var j=Array.prototype.filter.call.bind(Array.prototype.filter),k="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c};"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)}),Node.prototype.bind=function(a,b,c){console.error("Unhandled binding to Node: ",this,a,b,c)},Node.prototype.unbind=function(a){this.bindings||(this.bindings={});var b=this.bindings[a];b&&("function"==typeof b.close&&b.close(),this.bindings[a]=void 0)},Node.prototype.unbindAll=function(){if(this.bindings){for(var a=Object.keys(this.bindings),b=0;b<a.length;b++){var c=this.bindings[a[b]];c&&c.close()}this.bindings={}}};var l=Path.get("value");b.prototype={valueChanged:function(a){this.node[this.property]=this.sanitizeBoundValue(a)},sanitizeBoundValue:function(a){return void 0==a?"":String(a)},close:function(){this.closed||(this.observer.close(),this.observer=void 0,this.node=void 0,this.model=void 0,this.closed=!0)},get value(){return this.observer.value},set value(a){this.observer.setValue(a)},reset:function(){this.observer.reset()}},Text.prototype.bind=function(a,c,d){return"textContent"!==a?Node.prototype.bind.call(this,a,c,d):(this.unbind(a),this.bindings[a]=new b(this,"data",c,d))},c.prototype=k({__proto__:b.prototype,valueChanged:function(a){return this.conditional?(a?this.node.setAttribute(this.property,""):this.node.removeAttribute(this.property),void 0):(this.node.setAttribute(this.property,this.sanitizeBoundValue(a)),void 0)}}),Element.prototype.bind=function(a,b,d){return this.unbind(a),this.bindings[a]=new c(this,a,b,d)};var m;!function(){var a=document.createElement("div"),b=a.appendChild(document.createElement("input"));b.setAttribute("type","checkbox");var c,d=0;b.addEventListener("click",function(){d++,c=c||"click"}),b.addEventListener("change",function(){d++,c=c||"change"});var e=document.createEvent("MouseEvent");e.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),b.dispatchEvent(e),m=1==d?"change":c}(),e.prototype=k({__proto__:b.prototype,nodeValueChanged:function(){this.value=this.node[this.property],this.reset(),this.postUpdateBinding(),Platform.performMicrotaskCheckpoint()},postUpdateBinding:function(){},close:function(){this.closed||(this.node.removeEventListener(this.eventType,this.boundNodeValueChanged,!0),b.prototype.close.call(this))}}),g.prototype=k({__proto__:e.prototype,sanitizeBoundValue:function(a){return Boolean(a)},postUpdateBinding:function(){"INPUT"===this.node.tagName&&"radio"===this.node.type&&f(this.node).forEach(function(a){var b=a.bindings.checked;b&&(b.value=!1)})}}),HTMLInputElement.prototype.bind=function(a,b,c){return"value"!==a&&"checked"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]="value"===a?new e(this,"value",b,c):new g(this,b,c))},HTMLTextAreaElement.prototype.bind=function(a,b,c){return"value"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]=new e(this,a,b,c))},h.prototype=k({__proto__:e.prototype,valueChanged:function(a){var b,c,d=this.node.parentNode instanceof HTMLSelectElement?this.node.parentNode:void 0;d&&d.bindings&&d.bindings.value instanceof i&&(b=d.bindings.value,c=d.value),e.prototype.valueChanged.call(this,a),b&&!b.closed&&d.value!==c&&b.nodeValueChanged()}}),HTMLOptionElement.prototype.bind=function(a,b,c){return"value"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]=new h(this,b,c))},i.prototype=k({__proto__:e.prototype,valueChanged:function(a){function b(){d.node[d.property]=a,d.node[d.property]!=a&&c--&&n(b)}if(this.node[this.property]=a,this.node[this.property]!=a){var c=2,d=this;n(b)}}}),HTMLSelectElement.prototype.bind=function(a,b,c){return"selectedindex"===a&&(a="selectedIndex"),"selectedIndex"!==a&&"value"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]=new i(this,a,b,c))};var n=function(){function a(a){this.nextRunner=a,this.value=!1,this.lastValue=this.value,this.scheduled=[],this.scheduledIds=[],this.running=!1,this.observer=new PathObserver(this,"value",this.run,this)}function b(a){var b=a[e];a[e]||(b=d++,a[e]=b),c.schedule(a,b)}a.prototype={schedule:function(a,b){if(!this.scheduledIds[b]){if(this.running)return this.nextRunner.schedule(a,b);this.scheduledIds[b]=!0,this.scheduled.push(a),this.lastValue===this.value&&(this.value=!this.value)}},run:function(){this.running=!0;for(var a=0;a<this.scheduled.length;a++){var b=this.scheduled[a],c=b[e];this.scheduledIds[c]=!1,"function"==typeof b?b():b.resolve()}this.scheduled=[],this.scheduledIds=[],this.lastValue=this.value,this.running=!1}};var c=new a(new a),d=1,e="__scheduledId__";return b}()}(this),function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function d(a){return H[a.tagName]&&a.hasAttribute("template")}function e(a){return"TEMPLATE"==a.tagName||d(a)}function f(a){return I&&"TEMPLATE"==a.tagName}function g(a,b){var c=a.querySelectorAll(J);e(a)&&b(a),C(c,b)}function h(a){function b(a){HTMLTemplateElement.decorate(a)||h(a.content)}g(a,b)}function i(a,b){Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))})}function j(a){var b=a.ownerDocument;if(!b.defaultView)return b;var c=b.templateContentsOwner_;if(!c){for(c=b.implementation.createHTMLDocument("");c.lastChild;)c.removeChild(c.lastChild);b.templateContentsOwner_=c}return c}function k(a){if(!a.stagingDocument_){var b=a.ownerDocument;b.stagingDocument_||(b.stagingDocument_=b.implementation.createHTMLDocument(""),b.stagingDocument_.stagingDocument_=b.stagingDocument_),a.stagingDocument_=b.stagingDocument_}return a.stagingDocument_}function l(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];G[e.name]&&("template"!==e.name&&b.setAttribute(e.name,e.value),a.removeAttribute(e.name))}return b}function m(a,b,c){var d=a.content;if(c)return d.appendChild(b),void 0;for(var e;e=b.firstChild;)d.appendChild(e)}function n(a){"TEMPLATE"===a.tagName?I||(L?a.__proto__=HTMLTemplateElement.prototype:i(a,HTMLTemplateElement.prototype)):(i(a,HTMLTemplateElement.prototype),Object.defineProperty(a,"content",N))}function o(a){a.setModelFn_||(a.setModelFn_=function(){v(a,a.model,a.prepareBindingFn_)}),K(a.setModelFn_)}function p(a,b,c,d){if(a&&a.length){for(var e,f=a.length,g=0,h=0,i=0;f>h;){if(g=a.indexOf("{{",h),i=0>g?-1:a.indexOf("}}",g+2),0>i){if(!e)return;e.push(a.slice(h));break}e=e||[],e.push(a.slice(h,g));var j=a.slice(g+2,i).trim();e.push(Path.get(j));var k=d&&d(j,b,c);e.push(k),h=i+2}return h===f&&e.push(""),e.hasOnePath=4===e.length,e.isSimplePath=e.hasOnePath&&""==e[0]&&""==e[3],e.combinator=function(a){for(var b=e[0],c=1;c<e.length;c+=3){var d=e.hasOnePath?a:a[(c-1)/3];void 0!==d&&(b+=d),b+=e[c+2]}return b},e}}function q(a,b,c,d,e){var f,g;b.hasOnePath||(f=new CompoundPathObserver(void 0,void 0,b.combinator)),b.isSimplePath||(g=O);for(var h=1;h<b.length;h+=3){var i=(b[h],d),j=b[h],k=b[h+1],l=k&&k(d,c);void 0!==l&&(i=l,j=O),b.hasOnePath?b.isSimplePath?(f=i,g=j):f=new PathObserver(i,j,void 0,void 0,b.combinator):f.addPath(i,j)}b.hasOnePath||f.start();var m=c.bind(a,f,g);e&&e.push(m)}function r(a,b,c,d){for(var e=0;e<a.length;e+=2)q(a[e],a[e+1],b,c,d)}function s(a,c){b(a);for(var d,f=e(a),g=!1,h=!1,i=0;i<a.attributes.length;i++){for(var j=a.attributes[i],k=j.name,l=j.value;"_"===k[0];)k=k.substring(1);f&&(k===F?(g=!0,l=l||"{{}}"):(k===D||k===E)&&(h=!0,l=l||"{{}}"));var m=p(l,k,a,c);m&&(d=d||[],d.push(k,m))}return g&&!h&&(d=d||[],d.push(D,p("{{}}",D,a,c))),d}function t(a,b){if(a.nodeType===Node.ELEMENT_NODE)return s(a,b);if(a.nodeType===Node.TEXT_NODE){var c=p(a.data,"textContent",a,b);if(c)return["textContent",c]}}function u(a,b,c,d,e){if(b&&(b.templateRef&&(HTMLTemplateElement.decorate(a,b.templateRef),d&&a.setBindingDelegate_(d)),b.length&&r(b,a,c,e),b.children))for(var f=0,g=a.firstChild;g;g=g.nextSibling)u(g,b.children[f++],c,d,e)}function v(a,c,d){b(a);var e=t(a,d);e&&r(e,a,c);for(var f=a.firstChild;f;f=f.nextSibling)v(f,c,d)}function w(a,b){var c=b.importNode(a,!1);if(a.isTemplate_)return c;for(var d=a.firstChild;d;d=d.nextSibling)c.appendChild(w(d,b));return c}function x(a,b){var c=t(a,b);e(a)&&(a.isTemplate_=!0,c=c||[],c.templateRef=a);for(var d=a.firstChild,f=0;d;d=d.nextSibling,f++){var g=x(d,b);g&&(c=c||[],c.children=c.children||{},c.children[f]=g)}return c}function y(a,b,c){this.firstNode=a,this.lastNode=b,this.model=c}function z(a,b){if(a.firstChild)for(var c=new y(a.firstChild,a.lastChild,b),d=c.firstNode;d;)d.templateInstance_=c,d=d.nextSibling}function A(a){this.closed=!1,this.templateElement_=a,this.terminators=[],this.iteratedValue=void 0,this.arrayObserver=void 0,this.depsChanged=!1,this.hasRepeat=!1,this.repeatModel=void 0,this.repeatPath=void 0,this.hasBind=!1,this.bindModel=void 0,this.bindPath=void 0,this.hasIf=!1,this.ifModel=void 0,this.ifPath=void 0}var B,C=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.Map&&"function"==typeof a.Map.prototype.forEach?B=a.Map:(B=function(){this.keys=[],this.values=[]},B.prototype={set:function(a,b){var c=this.keys.indexOf(a);0>c?(this.keys.push(a),this.values.push(b)):this.values[c]=b},get:function(a){var b=this.keys.indexOf(a);if(!(0>b))return this.values[b]},"delete":function(a){var b=this.keys.indexOf(a);return 0>b?!1:(this.keys.splice(b,1),this.values.splice(b,1),!0)},forEach:function(a,b){for(var c=0;c<this.keys.length;c++)a.call(b||this,this.values[c],this.keys[c],this)}});"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)});var D="bind",E="repeat",F="if",G={template:!0,repeat:!0,bind:!0,ref:!0},H={THEAD:!0,TBODY:!0,TFOOT:!0,TH:!0,TR:!0,TD:!0,COLGROUP:!0,COL:!0,CAPTION:!0,OPTION:!0,OPTGROUP:!0},I="undefined"!=typeof HTMLTemplateElement,J="template, "+Object.keys(H).map(function(a){return a.toLowerCase()+"[template]"}).join(", "),K=function(){function a(a){this.nextRunner=a,this.value=!1,this.lastValue=this.value,this.scheduled=[],this.scheduledIds=[],this.running=!1,this.observer=new PathObserver(this,"value",this.run,this)}function b(a){var b=a[e];a[e]||(b=d++,a[e]=b),c.schedule(a,b)}a.prototype={schedule:function(a,b){if(!this.scheduledIds[b]){if(this.running)return this.nextRunner.schedule(a,b);this.scheduledIds[b]=!0,this.scheduled.push(a),this.lastValue===this.value&&(this.value=!this.value)}},run:function(){this.running=!0;for(var a=0;a<this.scheduled.length;a++){var b=this.scheduled[a],c=b[e];this.scheduledIds[c]=!1,"function"==typeof b?b():b.resolve()}this.scheduled=[],this.scheduledIds=[],this.lastValue=this.value,this.running=!1}};var c=new a(new a),d=1,e="__scheduledId__";return b}();document.addEventListener("DOMContentLoaded",function(){h(document),Platform.performMicrotaskCheckpoint()},!1),I||(a.HTMLTemplateElement=function(){throw TypeError("Illegal constructor")});var L="__proto__"in{};HTMLTemplateElement.decorate=function(a,c){if(a.templateIsDecorated_)return!1;var e=a;e.templateIsDecorated_=!0;var g=f(e),i=g,k=!g,o=!1;if(!g&&d(e)&&(b(!c),e=l(a),e.templateIsDecorated_=!0,g=f(e),o=!0),!g){n(e);var p=j(e);e.content_=p.createDocumentFragment()}return c?e.instanceRef_=c:k?m(e,a,o):i&&h(e.content),!0},HTMLTemplateElement.bootstrap=h;var M=a.HTMLUnknownElement||HTMLElement,N={get:function(){return this.content_},enumerable:!0,configurable:!0};I||(HTMLTemplateElement.prototype=Object.create(M.prototype),Object.defineProperty(HTMLTemplateElement.prototype,"content",N)),i(HTMLTemplateElement.prototype,{bind:function(a,b,c){return this.iterator_||(this.iterator_=new A(this)),this.bindings=this.bindings||{},"bind"===a?(this.iterator_.hasBind=!0,this.iterator_.bindModel=b,this.iterator_.bindPath=c,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.bind=this.iterator_):"repeat"===a?(this.iterator_.hasRepeat=!0,this.iterator_.repeatModel=b,this.iterator_.repeatPath=c,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.repeat=this.iterator_):"if"===a?(this.iterator_.hasIf=!0,this.iterator_.ifModel=b,this.iterator_.ifPath=c,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.if=this.iterator_):HTMLElement.prototype.bind.call(this,a,b,c)},unbind:function(a){if("bind"===a){if(!this.iterator_)return;return this.iterator_.hasBind=!1,this.iterator_.bindModel=void 0,this.iterator_.bindPath=void 0,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.bind=void 0}if("repeat"===a){if(!this.iterator_)return;return this.iterator_.hasRepeat=!1,this.iterator_.repeatModel=void 0,this.iterator_.repeatPath=void 0,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.repeat=void 0}if("if"===a){if(!this.iterator_)return;return this.iterator_.hasIf=!1,this.iterator_.ifModel=void 0,this.iterator_.ifPath=void 0,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.if=void 0}return HTMLElement.prototype.unbind.call(this,a)},createInstance:function(a,b){var c=this.ref.content,d=c.bindingMap_;d||(d=x(c,this.prepareBindingFn_)||[],c.bindingMap_=d);var e=k(this),f=w(c,e);return u(f,d,a,this.bindingDelegate_,b),z(f,a),f},get model(){return this.model_},set model(a){this.model_=a,o(this)},get bindingDelegate(){return this.bindingDelegate_},setBindingDelegate_:function(a){function b(b){var c=a&&a[b];if("function"==typeof c)return function(){return c.apply(a,arguments)}}this.bindingDelegate_=a,this.prepareBindingFn_=b("prepareBinding"),this.prepareInstanceModelFn_=b("prepareInstanceModel"),this.prepareInstancePositionChangedFn_=b("prepareInstancePositionChanged")},set bindingDelegate(a){this.setBindingDelegate_(a),o(this)},get ref(){var a,b=this.getAttribute("ref");if(b){var d=c(this);d&&(a=d.getElementById(b))}if(a||(a=this.instanceRef_),!a)return this;var e=a.ref;return e?e:a}});var O=Path.get("value");Object.defineProperty(Node.prototype,"templateInstance",{get:function(){var a=this.templateInstance_;return a?a:this.parentNode?this.parentNode.templateInstance:void 0}}),A.prototype={resolve:function(){if(this.depsChanging=!1,this.valueObserver&&(this.valueObserver.close(),this.valueObserver=void 0),!this.hasRepeat&&!this.hasBind)return this.valueChanged(),void 0;var a=this.hasRepeat===!0,b=a?this.repeatModel:this.bindModel,c=a?this.repeatPath:this.bindPath;if(this.hasIf){var d=function(b){var c=b[0],d=b[1];return d?a?c:[c]:void 0};this.valueObserver=new CompoundPathObserver(this.valueChanged,this,d),this.valueObserver.addPath(b,c),this.valueObserver.addPath(this.ifModel,this.ifPath),this.valueObserver.start()}else{var d=this.hasRepeat?void 0:function(a){return[a]};this.valueObserver=new PathObserver(b,c,this.valueChanged,this,d)}this.valueChanged(this.valueObserver.value)},valueChanged:function(a){Array.isArray(a)||(a=void 0);var b=this.iteratedValue;this.unobserve(),this.iteratedValue=a,this.iteratedValue&&(this.arrayObserver=new ArrayObserver(this.iteratedValue,this.handleSplices,this));var c=ArrayObserver.calculateSplices(this.iteratedValue||[],b||[]);c.length&&this.handleSplices(c)},getTerminatorAt:function(a){if(-1==a)return this.templateElement_;var b=this.terminators[2*a];if(b.nodeType!==Node.ELEMENT_NODE||this.templateElement_===b)return b;var c=b.iterator_;return c?c.getTerminatorAt(c.terminators.length/2-1):b},insertInstanceAt:function(a,b,c,d){var e=this.getTerminatorAt(a-1),f=e;b?f=b.lastChild||f:c&&(f=c[c.length-1]||f),this.terminators.splice(2*a,0,f,d);var g=this.templateElement_.parentNode,h=e.nextSibling;if(b)g.insertBefore(b,h);else if(c)for(var i=0;i<c.length;i++)g.insertBefore(c[i],h)},extractInstanceAt:function(a){var b=[],c=this.getTerminatorAt(a-1),d=this.getTerminatorAt(a);b.bound=this.terminators[2*a+1],this.terminators.splice(2*a,2);for(var e=this.templateElement_.parentNode;d!==c;){var f=c.nextSibling;f==d&&(d=c),e.removeChild(f),b.push(f)}return b},getDelegateFn:function(a){return a=a&&a(this.templateElement_),"function"==typeof a?a:null},handleSplices:function(a){if(!this.closed){var b=this.templateElement_;if(!b.parentNode||!b.ownerDocument.defaultView)return this.close(),void 0;void 0===this.instanceModelFn_&&(this.instanceModelFn_=this.getDelegateFn(b.prepareInstanceModelFn_)),void 0===this.instancePositionChangedFn_&&(this.instancePositionChangedFn_=this.getDelegateFn(b.prepareInstancePositionChangedFn_));var c=new B,d=0;a.forEach(function(a){a.removed.forEach(function(b){var e=this.extractInstanceAt(a.index+d);c.set(b,e)},this),d-=a.addedCount},this),a.forEach(function(a){for(var b=a.index;b<a.index+a.addedCount;b++){var d,e=this.iteratedValue[b],f=void 0,g=c.get(e);g?(c.delete(e),d=g.bound):(d=[],this.instanceModelFn_&&(e=this.instanceModelFn_(e)),void 0!==e&&(f=this.templateElement_.createInstance(e,d))),this.insertInstanceAt(b,f,g,d)}},this),c.forEach(function(a){this.closeInstanceBindings(a.bound)},this),this.instancePositionChangedFn_&&this.reportInstancesMoved(a)}},reportInstanceMoved:function(a){var b=this.getTerminatorAt(a-1),c=this.getTerminatorAt(a);if(b!==c){var d=b.nextSibling.templateInstance;this.instancePositionChangedFn_(d,a)}},reportInstancesMoved:function(a){for(var b=0,c=0,d=0;d<a.length;d++){var e=a[d];if(0!=c)for(;b<e.index;)this.reportInstanceMoved(b),b++;else b=e.index;for(;b<e.index+e.addedCount;)this.reportInstanceMoved(b),b++;c+=e.addedCount-e.removed.length}if(0!=c)for(var f=this.terminators.length/2;f>b;)this.reportInstanceMoved(b),b++},closeInstanceBindings:function(a){for(var b=0;b<a.length;b++)a[b].close()},unobserve:function(){this.arrayObserver&&(this.arrayObserver.close(),this.arrayObserver=void 0)},close:function(){if(!this.closed){this.unobserve();for(var a=1;a<this.terminators.length;a+=2)this.closeInstanceBindings(this.terminators[a]);this.terminators.length=0,this.valueObserver&&this.valueObserver.close(),this.valueObserver=void 0,this.templateElement_.iterator_=void 0,this.closed=!0}}},HTMLTemplateElement.forAllTemplatesFrom_=g}(this),function(a){"use strict";function b(a,b){if(!a)throw new Error("ASSERT: "+b)}function c(a){return a>=48&&57>=a}function d(a){return 32===a||9===a||11===a||12===a||160===a||a>=5760&&" ᠎              ".indexOf(String.fromCharCode(a))>0}function e(a){return 10===a||13===a||8232===a||8233===a}function f(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a}function g(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a||a>=48&&57>=a}function h(a){return"this"===a}function i(){for(;Y>X&&d(W.charCodeAt(X));)++X}function j(){var a,b;for(a=X++;Y>X&&(b=W.charCodeAt(X),g(b));)++X;return W.slice(a,X)}function k(){var a,b,c;return a=X,b=j(),c=1===b.length?S.Identifier:h(b)?S.Keyword:"null"===b?S.NullLiteral:"true"===b||"false"===b?S.BooleanLiteral:S.Identifier,{type:c,value:b,range:[a,X]}}function l(){var a,b,c=X,d=W.charCodeAt(X),e=W[X];switch(d){case 46:case 40:case 41:case 59:case 44:case 123:case 125:case 91:case 93:case 58:case 63:return++X,{type:S.Punctuator,value:String.fromCharCode(d),range:[c,X]};default:if(a=W.charCodeAt(X+1),61===a)switch(d){case 37:case 38:case 42:case 43:case 45:case 47:case 60:case 62:case 124:return X+=2,{type:S.Punctuator,value:String.fromCharCode(d)+String.fromCharCode(a),range:[c,X]};case 33:case 61:return X+=2,61===W.charCodeAt(X)&&++X,{type:S.Punctuator,value:W.slice(c,X),range:[c,X]}}}return b=W[X+1],e===b&&"&|".indexOf(e)>=0?(X+=2,{type:S.Punctuator,value:e+b,range:[c,X]}):"<>=!+-*%&|^/".indexOf(e)>=0?(++X,{type:S.Punctuator,value:e,range:[c,X]}):(s({},V.UnexpectedToken,"ILLEGAL"),void 0)}function m(){var a,d,e;if(e=W[X],b(c(e.charCodeAt(0))||"."===e,"Numeric literal must start with a decimal digit or a decimal point"),d=X,a="","."!==e){for(a=W[X++],e=W[X],"0"===a&&e&&c(e.charCodeAt(0))&&s({},V.UnexpectedToken,"ILLEGAL");c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("."===e){for(a+=W[X++];c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("e"===e||"E"===e)if(a+=W[X++],e=W[X],("+"===e||"-"===e)&&(a+=W[X++]),c(W.charCodeAt(X)))for(;c(W.charCodeAt(X));)a+=W[X++];else s({},V.UnexpectedToken,"ILLEGAL");return f(W.charCodeAt(X))&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.NumericLiteral,value:parseFloat(a),range:[d,X]}}function n(){var a,c,d,f="",g=!1;for(a=W[X],b("'"===a||'"'===a,"String literal must starts with a quote"),c=X,++X;Y>X;){if(d=W[X++],d===a){a="";break}if("\\"===d)if(d=W[X++],d&&e(d.charCodeAt(0)))"\r"===d&&"\n"===W[X]&&++X;else switch(d){case"n":f+="\n";break;case"r":f+="\r";break;case"t":f+="	";break;case"b":f+="\b";break;case"f":f+="\f";break;case"v":f+="";break;default:f+=d}else{if(e(d.charCodeAt(0)))break;f+=d}}return""!==a&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.StringLiteral,value:f,octal:g,range:[c,X]}}function o(a){return a.type===S.Identifier||a.type===S.Keyword||a.type===S.BooleanLiteral||a.type===S.NullLiteral}function p(){var a;return i(),X>=Y?{type:S.EOF,range:[X,X]}:(a=W.charCodeAt(X),40===a||41===a||58===a?l():39===a||34===a?n():f(a)?k():46===a?c(W.charCodeAt(X+1))?m():l():c(a)?m():l())}function q(){var a;return a=$,X=a.range[1],$=p(),X=a.range[1],a}function r(){var a;a=X,$=p(),X=a}function s(a,c){var d,e=Array.prototype.slice.call(arguments,2),f=c.replace(/%(\d)/g,function(a,c){return b(c<e.length,"Message reference must be in range"),e[c]});throw d=new Error(f),d.index=X,d.description=f,d}function t(a){s(a,V.UnexpectedToken,a.value)}function u(a){var b=q();(b.type!==S.Punctuator||b.value!==a)&&t(b)}function v(a){return $.type===S.Punctuator&&$.value===a}function w(a){return $.type===S.Keyword&&$.value===a}function x(){var a=[];for(u("[");!v("]");)v(",")?(q(),a.push(null)):(a.push(bb()),v("]")||u(","));return u("]"),Z.createArrayExpression(a)}function y(){var a;return i(),a=q(),a.type===S.StringLiteral||a.type===S.NumericLiteral?Z.createLiteral(a):Z.createIdentifier(a.value)}function z(){var a,b;return a=$,i(),(a.type===S.EOF||a.type===S.Punctuator)&&t(a),b=y(),u(":"),Z.createProperty("init",b,bb())}function A(){var a=[];for(u("{");!v("}");)a.push(z()),v("}")||u(",");return u("}"),Z.createObjectExpression(a)}function B(){var a;return u("("),a=bb(),u(")"),a}function C(){var a,b,c;return v("(")?B():(a=$.type,a===S.Identifier?c=Z.createIdentifier(q().value):a===S.StringLiteral||a===S.NumericLiteral?c=Z.createLiteral(q()):a===S.Keyword?w("this")&&(q(),c=Z.createThisExpression()):a===S.BooleanLiteral?(b=q(),b.value="true"===b.value,c=Z.createLiteral(b)):a===S.NullLiteral?(b=q(),b.value=null,c=Z.createLiteral(b)):v("[")?c=x():v("{")&&(c=A()),c?c:(t(q()),void 0))}function D(){var a=[];if(u("("),!v(")"))for(;Y>X&&(a.push(bb()),!v(")"));)u(",");return u(")"),a}function E(){var a;return a=q(),o(a)||t(a),Z.createIdentifier(a.value)}function F(){return u("."),E()}function G(){var a;return u("["),a=bb(),u("]"),a}function H(){var a,b;for(a=C();v(".")||v("[");)v("[")?(b=G(),a=Z.createMemberExpression("[",a,b)):(b=F(),a=Z.createMemberExpression(".",a,b));return a}function I(){var a,b;return $.type!==S.Punctuator&&$.type!==S.Keyword?b=ab():v("+")||v("-")||v("!")?(a=q(),b=I(),b=Z.createUnaryExpression(a.value,b)):w("delete")||w("void")||w("typeof")?s({},V.UnexpectedToken):b=ab(),b}function J(a){var b=0;if(a.type!==S.Punctuator&&a.type!==S.Keyword)return 0;switch(a.value){case"||":b=1;break;case"&&":b=2;break;case"==":case"!=":case"===":case"!==":b=6;break;case"<":case">":case"<=":case">=":case"instanceof":b=7;break;case"in":b=7;break;case"+":case"-":b=9;break;case"*":case"/":case"%":b=11}return b}function K(){var a,b,c,d,e,f,g,h;if(g=I(),b=$,c=J(b),0===c)return g;for(b.prec=c,q(),e=I(),d=[g,b,e];(c=J($))>0;){for(;d.length>2&&c<=d[d.length-2].prec;)e=d.pop(),f=d.pop().value,g=d.pop(),a=Z.createBinaryExpression(f,g,e),d.push(a);b=q(),b.prec=c,d.push(b),a=I(),d.push(a)}for(h=d.length-1,a=d[h];h>1;)a=Z.createBinaryExpression(d[h-1].value,d[h-2],a),h-=2;return a}function L(){var a,b,c;return a=K(),v("?")&&(q(),b=L(),u(":"),c=L(),a=Z.createConditionalExpression(a,b,c)),a}function M(){var a,b;return a=q(),a.type!==S.Identifier&&t(a),b=v("(")?D():[],Z.createFilter(a.value,b)}function N(){for(;v("|");)q(),M()}function O(){i(),r();var a=bb();a&&(","===$.value||"in"==$.value&&a.type===U.Identifier?Q(a):(N(),"as"===$.value?P(a):Z.createTopLevel(a))),$.type!==S.EOF&&t($)}function P(a){q();var b=q().value;Z.createAsExpression(a,b)}function Q(a){var b;","===$.value&&(q(),$.type!==S.Identifier&&t($),b=q().value),q();var c=bb();N(),Z.createInExpression(a.name,b,c)}function R(a,b){return Z=b,W=a,X=0,Y=W.length,$=null,_={labelSet:{}},O()}var S,T,U,V,W,X,Y,Z,$,_;S={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8},T={},T[S.BooleanLiteral]="Boolean",T[S.EOF]="<end>",T[S.Identifier]="Identifier",T[S.Keyword]="Keyword",T[S.NullLiteral]="Null",T[S.NumericLiteral]="Numeric",T[S.Punctuator]="Punctuator",T[S.StringLiteral]="String",U={ArrayExpression:"ArrayExpression",BinaryExpression:"BinaryExpression",CallExpression:"CallExpression",ConditionalExpression:"ConditionalExpression",EmptyStatement:"EmptyStatement",ExpressionStatement:"ExpressionStatement",Identifier:"Identifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",ObjectExpression:"ObjectExpression",Program:"Program",Property:"Property",ThisExpression:"ThisExpression",UnaryExpression:"UnaryExpression"},V={UnexpectedToken:"Unexpected token %0",UnknownLabel:"Undefined label '%0'",Redeclaration:"%0 '%1' has already been declared"};var ab=H,bb=L;a.esprima={parse:R}}(this),function(a){"use strict";function b(a,b,d,e){var f;try{if(f=c(a),f.scopeIdent&&(d.nodeType!==Node.ELEMENT_NODE||"TEMPLATE"!==d.tagName||"bind"!==b&&"repeat"!==b))throw Error("as and in can only be used within <template bind/repeat>")}catch(g){return console.error("Invalid expression syntax: "+a,g),void 0}return function(a,b){var c=f.getBinding(a,e);return f.scopeIdent&&c&&(b.polymerExpressionScopeIdent_=f.scopeIdent,f.indexIdent&&(b.polymerExpressionIndexIdent_=f.indexIdent)),c}}function c(a){var b=n[a];if(!b){var c=new j;esprima.parse(a,c),b=new k(c),n[a]=b}return b}function d(a){this.value=a}function e(a,b,c){this.delegate=a,this.name=b,this.last=c}function f(a,b){this.object=a,this.property=b}function g(a,b){this.name=a,this.args=[];for(var c=0;c<b.length;c++)this.args[c]=i(b[c])}function h(){throw Error("Not Implemented")}function i(a){return"function"==typeof a?a:a.valueFn()}function j(){this.expression=null,this.filters=[],this.deps={},this.depsList=[],this.currentPath=void 0,this.scopeIdent=void 0,this.indexIdent=void 0}function k(a){if(this.scopeIdent=a.scopeIdent,this.indexIdent=a.indexIdent,!a.expression)throw Error("No expression found.");this.expression=a.expression,i(this.expression),this.paths=a.depsList,this.filters=a.filters}function l(a){return String(a).replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}function m(){}var n=Object.create(null);d.prototype={valueFn:function(){var a=this.value;return function(){return a}}},e.prototype={getPath:function(){return this.path_||(this.path_=this.last?Path.get(this.last.getPath()+"."+this.name):Path.get(this.name)),this.path_},valueFn:function(){if(!this.valueFn_){var a=this.getPath(),b=this.delegate.deps[a];void 0===b&&(b=this.delegate.deps[a]=this.delegate.depsList.length,this.delegate.depsList.push(a));var c=this.delegate.depsList;this.valueFn_=function(a){return 1===c.length?a:a[b]}}return this.valueFn_},setValue:function(a,b){return this.getPath().setValueFrom(a,b)}},f.prototype={valueFn:function(){var a=this.object,b=this.property;return function(c){return a(c)[b(c)]}},setValue:function(a,b,c){a=this.object(c);var d=this.property(c);return a[d]=b}},g.prototype={transform:function(a,b,c,d,e){var f=d[this.name];if(f)e=void 0;else if(f=e[this.name],!f)return console.error("Cannot find filter: "+this.name),void 0;if(c?f=f.toModel:"function"==typeof f.toDOM&&(f=f.toDOM),"function"!=typeof f)return console.error("No "+(c?"toModel":"toDOM")+" found on"+this.name),void 0;for(var g=[a],h=0;h<this.args.length;h++)g[h+1]=i(this.args[h])(b);return f.apply(e,g)}};var o={"+":function(a){return+a},"-":function(a){return-a},"!":function(a){return!a}},p={"+":function(a,b){return a+b},"-":function(a,b){return a-b},"*":function(a,b){return a*b},"/":function(a,b){return a/b},"%":function(a,b){return a%b},"<":function(a,b){return b>a},">":function(a,b){return a>b},"<=":function(a,b){return b>=a},">=":function(a,b){return a>=b},"==":function(a,b){return a==b},"!=":function(a,b){return a!=b},"===":function(a,b){return a===b},"!==":function(a,b){return a!==b},"&&":function(a,b){return a&&b},"||":function(a,b){return a||b}};j.prototype={createUnaryExpression:function(a,b){if(!o[a])throw Error("Disallowed operator: "+a);return b=i(b),function(c){return o[a](b(c))}},createBinaryExpression:function(a,b,c){if(!p[a])throw Error("Disallowed operator: "+a);return b=i(b),c=i(c),function(d){return p[a](b(d),c(d))}},createConditionalExpression:function(a,b,c){return a=i(a),b=i(b),c=i(c),function(d){return a(d)?b(d):c(d)}},createIdentifier:function(a){var b=new e(this,a);return b.type="Identifier",b},createMemberExpression:function(a,b,c){if(b instanceof e){if("."==a)return new e(this,c.name,b);if(c instanceof d&&Path.get(c.value).valid)return new e(this,c.value,b)}return new f(i(b),i(c))},createLiteral:function(a){return new d(a.value)},createArrayExpression:function(a){for(var b=0;b<a.length;b++)a[b]=i(a[b]);return function(b){for(var c=[],d=0;d<a.length;d++)c.push(a[d](b));return c}},createProperty:function(a,b,c){return{key:b instanceof e?b.name:b.value,value:c}},createObjectExpression:function(a){for(var b=0;b<a.length;b++)a[b].value=i(a[b].value);return function(b){for(var c={},d=0;d<a.length;d++)c[a[d].key]=a[d].value(b);return c}},createFilter:function(a,b){this.filters.push(new g(a,b))},createAsExpression:function(a,b){this.expression=a,this.scopeIdent=b},createInExpression:function(a,b,c){this.expression=c,this.scopeIdent=a,this.indexIdent=b},createTopLevel:function(a){this.expression=a},createThisExpression:h},k.prototype={getBinding:function(a,b){function c(c){return f.getValue(c,b,a)}function d(c){var d;if(1==f.paths.length)d=f.paths[0].getValueFrom(a);else{d=[];for(var e=0;e<f.paths.length;e++)d[e]=f.paths[e].getValueFrom(a)}f.setValue(a,c,d,b,a)}var e=this.paths;if(!e.length)return{value:this.getValue(void 0,b,a)};var f=this;if(1===e.length)return new PathObserver(a,e[0],void 0,void 0,c,d);for(var g=new CompoundPathObserver(void 0,void 0,c,d),h=0;h<e.length;h++)g.addPath(a,e[h]);return g.start(),g},getValue:function(a,b,c){for(var d=i(this.expression)(a),e=0;e<this.filters.length;e++)d=this.filters[e].transform(d,a,!1,b,c);return d},setValue:function(a,b,c,d,e){for(var f=this.filters?this.filters.length:0;f-->0;)b=this.filters[f].transform(b,c,!0,d,e);
-return this.expression.setValue?this.expression.setValue(a,b,c):void 0}},m.prototype={styleObject:function(a){var b=[];for(var c in a)b.push(l(c)+": "+a[c]);return b.join("; ")},tokenList:function(a){var b=[];for(var c in a)a[c]&&b.push(c);return b.join(" ")},prepareInstancePositionChanged:function(a){var b=a.polymerExpressionIndexIdent_;if(b)return function(a,c){a.model[b]=c}},prepareBinding:function(a,c,d){return Path.get(a).valid?void 0:b(a,c,d,this)},prepareInstanceModel:function(a){var b=a.polymerExpressionScopeIdent_;if(b){var c=a.templateInstance?a.templateInstance.model:a.model;return function(a){var d=Object.create(c);return d[b]=a,d}}}},a.PolymerExpressions=m}(this),function(a){function b(){e||(e=!0,a.endOfMicrotask(function(){e=!1,logFlags.data&&console.group("Platform.flush()"),a.performMicrotaskCheckpoint(),logFlags.data&&console.groupEnd()}))}var c=document.createElement("style");c.textContent="template {display: none !important;} /* injected by platform.js */";var d=document.querySelector("head");d.insertBefore(c,d.firstChild);var e,f=125;if(window.addEventListener("WebComponentsReady",function(){b(),Observer.hasObjectObserve||(a.flushPoll=setInterval(b,f))}),window.CustomElements&&!CustomElements.useNative){var g=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=g.call(this,a,b);return CustomElements.upgradeAll(c),c}}a.flush=b}(window.Platform);
+    <script>/**
+ * @license
+ * Copyright (c) 2012-2014 The Polymer Authors. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// @version: 0.2.1-59f745d
+function PointerGestureEvent(a,b){var c=b||{},d=document.createEvent("Event"),e={bubbles:Boolean(c.bubbles)===c.bubbles||!0,cancelable:Boolean(c.cancelable)===c.cancelable||!0};d.initEvent(a,e.bubbles,e.cancelable);for(var f,g=Object.keys(c),h=0;h<g.length;h++)f=g[h],d[f]=c[f];return d.preventTap=this.preventTap,d}"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),function(global){"use strict";function detectObjectObserve(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={},d=[];return Object.observe(c,a),Array.observe(d,a),c.id=1,c.id=2,delete c.id,d.push(1,2),d.length=0,Object.deliverChangeRecords(a),5!==b.length?!1:"add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type||"splice"!=b[3].type||"splice"!=b[4].type?!1:(Object.unobserve(c,a),Array.unobserve(d,a),!0)}function detectEval(){if(global.document&&"securityPolicy"in global.document&&!global.document.securityPolicy.allowsEval)return!1;try{var a=new Function("","return true;");return a()}catch(b){return!1}}function isIndex(a){return+a===a>>>0}function toNumber(a){return+a}function isObject(a){return a===Object(a)}function areSameValue(a,b){return a===b?0!==a||1/a===1/b:numberIsNaN(a)&&numberIsNaN(b)?!0:a!==a&&b!==b}function isPathValid(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:pathRegExp.test(a))}function Path(a,b){if(b!==constructorIsPrivate)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:isIndex(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),void(hasEval&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn())))}function getPath(a){if(a instanceof Path)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=pathCache[a];if(b)return b;if(!isPathValid(a))return invalidPath;var b=new Path(a,constructorIsPrivate);return pathCache[a]=b,b}function dirtyCheck(a){for(var b=0;MAX_DIRTY_CHECK_CYCLES>b&&a.check_();)b++;return global.testingExposeCycleCount&&(global.dirtyCheckCycleCount=b),b>0}function objectIsEmpty(a){for(var b in a)return!1;return!0}function diffIsEmpty(a){return objectIsEmpty(a.added)&&objectIsEmpty(a.removed)&&objectIsEmpty(a.changed)}function diffObjectFromOldObject(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function runEOMTasks(){if(!eomTasks.length)return!1;for(var a=0;a<eomTasks.length;a++)eomTasks[a]();return eomTasks.length=0,!0}function newObservedObject(){function a(a){b&&b.state_===OPENED&&!d&&b.check_(a)}var b,c,d=!1,e=!0;return{open:function(c){if(b)throw Error("ObservedObject in use");e||Object.deliverChangeRecords(a),b=c,e=!1},observe:function(b,d){c=b,d?Array.observe(c,a):Object.observe(c,a)},deliver:function(b){d=b,Object.deliverChangeRecords(a),d=!1},close:function(){b=void 0,Object.unobserve(c,a),observedObjectCache.push(this)}}}function getObservedObject(a,b,c){var d=observedObjectCache.pop()||newObservedObject();return d.open(a),d.observe(b,c),d}function newObservedSet(){function a(b){if(b){var c=i.indexOf(b);c>=0?(i[c]=void 0,h.push(b)):h.indexOf(b)<0&&(h.push(b),Object.observe(b,e)),a(Object.getPrototypeOf(b))}}function b(){var b=i===emptyArray?[]:i;i=h,h=b;var c;for(var d in f)c=f[d],c&&c.state_==OPENED&&c.iterateObjects_(a);for(var g=0;g<i.length;g++){var j=i[g];j&&Object.unobserve(j,e)}i.length=0}function c(){k=!1,j&&b()}function d(){k||(j=!0,k=!0,runEOM(c))}function e(){b();var a;for(var c in f)a=f[c],a&&a.state_==OPENED&&a.check_()}var f=[],g=0,h=[],i=emptyArray,j=!1,k=!1,l={object:void 0,objects:h,open:function(b){f[b.id_]=b,g++,b.iterateObjects_(a)},close:function(a){if(f[a.id_]=void 0,g--,g)return void d();j=!1;for(var b=0;b<h.length;b++)Object.unobserve(h[b],e),Observer.unobservedCount++;f.length=0,h.length=0,observedSetCache.push(this)},reset:d};return l}function getObservedSet(a,b){return lastObservedSet&&lastObservedSet.object===b||(lastObservedSet=observedSetCache.pop()||newObservedSet(),lastObservedSet.object=b),lastObservedSet.open(a),lastObservedSet}function Observer(){this.state_=UNOPENED,this.callback_=void 0,this.target_=void 0,this.directObserver_=void 0,this.value_=void 0,this.id_=nextObserverId++}function addToAll(a){Observer._allObserversCount++,collectObservers&&allObservers.push(a)}function removeFromAll(){Observer._allObserversCount--}function ObjectObserver(a){Observer.call(this),this.value_=a,this.oldObject_=void 0}function ArrayObserver(a){if(!Array.isArray(a))throw Error("Provided object is not an Array");ObjectObserver.call(this,a)}function PathObserver(a,b){Observer.call(this),this.object_=a,this.path_=b instanceof Path?b:getPath(b),this.directObserver_=void 0}function CompoundObserver(){Observer.call(this),this.value_=[],this.directObserver_=void 0,this.observed_=[]}function identFn(a){return a}function ObserverTransform(a,b,c,d){this.callback_=void 0,this.target_=void 0,this.value_=void 0,this.observable_=a,this.getValueFn_=b||identFn,this.setValueFn_=c||identFn,this.dontPassThroughSet_=d}function notifyFunction(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function diffObjectFromChangeRecords(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];expectedRecordTypes[g.type]?(g.name in c||(c[g.name]=g.oldValue),"update"!=g.type&&("add"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function newSplice(a,b,c){return{index:a,removed:b,addedCount:c}}function ArraySplice(){}function calcSplices(a,b,c,d,e,f){return arraySplice.calcSplices(a,b,c,d,e,f)}function intersect(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function mergeSplice(a,b,c,d){for(var e=newSplice(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=intersect(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function createInitialSplices(a,b){for(var c=[],d=0;d<b.length;d++){var e=b[d];switch(e.type){case"splice":mergeSplice(c,e.index,e.removed.slice(),e.addedCount);break;case"add":case"update":case"delete":if(!isIndex(e.name))continue;var f=toNumber(e.name);if(0>f)continue;mergeSplice(c,f,[e.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(e))}}return c}function projectArraySplices(a,b){var c=[];return createInitialSplices(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?void(b.removed[0]!==a[b.index]&&c.push(b)):void(c=c.concat(calcSplices(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)))}),c}var hasObserve=detectObjectObserve(),hasEval=detectEval(),numberIsNaN=global.Number.isNaN||function(a){return"number"==typeof a&&global.isNaN(a)},createObject="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},identStart="[$_a-zA-Z]",identPart="[$_a-zA-Z0-9]",ident=identStart+"+"+identPart+"*",elementIndex="(?:[0-9]|[1-9]+[0-9]+)",identOrElementIndex="(?:"+ident+"|"+elementIndex+")",path="(?:"+identOrElementIndex+")(?:\\s*\\.\\s*"+identOrElementIndex+")*",pathRegExp=new RegExp("^"+path+"$"),constructorIsPrivate={},pathCache={};Path.get=getPath,Path.prototype=createObject({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a){for(var b=0;b<this.length;b++){if(null==a)return;a=a[this[b]]}return a},iterateObjects:function(a,b){for(var c=0;c<this.length;c++){if(c&&(a=a[this[c-1]]),!isObject(a))return;b(a)}},compiledGetValueFromFn:function(){var a=this.map(function(a){return isIndex(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var d=0;d<this.length-1;d++){{this[d]}c+=a[d],b+=" &&\n     "+c+" != null"}return b+=")\n",c+=a[d],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!isObject(a))return!1;a=a[this[c]]}return isObject(a)?(a[this[c]]=b,!0):!1}});var invalidPath=new Path("",constructorIsPrivate);invalidPath.valid=!1,invalidPath.getValueFrom=invalidPath.setValueFrom=function(){};var MAX_DIRTY_CHECK_CYCLES=1e3,eomTasks=[],runEOM=hasObserve?function(){var a={pingPong:!0},b=!1;return Object.observe(a,function(){runEOMTasks(),b=!1}),function(c){eomTasks.push(c),b||(b=!0,a.pingPong=!a.pingPong)}}():function(){return function(a){eomTasks.push(a)}}(),observedObjectCache=[],emptyArray=[],observedSetCache=[],lastObservedSet,UNOPENED=0,OPENED=1,CLOSED=2,RESETTING=3,nextObserverId=1;Observer.prototype={open:function(a,b){if(this.state_!=UNOPENED)throw Error("Observer has already been opened.");return addToAll(this),this.callback_=a,this.target_=b,this.state_=OPENED,this.connect_(),this.value_},close:function(){this.state_==OPENED&&(removeFromAll(this),this.state_=CLOSED,this.disconnect_(),this.value_=void 0,this.callback_=void 0,this.target_=void 0)},deliver:function(){this.state_==OPENED&&dirtyCheck(this)},report_:function(a){try{this.callback_.apply(this.target_,a)}catch(b){Observer._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},discardChanges:function(){return this.check_(void 0,!0),this.value_}};var collectObservers=!hasObserve,allObservers;Observer._allObserversCount=0,collectObservers&&(allObservers=[]);var runningMicrotaskCheckpoint=!1,hasDebugForceFullDelivery=hasObserve&&function(){try{return eval("%RunMicrotasks()"),!0}catch(ex){return!1}}();global.Platform=global.Platform||{},global.Platform.performMicrotaskCheckpoint=function(){if(!runningMicrotaskCheckpoint){if(hasDebugForceFullDelivery)return void eval("%RunMicrotasks()");if(collectObservers){runningMicrotaskCheckpoint=!0;var cycles=0,anyChanged,toCheck;do{cycles++,toCheck=allObservers,allObservers=[],anyChanged=!1;for(var i=0;i<toCheck.length;i++){var observer=toCheck[i];observer.state_==OPENED&&(observer.check_()&&(anyChanged=!0),allObservers.push(observer))}runEOMTasks()&&(anyChanged=!0)}while(MAX_DIRTY_CHECK_CYCLES>cycles&&anyChanged);global.testingExposeCycleCount&&(global.dirtyCheckCycleCount=cycles),runningMicrotaskCheckpoint=!1}}},collectObservers&&(global.Platform.clearObservers=function(){allObservers=[]}),ObjectObserver.prototype=createObject({__proto__:Observer.prototype,arrayObserve:!1,connect_:function(){hasObserve?this.directObserver_=getObservedObject(this,this.value_,this.arrayObserve):this.oldObject_=this.copyObject(this.value_)},copyObject:function(a){var b=Array.isArray(a)?[]:{};for(var c in a)b[c]=a[c];return Array.isArray(a)&&(b.length=a.length),b},check_:function(a){var b,c;if(hasObserve){if(!a)return!1;c={},b=diffObjectFromChangeRecords(this.value_,a,c)}else c=this.oldObject_,b=diffObjectFromOldObject(this.value_,this.oldObject_);return diffIsEmpty(b)?!1:(hasObserve||(this.oldObject_=this.copyObject(this.value_)),this.report_([b.added||{},b.removed||{},b.changed||{},function(a){return c[a]}]),!0)},disconnect_:function(){hasObserve?(this.directObserver_.close(),this.directObserver_=void 0):this.oldObject_=void 0},deliver:function(){this.state_==OPENED&&(hasObserve?this.directObserver_.deliver(!1):dirtyCheck(this))},discardChanges:function(){return this.directObserver_?this.directObserver_.deliver(!0):this.oldObject_=this.copyObject(this.value_),this.value_}}),ArrayObserver.prototype=createObject({__proto__:ObjectObserver.prototype,arrayObserve:!0,copyObject:function(a){return a.slice()},check_:function(a){var b;if(hasObserve){if(!a)return!1;b=projectArraySplices(this.value_,a)}else b=calcSplices(this.value_,0,this.value_.length,this.oldObject_,0,this.oldObject_.length);return b&&b.length?(hasObserve||(this.oldObject_=this.copyObject(this.value_)),this.report_([b]),!0):!1}}),ArrayObserver.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})},PathObserver.prototype=createObject({__proto__:Observer.prototype,connect_:function(){hasObserve&&(this.directObserver_=getObservedSet(this,this.object_)),this.check_(void 0,!0)},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0)},iterateObjects_:function(a){this.path_.iterateObjects(this.object_,a)},check_:function(a,b){var c=this.value_;return this.value_=this.path_.getValueFrom(this.object_),b||areSameValue(this.value_,c)?!1:(this.report_([this.value_,c]),!0)},setValue:function(a){this.path_&&this.path_.setValueFrom(this.object_,a)}});var observerSentinel={};CompoundObserver.prototype=createObject({__proto__:Observer.prototype,connect_:function(){if(this.check_(void 0,!0),hasObserve){for(var a,b=!1,c=0;c<this.observed_.length;c+=2)if(a=this.observed_[c],a!==observerSentinel){b=!0;break}return this.directObserver_?b?void this.directObserver_.reset():(this.directObserver_.close(),void(this.directObserver_=void 0)):void(b&&(this.directObserver_=getObservedSet(this,a)))}},closeObservers_:function(){for(var a=0;a<this.observed_.length;a+=2)this.observed_[a]===observerSentinel&&this.observed_[a+1].close();this.observed_.length=0},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0),this.closeObservers_()},addPath:function(a,b){if(this.state_!=UNOPENED&&this.state_!=RESETTING)throw Error("Cannot add paths once started.");this.observed_.push(a,b instanceof Path?b:getPath(b))},addObserver:function(a){if(this.state_!=UNOPENED&&this.state_!=RESETTING)throw Error("Cannot add observers once started.");a.open(this.deliver,this),this.observed_.push(observerSentinel,a)},startReset:function(){if(this.state_!=OPENED)throw Error("Can only reset while open");this.state_=RESETTING,this.closeObservers_()},finishReset:function(){if(this.state_!=RESETTING)throw Error("Can only finishReset after startReset");return this.state_=OPENED,this.connect_(),this.value_},iterateObjects_:function(a){for(var b,c=0;c<this.observed_.length;c+=2)b=this.observed_[c],b!==observerSentinel&&this.observed_[c+1].iterateObjects(b,a)},check_:function(a,b){for(var c,d=0;d<this.observed_.length;d+=2){var e=this.observed_[d+1],f=this.observed_[d],g=f===observerSentinel?e.discardChanges():e.getValueFrom(f);b?this.value_[d/2]=g:areSameValue(g,this.value_[d/2])||(c=c||[],c[d/2]=this.value_[d/2],this.value_[d/2]=g)}return c?(this.report_([this.value_,c,this.observed_]),!0):!1}}),ObserverTransform.prototype={open:function(a,b){return this.callback_=a,this.target_=b,this.value_=this.getValueFn_(this.observable_.open(this.observedCallback_,this)),this.value_},observedCallback_:function(a){if(a=this.getValueFn_(a),!areSameValue(a,this.value_)){var b=this.value_;this.value_=a,this.callback_.call(this.target_,this.value_,b)}},discardChanges:function(){return this.value_=this.getValueFn_(this.observable_.discardChanges()),this.value_},deliver:function(){return this.observable_.deliver()},setValue:function(a){return a=this.setValueFn_(a),!this.dontPassThroughSet_&&this.observable_.setValue?this.observable_.setValue(a):void 0},close:function(){this.observable_&&this.observable_.close(),this.callback_=void 0,this.target_=void 0,this.observable_=void 0,this.value_=void 0,this.getValueFn_=void 0,this.setValueFn_=void 0}};var expectedRecordTypes={add:!0,update:!0,"delete":!0};Observer.defineComputedProperty=function(a,b,c){var d=notifyFunction(a,b),e=c.open(function(a,b){e=a,d&&d("update",b)});return Object.defineProperty(a,b,{get:function(){return c.deliver(),e},set:function(a){return c.setValue(a),a},configurable:!0}),{close:function(){c.close(),Object.defineProperty(a,b,{value:e,writable:!0,configurable:!0})}}};var EDIT_LEAVE=0,EDIT_UPDATE=1,EDIT_ADD=2,EDIT_DELETE=3;ArraySplice.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(EDIT_LEAVE):(e.push(EDIT_UPDATE),d=g),b--,c--):f==h?(e.push(EDIT_DELETE),b--,d=h):(e.push(EDIT_ADD),c--,d=i)}else e.push(EDIT_DELETE),b--;else e.push(EDIT_ADD),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,c-b==0&&f-e==0)return[];if(b==c){for(var j=newSplice(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[newSplice(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case EDIT_LEAVE:j&&(l.push(j),j=void 0),m++,n++;break;case EDIT_UPDATE:j||(j=newSplice(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case EDIT_ADD:j||(j=newSplice(m,[],0)),j.addedCount++,m++;break;case EDIT_DELETE:j||(j=newSplice(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var arraySplice=new ArraySplice;global.Observer=Observer,global.Observer.runEOM_=runEOM,global.Observer.hasObjectObserve=hasObserve,global.ArrayObserver=ArrayObserver,global.ArrayObserver.calculateSplices=function(a,b){return arraySplice.calculateSplices(a,b)},global.ArraySplice=ArraySplice,global.ObjectObserver=ObjectObserver,global.PathObserver=PathObserver,global.CompoundObserver=CompoundObserver,global.Path=Path,global.ObserverTransform=ObserverTransform}("undefined"!=typeof global&&global&&"undefined"!=typeof module&&module?global:this||window),window.Platform=window.Platform||{},window.logFlags=window.logFlags||{},function(a){var b=a.flags||{};location.search.slice(1).split("&").forEach(function(a){a=a.split("="),a[0]&&(b[a[0]]=a[1]||!0)});var c=document.currentScript||document.querySelector('script[src*="platform.js"]');if(c)for(var d,e=c.attributes,f=0;f<e.length;f++)d=e[f],"src"!==d.name&&(b[d.name]=d.value||!0);b.log&&b.log.split(",").forEach(function(a){window.logFlags[a]=!0}),b.shadow=b.shadow||b.shadowdom||b.polyfill,b.shadow="native"===b.shadow?!1:b.shadow||!HTMLElement.prototype.createShadowRoot,b.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=b.register),b.imports&&(window.HTMLImports=window.HTMLImports||{flags:{}},window.HTMLImports.flags.imports=b.imports),a.flags=b}(Platform),Platform.flags.shadow?(window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return L(b).forEach(function(c){K(a,c,M(b,c))}),a}function d(a,b){return L(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}K(a,c,M(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=E.get(b);if(c)return c;var d=f(b),e=t(d);return q(b,e,a),e}function g(a,b){o(a,b,!0)}function h(a,b){o(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return H&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return H&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return H&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(a,b){try{return Object.getOwnPropertyDescriptor(a,b)}catch(c){return O}}function o(b,c,d){for(var e=L(b),f=0;f<e.length;f++){var g=e[f];if("polymerBlackList_"!==g&&!(g in c||b.polymerBlackList_&&b.polymerBlackList_[g])){N&&b.__lookupGetter__(g);var h,j,o=n(b,g);if(d&&"function"==typeof o.value)c[g]=m(g);else{var p=i(g);h=p?a.getEventHandlerGetter(g):k(g),(o.writable||o.set)&&(j=p?a.getEventHandlerSetter(g):l(g)),K(c,g,{get:h,set:j,configurable:o.configurable,enumerable:o.enumerable})}}}}function p(a,b,c){var e=a.prototype;q(e,b,c),d(b,a)}function q(a,c,d){var e=c.prototype;b(void 0===E.get(a)),E.set(a,c),F.set(e,a),g(a,e),d&&h(e,d),K(e,"constructor",{value:c,configurable:!0,enumerable:!1,writable:!0}),c.prototype=e}function r(a,b){return E.get(b.prototype)===a}function s(a){var b=Object.getPrototypeOf(a),c=f(b),d=t(c);return q(b,d,a),d}function t(a){function b(b){a.call(this,b)}var c=Object.create(a.prototype);return c.constructor=b,b.prototype=c,b}function u(a){return a instanceof G.EventTarget||a instanceof G.Event||a instanceof G.Range||a instanceof G.DOMImplementation||a instanceof G.CanvasRenderingContext2D||G.WebGLRenderingContext&&a instanceof G.WebGLRenderingContext}function v(a){return Q&&a instanceof Q||a instanceof S||a instanceof R||a instanceof T||a instanceof U||a instanceof P||a instanceof V||W&&a instanceof W||X&&a instanceof X}function w(a){return null===a?null:(b(v(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function x(a){return null===a?null:(b(u(a)),a.impl)}function y(a){return a&&u(a)?x(a):a}function z(a){return a&&!u(a)?w(a):a}function A(a,c){null!==c&&(b(v(a)),b(void 0===c||u(c)),a.polymerWrapper_=c)}function B(a,b,c){K(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function C(a,b){B(a,b,function(){return w(this.impl[b])})}function D(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=z(this);return a[b].apply(a,arguments)}})})}var E=new WeakMap,F=new WeakMap,G=Object.create(null),H=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(H)try{var I=new Function("","return true;");H=I()}catch(J){H=!1}var K=Object.defineProperty,L=Object.getOwnPropertyNames,M=Object.getOwnPropertyDescriptor;L(window);var N=/Firefox/.test(navigator.userAgent),O={get:function(){},set:function(){},configurable:!0,enumerable:!0},P=window.DOMImplementation,Q=window.EventTarget,R=window.Event,S=window.Node,T=window.Window,U=window.Range,V=window.CanvasRenderingContext2D,W=window.WebGLRenderingContext,X=window.SVGElementInstance;a.assert=b,a.constructorTable=E,a.defineGetter=B,a.defineWrapGetter=C,a.forwardMethodsToWrapper=D,a.isWrapper=u,a.isWrapperFor=r,a.mixin=c,a.nativePrototypeTable=F,a.oneOf=e,a.registerObject=s,a.registerWrapper=p,a.rewrap=A,a.unwrap=x,a.unwrapIfNeeded=y,a.wrap=w,a.wrapIfNeeded=z,a.wrappers=G}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if((h===a||l.subtree)&&!("attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){this.root=a,this.parent=b}function c(a,b){if(a.treeScope_!==b){a.treeScope_=b;for(var d=a.shadowRoot;d;d=d.olderShadowRoot)d.treeScope_.parent=b;for(var e=a.firstChild;e;e=e.nextSibling)c(e,b)}}function d(a){if(a.treeScope_)return a.treeScope_;var c,e=a.parentNode;return c=e?d(e):new b(a,null),a.treeScope_=c}b.prototype={get renderer(){return this.root instanceof a.wrappers.ShadowRoot?a.getRendererForHost(this.root.host):null},contains:function(a){for(;a;a=a.parent)if(a===this)return!0;return!1}},a.TreeScope=b,a.getTreeScope=d,a.setTreeScope=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof Q.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&P(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var m=null;if(g.length){if(c(i)&&(m=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(l(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,m,e)}a=b(a)?a.host:a.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a,b){return L(a)===L(b)}function m(a){S.get(a)||(S.set(a,!0),o(P(a),P(a.target)))}function n(a){switch(a.type){case"beforeunload":case"load":case"unload":return!0}return!1}function o(b,c){if(T.get(b))throw new Error("InvalidStateError");T.set(b,!0),a.renderAllPending();var d=g(c);return 2===d.length&&d[0].target instanceof Q.Document&&n(b)&&d.shift(),_.set(b,d),p(b,d)&&q(b,d)&&r(b,d),X.set(b,u.NONE),V.delete(b,null),T.delete(b),b.defaultPrevented}function p(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=u.CAPTURING_PHASE,!s(b[d],a,c)))return!1}return!0}function q(a,b){var c=u.AT_TARGET;return s(b[0],a,c)}function r(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=u.AT_TARGET;else{if(!d||Z.get(a))continue;c=u.BUBBLING_PHASE}if(!s(b[e],a,c))return}}function s(a,b,c){var d=a.target,e=a.currentTarget,f=R.get(e);if(!f)return!0;if("relatedTarget"in b){var g=O(b),h=g.relatedTarget;if(h&&h instanceof Object&&h.addEventListener){var j=P(h),k=i(e,j);if(k===d)return!0;W.set(b,k)}}X.set(b,c);var l=b.type,m=!1;U.set(b,d),V.set(b,e);for(var n=0;n<f.length;n++){var o=f[n];if(o.removed)m=!0;else if(!(o.type!==l||!o.capture&&c===u.CAPTURING_PHASE||o.capture&&c===u.BUBBLING_PHASE))try{if("function"==typeof o.handler?o.handler.call(e,b):o.handler.handleEvent(b),Z.get(b))return!1}catch(p){window.onerror?window.onerror(p.message):console.error(p,p.stack)}}if(m){var q=f.slice();f.length=0;for(var n=0;n<q.length;n++)q[n].removed||f.push(q[n])}return!Y.get(b)}function t(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function u(a,b){if(!(a instanceof ab))return P(y(ab,"Event",a,b));var c=a;return lb||"beforeunload"!==c.type?void(this.impl=c):new z(c)}function v(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:O(a.relatedTarget)}}):a
+}function w(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?void(this.impl=b):P(y(d,a,b,c))};if(e.prototype=Object.create(b.prototype),c&&M(e.prototype,c),d)try{N(d,e,new d("temp"))}catch(f){N(d,e,document.createEvent(a))}return e}function x(a,b){return function(){arguments[b]=O(arguments[b]);var c=O(this);c[a].apply(c,arguments)}}function y(a,b,c,d){if(jb)return new a(c,v(d));var e=O(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=O(b)),g.push(b)}),e["init"+b].apply(e,g),e}function z(a){u.call(this,a)}function A(a){return"function"==typeof a?!0:a&&a.handleEvent}function B(a){switch(a){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function C(a){this.impl=a}function D(a){return a instanceof Q.ShadowRoot&&(a=a.host),O(a)}function E(a,b){var c=R.get(a);if(c)for(var d=0;d<c.length;d++)if(!c[d].removed&&c[d].type===b)return!0;return!1}function F(a,b){for(var c=O(a);c;c=c.parentNode)if(E(P(c),b))return!0;return!1}function G(a){K(a,nb)}function H(b,c,d,e){a.renderAllPending();for(var f=P(ob.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function I(a){return function(){var b=$.get(this);return b&&b[a]&&b[a].value||null}}function J(a){var b=a.slice(2);return function(c){var d=$.get(this);d||(d=Object.create(null),$.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var K=a.forwardMethodsToWrapper,L=a.getTreeScope,M=a.mixin,N=a.registerWrapper,O=a.unwrap,P=a.wrap,Q=a.wrappers,R=(new WeakMap,new WeakMap),S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap,$=new WeakMap,_=new WeakMap;t.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var ab=window.Event;ab.prototype.polymerBlackList_={returnValue:!0,keyLocation:!0},u.prototype={get target(){return U.get(this)},get currentTarget(){return V.get(this)},get eventPhase(){return X.get(this)},get path(){var a=new Q.NodeList,b=_.get(this);if(b){for(var c=0,d=b.length-1,e=L(V.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=L(g);h.contains(e)&&(f!==d||g instanceof Q.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){Y.set(this,!0)},stopImmediatePropagation:function(){Y.set(this,!0),Z.set(this,!0)}},N(ab,u,document.createEvent("Event"));var bb=w("UIEvent",u),cb=w("CustomEvent",u),db={get relatedTarget(){return W.get(this)||P(O(this).relatedTarget)}},eb=M({initMouseEvent:x("initMouseEvent",14)},db),fb=M({initFocusEvent:x("initFocusEvent",5)},db),gb=w("MouseEvent",bb,eb),hb=w("FocusEvent",bb,fb),ib=Object.create(null),jb=function(){try{new window.FocusEvent("focus")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=M(M({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.BeforeUnloadEvent;z.prototype=Object.create(u.prototype),M(z.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}}),lb&&N(lb,z);var mb=window.EventTarget,nb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;nb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),C.prototype={addEventListener:function(a,b,c){if(A(b)&&!B(a)){var d=new t(a,b,c),e=R.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],R.set(this,e);e.push(d);var g=D(this);g.addEventListener_(a,m,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=R.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=D(this);h.removeEventListener_(a,m,!0)}}},dispatchEvent:function(b){var c=O(b),d=c.type;S.set(c,!1),a.renderAllPending();var e;F(this,d)||(e=function(){},this.addEventListener(d,e,!0));try{return O(this).dispatchEvent_(c)}finally{e&&this.removeEventListener(d,e,!0)}}},mb&&N(mb,C);var ob=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=H,a.getEventHandlerGetter=I,a.getEventHandlerSetter=J,a.wrapEventTargetMethods=G,a.wrappers.BeforeUnloadEvent=z,a.wrappers.CustomEvent=cb,a.wrappers.Event=u,a.wrappers.EventTarget=C,a.wrappers.FocusEvent=hb,a.wrappers.MouseEvent=gb,a.wrappers.UIEvent=bb}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(window.ShadowDOMPolyfill),function(a){"use strict";a.wrapHTMLCollection=a.wrapNodeList,a.wrappers.HTMLCollection=a.wrappers.NodeList}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){A(a instanceof w)}function c(a){var b=new y;return b[0]=a,b.length=1,b}function d(a,b,c){C(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){C(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);N=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;N=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new y,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b.length=c,e(a,b),b}function i(a){return a}function j(a,b){I(a,b),a.nodeIsInserted_()}function k(a,b){for(var c=D(b),d=0;d<a.length;d++)j(a[d],c)}function l(a){I(a,new z(a,null))}function m(a){for(var b=0;b<a.length;b++)l(a[b])}function n(a,b){var c=a.nodeType===w.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function p(a,b){o(a,b);var c=b.length;if(1===c)return J(b[0]);for(var d=J(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(J(b[e]));return d}function q(a){if(void 0!==a.firstChild_)for(var b=a.firstChild_;b;){var c=b;b=b.nextSibling_,c.parentNode_=c.previousSibling_=c.nextSibling_=void 0}a.firstChild_=a.lastChild_=void 0}function r(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){A(b.parentNode===a);var c=b.nextSibling,d=J(b),e=d.parentNode;e&&U.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=J(a),g=f.firstChild;g;)c=g.nextSibling,U.call(f,g),g=c}function s(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function t(a){for(var b,c=0;c<a.length;c++)b=a[c],b.parentNode.removeChild(b)}function u(a,b,c){var d;if(d=K(c?O.call(c,a.impl,!1):P.call(a.impl,!1)),b){for(var e=a.firstChild;e;e=e.nextSibling)d.appendChild(u(e,!0,c));if(a instanceof M.HTMLTemplateElement)for(var f=d.content,e=a.content.firstChild;e;e=e.nextSibling)f.appendChild(u(e,!0,c))}return d}function v(a,b){if(!b||D(a)!==D(b))return!1;for(var c=b;c;c=c.parentNode)if(c===a)return!0;return!1}function w(a){A(a instanceof Q),x.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0,this.treeScope_=void 0}var x=a.wrappers.EventTarget,y=a.wrappers.NodeList,z=a.TreeScope,A=a.assert,B=a.defineWrapGetter,C=a.enqueueMutation,D=a.getTreeScope,E=a.isWrapper,F=a.mixin,G=a.registerTransientObservers,H=a.registerWrapper,I=a.setTreeScope,J=a.unwrap,K=a.wrap,L=a.wrapIfNeeded,M=a.wrappers,N=!1,O=document.importNode,P=window.Node.prototype.cloneNode,Q=window.Node,R=window.DocumentFragment,S=(Q.prototype.appendChild,Q.prototype.compareDocumentPosition),T=Q.prototype.insertBefore,U=Q.prototype.removeChild,V=Q.prototype.replaceChild,W=/Trident/.test(navigator.userAgent),X=W?function(a,b){try{U.call(a,b)}catch(c){if(!(a instanceof R))throw c}}:function(a,b){U.call(a,b)};w.prototype=Object.create(x.prototype),F(w.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a);var d;c?E(c)?d=J(c):(d=c,c=K(d)):(c=null,d=null),c&&A(c.parentNode===this);var e,h=c?c.previousSibling:this.lastChild,i=!this.invalidateShadowRenderer()&&!s(a);if(e=i?g(a):f(a,this,h,c),i)n(this,a),q(this),T.call(this.impl,J(a),d);else{h||(this.firstChild_=e[0]),c||(this.lastChild_=e[e.length-1]);var j=d?d.parentNode:this.impl;j?T.call(j,p(this,e),d):o(this,e)}return C(this,"childList",{addedNodes:e,nextSibling:c,previousSibling:h}),k(e,this),a},removeChild:function(a){if(b(a),a.parentNode!==this){for(var d=!1,e=(this.childNodes,this.firstChild);e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=J(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&X(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else q(this),X(this.impl,f);return N||C(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),G(this,a),a},replaceChild:function(a,d){b(a);var e;if(E(d)?e=J(d):(e=d,d=K(e)),d.parentNode!==this)throw new Error("NotFoundError");var h,i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!s(a);return m?h=g(a):(i===a&&(i=a.nextSibling),h=f(a,this,j,i)),m?(n(this,a),q(this),V.call(this.impl,J(a),e)):(this.firstChild===d&&(this.firstChild_=h[0]),this.lastChild===d&&(this.lastChild_=h[h.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,e.parentNode&&V.call(e.parentNode,p(this,h),e)),C(this,"childList",{addedNodes:h,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(h,this),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:K(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:K(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:K(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:K(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:K(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==w.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)b.nodeType!=w.COMMENT_NODE&&(a+=b.textContent);return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(r(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else q(this),this.impl.textContent=a;var d=i(this.childNodes);C(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d,this)},get childNodes(){for(var a=new y,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){return u(this,a)},contains:function(a){return v(this,L(a))},compareDocumentPosition:function(a){return S.call(this.impl,J(a))},normalize:function(){for(var a,b,c=i(this.childNodes),d=[],e="",f=0;f<c.length;f++)b=c[f],b.nodeType===w.TEXT_NODE?a||b.data.length?a?(e+=b.data,d.push(b)):a=b:this.removeNode(b):(a&&d.length&&(a.data+=e,cleanUpNodes(d)),d=[],e="",a=null,b.childNodes.length&&b.normalize());a&&d.length&&(a.data+=e,t(d))}}),B(w,"ownerDocument"),H(Q,w,document.createDocumentFragment()),delete w.prototype.querySelector,delete w.prototype.querySelectorAll,w.prototype=F(Object.create(x.prototype),w.prototype),a.cloneNode=u,a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=w}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a},remove:function(){var a=this.parentNode;a&&a.removeChild(this)}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a>>>0}function c(a){d.call(this,a)}var d=a.wrappers.CharacterData,e=(a.enqueueMutation,a.mixin),f=a.registerWrapper,g=window.Text;c.prototype=Object.create(d.prototype),e(c.prototype,{splitText:function(a){a=b(a);var c=this.data;if(a>c.length)throw new Error("IndexSizeError");var d=c.slice(0,a),e=c.slice(a);this.data=d;var f=this.ownerDocument.createTextNode(e);return this.parentNode&&this.parentNode.insertBefore(f,this.nextSibling),f}}),f(g,c,document.createTextNode("")),a.wrappers.Text=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=(a.oneOf,a.registerWrapper),n=a.wrappers,o=window.Element,p=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(a){return o.prototype[a]}),q=p[0],r=o.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new n.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),p.forEach(function(a){"matches"!==a&&(d.prototype[a]=function(a){return this.matches(a)})}),o.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),m(o,d,document.createElementNS(null,"x")),a.matchesNames=p,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case">":return"&gt;";case'"':return"&quot;";case"Â ":return"&nbsp;"}}function c(a){return a.replace(z,b)}function d(a){return a.replace(A,b)}function e(a){for(var b={},c=0;c<a.length;c++)b[a[c]]=!0;return b}function f(a,b){switch(a.nodeType){case Node.ELEMENT_NODE:for(var e,f=a.tagName.toLowerCase(),h="<"+f,i=a.attributes,j=0;e=i[j];j++)h+=" "+e.name+'="'+c(e.value)+'"';return h+=">",B[f]?h:h+g(a)+"</"+f+">";case Node.TEXT_NODE:var k=a.data;return b&&C[b.localName]?k:d(k);case Node.COMMENT_NODE:return"<!--"+a.data+"-->";default:throw console.error(a),new Error("not implemented")}}function g(a){a instanceof y.HTMLTemplateElement&&(a=a.content);for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=f(c,a);return b}function h(a,b,c){var d=c||"div";a.textContent="";var e=w(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(x(f))}function i(a){o.call(this,a)}function j(a,b){var c=w(a.cloneNode(!1));c.innerHTML=b;for(var d,e=w(document.createDocumentFragment());d=c.firstChild;)e.appendChild(d);return x(e)}function k(b){return function(){return a.renderAllPending(),this.impl[b]}}function l(a){p(i,a,k(a))}function m(b){Object.defineProperty(i.prototype,b,{get:k(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function n(b){Object.defineProperty(i.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var o=a.wrappers.Element,p=a.defineGetter,q=a.enqueueMutation,r=a.mixin,s=a.nodesWereAdded,t=a.nodesWereRemoved,u=a.registerWrapper,v=a.snapshotNodeList,w=a.unwrap,x=a.wrap,y=a.wrappers,z=/[&\u00A0"]/g,A=/[&\u00A0<>]/g,B=e(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),C=e(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D=/MSIE/.test(navigator.userAgent),E=window.HTMLElement,F=window.HTMLTemplateElement;i.prototype=Object.create(o.prototype),r(i.prototype,{get innerHTML(){return g(this)},set innerHTML(a){if(D&&C[this.localName])return void(this.textContent=a);var b=v(this.childNodes);this.invalidateShadowRenderer()?this instanceof y.HTMLTemplateElement?h(this.content,a):h(this,a,this.tagName):!F&&this instanceof y.HTMLTemplateElement?h(this.content,a):this.impl.innerHTML=a;var c=v(this.childNodes);q(this,"childList",{addedNodes:c,removedNodes:b}),t(b),s(c,this)},get outerHTML(){return f(this,this.parentNode)},set outerHTML(a){var b=this.parentNode;if(b){b.invalidateShadowRenderer();var c=j(b,a);b.replaceChild(c,this)}},insertAdjacentHTML:function(a,b){var c,d;switch(String(a).toLowerCase()){case"beforebegin":c=this.parentNode,d=this;break;case"afterend":c=this.parentNode,d=this.nextSibling;break;case"afterbegin":c=this,d=this.firstChild;break;case"beforeend":c=this,d=null;break;default:return}var e=j(c,b);c.insertBefore(e,d)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(l),["scrollLeft","scrollTop"].forEach(m),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(n),u(E,i,document.createElement("b")),a.wrappers.HTMLElement=i,a.getInnerHTML=g,a.setInnerHTML=h}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=k.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);k.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=h(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!l){var b=c(a);j.set(this,i(b))}}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.unwrap,i=a.wrap,j=new WeakMap,k=new WeakMap,l=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),f(d.prototype,{get content(){return l?i(this.impl.content):j.get(this)}}),l&&g(l,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.wrap,h=window.HTMLSelectElement;b.prototype=Object.create(c.prototype),d(b.prototype,{add:function(a,b){"object"==typeof b&&(b=f(b)),f(this).add(f(a),b)},remove:function(a){return void 0===a?void c.prototype.remove.call(this):("object"==typeof a&&(a=f(a)),void f(this).remove(a))},get form(){return g(f(this).form)}}),e(h,b,document.createElement("select")),a.wrappers.HTMLSelectElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.wrap,h=a.wrapHTMLCollection,i=window.HTMLTableElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get caption(){return g(f(this).caption)},createCaption:function(){return g(f(this).createCaption())},get tHead(){return g(f(this).tHead)},createTHead:function(){return g(f(this).createTHead())},createTFoot:function(){return g(f(this).createTFoot())},get tFoot(){return g(f(this).tFoot)},get tBodies(){return h(f(this).tBodies)},createTBody:function(){return g(f(this).createTBody())},get rows(){return h(f(this).rows)},insertRow:function(a){return g(f(this).insertRow(a))}}),e(i,b,document.createElement("table")),a.wrappers.HTMLTableElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrapHTMLCollection,g=a.unwrap,h=a.wrap,i=window.HTMLTableSectionElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get rows(){return f(g(this).rows)},insertRow:function(a){return h(g(this).insertRow(a))}}),e(i,b,document.createElement("thead")),a.wrappers.HTMLTableSectionElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrapHTMLCollection,g=a.unwrap,h=a.wrap,i=window.HTMLTableRowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get cells(){return f(g(this).cells)},insertCell:function(a){return h(g(this).insertCell(a))}}),e(i,b,document.createElement("tr")),a.wrappers.HTMLTableRowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.registerObject,c="http://www.w3.org/2000/svg",d=document.createElementNS(c,"title"),e=b(d),f=Object.getPrototypeOf(e.prototype).constructor;a.wrappers.SVGElement=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){m.call(this,a)}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.SVGUseElement,h="http://www.w3.org/2000/svg",i=f(document.createElementNS(h,"g")),j=document.createElementNS(h,"use"),k=i.constructor,l=Object.getPrototypeOf(k.prototype),m=l.constructor;b.prototype=Object.create(l),"instanceRoot"in j&&c(b.prototype,{get instanceRoot(){return f(e(this).instanceRoot)},get animatedInstanceRoot(){return f(e(this).animatedInstanceRoot)}}),d(g,b,j),a.wrappers.SVGUseElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.SVGElementInstance;g&&(b.prototype=Object.create(c.prototype),d(b.prototype,{get correspondingElement(){return f(this.impl.correspondingElement)},get correspondingUseElement(){return f(this.impl.correspondingUseElement)},get parentNode(){return f(this.impl.parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return f(this.impl.firstChild)},get lastChild(){return f(this.impl.lastChild)},get previousSibling(){return f(this.impl.previousSibling)},get nextSibling(){return f(this.impl.nextSibling)}}),e(g,b),a.wrappers.SVGElementInstance=b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(g){c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))},toString:function(){return this.impl.toString()}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());
+e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createComment(""));a.wrappers.Comment=h,a.wrappers.DocumentFragment=g}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=k(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),i(b,this),this.treeScope_=new d(this,g(a));var e=a.shadowRoot;m.set(this,e),l.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.TreeScope,e=a.elementFromPoint,f=a.getInnerHTML,g=a.getTreeScope,h=a.mixin,i=a.rewrap,j=a.setInnerHTML,k=a.unwrap,l=new WeakMap,m=new WeakMap,n=/[ \t\n\r\f]/;b.prototype=Object.create(c.prototype),h(b.prototype,{get innerHTML(){return f(this)},set innerHTML(a){j(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return m.get(this)||null},get host(){return l.get(this)||null},invalidateShadowRenderer:function(){return l.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return e(this,this.ownerDocument,a,b)},getElementById:function(a){return n.test(a)?null:this.querySelector('[id="'+a+'"]')}}),a.wrappers.ShadowRoot=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){var b=I.get(a);return b||I.set(a,b=[]),b}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof z))return!1;if("*"===c||c===a.localName)return!0;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++){var b=P[a],c=b.parentRenderer;c&&c.dirty||b.render()}P=[]}function l(){y=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){var b=E(a).root;return b instanceof D?b:null}function o(a){return m(a.host)}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof A}function s(a){return a instanceof A}function t(a){return a instanceof B}function u(a){return a instanceof B}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y,z=a.wrappers.Element,A=a.wrappers.HTMLContentElement,B=a.wrappers.HTMLShadowElement,C=a.wrappers.Node,D=a.wrappers.ShadowRoot,E=(a.assert,a.getTreeScope),F=(a.mixin,a.oneOf),G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=F(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},get parentRenderer(){return E(this.host).renderer},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),y)return;y=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},C.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},A.prototype.getDistributedNodes=function(){return k(),g(this)},B.prototype.nodeIsInserted_=A.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}{var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap;window.Selection}b.prototype={get anchorNode(){return f(this.impl.anchorNode)},get focusNode(){return f(this.impl.focusNode)},addRange:function(a){this.impl.addRange(d(a))},collapse:function(a,b){this.impl.collapse(e(a),b)},containsNode:function(a,b){return this.impl.containsNode(e(a),b)},extend:function(a,b){this.impl.extend(e(a),b)},getRangeAt:function(a){return f(this.impl.getRangeAt(a))},removeRange:function(a){this.impl.removeRange(d(a))},selectAllChildren:function(a){this.impl.selectAllChildren(e(a))},toString:function(){return this.impl.toString()}},c(window.Selection,b,window.getSelection()),a.wrappers.Selection=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a),this.treeScope_=new p(this,null)}function c(a){var c=document[a];b.prototype[a]=function(){return A(c.apply(this.impl,arguments))}}function d(a,b){D.call(b.impl,z(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof o&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return A(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.wrappers.Selection,n=a.SelectorsInterface,o=a.wrappers.ShadowRoot,p=a.TreeScope,q=a.cloneNode,r=a.defineWrapGetter,s=a.elementFromPoint,t=a.forwardMethodsToWrapper,u=a.matchesNames,v=a.mixin,w=a.registerWrapper,x=a.renderAllPending,y=a.rewrap,z=a.unwrap,A=a.wrap,B=a.wrapEventTargetMethods,C=(a.wrapNodeList,new WeakMap);b.prototype=Object.create(k.prototype),r(b,"documentElement"),r(b,"body"),r(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var D=document.adoptNode,E=document.getSelection;if(v(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return s(this,this,a,b)},importNode:function(a,b){return q(a,b,this.impl)},getSelection:function(){return x(),new m(E.call(z(this)))}}),document.registerElement){var F=document.registerElement;b.prototype.registerElement=function(b,c){function d(a){return a?void(this.impl=a):c.extends?document.createElement(c.extends,b):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){A(this)instanceof d||y(this),b.apply(A(this),arguments)})});var k={prototype:i};c.extends&&(k.extends=c.extends),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i);F.call(z(this),b,k);return d},t([window.HTMLDocument||window.Document],["registerElement"])}t([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"].concat(u)),t([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById","getSelection"]),v(b.prototype,j),v(b.prototype,l),v(b.prototype,n),v(b.prototype,{get implementation(){var a=C.get(this);return a?a:(a=new g(z(this).implementation),C.set(this,a),a)}}),w(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&w(window.HTMLDocument,b),B([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),w(window.DOMImplementation,g),t([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.wrappers.Selection,e=a.mixin,f=a.registerWrapper,g=a.renderAllPending,h=a.unwrap,i=a.unwrapIfNeeded,j=a.wrap,k=window.Window,l=window.getComputedStyle,m=window.getSelection;b.prototype=Object.create(c.prototype),k.prototype.getComputedStyle=function(a,b){return j(this||window).getComputedStyle(i(a),b)},k.prototype.getSelection=function(){return j(this||window).getSelection()},delete window.getComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){k.prototype[a]=function(){var b=j(this||window);return b[a].apply(b,arguments)},delete window[a]}),e(b.prototype,{getComputedStyle:function(a,b){return g(),l.call(h(this),i(a),b)},getSelection:function(){return g(),new d(m.call(h(this)))}}),f(k,b),a.wrappers.Window=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.unwrap,c=window.DataTransfer||window.Clipboard,d=c.prototype.setDragImage;c.prototype.setDragImage=function(a,c,e){d.call(this,b(a),c,e)}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",base:"HTMLBaseElement",body:"HTMLBodyElement",br:"HTMLBRElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",content:"HTMLContentElement",data:"HTMLDataElement",datalist:"HTMLDataListElement",del:"HTMLModElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",dl:"HTMLDListElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",h1:"HTMLHeadingElement",head:"HTMLHeadElement",hr:"HTMLHRElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",img:"HTMLImageElement",input:"HTMLInputElement",keygen:"HTMLKeygenElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",li:"HTMLLIElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",object:"HTMLObjectElement",ol:"HTMLOListElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",shadow:"HTMLShadowElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",table:"HTMLTableElement",tbody:"HTMLTableSectionElement",template:"HTMLTemplateElement",textarea:"HTMLTextAreaElement",thead:"HTMLTableSectionElement",time:"HTMLTimeElement",title:"HTMLTitleElement",tr:"HTMLTableRowElement",track:"HTMLTrackElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]})}(window.ShadowDOMPolyfill),function(){window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded,Object.defineProperty(Element.prototype,"webkitShadowRoot",Object.getOwnPropertyDescriptor(Element.prototype,"shadowRoot"));var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b},Element.prototype.webkitCreateShadowRoot=Element.prototype.createShadowRoot}(),function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(l,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=[];if(b.sheet)try{d=b.sheet.cssRules}catch(e){}else console.warn("sheet not found",b);return b.parentNode.removeChild(b),d}function e(){v.initialized=!0,document.body.appendChild(v);var a=v.contentDocument,b=a.createElement("base");b.href=document.baseURI,a.head.appendChild(b)}function f(a){v.initialized||e(),document.body.appendChild(v),a(v.contentDocument),document.body.removeChild(v)}function g(a,b){if(b){var e;if(a.match("@import")&&x){var g=c(a);f(function(a){a.head.appendChild(g.impl),e=g.sheet.cssRules,b(e)})}else e=d(a),b(e)}}function h(a){a&&j().appendChild(document.createTextNode(a))}function i(a,b){var d=c(a);d.setAttribute(b,""),d.setAttribute(z,""),document.head.appendChild(d)}function j(){return w||(w=document.createElement("style"),w.setAttribute(z,""),w[z]=!0),w}var k={strictStyling:!1,registry:{},shimStyling:function(a,c,d){var e=this.prepareRoot(a,c,d),f=this.isTypeExtension(d),g=this.makeScopeSelector(c,f),h=b(e,!0);h=this.scopeCssText(h,g),a&&(a.shimmedStyle=h),this.addCssToDocument(h,c)},shimStyle:function(a,b){return this.shimCssText(a.textContent,b)},shimCssText:function(a,b){return a=this.insertDirectives(a),this.scopeCssText(a,b)},makeScopeSelector:function(a,b){return a?b?"[is="+a+"]":a:""},isTypeExtension:function(a){return a&&a.indexOf("-")<0},prepareRoot:function(a,b,c){var d=this.registerRoot(a,b,c);return this.replaceTextInStyles(d.rootStyles,this.insertDirectives),this.removeStyles(a,d.rootStyles),this.strictStyling&&this.applyScopeToContent(a,b),d.scopeStyles},removeStyles:function(a,b){for(var c,d=0,e=b.length;e>d&&(c=b[d]);d++)c.parentNode.removeChild(c)},registerRoot:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=this.findStyles(a);d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},findStyles:function(a){if(!a)return[];var b=a.querySelectorAll("style");return Array.prototype.filter.call(b,function(a){return!a.hasAttribute(A)})},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertDirectives:function(a){return a=this.insertPolyfillDirectivesInCssText(a),this.insertPolyfillRulesInCssText(a)},insertPolyfillDirectivesInCssText:function(a){return a=a.replace(m,function(a,b){return b.slice(0,-2)+"{"}),a.replace(n,function(a,b){return b+" {"})},insertPolyfillRulesInCssText:function(a){return a=a.replace(o,function(a,b){return b.slice(0,-1)}),a.replace(p,function(a,b,c,d){var e=a.replace(b,"").replace(c,"");return d+e})},scopeCssText:function(a,b){var c=this.extractUnscopedRulesFromCssText(a);if(a=this.insertPolyfillHostInCssText(a),a=this.convertColonHost(a),a=this.convertColonAncestor(a),a=this.convertCombinators(a),b){var a,d=this;g(a,function(c){a=d.scopeRules(c,b)})}return a=a+"\n"+c,a.trim()},extractUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";for(;b=r.exec(a);)c+=b[0].replace(b[2],"").replace(b[1],b[3])+"\n\n";return c},convertColonHost:function(a){return this.convertColonRule(a,cssColonHostRe,this.colonHostPartReplacer)},convertColonAncestor:function(a){return this.convertColonRule(a,cssColonAncestorRe,this.colonAncestorPartReplacer)},convertColonRule:function(a,b,c){return a.replace(b,function(a,b,d,e){if(b=polyfillHostNoCombinator,d){for(var f,g=d.split(","),h=[],i=0,j=g.length;j>i&&(f=g[i]);i++)f=f.trim(),h.push(c(b,f,e));return h.join(",")}return b+e})},colonAncestorPartReplacer:function(a,b,c){return b.match(s)?this.colonHostPartReplacer(a,b,c):a+b+c+", "+b+" "+a+c},colonHostPartReplacer:function(a,b,c){return a+b.replace(s,"")+c},convertCombinators:function(a){for(var b=0;b<combinatorsRe.length;b++)a=a.replace(combinatorsRe[b]," ");return a},scopeRules:function(a,b){var c="";return a&&Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(c+=this.scopeSelector(a.selectorText,b,this.strictStyling)+" {\n  ",c+=this.propertiesFromRule(a)+"\n}\n\n"):a.type===CSSRule.MEDIA_RULE?(c+="@media "+a.media.mediaText+" {\n",c+=this.scopeRules(a.cssRules,b),c+="\n}\n\n"):a.cssText&&(c+=a.cssText+"\n\n")},this),c},scopeSelector:function(a,b,c){var d=[],e=a.split(",");return e.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b)&&(a=c&&!a.match(polyfillHostNoCombinator)?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b)),d.push(a)},this),d.join(", ")},selectorNeedsScoping:function(a,b){var c=this.makeScopeMatcher(b);return!a.match(c)},makeScopeMatcher:function(a){return a=a.replace(/\[/g,"\\[").replace(/\[/g,"\\]"),new RegExp("^("+a+")"+selectorReSuffix,"m")},applySimpleSelectorScope:function(a,b){return a.match(polyfillHostRe)?(a=a.replace(polyfillHostNoCombinator,b),a.replace(polyfillHostRe,b+" ")):b+" "+a},applyStrictSelectorScope:function(a,b){b=b.replace(/\[is=([^\]]*)\]/g,"$1");var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(polyfillHostRe,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(hostRe,s).replace(colonHostRe,s).replace(colonAncestorRe,t)},propertiesFromRule:function(a){return a.style.content&&!a.style.content.match(/['"]+/)?a.style.cssText.replace(/content:[^;]*;/g,"content: '"+a.style.content+"';"):a.style.cssText},replaceTextInStyles:function(a,b){a&&b&&(a instanceof Array||(a=[a]),Array.prototype.forEach.call(a,function(a){a.textContent=b.call(this,a.textContent)},this))},addCssToDocument:function(a,b){a.match("@import")?i(a,b):h(a)}},l=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,m=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,n=/polyfill-next-selector[^}]*content\:[\s]*'([^']*)'[^}]*}([^{]*?){/gim,o=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,p=/(polyfill-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*}/gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/(polyfill-unscoped-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*}/gim,s="-shadowcsshost",t="-shadowcssancestor",u=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";cssColonHostRe=new RegExp("("+s+u,"gim"),cssColonAncestorRe=new RegExp("("+t+u,"gim"),selectorReSuffix="([>\\s~+[.,{:][\\s\\S]*)?$",hostRe=/@host/gim,colonHostRe=/\:host/gim,colonAncestorRe=/\:ancestor/gim,polyfillHostNoCombinator=s+"-no-combinator",polyfillHostRe=new RegExp(s,"gim"),polyfillAncestorRe=new RegExp(t,"gim"),combinatorsRe=[/\^\^/g,/\^/g,/\/shadow\//g,/\/shadow-deep\//g];var v=document.createElement("iframe");v.style.display="none";var w,x=navigator.userAgent.match("Chrome"),y="shim-shadowdom",z="shim-shadowdom-css",A="no-shim";if(window.ShadowDOMPolyfill){h("style { display: none !important; }\n");var B=wrap(document),C=B.querySelector("head");C.insertBefore(j(),C.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){var b=a.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var c="link[rel=stylesheet]["+y+"]",d="style["+y+"]";HTMLImports.importer.documentPreloadSelectors+=","+c,HTMLImports.importer.importsPreloadSelectors+=","+c,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,c,d].join(",");var e=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(a){if(!a[z]){var c=a.__importElement||a;if(!c.hasAttribute(y))return void e.call(this,a);a.__resource?(c=a.ownerDocument.createElement("style"),c.textContent=b.resolveCssText(a.__resource,a.href)):b.resolveStyle(c),c.textContent=k.shimStyle(c),c.removeAttribute(y,""),c.setAttribute(z,""),c[z]=!0,c.parentNode!==C&&(a.parentNode===C?C.replaceChild(c,a):C.appendChild(c)),c.__importParsed=!0,this.markParsingComplete(a)}};var f=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(a){return"link"===a.localName&&"stylesheet"===a.rel&&a.hasAttribute(y)?a.__resource:f.call(this,a)}}})}a.ShadowCSS=k}(window.Platform)):!function(){window.templateContent=window.templateContent||function(a){return a.content},window.wrap=window.unwrap=function(a){return a},addEventListener("DOMContentLoaded",function(){if(CustomElements.useNative===!1){var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b}}}),window.templateContent=function(a){if(window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(a),!a.content&&!a._content){for(var b=document.createDocumentFragment();a.firstChild;)b.appendChild(a.firstChild);a._content=b}return a.content||a._content}}(),function(a){"use strict";function b(a){return void 0!==m[a]}function c(){h.call(this),this._isInvalid=!0}function d(a){return""==a&&c.call(this),a.toLowerCase()}function e(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,63,96].indexOf(b)?a:encodeURIComponent(a)}function f(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,96].indexOf(b)?a:encodeURIComponent(a)}function g(a,g,h){function i(a){t.push(a)}var j=g||"scheme start",k=0,l="",r=!1,s=!1,t=[];a:for(;(a[k-1]!=o||0==k)&&!this._isInvalid;){var u=a[k];switch(j){case"scheme start":if(!u||!p.test(u)){if(g){i("Invalid scheme.");break a}l="",j="no scheme";continue}l+=u.toLowerCase(),j="scheme";break;case"scheme":if(u&&q.test(u))l+=u.toLowerCase();else{if(":"!=u){if(g){if(o==u)break a;i("Code point not allowed in scheme: "+u);break a}l="",k=0,j="no scheme";continue}if(this._scheme=l,l="",g)break a;b(this._scheme)&&(this._isRelative=!0),j="file"==this._scheme?"relative":this._isRelative&&h&&h._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==u?(query="?",j="query"):"#"==u?(this._fragment="#",j="fragment"):o!=u&&" "!=u&&"\n"!=u&&"\r"!=u&&(this._schemeData+=e(u));break;case"no scheme":if(h&&b(h._scheme)){j="relative";continue}i("Missing scheme."),c.call(this);break;case"relative or authority":if("/"!=u||"/"!=a[k+1]){i("Expected /, got: "+u),j="relative";continue}j="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=h._scheme),o==u){this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query;break a}if("/"==u||"\\"==u)"\\"==u&&i("\\ is an invalid code point."),j="relative slash";else if("?"==u)this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query="?",j="query";else{if("#"!=u){var v=a[k+1],w=a[k+2];("file"!=this._scheme||!p.test(u)||":"!=v&&"|"!=v||o!=w&&"/"!=w&&"\\"!=w&&"?"!=w&&"#"!=w)&&(this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._path.pop()),j="relative path";continue}this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query,this._fragment="#",j="fragment"}break;case"relative slash":if("/"!=u&&"\\"!=u){"file"!=this._scheme&&(this._host=h._host,this._port=h._port),j="relative path";continue}"\\"==u&&i("\\ is an invalid code point."),j="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=u){i("Expected '/', got: "+u),j="authority ignore slashes";continue}j="authority second slash";break;case"authority second slash":if(j="authority ignore slashes","/"!=u){i("Expected '/', got: "+u);continue}break;case"authority ignore slashes":if("/"!=u&&"\\"!=u){j="authority";continue}i("Expected authority, got: "+u);break;case"authority":if("@"==u){r&&(i("@ already seen."),l+="%40"),r=!0;for(var x=0;x<l.length;x++){var y=l[x];if(" "!=y&&"\n"!=y&&"\r"!=y)if(":"!=y||null!==this._password){var z=e(y);null!==this._password?this._password+=z:this._username+=z}else this._password="";else i("Invalid whitespace in authority.")}l=""}else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){k-=l.length,l="",j="host";continue}l+=u}break;case"file host":if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){2!=l.length||!p.test(l[0])||":"!=l[1]&&"|"!=l[1]?0==l.length?j="relative path start":(this._host=d.call(this,l),l="",j="relative path start"):j="relative path";continue}"  "==u||"\n"==u||"\r"==u?i("Invalid whitespace in file host."):l+=u;break;case"host":case"hostname":if(":"!=u||s){if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){if(this._host=d.call(this,l),l="",j="relative path start",g)break a;continue}"  "!=u&&"\n"!=u&&"\r"!=u?("["==u?s=!0:"]"==u&&(s=!1),l+=u):i("Invalid code point in host/hostname: "+u)}else if(this._host=d.call(this,l),l="",j="port","hostname"==g)break a;break;case"port":if(/[0-9]/.test(u))l+=u;else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u||g){if(""!=l){var A=parseInt(l,10);A!=m[this._scheme]&&(this._port=A+""),l=""}if(g)break a;j="relative path start";continue}"  "==u||"\n"==u||"\r"==u?i("Invalid code point in port: "+u):c.call(this)}break;case"relative path start":if("\\"==u&&i("'\\' not allowed in path."),j="relative path","/"!=u&&"\\"!=u)continue;break;case"relative path":if(o!=u&&"/"!=u&&"\\"!=u&&(g||"?"!=u&&"#"!=u))" "!=u&&"\n"!=u&&"\r"!=u&&(l+=e(u));else{"\\"==u&&i("\\ not allowed in relative path.");var B;(B=n[l.toLowerCase()])&&(l=B),".."==l?(this._path.pop(),"/"!=u&&"\\"!=u&&this._path.push("")):"."==l&&"/"!=u&&"\\"!=u?this._path.push(""):"."!=l&&("file"==this._scheme&&0==this._path.length&&2==l.length&&p.test(l[0])&&"|"==l[1]&&(l=l[0]+":"),this._path.push(l)),l="","?"==u?(this._query="?",j="query"):"#"==u&&(this._fragment="#",j="fragment")}break;case"query":g||"#"!=u?o!=u&&" "!=u&&"\n"!=u&&"\r"!=u&&(this._query+=f(u)):(this._fragment="#",j="fragment");break;case"fragment":o!=u&&"  "!=u&&"\n"!=u&&"\r"!=u&&(this._fragment+=u)}k++}}function h(){this._scheme="",this._schemeData="",this._username="",this._password=null,this._host="",this._port="",this._path=[],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}function i(a,b){void 0===b||b instanceof i||(b=new i(String(b))),this._url=a,h.call(this);var c=a.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");g.call(this,c,null,b)}var j=!1;if(!a.forceJURL)try{var k=new URL("b","http://a");j="http://a/b"===k.href}catch(l){}if(!j){var m=Object.create(null);m.ftp=21,m.file=0,m.gopher=70,m.http=80,m.https=443,m.ws=80,m.wss=443;var n=Object.create(null);n["%2e"]=".",n[".%2e"]="..",n["%2e."]="..",n["%2e%2e"]="..";var o=void 0,p=/[a-zA-Z]/,q=/[a-zA-Z0-9\+\-\.]/;i.prototype={get href(){if(this._isInvalid)return this._url;var a="";return(""!=this._username||null!=this._password)&&(a=this._username+(null!=this._password?":"+this._password:"")+"@"),this.protocol+(this._isRelative?"//"+a+this.host:"")+this.pathname+this._query+this._fragment},set href(a){h.call(this),g.call(this,a)},get protocol(){return this._scheme+":"},set protocol(a){this._isInvalid||g.call(this,a+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"host")},get hostname(){return this._host},set hostname(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"hostname")},get port(){return this._port},set port(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(a){!this._isInvalid&&this._isRelative&&(this._path=[],g.call(this,a,"relative path start"))},get search(){return this._isInvalid||!this._query||"?"==this._query?"":this._query},set search(a){!this._isInvalid&&this._isRelative&&(this._query="?","?"==a[0]&&(a=a.slice(1)),g.call(this,a,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"==this._fragment?"":this._fragment
+},set hash(a){this._isInvalid||(this._fragment="#","#"==a[0]&&(a=a.slice(1)),g.call(this,a,"fragment"))}},a.URL=i}}(window),function(a){function b(a){for(var b=a||{},d=1;d<arguments.length;d++){var e=arguments[d];try{for(var f in e)c(f,e,b)}catch(g){}}return b}function c(a,b,c){var e=d(b,a);Object.defineProperty(c,a,e)}function d(a,b){if(a){var c=Object.getOwnPropertyDescriptor(a,b);return c||d(Object.getPrototypeOf(a),b)}}Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();return d.push.apply(d,arguments),b.apply(a,d)}}),a.mixin=b}(window.Platform),function(a){"use strict";function b(a,b,c){var d="string"==typeof a?document.createElement(a):a.cloneNode(!0);if(d.innerHTML=b,c)for(var e in c)d.setAttribute(e,c[e]);return d}var c=DOMTokenList.prototype.add,d=DOMTokenList.prototype.remove;DOMTokenList.prototype.add=function(){for(var a=0;a<arguments.length;a++)c.call(this,arguments[a])},DOMTokenList.prototype.remove=function(){for(var a=0;a<arguments.length;a++)d.call(this,arguments[a])},DOMTokenList.prototype.toggle=function(a,b){1==arguments.length&&(b=!this.contains(a)),b?this.add(a):this.remove(a)},DOMTokenList.prototype.switch=function(a,b){a&&this.remove(a),b&&this.add(b)};var e=function(){return Array.prototype.slice.call(this)},f=window.NamedNodeMap||window.MozNamedAttrMap||{};if(NodeList.prototype.array=e,f.prototype.array=e,HTMLCollection.prototype.array=e,!window.performance){var g=Date.now();window.performance={now:function(){return Date.now()-g}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var a=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return a?function(b){return a(function(){b(performance.now())})}:function(a){return window.setTimeout(a,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(a){clearTimeout(a)}}());var h=[],i=function(){h.push(arguments)};window.Polymer=i,a.deliverDeclarations=function(){return a.deliverDeclarations=function(){throw"Possible attempt to load Polymer twice"},h},window.addEventListener("DOMContentLoaded",function(){window.Polymer===i&&(window.Polymer=function(){console.error('You tried to use polymer without loading it first. To load polymer, <link rel="import" href="components/polymer/polymer.html">')})}),a.createDOM=b}(window.Platform),window.templateContent=window.templateContent||function(a){return a.content},function(a){a=a||(window.Inspector={});var b;window.sinspect=function(a,d){b||(b=window.open("","ShadowDOM Inspector",null,!0),b.document.write(c),b.api={shadowize:shadowize}),f(a||wrap(document.body),d)};var c=["<!DOCTYPE html>","<html>","  <head>","    <title>ShadowDOM Inspector</title>","    <style>","      body {","      }","      pre {",'        font: 9pt "Courier New", monospace;',"        line-height: 1.5em;","      }","      tag {","        color: purple;","      }","      ul {","         margin: 0;","         padding: 0;","         list-style: none;","      }","      li {","         display: inline-block;","         background-color: #f1f1f1;","         padding: 4px 6px;","         border-radius: 4px;","         margin-right: 4px;","      }","    </style>","  </head>","  <body>",'    <ul id="crumbs">',"    </ul>",'    <div id="tree"></div>',"  </body>","</html>"].join("\n"),d=[],e=function(){var a=b.document,c=a.querySelector("#crumbs");c.textContent="";for(var e,g=0;e=d[g];g++){var h=a.createElement("a");h.href="#",h.textContent=e.localName,h.idx=g,h.onclick=function(a){for(var b;d.length>this.idx;)b=d.pop();f(b.shadow||b,b),a.preventDefault()},c.appendChild(a.createElement("li")).appendChild(h)}},f=function(a,c){var f=b.document;k=[];var g=c||a;d.push(g),e(),f.body.querySelector("#tree").innerHTML="<pre>"+j(a,a.childNodes)+"</pre>"},g=Array.prototype.forEach.call.bind(Array.prototype.forEach),h={STYLE:1,SCRIPT:1,"#comment":1,TEMPLATE:1},i=function(a){return h[a.nodeName]},j=function(a,b,c){if(i(a))return"";var d=c||"";if(a.localName||11==a.nodeType){var e=a.localName||"shadow-root",f=d+l(a);"content"==e&&(b=a.getDistributedNodes()),f+="<br/>";var h=d+"&nbsp;&nbsp;";g(b,function(a){f+=j(a,a.childNodes,h)}),f+=d,{br:1}[e]||(f+="<tag>&lt;/"+e+"&gt;</tag>",f+="<br/>")}else{var k=a.textContent.trim();f=k?d+'"'+k+'"<br/>':""}return f},k=[],l=function(a){var b="<tag>&lt;",c=a.localName||"shadow-root";return a.webkitShadowRoot||a.shadowRoot?(b+=' <button idx="'+k.length+'" onclick="api.shadowize.call(this)">'+c+"</button>",k.push(a)):b+=c||"shadow-root",a.attributes&&g(a.attributes,function(a){b+=" "+a.name+(a.value?'="'+a.value+'"':"")}),b+="&gt;</tag>"};shadowize=function(){var a=Number(this.attributes.idx.value),b=k[a];b?f(b.webkitShadowRoot||b.shadowRoot,b):(console.log("bad shadowize node"),console.dir(this))},a.output=j}(window.Inspector),function(){var a=document.createElement("style");a.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; } \n";var b=document.querySelector("head");b.insertBefore(a,b.firstChild)}(Platform),function(a){function b(a,b){return b=b||[],b.map||(b=[b]),a.apply(this,b.map(d))}function c(a,c,d){var e;switch(arguments.length){case 0:return;case 1:e=null;break;case 2:e=c.apply(this);break;default:e=b(d,c)}f[a]=e}function d(a){return f[a]}function e(a,c){HTMLImports.whenImportsReady(function(){b(c,a)})}var f={};a.marshal=d,a.module=c,a.using=e}(window),function(a){function b(a){f.textContent=d++,e.push(a)}function c(){for(;e.length;)e.shift()()}var d=0,e=[],f=document.createTextNode("");new(window.MutationObserver||JsMutationObserver)(c).observe(f,{characterData:!0}),a.endOfMicrotask=b}(Platform),function(a){function b(a,b,d){return a.replace(d,function(a,d,e,f){var g=e.replace(/["']/g,"");return g=c(b,g),d+"'"+g+"'"+f})}function c(a,b){var c=new URL(b,a);return d(c.href)}function d(a){var b=document.baseURI,c=new URL(a,b);return c.host===b.host&&c.port===b.port&&c.protocol===b.protocol?e(b.pathname,c.pathname):a}function e(a,b){for(var c=a.split("/"),d=b.split("/");c.length&&c[0]===d[0];)c.shift(),d.shift();for(var e=0,f=c.length-1;f>e;e++)d.unshift("..");return d.join("/")}var f={resolveDom:function(a,b){b=b||a.ownerDocument.baseURI,this.resolveAttributes(a,b),this.resolveStyles(a,b);var c=a.querySelectorAll("template");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)d.content&&this.resolveDom(d.content,b)},resolveTemplate:function(a){this.resolveDom(a.content,a.ownerDocument.baseURI)},resolveStyles:function(a,b){var c=a.querySelectorAll("style");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveStyle(d,b)},resolveStyle:function(a,b){b=b||a.ownerDocument.baseURI,a.textContent=this.resolveCssText(a.textContent,b)},resolveCssText:function(a,c){return a=b(a,c,g),b(a,c,h)},resolveAttributes:function(a,b){a.hasAttributes&&a.hasAttributes()&&this.resolveElementAttributes(a,b);var c=a&&a.querySelectorAll(j);if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveElementAttributes(d,b)},resolveElementAttributes:function(a,b){b=b||a.ownerDocument.baseURI,i.forEach(function(d){var e=a.attributes[d];if(e&&e.value&&e.value.search(k)<0){var f=c(b,e.value);e.value=f}})}},g=/(url\()([^)]*)(\))/g,h=/(@import[\s]+(?!url\())([^;]*)(;)/g,i=["href","src","action"],j="["+i.join("],[")+"]",k="{{.*}}";a.urlResolver=f}(Platform),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new WeakMap,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return void(c[d-1]=f)}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g,a.MutationObserver||(a.MutationObserver=g)}(this),window.HTMLImports=window.HTMLImports||{flags:{}},function(a){var b=(a.path,a.xhr),c=a.flags,d=function(a,b){this.cache={},this.onload=a,this.oncomplete=b,this.inflight=0,this.pending={}};d.prototype={addNodes:function(a){this.inflight+=a.length;for(var b,c=0,d=a.length;d>c&&(b=a[c]);c++)this.require(b);this.checkDone()},addNode:function(a){this.inflight++,this.require(a),this.checkDone()},require:function(a){var b=a.src||a.href;a.__nodeUrl=b,this.dedupe(b,a)||this.fetch(b,a)},dedupe:function(a,b){if(this.pending[a])return this.pending[a].push(b),!0;return this.cache[a]?(this.onload(a,b,this.cache[a]),this.tail(),!0):(this.pending[a]=[b],!1)},fetch:function(a,d){if(c.load&&console.log("fetch",a,d),a.match(/^data:/)){var e=a.split(","),f=e[0],g=e[1];g=f.indexOf(";base64")>-1?atob(g):decodeURIComponent(g),setTimeout(function(){this.receive(a,d,null,g)}.bind(this),0)}else{var h=function(b,c){this.receive(a,d,b,c)}.bind(this);b.load(a,h)}},receive:function(a,b,c,d){this.cache[a]=d;for(var e,f=this.pending[a],g=0,h=f.length;h>g&&(e=f[g]);g++)this.onload(a,e,d),this.tail();this.pending[a]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}},b=b||{async:!0,ok:function(a){return a.status>=200&&a.status<300||304===a.status||0===a.status},load:function(c,d,e){var f=new XMLHttpRequest;return(a.flags.debug||a.flags.bust)&&(c+="?"+Math.random()),f.open("GET",c,b.async),f.addEventListener("readystatechange",function(){4===f.readyState&&d.call(e,!b.ok(f)&&f,f.response||f.responseText,c)}),f.send(),f},loadDocument:function(a,b,c){this.load(a,b,c).responseType="document"}},a.xhr=b,a.Loader=d}(window.HTMLImports),function(a){function b(a){return"link"===a.localName&&a.rel===g}function c(a){var b,c=d(a);try{b=btoa(c)}catch(e){b=btoa(unescape(encodeURIComponent(c))),console.warn("Script contained non-latin characters that were forced to latin. Some characters may be wrong.",a)}return"data:text/javascript;base64,"+b}function d(a){return a.textContent+e(a)}function e(a){var b=a.__nodeUrl;if(!b){b=a.ownerDocument.baseURI;var c="["+Math.floor(1e3*(Math.random()+1))+"]",d=a.textContent.match(/Polymer\(['"]([^'"]*)/);c=d&&d[1]||c,b+="/"+c+".js"}return"\n//# sourceURL="+b+"\n"}function f(a){var b=a.ownerDocument.createElement("style");return b.textContent=a.textContent,n.resolveUrlsInStyle(b),b}var g="import",h=a.flags,i=/Trident/.test(navigator.userAgent),j=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document,k={documentSelectors:"link[rel="+g+"]",importsSelectors:["link[rel="+g+"]","link[rel=stylesheet]","style","script:not([type])",'script[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScript",style:"parseStyle"},parseNext:function(){var a=this.nextToParse();a&&this.parse(a)},parse:function(a){if(this.isParsed(a))return void(h.parse&&console.log("[%s] is already parsed",a.localName));var b=this[this.map[a.localName]];b&&(this.markParsing(a),b.call(this,a))},markParsing:function(a){h.parse&&console.log("parsing",a),this.parsingElement=a},markParsingComplete:function(a){a.__importParsed=!0,a.__importElement&&(a.__importElement.__importParsed=!0),this.parsingElement=null,h.parse&&console.log("completed",a),this.parseNext()},parseImport:function(a){if(a.import.__importParsed=!0,HTMLImports.__importsParsingHook&&HTMLImports.__importsParsingHook(a),a.dispatchEvent(a.__resource?new CustomEvent("load",{bubbles:!1}):new CustomEvent("error",{bubbles:!1})),a.__pending)for(var b;a.__pending.length;)b=a.__pending.shift(),b&&b({target:a});this.markParsingComplete(a)},parseLink:function(a){b(a)?this.parseImport(a):(a.href=a.href,this.parseGeneric(a))},parseStyle:function(a){var b=a;a=f(a),a.__importElement=b,this.parseGeneric(a)},parseGeneric:function(a){this.trackElement(a),document.head.appendChild(a)},trackElement:function(a,b){var c=this,d=function(d){b&&b(d),c.markParsingComplete(a)};if(a.addEventListener("load",d),a.addEventListener("error",d),i&&"style"===a.localName){var e=!1;if(-1==a.textContent.indexOf("@import"))e=!0;else if(a.sheet){e=!0;for(var f,g=a.sheet.cssRules,h=g?g.length:0,j=0;h>j&&(f=g[j]);j++)f.type===CSSRule.IMPORT_RULE&&(e=e&&Boolean(f.styleSheet))}e&&a.dispatchEvent(new CustomEvent("load",{bubbles:!1}))}},parseScript:function(b){var d=document.createElement("script");d.__importElement=b,d.src=b.src?b.src:c(b),a.currentScript=b,this.trackElement(d,function(){d.parentNode.removeChild(d),a.currentScript=null}),document.head.appendChild(d)},nextToParse:function(){return!this.parsingElement&&this.nextToParseInDoc(j)},nextToParseInDoc:function(a,c){for(var d,e=a.querySelectorAll(this.parseSelectorsForNode(a)),f=0,g=e.length;g>f&&(d=e[f]);f++)if(!this.isParsed(d))return this.hasResource(d)?b(d)?this.nextToParseInDoc(d.import,d):d:void 0;return c},parseSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===j?this.documentSelectors:this.importsSelectors},isParsed:function(a){return a.__importParsed},hasResource:function(a){return b(a)&&!a.import?!1:!0}},l=/(url\()([^)]*)(\))/g,m=/(@import[\s]+(?!url\())([^;]*)(;)/g,n={resolveUrlsInStyle:function(a){var b=a.ownerDocument,c=b.createElement("a");return a.textContent=this.resolveUrlsInCssText(a.textContent,c),a},resolveUrlsInCssText:function(a,b){var c=this.replaceUrls(a,b,l);return c=this.replaceUrls(c,b,m)},replaceUrls:function(a,b,c){return a.replace(c,function(a,c,d,e){var f=d.replace(/["']/g,"");return b.href=f,f=b.href,c+"'"+f+"'"+e})}};a.parser=k,a.path=n,a.isIE=i}(HTMLImports),function(a){function b(a){return c(a,m)}function c(a,b){return"link"===a.localName&&a.getAttribute("rel")===b}function d(a,b){var c=a;c instanceof Document||(c=document.implementation.createHTMLDocument(m)),c._URL=b;var d=c.createElement("base");d.setAttribute("href",b),c.baseURI||(c.baseURI=b);var e=c.createElement("meta");return e.setAttribute("charset","utf-8"),c.head.appendChild(e),c.head.appendChild(d),a instanceof Document||(c.body.innerHTML=a),window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(c),c}function e(a,b){b=b||n,g(function(){h(a,b)},b)}function f(a){return"complete"===a.readyState||a.readyState===u}function g(a,b){if(f(b))a&&a();else{var c=function(){("complete"===b.readyState||b.readyState===u)&&(b.removeEventListener(v,c),g(a,b))};b.addEventListener(v,c)}}function h(a,b){function c(){f==g&&requestAnimationFrame(a)}function d(){f++,c()}var e=b.querySelectorAll("link[rel=import]"),f=0,g=e.length;if(g)for(var h,j=0;g>j&&(h=e[j]);j++)i(h)?d.call(h):(h.addEventListener("load",d),h.addEventListener("error",d));else c()}function i(a){return k?a.import&&"loading"!==a.import.readyState:a.__importParsed}var j="import"in document.createElement("link"),k=j,l=a.flags,m="import",n=window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(document):document;if(k)var o={};else var p=(a.xhr,a.Loader),q=a.parser,o={documents:{},documentPreloadSelectors:"link[rel="+m+"]",importsPreloadSelectors:["link[rel="+m+"]"].join(","),loadNode:function(a){r.addNode(a)},loadSubtree:function(a){var b=this.marshalNodes(a);r.addNodes(b)},marshalNodes:function(a){return a.querySelectorAll(this.loadSelectorsForNode(a))},loadSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===n?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(a,c,e){if(l.load&&console.log("loaded",a,c),c.__resource=e,b(c)){var f=this.documents[a];f||(f=d(e,a),f.__importLink=c,this.bootDocument(f),this.documents[a]=f),c.import=f}q.parseNext()},bootDocument:function(a){this.loadSubtree(a),this.observe(a),q.parseNext()},loadedAll:function(){q.parseNext()}},r=new p(o.loaded.bind(o),o.loadedAll.bind(o));var s={get:function(){return HTMLImports.currentScript||document.currentScript},configurable:!0};if(Object.defineProperty(document,"_currentScript",s),Object.defineProperty(n,"_currentScript",s),!document.baseURI){var t={get:function(){return window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",t),Object.defineProperty(n,"baseURI",t)}var u=HTMLImports.isIE?"complete":"interactive",v="readystatechange";a.hasNative=j,a.useNative=k,a.importer=o,a.whenImportsReady=e,a.IMPORT_LINK_TYPE=m,a.isImportLoaded=i,a.importLoader=r}(window.HTMLImports),function(a){function b(a){for(var b,d=0,e=a.length;e>d&&(b=a[d]);d++)"childList"===b.type&&b.addedNodes.length&&c(b.addedNodes)}function c(a){for(var b,e=0,g=a.length;g>e&&(b=a[e]);e++)d(b)&&f.loadNode(b),b.children&&b.children.length&&c(b.children)}function d(a){return 1===a.nodeType&&g.call(a,f.loadSelectorsForNode(a))}function e(a){h.observe(a,{childList:!0,subtree:!0})}var f=(a.IMPORT_LINK_TYPE,a.importer),g=HTMLElement.prototype.matches||HTMLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,h=new MutationObserver(b);a.observe=e,f.observe=e}(HTMLImports),function(){function a(){HTMLImports.importer.bootDocument(b)}"function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a,b){var c=document.createEvent("HTMLEvents");return c.initEvent(a,b.bubbles===!1?!1:!0,b.cancelable===!1?!1:!0,b.detail),c});var b=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document;HTMLImports.whenImportsReady(function(){HTMLImports.ready=!0,HTMLImports.readyTime=(new Date).getTime(),b.dispatchEvent(new CustomEvent("HTMLImportsLoaded",{bubbles:!0}))}),HTMLImports.useNative||("complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?a():document.addEventListener("DOMContentLoaded",a))}(),window.CustomElements=window.CustomElements||{flags:{}},function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:void c(a,d)}),c(a,d)}function e(a){return h(a)?(i(a),!0):void l(a)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return A.dom&&console.group("upgrade:",b.localName),a.upgrade(b),A.dom&&console.groupEnd(),!0}}function i(a){l(a),r(a)&&d(a,function(a){l(a)})}function j(a){if(E.push(a),!D){D=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){D=!1;for(var a,b=E,c=0,d=b.length;d>c&&(a=b[c]);c++)a();E=[]}function l(a){C?j(function(){m(a)}):m(a)}function m(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("inserted:",a.localName),r(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?A.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.attachedCallback&&(A.dom&&console.log("inserted:",a.localName),a.attachedCallback())),A.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){C?j(function(){p(a)}):p(a)}function p(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("removed:",a.localName),r(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?A.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.detachedCallback&&a.detachedCallback()),A.dom&&console.groupEnd())}function q(a){return window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(a):a}function r(a){for(var b=a,c=q(document);b;){if(b==c)return!0;b=b.parentNode||b.host}}function s(a){if(a.shadowRoot&&!a.shadowRoot.__watched){A.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)t(b),b=b.olderShadowRoot}}function t(a){a.__watched||(w(a),a.__watched=!0)}function u(a){if(A.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(G(a.addedNodes,function(a){a.localName&&g(a)}),G(a.removedNodes,function(a){a.localName&&n(a)}))}),A.dom&&console.groupEnd()}function v(){u(F.takeRecords()),k()}function w(a){F.observe(a,{childList:!0,subtree:!0})}function x(a){w(a)}function y(a){A.dom&&console.group("upgradeDocument: ",a.baseURI.split("/").pop()),g(a),A.dom&&console.groupEnd()}function z(a){a=q(a);for(var b,c=a.querySelectorAll("link[rel="+B+"]"),d=0,e=c.length;e>d&&(b=c[d]);d++)b.import&&b.import.__parsed&&z(b.import);y(a)}var A=window.logFlags||{},B=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",C=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=C;var D=!1,E=[],F=new MutationObserver(u),G=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.IMPORT_LINK_TYPE=B,a.watchShadow=s,a.upgradeDocumentTree=z,a.upgradeAll=g,a.upgradeSubtree=f,a.insertedNode=i,a.observeDocument=x,a.upgradeDocument=y,a.takeRecords=v}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.registerElement: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.__name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.__name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeDocumentTree(document),g.ctor}function c(a){var b=m(a);return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.__name,c&&(a.is=a.__name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(z(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,j(b),a.insertedNode(b),a.upgradeSubtree(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){if(!a.setAttribute._polyfilled){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?x[a.toLowerCase()]:void 0}function n(a,b){x[a]=b}function o(a){return function(){return f(a)}}function p(a,b,c){return a===y?q(b,c):A(a,b)}function q(a,b){var c=m(b||a);if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=q(a);return d.setAttribute("is",b),d}var d=z(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function r(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=m(b||a.localName);if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function s(b){var c=B.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var t=a.flags,u=Boolean(document.registerElement),v=!t.register&&u&&!window.ShadowDOMPolyfill;if(v){var w=function(){};a.registry={},a.upgradeElement=w,a.watchShadow=w,a.upgrade=w,a.upgradeAll=w,a.upgradeSubtree=w,a.observeDocument=w,a.upgradeDocument=w,a.upgradeDocumentTree=w,a.takeRecords=w}else{var x={},y="http://www.w3.org/1999/xhtml",z=document.createElement.bind(document),A=document.createElementNS.bind(document),B=Node.prototype.cloneNode;document.registerElement=b,document.createElement=q,document.createElementNS=p,Node.prototype.cloneNode=s,a.registry=x,a.upgrade=r}var C;C=Object.__proto__||v?function(a,b){return a instanceof b}:function(a,b){for(var c=a;c;){if(c===b.prototype)return!0;c=c.__proto__}return!1},a.instanceof=C,document.register=document.registerElement,a.hasNative=u,a.useNative=v}(window.CustomElements),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===c}var c=a.IMPORT_LINK_TYPE,d={selectors:["link[rel="+c+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(d.selectors);e(b,function(a){d[d.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(a){b(a)&&this.parseImport(a)},parseImport:function(a){a.import&&d.parse(a.import)}},e=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.parser=d,a.IMPORT_LINK_TYPE=c}(window.CustomElements),function(a){function b(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0})),window.HTMLImports&&(HTMLImports.__importsParsingHook=function(a){CustomElements.parser.parse(a.import)})})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||a.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports&&!HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){if(window.ShadowDOMPolyfill){var a=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],b={};a.forEach(function(a){b[a]=CustomElements[a]}),a.forEach(function(a){CustomElements[a]=function(c){return b[a](wrap(c))}})}}(),function(a){function b(a){this.regex=a}var c=a.endOfMicrotask;b.prototype={extractUrls:function(a,b){for(var c,d,e=[];c=this.regex.exec(a);)d=new URL(c[1],b),e.push({matched:c[0],url:d.href});return e},process:function(a,b,c){var d=this.extractUrls(a,b);this.fetch(d,{},c)},fetch:function(a,b,d){var e=a.length;if(!e)return d(b);for(var f,g,h,i=function(){0===--e&&d(b)},j=function(a,c){var d=c.match,e=d.url;if(a)return b[e]="",i();var f=c.response||c.responseText;b[e]=f,this.fetch(this.extractUrls(f,e),b,i)},k=0;e>k;k++)f=a[k],h=f.url,b[h]?c(i):(g=this.xhr(h,j,this),g.match=f,b[h]=g)},xhr:function(a,b,c){var d=new XMLHttpRequest;return d.open("GET",a,!0),d.send(),d.onload=function(){b.call(c,null,d)},d.onerror=function(){b.call(c,null,d)},d}},a.Loader=b}(window.Platform),function(a){function b(){this.loader=new d(this.regex)}var c=a.urlResolver,d=a.Loader;b.prototype={regex:/@import\s+(?:url)?["'\(]*([^'"\)]*)['"\)]*;/g,resolve:function(a,b,c){var d=function(d){c(this.flatten(a,b,d))}.bind(this);this.loader.process(a,b,d)},resolveNode:function(a,b){var c=a.textContent,d=a.ownerDocument.baseURI,e=function(c){a.textContent=c,b(a)
+};this.resolve(c,d,e)},flatten:function(a,b,d){for(var e,f,g,h=this.loader.extractUrls(a,b),i=0;i<h.length;i++)e=h[i],f=e.url,g=c.resolveCssText(d[f],f),g=this.flatten(g,f,d),a=a.replace(e.matched,g);return a},loadStyles:function(a,b){function c(){e++,e===f&&b&&b()}for(var d,e=0,f=a.length,g=0;f>g&&(d=a[g]);g++)this.resolveNode(d,c)}};var e=new b;a.styleResolver=e}(window.Platform),function(a){a=a||{},a.external=a.external||{};var b={shadow:function(a){return a?a.shadowRoot||a.webkitShadowRoot:void 0},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);return this.canTarget(b)?b:void 0},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d}e=this.olderShadow(e)}return f}},owner:function(a){for(var b=a;b.parentNode;)b=b.parentNode;return b.nodeType!=Node.DOCUMENT_NODE&&b.nodeType!=Node.DOCUMENT_FRAGMENT_NODE&&(b=document),b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}};a.targetFinding=b,a.findTarget=b.findTarget.bind(b),window.PointerEventsPolyfill=a}(window.PointerEventsPolyfill),function(){function a(a){return"body /shadow-deep/ "+b(a)}function b(a){return'[touch-action="'+a+'"]'}function c(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; touch-action-delay: none; }"}var d=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],e="",f=(document.head,window.PointerEvent||window.MSPointerEvent),g=!window.ShadowDOMPolyfill&&document.head.createShadowRoot;if(f){d.forEach(function(d){String(d)===d?(e+=b(d)+c(d)+"\n",g&&(e+=a(d)+c(d)+"\n")):(e+=d.selectors.map(b)+c(d.rule)+"\n",g&&(e+=d.selectors.map(a)+c(d.rule)+"\n"))});var h=document.createElement("style");h.textContent=e,document.head.appendChild(h)}}(),function(a){function b(a,e){e=e||{};var f=e.buttons;if(!d&&!f&&"touch"!==a)switch(e.which){case 1:f=1;break;case 2:f=4;break;case 3:f=2;break;default:f=0}var i;if(c)i=new MouseEvent(a,e);else{i=document.createEvent("MouseEvent");for(var j,k={},l=0;l<g.length;l++)j=g[l],k[j]=e[j]||h[l];i.initMouseEvent(a,k.bubbles,k.cancelable,k.view,k.detail,k.screenX,k.screenY,k.clientX,k.clientY,k.ctrlKey,k.altKey,k.shiftKey,k.metaKey,k.button,k.relatedTarget)}i.__proto__=b.prototype,d||Object.defineProperty(i,"buttons",{get:function(){return f},enumerable:!0});var m=0;return m=e.pressure?e.pressure:f?.5:0,Object.defineProperties(i,{pointerId:{value:e.pointerId||0,enumerable:!0},width:{value:e.width||0,enumerable:!0},height:{value:e.height||0,enumerable:!0},pressure:{value:m,enumerable:!0},tiltX:{value:e.tiltX||0,enumerable:!0},tiltY:{value:e.tiltY||0,enumerable:!0},pointerType:{value:e.pointerType||"",enumerable:!0},hwTimestamp:{value:e.hwTimestamp||0,enumerable:!0},isPrimary:{value:e.isPrimary||!1,enumerable:!0}}),i}var c=!1,d=!1;try{var e=new MouseEvent("click",{buttons:1});c=!0,d=1===e.buttons,e=null}catch(f){}var g=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget"],h=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null];b.prototype=Object.create(MouseEvent.prototype),a.PointerEvent||(a.PointerEvent=b)}(window),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerEventsPolyfill),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0],d="undefined"!=typeof SVGElementInstance,e={targets:new WeakMap,handledEvents:new WeakMap,pointermap:new a.PointerMap,eventMap:{},eventSources:{},eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.unregister.call(b,a)},contains:a.external.contains||function(a,b){return a.contains(b)},down:function(a){a.bubbles=!0,this.fireEvent("pointerdown",a)},move:function(a){a.bubbles=!0,this.fireEvent("pointermove",a)},up:function(a){a.bubbles=!0,this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){a.bubbles=!0,this.fireEvent("pointercancel",a)},leaveOut:function(a){this.out(a),this.contains(a.target,a.relatedTarget)||this.leave(a)},enterOver:function(a){this.over(a),this.contains(a.target,a.relatedTarget)||this.enter(a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),this.handledEvents.set(a,!0)}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:a.external.addEvent||function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:a.external.removeEvent||function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(a,b){this.captureInfo&&(b.relatedTarget=null);var c=new PointerEvent(a,b);return b.preventDefault&&(c.preventDefault=b.preventDefault),this.targets.set(c,this.targets.get(b)||b.target),c},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var e,f={},g=0;g<b.length;g++)e=b[g],f[e]=a[e]||c[g],!d||"target"!==e&&"relatedTarget"!==e||f[e]instanceof SVGElementInstance&&(f[e]=f[e].correspondingUseElement);return a.preventDefault&&(f.preventDefault=function(){a.preventDefault()}),f},getTarget:function(a){return this.captureInfo&&this.captureInfo.id===a.pointerId?this.captureInfo.target:this.targets.get(a)},setCapture:function(a,b){this.captureInfo&&this.releaseCapture(this.captureInfo.id),this.captureInfo={id:a,target:b};var c=new PointerEvent("gotpointercapture",{bubbles:!0});this.implicitRelease=this.releaseCapture.bind(this,a),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease),this.targets.set(c,b),this.asyncDispatchEvent(c)},releaseCapture:function(a){if(this.captureInfo&&this.captureInfo.id===a){var b=new PointerEvent("lostpointercapture",{bubbles:!0}),c=this.captureInfo.target;this.captureInfo=null,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease),this.targets.set(b,c),this.asyncDispatchEvent(b)}},dispatchEvent:a.external.dispatchEvent||function(a){var b=this.getTarget(a);return b?b.dispatchEvent(a):void 0},asyncDispatchEvent:function(a){requestAnimationFrame(this.dispatchEvent.bind(this,a))}};e.boundHandler=e.eventHandler.bind(e),a.dispatcher=e,a.register=e.register.bind(e),a.unregister=e.unregister.bind(e)}(window.PointerEventsPolyfill),function(a){function b(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),g&&(this.observer=new g(this.mutationWatcher.bind(this)))}var c=Array.prototype.forEach.call.bind(Array.prototype.forEach),d=Array.prototype.map.call.bind(Array.prototype.map),e=Array.prototype.slice.call.bind(Array.prototype.slice),f=Array.prototype.filter.call.bind(Array.prototype.filter),g=window.MutationObserver||window.WebKitMutationObserver,h="[touch-action]",i={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};b.prototype={watchSubtree:function(b){a.targetFinding.canTarget(b)&&this.observer.observe(b,i)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){c(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(h):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(e(b))},installOnLoad:function(){document.addEventListener("readystatechange",function(){"complete"===document.readyState&&this.installNewSubtree(document)}.bind(this))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){var b=d(a,this.findElements,this);return b.push(f(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}},g||(b.prototype.watchSubtree=function(){console.warn("PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected")}),a.Installer=b}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=25,e={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},lastTouches:[],isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,e=a.clientX,f=a.clientY,g=0,h=c.length;h>g&&(b=c[g]);g++){var i=Math.abs(e-b.x),j=Math.abs(f-b.y);if(d>=i&&d>=j)return!0}},prepareEvent:function(a){var c=b.cloneEvent(a),d=c.preventDefault;return c.preventDefault=function(){a.preventDefault(),d()},c.pointerId=this.POINTER_ID,c.isPrimary=!0,c.pointerType=this.POINTER_TYPE,c},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.has(this.POINTER_ID);d&&this.cancel(a);var e=this.prepareEvent(a);c.set(this.POINTER_ID,a),b.down(e)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.move(c)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.get(this.POINTER_ID);if(d&&d.button===a.button){var e=this.prepareEvent(a);b.up(e),this.cleanupMouse()}}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.enterOver(c)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.leaveOut(c)}},cancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanupMouse()},cleanupMouse:function(){c["delete"](this.POINTER_ID)}};a.mouseEvents=e}(window.PointerEventsPolyfill),function(a){var b,c=a.dispatcher,d=a.findTarget,e=a.targetFinding.allShadows.bind(a.targetFinding),f=c.pointermap,g=Array.prototype.map.call.bind(Array.prototype.map),h=2500,i=200,j="touch-action",k=!1,l={scrollType:new WeakMap,events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){k?c.listen(a,this.events):b.enableOnSubtree(a)},unregister:function(a){k&&c.unlisten(a,this.events)},elementAdded:function(a){var b=a.getAttribute(j),d=this.touchActionToScrollType(b);d&&(this.scrollType.set(a,d),c.listen(a,this.events),e(a).forEach(function(a){this.scrollType.set(a,d),c.listen(a,this.events)},this))},elementRemoved:function(a){this.scrollType["delete"](a),c.unlisten(a,this.events),e(a).forEach(function(a){this.scrollType["delete"](a),c.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(j),d=this.touchActionToScrollType(c),f=this.touchActionToScrollType(b);d&&f?(this.scrollType.set(a,d),e(a).forEach(function(a){this.scrollType.set(a,d)},this)):f?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){(0===f.pointers()||1===f.pointers()&&f.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,i)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},typeToButtons:function(a){var b=0;return("touchstart"===a||"touchmove"===a)&&(b=1),b},touchToPointer:function(a){var b=c.cloneEvent(a);return b.pointerId=a.identifier+2,b.target=d(b),b.bubbles=!0,b.cancelable=!0,b.detail=this.clickCount,b.button=0,b.buttons=this.typeToButtons(this.currentTouchEvent),b.width=a.webkitRadiusX||a.radiusX||0,b.height=a.webkitRadiusY||a.radiusY||0,b.pressure=a.webkitForce||a.force||.5,b.isPrimary=this.isPrimaryTouch(a),b.pointerType=this.POINTER_TYPE,b},processTouches:function(a,b){var c=a.changedTouches;this.currentTouchEvent=a.type;var d=g(c,this.touchToPointer,this);d.forEach(function(b){b.preventDefault=function(){this.scrolling=!1,this.firstXY=null,a.preventDefault()}},this),d.forEach(b,this)},shouldScroll:function(a){if(this.firstXY){var b,c=this.scrollType.get(a.currentTarget);if("none"===c)b=!1;else if("XY"===c)b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)if(c.identifier===b)return!0},vacuumTouches:function(a){var b=a.touches;if(f.pointers()>=b.length){var c=[];f.forEach(function(a,d){if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(this.touchToPointer(e))}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){f.set(a.pointerId,{target:a.target,out:a,outTarget:a.target});c.over(a),c.enter(a),c.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,d=f.get(b.pointerId);if(d){var e=d.out,g=d.outTarget;c.move(b),e&&g!==b.target&&(e.relatedTarget=b.target,b.relatedTarget=g,e.target=g,b.target?(c.leaveOut(e),c.enterOver(b)):(b.target=g,b.relatedTarget=null,this.cancelOut(b))),d.out=b,d.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(c.up(a),c.out(a),c.leave(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){c.cancel(a),c.out(a),c.leave(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){f["delete"](a.pointerId),this.removePrimaryPointer(a)},dedupSynthMouse:function(b){var c=a.mouseEvents.lastTouches,d=b.changedTouches[0];if(this.isPrimaryTouch(d)){var e={x:d.clientX,y:d.clientY};c.push(e);var f=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,c,e);setTimeout(f,h)}}};k||(b=new a.Installer(l.elementAdded,l.elementRemoved,l.elementChanged,l)),a.touchEvents=l}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,e={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var c=a;return d&&(c=b.cloneEvent(a),c.pointerType=this.POINTER_TYPES[a.pointerType]),c},cleanup:function(a){c["delete"](a)},MSPointerDown:function(a){c.set(a.pointerId,a);var d=this.prepareEvent(a);b.down(d)},MSPointerMove:function(a){var c=this.prepareEvent(a);b.move(c)},MSPointerUp:function(a){var c=this.prepareEvent(a);b.up(c),this.cleanup(a.pointerId)},MSPointerOut:function(a){var c=this.prepareEvent(a);b.leaveOut(c)},MSPointerOver:function(a){var c=this.prepareEvent(a);b.enterOver(c)},MSPointerCancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var c=b.makeEvent("lostpointercapture",a);b.dispatchEvent(c)},MSGotPointerCapture:function(a){var c=b.makeEvent("gotpointercapture",a);b.dispatchEvent(c)}};a.msEvents=e}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher;if(void 0===window.navigator.pointerEnabled){if(Object.defineProperty(window.navigator,"pointerEnabled",{value:!0,enumerable:!0}),window.navigator.msPointerEnabled){var c=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:c,enumerable:!0}),b.registerSource("ms",a.msEvents)}else b.registerSource("mouse",a.mouseEvents),void 0!==window.ontouchstart&&b.registerSource("touch",a.touchEvents);b.register(document)}}(window.PointerEventsPolyfill),function(a){function b(a){if(!e.pointermap.has(a))throw new Error("InvalidPointerId")}var c,d,e=a.dispatcher,f=window.navigator;f.msPointerEnabled?(c=function(a){b(a),this.msSetPointerCapture(a)},d=function(a){b(a),this.msReleasePointerCapture(a)}):(c=function(a){b(a),e.setCapture(a,this)},d=function(a){b(a),e.releaseCapture(a,this)}),window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:c},releasePointerCapture:{value:d}})}(window.PointerEventsPolyfill),PointerGestureEvent.prototype.preventTap=function(){this.tapPrevented=!0},function(a){a=a||{},a.utils={LCA:{find:function(a,b){if(a===b)return a;if(a.contains){if(a.contains(b))return a;if(b.contains(a))return b}var c=this.depth(a),d=this.depth(b),e=c-d;for(e>0?a=this.walk(a,e):b=this.walk(b,-e);a&&b&&a!==b;)a=this.walk(a,1),b=this.walk(b,1);return a},walk:function(a,b){for(var c=0;b>c;c++)a=a.parentNode;return a},depth:function(a){for(var b=0;a;)b++,a=a.parentNode;return b}}},a.findLCA=function(b,c){return a.utils.LCA.find(b,c)},window.PointerGestures=a}(window.PointerGestures),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerGestures),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","screenX","screenY","pageX","pageY","tapPrevented"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],d={handledEvents:new WeakMap,targets:new WeakMap,handlers:{},recognizers:{},events:{},registerRecognizer:function(a,b){var c=b;this.recognizers[a]=c,c.events.forEach(function(a){if(c[a]){this.events[a]=!0;var b=c[a].bind(c);this.addHandler(a,b)}},this)},addHandler:function(a,b){var c=a;this.handlers[c]||(this.handlers[c]=[]),this.handlers[c].push(b)},registerTarget:function(a){this.listen(Object.keys(this.events),a)},unregisterTarget:function(a){this.unlisten(Object.keys(this.events),a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.handlers[b];c&&this.makeQueue(c,a),this.handledEvents.set(a,!0)}},makeQueue:function(a,b){var c=this.cloneEvent(b);requestAnimationFrame(this.runQueue.bind(this,a,c))},runQueue:function(a,b){this.currentPointerId=b.pointerId;for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)c(b);this.currentPointerId=0},listen:function(a,b){a.forEach(function(a){this.addEvent(a,this.boundHandler,!1,b)},this)},unlisten:function(a){a.forEach(function(a){this.removeEvent(a,this.boundHandler,!1,inTarget)},this)},addEvent:function(a,b,c,d){d.addEventListener(a,b,c)},removeEvent:function(a,b,c,d){d.removeEventListener(a,b,c)},makeEvent:function(a,b){return new PointerGestureEvent(a,b)},cloneEvent:function(a){for(var d,e={},f=0;f<b.length;f++)d=b[f],e[d]=a[d]||c[f];return e},dispatchEvent:function(a,b){var c=b||this.targets.get(a);c&&(c.dispatchEvent(a),a.tapPrevented&&this.preventTap(this.currentPointerId))},asyncDispatchEvent:function(a,b){requestAnimationFrame(this.dispatchEvent.bind(this,a,b))},preventTap:function(a){var b=this.recognizers.tap;b&&b.preventTap(a)}};d.boundHandler=d.eventHandler.bind(d),d.registerQueue=[],d.immediateRegister=!1,a.dispatcher=d,a.register=function(b){if(d.immediateRegister){var c=window.PointerEventsPolyfill;c&&c.register(b),a.dispatcher.registerTarget(b)}else d.registerQueue.push(b)},a.register(document)}(window.PointerGestures),function(a){var b=a.dispatcher,c={HOLD_DELAY:200,WIGGLE_THRESHOLD:16,events:["pointerdown","pointermove","pointerup","pointercancel"],heldPointer:null,holdJob:null,pulse:function(){var a=Date.now()-this.heldPointer.timeStamp,b=this.held?"holdpulse":"hold";this.fireHold(b,a),this.held=!0},cancel:function(){clearInterval(this.holdJob),this.held&&this.fireHold("release"),this.held=!1,this.heldPointer=null,this.target=null,this.holdJob=null},pointerdown:function(a){a.isPrimary&&!this.heldPointer&&(this.heldPointer=a,this.target=a.target,this.holdJob=setInterval(this.pulse.bind(this),this.HOLD_DELAY))},pointerup:function(a){this.heldPointer&&this.heldPointer.pointerId===a.pointerId&&this.cancel()},pointercancel:function(){this.cancel()},pointermove:function(a){if(this.heldPointer&&this.heldPointer.pointerId===a.pointerId){var b=a.clientX-this.heldPointer.clientX,c=a.clientY-this.heldPointer.clientY;b*b+c*c>this.WIGGLE_THRESHOLD&&this.cancel()}},fireHold:function(a,c){var d={pointerType:this.heldPointer.pointerType,clientX:this.heldPointer.clientX,clientY:this.heldPointer.clientY};c&&(d.holdTime=c);var e=b.makeEvent(a,d);b.dispatchEvent(e,this.target),e.tapPrevented&&b.preventTap(this.heldPointer.pointerId)}};b.registerRecognizer("hold",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel"],WIGGLE_THRESHOLD:4,clampDir:function(a){return a>0?1:-1},calcPositionDelta:function(a,b){var c=0,d=0;return a&&b&&(c=b.pageX-a.pageX,d=b.pageY-a.pageY),{x:c,y:d}},fireTrack:function(a,c,d){var e=d,f=this.calcPositionDelta(e.downEvent,c),g=this.calcPositionDelta(e.lastMoveEvent,c);g.x&&(e.xDirection=this.clampDir(g.x)),g.y&&(e.yDirection=this.clampDir(g.y));var h={dx:f.x,dy:f.y,ddx:g.x,ddy:g.y,clientX:c.clientX,clientY:c.clientY,pageX:c.pageX,pageY:c.pageY,screenX:c.screenX,screenY:c.screenY,xDirection:e.xDirection,yDirection:e.yDirection,trackInfo:e.trackInfo,relatedTarget:c.target,pointerType:c.pointerType},i=b.makeEvent(a,h);e.lastMoveEvent=c,b.dispatchEvent(i,e.downTarget)},pointerdown:function(a){if(a.isPrimary&&("mouse"===a.pointerType?1===a.buttons:!0)){var b={downEvent:a,downTarget:a.target,trackInfo:{},lastMoveEvent:null,xDirection:0,yDirection:0,tracking:!1};c.set(a.pointerId,b)}},pointermove:function(a){var b=c.get(a.pointerId);if(b)if(b.tracking)this.fireTrack("track",a,b);else{var d=this.calcPositionDelta(b.downEvent,a),e=d.x*d.x+d.y*d.y;e>this.WIGGLE_THRESHOLD&&(b.tracking=!0,this.fireTrack("trackstart",b.downEvent,b),this.fireTrack("track",a,b))}},pointerup:function(a){var b=c.get(a.pointerId);b&&(b.tracking&&this.fireTrack("trackend",a,b),c.delete(a.pointerId))},pointercancel:function(a){this.pointerup(a)}};b.registerRecognizer("track",d)}(window.PointerGestures),function(a){var b=a.dispatcher,c={MIN_VELOCITY:.5,MAX_QUEUE:4,moveQueue:[],target:null,pointerId:null,events:["pointerdown","pointermove","pointerup","pointercancel"],pointerdown:function(a){a.isPrimary&&!this.pointerId&&(this.pointerId=a.pointerId,this.target=a.target,this.addMove(a))},pointermove:function(a){a.pointerId===this.pointerId&&this.addMove(a)},pointerup:function(a){a.pointerId===this.pointerId&&this.fireFlick(a),this.cleanup()},pointercancel:function(){this.cleanup()},cleanup:function(){this.moveQueue=[],this.target=null,this.pointerId=null},addMove:function(a){this.moveQueue.length>=this.MAX_QUEUE&&this.moveQueue.shift(),this.moveQueue.push(a)},fireFlick:function(a){for(var c,d,e,f,g,h,i,j=a,k=this.moveQueue.length,l=0,m=0,n=0,o=0;k>o&&(i=this.moveQueue[o]);o++)c=j.timeStamp-i.timeStamp,d=j.clientX-i.clientX,e=j.clientY-i.clientY,f=d/c,g=e/c,h=Math.sqrt(f*f+g*g),h>n&&(l=f,m=g,n=h);var p=Math.abs(l)>Math.abs(m)?"x":"y",q=this.calcAngle(l,m);if(Math.abs(n)>=this.MIN_VELOCITY){var r=b.makeEvent("flick",{xVelocity:l,yVelocity:m,velocity:n,angle:q,majorAxis:p,pointerType:a.pointerType});b.dispatchEvent(r,this.target)}},calcAngle:function(a,b){return 180*Math.atan2(b,a)/Math.PI}};b.registerRecognizer("flick",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d=180/Math.PI,e={events:["pointerdown","pointermove","pointerup","pointercancel"],reference:{},pointerdown:function(b){if(c.set(b.pointerId,b),2==c.pointers()){var d=this.calcChord(),e=this.calcAngle(d);this.reference={angle:e,diameter:d.diameter,target:a.findLCA(d.a.target,d.b.target)}}},pointerup:function(a){c.delete(a.pointerId)},pointermove:function(a){c.has(a.pointerId)&&(c.set(a.pointerId,a),c.pointers()>1&&this.calcPinchRotate())},pointercancel:function(a){this.pointerup(a)},dispatchPinch:function(a,c){var d=a/this.reference.diameter,e=b.makeEvent("pinch",{scale:d,centerX:c.center.x,centerY:c.center.y});b.dispatchEvent(e,this.reference.target)},dispatchRotate:function(a,c){var d=Math.round((a-this.reference.angle)%360),e=b.makeEvent("rotate",{angle:d,centerX:c.center.x,centerY:c.center.y});b.dispatchEvent(e,this.reference.target)},calcPinchRotate:function(){var a=this.calcChord(),b=a.diameter,c=this.calcAngle(a);b!=this.reference.diameter&&this.dispatchPinch(b,a),c!=this.reference.angle&&this.dispatchRotate(c,a)},calcChord:function(){var a=[];c.forEach(function(b){a.push(b)});for(var b,d,e,f=0,g={a:a[0],b:a[1]},h=0;h<a.length;h++)for(var i=a[h],j=h+1;j<a.length;j++){var k=a[j];b=Math.abs(i.clientX-k.clientX),d=Math.abs(i.clientY-k.clientY),e=b+d,e>f&&(f=e,g={a:i,b:k})}return b=Math.abs(g.a.clientX+g.b.clientX)/2,d=Math.abs(g.a.clientY+g.b.clientY)/2,g.center={x:b,y:d},g.diameter=f,g},calcAngle:function(a){var b=a.a.clientX-a.b.clientX,c=a.a.clientY-a.b.clientY;return(360+Math.atan2(c,b)*d)%360}};b.registerRecognizer("pinch",e)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel","keyup"],pointerdown:function(a){a.isPrimary&&!a.tapPrevented&&c.set(a.pointerId,{target:a.target,buttons:a.buttons,x:a.clientX,y:a.clientY})},pointermove:function(a){if(a.isPrimary){var b=c.get(a.pointerId);b&&a.tapPrevented&&c.delete(a.pointerId)}},shouldTap:function(a,b){return a.tapPrevented?void 0:"mouse"===a.pointerType?1===b.buttons:!0},pointerup:function(d){var e=c.get(d.pointerId);if(e&&this.shouldTap(d,e)){var f=a.findLCA(e.target,d.target);if(f){var g=b.makeEvent("tap",{x:d.clientX,y:d.clientY,detail:d.detail,pointerType:d.pointerType});b.dispatchEvent(g,f)}}c.delete(d.pointerId)},pointercancel:function(a){c.delete(a.pointerId)},keyup:function(a){var c=a.keyCode;if(32===c){var d=a.target;d instanceof HTMLInputElement||d instanceof HTMLTextAreaElement||b.dispatchEvent(b.makeEvent("tap",{x:0,y:0,detail:0,pointerType:"unavailable"}),d)}},preventTap:function(a){c.delete(a)}};b.registerRecognizer("tap",d)}(window.PointerGestures),function(a){function b(){c.immediateRegister=!0;var b=c.registerQueue;b.forEach(a.register),b.length=0}var c=a.dispatcher;"complete"===document.readyState?b():document.addEventListener("readystatechange",function(){"complete"===document.readyState&&b()})}(window.PointerGestures),function(){"use strict";function a(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function b(a,b,c){var d=a.bindings_;return d||(d=a.bindings_={}),d[b]&&c[b].close(),d[b]=c}function c(a,b,c){return c}function d(a){return null==a?"":a}function e(a,b){a.data=d(b)}function f(a){return function(b){return e(a,b)}}function g(a,b,c,e){return c?void(e?a.setAttribute(b,""):a.removeAttribute(b)):void a.setAttribute(b,d(e))}function h(a,b,c){return function(d){g(a,b,c,d)}}function i(a){switch(a.type){case"checkbox":return u;case"radio":case"select-multiple":case"select-one":return"change";case"range":if(/Trident|MSIE/.test(navigator.userAgent))return"change";default:return"input"}}function j(a,b,c,e){a[b]=(e||d)(c)}function k(a,b,c){return function(d){return j(a,b,d,c)}}function l(){}function m(a,b,c,d){function e(){c.setValue(a[b]),c.discardChanges(),(d||l)(a),Platform.performMicrotaskCheckpoint()}var f=i(a);return a.addEventListener(f,e),{close:function(){a.removeEventListener(f,e),c.close()},observable_:c}}function n(a){return Boolean(a)}function o(b){if(b.form)return s(b.form.elements,function(a){return a!=b&&"INPUT"==a.tagName&&"radio"==a.type&&a.name==b.name});var c=a(b);if(!c)return[];var d=c.querySelectorAll('input[type="radio"][name="'+b.name+'"]');return s(d,function(a){return a!=b&&!a.form})}function p(a){"INPUT"===a.tagName&&"radio"===a.type&&o(a).forEach(function(a){var b=a.bindings_.checked;b&&b.observable_.setValue(!1)})}function q(a,b){var c,e,f,g=a.parentNode;g instanceof HTMLSelectElement&&g.bindings_&&g.bindings_.value&&(c=g,e=c.bindings_.value,f=c.value),a.value=d(b),c&&c.value!=f&&(e.observable_.setValue(c.value),e.observable_.discardChanges(),Platform.performMicrotaskCheckpoint())}function r(a){return function(b){q(a,b)}}var s=Array.prototype.filter.call.bind(Array.prototype.filter);Node.prototype.bind=function(a,b){console.error("Unhandled binding to Node: ",this,a,b)};var t=c;Object.defineProperty(Platform,"enableBindingsReflection",{get:function(){return t===b},set:function(a){return t=a?b:c,a},configurable:!0}),Text.prototype.bind=function(a,b,c){if("textContent"!==a)return Node.prototype.bind.call(this,a,b,c);
+if(c)return e(this,b);var d=b;return e(this,d.open(f(this))),t(this,a,d)},Element.prototype.bind=function(a,b,c){var d="?"==a[a.length-1];if(d&&(this.removeAttribute(a),a=a.slice(0,-1)),c)return g(this,a,d,b);var e=b;return g(this,a,d,e.open(h(this,a,d))),t(this,a,e)};var u;!function(){var a=document.createElement("div"),b=a.appendChild(document.createElement("input"));b.setAttribute("type","checkbox");var c,d=0;b.addEventListener("click",function(){d++,c=c||"click"}),b.addEventListener("change",function(){d++,c=c||"change"});var e=document.createEvent("MouseEvent");e.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),b.dispatchEvent(e),u=1==d?"change":c}(),HTMLInputElement.prototype.bind=function(a,c,e){if("value"!==a&&"checked"!==a)return HTMLElement.prototype.bind.call(this,a,c,e);this.removeAttribute(a);var f="checked"==a?n:d,g="checked"==a?p:l;if(e)return j(this,a,c,f);var h=c,i=m(this,a,h,g);return j(this,a,h.open(k(this,a,f)),f),b(this,a,i)},HTMLTextAreaElement.prototype.bind=function(a,b,c){if("value"!==a)return HTMLElement.prototype.bind.call(this,a,b,c);if(this.removeAttribute("value"),c)return j(this,"value",b);var e=b,f=m(this,"value",e);return j(this,"value",e.open(k(this,"value",d))),t(this,a,f)},HTMLOptionElement.prototype.bind=function(a,b,c){if("value"!==a)return HTMLElement.prototype.bind.call(this,a,b,c);if(this.removeAttribute("value"),c)return q(this,b);var d=b,e=m(this,"value",d);return q(this,d.open(r(this))),t(this,a,e)},HTMLSelectElement.prototype.bind=function(a,c,d){if("selectedindex"===a&&(a="selectedIndex"),"selectedIndex"!==a&&"value"!==a)return HTMLElement.prototype.bind.call(this,a,c,d);if(this.removeAttribute(a),d)return j(this,a,c);var e=c,f=m(this,a,e);return j(this,a,e.open(k(this,a))),b(this,a,f)}}(this),function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a){for(var b;b=a.parentNode;)a=b;return a}function d(a,b){if(b){for(var d,e="#"+b;!d&&(a=c(a),a.protoContent_?d=a.protoContent_.querySelector(e):a.getElementById&&(d=a.getElementById(b)),!d&&a.templateCreator_);)a=a.templateCreator_;return d}}function e(a){return"template"==a.tagName&&"http://www.w3.org/2000/svg"==a.namespaceURI}function f(a){return"TEMPLATE"==a.tagName&&"http://www.w3.org/1999/xhtml"==a.namespaceURI}function g(a){return Boolean(J[a.tagName]&&a.hasAttribute("template"))}function h(a){return void 0===a.isTemplate_&&(a.isTemplate_="TEMPLATE"==a.tagName||g(a)),a.isTemplate_}function i(a,b){var c=a.querySelectorAll(L);h(a)&&b(a),E(c,b)}function j(a){function b(a){HTMLTemplateElement.decorate(a)||j(a.content)}i(a,b)}function k(a,b){Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))})}function l(a){var b=a.ownerDocument;if(!b.defaultView)return b;var c=b.templateContentsOwner_;if(!c){for(c=b.implementation.createHTMLDocument("");c.lastChild;)c.removeChild(c.lastChild);b.templateContentsOwner_=c}return c}function m(a){if(!a.stagingDocument_){var b=a.ownerDocument;if(!b.stagingDocument_){b.stagingDocument_=b.implementation.createHTMLDocument("");var c=b.stagingDocument_.createElement("base");c.href=document.baseURI,b.stagingDocument_.head.appendChild(c),b.stagingDocument_.stagingDocument_=b.stagingDocument_}a.stagingDocument_=b.stagingDocument_}return a.stagingDocument_}function n(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];I[e.name]&&("template"!==e.name&&b.setAttribute(e.name,e.value),a.removeAttribute(e.name))}return b}function o(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];b.setAttribute(e.name,e.value),a.removeAttribute(e.name)}return a.parentNode.removeChild(a),b}function p(a,b,c){var d=a.content;if(c)return void d.appendChild(b);for(var e;e=b.firstChild;)d.appendChild(e)}function q(a){N?a.__proto__=HTMLTemplateElement.prototype:k(a,HTMLTemplateElement.prototype)}function r(a){a.setModelFn_||(a.setModelFn_=function(){a.setModelFnScheduled_=!1;var b=z(a,a.delegate_&&a.delegate_.prepareBinding);w(a,b,a.model_)}),a.setModelFnScheduled_||(a.setModelFnScheduled_=!0,Observer.runEOM_(a.setModelFn_))}function s(a,b,c,d){if(a&&a.length){for(var e,f=a.length,g=0,h=0,i=0,j=!0;f>h;){var g=a.indexOf("{{",h),k=a.indexOf("[[",h),l=!1,m="}}";if(k>=0&&(0>g||g>k)&&(g=k,l=!0,m="]]"),i=0>g?-1:a.indexOf(m,g+2),0>i){if(!e)return;e.push(a.slice(h));break}e=e||[],e.push(a.slice(h,g));var n=a.slice(g+2,i).trim();e.push(l),j=j&&l,e.push(Path.get(n));var o=d&&d(n,b,c);e.push(o),h=i+2}return h===f&&e.push(""),e.hasOnePath=5===e.length,e.isSimplePath=e.hasOnePath&&""==e[0]&&""==e[4],e.onlyOneTime=j,e.combinator=function(a){for(var b=e[0],c=1;c<e.length;c+=4){var d=e.hasOnePath?a:a[(c-1)/4];void 0!==d&&(b+=d),b+=e[c+3]}return b},e}}function t(a,b,c,d){if(b.hasOnePath){var e=b[3],f=e?e(d,c,!0):b[2].getValueFrom(d);return b.isSimplePath?f:b.combinator(f)}for(var g=[],h=1;h<b.length;h+=4){var e=b[h+2];g[(h-1)/4]=e?e(d,c):b[h+1].getValueFrom(d)}return b.combinator(g)}function u(a,b,c,d){var e=b[3],f=e?e(d,c,!1):new PathObserver(d,b[2]);return b.isSimplePath?f:new ObserverTransform(f,b.combinator)}function v(a,b,c,d){if(b.onlyOneTime)return t(a,b,c,d);if(b.hasOnePath)return u(a,b,c,d);for(var e=new CompoundObserver,f=1;f<b.length;f+=4){var g=b[f],h=b[f+2];if(h){var i=h(d,c,g);g?e.addPath(i):e.addObserver(i)}else{var j=b[f+1];g?e.addPath(j.getValueFrom(d)):e.addPath(d,j)}}return new ObserverTransform(e,b.combinator)}function w(a,b,c,d){for(var e=0;e<b.length;e+=2){var f=b[e],g=b[e+1],h=v(f,g,a,c),i=a.bind(f,h,g.onlyOneTime);i&&d&&d.push(i)}if(b.isTemplate){a.model_=c;var j=a.processBindingDirectives_(b);d&&j&&d.push(j)}}function x(a,b,c){var d=a.getAttribute(b);return s(""==d?"{{}}":d,b,a,c)}function y(a,c){b(a);for(var d=[],e=0;e<a.attributes.length;e++){for(var f=a.attributes[e],g=f.name,i=f.value;"_"===g[0];)g=g.substring(1);if(!h(a)||g!==H&&g!==F&&g!==G){var j=s(i,g,a,c);j&&d.push(g,j)}}return h(a)&&(d.isTemplate=!0,d.if=x(a,H,c),d.bind=x(a,F,c),d.repeat=x(a,G,c),!d.if||d.bind||d.repeat||(d.bind=s("{{}}",F,a,c))),d}function z(a,b){if(a.nodeType===Node.ELEMENT_NODE)return y(a,b);if(a.nodeType===Node.TEXT_NODE){var c=s(a.data,"textContent",a,b);if(c)return["textContent",c]}return[]}function A(a,b,c,d,e,f,g){for(var h=b.appendChild(c.importNode(a,!1)),i=0,j=a.firstChild;j;j=j.nextSibling)A(j,h,c,d.children[i++],e,f,g);return d.isTemplate&&(HTMLTemplateElement.decorate(h,a),f&&h.setDelegate_(f)),w(h,d,e,g),h}function B(a,b){var c=z(a,b);c.children={};for(var d=0,e=a.firstChild;e;e=e.nextSibling)c.children[d++]=B(e,b);return c}function C(a){this.closed=!1,this.templateElement_=a,this.instances=[],this.deps=void 0,this.iteratedValue=[],this.presentValue=void 0,this.arrayObserver=void 0}var D,E=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.Map&&"function"==typeof a.Map.prototype.forEach?D=a.Map:(D=function(){this.keys=[],this.values=[]},D.prototype={set:function(a,b){var c=this.keys.indexOf(a);0>c?(this.keys.push(a),this.values.push(b)):this.values[c]=b},get:function(a){var b=this.keys.indexOf(a);if(!(0>b))return this.values[b]},"delete":function(a){var b=this.keys.indexOf(a);return 0>b?!1:(this.keys.splice(b,1),this.values.splice(b,1),!0)},forEach:function(a,b){for(var c=0;c<this.keys.length;c++)a.call(b||this,this.values[c],this.keys[c],this)}});"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)});var F="bind",G="repeat",H="if",I={template:!0,repeat:!0,bind:!0,ref:!0},J={THEAD:!0,TBODY:!0,TFOOT:!0,TH:!0,TR:!0,TD:!0,COLGROUP:!0,COL:!0,CAPTION:!0,OPTION:!0,OPTGROUP:!0},K="undefined"!=typeof HTMLTemplateElement;K&&!function(){var a=document.createElement("template"),b=a.content.ownerDocument,c=b.appendChild(b.createElement("html")),d=c.appendChild(b.createElement("head")),e=b.createElement("base");e.href=document.baseURI,d.appendChild(e)}();var L="template, "+Object.keys(J).map(function(a){return a.toLowerCase()+"[template]"}).join(", ");document.addEventListener("DOMContentLoaded",function(){j(document),Platform.performMicrotaskCheckpoint()},!1),K||(a.HTMLTemplateElement=function(){throw TypeError("Illegal constructor")});var M,N="__proto__"in{};"function"==typeof MutationObserver&&(M=new MutationObserver(function(a){for(var b=0;b<a.length;b++)a[b].target.refChanged_()})),HTMLTemplateElement.decorate=function(a,c){if(a.templateIsDecorated_)return!1;var d=a;d.templateIsDecorated_=!0;var h=f(d)&&K,i=h,k=!h,m=!1;if(h||(g(d)?(b(!c),d=n(a),d.templateIsDecorated_=!0,h=K,m=!0):e(d)&&(d=o(a),d.templateIsDecorated_=!0,h=K)),!h){q(d);var r=l(d);d.content_=r.createDocumentFragment()}return c?d.instanceRef_=c:k?p(d,a,m):i&&j(d.content),!0},HTMLTemplateElement.bootstrap=j;var O=a.HTMLUnknownElement||HTMLElement,P={get:function(){return this.content_},enumerable:!0,configurable:!0};K||(HTMLTemplateElement.prototype=Object.create(O.prototype),Object.defineProperty(HTMLTemplateElement.prototype,"content",P)),k(HTMLTemplateElement.prototype,{bind:function(a,b,c){if("ref"!=a)return Element.prototype.bind.call(this,a,b,c);var d=this,e=c?b:b.open(function(a){d.setAttribute("ref",a),d.refChanged_()});return this.setAttribute("ref",e),this.refChanged_(),c?void 0:(this.bindings_?this.bindings_.ref=b:this.bindings_={ref:b},b)},processBindingDirectives_:function(a){return this.iterator_&&this.iterator_.closeDeps(),a.if||a.bind||a.repeat?(this.iterator_||(this.iterator_=new C(this)),this.iterator_.updateDependencies(a,this.model_),M&&M.observe(this,{attributes:!0,attributeFilter:["ref"]}),this.iterator_):void(this.iterator_&&(this.iterator_.close(),this.iterator_=void 0))},createInstance:function(a,b,c){b&&(c=this.newDelegate_(b)),this.refContent_||(this.refContent_=this.ref_.content);var d=this.refContent_;if(null===d.firstChild)return Q;var e=this.bindingMap_;e&&e.content===d||(e=B(d,c&&c.prepareBinding)||[],e.content=d,this.bindingMap_=e);var f=m(this),g=f.createDocumentFragment();g.templateCreator_=this,g.protoContent_=d,g.bindings_=[],g.terminator_=null;for(var h=g.templateInstance_={firstNode:null,lastNode:null,model:a},i=0,j=!1,k=d.firstChild;k;k=k.nextSibling){null===k.nextSibling&&(j=!0);var l=A(k,g,f,e.children[i++],a,c,g.bindings_);l.templateInstance_=h,j&&(g.terminator_=l)}return h.firstNode=g.firstChild,h.lastNode=g.lastChild,g.templateCreator_=void 0,g.protoContent_=void 0,g},get model(){return this.model_},set model(a){this.model_=a,r(this)},get bindingDelegate(){return this.delegate_&&this.delegate_.raw},refChanged_:function(){this.iterator_&&this.refContent_!==this.ref_.content&&(this.refContent_=void 0,this.iterator_.valueChanged(),this.iterator_.updateIteratedValue())},clear:function(){this.model_=void 0,this.delegate_=void 0,this.bindings_&&this.bindings_.ref&&this.bindings_.ref.close(),this.refContent_=void 0,this.iterator_&&(this.iterator_.valueChanged(),this.iterator_.close(),this.iterator_=void 0)},setDelegate_:function(a){this.delegate_=a,this.bindingMap_=void 0,this.iterator_&&(this.iterator_.instancePositionChangedFn_=void 0,this.iterator_.instanceModelFn_=void 0)},newDelegate_:function(a){function b(b){var c=a&&a[b];if("function"==typeof c)return function(){return c.apply(a,arguments)}}return a?{raw:a,prepareBinding:b("prepareBinding"),prepareInstanceModel:b("prepareInstanceModel"),prepareInstancePositionChanged:b("prepareInstancePositionChanged")}:{}},set bindingDelegate(a){if(this.delegate_)throw Error("Template must be cleared before a new bindingDelegate can be assigned");this.setDelegate_(this.newDelegate_(a))},get ref_(){var a=d(this,this.getAttribute("ref"));if(a||(a=this.instanceRef_),!a)return this;var b=a.ref_;return b?b:a}}),Object.defineProperty(Node.prototype,"templateInstance",{get:function(){var a=this.templateInstance_;return a?a:this.parentNode?this.parentNode.templateInstance:void 0}});var Q=document.createDocumentFragment();Q.bindings_=[],Q.terminator_=null,C.prototype={closeDeps:function(){var a=this.deps;a&&(a.ifOneTime===!1&&a.ifValue.close(),a.oneTime===!1&&a.value.close())},updateDependencies:function(a,b){this.closeDeps();var c=this.deps={},d=this.templateElement_;if(a.if){if(c.hasIf=!0,c.ifOneTime=a.if.onlyOneTime,c.ifValue=v(H,a.if,d,b),c.ifOneTime&&!c.ifValue)return void this.updateIteratedValue();c.ifOneTime||c.ifValue.open(this.updateIteratedValue,this)}a.repeat?(c.repeat=!0,c.oneTime=a.repeat.onlyOneTime,c.value=v(G,a.repeat,d,b)):(c.repeat=!1,c.oneTime=a.bind.onlyOneTime,c.value=v(F,a.bind,d,b)),c.oneTime||c.value.open(this.updateIteratedValue,this),this.updateIteratedValue()},updateIteratedValue:function(){if(this.deps.hasIf){var a=this.deps.ifValue;if(this.deps.ifOneTime||(a=a.discardChanges()),!a)return void this.valueChanged()}var b=this.deps.value;this.deps.oneTime||(b=b.discardChanges()),this.deps.repeat||(b=[b]);var c=this.deps.repeat&&!this.deps.oneTime&&Array.isArray(b);this.valueChanged(b,c)},valueChanged:function(a,b){Array.isArray(a)||(a=[]),a!==this.iteratedValue&&(this.unobserve(),this.presentValue=a,b&&(this.arrayObserver=new ArrayObserver(this.presentValue),this.arrayObserver.open(this.handleSplices,this)),this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,this.iteratedValue)))},getLastInstanceNode:function(a){if(-1==a)return this.templateElement_;var b=this.instances[a],c=b.terminator_;if(!c)return this.getLastInstanceNode(a-1);if(c.nodeType!==Node.ELEMENT_NODE||this.templateElement_===c)return c;var d=c.iterator_;return d?d.getLastTemplateNode():c},getLastTemplateNode:function(){return this.getLastInstanceNode(this.instances.length-1)},insertInstanceAt:function(a,b){var c=this.getLastInstanceNode(a-1),d=this.templateElement_.parentNode;this.instances.splice(a,0,b),d.insertBefore(b,c.nextSibling)},extractInstanceAt:function(a){for(var b=this.getLastInstanceNode(a-1),c=this.getLastInstanceNode(a),d=this.templateElement_.parentNode,e=this.instances.splice(a,1)[0];c!==b;){var f=b.nextSibling;f==c&&(c=b),e.appendChild(d.removeChild(f))}return e},getDelegateFn:function(a){return a=a&&a(this.templateElement_),"function"==typeof a?a:null},handleSplices:function(a){if(!this.closed&&a.length){var b=this.templateElement_;if(!b.parentNode)return void this.close();ArrayObserver.applySplices(this.iteratedValue,this.presentValue,a);var c=b.delegate_;void 0===this.instanceModelFn_&&(this.instanceModelFn_=this.getDelegateFn(c&&c.prepareInstanceModel)),void 0===this.instancePositionChangedFn_&&(this.instancePositionChangedFn_=this.getDelegateFn(c&&c.prepareInstancePositionChanged));for(var d=new D,e=0,f=0;f<a.length;f++){for(var g=a[f],h=g.removed,i=0;i<h.length;i++){var j=h[i],k=this.extractInstanceAt(g.index+e);k!==Q&&d.set(j,k)}e-=g.addedCount}for(var f=0;f<a.length;f++)for(var g=a[f],l=g.index;l<g.index+g.addedCount;l++){var j=this.iteratedValue[l],k=d.get(j);k?d.delete(j):(this.instanceModelFn_&&(j=this.instanceModelFn_(j)),k=void 0===j?Q:b.createInstance(j,void 0,c)),this.insertInstanceAt(l,k)}d.forEach(function(a){this.closeInstanceBindings(a)},this),this.instancePositionChangedFn_&&this.reportInstancesMoved(a)}},reportInstanceMoved:function(a){var b=this.instances[a];b!==Q&&this.instancePositionChangedFn_(b.templateInstance_,a)},reportInstancesMoved:function(a){for(var b=0,c=0,d=0;d<a.length;d++){var e=a[d];if(0!=c)for(;b<e.index;)this.reportInstanceMoved(b),b++;else b=e.index;for(;b<e.index+e.addedCount;)this.reportInstanceMoved(b),b++;c+=e.addedCount-e.removed.length}if(0!=c)for(var f=this.instances.length;f>b;)this.reportInstanceMoved(b),b++},closeInstanceBindings:function(a){for(var b=a.bindings_,c=0;c<b.length;c++)b[c].close()},unobserve:function(){this.arrayObserver&&(this.arrayObserver.close(),this.arrayObserver=void 0)},close:function(){if(!this.closed){this.unobserve();for(var a=0;a<this.instances.length;a++)this.closeInstanceBindings(this.instances[a]);this.instances.length=0,this.closeDeps(),this.templateElement_.iterator_=void 0,this.closed=!0}}},HTMLTemplateElement.forAllTemplatesFrom_=i}(this),function(a){"use strict";function b(a,b){if(!a)throw new Error("ASSERT: "+b)}function c(a){return a>=48&&57>=a}function d(a){return 32===a||9===a||11===a||12===a||160===a||a>=5760&&"áš€á Žâ€€â€â€‚â€ƒâ€„â€…â€†â€‡â€ˆâ€‰â€Šâ€¯âŸã€€ï»¿".indexOf(String.fromCharCode(a))>0}function e(a){return 10===a||13===a||8232===a||8233===a}function f(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a}function g(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a||a>=48&&57>=a}function h(a){return"this"===a}function i(){for(;Y>X&&d(W.charCodeAt(X));)++X}function j(){var a,b;for(a=X++;Y>X&&(b=W.charCodeAt(X),g(b));)++X;return W.slice(a,X)}function k(){var a,b,c;return a=X,b=j(),c=1===b.length?S.Identifier:h(b)?S.Keyword:"null"===b?S.NullLiteral:"true"===b||"false"===b?S.BooleanLiteral:S.Identifier,{type:c,value:b,range:[a,X]}}function l(){var a,b,c=X,d=W.charCodeAt(X),e=W[X];switch(d){case 46:case 40:case 41:case 59:case 44:case 123:case 125:case 91:case 93:case 58:case 63:return++X,{type:S.Punctuator,value:String.fromCharCode(d),range:[c,X]};default:if(a=W.charCodeAt(X+1),61===a)switch(d){case 37:case 38:case 42:case 43:case 45:case 47:case 60:case 62:case 124:return X+=2,{type:S.Punctuator,value:String.fromCharCode(d)+String.fromCharCode(a),range:[c,X]};case 33:case 61:return X+=2,61===W.charCodeAt(X)&&++X,{type:S.Punctuator,value:W.slice(c,X),range:[c,X]}}}return b=W[X+1],e===b&&"&|".indexOf(e)>=0?(X+=2,{type:S.Punctuator,value:e+b,range:[c,X]}):"<>=!+-*%&|^/".indexOf(e)>=0?(++X,{type:S.Punctuator,value:e,range:[c,X]}):void s({},V.UnexpectedToken,"ILLEGAL")}function m(){var a,d,e;if(e=W[X],b(c(e.charCodeAt(0))||"."===e,"Numeric literal must start with a decimal digit or a decimal point"),d=X,a="","."!==e){for(a=W[X++],e=W[X],"0"===a&&e&&c(e.charCodeAt(0))&&s({},V.UnexpectedToken,"ILLEGAL");c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("."===e){for(a+=W[X++];c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("e"===e||"E"===e)if(a+=W[X++],e=W[X],("+"===e||"-"===e)&&(a+=W[X++]),c(W.charCodeAt(X)))for(;c(W.charCodeAt(X));)a+=W[X++];else s({},V.UnexpectedToken,"ILLEGAL");return f(W.charCodeAt(X))&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.NumericLiteral,value:parseFloat(a),range:[d,X]}}function n(){var a,c,d,f="",g=!1;for(a=W[X],b("'"===a||'"'===a,"String literal must starts with a quote"),c=X,++X;Y>X;){if(d=W[X++],d===a){a="";break}if("\\"===d)if(d=W[X++],d&&e(d.charCodeAt(0)))"\r"===d&&"\n"===W[X]&&++X;else switch(d){case"n":f+="\n";break;case"r":f+="\r";break;case"t":f+="  ";break;case"b":f+="\b";break;case"f":f+="\f";break;case"v":f+="";break;default:f+=d}else{if(e(d.charCodeAt(0)))break;f+=d}}return""!==a&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.StringLiteral,value:f,octal:g,range:[c,X]}}function o(a){return a.type===S.Identifier||a.type===S.Keyword||a.type===S.BooleanLiteral||a.type===S.NullLiteral}function p(){var a;return i(),X>=Y?{type:S.EOF,range:[X,X]}:(a=W.charCodeAt(X),40===a||41===a||58===a?l():39===a||34===a?n():f(a)?k():46===a?c(W.charCodeAt(X+1))?m():l():c(a)?m():l())}function q(){var a;return a=$,X=a.range[1],$=p(),X=a.range[1],a}function r(){var a;a=X,$=p(),X=a}function s(a,c){var d,e=Array.prototype.slice.call(arguments,2),f=c.replace(/%(\d)/g,function(a,c){return b(c<e.length,"Message reference must be in range"),e[c]});throw d=new Error(f),d.index=X,d.description=f,d}function t(a){s(a,V.UnexpectedToken,a.value)}function u(a){var b=q();(b.type!==S.Punctuator||b.value!==a)&&t(b)}function v(a){return $.type===S.Punctuator&&$.value===a}function w(a){return $.type===S.Keyword&&$.value===a}function x(){var a=[];for(u("[");!v("]");)v(",")?(q(),a.push(null)):(a.push(bb()),v("]")||u(","));return u("]"),Z.createArrayExpression(a)}function y(){var a;return i(),a=q(),a.type===S.StringLiteral||a.type===S.NumericLiteral?Z.createLiteral(a):Z.createIdentifier(a.value)}function z(){var a,b;return a=$,i(),(a.type===S.EOF||a.type===S.Punctuator)&&t(a),b=y(),u(":"),Z.createProperty("init",b,bb())}function A(){var a=[];for(u("{");!v("}");)a.push(z()),v("}")||u(",");return u("}"),Z.createObjectExpression(a)}function B(){var a;return u("("),a=bb(),u(")"),a}function C(){var a,b,c;return v("(")?B():(a=$.type,a===S.Identifier?c=Z.createIdentifier(q().value):a===S.StringLiteral||a===S.NumericLiteral?c=Z.createLiteral(q()):a===S.Keyword?w("this")&&(q(),c=Z.createThisExpression()):a===S.BooleanLiteral?(b=q(),b.value="true"===b.value,c=Z.createLiteral(b)):a===S.NullLiteral?(b=q(),b.value=null,c=Z.createLiteral(b)):v("[")?c=x():v("{")&&(c=A()),c?c:void t(q()))}function D(){var a=[];if(u("("),!v(")"))for(;Y>X&&(a.push(bb()),!v(")"));)u(",");return u(")"),a}function E(){var a;return a=q(),o(a)||t(a),Z.createIdentifier(a.value)}function F(){return u("."),E()}function G(){var a;return u("["),a=bb(),u("]"),a}function H(){var a,b;for(a=C();v(".")||v("[");)v("[")?(b=G(),a=Z.createMemberExpression("[",a,b)):(b=F(),a=Z.createMemberExpression(".",a,b));return a}function I(){var a,b;return $.type!==S.Punctuator&&$.type!==S.Keyword?b=ab():v("+")||v("-")||v("!")?(a=q(),b=I(),b=Z.createUnaryExpression(a.value,b)):w("delete")||w("void")||w("typeof")?s({},V.UnexpectedToken):b=ab(),b}function J(a){var b=0;if(a.type!==S.Punctuator&&a.type!==S.Keyword)return 0;switch(a.value){case"||":b=1;break;case"&&":b=2;break;case"==":case"!=":case"===":case"!==":b=6;break;case"<":case">":case"<=":case">=":case"instanceof":b=7;break;case"in":b=7;break;case"+":case"-":b=9;break;case"*":case"/":case"%":b=11}return b}function K(){var a,b,c,d,e,f,g,h;if(g=I(),b=$,c=J(b),0===c)return g;for(b.prec=c,q(),e=I(),d=[g,b,e];(c=J($))>0;){for(;d.length>2&&c<=d[d.length-2].prec;)e=d.pop(),f=d.pop().value,g=d.pop(),a=Z.createBinaryExpression(f,g,e),d.push(a);b=q(),b.prec=c,d.push(b),a=I(),d.push(a)}for(h=d.length-1,a=d[h];h>1;)a=Z.createBinaryExpression(d[h-1].value,d[h-2],a),h-=2;return a}function L(){var a,b,c;return a=K(),v("?")&&(q(),b=L(),u(":"),c=L(),a=Z.createConditionalExpression(a,b,c)),a}function M(){var a,b;return a=q(),a.type!==S.Identifier&&t(a),b=v("(")?D():[],Z.createFilter(a.value,b)}function N(){for(;v("|");)q(),M()}function O(){i(),r();var a=bb();a&&(","===$.value||"in"==$.value&&a.type===U.Identifier?Q(a):(N(),"as"===$.value?P(a):Z.createTopLevel(a))),$.type!==S.EOF&&t($)}function P(a){q();var b=q().value;Z.createAsExpression(a,b)}function Q(a){var b;","===$.value&&(q(),$.type!==S.Identifier&&t($),b=q().value),q();var c=bb();N(),Z.createInExpression(a.name,b,c)}function R(a,b){return Z=b,W=a,X=0,Y=W.length,$=null,_={labelSet:{}},O()}var S,T,U,V,W,X,Y,Z,$,_;S={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8},T={},T[S.BooleanLiteral]="Boolean",T[S.EOF]="<end>",T[S.Identifier]="Identifier",T[S.Keyword]="Keyword",T[S.NullLiteral]="Null",T[S.NumericLiteral]="Numeric",T[S.Punctuator]="Punctuator",T[S.StringLiteral]="String",U={ArrayExpression:"ArrayExpression",BinaryExpression:"BinaryExpression",CallExpression:"CallExpression",ConditionalExpression:"ConditionalExpression",EmptyStatement:"EmptyStatement",ExpressionStatement:"ExpressionStatement",Identifier:"Identifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",ObjectExpression:"ObjectExpression",Program:"Program",Property:"Property",ThisExpression:"ThisExpression",UnaryExpression:"UnaryExpression"},V={UnexpectedToken:"Unexpected token %0",UnknownLabel:"Undefined label '%0'",Redeclaration:"%0 '%1' has already been declared"};var ab=H,bb=L;a.esprima={parse:R}}(this),function(a){"use strict";function b(a,b,d,e){var f;try{if(f=c(a),f.scopeIdent&&(d.nodeType!==Node.ELEMENT_NODE||"TEMPLATE"!==d.tagName||"bind"!==b&&"repeat"!==b))throw Error("as and in can only be used within <template bind/repeat>")}catch(g){return void console.error("Invalid expression syntax: "+a,g)}return function(a,b,c){var d=f.getBinding(a,e,c);return f.scopeIdent&&d&&(b.polymerExpressionScopeIdent_=f.scopeIdent,f.indexIdent&&(b.polymerExpressionIndexIdent_=f.indexIdent)),d}}function c(a){var b=s[a];if(!b){var c=new j;esprima.parse(a,c),b=new l(c),s[a]=b}return b}function d(a){this.value=a,this.valueFn_=void 0}function e(a){this.name=a,this.path=Path.get(a)}function f(a,b,c){"["==c&&b instanceof d&&Path.get(b.value).valid&&(c=".",b=new e(b.value)),this.dynamicDeps="function"==typeof a||a.dynamic,this.dynamic="function"==typeof b||b.dynamic||"["==c,this.simplePath=!this.dynamic&&!this.dynamicDeps&&b instanceof e&&(a instanceof f||a instanceof e),this.object=this.simplePath?a:i(a),this.property="."==c?b:i(b)}function g(a,b){this.name=a,this.args=[];for(var c=0;c<b.length;c++)this.args[c]=i(b[c])}function h(){throw Error("Not Implemented")}function i(a){return"function"==typeof a?a:a.valueFn()}function j(){this.expression=null,this.filters=[],this.deps={},this.currentPath=void 0,this.scopeIdent=void 0,this.indexIdent=void 0,this.dynamicDeps=!1}function k(a){this.value_=a}function l(a){if(this.scopeIdent=a.scopeIdent,this.indexIdent=a.indexIdent,!a.expression)throw Error("No expression found.");this.expression=a.expression,i(this.expression),this.filters=a.filters,this.dynamicDeps=a.dynamicDeps}function m(a){return String(a).replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}function n(a){return"o"===a[0]&&"n"===a[1]&&"-"===a[2]}function o(a,b){for(;a[w]&&!Object.prototype.hasOwnProperty.call(a,b);)a=a[w];return a}function p(a,b){if(0==b.length)return void 0;if(1==b.length)return o(a,b[0]);for(var c=0;null!=a&&c<b.length-1;c++)a=a[b[c]];return a}function q(a,b,c){var d=b.substring(3);return d=v[d]||d,function(b,e,f){function g(){return"{{ "+a+" }}"}var h,i,j;return j="function"==typeof c.resolveEventHandler?function(d){h=h||c.resolveEventHandler(b,a,e),h(d,d.detail,d.currentTarget),Platform&&"function"==typeof Platform.flush&&Platform.flush()}:function(c){h=h||a.getValueFrom(b),i=i||p(b,a,e),h.apply(i,[c,c.detail,c.currentTarget]),Platform&&"function"==typeof Platform.flush&&Platform.flush()},e.addEventListener(d,j),f?void 0:{open:g,discardChanges:g,close:function(){e.removeEventListener(d,j)}}}}function r(){}var s=Object.create(null);d.prototype={valueFn:function(){if(!this.valueFn_){var a=this.value;this.valueFn_=function(){return a}}return this.valueFn_}},e.prototype={valueFn:function(){if(!this.valueFn_){var a=(this.name,this.path);this.valueFn_=function(b,c){return c&&c.addPath(b,a),a.getValueFrom(b)}}return this.valueFn_},setValue:function(a,b){return 1==this.path.length,a=o(a,this.path[0]),this.path.setValueFrom(a,b)}},f.prototype={get fullPath(){if(!this.fullPath_){var a=this.object instanceof e?this.object.name:this.object.fullPath;this.fullPath_=Path.get(a+"."+this.property.name)}return this.fullPath_},valueFn:function(){if(!this.valueFn_){var a=this.object;if(this.simplePath){var b=this.fullPath;this.valueFn_=function(a,c){return c&&c.addPath(a,b),b.getValueFrom(a)}}else if(this.property instanceof e){var b=Path.get(this.property.name);this.valueFn_=function(c,d){var e=a(c,d);return d&&d.addPath(e,b),b.getValueFrom(e)}}else{var c=this.property;this.valueFn_=function(b,d){var e=a(b,d),f=c(b,d);return d&&d.addPath(e,f),e?e[f]:void 0}}}return this.valueFn_},setValue:function(a,b){if(this.simplePath)return this.fullPath.setValueFrom(a,b),b;var c=this.object(a),d=this.property instanceof e?this.property.name:this.property(a);return c[d]=b}},g.prototype={transform:function(a,b,c,d,e){var f=c[this.name],g=d;if(f)g=void 0;else if(f=g[this.name],!f)return void console.error("Cannot find filter: "+this.name);if(b?f=f.toModel:"function"==typeof f.toDOM&&(f=f.toDOM),"function"!=typeof f)return void console.error("No "+(b?"toModel":"toDOM")+" found on"+this.name);for(var h=[a],j=0;j<this.args.length;j++)h[j+1]=i(this.args[j])(d,e);return f.apply(g,h)}};var t={"+":function(a){return+a},"-":function(a){return-a},"!":function(a){return!a}},u={"+":function(a,b){return a+b},"-":function(a,b){return a-b},"*":function(a,b){return a*b},"/":function(a,b){return a/b},"%":function(a,b){return a%b},"<":function(a,b){return b>a},">":function(a,b){return a>b},"<=":function(a,b){return b>=a},">=":function(a,b){return a>=b},"==":function(a,b){return a==b},"!=":function(a,b){return a!=b},"===":function(a,b){return a===b},"!==":function(a,b){return a!==b},"&&":function(a,b){return a&&b},"||":function(a,b){return a||b}};j.prototype={createUnaryExpression:function(a,b){if(!t[a])throw Error("Disallowed operator: "+a);return b=i(b),function(c,d){return t[a](b(c,d))}},createBinaryExpression:function(a,b,c){if(!u[a])throw Error("Disallowed operator: "+a);return b=i(b),c=i(c),function(d,e){return u[a](b(d,e),c(d,e))}},createConditionalExpression:function(a,b,c){return a=i(a),b=i(b),c=i(c),function(d,e){return a(d,e)?b(d,e):c(d,e)}},createIdentifier:function(a){var b=new e(a);return b.type="Identifier",b},createMemberExpression:function(a,b,c){var d=new f(b,c,a);return d.dynamicDeps&&(this.dynamicDeps=!0),d},createLiteral:function(a){return new d(a.value)},createArrayExpression:function(a){for(var b=0;b<a.length;b++)a[b]=i(a[b]);return function(b,c){for(var d=[],e=0;e<a.length;e++)d.push(a[e](b,c));return d}},createProperty:function(a,b,c){return{key:b instanceof e?b.name:b.value,value:c}},createObjectExpression:function(a){for(var b=0;b<a.length;b++)a[b].value=i(a[b].value);return function(b,c){for(var d={},e=0;e<a.length;e++)d[a[e].key]=a[e].value(b,c);return d}},createFilter:function(a,b){this.filters.push(new g(a,b))},createAsExpression:function(a,b){this.expression=a,this.scopeIdent=b},createInExpression:function(a,b,c){this.expression=c,this.scopeIdent=a,this.indexIdent=b},createTopLevel:function(a){this.expression=a},createThisExpression:h},k.prototype={open:function(){return this.value_},discardChanges:function(){return this.value_},deliver:function(){},close:function(){}},l.prototype={getBinding:function(a,b,c){function d(){if(h)return h=!1,g;i.dynamicDeps&&f.startReset();var c=i.getValue(a,i.dynamicDeps?f:void 0,b);return i.dynamicDeps&&f.finishReset(),c}function e(c){return i.setValue(a,c,b),c}if(c)return this.getValue(a,void 0,b);var f=new CompoundObserver,g=this.getValue(a,f,b),h=!0,i=this;return new ObserverTransform(f,d,e,!0)},getValue:function(a,b,c){for(var d=i(this.expression)(a,b),e=0;e<this.filters.length;e++)d=this.filters[e].transform(d,!1,c,a,b);return d},setValue:function(a,b,c){for(var d=this.filters?this.filters.length:0;d-->0;)b=this.filters[d].transform(b,!0,c,a);return this.expression.setValue?this.expression.setValue(a,b):void 0}};var v={};["webkitAnimationStart","webkitAnimationEnd","webkitTransitionEnd","DOMFocusOut","DOMFocusIn","DOMMouseScroll"].forEach(function(a){v[a.toLowerCase()]=a});var w="@"+Math.random().toString(36).slice(2);r.prototype={styleObject:function(a){var b=[];for(var c in a)b.push(m(c)+": "+a[c]);return b.join("; ")},tokenList:function(a){var b=[];for(var c in a)a[c]&&b.push(c);return b.join(" ")},prepareInstancePositionChanged:function(a){var b=a.polymerExpressionIndexIdent_;if(b)return function(a,c){a.model[b]=c}},prepareBinding:function(a,c,d){var e=Path.get(a);if(n(c))return e.valid?q(e,c,this):void console.error("on-* bindings must be simple path expressions");{if(!e.valid)return b(a,c,d,this);if(1==e.length)return function(a,b,c){if(c)return e.getValueFrom(a);var d=o(a,e[0]);return new PathObserver(d,e)}}},prepareInstanceModel:function(a){var b=a.polymerExpressionScopeIdent_;if(b){var c=a.templateInstance?a.templateInstance.model:a.model,d=a.polymerExpressionIndexIdent_;return function(a){var e=Object.create(c);return e[b]=a,e[d]=void 0,e[w]=c,e}}}},a.PolymerExpressions=r,a.exposeGetExpression&&(a.getExpression_=c),a.PolymerExpressions.prepareEventBinding=q}(this),function(a){function b(){e||(e=!0,a.endOfMicrotask(function(){e=!1,logFlags.data&&console.group("Platform.flush()"),a.performMicrotaskCheckpoint(),logFlags.data&&console.groupEnd()}))}var c=document.createElement("style");
+c.textContent="template {display: none !important;} /* injected by platform.js */";var d=document.querySelector("head");d.insertBefore(c,d.firstChild);var e,f=125;if(window.addEventListener("WebComponentsReady",function(){b(),Observer.hasObjectObserve||(a.flushPoll=setInterval(b,f))}),window.CustomElements&&!CustomElements.useNative){var g=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=g.call(this,a,b);return CustomElements.upgradeAll(c),c}}a.flush=b}(window.Platform);
 //# sourceMappingURL=platform.js.map</script>
     <meta name="viewport" content="width=device-width, user-scalable=no">
     
@@ -54,35 +58,38 @@
  Use of this source code is governed by a BSD-style
  license that can be found in the LICENSE file.
 -->
-<script>// Copyright (c) 2012 The Polymer Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// @version: 0.1.1
-Polymer={},"function"==typeof window.Polymer&&(Polymer={}),function(a){function b(a,b){return a&&b&&Object.getOwnPropertyNames(b).forEach(function(c){var d=Object.getOwnPropertyDescriptor(b,c);d&&(Object.defineProperty(a,c,d),"function"==typeof d.value&&(d.value.nom=c))}),a}a.extend=b}(Polymer),function(a){function b(a,b,d){return a?a.stop():a=new c(this),a.go(b,d),a}var c=function(a){this.context=a};c.prototype={go:function(a,b){this.callback=a,this.handle=setTimeout(this.complete.bind(this),b)},stop:function(){this.handle&&(clearTimeout(this.handle),this.handle=null)},complete:function(){this.handle&&(this.stop(),this.callback.call(this.context))}},a.job=b}(Polymer),function(){var a={};HTMLElement.register=function(b,c){a[b]=c},HTMLElement.getPrototypeForTag=function(b){var c=b?a[b]:HTMLElement.prototype;return c||Object.getPrototypeOf(document.createElement(b))};var b=Event.prototype.stopPropagation;Event.prototype.stopPropagation=function(){this.cancelBubble=!0,b.apply(this,arguments)},HTMLImports.importer.preloadSelectors+=", polymer-element link[rel=stylesheet]"}(Polymer),function(a){function b(a){var c=b.caller,g=c.nom,h=c._super;if(h||(g||(g=c.nom=e.call(this,c)),g||console.warn("called super() on a method not installed declaratively (has no .nom property)"),h=d(c,g,f(this))),h){var i=h[g];return i._super||d(i,g,h),i.apply(this,a||[])}}function c(a,b,c){for(;a;){if(a[b]!==c&&a[b])return a;a=f(a)}}function d(a,b,d){return a._super=c(d,b,a),a._super&&(a._super[b].nom=b),a._super}function e(a){for(var b=this.__proto__;b&&b!==HTMLElement.prototype;){for(var c,d=Object.getOwnPropertyNames(b),e=0,f=d.length;f>e&&(c=d[e]);e++){var g=Object.getOwnPropertyDescriptor(b,c);if("function"==typeof g.value&&g.value===a)return c}b=b.__proto__}}function f(a){return a.__proto__}a.super=b}(Polymer),function(a){function b(a,b){var d=typeof b;return b instanceof Date&&(d="date"),c[d](a,b)}var c={string:function(a){return a},date:function(a){return new Date(Date.parse(a)||Date.now())},"boolean":function(a){return""===a?!0:"false"===a?!1:!!a},number:function(a){var b=parseFloat(a);return String(b)===a?b:a},object:function(a,b){if(null===b)return a;try{return JSON.parse(a.replace(/'/g,'"'))}catch(c){return a}},"function":function(a,b){return b}};a.deserializeValue=b}(Polymer),function(a){var b={};b.declaration={},b.instance={},a.api=b}(Polymer),function(a){var b={async:function(a,b,c){Platform.flush(),b=b&&b.length?b:[b];var d=function(){(this[a]||a).apply(this,b)}.bind(this);return c?setTimeout(d,c):requestAnimationFrame(d)},fire:function(a,b,c,d){var e=c||this;return e.dispatchEvent(new CustomEvent(a,{bubbles:void 0!==d?d:!0,detail:b})),b},asyncFire:function(){this.async("fire",arguments)},classFollows:function(a,b,c){b&&b.classList.remove(c),a&&a.classList.add(c)}};b.asyncMethod=b.async,a.api.instance.utils=b}(Polymer),function(a){function b(a){for(;a.parentNode;)a=a.parentNode;return a.host}var c=window.logFlags||{},d="on-",e={EVENT_PREFIX:d,hasEventPrefix:function(a){return a&&"o"===a[0]&&"n"===a[1]&&"-"===a[2]},removeEventPrefix:function(a){return a.slice(f)},addHostListeners:function(){var a=this.eventDelegates;c.events&&Object.keys(a).length>0&&console.log("[%s] addHostListeners:",this.localName,a),this.addNodeListeners(this,a,this.hostEventListener)},addNodeListeners:function(a,b,c){var d;for(var e in b)d||(d=c.bind(this)),this.addNodeListener(a,e,d)},addNodeListener:function(a,b,c){a.addEventListener(b,c)},hostEventListener:function(a){if(!a.cancelBubble){c.events&&console.group("[%s]: hostEventListener(%s)",this.localName,a.type);var b=this.findEventDelegate(a);b&&(c.events&&console.log("[%s] found host handler name [%s]",this.localName,b),this.dispatchMethod(this,b,[a,a.detail,this])),c.events&&console.groupEnd()}},findEventDelegate:function(a){return this.eventDelegates[a.type]},dispatchMethod:function(a,b,d){if(a){c.events&&console.group("[%s] dispatch [%s]",a.localName,b);var e="function"==typeof b?b:a[b];e&&e[d?"apply":"call"](a,d),c.events&&console.groupEnd(),Platform.flush()}},prepareBinding:function(a,d){return e.hasEventPrefix(d)?function(f,g){c.events&&console.log('event: [%s].%s => [%s].%s()"',g.localName,f.localName,a);var h=function(c){var d=b(g);if(d&&d.dispatchMethod){var e=d,h=a;"@"==a[0]&&(e=f,h=Path.get(a.slice(1)).getValueFrom(f)),d.dispatchMethod(e,h,[c,c.detail,g])}},i=e.removeEventPrefix(d);return g.addEventListener(i,h,!1),{close:function(){c.events&&console.log('event.remove: [%s].%s => [%s].%s()"',g.localName,d,f.localName,a),g.removeEventListener(i,h,!1)}}}:void 0}},f=d.length;a.api.instance.events=e}(Polymer),function(a){var b={copyInstanceAttributes:function(){var a=this._instanceAttributes;for(var b in a)this.hasAttribute(b)||this.setAttribute(b,a[b])},takeAttributes:function(){if(this._publishLC)for(var a,b=0,c=this.attributes,d=c.length;(a=c[b])&&d>b;b++)this.attributeToProperty(a.name,a.value)},attributeToProperty:function(b,c){var b=this.propertyForAttribute(b);if(b){if(c&&c.search(a.bindPattern)>=0)return;var d=this[b],c=this.deserializeValue(c,d);c!==d&&(this[b]=c)}},propertyForAttribute:function(a){var b=this._publishLC&&this._publishLC[a];return b},deserializeValue:function(b,c){return a.deserializeValue(b,c)},serializeValue:function(a,b){return"boolean"===b?a?"":void 0:"object"!==b&&"function"!==b&&void 0!==a?a:void 0},reflectPropertyToAttribute:function(a){var b=typeof this[a],c=this.serializeValue(this[a],b);void 0!==c?this.setAttribute(a,c):"boolean"===b&&this.removeAttribute(a)}};a.api.instance.attributes=b}(Polymer),function(a){function b(a){return new CompoundPathObserver(a.notifyPropertyChanges,a)}function c(a,b,c,e){d.bind&&console.log(f,c.localName||"object",e,a.localName,b);var g=Path.get(e),h=g.getValueFrom(c);return(null===h||void 0===h)&&g.setValueFrom(c,a[b]),PathObserver.defineProperty(a,b,c,e)}var d=window.logFlags||{},e={observeProperties:function(){var a=this._observeNames,c=this._publishNames;if(a&&a.length||c&&c.length){for(var d,e=this._propertyObserver=b(this),f=0,g=a.length;g>f&&(d=a[f]);f++){e.addPath(this,d);var h=Object.getOwnPropertyDescriptor(this.__proto__,d);h&&h.value&&this.observeArrayValue(d,h.value,null)}for(var d,f=0,g=c.length;g>f&&(d=c[f]);f++)this.observe&&void 0!==this.observe[d]||e.addPath(this,d);e.start()}},notifyPropertyChanges:function(a,b,c,d){for(var e,f,g={},h=0,i=c.length;i>h;h++)c[h]&&(e=d[2*h+1],void 0!==this.publish[e]&&this.reflectPropertyToAttribute(e),f=this.observe[e],f&&(this.observeArrayValue(e,a[h],b[h]),g[f]||(g[f]=!0,this.invokeMethod(f,[b[h],a[h],arguments]))))},observeArrayValue:function(a,b,c){var e=this.observe[a];if(e&&(Array.isArray(c)&&(d.observe&&console.log("[%s] observeArrayValue: unregister observer [%s]",this.localName,a),this.unregisterObserver(a+"__array")),Array.isArray(b))){d.observe&&console.log("[%s] observeArrayValue: register observer [%s]",this.localName,a,b);var f=this,g=new ArrayObserver(b,function(a,b){f.invokeMethod(e,[b])});this.registerObserver(a+"__array",g)}},bindProperty:function(a,b,d){return c(this,a,b,d)},unbindAllProperties:function(){this._propertyObserver&&this._propertyObserver.close(),this.unregisterObservers()},unbindProperty:function(a){return this.unregisterObserver(a)},invokeMethod:function(a,b){var c=this[a]||a;"function"==typeof c&&c.apply(this,b)},registerObserver:function(a,b){var c=this._observers||(this._observers={});c[a]=b},unregisterObserver:function(a){var b=this._observers;return b&&b[a]?(b[a].close(),b[a]=null,!0):void 0},unregisterObservers:function(){if(this._observers){for(var a,b,c=Object.keys(this._observers),d=0,e=c.length;e>d&&(a=c[d]);d++)b=this._observers[a],b.close();this._observers={}}}},f="[%s]: bindProperties: [%s] to [%s].[%s]";a.api.instance.properties=e}(Polymer),function(a){function b(a){d(a,c)}function c(a){a.unbindAll()}function d(a,b){if(a){b(a);for(var c=a.firstChild;c;c=c.nextSibling)d(c,b)}}var e=window.logFlags||0,f=a.api.instance.events,g=PolymerExpressions.prototype.prepareBinding;PolymerExpressions.prototype.prepareBinding=function(a,b,c){return f.prepareBinding(a,b,c)||g.call(this,a,b,c)};var h=new PolymerExpressions,i={syntax:h,instanceTemplate:function(a){return a.bindingDelegate=this.syntax,a.createInstance(this)},bind:function(a,b,c){this._elementPrepared||this.prepareElement();var d=this.propertyForAttribute(a);if(d){this.unbind(a);var e=this.bindProperty(d,b,c);return e.path=c,this.reflectPropertyToAttribute(d),this.bindings[a]=e}return this.super(arguments)},asyncUnbindAll:function(){this._unbound||(e.unbind&&console.log("[%s] asyncUnbindAll",this.localName),this._unbindAllJob=this.job(this._unbindAllJob,this.unbindAll,0))},unbindAll:function(){if(!this._unbound){this.unbindAllProperties(),this.super();for(var a=this.shadowRoot;a;)b(a),a=a.olderShadowRoot;this._unbound=!0}},cancelUnbindAll:function(a){return this._unbound?(e.unbind&&console.warn("[%s] already unbound, cannot cancel unbindAll",this.localName),void 0):(e.unbind&&console.log("[%s] cancelUnbindAll",this.localName),this._unbindAllJob&&(this._unbindAllJob=this._unbindAllJob.stop()),a||d(this.shadowRoot,function(a){a.cancelUnbindAll&&a.cancelUnbindAll()}),void 0)}},j=/\{\{([^{}]*)}}/;a.bindPattern=j,a.api.instance.mdv=i}(Polymer),function(a){function b(a){return a.hasOwnProperty("PolymerBase")}function c(){}var d=0,e={PolymerBase:!0,job:Polymer.job,"super":Polymer.super,created:function(){},ready:function(){},createdCallback:function(){this.created(),(this.ownerDocument.defaultView||this.alwaysPrepare||d>0)&&this.prepareElement()},prepareElement:function(){this._elementPrepared=!0,this.observeProperties(),this.copyInstanceAttributes(),this.takeAttributes(),this.addHostListeners(),d++,this.parseDeclarations(this.__proto__),d--,this.ready()},enteredViewCallback:function(){this._elementPrepared||this.prepareElement(),this.cancelUnbindAll(!0),this.enteredView&&this.enteredView()},leftViewCallback:function(){this.preventDispose||this.asyncUnbindAll(),this.leftView&&this.leftView()},enteredDocumentCallback:function(){this.enteredViewCallback()},leftDocumentCallback:function(){this.leftViewCallback()},parseDeclarations:function(a){a&&a.element&&(this.parseDeclarations(a.__proto__),a.parseDeclaration.call(this,a.element))},parseDeclaration:function(a){var b=this.fetchTemplate(a);b&&(this.element.hasAttribute("lightdom")?this.lightFromTemplate(b):this.shadowFromTemplate(b))},fetchTemplate:function(a){return a.querySelector("template")},shadowFromTemplate:function(a){if(a){var b=(this.shadowRoot,this.createShadowRoot());b.applyAuthorStyles=this.applyAuthorStyles,b.resetStyleInheritance=this.resetStyleInheritance;var c=this.instanceTemplate(a);return b.appendChild(c),this.shadowRootReady(b,a),b}},lightFromTemplate:function(a){if(a){var b=this.instanceTemplate(a);return this.appendChild(b),this.shadowRootReady(this,a),b}},shadowRootReady:function(a){this.marshalNodeReferences(a),PointerGestures.register(a)},marshalNodeReferences:function(a){var b=this.$=this.$||{};if(a)for(var c,d=a.querySelectorAll("[id]"),e=0,f=d.length;f>e&&(c=d[e]);e++)b[c.id]=c},attributeChangedCallback:function(a){"class"!==a&&"style"!==a&&this.attributeToProperty(a,this.getAttribute(a)),this.attributeChanged&&this.attributeChanged.apply(this,arguments)},onMutation:function(a,b){var c=new MutationObserver(function(a){b.call(this,c,a),c.disconnect()}.bind(this));c.observe(a,{childList:!0,subtree:!0})}};c.prototype=e,e.constructor=c,a.Base=c,a.isBase=b,a.api.instance.base=e}(Polymer),function(a){function b(a){return a.__proto__}var c=(window.logFlags||{},"element"),d="controller",e={STYLE_SCOPE_ATTRIBUTE:c,installControllerStyles:function(){var a=this.findStyleController();if(a&&!this.scopeHasElementStyle(a,d)){for(var c=b(this),e="";c&&c.element;)e+=c.element.cssTextForScope(d),c=b(c);if(e){var f=this.element.cssTextToScopeStyle(e,d);Polymer.applyStyleToScope(f,a)}}},findStyleController:function(){if(window.ShadowDOMPolyfill)return wrap(document.head);for(var a=this;a.parentNode;)a=a.parentNode;return a===document?document.head:a},scopeHasElementStyle:function(a,b){var d=c+"="+this.localName+"-"+b;return a.querySelector("style["+d+"]")}};a.api.instance.styles=e}(Polymer),function(a){var b={addResolvePathApi:function(){var a=this.elementPath(),b=this.getAttribute("assetpath")||"",c=this.relPath;this.prototype.resolvePath=function(d){var e=d;if(b){var f=b.slice(0,-1);e=c(f,e)}return a+b+e}},elementPath:function(){return this.urlToPath(HTMLImports.getDocumentUrl(this.ownerDocument))},relPath:function(a,b){for(var c=a.split("/"),d=b.split("/"),e=!1;c.length&&d.length&&c[0]===d[0];)c.shift(),d.shift(),e=!0;if(e)for(var f=0;f<c.length;f++)d.unshift("..");return d.join("/")},urlToPath:function(a){if(a){var b=a.split("/");return b.pop(),b.push(""),b.join("/")}return""}};a.api.declaration.path=b}(Polymer),function(a){function b(a,b){if(a){var d=c(a.textContent),e=a.getAttribute(g);e&&d.setAttribute(g,e),b.appendChild(d)}}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){return a&&a.__resource||""}function e(a,b){return n?n.call(a,b):void 0}var f=(window.logFlags||{},a.api.instance.styles),g=f.STYLE_SCOPE_ATTRIBUTE,h="style",i="[rel=stylesheet]",j="global",k="polymer-scope",l={installSheets:function(){this.cacheSheets(),this.cacheStyles(),this.installLocalSheets(),this.installGlobalStyles()},cacheSheets:function(){this.sheets=this.findNodes(i),this.sheets.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},cacheStyles:function(){this.styles=this.findNodes(h+"["+k+"]"),this.styles.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},installLocalSheets:function(){var a=this.sheets.filter(function(a){return!a.hasAttribute(k)}),b=this.templateContent();if(b){var e="";a.forEach(function(a){e+=d(a)+"\n"}),e&&b.insertBefore(c(e),b.firstChild)}},findNodes:function(a,b){var c=this.querySelectorAll(a).array(),d=this.templateContent();if(d){var e=d.querySelectorAll(a).array();c=c.concat(e)}return b?c.filter(b):c},templateContent:function(){var a=this.querySelector("template");return a&&templateContent(a)},installGlobalStyles:function(){var a=this.styleForScope(j);b(a,document.head)},cssTextForScope:function(a){var b="",c="["+k+"="+a+"]",f=function(a){return e(a,c)},g=this.sheets.filter(f);g.forEach(function(a){b+=d(a)+"\n\n"});var h=this.styles.filter(f);return h.forEach(function(a){b+=a.textContent+"\n\n"}),b},styleForScope:function(a){var b=this.cssTextForScope(a);return this.cssTextToScopeStyle(b,a)},cssTextToScopeStyle:function(a,b){if(a){var d=c(a);return d.setAttribute(g,this.getAttribute("name")+"-"+b),d}}},m=HTMLElement.prototype,n=m.matches||m.matchesSelector||m.webkitMatchesSelector||m.mozMatchesSelector;a.api.declaration.styles=l,a.applyStyleToScope=b}(Polymer),function(a){var b=a.api.instance.events,c=(window.logFlags||{},{parseHostEvents:function(){var a=this.prototype.eventDelegates;this.addAttributeDelegates(a)},addAttributeDelegates:function(a){for(var c,d=0;c=this.attributes[d];d++)b.hasEventPrefix(c.name)&&(a[b.removeEventPrefix(c.name)]=c.value.replace("{{","").replace("}}","").trim())},event_translations:{webkitanimationstart:"webkitAnimationStart",webkitanimationend:"webkitAnimationEnd",webkittransitionend:"webkitTransitionEnd",domfocusout:"DOMFocusOut",domfocusin:"DOMFocusIn"}});a.api.declaration.events=c}(Polymer),function(a){var b={inferObservers:function(a){var b,c=a.observe;for(var d in a)"Changed"===d.slice(-7)&&(c||(c=a.observe={}),b=d.slice(0,-7),c[b]=c[b]||d)},optimizePropertyMaps:function(a){if(a.observe){var b=a._observeNames=[];for(var c in a.observe)b.push(c)}if(a.publish){var b=a._publishNames=[];for(var c in a.publish)b.push(c)}},publishProperties:function(a,b){var c=a.publish;c&&(this.requireProperties(c,a,b),a._publishLC=this.lowerCaseMap(c))},requireProperties:function(a,b,c){for(var d in a)void 0===b[d]&&void 0===c[d]&&(b[d]=a[d])},lowerCaseMap:function(a){var b={};for(var c in a)b[c.toLowerCase()]=c;return b}};a.api.declaration.properties=b}(Polymer),function(a){var b="attributes",c={inheritAttributesObjects:function(a){this.inheritObject(a,"publishLC"),this.inheritObject(a,"_instanceAttributes")},publishAttributes:function(a,c){var d=this.getAttribute(b);if(d)for(var e,f=a.publish||(a.publish={}),g=d.split(d.indexOf(",")>=0?",":" "),h=0,i=g.length;i>h;h++)e=g[h].trim(),e&&void 0===f[e]&&void 0===c[e]&&(f[e]=null)},accumulateInstanceAttributes:function(){for(var a,b=this.prototype._instanceAttributes,c=this.attributes,d=0,e=c.length;e>d&&(a=c[d]);d++)this.isInstanceAttribute(a.name)&&(b[a.name]=a.value)},isInstanceAttribute:function(a){return!this.blackList[a]&&"on-"!==a.slice(0,3)},blackList:{name:1,"extends":1,constructor:1,noscript:1}};c.blackList[b]=1,a.api.declaration.attributes=c}(Polymer),function(a){function b(a){if(!Object.__proto__){var b=Object.getPrototypeOf(a);a.__proto__=b,d(b)&&(b.__proto__=Object.getPrototypeOf(b))}}var c=a.api,d=a.isBase,e=a.extend,f={register:function(a,b){this.prototype=this.buildPrototype(a,b),this.prototype.element=this,this.desugar(a,b),this.registerPrototype(a,b),this.publishConstructor()},buildPrototype:function(c,d){var e=a.getRegisteredPrototype(c),f=this.generateBasePrototype(d);return this.publishAttributes(e,f),this.publishProperties(e,f),this.inferObservers(e),this.inheritMetaData(e,f),e=this.chainObject(e,f),this.optimizePropertyMaps(e),b(e),e},inheritMetaData:function(a,b){this.inheritObject("observe",a,b),this.inheritObject("publish",a,b),this.inheritObject("_publishLC",a,b),this.inheritObject("_instanceAttributes",a,b),this.inheritObject("eventDelegates",a,b)},desugar:function(a,b){this.accumulateInstanceAttributes(),this.parseHostEvents(),this.installSheets(),this.adjustShadowElement(),this.addResolvePathApi(),window.ShadowDOMPolyfill&&Platform.ShadowCSS.shimStyling(this.templateContent(),a,b),this.prototype.registerCallback&&this.prototype.registerCallback(this)},adjustShadowElement:function(){if(!window.ShadowDOMPolyfill){var a=this.templateContent();if(a)for(var b,c=a.querySelectorAll("shadow"),d=0,e=c.length;e>d&&(b=c[d]);d++)b.children.length||b.appendChild(document.createElement("content"))}},publishConstructor:function(){var a=this.getAttribute("constructor");a&&(window[a]=this.ctor)},generateBasePrototype:function(a){var b=this.findBasePrototype(a);if(!b){var b=HTMLElement.getPrototypeForTag(a);b=this.ensureBaseApi(b),memoizedBases[a]=b}return b},findBasePrototype:function(a){return memoizedBases[a]},ensureBaseApi:function(a){if(!a.PolymerBase){a=Object.create(a);for(var b in c.instance)e(a,c.instance[b])}return a},inheritObject:function(a,b,c){var d=b[a]||{};b[a]=this.chainObject(d,c[a])},registerPrototype:function(a,b){var c={prototype:this.prototype},d=this.findTypeExtension(b);d&&(c.extends=d),this.ctor=document.register(a,c),this.prototype.constructor=this.ctor,HTMLElement.register(a,this.prototype)},findTypeExtension:function(a){if(a&&a.indexOf("-")<0)return a;var b=this.findBasePrototype(a);return b.element?this.findTypeExtension(b.element.extends):void 0}};f.chainObject=Object.__proto__?function(a,b){return a&&b&&a!==b&&(a.__proto__=b),a}:function(a,b){if(a&&b&&a!==b){var c=Object.create(b);a=e(c,a)}return a},memoizedBases={},c.declaration.prototype=f}(Polymer),function(a){function b(a,b){k[a]=b||{},d(a)}function c(a){return k[a]}function d(a){l[a]&&(l[a].registerWhenReady(),delete l[a])}function e(a){n[a]=!0;var b=m[a];b&&(b.forEach(function(a){a.registerWhenReady()}),delete m[a])}function f(a){return n[a]}function g(a){window.HTMLImports&&!HTMLImports.readyTime?addEventListener("HTMLImportsLoaded",a):a()}var h=a.extend,i=a.api.declaration,j=h(Object.create(HTMLElement.prototype),{createdCallback:function(){this.name=this.getAttribute("name"),this.extends=this.getAttribute("extends"),this.registerWhenReady()},registerWhenReady:function(){if(!this.waitingForPrototype(this.name)){var a=this.extends;this.waitingForExtendee(a)||(document.contains(this)?g(function(){this._register(a)}.bind(this)):this._register(a))}},_register:function(a){this.register(this.name,a),e(this.name)},waitingForPrototype:function(a){if(!c(a)){if(l[a]=this,this.hasAttribute("noscript"))if(window.CustomElements&&!CustomElements.useNative)b(a);else{var d=document.createElement("script");d.textContent="Polymer('"+a+"');",this.appendChild(d)}return!0}},waitingForExtendee:function(a){return a&&a.indexOf("-")>=0&&!f(a)?((m[a]=m[a]||[]).push(this),!0):void 0}});Object.keys(i).forEach(function(a){h(j,i[a])});var k={},l={},m={},n={};a.getRegisteredPrototype=c,h(b,a),window.Polymer=b,document.register("polymer-element",{prototype:j})}(Polymer);
+<script>/**
+ * @license
+ * Copyright (c) 2012-2014 The Polymer Authors. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// @version: 0.2.1-c690632
+Polymer={},"function"==typeof window.Polymer&&(Polymer={}),function(a){function b(a,b){return a&&b&&Object.getOwnPropertyNames(b).forEach(function(c){var d=Object.getOwnPropertyDescriptor(b,c);d&&(Object.defineProperty(a,c,d),"function"==typeof d.value&&(d.value.nom=c))}),a}a.extend=b}(Polymer),function(a){function b(a,b,d){return a?a.stop():a=new c(this),a.go(b,d),a}var c=function(a){this.context=a,this.boundComplete=this.complete.bind(this)};c.prototype={go:function(a,b){this.callback=a;var c;b?(c=setTimeout(this.boundComplete,b),this.handle=function(){clearTimeout(c)}):(c=requestAnimationFrame(this.boundComplete),this.handle=function(){cancelAnimationFrame(c)})},stop:function(){this.handle&&(this.handle(),this.handle=null)},complete:function(){this.handle&&(this.stop(),this.callback.call(this.context))}},a.job=b}(Polymer),function(){var a={};HTMLElement.register=function(b,c){a[b]=c},HTMLElement.getPrototypeForTag=function(b){var c=b?a[b]:HTMLElement.prototype;return c||Object.getPrototypeOf(document.createElement(b))};var b=Event.prototype.stopPropagation;Event.prototype.stopPropagation=function(){this.cancelBubble=!0,b.apply(this,arguments)}}(Polymer),function(a){function b(a){var c=b.caller,g=c.nom,h=c._super;if(h||(g||(g=c.nom=e.call(this,c)),g||console.warn("called super() on a method not installed declaratively (has no .nom property)"),h=d(c,g,f(this))),h){var i=h[g];return i._super||d(i,g,h),i.apply(this,a||[])}}function c(a,b,c){for(;a;){if(a[b]!==c&&a[b])return a;a=f(a)}}function d(a,b,d){return a._super=c(d,b,a),a._super&&(a._super[b].nom=b),a._super}function e(a){for(var b=this.__proto__;b&&b!==HTMLElement.prototype;){for(var c,d=Object.getOwnPropertyNames(b),e=0,f=d.length;f>e&&(c=d[e]);e++){var g=Object.getOwnPropertyDescriptor(b,c);if("function"==typeof g.value&&g.value===a)return c}b=b.__proto__}}function f(a){return a.__proto__}a.super=b}(Polymer),function(a){function b(a,b){var d=typeof b;return b instanceof Date&&(d="date"),c[d](a,b)}var c={string:function(a){return a},date:function(a){return new Date(Date.parse(a)||Date.now())},"boolean":function(a){return""===a?!0:"false"===a?!1:!!a},number:function(a){var b=parseFloat(a);return 0===b&&(b=parseInt(a)),isNaN(b)?a:b},object:function(a,b){if(null===b)return a;try{return JSON.parse(a.replace(/'/g,'"'))}catch(c){return a}},"function":function(a,b){return b}};a.deserializeValue=b}(Polymer),function(a){var b=a.extend,c={};c.declaration={},c.instance={},c.publish=function(a,c){for(var d in a)b(c,a[d])},a.api=c}(Polymer),function(a){var b={async:function(a,b,c){Platform.flush(),b=b&&b.length?b:[b];var d=function(){(this[a]||a).apply(this,b)}.bind(this),e=c?setTimeout(d,c):requestAnimationFrame(d);return c?e:~e},cancelAsync:function(a){0>a?cancelAnimationFrame(~a):clearTimeout(a)},fire:function(a,b,c,d,e){var f=c||this,b=b||{},g=new CustomEvent(a,{bubbles:void 0!==d?d:!0,cancelable:void 0!==e?e:!0,detail:b});return f.dispatchEvent(g),g},asyncFire:function(){this.async("fire",arguments)},classFollows:function(a,b,c){b&&b.classList.remove(c),a&&a.classList.add(c)}},c=function(){},d={};b.asyncMethod=b.async,a.api.instance.utils=b,a.nop=c,a.nob=d}(Polymer),function(a){var b=window.logFlags||{},c="on-",d={EVENT_PREFIX:c,addHostListeners:function(){var a=this.eventDelegates;b.events&&Object.keys(a).length>0&&console.log("[%s] addHostListeners:",this.localName,a);var d,e,f=this;for(var g in a)e=c+g,(d=PolymerExpressions.prepareEventBinding(Path.get(a[g]),e,{resolveEventHandler:function(a,b){var c=b.getValueFrom(f);return c?c.bind(f):void 0}}))(this,this,!1)},dispatchMethod:function(a,c,d){if(a){b.events&&console.group("[%s] dispatch [%s]",a.localName,c);var e="function"==typeof c?c:a[c];e&&e[d?"apply":"call"](a,d),b.events&&console.groupEnd(),Platform.flush()}}};a.api.instance.events=d}(Polymer),function(a){var b={copyInstanceAttributes:function(){var a=this._instanceAttributes;for(var b in a)this.hasAttribute(b)||this.setAttribute(b,a[b])},takeAttributes:function(){if(this._publishLC)for(var a,b=0,c=this.attributes,d=c.length;(a=c[b])&&d>b;b++)this.attributeToProperty(a.name,a.value)},attributeToProperty:function(b,c){var b=this.propertyForAttribute(b);if(b){if(c&&c.search(a.bindPattern)>=0)return;var d=this[b],c=this.deserializeValue(c,d);c!==d&&(this[b]=c)}},propertyForAttribute:function(a){var b=this._publishLC&&this._publishLC[a];return b},deserializeValue:function(b,c){return a.deserializeValue(b,c)},serializeValue:function(a,b){return"boolean"===b?a?"":void 0:"object"!==b&&"function"!==b&&void 0!==a?a:void 0},reflectPropertyToAttribute:function(a){var b=typeof this[a],c=this.serializeValue(this[a],b);void 0!==c?this.setAttribute(a,c):"boolean"===b&&this.removeAttribute(a)}};a.api.instance.attributes=b}(Polymer),function(a){function b(a,b,d){c.bind&&console.log(e,inB.localName||"object",inPath,a.localName,b);var f=d.discardChanges();return(null===f||void 0===f)&&d.setValue(a[b]),Observer.defineComputedProperty(a,b,d)}var c=window.logFlags||{},d={observeProperties:function(){var a=this._observeNames,b=this._publishNames;if(a&&a.length||b&&b.length){var c=this._propertyObserver=new CompoundObserver;this.registerObservers([c]);for(var d,e=0,f=a.length;f>e&&(d=a[e]);e++){c.addPath(this,d);var g=Object.getOwnPropertyDescriptor(this.__proto__,d);g&&g.value&&this.observeArrayValue(d,g.value,null)}for(var d,e=0,f=b.length;f>e&&(d=b[e]);e++)this.observe&&void 0!==this.observe[d]||c.addPath(this,d);c.open(this.notifyPropertyChanges,this)}},notifyPropertyChanges:function(a,b,c){var d,e,f={};for(var g in b)d=c[2*g+1],void 0!==this.publish[d]&&this.reflectPropertyToAttribute(d),e=this.observe[d],e&&(this.observeArrayValue(d,a[g],b[g]),f[e]||(f[e]=!0,this.invokeMethod(e,[b[g],a[g],arguments])))},observeArrayValue:function(a,b,d){var e=this.observe[a];if(e&&(Array.isArray(d)&&(c.observe&&console.log("[%s] observeArrayValue: unregister observer [%s]",this.localName,a),this.closeNamedObserver(a+"__array")),Array.isArray(b))){c.observe&&console.log("[%s] observeArrayValue: register observer [%s]",this.localName,a,b);var f=new ArrayObserver(b);f.open(function(a,b){this.invokeMethod(e,[b])},this),this.registerNamedObserver(a+"__array",f)}},bindProperty:function(a,c){return b(this,a,c)},invokeMethod:function(a,b){var c=this[a]||a;"function"==typeof c&&c.apply(this,b)},registerObservers:function(a){this._observers.push(a)},closeObservers:function(){for(var a=0,b=this._observers.length;b>a;a++)this.closeObserverArray(this._observers[a]);this._observers=[]},closeObserverArray:function(a){for(var b,c=0,d=a.length;d>c;c++)b=a[c],b&&b.close&&b.close()},registerNamedObserver:function(a,b){var c=this._namedObservers||(this._namedObservers={});c[a]=b},closeNamedObserver:function(a){var b=this._namedObservers;return b&&b[a]?(b[a].close(),b[a]=null,!0):void 0},closeNamedObservers:function(){if(this._namedObservers){for(var a,b,c=Object.keys(this._namedObservers),d=0,e=c.length;e>d&&(a=c[d]);d++)b=this._namedObservers[a],b.close();this._namedObservers={}}}},e="[%s]: bindProperties: [%s] to [%s].[%s]";a.api.instance.properties=d}(Polymer),function(a){function b(a){for(;a.parentNode;){if(a.lightDomController)return a;a=a.parentNode}return a.host}var c=window.logFlags||0,d=(a.api.instance.events,new PolymerExpressions);d.resolveEventHandler=function(a,c,d){var e=b(d);if(e){var f=c.getValueFrom(e);if(f)return f.bind(e)}};var e={syntax:d,instanceTemplate:function(a){var b=a.createInstance(this,this.syntax);return this.registerObservers(b.bindings_),b},bind:function(a,b){this._elementPrepared||this.prepareElement();var c=this.propertyForAttribute(a);if(c){var d=this.bindProperty(c,b);return this.reflectPropertyToAttribute(c),Platform.enableBindingsReflection&&(d.path=b.path_,this.bindings_=this.bindings_||{},this.bindings_[a]=d),d}return this.mixinSuper(arguments)},asyncUnbindAll:function(){this._unbound||(c.unbind&&console.log("[%s] asyncUnbindAll",this.localName),this._unbindAllJob=this.job(this._unbindAllJob,this.unbindAll,0))},unbindAll:function(){this._unbound||(this.closeObservers(),this.closeNamedObservers(),this._unbound=!0)},cancelUnbindAll:function(){return this._unbound?void(c.unbind&&console.warn("[%s] already unbound, cannot cancel unbindAll",this.localName)):(c.unbind&&console.log("[%s] cancelUnbindAll",this.localName),void(this._unbindAllJob&&(this._unbindAllJob=this._unbindAllJob.stop())))}},f=/\{\{([^{}]*)}}/;a.bindPattern=f,a.api.instance.mdv=e}(Polymer),function(a){function b(a){return a.hasOwnProperty("PolymerBase")}function c(){}var d=0,e={PolymerBase:!0,job:Polymer.job,"super":Polymer.super,created:function(){},ready:function(){},createdCallback:function(){this.created(),(this.ownerDocument.defaultView||this.alwaysPrepare||d>0)&&this.prepareElement()},prepareElement:function(){this._elementPrepared=!0,this.shadowRoots={},this._observers=[],this.observeProperties(),this.copyInstanceAttributes(),this.takeAttributes(),this.addHostListeners(),d++,this.parseDeclarations(this.__proto__),d--,this.removeAttribute("unresolved"),this.ready()},attachedCallback:function(){this._elementPrepared||this.prepareElement(),this.cancelUnbindAll(!0),this.attached&&this.attached(),this.enteredView&&this.enteredView(),this.hasBeenAttached||(this.hasBeenAttached=!0,this.domReady&&this.async("domReady"))},detachedCallback:function(){this.preventDispose||this.asyncUnbindAll(),this.detached&&this.detached(),this.leftView&&this.leftView()},enteredViewCallback:function(){this.attachedCallback()},leftViewCallback:function(){this.detachedCallback()},enteredDocumentCallback:function(){this.attachedCallback()},leftDocumentCallback:function(){this.detachedCallback()},parseDeclarations:function(a){a&&a.element&&(this.parseDeclarations(a.__proto__),a.parseDeclaration.call(this,a.element))},parseDeclaration:function(a){var b=this.fetchTemplate(a);if(b){var c=this.shadowFromTemplate(b);this.shadowRoots[a.name]=c}},fetchTemplate:function(a){return a.querySelector("template")},shadowFromTemplate:function(a){if(a){var b=this.createShadowRoot();b.resetStyleInheritance=this.resetStyleInheritance;var c=this.instanceTemplate(a);return b.appendChild(c),this.shadowRootReady(b,a),b}},lightFromTemplate:function(a){if(a){this.lightDomController=!0;var b=this.instanceTemplate(a);return this.appendChild(b),this.shadowRootReady(this,a),b}},shadowRootReady:function(a){this.marshalNodeReferences(a),PointerGestures.register(a)},marshalNodeReferences:function(a){var b=this.$=this.$||{};if(a)for(var c,d=a.querySelectorAll("[id]"),e=0,f=d.length;f>e&&(c=d[e]);e++)b[c.id]=c},attributeChangedCallback:function(a){"class"!==a&&"style"!==a&&this.attributeToProperty(a,this.getAttribute(a)),this.attributeChanged&&this.attributeChanged.apply(this,arguments)},onMutation:function(a,b){var c=new MutationObserver(function(a){b.call(this,c,a),c.disconnect()}.bind(this));c.observe(a,{childList:!0,subtree:!0})}};c.prototype=e,e.constructor=c,a.Base=c,a.isBase=b,a.api.instance.base=e}(Polymer),function(a){function b(a){return a.__proto__}function c(a,b){var c="",d=!1;b&&(c=b.localName,d=b.hasAttribute("is"));var e=Platform.ShadowCSS.makeScopeSelector(c,d);return Platform.ShadowCSS.shimCssText(a,e)}var d=(window.logFlags||{},"element"),e="controller",f={STYLE_SCOPE_ATTRIBUTE:d,installControllerStyles:function(){var a=this.findStyleScope();if(a&&!this.scopeHasNamedStyle(a,this.localName)){for(var c=b(this),d="";c&&c.element;)d+=c.element.cssTextForScope(e),c=b(c);d&&this.installScopeCssText(d,a)}},installScopeStyle:function(a,b,c){var c=this.findStyleScope(c),b=b||"";if(c&&!this.scopeHasNamedStyle(c,this.localName+b)){var d="";if(a instanceof Array)for(var e,f=0,g=a.length;g>f&&(e=a[f]);f++)d+=e.textContent+"\n\n";else d=a.textContent;this.installScopeCssText(d,c,b)}},installScopeCssText:function(a,b,d){if(b=b||this.findStyleScope(),d=d||"",b){window.ShadowDOMPolyfill&&(a=c(a,b.host));var f=this.element.cssTextToScopeStyle(a,e);Polymer.applyStyleToScope(f,b),b._scopeStyles[this.localName+d]=!0}},findStyleScope:function(a){for(var b=a||this;b.parentNode;)b=b.parentNode;return b},scopeHasNamedStyle:function(a,b){return a._scopeStyles=a._scopeStyles||{},a._scopeStyles[b]}};a.api.instance.styles=f}(Polymer),function(a){function b(a,b){if(f[a])throw"Already registered (Polymer) prototype for element "+a;e(a,b),d(a)}function c(a,b){h[a]=b}function d(a){h[a]&&(h[a].registerWhenReady(),delete h[a])}function e(a,b){return i[a]=b||{}}function f(a){return i[a]}var g=a.extend,h=(a.api,{}),i={};a.getRegisteredPrototype=f,a.waitingForPrototype=c,window.Polymer=b,g(Polymer,a);var j=Platform.deliverDeclarations();if(j)for(var k,l=0,m=j.length;m>l&&(k=j[l]);l++)b.apply(null,k)}(Polymer),function(a){var b={resolveElementPaths:function(a){Platform.urlResolver.resolveDom(a)},addResolvePathApi:function(){var a=this.getAttribute("assetpath")||"",b=new URL(a,this.ownerDocument.baseURI);this.prototype.resolvePath=function(a,c){var d=new URL(a,c||b);return d.href}}};a.api.declaration.path=b}(Polymer),function(a){function b(a,b){var c=new URL(a.getAttribute("href"),b).href;return"@import '"+c+"';"}function c(a,b){if(a){b===document&&(b=document.head),window.ShadowDOMPolyfill&&(b=document.head);var c=d(a.textContent),e=a.getAttribute(h);e&&c.setAttribute(h,e),b.appendChild(c)}}function d(a,b){b=b||document,b=b.createElement?b:b.ownerDocument;var c=b.createElement("style");return c.textContent=a,c}function e(a){return a&&a.__resource||""}function f(a,b){return p?p.call(a,b):void 0}var g=(window.logFlags||{},a.api.instance.styles),h=g.STYLE_SCOPE_ATTRIBUTE,i="style",j="@import",k="link[rel=stylesheet]",l="global",m="polymer-scope",n={loadStyles:function(a){var b=this.templateContent();b&&this.convertSheetsToStyles(b);var c=this.findLoadableStyles(b);c.length?Platform.styleResolver.loadStyles(c,a):a&&a()},convertSheetsToStyles:function(a){for(var c,e,f=a.querySelectorAll(k),g=0,h=f.length;h>g&&(c=f[g]);g++)e=d(b(c,this.ownerDocument.baseURI),this.ownerDocument),this.copySheetAttributes(e,c),c.parentNode.replaceChild(e,c)},copySheetAttributes:function(a,b){for(var c,d=0,e=b.attributes,f=e.length;(c=e[d])&&f>d;d++)"rel"!==c.name&&"href"!==c.name&&a.setAttribute(c.name,c.value)},findLoadableStyles:function(a){var b=[];if(a)for(var c,d=a.querySelectorAll(i),e=0,f=d.length;f>e&&(c=d[e]);e++)c.textContent.match(j)&&b.push(c);return b},installSheets:function(){this.cacheSheets(),this.cacheStyles(),this.installLocalSheets(),this.installGlobalStyles()},cacheSheets:function(){this.sheets=this.findNodes(k),this.sheets.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},cacheStyles:function(){this.styles=this.findNodes(i+"["+m+"]"),this.styles.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},installLocalSheets:function(){var a=this.sheets.filter(function(a){return!a.hasAttribute(m)}),b=this.templateContent();if(b){var c="";if(a.forEach(function(a){c+=e(a)+"\n"}),c){var f=d(c,this.ownerDocument);b.insertBefore(f,b.firstChild)}}},findNodes:function(a,b){var c=this.querySelectorAll(a).array(),d=this.templateContent();if(d){var e=d.querySelectorAll(a).array();c=c.concat(e)}return b?c.filter(b):c},templateContent:function(){var a=this.querySelector("template");return a&&templateContent(a)},installGlobalStyles:function(){var a=this.styleForScope(l);c(a,document.head)},cssTextForScope:function(a){var b="",c="["+m+"="+a+"]",d=function(a){return f(a,c)},g=this.sheets.filter(d);g.forEach(function(a){b+=e(a)+"\n\n"});var h=this.styles.filter(d);return h.forEach(function(a){b+=a.textContent+"\n\n"}),b},styleForScope:function(a){var b=this.cssTextForScope(a);return this.cssTextToScopeStyle(b,a)},cssTextToScopeStyle:function(a,b){if(a){var c=d(a);return c.setAttribute(h,this.getAttribute("name")+"-"+b),c}}},o=HTMLElement.prototype,p=o.matches||o.matchesSelector||o.webkitMatchesSelector||o.mozMatchesSelector;a.api.declaration.styles=n,a.applyStyleToScope=c}(Polymer),function(a){var b=(window.logFlags||{},a.api.instance.events),c=b.EVENT_PREFIX,d={parseHostEvents:function(){var a=this.prototype.eventDelegates;this.addAttributeDelegates(a)},addAttributeDelegates:function(a){for(var b,c=0;b=this.attributes[c];c++)this.hasEventPrefix(b.name)&&(a[this.removeEventPrefix(b.name)]=b.value.replace("{{","").replace("}}","").trim())},hasEventPrefix:function(a){return a&&"o"===a[0]&&"n"===a[1]&&"-"===a[2]},removeEventPrefix:function(a){return a.slice(e)}},e=c.length;a.api.declaration.events=d}(Polymer),function(a){var b={inferObservers:function(a){var b,c=a.observe;for(var d in a)"Changed"===d.slice(-7)&&(c||(c=a.observe={}),b=d.slice(0,-7),c[b]=c[b]||d)},explodeObservers:function(a){var b=a.observe;if(b){var c={};for(var d in b)for(var e,f=d.split(" "),g=0;e=f[g];g++)c[e]=b[d];a.observe=c}},optimizePropertyMaps:function(a){if(a.observe){var b=a._observeNames=[];for(var c in a.observe)for(var d,e=c.split(" "),f=0;d=e[f];f++)b.push(d)}if(a.publish){var b=a._publishNames=[];for(var c in a.publish)b.push(c)}},publishProperties:function(a,b){var c=a.publish;c&&(this.requireProperties(c,a,b),a._publishLC=this.lowerCaseMap(c))},requireProperties:function(a,b,c){for(var d in a)void 0===b[d]&&void 0===c[d]&&(b[d]=a[d])},lowerCaseMap:function(a){var b={};for(var c in a)b[c.toLowerCase()]=c;return b}};a.api.declaration.properties=b}(Polymer),function(a){var b="attributes",c=/\s|,/,d={inheritAttributesObjects:function(a){this.inheritObject(a,"publishLC"),this.inheritObject(a,"_instanceAttributes")},publishAttributes:function(a,d){var e=this.getAttribute(b);if(e)for(var f,g=a.publish||(a.publish={}),h=e.split(c),i=0,j=h.length;j>i;i++)f=h[i].trim(),f&&void 0===g[f]&&void 0===d[f]&&(g[f]=null)},accumulateInstanceAttributes:function(){for(var a,b=this.prototype._instanceAttributes,c=this.attributes,d=0,e=c.length;e>d&&(a=c[d]);d++)this.isInstanceAttribute(a.name)&&(b[a.name]=a.value)},isInstanceAttribute:function(a){return!this.blackList[a]&&"on-"!==a.slice(0,3)},blackList:{name:1,"extends":1,constructor:1,noscript:1,assetpath:1,"cache-csstext":1}};d.blackList[b]=1,a.api.declaration.attributes=d}(Polymer),function(a){function b(a){if(!Object.__proto__){var b=Object.getPrototypeOf(a);a.__proto__=b,d(b)&&(b.__proto__=Object.getPrototypeOf(b))}}var c=a.api,d=a.isBase,e=a.extend,f={register:function(a,b){this.buildPrototype(a,b),this.registerPrototype(a,b),this.publishConstructor()},buildPrototype:function(b,c){var d=a.getRegisteredPrototype(b),e=this.generateBasePrototype(c);this.desugarBeforeChaining(d,e),this.prototype=this.chainPrototypes(d,e),this.desugarAfterChaining(b,c)},desugarBeforeChaining:function(a,b){a.element=this,this.publishAttributes(a,b),this.publishProperties(a,b),this.inferObservers(a),this.explodeObservers(a)},chainPrototypes:function(a,c){this.inheritMetaData(a,c);var d=this.chainObject(a,c);return b(d),d},inheritMetaData:function(a,b){this.inheritObject("observe",a,b),this.inheritObject("publish",a,b),this.inheritObject("_publishLC",a,b),this.inheritObject("_instanceAttributes",a,b),this.inheritObject("eventDelegates",a,b)},desugarAfterChaining:function(a,b){this.optimizePropertyMaps(this.prototype),this.installSheets(),this.resolveElementPaths(this),this.accumulateInstanceAttributes(),this.parseHostEvents(),this.addResolvePathApi(),window.ShadowDOMPolyfill&&Platform.ShadowCSS.shimStyling(this.templateContent(),a,b),this.prototype.registerCallback&&this.prototype.registerCallback(this)},publishConstructor:function(){var a=this.getAttribute("constructor");a&&(window[a]=this.ctor)},generateBasePrototype:function(a){var b=this.findBasePrototype(a);if(!b){var b=HTMLElement.getPrototypeForTag(a);b=this.ensureBaseApi(b),g[a]=b}return b},findBasePrototype:function(a){return g[a]},ensureBaseApi:function(a){if(a.PolymerBase)return a;var b=Object.create(a);return c.publish(c.instance,b),this.mixinMethod(b,a,c.instance.mdv,"bind"),b},mixinMethod:function(a,b,c,d){var e=function(a){return b[d].apply(this,a)};a[d]=function(){return this.mixinSuper=e,c[d].apply(this,arguments)}},inheritObject:function(a,b,c){var d=b[a]||{};b[a]=this.chainObject(d,c[a])},registerPrototype:function(a,b){var c={prototype:this.prototype},d=this.findTypeExtension(b);d&&(c.extends=d),HTMLElement.register(a,this.prototype),this.ctor=document.registerElement(a,c)},findTypeExtension:function(a){if(a&&a.indexOf("-")<0)return a;var b=this.findBasePrototype(a);return b.element?this.findTypeExtension(b.element.extends):void 0}},g={};f.chainObject=Object.__proto__?function(a,b){return a&&b&&a!==b&&(a.__proto__=b),a}:function(a,b){if(a&&b&&a!==b){var c=Object.create(b);a=e(c,a)}return a},c.declaration.prototype=f}(Polymer),function(a){function b(a){return document.contains(a)?g:f}function c(){return f.length?f[0]:g[0]}function d(a){e.waitToReady=!0,CustomElements.ready=!1,HTMLImports.whenImportsReady(function(){e.addReadyCallback(a),e.waitToReady=!1,e.check()})}var e={wait:function(a,b,c){return-1===this.indexOf(a)&&(this.add(a),a.__check=b,a.__go=c),0!==this.indexOf(a)},add:function(a){b(a).push(a)},indexOf:function(a){var c=b(a).indexOf(a);return c>=0&&document.contains(a)&&(c+=HTMLImports.useNative||HTMLImports.ready?f.length:1e9),c},go:function(a){var b=this.remove(a);b&&(b.__go.call(b),b.__check=b.__go=null,this.check())},remove:function(a){var c=this.indexOf(a);if(0===c)return b(a).shift()},check:function(){var a=this.nextElement();return a&&a.__check.call(a),this.canReady()?(this.ready(),!0):void 0},nextElement:function(){return c()},canReady:function(){return!this.waitToReady&&this.isEmpty()},isEmpty:function(){return!f.length&&!g.length},ready:function(){if(CustomElements.ready===!1&&(CustomElements.upgradeDocumentTree(document),CustomElements.ready=!0),h)for(var a;h.length;)(a=h.shift())()},addReadyCallback:function(a){a&&h.push(a)},waitToReady:!0},f=[],g=[],h=[];document.addEventListener("WebComponentsReady",function(){CustomElements.ready=!1}),a.queue=e,a.whenPolymerReady=d}(Polymer),function(a){function b(a,b){a?(document.head.appendChild(a),d(b)):b&&b()}function c(a,c){if(a&&a.length){for(var d,e,f=document.createDocumentFragment(),g=0,h=a.length;h>g&&(d=a[g]);g++)e=document.createElement("link"),e.rel="import",e.href=d,f.appendChild(e);b(f,c)}else c&&c()}var d=a.whenPolymerReady;a.import=c,a.importElements=b}(Polymer),function(a){function b(a){return Boolean(HTMLElement.getPrototypeForTag(a))}function c(a){return a&&a.indexOf("-")>=0}var d=a.extend,e=a.api,f=a.queue,g=a.whenPolymerReady,h=a.getRegisteredPrototype,i=a.waitingForPrototype,j=d(Object.create(HTMLElement.prototype),{createdCallback:function(){this.getAttribute("name")&&this.init()},init:function(){this.name=this.getAttribute("name"),this.extends=this.getAttribute("extends"),this.loadResources(),this.registerWhenReady()},registerWhenReady:function(){this.registered||this.waitingForPrototype(this.name)||this.waitingForQueue()||this.waitingForResources()||f.go(this)},_register:function(){c(this.extends)&&!b(this.extends)&&console.warn("%s is attempting to extend %s, an unregistered element or one that was not registered with Polymer.",this.name,this.extends),this.register(this.name,this.extends),this.registered=!0},waitingForPrototype:function(a){return h(a)?void 0:(i(a,this),this.handleNoScript(a),!0)},handleNoScript:function(a){if(this.hasAttribute("noscript")&&!this.noscript)if(this.noscript=!0,window.CustomElements&&!CustomElements.useNative)Polymer(a);else{var b=document.createElement("script");b.textContent="Polymer('"+a+"');",this.appendChild(b)}},waitingForResources:function(){return this._needsResources},waitingForQueue:function(){return f.wait(this,this.registerWhenReady,this._register)},loadResources:function(){this._needsResources=!0,this.loadStyles(function(){this._needsResources=!1,this.registerWhenReady()}.bind(this))}});e.publish(e.declaration,j),a.getRegisteredPrototype=h,g(function(){document.body.removeAttribute("unresolved"),document.dispatchEvent(new CustomEvent("polymer-ready",{bubbles:!0}))}),document.registerElement("polymer-element",{prototype:j})}(Polymer);
 //# sourceMappingURL=polymer.js.map</script>
 <!-- <link rel="import" href="../polymer-dev/polymer.html"> -->
 <!DOCTYPE html>
diff --git a/tools/perf/page_sets/key_silk_cases/old_inbox_app.html b/tools/perf/page_sets/key_silk_cases/old_inbox_app.html
index 55607b7..3925911 100644
--- a/tools/perf/page_sets/key_silk_cases/old_inbox_app.html
+++ b/tools/perf/page_sets/key_silk_cases/old_inbox_app.html
@@ -7,40 +7,44 @@
 <html>
   <head>
     <title>app-widgets</title>
-    <script>// Copyright (c) 2012 The Polymer Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-function PointerGestureEvent(a,b){var c=b||{},d=document.createEvent("Event"),e={bubbles:Boolean(c.bubbles)===c.bubbles||!0,cancelable:Boolean(c.cancelable)===c.cancelable||!0};d.initEvent(a,e.bubbles,e.cancelable);for(var f,g=Object.keys(c),h=0;h<g.length;h++)f=g[h],d[f]=c[f];return d.preventTap=this.preventTap,d}"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),function(a){"use strict";function b(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={};if(Object.observe(c,a),c.id=1,c.id=2,delete c.id,Object.deliverChangeRecords(a),3!==b.length)return!1;if("new"==b[0].type&&"updated"==b[1].type&&"deleted"==b[2].type)F="new",G="updated",H="reconfigured",I="deleted";else if("add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type)return console.error("Unexpected change record names for Object.observe. Using dirty-checking instead"),!1;return Object.unobserve(c,a),c=[0],Array.observe(c,a),c[1]=1,c.length=0,Object.deliverChangeRecords(a),2!=b.length?!1:b[0].type!=J||b[1].type!=J?!1:(Array.unobserve(c,a),!0)}function c(){if(a.document&&"securityPolicy"in a.document&&!a.document.securityPolicy.allowsEval)return!1;try{var b=new Function("","return true;");return b()}catch(c){return!1}}function d(a){return+a===a>>>0}function e(a){return+a}function f(a){return a===Object(a)}function g(a,b){return a===b?0!==a||1/a===1/b:M(a)&&M(b)?!0:a!==a&&b!==b}function h(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:U.test(a))}function i(a,b){if(b!==V)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:d(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),L&&!K&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn()),void 0)}function j(a){if(a instanceof i)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=W[a];if(b)return b;if(!h(a))return X;var b=new i(a,V);return W[a]=b,b}function k(b){for(var c=0;Y>c&&b.check_();)b.report_(),c++;a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=c)}function l(a){for(var b in a)return!1;return!0}function m(a){return l(a.added)&&l(a.removed)&&l(a.changed)}function n(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function o(a,b){var c=b||(Array.isArray(a)?[]:{});for(var d in a)c[d]=a[d];return Array.isArray(a)&&(c.length=a.length),c}function p(a,b,c){if(this.closed_=!1,this.object_=a,this.callback=b,this.target=c,this.reporting_=!0,K){var d=this;this.boundInternalCallback_=function(a){d.internalCallback_(a)}}q(this)}function q(a){$&&(Z.push(a),p._allObserversCount++)}function r(a,b,c){p.call(this,a,b,c),this.connect_(),this.sync_(!0)}function s(a,b,c){if(!Array.isArray(a))throw Error("Provided object is not an Array");r.call(this,a,b,c)}function t(a){this.arr=[],this.callback=a,this.isObserved=!0}function u(a,b,c,d,e,g){var b=b instanceof i?b:j(b);return b.valid&&b.length&&f(a)?(p.call(this,a,c,d),this.transformFn_=e,this.setValueFn_=g,this.path_=b,this.connect_(),this.sync_(!0),void 0):(this.value_=b.getValueFrom(a),this.value=e?e(this.value_):this.value_,this.closed_=!0,void 0)}function v(a,b,c,d){p.call(this,void 0,a,b),this.transformFn_=c,this.setValueFn_=d,this.observed_=[],this.values_=[],this.value=void 0,this.oldValue=void 0,this.oldValues_=void 0,this.changeFlags_=void 0,this.started_=!1}function w(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function x(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];db[g.type]?(g.name in c||(c[g.name]=g.oldValue),g.type!=G&&(g.type!=F?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function y(a,b,c){return{index:a,removed:b,addedCount:c}}function z(){}function A(a,b,c,d,e,f){return ib.calcSplices(a,b,c,d,e,f)}function B(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function C(a,b,c,d){for(var e=y(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=B(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function D(a,b){for(var c=[],f=0;f<b.length;f++){var g=b[f];switch(g.type){case J:C(c,g.index,g.removed.slice(),g.addedCount);break;case F:case G:case I:if(!d(g.name))continue;var h=e(g.name);if(0>h)continue;C(c,h,[g.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(g))}}return c}function E(a,b){var c=[];return D(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?(b.removed[0]!==a[b.index]&&c.push(b),void 0):(c=c.concat(A(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)),void 0)}),c}var F="add",G="update",H="reconfigure",I="delete",J="splice",K=b(),L=c(),M=a.Number.isNaN||function(b){return"number"==typeof b&&a.isNaN(b)},N="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},O="[$_a-zA-Z]",P="[$_a-zA-Z0-9]",Q=O+"+"+P+"*",R="(?:[0-9]|[1-9]+[0-9]+)",S="(?:"+Q+"|"+R+")",T="(?:"+S+")(?:\\s*\\.\\s*"+S+")*",U=new RegExp("^"+T+"$"),V={},W={};i.get=j,i.prototype=N({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a,b){for(var c=0;c<this.length;c++){if(null==a)return;b&&b.observe(a),a=a[this[c]]}return a},compiledGetValueFromFn:function(){var a=this.map(function(a){return d(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var e=0;e<this.length-1;e++){{this[e]}c+=a[e],b+=" &&\n     "+c+" != null"}return b+=")\n",c+=a[e],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!f(a))return!1;a=a[this[c]]}return f(a)?(a[this[c]]=b,!0):!1}});var X=new i("",V);X.valid=!1,X.getValueFrom=X.setValueFrom=function(){};var Y=1e3;p.prototype={internalCallback_:function(a){this.closed_||this.reporting_&&this.check_(a)&&(this.report_(),this.testingResults&&(this.testingResults.anyChanged=!0))},close:function(){this.closed_||(this.object_&&"function"==typeof this.object_.close&&this.object_.close(),this.disconnect_(),this.object_=void 0,this.closed_=!0)},deliver:function(a){this.closed_||(K?(this.testingResults=a,Object.deliverChangeRecords(this.boundInternalCallback_),this.testingResults=void 0):k(this))},report_:function(){this.reporting_&&(this.sync_(!1),this.callback&&this.invokeCallback_(this.reportArgs),this.reportArgs=void 0)},invokeCallback_:function(a){try{this.callback.apply(this.target,a)}catch(b){p._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},reset:function(){this.closed_||(K&&(this.reporting_=!1,Object.deliverChangeRecords(this.boundInternalCallback_),this.reporting_=!0),this.sync_(!0))}};var Z,$=!K||a.forceCollectObservers;p._allObserversCount=0,$&&(Z=[]);var _=!1,ab="function"==typeof Object.deliverAllChangeRecords;a.Platform=a.Platform||{},a.Platform.performMicrotaskCheckpoint=function(){if(!_){if(ab)return Object.deliverAllChangeRecords(),void 0;if($){_=!0;var b=0,c={};do{b++;var d=Z;Z=[],c.anyChanged=!1;for(var e=0;e<d.length;e++){var f=d[e];f.closed_||(K?f.deliver(c):f.check_()&&(c.anyChanged=!0,f.report_()),Z.push(f))}}while(Y>b&&c.anyChanged);a.testingExposeCycleCount&&(a.dirtyCheckCycleCount=b),p._allObserversCount=Z.length,_=!1}}},$&&(a.Platform.clearObservers=function(){Z=[]}),r.prototype=N({__proto__:p.prototype,connect_:function(){K&&Object.observe(this.object_,this.boundInternalCallback_)},sync_:function(){K||(this.oldObject=o(this.object_))},check_:function(a){var b,c;if(K){if(!a)return!1;c={},b=x(this.object_,a,c)}else c=this.oldObject,b=n(this.object_,this.oldObject);return m(b)?!1:(this.reportArgs=[b.added||{},b.removed||{},b.changed||{}],this.reportArgs.push(function(a){return c[a]}),!0)},disconnect_:function(){K?this.object_&&Object.unobserve(this.object_,this.boundInternalCallback_):this.oldObject=void 0}}),s.prototype=N({__proto__:r.prototype,connect_:function(){K&&Array.observe(this.object_,this.boundInternalCallback_)},sync_:function(){K||(this.oldObject=this.object_.slice())},check_:function(a){var b;if(K){if(!a)return!1;b=E(this.object_,a)}else b=A(this.object_,0,this.object_.length,this.oldObject,0,this.oldObject.length);return b&&b.length?(this.reportArgs=[b],!0):!1}}),s.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})};var bb=Object.getPrototypeOf({}),cb=Object.getPrototypeOf([]);t.prototype={reset:function(){this.isObserved=!this.isObserved},observe:function(a){if(f(a)&&a!==bb&&a!==cb){var b=this.arr.indexOf(a);b>=0&&this.arr[b+1]===this.isObserved||(0>b&&(b=this.arr.length,this.arr[b]=a,Object.observe(a,this.callback)),this.arr[b+1]=this.isObserved,this.observe(Object.getPrototypeOf(a)))}},cleanup:function(){for(var a=0,b=0,c=this.isObserved;b<this.arr.length;){var d=this.arr[b];this.arr[b+1]==c?(b>a&&(this.arr[a]=d,this.arr[a+1]=c),a+=2):Object.unobserve(d,this.callback),b+=2}this.arr.length=a}},u.prototype=N({__proto__:p.prototype,connect_:function(){K&&(this.observedSet_=new t(this.boundInternalCallback_))},disconnect_:function(){this.value=void 0,this.value_=void 0,this.observedSet_&&(this.observedSet_.reset(),this.observedSet_.cleanup(),this.observedSet_=void 0)},check_:function(){return this.observedSet_&&this.observedSet_.reset(),this.value_=this.path_.getValueFrom(this.object_,this.observedSet_),this.observedSet_&&this.observedSet_.cleanup(),g(this.value_,this.oldValue_)?!1:(this.value=this.transformFn_?this.transformFn_(this.value_):this.value_,this.reportArgs=[this.value,this.oldValue],!0)},sync_:function(a){a&&(this.observedSet_&&this.observedSet_.reset(),this.value_=this.path_.getValueFrom(this.object_,this.observedSet_),this.value=this.transformFn_?this.transformFn_(this.value_):this.value_,this.observedSet_&&this.observedSet_.cleanup()),this.oldValue_=this.value_,this.oldValue=this.value},setValue:function(a){this.setValueFn_?this.setValueFn_(a):this.path_&&this.path_.setValueFrom(this.object_,a)}}),v.prototype=N({__proto__:u.prototype,addPath:function(a,b){if(this.started_)throw Error("Cannot add more paths once started.");var b=b instanceof i?b:j(b),c=b.getValueFrom(a);this.observed_.push(a,b),this.values_.push(c)},start:function(){this.started_=!0,this.connect_(),this.sync_(!0)},getValues_:function(){this.observedSet_&&this.observedSet_.reset();for(var a=!1,b=0;b<this.observed_.length;b+=2){var c=this.observed_[b+1],d=this.observed_[b],e=c.getValueFrom(d,this.observedSet_),f=this.values_[b/2];if(!g(e,f)){if(!a&&!this.transformFn_){this.oldValues_=this.oldValues_||[],this.changeFlags_=this.changeFlags_||[];for(var h=0;h<this.values_.length;h++)this.oldValues_[h]=this.values_[h],this.changeFlags_[h]=!1}this.transformFn_||(this.changeFlags_[b/2]=!0),this.values_[b/2]=e,a=!0}}return this.observedSet_&&this.observedSet_.cleanup(),a},check_:function(){if(this.getValues_()){if(this.transformFn_){if(this.value=this.transformFn_(this.values_),g(this.value,this.oldValue))return!1;this.reportArgs=[this.value,this.oldValue]}else this.reportArgs=[this.values_,this.oldValues_,this.changeFlags_,this.observed_];return!0}},sync_:function(a){a&&(this.getValues_(),this.transformFn_&&(this.value=this.transformFn_(this.values_))),this.transformFn_&&(this.oldValue=this.value)},close:function(){if(this.observed_){for(var a=0;a<this.observed_.length;a+=2){var b=this.observed_[a];b&&"function"==typeof b.close&&b.close()}this.observed_=void 0,this.values_=void 0}p.prototype.close.call(this)}});var db={};db[F]=!0,db[G]=!0,db[I]=!0,u.defineProperty=function(a,b,c,d){d=j(d);var e=w(a,b),f=new u(c,d,function(a,b){e&&e(G,b)});return Object.defineProperty(a,b,{get:function(){return d.getValueFrom(c)},set:function(a){d.setValueFrom(c,a)},configurable:!0}),{close:function(){var g=d.getValueFrom(c);e&&f.deliver(),f.close(),Object.defineProperty(a,b,{value:g,writable:!0,configurable:!0})}}};var eb=0,fb=1,gb=2,hb=3;z.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(eb):(e.push(fb),d=g),b--,c--):f==h?(e.push(hb),b--,d=h):(e.push(gb),c--,d=i)}else e.push(hb),b--;else e.push(gb),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,c-b==0&&f-e==0)return[];if(b==c){for(var j=y(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[y(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case eb:j&&(l.push(j),j=void 0),m++,n++;break;case fb:j||(j=y(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case gb:j||(j=y(m,[],0)),j.addedCount++,m++;break;case hb:j||(j=y(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var ib=new z;a.Observer=p,a.Observer.hasObjectObserve=K,a.ArrayObserver=s,a.ArrayObserver.calculateSplices=function(a,b){return ib.calculateSplices(a,b)},a.ArraySplice=z,a.ObjectObserver=r,a.PathObserver=u,a.CompoundPathObserver=v,a.Path=i,a.Observer.changeRecordTypes={add:F,update:G,reconfigure:H,"delete":I,splice:J}}("undefined"!=typeof global&&global?global:this||window),window.Platform=window.Platform||{},window.logFlags=window.logFlags||{},function(a){var b=a.flags||{};location.search.slice(1).split("&").forEach(function(a){a=a.split("="),a[0]&&(b[a[0]]=a[1]||!0)}),b.shadow=b.shadow||b.shadowdom||b.polyfill,b.shadow="native"===b.shadow?!1:b.shadow||!HTMLElement.prototype.createShadowRoot&&"polyfill",a.flags=b}(Platform),"polyfill"===Platform.flags.shadow?(window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return L(b).forEach(function(c){K(a,c,M(b,c))}),a}function d(a,b){return L(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}K(a,c,M(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=E.get(b);if(c)return c;var d=f(b),e=t(d);return q(b,e,a),e}function g(a,b){o(a,b,!0)}function h(a,b){o(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return H&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return H&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return H&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(a,b){try{return Object.getOwnPropertyDescriptor(a,b)}catch(c){return O}}function o(b,c,d){for(var e=L(b),f=0;f<e.length;f++){var g=e[f];if("polymerBlackList_"!==g&&!(g in c||b.polymerBlackList_&&b.polymerBlackList_[g])){N&&b.__lookupGetter__(g);var h,j,o=n(b,g);if(d&&"function"==typeof o.value)c[g]=m(g);else{var p=i(g);h=p?a.getEventHandlerGetter(g):k(g),(o.writable||o.set)&&(j=p?a.getEventHandlerSetter(g):l(g)),K(c,g,{get:h,set:j,configurable:o.configurable,enumerable:o.enumerable})}}}}function p(a,b,c){var e=a.prototype;q(e,b,c),d(b,a)}function q(a,c,d){var e=c.prototype;b(void 0===E.get(a)),E.set(a,c),F.set(e,a),g(a,e),d&&h(e,d),K(e,"constructor",{value:c,configurable:!0,enumerable:!1,writable:!0})}function r(a,b){return E.get(b.prototype)===a}function s(a){var b=Object.getPrototypeOf(a),c=f(b),d=t(c);return q(b,d,a),d}function t(a){function b(b){a.call(this,b)}return b.prototype=Object.create(a.prototype),b.prototype.constructor=b,b}function u(a){return a instanceof G.EventTarget||a instanceof G.Event||a instanceof G.Range||a instanceof G.DOMImplementation||a instanceof G.CanvasRenderingContext2D||G.WebGLRenderingContext&&a instanceof G.WebGLRenderingContext}function v(a){return a instanceof R||a instanceof Q||a instanceof S||a instanceof T||a instanceof P||a instanceof U||V&&a instanceof V}function w(a){return null===a?null:(b(v(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function x(a){return null===a?null:(b(u(a)),a.impl)}function y(a){return a&&u(a)?x(a):a}function z(a){return a&&!u(a)?w(a):a}function A(a,c){null!==c&&(b(v(a)),b(void 0===c||u(c)),a.polymerWrapper_=c)}function B(a,b,c){K(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function C(a,b){B(a,b,function(){return w(this.impl[b])})}function D(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=z(this);return a[b].apply(a,arguments)}})})}var E=new WeakMap,F=new WeakMap,G=Object.create(null),H=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(H)try{var I=new Function("","return true;");H=I()}catch(J){H=!1}var K=Object.defineProperty,L=Object.getOwnPropertyNames,M=Object.getOwnPropertyDescriptor;L(window);var N=/Firefox/.test(navigator.userAgent),O={get:function(){},set:function(){},configurable:!0,enumerable:!0},P=window.DOMImplementation,Q=window.Event,R=window.Node,S=window.Window,T=window.Range,U=window.CanvasRenderingContext2D,V=window.WebGLRenderingContext;a.assert=b,a.constructorTable=E,a.defineGetter=B,a.defineWrapGetter=C,a.forwardMethodsToWrapper=D,a.isWrapper=u,a.isWrapperFor=r,a.mixin=c,a.nativePrototypeTable=F,a.oneOf=e,a.registerObject=s,a.registerWrapper=p,a.rewrap=A,a.unwrap=x,a.unwrapIfNeeded=y,a.wrap=w,a.wrapIfNeeded=z,a.wrappers=G}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if((h===a||l.subtree)&&!("attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof O.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&N(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var l=null;if(g.length){if(c(i)&&(l=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(m(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,l,e)}a=b(a)?a.host:a.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a){for(var b;b=a.parentNode;)a=b;return a}function m(a,b){return l(a)===l(b)}function n(a,b){return a===b?!0:a instanceof O.ShadowRoot?n(l(a.host),b):!1}function o(a){return Q.get(a)?void 0:(Q.set(a,!0),p(N(a),N(a.target)))}function p(b,c){if(R.get(b))throw new Error("InvalidStateError");R.set(b,!0),a.renderAllPending();var d=g(c);return"load"===b.type&&2===d.length&&d[0].target instanceof O.Document&&d.shift(),Z.set(b,d),q(b,d)&&r(b,d)&&s(b,d),V.set(b,v.NONE),T.delete(b,null),R.delete(b),b.defaultPrevented}function q(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=v.CAPTURING_PHASE,!t(b[d],a,c)))return!1}return!0}function r(a,b){var c=v.AT_TARGET;return t(b[0],a,c)}function s(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=v.AT_TARGET;else{if(!d||X.get(a))continue;c=v.BUBBLING_PHASE}if(!t(b[e],a,c))return}}function t(a,b,c){var d=a.target,e=a.currentTarget,f=P.get(e);if(!f)return!0;if("relatedTarget"in b){var g=M(b);if(g.relatedTarget){var h=N(g.relatedTarget),j=i(e,h);if(j===d)return!0;U.set(b,j)}}V.set(b,c);var k=b.type,l=!1;S.set(b,d),T.set(b,e);for(var m=0;m<f.length;m++){var n=f[m];if(n.removed)l=!0;else if(!(n.type!==k||!n.capture&&c===v.CAPTURING_PHASE||n.capture&&c===v.BUBBLING_PHASE))try{if("function"==typeof n.handler?n.handler.call(e,b):n.handler.handleEvent(b),X.get(b))return!1}catch(o){window.onerror?window.onerror(o.message):console.error(o,o.stack)}}if(l){var p=f.slice();f.length=0;for(var m=0;m<p.length;m++)p[m].removed||f.push(p[m])}return!W.get(b)}function u(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function v(a,b){return a instanceof $?(this.impl=a,void 0):N(z($,"Event",a,b))}function w(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:M(a.relatedTarget)}}):a}function x(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?(this.impl=b,void 0):N(z(d,a,b,c))};if(e.prototype=Object.create(b.prototype),c&&K(e.prototype,c),d)try{L(d,e,new d("temp"))}catch(f){L(d,e,document.createEvent(a))}return e}function y(a,b){return function(){arguments[b]=M(arguments[b]);var c=M(this);c[a].apply(c,arguments)}}function z(a,b,c,d){if(hb)return new a(c,w(d));var e=M(document.createEvent(b)),f=gb[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=M(b)),g.push(b)}),e["init"+b].apply(e,g),e}function A(){v.call(this)}function B(a){return"function"==typeof a?!0:a&&a.handleEvent}function C(a){switch(a){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function D(a){this.impl=a}function E(a){return a instanceof O.ShadowRoot&&(a=a.host),M(a)}function F(a){J(a,kb)}function G(b,c,d,e){a.renderAllPending();for(var f=N(lb.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function H(a){return function(){var b=Y.get(this);return b&&b[a]&&b[a].value||null}}function I(a){var b=a.slice(2);return function(c){var d=Y.get(this);d||(d=Object.create(null),Y.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var J=a.forwardMethodsToWrapper,K=a.mixin,L=a.registerWrapper,M=a.unwrap,N=a.wrap,O=a.wrappers,P=(new WeakMap,new WeakMap),Q=new WeakMap,R=new WeakMap,S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap;u.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var $=window.Event;$.prototype.polymerBlackList_={returnValue:!0},v.prototype={get target(){return S.get(this)},get currentTarget(){return T.get(this)},get eventPhase(){return V.get(this)},get path(){var a=new O.NodeList,b=Z.get(this);if(b){for(var c=0,d=b.length-1,e=l(T.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=l(g);n(e,h)&&(f!==d||g instanceof O.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){W.set(this,!0)},stopImmediatePropagation:function(){W.set(this,!0),X.set(this,!0)}},L($,v,document.createEvent("Event"));var _=x("UIEvent",v),ab=x("CustomEvent",v),bb={get relatedTarget(){return U.get(this)||N(M(this).relatedTarget)}},cb=K({initMouseEvent:y("initMouseEvent",14)},bb),db=K({initFocusEvent:y("initFocusEvent",5)},bb),eb=x("MouseEvent",_,cb),fb=x("FocusEvent",_,db),gb=Object.create(null),hb=function(){try{new window.FocusEvent("focus")}catch(a){return!1}return!0}();if(!hb){var ib=function(a,b,c){if(c){var d=gb[c];b=K(K({},d),b)}gb[a]=b};ib("Event",{bubbles:!1,cancelable:!1}),ib("CustomEvent",{detail:null},"Event"),ib("UIEvent",{view:null,detail:0},"Event"),ib("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),ib("FocusEvent",{relatedTarget:null},"UIEvent")}A.prototype=Object.create(v.prototype),K(A.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}});var jb=window.EventTarget,kb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;kb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),D.prototype={addEventListener:function(a,b,c){if(B(b)&&!C(a)){var d=new u(a,b,c),e=P.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],P.set(this,e);e.push(d);var g=E(this);g.addEventListener_(a,o,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=P.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=E(this);h.removeEventListener_(a,o,!0)}}},dispatchEvent:function(a){p(a,this)}},jb&&L(jb,D);var lb=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=G,a.getEventHandlerGetter=H,a.getEventHandlerSetter=I,a.wrapEventTargetMethods=F,a.wrappers.BeforeUnloadEvent=A,a.wrappers.CustomEvent=ab,a.wrappers.Event=v,a.wrappers.EventTarget=D,a.wrappers.FocusEvent=fb,a.wrappers.MouseEvent=eb,a.wrappers.UIEvent=_}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d
-}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){v(a instanceof s)}function c(a){var b=new u;return b[0]=a,b.length=1,b}function d(a,b,c){x(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){x(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);F=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;F=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new u,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b.length=c,e(a,b),b}function i(a){return a}function j(a){a.nodeIsInserted_()}function k(a){for(var b=0;b<a.length;b++)j(a[b])}function l(){}function m(){}function n(a,b){var c=a.nodeType===s.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function p(a,b){o(a,b);var c=b.length;if(1===c)return C(b[0]);for(var d=C(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(C(b[e]));return d}function q(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){v(b.parentNode===a);var c=b.nextSibling,d=C(b),e=d.parentNode;e&&K.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=C(a),g=f.firstChild;g;)c=g.nextSibling,K.call(f,g),g=c}function r(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function s(a){v(a instanceof G),t.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0}var t=a.wrappers.EventTarget,u=a.wrappers.NodeList,v=a.assert,w=a.defineWrapGetter,x=a.enqueueMutation,y=a.isWrapper,z=a.mixin,A=a.registerTransientObservers,B=a.registerWrapper,C=a.unwrap,D=a.wrap,E=a.wrapIfNeeded,F=!1,G=window.Node,H=window.DocumentFragment,I=(G.prototype.appendChild,G.prototype.compareDocumentPosition),J=G.prototype.insertBefore,K=G.prototype.removeChild,L=G.prototype.replaceChild,M=/Trident/.test(navigator.userAgent),N=M?function(a,b){try{K.call(a,b)}catch(c){if(!(a instanceof H))throw c}}:function(a,b){K.call(a,b)};s.prototype=Object.create(t.prototype),z(s.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a);var d;c?y(c)?d=C(c):(d=c,c=D(d)):(c=null,d=null),c&&v(c.parentNode===this);var e,h=c?c.previousSibling:this.lastChild,i=!this.invalidateShadowRenderer()&&!r(a);if(e=i?g(a):f(a,this,h,c),i)n(this,a),J.call(this.impl,C(a),d);else{h||(this.firstChild_=e[0]),c||(this.lastChild_=e[e.length-1]);var j=d?d.parentNode:this.impl;j?J.call(j,p(this,e),d):o(this,e)}return x(this,"childList",{addedNodes:e,nextSibling:c,previousSibling:h}),k(e),a},removeChild:function(a){if(b(a),a.parentNode!==this){for(var d=!1,e=(this.childNodes,this.firstChild);e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=C(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&N(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else N(this.impl,f);return F||x(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),A(this,a),a},replaceChild:function(a,d){b(a);var e;if(y(d)?e=C(d):(e=d,d=D(e)),d.parentNode!==this)throw new Error("NotFoundError");var h,i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!r(a);return m?h=g(a):(i===a&&(i=a.nextSibling),h=f(a,this,j,i)),m?(n(this,a),L.call(this.impl,C(a),e)):(this.firstChild===d&&(this.firstChild_=h[0]),this.lastChild===d&&(this.lastChild_=h[h.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,e.parentNode&&L.call(e.parentNode,p(this,h),e)),x(this,"childList",{addedNodes:h,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(h),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:D(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:D(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:D(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:D(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:D(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==s.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)a+=b.textContent;return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(q(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else this.impl.textContent=a;var d=i(this.childNodes);x(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d)},get childNodes(){for(var a=new u,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){var b=D(this.impl.cloneNode(!1));if(a)for(var c=this.firstChild;c;c=c.nextSibling)b.appendChild(c.cloneNode(!0));return b},contains:function(a){if(!a)return!1;if(a=E(a),a===this)return!0;var b=a.parentNode;return b?this.contains(b):!1},compareDocumentPosition:function(a){return I.call(this.impl,C(a))}}),w(s,"ownerDocument"),B(G,s,document.createDocumentFragment()),delete s.prototype.querySelector,delete s.prototype.querySelectorAll,s.prototype=z(Object.create(t.prototype),s.prototype),a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=s}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=a.oneOf,n=a.registerWrapper,o=a.wrappers,p=window.Element,q=m(p.prototype,["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"]),r=p.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new o.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),"matches"!=q&&(d.prototype[q]=function(a){return this.matches(a)}),p.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),n(p,d),a.matchesName=q,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case'"':return"&quot;"}}function c(a){return a.replace(w,b)}function d(a){switch(a.nodeType){case Node.ELEMENT_NODE:for(var b,d=a.tagName.toLowerCase(),f="<"+d,g=a.attributes,h=0;b=g[h];h++)f+=" "+b.name+'="'+c(b.value)+'"';return f+=">",x[d]?f:f+e(a)+"</"+d+">";case Node.TEXT_NODE:return c(a.nodeValue);case Node.COMMENT_NODE:return"<!--"+c(a.nodeValue)+"-->";default:throw console.error(a),new Error("not implemented")}}function e(a){for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=d(c);return b}function f(a,b,c){var d=c||"div";a.textContent="";var e=u(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(v(f))}function g(a){m.call(this,a)}function h(a,b){var c=u(a.cloneNode(!1));c.innerHTML=b;for(var d,e=u(document.createDocumentFragment());d=c.firstChild;)e.appendChild(d);return v(e)}function i(b){return function(){return a.renderAllPending(),this.impl[b]}}function j(a){n(g,a,i(a))}function k(b){Object.defineProperty(g.prototype,b,{get:i(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function l(b){Object.defineProperty(g.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var m=a.wrappers.Element,n=a.defineGetter,o=a.enqueueMutation,p=a.mixin,q=a.nodesWereAdded,r=a.nodesWereRemoved,s=a.registerWrapper,t=a.snapshotNodeList,u=a.unwrap,v=a.wrap,w=/&|<|"/g,x={area:!0,base:!0,br:!0,col:!0,command:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0},y=window.HTMLElement;g.prototype=Object.create(m.prototype),p(g.prototype,{get innerHTML(){return e(this)},set innerHTML(a){var b=t(this.childNodes);this.invalidateShadowRenderer()?f(this,a,this.tagName):this.impl.innerHTML=a;var c=t(this.childNodes);o(this,"childList",{addedNodes:c,removedNodes:b}),r(b),q(c)},get outerHTML(){return d(this)},set outerHTML(a){var b=this.parentNode;if(b){b.invalidateShadowRenderer();var c=h(b,a);b.replaceChild(c,this)}},insertAdjacentHTML:function(a,b){var c,d;switch(String(a).toLowerCase()){case"beforebegin":c=this.parentNode,d=this;break;case"afterend":c=this.parentNode,d=this.nextSibling;break;case"afterbegin":c=this,d=this.firstChild;break;case"beforeend":c=this,d=null;break;default:return}var e=h(c,b);c.insertBefore(e,d)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(j),["scrollLeft","scrollTop"].forEach(k),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(l),s(y,g,document.createElement("b")),a.wrappers.HTMLElement=g,a.getInnerHTML=e,a.setInnerHTML=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=m.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);m.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=j(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!n){var b=c(a);l.set(this,k(b))}}var e=a.wrappers.HTMLElement,f=a.getInnerHTML,g=a.mixin,h=a.registerWrapper,i=a.setInnerHTML,j=a.unwrap,k=a.wrap,l=new WeakMap,m=new WeakMap,n=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),g(d.prototype,{get content(){return n?k(this.impl.content):l.get(this)},get innerHTML(){return f(this.content)},set innerHTML(a){i(this.content,a)}}),n&&h(n,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(g){c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createTextNode("")),i=f(document.createComment(""));a.wrappers.Comment=i,a.wrappers.DocumentFragment=g,a.wrappers.Text=h}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=i(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),g(b,this);var d=a.shadowRoot;k.set(this,d),j.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.elementFromPoint,e=a.getInnerHTML,f=a.mixin,g=a.rewrap,h=a.setInnerHTML,i=a.unwrap,j=new WeakMap,k=new WeakMap;b.prototype=Object.create(c.prototype),f(b.prototype,{get innerHTML(){return e(this)},set innerHTML(a){h(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return k.get(this)||null},get host(){return j.get(this)||null},invalidateShadowRenderer:function(){return j.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return d(this,this.ownerDocument,a,b)},getElementById:function(a){return this.querySelector("#"+a)}}),a.wrappers.ShadowRoot=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=F(a),g=F(c),h=e?F(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=G(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=F(a),d=c.parentNode;if(d){var e=G(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=I.get(a);c||I.set(a,c=[]),c.push(b)}function f(a){H.set(a,[])}function g(a){return H.get(a)}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof z))return!1;if(!L.test(c))return!1;if(":"===c[0]&&!M.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<O.length;a++)O[a].render();O=[]}function l(){y=null,k()}function m(a){var b=K.get(a);return b||(b=new q(a),K.set(a,b)),b}function n(a){for(;a;a=a.parentNode)if(a instanceof D)return a;return null}function o(a){return m(a.host)}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof A}function s(a){return a instanceof A}function t(a){return a instanceof B}function u(a){return a instanceof B}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){J.set(a,b)}var y,z=a.wrappers.Element,A=a.wrappers.HTMLContentElement,B=a.wrappers.HTMLShadowElement,C=a.wrappers.Node,D=a.wrappers.ShadowRoot,E=(a.assert,a.mixin,a.oneOf),F=a.unwrap,G=a.wrap,H=new WeakMap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=/^[*.:#[a-zA-Z_|]/,M=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),N=E(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),O=[],P=new ArraySplice;P.equals=function(a,b){return F(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(F(b)),g=a||new WeakMap,i=P.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=G(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&G(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},invalidate:function(){if(!this.dirty){if(this.dirty=!0,O.push(this),y)return;y=window[N](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},C.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},A.prototype.getDistributedNodes=function(){return k(),g(this)},B.prototype.nodeIsInserted_=A.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=I,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=J,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLSelectElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a)}function c(a){var c=document[a];b.prototype[a]=function(){return v(c.apply(this.impl,arguments))}}function d(a,b){z.call(b.impl,u(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof n&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return v(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.SelectorsInterface,n=a.wrappers.ShadowRoot,o=a.defineWrapGetter,p=a.elementFromPoint,q=a.forwardMethodsToWrapper,r=a.matchesName,s=a.mixin,t=a.registerWrapper,u=a.unwrap,v=a.wrap,w=a.rewrap,x=a.wrapEventTargetMethods,y=(a.wrapNodeList,new WeakMap);b.prototype=Object.create(k.prototype),o(b,"documentElement"),o(b,"body"),o(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var z=document.adoptNode,A=document.importNode;if(s(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return p(this,this,a,b)},importNode:function(a,b){var c=v(A.call(this.impl,u(a),!1));if(b)for(var d=a.firstChild;d;d=d.nextSibling)c.appendChild(this.importNode(d,!0));return c}}),document.register){var B=document.register;b.prototype.register=function(b,c){function d(a){return a?(this.impl=a,void 0):c.extends?document.createElement(c.extends,b):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);["createdCallback","enteredViewCallback","leftViewCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){v(this)instanceof d||w(this),b.apply(v(this),arguments)})});var k={prototype:i};c.extends&&(k.extends=c.extends),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i);B.call(u(this),b,k);return d},q([window.HTMLDocument||window.Document],["register"])}q([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild",r]),q([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById"]),s(b.prototype,j),s(b.prototype,l),s(b.prototype,m),s(b.prototype,{get implementation(){var a=y.get(this);return a?a:(a=new g(u(this).implementation),y.set(this,a),a)}}),t(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&t(window.HTMLDocument,b),x([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),t(window.DOMImplementation,g),q([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.unwrapIfNeeded,h=a.wrap,i=a.renderAllPending,j=window.Window;b.prototype=Object.create(c.prototype);var k=window.getComputedStyle;j.prototype.getComputedStyle=function(a,b){return i(),k.call(this||window,g(a),b)
-},delete window.getComputedStyle,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){j.prototype[a]=function(){var b=h(this||window);return b[a].apply(b,arguments)},delete window[a]}),d(b.prototype,{getComputedStyle:function(a,b){return k.call(f(this),g(a),b)}}),e(j,b),a.wrappers.Window=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",applet:"HTMLAppletElement",area:"HTMLAreaElement",br:"HTMLBRElement",base:"HTMLBaseElement",body:"HTMLBodyElement",button:"HTMLButtonElement",dl:"HTMLDListElement",datalist:"HTMLDataListElement",data:"HTMLDataElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",hr:"HTMLHRElement",head:"HTMLHeadElement",h1:"HTMLHeadingElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",input:"HTMLInputElement",li:"HTMLLIElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",del:"HTMLModElement",ol:"HTMLOListElement",object:"HTMLObjectElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",time:"HTMLTimeElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",table:"HTMLTableElement",tr:"HTMLTableRowElement",thead:"HTMLTableSectionElement",tbody:"HTMLTableSectionElement",textarea:"HTMLTextAreaElement",track:"HTMLTrackElement",title:"HTMLTitleElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]}),a.knownElements=c}(window.ShadowDOMPolyfill),function(){window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded,Object.defineProperty(Element.prototype,"webkitShadowRoot",Object.getOwnPropertyDescriptor(Element.prototype,"shadowRoot"));var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b},Element.prototype.webkitCreateShadowRoot=Element.prototype.createShadowRoot}(),function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(n,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=b.sheet.cssRules;return b.parentNode.removeChild(b),d}function e(a){for(var b=0,c=[];b<a.length;b++)c.push(a[b].cssText);return c.join("\n\n")}function f(a){a&&g().appendChild(document.createTextNode(a))}function g(){return h||(h=document.createElement("style"),h.setAttribute("ShadowCSSShim",""),h.shadowCssShim=!0),h}var h,i={strictStyling:!1,registry:{},shimStyling:function(a,b,d){var e=this.isTypeExtension(d),g=this.registerDefinition(a,b,d);this.strictStyling&&this.applyScopeToContent(a,b);var h=this.stylesToShimmedCssText(g.rootStyles,g.scopeStyles,b,e);g.shimmedStyle=c(h),a&&(a.shimmedStyle=g.shimmedStyle);for(var i,j=0,k=g.rootStyles.length;k>j&&(i=g.rootStyles[j]);j++)i.parentNode.removeChild(i);f(h)},stylesToShimmedCssText:function(a,b,c,d){c=c||"",this.insertPolyfillDirectives(a),this.insertPolyfillRules(a);var e=this.shimAtHost(b,c,d)+this.shimScoping(b,c,d);return e+=this.extractPolyfillUnscopedRules(a)},registerDefinition:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=a?a.querySelectorAll("style"):[];e=e?Array.prototype.slice.call(e,0):[],d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},isTypeExtension:function(a){return a&&a.indexOf("-")<0},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertPolyfillDirectives:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillDirectivesInCssText(a.textContent)},this)},insertPolyfillDirectivesInCssText:function(a){return a.replace(o,function(a,b){return b.slice(0,-2)+"{"})},insertPolyfillRules:function(a){a&&Array.prototype.forEach.call(a,function(a){a.textContent=this.insertPolyfillRulesInCssText(a.textContent)},this)},insertPolyfillRulesInCssText:function(a){return a.replace(p,function(a,b){return b.slice(0,-1)})},extractPolyfillUnscopedRules:function(a){var b="";return a&&Array.prototype.forEach.call(a,function(a){b+=this.extractPolyfillUnscopedRulesFromCssText(a.textContent)+"\n\n"},this),b},extractPolyfillUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";return c},shimAtHost:function(a,b,c){return a?this.convertAtHostStyles(a,b,c):void 0},convertAtHostStyles:function(a,c,f){var g=b(a),h=this;return g=g.replace(j,function(a,b){return h.scopeHostCss(b,c,f)}),g=e(this.findAtHostRules(d(g),this.makeScopeMatcher(c,f)))},scopeHostCss:function(a,b,c){var d=this;return a.replace(k,function(a,e,f){return d.scopeHostSelector(e,b,c)+" "+f+"\n	"})},scopeHostSelector:function(a,b,c){var d=[],e=a.split(","),f="[is="+b+"]";return e.forEach(function(a){a=a.trim(),a.match(l)?a=a.replace(l,c?f+"$1$3":b+"$1$3"):a.match(m)&&(a=c?f+a:b+a),d.push(a)},this),d.join(", ")},findAtHostRules:function(a,b){return Array.prototype.filter.call(a,this.isHostRule.bind(this,b))},isHostRule:function(a,b){return b.selectorText&&b.selectorText.match(a)||b.cssRules&&this.findAtHostRules(b.cssRules,a).length||b.type==CSSRule.WEBKIT_KEYFRAMES_RULE},shimScoping:function(a,b,c){return a?this.convertScopedStyles(a,b,c):void 0},convertScopedStyles:function(a,c,e){var f=b(a).replace(j,"");f=this.insertPolyfillHostInCssText(f),f=this.convertColonHost(f),f=this.convertPseudos(f),f=this.convertParts(f),f=this.convertCombinators(f);var g=d(f);return c&&(f=this.scopeRules(g,c,e)),f},convertPseudos:function(a){return a.replace(r," [pseudo=$1]")},convertParts:function(a){return a.replace(s," [part=$1]")},convertColonHost:function(a){return a.replace(u,function(a,b,c,d){if(b=y,c){for(var e,f=c.split(","),g=[],h=0,i=f.length;i>h&&(e=f[h]);h++)e=e.trim(),e.match(t)?g.push(b+e.replace(t,"")+d):g.push(b+e+d+", "+e+" "+b+d);return g.join(",")}return b+d})},convertCombinators:function(a){return a.replace(/\^\^/g," ").replace(/\^/g," ")},scopeRules:function(a,b,c){var d="";return Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(d+=this.scopeSelector(a.selectorText,b,c,this.strictStyling)+" {\n	",d+=this.propertiesFromRule(a)+"\n}\n\n"):a.media?(d+="@media "+a.media.mediaText+" {\n",d+=this.scopeRules(a.cssRules,b,c),d+="\n}\n\n"):a.cssText&&(d+=a.cssText+"\n\n")},this),d},scopeSelector:function(a,b,c,d){var e=[],f=a.split(",");return f.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b,c)&&(a=d&&!a.match(y)?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b,c)),e.push(a)},this),e.join(", ")},selectorNeedsScoping:function(a,b,c){var d=this.makeScopeMatcher(b,c);return!a.match(d)},makeScopeMatcher:function(a,b){var c=b?"\\[is=['\"]?"+a+"['\"]?\\]":a;return new RegExp("^("+c+")"+v,"m")},applySimpleSelectorScope:function(a,b,c){var d=c?"[is="+b+"]":b;return a.match(z)?(a=a.replace(y,d),a.replace(z,d+" ")):d+" "+a},applyStrictSelectorScope:function(a,b){var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(z,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(w,t).replace(x,t)},propertiesFromRule:function(a){return a.style.cssText}},j=/@host[^{]*{(([^}]*?{[^{]*?}[\s\S]*?)+)}/gim,k=/([^{]*)({[\s\S]*?})/gim,l=/(.*)((?:\*)|(?:\:scope))(.*)/,m=/^[.\[:]/,n=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,o=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,p=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/::(x-[^\s{,(]*)/gim,s=/::part\(([^)]*)\)/gim,t="-shadowcsshost",u=new RegExp("("+t+")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)","gim"),v="([>\\s~+[.,{:][\\s\\S]*)?$",w=/@host/gim,x=/\:host/gim,y=t+"-no-combinator",z=new RegExp(t,"gim");if(window.ShadowDOMPolyfill){f("style { display: none !important; }\n");var A=wrap(document),B=A.querySelector("head");B.insertBefore(g(),B.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){window.HTMLImports&&(HTMLImports.importer.preloadSelectors+=", link[rel=stylesheet]:not([nopolyfill])",HTMLImports.parser.parseGeneric=function(a){if(!a.shadowCssShim){var b=a;if(!a.hasAttribute("nopolyfill")){a.__resource&&(b=A.createElement("style"),b.textContent=a.__resource,a.ownerDocument===A&&a.parentNode.removeChild(a));var c=[b];b.textContent=i.stylesToShimmedCssText(c,c),b.shadowCssShim=!0}b.parentNode!==B&&B.appendChild(b)}})})}a.ShadowCSS=i}(window.Platform)):!function(){window.templateContent=window.templateContent||function(a){return a.content},window.wrap=window.unwrap=function(a){return a};var a=Element.prototype.webkitCreateShadowRoot;Element.prototype.webkitCreateShadowRoot=function(){var b=this.webkitShadowRoot,c=a.call(this);return c.olderShadowRoot=b,c.host=this,CustomElements.watchShadow(this),c},Object.defineProperties(Element.prototype,{shadowRoot:{get:function(){return this.webkitShadowRoot}},createShadowRoot:{value:function(){return this.webkitCreateShadowRoot()}}}),window.templateContent=function(a){if(window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(a),!a.content&&!a._content){for(var b=document.createDocumentFragment();a.firstChild;)b.appendChild(a.firstChild);a._content=b}return a.content||a._content}}(),function(a){function b(a){for(var b=a||{},d=1;d<arguments.length;d++){var e=arguments[d];try{for(var f in e)c(f,e,b)}catch(g){}}return b}function c(a,b,c){var e=d(b,a);Object.defineProperty(c,a,e)}function d(a,b){if(a){var c=Object.getOwnPropertyDescriptor(a,b);return c||d(Object.getPrototypeOf(a),b)}}Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();return d.push.apply(d,arguments),b.apply(a,d)}}),a.mixin=b}(window.Platform),function(a){"use strict";function b(a,b,c){var d="string"==typeof a?document.createElement(a):a.cloneNode(!0);if(d.innerHTML=b,c)for(var e in c)d.setAttribute(e,c[e]);return d}var c=DOMTokenList.prototype.add,d=DOMTokenList.prototype.remove;DOMTokenList.prototype.add=function(){for(var a=0;a<arguments.length;a++)c.call(this,arguments[a])},DOMTokenList.prototype.remove=function(){for(var a=0;a<arguments.length;a++)d.call(this,arguments[a])},DOMTokenList.prototype.toggle=function(a,b){1==arguments.length&&(b=!this.contains(a)),b?this.add(a):this.remove(a)},DOMTokenList.prototype.switch=function(a,b){a&&this.remove(a),b&&this.add(b)};var e=function(){return Array.prototype.slice.call(this)},f=window.NamedNodeMap||window.MozNamedAttrMap||{};if(NodeList.prototype.array=e,f.prototype.array=e,HTMLCollection.prototype.array=e,!window.performance){var g=Date.now();window.performance={now:function(){return Date.now()-g}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var a=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return a?function(b){return a(function(){b(performance.now())})}:function(a){return window.setTimeout(a,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(a){clearTimeout(a)}}());var h=document.createElement("template"),i=document.createElement("base");i.href=document.baseURI,h.content.ownerDocument.appendChild(i);var j=function(a,b){window.addEventListener("WebComponentsReady",function(){window.Polymer!==j?Polymer(a,b):console.warn('You tried to use polymer without loading it first. To load polymer, <link rel="import" href="components/polymer/plymer.html">')})};window.Polymer=j,a.createDOM=b}(window.Platform),window.templateContent=window.templateContent||function(a){return a.content},function(a){a=a||(window.Inspector={});var b;window.sinspect=function(a,d){b||(b=window.open("","ShadowDOM Inspector",null,!0),b.document.write(c),b.api={shadowize:shadowize}),f(a||wrap(document.body),d)};var c=["<!DOCTYPE html>","<html>","  <head>","    <title>ShadowDOM Inspector</title>","    <style>","      body {","      }","      pre {",'        font: 9pt "Courier New", monospace;',"        line-height: 1.5em;","      }","      tag {","        color: purple;","      }","      ul {","         margin: 0;","         padding: 0;","         list-style: none;","      }","      li {","         display: inline-block;","         background-color: #f1f1f1;","         padding: 4px 6px;","         border-radius: 4px;","         margin-right: 4px;","      }","    </style>","  </head>","  <body>",'    <ul id="crumbs">',"    </ul>",'    <div id="tree"></div>',"  </body>","</html>"].join("\n"),d=[],e=function(){var a=b.document,c=a.querySelector("#crumbs");c.textContent="";for(var e,g=0;e=d[g];g++){var h=a.createElement("a");h.href="#",h.textContent=e.localName,h.idx=g,h.onclick=function(a){for(var b;d.length>this.idx;)b=d.pop();f(b.shadow||b,b),a.preventDefault()},c.appendChild(a.createElement("li")).appendChild(h)}},f=function(a,c){var f=b.document;k=[];var g=c||a;d.push(g),e(),f.body.querySelector("#tree").innerHTML="<pre>"+j(a,a.childNodes)+"</pre>"},g=Array.prototype.forEach.call.bind(Array.prototype.forEach),h={STYLE:1,SCRIPT:1,"#comment":1,TEMPLATE:1},i=function(a){return h[a.nodeName]},j=function(a,b,c){if(i(a))return"";var d=c||"";if(a.localName||11==a.nodeType){var e=a.localName||"shadow-root",f=d+l(a);"content"==e&&(b=a.getDistributedNodes()),f+="<br/>";var h=d+"&nbsp;&nbsp;";g(b,function(a){f+=j(a,a.childNodes,h)}),f+=d,{br:1}[e]||(f+="<tag>&lt;/"+e+"&gt;</tag>",f+="<br/>")}else{var k=a.textContent.trim();f=k?d+'"'+k+'"<br/>':""}return f},k=[],l=function(a){var b="<tag>&lt;",c=a.localName||"shadow-root";return a.webkitShadowRoot||a.shadowRoot?(b+=' <button idx="'+k.length+'" onclick="api.shadowize.call(this)">'+c+"</button>",k.push(a)):b+=c||"shadow-root",a.attributes&&g(a.attributes,function(a){b+=" "+a.name+(a.value?'="'+a.value+'"':"")}),b+="&gt;</tag>"};shadowize=function(){var a=Number(this.attributes.idx.value),b=k[a];b?f(b.webkitShadowRoot||b.shadowRoot,b):(console.log("bad shadowize node"),console.dir(this))},a.output=j}(window.Inspector),function(){function a(){requestAnimationFrame(function(){for(var a,b=document.querySelectorAll(e),f=0,g=b.length;g>f&&(a=b[f]);f++)a.removeAttribute(c),a.setAttribute(d,"");if(b.length){var h=function(){for(var a,c=0,e=b.length;e>c&&(a=b[c]);c++)a.removeAttribute(d);document.body.removeEventListener(i,h,!1)};document.body.addEventListener(i,h,!1)}})}var b=.2,c="unresolved",d="resolved",e="["+c+"]",f="["+d+"]",g=document.createElement("style");g.textContent=e+" { opacity: 0; display: block; overflow: hidden; } \n"+f+"{ display: block; overflow: hidden;\n-webkit-transition: opacity "+b+"s; transition: opacity "+b+"s; }\n";var h=document.querySelector("head");h.insertBefore(g,h.firstChild);var i=void 0!==document.documentElement.style.webkitTransition?"webkitTransitionEnd":"transitionend";window.addEventListener("WebComponentsReady",a)}(Platform),function(a){function b(a){return d(a,i)}function c(a){return d(a,j)}function d(a,b){return"link"===a.localName&&a.getAttribute("rel")===b}function e(a){return"script"===a.localName}function f(a,b){var c=a;c instanceof Document||(c=document.implementation.createHTMLDocument(i)),c._URL=b;var d=c.createElement("base");return d.setAttribute("href",document.baseURI||document.URL),c.head.appendChild(d),a instanceof Document||(c.body.innerHTML=a),window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(c),c}a||(a=window.HTMLImports={flags:{}});var g,h=a.xhr,i="import",j="stylesheet",k={documents:{},cache:{},preloadSelectors:["link[rel="+i+"]","element link[rel="+j+"]","template","script[src]:not([type])",'script[src][type="text/javascript"]'].join(","),loader:function(a){return g=new l(k.loaded,a),g.cache=k.cache,g},load:function(a,b){g=k.loader(b),k.preload(a)},preload:function(a){var b=a.querySelectorAll(k.preloadSelectors);b=this.filterMainDocumentNodes(a,b),b=this.extractTemplateNodes(b),g.addNodes(b)},filterMainDocumentNodes:function(a,b){return a===document&&(b=Array.prototype.filter.call(b,function(a){return!e(a)})),b},extractTemplateNodes:function(a){var b=[];return a=Array.prototype.filter.call(a,function(a){if("template"===a.localName){if(a.content){var c=a.content.querySelectorAll("link[rel="+j+"]");c.length&&(b=b.concat(Array.prototype.slice.call(c,0)))}return!1}return!0}),b.length&&(a=a.concat(b)),a},loaded:function(a,d,e){if(b(d)){var g=k.documents[a];g||(g=f(e,a),p.resolvePathsInHTML(g),k.documents[a]=g,k.preload(g)),d.import=g,d.import.href=a,d.import.ownerNode=d,d.content=e=g}d.__resource=e,c(d)&&p.resolvePathsInStylesheet(d)}},l=function(a,b){this.onload=a,this.oncomplete=b,this.inflight=0,this.pending={},this.cache={}};l.prototype={addNodes:function(a){this.inflight+=a.length,q(a,this.require,this),this.checkDone()},require:function(a){var b=p.nodeUrl(a);b=p.makeAbsUrl(b),a.__nodeUrl=b,this.dedupe(b,a)||this.fetch(b,a)},dedupe:function(a,b){return this.pending[a]?(this.pending[a].push(b),!0):this.cache[a]?(this.onload(a,b,g.cache[a]),this.tail(),!0):(this.pending[a]=[b],!1)},fetch:function(a,b){var c=function(c,d){this.receive(a,b,c,d)}.bind(this);h.load(a,c)},receive:function(a,b,c,d){c||(g.cache[a]=d),g.pending[a].forEach(function(b){c||this.onload(a,b,d),this.tail()},this),g.pending[a]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}};var m=["href","src","action"],n="["+m.join("],[")+"]",o="{{.*}}",p={nodeUrl:function(a){return p.resolveUrl(p.documentURL,p.hrefOrSrc(a))},hrefOrSrc:function(a){return a.getAttribute("href")||a.getAttribute("src")},documentUrlFromNode:function(a){return p.getDocumentUrl(a.ownerDocument||a)},getDocumentUrl:function(a){var b=a&&(a._URL||a.impl&&a.impl._URL||a.baseURI||a.URL)||"";return b.split("#")[0]},resolveUrl:function(a,b){return this.isAbsUrl(b)?b:this.compressUrl(this.urlToPath(a)+b)},resolveRelativeUrl:function(a,b){return this.isAbsUrl(b)?b:this.makeDocumentRelPath(this.resolveUrl(a,b))},isAbsUrl:function(a){return/(^data:)|(^http[s]?:)|(^\/)/.test(a)},urlToPath:function(a){var b=a.split("/");return b.pop(),b.push(""),b.join("/")},compressUrl:function(a){var b="",c=a.indexOf("?");c>-1&&(b=a.substring(c),a=a.substring(c,0));for(var d,e=a.split("/"),f=0;f<e.length;f++)d=e[f],".."===d&&(e.splice(f-1,2),f-=2);return e.join("/")+b},makeDocumentRelPath:function(a){return p.urlElt.href=a,!p.urlElt.host||p.urlElt.host===window.location.host&&p.urlElt.protocol===window.location.protocol?this.makeRelPath(p.documentURL,p.urlElt.href):a},makeRelPath:function(a,b){for(var c=a.split("/"),d=b.split("/");c.length&&c[0]===d[0];)c.shift(),d.shift();for(var e=0,f=c.length-1;f>e;e++)d.unshift("..");var g=d.join("/");return g},makeAbsUrl:function(a){return p.urlElt.href=a,p.urlElt.href},resolvePathsInHTML:function(a,b){b=b||p.documentUrlFromNode(a),p.resolveAttributes(a,b),p.resolveStyleElts(a,b);var c=a.querySelectorAll("template");c&&q(c,function(a){a.content&&p.resolvePathsInHTML(a.content,b)})},resolvePathsInStylesheet:function(a){var b=p.nodeUrl(a);a.__resource=p.resolveCssText(a.__resource,b)},resolveStyleElts:function(a,b){var c=a.querySelectorAll("style");c&&q(c,function(a){a.textContent=p.resolveCssText(a.textContent,b)})},resolveCssText:function(a,b){return a.replace(/url\([^)]*\)/g,function(a){var c=a.replace(/["']/g,"").slice(4,-1);return c=p.resolveRelativeUrl(b,c),"url("+c+")"})},resolveAttributes:function(a,b){var c=a&&a.querySelectorAll(n);c&&q(c,function(a){this.resolveNodeAttributes(a,b)},this)},resolveNodeAttributes:function(a,b){m.forEach(function(c){var d=a.attributes[c];if(d&&d.value&&d.value.search(o)<0){var e=p.resolveRelativeUrl(b,d.value);d.value=e}})}};p.documentURL=p.getDocumentUrl(document),p.urlElt=document.createElement("a"),h=h||{async:!0,ok:function(a){return a.status>=200&&a.status<300||304===a.status||0===a.status},load:function(b,c,d){var e=new XMLHttpRequest;return(a.flags.debug||a.flags.bust)&&(b+="?"+Math.random()),e.open("GET",b,h.async),e.addEventListener("readystatechange",function(){4===e.readyState&&c.call(d,!h.ok(e)&&e,e.response||e.responseText,b)}),e.send(),e},loadDocument:function(a,b,c){this.load(a,b,c).responseType="document"}};var q=Array.prototype.forEach.call.bind(Array.prototype.forEach);Object.defineProperty(document,"_currentScript",{get:function(){return HTMLImports.currentScript||document.currentScript},writeable:!0,configurable:!0}),a.path=p,a.xhr=h,a.importer=k,a.getDocumentUrl=p.getDocumentUrl,a.IMPORT_LINK_TYPE=i}(window.HTMLImports),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===f}function c(a){return a.parentNode&&!d(a)&&!e(a)}function d(a){return a.ownerDocument===document||a.ownerDocument.impl===document}function e(a){return a.parentNode&&"element"===a.parentNode.localName}{var f="import",g={selectors:["link[rel="+f+"]","link[rel=stylesheet]","style","script:not([type])",'script[type="text/javascript"]'],map:{link:"parseLink",script:"parseScript",style:"parseGeneric"},parse:function(a){if(!a.__importParsed){a.__importParsed=!0;for(var b,c=a.querySelectorAll(g.selectors),d=a.scripts?a.scripts.length:0,e=0;e<c.length&&(b=c[e]);e++)g[g.map[b.localName]](b),a.scripts&&d!==a.scripts.length&&(d=a.scripts.length,c=a.querySelectorAll(g.selectors))}},parseLink:function(a){b(a)?a.import&&(g.parse(a.import),a.dispatchEvent(new CustomEvent("load"))):this.parseGeneric(a)},parseGeneric:function(a){c(a)&&document.head.appendChild(a)},parseScript:function(b){if(c(b)){var d=(b.__resource||b.textContent).trim();if(d){var e=b.__nodeUrl;if(!e){var e=a.path.documentUrlFromNode(b),f="["+Math.floor(1e3*(Math.random()+1))+"]",g=d.match(/Polymer\(['"]([^'"]*)/);f=g&&g[1]||f,e+="/"+f+".js"}d+="\n//# sourceURL="+e+"\n",a.currentScript=b,eval.call(window,d),a.currentScript=null}}}};Array.prototype.forEach.call.bind(Array.prototype.forEach)}a.parser=g}(HTMLImports),function(){function a(){HTMLImports.importer.load(document,function(){HTMLImports.parser.parse(document),HTMLImports.ready=!0,HTMLImports.readyTime=(new Date).getTime(),document.dispatchEvent(new CustomEvent("HTMLImportsLoaded",{bubbles:!0}))})}"function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?a():window.addEventListener("DOMContentLoaded",a)}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new WeakMap,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g,!a.MutationObserver&&a.WebKitMutationObserver&&(a.MutationObserver=a.WebKitMutationObserver),a.MutationObserver||(a.MutationObserver=g)}(this),window.CustomElements=window.CustomElements||{flags:{}},function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),q(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),q(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){p(a)}):p(a)}function p(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),q(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function q(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function r(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)s(b),b=b.olderShadowRoot}}function s(a){a.__watched||(v(a),a.__watched=!0)}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){a.localName&&g(a)}),D(a.removedNodes,function(a){a.localName&&n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=r,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");
-if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeAll(document),g.ctor}function c(a){var b=m(a);return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(x(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){if(!a.setAttribute._polyfilled){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?w[a.toLowerCase()]:void 0}function n(a,b){w[a]=b}function o(a){return function(){return f(a)}}function p(a,b){var c=m(b||a);return c?new c.ctor:x(a)}function q(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is")||a.localName,c=m(b);return c&&g(a,c)}}function r(b){var c=y.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var s=a.flags,t=Boolean(document.register),u=!s.register&&t;if(u){var v=function(){};a.registry={},a.upgradeElement=v,a.watchShadow=v,a.upgrade=v,a.upgradeAll=v,a.upgradeSubtree=v,a.observeDocument=v,a.upgradeDocument=v,a.takeRecords=v}else{var w={},x=document.createElement.bind(document),y=Node.prototype.cloneNode;document.register=b,document.createElement=p,Node.prototype.cloneNode=r,a.registry=w,a.upgrade=q}a.hasNative=t,a.useNative=u}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(a){function b(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||a.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){var a=document.createElement("style");a.textContent="element {display: none !important;} /* injected by platform.js */";var b=document.querySelector("head");if(b.insertBefore(a,b.firstChild),window.ShadowDOMPolyfill){var c=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],d={};c.forEach(function(a){d[a]=CustomElements[a]}),c.forEach(function(a){CustomElements[a]=function(b){return d[a](wrap(b))}})}}(),function(a){function b(a){f.textContent=d++,e.push(a)}function c(){for(;e.length;)e.shift()()}var d=0,e=[],f=document.createTextNode("");new(window.MutationObserver||JsMutationObserver)(c).observe(f,{characterData:!0}),a.endOfMicrotask=b}(Platform),function(a){a=a||{},a.external=a.external||{};var b={shadow:function(a){return a?a.shadowRoot||a.webkitShadowRoot:void 0},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);return this.canTarget(b)?b:void 0},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d}e=this.olderShadow(e)}return f}},owner:function(a){for(var b=a;b.parentNode;)b=b.parentNode;return b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}};a.targetFinding=b,a.findTarget=b.findTarget.bind(b),window.PointerEventsPolyfill=a}(window.PointerEventsPolyfill),function(){function a(a){return"body ^^ "+b(a)}function b(a){return'[touch-action="'+a+'"]'}function c(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; touch-action-delay: none; }"}var d=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],e="";d.forEach(function(d){String(d)===d?(e+=b(d)+c(d)+"\n",e+=a(d)+c(d)+"\n"):(e+=d.selectors.map(b)+c(d.rule)+"\n",e+=d.selectors.map(a)+c(d.rule)+"\n")});var f=document.createElement("style");f.textContent=e,document.head.appendChild(f)}(),function(a){function b(a,e){e=e||{};var f=e.buttons;if(void 0===f)switch(e.which){case 1:f=1;break;case 2:f=4;break;case 3:f=2;break;default:f=0}var i;if(c)i=new MouseEvent(a,e);else{i=document.createEvent("MouseEvent");for(var j,k={},l=0;l<g.length;l++)j=g[l],k[j]=e[j]||h[l];i.initMouseEvent(a,k.bubbles,k.cancelable,k.view,k.detail,k.screenX,k.screenY,k.clientX,k.clientY,k.ctrlKey,k.altKey,k.shiftKey,k.metaKey,k.button,k.relatedTarget)}i.__proto__=b.prototype,d||Object.defineProperty(i,"buttons",{get:function(){return f},enumerable:!0});var m=0;return m=e.pressure?e.pressure:f?.5:0,Object.defineProperties(i,{pointerId:{value:e.pointerId||0,enumerable:!0},width:{value:e.width||0,enumerable:!0},height:{value:e.height||0,enumerable:!0},pressure:{value:m,enumerable:!0},tiltX:{value:e.tiltX||0,enumerable:!0},tiltY:{value:e.tiltY||0,enumerable:!0},pointerType:{value:e.pointerType||"",enumerable:!0},hwTimestamp:{value:e.hwTimestamp||0,enumerable:!0},isPrimary:{value:e.isPrimary||!1,enumerable:!0}}),i}var c=!1,d=!1;try{var e=new MouseEvent("click",{buttons:1});c=!0,d=1===e.buttons}catch(f){}var g=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget"],h=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null];b.prototype=Object.create(MouseEvent.prototype),a.PointerEvent||(a.PointerEvent=b)}(window),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerEventsPolyfill),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,void 0,0,0,0,0,0,0,"",0,!1,"",null,null,0],d={targets:new WeakMap,handledEvents:new WeakMap,pointermap:new a.PointerMap,eventMap:{},eventSources:{},eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.unregister.call(b,a)},contains:a.external.contains||function(a,b){return a.contains(b)},down:function(a){this.fireEvent("pointerdown",a)},move:function(a){this.fireEvent("pointermove",a)},up:function(a){this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){this.fireEvent("pointercancel",a)},leaveOut:function(a){this.contains(a.target,a.relatedTarget)||this.leave(a),this.out(a)},enterOver:function(a){this.contains(a.target,a.relatedTarget)||this.enter(a),this.over(a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),this.handledEvents.set(a,!0)}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:a.external.addEvent||function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:a.external.removeEvent||function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(a,b){this.captureInfo&&(b.relatedTarget=null);var c=new PointerEvent(a,b);return b.preventDefault&&(c.preventDefault=b.preventDefault),this.targets.set(c,this.targets.get(b)||b.target),c},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var d,e={},f=0;f<b.length;f++)d=b[f],e[d]=a[d]||c[f];return a.preventDefault&&(e.preventDefault=function(){a.preventDefault()}),e},getTarget:function(a){return this.captureInfo&&this.captureInfo.id===a.pointerId?this.captureInfo.target:this.targets.get(a)},setCapture:function(a,b){this.captureInfo&&this.releaseCapture(this.captureInfo.id),this.captureInfo={id:a,target:b};var c=new PointerEvent("gotpointercapture",{bubbles:!0});this.implicitRelease=this.releaseCapture.bind(this,a),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease),this.targets.set(c,b),this.asyncDispatchEvent(c)},releaseCapture:function(a){if(this.captureInfo&&this.captureInfo.id===a){var b=new PointerEvent("lostpointercapture",{bubbles:!0}),c=this.captureInfo.target;this.captureInfo=null,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease),this.targets.set(b,c),this.asyncDispatchEvent(b)}},dispatchEvent:a.external.dispatchEvent||function(a){var b=this.getTarget(a);return b?b.dispatchEvent(a):void 0},asyncDispatchEvent:function(a){setTimeout(this.dispatchEvent.bind(this,a),0)}};d.boundHandler=d.eventHandler.bind(d),a.dispatcher=d,a.register=d.register.bind(d),a.unregister=d.unregister.bind(d)}(window.PointerEventsPolyfill),function(a){function b(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),g&&(this.observer=new g(this.mutationWatcher.bind(this)))}var c=Array.prototype.forEach.call.bind(Array.prototype.forEach),d=Array.prototype.map.call.bind(Array.prototype.map),e=Array.prototype.slice.call.bind(Array.prototype.slice),f=Array.prototype.filter.call.bind(Array.prototype.filter),g=window.MutationObserver||window.WebKitMutationObserver,h="[touch-action]",i={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};b.prototype={watchSubtree:function(b){a.targetFinding.canTarget(b)&&this.observer.observe(b,i)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){c(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(h):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(e(b))},installOnLoad:function(){document.addEventListener("DOMContentLoaded",this.installNewSubtree.bind(this,document))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){var b=d(a,this.findElements,this);return b.push(f(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}},g||(b.prototype.watchSubtree=function(){console.warn("PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected")}),a.Installer=b}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=25,e={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},lastTouches:[],isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,e=a.clientX,f=a.clientY,g=0,h=c.length;h>g&&(b=c[g]);g++){var i=Math.abs(e-b.x),j=Math.abs(f-b.y);if(d>=i&&d>=j)return!0}},prepareEvent:function(a){var c=b.cloneEvent(a),d=c.preventDefault;return c.preventDefault=function(){a.preventDefault(),d()},c.pointerId=this.POINTER_ID,c.isPrimary=!0,c.pointerType=this.POINTER_TYPE,c},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.has(this.POINTER_ID);d&&this.cancel(a);var e=this.prepareEvent(a);c.set(this.POINTER_ID,a),b.down(e)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.move(c)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.get(this.POINTER_ID);if(d&&d.button===a.button){var e=this.prepareEvent(a);b.up(e),this.cleanupMouse()}}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.enterOver(c)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.leaveOut(c)}},cancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanupMouse()},cleanupMouse:function(){c["delete"](this.POINTER_ID)}};a.mouseEvents=e}(window.PointerEventsPolyfill),function(a){var b,c=a.dispatcher,d=a.findTarget,e=a.targetFinding.allShadows.bind(a.targetFinding),f=c.pointermap,g=Array.prototype.map.call.bind(Array.prototype.map),h=2500,i=200,j="touch-action",k="string"==typeof document.head.style.touchAction,l={scrollType:new WeakMap,events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){k?c.listen(a,this.events):b.enableOnSubtree(a)},unregister:function(a){k&&c.unlisten(a,this.events)},elementAdded:function(a){var b=a.getAttribute(j),d=this.touchActionToScrollType(b);d&&(this.scrollType.set(a,d),c.listen(a,this.events),e(a).forEach(function(a){this.scrollType.set(a,d),c.listen(a,this.events)},this))},elementRemoved:function(a){this.scrollType["delete"](a),c.unlisten(a,this.events),e(a).forEach(function(a){this.scrollType["delete"](a),c.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(j),d=this.touchActionToScrollType(c),f=this.touchActionToScrollType(b);d&&f?(this.scrollType.set(a,d),e(a).forEach(function(a){this.scrollType.set(a,d)},this)):f?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){(0===f.pointers()||1===f.pointers()&&f.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,i)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},touchToPointer:function(a){var b=c.cloneEvent(a);return b.pointerId=a.identifier+2,b.target=d(b),b.bubbles=!0,b.cancelable=!0,b.detail=this.clickCount,b.button=0,b.buttons=1,b.width=a.webkitRadiusX||a.radiusX||0,b.height=a.webkitRadiusY||a.radiusY||0,b.pressure=a.webkitForce||a.force||.5,b.isPrimary=this.isPrimaryTouch(a),b.pointerType=this.POINTER_TYPE,b},processTouches:function(a,b){var c=a.changedTouches,d=g(c,this.touchToPointer,this);d.forEach(function(b){b.preventDefault=function(){this.scrolling=!1,this.firstXY=null,a.preventDefault()}},this),d.forEach(b,this)},shouldScroll:function(a){if(this.firstXY){var b,c=this.scrollType.get(a.currentTarget);if("none"===c)b=!1;else if("XY"===c)b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)if(c.identifier===b)return!0},vacuumTouches:function(a){var b=a.touches;if(f.pointers()>=b.length){var c=[];f.forEach(function(a,d){if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(this.touchToPointer(e))}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){f.set(a.pointerId,{target:a.target,out:a,outTarget:a.target});c.over(a),c.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,d=f.get(b.pointerId);if(d){var e=d.out,g=d.outTarget;c.move(b),e&&g!==b.target&&(e.relatedTarget=b.target,b.relatedTarget=g,e.target=g,b.target?(c.leaveOut(e),c.enterOver(b)):(b.target=g,b.relatedTarget=null,this.cancelOut(b))),d.out=b,d.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(c.up(a),c.out(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){c.cancel(a),c.out(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){f["delete"](a.pointerId),this.removePrimaryPointer(a)},dedupSynthMouse:function(b){var c=a.mouseEvents.lastTouches,d=b.changedTouches[0];if(this.isPrimaryTouch(d)){var e={x:d.clientX,y:d.clientY};c.push(e);var f=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,c,e);setTimeout(f,h)}}};k||(b=new a.Installer(l.elementAdded,l.elementRemoved,l.elementChanged,l)),a.touchEvents=l}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,e={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var c=a;return d&&(c=b.cloneEvent(a),c.pointerType=this.POINTER_TYPES[a.pointerType]),c},cleanup:function(a){c["delete"](a)},MSPointerDown:function(a){c.set(a.pointerId,a);var d=this.prepareEvent(a);b.down(d)},MSPointerMove:function(a){var c=this.prepareEvent(a);b.move(c)},MSPointerUp:function(a){var c=this.prepareEvent(a);b.up(c),this.cleanup(a.pointerId)},MSPointerOut:function(a){var c=this.prepareEvent(a);b.leaveOut(c)},MSPointerOver:function(a){var c=this.prepareEvent(a);b.enterOver(c)},MSPointerCancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var c=b.makeEvent("lostpointercapture",a);b.dispatchEvent(c)},MSGotPointerCapture:function(a){var c=b.makeEvent("gotpointercapture",a);b.dispatchEvent(c)}};a.msEvents=e}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher;if(void 0===window.navigator.pointerEnabled){if(Object.defineProperty(window.navigator,"pointerEnabled",{value:!0,enumerable:!0}),window.navigator.msPointerEnabled){var c=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:c,enumerable:!0}),b.registerSource("ms",a.msEvents)}else b.registerSource("mouse",a.mouseEvents),void 0!==window.ontouchstart&&b.registerSource("touch",a.touchEvents);b.register(document)}}(window.PointerEventsPolyfill),function(a){function b(a){if(!e.pointermap.has(a))throw new Error("InvalidPointerId")}var c,d,e=a.dispatcher,f=window.navigator;f.msPointerEnabled?(c=function(a){b(a),this.msSetPointerCapture(a)},d=function(a){b(a),this.msReleasePointerCapture(a)}):(c=function(a){b(a),e.setCapture(a,this)},d=function(a){b(a),e.releaseCapture(a,this)}),window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:c},releasePointerCapture:{value:d}})}(window.PointerEventsPolyfill),PointerGestureEvent.prototype.preventTap=function(){this.tapPrevented=!0},function(a){a=a||{},a.utils={LCA:{find:function(a,b){if(a===b)return a;if(a.contains){if(a.contains(b))return a;if(b.contains(a))return b}var c=this.depth(a),d=this.depth(b),e=c-d;for(e>0?a=this.walk(a,e):b=this.walk(b,-e);a&&b&&a!==b;)a=this.walk(a,1),b=this.walk(b,1);return a},walk:function(a,b){for(var c=0;b>c;c++)a=a.parentNode;return a},depth:function(a){for(var b=0;a;)b++,a=a.parentNode;return b}}},a.findLCA=function(b,c){return a.utils.LCA.find(b,c)},window.PointerGestures=a}(window.PointerGestures),function(a){function b(){this.ids=[],this.pointers=[]}b.prototype={set:function(a,b){var c=this.ids.indexOf(a);c>-1?this.pointers[c]=b:(this.ids.push(a),this.pointers.push(b))},has:function(a){return this.ids.indexOf(a)>-1},"delete":function(a){var b=this.ids.indexOf(a);b>-1&&(this.ids.splice(b,1),this.pointers.splice(b,1))},get:function(a){var b=this.ids.indexOf(a);return this.pointers[b]},get size(){return this.pointers.length},clear:function(){this.ids.length=0,this.pointers.length=0}},window.Map&&(b=window.Map),a.PointerMap=b}(window.PointerGestures),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","screenX","screenY","pageX","pageY","tapPrevented"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],d={handledEvents:new WeakMap,targets:new WeakMap,handlers:{},recognizers:{},events:{},registerRecognizer:function(a,b){var c=b;this.recognizers[a]=c,c.events.forEach(function(a){if(c[a]){this.events[a]=!0;var b=c[a].bind(c);this.addHandler(a,b)}},this)},addHandler:function(a,b){var c=a;this.handlers[c]||(this.handlers[c]=[]),this.handlers[c].push(b)},registerTarget:function(a){this.listen(Object.keys(this.events),a)},unregisterTarget:function(a){this.unlisten(Object.keys(this.events),a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.handlers[b];c&&this.makeQueue(c,a),this.handledEvents.set(a,!0)}},makeQueue:function(a,b){var c=this.cloneEvent(b);setTimeout(this.runQueue.bind(this,a,c),0)},runQueue:function(a,b){this.currentPointerId=b.pointerId;for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)c(b);this.currentPointerId=0},listen:function(a,b){a.forEach(function(a){this.addEvent(a,this.boundHandler,!1,b)},this)},unlisten:function(a){a.forEach(function(a){this.removeEvent(a,this.boundHandler,!1,inTarget)},this)},addEvent:function(a,b,c,d){d.addEventListener(a,b,c)},removeEvent:function(a,b,c,d){d.removeEventListener(a,b,c)},makeEvent:function(a,b){return new PointerGestureEvent(a,b)},cloneEvent:function(a){for(var d,e={},f=0;f<b.length;f++)d=b[f],e[d]=a[d]||c[f];return e},dispatchEvent:function(a,b){var c=b||this.targets.get(a);c&&(c.dispatchEvent(a),a.tapPrevented&&this.preventTap(this.currentPointerId))},asyncDispatchEvent:function(a,b){var c=function(){this.dispatchEvent(a,b)}.bind(this);setTimeout(c,0)},preventTap:function(a){var b=this.recognizers.tap;b&&b.preventTap(a)}};d.boundHandler=d.eventHandler.bind(d),a.dispatcher=d;var e=[],f=!1;a.register=function(b){if(f){var c=window.PointerEventsPolyfill;c&&c.register(b),a.dispatcher.registerTarget(b)}else e.push(b)},document.addEventListener("DOMContentLoaded",function(){f=!0,e.push(document),e.forEach(a.register)})}(window.PointerGestures),function(a){var b=a.dispatcher,c={HOLD_DELAY:200,WIGGLE_THRESHOLD:16,events:["pointerdown","pointermove","pointerup","pointercancel"],heldPointer:null,holdJob:null,pulse:function(){var a=Date.now()-this.heldPointer.timeStamp,b=this.held?"holdpulse":"hold";this.fireHold(b,a),this.held=!0},cancel:function(){clearInterval(this.holdJob),this.held&&this.fireHold("release"),this.held=!1,this.heldPointer=null,this.target=null,this.holdJob=null},pointerdown:function(a){a.isPrimary&&!this.heldPointer&&(this.heldPointer=a,this.target=a.target,this.holdJob=setInterval(this.pulse.bind(this),this.HOLD_DELAY))},pointerup:function(a){this.heldPointer&&this.heldPointer.pointerId===a.pointerId&&this.cancel()},pointercancel:function(){this.cancel()},pointermove:function(a){if(this.heldPointer&&this.heldPointer.pointerId===a.pointerId){var b=a.clientX-this.heldPointer.clientX,c=a.clientY-this.heldPointer.clientY;b*b+c*c>this.WIGGLE_THRESHOLD&&this.cancel()}},fireHold:function(a,c){var d={pointerType:this.heldPointer.pointerType};c&&(d.holdTime=c);var e=b.makeEvent(a,d);b.dispatchEvent(e,this.target),e.tapPrevented&&b.preventTap(this.heldPointer.pointerId)}};b.registerRecognizer("hold",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel"],WIGGLE_THRESHOLD:4,clampDir:function(a){return a>0?1:-1},calcPositionDelta:function(a,b){var c=0,d=0;return a&&b&&(c=b.pageX-a.pageX,d=b.pageY-a.pageY),{x:c,y:d}},fireTrack:function(a,c,d){var e=d,f=this.calcPositionDelta(e.downEvent,c),g=this.calcPositionDelta(e.lastMoveEvent,c);g.x&&(e.xDirection=this.clampDir(g.x)),g.y&&(e.yDirection=this.clampDir(g.y));var h={dx:f.x,dy:f.y,ddx:g.x,ddy:g.y,clientX:c.clientX,clientY:c.clientY,pageX:c.pageX,pageY:c.pageY,screenX:c.screenX,screenY:c.screenY,xDirection:e.xDirection,yDirection:e.yDirection,trackInfo:e.trackInfo,relatedTarget:c.target,pointerType:c.pointerType},i=b.makeEvent(a,h);e.lastMoveEvent=c,b.dispatchEvent(i,e.downTarget)},pointerdown:function(a){if(a.isPrimary&&("mouse"===a.pointerType?1===a.buttons:!0)){var b={downEvent:a,downTarget:a.target,trackInfo:{},lastMoveEvent:null,xDirection:0,yDirection:0,tracking:!1};c.set(a.pointerId,b)}},pointermove:function(a){var b=c.get(a.pointerId);if(b)if(b.tracking)this.fireTrack("track",a,b);else{var d=this.calcPositionDelta(b.downEvent,a),e=d.x*d.x+d.y*d.y;e>this.WIGGLE_THRESHOLD&&(b.tracking=!0,this.fireTrack("trackstart",b.downEvent,b),this.fireTrack("track",a,b))}},pointerup:function(a){var b=c.get(a.pointerId);b&&(b.tracking&&this.fireTrack("trackend",a,b),c.delete(a.pointerId))},pointercancel:function(a){this.pointerup(a)}};b.registerRecognizer("track",d)}(window.PointerGestures),function(a){var b=a.dispatcher,c={MIN_VELOCITY:.5,MAX_QUEUE:4,moveQueue:[],target:null,pointerId:null,events:["pointerdown","pointermove","pointerup","pointercancel"],pointerdown:function(a){a.isPrimary&&!this.pointerId&&(this.pointerId=a.pointerId,this.target=a.target,this.addMove(a))},pointermove:function(a){a.pointerId===this.pointerId&&this.addMove(a)},pointerup:function(a){a.pointerId===this.pointerId&&this.fireFlick(a),this.cleanup()},pointercancel:function(){this.cleanup()},cleanup:function(){this.moveQueue=[],this.target=null,this.pointerId=null},addMove:function(a){this.moveQueue.length>=this.MAX_QUEUE&&this.moveQueue.shift(),this.moveQueue.push(a)},fireFlick:function(a){for(var c,d,e,f,g,h,i,j=a,k=this.moveQueue.length,l=0,m=0,n=0,o=0;k>o&&(i=this.moveQueue[o]);o++)c=j.timeStamp-i.timeStamp,d=j.clientX-i.clientX,e=j.clientY-i.clientY,f=d/c,g=e/c,h=Math.sqrt(f*f+g*g),h>n&&(l=f,m=g,n=h);var p=Math.abs(l)>Math.abs(m)?"x":"y",q=this.calcAngle(l,m);if(Math.abs(n)>=this.MIN_VELOCITY){var r=b.makeEvent("flick",{xVelocity:l,yVelocity:m,velocity:n,angle:q,majorAxis:p,pointerType:a.pointerType});b.dispatchEvent(r,this.target)}},calcAngle:function(a,b){return 180*Math.atan2(b,a)/Math.PI}};b.registerRecognizer("flick",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel","keyup"],pointerdown:function(a){a.isPrimary&&!a.tapPrevented&&c.set(a.pointerId,{target:a.target,x:a.clientX,y:a.clientY})},pointermove:function(a){if(a.isPrimary){var b=c.get(a.pointerId);b&&a.tapPrevented&&c.delete(a.pointerId)}},pointerup:function(d){var e=c.get(d.pointerId);if(e&&!d.tapPrevented){var f=a.findLCA(e.target,d.target);if(f){var g=b.makeEvent("tap",{x:d.clientX,y:d.clientY,detail:d.detail,pointerType:d.pointerType});b.dispatchEvent(g,f)}}c.delete(d.pointerId)},pointercancel:function(a){c.delete(a.pointerId)},keyup:function(a){var c=a.keyCode;if(32===c){var d=a.target;d instanceof HTMLInputElement||d instanceof HTMLTextAreaElement||b.dispatchEvent(b.makeEvent("tap",{x:0,y:0,detail:0,pointerType:"unavailable"}),d)}},preventTap:function(a){c.delete(a)}};b.registerRecognizer("tap",d)}(window.PointerGestures),function(){"use strict";function a(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function b(a,b,c,d){this.closed=!1,this.node=a,this.property=b,this.model=c,this.path=Path.get(d),(this.model instanceof PathObserver||this.model instanceof CompoundPathObserver)&&this.path===l?(this.observer=this.model,this.observer.target=this,this.observer.callback=this.valueChanged):this.observer=new PathObserver(this.model,this.path,this.valueChanged,this),this.valueChanged(this.value)}function c(a,c,d,e){this.conditional="?"==c[c.length-1],this.conditional&&(a.removeAttribute(c),c=c.slice(0,-1)),b.call(this,a,c,d,e)}function d(a){switch(a.type){case"checkbox":return m;
-case"radio":case"select-multiple":case"select-one":return"change";default:return"input"}}function e(a,c,e,f){b.call(this,a,c,e,f),this.eventType=d(this.node),this.boundNodeValueChanged=this.nodeValueChanged.bind(this),this.node.addEventListener(this.eventType,this.boundNodeValueChanged,!0)}function f(b){if(b.form)return j(b.form.elements,function(a){return a!=b&&"INPUT"==a.tagName&&"radio"==a.type&&a.name==b.name});var c=a(b);if(!c)return[];var d=c.querySelectorAll('input[type="radio"][name="'+b.name+'"]');return j(d,function(a){return a!=b&&!a.form})}function g(a,b,c){e.call(this,a,"checked",b,c)}function h(a,b,c){e.call(this,a,"value",b,c)}function i(a,b,c,d){e.call(this,a,b,c,d)}var j=Array.prototype.filter.call.bind(Array.prototype.filter),k="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c};"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)}),Node.prototype.bind=function(a,b,c){console.error("Unhandled binding to Node: ",this,a,b,c)},Node.prototype.unbind=function(a){this.bindings||(this.bindings={});var b=this.bindings[a];b&&("function"==typeof b.close&&b.close(),this.bindings[a]=void 0)},Node.prototype.unbindAll=function(){if(this.bindings){for(var a=Object.keys(this.bindings),b=0;b<a.length;b++){var c=this.bindings[a[b]];c&&c.close()}this.bindings={}}};var l=Path.get("value");b.prototype={valueChanged:function(a){this.node[this.property]=this.sanitizeBoundValue(a)},sanitizeBoundValue:function(a){return void 0==a?"":String(a)},close:function(){this.closed||(this.observer.close(),this.observer=void 0,this.node=void 0,this.model=void 0,this.closed=!0)},get value(){return this.observer.value},set value(a){this.observer.setValue(a)},reset:function(){this.observer.reset()}},Text.prototype.bind=function(a,c,d){return"textContent"!==a?Node.prototype.bind.call(this,a,c,d):(this.unbind(a),this.bindings[a]=new b(this,"data",c,d))},c.prototype=k({__proto__:b.prototype,valueChanged:function(a){return this.conditional?(a?this.node.setAttribute(this.property,""):this.node.removeAttribute(this.property),void 0):(this.node.setAttribute(this.property,this.sanitizeBoundValue(a)),void 0)}}),Element.prototype.bind=function(a,b,d){return this.unbind(a),this.bindings[a]=new c(this,a,b,d)};var m;!function(){var a=document.createElement("div"),b=a.appendChild(document.createElement("input"));b.setAttribute("type","checkbox");var c,d=0;b.addEventListener("click",function(){d++,c=c||"click"}),b.addEventListener("change",function(){d++,c=c||"change"});var e=document.createEvent("MouseEvent");e.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),b.dispatchEvent(e),m=1==d?"change":c}(),e.prototype=k({__proto__:b.prototype,nodeValueChanged:function(){this.value=this.node[this.property],this.reset(),this.postUpdateBinding(),Platform.performMicrotaskCheckpoint()},postUpdateBinding:function(){},close:function(){this.closed||(this.node.removeEventListener(this.eventType,this.boundNodeValueChanged,!0),b.prototype.close.call(this))}}),g.prototype=k({__proto__:e.prototype,sanitizeBoundValue:function(a){return Boolean(a)},postUpdateBinding:function(){"INPUT"===this.node.tagName&&"radio"===this.node.type&&f(this.node).forEach(function(a){var b=a.bindings.checked;b&&(b.value=!1)})}}),HTMLInputElement.prototype.bind=function(a,b,c){return"value"!==a&&"checked"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]="value"===a?new e(this,"value",b,c):new g(this,b,c))},HTMLTextAreaElement.prototype.bind=function(a,b,c){return"value"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]=new e(this,a,b,c))},h.prototype=k({__proto__:e.prototype,valueChanged:function(a){var b,c,d=this.node.parentNode instanceof HTMLSelectElement?this.node.parentNode:void 0;d&&d.bindings&&d.bindings.value instanceof i&&(b=d.bindings.value,c=d.value),e.prototype.valueChanged.call(this,a),b&&!b.closed&&d.value!==c&&b.nodeValueChanged()}}),HTMLOptionElement.prototype.bind=function(a,b,c){return"value"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]=new h(this,b,c))},i.prototype=k({__proto__:e.prototype,valueChanged:function(a){function b(){d.node[d.property]=a,d.node[d.property]!=a&&c--&&n(b)}if(this.node[this.property]=a,this.node[this.property]!=a){var c=2,d=this;n(b)}}}),HTMLSelectElement.prototype.bind=function(a,b,c){return"selectedindex"===a&&(a="selectedIndex"),"selectedIndex"!==a&&"value"!==a?HTMLElement.prototype.bind.call(this,a,b,c):(this.unbind(a),this.removeAttribute(a),this.bindings[a]=new i(this,a,b,c))};var n=function(){function a(a){this.nextRunner=a,this.value=!1,this.lastValue=this.value,this.scheduled=[],this.scheduledIds=[],this.running=!1,this.observer=new PathObserver(this,"value",this.run,this)}function b(a){var b=a[e];a[e]||(b=d++,a[e]=b),c.schedule(a,b)}a.prototype={schedule:function(a,b){if(!this.scheduledIds[b]){if(this.running)return this.nextRunner.schedule(a,b);this.scheduledIds[b]=!0,this.scheduled.push(a),this.lastValue===this.value&&(this.value=!this.value)}},run:function(){this.running=!0;for(var a=0;a<this.scheduled.length;a++){var b=this.scheduled[a],c=b[e];this.scheduledIds[c]=!1,"function"==typeof b?b():b.resolve()}this.scheduled=[],this.scheduledIds=[],this.lastValue=this.value,this.running=!1}};var c=new a(new a),d=1,e="__scheduledId__";return b}()}(this),function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function d(a){return H[a.tagName]&&a.hasAttribute("template")}function e(a){return"TEMPLATE"==a.tagName||d(a)}function f(a){return I&&"TEMPLATE"==a.tagName}function g(a,b){var c=a.querySelectorAll(J);e(a)&&b(a),C(c,b)}function h(a){function b(a){HTMLTemplateElement.decorate(a)||h(a.content)}g(a,b)}function i(a,b){Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))})}function j(a){var b=a.ownerDocument;if(!b.defaultView)return b;var c=b.templateContentsOwner_;if(!c){for(c=b.implementation.createHTMLDocument("");c.lastChild;)c.removeChild(c.lastChild);b.templateContentsOwner_=c}return c}function k(a){if(!a.stagingDocument_){var b=a.ownerDocument;b.stagingDocument_||(b.stagingDocument_=b.implementation.createHTMLDocument(""),b.stagingDocument_.stagingDocument_=b.stagingDocument_),a.stagingDocument_=b.stagingDocument_}return a.stagingDocument_}function l(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];G[e.name]&&("template"!==e.name&&b.setAttribute(e.name,e.value),a.removeAttribute(e.name))}return b}function m(a,b,c){var d=a.content;if(c)return d.appendChild(b),void 0;for(var e;e=b.firstChild;)d.appendChild(e)}function n(a){"TEMPLATE"===a.tagName?I||(L?a.__proto__=HTMLTemplateElement.prototype:i(a,HTMLTemplateElement.prototype)):(i(a,HTMLTemplateElement.prototype),Object.defineProperty(a,"content",N))}function o(a){a.setModelFn_||(a.setModelFn_=function(){v(a,a.model,a.prepareBindingFn_)}),K(a.setModelFn_)}function p(a,b,c,d){if(a&&a.length){for(var e,f=a.length,g=0,h=0,i=0;f>h;){if(g=a.indexOf("{{",h),i=0>g?-1:a.indexOf("}}",g+2),0>i){if(!e)return;e.push(a.slice(h));break}e=e||[],e.push(a.slice(h,g));var j=a.slice(g+2,i).trim();e.push(Path.get(j));var k=d&&d(j,b,c);e.push(k),h=i+2}return h===f&&e.push(""),e.hasOnePath=4===e.length,e.isSimplePath=e.hasOnePath&&""==e[0]&&""==e[3],e.combinator=function(a){for(var b=e[0],c=1;c<e.length;c+=3){var d=e.hasOnePath?a:a[(c-1)/3];void 0!==d&&(b+=d),b+=e[c+2]}return b},e}}function q(a,b,c,d,e){var f,g;b.hasOnePath||(f=new CompoundPathObserver(void 0,void 0,b.combinator)),b.isSimplePath||(g=O);for(var h=1;h<b.length;h+=3){var i=(b[h],d),j=b[h],k=b[h+1],l=k&&k(d,c);void 0!==l&&(i=l,j=O),b.hasOnePath?b.isSimplePath?(f=i,g=j):f=new PathObserver(i,j,void 0,void 0,b.combinator):f.addPath(i,j)}b.hasOnePath||f.start();var m=c.bind(a,f,g);e&&e.push(m)}function r(a,b,c,d){for(var e=0;e<a.length;e+=2)q(a[e],a[e+1],b,c,d)}function s(a,c){b(a);for(var d,f=e(a),g=!1,h=!1,i=0;i<a.attributes.length;i++){for(var j=a.attributes[i],k=j.name,l=j.value;"_"===k[0];)k=k.substring(1);f&&(k===F?(g=!0,l=l||"{{}}"):(k===D||k===E)&&(h=!0,l=l||"{{}}"));var m=p(l,k,a,c);m&&(d=d||[],d.push(k,m))}return g&&!h&&(d=d||[],d.push(D,p("{{}}",D,a,c))),d}function t(a,b){if(a.nodeType===Node.ELEMENT_NODE)return s(a,b);if(a.nodeType===Node.TEXT_NODE){var c=p(a.data,"textContent",a,b);if(c)return["textContent",c]}}function u(a,b,c,d,e){if(b&&(b.templateRef&&(HTMLTemplateElement.decorate(a,b.templateRef),d&&a.setBindingDelegate_(d)),b.length&&r(b,a,c,e),b.children))for(var f=0,g=a.firstChild;g;g=g.nextSibling)u(g,b.children[f++],c,d,e)}function v(a,c,d){b(a);var e=t(a,d);e&&r(e,a,c);for(var f=a.firstChild;f;f=f.nextSibling)v(f,c,d)}function w(a,b){var c=b.importNode(a,!1);if(a.isTemplate_)return c;for(var d=a.firstChild;d;d=d.nextSibling)c.appendChild(w(d,b));return c}function x(a,b){var c=t(a,b);e(a)&&(a.isTemplate_=!0,c=c||[],c.templateRef=a);for(var d=a.firstChild,f=0;d;d=d.nextSibling,f++){var g=x(d,b);g&&(c=c||[],c.children=c.children||{},c.children[f]=g)}return c}function y(a,b,c){this.firstNode=a,this.lastNode=b,this.model=c}function z(a,b){if(a.firstChild)for(var c=new y(a.firstChild,a.lastChild,b),d=c.firstNode;d;)d.templateInstance_=c,d=d.nextSibling}function A(a){this.closed=!1,this.templateElement_=a,this.terminators=[],this.iteratedValue=void 0,this.arrayObserver=void 0,this.depsChanged=!1,this.hasRepeat=!1,this.repeatModel=void 0,this.repeatPath=void 0,this.hasBind=!1,this.bindModel=void 0,this.bindPath=void 0,this.hasIf=!1,this.ifModel=void 0,this.ifPath=void 0}var B,C=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.Map&&"function"==typeof a.Map.prototype.forEach?B=a.Map:(B=function(){this.keys=[],this.values=[]},B.prototype={set:function(a,b){var c=this.keys.indexOf(a);0>c?(this.keys.push(a),this.values.push(b)):this.values[c]=b},get:function(a){var b=this.keys.indexOf(a);if(!(0>b))return this.values[b]},"delete":function(a){var b=this.keys.indexOf(a);return 0>b?!1:(this.keys.splice(b,1),this.values.splice(b,1),!0)},forEach:function(a,b){for(var c=0;c<this.keys.length;c++)a.call(b||this,this.values[c],this.keys[c],this)}});"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)});var D="bind",E="repeat",F="if",G={template:!0,repeat:!0,bind:!0,ref:!0},H={THEAD:!0,TBODY:!0,TFOOT:!0,TH:!0,TR:!0,TD:!0,COLGROUP:!0,COL:!0,CAPTION:!0,OPTION:!0,OPTGROUP:!0},I="undefined"!=typeof HTMLTemplateElement,J="template, "+Object.keys(H).map(function(a){return a.toLowerCase()+"[template]"}).join(", "),K=function(){function a(a){this.nextRunner=a,this.value=!1,this.lastValue=this.value,this.scheduled=[],this.scheduledIds=[],this.running=!1,this.observer=new PathObserver(this,"value",this.run,this)}function b(a){var b=a[e];a[e]||(b=d++,a[e]=b),c.schedule(a,b)}a.prototype={schedule:function(a,b){if(!this.scheduledIds[b]){if(this.running)return this.nextRunner.schedule(a,b);this.scheduledIds[b]=!0,this.scheduled.push(a),this.lastValue===this.value&&(this.value=!this.value)}},run:function(){this.running=!0;for(var a=0;a<this.scheduled.length;a++){var b=this.scheduled[a],c=b[e];this.scheduledIds[c]=!1,"function"==typeof b?b():b.resolve()}this.scheduled=[],this.scheduledIds=[],this.lastValue=this.value,this.running=!1}};var c=new a(new a),d=1,e="__scheduledId__";return b}();document.addEventListener("DOMContentLoaded",function(){h(document),Platform.performMicrotaskCheckpoint()},!1),I||(a.HTMLTemplateElement=function(){throw TypeError("Illegal constructor")});var L="__proto__"in{};HTMLTemplateElement.decorate=function(a,c){if(a.templateIsDecorated_)return!1;var e=a;e.templateIsDecorated_=!0;var g=f(e),i=g,k=!g,o=!1;if(!g&&d(e)&&(b(!c),e=l(a),e.templateIsDecorated_=!0,g=f(e),o=!0),!g){n(e);var p=j(e);e.content_=p.createDocumentFragment()}return c?e.instanceRef_=c:k?m(e,a,o):i&&h(e.content),!0},HTMLTemplateElement.bootstrap=h;var M=a.HTMLUnknownElement||HTMLElement,N={get:function(){return this.content_},enumerable:!0,configurable:!0};I||(HTMLTemplateElement.prototype=Object.create(M.prototype),Object.defineProperty(HTMLTemplateElement.prototype,"content",N)),i(HTMLTemplateElement.prototype,{bind:function(a,b,c){return this.iterator_||(this.iterator_=new A(this)),this.bindings=this.bindings||{},"bind"===a?(this.iterator_.hasBind=!0,this.iterator_.bindModel=b,this.iterator_.bindPath=c,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.bind=this.iterator_):"repeat"===a?(this.iterator_.hasRepeat=!0,this.iterator_.repeatModel=b,this.iterator_.repeatPath=c,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.repeat=this.iterator_):"if"===a?(this.iterator_.hasIf=!0,this.iterator_.ifModel=b,this.iterator_.ifPath=c,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.if=this.iterator_):HTMLElement.prototype.bind.call(this,a,b,c)},unbind:function(a){if("bind"===a){if(!this.iterator_)return;return this.iterator_.hasBind=!1,this.iterator_.bindModel=void 0,this.iterator_.bindPath=void 0,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.bind=void 0}if("repeat"===a){if(!this.iterator_)return;return this.iterator_.hasRepeat=!1,this.iterator_.repeatModel=void 0,this.iterator_.repeatPath=void 0,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.repeat=void 0}if("if"===a){if(!this.iterator_)return;return this.iterator_.hasIf=!1,this.iterator_.ifModel=void 0,this.iterator_.ifPath=void 0,this.iterator_.depsChanging||(this.iterator_.depsChanging=!0,K(this.iterator_)),this.bindings.if=void 0}return HTMLElement.prototype.unbind.call(this,a)},createInstance:function(a,b){var c=this.ref.content,d=c.bindingMap_;d||(d=x(c,this.prepareBindingFn_)||[],c.bindingMap_=d);var e=k(this),f=w(c,e);return u(f,d,a,this.bindingDelegate_,b),z(f,a),f},get model(){return this.model_},set model(a){this.model_=a,o(this)},get bindingDelegate(){return this.bindingDelegate_},setBindingDelegate_:function(a){function b(b){var c=a&&a[b];if("function"==typeof c)return function(){return c.apply(a,arguments)}}this.bindingDelegate_=a,this.prepareBindingFn_=b("prepareBinding"),this.prepareInstanceModelFn_=b("prepareInstanceModel"),this.prepareInstancePositionChangedFn_=b("prepareInstancePositionChanged")},set bindingDelegate(a){this.setBindingDelegate_(a),o(this)},get ref(){var a,b=this.getAttribute("ref");if(b){var d=c(this);d&&(a=d.getElementById(b))}if(a||(a=this.instanceRef_),!a)return this;var e=a.ref;return e?e:a}});var O=Path.get("value");Object.defineProperty(Node.prototype,"templateInstance",{get:function(){var a=this.templateInstance_;return a?a:this.parentNode?this.parentNode.templateInstance:void 0}}),A.prototype={resolve:function(){if(this.depsChanging=!1,this.valueObserver&&(this.valueObserver.close(),this.valueObserver=void 0),!this.hasRepeat&&!this.hasBind)return this.valueChanged(),void 0;var a=this.hasRepeat===!0,b=a?this.repeatModel:this.bindModel,c=a?this.repeatPath:this.bindPath;if(this.hasIf){var d=function(b){var c=b[0],d=b[1];return d?a?c:[c]:void 0};this.valueObserver=new CompoundPathObserver(this.valueChanged,this,d),this.valueObserver.addPath(b,c),this.valueObserver.addPath(this.ifModel,this.ifPath),this.valueObserver.start()}else{var d=this.hasRepeat?void 0:function(a){return[a]};this.valueObserver=new PathObserver(b,c,this.valueChanged,this,d)}this.valueChanged(this.valueObserver.value)},valueChanged:function(a){Array.isArray(a)||(a=void 0);var b=this.iteratedValue;this.unobserve(),this.iteratedValue=a,this.iteratedValue&&(this.arrayObserver=new ArrayObserver(this.iteratedValue,this.handleSplices,this));var c=ArrayObserver.calculateSplices(this.iteratedValue||[],b||[]);c.length&&this.handleSplices(c)},getTerminatorAt:function(a){if(-1==a)return this.templateElement_;var b=this.terminators[2*a];if(b.nodeType!==Node.ELEMENT_NODE||this.templateElement_===b)return b;var c=b.iterator_;return c?c.getTerminatorAt(c.terminators.length/2-1):b},insertInstanceAt:function(a,b,c,d){var e=this.getTerminatorAt(a-1),f=e;b?f=b.lastChild||f:c&&(f=c[c.length-1]||f),this.terminators.splice(2*a,0,f,d);var g=this.templateElement_.parentNode,h=e.nextSibling;if(b)g.insertBefore(b,h);else if(c)for(var i=0;i<c.length;i++)g.insertBefore(c[i],h)},extractInstanceAt:function(a){var b=[],c=this.getTerminatorAt(a-1),d=this.getTerminatorAt(a);b.bound=this.terminators[2*a+1],this.terminators.splice(2*a,2);for(var e=this.templateElement_.parentNode;d!==c;){var f=c.nextSibling;f==d&&(d=c),e.removeChild(f),b.push(f)}return b},getDelegateFn:function(a){return a=a&&a(this.templateElement_),"function"==typeof a?a:null},handleSplices:function(a){if(!this.closed){var b=this.templateElement_;if(!b.parentNode||!b.ownerDocument.defaultView)return this.close(),void 0;void 0===this.instanceModelFn_&&(this.instanceModelFn_=this.getDelegateFn(b.prepareInstanceModelFn_)),void 0===this.instancePositionChangedFn_&&(this.instancePositionChangedFn_=this.getDelegateFn(b.prepareInstancePositionChangedFn_));var c=new B,d=0;a.forEach(function(a){a.removed.forEach(function(b){var e=this.extractInstanceAt(a.index+d);c.set(b,e)},this),d-=a.addedCount},this),a.forEach(function(a){for(var b=a.index;b<a.index+a.addedCount;b++){var d,e=this.iteratedValue[b],f=void 0,g=c.get(e);g?(c.delete(e),d=g.bound):(d=[],this.instanceModelFn_&&(e=this.instanceModelFn_(e)),void 0!==e&&(f=this.templateElement_.createInstance(e,d))),this.insertInstanceAt(b,f,g,d)}},this),c.forEach(function(a){this.closeInstanceBindings(a.bound)},this),this.instancePositionChangedFn_&&this.reportInstancesMoved(a)}},reportInstanceMoved:function(a){var b=this.getTerminatorAt(a-1),c=this.getTerminatorAt(a);if(b!==c){var d=b.nextSibling.templateInstance;this.instancePositionChangedFn_(d,a)}},reportInstancesMoved:function(a){for(var b=0,c=0,d=0;d<a.length;d++){var e=a[d];if(0!=c)for(;b<e.index;)this.reportInstanceMoved(b),b++;else b=e.index;for(;b<e.index+e.addedCount;)this.reportInstanceMoved(b),b++;c+=e.addedCount-e.removed.length}if(0!=c)for(var f=this.terminators.length/2;f>b;)this.reportInstanceMoved(b),b++},closeInstanceBindings:function(a){for(var b=0;b<a.length;b++)a[b].close()},unobserve:function(){this.arrayObserver&&(this.arrayObserver.close(),this.arrayObserver=void 0)},close:function(){if(!this.closed){this.unobserve();for(var a=1;a<this.terminators.length;a+=2)this.closeInstanceBindings(this.terminators[a]);this.terminators.length=0,this.valueObserver&&this.valueObserver.close(),this.valueObserver=void 0,this.templateElement_.iterator_=void 0,this.closed=!0}}},HTMLTemplateElement.forAllTemplatesFrom_=g}(this),function(a){"use strict";function b(a,b){if(!a)throw new Error("ASSERT: "+b)}function c(a){return a>=48&&57>=a}function d(a){return 32===a||9===a||11===a||12===a||160===a||a>=5760&&" ᠎              ".indexOf(String.fromCharCode(a))>0}function e(a){return 10===a||13===a||8232===a||8233===a}function f(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a}function g(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a||a>=48&&57>=a}function h(a){return"this"===a}function i(){for(;Y>X&&d(W.charCodeAt(X));)++X}function j(){var a,b;for(a=X++;Y>X&&(b=W.charCodeAt(X),g(b));)++X;return W.slice(a,X)}function k(){var a,b,c;return a=X,b=j(),c=1===b.length?S.Identifier:h(b)?S.Keyword:"null"===b?S.NullLiteral:"true"===b||"false"===b?S.BooleanLiteral:S.Identifier,{type:c,value:b,range:[a,X]}}function l(){var a,b,c=X,d=W.charCodeAt(X),e=W[X];switch(d){case 46:case 40:case 41:case 59:case 44:case 123:case 125:case 91:case 93:case 58:case 63:return++X,{type:S.Punctuator,value:String.fromCharCode(d),range:[c,X]};default:if(a=W.charCodeAt(X+1),61===a)switch(d){case 37:case 38:case 42:case 43:case 45:case 47:case 60:case 62:case 124:return X+=2,{type:S.Punctuator,value:String.fromCharCode(d)+String.fromCharCode(a),range:[c,X]};case 33:case 61:return X+=2,61===W.charCodeAt(X)&&++X,{type:S.Punctuator,value:W.slice(c,X),range:[c,X]}}}return b=W[X+1],e===b&&"&|".indexOf(e)>=0?(X+=2,{type:S.Punctuator,value:e+b,range:[c,X]}):"<>=!+-*%&|^/".indexOf(e)>=0?(++X,{type:S.Punctuator,value:e,range:[c,X]}):(s({},V.UnexpectedToken,"ILLEGAL"),void 0)}function m(){var a,d,e;if(e=W[X],b(c(e.charCodeAt(0))||"."===e,"Numeric literal must start with a decimal digit or a decimal point"),d=X,a="","."!==e){for(a=W[X++],e=W[X],"0"===a&&e&&c(e.charCodeAt(0))&&s({},V.UnexpectedToken,"ILLEGAL");c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("."===e){for(a+=W[X++];c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("e"===e||"E"===e)if(a+=W[X++],e=W[X],("+"===e||"-"===e)&&(a+=W[X++]),c(W.charCodeAt(X)))for(;c(W.charCodeAt(X));)a+=W[X++];else s({},V.UnexpectedToken,"ILLEGAL");return f(W.charCodeAt(X))&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.NumericLiteral,value:parseFloat(a),range:[d,X]}}function n(){var a,c,d,f="",g=!1;for(a=W[X],b("'"===a||'"'===a,"String literal must starts with a quote"),c=X,++X;Y>X;){if(d=W[X++],d===a){a="";break}if("\\"===d)if(d=W[X++],d&&e(d.charCodeAt(0)))"\r"===d&&"\n"===W[X]&&++X;else switch(d){case"n":f+="\n";break;case"r":f+="\r";break;case"t":f+="	";break;case"b":f+="\b";break;case"f":f+="\f";break;case"v":f+="";break;default:f+=d}else{if(e(d.charCodeAt(0)))break;f+=d}}return""!==a&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.StringLiteral,value:f,octal:g,range:[c,X]}}function o(a){return a.type===S.Identifier||a.type===S.Keyword||a.type===S.BooleanLiteral||a.type===S.NullLiteral}function p(){var a;return i(),X>=Y?{type:S.EOF,range:[X,X]}:(a=W.charCodeAt(X),40===a||41===a||58===a?l():39===a||34===a?n():f(a)?k():46===a?c(W.charCodeAt(X+1))?m():l():c(a)?m():l())}function q(){var a;return a=$,X=a.range[1],$=p(),X=a.range[1],a}function r(){var a;a=X,$=p(),X=a}function s(a,c){var d,e=Array.prototype.slice.call(arguments,2),f=c.replace(/%(\d)/g,function(a,c){return b(c<e.length,"Message reference must be in range"),e[c]});throw d=new Error(f),d.index=X,d.description=f,d}function t(a){s(a,V.UnexpectedToken,a.value)}function u(a){var b=q();(b.type!==S.Punctuator||b.value!==a)&&t(b)}function v(a){return $.type===S.Punctuator&&$.value===a}function w(a){return $.type===S.Keyword&&$.value===a}function x(){var a=[];for(u("[");!v("]");)v(",")?(q(),a.push(null)):(a.push(bb()),v("]")||u(","));return u("]"),Z.createArrayExpression(a)}function y(){var a;return i(),a=q(),a.type===S.StringLiteral||a.type===S.NumericLiteral?Z.createLiteral(a):Z.createIdentifier(a.value)}function z(){var a,b;return a=$,i(),(a.type===S.EOF||a.type===S.Punctuator)&&t(a),b=y(),u(":"),Z.createProperty("init",b,bb())}function A(){var a=[];for(u("{");!v("}");)a.push(z()),v("}")||u(",");return u("}"),Z.createObjectExpression(a)}function B(){var a;return u("("),a=bb(),u(")"),a}function C(){var a,b,c;return v("(")?B():(a=$.type,a===S.Identifier?c=Z.createIdentifier(q().value):a===S.StringLiteral||a===S.NumericLiteral?c=Z.createLiteral(q()):a===S.Keyword?w("this")&&(q(),c=Z.createThisExpression()):a===S.BooleanLiteral?(b=q(),b.value="true"===b.value,c=Z.createLiteral(b)):a===S.NullLiteral?(b=q(),b.value=null,c=Z.createLiteral(b)):v("[")?c=x():v("{")&&(c=A()),c?c:(t(q()),void 0))}function D(){var a=[];if(u("("),!v(")"))for(;Y>X&&(a.push(bb()),!v(")"));)u(",");return u(")"),a}function E(){var a;return a=q(),o(a)||t(a),Z.createIdentifier(a.value)}function F(){return u("."),E()}function G(){var a;return u("["),a=bb(),u("]"),a}function H(){var a,b;for(a=C();v(".")||v("[");)v("[")?(b=G(),a=Z.createMemberExpression("[",a,b)):(b=F(),a=Z.createMemberExpression(".",a,b));return a}function I(){var a,b;return $.type!==S.Punctuator&&$.type!==S.Keyword?b=ab():v("+")||v("-")||v("!")?(a=q(),b=I(),b=Z.createUnaryExpression(a.value,b)):w("delete")||w("void")||w("typeof")?s({},V.UnexpectedToken):b=ab(),b}function J(a){var b=0;if(a.type!==S.Punctuator&&a.type!==S.Keyword)return 0;switch(a.value){case"||":b=1;break;case"&&":b=2;break;case"==":case"!=":case"===":case"!==":b=6;break;case"<":case">":case"<=":case">=":case"instanceof":b=7;break;case"in":b=7;break;case"+":case"-":b=9;break;case"*":case"/":case"%":b=11}return b}function K(){var a,b,c,d,e,f,g,h;if(g=I(),b=$,c=J(b),0===c)return g;for(b.prec=c,q(),e=I(),d=[g,b,e];(c=J($))>0;){for(;d.length>2&&c<=d[d.length-2].prec;)e=d.pop(),f=d.pop().value,g=d.pop(),a=Z.createBinaryExpression(f,g,e),d.push(a);b=q(),b.prec=c,d.push(b),a=I(),d.push(a)}for(h=d.length-1,a=d[h];h>1;)a=Z.createBinaryExpression(d[h-1].value,d[h-2],a),h-=2;return a}function L(){var a,b,c;return a=K(),v("?")&&(q(),b=L(),u(":"),c=L(),a=Z.createConditionalExpression(a,b,c)),a}function M(){var a,b;return a=q(),a.type!==S.Identifier&&t(a),b=v("(")?D():[],Z.createFilter(a.value,b)}function N(){for(;v("|");)q(),M()}function O(){i(),r();var a=bb();a&&(","===$.value||"in"==$.value&&a.type===U.Identifier?Q(a):(N(),"as"===$.value?P(a):Z.createTopLevel(a))),$.type!==S.EOF&&t($)}function P(a){q();var b=q().value;Z.createAsExpression(a,b)}function Q(a){var b;","===$.value&&(q(),$.type!==S.Identifier&&t($),b=q().value),q();var c=bb();N(),Z.createInExpression(a.name,b,c)}function R(a,b){return Z=b,W=a,X=0,Y=W.length,$=null,_={labelSet:{}},O()}var S,T,U,V,W,X,Y,Z,$,_;S={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8},T={},T[S.BooleanLiteral]="Boolean",T[S.EOF]="<end>",T[S.Identifier]="Identifier",T[S.Keyword]="Keyword",T[S.NullLiteral]="Null",T[S.NumericLiteral]="Numeric",T[S.Punctuator]="Punctuator",T[S.StringLiteral]="String",U={ArrayExpression:"ArrayExpression",BinaryExpression:"BinaryExpression",CallExpression:"CallExpression",ConditionalExpression:"ConditionalExpression",EmptyStatement:"EmptyStatement",ExpressionStatement:"ExpressionStatement",Identifier:"Identifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",ObjectExpression:"ObjectExpression",Program:"Program",Property:"Property",ThisExpression:"ThisExpression",UnaryExpression:"UnaryExpression"},V={UnexpectedToken:"Unexpected token %0",UnknownLabel:"Undefined label '%0'",Redeclaration:"%0 '%1' has already been declared"};var ab=H,bb=L;a.esprima={parse:R}}(this),function(a){"use strict";function b(a,b,d,e){var f;try{if(f=c(a),f.scopeIdent&&(d.nodeType!==Node.ELEMENT_NODE||"TEMPLATE"!==d.tagName||"bind"!==b&&"repeat"!==b))throw Error("as and in can only be used within <template bind/repeat>")}catch(g){return console.error("Invalid expression syntax: "+a,g),void 0}return function(a,b){var c=f.getBinding(a,e);return f.scopeIdent&&c&&(b.polymerExpressionScopeIdent_=f.scopeIdent,f.indexIdent&&(b.polymerExpressionIndexIdent_=f.indexIdent)),c}}function c(a){var b=n[a];if(!b){var c=new j;esprima.parse(a,c),b=new k(c),n[a]=b}return b}function d(a){this.value=a}function e(a,b,c){this.delegate=a,this.name=b,this.last=c}function f(a,b){this.object=a,this.property=b}function g(a,b){this.name=a,this.args=[];for(var c=0;c<b.length;c++)this.args[c]=i(b[c])}function h(){throw Error("Not Implemented")}function i(a){return"function"==typeof a?a:a.valueFn()}function j(){this.expression=null,this.filters=[],this.deps={},this.depsList=[],this.currentPath=void 0,this.scopeIdent=void 0,this.indexIdent=void 0}function k(a){if(this.scopeIdent=a.scopeIdent,this.indexIdent=a.indexIdent,!a.expression)throw Error("No expression found.");this.expression=a.expression,i(this.expression),this.paths=a.depsList,this.filters=a.filters}function l(a){return String(a).replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}function m(){}var n=Object.create(null);d.prototype={valueFn:function(){var a=this.value;return function(){return a}}},e.prototype={getPath:function(){return this.path_||(this.path_=this.last?Path.get(this.last.getPath()+"."+this.name):Path.get(this.name)),this.path_},valueFn:function(){if(!this.valueFn_){var a=this.getPath(),b=this.delegate.deps[a];void 0===b&&(b=this.delegate.deps[a]=this.delegate.depsList.length,this.delegate.depsList.push(a));var c=this.delegate.depsList;this.valueFn_=function(a){return 1===c.length?a:a[b]}}return this.valueFn_},setValue:function(a,b){return this.getPath().setValueFrom(a,b)}},f.prototype={valueFn:function(){var a=this.object,b=this.property;return function(c){return a(c)[b(c)]}},setValue:function(a,b,c){a=this.object(c);var d=this.property(c);return a[d]=b}},g.prototype={transform:function(a,b,c,d,e){var f=d[this.name];if(f)e=void 0;else if(f=e[this.name],!f)return console.error("Cannot find filter: "+this.name),void 0;if(c?f=f.toModel:"function"==typeof f.toDOM&&(f=f.toDOM),"function"!=typeof f)return console.error("No "+(c?"toModel":"toDOM")+" found on"+this.name),void 0;for(var g=[a],h=0;h<this.args.length;h++)g[h+1]=i(this.args[h])(b);return f.apply(e,g)}};var o={"+":function(a){return+a},"-":function(a){return-a},"!":function(a){return!a}},p={"+":function(a,b){return a+b},"-":function(a,b){return a-b},"*":function(a,b){return a*b},"/":function(a,b){return a/b},"%":function(a,b){return a%b},"<":function(a,b){return b>a},">":function(a,b){return a>b},"<=":function(a,b){return b>=a},">=":function(a,b){return a>=b},"==":function(a,b){return a==b},"!=":function(a,b){return a!=b},"===":function(a,b){return a===b},"!==":function(a,b){return a!==b},"&&":function(a,b){return a&&b},"||":function(a,b){return a||b}};j.prototype={createUnaryExpression:function(a,b){if(!o[a])throw Error("Disallowed operator: "+a);return b=i(b),function(c){return o[a](b(c))}},createBinaryExpression:function(a,b,c){if(!p[a])throw Error("Disallowed operator: "+a);return b=i(b),c=i(c),function(d){return p[a](b(d),c(d))}},createConditionalExpression:function(a,b,c){return a=i(a),b=i(b),c=i(c),function(d){return a(d)?b(d):c(d)}},createIdentifier:function(a){var b=new e(this,a);return b.type="Identifier",b},createMemberExpression:function(a,b,c){if(b instanceof e){if("."==a)return new e(this,c.name,b);if(c instanceof d&&Path.get(c.value).valid)return new e(this,c.value,b)}return new f(i(b),i(c))},createLiteral:function(a){return new d(a.value)},createArrayExpression:function(a){for(var b=0;b<a.length;b++)a[b]=i(a[b]);return function(b){for(var c=[],d=0;d<a.length;d++)c.push(a[d](b));return c}},createProperty:function(a,b,c){return{key:b instanceof e?b.name:b.value,value:c}},createObjectExpression:function(a){for(var b=0;b<a.length;b++)a[b].value=i(a[b].value);return function(b){for(var c={},d=0;d<a.length;d++)c[a[d].key]=a[d].value(b);return c}},createFilter:function(a,b){this.filters.push(new g(a,b))},createAsExpression:function(a,b){this.expression=a,this.scopeIdent=b},createInExpression:function(a,b,c){this.expression=c,this.scopeIdent=a,this.indexIdent=b},createTopLevel:function(a){this.expression=a},createThisExpression:h},k.prototype={getBinding:function(a,b){function c(c){return f.getValue(c,b,a)}function d(c){var d;if(1==f.paths.length)d=f.paths[0].getValueFrom(a);else{d=[];for(var e=0;e<f.paths.length;e++)d[e]=f.paths[e].getValueFrom(a)}f.setValue(a,c,d,b,a)}var e=this.paths;if(!e.length)return{value:this.getValue(void 0,b,a)};var f=this;if(1===e.length)return new PathObserver(a,e[0],void 0,void 0,c,d);for(var g=new CompoundPathObserver(void 0,void 0,c,d),h=0;h<e.length;h++)g.addPath(a,e[h]);return g.start(),g},getValue:function(a,b,c){for(var d=i(this.expression)(a),e=0;e<this.filters.length;e++)d=this.filters[e].transform(d,a,!1,b,c);return d},setValue:function(a,b,c,d,e){for(var f=this.filters?this.filters.length:0;f-->0;)b=this.filters[f].transform(b,c,!0,d,e);
-return this.expression.setValue?this.expression.setValue(a,b,c):void 0}},m.prototype={styleObject:function(a){var b=[];for(var c in a)b.push(l(c)+": "+a[c]);return b.join("; ")},tokenList:function(a){var b=[];for(var c in a)a[c]&&b.push(c);return b.join(" ")},prepareInstancePositionChanged:function(a){var b=a.polymerExpressionIndexIdent_;if(b)return function(a,c){a.model[b]=c}},prepareBinding:function(a,c,d){return Path.get(a).valid?void 0:b(a,c,d,this)},prepareInstanceModel:function(a){var b=a.polymerExpressionScopeIdent_;if(b){var c=a.templateInstance?a.templateInstance.model:a.model;return function(a){var d=Object.create(c);return d[b]=a,d}}}},a.PolymerExpressions=m}(this),function(a){function b(){e||(e=!0,a.endOfMicrotask(function(){e=!1,logFlags.data&&console.group("Platform.flush()"),a.performMicrotaskCheckpoint(),logFlags.data&&console.groupEnd()}))}var c=document.createElement("style");c.textContent="template {display: none !important;} /* injected by platform.js */";var d=document.querySelector("head");d.insertBefore(c,d.firstChild);var e,f=125;if(window.addEventListener("WebComponentsReady",function(){b(),Observer.hasObjectObserve||(a.flushPoll=setInterval(b,f))}),window.CustomElements&&!CustomElements.useNative){var g=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=g.call(this,a,b);return CustomElements.upgradeAll(c),c}}a.flush=b}(window.Platform);
+    <script>/**
+ * @license
+ * Copyright (c) 2012-2014 The Polymer Authors. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// @version: 0.2.1-59f745d
+function PointerGestureEvent(a,b){var c=b||{},d=document.createEvent("Event"),e={bubbles:Boolean(c.bubbles)===c.bubbles||!0,cancelable:Boolean(c.cancelable)===c.cancelable||!0};d.initEvent(a,e.bubbles,e.cancelable);for(var f,g=Object.keys(c),h=0;h<g.length;h++)f=g[h],d[f]=c[f];return d.preventTap=this.preventTap,d}"undefined"==typeof WeakMap&&!function(){var a=Object.defineProperty,b=Date.now()%1e9,c=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")};c.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}},window.WeakMap=c}(),function(global){"use strict";function detectObjectObserve(){function a(a){b=a}if("function"!=typeof Object.observe||"function"!=typeof Array.observe)return!1;var b=[],c={},d=[];return Object.observe(c,a),Array.observe(d,a),c.id=1,c.id=2,delete c.id,d.push(1,2),d.length=0,Object.deliverChangeRecords(a),5!==b.length?!1:"add"!=b[0].type||"update"!=b[1].type||"delete"!=b[2].type||"splice"!=b[3].type||"splice"!=b[4].type?!1:(Object.unobserve(c,a),Array.unobserve(d,a),!0)}function detectEval(){if(global.document&&"securityPolicy"in global.document&&!global.document.securityPolicy.allowsEval)return!1;try{var a=new Function("","return true;");return a()}catch(b){return!1}}function isIndex(a){return+a===a>>>0}function toNumber(a){return+a}function isObject(a){return a===Object(a)}function areSameValue(a,b){return a===b?0!==a||1/a===1/b:numberIsNaN(a)&&numberIsNaN(b)?!0:a!==a&&b!==b}function isPathValid(a){return"string"!=typeof a?!1:(a=a.trim(),""==a?!0:"."==a[0]?!1:pathRegExp.test(a))}function Path(a,b){if(b!==constructorIsPrivate)throw Error("Use Path.get to retrieve path objects");return""==a.trim()?this:isIndex(a)?(this.push(a),this):(a.split(/\s*\.\s*/).filter(function(a){return a}).forEach(function(a){this.push(a)},this),void(hasEval&&this.length&&(this.getValueFrom=this.compiledGetValueFromFn())))}function getPath(a){if(a instanceof Path)return a;null==a&&(a=""),"string"!=typeof a&&(a=String(a));var b=pathCache[a];if(b)return b;if(!isPathValid(a))return invalidPath;var b=new Path(a,constructorIsPrivate);return pathCache[a]=b,b}function dirtyCheck(a){for(var b=0;MAX_DIRTY_CHECK_CYCLES>b&&a.check_();)b++;return global.testingExposeCycleCount&&(global.dirtyCheckCycleCount=b),b>0}function objectIsEmpty(a){for(var b in a)return!1;return!0}function diffIsEmpty(a){return objectIsEmpty(a.added)&&objectIsEmpty(a.removed)&&objectIsEmpty(a.changed)}function diffObjectFromOldObject(a,b){var c={},d={},e={};for(var f in b){var g=a[f];(void 0===g||g!==b[f])&&(f in a?g!==b[f]&&(e[f]=g):d[f]=void 0)}for(var f in a)f in b||(c[f]=a[f]);return Array.isArray(a)&&a.length!==b.length&&(e.length=a.length),{added:c,removed:d,changed:e}}function runEOMTasks(){if(!eomTasks.length)return!1;for(var a=0;a<eomTasks.length;a++)eomTasks[a]();return eomTasks.length=0,!0}function newObservedObject(){function a(a){b&&b.state_===OPENED&&!d&&b.check_(a)}var b,c,d=!1,e=!0;return{open:function(c){if(b)throw Error("ObservedObject in use");e||Object.deliverChangeRecords(a),b=c,e=!1},observe:function(b,d){c=b,d?Array.observe(c,a):Object.observe(c,a)},deliver:function(b){d=b,Object.deliverChangeRecords(a),d=!1},close:function(){b=void 0,Object.unobserve(c,a),observedObjectCache.push(this)}}}function getObservedObject(a,b,c){var d=observedObjectCache.pop()||newObservedObject();return d.open(a),d.observe(b,c),d}function newObservedSet(){function a(b){if(b){var c=i.indexOf(b);c>=0?(i[c]=void 0,h.push(b)):h.indexOf(b)<0&&(h.push(b),Object.observe(b,e)),a(Object.getPrototypeOf(b))}}function b(){var b=i===emptyArray?[]:i;i=h,h=b;var c;for(var d in f)c=f[d],c&&c.state_==OPENED&&c.iterateObjects_(a);for(var g=0;g<i.length;g++){var j=i[g];j&&Object.unobserve(j,e)}i.length=0}function c(){k=!1,j&&b()}function d(){k||(j=!0,k=!0,runEOM(c))}function e(){b();var a;for(var c in f)a=f[c],a&&a.state_==OPENED&&a.check_()}var f=[],g=0,h=[],i=emptyArray,j=!1,k=!1,l={object:void 0,objects:h,open:function(b){f[b.id_]=b,g++,b.iterateObjects_(a)},close:function(a){if(f[a.id_]=void 0,g--,g)return void d();j=!1;for(var b=0;b<h.length;b++)Object.unobserve(h[b],e),Observer.unobservedCount++;f.length=0,h.length=0,observedSetCache.push(this)},reset:d};return l}function getObservedSet(a,b){return lastObservedSet&&lastObservedSet.object===b||(lastObservedSet=observedSetCache.pop()||newObservedSet(),lastObservedSet.object=b),lastObservedSet.open(a),lastObservedSet}function Observer(){this.state_=UNOPENED,this.callback_=void 0,this.target_=void 0,this.directObserver_=void 0,this.value_=void 0,this.id_=nextObserverId++}function addToAll(a){Observer._allObserversCount++,collectObservers&&allObservers.push(a)}function removeFromAll(){Observer._allObserversCount--}function ObjectObserver(a){Observer.call(this),this.value_=a,this.oldObject_=void 0}function ArrayObserver(a){if(!Array.isArray(a))throw Error("Provided object is not an Array");ObjectObserver.call(this,a)}function PathObserver(a,b){Observer.call(this),this.object_=a,this.path_=b instanceof Path?b:getPath(b),this.directObserver_=void 0}function CompoundObserver(){Observer.call(this),this.value_=[],this.directObserver_=void 0,this.observed_=[]}function identFn(a){return a}function ObserverTransform(a,b,c,d){this.callback_=void 0,this.target_=void 0,this.value_=void 0,this.observable_=a,this.getValueFn_=b||identFn,this.setValueFn_=c||identFn,this.dontPassThroughSet_=d}function notifyFunction(a,b){if("function"==typeof Object.observe){var c=Object.getNotifier(a);return function(d,e){var f={object:a,type:d,name:b};2===arguments.length&&(f.oldValue=e),c.notify(f)}}}function diffObjectFromChangeRecords(a,b,c){for(var d={},e={},f=0;f<b.length;f++){var g=b[f];expectedRecordTypes[g.type]?(g.name in c||(c[g.name]=g.oldValue),"update"!=g.type&&("add"!=g.type?g.name in d?(delete d[g.name],delete c[g.name]):e[g.name]=!0:g.name in e?delete e[g.name]:d[g.name]=!0)):(console.error("Unknown changeRecord type: "+g.type),console.error(g))}for(var h in d)d[h]=a[h];for(var h in e)e[h]=void 0;var i={};for(var h in c)if(!(h in d||h in e)){var j=a[h];c[h]!==j&&(i[h]=j)}return{added:d,removed:e,changed:i}}function newSplice(a,b,c){return{index:a,removed:b,addedCount:c}}function ArraySplice(){}function calcSplices(a,b,c,d,e,f){return arraySplice.calcSplices(a,b,c,d,e,f)}function intersect(a,b,c,d){return c>b||a>d?-1:b==c||d==a?0:c>a?d>b?b-c:d-c:b>d?d-a:b-a}function mergeSplice(a,b,c,d){for(var e=newSplice(b,c,d),f=!1,g=0,h=0;h<a.length;h++){var i=a[h];if(i.index+=g,!f){var j=intersect(e.index,e.index+e.removed.length,i.index,i.index+i.addedCount);if(j>=0){a.splice(h,1),h--,g-=i.addedCount-i.removed.length,e.addedCount+=i.addedCount-j;var k=e.removed.length+i.removed.length-j;if(e.addedCount||k){var c=i.removed;if(e.index<i.index){var l=e.removed.slice(0,i.index-e.index);Array.prototype.push.apply(l,c),c=l}if(e.index+e.removed.length>i.index+i.addedCount){var m=e.removed.slice(i.index+i.addedCount-e.index);Array.prototype.push.apply(c,m)}e.removed=c,i.index<e.index&&(e.index=i.index)}else f=!0}else if(e.index<i.index){f=!0,a.splice(h,0,e),h++;var n=e.addedCount-e.removed.length;i.index+=n,g+=n}}}f||a.push(e)}function createInitialSplices(a,b){for(var c=[],d=0;d<b.length;d++){var e=b[d];switch(e.type){case"splice":mergeSplice(c,e.index,e.removed.slice(),e.addedCount);break;case"add":case"update":case"delete":if(!isIndex(e.name))continue;var f=toNumber(e.name);if(0>f)continue;mergeSplice(c,f,[e.oldValue],1);break;default:console.error("Unexpected record type: "+JSON.stringify(e))}}return c}function projectArraySplices(a,b){var c=[];return createInitialSplices(a,b).forEach(function(b){return 1==b.addedCount&&1==b.removed.length?void(b.removed[0]!==a[b.index]&&c.push(b)):void(c=c.concat(calcSplices(a,b.index,b.index+b.addedCount,b.removed,0,b.removed.length)))}),c}var hasObserve=detectObjectObserve(),hasEval=detectEval(),numberIsNaN=global.Number.isNaN||function(a){return"number"==typeof a&&global.isNaN(a)},createObject="__proto__"in{}?function(a){return a}:function(a){var b=a.__proto__;if(!b)return a;var c=Object.create(b);return Object.getOwnPropertyNames(a).forEach(function(b){Object.defineProperty(c,b,Object.getOwnPropertyDescriptor(a,b))}),c},identStart="[$_a-zA-Z]",identPart="[$_a-zA-Z0-9]",ident=identStart+"+"+identPart+"*",elementIndex="(?:[0-9]|[1-9]+[0-9]+)",identOrElementIndex="(?:"+ident+"|"+elementIndex+")",path="(?:"+identOrElementIndex+")(?:\\s*\\.\\s*"+identOrElementIndex+")*",pathRegExp=new RegExp("^"+path+"$"),constructorIsPrivate={},pathCache={};Path.get=getPath,Path.prototype=createObject({__proto__:[],valid:!0,toString:function(){return this.join(".")},getValueFrom:function(a){for(var b=0;b<this.length;b++){if(null==a)return;a=a[this[b]]}return a},iterateObjects:function(a,b){for(var c=0;c<this.length;c++){if(c&&(a=a[this[c-1]]),!isObject(a))return;b(a)}},compiledGetValueFromFn:function(){var a=this.map(function(a){return isIndex(a)?'["'+a+'"]':"."+a}),b="",c="obj";b+="if (obj != null";for(var d=0;d<this.length-1;d++){{this[d]}c+=a[d],b+=" &&\n     "+c+" != null"}return b+=")\n",c+=a[d],b+="  return "+c+";\nelse\n  return undefined;",new Function("obj",b)},setValueFrom:function(a,b){if(!this.length)return!1;for(var c=0;c<this.length-1;c++){if(!isObject(a))return!1;a=a[this[c]]}return isObject(a)?(a[this[c]]=b,!0):!1}});var invalidPath=new Path("",constructorIsPrivate);invalidPath.valid=!1,invalidPath.getValueFrom=invalidPath.setValueFrom=function(){};var MAX_DIRTY_CHECK_CYCLES=1e3,eomTasks=[],runEOM=hasObserve?function(){var a={pingPong:!0},b=!1;return Object.observe(a,function(){runEOMTasks(),b=!1}),function(c){eomTasks.push(c),b||(b=!0,a.pingPong=!a.pingPong)}}():function(){return function(a){eomTasks.push(a)}}(),observedObjectCache=[],emptyArray=[],observedSetCache=[],lastObservedSet,UNOPENED=0,OPENED=1,CLOSED=2,RESETTING=3,nextObserverId=1;Observer.prototype={open:function(a,b){if(this.state_!=UNOPENED)throw Error("Observer has already been opened.");return addToAll(this),this.callback_=a,this.target_=b,this.state_=OPENED,this.connect_(),this.value_},close:function(){this.state_==OPENED&&(removeFromAll(this),this.state_=CLOSED,this.disconnect_(),this.value_=void 0,this.callback_=void 0,this.target_=void 0)},deliver:function(){this.state_==OPENED&&dirtyCheck(this)},report_:function(a){try{this.callback_.apply(this.target_,a)}catch(b){Observer._errorThrownDuringCallback=!0,console.error("Exception caught during observer callback: "+(b.stack||b))}},discardChanges:function(){return this.check_(void 0,!0),this.value_}};var collectObservers=!hasObserve,allObservers;Observer._allObserversCount=0,collectObservers&&(allObservers=[]);var runningMicrotaskCheckpoint=!1,hasDebugForceFullDelivery=hasObserve&&function(){try{return eval("%RunMicrotasks()"),!0}catch(ex){return!1}}();global.Platform=global.Platform||{},global.Platform.performMicrotaskCheckpoint=function(){if(!runningMicrotaskCheckpoint){if(hasDebugForceFullDelivery)return void eval("%RunMicrotasks()");if(collectObservers){runningMicrotaskCheckpoint=!0;var cycles=0,anyChanged,toCheck;do{cycles++,toCheck=allObservers,allObservers=[],anyChanged=!1;for(var i=0;i<toCheck.length;i++){var observer=toCheck[i];observer.state_==OPENED&&(observer.check_()&&(anyChanged=!0),allObservers.push(observer))}runEOMTasks()&&(anyChanged=!0)}while(MAX_DIRTY_CHECK_CYCLES>cycles&&anyChanged);global.testingExposeCycleCount&&(global.dirtyCheckCycleCount=cycles),runningMicrotaskCheckpoint=!1}}},collectObservers&&(global.Platform.clearObservers=function(){allObservers=[]}),ObjectObserver.prototype=createObject({__proto__:Observer.prototype,arrayObserve:!1,connect_:function(){hasObserve?this.directObserver_=getObservedObject(this,this.value_,this.arrayObserve):this.oldObject_=this.copyObject(this.value_)},copyObject:function(a){var b=Array.isArray(a)?[]:{};for(var c in a)b[c]=a[c];return Array.isArray(a)&&(b.length=a.length),b},check_:function(a){var b,c;if(hasObserve){if(!a)return!1;c={},b=diffObjectFromChangeRecords(this.value_,a,c)}else c=this.oldObject_,b=diffObjectFromOldObject(this.value_,this.oldObject_);return diffIsEmpty(b)?!1:(hasObserve||(this.oldObject_=this.copyObject(this.value_)),this.report_([b.added||{},b.removed||{},b.changed||{},function(a){return c[a]}]),!0)},disconnect_:function(){hasObserve?(this.directObserver_.close(),this.directObserver_=void 0):this.oldObject_=void 0},deliver:function(){this.state_==OPENED&&(hasObserve?this.directObserver_.deliver(!1):dirtyCheck(this))},discardChanges:function(){return this.directObserver_?this.directObserver_.deliver(!0):this.oldObject_=this.copyObject(this.value_),this.value_}}),ArrayObserver.prototype=createObject({__proto__:ObjectObserver.prototype,arrayObserve:!0,copyObject:function(a){return a.slice()},check_:function(a){var b;if(hasObserve){if(!a)return!1;b=projectArraySplices(this.value_,a)}else b=calcSplices(this.value_,0,this.value_.length,this.oldObject_,0,this.oldObject_.length);return b&&b.length?(hasObserve||(this.oldObject_=this.copyObject(this.value_)),this.report_([b]),!0):!1}}),ArrayObserver.applySplices=function(a,b,c){c.forEach(function(c){for(var d=[c.index,c.removed.length],e=c.index;e<c.index+c.addedCount;)d.push(b[e]),e++;Array.prototype.splice.apply(a,d)})},PathObserver.prototype=createObject({__proto__:Observer.prototype,connect_:function(){hasObserve&&(this.directObserver_=getObservedSet(this,this.object_)),this.check_(void 0,!0)},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0)},iterateObjects_:function(a){this.path_.iterateObjects(this.object_,a)},check_:function(a,b){var c=this.value_;return this.value_=this.path_.getValueFrom(this.object_),b||areSameValue(this.value_,c)?!1:(this.report_([this.value_,c]),!0)},setValue:function(a){this.path_&&this.path_.setValueFrom(this.object_,a)}});var observerSentinel={};CompoundObserver.prototype=createObject({__proto__:Observer.prototype,connect_:function(){if(this.check_(void 0,!0),hasObserve){for(var a,b=!1,c=0;c<this.observed_.length;c+=2)if(a=this.observed_[c],a!==observerSentinel){b=!0;break}return this.directObserver_?b?void this.directObserver_.reset():(this.directObserver_.close(),void(this.directObserver_=void 0)):void(b&&(this.directObserver_=getObservedSet(this,a)))}},closeObservers_:function(){for(var a=0;a<this.observed_.length;a+=2)this.observed_[a]===observerSentinel&&this.observed_[a+1].close();this.observed_.length=0},disconnect_:function(){this.value_=void 0,this.directObserver_&&(this.directObserver_.close(this),this.directObserver_=void 0),this.closeObservers_()},addPath:function(a,b){if(this.state_!=UNOPENED&&this.state_!=RESETTING)throw Error("Cannot add paths once started.");this.observed_.push(a,b instanceof Path?b:getPath(b))},addObserver:function(a){if(this.state_!=UNOPENED&&this.state_!=RESETTING)throw Error("Cannot add observers once started.");a.open(this.deliver,this),this.observed_.push(observerSentinel,a)},startReset:function(){if(this.state_!=OPENED)throw Error("Can only reset while open");this.state_=RESETTING,this.closeObservers_()},finishReset:function(){if(this.state_!=RESETTING)throw Error("Can only finishReset after startReset");return this.state_=OPENED,this.connect_(),this.value_},iterateObjects_:function(a){for(var b,c=0;c<this.observed_.length;c+=2)b=this.observed_[c],b!==observerSentinel&&this.observed_[c+1].iterateObjects(b,a)},check_:function(a,b){for(var c,d=0;d<this.observed_.length;d+=2){var e=this.observed_[d+1],f=this.observed_[d],g=f===observerSentinel?e.discardChanges():e.getValueFrom(f);b?this.value_[d/2]=g:areSameValue(g,this.value_[d/2])||(c=c||[],c[d/2]=this.value_[d/2],this.value_[d/2]=g)}return c?(this.report_([this.value_,c,this.observed_]),!0):!1}}),ObserverTransform.prototype={open:function(a,b){return this.callback_=a,this.target_=b,this.value_=this.getValueFn_(this.observable_.open(this.observedCallback_,this)),this.value_},observedCallback_:function(a){if(a=this.getValueFn_(a),!areSameValue(a,this.value_)){var b=this.value_;this.value_=a,this.callback_.call(this.target_,this.value_,b)}},discardChanges:function(){return this.value_=this.getValueFn_(this.observable_.discardChanges()),this.value_},deliver:function(){return this.observable_.deliver()},setValue:function(a){return a=this.setValueFn_(a),!this.dontPassThroughSet_&&this.observable_.setValue?this.observable_.setValue(a):void 0},close:function(){this.observable_&&this.observable_.close(),this.callback_=void 0,this.target_=void 0,this.observable_=void 0,this.value_=void 0,this.getValueFn_=void 0,this.setValueFn_=void 0}};var expectedRecordTypes={add:!0,update:!0,"delete":!0};Observer.defineComputedProperty=function(a,b,c){var d=notifyFunction(a,b),e=c.open(function(a,b){e=a,d&&d("update",b)});return Object.defineProperty(a,b,{get:function(){return c.deliver(),e},set:function(a){return c.setValue(a),a},configurable:!0}),{close:function(){c.close(),Object.defineProperty(a,b,{value:e,writable:!0,configurable:!0})}}};var EDIT_LEAVE=0,EDIT_UPDATE=1,EDIT_ADD=2,EDIT_DELETE=3;ArraySplice.prototype={calcEditDistances:function(a,b,c,d,e,f){for(var g=f-e+1,h=c-b+1,i=new Array(g),j=0;g>j;j++)i[j]=new Array(h),i[j][0]=j;for(var k=0;h>k;k++)i[0][k]=k;for(var j=1;g>j;j++)for(var k=1;h>k;k++)if(this.equals(a[b+k-1],d[e+j-1]))i[j][k]=i[j-1][k-1];else{var l=i[j-1][k]+1,m=i[j][k-1]+1;i[j][k]=m>l?l:m}return i},spliceOperationsFromEditDistances:function(a){for(var b=a.length-1,c=a[0].length-1,d=a[b][c],e=[];b>0||c>0;)if(0!=b)if(0!=c){var f,g=a[b-1][c-1],h=a[b-1][c],i=a[b][c-1];f=i>h?g>h?h:g:g>i?i:g,f==g?(g==d?e.push(EDIT_LEAVE):(e.push(EDIT_UPDATE),d=g),b--,c--):f==h?(e.push(EDIT_DELETE),b--,d=h):(e.push(EDIT_ADD),c--,d=i)}else e.push(EDIT_DELETE),b--;else e.push(EDIT_ADD),c--;return e.reverse(),e},calcSplices:function(a,b,c,d,e,f){var g=0,h=0,i=Math.min(c-b,f-e);if(0==b&&0==e&&(g=this.sharedPrefix(a,d,i)),c==a.length&&f==d.length&&(h=this.sharedSuffix(a,d,i-g)),b+=g,e+=g,c-=h,f-=h,c-b==0&&f-e==0)return[];if(b==c){for(var j=newSplice(b,[],0);f>e;)j.removed.push(d[e++]);return[j]}if(e==f)return[newSplice(b,[],c-b)];for(var k=this.spliceOperationsFromEditDistances(this.calcEditDistances(a,b,c,d,e,f)),j=void 0,l=[],m=b,n=e,o=0;o<k.length;o++)switch(k[o]){case EDIT_LEAVE:j&&(l.push(j),j=void 0),m++,n++;break;case EDIT_UPDATE:j||(j=newSplice(m,[],0)),j.addedCount++,m++,j.removed.push(d[n]),n++;break;case EDIT_ADD:j||(j=newSplice(m,[],0)),j.addedCount++,m++;break;case EDIT_DELETE:j||(j=newSplice(m,[],0)),j.removed.push(d[n]),n++}return j&&l.push(j),l},sharedPrefix:function(a,b,c){for(var d=0;c>d;d++)if(!this.equals(a[d],b[d]))return d;return c},sharedSuffix:function(a,b,c){for(var d=a.length,e=b.length,f=0;c>f&&this.equals(a[--d],b[--e]);)f++;return f},calculateSplices:function(a,b){return this.calcSplices(a,0,a.length,b,0,b.length)},equals:function(a,b){return a===b}};var arraySplice=new ArraySplice;global.Observer=Observer,global.Observer.runEOM_=runEOM,global.Observer.hasObjectObserve=hasObserve,global.ArrayObserver=ArrayObserver,global.ArrayObserver.calculateSplices=function(a,b){return arraySplice.calculateSplices(a,b)},global.ArraySplice=ArraySplice,global.ObjectObserver=ObjectObserver,global.PathObserver=PathObserver,global.CompoundObserver=CompoundObserver,global.Path=Path,global.ObserverTransform=ObserverTransform}("undefined"!=typeof global&&global&&"undefined"!=typeof module&&module?global:this||window),window.Platform=window.Platform||{},window.logFlags=window.logFlags||{},function(a){var b=a.flags||{};location.search.slice(1).split("&").forEach(function(a){a=a.split("="),a[0]&&(b[a[0]]=a[1]||!0)});var c=document.currentScript||document.querySelector('script[src*="platform.js"]');if(c)for(var d,e=c.attributes,f=0;f<e.length;f++)d=e[f],"src"!==d.name&&(b[d.name]=d.value||!0);b.log&&b.log.split(",").forEach(function(a){window.logFlags[a]=!0}),b.shadow=b.shadow||b.shadowdom||b.polyfill,b.shadow="native"===b.shadow?!1:b.shadow||!HTMLElement.prototype.createShadowRoot,b.register&&(window.CustomElements=window.CustomElements||{flags:{}},window.CustomElements.flags.register=b.register),b.imports&&(window.HTMLImports=window.HTMLImports||{flags:{}},window.HTMLImports.flags.imports=b.imports),a.flags=b}(Platform),Platform.flags.shadow?(window.ShadowDOMPolyfill={},function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a,b){return L(b).forEach(function(c){K(a,c,M(b,c))}),a}function d(a,b){return L(b).forEach(function(c){switch(c){case"arguments":case"caller":case"length":case"name":case"prototype":case"toString":return}K(a,c,M(b,c))}),a}function e(a,b){for(var c=0;c<b.length;c++)if(b[c]in a)return b[c]}function f(a){var b=a.__proto__||Object.getPrototypeOf(a),c=E.get(b);if(c)return c;var d=f(b),e=t(d);return q(b,e,a),e}function g(a,b){o(a,b,!0)}function h(a,b){o(b,a,!1)}function i(a){return/^on[a-z]+$/.test(a)}function j(a){return/^\w[a-zA-Z_0-9]*$/.test(a)}function k(a){return H&&j(a)?new Function("return this.impl."+a):function(){return this.impl[a]}}function l(a){return H&&j(a)?new Function("v","this.impl."+a+" = v"):function(b){this.impl[a]=b}}function m(a){return H&&j(a)?new Function("return this.impl."+a+".apply(this.impl, arguments)"):function(){return this.impl[a].apply(this.impl,arguments)}}function n(a,b){try{return Object.getOwnPropertyDescriptor(a,b)}catch(c){return O}}function o(b,c,d){for(var e=L(b),f=0;f<e.length;f++){var g=e[f];if("polymerBlackList_"!==g&&!(g in c||b.polymerBlackList_&&b.polymerBlackList_[g])){N&&b.__lookupGetter__(g);var h,j,o=n(b,g);if(d&&"function"==typeof o.value)c[g]=m(g);else{var p=i(g);h=p?a.getEventHandlerGetter(g):k(g),(o.writable||o.set)&&(j=p?a.getEventHandlerSetter(g):l(g)),K(c,g,{get:h,set:j,configurable:o.configurable,enumerable:o.enumerable})}}}}function p(a,b,c){var e=a.prototype;q(e,b,c),d(b,a)}function q(a,c,d){var e=c.prototype;b(void 0===E.get(a)),E.set(a,c),F.set(e,a),g(a,e),d&&h(e,d),K(e,"constructor",{value:c,configurable:!0,enumerable:!1,writable:!0}),c.prototype=e}function r(a,b){return E.get(b.prototype)===a}function s(a){var b=Object.getPrototypeOf(a),c=f(b),d=t(c);return q(b,d,a),d}function t(a){function b(b){a.call(this,b)}var c=Object.create(a.prototype);return c.constructor=b,b.prototype=c,b}function u(a){return a instanceof G.EventTarget||a instanceof G.Event||a instanceof G.Range||a instanceof G.DOMImplementation||a instanceof G.CanvasRenderingContext2D||G.WebGLRenderingContext&&a instanceof G.WebGLRenderingContext}function v(a){return Q&&a instanceof Q||a instanceof S||a instanceof R||a instanceof T||a instanceof U||a instanceof P||a instanceof V||W&&a instanceof W||X&&a instanceof X}function w(a){return null===a?null:(b(v(a)),a.polymerWrapper_||(a.polymerWrapper_=new(f(a))(a)))}function x(a){return null===a?null:(b(u(a)),a.impl)}function y(a){return a&&u(a)?x(a):a}function z(a){return a&&!u(a)?w(a):a}function A(a,c){null!==c&&(b(v(a)),b(void 0===c||u(c)),a.polymerWrapper_=c)}function B(a,b,c){K(a.prototype,b,{get:c,configurable:!0,enumerable:!0})}function C(a,b){B(a,b,function(){return w(this.impl[b])})}function D(a,b){a.forEach(function(a){b.forEach(function(b){a.prototype[b]=function(){var a=z(this);return a[b].apply(a,arguments)}})})}var E=new WeakMap,F=new WeakMap,G=Object.create(null),H=!("securityPolicy"in document)||document.securityPolicy.allowsEval;if(H)try{var I=new Function("","return true;");H=I()}catch(J){H=!1}var K=Object.defineProperty,L=Object.getOwnPropertyNames,M=Object.getOwnPropertyDescriptor;L(window);var N=/Firefox/.test(navigator.userAgent),O={get:function(){},set:function(){},configurable:!0,enumerable:!0},P=window.DOMImplementation,Q=window.EventTarget,R=window.Event,S=window.Node,T=window.Window,U=window.Range,V=window.CanvasRenderingContext2D,W=window.WebGLRenderingContext,X=window.SVGElementInstance;a.assert=b,a.constructorTable=E,a.defineGetter=B,a.defineWrapGetter=C,a.forwardMethodsToWrapper=D,a.isWrapper=u,a.isWrapperFor=r,a.mixin=c,a.nativePrototypeTable=F,a.oneOf=e,a.registerObject=s,a.registerWrapper=p,a.rewrap=A,a.unwrap=x,a.unwrapIfNeeded=y,a.wrap=w,a.wrapIfNeeded=z,a.wrappers=G}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){g=!1;var a=f.slice(0);f=[];for(var b=0;b<a.length;b++)a[b]()}function c(a){f.push(a),g||(g=!0,d(b,0))}var d,e=window.MutationObserver,f=[],g=!1;if(e){var h=1,i=new e(b),j=document.createTextNode(h);i.observe(j,{characterData:!0}),d=function(){h=(h+1)%2,j.data=h}}else d=window.setImmediate||window.setTimeout;a.setEndOfMicrotask=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(){p||(k(c),p=!0)}function c(){p=!1;do for(var a=o.slice(),b=!1,c=0;c<a.length;c++){var d=a[c],e=d.takeRecords();f(d),e.length&&(d.callback_(e,d),b=!0)}while(b)}function d(a,b){this.type=a,this.target=b,this.addedNodes=new m.NodeList,this.removedNodes=new m.NodeList,this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function e(a,b){for(;a;a=a.parentNode){var c=n.get(a);if(c)for(var d=0;d<c.length;d++){var e=c[d];e.options.subtree&&e.addTransientObserver(b)}}}function f(a){for(var b=0;b<a.nodes_.length;b++){var c=a.nodes_[b],d=n.get(c);if(!d)return;for(var e=0;e<d.length;e++){var f=d[e];f.observer===a&&f.removeTransientObservers()}}}function g(a,c,e){for(var f=Object.create(null),g=Object.create(null),h=a;h;h=h.parentNode){var i=n.get(h);if(i)for(var j=0;j<i.length;j++){var k=i[j],l=k.options;if((h===a||l.subtree)&&!("attributes"===c&&!l.attributes||"attributes"===c&&l.attributeFilter&&(null!==e.namespace||-1===l.attributeFilter.indexOf(e.name))||"characterData"===c&&!l.characterData||"childList"===c&&!l.childList)){var m=k.observer;f[m.uid_]=m,("attributes"===c&&l.attributeOldValue||"characterData"===c&&l.characterDataOldValue)&&(g[m.uid_]=e.oldValue)}}}var o=!1;for(var p in f){var m=f[p],q=new d(c,a);"name"in e&&"namespace"in e&&(q.attributeName=e.name,q.attributeNamespace=e.namespace),e.addedNodes&&(q.addedNodes=e.addedNodes),e.removedNodes&&(q.removedNodes=e.removedNodes),e.previousSibling&&(q.previousSibling=e.previousSibling),e.nextSibling&&(q.nextSibling=e.nextSibling),void 0!==g[p]&&(q.oldValue=g[p]),m.records_.push(q),o=!0}o&&b()}function h(a){if(this.childList=!!a.childList,this.subtree=!!a.subtree,this.attributes="attributes"in a||!("attributeOldValue"in a||"attributeFilter"in a)?!!a.attributes:!0,this.characterData="characterDataOldValue"in a&&!("characterData"in a)?!0:!!a.characterData,!this.attributes&&(a.attributeOldValue||"attributeFilter"in a)||!this.characterData&&a.characterDataOldValue)throw new TypeError;if(this.characterData=!!a.characterData,this.attributeOldValue=!!a.attributeOldValue,this.characterDataOldValue=!!a.characterDataOldValue,"attributeFilter"in a){if(null==a.attributeFilter||"object"!=typeof a.attributeFilter)throw new TypeError;this.attributeFilter=q.call(a.attributeFilter)}else this.attributeFilter=null}function i(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++r,o.push(this)}function j(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var k=a.setEndOfMicrotask,l=a.wrapIfNeeded,m=a.wrappers,n=new WeakMap,o=[],p=!1,q=Array.prototype.slice,r=0;i.prototype={observe:function(a,b){a=l(a);var c,d=new h(b),e=n.get(a);e||n.set(a,e=[]);for(var f=0;f<e.length;f++)e[f].observer===this&&(c=e[f],c.removeTransientObservers(),c.options=d);c||(c=new j(this,a,d),e.push(c),this.nodes_.push(a))},disconnect:function(){this.nodes_.forEach(function(a){for(var b=n.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}},j.prototype={addTransientObserver:function(a){if(a!==this.target){this.transientObservedNodes.push(a);var b=n.get(a);b||n.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[];for(var b=0;b<a.length;b++)for(var c=a[b],d=n.get(c),e=0;e<d.length;e++)if(d[e]===this){d.splice(e,1);break}}},a.enqueueMutation=g,a.registerTransientObservers=e,a.wrappers.MutationObserver=i,a.wrappers.MutationRecord=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){this.root=a,this.parent=b}function c(a,b){if(a.treeScope_!==b){a.treeScope_=b;for(var d=a.shadowRoot;d;d=d.olderShadowRoot)d.treeScope_.parent=b;for(var e=a.firstChild;e;e=e.nextSibling)c(e,b)}}function d(a){if(a.treeScope_)return a.treeScope_;var c,e=a.parentNode;return c=e?d(e):new b(a,null),a.treeScope_=c}b.prototype={get renderer(){return this.root instanceof a.wrappers.ShadowRoot?a.getRendererForHost(this.root.host):null},contains:function(a){for(;a;a=a.parent)if(a===this)return!0;return!1}},a.TreeScope=b,a.getTreeScope=d,a.setTreeScope=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a instanceof Q.ShadowRoot}function c(a){var b=a.localName;return"content"===b||"shadow"===b}function d(a){return!!a.shadowRoot}function e(a){var b;return a.parentNode||(b=a.defaultView)&&P(b)||null}function f(f,g,h){if(h.length)return h.shift();if(b(f))return j(f)||f.host;var i=a.eventParentsTable.get(f);if(i){for(var k=1;k<i.length;k++)h[k-1]=i[k];return i[0]}if(g&&c(f)){var l=f.parentNode;if(l&&d(l))for(var m=a.getShadowTrees(l),n=j(g),k=0;k<m.length;k++)if(m[k].contains(n))return n}return e(f)}function g(a){for(var d=[],e=a,g=[],i=[];e;){var j=null;if(c(e)){j=h(d);var k=d[d.length-1]||e;d.push(k)}else d.length||d.push(e);var l=d[d.length-1];g.push({target:l,currentTarget:e}),b(e)&&d.pop(),e=f(e,j,i)}return g}function h(a){for(var b=a.length-1;b>=0;b--)if(!c(a[b]))return a[b];return null}function i(a,d){for(var e=[];a;){for(var g=[],i=d,j=void 0;i;){var m=null;if(g.length){if(c(i)&&(m=h(g),k(j))){var n=g[g.length-1];g.push(n)}}else g.push(i);if(l(i,a))return g[g.length-1];b(i)&&g.pop(),j=i,i=f(i,m,e)}a=b(a)?a.host:a.parentNode}}function j(b){return a.insertionParentTable.get(b)}function k(a){return j(a)}function l(a,b){return L(a)===L(b)}function m(a){S.get(a)||(S.set(a,!0),o(P(a),P(a.target)))}function n(a){switch(a.type){case"beforeunload":case"load":case"unload":return!0}return!1}function o(b,c){if(T.get(b))throw new Error("InvalidStateError");T.set(b,!0),a.renderAllPending();var d=g(c);return 2===d.length&&d[0].target instanceof Q.Document&&n(b)&&d.shift(),_.set(b,d),p(b,d)&&q(b,d)&&r(b,d),X.set(b,u.NONE),V.delete(b,null),T.delete(b),b.defaultPrevented}function p(a,b){for(var c,d=b.length-1;d>0;d--){var e=b[d].target,f=b[d].currentTarget;if(e!==f&&(c=u.CAPTURING_PHASE,!s(b[d],a,c)))return!1}return!0}function q(a,b){var c=u.AT_TARGET;return s(b[0],a,c)}function r(a,b){for(var c,d=a.bubbles,e=1;e<b.length;e++){var f=b[e].target,g=b[e].currentTarget;if(f===g)c=u.AT_TARGET;else{if(!d||Z.get(a))continue;c=u.BUBBLING_PHASE}if(!s(b[e],a,c))return}}function s(a,b,c){var d=a.target,e=a.currentTarget,f=R.get(e);if(!f)return!0;if("relatedTarget"in b){var g=O(b),h=g.relatedTarget;if(h&&h instanceof Object&&h.addEventListener){var j=P(h),k=i(e,j);if(k===d)return!0;W.set(b,k)}}X.set(b,c);var l=b.type,m=!1;U.set(b,d),V.set(b,e);for(var n=0;n<f.length;n++){var o=f[n];if(o.removed)m=!0;else if(!(o.type!==l||!o.capture&&c===u.CAPTURING_PHASE||o.capture&&c===u.BUBBLING_PHASE))try{if("function"==typeof o.handler?o.handler.call(e,b):o.handler.handleEvent(b),Z.get(b))return!1}catch(p){window.onerror?window.onerror(p.message):console.error(p,p.stack)}}if(m){var q=f.slice();f.length=0;for(var n=0;n<q.length;n++)q[n].removed||f.push(q[n])}return!Y.get(b)}function t(a,b,c){this.type=a,this.handler=b,this.capture=Boolean(c)}function u(a,b){if(!(a instanceof ab))return P(y(ab,"Event",a,b));var c=a;return lb||"beforeunload"!==c.type?void(this.impl=c):new z(c)}function v(a){return a&&a.relatedTarget?Object.create(a,{relatedTarget:{value:O(a.relatedTarget)}}):a
+}function w(a,b,c){var d=window[a],e=function(b,c){return b instanceof d?void(this.impl=b):P(y(d,a,b,c))};if(e.prototype=Object.create(b.prototype),c&&M(e.prototype,c),d)try{N(d,e,new d("temp"))}catch(f){N(d,e,document.createEvent(a))}return e}function x(a,b){return function(){arguments[b]=O(arguments[b]);var c=O(this);c[a].apply(c,arguments)}}function y(a,b,c,d){if(jb)return new a(c,v(d));var e=O(document.createEvent(b)),f=ib[b],g=[c];return Object.keys(f).forEach(function(a){var b=null!=d&&a in d?d[a]:f[a];"relatedTarget"===a&&(b=O(b)),g.push(b)}),e["init"+b].apply(e,g),e}function z(a){u.call(this,a)}function A(a){return"function"==typeof a?!0:a&&a.handleEvent}function B(a){switch(a){case"DOMAttrModified":case"DOMAttributeNameChanged":case"DOMCharacterDataModified":case"DOMElementNameChanged":case"DOMNodeInserted":case"DOMNodeInsertedIntoDocument":case"DOMNodeRemoved":case"DOMNodeRemovedFromDocument":case"DOMSubtreeModified":return!0}return!1}function C(a){this.impl=a}function D(a){return a instanceof Q.ShadowRoot&&(a=a.host),O(a)}function E(a,b){var c=R.get(a);if(c)for(var d=0;d<c.length;d++)if(!c[d].removed&&c[d].type===b)return!0;return!1}function F(a,b){for(var c=O(a);c;c=c.parentNode)if(E(P(c),b))return!0;return!1}function G(a){K(a,nb)}function H(b,c,d,e){a.renderAllPending();for(var f=P(ob.call(c.impl,d,e)),h=g(f,this),i=0;i<h.length;i++){var j=h[i];if(j.currentTarget===b)return j.target}return null}function I(a){return function(){var b=$.get(this);return b&&b[a]&&b[a].value||null}}function J(a){var b=a.slice(2);return function(c){var d=$.get(this);d||(d=Object.create(null),$.set(this,d));var e=d[a];if(e&&this.removeEventListener(b,e.wrapped,!1),"function"==typeof c){var f=function(b){var d=c.call(this,b);d===!1?b.preventDefault():"onbeforeunload"===a&&"string"==typeof d&&(b.returnValue=d)};this.addEventListener(b,f,!1),d[a]={value:c,wrapped:f}}}}var K=a.forwardMethodsToWrapper,L=a.getTreeScope,M=a.mixin,N=a.registerWrapper,O=a.unwrap,P=a.wrap,Q=a.wrappers,R=(new WeakMap,new WeakMap),S=new WeakMap,T=new WeakMap,U=new WeakMap,V=new WeakMap,W=new WeakMap,X=new WeakMap,Y=new WeakMap,Z=new WeakMap,$=new WeakMap,_=new WeakMap;t.prototype={equals:function(a){return this.handler===a.handler&&this.type===a.type&&this.capture===a.capture},get removed(){return null===this.handler},remove:function(){this.handler=null}};var ab=window.Event;ab.prototype.polymerBlackList_={returnValue:!0,keyLocation:!0},u.prototype={get target(){return U.get(this)},get currentTarget(){return V.get(this)},get eventPhase(){return X.get(this)},get path(){var a=new Q.NodeList,b=_.get(this);if(b){for(var c=0,d=b.length-1,e=L(V.get(this)),f=0;d>=f;f++){var g=b[f].currentTarget,h=L(g);h.contains(e)&&(f!==d||g instanceof Q.Node)&&(a[c++]=g)}a.length=c}return a},stopPropagation:function(){Y.set(this,!0)},stopImmediatePropagation:function(){Y.set(this,!0),Z.set(this,!0)}},N(ab,u,document.createEvent("Event"));var bb=w("UIEvent",u),cb=w("CustomEvent",u),db={get relatedTarget(){return W.get(this)||P(O(this).relatedTarget)}},eb=M({initMouseEvent:x("initMouseEvent",14)},db),fb=M({initFocusEvent:x("initFocusEvent",5)},db),gb=w("MouseEvent",bb,eb),hb=w("FocusEvent",bb,fb),ib=Object.create(null),jb=function(){try{new window.FocusEvent("focus")}catch(a){return!1}return!0}();if(!jb){var kb=function(a,b,c){if(c){var d=ib[c];b=M(M({},d),b)}ib[a]=b};kb("Event",{bubbles:!1,cancelable:!1}),kb("CustomEvent",{detail:null},"Event"),kb("UIEvent",{view:null,detail:0},"Event"),kb("MouseEvent",{screenX:0,screenY:0,clientX:0,clientY:0,ctrlKey:!1,altKey:!1,shiftKey:!1,metaKey:!1,button:0,relatedTarget:null},"UIEvent"),kb("FocusEvent",{relatedTarget:null},"UIEvent")}var lb=window.BeforeUnloadEvent;z.prototype=Object.create(u.prototype),M(z.prototype,{get returnValue(){return this.impl.returnValue},set returnValue(a){this.impl.returnValue=a}}),lb&&N(lb,z);var mb=window.EventTarget,nb=["addEventListener","removeEventListener","dispatchEvent"];[Node,Window].forEach(function(a){var b=a.prototype;nb.forEach(function(a){Object.defineProperty(b,a+"_",{value:b[a]})})}),C.prototype={addEventListener:function(a,b,c){if(A(b)&&!B(a)){var d=new t(a,b,c),e=R.get(this);if(e){for(var f=0;f<e.length;f++)if(d.equals(e[f]))return}else e=[],R.set(this,e);e.push(d);var g=D(this);g.addEventListener_(a,m,!0)}},removeEventListener:function(a,b,c){c=Boolean(c);var d=R.get(this);if(d){for(var e=0,f=!1,g=0;g<d.length;g++)d[g].type===a&&d[g].capture===c&&(e++,d[g].handler===b&&(f=!0,d[g].remove()));if(f&&1===e){var h=D(this);h.removeEventListener_(a,m,!0)}}},dispatchEvent:function(b){var c=O(b),d=c.type;S.set(c,!1),a.renderAllPending();var e;F(this,d)||(e=function(){},this.addEventListener(d,e,!0));try{return O(this).dispatchEvent_(c)}finally{e&&this.removeEventListener(d,e,!0)}}},mb&&N(mb,C);var ob=document.elementFromPoint;a.adjustRelatedTarget=i,a.elementFromPoint=H,a.getEventHandlerGetter=I,a.getEventHandlerSetter=J,a.wrapEventTargetMethods=G,a.wrappers.BeforeUnloadEvent=z,a.wrappers.CustomEvent=cb,a.wrappers.Event=u,a.wrappers.EventTarget=C,a.wrappers.FocusEvent=hb,a.wrappers.MouseEvent=gb,a.wrappers.UIEvent=bb}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,b){Object.defineProperty(a,b,{enumerable:!1})}function c(){this.length=0,b(this,"length")}function d(a){if(null==a)return a;for(var b=new c,d=0,e=a.length;e>d;d++)b[d]=f(a[d]);return b.length=e,b}function e(a,b){a.prototype[b]=function(){return d(this.impl[b].apply(this.impl,arguments))}}var f=a.wrap;c.prototype={item:function(a){return this[a]}},b(c.prototype,"item"),a.wrappers.NodeList=c,a.addWrapNodeListMethod=e,a.wrapNodeList=d}(window.ShadowDOMPolyfill),function(a){"use strict";a.wrapHTMLCollection=a.wrapNodeList,a.wrappers.HTMLCollection=a.wrappers.NodeList}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){A(a instanceof w)}function c(a){var b=new y;return b[0]=a,b.length=1,b}function d(a,b,c){C(b,"childList",{removedNodes:c,previousSibling:a.previousSibling,nextSibling:a.nextSibling})}function e(a,b){C(a,"childList",{removedNodes:b})}function f(a,b,d,e){if(a instanceof DocumentFragment){var f=h(a);N=!0;for(var g=f.length-1;g>=0;g--)a.removeChild(f[g]),f[g].parentNode_=b;N=!1;for(var g=0;g<f.length;g++)f[g].previousSibling_=f[g-1]||d,f[g].nextSibling_=f[g+1]||e;return d&&(d.nextSibling_=f[0]),e&&(e.previousSibling_=f[f.length-1]),f}var f=c(a),i=a.parentNode;return i&&i.removeChild(a),a.parentNode_=b,a.previousSibling_=d,a.nextSibling_=e,d&&(d.nextSibling_=a),e&&(e.previousSibling_=a),f}function g(a){if(a instanceof DocumentFragment)return h(a);var b=c(a),e=a.parentNode;return e&&d(a,e,b),b}function h(a){for(var b=new y,c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b.length=c,e(a,b),b}function i(a){return a}function j(a,b){I(a,b),a.nodeIsInserted_()}function k(a,b){for(var c=D(b),d=0;d<a.length;d++)j(a[d],c)}function l(a){I(a,new z(a,null))}function m(a){for(var b=0;b<a.length;b++)l(a[b])}function n(a,b){var c=a.nodeType===w.DOCUMENT_NODE?a:a.ownerDocument;c!==b.ownerDocument&&c.adoptNode(b)}function o(b,c){if(c.length){var d=b.ownerDocument;if(d!==c[0].ownerDocument)for(var e=0;e<c.length;e++)a.adoptNodeNoRemove(c[e],d)}}function p(a,b){o(a,b);var c=b.length;if(1===c)return J(b[0]);for(var d=J(a.ownerDocument.createDocumentFragment()),e=0;c>e;e++)d.appendChild(J(b[e]));return d}function q(a){if(void 0!==a.firstChild_)for(var b=a.firstChild_;b;){var c=b;b=b.nextSibling_,c.parentNode_=c.previousSibling_=c.nextSibling_=void 0}a.firstChild_=a.lastChild_=void 0}function r(a){if(a.invalidateShadowRenderer()){for(var b=a.firstChild;b;){A(b.parentNode===a);var c=b.nextSibling,d=J(b),e=d.parentNode;e&&U.call(e,d),b.previousSibling_=b.nextSibling_=b.parentNode_=null,b=c}a.firstChild_=a.lastChild_=null}else for(var c,f=J(a),g=f.firstChild;g;)c=g.nextSibling,U.call(f,g),g=c}function s(a){var b=a.parentNode;return b&&b.invalidateShadowRenderer()}function t(a){for(var b,c=0;c<a.length;c++)b=a[c],b.parentNode.removeChild(b)}function u(a,b,c){var d;if(d=K(c?O.call(c,a.impl,!1):P.call(a.impl,!1)),b){for(var e=a.firstChild;e;e=e.nextSibling)d.appendChild(u(e,!0,c));if(a instanceof M.HTMLTemplateElement)for(var f=d.content,e=a.content.firstChild;e;e=e.nextSibling)f.appendChild(u(e,!0,c))}return d}function v(a,b){if(!b||D(a)!==D(b))return!1;for(var c=b;c;c=c.parentNode)if(c===a)return!0;return!1}function w(a){A(a instanceof Q),x.call(this,a),this.parentNode_=void 0,this.firstChild_=void 0,this.lastChild_=void 0,this.nextSibling_=void 0,this.previousSibling_=void 0,this.treeScope_=void 0}var x=a.wrappers.EventTarget,y=a.wrappers.NodeList,z=a.TreeScope,A=a.assert,B=a.defineWrapGetter,C=a.enqueueMutation,D=a.getTreeScope,E=a.isWrapper,F=a.mixin,G=a.registerTransientObservers,H=a.registerWrapper,I=a.setTreeScope,J=a.unwrap,K=a.wrap,L=a.wrapIfNeeded,M=a.wrappers,N=!1,O=document.importNode,P=window.Node.prototype.cloneNode,Q=window.Node,R=window.DocumentFragment,S=(Q.prototype.appendChild,Q.prototype.compareDocumentPosition),T=Q.prototype.insertBefore,U=Q.prototype.removeChild,V=Q.prototype.replaceChild,W=/Trident/.test(navigator.userAgent),X=W?function(a,b){try{U.call(a,b)}catch(c){if(!(a instanceof R))throw c}}:function(a,b){U.call(a,b)};w.prototype=Object.create(x.prototype),F(w.prototype,{appendChild:function(a){return this.insertBefore(a,null)},insertBefore:function(a,c){b(a);var d;c?E(c)?d=J(c):(d=c,c=K(d)):(c=null,d=null),c&&A(c.parentNode===this);var e,h=c?c.previousSibling:this.lastChild,i=!this.invalidateShadowRenderer()&&!s(a);if(e=i?g(a):f(a,this,h,c),i)n(this,a),q(this),T.call(this.impl,J(a),d);else{h||(this.firstChild_=e[0]),c||(this.lastChild_=e[e.length-1]);var j=d?d.parentNode:this.impl;j?T.call(j,p(this,e),d):o(this,e)}return C(this,"childList",{addedNodes:e,nextSibling:c,previousSibling:h}),k(e,this),a},removeChild:function(a){if(b(a),a.parentNode!==this){for(var d=!1,e=(this.childNodes,this.firstChild);e;e=e.nextSibling)if(e===a){d=!0;break}if(!d)throw new Error("NotFoundError")}var f=J(a),g=a.nextSibling,h=a.previousSibling;if(this.invalidateShadowRenderer()){var i=this.firstChild,j=this.lastChild,k=f.parentNode;k&&X(k,f),i===a&&(this.firstChild_=g),j===a&&(this.lastChild_=h),h&&(h.nextSibling_=g),g&&(g.previousSibling_=h),a.previousSibling_=a.nextSibling_=a.parentNode_=void 0}else q(this),X(this.impl,f);return N||C(this,"childList",{removedNodes:c(a),nextSibling:g,previousSibling:h}),G(this,a),a},replaceChild:function(a,d){b(a);var e;if(E(d)?e=J(d):(e=d,d=K(e)),d.parentNode!==this)throw new Error("NotFoundError");var h,i=d.nextSibling,j=d.previousSibling,m=!this.invalidateShadowRenderer()&&!s(a);return m?h=g(a):(i===a&&(i=a.nextSibling),h=f(a,this,j,i)),m?(n(this,a),q(this),V.call(this.impl,J(a),e)):(this.firstChild===d&&(this.firstChild_=h[0]),this.lastChild===d&&(this.lastChild_=h[h.length-1]),d.previousSibling_=d.nextSibling_=d.parentNode_=void 0,e.parentNode&&V.call(e.parentNode,p(this,h),e)),C(this,"childList",{addedNodes:h,removedNodes:c(d),nextSibling:i,previousSibling:j}),l(d),k(h,this),d},nodeIsInserted_:function(){for(var a=this.firstChild;a;a=a.nextSibling)a.nodeIsInserted_()},hasChildNodes:function(){return null!==this.firstChild},get parentNode(){return void 0!==this.parentNode_?this.parentNode_:K(this.impl.parentNode)},get firstChild(){return void 0!==this.firstChild_?this.firstChild_:K(this.impl.firstChild)},get lastChild(){return void 0!==this.lastChild_?this.lastChild_:K(this.impl.lastChild)},get nextSibling(){return void 0!==this.nextSibling_?this.nextSibling_:K(this.impl.nextSibling)},get previousSibling(){return void 0!==this.previousSibling_?this.previousSibling_:K(this.impl.previousSibling)},get parentElement(){for(var a=this.parentNode;a&&a.nodeType!==w.ELEMENT_NODE;)a=a.parentNode;return a},get textContent(){for(var a="",b=this.firstChild;b;b=b.nextSibling)b.nodeType!=w.COMMENT_NODE&&(a+=b.textContent);return a},set textContent(a){var b=i(this.childNodes);if(this.invalidateShadowRenderer()){if(r(this),""!==a){var c=this.impl.ownerDocument.createTextNode(a);this.appendChild(c)}}else q(this),this.impl.textContent=a;var d=i(this.childNodes);C(this,"childList",{addedNodes:d,removedNodes:b}),m(b),k(d,this)},get childNodes(){for(var a=new y,b=0,c=this.firstChild;c;c=c.nextSibling)a[b++]=c;return a.length=b,a},cloneNode:function(a){return u(this,a)},contains:function(a){return v(this,L(a))},compareDocumentPosition:function(a){return S.call(this.impl,J(a))},normalize:function(){for(var a,b,c=i(this.childNodes),d=[],e="",f=0;f<c.length;f++)b=c[f],b.nodeType===w.TEXT_NODE?a||b.data.length?a?(e+=b.data,d.push(b)):a=b:this.removeNode(b):(a&&d.length&&(a.data+=e,cleanUpNodes(d)),d=[],e="",a=null,b.childNodes.length&&b.normalize());a&&d.length&&(a.data+=e,t(d))}}),B(w,"ownerDocument"),H(Q,w,document.createDocumentFragment()),delete w.prototype.querySelector,delete w.prototype.querySelectorAll,w.prototype=F(Object.create(x.prototype),w.prototype),a.cloneNode=u,a.nodeWasAdded=j,a.nodeWasRemoved=l,a.nodesWereAdded=k,a.nodesWereRemoved=m,a.snapshotNodeList=i,a.wrappers.Node=w}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a,c){for(var d,e=a.firstElementChild;e;){if(e.matches(c))return e;if(d=b(e,c))return d;e=e.nextElementSibling}return null}function c(a,b,d){for(var e=a.firstElementChild;e;)e.matches(b)&&(d[d.length++]=e),c(e,b,d),e=e.nextElementSibling;return d}var d={querySelector:function(a){return b(this,a)},querySelectorAll:function(a){return c(this,a,new NodeList)}},e={getElementsByTagName:function(a){return this.querySelectorAll(a)},getElementsByClassName:function(a){return this.querySelectorAll("."+a)},getElementsByTagNameNS:function(a,b){if("*"===a)return this.getElementsByTagName(b);for(var c=new NodeList,d=this.getElementsByTagName(b),e=0,f=0;e<d.length;e++)d[e].namespaceURI===a&&(c[f++]=d[e]);return c.length=f,c}};a.GetElementsByInterface=e,a.SelectorsInterface=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.nextSibling;return a}function c(a){for(;a&&a.nodeType!==Node.ELEMENT_NODE;)a=a.previousSibling;return a}var d=a.wrappers.NodeList,e={get firstElementChild(){return b(this.firstChild)},get lastElementChild(){return c(this.lastChild)},get childElementCount(){for(var a=0,b=this.firstElementChild;b;b=b.nextElementSibling)a++;return a},get children(){for(var a=new d,b=0,c=this.firstElementChild;c;c=c.nextElementSibling)a[b++]=c;return a.length=b,a},remove:function(){var a=this.parentNode;a&&a.removeChild(this)}},f={get nextElementSibling(){return b(this.nextSibling)},get previousElementSibling(){return c(this.previousSibling)}};a.ChildNodeInterface=f,a.ParentNodeInterface=e}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}var c=a.ChildNodeInterface,d=a.wrappers.Node,e=a.enqueueMutation,f=a.mixin,g=a.registerWrapper,h=window.CharacterData;b.prototype=Object.create(d.prototype),f(b.prototype,{get textContent(){return this.data},set textContent(a){this.data=a},get data(){return this.impl.data},set data(a){var b=this.impl.data;e(this,"characterData",{oldValue:b}),this.impl.data=a}}),f(b.prototype,c),g(h,b,document.createTextNode("")),a.wrappers.CharacterData=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a>>>0}function c(a){d.call(this,a)}var d=a.wrappers.CharacterData,e=(a.enqueueMutation,a.mixin),f=a.registerWrapper,g=window.Text;c.prototype=Object.create(d.prototype),e(c.prototype,{splitText:function(a){a=b(a);var c=this.data;if(a>c.length)throw new Error("IndexSizeError");var d=c.slice(0,a),e=c.slice(a);this.data=d;var f=this.ownerDocument.createTextNode(e);return this.parentNode&&this.parentNode.insertBefore(f,this.nextSibling),f}}),f(g,c,document.createTextNode("")),a.wrappers.Text=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b,c){var d=b.parentNode;if(d&&d.shadowRoot){var e=a.getRendererForHost(d);e.dependsOnAttribute(c)&&e.invalidate()}}function c(a,b,c){k(a,"attributes",{name:b,namespace:null,oldValue:c})}function d(a){h.call(this,a)}function e(a,c,d){var e=d||c;Object.defineProperty(a,c,{get:function(){return this.impl[c]},set:function(a){this.impl[c]=a,b(this,e)},configurable:!0,enumerable:!0})}var f=a.ChildNodeInterface,g=a.GetElementsByInterface,h=a.wrappers.Node,i=a.ParentNodeInterface,j=a.SelectorsInterface,k=(a.addWrapNodeListMethod,a.enqueueMutation),l=a.mixin,m=(a.oneOf,a.registerWrapper),n=a.wrappers,o=window.Element,p=["matches","mozMatchesSelector","msMatchesSelector","webkitMatchesSelector"].filter(function(a){return o.prototype[a]}),q=p[0],r=o.prototype[q];d.prototype=Object.create(h.prototype),l(d.prototype,{createShadowRoot:function(){var b=new n.ShadowRoot(this);this.impl.polymerShadowRoot_=b;var c=a.getRendererForHost(this);return c.invalidate(),b},get shadowRoot(){return this.impl.polymerShadowRoot_||null},setAttribute:function(a,d){var e=this.impl.getAttribute(a);this.impl.setAttribute(a,d),c(this,a,e),b(this,a)},removeAttribute:function(a){var d=this.impl.getAttribute(a);this.impl.removeAttribute(a),c(this,a,d),b(this,a)},matches:function(a){return r.call(this.impl,a)}}),p.forEach(function(a){"matches"!==a&&(d.prototype[a]=function(a){return this.matches(a)})}),o.prototype.webkitCreateShadowRoot&&(d.prototype.webkitCreateShadowRoot=d.prototype.createShadowRoot),e(d.prototype,"id"),e(d.prototype,"className","class"),l(d.prototype,f),l(d.prototype,g),l(d.prototype,i),l(d.prototype,j),m(o,d,document.createElementNS(null,"x")),a.matchesNames=p,a.wrappers.Element=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a){case"&":return"&amp;";case"<":return"&lt;";case">":return"&gt;";case'"':return"&quot;";case"Â ":return"&nbsp;"}}function c(a){return a.replace(z,b)}function d(a){return a.replace(A,b)}function e(a){for(var b={},c=0;c<a.length;c++)b[a[c]]=!0;return b}function f(a,b){switch(a.nodeType){case Node.ELEMENT_NODE:for(var e,f=a.tagName.toLowerCase(),h="<"+f,i=a.attributes,j=0;e=i[j];j++)h+=" "+e.name+'="'+c(e.value)+'"';return h+=">",B[f]?h:h+g(a)+"</"+f+">";case Node.TEXT_NODE:var k=a.data;return b&&C[b.localName]?k:d(k);case Node.COMMENT_NODE:return"<!--"+a.data+"-->";default:throw console.error(a),new Error("not implemented")}}function g(a){a instanceof y.HTMLTemplateElement&&(a=a.content);for(var b="",c=a.firstChild;c;c=c.nextSibling)b+=f(c,a);return b}function h(a,b,c){var d=c||"div";a.textContent="";var e=w(a.ownerDocument.createElement(d));e.innerHTML=b;for(var f;f=e.firstChild;)a.appendChild(x(f))}function i(a){o.call(this,a)}function j(a,b){var c=w(a.cloneNode(!1));c.innerHTML=b;for(var d,e=w(document.createDocumentFragment());d=c.firstChild;)e.appendChild(d);return x(e)}function k(b){return function(){return a.renderAllPending(),this.impl[b]}}function l(a){p(i,a,k(a))}function m(b){Object.defineProperty(i.prototype,b,{get:k(b),set:function(c){a.renderAllPending(),this.impl[b]=c},configurable:!0,enumerable:!0})}function n(b){Object.defineProperty(i.prototype,b,{value:function(){return a.renderAllPending(),this.impl[b].apply(this.impl,arguments)},configurable:!0,enumerable:!0})}var o=a.wrappers.Element,p=a.defineGetter,q=a.enqueueMutation,r=a.mixin,s=a.nodesWereAdded,t=a.nodesWereRemoved,u=a.registerWrapper,v=a.snapshotNodeList,w=a.unwrap,x=a.wrap,y=a.wrappers,z=/[&\u00A0"]/g,A=/[&\u00A0<>]/g,B=e(["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"]),C=e(["style","script","xmp","iframe","noembed","noframes","plaintext","noscript"]),D=/MSIE/.test(navigator.userAgent),E=window.HTMLElement,F=window.HTMLTemplateElement;i.prototype=Object.create(o.prototype),r(i.prototype,{get innerHTML(){return g(this)},set innerHTML(a){if(D&&C[this.localName])return void(this.textContent=a);var b=v(this.childNodes);this.invalidateShadowRenderer()?this instanceof y.HTMLTemplateElement?h(this.content,a):h(this,a,this.tagName):!F&&this instanceof y.HTMLTemplateElement?h(this.content,a):this.impl.innerHTML=a;var c=v(this.childNodes);q(this,"childList",{addedNodes:c,removedNodes:b}),t(b),s(c,this)},get outerHTML(){return f(this,this.parentNode)},set outerHTML(a){var b=this.parentNode;if(b){b.invalidateShadowRenderer();var c=j(b,a);b.replaceChild(c,this)}},insertAdjacentHTML:function(a,b){var c,d;switch(String(a).toLowerCase()){case"beforebegin":c=this.parentNode,d=this;break;case"afterend":c=this.parentNode,d=this.nextSibling;break;case"afterbegin":c=this,d=this.firstChild;break;case"beforeend":c=this,d=null;break;default:return}var e=j(c,b);c.insertBefore(e,d)}}),["clientHeight","clientLeft","clientTop","clientWidth","offsetHeight","offsetLeft","offsetTop","offsetWidth","scrollHeight","scrollWidth"].forEach(l),["scrollLeft","scrollTop"].forEach(m),["getBoundingClientRect","getClientRects","scrollIntoView"].forEach(n),u(E,i,document.createElement("b")),a.wrappers.HTMLElement=i,a.getInnerHTML=g,a.setInnerHTML=h}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.HTMLCanvasElement;b.prototype=Object.create(c.prototype),d(b.prototype,{getContext:function(){var a=this.impl.getContext.apply(this.impl,arguments);return a&&f(a)}}),e(g,b,document.createElement("canvas")),a.wrappers.HTMLCanvasElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLContentElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get select(){return this.getAttribute("select")},set select(a){this.setAttribute("select",a)},setAttribute:function(a,b){c.prototype.setAttribute.call(this,a,b),"select"===String(a).toLowerCase()&&this.invalidateShadowRenderer(!0)}}),f&&e(f,b),a.wrappers.HTMLContentElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a,b){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var e=f(document.createElement("img"));d.call(this,e),g(e,this),void 0!==a&&(e.width=a),void 0!==b&&(e.height=b)}var d=a.wrappers.HTMLElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLImageElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("img")),c.prototype=b.prototype,a.wrappers.HTMLImageElement=b,a.wrappers.Image=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=window.HTMLShadowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{}),f&&e(f,b),a.wrappers.HTMLShadowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){if(!a.defaultView)return a;var b=k.get(a);if(!b){for(b=a.implementation.createHTMLDocument("");b.lastChild;)b.removeChild(b.lastChild);k.set(a,b)}return b}function c(a){for(var c,d=b(a.ownerDocument),e=h(d.createDocumentFragment());c=a.firstChild;)e.appendChild(c);return e}function d(a){if(e.call(this,a),!l){var b=c(a);j.set(this,i(b))}}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.unwrap,i=a.wrap,j=new WeakMap,k=new WeakMap,l=window.HTMLTemplateElement;d.prototype=Object.create(e.prototype),f(d.prototype,{get content(){return l?i(this.impl.content):j.get(this)}}),l&&g(l,d),a.wrappers.HTMLTemplateElement=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.registerWrapper,e=window.HTMLMediaElement;b.prototype=Object.create(c.prototype),d(e,b,document.createElement("audio")),a.wrappers.HTMLMediaElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){d.call(this,a)}function c(a){if(!(this instanceof c))throw new TypeError("DOM object constructor cannot be called as a function.");var b=f(document.createElement("audio"));d.call(this,b),g(b,this),b.setAttribute("preload","auto"),void 0!==a&&b.setAttribute("src",a)}var d=a.wrappers.HTMLMediaElement,e=a.registerWrapper,f=a.unwrap,g=a.rewrap,h=window.HTMLAudioElement;b.prototype=Object.create(d.prototype),e(h,b,document.createElement("audio")),c.prototype=b.prototype,a.wrappers.HTMLAudioElement=b,a.wrappers.Audio=c}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){return a.replace(/\s+/g," ").trim()}function c(a){e.call(this,a)}function d(a,b,c,f){if(!(this instanceof d))throw new TypeError("DOM object constructor cannot be called as a function.");var g=i(document.createElement("option"));e.call(this,g),h(g,this),void 0!==a&&(g.text=a),void 0!==b&&g.setAttribute("value",b),c===!0&&g.setAttribute("selected",""),g.selected=f===!0}var e=a.wrappers.HTMLElement,f=a.mixin,g=a.registerWrapper,h=a.rewrap,i=a.unwrap,j=a.wrap,k=window.HTMLOptionElement;c.prototype=Object.create(e.prototype),f(c.prototype,{get text(){return b(this.textContent)},set text(a){this.textContent=b(String(a))},get form(){return j(i(this).form)}}),g(k,c,document.createElement("option")),d.prototype=c.prototype,a.wrappers.HTMLOptionElement=c,a.wrappers.Option=d}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.wrap,h=window.HTMLSelectElement;b.prototype=Object.create(c.prototype),d(b.prototype,{add:function(a,b){"object"==typeof b&&(b=f(b)),f(this).add(f(a),b)},remove:function(a){return void 0===a?void c.prototype.remove.call(this):("object"==typeof a&&(a=f(a)),void f(this).remove(a))},get form(){return g(f(this).form)}}),e(h,b,document.createElement("select")),a.wrappers.HTMLSelectElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.unwrap,g=a.wrap,h=a.wrapHTMLCollection,i=window.HTMLTableElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get caption(){return g(f(this).caption)},createCaption:function(){return g(f(this).createCaption())},get tHead(){return g(f(this).tHead)},createTHead:function(){return g(f(this).createTHead())},createTFoot:function(){return g(f(this).createTFoot())},get tFoot(){return g(f(this).tFoot)},get tBodies(){return h(f(this).tBodies)},createTBody:function(){return g(f(this).createTBody())},get rows(){return h(f(this).rows)},insertRow:function(a){return g(f(this).insertRow(a))}}),e(i,b,document.createElement("table")),a.wrappers.HTMLTableElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrapHTMLCollection,g=a.unwrap,h=a.wrap,i=window.HTMLTableSectionElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get rows(){return f(g(this).rows)},insertRow:function(a){return h(g(this).insertRow(a))}}),e(i,b,document.createElement("thead")),a.wrappers.HTMLTableSectionElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.HTMLElement,d=a.mixin,e=a.registerWrapper,f=a.wrapHTMLCollection,g=a.unwrap,h=a.wrap,i=window.HTMLTableRowElement;b.prototype=Object.create(c.prototype),d(b.prototype,{get cells(){return f(g(this).cells)},insertCell:function(a){return h(g(this).insertCell(a))}}),e(i,b,document.createElement("tr")),a.wrappers.HTMLTableRowElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){switch(a.localName){case"content":return new c(a);case"shadow":return new e(a);case"template":return new f(a)}d.call(this,a)}var c=a.wrappers.HTMLContentElement,d=a.wrappers.HTMLElement,e=a.wrappers.HTMLShadowElement,f=a.wrappers.HTMLTemplateElement,g=(a.mixin,a.registerWrapper),h=window.HTMLUnknownElement;b.prototype=Object.create(d.prototype),g(h,b),a.wrappers.HTMLUnknownElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.registerObject,c="http://www.w3.org/2000/svg",d=document.createElementNS(c,"title"),e=b(d),f=Object.getPrototypeOf(e.prototype).constructor;a.wrappers.SVGElement=f}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){m.call(this,a)}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.wrap,g=window.SVGUseElement,h="http://www.w3.org/2000/svg",i=f(document.createElementNS(h,"g")),j=document.createElementNS(h,"use"),k=i.constructor,l=Object.getPrototypeOf(k.prototype),m=l.constructor;b.prototype=Object.create(l),"instanceRoot"in j&&c(b.prototype,{get instanceRoot(){return f(e(this).instanceRoot)},get animatedInstanceRoot(){return f(e(this).animatedInstanceRoot)}}),d(g,b,j),a.wrappers.SVGUseElement=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.mixin,e=a.registerWrapper,f=a.wrap,g=window.SVGElementInstance;g&&(b.prototype=Object.create(c.prototype),d(b.prototype,{get correspondingElement(){return f(this.impl.correspondingElement)},get correspondingUseElement(){return f(this.impl.correspondingUseElement)},get parentNode(){return f(this.impl.parentNode)},get childNodes(){throw new Error("Not implemented")},get firstChild(){return f(this.impl.firstChild)},get lastChild(){return f(this.impl.lastChild)},get previousSibling(){return f(this.impl.previousSibling)},get nextSibling(){return f(this.impl.nextSibling)}}),e(g,b),a.wrappers.SVGElementInstance=b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrap,f=a.unwrapIfNeeded,g=a.wrap,h=window.CanvasRenderingContext2D;c(b.prototype,{get canvas(){return g(this.impl.canvas)},drawImage:function(){arguments[0]=f(arguments[0]),this.impl.drawImage.apply(this.impl,arguments)},createPattern:function(){return arguments[0]=e(arguments[0]),this.impl.createPattern.apply(this.impl,arguments)}}),d(h,b,document.createElement("canvas").getContext("2d")),a.wrappers.CanvasRenderingContext2D=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.mixin,d=a.registerWrapper,e=a.unwrapIfNeeded,f=a.wrap,g=window.WebGLRenderingContext;if(g){c(b.prototype,{get canvas(){return f(this.impl.canvas)},texImage2D:function(){arguments[5]=e(arguments[5]),this.impl.texImage2D.apply(this.impl,arguments)},texSubImage2D:function(){arguments[6]=e(arguments[6]),this.impl.texSubImage2D.apply(this.impl,arguments)}});var h=/WebKit/.test(navigator.userAgent)?{drawingBufferHeight:null,drawingBufferWidth:null}:{};d(g,b,h),a.wrappers.WebGLRenderingContext=b}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap,g=window.Range;b.prototype={get startContainer(){return f(this.impl.startContainer)},get endContainer(){return f(this.impl.endContainer)},get commonAncestorContainer(){return f(this.impl.commonAncestorContainer)},setStart:function(a,b){this.impl.setStart(e(a),b)},setEnd:function(a,b){this.impl.setEnd(e(a),b)},setStartBefore:function(a){this.impl.setStartBefore(e(a))},setStartAfter:function(a){this.impl.setStartAfter(e(a))},setEndBefore:function(a){this.impl.setEndBefore(e(a))},setEndAfter:function(a){this.impl.setEndAfter(e(a))},selectNode:function(a){this.impl.selectNode(e(a))},selectNodeContents:function(a){this.impl.selectNodeContents(e(a))},compareBoundaryPoints:function(a,b){return this.impl.compareBoundaryPoints(a,d(b))},extractContents:function(){return f(this.impl.extractContents())},cloneContents:function(){return f(this.impl.cloneContents())},insertNode:function(a){this.impl.insertNode(e(a))},surroundContents:function(a){this.impl.surroundContents(e(a))},cloneRange:function(){return f(this.impl.cloneRange())},isPointInRange:function(a,b){return this.impl.isPointInRange(e(a),b)},comparePoint:function(a,b){return this.impl.comparePoint(e(a),b)},intersectsNode:function(a){return this.impl.intersectsNode(e(a))},toString:function(){return this.impl.toString()}},g.prototype.createContextualFragment&&(b.prototype.createContextualFragment=function(a){return f(this.impl.createContextualFragment(a))}),c(window.Range,b,document.createRange()),a.wrappers.Range=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.GetElementsByInterface,c=a.ParentNodeInterface,d=a.SelectorsInterface,e=a.mixin,f=a.registerObject,g=f(document.createDocumentFragment());
+e(g.prototype,c),e(g.prototype,d),e(g.prototype,b);var h=f(document.createComment(""));a.wrappers.Comment=h,a.wrappers.DocumentFragment=g}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=k(a.impl.ownerDocument.createDocumentFragment());c.call(this,b),i(b,this),this.treeScope_=new d(this,g(a));var e=a.shadowRoot;m.set(this,e),l.set(this,a)}var c=a.wrappers.DocumentFragment,d=a.TreeScope,e=a.elementFromPoint,f=a.getInnerHTML,g=a.getTreeScope,h=a.mixin,i=a.rewrap,j=a.setInnerHTML,k=a.unwrap,l=new WeakMap,m=new WeakMap,n=/[ \t\n\r\f]/;b.prototype=Object.create(c.prototype),h(b.prototype,{get innerHTML(){return f(this)},set innerHTML(a){j(this,a),this.invalidateShadowRenderer()},get olderShadowRoot(){return m.get(this)||null},get host(){return l.get(this)||null},invalidateShadowRenderer:function(){return l.get(this).invalidateShadowRenderer()},elementFromPoint:function(a,b){return e(this,this.ownerDocument,a,b)},getElementById:function(a){return n.test(a)?null:this.querySelector('[id="'+a+'"]')}}),a.wrappers.ShadowRoot=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){a.previousSibling_=a.previousSibling,a.nextSibling_=a.nextSibling,a.parentNode_=a.parentNode}function c(a,c,e){var f=G(a),g=G(c),h=e?G(e):null;if(d(c),b(c),e)a.firstChild===e&&(a.firstChild_=e),e.previousSibling_=e.previousSibling;else{a.lastChild_=a.lastChild,a.lastChild===a.firstChild&&(a.firstChild_=a.firstChild);var i=H(f.lastChild);i&&(i.nextSibling_=i.nextSibling)}f.insertBefore(g,h)}function d(a){var c=G(a),d=c.parentNode;if(d){var e=H(d);b(a),a.previousSibling&&(a.previousSibling.nextSibling_=a),a.nextSibling&&(a.nextSibling.previousSibling_=a),e.lastChild===a&&(e.lastChild_=a),e.firstChild===a&&(e.firstChild_=a),d.removeChild(c)}}function e(a,b){g(b).push(a),x(a,b);var c=J.get(a);c||J.set(a,c=[]),c.push(b)}function f(a){I.set(a,[])}function g(a){var b=I.get(a);return b||I.set(a,b=[]),b}function h(a){for(var b=[],c=0,d=a.firstChild;d;d=d.nextSibling)b[c++]=d;return b}function i(a,b,c){for(var d=a.firstChild;d;d=d.nextSibling)if(b(d)){if(c(d)===!1)return}else i(d,b,c)}function j(a,b){var c=b.getAttribute("select");if(!c)return!0;if(c=c.trim(),!c)return!0;if(!(a instanceof z))return!1;if("*"===c||c===a.localName)return!0;if(!M.test(c))return!1;if(":"===c[0]&&!N.test(c))return!1;try{return a.matches(c)}catch(d){return!1}}function k(){for(var a=0;a<P.length;a++){var b=P[a],c=b.parentRenderer;c&&c.dirty||b.render()}P=[]}function l(){y=null,k()}function m(a){var b=L.get(a);return b||(b=new q(a),L.set(a,b)),b}function n(a){var b=E(a).root;return b instanceof D?b:null}function o(a){return m(a.host)}function p(a){this.skip=!1,this.node=a,this.childNodes=[]}function q(a){this.host=a,this.dirty=!1,this.invalidateAttributes(),this.associateNode(a)}function r(a){return a instanceof A}function s(a){return a instanceof A}function t(a){return a instanceof B}function u(a){return a instanceof B}function v(a){return a.shadowRoot}function w(a){for(var b=[],c=a.shadowRoot;c;c=c.olderShadowRoot)b.push(c);return b}function x(a,b){K.set(a,b)}var y,z=a.wrappers.Element,A=a.wrappers.HTMLContentElement,B=a.wrappers.HTMLShadowElement,C=a.wrappers.Node,D=a.wrappers.ShadowRoot,E=(a.assert,a.getTreeScope),F=(a.mixin,a.oneOf),G=a.unwrap,H=a.wrap,I=new WeakMap,J=new WeakMap,K=new WeakMap,L=new WeakMap,M=/^[*.:#[a-zA-Z_|]/,N=new RegExp("^:("+["link","visited","target","enabled","disabled","checked","indeterminate","nth-child","nth-last-child","nth-of-type","nth-last-of-type","first-child","last-child","first-of-type","last-of-type","only-of-type"].join("|")+")"),O=F(window,["requestAnimationFrame","mozRequestAnimationFrame","webkitRequestAnimationFrame","setTimeout"]),P=[],Q=new ArraySplice;Q.equals=function(a,b){return G(a.node)===b},p.prototype={append:function(a){var b=new p(a);return this.childNodes.push(b),b},sync:function(a){if(!this.skip){for(var b=this.node,e=this.childNodes,f=h(G(b)),g=a||new WeakMap,i=Q.calculateSplices(e,f),j=0,k=0,l=0,m=0;m<i.length;m++){for(var n=i[m];l<n.index;l++)k++,e[j++].sync(g);for(var o=n.removed.length,p=0;o>p;p++){var q=H(f[k++]);g.get(q)||d(q)}for(var r=n.addedCount,s=f[k]&&H(f[k]),p=0;r>p;p++){var t=e[j++],u=t.node;c(b,u,s),g.set(u,!0),t.sync(g)}l+=r}for(var m=l;m<e.length;m++)e[m].sync(g)}}},q.prototype={render:function(a){if(this.dirty){this.invalidateAttributes(),this.treeComposition();var b=this.host,c=b.shadowRoot;this.associateNode(b);for(var d=!e,e=a||new p(b),f=c.firstChild;f;f=f.nextSibling)this.renderNode(c,e,f,!1);d&&e.sync(),this.dirty=!1}},get parentRenderer(){return E(this.host).renderer},invalidate:function(){if(!this.dirty){if(this.dirty=!0,P.push(this),y)return;y=window[O](l,0)}},renderNode:function(a,b,c,d){if(v(c)){b=b.append(c);var e=m(c);e.dirty=!0,e.render(b)}else r(c)?this.renderInsertionPoint(a,b,c,d):t(c)?this.renderShadowInsertionPoint(a,b,c):this.renderAsAnyDomTree(a,b,c,d)},renderAsAnyDomTree:function(a,b,c,d){if(b=b.append(c),v(c)){var e=m(c);b.skip=!e.dirty,e.render(b)}else for(var f=c.firstChild;f;f=f.nextSibling)this.renderNode(a,b,f,d)},renderInsertionPoint:function(a,b,c,d){var e=g(c);if(e.length){this.associateNode(c);for(var f=0;f<e.length;f++){var h=e[f];r(h)&&d?this.renderInsertionPoint(a,b,h,d):this.renderAsAnyDomTree(a,b,h,d)}}else this.renderFallbackContent(a,b,c);this.associateNode(c.parentNode)},renderShadowInsertionPoint:function(a,b,c){var d=a.olderShadowRoot;if(d){x(d,c),this.associateNode(c.parentNode);for(var e=d.firstChild;e;e=e.nextSibling)this.renderNode(d,b,e,!0)}else this.renderFallbackContent(a,b,c)},renderFallbackContent:function(a,b,c){this.associateNode(c),this.associateNode(c.parentNode);for(var d=c.firstChild;d;d=d.nextSibling)this.renderAsAnyDomTree(a,b,d,!1)},invalidateAttributes:function(){this.attributes=Object.create(null)},updateDependentAttributes:function(a){if(a){var b=this.attributes;/\.\w+/.test(a)&&(b["class"]=!0),/#\w+/.test(a)&&(b.id=!0),a.replace(/\[\s*([^\s=\|~\]]+)/g,function(a,c){b[c]=!0})}},dependsOnAttribute:function(a){return this.attributes[a]},distribute:function(a,b){var c=this;i(a,s,function(a){f(a),c.updateDependentAttributes(a.getAttribute("select"));for(var d=0;d<b.length;d++){var g=b[d];void 0!==g&&j(g,a)&&(e(g,a),b[d]=void 0)}})},treeComposition:function(){for(var a=this.host,b=a.shadowRoot,c=[],d=a.firstChild;d;d=d.nextSibling)if(r(d)){var e=g(d);e&&e.length||(e=h(d)),c.push.apply(c,e)}else c.push(d);for(var f,j;b;){if(f=void 0,i(b,u,function(a){return f=a,!1}),j=f,this.distribute(b,c),j){var k=b.olderShadowRoot;if(k){b=k,x(b,j);continue}break}break}},associateNode:function(a){a.impl.polymerShadowRenderer_=this}},C.prototype.invalidateShadowRenderer=function(){var a=this.impl.polymerShadowRenderer_;return a?(a.invalidate(),!0):!1},A.prototype.getDistributedNodes=function(){return k(),g(this)},B.prototype.nodeIsInserted_=A.prototype.nodeIsInserted_=function(){this.invalidateShadowRenderer();var a,b=n(this);b&&(a=o(b)),this.impl.polymerShadowRenderer_=a,a&&a.invalidate()},a.eventParentsTable=J,a.getRendererForHost=m,a.getShadowTrees=w,a.insertionParentTable=K,a.renderAllPending=k,a.visual={insertBefore:c,remove:d}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(b){if(window[b]){d(!a.wrappers[b]);var i=function(a){c.call(this,a)};i.prototype=Object.create(c.prototype),e(i.prototype,{get form(){return h(g(this).form)}}),f(window[b],i,document.createElement(b.slice(4,-7))),a.wrappers[b]=i}}var c=a.wrappers.HTMLElement,d=a.assert,e=a.mixin,f=a.registerWrapper,g=a.unwrap,h=a.wrap,i=["HTMLButtonElement","HTMLFieldSetElement","HTMLInputElement","HTMLKeygenElement","HTMLLabelElement","HTMLLegendElement","HTMLObjectElement","HTMLOutputElement","HTMLTextAreaElement"];i.forEach(b)}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){this.impl=a}{var c=a.registerWrapper,d=a.unwrap,e=a.unwrapIfNeeded,f=a.wrap;window.Selection}b.prototype={get anchorNode(){return f(this.impl.anchorNode)},get focusNode(){return f(this.impl.focusNode)},addRange:function(a){this.impl.addRange(d(a))},collapse:function(a,b){this.impl.collapse(e(a),b)},containsNode:function(a,b){return this.impl.containsNode(e(a),b)},extend:function(a,b){this.impl.extend(e(a),b)},getRangeAt:function(a){return f(this.impl.getRangeAt(a))},removeRange:function(a){this.impl.removeRange(d(a))},selectAllChildren:function(a){this.impl.selectAllChildren(e(a))},toString:function(){return this.impl.toString()}},c(window.Selection,b,window.getSelection()),a.wrappers.Selection=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){k.call(this,a),this.treeScope_=new p(this,null)}function c(a){var c=document[a];b.prototype[a]=function(){return A(c.apply(this.impl,arguments))}}function d(a,b){D.call(b.impl,z(a)),e(a,b)}function e(a,b){a.shadowRoot&&b.adoptNode(a.shadowRoot),a instanceof o&&f(a,b);for(var c=a.firstChild;c;c=c.nextSibling)e(c,b)}function f(a,b){var c=a.olderShadowRoot;c&&b.adoptNode(c)}function g(a){this.impl=a}function h(a,b){var c=document.implementation[b];a.prototype[b]=function(){return A(c.apply(this.impl,arguments))}}function i(a,b){var c=document.implementation[b];a.prototype[b]=function(){return c.apply(this.impl,arguments)}}var j=a.GetElementsByInterface,k=a.wrappers.Node,l=a.ParentNodeInterface,m=a.wrappers.Selection,n=a.SelectorsInterface,o=a.wrappers.ShadowRoot,p=a.TreeScope,q=a.cloneNode,r=a.defineWrapGetter,s=a.elementFromPoint,t=a.forwardMethodsToWrapper,u=a.matchesNames,v=a.mixin,w=a.registerWrapper,x=a.renderAllPending,y=a.rewrap,z=a.unwrap,A=a.wrap,B=a.wrapEventTargetMethods,C=(a.wrapNodeList,new WeakMap);b.prototype=Object.create(k.prototype),r(b,"documentElement"),r(b,"body"),r(b,"head"),["createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","getElementById"].forEach(c);var D=document.adoptNode,E=document.getSelection;if(v(b.prototype,{adoptNode:function(a){return a.parentNode&&a.parentNode.removeChild(a),d(a,this),a},elementFromPoint:function(a,b){return s(this,this,a,b)},importNode:function(a,b){return q(a,b,this.impl)},getSelection:function(){return x(),new m(E.call(z(this)))}}),document.registerElement){var F=document.registerElement;b.prototype.registerElement=function(b,c){function d(a){return a?void(this.impl=a):c.extends?document.createElement(c.extends,b):document.createElement(b)}var e=c.prototype;if(a.nativePrototypeTable.get(e))throw new Error("NotSupportedError");for(var f,g=Object.getPrototypeOf(e),h=[];g&&!(f=a.nativePrototypeTable.get(g));)h.push(g),g=Object.getPrototypeOf(g);if(!f)throw new Error("NotSupportedError");for(var i=Object.create(f),j=h.length-1;j>=0;j--)i=Object.create(i);["createdCallback","attachedCallback","detachedCallback","attributeChangedCallback"].forEach(function(a){var b=e[a];b&&(i[a]=function(){A(this)instanceof d||y(this),b.apply(A(this),arguments)})});var k={prototype:i};c.extends&&(k.extends=c.extends),d.prototype=e,d.prototype.constructor=d,a.constructorTable.set(i,d),a.nativePrototypeTable.set(e,i);F.call(z(this),b,k);return d},t([window.HTMLDocument||window.Document],["registerElement"])}t([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement,window.HTMLHtmlElement],["appendChild","compareDocumentPosition","contains","getElementsByClassName","getElementsByTagName","getElementsByTagNameNS","insertBefore","querySelector","querySelectorAll","removeChild","replaceChild"].concat(u)),t([window.HTMLDocument||window.Document],["adoptNode","importNode","contains","createComment","createDocumentFragment","createElement","createElementNS","createEvent","createEventNS","createRange","createTextNode","elementFromPoint","getElementById","getSelection"]),v(b.prototype,j),v(b.prototype,l),v(b.prototype,n),v(b.prototype,{get implementation(){var a=C.get(this);return a?a:(a=new g(z(this).implementation),C.set(this,a),a)}}),w(window.Document,b,document.implementation.createHTMLDocument("")),window.HTMLDocument&&w(window.HTMLDocument,b),B([window.HTMLBodyElement,window.HTMLDocument||window.Document,window.HTMLHeadElement]),h(g,"createDocumentType"),h(g,"createDocument"),h(g,"createHTMLDocument"),i(g,"hasFeature"),w(window.DOMImplementation,g),t([window.DOMImplementation],["createDocumentType","createDocument","createHTMLDocument","hasFeature"]),a.adoptNodeNoRemove=d,a.wrappers.DOMImplementation=g,a.wrappers.Document=b}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){c.call(this,a)}var c=a.wrappers.EventTarget,d=a.wrappers.Selection,e=a.mixin,f=a.registerWrapper,g=a.renderAllPending,h=a.unwrap,i=a.unwrapIfNeeded,j=a.wrap,k=window.Window,l=window.getComputedStyle,m=window.getSelection;b.prototype=Object.create(c.prototype),k.prototype.getComputedStyle=function(a,b){return j(this||window).getComputedStyle(i(a),b)},k.prototype.getSelection=function(){return j(this||window).getSelection()},delete window.getComputedStyle,delete window.getSelection,["addEventListener","removeEventListener","dispatchEvent"].forEach(function(a){k.prototype[a]=function(){var b=j(this||window);return b[a].apply(b,arguments)},delete window[a]}),e(b.prototype,{getComputedStyle:function(a,b){return g(),l.call(h(this),i(a),b)},getSelection:function(){return g(),new d(m.call(h(this)))}}),f(k,b),a.wrappers.Window=b}(window.ShadowDOMPolyfill),function(a){"use strict";var b=a.unwrap,c=window.DataTransfer||window.Clipboard,d=c.prototype.setDragImage;c.prototype.setDragImage=function(a,c,e){d.call(this,b(a),c,e)}}(window.ShadowDOMPolyfill),function(a){"use strict";function b(a){var b=c[a],d=window[b];if(d){var e=document.createElement(a),f=e.constructor;window[b]=f}}var c=(a.isWrapperFor,{a:"HTMLAnchorElement",area:"HTMLAreaElement",audio:"HTMLAudioElement",base:"HTMLBaseElement",body:"HTMLBodyElement",br:"HTMLBRElement",button:"HTMLButtonElement",canvas:"HTMLCanvasElement",caption:"HTMLTableCaptionElement",col:"HTMLTableColElement",content:"HTMLContentElement",data:"HTMLDataElement",datalist:"HTMLDataListElement",del:"HTMLModElement",dir:"HTMLDirectoryElement",div:"HTMLDivElement",dl:"HTMLDListElement",embed:"HTMLEmbedElement",fieldset:"HTMLFieldSetElement",font:"HTMLFontElement",form:"HTMLFormElement",frame:"HTMLFrameElement",frameset:"HTMLFrameSetElement",h1:"HTMLHeadingElement",head:"HTMLHeadElement",hr:"HTMLHRElement",html:"HTMLHtmlElement",iframe:"HTMLIFrameElement",img:"HTMLImageElement",input:"HTMLInputElement",keygen:"HTMLKeygenElement",label:"HTMLLabelElement",legend:"HTMLLegendElement",li:"HTMLLIElement",link:"HTMLLinkElement",map:"HTMLMapElement",marquee:"HTMLMarqueeElement",menu:"HTMLMenuElement",menuitem:"HTMLMenuItemElement",meta:"HTMLMetaElement",meter:"HTMLMeterElement",object:"HTMLObjectElement",ol:"HTMLOListElement",optgroup:"HTMLOptGroupElement",option:"HTMLOptionElement",output:"HTMLOutputElement",p:"HTMLParagraphElement",param:"HTMLParamElement",pre:"HTMLPreElement",progress:"HTMLProgressElement",q:"HTMLQuoteElement",script:"HTMLScriptElement",select:"HTMLSelectElement",shadow:"HTMLShadowElement",source:"HTMLSourceElement",span:"HTMLSpanElement",style:"HTMLStyleElement",table:"HTMLTableElement",tbody:"HTMLTableSectionElement",template:"HTMLTemplateElement",textarea:"HTMLTextAreaElement",thead:"HTMLTableSectionElement",time:"HTMLTimeElement",title:"HTMLTitleElement",tr:"HTMLTableRowElement",track:"HTMLTrackElement",ul:"HTMLUListElement",video:"HTMLVideoElement"});Object.keys(c).forEach(b),Object.getOwnPropertyNames(a.wrappers).forEach(function(b){window[b]=a.wrappers[b]})}(window.ShadowDOMPolyfill),function(){window.wrap=ShadowDOMPolyfill.wrapIfNeeded,window.unwrap=ShadowDOMPolyfill.unwrapIfNeeded,Object.defineProperty(Element.prototype,"webkitShadowRoot",Object.getOwnPropertyDescriptor(Element.prototype,"shadowRoot"));var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b},Element.prototype.webkitCreateShadowRoot=Element.prototype.createShadowRoot}(),function(a){function b(a,b){var c="";return Array.prototype.forEach.call(a,function(a){c+=a.textContent+"\n\n"}),b||(c=c.replace(l,"")),c}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){var b=c(a);document.head.appendChild(b);var d=[];if(b.sheet)try{d=b.sheet.cssRules}catch(e){}else console.warn("sheet not found",b);return b.parentNode.removeChild(b),d}function e(){v.initialized=!0,document.body.appendChild(v);var a=v.contentDocument,b=a.createElement("base");b.href=document.baseURI,a.head.appendChild(b)}function f(a){v.initialized||e(),document.body.appendChild(v),a(v.contentDocument),document.body.removeChild(v)}function g(a,b){if(b){var e;if(a.match("@import")&&x){var g=c(a);f(function(a){a.head.appendChild(g.impl),e=g.sheet.cssRules,b(e)})}else e=d(a),b(e)}}function h(a){a&&j().appendChild(document.createTextNode(a))}function i(a,b){var d=c(a);d.setAttribute(b,""),d.setAttribute(z,""),document.head.appendChild(d)}function j(){return w||(w=document.createElement("style"),w.setAttribute(z,""),w[z]=!0),w}var k={strictStyling:!1,registry:{},shimStyling:function(a,c,d){var e=this.prepareRoot(a,c,d),f=this.isTypeExtension(d),g=this.makeScopeSelector(c,f),h=b(e,!0);h=this.scopeCssText(h,g),a&&(a.shimmedStyle=h),this.addCssToDocument(h,c)},shimStyle:function(a,b){return this.shimCssText(a.textContent,b)},shimCssText:function(a,b){return a=this.insertDirectives(a),this.scopeCssText(a,b)},makeScopeSelector:function(a,b){return a?b?"[is="+a+"]":a:""},isTypeExtension:function(a){return a&&a.indexOf("-")<0},prepareRoot:function(a,b,c){var d=this.registerRoot(a,b,c);return this.replaceTextInStyles(d.rootStyles,this.insertDirectives),this.removeStyles(a,d.rootStyles),this.strictStyling&&this.applyScopeToContent(a,b),d.scopeStyles},removeStyles:function(a,b){for(var c,d=0,e=b.length;e>d&&(c=b[d]);d++)c.parentNode.removeChild(c)},registerRoot:function(a,b,c){var d=this.registry[b]={root:a,name:b,extendsName:c},e=this.findStyles(a);d.rootStyles=e,d.scopeStyles=d.rootStyles;var f=this.registry[d.extendsName];return!f||a&&!a.querySelector("shadow")||(d.scopeStyles=f.scopeStyles.concat(d.scopeStyles)),d},findStyles:function(a){if(!a)return[];var b=a.querySelectorAll("style");return Array.prototype.filter.call(b,function(a){return!a.hasAttribute(A)})},applyScopeToContent:function(a,b){a&&(Array.prototype.forEach.call(a.querySelectorAll("*"),function(a){a.setAttribute(b,"")}),Array.prototype.forEach.call(a.querySelectorAll("template"),function(a){this.applyScopeToContent(a.content,b)},this))},insertDirectives:function(a){return a=this.insertPolyfillDirectivesInCssText(a),this.insertPolyfillRulesInCssText(a)},insertPolyfillDirectivesInCssText:function(a){return a=a.replace(m,function(a,b){return b.slice(0,-2)+"{"}),a.replace(n,function(a,b){return b+" {"})},insertPolyfillRulesInCssText:function(a){return a=a.replace(o,function(a,b){return b.slice(0,-1)}),a.replace(p,function(a,b,c,d){var e=a.replace(b,"").replace(c,"");return d+e})},scopeCssText:function(a,b){var c=this.extractUnscopedRulesFromCssText(a);if(a=this.insertPolyfillHostInCssText(a),a=this.convertColonHost(a),a=this.convertColonAncestor(a),a=this.convertCombinators(a),b){var a,d=this;g(a,function(c){a=d.scopeRules(c,b)})}return a=a+"\n"+c,a.trim()},extractUnscopedRulesFromCssText:function(a){for(var b,c="";b=q.exec(a);)c+=b[1].slice(0,-1)+"\n\n";for(;b=r.exec(a);)c+=b[0].replace(b[2],"").replace(b[1],b[3])+"\n\n";return c},convertColonHost:function(a){return this.convertColonRule(a,cssColonHostRe,this.colonHostPartReplacer)},convertColonAncestor:function(a){return this.convertColonRule(a,cssColonAncestorRe,this.colonAncestorPartReplacer)},convertColonRule:function(a,b,c){return a.replace(b,function(a,b,d,e){if(b=polyfillHostNoCombinator,d){for(var f,g=d.split(","),h=[],i=0,j=g.length;j>i&&(f=g[i]);i++)f=f.trim(),h.push(c(b,f,e));return h.join(",")}return b+e})},colonAncestorPartReplacer:function(a,b,c){return b.match(s)?this.colonHostPartReplacer(a,b,c):a+b+c+", "+b+" "+a+c},colonHostPartReplacer:function(a,b,c){return a+b.replace(s,"")+c},convertCombinators:function(a){for(var b=0;b<combinatorsRe.length;b++)a=a.replace(combinatorsRe[b]," ");return a},scopeRules:function(a,b){var c="";return a&&Array.prototype.forEach.call(a,function(a){a.selectorText&&a.style&&a.style.cssText?(c+=this.scopeSelector(a.selectorText,b,this.strictStyling)+" {\n  ",c+=this.propertiesFromRule(a)+"\n}\n\n"):a.type===CSSRule.MEDIA_RULE?(c+="@media "+a.media.mediaText+" {\n",c+=this.scopeRules(a.cssRules,b),c+="\n}\n\n"):a.cssText&&(c+=a.cssText+"\n\n")},this),c},scopeSelector:function(a,b,c){var d=[],e=a.split(",");return e.forEach(function(a){a=a.trim(),this.selectorNeedsScoping(a,b)&&(a=c&&!a.match(polyfillHostNoCombinator)?this.applyStrictSelectorScope(a,b):this.applySimpleSelectorScope(a,b)),d.push(a)},this),d.join(", ")},selectorNeedsScoping:function(a,b){var c=this.makeScopeMatcher(b);return!a.match(c)},makeScopeMatcher:function(a){return a=a.replace(/\[/g,"\\[").replace(/\[/g,"\\]"),new RegExp("^("+a+")"+selectorReSuffix,"m")},applySimpleSelectorScope:function(a,b){return a.match(polyfillHostRe)?(a=a.replace(polyfillHostNoCombinator,b),a.replace(polyfillHostRe,b+" ")):b+" "+a},applyStrictSelectorScope:function(a,b){b=b.replace(/\[is=([^\]]*)\]/g,"$1");var c=[" ",">","+","~"],d=a,e="["+b+"]";return c.forEach(function(a){var b=d.split(a);d=b.map(function(a){var b=a.trim().replace(polyfillHostRe,"");return b&&c.indexOf(b)<0&&b.indexOf(e)<0&&(a=b.replace(/([^:]*)(:*)(.*)/,"$1"+e+"$2$3")),a}).join(a)}),d},insertPolyfillHostInCssText:function(a){return a.replace(hostRe,s).replace(colonHostRe,s).replace(colonAncestorRe,t)},propertiesFromRule:function(a){return a.style.content&&!a.style.content.match(/['"]+/)?a.style.cssText.replace(/content:[^;]*;/g,"content: '"+a.style.content+"';"):a.style.cssText},replaceTextInStyles:function(a,b){a&&b&&(a instanceof Array||(a=[a]),Array.prototype.forEach.call(a,function(a){a.textContent=b.call(this,a.textContent)},this))},addCssToDocument:function(a,b){a.match("@import")?i(a,b):h(a)}},l=/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,m=/\/\*\s*@polyfill ([^*]*\*+([^/*][^*]*\*+)*\/)([^{]*?){/gim,n=/polyfill-next-selector[^}]*content\:[\s]*'([^']*)'[^}]*}([^{]*?){/gim,o=/\/\*\s@polyfill-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,p=/(polyfill-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*}/gim,q=/\/\*\s@polyfill-unscoped-rule([^*]*\*+([^/*][^*]*\*+)*)\//gim,r=/(polyfill-unscoped-rule)[^}]*(content\:[\s]*'([^']*)'[^;]*;)[^}]*}/gim,s="-shadowcsshost",t="-shadowcssancestor",u=")(?:\\(((?:\\([^)(]*\\)|[^)(]*)+?)\\))?([^,{]*)";cssColonHostRe=new RegExp("("+s+u,"gim"),cssColonAncestorRe=new RegExp("("+t+u,"gim"),selectorReSuffix="([>\\s~+[.,{:][\\s\\S]*)?$",hostRe=/@host/gim,colonHostRe=/\:host/gim,colonAncestorRe=/\:ancestor/gim,polyfillHostNoCombinator=s+"-no-combinator",polyfillHostRe=new RegExp(s,"gim"),polyfillAncestorRe=new RegExp(t,"gim"),combinatorsRe=[/\^\^/g,/\^/g,/\/shadow\//g,/\/shadow-deep\//g];var v=document.createElement("iframe");v.style.display="none";var w,x=navigator.userAgent.match("Chrome"),y="shim-shadowdom",z="shim-shadowdom-css",A="no-shim";if(window.ShadowDOMPolyfill){h("style { display: none !important; }\n");var B=wrap(document),C=B.querySelector("head");C.insertBefore(j(),C.childNodes[0]),document.addEventListener("DOMContentLoaded",function(){var b=a.urlResolver;if(window.HTMLImports&&!HTMLImports.useNative){var c="link[rel=stylesheet]["+y+"]",d="style["+y+"]";HTMLImports.importer.documentPreloadSelectors+=","+c,HTMLImports.importer.importsPreloadSelectors+=","+c,HTMLImports.parser.documentSelectors=[HTMLImports.parser.documentSelectors,c,d].join(",");var e=HTMLImports.parser.parseGeneric;HTMLImports.parser.parseGeneric=function(a){if(!a[z]){var c=a.__importElement||a;if(!c.hasAttribute(y))return void e.call(this,a);a.__resource?(c=a.ownerDocument.createElement("style"),c.textContent=b.resolveCssText(a.__resource,a.href)):b.resolveStyle(c),c.textContent=k.shimStyle(c),c.removeAttribute(y,""),c.setAttribute(z,""),c[z]=!0,c.parentNode!==C&&(a.parentNode===C?C.replaceChild(c,a):C.appendChild(c)),c.__importParsed=!0,this.markParsingComplete(a)}};var f=HTMLImports.parser.hasResource;HTMLImports.parser.hasResource=function(a){return"link"===a.localName&&"stylesheet"===a.rel&&a.hasAttribute(y)?a.__resource:f.call(this,a)}}})}a.ShadowCSS=k}(window.Platform)):!function(){window.templateContent=window.templateContent||function(a){return a.content},window.wrap=window.unwrap=function(a){return a},addEventListener("DOMContentLoaded",function(){if(CustomElements.useNative===!1){var a=Element.prototype.createShadowRoot;Element.prototype.createShadowRoot=function(){var b=a.call(this);return CustomElements.watchShadow(this),b}}}),window.templateContent=function(a){if(window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(a),!a.content&&!a._content){for(var b=document.createDocumentFragment();a.firstChild;)b.appendChild(a.firstChild);a._content=b}return a.content||a._content}}(),function(a){"use strict";function b(a){return void 0!==m[a]}function c(){h.call(this),this._isInvalid=!0}function d(a){return""==a&&c.call(this),a.toLowerCase()}function e(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,63,96].indexOf(b)?a:encodeURIComponent(a)}function f(a){var b=a.charCodeAt(0);return b>32&&127>b&&-1==[34,35,60,62,96].indexOf(b)?a:encodeURIComponent(a)}function g(a,g,h){function i(a){t.push(a)}var j=g||"scheme start",k=0,l="",r=!1,s=!1,t=[];a:for(;(a[k-1]!=o||0==k)&&!this._isInvalid;){var u=a[k];switch(j){case"scheme start":if(!u||!p.test(u)){if(g){i("Invalid scheme.");break a}l="",j="no scheme";continue}l+=u.toLowerCase(),j="scheme";break;case"scheme":if(u&&q.test(u))l+=u.toLowerCase();else{if(":"!=u){if(g){if(o==u)break a;i("Code point not allowed in scheme: "+u);break a}l="",k=0,j="no scheme";continue}if(this._scheme=l,l="",g)break a;b(this._scheme)&&(this._isRelative=!0),j="file"==this._scheme?"relative":this._isRelative&&h&&h._scheme==this._scheme?"relative or authority":this._isRelative?"authority first slash":"scheme data"}break;case"scheme data":"?"==u?(query="?",j="query"):"#"==u?(this._fragment="#",j="fragment"):o!=u&&" "!=u&&"\n"!=u&&"\r"!=u&&(this._schemeData+=e(u));break;case"no scheme":if(h&&b(h._scheme)){j="relative";continue}i("Missing scheme."),c.call(this);break;case"relative or authority":if("/"!=u||"/"!=a[k+1]){i("Expected /, got: "+u),j="relative";continue}j="authority ignore slashes";break;case"relative":if(this._isRelative=!0,"file"!=this._scheme&&(this._scheme=h._scheme),o==u){this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query;break a}if("/"==u||"\\"==u)"\\"==u&&i("\\ is an invalid code point."),j="relative slash";else if("?"==u)this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query="?",j="query";else{if("#"!=u){var v=a[k+1],w=a[k+2];("file"!=this._scheme||!p.test(u)||":"!=v&&"|"!=v||o!=w&&"/"!=w&&"\\"!=w&&"?"!=w&&"#"!=w)&&(this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._path.pop()),j="relative path";continue}this._host=h._host,this._port=h._port,this._path=h._path.slice(),this._query=h._query,this._fragment="#",j="fragment"}break;case"relative slash":if("/"!=u&&"\\"!=u){"file"!=this._scheme&&(this._host=h._host,this._port=h._port),j="relative path";continue}"\\"==u&&i("\\ is an invalid code point."),j="file"==this._scheme?"file host":"authority ignore slashes";break;case"authority first slash":if("/"!=u){i("Expected '/', got: "+u),j="authority ignore slashes";continue}j="authority second slash";break;case"authority second slash":if(j="authority ignore slashes","/"!=u){i("Expected '/', got: "+u);continue}break;case"authority ignore slashes":if("/"!=u&&"\\"!=u){j="authority";continue}i("Expected authority, got: "+u);break;case"authority":if("@"==u){r&&(i("@ already seen."),l+="%40"),r=!0;for(var x=0;x<l.length;x++){var y=l[x];if(" "!=y&&"\n"!=y&&"\r"!=y)if(":"!=y||null!==this._password){var z=e(y);null!==this._password?this._password+=z:this._username+=z}else this._password="";else i("Invalid whitespace in authority.")}l=""}else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){k-=l.length,l="",j="host";continue}l+=u}break;case"file host":if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){2!=l.length||!p.test(l[0])||":"!=l[1]&&"|"!=l[1]?0==l.length?j="relative path start":(this._host=d.call(this,l),l="",j="relative path start"):j="relative path";continue}"  "==u||"\n"==u||"\r"==u?i("Invalid whitespace in file host."):l+=u;break;case"host":case"hostname":if(":"!=u||s){if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u){if(this._host=d.call(this,l),l="",j="relative path start",g)break a;continue}"  "!=u&&"\n"!=u&&"\r"!=u?("["==u?s=!0:"]"==u&&(s=!1),l+=u):i("Invalid code point in host/hostname: "+u)}else if(this._host=d.call(this,l),l="",j="port","hostname"==g)break a;break;case"port":if(/[0-9]/.test(u))l+=u;else{if(o==u||"/"==u||"\\"==u||"?"==u||"#"==u||g){if(""!=l){var A=parseInt(l,10);A!=m[this._scheme]&&(this._port=A+""),l=""}if(g)break a;j="relative path start";continue}"  "==u||"\n"==u||"\r"==u?i("Invalid code point in port: "+u):c.call(this)}break;case"relative path start":if("\\"==u&&i("'\\' not allowed in path."),j="relative path","/"!=u&&"\\"!=u)continue;break;case"relative path":if(o!=u&&"/"!=u&&"\\"!=u&&(g||"?"!=u&&"#"!=u))" "!=u&&"\n"!=u&&"\r"!=u&&(l+=e(u));else{"\\"==u&&i("\\ not allowed in relative path.");var B;(B=n[l.toLowerCase()])&&(l=B),".."==l?(this._path.pop(),"/"!=u&&"\\"!=u&&this._path.push("")):"."==l&&"/"!=u&&"\\"!=u?this._path.push(""):"."!=l&&("file"==this._scheme&&0==this._path.length&&2==l.length&&p.test(l[0])&&"|"==l[1]&&(l=l[0]+":"),this._path.push(l)),l="","?"==u?(this._query="?",j="query"):"#"==u&&(this._fragment="#",j="fragment")}break;case"query":g||"#"!=u?o!=u&&" "!=u&&"\n"!=u&&"\r"!=u&&(this._query+=f(u)):(this._fragment="#",j="fragment");break;case"fragment":o!=u&&"  "!=u&&"\n"!=u&&"\r"!=u&&(this._fragment+=u)}k++}}function h(){this._scheme="",this._schemeData="",this._username="",this._password=null,this._host="",this._port="",this._path=[],this._query="",this._fragment="",this._isInvalid=!1,this._isRelative=!1}function i(a,b){void 0===b||b instanceof i||(b=new i(String(b))),this._url=a,h.call(this);var c=a.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g,"");g.call(this,c,null,b)}var j=!1;if(!a.forceJURL)try{var k=new URL("b","http://a");j="http://a/b"===k.href}catch(l){}if(!j){var m=Object.create(null);m.ftp=21,m.file=0,m.gopher=70,m.http=80,m.https=443,m.ws=80,m.wss=443;var n=Object.create(null);n["%2e"]=".",n[".%2e"]="..",n["%2e."]="..",n["%2e%2e"]="..";var o=void 0,p=/[a-zA-Z]/,q=/[a-zA-Z0-9\+\-\.]/;i.prototype={get href(){if(this._isInvalid)return this._url;var a="";return(""!=this._username||null!=this._password)&&(a=this._username+(null!=this._password?":"+this._password:"")+"@"),this.protocol+(this._isRelative?"//"+a+this.host:"")+this.pathname+this._query+this._fragment},set href(a){h.call(this),g.call(this,a)},get protocol(){return this._scheme+":"},set protocol(a){this._isInvalid||g.call(this,a+":","scheme start")},get host(){return this._isInvalid?"":this._port?this._host+":"+this._port:this._host},set host(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"host")},get hostname(){return this._host},set hostname(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"hostname")},get port(){return this._port},set port(a){!this._isInvalid&&this._isRelative&&g.call(this,a,"port")},get pathname(){return this._isInvalid?"":this._isRelative?"/"+this._path.join("/"):this._schemeData},set pathname(a){!this._isInvalid&&this._isRelative&&(this._path=[],g.call(this,a,"relative path start"))},get search(){return this._isInvalid||!this._query||"?"==this._query?"":this._query},set search(a){!this._isInvalid&&this._isRelative&&(this._query="?","?"==a[0]&&(a=a.slice(1)),g.call(this,a,"query"))},get hash(){return this._isInvalid||!this._fragment||"#"==this._fragment?"":this._fragment
+},set hash(a){this._isInvalid||(this._fragment="#","#"==a[0]&&(a=a.slice(1)),g.call(this,a,"fragment"))}},a.URL=i}}(window),function(a){function b(a){for(var b=a||{},d=1;d<arguments.length;d++){var e=arguments[d];try{for(var f in e)c(f,e,b)}catch(g){}}return b}function c(a,b,c){var e=d(b,a);Object.defineProperty(c,a,e)}function d(a,b){if(a){var c=Object.getOwnPropertyDescriptor(a,b);return c||d(Object.getPrototypeOf(a),b)}}Function.prototype.bind||(Function.prototype.bind=function(a){var b=this,c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();return d.push.apply(d,arguments),b.apply(a,d)}}),a.mixin=b}(window.Platform),function(a){"use strict";function b(a,b,c){var d="string"==typeof a?document.createElement(a):a.cloneNode(!0);if(d.innerHTML=b,c)for(var e in c)d.setAttribute(e,c[e]);return d}var c=DOMTokenList.prototype.add,d=DOMTokenList.prototype.remove;DOMTokenList.prototype.add=function(){for(var a=0;a<arguments.length;a++)c.call(this,arguments[a])},DOMTokenList.prototype.remove=function(){for(var a=0;a<arguments.length;a++)d.call(this,arguments[a])},DOMTokenList.prototype.toggle=function(a,b){1==arguments.length&&(b=!this.contains(a)),b?this.add(a):this.remove(a)},DOMTokenList.prototype.switch=function(a,b){a&&this.remove(a),b&&this.add(b)};var e=function(){return Array.prototype.slice.call(this)},f=window.NamedNodeMap||window.MozNamedAttrMap||{};if(NodeList.prototype.array=e,f.prototype.array=e,HTMLCollection.prototype.array=e,!window.performance){var g=Date.now();window.performance={now:function(){return Date.now()-g}}}window.requestAnimationFrame||(window.requestAnimationFrame=function(){var a=window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame;return a?function(b){return a(function(){b(performance.now())})}:function(a){return window.setTimeout(a,1e3/60)}}()),window.cancelAnimationFrame||(window.cancelAnimationFrame=function(){return window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||function(a){clearTimeout(a)}}());var h=[],i=function(){h.push(arguments)};window.Polymer=i,a.deliverDeclarations=function(){return a.deliverDeclarations=function(){throw"Possible attempt to load Polymer twice"},h},window.addEventListener("DOMContentLoaded",function(){window.Polymer===i&&(window.Polymer=function(){console.error('You tried to use polymer without loading it first. To load polymer, <link rel="import" href="components/polymer/polymer.html">')})}),a.createDOM=b}(window.Platform),window.templateContent=window.templateContent||function(a){return a.content},function(a){a=a||(window.Inspector={});var b;window.sinspect=function(a,d){b||(b=window.open("","ShadowDOM Inspector",null,!0),b.document.write(c),b.api={shadowize:shadowize}),f(a||wrap(document.body),d)};var c=["<!DOCTYPE html>","<html>","  <head>","    <title>ShadowDOM Inspector</title>","    <style>","      body {","      }","      pre {",'        font: 9pt "Courier New", monospace;',"        line-height: 1.5em;","      }","      tag {","        color: purple;","      }","      ul {","         margin: 0;","         padding: 0;","         list-style: none;","      }","      li {","         display: inline-block;","         background-color: #f1f1f1;","         padding: 4px 6px;","         border-radius: 4px;","         margin-right: 4px;","      }","    </style>","  </head>","  <body>",'    <ul id="crumbs">',"    </ul>",'    <div id="tree"></div>',"  </body>","</html>"].join("\n"),d=[],e=function(){var a=b.document,c=a.querySelector("#crumbs");c.textContent="";for(var e,g=0;e=d[g];g++){var h=a.createElement("a");h.href="#",h.textContent=e.localName,h.idx=g,h.onclick=function(a){for(var b;d.length>this.idx;)b=d.pop();f(b.shadow||b,b),a.preventDefault()},c.appendChild(a.createElement("li")).appendChild(h)}},f=function(a,c){var f=b.document;k=[];var g=c||a;d.push(g),e(),f.body.querySelector("#tree").innerHTML="<pre>"+j(a,a.childNodes)+"</pre>"},g=Array.prototype.forEach.call.bind(Array.prototype.forEach),h={STYLE:1,SCRIPT:1,"#comment":1,TEMPLATE:1},i=function(a){return h[a.nodeName]},j=function(a,b,c){if(i(a))return"";var d=c||"";if(a.localName||11==a.nodeType){var e=a.localName||"shadow-root",f=d+l(a);"content"==e&&(b=a.getDistributedNodes()),f+="<br/>";var h=d+"&nbsp;&nbsp;";g(b,function(a){f+=j(a,a.childNodes,h)}),f+=d,{br:1}[e]||(f+="<tag>&lt;/"+e+"&gt;</tag>",f+="<br/>")}else{var k=a.textContent.trim();f=k?d+'"'+k+'"<br/>':""}return f},k=[],l=function(a){var b="<tag>&lt;",c=a.localName||"shadow-root";return a.webkitShadowRoot||a.shadowRoot?(b+=' <button idx="'+k.length+'" onclick="api.shadowize.call(this)">'+c+"</button>",k.push(a)):b+=c||"shadow-root",a.attributes&&g(a.attributes,function(a){b+=" "+a.name+(a.value?'="'+a.value+'"':"")}),b+="&gt;</tag>"};shadowize=function(){var a=Number(this.attributes.idx.value),b=k[a];b?f(b.webkitShadowRoot||b.shadowRoot,b):(console.log("bad shadowize node"),console.dir(this))},a.output=j}(window.Inspector),function(){var a=document.createElement("style");a.textContent="body {transition: opacity ease-in 0.2s; } \nbody[unresolved] {opacity: 0; display: block; overflow: hidden; } \n";var b=document.querySelector("head");b.insertBefore(a,b.firstChild)}(Platform),function(a){function b(a,b){return b=b||[],b.map||(b=[b]),a.apply(this,b.map(d))}function c(a,c,d){var e;switch(arguments.length){case 0:return;case 1:e=null;break;case 2:e=c.apply(this);break;default:e=b(d,c)}f[a]=e}function d(a){return f[a]}function e(a,c){HTMLImports.whenImportsReady(function(){b(c,a)})}var f={};a.marshal=d,a.module=c,a.using=e}(window),function(a){function b(a){f.textContent=d++,e.push(a)}function c(){for(;e.length;)e.shift()()}var d=0,e=[],f=document.createTextNode("");new(window.MutationObserver||JsMutationObserver)(c).observe(f,{characterData:!0}),a.endOfMicrotask=b}(Platform),function(a){function b(a,b,d){return a.replace(d,function(a,d,e,f){var g=e.replace(/["']/g,"");return g=c(b,g),d+"'"+g+"'"+f})}function c(a,b){var c=new URL(b,a);return d(c.href)}function d(a){var b=document.baseURI,c=new URL(a,b);return c.host===b.host&&c.port===b.port&&c.protocol===b.protocol?e(b.pathname,c.pathname):a}function e(a,b){for(var c=a.split("/"),d=b.split("/");c.length&&c[0]===d[0];)c.shift(),d.shift();for(var e=0,f=c.length-1;f>e;e++)d.unshift("..");return d.join("/")}var f={resolveDom:function(a,b){b=b||a.ownerDocument.baseURI,this.resolveAttributes(a,b),this.resolveStyles(a,b);var c=a.querySelectorAll("template");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)d.content&&this.resolveDom(d.content,b)},resolveTemplate:function(a){this.resolveDom(a.content,a.ownerDocument.baseURI)},resolveStyles:function(a,b){var c=a.querySelectorAll("style");if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveStyle(d,b)},resolveStyle:function(a,b){b=b||a.ownerDocument.baseURI,a.textContent=this.resolveCssText(a.textContent,b)},resolveCssText:function(a,c){return a=b(a,c,g),b(a,c,h)},resolveAttributes:function(a,b){a.hasAttributes&&a.hasAttributes()&&this.resolveElementAttributes(a,b);var c=a&&a.querySelectorAll(j);if(c)for(var d,e=0,f=c.length;f>e&&(d=c[e]);e++)this.resolveElementAttributes(d,b)},resolveElementAttributes:function(a,b){b=b||a.ownerDocument.baseURI,i.forEach(function(d){var e=a.attributes[d];if(e&&e.value&&e.value.search(k)<0){var f=c(b,e.value);e.value=f}})}},g=/(url\()([^)]*)(\))/g,h=/(@import[\s]+(?!url\())([^;]*)(;)/g,i=["href","src","action"],j="["+i.join("],[")+"]",k="{{.*}}";a.urlResolver=f}(Platform),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new WeakMap,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return void(c[d-1]=f)}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g,a.MutationObserver||(a.MutationObserver=g)}(this),window.HTMLImports=window.HTMLImports||{flags:{}},function(a){var b=(a.path,a.xhr),c=a.flags,d=function(a,b){this.cache={},this.onload=a,this.oncomplete=b,this.inflight=0,this.pending={}};d.prototype={addNodes:function(a){this.inflight+=a.length;for(var b,c=0,d=a.length;d>c&&(b=a[c]);c++)this.require(b);this.checkDone()},addNode:function(a){this.inflight++,this.require(a),this.checkDone()},require:function(a){var b=a.src||a.href;a.__nodeUrl=b,this.dedupe(b,a)||this.fetch(b,a)},dedupe:function(a,b){if(this.pending[a])return this.pending[a].push(b),!0;return this.cache[a]?(this.onload(a,b,this.cache[a]),this.tail(),!0):(this.pending[a]=[b],!1)},fetch:function(a,d){if(c.load&&console.log("fetch",a,d),a.match(/^data:/)){var e=a.split(","),f=e[0],g=e[1];g=f.indexOf(";base64")>-1?atob(g):decodeURIComponent(g),setTimeout(function(){this.receive(a,d,null,g)}.bind(this),0)}else{var h=function(b,c){this.receive(a,d,b,c)}.bind(this);b.load(a,h)}},receive:function(a,b,c,d){this.cache[a]=d;for(var e,f=this.pending[a],g=0,h=f.length;h>g&&(e=f[g]);g++)this.onload(a,e,d),this.tail();this.pending[a]=null},tail:function(){--this.inflight,this.checkDone()},checkDone:function(){this.inflight||this.oncomplete()}},b=b||{async:!0,ok:function(a){return a.status>=200&&a.status<300||304===a.status||0===a.status},load:function(c,d,e){var f=new XMLHttpRequest;return(a.flags.debug||a.flags.bust)&&(c+="?"+Math.random()),f.open("GET",c,b.async),f.addEventListener("readystatechange",function(){4===f.readyState&&d.call(e,!b.ok(f)&&f,f.response||f.responseText,c)}),f.send(),f},loadDocument:function(a,b,c){this.load(a,b,c).responseType="document"}},a.xhr=b,a.Loader=d}(window.HTMLImports),function(a){function b(a){return"link"===a.localName&&a.rel===g}function c(a){var b,c=d(a);try{b=btoa(c)}catch(e){b=btoa(unescape(encodeURIComponent(c))),console.warn("Script contained non-latin characters that were forced to latin. Some characters may be wrong.",a)}return"data:text/javascript;base64,"+b}function d(a){return a.textContent+e(a)}function e(a){var b=a.__nodeUrl;if(!b){b=a.ownerDocument.baseURI;var c="["+Math.floor(1e3*(Math.random()+1))+"]",d=a.textContent.match(/Polymer\(['"]([^'"]*)/);c=d&&d[1]||c,b+="/"+c+".js"}return"\n//# sourceURL="+b+"\n"}function f(a){var b=a.ownerDocument.createElement("style");return b.textContent=a.textContent,n.resolveUrlsInStyle(b),b}var g="import",h=a.flags,i=/Trident/.test(navigator.userAgent),j=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document,k={documentSelectors:"link[rel="+g+"]",importsSelectors:["link[rel="+g+"]","link[rel=stylesheet]","style","script:not([type])",'script[type="text/javascript"]'].join(","),map:{link:"parseLink",script:"parseScript",style:"parseStyle"},parseNext:function(){var a=this.nextToParse();a&&this.parse(a)},parse:function(a){if(this.isParsed(a))return void(h.parse&&console.log("[%s] is already parsed",a.localName));var b=this[this.map[a.localName]];b&&(this.markParsing(a),b.call(this,a))},markParsing:function(a){h.parse&&console.log("parsing",a),this.parsingElement=a},markParsingComplete:function(a){a.__importParsed=!0,a.__importElement&&(a.__importElement.__importParsed=!0),this.parsingElement=null,h.parse&&console.log("completed",a),this.parseNext()},parseImport:function(a){if(a.import.__importParsed=!0,HTMLImports.__importsParsingHook&&HTMLImports.__importsParsingHook(a),a.dispatchEvent(a.__resource?new CustomEvent("load",{bubbles:!1}):new CustomEvent("error",{bubbles:!1})),a.__pending)for(var b;a.__pending.length;)b=a.__pending.shift(),b&&b({target:a});this.markParsingComplete(a)},parseLink:function(a){b(a)?this.parseImport(a):(a.href=a.href,this.parseGeneric(a))},parseStyle:function(a){var b=a;a=f(a),a.__importElement=b,this.parseGeneric(a)},parseGeneric:function(a){this.trackElement(a),document.head.appendChild(a)},trackElement:function(a,b){var c=this,d=function(d){b&&b(d),c.markParsingComplete(a)};if(a.addEventListener("load",d),a.addEventListener("error",d),i&&"style"===a.localName){var e=!1;if(-1==a.textContent.indexOf("@import"))e=!0;else if(a.sheet){e=!0;for(var f,g=a.sheet.cssRules,h=g?g.length:0,j=0;h>j&&(f=g[j]);j++)f.type===CSSRule.IMPORT_RULE&&(e=e&&Boolean(f.styleSheet))}e&&a.dispatchEvent(new CustomEvent("load",{bubbles:!1}))}},parseScript:function(b){var d=document.createElement("script");d.__importElement=b,d.src=b.src?b.src:c(b),a.currentScript=b,this.trackElement(d,function(){d.parentNode.removeChild(d),a.currentScript=null}),document.head.appendChild(d)},nextToParse:function(){return!this.parsingElement&&this.nextToParseInDoc(j)},nextToParseInDoc:function(a,c){for(var d,e=a.querySelectorAll(this.parseSelectorsForNode(a)),f=0,g=e.length;g>f&&(d=e[f]);f++)if(!this.isParsed(d))return this.hasResource(d)?b(d)?this.nextToParseInDoc(d.import,d):d:void 0;return c},parseSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===j?this.documentSelectors:this.importsSelectors},isParsed:function(a){return a.__importParsed},hasResource:function(a){return b(a)&&!a.import?!1:!0}},l=/(url\()([^)]*)(\))/g,m=/(@import[\s]+(?!url\())([^;]*)(;)/g,n={resolveUrlsInStyle:function(a){var b=a.ownerDocument,c=b.createElement("a");return a.textContent=this.resolveUrlsInCssText(a.textContent,c),a},resolveUrlsInCssText:function(a,b){var c=this.replaceUrls(a,b,l);return c=this.replaceUrls(c,b,m)},replaceUrls:function(a,b,c){return a.replace(c,function(a,c,d,e){var f=d.replace(/["']/g,"");return b.href=f,f=b.href,c+"'"+f+"'"+e})}};a.parser=k,a.path=n,a.isIE=i}(HTMLImports),function(a){function b(a){return c(a,m)}function c(a,b){return"link"===a.localName&&a.getAttribute("rel")===b}function d(a,b){var c=a;c instanceof Document||(c=document.implementation.createHTMLDocument(m)),c._URL=b;var d=c.createElement("base");d.setAttribute("href",b),c.baseURI||(c.baseURI=b);var e=c.createElement("meta");return e.setAttribute("charset","utf-8"),c.head.appendChild(e),c.head.appendChild(d),a instanceof Document||(c.body.innerHTML=a),window.HTMLTemplateElement&&HTMLTemplateElement.bootstrap&&HTMLTemplateElement.bootstrap(c),c}function e(a,b){b=b||n,g(function(){h(a,b)},b)}function f(a){return"complete"===a.readyState||a.readyState===u}function g(a,b){if(f(b))a&&a();else{var c=function(){("complete"===b.readyState||b.readyState===u)&&(b.removeEventListener(v,c),g(a,b))};b.addEventListener(v,c)}}function h(a,b){function c(){f==g&&requestAnimationFrame(a)}function d(){f++,c()}var e=b.querySelectorAll("link[rel=import]"),f=0,g=e.length;if(g)for(var h,j=0;g>j&&(h=e[j]);j++)i(h)?d.call(h):(h.addEventListener("load",d),h.addEventListener("error",d));else c()}function i(a){return k?a.import&&"loading"!==a.import.readyState:a.__importParsed}var j="import"in document.createElement("link"),k=j,l=a.flags,m="import",n=window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(document):document;if(k)var o={};else var p=(a.xhr,a.Loader),q=a.parser,o={documents:{},documentPreloadSelectors:"link[rel="+m+"]",importsPreloadSelectors:["link[rel="+m+"]"].join(","),loadNode:function(a){r.addNode(a)},loadSubtree:function(a){var b=this.marshalNodes(a);r.addNodes(b)},marshalNodes:function(a){return a.querySelectorAll(this.loadSelectorsForNode(a))},loadSelectorsForNode:function(a){var b=a.ownerDocument||a;return b===n?this.documentPreloadSelectors:this.importsPreloadSelectors},loaded:function(a,c,e){if(l.load&&console.log("loaded",a,c),c.__resource=e,b(c)){var f=this.documents[a];f||(f=d(e,a),f.__importLink=c,this.bootDocument(f),this.documents[a]=f),c.import=f}q.parseNext()},bootDocument:function(a){this.loadSubtree(a),this.observe(a),q.parseNext()},loadedAll:function(){q.parseNext()}},r=new p(o.loaded.bind(o),o.loadedAll.bind(o));var s={get:function(){return HTMLImports.currentScript||document.currentScript},configurable:!0};if(Object.defineProperty(document,"_currentScript",s),Object.defineProperty(n,"_currentScript",s),!document.baseURI){var t={get:function(){return window.location.href},configurable:!0};Object.defineProperty(document,"baseURI",t),Object.defineProperty(n,"baseURI",t)}var u=HTMLImports.isIE?"complete":"interactive",v="readystatechange";a.hasNative=j,a.useNative=k,a.importer=o,a.whenImportsReady=e,a.IMPORT_LINK_TYPE=m,a.isImportLoaded=i,a.importLoader=r}(window.HTMLImports),function(a){function b(a){for(var b,d=0,e=a.length;e>d&&(b=a[d]);d++)"childList"===b.type&&b.addedNodes.length&&c(b.addedNodes)}function c(a){for(var b,e=0,g=a.length;g>e&&(b=a[e]);e++)d(b)&&f.loadNode(b),b.children&&b.children.length&&c(b.children)}function d(a){return 1===a.nodeType&&g.call(a,f.loadSelectorsForNode(a))}function e(a){h.observe(a,{childList:!0,subtree:!0})}var f=(a.IMPORT_LINK_TYPE,a.importer),g=HTMLElement.prototype.matches||HTMLElement.prototype.matchesSelector||HTMLElement.prototype.webkitMatchesSelector||HTMLElement.prototype.mozMatchesSelector||HTMLElement.prototype.msMatchesSelector,h=new MutationObserver(b);a.observe=e,f.observe=e}(HTMLImports),function(){function a(){HTMLImports.importer.bootDocument(b)}"function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a,b){var c=document.createEvent("HTMLEvents");return c.initEvent(a,b.bubbles===!1?!1:!0,b.cancelable===!1?!1:!0,b.detail),c});var b=window.ShadowDOMPolyfill?window.ShadowDOMPolyfill.wrapIfNeeded(document):document;HTMLImports.whenImportsReady(function(){HTMLImports.ready=!0,HTMLImports.readyTime=(new Date).getTime(),b.dispatchEvent(new CustomEvent("HTMLImportsLoaded",{bubbles:!0}))}),HTMLImports.useNative||("complete"===document.readyState||"interactive"===document.readyState&&!window.attachEvent?a():document.addEventListener("DOMContentLoaded",a))}(),window.CustomElements=window.CustomElements||{flags:{}},function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:void c(a,d)}),c(a,d)}function e(a){return h(a)?(i(a),!0):void l(a)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return A.dom&&console.group("upgrade:",b.localName),a.upgrade(b),A.dom&&console.groupEnd(),!0}}function i(a){l(a),r(a)&&d(a,function(a){l(a)})}function j(a){if(E.push(a),!D){D=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){D=!1;for(var a,b=E,c=0,d=b.length;d>c&&(a=b[c]);c++)a();E=[]}function l(a){C?j(function(){m(a)}):m(a)}function m(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("inserted:",a.localName),r(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?A.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.attachedCallback&&(A.dom&&console.log("inserted:",a.localName),a.attachedCallback())),A.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){C?j(function(){p(a)}):p(a)}function p(a){(a.attachedCallback||a.detachedCallback||a.__upgraded__&&A.dom)&&(A.dom&&console.group("removed:",a.localName),r(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?A.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.detachedCallback&&a.detachedCallback()),A.dom&&console.groupEnd())}function q(a){return window.ShadowDOMPolyfill?ShadowDOMPolyfill.wrapIfNeeded(a):a}function r(a){for(var b=a,c=q(document);b;){if(b==c)return!0;b=b.parentNode||b.host}}function s(a){if(a.shadowRoot&&!a.shadowRoot.__watched){A.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)t(b),b=b.olderShadowRoot}}function t(a){a.__watched||(w(a),a.__watched=!0)}function u(a){if(A.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(G(a.addedNodes,function(a){a.localName&&g(a)}),G(a.removedNodes,function(a){a.localName&&n(a)}))}),A.dom&&console.groupEnd()}function v(){u(F.takeRecords()),k()}function w(a){F.observe(a,{childList:!0,subtree:!0})}function x(a){w(a)}function y(a){A.dom&&console.group("upgradeDocument: ",a.baseURI.split("/").pop()),g(a),A.dom&&console.groupEnd()}function z(a){a=q(a);for(var b,c=a.querySelectorAll("link[rel="+B+"]"),d=0,e=c.length;e>d&&(b=c[d]);d++)b.import&&b.import.__parsed&&z(b.import);y(a)}var A=window.logFlags||{},B=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",C=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=C;var D=!1,E=[],F=new MutationObserver(u),G=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.IMPORT_LINK_TYPE=B,a.watchShadow=s,a.upgradeDocumentTree=z,a.upgradeAll=g,a.upgradeSubtree=f,a.insertedNode=i,a.observeDocument=x,a.upgradeDocument=y,a.takeRecords=v}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.registerElement: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.registerElement: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(m(b))throw new Error("DuplicateDefinitionError: a type with name '"+String(b)+"' is already registered");if(!g.prototype)throw new Error("Options missing required prototype property");return g.__name=b.toLowerCase(),g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),n(g.__name,g),g.ctor=o(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeDocumentTree(document),g.ctor}function c(a){var b=m(a);return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.__name,c&&(a.is=a.__name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(z(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),b.removeAttribute("unresolved"),h(b,c),b.__upgraded__=!0,j(b),a.insertedNode(b),a.upgradeSubtree(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){if(!a.setAttribute._polyfilled){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)},a.setAttribute._polyfilled=!0}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments);var e=this.getAttribute(a);this.attributeChangedCallback&&e!==d&&this.attributeChangedCallback(a,d,e)}function m(a){return a?x[a.toLowerCase()]:void 0}function n(a,b){x[a]=b}function o(a){return function(){return f(a)}}function p(a,b,c){return a===y?q(b,c):A(a,b)}function q(a,b){var c=m(b||a);if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=q(a);return d.setAttribute("is",b),d}var d=z(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function r(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=m(b||a.localName);if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function s(b){var c=B.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var t=a.flags,u=Boolean(document.registerElement),v=!t.register&&u&&!window.ShadowDOMPolyfill;if(v){var w=function(){};a.registry={},a.upgradeElement=w,a.watchShadow=w,a.upgrade=w,a.upgradeAll=w,a.upgradeSubtree=w,a.observeDocument=w,a.upgradeDocument=w,a.upgradeDocumentTree=w,a.takeRecords=w}else{var x={},y="http://www.w3.org/1999/xhtml",z=document.createElement.bind(document),A=document.createElementNS.bind(document),B=Node.prototype.cloneNode;document.registerElement=b,document.createElement=q,document.createElementNS=p,Node.prototype.cloneNode=s,a.registry=x,a.upgrade=r}var C;C=Object.__proto__||v?function(a,b){return a instanceof b}:function(a,b){for(var c=a;c;){if(c===b.prototype)return!0;c=c.__proto__}return!1},a.instanceof=C,document.register=document.registerElement,a.hasNative=u,a.useNative=v}(window.CustomElements),function(a){function b(a){return"link"===a.localName&&a.getAttribute("rel")===c}var c=a.IMPORT_LINK_TYPE,d={selectors:["link[rel="+c+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(d.selectors);e(b,function(a){d[d.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(a){b(a)&&this.parseImport(a)},parseImport:function(a){a.import&&d.parse(a.import)}},e=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.parser=d,a.IMPORT_LINK_TYPE=c}(window.CustomElements),function(a){function b(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0})),window.HTMLImports&&(HTMLImports.__importsParsingHook=function(a){CustomElements.parser.parse(a.import)})})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState||a.flags.eager)b();else if("interactive"!==document.readyState||window.attachEvent||window.HTMLImports&&!window.HTMLImports.ready){var c=window.HTMLImports&&!HTMLImports.ready?"HTMLImportsLoaded":"DOMContentLoaded";window.addEventListener(c,b)}else b()}(window.CustomElements),function(){if(window.ShadowDOMPolyfill){var a=["upgradeAll","upgradeSubtree","observeDocument","upgradeDocument"],b={};a.forEach(function(a){b[a]=CustomElements[a]}),a.forEach(function(a){CustomElements[a]=function(c){return b[a](wrap(c))}})}}(),function(a){function b(a){this.regex=a}var c=a.endOfMicrotask;b.prototype={extractUrls:function(a,b){for(var c,d,e=[];c=this.regex.exec(a);)d=new URL(c[1],b),e.push({matched:c[0],url:d.href});return e},process:function(a,b,c){var d=this.extractUrls(a,b);this.fetch(d,{},c)},fetch:function(a,b,d){var e=a.length;if(!e)return d(b);for(var f,g,h,i=function(){0===--e&&d(b)},j=function(a,c){var d=c.match,e=d.url;if(a)return b[e]="",i();var f=c.response||c.responseText;b[e]=f,this.fetch(this.extractUrls(f,e),b,i)},k=0;e>k;k++)f=a[k],h=f.url,b[h]?c(i):(g=this.xhr(h,j,this),g.match=f,b[h]=g)},xhr:function(a,b,c){var d=new XMLHttpRequest;return d.open("GET",a,!0),d.send(),d.onload=function(){b.call(c,null,d)},d.onerror=function(){b.call(c,null,d)},d}},a.Loader=b}(window.Platform),function(a){function b(){this.loader=new d(this.regex)}var c=a.urlResolver,d=a.Loader;b.prototype={regex:/@import\s+(?:url)?["'\(]*([^'"\)]*)['"\)]*;/g,resolve:function(a,b,c){var d=function(d){c(this.flatten(a,b,d))}.bind(this);this.loader.process(a,b,d)},resolveNode:function(a,b){var c=a.textContent,d=a.ownerDocument.baseURI,e=function(c){a.textContent=c,b(a)
+};this.resolve(c,d,e)},flatten:function(a,b,d){for(var e,f,g,h=this.loader.extractUrls(a,b),i=0;i<h.length;i++)e=h[i],f=e.url,g=c.resolveCssText(d[f],f),g=this.flatten(g,f,d),a=a.replace(e.matched,g);return a},loadStyles:function(a,b){function c(){e++,e===f&&b&&b()}for(var d,e=0,f=a.length,g=0;f>g&&(d=a[g]);g++)this.resolveNode(d,c)}};var e=new b;a.styleResolver=e}(window.Platform),function(a){a=a||{},a.external=a.external||{};var b={shadow:function(a){return a?a.shadowRoot||a.webkitShadowRoot:void 0},canTarget:function(a){return a&&Boolean(a.elementFromPoint)},targetingShadow:function(a){var b=this.shadow(a);return this.canTarget(b)?b:void 0},olderShadow:function(a){var b=a.olderShadowRoot;if(!b){var c=a.querySelector("shadow");c&&(b=c.olderShadowRoot)}return b},allShadows:function(a){for(var b=[],c=this.shadow(a);c;)b.push(c),c=this.olderShadow(c);return b},searchRoot:function(a,b,c){if(a){var d,e,f=a.elementFromPoint(b,c);for(e=this.targetingShadow(f);e;){if(d=e.elementFromPoint(b,c)){var g=this.targetingShadow(d);return this.searchRoot(g,b,c)||d}e=this.olderShadow(e)}return f}},owner:function(a){for(var b=a;b.parentNode;)b=b.parentNode;return b.nodeType!=Node.DOCUMENT_NODE&&b.nodeType!=Node.DOCUMENT_FRAGMENT_NODE&&(b=document),b},findTarget:function(a){var b=a.clientX,c=a.clientY,d=this.owner(a.target);return d.elementFromPoint(b,c)||(d=document),this.searchRoot(d,b,c)}};a.targetFinding=b,a.findTarget=b.findTarget.bind(b),window.PointerEventsPolyfill=a}(window.PointerEventsPolyfill),function(){function a(a){return"body /shadow-deep/ "+b(a)}function b(a){return'[touch-action="'+a+'"]'}function c(a){return"{ -ms-touch-action: "+a+"; touch-action: "+a+"; touch-action-delay: none; }"}var d=["none","auto","pan-x","pan-y",{rule:"pan-x pan-y",selectors:["pan-x pan-y","pan-y pan-x"]}],e="",f=(document.head,window.PointerEvent||window.MSPointerEvent),g=!window.ShadowDOMPolyfill&&document.head.createShadowRoot;if(f){d.forEach(function(d){String(d)===d?(e+=b(d)+c(d)+"\n",g&&(e+=a(d)+c(d)+"\n")):(e+=d.selectors.map(b)+c(d.rule)+"\n",g&&(e+=d.selectors.map(a)+c(d.rule)+"\n"))});var h=document.createElement("style");h.textContent=e,document.head.appendChild(h)}}(),function(a){function b(a,e){e=e||{};var f=e.buttons;if(!d&&!f&&"touch"!==a)switch(e.which){case 1:f=1;break;case 2:f=4;break;case 3:f=2;break;default:f=0}var i;if(c)i=new MouseEvent(a,e);else{i=document.createEvent("MouseEvent");for(var j,k={},l=0;l<g.length;l++)j=g[l],k[j]=e[j]||h[l];i.initMouseEvent(a,k.bubbles,k.cancelable,k.view,k.detail,k.screenX,k.screenY,k.clientX,k.clientY,k.ctrlKey,k.altKey,k.shiftKey,k.metaKey,k.button,k.relatedTarget)}i.__proto__=b.prototype,d||Object.defineProperty(i,"buttons",{get:function(){return f},enumerable:!0});var m=0;return m=e.pressure?e.pressure:f?.5:0,Object.defineProperties(i,{pointerId:{value:e.pointerId||0,enumerable:!0},width:{value:e.width||0,enumerable:!0},height:{value:e.height||0,enumerable:!0},pressure:{value:m,enumerable:!0},tiltX:{value:e.tiltX||0,enumerable:!0},tiltY:{value:e.tiltY||0,enumerable:!0},pointerType:{value:e.pointerType||"",enumerable:!0},hwTimestamp:{value:e.hwTimestamp||0,enumerable:!0},isPrimary:{value:e.isPrimary||!1,enumerable:!0}}),i}var c=!1,d=!1;try{var e=new MouseEvent("click",{buttons:1});c=!0,d=1===e.buttons,e=null}catch(f){}var g=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget"],h=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null];b.prototype=Object.create(MouseEvent.prototype),a.PointerEvent||(a.PointerEvent=b)}(window),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerEventsPolyfill),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","which"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0],d="undefined"!=typeof SVGElementInstance,e={targets:new WeakMap,handledEvents:new WeakMap,pointermap:new a.PointerMap,eventMap:{},eventSources:{},eventSourceList:[],registerSource:function(a,b){var c=b,d=c.events;d&&(d.forEach(function(a){c[a]&&(this.eventMap[a]=c[a].bind(c))},this),this.eventSources[a]=c,this.eventSourceList.push(c))},register:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.register.call(b,a)},unregister:function(a){for(var b,c=this.eventSourceList.length,d=0;c>d&&(b=this.eventSourceList[d]);d++)b.unregister.call(b,a)},contains:a.external.contains||function(a,b){return a.contains(b)},down:function(a){a.bubbles=!0,this.fireEvent("pointerdown",a)},move:function(a){a.bubbles=!0,this.fireEvent("pointermove",a)},up:function(a){a.bubbles=!0,this.fireEvent("pointerup",a)},enter:function(a){a.bubbles=!1,this.fireEvent("pointerenter",a)},leave:function(a){a.bubbles=!1,this.fireEvent("pointerleave",a)},over:function(a){a.bubbles=!0,this.fireEvent("pointerover",a)},out:function(a){a.bubbles=!0,this.fireEvent("pointerout",a)},cancel:function(a){a.bubbles=!0,this.fireEvent("pointercancel",a)},leaveOut:function(a){this.out(a),this.contains(a.target,a.relatedTarget)||this.leave(a)},enterOver:function(a){this.over(a),this.contains(a.target,a.relatedTarget)||this.enter(a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.eventMap&&this.eventMap[b];c&&c(a),this.handledEvents.set(a,!0)}},listen:function(a,b){b.forEach(function(b){this.addEvent(a,b)},this)},unlisten:function(a,b){b.forEach(function(b){this.removeEvent(a,b)},this)},addEvent:a.external.addEvent||function(a,b){a.addEventListener(b,this.boundHandler)},removeEvent:a.external.removeEvent||function(a,b){a.removeEventListener(b,this.boundHandler)},makeEvent:function(a,b){this.captureInfo&&(b.relatedTarget=null);var c=new PointerEvent(a,b);return b.preventDefault&&(c.preventDefault=b.preventDefault),this.targets.set(c,this.targets.get(b)||b.target),c},fireEvent:function(a,b){var c=this.makeEvent(a,b);return this.dispatchEvent(c)},cloneEvent:function(a){for(var e,f={},g=0;g<b.length;g++)e=b[g],f[e]=a[e]||c[g],!d||"target"!==e&&"relatedTarget"!==e||f[e]instanceof SVGElementInstance&&(f[e]=f[e].correspondingUseElement);return a.preventDefault&&(f.preventDefault=function(){a.preventDefault()}),f},getTarget:function(a){return this.captureInfo&&this.captureInfo.id===a.pointerId?this.captureInfo.target:this.targets.get(a)},setCapture:function(a,b){this.captureInfo&&this.releaseCapture(this.captureInfo.id),this.captureInfo={id:a,target:b};var c=new PointerEvent("gotpointercapture",{bubbles:!0});this.implicitRelease=this.releaseCapture.bind(this,a),document.addEventListener("pointerup",this.implicitRelease),document.addEventListener("pointercancel",this.implicitRelease),this.targets.set(c,b),this.asyncDispatchEvent(c)},releaseCapture:function(a){if(this.captureInfo&&this.captureInfo.id===a){var b=new PointerEvent("lostpointercapture",{bubbles:!0}),c=this.captureInfo.target;this.captureInfo=null,document.removeEventListener("pointerup",this.implicitRelease),document.removeEventListener("pointercancel",this.implicitRelease),this.targets.set(b,c),this.asyncDispatchEvent(b)}},dispatchEvent:a.external.dispatchEvent||function(a){var b=this.getTarget(a);return b?b.dispatchEvent(a):void 0},asyncDispatchEvent:function(a){requestAnimationFrame(this.dispatchEvent.bind(this,a))}};e.boundHandler=e.eventHandler.bind(e),a.dispatcher=e,a.register=e.register.bind(e),a.unregister=e.unregister.bind(e)}(window.PointerEventsPolyfill),function(a){function b(a,b,c,d){this.addCallback=a.bind(d),this.removeCallback=b.bind(d),this.changedCallback=c.bind(d),g&&(this.observer=new g(this.mutationWatcher.bind(this)))}var c=Array.prototype.forEach.call.bind(Array.prototype.forEach),d=Array.prototype.map.call.bind(Array.prototype.map),e=Array.prototype.slice.call.bind(Array.prototype.slice),f=Array.prototype.filter.call.bind(Array.prototype.filter),g=window.MutationObserver||window.WebKitMutationObserver,h="[touch-action]",i={subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0,attributeFilter:["touch-action"]};b.prototype={watchSubtree:function(b){a.targetFinding.canTarget(b)&&this.observer.observe(b,i)},enableOnSubtree:function(a){this.watchSubtree(a),a===document&&"complete"!==document.readyState?this.installOnLoad():this.installNewSubtree(a)},installNewSubtree:function(a){c(this.findElements(a),this.addElement,this)},findElements:function(a){return a.querySelectorAll?a.querySelectorAll(h):[]},removeElement:function(a){this.removeCallback(a)},addElement:function(a){this.addCallback(a)},elementChanged:function(a,b){this.changedCallback(a,b)},concatLists:function(a,b){return a.concat(e(b))},installOnLoad:function(){document.addEventListener("readystatechange",function(){"complete"===document.readyState&&this.installNewSubtree(document)}.bind(this))},isElement:function(a){return a.nodeType===Node.ELEMENT_NODE},flattenMutationTree:function(a){var b=d(a,this.findElements,this);return b.push(f(a,this.isElement)),b.reduce(this.concatLists,[])},mutationWatcher:function(a){a.forEach(this.mutationHandler,this)},mutationHandler:function(a){if("childList"===a.type){var b=this.flattenMutationTree(a.addedNodes);b.forEach(this.addElement,this);var c=this.flattenMutationTree(a.removedNodes);c.forEach(this.removeElement,this)}else"attributes"===a.type&&this.elementChanged(a.target,a.oldValue)}},g||(b.prototype.watchSubtree=function(){console.warn("PointerEventsPolyfill: MutationObservers not found, touch-action will not be dynamically detected")}),a.Installer=b}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=25,e={POINTER_ID:1,POINTER_TYPE:"mouse",events:["mousedown","mousemove","mouseup","mouseover","mouseout"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},lastTouches:[],isEventSimulatedFromTouch:function(a){for(var b,c=this.lastTouches,e=a.clientX,f=a.clientY,g=0,h=c.length;h>g&&(b=c[g]);g++){var i=Math.abs(e-b.x),j=Math.abs(f-b.y);if(d>=i&&d>=j)return!0}},prepareEvent:function(a){var c=b.cloneEvent(a),d=c.preventDefault;return c.preventDefault=function(){a.preventDefault(),d()},c.pointerId=this.POINTER_ID,c.isPrimary=!0,c.pointerType=this.POINTER_TYPE,c},mousedown:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.has(this.POINTER_ID);d&&this.cancel(a);var e=this.prepareEvent(a);c.set(this.POINTER_ID,a),b.down(e)}},mousemove:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.move(c)}},mouseup:function(a){if(!this.isEventSimulatedFromTouch(a)){var d=c.get(this.POINTER_ID);if(d&&d.button===a.button){var e=this.prepareEvent(a);b.up(e),this.cleanupMouse()}}},mouseover:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.enterOver(c)}},mouseout:function(a){if(!this.isEventSimulatedFromTouch(a)){var c=this.prepareEvent(a);b.leaveOut(c)}},cancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanupMouse()},cleanupMouse:function(){c["delete"](this.POINTER_ID)}};a.mouseEvents=e}(window.PointerEventsPolyfill),function(a){var b,c=a.dispatcher,d=a.findTarget,e=a.targetFinding.allShadows.bind(a.targetFinding),f=c.pointermap,g=Array.prototype.map.call.bind(Array.prototype.map),h=2500,i=200,j="touch-action",k=!1,l={scrollType:new WeakMap,events:["touchstart","touchmove","touchend","touchcancel"],register:function(a){k?c.listen(a,this.events):b.enableOnSubtree(a)},unregister:function(a){k&&c.unlisten(a,this.events)},elementAdded:function(a){var b=a.getAttribute(j),d=this.touchActionToScrollType(b);d&&(this.scrollType.set(a,d),c.listen(a,this.events),e(a).forEach(function(a){this.scrollType.set(a,d),c.listen(a,this.events)},this))},elementRemoved:function(a){this.scrollType["delete"](a),c.unlisten(a,this.events),e(a).forEach(function(a){this.scrollType["delete"](a),c.unlisten(a,this.events)},this)},elementChanged:function(a,b){var c=a.getAttribute(j),d=this.touchActionToScrollType(c),f=this.touchActionToScrollType(b);d&&f?(this.scrollType.set(a,d),e(a).forEach(function(a){this.scrollType.set(a,d)},this)):f?this.elementRemoved(a):d&&this.elementAdded(a)},scrollTypes:{EMITTER:"none",XSCROLLER:"pan-x",YSCROLLER:"pan-y",SCROLLER:/^(?:pan-x pan-y)|(?:pan-y pan-x)|auto$/},touchActionToScrollType:function(a){var b=a,c=this.scrollTypes;return"none"===b?"none":b===c.XSCROLLER?"X":b===c.YSCROLLER?"Y":c.SCROLLER.exec(b)?"XY":void 0},POINTER_TYPE:"touch",firstTouch:null,isPrimaryTouch:function(a){return this.firstTouch===a.identifier},setPrimaryTouch:function(a){(0===f.pointers()||1===f.pointers()&&f.has(1))&&(this.firstTouch=a.identifier,this.firstXY={X:a.clientX,Y:a.clientY},this.scrolling=!1,this.cancelResetClickCount())},removePrimaryPointer:function(a){a.isPrimary&&(this.firstTouch=null,this.firstXY=null,this.resetClickCount())},clickCount:0,resetId:null,resetClickCount:function(){var a=function(){this.clickCount=0,this.resetId=null}.bind(this);this.resetId=setTimeout(a,i)},cancelResetClickCount:function(){this.resetId&&clearTimeout(this.resetId)},typeToButtons:function(a){var b=0;return("touchstart"===a||"touchmove"===a)&&(b=1),b},touchToPointer:function(a){var b=c.cloneEvent(a);return b.pointerId=a.identifier+2,b.target=d(b),b.bubbles=!0,b.cancelable=!0,b.detail=this.clickCount,b.button=0,b.buttons=this.typeToButtons(this.currentTouchEvent),b.width=a.webkitRadiusX||a.radiusX||0,b.height=a.webkitRadiusY||a.radiusY||0,b.pressure=a.webkitForce||a.force||.5,b.isPrimary=this.isPrimaryTouch(a),b.pointerType=this.POINTER_TYPE,b},processTouches:function(a,b){var c=a.changedTouches;this.currentTouchEvent=a.type;var d=g(c,this.touchToPointer,this);d.forEach(function(b){b.preventDefault=function(){this.scrolling=!1,this.firstXY=null,a.preventDefault()}},this),d.forEach(b,this)},shouldScroll:function(a){if(this.firstXY){var b,c=this.scrollType.get(a.currentTarget);if("none"===c)b=!1;else if("XY"===c)b=!0;else{var d=a.changedTouches[0],e=c,f="Y"===c?"X":"Y",g=Math.abs(d["client"+e]-this.firstXY[e]),h=Math.abs(d["client"+f]-this.firstXY[f]);b=g>=h}return this.firstXY=null,b}},findTouch:function(a,b){for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)if(c.identifier===b)return!0},vacuumTouches:function(a){var b=a.touches;if(f.pointers()>=b.length){var c=[];f.forEach(function(a,d){if(1!==d&&!this.findTouch(b,d-2)){var e=a.out;c.push(this.touchToPointer(e))}},this),c.forEach(this.cancelOut,this)}},touchstart:function(a){this.vacuumTouches(a),this.setPrimaryTouch(a.changedTouches[0]),this.dedupSynthMouse(a),this.scrolling||(this.clickCount++,this.processTouches(a,this.overDown))},overDown:function(a){f.set(a.pointerId,{target:a.target,out:a,outTarget:a.target});c.over(a),c.enter(a),c.down(a)},touchmove:function(a){this.scrolling||(this.shouldScroll(a)?(this.scrolling=!0,this.touchcancel(a)):(a.preventDefault(),this.processTouches(a,this.moveOverOut)))},moveOverOut:function(a){var b=a,d=f.get(b.pointerId);if(d){var e=d.out,g=d.outTarget;c.move(b),e&&g!==b.target&&(e.relatedTarget=b.target,b.relatedTarget=g,e.target=g,b.target?(c.leaveOut(e),c.enterOver(b)):(b.target=g,b.relatedTarget=null,this.cancelOut(b))),d.out=b,d.outTarget=b.target}},touchend:function(a){this.dedupSynthMouse(a),this.processTouches(a,this.upOut)},upOut:function(a){this.scrolling||(c.up(a),c.out(a),c.leave(a)),this.cleanUpPointer(a)},touchcancel:function(a){this.processTouches(a,this.cancelOut)},cancelOut:function(a){c.cancel(a),c.out(a),c.leave(a),this.cleanUpPointer(a)},cleanUpPointer:function(a){f["delete"](a.pointerId),this.removePrimaryPointer(a)},dedupSynthMouse:function(b){var c=a.mouseEvents.lastTouches,d=b.changedTouches[0];if(this.isPrimaryTouch(d)){var e={x:d.clientX,y:d.clientY};c.push(e);var f=function(a,b){var c=a.indexOf(b);c>-1&&a.splice(c,1)}.bind(null,c,e);setTimeout(f,h)}}};k||(b=new a.Installer(l.elementAdded,l.elementRemoved,l.elementChanged,l)),a.touchEvents=l}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher,c=b.pointermap,d=window.MSPointerEvent&&"number"==typeof window.MSPointerEvent.MSPOINTER_TYPE_MOUSE,e={events:["MSPointerDown","MSPointerMove","MSPointerUp","MSPointerOut","MSPointerOver","MSPointerCancel","MSGotPointerCapture","MSLostPointerCapture"],register:function(a){b.listen(a,this.events)},unregister:function(a){b.unlisten(a,this.events)},POINTER_TYPES:["","unavailable","touch","pen","mouse"],prepareEvent:function(a){var c=a;return d&&(c=b.cloneEvent(a),c.pointerType=this.POINTER_TYPES[a.pointerType]),c},cleanup:function(a){c["delete"](a)},MSPointerDown:function(a){c.set(a.pointerId,a);var d=this.prepareEvent(a);b.down(d)},MSPointerMove:function(a){var c=this.prepareEvent(a);b.move(c)},MSPointerUp:function(a){var c=this.prepareEvent(a);b.up(c),this.cleanup(a.pointerId)},MSPointerOut:function(a){var c=this.prepareEvent(a);b.leaveOut(c)},MSPointerOver:function(a){var c=this.prepareEvent(a);b.enterOver(c)},MSPointerCancel:function(a){var c=this.prepareEvent(a);b.cancel(c),this.cleanup(a.pointerId)},MSLostPointerCapture:function(a){var c=b.makeEvent("lostpointercapture",a);b.dispatchEvent(c)},MSGotPointerCapture:function(a){var c=b.makeEvent("gotpointercapture",a);b.dispatchEvent(c)}};a.msEvents=e}(window.PointerEventsPolyfill),function(a){var b=a.dispatcher;if(void 0===window.navigator.pointerEnabled){if(Object.defineProperty(window.navigator,"pointerEnabled",{value:!0,enumerable:!0}),window.navigator.msPointerEnabled){var c=window.navigator.msMaxTouchPoints;Object.defineProperty(window.navigator,"maxTouchPoints",{value:c,enumerable:!0}),b.registerSource("ms",a.msEvents)}else b.registerSource("mouse",a.mouseEvents),void 0!==window.ontouchstart&&b.registerSource("touch",a.touchEvents);b.register(document)}}(window.PointerEventsPolyfill),function(a){function b(a){if(!e.pointermap.has(a))throw new Error("InvalidPointerId")}var c,d,e=a.dispatcher,f=window.navigator;f.msPointerEnabled?(c=function(a){b(a),this.msSetPointerCapture(a)},d=function(a){b(a),this.msReleasePointerCapture(a)}):(c=function(a){b(a),e.setCapture(a,this)},d=function(a){b(a),e.releaseCapture(a,this)}),window.Element&&!Element.prototype.setPointerCapture&&Object.defineProperties(Element.prototype,{setPointerCapture:{value:c},releasePointerCapture:{value:d}})}(window.PointerEventsPolyfill),PointerGestureEvent.prototype.preventTap=function(){this.tapPrevented=!0},function(a){a=a||{},a.utils={LCA:{find:function(a,b){if(a===b)return a;if(a.contains){if(a.contains(b))return a;if(b.contains(a))return b}var c=this.depth(a),d=this.depth(b),e=c-d;for(e>0?a=this.walk(a,e):b=this.walk(b,-e);a&&b&&a!==b;)a=this.walk(a,1),b=this.walk(b,1);return a},walk:function(a,b){for(var c=0;b>c;c++)a=a.parentNode;return a},depth:function(a){for(var b=0;a;)b++,a=a.parentNode;return b}}},a.findLCA=function(b,c){return a.utils.LCA.find(b,c)},window.PointerGestures=a}(window.PointerGestures),function(a){function b(){if(c){var a=new Map;return a.pointers=d,a}this.keys=[],this.values=[]}var c=window.Map&&window.Map.prototype.forEach,d=function(){return this.size};b.prototype={set:function(a,b){var c=this.keys.indexOf(a);c>-1?this.values[c]=b:(this.keys.push(a),this.values.push(b))},has:function(a){return this.keys.indexOf(a)>-1},"delete":function(a){var b=this.keys.indexOf(a);b>-1&&(this.keys.splice(b,1),this.values.splice(b,1))},get:function(a){var b=this.keys.indexOf(a);return this.values[b]},clear:function(){this.keys.length=0,this.values.length=0},forEach:function(a,b){this.values.forEach(function(c,d){a.call(b,c,this.keys[d],this)},this)},pointers:function(){return this.keys.length}},a.PointerMap=b}(window.PointerGestures),function(a){var b=["bubbles","cancelable","view","detail","screenX","screenY","clientX","clientY","ctrlKey","altKey","shiftKey","metaKey","button","relatedTarget","buttons","pointerId","width","height","pressure","tiltX","tiltY","pointerType","hwTimestamp","isPrimary","type","target","currentTarget","screenX","screenY","pageX","pageY","tapPrevented"],c=[!1,!1,null,null,0,0,0,0,!1,!1,!1,!1,0,null,0,0,0,0,0,0,0,"",0,!1,"",null,null,0,0,0,0],d={handledEvents:new WeakMap,targets:new WeakMap,handlers:{},recognizers:{},events:{},registerRecognizer:function(a,b){var c=b;this.recognizers[a]=c,c.events.forEach(function(a){if(c[a]){this.events[a]=!0;var b=c[a].bind(c);this.addHandler(a,b)}},this)},addHandler:function(a,b){var c=a;this.handlers[c]||(this.handlers[c]=[]),this.handlers[c].push(b)},registerTarget:function(a){this.listen(Object.keys(this.events),a)},unregisterTarget:function(a){this.unlisten(Object.keys(this.events),a)},eventHandler:function(a){if(!this.handledEvents.get(a)){var b=a.type,c=this.handlers[b];c&&this.makeQueue(c,a),this.handledEvents.set(a,!0)}},makeQueue:function(a,b){var c=this.cloneEvent(b);requestAnimationFrame(this.runQueue.bind(this,a,c))},runQueue:function(a,b){this.currentPointerId=b.pointerId;for(var c,d=0,e=a.length;e>d&&(c=a[d]);d++)c(b);this.currentPointerId=0},listen:function(a,b){a.forEach(function(a){this.addEvent(a,this.boundHandler,!1,b)},this)},unlisten:function(a){a.forEach(function(a){this.removeEvent(a,this.boundHandler,!1,inTarget)},this)},addEvent:function(a,b,c,d){d.addEventListener(a,b,c)},removeEvent:function(a,b,c,d){d.removeEventListener(a,b,c)},makeEvent:function(a,b){return new PointerGestureEvent(a,b)},cloneEvent:function(a){for(var d,e={},f=0;f<b.length;f++)d=b[f],e[d]=a[d]||c[f];return e},dispatchEvent:function(a,b){var c=b||this.targets.get(a);c&&(c.dispatchEvent(a),a.tapPrevented&&this.preventTap(this.currentPointerId))},asyncDispatchEvent:function(a,b){requestAnimationFrame(this.dispatchEvent.bind(this,a,b))},preventTap:function(a){var b=this.recognizers.tap;b&&b.preventTap(a)}};d.boundHandler=d.eventHandler.bind(d),d.registerQueue=[],d.immediateRegister=!1,a.dispatcher=d,a.register=function(b){if(d.immediateRegister){var c=window.PointerEventsPolyfill;c&&c.register(b),a.dispatcher.registerTarget(b)}else d.registerQueue.push(b)},a.register(document)}(window.PointerGestures),function(a){var b=a.dispatcher,c={HOLD_DELAY:200,WIGGLE_THRESHOLD:16,events:["pointerdown","pointermove","pointerup","pointercancel"],heldPointer:null,holdJob:null,pulse:function(){var a=Date.now()-this.heldPointer.timeStamp,b=this.held?"holdpulse":"hold";this.fireHold(b,a),this.held=!0},cancel:function(){clearInterval(this.holdJob),this.held&&this.fireHold("release"),this.held=!1,this.heldPointer=null,this.target=null,this.holdJob=null},pointerdown:function(a){a.isPrimary&&!this.heldPointer&&(this.heldPointer=a,this.target=a.target,this.holdJob=setInterval(this.pulse.bind(this),this.HOLD_DELAY))},pointerup:function(a){this.heldPointer&&this.heldPointer.pointerId===a.pointerId&&this.cancel()},pointercancel:function(){this.cancel()},pointermove:function(a){if(this.heldPointer&&this.heldPointer.pointerId===a.pointerId){var b=a.clientX-this.heldPointer.clientX,c=a.clientY-this.heldPointer.clientY;b*b+c*c>this.WIGGLE_THRESHOLD&&this.cancel()}},fireHold:function(a,c){var d={pointerType:this.heldPointer.pointerType,clientX:this.heldPointer.clientX,clientY:this.heldPointer.clientY};c&&(d.holdTime=c);var e=b.makeEvent(a,d);b.dispatchEvent(e,this.target),e.tapPrevented&&b.preventTap(this.heldPointer.pointerId)}};b.registerRecognizer("hold",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel"],WIGGLE_THRESHOLD:4,clampDir:function(a){return a>0?1:-1},calcPositionDelta:function(a,b){var c=0,d=0;return a&&b&&(c=b.pageX-a.pageX,d=b.pageY-a.pageY),{x:c,y:d}},fireTrack:function(a,c,d){var e=d,f=this.calcPositionDelta(e.downEvent,c),g=this.calcPositionDelta(e.lastMoveEvent,c);g.x&&(e.xDirection=this.clampDir(g.x)),g.y&&(e.yDirection=this.clampDir(g.y));var h={dx:f.x,dy:f.y,ddx:g.x,ddy:g.y,clientX:c.clientX,clientY:c.clientY,pageX:c.pageX,pageY:c.pageY,screenX:c.screenX,screenY:c.screenY,xDirection:e.xDirection,yDirection:e.yDirection,trackInfo:e.trackInfo,relatedTarget:c.target,pointerType:c.pointerType},i=b.makeEvent(a,h);e.lastMoveEvent=c,b.dispatchEvent(i,e.downTarget)},pointerdown:function(a){if(a.isPrimary&&("mouse"===a.pointerType?1===a.buttons:!0)){var b={downEvent:a,downTarget:a.target,trackInfo:{},lastMoveEvent:null,xDirection:0,yDirection:0,tracking:!1};c.set(a.pointerId,b)}},pointermove:function(a){var b=c.get(a.pointerId);if(b)if(b.tracking)this.fireTrack("track",a,b);else{var d=this.calcPositionDelta(b.downEvent,a),e=d.x*d.x+d.y*d.y;e>this.WIGGLE_THRESHOLD&&(b.tracking=!0,this.fireTrack("trackstart",b.downEvent,b),this.fireTrack("track",a,b))}},pointerup:function(a){var b=c.get(a.pointerId);b&&(b.tracking&&this.fireTrack("trackend",a,b),c.delete(a.pointerId))},pointercancel:function(a){this.pointerup(a)}};b.registerRecognizer("track",d)}(window.PointerGestures),function(a){var b=a.dispatcher,c={MIN_VELOCITY:.5,MAX_QUEUE:4,moveQueue:[],target:null,pointerId:null,events:["pointerdown","pointermove","pointerup","pointercancel"],pointerdown:function(a){a.isPrimary&&!this.pointerId&&(this.pointerId=a.pointerId,this.target=a.target,this.addMove(a))},pointermove:function(a){a.pointerId===this.pointerId&&this.addMove(a)},pointerup:function(a){a.pointerId===this.pointerId&&this.fireFlick(a),this.cleanup()},pointercancel:function(){this.cleanup()},cleanup:function(){this.moveQueue=[],this.target=null,this.pointerId=null},addMove:function(a){this.moveQueue.length>=this.MAX_QUEUE&&this.moveQueue.shift(),this.moveQueue.push(a)},fireFlick:function(a){for(var c,d,e,f,g,h,i,j=a,k=this.moveQueue.length,l=0,m=0,n=0,o=0;k>o&&(i=this.moveQueue[o]);o++)c=j.timeStamp-i.timeStamp,d=j.clientX-i.clientX,e=j.clientY-i.clientY,f=d/c,g=e/c,h=Math.sqrt(f*f+g*g),h>n&&(l=f,m=g,n=h);var p=Math.abs(l)>Math.abs(m)?"x":"y",q=this.calcAngle(l,m);if(Math.abs(n)>=this.MIN_VELOCITY){var r=b.makeEvent("flick",{xVelocity:l,yVelocity:m,velocity:n,angle:q,majorAxis:p,pointerType:a.pointerType});b.dispatchEvent(r,this.target)}},calcAngle:function(a,b){return 180*Math.atan2(b,a)/Math.PI}};b.registerRecognizer("flick",c)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d=180/Math.PI,e={events:["pointerdown","pointermove","pointerup","pointercancel"],reference:{},pointerdown:function(b){if(c.set(b.pointerId,b),2==c.pointers()){var d=this.calcChord(),e=this.calcAngle(d);this.reference={angle:e,diameter:d.diameter,target:a.findLCA(d.a.target,d.b.target)}}},pointerup:function(a){c.delete(a.pointerId)},pointermove:function(a){c.has(a.pointerId)&&(c.set(a.pointerId,a),c.pointers()>1&&this.calcPinchRotate())},pointercancel:function(a){this.pointerup(a)},dispatchPinch:function(a,c){var d=a/this.reference.diameter,e=b.makeEvent("pinch",{scale:d,centerX:c.center.x,centerY:c.center.y});b.dispatchEvent(e,this.reference.target)},dispatchRotate:function(a,c){var d=Math.round((a-this.reference.angle)%360),e=b.makeEvent("rotate",{angle:d,centerX:c.center.x,centerY:c.center.y});b.dispatchEvent(e,this.reference.target)},calcPinchRotate:function(){var a=this.calcChord(),b=a.diameter,c=this.calcAngle(a);b!=this.reference.diameter&&this.dispatchPinch(b,a),c!=this.reference.angle&&this.dispatchRotate(c,a)},calcChord:function(){var a=[];c.forEach(function(b){a.push(b)});for(var b,d,e,f=0,g={a:a[0],b:a[1]},h=0;h<a.length;h++)for(var i=a[h],j=h+1;j<a.length;j++){var k=a[j];b=Math.abs(i.clientX-k.clientX),d=Math.abs(i.clientY-k.clientY),e=b+d,e>f&&(f=e,g={a:i,b:k})}return b=Math.abs(g.a.clientX+g.b.clientX)/2,d=Math.abs(g.a.clientY+g.b.clientY)/2,g.center={x:b,y:d},g.diameter=f,g},calcAngle:function(a){var b=a.a.clientX-a.b.clientX,c=a.a.clientY-a.b.clientY;return(360+Math.atan2(c,b)*d)%360}};b.registerRecognizer("pinch",e)}(window.PointerGestures),function(a){var b=a.dispatcher,c=new a.PointerMap,d={events:["pointerdown","pointermove","pointerup","pointercancel","keyup"],pointerdown:function(a){a.isPrimary&&!a.tapPrevented&&c.set(a.pointerId,{target:a.target,buttons:a.buttons,x:a.clientX,y:a.clientY})},pointermove:function(a){if(a.isPrimary){var b=c.get(a.pointerId);b&&a.tapPrevented&&c.delete(a.pointerId)}},shouldTap:function(a,b){return a.tapPrevented?void 0:"mouse"===a.pointerType?1===b.buttons:!0},pointerup:function(d){var e=c.get(d.pointerId);if(e&&this.shouldTap(d,e)){var f=a.findLCA(e.target,d.target);if(f){var g=b.makeEvent("tap",{x:d.clientX,y:d.clientY,detail:d.detail,pointerType:d.pointerType});b.dispatchEvent(g,f)}}c.delete(d.pointerId)},pointercancel:function(a){c.delete(a.pointerId)},keyup:function(a){var c=a.keyCode;if(32===c){var d=a.target;d instanceof HTMLInputElement||d instanceof HTMLTextAreaElement||b.dispatchEvent(b.makeEvent("tap",{x:0,y:0,detail:0,pointerType:"unavailable"}),d)}},preventTap:function(a){c.delete(a)}};b.registerRecognizer("tap",d)}(window.PointerGestures),function(a){function b(){c.immediateRegister=!0;var b=c.registerQueue;b.forEach(a.register),b.length=0}var c=a.dispatcher;"complete"===document.readyState?b():document.addEventListener("readystatechange",function(){"complete"===document.readyState&&b()})}(window.PointerGestures),function(){"use strict";function a(a){for(;a.parentNode;)a=a.parentNode;return"function"==typeof a.getElementById?a:null}function b(a,b,c){var d=a.bindings_;return d||(d=a.bindings_={}),d[b]&&c[b].close(),d[b]=c}function c(a,b,c){return c}function d(a){return null==a?"":a}function e(a,b){a.data=d(b)}function f(a){return function(b){return e(a,b)}}function g(a,b,c,e){return c?void(e?a.setAttribute(b,""):a.removeAttribute(b)):void a.setAttribute(b,d(e))}function h(a,b,c){return function(d){g(a,b,c,d)}}function i(a){switch(a.type){case"checkbox":return u;case"radio":case"select-multiple":case"select-one":return"change";case"range":if(/Trident|MSIE/.test(navigator.userAgent))return"change";default:return"input"}}function j(a,b,c,e){a[b]=(e||d)(c)}function k(a,b,c){return function(d){return j(a,b,d,c)}}function l(){}function m(a,b,c,d){function e(){c.setValue(a[b]),c.discardChanges(),(d||l)(a),Platform.performMicrotaskCheckpoint()}var f=i(a);return a.addEventListener(f,e),{close:function(){a.removeEventListener(f,e),c.close()},observable_:c}}function n(a){return Boolean(a)}function o(b){if(b.form)return s(b.form.elements,function(a){return a!=b&&"INPUT"==a.tagName&&"radio"==a.type&&a.name==b.name});var c=a(b);if(!c)return[];var d=c.querySelectorAll('input[type="radio"][name="'+b.name+'"]');return s(d,function(a){return a!=b&&!a.form})}function p(a){"INPUT"===a.tagName&&"radio"===a.type&&o(a).forEach(function(a){var b=a.bindings_.checked;b&&b.observable_.setValue(!1)})}function q(a,b){var c,e,f,g=a.parentNode;g instanceof HTMLSelectElement&&g.bindings_&&g.bindings_.value&&(c=g,e=c.bindings_.value,f=c.value),a.value=d(b),c&&c.value!=f&&(e.observable_.setValue(c.value),e.observable_.discardChanges(),Platform.performMicrotaskCheckpoint())}function r(a){return function(b){q(a,b)}}var s=Array.prototype.filter.call.bind(Array.prototype.filter);Node.prototype.bind=function(a,b){console.error("Unhandled binding to Node: ",this,a,b)};var t=c;Object.defineProperty(Platform,"enableBindingsReflection",{get:function(){return t===b},set:function(a){return t=a?b:c,a},configurable:!0}),Text.prototype.bind=function(a,b,c){if("textContent"!==a)return Node.prototype.bind.call(this,a,b,c);
+if(c)return e(this,b);var d=b;return e(this,d.open(f(this))),t(this,a,d)},Element.prototype.bind=function(a,b,c){var d="?"==a[a.length-1];if(d&&(this.removeAttribute(a),a=a.slice(0,-1)),c)return g(this,a,d,b);var e=b;return g(this,a,d,e.open(h(this,a,d))),t(this,a,e)};var u;!function(){var a=document.createElement("div"),b=a.appendChild(document.createElement("input"));b.setAttribute("type","checkbox");var c,d=0;b.addEventListener("click",function(){d++,c=c||"click"}),b.addEventListener("change",function(){d++,c=c||"change"});var e=document.createEvent("MouseEvent");e.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),b.dispatchEvent(e),u=1==d?"change":c}(),HTMLInputElement.prototype.bind=function(a,c,e){if("value"!==a&&"checked"!==a)return HTMLElement.prototype.bind.call(this,a,c,e);this.removeAttribute(a);var f="checked"==a?n:d,g="checked"==a?p:l;if(e)return j(this,a,c,f);var h=c,i=m(this,a,h,g);return j(this,a,h.open(k(this,a,f)),f),b(this,a,i)},HTMLTextAreaElement.prototype.bind=function(a,b,c){if("value"!==a)return HTMLElement.prototype.bind.call(this,a,b,c);if(this.removeAttribute("value"),c)return j(this,"value",b);var e=b,f=m(this,"value",e);return j(this,"value",e.open(k(this,"value",d))),t(this,a,f)},HTMLOptionElement.prototype.bind=function(a,b,c){if("value"!==a)return HTMLElement.prototype.bind.call(this,a,b,c);if(this.removeAttribute("value"),c)return q(this,b);var d=b,e=m(this,"value",d);return q(this,d.open(r(this))),t(this,a,e)},HTMLSelectElement.prototype.bind=function(a,c,d){if("selectedindex"===a&&(a="selectedIndex"),"selectedIndex"!==a&&"value"!==a)return HTMLElement.prototype.bind.call(this,a,c,d);if(this.removeAttribute(a),d)return j(this,a,c);var e=c,f=m(this,a,e);return j(this,a,e.open(k(this,a))),b(this,a,f)}}(this),function(a){"use strict";function b(a){if(!a)throw new Error("Assertion failed")}function c(a){for(var b;b=a.parentNode;)a=b;return a}function d(a,b){if(b){for(var d,e="#"+b;!d&&(a=c(a),a.protoContent_?d=a.protoContent_.querySelector(e):a.getElementById&&(d=a.getElementById(b)),!d&&a.templateCreator_);)a=a.templateCreator_;return d}}function e(a){return"template"==a.tagName&&"http://www.w3.org/2000/svg"==a.namespaceURI}function f(a){return"TEMPLATE"==a.tagName&&"http://www.w3.org/1999/xhtml"==a.namespaceURI}function g(a){return Boolean(J[a.tagName]&&a.hasAttribute("template"))}function h(a){return void 0===a.isTemplate_&&(a.isTemplate_="TEMPLATE"==a.tagName||g(a)),a.isTemplate_}function i(a,b){var c=a.querySelectorAll(L);h(a)&&b(a),E(c,b)}function j(a){function b(a){HTMLTemplateElement.decorate(a)||j(a.content)}i(a,b)}function k(a,b){Object.getOwnPropertyNames(b).forEach(function(c){Object.defineProperty(a,c,Object.getOwnPropertyDescriptor(b,c))})}function l(a){var b=a.ownerDocument;if(!b.defaultView)return b;var c=b.templateContentsOwner_;if(!c){for(c=b.implementation.createHTMLDocument("");c.lastChild;)c.removeChild(c.lastChild);b.templateContentsOwner_=c}return c}function m(a){if(!a.stagingDocument_){var b=a.ownerDocument;if(!b.stagingDocument_){b.stagingDocument_=b.implementation.createHTMLDocument("");var c=b.stagingDocument_.createElement("base");c.href=document.baseURI,b.stagingDocument_.head.appendChild(c),b.stagingDocument_.stagingDocument_=b.stagingDocument_}a.stagingDocument_=b.stagingDocument_}return a.stagingDocument_}function n(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];I[e.name]&&("template"!==e.name&&b.setAttribute(e.name,e.value),a.removeAttribute(e.name))}return b}function o(a){var b=a.ownerDocument.createElement("template");a.parentNode.insertBefore(b,a);for(var c=a.attributes,d=c.length;d-->0;){var e=c[d];b.setAttribute(e.name,e.value),a.removeAttribute(e.name)}return a.parentNode.removeChild(a),b}function p(a,b,c){var d=a.content;if(c)return void d.appendChild(b);for(var e;e=b.firstChild;)d.appendChild(e)}function q(a){N?a.__proto__=HTMLTemplateElement.prototype:k(a,HTMLTemplateElement.prototype)}function r(a){a.setModelFn_||(a.setModelFn_=function(){a.setModelFnScheduled_=!1;var b=z(a,a.delegate_&&a.delegate_.prepareBinding);w(a,b,a.model_)}),a.setModelFnScheduled_||(a.setModelFnScheduled_=!0,Observer.runEOM_(a.setModelFn_))}function s(a,b,c,d){if(a&&a.length){for(var e,f=a.length,g=0,h=0,i=0,j=!0;f>h;){var g=a.indexOf("{{",h),k=a.indexOf("[[",h),l=!1,m="}}";if(k>=0&&(0>g||g>k)&&(g=k,l=!0,m="]]"),i=0>g?-1:a.indexOf(m,g+2),0>i){if(!e)return;e.push(a.slice(h));break}e=e||[],e.push(a.slice(h,g));var n=a.slice(g+2,i).trim();e.push(l),j=j&&l,e.push(Path.get(n));var o=d&&d(n,b,c);e.push(o),h=i+2}return h===f&&e.push(""),e.hasOnePath=5===e.length,e.isSimplePath=e.hasOnePath&&""==e[0]&&""==e[4],e.onlyOneTime=j,e.combinator=function(a){for(var b=e[0],c=1;c<e.length;c+=4){var d=e.hasOnePath?a:a[(c-1)/4];void 0!==d&&(b+=d),b+=e[c+3]}return b},e}}function t(a,b,c,d){if(b.hasOnePath){var e=b[3],f=e?e(d,c,!0):b[2].getValueFrom(d);return b.isSimplePath?f:b.combinator(f)}for(var g=[],h=1;h<b.length;h+=4){var e=b[h+2];g[(h-1)/4]=e?e(d,c):b[h+1].getValueFrom(d)}return b.combinator(g)}function u(a,b,c,d){var e=b[3],f=e?e(d,c,!1):new PathObserver(d,b[2]);return b.isSimplePath?f:new ObserverTransform(f,b.combinator)}function v(a,b,c,d){if(b.onlyOneTime)return t(a,b,c,d);if(b.hasOnePath)return u(a,b,c,d);for(var e=new CompoundObserver,f=1;f<b.length;f+=4){var g=b[f],h=b[f+2];if(h){var i=h(d,c,g);g?e.addPath(i):e.addObserver(i)}else{var j=b[f+1];g?e.addPath(j.getValueFrom(d)):e.addPath(d,j)}}return new ObserverTransform(e,b.combinator)}function w(a,b,c,d){for(var e=0;e<b.length;e+=2){var f=b[e],g=b[e+1],h=v(f,g,a,c),i=a.bind(f,h,g.onlyOneTime);i&&d&&d.push(i)}if(b.isTemplate){a.model_=c;var j=a.processBindingDirectives_(b);d&&j&&d.push(j)}}function x(a,b,c){var d=a.getAttribute(b);return s(""==d?"{{}}":d,b,a,c)}function y(a,c){b(a);for(var d=[],e=0;e<a.attributes.length;e++){for(var f=a.attributes[e],g=f.name,i=f.value;"_"===g[0];)g=g.substring(1);if(!h(a)||g!==H&&g!==F&&g!==G){var j=s(i,g,a,c);j&&d.push(g,j)}}return h(a)&&(d.isTemplate=!0,d.if=x(a,H,c),d.bind=x(a,F,c),d.repeat=x(a,G,c),!d.if||d.bind||d.repeat||(d.bind=s("{{}}",F,a,c))),d}function z(a,b){if(a.nodeType===Node.ELEMENT_NODE)return y(a,b);if(a.nodeType===Node.TEXT_NODE){var c=s(a.data,"textContent",a,b);if(c)return["textContent",c]}return[]}function A(a,b,c,d,e,f,g){for(var h=b.appendChild(c.importNode(a,!1)),i=0,j=a.firstChild;j;j=j.nextSibling)A(j,h,c,d.children[i++],e,f,g);return d.isTemplate&&(HTMLTemplateElement.decorate(h,a),f&&h.setDelegate_(f)),w(h,d,e,g),h}function B(a,b){var c=z(a,b);c.children={};for(var d=0,e=a.firstChild;e;e=e.nextSibling)c.children[d++]=B(e,b);return c}function C(a){this.closed=!1,this.templateElement_=a,this.instances=[],this.deps=void 0,this.iteratedValue=[],this.presentValue=void 0,this.arrayObserver=void 0}var D,E=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.Map&&"function"==typeof a.Map.prototype.forEach?D=a.Map:(D=function(){this.keys=[],this.values=[]},D.prototype={set:function(a,b){var c=this.keys.indexOf(a);0>c?(this.keys.push(a),this.values.push(b)):this.values[c]=b},get:function(a){var b=this.keys.indexOf(a);if(!(0>b))return this.values[b]},"delete":function(a){var b=this.keys.indexOf(a);return 0>b?!1:(this.keys.splice(b,1),this.values.splice(b,1),!0)},forEach:function(a,b){for(var c=0;c<this.keys.length;c++)a.call(b||this,this.values[c],this.keys[c],this)}});"function"!=typeof document.contains&&(Document.prototype.contains=function(a){return a===this||a.parentNode===this?!0:this.documentElement.contains(a)});var F="bind",G="repeat",H="if",I={template:!0,repeat:!0,bind:!0,ref:!0},J={THEAD:!0,TBODY:!0,TFOOT:!0,TH:!0,TR:!0,TD:!0,COLGROUP:!0,COL:!0,CAPTION:!0,OPTION:!0,OPTGROUP:!0},K="undefined"!=typeof HTMLTemplateElement;K&&!function(){var a=document.createElement("template"),b=a.content.ownerDocument,c=b.appendChild(b.createElement("html")),d=c.appendChild(b.createElement("head")),e=b.createElement("base");e.href=document.baseURI,d.appendChild(e)}();var L="template, "+Object.keys(J).map(function(a){return a.toLowerCase()+"[template]"}).join(", ");document.addEventListener("DOMContentLoaded",function(){j(document),Platform.performMicrotaskCheckpoint()},!1),K||(a.HTMLTemplateElement=function(){throw TypeError("Illegal constructor")});var M,N="__proto__"in{};"function"==typeof MutationObserver&&(M=new MutationObserver(function(a){for(var b=0;b<a.length;b++)a[b].target.refChanged_()})),HTMLTemplateElement.decorate=function(a,c){if(a.templateIsDecorated_)return!1;var d=a;d.templateIsDecorated_=!0;var h=f(d)&&K,i=h,k=!h,m=!1;if(h||(g(d)?(b(!c),d=n(a),d.templateIsDecorated_=!0,h=K,m=!0):e(d)&&(d=o(a),d.templateIsDecorated_=!0,h=K)),!h){q(d);var r=l(d);d.content_=r.createDocumentFragment()}return c?d.instanceRef_=c:k?p(d,a,m):i&&j(d.content),!0},HTMLTemplateElement.bootstrap=j;var O=a.HTMLUnknownElement||HTMLElement,P={get:function(){return this.content_},enumerable:!0,configurable:!0};K||(HTMLTemplateElement.prototype=Object.create(O.prototype),Object.defineProperty(HTMLTemplateElement.prototype,"content",P)),k(HTMLTemplateElement.prototype,{bind:function(a,b,c){if("ref"!=a)return Element.prototype.bind.call(this,a,b,c);var d=this,e=c?b:b.open(function(a){d.setAttribute("ref",a),d.refChanged_()});return this.setAttribute("ref",e),this.refChanged_(),c?void 0:(this.bindings_?this.bindings_.ref=b:this.bindings_={ref:b},b)},processBindingDirectives_:function(a){return this.iterator_&&this.iterator_.closeDeps(),a.if||a.bind||a.repeat?(this.iterator_||(this.iterator_=new C(this)),this.iterator_.updateDependencies(a,this.model_),M&&M.observe(this,{attributes:!0,attributeFilter:["ref"]}),this.iterator_):void(this.iterator_&&(this.iterator_.close(),this.iterator_=void 0))},createInstance:function(a,b,c){b&&(c=this.newDelegate_(b)),this.refContent_||(this.refContent_=this.ref_.content);var d=this.refContent_;if(null===d.firstChild)return Q;var e=this.bindingMap_;e&&e.content===d||(e=B(d,c&&c.prepareBinding)||[],e.content=d,this.bindingMap_=e);var f=m(this),g=f.createDocumentFragment();g.templateCreator_=this,g.protoContent_=d,g.bindings_=[],g.terminator_=null;for(var h=g.templateInstance_={firstNode:null,lastNode:null,model:a},i=0,j=!1,k=d.firstChild;k;k=k.nextSibling){null===k.nextSibling&&(j=!0);var l=A(k,g,f,e.children[i++],a,c,g.bindings_);l.templateInstance_=h,j&&(g.terminator_=l)}return h.firstNode=g.firstChild,h.lastNode=g.lastChild,g.templateCreator_=void 0,g.protoContent_=void 0,g},get model(){return this.model_},set model(a){this.model_=a,r(this)},get bindingDelegate(){return this.delegate_&&this.delegate_.raw},refChanged_:function(){this.iterator_&&this.refContent_!==this.ref_.content&&(this.refContent_=void 0,this.iterator_.valueChanged(),this.iterator_.updateIteratedValue())},clear:function(){this.model_=void 0,this.delegate_=void 0,this.bindings_&&this.bindings_.ref&&this.bindings_.ref.close(),this.refContent_=void 0,this.iterator_&&(this.iterator_.valueChanged(),this.iterator_.close(),this.iterator_=void 0)},setDelegate_:function(a){this.delegate_=a,this.bindingMap_=void 0,this.iterator_&&(this.iterator_.instancePositionChangedFn_=void 0,this.iterator_.instanceModelFn_=void 0)},newDelegate_:function(a){function b(b){var c=a&&a[b];if("function"==typeof c)return function(){return c.apply(a,arguments)}}return a?{raw:a,prepareBinding:b("prepareBinding"),prepareInstanceModel:b("prepareInstanceModel"),prepareInstancePositionChanged:b("prepareInstancePositionChanged")}:{}},set bindingDelegate(a){if(this.delegate_)throw Error("Template must be cleared before a new bindingDelegate can be assigned");this.setDelegate_(this.newDelegate_(a))},get ref_(){var a=d(this,this.getAttribute("ref"));if(a||(a=this.instanceRef_),!a)return this;var b=a.ref_;return b?b:a}}),Object.defineProperty(Node.prototype,"templateInstance",{get:function(){var a=this.templateInstance_;return a?a:this.parentNode?this.parentNode.templateInstance:void 0}});var Q=document.createDocumentFragment();Q.bindings_=[],Q.terminator_=null,C.prototype={closeDeps:function(){var a=this.deps;a&&(a.ifOneTime===!1&&a.ifValue.close(),a.oneTime===!1&&a.value.close())},updateDependencies:function(a,b){this.closeDeps();var c=this.deps={},d=this.templateElement_;if(a.if){if(c.hasIf=!0,c.ifOneTime=a.if.onlyOneTime,c.ifValue=v(H,a.if,d,b),c.ifOneTime&&!c.ifValue)return void this.updateIteratedValue();c.ifOneTime||c.ifValue.open(this.updateIteratedValue,this)}a.repeat?(c.repeat=!0,c.oneTime=a.repeat.onlyOneTime,c.value=v(G,a.repeat,d,b)):(c.repeat=!1,c.oneTime=a.bind.onlyOneTime,c.value=v(F,a.bind,d,b)),c.oneTime||c.value.open(this.updateIteratedValue,this),this.updateIteratedValue()},updateIteratedValue:function(){if(this.deps.hasIf){var a=this.deps.ifValue;if(this.deps.ifOneTime||(a=a.discardChanges()),!a)return void this.valueChanged()}var b=this.deps.value;this.deps.oneTime||(b=b.discardChanges()),this.deps.repeat||(b=[b]);var c=this.deps.repeat&&!this.deps.oneTime&&Array.isArray(b);this.valueChanged(b,c)},valueChanged:function(a,b){Array.isArray(a)||(a=[]),a!==this.iteratedValue&&(this.unobserve(),this.presentValue=a,b&&(this.arrayObserver=new ArrayObserver(this.presentValue),this.arrayObserver.open(this.handleSplices,this)),this.handleSplices(ArrayObserver.calculateSplices(this.presentValue,this.iteratedValue)))},getLastInstanceNode:function(a){if(-1==a)return this.templateElement_;var b=this.instances[a],c=b.terminator_;if(!c)return this.getLastInstanceNode(a-1);if(c.nodeType!==Node.ELEMENT_NODE||this.templateElement_===c)return c;var d=c.iterator_;return d?d.getLastTemplateNode():c},getLastTemplateNode:function(){return this.getLastInstanceNode(this.instances.length-1)},insertInstanceAt:function(a,b){var c=this.getLastInstanceNode(a-1),d=this.templateElement_.parentNode;this.instances.splice(a,0,b),d.insertBefore(b,c.nextSibling)},extractInstanceAt:function(a){for(var b=this.getLastInstanceNode(a-1),c=this.getLastInstanceNode(a),d=this.templateElement_.parentNode,e=this.instances.splice(a,1)[0];c!==b;){var f=b.nextSibling;f==c&&(c=b),e.appendChild(d.removeChild(f))}return e},getDelegateFn:function(a){return a=a&&a(this.templateElement_),"function"==typeof a?a:null},handleSplices:function(a){if(!this.closed&&a.length){var b=this.templateElement_;if(!b.parentNode)return void this.close();ArrayObserver.applySplices(this.iteratedValue,this.presentValue,a);var c=b.delegate_;void 0===this.instanceModelFn_&&(this.instanceModelFn_=this.getDelegateFn(c&&c.prepareInstanceModel)),void 0===this.instancePositionChangedFn_&&(this.instancePositionChangedFn_=this.getDelegateFn(c&&c.prepareInstancePositionChanged));for(var d=new D,e=0,f=0;f<a.length;f++){for(var g=a[f],h=g.removed,i=0;i<h.length;i++){var j=h[i],k=this.extractInstanceAt(g.index+e);k!==Q&&d.set(j,k)}e-=g.addedCount}for(var f=0;f<a.length;f++)for(var g=a[f],l=g.index;l<g.index+g.addedCount;l++){var j=this.iteratedValue[l],k=d.get(j);k?d.delete(j):(this.instanceModelFn_&&(j=this.instanceModelFn_(j)),k=void 0===j?Q:b.createInstance(j,void 0,c)),this.insertInstanceAt(l,k)}d.forEach(function(a){this.closeInstanceBindings(a)},this),this.instancePositionChangedFn_&&this.reportInstancesMoved(a)}},reportInstanceMoved:function(a){var b=this.instances[a];b!==Q&&this.instancePositionChangedFn_(b.templateInstance_,a)},reportInstancesMoved:function(a){for(var b=0,c=0,d=0;d<a.length;d++){var e=a[d];if(0!=c)for(;b<e.index;)this.reportInstanceMoved(b),b++;else b=e.index;for(;b<e.index+e.addedCount;)this.reportInstanceMoved(b),b++;c+=e.addedCount-e.removed.length}if(0!=c)for(var f=this.instances.length;f>b;)this.reportInstanceMoved(b),b++},closeInstanceBindings:function(a){for(var b=a.bindings_,c=0;c<b.length;c++)b[c].close()},unobserve:function(){this.arrayObserver&&(this.arrayObserver.close(),this.arrayObserver=void 0)},close:function(){if(!this.closed){this.unobserve();for(var a=0;a<this.instances.length;a++)this.closeInstanceBindings(this.instances[a]);this.instances.length=0,this.closeDeps(),this.templateElement_.iterator_=void 0,this.closed=!0}}},HTMLTemplateElement.forAllTemplatesFrom_=i}(this),function(a){"use strict";function b(a,b){if(!a)throw new Error("ASSERT: "+b)}function c(a){return a>=48&&57>=a}function d(a){return 32===a||9===a||11===a||12===a||160===a||a>=5760&&"áš€á Žâ€€â€â€‚â€ƒâ€„â€…â€†â€‡â€ˆâ€‰â€Šâ€¯âŸã€€ï»¿".indexOf(String.fromCharCode(a))>0}function e(a){return 10===a||13===a||8232===a||8233===a}function f(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a}function g(a){return 36===a||95===a||a>=65&&90>=a||a>=97&&122>=a||a>=48&&57>=a}function h(a){return"this"===a}function i(){for(;Y>X&&d(W.charCodeAt(X));)++X}function j(){var a,b;for(a=X++;Y>X&&(b=W.charCodeAt(X),g(b));)++X;return W.slice(a,X)}function k(){var a,b,c;return a=X,b=j(),c=1===b.length?S.Identifier:h(b)?S.Keyword:"null"===b?S.NullLiteral:"true"===b||"false"===b?S.BooleanLiteral:S.Identifier,{type:c,value:b,range:[a,X]}}function l(){var a,b,c=X,d=W.charCodeAt(X),e=W[X];switch(d){case 46:case 40:case 41:case 59:case 44:case 123:case 125:case 91:case 93:case 58:case 63:return++X,{type:S.Punctuator,value:String.fromCharCode(d),range:[c,X]};default:if(a=W.charCodeAt(X+1),61===a)switch(d){case 37:case 38:case 42:case 43:case 45:case 47:case 60:case 62:case 124:return X+=2,{type:S.Punctuator,value:String.fromCharCode(d)+String.fromCharCode(a),range:[c,X]};case 33:case 61:return X+=2,61===W.charCodeAt(X)&&++X,{type:S.Punctuator,value:W.slice(c,X),range:[c,X]}}}return b=W[X+1],e===b&&"&|".indexOf(e)>=0?(X+=2,{type:S.Punctuator,value:e+b,range:[c,X]}):"<>=!+-*%&|^/".indexOf(e)>=0?(++X,{type:S.Punctuator,value:e,range:[c,X]}):void s({},V.UnexpectedToken,"ILLEGAL")}function m(){var a,d,e;if(e=W[X],b(c(e.charCodeAt(0))||"."===e,"Numeric literal must start with a decimal digit or a decimal point"),d=X,a="","."!==e){for(a=W[X++],e=W[X],"0"===a&&e&&c(e.charCodeAt(0))&&s({},V.UnexpectedToken,"ILLEGAL");c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("."===e){for(a+=W[X++];c(W.charCodeAt(X));)a+=W[X++];e=W[X]}if("e"===e||"E"===e)if(a+=W[X++],e=W[X],("+"===e||"-"===e)&&(a+=W[X++]),c(W.charCodeAt(X)))for(;c(W.charCodeAt(X));)a+=W[X++];else s({},V.UnexpectedToken,"ILLEGAL");return f(W.charCodeAt(X))&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.NumericLiteral,value:parseFloat(a),range:[d,X]}}function n(){var a,c,d,f="",g=!1;for(a=W[X],b("'"===a||'"'===a,"String literal must starts with a quote"),c=X,++X;Y>X;){if(d=W[X++],d===a){a="";break}if("\\"===d)if(d=W[X++],d&&e(d.charCodeAt(0)))"\r"===d&&"\n"===W[X]&&++X;else switch(d){case"n":f+="\n";break;case"r":f+="\r";break;case"t":f+="  ";break;case"b":f+="\b";break;case"f":f+="\f";break;case"v":f+="";break;default:f+=d}else{if(e(d.charCodeAt(0)))break;f+=d}}return""!==a&&s({},V.UnexpectedToken,"ILLEGAL"),{type:S.StringLiteral,value:f,octal:g,range:[c,X]}}function o(a){return a.type===S.Identifier||a.type===S.Keyword||a.type===S.BooleanLiteral||a.type===S.NullLiteral}function p(){var a;return i(),X>=Y?{type:S.EOF,range:[X,X]}:(a=W.charCodeAt(X),40===a||41===a||58===a?l():39===a||34===a?n():f(a)?k():46===a?c(W.charCodeAt(X+1))?m():l():c(a)?m():l())}function q(){var a;return a=$,X=a.range[1],$=p(),X=a.range[1],a}function r(){var a;a=X,$=p(),X=a}function s(a,c){var d,e=Array.prototype.slice.call(arguments,2),f=c.replace(/%(\d)/g,function(a,c){return b(c<e.length,"Message reference must be in range"),e[c]});throw d=new Error(f),d.index=X,d.description=f,d}function t(a){s(a,V.UnexpectedToken,a.value)}function u(a){var b=q();(b.type!==S.Punctuator||b.value!==a)&&t(b)}function v(a){return $.type===S.Punctuator&&$.value===a}function w(a){return $.type===S.Keyword&&$.value===a}function x(){var a=[];for(u("[");!v("]");)v(",")?(q(),a.push(null)):(a.push(bb()),v("]")||u(","));return u("]"),Z.createArrayExpression(a)}function y(){var a;return i(),a=q(),a.type===S.StringLiteral||a.type===S.NumericLiteral?Z.createLiteral(a):Z.createIdentifier(a.value)}function z(){var a,b;return a=$,i(),(a.type===S.EOF||a.type===S.Punctuator)&&t(a),b=y(),u(":"),Z.createProperty("init",b,bb())}function A(){var a=[];for(u("{");!v("}");)a.push(z()),v("}")||u(",");return u("}"),Z.createObjectExpression(a)}function B(){var a;return u("("),a=bb(),u(")"),a}function C(){var a,b,c;return v("(")?B():(a=$.type,a===S.Identifier?c=Z.createIdentifier(q().value):a===S.StringLiteral||a===S.NumericLiteral?c=Z.createLiteral(q()):a===S.Keyword?w("this")&&(q(),c=Z.createThisExpression()):a===S.BooleanLiteral?(b=q(),b.value="true"===b.value,c=Z.createLiteral(b)):a===S.NullLiteral?(b=q(),b.value=null,c=Z.createLiteral(b)):v("[")?c=x():v("{")&&(c=A()),c?c:void t(q()))}function D(){var a=[];if(u("("),!v(")"))for(;Y>X&&(a.push(bb()),!v(")"));)u(",");return u(")"),a}function E(){var a;return a=q(),o(a)||t(a),Z.createIdentifier(a.value)}function F(){return u("."),E()}function G(){var a;return u("["),a=bb(),u("]"),a}function H(){var a,b;for(a=C();v(".")||v("[");)v("[")?(b=G(),a=Z.createMemberExpression("[",a,b)):(b=F(),a=Z.createMemberExpression(".",a,b));return a}function I(){var a,b;return $.type!==S.Punctuator&&$.type!==S.Keyword?b=ab():v("+")||v("-")||v("!")?(a=q(),b=I(),b=Z.createUnaryExpression(a.value,b)):w("delete")||w("void")||w("typeof")?s({},V.UnexpectedToken):b=ab(),b}function J(a){var b=0;if(a.type!==S.Punctuator&&a.type!==S.Keyword)return 0;switch(a.value){case"||":b=1;break;case"&&":b=2;break;case"==":case"!=":case"===":case"!==":b=6;break;case"<":case">":case"<=":case">=":case"instanceof":b=7;break;case"in":b=7;break;case"+":case"-":b=9;break;case"*":case"/":case"%":b=11}return b}function K(){var a,b,c,d,e,f,g,h;if(g=I(),b=$,c=J(b),0===c)return g;for(b.prec=c,q(),e=I(),d=[g,b,e];(c=J($))>0;){for(;d.length>2&&c<=d[d.length-2].prec;)e=d.pop(),f=d.pop().value,g=d.pop(),a=Z.createBinaryExpression(f,g,e),d.push(a);b=q(),b.prec=c,d.push(b),a=I(),d.push(a)}for(h=d.length-1,a=d[h];h>1;)a=Z.createBinaryExpression(d[h-1].value,d[h-2],a),h-=2;return a}function L(){var a,b,c;return a=K(),v("?")&&(q(),b=L(),u(":"),c=L(),a=Z.createConditionalExpression(a,b,c)),a}function M(){var a,b;return a=q(),a.type!==S.Identifier&&t(a),b=v("(")?D():[],Z.createFilter(a.value,b)}function N(){for(;v("|");)q(),M()}function O(){i(),r();var a=bb();a&&(","===$.value||"in"==$.value&&a.type===U.Identifier?Q(a):(N(),"as"===$.value?P(a):Z.createTopLevel(a))),$.type!==S.EOF&&t($)}function P(a){q();var b=q().value;Z.createAsExpression(a,b)}function Q(a){var b;","===$.value&&(q(),$.type!==S.Identifier&&t($),b=q().value),q();var c=bb();N(),Z.createInExpression(a.name,b,c)}function R(a,b){return Z=b,W=a,X=0,Y=W.length,$=null,_={labelSet:{}},O()}var S,T,U,V,W,X,Y,Z,$,_;S={BooleanLiteral:1,EOF:2,Identifier:3,Keyword:4,NullLiteral:5,NumericLiteral:6,Punctuator:7,StringLiteral:8},T={},T[S.BooleanLiteral]="Boolean",T[S.EOF]="<end>",T[S.Identifier]="Identifier",T[S.Keyword]="Keyword",T[S.NullLiteral]="Null",T[S.NumericLiteral]="Numeric",T[S.Punctuator]="Punctuator",T[S.StringLiteral]="String",U={ArrayExpression:"ArrayExpression",BinaryExpression:"BinaryExpression",CallExpression:"CallExpression",ConditionalExpression:"ConditionalExpression",EmptyStatement:"EmptyStatement",ExpressionStatement:"ExpressionStatement",Identifier:"Identifier",Literal:"Literal",LabeledStatement:"LabeledStatement",LogicalExpression:"LogicalExpression",MemberExpression:"MemberExpression",ObjectExpression:"ObjectExpression",Program:"Program",Property:"Property",ThisExpression:"ThisExpression",UnaryExpression:"UnaryExpression"},V={UnexpectedToken:"Unexpected token %0",UnknownLabel:"Undefined label '%0'",Redeclaration:"%0 '%1' has already been declared"};var ab=H,bb=L;a.esprima={parse:R}}(this),function(a){"use strict";function b(a,b,d,e){var f;try{if(f=c(a),f.scopeIdent&&(d.nodeType!==Node.ELEMENT_NODE||"TEMPLATE"!==d.tagName||"bind"!==b&&"repeat"!==b))throw Error("as and in can only be used within <template bind/repeat>")}catch(g){return void console.error("Invalid expression syntax: "+a,g)}return function(a,b,c){var d=f.getBinding(a,e,c);return f.scopeIdent&&d&&(b.polymerExpressionScopeIdent_=f.scopeIdent,f.indexIdent&&(b.polymerExpressionIndexIdent_=f.indexIdent)),d}}function c(a){var b=s[a];if(!b){var c=new j;esprima.parse(a,c),b=new l(c),s[a]=b}return b}function d(a){this.value=a,this.valueFn_=void 0}function e(a){this.name=a,this.path=Path.get(a)}function f(a,b,c){"["==c&&b instanceof d&&Path.get(b.value).valid&&(c=".",b=new e(b.value)),this.dynamicDeps="function"==typeof a||a.dynamic,this.dynamic="function"==typeof b||b.dynamic||"["==c,this.simplePath=!this.dynamic&&!this.dynamicDeps&&b instanceof e&&(a instanceof f||a instanceof e),this.object=this.simplePath?a:i(a),this.property="."==c?b:i(b)}function g(a,b){this.name=a,this.args=[];for(var c=0;c<b.length;c++)this.args[c]=i(b[c])}function h(){throw Error("Not Implemented")}function i(a){return"function"==typeof a?a:a.valueFn()}function j(){this.expression=null,this.filters=[],this.deps={},this.currentPath=void 0,this.scopeIdent=void 0,this.indexIdent=void 0,this.dynamicDeps=!1}function k(a){this.value_=a}function l(a){if(this.scopeIdent=a.scopeIdent,this.indexIdent=a.indexIdent,!a.expression)throw Error("No expression found.");this.expression=a.expression,i(this.expression),this.filters=a.filters,this.dynamicDeps=a.dynamicDeps}function m(a){return String(a).replace(/[A-Z]/g,function(a){return"-"+a.toLowerCase()})}function n(a){return"o"===a[0]&&"n"===a[1]&&"-"===a[2]}function o(a,b){for(;a[w]&&!Object.prototype.hasOwnProperty.call(a,b);)a=a[w];return a}function p(a,b){if(0==b.length)return void 0;if(1==b.length)return o(a,b[0]);for(var c=0;null!=a&&c<b.length-1;c++)a=a[b[c]];return a}function q(a,b,c){var d=b.substring(3);return d=v[d]||d,function(b,e,f){function g(){return"{{ "+a+" }}"}var h,i,j;return j="function"==typeof c.resolveEventHandler?function(d){h=h||c.resolveEventHandler(b,a,e),h(d,d.detail,d.currentTarget),Platform&&"function"==typeof Platform.flush&&Platform.flush()}:function(c){h=h||a.getValueFrom(b),i=i||p(b,a,e),h.apply(i,[c,c.detail,c.currentTarget]),Platform&&"function"==typeof Platform.flush&&Platform.flush()},e.addEventListener(d,j),f?void 0:{open:g,discardChanges:g,close:function(){e.removeEventListener(d,j)}}}}function r(){}var s=Object.create(null);d.prototype={valueFn:function(){if(!this.valueFn_){var a=this.value;this.valueFn_=function(){return a}}return this.valueFn_}},e.prototype={valueFn:function(){if(!this.valueFn_){var a=(this.name,this.path);this.valueFn_=function(b,c){return c&&c.addPath(b,a),a.getValueFrom(b)}}return this.valueFn_},setValue:function(a,b){return 1==this.path.length,a=o(a,this.path[0]),this.path.setValueFrom(a,b)}},f.prototype={get fullPath(){if(!this.fullPath_){var a=this.object instanceof e?this.object.name:this.object.fullPath;this.fullPath_=Path.get(a+"."+this.property.name)}return this.fullPath_},valueFn:function(){if(!this.valueFn_){var a=this.object;if(this.simplePath){var b=this.fullPath;this.valueFn_=function(a,c){return c&&c.addPath(a,b),b.getValueFrom(a)}}else if(this.property instanceof e){var b=Path.get(this.property.name);this.valueFn_=function(c,d){var e=a(c,d);return d&&d.addPath(e,b),b.getValueFrom(e)}}else{var c=this.property;this.valueFn_=function(b,d){var e=a(b,d),f=c(b,d);return d&&d.addPath(e,f),e?e[f]:void 0}}}return this.valueFn_},setValue:function(a,b){if(this.simplePath)return this.fullPath.setValueFrom(a,b),b;var c=this.object(a),d=this.property instanceof e?this.property.name:this.property(a);return c[d]=b}},g.prototype={transform:function(a,b,c,d,e){var f=c[this.name],g=d;if(f)g=void 0;else if(f=g[this.name],!f)return void console.error("Cannot find filter: "+this.name);if(b?f=f.toModel:"function"==typeof f.toDOM&&(f=f.toDOM),"function"!=typeof f)return void console.error("No "+(b?"toModel":"toDOM")+" found on"+this.name);for(var h=[a],j=0;j<this.args.length;j++)h[j+1]=i(this.args[j])(d,e);return f.apply(g,h)}};var t={"+":function(a){return+a},"-":function(a){return-a},"!":function(a){return!a}},u={"+":function(a,b){return a+b},"-":function(a,b){return a-b},"*":function(a,b){return a*b},"/":function(a,b){return a/b},"%":function(a,b){return a%b},"<":function(a,b){return b>a},">":function(a,b){return a>b},"<=":function(a,b){return b>=a},">=":function(a,b){return a>=b},"==":function(a,b){return a==b},"!=":function(a,b){return a!=b},"===":function(a,b){return a===b},"!==":function(a,b){return a!==b},"&&":function(a,b){return a&&b},"||":function(a,b){return a||b}};j.prototype={createUnaryExpression:function(a,b){if(!t[a])throw Error("Disallowed operator: "+a);return b=i(b),function(c,d){return t[a](b(c,d))}},createBinaryExpression:function(a,b,c){if(!u[a])throw Error("Disallowed operator: "+a);return b=i(b),c=i(c),function(d,e){return u[a](b(d,e),c(d,e))}},createConditionalExpression:function(a,b,c){return a=i(a),b=i(b),c=i(c),function(d,e){return a(d,e)?b(d,e):c(d,e)}},createIdentifier:function(a){var b=new e(a);return b.type="Identifier",b},createMemberExpression:function(a,b,c){var d=new f(b,c,a);return d.dynamicDeps&&(this.dynamicDeps=!0),d},createLiteral:function(a){return new d(a.value)},createArrayExpression:function(a){for(var b=0;b<a.length;b++)a[b]=i(a[b]);return function(b,c){for(var d=[],e=0;e<a.length;e++)d.push(a[e](b,c));return d}},createProperty:function(a,b,c){return{key:b instanceof e?b.name:b.value,value:c}},createObjectExpression:function(a){for(var b=0;b<a.length;b++)a[b].value=i(a[b].value);return function(b,c){for(var d={},e=0;e<a.length;e++)d[a[e].key]=a[e].value(b,c);return d}},createFilter:function(a,b){this.filters.push(new g(a,b))},createAsExpression:function(a,b){this.expression=a,this.scopeIdent=b},createInExpression:function(a,b,c){this.expression=c,this.scopeIdent=a,this.indexIdent=b},createTopLevel:function(a){this.expression=a},createThisExpression:h},k.prototype={open:function(){return this.value_},discardChanges:function(){return this.value_},deliver:function(){},close:function(){}},l.prototype={getBinding:function(a,b,c){function d(){if(h)return h=!1,g;i.dynamicDeps&&f.startReset();var c=i.getValue(a,i.dynamicDeps?f:void 0,b);return i.dynamicDeps&&f.finishReset(),c}function e(c){return i.setValue(a,c,b),c}if(c)return this.getValue(a,void 0,b);var f=new CompoundObserver,g=this.getValue(a,f,b),h=!0,i=this;return new ObserverTransform(f,d,e,!0)},getValue:function(a,b,c){for(var d=i(this.expression)(a,b),e=0;e<this.filters.length;e++)d=this.filters[e].transform(d,!1,c,a,b);return d},setValue:function(a,b,c){for(var d=this.filters?this.filters.length:0;d-->0;)b=this.filters[d].transform(b,!0,c,a);return this.expression.setValue?this.expression.setValue(a,b):void 0}};var v={};["webkitAnimationStart","webkitAnimationEnd","webkitTransitionEnd","DOMFocusOut","DOMFocusIn","DOMMouseScroll"].forEach(function(a){v[a.toLowerCase()]=a});var w="@"+Math.random().toString(36).slice(2);r.prototype={styleObject:function(a){var b=[];for(var c in a)b.push(m(c)+": "+a[c]);return b.join("; ")},tokenList:function(a){var b=[];for(var c in a)a[c]&&b.push(c);return b.join(" ")},prepareInstancePositionChanged:function(a){var b=a.polymerExpressionIndexIdent_;if(b)return function(a,c){a.model[b]=c}},prepareBinding:function(a,c,d){var e=Path.get(a);if(n(c))return e.valid?q(e,c,this):void console.error("on-* bindings must be simple path expressions");{if(!e.valid)return b(a,c,d,this);if(1==e.length)return function(a,b,c){if(c)return e.getValueFrom(a);var d=o(a,e[0]);return new PathObserver(d,e)}}},prepareInstanceModel:function(a){var b=a.polymerExpressionScopeIdent_;if(b){var c=a.templateInstance?a.templateInstance.model:a.model,d=a.polymerExpressionIndexIdent_;return function(a){var e=Object.create(c);return e[b]=a,e[d]=void 0,e[w]=c,e}}}},a.PolymerExpressions=r,a.exposeGetExpression&&(a.getExpression_=c),a.PolymerExpressions.prepareEventBinding=q}(this),function(a){function b(){e||(e=!0,a.endOfMicrotask(function(){e=!1,logFlags.data&&console.group("Platform.flush()"),a.performMicrotaskCheckpoint(),logFlags.data&&console.groupEnd()}))}var c=document.createElement("style");
+c.textContent="template {display: none !important;} /* injected by platform.js */";var d=document.querySelector("head");d.insertBefore(c,d.firstChild);var e,f=125;if(window.addEventListener("WebComponentsReady",function(){b(),Observer.hasObjectObserve||(a.flushPoll=setInterval(b,f))}),window.CustomElements&&!CustomElements.useNative){var g=Document.prototype.importNode;Document.prototype.importNode=function(a,b){var c=g.call(this,a,b);return CustomElements.upgradeAll(c),c}}a.flush=b}(window.Platform);
 //# sourceMappingURL=platform.js.map</script>
     <meta name="viewport" content="width=device-width, user-scalable=no">
     
@@ -54,35 +58,38 @@
  Use of this source code is governed by a BSD-style
  license that can be found in the LICENSE file.
 -->
-<script>// Copyright (c) 2012 The Polymer Authors. All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//    * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//    * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//    * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-// @version: 0.1.1
-Polymer={},"function"==typeof window.Polymer&&(Polymer={}),function(a){function b(a,b){return a&&b&&Object.getOwnPropertyNames(b).forEach(function(c){var d=Object.getOwnPropertyDescriptor(b,c);d&&(Object.defineProperty(a,c,d),"function"==typeof d.value&&(d.value.nom=c))}),a}a.extend=b}(Polymer),function(a){function b(a,b,d){return a?a.stop():a=new c(this),a.go(b,d),a}var c=function(a){this.context=a};c.prototype={go:function(a,b){this.callback=a,this.handle=setTimeout(this.complete.bind(this),b)},stop:function(){this.handle&&(clearTimeout(this.handle),this.handle=null)},complete:function(){this.handle&&(this.stop(),this.callback.call(this.context))}},a.job=b}(Polymer),function(){var a={};HTMLElement.register=function(b,c){a[b]=c},HTMLElement.getPrototypeForTag=function(b){var c=b?a[b]:HTMLElement.prototype;return c||Object.getPrototypeOf(document.createElement(b))};var b=Event.prototype.stopPropagation;Event.prototype.stopPropagation=function(){this.cancelBubble=!0,b.apply(this,arguments)},HTMLImports.importer.preloadSelectors+=", polymer-element link[rel=stylesheet]"}(Polymer),function(a){function b(a){var c=b.caller,g=c.nom,h=c._super;if(h||(g||(g=c.nom=e.call(this,c)),g||console.warn("called super() on a method not installed declaratively (has no .nom property)"),h=d(c,g,f(this))),h){var i=h[g];return i._super||d(i,g,h),i.apply(this,a||[])}}function c(a,b,c){for(;a;){if(a[b]!==c&&a[b])return a;a=f(a)}}function d(a,b,d){return a._super=c(d,b,a),a._super&&(a._super[b].nom=b),a._super}function e(a){for(var b=this.__proto__;b&&b!==HTMLElement.prototype;){for(var c,d=Object.getOwnPropertyNames(b),e=0,f=d.length;f>e&&(c=d[e]);e++){var g=Object.getOwnPropertyDescriptor(b,c);if("function"==typeof g.value&&g.value===a)return c}b=b.__proto__}}function f(a){return a.__proto__}a.super=b}(Polymer),function(a){function b(a,b){var d=typeof b;return b instanceof Date&&(d="date"),c[d](a,b)}var c={string:function(a){return a},date:function(a){return new Date(Date.parse(a)||Date.now())},"boolean":function(a){return""===a?!0:"false"===a?!1:!!a},number:function(a){var b=parseFloat(a);return String(b)===a?b:a},object:function(a,b){if(null===b)return a;try{return JSON.parse(a.replace(/'/g,'"'))}catch(c){return a}},"function":function(a,b){return b}};a.deserializeValue=b}(Polymer),function(a){var b={};b.declaration={},b.instance={},a.api=b}(Polymer),function(a){var b={async:function(a,b,c){Platform.flush(),b=b&&b.length?b:[b];var d=function(){(this[a]||a).apply(this,b)}.bind(this);return c?setTimeout(d,c):requestAnimationFrame(d)},fire:function(a,b,c,d){var e=c||this;return e.dispatchEvent(new CustomEvent(a,{bubbles:void 0!==d?d:!0,detail:b})),b},asyncFire:function(){this.async("fire",arguments)},classFollows:function(a,b,c){b&&b.classList.remove(c),a&&a.classList.add(c)}};b.asyncMethod=b.async,a.api.instance.utils=b}(Polymer),function(a){function b(a){for(;a.parentNode;)a=a.parentNode;return a.host}var c=window.logFlags||{},d="on-",e={EVENT_PREFIX:d,hasEventPrefix:function(a){return a&&"o"===a[0]&&"n"===a[1]&&"-"===a[2]},removeEventPrefix:function(a){return a.slice(f)},addHostListeners:function(){var a=this.eventDelegates;c.events&&Object.keys(a).length>0&&console.log("[%s] addHostListeners:",this.localName,a),this.addNodeListeners(this,a,this.hostEventListener)},addNodeListeners:function(a,b,c){var d;for(var e in b)d||(d=c.bind(this)),this.addNodeListener(a,e,d)},addNodeListener:function(a,b,c){a.addEventListener(b,c)},hostEventListener:function(a){if(!a.cancelBubble){c.events&&console.group("[%s]: hostEventListener(%s)",this.localName,a.type);var b=this.findEventDelegate(a);b&&(c.events&&console.log("[%s] found host handler name [%s]",this.localName,b),this.dispatchMethod(this,b,[a,a.detail,this])),c.events&&console.groupEnd()}},findEventDelegate:function(a){return this.eventDelegates[a.type]},dispatchMethod:function(a,b,d){if(a){c.events&&console.group("[%s] dispatch [%s]",a.localName,b);var e="function"==typeof b?b:a[b];e&&e[d?"apply":"call"](a,d),c.events&&console.groupEnd(),Platform.flush()}},prepareBinding:function(a,d){return e.hasEventPrefix(d)?function(f,g){c.events&&console.log('event: [%s].%s => [%s].%s()"',g.localName,f.localName,a);var h=function(c){var d=b(g);if(d&&d.dispatchMethod){var e=d,h=a;"@"==a[0]&&(e=f,h=Path.get(a.slice(1)).getValueFrom(f)),d.dispatchMethod(e,h,[c,c.detail,g])}},i=e.removeEventPrefix(d);return g.addEventListener(i,h,!1),{close:function(){c.events&&console.log('event.remove: [%s].%s => [%s].%s()"',g.localName,d,f.localName,a),g.removeEventListener(i,h,!1)}}}:void 0}},f=d.length;a.api.instance.events=e}(Polymer),function(a){var b={copyInstanceAttributes:function(){var a=this._instanceAttributes;for(var b in a)this.hasAttribute(b)||this.setAttribute(b,a[b])},takeAttributes:function(){if(this._publishLC)for(var a,b=0,c=this.attributes,d=c.length;(a=c[b])&&d>b;b++)this.attributeToProperty(a.name,a.value)},attributeToProperty:function(b,c){var b=this.propertyForAttribute(b);if(b){if(c&&c.search(a.bindPattern)>=0)return;var d=this[b],c=this.deserializeValue(c,d);c!==d&&(this[b]=c)}},propertyForAttribute:function(a){var b=this._publishLC&&this._publishLC[a];return b},deserializeValue:function(b,c){return a.deserializeValue(b,c)},serializeValue:function(a,b){return"boolean"===b?a?"":void 0:"object"!==b&&"function"!==b&&void 0!==a?a:void 0},reflectPropertyToAttribute:function(a){var b=typeof this[a],c=this.serializeValue(this[a],b);void 0!==c?this.setAttribute(a,c):"boolean"===b&&this.removeAttribute(a)}};a.api.instance.attributes=b}(Polymer),function(a){function b(a){return new CompoundPathObserver(a.notifyPropertyChanges,a)}function c(a,b,c,e){d.bind&&console.log(f,c.localName||"object",e,a.localName,b);var g=Path.get(e),h=g.getValueFrom(c);return(null===h||void 0===h)&&g.setValueFrom(c,a[b]),PathObserver.defineProperty(a,b,c,e)}var d=window.logFlags||{},e={observeProperties:function(){var a=this._observeNames,c=this._publishNames;if(a&&a.length||c&&c.length){for(var d,e=this._propertyObserver=b(this),f=0,g=a.length;g>f&&(d=a[f]);f++){e.addPath(this,d);var h=Object.getOwnPropertyDescriptor(this.__proto__,d);h&&h.value&&this.observeArrayValue(d,h.value,null)}for(var d,f=0,g=c.length;g>f&&(d=c[f]);f++)this.observe&&void 0!==this.observe[d]||e.addPath(this,d);e.start()}},notifyPropertyChanges:function(a,b,c,d){for(var e,f,g={},h=0,i=c.length;i>h;h++)c[h]&&(e=d[2*h+1],void 0!==this.publish[e]&&this.reflectPropertyToAttribute(e),f=this.observe[e],f&&(this.observeArrayValue(e,a[h],b[h]),g[f]||(g[f]=!0,this.invokeMethod(f,[b[h],a[h],arguments]))))},observeArrayValue:function(a,b,c){var e=this.observe[a];if(e&&(Array.isArray(c)&&(d.observe&&console.log("[%s] observeArrayValue: unregister observer [%s]",this.localName,a),this.unregisterObserver(a+"__array")),Array.isArray(b))){d.observe&&console.log("[%s] observeArrayValue: register observer [%s]",this.localName,a,b);var f=this,g=new ArrayObserver(b,function(a,b){f.invokeMethod(e,[b])});this.registerObserver(a+"__array",g)}},bindProperty:function(a,b,d){return c(this,a,b,d)},unbindAllProperties:function(){this._propertyObserver&&this._propertyObserver.close(),this.unregisterObservers()},unbindProperty:function(a){return this.unregisterObserver(a)},invokeMethod:function(a,b){var c=this[a]||a;"function"==typeof c&&c.apply(this,b)},registerObserver:function(a,b){var c=this._observers||(this._observers={});c[a]=b},unregisterObserver:function(a){var b=this._observers;return b&&b[a]?(b[a].close(),b[a]=null,!0):void 0},unregisterObservers:function(){if(this._observers){for(var a,b,c=Object.keys(this._observers),d=0,e=c.length;e>d&&(a=c[d]);d++)b=this._observers[a],b.close();this._observers={}}}},f="[%s]: bindProperties: [%s] to [%s].[%s]";a.api.instance.properties=e}(Polymer),function(a){function b(a){d(a,c)}function c(a){a.unbindAll()}function d(a,b){if(a){b(a);for(var c=a.firstChild;c;c=c.nextSibling)d(c,b)}}var e=window.logFlags||0,f=a.api.instance.events,g=PolymerExpressions.prototype.prepareBinding;PolymerExpressions.prototype.prepareBinding=function(a,b,c){return f.prepareBinding(a,b,c)||g.call(this,a,b,c)};var h=new PolymerExpressions,i={syntax:h,instanceTemplate:function(a){return a.bindingDelegate=this.syntax,a.createInstance(this)},bind:function(a,b,c){this._elementPrepared||this.prepareElement();var d=this.propertyForAttribute(a);if(d){this.unbind(a);var e=this.bindProperty(d,b,c);return e.path=c,this.reflectPropertyToAttribute(d),this.bindings[a]=e}return this.super(arguments)},asyncUnbindAll:function(){this._unbound||(e.unbind&&console.log("[%s] asyncUnbindAll",this.localName),this._unbindAllJob=this.job(this._unbindAllJob,this.unbindAll,0))},unbindAll:function(){if(!this._unbound){this.unbindAllProperties(),this.super();for(var a=this.shadowRoot;a;)b(a),a=a.olderShadowRoot;this._unbound=!0}},cancelUnbindAll:function(a){return this._unbound?(e.unbind&&console.warn("[%s] already unbound, cannot cancel unbindAll",this.localName),void 0):(e.unbind&&console.log("[%s] cancelUnbindAll",this.localName),this._unbindAllJob&&(this._unbindAllJob=this._unbindAllJob.stop()),a||d(this.shadowRoot,function(a){a.cancelUnbindAll&&a.cancelUnbindAll()}),void 0)}},j=/\{\{([^{}]*)}}/;a.bindPattern=j,a.api.instance.mdv=i}(Polymer),function(a){function b(a){return a.hasOwnProperty("PolymerBase")}function c(){}var d=0,e={PolymerBase:!0,job:Polymer.job,"super":Polymer.super,created:function(){},ready:function(){},createdCallback:function(){this.created(),(this.ownerDocument.defaultView||this.alwaysPrepare||d>0)&&this.prepareElement()},prepareElement:function(){this._elementPrepared=!0,this.observeProperties(),this.copyInstanceAttributes(),this.takeAttributes(),this.addHostListeners(),d++,this.parseDeclarations(this.__proto__),d--,this.ready()},enteredViewCallback:function(){this._elementPrepared||this.prepareElement(),this.cancelUnbindAll(!0),this.enteredView&&this.enteredView()},leftViewCallback:function(){this.preventDispose||this.asyncUnbindAll(),this.leftView&&this.leftView()},enteredDocumentCallback:function(){this.enteredViewCallback()},leftDocumentCallback:function(){this.leftViewCallback()},parseDeclarations:function(a){a&&a.element&&(this.parseDeclarations(a.__proto__),a.parseDeclaration.call(this,a.element))},parseDeclaration:function(a){var b=this.fetchTemplate(a);b&&(this.element.hasAttribute("lightdom")?this.lightFromTemplate(b):this.shadowFromTemplate(b))},fetchTemplate:function(a){return a.querySelector("template")},shadowFromTemplate:function(a){if(a){var b=(this.shadowRoot,this.createShadowRoot());b.applyAuthorStyles=this.applyAuthorStyles,b.resetStyleInheritance=this.resetStyleInheritance;var c=this.instanceTemplate(a);return b.appendChild(c),this.shadowRootReady(b,a),b}},lightFromTemplate:function(a){if(a){var b=this.instanceTemplate(a);return this.appendChild(b),this.shadowRootReady(this,a),b}},shadowRootReady:function(a){this.marshalNodeReferences(a),PointerGestures.register(a)},marshalNodeReferences:function(a){var b=this.$=this.$||{};if(a)for(var c,d=a.querySelectorAll("[id]"),e=0,f=d.length;f>e&&(c=d[e]);e++)b[c.id]=c},attributeChangedCallback:function(a){"class"!==a&&"style"!==a&&this.attributeToProperty(a,this.getAttribute(a)),this.attributeChanged&&this.attributeChanged.apply(this,arguments)},onMutation:function(a,b){var c=new MutationObserver(function(a){b.call(this,c,a),c.disconnect()}.bind(this));c.observe(a,{childList:!0,subtree:!0})}};c.prototype=e,e.constructor=c,a.Base=c,a.isBase=b,a.api.instance.base=e}(Polymer),function(a){function b(a){return a.__proto__}var c=(window.logFlags||{},"element"),d="controller",e={STYLE_SCOPE_ATTRIBUTE:c,installControllerStyles:function(){var a=this.findStyleController();if(a&&!this.scopeHasElementStyle(a,d)){for(var c=b(this),e="";c&&c.element;)e+=c.element.cssTextForScope(d),c=b(c);if(e){var f=this.element.cssTextToScopeStyle(e,d);Polymer.applyStyleToScope(f,a)}}},findStyleController:function(){if(window.ShadowDOMPolyfill)return wrap(document.head);for(var a=this;a.parentNode;)a=a.parentNode;return a===document?document.head:a},scopeHasElementStyle:function(a,b){var d=c+"="+this.localName+"-"+b;return a.querySelector("style["+d+"]")}};a.api.instance.styles=e}(Polymer),function(a){var b={addResolvePathApi:function(){var a=this.elementPath(),b=this.getAttribute("assetpath")||"",c=this.relPath;this.prototype.resolvePath=function(d){var e=d;if(b){var f=b.slice(0,-1);e=c(f,e)}return a+b+e}},elementPath:function(){return this.urlToPath(HTMLImports.getDocumentUrl(this.ownerDocument))},relPath:function(a,b){for(var c=a.split("/"),d=b.split("/"),e=!1;c.length&&d.length&&c[0]===d[0];)c.shift(),d.shift(),e=!0;if(e)for(var f=0;f<c.length;f++)d.unshift("..");return d.join("/")},urlToPath:function(a){if(a){var b=a.split("/");return b.pop(),b.push(""),b.join("/")}return""}};a.api.declaration.path=b}(Polymer),function(a){function b(a,b){if(a){var d=c(a.textContent),e=a.getAttribute(g);e&&d.setAttribute(g,e),b.appendChild(d)}}function c(a){var b=document.createElement("style");return b.textContent=a,b}function d(a){return a&&a.__resource||""}function e(a,b){return n?n.call(a,b):void 0}var f=(window.logFlags||{},a.api.instance.styles),g=f.STYLE_SCOPE_ATTRIBUTE,h="style",i="[rel=stylesheet]",j="global",k="polymer-scope",l={installSheets:function(){this.cacheSheets(),this.cacheStyles(),this.installLocalSheets(),this.installGlobalStyles()},cacheSheets:function(){this.sheets=this.findNodes(i),this.sheets.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},cacheStyles:function(){this.styles=this.findNodes(h+"["+k+"]"),this.styles.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},installLocalSheets:function(){var a=this.sheets.filter(function(a){return!a.hasAttribute(k)}),b=this.templateContent();if(b){var e="";a.forEach(function(a){e+=d(a)+"\n"}),e&&b.insertBefore(c(e),b.firstChild)}},findNodes:function(a,b){var c=this.querySelectorAll(a).array(),d=this.templateContent();if(d){var e=d.querySelectorAll(a).array();c=c.concat(e)}return b?c.filter(b):c},templateContent:function(){var a=this.querySelector("template");return a&&templateContent(a)},installGlobalStyles:function(){var a=this.styleForScope(j);b(a,document.head)},cssTextForScope:function(a){var b="",c="["+k+"="+a+"]",f=function(a){return e(a,c)},g=this.sheets.filter(f);g.forEach(function(a){b+=d(a)+"\n\n"});var h=this.styles.filter(f);return h.forEach(function(a){b+=a.textContent+"\n\n"}),b},styleForScope:function(a){var b=this.cssTextForScope(a);return this.cssTextToScopeStyle(b,a)},cssTextToScopeStyle:function(a,b){if(a){var d=c(a);return d.setAttribute(g,this.getAttribute("name")+"-"+b),d}}},m=HTMLElement.prototype,n=m.matches||m.matchesSelector||m.webkitMatchesSelector||m.mozMatchesSelector;a.api.declaration.styles=l,a.applyStyleToScope=b}(Polymer),function(a){var b=a.api.instance.events,c=(window.logFlags||{},{parseHostEvents:function(){var a=this.prototype.eventDelegates;this.addAttributeDelegates(a)},addAttributeDelegates:function(a){for(var c,d=0;c=this.attributes[d];d++)b.hasEventPrefix(c.name)&&(a[b.removeEventPrefix(c.name)]=c.value.replace("{{","").replace("}}","").trim())},event_translations:{webkitanimationstart:"webkitAnimationStart",webkitanimationend:"webkitAnimationEnd",webkittransitionend:"webkitTransitionEnd",domfocusout:"DOMFocusOut",domfocusin:"DOMFocusIn"}});a.api.declaration.events=c}(Polymer),function(a){var b={inferObservers:function(a){var b,c=a.observe;for(var d in a)"Changed"===d.slice(-7)&&(c||(c=a.observe={}),b=d.slice(0,-7),c[b]=c[b]||d)},optimizePropertyMaps:function(a){if(a.observe){var b=a._observeNames=[];for(var c in a.observe)b.push(c)}if(a.publish){var b=a._publishNames=[];for(var c in a.publish)b.push(c)}},publishProperties:function(a,b){var c=a.publish;c&&(this.requireProperties(c,a,b),a._publishLC=this.lowerCaseMap(c))},requireProperties:function(a,b,c){for(var d in a)void 0===b[d]&&void 0===c[d]&&(b[d]=a[d])},lowerCaseMap:function(a){var b={};for(var c in a)b[c.toLowerCase()]=c;return b}};a.api.declaration.properties=b}(Polymer),function(a){var b="attributes",c={inheritAttributesObjects:function(a){this.inheritObject(a,"publishLC"),this.inheritObject(a,"_instanceAttributes")},publishAttributes:function(a,c){var d=this.getAttribute(b);if(d)for(var e,f=a.publish||(a.publish={}),g=d.split(d.indexOf(",")>=0?",":" "),h=0,i=g.length;i>h;h++)e=g[h].trim(),e&&void 0===f[e]&&void 0===c[e]&&(f[e]=null)},accumulateInstanceAttributes:function(){for(var a,b=this.prototype._instanceAttributes,c=this.attributes,d=0,e=c.length;e>d&&(a=c[d]);d++)this.isInstanceAttribute(a.name)&&(b[a.name]=a.value)},isInstanceAttribute:function(a){return!this.blackList[a]&&"on-"!==a.slice(0,3)},blackList:{name:1,"extends":1,constructor:1,noscript:1}};c.blackList[b]=1,a.api.declaration.attributes=c}(Polymer),function(a){function b(a){if(!Object.__proto__){var b=Object.getPrototypeOf(a);a.__proto__=b,d(b)&&(b.__proto__=Object.getPrototypeOf(b))}}var c=a.api,d=a.isBase,e=a.extend,f={register:function(a,b){this.prototype=this.buildPrototype(a,b),this.prototype.element=this,this.desugar(a,b),this.registerPrototype(a,b),this.publishConstructor()},buildPrototype:function(c,d){var e=a.getRegisteredPrototype(c),f=this.generateBasePrototype(d);return this.publishAttributes(e,f),this.publishProperties(e,f),this.inferObservers(e),this.inheritMetaData(e,f),e=this.chainObject(e,f),this.optimizePropertyMaps(e),b(e),e},inheritMetaData:function(a,b){this.inheritObject("observe",a,b),this.inheritObject("publish",a,b),this.inheritObject("_publishLC",a,b),this.inheritObject("_instanceAttributes",a,b),this.inheritObject("eventDelegates",a,b)},desugar:function(a,b){this.accumulateInstanceAttributes(),this.parseHostEvents(),this.installSheets(),this.adjustShadowElement(),this.addResolvePathApi(),window.ShadowDOMPolyfill&&Platform.ShadowCSS.shimStyling(this.templateContent(),a,b),this.prototype.registerCallback&&this.prototype.registerCallback(this)},adjustShadowElement:function(){if(!window.ShadowDOMPolyfill){var a=this.templateContent();if(a)for(var b,c=a.querySelectorAll("shadow"),d=0,e=c.length;e>d&&(b=c[d]);d++)b.children.length||b.appendChild(document.createElement("content"))}},publishConstructor:function(){var a=this.getAttribute("constructor");a&&(window[a]=this.ctor)},generateBasePrototype:function(a){var b=this.findBasePrototype(a);if(!b){var b=HTMLElement.getPrototypeForTag(a);b=this.ensureBaseApi(b),memoizedBases[a]=b}return b},findBasePrototype:function(a){return memoizedBases[a]},ensureBaseApi:function(a){if(!a.PolymerBase){a=Object.create(a);for(var b in c.instance)e(a,c.instance[b])}return a},inheritObject:function(a,b,c){var d=b[a]||{};b[a]=this.chainObject(d,c[a])},registerPrototype:function(a,b){var c={prototype:this.prototype},d=this.findTypeExtension(b);d&&(c.extends=d),this.ctor=document.register(a,c),this.prototype.constructor=this.ctor,HTMLElement.register(a,this.prototype)},findTypeExtension:function(a){if(a&&a.indexOf("-")<0)return a;var b=this.findBasePrototype(a);return b.element?this.findTypeExtension(b.element.extends):void 0}};f.chainObject=Object.__proto__?function(a,b){return a&&b&&a!==b&&(a.__proto__=b),a}:function(a,b){if(a&&b&&a!==b){var c=Object.create(b);a=e(c,a)}return a},memoizedBases={},c.declaration.prototype=f}(Polymer),function(a){function b(a,b){k[a]=b||{},d(a)}function c(a){return k[a]}function d(a){l[a]&&(l[a].registerWhenReady(),delete l[a])}function e(a){n[a]=!0;var b=m[a];b&&(b.forEach(function(a){a.registerWhenReady()}),delete m[a])}function f(a){return n[a]}function g(a){window.HTMLImports&&!HTMLImports.readyTime?addEventListener("HTMLImportsLoaded",a):a()}var h=a.extend,i=a.api.declaration,j=h(Object.create(HTMLElement.prototype),{createdCallback:function(){this.name=this.getAttribute("name"),this.extends=this.getAttribute("extends"),this.registerWhenReady()},registerWhenReady:function(){if(!this.waitingForPrototype(this.name)){var a=this.extends;this.waitingForExtendee(a)||(document.contains(this)?g(function(){this._register(a)}.bind(this)):this._register(a))}},_register:function(a){this.register(this.name,a),e(this.name)},waitingForPrototype:function(a){if(!c(a)){if(l[a]=this,this.hasAttribute("noscript"))if(window.CustomElements&&!CustomElements.useNative)b(a);else{var d=document.createElement("script");d.textContent="Polymer('"+a+"');",this.appendChild(d)}return!0}},waitingForExtendee:function(a){return a&&a.indexOf("-")>=0&&!f(a)?((m[a]=m[a]||[]).push(this),!0):void 0}});Object.keys(i).forEach(function(a){h(j,i[a])});var k={},l={},m={},n={};a.getRegisteredPrototype=c,h(b,a),window.Polymer=b,document.register("polymer-element",{prototype:j})}(Polymer);
+<script>/**
+ * @license
+ * Copyright (c) 2012-2014 The Polymer Authors. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *    * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *    * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+// @version: 0.2.1-c690632
+Polymer={},"function"==typeof window.Polymer&&(Polymer={}),function(a){function b(a,b){return a&&b&&Object.getOwnPropertyNames(b).forEach(function(c){var d=Object.getOwnPropertyDescriptor(b,c);d&&(Object.defineProperty(a,c,d),"function"==typeof d.value&&(d.value.nom=c))}),a}a.extend=b}(Polymer),function(a){function b(a,b,d){return a?a.stop():a=new c(this),a.go(b,d),a}var c=function(a){this.context=a,this.boundComplete=this.complete.bind(this)};c.prototype={go:function(a,b){this.callback=a;var c;b?(c=setTimeout(this.boundComplete,b),this.handle=function(){clearTimeout(c)}):(c=requestAnimationFrame(this.boundComplete),this.handle=function(){cancelAnimationFrame(c)})},stop:function(){this.handle&&(this.handle(),this.handle=null)},complete:function(){this.handle&&(this.stop(),this.callback.call(this.context))}},a.job=b}(Polymer),function(){var a={};HTMLElement.register=function(b,c){a[b]=c},HTMLElement.getPrototypeForTag=function(b){var c=b?a[b]:HTMLElement.prototype;return c||Object.getPrototypeOf(document.createElement(b))};var b=Event.prototype.stopPropagation;Event.prototype.stopPropagation=function(){this.cancelBubble=!0,b.apply(this,arguments)}}(Polymer),function(a){function b(a){var c=b.caller,g=c.nom,h=c._super;if(h||(g||(g=c.nom=e.call(this,c)),g||console.warn("called super() on a method not installed declaratively (has no .nom property)"),h=d(c,g,f(this))),h){var i=h[g];return i._super||d(i,g,h),i.apply(this,a||[])}}function c(a,b,c){for(;a;){if(a[b]!==c&&a[b])return a;a=f(a)}}function d(a,b,d){return a._super=c(d,b,a),a._super&&(a._super[b].nom=b),a._super}function e(a){for(var b=this.__proto__;b&&b!==HTMLElement.prototype;){for(var c,d=Object.getOwnPropertyNames(b),e=0,f=d.length;f>e&&(c=d[e]);e++){var g=Object.getOwnPropertyDescriptor(b,c);if("function"==typeof g.value&&g.value===a)return c}b=b.__proto__}}function f(a){return a.__proto__}a.super=b}(Polymer),function(a){function b(a,b){var d=typeof b;return b instanceof Date&&(d="date"),c[d](a,b)}var c={string:function(a){return a},date:function(a){return new Date(Date.parse(a)||Date.now())},"boolean":function(a){return""===a?!0:"false"===a?!1:!!a},number:function(a){var b=parseFloat(a);return 0===b&&(b=parseInt(a)),isNaN(b)?a:b},object:function(a,b){if(null===b)return a;try{return JSON.parse(a.replace(/'/g,'"'))}catch(c){return a}},"function":function(a,b){return b}};a.deserializeValue=b}(Polymer),function(a){var b=a.extend,c={};c.declaration={},c.instance={},c.publish=function(a,c){for(var d in a)b(c,a[d])},a.api=c}(Polymer),function(a){var b={async:function(a,b,c){Platform.flush(),b=b&&b.length?b:[b];var d=function(){(this[a]||a).apply(this,b)}.bind(this),e=c?setTimeout(d,c):requestAnimationFrame(d);return c?e:~e},cancelAsync:function(a){0>a?cancelAnimationFrame(~a):clearTimeout(a)},fire:function(a,b,c,d,e){var f=c||this,b=b||{},g=new CustomEvent(a,{bubbles:void 0!==d?d:!0,cancelable:void 0!==e?e:!0,detail:b});return f.dispatchEvent(g),g},asyncFire:function(){this.async("fire",arguments)},classFollows:function(a,b,c){b&&b.classList.remove(c),a&&a.classList.add(c)}},c=function(){},d={};b.asyncMethod=b.async,a.api.instance.utils=b,a.nop=c,a.nob=d}(Polymer),function(a){var b=window.logFlags||{},c="on-",d={EVENT_PREFIX:c,addHostListeners:function(){var a=this.eventDelegates;b.events&&Object.keys(a).length>0&&console.log("[%s] addHostListeners:",this.localName,a);var d,e,f=this;for(var g in a)e=c+g,(d=PolymerExpressions.prepareEventBinding(Path.get(a[g]),e,{resolveEventHandler:function(a,b){var c=b.getValueFrom(f);return c?c.bind(f):void 0}}))(this,this,!1)},dispatchMethod:function(a,c,d){if(a){b.events&&console.group("[%s] dispatch [%s]",a.localName,c);var e="function"==typeof c?c:a[c];e&&e[d?"apply":"call"](a,d),b.events&&console.groupEnd(),Platform.flush()}}};a.api.instance.events=d}(Polymer),function(a){var b={copyInstanceAttributes:function(){var a=this._instanceAttributes;for(var b in a)this.hasAttribute(b)||this.setAttribute(b,a[b])},takeAttributes:function(){if(this._publishLC)for(var a,b=0,c=this.attributes,d=c.length;(a=c[b])&&d>b;b++)this.attributeToProperty(a.name,a.value)},attributeToProperty:function(b,c){var b=this.propertyForAttribute(b);if(b){if(c&&c.search(a.bindPattern)>=0)return;var d=this[b],c=this.deserializeValue(c,d);c!==d&&(this[b]=c)}},propertyForAttribute:function(a){var b=this._publishLC&&this._publishLC[a];return b},deserializeValue:function(b,c){return a.deserializeValue(b,c)},serializeValue:function(a,b){return"boolean"===b?a?"":void 0:"object"!==b&&"function"!==b&&void 0!==a?a:void 0},reflectPropertyToAttribute:function(a){var b=typeof this[a],c=this.serializeValue(this[a],b);void 0!==c?this.setAttribute(a,c):"boolean"===b&&this.removeAttribute(a)}};a.api.instance.attributes=b}(Polymer),function(a){function b(a,b,d){c.bind&&console.log(e,inB.localName||"object",inPath,a.localName,b);var f=d.discardChanges();return(null===f||void 0===f)&&d.setValue(a[b]),Observer.defineComputedProperty(a,b,d)}var c=window.logFlags||{},d={observeProperties:function(){var a=this._observeNames,b=this._publishNames;if(a&&a.length||b&&b.length){var c=this._propertyObserver=new CompoundObserver;this.registerObservers([c]);for(var d,e=0,f=a.length;f>e&&(d=a[e]);e++){c.addPath(this,d);var g=Object.getOwnPropertyDescriptor(this.__proto__,d);g&&g.value&&this.observeArrayValue(d,g.value,null)}for(var d,e=0,f=b.length;f>e&&(d=b[e]);e++)this.observe&&void 0!==this.observe[d]||c.addPath(this,d);c.open(this.notifyPropertyChanges,this)}},notifyPropertyChanges:function(a,b,c){var d,e,f={};for(var g in b)d=c[2*g+1],void 0!==this.publish[d]&&this.reflectPropertyToAttribute(d),e=this.observe[d],e&&(this.observeArrayValue(d,a[g],b[g]),f[e]||(f[e]=!0,this.invokeMethod(e,[b[g],a[g],arguments])))},observeArrayValue:function(a,b,d){var e=this.observe[a];if(e&&(Array.isArray(d)&&(c.observe&&console.log("[%s] observeArrayValue: unregister observer [%s]",this.localName,a),this.closeNamedObserver(a+"__array")),Array.isArray(b))){c.observe&&console.log("[%s] observeArrayValue: register observer [%s]",this.localName,a,b);var f=new ArrayObserver(b);f.open(function(a,b){this.invokeMethod(e,[b])},this),this.registerNamedObserver(a+"__array",f)}},bindProperty:function(a,c){return b(this,a,c)},invokeMethod:function(a,b){var c=this[a]||a;"function"==typeof c&&c.apply(this,b)},registerObservers:function(a){this._observers.push(a)},closeObservers:function(){for(var a=0,b=this._observers.length;b>a;a++)this.closeObserverArray(this._observers[a]);this._observers=[]},closeObserverArray:function(a){for(var b,c=0,d=a.length;d>c;c++)b=a[c],b&&b.close&&b.close()},registerNamedObserver:function(a,b){var c=this._namedObservers||(this._namedObservers={});c[a]=b},closeNamedObserver:function(a){var b=this._namedObservers;return b&&b[a]?(b[a].close(),b[a]=null,!0):void 0},closeNamedObservers:function(){if(this._namedObservers){for(var a,b,c=Object.keys(this._namedObservers),d=0,e=c.length;e>d&&(a=c[d]);d++)b=this._namedObservers[a],b.close();this._namedObservers={}}}},e="[%s]: bindProperties: [%s] to [%s].[%s]";a.api.instance.properties=d}(Polymer),function(a){function b(a){for(;a.parentNode;){if(a.lightDomController)return a;a=a.parentNode}return a.host}var c=window.logFlags||0,d=(a.api.instance.events,new PolymerExpressions);d.resolveEventHandler=function(a,c,d){var e=b(d);if(e){var f=c.getValueFrom(e);if(f)return f.bind(e)}};var e={syntax:d,instanceTemplate:function(a){var b=a.createInstance(this,this.syntax);return this.registerObservers(b.bindings_),b},bind:function(a,b){this._elementPrepared||this.prepareElement();var c=this.propertyForAttribute(a);if(c){var d=this.bindProperty(c,b);return this.reflectPropertyToAttribute(c),Platform.enableBindingsReflection&&(d.path=b.path_,this.bindings_=this.bindings_||{},this.bindings_[a]=d),d}return this.mixinSuper(arguments)},asyncUnbindAll:function(){this._unbound||(c.unbind&&console.log("[%s] asyncUnbindAll",this.localName),this._unbindAllJob=this.job(this._unbindAllJob,this.unbindAll,0))},unbindAll:function(){this._unbound||(this.closeObservers(),this.closeNamedObservers(),this._unbound=!0)},cancelUnbindAll:function(){return this._unbound?void(c.unbind&&console.warn("[%s] already unbound, cannot cancel unbindAll",this.localName)):(c.unbind&&console.log("[%s] cancelUnbindAll",this.localName),void(this._unbindAllJob&&(this._unbindAllJob=this._unbindAllJob.stop())))}},f=/\{\{([^{}]*)}}/;a.bindPattern=f,a.api.instance.mdv=e}(Polymer),function(a){function b(a){return a.hasOwnProperty("PolymerBase")}function c(){}var d=0,e={PolymerBase:!0,job:Polymer.job,"super":Polymer.super,created:function(){},ready:function(){},createdCallback:function(){this.created(),(this.ownerDocument.defaultView||this.alwaysPrepare||d>0)&&this.prepareElement()},prepareElement:function(){this._elementPrepared=!0,this.shadowRoots={},this._observers=[],this.observeProperties(),this.copyInstanceAttributes(),this.takeAttributes(),this.addHostListeners(),d++,this.parseDeclarations(this.__proto__),d--,this.removeAttribute("unresolved"),this.ready()},attachedCallback:function(){this._elementPrepared||this.prepareElement(),this.cancelUnbindAll(!0),this.attached&&this.attached(),this.enteredView&&this.enteredView(),this.hasBeenAttached||(this.hasBeenAttached=!0,this.domReady&&this.async("domReady"))},detachedCallback:function(){this.preventDispose||this.asyncUnbindAll(),this.detached&&this.detached(),this.leftView&&this.leftView()},enteredViewCallback:function(){this.attachedCallback()},leftViewCallback:function(){this.detachedCallback()},enteredDocumentCallback:function(){this.attachedCallback()},leftDocumentCallback:function(){this.detachedCallback()},parseDeclarations:function(a){a&&a.element&&(this.parseDeclarations(a.__proto__),a.parseDeclaration.call(this,a.element))},parseDeclaration:function(a){var b=this.fetchTemplate(a);if(b){var c=this.shadowFromTemplate(b);this.shadowRoots[a.name]=c}},fetchTemplate:function(a){return a.querySelector("template")},shadowFromTemplate:function(a){if(a){var b=this.createShadowRoot();b.resetStyleInheritance=this.resetStyleInheritance;var c=this.instanceTemplate(a);return b.appendChild(c),this.shadowRootReady(b,a),b}},lightFromTemplate:function(a){if(a){this.lightDomController=!0;var b=this.instanceTemplate(a);return this.appendChild(b),this.shadowRootReady(this,a),b}},shadowRootReady:function(a){this.marshalNodeReferences(a),PointerGestures.register(a)},marshalNodeReferences:function(a){var b=this.$=this.$||{};if(a)for(var c,d=a.querySelectorAll("[id]"),e=0,f=d.length;f>e&&(c=d[e]);e++)b[c.id]=c},attributeChangedCallback:function(a){"class"!==a&&"style"!==a&&this.attributeToProperty(a,this.getAttribute(a)),this.attributeChanged&&this.attributeChanged.apply(this,arguments)},onMutation:function(a,b){var c=new MutationObserver(function(a){b.call(this,c,a),c.disconnect()}.bind(this));c.observe(a,{childList:!0,subtree:!0})}};c.prototype=e,e.constructor=c,a.Base=c,a.isBase=b,a.api.instance.base=e}(Polymer),function(a){function b(a){return a.__proto__}function c(a,b){var c="",d=!1;b&&(c=b.localName,d=b.hasAttribute("is"));var e=Platform.ShadowCSS.makeScopeSelector(c,d);return Platform.ShadowCSS.shimCssText(a,e)}var d=(window.logFlags||{},"element"),e="controller",f={STYLE_SCOPE_ATTRIBUTE:d,installControllerStyles:function(){var a=this.findStyleScope();if(a&&!this.scopeHasNamedStyle(a,this.localName)){for(var c=b(this),d="";c&&c.element;)d+=c.element.cssTextForScope(e),c=b(c);d&&this.installScopeCssText(d,a)}},installScopeStyle:function(a,b,c){var c=this.findStyleScope(c),b=b||"";if(c&&!this.scopeHasNamedStyle(c,this.localName+b)){var d="";if(a instanceof Array)for(var e,f=0,g=a.length;g>f&&(e=a[f]);f++)d+=e.textContent+"\n\n";else d=a.textContent;this.installScopeCssText(d,c,b)}},installScopeCssText:function(a,b,d){if(b=b||this.findStyleScope(),d=d||"",b){window.ShadowDOMPolyfill&&(a=c(a,b.host));var f=this.element.cssTextToScopeStyle(a,e);Polymer.applyStyleToScope(f,b),b._scopeStyles[this.localName+d]=!0}},findStyleScope:function(a){for(var b=a||this;b.parentNode;)b=b.parentNode;return b},scopeHasNamedStyle:function(a,b){return a._scopeStyles=a._scopeStyles||{},a._scopeStyles[b]}};a.api.instance.styles=f}(Polymer),function(a){function b(a,b){if(f[a])throw"Already registered (Polymer) prototype for element "+a;e(a,b),d(a)}function c(a,b){h[a]=b}function d(a){h[a]&&(h[a].registerWhenReady(),delete h[a])}function e(a,b){return i[a]=b||{}}function f(a){return i[a]}var g=a.extend,h=(a.api,{}),i={};a.getRegisteredPrototype=f,a.waitingForPrototype=c,window.Polymer=b,g(Polymer,a);var j=Platform.deliverDeclarations();if(j)for(var k,l=0,m=j.length;m>l&&(k=j[l]);l++)b.apply(null,k)}(Polymer),function(a){var b={resolveElementPaths:function(a){Platform.urlResolver.resolveDom(a)},addResolvePathApi:function(){var a=this.getAttribute("assetpath")||"",b=new URL(a,this.ownerDocument.baseURI);this.prototype.resolvePath=function(a,c){var d=new URL(a,c||b);return d.href}}};a.api.declaration.path=b}(Polymer),function(a){function b(a,b){var c=new URL(a.getAttribute("href"),b).href;return"@import '"+c+"';"}function c(a,b){if(a){b===document&&(b=document.head),window.ShadowDOMPolyfill&&(b=document.head);var c=d(a.textContent),e=a.getAttribute(h);e&&c.setAttribute(h,e),b.appendChild(c)}}function d(a,b){b=b||document,b=b.createElement?b:b.ownerDocument;var c=b.createElement("style");return c.textContent=a,c}function e(a){return a&&a.__resource||""}function f(a,b){return p?p.call(a,b):void 0}var g=(window.logFlags||{},a.api.instance.styles),h=g.STYLE_SCOPE_ATTRIBUTE,i="style",j="@import",k="link[rel=stylesheet]",l="global",m="polymer-scope",n={loadStyles:function(a){var b=this.templateContent();b&&this.convertSheetsToStyles(b);var c=this.findLoadableStyles(b);c.length?Platform.styleResolver.loadStyles(c,a):a&&a()},convertSheetsToStyles:function(a){for(var c,e,f=a.querySelectorAll(k),g=0,h=f.length;h>g&&(c=f[g]);g++)e=d(b(c,this.ownerDocument.baseURI),this.ownerDocument),this.copySheetAttributes(e,c),c.parentNode.replaceChild(e,c)},copySheetAttributes:function(a,b){for(var c,d=0,e=b.attributes,f=e.length;(c=e[d])&&f>d;d++)"rel"!==c.name&&"href"!==c.name&&a.setAttribute(c.name,c.value)},findLoadableStyles:function(a){var b=[];if(a)for(var c,d=a.querySelectorAll(i),e=0,f=d.length;f>e&&(c=d[e]);e++)c.textContent.match(j)&&b.push(c);return b},installSheets:function(){this.cacheSheets(),this.cacheStyles(),this.installLocalSheets(),this.installGlobalStyles()},cacheSheets:function(){this.sheets=this.findNodes(k),this.sheets.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},cacheStyles:function(){this.styles=this.findNodes(i+"["+m+"]"),this.styles.forEach(function(a){a.parentNode&&a.parentNode.removeChild(a)})},installLocalSheets:function(){var a=this.sheets.filter(function(a){return!a.hasAttribute(m)}),b=this.templateContent();if(b){var c="";if(a.forEach(function(a){c+=e(a)+"\n"}),c){var f=d(c,this.ownerDocument);b.insertBefore(f,b.firstChild)}}},findNodes:function(a,b){var c=this.querySelectorAll(a).array(),d=this.templateContent();if(d){var e=d.querySelectorAll(a).array();c=c.concat(e)}return b?c.filter(b):c},templateContent:function(){var a=this.querySelector("template");return a&&templateContent(a)},installGlobalStyles:function(){var a=this.styleForScope(l);c(a,document.head)},cssTextForScope:function(a){var b="",c="["+m+"="+a+"]",d=function(a){return f(a,c)},g=this.sheets.filter(d);g.forEach(function(a){b+=e(a)+"\n\n"});var h=this.styles.filter(d);return h.forEach(function(a){b+=a.textContent+"\n\n"}),b},styleForScope:function(a){var b=this.cssTextForScope(a);return this.cssTextToScopeStyle(b,a)},cssTextToScopeStyle:function(a,b){if(a){var c=d(a);return c.setAttribute(h,this.getAttribute("name")+"-"+b),c}}},o=HTMLElement.prototype,p=o.matches||o.matchesSelector||o.webkitMatchesSelector||o.mozMatchesSelector;a.api.declaration.styles=n,a.applyStyleToScope=c}(Polymer),function(a){var b=(window.logFlags||{},a.api.instance.events),c=b.EVENT_PREFIX,d={parseHostEvents:function(){var a=this.prototype.eventDelegates;this.addAttributeDelegates(a)},addAttributeDelegates:function(a){for(var b,c=0;b=this.attributes[c];c++)this.hasEventPrefix(b.name)&&(a[this.removeEventPrefix(b.name)]=b.value.replace("{{","").replace("}}","").trim())},hasEventPrefix:function(a){return a&&"o"===a[0]&&"n"===a[1]&&"-"===a[2]},removeEventPrefix:function(a){return a.slice(e)}},e=c.length;a.api.declaration.events=d}(Polymer),function(a){var b={inferObservers:function(a){var b,c=a.observe;for(var d in a)"Changed"===d.slice(-7)&&(c||(c=a.observe={}),b=d.slice(0,-7),c[b]=c[b]||d)},explodeObservers:function(a){var b=a.observe;if(b){var c={};for(var d in b)for(var e,f=d.split(" "),g=0;e=f[g];g++)c[e]=b[d];a.observe=c}},optimizePropertyMaps:function(a){if(a.observe){var b=a._observeNames=[];for(var c in a.observe)for(var d,e=c.split(" "),f=0;d=e[f];f++)b.push(d)}if(a.publish){var b=a._publishNames=[];for(var c in a.publish)b.push(c)}},publishProperties:function(a,b){var c=a.publish;c&&(this.requireProperties(c,a,b),a._publishLC=this.lowerCaseMap(c))},requireProperties:function(a,b,c){for(var d in a)void 0===b[d]&&void 0===c[d]&&(b[d]=a[d])},lowerCaseMap:function(a){var b={};for(var c in a)b[c.toLowerCase()]=c;return b}};a.api.declaration.properties=b}(Polymer),function(a){var b="attributes",c=/\s|,/,d={inheritAttributesObjects:function(a){this.inheritObject(a,"publishLC"),this.inheritObject(a,"_instanceAttributes")},publishAttributes:function(a,d){var e=this.getAttribute(b);if(e)for(var f,g=a.publish||(a.publish={}),h=e.split(c),i=0,j=h.length;j>i;i++)f=h[i].trim(),f&&void 0===g[f]&&void 0===d[f]&&(g[f]=null)},accumulateInstanceAttributes:function(){for(var a,b=this.prototype._instanceAttributes,c=this.attributes,d=0,e=c.length;e>d&&(a=c[d]);d++)this.isInstanceAttribute(a.name)&&(b[a.name]=a.value)},isInstanceAttribute:function(a){return!this.blackList[a]&&"on-"!==a.slice(0,3)},blackList:{name:1,"extends":1,constructor:1,noscript:1,assetpath:1,"cache-csstext":1}};d.blackList[b]=1,a.api.declaration.attributes=d}(Polymer),function(a){function b(a){if(!Object.__proto__){var b=Object.getPrototypeOf(a);a.__proto__=b,d(b)&&(b.__proto__=Object.getPrototypeOf(b))}}var c=a.api,d=a.isBase,e=a.extend,f={register:function(a,b){this.buildPrototype(a,b),this.registerPrototype(a,b),this.publishConstructor()},buildPrototype:function(b,c){var d=a.getRegisteredPrototype(b),e=this.generateBasePrototype(c);this.desugarBeforeChaining(d,e),this.prototype=this.chainPrototypes(d,e),this.desugarAfterChaining(b,c)},desugarBeforeChaining:function(a,b){a.element=this,this.publishAttributes(a,b),this.publishProperties(a,b),this.inferObservers(a),this.explodeObservers(a)},chainPrototypes:function(a,c){this.inheritMetaData(a,c);var d=this.chainObject(a,c);return b(d),d},inheritMetaData:function(a,b){this.inheritObject("observe",a,b),this.inheritObject("publish",a,b),this.inheritObject("_publishLC",a,b),this.inheritObject("_instanceAttributes",a,b),this.inheritObject("eventDelegates",a,b)},desugarAfterChaining:function(a,b){this.optimizePropertyMaps(this.prototype),this.installSheets(),this.resolveElementPaths(this),this.accumulateInstanceAttributes(),this.parseHostEvents(),this.addResolvePathApi(),window.ShadowDOMPolyfill&&Platform.ShadowCSS.shimStyling(this.templateContent(),a,b),this.prototype.registerCallback&&this.prototype.registerCallback(this)},publishConstructor:function(){var a=this.getAttribute("constructor");a&&(window[a]=this.ctor)},generateBasePrototype:function(a){var b=this.findBasePrototype(a);if(!b){var b=HTMLElement.getPrototypeForTag(a);b=this.ensureBaseApi(b),g[a]=b}return b},findBasePrototype:function(a){return g[a]},ensureBaseApi:function(a){if(a.PolymerBase)return a;var b=Object.create(a);return c.publish(c.instance,b),this.mixinMethod(b,a,c.instance.mdv,"bind"),b},mixinMethod:function(a,b,c,d){var e=function(a){return b[d].apply(this,a)};a[d]=function(){return this.mixinSuper=e,c[d].apply(this,arguments)}},inheritObject:function(a,b,c){var d=b[a]||{};b[a]=this.chainObject(d,c[a])},registerPrototype:function(a,b){var c={prototype:this.prototype},d=this.findTypeExtension(b);d&&(c.extends=d),HTMLElement.register(a,this.prototype),this.ctor=document.registerElement(a,c)},findTypeExtension:function(a){if(a&&a.indexOf("-")<0)return a;var b=this.findBasePrototype(a);return b.element?this.findTypeExtension(b.element.extends):void 0}},g={};f.chainObject=Object.__proto__?function(a,b){return a&&b&&a!==b&&(a.__proto__=b),a}:function(a,b){if(a&&b&&a!==b){var c=Object.create(b);a=e(c,a)}return a},c.declaration.prototype=f}(Polymer),function(a){function b(a){return document.contains(a)?g:f}function c(){return f.length?f[0]:g[0]}function d(a){e.waitToReady=!0,CustomElements.ready=!1,HTMLImports.whenImportsReady(function(){e.addReadyCallback(a),e.waitToReady=!1,e.check()})}var e={wait:function(a,b,c){return-1===this.indexOf(a)&&(this.add(a),a.__check=b,a.__go=c),0!==this.indexOf(a)},add:function(a){b(a).push(a)},indexOf:function(a){var c=b(a).indexOf(a);return c>=0&&document.contains(a)&&(c+=HTMLImports.useNative||HTMLImports.ready?f.length:1e9),c},go:function(a){var b=this.remove(a);b&&(b.__go.call(b),b.__check=b.__go=null,this.check())},remove:function(a){var c=this.indexOf(a);if(0===c)return b(a).shift()},check:function(){var a=this.nextElement();return a&&a.__check.call(a),this.canReady()?(this.ready(),!0):void 0},nextElement:function(){return c()},canReady:function(){return!this.waitToReady&&this.isEmpty()},isEmpty:function(){return!f.length&&!g.length},ready:function(){if(CustomElements.ready===!1&&(CustomElements.upgradeDocumentTree(document),CustomElements.ready=!0),h)for(var a;h.length;)(a=h.shift())()},addReadyCallback:function(a){a&&h.push(a)},waitToReady:!0},f=[],g=[],h=[];document.addEventListener("WebComponentsReady",function(){CustomElements.ready=!1}),a.queue=e,a.whenPolymerReady=d}(Polymer),function(a){function b(a,b){a?(document.head.appendChild(a),d(b)):b&&b()}function c(a,c){if(a&&a.length){for(var d,e,f=document.createDocumentFragment(),g=0,h=a.length;h>g&&(d=a[g]);g++)e=document.createElement("link"),e.rel="import",e.href=d,f.appendChild(e);b(f,c)}else c&&c()}var d=a.whenPolymerReady;a.import=c,a.importElements=b}(Polymer),function(a){function b(a){return Boolean(HTMLElement.getPrototypeForTag(a))}function c(a){return a&&a.indexOf("-")>=0}var d=a.extend,e=a.api,f=a.queue,g=a.whenPolymerReady,h=a.getRegisteredPrototype,i=a.waitingForPrototype,j=d(Object.create(HTMLElement.prototype),{createdCallback:function(){this.getAttribute("name")&&this.init()},init:function(){this.name=this.getAttribute("name"),this.extends=this.getAttribute("extends"),this.loadResources(),this.registerWhenReady()},registerWhenReady:function(){this.registered||this.waitingForPrototype(this.name)||this.waitingForQueue()||this.waitingForResources()||f.go(this)},_register:function(){c(this.extends)&&!b(this.extends)&&console.warn("%s is attempting to extend %s, an unregistered element or one that was not registered with Polymer.",this.name,this.extends),this.register(this.name,this.extends),this.registered=!0},waitingForPrototype:function(a){return h(a)?void 0:(i(a,this),this.handleNoScript(a),!0)},handleNoScript:function(a){if(this.hasAttribute("noscript")&&!this.noscript)if(this.noscript=!0,window.CustomElements&&!CustomElements.useNative)Polymer(a);else{var b=document.createElement("script");b.textContent="Polymer('"+a+"');",this.appendChild(b)}},waitingForResources:function(){return this._needsResources},waitingForQueue:function(){return f.wait(this,this.registerWhenReady,this._register)},loadResources:function(){this._needsResources=!0,this.loadStyles(function(){this._needsResources=!1,this.registerWhenReady()}.bind(this))}});e.publish(e.declaration,j),a.getRegisteredPrototype=h,g(function(){document.body.removeAttribute("unresolved"),document.dispatchEvent(new CustomEvent("polymer-ready",{bubbles:!0}))}),document.registerElement("polymer-element",{prototype:j})}(Polymer);
 //# sourceMappingURL=polymer.js.map</script>
 <!-- <link rel="import" href="../polymer-dev/polymer.html"> -->
 <!DOCTYPE html>
diff --git a/tools/perf/page_sets/top_10.py b/tools/perf/page_sets/top_10.py
new file mode 100644
index 0000000..5ed17cc
--- /dev/null
+++ b/tools/perf/page_sets/top_10.py
@@ -0,0 +1,126 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page.actions.navigate import NavigateAction
+from telemetry.page.actions.javascript import JavascriptAction
+from telemetry.page.actions.scroll import ScrollAction
+from telemetry.page.actions.wait import WaitAction
+from telemetry.page.page_set import PageSet
+from telemetry.page.page import Page
+
+
+class SimpleScrollPage(Page):
+  def __init__(self, url='', credentials=''):
+    super(SimpleScrollPage, self).__init__(url, '')
+    self.credentials = credentials
+
+  def RunSmoothness(self, action_runner):
+    action_runner.RunAction(ScrollAction())
+
+  def RunNavigateSteps(self, action_runner):
+    action_runner.RunAction(NavigateAction())
+
+
+class Google(SimpleScrollPage):
+  def __init__(self):
+    super(Google, self).__init__(
+      'https://www.google.com/#hl=en&q=barack+obama')
+
+  def RunNavigateSteps(self, action_runner):
+    super(Google, self).RunNavigateSteps(action_runner)
+    action_runner.RunAction(WaitAction(
+      {'condition': 'element', 'text': 'Next'}))
+
+
+class Gmail(SimpleScrollPage):
+  def __init__(self):
+    super(Gmail, self).__init__(
+      'https://mail.google.com/mail/', credentials='google')
+
+  def RunNavigateSteps(self, action_runner):
+    super(Gmail, self).RunNavigateSteps(action_runner)
+    action_runner.RunAction(WaitAction(
+      {'javascript' : 'window.gmonkey !== undefined &&'
+       'document.getElementById("gb") !== null'}))
+
+
+class GoogleCalendar(SimpleScrollPage):
+  def __init__(self):
+    super(GoogleCalendar, self).__init__(
+      'https://www.google.com/calendar/', credentials='google')
+
+  def RunNavigateSteps(self, action_runner):
+    super(GoogleCalendar, self).RunNavigateSteps(action_runner)
+    action_runner.RunAction(JavascriptAction(
+      { 'expression' :
+       '(function() { var elem = document.createElement("meta");'
+      'elem.name="viewport";'
+      'elem.content="initial-scale=1";'
+      'document.body.appendChild(elem); })();'}))
+    action_runner.RunAction(WaitAction({'seconds' : 2}))
+    action_runner.RunAction(WaitAction({
+      'condition' : 'element', 'selector' : 'div[class~="navForward"]'}))
+
+
+class Youtube(SimpleScrollPage):
+  def __init__(self):
+    super(Youtube, self).__init__(
+      'http://www.youtube.com', credentials='google')
+
+  def RunNavigateSteps(self, action_runner):
+    super(Youtube, self).RunNavigateSteps(action_runner)
+    action_runner.RunAction(WaitAction({'seconds' : 2}))
+
+
+class Facebook(SimpleScrollPage):
+  def __init__(self):
+    super(Facebook, self).__init__(
+      'http://www.facebook.com/barackobama', credentials='facebook')
+    self.name = "Facebook"
+
+  def RunNavigateSteps(self, action_runner):
+    super(Facebook, self).RunNavigateSteps(action_runner)
+    action_runner.RunAction(WaitAction(
+      {'condition': 'element', 'text': 'About'}))
+
+
+class Top10PageSet(PageSet):
+  def __init__(self):
+    super(Top10PageSet, self).__init__(
+      description='10 Pages chosen from Alexa top sites',
+      archive_data_file='data/top_10.json',
+      credentials_path='data/credentials.json',
+      user_agent_type='desktop')
+
+    # top google property; a google tab is often open
+    self.AddPage(Google())
+
+    # productivity, top google properties
+    self.AddPage(Gmail())
+
+    # productivity, top google properties
+    self.AddPage(GoogleCalendar())
+
+    # #3 (Alexa global)
+    self.AddPage(Youtube())
+
+    # top social, Public profile
+    self.AddPage(Facebook())
+
+    # #6 (Alexa) most visited worldwide,Picked an interesting page
+    wikipedia_page = SimpleScrollPage('http://en.wikipedia.org/wiki/Wikipedia')
+    wikipedia_page.name = "Wikipedia"
+    self.AddPage(wikipedia_page)
+
+    # #1 world commerce website by visits; #3 commerce in the US by time spent
+    self.AddPage(SimpleScrollPage('http://www.amazon.com'))
+
+    # #4 Alexa
+    self.AddPage(SimpleScrollPage('http://www.yahoo.com/'))
+
+    # #16 Alexa
+    self.AddPage(SimpleScrollPage('http://www.bing.com/'))
+
+    # #20 Alexa
+    self.AddPage(SimpleScrollPage('http://www.ask.com/'))
diff --git a/tools/perf/test-info.json b/tools/perf/test-info.json
index f6bd28a..3313092 100644
--- a/tools/perf/test-info.json
+++ b/tools/perf/test-info.json
@@ -101,7 +101,7 @@
   "media_perftests":{
     "description":"Microbenchmarks for media (media/) component.",
     "code":[
-      "chrome/src/media/media.gyp",
+      "chrome/src/media/media.gyp"
     ]
   },
   "memory.reload.2012Q3":{
diff --git a/tools/perf/unit-info.json b/tools/perf/unit-info.json
index 73a0c7c..28b294b 100644
--- a/tools/perf/unit-info.json
+++ b/tools/perf/unit-info.json
@@ -11,7 +11,7 @@
   "Celsius": {
     "improvement_direction": "down",
     "why": "Colder machines are faster."
-  }
+  },
   "commit_count": {
     "improvement_direction": "up",
     "why": "layer_tree_host_perftest"
@@ -70,25 +70,25 @@
     "improvement_direction": "down"
   },
   "mips": {
-    improvement_direction": "up",
+    "improvement_direction": "up",
     "why": "More instructions processed per time unit."
-  }
+  },
   "mpixels_sec": {
-    improvement_direction": "up",
+    "improvement_direction": "up",
     "why": "More pixels processed per time unit."
-  }
+  },
   "mtexel_sec": {
-    improvement_direction": "up",
+    "improvement_direction": "up",
     "why": "More texels processed per time unit."
-  }
+  },
   "mtri_sec": {
-    improvement_direction": "up",
+    "improvement_direction": "up",
     "why": "More triangles processed per time unit."
-  }
+  },
   "mvtx_sec": {
-    improvement_direction": "up",
+    "improvement_direction": "up",
     "why": "More vertices processed per time unit."
-  }
+  },
   "ms": {
     "improvement_direction": "down",
     "why": "Used in many Telemetry measurements. Fewer ms of time means faster."
diff --git a/tools/real_world_impact/nsfw_urls.py b/tools/real_world_impact/nsfw_urls.py
new file mode 100644
index 0000000..01977fc
--- /dev/null
+++ b/tools/real_world_impact/nsfw_urls.py
@@ -0,0 +1,79 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""NSFW urls in the Alexa top 2000 sites."""
+nsfw_urls = set([
+  "http://xhamster.com/",
+  "http://xvideos.com/",
+  "http://livejasmin.com/",
+  "http://pornhub.com/",
+  "http://redtube.com/",
+  "http://youporn.com/",
+  "http://xnxx.com/",
+  "http://tube8.com/",
+  "http://youjizz.com/",
+  "http://adultfriendfinder.com/",
+  "http://hardsextube.com/",
+  "http://yourlust.com/",
+  "http://drtuber.com/",
+  "http://beeg.com/",
+  "http://largeporntube.com/",
+  "http://nuvid.com/",
+  "http://bravotube.net/",
+  "http://spankwire.com/",
+  "http://discreethearts.com/",
+  "http://keezmovies.com/",
+  "http://xtube.com/",
+  "http://alphaporno.com/",
+  "http://4tube.com/",
+  "http://nudevista.com/",
+  "http://porntube.com/",
+  "http://xhamstercams.com/",
+  "http://porn.com/",
+  "http://video-one.com/",
+  "http://perfectgirls.net/",
+  "http://slutload.com/",
+  "http://sunporno.com/",
+  "http://tnaflix.com/",
+  "http://pornerbros.com/",
+  "http://h2porn.com/",
+  "http://adult-empire.com/",
+  "http://pornhublive.com/",
+  "http://sexitnow.com/",
+  "http://pornsharia.com/",
+  "http://freeones.com/",
+  "http://tubegalore.com/",
+  "http://xvideos.jp/",
+  "http://brazzers.com/",
+  "http://fapdu.com/",
+  "http://pornoxo.com/",
+  "http://extremetube.com/",
+  "http://hot-sex-tube.com/",
+  "http://xhamsterhq.com/",
+  "http://18andabused.com/",
+  "http://tubepleasure.com/",
+  "http://18schoolgirlz.com/",
+  "http://chaturbate.com/",
+  "http://motherless.com/",
+  "http://yobt.com/",
+  "http://empflix.com/",
+  "http://hellporno.com/",
+  "http://ashemaletube.com/",
+  "http://watchmygf.com/",
+  "http://redtubelive.com/",
+  "http://met-art.com/",
+  "http://gonzoxxxmovies.com/",
+  "http://shufuni.com/",
+  "http://vid2c.com/",
+  "http://dojki.com/",
+  "http://cerdas.com/",
+  "http://overthumbs.com/",
+  "http://xvideoslive.com/",
+  "http://playboy.com/",
+  "http://caribbeancom.com/",
+  "http://tubewolf.com/",
+  "http://xmatch.com/",
+  "http://ixxx.com/",
+  "http://nymphdate.com/",
+])
\ No newline at end of file
diff --git a/tools/real_world_impact/real_world_impact.py b/tools/real_world_impact/real_world_impact.py
new file mode 100755
index 0000000..144e72c
--- /dev/null
+++ b/tools/real_world_impact/real_world_impact.py
@@ -0,0 +1,554 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Tool for seeing the real world impact of a patch.
+#
+# Layout Tests can tell you whether something has changed, but this can help
+# you determine whether a subtle/controversial change is beneficial or not.
+#
+# It dumps the rendering of a large number of sites, both with and without a
+# patch being evaluated, then sorts them by greatest difference in rendering,
+# such that a human reviewer can quickly review the most impacted sites,
+# rather than having to manually try sites to see if anything changes.
+#
+# In future it might be possible to extend this to other kinds of differences,
+# e.g. page load times.
+
+import argparse
+from argparse import RawTextHelpFormatter
+from contextlib import closing
+import datetime
+import errno
+from distutils.spawn import find_executable
+from operator import itemgetter
+import multiprocessing
+import os
+import re
+from cStringIO import StringIO
+import subprocess
+import sys
+import textwrap
+import time
+from urllib2 import urlopen
+from urlparse import urlparse
+import webbrowser
+from zipfile import ZipFile
+
+from nsfw_urls import nsfw_urls
+
+action = None
+allow_js = False
+additional_content_shell_flags = ""
+chromium_src_root = ""
+chromium_out_dir = ""
+image_diff = ""
+content_shell = ""
+output_dir = ""
+num_sites = 100
+urls = []
+print_lock = multiprocessing.Lock()
+
+
+def MakeDirsIfNotExist(dir):
+  try:
+    os.makedirs(dir)
+  except OSError as e:
+    if e.errno != errno.EEXIST:
+      raise
+
+
+def SetupPathsAndOut():
+  global chromium_src_root, chromium_out_dir, output_dir
+  global image_diff, content_shell
+  chromium_src_root = os.path.abspath(os.path.join(os.path.dirname(__file__),
+                                                   os.pardir,
+                                                   os.pardir))
+  # Find out directory (might be out_linux for users of cr).
+  for out_suffix in ["_linux", ""]:
+    out_dir = os.path.join(chromium_src_root, "out" + out_suffix)
+    if os.path.exists(out_dir):
+      chromium_out_dir = out_dir
+      break
+  if not chromium_out_dir:
+    return False
+
+  this_script_name = "real_world_impact"
+  output_dir = os.path.join(chromium_out_dir,
+                            "Release",
+                            this_script_name)
+  MakeDirsIfNotExist(output_dir)
+
+  image_diff = os.path.join(chromium_out_dir, "Release", "image_diff")
+
+  if sys.platform == 'darwin':
+    content_shell = os.path.join(chromium_out_dir, "Release",
+                    "Content Shell.app/Contents/MacOS/Content Shell")
+  elif sys.platform.startswith('linux'):
+    content_shell = os.path.join(chromium_out_dir, "Release",
+                    "content_shell")
+  elif sys.platform.startswith('win'):
+    content_shell = os.path.join(chromium_out_dir, "Release",
+                    "content_shell.exe")
+  return True
+
+
+def CheckPrerequisites():
+  if not find_executable("wget"):
+    print "wget not found! Install wget and re-run this."
+    return False
+  if not os.path.exists(image_diff):
+    print "image_diff not found (%s)!" % image_diff
+    print "Build the image_diff target and re-run this."
+    return False
+  if not os.path.exists(content_shell):
+    print "Content shell not found (%s)!" % content_shell
+    print "Build Release/content_shell and re-run this."
+    return False
+  return True
+
+
+def PickSampleUrls():
+  global urls
+  data_dir = os.path.join(output_dir, "data")
+  MakeDirsIfNotExist(data_dir)
+
+  # Download Alexa top 1,000,000 sites
+  # TODO(johnme): Should probably update this when it gets too stale...
+  csv_path = os.path.join(data_dir, "top-1m.csv")
+  if not os.path.exists(csv_path):
+    print "Downloading list of top 1,000,000 sites from Alexa..."
+    csv_url = "http://s3.amazonaws.com/alexa-static/top-1m.csv.zip"
+    with closing(urlopen(csv_url)) as stream:
+      ZipFile(StringIO(stream.read())).extract("top-1m.csv", data_dir)
+
+  bad_urls_path = os.path.join(data_dir, "bad_urls.txt")
+  if os.path.exists(bad_urls_path):
+    with open(bad_urls_path) as f:
+      bad_urls = set(f.read().splitlines())
+  else:
+    bad_urls = set()
+
+  # See if we've already selected a sample of size num_sites (this way, if you
+  # call this script with arguments "before N" then "after N", where N is the
+  # same number, we'll use the same sample, as expected!).
+  urls_path = os.path.join(data_dir, "%06d_urls.txt" % num_sites)
+  if not os.path.exists(urls_path):
+    if action == 'compare':
+      print ("Error: you must run 'before %d' and 'after %d' before "
+             "running 'compare %d'") % (num_sites, num_sites, num_sites)
+      return False
+    print "Picking %d sample urls..." % num_sites
+
+    # TODO(johnme): For now this just gets the top num_sites entries. In future
+    # this should pick a weighted random sample. For example, it could fit a
+    # power-law distribution, which is a good model of website popularity
+    # (http://www.useit.com/alertbox/9704b.html).
+    urls = []
+    remaining_num_sites = num_sites
+    with open(csv_path) as f:
+      for entry in f:
+        if remaining_num_sites <= 0:
+          break
+        remaining_num_sites -= 1
+        hostname = entry.strip().split(',')[1]
+        if not '/' in hostname:  # Skip Alexa 1,000,000 entries that have paths.
+          url = "http://%s/" % hostname
+          if not url in bad_urls:
+            urls.append(url)
+    # Don't write these to disk yet; we'll do that in SaveWorkingUrls below
+    # once we have tried to download them and seen which ones fail.
+  else:
+    with open(urls_path) as f:
+      urls = [u for u in f.read().splitlines() if not u in bad_urls]
+  return True
+
+
+def SaveWorkingUrls():
+  # TODO(johnme): Update the list if a url that used to work goes offline.
+  urls_path = os.path.join(output_dir, "data", "%06d_urls.txt" % num_sites)
+  if not os.path.exists(urls_path):
+    with open(urls_path, 'w') as f:
+      f.writelines(u + '\n' for u in urls)
+
+
+def PrintElapsedTime(elapsed, detail=""):
+  elapsed = round(elapsed * 10) / 10.0
+  m = elapsed / 60
+  s = elapsed % 60
+  print "Took %dm%.1fs" % (m, s), detail
+
+
+def DownloadStaticCopyTask(url):
+  url_parts = urlparse(url)
+  host_dir = os.path.join(output_dir, "data", url_parts.hostname)
+  # Use wget for now, as does a reasonable job of spidering page dependencies
+  # (e.g. CSS, JS, images).
+  success = True
+  try:
+    subprocess.check_call(["wget",
+                           "--execute", "robots=off",
+                           ("--user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS "
+                            "X 10_8_5) AppleWebKit/537.36 (KHTML, like Gecko) C"
+                            "hrome/32.0.1700.14 Safari/537.36"),
+                           "--page-requisites",
+                           "--span-hosts",
+                           "--adjust-extension",
+                           "--convert-links",
+                           "--directory-prefix=" + host_dir,
+                           "--force-directories",
+                           "--default-page=index.html",
+                           "--no-check-certificate",
+                           "--timeout=5", # 5s timeout
+                           "--tries=2",
+                           "--quiet",
+                           url])
+  except KeyboardInterrupt:
+    success = False
+  except subprocess.CalledProcessError:
+    # Ignoring these for now, as some sites have issues with their subresources
+    # yet still produce a renderable index.html
+    pass #success = False
+  if success:
+    download_path = os.path.join(host_dir, url_parts.hostname, "index.html")
+    if not os.path.exists(download_path):
+      success = False
+    else:
+      with print_lock:
+        print "Downloaded:", url
+  if not success:
+    with print_lock:
+      print "Failed to download:", url
+    return False
+  return True
+
+
+def DownloadStaticCopies():
+  global urls
+  new_urls = []
+  for url in urls:
+    url_parts = urlparse(url)
+    host_dir = os.path.join(output_dir, "data", url_parts.hostname)
+    download_path = os.path.join(host_dir, url_parts.hostname, "index.html")
+    if not os.path.exists(download_path):
+      new_urls.append(url)
+
+  if new_urls:
+    print "Downloading static copies of %d sites..." % len(new_urls)
+    start_time = time.time()
+
+    results = multiprocessing.Pool(20).map(DownloadStaticCopyTask, new_urls)
+    failed_urls = [new_urls[i] for i,ret in enumerate(results) if not ret]
+    if failed_urls:
+      bad_urls_path = os.path.join(output_dir, "data", "bad_urls.txt")
+      with open(bad_urls_path, 'a') as f:
+        f.writelines(u + '\n' for u in failed_urls)
+      failed_urls_set = set(failed_urls)
+      urls = [u for u in urls if u not in failed_urls_set]
+
+    PrintElapsedTime(time.time() - start_time)
+
+  SaveWorkingUrls()
+
+
+def RunDrtTask(url):
+  url_parts = urlparse(url)
+  host_dir = os.path.join(output_dir, "data", url_parts.hostname)
+  html_path = os.path.join(host_dir, url_parts.hostname, "index.html")
+
+  if not allow_js:
+    nojs_path = os.path.join(host_dir, url_parts.hostname, "index-nojs.html")
+    if not os.path.exists(nojs_path):
+      with open(html_path) as f:
+        html = f.read()
+      if not html:
+        return False
+      # These aren't intended to be XSS safe :)
+      block_tags = (r'<\s*(script|object|video|audio|iframe|frameset|frame)'
+                    r'\b.*?<\s*\/\s*\1\s*>')
+      block_attrs = r'\s(onload|onerror)\s*=\s*(\'[^\']*\'|"[^"]*|\S*)'
+      html = re.sub(block_tags, '', html, flags=re.I|re.S)
+      html = re.sub(block_attrs, '', html, flags=re.I)
+      with open(nojs_path, 'w') as f:
+        f.write(html)
+    html_path = nojs_path
+
+  start_time = time.time()
+
+  with open(os.devnull, "w") as fnull:
+    p = subprocess.Popen([content_shell,
+                          "--dump-render-tree",
+                          additional_content_shell_flags,
+                          # The single quote is not a typo, it's a separator!
+                          html_path + "'--pixel-test"
+                         ],
+                         shell=False,
+                         stdout=subprocess.PIPE,
+                         stderr=fnull)
+  result = p.stdout.read()
+  PNG_START = b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A"
+  PNG_END = b"\x49\x45\x4E\x44\xAE\x42\x60\x82"
+  try:
+    start = result.index(PNG_START)
+    end = result.rindex(PNG_END) + 8
+  except ValueError:
+    return False
+
+  png_path = os.path.join(output_dir, action, url_parts.hostname + ".png")
+  MakeDirsIfNotExist(os.path.dirname(png_path))
+  with open(png_path, 'wb') as f:
+    f.write(result[start:end])
+  elapsed_time = (time.time() - start_time, url)
+  return elapsed_time
+
+
+def RunDrt():
+  print "Taking screenshots of %d pages..." % len(urls)
+  start_time = time.time()
+
+  results = multiprocessing.Pool().map(RunDrtTask, urls, 1)
+
+  max_time, url = max(t for t in results if t)
+  elapsed_detail = "(slowest: %.2fs on %s)" % (max_time, url)
+  PrintElapsedTime(time.time() - start_time, elapsed_detail)
+
+
+def CompareResultsTask(url):
+  url_parts = urlparse(url)
+  before_path = os.path.join(output_dir, "before", url_parts.hostname + ".png")
+  after_path = os.path.join(output_dir, "after", url_parts.hostname + ".png")
+  diff_path = os.path.join(output_dir, "diff", url_parts.hostname + ".png")
+  MakeDirsIfNotExist(os.path.join(output_dir, "diff"))
+
+  # TODO(johnme): Don't hardcode "real_world_impact".
+  red_path = ("data:image/gif;base64,R0lGODlhAQABAPAAAP8AAP///yH5BAAAAAAALAAAAA"
+              "ABAAEAAAICRAEAOw==")
+
+  before_exists = os.path.exists(before_path)
+  after_exists = os.path.exists(after_path)
+  if not before_exists and not after_exists:
+    # TODO(johnme): Make this more informative.
+    return (-100, url, red_path)
+  if before_exists != after_exists:
+    # TODO(johnme): Make this more informative.
+    return (200, url, red_path)
+
+  # Get percentage difference.
+  p = subprocess.Popen([image_diff, "--histogram",
+                        before_path, after_path],
+                        shell=False,
+                        stdout=subprocess.PIPE)
+  output,_ = p.communicate()
+  if p.returncode == 0:
+    return (0, url, before_path)
+  diff_match = re.match(r'histogram diff: (\d+\.\d{2})% (?:passed|failed)\n'
+                         'exact diff: (\d+\.\d{2})% (?:passed|failed)', output)
+  if not diff_match:
+    raise Exception("image_diff output format changed")
+  histogram_diff = float(diff_match.group(1))
+  exact_diff = float(diff_match.group(2))
+  combined_diff = max(histogram_diff + exact_diff / 8, 0.001)
+
+  # Produce diff PNG.
+  subprocess.call([image_diff, "--diff", before_path, after_path, diff_path])
+  return (combined_diff, url, diff_path)
+
+
+def CompareResults():
+  print "Running image_diff on %d pages..." % len(urls)
+  start_time = time.time()
+
+  results = multiprocessing.Pool().map(CompareResultsTask, urls)
+  results.sort(key=itemgetter(0), reverse=True)
+
+  PrintElapsedTime(time.time() - start_time)
+
+  now = datetime.datetime.today().strftime("%a %Y-%m-%d %H:%M")
+  html_start = textwrap.dedent("""\
+  <!DOCTYPE html>
+  <html>
+  <head>
+  <title>Real World Impact report %s</title>
+  <script>
+    var togglingImg = null;
+    var toggleTimer = null;
+
+    var before = true;
+    function toggle() {
+      var newFolder = before ? "before" : "after";
+      togglingImg.src = togglingImg.src.replace(/before|after|diff/, newFolder);
+      before = !before;
+      toggleTimer = setTimeout(toggle, 300);
+    }
+
+    function startToggle(img) {
+      before = true;
+      togglingImg = img;
+      if (!img.origSrc)
+        img.origSrc = img.src;
+      toggle();
+    }
+    function stopToggle(img) {
+      clearTimeout(toggleTimer);
+      img.src = img.origSrc;
+    }
+
+    document.onkeydown = function(e) {
+      e = e || window.event;
+      var keyCode = e.keyCode || e.which;
+      var newFolder;
+      switch (keyCode) {
+        case 49: //'1'
+          newFolder = "before"; break;
+        case 50: //'2'
+          newFolder = "after"; break;
+        case 51: //'3'
+          newFolder = "diff"; break;
+        default:
+          return;
+      }
+      var imgs = document.getElementsByTagName("img");
+      for (var i = 0; i < imgs.length; i++) {
+        imgs[i].src = imgs[i].src.replace(/before|after|diff/, newFolder);
+      }
+    };
+  </script>
+  <style>
+    h1 {
+      font-family: sans;
+    }
+    h2 {
+      font-family: monospace;
+      white-space: pre;
+    }
+    .nsfw-spacer {
+      height: 50vh;
+    }
+    .nsfw-warning {
+      background: yellow;
+      border: 10px solid red;
+    }
+    .info {
+      font-size: 1.2em;
+      font-style: italic;
+    }
+    body:not(.details-supported) details {
+      display: none;
+    }
+  </style>
+  </head>
+  <body>
+    <script>
+    if ('open' in document.createElement('details'))
+      document.body.className = "details-supported";
+    </script>
+    <!--<div class="nsfw-spacer"></div>-->
+    <p class="nsfw-warning">Warning: sites below are taken from the Alexa top %d
+    and may be NSFW.</p>
+    <!--<div class="nsfw-spacer"></div>-->
+    <h1>Real World Impact report %s</h1>
+    <p class="info">Press 1, 2 and 3 to switch between before, after and diff
+    screenshots respectively; or hover over the images to rapidly alternate
+    between before and after.</p>
+  """ % (now, num_sites, now))
+
+  html_same_row = """\
+  <h2>No difference on <a href="%s">%s</a>.</h2>
+  """
+
+  html_diff_row = """\
+  <h2>%7.3f%% difference on <a href="%s">%s</a>:</h2>
+  <img src="%s" width="800" height="600"
+       onmouseover="startToggle(this)" onmouseout="stopToggle(this)">
+  """
+
+  html_nsfw_diff_row = """\
+  <h2>%7.3f%% difference on <a href="%s">%s</a>:</h2>
+  <details>
+    <summary>This site may be NSFW. Click to expand/collapse.</summary>
+    <img src="%s" width="800" height="600"
+         onmouseover="startToggle(this)" onmouseout="stopToggle(this)">
+  </details>
+  """
+
+  html_end = textwrap.dedent("""\
+  </body>
+  </html>""")
+
+  html_path = os.path.join(output_dir, "diff.html")
+  with open(html_path, 'w') as f:
+    f.write(html_start)
+    for (diff_float, url, diff_path) in results:
+      diff_path = os.path.relpath(diff_path, output_dir)
+      if diff_float == 0:
+        f.write(html_same_row % (url, url))
+      elif url in nsfw_urls:
+        f.write(html_nsfw_diff_row % (diff_float, url, url, diff_path))
+      else:
+        f.write(html_diff_row % (diff_float, url, url, diff_path))
+    f.write(html_end)
+
+  webbrowser.open_new_tab("file://" + html_path)
+
+
+def main(argv):
+  global num_sites, action, allow_js, additional_content_shell_flags
+
+  parser = argparse.ArgumentParser(
+      formatter_class=RawTextHelpFormatter,
+      description="Compare the real world impact of a content shell change.",
+      epilog=textwrap.dedent("""\
+          Example usage:
+            1. Build content_shell in out/Release without any changes.
+            2. Run: %s before [num sites to test (default %d)].
+            3. Either:
+                 a. Apply your controversial patch and rebuild content_shell.
+                 b. Pass --additional_flags="--enable_your_flag" in step 4.
+            4. Run: %s after [num sites to test (default %d)].
+            5. Run: %s compare [num sites to test (default %d)].
+               This will open the results in your web browser.
+          """ % (argv[0], num_sites, argv[0], num_sites, argv[0], num_sites)))
+  parser.add_argument("--allow_js", help="Don't disable Javascript",
+                      action="store_true")
+  parser.add_argument("--additional_flags",
+                      help="Additional flags to pass to content shell")
+  parser.add_argument("action",
+                      help=textwrap.dedent("""\
+                        Action to perform.
+                          download - Just download the sites.
+                          before - Run content shell and record 'before' result.
+                          after - Run content shell and record 'after' result.
+                          compare - Compare before and after results.
+                      """),
+                      choices=["download", "before", "after", "compare"])
+  parser.add_argument("num_sites",
+                      help="Number of sites (default %s)" % num_sites,
+                      type=int, default=num_sites, nargs='?')
+  args = parser.parse_args()
+
+  action = args.action
+
+  if (args.num_sites):
+    num_sites = args.num_sites
+
+  if (args.allow_js):
+    allow_js = args.allow_js
+
+  if (args.additional_flags):
+    additional_content_shell_flags = args.additional_flags
+
+  if not SetupPathsAndOut() or not CheckPrerequisites() or not PickSampleUrls():
+    return 1
+
+  if action == 'compare':
+    CompareResults()
+  else:
+    DownloadStaticCopies()
+    if action != 'download':
+      RunDrt()
+  return 0
+
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
\ No newline at end of file
diff --git a/tools/strict_enum_value_checker/changed_file_1.h b/tools/strict_enum_value_checker/changed_file_1.h
new file mode 100644
index 0000000..e74e408
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_1.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mValidInsertion1,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_10.h b/tools/strict_enum_value_checker/changed_file_10.h
new file mode 100644
index 0000000..d7b370d
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_10.h
@@ -0,0 +1,23 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_2.h b/tools/strict_enum_value_checker/changed_file_2.h
new file mode 100644
index 0000000..04a801b
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_2.h
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_3.h b/tools/strict_enum_value_checker/changed_file_3.h
new file mode 100644
index 0000000..f839c14
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_3.h
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mErrata1,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_4.h b/tools/strict_enum_value_checker/changed_file_4.h
new file mode 100644
index 0000000..157153e
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_4.h
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_5.h b/tools/strict_enum_value_checker/changed_file_5.h
new file mode 100644
index 0000000..b788289
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_5.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_6.h b/tools/strict_enum_value_checker/changed_file_6.h
new file mode 100644
index 0000000..7bbbf83
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_6.h
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+  mBoundary // Do not add below here
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_7.h b/tools/strict_enum_value_checker/changed_file_7.h
new file mode 100644
index 0000000..61a2792
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_7.h
@@ -0,0 +1,33 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mInvalid1,
+  mError1,
+  mFunction1,
+  mInvalid2,
+  mInvalid3,
+  mInfo2,
+  mInvalid4,
+  mData4,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_8.h b/tools/strict_enum_value_checker/changed_file_8.h
new file mode 100644
index 0000000..56e9483
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_8.h
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mInsertion,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/changed_file_9.h b/tools/strict_enum_value_checker/changed_file_9.h
new file mode 100644
index 0000000..bea98f0
--- /dev/null
+++ b/tools/strict_enum_value_checker/changed_file_9.h
@@ -0,0 +1,32 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mValidInsertion1,
+  mValidInsertion2,
+  mValidInsertion3,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/mock_enum.h b/tools/strict_enum_value_checker/mock_enum.h
new file mode 100644
index 0000000..86e80b7
--- /dev/null
+++ b/tools/strict_enum_value_checker/mock_enum.h
@@ -0,0 +1,29 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MOCK_ENUM_H
+#define MOCK_ENUM_H
+
+// Here is our mock enum. Beyond testing it is completely meaningless.
+// MockEnum follows strict rules for valid modifications:
+//    1. NO reordering of entries
+//    2. NO deletions of entries
+//    3. New entries must be added just before mBoundary, never after
+//
+enum MockEnum {
+  mEntry1,
+  mEntry2,
+  mData1,
+  mData2,
+  mEntry3,
+  mInfo1,
+  mData3,
+  mError1,
+  mFunction1,
+  mInfo2,
+  mData4,
+  mBoundary // Do not add below here
+};
+
+#endif
diff --git a/tools/strict_enum_value_checker/strict_enum_value_checker.py b/tools/strict_enum_value_checker/strict_enum_value_checker.py
new file mode 100644
index 0000000..22a0276
--- /dev/null
+++ b/tools/strict_enum_value_checker/strict_enum_value_checker.py
@@ -0,0 +1,284 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class StrictEnumValueChecker(object):
+  """Verify that changes to enums are valid.
+
+  This class is used to check enums where reordering or deletion is not allowed,
+  and additions must be at the end of the enum, just prior to some "boundary"
+  entry. See comments at the top of the "extension_function_histogram_value.h"
+  file in chrome/browser/extensions for an example what are considered valid
+  changes. There are situations where this class gives false positive warnings,
+  i.e. it warns even though the edit is legitimate. Since the class warns using
+  prompt warnings, the user can always choose to continue. The main point is to
+  attract the attention to all (potentially or not) invalid edits.
+
+  """
+  def __init__(self, input_api, output_api, start_marker, end_marker, path):
+    self.input_api = input_api
+    self.output_api = output_api
+    self.start_marker = start_marker
+    self.end_marker = end_marker
+    self.path = path
+    self.results = []
+
+  class EnumRange(object):
+    """Represents a range of line numbers (1-based)"""
+    def __init__(self, first_line, last_line):
+      self.first_line = first_line
+      self.last_line = last_line
+
+    def Count(self):
+      return self.last_line - self.first_line + 1
+
+    def Contains(self, line_num):
+      return self.first_line <= line_num and line_num <= self.last_line
+
+  def LogInfo(self, message):
+    self.input_api.logging.info(message)
+    return
+
+  def LogDebug(self, message):
+    self.input_api.logging.debug(message)
+    return
+
+  def ComputeEnumRangeInContents(self, contents):
+    """Returns an |EnumRange| object representing the line extent of the
+    enum members in |contents|. The line numbers are 1-based,
+    compatible with line numbers returned by AffectedFile.ChangeContents().
+    |contents| is a list of strings reprenting the lines of a text file.
+
+    If either start_marker or end_marker cannot be found in
+    |contents|, returns None and emits detailed warnings about the problem.
+
+    """
+    first_enum_line = 0
+    last_enum_line = 0
+    line_num = 1  # Line numbers are 1-based
+    for line in contents:
+      if line.startswith(self.start_marker):
+        first_enum_line = line_num + 1
+      elif line.startswith(self.end_marker):
+        last_enum_line = line_num
+      line_num += 1
+
+    if first_enum_line == 0:
+      self.EmitWarning("The presubmit script could not find the start of the "
+                       "enum definition (\"%s\"). Did the enum definition "
+                       "change?" % self.start_marker)
+      return None
+
+    if last_enum_line == 0:
+      self.EmitWarning("The presubmit script could not find the end of the "
+                       "enum definition (\"%s\"). Did the enum definition "
+                       "change?" % self.end_marker)
+      return None
+
+    if first_enum_line >= last_enum_line:
+      self.EmitWarning("The presubmit script located the start of the enum "
+                       "definition (\"%s\" at line %d) *after* its end "
+                       "(\"%s\" at line %d). Something is not quite right."
+                       % (self.start_marker, first_enum_line,
+                          self.end_marker, last_enum_line))
+      return None
+
+    self.LogInfo("Line extent of (\"%s\") enum definition: "
+                 "first_line=%d, last_line=%d."
+                 % (self.start_marker, first_enum_line, last_enum_line))
+    return self.EnumRange(first_enum_line, last_enum_line)
+
+  def ComputeEnumRangeInNewFile(self, affected_file):
+    return self.ComputeEnumRangeInContents(affected_file.NewContents())
+
+  def GetLongMessage(self, local_path):
+    return str("The file \"%s\" contains the definition of the "
+               "(\"%s\") enum which should be edited in specific ways "
+               "only - *** read the comments at the top of the header file ***"
+               ". There are changes to the file that may be incorrect and "
+               "warrant manual confirmation after review. Note that this "
+               "presubmit script can not reliably report the nature of all "
+               "types of invalid changes, especially when the diffs are "
+               "complex. For example, an invalid deletion may be reported "
+               "whereas the change contains a valid rename."
+               % (local_path, self.start_marker))
+
+  def EmitWarning(self, message, line_number=None, line_text=None):
+    """Emits a presubmit prompt warning containing the short message
+    |message|. |item| is |LOCAL_PATH| with optional |line_number| and
+    |line_text|.
+
+    """
+    if line_number is not None and line_text is not None:
+      item = "%s(%d): %s" % (self.path, line_number, line_text)
+    elif line_number is not None:
+      item = "%s(%d)" % (self.path, line_number)
+    else:
+      item = self.path
+    long_message = self.GetLongMessage(self.path)
+    self.LogInfo(message)
+    self.results.append(
+      self.output_api.PresubmitPromptWarning(message, [item], long_message))
+
+  def CollectRangesInsideEnumDefinition(self, affected_file,
+                                        first_line, last_line):
+    """Returns a list of triplet (line_start, line_end, line_text) of ranges of
+    edits changes. The |line_text| part is the text at line |line_start|.
+    Since it used only for reporting purposes, we do not need all the text
+    lines in the range.
+
+    """
+    results = []
+    previous_line_number = 0
+    previous_range_start_line_number = 0
+    previous_range_start_text = ""
+
+    def addRange():
+      tuple = (previous_range_start_line_number,
+               previous_line_number,
+               previous_range_start_text)
+      results.append(tuple)
+
+    for line_number, line_text in affected_file.ChangedContents():
+      if first_line <= line_number and line_number <= last_line:
+        self.LogDebug("Line change at line number " + str(line_number) + ": " +
+                      line_text)
+        # Start a new interval if none started
+        if previous_range_start_line_number == 0:
+          previous_range_start_line_number = line_number
+          previous_range_start_text = line_text
+        # Add new interval if we reached past the previous one
+        elif line_number != previous_line_number + 1:
+          addRange()
+          previous_range_start_line_number = line_number
+          previous_range_start_text = line_text
+        previous_line_number = line_number
+
+    # Add a last interval if needed
+    if previous_range_start_line_number != 0:
+        addRange()
+    return results
+
+  def CheckForFileDeletion(self, affected_file):
+    """Emits a warning notification if file has been deleted """
+    if not affected_file.NewContents():
+      self.EmitWarning("The file seems to be deleted in the changelist. If "
+                       "your intent is to really delete the file, the code in "
+                       "PRESUBMIT.py should be updated to remove the "
+                       "|StrictEnumValueChecker| class.");
+      return False
+    return True
+
+  def GetDeletedLinesFromScmDiff(self, affected_file):
+    """Return a list of of line numbers (1-based) corresponding to lines
+    deleted from the new source file (if they had been present in it). Note
+    that if multiple contiguous lines have been deleted, the returned list will
+    contain contiguous line number entries. To prevent false positives, we
+    return deleted line numbers *only* from diff chunks which decrease the size
+    of the new file.
+
+    Note: We need this method because we have access to neither the old file
+    content nor the list of "delete" changes from the current presubmit script
+    API.
+
+    """
+    results = []
+    line_num = 0
+    deleting_lines = False
+    for line in affected_file.GenerateScmDiff().splitlines():
+      # Parse the unified diff chunk optional section heading, which looks like
+      # @@ -l,s +l,s @@ optional section heading
+      m = self.input_api.re.match(
+        r"^@@ \-([0-9]+)\,([0-9]+) \+([0-9]+)\,([0-9]+) @@", line)
+      if m:
+        old_line_num = int(m.group(1))
+        old_size = int(m.group(2))
+        new_line_num = int(m.group(3))
+        new_size = int(m.group(4))
+        line_num = new_line_num
+        # Return line numbers only from diff chunks decreasing the size of the
+        # new file
+        deleting_lines = old_size > new_size
+        continue
+      if not line.startswith("-"):
+        line_num += 1
+      if deleting_lines and line.startswith("-") and not line.startswith("--"):
+        results.append(line_num)
+    return results
+
+  def CheckForEnumEntryDeletions(self, affected_file):
+    """Look for deletions inside the enum definition. We currently use a
+    simple heuristics (not 100% accurate): if there are deleted lines inside
+    the enum definition, this might be a deletion.
+
+    """
+    range_new = self.ComputeEnumRangeInNewFile(affected_file)
+    if not range_new:
+      return False
+
+    is_ok = True
+    for line_num in self.GetDeletedLinesFromScmDiff(affected_file):
+      if range_new.Contains(line_num):
+        self.EmitWarning("It looks like you are deleting line(s) from the "
+                         "enum definition. This should never happen.",
+                         line_num)
+        is_ok = False
+    return is_ok
+
+  def CheckForEnumEntryInsertions(self, affected_file):
+    range = self.ComputeEnumRangeInNewFile(affected_file)
+    if not range:
+      return False
+
+    first_line = range.first_line
+    last_line = range.last_line
+
+    # Collect the range of changes inside the enum definition range.
+    is_ok = True
+    for line_start, line_end, line_text in \
+          self.CollectRangesInsideEnumDefinition(affected_file,
+                                                 first_line,
+                                                 last_line):
+      # The only edit we consider valid is adding 1 or more entries *exactly*
+      # at the end of the enum definition. Every other edit inside the enum
+      # definition will result in a "warning confirmation" message.
+      #
+      # TODO(rpaquay): We currently cannot detect "renames" of existing entries
+      # vs invalid insertions, so we sometimes will warn for valid edits.
+      is_valid_edit = (line_end == last_line - 1)
+
+      self.LogDebug("Edit range in new file at starting at line number %d and "
+                    "ending at line number %d: valid=%s"
+                    % (line_start, line_end, is_valid_edit))
+
+      if not is_valid_edit:
+        self.EmitWarning("The change starting at line %d and ending at line "
+                         "%d is *not* located *exactly* at the end of the "
+                         "enum definition. Unless you are renaming an "
+                         "existing entry, this is not a valid change, as new "
+                         "entries should *always* be added at the end of the "
+                         "enum definition, right before the \"%s\" "
+                         "entry." % (line_start, line_end, self.end_marker),
+                         line_start,
+                         line_text)
+        is_ok = False
+    return is_ok
+
+  def PerformChecks(self, affected_file):
+    if not self.CheckForFileDeletion(affected_file):
+      return
+    if not self.CheckForEnumEntryDeletions(affected_file):
+      return
+    if not self.CheckForEnumEntryInsertions(affected_file):
+      return
+
+  def ProcessHistogramValueFile(self, affected_file):
+    self.LogInfo("Start processing file \"%s\"" % affected_file.LocalPath())
+    self.PerformChecks(affected_file)
+    self.LogInfo("Done processing file \"%s\"" % affected_file.LocalPath())
+
+  def Run(self):
+    for file in self.input_api.AffectedFiles(include_deletes=True):
+      if file.LocalPath() == self.path:
+        self.ProcessHistogramValueFile(file)
+    return self.results
diff --git a/tools/strict_enum_value_checker/strict_enum_value_checker_test.py b/tools/strict_enum_value_checker/strict_enum_value_checker_test.py
new file mode 100755
index 0000000..4f95efe
--- /dev/null
+++ b/tools/strict_enum_value_checker/strict_enum_value_checker_test.py
@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import difflib
+import os
+import re
+import unittest
+
+from strict_enum_value_checker import StrictEnumValueChecker
+
+class MockLogging(object):
+  def __init__(self):
+    self.lines = []
+
+  def info(self, message):
+    self.lines.append(message)
+
+  def debug(self, message):
+    self.lines.append(message)
+
+class MockInputApi(object):
+  def __init__(self):
+    self.re = re
+    self.os_path = os.path
+    self.files = []
+    self.is_committing = False
+    self.logging = MockLogging()
+
+  def AffectedFiles(self, include_deletes=None):
+    return self.files
+
+
+class MockOutputApi(object):
+  class PresubmitResult(object):
+    def __init__(self, message, items=None, long_text=""):
+      self.message = message
+      self.items = items
+      self.long_text = long_text
+
+  class PresubmitError(PresubmitResult):
+    def __init__(self, message, items, long_text=""):
+      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
+      self.type = "error"
+
+  class PresubmitPromptWarning(PresubmitResult):
+    def __init__(self, message, items, long_text=""):
+      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
+      self.type = "warning"
+
+  class PresubmitNotifyResult(PresubmitResult):
+    def __init__(self, message, items, long_text=""):
+      MockOutputApi.PresubmitResult.__init__(self, message, items, long_text)
+      self.type = "notify"
+
+
+class MockFile(object):
+  def __init__(self, local_path, old_contents, new_contents):
+    self._local_path = local_path
+    self._new_contents = new_contents
+    self._old_contents = old_contents
+    self._cached_changed_contents = None
+
+  def ChangedContents(self):
+    return self._changed_contents
+
+  def NewContents(self):
+    return self._new_contents
+
+  def LocalPath(self):
+    return self._local_path
+
+  def IsDirectory(self):
+    return False
+
+  def GenerateScmDiff(self):
+    result = ""
+    for line in difflib.unified_diff(self._old_contents, self._new_contents,
+                                     self._local_path, self._local_path):
+      result += line
+    return result
+
+  # NOTE: This method is a copy of ChangeContents method of AffectedFile in
+  # presubmit_support.py
+  def ChangedContents(self):
+    """Returns a list of tuples (line number, line text) of all new lines.
+
+     This relies on the scm diff output describing each changed code section
+     with a line of the form
+
+     ^@@ <old line num>,<old size> <new line num>,<new size> @@$
+    """
+    if self._cached_changed_contents is not None:
+      return self._cached_changed_contents[:]
+    self._cached_changed_contents = []
+    line_num = 0
+
+    if self.IsDirectory():
+      return []
+
+    for line in self.GenerateScmDiff().splitlines():
+      m = re.match(r"^@@ [0-9\,\+\-]+ \+([0-9]+)\,[0-9]+ @@", line)
+      if m:
+        line_num = int(m.groups(1)[0])
+        continue
+      if line.startswith("+") and not line.startswith("++"):
+        self._cached_changed_contents.append((line_num, line[1:]))
+      if not line.startswith("-"):
+        line_num += 1
+    return self._cached_changed_contents[:]
+
+
+class MockChange(object):
+  def __init__(self, changed_files):
+    self._changed_files = changed_files
+
+  def LocalPaths(self):
+    return self._changed_files
+
+
+class StrictEnumValueCheckerTest(unittest.TestCase):
+  TEST_FILE_PATTERN = "changed_file_%s.h"
+  MOCK_FILE_LOCAL_PATH = "mock_enum.h"
+  START_MARKER = "enum MockEnum {"
+  END_MARKER = "  mBoundary"
+
+  def _ReadTextFileContents(self, path):
+    """Given a path, returns a list of strings corresponding to the text lines
+    in the file. Reads files in text format.
+
+    """
+    fo = open(path, "r")
+    try:
+      contents = fo.readlines()
+    finally:
+      fo.close()
+    return contents
+
+  def _ReadInputFile(self):
+    return self._ReadTextFileContents("mock_enum.h")
+
+  def _PrepareTest(self, new_file_path):
+    old_contents = self._ReadInputFile()
+    if not new_file_path:
+      new_contents = []
+    else:
+      new_contents = self._ReadTextFileContents(new_file_path)
+    input_api = MockInputApi()
+    mock_file = MockFile(self.MOCK_FILE_LOCAL_PATH,
+                         old_contents,
+                         new_contents)
+    input_api.files.append(mock_file)
+    output_api = MockOutputApi()
+    return input_api, output_api
+
+  def _RunTest(self, new_file_path):
+    input_api, output_api = self._PrepareTest(new_file_path)
+    checker = StrictEnumValueChecker(input_api, output_api, self.START_MARKER,
+                                     self.END_MARKER, self.MOCK_FILE_LOCAL_PATH)
+    results = checker.Run()
+    return results
+
+  def testDeleteFile(self):
+    results = self._RunTest(new_file_path=None)
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(1, len(results),
+                      "We should get a single warning about file deletion.")
+
+  def testSimpleValidEdit(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "1")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(0, len(results),
+                      "We should get no warning for simple edits.")
+
+  def testSingleDeletionOfEntry(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "2")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(1, len(results),
+                      "We should get a warning for an entry deletion.")
+
+  def testSingleRenameOfEntry(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "3")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(1, len(results),
+                      "We should get a warning for an entry rename, even "
+                      "though it is not optimal.")
+
+  def testMissingEnumStartOfEntry(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "4")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(1, len(results),
+                      "We should get a warning for a missing enum marker.")
+
+  def testMissingEnumEndOfEntry(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "5")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(1, len(results),
+                      "We should get a warning for a missing enum marker.")
+
+  def testInvertedEnumMarkersOfEntry(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "6")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(1, len(results),
+                      "We should get a warning for inverted enum markers.")
+
+  def testMultipleInvalidEdits(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "7")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(3, len(results),
+                      "We should get 3 warnings (one per edit).")
+
+  def testSingleInvalidInserts(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "8")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(1, len(results),
+                      "We should get a warning for a single invalid "
+                      "insertion inside the enum.")
+
+  def testMulitpleValidInserts(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "9")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(0, len(results),
+                      "We should not get a warning mulitple valid edits")
+
+  def testSingleValidDeleteOutsideOfEnum(self):
+    results = self._RunTest(self.TEST_FILE_PATTERN % "10")
+    # TODO(rpaquay) How to check it's the expected warning?'
+    self.assertEquals(0, len(results),
+                      "We should not get a warning for a deletion outside of "
+                      "the enum")
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/tools/telemetry/build/generate_telemetry_harness.sh b/tools/telemetry/build/generate_telemetry_harness.sh
new file mode 100755
index 0000000..11589ad
--- /dev/null
+++ b/tools/telemetry/build/generate_telemetry_harness.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This is a script meant to be run by a bot to periodically release new versions
+# of the telemetry harness. It needs to be run from one level above src/ (such
+# as build/).
+
+src/tools/telemetry/find_dependencies \
+  src/tools/perf/run_benchmark \
+  src/tools/perf/run_measurement \
+  src/tools/perf/record_wpr \
+  src/content/test/gpu/run_gpu_test.py \
+  --exclude=*/third_party/trace-viewer/test_data/* \
+  -z $1
diff --git a/tools/telemetry/cloud_storage b/tools/telemetry/cloud_storage
index 242b461..9081b33 100755
--- a/tools/telemetry/cloud_storage
+++ b/tools/telemetry/cloud_storage
@@ -57,7 +57,7 @@
     file_hash = cloud_storage.ReadHash(hash_path)
     file_buckets[file_path] = []
     for bucket in BUCKETS:
-      if file_hash in bucket_contents[bucket]:
+      if bucket in bucket_contents and file_hash in bucket_contents[bucket]:
         file_buckets[file_path].append(bucket)
 
   return file_buckets
@@ -85,7 +85,7 @@
       for path in paths:
         if not os.path.isdir(path):
           yield path
-          return
+          continue
 
         if recursive:
           for root, _, filenames in os.walk(path):
@@ -121,11 +121,6 @@
   def ProcessCommandLineArgs(cls, parser, args):
     args.bucket = BUCKET_ALIASES[args.bucket]
 
-    for path in args.files:
-      _, hash_path = _GetPaths(path)
-      if not os.path.exists(hash_path):
-        parser.error('File not found: %s' % hash_path)
-
   def Run(self, args):
     files = _FindFilesInCloudStorage(args.files)
 
@@ -134,14 +129,18 @@
         raise IOError('%s not found in Cloud Storage.' % file_path)
 
     for file_path, buckets in sorted(files.iteritems()):
+      if args.bucket in buckets:
+        buckets.remove(args.bucket)
+      if not buckets:
+        logging.info('Skipping %s, no action needed.' % file_path)
+        continue
+
       # Move to the target bucket.
       file_hash = cloud_storage.ReadHash(file_path + '.sha1')
       cloud_storage.Move(buckets.pop(), args.bucket, file_hash)
 
       # Delete all additional copies.
       for bucket in buckets:
-        if bucket == args.bucket:
-          continue
         cloud_storage.Delete(bucket, file_hash)
 
 
@@ -152,13 +151,6 @@
   def AddCommandLineArgs(cls, parser):
     parser.add_argument('files', nargs='+')
 
-  @classmethod
-  def ProcessCommandLineArgs(cls, parser, args):
-    for path in args.files:
-      _, hash_path = _GetPaths(path)
-      if not os.path.exists(hash_path):
-        parser.error('File not found: %s' % hash_path)
-
   def Run(self, args):
     files = _FindFilesInCloudStorage(args.files)
     for file_path, buckets in sorted(files.iteritems()):
diff --git a/tools/telemetry/telemetry/__init__.py b/tools/telemetry/telemetry/__init__.py
index cffbaac..4d3fdc0 100644
--- a/tools/telemetry/telemetry/__init__.py
+++ b/tools/telemetry/telemetry/__init__.py
@@ -9,18 +9,13 @@
 import os
 import sys
 
-
-# Ensure Python >= 2.7
+# Ensure Python >= 2.7.
 if sys.version_info < (2, 7):
-  logging.critical('Need Python 2.7 or greater.')
-  sys.exit(1)
+  print >> sys.stderr, 'Need Python 2.7 or greater.'
+  sys.exit(-1)
 
-
-from telemetry import exception_formatter
-exception_formatter.InstallUnhandledExceptionFormatter()
-
-from telemetry import interactive_debugging
-interactive_debugging.InstallDebuggingHooks()
+from telemetry.util import global_hooks
+global_hooks.InstallHooks()
 
 from telemetry.core.browser import Browser
 from telemetry.core.browser_options import BrowserFinderOptions
@@ -43,32 +38,3 @@
   if (inspect.isclass(getattr(m, x)) or
       inspect.isfunction(getattr(m, x))):
     __all__.append(x)
-
-
-def RemoveAllStalePycFiles(base_dir):
-  for dirname, _, filenames in os.walk(base_dir):
-    if '.svn' in dirname or '.git' in dirname:
-      continue
-    for filename in filenames:
-      root, ext = os.path.splitext(filename)
-      if ext != '.pyc':
-        continue
-
-      pyc_path = os.path.join(dirname, filename)
-      py_path = os.path.join(dirname, root + '.py')
-
-      try:
-        if not os.path.exists(py_path):
-          os.remove(pyc_path)
-      except OSError:
-        # Wrap OS calls in try/except in case another process touched this file.
-        pass
-
-    try:
-      os.removedirs(dirname)
-    except OSError:
-      # Wrap OS calls in try/except in case another process touched this dir.
-      pass
-
-
-RemoveAllStalePycFiles(os.path.dirname(__file__))
diff --git a/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_options.py b/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_options.py
index 90ab3d1..e8224f7 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_options.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/chrome_browser_options.py
@@ -37,5 +37,6 @@
     # Create a browser with oobe property.
     self.create_browser_with_oobe = False
     self.auto_login = True
+    self.gaia_login = False
     self.username = 'test@test.test'
     self.password = ''
diff --git a/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py b/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py
index 38fe7f7..a48d1ce 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/cros_browser_backend.py
@@ -205,7 +205,7 @@
       self.Close()
       raise
 
-    util.WaitFor(lambda: self.oobe_exists, 30)
+    util.WaitFor(lambda: self.oobe_exists, 10)
 
     if self.browser_options.auto_login:
       if self._is_guest:
@@ -215,8 +215,10 @@
         # incognito browser in a separate process, which we need to wait for.
         util.WaitFor(lambda: pid != self.pid, 10)
         self._WaitForBrowserToComeUp()
+      elif self.browser_options.gaia_login:
+        self._NavigateGaiaLogin()
       else:
-        self._NavigateLogin()
+        self._NavigateFakeLogin()
 
     logging.info('Browser is up!')
 
@@ -279,9 +281,9 @@
     ''')
 
   def _IsLoggedIn(self):
-    """Returns True if cryptohome has mounted, and the oobe has been
-    dismissed."""
-    return (self._cri.IsCryptohomeMounted() and
+    """Returns True if cryptohome has mounted, the browser is
+    responsive to devtools requests, and the oobe has been dismissed."""
+    return (self._cri.IsCryptohomeMounted(self.browser_options.username) and
             self.HasBrowserFinishedLaunching() and
             not self.oobe_exists)
 
@@ -312,19 +314,39 @@
             exceptions.BrowserConnectionGoneException):
       pass
 
-  def _NavigateGuestLogin(self):
-    """Navigates through oobe login screen as guest"""
-    if not self.oobe_exists:
-      raise exceptions.LoginException('Oobe missing')
-    self._WaitForSigninScreen()
-    self._ClickBrowseAsGuest()
-    util.WaitFor(self._IsLoggedIn, 30)
+  def _GaiaLoginContext(self):
+    oobe = self.oobe
+    # TODO(achuith): Implement an api in the oobe instead of calling
+    # chrome.send.
+    oobe.ExecuteJavaScript("chrome.send('addUser');")
+    for gaia_context in range(15):
+      try:
+        if oobe.EvaluateJavaScriptInContext(
+            "document.getElementById('Email') != null", gaia_context):
+          return gaia_context
+      except exceptions.EvaluateException:
+        pass
+    return None
 
-  def _NavigateLogin(self):
-    """Navigates through oobe login screen"""
+  def _NavigateGuestLogin(self):
+    """Navigates through oobe login screen as guest."""
+    logging.info('Logging in as guest')
+    oobe = self.oobe
+    util.WaitFor(lambda: oobe.EvaluateJavaScript(
+        'typeof Oobe !== \'undefined\''), 10)
+
+    if oobe.EvaluateJavaScript(
+        "typeof Oobe.guestLoginForTesting != 'undefined'"):
+      oobe.ExecuteJavaScript('Oobe.guestLoginForTesting();')
+    else:
+      self._WaitForSigninScreen()
+      self._ClickBrowseAsGuest()
+
+    util.WaitFor(lambda: self._cri.IsCryptohomeMounted('$guest'), 30)
+
+  def _NavigateFakeLogin(self):
+    """Logs in using Oobe.loginForTesting."""
     logging.info('Invoking Oobe.loginForTesting')
-    if not self.oobe_exists:
-      raise exceptions.LoginException('Oobe missing')
     oobe = self.oobe
     util.WaitFor(lambda: oobe.EvaluateJavaScript(
         'typeof Oobe !== \'undefined\''), 10)
@@ -336,7 +358,25 @@
     oobe.ExecuteJavaScript(
         'Oobe.loginForTesting(\'%s\', \'%s\');'
             % (self.browser_options.username, self.browser_options.password))
+    self._WaitForLogin()
 
+  def _NavigateGaiaLogin(self):
+    """Logs into the GAIA service with provided credentials."""
+    # TODO(achuith): Fake gaia service with a python server.
+    self._WaitForSigninScreen()
+    gaia_context = util.WaitFor(self._GaiaLoginContext, timeout=10)
+    oobe = self.oobe
+    oobe.ExecuteJavaScriptInContext(
+        "document.getElementById('Email').value='%s';"
+            % self.browser_options.username, gaia_context)
+    oobe.ExecuteJavaScriptInContext(
+        "document.getElementById('Passwd').value='%s';"
+            % self.browser_options.password, gaia_context)
+    oobe.ExecuteJavaScriptInContext(
+        "document.getElementById('signIn').click();", gaia_context)
+    self._WaitForLogin()
+
+  def _WaitForLogin(self):
     try:
       util.WaitFor(self._IsLoggedIn, 60)
     except util.TimeoutException:
@@ -353,11 +393,12 @@
 
     # Workaround for crbug.com/329271, crbug.com/334726.
     retries = 3
-    while not len(self.tab_list_backend):
+    while True:
       try:
         # Open a new window/tab.
         tab = self.tab_list_backend.New(timeout=30)
         tab.Navigate('about:blank', timeout=10)
+        break
       except (exceptions.TabCrashException, util.TimeoutException,
               IndexError):
         retries -= 1
diff --git a/tools/telemetry/telemetry/core/backends/chrome/cros_interface.py b/tools/telemetry/telemetry/core/backends/chrome/cros_interface.py
index 4c2265b..bb49ced 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/cros_interface.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/cros_interface.py
@@ -5,6 +5,7 @@
 import logging
 import os
 import re
+import shutil
 import subprocess
 import sys
 import tempfile
@@ -221,26 +222,52 @@
       f.flush()
       self.PushFile(f.name, remote_filename)
 
+  def GetFile(self, filename, destfile=None):
+    """Copies a local file |filename| to |destfile| on the device.
+
+    Args:
+      filename: The name of the local source file.
+      destfile: The name of the file to copy to, and if it is not specified
+        then it is the basename of the source file.
+
+    """
+    logging.debug("GetFile(%s, %s)" % (filename, destfile))
+    if self.local:
+      if destfile is not None and destfile != filename:
+        shutil.copyfile(filename, destfile)
+      return
+
+    if destfile is None:
+      destfile = os.path.basename(filename)
+    args = ['scp'] + self._ssh_args
+    if self._ssh_identity:
+      args.extend(['-i', self._ssh_identity])
+
+    args.extend(['root@%s:%s' % (self._hostname, filename),
+                 os.path.abspath(destfile)])
+    stdout, stderr = GetAllCmdOutput(args, quiet=True)
+    stderr = self._RemoveSSHWarnings(stderr)
+    if stderr != '':
+      raise OSError('No such file or directory %s' % stderr)
+
   def GetFileContents(self, filename):
+    """Get the contents of a file on the device.
+
+    Args:
+      filename: The name of the file on the device.
+
+    Returns:
+      A string containing the contents of the file.
+    """
+    # TODO: handle the self.local case
     assert not self.local
-    with tempfile.NamedTemporaryFile() as f:
-      args = ['scp'] + self._ssh_args
-      if self._ssh_identity:
-        args.extend(['-i', self._ssh_identity])
-
-      args.extend(['root@%s:%s' % (self._hostname, filename),
-                   os.path.abspath(f.name)])
-
-      stdout, stderr = GetAllCmdOutput(args, quiet=True)
-      stderr = self._RemoveSSHWarnings(stderr)
-
-      if stderr != '':
-        raise OSError('No such file or directory %s' % stderr)
-
-      with open(f.name, 'r') as f2:
-        res = f2.read()
-        logging.debug("GetFileContents(%s)->%s" % (filename, res))
-        return res
+    t = tempfile.NamedTemporaryFile()
+    self.GetFile(filename, t.name)
+    with open(t.name, 'r') as f2:
+      res = f2.read()
+      logging.debug("GetFileContents(%s)->%s" % (filename, res))
+      f2.close()
+      return res
 
   def ListProcesses(self):
     """Returns (pid, cmd, ppid, state) of all processes on the device."""
@@ -325,10 +352,17 @@
         return line_ary[0]
     return None
 
-  def IsCryptohomeMounted(self):
-    """Returns True iff a cryptohome is mounted (either as a user or guest)."""
-    return (self.RunCmdOnDevice(['/usr/sbin/cryptohome',
-                                 '--action=is_mounted'])[0].strip() == 'true')
+  def CryptohomePath(self, user):
+    """Returns the cryptohome mount point for |user|."""
+    return self.RunCmdOnDevice(
+        ['cryptohome-path', 'user', "'%s'" % user])[0].strip()
+
+  def IsCryptohomeMounted(self, username):
+    """Returns True iff |user|'s cryptohome is mounted."""
+    profile_path = self.CryptohomePath(username)
+    mount = self.FilesystemMountedAt(profile_path)
+    mount_prefix = 'guestfs' if username == '$guest' else '/home/.shadow/'
+    return mount and mount.startswith(mount_prefix)
 
   def TakeScreenShot(self, screenshot_prefix):
     """Takes a screenshot, useful for debugging failures."""
diff --git a/tools/telemetry/telemetry/core/backends/chrome/cros_interface_unittest.py b/tools/telemetry/telemetry/core/backends/chrome/cros_interface_unittest.py
index 5b75a6a..896cb6b 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/cros_interface_unittest.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/cros_interface_unittest.py
@@ -7,6 +7,7 @@
 # a bit.
 
 import socket
+import tempfile
 import unittest
 
 from telemetry import test
@@ -52,18 +53,46 @@
     cri = cros_interface.CrOSInterface(
       remote,
       options_for_unittests.GetCopy().cros_ssh_identity)
-    hosts = cri.GetFileContents('/etc/hosts')
-    assert hosts.startswith('# /etc/hosts')
+    hosts = cri.GetFileContents('/etc/lsb-release')
+    self.assertTrue('CHROMEOS' in hosts)
 
   @test.Enabled('cros-chrome')
-  def testGetFileContentsForSomethingThatDoesntExist(self):
+  def testGetFileContentsNonExistent(self):
     remote = options_for_unittests.GetCopy().cros_remote
     cri = cros_interface.CrOSInterface(
       remote,
       options_for_unittests.GetCopy().cros_ssh_identity)
+    f = tempfile.NamedTemporaryFile()
+    cri.PushContents('testGetFileNonExistent', f.name)
+    cri.RmRF(f.name)
     self.assertRaises(
       OSError,
-      lambda: cri.GetFileContents('/tmp/209fuslfskjf/dfsfsf'))
+      lambda: cri.GetFileContents(f.name))
+
+  @test.Enabled('cros-chrome')
+  def testGetFile(self): # pylint: disable=R0201
+    remote = options_for_unittests.GetCopy().cros_remote
+    cri = cros_interface.CrOSInterface(
+      remote,
+      options_for_unittests.GetCopy().cros_ssh_identity)
+    f = tempfile.NamedTemporaryFile()
+    cri.GetFile('/etc/lsb-release', f.name)
+    with open(f.name, 'r') as f2:
+      res = f2.read()
+      self.assertTrue('CHROMEOS' in res)
+
+  @test.Enabled('cros-chrome')
+  def testGetFileNonExistent(self):
+    remote = options_for_unittests.GetCopy().cros_remote
+    cri = cros_interface.CrOSInterface(
+      remote,
+      options_for_unittests.GetCopy().cros_ssh_identity)
+    f = tempfile.NamedTemporaryFile()
+    cri.PushContents('testGetFileNonExistent', f.name)
+    cri.RmRF(f.name)
+    self.assertRaises(
+      OSError,
+      lambda: cri.GetFile(f.name))
 
   @test.Enabled('cros-chrome')
   def testIsServiceRunning(self):
diff --git a/tools/telemetry/telemetry/core/backends/chrome/cros_unittest.py b/tools/telemetry/telemetry/core/backends/chrome/cros_unittest.py
index 0c4690d..6c0d266 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/cros_unittest.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/cros_unittest.py
@@ -20,8 +20,7 @@
     self._cri = cros_interface.CrOSInterface(options.cros_remote,
                                              options.cros_ssh_identity)
     self._is_guest = options.browser_type == 'cros-chrome-guest'
-    self._username = ('$guest' if self._is_guest
-                                else options.browser_options.username)
+    self._username = options.browser_options.username
     self._password = options.browser_options.password
     self._load_extension = None
 
@@ -51,20 +50,11 @@
     self.assertTrue(extension)
     return extension
 
-  def _CryptohomePath(self, user):
-    """Returns the cryptohome mount point for |user|."""
-    return self._cri.RunCmdOnDevice(
-        ['cryptohome-path', 'user', "'%s'" % user])[0].strip()
-
   def _IsCryptohomeMounted(self):
-    """Returns True iff |user|'s cryptohome is mounted."""
-    profile_path = self._CryptohomePath(self._username)
-    mount = self._cri.FilesystemMountedAt(profile_path)
-    if not mount:
-      return False
-    if self._is_guest:
-      return mount == 'guestfs'
-    return mount.startswith('/home/.shadow/')
+    """Returns True if cryptohome is mounted. as determined by the cmd
+    cryptohome --action=is_mounted"""
+    return self._cri.RunCmdOnDevice(
+        ['/usr/sbin/cryptohome', '--action=is_mounted'])[0].strip() == 'true'
 
   @test.Enabled('chromeos')
   def testCryptohome(self):
@@ -82,7 +72,7 @@
         self.assertEquals(chronos_fs, 'guestfs')
       else:
         crypto_fs = self._cri.FilesystemMountedAt(
-            self._CryptohomePath(self._username))
+            self._cri.CryptohomePath(self._username))
         self.assertEquals(crypto_fs, chronos_fs)
 
     self.assertFalse(self._IsCryptohomeMounted())
diff --git a/tools/telemetry/telemetry/core/backends/chrome/inspector_backend.py b/tools/telemetry/telemetry/core/backends/chrome/inspector_backend.py
index 640c64f..ce74b76 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/inspector_backend.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/inspector_backend.py
@@ -53,14 +53,18 @@
 
   def _Connect(self, timeout=10):
     assert not self._socket
+    logging.debug('InspectorBackend._Connect() to %s' % self.debugger_url)
     try:
       self._socket = websocket.create_connection(self.debugger_url,
           timeout=timeout)
-    except (websocket.WebSocketException):
-      if self._browser_backend.IsBrowserRunning():
-        raise exceptions.TabCrashException(sys.exc_info()[1])
+    except (websocket.WebSocketException, util.TimeoutException):
+      err_msg = sys.exc_info()[1]
+      if not self._browser_backend.IsBrowserRunning():
+        raise exceptions.BrowserGoneException(err_msg)
+      elif not self._browser_backend.HasBrowserFinishedLaunching():
+        raise exceptions.BrowserConnectionGoneException(err_msg)
       else:
-        raise exceptions.BrowserGoneException()
+        raise exceptions.TabCrashException(err_msg)
 
     self._cur_socket_timeout = 0
     self._next_request_id = 0
@@ -93,15 +97,6 @@
   def debugger_url(self):
     return self._context['webSocketDebuggerUrl']
 
-  # TODO(tonyg): TabListBackend should ask InspectorBackend to
-  # Activate and Close, not the other way around (crbug.com/233001).
-
-  def Activate(self):
-    self._browser_backend.tab_list_backend.ActivateTab(self.debugger_url)
-
-  def Close(self):
-    self._browser_backend.tab_list_backend.CloseTab(self.debugger_url)
-
   # Public methods implemented in JavaScript.
 
   @property
diff --git a/tools/telemetry/telemetry/core/backends/chrome/inspector_backend_list.py b/tools/telemetry/telemetry/core/backends/chrome/inspector_backend_list.py
index c1a4a3d..2f7385e 100644
--- a/tools/telemetry/telemetry/core/backends/chrome/inspector_backend_list.py
+++ b/tools/telemetry/telemetry/core/backends/chrome/inspector_backend_list.py
@@ -15,15 +15,16 @@
 class InspectorBackendList(collections.Sequence):
   """A dynamic sequence of active InspectorBackends."""
 
-  def __init__(self, browser_backend, backend_wrapper=None):
+  def __init__(self, browser_backend, backend_wrapper):
     """Constructor.
 
     Args:
       browser_backend: The BrowserBackend instance to query for
           InspectorBackends.
       backend_wrapper: A public interface for wrapping each
-          InspectorBackend. It must accept a single argument of the
-          InspectorBackend to wrap and may expose whatever methods
+          InspectorBackend. It must accept an argument of the
+          InspectorBackend to wrap, and an argument of the
+          InspectorBackendList, and may expose whatever methods
           are desired on top of that backend.
     """
     self._browser_backend = browser_backend
@@ -54,8 +55,7 @@
       backend = inspector_backend.InspectorBackend(
           self._browser_backend,
           self._inspectable_contexts_dict[context_id])
-      if self._backend_wrapper:
-        backend = self._backend_wrapper(backend)
+      backend = self._backend_wrapper(backend, self)
       self._inspector_backend_dict[context_id] = backend
     return self._inspector_backend_dict[context_id]
 
@@ -83,6 +83,15 @@
     for context_id in self._inspectable_contexts_dict.keys():
       if context_id not in context_ids:
         del self._inspectable_contexts_dict[context_id]
+      else:
+        # Also remove inspectable contexts that have no websocketDebuggerUrls.
+        context = next(context for context in contexts
+                      if context['id'] == context_id)
+        if (context_id not in self._inspector_backend_dict.keys() and
+            'webSocketDebuggerUrl' not in context):
+          logging.debug('webSocketDebuggerUrl missing, removing %s'
+                        % context_id)
+          del self._inspectable_contexts_dict[context_id]
 
     # Clean up any backends for contexts that have gone away.
     for context_id in self._inspector_backend_dict.keys():
diff --git a/tools/telemetry/telemetry/core/discover.py b/tools/telemetry/telemetry/core/discover.py
index 88f22bd..5b9ac0b 100644
--- a/tools/telemetry/telemetry/core/discover.py
+++ b/tools/telemetry/telemetry/core/discover.py
@@ -9,6 +9,7 @@
 
 from telemetry import decorators
 from telemetry.core import camel_case
+from telemetry.core import util
 
 
 @decorators.Cache
@@ -95,13 +96,30 @@
 
   return classes
 
+_counter = [0]
+def _GetUniqueModuleName():
+  _counter[0] += 1
+  return "module_" + str(_counter[0])
+
+def IsPageSetFile(file_path):
+  root_name, ext_name = os.path.splitext(file_path)
+  if ext_name == '.json':
+    return True
+  elif ext_name != '.py':
+    return False
+  if 'unittest' in root_name or root_name in ('PRESUBMIT', '__init__'):
+    return False
+  module = util.GetPythonPageSetModule(file_path)
+  for class_name in dir(module):
+    if class_name.endswith('PageSet') and class_name != 'PageSet':
+      return True
+  return False
+
 def GetAllPageSetFilenames(dir_path):
   results = []
-  start_dir = os.path.dirname(dir_path)
-  for dirpath, _, filenames in os.walk(start_dir):
+  for sub_path, _, filenames in os.walk(dir_path):
     for f in filenames:
-      if os.path.splitext(f)[1] != '.json':
-        continue
-      filename = os.path.join(dirpath, f)
-      results.append(filename)
+      filename = os.path.join(sub_path, f)
+      if IsPageSetFile(filename):
+        results.append(filename)
   return results
diff --git a/tools/telemetry/telemetry/core/discover_unittest.py b/tools/telemetry/telemetry/core/discover_unittest.py
index 34bc891..c3df4a4 100644
--- a/tools/telemetry/telemetry/core/discover_unittest.py
+++ b/tools/telemetry/telemetry/core/discover_unittest.py
@@ -50,3 +50,14 @@
         'dummy_exception_impl2': 'DummyExceptionImpl2',
     }
     self.assertEqual(actual_classes, expected_classes)
+
+  def testIsPageSetFile(self):
+    top_10_ps_dir = os.path.join(util.GetChromiumSrcDir(),
+                                 'tools/perf/page_sets/top_10.py')
+    test_ps_dir = os.path.join(util.GetTelemetryDir(),
+                               'unittest_data/test_page_set.py')
+    page_set_dir = os.path.join(util.GetTelemetryDir(),
+                               'telemetry/page/page_set.py')
+    self.assertTrue(discover.IsPageSetFile(top_10_ps_dir))
+    self.assertFalse(discover.IsPageSetFile(test_ps_dir))
+    self.assertFalse(discover.IsPageSetFile(page_set_dir))
diff --git a/tools/telemetry/telemetry/core/extension_page.py b/tools/telemetry/telemetry/core/extension_page.py
index 3423e68..b76d7b8 100644
--- a/tools/telemetry/telemetry/core/extension_page.py
+++ b/tools/telemetry/telemetry/core/extension_page.py
@@ -14,8 +14,8 @@
 class ExtensionPage(web_contents.WebContents):
   """Represents an extension page in the browser"""
 
-  def __init__(self, inspector_backend):
-    super(ExtensionPage, self).__init__(inspector_backend)
+  def __init__(self, inspector_backend, backend_list):
+    super(ExtensionPage, self).__init__(inspector_backend, backend_list)
     self.url = inspector_backend.url
     self.extension_id = UrlToExtensionId(self.url)
 
diff --git a/tools/telemetry/telemetry/core/platform/__init__.py b/tools/telemetry/telemetry/core/platform/__init__.py
index f797408..76d6401 100644
--- a/tools/telemetry/telemetry/core/platform/__init__.py
+++ b/tools/telemetry/telemetry/core/platform/__init__.py
@@ -211,7 +211,8 @@
     """Stops monitoring power utilization and returns collects stats
 
     Returns:
-      A dict of power utilization statistics containing: {
+      None if power measurement failed for some reason, otherwise a dict of
+      power utilization statistics containing: {
         # An identifier for the data provider. Allows to evaluate the precision
         # of the data. Example values: monsoon, powermetrics, ds2784
         'identifier': identifier,
diff --git a/tools/telemetry/telemetry/core/platform/mac_platform_backend.py b/tools/telemetry/telemetry/core/platform/mac_platform_backend.py
index 5f6f85c..631a562 100644
--- a/tools/telemetry/telemetry/core/platform/mac_platform_backend.py
+++ b/tools/telemetry/telemetry/core/platform/mac_platform_backend.py
@@ -47,7 +47,11 @@
 
   def _GetIdleWakeupCount(self, pid):
     top_output = self._GetTopOutput(pid, ['idlew'])
-    assert top_output[-2] == 'IDLEW'
+
+    # Sometimes top won't return anything here, just ignore such cases -
+    # crbug.com/354812 .
+    if top_output[-2] != 'IDLEW':
+      return 0
     # Numbers reported by top may have a '+' appended.
     wakeup_count = int(top_output[-1].strip('+ '))
     return wakeup_count
@@ -151,7 +155,7 @@
   def FlushEntireSystemCache(self):
     mavericks_or_later = self.GetOSVersionName() >= MAVERICKS
     p = self.LaunchApplication('purge', elevate_privilege=mavericks_or_later)
-    p.wait()
+    p.communicate()
     assert p.returncode == 0, 'Failed to flush system cache'
 
   def CanMonitorPowerAsync(self):
diff --git a/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor.py b/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor.py
index 5e53af0..b924b70 100644
--- a/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor.py
+++ b/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor.py
@@ -84,8 +84,12 @@
     """Parse output of powermetrics command line utility.
 
     Returns:
-        Dictionary in the format returned by StopMonitoringPowerAsync().
+        Dictionary in the format returned by StopMonitoringPowerAsync() or None
+        if |powermetrics_output| is empty - crbug.com/353250 .
     """
+    if len(powermetrics_output) == 0:
+      logging.warning("powermetrics produced zero length output")
+      return None
 
     # Container to collect samples for running averages.
     # out_path - list containing the key path in the output dictionary.
@@ -239,13 +243,16 @@
     try:
       self._powermetrics_process.send_signal(signal.SIGINFO)
       self._powermetrics_process.send_signal(signal.SIGTERM)
-      returncode = self._powermetrics_process.wait()
+      (power_stdout, power_stderr) = self._powermetrics_process.communicate()
+      returncode = self._powermetrics_process.returncode
       assert returncode in [0, -15], (
-          "powermetrics return code: %d" % returncode)
+          """powermetrics error
+          return code=%d
+          stdout=(%s)
+          stderr=(%s)""" % (returncode, power_stdout, power_stderr))
 
       with open(self._output_filename, 'rb') as output_file:
         powermetrics_output = output_file.read()
-      assert len(powermetrics_output) > 0
       return PowerMetricsPowerMonitor.ParsePowerMetricsOutput(
           powermetrics_output)
 
diff --git a/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor_unittest.py b/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor_unittest.py
index b1ab68d..df3c094 100644
--- a/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor_unittest.py
+++ b/tools/telemetry/telemetry/core/platform/power_monitor/powermetrics_power_monitor_unittest.py
@@ -24,6 +24,12 @@
         "Error checking powermetrics availability: '%s'" % '|'.join(os.uname()))
 
   @test.Enabled('mac')
+  def testParseEmptyPowerMetricsOutput(self):
+    # Important to handle zero length powermetrics outout - crbug.com/353250 .
+    self.assertIsNone(powermetrics_power_monitor.PowerMetricsPowerMonitor.
+        ParsePowerMetricsOutput(''))
+
+  @test.Enabled('mac')
   def testParsePowerMetricsOutput(self):
     def getOutput(output_file):
       test_data_path = os.path.join(util.GetUnittestDataDir(),
diff --git a/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py
index d16c35a..030ccb2 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/android_screen_recorder_profiler.py
@@ -36,7 +36,6 @@
 
   def CollectProfile(self):
     self._recorder.communicate(input='\n')
-    self._recorder.wait()
 
     print 'Screen recording saved as %s' % self._output_path
     print 'To view, open in Chrome or a video player'
diff --git a/tools/telemetry/telemetry/core/platform/profiler/android_systrace_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/android_systrace_profiler.py
index fb4767c..43acaf6 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/android_systrace_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/android_systrace_profiler.py
@@ -53,7 +53,7 @@
   def CollectProfile(self):
     self._profiler.communicate(input='\n')
     trace_result = self._browser_backend.StopTracing()
-    self._profiler.wait()
+    self._profiler.communicate()
 
     trace_file = StringIO.StringIO()
     trace_result.Serialize(trace_file)
diff --git a/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py b/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py
index efef875..edefdde 100644
--- a/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py
+++ b/tools/telemetry/telemetry/core/platform/profiler/vtune_profiler.py
@@ -91,9 +91,10 @@
         browser_type.startswith('cros')):
       return False
     try:
-      return not subprocess.Popen(['amplxe-cl', '-version'],
-                                  stderr=subprocess.STDOUT,
-                                  stdout=subprocess.PIPE).wait()
+      proc = subprocess.Popen(['amplxe-cl', '-version'],
+                              stderr=subprocess.STDOUT,
+                              stdout=subprocess.PIPE).communicate()
+      return not proc.returncode
     except OSError:
       return False
 
diff --git a/tools/telemetry/telemetry/core/platform/win_platform_backend.py b/tools/telemetry/telemetry/core/platform/win_platform_backend.py
index 34c85da..7597488 100644
--- a/tools/telemetry/telemetry/core/platform/win_platform_backend.py
+++ b/tools/telemetry/telemetry/core/platform/win_platform_backend.py
@@ -83,7 +83,7 @@
     if kill_process_tree:
       cmd.append('/T')
     subprocess.Popen(cmd, stdout=subprocess.PIPE,
-                     stderr=subprocess.STDOUT).wait()
+                     stderr=subprocess.STDOUT).communicate()
 
   def GetSystemProcessInfo(self):
     # [3:] To skip 2 blank lines and header.
diff --git a/tools/telemetry/telemetry/core/repeat_options.py b/tools/telemetry/telemetry/core/repeat_options.py
index 9d50ca3..78adb84 100644
--- a/tools/telemetry/telemetry/core/repeat_options.py
+++ b/tools/telemetry/telemetry/core/repeat_options.py
@@ -15,12 +15,14 @@
 
   @classmethod
   def AddCommandLineArgs(cls, parser):
+    """Adds the repeat options group to the given options parser."""
     group = optparse.OptionGroup(parser, 'Repeat options')
     group.add_option('--page-repeat', default=1, type='int',
                      help='Number of times to repeat each individual page '
                      'before proceeding with the next page in the pageset.')
     group.add_option('--pageset-repeat', default=1, type='int',
                      help='Number of times to repeat the entire pageset.')
+    parser.add_option_group(group)
 
   def UpdateFromParseResults(self, finder_options):
     """Copies options from the given options object to this object."""
diff --git a/tools/telemetry/telemetry/core/tab.py b/tools/telemetry/telemetry/core/tab.py
index 7f86432..5e6138d 100644
--- a/tools/telemetry/telemetry/core/tab.py
+++ b/tools/telemetry/telemetry/core/tab.py
@@ -23,8 +23,8 @@
       # Evaluates 1+1 in the tab's JavaScript context.
       tab.Evaluate('1+1')
   """
-  def __init__(self, inspector_backend):
-    super(Tab, self).__init__(inspector_backend)
+  def __init__(self, inspector_backend, backend_list):
+    super(Tab, self).__init__(inspector_backend, backend_list)
     self._tab_contents_bounding_box = None
 
   @property
@@ -64,7 +64,14 @@
     and the page's documentVisibilityState becoming 'visible', and yet more
     delay until the actual tab is visible to the user. None of these delays
     are included in this call."""
-    self._inspector_backend.Activate()
+    self._backend_list.ActivateTab(self._inspector_backend.debugger_url)
+
+  def Close(self):
+    """Closes this tab.
+
+    Not all browsers or browser versions support this method.
+    Be sure to check browser.supports_tab_control."""
+    self._backend_list.CloseTab(self._inspector_backend.debugger_url)
 
   @property
   def screenshot_supported(self):
diff --git a/tools/telemetry/telemetry/core/util.py b/tools/telemetry/telemetry/core/util.py
index 55a2863..e44bd26 100644
--- a/tools/telemetry/telemetry/core/util.py
+++ b/tools/telemetry/telemetry/core/util.py
@@ -1,6 +1,7 @@
 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
+import imp
 import inspect
 import logging
 import os
@@ -39,6 +40,14 @@
   if os.path.isdir(path) and path not in sys.path:
     sys.path.append(path)
 
+_counter = [0]
+def _GetUniqueModuleName():
+  _counter[0] += 1
+  return "page_set_module_" + str(_counter[0])
+
+def GetPythonPageSetModule(file_path):
+  return imp.load_source(_GetUniqueModuleName(), file_path)
+
 
 def WaitFor(condition, timeout):
   """Waits for up to |timeout| secs for the function |condition| to return True.
diff --git a/tools/telemetry/telemetry/core/web_contents.py b/tools/telemetry/telemetry/core/web_contents.py
index 15c87e8..25cc175 100644
--- a/tools/telemetry/telemetry/core/web_contents.py
+++ b/tools/telemetry/telemetry/core/web_contents.py
@@ -12,20 +12,14 @@
 # independent of Tab.
 class WebContents(object):
   """Represents web contents in the browser"""
-  def __init__(self, inspector_backend):
+  def __init__(self, inspector_backend, backend_list):
     self._inspector_backend = inspector_backend
+    self._backend_list = backend_list
 
     with open(os.path.join(os.path.dirname(__file__),
         'network_quiescence.js')) as f:
       self._quiescence_js = f.read()
 
-  def Close(self):
-    """Closes this page.
-
-    Not all browsers or browser versions support this method.
-    Be sure to check browser.supports_tab_control."""
-    self._inspector_backend.Close()
-
   def WaitForDocumentReadyStateToBeComplete(self,
       timeout=DEFAULT_WEB_CONTENTS_TIMEOUT):
     self.WaitForJavaScriptExpression(
diff --git a/tools/telemetry/telemetry/exception_formatter.py b/tools/telemetry/telemetry/exception_formatter.py
deleted file mode 100644
index 8dafd44..0000000
--- a/tools/telemetry/telemetry/exception_formatter.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Print prettier and more detailed exceptions."""
-
-import math
-import os
-import sys
-import traceback
-
-from telemetry.core import util
-
-
-def InstallUnhandledExceptionFormatter():
-  sys.excepthook = PrintFormattedException
-
-
-def PrintFormattedException(exception_class, exception, tb):
-  """Prints an Exception in a more useful format than the default.
-
-  TODO(tonyg): Consider further enhancements. For instance:
-    - Report stacks to maintainers like depot_tools does.
-    - Add a debug flag to automatically start pdb upon exception.
-  """
-  def _GetFinalFrame(frame):
-    final_frame = None
-    while frame is not None:
-      final_frame = frame
-      frame = frame.tb_next
-    return final_frame
-
-  def _AbbreviateMiddle(target, middle, length):
-    assert length >= 0, 'Must provide positive length'
-    assert len(middle) <= length, 'middle must not be greater than length'
-    if len(target) <= length:
-      return target
-    half_length = (length - len(middle)) / 2.
-    return '%s%s%s' % (target[:int(math.floor(half_length))],
-                       middle,
-                       target[-int(math.ceil(half_length)):])
-
-  base_dir = os.path.abspath(util.GetChromiumSrcDir())
-  formatted_exception = traceback.format_exception(
-      exception_class, exception, tb)
-  extracted_tb = traceback.extract_tb(tb)
-  traceback_header = formatted_exception[0].strip()
-  exception = ''.join([l[2:] if l[:2] == '  ' else l for l in
-                       traceback.format_exception_only(exception_class,
-                                                       exception)])
-  local_variables = [(variable, value) for variable, value in
-                     _GetFinalFrame(tb).tb_frame.f_locals.iteritems()
-                     if variable != 'self']
-
-  # Format the traceback.
-  print >> sys.stderr
-  print >> sys.stderr, traceback_header
-  for filename, line, function, text in extracted_tb:
-    filename = os.path.abspath(filename)
-    if filename.startswith(base_dir):
-      filename = filename[len(base_dir)+1:]
-    print >> sys.stderr, '  %s at %s:%d' % (function, filename, line)
-    print >> sys.stderr, '    %s' % text
-
-  # Format the locals.
-  if local_variables:
-    print >> sys.stderr
-    print >> sys.stderr, 'Locals:'
-    longest_variable = max([len(v) for v, _ in local_variables])
-    for variable, value in sorted(local_variables):
-      value = repr(value)
-      possibly_truncated_value = _AbbreviateMiddle(value, ' ... ', 1024)
-      truncation_indication = ''
-      if len(possibly_truncated_value) != len(value):
-        truncation_indication = ' (truncated)'
-      print >> sys.stderr, '  %s: %s%s' % (variable.ljust(longest_variable + 1),
-                                           possibly_truncated_value,
-                                           truncation_indication)
-
-  # Format the exception.
-  print >> sys.stderr
-  print >> sys.stderr, exception
diff --git a/tools/telemetry/telemetry/interactive_debugging.py b/tools/telemetry/telemetry/interactive_debugging.py
deleted file mode 100644
index 3345260..0000000
--- a/tools/telemetry/telemetry/interactive_debugging.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""When SIGUSR1 is received, print a stack trace."""
-
-import signal
-import traceback
-
-
-def _PrintDiagnostics(_, stack_frame):
-  print """"SIGUSR1 received, printing stack trace:
-      %s""" % ("".join(traceback.format_stack(stack_frame)))
-
-def InstallDebuggingHooks():
-  # Windows doesn't define SIGUSR1.
-  if not hasattr(signal, 'SIGUSR1'):
-    return
-
-  signal.signal(signal.SIGUSR1, _PrintDiagnostics)
diff --git a/tools/telemetry/telemetry/page/actions/action_runner.py b/tools/telemetry/telemetry/page/actions/action_runner.py
new file mode 100644
index 0000000..a790894
--- /dev/null
+++ b/tools/telemetry/telemetry/page/actions/action_runner.py
@@ -0,0 +1,20 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class ActionRunner(object):
+  def __init__(self, page, tab, page_test=None):
+    self._page = page
+    self._tab = tab
+    self._page_test = page_test
+
+  def RunAction(self, action):
+    if not action.WillWaitAfterRun():
+      action.WillRunAction(self._page, self._tab)
+    if self._page_test:
+      self._page_test.WillRunAction(self._page, self._tab, action)
+    try:
+      action.RunActionAndMaybeWait(self._page, self._tab)
+    finally:
+      if self._page_test:
+        self._page_test.DidRunAction(self._page, self._tab, action)
diff --git a/tools/telemetry/telemetry/page/actions/page_action.py b/tools/telemetry/telemetry/page/actions/page_action.py
index 04e7427..f342888 100644
--- a/tools/telemetry/telemetry/page/actions/page_action.py
+++ b/tools/telemetry/telemetry/page/actions/page_action.py
@@ -30,17 +30,6 @@
     else:
       self.wait_until = None
 
-  def CustomizeBrowserOptionsForPageSet(self, options):
-    """Override to add action-specific options to the BrowserOptions
-    object. These options will be set for the whole page set.
-
-    If the browser is not being restarted for every page in the page set then
-    all browser options required for the action must be set here. This, however,
-    requires that they do not conflict with options require by other actions
-    used up by the page set.
-    """
-    pass
-
   def WillRunAction(self, page, tab):
     """Override to do action-specific setup before
     Test.WillRunAction is called."""
diff --git a/tools/telemetry/telemetry/page/actions/pinch.js b/tools/telemetry/telemetry/page/actions/pinch.js
index 499c557..0a2b15d 100644
--- a/tools/telemetry/telemetry/page/actions/pinch.js
+++ b/tools/telemetry/telemetry/page/actions/pinch.js
@@ -63,7 +63,7 @@
                                    this.options_.pixels_to_cover_,
                                    anchor_left, anchor_top,
                                    this.onGestureComplete_.bind(this),
-                                   this.speed_);
+                                   this.options_.speed_);
   };
 
   PinchAction.prototype.onGestureComplete_ = function() {
diff --git a/tools/telemetry/telemetry/page/actions/scroll_unittest.py b/tools/telemetry/telemetry/page/actions/scroll_unittest.py
index cb5cb4f..98684f9 100644
--- a/tools/telemetry/telemetry/page/actions/scroll_unittest.py
+++ b/tools/telemetry/telemetry/page/actions/scroll_unittest.py
@@ -16,12 +16,11 @@
     super(ScrollActionTest, self).setUp()
 
   def CreateAndNavigateToPageFromUnittestDataDir(
-    self, filename, page_attributes):
+    self, filename):
     self._browser.SetHTTPServerDirectories(util.GetUnittestDataDir())
     page = page_module.Page(
       self._browser.http_server.UrlOf(filename),
-      None, # In this test, we don't need a page set.
-      attributes=page_attributes)
+      None) # In this test, we don't need a page set.
 
     self._tab.Navigate(page.url)
     self._tab.WaitForDocumentReadyStateToBeComplete()
@@ -30,11 +29,8 @@
 
   @test.Disabled  # Disabled due to flakiness: crbug.com/330544
   def testScrollAction(self):
-    page = self.CreateAndNavigateToPageFromUnittestDataDir(
-        "blank.html",
-        page_attributes={"smoothness": {
-          "action": "scroll"
-          }})
+    page = self.CreateAndNavigateToPageFromUnittestDataDir("blank.html")
+    setattr(page, 'smoothness', {"action": "scroll"})
     # Make page bigger than window so it's scrollable.
     self._tab.ExecuteJavaScript("""document.body.style.height =
                               (2 * window.innerHeight + 1) + 'px';""")
@@ -69,7 +65,7 @@
                             (scroll_position, scroll_height))
 
   def testBoundingClientRect(self):
-    self.CreateAndNavigateToPageFromUnittestDataDir('blank.html', {})
+    self.CreateAndNavigateToPageFromUnittestDataDir('blank.html')
     with open(os.path.join(os.path.dirname(__file__),
                            'gesture_common.js')) as f:
       js = f.read()
diff --git a/tools/telemetry/telemetry/page/actions/tap.js b/tools/telemetry/telemetry/page/actions/tap.js
index 8a1c731..8d42247 100644
--- a/tools/telemetry/telemetry/page/actions/tap.js
+++ b/tools/telemetry/telemetry/page/actions/tap.js
@@ -17,7 +17,7 @@
       this.element_ = document.body;
       this.left_position_percentage_ = 0.5;
       this.top_position_percentage_ = 0.5;
-      this.duration_ms_ = 0;
+      this.duration_ms_ = 50;
       this.gesture_source_type_ = chrome.gpuBenchmarking.DEFAULT_INPUT;
     }
   }
diff --git a/tools/telemetry/telemetry/page/actions/tap.py b/tools/telemetry/telemetry/page/actions/tap.py
index 202a005..716109a 100644
--- a/tools/telemetry/telemetry/page/actions/tap.py
+++ b/tools/telemetry/telemetry/page/actions/tap.py
@@ -67,7 +67,7 @@
   def RunGesture(self, page, tab):
     left_position_percentage = 0.5
     top_position_percentage = 0.5
-    duration_ms = 0
+    duration_ms = 50
     gesture_source_type = GestureAction.GetGestureSourceTypeFromOptions(tab)
     if hasattr(self, 'left_position_percentage'):
       left_position_percentage = self.left_position_percentage
diff --git a/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py b/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py
index f9ed552..55147c4 100644
--- a/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py
+++ b/tools/telemetry/telemetry/page/buildbot_page_measurement_results.py
@@ -2,12 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-from collections import defaultdict
-
 from telemetry import value as value_module
 from telemetry.page import page_measurement_results
 from telemetry.page import perf_tests_helper
-from telemetry.value import merge_values
+from telemetry.value import summary as summary_module
 
 
 class BuildbotPageMeasurementResults(
@@ -23,6 +21,10 @@
     self._output_stream.write(output + '\n')
     self._output_stream.flush()
 
+  @property
+  def had_errors_or_failures(self):
+    return self.errors or self.failures
+
   def PrintSummary(self):
     """Print summary data in a format expected by buildbot for perf dashboards.
 
@@ -32,108 +34,20 @@
     # Print out the list of unique pages.
     perf_tests_helper.PrintPages(
         [page.display_name for page in self.pages_that_succeeded])
-    self._PrintPerPageResults()
+    summary = summary_module.Summary(self.all_page_specific_values,
+                                     self.had_errors_or_failures)
+    for value in summary.interleaved_computed_per_page_values_and_summaries:
+      if value.page:
+        self._PrintComputedPerPageValue(value)
+      else:
+        self._PrintComputedSummaryValue(value)
     self._PrintOverallResults()
 
-  @property
-  def had_errors_or_failures(self):
-    return self.errors or self.failures
-
-  def _PrintPerPageResults(self):
-    all_successful_page_values = self.all_page_specific_values
-
-    # We will later need to determine how many values were originally created
-    # for each value name, to apply a workaround meant to clean up the printf
-    # output.
-    num_successful_pages_for_value_name = defaultdict(int)
-    for v in all_successful_page_values:
-      num_successful_pages_for_value_name[v.name] += 1
-
-    # By here, due to page repeat options, all_values_from_successful_pages
-    # contains values of the same name not only from mulitple pages, but also
-    # from the same name. So even if, for instance, only one page ran, it may
-    # have run twice, producing two 'x' values.
-    #
-    # So, get rid of the repeated pages by merging.
-    merged_page_values = merge_values.MergeLikeValuesFromSamePage(
-        all_successful_page_values)
-
-    # Now we have a bunch of values, but there is only one value_name per page.
-    # Suppose page1 and page2 ran, producing values x and y. We want to print
-    #    x_by_url for page1
-    #    x_by_url for page2
-    #    x for page1, page2 combined
-    #
-    #    y_by_url for page1
-    #    y_by_url for page2
-    #    y for page1, page2 combined
-    #
-    # We already have the x_by_url values in the values array. But, we will need
-    # them indexable by the value name.
-    #
-    # The following dict maps value_name -> list of pages that have values of
-    # that name.
-    per_page_values_by_value_name = defaultdict(list)
-    for value in merged_page_values:
-      per_page_values_by_value_name[value.name].append(value)
-
-    # We already have the x_by_url values in the values array. But, we also need
-    # the values merged across the pages. And, we will need them indexed by
-    # value name so that we can find them when printing out value names in
-    # alphabetical order.
-    merged_pages_value_by_value_name = {}
-    if not self.pages_that_had_errors_or_failures:
-      for value in merge_values.MergeLikeValuesFromDifferentPages(
-          all_successful_page_values):
-        assert value.name not in merged_pages_value_by_value_name
-        merged_pages_value_by_value_name[value.name] = value
-
-    # sorted_value names will govern the order we start printing values.
-    value_names = set([v.name for v in merged_page_values])
-    sorted_value_names = sorted(value_names)
-
-    # Time to walk through the values by name, printing first the by_url values
-    # and then the merged_site value.
-    for value_name in sorted_value_names:
-      per_page_values = per_page_values_by_value_name.get(value_name, [])
-
-      # Sort the values by their url
-      sorted_per_page_values = list(per_page_values)
-      sorted_per_page_values.sort(
-          key=lambda per_page_values: per_page_values.page.display_name)
-
-      # Output the _by_url results.
-      num_successful_pages_for_this_value_name = (
-          num_successful_pages_for_value_name[value_name])
-      for per_page_value in sorted_per_page_values:
-        self._PrintPerPageValue(per_page_value,
-                                num_successful_pages_for_this_value_name)
-
-      # Output the combined values.
-      merged_pages_value = merged_pages_value_by_value_name.get(value_name,
-                                                                None)
-      if merged_pages_value:
-        self._PrintMergedPagesValue(merged_pages_value)
-
-  def _PrintPerPageValue(self, value, num_successful_pages_for_this_value_name):
+  def _PrintComputedPerPageValue(self, value):
     # We dont print per-page-values when there is a trace tag.
     if self._trace_tag:
       return
 
-    # If there were any page errors, we typically will print nothing.
-    #
-    # Note: this branch is structured less-densely to improve legibility.
-    if num_successful_pages_for_this_value_name > 1:
-      should_print = True
-    elif (self.had_errors_or_failures and
-         num_successful_pages_for_this_value_name == 1):
-      should_print = True
-    else:
-      should_print = False
-
-    if not should_print:
-      return
-
     # Actually print the result.
     buildbot_value = value.GetBuildbotValue()
     buildbot_data_type = value.GetBuildbotDataType(
@@ -144,7 +58,7 @@
                           buildbot_trace_name,
                           buildbot_value, value.units, buildbot_data_type)
 
-  def _PrintMergedPagesValue(self, value):
+  def _PrintComputedSummaryValue(self, value):
     # If there were any page errors, we typically will print nothing.
     #
     # Note: this branch is structured less-densely to improve legibility.
@@ -153,9 +67,9 @@
 
     buildbot_value = value.GetBuildbotValue()
     buildbot_data_type = value.GetBuildbotDataType(
-        output_context=value_module.MERGED_PAGES_RESULT_OUTPUT_CONTEXT)
+        output_context=value_module.COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT)
     buildbot_measurement_name, buildbot_trace_name = (
-        value.GetBuildbotMeasurementAndTraceNameForMergedPagesResult(
+        value.GetBuildbotMeasurementAndTraceNameForComputedSummaryResult(
             self._trace_tag))
 
     self._PrintPerfResult(buildbot_measurement_name,
@@ -171,7 +85,7 @@
         buildbot_data_type = value.GetBuildbotDataType(
             output_context=value_module.SUMMARY_RESULT_OUTPUT_CONTEXT)
         buildbot_measurement_name, buildbot_trace_name = (
-            value.GetBuildbotMeasurementAndTraceNameForMergedPagesResult(
+            value.GetBuildbotMeasurementAndTraceNameForComputedSummaryResult(
                 self._trace_tag))
         self._PrintPerfResult(
             buildbot_measurement_name,
diff --git a/tools/telemetry/telemetry/page/page.py b/tools/telemetry/telemetry/page/page.py
index 8d189cd..0269261 100644
--- a/tools/telemetry/telemetry/page/page.py
+++ b/tools/telemetry/telemetry/page/page.py
@@ -10,31 +10,33 @@
 
 
 class Page(object):
-  def __init__(self, url, page_set, attributes=None, base_dir=None):
+  def __init__(self, url, page_set=None, base_dir=None):
     self.url = url
     self.page_set = page_set
     self._base_dir = base_dir
 
     # These attributes can be set dynamically by the page.
+    self.startup_url = page_set.startup_url if page_set else ''
     self.credentials = None
     self.disabled = False
     self.name = None
     self.script_to_evaluate_on_commit = None
+    self._SchemeErrorCheck()
 
-    if attributes:
-      for k, v in attributes.iteritems():
-        setattr(self, k, v)
-
+  def _SchemeErrorCheck(self):
     if not self._scheme:
       raise ValueError('Must prepend the URL with scheme (e.g. file://)')
 
-    if hasattr(self, 'startup_url') and self.startup_url:
+    if self.startup_url:
       startup_url_scheme = urlparse.urlparse(self.startup_url).scheme
       if not startup_url_scheme:
         raise ValueError('Must prepend the URL with scheme (e.g. http://)')
       if startup_url_scheme == 'file':
         raise ValueError('startup_url with local file scheme is not supported')
 
+  # With python page_set, this property will no longer be needed since pages can
+  # share property through a common ancestor class.
+  # TODO(nednguyen): remove this when crbug.com/239179 is marked fixed
   def __getattr__(self, name):
     # Inherit attributes from the page set.
     if self.page_set and hasattr(self.page_set, name):
@@ -42,6 +44,7 @@
     raise AttributeError(
         '%r object has no attribute %r' % (self.__class__, name))
 
+
   @decorators.Cache
   def GetSyntheticDelayCategories(self):
     if not hasattr(self, 'synthetic_delays'):
@@ -65,6 +68,10 @@
   def __str__(self):
     return self.url
 
+  def AddCustomizeBrowserOptions(self, options):
+    """ Inherit page overrides this to add customized browser options."""
+    pass
+
   @property
   def _scheme(self):
     return urlparse.urlparse(self.url).scheme
diff --git a/tools/telemetry/telemetry/page/page_filter_unittest.py b/tools/telemetry/telemetry/page/page_filter_unittest.py
index 01f6416..70e7410 100644
--- a/tools/telemetry/telemetry/page/page_filter_unittest.py
+++ b/tools/telemetry/telemetry/page/page_filter_unittest.py
@@ -28,18 +28,12 @@
 class PageFilterTest(unittest.TestCase):
   def setUp(self):
     ps = page_set.PageSet()
-    self.p1 = page.Page(
-        'file://conformance/textures/tex-sub-image-2d.html',
-        ps,
-        { 'name': 'WebglConformance.conformance_textures_tex_sub_image_2d' })
-    self.p2 = page.Page(
-        'file://othersuite/textures/tex-sub-image-3d.html',
-        ps,
-        { 'name': 'OtherSuite.textures_tex_sub_image_3d' })
-    self.p3 = page.Page(
-        'file://othersuite/textures/tex-sub-image-3d.html',
-        ps,
-        { 'name': None })
+    self.p1 = page.Page('file://conformance/textures/tex-sub-image-2d.html', ps)
+    self.p1.name = 'WebglConformance.conformance_textures_tex_sub_image_2d'
+    self.p2 = page.Page('file://othersuite/textures/tex-sub-image-3d.html', ps)
+    self.p2.name = 'OtherSuite.textures_tex_sub_image_3d'
+    self.p3 = page.Page('file://othersuite/textures/tex-sub-image-3d.html', ps)
+    self.p3.name = None
 
   def testURLPattern(self):
     options = MockUrlFilterOptions('conformance/textures', '')
diff --git a/tools/telemetry/telemetry/page/page_measurement_results.py b/tools/telemetry/telemetry/page/page_measurement_results.py
index e97210a..028e299 100644
--- a/tools/telemetry/telemetry/page/page_measurement_results.py
+++ b/tools/telemetry/telemetry/page/page_measurement_results.py
@@ -52,14 +52,19 @@
     self._page_specific_values_for_current_page = []
 
   def Add(self, trace_name, units, value, chart_name=None, data_type='default'):
+    # TODO(isherman): Remove this as well.
     value = value_backcompat.ConvertOldCallingConventionToValue(
       self._current_page,
       trace_name, units, value, chart_name, data_type)
+    self.AddValue(value)
+
+  def AddValue(self, value):
     self._ValidateValue(value)
     self._page_specific_values_for_current_page.append(value)
     self._all_page_specific_values.append(value)
 
   def AddSummaryValue(self, value):
+    assert value.page is None
     self._ValidateValue(value)
     self._all_summary_values.append(value)
 
diff --git a/tools/telemetry/telemetry/page/page_measurement_results_unittest.py b/tools/telemetry/telemetry/page/page_measurement_results_unittest.py
index 43b958f..3817880 100644
--- a/tools/telemetry/telemetry/page/page_measurement_results_unittest.py
+++ b/tools/telemetry/telemetry/page/page_measurement_results_unittest.py
@@ -87,6 +87,14 @@
     self.assertEquals('b_units', results.GetUnitsForValueName('b'))
     self.assertEquals('c_units', results.GetUnitsForValueName('c'))
 
+  def test_add_summary_value_with_page_specified(self):
+    results = NonPrintingPageMeasurementResults()
+    results.WillMeasurePage(self.pages[0])
+    self.assertRaises(
+      AssertionError,
+      lambda: results.AddSummaryValue(scalar.ScalarValue(self.pages[0],
+                                                         'a', 'units', 3)))
+
   def test_unit_change(self):
     results = NonPrintingPageMeasurementResults()
     results.WillMeasurePage(self.pages[0])
diff --git a/tools/telemetry/telemetry/page/page_measurement_unittest_base.py b/tools/telemetry/telemetry/page/page_measurement_unittest_base.py
index 35c3db8..5a6021e 100644
--- a/tools/telemetry/telemetry/page/page_measurement_unittest_base.py
+++ b/tools/telemetry/telemetry/page/page_measurement_unittest_base.py
@@ -38,6 +38,7 @@
     temp_parser = options.CreateParser()
     page_runner.AddCommandLineArgs(temp_parser)
     measurement.AddCommandLineArgs(temp_parser)
+    measurement.SetArgumentDefaults(temp_parser)
     defaults = temp_parser.get_default_values()
     for k, v in defaults.__dict__.items():
       if hasattr(options, k):
@@ -51,3 +52,34 @@
     page_runner.ProcessCommandLineArgs(temp_parser, options)
     measurement.ProcessCommandLineArgs(temp_parser, options)
     return page_runner.Run(measurement, ps, expectations, options)
+
+  def TestTracingCleanedUp(self, measurement_class, options=None):
+    ps = self.CreatePageSetFromFileInUnittestDataDir('blank.html')
+    start_tracing_called = [False]
+    stop_tracing_called = [False]
+
+    class BuggyMeasurement(measurement_class):
+      def __init__(self, *args, **kwargs):
+        measurement_class.__init__(self, *args, **kwargs)
+
+      # Inject fake tracing methods to browser
+      def TabForPage(self, page, browser):
+        ActualStartTracing = browser.StartTracing
+        def FakeStartTracing(*args, **kwargs):
+          ActualStartTracing(*args, **kwargs)
+          start_tracing_called[0] = True
+          raise Exception('Intentional exception')
+        browser.StartTracing = FakeStartTracing
+
+        ActualStopTracing = browser.StopTracing
+        def FakeStopTracing(*args, **kwargs):
+          ActualStopTracing(*args, **kwargs)
+          stop_tracing_called[0] = True
+        browser.StopTracing = FakeStopTracing
+
+        return measurement_class.TabForPage(self, page, browser)
+
+    measurement = BuggyMeasurement()
+    self.RunMeasurement(measurement, ps, options=options)
+    if start_tracing_called[0]:
+      self.assertTrue(stop_tracing_called[0])
diff --git a/tools/telemetry/telemetry/page/page_runner.py b/tools/telemetry/telemetry/page/page_runner.py
index b264c2c..7344172 100644
--- a/tools/telemetry/telemetry/page/page_runner.py
+++ b/tools/telemetry/telemetry/page/page_runner.py
@@ -14,7 +14,6 @@
 import traceback
 
 from telemetry import decorators
-from telemetry import exception_formatter
 from telemetry.core import browser_finder
 from telemetry.core import exceptions
 from telemetry.core import util
@@ -26,6 +25,7 @@
 from telemetry.page import results_options
 from telemetry.page.actions import navigate
 from telemetry.page.actions import page_action
+from telemetry.util import exception_formatter
 
 
 class _RunState(object):
@@ -326,8 +326,6 @@
   if page_set.user_agent_type:
     browser_options.browser_user_agent_type = page_set.user_agent_type
 
-  test.CustomizeBrowserOptionsForPageSet(page_set,
-                                         possible_browser.finder_options)
   if finder_options.profiler:
     profiler_class = profiler_finder.FindProfiler(finder_options.profiler)
     profiler_class.CustomizeBrowserOptions(possible_browser.browser_type,
diff --git a/tools/telemetry/telemetry/page/page_runner_unittest.py b/tools/telemetry/telemetry/page/page_runner_unittest.py
index 38ba0d0..1b0d560 100644
--- a/tools/telemetry/telemetry/page/page_runner_unittest.py
+++ b/tools/telemetry/telemetry/page/page_runner_unittest.py
@@ -399,10 +399,10 @@
         super(Measurement, self).__init__()
         self.browser_restarted = False
 
-      def CustomizeBrowserOptionsForPageSet(self, ps, options):
+      def CustomizeBrowserOptionsForSinglePage(self, ps, options):
         self.browser_restarted = True
-        super(Measurement, self).CustomizeBrowserOptionsForPageSet(ps,
-                                                                   options)
+        super(Measurement, self).CustomizeBrowserOptionsForSinglePage(ps,
+                                                                      options)
       def MeasurePage(self, page, tab, results):
         pass
 
@@ -412,6 +412,7 @@
     if not browser_finder.FindBrowser(options):
       return
     test = Measurement()
+    SetUpPageRunnerArguments(options)
     page_runner.Run(test, ps, expectations, options)
     self.assertEquals('about:blank', options.browser_options.startup_url)
     self.assertTrue(test.browser_restarted)
diff --git a/tools/telemetry/telemetry/page/page_set.py b/tools/telemetry/telemetry/page/page_set.py
index 853f60b..218ad1f 100644
--- a/tools/telemetry/telemetry/page/page_set.py
+++ b/tools/telemetry/telemetry/page/page_set.py
@@ -3,13 +3,16 @@
 # found in the LICENSE file.
 
 import csv
+import inspect
 import json
 import logging
 import os
 
+from telemetry.core import util
 from telemetry.page import cloud_storage
 from telemetry.page import page as page_module
 from telemetry.page import page_set_archive_info
+from telemetry.page.actions.navigate import NavigateAction
 
 # TODO(nednguyen): Remove this when crbug.com/239179 is marked fixed
 LEGACY_NAME_CONVERSION_DICT = {
@@ -24,22 +27,34 @@
 }
 
 
+class PageSetError(Exception):
+  pass
+
+
 class PageSet(object):
-  def __init__(self, file_path='', attributes=None):
+  def __init__(self, file_path='', description='', archive_data_file='',
+               credentials_path=None, user_agent_type=None,
+               make_javascript_deterministic=True, startup_url='', pages=None,
+               serving_dirs=None):
     self.file_path = file_path
-
     # These attributes can be set dynamically by the page set.
-    self.description = ''
-    self.archive_data_file = ''
-    self.credentials_path = None
-    self.user_agent_type = None
-    self.make_javascript_deterministic = True
-    self.startup_url = ''
+    self.description = description
+    self.archive_data_file = archive_data_file
+    self.credentials_path = credentials_path
+    self.user_agent_type = user_agent_type
+    self.make_javascript_deterministic = make_javascript_deterministic
+    self.wpr_archive_info = None
+    self.startup_url = startup_url
+    if pages:
+      self.pages = pages
+    else:
+      self.pages = []
+    if serving_dirs:
+      self.serving_dirs = serving_dirs
+    else:
+      self.serving_dirs = set()
 
-    # Temporay fixes for default navigate steps.
-    # TODO(nednguyen): change this to a method of page set.
-    self.RunNavigateSteps = {'action': 'navigate'}
-
+  def _InitializeFromDict(self, attributes):
     if attributes:
       for k, v in attributes.iteritems():
         if k in LEGACY_NAME_CONVERSION_DICT:
@@ -47,27 +62,22 @@
         else:
           setattr(self, k, v)
 
-    # Create a PageSetArchiveInfo object.
-    if self.archive_data_file:
-      self.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
-          os.path.join(self._base_dir, self.archive_data_file))
-    else:
-      self.wpr_archive_info = None
-
     # Create a Page object for every page.
     self.pages = []
     if attributes and 'pages' in attributes:
       for page_attributes in attributes['pages']:
         url = page_attributes.pop('url')
-
         page = page_module.Page(
-            url, self, attributes=page_attributes, base_dir=self._base_dir)
+            url, self, base_dir=self._base_dir)
+        for k, v in page_attributes.iteritems():
+          setattr(page, k, v)
+        page._SchemeErrorCheck()  # pylint: disable=W0212
         for legacy_name in LEGACY_NAME_CONVERSION_DICT:
           if hasattr(page, legacy_name):
             setattr(page, LEGACY_NAME_CONVERSION_DICT[legacy_name],
                     getattr(page, legacy_name))
             delattr(page, legacy_name)
-        self.pages.append(page)
+        self.AddPage(page)
 
     # Prepend _base_dir to our serving dirs.
     # Always use realpath to ensure no duplicates in set.
@@ -78,6 +88,13 @@
       for serving_dir in attributes['serving_dirs']:
         self.serving_dirs.add(
             os.path.realpath(os.path.join(self._base_dir, serving_dir)))
+    self._Initialize()
+
+  def _Initialize(self):
+    # Create a PageSetArchiveInfo object.
+    if self.archive_data_file:
+      self.wpr_archive_info = page_set_archive_info.PageSetArchiveInfo.FromFile(
+          os.path.join(self._base_dir, self.archive_data_file))
 
     # Attempt to download the credentials file.
     if self.credentials_path:
@@ -108,16 +125,66 @@
             continue
           cloud_storage.GetIfChanged(path)
 
-  @classmethod
-  def FromFile(cls, file_path):
+  def AddPage(self, page):
+    self.pages.append(page)
+
+  # In json page_set, a page inherits attributes from its page_set. With
+  # python page_set, this property will no longer be needed since pages can
+  # share property through a common ancestor class.
+  # TODO(nednguyen): move this to page when crbug.com/239179 is marked fixed
+  def RunNavigateSteps(self, action_runner):
+    action_runner.RunAction(NavigateAction())
+
+  @staticmethod
+  def FromFile(file_path):
+    _, ext_name = os.path.splitext(file_path)
+    if ext_name == '.json':
+      return PageSet.FromJSONFile(file_path)
+    elif ext_name == '.py':
+      return PageSet.FromPythonFile(file_path)
+    else:
+      raise PageSetError("Pageset %s has unsupported file type" % file_path)
+
+  @staticmethod
+  def FromPythonFile(file_path):
+    page_set_classes = []
+    module = util.GetPythonPageSetModule(file_path)
+    for m in dir(module):
+      if m.endswith('PageSet') and m != 'PageSet':
+        page_set_classes.append(getattr(module, m))
+    if len(page_set_classes) != 1:
+      raise PageSetError("Pageset file needs to contain exactly 1 pageset class"
+                         " with prefix 'PageSet'")
+    page_set = page_set_classes[0]()
+    page_set.file_path = file_path
+    page_set._Initialize() # pylint: disable=W0212
+    for page in page_set.pages:
+      page.page_set = page_set
+      page_class = page.__class__
+
+      for method_name, method in inspect.getmembers(page_class,
+                                                    predicate=inspect.ismethod):
+        if method_name.startswith("Run"):
+          args, _, _, _ = inspect.getargspec(method)
+          if not (args[0] == "self" and args[1] == "action_runner"):
+            raise PageSetError("""Definition of Run<...> method of all
+pages in %s must be in the form of def Run<...>(self, action_runner):"""
+                                     % file_path)
+    return page_set
+
+
+  @staticmethod
+  def FromJSONFile(file_path):
     with open(file_path, 'r') as f:
       contents = f.read()
     data = json.loads(contents)
-    return cls.FromDict(data, file_path)
+    return PageSet.FromDict(data, file_path)
 
-  @classmethod
-  def FromDict(cls, data, file_path):
-    return cls(file_path, data)
+  @staticmethod
+  def FromDict(attributes, file_path=''):
+    page_set = PageSet(file_path)
+    page_set._InitializeFromDict(attributes) # pylint: disable=W0212
+    return page_set
 
   @property
   def _base_dir(self):
@@ -150,7 +217,7 @@
 
       for csv_row in csv_reader:
         if csv_row[url_index] in page_set_dict:
-          pages.append(page_set_dict[csv_row[url_index]])
+          self.AddPage(page_set_dict[csv_row[url_index]])
         else:
           raise Exception('Unusable results_file.')
 
diff --git a/tools/telemetry/telemetry/page/page_set_unittest.py b/tools/telemetry/telemetry/page/page_set_unittest.py
index 38dbb06..0c50571 100644
--- a/tools/telemetry/telemetry/page/page_set_unittest.py
+++ b/tools/telemetry/telemetry/page/page_set_unittest.py
@@ -6,6 +6,7 @@
 import tempfile
 import unittest
 
+from telemetry.core import util
 from telemetry.page import page_set
 
 
@@ -33,10 +34,10 @@
 class TestPageSet(unittest.TestCase):
   def testSimpleSet(self):
     try:
-      with tempfile.NamedTemporaryFile(delete=False) as f:
+      with tempfile.NamedTemporaryFile(delete=False, suffix=".json") as f:
         f.write(simple_archive_info)
 
-      with tempfile.NamedTemporaryFile(delete=False) as f2:
+      with tempfile.NamedTemporaryFile(delete=False, suffix=".json") as f2:
         f2.write(simple_set % f.name.replace('\\', '\\\\'))
 
       ps = page_set.PageSet.FromFile(f2.name)
@@ -86,10 +87,53 @@
         },
       ]}, 'file://foo.js')
 
-    self.assertEquals(ps.pages[0].RunNavigateSteps, {'action': 'navigate'})
+    self.assertTrue(hasattr(ps.pages[0], 'RunNavigateSteps'))
     self.assertEquals(ps.pages[0].RunSmoothness, {'action': 'scroll'})
     self.assertEquals(ps.pages[0].RunStressMemory, {'action': 'javasciprt'})
 
     self.assertEquals(ps.pages[1].RunSmoothness, {'action': 'scroll'})
     self.assertEquals(ps.pages[1].RunNavigateSteps, {'action': 'navigate2'})
     self.assertEquals(ps.pages[1].RunRepaint, {'action': 'scroll'})
+
+  def testRunNavigateStepsInheritance(self):
+    ps = page_set.PageSet.FromDict({
+      'serving_dirs': ['a/b'],
+      'navigate_steps' : { 'action' : 'navigate1' },
+      'pages': [
+        {'url': 'http://www.foo.com',
+        },
+        {'url': 'http://www.bar.com',
+         'navigate_steps': {'action': 'navigate2'},
+        },
+      ]}, 'file://foo.js')
+
+    self.assertEquals(ps.pages[0].RunNavigateSteps, {'action': 'navigate1'})
+    self.assertEquals(ps.pages[1].RunNavigateSteps, {'action': 'navigate2'})
+
+
+  def testSuccesfulPythonPageSetLoading(self):
+    test_pps_dir = os.path.join(util.GetUnittestDataDir(), 'test_page_set.py')
+    pps = page_set.PageSet.FromFile(test_pps_dir)
+    self.assertEqual('TestPageSet', pps.__class__.__name__)
+    self.assertEqual('A pageset for testing purpose', pps.description)
+    self.assertEqual('data/test.json', pps.archive_data_file)
+    self.assertEqual('data/credential', pps.credentials_path)
+    self.assertEqual('desktop', pps.user_agent_type)
+    self.assertEqual(test_pps_dir, pps.file_path)
+    self.assertEqual(1, len(pps.pages))
+    google_page = pps.pages[0]
+    self.assertEqual('https://www.google.com', google_page.url)
+    self.assertIs(pps, google_page.page_set)
+    self.assertTrue(hasattr(google_page, 'RunNavigateSteps'))
+    self.assertTrue(5, google_page.RunGetActionRunner(action_runner=5))
+
+  def testMultiplePythonPageSetsLoading(self):
+    test_pps_1_dir = os.path.join(util.GetUnittestDataDir(),
+                                'test_simple_one_page_set.py')
+    test_pps_2_dir = os.path.join(util.GetUnittestDataDir(),
+                                'test_simple_two_page_set.py')
+    pps1 = page_set.PageSet.FromFile(test_pps_1_dir)
+    pps2 = page_set.PageSet.FromFile(test_pps_2_dir)
+
+    self.assertEqual('TestSimpleOnePageSet', pps1.__class__.__name__)
+    self.assertEqual('TestSimpleTwoPageSet', pps2.__class__.__name__)
diff --git a/tools/telemetry/telemetry/page/page_test.py b/tools/telemetry/telemetry/page/page_test.py
index 0498aa2..be08df5 100644
--- a/tools/telemetry/telemetry/page/page_test.py
+++ b/tools/telemetry/telemetry/page/page_test.py
@@ -5,11 +5,11 @@
 import logging
 
 from telemetry.core import command_line
+
 from telemetry.page import test_expectations
+from telemetry.page.actions import action_runner as action_runner_module
 from telemetry.page.actions import all_page_actions
 from telemetry.page.actions import interact
-from telemetry.page.actions import navigate
-from telemetry.page.actions import page_action
 
 
 def _GetActionFromData(action_data):
@@ -49,6 +49,13 @@
   return action_list
 
 
+def GetRunMethodForPage(page, action_name):
+  def RunMethod(action_runner):
+    for action in GetCompoundActionFromPage(page, action_name):
+      action_runner.RunAction(action)
+  return RunMethod
+
+
 class Failure(Exception):
   """Exception that can be thrown from PageMeasurement to indicate an
   undesired but designed-for problem."""
@@ -58,6 +65,8 @@
 class PageTest(command_line.Command):
   """A class styled on unittest.TestCase for creating page-specific tests."""
 
+  options = {}
+
   def __init__(self,
                test_method_name,
                action_name_to_run='',
@@ -100,6 +109,10 @@
     # _exit_requested is set to true when the test requests an early exit.
     self._exit_requested = False
 
+  @classmethod
+  def SetArgumentDefaults(cls, parser):
+    parser.set_defaults(**cls.options)
+
   @property
   def discard_first_result(self):
     """When set to True, the first run of the test is discarded.  This is
@@ -184,21 +197,6 @@
     """Override to add test-specific options to the BrowserOptions object"""
     pass
 
-  def CustomizeBrowserOptionsForPageSet(self, page_set, options):
-    """Set options required for this page set.
-
-    These options will be used every time the browser is started while running
-    this page set. They may, however, be further modified by
-    CustomizeBrowserOptionsForSinglePage or by the profiler.
-    """
-    for page in page_set:
-      if not self.CanRunForPage(page):
-        return
-      interactive = options and options.interactive
-      for action in GetCompoundActionFromPage(
-          page, self._action_name_to_run, interactive):
-        action.CustomizeBrowserOptionsForPageSet(options)
-
   def CustomizeBrowserOptionsForSinglePage(self, page, options):
     """Set options specific to the test and the given page.
 
@@ -297,42 +295,30 @@
 
   def RunPage(self, page, tab, results):
     interactive = self.options and self.options.interactive
-    compound_action = GetCompoundActionFromPage(
-        page, self._action_name_to_run, interactive)
+    action_runner = action_runner_module.ActionRunner(page, tab, self)
     self.WillRunActions(page, tab)
-    self._RunCompoundAction(page, tab, compound_action)
+    if interactive:
+      action_runner.RunAction(interact.InteractAction())
+    else:
+      self._RunMethod(page, self._action_name_to_run, action_runner)
     self.DidRunActions(page, tab)
     self._test_method(page, tab, results)
 
-  def _RunCompoundAction(self, page, tab, actions, run_setup_methods=True):
-    for action in actions:
-      if not action.WillWaitAfterRun():
-        action.WillRunAction(page, tab)
-      if run_setup_methods:
-        self.WillRunAction(page, tab, action)
-      try:
-        action.RunActionAndMaybeWait(page, tab)
-      finally:
-        if run_setup_methods:
-          self.DidRunAction(page, tab, action)
-
-      # Note that we must not call util.CloseConnections here. Many tests
-      # navigate to a URL in the first action and then wait for a condition
-      # in the second action. Calling util.CloseConnections here often
-      # aborts resource loads performed by the page.
+  def _RunMethod(self, page, method_name, action_runner):
+    if hasattr(page, method_name):
+      run_method = getattr(page, method_name)
+      # method is runnable, this must be the RunMethod of legacy json page_set
+      if not callable(run_method):
+        run_method = GetRunMethodForPage(page, method_name)
+      run_method(action_runner)
 
   def RunNavigateSteps(self, page, tab):
     """Navigates the tab to the page URL attribute.
 
     Runs the 'navigate_steps' page attribute as a compound action.
     """
-    navigate_actions = GetCompoundActionFromPage(page, 'RunNavigateSteps')
-    if not any(isinstance(action, navigate.NavigateAction)
-        for action in navigate_actions):
-      raise page_action.PageActionFailed(
-          'No NavigateAction in navigate_steps')
-
-    self._RunCompoundAction(page, tab, navigate_actions, False)
+    action_runner = action_runner_module.ActionRunner(page, tab, None)
+    self._RunMethod(page, "RunNavigateSteps", action_runner)
 
   def IsExiting(self):
     return self._exit_requested
diff --git a/tools/telemetry/telemetry/page/page_test_runner.py b/tools/telemetry/telemetry/page/page_test_runner.py
index 18bc69c..369c19e 100644
--- a/tools/telemetry/telemetry/page/page_test_runner.py
+++ b/tools/telemetry/telemetry/page/page_test_runner.py
@@ -95,8 +95,8 @@
           'pages': [{'url': page_set_arg}]
           }, os.path.dirname(__file__))
 
-    # We've been given a page set JSON. Load it.
-    if page_set_arg.endswith('.json'):
+    # We've been given a page set JSON or PYTHON. Load it.
+    if page_set_arg.endswith('.json') or page_set_arg.endswith('.py'):
       return page_set.PageSet.FromFile(page_set_arg)
 
     # We've been given a file or directory. Create a page set containing it.
diff --git a/tools/telemetry/telemetry/page/record_wpr.py b/tools/telemetry/telemetry/page/record_wpr.py
index c3f841e..5696796 100755
--- a/tools/telemetry/telemetry/page/record_wpr.py
+++ b/tools/telemetry/telemetry/page/record_wpr.py
@@ -22,6 +22,8 @@
 from telemetry.page import page_test
 from telemetry.page import profile_creator
 from telemetry.page import test_expectations
+from telemetry.page.actions import action_runner as action_runner_module
+from telemetry.page.actions import interact
 
 
 class RecordPage(page_test.PageTest):
@@ -38,12 +40,6 @@
   def CanRunForPage(self, page):
     return page.url.startswith('http')
 
-  def CustomizeBrowserOptionsForPageSet(self, pset, options):
-    for page in pset:
-      for compound_action in self._CompoundActionsForPage(page, options):
-        for action in compound_action:
-          action.CustomizeBrowserOptionsForPageSet(options)
-
   def WillNavigateToPage(self, page, tab):
     """Override to ensure all resources are fetched from network."""
     tab.ClearCache(force=False)
@@ -74,21 +70,18 @@
     # Run the actions for all measurements. Reload the page between
     # actions.
     should_reload = False
-    for compound_action in self._CompoundActionsForPage(page, self.options):
-      if should_reload:
-        self.RunNavigateSteps(page, tab)
-      self._RunCompoundAction(page, tab, compound_action)
-      should_reload = True
-
-  def _CompoundActionsForPage(self, page, options):
-    actions = []
+    interactive = self.options and self.options.interactive
     for action_name in self._action_names:
       if not hasattr(page, action_name):
         continue
-      interactive = options and options.interactive
-      actions.append(page_test.GetCompoundActionFromPage(
-          page, action_name, interactive))
-    return actions
+      if should_reload:
+        self.RunNavigateSteps(page, tab)
+      action_runner = action_runner_module.ActionRunner(page, tab, self)
+      if interactive:
+        action_runner.RunAction(interact.InteractAction())
+      else:
+        self._RunMethod(page, self._action_name_to_run, action_runner)
+      should_reload = True
 
 
 def _CreatePageSetForUrl(url):
@@ -130,10 +123,11 @@
   if target in tests:
     recorder.test = tests[target]().test()
     recorder.test.AddCommandLineArgs(parser)
+    recorder.test.SetArgumentDefaults(parser)
     parser.parse_args()
     recorder.test.ProcessCommandLineArgs(parser, options)
     ps = tests[target]().CreatePageSet(options)
-  elif target.endswith('.json'):
+  elif target.endswith('.json') or target.endswith('.py'):
     parser.parse_args()
     ps = page_set.PageSet.FromFile(target)
   elif target.startswith('http'):
diff --git a/tools/telemetry/telemetry/test.py b/tools/telemetry/telemetry/test.py
index a545105..3559d9c 100644
--- a/tools/telemetry/telemetry/test.py
+++ b/tools/telemetry/telemetry/test.py
@@ -50,12 +50,12 @@
       parser.add_option_group(group)
 
   @classmethod
-  def ProcessCommandLineArgs(cls, parser, args):
-    # TODO: This overrides the arguments the user specifies at the command-line.
-    # That's not right. http://crbug.com/330058
-    for key, value in cls.options.iteritems():
-      setattr(args, key, value)
+  def SetArgumentDefaults(cls, parser):
+    cls.PageTestClass().SetArgumentDefaults(parser)
+    parser.set_defaults(**cls.options)
 
+  @classmethod
+  def ProcessCommandLineArgs(cls, parser, args):
     cls.PageTestClass().ProcessCommandLineArgs(parser, args)
 
   def CustomizeBrowserOptions(self, options):
@@ -122,7 +122,7 @@
                       'instructions below.',
                       generated_profile_archive_path)
         logging.error(e)
-        sys.exit(1)
+        sys.exit(-1)
 
     # Unzip profile directory.
     extracted_profile_dir_path = (
@@ -138,7 +138,7 @@
         if os.path.exists(extracted_profile_dir_path):
           shutil.rmtree(extracted_profile_dir_path)
         logging.error("Error extracting profile directory zip file: %s", e)
-        sys.exit(1)
+        sys.exit(-1)
 
     # Run with freshly extracted profile directory.
     logging.info("Using profile archive directory: %s",
diff --git a/tools/telemetry/telemetry/test_runner.py b/tools/telemetry/telemetry/test_runner.py
index 103a5d7..71f3ef2 100644
--- a/tools/telemetry/telemetry/test_runner.py
+++ b/tools/telemetry/telemetry/test_runner.py
@@ -89,21 +89,26 @@
 
   @classmethod
   def AddCommandLineArgs(cls, parser):
+    test.AddCommandLineArgs(parser)
+
     # Allow tests to add their own command line options.
     matching_tests = []
     for arg in sys.argv[1:]:
       matching_tests += _MatchTestName(arg)
-    # TODO(dtu): After move to argparse, add command-line args for all tests
-    # to subparser. Using subparsers will avoid duplicate arguments.
+
     if matching_tests:
-      matching_tests.pop().AddCommandLineArgs(parser)
-    test.AddCommandLineArgs(parser)
+      # TODO(dtu): After move to argparse, add command-line args for all tests
+      # to subparser. Using subparsers will avoid duplicate arguments.
+      matching_test = matching_tests.pop()
+      matching_test.AddCommandLineArgs(parser)
+      # The test's options override the defaults!
+      matching_test.SetArgumentDefaults(parser)
 
   @classmethod
   def ProcessCommandLineArgs(cls, parser, args):
     if not args.positional_args:
       _PrintTestList(_Tests())
-      sys.exit(1)
+      sys.exit(-1)
 
     input_test_name = args.positional_args[0]
     matching_tests = _MatchTestName(input_test_name)
@@ -111,22 +116,22 @@
       print >> sys.stderr, 'No test named "%s".' % input_test_name
       print >> sys.stderr
       _PrintTestList(_Tests())
-      sys.exit(1)
+      sys.exit(-1)
 
     if len(matching_tests) > 1:
       print >> sys.stderr, 'Multiple tests named "%s".' % input_test_name
       print >> sys.stderr, 'Did you mean one of these?'
       print >> sys.stderr
       _PrintTestList(matching_tests)
-      sys.exit(1)
+      sys.exit(-1)
 
     test_class = matching_tests.pop()
     if issubclass(test_class, page_test.PageTest):
-      if len(args.tests) < 2:
+      if len(args.positional_args) < 2:
         parser.error('Need to specify a page set for "%s".' % test_class.Name())
-      if len(args.tests) > 2:
+      if len(args.positional_args) > 2:
         parser.error('Too many arguments.')
-      page_set_path = args.tests[1]
+      page_set_path = args.positional_args[1]
       if not os.path.exists(page_set_path):
         parser.error('Page set not found.')
       if not (os.path.isfile(page_set_path) and
@@ -138,7 +143,7 @@
         page_set = page_set_path
       test_class = TestWrapper
     else:
-      if len(args.tests) > 1:
+      if len(args.positional_args) > 1:
         parser.error('Too many arguments.')
 
     assert issubclass(test_class, test.Test), 'Trying to run a non-Test?!'
diff --git a/tools/telemetry/telemetry/util/exception_formatter.py b/tools/telemetry/telemetry/util/exception_formatter.py
new file mode 100644
index 0000000..e226067
--- /dev/null
+++ b/tools/telemetry/telemetry/util/exception_formatter.py
@@ -0,0 +1,78 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Print prettier and more detailed exceptions."""
+
+import math
+import os
+import sys
+import traceback
+
+from telemetry.core import util
+
+
+def PrintFormattedException(exception_class, exception, tb):
+  """Prints an Exception in a more useful format than the default.
+
+  TODO(tonyg): Consider further enhancements. For instance:
+    - Report stacks to maintainers like depot_tools does.
+    - Add a debug flag to automatically start pdb upon exception.
+  """
+  def _GetFinalFrame(frame):
+    final_frame = None
+    while frame is not None:
+      final_frame = frame
+      frame = frame.tb_next
+    return final_frame
+
+  def _AbbreviateMiddle(target, middle, length):
+    assert length >= 0, 'Must provide positive length'
+    assert len(middle) <= length, 'middle must not be greater than length'
+    if len(target) <= length:
+      return target
+    half_length = (length - len(middle)) / 2.
+    return '%s%s%s' % (target[:int(math.floor(half_length))],
+                       middle,
+                       target[-int(math.ceil(half_length)):])
+
+  base_dir = os.path.abspath(util.GetChromiumSrcDir())
+  formatted_exception = traceback.format_exception(
+      exception_class, exception, tb)
+  extracted_tb = traceback.extract_tb(tb)
+  traceback_header = formatted_exception[0].strip()
+  exception = ''.join([l[2:] if l[:2] == '  ' else l for l in
+                       traceback.format_exception_only(exception_class,
+                                                       exception)])
+  local_variables = [(variable, value) for variable, value in
+                     _GetFinalFrame(tb).tb_frame.f_locals.iteritems()
+                     if variable != 'self']
+
+  # Format the traceback.
+  print >> sys.stderr
+  print >> sys.stderr, traceback_header
+  for filename, line, function, text in extracted_tb:
+    filename = os.path.abspath(filename)
+    if filename.startswith(base_dir):
+      filename = filename[len(base_dir)+1:]
+    print >> sys.stderr, '  %s at %s:%d' % (function, filename, line)
+    print >> sys.stderr, '    %s' % text
+
+  # Format the locals.
+  if local_variables:
+    print >> sys.stderr
+    print >> sys.stderr, 'Locals:'
+    longest_variable = max([len(v) for v, _ in local_variables])
+    for variable, value in sorted(local_variables):
+      value = repr(value)
+      possibly_truncated_value = _AbbreviateMiddle(value, ' ... ', 1024)
+      truncation_indication = ''
+      if len(possibly_truncated_value) != len(value):
+        truncation_indication = ' (truncated)'
+      print >> sys.stderr, '  %s: %s%s' % (variable.ljust(longest_variable + 1),
+                                           possibly_truncated_value,
+                                           truncation_indication)
+
+  # Format the exception.
+  print >> sys.stderr
+  print >> sys.stderr, exception
diff --git a/tools/telemetry/telemetry/util/global_hooks.py b/tools/telemetry/telemetry/util/global_hooks.py
new file mode 100644
index 0000000..50ed5b5
--- /dev/null
+++ b/tools/telemetry/telemetry/util/global_hooks.py
@@ -0,0 +1,75 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Hooks that apply globally to all scripts that import or use Telemetry."""
+
+import os
+import signal
+import sys
+import traceback
+
+from telemetry.core import util
+from telemetry.util import exception_formatter
+
+
+def InstallHooks():
+  RemoveAllStalePycFiles(util.GetTelemetryDir())
+  RemoveAllStalePycFiles(util.GetBaseDir())
+  InstallUnhandledExceptionFormatter()
+  InstallStackDumpOnSigusr1()
+  InstallTerminationHook()
+
+
+def RemoveAllStalePycFiles(base_dir):
+  """Scan directories for old .pyc files without a .py file and delete them."""
+  for dirname, _, filenames in os.walk(base_dir):
+    if '.svn' in dirname or '.git' in dirname:
+      continue
+    for filename in filenames:
+      root, ext = os.path.splitext(filename)
+      if ext != '.pyc':
+        continue
+
+      pyc_path = os.path.join(dirname, filename)
+      py_path = os.path.join(dirname, root + '.py')
+
+      try:
+        if not os.path.exists(py_path):
+          os.remove(pyc_path)
+      except OSError:
+        # Wrap OS calls in try/except in case another process touched this file.
+        pass
+
+    try:
+      os.removedirs(dirname)
+    except OSError:
+      # Wrap OS calls in try/except in case another process touched this dir.
+      pass
+
+
+def InstallUnhandledExceptionFormatter():
+  """Print prettier exceptions that also contain the stack frame's locals."""
+  sys.excepthook = exception_formatter.PrintFormattedException
+
+
+def InstallStackDumpOnSigusr1():
+  """Catch SIGUSR1 and print a stack trace."""
+  # Windows doesn't define SIGUSR1.
+  if not hasattr(signal, 'SIGUSR1'):
+    return
+
+  def PrintDiagnostics(_, stack_frame):
+    print >> sys.stderr, 'SIGUSR1 received, printing stack trace:'
+    traceback.print_stack(stack_frame)
+  signal.signal(signal.SIGUSR1, PrintDiagnostics)
+
+
+def InstallTerminationHook():
+  """Catch SIGTERM, print a stack trace, and exit."""
+  def PrintStackAndExit(sig, stack_frame):
+    print >> sys.stderr, 'Traceback (most recent call last):'
+    traceback.print_stack(stack_frame)
+    print >> sys.stderr, 'Received signal %s, exiting' % sig
+    sys.exit(-1)
+  signal.signal(signal.SIGTERM, PrintStackAndExit)
diff --git a/tools/telemetry/telemetry/value/__init__.py b/tools/telemetry/telemetry/value/__init__.py
index 991b249..80a2269 100644
--- a/tools/telemetry/telemetry/value/__init__.py
+++ b/tools/telemetry/telemetry/value/__init__.py
@@ -31,7 +31,7 @@
 # but there you have it. There are three contexts in which Values are converted
 # for use by buildbot, represented by these output-intent values.
 PER_PAGE_RESULT_OUTPUT_CONTEXT = 'per-page-result-output-context'
-MERGED_PAGES_RESULT_OUTPUT_CONTEXT = 'merged-pages-result-output-context'
+COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT = 'merged-pages-result-output-context'
 SUMMARY_RESULT_OUTPUT_CONTEXT = 'summary-result-output-context'
 
 class Value(object):
@@ -99,7 +99,7 @@
   def _IsImportantGivenOutputIntent(self, output_context):
     if output_context == PER_PAGE_RESULT_OUTPUT_CONTEXT:
       return False
-    elif output_context == MERGED_PAGES_RESULT_OUTPUT_CONTEXT:
+    elif output_context == COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT:
       return self.important
     elif output_context == SUMMARY_RESULT_OUTPUT_CONTEXT:
       return self.important
@@ -128,7 +128,8 @@
     else:
       return self.name
 
-  def GetBuildbotMeasurementAndTraceNameForMergedPagesResult(self, trace_tag):
+  def GetBuildbotMeasurementAndTraceNameForComputedSummaryResult(
+      self, trace_tag):
     measurement, bb_trace_name = (
         _ConvertValueNameToBuildbotChartAndTraceName(self.name))
     if trace_tag:
diff --git a/tools/telemetry/telemetry/value/scalar_unittest.py b/tools/telemetry/telemetry/value/scalar_unittest.py
index e375d01..3666c8b 100644
--- a/tools/telemetry/telemetry/value/scalar_unittest.py
+++ b/tools/telemetry/telemetry/value/scalar_unittest.py
@@ -29,7 +29,7 @@
     page0 = self.pages[0]
     v = scalar.ScalarValue(page0, 'x', 'unit', 3, important=True)
     self.assertEquals('default', v.GetBuildbotDataType(
-        value.MERGED_PAGES_RESULT_OUTPUT_CONTEXT))
+        value.COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT))
     self.assertEquals([3], v.GetBuildbotValue())
     self.assertEquals(('x_by_url', page0.display_name),
                       v.GetBuildbotMeasurementAndTraceNameForPerPageResult())
@@ -37,7 +37,7 @@
     v = scalar.ScalarValue(page0, 'x', 'unit', 3, important=False)
     self.assertEquals(
         'unimportant',
-        v.GetBuildbotDataType(value.MERGED_PAGES_RESULT_OUTPUT_CONTEXT))
+        v.GetBuildbotDataType(value.COMPUTED_PER_PAGE_SUMMARY_OUTPUT_CONTEXT))
 
   def testScalarSamePageMerging(self):
     page0 = self.pages[0]
diff --git a/tools/telemetry/telemetry/value/summary.py b/tools/telemetry/telemetry/value/summary.py
new file mode 100644
index 0000000..d4a3180
--- /dev/null
+++ b/tools/telemetry/telemetry/value/summary.py
@@ -0,0 +1,156 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from collections import defaultdict
+
+from telemetry.value import merge_values
+
+class Summary(object):
+  """Computes summary values from the per-page-run values produced by a test.
+
+  Some telemetry benchmark repeat a number of times in order to get a reliable
+  measurement. The test does not have to handle merging of these runs:
+  summarizer does it for you.
+
+  For instance, if two pages run, 3 and 1 time respectively:
+      ScalarValue(page1, 'foo', units='ms', 1)
+      ScalarValue(page1, 'foo', units='ms', 1)
+      ScalarValue(page1, 'foo', units='ms', 1)
+      ScalarValue(page2, 'foo', units='ms', 2)
+
+  Then summarizer will produce two sets of values. First,
+  computed_per_page_values:
+      [
+         ListOfScalarValues(page1, 'foo', units='ms', [1,1,1])],
+         ListOfScalarValues(page2, 'foo', units='ms', [2])]
+      ]
+
+  In addition, it will produce a summary value:
+      [
+         ListOfScalarValues(page=None, 'foo', units='ms', [1,1,1,2])]
+      ]
+
+  """
+  def __init__(self, all_page_specific_values, had_errors_or_failures):
+    self.had_errors_or_failures = had_errors_or_failures
+    self._computed_per_page_values = []
+    self._computed_summary_values = []
+    self._interleaved_computed_per_page_values_and_summaries = []
+    self._ComputePerPageValues(all_page_specific_values)
+
+  @property
+  def computed_per_page_values(self):
+    return self._computed_per_page_values
+
+  @property
+  def computed_summary_values(self):
+    return self._computed_summary_values
+
+  @property
+  def interleaved_computed_per_page_values_and_summaries(self):
+    """Returns the computed per page values and summary values interleaved.
+
+    All the results for a given name are printed together. First per page
+    values, then summary values.
+
+    """
+    return self._interleaved_computed_per_page_values_and_summaries
+
+  def _ComputePerPageValues(self, all_page_specific_values):
+    all_successful_page_values = all_page_specific_values
+
+    # We will later need to determine how many values were originally created
+    # for each value name, to apply a workaround meant to clean up the printf
+    # output.
+    num_successful_pages_for_value_name = defaultdict(int)
+    for v in all_successful_page_values:
+      num_successful_pages_for_value_name[v.name] += 1
+
+    # By here, due to page repeat options, all_values_from_successful_pages
+    # contains values of the same name not only from mulitple pages, but also
+    # from the same name. So even if, for instance, only one page ran, it may
+    # have run twice, producing two 'x' values.
+    #
+    # So, get rid of the repeated pages by merging.
+    merged_page_values = merge_values.MergeLikeValuesFromSamePage(
+        all_successful_page_values)
+
+    # Now we have a bunch of values, but there is only one value_name per page.
+    # Suppose page1 and page2 ran, producing values x and y. We want to print
+    #    x_by_url for page1
+    #    x_by_url for page2
+    #    x for page1, page2 combined
+    #
+    #    y_by_url for page1
+    #    y_by_url for page2
+    #    y for page1, page2 combined
+    #
+    # We already have the x_by_url values in the values array. But, we will need
+    # them indexable by the value name.
+    #
+    # The following dict maps value_name -> list of pages that have values of
+    # that name.
+    per_page_values_by_value_name = defaultdict(list)
+    for value in merged_page_values:
+      per_page_values_by_value_name[value.name].append(value)
+
+    # We already have the x_by_url values in the values array. But, we also need
+    # the values merged across the pages. And, we will need them indexed by
+    # value name so that we can find them when printing out value names in
+    # alphabetical order.
+    merged_pages_value_by_value_name = {}
+    if not self.had_errors_or_failures:
+      for value in merge_values.MergeLikeValuesFromDifferentPages(
+          all_successful_page_values):
+        assert value.name not in merged_pages_value_by_value_name
+        merged_pages_value_by_value_name[value.name] = value
+
+    # sorted_value names will govern the order we start printing values.
+    value_names = set([v.name for v in merged_page_values])
+    sorted_value_names = sorted(value_names)
+
+    # Time to walk through the values by name, printing first the by_url values
+    # and then the merged_site value.
+    for value_name in sorted_value_names:
+      per_page_values = per_page_values_by_value_name.get(value_name, [])
+
+      # Sort the values by their url
+      sorted_per_page_values = list(per_page_values)
+      sorted_per_page_values.sort(
+          key=lambda per_page_values: per_page_values.page.display_name)
+
+      # Output the _by_url results.
+      num_successful_pages_for_this_value_name = (
+          num_successful_pages_for_value_name[value_name])
+      for per_page_value in sorted_per_page_values:
+        self._ComputePerPageValue(per_page_value,
+                                  num_successful_pages_for_this_value_name)
+
+      # Output the combined values.
+      merged_pages_value = merged_pages_value_by_value_name.get(value_name,
+                                                                None)
+      if merged_pages_value:
+        self._computed_summary_values.append(merged_pages_value)
+        self._interleaved_computed_per_page_values_and_summaries.append(
+            merged_pages_value)
+
+  def _ComputePerPageValue(
+      self, value, num_successful_pages_for_this_value_name):
+    # If there were any page errors, we typically will print nothing.
+    #
+    # Note: this branch is structured less-densely to improve legibility.
+    if num_successful_pages_for_this_value_name > 1:
+      should_print = True
+    elif (self.had_errors_or_failures and
+         num_successful_pages_for_this_value_name == 1):
+      should_print = True
+    else:
+      should_print = False
+
+    if not should_print:
+      return
+
+    # Actually save the result.
+    self._computed_per_page_values.append(value)
+    self._interleaved_computed_per_page_values_and_summaries.append(value)
diff --git a/tools/telemetry/telemetry/value/summary_unittest.py b/tools/telemetry/telemetry/value/summary_unittest.py
new file mode 100644
index 0000000..26a1e32
--- /dev/null
+++ b/tools/telemetry/telemetry/value/summary_unittest.py
@@ -0,0 +1,8 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# TODO(nduca): Convert preexisting unittests to be summary tests. Summary is
+# currently very thoroughly unit tested by
+# buildbot_page_measurement_results_unittest. It originated as part of that
+# code, but was extracted because it proved useful.
diff --git a/tools/telemetry/telemetry/web_components/results_viewer.py b/tools/telemetry/telemetry/web_components/results_viewer.py
index 02194c7..6eddcac 100644
--- a/tools/telemetry/telemetry/web_components/results_viewer.py
+++ b/tools/telemetry/telemetry/web_components/results_viewer.py
@@ -5,26 +5,21 @@
 import json
 import sys
 
-from telemetry.web_components import viewer
+from telemetry.web_components import web_component
 
 
-class ResultsViewer(viewer.Viewer):
-  def __init__(self, data_to_view):
+class ResultsViewer(web_component.WebComponent):
+  def __init__(self, data_to_view=None):
     super(ResultsViewer, self).__init__(
       tvcm_module_name='telemetry.web_components.results_viewer',
       js_class_name='telemetry.web_components.ResultsViewer',
       data_binding_property='dataToView')
-
-    self._data_to_view = data_to_view
-
-  @property
-  def data_to_view(self):
-    return self._data_to_view
+    self.data_to_view = data_to_view
 
   def WriteDataToFileAsJson(self, f):
-    json.dump(self._data_to_view, f)
+    json.dump(self.data_to_view, f)
 
 
 if __name__ == '__main__':
   x = ResultsViewer({'hello': 'world', 'nice': ['to', 'see', 'you']})
-  x.WriteViewerToFile(sys.stdout)
+  x.WriteWebComponentToFile(sys.stdout)
diff --git a/tools/telemetry/telemetry/web_components/ui/bar_chart.css b/tools/telemetry/telemetry/web_components/ui/bar_chart.css
deleted file mode 100644
index a8fe22d..0000000
--- a/tools/telemetry/telemetry/web_components/ui/bar_chart.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Copyright 2014 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
diff --git a/tools/telemetry/telemetry/web_components/ui/bar_chart.js b/tools/telemetry/telemetry/web_components/ui/bar_chart.js
deleted file mode 100644
index b8b0b79..0000000
--- a/tools/telemetry/telemetry/web_components/ui/bar_chart.js
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.require('tvcm.range');
-tvcm.require('tracing.color_scheme');
-tvcm.require('telemetry.web_components.ui.d3');
-tvcm.require('telemetry.web_components.ui.chart_base');
-
-tvcm.requireStylesheet('telemetry.web_components.ui.bar_chart');
-
-tvcm.exportTo('telemetry.web_components.ui', function() {
-  var ChartBase = telemetry.web_components.ui.ChartBase;
-  var getColorOfKey = telemetry.web_components.ui.getColorOfKey;
-
-  /**
-   * @constructor
-   */
-  var BarChart = tvcm.ui.define('bar-chart', ChartBase);
-
-  BarChart.prototype = {
-    __proto__: ChartBase.prototype,
-
-    decorate: function() {
-      ChartBase.prototype.decorate.call(this);
-      this.classList.add('bar-chart');
-
-      this.xScale_ = undefined;
-      this.xSubScale_ = undefined;
-      this.yScale_ = undefined;
-
-      this.data_ = undefined;
-      this.xLabelValues_ = undefined;
-      this.xLabelKey_ = undefined;
-      this.seriesKeys_ = undefined;
-    },
-
-    get data() {
-      return this.data_;
-    },
-
-    get xLabelKey() {
-      return this.xLabelKey_;
-    },
-
-    setDataAndXLabelKey: function(data, xLabelKey) {
-      if (data !== undefined) {
-        // Figure out what the series keys are. E.g. for {label: 'a', value1: 3,
-        // value2: 4} compute ['value1', 'value2'].
-        var seriesKeys = [];
-        d3.keys(data[0]).forEach(function(k) {
-          if (k == xLabelKey)
-            return;
-          seriesKeys.push(k);
-        });
-
-        // Figure out the x labels in the data set. E.g. from
-        //   [{label: 'a', ...}, {label: 'b', ...}]
-        // we would commpute ['a', 'y'].
-        var xLabelValues = [];
-        var seenXLabelValues = {};
-        data.forEach(function(d) {
-          var xLabelValue = d[xLabelKey];
-          if (seenXLabelValues[xLabelValue])
-            throw new Error('Label ' + xLabelValue + ' has been used already');
-          xLabelValues.push(xLabelValue);
-          seenXLabelValues[xLabelValue] = true;
-        }, this);
-        this.xLabelKey_ = xLabelKey;
-        this.seriesKeys_ = seriesKeys;
-        this.xLabelValues_ = xLabelValues;
-      } else {
-        this.xLabelKey_ = undefined;
-        this.seriesKeys_ = undefined;
-        this.xLabelValues_ = undefined;
-      }
-      this.data_ = data;
-      this.updateContents_();
-    },
-
-    getLegendKeys_: function() {
-      if (this.seriesKeys_ &&
-          this.seriesKeys_.length > 1)
-        return this.seriesKeys_.slice();
-      return [];
-    },
-
-    updateScales_: function(width, height) {
-      if (this.data_ === undefined) {
-        this.xScale_ = undefined;
-        this.xSubScale_ = undefined;
-        this.yScale_ = undefined;
-        return;
-      }
-
-      // xScale maps x labels to a position in the overall timeline.
-      this.xScale_ = d3.scale.ordinal();
-      this.xScale_.rangeRoundBands([0, width], .1);
-      this.xScale_.domain(this.xLabelValues_);
-
-      // xSubScale maps an individual series to a position within its group
-      // of related bars.
-      this.xSubScale_ = d3.scale.ordinal();
-      this.xSubScale_.domain(this.seriesKeys_)
-          .rangeRoundBands([0, this.xScale_.rangeBand()]);
-
-      // Regular mapping of values to the full chart height.
-      var yRange = new tvcm.Range();
-      this.data_.forEach(function(d) {
-        this.seriesKeys_.forEach(function(k) {
-          yRange.addValue(d[k]);
-        }, this);
-      }, this);
-      this.yScale_ = d3.scale.linear();
-      this.yScale_.range([height, 0]);
-
-      this.yScale_.domain([yRange.min, yRange.max]);
-    },
-
-    updateContents_: function() {
-      ChartBase.prototype.updateContents_.call(this);
-      if (!this.data_)
-        return;
-
-      var width = this.chartAreaSize.width;
-      var height = this.chartAreaSize.height;
-
-      var chartAreaSel = d3.select(this.chartAreaElement);
-
-      // An index-group has the rects from the same array index in the source
-      // data set.
-      var indexGroupSel = chartAreaSel.selectAll('.index-group')
-          .data(this.data_);
-      indexGroupSel.enter().append('g')
-          .attr('class', '.index-group')
-          .attr('transform', function(d) {
-            var k = d[this.xLabelKey_];
-            return 'translate(' + this.xScale_(k) + ',0)';
-          }.bind(this));
-      indexGroupSel.exit().remove();
-
-      // Within an index group, create a rect for each actual value.
-      var rectsSel = indexGroupSel.selectAll('rect')
-        .data(function(d) {
-            // 'd' is an index in the original array. We want to extract out the
-            // actual values from it from this.seriesKeys_. This we turn into
-            // {name: seriesKey, value: d[seriesKey]} objects that then get
-            // data-bound to each rect.
-            var values = [];
-            for (var i = 0; i < this.seriesKeys_.length; i++) {
-              var k = this.seriesKeys_[i];
-              values.push({name: k,
-                           value: d[k]});
-            }
-            return values;
-          }.bind(this));
-
-      rectsSel.enter().append('rect')
-        .attr('width', this.xSubScale_.rangeBand())
-        .attr('x', function(d) {
-            return this.xSubScale_(d.name);
-          }.bind(this))
-        .attr('y', function(d) {
-            return this.yScale_(d.value);
-          }.bind(this))
-        .attr('height', function(d) {
-            return height - this.yScale_(d.value);
-          }.bind(this))
-        .style('fill', function(d) {
-            return getColorOfKey(d.name);
-          });
-    }
-  };
-
-  return {
-    BarChart: BarChart
-  };
-});
diff --git a/tools/telemetry/telemetry/web_components/ui/bar_chart_unittest.js b/tools/telemetry/telemetry/web_components/ui/bar_chart_unittest.js
deleted file mode 100644
index d5f3012..0000000
--- a/tools/telemetry/telemetry/web_components/ui/bar_chart_unittest.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.require('telemetry.web_components.ui.bar_chart');
-
-tvcm.testSuite('telemetry.web_components.ui.bar_chart_unittest', function() {
-  test('singleSeries', function() {
-    var chart = new telemetry.web_components.ui.BarChart();
-    chart.width = 400;
-    chart.height = 200;
-    chart.chartTitle = 'Chart title';
-    var data = [
-      {label: 'a', value: 100},
-      {label: 'b', value: 40},
-      {label: 'c', value: 20}
-    ];
-    chart.setDataAndXLabelKey(data, 'label');
-    this.addHTMLOutput(chart);
-  });
-
-  test('twoSeries', function() {
-    var chart = new telemetry.web_components.ui.BarChart();
-    chart.width = 400;
-    chart.height = 200;
-    chart.chartTitle = 'Chart title';
-    var data = [
-      {label: 'a', value1: 100, value2: 50},
-      {label: 'b', value1: 75, value2: 10},
-      {label: 'c', value1: 50, value2: 125}
-    ];
-    chart.setDataAndXLabelKey(data, 'label');
-    this.addHTMLOutput(chart);
-  });
-});
diff --git a/tools/telemetry/telemetry/web_components/ui/chart_base.html b/tools/telemetry/telemetry/web_components/ui/chart_base.html
deleted file mode 100644
index c51ab14..0000000
--- a/tools/telemetry/telemetry/web_components/ui/chart_base.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-Copyright 2014 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<style>
-  .chart-base #title {
-    font-size: 18pt;
-  }
-
-  .chart-base .axis path,
-  .chart-base .axis line {
-    fill: none;
-    shape-rendering: crispEdges;
-    stroke: #000;
-  }
-</style>
-<template id="chart-base-template">
-  <svg> <!-- svg tag is dropped by ChartBase.decorate. -->
-    <g xmlns="http://www.w3.org/2000/svg" id="chart-area">
-      <g class="x axis"></g>
-      <g class="y axis"></g>
-      <text id="title"></text>
-    </g>
-  </svg>
-</template>
diff --git a/tools/telemetry/telemetry/web_components/ui/chart_base.js b/tools/telemetry/telemetry/web_components/ui/chart_base.js
deleted file mode 100644
index 6c061bc..0000000
--- a/tools/telemetry/telemetry/web_components/ui/chart_base.js
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.require('tvcm.utils');
-tvcm.require('telemetry.web_components.ui.d3');
-tvcm.requireTemplate('telemetry.web_components.ui.chart_base');
-
-tvcm.exportTo('telemetry.web_components.ui', function() {
-  var svgNS = 'http://www.w3.org/2000/svg';
-
-  function getColorOfKey(key) {
-    var id = tracing.getStringColorId(key);
-    return tracing.getColorPalette()[id];
-  }
-
-  /**
-   * A virtual base class for basic charts that provides X and Y axes, if
-   * needed, a title, and legend.
-   *
-   * @constructor
-   */
-  var ChartBase = tvcm.ui.define('svg', undefined, svgNS);
-
-  ChartBase.prototype = {
-    __proto__: HTMLUnknownElement.prototype,
-
-    decorate: function() {
-      this.classList.add('chart-base');
-      this.chartTitle_ = undefined;
-      this.data_ = undefined;
-      this.seriesKeys_ = undefined;
-      this.width_ = 400;
-      this.height_ = 300;
-
-      // This should use tvcm.instantiateTemplate. However, creating
-      // svg-namespaced elements inside a template isn't possible. Thus, this
-      // hack.
-      var template = document.head.querySelector('#chart-base-template');
-      var svgEl = template.content.querySelector('svg');
-      for (var i = 0; i < svgEl.children.length; i++)
-        this.appendChild(svgEl.children[i].cloneNode(true));
-    },
-
-    get chartTitle() {
-      return chartTitle_;
-    },
-
-    set chartTitle(chartTitle) {
-      this.chartTitle_ = chartTitle;
-      this.updateContents_();
-    },
-
-    get chartAreaElement() {
-      return this.querySelector('#chart-area');
-    },
-
-    get width() {
-      return width_;
-    },
-
-    set width(width) {
-      this.width_ = width;
-      this.updateContents_();
-    },
-
-    get height() {
-      return height_;
-    },
-
-    set height(height) {
-      this.height_ = height;
-      this.updateContents_();
-    },
-
-    get data() {
-      return this.data_;
-    },
-
-    get margin() {
-      var margin = {top: 20, right: 20, bottom: 30, left: 50};
-      if (this.chartTitle_)
-        margin.top += 20;
-      return margin;
-    },
-
-    get chartAreaSize() {
-      var margin = this.margin;
-      return {
-        width: this.width_ - margin.left - margin.right,
-        height: this.height_ - margin.top - margin.bottom
-      };
-    },
-
-    getLegendKeys_: function() {
-      throw new Error('Not implemented');
-    },
-
-    updateScales_: function(width, height) {
-      throw new Error('Not implemented');
-    },
-
-    updateContents_: function() {
-      var margin = this.margin;
-      var width = this.chartAreaSize.width;
-      var height = this.chartAreaSize.height;
-
-      var thisSel = d3.select(this);
-      thisSel.attr('width', this.width_);
-      thisSel.attr('height', this.height_);
-
-      var chartAreaSel = d3.select(this.chartAreaElement);
-      chartAreaSel.attr(
-          'transform',
-          'translate(' + margin.left + ',' + margin.top + ')');
-
-      this.updateScales_(width, height);
-
-      // Axes.
-      if (this.xScale_ && this.yScale_) {
-        var xAxisRenderer = d3.svg.axis()
-            .scale(this.xScale_)
-            .orient('bottom');
-
-        var yAxisRenderer = d3.svg.axis()
-            .scale(this.yScale_)
-            .orient('left');
-
-        chartAreaSel.select('.x.axis')
-            .attr('transform', 'translate(0,' + height + ')')
-            .call(xAxisRenderer);
-
-        chartAreaSel.select('.y.axis')
-            .call(yAxisRenderer);
-      }
-
-      // Title.
-      var titleSel = chartAreaSel.select('#title');
-      if (this.chartTitle_) {
-        titleSel.attr('transform', 'translate(' + width * 0.5 + ',-5)')
-            .style('display', undefined)
-            .style('text-anchor', 'middle')
-            .attr('class', 'title')
-            .attr('width', width)
-            .text(this.chartTitle_);
-      } else {
-        titleSel.style('display', 'none');
-      }
-
-      this.updateLegend_();
-    },
-
-    updateLegend_: function() {
-      var keys = this.getLegendKeys_();
-
-      var chartAreaSel = d3.select(this.chartAreaElement);
-      var chartAreaSize = this.chartAreaSize;
-
-      var legendEntriesSel = chartAreaSel.selectAll('.legend')
-          .data(keys.slice().reverse());
-
-      legendEntriesSel.enter()
-          .append('g')
-          .attr('class', 'legend')
-          .attr('transform', function(d, i) {
-            return 'translate(0,' + i * 20 + ')';
-          }).append('text').text(function(key) {
-            return key;
-          });
-      legendEntriesSel.exit().remove();
-
-      legendEntriesSel.attr('x', chartAreaSize.width - 18)
-          .attr('width', 18)
-          .attr('height', 18)
-          .style('fill', function(key) {
-            return getColorOfKey(key);
-          });
-
-      legendEntriesSel.selectAll('text')
-        .attr('x', chartAreaSize.width - 24)
-        .attr('y', 9)
-        .attr('dy', '.35em')
-        .style('text-anchor', 'end')
-        .text(function(d) { return d; });
-    }
-  };
-
-  return {
-    getColorOfKey: getColorOfKey,
-    ChartBase: ChartBase
-  };
-});
diff --git a/tools/telemetry/telemetry/web_components/ui/d3.js b/tools/telemetry/telemetry/web_components/ui/d3.js
deleted file mode 100644
index 824b293..0000000
--- a/tools/telemetry/telemetry/web_components/ui/d3.js
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.requireRawScript('d3.min.js');
-
-tvcm.exportTo('telemetry.web_components.ui', function() {
-  return {};
-});
diff --git a/tools/telemetry/telemetry/web_components/ui/line_chart.css b/tools/telemetry/telemetry/web_components/ui/line_chart.css
deleted file mode 100644
index dbdd04e..0000000
--- a/tools/telemetry/telemetry/web_components/ui/line_chart.css
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Copyright 2014 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-.line-chart .line {
-  fill: none;
-  stroke-width: 1.5px;
-}
\ No newline at end of file
diff --git a/tools/telemetry/telemetry/web_components/ui/line_chart.js b/tools/telemetry/telemetry/web_components/ui/line_chart.js
deleted file mode 100644
index 2533b6b..0000000
--- a/tools/telemetry/telemetry/web_components/ui/line_chart.js
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.require('tvcm.range');
-tvcm.require('tracing.color_scheme');
-tvcm.require('telemetry.web_components.ui.d3');
-tvcm.require('telemetry.web_components.ui.chart_base');
-
-tvcm.requireStylesheet('telemetry.web_components.ui.line_chart');
-
-tvcm.exportTo('telemetry.web_components.ui', function() {
-  var ChartBase = telemetry.web_components.ui.ChartBase;
-  var getColorOfKey = telemetry.web_components.ui.getColorOfKey;
-
-  /**
-   * @constructor
-   */
-  var LineChart = tvcm.ui.define('line-chart', ChartBase);
-
-  LineChart.prototype = {
-    __proto__: ChartBase.prototype,
-
-    decorate: function() {
-      ChartBase.prototype.decorate.call(this);
-      this.classList.add('line-chart');
-
-      this.xScale_ = d3.scale.linear();
-      this.yScale_ = d3.scale.linear();
-      d3.select(this.chartAreaElement)
-          .append('g')
-          .attr('id', 'series');
-    },
-
-    /**
-     * Sets the data array for the object
-     *
-     * @param {Array} data The data. Each element must be an object, with at
-     * least an x property. All other properties become series names in the
-     * chart.
-     */
-    set data(data) {
-      if (data.length == 0)
-        throw new Error('Data must be nonzero. Pass undefined.');
-
-      var keys;
-      if (data !== undefined) {
-        var d = data[0];
-        if (d.x === undefined)
-          throw new Error('Elements must have "x" fields');
-        keys = d3.keys(data[0]);
-        keys.splice(keys.indexOf('x'), 1);
-        if (keys.length == 0)
-          throw new Error('Elements must have at least one other field than X');
-      } else {
-        keys = undefined;
-      }
-      this.data_ = data;
-      this.seriesKeys_ = keys;
-
-      this.updateContents_();
-    },
-
-    getLegendKeys_: function() {
-      if (this.seriesKeys_ &&
-          this.seriesKeys_.length > 1)
-        return this.seriesKeys_.slice();
-      return [];
-    },
-
-    updateScales_: function(width, height) {
-      if (this.data_ === undefined)
-        return;
-
-      // X.
-      this.xScale_.range([0, width]);
-      this.xScale_.domain(d3.extent(this.data_, function(d) { return d.x; }));
-
-      // Y.
-      var yRange = new tvcm.Range();
-      this.data_.forEach(function(d) {
-        this.seriesKeys_.forEach(function(k) {
-          yRange.addValue(d[k]);
-        });
-      }, this);
-
-      this.yScale_.range([height, 0]);
-      this.yScale_.domain([yRange.min, yRange.max]);
-    },
-
-    updateContents_: function() {
-      ChartBase.prototype.updateContents_.call(this);
-      if (!this.data_)
-        return;
-
-      var chartAreaSel = d3.select(this.chartAreaElement);
-      var seriesSel = chartAreaSel.select('#series');
-      var pathsSel = seriesSel.selectAll('path').data(this.seriesKeys_);
-      pathsSel.enter()
-          .append('path')
-          .attr('class', 'line')
-          .style('stroke', function(key) {
-            return getColorOfKey(key);
-          })
-          .attr('d', function(key) {
-            var line = d3.svg.line()
-              .x(function(d) { return this.xScale_(d.x); }.bind(this))
-              .y(function(d) { return this.yScale_(d[key]); }.bind(this));
-            return line(this.data_);
-          }.bind(this));
-      pathsSel.exit().remove();
-    }
-  };
-
-  return {
-    LineChart: LineChart
-  };
-});
diff --git a/tools/telemetry/telemetry/web_components/ui/line_chart_unittest.js b/tools/telemetry/telemetry/web_components/ui/line_chart_unittest.js
deleted file mode 100644
index f81b2f5..0000000
--- a/tools/telemetry/telemetry/web_components/ui/line_chart_unittest.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.require('telemetry.web_components.ui.line_chart');
-
-tvcm.testSuite('telemetry.web_components.ui.line_chart_unittest', function() {
-  test('singleSeries', function() {
-    var chart = new telemetry.web_components.ui.LineChart();
-    chart.width = 400;
-    chart.height = 200;
-    chart.chartTitle = 'Chart title';
-    var data = [
-      {x: 10, y: 100},
-      {x: 20, y: 110},
-      {x: 30, y: 100},
-      {x: 40, y: 50}
-    ];
-    chart.data = data;
-    this.addHTMLOutput(chart);
-  });
-
-  test('twoSeries', function() {
-    var chart = new telemetry.web_components.ui.LineChart();
-    chart.width = 400;
-    chart.height = 200;
-    chart.chartTitle = 'Chart title';
-    var data = [
-      {x: 10, value1: 100, value2: 50},
-      {x: 20, value1: 110, value2: 75},
-      {x: 30, value1: 100, value2: 125},
-      {x: 40, value1: 50, value2: 125}
-    ];
-    chart.data = data;
-    this.addHTMLOutput(chart);
-  });
-});
diff --git a/tools/telemetry/telemetry/web_components/ui/pie_chart.css b/tools/telemetry/telemetry/web_components/ui/pie_chart.css
deleted file mode 100644
index a8fe22d..0000000
--- a/tools/telemetry/telemetry/web_components/ui/pie_chart.css
+++ /dev/null
@@ -1,4 +0,0 @@
-/* Copyright 2014 The Chromium Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
diff --git a/tools/telemetry/telemetry/web_components/ui/pie_chart.js b/tools/telemetry/telemetry/web_components/ui/pie_chart.js
deleted file mode 100644
index a3ba32e..0000000
--- a/tools/telemetry/telemetry/web_components/ui/pie_chart.js
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.require('tvcm.range');
-tvcm.require('tracing.color_scheme');
-tvcm.require('telemetry.web_components.ui.d3');
-tvcm.require('telemetry.web_components.ui.chart_base');
-
-tvcm.requireStylesheet('telemetry.web_components.ui.pie_chart');
-
-tvcm.exportTo('telemetry.web_components.ui', function() {
-  var ChartBase = telemetry.web_components.ui.ChartBase;
-  var getColorOfKey = telemetry.web_components.ui.getColorOfKey;
-
-  /**
-   * @constructor
-   */
-  var PieChart = tvcm.ui.define('pie-chart', ChartBase);
-
-  PieChart.prototype = {
-    __proto__: ChartBase.prototype,
-
-    decorate: function() {
-      ChartBase.prototype.decorate.call(this);
-      this.classList.add('pie-chart');
-
-      this.data_ = undefined;
-      this.seriesKeys_ = undefined;
-
-      var chartAreaSel = d3.select(this.chartAreaElement);
-      this.pieGroup_ = chartAreaSel.append('g')
-        .attr('class', 'pie-group')
-        .node();
-    },
-
-    get data() {
-      return this.data_;
-    },
-
-
-    /**
-     * @param {Array} data Data for the chart, where each element in the array
-     * must be of the form {label: str, value: number}.
-     */
-    set data(data) {
-      if (data !== undefined) {
-        // Figure out the label values in the data set. E.g. from
-        //   [{label: 'a', ...}, {label: 'b', ...}]
-        // we would commpute ['a', 'y']. These become the series keys.
-        var seriesKeys = [];
-        var seenSeriesKeys = {};
-        data.forEach(function(d) {
-          var k = d.label;
-          if (seenSeriesKeys[k])
-            throw new Error('Label ' + k + ' has been used already');
-          seriesKeys.push(k);
-          seenSeriesKeys[k] = true;
-        }, this);
-        this.seriesKeys_ = seriesKeys;
-      } else {
-        this.seriesKeys_ = undefined;
-      }
-      this.data_ = data;
-      this.updateContents_();
-    },
-
-    getLegendKeys_: function() {
-      if (this.data_ === undefined)
-        return [];
-      return this.seriesKeys_;
-    },
-
-    updateScales_: function(width, height) {
-      if (this.data_ === undefined)
-        return;
-    },
-
-    updateContents_: function() {
-      ChartBase.prototype.updateContents_.call(this);
-      if (!this.data_)
-        return;
-
-      var width = this.chartAreaSize.width;
-      var height = this.chartAreaSize.height;
-      var radius = Math.min(width, height) / 2;
-
-      var pieGroupSel = d3.select(this.pieGroup_);
-      pieGroupSel.attr('transform',
-                       'translate(' + width / 2 + ',' + height / 2 + ')');
-
-      // Bind the pie layout to its data
-      var pieLayout = d3.layout.pie()
-        .value(function(d) { return d.value; })
-        .sort(null);
-
-      var piePathsSel = pieGroupSel.datum(this.data_).selectAll('path')
-        .data(pieLayout);
-
-
-      var arcRenderer = d3.svg.arc()
-        .innerRadius(0)
-        .outerRadius(radius - 20);
-      piePathsSel.enter().append('path')
-        .attr('fill', function(d, i) {
-            var origData = this.data_[i];
-            return getColorOfKey(origData.label);
-          }.bind(this))
-        .attr('d', arcRenderer);
-      piePathsSel.exit().remove();
-    }
-  };
-
-  return {
-    PieChart: PieChart
-  };
-});
diff --git a/tools/telemetry/telemetry/web_components/ui/pie_chart_unittest.js b/tools/telemetry/telemetry/web_components/ui/pie_chart_unittest.js
deleted file mode 100644
index 4592a93..0000000
--- a/tools/telemetry/telemetry/web_components/ui/pie_chart_unittest.js
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-'use strict';
-
-tvcm.require('telemetry.web_components.ui.pie_chart');
-
-tvcm.testSuite('telemetry.web_components.ui.pie_chart_unittest', function() {
-  test('simple', function() {
-    var chart = new telemetry.web_components.ui.PieChart();
-    chart.width = 400;
-    chart.height = 200;
-    chart.chartTitle = 'Chart title';
-    var data = [
-      {label: 'a', value: 100},
-      {label: 'b', value: 200},
-      {label: 'c', value: 300}
-    ];
-    chart.data = data;
-    this.addHTMLOutput(chart);
-  });
-});
diff --git a/tools/telemetry/telemetry/web_components/viewer.py b/tools/telemetry/telemetry/web_components/viewer.py
deleted file mode 100644
index b5e6db1..0000000
--- a/tools/telemetry/telemetry/web_components/viewer.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright (c) 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import HTMLParser
-import json
-import os
-import string
-
-from telemetry.web_components import web_components_project
-from tvcm import generate
-
-
-class Viewer(object):
-  """An HTML-based viewer of data, built out of telemetry components.
-
-  A viewer is used to visualize complex data that is produced from a telemtry
-  benchmark. A viewer is backed by a .js file that contains a telemetry
-  component. Python-side, it knows enough to instantiate that component and pass
-  it its data. Viewers are typically written to HTML files in order to be
-  displayed.
-
-  Python-side, a viewer class can be anything, as long as it implements the
-  WriteDataToFileAsJSON. The data written here is passed to the
-  data_binding_property of the JS-side class specified during the viewer's
-  construction.
-
-  """
-  def __init__(self, tvcm_module_name, js_class_name, data_binding_property):
-    self._tvcm_module_name = tvcm_module_name
-    self._js_class_name = js_class_name
-    self._data_binding_property = data_binding_property
-
-  def WriteDataToFileAsJson(self, f):
-    raise NotImplementedError()
-
-  def WriteViewerToFile(self, f):
-    project = web_components_project.WebComponentsProject()
-    load_sequence = project.CalcLoadSequenceForModuleNames(
-      [self._tvcm_module_name])
-
-    with open(os.path.join(os.path.dirname(__file__),
-                           'viewer_bootstrap.js')) as bfile:
-      bootstrap_js_template = string.Template(bfile.read())
-    bootstrap_js = bootstrap_js_template.substitute(
-      js_class_name=self._js_class_name,
-      data_binding_property=self._data_binding_property)
-
-    bootstrap_script = generate.ExtraScript(text_content=bootstrap_js)
-
-    class ViewerDataScript(generate.ExtraScript):
-      def __init__(self, results_component):
-        super(ViewerDataScript, self).__init__()
-        self._results_component = results_component
-
-      def WriteToFile(self, output_file):
-        output_file.write('<script id="viewer-data" type="application/json">\n')
-        self._results_component.WriteDataToFileAsJson(output_file)
-        output_file.write('</script>\n')
-
-
-    generate.GenerateStandaloneHTMLToFile(
-        f, load_sequence,
-        title='Telemetry results',
-        extra_scripts=[bootstrap_script, ViewerDataScript(self)])
-
-  @staticmethod
-  def ReadDataObjectFromViewerFile(f):
-    """Reads the data inside a viewer file written with WriteViewerToFile
-
-    Returns None if the viewer data wasn't found, the JSON.parse'd object on
-    success. Raises exception if the viewer data was corrupt.
-    """
-    class MyHTMLParser(HTMLParser.HTMLParser):
-      def __init__(self):
-        HTMLParser.HTMLParser.__init__(self)
-        self._got_data_tag = False
-        self._in_data_tag = False
-        self._data_records = []
-
-      def handle_starttag(self, tag, attrs):
-        if tag != 'script':
-          return
-        id_attr = dict(attrs).get('id', None)
-        if id_attr == 'viewer-data':
-          assert not self._got_data_tag
-          self._got_data_tag = True
-          self._in_data_tag = True
-
-      def handle_endtag(self, tag):
-        self._in_data_tag = False
-
-      def handle_data(self, data):
-        if self._in_data_tag:
-          self._data_records.append(data)
-
-      @property
-      def data(self):
-        if not self._got_data_tag:
-          raise Exception('Missing <script> with #data-view')
-        if self._in_data_tag:
-          raise Exception('Missing </script> on #data-view')
-        return json.loads(''.join(self._data_records))
-
-    parser = MyHTMLParser()
-    for line in f:
-      parser.feed(line)
-    return parser.data
diff --git a/tools/telemetry/telemetry/web_components/viewer_bootstrap.js b/tools/telemetry/telemetry/web_components/viewer_bootstrap.js
deleted file mode 100644
index 8b31b05..0000000
--- a/tools/telemetry/telemetry/web_components/viewer_bootstrap.js
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-'use strict';
-
-var g_results;
-document.addEventListener('DOMContentLoaded', function() {
-  var viewerDataScript = document.querySelector('#viewer-data');
-  var data;
-  try {
-    data = JSON.parse(viewerDataScript.textContent);
-  } catch (e) {
-    tvcm.showPanic('Could not load data', e.stack || e);
-  }
-  g_results = new $js_class_name;
-  g_results.$data_binding_property = data;
-  document.body.appendChild(g_results);
-});
diff --git a/tools/telemetry/telemetry/web_components/viewer_unittest.py b/tools/telemetry/telemetry/web_components/viewer_unittest.py
deleted file mode 100644
index 9394eee..0000000
--- a/tools/telemetry/telemetry/web_components/viewer_unittest.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright (c) 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import unittest
-import StringIO
-
-from telemetry.web_components import viewer
-
-class SimpleViewer(viewer.Viewer):
-  def __init__(self):
-    super(SimpleViewer, self).__init__(
-      tvcm_module_name='telemetry.web_components.viewer_unittest_data',
-      js_class_name='telemetry.web_components.SimpleViewer',
-      data_binding_property='dataToView')
-
-  def WriteDataToFileAsJson(self, f):
-    f.write("1\n")
-
-class ViewerTests(unittest.TestCase):
-  def testForSmoke(self):
-    v = SimpleViewer()
-
-    f = StringIO.StringIO()
-    v.WriteViewerToFile(f)
-
-  def testRead(self):
-    v = SimpleViewer()
-
-    f = StringIO.StringIO()
-    v.WriteViewerToFile(f)
-
-    f.seek(0)
-
-    data = SimpleViewer.ReadDataObjectFromViewerFile(f)
-    self.assertEquals(data, 1)
diff --git a/tools/telemetry/telemetry/web_components/web_component.py b/tools/telemetry/telemetry/web_components/web_component.py
new file mode 100644
index 0000000..ee81aa4
--- /dev/null
+++ b/tools/telemetry/telemetry/web_components/web_component.py
@@ -0,0 +1,124 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import HTMLParser
+import json
+import os
+import string
+
+from telemetry.web_components import web_components_project
+from tvcm import generate
+
+
+class WebComponent(object):
+  """An HTML-based viewer of data, built out of telemetry components.
+
+  A WebComponent is used to visualize complex data that is produced from a
+  telemtry benchmark. A WebComponent is a Javascript class that can be
+  data-bound, plus python-side bindings that let us write HTML files that
+  instantiate that class and bind it to specific data.
+
+  The primary job of the python side of a WebComponent is to implement the
+  WriteDataToFileAsJson. The data written here is passed to the
+  data_binding_property of the JS-side class.
+
+  The primary job of the javascript side of a WebComponent is visualization: it
+  takes the data from python and renders a UI for displaying that data in some
+  manner.
+
+  """
+  def __init__(self, tvcm_module_name, js_class_name, data_binding_property):
+    self._tvcm_module_name = tvcm_module_name
+    self._js_class_name = js_class_name
+    self._data_binding_property = data_binding_property
+    self._data_to_view = None
+
+  @property
+  def data_to_view(self):
+    return self._data_to_view
+
+  @data_to_view.setter
+  def data_to_view(self, data_to_view):
+    self._data_to_view = data_to_view
+
+  def WriteDataToFileAsJson(self, f):
+    raise NotImplementedError()
+
+  def GetDependentModuleNames(self):
+    return [self._tvcm_module_name]
+
+  def WriteWebComponentToFile(self, f):
+    project = web_components_project.WebComponentsProject()
+    load_sequence = project.CalcLoadSequenceForModuleNames(
+      self.GetDependentModuleNames())
+
+    with open(os.path.join(os.path.dirname(__file__),
+                           'web_component_bootstrap.js')) as bfile:
+      bootstrap_js_template = string.Template(bfile.read())
+    bootstrap_js = bootstrap_js_template.substitute(
+      js_class_name=self._js_class_name,
+      data_binding_property=self._data_binding_property)
+
+    bootstrap_script = generate.ExtraScript(text_content=bootstrap_js)
+
+    class WebComponentDataScript(generate.ExtraScript):
+      def __init__(self, results_component):
+        super(WebComponentDataScript, self).__init__()
+        self._results_component = results_component
+
+      def WriteToFile(self, output_file):
+        output_file.write('<script id="telemetry-web-component-data" ' +
+                          'type="application/json">\n')
+        self._results_component.WriteDataToFileAsJson(output_file)
+        output_file.write('</script>\n')
+
+
+    generate.GenerateStandaloneHTMLToFile(
+        f, load_sequence,
+        title='Telemetry results',
+        extra_scripts=[bootstrap_script, WebComponentDataScript(self)])
+
+  @staticmethod
+  def ReadDataObjectFromWebComponentFile(f):
+    """Reads the data inside a file written with WriteWebComponentToFile
+
+    Returns None if the data wasn't found, the JSON.parse'd object on success.
+    Raises exception if the HTML file was corrupt.
+
+    """
+    class MyHTMLParser(HTMLParser.HTMLParser):
+      def __init__(self):
+        HTMLParser.HTMLParser.__init__(self)
+        self._got_data_tag = False
+        self._in_data_tag = False
+        self._data_records = []
+
+      def handle_starttag(self, tag, attrs):
+        if tag != 'script':
+          return
+        id_attr = dict(attrs).get('id', None)
+        if id_attr == 'telemetry-web-component-data':
+          assert not self._got_data_tag
+          self._got_data_tag = True
+          self._in_data_tag = True
+
+      def handle_endtag(self, tag):
+        self._in_data_tag = False
+
+      def handle_data(self, data):
+        if self._in_data_tag:
+          self._data_records.append(data)
+
+      @property
+      def data(self):
+        if not self._got_data_tag:
+          raise Exception('Missing <script> with #telemetry-web-component-data')
+        if self._in_data_tag:
+          raise Exception('Missing </script> on #telemetry-web-component-data')
+        return json.loads(''.join(self._data_records))
+
+    parser = MyHTMLParser()
+    for line in f:
+      parser.feed(line)
+    return parser.data
diff --git a/tools/telemetry/telemetry/web_components/web_component_bootstrap.js b/tools/telemetry/telemetry/web_components/web_component_bootstrap.js
new file mode 100644
index 0000000..eaee109
--- /dev/null
+++ b/tools/telemetry/telemetry/web_components/web_component_bootstrap.js
@@ -0,0 +1,19 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+'use strict';
+
+var g_results;
+document.addEventListener('DOMContentLoaded', function() {
+  var componentDataScript = document.querySelector(
+      '#telemetry-web-component-data');
+  var data;
+  try {
+    data = JSON.parse(componentDataScript.textContent);
+  } catch (e) {
+    tvcm.showPanic('Could not load data', e.stack || e);
+  }
+  g_results = new $js_class_name;
+  g_results.$data_binding_property = data;
+  document.body.appendChild(g_results);
+});
diff --git a/tools/telemetry/telemetry/web_components/web_component_unittest.py b/tools/telemetry/telemetry/web_components/web_component_unittest.py
new file mode 100644
index 0000000..7387adb
--- /dev/null
+++ b/tools/telemetry/telemetry/web_components/web_component_unittest.py
@@ -0,0 +1,36 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import unittest
+import StringIO
+
+from telemetry.web_components import web_component
+
+class SimpleWebComponent(web_component.WebComponent):
+  def __init__(self):
+    super(SimpleWebComponent, self).__init__(
+      tvcm_module_name='telemetry.web_components.viewer_unittest_data',
+      js_class_name='telemetry.web_components.SimpleWebComponent',
+      data_binding_property='dataToView')
+
+  def WriteDataToFileAsJson(self, f):
+    f.write("1\n")
+
+class WebComponentTests(unittest.TestCase):
+  def testForSmoke(self):
+    v = SimpleWebComponent()
+
+    f = StringIO.StringIO()
+    v.WriteWebComponentToFile(f)
+
+  def testRead(self):
+    v = SimpleWebComponent()
+
+    f = StringIO.StringIO()
+    v.WriteWebComponentToFile(f)
+
+    f.seek(0)
+
+    data = SimpleWebComponent.ReadDataObjectFromWebComponentFile(f)
+    self.assertEquals(data, 1)
diff --git a/tools/telemetry/third_party/d3/LICENSE b/tools/telemetry/third_party/d3/LICENSE
deleted file mode 100644
index fb7d95d..0000000
--- a/tools/telemetry/third_party/d3/LICENSE
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 2014, Michael Bostock
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-* The name Michael Bostock may not be used to endorse or promote products
-  derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tools/telemetry/third_party/d3/README.chromium b/tools/telemetry/third_party/d3/README.chromium
deleted file mode 100644
index 35362f8..0000000
--- a/tools/telemetry/third_party/d3/README.chromium
+++ /dev/null
@@ -1,15 +0,0 @@
-Name: d3
-Short Name: d3
-URL: https://github.com/mbostock/d3
-Version: 0
-Revision: 0b2fe8fe9eaa529f70f6ab93bc8580b2a5328f43
-Date: Sat Mar 1 11:31:09 2014 -0800
-License: BSD
-License File: NOT_SHIPPED
-Security Critical: no
-
-Description:
-A JavaScript visualization library for HTML and SVG.
-
-Local Modifications:
-Took only the minified JS file and associated license.
diff --git a/tools/telemetry/third_party/d3/d3.min.js b/tools/telemetry/third_party/d3/d3.min.js
deleted file mode 100644
index b0178b6..0000000
--- a/tools/telemetry/third_party/d3/d3.min.js
+++ /dev/null
@@ -1,5 +0,0 @@
-!function(){function n(n){return null!=n&&!isNaN(n)}function t(n){return n.length}function e(n){for(var t=1;n*t%1;)t*=10;return t}function r(n,t){try{for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}catch(r){n.prototype=t}}function u(){}function i(n){return aa+n in this}function o(n){return n=aa+n,n in this&&delete this[n]}function a(){var n=[];return this.forEach(function(t){n.push(t)}),n}function c(){var n=0;for(var t in this)t.charCodeAt(0)===ca&&++n;return n}function s(){for(var n in this)if(n.charCodeAt(0)===ca)return!1;return!0}function l(){}function f(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function h(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.substring(1);for(var e=0,r=sa.length;r>e;++e){var u=sa[e]+t;if(u in n)return u}}function g(){}function p(){}function v(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new u;return t.on=function(t,u){var i,o=r.get(t);return arguments.length<2?o&&o.on:(o&&(o.on=null,e=e.slice(0,i=e.indexOf(o)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function d(){Xo.event.preventDefault()}function m(){for(var n,t=Xo.event;n=t.sourceEvent;)t=n;return t}function y(n){for(var t=new p,e=0,r=arguments.length;++e<r;)t[arguments[e]]=v(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=Xo.event;u.target=n,Xo.event=u,t[u.type].apply(e,r)}finally{Xo.event=i}}},t}function x(n){return fa(n,da),n}function M(n){return"function"==typeof n?n:function(){return ha(n,this)}}function _(n){return"function"==typeof n?n:function(){return ga(n,this)}}function b(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=Xo.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?a:o:n.local?i:u}function w(n){return n.trim().replace(/\s+/g," ")}function S(n){return new RegExp("(?:^|\\s+)"+Xo.requote(n)+"(?:\\s+|$)","g")}function k(n){return n.trim().split(/^|\s+/)}function E(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=k(n).map(A);var u=n.length;return"function"==typeof t?r:e}function A(n){var t=S(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",w(u+" "+n))):e.setAttribute("class",w(u.replace(t," ")))}}function C(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function N(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function L(n){return"function"==typeof n?n:(n=Xo.ns.qualify(n)).local?function(){return this.ownerDocument.createElementNS(n.space,n.local)}:function(){return this.ownerDocument.createElementNS(this.namespaceURI,n)}}function T(n){return{__data__:n}}function q(n){return function(){return va(this,n)}}function z(n){return arguments.length||(n=Xo.ascending),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function R(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function D(n){return fa(n,ya),n}function P(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t<c;);return o}}function U(){var n=this.__transition__;n&&++n.active}function j(n,t,e){function r(){var t=this[o];t&&(this.removeEventListener(n,t,t.$),delete this[o])}function u(){var u=c(t,Bo(arguments));r.call(this),this.addEventListener(n,this[o]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+Xo.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var o="__on"+n,a=n.indexOf("."),c=H;a>0&&(n=n.substring(0,a));var s=Ma.get(n);return s&&(n=s,c=F),a?t?u:r:t?g:i}function H(n,t){return function(e){var r=Xo.event;Xo.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{Xo.event=r}}}function F(n,t){var e=H(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function O(){var n=".dragsuppress-"+ ++ba,t="click"+n,e=Xo.select(Go).on("touchmove"+n,d).on("dragstart"+n,d).on("selectstart"+n,d);if(_a){var r=Jo.style,u=r[_a];r[_a]="none"}return function(i){function o(){e.on(t,null)}e.on(n,null),_a&&(r[_a]=u),i&&(e.on(t,function(){d(),o()},!0),setTimeout(o,0))}}function Y(n,t){t.changedTouches&&(t=t.changedTouches[0]);var e=n.ownerSVGElement||n;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>wa&&(Go.scrollX||Go.scrollY)){e=Xo.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var u=e[0][0].getScreenCTM();wa=!(u.f||u.e),e.remove()}return wa?(r.x=t.pageX,r.y=t.pageY):(r.x=t.clientX,r.y=t.clientY),r=r.matrixTransform(n.getScreenCTM().inverse()),[r.x,r.y]}var i=n.getBoundingClientRect();return[t.clientX-i.left-n.clientLeft,t.clientY-i.top-n.clientTop]}function I(n){return n>0?1:0>n?-1:0}function Z(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function V(n){return n>1?0:-1>n?Sa:Math.acos(n)}function X(n){return n>1?Ea:-1>n?-Ea:Math.asin(n)}function $(n){return((n=Math.exp(n))-1/n)/2}function B(n){return((n=Math.exp(n))+1/n)/2}function W(n){return((n=Math.exp(2*n))-1)/(n+1)}function J(n){return(n=Math.sin(n/2))*n}function G(){}function K(n,t,e){return new Q(n,t,e)}function Q(n,t,e){this.h=n,this.s=t,this.l=e}function nt(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,gt(u(n+120),u(n),u(n-120))}function tt(n,t,e){return new et(n,t,e)}function et(n,t,e){this.h=n,this.c=t,this.l=e}function rt(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),ut(e,Math.cos(n*=Na)*t,Math.sin(n)*t)}function ut(n,t,e){return new it(n,t,e)}function it(n,t,e){this.l=n,this.a=t,this.b=e}function ot(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=ct(u)*Fa,r=ct(r)*Oa,i=ct(i)*Ya,gt(lt(3.2404542*u-1.5371385*r-.4985314*i),lt(-.969266*u+1.8760108*r+.041556*i),lt(.0556434*u-.2040259*r+1.0572252*i))}function at(n,t,e){return n>0?tt(Math.atan2(e,t)*La,Math.sqrt(t*t+e*e),n):tt(0/0,0/0,n)}function ct(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function st(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function lt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function ft(n){return gt(n>>16,255&n>>8,255&n)}function ht(n){return ft(n)+""}function gt(n,t,e){return new pt(n,t,e)}function pt(n,t,e){this.r=n,this.g=t,this.b=e}function vt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function dt(n,t,e){var r,u,i,o,a=0,c=0,s=0;if(u=/([a-z]+)\((.*)\)/i.exec(n))switch(i=u[2].split(","),u[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return t(Mt(i[0]),Mt(i[1]),Mt(i[2]))}return(o=Va.get(n))?t(o.r,o.g,o.b):(null!=n&&"#"===n.charAt(0)&&(r=parseInt(n.substring(1),16),isNaN(r)||(4===n.length?(a=(3840&r)>>4,a=a>>4|a,c=240&r,c=c>>4|c,s=15&r,s=s<<4|s):7===n.length&&(a=(16711680&r)>>16,c=(65280&r)>>8,s=255&r))),t(a,c,s))}function mt(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),K(r,u,c)}function yt(n,t,e){n=xt(n),t=xt(t),e=xt(e);var r=st((.4124564*n+.3575761*t+.1804375*e)/Fa),u=st((.2126729*n+.7151522*t+.072175*e)/Oa),i=st((.0193339*n+.119192*t+.9503041*e)/Ya);return ut(116*u-16,500*(r-u),200*(u-i))}function xt(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Mt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function _t(n){return"function"==typeof n?n:function(){return n}}function bt(n){return n}function wt(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),St(t,e,n,r)}}function St(n,t,e,r){function u(){var n,t=c.status;if(!t&&c.responseText||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return o.error.call(i,r),void 0}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=Xo.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,s=null;return!Go.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=Xo.event;Xo.event=n;try{o.progress.call(i,c)}finally{Xo.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(s=n,i):s},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(Bo(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var l in a)c.setRequestHeader(l,a[l]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=s&&(c.responseType=s),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},Xo.rebind(i,o,"on"),null==r?i:i.get(kt(r))}function kt(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Et(){var n=At(),t=Ct()-n;t>24?(isFinite(t)&&(clearTimeout(Wa),Wa=setTimeout(Et,t)),Ba=0):(Ba=1,Ga(Et))}function At(){var n=Date.now();for(Ja=Xa;Ja;)n>=Ja.t&&(Ja.f=Ja.c(n-Ja.t)),Ja=Ja.n;return n}function Ct(){for(var n,t=Xa,e=1/0;t;)t.f?t=n?n.n=t.n:Xa=t.n:(t.t<e&&(e=t.t),t=(n=t).n);return $a=n,e}function Nt(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function Lt(n,t){var e=Math.pow(10,3*oa(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Tt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r?function(n){for(var t=n.length,u=[],i=0,o=r[0];t>0&&o>0;)u.push(n.substring(t-=o,t+o)),o=r[i=(i+1)%r.length];return u.reverse().join(e)}:bt;return function(n){var e=Qa.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"",c=e[4]||"",s=e[5],l=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1;switch(h&&(h=+h.substring(1)),(s||"0"===r&&"="===o)&&(s=r="0",o="=",f&&(l-=Math.floor((l-1)/4))),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=nc.get(g)||qt;var y=s&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):a;if(0>p){var c=Xo.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x=n.lastIndexOf("."),M=0>x?n:n.substring(0,x),_=0>x?"":t+n.substring(x+1);!s&&f&&(M=i(M));var b=v.length+M.length+_.length+(y?0:u.length),w=l>b?new Array(b=l-b+1).join(r):"";return y&&(M=i(w+M)),u+=v,n=M+_,("<"===o?u+n+w:">"===o?w+u+n:"^"===o?w.substring(0,b>>=1)+u+n+w.substring(b):u+(y?n:w+n))+e}}}function qt(n){return n+""}function zt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Rt(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new ec(e-1)),1),e}function i(n,e){return t(n=new ec(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{ec=zt;var r=new zt;return r._=n,o(r,t,e)}finally{ec=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Dt(n);return c.floor=c,c.round=Dt(r),c.ceil=Dt(u),c.offset=Dt(i),c.range=a,n}function Dt(n){return function(t,e){try{ec=zt;var r=new zt;return r._=t,n(r,e)._}finally{ec=Date}}}function Pt(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++a<r;)37===n.charCodeAt(a)&&(o.push(n.substring(c,a)),null!=(u=uc[e=n.charAt(++a)])&&(e=n.charAt(++a)),(i=C[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),o.push(e),c=a+1);return o.push(n.substring(c,a)),o.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&ec!==zt,o=new(i?zt:ec);return"j"in r?o.setFullYear(r.y,0,r.j):"w"in r&&("W"in r||"U"in r)?(o.setFullYear(r.y,0,1),o.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(o.getDay()+5)%7:r.w+7*r.U-(o.getDay()+6)%7)):o.setFullYear(r.y,r.m,r.d),o.setHours(r.H+Math.floor(r.Z/100),r.M+r.Z%100,r.S,r.L),i?o._:o},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,o,a=0,c=t.length,s=e.length;c>a;){if(r>=s)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=N[o in uc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){b.lastIndex=0;var r=b.exec(t.substring(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){M.lastIndex=0;var r=M.exec(t.substring(e));return r?(n.w=_.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.substring(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.substring(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,C.c.toString(),t,r)}function c(n,t,r){return e(n,C.x.toString(),t,r)}function s(n,t,r){return e(n,C.X.toString(),t,r)}function l(n,t,e){var r=x.get(t.substring(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{ec=zt;var t=new ec;return t._=n,r(t)}finally{ec=Date}}var r=t(n);return e.parse=function(n){try{ec=zt;var t=r.parse(n);return t&&t._}finally{ec=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ee;var x=Xo.map(),M=jt(v),_=Ht(v),b=jt(d),w=Ht(d),S=jt(m),k=Ht(m),E=jt(y),A=Ht(y);p.forEach(function(n,t){x.set(n.toLowerCase(),t)});var C={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Ut(n.getDate(),t,2)},e:function(n,t){return Ut(n.getDate(),t,2)},H:function(n,t){return Ut(n.getHours(),t,2)},I:function(n,t){return Ut(n.getHours()%12||12,t,2)},j:function(n,t){return Ut(1+tc.dayOfYear(n),t,3)},L:function(n,t){return Ut(n.getMilliseconds(),t,3)},m:function(n,t){return Ut(n.getMonth()+1,t,2)},M:function(n,t){return Ut(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Ut(n.getSeconds(),t,2)},U:function(n,t){return Ut(tc.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Ut(tc.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Ut(n.getFullYear()%100,t,2)},Y:function(n,t){return Ut(n.getFullYear()%1e4,t,4)},Z:ne,"%":function(){return"%"}},N={a:r,A:u,b:i,B:o,c:a,d:Bt,e:Bt,H:Jt,I:Jt,j:Wt,L:Qt,m:$t,M:Gt,p:l,S:Kt,U:Ot,w:Ft,W:Yt,x:c,X:s,y:Zt,Y:It,Z:Vt,"%":te};return t}function Ut(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function jt(n){return new RegExp("^(?:"+n.map(Xo.requote).join("|")+")","i")}function Ht(n){for(var t=new u,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function Ft(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Ot(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.U=+r[0],e+r[0].length):-1}function Yt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e));return r?(n.W=+r[0],e+r[0].length):-1}function It(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Zt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.y=Xt(+r[0]),e+r[0].length):-1}function Vt(n,t,e){return/^[+-]\d{4}$/.test(t=t.substring(e,e+5))?(n.Z=+t,e+5):-1}function Xt(n){return n+(n>68?1900:2e3)}function $t(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Bt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function Wt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function Jt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function Gt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function Kt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function Qt(n,t,e){ic.lastIndex=0;var r=ic.exec(t.substring(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ne(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=~~(oa(t)/60),u=oa(t)%60;return e+Ut(r,"0",2)+Ut(u,"0",2)}function te(n,t,e){oc.lastIndex=0;var r=oc.exec(t.substring(e,e+1));return r?e+r[0].length:-1}function ee(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function re(){}function ue(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function ie(n,t){n&&lc.hasOwnProperty(n.type)&&lc[n.type](n,t)}function oe(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function ae(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)oe(n[e],t,1);t.polygonEnd()}function ce(){function n(n,t){n*=Na,t=t*Na/2+Sa/4;var e=n-r,o=e>=0?1:-1,a=o*e,c=Math.cos(t),s=Math.sin(t),l=i*s,f=u*c+l*Math.cos(a),h=l*o*Math.sin(a);hc.add(Math.atan2(h,f)),r=n,u=c,i=s}var t,e,r,u,i;gc.point=function(o,a){gc.point=n,r=(t=o)*Na,u=Math.cos(a=(e=a)*Na/2+Sa/4),i=Math.sin(a)},gc.lineEnd=function(){n(t,e)}}function se(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function le(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function fe(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function he(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ge(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function pe(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function ve(n){return[Math.atan2(n[1],n[0]),X(n[2])]}function de(n,t){return oa(n[0]-t[0])<Aa&&oa(n[1]-t[1])<Aa}function me(n,t){n*=Na;var e=Math.cos(t*=Na);ye(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function ye(n,t,e){++pc,dc+=(n-dc)/pc,mc+=(t-mc)/pc,yc+=(e-yc)/pc}function xe(){function n(n,u){n*=Na;var i=Math.cos(u*=Na),o=i*Math.cos(n),a=i*Math.sin(n),c=Math.sin(u),s=Math.atan2(Math.sqrt((s=e*c-r*a)*s+(s=r*o-t*c)*s+(s=t*a-e*o)*s),t*o+e*a+r*c);vc+=s,xc+=s*(t+(t=o)),Mc+=s*(e+(e=a)),_c+=s*(r+(r=c)),ye(t,e,r)}var t,e,r;kc.point=function(u,i){u*=Na;var o=Math.cos(i*=Na);t=o*Math.cos(u),e=o*Math.sin(u),r=Math.sin(i),kc.point=n,ye(t,e,r)}}function Me(){kc.point=me}function _e(){function n(n,t){n*=Na;var e=Math.cos(t*=Na),o=e*Math.cos(n),a=e*Math.sin(n),c=Math.sin(t),s=u*c-i*a,l=i*o-r*c,f=r*a-u*o,h=Math.sqrt(s*s+l*l+f*f),g=r*o+u*a+i*c,p=h&&-V(g)/h,v=Math.atan2(h,g);bc+=p*s,wc+=p*l,Sc+=p*f,vc+=v,xc+=v*(r+(r=o)),Mc+=v*(u+(u=a)),_c+=v*(i+(i=c)),ye(r,u,i)}var t,e,r,u,i;kc.point=function(o,a){t=o,e=a,kc.point=n,o*=Na;var c=Math.cos(a*=Na);r=c*Math.cos(o),u=c*Math.sin(o),i=Math.sin(a),ye(r,u,i)},kc.lineEnd=function(){n(t,e),kc.lineEnd=Me,kc.point=me}}function be(){return!0}function we(n,t,e,r,u){var i=[],o=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(de(e,r)){u.lineStart();for(var a=0;t>a;++a)u.point((e=n[a])[0],e[1]);return u.lineEnd(),void 0}var c=new ke(e,n,null,!0),s=new ke(e,null,c,!1);c.o=s,i.push(c),o.push(s),c=new ke(r,n,null,!1),s=new ke(r,null,c,!0),c.o=s,i.push(c),o.push(s)}}),o.sort(t),Se(i),Se(o),i.length){for(var a=0,c=e,s=o.length;s>a;++a)o[a].e=c=!c;for(var l,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;l=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,s=l.length;s>a;++a)u.point((f=l[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){l=g.p.z;for(var a=l.length-1;a>=0;--a)u.point((f=l[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,l=g.z,p=!p}while(!g.v);u.lineEnd()}}}function Se(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function ke(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Ee(n,t,e,r){return function(u,i){function o(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function a(n,t){var e=u(n,t);d.point(e[0],e[1])}function c(){y.point=a,d.lineStart()}function s(){y.point=o,d.lineEnd()}function l(n,t){v.push([n,t]);var e=u(n,t);M.point(e[0],e[1])}function f(){M.lineStart(),v=[]}function h(){l(v[0][0],v[0][1]),M.lineEnd();var n,t=M.clean(),e=x.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r){if(1&t){n=e[0];var u,r=n.length-1,o=-1;for(i.lineStart();++o<r;)i.point((u=n[o])[0],u[1]);return i.lineEnd(),void 0}r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Ae))}}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:s,polygonStart:function(){y.point=l,y.lineStart=f,y.lineEnd=h,g=[],p=[],i.polygonStart()},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=s,g=Xo.merge(g);var n=Le(m,p);g.length?we(g,Ne,n,e,i):n&&(i.lineStart(),e(null,null,1,i),i.lineEnd()),i.polygonEnd(),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},x=Ce(),M=t(x);return y}}function Ae(n){return n.length>1}function Ce(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:g,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function Ne(n,t){return((n=n.x)[0]<0?n[1]-Ea-Aa:Ea-n[1])-((t=t.x)[0]<0?t[1]-Ea-Aa:Ea-t[1])}function Le(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,o=0;hc.reset();for(var a=0,c=t.length;c>a;++a){var s=t[a],l=s.length;if(l)for(var f=s[0],h=f[0],g=f[1]/2+Sa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===l&&(d=0),n=s[d];var m=n[0],y=n[1]/2+Sa/4,x=Math.sin(y),M=Math.cos(y),_=m-h,b=_>=0?1:-1,w=b*_,S=w>Sa,k=p*x;if(hc.add(Math.atan2(k*b*Math.sin(w),v*M+k*Math.cos(w))),i+=S?_+b*ka:_,S^h>=e^m>=e){var E=fe(se(f),se(n));pe(E);var A=fe(u,E);pe(A);var C=(S^_>=0?-1:1)*X(A[2]);(r>C||r===C&&(E[0]||E[1]))&&(o+=S^_>=0?1:-1)}if(!d++)break;h=m,p=x,v=M,f=n}}return(-Aa>i||Aa>i&&0>hc)^1&o}function Te(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?Sa:-Sa,c=oa(i-e);oa(c-Sa)<Aa?(n.point(e,r=(r+o)/2>0?Ea:-Ea),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=Sa&&(oa(e-u)<Aa&&(e-=u*Aa),oa(i-a)<Aa&&(i-=a*Aa),r=qe(e,r,i,o),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),t=0),n.point(e=i,r=o),u=a},lineEnd:function(){n.lineEnd(),e=r=0/0},clean:function(){return 2-t}}}function qe(n,t,e,r){var u,i,o=Math.sin(n-e);return oa(o)>Aa?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function ze(n,t,e,r){var u;if(null==n)u=e*Ea,r.point(-Sa,u),r.point(0,u),r.point(Sa,u),r.point(Sa,0),r.point(Sa,-u),r.point(0,-u),r.point(-Sa,-u),r.point(-Sa,0),r.point(-Sa,u);else if(oa(n[0]-t[0])>Aa){var i=n[0]<t[0]?Sa:-Sa;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Re(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,s,l;return{lineStart:function(){s=c=!1,l=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?Sa:-Sa),h):0;if(!e&&(s=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(de(e,g)||de(p,g))&&(p[0]+=Aa,p[1]+=Aa,v=t(p[0],p[1]))),v!==c)l=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(l=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&de(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return l|(s&&c)<<1}}}function r(n,t,e){var r=se(n),u=se(t),o=[1,0,0],a=fe(r,u),c=le(a,a),s=a[0],l=c-s*s;if(!l)return!e&&n;var f=i*c/l,h=-i*s/l,g=fe(o,a),p=ge(o,f),v=ge(a,h);he(p,v);var d=g,m=le(p,d),y=le(d,d),x=m*m-y*(le(p,p)-1);if(!(0>x)){var M=Math.sqrt(x),_=ge(d,(-m-M)/y);if(he(_,p),_=ve(_),!e)return _;var b,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(b=w,w=S,S=b);var A=S-w,C=oa(A-Sa)<Aa,N=C||Aa>A;if(!C&&k>E&&(b=k,k=E,E=b),N?C?k+E>0^_[1]<(oa(_[0]-w)<Aa?k:E):k<=_[1]&&_[1]<=E:A>Sa^(w<=_[0]&&_[0]<=S)){var L=ge(d,(-m+M)/y);return he(L,p),[_,ve(L)]}}}function u(t,e){var r=o?n:Sa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=oa(i)>Aa,c=cr(n,6*Na);return Ee(t,e,c,o?[0,-n]:[-Sa,n-Sa])}function De(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,s=o.y,l=a.x,f=a.y,h=0,g=1,p=l-c,v=f-s;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-s,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-s,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:s+h*v}),1>g&&(u.b={x:c+g*p,y:s+g*v}),u}}}}}}function Pe(n,t,e,r){function u(r,u){return oa(r[0]-n)<Aa?u>0?0:3:oa(r[0]-e)<Aa?u>0?2:1:oa(r[1]-t)<Aa?u>0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,s=a[0];c>o;++o)i=a[o],s[1]<=r?i[1]>r&&Z(s,i,n)>0&&++t:i[1]<=r&&Z(s,i,n)<0&&--t,s=i;return 0!==t}function s(i,a,c,s){var l=0,f=0;if(null==i||(l=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do s.point(0===l||3===l?n:e,l>1?r:t);while((l=(l+c+4)%4)!==f)}else s.point(a[0],a[1])}function l(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){l(n,t)&&a.point(n,t)}function h(){N.point=p,d&&d.push(m=[]),S=!0,w=!1,_=b=0/0}function g(){v&&(p(y,x),M&&w&&A.rejoin(),v.push(A.buffer())),N.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Ac,Math.min(Ac,n)),t=Math.max(-Ac,Math.min(Ac,t));var e=l(n,t);if(d&&m.push([n,t]),S)y=n,x=t,M=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:_,y:b},b:{x:n,y:t}};C(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}_=n,b=t,w=e}var v,d,m,y,x,M,_,b,w,S,k,E=a,A=Ce(),C=De(n,t,e,r),N={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=Xo.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),s(null,null,1,a),a.lineEnd()),u&&we(v,i,t,s,a),a.polygonEnd()),v=d=m=null}};return N}}function Ue(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function je(n){var t=0,e=Sa/3,r=nr(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*Sa/180,e=n[1]*Sa/180):[180*(t/Sa),180*(e/Sa)]},u}function He(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,X((i-(n*n+e*e)*u*u)/(2*u))]},e}function Fe(){function n(n,t){Nc+=u*n-r*t,r=n,u=t}var t,e,r,u;Rc.point=function(i,o){Rc.point=n,t=r=i,e=u=o},Rc.lineEnd=function(){n(t,e)}}function Oe(n,t){Lc>n&&(Lc=n),n>qc&&(qc=n),Tc>t&&(Tc=t),t>zc&&(zc=t)}function Ye(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Ie(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Ie(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Ie(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Ze(n,t){dc+=n,mc+=t,++yc}function Ve(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);xc+=o*(t+n)/2,Mc+=o*(e+r)/2,_c+=o,Ze(t=n,e=r)}var t,e;Pc.point=function(r,u){Pc.point=n,Ze(t=r,e=u)}}function Xe(){Pc.point=Ze}function $e(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);xc+=o*(r+n)/2,Mc+=o*(u+t)/2,_c+=o,o=u*n-r*t,bc+=o*(r+n),wc+=o*(u+t),Sc+=3*o,Ze(r=n,u=t)}var t,e,r,u;Pc.point=function(i,o){Pc.point=n,Ze(t=r=i,e=u=o)},Pc.lineEnd=function(){n(t,e)}}function Be(n){function t(t,e){n.moveTo(t,e),n.arc(t,e,o,0,ka)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:g};return a}function We(n){function t(n){return(a?r:e)(n)}function e(t){return Ke(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){x=0/0,S.point=i,t.lineStart()}function i(e,r){var i=se([e,r]),o=n(e,r);u(x,M,y,_,b,w,x=o[0],M=o[1],y=e,_=i[0],b=i[1],w=i[2],a,t),t.point(x,M)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=s,S.lineEnd=l}function s(n,t){i(f=n,h=t),g=x,p=M,v=_,d=b,m=w,S.point=i}function l(){u(x,M,y,_,b,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,x,M,_,b,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,s,l,f,h,g,p,v,d,m){var y=l-t,x=f-e,M=y*y+x*x;if(M>4*i&&d--){var _=a+g,b=c+p,w=s+v,S=Math.sqrt(_*_+b*b+w*w),k=Math.asin(w/=S),E=oa(oa(w)-1)<Aa||oa(r-h)<Aa?(r+h)/2:Math.atan2(b,_),A=n(E,k),C=A[0],N=A[1],L=C-t,T=N-e,q=x*L-y*T;(q*q/M>i||oa((y*L+x*T)/M-.5)>.3||o>a*g+c*p+s*v)&&(u(t,e,r,a,c,s,C,N,E,_/=S,b/=S,w,d,m),m.point(C,N),u(C,N,E,_,b,w,l,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Na),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function Je(n){var t=We(function(t,e){return n([t*La,e*La])});return function(n){return tr(t(n))}}function Ge(n){this.stream=n}function Ke(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Qe(n){return nr(function(){return n})()}function nr(n){function t(n){return n=a(n[0]*Na,n[1]*Na),[n[0]*h+c,s-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(s-n[1])/h),n&&[n[0]*La,n[1]*La]}function r(){a=Ue(o=ur(m,y,x),i);var n=i(v,d);return c=g-n[0]*h,s=p+n[1]*h,u()}function u(){return l&&(l.valid=!1,l=null),t}var i,o,a,c,s,l,f=We(function(n,t){return n=i(n,t),[n[0]*h+c,s-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,y=0,x=0,M=Ec,_=bt,b=null,w=null;return t.stream=function(n){return l&&(l.valid=!1),l=tr(M(o,f(_(n)))),l.valid=!0,l},t.clipAngle=function(n){return arguments.length?(M=null==n?(b=n,Ec):Re((b=+n)*Na),u()):b
-},t.clipExtent=function(n){return arguments.length?(w=n,_=n?Pe(n[0][0],n[0][1],n[1][0],n[1][1]):bt,u()):w},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Na,d=n[1]%360*Na,r()):[v*La,d*La]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Na,y=n[1]%360*Na,x=n.length>2?n[2]%360*Na:0,r()):[m*La,y*La,x*La]},Xo.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function tr(n){return Ke(n,function(t,e){n.point(t*Na,e*Na)})}function er(n,t){return[n,t]}function rr(n,t){return[n>Sa?n-ka:-Sa>n?n+ka:n,t]}function ur(n,t,e){return n?t||e?Ue(or(n),ar(t,e)):or(n):t||e?ar(t,e):rr}function ir(n){return function(t,e){return t+=n,[t>Sa?t-ka:-Sa>t?t+ka:t,e]}}function or(n){var t=ir(n);return t.invert=ir(-n),t}function ar(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*r+a*u;return[Math.atan2(c*i-l*o,a*r-s*u),X(l*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,s=Math.sin(t),l=s*i-c*o;return[Math.atan2(c*i+s*o,a*r+l*u),X(l*r-a*u)]},e}function cr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=sr(e,u),i=sr(e,i),(o>0?i>u:u>i)&&(u+=o*ka)):(u=n+o*ka,i=n-.5*c);for(var s,l=u;o>0?l>i:i>l;l-=c)a.point((s=ve([e,-r*Math.cos(l),-r*Math.sin(l)]))[0],s[1])}}function sr(n,t){var e=se(t);e[0]-=n,pe(e);var r=V(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Aa)%(2*Math.PI)}function lr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function fr(n,t,e){var r=Xo.range(n,t-Aa,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function hr(n){return n.source}function gr(n){return n.target}function pr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),s=u*Math.sin(n),l=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(J(r-t)+u*o*J(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*l,u=e*s+t*f,o=e*i+t*a;return[Math.atan2(u,r)*La,Math.atan2(o,Math.sqrt(r*r+u*u))*La]}:function(){return[n*La,t*La]};return p.distance=h,p}function vr(){function n(n,u){var i=Math.sin(u*=Na),o=Math.cos(u),a=oa((n*=Na)-t),c=Math.cos(a);Uc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;jc.point=function(u,i){t=u*Na,e=Math.sin(i*=Na),r=Math.cos(i),jc.point=n},jc.lineEnd=function(){jc.point=jc.lineEnd=g}}function dr(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function mr(n,t){function e(n,t){var e=oa(oa(t)-Ea)<Aa?0:o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(Sa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=I(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ea]},e):xr}function yr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return oa(u)<Aa?er:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-I(u)*Math.sqrt(n*n+e*e)]},e)}function xr(n,t){return[n,Math.log(Math.tan(Sa/4+t/2))]}function Mr(n){var t,e=Qe(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var o=i.apply(e,arguments);if(o===e){if(t=null==n){var a=Sa*r(),c=u();i([[c[0]-a,c[1]-a],[c[0]+a,c[1]+a]])}}else t&&(o=null);return o},e.clipExtent(null)}function _r(n,t){return[Math.log(Math.tan(Sa/4+t/2)),-n]}function br(n){return n[0]}function wr(n){return n[1]}function Sr(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Z(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function kr(n,t){return n[0]-t[0]||n[1]-t[1]}function Er(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Ar(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],s=e[1],l=t[1]-c,f=r[1]-s,h=(a*(c-s)-f*(u-i))/(f*o-a*l);return[u+h*o,c+h*l]}function Cr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Nr(){Jr(this),this.edge=this.site=this.circle=null}function Lr(n){var t=Jc.pop()||new Nr;return t.site=n,t}function Tr(n){Or(n),$c.remove(n),Jc.push(n),Jr(n)}function qr(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Tr(n);for(var c=i;c.circle&&oa(e-c.circle.x)<Aa&&oa(r-c.circle.cy)<Aa;)i=c.P,a.unshift(c),Tr(c),c=i;a.unshift(c),Or(c);for(var s=o;s.circle&&oa(e-s.circle.x)<Aa&&oa(r-s.circle.cy)<Aa;)o=s.N,a.push(s),Tr(s),s=o;a.push(s),Or(s);var l,f=a.length;for(l=1;f>l;++l)s=a[l],c=a[l-1],$r(s.edge,c.site,s.site,u);c=a[0],s=a[f-1],s.edge=Vr(c.site,s.site,null,u),Fr(c),Fr(s)}function zr(n){for(var t,e,r,u,i=n.x,o=n.y,a=$c._;a;)if(r=Rr(a,o)-i,r>Aa)a=a.L;else{if(u=i-Dr(a,o),!(u>Aa)){r>-Aa?(t=a.P,e=a):u>-Aa?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Lr(n);if($c.insert(t,c),t||e){if(t===e)return Or(t),e=Lr(t.site),$c.insert(c,e),c.edge=e.edge=Vr(t.site,c.site),Fr(t),Fr(e),void 0;if(!e)return c.edge=Vr(t.site,c.site),void 0;Or(t),Or(e);var s=t.site,l=s.x,f=s.y,h=n.x-l,g=n.y-f,p=e.site,v=p.x-l,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,x=v*v+d*d,M={x:(d*y-g*x)/m+l,y:(h*x-v*y)/m+f};$r(e.edge,s,p,M),c.edge=Vr(s,n,null,M),e.edge=Vr(n,p,null,M),Fr(t),Fr(e)}}function Rr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,s=c-t;if(!s)return a;var l=a-r,f=1/i-1/s,h=l/s;return f?(-h+Math.sqrt(h*h-2*f*(l*l/(-2*s)-c+s/2+u-i/2)))/f+r:(r+a)/2}function Dr(n,t){var e=n.N;if(e)return Rr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Pr(n){this.site=n,this.edges=[]}function Ur(n){for(var t,e,r,u,i,o,a,c,s,l,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Xc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)l=a[o].end(),r=l.x,u=l.y,s=a[++o%c].start(),t=s.x,e=s.y,(oa(r-t)>Aa||oa(u-e)>Aa)&&(a.splice(o,0,new Br(Xr(i.site,l,oa(r-f)<Aa&&p-u>Aa?{x:f,y:oa(t-f)<Aa?e:p}:oa(u-p)<Aa&&h-r>Aa?{x:oa(e-p)<Aa?t:h,y:p}:oa(r-h)<Aa&&u-g>Aa?{x:h,y:oa(t-h)<Aa?e:g}:oa(u-g)<Aa&&r-f>Aa?{x:oa(e-g)<Aa?t:f,y:g}:null),i.site,null)),++c)}function jr(n,t){return t.angle-n.angle}function Hr(){Jr(this),this.x=this.y=this.arc=this.site=this.cy=null}function Fr(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var o=u.x,a=u.y,c=r.x-o,s=r.y-a,l=i.x-o,f=i.y-a,h=2*(c*f-s*l);if(!(h>=-Ca)){var g=c*c+s*s,p=l*l+f*f,v=(f*g-s*p)/h,d=(c*p-l*g)/h,f=d+a,m=Gc.pop()||new Hr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,x=Wc._;x;)if(m.y<x.y||m.y===x.y&&m.x<=x.x){if(!x.L){y=x.P;break}x=x.L}else{if(!x.R){y=x;break}x=x.R}Wc.insert(y,m),y||(Bc=m)}}}}function Or(n){var t=n.circle;t&&(t.P||(Bc=t.N),Wc.remove(t),Gc.push(t),Jr(t),n.circle=null)}function Yr(n){for(var t,e=Vc,r=De(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Ir(t,n)||!r(t)||oa(t.a.x-t.b.x)<Aa&&oa(t.a.y-t.b.y)<Aa)&&(t.a=t.b=null,e.splice(u,1))}function Ir(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,o=t[0][0],a=t[1][0],c=t[0][1],s=t[1][1],l=n.l,f=n.r,h=l.x,g=l.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(o>d||d>=a)return;if(h>p){if(i){if(i.y>=s)return}else i={x:d,y:c};e={x:d,y:s}}else{if(i){if(i.y<c)return}else i={x:d,y:s};e={x:d,y:c}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=s)return}else i={x:(c-u)/r,y:c};e={x:(s-u)/r,y:s}}else{if(i){if(i.y<c)return}else i={x:(s-u)/r,y:s};e={x:(c-u)/r,y:c}}else if(v>g){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.x<o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}return n.a=i,n.b=e,!0}function Zr(n,t){this.l=n,this.r=t,this.a=this.b=null}function Vr(n,t,e,r){var u=new Zr(n,t);return Vc.push(u),e&&$r(u,n,t,e),r&&$r(u,t,n,r),Xc[n.i].edges.push(new Br(u,n,t)),Xc[t.i].edges.push(new Br(u,t,n)),u}function Xr(n,t,e){var r=new Zr(n,null);return r.a=t,r.b=e,Vc.push(r),r}function $r(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function Br(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function Wr(){this._=null}function Jr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function Gr(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function Kr(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function Qr(n){for(;n.L;)n=n.L;return n}function nu(n,t){var e,r,u,i=n.sort(tu).pop();for(Vc=[],Xc=new Array(n.length),$c=new Wr,Wc=new Wr;;)if(u=Bc,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(Xc[i.i]=new Pr(i),zr(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;qr(u.arc)}t&&(Yr(t),Ur(t));var o={cells:Xc,edges:Vc};return $c=Wc=Vc=Xc=null,o}function tu(n,t){return t.y-n.y||t.x-n.x}function eu(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function ru(n){return n.x}function uu(n){return n.y}function iu(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function ou(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var o=.5*(e+u),a=.5*(r+i),c=t.nodes;c[0]&&ou(n,c[0],e,r,o,a),c[1]&&ou(n,c[1],o,r,u,a),c[2]&&ou(n,c[2],e,a,o,i),c[3]&&ou(n,c[3],o,a,u,i)}}function au(n,t){n=Xo.rgb(n),t=Xo.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+vt(Math.round(e+i*n))+vt(Math.round(r+o*n))+vt(Math.round(u+a*n))}}function cu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=fu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function su(n,t){return t-=n=+n,function(e){return n+t*e}}function lu(n,t){var e,r,u,i,o,a=0,c=0,s=[],l=[];for(n+="",t+="",Qc.lastIndex=0,r=0;e=Qc.exec(t);++r)e.index&&s.push(t.substring(a,c=e.index)),l.push({i:s.length,x:e[0]}),s.push(null),a=Qc.lastIndex;for(a<t.length&&s.push(t.substring(a)),r=0,i=l.length;(e=Qc.exec(n))&&i>r;++r)if(o=l[r],o.x==e[0]){if(o.i)if(null==s[o.i+1])for(s[o.i-1]+=o.x,s.splice(o.i,1),u=r+1;i>u;++u)l[u].i--;else for(s[o.i-1]+=o.x+s[o.i+1],s.splice(o.i,2),u=r+1;i>u;++u)l[u].i-=2;else if(null==s[o.i+1])s[o.i]=o.x;else for(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1),u=r+1;i>u;++u)l[u].i--;l.splice(r,1),i--,r--}else o.x=su(parseFloat(e[0]),parseFloat(o.x));for(;i>r;)o=l.pop(),null==s[o.i+1]?s[o.i]=o.x:(s[o.i]=o.x+s[o.i+1],s.splice(o.i+1,1)),i--;return 1===s.length?null==s[0]?(o=l[0].x,function(n){return o(n)+""}):function(){return t}:function(n){for(r=0;i>r;++r)s[(o=l[r]).i]=o.x(n);return s.join("")}}function fu(n,t){for(var e,r=Xo.interpolators.length;--r>=0&&!(e=Xo.interpolators[r](n,t)););return e}function hu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(fu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function gu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function pu(n){return function(t){return 1-n(1-t)}}function vu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function du(n){return n*n}function mu(n){return n*n*n}function yu(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function xu(n){return function(t){return Math.pow(t,n)}}function Mu(n){return 1-Math.cos(n*Ea)}function _u(n){return Math.pow(2,10*(n-1))}function bu(n){return 1-Math.sqrt(1-n*n)}function wu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/ka*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*ka/t)}}function Su(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function ku(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Eu(n,t){n=Xo.hcl(n),t=Xo.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return rt(e+i*n,r+o*n,u+a*n)+""}}function Au(n,t){n=Xo.hsl(n),t=Xo.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return nt(e+i*n,r+o*n,u+a*n)+""}}function Cu(n,t){n=Xo.lab(n),t=Xo.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ot(e+i*n,r+o*n,u+a*n)+""}}function Nu(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Lu(n){var t=[n.a,n.b],e=[n.c,n.d],r=qu(t),u=Tu(t,e),i=qu(zu(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*La,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*La:0}function Tu(n,t){return n[0]*t[0]+n[1]*t[1]}function qu(n){var t=Math.sqrt(Tu(n,n));return t&&(n[0]/=t,n[1]/=t),t}function zu(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ru(n,t){var e,r=[],u=[],i=Xo.transform(n),o=Xo.transform(t),a=i.translate,c=o.translate,s=i.rotate,l=o.rotate,f=i.skew,h=o.skew,g=i.scale,p=o.scale;return a[0]!=c[0]||a[1]!=c[1]?(r.push("translate(",null,",",null,")"),u.push({i:1,x:su(a[0],c[0])},{i:3,x:su(a[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),s!=l?(s-l>180?l+=360:l-s>180&&(s+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:su(s,l)})):l&&r.push(r.pop()+"rotate("+l+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:su(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:su(g[0],p[0])},{i:e-2,x:su(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i<e;)r[(t=u[i]).i]=t.x(n);return r.join("")}}function Du(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return(e-n)*t}}function Pu(n,t){return t=t-(n=+n)?1/(t-n):0,function(e){return Math.max(0,Math.min(1,(e-n)*t))}}function Uu(n){for(var t=n.source,e=n.target,r=Hu(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function ju(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Hu(n,t){if(n===t)return n;for(var e=ju(n),r=ju(t),u=e.pop(),i=r.pop(),o=null;u===i;)o=u,u=e.pop(),i=r.pop();return o}function Fu(n){n.fixed|=2}function Ou(n){n.fixed&=-7}function Yu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function Iu(n){n.fixed&=-5}function Zu(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,o=n.nodes,a=o.length,c=-1;++c<a;)i=o[c],null!=i&&(Zu(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var s=t*e[n.point.index];n.charge+=n.pointCharge=s,r+=s*n.point.x,u+=s*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function Vu(n,t){return Xo.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=Wu,n}function Xu(n){return n.children}function $u(n){return n.value}function Bu(n,t){return t.value-n.value}function Wu(n){return Xo.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function Ju(n){return n.x}function Gu(n){return n.y}function Ku(n,t,e){n.y0=t,n.y=e}function Qu(n){return Xo.range(n.length)}function ni(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function ti(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function ei(n){return n.reduce(ri,0)}function ri(n,t){return n+t[1]}function ui(n,t){return ii(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function ii(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function oi(n){return[Xo.min(n),Xo.max(n)]}function ai(n,t){return n.parent==t.parent?1:2}function ci(n){var t=n.children;return t&&t.length?t[0]:n._tree.thread}function si(n){var t,e=n.children;return e&&(t=e.length)?e[t-1]:n._tree.thread}function li(n,t){var e=n.children;if(e&&(u=e.length))for(var r,u,i=-1;++i<u;)t(r=li(e[i],t),n)>0&&(n=r);return n}function fi(n,t){return n.x-t.x}function hi(n,t){return t.x-n.x}function gi(n,t){return n.depth-t.depth}function pi(n,t){function e(n,r){var u=n.children;if(u&&(o=u.length))for(var i,o,a=null,c=-1;++c<o;)i=u[c],e(i,a),a=i;t(n,r)}e(n,null)}function vi(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i]._tree,t.prelim+=e,t.mod+=e,e+=t.shift+(r+=t.change)}function di(n,t,e){n=n._tree,t=t._tree;var r=e/(t.number-n.number);n.change+=r,t.change-=r,t.shift+=e,t.prelim+=e,t.mod+=e}function mi(n,t,e){return n._tree.ancestor.parent==t.parent?n._tree.ancestor:e}function yi(n,t){return n.value-t.value}function xi(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Mi(n,t){n._pack_next=t,t._pack_prev=n}function _i(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function bi(n){function t(n){l=Math.min(n.x-n.r,l),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(s=e.length)){var e,r,u,i,o,a,c,s,l=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(wi),r=e[0],r.x=-r.r,r.y=0,t(r),s>1&&(u=e[1],u.x=u.r,u.y=0,t(u),s>2))for(i=e[2],Ei(r,u,i),t(i),xi(r,i),r._pack_prev=i,xi(i,u),u=r._pack_next,o=3;s>o;o++){Ei(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(_i(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!_i(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?Mi(r,u=a):Mi(r=c,u),o--):(xi(r,i),u=i,t(i))}var m=(l+f)/2,y=(h+g)/2,x=0;for(o=0;s>o;o++)i=e[o],i.x-=m,i.y-=y,x=Math.max(x,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=x,e.forEach(Si)}}function wi(n){n._pack_next=n._pack_prev=n}function Si(n){delete n._pack_next,delete n._pack_prev}function ki(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i<o;)ki(u[i],t,e,r)}function Ei(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var o=t.r+e.r,a=u*u+i*i;o*=o,r*=r;var c=.5+(r-o)/(2*a),s=Math.sqrt(Math.max(0,2*o*(r+a)-(r-=a)*r-o*o))/(2*a);e.x=n.x+c*u+s*i,e.y=n.y+c*i-s*u}else e.x=n.x+r,e.y=n.y}function Ai(n){return 1+Xo.max(n,function(n){return n.y})}function Ci(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Ni(n){var t=n.children;return t&&t.length?Ni(t[0]):n}function Li(n){var t,e=n.children;return e&&(t=e.length)?Li(e[t-1]):n}function Ti(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function qi(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function zi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ri(n){return n.rangeExtent?n.rangeExtent():zi(n.range())}function Di(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Pi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Ui(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ls}function ji(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++o<=a;)u.push(e(n[o-1],n[o])),i.push(r(t[o-1],t[o]));return function(t){var e=Xo.bisect(n,t,1,a)-1;return i[e](u[e](t))}}function Hi(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?ji:Di,c=r?Pu:Du;return o=u(n,t,c,e),a=u(t,n,c,fu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Nu)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Ii(n,t)},i.tickFormat=function(t,e){return Zi(n,t,e)},i.nice=function(t){return Oi(n,t),u()},i.copy=function(){return Hi(n,t,e,r)},u()}function Fi(n,t){return Xo.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Oi(n,t){return Pi(n,Ui(Yi(n,t)[2]))}function Yi(n,t){null==t&&(t=10);var e=zi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Ii(n,t){return Xo.range.apply(Xo,Yi(n,t))}function Zi(n,t,e){var r=Yi(n,t);return Xo.format(e?e.replace(Qa,function(n,t,e,u,i,o,a,c,s,l){return[t,e,u,i,o,a,c,s||"."+Xi(l,r),l].join("")}):",."+Vi(r[2])+"f")}function Vi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Xi(n,t){var e=Vi(t[2]);return n in fs?Math.abs(e-Vi(Math.max(Math.abs(t[0]),Math.abs(t[1]))))+ +("e"!==n):e-2*("%"===n)}function $i(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Pi(r.map(u),e?Math:gs);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=zi(r),o=[],a=n[0],c=n[1],s=Math.floor(u(a)),l=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(l-s)){if(e){for(;l>s;s++)for(var h=1;f>h;h++)o.push(i(s)*h);o.push(i(s))}else for(o.push(i(s));s++<l;)for(var h=f-1;h>0;h--)o.push(i(s)*h);for(s=0;o[s]<a;s++);for(l=o.length;o[l-1]>c;l--);o=o.slice(s,l)}return o},o.tickFormat=function(n,t){if(!arguments.length)return hs;arguments.length<2?t=hs:"function"!=typeof t&&(t=Xo.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return $i(n.copy(),t,e,r)},Fi(o,n)}function Bi(n,t,e){function r(t){return n(u(t))}var u=Wi(t),i=Wi(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Ii(e,n)},r.tickFormat=function(n,t){return Zi(e,n,t)},r.nice=function(n){return r.domain(Oi(e,n))},r.exponent=function(o){return arguments.length?(u=Wi(t=o),i=Wi(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Bi(n.copy(),t,e)},Fi(r,n)}function Wi(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Ji(n,t){function e(e){return o[((i.get(e)||"range"===t.t&&i.set(e,n.push(e)))-1)%o.length]}function r(t,e){return Xo.range(n.length).map(function(n){return t+e*n})}var i,o,a;return e.domain=function(r){if(!arguments.length)return n;n=[],i=new u;for(var o,a=-1,c=r.length;++a<c;)i.has(o=r[a])||i.set(o,n.push(o));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(o=n,a=0,t={t:"range",a:arguments},e):o},e.rangePoints=function(u,i){arguments.length<2&&(i=0);var c=u[0],s=u[1],l=(s-c)/(Math.max(1,n.length-1)+i);return o=r(n.length<2?(c+s)/2:c+l*i/2,l),a=0,t={t:"rangePoints",a:arguments},e},e.rangeBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=(f-l)/(n.length-i+2*c);return o=r(l+h*c,h),s&&o.reverse(),a=h*(1-i),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,i,c){arguments.length<2&&(i=0),arguments.length<3&&(c=i);var s=u[1]<u[0],l=u[s-0],f=u[1-s],h=Math.floor((f-l)/(n.length-i+2*c)),g=f-l-(n.length-i)*h;return o=r(l+Math.round(g/2),h),s&&o.reverse(),a=Math.round(h*(1-i)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return zi(t.a[0])},e.copy=function(){return Ji(n,t)},e.domain(n)}function Gi(n,t){function e(){var e=0,i=t.length;for(u=[];++e<i;)u[e-1]=Xo.quantile(n,e/i);return r}function r(n){return isNaN(n=+n)?void 0:t[Xo.bisect(u,n)]}var u;return r.domain=function(t){return arguments.length?(n=t.filter(function(n){return!isNaN(n)}).sort(Xo.ascending),e()):n},r.range=function(n){return arguments.length?(t=n,e()):t},r.quantiles=function(){return u},r.invertExtent=function(e){return e=t.indexOf(e),0>e?[0/0,0/0]:[e>0?u[e-1]:n[0],e<u.length?u[e]:n[n.length-1]]},r.copy=function(){return Gi(n,t)},e()}function Ki(n,t,e){function r(t){return e[Math.max(0,Math.min(o,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),o=e.length-1,r}var i,o;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return Ki(n,t,e)},u()}function Qi(n,t){function e(e){return e>=e?t[Xo.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return Qi(n,t)},e}function no(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Ii(n,t)},t.tickFormat=function(t,e){return Zi(n,t,e)},t.copy=function(){return no(n)},t}function to(n){return n.innerRadius}function eo(n){return n.outerRadius}function ro(n){return n.startAngle}function uo(n){return n.endAngle}function io(n){function t(t){function o(){s.push("M",i(n(l),a))}for(var c,s=[],l=[],f=-1,h=t.length,g=_t(e),p=_t(r);++f<h;)u.call(this,c=t[f],f)?l.push([+g.call(this,c,f),+p.call(this,c,f)]):l.length&&(o(),l=[]);return l.length&&o(),s.length?s.join(""):null}var e=br,r=wr,u=be,i=oo,o=i.key,a=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(o="function"==typeof n?i=n:(i=Ms.get(n)||oo).key,t):o},t.tension=function(n){return arguments.length?(a=n,t):a},t}function oo(n){return n.join("L")}function ao(n){return oo(n)+"Z"}function co(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function so(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function lo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function fo(n,t){return n.length<4?oo(n):n[1]+po(n.slice(1,n.length-1),vo(n,t))}function ho(n,t){return n.length<3?oo(n):n[0]+po((n.push(n[0]),n),vo([n[n.length-2]].concat(n,[n[1]]),t))}function go(n,t){return n.length<3?oo(n):n[0]+po(n,vo(n,t))}function po(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return oo(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],o=t[0],a=o,c=1;if(e&&(r+="Q"+(i[0]-2*o[0]/3)+","+(i[1]-2*o[1]/3)+","+i[0]+","+i[1],u=n[1],c=2),t.length>1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var s=2;s<t.length;s++,c++)i=n[c],a=t[s],r+="S"+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1]}if(e){var l=n[c];r+="Q"+(i[0]+2*a[0]/3)+","+(i[1]+2*a[1]/3)+","+l[0]+","+l[1]}return r}function vo(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],o=n[1],a=1,c=n.length;++a<c;)e=i,i=o,o=n[a],r.push([u*(o[0]-e[0]),u*(o[1]-e[1])]);return r}function mo(n){if(n.length<3)return oo(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],o=[u,u,u,(r=n[1])[0]],a=[i,i,i,r[1]],c=[u,",",i,"L",_o(ws,o),",",_o(ws,a)];for(n.push(n[e-1]);++t<=e;)r=n[t],o.shift(),o.push(r[0]),a.shift(),a.push(r[1]),bo(c,o,a);return n.pop(),c.push("L",r),c.join("")}function yo(n){if(n.length<4)return oo(n);for(var t,e=[],r=-1,u=n.length,i=[0],o=[0];++r<3;)t=n[r],i.push(t[0]),o.push(t[1]);for(e.push(_o(ws,i)+","+_o(ws,o)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),o.shift(),o.push(t[1]),bo(e,i,o);return e.join("")}function xo(n){for(var t,e,r=-1,u=n.length,i=u+4,o=[],a=[];++r<4;)e=n[r%u],o.push(e[0]),a.push(e[1]);for(t=[_o(ws,o),",",_o(ws,a)],--r;++r<i;)e=n[r%u],o.shift(),o.push(e[0]),a.shift(),a.push(e[1]),bo(t,o,a);return t.join("")}function Mo(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],o=n[0][1],a=n[e][0]-i,c=n[e][1]-o,s=-1;++s<=e;)r=n[s],u=s/e,r[0]=t*r[0]+(1-t)*(i+u*a),r[1]=t*r[1]+(1-t)*(o+u*c);return mo(n)}function _o(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function bo(n,t,e){n.push("C",_o(_s,t),",",_o(_s,e),",",_o(bs,t),",",_o(bs,e),",",_o(ws,t),",",_o(ws,e))}function wo(n,t){return(t[1]-n[1])/(t[0]-n[0])}function So(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],o=r[0]=wo(u,i);++t<e;)r[t]=(o+(o=wo(u=i,i=n[t+1])))/2;return r[t]=o,r}function ko(n){for(var t,e,r,u,i=[],o=So(n),a=-1,c=n.length-1;++a<c;)t=wo(n[a],n[a+1]),oa(t)<Aa?o[a]=o[a+1]=0:(e=o[a]/t,r=o[a+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function Eo(n){return n.length<3?oo(n):n[0]+po(n,ko(n))}function Ao(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]+ys,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Co(n){function t(t){function c(){v.push("M",a(n(m),f),l,s(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,x=t.length,M=_t(e),_=_t(u),b=e===r?function(){return g}:_t(r),w=u===i?function(){return p}:_t(i);++y<x;)o.call(this,h=t[y],y)?(d.push([g=+M.call(this,h,y),p=+_.call(this,h,y)]),m.push([+b.call(this,h,y),+w.call(this,h,y)])):d.length&&(c(),d=[],m=[]);return d.length&&c(),v.length?v.join(""):null}var e=br,r=br,u=0,i=wr,o=be,a=oo,c=a.key,s=a,l="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(o=n,t):o},t.interpolate=function(n){return arguments.length?(c="function"==typeof n?a=n:(a=Ms.get(n)||oo).key,s=a.reverse||a,l=a.closed?"M":"L",t):c},t.tension=function(n){return arguments.length?(f=n,t):f},t}function No(n){return n.radius}function Lo(n){return[n.x,n.y]}function To(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]+ys;return[e*Math.cos(r),e*Math.sin(r)]}}function qo(){return 64}function zo(){return"circle"}function Ro(n){var t=Math.sqrt(n/Sa);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Do(n,t){return fa(n,Ns),n.id=t,n}function Po(n,t,e,r){var u=n.id;return R(n,"function"==typeof e?function(n,i,o){n.__transition__[u].tween.set(t,r(e.call(n,n.__data__,i,o)))}:(e=r(e),function(n){n.__transition__[u].tween.set(t,e)}))}function Uo(n){return null==n&&(n=""),function(){this.textContent=n}}function jo(n,t,e,r){var i=n.__transition__||(n.__transition__={active:0,count:0}),o=i[e];if(!o){var a=r.time;o=i[e]={tween:new u,time:a,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,Xo.timer(function(r){function u(r){return i.active>e?s():(i.active=e,o.event&&o.event.start.call(n,l,t),o.tween.forEach(function(e,r){(r=r.call(n,l,t))&&v.push(r)}),Xo.timer(function(){return p.c=c(r||1)?be:c,1},0,a),void 0)}function c(r){if(i.active!==e)return s();for(var u=r/g,a=f(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,l,t),s()):void 0}function s(){return--i.count?delete i[e]:delete n.__transition__,1}var l=n.__data__,f=o.ease,h=o.delay,g=o.duration,p=Ja,v=[];return p.t=h+a,r>=h?u(r-h):(p.c=u,void 0)},0,a)}}function Ho(n,t){n.attr("transform",function(n){return"translate("+t(n)+",0)"})}function Fo(n,t){n.attr("transform",function(n){return"translate(0,"+t(n)+")"})}function Oo(n){return n.toISOString()}function Yo(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=Xo.bisect(js,u);return i==js.length?[t.year,Yi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/js[i-1]<js[i]/u?i-1:i]:[Os,Yi(n,e)[2]]
-}return r.invert=function(t){return Io(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(Io)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,Io(+e+1),t).length}var i=r.domain(),o=zi(i),a=null==n?u(o,10):"number"==typeof n&&u(o,n);return a&&(n=a[0],t=a[1]),r.domain(Pi(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=Io(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Io(+t+1);return t}}:n))},r.ticks=function(n,t){var e=zi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Io(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Yo(n.copy(),t,e)},Fi(r,n)}function Io(n){return new Date(n)}function Zo(n){return JSON.parse(n.responseText)}function Vo(n){var t=Wo.createRange();return t.selectNode(Wo.body),t.createContextualFragment(n.responseText)}var Xo={version:"3.4.3"};Date.now||(Date.now=function(){return+new Date});var $o=[].slice,Bo=function(n){return $o.call(n)},Wo=document,Jo=Wo.documentElement,Go=window;try{Bo(Jo.childNodes)[0].nodeType}catch(Ko){Bo=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}try{Wo.createElement("div").style.setProperty("opacity",0,"")}catch(Qo){var na=Go.Element.prototype,ta=na.setAttribute,ea=na.setAttributeNS,ra=Go.CSSStyleDeclaration.prototype,ua=ra.setProperty;na.setAttribute=function(n,t){ta.call(this,n,t+"")},na.setAttributeNS=function(n,t,e){ea.call(this,n,t,e+"")},ra.setProperty=function(n,t,e){ua.call(this,n,t+"",e)}}Xo.ascending=function(n,t){return t>n?-1:n>t?1:n>=t?0:0/0},Xo.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},Xo.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},Xo.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i&&!(null!=(e=n[u])&&e>=e);)e=void 0;for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i&&!(null!=(e=t.call(n,n[u],u))&&e>=e);)e=void 0;for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},Xo.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i<o&&!(null!=(e=u=n[i])&&e>=e);)e=u=void 0;for(;++i<o;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<o&&!(null!=(e=u=t.call(n,n[i],i))&&e>=e);)e=void 0;for(;++i<o;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},Xo.sum=function(n,t){var e,r=0,u=n.length,i=-1;if(1===arguments.length)for(;++i<u;)isNaN(e=+n[i])||(r+=e);else for(;++i<u;)isNaN(e=+t.call(n,n[i],i))||(r+=e);return r},Xo.mean=function(t,e){var r,u=t.length,i=0,o=-1,a=0;if(1===arguments.length)for(;++o<u;)n(r=t[o])&&(i+=(r-i)/++a);else for(;++o<u;)n(r=e.call(t,t[o],o))&&(i+=(r-i)/++a);return a?i:void 0},Xo.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},Xo.median=function(t,e){return arguments.length>1&&(t=t.map(e)),t=t.filter(n),t.length?Xo.quantile(t.sort(Xo.ascending),.5):void 0},Xo.bisector=function(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n.call(t,t[i],i)<e?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;e<n.call(t,t[i],i)?u=i:r=i+1}return r}}};var ia=Xo.bisector(function(n){return n});Xo.bisectLeft=ia.left,Xo.bisect=Xo.bisectRight=ia.right,Xo.shuffle=function(n){for(var t,e,r=n.length;r;)e=0|Math.random()*r--,t=n[r],n[r]=n[e],n[e]=t;return n},Xo.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},Xo.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},Xo.zip=function(){if(!(u=arguments.length))return[];for(var n=-1,e=Xo.min(arguments,t),r=new Array(e);++n<e;)for(var u,i=-1,o=r[n]=new Array(u);++i<u;)o[i]=arguments[i][n];return r},Xo.transpose=function(n){return Xo.zip.apply(Xo,n)},Xo.keys=function(n){var t=[];for(var e in n)t.push(e);return t},Xo.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},Xo.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},Xo.merge=function(n){for(var t,e,r,u=n.length,i=-1,o=0;++i<u;)o+=n[i].length;for(e=new Array(o);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var oa=Math.abs;Xo.range=function(n,t,r){if(arguments.length<3&&(r=1,arguments.length<2&&(t=n,n=0)),1/0===(t-n)/r)throw new Error("infinite range");var u,i=[],o=e(oa(r)),a=-1;if(n*=o,t*=o,r*=o,0>r)for(;(u=n+r*++a)>t;)i.push(u/o);else for(;(u=n+r*++a)<t;)i.push(u/o);return i},Xo.map=function(n){var t=new u;if(n instanceof u)n.forEach(function(n,e){t.set(n,e)});else for(var e in n)t.set(e,n[e]);return t},r(u,{has:i,get:function(n){return this[aa+n]},set:function(n,t){return this[aa+n]=t},remove:o,keys:a,values:function(){var n=[];return this.forEach(function(t,e){n.push(e)}),n},entries:function(){var n=[];return this.forEach(function(t,e){n.push({key:t,value:e})}),n},size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1),this[t])}});var aa="\x00",ca=aa.charCodeAt(0);Xo.nest=function(){function n(t,a,c){if(c>=o.length)return r?r.call(i,a):e?a.sort(e):a;for(var s,l,f,h,g=-1,p=a.length,v=o[c++],d=new u;++g<p;)(h=d.get(s=v(l=a[g])))?h.push(l):d.set(s,[l]);return t?(l=t(),f=function(e,r){l.set(e,n(t,r,c))}):(l={},f=function(e,r){l[e]=n(t,r,c)}),d.forEach(f),l}function t(n,e){if(e>=o.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,i={},o=[],a=[];return i.map=function(t,e){return n(e,t,0)},i.entries=function(e){return t(n(Xo.map,e,0),0)},i.key=function(n){return o.push(n),i},i.sortKeys=function(n){return a[o.length-1]=n,i},i.sortValues=function(n){return e=n,i},i.rollup=function(n){return r=n,i},i},Xo.set=function(n){var t=new l;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},r(l,{has:i,add:function(n){return this[aa+n]=!0,n},remove:function(n){return n=aa+n,n in this&&delete this[n]},values:a,size:c,empty:s,forEach:function(n){for(var t in this)t.charCodeAt(0)===ca&&n.call(this,t.substring(1))}}),Xo.behavior={},Xo.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=f(n,t,t[e]);return n};var sa=["webkit","ms","moz","Moz","o","O"];Xo.dispatch=function(){for(var n=new p,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=v(n);return n},p.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.substring(e+1),n=n.substring(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},Xo.event=null,Xo.requote=function(n){return n.replace(la,"\\$&")};var la=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,fa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ha=function(n,t){return t.querySelector(n)},ga=function(n,t){return t.querySelectorAll(n)},pa=Jo[h(Jo,"matchesSelector")],va=function(n,t){return pa.call(n,t)};"function"==typeof Sizzle&&(ha=function(n,t){return Sizzle(n,t)[0]||null},ga=Sizzle,va=Sizzle.matchesSelector),Xo.selection=function(){return xa};var da=Xo.selection.prototype=[];da.select=function(n){var t,e,r,u,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]),t.parentNode=(r=this[o]).parentNode;for(var c=-1,s=r.length;++c<s;)(u=r[c])?(t.push(e=n.call(u,u.__data__,c,o)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return x(i)},da.selectAll=function(n){var t,e,r=[];n=_(n);for(var u=-1,i=this.length;++u<i;)for(var o=this[u],a=-1,c=o.length;++a<c;)(e=o[a])&&(r.push(t=Bo(n.call(e,e.__data__,a,u))),t.parentNode=e);return x(r)};var ma={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};Xo.ns={prefix:ma,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&(e=n.substring(0,t),n=n.substring(t+1)),ma.hasOwnProperty(e)?{space:ma[e],local:n}:n}},da.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=Xo.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(b(t,n[t]));return this}return this.each(b(n,t))},da.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=k(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!S(n[u]).test(t))return!1;return!0}for(t in n)this.each(E(t,n[t]));return this}return this.each(E(n,t))},da.style=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t="");for(e in n)this.each(C(e,n[e],t));return this}if(2>r)return Go.getComputedStyle(this.node(),null).getPropertyValue(n);e=""}return this.each(C(n,t,e))},da.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(N(t,n[t]));return this}return this.each(N(n,t))},da.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},da.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},da.append=function(n){return n=L(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},da.insert=function(n,t){return n=L(n),t=M(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},da.remove=function(){return this.each(function(){var n=this.parentNode;n&&n.removeChild(this)})},da.data=function(n,t){function e(n,e){var r,i,o,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new u,y=new u,x=[];for(r=-1;++r<a;)d=t.call(i=n[r],i.__data__,r),m.has(d)?v[r]=i:m.set(d,i),x.push(d);for(r=-1;++r<f;)d=t.call(e,o=e[r],r),(i=m.get(d))?(g[r]=i,i.__data__=o):y.has(d)||(p[r]=T(o)),y.set(d,o),m.remove(d);for(r=-1;++r<a;)m.has(x[r])&&(v[r]=n[r])}else{for(r=-1;++r<h;)i=n[r],o=e[r],i?(i.__data__=o,g[r]=i):p[r]=T(o);for(;f>r;++r)p[r]=T(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,c.push(p),s.push(g),l.push(v)}var r,i,o=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++o<a;)(i=r[o])&&(n[o]=i.__data__);return n}var c=D([]),s=x([]),l=x([]);if("function"==typeof n)for(;++o<a;)e(r=this[o],n.call(r,r.parentNode.__data__,o));else for(;++o<a;)e(r=this[o],n);return s.enter=function(){return c},s.exit=function(){return l},s},da.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},da.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return x(u)},da.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},da.sort=function(n){n=z.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},da.each=function(n){return R(this,function(t,e,r){n.call(t,t.__data__,e,r)})},da.call=function(n){var t=Bo(arguments);return n.apply(t[0]=this,t),this},da.empty=function(){return!this.node()},da.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},da.size=function(){var n=0;return this.each(function(){++n}),n};var ya=[];Xo.selection.enter=D,Xo.selection.enter.prototype=ya,ya.append=da.append,ya.empty=da.empty,ya.node=da.node,ya.call=da.call,ya.size=da.size,ya.select=function(n){for(var t,e,r,u,i,o=[],a=-1,c=this.length;++a<c;){r=(u=this[a]).update,o.push(t=[]),t.parentNode=u.parentNode;for(var s=-1,l=u.length;++s<l;)(i=u[s])?(t.push(r[s]=e=n.call(u.parentNode,i.__data__,s,a)),e.__data__=i.__data__):t.push(null)}return x(o)},ya.insert=function(n,t){return arguments.length<2&&(t=P(this)),da.insert.call(this,n,t)},da.transition=function(){for(var n,t,e=ks||++Ls,r=[],u=Es||{time:Date.now(),ease:yu,delay:0,duration:250},i=-1,o=this.length;++i<o;){r.push(n=[]);for(var a=this[i],c=-1,s=a.length;++c<s;)(t=a[c])&&jo(t,c,e,u),n.push(t)}return Do(r,e)},da.interrupt=function(){return this.each(U)},Xo.select=function(n){var t=["string"==typeof n?ha(n,Wo):n];return t.parentNode=Jo,x([t])},Xo.selectAll=function(n){var t=Bo("string"==typeof n?ga(n,Wo):n);return t.parentNode=Jo,x([t])};var xa=Xo.select(Jo);da.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(j(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(j(n,t,e))};var Ma=Xo.map({mouseenter:"mouseover",mouseleave:"mouseout"});Ma.forEach(function(n){"on"+n in Wo&&Ma.remove(n)});var _a="onselectstart"in Wo?null:h(Jo.style,"userSelect"),ba=0;Xo.mouse=function(n){return Y(n,m())};var wa=/WebKit/.test(Go.navigator.userAgent)?-1:0;Xo.touches=function(n,t){return arguments.length<2&&(t=m().touches),t?Bo(t).map(function(t){var e=Y(n,t);return e.identifier=t.identifier,e}):[]},Xo.behavior.drag=function(){function n(){this.on("mousedown.drag",o).on("touchstart.drag",a)}function t(){return Xo.event.changedTouches[0].identifier}function e(n,t){return Xo.touches(n).filter(function(n){return n.identifier===t})[0]}function r(n,t,e,r){return function(){function o(){var n=t(l,g),e=n[0]-v[0],r=n[1]-v[1];d|=e|r,v=n,f({type:"drag",x:n[0]+c[0],y:n[1]+c[1],dx:e,dy:r})}function a(){m.on(e+"."+p,null).on(r+"."+p,null),y(d&&Xo.event.target===h),f({type:"dragend"})}var c,s=this,l=s.parentNode,f=u.of(s,arguments),h=Xo.event.target,g=n(),p=null==g?"drag":"drag-"+g,v=t(l,g),d=0,m=Xo.select(Go).on(e+"."+p,o).on(r+"."+p,a),y=O();i?(c=i.apply(s,arguments),c=[c.x-v[0],c.y-v[1]]):c=[0,0],f({type:"dragstart"})}}var u=y(n,"drag","dragstart","dragend"),i=null,o=r(g,Xo.mouse,"mousemove","mouseup"),a=r(t,e,"touchmove","touchend");return n.origin=function(t){return arguments.length?(i=t,n):i},Xo.rebind(n,u,"on")};var Sa=Math.PI,ka=2*Sa,Ea=Sa/2,Aa=1e-6,Ca=Aa*Aa,Na=Sa/180,La=180/Sa,Ta=Math.SQRT2,qa=2,za=4;Xo.interpolateZoom=function(n,t){function e(n){var t=n*y;if(m){var e=B(v),o=i/(qa*h)*(e*W(Ta*t+v)-$(v));return[r+o*s,u+o*l,i*e/B(Ta*t+v)]}return[r+n*s,u+n*l,i*Math.exp(Ta*t)]}var r=n[0],u=n[1],i=n[2],o=t[0],a=t[1],c=t[2],s=o-r,l=a-u,f=s*s+l*l,h=Math.sqrt(f),g=(c*c-i*i+za*f)/(2*i*qa*h),p=(c*c-i*i-za*f)/(2*c*qa*h),v=Math.log(Math.sqrt(g*g+1)-g),d=Math.log(Math.sqrt(p*p+1)-p),m=d-v,y=(m||Math.log(c/i))/Ta;return e.duration=1e3*y,e},Xo.behavior.zoom=function(){function n(n){n.on(A,s).on(Pa+".zoom",f).on(C,h).on("dblclick.zoom",g).on(L,l)}function t(n){return[(n[0]-S.x)/S.k,(n[1]-S.y)/S.k]}function e(n){return[n[0]*S.k+S.x,n[1]*S.k+S.y]}function r(n){S.k=Math.max(E[0],Math.min(E[1],n))}function u(n,t){t=e(t),S.x+=n[0]-t[0],S.y+=n[1]-t[1]}function i(){_&&_.domain(M.range().map(function(n){return(n-S.x)/S.k}).map(M.invert)),w&&w.domain(b.range().map(function(n){return(n-S.y)/S.k}).map(b.invert))}function o(n){n({type:"zoomstart"})}function a(n){i(),n({type:"zoom",scale:S.k,translate:[S.x,S.y]})}function c(n){n({type:"zoomend"})}function s(){function n(){l=1,u(Xo.mouse(r),g),a(i)}function e(){f.on(C,Go===r?h:null).on(N,null),p(l&&Xo.event.target===s),c(i)}var r=this,i=T.of(r,arguments),s=Xo.event.target,l=0,f=Xo.select(Go).on(C,n).on(N,e),g=t(Xo.mouse(r)),p=O();U.call(r),o(i)}function l(){function n(){var n=Xo.touches(g);return h=S.k,n.forEach(function(n){n.identifier in v&&(v[n.identifier]=t(n))}),n}function e(){for(var t=Xo.event.changedTouches,e=0,i=t.length;i>e;++e)v[t[e].identifier]=null;var o=n(),c=Date.now();if(1===o.length){if(500>c-x){var s=o[0],l=v[s.identifier];r(2*S.k),u(s,l),d(),a(p)}x=c}else if(o.length>1){var s=o[0],f=o[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function i(){for(var n,t,e,i,o=Xo.touches(g),c=0,s=o.length;s>c;++c,i=null)if(e=o[c],i=v[e.identifier]){if(t)break;n=e,t=i}if(i){var l=(l=e[0]-n[0])*l+(l=e[1]-n[1])*l,f=m&&Math.sqrt(l/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+i[0])/2,(t[1]+i[1])/2],r(f*h)}x=null,u(n,t),a(p)}function f(){if(Xo.event.touches.length){for(var t=Xo.event.changedTouches,e=0,r=t.length;r>e;++e)delete v[t[e].identifier];for(var u in v)return void n()}b.on(M,null).on(_,null),w.on(A,s).on(L,l),k(),c(p)}var h,g=this,p=T.of(g,arguments),v={},m=0,y=Xo.event.changedTouches[0].identifier,M="touchmove.zoom-"+y,_="touchend.zoom-"+y,b=Xo.select(Go).on(M,i).on(_,f),w=Xo.select(g).on(A,null).on(L,e),k=O();U.call(g),e(),o(p)}function f(){var n=T.of(this,arguments);m?clearTimeout(m):(U.call(this),o(n)),m=setTimeout(function(){m=null,c(n)},50),d();var e=v||Xo.mouse(this);p||(p=t(e)),r(Math.pow(2,.002*Ra())*S.k),u(e,p),a(n)}function h(){p=null}function g(){var n=T.of(this,arguments),e=Xo.mouse(this),i=t(e),s=Math.log(S.k)/Math.LN2;o(n),r(Math.pow(2,Xo.event.shiftKey?Math.ceil(s)-1:Math.floor(s)+1)),u(e,i),a(n),c(n)}var p,v,m,x,M,_,b,w,S={x:0,y:0,k:1},k=[960,500],E=Da,A="mousedown.zoom",C="mousemove.zoom",N="mouseup.zoom",L="touchstart.zoom",T=y(n,"zoomstart","zoom","zoomend");return n.event=function(n){n.each(function(){var n=T.of(this,arguments),t=S;ks?Xo.select(this).transition().each("start.zoom",function(){S=this.__chart__||{x:0,y:0,k:1},o(n)}).tween("zoom:zoom",function(){var e=k[0],r=k[1],u=e/2,i=r/2,o=Xo.interpolateZoom([(u-S.x)/S.k,(i-S.y)/S.k,e/S.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=o(t),c=e/r[2];this.__chart__=S={x:u-r[0]*c,y:i-r[1]*c,k:c},a(n)}}).each("end.zoom",function(){c(n)}):(this.__chart__=S,o(n),a(n),c(n))})},n.translate=function(t){return arguments.length?(S={x:+t[0],y:+t[1],k:S.k},i(),n):[S.x,S.y]},n.scale=function(t){return arguments.length?(S={x:S.x,y:S.y,k:+t},i(),n):S.k},n.scaleExtent=function(t){return arguments.length?(E=null==t?Da:[+t[0],+t[1]],n):E},n.center=function(t){return arguments.length?(v=t&&[+t[0],+t[1]],n):v},n.size=function(t){return arguments.length?(k=t&&[+t[0],+t[1]],n):k},n.x=function(t){return arguments.length?(_=t,M=t.copy(),S={x:0,y:0,k:1},n):_},n.y=function(t){return arguments.length?(w=t,b=t.copy(),S={x:0,y:0,k:1},n):w},Xo.rebind(n,T,"on")};var Ra,Da=[0,1/0],Pa="onwheel"in Wo?(Ra=function(){return-Xo.event.deltaY*(Xo.event.deltaMode?120:1)},"wheel"):"onmousewheel"in Wo?(Ra=function(){return Xo.event.wheelDelta},"mousewheel"):(Ra=function(){return-Xo.event.detail},"MozMousePixelScroll");G.prototype.toString=function(){return this.rgb()+""},Xo.hsl=function(n,t,e){return 1===arguments.length?n instanceof Q?K(n.h,n.s,n.l):dt(""+n,mt,K):K(+n,+t,+e)};var Ua=Q.prototype=new G;Ua.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,this.l/n)},Ua.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),K(this.h,this.s,n*this.l)},Ua.rgb=function(){return nt(this.h,this.s,this.l)},Xo.hcl=function(n,t,e){return 1===arguments.length?n instanceof et?tt(n.h,n.c,n.l):n instanceof it?at(n.l,n.a,n.b):at((n=yt((n=Xo.rgb(n)).r,n.g,n.b)).l,n.a,n.b):tt(+n,+t,+e)};var ja=et.prototype=new G;ja.brighter=function(n){return tt(this.h,this.c,Math.min(100,this.l+Ha*(arguments.length?n:1)))},ja.darker=function(n){return tt(this.h,this.c,Math.max(0,this.l-Ha*(arguments.length?n:1)))},ja.rgb=function(){return rt(this.h,this.c,this.l).rgb()},Xo.lab=function(n,t,e){return 1===arguments.length?n instanceof it?ut(n.l,n.a,n.b):n instanceof et?rt(n.l,n.c,n.h):yt((n=Xo.rgb(n)).r,n.g,n.b):ut(+n,+t,+e)};var Ha=18,Fa=.95047,Oa=1,Ya=1.08883,Ia=it.prototype=new G;Ia.brighter=function(n){return ut(Math.min(100,this.l+Ha*(arguments.length?n:1)),this.a,this.b)},Ia.darker=function(n){return ut(Math.max(0,this.l-Ha*(arguments.length?n:1)),this.a,this.b)},Ia.rgb=function(){return ot(this.l,this.a,this.b)},Xo.rgb=function(n,t,e){return 1===arguments.length?n instanceof pt?gt(n.r,n.g,n.b):dt(""+n,gt,nt):gt(~~n,~~t,~~e)};var Za=pt.prototype=new G;Za.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),gt(Math.min(255,~~(t/n)),Math.min(255,~~(e/n)),Math.min(255,~~(r/n)))):gt(u,u,u)},Za.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),gt(~~(n*this.r),~~(n*this.g),~~(n*this.b))},Za.hsl=function(){return mt(this.r,this.g,this.b)},Za.toString=function(){return"#"+vt(this.r)+vt(this.g)+vt(this.b)};var Va=Xo.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});Va.forEach(function(n,t){Va.set(n,ft(t))}),Xo.functor=_t,Xo.xhr=wt(bt),Xo.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var o=St(n,t,null==e?r:u(e),i);return o.row=function(n){return arguments.length?o.response(null==(e=n)?r:u(n)):e},o}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(o).join(n)}function o(n){return a.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var a=new RegExp('["'+n+"\n]"),c=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(l>=s)return o;if(u)return u=!1,i;var t=l;if(34===n.charCodeAt(t)){for(var e=t;e++<s;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}l=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++l):10===r&&(u=!0),n.substring(t+1,e).replace(/""/g,'"')}for(;s>l;){var r=n.charCodeAt(l++),a=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(l)&&(++l,++a);else if(r!==c)continue;return n.substring(t,l-a)}return n.substring(t)}for(var r,u,i={},o={},a=[],s=n.length,l=0,f=0;(r=e())!==o;){for(var h=[];r!==i&&r!==o;)h.push(r),r=e();(!t||(h=t(h,f++)))&&a.push(h)}return a},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new l,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(o).join(n)].concat(t.map(function(t){return u.map(function(n){return o(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},Xo.csv=Xo.dsv(",","text/csv"),Xo.tsv=Xo.dsv("	","text/tab-separated-values");var Xa,$a,Ba,Wa,Ja,Ga=Go[h(Go,"requestAnimationFrame")]||function(n){setTimeout(n,17)};Xo.timer=function(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,f:!1,n:null};$a?$a.n=i:Xa=i,$a=i,Ba||(Wa=clearTimeout(Wa),Ba=1,Ga(Et))},Xo.timer.flush=function(){At(),Ct()},Xo.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var Ka=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(Lt);Xo.formatPrefix=function(n,t){var e=0;return n&&(0>n&&(n*=-1),t&&(n=Xo.round(n,Nt(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Ka[8+e/3]};var Qa=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,nc=Xo.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=Xo.round(n,Nt(n,t))).toFixed(Math.max(0,Math.min(20,Nt(n*(1+1e-15),t))))}}),tc=Xo.time={},ec=Date;zt.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){rc.setUTCDate.apply(this._,arguments)},setDay:function(){rc.setUTCDay.apply(this._,arguments)},setFullYear:function(){rc.setUTCFullYear.apply(this._,arguments)},setHours:function(){rc.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){rc.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){rc.setUTCMinutes.apply(this._,arguments)},setMonth:function(){rc.setUTCMonth.apply(this._,arguments)},setSeconds:function(){rc.setUTCSeconds.apply(this._,arguments)},setTime:function(){rc.setTime.apply(this._,arguments)}};var rc=Date.prototype;tc.year=Rt(function(n){return n=tc.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),tc.years=tc.year.range,tc.years.utc=tc.year.utc.range,tc.day=Rt(function(n){var t=new ec(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),tc.days=tc.day.range,tc.days.utc=tc.day.utc.range,tc.dayOfYear=function(n){var t=tc.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=tc[n]=Rt(function(n){return(n=tc.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});tc[n+"s"]=e.range,tc[n+"s"].utc=e.utc.range,tc[n+"OfYear"]=function(n){var e=tc.year(n).getDay();return Math.floor((tc.dayOfYear(n)+(e+t)%7)/7)}}),tc.week=tc.sunday,tc.weeks=tc.sunday.range,tc.weeks.utc=tc.sunday.utc.range,tc.weekOfYear=tc.sundayOfYear;var uc={"-":"",_:" ",0:"0"},ic=/^\s*\d+/,oc=/^%/;Xo.locale=function(n){return{numberFormat:Tt(n),timeFormat:Pt(n)}};var ac=Xo.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});Xo.format=ac.numberFormat,Xo.geo={},re.prototype={s:0,t:0,add:function(n){ue(n,this.t,cc),ue(cc.s,this.s,this),this.s?this.t+=cc.t:this.s=cc.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var cc=new re;Xo.geo.stream=function(n,t){n&&sc.hasOwnProperty(n.type)?sc[n.type](n,t):ie(n,t)};var sc={Feature:function(n,t){ie(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)ie(e[r].geometry,t)}},lc={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){oe(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)oe(e[r],t,0)},Polygon:function(n,t){ae(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)ae(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)ie(e[r],t)}};Xo.geo.area=function(n){return fc=0,Xo.geo.stream(n,gc),fc};var fc,hc=new re,gc={sphere:function(){fc+=4*Sa},point:g,lineStart:g,lineEnd:g,polygonStart:function(){hc.reset(),gc.lineStart=ce},polygonEnd:function(){var n=2*hc;fc+=0>n?4*Sa+n:n,gc.lineStart=gc.lineEnd=gc.point=g}};Xo.geo.bounds=function(){function n(n,t){x.push(M=[l=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=se([t*Na,e*Na]);if(m){var u=fe(m,r),i=[u[1],-u[0],0],o=fe(i,u);pe(o),o=ve(o);var c=t-p,s=c>0?1:-1,v=o[0]*La*s,d=oa(c)>180;if(d^(v>s*p&&s*t>v)){var y=o[1]*La;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>s*p&&s*t>v)){var y=-o[1]*La;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t):h>=l?(l>t&&(l=t),t>h&&(h=t)):t>p?a(l,t)>a(l,h)&&(h=t):a(t,h)>a(l,h)&&(l=t)}else n(t,e);m=r,p=t}function e(){_.point=t}function r(){M[0]=l,M[1]=h,_.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=oa(r)>180?r+(r>0?360:-360):r}else v=n,d=e;gc.point(n,e),t(n,e)}function i(){gc.lineStart()}function o(){u(v,d),gc.lineEnd(),oa(y)>Aa&&(l=-(h=180)),M[0]=l,M[1]=h,m=null}function a(n,t){return(t-=n)<0?t+360:t}function c(n,t){return n[0]-t[0]}function s(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var l,f,h,g,p,v,d,m,y,x,M,_={point:n,lineStart:e,lineEnd:r,polygonStart:function(){_.point=u,_.lineStart=i,_.lineEnd=o,y=0,gc.polygonStart()},polygonEnd:function(){gc.polygonEnd(),_.point=n,_.lineStart=e,_.lineEnd=r,0>hc?(l=-(h=180),f=-(g=90)):y>Aa?g=90:-Aa>y&&(f=-90),M[0]=l,M[1]=h}};return function(n){g=h=-(l=f=1/0),x=[],Xo.geo.stream(n,_);
-var t=x.length;if(t){x.sort(c);for(var e,r=1,u=x[0],i=[u];t>r;++r)e=x[r],s(e[0],u)||s(e[1],u)?(a(u[0],e[1])>a(u[0],u[1])&&(u[1]=e[1]),a(e[0],u[1])>a(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var o,e,p=-1/0,t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(o=a(u[1],e[0]))>p&&(p=o,l=e[0],h=u[1])}return x=M=null,1/0===l||1/0===f?[[0/0,0/0],[0/0,0/0]]:[[l,f],[h,g]]}}(),Xo.geo.centroid=function(n){pc=vc=dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,kc);var t=bc,e=wc,r=Sc,u=t*t+e*e+r*r;return Ca>u&&(t=xc,e=Mc,r=_c,Aa>vc&&(t=dc,e=mc,r=yc),u=t*t+e*e+r*r,Ca>u)?[0/0,0/0]:[Math.atan2(e,t)*La,X(r/Math.sqrt(u))*La]};var pc,vc,dc,mc,yc,xc,Mc,_c,bc,wc,Sc,kc={sphere:g,point:me,lineStart:xe,lineEnd:Me,polygonStart:function(){kc.lineStart=_e},polygonEnd:function(){kc.lineStart=xe}},Ec=Ee(be,Te,ze,[-Sa,-Sa/2]),Ac=1e9;Xo.geo.clipExtent=function(){var n,t,e,r,u,i,o={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(a){return arguments.length?(i=Pe(n=+a[0][0],t=+a[0][1],e=+a[1][0],r=+a[1][1]),u&&(u.valid=!1,u=null),o):[[n,t],[e,r]]}};return o.extent([[0,0],[960,500]])},(Xo.geo.conicEqualArea=function(){return je(He)}).raw=He,Xo.geo.albers=function(){return Xo.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},Xo.geo.albersUsa=function(){function n(n){var i=n[0],o=n[1];return t=null,e(i,o),t||(r(i,o),t)||u(i,o),t}var t,e,r,u,i=Xo.geo.albers(),o=Xo.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),a=Xo.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),c={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?o:u>=.166&&.234>u&&r>=-.214&&-.115>r?a:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=o.stream(n),r=a.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),o.precision(t),a.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),o.scale(.35*t),a.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var s=i.scale(),l=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[l-.455*s,f-.238*s],[l+.455*s,f+.238*s]]).stream(c).point,r=o.translate([l-.307*s,f+.201*s]).clipExtent([[l-.425*s+Aa,f+.12*s+Aa],[l-.214*s-Aa,f+.234*s-Aa]]).stream(c).point,u=a.translate([l-.205*s,f+.212*s]).clipExtent([[l-.214*s+Aa,f+.166*s+Aa],[l-.115*s-Aa,f+.234*s-Aa]]).stream(c).point,n},n.scale(1070)};var Cc,Nc,Lc,Tc,qc,zc,Rc={point:g,lineStart:g,lineEnd:g,polygonStart:function(){Nc=0,Rc.lineStart=Fe},polygonEnd:function(){Rc.lineStart=Rc.lineEnd=Rc.point=g,Cc+=oa(Nc/2)}},Dc={point:Oe,lineStart:g,lineEnd:g,polygonStart:g,polygonEnd:g},Pc={point:Ze,lineStart:Ve,lineEnd:Xe,polygonStart:function(){Pc.lineStart=$e},polygonEnd:function(){Pc.point=Ze,Pc.lineStart=Ve,Pc.lineEnd=Xe}};Xo.geo.path=function(){function n(n){return n&&("function"==typeof a&&i.pointRadius(+a.apply(this,arguments)),o&&o.valid||(o=u(i)),Xo.geo.stream(n,o)),i.result()}function t(){return o=null,n}var e,r,u,i,o,a=4.5;return n.area=function(n){return Cc=0,Xo.geo.stream(n,u(Rc)),Cc},n.centroid=function(n){return dc=mc=yc=xc=Mc=_c=bc=wc=Sc=0,Xo.geo.stream(n,u(Pc)),Sc?[bc/Sc,wc/Sc]:_c?[xc/_c,Mc/_c]:yc?[dc/yc,mc/yc]:[0/0,0/0]},n.bounds=function(n){return qc=zc=-(Lc=Tc=1/0),Xo.geo.stream(n,u(Dc)),[[Lc,Tc],[qc,zc]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||Je(n):bt,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Ye:new Be(n),"function"!=typeof a&&i.pointRadius(a),t()):r},n.pointRadius=function(t){return arguments.length?(a="function"==typeof t?t:(i.pointRadius(+t),+t),n):a},n.projection(Xo.geo.albersUsa()).context(null)},Xo.geo.transform=function(n){return{stream:function(t){var e=new Ge(t);for(var r in n)e[r]=n[r];return e}}},Ge.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},Xo.geo.projection=Qe,Xo.geo.projectionMutator=nr,(Xo.geo.equirectangular=function(){return Qe(er)}).raw=er.invert=er,Xo.geo.rotation=function(n){function t(t){return t=n(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t}return n=ur(n[0]%360*Na,n[1]*Na,n.length>2?n[2]*Na:0),t.invert=function(t){return t=n.invert(t[0]*Na,t[1]*Na),t[0]*=La,t[1]*=La,t},t},rr.invert=er,Xo.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=ur(-n[0]*Na,-n[1]*Na,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=La,n[1]*=La}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=cr((t=+r)*Na,u*Na),n):t},n.precision=function(r){return arguments.length?(e=cr(t*Na,(u=+r)*Na),n):u},n.angle(90)},Xo.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Na,u=n[1]*Na,i=t[1]*Na,o=Math.sin(r),a=Math.cos(r),c=Math.sin(u),s=Math.cos(u),l=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*o)*e+(e=s*l-c*f*a)*e),c*l+s*f*a)},Xo.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return Xo.range(Math.ceil(i/d)*d,u,d).map(h).concat(Xo.range(Math.ceil(s/m)*m,c,m).map(g)).concat(Xo.range(Math.ceil(r/p)*p,e,p).filter(function(n){return oa(n%d)>Aa}).map(l)).concat(Xo.range(Math.ceil(a/v)*v,o,v).filter(function(n){return oa(n%m)>Aa}).map(f))}var e,r,u,i,o,a,c,s,l,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(c).slice(1),h(u).reverse().slice(1),g(s).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],s=+t[0][1],c=+t[1][1],i>u&&(t=i,i=u,u=t),s>c&&(t=s,s=c,c=t),n.precision(y)):[[i,s],[u,c]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],a=+t[0][1],o=+t[1][1],r>e&&(t=r,r=e,e=t),a>o&&(t=a,a=o,o=t),n.precision(y)):[[r,a],[e,o]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,l=lr(a,o,90),f=fr(r,e,y),h=lr(s,c,90),g=fr(i,u,y),n):y},n.majorExtent([[-180,-90+Aa],[180,90-Aa]]).minorExtent([[-180,-80-Aa],[180,80+Aa]])},Xo.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=hr,u=gr;return n.distance=function(){return Xo.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},Xo.geo.interpolate=function(n,t){return pr(n[0]*Na,n[1]*Na,t[0]*Na,t[1]*Na)},Xo.geo.length=function(n){return Uc=0,Xo.geo.stream(n,jc),Uc};var Uc,jc={sphere:g,point:g,lineStart:vr,lineEnd:g,polygonStart:g,polygonEnd:g},Hc=dr(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(Xo.geo.azimuthalEqualArea=function(){return Qe(Hc)}).raw=Hc;var Fc=dr(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},bt);(Xo.geo.azimuthalEquidistant=function(){return Qe(Fc)}).raw=Fc,(Xo.geo.conicConformal=function(){return je(mr)}).raw=mr,(Xo.geo.conicEquidistant=function(){return je(yr)}).raw=yr;var Oc=dr(function(n){return 1/n},Math.atan);(Xo.geo.gnomonic=function(){return Qe(Oc)}).raw=Oc,xr.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ea]},(Xo.geo.mercator=function(){return Mr(xr)}).raw=xr;var Yc=dr(function(){return 1},Math.asin);(Xo.geo.orthographic=function(){return Qe(Yc)}).raw=Yc;var Ic=dr(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(Xo.geo.stereographic=function(){return Qe(Ic)}).raw=Ic,_r.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ea]},(Xo.geo.transverseMercator=function(){var n=Mr(_r),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[-n[1],n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},n.rotate([0,0])}).raw=_r,Xo.geom={},Xo.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=_t(e),i=_t(r),o=n.length,a=[],c=[];for(t=0;o>t;t++)a.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(a.sort(kr),t=0;o>t;t++)c.push([a[t][0],-a[t][1]]);var s=Sr(a),l=Sr(c),f=l[0]===s[0],h=l[l.length-1]===s[s.length-1],g=[];for(t=s.length-1;t>=0;--t)g.push(n[a[s[t]][2]]);for(t=+f;t<l.length-h;++t)g.push(n[a[l[t]][2]]);return g}var e=br,r=wr;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},Xo.geom.polygon=function(n){return fa(n,Zc),n};var Zc=Xo.geom.polygon.prototype=[];Zc.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},Zc.centroid=function(n){var t,e,r=-1,u=this.length,i=0,o=0,a=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=a,a=this[r],e=t[0]*a[1]-a[0]*t[1],i+=(t[0]+a[0])*e,o+=(t[1]+a[1])*e;return[i*n,o*n]},Zc.clip=function(n){for(var t,e,r,u,i,o,a=Cr(n),c=-1,s=this.length-Cr(this),l=this[s-1];++c<s;){for(t=n.slice(),n.length=0,u=this[c],i=t[(r=t.length-a)-1],e=-1;++e<r;)o=t[e],Er(o,l,u)?(Er(i,l,u)||n.push(Ar(i,o,l,u)),n.push(o)):Er(i,l,u)&&n.push(Ar(i,o,l,u)),i=o;a&&n.push(n[0]),l=u}return n};var Vc,Xc,$c,Bc,Wc,Jc=[],Gc=[];Pr.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(jr),t.length},Br.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},Wr.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=Qr(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(Gr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Kr(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(Kr(this,e),n=e,e=n.U),e.C=!1,r.C=!0,Gr(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,o=n.R;if(e=i?o?Qr(o):i:o,u?u.L===n?u.L=e:u.R=e:this._=e,i&&o?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==o?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=o,o.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return n.C=!1,void 0;do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,Gr(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,Kr(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,Gr(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,Kr(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,Gr(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,Kr(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},Xo.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=a[0][0],u=a[0][1],i=a[1][0],o=a[1][1];return nu(e(n),a).cells.forEach(function(e,a){var c=e.edges,s=e.site,l=t[a]=c.length?c.map(function(n){var t=n.start();return[t.x,t.y]}):s.x>=r&&s.x<=i&&s.y>=u&&s.y<=o?[[r,o],[i,o],[i,u],[r,u]]:[];l.point=n[a]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Aa)*Aa,y:Math.round(o(n,t)/Aa)*Aa,i:t}})}var r=br,u=wr,i=r,o=u,a=Kc;return n?t(n):(t.links=function(n){return nu(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return nu(e(n)).cells.forEach(function(e,r){for(var u,i,o=e.site,a=e.edges.sort(jr),c=-1,s=a.length,l=a[s-1].edge,f=l.l===o?l.r:l.l;++c<s;)u=l,i=f,l=a[c].edge,f=l.l===o?l.r:l.l,r<i.i&&r<f.i&&eu(o,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=_t(r=n),t):r},t.y=function(n){return arguments.length?(o=_t(u=n),t):u},t.clipExtent=function(n){return arguments.length?(a=null==n?Kc:n,t):a===Kc?null:a},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):a===Kc?null:a&&a[1]},t)};var Kc=[[-1e6,-1e6],[1e6,1e6]];Xo.geom.delaunay=function(n){return Xo.geom.voronoi().triangles(n)},Xo.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,o,a){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var c=n.x,l=n.y;if(null!=c)if(oa(c-e)+oa(l-r)<.01)s(n,t,e,r,u,i,o,a);else{var f=n.point;n.x=n.y=n.point=null,s(n,f,c,l,u,i,o,a),s(n,t,e,r,u,i,o,a)}else n.x=e,n.y=r,n.point=t}else s(n,t,e,r,u,i,o,a)}function s(n,t,e,r,u,o,a,c){var s=.5*(u+a),l=.5*(o+c),f=e>=s,h=r>=l,g=(h<<1)+f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=iu()),f?u=s:a=s,h?o=l:c=l,i(n,t,e,r,u,o,a,c)}var l,f,h,g,p,v,d,m,y,x=_t(a),M=_t(c);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,o)for(g=0;p>g;++g)l=n[g],l.x<v&&(v=l.x),l.y<d&&(d=l.y),l.x>m&&(m=l.x),l.y>y&&(y=l.y),f.push(l.x),h.push(l.y);else for(g=0;p>g;++g){var _=+x(l=n[g],g),b=+M(l,g);v>_&&(v=_),d>b&&(d=b),_>m&&(m=_),b>y&&(y=b),f.push(_),h.push(b)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=iu();if(k.add=function(n){i(k,n,+x(n,++g),+M(n,g),v,d,m,y)},k.visit=function(n){ou(n,k,v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=l=null,k}var o,a=br,c=wr;return(o=arguments.length)?(a=ru,c=uu,3===o&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(a=n,i):a},i.y=function(n){return arguments.length?(c=n,i):c},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},Xo.interpolateRgb=au,Xo.interpolateObject=cu,Xo.interpolateNumber=su,Xo.interpolateString=lu;var Qc=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;Xo.interpolate=fu,Xo.interpolators=[function(n,t){var e=typeof t;return("string"===e?Va.has(t)||/^(#|rgb\(|hsl\()/.test(t)?au:lu:t instanceof G?au:"object"===e?Array.isArray(t)?hu:cu:su)(n,t)}],Xo.interpolateArray=hu;var ns=function(){return bt},ts=Xo.map({linear:ns,poly:xu,quad:function(){return du},cubic:function(){return mu},sin:function(){return Mu},exp:function(){return _u},circle:function(){return bu},elastic:wu,back:Su,bounce:function(){return ku}}),es=Xo.map({"in":bt,out:pu,"in-out":vu,"out-in":function(n){return vu(pu(n))}});Xo.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.substring(0,t):n,r=t>=0?n.substring(t+1):"in";return e=ts.get(e)||ns,r=es.get(r)||bt,gu(r(e.apply(null,$o.call(arguments,1))))},Xo.interpolateHcl=Eu,Xo.interpolateHsl=Au,Xo.interpolateLab=Cu,Xo.interpolateRound=Nu,Xo.transform=function(n){var t=Wo.createElementNS(Xo.ns.prefix.svg,"g");return(Xo.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Lu(e?e.matrix:rs)})(n)},Lu.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var rs={a:1,b:0,c:0,d:1,e:0,f:0};Xo.interpolateTransform=Ru,Xo.layout={},Xo.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Uu(n[e]));return t}},Xo.layout.chord=function(){function n(){var n,s,f,h,g,p={},v=[],d=Xo.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(s=0,g=-1;++g<i;)s+=u[h][g];v.push(s),m.push(Xo.range(i)),n+=s}for(o&&d.sort(function(n,t){return o(v[n],v[t])}),a&&m.forEach(function(n,t){n.sort(function(n,e){return a(u[t][n],u[t][e])})}),n=(ka-l*i)/n,s=0,h=-1;++h<i;){for(f=s,g=-1;++g<i;){var y=d[h],x=m[y][g],M=u[y][x],_=s,b=s+=M*n;p[y+"-"+x]={index:y,subindex:x,startAngle:_,endAngle:b,value:M}}r[y]={index:y,startAngle:f,endAngle:s,value:(s-f)/n},s+=l}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&t()}function t(){e.sort(function(n,t){return c((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,o,a,c,s={},l=0;return s.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,s):u},s.padding=function(n){return arguments.length?(l=n,e=r=null,s):l},s.sortGroups=function(n){return arguments.length?(o=n,e=r=null,s):o},s.sortSubgroups=function(n){return arguments.length?(a=n,e=null,s):a},s.sortChords=function(n){return arguments.length?(c=n,e&&t(),s):c},s.chords=function(){return e||n(),e},s.groups=function(){return r||n(),r},s},Xo.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,o=t.cy-n.y,a=u-e,c=i*i+o*o;if(c>a*a/d){if(p>c){var s=t.charge/c;n.px-=i*s,n.py-=o*s}return!0}if(t.point&&c&&p>c){var s=t.pointCharge/c;n.px-=i*s,n.py-=o*s}}return!t.charge}}function t(n){n.px=Xo.event.x,n.py=Xo.event.y,a.resume()}var e,r,u,i,o,a={},c=Xo.dispatch("start","tick","end"),s=[1,1],l=.9,f=us,h=is,g=-30,p=os,v=.1,d=.64,m=[],y=[];return a.tick=function(){if((r*=.99)<.005)return c.end({type:"end",alpha:r=0}),!0;var t,e,a,f,h,p,d,x,M,_=m.length,b=y.length;for(e=0;b>e;++e)a=y[e],f=a.source,h=a.target,x=h.x-f.x,M=h.y-f.y,(p=x*x+M*M)&&(p=r*i[e]*((p=Math.sqrt(p))-u[e])/p,x*=p,M*=p,h.x-=x*(d=f.weight/(h.weight+f.weight)),h.y-=M*d,f.x+=x*(d=1-d),f.y+=M*d);if((d=r*v)&&(x=s[0]/2,M=s[1]/2,e=-1,d))for(;++e<_;)a=m[e],a.x+=(x-a.x)*d,a.y+=(M-a.y)*d;if(g)for(Zu(t=Xo.geom.quadtree(m),r,o),e=-1;++e<_;)(a=m[e]).fixed||t.visit(n(a));for(e=-1;++e<_;)a=m[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*l,a.y-=(a.py-(a.py=a.y))*l);c.tick({type:"tick",alpha:r})},a.nodes=function(n){return arguments.length?(m=n,a):m},a.links=function(n){return arguments.length?(y=n,a):y},a.size=function(n){return arguments.length?(s=n,a):s},a.linkDistance=function(n){return arguments.length?(f="function"==typeof n?n:+n,a):f},a.distance=a.linkDistance,a.linkStrength=function(n){return arguments.length?(h="function"==typeof n?n:+n,a):h},a.friction=function(n){return arguments.length?(l=+n,a):l},a.charge=function(n){return arguments.length?(g="function"==typeof n?n:+n,a):g},a.chargeDistance=function(n){return arguments.length?(p=n*n,a):Math.sqrt(p)},a.gravity=function(n){return arguments.length?(v=+n,a):v},a.theta=function(n){return arguments.length?(d=n*n,a):Math.sqrt(d)},a.alpha=function(n){return arguments.length?(n=+n,r?r=n>0?n:0:n>0&&(c.start({type:"start",alpha:r=n}),Xo.timer(a.tick)),a):r},a.start=function(){function n(n,r){if(!e){for(e=new Array(c),a=0;c>a;++a)e[a]=[];for(a=0;s>a;++a){var u=y[a];e[u.source.index].push(u.target),e[u.target.index].push(u.source)}}for(var i,o=e[t],a=-1,s=o.length;++a<s;)if(!isNaN(i=o[a][n]))return i;return Math.random()*r}var t,e,r,c=m.length,l=y.length,p=s[0],v=s[1];for(t=0;c>t;++t)(r=m[t]).index=t,r.weight=0;for(t=0;l>t;++t)r=y[t],"number"==typeof r.source&&(r.source=m[r.source]),"number"==typeof r.target&&(r.target=m[r.target]),++r.source.weight,++r.target.weight;for(t=0;c>t;++t)r=m[t],isNaN(r.x)&&(r.x=n("x",p)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(u=[],"function"==typeof f)for(t=0;l>t;++t)u[t]=+f.call(this,y[t],t);else for(t=0;l>t;++t)u[t]=f;if(i=[],"function"==typeof h)for(t=0;l>t;++t)i[t]=+h.call(this,y[t],t);else for(t=0;l>t;++t)i[t]=h;if(o=[],"function"==typeof g)for(t=0;c>t;++t)o[t]=+g.call(this,m[t],t);else for(t=0;c>t;++t)o[t]=g;return a.resume()},a.resume=function(){return a.alpha(.1)},a.stop=function(){return a.alpha(0)},a.drag=function(){return e||(e=Xo.behavior.drag().origin(bt).on("dragstart.force",Fu).on("drag.force",t).on("dragend.force",Ou)),arguments.length?(this.on("mouseover.force",Yu).on("mouseout.force",Iu).call(e),void 0):e},Xo.rebind(a,c,"on")};var us=20,is=1,os=1/0;Xo.layout.hierarchy=function(){function n(t,o,a){var c=u.call(e,t,o);if(t.depth=o,a.push(t),c&&(s=c.length)){for(var s,l,f=-1,h=t.children=new Array(s),g=0,p=o+1;++f<s;)l=h[f]=n(c[f],p,a),l.parent=t,g+=l.value;r&&h.sort(r),i&&(t.value=g)}else delete t.children,i&&(t.value=+i.call(e,t,o)||0);return t}function t(n,r){var u=n.children,o=0;if(u&&(a=u.length))for(var a,c=-1,s=r+1;++c<a;)o+=t(u[c],s);else i&&(o=+i.call(e,n,r)||0);return i&&(n.value=o),o}function e(t){var e=[];return n(t,0,e),e}var r=Bu,u=Xu,i=$u;return e.sort=function(n){return arguments.length?(r=n,e):r},e.children=function(n){return arguments.length?(u=n,e):u},e.value=function(n){return arguments.length?(i=n,e):i},e.revalue=function(n){return t(n,0),n},e},Xo.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(o=i.length)){var o,a,c,s=-1;for(r=t.value?r/t.value:0;++s<o;)n(a=i[s],e,c=a.value*r,u),e+=c}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var o=r.call(this,e,i);return n(o[0],0,u[0],u[1]/t(o[0])),o}var r=Xo.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},Vu(e,r)},Xo.layout.pie=function(){function n(i){var o=i.map(function(e,r){return+t.call(n,e,r)}),a=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof u?u.apply(this,arguments):u)-a)/Xo.sum(o),s=Xo.range(i.length);null!=e&&s.sort(e===as?function(n,t){return o[t]-o[n]}:function(n,t){return e(i[n],i[t])});var l=[];return s.forEach(function(n){var t;l[n]={data:i[n],value:t=o[n],startAngle:a,endAngle:a+=t*c}}),l}var t=Number,e=as,r=0,u=ka;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n};var as={};Xo.layout.stack=function(){function n(a,c){var s=a.map(function(e,r){return t.call(n,e,r)}),l=s.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),o.call(n,t,e)]})}),f=e.call(n,l,c);s=Xo.permute(s,f),l=Xo.permute(l,f);var h,g,p,v=r.call(n,l,c),d=s.length,m=s[0].length;for(g=0;m>g;++g)for(u.call(n,s[0][g],p=v[g],l[0][g][1]),h=1;d>h;++h)u.call(n,s[h][g],p+=l[h-1][g][1],l[h][g][1]);return a}var t=bt,e=Qu,r=ni,u=Ku,i=Ju,o=Gu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:cs.get(t)||Qu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:ss.get(t)||ni,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(o=t,n):o},n.out=function(t){return arguments.length?(u=t,n):u},n};var cs=Xo.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(ti),i=n.map(ei),o=Xo.range(r).sort(function(n,t){return u[n]-u[t]}),a=0,c=0,s=[],l=[];for(t=0;r>t;++t)e=o[t],c>a?(a+=i[e],s.push(e)):(c+=i[e],l.push(e));return l.reverse().concat(s)},reverse:function(n){return Xo.range(n.length).reverse()},"default":Qu}),ss=Xo.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,o=[],a=0,c=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>a&&(a=r),o.push(r)}for(e=0;i>e;++e)c[e]=(a-o[e])/2;return c},wiggle:function(n){var t,e,r,u,i,o,a,c,s,l=n.length,f=n[0],h=f.length,g=[];for(g[0]=c=s=0,e=1;h>e;++e){for(t=0,u=0;l>t;++t)u+=n[t][e][1];for(t=0,i=0,a=f[e][0]-f[e-1][0];l>t;++t){for(r=0,o=(n[t][e][1]-n[t][e-1][1])/(2*a);t>r;++r)o+=(n[r][e][1]-n[r][e-1][1])/a;i+=o*n[t][e][1]}g[e]=c-=u?i/u*a:0,s>c&&(s=c)}for(e=0;h>e;++e)g[e]-=s;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,o=1/u,a=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=o}for(e=0;i>e;++e)a[e]=0;return a},zero:ni});Xo.layout.histogram=function(){function n(n,i){for(var o,a,c=[],s=n.map(e,this),l=r.call(this,s,i),f=u.call(this,l,s,i),i=-1,h=s.length,g=f.length-1,p=t?1:1/h;++i<g;)o=c[i]=[],o.dx=f[i+1]-(o.x=f[i]),o.y=0;if(g>0)for(i=-1;++i<h;)a=s[i],a>=l[0]&&a<=l[1]&&(o=c[Xo.bisect(f,a,1,g)-1],o.y+=p,o.push(n[i]));return c}var t=!0,e=Number,r=oi,u=ui;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=_t(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return ii(n,t)}:_t(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},Xo.layout.tree=function(){function n(n,i){function o(n,t){var r=n.children,u=n._tree;if(r&&(i=r.length)){for(var i,a,s,l=r[0],f=l,h=-1;++h<i;)s=r[h],o(s,a),f=c(s,a,f),a=s;vi(n);var g=.5*(l._tree.prelim+s._tree.prelim);t?(u.prelim=t._tree.prelim+e(n,t),u.mod=u.prelim-g):u.prelim=g}else t&&(u.prelim=t._tree.prelim+e(n,t))}function a(n,t){n.x=n._tree.prelim+t;var e=n.children;if(e&&(r=e.length)){var r,u=-1;for(t+=n._tree.mod;++u<r;)a(e[u],t)}}function c(n,t,r){if(t){for(var u,i=n,o=n,a=t,c=n.parent.children[0],s=i._tree.mod,l=o._tree.mod,f=a._tree.mod,h=c._tree.mod;a=si(a),i=ci(i),a&&i;)c=ci(c),o=si(o),o._tree.ancestor=n,u=a._tree.prelim+f-i._tree.prelim-s+e(a,i),u>0&&(di(mi(a,n,r),n,u),s+=u,l+=u),f+=a._tree.mod,s+=i._tree.mod,h+=c._tree.mod,l+=o._tree.mod;a&&!si(o)&&(o._tree.thread=a,o._tree.mod+=f-l),i&&!ci(c)&&(c._tree.thread=i,c._tree.mod+=s-h,r=n)}return r}var s=t.call(this,n,i),l=s[0];pi(l,function(n,t){n._tree={ancestor:n,prelim:0,mod:0,change:0,shift:0,number:t?t._tree.number+1:0}}),o(l),a(l,-l._tree.prelim);var f=li(l,hi),h=li(l,fi),g=li(l,gi),p=f.x-e(f,h)/2,v=h.x+e(h,f)/2,d=g.depth||1;return pi(l,u?function(n){n.x*=r[0],n.y=n.depth*r[1],delete n._tree}:function(n){n.x=(n.x-p)/(v-p)*r[0],n.y=n.depth/d*r[1],delete n._tree}),s}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.pack=function(){function n(n,i){var o=e.call(this,n,i),a=o[0],c=u[0],s=u[1],l=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(a.x=a.y=0,pi(a,function(n){n.r=+l(n.value)}),pi(a,bi),r){var f=r*(t?1:Math.max(2*a.r/c,2*a.r/s))/2;pi(a,function(n){n.r+=f}),pi(a,bi),pi(a,function(n){n.r-=f})}return ki(a,c/2,s/2,t?1:1/Math.max(2*a.r/c,2*a.r/s)),o}var t,e=Xo.layout.hierarchy().sort(yi),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},Vu(n,e)},Xo.layout.cluster=function(){function n(n,i){var o,a=t.call(this,n,i),c=a[0],s=0;pi(c,function(n){var t=n.children;t&&t.length?(n.x=Ci(t),n.y=Ai(t)):(n.x=o?s+=e(n,o):0,n.y=0,o=n)});var l=Ni(c),f=Li(c),h=l.x-e(l,f)/2,g=f.x+e(f,l)/2;return pi(c,u?function(n){n.x=(n.x-c.x)*r[0],n.y=(c.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(c.y?n.y/c.y:1))*r[1]}),a}var t=Xo.layout.hierarchy().sort(null).value(null),e=ai,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},Vu(n,t)},Xo.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var o,a,c,s=f(e),l=[],h=i.slice(),p=1/0,v="slice"===g?s.dx:"dice"===g?s.dy:"slice-dice"===g?1&e.depth?s.dy:s.dx:Math.min(s.dx,s.dy);for(n(h,s.dx*s.dy/e.value),l.area=0;(c=h.length)>0;)l.push(o=h[c-1]),l.area+=o.area,"squarify"!==g||(a=r(l,v))<=p?(h.pop(),p=a):(l.area-=l.pop().area,u(l,v,s,!1),v=Math.min(s.dx,s.dy),l.length=l.area=0,p=1/0);l.length&&(u(l,v,s,!0),l.length=l.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,o=f(t),a=r.slice(),c=[];for(n(a,o.dx*o.dy/t.value),c.area=0;i=a.pop();)c.push(i),c.area+=i.area,null!=i.z&&(u(c,i.z?o.dx:o.dy,o,!a.length),c.length=c.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,o=-1,a=n.length;++o<a;)(e=n[o].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,o=n.length,a=e.x,s=e.y,l=t?c(n.area/t):0;if(t==e.dx){for((r||l>e.dy)&&(l=e.dy);++i<o;)u=n[i],u.x=a,u.y=s,u.dy=l,a+=u.dx=Math.min(e.x+e.dx-a,l?c(u.area/l):0);u.z=!0,u.dx+=e.x+e.dx-a,e.y+=l,e.dy-=l}else{for((r||l>e.dx)&&(l=e.dx);++i<o;)u=n[i],u.x=a,u.y=s,u.dx=l,s+=u.dy=Math.min(e.y+e.dy-s,l?c(u.area/l):0);u.z=!1,u.dy+=e.y+e.dy-s,e.x+=l,e.dx-=l}}function i(r){var u=o||a(r),i=u[0];return i.x=0,i.y=0,i.dx=s[0],i.dy=s[1],o&&a.revalue(i),n([i],i.dx*i.dy/i.value),(o?e:t)(i),h&&(o=u),u}var o,a=Xo.layout.hierarchy(),c=Math.round,s=[1,1],l=null,f=Ti,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(s=n,i):s},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ti(t):qi(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return qi(t,n)}if(!arguments.length)return l;var r;return f=null==(l=n)?Ti:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(c=n?Math.round:Number,i):c!=Number},i.sticky=function(n){return arguments.length?(h=n,o=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},Vu(i,a)},Xo.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=Xo.random.normal.apply(Xo,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=Xo.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},Xo.scale={};var ls={floor:bt,ceil:bt};Xo.scale.linear=function(){return Hi([0,1],[0,1],fu,!1)};var fs={s:1,g:1,p:1,r:1,e:1};Xo.scale.log=function(){return $i(Xo.scale.linear().domain([0,1]),10,!0,[1,10])};var hs=Xo.format(".0e"),gs={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};Xo.scale.pow=function(){return Bi(Xo.scale.linear(),1,[0,1])},Xo.scale.sqrt=function(){return Xo.scale.pow().exponent(.5)},Xo.scale.ordinal=function(){return Ji([],{t:"range",a:[[]]})},Xo.scale.category10=function(){return Xo.scale.ordinal().range(ps)},Xo.scale.category20=function(){return Xo.scale.ordinal().range(vs)},Xo.scale.category20b=function(){return Xo.scale.ordinal().range(ds)},Xo.scale.category20c=function(){return Xo.scale.ordinal().range(ms)};var ps=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(ht),vs=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(ht),ds=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(ht),ms=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(ht);Xo.scale.quantile=function(){return Gi([],[])},Xo.scale.quantize=function(){return Ki(0,1,[0,1])},Xo.scale.threshold=function(){return Qi([.5],[0,1])
-},Xo.scale.identity=function(){return no([0,1])},Xo.svg={},Xo.svg.arc=function(){function n(){var n=t.apply(this,arguments),i=e.apply(this,arguments),o=r.apply(this,arguments)+ys,a=u.apply(this,arguments)+ys,c=(o>a&&(c=o,o=a,a=c),a-o),s=Sa>c?"0":"1",l=Math.cos(o),f=Math.sin(o),h=Math.cos(a),g=Math.sin(a);return c>=xs?n?"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"M0,"+n+"A"+n+","+n+" 0 1,0 0,"+-n+"A"+n+","+n+" 0 1,0 0,"+n+"Z":"M0,"+i+"A"+i+","+i+" 0 1,1 0,"+-i+"A"+i+","+i+" 0 1,1 0,"+i+"Z":n?"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L"+n*h+","+n*g+"A"+n+","+n+" 0 "+s+",0 "+n*l+","+n*f+"Z":"M"+i*l+","+i*f+"A"+i+","+i+" 0 "+s+",1 "+i*h+","+i*g+"L0,0"+"Z"}var t=to,e=eo,r=ro,u=uo;return n.innerRadius=function(e){return arguments.length?(t=_t(e),n):t},n.outerRadius=function(t){return arguments.length?(e=_t(t),n):e},n.startAngle=function(t){return arguments.length?(r=_t(t),n):r},n.endAngle=function(t){return arguments.length?(u=_t(t),n):u},n.centroid=function(){var n=(t.apply(this,arguments)+e.apply(this,arguments))/2,i=(r.apply(this,arguments)+u.apply(this,arguments))/2+ys;return[Math.cos(i)*n,Math.sin(i)*n]},n};var ys=-Ea,xs=ka-Aa;Xo.svg.line=function(){return io(bt)};var Ms=Xo.map({linear:oo,"linear-closed":ao,step:co,"step-before":so,"step-after":lo,basis:mo,"basis-open":yo,"basis-closed":xo,bundle:Mo,cardinal:go,"cardinal-open":fo,"cardinal-closed":ho,monotone:Eo});Ms.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var _s=[0,2/3,1/3,0],bs=[0,1/3,2/3,0],ws=[0,1/6,2/3,1/6];Xo.svg.line.radial=function(){var n=io(Ao);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},so.reverse=lo,lo.reverse=so,Xo.svg.area=function(){return Co(bt)},Xo.svg.area.radial=function(){var n=Co(Ao);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},Xo.svg.chord=function(){function n(n,a){var c=t(this,i,n,a),s=t(this,o,n,a);return"M"+c.p0+r(c.r,c.p1,c.a1-c.a0)+(e(c,s)?u(c.r,c.p1,c.r,c.p0):u(c.r,c.p1,s.r,s.p0)+r(s.r,s.p1,s.a1-s.a0)+u(s.r,s.p1,c.r,c.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=a.call(n,u,r),o=c.call(n,u,r)+ys,l=s.call(n,u,r)+ys;return{r:i,a0:o,a1:l,p0:[i*Math.cos(o),i*Math.sin(o)],p1:[i*Math.cos(l),i*Math.sin(l)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>Sa)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=hr,o=gr,a=No,c=ro,s=uo;return n.radius=function(t){return arguments.length?(a=_t(t),n):a},n.source=function(t){return arguments.length?(i=_t(t),n):i},n.target=function(t){return arguments.length?(o=_t(t),n):o},n.startAngle=function(t){return arguments.length?(c=_t(t),n):c},n.endAngle=function(t){return arguments.length?(s=_t(t),n):s},n},Xo.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),o=e.call(this,n,u),a=(i.y+o.y)/2,c=[i,{x:i.x,y:a},{x:o.x,y:a},o];return c=c.map(r),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var t=hr,e=gr,r=Lo;return n.source=function(e){return arguments.length?(t=_t(e),n):t},n.target=function(t){return arguments.length?(e=_t(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},Xo.svg.diagonal.radial=function(){var n=Xo.svg.diagonal(),t=Lo,e=n.projection;return n.projection=function(n){return arguments.length?e(To(t=n)):t},n},Xo.svg.symbol=function(){function n(n,r){return(Ss.get(t.call(this,n,r))||Ro)(e.call(this,n,r))}var t=zo,e=qo;return n.type=function(e){return arguments.length?(t=_t(e),n):t},n.size=function(t){return arguments.length?(e=_t(t),n):e},n};var Ss=Xo.map({circle:Ro,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Cs)),e=t*Cs;return"M0,"+-t+"L"+e+",0"+" 0,"+t+" "+-e+",0"+"Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/As),e=t*As/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});Xo.svg.symbolTypes=Ss.keys();var ks,Es,As=Math.sqrt(3),Cs=Math.tan(30*Na),Ns=[],Ls=0;Ns.call=da.call,Ns.empty=da.empty,Ns.node=da.node,Ns.size=da.size,Xo.transition=function(n){return arguments.length?ks?n.transition():n:xa.transition()},Xo.transition.prototype=Ns,Ns.select=function(n){var t,e,r,u=this.id,i=[];n=M(n);for(var o=-1,a=this.length;++o<a;){i.push(t=[]);for(var c=this[o],s=-1,l=c.length;++s<l;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),jo(e,s,u,r.__transition__[u]),t.push(e)):t.push(null)}return Do(i,u)},Ns.selectAll=function(n){var t,e,r,u,i,o=this.id,a=[];n=_(n);for(var c=-1,s=this.length;++c<s;)for(var l=this[c],f=-1,h=l.length;++f<h;)if(r=l[f]){i=r.__transition__[o],e=n.call(r,r.__data__,f,c),a.push(t=[]);for(var g=-1,p=e.length;++g<p;)(u=e[g])&&jo(u,g,o,i),t.push(u)}return Do(a,o)},Ns.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=q(n));for(var i=0,o=this.length;o>i;i++){u.push(t=[]);for(var e=this[i],a=0,c=e.length;c>a;a++)(r=e[a])&&n.call(r,r.__data__,a,i)&&t.push(r)}return Do(u,this.id)},Ns.tween=function(n,t){var e=this.id;return arguments.length<2?this.node().__transition__[e].tween.get(n):R(this,null==t?function(t){t.__transition__[e].tween.remove(n)}:function(r){r.__transition__[e].tween.set(n,t)})},Ns.attr=function(n,t){function e(){this.removeAttribute(a)}function r(){this.removeAttributeNS(a.space,a.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(a);return e!==n&&(t=o(e,n),function(n){this.setAttribute(a,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(a.space,a.local);return e!==n&&(t=o(e,n),function(n){this.setAttributeNS(a.space,a.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var o="transform"==n?Ru:fu,a=Xo.ns.qualify(n);return Po(this,"attr."+n,t,a.local?i:u)},Ns.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=Xo.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Ns.style=function(n,t,e){function r(){this.style.removeProperty(n)}function u(t){return null==t?r:(t+="",function(){var r,u=Go.getComputedStyle(this,null).getPropertyValue(n);return u!==t&&(r=fu(u,t),function(t){this.style.setProperty(n,r(t),e)})})}var i=arguments.length;if(3>i){if("string"!=typeof n){2>i&&(t="");for(e in n)this.style(e,n[e],t);return this}e=""}return Po(this,"style."+n,t,u)},Ns.styleTween=function(n,t,e){function r(r,u){var i=t.call(this,r,u,Go.getComputedStyle(this,null).getPropertyValue(n));return i&&function(t){this.style.setProperty(n,i(t),e)}}return arguments.length<3&&(e=""),this.tween("style."+n,r)},Ns.text=function(n){return Po(this,"text",n,Uo)},Ns.remove=function(){return this.each("end.transition",function(){var n;this.__transition__.count<2&&(n=this.parentNode)&&n.removeChild(this)})},Ns.ease=function(n){var t=this.id;return arguments.length<1?this.node().__transition__[t].ease:("function"!=typeof n&&(n=Xo.ease.apply(Xo,arguments)),R(this,function(e){e.__transition__[t].ease=n}))},Ns.delay=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].delay=+n.call(e,e.__data__,r,u)}:(n=+n,function(e){e.__transition__[t].delay=n}))},Ns.duration=function(n){var t=this.id;return R(this,"function"==typeof n?function(e,r,u){e.__transition__[t].duration=Math.max(1,n.call(e,e.__data__,r,u))}:(n=Math.max(1,n),function(e){e.__transition__[t].duration=n}))},Ns.each=function(n,t){var e=this.id;if(arguments.length<2){var r=Es,u=ks;ks=e,R(this,function(t,r,u){Es=t.__transition__[e],n.call(t,t.__data__,r,u)}),Es=r,ks=u}else R(this,function(r){var u=r.__transition__[e];(u.event||(u.event=Xo.dispatch("start","end"))).on(n,t)});return this},Ns.transition=function(){for(var n,t,e,r,u=this.id,i=++Ls,o=[],a=0,c=this.length;c>a;a++){o.push(n=[]);for(var t=this[a],s=0,l=t.length;l>s;s++)(e=t[s])&&(r=Object.create(e.__transition__[u]),r.delay+=r.duration,jo(e,s,i,r)),n.push(e)}return Do(o,i)},Xo.svg.axis=function(){function n(n){n.each(function(){var n,s=Xo.select(this),l=this.__chart__||e,f=this.__chart__=e.copy(),h=null==c?f.ticks?f.ticks.apply(f,a):f.domain():c,g=null==t?f.tickFormat?f.tickFormat.apply(f,a):bt:t,p=s.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Aa),d=Xo.transition(p.exit()).style("opacity",Aa).remove(),m=Xo.transition(p).style("opacity",1),y=Ri(f),x=s.selectAll(".domain").data([0]),M=(x.enter().append("path").attr("class","domain"),Xo.transition(x));v.append("line"),v.append("text");var _=v.select("line"),b=m.select("line"),w=p.select("text").text(g),S=v.select("text"),k=m.select("text");switch(r){case"bottom":n=Ho,_.attr("y2",u),S.attr("y",Math.max(u,0)+o),b.attr("x2",0).attr("y2",u),k.attr("x",0).attr("y",Math.max(u,0)+o),w.attr("dy",".71em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+i+"V0H"+y[1]+"V"+i);break;case"top":n=Ho,_.attr("y2",-u),S.attr("y",-(Math.max(u,0)+o)),b.attr("x2",0).attr("y2",-u),k.attr("x",0).attr("y",-(Math.max(u,0)+o)),w.attr("dy","0em").style("text-anchor","middle"),M.attr("d","M"+y[0]+","+-i+"V0H"+y[1]+"V"+-i);break;case"left":n=Fo,_.attr("x2",-u),S.attr("x",-(Math.max(u,0)+o)),b.attr("x2",-u).attr("y2",0),k.attr("x",-(Math.max(u,0)+o)).attr("y",0),w.attr("dy",".32em").style("text-anchor","end"),M.attr("d","M"+-i+","+y[0]+"H0V"+y[1]+"H"+-i);break;case"right":n=Fo,_.attr("x2",u),S.attr("x",Math.max(u,0)+o),b.attr("x2",u).attr("y2",0),k.attr("x",Math.max(u,0)+o).attr("y",0),w.attr("dy",".32em").style("text-anchor","start"),M.attr("d","M"+i+","+y[0]+"H0V"+y[1]+"H"+i)}if(f.rangeBand){var E=f,A=E.rangeBand()/2;l=f=function(n){return E(n)+A}}else l.rangeBand?l=f:d.call(n,f);v.call(n,l),m.call(n,f)})}var t,e=Xo.scale.linear(),r=Ts,u=6,i=6,o=3,a=[10],c=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in qs?t+"":Ts,n):r},n.ticks=function(){return arguments.length?(a=arguments,n):a},n.tickValues=function(t){return arguments.length?(c=t,n):c},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(o=+t,n):o},n.tickSubdivide=function(){return arguments.length&&n},n};var Ts="bottom",qs={top:1,right:1,bottom:1,left:1};Xo.svg.brush=function(){function n(i){i.each(function(){var i=Xo.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",u).on("touchstart.brush",u),o=i.selectAll(".background").data([0]);o.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),i.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var a=i.selectAll(".resize").data(p,bt);a.exit().remove(),a.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return zs[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),a.style("display",n.empty()?"none":null);var l,f=Xo.transition(i),h=Xo.transition(o);c&&(l=Ri(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),e(f)),s&&(l=Ri(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),r(f)),t(f)})}function t(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+l[+/e$/.test(n)]+","+f[+/^s/.test(n)]+")"})}function e(n){n.select(".extent").attr("x",l[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",l[1]-l[0])}function r(n){n.select(".extent").attr("y",f[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",f[1]-f[0])}function u(){function u(){32==Xo.event.keyCode&&(C||(x=null,L[0]-=l[1],L[1]-=f[1],C=2),d())}function p(){32==Xo.event.keyCode&&2==C&&(L[0]+=l[1],L[1]+=f[1],C=0,d())}function v(){var n=Xo.mouse(_),u=!1;M&&(n[0]+=M[0],n[1]+=M[1]),C||(Xo.event.altKey?(x||(x=[(l[0]+l[1])/2,(f[0]+f[1])/2]),L[0]=l[+(n[0]<x[0])],L[1]=f[+(n[1]<x[1])]):x=null),E&&m(n,c,0)&&(e(S),u=!0),A&&m(n,s,1)&&(r(S),u=!0),u&&(t(S),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,a=Ri(t),c=a[0],s=a[1],p=L[e],v=e?f:l,d=v[1]-v[0];return C&&(c-=p,s-=d+p),r=(e?g:h)?Math.max(c,Math.min(s,n[e])):n[e],C?u=(r+=p)+d:(x&&(p=Math.max(c,Math.min(s,2*x[e]-r))),r>p?(u=r,r=p):u=p),v[0]!=r||v[1]!=u?(e?o=null:i=null,v[0]=r,v[1]=u,!0):void 0}function y(){v(),S.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),Xo.select("body").style("cursor",null),T.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),N(),w({type:"brushend"})}var x,M,_=this,b=Xo.select(Xo.event.target),w=a.of(_,arguments),S=Xo.select(_),k=b.datum(),E=!/^(n|s)$/.test(k)&&c,A=!/^(e|w)$/.test(k)&&s,C=b.classed("extent"),N=O(),L=Xo.mouse(_),T=Xo.select(Go).on("keydown.brush",u).on("keyup.brush",p);if(Xo.event.changedTouches?T.on("touchmove.brush",v).on("touchend.brush",y):T.on("mousemove.brush",v).on("mouseup.brush",y),S.interrupt().selectAll("*").interrupt(),C)L[0]=l[0]-L[0],L[1]=f[0]-L[1];else if(k){var q=+/w$/.test(k),z=+/^n/.test(k);M=[l[1-q]-L[0],f[1-z]-L[1]],L[0]=l[q],L[1]=f[z]}else Xo.event.altKey&&(x=L.slice());S.style("pointer-events","none").selectAll(".resize").style("display",null),Xo.select("body").style("cursor",b.style("cursor")),w({type:"brushstart"}),v()}var i,o,a=y(n,"brushstart","brush","brushend"),c=null,s=null,l=[0,0],f=[0,0],h=!0,g=!0,p=Rs[0];return n.event=function(n){n.each(function(){var n=a.of(this,arguments),t={x:l,y:f,i:i,j:o},e=this.__chart__||t;this.__chart__=t,ks?Xo.select(this).transition().each("start.brush",function(){i=e.i,o=e.j,l=e.x,f=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=hu(l,t.x),r=hu(f,t.y);return i=o=null,function(u){l=t.x=e(u),f=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){i=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,p=Rs[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,p=Rs[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(h=!!t[0],g=!!t[1]):c?h=!!t:s&&(g=!!t),n):c&&s?[h,g]:c?h:s?g:null},n.extent=function(t){var e,r,u,a,h;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),i=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(h=e,e=r,r=h),(e!=l[0]||r!=l[1])&&(l=[e,r])),s&&(u=t[0],a=t[1],c&&(u=u[1],a=a[1]),o=[u,a],s.invert&&(u=s(u),a=s(a)),u>a&&(h=u,u=a,a=h),(u!=f[0]||a!=f[1])&&(f=[u,a])),n):(c&&(i?(e=i[0],r=i[1]):(e=l[0],r=l[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(h=e,e=r,r=h))),s&&(o?(u=o[0],a=o[1]):(u=f[0],a=f[1],s.invert&&(u=s.invert(u),a=s.invert(a)),u>a&&(h=u,u=a,a=h))),c&&s?[[e,u],[r,a]]:c?[e,r]:s&&[u,a])},n.clear=function(){return n.empty()||(l=[0,0],f=[0,0],i=o=null),n},n.empty=function(){return!!c&&l[0]==l[1]||!!s&&f[0]==f[1]},Xo.rebind(n,a,"on")};var zs={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},Rs=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Ds=tc.format=ac.timeFormat,Ps=Ds.utc,Us=Ps("%Y-%m-%dT%H:%M:%S.%LZ");Ds.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?Oo:Us,Oo.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},Oo.toString=Us.toString,tc.second=Rt(function(n){return new ec(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),tc.seconds=tc.second.range,tc.seconds.utc=tc.second.utc.range,tc.minute=Rt(function(n){return new ec(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),tc.minutes=tc.minute.range,tc.minutes.utc=tc.minute.utc.range,tc.hour=Rt(function(n){var t=n.getTimezoneOffset()/60;return new ec(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),tc.hours=tc.hour.range,tc.hours.utc=tc.hour.utc.range,tc.month=Rt(function(n){return n=tc.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),tc.months=tc.month.range,tc.months.utc=tc.month.utc.range;var js=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Hs=[[tc.second,1],[tc.second,5],[tc.second,15],[tc.second,30],[tc.minute,1],[tc.minute,5],[tc.minute,15],[tc.minute,30],[tc.hour,1],[tc.hour,3],[tc.hour,6],[tc.hour,12],[tc.day,1],[tc.day,2],[tc.week,1],[tc.month,1],[tc.month,3],[tc.year,1]],Fs=Ds.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",be]]),Os={range:function(n,t,e){return Xo.range(Math.ceil(n/e)*e,+t,e).map(Io)},floor:bt,ceil:bt};Hs.year=tc.year,tc.scale=function(){return Yo(Xo.scale.linear(),Hs,Fs)};var Ys=Hs.map(function(n){return[n[0].utc,n[1]]}),Is=Ps.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",be]]);Ys.year=tc.year.utc,tc.scale.utc=function(){return Yo(Xo.scale.linear(),Ys,Is)},Xo.text=wt(function(n){return n.responseText}),Xo.json=function(n,t){return St(n,"application/json",Zo,t)},Xo.html=function(n,t){return St(n,"text/html",Vo,t)},Xo.xml=wt(function(n){return n.responseXML}),"function"==typeof define&&define.amd?define(Xo):"object"==typeof module&&module.exports?module.exports=Xo:this.d3=Xo}();
\ No newline at end of file
diff --git a/tools/telemetry/unittest_data/test_page_set.py b/tools/telemetry/unittest_data/test_page_set.py
new file mode 100644
index 0000000..fb0d0fb
--- /dev/null
+++ b/tools/telemetry/unittest_data/test_page_set.py
@@ -0,0 +1,25 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page.page_set import PageSet
+from telemetry.page.page import Page
+
+class TestPageSet(PageSet):
+  def __init__(self):
+    super(TestPageSet, self).__init__(
+      description='A pageset for testing purpose',
+      archive_data_file='data/test.json',
+      credentials_path='data/credential',
+      user_agent_type='desktop')
+
+    #top google property; a google tab is often open
+    class Google(Page):
+      def __init__(self):
+        super(Google, self).__init__('https://www.google.com')
+
+      def RunGetActionRunner(self, action_runner):
+        return action_runner
+
+    self.AddPage(Google())
+
diff --git a/tools/telemetry/unittest_data/test_simple_one_page_set.py b/tools/telemetry/unittest_data/test_simple_one_page_set.py
new file mode 100644
index 0000000..98782e3
--- /dev/null
+++ b/tools/telemetry/unittest_data/test_simple_one_page_set.py
@@ -0,0 +1,13 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page.page_set import PageSet
+
+class TestSimpleOnePageSet(PageSet):
+  def __init__(self):
+    super(TestSimpleOnePageSet, self).__init__(
+      description='A pageset for testing purpose',
+      archive_data_file='data/test.json',
+      credentials_path='data/credential',
+      user_agent_type='desktop')
diff --git a/tools/telemetry/unittest_data/test_simple_two_page_set.py b/tools/telemetry/unittest_data/test_simple_two_page_set.py
new file mode 100644
index 0000000..7947771
--- /dev/null
+++ b/tools/telemetry/unittest_data/test_simple_two_page_set.py
@@ -0,0 +1,13 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from telemetry.page.page_set import PageSet
+
+class TestSimpleTwoPageSet(PageSet):
+  def __init__(self):
+    super(TestSimpleTwoPageSet, self).__init__(
+      description='A pageset for testing purpose',
+      archive_data_file='data/test.json',
+      credentials_path='data/credential',
+      user_agent_type='desktop')
diff --git a/tools/valgrind/drmemory/suppressions.txt b/tools/valgrind/drmemory/suppressions.txt
index 033aaad..c8f014b 100644
--- a/tools/valgrind/drmemory/suppressions.txt
+++ b/tools/valgrind/drmemory/suppressions.txt
@@ -445,10 +445,6 @@
 skia.dll!SkDraw::drawPosText
 skia.dll!SkBitmapDevice::drawPosText
 skia.dll!SkCanvas::drawPosText
-gfx.dll!gfx::internal::SkiaTextRenderer::DrawPosText
-gfx.dll!gfx::RenderTextWin::DrawVisualText
-gfx.dll!gfx::RenderText::Draw
-gfx.dll!gfx::Canvas::DrawStringRectWithShadows
 
 HANDLE LEAK
 name=http://crbug.com/346993
diff --git a/tools/valgrind/gtest_exclude/base_unittests.gtest.txt b/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
index 35c209d..aa85c27 100644
--- a/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
+++ b/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
@@ -24,3 +24,6 @@
 
 # Flaky under Valgrind, see http://crbug.com/55517
 PlatformFile.TouchGetInfoPlatformFile
+
+# Crashes under Valgrind, see http://crbug.com/355436
+OutOfMemoryHandledTest.Unchecked*
diff --git a/tools/valgrind/gtest_exclude/media_unittests.gtest_mac.txt b/tools/valgrind/gtest_exclude/media_unittests.gtest_mac.txt
new file mode 100644
index 0000000..138864b
--- /dev/null
+++ b/tools/valgrind/gtest_exclude/media_unittests.gtest_mac.txt
@@ -0,0 +1,3 @@
+# Crashes under Valgrind on Mac, http://crbug.com/344108
+VideoCaptureDeviceTest.FakeCapture
+VideoCaptureDeviceTest.FakeCaptureVariableResolution
diff --git a/tools/valgrind/memcheck/suppressions.txt b/tools/valgrind/memcheck/suppressions.txt
index 3f79648..89d33e9 100644
--- a/tools/valgrind/memcheck/suppressions.txt
+++ b/tools/valgrind/memcheck/suppressions.txt
@@ -1406,16 +1406,16 @@
 {
    bug_64887_a
    Memcheck:Uninitialized
-   fun:_itoa_word
-   fun:vfprintf
-   fun:vsnprintf
-   fun:snprintf
-   fun:_ZN7testing*26PrintByteSegmentInObjectToEPKhmmPSo
-   fun:_ZN7testing*24PrintBytesInObjectToImplEPKhmPSo
-   fun:_ZN7testing9internal220PrintBytesInObjectToEPKhmPSo
-   fun:_ZN7testing9internal220TypeWithoutFormatterI*
+   ...
+   fun:*vfprintf
+   ...
+   fun:_ZN7testing*PrintByteSegmentInObjectTo*
+   ...
+   fun:_ZN7testing*PrintBytesInObjectTo*
+   fun:_ZN7testing9internal220PrintBytesInObjectToEPKhjPSo
+   fun:_ZN7testing9internal220TypeWithoutFormatter*
    fun:_ZN7testing9internal2lsIcSt11char_traitsIcE*
-   fun:_ZN16testing_internal26DefaultPrintNonContainerToI*
+   fun:_ZN16testing_internal26DefaultPrintNonContainerTo*
    fun:_ZN7testing8internal14DefaultPrintToI*
    fun:_ZN7testing8internal7PrintToI*
    fun:_ZN7testing8internal16UniversalPrinterI*
@@ -1424,42 +1424,6 @@
 {
    bug_64887_b
    Memcheck:Uninitialized
-   fun:_itoa_word
-   fun:vfprintf
-   fun:*vsnprintf*
-   fun:*snprintf*
-   fun:_ZN7testing*PrintByteSegmentInObjectTo*
-   fun:_ZN7testing*PrintBytesInObjectToImplEPKhjPSo
-   fun:_ZN7testing9internal220PrintBytesInObjectToEPKhjPSo
-   fun:_ZN7testing9internal220TypeWithoutFormatter*
-   fun:_ZN7testing9internal2lsIcSt11char_traitsIcE*
-   fun:_ZN16testing_internal26DefaultPrintNonContainerTo*
-   fun:_ZN7testing8internal14DefaultPrintToI*
-   fun:_ZN7testing8internal7PrintToI*
-   fun:_ZN7testing8internal16UniversalPrinterI*
-   fun:_ZN7testing8internal14UniversalPrintI*
-}
-{
-   bug_64887_c
-   Memcheck:Uninitialized
-   fun:_itoa_word
-   fun:vfprintf
-   fun:*vsnprintf*
-   fun:*snprintf*
-   fun:_ZN7testing*PrintByteSegmentInObjectTo*
-   fun:_ZN7testing*PrintBytesInObjectToImplEPKhjPSo
-   fun:_ZN7testing9internal220PrintBytesInObjectToEPKhjPSo
-   fun:_ZN7testing9internal220TypeWithoutFormatter*
-   fun:_ZN7testing9internal2lsIcSt11char_traitsIcE*
-   fun:_ZN16testing_internal26DefaultPrintNonContainerTo*
-   fun:_ZN7testing8internal14DefaultPrintToI*
-   fun:_ZN7testing8internal7PrintToI*
-   fun:_ZN7testing8internal16UniversalPrinterI*
-   fun:_ZN7testing8internal14UniversalPrintI*
-}
-{
-   bug_64887_d
-   Memcheck:Uninitialized
    ...
    fun:_ZNSolsEx
    fun:_ZN7testing9internal220TypeWithoutFormatterIN5media7PreloadELNS0_8TypeKindE1EE10PrintValueERKS3_PSo
@@ -1480,7 +1444,7 @@
    fun:_ZN5media11MockDemuxer10SetPreloadENS_7PreloadE
 }
 {
-   bug_64887_e
+   bug_64887_c
    Memcheck:Uninitialized
    ...
    fun:_ZNSolsEx
@@ -6314,10 +6278,3 @@
    fun:_ZN3WTFL16threadEntryPointEPv
    fun:_ZN3WTFL19wtfThreadEntryPointEPv
 }
-{
-   bug_349939
-   Memcheck:Uninitialized
-   ...
-   fun:_ZN7content9webcrypto9UnwrapKeyEN5blink18WebCryptoKeyFormatERKNS0_10CryptoDataERKNS1_12WebCryptoKeyERKNS1_18WebCryptoAlgorithmESB_biPS6_
-   fun:_ZN7content9webcrypto53SharedCryptoTest_AesKwRawSymkeyUnwrapCorruptData_Test8TestBodyEv
-}
diff --git a/tools/valgrind/tsan_v2/ignores.txt b/tools/valgrind/tsan_v2/ignores.txt
index 45d08ba..10acb4c 100644
--- a/tools/valgrind/tsan_v2/ignores.txt
+++ b/tools/valgrind/tsan_v2/ignores.txt
@@ -10,3 +10,7 @@
 
 # See http://crbug.com/172104
 fun:*v8*internal*ThreadEntry*
+
+# Avoid deadlocks between race reports on _M_rep() called from
+# base::FilePath::StripTrailingSeparatorsInternal(), see http://crbug.com/356676
+fun:*StripTrailingSeparatorsInternal*
diff --git a/ui/accessibility/accessibility.target.darwin-arm.mk b/ui/accessibility/accessibility.target.darwin-arm.mk
index 0048940..1603501 100644
--- a/ui/accessibility/accessibility.target.darwin-arm.mk
+++ b/ui/accessibility/accessibility.target.darwin-arm.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -215,9 +214,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -226,6 +223,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/accessibility.target.darwin-mips.mk b/ui/accessibility/accessibility.target.darwin-mips.mk
index 93bee86..1d46543 100644
--- a/ui/accessibility/accessibility.target.darwin-mips.mk
+++ b/ui/accessibility/accessibility.target.darwin-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -213,9 +212,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -224,6 +221,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/accessibility.target.darwin-x86.mk b/ui/accessibility/accessibility.target.darwin-x86.mk
index a73ec1a..449b695 100644
--- a/ui/accessibility/accessibility.target.darwin-x86.mk
+++ b/ui/accessibility/accessibility.target.darwin-x86.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/accessibility.target.darwin-x86_64.mk b/ui/accessibility/accessibility.target.darwin-x86_64.mk
new file mode 100644
index 0000000..14d8ddd
--- /dev/null
+++ b/ui/accessibility/accessibility.target.darwin-x86_64.mk
@@ -0,0 +1,338 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_accessibility_accessibility_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/accessibility/ax_node.cc \
+	ui/accessibility/ax_node_data.cc \
+	ui/accessibility/ax_serializable_tree.cc \
+	ui/accessibility/ax_text_utils.cc \
+	ui/accessibility/ax_tree.cc \
+	ui/accessibility/ax_tree_serializer.cc \
+	ui/accessibility/ax_tree_update.cc \
+	ui/accessibility/ax_view_state.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DACCESSIBILITY_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DACCESSIBILITY_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_accessibility_accessibility_gyp
+
+# Alias gyp target name.
+.PHONY: accessibility
+accessibility: ui_accessibility_accessibility_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/accessibility/accessibility.target.linux-arm.mk b/ui/accessibility/accessibility.target.linux-arm.mk
index 0048940..1603501 100644
--- a/ui/accessibility/accessibility.target.linux-arm.mk
+++ b/ui/accessibility/accessibility.target.linux-arm.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -215,9 +214,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -226,6 +223,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/accessibility.target.linux-mips.mk b/ui/accessibility/accessibility.target.linux-mips.mk
index 93bee86..1d46543 100644
--- a/ui/accessibility/accessibility.target.linux-mips.mk
+++ b/ui/accessibility/accessibility.target.linux-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -213,9 +212,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -224,6 +221,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/accessibility.target.linux-x86.mk b/ui/accessibility/accessibility.target.linux-x86.mk
index a73ec1a..449b695 100644
--- a/ui/accessibility/accessibility.target.linux-x86.mk
+++ b/ui/accessibility/accessibility.target.linux-x86.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/accessibility.target.linux-x86_64.mk b/ui/accessibility/accessibility.target.linux-x86_64.mk
new file mode 100644
index 0000000..14d8ddd
--- /dev/null
+++ b/ui/accessibility/accessibility.target.linux-x86_64.mk
@@ -0,0 +1,338 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_accessibility_accessibility_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_accessibility_ax_gen_gyp)/ui_accessibility_ax_gen_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/accessibility/ax_node.cc \
+	ui/accessibility/ax_node_data.cc \
+	ui/accessibility/ax_serializable_tree.cc \
+	ui/accessibility/ax_text_utils.cc \
+	ui/accessibility/ax_tree.cc \
+	ui/accessibility/ax_tree_serializer.cc \
+	ui/accessibility/ax_tree_update.cc \
+	ui/accessibility/ax_view_state.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DACCESSIBILITY_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DACCESSIBILITY_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_accessibility_ax_gen_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_accessibility_accessibility_gyp
+
+# Alias gyp target name.
+.PHONY: accessibility
+accessibility: ui_accessibility_accessibility_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/accessibility/ax_enums.idl b/ui/accessibility/ax_enums.idl
index 0f86c3d..bf11694 100644
--- a/ui/accessibility/ax_enums.idl
+++ b/ui/accessibility/ax_enums.idl
@@ -252,6 +252,7 @@
 
     // Relationships between this element and other elements.
     ax_attr_title_ui_element,
+    ax_attr_activedescendant_id,
 
     // Color value for AX_ROLE_COLOR_WELL, each component is 0..255
     ax_attr_color_value_red,
@@ -306,6 +307,13 @@
     // column.
     ax_attr_indirect_child_ids,
 
+    // Relationships between this element and other elements.
+    ax_attr_controls_ids,
+    ax_attr_describedby_ids,
+    ax_attr_flowto_ids,
+    ax_attr_labelledby_ids,
+    ax_attr_owns_ids,
+
     // Character indices where line breaks occur.
     ax_attr_line_breaks,
 
diff --git a/ui/accessibility/ax_gen.target.darwin-arm.mk b/ui/accessibility/ax_gen.target.darwin-arm.mk
index 3d8b68c..de8045b 100644
--- a/ui/accessibility/ax_gen.target.darwin-arm.mk
+++ b/ui/accessibility/ax_gen.target.darwin-arm.mk
@@ -127,6 +127,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -212,6 +213,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/ax_gen.target.darwin-mips.mk b/ui/accessibility/ax_gen.target.darwin-mips.mk
index 1a04e95..92c3c48 100644
--- a/ui/accessibility/ax_gen.target.darwin-mips.mk
+++ b/ui/accessibility/ax_gen.target.darwin-mips.mk
@@ -126,6 +126,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,6 +211,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/ax_gen.target.darwin-x86.mk b/ui/accessibility/ax_gen.target.darwin-x86.mk
index 1535325..bf97248 100644
--- a/ui/accessibility/ax_gen.target.darwin-x86.mk
+++ b/ui/accessibility/ax_gen.target.darwin-x86.mk
@@ -128,6 +128,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -213,6 +214,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/ax_gen.target.darwin-x86_64.mk b/ui/accessibility/ax_gen.target.darwin-x86_64.mk
new file mode 100644
index 0000000..61b076c
--- /dev/null
+++ b/ui/accessibility/ax_gen.target.darwin-x86_64.mk
@@ -0,0 +1,310 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_accessibility_ax_gen_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "genapi_bundle":
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: $(LOCAL_PATH)/tools/json_schema_compiler/cc_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/code.py $(LOCAL_PATH)/tools/json_schema_compiler/compiler.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_bundle_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_type_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_util.py $(LOCAL_PATH)/tools/json_schema_compiler/h_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/idl_schema.py $(LOCAL_PATH)/tools/json_schema_compiler/json_schema.py $(LOCAL_PATH)/tools/json_schema_compiler/model.py $(LOCAL_PATH)/tools/json_schema_compiler/util_cc_helper.py $(LOCAL_PATH)/ui/accessibility/ax_enums.idl $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating C++ API bundle code ($@)"
+	$(hide)cd $(gyp_local_path)/ui/accessibility; mkdir -p $(gyp_shared_intermediate_dir)/ui/accessibility; python ../../tools/json_schema_compiler/compiler.py "--root=../.." "--destdir=$(gyp_shared_intermediate_dir)" "--namespace=" "--generator=cpp-bundle" "--impl-dir=chrome/browser/extensions/api" ax_enums.idl
+
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h ;
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.h: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h ;
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h ;
+
+
+
+### Generated for rule "ui_accessibility_accessibility_gyp_ax_gen_target_genapi_idl":
+# "{'inputs': ['../../tools/json_schema_compiler/cc_generator.py', '../../tools/json_schema_compiler/code.py', '../../tools/json_schema_compiler/compiler.py', '../../tools/json_schema_compiler/cpp_generator.py', '../../tools/json_schema_compiler/cpp_type_generator.py', '../../tools/json_schema_compiler/cpp_util.py', '../../tools/json_schema_compiler/h_generator.py', '../../tools/json_schema_compiler/idl_schema.py', '../../tools/json_schema_compiler/model.py', '../../tools/json_schema_compiler/util.cc', '../../tools/json_schema_compiler/util.h', '../../tools/json_schema_compiler/util_cc_helper.py'], 'process_outputs_as_sources': '1', 'extension': 'idl', 'msvs_external_rule': '1', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/accessibility/%(INPUT_ROOT)s.cc', '$(gyp_shared_intermediate_dir)/ui/accessibility/%(INPUT_ROOT)s.h'], 'rule_name': 'genapi_idl', 'rule_sources': ['ax_enums.idl'], 'action': ['python', '../../tools/json_schema_compiler/compiler.py', '$(RULE_SOURCES)', '--root=../..', '--destdir=$(gyp_shared_intermediate_dir)', '--namespace=', '--generator=cpp', '--impl-dir=chrome/browser/extensions/api'], 'message': 'Generating C++ code from $(RULE_SOURCES) IDL files'}":
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: $(LOCAL_PATH)/ui/accessibility/ax_enums.idl $(LOCAL_PATH)/tools/json_schema_compiler/cc_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/code.py $(LOCAL_PATH)/tools/json_schema_compiler/compiler.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_type_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_util.py $(LOCAL_PATH)/tools/json_schema_compiler/h_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/idl_schema.py $(LOCAL_PATH)/tools/json_schema_compiler/model.py $(LOCAL_PATH)/tools/json_schema_compiler/util.cc $(LOCAL_PATH)/tools/json_schema_compiler/util.h $(LOCAL_PATH)/tools/json_schema_compiler/util_cc_helper.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/accessibility; cd $(gyp_local_path)/ui/accessibility; python ../../tools/json_schema_compiler/compiler.py ax_enums.idl "--root=../.." "--destdir=$(gyp_shared_intermediate_dir)" "--namespace=" "--generator=cpp" "--impl-dir=chrome/browser/extensions/api"
+
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.h: $(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc ;
+.PHONY: ui_accessibility_ax_gen_gyp_rule_trigger
+ui_accessibility_ax_gen_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/generated_api.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/generated_schemas.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/ax_enums.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/generated_api.cc \
+	$(gyp_intermediate_dir)/generated_schemas.cc \
+	$(gyp_intermediate_dir)/ax_enums.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.h \
+	ui_accessibility_ax_gen_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/ui/accessibility
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_accessibility_ax_gen_gyp
+
+# Alias gyp target name.
+.PHONY: ax_gen
+ax_gen: ui_accessibility_ax_gen_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/accessibility/ax_gen.target.linux-arm.mk b/ui/accessibility/ax_gen.target.linux-arm.mk
index 3d8b68c..de8045b 100644
--- a/ui/accessibility/ax_gen.target.linux-arm.mk
+++ b/ui/accessibility/ax_gen.target.linux-arm.mk
@@ -127,6 +127,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -212,6 +213,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/ax_gen.target.linux-mips.mk b/ui/accessibility/ax_gen.target.linux-mips.mk
index 1a04e95..92c3c48 100644
--- a/ui/accessibility/ax_gen.target.linux-mips.mk
+++ b/ui/accessibility/ax_gen.target.linux-mips.mk
@@ -126,6 +126,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,6 +211,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/ax_gen.target.linux-x86.mk b/ui/accessibility/ax_gen.target.linux-x86.mk
index 1535325..bf97248 100644
--- a/ui/accessibility/ax_gen.target.linux-x86.mk
+++ b/ui/accessibility/ax_gen.target.linux-x86.mk
@@ -128,6 +128,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -213,6 +214,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/accessibility/ax_gen.target.linux-x86_64.mk b/ui/accessibility/ax_gen.target.linux-x86_64.mk
new file mode 100644
index 0000000..61b076c
--- /dev/null
+++ b/ui/accessibility/ax_gen.target.linux-x86_64.mk
@@ -0,0 +1,310 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_accessibility_ax_gen_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "genapi_bundle":
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h: $(LOCAL_PATH)/tools/json_schema_compiler/cc_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/code.py $(LOCAL_PATH)/tools/json_schema_compiler/compiler.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_bundle_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_type_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_util.py $(LOCAL_PATH)/tools/json_schema_compiler/h_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/idl_schema.py $(LOCAL_PATH)/tools/json_schema_compiler/json_schema.py $(LOCAL_PATH)/tools/json_schema_compiler/model.py $(LOCAL_PATH)/tools/json_schema_compiler/util_cc_helper.py $(LOCAL_PATH)/ui/accessibility/ax_enums.idl $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating C++ API bundle code ($@)"
+	$(hide)cd $(gyp_local_path)/ui/accessibility; mkdir -p $(gyp_shared_intermediate_dir)/ui/accessibility; python ../../tools/json_schema_compiler/compiler.py "--root=../.." "--destdir=$(gyp_shared_intermediate_dir)" "--namespace=" "--generator=cpp-bundle" "--impl-dir=chrome/browser/extensions/api" ax_enums.idl
+
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h ;
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.h: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h ;
+$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h ;
+
+
+
+### Generated for rule "ui_accessibility_accessibility_gyp_ax_gen_target_genapi_idl":
+# "{'inputs': ['../../tools/json_schema_compiler/cc_generator.py', '../../tools/json_schema_compiler/code.py', '../../tools/json_schema_compiler/compiler.py', '../../tools/json_schema_compiler/cpp_generator.py', '../../tools/json_schema_compiler/cpp_type_generator.py', '../../tools/json_schema_compiler/cpp_util.py', '../../tools/json_schema_compiler/h_generator.py', '../../tools/json_schema_compiler/idl_schema.py', '../../tools/json_schema_compiler/model.py', '../../tools/json_schema_compiler/util.cc', '../../tools/json_schema_compiler/util.h', '../../tools/json_schema_compiler/util_cc_helper.py'], 'process_outputs_as_sources': '1', 'extension': 'idl', 'msvs_external_rule': '1', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/accessibility/%(INPUT_ROOT)s.cc', '$(gyp_shared_intermediate_dir)/ui/accessibility/%(INPUT_ROOT)s.h'], 'rule_name': 'genapi_idl', 'rule_sources': ['ax_enums.idl'], 'action': ['python', '../../tools/json_schema_compiler/compiler.py', '$(RULE_SOURCES)', '--root=../..', '--destdir=$(gyp_shared_intermediate_dir)', '--namespace=', '--generator=cpp', '--impl-dir=chrome/browser/extensions/api'], 'message': 'Generating C++ code from $(RULE_SOURCES) IDL files'}":
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc: $(LOCAL_PATH)/ui/accessibility/ax_enums.idl $(LOCAL_PATH)/tools/json_schema_compiler/cc_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/code.py $(LOCAL_PATH)/tools/json_schema_compiler/compiler.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_type_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/cpp_util.py $(LOCAL_PATH)/tools/json_schema_compiler/h_generator.py $(LOCAL_PATH)/tools/json_schema_compiler/idl_schema.py $(LOCAL_PATH)/tools/json_schema_compiler/model.py $(LOCAL_PATH)/tools/json_schema_compiler/util.cc $(LOCAL_PATH)/tools/json_schema_compiler/util.h $(LOCAL_PATH)/tools/json_schema_compiler/util_cc_helper.py $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/accessibility; cd $(gyp_local_path)/ui/accessibility; python ../../tools/json_schema_compiler/compiler.py ax_enums.idl "--root=../.." "--destdir=$(gyp_shared_intermediate_dir)" "--namespace=" "--generator=cpp" "--impl-dir=chrome/browser/extensions/api"
+
+$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.h: $(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc ;
+.PHONY: ui_accessibility_ax_gen_gyp_rule_trigger
+ui_accessibility_ax_gen_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/generated_api.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/generated_schemas.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/ax_enums.cc: $(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/generated_api.cc \
+	$(gyp_intermediate_dir)/generated_schemas.cc \
+	$(gyp_intermediate_dir)/ax_enums.cc \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_api.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/generated_schemas.h \
+	$(gyp_shared_intermediate_dir)/ui/accessibility/ax_enums.h \
+	ui_accessibility_ax_gen_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/ui/accessibility
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir) \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_accessibility_ax_gen_gyp
+
+# Alias gyp target name.
+.PHONY: ax_gen
+ax_gen: ui_accessibility_ax_gen_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/accessibility/ax_node_data.cc b/ui/accessibility/ax_node_data.cc
index 9a796a3..d287ac9 100644
--- a/ui/accessibility/ax_node_data.cc
+++ b/ui/accessibility/ax_node_data.cc
@@ -192,6 +192,9 @@
       case AX_ATTR_TITLE_UI_ELEMENT:
         result += " title_elem=" + value;
         break;
+      case AX_ATTR_ACTIVEDESCENDANT_ID:
+        result += " activedescendant=" + value;
+        break;
       case AX_ATTR_COLOR_VALUE_RED:
         result += " color_value_red=" + value;
         break;
@@ -352,6 +355,21 @@
       case AX_ATTR_INDIRECT_CHILD_IDS:
         result += " indirect_child_ids=" + IntVectorToString(values);
         break;
+      case AX_ATTR_CONTROLS_IDS:
+        result += " controls_ids=" + IntVectorToString(values);
+        break;
+      case AX_ATTR_DESCRIBEDBY_IDS:
+        result += " describedby_ids=" + IntVectorToString(values);
+        break;
+      case AX_ATTR_FLOWTO_IDS:
+        result += " flowto_ids=" + IntVectorToString(values);
+        break;
+      case AX_ATTR_LABELLEDBY_IDS:
+        result += " labelledby_ids=" + IntVectorToString(values);
+        break;
+      case AX_ATTR_OWNS_IDS:
+        result += " owns_ids=" + IntVectorToString(values);
+        break;
       case AX_ATTR_LINE_BREAKS:
         result += " line_breaks=" + IntVectorToString(values);
         break;
diff --git a/ui/accessibility/ax_tree_unittest.cc b/ui/accessibility/ax_tree_unittest.cc
index 7dcf59e..f4c609e 100644
--- a/ui/accessibility/ax_tree_unittest.cc
+++ b/ui/accessibility/ax_tree_unittest.cc
@@ -32,16 +32,8 @@
     new_root_ids_.push_back(new_root->id());
   }
 
-  void Reset() {
-    deleted_ids_.clear();
-    created_ids_.clear();
-    changed_ids_.clear();
-    new_root_ids_.clear();
-  }
-
   const std::vector<int32>& deleted_ids() { return deleted_ids_; }
   const std::vector<int32>& created_ids() { return created_ids_; }
-  const std::vector<int32>& changed_ids() { return changed_ids_; }
   const std::vector<int32>& new_root_ids() { return new_root_ids_; }
 
  private:
diff --git a/ui/accessibility/ax_view_state.cc b/ui/accessibility/ax_view_state.cc
index fb19e2d..11044bc 100644
--- a/ui/accessibility/ax_view_state.cc
+++ b/ui/accessibility/ax_view_state.cc
@@ -8,12 +8,20 @@
 
 AXViewState::AXViewState()
     : role(AX_ROLE_CLIENT),
-      state(0),
       selection_start(-1),
       selection_end(-1),
       index(-1),
-      count(-1) { }
+      count(-1),
+      state_(0) { }
 
 AXViewState::~AXViewState() { }
 
+void AXViewState::AddStateFlag(ui::AXState state_flag) {
+  state_ |= (1 << state_flag);
+}
+
+bool AXViewState::HasStateFlag(ui::AXState state_flag) const {
+  return 0 != (state_ & (1 << state_flag));
+}
+
 }  // namespace ui
diff --git a/ui/accessibility/ax_view_state.h b/ui/accessibility/ax_view_state.h
index 2cb2152..5d72d47 100644
--- a/ui/accessibility/ax_view_state.h
+++ b/ui/accessibility/ax_view_state.h
@@ -26,13 +26,13 @@
   AXViewState();
   ~AXViewState();
 
+  // Set or check bits in |state_|.
+  void AddStateFlag(ui::AXState state);
+  bool HasStateFlag(ui::AXState state) const;
+
   // The view's role, like button or list box.
   AXRole role;
 
-  // The view's state, a bitmask containing fields such as checked
-  // (for a checkbox) and protected (for a password text box).
-  uint32 state;
-
   // The view's name / label.
   base::string16 name;
 
@@ -66,6 +66,11 @@
   // be a safe no-op if the view is deleted. Typically, accessible views
   // should use a WeakPtr when binding the callback.
   base::Callback<void(const base::string16&)> set_value_callback;
+
+ private:
+  // The view's state, a bitmask containing fields such as checked
+  // (for a checkbox) and protected (for a password text box).
+  uint32 state_;
 };
 
 }  // namespace ui
diff --git a/ui/android/bitmap_format_java.target.darwin-arm.mk b/ui/android/bitmap_format_java.target.darwin-arm.mk
index 53304c5..9e9a68b 100644
--- a/ui/android/bitmap_format_java.target.darwin-arm.mk
+++ b/ui/android/bitmap_format_java.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/bitmap_format_java.target.darwin-mips.mk b/ui/android/bitmap_format_java.target.darwin-mips.mk
index 7e708ec..e32bed2 100644
--- a/ui/android/bitmap_format_java.target.darwin-mips.mk
+++ b/ui/android/bitmap_format_java.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/bitmap_format_java.target.darwin-x86.mk b/ui/android/bitmap_format_java.target.darwin-x86.mk
index 406d2c6..3b2c06d 100644
--- a/ui/android/bitmap_format_java.target.darwin-x86.mk
+++ b/ui/android/bitmap_format_java.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/bitmap_format_java.target.darwin-x86_64.mk b/ui/android/bitmap_format_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..665971a
--- /dev/null
+++ b/ui/android/bitmap_format_java.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_android_bitmap_format_java_gyp
+LOCAL_MODULE_STEM := bitmap_format_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_android_ui_android_gyp_bitmap_format_java_target_generate_java_constants":
+# "{'inputs': ['../../build/android/gyp/util/build_utils.py', '../../build/android/gyp/gcc_preprocess.py', '../gfx/android/bitmap_config_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['java/BitmapFormat.template'], 'action': ['python', '../../build/android/gyp/gcc_preprocess.py', '--include-path=../..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: $(LOCAL_PATH)/ui/android/java/BitmapFormat.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/ui/gfx/android/bitmap_config_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx; cd $(gyp_local_path)/ui/android; python ../../build/android/gyp/gcc_preprocess.py "--include-path=../.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java" "--template=java/BitmapFormat.template"
+
+.PHONY: ui_android_bitmap_format_java_gyp_rule_trigger
+ui_android_bitmap_format_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	ui_android_bitmap_format_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_android_bitmap_format_java_gyp
+
+# Alias gyp target name.
+.PHONY: bitmap_format_java
+bitmap_format_java: ui_android_bitmap_format_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/android/bitmap_format_java.target.linux-arm.mk b/ui/android/bitmap_format_java.target.linux-arm.mk
index 53304c5..9e9a68b 100644
--- a/ui/android/bitmap_format_java.target.linux-arm.mk
+++ b/ui/android/bitmap_format_java.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/bitmap_format_java.target.linux-mips.mk b/ui/android/bitmap_format_java.target.linux-mips.mk
index 7e708ec..e32bed2 100644
--- a/ui/android/bitmap_format_java.target.linux-mips.mk
+++ b/ui/android/bitmap_format_java.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/bitmap_format_java.target.linux-x86.mk b/ui/android/bitmap_format_java.target.linux-x86.mk
index 406d2c6..3b2c06d 100644
--- a/ui/android/bitmap_format_java.target.linux-x86.mk
+++ b/ui/android/bitmap_format_java.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/bitmap_format_java.target.linux-x86_64.mk b/ui/android/bitmap_format_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..665971a
--- /dev/null
+++ b/ui/android/bitmap_format_java.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_android_bitmap_format_java_gyp
+LOCAL_MODULE_STEM := bitmap_format_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_android_ui_android_gyp_bitmap_format_java_target_generate_java_constants":
+# "{'inputs': ['../../build/android/gyp/util/build_utils.py', '../../build/android/gyp/gcc_preprocess.py', '../gfx/android/bitmap_config_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['java/BitmapFormat.template'], 'action': ['python', '../../build/android/gyp/gcc_preprocess.py', '--include-path=../..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java: $(LOCAL_PATH)/ui/android/java/BitmapFormat.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/ui/gfx/android/bitmap_config_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx; cd $(gyp_local_path)/ui/android; python ../../build/android/gyp/gcc_preprocess.py "--include-path=../.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java" "--template=java/BitmapFormat.template"
+
+.PHONY: ui_android_bitmap_format_java_gyp_rule_trigger
+ui_android_bitmap_format_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/gfx/BitmapFormat.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	ui_android_bitmap_format_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_android_bitmap_format_java_gyp
+
+# Alias gyp target name.
+.PHONY: bitmap_format_java
+bitmap_format_java: ui_android_bitmap_format_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java b/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java
index dd04217..5c4549c 100644
--- a/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java
+++ b/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java
@@ -39,14 +39,15 @@
                                                  int reqHeight) {
         Resources res = Resources.getSystem();
         int resId = res.getIdentifier(name, null, null);
+        if (resId == 0) return null;
 
         final BitmapFactory.Options options = new BitmapFactory.Options();
         options.inJustDecodeBounds = true;
         BitmapFactory.decodeResource(res, resId, options);
 
         options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
-
         options.inJustDecodeBounds = false;
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
         return BitmapFactory.decodeResource(res, resId, options);
     }
 
diff --git a/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java b/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java
index 863fa1b..c154ea0 100644
--- a/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java
+++ b/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java
@@ -31,6 +31,7 @@
     private final Context mAppContext;
     private final WindowManager mWinManager;
     private Point mTempPoint = new Point();
+    private DisplayMetrics mTempMetrics = new DisplayMetrics();
 
     private DeviceDisplayInfo(Context context) {
         mAppContext = context.getApplicationContext();
@@ -42,7 +43,8 @@
      */
     @CalledByNative
     public int getDisplayHeight() {
-        return getMetrics().heightPixels;
+        getDisplay().getSize(mTempPoint);
+        return mTempPoint.y;
     }
 
     /**
@@ -50,7 +52,8 @@
      */
     @CalledByNative
     public int getDisplayWidth() {
-        return getMetrics().widthPixels;
+        getDisplay().getSize(mTempPoint);
+        return mTempPoint.x;
     }
 
     /**
@@ -140,7 +143,8 @@
      */
     @CalledByNative
     public double getDIPScale() {
-        return getMetrics().density;
+        getDisplay().getMetrics(mTempMetrics);
+        return mTempMetrics.density;
     }
 
     /**
@@ -178,10 +182,6 @@
         return mWinManager.getDefaultDisplay();
     }
 
-    private DisplayMetrics getMetrics() {
-        return mAppContext.getResources().getDisplayMetrics();
-    }
-
     /**
      * Creates DeviceDisplayInfo for a given Context.
      *
diff --git a/ui/android/java/strings/translations/android_ui_strings_am.xtb b/ui/android/java/strings/translations/android_ui_strings_am.xtb
index 0969b29..c72ce6a 100644
--- a/ui/android/java/strings/translations/android_ui_strings_am.xtb
+++ b/ui/android/java/strings/translations/android_ui_strings_am.xtb
@@ -2,7 +2,7 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="am">
 <translation id="6017514345406065928">አረንጓዴ</translation>
-<translation id="7658239707568436148">ሰርዝ</translation>
+<translation id="7658239707568436148">ይቅር</translation>
 <translation id="9068849894565669697">ቀለም ይምረጡ</translation>
 <translation id="4115378294792113321">ሮዝ</translation>
 <translation id="793640675459356075">የተመረጠውን ፋይል መክፈት አልተሳካም</translation>
diff --git a/ui/android/window_open_disposition_java.target.darwin-arm.mk b/ui/android/window_open_disposition_java.target.darwin-arm.mk
index 2d73885..b890532 100644
--- a/ui/android/window_open_disposition_java.target.darwin-arm.mk
+++ b/ui/android/window_open_disposition_java.target.darwin-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/window_open_disposition_java.target.darwin-mips.mk b/ui/android/window_open_disposition_java.target.darwin-mips.mk
index 4d64d18..e7ad841 100644
--- a/ui/android/window_open_disposition_java.target.darwin-mips.mk
+++ b/ui/android/window_open_disposition_java.target.darwin-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/window_open_disposition_java.target.darwin-x86.mk b/ui/android/window_open_disposition_java.target.darwin-x86.mk
index b709330..a627c73 100644
--- a/ui/android/window_open_disposition_java.target.darwin-x86.mk
+++ b/ui/android/window_open_disposition_java.target.darwin-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/window_open_disposition_java.target.darwin-x86_64.mk b/ui/android/window_open_disposition_java.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7c5796e
--- /dev/null
+++ b/ui/android/window_open_disposition_java.target.darwin-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_android_window_open_disposition_java_gyp
+LOCAL_MODULE_STEM := window_open_disposition_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_android_ui_android_gyp_window_open_disposition_java_target_generate_java_constants":
+# "{'inputs': ['../../build/android/gyp/util/build_utils.py', '../../build/android/gyp/gcc_preprocess.py', '../base/window_open_disposition_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['java/WindowOpenDisposition.template'], 'action': ['python', '../../build/android/gyp/gcc_preprocess.py', '--include-path=../..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: $(LOCAL_PATH)/ui/android/java/WindowOpenDisposition.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/ui/base/window_open_disposition_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/ui; cd $(gyp_local_path)/ui/android; python ../../build/android/gyp/gcc_preprocess.py "--include-path=../.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java" "--template=java/WindowOpenDisposition.template"
+
+.PHONY: ui_android_window_open_disposition_java_gyp_rule_trigger
+ui_android_window_open_disposition_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	ui_android_window_open_disposition_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_android_window_open_disposition_java_gyp
+
+# Alias gyp target name.
+.PHONY: window_open_disposition_java
+window_open_disposition_java: ui_android_window_open_disposition_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/android/window_open_disposition_java.target.linux-arm.mk b/ui/android/window_open_disposition_java.target.linux-arm.mk
index 2d73885..b890532 100644
--- a/ui/android/window_open_disposition_java.target.linux-arm.mk
+++ b/ui/android/window_open_disposition_java.target.linux-arm.mk
@@ -94,6 +94,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -176,6 +177,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/window_open_disposition_java.target.linux-mips.mk b/ui/android/window_open_disposition_java.target.linux-mips.mk
index 4d64d18..e7ad841 100644
--- a/ui/android/window_open_disposition_java.target.linux-mips.mk
+++ b/ui/android/window_open_disposition_java.target.linux-mips.mk
@@ -93,6 +93,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -174,6 +175,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/window_open_disposition_java.target.linux-x86.mk b/ui/android/window_open_disposition_java.target.linux-x86.mk
index b709330..a627c73 100644
--- a/ui/android/window_open_disposition_java.target.linux-x86.mk
+++ b/ui/android/window_open_disposition_java.target.linux-x86.mk
@@ -95,6 +95,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/android/window_open_disposition_java.target.linux-x86_64.mk b/ui/android/window_open_disposition_java.target.linux-x86_64.mk
new file mode 100644
index 0000000..7c5796e
--- /dev/null
+++ b/ui/android/window_open_disposition_java.target.linux-x86_64.mk
@@ -0,0 +1,233 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_android_window_open_disposition_java_gyp
+LOCAL_MODULE_STEM := window_open_disposition_java
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_android_ui_android_gyp_window_open_disposition_java_target_generate_java_constants":
+# "{'inputs': ['../../build/android/gyp/util/build_utils.py', '../../build/android/gyp/gcc_preprocess.py', '../base/window_open_disposition_list.h'], 'extension': 'template', 'outputs': ['$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/%(INPUT_ROOT)s.java'], 'variables': {'output_path': '$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/%(INPUT_ROOT)s.java'}, 'rule_name': 'generate_java_constants', 'rule_sources': ['java/WindowOpenDisposition.template'], 'action': ['python', '../../build/android/gyp/gcc_preprocess.py', '--include-path=../..', '--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/%(INPUT_ROOT)s.java', '--template=$(RULE_SOURCES)'], 'message': 'Generating Java from cpp template $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java: $(LOCAL_PATH)/ui/android/java/WindowOpenDisposition.template $(LOCAL_PATH)/build/android/gyp/util/build_utils.py $(LOCAL_PATH)/build/android/gyp/gcc_preprocess.py $(LOCAL_PATH)/ui/base/window_open_disposition_list.h $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/templates/org/chromium/ui; cd $(gyp_local_path)/ui/android; python ../../build/android/gyp/gcc_preprocess.py "--include-path=../.." "--output=$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java" "--template=java/WindowOpenDisposition.template"
+
+.PHONY: ui_android_window_open_disposition_java_gyp_rule_trigger
+ui_android_window_open_disposition_java_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/templates/org/chromium/ui/WindowOpenDisposition.java
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	ui_android_window_open_disposition_java_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_android_window_open_disposition_java_gyp
+
+# Alias gyp target name.
+.PHONY: window_open_disposition_java
+window_open_disposition_java: ui_android_window_open_disposition_java_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/app_list/app_list.gyp b/ui/app_list/app_list.gyp
index 6340b7b..182d9c6 100644
--- a/ui/app_list/app_list.gyp
+++ b/ui/app_list/app_list.gyp
@@ -18,6 +18,7 @@
         '../base/strings/ui_strings.gyp:ui_strings',
         '../base/ui_base.gyp:ui_base',
         '../compositor/compositor.gyp:compositor',
+        '../events/events.gyp:events_base',
         '../gfx/gfx.gyp:gfx',
         '../gfx/gfx.gyp:gfx_geometry',
         '../resources/ui_resources.gyp:ui_resources',
@@ -103,6 +104,7 @@
         'views/apps_grid_view.cc',
         'views/apps_grid_view.h',
         'views/apps_grid_view_delegate.h',
+        'views/apps_grid_view_folder_delegate.h',
         'views/cached_label.cc',
         'views/cached_label.h',
         'views/contents_switcher_view.cc',
@@ -220,6 +222,7 @@
         'test/run_all_unittests.cc',
         'views/app_list_main_view_unittest.cc',
         'views/apps_grid_view_unittest.cc',
+        'views/folder_header_view_unittest.cc',
         'views/search_box_view_unittest.cc',
         'views/search_result_list_view_unittest.cc',
         'views/test/apps_grid_view_test_api.cc',
@@ -254,11 +257,6 @@
             ['exclude', 'cocoa/'],
           ],
         }],
-        ['desktop_linux == 1 or chromeos == 1 or OS == "ios"', {
-          'dependencies': [
-            '../base/strings/ui_strings.gyp:ui_unittest_strings',
-          ],
-        }],
         # See http://crbug.com/162998#c4 for why this is needed.
         # TODO(dmikurube): Kill linux_use_tcmalloc. http://crbug.com/345554
         ['OS=="linux" and ((use_allocator!="none" and use_allocator!="see_use_tcmalloc") or (use_allocator=="see_use_tcmalloc" and linux_use_tcmalloc==1))', {
diff --git a/ui/app_list/app_list_constants.cc b/ui/app_list/app_list_constants.cc
index 6c2ec45..efcf5a7 100644
--- a/ui/app_list/app_list_constants.cc
+++ b/ui/app_list/app_list_constants.cc
@@ -64,10 +64,19 @@
 const int kExperimentalPreferredCols = 6;
 const int kExperimentalPreferredRows = 3;
 
+// Radius of the circle, in which if entered, show re-order preview.
+const int kReorderDroppingCircleRadius = 35;
+
+// Max items allowed in a folder.
+size_t kMaxFolderItems = 16;
+
 // Number of the top items in a folder, which are shown inside the folder icon
 // and animated when opening and closing a folder.
 const size_t kNumFolderTopItems = 4;
 
+// Maximum length of the folder name in chars.
+const size_t kMaxFolderNameChars = 40;
+
 // Font style for app item labels.
 const ui::ResourceBundle::FontStyle kItemTextFontStyle =
     ui::ResourceBundle::SmallBoldFont;
diff --git a/ui/app_list/app_list_constants.h b/ui/app_list/app_list_constants.h
index 8245017..cb2c30a 100644
--- a/ui/app_list/app_list_constants.h
+++ b/ui/app_list/app_list_constants.h
@@ -49,7 +49,11 @@
 APP_LIST_EXPORT extern const int kExperimentalPreferredCols;
 APP_LIST_EXPORT extern const int kExperimentalPreferredRows;
 
+APP_LIST_EXPORT extern const int kReorderDroppingCircleRadius;
+
+APP_LIST_EXPORT extern size_t kMaxFolderItems;
 APP_LIST_EXPORT extern const size_t kNumFolderTopItems;
+APP_LIST_EXPORT extern const size_t kMaxFolderNameChars;
 
 APP_LIST_EXPORT extern const ui::ResourceBundle::FontStyle kItemTextFontStyle;
 
diff --git a/ui/app_list/app_list_menu.cc b/ui/app_list/app_list_menu.cc
index 8c0727c..c37a555 100644
--- a/ui/app_list/app_list_menu.cc
+++ b/ui/app_list/app_list_menu.cc
@@ -67,6 +67,10 @@
 }
 
 bool AppListMenu::IsCommandIdEnabled(int command_id) const {
+  if (command_id >= SELECT_PROFILE &&
+      command_id < SELECT_PROFILE + static_cast<int>(users_.size())) {
+    return !users_[command_id - SELECT_PROFILE].signin_required;
+  }
   return true;
 }
 
diff --git a/ui/app_list/app_list_view_delegate.cc b/ui/app_list/app_list_view_delegate.cc
index 2156cf5..6c57780 100644
--- a/ui/app_list/app_list_view_delegate.cc
+++ b/ui/app_list/app_list_view_delegate.cc
@@ -6,10 +6,8 @@
 
 namespace app_list {
 
-AppListViewDelegate::User::User() : active(false) {
-}
+AppListViewDelegate::User::User() : active(false), signin_required(false) {}
 
-AppListViewDelegate::User::~User() {
-}
+AppListViewDelegate::User::~User() {}
 
 }  // app_list
diff --git a/ui/app_list/app_list_view_delegate.h b/ui/app_list/app_list_view_delegate.h
index aac3f35..f0c43db 100644
--- a/ui/app_list/app_list_view_delegate.h
+++ b/ui/app_list/app_list_view_delegate.h
@@ -52,6 +52,9 @@
 
     // The path to this user's profile directory.
     base::FilePath profile_path;
+
+    // Whether or not the current profile requires sign-in beofre use.
+    bool signin_required;
   };
   typedef std::vector<User> Users;
 
diff --git a/ui/app_list/test/app_list_test_model.cc b/ui/app_list/test/app_list_test_model.cc
index 7a90812..66d2a69 100644
--- a/ui/app_list/test/app_list_test_model.cc
+++ b/ui/app_list/test/app_list_test_model.cc
@@ -69,6 +69,27 @@
     CreateAndAddItem(GetItemName(start_index + i));
 }
 
+AppListFolderItem* AppListTestModel::CreateAndPopulateFolderWithApps(int n) {
+  DCHECK_GT(n, 1);
+  int start_index = static_cast<int>(top_level_item_list()->item_count());
+  AppListTestItem* item = CreateAndAddItem(GetItemName(start_index));
+  std::string merged_item_id = item->id();
+  for (int i = 1; i < n; ++i) {
+    AppListTestItem* new_item = CreateAndAddItem(GetItemName(start_index + i));
+    merged_item_id = AppListModel::MergeItems(merged_item_id, new_item->id());
+  }
+  AppListItem* merged_item = FindItem(merged_item_id);
+  DCHECK(merged_item->GetItemType() == AppListFolderItem::kItemType);
+  return static_cast<AppListFolderItem*>(merged_item);
+}
+
+AppListFolderItem* AppListTestModel::CreateAndAddOemFolder(
+    const std::string& id) {
+  AppListFolderItem* folder =
+      new AppListFolderItem(id, AppListFolderItem::FOLDER_TYPE_OEM);
+  return static_cast<AppListFolderItem*>(AddItem(folder));
+}
+
 void AppListTestModel::PopulateAppWithId(int id) {
   CreateAndAddItem(GetItemName(id));
 }
diff --git a/ui/app_list/test/app_list_test_model.h b/ui/app_list/test/app_list_test_model.h
index c7ef6fa..2d2fc95 100644
--- a/ui/app_list/test/app_list_test_model.h
+++ b/ui/app_list/test/app_list_test_model.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "ui/app_list/app_list_folder_item.h"
 #include "ui/app_list/app_list_item.h"
 #include "ui/app_list/app_list_model.h"
 
@@ -47,6 +48,11 @@
   // Populate the model with |n| items titled "Item #".
   void PopulateApps(int n);
 
+  // Creates and populate a folder with |n| test apps in it.
+  AppListFolderItem* CreateAndPopulateFolderWithApps(int n);
+
+  AppListFolderItem* CreateAndAddOemFolder(const std::string& id);
+
   // Populate the model with an item titled "Item |id|".
   void PopulateAppWithId(int id);
 
diff --git a/ui/app_list/views/app_list_folder_view.cc b/ui/app_list/views/app_list_folder_view.cc
index 548fc0d..d51d67f 100644
--- a/ui/app_list/views/app_list_folder_view.cc
+++ b/ui/app_list/views/app_list_folder_view.cc
@@ -42,8 +42,7 @@
 
 AppListFolderView::AppListFolderView(AppsContainerView* container_view,
                                      AppListModel* model,
-                                     AppListMainView* app_list_main_view,
-                                     content::WebContents* start_page_contents)
+                                     AppListMainView* app_list_main_view)
     : container_view_(container_view),
       app_list_main_view_(app_list_main_view),
       folder_header_view_(new FolderHeaderView(this)),
@@ -56,8 +55,8 @@
   view_model_->Add(folder_header_view_, kIndexFolderHeader);
 
   items_grid_view_ =
-      new AppsGridView(app_list_main_view_, pagination_model_.get(), NULL);
-  items_grid_view_->set_is_root_level(false);
+      new AppsGridView(app_list_main_view_, pagination_model_.get());
+  items_grid_view_->set_folder_delegate(this);
   items_grid_view_->SetLayout(
       kPreferredIconDimension,
       container_view->apps_grid_view()->cols(),
@@ -227,7 +226,7 @@
   folder_header_view_->UpdateFolderNameVisibility(visible);
 }
 
-bool AppListFolderView::IsPointOutsideOfFolderBoundray(
+bool AppListFolderView::IsPointOutsideOfFolderBoundary(
     const gfx::Point& point) {
   if (!GetLocalBounds().Contains(point))
     return true;
diff --git a/ui/app_list/views/app_list_folder_view.h b/ui/app_list/views/app_list_folder_view.h
index 198f691..b6d9600 100644
--- a/ui/app_list/views/app_list_folder_view.h
+++ b/ui/app_list/views/app_list_folder_view.h
@@ -7,16 +7,13 @@
 
 #include "ui/app_list/app_list_item_list_observer.h"
 #include "ui/app_list/views/apps_grid_view.h"
+#include "ui/app_list/views/apps_grid_view_folder_delegate.h"
 #include "ui/app_list/views/folder_header_view.h"
 #include "ui/app_list/views/folder_header_view_delegate.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/view.h"
 
-namespace content {
-class WebContents;
-}
-
 namespace views {
 class ViewModel;
 }
@@ -35,12 +32,12 @@
 class AppListFolderView : public views::View,
                           public FolderHeaderViewDelegate,
                           public AppListModelObserver,
-                          public ui::ImplicitAnimationObserver {
+                          public ui::ImplicitAnimationObserver,
+                          public AppsGridViewFolderDelegate {
  public:
   AppListFolderView(AppsContainerView* container_view,
                     AppListModel* model,
-                    AppListMainView* app_list_main_view,
-                    content::WebContents* start_page_contents);
+                    AppListMainView* app_list_main_view);
   virtual ~AppListFolderView();
 
   void SetAppListFolderItem(AppListFolderItem* folder);
@@ -54,39 +51,11 @@
   // AppListFolderView.
   gfx::Rect GetItemIconBoundsAt(int index);
 
-  // Updates the folder view background to show or hide folder container ink
-  // bubble.
-  void UpdateFolderViewBackground(bool show_bubble);
-
   void UpdateFolderNameVisibility(bool visible);
 
-  // Returns true if |point| falls outside of the folder container ink bubble.
-  bool IsPointOutsideOfFolderBoundray(const gfx::Point& point);
-
-  // Called when a folder item is dragged out of the folder to be re-parented.
-  // |original_drag_view| is the |drag_view_| inside the folder's grid view.
-  // |drag_point_in_folder_grid| is the last drag point in coordinate of the
-  // AppsGridView inside the folder.
-  void ReparentItem(AppListItemView* original_drag_view,
-      const gfx::Point& drag_point_in_folder_grid);
-
-  // Dispatches drag event from the hidden grid view to the root level grid view
-  // for re-parenting a folder item.
-  void DispatchDragEventForReparent(AppsGridView::Pointer pointer,
-      const ui::LocatedEvent& event);
-
-  // Dispatches EndDrag event from the hidden grid view to the root level grid
-  // view for reparenting a folder item.
-  // |events_forwarded_to_drag_drop_host|: True if the dragged item is dropped
-  // to the drag_drop_host, eg. dropped on shelf.
-  void DispatchEndDragEventForReparent(bool events_forwarded_to_drag_drop_host);
-
   // Hides the view immediately without animation.
   void HideViewImmediately();
 
-  // Returns true if the associated folder item is an OEM folder.
-  bool IsOEMFolder() const;
-
   // views::View
   virtual gfx::Size GetPreferredSize() OVERRIDE;
   virtual void Layout() OVERRIDE;
@@ -117,6 +86,19 @@
   virtual void SetItemName(AppListFolderItem* item,
                            const std::string& name) OVERRIDE;
 
+  // Overridden from AppsGridViewFolderDelegate:
+  virtual void UpdateFolderViewBackground(bool show_bubble) OVERRIDE;
+  virtual void ReparentItem(AppListItemView* original_drag_view,
+                            const gfx::Point& drag_point_in_folder_grid)
+      OVERRIDE;
+  virtual void DispatchDragEventForReparent(AppsGridView::Pointer pointer,
+                                            const ui::LocatedEvent& event)
+      OVERRIDE;
+  virtual void DispatchEndDragEventForReparent(
+      bool events_forwarded_to_drag_drop_host) OVERRIDE;
+  virtual bool IsPointOutsideOfFolderBoundary(const gfx::Point& point) OVERRIDE;
+  virtual bool IsOEMFolder() const OVERRIDE;
+
   AppsContainerView* container_view_;  // Not owned.
   AppListMainView* app_list_main_view_;   // Not Owned.
   FolderHeaderView* folder_header_view_;  // Owned by views hierarchy.
diff --git a/ui/app_list/views/apps_container_view.cc b/ui/app_list/views/apps_container_view.cc
index 2a0ca0c..a56b3a9 100644
--- a/ui/app_list/views/apps_container_view.cc
+++ b/ui/app_list/views/apps_container_view.cc
@@ -23,13 +23,11 @@
 
 AppsContainerView::AppsContainerView(AppListMainView* app_list_main_view,
                                      PaginationModel* pagination_model,
-                                     AppListModel* model,
-                                     content::WebContents* start_page_contents)
+                                     AppListModel* model)
     : model_(model),
       show_state_(SHOW_APPS),
       top_icon_animation_pending_count_(0) {
-  apps_grid_view_ = new AppsGridView(
-      app_list_main_view, pagination_model, start_page_contents);
+  apps_grid_view_ = new AppsGridView(app_list_main_view, pagination_model);
   int cols = kPreferredCols;
   int rows = kPreferredRows;
   if (app_list::switches::IsExperimentalAppListPositionEnabled()) {
@@ -42,11 +40,8 @@
   folder_background_view_ = new FolderBackgroundView();
   AddChildView(folder_background_view_);
 
-  app_list_folder_view_ = new AppListFolderView(
-      this,
-      model,
-      app_list_main_view,
-      start_page_contents);
+  app_list_folder_view_ =
+      new AppListFolderView(this, model, app_list_main_view);
   AddChildView(app_list_folder_view_);
 
   apps_grid_view_->SetModel(model_);
diff --git a/ui/app_list/views/apps_container_view.h b/ui/app_list/views/apps_container_view.h
index 7b23f8f..1c8a913 100644
--- a/ui/app_list/views/apps_container_view.h
+++ b/ui/app_list/views/apps_container_view.h
@@ -33,8 +33,7 @@
  public:
   AppsContainerView(AppListMainView* app_list_main_view,
                     PaginationModel* pagination_model,
-                    AppListModel* model,
-                    content::WebContents* start_page_contents);
+                    AppListModel* model);
   virtual ~AppsContainerView();
 
   // Shows the active folder content specified by |folder_item|.
diff --git a/ui/app_list/views/apps_grid_view.cc b/ui/app_list/views/apps_grid_view.cc
index 6be7b42..63f817c 100644
--- a/ui/app_list/views/apps_grid_view.cc
+++ b/ui/app_list/views/apps_grid_view.cc
@@ -95,11 +95,6 @@
 // UI.
 const int kFolderDroppingCircleRadius = 15;
 
-// Radius of the circle, in which if entered, show re-order preview.
-const int kReorderDroppingCircleRadius = 35;
-
-// Max items allowed in a folder.
-size_t kMaxFolderItems = 16;
 
 // RowMoveAnimationDelegate is used when moving an item into a different row.
 // Before running the animation, the item's layer is re-created and kept in
@@ -318,14 +313,13 @@
 #endif  // defined(OS_WIN)
 
 AppsGridView::AppsGridView(AppsGridViewDelegate* delegate,
-                           PaginationModel* pagination_model,
-                           content::WebContents* start_page_contents)
+                           PaginationModel* pagination_model)
     : model_(NULL),
       item_list_(NULL),
       delegate_(delegate),
+      folder_delegate_(NULL),
       pagination_model_(pagination_model),
       page_switcher_view_(new PageSwitcher(pagination_model)),
-      start_page_view_(NULL),
       cols_(0),
       rows_per_page_(0),
       selected_view_(NULL),
@@ -338,7 +332,6 @@
       page_flip_target_(-1),
       page_flip_delay_in_ms_(kPageFlipDelayInMs),
       bounds_animator_(this),
-      is_root_level_(true),
       activated_item_view_(NULL),
       dragging_for_reparent_item_(false),
       weak_factory_(this) {
@@ -347,13 +340,6 @@
 
   pagination_model_->AddObserver(this);
   AddChildView(page_switcher_view_);
-
-  if (start_page_contents) {
-    start_page_view_ =
-        new views::WebView(start_page_contents->GetBrowserContext());
-    start_page_view_->SetWebContents(start_page_contents);
-    AddChildView(start_page_view_);
-  }
 }
 
 AppsGridView::~AppsGridView() {
@@ -507,7 +493,7 @@
                                       const ui::LocatedEvent& event) {
   DCHECK(drag_view_);
 
-  if (!is_root_level_)
+  if (folder_delegate_)
     UpdateDragStateInsideFolder(pointer, event);
 
   gfx::Point drag_point_in_grid_view;
@@ -603,15 +589,12 @@
     DCHECK(!IsDraggingForReparentInRootLevelGridView());
     forward_events_to_drag_and_drop_host_ = false;
     drag_and_drop_host_->EndDrag(cancel);
-    if (IsDraggingForReprentInHiddenGridView()) {
-      static_cast<AppListFolderView*>(parent())->
-          DispatchEndDragEventForReparent(true);
-    }
+    if (IsDraggingForReparentInHiddenGridView())
+      folder_delegate_->DispatchEndDragEventForReparent(true);
   } else if (!cancel && dragging()) {
-    if (IsDraggingForReprentInHiddenGridView()) {
+    if (IsDraggingForReparentInHiddenGridView()) {
       // Forward the EndDrag event to the root level grid view.
-      static_cast<AppListFolderView*>(parent())->
-          DispatchEndDragEventForReparent(false);
+      folder_delegate_->DispatchEndDragEventForReparent(false);
       EndDragForReparentInHiddenFolderGridView();
       return;
     } else {
@@ -666,12 +649,10 @@
 
   // If user releases mouse inside a folder's grid view, burst the folder
   // container ink bubble.
-  if (!cancel && !is_root_level_ && !IsDraggingForReprentInHiddenGridView()) {
-    static_cast<AppListFolderView*>(parent())->
-        UpdateFolderViewBackground(false);
-  }
+  if (folder_delegate_ && !IsDraggingForReparentInHiddenGridView())
+    folder_delegate_->UpdateFolderViewBackground(false);
 
-  if (IsDraggingForReprentInHiddenGridView())
+  if (IsDraggingForReparentInHiddenGridView())
     dragging_for_reparent_item_ = false;
 }
 
@@ -824,8 +805,6 @@
   rect.set_y(rect.bottom() - page_switcher_height);
   rect.set_height(page_switcher_height);
   page_switcher_view_->SetBoundsRect(rect);
-
-  LayoutStartPage();
 }
 
 bool AppsGridView::OnKeyPressed(const ui::KeyEvent& event) {
@@ -902,9 +881,9 @@
 }
 
 void AppsGridView::UpdatePaging() {
-  int total_page = start_page_view_ ? 1 : 0;
-  if (view_model_.view_size() && tiles_per_page())
-    total_page += (view_model_.view_size() - 1) / tiles_per_page() + 1;
+  int total_page = view_model_.view_size() && tiles_per_page()
+                       ? (view_model_.view_size() - 1) / tiles_per_page() + 1
+                       : 0;
 
   pagination_model_->SetTotalPages(total_page);
 }
@@ -949,19 +928,11 @@
 
 AppsGridView::Index AppsGridView::GetIndexFromModelIndex(
     int model_index) const {
-  int page = model_index / tiles_per_page();
-  if (start_page_view_)
-    ++page;
-
-  return Index(page, model_index % tiles_per_page());
+  return Index(model_index / tiles_per_page(), model_index % tiles_per_page());
 }
 
 int AppsGridView::GetModelIndexFromIndex(const Index& index) const {
-  int model_index = index.page * tiles_per_page() + index.slot;
-  if (start_page_view_)
-    model_index -= tiles_per_page();
-
-  return model_index;
+  return index.page * tiles_per_page() + index.slot;
 }
 
 void AppsGridView::SetSelectedItemByIndex(const Index& index) {
@@ -983,11 +954,8 @@
 }
 
 bool AppsGridView::IsValidIndex(const Index& index) const {
-  const int item_page_start = start_page_view_ ? 1 : 0;
-  return index.page >= item_page_start &&
-         index.page < pagination_model_->total_pages() &&
-         index.slot >= 0 &&
-         index.slot < tiles_per_page() &&
+  return index.page >= 0 && index.page < pagination_model_->total_pages() &&
+         index.slot >= 0 && index.slot < tiles_per_page() &&
          GetModelIndexFromIndex(index) < view_model_.view_size();
 }
 
@@ -1304,10 +1272,9 @@
 }
 
 void AppsGridView::OnFolderItemReparentTimer() {
-  DCHECK(!is_root_level_);
+  DCHECK(folder_delegate_);
   if (drag_out_of_folder_container_) {
-    static_cast<AppListFolderView*>(parent())->ReparentItem(
-        drag_view_, last_drag_point_);
+    folder_delegate_->ReparentItem(drag_view_, last_drag_point_);
 
     // Set the flag in the folder's grid view.
     dragging_for_reparent_item_ = true;
@@ -1329,7 +1296,7 @@
   if (IsUnderOEMFolder())
     return;
 
-  if (IsDraggingForReprentInHiddenGridView()) {
+  if (IsDraggingForReparentInHiddenGridView()) {
     // Dispatch drag event to root level grid view for re-parenting folder
     // folder item purpose.
     DispatchDragEventForReparent(pointer, event);
@@ -1337,15 +1304,14 @@
   }
 
   // Regular drag and drop in a folder's grid view.
-  AppListFolderView* folder_view = static_cast<AppListFolderView*>(parent());
-  folder_view->UpdateFolderViewBackground(true);
+  folder_delegate_->UpdateFolderViewBackground(true);
 
   // Calculate if the drag_view_ is dragged out of the folder's container
   // ink bubble.
   gfx::Rect bounds_to_folder_view = ConvertRectToParent(drag_view_->bounds());
   gfx::Point pt = bounds_to_folder_view.CenterPoint();
   bool is_item_dragged_out_of_folder =
-      folder_view->IsPointOutsideOfFolderBoundray(pt);
+      folder_delegate_->IsPointOutsideOfFolderBoundary(pt);
   if (is_item_dragged_out_of_folder) {
     if (!drag_out_of_folder_container_) {
       folder_item_reparent_timer_.Start(FROM_HERE,
@@ -1360,11 +1326,11 @@
 }
 
 bool AppsGridView::IsDraggingForReparentInRootLevelGridView() const {
-  return (is_root_level_ && dragging_for_reparent_item_);
+  return (!folder_delegate_ && dragging_for_reparent_item_);
 }
 
-bool AppsGridView::IsDraggingForReprentInHiddenGridView() const {
-  return (!is_root_level_ && dragging_for_reparent_item_);
+bool AppsGridView::IsDraggingForReparentInHiddenGridView() const {
+  return (folder_delegate_ && dragging_for_reparent_item_);
 }
 
 gfx::Rect AppsGridView::GetTargetIconRectInFolder(
@@ -1381,17 +1347,16 @@
 }
 
 bool AppsGridView::IsUnderOEMFolder() {
-  if (is_root_level_)
+  if (!folder_delegate_)
     return false;
 
-  return static_cast<AppListFolderView*>(parent())->IsOEMFolder();
+  return folder_delegate_->IsOEMFolder();
 }
 
 void AppsGridView::DispatchDragEventForReparent(
     Pointer pointer,
     const ui::LocatedEvent& event) {
-  static_cast<AppListFolderView*>(parent())->
-      DispatchDragEventForReparent(pointer, event);
+  folder_delegate_->DispatchDragEventForReparent(pointer, event);
 }
 
 void AppsGridView::EndDragFromReparentItemInRootLevel(
@@ -1474,7 +1439,7 @@
 }
 
 void AppsGridView::OnFolderItemRemoved() {
-  DCHECK(!is_root_level_);
+  DCHECK(folder_delegate_);
   item_list_ = NULL;
 }
 
@@ -1829,29 +1794,6 @@
   }
 }
 
-void AppsGridView::LayoutStartPage() {
-  if (!start_page_view_)
-    return;
-
-  gfx::Rect start_page_bounds(GetLocalBounds());
-  start_page_bounds.set_height(start_page_bounds.height() -
-                               page_switcher_view_->height());
-
-  const int page_width = width() + kPagePadding;
-  const int current_page = pagination_model_->selected_page();
-  if (current_page > 0)
-    start_page_bounds.Offset(-page_width, 0);
-
-  const PaginationModel::Transition& transition =
-      pagination_model_->transition();
-  if (current_page == 0 || transition.target_page == 0) {
-    const int dir = transition.target_page > current_page ? -1 : 1;
-    start_page_bounds.Offset(transition.progress * page_width * dir, 0);
-  }
-
-  start_page_view_->SetBoundsRect(start_page_bounds);
-}
-
 void AppsGridView::OnListItemAdded(size_t index, AppListItem* item) {
   EndDrag(true);
 
@@ -1874,7 +1816,8 @@
 
   // If there is only one item left under the folder, remove the folder.
   // We do allow OEM folder to contain only one item.
-  if (!is_root_level_ && item_list_->item_count() == 1 && !IsUnderOEMFolder()) {
+  if (folder_delegate_ && item_list_->item_count() == 1 &&
+      !IsUnderOEMFolder()) {
     std::string folder_id = item_list_->item_at(0)->folder_id();
     // TODO(jennyz): Don't remove the folder if this is an OEM folder, this
     // depends on https://codereview.chromium.org/197403005/.
@@ -1955,8 +1898,8 @@
 bool AppsGridView::EnableFolderDragDropUI() {
   // Enable drag and drop folder UI only if it is at the app list root level
   // and the switch is on and the target folder can still accept new items.
-  return switches::IsFolderUIEnabled() && is_root_level_ &&
-      CanDropIntoTarget(drop_target_);
+  return switches::IsFolderUIEnabled() && !folder_delegate_ &&
+         CanDropIntoTarget(drop_target_);
 }
 
 bool AppsGridView::CanDropIntoTarget(const Index& drop_target) {
@@ -2129,7 +2072,7 @@
 
   for (int i = 0; i < view_model_.view_size(); ++i) {
     views::View* view = view_model_.view_at(i);
-    if (view->bounds() == tile_rect)
+    if (view->bounds() == tile_rect && view != drag_view_)
       return view;
   }
   return NULL;
diff --git a/ui/app_list/views/apps_grid_view.h b/ui/app_list/views/apps_grid_view.h
index 096730e..22d8bb1 100644
--- a/ui/app_list/views/apps_grid_view.h
+++ b/ui/app_list/views/apps_grid_view.h
@@ -51,6 +51,7 @@
 class ApplicationDragAndDropHost;
 class AppListItemView;
 class AppsGridViewDelegate;
+class AppsGridViewFolderDelegate;
 class PageSwitcher;
 class PaginationModel;
 
@@ -70,12 +71,9 @@
 
   // Constructs the app icon grid view. |delegate| is the delegate of this
   // view, which usually is the hosting AppListView. |pagination_model| is
-  // the paging info shared within the launcher UI. |start_page_contents| is
-  // the contents for the launcher start page. It could be NULL if the start
-  // page is not available.
+  // the paging info shared within the launcher UI.
   AppsGridView(AppsGridViewDelegate* delegate,
-               PaginationModel* pagination_model,
-               content::WebContents* start_page_contents);
+               PaginationModel* pagination_model);
   virtual ~AppsGridView();
 
   // Sets fixed layout parameters. After setting this, CalculateLayout below
@@ -199,7 +197,9 @@
     return forward_events_to_drag_and_drop_host_;
   }
 
-  void set_is_root_level(bool value) { is_root_level_ = value; }
+  void set_folder_delegate(AppsGridViewFolderDelegate* folder_delegate) {
+    folder_delegate_ = folder_delegate;
+  }
 
   AppListItemView* activated_item_view() const {
     return activated_item_view_;
@@ -343,9 +343,6 @@
   // buffer area surrounding it.
   bool IsPointWithinDragBuffer(const gfx::Point& point) const;
 
-  // Handles start page layout and transition animation.
-  void LayoutStartPage();
-
   // Overridden from views::ButtonListener:
   virtual void ButtonPressed(views::Button* sender,
                              const ui::Event& event) OVERRIDE;
@@ -433,7 +430,7 @@
 
   // Returns true if drag event is happening in the hidden AppsGridView of the
   // folder during reparenting a folder item.
-  bool IsDraggingForReprentInHiddenGridView() const;
+  bool IsDraggingForReparentInHiddenGridView() const;
 
   // Returns the target icon bounds for |drag_item_view| to fly back
   // to its parent |folder_item_view| in animation.
@@ -446,9 +443,12 @@
   AppListModel* model_;  // Owned by AppListView.
   AppListItemList* item_list_;  // Not owned.
   AppsGridViewDelegate* delegate_;
+
+  // This can be NULL. Only grid views inside folders have a folder delegate.
+  AppsGridViewFolderDelegate* folder_delegate_;
+
   PaginationModel* pagination_model_;  // Owned by AppListController.
   PageSwitcher* page_switcher_view_;  // Owned by views hierarchy.
-  views::WebView* start_page_view_;  // Owned by views hierarchy.
 
   gfx::Size icon_size_;
   int cols_;
@@ -521,9 +521,6 @@
 
   views::BoundsAnimator bounds_animator_;
 
-  // If true, AppsGridView is rending items at the root level of the app list.
-  bool is_root_level_;
-
   // The most recent activated item view.
   AppListItemView* activated_item_view_;
 
diff --git a/ui/app_list/views/apps_grid_view_folder_delegate.h b/ui/app_list/views/apps_grid_view_folder_delegate.h
new file mode 100644
index 0000000..60d8f5e
--- /dev/null
+++ b/ui/app_list/views/apps_grid_view_folder_delegate.h
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_APP_LIST_VIEWS_APPS_GRID_VIEW_FOLDER_DELEGATE_H_
+#define UI_APP_LIST_VIEWS_APPS_GRID_VIEW_FOLDER_DELEGATE_H_
+
+#include "ui/app_list/app_list_export.h"
+#include "ui/app_list/views/apps_grid_view.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace ui {
+class LocatedEvent;
+}
+
+namespace app_list {
+
+class AppListItemView;
+
+// A delegate which allows an AppsGridView to communicate with its host folder.
+class APP_LIST_EXPORT AppsGridViewFolderDelegate {
+ public:
+  // Updates the folder view background to show or hide folder container ink
+  // bubble.
+  virtual void UpdateFolderViewBackground(bool show_bubble) = 0;
+
+  // Called when a folder item is dragged out of the folder to be re-parented.
+  // |original_drag_view| is the |drag_view_| inside the folder's grid view.
+  // |drag_point_in_folder_grid| is the last drag point in coordinate of the
+  // AppsGridView inside the folder.
+  virtual void ReparentItem(AppListItemView* original_drag_view,
+                            const gfx::Point& drag_point_in_folder_grid) = 0;
+
+  // Dispatches drag event from the hidden grid view to the root level grid view
+  // for re-parenting a folder item.
+  virtual void DispatchDragEventForReparent(AppsGridView::Pointer pointer,
+                                            const ui::LocatedEvent& event) = 0;
+
+  // Dispatches EndDrag event from the hidden grid view to the root level grid
+  // view for reparenting a folder item.
+  // |events_forwarded_to_drag_drop_host|: True if the dragged item is dropped
+  // to the drag_drop_host, eg. dropped on shelf.
+  virtual void DispatchEndDragEventForReparent(
+      bool events_forwarded_to_drag_drop_host) = 0;
+
+  // Returns true if |point| falls outside of the folder container ink bubble.
+  virtual bool IsPointOutsideOfFolderBoundary(const gfx::Point& point) = 0;
+
+  // Returns true if the associated folder item is an OEM folder.
+  virtual bool IsOEMFolder() const = 0;
+
+ protected:
+  virtual ~AppsGridViewFolderDelegate() {}
+};
+
+}  // namespace app_list
+
+#endif  // UI_APP_LIST_VIEWS_APPS_GRID_VIEW_FOLDER_DELEGATE_H_
diff --git a/ui/app_list/views/apps_grid_view_unittest.cc b/ui/app_list/views/apps_grid_view_unittest.cc
index ed88983..313015a 100644
--- a/ui/app_list/views/apps_grid_view_unittest.cc
+++ b/ui/app_list/views/apps_grid_view_unittest.cc
@@ -14,12 +14,15 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/timer/timer.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/app_list/app_list_constants.h"
+#include "ui/app_list/app_list_folder_item.h"
 #include "ui/app_list/app_list_item.h"
 #include "ui/app_list/app_list_model.h"
 #include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/pagination_model.h"
 #include "ui/app_list/test/app_list_test_model.h"
 #include "ui/app_list/views/app_list_item_view.h"
+#include "ui/app_list/views/apps_grid_view_folder_delegate.h"
 #include "ui/app_list/views/test/apps_grid_view_test_api.h"
 #include "ui/views/test/views_test_base.h"
 
@@ -105,8 +108,7 @@
     model_.reset(new AppListTestModel);
     pagination_model_.reset(new PaginationModel);
 
-    apps_grid_view_.reset(
-        new AppsGridView(NULL, pagination_model_.get(), NULL));
+    apps_grid_view_.reset(new AppsGridView(NULL, pagination_model_.get()));
     apps_grid_view_->SetLayout(kIconDimension, kCols, kRows);
     apps_grid_view_->SetBoundsRect(gfx::Rect(gfx::Size(kWidth, kHeight)));
     apps_grid_view_->SetModel(model_.get());
@@ -179,6 +181,42 @@
   DISALLOW_COPY_AND_ASSIGN(AppsGridViewTest);
 };
 
+class TestAppsGridViewFolderDelegate : public AppsGridViewFolderDelegate {
+ public:
+  TestAppsGridViewFolderDelegate() : show_bubble_(false) {}
+  virtual ~TestAppsGridViewFolderDelegate() {}
+
+  // Overridden from AppsGridViewFolderDelegate:
+  virtual void UpdateFolderViewBackground(bool show_bubble) OVERRIDE {
+    show_bubble_ = show_bubble;
+  }
+
+  virtual void ReparentItem(AppListItemView* original_drag_view,
+                            const gfx::Point& drag_point_in_folder_grid)
+      OVERRIDE {}
+
+  virtual void DispatchDragEventForReparent(AppsGridView::Pointer pointer,
+                                            const ui::LocatedEvent& event)
+      OVERRIDE {}
+
+  virtual void DispatchEndDragEventForReparent(
+      bool events_forwarded_to_drag_drop_host) OVERRIDE {}
+
+  virtual bool IsPointOutsideOfFolderBoundary(const gfx::Point& point)
+      OVERRIDE {
+    return false;
+  }
+
+  virtual bool IsOEMFolder() const OVERRIDE { return false; }
+
+  bool show_bubble() { return show_bubble_; }
+
+ private:
+  bool show_bubble_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestAppsGridViewFolderDelegate);
+};
+
 TEST_F(AppsGridViewTest, CreatePage) {
   // Fully populates a page.
   const int kPages = 1;
@@ -271,6 +309,178 @@
   test_api_->LayoutToIdealBounds();
 }
 
+TEST_F(AppsGridViewTest, MouseDragItemIntoFolder) {
+  size_t kTotalItems = 3;
+  model_->PopulateApps(kTotalItems);
+  EXPECT_EQ(model_->top_level_item_list()->item_count(), kTotalItems);
+  EXPECT_EQ(std::string("Item 0,Item 1,Item 2"), model_->GetModelContent());
+
+  gfx::Point from = GetItemTileRectAt(0, 1).CenterPoint();
+  gfx::Point to = GetItemTileRectAt(0, 0).CenterPoint();
+
+  // Dragging item_1 over item_0 creates a folder.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  apps_grid_view_->EndDrag(false);
+  EXPECT_EQ(kTotalItems - 1, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(AppListFolderItem::kItemType,
+            model_->top_level_item_list()->item_at(0)->GetItemType());
+  AppListFolderItem* folder_item = static_cast<AppListFolderItem*>(
+      model_->top_level_item_list()->item_at(0));
+  EXPECT_EQ(2u, folder_item->ChildItemCount());
+  AppListItem* item_0 = model_->FindItem("Item 0");
+  EXPECT_TRUE(item_0->IsInFolder());
+  EXPECT_EQ(folder_item->id(), item_0->folder_id());
+  AppListItem* item_1 = model_->FindItem("Item 1");
+  EXPECT_TRUE(item_1->IsInFolder());
+  EXPECT_EQ(folder_item->id(), item_1->folder_id());
+  std::string expected_items = folder_item->id() + ",Item 2";
+  EXPECT_EQ(expected_items, model_->GetModelContent());
+  test_api_->LayoutToIdealBounds();
+
+  // Dragging item_2 to the folder adds item_2 to the folder.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  apps_grid_view_->EndDrag(false);
+
+  EXPECT_EQ(kTotalItems - 2, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(folder_item->id(), model_->GetModelContent());
+  EXPECT_EQ(3u, folder_item->ChildItemCount());
+  item_0 = model_->FindItem("Item 0");
+  EXPECT_TRUE(item_0->IsInFolder());
+  EXPECT_EQ(folder_item->id(), item_0->folder_id());
+  item_1 = model_->FindItem("Item 1");
+  EXPECT_TRUE(item_1->IsInFolder());
+  EXPECT_EQ(folder_item->id(), item_1->folder_id());
+  AppListItem* item_2 = model_->FindItem("Item 2");
+  EXPECT_TRUE(item_2->IsInFolder());
+  EXPECT_EQ(folder_item->id(), item_2->folder_id());
+  test_api_->LayoutToIdealBounds();
+}
+
+TEST_F(AppsGridViewTest, MouseDragMaxItemsInFolder) {
+  // Create and add a folder with 15 items in it.
+  size_t kTotalItems = kMaxFolderItems - 1;
+  model_->CreateAndPopulateFolderWithApps(kTotalItems);
+  EXPECT_EQ(1u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(AppListFolderItem::kItemType,
+            model_->top_level_item_list()->item_at(0)->GetItemType());
+  AppListFolderItem* folder_item = static_cast<AppListFolderItem*>(
+      model_->top_level_item_list()->item_at(0));
+  EXPECT_EQ(kTotalItems, folder_item->ChildItemCount());
+
+  // Create and add another 2 items.
+  model_->PopulateAppWithId(kTotalItems);
+  model_->PopulateAppWithId(kTotalItems + 1);
+  EXPECT_EQ(3u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(folder_item->id(), model_->top_level_item_list()->item_at(0)->id());
+  EXPECT_EQ(model_->GetItemName(kMaxFolderItems - 1),
+            model_->top_level_item_list()->item_at(1)->id());
+  EXPECT_EQ(model_->GetItemName(kMaxFolderItems),
+            model_->top_level_item_list()->item_at(2)->id());
+
+  gfx::Point from = GetItemTileRectAt(0, 1).CenterPoint();
+  gfx::Point to = GetItemTileRectAt(0, 0).CenterPoint();
+
+  // Dragging one item into the folder, the folder should accept the item.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  apps_grid_view_->EndDrag(false);
+  EXPECT_EQ(2u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(folder_item->id(), model_->top_level_item_list()->item_at(0)->id());
+  EXPECT_EQ(kMaxFolderItems, folder_item->ChildItemCount());
+  EXPECT_EQ(model_->GetItemName(kMaxFolderItems),
+            model_->top_level_item_list()->item_at(1)->id());
+  test_api_->LayoutToIdealBounds();
+
+  // Dragging the last item over the folder, the folder won't accept the new
+  // item, instead, it will re-order the items.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  apps_grid_view_->EndDrag(false);
+  EXPECT_EQ(2u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(model_->GetItemName(kMaxFolderItems),
+            model_->top_level_item_list()->item_at(0)->id());
+  EXPECT_EQ(folder_item->id(), model_->top_level_item_list()->item_at(1)->id());
+  EXPECT_EQ(kMaxFolderItems, folder_item->ChildItemCount());
+  test_api_->LayoutToIdealBounds();
+}
+
+TEST_F(AppsGridViewTest, MouseDragItemReorder) {
+  size_t kTotalItems = 2;
+  model_->PopulateApps(kTotalItems);
+  EXPECT_EQ(2u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(std::string("Item 0,Item 1"), model_->GetModelContent());
+
+  gfx::Point from = GetItemTileRectAt(0, 1).CenterPoint();
+  int reorder_offset = (GetItemTileRectAt(0, 1).CenterPoint() -
+                        GetItemTileRectAt(0, 0).CenterPoint()).Length() -
+                       kReorderDroppingCircleRadius -
+                       kPreferredIconDimension / 2 + 5;
+  gfx::Point to = gfx::Point(from.x() - reorder_offset, from.y());
+
+  // Dragging item_1 closing to item_0 should leads to re-ordering these two
+  // items.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  apps_grid_view_->EndDrag(false);
+  EXPECT_EQ(2u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(std::string("Item 1,Item 0"), model_->GetModelContent());
+  test_api_->LayoutToIdealBounds();
+}
+
+TEST_F(AppsGridViewTest, MouseDragFolderReorder) {
+  size_t kTotalItems = 2;
+  model_->CreateAndPopulateFolderWithApps(kTotalItems);
+  model_->PopulateAppWithId(kTotalItems);
+  EXPECT_EQ(2u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ(AppListFolderItem::kItemType,
+            model_->top_level_item_list()->item_at(0)->GetItemType());
+  AppListFolderItem* folder_item = static_cast<AppListFolderItem*>(
+      model_->top_level_item_list()->item_at(0));
+  EXPECT_EQ("Item 2", model_->top_level_item_list()->item_at(1)->id());
+
+  gfx::Point from = GetItemTileRectAt(0, 0).CenterPoint();
+  gfx::Point to = GetItemTileRectAt(0, 1).CenterPoint();
+
+  // Dragging folder over item_1 should leads to re-ordering these two
+  // items.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  apps_grid_view_->EndDrag(false);
+  EXPECT_EQ(2u, model_->top_level_item_list()->item_count());
+  EXPECT_EQ("Item 2", model_->top_level_item_list()->item_at(0)->id());
+  EXPECT_EQ(folder_item->id(), model_->top_level_item_list()->item_at(1)->id());
+  test_api_->LayoutToIdealBounds();
+}
+
+TEST_F(AppsGridViewTest, MouseDragWithCancelDeleteAddItem) {
+  size_t kTotalItems = 4;
+  model_->PopulateApps(kTotalItems);
+  EXPECT_EQ(model_->top_level_item_list()->item_count(), kTotalItems);
+  EXPECT_EQ(std::string("Item 0,Item 1,Item 2,Item 3"),
+            model_->GetModelContent());
+
+  gfx::Point from = GetItemTileRectAt(0, 0).CenterPoint();
+  gfx::Point to = GetItemTileRectAt(0, 1).CenterPoint();
+
+  // Canceling drag should keep existing order.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  apps_grid_view_->EndDrag(true);
+  EXPECT_EQ(std::string("Item 0,Item 1,Item 2,Item 3"),
+            model_->GetModelContent());
+  test_api_->LayoutToIdealBounds();
+
+  // Deleting an item keeps remaining intact.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  model_->DeleteItem(model_->GetItemName(2));
+  apps_grid_view_->EndDrag(false);
+  EXPECT_EQ(std::string("Item 0,Item 1,Item 3"), model_->GetModelContent());
+  test_api_->LayoutToIdealBounds();
+
+  // Adding a launcher item cancels the drag and respects the order.
+  SimulateDrag(AppsGridView::MOUSE, from, to);
+  model_->CreateAndAddItem("Extra");
+  apps_grid_view_->EndDrag(false);
+  EXPECT_EQ(std::string("Item 0,Item 1,Item 3,Extra"),
+            model_->GetModelContent());
+  test_api_->LayoutToIdealBounds();
+}
+
 TEST_F(AppsGridViewTest, MouseDragFlipPage) {
   test_api_->SetPageFlipDelay(10);
   pagination_model_->SetTransitionDurations(10, 10);
@@ -352,6 +562,26 @@
   test_api_->LayoutToIdealBounds();
 }
 
+TEST_F(AppsGridViewTest, UpdateFolderBackgroundOnCancelDrag) {
+  const int kTotalItems = 4;
+  TestAppsGridViewFolderDelegate folder_delegate;
+  apps_grid_view_->set_folder_delegate(&folder_delegate);
+  model_->PopulateApps(kTotalItems);
+  EXPECT_EQ(std::string("Item 0,Item 1,Item 2,Item 3"),
+            model_->GetModelContent());
+
+  gfx::Point mouse_from = GetItemTileRectAt(0, 0).CenterPoint();
+  gfx::Point mouse_to = GetItemTileRectAt(0, 1).CenterPoint();
+
+  // Starts a mouse drag and then cancels it.
+  SimulateDrag(AppsGridView::MOUSE, mouse_from, mouse_to);
+  EXPECT_TRUE(folder_delegate.show_bubble());
+  apps_grid_view_->EndDrag(true);
+  EXPECT_FALSE(folder_delegate.show_bubble());
+  EXPECT_EQ(std::string("Item 0,Item 1,Item 2,Item 3"),
+            model_->GetModelContent());
+}
+
 TEST_F(AppsGridViewTest, HighlightWithKeyboard) {
   const int kPages = 3;
   const int kItems = (kPages - 1) * kTilesPerPage + 1;
diff --git a/ui/app_list/views/contents_view.cc b/ui/app_list/views/contents_view.cc
index 0121cf6..60968c3 100644
--- a/ui/app_list/views/contents_view.cc
+++ b/ui/app_list/views/contents_view.cc
@@ -11,6 +11,7 @@
 #include "ui/app_list/app_list_switches.h"
 #include "ui/app_list/app_list_view_delegate.h"
 #include "ui/app_list/pagination_model.h"
+#include "ui/app_list/views/app_list_folder_view.h"
 #include "ui/app_list/views/app_list_main_view.h"
 #include "ui/app_list/views/apps_container_view.h"
 #include "ui/app_list/views/apps_grid_view.h"
@@ -58,10 +59,8 @@
       kPageTransitionDurationInMs,
       kOverscrollPageTransitionDurationMs);
 
-  content::WebContents* start_page_contents =
-      view_delegate ? view_delegate->GetStartPageContents() : NULL;
-  apps_container_view_ = new AppsContainerView(
-      app_list_main_view, pagination_model, model, start_page_contents);
+  apps_container_view_ =
+      new AppsContainerView(app_list_main_view, pagination_model, model);
   AddChildView(apps_container_view_);
   view_model_->Add(apps_container_view_, kIndexAppsContainer);
 
@@ -79,6 +78,12 @@
 void ContentsView::CancelDrag() {
   if (apps_container_view_->apps_grid_view()->has_dragged_view())
     apps_container_view_->apps_grid_view()->EndDrag(true);
+  if (apps_container_view_->app_list_folder_view()
+          ->items_grid_view()
+          ->has_dragged_view()) {
+    apps_container_view_->app_list_folder_view()->items_grid_view()->EndDrag(
+        true);
+  }
 }
 
 void ContentsView::SetDragAndDropHostOfCurrentAppList(
diff --git a/ui/app_list/views/folder_header_view.cc b/ui/app_list/views/folder_header_view.cc
index 9819b34..7a2c0f2 100644
--- a/ui/app_list/views/folder_header_view.cc
+++ b/ui/app_list/views/folder_header_view.cc
@@ -47,6 +47,12 @@
   virtual ~FolderNameView() {
   }
 
+  void Update() {
+    SetBackgroundColor(text().size() <= kMaxFolderNameChars
+                           ? kContentsBackgroundColor
+                           : SK_ColorRED);
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(FolderNameView);
 };
@@ -91,8 +97,9 @@
     return;
   folder_item_->AddObserver(this);
 
-  folder_name_view_->SetEnabled(folder_item->folder_type() !=
+  folder_name_view_->SetEnabled(folder_item_->folder_type() !=
                                 AppListFolderItem::FOLDER_TYPE_OEM);
+
   Update();
 }
 
@@ -111,12 +118,26 @@
     return;
 
   folder_name_view_->SetVisible(folder_name_visible_);
-  if (folder_name_visible_)
+  if (folder_name_visible_) {
     folder_name_view_->SetText(base::UTF8ToUTF16(folder_item_->name()));
+    folder_name_view_->Update();
+  }
 
   Layout();
 }
 
+const base::string16& FolderHeaderView::GetFolderNameForTest() {
+  return folder_name_view_->text();
+}
+
+void FolderHeaderView::SetFolderNameForTest(const base::string16& name) {
+  folder_name_view_->SetText(name);
+}
+
+bool FolderHeaderView::IsFolderNameEnabledForTest() const {
+  return folder_name_view_->enabled();
+}
+
 gfx::Size FolderHeaderView::GetPreferredSize() {
   return gfx::Size(kPreferredWidth, kPreferredHeight);
 }
@@ -172,9 +193,13 @@
   if (!folder_item_)
     return;
 
+  folder_name_view_->Update();
   folder_item_->RemoveObserver(this);
-  std::string name = base::UTF16ToUTF8(folder_name_view_->text());
-  delegate_->SetItemName(folder_item_, name);
+  // Enforce the maximum folder name length in UI.
+  std::string name = base::UTF16ToUTF8(
+      folder_name_view_->text().substr(0, kMaxFolderNameChars));
+  if (name != folder_item_->name())
+    delegate_->SetItemName(folder_item_, name);
   folder_item_->AddObserver(this);
 
   Layout();
diff --git a/ui/app_list/views/folder_header_view.h b/ui/app_list/views/folder_header_view.h
index 6b1ca12..109c39a 100644
--- a/ui/app_list/views/folder_header_view.h
+++ b/ui/app_list/views/folder_header_view.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "ui/app_list/app_list_export.h"
 #include "ui/app_list/app_list_item_observer.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/textfield/textfield_controller.h"
@@ -22,11 +23,15 @@
 class AppListFolderView;
 class FolderHeaderViewDelegate;
 
+namespace test {
+class FolderHeaderViewTest;
+}
+
 // FolderHeaderView contains a back button and an editable folder name field.
-class FolderHeaderView : public views::View,
-                         public views::TextfieldController,
-                         public views::ButtonListener,
-                         public AppListItemObserver {
+class APP_LIST_EXPORT FolderHeaderView : public views::View,
+                                         public views::TextfieldController,
+                                         public views::ButtonListener,
+                                         public AppListItemObserver {
  public:
   explicit FolderHeaderView(FolderHeaderViewDelegate* delegate);
   virtual ~FolderHeaderView();
@@ -40,10 +45,18 @@
 
  private:
   class FolderNameView;
+  friend class test::FolderHeaderViewTest;
 
   // Updates UI.
   void Update();
 
+  // Gets and sets the folder name for test.
+  const base::string16& GetFolderNameForTest();
+  void SetFolderNameForTest(const base::string16& name);
+
+  // Returns true if folder name is enabled, only for testing use.
+  bool IsFolderNameEnabledForTest() const;
+
   // views::View overrides:
   virtual void Layout() OVERRIDE;
   virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
diff --git a/ui/app_list/views/folder_header_view_delegate.h b/ui/app_list/views/folder_header_view_delegate.h
index 982920e..639b7fc 100644
--- a/ui/app_list/views/folder_header_view_delegate.h
+++ b/ui/app_list/views/folder_header_view_delegate.h
@@ -25,7 +25,6 @@
   virtual void SetItemName(AppListFolderItem* item,
                            const std::string& name) = 0;
 
- protected:
   virtual ~FolderHeaderViewDelegate() {}
 };
 
diff --git a/ui/app_list/views/folder_header_view_unittest.cc b/ui/app_list/views/folder_header_view_unittest.cc
new file mode 100644
index 0000000..14e162f
--- /dev/null
+++ b/ui/app_list/views/folder_header_view_unittest.cc
@@ -0,0 +1,136 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/app_list/views/folder_header_view.h"
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/app_list/app_list_constants.h"
+#include "ui/app_list/app_list_folder_item.h"
+#include "ui/app_list/app_list_item.h"
+#include "ui/app_list/app_list_model.h"
+#include "ui/app_list/test/app_list_test_model.h"
+#include "ui/app_list/views/folder_header_view_delegate.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace app_list {
+namespace test {
+
+namespace {
+
+class TestFolderHeaderViewDelegate : public FolderHeaderViewDelegate {
+ public:
+  TestFolderHeaderViewDelegate() {}
+  virtual ~TestFolderHeaderViewDelegate() {}
+
+  // FolderHeaderViewDelegate
+  virtual void NavigateBack(AppListFolderItem* item,
+                            const ui::Event& event_flags) OVERRIDE {}
+
+  virtual void GiveBackFocusToSearchBox() OVERRIDE {}
+
+  virtual void SetItemName(AppListFolderItem* item,
+                           const std::string& name) OVERRIDE {
+    folder_name_ = name;
+  }
+
+  const std::string& folder_name() const { return folder_name_; }
+
+ private:
+  std::string folder_name_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestFolderHeaderViewDelegate);
+};
+
+}  // namespace
+
+class FolderHeaderViewTest : public views::ViewsTestBase {
+ public:
+  FolderHeaderViewTest() {}
+  virtual ~FolderHeaderViewTest() {}
+
+  // testing::Test overrides:
+  virtual void SetUp() OVERRIDE {
+    views::ViewsTestBase::SetUp();
+    model_.reset(new AppListTestModel);
+
+    delegate_.reset(new TestFolderHeaderViewDelegate);
+    folder_header_view_.reset(new FolderHeaderView(delegate_.get()));
+  }
+
+  virtual void TearDown() OVERRIDE {
+    folder_header_view_.reset();  // Release apps grid view before models.
+    delegate_.reset();
+    views::ViewsTestBase::TearDown();
+  }
+
+ protected:
+  void UpdateFolderName(const std::string& name) {
+    base::string16 folder_name = base::UTF8ToUTF16(name);
+    folder_header_view_->SetFolderNameForTest(folder_name);
+    folder_header_view_->ContentsChanged(NULL, folder_name);
+  }
+
+  const std::string GetFolderNameFromUI() {
+    return base::UTF16ToUTF8(folder_header_view_->GetFolderNameForTest());
+  }
+
+  bool CanEditFolderName() {
+    return folder_header_view_->IsFolderNameEnabledForTest();
+  }
+
+  scoped_ptr<AppListTestModel> model_;
+  scoped_ptr<FolderHeaderView> folder_header_view_;
+  scoped_ptr<TestFolderHeaderViewDelegate> delegate_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(FolderHeaderViewTest);
+};
+
+TEST_F(FolderHeaderViewTest, SetFolderName) {
+  // Creating a folder with empty folder name.
+  AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
+  folder_header_view_->SetFolderItem(folder_item);
+  EXPECT_EQ("", GetFolderNameFromUI());
+  EXPECT_TRUE(CanEditFolderName());
+
+  // Update UI to set folder name to "test folder".
+  UpdateFolderName("test folder");
+  EXPECT_EQ("test folder", delegate_->folder_name());
+}
+
+TEST_F(FolderHeaderViewTest, MaxFoldernNameLength) {
+  // Creating a folder with empty folder name.
+  AppListFolderItem* folder_item = model_->CreateAndPopulateFolderWithApps(2);
+  folder_header_view_->SetFolderItem(folder_item);
+  EXPECT_EQ("", GetFolderNameFromUI());
+  EXPECT_TRUE(CanEditFolderName());
+
+  // Update UI to set folder name to really long one beyond its maxium limit,
+  // The folder name should be trucated to the maximum length.
+  std::string max_len_name;
+  for (size_t i = 0; i < kMaxFolderNameChars; ++i)
+    max_len_name += "a";
+  UpdateFolderName(max_len_name);
+  EXPECT_EQ(max_len_name, delegate_->folder_name());
+  std::string too_long_name = max_len_name + "a";
+  UpdateFolderName(too_long_name);
+  EXPECT_EQ(max_len_name, delegate_->folder_name());
+}
+
+TEST_F(FolderHeaderViewTest, OemFolderNameNotEditable) {
+  AppListFolderItem* folder_item = model_->CreateAndAddOemFolder("oem folder");
+  folder_header_view_->SetFolderItem(folder_item);
+  EXPECT_EQ("", GetFolderNameFromUI());
+  EXPECT_FALSE(CanEditFolderName());
+}
+
+}  // namespace test
+}  // namespace app_list
diff --git a/ui/aura/aura.gyp b/ui/aura/aura.gyp
index cc94586..6bf7b2e 100644
--- a/ui/aura/aura.gyp
+++ b/ui/aura/aura.gyp
@@ -27,14 +27,6 @@
         'AURA_IMPLEMENTATION',
       ],
       'sources': [
-        'client/activation_change_observer.h',
-        'client/activation_change_observer.cc',
-        'client/activation_client.cc',
-        'client/activation_client.h',
-        'client/activation_delegate.cc',
-        'client/activation_delegate.h',
-        'client/animation_host.cc',
-        'client/animation_host.h',
         'client/aura_constants.cc',
         'client/aura_constants.h',
         'client/capture_client.cc',
@@ -48,30 +40,16 @@
         'client/default_activation_client.h',
         'client/default_capture_client.cc',
         'client/default_capture_client.h',
-        'client/dispatcher_client.cc',
-        'client/dispatcher_client.h',
-        'client/drag_drop_client.cc',
-        'client/drag_drop_client.h',
-        'client/drag_drop_delegate.cc',
-        'client/drag_drop_delegate.h',
         'client/event_client.cc',
         'client/event_client.h',
         'client/focus_change_observer.cc',
         'client/focus_change_observer.h',
         'client/focus_client.cc',
         'client/focus_client.h',
-        'client/scoped_tooltip_disabler.cc',
-        'client/scoped_tooltip_disabler.h',
         'client/screen_position_client.cc',
         'client/screen_position_client.h',
-        'client/tooltip_client.cc',
-        'client/tooltip_client.h',
-        'client/transient_window_client.cc',
-        'client/transient_window_client.h',
         'client/visibility_client.cc',
         'client/visibility_client.h',
-        'client/window_move_client.cc',
-        'client/window_move_client.h',
         'client/window_stacking_client.cc',
         'client/window_stacking_client.h',
         'client/window_tree_client.cc',
@@ -114,6 +92,28 @@
         'window_tree_host_win.h',
         'window_tree_host_x11.cc',
         'window_tree_host_x11.h',
+        '../wm/public/activation_change_observer.h',
+        '../wm/public/activation_change_observer.cc',
+        '../wm/public/activation_client.cc',
+        '../wm/public/activation_client.h',
+        '../wm/public/activation_delegate.cc',
+        '../wm/public/activation_delegate.h',
+        '../wm/public/animation_host.cc',
+        '../wm/public/animation_host.h',
+        '../wm/public/dispatcher_client.cc',
+        '../wm/public/dispatcher_client.h',
+        '../wm/public/drag_drop_client.cc',
+        '../wm/public/drag_drop_client.h',
+        '../wm/public/drag_drop_delegate.cc',
+        '../wm/public/drag_drop_delegate.h',
+        '../wm/public/scoped_tooltip_disabler.cc',
+        '../wm/public/scoped_tooltip_disabler.h',
+        '../wm/public/tooltip_client.cc',
+        '../wm/public/tooltip_client.h',
+        '../wm/public/transient_window_client.cc',
+        '../wm/public/transient_window_client.h',
+        '../wm/public/window_move_client.cc',
+        '../wm/public/window_move_client.h',
       ],
       'conditions': [
         ['use_x11==1', {
diff --git a/ui/aura/client/activation_change_observer.cc b/ui/aura/client/activation_change_observer.cc
deleted file mode 100644
index db9f332..0000000
--- a/ui/aura/client/activation_change_observer.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/activation_change_observer.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationChangeObserver*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
-    ActivationChangeObserver*, kActivationChangeObserverKey, NULL);
-
-void SetActivationChangeObserver(
-    Window* window,
-    ActivationChangeObserver* observer) {
-  window->SetProperty(kActivationChangeObserverKey, observer);
-}
-
-ActivationChangeObserver* GetActivationChangeObserver(Window* window) {
-  return window ? window->GetProperty(kActivationChangeObserverKey) : NULL;
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/activation_change_observer.h b/ui/aura/client/activation_change_observer.h
deleted file mode 100644
index 2f247db..0000000
--- a/ui/aura/client/activation_change_observer.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ACTIVATION_CHANGE_OBSERVER_H_
-#define UI_AURA_CLIENT_ACTIVATION_CHANGE_OBSERVER_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace aura {
-class Window;
-
-namespace client {
-
-class AURA_EXPORT ActivationChangeObserver {
- public:
-  // Called when |active| gains focus, or there is no active window
-  // (|active| is NULL in this case.) |old_active| refers to the
-  // previous active window or NULL if there was no previously active
-  // window.
-  virtual void OnWindowActivated(Window* gained_active,
-                                 Window* lost_active) = 0;
-
-  // Called when during window activation the currently active window is
-  // selected for activation. This can happen when a window requested for
-  // activation cannot be activated because a system modal window is active.
-  virtual void OnAttemptToReactivateWindow(aura::Window* request_active,
-                                           aura::Window* actual_active) {}
-
- protected:
-  virtual ~ActivationChangeObserver() {}
-};
-
-// Gets/Sets the ActivationChangeObserver for a specific window. This observer
-// is notified after the ActivationClient notifies all registered observers.
-AURA_EXPORT void SetActivationChangeObserver(
-    Window* window,
-    ActivationChangeObserver* observer);
-AURA_EXPORT ActivationChangeObserver* GetActivationChangeObserver(
-    Window* window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_ACTIVATION_CHANGE_OBSERVER_H_
diff --git a/ui/aura/client/activation_client.cc b/ui/aura/client/activation_client.cc
deleted file mode 100644
index 71d079b..0000000
--- a/ui/aura/client/activation_client.cc
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/activation_client.h"
-
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationClient*)
-
-namespace aura {
-namespace client {
-
-DEFINE_WINDOW_PROPERTY_KEY(
-    ActivationClient*, kRootWindowActivationClientKey, NULL);
-DEFINE_WINDOW_PROPERTY_KEY(bool, kHideOnDeactivate, false);
-
-void SetActivationClient(Window* root_window, ActivationClient* client) {
-  root_window->SetProperty(kRootWindowActivationClientKey, client);
-}
-
-ActivationClient* GetActivationClient(Window* root_window) {
-  return root_window ?
-      root_window->GetProperty(kRootWindowActivationClientKey) : NULL;
-}
-
-void SetHideOnDeactivate(Window* window, bool hide_on_deactivate) {
-  window->SetProperty(kHideOnDeactivate, hide_on_deactivate);
-}
-
-bool GetHideOnDeactivate(Window* window) {
-  return window->GetProperty(kHideOnDeactivate);
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/activation_client.h b/ui/aura/client/activation_client.h
deleted file mode 100644
index 054829e..0000000
--- a/ui/aura/client/activation_client.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
-#define UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace ui {
-class Event;
-}
-
-namespace aura {
-class Window;
-
-namespace client {
-class ActivationChangeObserver;
-
-// An interface implemented by an object that manages window activation.
-class AURA_EXPORT ActivationClient {
- public:
-  // Adds/Removes ActivationChangeObservers.
-  virtual void AddObserver(ActivationChangeObserver* observer) = 0;
-  virtual void RemoveObserver(ActivationChangeObserver* observer) = 0;
-
-  // Activates |window|. If |window| is NULL, nothing happens.
-  virtual void ActivateWindow(Window* window) = 0;
-
-  // Deactivates |window|. What (if anything) is activated next is up to the
-  // client. If |window| is NULL, nothing happens.
-  virtual void DeactivateWindow(Window* window) = 0;
-
-  // Retrieves the active window, or NULL if there is none.
-  virtual Window* GetActiveWindow() = 0;
-
-  // Retrieves the activatable window for |window|, or NULL if there is none.
-  // Note that this is often but not always the toplevel window (see
-  // GetToplevelWindow() below), as the toplevel window may not be activatable
-  // (for example it may be blocked by a modal transient, or some other
-  // condition).
-  virtual Window* GetActivatableWindow(Window* window) = 0;
-
-  // Retrieves the toplevel window for |window|, or NULL if there is none.
-  virtual Window* GetToplevelWindow(Window* window) = 0;
-
-  // Invoked prior to |window| getting focus as a result of the |event|. |event|
-  // may be NULL. Returning false blocks |window| from getting focus.
-  virtual bool OnWillFocusWindow(Window* window, const ui::Event* event) = 0;
-
-  // Returns true if |window| can be activated, false otherwise. If |window| has
-  // a modal child it can not be activated.
-  virtual bool CanActivateWindow(Window* window) const = 0;
-
- protected:
-  virtual ~ActivationClient() {}
-};
-
-// Sets/Gets the activation client on the root Window.
-AURA_EXPORT void SetActivationClient(Window* root_window,
-                                     ActivationClient* client);
-AURA_EXPORT ActivationClient* GetActivationClient(Window* root_window);
-
-// Some types of transient window are only visible when active.
-// The transient parents of these windows may have visual appearance properties
-// that differ from transient parents that can be deactivated.
-// The presence of this property implies these traits.
-// TODO(beng): currently the UI framework (views) implements the actual
-//             close-on-deactivate component of this feature but it should be
-//             possible to implement in the aura client.
-AURA_EXPORT void SetHideOnDeactivate(Window* window, bool hide_on_deactivate);
-AURA_EXPORT bool GetHideOnDeactivate(Window* window);
-
-}  // namespace clients
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_ACTIVATION_CLIENT_H_
diff --git a/ui/aura/client/activation_delegate.cc b/ui/aura/client/activation_delegate.cc
deleted file mode 100644
index 51b22b0..0000000
--- a/ui/aura/client/activation_delegate.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/activation_delegate.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationDelegate*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
-    ActivationDelegate*, kActivationDelegateKey, NULL);
-
-void SetActivationDelegate(Window* window, ActivationDelegate* delegate) {
-  window->SetProperty(kActivationDelegateKey, delegate);
-}
-
-ActivationDelegate* GetActivationDelegate(Window* window) {
-  return window->GetProperty(kActivationDelegateKey);
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/activation_delegate.h b/ui/aura/client/activation_delegate.h
deleted file mode 100644
index 0ce8638..0000000
--- a/ui/aura/client/activation_delegate.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
-#define UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace ui {
-class Event;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// An interface implemented by an object that configures and responds to changes
-// to a window's activation state.
-class AURA_EXPORT ActivationDelegate {
- public:
-  // Returns true if the window should be activated.
-  virtual bool ShouldActivate() const = 0;
-
- protected:
-  virtual ~ActivationDelegate() {}
-};
-
-// Sets/Gets the ActivationDelegate on the Window. No ownership changes.
-AURA_EXPORT void SetActivationDelegate(Window* window,
-                                       ActivationDelegate* delegate);
-AURA_EXPORT ActivationDelegate* GetActivationDelegate(Window* window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_ACTIVATION_DELEGATE_H_
diff --git a/ui/aura/client/animation_host.cc b/ui/aura/client/animation_host.cc
deleted file mode 100644
index 0afe583..0000000
--- a/ui/aura/client/animation_host.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/animation_host.h"
-
-#include "base/compiler_specific.h"
-#include "ui/aura/aura_export.h"
-
-#include "ui/aura/env.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::AnimationHost*)
-
-namespace aura {
-namespace client {
-
-DEFINE_WINDOW_PROPERTY_KEY(AnimationHost*, kRootWindowAnimationHostKey, NULL);
-
-void SetAnimationHost(Window* window, AnimationHost* animation_host) {
-  DCHECK(window);
-  window->SetProperty(kRootWindowAnimationHostKey, animation_host);
-}
-
-AnimationHost* GetAnimationHost(Window* window) {
-  DCHECK(window);
-  return window->GetProperty(kRootWindowAnimationHostKey);
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/animation_host.h b/ui/aura/client/animation_host.h
deleted file mode 100644
index c433b6d..0000000
--- a/ui/aura/client/animation_host.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_ANIMATION_HOST_H_
-#define UI_AURA_CLIENT_ANIMATION_HOST_H_
-
-#include "base/compiler_specific.h"
-#include "ui/aura/aura_export.h"
-
-namespace gfx {
-class Vector2d;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// Interface for top level window host of animation. Communicates additional
-// bounds required for animation as well as animation completion for deferring
-// window closes on hide.
-class AURA_EXPORT AnimationHost {
- public:
-  // Ensure the host window is at least this large so that transitions have
-  // sufficient space.
-  // The |top_left_delta| parameter contains the offset to be subtracted from
-  // the window bounds for the top left corner.
-  // The |bottom_right_delta| parameter contains the offset to be added to the
-  // window bounds for the bottom right.
-  virtual void SetHostTransitionOffsets(
-      const gfx::Vector2d& top_left_delta,
-      const gfx::Vector2d& bottom_right_delta) = 0;
-
-  // Called after the window has faded out on a hide.
-  virtual void OnWindowHidingAnimationCompleted() = 0;
-
- protected:
-  virtual ~AnimationHost() {}
-};
-
-AURA_EXPORT void SetAnimationHost(Window* window,
-                                  AnimationHost* animation_host);
-AURA_EXPORT AnimationHost* GetAnimationHost(Window* window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_ANIMATION_HOST_H_
diff --git a/ui/aura/client/default_activation_client.cc b/ui/aura/client/default_activation_client.cc
index ccb660b..b11d7bf 100644
--- a/ui/aura/client/default_activation_client.cc
+++ b/ui/aura/client/default_activation_client.cc
@@ -4,9 +4,9 @@
 
 #include "ui/aura/client/default_activation_client.h"
 
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
 #include "ui/aura/window.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace aura {
 namespace client {
diff --git a/ui/aura/client/default_activation_client.h b/ui/aura/client/default_activation_client.h
index 842ee90..47e19db 100644
--- a/ui/aura/client/default_activation_client.h
+++ b/ui/aura/client/default_activation_client.h
@@ -11,8 +11,8 @@
 #include "base/logging.h"
 #include "base/observer_list.h"
 #include "ui/aura/aura_export.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window_observer.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace aura {
 namespace client {
diff --git a/ui/aura/client/dispatcher_client.cc b/ui/aura/client/dispatcher_client.cc
deleted file mode 100644
index 55eda0e..0000000
--- a/ui/aura/client/dispatcher_client.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/dispatcher_client.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DispatcherClient*);
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(DispatcherClient*, kDispatcherClientKey, NULL);
-
-void SetDispatcherClient(Window* root_window, DispatcherClient* client) {
-  DCHECK_EQ(root_window->GetRootWindow(), root_window);
-  root_window->SetProperty(kDispatcherClientKey, client);
-}
-
-DispatcherClient* GetDispatcherClient(Window* root_window) {
-  if (root_window)
-    DCHECK_EQ(root_window->GetRootWindow(), root_window);
-  return root_window ? root_window->GetProperty(kDispatcherClientKey) : NULL;
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/dispatcher_client.h b/ui/aura/client/dispatcher_client.h
deleted file mode 100644
index 42cb25e..0000000
--- a/ui/aura/client/dispatcher_client.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
-#define UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
-
-#include "base/message_loop/message_pump_dispatcher.h"
-#include "ui/aura/aura_export.h"
-
-namespace aura {
-class Window;
-namespace client {
-
-// An interface implemented by an object which handles nested dispatchers.
-class AURA_EXPORT DispatcherClient {
- public:
-  virtual void RunWithDispatcher(base::MessagePumpDispatcher* dispatcher) = 0;
-
-  virtual void QuitNestedMessageLoop() = 0;
-};
-
-AURA_EXPORT void SetDispatcherClient(Window* root_window,
-                                     DispatcherClient* client);
-AURA_EXPORT DispatcherClient* GetDispatcherClient(Window* root_window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_DISPATCHER_CLIENT_H_
diff --git a/ui/aura/client/drag_drop_client.cc b/ui/aura/client/drag_drop_client.cc
deleted file mode 100644
index 56050e8..0000000
--- a/ui/aura/client/drag_drop_client.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/drag_drop_client.h"
-
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DragDropClient*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
-    DragDropClient*, kRootWindowDragDropClientKey, NULL);
-
-void SetDragDropClient(Window* root_window, DragDropClient* client) {
-  DCHECK_EQ(root_window->GetRootWindow(), root_window);
-  root_window->SetProperty(kRootWindowDragDropClientKey, client);
-}
-
-DragDropClient* GetDragDropClient(Window* root_window) {
-  if (root_window)
-    DCHECK_EQ(root_window->GetRootWindow(), root_window);
-  return root_window ?
-      root_window->GetProperty(kRootWindowDragDropClientKey) : NULL;
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/drag_drop_client.h b/ui/aura/client/drag_drop_client.h
deleted file mode 100644
index 7277d6b..0000000
--- a/ui/aura/client/drag_drop_client.h
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_DRAG_DROP_CLIENT_H_
-#define UI_AURA_CLIENT_DRAG_DROP_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-#include "ui/base/dragdrop/drag_drop_types.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace ui {
-class LocatedEvent;
-class OSExchangeData;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// An interface implemented by an object that controls a drag and drop session.
-class AURA_EXPORT DragDropClient {
- public:
-  virtual ~DragDropClient() {}
-
-  // Initiates a drag and drop session. Returns the drag operation that was
-  // applied at the end of the drag drop session. |root_location| is in the
-  // root Window's coordinate system.
-  virtual int StartDragAndDrop(const ui::OSExchangeData& data,
-                               aura::Window* root_window,
-                               aura::Window* source_window,
-                               const gfx::Point& root_location,
-                               int operation,
-                               ui::DragDropTypes::DragEventSource source) = 0;
-
-  // Called when mouse is dragged during a drag and drop.
-  virtual void DragUpdate(aura::Window* target,
-                          const ui::LocatedEvent& event) = 0;
-
-  // Called when mouse is released during a drag and drop.
-  virtual void Drop(aura::Window* target,
-                    const ui::LocatedEvent& event) = 0;
-
-  // Called when a drag and drop session is cancelled.
-  virtual void DragCancel() = 0;
-
-  // Returns true if a drag and drop session is in progress.
-  virtual bool IsDragDropInProgress() = 0;
-};
-
-AURA_EXPORT void SetDragDropClient(Window* root_window,
-                                   DragDropClient* client);
-AURA_EXPORT DragDropClient* GetDragDropClient(Window* root_window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_DRAG_DROP_CLIENT_H_
diff --git a/ui/aura/client/drag_drop_delegate.cc b/ui/aura/client/drag_drop_delegate.cc
deleted file mode 100644
index 92d986b..0000000
--- a/ui/aura/client/drag_drop_delegate.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/drag_drop_delegate.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DragDropDelegate*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
-    DragDropDelegate*, kDragDropDelegateKey, NULL);
-
-void SetDragDropDelegate(Window* window, DragDropDelegate* delegate) {
-  window->SetProperty(kDragDropDelegateKey, delegate);
-}
-
-DragDropDelegate* GetDragDropDelegate(Window* window) {
-  return window->GetProperty(kDragDropDelegateKey);
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/drag_drop_delegate.h b/ui/aura/client/drag_drop_delegate.h
deleted file mode 100644
index dde7f32..0000000
--- a/ui/aura/client/drag_drop_delegate.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_DRAG_DROP_DELEGATE_H_
-#define UI_AURA_CLIENT_DRAG_DROP_DELEGATE_H_
-
-#include "ui/aura/aura_export.h"
-
-namespace ui {
-class DropTargetEvent;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-// Delegate interface for drag and drop actions on aura::Window.
-class AURA_EXPORT DragDropDelegate {
- public:
-  // OnDragEntered is invoked when the mouse enters this window during a drag &
-  // drop session. This is immediately followed by an invocation of
-  // OnDragUpdated, and eventually one of OnDragExited or OnPerformDrop.
-  virtual void OnDragEntered(const ui::DropTargetEvent& event) = 0;
-
-  // Invoked during a drag and drop session while the mouse is over the window.
-  // This should return a bitmask of the DragDropTypes::DragOperation supported
-  // based on the location of the event. Return 0 to indicate the drop should
-  // not be accepted.
-  virtual int OnDragUpdated(const ui::DropTargetEvent& event) = 0;
-
-  // Invoked during a drag and drop session when the mouse exits the window, or
-  // when the drag session was canceled and the mouse was over the window.
-  virtual void OnDragExited() = 0;
-
-  // Invoked during a drag and drop session when OnDragUpdated returns a valid
-  // operation and the user release the mouse.
-  virtual int OnPerformDrop(const ui::DropTargetEvent& event) = 0;
-
- protected:
-  virtual ~DragDropDelegate() {}
-};
-
-AURA_EXPORT void SetDragDropDelegate(Window* window,
-                                     DragDropDelegate* delegate);
-AURA_EXPORT DragDropDelegate* GetDragDropDelegate(Window* window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_DRAG_DROP_DELEGATE_H_
diff --git a/ui/aura/client/scoped_tooltip_disabler.cc b/ui/aura/client/scoped_tooltip_disabler.cc
deleted file mode 100644
index d3c1033..0000000
--- a/ui/aura/client/scoped_tooltip_disabler.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/scoped_tooltip_disabler.h"
-
-#include "ui/aura/client/tooltip_client.h"
-#include "ui/aura/window.h"
-
-namespace aura {
-namespace client {
-
-ScopedTooltipDisabler::ScopedTooltipDisabler(aura::Window* window)
-    : root_(window ? window->GetRootWindow() : NULL) {
-  if (root_) {
-    root_->AddObserver(this);
-    TooltipClient* client = GetTooltipClient(root_);
-    if (client)
-      client->SetTooltipsEnabled(false);
-  }
-}
-
-ScopedTooltipDisabler::~ScopedTooltipDisabler() {
-  EnableTooltips();
-}
-
-void ScopedTooltipDisabler::EnableTooltips() {
-  if (!root_)
-    return;
-  TooltipClient* client = GetTooltipClient(root_);
-  if (client)
-    client->SetTooltipsEnabled(true);
-  root_->RemoveObserver(this);
-  root_ = NULL;
-}
-
-void ScopedTooltipDisabler::OnWindowDestroying(aura::Window* window) {
-  EnableTooltips();
-}
-
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/scoped_tooltip_disabler.h b/ui/aura/client/scoped_tooltip_disabler.h
deleted file mode 100644
index 5d1b2ea..0000000
--- a/ui/aura/client/scoped_tooltip_disabler.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_SCOPED_TOOLTIP_DISABLER_H_
-#define UI_AURA_CLIENT_SCOPED_TOOLTIP_DISABLER_H_
-
-#include "ui/aura/window_observer.h"
-
-namespace aura {
-namespace client {
-
-// Use to temporarily disable tooltips.
-class AURA_EXPORT ScopedTooltipDisabler : aura::WindowObserver {
- public:
-  // Disables tooltips on |window| (does nothing if |window| is NULL). Tooltips
-  // are reenabled from the destructor when there are no most outstanding
-  // ScopedTooltipDisablers for |window|.
-  explicit ScopedTooltipDisabler(aura::Window* window);
-  virtual ~ScopedTooltipDisabler();
-
- private:
-  // Reenables the tooltips on the TooltipClient.
-  void EnableTooltips();
-
-  // aura::WindowObserver:
-  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
-
-  // The RootWindow to disable Tooltips on; NULL if the Window passed to the
-  // constructor was not in a root or the root has been destroyed.
-  aura::Window* root_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedTooltipDisabler);
-};
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_SCOPED_TOOLTIP_DISABLER_H_
diff --git a/ui/aura/client/tooltip_client.cc b/ui/aura/client/tooltip_client.cc
deleted file mode 100644
index 770be41..0000000
--- a/ui/aura/client/tooltip_client.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/tooltip_client.h"
-
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::TooltipClient*)
-DECLARE_WINDOW_PROPERTY_TYPE(base::string16*)
-
-namespace aura {
-namespace client {
-
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
-    TooltipClient*, kRootWindowTooltipClientKey, NULL);
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(base::string16*, kTooltipTextKey, NULL);
-
-void SetTooltipClient(Window* root_window, TooltipClient* client) {
-  DCHECK_EQ(root_window->GetRootWindow(), root_window);
-  root_window->SetProperty(kRootWindowTooltipClientKey, client);
-}
-
-TooltipClient* GetTooltipClient(Window* root_window) {
-  if (root_window)
-    DCHECK_EQ(root_window->GetRootWindow(), root_window);
-  return root_window ?
-      root_window->GetProperty(kRootWindowTooltipClientKey) : NULL;
-}
-
-void SetTooltipText(Window* window, base::string16* tooltip_text) {
-  window->SetProperty(kTooltipTextKey, tooltip_text);
-}
-
-const base::string16 GetTooltipText(Window* window) {
-  base::string16* string_ptr = window->GetProperty(kTooltipTextKey);
-  return string_ptr ? *string_ptr : base::string16();
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/tooltip_client.h b/ui/aura/client/tooltip_client.h
deleted file mode 100644
index 875e0e2..0000000
--- a/ui/aura/client/tooltip_client.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_TOOLTIP_CLIENT_H_
-#define UI_AURA_CLIENT_TOOLTIP_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-#include "ui/gfx/font.h"
-
-namespace aura {
-class Window;
-namespace client {
-
-class ScopedTooltipDisabler;
-
-class AURA_EXPORT TooltipClient {
- public:
-  // Informs the shell tooltip manager of change in tooltip for window |target|.
-  virtual void UpdateTooltip(Window* target) = 0;
-
-  // Sets the time after which the tooltip is hidden for Window |target|. If
-  // |timeout_in_ms| is <= 0, the tooltip is shown indefinitely.
-  virtual void SetTooltipShownTimeout(Window* target, int timeout_in_ms) = 0;
-
- protected:
-  // Enables/Disables tooltips. This is treated as a reference count. Consumers
-  // must use ScopedTooltipDisabler to enable/disabled tooltips.
-  virtual void SetTooltipsEnabled(bool enable) = 0;
-
- private:
-  friend class ScopedTooltipDisabler;
-};
-
-AURA_EXPORT void SetTooltipClient(Window* root_window,
-                                  TooltipClient* client);
-AURA_EXPORT TooltipClient* GetTooltipClient(Window* root_window);
-
-AURA_EXPORT void SetTooltipText(Window* window, base::string16* tooltip_text);
-AURA_EXPORT const base::string16 GetTooltipText(Window* window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_TOOLTIP_CLIENT_H_
diff --git a/ui/aura/client/transient_window_client.cc b/ui/aura/client/transient_window_client.cc
deleted file mode 100644
index 47b50b9..0000000
--- a/ui/aura/client/transient_window_client.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/transient_window_client.h"
-
-namespace aura {
-namespace client {
-
-namespace {
-
-TransientWindowClient* instance = NULL;
-
-}  // namespace
-
-void SetTransientWindowClient(TransientWindowClient* client) {
-  instance = client;
-}
-
-TransientWindowClient* GetTransientWindowClient() {
-  return instance;
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/transient_window_client.h b/ui/aura/client/transient_window_client.h
deleted file mode 100644
index 96434d7..0000000
--- a/ui/aura/client/transient_window_client.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_TRANSIENT_WINDOW_CLIENT_H_
-#define UI_AURA_CLIENT_TRANSIENT_WINDOW_CLIENT_H_
-
-#include "base/basictypes.h"
-#include "ui/aura/aura_export.h"
-
-namespace aura {
-
-class Window;
-
-namespace client {
-
-// TransientWindowClient is used to add or remove transient windows. Transient
-// children get the following behavior:
-// . The transient parent destroys any transient children when it is
-//   destroyed. This means a transient child is destroyed if either its parent
-//   or transient parent is destroyed.
-// . If a transient child and its transient parent share the same parent, then
-//   transient children are always ordered above the transient parent.
-// Transient windows are typically used for popups and menus.
-// TODO(sky): nuke this class and replace with calls to TransientWindowManager.
-// This is temporary until we start moving to ui/wm.
-class AURA_EXPORT TransientWindowClient {
- public:
-  virtual void AddTransientChild(Window* parent, Window* child) = 0;
-  virtual void RemoveTransientChild(Window* parent, Window* child) = 0;
-  virtual Window* GetTransientParent(Window* window) = 0;
-  virtual const Window* GetTransientParent(const Window* window) = 0;
-
- protected:
-  virtual ~TransientWindowClient() {}
-};
-
-// Sets/gets the TransientWindowClient. This does *not* take ownership of
-// |client|. It is assumed the caller will invoke SetTransientWindowClient(NULL)
-// before deleting |client|.
-AURA_EXPORT void SetTransientWindowClient(TransientWindowClient* client);
-AURA_EXPORT TransientWindowClient* GetTransientWindowClient();
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_TRANSIENT_WINDOW_CLIENT_H_
diff --git a/ui/aura/client/window_move_client.cc b/ui/aura/client/window_move_client.cc
deleted file mode 100644
index c65452d..0000000
--- a/ui/aura/client/window_move_client.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/aura/client/window_move_client.h"
-
-#include "ui/aura/window.h"
-#include "ui/aura/window_property.h"
-
-DECLARE_WINDOW_PROPERTY_TYPE(aura::client::WindowMoveClient*)
-
-namespace aura {
-namespace client {
-
-// A property key to store a client that handles window moves.
-DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
-    WindowMoveClient*, kWindowMoveClientKey, NULL);
-
-void SetWindowMoveClient(Window* window, WindowMoveClient* client) {
-  window->SetProperty(kWindowMoveClientKey, client);
-}
-
-WindowMoveClient* GetWindowMoveClient(Window* window) {
-  return window->GetProperty(kWindowMoveClientKey);
-}
-
-}  // namespace client
-}  // namespace aura
diff --git a/ui/aura/client/window_move_client.h b/ui/aura/client/window_move_client.h
deleted file mode 100644
index 15e4245..0000000
--- a/ui/aura/client/window_move_client.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_
-#define UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_
-
-#include "ui/aura/aura_export.h"
-#include "ui/gfx/vector2d.h"
-
-namespace gfx {
-class Point;
-}
-
-namespace aura {
-class Window;
-namespace client {
-
-enum WindowMoveResult {
-  MOVE_SUCCESSFUL,  // Moving window was successful.
-  MOVE_CANCELED    // Moving window was canceled.
-};
-
-enum WindowMoveSource {
-  WINDOW_MOVE_SOURCE_MOUSE,
-  WINDOW_MOVE_SOURCE_TOUCH,
-};
-
-// An interface implemented by an object that manages programatically keyed
-// window moving.
-class AURA_EXPORT WindowMoveClient {
- public:
-  // Starts a nested message loop for moving the window. |drag_offset| is the
-  // offset from the window origin to the cursor when the drag was started.
-  // Returns MOVE_SUCCESSFUL if the move has completed successfully, or
-  // MOVE_CANCELED otherwise.
-  virtual WindowMoveResult RunMoveLoop(Window* window,
-                                       const gfx::Vector2d& drag_offset,
-                                       WindowMoveSource source) = 0;
-
-  // Ends a previously started move loop.
-  virtual void EndMoveLoop() = 0;
-
- protected:
-  virtual ~WindowMoveClient() {}
-};
-
-// Sets/Gets the activation client for the specified window.
-AURA_EXPORT void SetWindowMoveClient(Window* window,
-                                     WindowMoveClient* client);
-AURA_EXPORT WindowMoveClient* GetWindowMoveClient(Window* window);
-
-}  // namespace client
-}  // namespace aura
-
-#endif  // UI_AURA_CLIENT_WINDOW_MOVE_CLIENT_H_
diff --git a/ui/aura/demo/demo_main.cc b/ui/aura/demo/demo_main.cc
index b254069..548aede 100644
--- a/ui/aura/demo/demo_main.cc
+++ b/ui/aura/demo/demo_main.cc
@@ -71,8 +71,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {}
   virtual bool HasHitTestMask() const OVERRIDE { return false; }
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {}
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE {}
 
  private:
   SkColor color_;
diff --git a/ui/aura/test/test_window_delegate.cc b/ui/aura/test/test_window_delegate.cc
index e5ae364..7f0ca1b 100644
--- a/ui/aura/test/test_window_delegate.cc
+++ b/ui/aura/test/test_window_delegate.cc
@@ -96,10 +96,6 @@
 void TestWindowDelegate::GetHitTestMask(gfx::Path* mask) const {
 }
 
-void TestWindowDelegate::DidRecreateLayer(ui::Layer *old_layer,
-                                          ui::Layer *new_layer) {
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // ColorTestWindowDelegate
 
diff --git a/ui/aura/test/test_window_delegate.h b/ui/aura/test/test_window_delegate.h
index 5a13410..6f36e44 100644
--- a/ui/aura/test/test_window_delegate.h
+++ b/ui/aura/test/test_window_delegate.h
@@ -60,8 +60,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
   virtual bool HasHitTestMask() const OVERRIDE;
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE;
 
  private:
   int window_component_;
diff --git a/ui/aura/window.cc b/ui/aura/window.cc
index 2d3300f..86c9046 100644
--- a/ui/aura/window.cc
+++ b/ui/aura/window.cc
@@ -27,7 +27,6 @@
 #include "ui/aura/window_observer.h"
 #include "ui/aura/window_tracker.h"
 #include "ui/aura/window_tree_host.h"
-#include "ui/compositor/clone_layer.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/layer.h"
 #include "ui/events/event_target_iterator.h"
@@ -227,10 +226,14 @@
     delegate_->OnWindowDestroying(this);
   FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowDestroying(this));
 
-  // Let the root know so that it can remove any references to us.
+  // TODO(beng): See comment in window_event_dispatcher.h. This shouldn't be
+  //             necessary but unfortunately is right now due to ordering
+  //             peculiarities. WED must be notified _after_ other observers
+  //             are notified of pending teardown but before the hierarchy
+  //             is actually torn down.
   WindowTreeHost* host = GetHost();
   if (host)
-    host->dispatcher()->OnWindowDestroying(this);
+    host->dispatcher()->OnPostNotifiedWindowDestroying(this);
 
   // Then destroy the children.
   RemoveOrDestroyChildren();
@@ -297,6 +300,11 @@
     layer()->SetFillsBoundsOpaquely(!transparent_);
 }
 
+void Window::SetFillsBoundsCompletely(bool fills_bounds) {
+  if (layer())
+    layer()->SetFillsBoundsCompletely(fills_bounds);
+}
+
 Window* Window::GetRootWindow() {
   return const_cast<Window*>(
       static_cast<const Window*>(this)->GetRootWindow());
@@ -379,12 +387,11 @@
     NOTREACHED();
     return;
   }
-  WindowEventDispatcher* dispatcher = GetHost()->dispatcher();
-  bool contained_mouse = IsVisible() && dispatcher &&
-      ContainsPointInRoot(dispatcher->GetLastMouseLocationInRoot());
+  FOR_EACH_OBSERVER(WindowObserver, observers_,
+                    OnWindowTransforming(this));
   layer()->SetTransform(transform);
-  if (dispatcher)
-    dispatcher->OnWindowTransformed(this, contained_mouse);
+  FOR_EACH_OBSERVER(WindowObserver, observers_,
+                    OnWindowTransformed(this));
 }
 
 void Window::SetLayoutManager(LayoutManager* layout_manager) {
@@ -571,11 +578,15 @@
   if (source->GetRootWindow() != target->GetRootWindow()) {
     client::ScreenPositionClient* source_client =
         client::GetScreenPositionClient(source->GetRootWindow());
-    source_client->ConvertPointToScreen(source, point);
+    // |source_client| can be NULL in tests.
+    if (source_client)
+      source_client->ConvertPointToScreen(source, point);
 
     client::ScreenPositionClient* target_client =
         client::GetScreenPositionClient(target->GetRootWindow());
-    target_client->ConvertPointFromScreen(target, point);
+    // |target_client| can be NULL in tests.
+    if (target_client)
+      target_client->ConvertPointFromScreen(target, point);
   } else if ((source != target) && (!source->layer() || !target->layer())) {
     if (!source->layer()) {
       gfx::Vector2d offset_to_layer;
@@ -593,6 +604,16 @@
   }
 }
 
+// static
+void Window::ConvertRectToTarget(const Window* source,
+                                 const Window* target,
+                                 gfx::Rect* rect) {
+  DCHECK(rect);
+  gfx::Point origin = rect->origin();
+  ConvertPointToTarget(source, target, &origin);
+  rect->set_origin(origin);
+}
+
 void Window::MoveCursorTo(const gfx::Point& point_in_window) {
   Window* root_window = GetRootWindow();
   DCHECK(root_window);
@@ -753,17 +774,6 @@
     delegate_->OnDeviceScaleFactorChanged(device_scale_factor);
 }
 
-scoped_ptr<ui::Layer> Window::RecreateLayer() {
-  scoped_ptr<ui::Layer> old_layer(ui::CloneLayer(this));
-  if (!old_layer)
-    return old_layer.Pass();
-
-  if (delegate_)
-    delegate_->DidRecreateLayer(old_layer.get(), layer());
-
-  return old_layer.Pass();
-}
-
 #if !defined(NDEBUG)
 std::string Window::GetDebugInfo() const {
   return base::StringPrintf(
@@ -888,7 +898,7 @@
   // changed notification from the layer (this typically happens after animating
   // hidden). We must notify ourselves.
   if (!layer() || layer()->delegate() != this)
-    OnWindowBoundsChanged(old_bounds, ContainsMouse());
+    OnWindowBoundsChanged(old_bounds);
 }
 
 void Window::SetVisible(bool visible) {
@@ -899,10 +909,6 @@
   FOR_EACH_OBSERVER(WindowObserver, observers_,
                     OnWindowVisibilityChanging(this, visible));
 
-  WindowTreeHost* host = GetHost();
-  if (host)
-    host->dispatcher()->DispatchMouseExitToHidingWindow(this);
-
   client::VisibilityClient* visibility_client =
       client::GetVisibilityClient(this);
   if (visibility_client)
@@ -918,9 +924,6 @@
     delegate_->OnWindowTargetVisibilityChanged(visible);
 
   NotifyWindowVisibilityChanged(this, visible);
-
-  if (host)
-    host->dispatcher()->OnWindowVisibilityChanged(this, visible);
 }
 
 void Window::SchedulePaint() {
@@ -1008,11 +1011,8 @@
   FOR_EACH_OBSERVER(WindowObserver, observers_, OnWillRemoveWindow(child));
   Window* root_window = child->GetRootWindow();
   Window* new_root_window = new_parent ? new_parent->GetRootWindow() : NULL;
-  if (root_window && root_window != new_root_window) {
-    root_window->GetHost()->dispatcher()->OnWindowRemovedFromRootWindow(
-        child, new_root_window);
-    child->NotifyRemovingFromRootWindow();
-  }
+  if (root_window && root_window != new_root_window)
+    child->NotifyRemovingFromRootWindow(new_root_window);
 
   gfx::Vector2d offset;
   GetAncestorWithLayer(&offset);
@@ -1181,12 +1181,12 @@
   FOR_EACH_OBSERVER(WindowObserver, observers_, OnWindowStackingChanged(this));
 }
 
-void Window::NotifyRemovingFromRootWindow() {
+void Window::NotifyRemovingFromRootWindow(Window* new_root) {
   FOR_EACH_OBSERVER(WindowObserver, observers_,
-                    OnWindowRemovingFromRootWindow(this));
+                    OnWindowRemovingFromRootWindow(this, new_root));
   for (Window::Windows::const_iterator it = children_.begin();
        it != children_.end(); ++it) {
-    (*it)->NotifyRemovingFromRootWindow();
+    (*it)->NotifyRemovingFromRootWindow(new_root);
   }
 }
 
@@ -1303,8 +1303,7 @@
   }
 }
 
-void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds,
-                                   bool contained_mouse) {
+void Window::OnWindowBoundsChanged(const gfx::Rect& old_bounds) {
   if (layer()) {
     bounds_ = layer()->bounds();
     if (parent_ && !parent_->layer()) {
@@ -1323,9 +1322,6 @@
   FOR_EACH_OBSERVER(WindowObserver,
                     observers_,
                     OnWindowBoundsChanged(this, old_bounds, bounds()));
-  WindowTreeHost* host = GetHost();
-  if (host)
-    host->dispatcher()->OnWindowBoundsChanged(this, contained_mouse);
 }
 
 void Window::OnPaintLayer(gfx::Canvas* canvas) {
@@ -1334,7 +1330,7 @@
 
 base::Closure Window::PrepareForLayerBoundsChange() {
   return base::Bind(&Window::OnWindowBoundsChanged, base::Unretained(this),
-                    bounds(), ContainsMouse());
+                    bounds());
 }
 
 bool Window::CanAcceptEvent(const ui::Event& event) {
diff --git a/ui/aura/window.h b/ui/aura/window.h
index b508d35..2324533 100644
--- a/ui/aura/window.h
+++ b/ui/aura/window.h
@@ -101,6 +101,9 @@
   bool transparent() const { return transparent_; }
   void SetTransparent(bool transparent);
 
+  // See description in Layer::SetFillsBoundsCompletely.
+  void SetFillsBoundsCompletely(bool fills_bounds);
+
   WindowDelegate* delegate() { return delegate_; }
   const WindowDelegate* delegate() const { return delegate_; }
 
@@ -207,6 +210,9 @@
   static void ConvertPointToTarget(const Window* source,
                                    const Window* target,
                                    gfx::Point* point);
+  static void ConvertRectToTarget(const Window* source,
+                                  const Window* target,
+                                  gfx::Rect* rect);
 
   // Moves the cursor to the specified location relative to the window.
   virtual void MoveCursorTo(const gfx::Point& point_in_window);
@@ -314,9 +320,6 @@
   // Overridden from ui::LayerDelegate:
   virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE;
 
-  // Overriden from ui::LayerOwner.
-  virtual scoped_ptr<ui::Layer> RecreateLayer() OVERRIDE;
-
 #if !defined(NDEBUG)
   // These methods are useful when debugging.
   std::string GetDebugInfo() const;
@@ -414,7 +417,7 @@
 
   // Notifies observers registered with this Window (and its subtree) when the
   // Window has been added or is about to be removed from a RootWindow.
-  void NotifyRemovingFromRootWindow();
+  void NotifyRemovingFromRootWindow(Window* new_root);
   void NotifyAddedToRootWindow();
 
   // Methods implementing hierarchy change notifications. See WindowObserver for
@@ -447,10 +450,8 @@
 
   // Invoked when the bounds of the window changes. This may be invoked directly
   // by us, or from the closure returned by PrepareForLayerBoundsChange() after
-  // the bounds of the layer has changed. |old_bounds| is the previous bounds,
-  // and |contained_mouse| is true if the mouse was previously within the
-  // window's bounds.
-  void OnWindowBoundsChanged(const gfx::Rect& old_bounds, bool contained_mouse);
+  // the bounds of the layer has changed. |old_bounds| is the previous bounds.
+  void OnWindowBoundsChanged(const gfx::Rect& old_bounds);
 
   // Overridden from ui::LayerDelegate:
   virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE;
diff --git a/ui/aura/window_delegate.h b/ui/aura/window_delegate.h
index 7a4f550..90e978a 100644
--- a/ui/aura/window_delegate.h
+++ b/ui/aura/window_delegate.h
@@ -100,13 +100,6 @@
   // above returns true.
   virtual void GetHitTestMask(gfx::Path* mask) const = 0;
 
-  // Called from RecreateLayer() after the new layer was created. old_layer is
-  // the layer that will be returned to the caller of RecreateLayer, new_layer
-  // will be the layer now used on the Window. The implementation only has to do
-  // anything if the layer has external content (SetExternalTexture /
-  // SetTextureMailbox / SetDelegatedFrame was called).
-  virtual void DidRecreateLayer(ui::Layer* old_layer, ui::Layer* new_layer) = 0;
-
  protected:
   virtual ~WindowDelegate() {}
 };
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc
index 170d513..5489596 100644
--- a/ui/aura/window_event_dispatcher.cc
+++ b/ui/aura/window_event_dispatcher.cc
@@ -82,13 +82,16 @@
       synthesize_mouse_move_(false),
       move_hold_count_(0),
       dispatching_held_event_(false),
+      observer_manager_(this),
       repost_event_factory_(this),
       held_event_factory_(this) {
   ui::GestureRecognizer::Get()->AddGestureEventHelper(this);
+  Env::GetInstance()->AddObserver(this);
 }
 
 WindowEventDispatcher::~WindowEventDispatcher() {
   TRACE_EVENT0("shutdown", "WindowEventDispatcher::Destructor");
+  Env::GetInstance()->RemoveObserver(this);
   ui::GestureRecognizer::Get()->RemoveGestureEventHelper(this);
 }
 
@@ -118,7 +121,7 @@
 void WindowEventDispatcher::OnMouseEventsEnableStateChanged(bool enabled) {
   // Send entered / exited so that visual state can be updated to match
   // mouse events state.
-  PostMouseMoveEventAfterWindowChange();
+  PostSynthesizeMouseMove();
   // TODO(mazda): Add code to disable mouse events when |enabled| == false.
 }
 
@@ -133,21 +136,6 @@
     return;
 }
 
-Window* WindowEventDispatcher::GetGestureTarget(ui::GestureEvent* event) {
-  Window* target = NULL;
-  if (!event->IsEndingEvent()) {
-    // The window that received the start event (e.g. scroll begin) needs to
-    // receive the end event (e.g. scroll end).
-    target = client::GetCaptureWindow(window());
-  }
-  if (!target) {
-    target = ConsumerToWindow(
-        ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
-  }
-
-  return target;
-}
-
 void WindowEventDispatcher::DispatchGestureEvent(ui::GestureEvent* event) {
   DispatchDetails details = DispatchHeldEvents();
   if (details.dispatcher_destroyed)
@@ -162,39 +150,6 @@
   }
 }
 
-void WindowEventDispatcher::OnWindowDestroying(Window* window) {
-  DispatchMouseExitToHidingWindow(window);
-  if (window->IsVisible() &&
-      window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
-    PostMouseMoveEventAfterWindowChange();
-  }
-
-  // Hiding the window releases capture which can implicitly destroy the window
-  // so the window may no longer be valid after this call.
-  OnWindowHidden(window, WINDOW_DESTROYED);
-}
-
-void WindowEventDispatcher::OnWindowBoundsChanged(Window* window,
-                                                  bool contained_mouse_point) {
-  if (contained_mouse_point ||
-      (window->IsVisible() &&
-       window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
-    PostMouseMoveEventAfterWindowChange();
-  }
-}
-
-void WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) {
-  // The mouse capture is intentionally ignored. Think that a mouse enters
-  // to a window, the window sets the capture, the mouse exits the window,
-  // and then it releases the capture. In that case OnMouseExited won't
-  // be called. So it is natural not to emit OnMouseExited even though
-  // |window| is the capture window.
-  gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
-  if (window->Contains(mouse_moved_handler_) &&
-      window->ContainsPointInRoot(last_mouse_location))
-    DispatchMouseExitAtPoint(last_mouse_location);
-}
-
 void WindowEventDispatcher::DispatchMouseExitAtPoint(const gfx::Point& point) {
   ui::MouseEvent event(ui::ET_MOUSE_EXITED, point, point, ui::EF_NONE,
                        ui::EF_NONE);
@@ -204,26 +159,6 @@
     return;
 }
 
-void WindowEventDispatcher::OnWindowVisibilityChanged(Window* window,
-                                                      bool is_visible) {
-  if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
-    PostMouseMoveEventAfterWindowChange();
-
-  // Hiding the window releases capture which can implicitly destroy the window
-  // so the window may no longer be valid after this call.
-  if (!is_visible)
-    OnWindowHidden(window, WINDOW_HIDDEN);
-}
-
-void WindowEventDispatcher::OnWindowTransformed(Window* window,
-                                                bool contained_mouse) {
-  if (contained_mouse ||
-      (window->IsVisible() &&
-       window->ContainsPointInRoot(GetLastMouseLocationInRoot()))) {
-    PostMouseMoveEventAfterWindowChange();
-  }
-}
-
 void WindowEventDispatcher::ProcessedTouchEvent(ui::TouchEvent* event,
                                                 Window* window,
                                                 ui::EventResult result) {
@@ -273,29 +208,16 @@
   mouse_moved_handler_ = NULL;
 }
 
-void WindowEventDispatcher::OnHostResized(const gfx::Size& size) {
-  TRACE_EVENT1("ui", "WindowEventDispatcher::OnHostResized",
-               "size", size.ToString());
-
-  DispatchDetails details = DispatchHeldEvents();
-  if (details.dispatcher_destroyed)
-    return;
-
-  // Constrain the mouse position within the new root Window size.
-  gfx::Point point;
-  if (host_->QueryMouseLocation(&point)) {
-    SetLastMouseLocation(window(),
-                         ui::ConvertPointToDIP(window()->layer(), point));
-  }
-  synthesize_mouse_move_ = false;
-}
-
 void WindowEventDispatcher::OnCursorMovedToRootLocation(
     const gfx::Point& root_location) {
   SetLastMouseLocation(window(), root_location);
   synthesize_mouse_move_ = false;
 }
 
+void WindowEventDispatcher::OnPostNotifiedWindowDestroying(Window* window) {
+  OnWindowHidden(window, WINDOW_DESTROYED);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WindowEventDispatcher, private:
 
@@ -312,6 +234,18 @@
   event->UpdateForRootTransform(host_->GetInverseRootTransform());
 }
 
+void WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) {
+  // The mouse capture is intentionally ignored. Think that a mouse enters
+  // to a window, the window sets the capture, the mouse exits the window,
+  // and then it releases the capture. In that case OnMouseExited won't
+  // be called. So it is natural not to emit OnMouseExited even though
+  // |window| is the capture window.
+  gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
+  if (window->Contains(mouse_moved_handler_) &&
+      window->ContainsPointInRoot(last_mouse_location))
+    DispatchMouseExitAtPoint(last_mouse_location);
+}
+
 ui::EventDispatchDetails WindowEventDispatcher::DispatchMouseEnterOrExit(
     const ui::MouseEvent& event,
     ui::EventType type) {
@@ -357,28 +291,6 @@
   return details;
 }
 
-void WindowEventDispatcher::OnWindowAddedToRootWindow(Window* attached) {
-  if (attached->IsVisible() &&
-      attached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
-    PostMouseMoveEventAfterWindowChange();
-  }
-}
-
-void WindowEventDispatcher::OnWindowRemovedFromRootWindow(Window* detached,
-                                                          Window* new_root) {
-  DCHECK(aura::client::GetCaptureWindow(window()) != window());
-
-  DispatchMouseExitToHidingWindow(detached);
-  if (detached->IsVisible() &&
-      detached->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
-    PostMouseMoveEventAfterWindowChange();
-  }
-
-  // Hiding the window releases capture which can implicitly destroy the window
-  // so the window may no longer be valid after this call.
-  OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
-}
-
 void WindowEventDispatcher::OnWindowHidden(Window* invisible,
                                            WindowHiddenReason reason) {
   // If the window the mouse was pressed in becomes invisible, it should no
@@ -398,12 +310,17 @@
   CleanupGestureState(invisible);
 
   // Do not clear the capture, and the |event_dispatch_target_| if the
-  // window is moving across root windows, because the target itself
-  // is actually still visible and clearing them stops further event
-  // processing, which can cause unexpected behaviors. See
-  // crbug.com/157583
+  // window is moving across hosts, because the target itself is actually still
+  // visible and clearing them stops further event processing, which can cause
+  // unexpected behaviors. See crbug.com/157583
   if (reason != WINDOW_MOVING) {
-    Window* capture_window = aura::client::GetCaptureWindow(window());
+    // We don't ask |invisible| here, because invisible may have been removed
+    // from the window hierarchy already by the time this function is called
+    // (OnWindowDestroyed).
+    client::CaptureClient* capture_client =
+        client::GetCaptureClient(host_->window());
+    Window* capture_window =
+        capture_client ? capture_client->GetCaptureWindow() : NULL;
 
     if (invisible->Contains(event_dispatch_target_))
       event_dispatch_target_ = NULL;
@@ -427,6 +344,21 @@
   }
 }
 
+Window* WindowEventDispatcher::GetGestureTarget(ui::GestureEvent* event) {
+  Window* target = NULL;
+  if (!event->IsEndingEvent()) {
+    // The window that received the start event (e.g. scroll begin) needs to
+    // receive the end event (e.g. scroll end).
+    target = client::GetCaptureWindow(window());
+  }
+  if (!target) {
+    target = ConsumerToWindow(
+        ui::GestureRecognizer::Get()->GetTargetForGestureEvent(*event));
+  }
+
+  return target;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WindowEventDispatcher, aura::client::CaptureDelegate implementation:
 
@@ -586,6 +518,129 @@
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, WindowObserver implementation:
+
+void WindowEventDispatcher::OnWindowDestroying(Window* window) {
+  if (!host_->window()->Contains(window))
+    return;
+
+  DispatchMouseExitToHidingWindow(window);
+  SynthesizeMouseMoveAfterChangeToWindow(window);
+}
+
+void WindowEventDispatcher::OnWindowDestroyed(Window* window) {
+  // We observe all windows regardless of what root Window (if any) they're
+  // attached to.
+  observer_manager_.Remove(window);
+}
+
+void WindowEventDispatcher::OnWindowAddedToRootWindow(Window* attached) {
+  if (!observer_manager_.IsObserving(attached))
+    observer_manager_.Add(attached);
+
+  if (!host_->window()->Contains(attached))
+    return;
+
+  SynthesizeMouseMoveAfterChangeToWindow(attached);
+}
+
+void WindowEventDispatcher::OnWindowRemovingFromRootWindow(Window* detached,
+                                                           Window* new_root) {
+  if (!host_->window()->Contains(detached))
+    return;
+
+  DCHECK(client::GetCaptureWindow(window()) != window());
+
+  DispatchMouseExitToHidingWindow(detached);
+  SynthesizeMouseMoveAfterChangeToWindow(detached);
+
+  // Hiding the window releases capture which can implicitly destroy the window
+  // so the window may no longer be valid after this call.
+  OnWindowHidden(detached, new_root ? WINDOW_MOVING : WINDOW_HIDDEN);
+}
+
+void WindowEventDispatcher::OnWindowVisibilityChanging(Window* window,
+                                                       bool visible) {
+  if (!host_->window()->Contains(window))
+    return;
+
+  DispatchMouseExitToHidingWindow(window);
+}
+
+void WindowEventDispatcher::OnWindowVisibilityChanged(Window* window,
+                                                      bool visible) {
+  if (!host_->window()->Contains(window))
+    return;
+
+  if (window->ContainsPointInRoot(GetLastMouseLocationInRoot()))
+    PostSynthesizeMouseMove();
+
+  // Hiding the window releases capture which can implicitly destroy the window
+  // so the window may no longer be valid after this call.
+  if (!visible)
+    OnWindowHidden(window, WINDOW_HIDDEN);
+}
+
+void WindowEventDispatcher::OnWindowBoundsChanged(Window* window,
+                                                  const gfx::Rect& old_bounds,
+                                                  const gfx::Rect& new_bounds) {
+  if (!host_->window()->Contains(window))
+    return;
+
+  if (window == host_->window()) {
+    TRACE_EVENT1("ui", "WindowEventDispatcher::OnWindowBoundsChanged(root)",
+                 "size", new_bounds.size().ToString());
+
+    DispatchDetails details = DispatchHeldEvents();
+    if (details.dispatcher_destroyed)
+      return;
+
+    // Constrain the mouse position within the new root Window size.
+    gfx::Point point;
+    if (host_->QueryMouseLocation(&point)) {
+      SetLastMouseLocation(
+          host_->window(),
+          ui::ConvertPointToDIP(host_->window()->layer(), point));
+    }
+    synthesize_mouse_move_ = false;
+  }
+
+  if (window->IsVisible()) {
+    gfx::Rect old_bounds_in_root = old_bounds, new_bounds_in_root = new_bounds;
+    Window::ConvertRectToTarget(window->parent(), host_->window(),
+                                &old_bounds_in_root);
+    Window::ConvertRectToTarget(window->parent(), host_->window(),
+                                &new_bounds_in_root);
+    gfx::Point last_mouse_location = GetLastMouseLocationInRoot();
+    if (old_bounds_in_root.Contains(last_mouse_location) !=
+        new_bounds_in_root.Contains(last_mouse_location)) {
+      PostSynthesizeMouseMove();
+    }
+  }
+}
+
+void WindowEventDispatcher::OnWindowTransforming(Window* window) {
+  if (!host_->window()->Contains(window))
+    return;
+
+  SynthesizeMouseMoveAfterChangeToWindow(window);
+}
+
+void WindowEventDispatcher::OnWindowTransformed(Window* window) {
+  if (!host_->window()->Contains(window))
+    return;
+
+  SynthesizeMouseMoveAfterChangeToWindow(window);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// WindowEventDispatcher, EnvObserver implementation:
+
+void WindowEventDispatcher::OnWindowInitialized(Window* window) {
+  observer_manager_.Add(window);
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // WindowEventDispatcher, private:
 
 ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() {
@@ -625,7 +680,7 @@
   return dispatch_details;
 }
 
-void WindowEventDispatcher::PostMouseMoveEventAfterWindowChange() {
+void WindowEventDispatcher::PostSynthesizeMouseMove() {
   if (synthesize_mouse_move_)
     return;
   synthesize_mouse_move_ = true;
@@ -636,6 +691,14 @@
           held_event_factory_.GetWeakPtr()));
 }
 
+void WindowEventDispatcher::SynthesizeMouseMoveAfterChangeToWindow(
+    Window* window) {
+  if (window->IsVisible() &&
+      window->ContainsPointInRoot(GetLastMouseLocationInRoot())) {
+    PostSynthesizeMouseMove();
+  }
+}
+
 ui::EventDispatchDetails WindowEventDispatcher::SynthesizeMouseMoveEvent() {
   DispatchDetails details;
   if (!synthesize_mouse_move_)
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h
index c782649..f0cb67f 100644
--- a/ui/aura/window_event_dispatcher.h
+++ b/ui/aura/window_event_dispatcher.h
@@ -13,8 +13,11 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
+#include "base/scoped_observer.h"
 #include "ui/aura/aura_export.h"
 #include "ui/aura/client/capture_delegate.h"
+#include "ui/aura/env_observer.h"
+#include "ui/aura/window_observer.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/event_processor.h"
@@ -39,7 +42,6 @@
 }
 
 namespace aura {
-class RootWindowObserver;
 class TestScreen;
 class WindowTargeter;
 class WindowTreeHost;
@@ -50,7 +52,9 @@
 //             event dispatch.
 class AURA_EXPORT WindowEventDispatcher : public ui::EventProcessor,
                                           public ui::GestureEventHelper,
-                                          public client::CaptureDelegate {
+                                          public client::CaptureDelegate,
+                                          public WindowObserver,
+                                          public EnvObserver {
  public:
   explicit WindowEventDispatcher(WindowTreeHost* host);
   virtual ~WindowEventDispatcher();
@@ -68,35 +72,15 @@
 
   void DispatchCancelModeEvent();
 
-  // Returns a target window for the given gesture event.
-  Window* GetGestureTarget(ui::GestureEvent* event);
-
   // Handles a gesture event. Returns true if handled. Unlike the other
   // event-dispatching function (e.g. for touch/mouse/keyboard events), gesture
   // events are dispatched from GestureRecognizer instead of WindowTreeHost.
   void DispatchGestureEvent(ui::GestureEvent* event);
 
-  // Invoked when |window| is being destroyed.
-  void OnWindowDestroying(Window* window);
-
-  // Invoked when |window|'s bounds have changed. |contained_mouse| indicates if
-  // the bounds before change contained the |last_moust_location()|.
-  void OnWindowBoundsChanged(Window* window, bool contained_mouse);
-
-  // Dispatches OnMouseExited to the |window| which is hiding if necessary.
-  void DispatchMouseExitToHidingWindow(Window* window);
-
   // Dispatches a ui::ET_MOUSE_EXITED event at |point|.
+  // TODO(beng): needed only for WTH::OnCursorVisibilityChanged().
   void DispatchMouseExitAtPoint(const gfx::Point& point);
 
-  // Invoked when |window|'s visibility has changed.
-  void OnWindowVisibilityChanged(Window* window, bool is_visible);
-
-  // Invoked when |window|'s transform has changed. |contained_mouse|
-  // indicates if the bounds before change contained the
-  // |last_moust_location()|.
-  void OnWindowTransformed(Window* window, bool contained_mouse);
-
   // Gesture Recognition -------------------------------------------------------
 
   // When a touch event is dispatched to a Window, it may want to process the
@@ -124,10 +108,17 @@
   gfx::Point GetLastMouseLocationInRoot() const;
 
   void OnHostLostMouseGrab();
-  // TODO(beng): replace with a window observer.
-  void OnHostResized(const gfx::Size& size);
   void OnCursorMovedToRootLocation(const gfx::Point& root_location);
 
+  // TODO(beng): This is only needed because this cleanup needs to happen after
+  //             all other observers are notified of OnWindowDestroying() but
+  //             before OnWindowDestroyed() is sent (i.e. while the window
+  //             hierarchy is still intact). This didn't seem worth adding a
+  //             generic notification for as only this class needs to implement
+  //             it. I would however like to find a way to do this via an
+  //             observer.
+  void OnPostNotifiedWindowDestroying(Window* window);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(WindowEventDispatcherTest,
                            KeepTranslatedEventInRoot);
@@ -153,6 +144,9 @@
   // the event received from the host.
   void TransformEventForDeviceScaleFactor(ui::LocatedEvent* event);
 
+  // Dispatches OnMouseExited to the |window| which is hiding if necessary.
+  void DispatchMouseExitToHidingWindow(Window* window);
+
   // Dispatches the specified event type (intended for enter/exit) to the
   // |mouse_moved_handler_|.
   ui::EventDispatchDetails DispatchMouseEnterOrExit(
@@ -161,11 +155,6 @@
   ui::EventDispatchDetails ProcessGestures(
       ui::GestureRecognizer::Gestures* gestures) WARN_UNUSED_RESULT;
 
-  // Called when a Window is attached or detached from the
-  // WindowEventDispatcher.
-  void OnWindowAddedToRootWindow(Window* window);
-  void OnWindowRemovedFromRootWindow(Window* window, Window* new_root);
-
   // Called when a window becomes invisible, either by being removed
   // from root window hierarchy, via SetVisible(false) or being destroyed.
   // |reason| specifies what triggered the hiding. Note that becoming invisible
@@ -177,6 +166,9 @@
   // |window| itself). This includes cancelling active touch points.
   void CleanupGestureState(Window* window);
 
+  // Returns a target window for the given gesture event.
+  Window* GetGestureTarget(ui::GestureEvent* event);
+
   // Overridden from aura::client::CaptureDelegate:
   virtual void UpdateCapture(Window* old_capture, Window* new_capture) OVERRIDE;
   virtual void OnOtherRootGotCapture() OVERRIDE;
@@ -199,6 +191,24 @@
   virtual void DispatchPostponedGestureEvent(ui::GestureEvent* event) OVERRIDE;
   virtual void DispatchCancelTouchEvent(ui::TouchEvent* event) OVERRIDE;
 
+  // Overridden from WindowObserver:
+  virtual void OnWindowDestroying(Window* window) OVERRIDE;
+  virtual void OnWindowDestroyed(Window* window) OVERRIDE;
+  virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE;
+  virtual void OnWindowRemovingFromRootWindow(Window* window,
+                                              Window* new_root) OVERRIDE;
+  virtual void OnWindowVisibilityChanging(Window* window,
+                                          bool visible) OVERRIDE;
+  virtual void OnWindowVisibilityChanged(Window* window, bool visible) OVERRIDE;
+  virtual void OnWindowBoundsChanged(Window* window,
+                                     const gfx::Rect& old_bounds,
+                                     const gfx::Rect& new_bounds) OVERRIDE;
+  virtual void OnWindowTransforming(Window* window) OVERRIDE;
+  virtual void OnWindowTransformed(Window* window) OVERRIDE;
+
+  // Overridden from EnvObserver:
+  virtual void OnWindowInitialized(Window* window) OVERRIDE;
+
   // We hold and aggregate mouse drags and touch moves as a way of throttling
   // resizes when HoldMouseMoves() is called. The following methods are used to
   // dispatch held and newly incoming mouse and touch events, typically when an
@@ -206,17 +216,19 @@
   // ReleaseMouseMoves()/ReleaseTouchMoves() is called.  NOTE: because these
   // methods dispatch events from WindowTreeHost the coordinates are in terms of
   // the root.
-
   ui::EventDispatchDetails DispatchHeldEvents() WARN_UNUSED_RESULT;
+
+  // Posts a task to send synthesized mouse move event if there is no a pending
+  // task.
+  void PostSynthesizeMouseMove();
+
   // Creates and dispatches synthesized mouse move event using the
   // current mouse location.
   ui::EventDispatchDetails SynthesizeMouseMoveEvent() WARN_UNUSED_RESULT;
 
-  void SynthesizeMouseMoveEventAsync();
-
-  // Posts a task to send synthesized mouse move event if there
-  // is no a pending task.
-  void PostMouseMoveEventAfterWindowChange();
+  // Calls SynthesizeMouseMove() if |window| is currently visible and contains
+  // the mouse cursor.
+  void SynthesizeMouseMoveAfterChangeToWindow(Window* window);
 
   void PreDispatchLocatedEvent(Window* target, ui::LocatedEvent* event);
   void PreDispatchMouseEvent(Window* target, ui::MouseEvent* event);
@@ -246,6 +258,8 @@
   // Set when dispatching a held event.
   bool dispatching_held_event_;
 
+  ScopedObserver<aura::Window, aura::WindowObserver> observer_manager_;
+
   // Used to schedule reposting an event.
   base::WeakPtrFactory<WindowEventDispatcher> repost_event_factory_;
 
diff --git a/ui/aura/window_observer.h b/ui/aura/window_observer.h
index bd909d8..926e5c4 100644
--- a/ui/aura/window_observer.h
+++ b/ui/aura/window_observer.h
@@ -75,6 +75,10 @@
                                      const gfx::Rect& old_bounds,
                                      const gfx::Rect& new_bounds) {}
 
+  // Invoked when SetTransform() is invoked on |window|.
+  virtual void OnWindowTransforming(Window* window) {}
+  virtual void OnWindowTransformed(Window* window) {}
+
   // Invoked when |window|'s position among its siblings in the stacking order
   // has changed.
   virtual void OnWindowStackingChanged(Window* window) {}
@@ -100,8 +104,11 @@
   // Called when a Window has been added to a RootWindow.
   virtual void OnWindowAddedToRootWindow(Window* window) {}
 
-  // Called when a Window is about to be removed from a RootWindow.
-  virtual void OnWindowRemovingFromRootWindow(Window* window) {}
+  // Called when a Window is about to be removed from a root Window.
+  // |new_root| contains the new root Window if it is being added to one
+  // atomically.
+  virtual void OnWindowRemovingFromRootWindow(Window* window,
+                                              Window* new_root) {}
 
  protected:
   virtual ~WindowObserver() {}
diff --git a/ui/aura/window_tree_host.cc b/ui/aura/window_tree_host.cc
index 4958c41..9c3cf12 100644
--- a/ui/aura/window_tree_host.cc
+++ b/ui/aura/window_tree_host.cc
@@ -287,7 +287,6 @@
   // transformed size of the root window.
   UpdateRootWindowSize(layer_size);
   FOR_EACH_OBSERVER(WindowTreeHostObserver, observers_, OnHostResized(this));
-  dispatcher()->OnHostResized(layer_size);
 }
 
 void WindowTreeHost::OnHostCloseRequested() {
diff --git a/ui/aura/window_tree_host_x11.cc b/ui/aura/window_tree_host_x11.cc
index 4048a5d..a57f2a9 100644
--- a/ui/aura/window_tree_host_x11.cc
+++ b/ui/aura/window_tree_host_x11.cc
@@ -39,6 +39,7 @@
 #include "ui/compositor/dip_util.h"
 #include "ui/compositor/layer.h"
 #include "ui/events/event.h"
+#include "ui/events/event_switches.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/events/x/device_data_manager.h"
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc
index ba183cf..986929b 100644
--- a/ui/aura/window_unittest.cc
+++ b/ui/aura/window_unittest.cc
@@ -2129,7 +2129,8 @@
   virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
     ++added_count_;
   }
-  virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
+  virtual void OnWindowRemovingFromRootWindow(Window* window,
+                                              Window* new_root) OVERRIDE {
     ++removed_count_;
   }
 
@@ -2391,7 +2392,8 @@
   virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
     added_count_++;
   }
-  virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
+  virtual void OnWindowRemovingFromRootWindow(Window* window,
+                                              Window* new_root) OVERRIDE {
     removed_count_++;
   }
 
diff --git a/ui/base/clipboard/clipboard_aurax11.cc b/ui/base/clipboard/clipboard_aurax11.cc
index dde85fe..7076844 100644
--- a/ui/base/clipboard/clipboard_aurax11.cc
+++ b/ui/base/clipboard/clipboard_aurax11.cc
@@ -762,8 +762,11 @@
 // Write an extra flavor that signifies WebKit was the last to modify the
 // pasteboard. This flavor has no data.
 void Clipboard::WriteWebSmartPaste() {
-  aurax11_details_->InsertMapping(kMimeTypeWebkitSmartPaste,
-                                  scoped_refptr<base::RefCountedMemory>());
+  std::string empty;
+  aurax11_details_->InsertMapping(
+      kMimeTypeWebkitSmartPaste,
+      scoped_refptr<base::RefCountedMemory>(
+          base::RefCountedString::TakeString(&empty)));
 }
 
 void Clipboard::WriteBitmap(const SkBitmap& bitmap) {
diff --git a/ui/base/cocoa/underlay_opengl_hosting_window.mm b/ui/base/cocoa/underlay_opengl_hosting_window.mm
index 4e20836..39a3036 100644
--- a/ui/base/cocoa/underlay_opengl_hosting_window.mm
+++ b/ui/base/cocoa/underlay_opengl_hosting_window.mm
@@ -33,8 +33,8 @@
 namespace {
 
 bool CoreAnimationIsEnabled() {
-  static bool is_enabled = CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kEnableCoreAnimation);
+  static bool is_enabled = !CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableCoreAnimation);
   return is_enabled;
 }
 
diff --git a/ui/base/cursor/cursor_loader_x11.cc b/ui/base/cursor/cursor_loader_x11.cc
index 8cfcce6..0161da2 100644
--- a/ui/base/cursor/cursor_loader_x11.cc
+++ b/ui/base/cursor/cursor_loader_x11.cc
@@ -12,6 +12,7 @@
 #include "grit/ui_resources.h"
 #include "skia/ext/image_operations.h"
 #include "ui/base/cursor/cursor.h"
+#include "ui/base/cursor/cursor_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/x/x11_util.h"
 #include "ui/gfx/image/image.h"
@@ -259,48 +260,4 @@
   return GetXCursor(CursorShapeFromNative(native_cursor));
 }
 
-void ScaleAndRotateCursorBitmapAndHotpoint(float scale,
-                                           gfx::Display::Rotation rotation,
-                                           SkBitmap* bitmap,
-                                           gfx::Point* hotpoint) {
-  switch (rotation) {
-    case gfx::Display::ROTATE_0:
-      break;
-    case gfx::Display::ROTATE_90:
-      hotpoint->SetPoint(bitmap->height() - hotpoint->y(), hotpoint->x());
-      *bitmap = SkBitmapOperations::Rotate(
-          *bitmap, SkBitmapOperations::ROTATION_90_CW);
-      break;
-    case gfx::Display::ROTATE_180:
-      hotpoint->SetPoint(
-          bitmap->width() - hotpoint->x(), bitmap->height() - hotpoint->y());
-      *bitmap = SkBitmapOperations::Rotate(
-          *bitmap, SkBitmapOperations::ROTATION_180_CW);
-      break;
-    case gfx::Display::ROTATE_270:
-      hotpoint->SetPoint(hotpoint->y(), bitmap->width() - hotpoint->x());
-      *bitmap = SkBitmapOperations::Rotate(
-          *bitmap, SkBitmapOperations::ROTATION_270_CW);
-      break;
-  }
-
-  if (scale < FLT_EPSILON) {
-    NOTREACHED() << "Scale must be larger than 0.";
-    scale = 1.0f;
-  }
-
-  if (scale == 1.0f)
-    return;
-
-  gfx::Size scaled_size = gfx::ToFlooredSize(
-      gfx::ScaleSize(gfx::Size(bitmap->width(), bitmap->height()), scale));
-
-  *bitmap = skia::ImageOperations::Resize(
-      *bitmap,
-      skia::ImageOperations::RESIZE_BETTER,
-      scaled_size.width(),
-      scaled_size.height());
-  *hotpoint = gfx::ToFlooredPoint(gfx::ScalePoint(*hotpoint, scale));
-}
-
 }  // namespace ui
diff --git a/ui/base/cursor/cursor_loader_x11.h b/ui/base/cursor/cursor_loader_x11.h
index d493b1e..34edc91 100644
--- a/ui/base/cursor/cursor_loader_x11.h
+++ b/ui/base/cursor/cursor_loader_x11.h
@@ -56,15 +56,6 @@
   DISALLOW_COPY_AND_ASSIGN(CursorLoaderX11);
 };
 
-// Scale and rotate the cursor's bitmap and hotpoint.
-// |bitmap_in_out| and |hotpoint_in_out| are used as
-// both input and output.
-UI_BASE_EXPORT void ScaleAndRotateCursorBitmapAndHotpoint(
-    float scale,
-    gfx::Display::Rotation rotation,
-    SkBitmap* bitmap_in_out,
-    gfx::Point* hotpoint_in_out);
-
 }  // namespace ui
 
 #endif  // UI_BASE_CURSOR_CURSOR_LOADER_X11_H_
diff --git a/ui/base/cursor/cursor_loader_x11_unittest.cc b/ui/base/cursor/cursor_loader_x11_unittest.cc
index c2413b6..75ea12b 100644
--- a/ui/base/cursor/cursor_loader_x11_unittest.cc
+++ b/ui/base/cursor/cursor_loader_x11_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/cursor_util.h"
 
 namespace ui {
 
diff --git a/ui/base/cursor/cursor_ozone.cc b/ui/base/cursor/cursor_ozone.cc
index d60e2db..deb17c2 100644
--- a/ui/base/cursor/cursor_ozone.cc
+++ b/ui/base/cursor/cursor_ozone.cc
@@ -9,11 +9,13 @@
 namespace ui {
 
 void Cursor::RefCustomCursor() {
-  CursorFactoryOzone::GetInstance()->RefImageCursor(platform_cursor_);
+  if (platform_cursor_)
+    CursorFactoryOzone::GetInstance()->RefImageCursor(platform_cursor_);
 }
 
 void Cursor::UnrefCustomCursor() {
-  CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor_);
+  if (platform_cursor_)
+    CursorFactoryOzone::GetInstance()->UnrefImageCursor(platform_cursor_);
 }
 
 }  // namespace ui
diff --git a/ui/base/cursor/cursor_util.cc b/ui/base/cursor/cursor_util.cc
new file mode 100644
index 0000000..a17d944
--- /dev/null
+++ b/ui/base/cursor/cursor_util.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/cursor/cursor_util.h"
+
+#include "base/logging.h"
+#include "skia/ext/image_operations.h"
+#include "ui/gfx/point_conversions.h"
+#include "ui/gfx/size_conversions.h"
+#include "ui/gfx/skbitmap_operations.h"
+#include "ui/gfx/skia_util.h"
+
+namespace ui {
+
+void ScaleAndRotateCursorBitmapAndHotpoint(float scale,
+                                           gfx::Display::Rotation rotation,
+                                           SkBitmap* bitmap,
+                                           gfx::Point* hotpoint) {
+  switch (rotation) {
+    case gfx::Display::ROTATE_0:
+      break;
+    case gfx::Display::ROTATE_90:
+      hotpoint->SetPoint(bitmap->height() - hotpoint->y(), hotpoint->x());
+      *bitmap = SkBitmapOperations::Rotate(
+          *bitmap, SkBitmapOperations::ROTATION_90_CW);
+      break;
+    case gfx::Display::ROTATE_180:
+      hotpoint->SetPoint(
+          bitmap->width() - hotpoint->x(), bitmap->height() - hotpoint->y());
+      *bitmap = SkBitmapOperations::Rotate(
+          *bitmap, SkBitmapOperations::ROTATION_180_CW);
+      break;
+    case gfx::Display::ROTATE_270:
+      hotpoint->SetPoint(hotpoint->y(), bitmap->width() - hotpoint->x());
+      *bitmap = SkBitmapOperations::Rotate(
+          *bitmap, SkBitmapOperations::ROTATION_270_CW);
+      break;
+  }
+
+  if (scale < FLT_EPSILON) {
+    NOTREACHED() << "Scale must be larger than 0.";
+    scale = 1.0f;
+  }
+
+  if (scale == 1.0f)
+    return;
+
+  gfx::Size scaled_size = gfx::ToFlooredSize(
+      gfx::ScaleSize(gfx::Size(bitmap->width(), bitmap->height()), scale));
+
+  *bitmap = skia::ImageOperations::Resize(
+      *bitmap,
+      skia::ImageOperations::RESIZE_BETTER,
+      scaled_size.width(),
+      scaled_size.height());
+  *hotpoint = gfx::ToFlooredPoint(gfx::ScalePoint(*hotpoint, scale));
+}
+
+}  // namespace ui
diff --git a/ui/base/cursor/cursor_util.h b/ui/base/cursor/cursor_util.h
new file mode 100644
index 0000000..1625156
--- /dev/null
+++ b/ui/base/cursor/cursor_util.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_CURSOR_CURSOR_UTIL_H_
+#define UI_BASE_CURSOR_CURSOR_UTIL_H_
+
+#include "base/compiler_specific.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/ui_base_export.h"
+#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/point.h"
+
+namespace ui {
+
+// Scale and rotate the cursor's bitmap and hotpoint.
+// |bitmap_in_out| and |hotpoint_in_out| are used as
+// both input and output.
+UI_BASE_EXPORT void ScaleAndRotateCursorBitmapAndHotpoint(
+    float scale,
+    gfx::Display::Rotation rotation,
+    SkBitmap* bitmap_in_out,
+    gfx::Point* hotpoint_in_out);
+
+}  // namespace ui
+
+#endif  // UI_BASE_CURSOR_CURSOR_UTIL_H_
diff --git a/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc b/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
index 4472023..c24c80f 100644
--- a/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
+++ b/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
@@ -5,6 +5,8 @@
 #include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
 
 #include "base/logging.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/cursor/cursors_aura.h"
 
 namespace ui {
 
@@ -27,9 +29,17 @@
 PlatformCursor BitmapCursorFactoryOzone::GetDefaultCursor(int type) {
   if (type == kCursorNone)
     return NULL;  // NULL is used for hidden cursor.
-  // TODO(spang): Use ChromeOS cursor bitmaps as default cursors.
-  LOG(FATAL) << "default cursors not yet supported";
-  return NULL;  // not reached
+
+  if (!default_cursors_.count(type)) {
+    // Create new owned image cursor from default aura bitmap for this type.
+    SkBitmap bitmap;
+    gfx::Point hotspot;
+    CHECK(GetCursorBitmap(type, &bitmap, &hotspot));
+    default_cursors_[type] = new BitmapCursorOzone(bitmap, hotspot);
+  }
+
+  // Returned owned default cursor for this type.
+  return default_cursors_[type];
 }
 
 PlatformCursor BitmapCursorFactoryOzone::CreateImageCursor(
diff --git a/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h b/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h
index 88b2404..aef4d7c 100644
--- a/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h
+++ b/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h
@@ -5,6 +5,8 @@
 #ifndef UI_BASE_CURSOR_OZONE_BITMAP_CURSOR_FACTORY_OZONE_H_
 #define UI_BASE_CURSOR_OZONE_BITMAP_CURSOR_FACTORY_OZONE_H_
 
+#include <map>
+
 #include "base/memory/ref_counted.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/base/cursor/cursor.h"
@@ -30,6 +32,8 @@
 
   SkBitmap bitmap_;
   gfx::Point hotspot_;
+
+  DISALLOW_COPY_AND_ASSIGN(BitmapCursorOzone);
 };
 
 // CursorFactoryOzone implementation for bitmapped cursors.
@@ -57,6 +61,13 @@
   // subclasses. If the cursor is hidden (kCursorNone) then cursor is NULL.
   virtual void SetBitmapCursor(gfx::AcceleratedWidget window,
                                scoped_refptr<BitmapCursorOzone> cursor);
+
+ private:
+  // Default cursors are cached & owned by the factory.
+  typedef std::map<int, scoped_refptr<BitmapCursorOzone> > DefaultCursorMap;
+  DefaultCursorMap default_cursors_;
+
+  DISALLOW_COPY_AND_ASSIGN(BitmapCursorFactoryOzone);
 };
 
 }  // namespace ui
diff --git a/ui/base/dragdrop/drag_utils.cc b/ui/base/dragdrop/drag_utils.cc
index d2caaeb..7be094f 100644
--- a/ui/base/dragdrop/drag_utils.cc
+++ b/ui/base/dragdrop/drag_utils.cc
@@ -41,8 +41,10 @@
 
   // Overridden from gfx::CanvasImageSource.
   virtual void Draw(gfx::Canvas* canvas) OVERRIDE {
-    // Paint the icon.
-    canvas->DrawImageInt(icon_, (size().width() - icon_.width()) / 2, 0);
+    if (!icon_.isNull()) {
+      // Paint the icon.
+      canvas->DrawImageInt(icon_, (size().width() - icon_.width()) / 2, 0);
+    }
 
     base::string16 name = file_name_.BaseName().LossyDisplayName();
     const int flags = gfx::Canvas::TEXT_ALIGN_CENTER;
@@ -81,11 +83,10 @@
 }  // namespace
 
 void CreateDragImageForFile(const base::FilePath& file_name,
-                            const gfx::ImageSkia* icon,
+                            const gfx::ImageSkia& icon,
                             ui::OSExchangeData* data_object) {
-  DCHECK(icon);
   DCHECK(data_object);
-  gfx::CanvasImageSource* source = new FileDragImageSource(file_name, *icon);
+  gfx::CanvasImageSource* source = new FileDragImageSource(file_name, icon);
   gfx::Size size = source->size();
   // ImageSkia takes ownership of |source|.
   gfx::ImageSkia image = gfx::ImageSkia(source, size);
diff --git a/ui/base/dragdrop/drag_utils.h b/ui/base/dragdrop/drag_utils.h
index 5b7235f..f035561 100644
--- a/ui/base/dragdrop/drag_utils.h
+++ b/ui/base/dragdrop/drag_utils.h
@@ -28,10 +28,10 @@
 
 // Creates a dragging image to be displayed when the user drags a file from
 // Chrome (via the download manager, for example). The drag image is set into
-// the supplied data_object. 'file_name' can be a full path, but the directory
-// portion will be truncated in the drag image.
+// the supplied data_object. |file_name| can be a full path, but the directory
+// portion will be truncated in the drag image. |icon| can be empty.
 UI_BASE_EXPORT void CreateDragImageForFile(const base::FilePath& file_name,
-                                           const gfx::ImageSkia* icon,
+                                           const gfx::ImageSkia& icon,
                                            ui::OSExchangeData* data_object);
 
 // Sets the drag image on data_object from the supplied canvas. width/height
diff --git a/ui/base/dragdrop/file_info.cc b/ui/base/dragdrop/file_info.cc
new file mode 100644
index 0000000..e5b894a
--- /dev/null
+++ b/ui/base/dragdrop/file_info.cc
@@ -0,0 +1,17 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/dragdrop/file_info.h"
+
+namespace ui {
+
+FileInfo::FileInfo() {}
+
+FileInfo::FileInfo(const base::FilePath& path,
+                   const base::FilePath& display_name)
+    : path(path), display_name(display_name) {}
+
+FileInfo::~FileInfo() {}
+
+}  // namespace ui
diff --git a/ui/base/dragdrop/file_info.h b/ui/base/dragdrop/file_info.h
new file mode 100644
index 0000000..6e4f456
--- /dev/null
+++ b/ui/base/dragdrop/file_info.h
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_DRAGDROP_FILE_INFO_H_
+#define UI_BASE_DRAGDROP_FILE_INFO_H_
+
+#include "base/files/file_path.h"
+#include "ui/base/ui_base_export.h"
+
+namespace ui {
+
+// struct that bundles a file's path with an optional display name.
+struct UI_BASE_EXPORT FileInfo {
+  FileInfo();
+  FileInfo(const base::FilePath& path, const base::FilePath& display_name);
+  ~FileInfo();
+
+  base::FilePath path;
+  base::FilePath display_name;  // Optional.
+};
+
+}  // namespace ui
+
+#endif  // UI_BASE_DRAGDROP_FILE_INFO_H_
diff --git a/ui/base/dragdrop/gtk_dnd_util.cc b/ui/base/dragdrop/gtk_dnd_util.cc
index 163dce4..1282723 100644
--- a/ui/base/dragdrop/gtk_dnd_util.cc
+++ b/ui/base/dragdrop/gtk_dnd_util.cc
@@ -55,6 +55,11 @@
           ui::GetAtomForTarget(ui::CUSTOM_DATA), 0, ui::CUSTOM_DATA);
       break;
 
+    case ui::RENDERER_TAINT:
+      gtk_target_list_add(targets,
+          ui::GetAtomForTarget(ui::RENDERER_TAINT), 0, ui::RENDERER_TAINT);
+      break;
+
     default:
       NOTREACHED() << " Unexpected target code: " << target_code;
   }
@@ -114,6 +119,11 @@
           kMimeTypeWebCustomData, false);
       return kCustomData;
 
+    case RENDERER_TAINT:
+      static const GdkAtom kRendererTaint = gdk_atom_intern(
+          "chromium/x-renderer-taint", false);
+      return kRendererTaint;
+
     default:
       NOTREACHED();
   }
diff --git a/ui/base/dragdrop/gtk_dnd_util.h b/ui/base/dragdrop/gtk_dnd_util.h
index b07a86d..33ee837 100644
--- a/ui/base/dragdrop/gtk_dnd_util.h
+++ b/ui/base/dragdrop/gtk_dnd_util.h
@@ -39,7 +39,11 @@
 
   // Custom data for web drag/drop.
   CUSTOM_DATA = 1 << 10,
-  INVALID_TARGET = 1 << 11,
+
+  // Tracks if the drag originated from the renderer.
+  RENDERER_TAINT = 1 << 11,
+
+  INVALID_TARGET = 1 << 12,
 };
 
 // Get the atom for a given target (of the above enum type). Will return NULL
diff --git a/ui/base/dragdrop/os_exchange_data.cc b/ui/base/dragdrop/os_exchange_data.cc
index cc81693..64c8093 100644
--- a/ui/base/dragdrop/os_exchange_data.cc
+++ b/ui/base/dragdrop/os_exchange_data.cc
@@ -18,15 +18,6 @@
 
 OSExchangeData::DownloadFileInfo::~DownloadFileInfo() {}
 
-OSExchangeData::FileInfo::FileInfo(
-    const base::FilePath& path,
-    const base::FilePath& display_name)
-    : path(path),
-      display_name(display_name) {
-}
-
-OSExchangeData::FileInfo::~FileInfo() {}
-
 OSExchangeData::OSExchangeData() : provider_(CreateProvider()) {
 }
 
@@ -36,6 +27,14 @@
 OSExchangeData::~OSExchangeData() {
 }
 
+void OSExchangeData::MarkOriginatedFromRenderer() {
+  provider_->MarkOriginatedFromRenderer();
+}
+
+bool OSExchangeData::DidOriginateFromRenderer() const {
+  return provider_->DidOriginateFromRenderer();
+}
+
 void OSExchangeData::SetString(const base::string16& data) {
   provider_->SetString(data);
 }
@@ -137,10 +136,6 @@
 void OSExchangeData::SetDownloadFileInfo(const DownloadFileInfo& download) {
   provider_->SetDownloadFileInfo(download);
 }
-
-void OSExchangeData::SetInDragLoop(bool in_drag_loop) {
-  provider_->SetInDragLoop(in_drag_loop);
-}
 #endif
 
 #if defined(OS_WIN) || defined(USE_AURA)
diff --git a/ui/base/dragdrop/os_exchange_data.h b/ui/base/dragdrop/os_exchange_data.h
index 8b848ce..5a1cbd5 100644
--- a/ui/base/dragdrop/os_exchange_data.h
+++ b/ui/base/dragdrop/os_exchange_data.h
@@ -33,6 +33,8 @@
 
 namespace ui {
 
+struct FileInfo;
+
 ///////////////////////////////////////////////////////////////////////////////
 //
 // OSExchangeData
@@ -82,17 +84,6 @@
     scoped_refptr<DownloadFileProvider> downloader;
   };
 
-  // Encapsulates the info about a file.
-  struct UI_BASE_EXPORT FileInfo {
-    FileInfo(const base::FilePath& path, const base::FilePath& display_name);
-    ~FileInfo();
-
-    // The path of the file.
-    base::FilePath path;
-    // The display name of the file. This field is optional.
-    base::FilePath display_name;
-  };
-
   // Provider defines the platform specific part of OSExchangeData that
   // interacts with the native system.
   class UI_BASE_EXPORT Provider {
@@ -102,6 +93,9 @@
 
     virtual Provider* Clone() const = 0;
 
+    virtual void MarkOriginatedFromRenderer() = 0;
+    virtual bool DidOriginateFromRenderer() const = 0;
+
     virtual void SetString(const base::string16& data) = 0;
     virtual void SetURL(const GURL& url, const base::string16& title) = 0;
     virtual void SetFilename(const base::FilePath& path) = 0;
@@ -125,14 +119,15 @@
     virtual bool HasFile() const = 0;
     virtual bool HasCustomFormat(const CustomFormat& format) const = 0;
 
-#if defined(OS_WIN)
+#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
     virtual void SetFileContents(const base::FilePath& filename,
                                  const std::string& file_contents) = 0;
+#endif
+#if defined(OS_WIN)
     virtual bool GetFileContents(base::FilePath* filename,
                                  std::string* file_contents) const = 0;
     virtual bool HasFileContents() const = 0;
     virtual void SetDownloadFileInfo(const DownloadFileInfo& download) = 0;
-    virtual void SetInDragLoop(bool in_drag_loop) = 0;
 #endif
 
 #if defined(OS_WIN) || defined(USE_AURA)
@@ -163,6 +158,12 @@
   const Provider& provider() const { return *provider_; }
   Provider& provider() { return *provider_; }
 
+  // Marks drag data as tainted if it originates from the renderer. This is used
+  // to avoid granting privileges to a renderer when dragging in tainted data,
+  // since it could allow potential escalation of privileges.
+  void MarkOriginatedFromRenderer();
+  bool DidOriginateFromRenderer() const;
+
   // These functions add data to the OSExchangeData object of various Chrome
   // types. The OSExchangeData object takes care of translating the data into
   // a format suitable for exchange with the OS.
@@ -211,7 +212,8 @@
                      const std::set<CustomFormat>& custom_formats) const;
 
 #if defined(OS_WIN)
-  // Adds the bytes of a file (CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR).
+  // Adds the bytes of a file (CFSTR_FILECONTENTS and CFSTR_FILEDESCRIPTOR on
+  // Windows).
   void SetFileContents(const base::FilePath& filename,
                        const std::string& file_contents);
   bool GetFileContents(base::FilePath* filename,
@@ -219,8 +221,6 @@
 
   // Adds a download file with full path (CF_HDROP).
   void SetDownloadFileInfo(const DownloadFileInfo& download);
-
-  void SetInDragLoop(bool in_drag_loop);
 #endif
 
 #if defined(OS_WIN) || defined(USE_AURA)
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aura.cc b/ui/base/dragdrop/os_exchange_data_provider_aura.cc
index f98cf9c..2a44793 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aura.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_aura.cc
@@ -9,6 +9,7 @@
 #include "net/base/net_util.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/dragdrop/file_info.h"
 
 namespace ui {
 
@@ -33,6 +34,15 @@
   return ret;
 }
 
+void OSExchangeDataProviderAura::MarkOriginatedFromRenderer() {
+  // TODO(dcheng): Currently unneeded because ChromeOS Aura correctly separates
+  // URL and filename metadata, and does not implement the DownloadURL protocol.
+}
+
+bool OSExchangeDataProviderAura::DidOriginateFromRenderer() const {
+  return false;
+}
+
 void OSExchangeDataProviderAura::SetString(const base::string16& data) {
   string_ = data;
   formats_ |= OSExchangeData::STRING;
@@ -49,12 +59,12 @@
 
 void OSExchangeDataProviderAura::SetFilename(const base::FilePath& path) {
   filenames_.clear();
-  filenames_.push_back(OSExchangeData::FileInfo(path, base::FilePath()));
+  filenames_.push_back(FileInfo(path, base::FilePath()));
   formats_ |= OSExchangeData::FILE_NAME;
 }
 
 void OSExchangeDataProviderAura::SetFilenames(
-    const std::vector<OSExchangeData::FileInfo>& filenames) {
+    const std::vector<FileInfo>& filenames) {
   filenames_ = filenames;
   formats_ |= OSExchangeData::FILE_NAME;
 }
@@ -100,7 +110,7 @@
 }
 
 bool OSExchangeDataProviderAura::GetFilenames(
-    std::vector<OSExchangeData::FileInfo>* filenames) const {
+    std::vector<FileInfo>* filenames) const {
   if ((formats_ & OSExchangeData::FILE_NAME) == 0)
     return false;
   *filenames = filenames_;
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aura.h b/ui/base/dragdrop/os_exchange_data_provider_aura.h
index 410bc86..e54a2fd 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aura.h
+++ b/ui/base/dragdrop/os_exchange_data_provider_aura.h
@@ -27,11 +27,12 @@
 
   // Overridden from OSExchangeData::Provider:
   virtual Provider* Clone() const OVERRIDE;
+  virtual void MarkOriginatedFromRenderer() OVERRIDE;
+  virtual bool DidOriginateFromRenderer() const OVERRIDE;
   virtual void SetString(const base::string16& data) OVERRIDE;
   virtual void SetURL(const GURL& url, const base::string16& title) OVERRIDE;
   virtual void SetFilename(const base::FilePath& path) OVERRIDE;
-  virtual void SetFilenames(
-      const std::vector<OSExchangeData::FileInfo>& filenames) OVERRIDE;
+  virtual void SetFilenames(const std::vector<FileInfo>& filenames) OVERRIDE;
   virtual void SetPickledData(const OSExchangeData::CustomFormat& format,
                               const Pickle& data) OVERRIDE;
   virtual bool GetString(base::string16* data) const OVERRIDE;
@@ -39,8 +40,7 @@
                               GURL* url,
                               base::string16* title) const OVERRIDE;
   virtual bool GetFilename(base::FilePath* path) const OVERRIDE;
-  virtual bool GetFilenames(
-      std::vector<OSExchangeData::FileInfo>* filenames) const OVERRIDE;
+  virtual bool GetFilenames(std::vector<FileInfo>* filenames) const OVERRIDE;
   virtual bool GetPickledData(const OSExchangeData::CustomFormat& format,
                               Pickle* data) const OVERRIDE;
   virtual bool HasString() const OVERRIDE;
@@ -78,7 +78,7 @@
   base::string16 title_;
 
   // File name.
-  std::vector<OSExchangeData::FileInfo> filenames_;
+  std::vector<FileInfo> filenames_;
 
   // PICKLED_DATA contents.
   PickleData pickle_data_;
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc b/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
index 15ab97d..2f013ec 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
@@ -12,6 +12,7 @@
 #include "net/base/net_util.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
+#include "ui/base/dragdrop/file_info.h"
 #include "ui/base/x/selection_utils.h"
 #include "ui/base/x/x11_util.h"
 
@@ -25,6 +26,9 @@
 namespace {
 
 const char kDndSelection[] = "XdndSelection";
+const char kRendererTaint[] = "chromium/x-renderer-taint";
+
+const char kNetscapeURL[] = "_NETSCAPE_URL";
 
 const char* kAtomsToCache[] = {
   kString,
@@ -33,7 +37,9 @@
   kDndSelection,
   Clipboard::kMimeTypeURIList,
   kMimeTypeMozillaURL,
+  kNetscapeURL,
   Clipboard::kMimeTypeText,
+  kRendererTaint,
   NULL
 };
 
@@ -108,6 +114,18 @@
   return ret;
 }
 
+void OSExchangeDataProviderAuraX11::MarkOriginatedFromRenderer() {
+  std::string empty;
+  format_map_.Insert(atom_cache_.GetAtom(kRendererTaint),
+                     scoped_refptr<base::RefCountedMemory>(
+                         base::RefCountedString::TakeString(&empty)));
+}
+
+bool OSExchangeDataProviderAuraX11::DidOriginateFromRenderer() const {
+  return format_map_.find(atom_cache_.GetAtom(kRendererTaint)) !=
+         format_map_.end();
+}
+
 void OSExchangeDataProviderAuraX11::SetString(const base::string16& text_data) {
   std::string utf8 = base::UTF16ToUTF8(text_data);
   scoped_refptr<base::RefCountedMemory> mem(
@@ -121,8 +139,10 @@
 
 void OSExchangeDataProviderAuraX11::SetURL(const GURL& url,
                                            const base::string16& title) {
-  // Mozilla's URL format: (UTF16: URL, newline, title)
+  // TODO(dcheng): The original GTK code tries very hard to avoid writing out an
+  // empty title. Is this necessary?
   if (url.is_valid()) {
+    // Mozilla's URL format: (UTF16: URL, newline, title)
     base::string16 spec = base::UTF8ToUTF16(url.spec());
 
     std::vector<unsigned char> data;
@@ -134,21 +154,34 @@
 
     format_map_.Insert(atom_cache_.GetAtom(kMimeTypeMozillaURL), mem);
 
+    // Set _NETSCAPE_URL as well, since some file managers like Nautilus use it
+    // to create a link to the URL. Setting text/uri-list doesn't work as well,
+    // because Nautilus tries to fetch the contents of the URL instead.
+    // Format is UTF8: URL + "\n" + title.
+    std::string netscape_url = url.spec();
+    netscape_url += "\n";
+    netscape_url += base::UTF16ToUTF8(title);
+    format_map_.Insert(atom_cache_.GetAtom(kNetscapeURL),
+                       scoped_refptr<base::RefCountedMemory>(
+                           base::RefCountedString::TakeString(&netscape_url)));
+
+    // And finally a string fallback as well.
     SetString(spec);
   }
 }
 
 void OSExchangeDataProviderAuraX11::SetFilename(const base::FilePath& path) {
-  std::vector<OSExchangeData::FileInfo> data;
-  data.push_back(OSExchangeData::FileInfo(path, base::FilePath()));
+  std::vector<FileInfo> data;
+  data.push_back(FileInfo(path, base::FilePath()));
   SetFilenames(data);
 }
 
 void OSExchangeDataProviderAuraX11::SetFilenames(
-    const std::vector<OSExchangeData::FileInfo>& filenames) {
+    const std::vector<FileInfo>& filenames) {
   std::vector<std::string> paths;
-  for (std::vector<OSExchangeData::FileInfo>::const_iterator it =
-           filenames.begin(); it != filenames.end(); ++it) {
+  for (std::vector<FileInfo>::const_iterator it = filenames.begin();
+       it != filenames.end();
+       ++it) {
     std::string url_spec = net::FilePathToFileURL(it->path).spec();
     if (!url_spec.empty())
       paths.push_back(url_spec);
@@ -246,7 +279,7 @@
 }
 
 bool OSExchangeDataProviderAuraX11::GetFilename(base::FilePath* path) const {
-  std::vector<OSExchangeData::FileInfo> filenames;
+  std::vector<FileInfo> filenames;
   if (GetFilenames(&filenames)) {
     *path = filenames.front().path;
     return true;
@@ -256,7 +289,7 @@
 }
 
 bool OSExchangeDataProviderAuraX11::GetFilenames(
-    std::vector<OSExchangeData::FileInfo>* filenames) const {
+    std::vector<FileInfo>* filenames) const {
   std::vector< ::Atom> url_atoms = ui::GetURIListAtomsFrom(&atom_cache_);
   std::vector< ::Atom> requested_types;
   ui::GetAtomIntersection(url_atoms, GetTargets(), &requested_types);
@@ -270,8 +303,7 @@
       GURL url(*it);
       base::FilePath file_path;
       if (url.SchemeIsFile() && net::FileURLToFilePath(url, &file_path)) {
-        filenames->push_back(OSExchangeData::FileInfo(file_path,
-                                                      base::FilePath()));
+        filenames->push_back(FileInfo(file_path, base::FilePath()));
       }
     }
   }
@@ -373,6 +405,40 @@
   return !requested_types.empty();
 }
 
+void OSExchangeDataProviderAuraX11::SetFileContents(
+    const base::FilePath& filename,
+    const std::string& file_contents) {
+  DCHECK(!filename.empty());
+
+  file_contents_name_ = filename;
+
+  // Direct save handling is a complicated juggling affair between this class,
+  // SelectionFormat, and DesktopDragDropClientAuraX11. The general idea behind
+  // the protocol is this:
+  // - The source window sets its XdndDirectSave0 window property to the
+  //   proposed filename.
+  // - When a target window receives the drop, it updates the XdndDirectSave0
+  //   property on the source window to the filename it would like the contents
+  //   to be saved to and then requests the XdndDirectSave0 type from the
+  //   source.
+  // - The source is supposed to copy the file here and return success (S),
+  //   failure (F), or error (E).
+  // - In this case, failure means the destination should try to populate the
+  //   file itself by copying the data from application/octet-stream. To make
+  //   things simpler for Chrome, we always 'fail' and let the destination do
+  //   the work.
+  std::string failure("F");
+  format_map_.Insert(
+      atom_cache_.GetAtom("XdndDirectSave0"),
+                          scoped_refptr<base::RefCountedMemory>(
+                              base::RefCountedString::TakeString(&failure)));
+  std::string file_contents_copy = file_contents;
+  format_map_.Insert(
+      atom_cache_.GetAtom("application/octet-stream"),
+      scoped_refptr<base::RefCountedMemory>(
+          base::RefCountedString::TakeString(&file_contents_copy)));
+}
+
 void OSExchangeDataProviderAuraX11::SetHtml(const base::string16& html,
                                             const GURL& base_url) {
   std::vector<unsigned char> bytes;
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aurax11.h b/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
index a336206..40c0deb 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
+++ b/ui/base/dragdrop/os_exchange_data_provider_aurax11.h
@@ -56,13 +56,18 @@
   // Makes a copy of the format map currently being offered.
   SelectionFormatMap GetFormatMap() const;
 
+  const base::FilePath& file_contents_name() const {
+    return file_contents_name_;
+  }
+
   // Overridden from OSExchangeData::Provider:
   virtual Provider* Clone() const OVERRIDE;
+  virtual void MarkOriginatedFromRenderer() OVERRIDE;
+  virtual bool DidOriginateFromRenderer() const OVERRIDE;
   virtual void SetString(const base::string16& data) OVERRIDE;
   virtual void SetURL(const GURL& url, const base::string16& title) OVERRIDE;
   virtual void SetFilename(const base::FilePath& path) OVERRIDE;
-  virtual void SetFilenames(
-      const std::vector<OSExchangeData::FileInfo>& filenames) OVERRIDE;
+  virtual void SetFilenames(const std::vector<FileInfo>& filenames) OVERRIDE;
   virtual void SetPickledData(const OSExchangeData::CustomFormat& format,
                               const Pickle& pickle) OVERRIDE;
   virtual bool GetString(base::string16* data) const OVERRIDE;
@@ -70,8 +75,7 @@
                               GURL* url,
                               base::string16* title) const OVERRIDE;
   virtual bool GetFilename(base::FilePath* path) const OVERRIDE;
-  virtual bool GetFilenames(
-      std::vector<OSExchangeData::FileInfo>* filenames) const OVERRIDE;
+  virtual bool GetFilenames(std::vector<FileInfo>* filenames) const OVERRIDE;
   virtual bool GetPickledData(const OSExchangeData::CustomFormat& format,
                               Pickle* pickle) const OVERRIDE;
   virtual bool HasString() const OVERRIDE;
@@ -81,6 +85,9 @@
   virtual bool HasCustomFormat(const OSExchangeData::CustomFormat& format) const
       OVERRIDE;
 
+  virtual void SetFileContents(const base::FilePath& filename,
+                               const std::string& file_contents) OVERRIDE;
+
   virtual void SetHtml(const base::string16& html,
                        const GURL& base_url) OVERRIDE;
   virtual bool GetHtml(base::string16* html, GURL* base_url) const OVERRIDE;
@@ -129,6 +136,9 @@
   // to |selection_owner_| when we take the selection.
   SelectionFormatMap format_map_;
 
+  // Auxilary data for the X Direct Save protocol.
+  base::FilePath file_contents_name_;
+
   // Takes a snapshot of |format_map_| and offers it to other windows.
   mutable SelectionOwner selection_owner_;
 
diff --git a/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc b/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc
index b62e0d9..1601007 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_aurax11_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/dragdrop/file_info.h"
 #include "url/gurl.h"
 
 const char kFileURL[] = "file:///home/user/file.txt";
@@ -88,7 +89,7 @@
   EXPECT_TRUE(provider.HasURL(ui::OSExchangeData::DO_NOT_CONVERT_FILENAMES));
 
   // We should only receive the file from GetFilenames().
-  std::vector<OSExchangeData::FileInfo> filenames;
+  std::vector<FileInfo> filenames;
   EXPECT_TRUE(provider.GetFilenames(&filenames));
   ASSERT_EQ(1u, filenames.size());
   EXPECT_EQ(kFileName, filenames[0].path.value());
diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.cc b/ui/base/dragdrop/os_exchange_data_provider_win.cc
index fa2052a..e4f117e 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_win.cc
+++ b/ui/base/dragdrop/os_exchange_data_provider_win.cc
@@ -18,11 +18,20 @@
 #include "net/base/net_util.h"
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/clipboard_util_win.h"
+#include "ui/base/dragdrop/file_info.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "url/gurl.h"
 
 namespace ui {
 
+static const OSExchangeData::CustomFormat& GetRendererTaintCustomType() {
+  CR_DEFINE_STATIC_LOCAL(
+      ui::OSExchangeData::CustomFormat,
+      format,
+      (ui::Clipboard::GetFormatType("chromium/x-renderer-taint")));
+  return format;
+}
+
 // Creates a new STGMEDIUM object to hold the specified text. The caller
 // owns the resulting object. The "Bytes" version does not NULL terminate, the
 // string version does.
@@ -269,6 +278,16 @@
   return new OSExchangeDataProviderWin(data_object());
 }
 
+void OSExchangeDataProviderWin::MarkOriginatedFromRenderer() {
+  STGMEDIUM* storage = GetStorageForString(std::string());
+  data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
+      GetRendererTaintCustomType().ToFormatEtc(), storage));
+}
+
+bool OSExchangeDataProviderWin::DidOriginateFromRenderer() const {
+  return HasCustomFormat(GetRendererTaintCustomType());
+}
+
 void OSExchangeDataProviderWin::SetString(const base::string16& data) {
   STGMEDIUM* storage = GetStorageForString(data);
   data_->contents_.push_back(new DataObjectImpl::StoredDataInfo(
@@ -334,7 +353,7 @@
 }
 
 void OSExchangeDataProviderWin::SetFilenames(
-    const std::vector<OSExchangeData::FileInfo>& filenames) {
+    const std::vector<FileInfo>& filenames) {
   for (size_t i = 0; i < filenames.size(); ++i) {
     STGMEDIUM* storage = GetStorageForFileName(filenames[i].path);
     DataObjectImpl::StoredDataInfo* info = new DataObjectImpl::StoredDataInfo(
@@ -421,14 +440,13 @@
 }
 
 bool OSExchangeDataProviderWin::GetFilenames(
-    std::vector<OSExchangeData::FileInfo>* filenames) const {
+    std::vector<FileInfo>* filenames) const {
   std::vector<base::string16> filenames_local;
   bool success = ClipboardUtil::GetFilenames(source_object_, &filenames_local);
   if (success) {
     for (size_t i = 0; i < filenames_local.size(); ++i)
       filenames->push_back(
-          OSExchangeData::FileInfo(base::FilePath(filenames_local[i]),
-                                   base::FilePath()));
+          FileInfo(base::FilePath(filenames_local[i]), base::FilePath()));
   }
   return success;
 }
@@ -519,11 +537,6 @@
   info->downloader = download.downloader;
   data_->contents_.push_back(info);
 }
-
-void OSExchangeDataProviderWin::SetInDragLoop(bool in_drag_loop) {
-  data_->set_in_drag_loop(in_drag_loop);
-}
-
 #if defined(USE_AURA)
 
 void OSExchangeDataProviderWin::SetDragImage(
diff --git a/ui/base/dragdrop/os_exchange_data_provider_win.h b/ui/base/dragdrop/os_exchange_data_provider_win.h
index 111ef3b..ffe37e7 100644
--- a/ui/base/dragdrop/os_exchange_data_provider_win.h
+++ b/ui/base/dragdrop/os_exchange_data_provider_win.h
@@ -149,11 +149,12 @@
 
   // OSExchangeData::Provider methods.
   virtual Provider* Clone() const;
+  virtual void MarkOriginatedFromRenderer();
+  virtual bool DidOriginateFromRenderer() const;
   virtual void SetString(const base::string16& data);
   virtual void SetURL(const GURL& url, const base::string16& title);
   virtual void SetFilename(const base::FilePath& path);
-  virtual void SetFilenames(
-      const std::vector<OSExchangeData::FileInfo>& filenames);
+  virtual void SetFilenames(const std::vector<FileInfo>& filenames);
   virtual void SetPickledData(const OSExchangeData::CustomFormat& format,
                               const Pickle& data);
   virtual void SetFileContents(const base::FilePath& filename,
@@ -165,8 +166,7 @@
                               GURL* url,
                               base::string16* title) const;
   virtual bool GetFilename(base::FilePath* path) const;
-  virtual bool GetFilenames(
-      std::vector<OSExchangeData::FileInfo>* filenames) const;
+  virtual bool GetFilenames(std::vector<FileInfo>* filenames) const;
   virtual bool GetPickledData(const OSExchangeData::CustomFormat& format,
                               Pickle* data) const;
   virtual bool GetFileContents(base::FilePath* filename,
@@ -181,7 +181,6 @@
       const OSExchangeData::CustomFormat& format) const;
   virtual void SetDownloadFileInfo(
       const OSExchangeData::DownloadFileInfo& download_info);
-  virtual void SetInDragLoop(bool in_drag_loop) OVERRIDE;
 #if defined(USE_AURA)
   virtual void SetDragImage(const gfx::ImageSkia& image,
                             const gfx::Vector2d& cursor_offset) OVERRIDE;
diff --git a/ui/base/ime/OWNERS b/ui/base/ime/OWNERS
index ec3410f..bc96702 100644
--- a/ui/base/ime/OWNERS
+++ b/ui/base/ime/OWNERS
@@ -1,11 +1,10 @@
-nona@chromium.org
-penghuang@chromium.org
-
-# Chrome OS IME
-komatsu@chromium.org
-
-# Windows Aura IME
-yukawa@chromium.org
-
-# Linux Aura IME
+# primary reviewer.
 yukishiino@chromium.org
+
+# backup reviewers.
+komatsu@chromium.org
+mukai@chromium.org
+nona@chromium.org
+
+# For Windows.
+yukawa@chromium.org
diff --git a/ui/base/ime/dummy_text_input_client.cc b/ui/base/ime/dummy_text_input_client.cc
index 711dfdd..b5cd729 100644
--- a/ui/base/ime/dummy_text_input_client.cc
+++ b/ui/base/ime/dummy_text_input_client.cc
@@ -7,14 +7,17 @@
 
 namespace ui {
 
-DummyTextInputClient::DummyTextInputClient() {
-}
+DummyTextInputClient::DummyTextInputClient()
+    : text_input_type_(TEXT_INPUT_TYPE_NONE) {}
+
+DummyTextInputClient::DummyTextInputClient(TextInputType text_input_type)
+    : text_input_type_(text_input_type) {}
 
 DummyTextInputClient::~DummyTextInputClient() {
 }
 
 void DummyTextInputClient::SetCompositionText(
-    const ui::CompositionText& composition) {
+    const CompositionText& composition) {
 }
 
 void DummyTextInputClient::ConfirmCompositionText() {
@@ -33,11 +36,11 @@
   return NULL;
 }
 
-ui::TextInputType DummyTextInputClient::GetTextInputType() const {
-  return TEXT_INPUT_TYPE_NONE;
+TextInputType DummyTextInputClient::GetTextInputType() const {
+  return text_input_type_;
 }
 
-ui::TextInputMode DummyTextInputClient::GetTextInputMode() const {
+TextInputMode DummyTextInputClient::GetTextInputMode() const {
   return TEXT_INPUT_MODE_DEFAULT;
 }
 
diff --git a/ui/base/ime/dummy_text_input_client.h b/ui/base/ime/dummy_text_input_client.h
index 5c8a52e..3961302 100644
--- a/ui/base/ime/dummy_text_input_client.h
+++ b/ui/base/ime/dummy_text_input_client.h
@@ -13,18 +13,18 @@
 class DummyTextInputClient : public TextInputClient {
  public:
   DummyTextInputClient();
+  explicit DummyTextInputClient(TextInputType text_input_type);
   virtual ~DummyTextInputClient();
 
   // Overriden from TextInputClient.
-  virtual void SetCompositionText(
-      const ui::CompositionText& composition) OVERRIDE;
+  virtual void SetCompositionText(const CompositionText& composition) OVERRIDE;
   virtual void ConfirmCompositionText() OVERRIDE;
   virtual void ClearCompositionText() OVERRIDE;
   virtual void InsertText(const base::string16& text) OVERRIDE;
   virtual void InsertChar(base::char16 ch, int flags) OVERRIDE;
   virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE;
-  virtual ui::TextInputType GetTextInputType() const OVERRIDE;
-  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE;
+  virtual TextInputType GetTextInputType() const OVERRIDE;
+  virtual TextInputMode GetTextInputMode() const OVERRIDE;
   virtual bool CanComposeInline() const OVERRIDE;
   virtual gfx::Rect GetCaretBounds() const OVERRIDE;
   virtual bool GetCompositionCharacterBounds(uint32 index,
@@ -45,6 +45,10 @@
   virtual void OnCandidateWindowShown() OVERRIDE;
   virtual void OnCandidateWindowUpdated() OVERRIDE;
   virtual void OnCandidateWindowHidden() OVERRIDE;
+
+  TextInputType text_input_type_;
+
+  DISALLOW_COPY_AND_ASSIGN(DummyTextInputClient);
 };
 
 }  // namespace ui
diff --git a/ui/base/layout.cc b/ui/base/layout.cc
index 2c1fb51..01c38f1 100644
--- a/ui/base/layout.cc
+++ b/ui/base/layout.cc
@@ -20,6 +20,7 @@
 
 #if defined(OS_WIN)
 #include "base/win/metro.h"
+#include "ui/gfx/win/dpi.h"
 #include <Windows.h>
 #endif  // defined(OS_WIN)
 
@@ -90,7 +91,7 @@
   for (std::vector<ScaleFactor>::const_iterator it =
           g_supported_scale_factors->begin();
        it != g_supported_scale_factors->end(); ++it) {
-    scales.push_back(GetImageScale(*it));
+    scales.push_back(kScaleFactorScales[*it]);
   }
   gfx::ImageSkia::SetSupportedScales(scales);
 }
@@ -117,7 +118,11 @@
 }
 
 float GetImageScale(ScaleFactor scale_factor) {
-  return kScaleFactorScales[scale_factor];
+#if defined(OS_WIN)
+  if (gfx::IsHighDPIEnabled())
+    return gfx::win::GetDeviceScaleFactor();
+#endif
+  return GetScaleForScaleFactor(scale_factor);
 }
 
 bool IsScaleFactorSupported(ScaleFactor scale_factor) {
@@ -144,6 +149,10 @@
   return closest_match;
 }
 
+float GetScaleForScaleFactor(ScaleFactor scale_factor) {
+  return kScaleFactorScales[scale_factor];
+}
+
 namespace test {
 
 ScopedSetSupportedScaleFactors::ScopedSetSupportedScaleFactors(
diff --git a/ui/base/layout.h b/ui/base/layout.h
index 2ea39a2..690335a 100644
--- a/ui/base/layout.h
+++ b/ui/base/layout.h
@@ -57,7 +57,8 @@
 // platform, in ascending order.
 UI_BASE_EXPORT const std::vector<ScaleFactor>& GetSupportedScaleFactors();
 
-// Returns the float scale value for |scale_factor|.
+// Returns the actual image scale to be used for the scale factor passed in.
+// On Windows high dpi, this returns the dpi scale for the display.
 UI_BASE_EXPORT float GetImageScale(ScaleFactor scale_factor);
 
 // Returns the supported ScaleFactor which most closely matches |scale|.
@@ -77,6 +78,9 @@
 // Finding the closest match is inefficient and shouldn't be done frequently.
 UI_BASE_EXPORT ScaleFactor FindClosestScaleFactorUnsafe(float scale);
 
+// Returns the image scale for the scale factor passed in.
+UI_BASE_EXPORT float GetScaleForScaleFactor(ScaleFactor scale_factor);
+
 namespace test {
 // Class which changes the value of GetSupportedScaleFactors() to
 // |new_scale_factors| for the duration of its lifetime.
diff --git a/ui/base/models/simple_menu_model.h b/ui/base/models/simple_menu_model.h
index 8cd936b..78c8fd6 100644
--- a/ui/base/models/simple_menu_model.h
+++ b/ui/base/models/simple_menu_model.h
@@ -27,6 +27,8 @@
  public:
   class UI_BASE_EXPORT Delegate {
    public:
+    virtual ~Delegate() {}
+
     // Methods for determining the state of specific command ids.
     virtual bool IsCommandIdChecked(int command_id) const = 0;
     virtual bool IsCommandIdEnabled(int command_id) const = 0;
@@ -63,9 +65,6 @@
 
     // Notifies the delegate that the menu has closed.
     virtual void MenuClosed(SimpleMenuModel* source);
-
-   protected:
-    virtual ~Delegate() {}
   };
 
   // The Delegate can be NULL, though if it is items can't be checked or
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index 36f0e77..daea33f 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -106,8 +106,6 @@
     ScaleFactor scale_factor = GetSupportedScaleFactor(scale);
     bool found = rb_->LoadBitmap(resource_id_, &scale_factor,
                                  &image, &fell_back_to_1x);
-    // Force to a supported scale.
-    scale = ui::GetImageScale(scale_factor);
     if (!found)
       return gfx::ImageSkiaRep();
 
@@ -131,8 +129,11 @@
         mask.eraseColor(SK_ColorRED);
         image = SkBitmapOperations::CreateBlendedBitmap(image, mask, 0.2);
       }
+    } else {
+      image = PlatformScaleImage(image,
+                                 ui::GetScaleForScaleFactor(scale_factor),
+                                 scale);
     }
-
     return gfx::ImageSkiaRep(image, scale);
   }
 
@@ -353,12 +354,13 @@
         "Missing call to SetResourcesDataDLL?";
 
 #if defined(OS_CHROMEOS) || defined(OS_WIN)
-    ui::ScaleFactor scale_factor_to_load = GetMaxScaleFactor();
+  ui::ScaleFactor scale_factor_to_load = GetMaxScaleFactor();
 #else
-    ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P;
+  ui::ScaleFactor scale_factor_to_load = ui::SCALE_FACTOR_100P;
 #endif
 
     float scale = GetImageScale(scale_factor_to_load);
+
     // TODO(oshima): Consider reading the image size from png IHDR chunk and
     // skip decoding here and remove #ifdef below.
     // ResourceBundle::GetSharedInstance() is destroyed after the
@@ -820,4 +822,13 @@
   return gfx::PNGCodec::Decode(buf, size, bitmap);
 }
 
+#if !defined(OS_WIN)
+// static
+SkBitmap ResourceBundle::PlatformScaleImage(const SkBitmap& image,
+                                            float loaded_image_scale,
+                                            float desired_scale) {
+  return image;
+}
+#endif
+
 }  // namespace ui
diff --git a/ui/base/resource/resource_bundle.h b/ui/base/resource/resource_bundle.h
index 809b112..93b50ea 100644
--- a/ui/base/resource/resource_bundle.h
+++ b/ui/base/resource/resource_bundle.h
@@ -353,6 +353,16 @@
 
   const base::FilePath& GetOverriddenPakPath();
 
+  // Platform specific image scaling is done here. Currently only implemented
+  // for Windows.
+  // |image| is the bitmap to be scaled.
+  // |loaded_image_scale| is the current scale of the bitmap.
+  // |desired_scale| is the desired scale of the bitmap.
+  // Returns the scaled bitmap or the original bitmap.
+ static SkBitmap PlatformScaleImage(const SkBitmap& image,
+                                    float loaded_image_scale,
+                                    float desired_scale);
+
   // This pointer is guaranteed to outlive the ResourceBundle instance and may
   // be NULL.
   Delegate* delegate_;
diff --git a/ui/base/resource/resource_bundle_win.cc b/ui/base/resource/resource_bundle_win.cc
index be73085..13f74e0 100644
--- a/ui/base/resource/resource_bundle_win.cc
+++ b/ui/base/resource/resource_bundle_win.cc
@@ -7,9 +7,13 @@
 #include "base/logging.h"
 #include "base/path_service.h"
 #include "base/strings/utf_string_conversions.h"
+#include "skia/ext/image_operations.h"
 #include "ui/base/layout.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/resource/resource_data_dll_win.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_source.h"
 #include "ui/gfx/win/dpi.h"
 
 namespace ui {
@@ -61,6 +65,34 @@
   return GetImageNamed(resource_id);
 }
 
+// static
+SkBitmap ResourceBundle::PlatformScaleImage(const SkBitmap& image,
+                                            float loaded_image_scale,
+                                            float desired_bitmap_scale) {
+  if (!gfx::IsHighDPIEnabled())
+    return image;
+
+  // On Windows we can have multiple device scales like 1/1.25/1.5/2, etc.
+  // We only have 1x and 2x data packs. We need to scale the bitmaps
+  // accordingly.
+  if (loaded_image_scale == desired_bitmap_scale)
+    return image;
+
+  SkBitmap scaled_image;
+  gfx::Size unscaled_size(image.width(), image.height());
+  gfx::Size scaled_size = ToCeiledSize(
+      gfx::ScaleSize(unscaled_size,
+                      desired_bitmap_scale / loaded_image_scale));
+  scaled_image = skia::ImageOperations::Resize(
+      image,
+      skia::ImageOperations::RESIZE_LANCZOS3,
+      scaled_size.width(),
+      scaled_size.height());
+  DCHECK_EQ(scaled_image.width(), scaled_size.width());
+  DCHECK_EQ(scaled_image.height(), scaled_size.height());
+  return scaled_image;
+}
+
 void SetResourcesDataDLL(HINSTANCE handle) {
   resources_data_dll = handle;
 }
diff --git a/ui/base/strings/app_locale_settings_ar.xtb b/ui/base/strings/app_locale_settings_ar.xtb
index bc74a3b..6eb1ddc 100644
--- a/ui/base/strings/app_locale_settings_ar.xtb
+++ b/ui/base/strings/app_locale_settings_ar.xtb
@@ -2,8 +2,8 @@
 <!DOCTYPE translationbundle>
 <translationbundle lang="ar">
 <translation id="IDS_MINIMUM_UI_FONT_SIZE">10</translation>
-<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI,Droid Arabic Kufi,ui-sans, 13px</translation>
+<translation id="IDS_UI_FONT_FAMILY_CROS">Noto Sans UI, Noto Naskh Arabic UI, ui-sans, 13px</translation>
 <if expr="chromeos">
-  <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI, Droid Arabic Naskh, sans-serif</translation>
+  <translation id="IDS_WEB_FONT_FAMILY">Noto Sans UI, Noto Naskh Arabic UI, sans-serif</translation>
 </if>
 </translationbundle>
diff --git a/ui/base/strings/ui_strings.grd b/ui/base/strings/ui_strings.grd
index 3ff5014..9b0d714 100644
--- a/ui/base/strings/ui_strings.grd
+++ b/ui/base/strings/ui_strings.grd
@@ -1878,7 +1878,7 @@
         Scroll Down
       </message>
 
-      <!-- Edit field context menu item labels. -->
+      <!-- Textfield context menu item labels. -->
       <message name="IDS_APP_UNDO" desc="The text label of the Undo menu item">
         &amp;Undo
       </message>
@@ -1898,6 +1898,66 @@
         Select &amp;all
       </message>
 
+      <!-- Textfield editing commands; their actual string contents are unused. -->
+      <!-- These match third_party/WebKit/Source/core/editing/EditorCommand.cpp. -->
+      <message name="IDS_DELETE_BACKWARD" desc="A command to delete backward.">
+        Delete Backward
+      </message>
+      <message name="IDS_DELETE_FORWARD" desc="A command to delete forward.">
+        Delete Forward
+      </message>
+      <message name="IDS_DELETE_TO_BEGINNING_OF_LINE" desc="A command to delete to the beginning of the line.">
+        Delete To Beginning Of Line
+      </message>
+      <message name="IDS_DELETE_TO_END_OF_LINE" desc="A command to delete to the end of the line.">
+        Delete To End Of Line
+      </message>
+      <message name="IDS_DELETE_WORD_BACKWARD" desc="A command to delete backward by a word.">
+        Delete Word Backward
+      </message>
+      <message name="IDS_DELETE_WORD_FORWARD" desc="A command to delete forward by a word.">
+        Delete Word Forward
+      </message>
+      <message name="IDS_MOVE_LEFT" desc="A command to move the cursor left.">
+        Move Left
+      </message>
+      <message name="IDS_MOVE_LEFT_AND_MODIFY_SELECTION" desc="A command to move the cursor left and modify the selection.">
+        Move Left And Modify Selection
+      </message>
+      <message name="IDS_MOVE_RIGHT" desc="A command to move the cursor right.">
+        Move Right
+      </message>
+      <message name="IDS_MOVE_RIGHT_AND_MODIFY_SELECTION" desc="A command to move the cursor right and modify the selection.">
+        Move Right And Modify Selection
+      </message>
+      <message name="IDS_MOVE_WORD_LEFT" desc="A command to move the cursor left to the next word break.">
+        Move Word Left
+      </message>
+      <message name="IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION" desc="A command to move the cursor left to the next word break and modify the selection.">
+        Move Word Left And Modify Selection
+      </message>
+      <message name="IDS_MOVE_WORD_RIGHT" desc="A command to move the cursor right to the next word break.">
+        Move Word Right
+      </message>
+      <message name="IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION" desc="A command to move the cursor right to the next word break and modify the selection.">
+        Move Word Right And Modify Selection
+      </message>
+      <message name="IDS_MOVE_TO_BEGINNING_OF_LINE" desc="A command to move the cursor to the beginning of the line.">
+        Move To Beginning Of Line
+      </message>
+      <message name="IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION" desc="A command to move the cursor to the beginning of the line and modify the selection.">
+        Move To Beginning Of Line And Modify Selection
+      </message>
+      <message name="IDS_MOVE_TO_END_OF_LINE" desc="A command to move the cursor to the end of the line.">
+        Move To End Of Line
+      </message>
+      <message name="IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION" desc="A command to move the cursor to the end of the line and modify the selection.">
+        Move To End Of Line And Modify Selection
+      </message>
+      <message name="IDS_APP_REDO" desc="A command to redo an action.">
+        Redo
+      </message>
+
       <!-- Generic terms -->
       <message name="IDS_APP_OK" desc="Used for Ok on buttons">
         OK
diff --git a/ui/base/strings/ui_strings.gyp b/ui/base/strings/ui_strings.gyp
index a9f2bf7..1fee519 100644
--- a/ui/base/strings/ui_strings.gyp
+++ b/ui/base/strings/ui_strings.gyp
@@ -37,53 +37,4 @@
       },
     },
   ],
-  'conditions': [
-    ['OS != "mac"', {
-      'targets': [{
-        'target_name': 'ui_unittest_strings',
-        'type': 'none',
-        'dependencies': [
-          'ui_strings',
-        ],
-        'variables': {
-          'repack_path': '<(DEPTH)/tools/grit/grit/format/repack.py',
-          'conditions': [
-            ['OS == "ios"', {
-              'pak_output': '<(PRODUCT_DIR)/ui_unittests_strings/en.lproj/locale.pak',
-            }, {
-              'pak_output': '<(PRODUCT_DIR)/ui_unittests_strings/en-US.pak',
-            }],
-          ],
-        },
-        'actions': [
-          {
-            'action_name': 'repack_ui_unittest_strings',
-            'variables': {
-              'pak_inputs': [
-                '<(grit_base_out_dir)/ui_strings/ui_strings_en-US.pak',
-                '<(grit_base_out_dir)/app_locale_settings/app_locale_settings_en-US.pak',
-              ],
-            },
-            'inputs': [
-              '<(repack_path)',
-              '<@(pak_inputs)',
-            ],
-            'outputs': [
-              '<(pak_output)',
-            ],
-            'action': ['python', '<(repack_path)', '<@(_outputs)',
-                       '<@(pak_inputs)'],
-          },
-        ],
-        'copies': [
-          {
-            'destination': '<(PRODUCT_DIR)/ui_unittests_strings',
-            'files': [
-              '<(grit_base_out_dir)/ui_resources/ui_resources_100_percent.pak',
-            ],
-          },
-        ],
-      }],
-    }],
-  ],
 }
diff --git a/ui/base/strings/ui_strings.target.darwin-x86.mk b/ui/base/strings/ui_strings.target.darwin-x86.mk
index 0c8238e..139194e 100644
--- a/ui/base/strings/ui_strings.target.darwin-x86.mk
+++ b/ui/base/strings/ui_strings.target.darwin-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/ui_strings.grd $(LOCAL_PATH)/ui/base/strings/ui_strings_am.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ar.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bg.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ca.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_cs.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_da.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_de.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_el.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_et.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fa.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fil.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_gu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_id.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_it.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_iw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ja.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_kn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ko.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lt.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ml.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_mr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ms.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_nl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_no.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ro.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ru.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ta.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_te.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_th.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_tr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_uk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_vi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ui_strings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_strings $(gyp_shared_intermediate_dir)/ui/ui_strings/grit; python ../../../tools/grit/grit.py -i ui_strings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_strings $(gyp_shared_intermediate_dir)/ui/ui_strings/grit; python ../../../tools/grit/grit.py -i ui_strings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_am.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
 $(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ar.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
@@ -84,7 +84,7 @@
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/app_locale_settings.grd $(LOCAL_PATH)/ui/base/strings/app_locale_settings_am.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ar.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bg.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ca.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_cs.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_da.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_de.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_el.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_et.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fa.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fil.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_gu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_he.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_id.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_it.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ja.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_kn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ko.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lt.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ml.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_mr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ms.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nb.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ro.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ru.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sw.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ta.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_te.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_th.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_tr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_uk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_vi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from app_locale_settings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/app_locale_settings $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit; python ../../../tools/grit/grit.py -i app_locale_settings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/app_locale_settings" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/app_locale_settings $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit; python ../../../tools/grit/grit.py -i app_locale_settings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/app_locale_settings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_am.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ar.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
diff --git a/ui/base/strings/ui_strings.target.darwin-x86_64.mk b/ui/base/strings/ui_strings.target.darwin-x86_64.mk
new file mode 100644
index 0000000..139194e
--- /dev/null
+++ b/ui/base/strings/ui_strings.target.darwin-x86_64.mk
@@ -0,0 +1,277 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_base_strings_ui_strings_gyp
+LOCAL_MODULE_STEM := ui_strings
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "ui_strings":
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/ui_strings.grd $(LOCAL_PATH)/ui/base/strings/ui_strings_am.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ar.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bg.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ca.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_cs.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_da.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_de.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_el.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_et.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fa.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fil.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_gu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_id.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_it.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_iw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ja.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_kn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ko.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lt.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ml.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_mr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ms.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_nl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_no.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ro.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ru.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ta.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_te.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_th.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_tr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_uk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_vi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ui_strings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_strings $(gyp_shared_intermediate_dir)/ui/ui_strings/grit; python ../../../tools/grit/grit.py -i ui_strings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_am.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ar.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bg.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bn.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ca.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_cs.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_da.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_de.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_el.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-GB.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-US.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es-419.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_et.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fa.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fil.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_gu.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_he.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hu.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_id.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_it.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ja.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_kn.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ko.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lt.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lv.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ml.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_mr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ms.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nl.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nb.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pl.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-BR.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-PT.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ro.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ru.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sk.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sl.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sv.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sw.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ta.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_te.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_th.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_tr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_uk.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_vi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-CN.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-TW.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+
+### Rules for action "app_locale_settings":
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/app_locale_settings.grd $(LOCAL_PATH)/ui/base/strings/app_locale_settings_am.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ar.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bg.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ca.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_cs.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_da.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_de.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_el.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_et.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fa.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fil.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_gu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_he.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_id.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_it.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ja.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_kn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ko.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lt.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ml.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_mr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ms.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nb.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ro.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ru.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sw.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ta.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_te.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_th.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_tr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_uk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_vi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from app_locale_settings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/app_locale_settings $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit; python ../../../tools/grit/grit.py -i app_locale_settings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/app_locale_settings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_am.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ar.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bg.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bn.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ca.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_cs.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_da.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_de.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_el.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-GB.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-US.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es-419.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_et.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fa.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fil.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_gu.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_he.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hu.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_id.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_it.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ja.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_kn.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ko.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lt.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lv.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ml.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_mr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ms.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nl.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nb.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pl.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-BR.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-PT.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ro.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ru.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sk.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sl.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sv.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sw.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ta.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_te.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_th.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_tr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_uk.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_vi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-CN.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-TW.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_am.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ar.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bg.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bn.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ca.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_cs.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_da.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_de.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_el.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_et.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fa.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fil.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_gu.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_he.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hu.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_id.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_it.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ja.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_kn.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ko.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lt.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lv.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ml.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_mr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ms.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nl.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nb.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pl.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ro.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ru.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sk.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sl.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sv.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sw.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ta.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_te.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_th.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_tr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_uk.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_vi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-TW.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_am.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ar.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bg.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bn.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ca.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_cs.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_da.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_de.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_el.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_et.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fa.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fil.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_gu.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_he.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hu.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_id.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_it.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ja.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_kn.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ko.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lt.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lv.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ml.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_mr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ms.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nl.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nb.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pl.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ro.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ru.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sk.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sl.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sv.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sw.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ta.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_te.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_th.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_tr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_uk.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_vi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-TW.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_base_strings_ui_strings_gyp
+
+# Alias gyp target name.
+.PHONY: ui_strings
+ui_strings: ui_base_strings_ui_strings_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/base/strings/ui_strings.target.linux-x86.mk b/ui/base/strings/ui_strings.target.linux-x86.mk
index 0c8238e..139194e 100644
--- a/ui/base/strings/ui_strings.target.linux-x86.mk
+++ b/ui/base/strings/ui_strings.target.linux-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/ui_strings.grd $(LOCAL_PATH)/ui/base/strings/ui_strings_am.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ar.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bg.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ca.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_cs.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_da.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_de.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_el.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_et.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fa.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fil.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_gu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_id.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_it.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_iw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ja.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_kn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ko.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lt.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ml.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_mr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ms.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_nl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_no.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ro.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ru.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ta.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_te.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_th.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_tr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_uk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_vi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ui_strings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_strings $(gyp_shared_intermediate_dir)/ui/ui_strings/grit; python ../../../tools/grit/grit.py -i ui_strings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_strings $(gyp_shared_intermediate_dir)/ui/ui_strings/grit; python ../../../tools/grit/grit.py -i ui_strings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_am.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
 $(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ar.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
@@ -84,7 +84,7 @@
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/app_locale_settings.grd $(LOCAL_PATH)/ui/base/strings/app_locale_settings_am.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ar.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bg.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ca.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_cs.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_da.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_de.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_el.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_et.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fa.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fil.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_gu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_he.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_id.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_it.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ja.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_kn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ko.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lt.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ml.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_mr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ms.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nb.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ro.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ru.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sw.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ta.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_te.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_th.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_tr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_uk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_vi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from app_locale_settings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/app_locale_settings $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit; python ../../../tools/grit/grit.py -i app_locale_settings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/app_locale_settings" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/app_locale_settings $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit; python ../../../tools/grit/grit.py -i app_locale_settings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/app_locale_settings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_am.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
 $(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ar.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
diff --git a/ui/base/strings/ui_strings.target.linux-x86_64.mk b/ui/base/strings/ui_strings.target.linux-x86_64.mk
new file mode 100644
index 0000000..139194e
--- /dev/null
+++ b/ui/base/strings/ui_strings.target.linux-x86_64.mk
@@ -0,0 +1,277 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_base_strings_ui_strings_gyp
+LOCAL_MODULE_STEM := ui_strings
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "ui_strings":
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/ui_strings.grd $(LOCAL_PATH)/ui/base/strings/ui_strings_am.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ar.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bg.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_bn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ca.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_cs.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_da.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_de.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_el.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_es.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_et.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fa.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fil.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_fr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_gu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_hu.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_id.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_it.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_iw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ja.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_kn.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ko.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lt.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_lv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ml.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_mr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ms.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_nl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_no.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ro.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ru.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sl.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sv.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_sw.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_ta.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_te.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_th.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_tr.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_uk.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_vi.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/ui_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ui_strings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_strings $(gyp_shared_intermediate_dir)/ui/ui_strings/grit; python ../../../tools/grit/grit.py -i ui_strings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_strings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_am.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ar.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bg.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bn.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ca.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_cs.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_da.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_de.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_el.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-GB.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-US.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es-419.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_et.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fa.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fil.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_gu.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_he.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hu.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_id.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_it.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ja.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_kn.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ko.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lt.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lv.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ml.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_mr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ms.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nl.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nb.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pl.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-BR.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-PT.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ro.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ru.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sk.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sl.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sv.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sw.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ta.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_te.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_th.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_tr.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_uk.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_vi.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-CN.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-TW.pak: $(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h ;
+
+### Rules for action "app_locale_settings":
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/base/strings/app_locale_settings.grd $(LOCAL_PATH)/ui/base/strings/app_locale_settings_am.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ar.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bg.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_bn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ca.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_cs.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_da.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_de.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_el.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_en-GB.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es-419.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_es.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_et.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fa.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fil.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_fr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_gu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_he.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_hu.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_id.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_it.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ja.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_kn.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ko.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lt.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_lv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ml.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_mr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ms.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nb.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_nl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-BR.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_pt-PT.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ro.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ru.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sl.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sv.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_sw.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_ta.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_te.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_th.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_tr.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_uk.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_vi.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-CN.xtb $(LOCAL_PATH)/ui/base/strings/app_locale_settings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from app_locale_settings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/base/strings; mkdir -p $(gyp_shared_intermediate_dir)/ui/app_locale_settings $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit; python ../../../tools/grit/grit.py -i app_locale_settings.grd build -f ../../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/app_locale_settings" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_am.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ar.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bg.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bn.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ca.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_cs.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_da.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_de.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_el.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-GB.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-US.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es-419.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_et.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fa.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fil.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_gu.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_he.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hu.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_id.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_it.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ja.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_kn.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ko.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lt.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lv.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ml.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_mr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ms.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nl.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nb.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pl.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-BR.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-PT.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ro.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ru.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sk.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sl.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sv.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sw.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ta.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_te.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_th.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_tr.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_uk.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_vi.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-CN.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-TW.pak: $(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/grit/ui_strings.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_am.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ar.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bg.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_bn.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ca.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_cs.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_da.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_de.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_el.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_et.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fa.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fil.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_fr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_gu.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_he.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_hu.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_id.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_it.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ja.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_kn.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ko.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lt.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_lv.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ml.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_mr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ms.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nl.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_nb.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pl.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ro.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ru.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sk.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sl.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sv.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_sw.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_ta.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_te.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_th.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_tr.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_uk.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_vi.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings/ui_strings_zh-TW.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/grit/app_locale_settings.h \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_am.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ar.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bg.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_bn.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ca.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_cs.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_da.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_de.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_el.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_et.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fa.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fil.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_fr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_gu.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_he.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_hu.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_id.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_it.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ja.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_kn.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ko.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lt.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_lv.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ml.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_mr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ms.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nl.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_nb.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pl.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ro.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ru.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sk.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sl.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sv.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_sw.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_ta.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_te.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_th.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_tr.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_uk.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_vi.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings/app_locale_settings_zh-TW.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_base_strings_ui_strings_gyp
+
+# Alias gyp target name.
+.PHONY: ui_strings
+ui_strings: ui_base_strings_ui_strings_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/base/strings/ui_strings_am.xtb b/ui/base/strings/ui_strings_am.xtb
index 9d218d9..349f686 100644
--- a/ui/base/strings/ui_strings_am.xtb
+++ b/ui/base/strings/ui_strings_am.xtb
@@ -20,7 +20,7 @@
 <translation id="7511635910912978956"><ph name="NUMBER_FEW"/> ሰዓቶች ይቀራሉ</translation>
 <translation id="8717309436826820190"><ph name="NUMBER_OF_NOTIFICATIONS"/> ተጨማሪ ከ<ph name="SOURCE_OF_NOTIFICATIONS"/></translation>
 <translation id="5948410903763073882">Alt+<ph name="KEY_COMBO_NAME"/></translation>
-<translation id="7658239707568436148">ሰርዝ</translation>
+<translation id="7658239707568436148">ይቅር</translation>
 <translation id="7222373446505536781">F11</translation>
 <translation id="1761785978543082658"><ph name="QUANTITY"/> ባ</translation>
 <translation id="3660179305079774227">የላይ ቀስት</translation>
diff --git a/ui/base/strings/ui_strings_th.xtb b/ui/base/strings/ui_strings_th.xtb
index 639298f..a3fb419 100644
--- a/ui/base/strings/ui_strings_th.xtb
+++ b/ui/base/strings/ui_strings_th.xtb
@@ -186,7 +186,7 @@
 <translation id="3759876923365568382">เหลือ <ph name="NUMBER_FEW"/> วัน</translation>
 <translation id="6907759265145635167"><ph name="QUANTITY"/> PB/วินาที</translation>
 <translation id="2743387203779672305">คัดลอกไว้ที่คลิปบอร์ด</translation>
-<translation id="8371695176452482769">พูดเดี๋ยวนี้</translation>
+<translation id="8371695176452482769">เชิญพูดเลย</translation>
 <translation id="6965382102122355670">ตกลง</translation>
 <translation id="7850320739366109486">ห้ามรบกวน</translation>
 <translation id="6978839998405419496"><ph name="NUMBER_ZERO"/> days ago</translation>
diff --git a/ui/base/test/run_all_unittests.cc b/ui/base/test/run_all_unittests.cc
index 9d40ebb..8573da0 100644
--- a/ui/base/test/run_all_unittests.cc
+++ b/ui/base/test/run_all_unittests.cc
@@ -75,10 +75,8 @@
       exe_path.AppendASCII("ui_test.pak"));
 
   // ui_unittests can't depend on the locales folder which Chrome will make
-  // later, so use the path created by ui_unittest_strings.
-  PathService::Override(
-      ui::DIR_LOCALES,
-      exe_path.AppendASCII("ui_unittests_strings"));
+  // later, so use the path created by ui_test_pak.
+  PathService::Override(ui::DIR_LOCALES, exe_path.AppendASCII("ui"));
 #endif
 }
 
diff --git a/ui/base/ui_base.gyp b/ui/base/ui_base.gyp
index cab62df..16737cb 100644
--- a/ui/base/ui_base.gyp
+++ b/ui/base/ui_base.gyp
@@ -129,6 +129,8 @@
         'cursor/cursor_loader_x11.h',
         'cursor/cursor_ozone.cc',
         'cursor/cursor_mac.mm',
+        'cursor/cursor_util.cc',
+        'cursor/cursor_util.h',
         'cursor/cursor_win.cc',
         'cursor/cursor_x11.cc',
         'cursor/cursors_aura.cc',
@@ -158,6 +160,8 @@
         'dragdrop/drop_target_event.h',
         'dragdrop/drop_target_win.cc',
         'dragdrop/drop_target_win.h',
+        'dragdrop/file_info.cc',
+        'dragdrop/file_info.h',
         'dragdrop/gtk_dnd_util.cc',
         'dragdrop/gtk_dnd_util.h',
         'dragdrop/os_exchange_data.cc',
@@ -326,6 +330,8 @@
         'x/selection_utils.h',
         'x/work_area_watcher_x.cc',
         'x/work_area_watcher_x.h',
+        'x/x11_menu_list.cc',
+        'x/x11_menu_list.h',
         'x/x11_util.cc',
         'x/x11_util.h',
         'x/x11_util_internal.h',
@@ -601,15 +607,6 @@
         }],
       ],
     },
-    {
-      'target_name': 'webui_test_support',
-      'type': 'none',
-      'direct_dependent_settings': {
-        'include_dirs': [
-          '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources',
-        ]
-      }
-    },
   ],
   'conditions': [
     ['OS=="android"' , {
diff --git a/ui/base/ui_base.target.darwin-arm.mk b/ui/base/ui_base.target.darwin-arm.mk
index b499c74..ce36230 100644
--- a/ui/base/ui_base.target.darwin-arm.mk
+++ b/ui/base/ui_base.target.darwin-arm.mk
@@ -41,7 +41,9 @@
 	ui/base/clipboard/clipboard_constants.cc \
 	ui/base/clipboard/custom_data_helper.cc \
 	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
 	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
 	ui/base/l10n/formatter.cc \
 	ui/base/l10n/l10n_util.cc \
 	ui/base/l10n/l10n_util_android.cc \
@@ -139,9 +141,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -150,6 +150,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -263,9 +264,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -274,6 +273,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base.target.darwin-mips.mk b/ui/base/ui_base.target.darwin-mips.mk
index e9533e1..7dcf366 100644
--- a/ui/base/ui_base.target.darwin-mips.mk
+++ b/ui/base/ui_base.target.darwin-mips.mk
@@ -41,7 +41,9 @@
 	ui/base/clipboard/clipboard_constants.cc \
 	ui/base/clipboard/custom_data_helper.cc \
 	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
 	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
 	ui/base/l10n/formatter.cc \
 	ui/base/l10n/l10n_util.cc \
 	ui/base/l10n/l10n_util_android.cc \
@@ -138,9 +140,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -149,6 +149,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -261,9 +262,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -272,6 +271,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base.target.darwin-x86.mk b/ui/base/ui_base.target.darwin-x86.mk
index 37c23fb..deb89df 100644
--- a/ui/base/ui_base.target.darwin-x86.mk
+++ b/ui/base/ui_base.target.darwin-x86.mk
@@ -41,7 +41,9 @@
 	ui/base/clipboard/clipboard_constants.cc \
 	ui/base/clipboard/custom_data_helper.cc \
 	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
 	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
 	ui/base/l10n/formatter.cc \
 	ui/base/l10n/l10n_util.cc \
 	ui/base/l10n/l10n_util_android.cc \
@@ -139,9 +141,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -150,6 +150,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -262,9 +263,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -273,6 +272,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base.target.darwin-x86_64.mk b/ui/base/ui_base.target.darwin-x86_64.mk
new file mode 100644
index 0000000..b25b8be
--- /dev/null
+++ b/ui/base/ui_base.target.darwin-x86_64.mk
@@ -0,0 +1,390 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_base_ui_base_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,ui_base_strings_ui_strings_gyp)/ui_strings.stamp \
+	$(call intermediates-dir-for,GYP,ui_base_ui_base_jni_headers_gyp)/ui_base_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/base/accelerators/accelerator.cc \
+	ui/base/accelerators/accelerator_manager.cc \
+	ui/base/android/ui_base_jni_registrar.cc \
+	ui/base/android/view_android.cc \
+	ui/base/android/window_android.cc \
+	ui/base/base_window.cc \
+	ui/base/clipboard/clipboard.cc \
+	ui/base/clipboard/clipboard_android.cc \
+	ui/base/clipboard/clipboard_constants.cc \
+	ui/base/clipboard/custom_data_helper.cc \
+	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
+	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
+	ui/base/l10n/formatter.cc \
+	ui/base/l10n/l10n_util.cc \
+	ui/base/l10n/l10n_util_android.cc \
+	ui/base/l10n/l10n_util_plurals.cc \
+	ui/base/l10n/l10n_util_posix.cc \
+	ui/base/l10n/time_format.cc \
+	ui/base/layout.cc \
+	ui/base/models/combobox_model.cc \
+	ui/base/models/list_selection_model.cc \
+	ui/base/models/menu_model.cc \
+	ui/base/models/simple_menu_model.cc \
+	ui/base/models/table_model.cc \
+	ui/base/models/tree_model.cc \
+	ui/base/resource/data_pack.cc \
+	ui/base/resource/resource_bundle.cc \
+	ui/base/resource/resource_bundle_android.cc \
+	ui/base/text/bytes_formatting.cc \
+	ui/base/touch/touch_device_android.cc \
+	ui/base/touch/touch_enabled.cc \
+	ui/base/ui_base_exports.cc \
+	ui/base/ui_base_paths.cc \
+	ui/base/ui_base_switches.cc \
+	ui/base/ui_base_switches_util.cc \
+	ui/base/webui/jstemplate_builder.cc \
+	ui/base/webui/web_ui_util.cc \
+	ui/base/window_open_disposition.cc \
+	ui/base/ime/candidate_window.cc \
+	ui/base/ime/composition_text.cc \
+	ui/base/ime/dummy_input_method_delegate.cc \
+	ui/base/ime/infolist_entry.cc \
+	ui/base/ime/input_method_base.cc \
+	ui/base/ime/input_method_initializer.cc \
+	ui/base/ime/mock_input_method.cc \
+	ui/base/ime/text_input_client.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUI_BASE_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUI_BASE_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_base_ui_base_gyp
+
+# Alias gyp target name.
+.PHONY: ui_base
+ui_base: ui_base_ui_base_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/base/ui_base.target.linux-arm.mk b/ui/base/ui_base.target.linux-arm.mk
index b499c74..ce36230 100644
--- a/ui/base/ui_base.target.linux-arm.mk
+++ b/ui/base/ui_base.target.linux-arm.mk
@@ -41,7 +41,9 @@
 	ui/base/clipboard/clipboard_constants.cc \
 	ui/base/clipboard/custom_data_helper.cc \
 	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
 	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
 	ui/base/l10n/formatter.cc \
 	ui/base/l10n/l10n_util.cc \
 	ui/base/l10n/l10n_util_android.cc \
@@ -139,9 +141,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -150,6 +150,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -263,9 +264,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -274,6 +273,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base.target.linux-mips.mk b/ui/base/ui_base.target.linux-mips.mk
index e9533e1..7dcf366 100644
--- a/ui/base/ui_base.target.linux-mips.mk
+++ b/ui/base/ui_base.target.linux-mips.mk
@@ -41,7 +41,9 @@
 	ui/base/clipboard/clipboard_constants.cc \
 	ui/base/clipboard/custom_data_helper.cc \
 	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
 	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
 	ui/base/l10n/formatter.cc \
 	ui/base/l10n/l10n_util.cc \
 	ui/base/l10n/l10n_util_android.cc \
@@ -138,9 +140,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -149,6 +149,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -261,9 +262,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -272,6 +271,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base.target.linux-x86.mk b/ui/base/ui_base.target.linux-x86.mk
index 37c23fb..deb89df 100644
--- a/ui/base/ui_base.target.linux-x86.mk
+++ b/ui/base/ui_base.target.linux-x86.mk
@@ -41,7 +41,9 @@
 	ui/base/clipboard/clipboard_constants.cc \
 	ui/base/clipboard/custom_data_helper.cc \
 	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
 	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
 	ui/base/l10n/formatter.cc \
 	ui/base/l10n/l10n_util.cc \
 	ui/base/l10n/l10n_util_android.cc \
@@ -139,9 +141,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -150,6 +150,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -262,9 +263,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -273,6 +272,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base.target.linux-x86_64.mk b/ui/base/ui_base.target.linux-x86_64.mk
new file mode 100644
index 0000000..b25b8be
--- /dev/null
+++ b/ui/base/ui_base.target.linux-x86_64.mk
@@ -0,0 +1,390 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_base_ui_base_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,ui_base_strings_ui_strings_gyp)/ui_strings.stamp \
+	$(call intermediates-dir-for,GYP,ui_base_ui_base_jni_headers_gyp)/ui_base_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/base/accelerators/accelerator.cc \
+	ui/base/accelerators/accelerator_manager.cc \
+	ui/base/android/ui_base_jni_registrar.cc \
+	ui/base/android/view_android.cc \
+	ui/base/android/window_android.cc \
+	ui/base/base_window.cc \
+	ui/base/clipboard/clipboard.cc \
+	ui/base/clipboard/clipboard_android.cc \
+	ui/base/clipboard/clipboard_constants.cc \
+	ui/base/clipboard/custom_data_helper.cc \
+	ui/base/clipboard/scoped_clipboard_writer.cc \
+	ui/base/cursor/cursor_util.cc \
+	ui/base/device_form_factor_android.cc \
+	ui/base/dragdrop/file_info.cc \
+	ui/base/l10n/formatter.cc \
+	ui/base/l10n/l10n_util.cc \
+	ui/base/l10n/l10n_util_android.cc \
+	ui/base/l10n/l10n_util_plurals.cc \
+	ui/base/l10n/l10n_util_posix.cc \
+	ui/base/l10n/time_format.cc \
+	ui/base/layout.cc \
+	ui/base/models/combobox_model.cc \
+	ui/base/models/list_selection_model.cc \
+	ui/base/models/menu_model.cc \
+	ui/base/models/simple_menu_model.cc \
+	ui/base/models/table_model.cc \
+	ui/base/models/tree_model.cc \
+	ui/base/resource/data_pack.cc \
+	ui/base/resource/resource_bundle.cc \
+	ui/base/resource/resource_bundle_android.cc \
+	ui/base/text/bytes_formatting.cc \
+	ui/base/touch/touch_device_android.cc \
+	ui/base/touch/touch_enabled.cc \
+	ui/base/ui_base_exports.cc \
+	ui/base/ui_base_paths.cc \
+	ui/base/ui_base_switches.cc \
+	ui/base/ui_base_switches_util.cc \
+	ui/base/webui/jstemplate_builder.cc \
+	ui/base/webui/web_ui_util.cc \
+	ui/base/window_open_disposition.cc \
+	ui/base/ime/candidate_window.cc \
+	ui/base/ime/composition_text.cc \
+	ui/base/ime/dummy_input_method_delegate.cc \
+	ui/base/ime/infolist_entry.cc \
+	ui/base/ime/input_method_base.cc \
+	ui/base/ime/input_method_initializer.cc \
+	ui/base/ime/mock_input_method.cc \
+	ui/base/ime/text_input_client.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUI_BASE_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUI_BASE_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_base_ui_base_gyp
+
+# Alias gyp target name.
+.PHONY: ui_base
+ui_base: ui_base_ui_base_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/base/ui_base_jni_headers.target.darwin-arm.mk b/ui/base/ui_base_jni_headers.target.darwin-arm.mk
index 584e853..4e565ea 100644
--- a/ui/base/ui_base_jni_headers.target.darwin-arm.mk
+++ b/ui/base/ui_base_jni_headers.target.darwin-arm.mk
@@ -155,6 +155,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -237,6 +238,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base_jni_headers.target.darwin-mips.mk b/ui/base/ui_base_jni_headers.target.darwin-mips.mk
index 0e4e185..eafcb07 100644
--- a/ui/base/ui_base_jni_headers.target.darwin-mips.mk
+++ b/ui/base/ui_base_jni_headers.target.darwin-mips.mk
@@ -154,6 +154,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -235,6 +236,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base_jni_headers.target.darwin-x86.mk b/ui/base/ui_base_jni_headers.target.darwin-x86.mk
index 226d36c..f2182e7 100644
--- a/ui/base/ui_base_jni_headers.target.darwin-x86.mk
+++ b/ui/base/ui_base_jni_headers.target.darwin-x86.mk
@@ -156,6 +156,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -238,6 +239,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base_jni_headers.target.darwin-x86_64.mk b/ui/base/ui_base_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..0885c53
--- /dev/null
+++ b/ui/base/ui_base_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,294 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_base_ui_base_jni_headers_gyp
+LOCAL_MODULE_STEM := ui_base_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_base_ui_base_gyp_ui_base_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../android/java/src/org/chromium/ui/base/Clipboard.java', '../android/java/src/org/chromium/ui/base/LocalizationUtils.java', '../android/java/src/org/chromium/ui/base/SelectFileDialog.java', '../android/java/src/org/chromium/ui/base/TouchDevice.java', '../android/java/src/org/chromium/ui/base/ViewAndroid.java', '../android/java/src/org/chromium/ui/base/WindowAndroid.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/ui/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/Clipboard.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/Clipboard.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/LocalizationUtils.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/SelectFileDialog.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/TouchDevice.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/TouchDevice.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/ViewAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/ViewAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/WindowAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h \
+	ui_base_ui_base_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_base_ui_base_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: ui_base_jni_headers
+ui_base_jni_headers: ui_base_ui_base_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/base/ui_base_jni_headers.target.linux-arm.mk b/ui/base/ui_base_jni_headers.target.linux-arm.mk
index 584e853..4e565ea 100644
--- a/ui/base/ui_base_jni_headers.target.linux-arm.mk
+++ b/ui/base/ui_base_jni_headers.target.linux-arm.mk
@@ -155,6 +155,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -237,6 +238,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base_jni_headers.target.linux-mips.mk b/ui/base/ui_base_jni_headers.target.linux-mips.mk
index 0e4e185..eafcb07 100644
--- a/ui/base/ui_base_jni_headers.target.linux-mips.mk
+++ b/ui/base/ui_base_jni_headers.target.linux-mips.mk
@@ -154,6 +154,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -235,6 +236,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base_jni_headers.target.linux-x86.mk b/ui/base/ui_base_jni_headers.target.linux-x86.mk
index 226d36c..f2182e7 100644
--- a/ui/base/ui_base_jni_headers.target.linux-x86.mk
+++ b/ui/base/ui_base_jni_headers.target.linux-x86.mk
@@ -156,6 +156,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -238,6 +239,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/base/ui_base_jni_headers.target.linux-x86_64.mk b/ui/base/ui_base_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..0885c53
--- /dev/null
+++ b/ui/base/ui_base_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,294 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_base_ui_base_jni_headers_gyp
+LOCAL_MODULE_STEM := ui_base_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_base_ui_base_gyp_ui_base_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../android/java/src/org/chromium/ui/base/Clipboard.java', '../android/java/src/org/chromium/ui/base/LocalizationUtils.java', '../android/java/src/org/chromium/ui/base/SelectFileDialog.java', '../android/java/src/org/chromium/ui/base/TouchDevice.java', '../android/java/src/org/chromium/ui/base/ViewAndroid.java', '../android/java/src/org/chromium/ui/base/WindowAndroid.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/ui/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/Clipboard.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/Clipboard.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/LocalizationUtils.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/LocalizationUtils.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/SelectFileDialog.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/SelectFileDialog.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/TouchDevice.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/TouchDevice.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/ViewAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/ViewAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/base/WindowAndroid.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/jni; cd $(gyp_local_path)/ui/base; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/base/WindowAndroid.java --output_dir "$(gyp_shared_intermediate_dir)/ui/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_base_ui_base_jni_headers_gyp_rule_trigger
+ui_base_ui_base_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/jni/Clipboard_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/LocalizationUtils_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/SelectFileDialog_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/TouchDevice_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/ViewAndroid_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/jni/WindowAndroid_jni.h \
+	ui_base_ui_base_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_base_ui_base_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: ui_base_jni_headers
+ui_base_jni_headers: ui_base_ui_base_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc
index 91fc9a9..99e93c1 100644
--- a/ui/base/ui_base_switches.cc
+++ b/ui/base/ui_base_switches.cc
@@ -7,8 +7,8 @@
 namespace switches {
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
-// Enable use of CoreAnimation to draw on the Mac.
-const char kEnableCoreAnimation[] = "enable-core-animation";
+// Disable use of CoreAnimation to draw on the Mac.
+const char kDisableCoreAnimation[] = "disable-core-animation";
 #endif
 
 // Disables use of DWM composition for top level windows.
@@ -68,9 +68,4 @@
 const char kTabletUI[] = "tablet-ui";
 #endif
 
-#if defined(USE_XI2_MT)
-// The calibration factors given as "<left>,<right>,<top>,<bottom>".
-const char kTouchCalibration[] = "touch-calibration";
-#endif
-
 }  // namespace switches
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h
index 3a3ea3a..fbdce7e 100644
--- a/ui/base/ui_base_switches.h
+++ b/ui/base/ui_base_switches.h
@@ -13,7 +13,7 @@
 namespace switches {
 
 #if defined(OS_MACOSX) && !defined(OS_IOS)
-UI_BASE_EXPORT extern const char kEnableCoreAnimation[];
+UI_BASE_EXPORT extern const char kDisableCoreAnimation[];
 #endif
 
 UI_BASE_EXPORT extern const char kDisableDwmComposition[];
@@ -35,10 +35,6 @@
 UI_BASE_EXPORT extern const char kTabletUI[];
 #endif
 
-#if defined(USE_XI2_MT)
-UI_BASE_EXPORT extern const char kTouchCalibration[];
-#endif
-
 }  // namespace switches
 
 #endif  // UI_BASE_UI_BASE_SWITCHES_H_
diff --git a/ui/base/x/selection_requestor.cc b/ui/base/x/selection_requestor.cc
index f044cf8..158028d 100644
--- a/ui/base/x/selection_requestor.cc
+++ b/ui/base/x/selection_requestor.cc
@@ -55,6 +55,13 @@
   base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
   base::RunLoop run_loop;
 
+  // Stop waiting for a response after a certain amount of time.
+  const int kMaxWaitTimeForClipboardResponse = 300;
+  loop->PostDelayedTask(
+      FROM_HERE,
+      run_loop.QuitClosure(),
+      base::TimeDelta::FromMilliseconds(kMaxWaitTimeForClipboardResponse));
+
   PendingRequest pending_request(target, run_loop.QuitClosure());
   pending_requests_.push_back(&pending_request);
   run_loop.Run();
diff --git a/ui/base/x/selection_utils.cc b/ui/base/x/selection_utils.cc
index 82b1051..d5ce1c0 100644
--- a/ui/base/x/selection_utils.cc
+++ b/ui/base/x/selection_utils.cc
@@ -19,12 +19,16 @@
 const char kMimeTypeMozillaURL[] = "text/x-moz-url";
 const char kString[] = "STRING";
 const char kText[] = "TEXT";
+const char kTextPlain[] = "text/plain";
+const char kTextPlainUtf8[] = "text/plain;charset=utf-8";
 const char kUtf8String[] = "UTF8_STRING";
 
 const char* kSelectionDataAtoms[] = {
   Clipboard::kMimeTypeHTML,
   kString,
   kText,
+  kTextPlain,
+  kTextPlainUtf8,
   kUtf8String,
   NULL
 };
@@ -34,6 +38,8 @@
   atoms.push_back(atom_cache->GetAtom(kUtf8String));
   atoms.push_back(atom_cache->GetAtom(kString));
   atoms.push_back(atom_cache->GetAtom(kText));
+  atoms.push_back(atom_cache->GetAtom(kTextPlain));
+  atoms.push_back(atom_cache->GetAtom(kTextPlainUtf8));
   return atoms;
 }
 
@@ -192,9 +198,11 @@
 
 std::string SelectionData::GetText() const {
   if (type_ == atom_cache_.GetAtom(kUtf8String) ||
-      type_ == atom_cache_.GetAtom(kText)) {
+      type_ == atom_cache_.GetAtom(kText) ||
+      type_ == atom_cache_.GetAtom(kTextPlainUtf8)) {
     return RefCountedMemoryToString(memory_);
-  } else if (type_ == atom_cache_.GetAtom(kString)) {
+  } else if (type_ == atom_cache_.GetAtom(kString) ||
+             type_ == atom_cache_.GetAtom(kTextPlain)) {
     std::string result;
     base::ConvertToUtf8AndNormalize(RefCountedMemoryToString(memory_),
                                     base::kCodepageLatin1,
diff --git a/ui/base/x/x11_menu_list.cc b/ui/base/x/x11_menu_list.cc
new file mode 100644
index 0000000..3396e57
--- /dev/null
+++ b/ui/base/x/x11_menu_list.cc
@@ -0,0 +1,46 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/x/x11_menu_list.h"
+
+#include "base/memory/singleton.h"
+#include "ui/base/x/x11_util.h"
+
+namespace ui {
+
+// static
+XMenuList* XMenuList::GetInstance() {
+  return Singleton<XMenuList>::get();
+}
+
+XMenuList::XMenuList()
+    : menu_type_atom_(GetAtom("_NET_WM_WINDOW_TYPE_MENU")) {
+}
+
+XMenuList::~XMenuList() {
+  menus_.clear();
+}
+
+void XMenuList::MaybeRegisterMenu(XID menu) {
+  int value = 0;
+  if (!GetIntProperty(menu, "_NET_WM_WINDOW_TYPE", &value) ||
+      static_cast<Atom>(value) != menu_type_atom_) {
+    return;
+  }
+  menus_.push_back(menu);
+}
+
+void XMenuList::MaybeUnregisterMenu(XID menu) {
+  std::vector<XID>::iterator iter = std::find(menus_.begin(), menus_.end(),
+                                              menu);
+  if (iter == menus_.end())
+    return;
+  menus_.erase(iter);
+}
+
+void XMenuList::InsertMenuWindowXIDs(std::vector<XID>* stack) {
+  stack->insert(stack->begin(), menus_.begin(), menus_.end());
+}
+
+}  // namespace ui
diff --git a/ui/base/x/x11_menu_list.h b/ui/base/x/x11_menu_list.h
new file mode 100644
index 0000000..4e8476a
--- /dev/null
+++ b/ui/base/x/x11_menu_list.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_BASE_X_X11_MENU_LIST_H_
+#define UI_BASE_X_X11_MENU_LIST_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "ui/base/ui_base_export.h"
+#include "ui/gfx/x/x11_types.h"
+
+typedef unsigned long Atom;
+
+// A process wide singleton cache for X menus.
+template <typename T> struct DefaultSingletonTraits;
+
+namespace ui {
+
+// Keeps track of created and destroyed top level menu windows.
+class UI_BASE_EXPORT XMenuList {
+ public:
+  static XMenuList* GetInstance();
+
+  // Checks if |menu| has _NET_WM_WINDOW_TYPE property set to
+  // "_NET_WM_WINDOW_TYPE_MENU" atom and if so caches it.
+  void MaybeRegisterMenu(XID menu);
+
+  // Finds |menu| in cache and if found removes it.
+  void MaybeUnregisterMenu(XID menu);
+
+  // Inserts cached menu XIDs at the beginning of |stack|.
+  void InsertMenuWindowXIDs(std::vector<XID>* stack);
+
+ private:
+  friend struct DefaultSingletonTraits<XMenuList>;
+  XMenuList();
+  ~XMenuList();
+
+  std::vector<XID> menus_;
+  ::Atom menu_type_atom_;
+  DISALLOW_COPY_AND_ASSIGN(XMenuList);
+};
+
+}  // namespace ui
+
+#endif  // UI_BASE_X_X11_MENU_LIST_H_
diff --git a/ui/base/x/x11_util.cc b/ui/base/x/x11_util.cc
index 007157c..708f962 100644
--- a/ui/base/x/x11_util.cc
+++ b/ui/base/x/x11_util.cc
@@ -35,6 +35,7 @@
 #include "base/threading/thread.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkPostConfig.h"
+#include "ui/base/x/x11_menu_list.h"
 #include "ui/base/x/x11_util_internal.h"
 #include "ui/events/event_utils.h"
 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
@@ -965,6 +966,22 @@
   return !err_tracker.FoundNewError();
 }
 
+bool SetStringProperty(XID window,
+                       Atom property,
+                       Atom type,
+                       const std::string& value) {
+  gfx::X11ErrorTracker err_tracker;
+  XChangeProperty(gfx::GetXDisplay(),
+                  window,
+                  property,
+                  type,
+                  8,
+                  PropModeReplace,
+                  reinterpret_cast<const unsigned char*>(value.c_str()),
+                  value.size());
+  return !err_tracker.FoundNewError();
+}
+
 Atom GetAtom(const char* name) {
 #if defined(TOOLKIT_GTK)
   return gdk_x11_get_xatom_by_name_for_display(
@@ -1067,6 +1084,18 @@
   if (depth > max_depth)
     return false;
 
+  std::vector<XID> windows;
+  std::vector<XID>::iterator iter;
+  if (depth == 0) {
+    XMenuList::GetInstance()->InsertMenuWindowXIDs(&windows);
+    // Enumerate the menus first.
+    for (iter = windows.begin(); iter != windows.end(); iter++) {
+      if (delegate->ShouldStopIterating(*iter))
+        return true;
+    }
+    windows.clear();
+  }
+
   XID root, parent, *children;
   unsigned int num_children;
   int status = XQueryTree(gfx::GetXDisplay(), window, &root, &parent, &children,
@@ -1074,7 +1103,6 @@
   if (status == 0)
     return false;
 
-  std::vector<XID> windows;
   for (int i = static_cast<int>(num_children) - 1; i >= 0; i--)
     windows.push_back(children[i]);
 
@@ -1082,7 +1110,6 @@
 
   // XQueryTree returns the children of |window| in bottom-to-top order, so
   // reverse-iterate the list to check the windows from top-to-bottom.
-  std::vector<XID>::iterator iter;
   for (iter = windows.begin(); iter != windows.end(); iter++) {
     if (IsWindowNamed(*iter) && delegate->ShouldStopIterating(*iter))
       return true;
@@ -1118,6 +1145,7 @@
     ui::EnumerateAllWindows(delegate, kMaxSearchDepth);
     return;
   }
+  XMenuList::GetInstance()->InsertMenuWindowXIDs(&stack);
 
   std::vector<XID>::iterator iter;
   for (iter = stack.begin(); iter != stack.end(); iter++) {
diff --git a/ui/base/x/x11_util.h b/ui/base/x/x11_util.h
index dbcd987..519b149 100644
--- a/ui/base/x/x11_util.h
+++ b/ui/base/x/x11_util.h
@@ -203,6 +203,10 @@
                                          const std::string& name,
                                          const std::string& type,
                                          const std::vector<Atom>& value);
+UI_BASE_EXPORT bool SetStringProperty(XID window,
+                                      Atom property,
+                                      Atom type,
+                                      const std::string& value);
 
 // Gets the X atom for default display corresponding to atom_name.
 Atom GetAtom(const char* atom_name);
diff --git a/ui/compositor/clone_layer.cc b/ui/compositor/clone_layer.cc
deleted file mode 100644
index f1337b0..0000000
--- a/ui/compositor/clone_layer.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/compositor/clone_layer.h"
-
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_delegate.h"
-#include "ui/compositor/layer_owner.h"
-
-namespace ui {
-
-scoped_ptr<ui::Layer> CloneLayer(LayerOwner* layer_owner) {
-  scoped_ptr<ui::Layer> old_layer(layer_owner->AcquireLayer());
-  if (!old_layer)
-    return old_layer.Pass();
-
-  LayerDelegate* old_delegate = old_layer->delegate();
-  old_layer->set_delegate(NULL);
-
-  const gfx::Rect layer_bounds(old_layer->bounds());
-  Layer* new_layer = new ui::Layer(old_layer->type());
-  layer_owner->SetLayer(new_layer);
-  new_layer->SetVisible(old_layer->visible());
-  new_layer->set_scale_content(old_layer->scale_content());
-  new_layer->SetBounds(layer_bounds);
-  new_layer->SetMasksToBounds(old_layer->GetMasksToBounds());
-  new_layer->set_name(old_layer->name());
-  new_layer->SetFillsBoundsOpaquely(old_layer->fills_bounds_opaquely());
-
-  // Install new layer as a sibling of the old layer, stacked below it.
-  if (old_layer->parent()) {
-    old_layer->parent()->Add(new_layer);
-    old_layer->parent()->StackBelow(new_layer, old_layer.get());
-  }
-
-  // Migrate all the child layers over to the new layer. Copy the list because
-  // the items are removed during iteration.
-  std::vector<ui::Layer*> children_copy = old_layer->children();
-  for (std::vector<ui::Layer*>::const_iterator it = children_copy.begin();
-       it != children_copy.end();
-       ++it) {
-    ui::Layer* child = *it;
-    new_layer->Add(child);
-  }
-
-  // Install the delegate last so that the delegate isn't notified as we copy
-  // state to the new layer.
-  new_layer->set_delegate(old_delegate);
-
-  return old_layer.Pass();
-}
-
-}  // namespace ui
diff --git a/ui/compositor/clone_layer.h b/ui/compositor/clone_layer.h
deleted file mode 100644
index 4e439ce..0000000
--- a/ui/compositor/clone_layer.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_COMPOSITOR_CLONE_LAYER_H_
-#define UI_COMPOSITOR_CLONE_LAYER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "ui/compositor/compositor_export.h"
-
-namespace ui {
-
-class Layer;
-class LayerOwner;
-
-// Creates a new Layer for |layer_owner| returning the old. This does NOT
-// recurse. All the existing children of the layer are moved to the new layer.
-// This does nothing if |layer_owner| currently has no layer.
-COMPOSITOR_EXPORT scoped_ptr<ui::Layer> CloneLayer(LayerOwner* layer_owner);
-
-}  // namespace ui
-
-#endif  // UI_COMPOSITOR_CLONE_LAYER_H_
diff --git a/ui/compositor/compositor.gyp b/ui/compositor/compositor.gyp
index 64e69c0..18f6c8c 100644
--- a/ui/compositor/compositor.gyp
+++ b/ui/compositor/compositor.gyp
@@ -24,8 +24,6 @@
         'COMPOSITOR_IMPLEMENTATION',
       ],
       'sources': [
-        'clone_layer.cc',
-        'clone_layer.h',
         'compositor.cc',
         'compositor.h',
         'compositor_export.h',
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc
index f4c735b..1637d5e 100644
--- a/ui/compositor/layer.cc
+++ b/ui/compositor/layer.cc
@@ -61,6 +61,7 @@
       visible_(true),
       force_render_surface_(false),
       fills_bounds_opaquely_(true),
+      fills_bounds_completely_(false),
       background_blur_radius_(0),
       layer_saturation_(0.0f),
       layer_brightness_(0.0f),
@@ -85,6 +86,7 @@
       visible_(true),
       force_render_surface_(false),
       fills_bounds_opaquely_(true),
+      fills_bounds_completely_(false),
       background_blur_radius_(0),
       layer_saturation_(0.0f),
       layer_brightness_(0.0f),
@@ -444,6 +446,10 @@
   cc_layer_->SetContentsOpaque(fills_bounds_opaquely);
 }
 
+void Layer::SetFillsBoundsCompletely(bool fills_bounds_completely) {
+  fills_bounds_completely_ = fills_bounds_completely;
+}
+
 void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
   // Finish animations being handled by cc_layer_.
   if (animator_.get()) {
@@ -662,6 +668,8 @@
     canvas->Restore();
 }
 
+bool Layer::FillsBoundsCompletely() const { return fills_bounds_completely_; }
+
 unsigned Layer::PrepareTexture() {
   DCHECK(texture_layer_.get());
   return texture_->PrepareTexture();
diff --git a/ui/compositor/layer.h b/ui/compositor/layer.h
index 209e99e..ed805bf 100644
--- a/ui/compositor/layer.h
+++ b/ui/compositor/layer.h
@@ -249,6 +249,10 @@
   void SetFillsBoundsOpaquely(bool fills_bounds_opaquely);
   bool fills_bounds_opaquely() const { return fills_bounds_opaquely_; }
 
+  // Set to true if this layer always paints completely within its bounds. If so
+  // we can omit an unnecessary clear, even if the layer is transparent.
+  void SetFillsBoundsCompletely(bool fills_bounds_completely);
+
   const std::string& name() const { return name_; }
   void set_name(const std::string& name) { name_ = name; }
 
@@ -318,6 +322,7 @@
   virtual void PaintContents(
       SkCanvas* canvas, const gfx::Rect& clip, gfx::RectF* opaque) OVERRIDE;
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE {}
+  virtual bool FillsBoundsCompletely() const OVERRIDE;
 
   cc::Layer* cc_layer() { return cc_layer_; }
 
@@ -424,6 +429,7 @@
   bool force_render_surface_;
 
   bool fills_bounds_opaquely_;
+  bool fills_bounds_completely_;
 
   // Union of damaged rects, in pixel coordinates, to be used when
   // compositor is ready to paint the content.
diff --git a/ui/compositor/layer_owner.cc b/ui/compositor/layer_owner.cc
index c00b7fc..a797a0c 100644
--- a/ui/compositor/layer_owner.cc
+++ b/ui/compositor/layer_owner.cc
@@ -4,9 +4,11 @@
 
 #include "ui/compositor/layer_owner.h"
 
+#include "ui/compositor/layer_owner_delegate.h"
+
 namespace ui {
 
-LayerOwner::LayerOwner() : layer_(NULL) {
+LayerOwner::LayerOwner() : layer_(NULL), layer_owner_delegate_(NULL) {
 }
 
 LayerOwner::~LayerOwner() {
@@ -26,7 +28,48 @@
 }
 
 scoped_ptr<Layer> LayerOwner::RecreateLayer() {
-  return scoped_ptr<ui::Layer>();
+  scoped_ptr<ui::Layer> old_layer(AcquireLayer());
+  if (!old_layer)
+    return old_layer.Pass();
+
+  LayerDelegate* old_delegate = old_layer->delegate();
+  old_layer->set_delegate(NULL);
+
+  const gfx::Rect layer_bounds(old_layer->bounds());
+  Layer* new_layer = new ui::Layer(old_layer->type());
+  SetLayer(new_layer);
+  new_layer->SetVisible(old_layer->visible());
+  new_layer->set_scale_content(old_layer->scale_content());
+  new_layer->SetBounds(layer_bounds);
+  new_layer->SetMasksToBounds(old_layer->GetMasksToBounds());
+  new_layer->set_name(old_layer->name());
+  new_layer->SetFillsBoundsOpaquely(old_layer->fills_bounds_opaquely());
+  new_layer->SetFillsBoundsCompletely(old_layer->FillsBoundsCompletely());
+
+  // Install new layer as a sibling of the old layer, stacked below it.
+  if (old_layer->parent()) {
+    old_layer->parent()->Add(new_layer);
+    old_layer->parent()->StackBelow(new_layer, old_layer.get());
+  }
+
+  // Migrate all the child layers over to the new layer. Copy the list because
+  // the items are removed during iteration.
+  std::vector<ui::Layer*> children_copy = old_layer->children();
+  for (std::vector<ui::Layer*>::const_iterator it = children_copy.begin();
+       it != children_copy.end();
+       ++it) {
+    ui::Layer* child = *it;
+    new_layer->Add(child);
+  }
+
+  // Install the delegate last so that the delegate isn't notified as we copy
+  // state to the new layer.
+  new_layer->set_delegate(old_delegate);
+
+  if (layer_owner_delegate_)
+    layer_owner_delegate_->OnLayerRecreated(old_layer.get(), new_layer);
+
+  return old_layer.Pass();
 }
 
 void LayerOwner::DestroyLayer() {
diff --git a/ui/compositor/layer_owner.h b/ui/compositor/layer_owner.h
index b442bad..4828e74 100644
--- a/ui/compositor/layer_owner.h
+++ b/ui/compositor/layer_owner.h
@@ -11,6 +11,7 @@
 #include "ui/compositor/layer.h"
 
 namespace ui {
+class LayerOwnerDelegate;
 
 class COMPOSITOR_EXPORT LayerOwner {
  public:
@@ -32,11 +33,15 @@
   //
   // This does not recurse. Existing children of the layer are moved to the new
   // layer.
-  virtual scoped_ptr<Layer> RecreateLayer();
+  scoped_ptr<Layer> RecreateLayer();
 
   ui::Layer* layer() { return layer_; }
   const ui::Layer* layer() const { return layer_; }
 
+  void set_layer_owner_delegate(LayerOwnerDelegate* delegate) {
+    layer_owner_delegate_ = delegate;
+  }
+
  protected:
   void DestroyLayer();
 
@@ -51,6 +56,8 @@
   scoped_ptr<Layer> layer_owner_;
   Layer* layer_;
 
+  LayerOwnerDelegate* layer_owner_delegate_;
+
   DISALLOW_COPY_AND_ASSIGN(LayerOwner);
 };
 
diff --git a/ui/compositor/layer_owner_delegate.h b/ui/compositor/layer_owner_delegate.h
new file mode 100644
index 0000000..e5362d9
--- /dev/null
+++ b/ui/compositor/layer_owner_delegate.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_COMPOSITOR_LAYER_OWNER_DELEGATE_H_
+#define UI_COMPOSITOR_LAYER_OWNER_DELEGATE_H_
+
+#include "ui/compositor/compositor_export.h"
+
+namespace ui {
+class Layer;
+
+// Called from RecreateLayer() after the new layer was created. old_layer is
+// the layer that will be returned to the caller of RecreateLayer, new_layer
+// will be the layer now used. Used when the layer has external content
+// (SetExternalTexture / SetTextureMailbox / SetDelegatedFrame was called).
+class COMPOSITOR_EXPORT LayerOwnerDelegate {
+ public:
+  virtual void OnLayerRecreated(Layer* old_layer, Layer* new_layer) = 0;
+
+ protected:
+  virtual ~LayerOwnerDelegate() {}
+};
+
+}  // namespace ui
+
+#endif  // UI_COMPOSITOR_LAYER_OWNER_DELEGATE_H_
diff --git a/ui/display/chromeos/native_display_delegate.h b/ui/display/chromeos/native_display_delegate.h
index 2b3b776..8322ecf 100644
--- a/ui/display/chromeos/native_display_delegate.h
+++ b/ui/display/chromeos/native_display_delegate.h
@@ -5,6 +5,10 @@
 #ifndef UI_DISPLAY_CHROMEOS_NATIVE_DISPLAY_DELEGATE_H_
 #define UI_DISPLAY_CHROMEOS_NATIVE_DISPLAY_DELEGATE_H_
 
+#include <stdint.h>
+
+#include <vector>
+
 #include "ui/display/display_constants.h"
 #include "ui/display/display_export.h"
 
@@ -38,7 +42,7 @@
   virtual void SyncWithServer() = 0;
 
   // Sets the window's background color to |color_argb|.
-  virtual void SetBackgroundColor(uint32 color_argb) = 0;
+  virtual void SetBackgroundColor(uint32_t color_argb) = 0;
 
   // Enables DPMS and forces it to the "on" state.
   virtual void ForceDPMSOn() = 0;
@@ -71,6 +75,11 @@
   virtual bool SetHDCPState(const ui::DisplaySnapshot& output,
                             ui::HDCPState state) = 0;
 
+  // Gets the available list of color calibrations.
+  virtual std::vector<ui::ColorCalibrationProfile>
+      GetAvailableColorCalibrationProfiles(
+          const ui::DisplaySnapshot& output) = 0;
+
   // Sets the color calibration of |output| to |new_profile|.
   virtual bool SetColorCalibrationProfile(
       const ui::DisplaySnapshot& output,
diff --git a/ui/display/chromeos/output_configurator.cc b/ui/display/chromeos/output_configurator.cc
index 1a98b1d..9523afe 100644
--- a/ui/display/chromeos/output_configurator.cc
+++ b/ui/display/chromeos/output_configurator.cc
@@ -12,8 +12,15 @@
 #include "base/time/time.h"
 #include "ui/display/chromeos/display_mode.h"
 #include "ui/display/chromeos/display_snapshot.h"
+#include "ui/display/chromeos/native_display_delegate.h"
+
+#if defined(USE_OZONE)
+#include "ui/display/chromeos/ozone/native_display_delegate_ozone.h"
+#include "ui/display/chromeos/ozone/touchscreen_delegate_ozone.h"
+#elif defined(USE_X11)
 #include "ui/display/chromeos/x11/native_display_delegate_x11.h"
 #include "ui/display/chromeos/x11/touchscreen_delegate_x11.h"
+#endif
 
 namespace ui {
 
@@ -23,7 +30,7 @@
 
 // The delay to perform configuration after RRNotify.  See the comment
 // in |Dispatch()|.
-const int64 kConfigureDelayMs = 500;
+const int kConfigureDelayMs = 500;
 
 // Returns a string describing |state|.
 std::string DisplayPowerStateToString(chromeos::DisplayPowerState state) {
@@ -98,8 +105,6 @@
       selected_mode(NULL),
       mirror_mode(NULL) {}
 
-OutputConfigurator::DisplayState::~DisplayState() {}
-
 bool OutputConfigurator::TestApi::TriggerConfigureTimeout() {
   if (configurator_->configure_timer_.get() &&
       configurator_->configure_timer_->IsRunning()) {
@@ -191,15 +196,28 @@
     return;
 
   if (!native_display_delegate_) {
+#if defined(USE_OZONE)
+    native_display_delegate_.reset(new NativeDisplayDelegateOzone());
+#elif defined(USE_X11)
     native_display_delegate_.reset(new NativeDisplayDelegateX11());
+#else
+    NOTREACHED();
+#endif
     native_display_delegate_->AddObserver(this);
   }
 
-  if (!touchscreen_delegate_)
+  if (!touchscreen_delegate_) {
+#if defined(USE_OZONE)
+    touchscreen_delegate_.reset(new TouchscreenDelegateOzone());
+#elif defined(USE_X11)
     touchscreen_delegate_.reset(new TouchscreenDelegateX11());
+#else
+    NOTREACHED();
+#endif
+  }
 }
 
-void OutputConfigurator::ForceInitialConfigure(uint32 background_color_argb) {
+void OutputConfigurator::ForceInitialConfigure(uint32_t background_color_argb) {
   if (!configure_display_)
     return;
 
@@ -287,7 +305,7 @@
 
 bool OutputConfigurator::QueryOutputProtectionStatus(
     OutputProtectionClientId client_id,
-    int64 display_id,
+    int64_t display_id,
     uint32_t* link_mask,
     uint32_t* protection_mask) {
   if (!configure_display_)
@@ -344,7 +362,7 @@
 
 bool OutputConfigurator::EnableOutputProtection(
     OutputProtectionClientId client_id,
-    int64 display_id,
+    int64_t display_id,
     uint32_t desired_method_mask) {
   if (!configure_display_)
     return false;
@@ -381,19 +399,26 @@
   return true;
 }
 
+std::vector<ui::ColorCalibrationProfile>
+OutputConfigurator::GetAvailableColorCalibrationProfiles(
+    int64_t display_id) {
+  for (size_t i = 0; i < cached_outputs_.size(); ++i) {
+    if (cached_outputs_[i].display &&
+        cached_outputs_[i].display->display_id() == display_id) {
+      return native_display_delegate_->GetAvailableColorCalibrationProfiles(
+          *cached_outputs_[i].display);
+    }
+  }
+
+  return std::vector<ui::ColorCalibrationProfile>();
+}
+
 bool OutputConfigurator::SetColorCalibrationProfile(
-    int64 display_id,
+    int64_t display_id,
     ui::ColorCalibrationProfile new_profile) {
   for (size_t i = 0; i < cached_outputs_.size(); ++i) {
     if (cached_outputs_[i].display &&
         cached_outputs_[i].display->display_id() == display_id) {
-      std::vector<ColorCalibrationProfile>::const_iterator iter =
-          std::find(cached_outputs_[i].available_color_profiles.begin(),
-                    cached_outputs_[i].available_color_profiles.end(),
-                    new_profile);
-      if (iter == cached_outputs_[i].available_color_profiles.end())
-        return false;
-
       return native_display_delegate_->SetColorCalibrationProfile(
           *cached_outputs_[i].display, new_profile);
     }
@@ -907,9 +932,11 @@
         // state so that its native mode will be used.
         return OUTPUT_STATE_SINGLE;
       } else {
+        if (!state_controller_)
+          return OUTPUT_STATE_DUAL_EXTENDED;
         // With either both outputs on or both outputs off, use one of the
         // dual modes.
-        std::vector<int64> display_ids;
+        std::vector<int64_t> display_ids;
         for (size_t i = 0; i < cached_outputs_.size(); ++i) {
           // If display id isn't available, switch to extended mode.
           if (!cached_outputs_[i].display->has_proper_display_id())
diff --git a/ui/display/chromeos/output_configurator.h b/ui/display/chromeos/output_configurator.h
index d23621b..c89f4bc 100644
--- a/ui/display/chromeos/output_configurator.h
+++ b/ui/display/chromeos/output_configurator.h
@@ -5,11 +5,12 @@
 #ifndef UI_DISPLAY_CHROMEOS_OUTPUT_CONFIGURATOR_H_
 #define UI_DISPLAY_CHROMEOS_OUTPUT_CONFIGURATOR_H_
 
+#include <stdint.h>
+
 #include <map>
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/event_types.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
@@ -47,7 +48,6 @@
 
   struct DisplayState {
     DisplayState();
-    ~DisplayState();
 
     DisplaySnapshot* display;  // Not owned.
 
@@ -61,8 +61,6 @@
 
     // Mode used when displaying the same desktop on multiple outputs.
     const DisplayMode* mirror_mode;
-
-    std::vector<ui::ColorCalibrationProfile> available_color_profiles;
   };
 
   typedef std::vector<DisplayState> DisplayStateList;
@@ -91,11 +89,11 @@
 
     // Called when displays are detected.
     virtual OutputState GetStateForDisplayIds(
-        const std::vector<int64>& display_ids) const = 0;
+        const std::vector<int64_t>& display_ids) const = 0;
 
     // Queries the resolution (|size|) in pixels to select output mode for the
     // given display id.
-    virtual bool GetResolutionForDisplayId(int64 display_id,
+    virtual bool GetResolutionForDisplayId(int64_t display_id,
                                            gfx::Size* size) const = 0;
   };
 
@@ -202,7 +200,7 @@
   // If |background_color_argb| is non zero and there are multiple displays,
   // OutputConfigurator sets the background color of X's RootWindow to this
   // color.
-  void ForceInitialConfigure(uint32 background_color_argb);
+  void ForceInitialConfigure(uint32_t background_color_argb);
 
   // Stop handling display configuration events/requests.
   void PrepareForExit();
@@ -250,7 +248,7 @@
   // which is a bitmask of the OutputProtectionMethod values.
   // Returns true on success.
   bool QueryOutputProtectionStatus(OutputProtectionClientId client_id,
-                                   int64 display_id,
+                                   int64_t display_id,
                                    uint32_t* link_mask,
                                    uint32_t* protection_mask);
 
@@ -259,17 +257,22 @@
   // of the OutputProtectionMethod values.
   // Returns true when the protection request has been made.
   bool EnableOutputProtection(OutputProtectionClientId client_id,
-                              int64 display_id,
+                              int64_t display_id,
                               uint32_t desired_protection_mask);
 
+  // Checks the available color profiles for |display_id| and fills the result
+  // into |profiles|.
+  std::vector<ui::ColorCalibrationProfile> GetAvailableColorCalibrationProfiles(
+      int64_t display_id);
+
   // Updates the color calibration to |new_profile|.
   bool SetColorCalibrationProfile(
-      int64 display_id,
+      int64_t display_id,
       ui::ColorCalibrationProfile new_profile);
 
  private:
   // Mapping a display_id to a protection request bitmask.
-  typedef std::map<int64, uint32_t> DisplayProtections;
+  typedef std::map<int64_t, uint32_t> DisplayProtections;
   // Mapping a client to its protection request.
   typedef std::map<OutputProtectionClientId, DisplayProtections>
       ProtectionRequests;
diff --git a/ui/display/chromeos/output_configurator_unittest.cc b/ui/display/chromeos/output_configurator_unittest.cc
index 27b5446..9dfafe5 100644
--- a/ui/display/chromeos/output_configurator_unittest.cc
+++ b/ui/display/chromeos/output_configurator_unittest.cc
@@ -4,13 +4,14 @@
 
 #include "ui/display/chromeos/output_configurator.h"
 
+#include <stdint.h>
+
 #include <cmath>
 #include <cstdarg>
 #include <map>
 #include <string>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/format_macros.h"
 #include "base/memory/scoped_vector.h"
@@ -43,7 +44,7 @@
 
 // Returns a string describing a TestNativeDisplayDelegate::SetBackgroundColor()
 // call.
-std::string GetBackgroundAction(uint32 color_argb) {
+std::string GetBackgroundAction(uint32_t color_argb) {
   return base::StringPrintf("background(0x%x)", color_argb);
 }
 
@@ -212,7 +213,7 @@
   virtual void GrabServer() OVERRIDE { log_->AppendAction(kGrab); }
   virtual void UngrabServer() OVERRIDE { log_->AppendAction(kUngrab); }
   virtual void SyncWithServer() OVERRIDE { log_->AppendAction(kSync); }
-  virtual void SetBackgroundColor(uint32 color_argb) OVERRIDE {
+  virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE {
     log_->AppendAction(GetBackgroundAction(color_argb));
   }
   virtual void ForceDPMSOn() OVERRIDE { log_->AppendAction(kForceDPMS); }
@@ -254,6 +255,12 @@
     return true;
   }
 
+  virtual std::vector<ui::ColorCalibrationProfile>
+  GetAvailableColorCalibrationProfiles(
+      const DisplaySnapshot& output) OVERRIDE {
+    return std::vector<ui::ColorCalibrationProfile>();
+  }
+
   virtual bool SetColorCalibrationProfile(
       const DisplaySnapshot& output,
       ui::ColorCalibrationProfile new_profile) OVERRIDE {
@@ -343,10 +350,10 @@
 
   // OutputConfigurator::StateController overrides:
   virtual OutputState GetStateForDisplayIds(
-      const std::vector<int64>& outputs) const OVERRIDE {
+      const std::vector<int64_t>& outputs) const OVERRIDE {
     return state_;
   }
-  virtual bool GetResolutionForDisplayId(int64 display_id,
+  virtual bool GetResolutionForDisplayId(int64_t display_id,
                                          gfx::Size* size) const OVERRIDE {
     return false;
   }
diff --git a/ui/display/chromeos/ozone/native_display_delegate_ozone.cc b/ui/display/chromeos/ozone/native_display_delegate_ozone.cc
new file mode 100644
index 0000000..f9dc678
--- /dev/null
+++ b/ui/display/chromeos/ozone/native_display_delegate_ozone.cc
@@ -0,0 +1,95 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/chromeos/ozone/native_display_delegate_ozone.h"
+
+#include "base/logging.h"
+
+namespace ui {
+
+NativeDisplayDelegateOzone::NativeDisplayDelegateOzone() {}
+
+NativeDisplayDelegateOzone::~NativeDisplayDelegateOzone() {}
+
+void NativeDisplayDelegateOzone::Initialize() {
+  NOTIMPLEMENTED();
+}
+
+void NativeDisplayDelegateOzone::GrabServer() {
+  NOTIMPLEMENTED();
+}
+
+void NativeDisplayDelegateOzone::UngrabServer() {
+  NOTIMPLEMENTED();
+}
+
+void NativeDisplayDelegateOzone::SyncWithServer() {
+  NOTIMPLEMENTED();
+}
+
+void NativeDisplayDelegateOzone::SetBackgroundColor(uint32_t color_argb) {
+  NOTIMPLEMENTED();
+}
+
+void NativeDisplayDelegateOzone::ForceDPMSOn() {
+  NOTIMPLEMENTED();
+}
+
+std::vector<ui::DisplaySnapshot*> NativeDisplayDelegateOzone::GetOutputs() {
+  NOTIMPLEMENTED();
+  return std::vector<ui::DisplaySnapshot*>();
+}
+
+void NativeDisplayDelegateOzone::AddMode(const ui::DisplaySnapshot& output,
+                                         const ui::DisplayMode* mode) {
+  NOTIMPLEMENTED();
+}
+
+bool NativeDisplayDelegateOzone::Configure(const ui::DisplaySnapshot& output,
+                                           const ui::DisplayMode* mode,
+                                           const gfx::Point& origin) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void NativeDisplayDelegateOzone::CreateFrameBuffer(const gfx::Size& size) {
+  NOTIMPLEMENTED();
+}
+
+bool NativeDisplayDelegateOzone::GetHDCPState(const ui::DisplaySnapshot& output,
+                                              ui::HDCPState* state) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+bool NativeDisplayDelegateOzone::SetHDCPState(const ui::DisplaySnapshot& output,
+                                              ui::HDCPState state) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+std::vector<ui::ColorCalibrationProfile>
+NativeDisplayDelegateOzone::GetAvailableColorCalibrationProfiles(
+    const ui::DisplaySnapshot& output) {
+  NOTIMPLEMENTED();
+  return std::vector<ui::ColorCalibrationProfile>();
+}
+
+bool NativeDisplayDelegateOzone::SetColorCalibrationProfile(
+    const ui::DisplaySnapshot& output,
+    ui::ColorCalibrationProfile new_profile) {
+  NOTIMPLEMENTED();
+  return false;
+}
+
+void NativeDisplayDelegateOzone::AddObserver(NativeDisplayObserver* observer) {
+  NOTIMPLEMENTED();
+}
+
+void NativeDisplayDelegateOzone::RemoveObserver(
+    NativeDisplayObserver* observer) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace ui
diff --git a/ui/display/chromeos/ozone/native_display_delegate_ozone.h b/ui/display/chromeos/ozone/native_display_delegate_ozone.h
new file mode 100644
index 0000000..1519b85
--- /dev/null
+++ b/ui/display/chromeos/ozone/native_display_delegate_ozone.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_CHROMEOS_OZONE_NATIVE_DISPLAY_DELEGATE_OZONE_H_
+#define UI_DISPLAY_CHROMEOS_OZONE_NATIVE_DISPLAY_DELEGATE_OZONE_H_
+
+#include "base/macros.h"
+#include "ui/display/chromeos/native_display_delegate.h"
+
+namespace ui {
+
+class NativeDisplayDelegateOzone : public NativeDisplayDelegate {
+ public:
+  NativeDisplayDelegateOzone();
+  virtual ~NativeDisplayDelegateOzone();
+
+  // NativeDisplayDelegate overrides:
+  virtual void Initialize() OVERRIDE;
+  virtual void GrabServer() OVERRIDE;
+  virtual void UngrabServer() OVERRIDE;
+  virtual void SyncWithServer() OVERRIDE;
+  virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE;
+  virtual void ForceDPMSOn() OVERRIDE;
+  virtual std::vector<ui::DisplaySnapshot*> GetOutputs() OVERRIDE;
+  virtual void AddMode(const ui::DisplaySnapshot& output,
+                       const ui::DisplayMode* mode) OVERRIDE;
+  virtual bool Configure(const ui::DisplaySnapshot& output,
+                         const ui::DisplayMode* mode,
+                         const gfx::Point& origin) OVERRIDE;
+  virtual void CreateFrameBuffer(const gfx::Size& size) OVERRIDE;
+  virtual bool GetHDCPState(const ui::DisplaySnapshot& output,
+                            ui::HDCPState* state) OVERRIDE;
+  virtual bool SetHDCPState(const ui::DisplaySnapshot& output,
+                            ui::HDCPState state) OVERRIDE;
+  virtual std::vector<ui::ColorCalibrationProfile>
+      GetAvailableColorCalibrationProfiles(
+          const ui::DisplaySnapshot& output) OVERRIDE;
+  virtual bool SetColorCalibrationProfile(
+      const ui::DisplaySnapshot& output,
+      ui::ColorCalibrationProfile new_profile) OVERRIDE;
+  virtual void AddObserver(NativeDisplayObserver* observer) OVERRIDE;
+  virtual void RemoveObserver(NativeDisplayObserver* observer) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(NativeDisplayDelegateOzone);
+};
+
+}  // namespace ui
+
+#endif  // UI_DISPLAY_CHROMEOS_OZONE_NATIVE_DISPLAY_DELEGATE_OZONE_H_
diff --git a/ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc
new file mode 100644
index 0000000..f25f359
--- /dev/null
+++ b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.cc
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/chromeos/ozone/touchscreen_delegate_ozone.h"
+
+namespace ui {
+
+TouchscreenDelegateOzone::TouchscreenDelegateOzone() {}
+
+TouchscreenDelegateOzone::~TouchscreenDelegateOzone() {}
+
+void TouchscreenDelegateOzone::AssociateTouchscreens(
+    std::vector<OutputConfigurator::DisplayState>* outputs) {
+  NOTIMPLEMENTED();
+}
+
+void TouchscreenDelegateOzone::ConfigureCTM(
+    int touch_device_id,
+    const OutputConfigurator::CoordinateTransformation& ctm) {
+  NOTIMPLEMENTED();
+}
+
+}  // namespace ui
diff --git a/ui/display/chromeos/ozone/touchscreen_delegate_ozone.h b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.h
new file mode 100644
index 0000000..f9fd34a
--- /dev/null
+++ b/ui/display/chromeos/ozone/touchscreen_delegate_ozone.h
@@ -0,0 +1,31 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_CHROMEOS_OZONE_TOUCHSCREEN_DELEGATE_OZONE_H_
+#define UI_DISPLAY_CHROMEOS_OZONE_TOUCHSCREEN_DELEGATE_OZONE_H_
+
+#include "ui/display/chromeos/output_configurator.h"
+
+namespace ui {
+
+class TouchscreenDelegateOzone
+    : public OutputConfigurator::TouchscreenDelegate {
+ public:
+  TouchscreenDelegateOzone();
+  virtual ~TouchscreenDelegateOzone();
+
+  // OutputConfigurator::TouchscreenDelegate overrides:
+  virtual void AssociateTouchscreens(
+      std::vector<OutputConfigurator::DisplayState>* outputs) OVERRIDE;
+  virtual void ConfigureCTM(
+      int touch_device_id,
+      const OutputConfigurator::CoordinateTransformation& ctm) OVERRIDE;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TouchscreenDelegateOzone);
+};
+
+}  // namespace ui
+
+#endif  // UI_DISPLAY_CHROMEOS_OZONE_TOUCHSCREEN_DELEGATE_OZONE_H_
diff --git a/ui/display/chromeos/x11/display_snapshot_x11.cc b/ui/display/chromeos/x11/display_snapshot_x11.cc
index 366a1f3..9228a07 100644
--- a/ui/display/chromeos/x11/display_snapshot_x11.cc
+++ b/ui/display/chromeos/x11/display_snapshot_x11.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/stringprintf.h"
 #include "ui/display/chromeos/x11/display_mode_x11.h"
-#include "ui/display/chromeos/x11/display_util.h"
+#include "ui/display/x11/edid_parser_x11.h"
 
 namespace ui {
 
diff --git a/ui/display/chromeos/x11/display_util.cc b/ui/display/chromeos/x11/display_util.cc
deleted file mode 100644
index 107d8be..0000000
--- a/ui/display/chromeos/x11/display_util.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/display/chromeos/x11/display_util.h"
-
-#include <X11/extensions/Xrandr.h>
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "base/x11/edid_parser_x11.h"
-
-namespace ui {
-
-namespace {
-
-struct OutputTypeMapping {
-  // Prefix of output name.
-  std::string name;
-  OutputType type;
-};
-
-const OutputTypeMapping kOutputTypeMapping[] = {
-    {"LVDS", OUTPUT_TYPE_INTERNAL},
-    {"eDP", OUTPUT_TYPE_INTERNAL},
-    {"DSI", OUTPUT_TYPE_INTERNAL},
-    {"VGA", OUTPUT_TYPE_VGA},
-    {"HDMI", OUTPUT_TYPE_HDMI},
-    {"DVI", OUTPUT_TYPE_DVI},
-    {"DP", OUTPUT_TYPE_DISPLAYPORT}
-};
-
-// Gets some useful data from the specified output device, such like
-// manufacturer's ID, product code, and human readable name. Returns false if it
-// fails to get those data and doesn't touch manufacturer ID/product code/name.
-// NULL can be passed for unwanted output parameters.
-bool GetOutputDeviceData(XID output,
-                         uint16* manufacturer_id,
-                         std::string* human_readable_name) {
-  unsigned long nitems = 0;
-  unsigned char* prop = NULL;
-  if (!base::GetEDIDProperty(output, &nitems, &prop))
-    return false;
-
-  bool result = base::ParseOutputDeviceData(
-      prop, nitems, manufacturer_id, human_readable_name);
-  XFree(prop);
-  return result;
-}
-
-}  // namespace
-
-OutputType GetOutputTypeFromName(const std::string& name) {
-  for (unsigned int i = 0; i < arraysize(kOutputTypeMapping); ++i) {
-    if (name.find(kOutputTypeMapping[i].name) == 0) {
-      return kOutputTypeMapping[i].type;
-    }
-  }
-
-  return OUTPUT_TYPE_UNKNOWN;
-}
-
-std::string GetDisplayName(RROutput output) {
-  std::string display_name;
-  GetOutputDeviceData(output, NULL, &display_name);
-  return display_name;
-}
-
-bool GetOutputOverscanFlag(RROutput output, bool* flag) {
-  unsigned long nitems = 0;
-  unsigned char* prop = NULL;
-  if (!base::GetEDIDProperty(output, &nitems, &prop))
-    return false;
-
-  bool found = ParseOutputOverscanFlag(prop, nitems, flag);
-  XFree(prop);
-  return found;
-}
-
-bool ParseOutputOverscanFlag(const unsigned char* prop,
-                             unsigned long nitems,
-                             bool* flag) {
-  // See http://en.wikipedia.org/wiki/Extended_display_identification_data
-  // for the extension format of EDID.  Also see EIA/CEA-861 spec for
-  // the format of the extensions and how video capability is encoded.
-  //  - byte 0: tag.  should be 02h.
-  //  - byte 1: revision.  only cares revision 3 (03h).
-  //  - byte 4-: data block.
-  const unsigned int kExtensionBase = 128;
-  const unsigned int kExtensionSize = 128;
-  const unsigned int kNumExtensionsOffset = 126;
-  const unsigned int kDataBlockOffset = 4;
-  const unsigned char kCEAExtensionTag = '\x02';
-  const unsigned char kExpectedExtensionRevision = '\x03';
-  const unsigned char kExtendedTag = 7;
-  const unsigned char kExtendedVideoCapabilityTag = 0;
-  const unsigned int kPTOverscan = 4;
-  const unsigned int kITOverscan = 2;
-  const unsigned int kCEOverscan = 0;
-
-  if (nitems <= kNumExtensionsOffset)
-    return false;
-
-  unsigned char num_extensions = prop[kNumExtensionsOffset];
-
-  for (size_t i = 0; i < num_extensions; ++i) {
-    // Skip parsing the whole extension if size is not enough.
-    if (nitems < kExtensionBase + (i + 1) * kExtensionSize)
-      break;
-
-    const unsigned char* extension = prop + kExtensionBase + i * kExtensionSize;
-    unsigned char tag = extension[0];
-    unsigned char revision = extension[1];
-    if (tag != kCEAExtensionTag || revision != kExpectedExtensionRevision)
-      continue;
-
-    unsigned char timing_descriptors_start =
-        std::min(extension[2], static_cast<unsigned char>(kExtensionSize));
-    const unsigned char* data_block = extension + kDataBlockOffset;
-    while (data_block < extension + timing_descriptors_start) {
-      // A data block is encoded as:
-      // - byte 1 high 3 bits: tag. '07' for extended tags.
-      // - byte 1 remaining bits: the length of data block.
-      // - byte 2: the extended tag.  '0' for video capability.
-      // - byte 3: the capability.
-      unsigned char tag = data_block[0] >> 5;
-      unsigned char payload_length = data_block[0] & 0x1f;
-      if (static_cast<unsigned long>(data_block + payload_length - prop) >
-          nitems)
-        break;
-
-      if (tag != kExtendedTag || payload_length < 2) {
-        data_block += payload_length + 1;
-        continue;
-      }
-
-      unsigned char extended_tag_code = data_block[1];
-      if (extended_tag_code != kExtendedVideoCapabilityTag) {
-        data_block += payload_length + 1;
-        continue;
-      }
-
-      // The difference between preferred, IT, and CE video formats
-      // doesn't matter. Sets |flag| to true if any of these flags are true.
-      if ((data_block[2] & (1 << kPTOverscan)) ||
-          (data_block[2] & (1 << kITOverscan)) ||
-          (data_block[2] & (1 << kCEOverscan))) {
-        *flag = true;
-      } else {
-        *flag = false;
-      }
-      return true;
-    }
-  }
-
-  return false;
-}
-
-}  // namespace ui
diff --git a/ui/display/chromeos/x11/display_util.h b/ui/display/chromeos/x11/display_util.h
deleted file mode 100644
index 33d9545..0000000
--- a/ui/display/chromeos/x11/display_util.h
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_H_
-#define UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_H_
-
-#include <string>
-
-#include "ui/display/display_constants.h"
-#include "ui/display/display_export.h"
-
-typedef unsigned long RROutput;
-
-namespace ui {
-
-// Returns the OutputType by matching known type prefixes to |name|. Returns
-// OUTPUT_TYPE_UNKNOWN if no valid match.
-DISPLAY_EXPORT OutputType GetOutputTypeFromName(const std::string& name);
-
-// Generate the human readable string from EDID obtained from |output|.
-DISPLAY_EXPORT std::string GetDisplayName(RROutput output);
-
-// Gets the overscan flag from |output| and stores to |flag|. Returns true if
-// the flag is found. Otherwise returns false and doesn't touch |flag|. The
-// output will produce overscan if |flag| is set to true, but the output may
-// still produce overscan even though it returns true and |flag| is set to
-// false.
-DISPLAY_EXPORT bool GetOutputOverscanFlag(RROutput output, bool* flag);
-
-DISPLAY_EXPORT bool ParseOutputOverscanFlag(const unsigned char* prop,
-                                            unsigned long nitems,
-                                            bool* flag);
-
-}  // namespace ui
-
-#endif  // UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_H_
diff --git a/ui/display/chromeos/x11/display_util_unittest.cc b/ui/display/chromeos/x11/display_util_unittest.cc
deleted file mode 100644
index 03a6af5..0000000
--- a/ui/display/chromeos/x11/display_util_unittest.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/display/chromeos/x11/display_util.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include <X11/extensions/Xrandr.h>
-
-namespace ui {
-
-namespace {
-
-// Returns the number of characters in the string literal but doesn't count its
-// terminator NULL byte.
-#define charsize(str) (arraysize(str) - 1)
-
-// Sample EDID data extracted from real devices.
-const unsigned char kNormalDisplay[] =
-    "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01"
-    "\x02\x16\x01\x04\xb5\x40\x28\x78\xe2\x8d\x85\xad\x4f\x35\xb1\x25"
-    "\x0e\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
-    "\x01\x01\x01\x01\x01\x01\xe2\x68\x00\xa0\xa0\x40\x2e\x60\x30\x20"
-    "\x36\x00\x81\x90\x21\x00\x00\x1a\xbc\x1b\x00\xa0\x50\x20\x17\x30"
-    "\x30\x20\x36\x00\x81\x90\x21\x00\x00\x1a\x00\x00\x00\xfc\x00\x48"
-    "\x50\x20\x5a\x52\x33\x30\x77\x0a\x20\x20\x20\x20\x00\x00\x00\xff"
-    "\x00\x43\x4e\x34\x32\x30\x32\x31\x33\x37\x51\x0a\x20\x20\x00\x71";
-
-const unsigned char kInternalDisplay[] =
-    "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00"
-    "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27"
-    "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
-    "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30"
-    "\x13\x00\x05\xa3\x10\x00\x00\x19\x00\x00\x00\x0f\x00\x00\x00\x00"
-    "\x00\x00\x00\x00\x00\x23\x87\x02\x64\x00\x00\x00\x00\xfe\x00\x53"
-    "\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x00\x00\x00\xfe"
-    "\x00\x31\x32\x31\x41\x54\x31\x31\x2d\x38\x30\x31\x0a\x20\x00\x45";
-
-const unsigned char kOverscanDisplay[] =
-    "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00"
-    "\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26"
-    "\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00"
-    "\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
-    "\x45\x00\xa0\x5a\x00\x00\x00\x1e\x66\x21\x56\xaa\x51\x00\x1e\x30"
-    "\x46\x8f\x33\x00\xa0\x5a\x00\x00\x00\x1e\x00\x00\x00\xfd\x00\x18"
-    "\x4b\x0f\x51\x17\x00\x0a\x20\x20\x20\x20\x20\x20\x00\x00\x00\xfc"
-    "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d"
-    "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07"
-    "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01"
-    "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00"
-    "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00"
-    "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0"
-    "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
-    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6";
-
-// The EDID info misdetecting overscan once. see crbug.com/226318
-const unsigned char kMisdetecedDisplay[] =
-    "\x00\xff\xff\xff\xff\xff\xff\x00\x10\xac\x64\x40\x4c\x30\x30\x32"
-    "\x0c\x15\x01\x03\x80\x40\x28\x78\xea\x8d\x85\xad\x4f\x35\xb1\x25"
-    "\x0e\x50\x54\xa5\x4b\x00\x71\x4f\x81\x00\x81\x80\xd1\x00\xa9\x40"
-    "\x01\x01\x01\x01\x01\x01\x28\x3c\x80\xa0\x70\xb0\x23\x40\x30\x20"
-    "\x36\x00\x81\x91\x21\x00\x00\x1a\x00\x00\x00\xff\x00\x50\x48\x35"
-    "\x4e\x59\x31\x33\x4e\x32\x30\x30\x4c\x0a\x00\x00\x00\xfc\x00\x44"
-    "\x45\x4c\x4c\x20\x55\x33\x30\x31\x31\x0a\x20\x20\x00\x00\x00\xfd"
-    "\x00\x31\x56\x1d\x5e\x12\x00\x0a\x20\x20\x20\x20\x20\x20\x01\x38"
-    "\x02\x03\x29\xf1\x50\x90\x05\x04\x03\x02\x07\x16\x01\x06\x11\x12"
-    "\x15\x13\x14\x1f\x20\x23\x0d\x7f\x07\x83\x0f\x00\x00\x67\x03\x0c"
-    "\x00\x10\x00\x38\x2d\xe3\x05\x03\x01\x02\x3a\x80\x18\x71\x38\x2d"
-    "\x40\x58\x2c\x45\x00\x81\x91\x21\x00\x00\x1e\x01\x1d\x80\x18\x71"
-    "\x1c\x16\x20\x58\x2c\x25\x00\x81\x91\x21\x00\x00\x9e\x01\x1d\x00"
-    "\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\x81\x91\x21\x00\x00\x1e\x8c"
-    "\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\x81\x91\x21\x00\x00"
-    "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x94";
-
-}  // namespace
-
-TEST(DisplayUtilTest, ParseOverscanFlag) {
-  bool flag = false;
-  EXPECT_FALSE(
-      ParseOutputOverscanFlag(kNormalDisplay, charsize(kNormalDisplay), &flag));
-
-  flag = false;
-  EXPECT_FALSE(ParseOutputOverscanFlag(
-      kInternalDisplay, charsize(kInternalDisplay), &flag));
-
-  flag = false;
-  EXPECT_TRUE(ParseOutputOverscanFlag(
-      kOverscanDisplay, charsize(kOverscanDisplay), &flag));
-  EXPECT_TRUE(flag);
-
-  flag = false;
-  EXPECT_FALSE(ParseOutputOverscanFlag(
-      kMisdetecedDisplay, charsize(kMisdetecedDisplay), &flag));
-
-  flag = false;
-  // Copy |kOverscanDisplay| and set flags to false in it. The overscan flags
-  // are embedded at byte 150 in this specific example. Fix here too when the
-  // contents of kOverscanDisplay is altered.
-  std::string display_data(reinterpret_cast<const char*>(kOverscanDisplay),
-                           charsize(kOverscanDisplay));
-  display_data[150] = '\0';
-  EXPECT_TRUE(ParseOutputOverscanFlag(
-      reinterpret_cast<const unsigned char*>(display_data.data()),
-      display_data.size(),
-      &flag));
-  EXPECT_FALSE(flag);
-}
-
-TEST(DisplayUtilTest, ParseBrokenOverscanData) {
-  // Do not fill valid data here because it anyway fails to parse the data.
-  scoped_ptr<unsigned char[]> data(new unsigned char[126]);
-  bool flag = false;
-  EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 0, &flag));
-  EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 126, &flag));
-
-  // extending data because ParseOutputOverscanFlag() will access the data.
-  data.reset(new unsigned char[150]);
-  // The number of CEA extensions is stored at byte 126.
-  data[126] = '\x01';
-  EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 128, &flag));
-  EXPECT_FALSE(ParseOutputOverscanFlag(data.get(), 150, &flag));
-}
-
-TEST(DisplayUtilTest, GetOutputTypeFromName) {
-  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("LVDS"));
-  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("eDP"));
-  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("DSI"));
-  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("LVDSxx"));
-  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("eDPzz"));
-  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("DSIyy"));
-
-  EXPECT_EQ(OUTPUT_TYPE_VGA, GetOutputTypeFromName("VGA"));
-  EXPECT_EQ(OUTPUT_TYPE_VGA, GetOutputTypeFromName("VGAxx"));
-  EXPECT_EQ(OUTPUT_TYPE_HDMI, GetOutputTypeFromName("HDMI"));
-  EXPECT_EQ(OUTPUT_TYPE_HDMI, GetOutputTypeFromName("HDMIyy"));
-  EXPECT_EQ(OUTPUT_TYPE_DVI, GetOutputTypeFromName("DVI"));
-  EXPECT_EQ(OUTPUT_TYPE_DVI, GetOutputTypeFromName("DVIzz"));
-  EXPECT_EQ(OUTPUT_TYPE_DISPLAYPORT, GetOutputTypeFromName("DP"));
-  EXPECT_EQ(OUTPUT_TYPE_DISPLAYPORT, GetOutputTypeFromName("DPww"));
-
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("xyz"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("abcLVDS"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("cdeeDP"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("abcDSI"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("LVD"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("eD"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("DS"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("VG"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("HDM"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("DV"));
-  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("D"));
-}
-
-}  // namespace ui
diff --git a/ui/display/chromeos/x11/display_util_x11.cc b/ui/display/chromeos/x11/display_util_x11.cc
new file mode 100644
index 0000000..f5a4f27
--- /dev/null
+++ b/ui/display/chromeos/x11/display_util_x11.cc
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/chromeos/x11/display_util_x11.h"
+
+#include "base/macros.h"
+
+namespace ui {
+
+namespace {
+
+struct OutputTypeMapping {
+  // Prefix of output name.
+  const char* name;
+  OutputType type;
+};
+
+const OutputTypeMapping kOutputTypeMapping[] = {
+  {"LVDS", OUTPUT_TYPE_INTERNAL},
+  {"eDP", OUTPUT_TYPE_INTERNAL},
+  {"DSI", OUTPUT_TYPE_INTERNAL},
+  {"VGA", OUTPUT_TYPE_VGA},
+  {"HDMI", OUTPUT_TYPE_HDMI},
+  {"DVI", OUTPUT_TYPE_DVI},
+  {"DP", OUTPUT_TYPE_DISPLAYPORT}
+};
+
+}  // namespace
+
+OutputType GetOutputTypeFromName(const std::string& name) {
+  for (unsigned int i = 0; i < arraysize(kOutputTypeMapping); ++i) {
+    if (name.find(kOutputTypeMapping[i].name) == 0) {
+      return kOutputTypeMapping[i].type;
+    }
+  }
+
+  return OUTPUT_TYPE_UNKNOWN;
+}
+
+}  // namespace ui
diff --git a/ui/display/chromeos/x11/display_util_x11.h b/ui/display/chromeos/x11/display_util_x11.h
new file mode 100644
index 0000000..c8a7837
--- /dev/null
+++ b/ui/display/chromeos/x11/display_util_x11.h
@@ -0,0 +1,24 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_X11_H_
+#define UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_X11_H_
+
+#include <string>
+
+#include "ui/display/display_constants.h"
+#include "ui/display/display_export.h"
+
+typedef unsigned long XID;
+typedef XID RROutput;
+
+namespace ui {
+
+// Returns the OutputType by matching known type prefixes to |name|. Returns
+// OUTPUT_TYPE_UNKNOWN if no valid match.
+DISPLAY_EXPORT OutputType GetOutputTypeFromName(const std::string& name);
+
+}  // namespace ui
+
+#endif  // UI_DISPLAY_CHROMEOS_DISPLAY_UTIL_X11_H_
diff --git a/ui/display/chromeos/x11/display_util_x11_unittest.cc b/ui/display/chromeos/x11/display_util_x11_unittest.cc
new file mode 100644
index 0000000..e178f7f
--- /dev/null
+++ b/ui/display/chromeos/x11/display_util_x11_unittest.cc
@@ -0,0 +1,42 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/chromeos/x11/display_util_x11.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+TEST(DisplayUtilX11Test, GetOutputTypeFromName) {
+  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("LVDS"));
+  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("eDP"));
+  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("DSI"));
+  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("LVDSxx"));
+  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("eDPzz"));
+  EXPECT_EQ(OUTPUT_TYPE_INTERNAL, GetOutputTypeFromName("DSIyy"));
+
+  EXPECT_EQ(OUTPUT_TYPE_VGA, GetOutputTypeFromName("VGA"));
+  EXPECT_EQ(OUTPUT_TYPE_VGA, GetOutputTypeFromName("VGAxx"));
+  EXPECT_EQ(OUTPUT_TYPE_HDMI, GetOutputTypeFromName("HDMI"));
+  EXPECT_EQ(OUTPUT_TYPE_HDMI, GetOutputTypeFromName("HDMIyy"));
+  EXPECT_EQ(OUTPUT_TYPE_DVI, GetOutputTypeFromName("DVI"));
+  EXPECT_EQ(OUTPUT_TYPE_DVI, GetOutputTypeFromName("DVIzz"));
+  EXPECT_EQ(OUTPUT_TYPE_DISPLAYPORT, GetOutputTypeFromName("DP"));
+  EXPECT_EQ(OUTPUT_TYPE_DISPLAYPORT, GetOutputTypeFromName("DPww"));
+
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("xyz"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("abcLVDS"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("cdeeDP"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("abcDSI"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("LVD"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("eD"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("DS"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("VG"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("HDM"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("DV"));
+  EXPECT_EQ(OUTPUT_TYPE_UNKNOWN, GetOutputTypeFromName("D"));
+}
+
+}  // namespace ui
diff --git a/ui/display/chromeos/x11/native_display_delegate_x11.cc b/ui/display/chromeos/x11/native_display_delegate_x11.cc
index 2135ad9..8f687c9 100644
--- a/ui/display/chromeos/x11/native_display_delegate_x11.cc
+++ b/ui/display/chromeos/x11/native_display_delegate_x11.cc
@@ -16,12 +16,12 @@
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_pump_x11.h"
 #include "base/stl_util.h"
-#include "base/x11/edid_parser_x11.h"
 #include "ui/display/chromeos/native_display_observer.h"
 #include "ui/display/chromeos/x11/display_mode_x11.h"
 #include "ui/display/chromeos/x11/display_snapshot_x11.h"
-#include "ui/display/chromeos/x11/display_util.h"
+#include "ui/display/chromeos/x11/display_util_x11.h"
 #include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
+#include "ui/display/x11/edid_parser_x11.h"
 #include "ui/gfx/x/x11_error_tracker.h"
 
 namespace ui {
@@ -195,7 +195,7 @@
 
 void NativeDisplayDelegateX11::SyncWithServer() { XSync(display_, 0); }
 
-void NativeDisplayDelegateX11::SetBackgroundColor(uint32 color_argb) {
+void NativeDisplayDelegateX11::SetBackgroundColor(uint32_t color_argb) {
   // Configuring CRTCs/Framebuffer clears the boot screen image.  Set the
   // same background color while configuring the display to minimize the
   // duration of black screen at boot time. The background is filled with
@@ -343,7 +343,8 @@
     RRCrtc* last_used_crtc,
     int index) {
   int64_t display_id = 0;
-  bool has_display_id = base::GetDisplayId(id, index, &display_id);
+  bool has_display_id = GetDisplayId(
+      id, static_cast<uint8_t>(index), &display_id);
 
   OutputType type = GetOutputTypeFromName(info->name);
   if (type == OUTPUT_TYPE_UNKNOWN)
@@ -384,9 +385,6 @@
   const DisplayMode* native_mode = NULL;
   std::vector<const DisplayMode*> display_modes;
 
-  // TODO(mukai|marcheu): check the system status and fill the correct list of
-  // available color profiles.
-
   for (int i = 0; i < info->nmode; ++i) {
     const RRMode mode = info->modes[i];
     if (modes_.find(mode) != modes_.end()) {
@@ -607,6 +605,15 @@
   return ret;
 }
 
+
+std::vector<ColorCalibrationProfile>
+NativeDisplayDelegateX11::GetAvailableColorCalibrationProfiles(
+    const DisplaySnapshot& output) {
+  // TODO(mukai|marcheu): Checks the system data and fills the result.
+  // Note that the order would be Dynamic -> Standard -> Movie -> Reading.
+  return std::vector<ColorCalibrationProfile>();
+}
+
 bool NativeDisplayDelegateX11::SetColorCalibrationProfile(
     const DisplaySnapshot& output,
     ColorCalibrationProfile new_profile) {
diff --git a/ui/display/chromeos/x11/native_display_delegate_x11.h b/ui/display/chromeos/x11/native_display_delegate_x11.h
index 1affda4..d4b608d 100644
--- a/ui/display/chromeos/x11/native_display_delegate_x11.h
+++ b/ui/display/chromeos/x11/native_display_delegate_x11.h
@@ -5,10 +5,11 @@
 #ifndef UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
 #define UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
 
+#include <stdint.h>
+
 #include <map>
 #include <vector>
 
-#include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/event_types.h"
 #include "base/memory/scoped_ptr.h"
@@ -70,7 +71,7 @@
   virtual void GrabServer() OVERRIDE;
   virtual void UngrabServer() OVERRIDE;
   virtual void SyncWithServer() OVERRIDE;
-  virtual void SetBackgroundColor(uint32 color_argb) OVERRIDE;
+  virtual void SetBackgroundColor(uint32_t color_argb) OVERRIDE;
   virtual void ForceDPMSOn() OVERRIDE;
   virtual std::vector<DisplaySnapshot*> GetOutputs() OVERRIDE;
   virtual void AddMode(const DisplaySnapshot& output,
@@ -83,6 +84,9 @@
                             HDCPState* state) OVERRIDE;
   virtual bool SetHDCPState(const DisplaySnapshot& output,
                             HDCPState state) OVERRIDE;
+  virtual std::vector<ColorCalibrationProfile>
+      GetAvailableColorCalibrationProfiles(
+          const DisplaySnapshot& output) OVERRIDE;
   virtual bool SetColorCalibrationProfile(
       const DisplaySnapshot& output,
       ColorCalibrationProfile new_profile) OVERRIDE;
diff --git a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.cc b/ui/display/chromeos/x11/native_display_event_dispatcher_x11.cc
index 786d865..613608a 100644
--- a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.cc
+++ b/ui/display/chromeos/x11/native_display_event_dispatcher_x11.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/time/default_tick_clock.h"
 #include "ui/display/chromeos/x11/native_display_event_dispatcher_x11.h"
 #include "ui/display/chromeos/x11/display_mode_x11.h"
 #include "ui/display/chromeos/x11/display_snapshot_x11.h"
@@ -10,10 +11,15 @@
 
 namespace ui {
 
+// static
+const int NativeDisplayEventDispatcherX11::kCachedOutputsExpirationMs = 5000;
+
 NativeDisplayEventDispatcherX11::NativeDisplayEventDispatcherX11(
     NativeDisplayDelegateX11::HelperDelegate* delegate,
     int xrandr_event_base)
-    : delegate_(delegate), xrandr_event_base_(xrandr_event_base) {}
+    : delegate_(delegate),
+      xrandr_event_base_(xrandr_event_base),
+      tick_clock_(new base::DefaultTickClock) {}
 
 NativeDisplayEventDispatcherX11::~NativeDisplayEventDispatcherX11() {}
 
@@ -45,37 +51,49 @@
           << " mode=" << output_change_event->mode
           << " action=" << (connected ? "connected" : "disconnected");
 
-  bool found_changed_output = false;
-  const std::vector<DisplaySnapshot*>& cached_outputs =
-      delegate_->GetCachedOutputs();
-  for (std::vector<DisplaySnapshot*>::const_iterator it =
-           cached_outputs.begin();
-       it != cached_outputs.end();
-       ++it) {
-    const DisplaySnapshotX11* x11_output =
-        static_cast<const DisplaySnapshotX11*>(*it);
-    const DisplayModeX11* x11_mode =
-        static_cast<const DisplayModeX11*>(x11_output->current_mode());
+  bool force_notify = last_notified_time_.is_null() ||
+      (tick_clock_->NowTicks() - last_notified_time_).InMilliseconds() >=
+      kCachedOutputsExpirationMs;
+  if (!force_notify) {
+    bool found_changed_output = false;
+    const std::vector<DisplaySnapshot*>& cached_outputs =
+        delegate_->GetCachedOutputs();
+    for (std::vector<DisplaySnapshot*>::const_iterator it =
+             cached_outputs.begin();
+         it != cached_outputs.end();
+         ++it) {
+      const DisplaySnapshotX11* x11_output =
+          static_cast<const DisplaySnapshotX11*>(*it);
+      const DisplayModeX11* x11_mode =
+          static_cast<const DisplayModeX11*>(x11_output->current_mode());
 
-    if (x11_output->output() == output_change_event->output) {
-      if (connected && x11_output->crtc() == output_change_event->crtc &&
-          x11_mode->mode_id() == output_change_event->mode) {
-        VLOG(1) << "Ignoring event describing already-cached state";
-        return POST_DISPATCH_PERFORM_DEFAULT;
+      if (x11_output->output() == output_change_event->output) {
+        if (connected && x11_output->crtc() == output_change_event->crtc &&
+            x11_mode->mode_id() == output_change_event->mode) {
+          VLOG(1) << "Ignoring event describing already-cached state";
+          return POST_DISPATCH_PERFORM_DEFAULT;
+        }
+        found_changed_output = true;
+        break;
       }
-      found_changed_output = true;
-      break;
+    }
+
+    if (!connected && !found_changed_output) {
+      VLOG(1) << "Ignoring event describing already-disconnected output";
+      return POST_DISPATCH_PERFORM_DEFAULT;
     }
   }
 
-  if (!connected && !found_changed_output) {
-    VLOG(1) << "Ignoring event describing already-disconnected output";
-    return POST_DISPATCH_PERFORM_DEFAULT;
-  }
+  last_notified_time_ = tick_clock_->NowTicks();
 
   delegate_->NotifyDisplayObservers();
 
   return POST_DISPATCH_PERFORM_DEFAULT;
 }
 
+void NativeDisplayEventDispatcherX11::SetTickClockForTest(
+    scoped_ptr<base::TickClock> tick_clock) {
+  tick_clock_ = tick_clock.Pass();
+}
+
 }  // namespace ui
diff --git a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.h b/ui/display/chromeos/x11/native_display_event_dispatcher_x11.h
index 94034b6..d173efd 100644
--- a/ui/display/chromeos/x11/native_display_event_dispatcher_x11.h
+++ b/ui/display/chromeos/x11/native_display_event_dispatcher_x11.h
@@ -6,6 +6,8 @@
 #define UI_DISPLAY_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
 
 #include "base/message_loop/message_pump_dispatcher.h"
+#include "base/time/tick_clock.h"
+#include "base/time/time.h"
 #include "ui/display/chromeos/x11/native_display_delegate_x11.h"
 
 namespace ui {
@@ -27,6 +29,11 @@
   // Spurious events will have no effect.
   virtual uint32_t Dispatch(const base::NativeEvent& event) OVERRIDE;
 
+  void SetTickClockForTest(scoped_ptr<base::TickClock> tick_clock);
+
+  // How long the cached output is valid.
+  static const int kCachedOutputsExpirationMs;
+
  private:
   NativeDisplayDelegateX11::HelperDelegate* delegate_;  // Not owned.
 
@@ -34,6 +41,11 @@
   // decoding events regarding output add/remove.
   int xrandr_event_base_;
 
+  // The last time display observers were notified.
+  base::TimeTicks last_notified_time_;
+
+  scoped_ptr<base::TickClock> tick_clock_;
+
   DISALLOW_COPY_AND_ASSIGN(NativeDisplayEventDispatcherX11);
 };
 
diff --git a/ui/display/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc b/ui/display/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
index abb4237..d43a630 100644
--- a/ui/display/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
+++ b/ui/display/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
@@ -7,6 +7,7 @@
 #undef Bool
 #undef None
 
+#include "base/test/simple_test_tick_clock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/display/chromeos/x11/display_mode_x11.h"
 #include "ui/display/chromeos/x11/display_snapshot_x11.h"
@@ -105,6 +106,7 @@
   int xrandr_event_base_;
   scoped_ptr<TestHelperDelegate> helper_delegate_;
   scoped_ptr<NativeDisplayEventDispatcherX11> dispatcher_;
+  base::SimpleTestTickClock* test_tick_clock_;  // Owned by |dispatcher_|.
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NativeDisplayEventDispatcherX11Test);
@@ -114,7 +116,12 @@
     : xrandr_event_base_(10),
       helper_delegate_(new TestHelperDelegate()),
       dispatcher_(new NativeDisplayEventDispatcherX11(helper_delegate_.get(),
-                                                      xrandr_event_base_)) {}
+                                                      xrandr_event_base_)),
+      test_tick_clock_(new base::SimpleTestTickClock) {
+  test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1));
+  dispatcher_->SetTickClockForTest(
+      scoped_ptr<base::TickClock>(test_tick_clock_));
+}
 
 NativeDisplayEventDispatcherX11Test::~NativeDisplayEventDispatcherX11Test() {}
 
@@ -172,8 +179,12 @@
   outputs.push_back(CreateOutput(1, 10));
   helper_delegate_->set_cached_outputs(outputs.get());
 
+  // Very first event will not be ignored.
   DispatchOutputChangeEvent(1, 10, 20, true);
-  EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
+  EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
+
+  DispatchOutputChangeEvent(1, 10, 20, true);
+  EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
 }
 
 TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDisconnect) {
@@ -241,4 +252,50 @@
   EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
 }
 
+TEST_F(NativeDisplayEventDispatcherX11Test,
+       ForceUpdateAfterCacheExpiration) {
+  // +1 to compenstate a possible rounding error.
+  const int kHalfOfExpirationMs =
+      NativeDisplayEventDispatcherX11::kCachedOutputsExpirationMs / 2 + 1;
+
+  ScopedVector<DisplaySnapshot> outputs;
+  outputs.push_back(CreateOutput(1, 10));
+  outputs.push_back(CreateOutput(2, 11));
+  helper_delegate_->set_cached_outputs(outputs.get());
+
+  EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
+
+  DispatchOutputChangeEvent(2, 11, 20, true);
+  EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
+
+  // Duplicated event will be ignored.
+  DispatchOutputChangeEvent(2, 11, 20, true);
+  EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
+
+  test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
+      kHalfOfExpirationMs));
+
+  // Duplicated event will still be ignored.
+  DispatchOutputChangeEvent(2, 11, 20, true);
+  EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
+
+  // Duplicated event does notify after expiration timeout.
+  test_tick_clock_->Advance(
+      base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
+  DispatchOutputChangeEvent(2, 11, 20, true);
+  EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
+
+  // Last update time has been updated, so next duplicated change event
+  // will be ignored.
+  DispatchOutputChangeEvent(2, 11, 20, true);
+  EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
+
+  // Another duplicated change event arrived within expiration time will
+  // be ignored again.
+  test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(
+      kHalfOfExpirationMs));
+  DispatchOutputChangeEvent(2, 11, 20, true);
+  EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
+}
+
 }  // namespace ui
diff --git a/ui/display/display.gyp b/ui/display/display.gyp
index 5f766ac..da58929 100644
--- a/ui/display/display.gyp
+++ b/ui/display/display.gyp
@@ -27,12 +27,16 @@
         'chromeos/native_display_observer.h',
         'chromeos/output_configurator.cc',
         'chromeos/output_configurator.h',
-        'chromeos/x11/display_util.cc',
-        'chromeos/x11/display_util.h',
+        'chromeos/ozone/native_display_delegate_ozone.cc',
+        'chromeos/ozone/native_display_delegate_ozone.h',
+        'chromeos/ozone/touchscreen_delegate_ozone.cc',
+        'chromeos/ozone/touchscreen_delegate_ozone.h',
         'chromeos/x11/display_mode_x11.cc',
         'chromeos/x11/display_mode_x11.h',
         'chromeos/x11/display_snapshot_x11.cc',
         'chromeos/x11/display_snapshot_x11.h',
+        'chromeos/x11/display_util_x11.cc',
+        'chromeos/x11/display_util_x11.h',
         'chromeos/x11/native_display_delegate_x11.cc',
         'chromeos/x11/native_display_delegate_x11.h',
         'chromeos/x11/native_display_event_dispatcher_x11.cc',
@@ -41,6 +45,10 @@
         'chromeos/x11/touchscreen_delegate_x11.h',
         'display_constants.h',
         'display_export.h',
+        'edid_parser.cc',
+        'edid_parser.h',
+        'x11/edid_parser_x11.cc',
+        'x11/edid_parser_x11.h',
       ],
       'conditions': [
         ['use_x11 == 1', {
diff --git a/ui/display/display_constants.h b/ui/display/display_constants.h
index df0f1cc..7ad2664 100644
--- a/ui/display/display_constants.h
+++ b/ui/display/display_constants.h
@@ -37,12 +37,14 @@
 // HDCP protection state.
 enum HDCPState { HDCP_STATE_UNDESIRED, HDCP_STATE_DESIRED, HDCP_STATE_ENABLED };
 
-// Color calibration profiles.
+// Color calibration profiles. Don't change the order, and edit
+// tools/metrics/histograms/histograms.xml when a new item is added.
 enum ColorCalibrationProfile {
   COLOR_PROFILE_STANDARD,
   COLOR_PROFILE_DYNAMIC,
   COLOR_PROFILE_MOVIE,
   COLOR_PROFILE_READING,
+  NUM_COLOR_PROFILES,
 };
 
 }  // namespace ui
diff --git a/ui/display/display_unittests.gypi b/ui/display/display_unittests.gypi
index 6597bb9..591bde5 100644
--- a/ui/display/display_unittests.gypi
+++ b/ui/display/display_unittests.gypi
@@ -8,11 +8,13 @@
   'dependencies': [
     '../base/base.gyp:test_support_base',
     '../testing/gtest.gyp:gtest',
+    '../ui/display/display.gyp:display',
     '../ui/gfx/gfx.gyp:gfx_geometry',
   ],
   'sources': [
+    'edid_parser_unittest.cc',
     'chromeos/output_configurator_unittest.cc',
-    'chromeos/x11/display_util_unittest.cc',
+    'chromeos/x11/display_util_x11_unittest.cc',
     'chromeos/x11/native_display_event_dispatcher_x11_unittest.cc',
   ],
   'conditions': [
@@ -21,7 +23,6 @@
     # not like empty libraries.
     ['chromeos == 1', {
       'dependencies': [
-        '../ui/display/display.gyp:display',
         '../ui/display/display.gyp:display_test_util',
       ],
     }],
diff --git a/ui/display/edid_parser.cc b/ui/display/edid_parser.cc
new file mode 100644
index 0000000..686b071
--- /dev/null
+++ b/ui/display/edid_parser.cc
@@ -0,0 +1,197 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/edid_parser.h"
+
+#include <algorithm>
+
+#include "base/hash.h"
+#include "base/strings/string_util.h"
+#include "base/sys_byteorder.h"
+
+namespace ui {
+
+namespace {
+
+// Returns 64-bit persistent ID for the specified manufacturer's ID and
+// product_code_hash, and the index of the output it is connected to.
+// |output_index| is used to distinguish the displays of the same type. For
+// example, swapping two identical display between two outputs will not be
+// treated as swap. The 'serial number' field in EDID isn't used here because
+// it is not guaranteed to have unique number and it may have the same fixed
+// value (like 0).
+int64_t GetID(uint16_t manufacturer_id,
+              uint32_t product_code_hash,
+              uint8_t output_index) {
+  return ((static_cast<int64_t>(manufacturer_id) << 40) |
+          (static_cast<int64_t>(product_code_hash) << 8) | output_index);
+}
+
+}  // namespace
+
+bool GetDisplayIdFromEDID(const std::vector<uint8_t>& edid,
+                          uint8_t output_index,
+                          int64_t* display_id_out) {
+  uint16_t manufacturer_id = 0;
+  std::string product_name;
+
+  // ParseOutputDeviceData fails if it doesn't have product_name.
+  ParseOutputDeviceData(edid, &manufacturer_id, &product_name);
+
+  // Generates product specific value from product_name instead of product code.
+  // See crbug.com/240341
+  uint32_t product_code_hash = product_name.empty() ?
+      0 : base::Hash(product_name);
+  if (manufacturer_id != 0) {
+    // An ID based on display's index will be assigned later if this call
+    // fails.
+    *display_id_out = GetID(
+        manufacturer_id, product_code_hash, output_index);
+    return true;
+  }
+  return false;
+}
+
+bool ParseOutputDeviceData(const std::vector<uint8_t>& edid,
+                           uint16_t* manufacturer_id,
+                           std::string* human_readable_name) {
+  // See http://en.wikipedia.org/wiki/Extended_display_identification_data
+  // for the details of EDID data format.  We use the following data:
+  //   bytes 8-9: manufacturer EISA ID, in big-endian
+  //   bytes 54-125: four descriptors (18-bytes each) which may contain
+  //     the display name.
+  const unsigned int kManufacturerOffset = 8;
+  const unsigned int kManufacturerLength = 2;
+  const unsigned int kDescriptorOffset = 54;
+  const unsigned int kNumDescriptors = 4;
+  const unsigned int kDescriptorLength = 18;
+  // The specifier types.
+  const unsigned char kMonitorNameDescriptor = 0xfc;
+
+  if (manufacturer_id) {
+    if (edid.size() < kManufacturerOffset + kManufacturerLength) {
+      LOG(ERROR) << "too short EDID data: manifacturer id";
+      return false;
+    }
+
+    *manufacturer_id =
+        *reinterpret_cast<const uint16_t*>(&edid[kManufacturerOffset]);
+#if defined(ARCH_CPU_LITTLE_ENDIAN)
+    *manufacturer_id = base::ByteSwap(*manufacturer_id);
+#endif
+  }
+
+  if (!human_readable_name)
+    return true;
+
+  human_readable_name->clear();
+  for (unsigned int i = 0; i < kNumDescriptors; ++i) {
+    if (edid.size() < kDescriptorOffset + (i + 1) * kDescriptorLength)
+      break;
+
+    size_t offset = kDescriptorOffset + i * kDescriptorLength;
+    // If the descriptor contains the display name, it has the following
+    // structure:
+    //   bytes 0-2, 4: \0
+    //   byte 3: descriptor type, defined above.
+    //   bytes 5-17: text data, ending with \r, padding with spaces
+    // we should check bytes 0-2 and 4, since it may have other values in
+    // case that the descriptor contains other type of data.
+    if (edid[offset] == 0 && edid[offset + 1] == 0 && edid[offset + 2] == 0 &&
+        edid[offset + 3] == kMonitorNameDescriptor && edid[offset + 4] == 0) {
+      std::string found_name(reinterpret_cast<const char*>(&edid[offset + 5]),
+                             kDescriptorLength - 5);
+      base::TrimWhitespaceASCII(
+          found_name, base::TRIM_TRAILING, human_readable_name);
+      break;
+    }
+  }
+
+  // Verify if the |human_readable_name| consists of printable characters only.
+  for (size_t i = 0; i < human_readable_name->size(); ++i) {
+    char c = (*human_readable_name)[i];
+    if (!isascii(c) || !isprint(c)) {
+      human_readable_name->clear();
+      LOG(ERROR) << "invalid EDID: human unreadable char in name";
+      return false;
+    }
+  }
+
+  return true;
+}
+
+bool ParseOutputOverscanFlag(const std::vector<uint8_t>& edid,
+                             bool* flag) {
+  // See http://en.wikipedia.org/wiki/Extended_display_identification_data
+  // for the extension format of EDID.  Also see EIA/CEA-861 spec for
+  // the format of the extensions and how video capability is encoded.
+  //  - byte 0: tag.  should be 02h.
+  //  - byte 1: revision.  only cares revision 3 (03h).
+  //  - byte 4-: data block.
+  const unsigned int kExtensionBase = 128;
+  const unsigned int kExtensionSize = 128;
+  const unsigned int kNumExtensionsOffset = 126;
+  const unsigned int kDataBlockOffset = 4;
+  const unsigned char kCEAExtensionTag = '\x02';
+  const unsigned char kExpectedExtensionRevision = '\x03';
+  const unsigned char kExtendedTag = 7;
+  const unsigned char kExtendedVideoCapabilityTag = 0;
+  const unsigned int kPTOverscan = 4;
+  const unsigned int kITOverscan = 2;
+  const unsigned int kCEOverscan = 0;
+
+  if (edid.size() <= kNumExtensionsOffset)
+    return false;
+
+  unsigned char num_extensions = edid[kNumExtensionsOffset];
+
+  for (size_t i = 0; i < num_extensions; ++i) {
+    // Skip parsing the whole extension if size is not enough.
+    if (edid.size() < kExtensionBase + (i + 1) * kExtensionSize)
+      break;
+
+    size_t extension_offset = kExtensionBase + i * kExtensionSize;
+    unsigned char tag = edid[extension_offset];
+    unsigned char revision = edid[extension_offset + 1];
+    if (tag != kCEAExtensionTag || revision != kExpectedExtensionRevision)
+      continue;
+
+    unsigned char timing_descriptors_start = std::min(
+        edid[extension_offset + 2], static_cast<unsigned char>(kExtensionSize));
+
+    for (size_t data_offset = extension_offset + kDataBlockOffset;
+         data_offset < extension_offset + timing_descriptors_start;) {
+      // A data block is encoded as:
+      // - byte 1 high 3 bits: tag. '07' for extended tags.
+      // - byte 1 remaining bits: the length of data block.
+      // - byte 2: the extended tag.  '0' for video capability.
+      // - byte 3: the capability.
+      unsigned char tag = edid[data_offset] >> 5;
+      unsigned char payload_length = edid[data_offset] & 0x1f;
+      if (data_offset + payload_length > edid.size())
+        break;
+
+      if (tag != kExtendedTag || payload_length < 2 ||
+          edid[data_offset + 1] != kExtendedVideoCapabilityTag) {
+        data_offset += payload_length + 1;
+        continue;
+      }
+
+      // The difference between preferred, IT, and CE video formats
+      // doesn't matter. Sets |flag| to true if any of these flags are true.
+      if ((edid[data_offset + 2] & (1 << kPTOverscan)) ||
+          (edid[data_offset + 2] & (1 << kITOverscan)) ||
+          (edid[data_offset + 2] & (1 << kCEOverscan))) {
+        *flag = true;
+      } else {
+        *flag = false;
+      }
+      return true;
+    }
+  }
+
+  return false;
+}
+
+}  // namespace ui
diff --git a/ui/display/edid_parser.h b/ui/display/edid_parser.h
new file mode 100644
index 0000000..2527abf
--- /dev/null
+++ b/ui/display/edid_parser.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_EDID_PARSER_H_
+#define UI_DISPLAY_EDID_PARSER_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "ui/display/display_export.h"
+
+// EDID (Extended Display Identification Data) is a format for monitor
+// metadata. This provides a parser for the data.
+
+namespace ui {
+
+// Generates the display id for the pair of |edid| and |index|, and store in
+// |display_id_out|. Returns true if the display id is successfully generated,
+// or false otherwise.
+DISPLAY_EXPORT bool GetDisplayIdFromEDID(const std::vector<uint8_t>& edid,
+                                         uint8_t index,
+                                         int64_t* display_id_out);
+
+// Parses |edid| as EDID data and stores extracted data into |manufacturer_id|
+// and |human_readable_name| and returns true. NULL can be passed for unwanted
+// output parameters. Some devices (especially internal displays) may not have
+// the field for |human_readable_name|, and it will return true in that case.
+DISPLAY_EXPORT bool ParseOutputDeviceData(const std::vector<uint8_t>& edid,
+                                          uint16_t* manufacturer_id,
+                                          std::string* human_readable_name);
+
+DISPLAY_EXPORT bool ParseOutputOverscanFlag(const std::vector<uint8_t>& edid,
+                                            bool* flag);
+
+}  // namespace ui
+
+#endif // UI_DISPLAY_EDID_PARSER_H_
diff --git a/ui/display/edid_parser_unittest.cc b/ui/display/edid_parser_unittest.cc
new file mode 100644
index 0000000..cac630e
--- /dev/null
+++ b/ui/display/edid_parser_unittest.cc
@@ -0,0 +1,229 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/edid_parser.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ui {
+
+namespace {
+
+// Returns the number of characters in the string literal but doesn't count its
+// terminator NULL byte.
+#define charsize(str) (arraysize(str) - 1)
+
+// Sample EDID data extracted from real devices.
+const unsigned char kNormalDisplay[] =
+    "\x00\xff\xff\xff\xff\xff\xff\x00\x22\xf0\x6c\x28\x01\x01\x01\x01"
+    "\x02\x16\x01\x04\xb5\x40\x28\x78\xe2\x8d\x85\xad\x4f\x35\xb1\x25"
+    "\x0e\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+    "\x01\x01\x01\x01\x01\x01\xe2\x68\x00\xa0\xa0\x40\x2e\x60\x30\x20"
+    "\x36\x00\x81\x90\x21\x00\x00\x1a\xbc\x1b\x00\xa0\x50\x20\x17\x30"
+    "\x30\x20\x36\x00\x81\x90\x21\x00\x00\x1a\x00\x00\x00\xfc\x00\x48"
+    "\x50\x20\x5a\x52\x33\x30\x77\x0a\x20\x20\x20\x20\x00\x00\x00\xff"
+    "\x00\x43\x4e\x34\x32\x30\x32\x31\x33\x37\x51\x0a\x20\x20\x00\x71";
+
+const unsigned char kInternalDisplay[] =
+    "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\xa3\x42\x31\x00\x00\x00\x00"
+    "\x00\x15\x01\x03\x80\x1a\x10\x78\x0a\xd3\xe5\x95\x5c\x60\x90\x27"
+    "\x19\x50\x54\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01"
+    "\x01\x01\x01\x01\x01\x01\x9e\x1b\x00\xa0\x50\x20\x12\x30\x10\x30"
+    "\x13\x00\x05\xa3\x10\x00\x00\x19\x00\x00\x00\x0f\x00\x00\x00\x00"
+    "\x00\x00\x00\x00\x00\x23\x87\x02\x64\x00\x00\x00\x00\xfe\x00\x53"
+    "\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x00\x00\x00\xfe"
+    "\x00\x31\x32\x31\x41\x54\x31\x31\x2d\x38\x30\x31\x0a\x20\x00\x45";
+
+const unsigned char kOverscanDisplay[] =
+    "\x00\xff\xff\xff\xff\xff\xff\x00\x4c\x2d\xfe\x08\x00\x00\x00\x00"
+    "\x29\x15\x01\x03\x80\x10\x09\x78\x0a\xee\x91\xa3\x54\x4c\x99\x26"
+    "\x0f\x50\x54\xbd\xef\x80\x71\x4f\x81\xc0\x81\x00\x81\x80\x95\x00"
+    "\xa9\xc0\xb3\x00\x01\x01\x02\x3a\x80\x18\x71\x38\x2d\x40\x58\x2c"
+    "\x45\x00\xa0\x5a\x00\x00\x00\x1e\x66\x21\x56\xaa\x51\x00\x1e\x30"
+    "\x46\x8f\x33\x00\xa0\x5a\x00\x00\x00\x1e\x00\x00\x00\xfd\x00\x18"
+    "\x4b\x0f\x51\x17\x00\x0a\x20\x20\x20\x20\x20\x20\x00\x00\x00\xfc"
+    "\x00\x53\x41\x4d\x53\x55\x4e\x47\x0a\x20\x20\x20\x20\x20\x01\x1d"
+    "\x02\x03\x1f\xf1\x47\x90\x04\x05\x03\x20\x22\x07\x23\x09\x07\x07"
+    "\x83\x01\x00\x00\xe2\x00\x0f\x67\x03\x0c\x00\x20\x00\xb8\x2d\x01"
+    "\x1d\x80\x18\x71\x1c\x16\x20\x58\x2c\x25\x00\xa0\x5a\x00\x00\x00"
+    "\x9e\x01\x1d\x00\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\xa0\x5a\x00"
+    "\x00\x00\x1e\x8c\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\xa0"
+    "\x5a\x00\x00\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc6";
+
+// The EDID info misdetecting overscan once. see crbug.com/226318
+const unsigned char kMisdetectedDisplay[] =
+    "\x00\xff\xff\xff\xff\xff\xff\x00\x10\xac\x64\x40\x4c\x30\x30\x32"
+    "\x0c\x15\x01\x03\x80\x40\x28\x78\xea\x8d\x85\xad\x4f\x35\xb1\x25"
+    "\x0e\x50\x54\xa5\x4b\x00\x71\x4f\x81\x00\x81\x80\xd1\x00\xa9\x40"
+    "\x01\x01\x01\x01\x01\x01\x28\x3c\x80\xa0\x70\xb0\x23\x40\x30\x20"
+    "\x36\x00\x81\x91\x21\x00\x00\x1a\x00\x00\x00\xff\x00\x50\x48\x35"
+    "\x4e\x59\x31\x33\x4e\x32\x30\x30\x4c\x0a\x00\x00\x00\xfc\x00\x44"
+    "\x45\x4c\x4c\x20\x55\x33\x30\x31\x31\x0a\x20\x20\x00\x00\x00\xfd"
+    "\x00\x31\x56\x1d\x5e\x12\x00\x0a\x20\x20\x20\x20\x20\x20\x01\x38"
+    "\x02\x03\x29\xf1\x50\x90\x05\x04\x03\x02\x07\x16\x01\x06\x11\x12"
+    "\x15\x13\x14\x1f\x20\x23\x0d\x7f\x07\x83\x0f\x00\x00\x67\x03\x0c"
+    "\x00\x10\x00\x38\x2d\xe3\x05\x03\x01\x02\x3a\x80\x18\x71\x38\x2d"
+    "\x40\x58\x2c\x45\x00\x81\x91\x21\x00\x00\x1e\x01\x1d\x80\x18\x71"
+    "\x1c\x16\x20\x58\x2c\x25\x00\x81\x91\x21\x00\x00\x9e\x01\x1d\x00"
+    "\x72\x51\xd0\x1e\x20\x6e\x28\x55\x00\x81\x91\x21\x00\x00\x1e\x8c"
+    "\x0a\xd0\x8a\x20\xe0\x2d\x10\x10\x3e\x96\x00\x81\x91\x21\x00\x00"
+    "\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x94";
+
+const unsigned char kLP2565A[] =
+    "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x76\x26\x01\x01\x01\x01"
+    "\x02\x12\x01\x03\x80\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26"
+    "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x81\x80\x81\x99\x71\x00\xA9\x00"
+    "\xA9\x40\xB3\x00\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20"
+    "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E"
+    "\x5E\x11\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48"
+    "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF"
+    "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\xA4";
+
+const unsigned char kLP2565B[] =
+    "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00\x22\xF0\x75\x26\x01\x01\x01\x01"
+    "\x02\x12\x01\x03\x6E\x34\x21\x78\xEE\xEF\x95\xA3\x54\x4C\x9B\x26"
+    "\x0F\x50\x54\xA5\x6B\x80\x81\x40\x71\x00\xA9\x00\xA9\x40\xA9\x4F"
+    "\xB3\x00\xD1\xC0\xD1\x00\x28\x3C\x80\xA0\x70\xB0\x23\x40\x30\x20"
+    "\x36\x00\x07\x44\x21\x00\x00\x1A\x00\x00\x00\xFD\x00\x30\x55\x1E"
+    "\x5E\x15\x00\x0A\x20\x20\x20\x20\x20\x20\x00\x00\x00\xFC\x00\x48"
+    "\x50\x20\x4C\x50\x32\x34\x36\x35\x0A\x20\x20\x20\x00\x00\x00\xFF"
+    "\x00\x43\x4E\x4B\x38\x30\x32\x30\x34\x48\x4D\x0A\x20\x20\x00\x45";
+
+}  // namespace
+
+TEST(EDIDParserTest, ParseOverscanFlag) {
+  bool flag = false;
+  std::vector<uint8_t> edid(
+      kNormalDisplay, kNormalDisplay + charsize(kNormalDisplay));
+  EXPECT_FALSE(ParseOutputOverscanFlag(edid, &flag));
+
+  flag = false;
+  edid.assign(kInternalDisplay, kInternalDisplay + charsize(kInternalDisplay));
+  EXPECT_FALSE(ParseOutputOverscanFlag(edid, &flag));
+
+  flag = false;
+  edid.assign(kOverscanDisplay, kOverscanDisplay + charsize(kOverscanDisplay));
+  EXPECT_TRUE(ParseOutputOverscanFlag(edid, &flag));
+  EXPECT_TRUE(flag);
+
+  flag = false;
+  edid.assign(
+      kMisdetectedDisplay, kMisdetectedDisplay + charsize(kMisdetectedDisplay));
+  EXPECT_FALSE(ParseOutputOverscanFlag(edid, &flag));
+
+  flag = false;
+  // Copy |kOverscanDisplay| and set flags to false in it. The overscan flags
+  // are embedded at byte 150 in this specific example. Fix here too when the
+  // contents of kOverscanDisplay is altered.
+  edid.assign(kOverscanDisplay, kOverscanDisplay + charsize(kOverscanDisplay));
+  edid[150] = '\0';
+  EXPECT_TRUE(ParseOutputOverscanFlag(edid, &flag));
+  EXPECT_FALSE(flag);
+}
+
+TEST(EDIDParserTest, ParseBrokenOverscanData) {
+  // Do not fill valid data here because it anyway fails to parse the data.
+  std::vector<uint8_t> data;
+  bool flag = false;
+  EXPECT_FALSE(ParseOutputOverscanFlag(data, &flag));
+  data.assign(126, '\0');
+  EXPECT_FALSE(ParseOutputOverscanFlag(data, &flag));
+
+  // extending data because ParseOutputOverscanFlag() will access the data.
+  data.assign(128, '\0');
+  // The number of CEA extensions is stored at byte 126.
+  data[126] = '\x01';
+  EXPECT_FALSE(ParseOutputOverscanFlag(data, &flag));
+
+  data.assign(150, '\0');
+  data[126] = '\x01';
+  EXPECT_FALSE(ParseOutputOverscanFlag(data, &flag));
+}
+
+TEST(EDIDParserTest, ParseEDID) {
+  uint16_t manufacturer_id = 0;
+  std::string human_readable_name;
+  std::vector<uint8_t> edid(
+      kNormalDisplay, kNormalDisplay + charsize(kNormalDisplay));
+  EXPECT_TRUE(ParseOutputDeviceData(
+      edid, &manufacturer_id, &human_readable_name));
+  EXPECT_EQ(0x22f0u, manufacturer_id);
+  EXPECT_EQ("HP ZR30w", human_readable_name);
+
+  manufacturer_id = 0;
+  human_readable_name.clear();
+  edid.assign(kInternalDisplay, kInternalDisplay + charsize(kInternalDisplay));
+  EXPECT_TRUE(ParseOutputDeviceData(edid, &manufacturer_id, NULL));
+  EXPECT_EQ(0x4ca3u, manufacturer_id);
+  EXPECT_EQ("", human_readable_name);
+
+  // Internal display doesn't have name.
+  EXPECT_TRUE(ParseOutputDeviceData(edid, NULL, &human_readable_name));
+  EXPECT_TRUE(human_readable_name.empty());
+
+  manufacturer_id = 0;
+  human_readable_name.clear();
+  edid.assign(kOverscanDisplay, kOverscanDisplay + charsize(kOverscanDisplay));
+  EXPECT_TRUE(ParseOutputDeviceData(
+      edid, &manufacturer_id, &human_readable_name));
+  EXPECT_EQ(0x4c2du, manufacturer_id);
+  EXPECT_EQ("SAMSUNG", human_readable_name);
+}
+
+TEST(EDIDParserTest, ParseBrokenEDID) {
+  uint16_t manufacturer_id = 0;
+  std::string human_readable_name;
+  std::vector<uint8_t> edid;
+
+  // length == 0
+  EXPECT_FALSE(ParseOutputDeviceData(
+      edid, &manufacturer_id, &human_readable_name));
+
+  // name is broken. Copying kNormalDisplay and substitute its name data by
+  // some control code.
+  edid.assign(kNormalDisplay, kNormalDisplay + charsize(kNormalDisplay));
+
+  // display's name data is embedded in byte 95-107 in this specific example.
+  // Fix here too when the contents of kNormalDisplay is altered.
+  edid[97] = '\x1b';
+  EXPECT_FALSE(ParseOutputDeviceData(
+      edid, &manufacturer_id, &human_readable_name));
+
+  // If |human_readable_name| isn't specified, it skips parsing the name.
+  manufacturer_id = 0;
+  EXPECT_TRUE(ParseOutputDeviceData(edid, &manufacturer_id, NULL));
+  EXPECT_EQ(0x22f0u, manufacturer_id);
+}
+
+TEST(EDIDParserTest, GetDisplayId) {
+  // EDID of kLP2565A and B are slightly different but actually the same device.
+  int64_t id1 = -1;
+  int64_t id2 = -1;
+  std::vector<uint8_t> edid(kLP2565A, kLP2565A + charsize(kLP2565A));
+  EXPECT_TRUE(GetDisplayIdFromEDID(edid, 0, &id1));
+  edid.assign(kLP2565B, kLP2565B + charsize(kLP2565B));
+  EXPECT_TRUE(GetDisplayIdFromEDID(edid, 0, &id2));
+  EXPECT_EQ(id1, id2);
+  EXPECT_NE(-1, id1);
+}
+
+TEST(EDIDParserTest, GetDisplayIdFromInternal) {
+  int64_t id = -1;
+  std::vector<uint8_t> edid(
+      kInternalDisplay, kInternalDisplay + charsize(kInternalDisplay));
+  EXPECT_TRUE(GetDisplayIdFromEDID(edid, 0, &id));
+  EXPECT_NE(-1, id);
+}
+
+TEST(EDIDParserTest, GetDisplayIdFailure) {
+  int64_t id = -1;
+  std::vector<uint8_t> edid;
+  EXPECT_FALSE(GetDisplayIdFromEDID(edid, 0, &id));
+  EXPECT_EQ(-1, id);
+}
+
+}   // namespace ui
diff --git a/ui/display/x11/edid_parser_x11.cc b/ui/display/x11/edid_parser_x11.cc
new file mode 100644
index 0000000..c53bd89
--- /dev/null
+++ b/ui/display/x11/edid_parser_x11.cc
@@ -0,0 +1,123 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/x11/edid_parser_x11.h"
+
+#include <X11/extensions/Xrandr.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_util.h"
+#include "ui/display/edid_parser.h"
+
+namespace ui {
+
+namespace {
+
+bool IsRandRAvailable() {
+  int randr_version_major = 0;
+  int randr_version_minor = 0;
+  static bool is_randr_available = XRRQueryVersion(
+      base::MessagePumpX11::GetDefaultXDisplay(),
+      &randr_version_major, &randr_version_minor);
+  return is_randr_available;
+}
+
+// Get the EDID data from the |output| and stores to |edid|.
+// Returns true if EDID property is successfully obtained. Otherwise returns
+// false and does not touch |edid|.
+bool GetEDIDProperty(XID output, std::vector<uint8_t>* edid) {
+  if (!IsRandRAvailable())
+    return false;
+
+  Display* display = base::MessagePumpX11::GetDefaultXDisplay();
+
+  static Atom edid_property = XInternAtom(
+      base::MessagePumpX11::GetDefaultXDisplay(),
+      RR_PROPERTY_RANDR_EDID, false);
+
+  bool has_edid_property = false;
+  int num_properties = 0;
+  Atom* properties = XRRListOutputProperties(display, output, &num_properties);
+  for (int i = 0; i < num_properties; ++i) {
+    if (properties[i] == edid_property) {
+      has_edid_property = true;
+      break;
+    }
+  }
+  XFree(properties);
+  if (!has_edid_property)
+    return false;
+
+  Atom actual_type;
+  int actual_format;
+  unsigned long bytes_after;
+  unsigned long nitems = 0;
+  unsigned char* prop = NULL;
+  XRRGetOutputProperty(display,
+                       output,
+                       edid_property,
+                       0,                // offset
+                       128,              // length
+                       false,            // _delete
+                       false,            // pending
+                       AnyPropertyType,  // req_type
+                       &actual_type,
+                       &actual_format,
+                       &nitems,
+                       &bytes_after,
+                       &prop);
+  DCHECK_EQ(XA_INTEGER, actual_type);
+  DCHECK_EQ(8, actual_format);
+  edid->assign(prop, prop + nitems);
+  XFree(prop);
+  return true;
+}
+
+// Gets some useful data from the specified output device, such like
+// manufacturer's ID, product code, and human readable name. Returns false if it
+// fails to get those data and doesn't touch manufacturer ID/product code/name.
+// NULL can be passed for unwanted output parameters.
+bool GetOutputDeviceData(XID output,
+                         uint16_t* manufacturer_id,
+                         std::string* human_readable_name) {
+  std::vector<uint8_t> edid;
+  if (!GetEDIDProperty(output, &edid))
+    return false;
+
+  bool result = ParseOutputDeviceData(
+      edid, manufacturer_id, human_readable_name);
+  return result;
+}
+
+}  // namespace
+
+bool GetDisplayId(XID output_id,
+                  uint8_t output_index,
+                  int64_t* display_id_out) {
+  std::vector<uint8_t> edid;
+  if (!GetEDIDProperty(output_id, &edid))
+    return false;
+
+  bool result = GetDisplayIdFromEDID(edid, output_index, display_id_out);
+  return result;
+}
+
+std::string GetDisplayName(RROutput output) {
+  std::string display_name;
+  GetOutputDeviceData(output, NULL, &display_name);
+  return display_name;
+}
+
+bool GetOutputOverscanFlag(RROutput output, bool* flag) {
+  std::vector<uint8_t> edid;
+  if (!GetEDIDProperty(output, &edid))
+    return false;
+
+  bool found = ParseOutputOverscanFlag(edid, flag);
+  return found;
+}
+
+}  // namespace ui
diff --git a/ui/display/x11/edid_parser_x11.h b/ui/display/x11/edid_parser_x11.h
new file mode 100644
index 0000000..951dd2f
--- /dev/null
+++ b/ui/display/x11/edid_parser_x11.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_DISPLAY_X11_EDID_PARSER_X11_H_
+#define UI_DISPLAY_X11_EDID_PARSER_X11_H_
+
+#include <stdint.h>
+
+#include <string>
+
+#include "ui/display/display_constants.h"
+#include "ui/display/display_export.h"
+
+typedef unsigned long XID;
+typedef XID RROutput;
+
+// Xrandr utility functions to help get EDID information.
+
+namespace ui {
+
+// Gets the EDID data from |output| and generates the display id through
+// |GetDisplayIdFromEDID|.
+DISPLAY_EXPORT bool GetDisplayId(XID output,
+                                 uint8_t index,
+                                 int64_t* display_id_out);
+
+// Generate the human readable string from EDID obtained from |output|.
+DISPLAY_EXPORT std::string GetDisplayName(RROutput output);
+
+// Gets the overscan flag from |output| and stores to |flag|. Returns true if
+// the flag is found. Otherwise returns false and doesn't touch |flag|. The
+// output will produce overscan if |flag| is set to true, but the output may
+// still produce overscan even though it returns true and |flag| is set to
+// false.
+DISPLAY_EXPORT bool GetOutputOverscanFlag(RROutput output, bool* flag);
+
+}  // namespace ui
+
+#endif  // UI_DISPLAY_X11_EDID_PARSER_X11_H_
diff --git a/ui/events/dom4_keycode_converter.target.darwin-arm.mk b/ui/events/dom4_keycode_converter.target.darwin-arm.mk
index e37fb84..6560560 100644
--- a/ui/events/dom4_keycode_converter.target.darwin-arm.mk
+++ b/ui/events/dom4_keycode_converter.target.darwin-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/dom4_keycode_converter.target.darwin-mips.mk b/ui/events/dom4_keycode_converter.target.darwin-mips.mk
index 78e7dc4..1fe3550 100644
--- a/ui/events/dom4_keycode_converter.target.darwin-mips.mk
+++ b/ui/events/dom4_keycode_converter.target.darwin-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -160,6 +161,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/dom4_keycode_converter.target.darwin-x86.mk b/ui/events/dom4_keycode_converter.target.darwin-x86.mk
index 81ac6c0..beddd93 100644
--- a/ui/events/dom4_keycode_converter.target.darwin-x86.mk
+++ b/ui/events/dom4_keycode_converter.target.darwin-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/dom4_keycode_converter.target.darwin-x86_64.mk b/ui/events/dom4_keycode_converter.target.darwin-x86_64.mk
new file mode 100644
index 0000000..ae4e5e9
--- /dev/null
+++ b/ui/events/dom4_keycode_converter.target.darwin-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_dom4_keycode_converter_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/keycodes/dom4/keycode_converter.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_dom4_keycode_converter_gyp
+
+# Alias gyp target name.
+.PHONY: dom4_keycode_converter
+dom4_keycode_converter: ui_events_dom4_keycode_converter_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/dom4_keycode_converter.target.linux-arm.mk b/ui/events/dom4_keycode_converter.target.linux-arm.mk
index e37fb84..6560560 100644
--- a/ui/events/dom4_keycode_converter.target.linux-arm.mk
+++ b/ui/events/dom4_keycode_converter.target.linux-arm.mk
@@ -78,6 +78,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -162,6 +163,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/dom4_keycode_converter.target.linux-mips.mk b/ui/events/dom4_keycode_converter.target.linux-mips.mk
index 78e7dc4..1fe3550 100644
--- a/ui/events/dom4_keycode_converter.target.linux-mips.mk
+++ b/ui/events/dom4_keycode_converter.target.linux-mips.mk
@@ -77,6 +77,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -160,6 +161,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/dom4_keycode_converter.target.linux-x86.mk b/ui/events/dom4_keycode_converter.target.linux-x86.mk
index 81ac6c0..beddd93 100644
--- a/ui/events/dom4_keycode_converter.target.linux-x86.mk
+++ b/ui/events/dom4_keycode_converter.target.linux-x86.mk
@@ -79,6 +79,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -163,6 +164,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/dom4_keycode_converter.target.linux-x86_64.mk b/ui/events/dom4_keycode_converter.target.linux-x86_64.mk
new file mode 100644
index 0000000..ae4e5e9
--- /dev/null
+++ b/ui/events/dom4_keycode_converter.target.linux-x86_64.mk
@@ -0,0 +1,259 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_dom4_keycode_converter_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/keycodes/dom4/keycode_converter.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_dom4_keycode_converter_gyp
+
+# Alias gyp target name.
+.PHONY: dom4_keycode_converter
+dom4_keycode_converter: ui_events_dom4_keycode_converter_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/event.h b/ui/events/event.h
index c7182fb..51d73f8 100644
--- a/ui/events/event.h
+++ b/ui/events/event.h
@@ -11,6 +11,7 @@
 #include "base/logging.h"
 #include "base/time/time.h"
 #include "ui/events/event_constants.h"
+#include "ui/events/gesture_event_details.h"
 #include "ui/events/gestures/gesture_types.h"
 #include "ui/events/keycodes/keyboard_codes.h"
 #include "ui/events/latency_info.h"
diff --git a/ui/events/event_processor.cc b/ui/events/event_processor.cc
index 1a50d2b..3077cc8 100644
--- a/ui/events/event_processor.cc
+++ b/ui/events/event_processor.cc
@@ -14,12 +14,22 @@
   CHECK(root);
   EventTargeter* targeter = root->GetEventTargeter();
   CHECK(targeter);
+
   PrepareEventForDispatch(event);
   EventTarget* target = targeter->FindTargetForEvent(root, event);
-  if (!target)
-    return EventDispatchDetails();
 
-  return DispatchEvent(target, event);
+  while (target) {
+    EventDispatchDetails details = DispatchEvent(target, event);
+    if (details.dispatcher_destroyed ||
+        details.target_destroyed ||
+        event->handled()) {
+      return details;
+    }
+
+    target = targeter->FindNextBestTarget(target, event);
+  }
+
+  return EventDispatchDetails();
 }
 
 void EventProcessor::PrepareEventForDispatch(Event* event) {
diff --git a/ui/events/event_processor_unittest.cc b/ui/events/event_processor_unittest.cc
index 1511819..048a4cd 100644
--- a/ui/events/event_processor_unittest.cc
+++ b/ui/events/event_processor_unittest.cc
@@ -2,12 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <vector>
+
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event.h"
 #include "ui/events/event_targeter.h"
+#include "ui/events/test/events_test_utils.h"
+#include "ui/events/test/test_event_handler.h"
 #include "ui/events/test/test_event_processor.h"
 #include "ui/events/test/test_event_target.h"
 
+typedef std::vector<std::string> HandlerSequenceRecorder;
+
 namespace ui {
 namespace test {
 
@@ -188,7 +194,7 @@
   EXPECT_FALSE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
   root()->child_at(0)->ResetReceivedEvents();
 
-  // Install an even handler on |child| which always prevents the target from
+  // Install an event handler on |child| which always prevents the target from
   // receiving event.
   root()->child_at(0)->SetEventTargeter(
       scoped_ptr<EventTargeter>(new IgnoreEventTargeter()));
@@ -199,5 +205,170 @@
   EXPECT_TRUE(root()->DidReceiveEvent(ET_MOUSE_MOVED));
 }
 
+// An EventTargeter which is used to allow a bubbling behaviour in event
+// dispatch: if an event is not handled after being dispatched to its
+// initial target, the event is dispatched to the next-best target as
+// specified by FindNextBestTarget().
+class BubblingEventTargeter : public EventTargeter {
+ public:
+  explicit BubblingEventTargeter(TestEventTarget* initial_target)
+    : initial_target_(initial_target) {}
+  virtual ~BubblingEventTargeter() {}
+
+ private:
+  // EventTargeter:
+  virtual EventTarget* FindTargetForEvent(EventTarget* root,
+                                          Event* event) OVERRIDE {
+    return initial_target_;
+  }
+
+  virtual EventTarget* FindNextBestTarget(EventTarget* previous_target,
+                                          Event* event) OVERRIDE {
+    return previous_target->GetParentTarget();
+  }
+
+  TestEventTarget* initial_target_;
+
+  DISALLOW_COPY_AND_ASSIGN(BubblingEventTargeter);
+};
+
+// Tests that unhandled events are correctly dispatched to the next-best
+// target as decided by the BubblingEventTargeter.
+TEST_F(EventProcessorTest, DispatchToNextBestTarget) {
+  scoped_ptr<TestEventTarget> child(new TestEventTarget());
+  scoped_ptr<TestEventTarget> grandchild(new TestEventTarget());
+
+  root()->SetEventTargeter(
+      scoped_ptr<EventTargeter>(new BubblingEventTargeter(grandchild.get())));
+  child->AddChild(grandchild.Pass());
+  root()->AddChild(child.Pass());
+
+  ASSERT_EQ(1u, root()->child_count());
+  ASSERT_EQ(1u, root()->child_at(0)->child_count());
+  ASSERT_EQ(0u, root()->child_at(0)->child_at(0)->child_count());
+
+  TestEventTarget* child_r = root()->child_at(0);
+  TestEventTarget* grandchild_r = child_r->child_at(0);
+
+  // When the root has a BubblingEventTargeter installed, events targeted
+  // at the grandchild target should be dispatched to all three targets.
+  KeyEvent key_event(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false);
+  DispatchEvent(&key_event);
+  EXPECT_TRUE(root()->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_TRUE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
+  root()->ResetReceivedEvents();
+  child_r->ResetReceivedEvents();
+  grandchild_r->ResetReceivedEvents();
+
+  // Add a pre-target handler on the child of the root that will mark the event
+  // as handled. No targets in the hierarchy should receive the event.
+  TestEventHandler handler;
+  child_r->AddPreTargetHandler(&handler);
+  key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false);
+  DispatchEvent(&key_event);
+  EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_FALSE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_FALSE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_EQ(1, handler.num_key_events());
+  handler.Reset();
+
+  // Add a post-target handler on the child of the root that will mark the event
+  // as handled. Only the grandchild (the initial target) should receive the
+  // event.
+  child_r->RemovePreTargetHandler(&handler);
+  child_r->AddPostTargetHandler(&handler);
+  key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false);
+  DispatchEvent(&key_event);
+  EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_FALSE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_EQ(1, handler.num_key_events());
+  handler.Reset();
+  grandchild_r->ResetReceivedEvents();
+  child_r->RemovePostTargetHandler(&handler);
+
+  // Mark the event as handled when it reaches the EP_TARGET phase of
+  // dispatch at the child of the root. The child and grandchild
+  // targets should both receive the event, but the root should not.
+  child_r->set_mark_events_as_handled(true);
+  key_event = KeyEvent(ET_KEY_PRESSED, VKEY_ESCAPE, 0, false);
+  DispatchEvent(&key_event);
+  EXPECT_FALSE(root()->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_TRUE(child_r->DidReceiveEvent(ET_KEY_PRESSED));
+  EXPECT_TRUE(grandchild_r->DidReceiveEvent(ET_KEY_PRESSED));
+  root()->ResetReceivedEvents();
+  child_r->ResetReceivedEvents();
+  grandchild_r->ResetReceivedEvents();
+  child_r->set_mark_events_as_handled(false);
+}
+
+// Tests that unhandled events are seen by the correct sequence of
+// targets, pre-target handlers, and post-target handlers when
+// a BubblingEventTargeter is installed on the root target.
+TEST_F(EventProcessorTest, HandlerSequence) {
+  scoped_ptr<TestEventTarget> child(new TestEventTarget());
+  scoped_ptr<TestEventTarget> grandchild(new TestEventTarget());
+
+  root()->SetEventTargeter(
+      scoped_ptr<EventTargeter>(new BubblingEventTargeter(grandchild.get())));
+  child->AddChild(grandchild.Pass());
+  root()->AddChild(child.Pass());
+
+  ASSERT_EQ(1u, root()->child_count());
+  ASSERT_EQ(1u, root()->child_at(0)->child_count());
+  ASSERT_EQ(0u, root()->child_at(0)->child_at(0)->child_count());
+
+  TestEventTarget* child_r = root()->child_at(0);
+  TestEventTarget* grandchild_r = child_r->child_at(0);
+
+  HandlerSequenceRecorder recorder;
+  root()->set_target_name("R");
+  root()->set_recorder(&recorder);
+  child_r->set_target_name("C");
+  child_r->set_recorder(&recorder);
+  grandchild_r->set_target_name("G");
+  grandchild_r->set_recorder(&recorder);
+
+  TestEventHandler pre_root;
+  pre_root.set_handler_name("PreR");
+  pre_root.set_recorder(&recorder);
+  root()->AddPreTargetHandler(&pre_root);
+
+  TestEventHandler pre_child;
+  pre_child.set_handler_name("PreC");
+  pre_child.set_recorder(&recorder);
+  child_r->AddPreTargetHandler(&pre_child);
+
+  TestEventHandler pre_grandchild;
+  pre_grandchild.set_handler_name("PreG");
+  pre_grandchild.set_recorder(&recorder);
+  grandchild_r->AddPreTargetHandler(&pre_grandchild);
+
+  TestEventHandler post_root;
+  post_root.set_handler_name("PostR");
+  post_root.set_recorder(&recorder);
+  root()->AddPostTargetHandler(&post_root);
+
+  TestEventHandler post_child;
+  post_child.set_handler_name("PostC");
+  post_child.set_recorder(&recorder);
+  child_r->AddPostTargetHandler(&post_child);
+
+  TestEventHandler post_grandchild;
+  post_grandchild.set_handler_name("PostG");
+  post_grandchild.set_recorder(&recorder);
+  grandchild_r->AddPostTargetHandler(&post_grandchild);
+
+  MouseEvent mouse(ET_MOUSE_MOVED, gfx::Point(10, 10), gfx::Point(10, 10),
+                   EF_NONE, EF_NONE);
+  DispatchEvent(&mouse);
+
+  std::string expected[] = { "PreR", "PreC", "PreG", "G", "PostG", "PostC",
+      "PostR", "PreR", "PreC", "C", "PostC", "PostR", "PreR", "R", "PostR" };
+  EXPECT_EQ(std::vector<std::string>(
+      expected, expected + arraysize(expected)), recorder);
+}
+
 }  // namespace test
 }  // namespace ui
diff --git a/ui/events/event_rewriter.h b/ui/events/event_rewriter.h
new file mode 100644
index 0000000..f948725
--- /dev/null
+++ b/ui/events/event_rewriter.h
@@ -0,0 +1,68 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_EVENT_REWRITER_H_
+#define UI_EVENTS_EVENT_REWRITER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/events/events_export.h"
+
+namespace ui {
+
+class Event;
+
+// Return status of EventRewriter operations; see that class below.
+enum EventRewriteStatus {
+  // Nothing was done; no rewritten event returned. Pass the original
+  // event to later rewriters, or send it to the EventProcessor if this
+  // was the final rewriter.
+  EVENT_REWRITE_CONTINUE,
+
+  // The event has been rewritten. Send the rewritten event to the
+  // EventProcessor instead of the original event (without sending
+  // either to any later rewriters).
+  EVENT_REWRITE_REWRITTEN,
+
+  // The event should be discarded, neither passing it to any later
+  // rewriters nor sending it to the EventProcessor.
+  EVENT_REWRITE_DISCARD,
+
+  // The event has been rewritten. As for EVENT_REWRITE_REWRITTEN,
+  // send the rewritten event to the EventProcessor instead of the
+  // original event (without sending either to any later rewriters).
+  // In addition the rewriter has one or more additional new events
+  // to be retrieved using |NextDispatchEvent()| and sent to the
+  // EventProcessor.
+  EVENT_REWRITE_DISPATCH_ANOTHER,
+};
+
+// EventRewriter provides a mechanism for Events to be rewritten
+// before being dispatched from EventSource to EventProcessor.
+class EVENTS_EXPORT EventRewriter {
+ public:
+  virtual ~EventRewriter() {}
+
+  // Potentially rewrites (replaces) an event, or requests it be discarded.
+  // or discards an event. If the rewriter wants to rewrite an event, and
+  // dispatch another event once the rewritten event is dispatched, it should
+  // return EVENT_REWRITE_DISPATCH_ANOTHER, and return the next event to
+  // dispatch from |NextDispatchEvent()|.
+  virtual EventRewriteStatus RewriteEvent(
+      const Event& event,
+      scoped_ptr<Event>* rewritten_event) = 0;
+
+  // Supplies an additional event to be dispatched. It is only valid to
+  // call this after the immediately previous call to |RewriteEvent()|
+  // or |NextDispatchEvent()| has returned EVENT_REWRITE_DISPATCH_ANOTHER.
+  // Should only return either EVENT_REWRITE_REWRITTEN or
+  // EVENT_REWRITE_DISPATCH_ANOTHER; otherwise the previous call should not
+  // have returned EVENT_REWRITE_DISPATCH_ANOTHER.
+  virtual EventRewriteStatus NextDispatchEvent(
+      const Event& last_event,
+      scoped_ptr<Event>* new_event) = 0;
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_EVENT_REWRITER_H_
diff --git a/ui/events/event_rewriter_unittest.cc b/ui/events/event_rewriter_unittest.cc
new file mode 100644
index 0000000..11a05c9
--- /dev/null
+++ b/ui/events/event_rewriter_unittest.cc
@@ -0,0 +1,231 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/event_rewriter.h"
+
+#include <list>
+#include <map>
+#include <set>
+#include <utility>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/test/test_event_processor.h"
+
+namespace ui {
+
+namespace {
+
+// To test the handling of |EventRewriter|s through |EventSource|,
+// we rewrite and test event types.
+class TestEvent : public Event {
+ public:
+  explicit TestEvent(EventType type)
+      : Event(type, base::TimeDelta(), 0), unique_id_(next_unique_id_++) {}
+  virtual ~TestEvent() {}
+  int unique_id() const { return unique_id_; }
+
+ private:
+  static int next_unique_id_;
+  int unique_id_;
+};
+
+int TestEvent::next_unique_id_ = 0;
+
+// TestEventRewriteProcessor is set up with a sequence of event types,
+// and fails if the events received via OnEventFromSource() do not match
+// this sequence. These expected event types are consumed on receipt.
+class TestEventRewriteProcessor : public test::TestEventProcessor {
+ public:
+  TestEventRewriteProcessor() {}
+  virtual ~TestEventRewriteProcessor() { CheckAllReceived(); }
+
+  void AddExpectedEvent(EventType type) { expected_events_.push_back(type); }
+  // Test that all expected events have been received.
+  void CheckAllReceived() { EXPECT_TRUE(expected_events_.empty()); }
+
+  // EventProcessor:
+  virtual EventDispatchDetails OnEventFromSource(Event* event) OVERRIDE {
+    EXPECT_FALSE(expected_events_.empty());
+    EXPECT_EQ(expected_events_.front(), event->type());
+    expected_events_.pop_front();
+    return EventDispatchDetails();
+  }
+
+ private:
+  std::list<EventType> expected_events_;
+  DISALLOW_COPY_AND_ASSIGN(TestEventRewriteProcessor);
+};
+
+// Trivial EventSource that does nothing but send events.
+class TestEventRewriteSource : public EventSource {
+ public:
+  explicit TestEventRewriteSource(EventProcessor* processor)
+      : processor_(processor) {}
+  virtual EventProcessor* GetEventProcessor() OVERRIDE { return processor_; }
+  void Send(EventType type) {
+    scoped_ptr<Event> event(new TestEvent(type));
+    (void)SendEventToProcessor(event.get());
+  }
+
+ private:
+  EventProcessor* processor_;
+};
+
+// This EventRewriter always returns the same status, and if rewriting, the
+// same event type; it is used to test simple rewriting, and rewriter addition,
+// removal, and sequencing. Consequently EVENT_REWRITE_DISPATCH_ANOTHER is not
+// supported here (calls to NextDispatchEvent() would continue indefinitely).
+class TestConstantEventRewriter : public EventRewriter {
+ public:
+  TestConstantEventRewriter(EventRewriteStatus status, EventType type)
+      : status_(status), type_(type) {
+    CHECK_NE(EVENT_REWRITE_DISPATCH_ANOTHER, status);
+  }
+
+  virtual EventRewriteStatus RewriteEvent(const Event& event,
+                                          scoped_ptr<Event>* rewritten_event)
+      OVERRIDE {
+    if (status_ == EVENT_REWRITE_REWRITTEN)
+      rewritten_event->reset(new TestEvent(type_));
+    return status_;
+  }
+  virtual EventRewriteStatus NextDispatchEvent(const Event& last_event,
+                                               scoped_ptr<Event>* new_event)
+      OVERRIDE {
+    NOTREACHED();
+    return status_;
+  }
+
+ private:
+  EventRewriteStatus status_;
+  EventType type_;
+};
+
+// This EventRewriter runs a simple state machine; it is used to test
+// EVENT_REWRITE_DISPATCH_ANOTHER.
+class TestStateMachineEventRewriter : public EventRewriter {
+ public:
+  TestStateMachineEventRewriter() : last_rewritten_event_(0), state_(0) {}
+  void AddRule(int from_state, EventType from_type,
+               int to_state, EventType to_type, EventRewriteStatus to_status) {
+    RewriteResult r = {to_state, to_type, to_status};
+    rules_.insert(std::pair<RewriteCase, RewriteResult>(
+        RewriteCase(from_state, from_type), r));
+  }
+  virtual EventRewriteStatus RewriteEvent(const Event& event,
+                                          scoped_ptr<Event>* rewritten_event)
+      OVERRIDE {
+    RewriteRules::iterator find =
+        rules_.find(RewriteCase(state_, event.type()));
+    if (find == rules_.end())
+      return EVENT_REWRITE_CONTINUE;
+    if ((find->second.status == EVENT_REWRITE_REWRITTEN) ||
+        (find->second.status == EVENT_REWRITE_DISPATCH_ANOTHER)) {
+      last_rewritten_event_ = new TestEvent(find->second.type);
+      rewritten_event->reset(last_rewritten_event_);
+    } else {
+      last_rewritten_event_ = 0;
+    }
+    state_ = find->second.state;
+    return find->second.status;
+  }
+  virtual EventRewriteStatus NextDispatchEvent(const Event& last_event,
+                                               scoped_ptr<Event>* new_event)
+      OVERRIDE {
+    EXPECT_TRUE(last_rewritten_event_);
+    const TestEvent* arg_last = static_cast<const TestEvent*>(&last_event);
+    EXPECT_EQ(last_rewritten_event_->unique_id(), arg_last->unique_id());
+    const TestEvent* arg_new = static_cast<const TestEvent*>(new_event->get());
+    EXPECT_FALSE(arg_new && arg_last->unique_id() == arg_new->unique_id());
+    return RewriteEvent(last_event, new_event);
+  }
+
+ private:
+  typedef std::pair<int, EventType> RewriteCase;
+  struct RewriteResult {
+    int state;
+    EventType type;
+    EventRewriteStatus status;
+  };
+  typedef std::map<RewriteCase, RewriteResult> RewriteRules;
+  RewriteRules rules_;
+  TestEvent* last_rewritten_event_;
+  int state_;
+};
+
+}  // namespace
+
+TEST(EventRewriterTest, EventRewriting) {
+  // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE;
+  // it is placed at the beginning of the chain and later removed,
+  // to verify that rewriter removal works.
+  TestConstantEventRewriter r0(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
+
+  // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE;
+  // it is placed at the beginning of the chain to verify that a
+  // later rewriter sees the events.
+  TestConstantEventRewriter r1(EVENT_REWRITE_CONTINUE, ET_UNKNOWN);
+
+  // TestEventRewriter r2 has a state machine, primarily to test
+  // |EVENT_REWRITE_DISPATCH_ANOTHER|.
+  TestStateMachineEventRewriter r2;
+
+  // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE;
+  // it is placed at the end of the chain to verify that previously
+  // rewritten events are not passed further down the chain.
+  TestConstantEventRewriter r3(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
+
+  TestEventRewriteProcessor p;
+  TestEventRewriteSource s(&p);
+  s.AddEventRewriter(&r0);
+  s.AddEventRewriter(&r1);
+  s.AddEventRewriter(&r2);
+
+  // These events should be rewritten by r0 to ET_CANCEL_MODE.
+  p.AddExpectedEvent(ET_CANCEL_MODE);
+  s.Send(ET_MOUSE_DRAGGED);
+  p.AddExpectedEvent(ET_CANCEL_MODE);
+  s.Send(ET_MOUSE_PRESSED);
+  p.CheckAllReceived();
+
+  // Remove r0, and verify that it's gone and that events make it through.
+  s.AddEventRewriter(&r3);
+  s.RemoveEventRewriter(&r0);
+  r2.AddRule(0, ET_SCROLL_FLING_START,
+             0, ET_SCROLL_FLING_CANCEL, EVENT_REWRITE_REWRITTEN);
+  p.AddExpectedEvent(ET_SCROLL_FLING_CANCEL);
+  s.Send(ET_SCROLL_FLING_START);
+  p.CheckAllReceived();
+  s.RemoveEventRewriter(&r3);
+
+  // Verify EVENT_REWRITE_DISPATCH_ANOTHER using a state machine
+  // (that happens to be analogous to sticky keys).
+  r2.AddRule(0, ET_KEY_PRESSED,
+             1, ET_KEY_PRESSED, EVENT_REWRITE_CONTINUE);
+  r2.AddRule(1, ET_MOUSE_PRESSED,
+             0, ET_MOUSE_PRESSED, EVENT_REWRITE_CONTINUE);
+  r2.AddRule(1, ET_KEY_RELEASED,
+             2, ET_KEY_RELEASED, EVENT_REWRITE_DISCARD);
+  r2.AddRule(2, ET_MOUSE_RELEASED,
+             3, ET_MOUSE_RELEASED, EVENT_REWRITE_DISPATCH_ANOTHER);
+  r2.AddRule(3, ET_MOUSE_RELEASED,
+             0, ET_KEY_RELEASED, EVENT_REWRITE_REWRITTEN);
+  p.AddExpectedEvent(ET_KEY_PRESSED);
+  s.Send(ET_KEY_PRESSED);
+  s.Send(ET_KEY_RELEASED);
+  p.AddExpectedEvent(ET_MOUSE_PRESSED);
+  s.Send(ET_MOUSE_PRESSED);
+
+  // Removing rewriters r1 and r3 shouldn't affect r2.
+  s.RemoveEventRewriter(&r1);
+  s.RemoveEventRewriter(&r3);
+
+  // Continue with the state-based rewriting.
+  p.AddExpectedEvent(ET_MOUSE_RELEASED);
+  p.AddExpectedEvent(ET_KEY_RELEASED);
+  s.Send(ET_MOUSE_RELEASED);
+  p.CheckAllReceived();
+}
+
+}  // namespace ui
diff --git a/ui/events/event_source.cc b/ui/events/event_source.cc
index a408130..0f3dfb8 100644
--- a/ui/events/event_source.cc
+++ b/ui/events/event_source.cc
@@ -4,11 +4,70 @@
 
 #include "ui/events/event_source.h"
 
+#include <algorithm>
+
 #include "ui/events/event_processor.h"
+#include "ui/events/event_rewriter.h"
 
 namespace ui {
 
+EventSource::EventSource() {}
+
+EventSource::~EventSource() {}
+
+void EventSource::AddEventRewriter(EventRewriter* rewriter) {
+  DCHECK(rewriter);
+  DCHECK(rewriter_list_.end() ==
+         std::find(rewriter_list_.begin(), rewriter_list_.end(), rewriter));
+  rewriter_list_.push_back(rewriter);
+}
+
+void EventSource::RemoveEventRewriter(EventRewriter* rewriter) {
+  EventRewriterList::iterator find =
+      std::find(rewriter_list_.begin(), rewriter_list_.end(), rewriter);
+  if (find != rewriter_list_.end())
+    rewriter_list_.erase(find);
+}
+
 EventDispatchDetails EventSource::SendEventToProcessor(Event* event) {
+  scoped_ptr<Event> rewritten_event;
+  EventRewriteStatus status = EVENT_REWRITE_CONTINUE;
+  EventRewriterList::const_iterator it = rewriter_list_.begin(),
+                                    end = rewriter_list_.end();
+  for (; it != end; ++it) {
+    status = (*it)->RewriteEvent(*event, &rewritten_event);
+    if (status == EVENT_REWRITE_DISCARD) {
+      CHECK(!rewritten_event);
+      return EventDispatchDetails();
+    }
+    if (status == EVENT_REWRITE_CONTINUE) {
+      CHECK(!rewritten_event);
+      continue;
+    }
+    break;
+  }
+  CHECK((it == end && !rewritten_event) || rewritten_event);
+  EventDispatchDetails details =
+      DeliverEventToProcessor(rewritten_event ? rewritten_event.get() : event);
+  if (details.dispatcher_destroyed)
+    return details;
+
+  while (status == EVENT_REWRITE_DISPATCH_ANOTHER) {
+    scoped_ptr<Event> new_event;
+    status = (*it)->NextDispatchEvent(*rewritten_event, &new_event);
+    if (status == EVENT_REWRITE_DISCARD)
+      return EventDispatchDetails();
+    CHECK_NE(EVENT_REWRITE_CONTINUE, status);
+    CHECK(new_event);
+    details = DeliverEventToProcessor(new_event.get());
+    if (details.dispatcher_destroyed)
+      return details;
+    rewritten_event.reset(new_event.release());
+  }
+  return EventDispatchDetails();
+}
+
+EventDispatchDetails EventSource::DeliverEventToProcessor(Event* event) {
   EventProcessor* processor = GetEventProcessor();
   CHECK(processor);
   return processor->OnEventFromSource(event);
diff --git a/ui/events/event_source.h b/ui/events/event_source.h
index aba2c1f..de22bda 100644
--- a/ui/events/event_source.h
+++ b/ui/events/event_source.h
@@ -5,6 +5,8 @@
 #ifndef UI_EVENTS_EVENT_SOURCE_H_
 #define UI_EVENTS_EVENT_SOURCE_H_
 
+#include <vector>
+
 #include "ui/events/event_dispatcher.h"
 #include "ui/events/events_export.h"
 
@@ -12,17 +14,32 @@
 
 class Event;
 class EventProcessor;
+class EventRewriter;
 
 // EventSource receives events from the native platform (e.g. X11, win32 etc.)
 // and sends the events to an EventProcessor.
 class EVENTS_EXPORT EventSource {
  public:
-  virtual ~EventSource() {}
+  EventSource();
+  virtual ~EventSource();
 
   virtual EventProcessor* GetEventProcessor() = 0;
 
+  // Adds a rewriter to modify events before they are sent to the
+  // EventProcessor. The rewriter must be explicitly removed from the
+  // EventSource before the rewriter is destroyed. The EventSource
+  // does not take ownership of the rewriter.
+  void AddEventRewriter(EventRewriter* rewriter);
+  void RemoveEventRewriter(EventRewriter* rewriter);
+
  protected:
   EventDispatchDetails SendEventToProcessor(Event* event);
+
+ private:
+  typedef std::vector<EventRewriter*> EventRewriterList;
+  EventDispatchDetails DeliverEventToProcessor(Event* event);
+  EventRewriterList rewriter_list_;
+  DISALLOW_COPY_AND_ASSIGN(EventSource);
 };
 
 }  // namespace ui
diff --git a/ui/events/event_switches.cc b/ui/events/event_switches.cc
index 195e2bb..314370a 100644
--- a/ui/events/event_switches.cc
+++ b/ui/events/event_switches.cc
@@ -27,4 +27,9 @@
 const char kTouchDevices[] = "touch-devices";
 #endif
 
+#if defined(USE_XI2_MT)
+// The calibration factors given as "<left>,<right>,<top>,<bottom>".
+const char kTouchCalibration[] = "touch-calibration";
+#endif
+
 }  // namespace switches
diff --git a/ui/events/event_switches.h b/ui/events/event_switches.h
index d434304..caaa779 100644
--- a/ui/events/event_switches.h
+++ b/ui/events/event_switches.h
@@ -20,6 +20,10 @@
 EVENTS_BASE_EXPORT extern const char kTouchDevices[];
 #endif
 
+#if defined(USE_XI2_MT)
+EVENTS_BASE_EXPORT extern const char kTouchCalibration[];
+#endif
+
 }  // namespace switches
 
 #endif  // UI_EVENTS_EVENTS_SWITCHES_H_
diff --git a/ui/events/event_targeter.cc b/ui/events/event_targeter.cc
index 50fe7e9..85b4c3f 100644
--- a/ui/events/event_targeter.cc
+++ b/ui/events/event_targeter.cc
@@ -55,4 +55,9 @@
   return true;
 }
 
+EventTarget* EventTargeter::FindNextBestTarget(EventTarget* previous_target,
+                                               Event* event) {
+  return NULL;
+}
+
 }  // namespace ui
diff --git a/ui/events/event_targeter.h b/ui/events/event_targeter.h
index b93cc55..44ea2a0 100644
--- a/ui/events/event_targeter.h
+++ b/ui/events/event_targeter.h
@@ -26,8 +26,8 @@
 
   // Same as FindTargetForEvent(), but used for positional events. The location
   // etc. of |event| are in |root|'s coordinate system. When finding the target
-  // for the event, the targeter can mutate the |event| (e.g. chnage the
-  // coordinate to be in the returned target's coordinate sustem) so that it can
+  // for the event, the targeter can mutate the |event| (e.g. change the
+  // coordinate to be in the returned target's coordinate system) so that it can
   // be dispatched to the target without any farther modification.
   virtual EventTarget* FindTargetForLocatedEvent(EventTarget* root,
                                                  LocatedEvent* event);
@@ -37,6 +37,13 @@
   // coordinate system.
   virtual bool SubtreeShouldBeExploredForEvent(EventTarget* target,
                                                const LocatedEvent& event);
+
+  // Returns the next best target for |event| as compared to |previous_target|.
+  // Also mutates |event| so that it can be dispatched to the returned target
+  // (e.g., by changing |event|'s location to be in the returned target's
+  // coordinate space).
+  virtual EventTarget* FindNextBestTarget(EventTarget* previous_target,
+                                          Event* event);
 };
 
 }  // namespace ui
diff --git a/ui/events/events.gyp b/ui/events/events.gyp
index 30d2a41..bb8107f 100644
--- a/ui/events/events.gyp
+++ b/ui/events/events.gyp
@@ -25,16 +25,20 @@
       'dependencies': [
         '<(DEPTH)/base/base.gyp:base',
         '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+        '../gfx/gfx.gyp:gfx',
+        '../gfx/gfx.gyp:gfx_geometry',
         'dom4_keycode_converter',
       ],
       'defines': [
         'EVENTS_BASE_IMPLEMENTATION',
       ],
       'sources': [
-        'events_base_export.h',
         'event_constants.h',
         'event_switches.cc',
         'event_switches.h',
+        'events_base_export.h',
+        'gesture_event_details.cc',
+        'gesture_event_details.h',
         'keycodes/keyboard_code_conversion.cc',
         'keycodes/keyboard_code_conversion.h',
         'keycodes/keyboard_code_conversion_android.cc',
@@ -90,6 +94,7 @@
         'event_handler.h',
         'event_processor.cc',
         'event_processor.h',
+        'event_rewriter.h',
         'event_source.cc',
         'event_source.h',
         'event_target.cc',
@@ -110,7 +115,6 @@
         'gestures/gesture_recognizer_impl.h',
         'gestures/gesture_sequence.cc',
         'gestures/gesture_sequence.h',
-        'gestures/gesture_types.cc',
         'gestures/gesture_types.h',
         'gestures/velocity_calculator.cc',
         'gestures/velocity_calculator.h',
@@ -133,6 +137,15 @@
         'ozone/event_factory_ozone.cc',
         'ozone/event_factory_ozone.h',
         'ozone/events_ozone.cc',
+        'platform/platform_event_dispatcher.h',
+        'platform/platform_event_observer.h',
+        'platform/platform_event_source.cc',
+        'platform/platform_event_source.h',
+        'platform/platform_event_types.h',
+        'platform/scoped_event_dispatcher.cc',
+        'platform/scoped_event_dispatcher.h',
+        'platform/x11/x11_event_source.cc',
+        'platform/x11/x11_event_source.h',
         'win/events_win.cc',
         'x/events_x.cc',
       ],
@@ -149,6 +162,11 @@
             '<(DEPTH)/build/linux/system.gyp:x11',
           ],
         }],
+        ['use_glib==1', {
+          'dependencies': [
+            '../../build/linux/system.gyp:glib',
+          ],
+        }],
         ['use_ozone_evdev==1', {
           'defines': ['USE_OZONE_EVDEV=1'],
         }],
@@ -272,6 +290,7 @@
         'cocoa/cocoa_event_utils_unittest.mm',
         'event_dispatcher_unittest.cc',
         'event_processor_unittest.cc',
+        'event_rewriter_unittest.cc',
         'event_unittest.cc',
         'gestures/velocity_calculator_unittest.cc',
         'gesture_detection/bitset_32_unittest.cc',
@@ -284,6 +303,7 @@
         'latency_info_unittest.cc',
         'ozone/evdev/key_event_converter_evdev_unittest.cc',
         'ozone/evdev/touch_event_converter_evdev_unittest.cc',
+        'platform/platform_event_source_unittest.cc',
         'x/events_x_unittest.cc',
       ],
       'conditions': [
diff --git a/ui/events/events.target.darwin-arm.mk b/ui/events/events.target.darwin-arm.mk
index d6c03aa..b2aa2f1 100644
--- a/ui/events/events.target.darwin-arm.mk
+++ b/ui/events/events.target.darwin-arm.mk
@@ -38,8 +38,9 @@
 	ui/events/gestures/gesture_point.cc \
 	ui/events/gestures/gesture_recognizer_impl.cc \
 	ui/events/gestures/gesture_sequence.cc \
-	ui/events/gestures/gesture_types.cc \
-	ui/events/gestures/velocity_calculator.cc
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
 
 
 # Flags passed to both C and C++ files.
@@ -102,9 +103,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -113,6 +112,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +230,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/events.target.darwin-mips.mk b/ui/events/events.target.darwin-mips.mk
index 538b95a..af24a6c 100644
--- a/ui/events/events.target.darwin-mips.mk
+++ b/ui/events/events.target.darwin-mips.mk
@@ -38,8 +38,9 @@
 	ui/events/gestures/gesture_point.cc \
 	ui/events/gestures/gesture_recognizer_impl.cc \
 	ui/events/gestures/gesture_sequence.cc \
-	ui/events/gestures/gesture_types.cc \
-	ui/events/gestures/velocity_calculator.cc
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
 
 
 # Flags passed to both C and C++ files.
@@ -101,9 +102,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -112,6 +111,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +228,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/events.target.darwin-x86.mk b/ui/events/events.target.darwin-x86.mk
index b7d5816..7d4a445 100644
--- a/ui/events/events.target.darwin-x86.mk
+++ b/ui/events/events.target.darwin-x86.mk
@@ -38,8 +38,9 @@
 	ui/events/gestures/gesture_point.cc \
 	ui/events/gestures/gesture_recognizer_impl.cc \
 	ui/events/gestures/gesture_sequence.cc \
-	ui/events/gestures/gesture_types.cc \
-	ui/events/gestures/velocity_calculator.cc
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
 
 
 # Flags passed to both C and C++ files.
@@ -103,9 +104,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -114,6 +113,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +222,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +231,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/events.target.darwin-x86_64.mk b/ui/events/events.target.darwin-x86_64.mk
new file mode 100644
index 0000000..edc8312
--- /dev/null
+++ b/ui/events/events.target.darwin-x86_64.mk
@@ -0,0 +1,343 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_events_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/event.cc \
+	ui/events/event_dispatcher.cc \
+	ui/events/event_handler.cc \
+	ui/events/event_processor.cc \
+	ui/events/event_source.cc \
+	ui/events/event_target.cc \
+	ui/events/event_targeter.cc \
+	ui/events/event_utils.cc \
+	ui/events/events_stub.cc \
+	ui/events/gestures/gesture_configuration.cc \
+	ui/events/gestures/gesture_point.cc \
+	ui/events/gestures/gesture_recognizer_impl.cc \
+	ui/events/gestures/gesture_sequence.cc \
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_events_gyp
+
+# Alias gyp target name.
+.PHONY: events
+events: ui_events_events_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/events.target.linux-arm.mk b/ui/events/events.target.linux-arm.mk
index d6c03aa..b2aa2f1 100644
--- a/ui/events/events.target.linux-arm.mk
+++ b/ui/events/events.target.linux-arm.mk
@@ -38,8 +38,9 @@
 	ui/events/gestures/gesture_point.cc \
 	ui/events/gestures/gesture_recognizer_impl.cc \
 	ui/events/gestures/gesture_sequence.cc \
-	ui/events/gestures/gesture_types.cc \
-	ui/events/gestures/velocity_calculator.cc
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
 
 
 # Flags passed to both C and C++ files.
@@ -102,9 +103,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -113,6 +112,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +230,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/events.target.linux-mips.mk b/ui/events/events.target.linux-mips.mk
index 538b95a..af24a6c 100644
--- a/ui/events/events.target.linux-mips.mk
+++ b/ui/events/events.target.linux-mips.mk
@@ -38,8 +38,9 @@
 	ui/events/gestures/gesture_point.cc \
 	ui/events/gestures/gesture_recognizer_impl.cc \
 	ui/events/gestures/gesture_sequence.cc \
-	ui/events/gestures/gesture_types.cc \
-	ui/events/gestures/velocity_calculator.cc
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
 
 
 # Flags passed to both C and C++ files.
@@ -101,9 +102,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -112,6 +111,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -230,6 +228,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/events.target.linux-x86.mk b/ui/events/events.target.linux-x86.mk
index b7d5816..7d4a445 100644
--- a/ui/events/events.target.linux-x86.mk
+++ b/ui/events/events.target.linux-x86.mk
@@ -38,8 +38,9 @@
 	ui/events/gestures/gesture_point.cc \
 	ui/events/gestures/gesture_recognizer_impl.cc \
 	ui/events/gestures/gesture_sequence.cc \
-	ui/events/gestures/gesture_types.cc \
-	ui/events/gestures/velocity_calculator.cc
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
 
 
 # Flags passed to both C and C++ files.
@@ -103,9 +104,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -114,6 +113,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +222,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +231,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/events.target.linux-x86_64.mk b/ui/events/events.target.linux-x86_64.mk
new file mode 100644
index 0000000..edc8312
--- /dev/null
+++ b/ui/events/events.target.linux-x86_64.mk
@@ -0,0 +1,343 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_events_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/event.cc \
+	ui/events/event_dispatcher.cc \
+	ui/events/event_handler.cc \
+	ui/events/event_processor.cc \
+	ui/events/event_source.cc \
+	ui/events/event_target.cc \
+	ui/events/event_targeter.cc \
+	ui/events/event_utils.cc \
+	ui/events/events_stub.cc \
+	ui/events/gestures/gesture_configuration.cc \
+	ui/events/gestures/gesture_point.cc \
+	ui/events/gestures/gesture_recognizer_impl.cc \
+	ui/events/gestures/gesture_sequence.cc \
+	ui/events/gestures/velocity_calculator.cc \
+	ui/events/platform/platform_event_source.cc \
+	ui/events/platform/scoped_event_dispatcher.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_events_gyp
+
+# Alias gyp target name.
+.PHONY: events
+events: ui_events_events_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/events_base.target.darwin-arm.mk b/ui/events/events_base.target.darwin-arm.mk
index 691f6ba..57a2902 100644
--- a/ui/events/events_base.target.darwin-arm.mk
+++ b/ui/events/events_base.target.darwin-arm.mk
@@ -10,7 +10,8 @@
 gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
 
 # Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
 
 GYP_GENERATED_OUTPUTS :=
 
@@ -24,6 +25,7 @@
 
 LOCAL_SRC_FILES := \
 	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
 	ui/events/keycodes/keyboard_code_conversion.cc \
 	ui/events/keycodes/keyboard_code_conversion_android.cc \
 	ui/events/latency_info.cc
@@ -81,7 +83,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -96,8 +115,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -166,7 +201,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -182,8 +234,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -246,7 +314,8 @@
 
 LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
 
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/ui/events/events_base.target.darwin-mips.mk b/ui/events/events_base.target.darwin-mips.mk
index 6b3316e..67b159b 100644
--- a/ui/events/events_base.target.darwin-mips.mk
+++ b/ui/events/events_base.target.darwin-mips.mk
@@ -10,7 +10,8 @@
 gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
 
 # Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
 
 GYP_GENERATED_OUTPUTS :=
 
@@ -24,6 +25,7 @@
 
 LOCAL_SRC_FILES := \
 	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
 	ui/events/keycodes/keyboard_code_conversion.cc \
 	ui/events/keycodes/keyboard_code_conversion_android.cc \
 	ui/events/latency_info.cc
@@ -80,7 +82,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -95,8 +114,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -164,7 +199,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -180,8 +232,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -240,7 +308,8 @@
 
 LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
 
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/ui/events/events_base.target.darwin-x86.mk b/ui/events/events_base.target.darwin-x86.mk
index 9d764e3..6c58566 100644
--- a/ui/events/events_base.target.darwin-x86.mk
+++ b/ui/events/events_base.target.darwin-x86.mk
@@ -10,7 +10,8 @@
 gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
 
 # Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
 
 GYP_GENERATED_OUTPUTS :=
 
@@ -24,6 +25,7 @@
 
 LOCAL_SRC_FILES := \
 	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
 	ui/events/keycodes/keyboard_code_conversion.cc \
 	ui/events/keycodes/keyboard_code_conversion_android.cc \
 	ui/events/latency_info.cc
@@ -82,7 +84,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -97,8 +116,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -167,7 +202,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -183,8 +235,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -242,7 +310,8 @@
 
 LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
 
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/ui/events/events_base.target.darwin-x86_64.mk b/ui/events/events_base.target.darwin-x86_64.mk
new file mode 100644
index 0000000..bcd4c13
--- /dev/null
+++ b/ui/events/events_base.target.darwin-x86_64.mk
@@ -0,0 +1,331 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_events_base_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
+	ui/events/keycodes/keyboard_code_conversion.cc \
+	ui/events/keycodes/keyboard_code_conversion_android.cc \
+	ui/events/latency_info.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_events_base_gyp
+
+# Alias gyp target name.
+.PHONY: events_base
+events_base: ui_events_events_base_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/events_base.target.linux-arm.mk b/ui/events/events_base.target.linux-arm.mk
index 691f6ba..57a2902 100644
--- a/ui/events/events_base.target.linux-arm.mk
+++ b/ui/events/events_base.target.linux-arm.mk
@@ -10,7 +10,8 @@
 gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
 
 # Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
 
 GYP_GENERATED_OUTPUTS :=
 
@@ -24,6 +25,7 @@
 
 LOCAL_SRC_FILES := \
 	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
 	ui/events/keycodes/keyboard_code_conversion.cc \
 	ui/events/keycodes/keyboard_code_conversion_android.cc \
 	ui/events/latency_info.cc
@@ -81,7 +83,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -96,8 +115,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -166,7 +201,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -182,8 +234,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -246,7 +314,8 @@
 
 LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
 
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/ui/events/events_base.target.linux-mips.mk b/ui/events/events_base.target.linux-mips.mk
index 6b3316e..67b159b 100644
--- a/ui/events/events_base.target.linux-mips.mk
+++ b/ui/events/events_base.target.linux-mips.mk
@@ -10,7 +10,8 @@
 gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
 
 # Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
 
 GYP_GENERATED_OUTPUTS :=
 
@@ -24,6 +25,7 @@
 
 LOCAL_SRC_FILES := \
 	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
 	ui/events/keycodes/keyboard_code_conversion.cc \
 	ui/events/keycodes/keyboard_code_conversion_android.cc \
 	ui/events/latency_info.cc
@@ -80,7 +82,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -95,8 +114,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -164,7 +199,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -180,8 +232,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -240,7 +308,8 @@
 
 LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
 
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/ui/events/events_base.target.linux-x86.mk b/ui/events/events_base.target.linux-x86.mk
index 9d764e3..6c58566 100644
--- a/ui/events/events_base.target.linux-x86.mk
+++ b/ui/events/events_base.target.linux-x86.mk
@@ -10,7 +10,8 @@
 gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
 
 # Make sure our deps are built first.
-GYP_TARGET_DEPENDENCIES :=
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
 
 GYP_GENERATED_OUTPUTS :=
 
@@ -24,6 +25,7 @@
 
 LOCAL_SRC_FILES := \
 	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
 	ui/events/keycodes/keyboard_code_conversion.cc \
 	ui/events/keycodes/keyboard_code_conversion_android.cc \
 	ui/events/latency_info.cc
@@ -82,7 +84,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -97,8 +116,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -167,7 +202,24 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -183,8 +235,24 @@
 
 # Include paths placed before CFLAGS/CPPFLAGS
 LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
 	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
 	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
 	$(PWD)/frameworks/wilhelm/include \
 	$(PWD)/bionic \
 	$(PWD)/external/stlport/stlport
@@ -242,7 +310,8 @@
 
 LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
 
-LOCAL_STATIC_LIBRARIES :=
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
 
 # Enable grouping to fix circular references
 LOCAL_GROUP_STATIC_LIBRARIES := true
diff --git a/ui/events/events_base.target.linux-x86_64.mk b/ui/events/events_base.target.linux-x86_64.mk
new file mode 100644
index 0000000..bcd4c13
--- /dev/null
+++ b/ui/events/events_base.target.linux-x86_64.mk
@@ -0,0 +1,331 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_events_base_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/event_switches.cc \
+	ui/events/gesture_event_details.cc \
+	ui/events/keycodes/keyboard_code_conversion.cc \
+	ui/events/keycodes/keyboard_code_conversion_android.cc \
+	ui/events/latency_info.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DEVENTS_BASE_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_events_base_gyp
+
+# Alias gyp target name.
+.PHONY: events_base
+events_base: ui_events_events_base_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/gesture_detection.target.darwin-arm.mk b/ui/events/gesture_detection.target.darwin-arm.mk
index 70b3dc6..d8edaa1 100644
--- a/ui/events/gesture_detection.target.darwin-arm.mk
+++ b/ui/events/gesture_detection.target.darwin-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/gesture_detection.target.darwin-mips.mk b/ui/events/gesture_detection.target.darwin-mips.mk
index 4b2e134..38c9edb 100644
--- a/ui/events/gesture_detection.target.darwin-mips.mk
+++ b/ui/events/gesture_detection.target.darwin-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -225,6 +222,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/gesture_detection.target.darwin-x86.mk b/ui/events/gesture_detection.target.darwin-x86.mk
index 9795472..a387b8f 100644
--- a/ui/events/gesture_detection.target.darwin-x86.mk
+++ b/ui/events/gesture_detection.target.darwin-x86.mk
@@ -98,9 +98,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -217,9 +216,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -228,6 +225,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/gesture_detection.target.darwin-x86_64.mk b/ui/events/gesture_detection.target.darwin-x86_64.mk
new file mode 100644
index 0000000..f2f816c
--- /dev/null
+++ b/ui/events/gesture_detection.target.darwin-x86_64.mk
@@ -0,0 +1,337 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_gesture_detection_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/gesture_detection/filtered_gesture_provider.cc \
+	ui/events/gesture_detection/gesture_detector.cc \
+	ui/events/gesture_detection/gesture_event_data.cc \
+	ui/events/gesture_detection/gesture_event_data_packet.cc \
+	ui/events/gesture_detection/gesture_config_helper_android.cc \
+	ui/events/gesture_detection/gesture_provider.cc \
+	ui/events/gesture_detection/scale_gesture_detector.cc \
+	ui/events/gesture_detection/snap_scroll_controller.cc \
+	ui/events/gesture_detection/touch_disposition_gesture_filter.cc \
+	ui/events/gesture_detection/velocity_tracker_state.cc \
+	ui/events/gesture_detection/velocity_tracker.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGESTURE_DETECTION_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGESTURE_DETECTION_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_gesture_detection_gyp
+
+# Alias gyp target name.
+.PHONY: gesture_detection
+gesture_detection: ui_events_gesture_detection_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/gesture_detection.target.linux-arm.mk b/ui/events/gesture_detection.target.linux-arm.mk
index 70b3dc6..d8edaa1 100644
--- a/ui/events/gesture_detection.target.linux-arm.mk
+++ b/ui/events/gesture_detection.target.linux-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/gesture_detection.target.linux-mips.mk b/ui/events/gesture_detection.target.linux-mips.mk
index 4b2e134..38c9edb 100644
--- a/ui/events/gesture_detection.target.linux-mips.mk
+++ b/ui/events/gesture_detection.target.linux-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -225,6 +222,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/gesture_detection.target.linux-x86.mk b/ui/events/gesture_detection.target.linux-x86.mk
index 9795472..a387b8f 100644
--- a/ui/events/gesture_detection.target.linux-x86.mk
+++ b/ui/events/gesture_detection.target.linux-x86.mk
@@ -98,9 +98,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -217,9 +216,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -228,6 +225,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/events/gesture_detection.target.linux-x86_64.mk b/ui/events/gesture_detection.target.linux-x86_64.mk
new file mode 100644
index 0000000..f2f816c
--- /dev/null
+++ b/ui/events/gesture_detection.target.linux-x86_64.mk
@@ -0,0 +1,337 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_events_gesture_detection_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/events/gesture_detection/filtered_gesture_provider.cc \
+	ui/events/gesture_detection/gesture_detector.cc \
+	ui/events/gesture_detection/gesture_event_data.cc \
+	ui/events/gesture_detection/gesture_event_data_packet.cc \
+	ui/events/gesture_detection/gesture_config_helper_android.cc \
+	ui/events/gesture_detection/gesture_provider.cc \
+	ui/events/gesture_detection/scale_gesture_detector.cc \
+	ui/events/gesture_detection/snap_scroll_controller.cc \
+	ui/events/gesture_detection/touch_disposition_gesture_filter.cc \
+	ui/events/gesture_detection/velocity_tracker_state.cc \
+	ui/events/gesture_detection/velocity_tracker.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGESTURE_DETECTION_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGESTURE_DETECTION_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_events_gesture_detection_gyp
+
+# Alias gyp target name.
+.PHONY: gesture_detection
+gesture_detection: ui_events_gesture_detection_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/events/gesture_detection/gesture_event_data.cc b/ui/events/gesture_detection/gesture_event_data.cc
index af54592..345b630 100644
--- a/ui/events/gesture_detection/gesture_event_data.cc
+++ b/ui/events/gesture_detection/gesture_event_data.cc
@@ -8,18 +8,27 @@
 
 namespace ui {
 
-GestureEventData::GestureEventData()
-    : type(ET_UNKNOWN), x(0), y(0) {}
-
 GestureEventData::GestureEventData(EventType type,
                                    base::TimeTicks time,
                                    float x,
                                    float y,
-                                   const Details& details)
+                                   const GestureEventDetails& details)
     : type(type), time(time), x(x), y(y), details(details) {
   DCHECK(ET_GESTURE_TYPE_START <= type && type <= ET_GESTURE_TYPE_END);
 }
 
-GestureEventData::Details::Details() { memset(this, 0, sizeof(Details)); }
+GestureEventData::GestureEventData(EventType type,
+                                   base::TimeTicks time,
+                                   float x,
+                                   float y)
+    : type(type),
+      time(time),
+      x(x),
+      y(y),
+      details(GestureEventDetails(type, 0, 0)) {
+  DCHECK(ET_GESTURE_TYPE_START <= type && type <= ET_GESTURE_TYPE_END);
+}
+
+GestureEventData::GestureEventData() : type(ET_UNKNOWN), x(0), y(0) {}
 
 }  //  namespace ui
diff --git a/ui/events/gesture_detection/gesture_event_data.h b/ui/events/gesture_detection/gesture_event_data.h
index 008ef3c..280103a 100644
--- a/ui/events/gesture_detection/gesture_event_data.h
+++ b/ui/events/gesture_detection/gesture_event_data.h
@@ -8,78 +8,30 @@
 #include "base/time/time.h"
 #include "ui/events/event_constants.h"
 #include "ui/events/gesture_detection/gesture_detection_export.h"
+#include "ui/events/gesture_event_details.h"
 
 namespace ui {
 
 class GestureEventDataPacket;
 
-// Simple transport construct for gesture-related event data.
-// TODO(jdduke): Merge this class with ui::GestureEventDetails.
 struct GESTURE_DETECTION_EXPORT GestureEventData {
-  struct Details;
   GestureEventData(EventType type,
                    base::TimeTicks time,
                    float x,
                    float y,
-                   const Details& details);
+                   const GestureEventDetails& details);
+
+  GestureEventData(EventType type,
+                   base::TimeTicks time,
+                   float x,
+                   float y);
 
   EventType type;
   base::TimeTicks time;
   float x;
   float y;
 
-  // TODO(jdduke): Determine if we can simply re-use blink::WebGestureEvent, as
-  // this is more or less straight up duplication.
-  struct GESTURE_DETECTION_EXPORT Details {
-    Details();
-    union {
-      // Tap information must be set for ET_GESTURE_TAP,
-      // ET_GESTURE_TAP_UNCONFIRMED, and ET_GESTURE_DOUBLE_TAP events.
-      struct {
-        int tap_count;
-        float width;
-        float height;
-      } tap;
-
-      struct {
-        float width;
-        float height;
-      } tap_down;
-
-      struct {
-        float width;
-        float height;
-      } show_press;
-
-      struct {
-        float width;
-        float height;
-      } long_press;
-
-      struct {
-        // Initial motion that triggered the scroll.
-        // May be redundant with delta_x/delta_y in the first scroll_update.
-        float delta_x_hint;
-        float delta_y_hint;
-      } scroll_begin;
-
-      struct {
-        float delta_x;
-        float delta_y;
-        float velocity_x;
-        float velocity_y;
-      } scroll_update;
-
-      struct {
-        float velocity_x;
-        float velocity_y;
-      } fling_start;
-
-      struct {
-        float scale;
-      } pinch_update;
-    };
-  } details;
+  GestureEventDetails details;
 
  private:
   friend class GestureEventDataPacket;
diff --git a/ui/events/gesture_detection/gesture_event_details.cc b/ui/events/gesture_detection/gesture_event_details.cc
new file mode 100644
index 0000000..1de178d
--- /dev/null
+++ b/ui/events/gesture_detection/gesture_event_details.cc
@@ -0,0 +1,112 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/gesture_detection/gesture_event_details.h"
+
+namespace ui {
+
+GestureEventDetails::GestureEventDetails() : type_(ET_UNKNOWN) {}
+
+GestureEventDetails::GestureEventDetails(ui::EventType type,
+                                         float delta_x,
+                                         float delta_y)
+    : type_(type),
+      touch_points_(1) {
+  switch (type_) {
+    case ui::ET_GESTURE_SCROLL_BEGIN:
+      data.scroll_begin.x_hint = delta_x;
+      data.scroll_begin.y_hint = delta_y;
+      break;
+
+    case ui::ET_GESTURE_SCROLL_UPDATE:
+      data.scroll_update.x = delta_x;
+      data.scroll_update.y = delta_y;
+      data.scroll_update.x_ordinal = delta_x;
+      data.scroll_update.y_ordinal = delta_y;
+      break;
+
+    case ui::ET_SCROLL_FLING_START:
+      data.fling_velocity.x = delta_x;
+      data.fling_velocity.y = delta_y;
+      data.fling_velocity.x_ordinal = delta_x;
+      data.fling_velocity.y_ordinal = delta_y;
+      break;
+
+    case ui::ET_GESTURE_LONG_PRESS:
+      data.touch_id = static_cast<int>(delta_x);
+      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for long press.";
+      break;
+
+    case ui::ET_GESTURE_TWO_FINGER_TAP:
+      data.first_finger_enclosing_rectangle.width = delta_x;
+      data.first_finger_enclosing_rectangle.height = delta_y;
+      break;
+
+    case ui::ET_GESTURE_PINCH_UPDATE:
+      data.scale = delta_x;
+      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for pinch";
+      break;
+
+    case ui::ET_GESTURE_MULTIFINGER_SWIPE:
+      data.swipe.left = delta_x < 0;
+      data.swipe.right = delta_x > 0;
+      data.swipe.up = delta_y < 0;
+      data.swipe.down = delta_y > 0;
+      break;
+
+    case ui::ET_GESTURE_TAP:
+      data.tap_count = static_cast<int>(delta_x);
+      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for tap.";
+      break;
+
+    default:
+      if (delta_x != 0.f || delta_y != 0.f) {
+        DLOG(WARNING) << "A gesture event (" << type << ") had unknown data: ("
+                      << delta_x << "," << delta_y;
+      }
+      break;
+  }
+}
+
+GestureEventDetails::GestureEventDetails(ui::EventType type,
+                                         float delta_x,
+                                         float delta_y,
+                                         float delta_x_ordinal,
+                                         float delta_y_ordinal)
+    : type_(type),
+      touch_points_(1) {
+  CHECK(type == ui::ET_GESTURE_SCROLL_UPDATE ||
+        type == ui::ET_SCROLL_FLING_START);
+  switch (type_) {
+    case ui::ET_GESTURE_SCROLL_UPDATE:
+      data.scroll_update.x = delta_x;
+      data.scroll_update.y = delta_y;
+      data.scroll_update.x_ordinal = delta_x_ordinal;
+      data.scroll_update.y_ordinal = delta_y_ordinal;
+      break;
+
+    case ui::ET_SCROLL_FLING_START:
+      data.fling_velocity.x = delta_x;
+      data.fling_velocity.y = delta_y;
+      data.fling_velocity.x_ordinal = delta_x_ordinal;
+      data.fling_velocity.y_ordinal = delta_y_ordinal;
+      break;
+
+    default:
+      break;
+  }
+}
+
+void GestureEventDetails::SetScrollVelocity(float velocity_x,
+                                            float velocity_y,
+                                            float velocity_x_ordinal,
+                                            float velocity_y_ordinal) {
+  CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+  data.scroll_update.velocity_x = velocity_x;
+  data.scroll_update.velocity_y = velocity_y;
+  data.scroll_update.velocity_x_ordinal = velocity_x_ordinal;
+  data.scroll_update.velocity_y_ordinal = velocity_y_ordinal;
+}
+
+}  // namespace ui
diff --git a/ui/events/gesture_detection/gesture_event_details.h b/ui/events/gesture_detection/gesture_event_details.h
new file mode 100644
index 0000000..8c924e7
--- /dev/null
+++ b/ui/events/gesture_detection/gesture_event_details.h
@@ -0,0 +1,201 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
+#define UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
+
+#include "base/logging.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/events_base_export.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/rect_conversions.h"
+
+namespace ui {
+
+struct EVENTS_BASE_EXPORT GestureEventDetails {
+ public:
+  GestureEventDetails();
+  GestureEventDetails(EventType type, float delta_x, float delta_y);
+  GestureEventDetails(EventType type,
+                      float delta_x, float delta_y,
+                      float delta_x_ordinal, float delta_y_ordinal);
+
+  EventType type() const { return type_; }
+
+  int touch_points() const { return touch_points_; }
+  void set_touch_points(int touch_points) { touch_points_ = touch_points; }
+
+  // TODO(tdresser): Return RectF. See crbug.com/337824.
+  const gfx::Rect bounding_box() const {
+    return ToEnclosingRect(bounding_box_);
+  }
+  void set_bounding_box(const gfx::RectF& box) { bounding_box_ = box; }
+
+  void SetScrollVelocity(float velocity_x, float velocity_y,
+                         float velocity_x_ordinal, float velocity_y_ordinal);
+
+  float scroll_x_hint() const {
+    CHECK_EQ(ui::ET_GESTURE_SCROLL_BEGIN, type_);
+    return data.scroll_begin.x_hint;
+  }
+
+  float scroll_y_hint() const {
+    CHECK_EQ(ui::ET_GESTURE_SCROLL_BEGIN, type_);
+    return data.scroll_begin.y_hint;
+  }
+
+  float scroll_x() const {
+    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.x;
+  }
+
+  float scroll_y() const {
+    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.y;
+  }
+
+  float velocity_x() const {
+    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ? data.fling_velocity.x :
+                                                data.scroll_update.velocity_x;
+  }
+
+  float velocity_y() const {
+    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ? data.fling_velocity.y :
+                                                data.scroll_update.velocity_y;
+  }
+
+  // *_ordinal values are unmodified by rail based clamping.
+  float scroll_x_ordinal() const {
+    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.x_ordinal;
+  }
+
+  float scroll_y_ordinal() const {
+    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.y_ordinal;
+  }
+
+  float velocity_x_ordinal() const {
+    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ?
+        data.fling_velocity.x_ordinal :
+        data.scroll_update.velocity_x_ordinal;
+  }
+
+  float velocity_y_ordinal() const {
+    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ?
+        data.fling_velocity.y_ordinal :
+        data.scroll_update.velocity_y_ordinal;
+  }
+
+  int touch_id() const {
+    CHECK_EQ(ui::ET_GESTURE_LONG_PRESS, type_);
+    return data.touch_id;
+  }
+
+  float first_finger_width() const {
+    CHECK_EQ(ui::ET_GESTURE_TWO_FINGER_TAP, type_);
+    return data.first_finger_enclosing_rectangle.width;
+  }
+
+  float first_finger_height() const {
+    CHECK_EQ(ui::ET_GESTURE_TWO_FINGER_TAP, type_);
+    return data.first_finger_enclosing_rectangle.height;
+  }
+
+  float scale() const {
+    CHECK_EQ(ui::ET_GESTURE_PINCH_UPDATE, type_);
+    return data.scale;
+  }
+
+  bool swipe_left() const {
+    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.left;
+  }
+
+  bool swipe_right() const {
+    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.right;
+  }
+
+  bool swipe_up() const {
+    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.up;
+  }
+
+  bool swipe_down() const {
+    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.down;
+  }
+
+  int tap_count() const {
+    CHECK_EQ(ui::ET_GESTURE_TAP, type_);
+    return data.tap_count;
+  }
+
+ private:
+  ui::EventType type_;
+  union {
+    struct {  // SCROLL start details.
+      // Distance that caused the scroll to start.  Generally redundant with
+      // the x/y values from the first scroll_update.
+      float x_hint;
+      float y_hint;
+    } scroll_begin;
+
+    struct {  // SCROLL delta.
+      float x;
+      float y;
+      float velocity_x;
+      float velocity_y;
+      float x_ordinal;
+      float y_ordinal;
+      float velocity_x_ordinal;
+      float velocity_y_ordinal;
+    } scroll_update;
+
+    float scale;  // PINCH scale.
+
+    struct {  // FLING velocity.
+      float x;
+      float y;
+      float x_ordinal;
+      float y_ordinal;
+    } fling_velocity;
+
+    int touch_id;  // LONG_PRESS touch-id.
+
+    // Dimensions of the first finger's enclosing rectangle for TWO_FINGER_TAP.
+    struct {
+      float width;
+      float height;
+    } first_finger_enclosing_rectangle;
+
+    struct {  // SWIPE direction.
+      bool left;
+      bool right;
+      bool up;
+      bool down;
+    } swipe;
+
+    int tap_count;  // TAP repeat count.
+  } data;
+
+  int touch_points_;  // Number of active touch points in the gesture.
+
+  // Bounding box is an axis-aligned rectangle that contains all the
+  // enclosing rectangles of the touch-points in the gesture.
+  gfx::RectF bounding_box_;
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc
index 35cd67b..4deeba2 100644
--- a/ui/events/gesture_detection/gesture_provider.cc
+++ b/ui/events/gesture_detection/gesture_provider.cc
@@ -34,7 +34,7 @@
                                base::TimeTicks time,
                                float x,
                                float y,
-                               const GestureEventData::Details& details) {
+                               const GestureEventDetails& details) {
   return GestureEventData(type, time, x, y, details);
 }
 
@@ -42,32 +42,33 @@
                                base::TimeTicks time,
                                float x,
                                float y) {
-  return CreateGesture(type, time, x, y, GestureEventData::Details());
-}
+  return GestureEventData(type, time, x, y);
+  }
 
 GestureEventData CreateGesture(EventType type,
                                const MotionEvent& event,
-                               const GestureEventData::Details& details) {
+                               const GestureEventDetails& details) {
   return CreateGesture(
       type, event.GetEventTime(), event.GetX(), event.GetY(), details);
 }
 
 GestureEventData CreateGesture(EventType type,
                                const MotionEvent& event) {
-  return CreateGesture(type, event, GestureEventData::Details());
+  return CreateGesture(type, event.GetEventTime(), event.GetX(), event.GetY());
 }
 
 float Round(float f) {
   return (f > 0.f) ? std::floor(f + 0.5f) : std::ceil(f - 0.5f);
 }
 
-GestureEventData::Details CreateTapGestureDetails(const MotionEvent& event) {
-  GestureEventData::Details tap_details;
+GestureEventDetails CreateTapGestureDetails(EventType type,
+                                            const MotionEvent& event) {
   // Set the tap count to 1 even for ET_GESTURE_DOUBLE_TAP, in order to be
   // consistent with double tap behavior on a mobile viewport. See
   // crbug.com/234986 for context.
-  tap_details.tap.tap_count = 1;
-  tap_details.tap.width = tap_details.tap.height = event.GetTouchMajor();
+  GestureEventDetails tap_details(type, 1, 0);
+  tap_details.set_bounding_box(
+      gfx::RectF(event.GetTouchMajor(), event.GetTouchMajor()));
   return tap_details;
 }
 
@@ -129,8 +130,8 @@
                                     detector.GetFocusX(),
                                     detector.GetFocusY()));
     }
-    GestureEventData::Details pinch_details;
-    pinch_details.pinch_update.scale = detector.GetScaleFactor();
+    GestureEventDetails pinch_details(
+        ET_GESTURE_PINCH_UPDATE, detector.GetScaleFactor(), 0);
     provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE,
                                   detector.GetEventTime(),
                                   detector.GetFocusX(),
@@ -229,8 +230,9 @@
     accumulated_scroll_error_x_ = 0;
     accumulated_scroll_error_y_ = 0;
 
-    GestureEventData::Details tap_details;
-    tap_details.tap.width = tap_details.tap.height = e.GetTouchMajor();
+    GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN, 0, 0);
+    tap_details.set_bounding_box(
+        gfx::RectF(e.GetTouchMajor(), e.GetTouchMajor()));
     provider_->Send(CreateGesture(ET_GESTURE_TAP_DOWN, e, tap_details));
 
     // Return true to indicate that we want to handle touch.
@@ -270,9 +272,8 @@
     if (!provider_->IsScrollInProgress()) {
       // Note that scroll start hints are in distance traveled, where
       // scroll deltas are in the opposite direction.
-      GestureEventData::Details scroll_details;
-      scroll_details.scroll_begin.delta_x_hint = -raw_distance_x;
-      scroll_details.scroll_begin.delta_y_hint = -raw_distance_y;
+      GestureEventDetails scroll_details(
+          ET_GESTURE_SCROLL_BEGIN, -raw_distance_x, -raw_distance_y);
       provider_->Send(CreateGesture(ET_GESTURE_SCROLL_BEGIN,
                                     e2.GetEventTime(),
                                     e1.GetX(),
@@ -293,9 +294,7 @@
     accumulated_scroll_error_y_ += (distance_y - dy);
 
     if (dx || dy) {
-      GestureEventData::Details scroll_details;
-      scroll_details.scroll_update.delta_x = -dx;
-      scroll_details.scroll_update.delta_y = -dy;
+      GestureEventDetails scroll_details(ET_GESTURE_SCROLL_UPDATE, -dx, -dy);
       provider_->Send(
           CreateGesture(ET_GESTURE_SCROLL_UPDATE, e2, scroll_details));
     }
@@ -321,10 +320,10 @@
   }
 
   virtual void OnShowPress(const MotionEvent& e) OVERRIDE {
-    GestureEventData::Details show_press_details;
+    GestureEventDetails show_press_details(ET_GESTURE_SHOW_PRESS, 0, 0);
     // TODO(jdduke): Expose minor axis length and rotation in |MotionEvent|.
-    show_press_details.show_press.width = e.GetTouchMajor();
-    show_press_details.show_press.height = show_press_details.show_press.width;
+    show_press_details.set_bounding_box(
+        gfx::RectF(e.GetTouchMajor(), e.GetTouchMajor()));
     provider_->Send(
         CreateGesture(ET_GESTURE_SHOW_PRESS, e, show_press_details));
   }
@@ -352,7 +351,9 @@
         // Notify Blink about this tapUp event anyway, when none of the above
         // conditions applied.
         provider_->Send(CreateGesture(
-            ET_GESTURE_TAP_UNCONFIRMED, e, CreateTapGestureDetails(e)));
+            ET_GESTURE_TAP_UNCONFIRMED,
+            e,
+            CreateTapGestureDetails(ET_GESTURE_TAP_UNCONFIRMED, e)));
       }
     }
 
@@ -370,8 +371,8 @@
 
     ignore_single_tap_ = true;
 
-    provider_->Send(
-        CreateGesture(ET_GESTURE_TAP, e, CreateTapGestureDetails(e)));
+    provider_->Send(CreateGesture(
+        ET_GESTURE_TAP, e, CreateTapGestureDetails(ET_GESTURE_TAP, e)));
     return true;
   }
 
@@ -400,9 +401,8 @@
           // Begin double-tap drag zoom mode if the move distance is
           // further than the threshold.
           if (IsDistanceGreaterThanTouchSlop(distance_x, distance_y)) {
-            GestureEventData::Details scroll_details;
-            scroll_details.scroll_begin.delta_x_hint = -distance_x;
-            scroll_details.scroll_begin.delta_y_hint = -distance_y;
+            GestureEventDetails scroll_details(
+                ET_GESTURE_SCROLL_BEGIN, -distance_x, -distance_y);
             provider_->Send(
                 CreateGesture(ET_GESTURE_SCROLL_BEGIN, e, scroll_details));
             provider_->Send(
@@ -416,11 +416,10 @@
           provider_->Send(CreateGesture(ET_GESTURE_SCROLL_UPDATE, e));
 
           float dy = double_tap_y_ - e.GetY();
-          GestureEventData::Details pinch_details;
-          pinch_details.pinch_update.scale =
-              std::pow(dy > 0 ? 1.0f - kDoubleTapDragZoomSpeed
-                              : 1.0f + kDoubleTapDragZoomSpeed,
-                       std::abs(dy * px_to_dp_));
+          float scale = std::pow(dy > 0 ? 1.0f - kDoubleTapDragZoomSpeed
+                                        : 1.0f + kDoubleTapDragZoomSpeed,
+                                 std::abs(dy * px_to_dp_));
+          GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0);
           provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE,
                                         e.GetEventTime(),
                                         Round(double_tap_drag_zoom_anchor_x_),
@@ -431,8 +430,10 @@
       case MotionEvent::ACTION_UP:
         if (double_tap_mode_ != DOUBLE_TAP_MODE_DRAG_ZOOM) {
           // Normal double-tap gesture.
-          provider_->Send(CreateGesture(
-              ET_GESTURE_DOUBLE_TAP, e, CreateTapGestureDetails(e)));
+          provider_->Send(
+              CreateGesture(ET_GESTURE_DOUBLE_TAP,
+                            e,
+                            CreateTapGestureDetails(ET_GESTURE_DOUBLE_TAP, e)));
         }
         EndDoubleTapDragIfNecessary(e);
         break;
@@ -451,9 +452,9 @@
     DCHECK(!IsDoubleTapInProgress());
     SetIgnoreSingleTap(true);
 
-    GestureEventData::Details long_press_details;
-    long_press_details.long_press.width = e.GetTouchMajor();
-    long_press_details.long_press.height = long_press_details.long_press.width;
+    GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS, 0, 0);
+    long_press_details.set_bounding_box(
+        gfx::RectF(e.GetTouchMajor(), e.GetTouchMajor()));
     provider_->Send(
         CreateGesture(ET_GESTURE_LONG_PRESS, e, long_press_details));
 
@@ -716,16 +717,14 @@
     // ET_SCROLL_FLING_START to send the fling to the correct target. Send if it
     // has not sent.  The distance traveled in one second is a reasonable scroll
     // start hint.
-    GestureEventData::Details scroll_details;
-    scroll_details.scroll_begin.delta_x_hint = velocity_x;
-    scroll_details.scroll_begin.delta_y_hint = velocity_y;
+    GestureEventDetails scroll_details(
+        ET_GESTURE_SCROLL_BEGIN, velocity_x, velocity_y);
     Send(CreateGesture(ET_GESTURE_SCROLL_BEGIN, time, x, y, scroll_details));
   }
   EndTouchScrollIfNecessary(time, false);
 
-  GestureEventData::Details fling_details;
-  fling_details.fling_start.velocity_x = velocity_x;
-  fling_details.fling_start.velocity_y = velocity_y;
+  GestureEventDetails fling_details(
+      ET_SCROLL_FLING_START, velocity_x, velocity_y);
   Send(CreateGesture(ET_SCROLL_FLING_START, time, x, y, fling_details));
 }
 
@@ -801,9 +800,9 @@
       !current_longpress_time_.is_null() &&
       !scale_gesture_listener_->IsScaleGestureDetectionInProgress()) {
     SendTapCancelIfNecessary(event);
-    GestureEventData::Details long_tap_details;
-    long_tap_details.long_press.width = event.GetTouchMajor();
-    long_tap_details.long_press.height = long_tap_details.long_press.width;
+    GestureEventDetails long_tap_details(ET_GESTURE_LONG_TAP, 0, 0);
+    long_tap_details.set_bounding_box(
+        gfx::RectF(event.GetTouchMajor(), event.GetTouchMajor()));
     Send(CreateGesture(ET_GESTURE_LONG_TAP, event, long_tap_details));
     return true;
   }
diff --git a/ui/events/gesture_detection/gesture_provider_unittest.cc b/ui/events/gesture_detection/gesture_provider_unittest.cc
index 569abe5..1be9ec7 100644
--- a/ui/events/gesture_detection/gesture_provider_unittest.cc
+++ b/ui/events/gesture_detection/gesture_provider_unittest.cc
@@ -208,10 +208,9 @@
   EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
   EXPECT_EQ(ET_GESTURE_TAP, GetMostRecentGestureEventType());
   // Ensure tap details have been set.
-  EXPECT_EQ(10, GetMostRecentGestureEvent().details.tap.width);
-  EXPECT_EQ(10, GetMostRecentGestureEvent().details.tap.height);
-  EXPECT_EQ(1, GetMostRecentGestureEvent().details.tap.tap_count);
-
+  EXPECT_EQ(10, GetMostRecentGestureEvent().details.bounding_box().width());
+  EXPECT_EQ(10, GetMostRecentGestureEvent().details.bounding_box().height());
+  EXPECT_EQ(1, GetMostRecentGestureEvent().details.tap_count());
 }
 
 // Verify that a DOWN followed shortly by an UP will trigger
@@ -231,9 +230,9 @@
   EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
   EXPECT_EQ(ET_GESTURE_TAP_UNCONFIRMED, GetMostRecentGestureEventType());
   // Ensure tap details have been set.
-  EXPECT_EQ(10, GetMostRecentGestureEvent().details.tap.width);
-  EXPECT_EQ(10, GetMostRecentGestureEvent().details.tap.height);
-  EXPECT_EQ(1, GetMostRecentGestureEvent().details.tap.tap_count);
+  EXPECT_EQ(10, GetMostRecentGestureEvent().details.bounding_box().width());
+  EXPECT_EQ(10, GetMostRecentGestureEvent().details.bounding_box().height());
+  EXPECT_EQ(1, GetMostRecentGestureEvent().details.tap_count());
 
   EXPECT_FALSE(HasReceivedGesture(ET_GESTURE_TAP));
 }
@@ -306,8 +305,8 @@
 
   // We don't want to take a dependency here on exactly how hints are calculated
   // for a fling (eg. may depend on velocity), so just validate the direction.
-  int hint_x = GetReceivedGesture(2).details.scroll_begin.delta_x_hint;
-  int hint_y = GetReceivedGesture(2).details.scroll_begin.delta_y_hint;
+  int hint_x = GetReceivedGesture(2).details.scroll_x_hint();
+  int hint_y = GetReceivedGesture(2).details.scroll_y_hint();
   EXPECT_TRUE(hint_x > 0 && hint_y > 0 && hint_x > hint_y)
       << "ScrollBegin hint should be in positive X axis";
 
@@ -401,9 +400,9 @@
   const GestureEventData& double_tap = GetMostRecentGestureEvent();
   EXPECT_EQ(ET_GESTURE_DOUBLE_TAP, double_tap.type);
   // Ensure tap details have been set.
-  EXPECT_EQ(10, double_tap.details.tap.width);
-  EXPECT_EQ(10, double_tap.details.tap.height);
-  EXPECT_EQ(1, double_tap.details.tap.tap_count);
+  EXPECT_EQ(10, double_tap.details.bounding_box().width());
+  EXPECT_EQ(10, double_tap.details.bounding_box().height());
+  EXPECT_EQ(1, double_tap.details.tap_count());
 }
 
 TEST_F(GestureProviderTest, DoubleTapDragZoom) {
@@ -434,8 +433,8 @@
   EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
   const GestureEventData* scroll_begin_gesture = GetActiveScrollBeginEvent();
   ASSERT_TRUE(!!scroll_begin_gesture);
-  EXPECT_EQ(0, scroll_begin_gesture->details.scroll_begin.delta_x_hint);
-  EXPECT_EQ(100, scroll_begin_gesture->details.scroll_begin.delta_y_hint);
+  EXPECT_EQ(0, scroll_begin_gesture->details.scroll_x_hint());
+  EXPECT_EQ(100, scroll_begin_gesture->details.scroll_y_hint());
   EXPECT_EQ(ET_GESTURE_PINCH_BEGIN, GetMostRecentGestureEventType());
 
   event = ObtainMotionEvent(down_time_2 + kOneMicrosecond * 2,
@@ -538,8 +537,8 @@
   EXPECT_EQ(kFakeCoordY - delta_y, gesture.y);
 
   // No horizontal delta because of snapping.
-  EXPECT_EQ(0, gesture.details.scroll_update.delta_x);
-  EXPECT_EQ(-delta_y / 2, gesture.details.scroll_update.delta_y);
+  EXPECT_EQ(0, gesture.details.scroll_x());
+  EXPECT_EQ(-delta_y / 2, gesture.details.scroll_y());
 }
 
 // Verify that fractional scroll deltas are rounded as expected and that
@@ -585,11 +584,11 @@
 
     // Verify that we're scrolling vertically by the expected amount
     // (modulo rounding).
-    EXPECT_GE(gesture.details.scroll_update.delta_y, (int)delta_y);
-    EXPECT_LE(gesture.details.scroll_update.delta_y, ((int)delta_y) + 1);
+    EXPECT_GE(gesture.details.scroll_y(), (int)delta_y);
+    EXPECT_LE(gesture.details.scroll_y(), ((int)delta_y) + 1);
 
     // And that there has been no horizontal motion at all.
-    EXPECT_EQ(0, gesture.details.scroll_update.delta_x);
+    EXPECT_EQ(0, gesture.details.scroll_x());
   }
 }
 
@@ -623,8 +622,8 @@
 
   const GestureEventData* scroll_begin_gesture = GetActiveScrollBeginEvent();
   ASSERT_TRUE(!!scroll_begin_gesture);
-  EXPECT_EQ(delta_x, scroll_begin_gesture->details.scroll_begin.delta_x_hint);
-  EXPECT_EQ(delta_y, scroll_begin_gesture->details.scroll_begin.delta_y_hint);
+  EXPECT_EQ(delta_x, scroll_begin_gesture->details.scroll_x_hint());
+  EXPECT_EQ(delta_y, scroll_begin_gesture->details.scroll_y_hint());
 }
 
 TEST_F(GestureProviderTest, LongPressAndTapCancelledWhenScrollBegins) {
@@ -764,8 +763,8 @@
 
   EXPECT_EQ(ET_GESTURE_SCROLL_UPDATE, GetMostRecentGestureEventType());
   GestureEventData gesture = GetMostRecentGestureEvent();
-  EXPECT_EQ(0, gesture.details.scroll_update.delta_x);
-  EXPECT_EQ(scroll_delta, gesture.details.scroll_update.delta_y);
+  EXPECT_EQ(0, gesture.details.scroll_x());
+  EXPECT_EQ(scroll_delta, gesture.details.scroll_y());
 }
 
 TEST_F(GestureProviderTest, NoDoubleTapWhenExplicitlyDisabled) {
diff --git a/ui/events/gesture_detection/touch_disposition_gesture_filter.cc b/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
index 414c46b..a64c1b6 100644
--- a/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
+++ b/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
@@ -6,6 +6,7 @@
 
 #include "base/auto_reset.h"
 #include "base/logging.h"
+#include "ui/events/gesture_event_details.h"
 
 namespace ui {
 namespace {
@@ -16,7 +17,7 @@
 
 GestureEventData CreateGesture(EventType type) {
   return GestureEventData(
-      type, base::TimeTicks(), 0, 0, GestureEventData::Details());
+      type, base::TimeTicks(), 0, 0, GestureEventDetails(type, 0, 0));
 }
 
 enum RequiredTouches {
diff --git a/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc b/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
index 687a0b7..79f1096 100644
--- a/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
+++ b/ui/events/gesture_detection/touch_disposition_gesture_filter_unittest.cc
@@ -168,8 +168,7 @@
   }
 
   static GestureEventData CreateGesture(EventType type) {
-    return GestureEventData(
-        type, base::TimeTicks(), 0, 0, GestureEventData::Details());
+    return GestureEventData(type, base::TimeTicks(), 0, 0);
   }
 
  private:
diff --git a/ui/events/gesture_event_details.cc b/ui/events/gesture_event_details.cc
new file mode 100644
index 0000000..983d2a1
--- /dev/null
+++ b/ui/events/gesture_event_details.cc
@@ -0,0 +1,118 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/gesture_event_details.h"
+
+namespace ui {
+
+GestureEventDetails::GestureEventDetails() : type_(ET_UNKNOWN) {}
+
+GestureEventDetails::GestureEventDetails(ui::EventType type,
+                                         float delta_x,
+                                         float delta_y)
+    : type_(type),
+      touch_points_(1) {
+  switch (type_) {
+    case ui::ET_GESTURE_SCROLL_BEGIN:
+      data.scroll_begin.x_hint = delta_x;
+      data.scroll_begin.y_hint = delta_y;
+      break;
+
+    case ui::ET_GESTURE_SCROLL_UPDATE:
+      data.scroll_update.x = delta_x;
+      data.scroll_update.y = delta_y;
+      data.scroll_update.x_ordinal = delta_x;
+      data.scroll_update.y_ordinal = delta_y;
+      break;
+
+    case ui::ET_SCROLL_FLING_START:
+      data.fling_velocity.x = delta_x;
+      data.fling_velocity.y = delta_y;
+      data.fling_velocity.x_ordinal = delta_x;
+      data.fling_velocity.y_ordinal = delta_y;
+      break;
+
+    case ui::ET_GESTURE_LONG_PRESS:
+      data.touch_id = static_cast<int>(delta_x);
+      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for long press.";
+      break;
+
+    case ui::ET_GESTURE_TWO_FINGER_TAP:
+      data.first_finger_enclosing_rectangle.width = delta_x;
+      data.first_finger_enclosing_rectangle.height = delta_y;
+      break;
+
+    case ui::ET_GESTURE_PINCH_UPDATE:
+      data.scale = delta_x;
+      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for pinch";
+      break;
+
+    case ui::ET_GESTURE_MULTIFINGER_SWIPE:
+      data.swipe.left = delta_x < 0;
+      data.swipe.right = delta_x > 0;
+      data.swipe.up = delta_y < 0;
+      data.swipe.down = delta_y > 0;
+      break;
+
+    case ui::ET_GESTURE_TAP:
+    case ui::ET_GESTURE_DOUBLE_TAP:
+    case ui::ET_GESTURE_TAP_UNCONFIRMED:
+      data.tap_count = static_cast<int>(delta_x);
+      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for tap.";
+      break;
+
+    default:
+      if (delta_x != 0.f || delta_y != 0.f) {
+        DLOG(WARNING) << "A gesture event (" << type << ") had unknown data: ("
+                      << delta_x << "," << delta_y;
+      }
+      break;
+  }
+}
+
+GestureEventDetails::GestureEventDetails(ui::EventType type,
+                                         float delta_x,
+                                         float delta_y,
+                                         float delta_x_ordinal,
+                                         float delta_y_ordinal)
+    : type_(type),
+      touch_points_(1) {
+  CHECK(type == ui::ET_GESTURE_SCROLL_UPDATE ||
+        type == ui::ET_SCROLL_FLING_START);
+  switch (type_) {
+    case ui::ET_GESTURE_SCROLL_UPDATE:
+      data.scroll_update.x = delta_x;
+      data.scroll_update.y = delta_y;
+      data.scroll_update.x_ordinal = delta_x_ordinal;
+      data.scroll_update.y_ordinal = delta_y_ordinal;
+      break;
+
+    case ui::ET_SCROLL_FLING_START:
+      data.fling_velocity.x = delta_x;
+      data.fling_velocity.y = delta_y;
+      data.fling_velocity.x_ordinal = delta_x_ordinal;
+      data.fling_velocity.y_ordinal = delta_y_ordinal;
+      break;
+
+    default:
+      break;
+  }
+}
+
+void GestureEventDetails::SetScrollVelocity(float velocity_x,
+                                            float velocity_y,
+                                            float velocity_x_ordinal,
+                                            float velocity_y_ordinal) {
+  CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+  data.scroll_update.velocity_x = velocity_x;
+  data.scroll_update.velocity_y = velocity_y;
+  data.scroll_update.velocity_x_ordinal = velocity_x_ordinal;
+  data.scroll_update.velocity_y_ordinal = velocity_y_ordinal;
+}
+
+GestureEventDetails::Details::Details() {
+  memset(this, 0, sizeof(Details));
+}
+
+}  // namespace ui
diff --git a/ui/events/gesture_event_details.h b/ui/events/gesture_event_details.h
new file mode 100644
index 0000000..f1c592f
--- /dev/null
+++ b/ui/events/gesture_event_details.h
@@ -0,0 +1,212 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
+#define UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
+
+#include "base/logging.h"
+#include "ui/events/event_constants.h"
+#include "ui/events/events_base_export.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/rect_conversions.h"
+
+namespace ui {
+
+struct EVENTS_BASE_EXPORT GestureEventDetails {
+ public:
+  GestureEventDetails();
+  GestureEventDetails(EventType type, float delta_x, float delta_y);
+  GestureEventDetails(EventType type,
+                      float delta_x, float delta_y,
+                      float delta_x_ordinal, float delta_y_ordinal);
+
+  EventType type() const { return type_; }
+
+  int touch_points() const { return touch_points_; }
+  void set_touch_points(int touch_points) { touch_points_ = touch_points; }
+
+  // TODO(tdresser): Return RectF. See crbug.com/337824.
+  const gfx::Rect bounding_box() const {
+    return ToEnclosingRect(bounding_box_);
+  }
+
+  const gfx::RectF& bounding_box_f() const {
+    return bounding_box_;
+  }
+
+  void set_bounding_box(const gfx::RectF& box) { bounding_box_ = box; }
+
+  void SetScrollVelocity(float velocity_x, float velocity_y,
+                         float velocity_x_ordinal, float velocity_y_ordinal);
+
+  float scroll_x_hint() const {
+    DCHECK_EQ(ui::ET_GESTURE_SCROLL_BEGIN, type_);
+    return data.scroll_begin.x_hint;
+  }
+
+  float scroll_y_hint() const {
+    DCHECK_EQ(ui::ET_GESTURE_SCROLL_BEGIN, type_);
+    return data.scroll_begin.y_hint;
+  }
+
+  float scroll_x() const {
+    DCHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.x;
+  }
+
+  float scroll_y() const {
+    DCHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.y;
+  }
+
+  float velocity_x() const {
+    DCHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ? data.fling_velocity.x :
+                                                data.scroll_update.velocity_x;
+  }
+
+  float velocity_y() const {
+    DCHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ? data.fling_velocity.y :
+                                                data.scroll_update.velocity_y;
+  }
+
+  // *_ordinal values are unmodified by rail based clamping.
+  float scroll_x_ordinal() const {
+    DCHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.x_ordinal;
+  }
+
+  float scroll_y_ordinal() const {
+    DCHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
+    return data.scroll_update.y_ordinal;
+  }
+
+  float velocity_x_ordinal() const {
+    DCHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ?
+        data.fling_velocity.x_ordinal :
+        data.scroll_update.velocity_x_ordinal;
+  }
+
+  float velocity_y_ordinal() const {
+    DCHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
+          type_ == ui::ET_SCROLL_FLING_START);
+    return type_ == ui::ET_SCROLL_FLING_START ?
+        data.fling_velocity.y_ordinal :
+        data.scroll_update.velocity_y_ordinal;
+  }
+
+  int touch_id() const {
+    DCHECK_EQ(ui::ET_GESTURE_LONG_PRESS, type_);
+    return data.touch_id;
+  }
+
+  float first_finger_width() const {
+    DCHECK_EQ(ui::ET_GESTURE_TWO_FINGER_TAP, type_);
+    return data.first_finger_enclosing_rectangle.width;
+  }
+
+  float first_finger_height() const {
+    DCHECK_EQ(ui::ET_GESTURE_TWO_FINGER_TAP, type_);
+    return data.first_finger_enclosing_rectangle.height;
+  }
+
+  float scale() const {
+    DCHECK_EQ(ui::ET_GESTURE_PINCH_UPDATE, type_);
+    return data.scale;
+  }
+
+  bool swipe_left() const {
+    DCHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.left;
+  }
+
+  bool swipe_right() const {
+    DCHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.right;
+  }
+
+  bool swipe_up() const {
+    DCHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.up;
+  }
+
+  bool swipe_down() const {
+    DCHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
+    return data.swipe.down;
+  }
+
+  int tap_count() const {
+    DCHECK(type_ == ui::ET_GESTURE_TAP ||
+           type_ == ui::ET_GESTURE_TAP_UNCONFIRMED ||
+           type_ == ET_GESTURE_DOUBLE_TAP);
+    return data.tap_count;
+  }
+
+ private:
+  ui::EventType type_;
+  union Details {
+    Details();
+    struct {  // SCROLL start details.
+      // Distance that caused the scroll to start.  Generally redundant with
+      // the x/y values from the first scroll_update.
+      float x_hint;
+      float y_hint;
+    } scroll_begin;
+
+    struct {  // SCROLL delta.
+      float x;
+      float y;
+      float velocity_x;
+      float velocity_y;
+      float x_ordinal;
+      float y_ordinal;
+      float velocity_x_ordinal;
+      float velocity_y_ordinal;
+    } scroll_update;
+
+    float scale;  // PINCH scale.
+
+    struct {  // FLING velocity.
+      float x;
+      float y;
+      float x_ordinal;
+      float y_ordinal;
+    } fling_velocity;
+
+    int touch_id;  // LONG_PRESS touch-id.
+
+    // Dimensions of the first finger's enclosing rectangle for
+    // TWO_FINGER_TAP.
+    struct {
+      float width;
+      float height;
+    } first_finger_enclosing_rectangle;
+
+    struct {  // SWIPE direction.
+      bool left;
+      bool right;
+      bool up;
+      bool down;
+    } swipe;
+
+    // Tap information must be set for ET_GESTURE_TAP,
+    // ET_GESTURE_TAP_UNCONFIRMED, and ET_GESTURE_DOUBLE_TAP events.
+    int tap_count;  // TAP repeat count.
+  } data;
+
+  int touch_points_;  // Number of active touch points in the gesture.
+
+  // Bounding box is an axis-aligned rectangle that contains all the
+  // enclosing rectangles of the touch-points in the gesture.
+  gfx::RectF bounding_box_;
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_GESTURE_DETECTION_GESTURE_EVENT_DETAILS_H_
diff --git a/ui/events/gestures/gesture_recognizer.h b/ui/events/gestures/gesture_recognizer.h
index 8363199..f33a7a7 100644
--- a/ui/events/gestures/gesture_recognizer.h
+++ b/ui/events/gestures/gesture_recognizer.h
@@ -11,6 +11,7 @@
 #include "ui/events/event_constants.h"
 #include "ui/events/events_export.h"
 #include "ui/events/gestures/gesture_types.h"
+#include "ui/gfx/geometry/point_f.h"
 
 namespace ui {
 // A GestureRecognizer is an abstract base class for conversion of touch events
diff --git a/ui/events/gestures/gesture_sequence.h b/ui/events/gestures/gesture_sequence.h
index 986be0b..62676e9 100644
--- a/ui/events/gestures/gesture_sequence.h
+++ b/ui/events/gestures/gesture_sequence.h
@@ -7,6 +7,7 @@
 
 #include "base/timer/timer.h"
 #include "ui/events/event_constants.h"
+#include "ui/events/gesture_event_details.h"
 #include "ui/events/gestures/gesture_point.h"
 #include "ui/events/gestures/gesture_recognizer.h"
 #include "ui/gfx/rect.h"
diff --git a/ui/events/gestures/gesture_types.cc b/ui/events/gestures/gesture_types.cc
deleted file mode 100644
index a086c66..0000000
--- a/ui/events/gestures/gesture_types.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/events/gestures/gesture_types.h"
-
-namespace ui {
-
-GestureEventDetails::GestureEventDetails(ui::EventType type,
-                                         float delta_x,
-                                         float delta_y)
-    : type_(type),
-      touch_points_(1) {
-  switch (type_) {
-    case ui::ET_GESTURE_SCROLL_BEGIN:
-      data.scroll_begin.x_hint = delta_x;
-      data.scroll_begin.y_hint = delta_y;
-      break;
-
-    case ui::ET_GESTURE_SCROLL_UPDATE:
-      data.scroll_update.x = delta_x;
-      data.scroll_update.y = delta_y;
-      data.scroll_update.x_ordinal = delta_x;
-      data.scroll_update.y_ordinal = delta_y;
-      break;
-
-    case ui::ET_SCROLL_FLING_START:
-      data.fling_velocity.x = delta_x;
-      data.fling_velocity.y = delta_y;
-      data.fling_velocity.x_ordinal = delta_x;
-      data.fling_velocity.y_ordinal = delta_y;
-      break;
-
-    case ui::ET_GESTURE_LONG_PRESS:
-      data.touch_id = static_cast<int>(delta_x);
-      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for long press.";
-      break;
-
-    case ui::ET_GESTURE_TWO_FINGER_TAP:
-      data.first_finger_enclosing_rectangle.width = delta_x;
-      data.first_finger_enclosing_rectangle.height = delta_y;
-      break;
-
-    case ui::ET_GESTURE_PINCH_UPDATE:
-      data.scale = delta_x;
-      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for pinch";
-      break;
-
-    case ui::ET_GESTURE_MULTIFINGER_SWIPE:
-      data.swipe.left = delta_x < 0;
-      data.swipe.right = delta_x > 0;
-      data.swipe.up = delta_y < 0;
-      data.swipe.down = delta_y > 0;
-      break;
-
-    case ui::ET_GESTURE_TAP:
-      data.tap_count = static_cast<int>(delta_x);
-      CHECK_EQ(0.f, delta_y) << "Unknown data in delta_y for tap.";
-      break;
-
-    default:
-      if (delta_x != 0.f || delta_y != 0.f) {
-        DLOG(WARNING) << "A gesture event (" << type << ") had unknown data: ("
-                      << delta_x << "," << delta_y;
-      }
-      break;
-  }
-}
-
-GestureEventDetails::GestureEventDetails(ui::EventType type,
-                                         float delta_x,
-                                         float delta_y,
-                                         float delta_x_ordinal,
-                                         float delta_y_ordinal)
-    : type_(type),
-      touch_points_(1) {
-  CHECK(type == ui::ET_GESTURE_SCROLL_UPDATE ||
-        type == ui::ET_SCROLL_FLING_START);
-  switch (type_) {
-    case ui::ET_GESTURE_SCROLL_UPDATE:
-      data.scroll_update.x = delta_x;
-      data.scroll_update.y = delta_y;
-      data.scroll_update.x_ordinal = delta_x_ordinal;
-      data.scroll_update.y_ordinal = delta_y_ordinal;
-      break;
-
-    case ui::ET_SCROLL_FLING_START:
-      data.fling_velocity.x = delta_x;
-      data.fling_velocity.y = delta_y;
-      data.fling_velocity.x_ordinal = delta_x_ordinal;
-      data.fling_velocity.y_ordinal = delta_y_ordinal;
-      break;
-
-    default:
-      break;
-  }
-}
-
-void GestureEventDetails::SetScrollVelocity(float velocity_x,
-                                            float velocity_y,
-                                            float velocity_x_ordinal,
-                                            float velocity_y_ordinal) {
-  CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
-  data.scroll_update.velocity_x = velocity_x;
-  data.scroll_update.velocity_y = velocity_y;
-  data.scroll_update.velocity_x_ordinal = velocity_x_ordinal;
-  data.scroll_update.velocity_y_ordinal = velocity_y_ordinal;
-}
-
-}  // namespace ui
diff --git a/ui/events/gestures/gesture_types.h b/ui/events/gestures/gesture_types.h
index 5887b75..8514508 100644
--- a/ui/events/gestures/gesture_types.h
+++ b/ui/events/gestures/gesture_types.h
@@ -5,199 +5,13 @@
 #ifndef UI_EVENTS_GESTURES_GESTURE_TYPES_H_
 #define UI_EVENTS_GESTURES_GESTURE_TYPES_H_
 
-#include "base/logging.h"
-#include "ui/events/event_constants.h"
 #include "ui/events/events_export.h"
-#include "ui/gfx/rect.h"
-#include "ui/gfx/rect_conversions.h"
 
 namespace ui {
 
 class GestureEvent;
 class TouchEvent;
 
-struct EVENTS_EXPORT GestureEventDetails {
- public:
-  GestureEventDetails(EventType type, float delta_x, float delta_y);
-  GestureEventDetails(EventType type,
-                      float delta_x, float delta_y,
-                      float delta_x_ordinal, float delta_y_ordinal);
-
-  EventType type() const { return type_; }
-
-  int touch_points() const { return touch_points_; }
-  void set_touch_points(int touch_points) { touch_points_ = touch_points; }
-
-  // TODO(tdresser): Return RectF. See crbug.com/337824.
-  const gfx::Rect bounding_box() const {
-    return ToEnclosingRect(bounding_box_);
-  }
-  void set_bounding_box(const gfx::RectF& box) { bounding_box_ = box; }
-
-  void SetScrollVelocity(float velocity_x, float velocity_y,
-                         float velocity_x_ordinal, float velocity_y_ordinal);
-
-  float scroll_x_hint() const {
-    CHECK_EQ(ui::ET_GESTURE_SCROLL_BEGIN, type_);
-    return data.scroll_begin.x_hint;
-  }
-
-  float scroll_y_hint() const {
-    CHECK_EQ(ui::ET_GESTURE_SCROLL_BEGIN, type_);
-    return data.scroll_begin.y_hint;
-  }
-
-  float scroll_x() const {
-    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
-    return data.scroll_update.x;
-  }
-
-  float scroll_y() const {
-    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
-    return data.scroll_update.y;
-  }
-
-  float velocity_x() const {
-    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
-          type_ == ui::ET_SCROLL_FLING_START);
-    return type_ == ui::ET_SCROLL_FLING_START ? data.fling_velocity.x :
-                                                data.scroll_update.velocity_x;
-  }
-
-  float velocity_y() const {
-    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
-          type_ == ui::ET_SCROLL_FLING_START);
-    return type_ == ui::ET_SCROLL_FLING_START ? data.fling_velocity.y :
-                                                data.scroll_update.velocity_y;
-  }
-
-  // *_ordinal values are unmodified by rail based clamping.
-  float scroll_x_ordinal() const {
-    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
-    return data.scroll_update.x_ordinal;
-  }
-
-  float scroll_y_ordinal() const {
-    CHECK_EQ(ui::ET_GESTURE_SCROLL_UPDATE, type_);
-    return data.scroll_update.y_ordinal;
-  }
-
-  float velocity_x_ordinal() const {
-    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
-          type_ == ui::ET_SCROLL_FLING_START);
-    return type_ == ui::ET_SCROLL_FLING_START ?
-        data.fling_velocity.x_ordinal :
-        data.scroll_update.velocity_x_ordinal;
-  }
-
-  float velocity_y_ordinal() const {
-    CHECK(type_ == ui::ET_GESTURE_SCROLL_UPDATE ||
-          type_ == ui::ET_SCROLL_FLING_START);
-    return type_ == ui::ET_SCROLL_FLING_START ?
-        data.fling_velocity.y_ordinal :
-        data.scroll_update.velocity_y_ordinal;
-  }
-
-  int touch_id() const {
-    CHECK_EQ(ui::ET_GESTURE_LONG_PRESS, type_);
-    return data.touch_id;
-  }
-
-  float first_finger_width() const {
-    CHECK_EQ(ui::ET_GESTURE_TWO_FINGER_TAP, type_);
-    return data.first_finger_enclosing_rectangle.width;
-  }
-
-  float first_finger_height() const {
-    CHECK_EQ(ui::ET_GESTURE_TWO_FINGER_TAP, type_);
-    return data.first_finger_enclosing_rectangle.height;
-  }
-
-  float scale() const {
-    CHECK_EQ(ui::ET_GESTURE_PINCH_UPDATE, type_);
-    return data.scale;
-  }
-
-  bool swipe_left() const {
-    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
-    return data.swipe.left;
-  }
-
-  bool swipe_right() const {
-    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
-    return data.swipe.right;
-  }
-
-  bool swipe_up() const {
-    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
-    return data.swipe.up;
-  }
-
-  bool swipe_down() const {
-    CHECK_EQ(ui::ET_GESTURE_MULTIFINGER_SWIPE, type_);
-    return data.swipe.down;
-  }
-
-  int tap_count() const {
-    CHECK_EQ(ui::ET_GESTURE_TAP, type_);
-    return data.tap_count;
-  }
-
- private:
-  ui::EventType type_;
-  union {
-    struct {  // SCROLL start details.
-      // Distance that caused the scroll to start.  Generally redundant with
-      // the x/y values from the first scroll_update.
-      float x_hint;
-      float y_hint;
-    } scroll_begin;
-
-    struct {  // SCROLL delta.
-      float x;
-      float y;
-      float velocity_x;
-      float velocity_y;
-      float x_ordinal;
-      float y_ordinal;
-      float velocity_x_ordinal;
-      float velocity_y_ordinal;
-    } scroll_update;
-
-    float scale;  // PINCH scale.
-
-    struct {  // FLING velocity.
-      float x;
-      float y;
-      float x_ordinal;
-      float y_ordinal;
-    } fling_velocity;
-
-    int touch_id;  // LONG_PRESS touch-id.
-
-    // Dimensions of the first finger's enclosing rectangle for TWO_FINGER_TAP.
-    struct {
-      float width;
-      float height;
-    } first_finger_enclosing_rectangle;
-
-    struct {  // SWIPE direction.
-      bool left;
-      bool right;
-      bool up;
-      bool down;
-    } swipe;
-
-    int tap_count;  // TAP repeat count.
-  } data;
-
-  int touch_points_;  // Number of active touch points in the gesture.
-
-  // Bounding box is an axis-aligned rectangle that contains all the
-  // enclosing rectangles of the touch-points in the gesture.
-  gfx::RectF bounding_box_;
-};
-
 // An abstract type for consumers of gesture-events created by the
 // gesture-recognizer.
 class EVENTS_EXPORT GestureConsumer {
diff --git a/ui/events/ozone/evdev/event_factory_evdev.cc b/ui/events/ozone/evdev/event_factory_evdev.cc
index e36d8d0..cf9a607 100644
--- a/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -20,6 +20,10 @@
 #include "ui/events/ozone/evdev/device_manager_udev.h"
 #endif
 
+#ifndef EVIOCSCLOCKID
+#define EVIOCSCLOCKID  _IOW('E', 0xa0, int)
+#endif
+
 namespace ui {
 
 namespace {
@@ -56,6 +60,13 @@
     return;
   }
 
+  // Use monotonic timestamps for events. The touch code in particular
+  // expects event timestamps to correlate to the monotonic clock
+  // (base::TimeTicks).
+  unsigned int clk = CLOCK_MONOTONIC;
+  if (ioctl(fd, EVIOCSCLOCKID, &clk))
+    PLOG(ERROR) << "failed to set CLOCK_MONOTONIC";
+
   EventDeviceInfo devinfo;
   if (!devinfo.Initialize(fd)) {
     LOG(ERROR) << "failed to get device information for " << path.value();
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev.cc b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
index 46eda1b..cb78cbe 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev.cc
@@ -131,7 +131,7 @@
           altered_slots_.set(current_slot_);
           break;
         default:
-          NOTREACHED() << "invalid code for EV_ABS: " << input.code;
+          NOTIMPLEMENTED() << "invalid code for EV_ABS: " << input.code;
       }
     } else if (input.type == EV_SYN) {
       switch (input.code) {
@@ -163,7 +163,7 @@
         case SYN_MT_REPORT:
         case SYN_CONFIG:
         case SYN_DROPPED:
-          NOTREACHED() << "invalid code for EV_SYN: " << input.code;
+          NOTIMPLEMENTED() << "invalid code for EV_SYN: " << input.code;
           break;
       }
     } else if (input.type == EV_KEY) {
@@ -171,10 +171,10 @@
         case BTN_TOUCH:
           break;
         default:
-          NOTREACHED() << "invalid code for EV_KEY: " << input.code;
+          NOTIMPLEMENTED() << "invalid code for EV_KEY: " << input.code;
       }
     } else {
-      NOTREACHED() << "invalid type: " << input.type;
+      NOTIMPLEMENTED() << "invalid type: " << input.type;
     }
   }
 }
diff --git a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index 5dbe82c..5fb8886 100644
--- a/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -79,7 +79,7 @@
   int fds[2];
 
   if (pipe(fds))
-    NOTREACHED() << "failed pipe(): " << strerror(errno);
+    PLOG(FATAL) << "failed pipe";
 
   DCHECK(SetNonBlocking(fds[0]) == 0)
       << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
diff --git a/ui/events/platform/platform_event_dispatcher.h b/ui/events/platform/platform_event_dispatcher.h
new file mode 100644
index 0000000..5cc91db
--- /dev/null
+++ b/ui/events/platform/platform_event_dispatcher.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_PLATFORM_EVENT_DISPATCHER_H_
+#define UI_EVENTS_PLATFORM_PLATFORM_EVENT_DISPATCHER_H_
+
+#include "base/basictypes.h"
+#include "ui/events/events_export.h"
+#include "ui/events/platform/platform_event_types.h"
+
+namespace ui {
+
+// See documentation for |PlatformEventDispatcher::DispatchEvent()| for
+// explanation of the meaning of the flags.
+enum PostDispatchAction {
+  POST_DISPATCH_NONE = 0x0,
+  POST_DISPATCH_QUIT_LOOP = 0x1,
+  POST_DISPATCH_PERFORM_DEFAULT = 0x2,
+  POST_DISPATCH_STOP_PROPAGATION = 0x4,
+};
+
+// PlatformEventDispatcher receives events from a PlatformEventSource and
+// dispatches them.
+class EVENTS_EXPORT PlatformEventDispatcher {
+ public:
+  // Returns whether this dispatcher wants to dispatch |event|.
+  virtual bool CanDispatchEvent(const PlatformEvent& event) = 0;
+
+  // Dispatches |event|. If this is not the default dispatcher, then the
+  // dispatcher can request that the default dispatcher gets a chance to
+  // dispatch the event by setting POST_DISPATCH_PERFORM_DEFAULT to the return
+  // value. If a nested message-loop is active, then the dispatcher can signal
+  // that the nested message-loop should be terminated by setting
+  // POST_DISPATCH_QUIT_LOOP flag on the return value. If the dispatcher has
+  // processed the event, and no other dispatcher should be allowed to dispatch
+  // the event, then the dispatcher should set POST_DISPATCH_STOP_PROPAGATION
+  // flag on the return value.
+  virtual uint32_t DispatchEvent(const PlatformEvent& event) = 0;
+
+ protected:
+  virtual ~PlatformEventDispatcher() {}
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_PLATFORM_EVENT_DISPATCHER_H_
diff --git a/ui/events/platform/platform_event_observer.h b/ui/events/platform/platform_event_observer.h
new file mode 100644
index 0000000..bde2733
--- /dev/null
+++ b/ui/events/platform/platform_event_observer.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_PLATFORM_EVENT_OBSERVER_H_
+#define UI_EVENTS_PLATFORM_PLATFORM_EVENT_OBSERVER_H_
+
+#include "ui/events/events_export.h"
+#include "ui/events/platform/platform_event_types.h"
+
+namespace ui {
+
+// PlatformEventObserver can be installed on a PlatformEventSource, and it
+// receives all events that are dispatched to the dispatchers.
+class EVENTS_EXPORT PlatformEventObserver {
+ public:
+  enum EventStatus {
+    EVENT_STATUS_CONTINUE,
+    EVENT_STATUS_HANDLED
+  };
+
+  // This is called before the dispatcher receives the event. The observer can
+  // consume the event and stop the event from reaching the dispatcher or other
+  // observers by returning EVENT_STATUS_HANDLED from this function. The event
+  // dispatch continues as usual if this returns EVENT_STATUS_CONTINUE.
+  virtual EventStatus WillProcessEvent(const PlatformEvent& event) = 0;
+
+  // This is called after the event has been dispatched to the dispatcher(s).
+  virtual void DidProcessEvent(const PlatformEvent& event) = 0;
+
+ protected:
+  virtual ~PlatformEventObserver() {}
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_PLATFORM_EVENT_OBSERVER_H_
diff --git a/ui/events/platform/platform_event_source.cc b/ui/events/platform/platform_event_source.cc
new file mode 100644
index 0000000..ac3d275
--- /dev/null
+++ b/ui/events/platform/platform_event_source.cc
@@ -0,0 +1,135 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/platform/platform_event_source.h"
+
+#include <algorithm>
+
+#include "base/message_loop/message_loop.h"
+#include "ui/events/event.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/events/platform/platform_event_observer.h"
+#include "ui/events/platform/scoped_event_dispatcher.h"
+
+namespace ui {
+
+// static
+PlatformEventSource* PlatformEventSource::instance_ = NULL;
+
+PlatformEventSource::PlatformEventSource()
+    : overridden_dispatcher_(NULL),
+      overridden_dispatcher_restored_(false) {
+  CHECK(!instance_) << "Only one platform event source can be created.";
+  instance_ = this;
+}
+
+PlatformEventSource::~PlatformEventSource() {
+  CHECK_EQ(this, instance_);
+  instance_ = NULL;
+}
+
+PlatformEventSource* PlatformEventSource::GetInstance() { return instance_; }
+
+void PlatformEventSource::AddPlatformEventDispatcher(
+    PlatformEventDispatcher* dispatcher) {
+  CHECK(dispatcher);
+  DCHECK(std::find(dispatchers_.begin(), dispatchers_.end(), dispatcher) ==
+         dispatchers_.end());
+  dispatchers_.push_back(dispatcher);
+}
+
+void PlatformEventSource::RemovePlatformEventDispatcher(
+    PlatformEventDispatcher* dispatcher) {
+  PlatformEventDispatcherList::iterator remove =
+      std::remove(dispatchers_.begin(), dispatchers_.end(), dispatcher);
+  if (remove != dispatchers_.end())
+    dispatchers_.erase(remove);
+}
+
+scoped_ptr<ScopedEventDispatcher> PlatformEventSource::OverrideDispatcher(
+    PlatformEventDispatcher* dispatcher) {
+  CHECK(dispatcher);
+  overridden_dispatcher_restored_ = false;
+  return make_scoped_ptr(
+      new ScopedEventDispatcher(&overridden_dispatcher_, dispatcher));
+}
+
+void PlatformEventSource::AddPlatformEventObserver(
+    PlatformEventObserver* observer) {
+  CHECK(observer);
+  observers_.AddObserver(observer);
+}
+
+void PlatformEventSource::RemovePlatformEventObserver(
+    PlatformEventObserver* observer) {
+  observers_.RemoveObserver(observer);
+}
+
+uint32_t PlatformEventSource::DispatchEvent(PlatformEvent platform_event) {
+  uint32_t action = POST_DISPATCH_PERFORM_DEFAULT;
+  bool should_quit = false;
+
+  if (!WillProcessEvent(platform_event)) {
+    // Give the overridden dispatcher a chance to dispatch the event first.
+    if (overridden_dispatcher_)
+      action = overridden_dispatcher_->DispatchEvent(platform_event);
+    should_quit = !!(action & POST_DISPATCH_QUIT_LOOP);
+
+    if (action & POST_DISPATCH_PERFORM_DEFAULT) {
+      for (PlatformEventDispatcherList::iterator i = dispatchers_.begin();
+           i != dispatchers_.end();
+           ++i) {
+        PlatformEventDispatcher* dispatcher = *(i);
+        if (dispatcher->CanDispatchEvent(platform_event))
+          action = dispatcher->DispatchEvent(platform_event);
+        if (action & POST_DISPATCH_QUIT_LOOP)
+          should_quit = true;
+        if (action & POST_DISPATCH_STOP_PROPAGATION)
+          break;
+      }
+    }
+  }
+  DidProcessEvent(platform_event);
+
+  // Terminate the message-loop if the dispatcher requested for it.
+  if (should_quit) {
+    base::MessageLoop::current()->QuitNow();
+    action |= POST_DISPATCH_QUIT_LOOP;
+  }
+
+  // If an overridden dispatcher has been destroyed, then the platform
+  // event-source should halt dispatching the current stream of events, and wait
+  // until the next message-loop iteration for dispatching events. This lets any
+  // nested message-loop to unwind correctly and any new dispatchers to receive
+  // the correct sequence of events.
+  if (overridden_dispatcher_restored_)
+    action |= POST_DISPATCH_QUIT_LOOP;
+
+  overridden_dispatcher_restored_ = false;
+
+  return action;
+}
+
+bool PlatformEventSource::WillProcessEvent(PlatformEvent event) {
+  if (observers_.might_have_observers()) {
+    ObserverListBase<PlatformEventObserver>::Iterator it(observers_);
+    PlatformEventObserver* obs;
+    while ((obs = it.GetNext()) != NULL) {
+      if (obs->WillProcessEvent(event))
+        return true;
+    }
+  }
+  return false;
+}
+
+void PlatformEventSource::DidProcessEvent(PlatformEvent event) {
+  FOR_EACH_OBSERVER(PlatformEventObserver, observers_, DidProcessEvent(event));
+}
+
+void PlatformEventSource::OnOverriddenDispatcherRestored() {
+  CHECK(overridden_dispatcher_);
+  overridden_dispatcher_restored_ = true;
+}
+
+}  // namespace ui
diff --git a/ui/events/platform/platform_event_source.h b/ui/events/platform/platform_event_source.h
new file mode 100644
index 0000000..ce2cda9
--- /dev/null
+++ b/ui/events/platform/platform_event_source.h
@@ -0,0 +1,88 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_PLATFORM_EVENT_SOURCE_H_
+#define UI_EVENTS_PLATFORM_PLATFORM_EVENT_SOURCE_H_
+
+#include <map>
+#include <vector>
+
+#include "base/auto_reset.h"
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "ui/events/events_export.h"
+#include "ui/events/platform/platform_event_types.h"
+
+namespace ui {
+
+class Event;
+class PlatformEventDispatcher;
+class PlatformEventObserver;
+class ScopedEventDispatcher;
+
+// PlatformEventSource receives events from a source and dispatches the events
+// to the appropriate dispatchers.
+class EVENTS_EXPORT PlatformEventSource {
+ public:
+  virtual ~PlatformEventSource();
+
+  static PlatformEventSource* GetInstance();
+
+  void AddPlatformEventDispatcher(PlatformEventDispatcher* dispatcher);
+  void RemovePlatformEventDispatcher(PlatformEventDispatcher* dispatcher);
+
+  // Installs a PlatformEventDispatcher that receives all the events. The
+  // dispatcher can process the event, or request that the default dispatchers
+  // be invoked by setting |POST_DISPATCH_PERFORM_DEFAULT| flag from the
+  // |DispatchEvent()| override.
+  // The returned |ScopedEventDispatcher| object is a handler for the overridden
+  // dispatcher. When this handler is destroyed, it removes the overridden
+  // dispatcher, and restores the previous override-dispatcher (or NULL if there
+  // wasn't any).
+  scoped_ptr<ScopedEventDispatcher> OverrideDispatcher(
+      PlatformEventDispatcher* dispatcher);
+
+  void AddPlatformEventObserver(PlatformEventObserver* observer);
+  void RemovePlatformEventObserver(PlatformEventObserver* observer);
+
+ protected:
+  PlatformEventSource();
+
+  // Dispatches |platform_event| to the dispatchers. If there is an override
+  // dispatcher installed using |OverrideDispatcher()|, then that dispatcher
+  // receives the event first. |POST_DISPATCH_QUIT_LOOP| flag is set in the
+  // returned value if the event-source should stop dispatching events at the
+  // current message-loop iteration.
+  virtual uint32_t DispatchEvent(PlatformEvent platform_event);
+
+ private:
+  friend class ScopedEventDispatcher;
+  static PlatformEventSource* instance_;
+
+  void OnOverriddenDispatcherRestored();
+
+  // Invokes the corresponding methods on the PlatformEventObservers added to
+  // the event-source.
+  // Returns true from |WillProcessEvent()| if any of the observers in the list
+  // consumes the event and returns true from |WillProcessEvent()|.
+  bool WillProcessEvent(PlatformEvent platform_event);
+  void DidProcessEvent(PlatformEvent platform_event);
+
+  typedef std::vector<PlatformEventDispatcher*> PlatformEventDispatcherList;
+  PlatformEventDispatcherList dispatchers_;
+  PlatformEventDispatcher* overridden_dispatcher_;
+
+  // Used to keep track of whether the current override-dispatcher has been
+  // reset and a previous override-dispatcher has been restored.
+  bool overridden_dispatcher_restored_;
+
+  ObserverList<PlatformEventObserver> observers_;
+
+  DISALLOW_COPY_AND_ASSIGN(PlatformEventSource);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_PLATFORM_EVENT_SOURCE_H_
diff --git a/ui/events/platform/platform_event_source_unittest.cc b/ui/events/platform/platform_event_source_unittest.cc
new file mode 100644
index 0000000..56aef35
--- /dev/null
+++ b/ui/events/platform/platform_event_source_unittest.cc
@@ -0,0 +1,609 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/platform/platform_event_source.h"
+
+#include "base/bind.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+#include "ui/events/platform/platform_event_observer.h"
+#include "ui/events/platform/scoped_event_dispatcher.h"
+
+namespace ui {
+
+namespace {
+
+scoped_ptr<PlatformEvent> CreatePlatformEvent() {
+  scoped_ptr<PlatformEvent> event(new PlatformEvent());
+  memset(event.get(), 0, sizeof(PlatformEvent));
+  return event.Pass();
+}
+
+template <typename T>
+void DestroyScopedPtr(scoped_ptr<T> object) {}
+
+}  // namespace
+
+class TestPlatformEventSource : public PlatformEventSource {
+ public:
+  TestPlatformEventSource() {}
+  virtual ~TestPlatformEventSource() {}
+
+  uint32_t Dispatch(const PlatformEvent& event) { return DispatchEvent(event); }
+
+  // Dispatches the stream of events, and returns the number of events that are
+  // dispatched before it is requested to stop.
+  size_t DispatchEventStream(const ScopedVector<PlatformEvent>& events) {
+    for (size_t count = 0; count < events.size(); ++count) {
+      uint32_t action = DispatchEvent(*events[count]);
+      if (action & POST_DISPATCH_QUIT_LOOP)
+        return count + 1;
+    }
+    return events.size();
+  }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(TestPlatformEventSource);
+};
+
+class TestPlatformEventDispatcher : public PlatformEventDispatcher {
+ public:
+  TestPlatformEventDispatcher(int id, std::vector<int>* list)
+      : id_(id), list_(list), post_dispatch_action_(POST_DISPATCH_NONE) {
+    PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
+  }
+  virtual ~TestPlatformEventDispatcher() {
+    PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
+  }
+
+  void set_post_dispatch_action(uint32_t action) {
+    post_dispatch_action_ = action;
+  }
+
+ protected:
+  // PlatformEventDispatcher:
+  virtual bool CanDispatchEvent(const PlatformEvent& event) OVERRIDE {
+    return true;
+  }
+
+  virtual uint32_t DispatchEvent(const PlatformEvent& event) OVERRIDE {
+    list_->push_back(id_);
+    return post_dispatch_action_;
+  }
+
+ private:
+  int id_;
+  std::vector<int>* list_;
+  uint32_t post_dispatch_action_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestPlatformEventDispatcher);
+};
+
+class TestPlatformEventObserver : public PlatformEventObserver {
+ public:
+  TestPlatformEventObserver(int id, std::vector<int>* list)
+      : id_(id), list_(list), consume_event_(false) {
+    PlatformEventSource::GetInstance()->AddPlatformEventObserver(this);
+  }
+  virtual ~TestPlatformEventObserver() {
+    PlatformEventSource::GetInstance()->RemovePlatformEventObserver(this);
+  }
+
+  void set_consume_event(bool consume) { consume_event_ = consume; }
+
+ protected:
+  // PlatformEventObserver:
+  virtual EventStatus WillProcessEvent(const PlatformEvent& event) OVERRIDE {
+    list_->push_back(id_);
+    return consume_event_ ? EVENT_STATUS_HANDLED : EVENT_STATUS_CONTINUE;
+  }
+
+  virtual void DidProcessEvent(const PlatformEvent& event) OVERRIDE {}
+
+ private:
+  int id_;
+  std::vector<int>* list_;
+  bool consume_event_;
+
+  DISALLOW_COPY_AND_ASSIGN(TestPlatformEventObserver);
+};
+
+class PlatformEventTest : public testing::Test {
+ public:
+  PlatformEventTest() {}
+  virtual ~PlatformEventTest() {}
+
+  TestPlatformEventSource* source() { return source_.get(); }
+
+ protected:
+  // testing::Test:
+  virtual void SetUp() OVERRIDE {
+    source_.reset(new TestPlatformEventSource());
+  }
+
+ private:
+  scoped_ptr<TestPlatformEventSource> source_;
+
+  DISALLOW_COPY_AND_ASSIGN(PlatformEventTest);
+};
+
+// Tests that a dispatcher receives an event.
+TEST_F(PlatformEventTest, DispatcherBasic) {
+  std::vector<int> list_dispatcher;
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  EXPECT_EQ(0u, list_dispatcher.size());
+  {
+    TestPlatformEventDispatcher dispatcher(1, &list_dispatcher);
+
+    scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+    source()->Dispatch(*event);
+    ASSERT_EQ(1u, list_dispatcher.size());
+    EXPECT_EQ(1, list_dispatcher[0]);
+  }
+
+  list_dispatcher.clear();
+  event = CreatePlatformEvent();
+  source()->Dispatch(*event);
+  EXPECT_EQ(0u, list_dispatcher.size());
+}
+
+// Tests that dispatchers receive events in the correct order.
+TEST_F(PlatformEventTest, DispatcherOrder) {
+  std::vector<int> list_dispatcher;
+  int sequence[] = {21, 3, 6, 45};
+  ScopedVector<TestPlatformEventDispatcher> dispatchers;
+  for (size_t i = 0; i < arraysize(sequence); ++i) {
+    dispatchers.push_back(
+        new TestPlatformEventDispatcher(sequence[i], &list_dispatcher));
+  }
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  ASSERT_EQ(arraysize(sequence), list_dispatcher.size());
+  EXPECT_EQ(std::vector<int>(sequence, sequence + arraysize(sequence)),
+            list_dispatcher);
+}
+
+// Tests that if a dispatcher consumes the event, the subsequent dispatchers do
+// not receive the event.
+TEST_F(PlatformEventTest, DispatcherConsumesEventToStopDispatch) {
+  std::vector<int> list_dispatcher;
+  TestPlatformEventDispatcher first(12, &list_dispatcher);
+  TestPlatformEventDispatcher second(23, &list_dispatcher);
+
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  ASSERT_EQ(2u, list_dispatcher.size());
+  EXPECT_EQ(12, list_dispatcher[0]);
+  EXPECT_EQ(23, list_dispatcher[1]);
+  list_dispatcher.clear();
+
+  first.set_post_dispatch_action(POST_DISPATCH_STOP_PROPAGATION);
+  event = CreatePlatformEvent();
+  source()->Dispatch(*event);
+  ASSERT_EQ(1u, list_dispatcher.size());
+  EXPECT_EQ(12, list_dispatcher[0]);
+}
+
+// Tests that observers receive events.
+TEST_F(PlatformEventTest, ObserverBasic) {
+  std::vector<int> list_observer;
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  EXPECT_EQ(0u, list_observer.size());
+  {
+    TestPlatformEventObserver observer(31, &list_observer);
+
+    scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+    source()->Dispatch(*event);
+    ASSERT_EQ(1u, list_observer.size());
+    EXPECT_EQ(31, list_observer[0]);
+  }
+
+  list_observer.clear();
+  event = CreatePlatformEvent();
+  source()->Dispatch(*event);
+  EXPECT_EQ(0u, list_observer.size());
+}
+
+// Tests that observers receive events in the correct order.
+TEST_F(PlatformEventTest, ObserverOrder) {
+  std::vector<int> list_observer;
+  const int sequence[] = {21, 3, 6, 45};
+  ScopedVector<TestPlatformEventObserver> observers;
+  for (size_t i = 0; i < arraysize(sequence); ++i) {
+    observers.push_back(
+        new TestPlatformEventObserver(sequence[i], &list_observer));
+  }
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  ASSERT_EQ(arraysize(sequence), list_observer.size());
+  EXPECT_EQ(std::vector<int>(sequence, sequence + arraysize(sequence)),
+            list_observer);
+}
+
+// Tests that observers and dispatchers receive events in the correct order.
+TEST_F(PlatformEventTest, DispatcherAndObserverOrder) {
+  std::vector<int> list;
+  TestPlatformEventDispatcher first_d(12, &list);
+  TestPlatformEventObserver first_o(10, &list);
+  TestPlatformEventDispatcher second_d(23, &list);
+  TestPlatformEventObserver second_o(20, &list);
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  const int expected[] = {10, 20, 12, 23};
+  EXPECT_EQ(std::vector<int>(expected, expected + arraysize(expected)), list);
+}
+
+// Tests that an observer can consume an event and stop its dispatch.
+TEST_F(PlatformEventTest, ObserverConsumesEventToStopDispatch) {
+  std::vector<int> list;
+  TestPlatformEventDispatcher first_d(12, &list);
+  TestPlatformEventObserver first_o(10, &list);
+  TestPlatformEventDispatcher second_d(23, &list);
+  TestPlatformEventObserver second_o(20, &list);
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  const int expected[] = {10, 20, 12, 23};
+  EXPECT_EQ(std::vector<int>(expected, expected + arraysize(expected)), list);
+
+  list.clear();
+  first_o.set_consume_event(true);
+  event = CreatePlatformEvent();
+  source()->Dispatch(*event);
+  ASSERT_EQ(1u, list.size());
+  EXPECT_EQ(10, list[0]);
+}
+
+// Tests that an overridden dispatcher receives events before the default
+// dispatchers.
+TEST_F(PlatformEventTest, OverriddenDispatcherBasic) {
+  std::vector<int> list;
+  TestPlatformEventDispatcher dispatcher(10, &list);
+  TestPlatformEventObserver observer(15, &list);
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  ASSERT_EQ(2u, list.size());
+  EXPECT_EQ(15, list[0]);
+  EXPECT_EQ(10, list[1]);
+  list.clear();
+
+  TestPlatformEventDispatcher overriding_dispatcher(20, &list);
+  source()->RemovePlatformEventDispatcher(&overriding_dispatcher);
+  scoped_ptr<ScopedEventDispatcher> handle =
+      source()->OverrideDispatcher(&overriding_dispatcher);
+  source()->Dispatch(*event);
+  ASSERT_EQ(2u, list.size());
+  EXPECT_EQ(15, list[0]);
+  EXPECT_EQ(20, list[1]);
+}
+
+// Tests that an overridden dispatcher can request that the default dispatchers
+// can dispatch the events.
+TEST_F(PlatformEventTest, OverriddenDispatcherInvokeDefaultDispatcher) {
+  std::vector<int> list;
+  TestPlatformEventDispatcher dispatcher(10, &list);
+  TestPlatformEventObserver observer(15, &list);
+  TestPlatformEventDispatcher overriding_dispatcher(20, &list);
+  source()->RemovePlatformEventDispatcher(&overriding_dispatcher);
+  scoped_ptr<ScopedEventDispatcher> handle =
+      source()->OverrideDispatcher(&overriding_dispatcher);
+  overriding_dispatcher.set_post_dispatch_action(POST_DISPATCH_PERFORM_DEFAULT);
+
+  scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+  source()->Dispatch(*event);
+  // First the observer, then the overriding dispatcher, then the default
+  // dispatcher.
+  ASSERT_EQ(3u, list.size());
+  EXPECT_EQ(15, list[0]);
+  EXPECT_EQ(20, list[1]);
+  EXPECT_EQ(10, list[2]);
+  list.clear();
+
+  // Install a second overriding dispatcher.
+  TestPlatformEventDispatcher second_overriding(50, &list);
+  source()->RemovePlatformEventDispatcher(&second_overriding);
+  scoped_ptr<ScopedEventDispatcher> second_override_handle =
+      source()->OverrideDispatcher(&second_overriding);
+  source()->Dispatch(*event);
+  ASSERT_EQ(2u, list.size());
+  EXPECT_EQ(15, list[0]);
+  EXPECT_EQ(50, list[1]);
+  list.clear();
+
+  second_overriding.set_post_dispatch_action(POST_DISPATCH_PERFORM_DEFAULT);
+  source()->Dispatch(*event);
+  // First the observer, then the second overriding dispatcher, then the default
+  // dispatcher.
+  ASSERT_EQ(3u, list.size());
+  EXPECT_EQ(15, list[0]);
+  EXPECT_EQ(50, list[1]);
+  EXPECT_EQ(10, list[2]);
+}
+
+// Provides mechanism for running tests from inside an active message-loop.
+class PlatformEventTestWithMessageLoop : public PlatformEventTest {
+ public:
+  PlatformEventTestWithMessageLoop() {}
+  virtual ~PlatformEventTestWithMessageLoop() {}
+
+  void Run() {
+    message_loop_.PostTask(
+        FROM_HERE,
+        base::Bind(&PlatformEventTestWithMessageLoop::RunTest,
+                   base::Unretained(this)));
+    message_loop_.Run();
+  }
+
+ protected:
+  void RunTest() {
+    RunTestImpl();
+    message_loop_.Quit();
+  }
+
+  virtual void RunTestImpl() = 0;
+
+ private:
+  base::MessageLoopForUI message_loop_;
+
+  DISALLOW_COPY_AND_ASSIGN(PlatformEventTestWithMessageLoop);
+};
+
+#define RUN_TEST_IN_MESSAGE_LOOP(name) \
+  TEST_F(name, Run) { Run(); }
+
+// Tests that a ScopedEventDispatcher restores the previous dispatcher when
+// destroyed.
+class ScopedDispatcherRestoresAfterDestroy
+    : public PlatformEventTestWithMessageLoop {
+ public:
+  // PlatformEventTestWithMessageLoop:
+  virtual void RunTestImpl() OVERRIDE {
+    std::vector<int> list;
+    TestPlatformEventDispatcher dispatcher(10, &list);
+    TestPlatformEventObserver observer(15, &list);
+
+    TestPlatformEventDispatcher first_overriding(20, &list);
+    source()->RemovePlatformEventDispatcher(&first_overriding);
+    scoped_ptr<ScopedEventDispatcher> first_override_handle =
+        source()->OverrideDispatcher(&first_overriding);
+
+    // Install a second overriding dispatcher.
+    TestPlatformEventDispatcher second_overriding(50, &list);
+    source()->RemovePlatformEventDispatcher(&second_overriding);
+    scoped_ptr<ScopedEventDispatcher> second_override_handle =
+        source()->OverrideDispatcher(&second_overriding);
+
+    scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list.size());
+    EXPECT_EQ(15, list[0]);
+    EXPECT_EQ(50, list[1]);
+    list.clear();
+
+    second_override_handle.reset();
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list.size());
+    EXPECT_EQ(15, list[0]);
+    EXPECT_EQ(20, list[1]);
+  }
+};
+
+RUN_TEST_IN_MESSAGE_LOOP(ScopedDispatcherRestoresAfterDestroy)
+
+// This dispatcher destroys the handle to the ScopedEventDispatcher when
+// dispatching an event.
+class DestroyScopedHandleDispatcher : public TestPlatformEventDispatcher {
+ public:
+  DestroyScopedHandleDispatcher(int id, std::vector<int>* list)
+      : TestPlatformEventDispatcher(id, list) {}
+  virtual ~DestroyScopedHandleDispatcher() {}
+
+  void SetScopedHandle(scoped_ptr<ScopedEventDispatcher> handler) {
+    handler_ = handler.Pass();
+  }
+
+ private:
+  // PlatformEventDispatcher:
+  virtual bool CanDispatchEvent(const PlatformEvent& event) OVERRIDE {
+    return true;
+  }
+
+  virtual uint32_t DispatchEvent(const PlatformEvent& event) OVERRIDE {
+    handler_.reset();
+    return TestPlatformEventDispatcher::DispatchEvent(event);
+  }
+
+  scoped_ptr<ScopedEventDispatcher> handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(DestroyScopedHandleDispatcher);
+};
+
+// Tests that resetting an overridden dispatcher causes the nested message-loop
+// iteration to stop and the rest of the events are dispatched in the next
+// iteration.
+class DestroyedNestedOverriddenDispatcherQuitsNestedLoopIteration
+    : public PlatformEventTestWithMessageLoop {
+ public:
+  void NestedTask(std::vector<int>* list,
+                  TestPlatformEventDispatcher* dispatcher) {
+    ScopedVector<PlatformEvent> events;
+    scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+    events.push_back(event.release());
+    event = CreatePlatformEvent();
+    events.push_back(event.release());
+
+    // Attempt to dispatch a couple of events. Dispatching the first event will
+    // have terminated the ScopedEventDispatcher object, which will terminate
+    // the current iteration of the message-loop.
+    size_t count = source()->DispatchEventStream(events);
+    EXPECT_EQ(1u, count);
+    ASSERT_EQ(2u, list->size());
+    EXPECT_EQ(15, (*list)[0]);
+    EXPECT_EQ(20, (*list)[1]);
+    list->clear();
+
+    ASSERT_LT(count, events.size());
+    events.erase(events.begin(), events.begin() + count);
+
+    count = source()->DispatchEventStream(events);
+    EXPECT_EQ(1u, count);
+    ASSERT_EQ(2u, list->size());
+    EXPECT_EQ(15, (*list)[0]);
+    EXPECT_EQ(10, (*list)[1]);
+    list->clear();
+
+    // Terminate the message-loop.
+    base::MessageLoopForUI::current()->QuitNow();
+  }
+
+  // PlatformEventTestWithMessageLoop:
+  virtual void RunTestImpl() OVERRIDE {
+    std::vector<int> list;
+    TestPlatformEventDispatcher dispatcher(10, &list);
+    TestPlatformEventObserver observer(15, &list);
+
+    DestroyScopedHandleDispatcher overriding(20, &list);
+    source()->RemovePlatformEventDispatcher(&overriding);
+    scoped_ptr<ScopedEventDispatcher> override_handle =
+        source()->OverrideDispatcher(&overriding);
+
+    scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list.size());
+    EXPECT_EQ(15, list[0]);
+    EXPECT_EQ(20, list[1]);
+    list.clear();
+
+    overriding.SetScopedHandle(override_handle.Pass());
+    base::RunLoop run_loop;
+    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+    base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
+    loop->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &DestroyedNestedOverriddenDispatcherQuitsNestedLoopIteration::
+                NestedTask,
+            base::Unretained(this),
+            base::Unretained(&list),
+            base::Unretained(&overriding)));
+    run_loop.Run();
+
+    // Dispatching the event should now reach the default dispatcher.
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list.size());
+    EXPECT_EQ(15, list[0]);
+    EXPECT_EQ(10, list[1]);
+  }
+};
+
+RUN_TEST_IN_MESSAGE_LOOP(
+    DestroyedNestedOverriddenDispatcherQuitsNestedLoopIteration)
+
+// Tests that resetting an overridden dispatcher, and installing another
+// overridden dispatcher before the nested message-loop completely unwinds
+// function correctly.
+class ConsecutiveOverriddenDispatcherInTheSameMessageLoopIteration
+    : public PlatformEventTestWithMessageLoop {
+ public:
+  void NestedTask(scoped_ptr<ScopedEventDispatcher> dispatch_handle,
+                  std::vector<int>* list) {
+    scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list->size());
+    EXPECT_EQ(15, (*list)[0]);
+    EXPECT_EQ(20, (*list)[1]);
+    list->clear();
+
+    // Reset the override dispatcher. This should restore the default
+    // dispatcher.
+    dispatch_handle.reset();
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list->size());
+    EXPECT_EQ(15, (*list)[0]);
+    EXPECT_EQ(10, (*list)[1]);
+    list->clear();
+
+    // Install another override-dispatcher.
+    DestroyScopedHandleDispatcher second_overriding(70, list);
+    source()->RemovePlatformEventDispatcher(&second_overriding);
+    scoped_ptr<ScopedEventDispatcher> second_override_handle =
+        source()->OverrideDispatcher(&second_overriding);
+
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list->size());
+    EXPECT_EQ(15, (*list)[0]);
+    EXPECT_EQ(70, (*list)[1]);
+    list->clear();
+
+    second_overriding.SetScopedHandle(second_override_handle.Pass());
+    second_overriding.set_post_dispatch_action(POST_DISPATCH_QUIT_LOOP);
+    base::RunLoop run_loop;
+    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+    base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
+    loop->PostTask(
+        FROM_HERE,
+        base::Bind(base::IgnoreResult(&TestPlatformEventSource::Dispatch),
+                   base::Unretained(source()),
+                   *event));
+    run_loop.Run();
+    ASSERT_EQ(2u, list->size());
+    EXPECT_EQ(15, (*list)[0]);
+    EXPECT_EQ(70, (*list)[1]);
+    list->clear();
+
+    // Terminate the message-loop.
+    base::MessageLoopForUI::current()->QuitNow();
+  }
+
+  // PlatformEventTestWithMessageLoop:
+  virtual void RunTestImpl() OVERRIDE {
+    std::vector<int> list;
+    TestPlatformEventDispatcher dispatcher(10, &list);
+    TestPlatformEventObserver observer(15, &list);
+
+    TestPlatformEventDispatcher overriding(20, &list);
+    source()->RemovePlatformEventDispatcher(&overriding);
+    scoped_ptr<ScopedEventDispatcher> override_handle =
+        source()->OverrideDispatcher(&overriding);
+
+    scoped_ptr<PlatformEvent> event(CreatePlatformEvent());
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list.size());
+    EXPECT_EQ(15, list[0]);
+    EXPECT_EQ(20, list[1]);
+    list.clear();
+
+    // Start a nested message-loop, and destroy |override_handle| in the nested
+    // loop. That should terminate the nested loop, restore the previous
+    // dispatchers, and return control to this function.
+    base::RunLoop run_loop;
+    base::MessageLoopForUI* loop = base::MessageLoopForUI::current();
+    base::MessageLoopForUI::ScopedNestableTaskAllower allow_nested(loop);
+    loop->PostTask(
+        FROM_HERE,
+        base::Bind(
+            &ConsecutiveOverriddenDispatcherInTheSameMessageLoopIteration::
+                NestedTask,
+            base::Unretained(this),
+            base::Passed(&override_handle),
+            base::Unretained(&list)));
+    run_loop.Run();
+
+    // Dispatching the event should now reach the default dispatcher.
+    source()->Dispatch(*event);
+    ASSERT_EQ(2u, list.size());
+    EXPECT_EQ(15, list[0]);
+    EXPECT_EQ(10, list[1]);
+  }
+};
+
+RUN_TEST_IN_MESSAGE_LOOP(
+    ConsecutiveOverriddenDispatcherInTheSameMessageLoopIteration)
+
+}  // namespace ui
diff --git a/ui/events/platform/platform_event_types.h b/ui/events/platform/platform_event_types.h
new file mode 100644
index 0000000..dedb38f
--- /dev/null
+++ b/ui/events/platform/platform_event_types.h
@@ -0,0 +1,14 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_PLATFORM_EVENT_TYPES_H_
+#define UI_EVENTS_PLATFORM_PLATFORM_EVENT_TYPES_H_
+
+#include "base/event_types.h"
+
+namespace ui {
+typedef base::NativeEvent PlatformEvent;
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_PLATFORM_EVENT_TYPES_H_
diff --git a/ui/events/platform/scoped_event_dispatcher.cc b/ui/events/platform/scoped_event_dispatcher.cc
new file mode 100644
index 0000000..b0941ab
--- /dev/null
+++ b/ui/events/platform/scoped_event_dispatcher.cc
@@ -0,0 +1,21 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/platform/scoped_event_dispatcher.h"
+
+#include "ui/events/platform/platform_event_source.h"
+
+namespace ui {
+
+ScopedEventDispatcher::ScopedEventDispatcher(
+    PlatformEventDispatcher** scoped_dispatcher,
+    PlatformEventDispatcher* new_dispatcher)
+    : original_(*scoped_dispatcher),
+      restore_(scoped_dispatcher, new_dispatcher) {}
+
+ScopedEventDispatcher::~ScopedEventDispatcher() {
+  PlatformEventSource::GetInstance()->OnOverriddenDispatcherRestored();
+}
+
+}  // namespace ui
diff --git a/ui/events/platform/scoped_event_dispatcher.h b/ui/events/platform/scoped_event_dispatcher.h
new file mode 100644
index 0000000..a2f5294
--- /dev/null
+++ b/ui/events/platform/scoped_event_dispatcher.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_SCOPED_EVENT_DISPATCHER_H_
+#define UI_EVENTS_PLATFORM_SCOPED_EVENT_DISPATCHER_H_
+
+#include "base/auto_reset.h"
+#include "base/basictypes.h"
+#include "ui/events/events_export.h"
+
+namespace ui {
+
+class PlatformEventDispatcher;
+
+// A temporary PlatformEventDispatcher can be installed on a
+// PlatformEventSource that overrides all installed event dispatchers, and
+// always gets a chance to dispatch the event first. The PlatformEventSource
+// returns a ScopedEventDispatcher object in such cases. This
+// ScopedEventDispatcher object can be used to dispatch the event to any
+// previous overridden dispatcher. When this object is destroyed, it removes the
+// override-dispatcher, and restores the previous override-dispatcher.
+class EVENTS_EXPORT ScopedEventDispatcher {
+ public:
+  ScopedEventDispatcher(PlatformEventDispatcher** scoped_dispatcher,
+                        PlatformEventDispatcher* new_dispatcher);
+  ~ScopedEventDispatcher();
+
+  operator PlatformEventDispatcher*() const { return original_; }
+
+ private:
+  PlatformEventDispatcher* original_;
+  base::AutoReset<PlatformEventDispatcher*> restore_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedEventDispatcher);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_SCOPED_EVENT_DISPATCHER_H_
diff --git a/ui/events/platform/x11/x11_event_source.cc b/ui/events/platform/x11/x11_event_source.cc
new file mode 100644
index 0000000..63cba76
--- /dev/null
+++ b/ui/events/platform/x11/x11_event_source.cc
@@ -0,0 +1,201 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/platform/x11/x11_event_source.h"
+
+#include <glib.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/XKBlib.h>
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "ui/events/platform/platform_event_dispatcher.h"
+
+namespace ui {
+
+namespace {
+
+struct GLibX11Source : public GSource {
+  // Note: The GLibX11Source is created and destroyed by GLib. So its
+  // constructor/destructor may or may not get called.
+  XDisplay* display;
+  GPollFD* poll_fd;
+};
+
+gboolean XSourcePrepare(GSource* source, gint* timeout_ms) {
+  GLibX11Source* gxsource = static_cast<GLibX11Source*>(source);
+  if (XPending(gxsource->display))
+    *timeout_ms = 0;
+  else
+    *timeout_ms = -1;
+  return FALSE;
+}
+
+gboolean XSourceCheck(GSource* source) {
+  GLibX11Source* gxsource = static_cast<GLibX11Source*>(source);
+  return XPending(gxsource->display);
+}
+
+gboolean XSourceDispatch(GSource* source,
+                         GSourceFunc unused_func,
+                         gpointer data) {
+  X11EventSource* x11_source = static_cast<X11EventSource*>(data);
+  x11_source->DispatchXEvents();
+  return TRUE;
+}
+
+GSourceFuncs XSourceFuncs = {
+  XSourcePrepare,
+  XSourceCheck,
+  XSourceDispatch,
+  NULL
+};
+
+int g_xinput_opcode = -1;
+
+bool InitializeXInput2(XDisplay* display) {
+  if (!display)
+    return false;
+
+  int event, err;
+
+  int xiopcode;
+  if (!XQueryExtension(display, "XInputExtension", &xiopcode, &event, &err)) {
+    DVLOG(1) << "X Input extension not available.";
+    return false;
+  }
+  g_xinput_opcode = xiopcode;
+
+#if defined(USE_XI2_MT)
+  // USE_XI2_MT also defines the required XI2 minor minimum version.
+  int major = 2, minor = USE_XI2_MT;
+#else
+  int major = 2, minor = 0;
+#endif
+  if (XIQueryVersion(display, &major, &minor) == BadRequest) {
+    DVLOG(1) << "XInput2 not supported in the server.";
+    return false;
+  }
+#if defined(USE_XI2_MT)
+  if (major < 2 || (major == 2 && minor < USE_XI2_MT)) {
+    DVLOG(1) << "XI version on server is " << major << "." << minor << ". "
+            << "But 2." << USE_XI2_MT << " is required.";
+    return false;
+  }
+#endif
+
+  return true;
+}
+
+bool InitializeXkb(XDisplay* display) {
+  if (!display)
+    return false;
+
+  int opcode, event, error;
+  int major = XkbMajorVersion;
+  int minor = XkbMinorVersion;
+  if (!XkbQueryExtension(display, &opcode, &event, &error, &major, &minor)) {
+    DVLOG(1) << "Xkb extension not available.";
+    return false;
+  }
+
+  // Ask the server not to send KeyRelease event when the user holds down a key.
+  // crbug.com/138092
+  Bool supported_return;
+  if (!XkbSetDetectableAutoRepeat(display, True, &supported_return)) {
+    DVLOG(1) << "XKB not supported in the server.";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+X11EventSource::X11EventSource(XDisplay* display)
+    : display_(display),
+      x_source_(NULL) {
+  CHECK(display_);
+  InitializeXInput2(display_);
+  InitializeXkb(display_);
+
+  InitXSource();
+}
+
+X11EventSource::~X11EventSource() {
+  g_source_destroy(x_source_);
+  g_source_unref(x_source_);
+}
+
+// static
+X11EventSource* X11EventSource::GetInstance() {
+  return static_cast<X11EventSource*>(PlatformEventSource::GetInstance());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// X11EventSource, public
+
+void X11EventSource::DispatchXEvents() {
+  DCHECK(display_);
+  // Handle all pending events.
+  // It may be useful to eventually align this event dispatch with vsync, but
+  // not yet.
+  while (XPending(display_)) {
+    XEvent xevent;
+    XNextEvent(display_, &xevent);
+    uint32_t action = DispatchEvent(&xevent);
+    if (action & POST_DISPATCH_QUIT_LOOP)
+      break;
+  }
+}
+
+void X11EventSource::BlockUntilWindowMapped(XID window) {
+  XEvent event;
+  do {
+    // Block until there's a message of |event_mask| type on |w|. Then remove
+    // it from the queue and stuff it in |event|.
+    XWindowEvent(display_, window, StructureNotifyMask, &event);
+    DispatchEvent(&event);
+  } while (event.type != MapNotify);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// X11EventSource, private
+
+void X11EventSource::InitXSource() {
+  CHECK(!x_source_);
+  CHECK(display_) << "Unable to get connection to X server";
+
+  x_poll_.reset(new GPollFD());
+  x_poll_->fd = ConnectionNumber(display_);
+  x_poll_->events = G_IO_IN;
+  x_poll_->revents = 0;
+
+  GLibX11Source* glib_x_source = static_cast<GLibX11Source*>
+      (g_source_new(&XSourceFuncs, sizeof(GLibX11Source)));
+  glib_x_source->display = display_;
+  glib_x_source->poll_fd = x_poll_.get();
+
+  x_source_ = glib_x_source;
+  g_source_add_poll(x_source_, x_poll_.get());
+  g_source_set_can_recurse(x_source_, TRUE);
+  g_source_set_callback(x_source_, NULL, this, NULL);
+  g_source_attach(x_source_, g_main_context_default());
+}
+
+uint32_t X11EventSource::DispatchEvent(XEvent* xevent) {
+  bool have_cookie = false;
+  if (xevent->type == GenericEvent &&
+      XGetEventData(xevent->xgeneric.display, &xevent->xcookie)) {
+    have_cookie = true;
+  }
+  int action = PlatformEventSource::DispatchEvent(xevent);
+  if (have_cookie)
+    XFreeEventData(xevent->xgeneric.display, &xevent->xcookie);
+  return action;
+}
+
+}  // namespace ui
diff --git a/ui/events/platform/x11/x11_event_source.h b/ui/events/platform/x11/x11_event_source.h
new file mode 100644
index 0000000..93a371e
--- /dev/null
+++ b/ui/events/platform/x11/x11_event_source.h
@@ -0,0 +1,65 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_H_
+#define UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/events/events_export.h"
+#include "ui/events/platform/platform_event_source.h"
+#include "ui/gfx/x/x11_types.h"
+
+typedef struct _GPollFD GPollFD;
+typedef struct _GSource GSource;
+typedef union _XEvent XEvent;
+typedef unsigned long XID;
+
+namespace ui {
+
+// A PlatformEventSource implementation for reading events from X11 server and
+// dispatching the events to the appropriate dispatcher.
+class EVENTS_EXPORT X11EventSource : public PlatformEventSource {
+ public:
+  explicit X11EventSource(XDisplay* display);
+  virtual ~X11EventSource();
+
+  static X11EventSource* GetInstance();
+
+  // Called by the glib source dispatch function. Processes all (if any)
+  // available X events.
+  void DispatchXEvents();
+
+  // Blocks on the X11 event queue until we receive notification from the
+  // xserver that |w| has been mapped; StructureNotifyMask events on |w| are
+  // pulled out from the queue and dispatched out of order.
+  //
+  // For those that know X11, this is really a wrapper around XWindowEvent
+  // which still makes sure the preempted event is dispatched instead of
+  // dropped on the floor. This method exists because mapping a window is
+  // asynchronous (and we receive an XEvent when mapped), while there are also
+  // functions which require a mapped window.
+  void BlockUntilWindowMapped(XID window);
+
+ private:
+  // Initializes the glib event source for X.
+  void InitXSource();
+
+  // PlatformEventSource:
+  virtual uint32_t DispatchEvent(XEvent* xevent) OVERRIDE;
+
+  // The connection to the X11 server used to receive the events.
+  XDisplay* display_;
+
+  // The GLib event source for X events.
+  GSource* x_source_;
+
+  // The poll attached to |x_source_|.
+  scoped_ptr<GPollFD> x_poll_;
+
+  DISALLOW_COPY_AND_ASSIGN(X11EventSource);
+};
+
+}  // namespace ui
+
+#endif  // UI_EVENTS_PLATFORM_X11_X11_EVENT_SOURCE_H_
diff --git a/ui/events/test/test_event_handler.cc b/ui/events/test/test_event_handler.cc
index 19b7191..f97aad5 100644
--- a/ui/events/test/test_event_handler.cc
+++ b/ui/events/test/test_event_handler.cc
@@ -14,7 +14,9 @@
       num_mouse_events_(0),
       num_scroll_events_(0),
       num_touch_events_(0),
-      num_gesture_events_(0) {
+      num_gesture_events_(0),
+      recorder_(NULL),
+      handler_name_("unknown") {
 }
 
 TestEventHandler::~TestEventHandler() {}
@@ -28,23 +30,33 @@
 }
 
 void TestEventHandler::OnKeyEvent(KeyEvent* event) {
+  if (recorder_)
+    recorder_->push_back(handler_name_);
   num_key_events_++;
   event->SetHandled();
 }
 
 void TestEventHandler::OnMouseEvent(MouseEvent* event) {
+  if (recorder_)
+    recorder_->push_back(handler_name_);
   num_mouse_events_++;
 }
 
 void TestEventHandler::OnScrollEvent(ScrollEvent* event) {
+  if (recorder_)
+    recorder_->push_back(handler_name_);
   num_scroll_events_++;
 }
 
 void TestEventHandler::OnTouchEvent(TouchEvent* event) {
+  if (recorder_)
+    recorder_->push_back(handler_name_);
   num_touch_events_++;
 }
 
 void TestEventHandler::OnGestureEvent(GestureEvent* event) {
+  if (recorder_)
+    recorder_->push_back(handler_name_);
   num_gesture_events_++;
 }
 
diff --git a/ui/events/test/test_event_handler.h b/ui/events/test/test_event_handler.h
index e0c2fca..8937b25 100644
--- a/ui/events/test/test_event_handler.h
+++ b/ui/events/test/test_event_handler.h
@@ -5,10 +5,15 @@
 #ifndef UI_EVENTS_TEST_TEST_EVENT_HANDLER_H_
 #define UI_EVENTS_TEST_TEST_EVENT_HANDLER_H_
 
+#include <string>
+#include <vector>
+
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "ui/events/event_handler.h"
 
+typedef std::vector<std::string> HandlerSequenceRecorder;
+
 namespace ui {
 namespace test {
 
@@ -27,6 +32,13 @@
 
   void Reset();
 
+  void set_recorder(HandlerSequenceRecorder* recorder) {
+    recorder_ = recorder;
+  }
+  void set_handler_name(const std::string& handler_name) {
+    handler_name_ = handler_name;
+  }
+
   // EventHandler overrides:
   virtual void OnKeyEvent(KeyEvent* event) OVERRIDE;
   virtual void OnMouseEvent(MouseEvent* event) OVERRIDE;
@@ -42,6 +54,9 @@
   int num_touch_events_;
   int num_gesture_events_;
 
+  HandlerSequenceRecorder* recorder_;
+  std::string handler_name_;
+
   DISALLOW_COPY_AND_ASSIGN(TestEventHandler);
 };
 
diff --git a/ui/events/test/test_event_target.cc b/ui/events/test/test_event_target.cc
index 68d2eb2..1274dd5 100644
--- a/ui/events/test/test_event_target.cc
+++ b/ui/events/test/test_event_target.cc
@@ -12,7 +12,10 @@
 namespace test {
 
 TestEventTarget::TestEventTarget()
-    : parent_(NULL) {}
+    : parent_(NULL),
+      mark_events_as_handled_(false),
+      recorder_(NULL),
+      target_name_("unknown") {}
 TestEventTarget::~TestEventTarget() {}
 
 void TestEventTarget::AddChild(scoped_ptr<TestEventTarget> child) {
@@ -70,8 +73,12 @@
 }
 
 void TestEventTarget::OnEvent(Event* event) {
+  if (recorder_)
+    recorder_->push_back(target_name_);
   received_.insert(event->type());
   EventTarget::OnEvent(event);
+  if (!event->handled() && mark_events_as_handled_)
+    event->SetHandled();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/events/test/test_event_target.h b/ui/events/test/test_event_target.h
index 43994ff..368e295 100644
--- a/ui/events/test/test_event_target.h
+++ b/ui/events/test/test_event_target.h
@@ -6,10 +6,14 @@
 #define UI_EVENTS_TEST_TEST_EVENT_TARGET_H_
 
 #include <set>
+#include <string>
+#include <vector>
 
 #include "base/memory/scoped_vector.h"
 #include "ui/events/event_target.h"
 
+typedef std::vector<std::string> HandlerSequenceRecorder;
+
 namespace gfx {
 class Point;
 }
@@ -27,6 +31,10 @@
 
   TestEventTarget* parent() { return parent_; }
 
+  void set_mark_events_as_handled(bool handle) {
+    mark_events_as_handled_ = handle;
+  }
+
   TestEventTarget* child_at(int index) { return children_[index]; }
   size_t child_count() const { return children_.size(); }
 
@@ -35,6 +43,13 @@
   bool DidReceiveEvent(ui::EventType type) const;
   void ResetReceivedEvents();
 
+  void set_recorder(HandlerSequenceRecorder* recorder) {
+    recorder_ = recorder;
+  }
+  void set_target_name(const std::string& target_name) {
+    target_name_ = target_name;
+  }
+
  protected:
   bool Contains(TestEventTarget* target) const;
 
@@ -53,9 +68,13 @@
   TestEventTarget* parent_;
   ScopedVector<TestEventTarget> children_;
   scoped_ptr<EventTargeter> targeter_;
+  bool mark_events_as_handled_;
 
   std::set<ui::EventType> received_;
 
+  HandlerSequenceRecorder* recorder_;
+  std::string target_name_;
+
   DISALLOW_COPY_AND_ASSIGN(TestEventTarget);
 };
 
diff --git a/ui/gfx/android/java_bitmap.cc b/ui/gfx/android/java_bitmap.cc
index 844385b..90df12a 100644
--- a/ui/gfx/android/java_bitmap.cc
+++ b/ui/gfx/android/java_bitmap.cc
@@ -9,7 +9,6 @@
 #include "base/android/jni_string.h"
 #include "base/logging.h"
 #include "jni/BitmapHelper_jni.h"
-#include "skia/ext/image_operations.h"
 #include "ui/gfx/size.h"
 
 using base::android::AttachCurrentThread;
@@ -61,13 +60,27 @@
 ScopedJavaLocalRef<jobject> CreateJavaBitmap(int width,
                                              int height,
                                              SkBitmap::Config bitmap_config) {
+  DCHECK_GT(width, 0);
+  DCHECK_GT(height, 0);
   int java_bitmap_config = SkBitmapConfigToBitmapFormat(bitmap_config);
   return Java_BitmapHelper_createBitmap(
       AttachCurrentThread(), width, height, java_bitmap_config);
 }
 
+ScopedJavaLocalRef<jobject> CreateJavaBitmapFromAndroidResource(
+    const char* name,
+    gfx::Size size) {
+  DCHECK(name);
+  DCHECK(!size.IsEmpty());
+  JNIEnv* env = AttachCurrentThread();
+  ScopedJavaLocalRef<jstring> jname(env, env->NewStringUTF(name));
+  return Java_BitmapHelper_decodeDrawableResource(
+      env, jname.obj(), size.width(), size.height());
+}
+
 ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(const SkBitmap* skbitmap) {
   DCHECK(skbitmap);
+  DCHECK(!skbitmap->isNull());
   SkBitmap::Config bitmap_config = skbitmap->getConfig();
   DCHECK((bitmap_config == SkBitmap::kRGB_565_Config) ||
          (bitmap_config == SkBitmap::kARGB_8888_Config));
@@ -82,8 +95,13 @@
   return jbitmap;
 }
 
-SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap) {
-  DCHECK_EQ(jbitmap.format(), ANDROID_BITMAP_FORMAT_RGBA_8888);
+SkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap) {
+  // TODO(jdduke): Convert to DCHECK's when sufficient data has been capture for
+  // crbug.com/341406.
+  CHECK_EQ(jbitmap.format(), ANDROID_BITMAP_FORMAT_RGBA_8888);
+  CHECK(!jbitmap.size().IsEmpty());
+  CHECK_GT(jbitmap.stride(), 0U);
+  CHECK(jbitmap.pixels());
 
   gfx::Size src_size = jbitmap.size();
 
@@ -97,30 +115,13 @@
                << "x" << src_size.height() << " stride=" << jbitmap.stride();
   }
   SkAutoLockPixels dst_lock(skbitmap);
-  void* src_pixels = jbitmap.pixels();
+  const void* src_pixels = jbitmap.pixels();
   void* dst_pixels = skbitmap.getPixels();
-  CHECK(src_pixels);
-
   memcpy(dst_pixels, src_pixels, skbitmap.getSize());
 
   return skbitmap;
 }
 
-SkBitmap CreateSkBitmapFromResource(const char* name, gfx::Size size) {
-  DCHECK(!size.IsEmpty());
-  JNIEnv* env = AttachCurrentThread();
-  ScopedJavaLocalRef<jstring> jname(env, env->NewStringUTF(name));
-  ScopedJavaLocalRef<jobject> jobj(Java_BitmapHelper_decodeDrawableResource(
-      env, jname.obj(), size.width(), size.height()));
-  if (jobj.is_null())
-    return SkBitmap();
-
-  JavaBitmap jbitmap(jobj.obj());
-  SkBitmap bitmap = CreateSkBitmapFromJavaBitmap(jbitmap);
-  return skia::ImageOperations::Resize(
-      bitmap, skia::ImageOperations::RESIZE_BOX, size.width(), size.height());
-}
-
 SkBitmap::Config ConvertToSkiaConfig(jobject bitmap_config) {
   int jbitmap_config = Java_BitmapHelper_getBitmapFormatForConfig(
       AttachCurrentThread(), bitmap_config);
diff --git a/ui/gfx/android/java_bitmap.h b/ui/gfx/android/java_bitmap.h
index 5cda137..44a17ca 100644
--- a/ui/gfx/android/java_bitmap.h
+++ b/ui/gfx/android/java_bitmap.h
@@ -31,6 +31,7 @@
   ~JavaBitmap();
 
   inline void* pixels() { return pixels_; }
+  inline const void* pixels() const { return pixels_; }
   inline const gfx::Size& size() const { return size_; }
   // Formats are in android/bitmap.h; e.g. ANDROID_BITMAP_FORMAT_RGBA_8888
   inline int format() const { return format_; }
@@ -49,22 +50,29 @@
   DISALLOW_COPY_AND_ASSIGN(JavaBitmap);
 };
 
-// Allocates a Java-backed bitmap (android.graphics.Bitmap) with the given size
-// and configuration.
+// Allocates a Java-backed bitmap (android.graphics.Bitmap) with the given
+// (non-empty!) size and configuration.
 GFX_EXPORT base::android::ScopedJavaLocalRef<jobject> CreateJavaBitmap(
     int width,
     int height,
     SkBitmap::Config bitmap_config);
 
+// Loads a Java-backed bitmap (android.graphics.Bitmap) from the provided
+// drawable resource identifier (e.g., android:drawable/overscroll_glow). If the
+// resource loads successfully, it will be integrally scaled down, preserving
+// aspect ratio, to a size no smaller than |size|. Otherwise, null is returned.
+GFX_EXPORT base::android::ScopedJavaLocalRef<jobject>
+    CreateJavaBitmapFromAndroidResource(const char* name, gfx::Size size);
+
+// Converts |skbitmap| to a Java-backed bitmap (android.graphics.Bitmap).
+// Note: |skbitmap| is assumed to be non-null, non-empty and one of RGBA_8888 or
+// RGB_565 formats.
 GFX_EXPORT base::android::ScopedJavaLocalRef<jobject> ConvertToJavaBitmap(
     const SkBitmap* skbitmap);
 
-GFX_EXPORT SkBitmap CreateSkBitmapFromJavaBitmap(JavaBitmap& jbitmap);
-
-// If the resource loads successfully, it will be resized to |size|.
-// Note: If the source resource is smaller than |size|, quality may suffer.
-GFX_EXPORT SkBitmap CreateSkBitmapFromResource(const char* name,
-                                               gfx::Size size);
+// Converts |bitmap| to an SkBitmap of the same size and format.
+// Note: |jbitmap| is assumed to be non-null, non-empty and of format RGBA_8888.
+GFX_EXPORT SkBitmap CreateSkBitmapFromJavaBitmap(const JavaBitmap& jbitmap);
 
 // Returns a Skia config value for the requested input java Bitmap.Config.
 GFX_EXPORT SkBitmap::Config ConvertToSkiaConfig(jobject bitmap_config);
diff --git a/ui/gfx/canvas_skia.cc b/ui/gfx/canvas_skia.cc
index 1ad60ba..fe6dcca 100644
--- a/ui/gfx/canvas_skia.cc
+++ b/ui/gfx/canvas_skia.cc
@@ -230,7 +230,7 @@
   Rect clip_rect(text_bounds);
   clip_rect.Inset(ShadowValue::GetMargin(shadows));
 
-  canvas_->save(SkCanvas::kClip_SaveFlag);
+  canvas_->save();
   ClipRect(clip_rect);
 
   Rect rect(text_bounds);
@@ -424,7 +424,7 @@
   rect.set_height(line_height);
   render_text->SetDisplayRect(rect);
 
-  canvas_->save(SkCanvas::kClip_SaveFlag);
+  canvas_->save();
   ClipRect(display_rect);
   render_text->Draw(this);
   canvas_->restore();
diff --git a/ui/gfx/color_analysis_unittest.cc b/ui/gfx/color_analysis_unittest.cc
index 7757eb9..b8234d6 100644
--- a/ui/gfx/color_analysis_unittest.cc
+++ b/ui/gfx/color_analysis_unittest.cc
@@ -104,15 +104,6 @@
     prebaked_sample_results_.push_back(sample);
   }
 
-  void Reset() {
-    prebaked_sample_results_.clear();
-    ResetCounter();
-  }
-
-  void ResetCounter() {
-    current_result_index_ = 0;
-  }
-
   virtual int GetSample(int width, int height) OVERRIDE {
     if (current_result_index_ >= prebaked_sample_results_.size()) {
       current_result_index_ = 0;
diff --git a/ui/gfx/gfx.target.darwin-arm.mk b/ui/gfx/gfx.target.darwin-arm.mk
index 0f365d0..ba93554 100644
--- a/ui/gfx/gfx.target.darwin-arm.mk
+++ b/ui/gfx/gfx.target.darwin-arm.mk
@@ -147,9 +147,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -162,6 +160,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -274,9 +273,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -289,6 +286,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx.target.darwin-mips.mk b/ui/gfx/gfx.target.darwin-mips.mk
index 51fef3f..64a569b 100644
--- a/ui/gfx/gfx.target.darwin-mips.mk
+++ b/ui/gfx/gfx.target.darwin-mips.mk
@@ -146,9 +146,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -161,6 +159,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -272,9 +271,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -287,6 +284,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx.target.darwin-x86.mk b/ui/gfx/gfx.target.darwin-x86.mk
index 0ac0530..8eb0406 100644
--- a/ui/gfx/gfx.target.darwin-x86.mk
+++ b/ui/gfx/gfx.target.darwin-x86.mk
@@ -148,9 +148,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -163,6 +161,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -275,9 +274,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -290,6 +287,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx.target.darwin-x86_64.mk b/ui/gfx/gfx.target.darwin-x86_64.mk
new file mode 100644
index 0000000..456e129
--- /dev/null
+++ b/ui/gfx/gfx.target.darwin-x86_64.mk
@@ -0,0 +1,403 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_gfx_gfx_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,third_party_libjpeg_libjpeg_gyp)/libjpeg.stamp \
+	$(call intermediates-dir-for,GYP,ui_gfx_gfx_jni_headers_gyp)/gfx_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/gfx/android/device_display_info.cc \
+	ui/gfx/android/gfx_jni_registrar.cc \
+	ui/gfx/android/java_bitmap.cc \
+	ui/gfx/android/scroller.cc \
+	ui/gfx/android/shared_device_display_info.cc \
+	ui/gfx/android/view_configuration.cc \
+	ui/gfx/animation/animation.cc \
+	ui/gfx/animation/animation_container.cc \
+	ui/gfx/animation/linear_animation.cc \
+	ui/gfx/animation/multi_animation.cc \
+	ui/gfx/animation/slide_animation.cc \
+	ui/gfx/animation/tween.cc \
+	ui/gfx/blit.cc \
+	ui/gfx/canvas.cc \
+	ui/gfx/canvas_android.cc \
+	ui/gfx/codec/jpeg_codec.cc \
+	ui/gfx/codec/png_codec.cc \
+	ui/gfx/color_analysis.cc \
+	ui/gfx/color_profile.cc \
+	ui/gfx/color_utils.cc \
+	ui/gfx/display.cc \
+	ui/gfx/favicon_size.cc \
+	ui/gfx/font.cc \
+	ui/gfx/font_list.cc \
+	ui/gfx/font_list_impl.cc \
+	ui/gfx/font_render_params_android.cc \
+	ui/gfx/gfx_paths.cc \
+	ui/gfx/gpu_memory_buffer.cc \
+	ui/gfx/image/canvas_image_source.cc \
+	ui/gfx/image/image.cc \
+	ui/gfx/image/image_family.cc \
+	ui/gfx/image/image_png_rep.cc \
+	ui/gfx/image/image_skia.cc \
+	ui/gfx/image/image_skia_operations.cc \
+	ui/gfx/image/image_skia_rep.cc \
+	ui/gfx/image/image_util.cc \
+	ui/gfx/interpolated_transform.cc \
+	ui/gfx/linux_font_delegate.cc \
+	ui/gfx/platform_font_android.cc \
+	ui/gfx/range/range.cc \
+	ui/gfx/screen.cc \
+	ui/gfx/screen_android.cc \
+	ui/gfx/scrollbar_size.cc \
+	ui/gfx/sequential_id_generator.cc \
+	ui/gfx/shadow_value.cc \
+	ui/gfx/skbitmap_operations.cc \
+	ui/gfx/skia_util.cc \
+	ui/gfx/switches.cc \
+	ui/gfx/sys_color_change_listener.cc \
+	ui/gfx/text_elider.cc \
+	ui/gfx/text_utils.cc \
+	ui/gfx/text_utils_android.cc \
+	ui/gfx/transform.cc \
+	ui/gfx/transform_util.cc \
+	ui/gfx/ui_gfx_exports.cc \
+	ui/gfx/utf16_indexing.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gfx \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gfx \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gfx_gfx_gyp
+
+# Alias gyp target name.
+.PHONY: gfx
+gfx: ui_gfx_gfx_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/gfx/gfx.target.linux-arm.mk b/ui/gfx/gfx.target.linux-arm.mk
index 0f365d0..ba93554 100644
--- a/ui/gfx/gfx.target.linux-arm.mk
+++ b/ui/gfx/gfx.target.linux-arm.mk
@@ -147,9 +147,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -162,6 +160,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -274,9 +273,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -289,6 +286,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx.target.linux-mips.mk b/ui/gfx/gfx.target.linux-mips.mk
index 51fef3f..64a569b 100644
--- a/ui/gfx/gfx.target.linux-mips.mk
+++ b/ui/gfx/gfx.target.linux-mips.mk
@@ -146,9 +146,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -161,6 +159,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -272,9 +271,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -287,6 +284,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx.target.linux-x86.mk b/ui/gfx/gfx.target.linux-x86.mk
index 0ac0530..8eb0406 100644
--- a/ui/gfx/gfx.target.linux-x86.mk
+++ b/ui/gfx/gfx.target.linux-x86.mk
@@ -148,9 +148,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -163,6 +161,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -275,9 +274,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -290,6 +287,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx.target.linux-x86_64.mk b/ui/gfx/gfx.target.linux-x86_64.mk
new file mode 100644
index 0000000..456e129
--- /dev/null
+++ b/ui/gfx/gfx.target.linux-x86_64.mk
@@ -0,0 +1,403 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_gfx_gfx_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp \
+	$(call intermediates-dir-for,GYP,third_party_libjpeg_libjpeg_gyp)/libjpeg.stamp \
+	$(call intermediates-dir-for,GYP,ui_gfx_gfx_jni_headers_gyp)/gfx_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/gfx/android/device_display_info.cc \
+	ui/gfx/android/gfx_jni_registrar.cc \
+	ui/gfx/android/java_bitmap.cc \
+	ui/gfx/android/scroller.cc \
+	ui/gfx/android/shared_device_display_info.cc \
+	ui/gfx/android/view_configuration.cc \
+	ui/gfx/animation/animation.cc \
+	ui/gfx/animation/animation_container.cc \
+	ui/gfx/animation/linear_animation.cc \
+	ui/gfx/animation/multi_animation.cc \
+	ui/gfx/animation/slide_animation.cc \
+	ui/gfx/animation/tween.cc \
+	ui/gfx/blit.cc \
+	ui/gfx/canvas.cc \
+	ui/gfx/canvas_android.cc \
+	ui/gfx/codec/jpeg_codec.cc \
+	ui/gfx/codec/png_codec.cc \
+	ui/gfx/color_analysis.cc \
+	ui/gfx/color_profile.cc \
+	ui/gfx/color_utils.cc \
+	ui/gfx/display.cc \
+	ui/gfx/favicon_size.cc \
+	ui/gfx/font.cc \
+	ui/gfx/font_list.cc \
+	ui/gfx/font_list_impl.cc \
+	ui/gfx/font_render_params_android.cc \
+	ui/gfx/gfx_paths.cc \
+	ui/gfx/gpu_memory_buffer.cc \
+	ui/gfx/image/canvas_image_source.cc \
+	ui/gfx/image/image.cc \
+	ui/gfx/image/image_family.cc \
+	ui/gfx/image/image_png_rep.cc \
+	ui/gfx/image/image_skia.cc \
+	ui/gfx/image/image_skia_operations.cc \
+	ui/gfx/image/image_skia_rep.cc \
+	ui/gfx/image/image_util.cc \
+	ui/gfx/interpolated_transform.cc \
+	ui/gfx/linux_font_delegate.cc \
+	ui/gfx/platform_font_android.cc \
+	ui/gfx/range/range.cc \
+	ui/gfx/screen.cc \
+	ui/gfx/screen_android.cc \
+	ui/gfx/scrollbar_size.cc \
+	ui/gfx/sequential_id_generator.cc \
+	ui/gfx/shadow_value.cc \
+	ui/gfx/skbitmap_operations.cc \
+	ui/gfx/skia_util.cc \
+	ui/gfx/switches.cc \
+	ui/gfx/sys_color_change_listener.cc \
+	ui/gfx/text_elider.cc \
+	ui/gfx/text_utils.cc \
+	ui/gfx/text_utils_android.cc \
+	ui/gfx/transform.cc \
+	ui/gfx/transform_util.cc \
+	ui/gfx/ui_gfx_exports.cc \
+	ui/gfx/utf16_indexing.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gfx \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(PWD)/external/jpeg \
+	$(gyp_shared_intermediate_dir)/ui/gfx \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gfx_gfx_gyp
+
+# Alias gyp target name.
+.PHONY: gfx
+gfx: ui_gfx_gfx_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/gfx/gfx_geometry.target.darwin-arm.mk b/ui/gfx/gfx_geometry.target.darwin-arm.mk
index 9f4c51c..5141a50 100644
--- a/ui/gfx/gfx_geometry.target.darwin-arm.mk
+++ b/ui/gfx/gfx_geometry.target.darwin-arm.mk
@@ -98,6 +98,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -183,6 +184,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_geometry.target.darwin-mips.mk b/ui/gfx/gfx_geometry.target.darwin-mips.mk
index a54e4db..bfc41ae 100644
--- a/ui/gfx/gfx_geometry.target.darwin-mips.mk
+++ b/ui/gfx/gfx_geometry.target.darwin-mips.mk
@@ -97,6 +97,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -181,6 +182,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_geometry.target.darwin-x86.mk b/ui/gfx/gfx_geometry.target.darwin-x86.mk
index f774802..699dfe3 100644
--- a/ui/gfx/gfx_geometry.target.darwin-x86.mk
+++ b/ui/gfx/gfx_geometry.target.darwin-x86.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -184,6 +185,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_geometry.target.darwin-x86_64.mk b/ui/gfx/gfx_geometry.target.darwin-x86_64.mk
new file mode 100644
index 0000000..2025f25
--- /dev/null
+++ b/ui/gfx/gfx_geometry.target.darwin-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_gfx_gfx_geometry_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/gfx/geometry/box_f.cc \
+	ui/gfx/geometry/cubic_bezier.cc \
+	ui/gfx/geometry/insets.cc \
+	ui/gfx/geometry/insets_f.cc \
+	ui/gfx/geometry/matrix3_f.cc \
+	ui/gfx/geometry/point.cc \
+	ui/gfx/geometry/point3_f.cc \
+	ui/gfx/geometry/point_conversions.cc \
+	ui/gfx/geometry/point_f.cc \
+	ui/gfx/geometry/quad_f.cc \
+	ui/gfx/geometry/rect.cc \
+	ui/gfx/geometry/rect_conversions.cc \
+	ui/gfx/geometry/rect_f.cc \
+	ui/gfx/geometry/size.cc \
+	ui/gfx/geometry/size_conversions.cc \
+	ui/gfx/geometry/size_f.cc \
+	ui/gfx/geometry/vector2d.cc \
+	ui/gfx/geometry/vector2d_conversions.cc \
+	ui/gfx/geometry/vector2d_f.cc \
+	ui/gfx/geometry/vector3d_f.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gfx_gfx_geometry_gyp
+
+# Alias gyp target name.
+.PHONY: gfx_geometry
+gfx_geometry: ui_gfx_gfx_geometry_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/gfx/gfx_geometry.target.linux-arm.mk b/ui/gfx/gfx_geometry.target.linux-arm.mk
index 9f4c51c..5141a50 100644
--- a/ui/gfx/gfx_geometry.target.linux-arm.mk
+++ b/ui/gfx/gfx_geometry.target.linux-arm.mk
@@ -98,6 +98,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -183,6 +184,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_geometry.target.linux-mips.mk b/ui/gfx/gfx_geometry.target.linux-mips.mk
index a54e4db..bfc41ae 100644
--- a/ui/gfx/gfx_geometry.target.linux-mips.mk
+++ b/ui/gfx/gfx_geometry.target.linux-mips.mk
@@ -97,6 +97,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -181,6 +182,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_geometry.target.linux-x86.mk b/ui/gfx/gfx_geometry.target.linux-x86.mk
index f774802..699dfe3 100644
--- a/ui/gfx/gfx_geometry.target.linux-x86.mk
+++ b/ui/gfx/gfx_geometry.target.linux-x86.mk
@@ -99,6 +99,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -184,6 +185,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DGFX_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_geometry.target.linux-x86_64.mk b/ui/gfx/gfx_geometry.target.linux-x86_64.mk
new file mode 100644
index 0000000..2025f25
--- /dev/null
+++ b/ui/gfx/gfx_geometry.target.linux-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_gfx_gfx_geometry_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/gfx/geometry/box_f.cc \
+	ui/gfx/geometry/cubic_bezier.cc \
+	ui/gfx/geometry/insets.cc \
+	ui/gfx/geometry/insets_f.cc \
+	ui/gfx/geometry/matrix3_f.cc \
+	ui/gfx/geometry/point.cc \
+	ui/gfx/geometry/point3_f.cc \
+	ui/gfx/geometry/point_conversions.cc \
+	ui/gfx/geometry/point_f.cc \
+	ui/gfx/geometry/quad_f.cc \
+	ui/gfx/geometry/rect.cc \
+	ui/gfx/geometry/rect_conversions.cc \
+	ui/gfx/geometry/rect_f.cc \
+	ui/gfx/geometry/size.cc \
+	ui/gfx/geometry/size_conversions.cc \
+	ui/gfx/geometry/size_f.cc \
+	ui/gfx/geometry/vector2d.cc \
+	ui/gfx/geometry/vector2d_conversions.cc \
+	ui/gfx/geometry/vector2d_f.cc \
+	ui/gfx/geometry/vector3d_f.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGFX_IMPLEMENTATION' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gfx_gfx_geometry_gyp
+
+# Alias gyp target name.
+.PHONY: gfx_geometry
+gfx_geometry: ui_gfx_gfx_geometry_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/gfx/gfx_jni_headers.target.darwin-arm.mk b/ui/gfx/gfx_jni_headers.target.darwin-arm.mk
index ffd608e..8c2b4a6 100644
--- a/ui/gfx/gfx_jni_headers.target.darwin-arm.mk
+++ b/ui/gfx/gfx_jni_headers.target.darwin-arm.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -201,6 +202,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_jni_headers.target.darwin-mips.mk b/ui/gfx/gfx_jni_headers.target.darwin-mips.mk
index 393e61d..3204930 100644
--- a/ui/gfx/gfx_jni_headers.target.darwin-mips.mk
+++ b/ui/gfx/gfx_jni_headers.target.darwin-mips.mk
@@ -118,6 +118,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -199,6 +200,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_jni_headers.target.darwin-x86.mk b/ui/gfx/gfx_jni_headers.target.darwin-x86.mk
index 57fde5f..284f002 100644
--- a/ui/gfx/gfx_jni_headers.target.darwin-x86.mk
+++ b/ui/gfx/gfx_jni_headers.target.darwin-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -202,6 +203,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_jni_headers.target.darwin-x86_64.mk b/ui/gfx/gfx_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..c0be65d
--- /dev/null
+++ b/ui/gfx/gfx_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,258 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_gfx_gfx_jni_headers_gyp
+LOCAL_MODULE_STEM := gfx_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_gfx_gfx_gyp_gfx_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/gfx/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../android/java/src/org/chromium/ui/gfx/BitmapHelper.java', '../android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java', '../android/java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/ui/gfx/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gfx/jni; cd $(gyp_local_path)/ui/gfx; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gfx/BitmapHelper.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gfx/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gfx_gfx_jni_headers_gyp_rule_trigger
+ui_gfx_gfx_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gfx/jni; cd $(gyp_local_path)/ui/gfx; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gfx/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gfx_gfx_jni_headers_gyp_rule_trigger
+ui_gfx_gfx_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gfx/jni; cd $(gyp_local_path)/ui/gfx; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gfx/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gfx_gfx_jni_headers_gyp_rule_trigger
+ui_gfx_gfx_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h \
+	ui_gfx_gfx_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gfx_gfx_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: gfx_jni_headers
+gfx_jni_headers: ui_gfx_gfx_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/gfx/gfx_jni_headers.target.linux-arm.mk b/ui/gfx/gfx_jni_headers.target.linux-arm.mk
index ffd608e..8c2b4a6 100644
--- a/ui/gfx/gfx_jni_headers.target.linux-arm.mk
+++ b/ui/gfx/gfx_jni_headers.target.linux-arm.mk
@@ -119,6 +119,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -201,6 +202,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_jni_headers.target.linux-mips.mk b/ui/gfx/gfx_jni_headers.target.linux-mips.mk
index 393e61d..3204930 100644
--- a/ui/gfx/gfx_jni_headers.target.linux-mips.mk
+++ b/ui/gfx/gfx_jni_headers.target.linux-mips.mk
@@ -118,6 +118,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -199,6 +200,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_jni_headers.target.linux-x86.mk b/ui/gfx/gfx_jni_headers.target.linux-x86.mk
index 57fde5f..284f002 100644
--- a/ui/gfx/gfx_jni_headers.target.linux-x86.mk
+++ b/ui/gfx/gfx_jni_headers.target.linux-x86.mk
@@ -120,6 +120,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -202,6 +203,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gfx/gfx_jni_headers.target.linux-x86_64.mk b/ui/gfx/gfx_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..c0be65d
--- /dev/null
+++ b/ui/gfx/gfx_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,258 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_gfx_gfx_jni_headers_gyp
+LOCAL_MODULE_STEM := gfx_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+
+### Generated for rule "ui_gfx_gfx_gyp_gfx_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/gfx/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../android/java/src/org/chromium/ui/gfx/BitmapHelper.java', '../android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java', '../android/java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/ui/gfx/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gfx/BitmapHelper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gfx/jni; cd $(gyp_local_path)/ui/gfx; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gfx/BitmapHelper.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gfx/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gfx_gfx_jni_headers_gyp_rule_trigger
+ui_gfx_gfx_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gfx/jni; cd $(gyp_local_path)/ui/gfx; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gfx/DeviceDisplayInfo.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gfx/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gfx_gfx_jni_headers_gyp_rule_trigger
+ui_gfx_gfx_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gfx/jni; cd $(gyp_local_path)/ui/gfx; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gfx/ViewConfigurationHelper.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gfx/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gfx_gfx_jni_headers_gyp_rule_trigger
+ui_gfx_gfx_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/BitmapHelper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/DeviceDisplayInfo_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gfx/jni/ViewConfigurationHelper_jni.h \
+	ui_gfx_gfx_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gfx_gfx_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: gfx_jni_headers
+gfx_jni_headers: ui_gfx_gfx_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/gfx/gpu_memory_buffer.h b/ui/gfx/gpu_memory_buffer.h
index 3510a91..2ddc89c 100644
--- a/ui/gfx/gpu_memory_buffer.h
+++ b/ui/gfx/gpu_memory_buffer.h
@@ -18,7 +18,7 @@
 enum GpuMemoryBufferType {
   EMPTY_BUFFER,
   SHARED_MEMORY_BUFFER,
-  EGL_CLIENT_BUFFER,
+  ANDROID_NATIVE_BUFFER,
   IO_SURFACE_BUFFER,
   GPU_MEMORY_BUFFER_TYPE_LAST = IO_SURFACE_BUFFER
 };
diff --git a/ui/gfx/ozone/dri/dri_skbitmap.cc b/ui/gfx/ozone/dri/dri_skbitmap.cc
index 61361d6..5e62dd2 100644
--- a/ui/gfx/ozone/dri/dri_skbitmap.cc
+++ b/ui/gfx/ozone/dri/dri_skbitmap.cc
@@ -23,118 +23,15 @@
   drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_request);
 }
 
-// Special DRM implementation of a SkPixelRef. The DRM allocator will create a
-// SkPixelRef for the backing pixels. It will then associate the SkPixelRef with
-// the SkBitmap. SkBitmap will access the allocated memory by locking the pixels
-// in the SkPixelRef.
-// At the end of its life the SkPixelRef is responsible for deallocating the
-// pixel memory.
-class DriSkPixelRef : public SkPixelRef {
- public:
-  DriSkPixelRef(const SkImageInfo& info,
-                void* pixels,
-                SkColorTable* color_table_,
-                size_t size,
-                size_t row_bites,
-                int fd,
-                uint32_t handle);
-  virtual ~DriSkPixelRef();
-
-  virtual bool onNewLockPixels(LockRec* rec) OVERRIDE;
-  virtual void onUnlockPixels() OVERRIDE;
-
-  SK_DECLARE_UNFLATTENABLE_OBJECT()
- private:
-  // Raw pointer to the pixel memory.
-  void* pixels_;
-
-  // Optional color table associated with the pixel memory.
-  SkColorTable* color_table_;
-
-  // Size of the allocated memory.
-  size_t size_;
-
-  // Number of bytes between subsequent rows in the bitmap (stride).
-  size_t row_bytes_;
-
-  // File descriptor to the graphics card used to allocate/deallocate the
-  // memory.
-  int fd_;
-
-  // Handle for the allocated memory.
-  uint32_t handle_;
-
-  DISALLOW_COPY_AND_ASSIGN(DriSkPixelRef);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// DriSkPixelRef implementation
-
-DriSkPixelRef::DriSkPixelRef(
+bool CreateDumbBuffer(
+    DriSkBitmap* bitmap,
     const SkImageInfo& info,
-    void* pixels,
-    SkColorTable* color_table,
-    size_t size,
-    size_t row_bytes,
-    int fd,
-    uint32_t handle)
-  : SkPixelRef(info),
-    pixels_(pixels),
-    color_table_(color_table),
-    size_(size),
-    row_bytes_(row_bytes),
-    fd_(fd),
-    handle_(handle) {
-}
-
-DriSkPixelRef::~DriSkPixelRef() {
-  munmap(pixels_, size_);
-  DestroyDumbBuffer(fd_, handle_);
-}
-
-bool DriSkPixelRef::onNewLockPixels(LockRec* rec) {
-  rec->fPixels = pixels_;
-  rec->fRowBytes = row_bytes_;
-  rec->fColorTable = color_table_;
-  return true;
-}
-
-void DriSkPixelRef::onUnlockPixels() {
-}
-
-}  // namespace
-
-// Allocates pixel memory for a SkBitmap using DRM dumb buffers.
-class DriAllocator : public SkBitmap::Allocator {
- public:
-  DriAllocator();
-
-  virtual bool allocPixelRef(SkBitmap* bitmap,
-                             SkColorTable* color_table) OVERRIDE;
-
- private:
-  bool AllocatePixels(DriSkBitmap* bitmap, SkColorTable* color_table);
-
-  DISALLOW_COPY_AND_ASSIGN(DriAllocator);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// DriAllocator implementation
-
-DriAllocator::DriAllocator() {
-}
-
-bool DriAllocator::allocPixelRef(SkBitmap* bitmap,
-                                 SkColorTable* color_table) {
-  return AllocatePixels(static_cast<DriSkBitmap*>(bitmap), color_table);
-}
-
-bool DriAllocator::AllocatePixels(DriSkBitmap* bitmap,
-                                  SkColorTable* color_table) {
+    size_t* stride,
+    void** pixels) {
   struct drm_mode_create_dumb request;
-  request.width = bitmap->width();
-  request.height = bitmap->height();
-  request.bpp = bitmap->bytesPerPixel() << 3;
+  request.width = info.width();
+  request.height = info.height();
+  request.bpp = info.bytesPerPixel() << 3;
   request.flags = 0;
 
   if (drmIoctl(bitmap->get_fd(), DRM_IOCTL_MODE_CREATE_DUMB, &request) < 0) {
@@ -143,9 +40,8 @@
     return false;
   }
 
-  CHECK(request.size == bitmap->getSize());
-
   bitmap->set_handle(request.handle);
+  *stride = request.pitch;
 
   struct drm_mode_map_dumb map_request;
   map_request.handle = bitmap->get_handle();
@@ -156,39 +52,33 @@
     return false;
   }
 
-  void* pixels = mmap(0,
-                      bitmap->getSize(),
-                      PROT_READ | PROT_WRITE,
-                      MAP_SHARED,
-                      bitmap->get_fd(),
-                      map_request.offset);
-  if (pixels == MAP_FAILED) {
+  *pixels = mmap(0,
+                 request.size,
+                 PROT_READ | PROT_WRITE,
+                 MAP_SHARED,
+                 bitmap->get_fd(),
+                 map_request.offset);
+  if (*pixels == MAP_FAILED) {
     DLOG(ERROR) << "Cannot mmap dumb buffer (" << errno << ") "
                 << strerror(errno);
     DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle());
     return false;
   }
 
-  SkImageInfo info;
-  if (!bitmap->asImageInfo(&info)) {
-    DLOG(ERROR) << "Cannot get skia image info";
-    DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle());
-    return false;
-  }
-
-  bitmap->setPixelRef(new DriSkPixelRef(
-      info,
-      pixels,
-      color_table,
-      bitmap->getSize(),
-      bitmap->rowBytes(),
-      bitmap->get_fd(),
-      bitmap->get_handle()))->unref();
-  bitmap->lockPixels();
-
   return true;
 }
 
+void ReleasePixels(void* addr, void* context) {
+  DriSkBitmap *bitmap = reinterpret_cast<DriSkBitmap*>(context);
+  if (!bitmap && !bitmap->getPixels())
+    return;
+
+  munmap(bitmap->getPixels(), bitmap->getSize());
+  DestroyDumbBuffer(bitmap->get_fd(), bitmap->get_handle());
+}
+
+}  // namespace
+
 ////////////////////////////////////////////////////////////////////////////////
 // DriSkBitmap implementation
 
@@ -201,9 +91,19 @@
 DriSkBitmap::~DriSkBitmap() {
 }
 
-bool DriSkBitmap::Initialize() {
-  DriAllocator drm_allocator;
-  return allocPixels(&drm_allocator, NULL);
+bool DriSkBitmap::Initialize(const SkImageInfo& info) {
+  size_t stride = 0;
+  void* pixels = NULL;
+  if (!CreateDumbBuffer(this, info, &stride, &pixels)) {
+    DLOG(ERROR) << "Cannot allocate drm dumb buffer";
+    return false;
+  }
+  if (!installPixels(info, pixels, stride, ReleasePixels, this)) {
+    DLOG(ERROR) << "Cannot install Skia pixels for drm buffer";
+    return false;
+  }
+
+  return true;
 }
 
 uint8_t DriSkBitmap::GetColorDepth() const {
diff --git a/ui/gfx/ozone/dri/dri_skbitmap.h b/ui/gfx/ozone/dri/dri_skbitmap.h
index f5b8f94..812298a 100644
--- a/ui/gfx/ozone/dri/dri_skbitmap.h
+++ b/ui/gfx/ozone/dri/dri_skbitmap.h
@@ -20,7 +20,9 @@
 
   // Allocates the backing pixels using DRI.
   // Return true on success, false otherwise.
-  virtual bool Initialize();
+  virtual bool Initialize(const SkImageInfo& info);
+
+  void set_handle(uint32_t handle) { handle_ = handle; };
 
   uint32_t get_handle() const { return handle_; };
 
@@ -32,10 +34,8 @@
   uint8_t GetColorDepth() const;
 
  private:
-  friend class DriAllocator;
   friend class HardwareDisplayController;
 
-  void set_handle(uint32_t handle) { handle_ = handle; };
   void set_framebuffer(uint32_t framebuffer) { framebuffer_ = framebuffer; };
 
   // File descriptor used by the DRI allocator to request buffers from the DRI
diff --git a/ui/gfx/ozone/dri/dri_surface.cc b/ui/gfx/ozone/dri/dri_surface.cc
index 8b0af66..7a0136f 100644
--- a/ui/gfx/ozone/dri/dri_surface.cc
+++ b/ui/gfx/ozone/dri/dri_surface.cc
@@ -56,11 +56,11 @@
     bitmaps_[i].reset(CreateBuffer());
     // TODO(dnicoara) Should select the configuration based on what the
     // underlying system supports.
-    bitmaps_[i]->setConfig(SkBitmap::kARGB_8888_Config,
-                           size_.width(),
-                           size_.height());
-
-    if (!bitmaps_[i]->Initialize()) {
+    SkImageInfo info = SkImageInfo::Make(size_.width(),
+                                         size_.height(),
+                                         kPMColor_SkColorType,
+                                         kPremul_SkAlphaType);
+    if (!bitmaps_[i]->Initialize(info)) {
       return false;
     }
   }
diff --git a/ui/gfx/ozone/dri/dri_surface_factory.cc b/ui/gfx/ozone/dri/dri_surface_factory.cc
index 5166679..661944a 100644
--- a/ui/gfx/ozone/dri/dri_surface_factory.cc
+++ b/ui/gfx/ozone/dri/dri_surface_factory.cc
@@ -211,6 +211,9 @@
     return gfx::kNullAcceleratedWidget;
   }
 
+  // Initial cursor set.
+  ResetCursor();
+
   return reinterpret_cast<gfx::AcceleratedWidget>(controller_->get_surface());
 }
 
@@ -273,17 +276,19 @@
 void DriSurfaceFactory::SetHardwareCursor(gfx::AcceleratedWidget window,
                                           const SkBitmap& image,
                                           const gfx::Point& location) {
+  cursor_bitmap_ = image;
+  cursor_location_ = location;
+
   if (state_ != INITIALIZED)
     return;
 
-  UpdateCursorImage(cursor_surface_.get(), image);
-  controller_->MoveCursor(location);
-  controller_->SetCursor(*cursor_surface_.get());
-  cursor_surface_->SwapBuffers();
+  ResetCursor();
 }
 
 void DriSurfaceFactory::MoveHardwareCursor(gfx::AcceleratedWidget window,
                                            const gfx::Point& location) {
+  cursor_location_ = location;
+
   if (state_ != INITIALIZED)
     return;
 
@@ -291,10 +296,12 @@
 }
 
 void DriSurfaceFactory::UnsetHardwareCursor(gfx::AcceleratedWidget window) {
+  cursor_bitmap_.reset();
+
   if (state_ != INITIALIZED)
     return;
 
-  controller_->UnsetCursor();
+  ResetCursor();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -367,4 +374,19 @@
   drmHandleEvent(fd, &drm_event);
 }
 
+void DriSurfaceFactory::ResetCursor() {
+  if (!cursor_bitmap_.empty()) {
+    // Draw new cursor into backbuffer.
+    UpdateCursorImage(cursor_surface_.get(), cursor_bitmap_);
+
+    // Reset location & buffer.
+    controller_->MoveCursor(cursor_location_);
+    controller_->SetCursor(cursor_surface_.get());
+  } else {
+    // No cursor set.
+    controller_->UnsetCursor();
+  }
+}
+
+
 }  // namespace gfx
diff --git a/ui/gfx/ozone/dri/dri_surface_factory.h b/ui/gfx/ozone/dri/dri_surface_factory.h
index 4981394..3b958bd 100644
--- a/ui/gfx/ozone/dri/dri_surface_factory.h
+++ b/ui/gfx/ozone/dri/dri_surface_factory.h
@@ -6,6 +6,7 @@
 #define UI_GFX_OZONE_DRI_DRI_SURFACE_FACTORY_H_
 
 #include "base/memory/scoped_ptr.h"
+#include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/ozone/surface_factory_ozone.h"
 
 namespace gfx {
@@ -67,6 +68,9 @@
   // pending frame.
   virtual void WaitForPageFlipEvent(int fd);
 
+  // Draw the last set cursor & update the cursor plane.
+  void ResetCursor();
+
   scoped_ptr<DriWrapper> drm_;
 
   HardwareState state_;
@@ -76,6 +80,9 @@
 
   scoped_ptr<DriSurface> cursor_surface_;
 
+  SkBitmap cursor_bitmap_;
+  gfx::Point cursor_location_;
+
   DISALLOW_COPY_AND_ASSIGN(DriSurfaceFactory);
 };
 
diff --git a/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc b/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc
index d9c8122..b0e108e 100644
--- a/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc
+++ b/ui/gfx/ozone/dri/dri_surface_factory_unittest.cc
@@ -115,8 +115,8 @@
   MockDriSkBitmap() : DriSkBitmap(kFd) {}
   virtual ~MockDriSkBitmap() {}
 
-  virtual bool Initialize() OVERRIDE {
-    allocPixels();
+  virtual bool Initialize(const SkImageInfo& info) OVERRIDE {
+    allocPixels(info);
     eraseColor(SK_ColorBLACK);
     return true;
   }
diff --git a/ui/gfx/ozone/dri/dri_surface_unittest.cc b/ui/gfx/ozone/dri/dri_surface_unittest.cc
index bb0d0a1..434e85e 100644
--- a/ui/gfx/ozone/dri/dri_surface_unittest.cc
+++ b/ui/gfx/ozone/dri/dri_surface_unittest.cc
@@ -74,11 +74,11 @@
         initialize_expectation_(initialize_expectation) {}
   virtual ~MockDriSkBitmap() {}
 
-  virtual bool Initialize() OVERRIDE {
+  virtual bool Initialize(const SkImageInfo& info) OVERRIDE {
     if (!initialize_expectation_)
       return false;
 
-    allocPixels();
+    allocPixels(info);
     // Clear the bitmap to black.
     eraseColor(SK_ColorBLACK);
 
diff --git a/ui/gfx/ozone/dri/hardware_display_controller.cc b/ui/gfx/ozone/dri/hardware_display_controller.cc
index e08cecf..55dd008 100644
--- a/ui/gfx/ozone/dri/hardware_display_controller.cc
+++ b/ui/gfx/ozone/dri/hardware_display_controller.cc
@@ -133,12 +133,14 @@
   surface_->SwapBuffers();
 }
 
-bool HardwareDisplayController::SetCursor(const DriSurface& surface) {
+bool HardwareDisplayController::SetCursor(DriSurface* surface) {
   CHECK(state_ != UNASSOCIATED);
-  return drm_->SetCursor(crtc_id_,
-                         surface.GetHandle(),
-                         surface.size().width(),
-                         surface.size().height());
+  bool ret = drm_->SetCursor(crtc_id_,
+                         surface->GetHandle(),
+                         surface->size().width(),
+                         surface->size().height());
+  surface->SwapBuffers();
+  return ret;
 }
 
 bool HardwareDisplayController::UnsetCursor() {
diff --git a/ui/gfx/ozone/dri/hardware_display_controller.h b/ui/gfx/ozone/dri/hardware_display_controller.h
index e0ae007..46861a1 100644
--- a/ui/gfx/ozone/dri/hardware_display_controller.h
+++ b/ui/gfx/ozone/dri/hardware_display_controller.h
@@ -147,7 +147,7 @@
                        unsigned int useconds);
 
   // Set the hardware cursor to show the contents of |surface|.
-  bool SetCursor(const DriSurface& surface);
+  bool SetCursor(DriSurface* surface);
 
   bool UnsetCursor();
 
diff --git a/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc b/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc
index db817f0..b5cf465 100644
--- a/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc
+++ b/ui/gfx/ozone/dri/hardware_display_controller_unittest.cc
@@ -151,8 +151,8 @@
   MockDriSkBitmap(int fd) : DriSkBitmap(fd) {}
   virtual ~MockDriSkBitmap() {}
 
-  virtual bool Initialize() OVERRIDE {
-    return allocPixels();
+  virtual bool Initialize(const SkImageInfo& info) OVERRIDE {
+    return allocPixels(info);
   }
  private:
   DISALLOW_COPY_AND_ASSIGN(MockDriSkBitmap);
diff --git a/ui/gfx/ozone/impl/file_surface_factory.cc b/ui/gfx/ozone/impl/file_surface_factory.cc
index 2120bd1..7083376 100644
--- a/ui/gfx/ozone/impl/file_surface_factory.cc
+++ b/ui/gfx/ozone/impl/file_surface_factory.cc
@@ -65,9 +65,9 @@
 bool FileSurfaceFactory::AttemptToResizeAcceleratedWidget(
     AcceleratedWidget widget,
     const Rect& bounds) {
-  device_ = skia::AdoptRef(new SkBitmapDevice(SkBitmap::kARGB_8888_Config,
-                                              bounds.width(),
-                                              bounds.height()));
+  SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(),
+                                                bounds.height());
+  device_ = skia::AdoptRef(SkBitmapDevice::Create(info));
   canvas_ = skia::AdoptRef(new SkCanvas(device_.get()));
   return true;
 }
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 9813606..6455738 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -160,7 +160,8 @@
 const SkScalar kUnderlineMetricsNotSet = -1.0f;
 
 SkiaTextRenderer::SkiaTextRenderer(Canvas* canvas)
-    : canvas_skia_(canvas->sk_canvas()),
+    : canvas_(canvas),
+      canvas_skia_(canvas->sk_canvas()),
       started_drawing_(false),
       underline_thickness_(kUnderlineMetricsNotSet),
       underline_position_(0.0f) {
@@ -279,8 +280,20 @@
     DrawUnderline(x, y, width);
   if (strike)
     DrawStrike(x, y, width);
-  if (diagonal_strike)
-    DrawDiagonalStrike(x, y, width);
+  if (diagonal_strike) {
+    if (!diagonal_)
+      diagonal_.reset(new DiagonalStrike(canvas_, Point(x, y), paint_));
+    diagonal_->AddPiece(width, paint_.getColor());
+  } else if (diagonal_) {
+    EndDiagonalStrike();
+  }
+}
+
+void SkiaTextRenderer::EndDiagonalStrike() {
+  if (diagonal_) {
+    diagonal_->Draw();
+    diagonal_.reset();
+  }
 }
 
 void SkiaTextRenderer::DrawUnderline(int x, int y, int width) {
@@ -302,15 +315,51 @@
   canvas_skia_->drawRect(r, paint_);
 }
 
-void SkiaTextRenderer::DrawDiagonalStrike(int x, int y, int width) const {
+SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas,
+                                                 Point start,
+                                                 const SkPaint& paint)
+    : canvas_(canvas),
+      start_(start),
+      paint_(paint),
+      total_length_(0) {
+}
+
+SkiaTextRenderer::DiagonalStrike::~DiagonalStrike() {
+}
+
+void SkiaTextRenderer::DiagonalStrike::AddPiece(int length, SkColor color) {
+  pieces_.push_back(Piece(length, color));
+  total_length_ += length;
+}
+
+void SkiaTextRenderer::DiagonalStrike::Draw() {
   const SkScalar text_size = paint_.getTextSize();
   const SkScalar offset = SkScalarMul(text_size, kDiagonalStrikeMarginOffset);
+  const int thickness =
+      SkScalarCeilToInt(SkScalarMul(text_size, kLineThickness) * 2);
+  const int height = SkScalarCeilToInt(text_size - offset);
+  const Point end = start_ + Vector2d(total_length_, -height);
 
-  SkPaint paint(paint_);
-  paint.setAntiAlias(true);
-  paint.setStyle(SkPaint::kFill_Style);
-  paint.setStrokeWidth(SkScalarMul(text_size, kLineThickness) * 2);
-  canvas_skia_->drawLine(x, y, x + width, y - text_size + offset, paint);
+  paint_.setAntiAlias(true);
+  paint_.setStrokeWidth(thickness);
+
+  const bool clipped = pieces_.size() > 1;
+  int x = start_.x();
+  for (size_t i = 0; i < pieces_.size(); ++i) {
+    paint_.setColor(pieces_[i].second);
+
+    if (clipped) {
+      canvas_->Save();
+      canvas_->ClipRect(Rect(x, 0, pieces_[i].first, start_.y() + thickness));
+    }
+
+    canvas_->DrawLine(start_, end, paint_);
+
+    if (clipped)
+      canvas_->Restore();
+
+    x += pieces_[i].first;
+  }
 }
 
 StyleIterator::StyleIterator(const BreakList<SkColor>& colors,
diff --git a/ui/gfx/render_text.h b/ui/gfx/render_text.h
index 9ae2e54..93054b4 100644
--- a/ui/gfx/render_text.h
+++ b/ui/gfx/render_text.h
@@ -13,6 +13,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/i18n/rtl.h"
+#include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "skia/ext/refptr.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -73,11 +74,35 @@
   //   third_party/skia/src/core/SkTextFormatParams.h
   void DrawDecorations(int x, int y, int width, bool underline, bool strike,
                        bool diagonal_strike);
+  // Finishes any ongoing diagonal strike run.
+  void EndDiagonalStrike();
   void DrawUnderline(int x, int y, int width);
   void DrawStrike(int x, int y, int width) const;
-  void DrawDiagonalStrike(int x, int y, int width) const;
 
  private:
+  // Helper class to draw a diagonal line with multiple pieces of different
+  // lengths and colors; to support text selection appearances.
+  class DiagonalStrike {
+   public:
+    DiagonalStrike(Canvas* canvas, Point start, const SkPaint& paint);
+    ~DiagonalStrike();
+
+    void AddPiece(int length, SkColor color);
+    void Draw();
+
+   private:
+    typedef std::pair<int, SkColor> Piece;
+
+    Canvas* canvas_;
+    const Point start_;
+    SkPaint paint_;
+    int total_length_;
+    std::vector<Piece> pieces_;
+
+    DISALLOW_COPY_AND_ASSIGN(DiagonalStrike);
+  };
+
+  Canvas* canvas_;
   SkCanvas* canvas_skia_;
   bool started_drawing_;
   SkPaint paint_;
@@ -85,6 +110,7 @@
   skia::RefPtr<SkShader> deferred_fade_shader_;
   SkScalar underline_thickness_;
   SkScalar underline_position_;
+  scoped_ptr<DiagonalStrike> diagonal_;
 
   DISALLOW_COPY_AND_ASSIGN(SkiaTextRenderer);
 };
diff --git a/ui/gfx/render_text_mac.cc b/ui/gfx/render_text_mac.cc
index f41704c..af0be63 100644
--- a/ui/gfx/render_text_mac.cc
+++ b/ui/gfx/render_text_mac.cc
@@ -174,6 +174,8 @@
     renderer.DrawDecorations(run.origin.x(), run.origin.y(), run.width,
                              run.underline, run.strike, run.diagonal_strike);
   }
+
+  renderer.EndDiagonalStrike();
 }
 
 RenderTextMac::TextRun::TextRun()
diff --git a/ui/gfx/render_text_pango.cc b/ui/gfx/render_text_pango.cc
index 4bfdaa7..fdf3d59 100644
--- a/ui/gfx/render_text_pango.cc
+++ b/ui/gfx/render_text_pango.cc
@@ -487,6 +487,8 @@
     } while (glyph_index < glyph_count);
   }
 
+  renderer.EndDiagonalStrike();
+
   // Undo the temporarily applied composition underlines and selection colors.
   UndoCompositionAndSelectionStyles();
 }
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index 53b6043..46f46dd 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -878,6 +878,8 @@
 
       preceding_segment_widths += segment_width;
     }
+
+    renderer.EndDiagonalStrike();
   }
 
   UndoCompositionAndSelectionStyles();
@@ -1007,13 +1009,6 @@
 
     if (run->glyph_count > 0) {
       run->advance_widths.reset(new int[run->glyph_count]);
-      // TODO(asvitkine): Temporary instrumentation to debug a double-free
-      // crash where we're seeing these two being equal inexplicably. Hitting
-      // this implies that the malloc book-keeping is corrupt and it returned
-      // the same pointer for two different allocs, which we can debug further.
-      // http://crbug.com/348103
-      CHECK_NE(static_cast<void*>(run->logical_clusters.get()),
-               static_cast<void*>(run->advance_widths.get()));
       run->offsets.reset(new GOFFSET[run->glyph_count]);
       hr = ScriptPlace(cached_hdc_,
                        &run->script_cache,
diff --git a/ui/gfx/win/hwnd_util.cc b/ui/gfx/win/hwnd_util.cc
index a986e66..e28398a 100644
--- a/ui/gfx/win/hwnd_util.cc
+++ b/ui/gfx/win/hwnd_util.cc
@@ -207,9 +207,10 @@
 void ShowSystemMenu(HWND window) {
   RECT rect;
   GetWindowRect(window, &rect);
-  Point point = Point(rect.left, rect.top);
+  Point point = Point(base::i18n::IsRTL() ? rect.right : rect.left, rect.top);
   static const int kSystemMenuOffset = 10;
-  point.Offset(kSystemMenuOffset, kSystemMenuOffset);
+  point.Offset(base::i18n::IsRTL() ? -kSystemMenuOffset : kSystemMenuOffset,
+               kSystemMenuOffset);
   ShowSystemMenuAtPoint(window, point);
 }
 
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp
index 4d4d658..a45e8ce 100644
--- a/ui/gl/gl.gyp
+++ b/ui/gl/gl.gyp
@@ -97,6 +97,7 @@
         'gl_state_restorer.h',
         'gl_surface.cc',
         'gl_surface.h',
+        'gl_surface_android.cc',
         'gl_surface_mac.cc',
         'gl_surface_stub.cc',
         'gl_surface_stub.h',
@@ -104,6 +105,7 @@
         'gl_surface_x11.cc',
         'gl_surface_osmesa.cc',
         'gl_surface_osmesa.h',
+        'gl_surface_ozone.cc',
         'gl_switches.cc',
         'gl_switches.h',
         'gl_version_info.cc',
@@ -175,6 +177,8 @@
             'egl_util.h',
             'gl_context_egl.cc',
             'gl_context_egl.h',
+            'gl_image_egl.cc',
+            'gl_image_egl.h',
             'gl_surface_egl.cc',
             'gl_surface_egl.h',
             'gl_egl_api_implementation.cc',
@@ -273,8 +277,8 @@
             'gl_jni_headers',
           ],
           'sources': [
-            'gl_image_egl.cc',
-            'gl_image_egl.h',
+            'gl_image_android_native_buffer.cc',
+            'gl_image_android_native_buffer.h',
           ],
           'link_settings': {
             'libraries': [
diff --git a/ui/gl/gl.target.darwin-arm.mk b/ui/gl/gl.target.darwin-arm.mk
index 8f14024..71f86db 100644
--- a/ui/gl/gl.target.darwin-arm.mk
+++ b/ui/gl/gl.target.darwin-arm.mk
@@ -105,6 +105,7 @@
 	ui/gl/gl_share_group.cc \
 	ui/gl/gl_state_restorer.cc \
 	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
 	ui/gl/gl_surface_stub.cc \
 	ui/gl/gl_surface_osmesa.cc \
 	ui/gl/gl_switches.cc \
@@ -115,10 +116,11 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
 	ui/gl/gl_implementation_osmesa.cc \
-	ui/gl/gl_image_egl.cc
+	ui/gl/gl_image_android_native_buffer.cc
 
 
 # Flags passed to both C and C++ files.
@@ -184,9 +186,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -196,6 +196,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -312,9 +313,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -324,6 +323,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl.target.darwin-mips.mk b/ui/gl/gl.target.darwin-mips.mk
index 614a1cd..8d4cf62 100644
--- a/ui/gl/gl.target.darwin-mips.mk
+++ b/ui/gl/gl.target.darwin-mips.mk
@@ -105,6 +105,7 @@
 	ui/gl/gl_share_group.cc \
 	ui/gl/gl_state_restorer.cc \
 	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
 	ui/gl/gl_surface_stub.cc \
 	ui/gl/gl_surface_osmesa.cc \
 	ui/gl/gl_switches.cc \
@@ -115,10 +116,11 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
 	ui/gl/gl_implementation_osmesa.cc \
-	ui/gl/gl_image_egl.cc
+	ui/gl/gl_image_android_native_buffer.cc
 
 
 # Flags passed to both C and C++ files.
@@ -183,9 +185,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -195,6 +195,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -310,9 +311,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -322,6 +321,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl.target.darwin-x86.mk b/ui/gl/gl.target.darwin-x86.mk
index 42d1fe6..8db82e8 100644
--- a/ui/gl/gl.target.darwin-x86.mk
+++ b/ui/gl/gl.target.darwin-x86.mk
@@ -105,6 +105,7 @@
 	ui/gl/gl_share_group.cc \
 	ui/gl/gl_state_restorer.cc \
 	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
 	ui/gl/gl_surface_stub.cc \
 	ui/gl/gl_surface_osmesa.cc \
 	ui/gl/gl_switches.cc \
@@ -115,10 +116,11 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
 	ui/gl/gl_implementation_osmesa.cc \
-	ui/gl/gl_image_egl.cc
+	ui/gl/gl_image_android_native_buffer.cc
 
 
 # Flags passed to both C and C++ files.
@@ -185,9 +187,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -197,6 +197,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -313,9 +314,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -325,6 +324,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl.target.darwin-x86_64.mk b/ui/gl/gl.target.darwin-x86_64.mk
new file mode 100644
index 0000000..e55094c
--- /dev/null
+++ b/ui/gl/gl.target.darwin-x86_64.mk
@@ -0,0 +1,441 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_gl_gl_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_mesa_mesa_headers_gyp)/mesa_headers.stamp \
+	$(call intermediates-dir-for,GYP,ui_gl_gl_jni_headers_gyp)/gl_jni_headers.stamp
+
+### Rules for action "generate_gl_bindings":
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: $(LOCAL_PATH)/ui/gl/generate_bindings.py $(LOCAL_PATH)/third_party/mesa/src/include/GL/glext.h $(LOCAL_PATH)/third_party/khronos/GLES2/gl2ext.h $(LOCAL_PATH)/ui/gl/GL/glextchromium.h $(LOCAL_PATH)/gpu/GLES2/gl2chromium.h $(LOCAL_PATH)/gpu/GLES2/gl2extchromium.h $(LOCAL_PATH)/third_party/khronos/EGL/eglext.h $(LOCAL_PATH)/ui/gl/EGL/eglextchromium.h $(LOCAL_PATH)/third_party/mesa/src/include/GL/wglext.h $(LOCAL_PATH)/third_party/mesa/src/include/GL/glx.h $(LOCAL_PATH)/third_party/mesa/src/include/GL/glxext.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: ui_gl_gl_gyp_gl_target_generate_gl_bindings ($@)"
+	$(hide)cd $(gyp_local_path)/ui/gl; mkdir -p $(gyp_shared_intermediate_dir)/ui/gl; python generate_bindings.py "--header-paths=../../third_party/khronos:../../third_party/mesa/src/include" "$(gyp_shared_intermediate_dir)/ui/gl"
+
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_egl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_gl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_glx.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_osmesa.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_wgl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_mock_autogen_gl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_egl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_gl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_glx.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_osmesa.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_wgl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_mock_autogen_gl.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/gl_bindings_autogen_gl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/gl_bindings_autogen_osmesa.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/gl_bindings_autogen_egl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/gl_bindings_autogen_gl.cc \
+	$(gyp_intermediate_dir)/gl_bindings_autogen_osmesa.cc \
+	$(gyp_intermediate_dir)/gl_bindings_autogen_egl.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/ui/gl
+
+LOCAL_SRC_FILES := \
+	ui/gl/android/gl_jni_registrar.cc \
+	ui/gl/android/scoped_java_surface.cc \
+	ui/gl/android/surface_texture.cc \
+	ui/gl/android/surface_texture_listener.cc \
+	ui/gl/gl_bindings_skia_in_process.cc \
+	ui/gl/gl_context.cc \
+	ui/gl/gl_context_android.cc \
+	ui/gl/gl_context_osmesa.cc \
+	ui/gl/gl_context_stub.cc \
+	ui/gl/gl_context_stub_with_extensions.cc \
+	ui/gl/gl_fence.cc \
+	ui/gl/gl_gl_api_implementation.cc \
+	ui/gl/gl_image.cc \
+	ui/gl/gl_image_android.cc \
+	ui/gl/gl_image_shm.cc \
+	ui/gl/gl_image_stub.cc \
+	ui/gl/gl_implementation.cc \
+	ui/gl/gl_implementation_android.cc \
+	ui/gl/gl_osmesa_api_implementation.cc \
+	ui/gl/gl_share_group.cc \
+	ui/gl/gl_state_restorer.cc \
+	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
+	ui/gl/gl_surface_stub.cc \
+	ui/gl/gl_surface_osmesa.cc \
+	ui/gl/gl_switches.cc \
+	ui/gl/gl_version_info.cc \
+	ui/gl/gpu_switching_manager.cc \
+	ui/gl/scoped_binders.cc \
+	ui/gl/scoped_make_current.cc \
+	ui/gl/sync_control_vsync_provider.cc \
+	ui/gl/egl_util.cc \
+	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
+	ui/gl/gl_surface_egl.cc \
+	ui/gl/gl_egl_api_implementation.cc \
+	ui/gl/gl_implementation_osmesa.cc \
+	ui/gl/gl_image_android_native_buffer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGL_IMPLEMENTATION' \
+	'-DGL_GLEXT_PROTOTYPES' \
+	'-DEGL_EGLEXT_PROTOTYPES' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/swiftshader/include \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGL_IMPLEMENTATION' \
+	'-DGL_GLEXT_PROTOTYPES' \
+	'-DEGL_EGLEXT_PROTOTYPES' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/swiftshader/include \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gl_gl_gyp
+
+# Alias gyp target name.
+.PHONY: gl
+gl: ui_gl_gl_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/gl/gl.target.linux-arm.mk b/ui/gl/gl.target.linux-arm.mk
index 8f14024..71f86db 100644
--- a/ui/gl/gl.target.linux-arm.mk
+++ b/ui/gl/gl.target.linux-arm.mk
@@ -105,6 +105,7 @@
 	ui/gl/gl_share_group.cc \
 	ui/gl/gl_state_restorer.cc \
 	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
 	ui/gl/gl_surface_stub.cc \
 	ui/gl/gl_surface_osmesa.cc \
 	ui/gl/gl_switches.cc \
@@ -115,10 +116,11 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
 	ui/gl/gl_implementation_osmesa.cc \
-	ui/gl/gl_image_egl.cc
+	ui/gl/gl_image_android_native_buffer.cc
 
 
 # Flags passed to both C and C++ files.
@@ -184,9 +186,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -196,6 +196,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -312,9 +313,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -324,6 +323,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl.target.linux-mips.mk b/ui/gl/gl.target.linux-mips.mk
index 614a1cd..8d4cf62 100644
--- a/ui/gl/gl.target.linux-mips.mk
+++ b/ui/gl/gl.target.linux-mips.mk
@@ -105,6 +105,7 @@
 	ui/gl/gl_share_group.cc \
 	ui/gl/gl_state_restorer.cc \
 	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
 	ui/gl/gl_surface_stub.cc \
 	ui/gl/gl_surface_osmesa.cc \
 	ui/gl/gl_switches.cc \
@@ -115,10 +116,11 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
 	ui/gl/gl_implementation_osmesa.cc \
-	ui/gl/gl_image_egl.cc
+	ui/gl/gl_image_android_native_buffer.cc
 
 
 # Flags passed to both C and C++ files.
@@ -183,9 +185,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -195,6 +195,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -310,9 +311,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -322,6 +321,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl.target.linux-x86.mk b/ui/gl/gl.target.linux-x86.mk
index 42d1fe6..8db82e8 100644
--- a/ui/gl/gl.target.linux-x86.mk
+++ b/ui/gl/gl.target.linux-x86.mk
@@ -105,6 +105,7 @@
 	ui/gl/gl_share_group.cc \
 	ui/gl/gl_state_restorer.cc \
 	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
 	ui/gl/gl_surface_stub.cc \
 	ui/gl/gl_surface_osmesa.cc \
 	ui/gl/gl_switches.cc \
@@ -115,10 +116,11 @@
 	ui/gl/sync_control_vsync_provider.cc \
 	ui/gl/egl_util.cc \
 	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
 	ui/gl/gl_surface_egl.cc \
 	ui/gl/gl_egl_api_implementation.cc \
 	ui/gl/gl_implementation_osmesa.cc \
-	ui/gl/gl_image_egl.cc
+	ui/gl/gl_image_android_native_buffer.cc
 
 
 # Flags passed to both C and C++ files.
@@ -185,9 +187,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -197,6 +197,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -313,9 +314,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -325,6 +324,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl.target.linux-x86_64.mk b/ui/gl/gl.target.linux-x86_64.mk
new file mode 100644
index 0000000..e55094c
--- /dev/null
+++ b/ui/gl/gl.target.linux-x86_64.mk
@@ -0,0 +1,441 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_gl_gl_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_mesa_mesa_headers_gyp)/mesa_headers.stamp \
+	$(call intermediates-dir-for,GYP,ui_gl_gl_jni_headers_gyp)/gl_jni_headers.stamp
+
+### Rules for action "generate_gl_bindings":
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc: $(LOCAL_PATH)/ui/gl/generate_bindings.py $(LOCAL_PATH)/third_party/mesa/src/include/GL/glext.h $(LOCAL_PATH)/third_party/khronos/GLES2/gl2ext.h $(LOCAL_PATH)/ui/gl/GL/glextchromium.h $(LOCAL_PATH)/gpu/GLES2/gl2chromium.h $(LOCAL_PATH)/gpu/GLES2/gl2extchromium.h $(LOCAL_PATH)/third_party/khronos/EGL/eglext.h $(LOCAL_PATH)/ui/gl/EGL/eglextchromium.h $(LOCAL_PATH)/third_party/mesa/src/include/GL/wglext.h $(LOCAL_PATH)/third_party/mesa/src/include/GL/glx.h $(LOCAL_PATH)/third_party/mesa/src/include/GL/glxext.h $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: ui_gl_gl_gyp_gl_target_generate_gl_bindings ($@)"
+	$(hide)cd $(gyp_local_path)/ui/gl; mkdir -p $(gyp_shared_intermediate_dir)/ui/gl; python generate_bindings.py "--header-paths=../../third_party/khronos:../../third_party/mesa/src/include" "$(gyp_shared_intermediate_dir)/ui/gl"
+
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_egl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_gl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_glx.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_osmesa.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_wgl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+$(gyp_shared_intermediate_dir)/ui/gl/gl_mock_autogen_gl.h: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_egl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_gl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_glx.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_glx.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_mock.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_osmesa.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.cc \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_wgl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_api_autogen_wgl.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/gl_mock_autogen_gl.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+$(gyp_intermediate_dir)/gl_bindings_autogen_gl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_gl.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/gl_bindings_autogen_osmesa.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_osmesa.cc
+	mkdir -p $(@D); cp $< $@
+$(gyp_intermediate_dir)/gl_bindings_autogen_egl.cc: $(gyp_shared_intermediate_dir)/ui/gl/gl_bindings_autogen_egl.cc
+	mkdir -p $(@D); cp $< $@
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_intermediate_dir)/gl_bindings_autogen_gl.cc \
+	$(gyp_intermediate_dir)/gl_bindings_autogen_osmesa.cc \
+	$(gyp_intermediate_dir)/gl_bindings_autogen_egl.cc
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS := \
+	$(gyp_shared_intermediate_dir)/ui/gl
+
+LOCAL_SRC_FILES := \
+	ui/gl/android/gl_jni_registrar.cc \
+	ui/gl/android/scoped_java_surface.cc \
+	ui/gl/android/surface_texture.cc \
+	ui/gl/android/surface_texture_listener.cc \
+	ui/gl/gl_bindings_skia_in_process.cc \
+	ui/gl/gl_context.cc \
+	ui/gl/gl_context_android.cc \
+	ui/gl/gl_context_osmesa.cc \
+	ui/gl/gl_context_stub.cc \
+	ui/gl/gl_context_stub_with_extensions.cc \
+	ui/gl/gl_fence.cc \
+	ui/gl/gl_gl_api_implementation.cc \
+	ui/gl/gl_image.cc \
+	ui/gl/gl_image_android.cc \
+	ui/gl/gl_image_shm.cc \
+	ui/gl/gl_image_stub.cc \
+	ui/gl/gl_implementation.cc \
+	ui/gl/gl_implementation_android.cc \
+	ui/gl/gl_osmesa_api_implementation.cc \
+	ui/gl/gl_share_group.cc \
+	ui/gl/gl_state_restorer.cc \
+	ui/gl/gl_surface.cc \
+	ui/gl/gl_surface_android.cc \
+	ui/gl/gl_surface_stub.cc \
+	ui/gl/gl_surface_osmesa.cc \
+	ui/gl/gl_switches.cc \
+	ui/gl/gl_version_info.cc \
+	ui/gl/gpu_switching_manager.cc \
+	ui/gl/scoped_binders.cc \
+	ui/gl/scoped_make_current.cc \
+	ui/gl/sync_control_vsync_provider.cc \
+	ui/gl/egl_util.cc \
+	ui/gl/gl_context_egl.cc \
+	ui/gl/gl_image_egl.cc \
+	ui/gl/gl_surface_egl.cc \
+	ui/gl/gl_egl_api_implementation.cc \
+	ui/gl/gl_implementation_osmesa.cc \
+	ui/gl/gl_image_android_native_buffer.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGL_IMPLEMENTATION' \
+	'-DGL_GLEXT_PROTOTYPES' \
+	'-DEGL_EGLEXT_PROTOTYPES' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/swiftshader/include \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DGL_IMPLEMENTATION' \
+	'-DGL_GLEXT_PROTOTYPES' \
+	'-DEGL_EGLEXT_PROTOTYPES' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/swiftshader/include \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gl_gl_gyp
+
+# Alias gyp target name.
+.PHONY: gl
+gl: ui_gl_gl_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index d2deb61..cd9a28c 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -26,20 +26,6 @@
     current_real_context_ = LAZY_INSTANCE_INITIALIZER;
 }  // namespace
 
-GLContext::FlushEvent::FlushEvent() {
-}
-
-GLContext::FlushEvent::~FlushEvent() {
-}
-
-void GLContext::FlushEvent::Signal() {
-  flag_.Set();
-}
-
-bool GLContext::FlushEvent::IsSignaled() {
-  return flag_.IsSet();
-}
-
 GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) {
   if (!share_group_.get())
     share_group_ = new GLShareGroup;
@@ -54,13 +40,6 @@
   }
 }
 
-scoped_refptr<GLContext::FlushEvent> GLContext::SignalFlush() {
-  DCHECK(IsCurrent(NULL));
-  scoped_refptr<FlushEvent> flush_event = new FlushEvent();
-  flush_events_.push_back(flush_event);
-  return flush_event;
-}
-
 bool GLContext::GetTotalGpuMemory(size_t* bytes) {
   DCHECK(bytes);
   *bytes = 0;
@@ -193,12 +172,6 @@
   SetGLToRealGLApi();
 }
 
-void GLContext::OnFlush() {
-  for (size_t n = 0; n < flush_events_.size(); n++)
-    flush_events_[n]->Signal();
-  flush_events_.clear();
-}
-
 GLContextReal::GLContextReal(GLShareGroup* share_group)
     : GLContext(share_group) {}
 
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index b4a7a16..f40b1bb 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -6,12 +6,10 @@
 #define UI_GL_GL_CONTEXT_H_
 
 #include <string>
-#include <vector>
 
 #include "base/basictypes.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/synchronization/cancellation_flag.h"
 #include "ui/gl/gl_share_group.h"
 #include "ui/gl/gl_state_restorer.h"
 #include "ui/gl/gpu_preference.h"
@@ -34,25 +32,6 @@
   virtual bool Initialize(
       GLSurface* compatible_surface, GpuPreference gpu_preference) = 0;
 
-  class FlushEvent : public base::RefCountedThreadSafe<FlushEvent> {
-    public:
-      bool IsSignaled();
-
-    private:
-      friend class base::RefCountedThreadSafe<FlushEvent>;
-      friend class GLContext;
-      FlushEvent();
-      virtual ~FlushEvent();
-      void Signal();
-
-      base::CancellationFlag flag_;
-  };
-
-  // Needs to be called with this context current. It will return a FlushEvent
-  // that is initially unsignaled, but will transition to signaled after the
-  // next glFlush() or glFinish() occurs in this context.
-  scoped_refptr<FlushEvent> SignalFlush();
-
   // Destroys the GL context.
   virtual void Destroy() = 0;
 
@@ -135,9 +114,6 @@
   // Returns the GL renderer string. The context must be current.
   virtual std::string GetGLRenderer();
 
-  // Called when glFlush()/glFinish() is called with this context current.
-  void OnFlush();
-
  protected:
   virtual ~GLContext();
 
@@ -164,8 +140,6 @@
   scoped_ptr<GLStateRestorer> state_restorer_;
   scoped_ptr<GLVersionInfo> version_info_;
 
-  std::vector<scoped_refptr<FlushEvent> > flush_events_;
-
   DISALLOW_COPY_AND_ASSIGN(GLContext);
 };
 
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
index 262de48..f44570e 100644
--- a/ui/gl/gl_fence.cc
+++ b/ui/gl/gl_fence.cc
@@ -25,11 +25,8 @@
     //     We will arbitrarily return TRUE for consistency.
     glGenFencesNV(1, &fence_);
     glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
-    if (flush) {
+    if (flush)
       glFlush();
-    } else {
-      flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
-    }
   }
 
   virtual bool HasCompleted() OVERRIDE {
@@ -37,15 +34,11 @@
   }
 
   virtual void ClientWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      glFinishFenceNV(fence_);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
+    glFinishFenceNV(fence_);
   }
 
   virtual void ServerWait() OVERRIDE {
-    ClientWait();
+    glFinishFenceNV(fence_);
   }
 
  private:
@@ -54,18 +47,14 @@
   }
 
   GLuint fence_;
-  scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
 };
 
 class GLFenceARBSync: public gfx::GLFence {
  public:
   GLFenceARBSync(bool flush) {
     sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
-    if (flush) {
+    if (flush)
       glFlush();
-    } else {
-      flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
-    }
   }
 
   virtual bool HasCompleted() OVERRIDE {
@@ -80,19 +69,11 @@
   }
 
   virtual void ClientWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
+    glClientWaitSync(sync_, GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
   }
 
   virtual void ServerWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
+    glWaitSync(sync_, 0, GL_TIMEOUT_IGNORED);
   }
 
  private:
@@ -101,7 +82,6 @@
   }
 
   GLsync sync_;
-  scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
 };
 
 #if !defined(OS_MACOSX)
@@ -110,11 +90,8 @@
   EGLFenceSync(bool flush) {
     display_ = eglGetCurrentDisplay();
     sync_ = eglCreateSyncKHR(display_, EGL_SYNC_FENCE_KHR, NULL);
-    if (flush) {
+    if (flush)
       glFlush();
-    } else {
-      flush_event_ = gfx::GLContext::GetCurrent()->SignalFlush();
-    }
   }
 
   virtual bool HasCompleted() OVERRIDE {
@@ -125,22 +102,14 @@
   }
 
   virtual void ClientWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      EGLint flags = 0;
-      EGLTimeKHR time = EGL_FOREVER_KHR;
-      eglClientWaitSyncKHR(display_, sync_, flags, time);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
+    EGLint flags = 0;
+    EGLTimeKHR time = EGL_FOREVER_KHR;
+    eglClientWaitSyncKHR(display_, sync_, flags, time);
   }
 
   virtual void ServerWait() OVERRIDE {
-    if (!flush_event_ || flush_event_->IsSignaled()) {
-      EGLint flags = 0;
-      eglWaitSyncKHR(display_, sync_, flags);
-    } else {
-      LOG(ERROR) << "Trying to wait for uncommitted fence. Skipping...";
-    }
+    EGLint flags = 0;
+    eglWaitSyncKHR(display_, sync_, flags);
   }
 
 
@@ -151,15 +120,11 @@
 
   EGLSyncKHR sync_;
   EGLDisplay display_;
-  scoped_refptr<gfx::GLContext::FlushEvent> flush_event_;
 };
 #endif // !OS_MACOSX
 
 // static
 gfx::GLFence* CreateFence(bool flush) {
-  DCHECK(gfx::GLContext::GetCurrent())
-      << "Trying to create fence with no context";
-
 #if !defined(OS_MACOSX)
   if (gfx::g_driver_egl.ext.b_EGL_KHR_fence_sync)
     return new EGLFenceSync(flush);
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
index 021f345..c1967ec 100644
--- a/ui/gl/gl_fence.h
+++ b/ui/gl/gl_fence.h
@@ -16,16 +16,11 @@
   virtual ~GLFence();
 
   static GLFence* Create();
-
   // Creates a fence that is not guaranteed to signal until the current context
-  // is flushed. It is illegal to call Client/ServerWait() on a fence without
-  // having explicitly called glFlush() or glFinish() in the originating
-  // context.
+  // is flushed. Use with caution.
   static GLFence* CreateWithoutFlush();
-
   virtual bool HasCompleted() = 0;
   virtual void ClientWait() = 0;
-
   // Will block the server if supported, but might fall back to blocking the
   // client.
   virtual void ServerWait() = 0;
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index 0965d91..f925f64 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -343,11 +343,6 @@
   driver_ = driver;
 }
 
-void GLApiBase::SignalFlush() {
-  DCHECK(GLContext::GetCurrent());
-  GLContext::GetCurrent()->OnFlush();
-}
-
 RealGLApi::RealGLApi() {
 }
 
@@ -358,16 +353,6 @@
   InitializeBase(driver);
 }
 
-void RealGLApi::glFlushFn() {
-  GLApiBase::glFlushFn();
-  GLApiBase::SignalFlush();
-}
-
-void RealGLApi::glFinishFn() {
-  GLApiBase::glFinishFn();
-  GLApiBase::SignalFlush();
-}
-
 TraceGLApi::~TraceGLApi() {
 }
 
@@ -460,14 +445,4 @@
   }
 }
 
-void VirtualGLApi::glFlushFn() {
-  GLApiBase::glFlushFn();
-  GLApiBase::SignalFlush();
-}
-
-void VirtualGLApi::glFinishFn() {
-  GLApiBase::glFinishFn();
-  GLApiBase::SignalFlush();
-}
-
 }  // namespace gfx
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h
index e764ec3..c87dbd1 100644
--- a/ui/gl/gl_gl_api_implementation.h
+++ b/ui/gl/gl_gl_api_implementation.h
@@ -41,7 +41,6 @@
   GLApiBase();
   virtual ~GLApiBase();
   void InitializeBase(DriverGL* driver);
-  void SignalFlush();
 
   DriverGL* driver_;
 };
@@ -52,10 +51,6 @@
   RealGLApi();
   virtual ~RealGLApi();
   void Initialize(DriverGL* driver);
-
- private:
-  virtual void glFinishFn() OVERRIDE;
-  virtual void glFlushFn() OVERRIDE;
 };
 
 // Inserts a TRACE for every GL call.
@@ -87,12 +82,10 @@
 
   void OnReleaseVirtuallyCurrent(GLContext* virtual_context);
 
-private:
   // Overridden functions from GLApiBase
   virtual const GLubyte* glGetStringFn(GLenum name) OVERRIDE;
-  virtual void glFinishFn() OVERRIDE;
-  virtual void glFlushFn() OVERRIDE;
 
+ private:
   // The real context we're running on.
   GLContext* real_context_;
 
diff --git a/ui/gl/gl_glx_api_implementation.cc b/ui/gl/gl_glx_api_implementation.cc
index 444a1b2..0392c39 100644
--- a/ui/gl/gl_glx_api_implementation.cc
+++ b/ui/gl/gl_glx_api_implementation.cc
@@ -81,6 +81,7 @@
     info->version = version;
   if (extensions)
     info->extensions = extensions;
+  info->direct_rendering = !!glXIsDirect(display, glXGetCurrentContext());
   return true;
 }
 
diff --git a/ui/gl/gl_image_android.cc b/ui/gl/gl_image_android.cc
index e56dc2d..4d04be1 100644
--- a/ui/gl/gl_image_android.cc
+++ b/ui/gl/gl_image_android.cc
@@ -5,7 +5,7 @@
 #include "ui/gl/gl_image.h"
 
 #include "base/debug/trace_event.h"
-#include "ui/gl/gl_image_egl.h"
+#include "ui/gl/gl_image_android_native_buffer.h"
 #include "ui/gl/gl_image_shm.h"
 #include "ui/gl/gl_image_stub.h"
 #include "ui/gl/gl_implementation.h"
@@ -41,8 +41,9 @@
 
           return image;
         }
-        case EGL_CLIENT_BUFFER: {
-          scoped_refptr<GLImageEGL> image(new GLImageEGL(size));
+        case ANDROID_NATIVE_BUFFER: {
+          scoped_refptr<GLImageAndroidNativeBuffer> image(
+              new GLImageAndroidNativeBuffer(size));
           if (!image->Initialize(buffer))
             return NULL;
 
diff --git a/ui/gl/gl_image_android_native_buffer.cc b/ui/gl/gl_image_android_native_buffer.cc
new file mode 100644
index 0000000..6d11497
--- /dev/null
+++ b/ui/gl/gl_image_android_native_buffer.cc
@@ -0,0 +1,118 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_image_android_native_buffer.h"
+
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/scoped_binders.h"
+
+namespace gfx {
+
+GLImageAndroidNativeBuffer::GLImageAndroidNativeBuffer(gfx::Size size)
+    : GLImageEGL(size),
+      release_after_use_(false),
+      in_use_(false),
+      target_(0),
+      egl_image_for_unbind_(EGL_NO_IMAGE_KHR),
+      texture_id_for_unbind_(0) {}
+
+GLImageAndroidNativeBuffer::~GLImageAndroidNativeBuffer() { Destroy(); }
+
+bool GLImageAndroidNativeBuffer::Initialize(gfx::GpuMemoryBufferHandle buffer) {
+  DCHECK(buffer.native_buffer);
+
+  EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+  return GLImageEGL::Initialize(
+      EGL_NATIVE_BUFFER_ANDROID, buffer.native_buffer, attrs);
+}
+
+void GLImageAndroidNativeBuffer::Destroy() {
+  if (egl_image_for_unbind_ != EGL_NO_IMAGE_KHR) {
+    eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
+                       egl_image_for_unbind_);
+    egl_image_for_unbind_ = EGL_NO_IMAGE_KHR;
+  }
+  if (texture_id_for_unbind_) {
+    glDeleteTextures(1, &texture_id_for_unbind_);
+    texture_id_for_unbind_ = 0;
+  }
+
+  GLImageEGL::Destroy();
+}
+
+bool GLImageAndroidNativeBuffer::BindTexImage(unsigned target) {
+  DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
+
+  if (target == GL_TEXTURE_RECTANGLE_ARB) {
+    LOG(ERROR) << "EGLImage cannot be bound to TEXTURE_RECTANGLE_ARB target";
+    return false;
+  }
+
+  if (target_ && target_ != target) {
+    LOG(ERROR) << "EGLImage can only be bound to one target";
+    return false;
+  }
+  target_ = target;
+
+  // Defer ImageTargetTexture2D if not currently in use.
+  if (!in_use_)
+    return true;
+
+  glEGLImageTargetTexture2DOES(target_, egl_image_);
+  DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+  return true;
+}
+
+void GLImageAndroidNativeBuffer::WillUseTexImage() {
+  DCHECK(egl_image_);
+  DCHECK(!in_use_);
+  in_use_ = true;
+  glEGLImageTargetTexture2DOES(target_, egl_image_);
+  DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+void GLImageAndroidNativeBuffer::DidUseTexImage() {
+  DCHECK(in_use_);
+  in_use_ = false;
+
+  if (!release_after_use_)
+    return;
+
+  if (egl_image_for_unbind_ == EGL_NO_IMAGE_KHR) {
+    DCHECK_EQ(0u, texture_id_for_unbind_);
+    glGenTextures(1, &texture_id_for_unbind_);
+
+    {
+      ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id_for_unbind_);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+      char zero[4] = {0, };
+      glTexImage2D(
+          GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, &zero);
+    }
+
+    EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+    // Need to pass current EGL rendering context to eglCreateImageKHR for
+    // target type EGL_GL_TEXTURE_2D_KHR.
+    egl_image_for_unbind_ = eglCreateImageKHR(
+        GLSurfaceEGL::GetHardwareDisplay(),
+        eglGetCurrentContext(),
+        EGL_GL_TEXTURE_2D_KHR,
+        reinterpret_cast<EGLClientBuffer>(texture_id_for_unbind_),
+        attrs);
+    DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_for_unbind_)
+        << "Error creating EGLImage: " << eglGetError();
+  }
+
+  glEGLImageTargetTexture2DOES(target_, egl_image_for_unbind_);
+  DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+void GLImageAndroidNativeBuffer::SetReleaseAfterUse() {
+  release_after_use_ = true;
+}
+
+}  // namespace gfx
diff --git a/ui/gl/gl_image_android_native_buffer.h b/ui/gl/gl_image_android_native_buffer.h
new file mode 100644
index 0000000..28fe5c1
--- /dev/null
+++ b/ui/gl/gl_image_android_native_buffer.h
@@ -0,0 +1,40 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_IMAGE_ANDROID_NATIVE_BUFFER_H_
+#define UI_GL_GL_IMAGE_ANDROID_NATIVE_BUFFER_H_
+
+#include "ui/gl/gl_image_egl.h"
+
+namespace gfx {
+
+class GL_EXPORT GLImageAndroidNativeBuffer : public GLImageEGL {
+ public:
+  explicit GLImageAndroidNativeBuffer(gfx::Size size);
+
+  bool Initialize(gfx::GpuMemoryBufferHandle buffer);
+
+  // Overridden from GLImage:
+  virtual void Destroy() OVERRIDE;
+  virtual bool BindTexImage(unsigned target) OVERRIDE;
+  virtual void WillUseTexImage() OVERRIDE;
+  virtual void DidUseTexImage() OVERRIDE;
+  virtual void SetReleaseAfterUse() OVERRIDE;
+
+ protected:
+  virtual ~GLImageAndroidNativeBuffer();
+
+ private:
+  bool release_after_use_;
+  bool in_use_;
+  unsigned target_;
+  EGLImageKHR egl_image_for_unbind_;
+  GLuint texture_id_for_unbind_;
+
+  DISALLOW_COPY_AND_ASSIGN(GLImageAndroidNativeBuffer);
+};
+
+}  // namespace gfx
+
+#endif  // UI_GL_GL_IMAGE_ANDROID_NATIVE_BUFFER_H_
diff --git a/ui/gl/gl_image_egl.cc b/ui/gl/gl_image_egl.cc
index ddd2f6f..5531c8d 100644
--- a/ui/gl/gl_image_egl.cc
+++ b/ui/gl/gl_image_egl.cc
@@ -4,36 +4,24 @@
 
 #include "ui/gl/gl_image_egl.h"
 
-#include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_surface_egl.h"
 
 namespace gfx {
 
 GLImageEGL::GLImageEGL(gfx::Size size)
-    : egl_image_(EGL_NO_IMAGE_KHR),
-      size_(size),
-      release_after_use_(false),
-      in_use_(false),
-      target_(0) {
-}
+    : egl_image_(EGL_NO_IMAGE_KHR), size_(size) {}
 
-GLImageEGL::~GLImageEGL() {
-  Destroy();
-}
+GLImageEGL::~GLImageEGL() { Destroy(); }
 
-bool GLImageEGL::Initialize(gfx::GpuMemoryBufferHandle buffer) {
-  DCHECK(buffer.native_buffer);
-  EGLint attrs[] = {
-    EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
-    EGL_NONE,
-  };
-  egl_image_ = eglCreateImageKHR(
-      GLSurfaceEGL::GetHardwareDisplay(),
-      EGL_NO_CONTEXT,
-      EGL_NATIVE_BUFFER_ANDROID,
-      buffer.native_buffer,
-      attrs);
-
+bool GLImageEGL::Initialize(EGLenum target,
+                            EGLClientBuffer buffer,
+                            const EGLint* attrs) {
+  DCHECK_EQ(EGL_NO_IMAGE_KHR, egl_image_);
+  egl_image_ = eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
+                                 EGL_NO_CONTEXT,
+                                 target,
+                                 buffer,
+                                 attrs);
   if (egl_image_ == EGL_NO_IMAGE_KHR) {
     EGLint error = eglGetError();
     LOG(ERROR) << "Error creating EGLImage: " << error;
@@ -44,90 +32,19 @@
 }
 
 void GLImageEGL::Destroy() {
-  if (egl_image_ == EGL_NO_IMAGE_KHR)
-    return;
-
-  EGLBoolean success = eglDestroyImageKHR(
-      GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
-
-  if (success == EGL_FALSE) {
-    EGLint error = eglGetError();
-    LOG(ERROR) << "Error destroying EGLImage: " << error;
+  if (egl_image_ != EGL_NO_IMAGE_KHR) {
+    eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
+    egl_image_ = EGL_NO_IMAGE_KHR;
   }
-
-  egl_image_ = EGL_NO_IMAGE_KHR;
 }
 
-gfx::Size GLImageEGL::GetSize() {
-  return size_;
-}
+gfx::Size GLImageEGL::GetSize() { return size_; }
 
 bool GLImageEGL::BindTexImage(unsigned target) {
-  if (egl_image_ == EGL_NO_IMAGE_KHR) {
-    LOG(ERROR) << "NULL EGLImage in BindTexImage";
-    return false;
-  }
-
-  if (target == GL_TEXTURE_RECTANGLE_ARB) {
-    LOG(ERROR) << "EGLImage cannot be bound to TEXTURE_RECTANGLE_ARB target";
-    return false;
-  }
-
-  if (target_ && target_ != target) {
-    LOG(ERROR) << "EGLImage can only be bound to one target";
-    return false;
-  }
-  target_ = target;
-
-  // Defer ImageTargetTexture2D if not currently in use.
-  if (!in_use_)
-    return true;
-
-  glEGLImageTargetTexture2DOES(target_, egl_image_);
+  DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_);
+  glEGLImageTargetTexture2DOES(target, egl_image_);
   DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
   return true;
 }
 
-void GLImageEGL::ReleaseTexImage(unsigned target) {
-  // Nothing to do here as image is released after each use or there is no need
-  // to release image.
-}
-
-void GLImageEGL::WillUseTexImage() {
-  DCHECK(egl_image_);
-  DCHECK(!in_use_);
-  in_use_ = true;
-  glEGLImageTargetTexture2DOES(target_, egl_image_);
-  DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
-}
-
-void GLImageEGL::DidUseTexImage() {
-  DCHECK(in_use_);
-  in_use_ = false;
-
-  if (!release_after_use_)
-    return;
-
-  char zero[4] = { 0, };
-  glTexImage2D(target_,
-               0,
-               GL_RGBA,
-               1,
-               1,
-               0,
-               GL_RGBA,
-               GL_UNSIGNED_BYTE,
-               &zero);
-}
-
-void GLImageEGL::WillModifyTexImage() {
-}
-
-void GLImageEGL::DidModifyTexImage() {
-}
-
-void GLImageEGL::SetReleaseAfterUse() {
-  release_after_use_ = true;
-}
-
 }  // namespace gfx
diff --git a/ui/gl/gl_image_egl.h b/ui/gl/gl_image_egl.h
index 5a1b5b3..1339654 100644
--- a/ui/gl/gl_image_egl.h
+++ b/ui/gl/gl_image_egl.h
@@ -5,7 +5,7 @@
 #ifndef UI_GL_GL_IMAGE_EGL_H_
 #define UI_GL_GL_IMAGE_EGL_H_
 
-#include "ui/gl/gl_bindings.h"  // for EGLImageKHR
+#include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_image.h"
 
 namespace gfx {
@@ -14,29 +14,25 @@
  public:
   explicit GLImageEGL(gfx::Size size);
 
-  bool Initialize(gfx::GpuMemoryBufferHandle buffer);
+  bool Initialize(EGLenum target, EGLClientBuffer buffer, const EGLint* attrs);
 
-  // Implement GLImage.
+  // Overridden from GLImage:
   virtual void Destroy() OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
   virtual bool BindTexImage(unsigned target) OVERRIDE;
-  virtual void ReleaseTexImage(unsigned target) OVERRIDE;
-  virtual void WillUseTexImage() OVERRIDE;
-  virtual void DidUseTexImage() OVERRIDE;
-  virtual void WillModifyTexImage() OVERRIDE;
-  virtual void DidModifyTexImage() OVERRIDE;
-  virtual void SetReleaseAfterUse() OVERRIDE;
+  virtual void ReleaseTexImage(unsigned target) OVERRIDE {}
+  virtual void WillUseTexImage() OVERRIDE {}
+  virtual void DidUseTexImage() OVERRIDE {}
+  virtual void WillModifyTexImage() OVERRIDE {}
+  virtual void DidModifyTexImage() OVERRIDE {}
 
  protected:
   virtual ~GLImageEGL();
 
- private:
   EGLImageKHR egl_image_;
   gfx::Size size_;
-  bool release_after_use_;
-  bool in_use_;
-  unsigned target_;
 
+ private:
   DISALLOW_COPY_AND_ASSIGN(GLImageEGL);
 };
 
diff --git a/ui/gl/gl_image_glx.cc b/ui/gl/gl_image_glx.cc
index 018c761..b68a5fe 100644
--- a/ui/gl/gl_image_glx.cc
+++ b/ui/gl/gl_image_glx.cc
@@ -23,9 +23,7 @@
 //   scoped_ptr<XVisualInfo, ScopedPtrXFree> foo(...);
 // where "XVisualInfo" is any X type that is freed with XFree.
 struct ScopedPtrXFree {
-  void operator()(void* x) const {
-    ::XFree(x);
-  }
+  void operator()(void* x) const { ::XFree(x); }
 };
 
 int BindToTextureFormat(int depth) {
@@ -45,15 +43,12 @@
 }  // namespace anonymous
 
 GLImageGLX::GLImageGLX(gfx::PluginWindowHandle window)
-  : display_(base::MessagePumpForUI::GetDefaultXDisplay()),
-    window_(window),
-    pixmap_(0),
-    glx_pixmap_(0) {
-}
+    : display_(base::MessagePumpForUI::GetDefaultXDisplay()),
+      window_(window),
+      pixmap_(0),
+      glx_pixmap_(0) {}
 
-GLImageGLX::~GLImageGLX() {
-  Destroy();
-}
+GLImageGLX::~GLImageGLX() { Destroy(); }
 
 bool GLImageGLX::Initialize() {
   if (!GLSurfaceGLX::IsTextureFromPixmapSupported()) {
@@ -71,13 +66,10 @@
   templ.visualid = XVisualIDFromVisual(attributes.visual);
   int num_visinfo = 0;
   scoped_ptr<XVisualInfo, ScopedPtrXFree> visinfo(
-      XGetVisualInfo(display_,
-                     VisualIDMask,
-                     &templ,
-                     &num_visinfo));
+      XGetVisualInfo(display_, VisualIDMask, &templ, &num_visinfo));
   if (!visinfo.get()) {
-    LOG(ERROR) << "XGetVisualInfo failed for visual id " <<
-        templ.visualid << ".";
+    LOG(ERROR) << "XGetVisualInfo failed for visual id " << templ.visualid
+               << ".";
     return false;
   }
   if (!num_visinfo) {
@@ -86,19 +78,14 @@
   }
 
   int config_attribs[] = {
-    static_cast<int>(GLX_VISUAL_ID),
-    static_cast<int>(visinfo->visualid),
-    GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT,
-    GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_EXT,
-    BindToTextureFormat(visinfo->depth), GL_TRUE,
-    0
-  };
+      static_cast<int>(GLX_VISUAL_ID),     static_cast<int>(visinfo->visualid),
+      GLX_DRAWABLE_TYPE,                   GLX_PIXMAP_BIT,
+      GLX_BIND_TO_TEXTURE_TARGETS_EXT,     GLX_TEXTURE_2D_EXT,
+      BindToTextureFormat(visinfo->depth), GL_TRUE,
+      0};
   int num_elements = 0;
-  scoped_ptr<GLXFBConfig, ScopedPtrXFree> config(
-      glXChooseFBConfig(display_,
-                        DefaultScreen(display_),
-                        config_attribs,
-                        &num_elements));
+  scoped_ptr<GLXFBConfig, ScopedPtrXFree> config(glXChooseFBConfig(
+      display_, DefaultScreen(display_), config_attribs, &num_elements));
   if (!config.get()) {
     LOG(ERROR) << "glXChooseFBConfig failed.";
     return false;
@@ -124,16 +111,11 @@
     return false;
   }
 
-  int pixmap_attribs[] = {
-    GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
-    GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth),
-    0
-  };
-  glx_pixmap_ = glXCreatePixmap(
-      display_,
-      *config.get(),
-      pixmap_,
-      pixmap_attribs);
+  int pixmap_attribs[] = {GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
+                          GLX_TEXTURE_FORMAT_EXT, TextureFormat(visinfo->depth),
+                          0};
+  glx_pixmap_ =
+      glXCreatePixmap(display_, *config.get(), pixmap_, pixmap_attribs);
   if (!glx_pixmap_) {
     LOG(ERROR) << "glXCreatePixmap failed.";
     return false;
@@ -154,9 +136,7 @@
   }
 }
 
-gfx::Size GLImageGLX::GetSize() {
-  return size_;
-}
+gfx::Size GLImageGLX::GetSize() { return size_; }
 
 bool GLImageGLX::BindTexImage(unsigned target) {
   if (!glx_pixmap_)
@@ -177,16 +157,4 @@
   glXReleaseTexImageEXT(display_, glx_pixmap_, GLX_FRONT_LEFT_EXT);
 }
 
-void GLImageGLX::WillUseTexImage() {
-}
-
-void GLImageGLX::DidUseTexImage() {
-}
-
-void GLImageGLX::WillModifyTexImage() {
-}
-
-void GLImageGLX::DidModifyTexImage() {
-}
-
 }  // namespace gfx
diff --git a/ui/gl/gl_image_glx.h b/ui/gl/gl_image_glx.h
index 0fe1d3e..d945202 100644
--- a/ui/gl/gl_image_glx.h
+++ b/ui/gl/gl_image_glx.h
@@ -18,15 +18,15 @@
 
   virtual bool Initialize();
 
-  // Implement GLImage.
+  // Overridden from GLImage:
   virtual void Destroy() OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
   virtual bool BindTexImage(unsigned target) OVERRIDE;
   virtual void ReleaseTexImage(unsigned target) OVERRIDE;
-  virtual void WillUseTexImage() OVERRIDE;
-  virtual void DidUseTexImage() OVERRIDE;
-  virtual void WillModifyTexImage() OVERRIDE;
-  virtual void DidModifyTexImage() OVERRIDE;
+  virtual void WillUseTexImage() OVERRIDE {}
+  virtual void DidUseTexImage() OVERRIDE {}
+  virtual void WillModifyTexImage() OVERRIDE {}
+  virtual void DidModifyTexImage() OVERRIDE {}
 
  protected:
   virtual ~GLImageGLX();
diff --git a/ui/gl/gl_image_io_surface.cc b/ui/gl/gl_image_io_surface.cc
index 4d62651..e20c739 100644
--- a/ui/gl/gl_image_io_surface.cc
+++ b/ui/gl/gl_image_io_surface.cc
@@ -11,14 +11,11 @@
 namespace gfx {
 
 GLImageIOSurface::GLImageIOSurface(gfx::Size size)
-    : io_surface_support_(IOSurfaceSupport::Initialize()),
-      size_(size) {
+    : io_surface_support_(IOSurfaceSupport::Initialize()), size_(size) {
   CHECK(io_surface_support_);
 }
 
-GLImageIOSurface::~GLImageIOSurface() {
-  Destroy();
-}
+GLImageIOSurface::~GLImageIOSurface() { Destroy(); }
 
 bool GLImageIOSurface::Initialize(gfx::GpuMemoryBufferHandle buffer) {
   io_surface_.reset(io_surface_support_->IOSurfaceLookup(buffer.io_surface_id));
@@ -30,12 +27,7 @@
   return true;
 }
 
-void GLImageIOSurface::Destroy() {
-}
-
-gfx::Size GLImageIOSurface::GetSize() {
-  return size_;
-}
+gfx::Size GLImageIOSurface::GetSize() { return size_; }
 
 bool GLImageIOSurface::BindTexImage(unsigned target) {
   if (target != GL_TEXTURE_RECTANGLE_ARB) {
@@ -45,20 +37,20 @@
     return false;
   }
 
-  CGLContextObj cgl_context = static_cast<CGLContextObj>(
-      GLContext::GetCurrent()->GetHandle());
+  CGLContextObj cgl_context =
+      static_cast<CGLContextObj>(GLContext::GetCurrent()->GetHandle());
 
   DCHECK(io_surface_);
-  CGLError cgl_error = io_surface_support_->CGLTexImageIOSurface2D(
-      cgl_context,
-      target,
-      GL_RGBA,
-      size_.width(),
-      size_.height(),
-      GL_BGRA,
-      GL_UNSIGNED_INT_8_8_8_8_REV,
-      io_surface_.get(),
-      0);
+  CGLError cgl_error =
+      io_surface_support_->CGLTexImageIOSurface2D(cgl_context,
+                                                  target,
+                                                  GL_RGBA,
+                                                  size_.width(),
+                                                  size_.height(),
+                                                  GL_BGRA,
+                                                  GL_UNSIGNED_INT_8_8_8_8_REV,
+                                                  io_surface_.get(),
+                                                  0);
   if (cgl_error != kCGLNoError) {
     LOG(ERROR) << "Error in CGLTexImageIOSurface2D";
     return false;
@@ -67,19 +59,4 @@
   return true;
 }
 
-void GLImageIOSurface::ReleaseTexImage(unsigned target) {
-}
-
-void GLImageIOSurface::WillUseTexImage() {
-}
-
-void GLImageIOSurface::DidUseTexImage() {
-}
-
-void GLImageIOSurface::WillModifyTexImage() {
-}
-
-void GLImageIOSurface::DidModifyTexImage() {
-}
-
 }  // namespace gfx
diff --git a/ui/gl/gl_image_io_surface.h b/ui/gl/gl_image_io_surface.h
index 5739f47..79bf41c 100644
--- a/ui/gl/gl_image_io_surface.h
+++ b/ui/gl/gl_image_io_surface.h
@@ -18,15 +18,15 @@
 
   bool Initialize(gfx::GpuMemoryBufferHandle buffer);
 
-  // Implement GLImage.
-  virtual void Destroy() OVERRIDE;
+  // Overridden from GLImage:
+  virtual void Destroy() OVERRIDE {}
   virtual gfx::Size GetSize() OVERRIDE;
   virtual bool BindTexImage(unsigned target) OVERRIDE;
-  virtual void ReleaseTexImage(unsigned target) OVERRIDE;
-  virtual void WillUseTexImage() OVERRIDE;
-  virtual void DidUseTexImage() OVERRIDE;
-  virtual void WillModifyTexImage() OVERRIDE;
-  virtual void DidModifyTexImage() OVERRIDE;
+  virtual void ReleaseTexImage(unsigned target) OVERRIDE {}
+  virtual void WillUseTexImage() OVERRIDE {}
+  virtual void DidUseTexImage() OVERRIDE {}
+  virtual void WillModifyTexImage() OVERRIDE {}
+  virtual void DidModifyTexImage() OVERRIDE {}
 
  protected:
   virtual ~GLImageIOSurface();
diff --git a/ui/gl/gl_image_shm.cc b/ui/gl/gl_image_shm.cc
index 40ad67a..156d0f2 100644
--- a/ui/gl/gl_image_shm.cc
+++ b/ui/gl/gl_image_shm.cc
@@ -6,7 +6,12 @@
 
 #include "base/debug/trace_event.h"
 #include "base/process/process_handle.h"
-#include "ui/gl/gl_bindings.h"
+#include "ui/gl/scoped_binders.h"
+
+#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
+    defined(USE_OZONE)
+#include "ui/gl/gl_surface_egl.h"
+#endif
 
 namespace gfx {
 
@@ -64,12 +69,17 @@
 
 GLImageShm::GLImageShm(gfx::Size size, unsigned internalformat)
     : size_(size),
-      internalformat_(internalformat) {
+      internalformat_(internalformat)
+#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
+    defined(USE_OZONE)
+      ,
+      egl_texture_id_(0u),
+      egl_image_(EGL_NO_IMAGE_KHR)
+#endif
+{
 }
 
-GLImageShm::~GLImageShm() {
-  Destroy();
-}
+GLImageShm::~GLImageShm() { Destroy(); }
 
 bool GLImageShm::Initialize(gfx::GpuMemoryBufferHandle buffer) {
   if (!ValidFormat(internalformat_)) {
@@ -96,11 +106,21 @@
 }
 
 void GLImageShm::Destroy() {
+#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
+    defined(USE_OZONE)
+  if (egl_image_ != EGL_NO_IMAGE_KHR) {
+    eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
+    egl_image_ = EGL_NO_IMAGE_KHR;
+  }
+
+  if (egl_texture_id_) {
+    glDeleteTextures(1, &egl_texture_id_);
+    egl_texture_id_ = 0u;
+  }
+#endif
 }
 
-gfx::Size GLImageShm::GetSize() {
-  return size_;
-}
+gfx::Size GLImageShm::GetSize() { return size_; }
 
 bool GLImageShm::BindTexImage(unsigned target) {
   TRACE_EVENT0("gpu", "GLImageShm::BindTexImage");
@@ -115,6 +135,54 @@
   }
 
   DCHECK(shared_memory_->memory());
+
+#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
+    defined(USE_OZONE)
+  if (target == GL_TEXTURE_EXTERNAL_OES) {
+    if (egl_image_ != EGL_NO_IMAGE_KHR)
+      eglDestroyImageKHR(GLSurfaceEGL::GetHardwareDisplay(), egl_image_);
+
+    if (!egl_texture_id_)
+      glGenTextures(1, &egl_texture_id_);
+
+    {
+      ScopedTextureBinder texture_binder(GL_TEXTURE_2D, egl_texture_id_);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+      glTexImage2D(GL_TEXTURE_2D,
+                   0,  // mip level
+                   TextureFormat(internalformat_),
+                   size_.width(),
+                   size_.height(),
+                   0,  // border
+                   DataFormat(internalformat_),
+                   DataType(internalformat_),
+                   shared_memory_->memory());
+    }
+
+    EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE};
+    // Need to pass current EGL rendering context to eglCreateImageKHR for
+    // target type EGL_GL_TEXTURE_2D_KHR.
+    egl_image_ =
+        eglCreateImageKHR(GLSurfaceEGL::GetHardwareDisplay(),
+                          eglGetCurrentContext(),
+                          EGL_GL_TEXTURE_2D_KHR,
+                          reinterpret_cast<EGLClientBuffer>(egl_texture_id_),
+                          attrs);
+    DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_)
+        << "Error creating EGLImage: " << eglGetError();
+
+    glEGLImageTargetTexture2DOES(target, egl_image_);
+    DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+    shared_memory_->Unmap();
+    return true;
+  }
+#endif
+
+  DCHECK_NE(static_cast<GLenum>(GL_TEXTURE_EXTERNAL_OES), target);
   glTexImage2D(target,
                0,  // mip level
                TextureFormat(internalformat_),
@@ -129,19 +197,4 @@
   return true;
 }
 
-void GLImageShm::ReleaseTexImage(unsigned target) {
-}
-
-void GLImageShm::WillUseTexImage() {
-}
-
-void GLImageShm::DidUseTexImage() {
-}
-
-void GLImageShm::WillModifyTexImage() {
-}
-
-void GLImageShm::DidModifyTexImage() {
-}
-
 }  // namespace gfx
diff --git a/ui/gl/gl_image_shm.h b/ui/gl/gl_image_shm.h
index fea9d33..079bab9 100644
--- a/ui/gl/gl_image_shm.h
+++ b/ui/gl/gl_image_shm.h
@@ -6,6 +6,7 @@
 #define UI_GL_GL_IMAGE_SHM_H_
 
 #include "base/memory/scoped_ptr.h"
+#include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_image.h"
 
 namespace gfx {
@@ -20,11 +21,11 @@
   virtual void Destroy() OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
   virtual bool BindTexImage(unsigned target) OVERRIDE;
-  virtual void ReleaseTexImage(unsigned target) OVERRIDE;
-  virtual void WillUseTexImage() OVERRIDE;
-  virtual void DidUseTexImage() OVERRIDE;
-  virtual void WillModifyTexImage() OVERRIDE;
-  virtual void DidModifyTexImage() OVERRIDE;
+  virtual void ReleaseTexImage(unsigned target) OVERRIDE {}
+  virtual void WillUseTexImage() OVERRIDE {}
+  virtual void DidUseTexImage() OVERRIDE {}
+  virtual void WillModifyTexImage() OVERRIDE {}
+  virtual void DidModifyTexImage() OVERRIDE {}
 
  protected:
   virtual ~GLImageShm();
@@ -33,6 +34,11 @@
   scoped_ptr<base::SharedMemory> shared_memory_;
   gfx::Size size_;
   unsigned internalformat_;
+#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || \
+    defined(USE_OZONE)
+  GLuint egl_texture_id_;
+  EGLImageKHR egl_image_;
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(GLImageShm);
 };
diff --git a/ui/gl/gl_image_stub.cc b/ui/gl/gl_image_stub.cc
index 2a5ecde..d789ce5 100644
--- a/ui/gl/gl_image_stub.cc
+++ b/ui/gl/gl_image_stub.cc
@@ -6,37 +6,12 @@
 
 namespace gfx {
 
-GLImageStub::GLImageStub() {
-}
+GLImageStub::GLImageStub() {}
 
-GLImageStub::~GLImageStub() {
-  Destroy();
-}
+GLImageStub::~GLImageStub() { Destroy(); }
 
-void GLImageStub::Destroy() {
-}
+gfx::Size GLImageStub::GetSize() { return gfx::Size(1, 1); }
 
-gfx::Size GLImageStub::GetSize() {
-  return gfx::Size(1, 1);
-}
-
-bool GLImageStub::BindTexImage(unsigned target) {
-  return true;
-}
-
-void GLImageStub::ReleaseTexImage(unsigned target) {
-}
-
-void GLImageStub::WillUseTexImage() {
-}
-
-void GLImageStub::DidUseTexImage() {
-}
-
-void GLImageStub::WillModifyTexImage() {
-}
-
-void GLImageStub::DidModifyTexImage() {
-}
+bool GLImageStub::BindTexImage(unsigned target) { return true; }
 
 }  // namespace gfx
diff --git a/ui/gl/gl_image_stub.h b/ui/gl/gl_image_stub.h
index e2593ef..5f2fdb2 100644
--- a/ui/gl/gl_image_stub.h
+++ b/ui/gl/gl_image_stub.h
@@ -14,15 +14,15 @@
  public:
   GLImageStub();
 
-  // Implement GLImage.
-  virtual void Destroy() OVERRIDE;
+  // Overridden from GLImage:
+  virtual void Destroy() OVERRIDE {}
   virtual gfx::Size GetSize() OVERRIDE;
   virtual bool BindTexImage(unsigned target) OVERRIDE;
-  virtual void ReleaseTexImage(unsigned target) OVERRIDE;
-  virtual void WillUseTexImage() OVERRIDE;
-  virtual void DidUseTexImage() OVERRIDE;
-  virtual void WillModifyTexImage() OVERRIDE;
-  virtual void DidModifyTexImage() OVERRIDE;
+  virtual void ReleaseTexImage(unsigned target) OVERRIDE {}
+  virtual void WillUseTexImage() OVERRIDE {}
+  virtual void DidUseTexImage() OVERRIDE {}
+  virtual void WillModifyTexImage() OVERRIDE {}
+  virtual void DidModifyTexImage() OVERRIDE {}
 
  protected:
   virtual ~GLImageStub();
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index a7db8b0..9d6b34e 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -161,4 +161,7 @@
   SetNullDrawGLBindingsEnabledGL(initial_enabled_);
 }
 
+GLWindowSystemBindingInfo::GLWindowSystemBindingInfo()
+    : direct_rendering(true) {}
+
 }  // namespace gfx
diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h
index 6f4eaf7..7319b47 100644
--- a/ui/gl/gl_implementation.h
+++ b/ui/gl/gl_implementation.h
@@ -27,10 +27,12 @@
   kGLImplementationMockGL
 };
 
-struct GLWindowSystemBindingInfo {
+struct GL_EXPORT GLWindowSystemBindingInfo {
+  GLWindowSystemBindingInfo();
   std::string vendor;
   std::string version;
   std::string extensions;
+  bool direct_rendering;
 };
 
 void GetAllowedGLImplementations(std::vector<GLImplementation>* impls);
diff --git a/ui/gl/gl_implementation_osmesa.cc b/ui/gl/gl_implementation_osmesa.cc
index f090735..c8ef874 100644
--- a/ui/gl/gl_implementation_osmesa.cc
+++ b/ui/gl/gl_implementation_osmesa.cc
@@ -17,10 +17,11 @@
 
 // Load a library, printing an error message on failure.
 base::NativeLibrary LoadLibrary(const base::FilePath& filename) {
-  std::string error;
+  base::NativeLibraryLoadError error;
   base::NativeLibrary library = base::LoadNativeLibrary(filename, &error);
   if (!library) {
-    DVLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": " << error;
+    DVLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": "
+             << error.ToString();
     return NULL;
   }
   return library;
diff --git a/ui/gl/gl_jni_headers.target.darwin-arm.mk b/ui/gl/gl_jni_headers.target.darwin-arm.mk
index eb01578..61125a4 100644
--- a/ui/gl/gl_jni_headers.target.darwin-arm.mk
+++ b/ui/gl/gl_jni_headers.target.darwin-arm.mk
@@ -108,6 +108,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl_jni_headers.target.darwin-mips.mk b/ui/gl/gl_jni_headers.target.darwin-mips.mk
index e57c056..dbd612a 100644
--- a/ui/gl/gl_jni_headers.target.darwin-mips.mk
+++ b/ui/gl/gl_jni_headers.target.darwin-mips.mk
@@ -107,6 +107,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl_jni_headers.target.darwin-x86.mk b/ui/gl/gl_jni_headers.target.darwin-x86.mk
index a6ad752..95f6dc7 100644
--- a/ui/gl/gl_jni_headers.target.darwin-x86.mk
+++ b/ui/gl/gl_jni_headers.target.darwin-x86.mk
@@ -109,6 +109,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -191,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl_jni_headers.target.darwin-x86_64.mk b/ui/gl/gl_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..dcbc2c3
--- /dev/null
+++ b/ui/gl/gl_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,247 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_gl_gl_jni_headers_gyp
+LOCAL_MODULE_STEM := gl_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,ui_gl_surface_jni_headers_gyp)/surface_jni_headers.stamp
+
+
+### Generated for rule "ui_gl_gl_gyp_gl_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/gl/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java', '../android/java/src/org/chromium/ui/gl/SurfaceTextureListener.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/ui/gl/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gl/jni; cd $(gyp_local_path)/ui/gl; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gl/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gl_gl_jni_headers_gyp_rule_trigger
+ui_gl_gl_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gl/SurfaceTextureListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gl/jni; cd $(gyp_local_path)/ui/gl; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gl/SurfaceTextureListener.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gl/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gl_gl_jni_headers_gyp_rule_trigger
+ui_gl_gl_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h \
+	ui_gl_gl_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gl_gl_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: gl_jni_headers
+gl_jni_headers: ui_gl_gl_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/gl/gl_jni_headers.target.linux-arm.mk b/ui/gl/gl_jni_headers.target.linux-arm.mk
index eb01578..61125a4 100644
--- a/ui/gl/gl_jni_headers.target.linux-arm.mk
+++ b/ui/gl/gl_jni_headers.target.linux-arm.mk
@@ -108,6 +108,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl_jni_headers.target.linux-mips.mk b/ui/gl/gl_jni_headers.target.linux-mips.mk
index e57c056..dbd612a 100644
--- a/ui/gl/gl_jni_headers.target.linux-mips.mk
+++ b/ui/gl/gl_jni_headers.target.linux-mips.mk
@@ -107,6 +107,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl_jni_headers.target.linux-x86.mk b/ui/gl/gl_jni_headers.target.linux-x86.mk
index a6ad752..95f6dc7 100644
--- a/ui/gl/gl_jni_headers.target.linux-x86.mk
+++ b/ui/gl/gl_jni_headers.target.linux-x86.mk
@@ -109,6 +109,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -191,6 +192,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/gl_jni_headers.target.linux-x86_64.mk b/ui/gl/gl_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..dcbc2c3
--- /dev/null
+++ b/ui/gl/gl_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,247 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_gl_gl_jni_headers_gyp
+LOCAL_MODULE_STEM := gl_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,ui_gl_surface_jni_headers_gyp)/surface_jni_headers.stamp
+
+
+### Generated for rule "ui_gl_gl_gyp_gl_jni_headers_target_generate_jni_headers":
+# "{'inputs': ['../../base/android/jni_generator/jni_generator.py', '../../android_webview/build/jarjar-rules.txt'], 'process_outputs_as_sources': '1', 'extension': 'java', 'outputs': ['$(gyp_shared_intermediate_dir)/ui/gl/jni/%(INPUT_ROOT)s_jni.h'], 'rule_name': 'generate_jni_headers', 'rule_sources': ['../android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java', '../android/java/src/org/chromium/ui/gl/SurfaceTextureListener.java'], 'action': ['../../base/android/jni_generator/jni_generator.py', '--input_file', '$(RULE_SOURCES)', '--output_dir', '$(gyp_shared_intermediate_dir)/ui/gl/jni', '--includes', 'base/android/jni_generator/jni_generator_helper.h', '--optimize_generation', '0', '--jarjar', '../../android_webview/build/jarjar-rules.txt', '--ptr_type', 'long'], 'message': 'Generating JNI bindings from $(RULE_SOURCES)'}":
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gl/jni; cd $(gyp_local_path)/ui/gl; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gl/SurfaceTexturePlatformWrapper.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gl/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gl_gl_jni_headers_gyp_rule_trigger
+ui_gl_gl_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h
+
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h: $(LOCAL_PATH)/ui/android/java/src/org/chromium/ui/gl/SurfaceTextureListener.java $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(LOCAL_PATH)/android_webview/build/jarjar-rules.txt $(GYP_TARGET_DEPENDENCIES)
+	mkdir -p $(gyp_shared_intermediate_dir)/ui/gl/jni; cd $(gyp_local_path)/ui/gl; ../../base/android/jni_generator/jni_generator.py --input_file ../android/java/src/org/chromium/ui/gl/SurfaceTextureListener.java --output_dir "$(gyp_shared_intermediate_dir)/ui/gl/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0 --jarjar ../../android_webview/build/jarjar-rules.txt --ptr_type long
+
+.PHONY: ui_gl_gl_jni_headers_gyp_rule_trigger
+ui_gl_gl_jni_headers_gyp_rule_trigger: $(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h
+
+### Finished generating for all rules
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTexturePlatformWrapper_jni.h \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/SurfaceTextureListener_jni.h \
+	ui_gl_gl_jni_headers_gyp_rule_trigger
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gl_gl_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: gl_jni_headers
+gl_jni_headers: ui_gl_gl_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/gl/gl_state_restorer.h b/ui/gl/gl_state_restorer.h
index 5c14214..7edc998 100644
--- a/ui/gl/gl_state_restorer.h
+++ b/ui/gl/gl_state_restorer.h
@@ -20,6 +20,7 @@
   virtual bool IsInitialized() = 0;
   virtual void RestoreState(const GLStateRestorer* prev_state) = 0;
   virtual void RestoreAllTextureUnitBindings() = 0;
+  virtual void RestoreActiveTextureUnitBinding(unsigned int target) = 0;
   virtual void RestoreFramebufferBindings() = 0;
 
   DISALLOW_COPY_AND_ASSIGN(GLStateRestorer);
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index 5d35b33..4e74f49 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -177,18 +177,8 @@
   return false;
 }
 
-std::string GLSurface::GetExtensions() {
-  return std::string();
-}
-
-bool GLSurface::HasExtension(const char* name) {
-  std::string extensions = GetExtensions();
-  extensions += " ";
-
-  std::string delimited_name(name);
-  delimited_name += " ";
-
-  return extensions.find(delimited_name) != std::string::npos;
+bool GLSurface::SupportsPostSubBuffer() {
+  return false;
 }
 
 unsigned int GLSurface::GetBackingFrameBufferObject() {
@@ -294,8 +284,8 @@
   return surface_->PostSubBuffer(x, y, width, height);
 }
 
-std::string GLSurfaceAdapter::GetExtensions() {
-  return surface_->GetExtensions();
+bool GLSurfaceAdapter::SupportsPostSubBuffer() {
+  return surface_->SupportsPostSubBuffer();
 }
 
 gfx::Size GLSurfaceAdapter::GetSize() {
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
index f7a02f0..70336ba 100644
--- a/ui/gl/gl_surface.h
+++ b/ui/gl/gl_surface.h
@@ -57,11 +57,8 @@
   // Get the underlying platform specific surface "handle".
   virtual void* GetHandle() = 0;
 
-  // Returns space separated list of surface specific extensions.
-  // The surface must be current.
-  virtual std::string GetExtensions();
-
-  bool HasExtension(const char* name);
+  // Returns whether or not the surface supports PostSubBuffer.
+  virtual bool SupportsPostSubBuffer();
 
   // Returns the internal frame buffer object name if the surface is backed by
   // FBO. Otherwise returns 0.
@@ -147,7 +144,7 @@
   virtual bool IsOffscreen() OVERRIDE;
   virtual bool SwapBuffers() OVERRIDE;
   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
-  virtual std::string GetExtensions() OVERRIDE;
+  virtual bool SupportsPostSubBuffer() OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
   virtual void* GetHandle() OVERRIDE;
   virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
diff --git a/ui/gl/gl_surface_android.cc b/ui/gl/gl_surface_android.cc
new file mode 100644
index 0000000..9452232
--- /dev/null
+++ b/ui/gl/gl_surface_android.cc
@@ -0,0 +1,89 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface.h"
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "third_party/khronos/EGL/egl.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+
+namespace gfx {
+
+// static
+bool GLSurface::InitializeOneOffInternal() {
+  switch (GetGLImplementation()) {
+    case kGLImplementationEGLGLES2:
+      if (!GLSurfaceEGL::InitializeOneOff()) {
+        LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
+        return false;
+      }
+    default:
+      break;
+  }
+  return true;
+}
+
+// static
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+    gfx::AcceleratedWidget window) {
+
+  if (GetGLImplementation() == kGLImplementationOSMesaGL) {
+    scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
+    if (!surface->Initialize())
+      return NULL;
+    return surface;
+  }
+  DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
+  if (window != kNullAcceleratedWidget) {
+    scoped_refptr<GLSurface> surface = new NativeViewGLSurfaceEGL(window);
+    if (surface->Initialize())
+      return surface;
+  } else {
+    scoped_refptr<GLSurface> surface = new GLSurfaceStub();
+    if (surface->Initialize())
+      return surface;
+  }
+  return NULL;
+}
+
+// static
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+    const gfx::Size& size) {
+  switch (GetGLImplementation()) {
+    case kGLImplementationOSMesaGL: {
+      scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(1, size));
+      if (!surface->Initialize())
+        return NULL;
+
+      return surface;
+    }
+    case kGLImplementationEGLGLES2: {
+      scoped_refptr<GLSurface> surface;
+      if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
+          (size.width() == 0 && size.height() == 0)) {
+        surface = new SurfacelessEGL(size);
+      } else {
+        surface = new PbufferGLSurfaceEGL(size);
+      }
+
+      if (!surface->Initialize())
+        return NULL;
+      return surface;
+    }
+    default:
+      NOTREACHED();
+      return NULL;
+  }
+}
+
+EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
+  return EGL_DEFAULT_DISPLAY;
+}
+
+}  // namespace gfx
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index a2beccd..e8e301a 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -13,7 +13,6 @@
 #include "base/android/sys_utils.h"
 #endif
 
-#include "base/command_line.h"
 #include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
@@ -38,11 +37,6 @@
 #include "ui/gfx/ozone/surface_factory_ozone.h"
 #endif
 
-// From ANGLE's egl/eglext.h.
-#if !defined(EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE)
-#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE \
-    reinterpret_cast<EGLNativeDisplayType>(-2)
-#endif
 #if !defined(EGL_FIXED_SIZE_ANGLE)
 #define EGL_FIXED_SIZE_ANGLE 0x3201
 #endif
@@ -127,26 +121,7 @@
   if (initialized)
     return true;
 
-#if defined(USE_X11)
-  g_native_display = base::MessagePumpForUI::GetDefaultXDisplay();
-#elif defined(OS_WIN)
-  g_native_display = EGL_DEFAULT_DISPLAY;
-  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableD3D11) &&
-      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableD3D11)) {
-    g_native_display = EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE;
-  }
-#elif defined(USE_OZONE)
-  gfx::SurfaceFactoryOzone* surface_factory =
-      gfx::SurfaceFactoryOzone::GetInstance();
-  if (surface_factory->InitializeHardware() !=
-      gfx::SurfaceFactoryOzone::INITIALIZED) {
-    LOG(ERROR) << "OZONE failed to initialize hardware";
-    return false;
-  }
-  g_native_display = surface_factory->GetNativeDisplay();
-#else
-  g_native_display = EGL_DEFAULT_DISPLAY;
-#endif
+  g_native_display = GetPlatformDefaultEGLNativeDisplay();
   g_display = eglGetDisplay(g_native_display);
   if (!g_display) {
     LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
@@ -192,7 +167,8 @@
 
 #if defined(USE_OZONE)
   const EGLint* config_attribs =
-      surface_factory->GetEGLSurfaceProperties(choose_attributes);
+      SurfaceFactoryOzone::GetInstance()->GetEGLSurfaceProperties(
+          choose_attributes);
 #else
   const EGLint* config_attribs = choose_attributes;
 #endif
@@ -328,9 +304,13 @@
   return g_egl_create_context_robustness_supported;
 }
 
+bool GLSurfaceEGL::IsEGLSurfacelessContextSupported() {
+  return g_egl_surfaceless_context_supported;
+}
+
 GLSurfaceEGL::~GLSurfaceEGL() {}
 
-NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(gfx::AcceleratedWidget window)
+NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(EGLNativeWindowType window)
     : window_(window),
       surface_(NULL),
       supports_post_sub_buffer_(false),
@@ -350,11 +330,6 @@
     scoped_ptr<VSyncProvider> sync_provider) {
   DCHECK(!surface_);
 
-  if (window_ == kNullAcceleratedWidget) {
-    LOG(ERROR) << "Trying to create surface without window.";
-    return false;
-  }
-
   if (!GetDisplay()) {
     LOG(ERROR) << "Trying to create surface with invalid display.";
     return false;
@@ -559,13 +534,8 @@
   return surface_;
 }
 
-std::string NativeViewGLSurfaceEGL::GetExtensions() {
-  std::string extensions = GLSurface::GetExtensions();
-  if (supports_post_sub_buffer_) {
-    extensions += extensions.empty() ? "" : " ";
-    extensions += "GL_CHROMIUM_post_sub_buffer";
-  }
-  return extensions;
+bool NativeViewGLSurfaceEGL::SupportsPostSubBuffer() {
+  return supports_post_sub_buffer_;
 }
 
 bool NativeViewGLSurfaceEGL::PostSubBuffer(
@@ -766,111 +736,4 @@
 SurfacelessEGL::~SurfacelessEGL() {
 }
 
-#if defined(ANDROID) || defined(USE_OZONE)
-
-// A thin subclass of |GLSurfaceOSMesa| that can be used in place
-// of a native hardware-provided surface when a native surface
-// provider is not available.
-class GLSurfaceOSMesaHeadless : public GLSurfaceOSMesa {
- public:
-  explicit GLSurfaceOSMesaHeadless(gfx::AcceleratedWidget window);
-
-  virtual bool IsOffscreen() OVERRIDE;
-  virtual bool SwapBuffers() OVERRIDE;
-
- protected:
-  virtual ~GLSurfaceOSMesaHeadless();
-
- private:
-
-  DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesaHeadless);
-};
-
-bool GLSurfaceOSMesaHeadless::IsOffscreen() { return false; }
-
-bool GLSurfaceOSMesaHeadless::SwapBuffers() { return true; }
-
-GLSurfaceOSMesaHeadless::GLSurfaceOSMesaHeadless(gfx::AcceleratedWidget window)
-    : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)) {
-  DCHECK(window);
-}
-
-GLSurfaceOSMesaHeadless::~GLSurfaceOSMesaHeadless() { Destroy(); }
-
-// static
-bool GLSurface::InitializeOneOffInternal() {
-  switch (GetGLImplementation()) {
-    case kGLImplementationEGLGLES2:
-      if (!GLSurfaceEGL::InitializeOneOff()) {
-        LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
-        return false;
-      }
-    default:
-      break;
-  }
-  return true;
-}
-
-// static
-scoped_refptr<GLSurface>
-GLSurface::CreateViewGLSurface(gfx::AcceleratedWidget window) {
-
-  if (GetGLImplementation() == kGLImplementationOSMesaGL) {
-    scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless(window));
-    if (!surface->Initialize())
-      return NULL;
-    return surface;
-  }
-  DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
-  if (window) {
-    scoped_refptr<NativeViewGLSurfaceEGL> surface;
-    scoped_ptr<VSyncProvider> sync_provider;
-#if defined(USE_OZONE)
-    window = gfx::SurfaceFactoryOzone::GetInstance()->RealizeAcceleratedWidget(
-        window);
-    sync_provider =
-        gfx::SurfaceFactoryOzone::GetInstance()->CreateVSyncProvider(window);
-#endif
-    surface = new NativeViewGLSurfaceEGL(window);
-    if(surface->Initialize(sync_provider.Pass()))
-      return surface;
-  } else {
-    scoped_refptr<GLSurface> surface = new GLSurfaceStub();
-    if (surface->Initialize())
-      return surface;
-  }
-  return NULL;
-}
-
-// static
-scoped_refptr<GLSurface>
-GLSurface::CreateOffscreenGLSurface(const gfx::Size& size) {
-  switch (GetGLImplementation()) {
-    case kGLImplementationOSMesaGL: {
-      scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(1, size));
-      if (!surface->Initialize())
-        return NULL;
-
-      return surface;
-    }
-    case kGLImplementationEGLGLES2: {
-      scoped_refptr<GLSurface> surface;
-      if (g_egl_surfaceless_context_supported &&
-         (size.width() == 0 && size.height() == 0)) {
-        surface = new SurfacelessEGL(size);
-      } else
-        surface = new PbufferGLSurfaceEGL(size);
-
-      if (!surface->Initialize())
-        return NULL;
-      return surface;
-    }
-    default:
-      NOTREACHED();
-      return NULL;
-  }
-}
-
-#endif
-
 }  // namespace gfx
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
index 73ec213..4c28928 100644
--- a/ui/gl/gl_surface_egl.h
+++ b/ui/gl/gl_surface_egl.h
@@ -13,7 +13,6 @@
 
 #include "base/compiler_specific.h"
 #include "base/time/time.h"
-#include "ui/gfx/native_widget_types.h"
 #include "ui/gfx/size.h"
 #include "ui/gfx/vsync_provider.h"
 #include "ui/gl/gl_bindings.h"
@@ -21,6 +20,9 @@
 
 namespace gfx {
 
+// Get default EGL display for GLSurfaceEGL (differs by platform).
+EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay();
+
 // Interface for EGL surface.
 class GL_EXPORT GLSurfaceEGL : public GLSurface {
  public:
@@ -39,6 +41,7 @@
   static const char* GetEGLExtensions();
   static bool HasEGLExtension(const char* name);
   static bool IsCreateContextRobustnessSupported();
+  static bool IsEGLSurfacelessContextSupported();
 
  protected:
   virtual ~GLSurfaceEGL();
@@ -50,7 +53,7 @@
 // Encapsulates an EGL surface bound to a view.
 class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
  public:
-  explicit NativeViewGLSurfaceEGL(gfx::AcceleratedWidget window);
+  explicit NativeViewGLSurfaceEGL(EGLNativeWindowType window);
 
   // Implement GLSurface.
   virtual EGLConfig GetConfig() OVERRIDE;
@@ -62,7 +65,7 @@
   virtual bool SwapBuffers() OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
   virtual EGLSurface GetHandle() OVERRIDE;
-  virtual std::string GetExtensions() OVERRIDE;
+  virtual bool SupportsPostSubBuffer() OVERRIDE;
   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
   virtual VSyncProvider* GetVSyncProvider() OVERRIDE;
 
@@ -75,7 +78,7 @@
   void SetHandle(EGLSurface surface);
 
  private:
-  gfx::AcceleratedWidget window_;
+  EGLNativeWindowType window_;
   EGLSurface surface_;
   bool supports_post_sub_buffer_;
   EGLConfig config_;
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc
index b08a5d0..17a481a 100644
--- a/ui/gl/gl_surface_glx.cc
+++ b/ui/gl/gl_surface_glx.cc
@@ -615,13 +615,8 @@
   return reinterpret_cast<void*>(GetDrawableHandle());
 }
 
-std::string NativeViewGLSurfaceGLX::GetExtensions() {
-  std::string extensions = GLSurface::GetExtensions();
-  if (gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer) {
-    extensions += extensions.empty() ? "" : " ";
-    extensions += "GL_CHROMIUM_post_sub_buffer";
-  }
-  return extensions;
+bool NativeViewGLSurfaceGLX::SupportsPostSubBuffer() {
+  return gfx::g_driver_glx.ext.b_GLX_MESA_copy_sub_buffer;
 }
 
 void* NativeViewGLSurfaceGLX::GetConfig() {
diff --git a/ui/gl/gl_surface_glx.h b/ui/gl/gl_surface_glx.h
index c41f4ef..f9bff2b 100644
--- a/ui/gl/gl_surface_glx.h
+++ b/ui/gl/gl_surface_glx.h
@@ -60,7 +60,7 @@
   virtual bool SwapBuffers() OVERRIDE;
   virtual gfx::Size GetSize() OVERRIDE;
   virtual void* GetHandle() OVERRIDE;
-  virtual std::string GetExtensions() OVERRIDE;
+  virtual bool SupportsPostSubBuffer() OVERRIDE;
   virtual void* GetConfig() OVERRIDE;
   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
   virtual VSyncProvider* GetVSyncProvider() OVERRIDE;
diff --git a/ui/gl/gl_surface_osmesa.cc b/ui/gl/gl_surface_osmesa.cc
index 9a556bc..8018fe8 100644
--- a/ui/gl/gl_surface_osmesa.cc
+++ b/ui/gl/gl_surface_osmesa.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/logging.h"
+#include "third_party/mesa/src/include/GL/osmesa.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_surface_osmesa.h"
@@ -82,4 +83,13 @@
   Destroy();
 }
 
+bool GLSurfaceOSMesaHeadless::IsOffscreen() { return false; }
+
+bool GLSurfaceOSMesaHeadless::SwapBuffers() { return true; }
+
+GLSurfaceOSMesaHeadless::GLSurfaceOSMesaHeadless()
+    : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)) {}
+
+GLSurfaceOSMesaHeadless::~GLSurfaceOSMesaHeadless() { Destroy(); }
+
 }  // namespace gfx
diff --git a/ui/gl/gl_surface_osmesa.h b/ui/gl/gl_surface_osmesa.h
index a823231..b4b4827 100644
--- a/ui/gl/gl_surface_osmesa.h
+++ b/ui/gl/gl_surface_osmesa.h
@@ -39,6 +39,23 @@
   DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesa);
 };
 
+// A thin subclass of |GLSurfaceOSMesa| that can be used in place
+// of a native hardware-provided surface when a native surface
+// provider is not available.
+class GLSurfaceOSMesaHeadless : public GLSurfaceOSMesa {
+ public:
+  explicit GLSurfaceOSMesaHeadless();
+
+  virtual bool IsOffscreen() OVERRIDE;
+  virtual bool SwapBuffers() OVERRIDE;
+
+ protected:
+  virtual ~GLSurfaceOSMesaHeadless();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesaHeadless);
+};
+
 }  // namespace gfx
 
 #endif  // UI_GL_GL_SURFACE_OSMESA_H_
diff --git a/ui/gl/gl_surface_ozone.cc b/ui/gl/gl_surface_ozone.cc
new file mode 100644
index 0000000..5cf70c7
--- /dev/null
+++ b/ui/gl/gl_surface_ozone.cc
@@ -0,0 +1,104 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface.h"
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/ozone/surface_factory_ozone.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+
+namespace gfx {
+
+// static
+bool GLSurface::InitializeOneOffInternal() {
+  switch (GetGLImplementation()) {
+    case kGLImplementationEGLGLES2:
+      if (gfx::SurfaceFactoryOzone::GetInstance()->InitializeHardware() !=
+          gfx::SurfaceFactoryOzone::INITIALIZED) {
+        LOG(ERROR) << "Ozone failed to initialize hardware";
+        return false;
+      }
+
+      if (!GLSurfaceEGL::InitializeOneOff()) {
+        LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
+        return false;
+      }
+
+      return true;
+    case kGLImplementationOSMesaGL:
+    case kGLImplementationMockGL:
+      return true;
+    default:
+      return false;
+  }
+}
+
+// static
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+    gfx::AcceleratedWidget window) {
+  if (GetGLImplementation() == kGLImplementationOSMesaGL) {
+    scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
+    if (!surface->Initialize())
+      return NULL;
+    return surface;
+  }
+  DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
+  if (window != kNullAcceleratedWidget) {
+    EGLNativeWindowType egl_window =
+        gfx::SurfaceFactoryOzone::GetInstance()->RealizeAcceleratedWidget(
+            window);
+    scoped_ptr<VSyncProvider> sync_provider =
+        gfx::SurfaceFactoryOzone::GetInstance()->CreateVSyncProvider(
+            egl_window);
+    scoped_refptr<NativeViewGLSurfaceEGL> surface =
+        new NativeViewGLSurfaceEGL(egl_window);
+    if (surface->Initialize(sync_provider.Pass()))
+      return surface;
+  } else {
+    scoped_refptr<GLSurface> surface = new GLSurfaceStub();
+    if (surface->Initialize())
+      return surface;
+  }
+  return NULL;
+}
+
+// static
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+    const gfx::Size& size) {
+  switch (GetGLImplementation()) {
+    case kGLImplementationOSMesaGL: {
+      scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(1, size));
+      if (!surface->Initialize())
+        return NULL;
+
+      return surface;
+    }
+    case kGLImplementationEGLGLES2: {
+      scoped_refptr<GLSurface> surface;
+      if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
+          (size.width() == 0 && size.height() == 0)) {
+        surface = new SurfacelessEGL(size);
+      } else
+        surface = new PbufferGLSurfaceEGL(size);
+
+      if (!surface->Initialize())
+        return NULL;
+      return surface;
+    }
+    default:
+      NOTREACHED();
+      return NULL;
+  }
+}
+
+EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
+  return SurfaceFactoryOzone::GetInstance()->GetNativeDisplay();
+}
+
+}  // namespace gfx
diff --git a/ui/gl/gl_surface_win.cc b/ui/gl/gl_surface_win.cc
index 6307f14..eb99421 100644
--- a/ui/gl/gl_surface_win.cc
+++ b/ui/gl/gl_surface_win.cc
@@ -6,12 +6,14 @@
 
 #include <dwmapi.h>
 
+#include "base/command_line.h"
 #include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/win/windows_version.h"
 #include "third_party/mesa/src/include/GL/osmesa.h"
 #include "ui/gfx/frame_time.h"
+#include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface_egl.h"
@@ -19,6 +21,12 @@
 #include "ui/gl/gl_surface_stub.h"
 #include "ui/gl/gl_surface_wgl.h"
 
+// From ANGLE's egl/eglext.h.
+#if !defined(EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE)
+#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE \
+  reinterpret_cast<EGLNativeDisplayType>(-2)
+#endif
+
 namespace gfx {
 
 // This OSMesa GL surface can use GDI to swap the contents of the buffer to a
@@ -33,7 +41,7 @@
   virtual void Destroy() OVERRIDE;
   virtual bool IsOffscreen() OVERRIDE;
   virtual bool SwapBuffers() OVERRIDE;
-  virtual std::string GetExtensions() OVERRIDE;
+  virtual bool SupportsPostSubBuffer() OVERRIDE;
   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
 
  private:
@@ -171,11 +179,8 @@
   return true;
 }
 
-std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
-  std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
-  extensions += extensions.empty() ? "" : " ";
-  extensions += "GL_CHROMIUM_post_sub_buffer";
-  return extensions;
+bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() {
+  return true;
 }
 
 bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
@@ -228,6 +233,7 @@
       return surface;
     }
     case kGLImplementationEGLGLES2: {
+      DCHECK(window != gfx::kNullAcceleratedWidget);
       scoped_refptr<NativeViewGLSurfaceEGL> surface(
           new NativeViewGLSurfaceEGL(window));
       scoped_ptr<VSyncProvider> sync_provider;
@@ -288,4 +294,12 @@
   }
 }
 
+EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
+  if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableD3D11) &&
+      CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableD3D11))
+    return EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE;
+
+  return EGL_DEFAULT_DISPLAY;
+}
+
 }  // namespace gfx
diff --git a/ui/gl/gl_surface_x11.cc b/ui/gl/gl_surface_x11.cc
index 54c7f43..066f915 100644
--- a/ui/gl/gl_surface_x11.cc
+++ b/ui/gl/gl_surface_x11.cc
@@ -9,6 +9,7 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/message_loop/message_loop.h"
 #include "third_party/mesa/src/include/GL/osmesa.h"
+#include "ui/gfx/native_widget_types.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_implementation.h"
 #include "ui/gl/gl_surface_egl.h"
@@ -32,7 +33,7 @@
   virtual bool Resize(const gfx::Size& new_size) OVERRIDE;
   virtual bool IsOffscreen() OVERRIDE;
   virtual bool SwapBuffers() OVERRIDE;
-  virtual std::string GetExtensions() OVERRIDE;
+  virtual bool SupportsPostSubBuffer() OVERRIDE;
   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
 
  protected:
@@ -218,11 +219,8 @@
   return true;
 }
 
-std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
-  std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
-  extensions += extensions.empty() ? "" : " ";
-  extensions += "GL_CHROMIUM_post_sub_buffer";
-  return extensions;
+bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() {
+  return true;
 }
 
 bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
@@ -293,6 +291,7 @@
       return surface;
     }
     case kGLImplementationEGLGLES2: {
+      DCHECK(window != gfx::kNullAcceleratedWidget);
       scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(window));
       if (!surface->Initialize())
         return NULL;
@@ -341,4 +340,8 @@
   }
 }
 
+EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
+  return base::MessagePumpForUI::GetDefaultXDisplay();
+}
+
 }  // namespace gfx
diff --git a/ui/gl/scoped_binders.cc b/ui/gl/scoped_binders.cc
index eef92c1..bb2b290 100644
--- a/ui/gl/scoped_binders.cc
+++ b/ui/gl/scoped_binders.cc
@@ -59,7 +59,7 @@
   if (state_restorer_) {
     DCHECK(!!GLContext::GetCurrent());
     DCHECK_EQ(state_restorer_, GLContext::GetCurrent()->GetGLStateRestorer());
-    state_restorer_->RestoreAllTextureUnitBindings();
+    state_restorer_->RestoreActiveTextureUnitBinding(target_);
   } else {
     glBindTexture(target_, old_id_);
   }
diff --git a/ui/gl/surface_jni_headers.target.darwin-arm.mk b/ui/gl/surface_jni_headers.target.darwin-arm.mk
index 2870dd7..6b5fe3c 100644
--- a/ui/gl/surface_jni_headers.target.darwin-arm.mk
+++ b/ui/gl/surface_jni_headers.target.darwin-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/surface_jni_headers.target.darwin-mips.mk b/ui/gl/surface_jni_headers.target.darwin-mips.mk
index c94763b..58eed77 100644
--- a/ui/gl/surface_jni_headers.target.darwin-mips.mk
+++ b/ui/gl/surface_jni_headers.target.darwin-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/surface_jni_headers.target.darwin-x86.mk b/ui/gl/surface_jni_headers.target.darwin-x86.mk
index 03a9f1a..e567084 100644
--- a/ui/gl/surface_jni_headers.target.darwin-x86.mk
+++ b/ui/gl/surface_jni_headers.target.darwin-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/surface_jni_headers.target.darwin-x86_64.mk b/ui/gl/surface_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..6193d5e
--- /dev/null
+++ b/ui/gl/surface_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_gl_surface_jni_headers_gyp
+LOCAL_MODULE_STEM := surface_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/view/Surface.class ($@)"
+	$(hide)cd $(gyp_local_path)/ui/gl; mkdir -p $(gyp_shared_intermediate_dir)/ui/gl/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/view/Surface.class --output_dir "$(gyp_shared_intermediate_dir)/ui/gl/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gl_surface_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: surface_jni_headers
+surface_jni_headers: ui_gl_surface_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/gl/surface_jni_headers.target.linux-arm.mk b/ui/gl/surface_jni_headers.target.linux-arm.mk
index 2870dd7..6b5fe3c 100644
--- a/ui/gl/surface_jni_headers.target.linux-arm.mk
+++ b/ui/gl/surface_jni_headers.target.linux-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/surface_jni_headers.target.linux-mips.mk b/ui/gl/surface_jni_headers.target.linux-mips.mk
index c94763b..58eed77 100644
--- a/ui/gl/surface_jni_headers.target.linux-mips.mk
+++ b/ui/gl/surface_jni_headers.target.linux-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/surface_jni_headers.target.linux-x86.mk b/ui/gl/surface_jni_headers.target.linux-x86.mk
index 03a9f1a..e567084 100644
--- a/ui/gl/surface_jni_headers.target.linux-x86.mk
+++ b/ui/gl/surface_jni_headers.target.linux-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/gl/surface_jni_headers.target.linux-x86_64.mk b/ui/gl/surface_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..6193d5e
--- /dev/null
+++ b/ui/gl/surface_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_gl_surface_jni_headers_gyp
+LOCAL_MODULE_STEM := surface_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/view/Surface.class ($@)"
+	$(hide)cd $(gyp_local_path)/ui/gl; mkdir -p $(gyp_shared_intermediate_dir)/ui/gl/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/view/Surface.class --output_dir "$(gyp_shared_intermediate_dir)/ui/gl/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/ui/gl/jni/Surface_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_gl_surface_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: surface_jni_headers
+surface_jni_headers: ui_gl_surface_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/keyboard/keyboard.cc b/ui/keyboard/keyboard.cc
index d790127..436b935 100644
--- a/ui/keyboard/keyboard.cc
+++ b/ui/keyboard/keyboard.cc
@@ -5,71 +5,14 @@
 #include "ui/keyboard/keyboard.h"
 
 #include "base/files/file_path.h"
-#include "base/memory/singleton.h"
 #include "base/path_service.h"
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/web_ui_controller_factory.h"
 #include "ui/base/resource/resource_bundle.h"
-#include "ui/keyboard/keyboard_constants.h"
-#include "ui/keyboard/keyboard_ui_controller.h"
-#include "url/gurl.h"
-
-namespace {
-
-using content::BrowserContext;
-using content::WebUI;
-using content::WebUIController;
-
-class KeyboardWebUIControllerFactory : public content::WebUIControllerFactory {
- public:
-  // |WebUIControllerFactory| implementation:
-  virtual content::WebUI::TypeID GetWebUIType(
-      content::BrowserContext* browser_context,
-      const GURL& url) const OVERRIDE {
-    if (url == GURL(keyboard::kKeyboardWebUIURL))
-      return const_cast<KeyboardWebUIControllerFactory*>(this);
-
-    return WebUI::kNoWebUI;
-  }
-  virtual bool UseWebUIForURL(content::BrowserContext* browser_context,
-                              const GURL& url) const OVERRIDE {
-    return GetWebUIType(browser_context, url) != WebUI::kNoWebUI;
-  }
-  virtual bool UseWebUIBindingsForURL(content::BrowserContext* browser_context,
-                                      const GURL& url) const OVERRIDE {
-    return UseWebUIForURL(browser_context, url);
-  }
-  virtual content::WebUIController* CreateWebUIControllerForURL(
-      content::WebUI* web_ui,
-      const GURL& url) const OVERRIDE {
-    if (url == GURL(keyboard::kKeyboardWebUIURL))
-      return new keyboard::KeyboardUIController(web_ui);
-    return NULL;
-  }
-
-  static KeyboardWebUIControllerFactory* GetInstance() {
-    return Singleton<KeyboardWebUIControllerFactory>::get();
-  }
-
- protected:
-  KeyboardWebUIControllerFactory() {}
-  virtual ~KeyboardWebUIControllerFactory() {}
-
- private:
-  friend struct DefaultSingletonTraits<KeyboardWebUIControllerFactory>;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyboardWebUIControllerFactory);
-};
-
-}  // namespace
 
 namespace keyboard {
 
 static bool initialized = false;
 
 void ResetKeyboardForTesting() {
-  content::WebUIControllerFactory::UnregisterFactoryForTesting(
-      KeyboardWebUIControllerFactory::GetInstance());
   initialized = false;
 }
 
@@ -84,9 +27,6 @@
       FILE_PATH_LITERAL("keyboard_resources.pak"));
   ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
       pak_file, ui::SCALE_FACTOR_100P);
-
-  content::WebUIControllerFactory::RegisterFactory(
-      KeyboardWebUIControllerFactory::GetInstance());
 }
 
 }  // namespace keyboard
diff --git a/ui/keyboard/keyboard.gyp b/ui/keyboard/keyboard.gyp
index fd093fc..fe359c6 100644
--- a/ui/keyboard/keyboard.gyp
+++ b/ui/keyboard/keyboard.gyp
@@ -64,13 +64,11 @@
         'keyboard_controller_observer.h',
         'keyboard_controller_proxy.cc',
         'keyboard_controller_proxy.h',
+        'keyboard_layout_manager.h',
+        'keyboard_layout_manager.cc',
         'keyboard_export.h',
         'keyboard_switches.cc',
         'keyboard_switches.h',
-        'keyboard_ui_controller.cc',
-        'keyboard_ui_controller.h',
-        'keyboard_ui_handler.cc',
-        'keyboard_ui_handler.h',
         'keyboard_util.cc',
         'keyboard_util.h',
       ]
diff --git a/ui/keyboard/keyboard.h b/ui/keyboard/keyboard.h
index c47cf8c..a0aed8a 100644
--- a/ui/keyboard/keyboard.h
+++ b/ui/keyboard/keyboard.h
@@ -10,9 +10,8 @@
 namespace keyboard {
 
 // Initializes the keyboard module. This includes adding the necessary pak files
-// for loading resources used in for the virtual keyboard, and registers
-// a WebUIControllerFactory for creating a WebUIController necessary for the
-// virtual keyboard. This becomes a no-op after the first call.
+// for loading resources used in for the virtual keyboard. This becomes a no-op
+// after the first call.
 KEYBOARD_EXPORT void InitializeKeyboard();
 
 // Resets the keyboard to an uninitialized state. Required for
diff --git a/ui/keyboard/keyboard_constants.cc b/ui/keyboard/keyboard_constants.cc
index 35f8130..b13a604 100644
--- a/ui/keyboard/keyboard_constants.cc
+++ b/ui/keyboard/keyboard_constants.cc
@@ -6,7 +6,7 @@
 
 namespace keyboard {
 
-const char kKeyboardWebUIURL[] = "chrome://keyboard";
-const char kKeyboardWebUIHost[] = "keyboard";
+const char kKeyboardURL[] = "chrome://keyboard";
+const char kKeyboardHost[] = "keyboard";
 
 }  // namespace keyboard
diff --git a/ui/keyboard/keyboard_constants.h b/ui/keyboard/keyboard_constants.h
index eff96ea..75607c1 100644
--- a/ui/keyboard/keyboard_constants.h
+++ b/ui/keyboard/keyboard_constants.h
@@ -9,11 +9,11 @@
 
 namespace keyboard {
 
-// The URL of the keyboard WebUI.
-KEYBOARD_EXPORT extern const char kKeyboardWebUIURL[];
+// The URL of the keyboard extension.
+KEYBOARD_EXPORT extern const char kKeyboardURL[];
 
-// The host of the keyboard WebUI URL.
-KEYBOARD_EXPORT extern const char kKeyboardWebUIHost[];
+// The host of the keyboard extension URL.
+KEYBOARD_EXPORT extern const char kKeyboardHost[];
 
 }  // namespace keyboard
 
diff --git a/ui/keyboard/keyboard_controller.cc b/ui/keyboard/keyboard_controller.cc
index ba99514..1de832c 100644
--- a/ui/keyboard/keyboard_controller.cc
+++ b/ui/keyboard/keyboard_controller.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/command_line.h"
-#include "ui/aura/layout_manager.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/base/cursor/cursor.h"
@@ -20,6 +19,7 @@
 #include "ui/gfx/skia_util.h"
 #include "ui/keyboard/keyboard_controller_observer.h"
 #include "ui/keyboard/keyboard_controller_proxy.h"
+#include "ui/keyboard/keyboard_layout_manager.h"
 #include "ui/keyboard/keyboard_switches.h"
 #include "ui/keyboard/keyboard_util.h"
 #include "ui/wm/core/masked_window_targeter.h"
@@ -40,34 +40,6 @@
 // hide animation finishes.
 const float kAnimationStartOrAfterHideOpacity = 0.2f;
 
-// The ratio between the height of the keyboard and the screen when using the
-// usability keyboard.
-const float kUsabilityKeyboardHeightRatio = 1.0f;
-
-// The default ratio between the height of the keyboard and the screen.
-const float kDefaultKeyboardHeightRatio = 0.3f;
-
-// The ratio between the height of the keyboard and the screen when using the
-// accessibility keyboard.
-const float kAccessibilityKeyboardHeightRatio = 0.3f;
-
-float GetKeyboardHeightRatio(){
-  if (keyboard::IsKeyboardUsabilityExperimentEnabled()) {
-    return kUsabilityKeyboardHeightRatio;
-  } else if (keyboard::GetAccessibilityKeyboardEnabled()) {
-    return kAccessibilityKeyboardHeightRatio;
-  }
-  return kDefaultKeyboardHeightRatio;
-}
-gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds) {
-  const float kKeyboardHeightRatio = GetKeyboardHeightRatio();
-  return gfx::Rect(
-      window_bounds.x(),
-      window_bounds.y() + window_bounds.height() * (1 - kKeyboardHeightRatio),
-      window_bounds.width(),
-      window_bounds.height() * kKeyboardHeightRatio);
-}
-
 // Event targeter for the keyboard container.
 class KeyboardContainerTargeter : public wm::MaskedWindowTargeter {
  public:
@@ -84,7 +56,7 @@
   virtual bool GetHitTestMask(aura::Window* window,
                               gfx::Path* mask) const OVERRIDE {
     gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() :
-        KeyboardBoundsFromWindowBounds(window->bounds());
+        keyboard::DefaultKeyboardBoundsFromWindowBounds(window->bounds());
     mask->addRect(RectToSkRect(keyboard_bounds));
     return true;
   }
@@ -133,11 +105,9 @@
   virtual bool HasHitTestMask() const OVERRIDE { return true; }
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE {
     gfx::Rect keyboard_bounds = proxy_ ? proxy_->GetKeyboardWindow()->bounds() :
-        KeyboardBoundsFromWindowBounds(bounds_);
+        keyboard::DefaultKeyboardBoundsFromWindowBounds(bounds_);
     mask->addRect(RectToSkRect(keyboard_bounds));
   }
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE {}
 
   gfx::Rect bounds_;
   keyboard::KeyboardControllerProxy* proxy_;
@@ -208,54 +178,6 @@
   animator_->RemoveObserver(this);
 }
 
-// LayoutManager for the virtual keyboard container.  Manages a single window
-// (the virtual keyboard) and keeps it positioned at the bottom of the
-// owner window.
-class KeyboardLayoutManager : public aura::LayoutManager {
- public:
-  explicit KeyboardLayoutManager(KeyboardController* controller)
-      : controller_(controller), keyboard_(NULL) {
-  }
-
-  // Overridden from aura::LayoutManager
-  virtual void OnWindowResized() OVERRIDE {
-    if (keyboard_ && !controller_->proxy()->resizing_from_contents())
-      ResizeKeyboardToDefault(keyboard_);
-  }
-  virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE {
-    DCHECK(!keyboard_);
-    keyboard_ = child;
-    ResizeKeyboardToDefault(keyboard_);
-  }
-  virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
-  virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
-  virtual void OnChildWindowVisibilityChanged(aura::Window* child,
-                                              bool visible) OVERRIDE {}
-  virtual void SetChildBounds(aura::Window* child,
-                              const gfx::Rect& requested_bounds) OVERRIDE {
-    // SetChildBounds can be invoked by resizing from the container or by
-    // resizing from the contents (through window.resizeTo call in JS).
-    // The flag resizing_from_contents() is used to determine the keyboard is
-    // resizing from which.
-    if (controller_->proxy()->resizing_from_contents()) {
-      controller_->NotifyKeyboardBoundsChanging(requested_bounds);
-      SetChildBoundsDirect(child, requested_bounds);
-    }
-  }
-
- private:
-  void ResizeKeyboardToDefault(aura::Window* child) {
-    gfx::Rect keyboard_bounds = KeyboardBoundsFromWindowBounds(
-        controller_->GetContainerWindow()->bounds());
-    SetChildBoundsDirect(child, keyboard_bounds);
-  }
-
-  KeyboardController* controller_;
-  aura::Window* keyboard_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager);
-};
-
 KeyboardController::KeyboardController(KeyboardControllerProxy* proxy)
     : proxy_(proxy),
       input_method_(NULL),
diff --git a/ui/keyboard/keyboard_controller.h b/ui/keyboard/keyboard_controller.h
index 7dc25c1..86cd12d 100644
--- a/ui/keyboard/keyboard_controller.h
+++ b/ui/keyboard/keyboard_controller.h
@@ -31,7 +31,6 @@
 class CallbackAnimationObserver;
 class KeyboardControllerObserver;
 class KeyboardControllerProxy;
-class KeyboardLayoutManager;
 
 // Provides control of the virtual keyboard, including providing a container
 // and controlling visibility.
diff --git a/ui/keyboard/keyboard_controller_proxy.cc b/ui/keyboard/keyboard_controller_proxy.cc
index c550a3f..acd78f8 100644
--- a/ui/keyboard/keyboard_controller_proxy.cc
+++ b/ui/keyboard/keyboard_controller_proxy.cc
@@ -4,6 +4,7 @@
 
 #include "ui/keyboard/keyboard_controller_proxy.h"
 
+#include "base/command_line.h"
 #include "base/values.h"
 #include "content/public/browser/site_instance.h"
 #include "content/public/browser/web_contents.h"
@@ -16,43 +17,11 @@
 #include "ui/aura/layout_manager.h"
 #include "ui/aura/window.h"
 #include "ui/keyboard/keyboard_constants.h"
+#include "ui/keyboard/keyboard_switches.h"
 #include "ui/keyboard/keyboard_util.h"
 
 namespace {
 
-// Converts ui::TextInputType to string.
-std::string TextInputTypeToString(ui::TextInputType type) {
-  switch (type) {
-    case ui::TEXT_INPUT_TYPE_NONE:
-      return "none";
-    case ui::TEXT_INPUT_TYPE_PASSWORD:
-      return "password";
-    case ui::TEXT_INPUT_TYPE_EMAIL:
-      return "email";
-    case ui::TEXT_INPUT_TYPE_NUMBER:
-      return "number";
-    case ui::TEXT_INPUT_TYPE_TELEPHONE:
-      return "tel";
-    case ui::TEXT_INPUT_TYPE_URL:
-      return "url";
-    case ui::TEXT_INPUT_TYPE_DATE:
-      return "date";
-    case ui::TEXT_INPUT_TYPE_TEXT:
-    case ui::TEXT_INPUT_TYPE_SEARCH:
-    case ui::TEXT_INPUT_TYPE_DATE_TIME:
-    case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL:
-    case ui::TEXT_INPUT_TYPE_MONTH:
-    case ui::TEXT_INPUT_TYPE_TIME:
-    case ui::TEXT_INPUT_TYPE_WEEK:
-    case ui::TEXT_INPUT_TYPE_TEXT_AREA:
-    case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE:
-    case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD:
-      return "text";
-  }
-  NOTREACHED();
-  return "";
-}
-
 // The WebContentsDelegate for the keyboard.
 // The delegate deletes itself when the keyboard is destroyed.
 class KeyboardContentsDelegate : public content::WebContentsDelegate,
@@ -112,15 +81,19 @@
 namespace keyboard {
 
 KeyboardControllerProxy::KeyboardControllerProxy()
-    : default_url_(kKeyboardWebUIURL), resizing_from_contents_(false) {
+    : default_url_(kKeyboardURL), resizing_from_contents_(false) {
 }
 
 KeyboardControllerProxy::~KeyboardControllerProxy() {
 }
 
 const GURL& KeyboardControllerProxy::GetVirtualKeyboardUrl() {
-  const GURL& override_url = GetOverrideContentUrl();
-  return override_url.is_valid() ? override_url : default_url_;
+  if (keyboard::IsInputViewEnabled()) {
+    const GURL& override_url = GetOverrideContentUrl();
+    return override_url.is_valid() ? override_url : default_url_;
+  } else {
+    return default_url_;
+  }
 }
 
 void KeyboardControllerProxy::LoadContents(const GURL& url) {
@@ -165,17 +138,6 @@
 }
 
 void KeyboardControllerProxy::SetUpdateInputType(ui::TextInputType type) {
-  content::WebUI* webui = keyboard_contents_ ?
-      keyboard_contents_->GetCommittedWebUI() : NULL;
-
-  if (webui &&
-      (0 != (webui->GetBindings() & content::BINDINGS_POLICY_WEB_UI))) {
-    // Only call OnTextInputBoxFocused function if it is a web ui keyboard,
-    // not an extension based keyboard.
-    base::DictionaryValue input_context;
-    input_context.SetString("type", TextInputTypeToString(type));
-    webui->CallJavascriptFunction("OnTextInputBoxFocused", input_context);
-  }
 }
 
 void KeyboardControllerProxy::EnsureCaretInWorkArea() {
diff --git a/ui/keyboard/keyboard_controller_proxy.h b/ui/keyboard/keyboard_controller_proxy.h
index 35af78c..8f48c0c 100644
--- a/ui/keyboard/keyboard_controller_proxy.h
+++ b/ui/keyboard/keyboard_controller_proxy.h
@@ -70,9 +70,7 @@
   // necesasry animation, or delay the visibility change as it desires.
   virtual void HideKeyboardContainer(aura::Window* container);
 
-  // Updates the type of the focused text input box. The default implementation
-  // calls OnTextInputBoxFocused javascript function through webui to update the
-  // type the of focused input box.
+  // Updates the type of the focused text input box.
   virtual void SetUpdateInputType(ui::TextInputType type);
 
   // Ensures caret in current work area (not occluded by virtual keyboard
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index 79a0c27..d735883 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -14,6 +14,7 @@
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/ime/dummy_text_input_client.h"
 #include "ui/base/ime/input_method.h"
 #include "ui/base/ime/input_method_factory.h"
 #include "ui/base/ime/text_input_client.h"
@@ -131,67 +132,6 @@
   DISALLOW_COPY_AND_ASSIGN(EventObserver);
 };
 
-class TestTextInputClient : public ui::TextInputClient {
- public:
-  explicit TestTextInputClient(ui::TextInputType type)
-      : type_(type) {}
-  virtual ~TestTextInputClient() {}
-
- private:
-  // Overridden from ui::TextInputClient:
-  virtual void SetCompositionText(
-      const ui::CompositionText& composition) OVERRIDE {}
-  virtual void ConfirmCompositionText() OVERRIDE {}
-  virtual void ClearCompositionText() OVERRIDE {}
-  virtual void InsertText(const base::string16& text) OVERRIDE {}
-  virtual void InsertChar(base::char16 ch, int flags) OVERRIDE {}
-  virtual gfx::NativeWindow GetAttachedWindow() const OVERRIDE {
-    return static_cast<gfx::NativeWindow>(NULL);
-  }
-  virtual ui::TextInputType GetTextInputType() const OVERRIDE {
-    return type_;
-  }
-  virtual ui::TextInputMode GetTextInputMode() const OVERRIDE {
-    return ui::TEXT_INPUT_MODE_DEFAULT;
-  }
-  virtual bool CanComposeInline() const OVERRIDE { return false; }
-  virtual gfx::Rect GetCaretBounds() const OVERRIDE { return gfx::Rect(); }
-
-  virtual bool GetCompositionCharacterBounds(
-      uint32 index,
-      gfx::Rect* rect) const OVERRIDE {
-    return false;
-  }
-  virtual bool HasCompositionText() const OVERRIDE { return false; }
-  virtual bool GetTextRange(gfx::Range* range) const OVERRIDE { return false; }
-  virtual bool GetCompositionTextRange(gfx::Range* range) const OVERRIDE {
-    return false;
-  }
-  virtual bool GetSelectionRange(gfx::Range* range) const OVERRIDE {
-    return false;
-  }
-  virtual bool SetSelectionRange(const gfx::Range& range) OVERRIDE {
-    return false;
-  }
-  virtual bool DeleteRange(const gfx::Range& range) OVERRIDE { return false; }
-  virtual bool GetTextFromRange(const gfx::Range& range,
-                                base::string16* text) const OVERRIDE {
-    return false;
-  }
-  virtual void OnInputMethodChanged() OVERRIDE {}
-  virtual bool ChangeTextDirectionAndLayoutAlignment(
-      base::i18n::TextDirection direction) OVERRIDE { return false; }
-  virtual void ExtendSelectionAndDelete(size_t before, size_t after) OVERRIDE {}
-  virtual void EnsureCaretInRect(const gfx::Rect& rect) OVERRIDE {}
-  virtual void OnCandidateWindowShown() OVERRIDE {}
-  virtual void OnCandidateWindowUpdated() OVERRIDE {}
-  virtual void OnCandidateWindowHidden() OVERRIDE {}
-
-  ui::TextInputType type_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestTextInputClient);
-};
-
 class KeyboardContainerObserver : public aura::WindowObserver {
  public:
   explicit KeyboardContainerObserver(aura::Window* window) : window_(window) {
@@ -245,7 +185,7 @@
   KeyboardController* controller() { return controller_.get(); }
 
   void ShowKeyboard() {
-    TestTextInputClient test_text_input_client(ui::TEXT_INPUT_TYPE_TEXT);
+    ui::DummyTextInputClient test_text_input_client(ui::TEXT_INPUT_TYPE_TEXT);
     SetFocus(&test_text_input_client);
   }
 
@@ -374,11 +314,11 @@
 TEST_F(KeyboardControllerTest, VisibilityChangeWithTextInputTypeChange) {
   const gfx::Rect& root_bounds = root_window()->bounds();
 
-  TestTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
-  TestTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
-  TestTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT);
-  TestTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE);
-  TestTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE);
+  ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
+  ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
+  ui::DummyTextInputClient input_client_2(ui::TEXT_INPUT_TYPE_TEXT);
+  ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE);
+  ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE);
 
   aura::Window* keyboard_container(controller()->GetContainerWindow());
   scoped_ptr<KeyboardContainerObserver> keyboard_container_observer(
@@ -415,10 +355,10 @@
 TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) {
   const gfx::Rect& root_bounds = root_window()->bounds();
 
-  TestTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
-  TestTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
-  TestTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE);
-  TestTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE);
+  ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
+  ui::DummyTextInputClient input_client_1(ui::TEXT_INPUT_TYPE_TEXT);
+  ui::DummyTextInputClient no_input_client_0(ui::TEXT_INPUT_TYPE_NONE);
+  ui::DummyTextInputClient no_input_client_1(ui::TEXT_INPUT_TYPE_NONE);
 
   aura::Window* keyboard_container(controller()->GetContainerWindow());
   scoped_ptr<KeyboardContainerObserver> keyboard_container_observer(
@@ -608,8 +548,8 @@
 TEST_F(KeyboardControllerUsabilityTest, KeyboardAlwaysVisibleInUsabilityTest) {
   const gfx::Rect& root_bounds = root_window()->bounds();
 
-  TestTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
-  TestTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
+  ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
+  ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
 
   aura::Window* keyboard_container(controller()->GetContainerWindow());
   keyboard_container->SetBounds(root_bounds);
diff --git a/ui/keyboard/keyboard_layout_manager.cc b/ui/keyboard/keyboard_layout_manager.cc
new file mode 100644
index 0000000..3208541
--- /dev/null
+++ b/ui/keyboard/keyboard_layout_manager.cc
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/keyboard/keyboard_layout_manager.h"
+
+#include "ui/keyboard/keyboard_controller.h"
+#include "ui/keyboard/keyboard_controller_proxy.h"
+#include "ui/keyboard/keyboard_util.h"
+
+namespace keyboard {
+
+// Overridden from aura::LayoutManager
+void KeyboardLayoutManager::OnWindowResized() {
+  if (keyboard_ && !controller_->proxy()->resizing_from_contents())
+    ResizeKeyboardToDefault(keyboard_);
+}
+
+void KeyboardLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
+  DCHECK(!keyboard_);
+  keyboard_ = child;
+  ResizeKeyboardToDefault(keyboard_);
+}
+
+void KeyboardLayoutManager::SetChildBounds(aura::Window* child,
+                                           const gfx::Rect& requested_bounds) {
+  // SetChildBounds can be invoked by resizing from the container or by
+  // resizing from the contents (through window.resizeTo call in JS).
+  // The flag resizing_from_contents() is used to determine the source of the
+  // resize.
+  if (controller_->proxy()->resizing_from_contents()) {
+    controller_->NotifyKeyboardBoundsChanging(requested_bounds);
+    SetChildBoundsDirect(child, requested_bounds);
+  }
+}
+
+void KeyboardLayoutManager::ResizeKeyboardToDefault(aura::Window* child) {
+  gfx::Rect keyboard_bounds = DefaultKeyboardBoundsFromWindowBounds(
+      controller_->GetContainerWindow()->bounds());
+  SetChildBoundsDirect(child, keyboard_bounds);
+}
+
+}  // namespace keyboard
diff --git a/ui/keyboard/keyboard_layout_manager.h b/ui/keyboard/keyboard_layout_manager.h
new file mode 100644
index 0000000..52af5c9
--- /dev/null
+++ b/ui/keyboard/keyboard_layout_manager.h
@@ -0,0 +1,45 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_KEYBOARD_KEYBOARD_LAYOUT_MANAGER_H_
+#define UI_KEYBOARD_KEYBOARD_LAYOUT_MANAGER_H_
+
+#include "ui/aura/layout_manager.h"
+#include "ui/aura/window.h"
+
+namespace keyboard {
+
+class KeyboardController;
+
+// LayoutManager for the virtual keyboard container. Manages a single window
+// (the virtual keyboard) and keeps it positioned at the bottom of the
+// owner window.
+class KeyboardLayoutManager : public aura::LayoutManager {
+ public:
+  explicit KeyboardLayoutManager(KeyboardController* controller)
+      : controller_(controller), keyboard_(NULL) {
+  }
+
+  // Overridden from aura::LayoutManager
+  virtual void OnWindowResized() OVERRIDE;
+  virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
+  virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
+  virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
+  virtual void OnChildWindowVisibilityChanged(aura::Window* child,
+                                              bool visible) OVERRIDE {}
+  virtual void SetChildBounds(aura::Window* child,
+                              const gfx::Rect& requested_bounds) OVERRIDE;
+
+ private:
+  void ResizeKeyboardToDefault(aura::Window* child);
+
+  KeyboardController* controller_;
+  aura::Window* keyboard_;
+
+  DISALLOW_COPY_AND_ASSIGN(KeyboardLayoutManager);
+};
+
+}  // namespace keyboard
+
+#endif  // UI_KEYBOARD_KEYBOARD_LAYOUT_MANAGER_H_
diff --git a/ui/keyboard/keyboard_resources.grd b/ui/keyboard/keyboard_resources.grd
index e86a630..9aec103 100644
--- a/ui/keyboard/keyboard_resources.grd
+++ b/ui/keyboard/keyboard_resources.grd
@@ -15,23 +15,6 @@
   </outputs>
   <release seq="1">
     <includes>
-      <include name="IDR_KEYBOARD_API_ADAPTER_JS" file="resources/api_adapter.js" type="BINDATA" />
-      <include name="IDR_KEYBOARD_CONSTANTS_JS" file="resources/constants.js" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_ALTKEY" file="resources/elements/kb-altkey.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_ALTKEY_CONTAINER" file="resources/elements/kb-altkey-container.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_ALTKEY_DATA" file="resources/elements/kb-altkey-data.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_ALTKEY_SET" file="resources/elements/kb-altkey-set.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_KEY" file="resources/elements/kb-key.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_KEY_BASE" file="resources/elements/kb-key-base.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_KEY_CODES" file="resources/elements/kb-key-codes.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_KEY_IMPORT" file="resources/elements/kb-key-import.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_KEY_SEQUENCE" file="resources/elements/kb-key-sequence.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_KEYBOARD" file="resources/elements/kb-keyboard.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_KEYSET" file="resources/elements/kb-keyset.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_MODIFIER_KEY" file="resources/elements/kb-modifier-key.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_OPTIONS_MENU" file="resources/elements/kb-options-menu.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_ROW" file="resources/elements/kb-row.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_ELEMENTS_SHIFT_KEY" file="resources/elements/kb-shift-key.html" type="BINDATA" />
       <include name="IDR_KEYBOARD_FUNCTION_KEY_ROW" file="resources/layouts/function-key-row.html" type="BINDATA" />
       <include name="IDR_KEYBOARD_IMAGES_BACK" file="resources/images/back.svg" type="BINDATA" />
       <include name="IDR_KEYBOARD_IMAGES_BACKSPACE" file="resources/images/backspace.svg" type="BINDATA" />
@@ -58,15 +41,11 @@
       <include name="IDR_KEYBOARD_IMAGES_UP" file="resources/images/up.svg" type="BINDATA" />
       <include name="IDR_KEYBOARD_IMAGES_VOLUME_DOWN" file="resources/images/volume-down.svg" type="BINDATA" />
       <include name="IDR_KEYBOARD_IMAGES_VOLUME_UP" file="resources/images/volume-up.svg" type="BINDATA" />
-      <!-- Don't flatten html file here. Otherwise, webui keyboard will not load the correct css file. -->
-      <include name="IDR_KEYBOARD_INDEX" file="resources/index.html" allowexternalscript="true" type="BINDATA" />
-      <include name="IDR_KEYBOARD_LAYOUTS_DVORAK" file="resources/layouts/dvorak.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS" file="resources/layouts/latin-accents.js" type="BINDATA" />
+      <include name="IDR_KEYBOARD_INDEX" file="resources/index.html" allowexternalscript="true" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_KEYBOARD_JS" file="resources/keyboard.js" flattenhtml="true" type="BINDATA" />
       <include name="IDR_KEYBOARD_LAYOUTS_NUMERIC" file="resources/layouts/numeric.html" type="BINDATA" />
       <include name="IDR_KEYBOARD_LAYOUTS_QWERTY" file="resources/layouts/qwerty.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_LAYOUTS_SYMBOL_ALTKEYS" file="resources/layouts/symbol-altkeys.js" type="BINDATA" />
       <include name="IDR_KEYBOARD_LAYOUTS_SYSTEM_QWERTY" file="resources/layouts/system-qwerty.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_MAIN_JS" file="resources/main.js" type="BINDATA" />
       <include name="IDR_KEYBOARD_MANIFEST" file="resources/manifest.json" type="BINDATA" />
       <include name="IDR_KEYBOARD_MAIN_CSS" file="resources/main.css" type="BINDATA" />
       <include name="IDR_KEYBOARD_POLYMER_LOADER" file="resources/polymer_loader.js" flattenhtml="true" type="BINDATA" />
@@ -76,13 +55,6 @@
       <include name="IDR_KEYBOARD_SOUNDS_KEYPRESS_SPACEBAR" file="resources/sounds/keypress-spacebar.wav" type="BINDATA" />
       <include name="IDR_KEYBOARD_SOUNDS_KEYPRESS_STANDARD" file="resources/sounds/keypress-standard.wav" type="BINDATA" />
       <include name="IDR_KEYBOARD_SPACEBAR_ROW" file="resources/layouts/spacebar-row.html" type="BINDATA" />
-      <include name="IDR_KEYBOARD_TOUCH_FUZZING_JS" file="resources/touch_fuzzing.js" type="BINDATA" />
-      <include name="IDR_KEYBOARD_VOICE_INPUT_JS" file="resources/voice_input.js" type="BINDATA" />
-      <include name="IDR_KEYBOARD_WEBUI_INDEX" file="resources/webui_index.html" allowexternalscript="true" type="BINDATA" />
-      <include name="IDR_KEYBOARD_WEBUI_API_ADAPTER_JS" file="resources/webui/api_adapter.js" type="BINDATA" />
-      <include name="IDR_KEYBOARD_WEBUI_CONSTANTS_JS" file="resources/webui/constants.js" type="BINDATA" />
-      <include name="IDR_KEYBOARD_WEBUI_MAIN_CSS" file="resources/webui/main.css" type="BINDATA" />
-      <include name="IDR_KEYBOARD_WEBUI_QWERTY" file="resources/layouts/webui_qwerty.html" type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/ui/keyboard/keyboard_switches.cc b/ui/keyboard/keyboard_switches.cc
index aeecf37..36a1aeb 100644
--- a/ui/keyboard/keyboard_switches.cc
+++ b/ui/keyboard/keyboard_switches.cc
@@ -9,6 +9,9 @@
 
 const char kEnableSwipeSelection[] = "enable-swipe-selection";
 
+const char kDisableInputView[] = "disable-input-view";
+const char kEnableInputView[] = "enable-input-view";
+
 const char kEnableVirtualKeyboard[] = "enable-virtual-keyboard";
 const char kKeyboardUsabilityExperiment[] = "keyboard-usability-experiment";
 
diff --git a/ui/keyboard/keyboard_switches.h b/ui/keyboard/keyboard_switches.h
index 04d4e73..21f9471 100644
--- a/ui/keyboard/keyboard_switches.h
+++ b/ui/keyboard/keyboard_switches.h
@@ -13,6 +13,14 @@
 // Enables the swipe selection feature on the virtual keyboard.
 KEYBOARD_EXPORT extern const char kEnableSwipeSelection[];
 
+// Disables IME extension APIs from overriding the URL for specifying the
+// contents of the virtual keyboard container.
+KEYBOARD_EXPORT extern const char kDisableInputView[];
+
+// Enables an IME extension API to set a URL for specifying the contents
+// of the virtual keyboard container.
+KEYBOARD_EXPORT extern const char kEnableInputView[];
+
 // Enables the virtual keyboard.
 KEYBOARD_EXPORT extern const char kEnableVirtualKeyboard[];
 
diff --git a/ui/keyboard/keyboard_ui_controller.cc b/ui/keyboard/keyboard_ui_controller.cc
deleted file mode 100644
index 70bf2f0..0000000
--- a/ui/keyboard/keyboard_ui_controller.cc
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/keyboard/keyboard_ui_controller.h"
-
-#include "content/public/browser/browser_context.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "grit/keyboard_resources.h"
-#include "ui/keyboard/keyboard_constants.h"
-#include "ui/keyboard/keyboard_ui_handler.h"
-
-namespace {
-
-content::WebUIDataSource* CreateKeyboardUIDataSource() {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(keyboard::kKeyboardWebUIHost);
-
-  source->SetDefaultResource(IDR_KEYBOARD_WEBUI_INDEX);
-  source->AddResourcePath("elements/kb-altkey.html",
-                          IDR_KEYBOARD_ELEMENTS_ALTKEY);
-  source->AddResourcePath("elements/kb-altkey-container.html",
-                          IDR_KEYBOARD_ELEMENTS_ALTKEY_CONTAINER);
-  source->AddResourcePath("elements/kb-altkey-data.html",
-                          IDR_KEYBOARD_ELEMENTS_ALTKEY_DATA);
-  source->AddResourcePath("elements/kb-altkey-set.html",
-                          IDR_KEYBOARD_ELEMENTS_ALTKEY_SET);
-  source->AddResourcePath("elements/kb-key.html", IDR_KEYBOARD_ELEMENTS_KEY);
-  source->AddResourcePath("elements/kb-key-base.html",
-                          IDR_KEYBOARD_ELEMENTS_KEY_BASE);
-  source->AddResourcePath("elements/kb-key-codes.html",
-                          IDR_KEYBOARD_ELEMENTS_KEY_CODES);
-  source->AddResourcePath("elements/kb-keyboard.html",
-                          IDR_KEYBOARD_ELEMENTS_KEYBOARD);
-  source->AddResourcePath("elements/kb-keyset.html",
-                          IDR_KEYBOARD_ELEMENTS_KEYSET);
-  source->AddResourcePath("elements/kb-modifier-key.html",
-                          IDR_KEYBOARD_ELEMENTS_MODIFIER_KEY);
-  source->AddResourcePath("elements/kb-options-menu.html",
-                          IDR_KEYBOARD_ELEMENTS_OPTIONS_MENU);
-  source->AddResourcePath("elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW);
-  source->AddResourcePath("elements/kb-shift-key.html",
-                          IDR_KEYBOARD_ELEMENTS_SHIFT_KEY);
-  source->AddResourcePath("images/back.svg",
-                          IDR_KEYBOARD_IMAGES_BACK);
-  source->AddResourcePath("images/backspace.svg",
-                          IDR_KEYBOARD_IMAGES_BACKSPACE);
-  source->AddResourcePath("images/brightness-down.svg",
-                          IDR_KEYBOARD_IMAGES_BRIGHTNESS_DOWN);
-  source->AddResourcePath("images/brightness-up.svg",
-                          IDR_KEYBOARD_IMAGES_BRIGHTNESS_UP);
-  source->AddResourcePath("images/change-window.svg",
-                          IDR_KEYBOARD_IMAGES_CHANGE_WINDOW);
-  source->AddResourcePath("images/down.svg",
-                          IDR_KEYBOARD_IMAGES_DOWN);
-  source->AddResourcePath("images/forward.svg",
-                          IDR_KEYBOARD_IMAGES_FORWARD);
-  source->AddResourcePath("images/fullscreen.svg",
-                          IDR_KEYBOARD_IMAGES_FULLSCREEN);
-  source->AddResourcePath("images/hide-keyboard.svg",
-                          IDR_KEYBOARD_IMAGES_HIDE_KEYBOARD);
-  source->AddResourcePath("images/left.svg",
-                          IDR_KEYBOARD_IMAGES_LEFT);
-  source->AddResourcePath("images/microphone.svg",
-                          IDR_KEYBOARD_IMAGES_MICROPHONE);
-  source->AddResourcePath("images/microphone-green.svg",
-                          IDR_KEYBOARD_IMAGES_MICROPHONE_GREEN);
-  source->AddResourcePath("images/mute.svg",
-                          IDR_KEYBOARD_IMAGES_MUTE);
-  source->AddResourcePath("images/reload.svg",
-                          IDR_KEYBOARD_IMAGES_RELOAD);
-  source->AddResourcePath("images/return.svg",
-                          IDR_KEYBOARD_IMAGES_RETURN);
-  source->AddResourcePath("images/right.svg",
-                          IDR_KEYBOARD_IMAGES_RIGHT);
-  source->AddResourcePath("images/search.svg",
-                          IDR_KEYBOARD_IMAGES_SEARCH);
-  source->AddResourcePath("images/shift.svg",
-                          IDR_KEYBOARD_IMAGES_SHIFT);
-  source->AddResourcePath("images/shift-filled.svg",
-                          IDR_KEYBOARD_IMAGES_SHIFT_FILLED);
-  source->AddResourcePath("images/shutdown.svg",
-                          IDR_KEYBOARD_IMAGES_SHUTDOWN);
-  source->AddResourcePath("images/tab.svg",
-                          IDR_KEYBOARD_IMAGES_TAB);
-  source->AddResourcePath("images/up.svg",
-                          IDR_KEYBOARD_IMAGES_UP);
-  source->AddResourcePath("images/volume-down.svg",
-                          IDR_KEYBOARD_IMAGES_VOLUME_DOWN);
-  source->AddResourcePath("images/volume-up.svg",
-                          IDR_KEYBOARD_IMAGES_VOLUME_UP);
-  source->AddResourcePath("layouts/latin-accents.js",
-                          IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS);
-  source->AddResourcePath("layouts/numeric.html", IDR_KEYBOARD_LAYOUTS_NUMERIC);
-  source->AddResourcePath("layouts/system-qwerty.html",
-                          IDR_KEYBOARD_LAYOUTS_SYSTEM_QWERTY);
-  source->AddResourcePath("main.js", IDR_KEYBOARD_MAIN_JS);
-  source->AddResourcePath("polymer_loader.js", IDR_KEYBOARD_POLYMER_LOADER);
-  source->AddResourcePath("roboto_bold.ttf", IDR_KEYBOARD_ROBOTO_BOLD_TTF);
-  source->AddResourcePath("sounds/keypress-delete.wav",
-                          IDR_KEYBOARD_SOUNDS_KEYPRESS_DELETE);
-  source->AddResourcePath("sounds/keypress-return.wav",
-                          IDR_KEYBOARD_SOUNDS_KEYPRESS_RETURN);
-  source->AddResourcePath("sounds/keypress-spacebar.wav",
-                          IDR_KEYBOARD_SOUNDS_KEYPRESS_SPACEBAR);
-  source->AddResourcePath("sounds/keypress-standard.wav",
-                          IDR_KEYBOARD_SOUNDS_KEYPRESS_STANDARD);
-  source->AddResourcePath("touch_fuzzing.js", IDR_KEYBOARD_TOUCH_FUZZING_JS);
-  source->AddResourcePath("voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS);
-
-  // These files are specific to the WebUI version
-  source->AddResourcePath("api_adapter.js", IDR_KEYBOARD_WEBUI_API_ADAPTER_JS);
-  source->AddResourcePath("constants.js", IDR_KEYBOARD_WEBUI_CONSTANTS_JS);
-  source->AddResourcePath("layouts/qwerty.html", IDR_KEYBOARD_WEBUI_QWERTY);
-  source->AddResourcePath("main.css", IDR_KEYBOARD_WEBUI_MAIN_CSS);
-
-  return source;
-}
-
-}  // namespace
-
-namespace keyboard {
-
-KeyboardUIController::KeyboardUIController(content::WebUI* web_ui)
-    : WebUIController(web_ui) {
-  content::BrowserContext* browser_context =
-      web_ui->GetWebContents()->GetBrowserContext();
-  web_ui->AddMessageHandler(new KeyboardUIHandler());
-  content::WebUIDataSource::Add(
-      browser_context,
-      CreateKeyboardUIDataSource());
-}
-
-KeyboardUIController::~KeyboardUIController() {}
-
-}  // namespace keyboard
diff --git a/ui/keyboard/keyboard_ui_controller.h b/ui/keyboard/keyboard_ui_controller.h
deleted file mode 100644
index b06ec26..0000000
--- a/ui/keyboard/keyboard_ui_controller.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_KEYBOARD_KEYBOARD_UI_CONTROLLER_H_
-#define UI_KEYBOARD_KEYBOARD_UI_CONTROLLER_H_
-
-#include "content/public/browser/web_ui_controller.h"
-#include "ui/keyboard/keyboard_export.h"
-
-namespace content {
-class WebUI;
-};
-
-namespace keyboard {
-
-// WebUIController for chrome://keyboard/.
-class KEYBOARD_EXPORT KeyboardUIController : public content::WebUIController {
- public:
-  explicit KeyboardUIController(content::WebUI* web_ui);
-  virtual ~KeyboardUIController();
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(KeyboardUIController);
-};
-
-}  // namespace keyboard
-
-#endif  // UI_KEYBOARD_KEYBOARD_UI_CONTROLLER_H_
diff --git a/ui/keyboard/keyboard_ui_handler.cc b/ui/keyboard/keyboard_ui_handler.cc
deleted file mode 100644
index 88f4751..0000000
--- a/ui/keyboard/keyboard_ui_handler.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/keyboard/keyboard_ui_handler.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/values.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_contents_view.h"
-#include "content/public/browser/web_ui.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/base/ime/input_method.h"
-#include "ui/base/ime/text_input_client.h"
-#include "ui/keyboard/keyboard_controller.h"
-#include "ui/keyboard/keyboard_util.h"
-
-namespace keyboard {
-
-KeyboardUIHandler::KeyboardUIHandler() {
-}
-
-KeyboardUIHandler::~KeyboardUIHandler() {
-}
-
-void KeyboardUIHandler::RegisterMessages() {
-  web_ui()->RegisterMessageCallback(
-      "insertText",
-      base::Bind(&KeyboardUIHandler::HandleInsertTextMessage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(
-      "getInputContext",
-      base::Bind(&KeyboardUIHandler::HandleGetInputContextMessage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(
-      "sendKeyEvent",
-      base::Bind(&KeyboardUIHandler::HandleSendKeyEventMessage,
-                 base::Unretained(this)));
-  web_ui()->RegisterMessageCallback(
-      "hideKeyboard",
-      base::Bind(&KeyboardUIHandler::HandleHideKeyboard,
-                 base::Unretained(this)));
-}
-
-void KeyboardUIHandler::HandleInsertTextMessage(const base::ListValue* args) {
-  base::string16 text;
-  if (!args->GetString(0, &text)) {
-    LOG(ERROR) << "insertText failed: bad argument";
-    return;
-  }
-
-  aura::Window* root_window =
-      web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow();
-  if (!root_window) {
-    LOG(ERROR) << "insertText failed: no root window";
-    return;
-  }
-
-  if (!keyboard::InsertText(text, root_window))
-    LOG(ERROR) << "insertText failed";
-}
-
-void KeyboardUIHandler::HandleGetInputContextMessage(
-    const base::ListValue* args) {
-  int request_id;
-  if (!args->GetInteger(0, &request_id)) {
-    LOG(ERROR) << "getInputContext failed: bad argument";
-    return;
-  }
-  base::DictionaryValue results;
-  results.SetInteger("requestId", request_id);
-
-  aura::Window* root_window =
-      web_ui()->GetWebContents()->GetView()->GetNativeView()->GetRootWindow();
-  if (!root_window) {
-    LOG(ERROR) << "getInputContext failed: no root window";
-    return;
-  }
-  ui::InputMethod* input_method =
-      root_window->GetProperty(aura::client::kRootWindowInputMethodKey);
-  if (!input_method) {
-    LOG(ERROR) << "getInputContext failed: no input method";
-    return;
-  }
-
-  ui::TextInputClient* tic = input_method->GetTextInputClient();
-  results.SetInteger("type",
-                     tic ? tic->GetTextInputType() : ui::TEXT_INPUT_TYPE_NONE);
-
-  web_ui()->CallJavascriptFunction("GetInputContextCallback",
-                                   results);
-}
-
-void KeyboardUIHandler::HandleSendKeyEventMessage(
-    const base::ListValue* args) {
-  const base::DictionaryValue* params = NULL;
-  std::string type;
-  int char_value;
-  int key_code;
-  std::string key_name;
-  int modifiers;
-
-  if (!args->GetDictionary(0, &params) ||
-      !params->GetString("type", &type) ||
-      !params->GetInteger("charValue", &char_value) ||
-      !params->GetInteger("keyCode", &key_code) ||
-      !params->GetString("keyName", &key_name) ||
-      !params->GetInteger("modifiers", &modifiers)) {
-    LOG(ERROR) << "SendKeyEvent failed: bad argument";
-    return;
-  }
-
-  aura::WindowTreeHost* host =
-      web_ui()->GetWebContents()->GetView()->GetNativeView()->GetHost();
-  if (!host) {
-    LOG(ERROR) << "sendKeyEvent failed: no dispatcher";
-    return;
-  }
-
-  if (!keyboard::SendKeyEvent(type,
-                              char_value,
-                              key_code,
-                              key_name,
-                              modifiers,
-                              host)) {
-    LOG(ERROR) << "sendKeyEvent failed";
-  }
-}
-
-void KeyboardUIHandler::HandleHideKeyboard(const base::ListValue* args) {
-  // TODO(stevet): Call into the keyboard controller to hide the keyboard
-  // directly.
-  NOTIMPLEMENTED();
-  return;
-}
-
-}  // namespace keyboard
diff --git a/ui/keyboard/keyboard_ui_handler.h b/ui/keyboard/keyboard_ui_handler.h
deleted file mode 100644
index 3c14f74..0000000
--- a/ui/keyboard/keyboard_ui_handler.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_KEYBOARD_KEYBOARD_UI_HANDLER_H_
-#define UI_KEYBOARD_KEYBOARD_UI_HANDLER_H_
-
-#include "base/basictypes.h"
-#include "base/compiler_specific.h"
-#include "content/public/browser/web_ui_message_handler.h"
-
-namespace keyboard {
-
-// The WebUI handler for chrome://keyboard.  Inserts text into the currently
-// focused TextInputClient.
-class KeyboardUIHandler : public content::WebUIMessageHandler {
- public:
-  KeyboardUIHandler();
-  virtual ~KeyboardUIHandler();
-
- private:
-  // |content::WebUIMessageHandler| implementation:
-  virtual void RegisterMessages() OVERRIDE;
-
-  // Callback for the "insertText" message.
-  void HandleInsertTextMessage(const base::ListValue* args);
-
-  // Callback for the "getInputContext" message. The first element in
-  // |args| should be an integer representing request ID.
-  void HandleGetInputContextMessage(const base::ListValue* args);
-
-  // Callback for the "sendKeyEvent" message. The first element in |args| is a
-  // dictionary containing an event type, the character being pressed or
-  // released, a virtual key code, and the state of the shift key.
-  void HandleSendKeyEventMessage(const base::ListValue* args);
-
-  // Callback for the "hideKeyboard" message.
-  void HandleHideKeyboard(const base::ListValue* args);
-
-  DISALLOW_COPY_AND_ASSIGN(KeyboardUIHandler);
-};
-
-}  // namespace keyboard
-
-#endif  // UI_KEYBOARD_KEYBOARD_UI_HANDLER_H_
diff --git a/ui/keyboard/keyboard_util.cc b/ui/keyboard/keyboard_util.cc
index d9b0605..157e4be 100644
--- a/ui/keyboard/keyboard_util.cc
+++ b/ui/keyboard/keyboard_util.cc
@@ -43,10 +43,42 @@
 
 base::LazyInstance<GURL> g_override_content_url = LAZY_INSTANCE_INITIALIZER;
 
+// The ratio between the height of the keyboard and the screen when using the
+// usability keyboard.
+const float kUsabilityKeyboardHeightRatio = 1.0f;
+
+// The default ratio between the height of the keyboard and the screen.
+const float kDefaultKeyboardHeightRatio = 0.41f;
+
+// The ratio between the height of the keyboard and the screen when using the
+// accessibility keyboard.
+const float kAccessibilityKeyboardHeightRatio = 0.3f;
+
+float GetKeyboardHeightRatio(){
+  if (keyboard::IsKeyboardUsabilityExperimentEnabled()) {
+    return kUsabilityKeyboardHeightRatio;
+  } else if (keyboard::GetAccessibilityKeyboardEnabled()) {
+    return kAccessibilityKeyboardHeightRatio;
+  }
+  return kDefaultKeyboardHeightRatio;
+}
+
+bool g_touch_keyboard_enabled = false;
+
 }  // namespace
 
 namespace keyboard {
 
+gfx::Rect DefaultKeyboardBoundsFromWindowBounds(
+    const gfx::Rect& window_bounds) {
+  const float kKeyboardHeightRatio = GetKeyboardHeightRatio();
+  return gfx::Rect(
+      window_bounds.x(),
+      window_bounds.y() + window_bounds.height() * (1 - kKeyboardHeightRatio),
+      window_bounds.width(),
+      window_bounds.height() * kKeyboardHeightRatio);
+}
+
 void SetAccessibilityKeyboardEnabled(bool enabled) {
   g_accessibility_keyboard_enabled = enabled;
 }
@@ -55,6 +87,14 @@
   return g_accessibility_keyboard_enabled;
 }
 
+void SetTouchKeyboardEnabled(bool enabled) {
+  g_touch_keyboard_enabled = enabled;
+}
+
+bool GetTouchKeyboardEnabled() {
+  return g_touch_keyboard_enabled;
+}
+
 std::string GetKeyboardLayout() {
   // TODO(bshe): layout string is currently hard coded. We should use more
   // standard keyboard layouts.
@@ -65,7 +105,8 @@
   return g_accessibility_keyboard_enabled ||
       CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kEnableVirtualKeyboard) ||
-      IsKeyboardUsabilityExperimentEnabled();
+      IsKeyboardUsabilityExperimentEnabled() ||
+      g_touch_keyboard_enabled;
 }
 
 bool IsKeyboardUsabilityExperimentEnabled() {
@@ -73,6 +114,15 @@
       switches::kKeyboardUsabilityExperiment);
 }
 
+bool IsInputViewEnabled() {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableInputView))
+    return true;
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableInputView))
+    return false;
+  // Default value if no command line flags specified.
+  return false;
+}
+
 bool InsertText(const base::string16& text, aura::Window* root_window) {
   if (!root_window)
     return false;
@@ -221,29 +271,6 @@
   // necessary to have a custom path for the extension path, so the resource
   // map cannot be used directly.
   static const GritResourceMap kKeyboardResources[] = {
-    {"keyboard/api_adapter.js", IDR_KEYBOARD_API_ADAPTER_JS},
-    {"keyboard/constants.js", IDR_KEYBOARD_CONSTANTS_JS},
-    {"keyboard/elements/kb-altkey.html", IDR_KEYBOARD_ELEMENTS_ALTKEY},
-    {"keyboard/elements/kb-altkey-container.html",
-        IDR_KEYBOARD_ELEMENTS_ALTKEY_CONTAINER},
-    {"keyboard/elements/kb-altkey-data.html",
-        IDR_KEYBOARD_ELEMENTS_ALTKEY_DATA},
-    {"keyboard/elements/kb-altkey-set.html", IDR_KEYBOARD_ELEMENTS_ALTKEY_SET},
-    {"keyboard/elements/kb-key.html", IDR_KEYBOARD_ELEMENTS_KEY},
-    {"keyboard/elements/kb-key-base.html", IDR_KEYBOARD_ELEMENTS_KEY_BASE},
-    {"keyboard/elements/kb-key-codes.html", IDR_KEYBOARD_ELEMENTS_KEY_CODES},
-    {"keyboard/elements/kb-key-import.html",
-        IDR_KEYBOARD_ELEMENTS_KEY_IMPORT},
-    {"keyboard/elements/kb-key-sequence.html",
-        IDR_KEYBOARD_ELEMENTS_KEY_SEQUENCE},
-    {"keyboard/elements/kb-keyboard.html", IDR_KEYBOARD_ELEMENTS_KEYBOARD},
-    {"keyboard/elements/kb-keyset.html", IDR_KEYBOARD_ELEMENTS_KEYSET},
-    {"keyboard/elements/kb-modifier-key.html",
-        IDR_KEYBOARD_ELEMENTS_MODIFIER_KEY},
-    {"keyboard/elements/kb-options-menu.html",
-        IDR_KEYBOARD_ELEMENTS_OPTIONS_MENU},
-    {"keyboard/elements/kb-row.html", IDR_KEYBOARD_ELEMENTS_ROW},
-    {"keyboard/elements/kb-shift-key.html", IDR_KEYBOARD_ELEMENTS_SHIFT_KEY},
     {"keyboard/layouts/function-key-row.html", IDR_KEYBOARD_FUNCTION_KEY_ROW},
     {"keyboard/images/back.svg", IDR_KEYBOARD_IMAGES_BACK},
     {"keyboard/images/backspace.svg", IDR_KEYBOARD_IMAGES_BACKSPACE},
@@ -273,15 +300,11 @@
     {"keyboard/images/volume-down.svg", IDR_KEYBOARD_IMAGES_VOLUME_DOWN},
     {"keyboard/images/volume-up.svg", IDR_KEYBOARD_IMAGES_VOLUME_UP},
     {"keyboard/index.html", IDR_KEYBOARD_INDEX},
-    {"keyboard/layouts/dvorak.html", IDR_KEYBOARD_LAYOUTS_DVORAK},
-    {"keyboard/layouts/latin-accents.js", IDR_KEYBOARD_LAYOUTS_LATIN_ACCENTS},
+    {"keyboard/keyboard.js", IDR_KEYBOARD_JS},
     {"keyboard/layouts/numeric.html", IDR_KEYBOARD_LAYOUTS_NUMERIC},
     {"keyboard/layouts/qwerty.html", IDR_KEYBOARD_LAYOUTS_QWERTY},
-    {"keyboard/layouts/symbol-altkeys.js",
-        IDR_KEYBOARD_LAYOUTS_SYMBOL_ALTKEYS},
     {"keyboard/layouts/system-qwerty.html", IDR_KEYBOARD_LAYOUTS_SYSTEM_QWERTY},
     {"keyboard/layouts/spacebar-row.html", IDR_KEYBOARD_SPACEBAR_ROW},
-    {"keyboard/main.js", IDR_KEYBOARD_MAIN_JS},
     {"keyboard/manifest.json", IDR_KEYBOARD_MANIFEST},
     {"keyboard/main.css", IDR_KEYBOARD_MAIN_CSS},
     {"keyboard/polymer_loader.js", IDR_KEYBOARD_POLYMER_LOADER},
@@ -294,8 +317,6 @@
         IDR_KEYBOARD_SOUNDS_KEYPRESS_SPACEBAR},
     {"keyboard/sounds/keypress-standard.wav",
         IDR_KEYBOARD_SOUNDS_KEYPRESS_STANDARD},
-    {"keyboard/touch_fuzzing.js", IDR_KEYBOARD_TOUCH_FUZZING_JS},
-    {"keyboard/voice_input.js", IDR_KEYBOARD_VOICE_INPUT_JS},
   };
   static const size_t kKeyboardResourcesSize = arraysize(kKeyboardResources);
   *size = kKeyboardResourcesSize;
diff --git a/ui/keyboard/keyboard_util.h b/ui/keyboard/keyboard_util.h
index b267422..a3a1f8a 100644
--- a/ui/keyboard/keyboard_util.h
+++ b/ui/keyboard/keyboard_util.h
@@ -38,12 +38,22 @@
   KEYBOARD_CONTROL_MAX,
 };
 
+// Gets the default keyboard bounds from |window_bounds|.
+KEYBOARD_EXPORT gfx::Rect DefaultKeyboardBoundsFromWindowBounds(
+    const gfx::Rect& window_bounds);
+
 // Sets the state of the a11y onscreen keyboard.
 KEYBOARD_EXPORT void SetAccessibilityKeyboardEnabled(bool enabled);
 
 // Gets the state of the a11y onscreen keyboard.
 KEYBOARD_EXPORT bool GetAccessibilityKeyboardEnabled();
 
+// Sets the state of the touch onscreen keyboard.
+KEYBOARD_EXPORT void SetTouchKeyboardEnabled(bool enabled);
+
+// Gets the state of the touch onscreen keyboard.
+KEYBOARD_EXPORT bool GetTouchKeyboardEnabled();
+
 // Gets the default keyboard layout.
 KEYBOARD_EXPORT std::string GetKeyboardLayout();
 
@@ -53,6 +63,10 @@
 // Returns true if the keyboard usability test is enabled.
 KEYBOARD_EXPORT bool IsKeyboardUsabilityExperimentEnabled();
 
+// Returns true if an IME extension can specify a custom input view for the
+// virtual keyboard window.
+KEYBOARD_EXPORT bool IsInputViewEnabled();
+
 // Insert |text| into the active TextInputClient associated with |root_window|,
 // if there is one. Returns true if |text| was successfully inserted. Note
 // that this may convert |text| into ui::KeyEvents for injection in some
diff --git a/ui/keyboard/resources/elements/kb-altkey-container.html b/ui/keyboard/resources/elements/kb-altkey-container.html
index 552c70f..510d20b 100644
--- a/ui/keyboard/resources/elements/kb-altkey-container.html
+++ b/ui/keyboard/resources/elements/kb-altkey-container.html
@@ -20,30 +20,4 @@
     </style>
     <content select="#{{keyset}}"></content>
   </template>
-  <script>
-    Polymer('kb-altkey-container', {
-      resetActiveElement: function() {
-        var activeAccentKeySet = this.querySelector('#' + this.keyset);
-        var offset = activeAccentKeySet.offset;
-        var element = activeAccentKeySet.firstElementChild;
-        while (offset) {
-          element = element.nextElementSibling;
-          offset--;
-        }
-        element.classList.add('active');
-      },
-      up: function(detail) {
-        this.hidden = true;
-        this.resetActiveElement();
-        this.keyset = null;
-      },
-
-      hiddenChanged: function() {
-        this.fire('stateChange', {
-          state: 'candidatePopupVisibility',
-          value: !!this.hidden
-        });
-      },
-    });
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-altkey-container.js b/ui/keyboard/resources/elements/kb-altkey-container.js
new file mode 100644
index 0000000..c6c4fe6
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-altkey-container.js
@@ -0,0 +1,28 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer('kb-altkey-container', {
+  resetActiveElement: function() {
+    var activeAccentKeySet = this.querySelector('#' + this.keyset);
+    var offset = activeAccentKeySet.offset;
+    var element = activeAccentKeySet.firstElementChild;
+    while (offset) {
+      element = element.nextElementSibling;
+      offset--;
+    }
+    element.classList.add('active');
+  },
+  up: function(detail) {
+    this.hidden = true;
+    this.resetActiveElement();
+    this.keyset = null;
+  },
+
+  hiddenChanged: function() {
+    this.fire('stateChange', {
+      state: 'candidatePopupVisibility',
+      value: !!this.hidden
+    });
+  },
+});
diff --git a/ui/keyboard/resources/elements/kb-altkey-data.html b/ui/keyboard/resources/elements/kb-altkey-data.html
index 67f793a..63b8fad 100644
--- a/ui/keyboard/resources/elements/kb-altkey-data.html
+++ b/ui/keyboard/resources/elements/kb-altkey-data.html
@@ -5,128 +5,4 @@
   -->
 
 <polymer-element name="kb-altkey-data" attributes="char list">
-<script>
-  (function() {
-    var altKeys = {};
-    var idMap = {};
-
-    /**
-     * Creates a unique identifier based on the key provided.
-     * This identifier is of the form 'idHASH' where HASH is
-     * the concatenation of the keycodes of every character in the string.
-     * @param {string} key Key for which we want an identifier.
-     * @return {string} The unique id for key.
-     */
-    function createId(key) {
-      var hash = key.split('').map(
-        // Returns the key code for the character.
-        function(character) {
-          return character.charCodeAt(0);
-        }
-      ).join('');
-      return 'id' + hash;
-    }
-
-    Polymer('kb-altkey-data', {
-
-      /**
-       * Retrieves a list of alternative keys to display on a long-press.
-       * @param {string} char The base character.
-       * @param {boolean=} opt_force If true, force the creation of a list
-       *    even if empty. Used when constructing a set of alternates for keys
-       *    with hintTexts.
-       * @return {?Object.{id: string, list: string}}
-       */
-      getAltkeys: function(char, opt_force) {
-        var id = idMap[char];
-        if (id) {
-          return {
-            'id': id,
-            'keys': altKeys[id]
-          };
-        }
-        if (opt_force) {
-          return {
-            'id': createId(char),
-            'keys': []
-          };
-        }
-      },
-
-      /**
-       * Registers lists of alternative keys displayed on a long-press.
-       * @param {Object.<string, Array.<string>>} data Mapping of characters to
-       *     lists of alternatives.
-       */
-      registerAltkeys: function(data) {
-        for (var key in data) {
-          var id = idMap[key];
-          if (!id)
-            idMap[key] = id = createId(key);
-          altKeys[id] = data[key];
-        }
-      },
-
-      /**
-       * Creates a list of alternate candidates to display in a popup on a
-       * long-press.
-       * @param {string} char The base character.
-       * @param {number} maxLeftOffset Limits the number of candidates
-       *      displayed to the left of the base character to prevent running
-       *      past the left edge of the keyboard.
-       * @param {number} maxRightOffset Limits the number of candidates
-       *     displayed to the right of the base character to prvent running
-       *     past the right edge of the keyboard.
-       * @param {string=} opt_additionalKeys Optional list of additional keys
-       *     to include in the candidates list.
-       */
-      createAltkeySet: function(char,
-                                maxLeftOffset,
-                                maxRightOffset,
-                                opt_additionalKeys) {
-        var altKeys = this.getAltkeys(char, true /* forced */);
-        if (altKeys) {
-          var list = altKeys.keys;
-          if (opt_additionalKeys)
-            list = opt_additionalKeys.split('').concat(list);
-          list = [char].concat(list);
-
-          var set = document.createElement('kb-altkey-set');
-          // Candiates are approximately in decreasing order of usage, and are
-          // arranged in a single row in the popup display.  To reduce the
-          // expected length of the drag gesture for selecting a candidate,
-          // more likely candidates are placed in the center of the popup,
-          // which is achieved by alternately appending and prepending
-          // candiates in the alternatives popup.
-          var prepend = false;
-          var leftOffset = 0;
-          var rightOffset = 0;
-          for (var i = 0; i < list.length; i++) {
-            var key = document.createElement('kb-altkey');
-            key.textContent = list[i];
-            if (prepend) {
-              set.insertBefore(key, set.firstChild);
-              leftOffset++;
-            } else {
-              set.appendChild(key);
-              rightOffset++;
-            }
-            prepend = !prepend;
-            // Verify that there is room remaining for an additional character.
-            if (leftOffset == maxLeftOffset && rightOffset == maxRightOffset)
-              break;
-            if (leftOffset == maxLeftOffset)
-              prepend = false;
-            else if (rightOffset == maxRightOffset)
-              prepend = true;
-          }
-          set.id = altKeys.id;
-          set.offset = leftOffset;
-          return set;
-        }
-      },
-
-    });
-  })();
-</script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-altkey-data.js b/ui/keyboard/resources/elements/kb-altkey-data.js
new file mode 100644
index 0000000..e45cb31
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-altkey-data.js
@@ -0,0 +1,126 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+  var altKeys = {};
+  var idMap = {};
+
+    /**
+     * Creates a unique identifier based on the key provided.
+     * This identifier is of the form 'idHASH' where HASH is
+     * the concatenation of the keycodes of every character in the string.
+     * @param {string} key Key for which we want an identifier.
+     * @return {string} The unique id for key.
+     */
+     function createId(key) {
+      var hash = key.split('').map(
+        // Returns the key code for the character.
+        function(character) {
+          return character.charCodeAt(0);
+        }
+        ).join('');
+      return 'id' + hash;
+    }
+
+    Polymer('kb-altkey-data', {
+
+      /**
+       * Retrieves a list of alternative keys to display on a long-press.
+       * @param {string} char The base character.
+       * @param {boolean=} opt_force If true, force the creation of a list
+       *    even if empty. Used when constructing a set of alternates for keys
+       *    with hintTexts.
+       * @return {?Object.{id: string, list: string}}
+       */
+       getAltkeys: function(char, opt_force) {
+        var id = idMap[char];
+        if (id) {
+          return {
+            'id': id,
+            'keys': altKeys[id]
+          };
+        }
+        if (opt_force) {
+          return {
+            'id': createId(char),
+            'keys': []
+          };
+        }
+      },
+
+      /**
+       * Registers lists of alternative keys displayed on a long-press.
+       * @param {Object.<string, Array.<string>>} data Mapping of characters to
+       *     lists of alternatives.
+       */
+       registerAltkeys: function(data) {
+        for (var key in data) {
+          var id = idMap[key];
+          if (!id)
+            idMap[key] = id = createId(key);
+          altKeys[id] = data[key];
+        }
+      },
+
+      /**
+       * Creates a list of alternate candidates to display in a popup on a
+       * long-press.
+       * @param {string} char The base character.
+       * @param {number} maxLeftOffset Limits the number of candidates
+       *      displayed to the left of the base character to prevent running
+       *      past the left edge of the keyboard.
+       * @param {number} maxRightOffset Limits the number of candidates
+       *     displayed to the right of the base character to prvent running
+       *     past the right edge of the keyboard.
+       * @param {string=} opt_additionalKeys Optional list of additional keys
+       *     to include in the candidates list.
+       */
+       createAltkeySet: function(char,
+        maxLeftOffset,
+        maxRightOffset,
+        opt_additionalKeys) {
+        var altKeys = this.getAltkeys(char, true /* forced */);
+        if (altKeys) {
+          var list = altKeys.keys;
+          if (opt_additionalKeys)
+            list = opt_additionalKeys.split('').concat(list);
+          list = [char].concat(list);
+
+          var set = document.createElement('kb-altkey-set');
+          // Candiates are approximately in decreasing order of usage, and are
+          // arranged in a single row in the popup display.  To reduce the
+          // expected length of the drag gesture for selecting a candidate,
+          // more likely candidates are placed in the center of the popup,
+          // which is achieved by alternately appending and prepending
+          // candiates in the alternatives popup.
+          var prepend = false;
+          var leftOffset = 0;
+          var rightOffset = 0;
+          for (var i = 0; i < list.length; i++) {
+            var key = document.createElement('kb-altkey');
+            key.textContent = list[i];
+            if (prepend) {
+              set.insertBefore(key, set.firstChild);
+              leftOffset++;
+            } else {
+              set.appendChild(key);
+              rightOffset++;
+            }
+            prepend = !prepend;
+            // Verify that there is room remaining for an additional character.
+            if (leftOffset == maxLeftOffset && rightOffset == maxRightOffset)
+              break;
+            if (leftOffset == maxLeftOffset)
+              prepend = false;
+            else if (rightOffset == maxRightOffset)
+              prepend = true;
+          }
+          set.id = altKeys.id;
+          set.offset = leftOffset;
+          return set;
+        }
+      },
+
+    });
+})();
diff --git a/ui/keyboard/resources/elements/kb-altkey-set.html b/ui/keyboard/resources/elements/kb-altkey-set.html
index dfa93c3..65a175f 100644
--- a/ui/keyboard/resources/elements/kb-altkey-set.html
+++ b/ui/keyboard/resources/elements/kb-altkey-set.html
@@ -17,9 +17,4 @@
     </style>
     <content select="*"></content>
   </template>
-  <script>
-    Polymer('kb-altkey-set', {
-      offset: 0,
-    });
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-altkey-set.js b/ui/keyboard/resources/elements/kb-altkey-set.js
new file mode 100644
index 0000000..9679d9f
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-altkey-set.js
@@ -0,0 +1,7 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer('kb-altkey-set', {
+  offset: 0,
+});
diff --git a/ui/keyboard/resources/elements/kb-altkey.html b/ui/keyboard/resources/elements/kb-altkey.html
index b6e6615..34ff0fe 100644
--- a/ui/keyboard/resources/elements/kb-altkey.html
+++ b/ui/keyboard/resources/elements/kb-altkey.html
@@ -49,53 +49,4 @@
       <content></content>
     </div>
   </template>
-  <script>
-    /**
-     * Filter out mouse/touch movements internal to this node. When moving
-     * inside a node, the event should be filter out.
-     * @param {Node} node The accent key node which receives event.
-     * @param {event} event A pointer move event.
-     * @return {boolean} True if event is external to node.
-     */
-    function isRelevantEvent(node, event) {
-      return !(node.compareDocumentPosition(event.relatedTarget)
-          & Node.DOCUMENT_POSITION_CONTAINED_BY);
-    };
-    Polymer('kb-altkey', {
-      over: function(event) {
-        if (isRelevantEvent(this, event)) {
-          // Dragging over an accent key is equivalent to pressing on the accent
-          // key.
-          this.fire('key-down', {});
-        }
-      },
-
-      out: function(event) {
-        if (isRelevantEvent(this, event)) {
-          this.classList.remove('active');
-        }
-      },
-
-      up: function(event) {
-        var detail = {
-            char: this.charValue
-        };
-        this.fire('key-up', detail);
-      },
-
-      // TODO(bshe): kb-altkey should extend from kb-key-base.
-      autoRelease: function() {
-      },
-
-      /**
-       * Character value associated with the key. Typically, the value is a
-       * single character, but may be multi-character in cases like a ".com"
-       * button.
-       * @return {string}
-       */
-      get charValue() {
-        return this.char || this.textContent;
-      }
-    });
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-altkey.js b/ui/keyboard/resources/elements/kb-altkey.js
new file mode 100644
index 0000000..ee70a5e
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-altkey.js
@@ -0,0 +1,52 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * Filter out mouse/touch movements internal to this node. When moving
+ * inside a node, the event should be filter out.
+ * @param {Node} node The accent key node which receives event.
+ * @param {event} event A pointer move event.
+ * @return {boolean} True if event is external to node.
+ */
+ function isRelevantEvent(node, event) {
+  return !(node.compareDocumentPosition(event.relatedTarget)
+    & Node.DOCUMENT_POSITION_CONTAINED_BY);
+};
+Polymer('kb-altkey', {
+  over: function(event) {
+    if (isRelevantEvent(this, event)) {
+      // Dragging over an accent key is equivalent to pressing on the accent
+      // key.
+      this.fire('key-down', {});
+    }
+  },
+
+  out: function(event) {
+    if (isRelevantEvent(this, event)) {
+      this.classList.remove('active');
+    }
+  },
+
+  up: function(event) {
+    var detail = {
+      char: this.charValue
+    };
+    this.fire('key-up', detail);
+  },
+
+  // TODO(bshe): kb-altkey should extend from kb-key-base.
+  autoRelease: function() {
+  },
+
+  /**
+   * Character value associated with the key. Typically, the value is a
+   * single character, but may be multi-character in cases like a ".com"
+   * button.
+   * @return {string}
+   */
+   get charValue() {
+    return this.char || this.textContent;
+  }
+});
+
diff --git a/ui/keyboard/resources/elements/kb-key-base.html b/ui/keyboard/resources/elements/kb-key-base.html
index 419c253..c1649b8 100644
--- a/ui/keyboard/resources/elements/kb-key-base.html
+++ b/ui/keyboard/resources/elements/kb-key-base.html
@@ -4,233 +4,6 @@
   -- found in the LICENSE file.
   -->
 
-<polymer-element name="kb-key-base"
-    on-pointerout="{{out}}"
-    attributes="char invert repeat hintText toKeyset toLayout">
-  <script>
-    /**
-     * The long-press delay in milliseconds before long-press handler is
-     * invoked.
-     * @const
-     * @type {number}
-     */
-    var LONGPRESS_DELAY_MSEC = 500;
-
-    /**
-     * The maximum number of elements in one keyset rule.
-     * @const
-     * @type {number}
-     */
-    var MAXIMUM_NUM_OF_RULE_ELEMENTS = 3;
-
-    /**
-     * The minumum number of elements in one keyset rule.
-     * @const
-     * @type {number}
-     */
-    var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
-
-    /**
-     * The index of event type element in the splitted keyset rule.
-     * @const
-     * @type {number}
-     */
-    var EVENT_TYPE = 0;
-
-    /**
-     * The index of toKeyset element in the splitted keyset rule.
-     * @const
-     * @type {number}
-     */
-    var TO_KEYSET = 1;
-
-    /**
-     * The index of nextKeyset element in the splitted keyset rule.
-     * @const
-     * @type {number}
-     */
-    var NEXT_KEYSET = 2;
-
-    /**
-     * The index offset of toKeyset and nextKeyset elements in splitted keyset
-     * rule array and the array in keysetRules.
-     * @const
-     * @type {number}
-     */
-    var OFFSET = 1;
-
-    /**
-     * The minumum number of elements in one keyset rule.
-     * @const {number}
-     */
-    var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
-
-    Polymer('kb-key-base', {
-      repeat: false,
-      invert: false,
-      longPressTimer: null,
-      pointerId: undefined,
-
-      /**
-       * The keyset transition rules. It defines which keyset to transit to on
-       * which key events. It consists at most four rules (down, up, long, dbl).
-       * If no rule is defined for a key event, the event wont trigger a keyset
-       * change.
-       * @type {Object.<string, Array.<string>}
-       */
-      keysetRules: null,
-
-      ready: function() {
-        if (this.toKeyset) {
-          // Parsing keyset rules from toKeyset attribute string.
-          // An rule can be defined as: (down|up|long|dbl):keysetid[:keysetid]
-          // and each rule are separated by a semicolon. The first element
-          // defines the event this rule applies to. The second element defines
-          // what keyset to transit to after event received. The third optional
-          // element defines what keyset to transit to after a key is pressed in
-          // the new keyset. It is useful when you want to transit to a not
-          // locked keyset. For example, after transit to a upper case keyset,
-          // it may make sense to transit back to lower case after user typed
-          // any key at the upper case keyset.
-          var rules =
-              this.toKeyset.replace(/(\r\n|\n|\r| )/g, '').split(';');
-          this.keysetRules = {};
-          var self = this;
-          rules.forEach(function(element) {
-            if (element == '')
-              return;
-            var keyValues = element.split(':', MAXIMUM_NUM_OF_RULE_ELEMENTS);
-            if (keyValues.length < MINIMUM_NUM_OF_RULE_ELEMENTS) {
-              console.error('Invalid keyset rules: ' + element);
-              return;
-            }
-            self.keysetRules[keyValues[EVENT_TYPE]] = [keyValues[TO_KEYSET],
-                (keyValues[NEXT_KEYSET] ? keyValues[NEXT_KEYSET] : null)];
-          });
-        }
-      },
-
-      down: function(event) {
-        this.pointerId = event.pointerId;
-        var detail = this.populateDetails('down');
-        this.fire('key-down', detail);
-        this.longPressTimer = this.generateLongPressTimer();
-      },
-      out: function(event) {
-        this.classList.remove('active');
-        clearTimeout(this.longPressTimer);
-      },
-      up: function(event) {
-        this.generateKeyup();
-      },
-
-      /**
-       * Releases the pressed key programmatically and fires key-up event. This
-       * should be called if a second key is pressed while the first key is not
-       * released yet.
-       */
-      autoRelease: function() {
-        this.generateKeyup();
-      },
-
-      /**
-       * Drops the pressed key.
-       */
-      dropKey: function() {
-        this.classList.remove('active');
-        clearTimeout(this.longPressTimer);
-        this.pointerId = undefined;
-      },
-
-      /**
-       * Populates details for this key, and then fires a key-up event.
-       */
-      generateKeyup: function() {
-        if (this.pointerId === undefined)
-          return;
-
-        // Invalidates the pointerId so the subsequent pointerup event is a
-        // noop.
-        this.pointerId = undefined;
-        clearTimeout(this.longPressTimer);
-        var detail = this.populateDetails('up');
-        this.fire('key-up', detail);
-      },
-
-      /**
-       * Character value associated with the key. Typically, the value is a
-       * single character, but may be multi-character in cases like a ".com"
-       * button.
-       * @return {string}
-       */
-      get charValue() {
-        return this.invert ? this.hintText : (this.char || this.textContent);
-      },
-
-      /**
-       * Hint text value associated with the key. Typically, the value is a
-       * single character.
-       * @return {string}
-       */
-      get hintTextValue() {
-        return this.invert ? (this.char || this.textContent) : this.hintText;
-      },
-
-      /**
-       * Handles a swipe flick that originated from this key.
-       * @param {detail} The details of the swipe.
-       */
-      onFlick: function(detail) {
-        if (!(detail.direction & SwipeDirection.UP) || !this.hintTextValue)
-          return;
-        var typeDetails = {char: this.hintTextValue};
-        this.fire('type-key', typeDetails);
-      },
-
-      /**
-       * Returns a subset of the key attributes.
-       * @param {string} caller The id of the function which called
-       *     populateDetails.
-       */
-      populateDetails: function(caller) {
-        var detail = {
-          char: this.charValue,
-          toLayout: this.toLayout,
-          repeat: this.repeat
-        };
-
-        switch (caller) {
-          case ('up'):
-            if (this.keysetRules && this.keysetRules.up != undefined) {
-              detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET];
-              detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET];
-            }
-            break;
-          case ('down'):
-            if (this.keysetRules && this.keysetRules.down != undefined) {
-              detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET];
-              detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET];
-            }
-            break;
-          default:
-            break;
-        }
-        return detail;
-      },
-
-      generateLongPressTimer: function() {
-        return this.async(function() {
-          var detail = {
-            char: this.charValue,
-            hintText: this.hintTextValue
-          };
-          if (this.keysetRules && this.keysetRules.long != undefined) {
-            detail.toKeyset = this.keysetRules.long[TO_KEYSET - OFFSET];
-            detail.nextKeyset = this.keysetRules.long[NEXT_KEYSET - OFFSET];
-          }
-          this.fire('key-longpress', detail);
-        }, null, LONGPRESS_DELAY_MSEC);
-      },
-    });
-  </script>
+<polymer-element name="kb-key-base" on-pointerout="{{out}}" attributes="char
+    invert repeat hintText toKeyset toLayout">
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-key-base.js b/ui/keyboard/resources/elements/kb-key-base.js
new file mode 100644
index 0000000..ed6b527
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-key-base.js
@@ -0,0 +1,228 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * The long-press delay in milliseconds before long-press handler is
+ * invoked.
+ * @const
+ * @type {number}
+ */
+var LONGPRESS_DELAY_MSEC = 500;
+
+/**
+ * The maximum number of elements in one keyset rule.
+ * @const
+ * @type {number}
+ */
+var MAXIMUM_NUM_OF_RULE_ELEMENTS = 3;
+
+/**
+ * The minumum number of elements in one keyset rule.
+ * @const
+ * @type {number}
+ */
+var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
+
+/**
+ * The index of event type element in the splitted keyset rule.
+ * @const
+ * @type {number}
+ */
+var EVENT_TYPE = 0;
+
+/**
+ * The index of toKeyset element in the splitted keyset rule.
+ * @const
+ * @type {number}
+ */
+var TO_KEYSET = 1;
+
+/**
+ * The index of nextKeyset element in the splitted keyset rule.
+ * @const
+ * @type {number}
+ */
+var NEXT_KEYSET = 2;
+
+/**
+ * The index offset of toKeyset and nextKeyset elements in splitted keyset
+ * rule array and the array in keysetRules.
+ * @const
+ * @type {number}
+ */
+var OFFSET = 1;
+
+/**
+ * The minumum number of elements in one keyset rule.
+ * @const {number}
+ */
+var MINIMUM_NUM_OF_RULE_ELEMENTS = 2;
+
+Polymer('kb-key-base', {
+  repeat: false,
+  invert: false,
+  longPressTimer: null,
+  pointerId: undefined,
+
+  /**
+   * The keyset transition rules. It defines which keyset to transit to on
+   * which key events. It consists at most four rules (down, up, long, dbl).
+   * If no rule is defined for a key event, the event wont trigger a keyset
+   * change.
+   * @type {Object.<string, Array.<string>}
+   */
+  keysetRules: null,
+
+  ready: function() {
+    if (this.toKeyset) {
+      // Parsing keyset rules from toKeyset attribute string.
+      // An rule can be defined as: (down|up|long|dbl):keysetid[:keysetid]
+      // and each rule are separated by a semicolon. The first element
+      // defines the event this rule applies to. The second element defines
+      // what keyset to transit to after event received. The third optional
+      // element defines what keyset to transit to after a key is pressed in
+      // the new keyset. It is useful when you want to transit to a not
+      // locked keyset. For example, after transit to a upper case keyset,
+      // it may make sense to transit back to lower case after user typed
+      // any key at the upper case keyset.
+      var rules =
+          this.toKeyset.replace(/(\r\n|\n|\r| )/g, '').split(';');
+      this.keysetRules = {};
+      var self = this;
+      rules.forEach(function(element) {
+        if (element == '')
+          return;
+        var keyValues = element.split(':', MAXIMUM_NUM_OF_RULE_ELEMENTS);
+        if (keyValues.length < MINIMUM_NUM_OF_RULE_ELEMENTS) {
+          console.error('Invalid keyset rules: ' + element);
+          return;
+        }
+        self.keysetRules[keyValues[EVENT_TYPE]] = [keyValues[TO_KEYSET],
+            (keyValues[NEXT_KEYSET] ? keyValues[NEXT_KEYSET] : null)];
+      });
+    }
+  },
+
+  down: function(event) {
+    this.pointerId = event.pointerId;
+    var detail = this.populateDetails('down');
+    this.fire('key-down', detail);
+    this.longPressTimer = this.generateLongPressTimer();
+  },
+  out: function(event) {
+    this.classList.remove('active');
+    clearTimeout(this.longPressTimer);
+  },
+  up: function(event) {
+    this.generateKeyup();
+  },
+
+  /**
+   * Releases the pressed key programmatically and fires key-up event. This
+   * should be called if a second key is pressed while the first key is not
+   * released yet.
+   */
+  autoRelease: function() {
+    this.generateKeyup();
+  },
+
+  /**
+   * Drops the pressed key.
+   */
+  dropKey: function() {
+    this.classList.remove('active');
+    clearTimeout(this.longPressTimer);
+    this.pointerId = undefined;
+  },
+
+  /**
+   * Populates details for this key, and then fires a key-up event.
+   */
+  generateKeyup: function() {
+    if (this.pointerId === undefined)
+      return;
+
+    // Invalidates the pointerId so the subsequent pointerup event is a
+    // noop.
+    this.pointerId = undefined;
+    clearTimeout(this.longPressTimer);
+    var detail = this.populateDetails('up');
+    this.fire('key-up', detail);
+  },
+
+  /**
+   * Character value associated with the key. Typically, the value is a
+   * single character, but may be multi-character in cases like a ".com"
+   * button.
+   * @return {string}
+   */
+  get charValue() {
+    return this.invert ? this.hintText : (this.char || this.textContent);
+  },
+
+  /**
+   * Hint text value associated with the key. Typically, the value is a
+   * single character.
+   * @return {string}
+   */
+  get hintTextValue() {
+    return this.invert ? (this.char || this.textContent) : this.hintText;
+  },
+
+  /**
+   * Handles a swipe flick that originated from this key.
+   * @param {detail} The details of the swipe.
+   */
+  onFlick: function(detail) {
+    if (!(detail.direction & SwipeDirection.UP) || !this.hintTextValue)
+      return;
+    var typeDetails = {char: this.hintTextValue};
+    this.fire('type-key', typeDetails);
+  },
+
+  /**
+   * Returns a subset of the key attributes.
+   * @param {string} caller The id of the function which called
+   *     populateDetails.
+   */
+  populateDetails: function(caller) {
+    var detail = {
+      char: this.charValue,
+      toLayout: this.toLayout,
+      repeat: this.repeat
+    };
+
+    switch (caller) {
+      case ('up'):
+        if (this.keysetRules && this.keysetRules.up != undefined) {
+          detail.toKeyset = this.keysetRules.up[TO_KEYSET - OFFSET];
+          detail.nextKeyset = this.keysetRules.up[NEXT_KEYSET - OFFSET];
+        }
+        break;
+      case ('down'):
+        if (this.keysetRules && this.keysetRules.down != undefined) {
+          detail.toKeyset = this.keysetRules.down[TO_KEYSET - OFFSET];
+          detail.nextKeyset = this.keysetRules.down[NEXT_KEYSET - OFFSET];
+        }
+        break;
+      default:
+        break;
+    }
+    return detail;
+  },
+
+  generateLongPressTimer: function() {
+    return this.async(function() {
+      var detail = {
+        char: this.charValue,
+        hintText: this.hintTextValue
+      };
+      if (this.keysetRules && this.keysetRules.long != undefined) {
+        detail.toKeyset = this.keysetRules.long[TO_KEYSET - OFFSET];
+        detail.nextKeyset = this.keysetRules.long[NEXT_KEYSET - OFFSET];
+      }
+      this.fire('key-longpress', detail);
+    }, null, LONGPRESS_DELAY_MSEC);
+  },
+});
diff --git a/ui/keyboard/resources/elements/kb-key-codes.html b/ui/keyboard/resources/elements/kb-key-codes.html
index d99a00f..8fc0ee8 100644
--- a/ui/keyboard/resources/elements/kb-key-codes.html
+++ b/ui/keyboard/resources/elements/kb-key-codes.html
@@ -5,229 +5,4 @@
   -->
 
 <polymer-element name="kb-key-codes">
-<script>
-  (function() {
-
-    // Flag values for ctrl, alt and shift as defined by EventFlags
-    // in "event_constants.h".
-    // @enum {number}
-    var Modifier = {
-      NONE: 0,
-      ALT: 8,
-      CONTROL: 4,
-      SHIFT: 2
-    }
-
-    // Each virtual key event is assigned a unique ID.
-    var nextRequestID = 0;
-
-    // Keycodes have been deprecated in the KeyEvent specification, but are
-    // nonetheless required to support legacy web content.  The Keycodes in the
-    // following table are based on subset of US-EN 101-key keyboard. These
-    // codes are used in the absence of explicit keycodes for kb-key and
-    // kb-keysequence elements. Keyboard layout authors may explicitly set the
-    // keyCode attribute for kb-key or kb-keysequence elements to refer to
-    // indices in this table in order to emulate a physical keyboard with an
-    // alternate layout.  Not all keys on a virtual keyboard are required to
-    // have keyCodes. The shiftModifier specifies whether to always include or
-    // exclude the shift modifer when sending key events for this key. If it's
-    // undefined, it will defer to state of the keyboard.
-    // TODO(rsadam): Correctly propagate shutdown keycode. This is currently
-    // ignored due to chromoting (crbug/146609)
-    var keyCodes = {
-      '\b': {keyCode: 0x08, keyName: 'Backspace', shiftModifier: false},
-      '\t': {keyCode: 0x09, keyName: 'Tab', shiftModifier: false},
-      '\n': {keyCode: 0x0D, keyName: 'Enter', shiftModifier: false},
-      'Esc': {keyCode: 0x1B, keyName: 'Escape', shiftModifier: false},
-      ' ': {keyCode: 0x20, keyName: 'Space', shiftModifier: false},
-      'Arrow-Left': {keyCode: 0x25, keyName: 'ArrowLeft',
-          shiftModifier: undefined},
-      'Arrow-Up': {keyCode: 0x26, keyName: 'ArrowUp', shiftModifier: undefined},
-      'Arrow-Right': {keyCode: 0x27, keyName: 'ArrowRight',
-          shiftModifier: undefined},
-      'Arrow-Down': {keyCode: 0x28, keyName: 'ArrowDown',
-          shiftModifier: undefined},
-      '0': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: false},
-      ')': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: true},
-      '1': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: false},
-      '!': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: true},
-      '2': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: false},
-      '@': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: true},
-      '3': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: false},
-      '#': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: true},
-      '4': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: false},
-      '$': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: true},
-      '5': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: false},
-      '%': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: true},
-      '6': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: false},
-      '^': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: true},
-      '7': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: false},
-      '&': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: true},
-      '8': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: false},
-      '*': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: true},
-      '9': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: false},
-      '(': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: true},
-      'a': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: false},
-      'A': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: true},
-      'b': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: false},
-      'B': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: true},
-      'c': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: false},
-      'C': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: true},
-      'd': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: false},
-      'D': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: true},
-      'e': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: false},
-      'E': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: true},
-      'f': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: false},
-      'F': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: true},
-      'g': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: false},
-      'G': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: true},
-      'h': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: false},
-      'H': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: true},
-      'i': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: false},
-      'I': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: true},
-      'j': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: false},
-      'J': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: true},
-      'k': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: false},
-      'K': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: true},
-      'l': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: false},
-      'L': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: true},
-      'm': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: false},
-      'M': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: true},
-      'n': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: false},
-      'N': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: true},
-      'o': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: false},
-      'O': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: true},
-      'p': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: false},
-      'P': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: true},
-      'q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: false},
-      'Q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: true},
-      'r': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: false},
-      'R': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: true},
-      's': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: false},
-      'S': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: true},
-      't': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: false},
-      'T': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: true},
-      'u': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: false},
-      'U': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: true},
-      'v': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: false},
-      'V': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: true},
-      'w': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: false},
-      'W': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: true},
-      'x': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: false},
-      'X': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: true},
-      'y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: false},
-      'Y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: true},
-      'z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: false},
-      'Z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: true},
-      'Fullscreen': {keyCode: 0x7A, shiftModifier: false},
-      'Shutdown': {keyCode: 0x98, shiftModifier: false},
-      'Back': {keyCode: 0xA6, shiftModifier: false},
-      'Forward': {keyCode: 0xA7, shiftModifier: false},
-      'Reload': {keyCode: 0xA8, shiftModifier: false},
-      'Search': {keyCode: 0xAA, shiftModifier: false},
-      'Mute': {keyCode: 0xAD, keyName: 'VolumeMute', shiftModifier: false},
-      'Volume-Down': {keyCode: 0xAE, keyName: 'VolumeDown',
-          shiftModifier: false},
-      'Volume-Up': {keyCode: 0xAF, keyName: 'VolumeUp', shiftModifier: false},
-      'Change-Window': {keyCode: 0xB6, shiftModifier: false},
-      ';': {keyCode: 0xBA, keyName: 'Semicolon', shiftModifier: false},
-      ':': {keyCode: 0xBA, keyName: 'Semicolon',shiftModifier: true},
-      '=': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: false},
-      '+': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: true},
-      ',': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: false},
-      '<': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: true},
-      '-': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: false},
-      '_': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: true},
-      '.': {keyCode: 0xBE, keyName: 'Period', shiftModifier: false},
-      '>': {keyCode: 0xBE, keyName: 'Period', shiftModifier: true},
-      '/': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: false},
-      '?': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: true},
-      '`': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: false},
-      '~': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: true},
-      'Brightness-Down': {keyCode: 0xD8, keyName: 'BrightnessDown',
-          shiftModifier: false},
-      'Brightness-Up': {keyCode: 0xD9, keyName: 'BrightnessUp',
-          shiftModifier: false},
-      '[': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: false},
-      '{': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: true},
-      '\\': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: false},
-      '|': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: true},
-      ']': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: false},
-      '}': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: true},
-      '\'': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: false},
-      '"': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: true},
-    };
-
-    Polymer('kb-key-codes', {
-      /**
-       * Retrieves the keyCode and status of the shift modifier.
-       * @param {string} id ID of an entry in the code table.
-       * @return {keyCode: numeric, shiftModifier: boolean}
-       */
-      GetKeyCodeAndModifiers: function(id) {
-        var entry = keyCodes[id];
-        if (entry) {
-          return {
-            keyCode: entry.keyCode,
-            keyName: entry.keyName || 'Unidentified',
-            shiftModifier: entry.shiftModifier
-          };
-        }
-        if (id.length != 1)
-          return;
-        // Special case of accented characters.
-        return {
-          keyCode: 0,
-          keyName: 'Unidentified',
-          shiftModifier: false
-        };
-      },
-
-     /**
-      * Creates a virtual key event for use with the keyboard extension API.
-      * See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent.
-      * @param {Object} detail Attribute of the key being pressed or released.
-      * @param {string} type The type of key event, which may be keydown
-      *     or keyup.
-      * @return {?KeyboardEvent} A KeyboardEvent object, or undefined on
-      *     failure.
-      */
-     createVirtualKeyEvent: function(detail, type) {
-       var char = detail.char;
-       var keyCode = detail.keyCode;
-       var keyName = detail.keyName;
-       // The shift modifier is handled specially. Some charactares like '+'
-       // {keyCode: 0xBB, shiftModifier: true}, are available on non-upper
-       // keysets, and so we rely on caching the correct shiftModifier. If
-       // the cached value of the shiftModifier is undefined, we defer to
-       // the shiftModifier in the detail.
-       var shiftModifier = detail.shiftModifier;
-       if (keyCode == undefined || keyName == undefined) {
-         var state = this.GetKeyCodeAndModifiers(char);
-         if (state) {
-           keyCode = keyCode || state.keyCode;
-           keyName = keyName || state.keyName;
-           shiftModifier = (state.shiftModifier == undefined) ?
-               shiftModifier : state.shiftModifier;
-         } else {
-           // Keycode not defined.
-           return;
-         }
-       }
-       var modifiers = Modifier.NONE;
-       modifiers = shiftModifier ? modifiers | Modifier.SHIFT : modifiers;
-       modifiers = detail.controlModifier ?
-           modifiers | Modifier.CONTROL : modifiers;
-       modifiers = detail.altModifier ? modifiers | Modifier.ALT : modifiers;
-       return {
-         type: type,
-         charValue: char.charCodeAt(0),
-         keyCode: keyCode,
-         keyName: keyName,
-         modifiers: modifiers
-       };
-     },
-    });
-  })();
-</script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-key-codes.js b/ui/keyboard/resources/elements/kb-key-codes.js
new file mode 100644
index 0000000..103fe44
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-key-codes.js
@@ -0,0 +1,227 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+
+  // Flag values for ctrl, alt and shift as defined by EventFlags
+  // in "event_constants.h".
+  // @enum {number}
+  var Modifier = {
+    NONE: 0,
+    ALT: 8,
+    CONTROL: 4,
+    SHIFT: 2
+  }
+
+  // Each virtual key event is assigned a unique ID.
+  var nextRequestID = 0;
+
+  // Keycodes have been deprecated in the KeyEvent specification, but are
+  // nonetheless required to support legacy web content.  The Keycodes in the
+  // following table are based on subset of US-EN 101-key keyboard. These
+  // codes are used in the absence of explicit keycodes for kb-key and
+  // kb-keysequence elements. Keyboard layout authors may explicitly set the
+  // keyCode attribute for kb-key or kb-keysequence elements to refer to
+  // indices in this table in order to emulate a physical keyboard with an
+  // alternate layout.  Not all keys on a virtual keyboard are required to
+  // have keyCodes. The shiftModifier specifies whether to always include or
+  // exclude the shift modifer when sending key events for this key. If it's
+  // undefined, it will defer to state of the keyboard.
+  // TODO(rsadam): Correctly propagate shutdown keycode. This is currently
+  // ignored due to chromoting (crbug/146609)
+  var keyCodes = {
+    '\b': {keyCode: 0x08, keyName: 'Backspace', shiftModifier: false},
+    '\t': {keyCode: 0x09, keyName: 'Tab', shiftModifier: false},
+    '\n': {keyCode: 0x0D, keyName: 'Enter', shiftModifier: false},
+    'Esc': {keyCode: 0x1B, keyName: 'Escape', shiftModifier: false},
+    ' ': {keyCode: 0x20, keyName: 'Space', shiftModifier: false},
+    'Arrow-Left': {keyCode: 0x25, keyName: 'ArrowLeft',
+        shiftModifier: undefined},
+    'Arrow-Up': {keyCode: 0x26, keyName: 'ArrowUp', shiftModifier: undefined},
+    'Arrow-Right': {keyCode: 0x27, keyName: 'ArrowRight',
+        shiftModifier: undefined},
+    'Arrow-Down': {keyCode: 0x28, keyName: 'ArrowDown',
+        shiftModifier: undefined},
+    '0': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: false},
+    ')': {keyCode: 0x30, keyName: 'Digit0', shiftModifier: true},
+    '1': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: false},
+    '!': {keyCode: 0x31, keyName: 'Digit1', shiftModifier: true},
+    '2': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: false},
+    '@': {keyCode: 0x32, keyName: 'Digit2', shiftModifier: true},
+    '3': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: false},
+    '#': {keyCode: 0x33, keyName: 'Digit3', shiftModifier: true},
+    '4': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: false},
+    '$': {keyCode: 0x34, keyName: 'Digit4', shiftModifier: true},
+    '5': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: false},
+    '%': {keyCode: 0x35, keyName: 'Digit5', shiftModifier: true},
+    '6': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: false},
+    '^': {keyCode: 0x36, keyName: 'Digit6', shiftModifier: true},
+    '7': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: false},
+    '&': {keyCode: 0x37, keyName: 'Digit7', shiftModifier: true},
+    '8': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: false},
+    '*': {keyCode: 0x38, keyName: 'Digit8', shiftModifier: true},
+    '9': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: false},
+    '(': {keyCode: 0x39, keyName: 'Digit9', shiftModifier: true},
+    'a': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: false},
+    'A': {keyCode: 0x41, keyName: 'KeyA', shiftModifier: true},
+    'b': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: false},
+    'B': {keyCode: 0x42, keyName: 'KeyB', shiftModifier: true},
+    'c': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: false},
+    'C': {keyCode: 0x43, keyName: 'KeyC', shiftModifier: true},
+    'd': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: false},
+    'D': {keyCode: 0x44, keyName: 'KeyD', shiftModifier: true},
+    'e': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: false},
+    'E': {keyCode: 0x45, keyName: 'KeyE', shiftModifier: true},
+    'f': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: false},
+    'F': {keyCode: 0x46, keyName: 'KeyF', shiftModifier: true},
+    'g': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: false},
+    'G': {keyCode: 0x47, keyName: 'KeyG', shiftModifier: true},
+    'h': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: false},
+    'H': {keyCode: 0x48, keyName: 'KeyH', shiftModifier: true},
+    'i': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: false},
+    'I': {keyCode: 0x49, keyName: 'KeyI', shiftModifier: true},
+    'j': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: false},
+    'J': {keyCode: 0x4A, keyName: 'KeyJ', shiftModifier: true},
+    'k': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: false},
+    'K': {keyCode: 0x4B, keyName: 'KeyK', shiftModifier: true},
+    'l': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: false},
+    'L': {keyCode: 0x4C, keyName: 'KeyL', shiftModifier: true},
+    'm': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: false},
+    'M': {keyCode: 0x4D, keyName: 'KeyM', shiftModifier: true},
+    'n': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: false},
+    'N': {keyCode: 0x4E, keyName: 'KeyN', shiftModifier: true},
+    'o': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: false},
+    'O': {keyCode: 0x4F, keyName: 'KeyO', shiftModifier: true},
+    'p': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: false},
+    'P': {keyCode: 0x50, keyName: 'KeyP', shiftModifier: true},
+    'q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: false},
+    'Q': {keyCode: 0x51, keyName: 'KeyQ', shiftModifier: true},
+    'r': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: false},
+    'R': {keyCode: 0x52, keyName: 'KeyR', shiftModifier: true},
+    's': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: false},
+    'S': {keyCode: 0x53, keyName: 'KeyS', shiftModifier: true},
+    't': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: false},
+    'T': {keyCode: 0x54, keyName: 'KeyT', shiftModifier: true},
+    'u': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: false},
+    'U': {keyCode: 0x55, keyName: 'KeyU', shiftModifier: true},
+    'v': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: false},
+    'V': {keyCode: 0x56, keyName: 'KeyV', shiftModifier: true},
+    'w': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: false},
+    'W': {keyCode: 0x57, keyName: 'KeyW', shiftModifier: true},
+    'x': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: false},
+    'X': {keyCode: 0x58, keyName: 'KeyX', shiftModifier: true},
+    'y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: false},
+    'Y': {keyCode: 0x59, keyName: 'KeyY', shiftModifier: true},
+    'z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: false},
+    'Z': {keyCode: 0x5A, keyName: 'KeyZ', shiftModifier: true},
+    'Fullscreen': {keyCode: 0x7A, shiftModifier: false},
+    'Shutdown': {keyCode: 0x98, shiftModifier: false},
+    'Back': {keyCode: 0xA6, shiftModifier: false},
+    'Forward': {keyCode: 0xA7, shiftModifier: false},
+    'Reload': {keyCode: 0xA8, shiftModifier: false},
+    'Search': {keyCode: 0xAA, shiftModifier: false},
+    'Mute': {keyCode: 0xAD, keyName: 'VolumeMute', shiftModifier: false},
+    'Volume-Down': {keyCode: 0xAE, keyName: 'VolumeDown',
+        shiftModifier: false},
+    'Volume-Up': {keyCode: 0xAF, keyName: 'VolumeUp', shiftModifier: false},
+    'Change-Window': {keyCode: 0xB6, shiftModifier: false},
+    ';': {keyCode: 0xBA, keyName: 'Semicolon', shiftModifier: false},
+    ':': {keyCode: 0xBA, keyName: 'Semicolon',shiftModifier: true},
+    '=': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: false},
+    '+': {keyCode: 0xBB, keyName: 'Equal', shiftModifier: true},
+    ',': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: false},
+    '<': {keyCode: 0xBC, keyName: 'Comma', shiftModifier: true},
+    '-': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: false},
+    '_': {keyCode: 0xBD, keyName: 'Minus', shiftModifier: true},
+    '.': {keyCode: 0xBE, keyName: 'Period', shiftModifier: false},
+    '>': {keyCode: 0xBE, keyName: 'Period', shiftModifier: true},
+    '/': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: false},
+    '?': {keyCode: 0xBF, keyName: 'Slash', shiftModifier: true},
+    '`': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: false},
+    '~': {keyCode: 0xC0, keyName: 'Backquote', shiftModifier: true},
+    'Brightness-Down': {keyCode: 0xD8, keyName: 'BrightnessDown',
+        shiftModifier: false},
+    'Brightness-Up': {keyCode: 0xD9, keyName: 'BrightnessUp',
+        shiftModifier: false},
+    '[': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: false},
+    '{': {keyCode: 0xDB, keyName: 'BracketLeft', shiftModifier: true},
+    '\\': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: false},
+    '|': {keyCode: 0xDC, keyName: 'Backslash', shiftModifier: true},
+    ']': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: false},
+    '}': {keyCode: 0xDD, keyName: 'BracketRight', shiftModifier: true},
+    '\'': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: false},
+    '"': {keyCode: 0xDE, keyName: 'Quote', shiftModifier: true},
+  };
+
+  Polymer('kb-key-codes', {
+    /**
+     * Retrieves the keyCode and status of the shift modifier.
+     * @param {string} id ID of an entry in the code table.
+     * @return {keyCode: numeric, shiftModifier: boolean}
+     */
+    GetKeyCodeAndModifiers: function(id) {
+      var entry = keyCodes[id];
+      if (entry) {
+        return {
+          keyCode: entry.keyCode,
+          keyName: entry.keyName || 'Unidentified',
+          shiftModifier: entry.shiftModifier
+        };
+      }
+      if (id.length != 1)
+        return;
+      // Special case of accented characters.
+      return {
+        keyCode: 0,
+        keyName: 'Unidentified',
+        shiftModifier: false
+      };
+    },
+
+   /**
+    * Creates a virtual key event for use with the keyboard extension API.
+    * See http://www.w3.org/TR/DOM-Level-3-Events/#events-KeyboardEvent.
+    * @param {Object} detail Attribute of the key being pressed or released.
+    * @param {string} type The type of key event, which may be keydown
+    *     or keyup.
+    * @return {?KeyboardEvent} A KeyboardEvent object, or undefined on
+    *     failure.
+    */
+   createVirtualKeyEvent: function(detail, type) {
+     var char = detail.char;
+     var keyCode = detail.keyCode;
+     var keyName = detail.keyName;
+     // The shift modifier is handled specially. Some charactares like '+'
+     // {keyCode: 0xBB, shiftModifier: true}, are available on non-upper
+     // keysets, and so we rely on caching the correct shiftModifier. If
+     // the cached value of the shiftModifier is undefined, we defer to
+     // the shiftModifier in the detail.
+     var shiftModifier = detail.shiftModifier;
+     if (keyCode == undefined || keyName == undefined) {
+       var state = this.GetKeyCodeAndModifiers(char);
+       if (state) {
+         keyCode = keyCode || state.keyCode;
+         keyName = keyName || state.keyName;
+         shiftModifier = (state.shiftModifier == undefined) ?
+             shiftModifier : state.shiftModifier;
+       } else {
+         // Keycode not defined.
+         return;
+       }
+     }
+     var modifiers = Modifier.NONE;
+     modifiers = shiftModifier ? modifiers | Modifier.SHIFT : modifiers;
+     modifiers = detail.controlModifier ?
+         modifiers | Modifier.CONTROL : modifiers;
+     modifiers = detail.altModifier ? modifiers | Modifier.ALT : modifiers;
+     return {
+       type: type,
+       charValue: char.charCodeAt(0),
+       keyCode: keyCode,
+       keyName: keyName,
+       modifiers: modifiers
+     };
+   },
+  });
+})();
diff --git a/ui/keyboard/resources/elements/kb-key-import.html b/ui/keyboard/resources/elements/kb-key-import.html
index 1174eb4..e703b25 100644
--- a/ui/keyboard/resources/elements/kb-key-import.html
+++ b/ui/keyboard/resources/elements/kb-key-import.html
@@ -12,23 +12,4 @@
       }
     </style>
   </template>
-  <script>
-    Polymer('kb-key-import', {
-      /**
-      * The id of the document fragment that will be imported.
-       */
-      importId: null,
-
-      /**
-       * Import content from a document fragment.
-       * @param {!DocumentFragment} content Document fragment that contains
-       *     the content to import.
-       */
-      importDoc: function(content) {
-        var id = this.getAttribute('importId');
-        var fragment = content.querySelector('#' + id);
-        return fragment && fragment.content ? fragment.content : fragment;
-      }
-    });
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-key-import.js b/ui/keyboard/resources/elements/kb-key-import.js
new file mode 100644
index 0000000..a06774c
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-key-import.js
@@ -0,0 +1,22 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer('kb-key-import', {
+  /**
+  * The id of the document fragment that will be imported.
+   */
+  importId: null,
+
+  /**
+   * Import content from a document fragment.
+   * @param {!DocumentFragment} content Document fragment that contains
+   *     the content to import.
+   */
+  importDoc: function(content) {
+    var id = this.getAttribute('importId');
+    var fragment = content.querySelector('#' + id);
+    return fragment && fragment.content ? fragment.content : fragment;
+  }
+});
+
diff --git a/ui/keyboard/resources/elements/kb-key-sequence.html b/ui/keyboard/resources/elements/kb-key-sequence.html
index b0bbc23..212e427 100644
--- a/ui/keyboard/resources/elements/kb-key-sequence.html
+++ b/ui/keyboard/resources/elements/kb-key-sequence.html
@@ -4,8 +4,8 @@
   -- found in the LICENSE file.
   -->
 
-<polymer-element name="kb-key-sequence"
-    attributes="keys hintTexts keyCodes invert">
+<polymer-element name="kb-key-sequence" attributes="keys hintTexts keyCodes
+    invert">
   <template>
     <style>
       :host {
@@ -13,61 +13,4 @@
       }
     </style>
   </template>
-  <script>
-    (function() {
-
-      var metadata = null;
-
-      function getKeyCodeAndModifiers(keyCodeIndex) {
-        if (!metadata)
-          metadata = document.createElement('kb-key-codes'); 
-        return metadata.GetKeyCodeAndModifiers(keyCodeIndex);
-      }
-
-      Polymer('kb-key-sequence', {
-        /**
-         * Generates the DOM structure to replace (expand) this kb-key-sequence.
-         */
-        generateDom: function() {
-          var replacement = document.createDocumentFragment();
-          var newKeys = this.getAttribute('keys');
-          var newHintTexts = this.getAttribute('hintTexts');
-          var keyCodes = this.getAttribute('hintCodes') || newKeys;
-          var invert = this.getAttribute('invert');
-          if (newKeys) {
-            if (newHintTexts && newKeys.length != newHintTexts.length) {
-              console.error('keys and hintTexts do not match');
-              return;
-            }
-            if (keyCodes && newKeys.length != keyCodes.length) {
-               console.error('keys and keyCodes do not match');
-              return;
-            }
-
-            for (var i = 0; i < newKeys.length; i++) {
-              var key = document.createElement('kb-key');
-              key.innerText = newKeys[i];
-              key.accents = newKeys[i];
-              if (newHintTexts)
-                key.hintText = newHintTexts[i];
-              var keyCodeIndex = keyCodes[i];
-              if (invert) {
-                key.invert = true;
-                key.char = newKeys[i];
-                keyCodeIndex = key.hintText;
-              }
-              var state = getKeyCodeAndModifiers(keyCodeIndex);
-              if (state) {
-                key.keyCode = state.keyCode;
-                key.keyName = state.keyName;
-                key.shiftModifier = state.shiftModifier;
-              }
-              replacement.appendChild(key);
-            }
-          }
-          return replacement;
-        }
-      });
-    })();
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-key-sequence.js b/ui/keyboard/resources/elements/kb-key-sequence.js
new file mode 100644
index 0000000..7bd4d49
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-key-sequence.js
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function() {
+
+  var metadata = null;
+
+  function getKeyCodeAndModifiers(keyCodeIndex) {
+    if (!metadata)
+      metadata = document.createElement('kb-key-codes');
+    return metadata.GetKeyCodeAndModifiers(keyCodeIndex);
+  }
+
+  Polymer('kb-key-sequence', {
+    /**
+     * Generates the DOM structure to replace (expand) this kb-key-sequence.
+     */
+    generateDom: function() {
+      var replacement = document.createDocumentFragment();
+      var newKeys = this.getAttribute('keys');
+      var newHintTexts = this.getAttribute('hintTexts');
+      var keyCodes = this.getAttribute('hintCodes') || newKeys;
+      var invert = this.getAttribute('invert');
+      if (newKeys) {
+        if (newHintTexts && newKeys.length != newHintTexts.length) {
+          console.error('keys and hintTexts do not match');
+          return;
+        }
+        if (keyCodes && newKeys.length != keyCodes.length) {
+           console.error('keys and keyCodes do not match');
+          return;
+        }
+
+        for (var i = 0; i < newKeys.length; i++) {
+          var key = document.createElement('kb-key');
+          key.innerText = newKeys[i];
+          key.accents = newKeys[i];
+          if (newHintTexts)
+            key.hintText = newHintTexts[i];
+          var keyCodeIndex = keyCodes[i];
+          if (invert) {
+            key.invert = true;
+            key.char = newKeys[i];
+            keyCodeIndex = key.hintText;
+          }
+          var state = getKeyCodeAndModifiers(keyCodeIndex);
+          if (state) {
+            key.keyCode = state.keyCode;
+            key.keyName = state.keyName;
+            key.shiftModifier = state.shiftModifier;
+          }
+          replacement.appendChild(key);
+        }
+      }
+      return replacement;
+    }
+  });
+})();
+
diff --git a/ui/keyboard/resources/elements/kb-key.html b/ui/keyboard/resources/elements/kb-key.html
index 9992aaf..e430edc 100644
--- a/ui/keyboard/resources/elements/kb-key.html
+++ b/ui/keyboard/resources/elements/kb-key.html
@@ -4,8 +4,8 @@
   -- found in the LICENSE file.
   -->
 
-<polymer-element name="kb-key" extends="kb-key-base"
-    attributes="image keyCode keyName shiftModifier sound stretch weight">
+<polymer-element name="kb-key" extends="kb-key-base" attributes="image keyCode
+    keyName shiftModifier sound stretch weight">
   <template>
     <style>
       :host {
@@ -99,217 +99,19 @@
         border-bottom-color: #4a4a4a;
         border-top-color: #878787;
       }
-
-      /** TODO(rsadam@): Move to kb-row once /shadow/ is supported. */
-      :ancestor(kb-row:nth-child(2)):host(:not(.dark):not(.active)) {
-        -webkit-box-shadow: inset 0px 1px #666666, inset 0px -1px #4c4c4c;
-        background-image: -webkit-linear-gradient(#5a5a5a, #515151);
-        background-size: cover;
-        border-bottom-color: #414141;
-        border-top-color: #7f7f7f;
-      }
-
-      :ancestor(kb-row:nth-child(3)):host(:not(.dark):not(.active)) {
-        -webkit-box-shadow: inset 0px 1px #5d5d5d, inset 0px -1px #444444;
-        background-image: -webkit-linear-gradient(#505050, #494949);
-        background-size: cover;
-        border-bottom-color: #3a3a3a;
-        border-top-color: #787878;
-      }
-
-      :ancestor(kb-row:nth-child(n+3)):host(:not(.dark):not(.active)) {
-        -webkit-box-shadow: inset 0px 1px #565656, inset 0px -1px #434343;
-        background-image: -webkit-linear-gradient(#484848, #474747);
-        background-size: cover;
-        border-bottom-color: #393939;
-        border-top-color: #717171;
-      }
-
-      :ancestor(kb-row:nth-child(2)):host(:not([invert])) .hint {
-        color: #2C2C2C;
-      }
-
-      :ancestor(kb-row:nth-child(3)):host(:not([invert])) .hint {
-        color: #272727;
-      }
-
-      :ancestor(kb-row:nth-child(n+3)):host(:not([invert])) .hint {
-        color: #232323;
-      }
-
-      /**
-       * The microphone key is handled separately from other images since the
-       * image displayed changes depending on whether it's pressed or not.
-       */
-      :ancestor(.microphone) .key {
-        background-image: url('../images/microphone.svg');
-        background-position: 10%;
-      }
-
-      :ancestor(.audio .microphone) .key {
-        background-image: url('../images/microphone-green.svg');
-      }
-
-      /* TODO(rsadam@): Use different assets for caps-lock and highlight. */
-      :ancestor(.caps-locked):host(kb-shift-key.dark) .key,
-      /**
-       * Controls whether the shift key should be highlighted.
-       * Only highlights if we are in the upper keyset, but not
-       * capslocked.
-       */
-      :ancestor(kb-keyboard:not(.caps-locked)[keyset=upper]):host(
-          kb-shift-key) .key {
-        background-image: url('../images/shift-filled.svg');
-      }
-
-      :ancestor(kb-keyboard:not(.caps-locked)[keyset=lower]):host(
-          kb-shift-key) .key {
-        background-image: url('../images/shift.svg');
-      }
-
-      :ancestor(kb-keyboard.ctrl-active):host(
-          kb-modifier-key[char=Ctrl]),
-      :ancestor(kb-keyboard.alt-active):host(
-          kb-modifier-key[char=Alt]) {
-        color: lightblue;
-      }
     </style>
     <div id="key" class="key">
       <content></content>
     </div>
     <div class="hint" part="hint">{{hintText}}</div>
   </template>
-  <script>
-    Polymer('kb-key', {
-      /**
-       * The background image to display on this key. Does not display an
-       * image if this is the empty string.
-       * @type {string}
-       */
-      image: "",
-
-      /**
-       * The background image size to use if an image is specified. The size
-       * is provided as a string, for example, "50%".
-       * @type {string}
-       */
-      imageSize: "",
-
-      /**
-       * Key codes have been deprecated in DOM3 key events, but are required
-       * for legacy web content. The key codes depend on the position of the
-       * key on the keyboard and is independent of which modifier keys (shift,
-       *  alt, ...) are active.
-       * @type {number|undefined}
-       */
-      keyCode: undefined,
-
-      /**
-       * Name of the key as defined in the DOM3 specification for key events.
-       * Like the keyCode, the keyName is independent of the state of the
-       * modifier keys.
-       * @type {string|undefined}
-       */
-      keyName: undefined,
-
-      /**
-       * Whether the shift key is pressed when producing the key value.
-       * @type {boolean}
-       */
-      shiftModifier: false,
-
-      /**
-       * The sound to play when this key is pressed.
-       * @type {Sound}
-       */
-      sound: Sound.DEFAULT,
-
-      /**
-       * Whether the key can be stretched to accomodate pixel rounding errors.
-       */
-      stretch: false,
-
-      /**
-       * Weighting to use for layout in order to properly size the key.
-       * Keys with a high weighting are wider than normal keys.
-       * @type {number}
-       */
-      weight: DEFAULT_KEY_WEIGHT,
-
-      /**
-       * Called when the image attribute changes. This is used to set the
-       * background image of the key.
-       * TODO(rsadam): Remove when polymer {{}} syntax regression is fixed.
-       */
-      imageChanged: function() {
-        if (!this.image) {
-          this.$.key.style.backgroundImage = "none";
-        } else {
-          this.$.key.style.backgroundImage =
-              "url(images/" + this.image + ".svg)";
-        }
-      },
-
-      /**
-       * Returns a subset of the key attributes.
-       * @param {string} caller The id of the function that called
-       *     populateDetails.
-       * @return {Object} Mapping of attributes for the key element.
-       */
-      populateDetails: function(caller) {
-        var details = this.super([caller]);
-        details.keyCode = this.keyCode;
-        details.keyName = this.keyName;
-        details.shiftModifier = this.shiftModifier;
-        details.sound = this.sound;
-        return details;
-      },
-    });
-  </script>
 </polymer-element>
 
 <!-- Special keys -->
 <polymer-element name="kb-abc-key" class="symbol dark" char="Invalid"
     extends="kb-key" weight="125">
-  <script>
-    Polymer('kb-abc-key', {
-      populateDetails: function(caller) {
-        var detail = this.super([caller]);
-        switch (caller) {
-          case ('down'):
-            detail.relegateToShift = true;
-            break;
-          default:
-            break;
-        }
-        return detail;
-      }
-    });
-  </script>
 </polymer-element>
 
 <polymer-element name="kb-hide-keyboard-key" class="hide-keyboard dark"
     align="center" attributes="showMenu" char="Invalid" extends="kb-key">
-  <script>
-    Polymer('kb-hide-keyboard-key', {
-      /**
-       * Whether to show the options menu on key-up.
-       * @type {boolean}
-       */
-      showMenu: true,
-
-      up: function(event) {
-        if (!this.showMenu) {
-          hideKeyboard();
-          return;
-        }
-        var details = {
-          left: this.offsetLeft,
-          top: this.offsetTop,
-          width: this.clientWidth,
-        };
-        this.fire('show-options', details);
-      },
-    });
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-key.js b/ui/keyboard/resources/elements/kb-key.js
new file mode 100644
index 0000000..c58b190
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-key.js
@@ -0,0 +1,111 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer('kb-key', {
+  /**
+   * The background image to display on this key. Does not display an
+   * image if this is the empty string.
+   * @type {string}
+   */
+  image: "",
+
+  /**
+   * The background image size to use if an image is specified. The size
+   * is provided as a string, for example, "50%".
+   * @type {string}
+   */
+  imageSize: "",
+
+  /**
+   * Key codes have been deprecated in DOM3 key events, but are required
+   * for legacy web content. The key codes depend on the position of the
+   * key on the keyboard and is independent of which modifier keys (shift,
+   *  alt, ...) are active.
+   * @type {number|undefined}
+   */
+  keyCode: undefined,
+
+  /**
+   * Name of the key as defined in the DOM3 specification for key events.
+   * Like the keyCode, the keyName is independent of the state of the
+   * modifier keys.
+   * @type {string|undefined}
+   */
+  keyName: undefined,
+
+  /**
+   * Whether the shift key is pressed when producing the key value.
+   * @type {boolean}
+   */
+  shiftModifier: false,
+
+  /**
+   * The sound to play when this key is pressed.
+   * @type {Sound}
+   */
+  sound: Sound.DEFAULT,
+
+  /**
+   * Whether the key can be stretched to accomodate pixel rounding errors.
+   */
+  stretch: false,
+
+  /**
+   * Weighting to use for layout in order to properly size the key.
+   * Keys with a high weighting are wider than normal keys.
+   * @type {number}
+   */
+  weight: DEFAULT_KEY_WEIGHT,
+
+  /**
+   * Called when the image attribute changes. This is used to set the
+   * background image of the key.
+   * TODO(rsadam): Remove when polymer {{}} syntax regression is fixed.
+   */
+  imageChanged: function() {
+    if (!this.image) {
+      this.$.key.style.backgroundImage = "none";
+    } else {
+      this.$.key.style.backgroundImage =
+          "url(images/" + this.image + ".svg)";
+    }
+  },
+
+  /**
+   * Returns a subset of the key attributes.
+   * @param {string} caller The id of the function that called
+   *     populateDetails.
+   * @return {Object} Mapping of attributes for the key element.
+   */
+  populateDetails: function(caller) {
+    var details = this.super([caller]);
+    details.keyCode = this.keyCode;
+    details.keyName = this.keyName;
+    details.shiftModifier = this.shiftModifier;
+    details.sound = this.sound;
+    return details;
+  },
+});
+;
+
+Polymer('kb-abc-key', {
+  populateDetails: function(caller) {
+    var detail = this.super([caller]);
+    switch (caller) {
+      case ('down'):
+        detail.relegateToShift = true;
+        break;
+      default:
+        break;
+    }
+    return detail;
+  }
+});
+;
+
+Polymer('kb-hide-keyboard-key', {
+  up: function(event) {
+    hideKeyboard();
+  },
+});
diff --git a/ui/keyboard/resources/elements/kb-keyboard.html b/ui/keyboard/resources/elements/kb-keyboard.html
index c27197d..761e3c4 100644
--- a/ui/keyboard/resources/elements/kb-keyboard.html
+++ b/ui/keyboard/resources/elements/kb-keyboard.html
@@ -9,8 +9,7 @@
     on-key-longpress="{{keyLongpress}}" on-pointerup="{{up}}"
     on-pointerdown="{{down}}" on-pointerout="{{out}}"
     on-enable-sel="{{enableSel}}" on-enable-dbl="{{enableDbl}}"
-    on-key-out="{{keyOut}}" on-show-options="{{showOptions}}"
-    on-set-layout="{{setLayout}}" on-type-key="{{type}}"
+    on-key-out="{{keyOut}}" on-set-layout="{{setLayout}}" on-type-key="{{type}}"
     attributes="inputType inputTypeToLayoutMap keyset layout volume">
   <template>
     <style>
@@ -36,1033 +35,6 @@
       -- keyboard layouts.
       -->
     <content id="content"></content>
-    <kb-keyboard-overlay id="overlay" hidden></kb-keyboard-overlay>
     <kb-key-codes id="keyCodeMetadata"></kb-key-codes>
-
   </template>
-  <script>
-    /**
-     * The repeat delay in milliseconds before a key starts repeating. Use the
-     * same rate as Chromebook.
-     * (See chrome/browser/chromeos/language_preferences.cc)
-     * @const
-     * @type {number}
-     */
-    var REPEAT_DELAY_MSEC = 500;
-
-    /**
-     * The repeat interval or number of milliseconds between subsequent
-     * keypresses. Use the same rate as Chromebook.
-     * @const
-     * @type {number}
-     */
-    var REPEAT_INTERVAL_MSEC = 50;
-
-    /**
-     * The double click/tap interval.
-     * @const
-     * @type {number}
-     */
-    var DBL_INTERVAL_MSEC = 300;
-
-    /**
-     * The index of the name of the keyset when searching for all keysets.
-     * @const
-     * @type {number}
-     */
-    var REGEX_KEYSET_INDEX = 1;
-
-    /**
-     * The integer number of matches when searching for keysets.
-     * @const
-     * @type {number}
-     */
-    var REGEX_MATCH_COUNT = 2;
-
-    /**
-     * The boolean to decide if keyboard should transit to upper case keyset
-     * when spacebar is pressed. If a closing punctuation is followed by a
-     * spacebar, keyboard should automatically transit to upper case.
-     * @type {boolean}
-     */
-    var enterUpperOnSpace = false;
-
-    /**
-     * A structure to track the currently repeating key on the keyboard.
-     */
-    var repeatKey = {
-
-      /**
-        * The timer for the delay before repeating behaviour begins.
-        * @type {number|undefined}
-        */
-      timer: undefined,
-
-      /**
-       * The interval timer for issuing keypresses of a repeating key.
-       * @type {number|undefined}
-       */
-      interval: undefined,
-
-      /**
-       * The key which is currently repeating.
-       * @type {BaseKey|undefined}
-       */
-      key: undefined,
-
-      /**
-       * Cancel the repeat timers of the currently active key.
-       */
-      cancel: function() {
-        clearTimeout(this.timer);
-        clearInterval(this.interval);
-        this.timer = undefined;
-        this.interval = undefined;
-        this.key = undefined;
-      }
-    };
-
-    /**
-     * The minimum movement interval needed to trigger cursor move on
-     * horizontal and vertical way.
-     * @const
-     * @type {number}
-     */
-    var MIN_SWIPE_DIST_X = 50;
-    var MIN_SWIPE_DIST_Y = 20;
-
-    /**
-     * The maximum swipe distance that will trigger hintText of a key
-     * to be typed.
-     * @const
-     * @type {number}
-     */
-    var MAX_SWIPE_FLICK_DIST = 60;
-
-    /**
-     * The boolean to decide if it is swipe in process or finished.
-     * @type {boolean}
-     */
-    var swipeInProgress = false;
-
-    // Flag values for ctrl, alt and shift as defined by EventFlags
-    // in "event_constants.h".
-    // @enum {number}
-    var Modifier = {
-      NONE: 0,
-      ALT: 8,
-      CONTROL: 4,
-      SHIFT: 2
-    };
-
-    /**
-     * A structure to track the current swipe status.
-     */
-    var swipeTracker = {
-      /**
-       * The latest PointerMove event in the swipe.
-       * @type {Object}
-       */
-      currentEvent: undefined,
-
-      /**
-       * Whether or not a swipe changes direction.
-       * @type {false}
-       */
-      isComplex: false,
-
-      /**
-       * The count of horizontal and vertical movement.
-       * @type {number}
-       */
-      offset_x : 0,
-      offset_y : 0,
-
-      /**
-       * Last touch coordinate.
-       * @type {number}
-       */
-      pre_x : 0,
-      pre_y : 0,
-
-      /**
-       * The PointerMove event which triggered the swipe.
-       * @type {Object}
-       */
-      startEvent: undefined,
-
-      /**
-       * The flag of current modifier key.
-       * @type {number}
-       */
-      swipeFlags : 0,
-
-      /**
-       * Current swipe direction.
-       * @type {number}
-       */
-      swipeDirection : 0,
-
-      /**
-       * The number of times we've swiped within a single swipe.
-       * @type {number}
-       */
-      swipeIndex: 0,
-
-      /**
-       * Returns the combined direction of the x and y offsets.
-       * @return {number} The latest direction.
-       */
-      getOffsetDirection: function() {
-        // TODO (rsadam): Use angles to figure out the direction.
-        var direction = 0;
-        // Checks for horizontal swipe.
-        if (Math.abs(this.offset_x) > MIN_SWIPE_DIST_X) {
-          if (this.offset_x > 0) {
-            direction |= SwipeDirection.RIGHT;
-          } else {
-            direction |= SwipeDirection.LEFT;
-          }
-        }
-        // Checks for vertical swipe.
-        if (Math.abs(this.offset_y) > MIN_SWIPE_DIST_Y) {
-          if (this.offset_y < 0) {
-            direction |= SwipeDirection.UP;
-          } else {
-            direction |= SwipeDirection.DOWN;
-          }
-        }
-        return direction;
-      },
-
-      /**
-       * Populates the swipe update details.
-       * @param {boolean} endSwipe Whether this is the final event for this
-       *     swipe.
-       * @return {Object} The current state of the swipeTracker.
-       */
-      populateDetails: function(endSwipe) {
-        var detail = {};
-        detail.direction = this.swipeDirection;
-        detail.index = this.swipeIndex;
-        detail.status = this.swipeStatus;
-        detail.endSwipe = endSwipe;
-        detail.startEvent = this.startEvent;
-        detail.currentEvent = this.currentEvent;
-        detail.isComplex = this.isComplex;
-        return detail;
-      },
-
-      /**
-       * Reset all the values when swipe finished.
-       */
-      resetAll: function() {
-        this.offset_x = 0;
-        this.offset_y = 0;
-        this.pre_x = 0;
-        this.pre_y = 0;
-        this.swipeFlags = 0;
-        this.swipeDirection = 0;
-        this.swipeIndex = 0;
-        this.startEvent = undefined;
-        this.currentEvent = undefined;
-        this.isComplex = false;
-      },
-
-      /**
-       * Updates the swipe path with the current event.
-       * @param {Object} event The PointerEvent that triggered this update.
-       * @return {boolean} Whether or not to notify swipe observers.
-       */
-      update: function(event) {
-        if(!event.isPrimary)
-          return false;
-        // Update priors.
-        this.offset_x += event.screenX - this.pre_x;
-        this.offset_y += event.screenY - this.pre_y;
-        this.pre_x = event.screenX;
-        this.pre_y = event.screenY;
-
-        // Check if movement crosses minimum thresholds in each direction.
-        var direction = this.getOffsetDirection();
-        if (direction == 0)
-          return false;
-        // If swipeIndex is zero the current event is triggering the swipe.
-        if (this.swipeIndex == 0) {
-          this.startEvent = event;
-        } else if (direction != this.swipeDirection) {
-          // Toggle the isComplex flag.
-          this.isComplex = true;
-        }
-        // Update the swipe tracker.
-        this.swipeDirection = direction;
-        this.offset_x = 0;
-        this.offset_y = 0;
-        this.currentEvent = event;
-        this.swipeIndex++;
-        return true;
-      },
-
-    };
-
-    Polymer('kb-keyboard', {
-      alt: null,
-      config: null,
-      control: null,
-      dblDetail_: null,
-      dblTimer_: null,
-      inputType: null,
-      lastPressedKey: null,
-      shift: null,
-      sounds: {},
-      stale: true,
-      swipeHandler: null,
-      voiceInput_: null,
-      //TODO(rsadam@): Add a control to let users change this.
-      volume: DEFAULT_VOLUME,
-
-      /**
-       * The default input type to keyboard layout map. The key must be one of
-       * the input box type values.
-       * @type {object}
-       */
-      inputTypeToLayoutMap: {
-        number: "numeric",
-        text: "qwerty",
-        password: "qwerty"
-      },
-
-      /**
-       * Caches the specified sound on the keyboard.
-       * @param {string} soundId The name of the .wav file in the "sounds"
-           directory.
-       */
-      addSound: function(soundId) {
-        // Check if already loaded.
-        if (soundId == Sound.NONE || this.sounds[soundId])
-          return;
-        var pool = [];
-        for (var i = 0; i < SOUND_POOL_SIZE; i++) {
-          var audio = document.createElement('audio');
-          audio.preload = "auto";
-          audio.id = soundId;
-          audio.src = "../sounds/" + soundId + ".wav";
-          audio.volume = this.volume;
-          pool.push(audio);
-        }
-        this.sounds[soundId] = pool;
-      },
-
-      /**
-       * Changes the current keyset.
-       * @param {Object} detail The detail of the event that called this
-       *     function.
-       */
-      changeKeyset: function(detail) {
-        if (detail.relegateToShift && this.shift) {
-          this.keyset = this.shift.textKeyset;
-          this.activeKeyset.nextKeyset = undefined;
-          return true;
-        }
-        var toKeyset = detail.toKeyset;
-        if (toKeyset) {
-          this.keyset = toKeyset;
-          this.activeKeyset.nextKeyset = detail.nextKeyset;
-          return true;
-        }
-        return false;
-      },
-
-      keysetChanged: function() {
-        var keyset = this.activeKeyset;
-        // Show the keyset if it has been initialized.
-        if (keyset)
-          keyset.show();
-      },
-
-      configChanged: function() {
-        this.layout = this.config.layout;
-      },
-
-      ready: function() {
-        this.voiceInput_ = new VoiceInput(this);
-        this.swipeHandler = this.move.bind(this);
-        var self = this;
-        getKeyboardConfig(function(config) {
-          self.config = config;
-        });
-      },
-
-      /**
-       * Registers a callback for state change events.
-       * @param{!Function} callback Callback function to register.
-       */
-      addKeysetChangedObserver: function(callback) {
-        this.addEventListener('stateChange', callback);
-      },
-
-      /**
-       * Called when the type of focused input box changes. If a keyboard layout
-       * is defined for the current input type, that layout will be loaded.
-       * Otherwise, the keyboard layout for 'text' type will be loaded.
-       */
-      inputTypeChanged: function() {
-        // Disable layout switching at accessbility mode.
-        if (this.config && this.config.a11ymode)
-          return;
-
-        // TODO(bshe): Toggle visibility of some keys in a keyboard layout
-        // according to the input type.
-        var layout = this.inputTypeToLayoutMap[this.inputType];
-        if (!layout)
-          layout = this.inputTypeToLayoutMap.text;
-        this.layout = layout;
-      },
-
-      /**
-       * When double click/tap event is enabled, the second key-down and key-up
-       * events on the same key should be skipped. Return true when the event
-       * with |detail| should be skipped.
-       * @param {Object} detail The detail of key-up or key-down event.
-       */
-      skipEvent: function(detail) {
-        if (this.dblDetail_) {
-          if (this.dblDetail_.char != detail.char) {
-            // The second key down is not on the same key. Double click/tap
-            // should be ignored.
-            this.dblDetail_ = null;
-            clearTimeout(this.dblTimer_);
-          } else if (this.dblDetail_.clickCount == 1) {
-            return true;
-          }
-        }
-        return false;
-      },
-
-      /**
-       * Handles a swipe update.
-       * param {Object} detail The swipe update details.
-       */
-      onSwipeUpdate: function(detail) {
-        var direction = detail.direction;
-        if (!direction)
-          console.error("Swipe direction cannot be: " + direction);
-        // Triggers swipe editting if it's a purely horizontal swipe.
-        if (!(direction & (SwipeDirection.UP | SwipeDirection.DOWN))) {
-          // Nothing to do if the swipe has ended.
-          if (detail.endSwipe)
-            return;
-          var modifiers = 0;
-          // TODO (rsadam): This doesn't take into account index shifts caused
-          // by vertical swipes.
-          if (detail.index % 2 != 0) {
-            modifiers |= Modifier.SHIFT;
-            modifiers |= Modifier.CONTROL;
-          }
-          MoveCursor(direction, modifiers);
-          return;
-        }
-        // Triggers swipe hintText if it's a purely vertical swipe.
-        if (!(direction & (SwipeDirection.LEFT | SwipeDirection.RIGHT))) {
-          // Check if event is relevant to us.
-          if ((!detail.endSwipe) || (detail.isComplex))
-            return;
-          // Too long a swipe.
-          var distance = Math.abs(detail.startEvent.screenY -
-              detail.currentEvent.screenY);
-          if (distance > MAX_SWIPE_FLICK_DIST)
-            return;
-          var triggerKey = detail.startEvent.target;
-          if (triggerKey && triggerKey.onFlick)
-            triggerKey.onFlick(detail);
-        }
-      },
-
-      /**
-       * This function is bound to swipeHandler. Updates the current swipe
-       * status so that PointerEvents can be converted to Swipe events.
-       * @param {PointerEvent} event.
-       */
-      move: function(event) {
-        if (!swipeTracker.update(event))
-          return;
-        // Conversion was successful, swipe is now in progress.
-        swipeInProgress = true;
-        if (this.lastPressedKey) {
-          this.lastPressedKey.classList.remove('active');
-          this.lastPressedKey = null;
-        }
-        this.onSwipeUpdate(swipeTracker.populateDetails(false));
-      },
-
-      /**
-       * Handles key-down event that is sent by kb-key-base.
-       * @param {CustomEvent} event The key-down event dispatched by
-       *     kb-key-base.
-       * @param {Object} detail The detail of pressed kb-key.
-       */
-      keyDown: function(event, detail) {
-        if (this.skipEvent(detail))
-          return;
-
-        if (this.lastPressedKey) {
-          this.lastPressedKey.classList.remove('active');
-          this.lastPressedKey.autoRelease();
-        }
-        this.lastPressedKey = event.target;
-        this.lastPressedKey.classList.add('active');
-        repeatKey.cancel();
-        this.playSound(detail.sound);
-
-        var char = detail.char;
-        switch(char) {
-          case 'Shift':
-            this.classList.remove('caps-locked');
-            break;
-          case 'Alt':
-          case 'Ctrl':
-            var modifier = char.toLowerCase() + "-active";
-            // Removes modifier if already active.
-            if (this.classList.contains(modifier))
-              this.classList.remove(modifier);
-            break;
-          case 'Invalid':
-            // Not all Invalid keys are transition keys. Reset control keys if
-            // we pressed a transition key.
-            if (event.target.toKeyset || detail.relegateToShift)
-              this.onNonControlKeyTyped();
-            break;
-          default:
-            // Notify shift key.
-            if (this.shift)
-              this.shift.onNonControlKeyDown();
-            if (this.ctrl)
-              this.ctrl.onNonControlKeyDown();
-            if (this.alt)
-              this.alt.onNonControlKeyDown();
-            break;
-        }
-        if(this.changeKeyset(detail))
-          return;
-        if (detail.repeat) {
-          this.keyTyped(detail);
-          this.onNonControlKeyTyped();
-          repeatKey.key = this.lastPressedKey;
-          var self = this;
-          repeatKey.timer = setTimeout(function() {
-            repeatKey.timer = undefined;
-            repeatKey.interval = setInterval(function() {
-               self.playSound(detail.sound);
-               self.keyTyped(detail);
-            }, REPEAT_INTERVAL_MSEC);
-          }, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC));
-        }
-      },
-
-      /**
-       * Handles key-out event that is sent by kb-shift-key.
-       * @param {CustomEvent} event The key-out event dispatched by
-       *     kb-shift-key.
-       * @param {Object} detail The detail of pressed kb-shift-key.
-       */
-      keyOut: function(event, detail) {
-        this.changeKeyset(detail);
-      },
-
-      /**
-       * Enable/start double click/tap event recognition.
-       * @param {CustomEvent} event The enable-dbl event dispatched by
-       *     kb-shift-key.
-       * @param {Object} detail The detail of pressed kb-shift-key.
-       */
-      enableDbl: function(event, detail) {
-        if (!this.dblDetail_) {
-          this.dblDetail_ = detail;
-          this.dblDetail_.clickCount = 0;
-          var self = this;
-          this.dblTimer_ = setTimeout(function() {
-            self.dblDetail_.callback = null;
-            self.dblDetail_ = null;
-          }, DBL_INTERVAL_MSEC);
-        }
-      },
-
-      /**
-       * Enable the selection while swipe.
-       * @param {CustomEvent} event The enable-dbl event dispatched by
-       *    kb-shift-key.
-       */
-      enableSel: function(event) {
-        // TODO(rsadam): Disabled for now. May come back if we revert swipe
-        // selection to not do word selection.
-      },
-
-      /**
-       * Handles pointerdown event. This is used for swipe selection process.
-       * to get the start pre_x and pre_y. And also add a pointermove handler
-       * to start handling the swipe selection event.
-       * @param {PointerEvent} event The pointerup event that received by
-       *     kb-keyboard.
-       */
-      down: function(event) {
-        var layout = getKeysetLayout(this.activeKeysetId);
-        var key = layout.findClosestKey(event.clientX, event.clientY);
-        if (key)
-          key.down(event);
-        if (event.isPrimary) {
-          swipeTracker.pre_x = event.screenX;
-          swipeTracker.pre_y = event.screenY;
-          this.addEventListener("pointermove", this.swipeHandler, false);
-        }
-      },
-
-      /**
-       * Handles pointerup event. This is used for double tap/click events.
-       * @param {PointerEvent} event The pointerup event that bubbled to
-       *     kb-keyboard.
-       */
-      up: function(event) {
-        var layout = getKeysetLayout(this.activeKeysetId);
-        var key = layout.findClosestKey(event.clientX, event.clientY);
-        if (key)
-          key.up(event);
-        // When touch typing, it is very possible that finger moves slightly out
-        // of the key area before releases. The key should not be dropped in
-        // this case.
-        // TODO(rsadam@) Change behaviour such that the key drops and the second
-        // key gets pressed.
-        if (this.lastPressedKey &&
-            this.lastPressedKey.pointerId == event.pointerId) {
-          this.lastPressedKey.autoRelease();
-        }
-
-        if (this.dblDetail_) {
-          this.dblDetail_.clickCount++;
-          if (this.dblDetail_.clickCount == 2) {
-            this.dblDetail_.callback();
-            this.changeKeyset(this.dblDetail_);
-            clearTimeout(this.dblTimer_);
-
-            this.classList.add('caps-locked');
-
-            this.dblDetail_ = null;
-          }
-        }
-
-        // TODO(zyaozhujun): There are some edge cases to deal with later.
-        // (for instance, what if a second finger trigger a down and up
-        // event sequence while swiping).
-        // When pointer up from the screen, a swipe selection session finished,
-        // all the data should be reset to prepare for the next session.
-        if (event.isPrimary && swipeInProgress) {
-          swipeInProgress = false;
-          this.onSwipeUpdate(swipeTracker.populateDetails(true))
-          swipeTracker.resetAll();
-        }
-        this.removeEventListener('pointermove', this.swipeHandler, false);
-      },
-
-      /**
-       * Handles PointerOut event. This is used for when a swipe gesture goes
-       * outside of the keyboard window.
-       * @param {Object} event The pointerout event that bubbled to the
-       *    kb-keyboard.
-       */
-      out: function(event) {
-        // Ignore if triggered from one of the keys.
-        if (this.compareDocumentPosition(event.relatedTarget) &
-            Node.DOCUMENT_POSITION_CONTAINED_BY)
-          return;
-        if (swipeInProgress)
-          this.onSwipeUpdate(swipeTracker.populateDetails(true))
-        // Touched outside of the keyboard area, so disables swipe.
-        swipeInProgress = false;
-        swipeTracker.resetAll();
-        this.removeEventListener('pointermove', this.swipeHandler, false);
-      },
-
-      /**
-       * Handles a TypeKey event. This is used for when we programmatically
-       * want to type a specific key.
-       * @param {CustomEvent} event The TypeKey event that bubbled to the
-       *    kb-keyboard.
-       */
-      type: function(event) {
-        this.keyTyped(event.detail);
-      },
-
-      /**
-       * Handles key-up event that is sent by kb-key-base.
-       * @param {CustomEvent} event The key-up event dispatched by kb-key-base.
-       * @param {Object} detail The detail of pressed kb-key.
-       */
-      keyUp: function(event, detail) {
-        if (this.skipEvent(detail))
-          return;
-        if (swipeInProgress)
-          return;
-        if (detail.activeModifier) {
-          var modifier = detail.activeModifier.toLowerCase() + "-active";
-          this.classList.add(modifier);
-        }
-        // Adds the current keyboard modifiers to the detail.
-        if (this.ctrl)
-          detail.controlModifier = this.ctrl.isActive();
-        if (this.alt)
-          detail.altModifier = this.alt.isActive();
-        if (this.lastPressedKey)
-          this.lastPressedKey.classList.remove('active');
-        // Keyset transition key. This is needed to transition from upper
-        // to lower case when we are not in caps mode, as well as when
-        // we're ending chording.
-        this.changeKeyset(detail);
-
-        if (this.lastPressedKey &&
-            this.lastPressedKey.charValue != event.target.charValue) {
-          return;
-        }
-        if (repeatKey.key == event.target) {
-          repeatKey.cancel();
-          this.lastPressedKey = null;
-          return;
-        }
-        var toLayoutId = detail.toLayout;
-        // Layout transition key.
-        if (toLayoutId)
-          this.layout = toLayoutId;
-        var char = detail.char;
-        this.lastPressedKey = null;
-        // Characters that should not be typed.
-        switch(char) {
-          case 'Invalid':
-          case 'Shift':
-          case 'Ctrl':
-          case 'Alt':
-            enterUpperOnSpace = false;
-            swipeTracker.swipeFlags = 0;
-            return;
-          case 'Microphone':
-            this.voiceInput_.onDown();
-            return;
-          default:
-            break;
-        }
-        // Tries to type the character. Resorts to insertText if that fails.
-        if(!this.keyTyped(detail))
-          insertText(char);
-        // Post-typing logic.
-        switch(char) {
-          case ' ':
-            if(enterUpperOnSpace) {
-              enterUpperOnSpace = false;
-              if (this.shift) {
-                var shiftDetail = this.shift.onSpaceAfterPunctuation();
-                // Check if transition defined.
-                this.changeKeyset(shiftDetail);
-              } else {
-                console.error('Capitalization on space after punctuation \
-                            enabled, but cannot find target keyset.');
-              }
-              // Immediately return to maintain shift-state. Space is a
-              // non-control key and would otherwise trigger a reset of the
-              // shift key, causing a transition to lower case.
-              // TODO(rsadam): Add unit test after Polymer uprev complete.
-              return;
-            }
-            break;
-          case '.':
-          case '?':
-          case '!':
-            enterUpperOnSpace = this.shouldUpperOnSpace();
-            break;
-          default:
-            enterUpperOnSpace = false;
-            break;
-        }
-        // Reset control keys.
-        this.onNonControlKeyTyped();
-      },
-
-      /*
-       * Handles key-longpress event that is sent by kb-key-base.
-       * @param {CustomEvent} event The key-longpress event dispatched by
-       *     kb-key-base.
-       * @param {Object} detail The detail of pressed key.
-       */
-      keyLongpress: function(event, detail) {
-        // If the gesture is long press, remove the pointermove listener.
-        this.removeEventListener('pointermove', this.swipeHandler, false);
-        // Keyset transtion key.
-        if (this.changeKeyset(detail)) {
-          // Locks the keyset before removing active to prevent flicker.
-          this.classList.add('caps-locked');
-          // Makes last pressed key inactive if transit to a new keyset on long
-          // press.
-          if (this.lastPressedKey)
-            this.lastPressedKey.classList.remove('active');
-        }
-      },
-
-      /**
-       * Plays the specified sound.
-       * @param {Sound} sound The id of the audio tag.
-       */
-      playSound: function(sound) {
-        if (!sound || sound == Sound.NONE)
-          return;
-        var pool = this.sounds[sound];
-        if (!pool) {
-          console.error("Cannot find audio tag: " + sound);
-          return;
-        }
-        // Search the sound pool for a free resource.
-        for (var i = 0; i < pool.length; i++) {
-          if (pool[i].paused) {
-            pool[i].play();
-            return;
-          }
-        }
-      },
-
-      /**
-       * Whether we should transit to upper case when seeing a space after
-       * punctuation.
-       * @return {boolean}
-       */
-      shouldUpperOnSpace: function() {
-        // TODO(rsadam): Add other input types in which we should not
-        // transition to upper after a space.
-        return this.inputTypeValue != 'password';
-      },
-
-      /**
-       * Show menu for selecting a keyboard layout.
-       * @param {!Event} event The triggering event.
-       * @param {{left: number, top: number, width: number}} details Location of
-       *     the button that triggered the popup.
-       */
-      showOptions: function(event, details) {
-        var overlay = this.$.overlay;
-        if (!overlay) {
-          console.error('Missing overlay.');
-          return;
-        }
-        var menu = overlay.$.options;
-        if (!menu) {
-           console.error('Missing options menu.');
-        }
-        menu.hidden = false;
-        overlay.hidden = false;
-        var left = details.left + details.width - menu.clientWidth;
-        var top = details.top - menu.clientHeight;
-        menu.style.left = left + 'px';
-        menu.style.top = top + 'px';
-      },
-
-      /**
-       * Handler for the 'set-layout' event.
-       * @param {!Event} event The triggering event.
-       * @param {{layout: string}} details Details of the event, which contains
-       *     the name of the layout to activate.
-       */
-      setLayout: function(event, details) {
-        this.layout = details.layout;
-      },
-
-      /**
-       * Handles a change in the keyboard layout. Auto-selects the default
-       * keyset for the new layout.
-       */
-      layoutChanged: function() {
-        this.stale = true;
-        if (!this.selectDefaultKeyset()) {
-          this.fire('stateChange', {state: 'loadingKeyset'});
-
-          // Keyset selection fails if the keysets have not been loaded yet.
-          var keysets = document.querySelector('#' + this.layout);
-          if (keysets && keysets.content) {
-            var content = flattenKeysets(keysets.content);
-            this.appendChild(content);
-            this.selectDefaultKeyset();
-          } else {
-            // Add link for the keysets if missing from the document. Force
-            // a layout change after resolving the import of the link.
-            var query = 'link[id=' + this.layout + ']';
-            if (!document.querySelector(query)) {
-              // Layout has not beeen loaded yet.
-              var link = document.createElement('link');
-              link.id = this.layout;
-              link.setAttribute('rel', 'import');
-              link.setAttribute('href', 'layouts/' + this.layout + '.html');
-              document.head.appendChild(link);
-
-              // Load content for the new link element.
-              var self = this;
-              HTMLImports.importer.load(document, function() {
-                HTMLImports.parser.parseLink(link);
-                self.layoutChanged();
-              });
-            }
-          }
-        // New keyset has already been loaded, can show immediately.
-        } else {
-          this.activeKeyset.show();
-        }
-      },
-
-      /**
-       * Notifies the modifier keys that a non-control key was typed. This
-       * lets them reset sticky behaviour. A non-control key is defined as
-       * any key that is not Control, Alt, or Shift.
-       */
-      onNonControlKeyTyped: function() {
-        if (this.shift)
-          this.shift.onNonControlKeyTyped();
-        if (this.ctrl)
-          this.ctrl.onNonControlKeyTyped();
-        if (this.alt)
-          this.alt.onNonControlKeyTyped();
-        this.classList.remove('ctrl-active');
-        this.classList.remove('alt-active');
-      },
-
-      /**
-       * Callback function for when volume is changed.
-       */
-      volumeChanged: function() {
-        var toChange = Object.keys(this.sounds);
-        for (var i = 0; i < toChange.length; i++) {
-          var pool = this.sounds[toChange[i]];
-          for (var j = 0; j < pool.length; j++) {
-            pool[j].volume = this.volume;
-          }
-        }
-      },
-
-      /**
-       * Id for the active keyset.
-       * @type {string}
-       */
-      get activeKeysetId() {
-        return this.layout + '-' + this.keyset;
-      },
-
-      /**
-       * The active keyset DOM object.
-       * @type {kb-keyset}
-       */
-      get activeKeyset() {
-        return this.querySelector('#' + this.activeKeysetId);
-      },
-
-      /**
-       * The current input type.
-       * @type {string}
-       */
-      get inputTypeValue() {
-        return this.inputType;
-      },
-
-      /**
-       * Changes the input type if it's different from the current
-       * type, else resets the keyset to the default keyset.
-       * @type {string}
-       */
-      set inputTypeValue(value) {
-        if (value == this.inputType)
-          this.selectDefaultKeyset();
-        else
-          this.inputType = value;
-      },
-
-      /**
-       * The keyboard is ready for input once the target keyset appears
-       * in the distributed nodes for the keyboard.
-       * @return {boolean} Indicates if the keyboard is ready for input.
-       */
-      isReady: function() {
-        var keyset =  this.activeKeyset;
-        if (!keyset)
-          return false;
-        var nodes = this.$.content.getDistributedNodes();
-        for (var i = 0; i < nodes.length; i++) {
-          if (nodes[i].id && nodes[i].id == keyset.id)
-            return true;
-        }
-        return false;
-      },
-
-      /**
-       * Generates fabricated key events to simulate typing on a
-       * physical keyboard.
-       * @param {Object} detail Attributes of the key being typed.
-       * @return {boolean} Whether the key type succeeded.
-       */
-      keyTyped: function(detail) {
-        var builder = this.$.keyCodeMetadata;
-        if (this.ctrl)
-          detail.controlModifier = this.ctrl.isActive();
-        if (this.alt)
-          detail.altModifier = this.alt.isActive();
-        var downEvent = builder.createVirtualKeyEvent(detail, "keydown");
-        if (downEvent) {
-          sendKeyEvent(downEvent);
-          sendKeyEvent(builder.createVirtualKeyEvent(detail, "keyup"));
-          return true;
-        }
-        return false;
-      },
-
-      /**
-       * Selects the default keyset for a layout.
-       * @return {boolean} True if successful. This method can fail if the
-       *     keysets corresponding to the layout have not been injected.
-       */
-      selectDefaultKeyset: function() {
-        var keysets = this.querySelectorAll('kb-keyset');
-        // Full name of the keyset is of the form 'layout-keyset'.
-        var regex = new RegExp('^' + this.layout + '-(.+)');
-        var keysetsLoaded = false;
-        for (var i = 0; i < keysets.length; i++) {
-          var matches = keysets[i].id.match(regex);
-          if (matches && matches.length == REGEX_MATCH_COUNT) {
-             keysetsLoaded = true;
-             // Without both tests for a default keyset, it is possible to get
-             // into a state where multiple layouts are displayed.  A
-             // reproducable test case is do the following set of keyset
-             // transitions: qwerty -> system -> dvorak -> qwerty.
-             // TODO(kevers): Investigate why this is the case.
-             if (keysets[i].isDefault ||
-                 keysets[i].getAttribute('isDefault') == 'true') {
-               this.keyset = matches[REGEX_KEYSET_INDEX];
-               this.classList.remove('caps-locked');
-               this.classList.remove('alt-active');
-               this.classList.remove('ctrl-active');
-               // Caches shift key.
-               this.shift = this.querySelector('kb-shift-key');
-               if (this.shift)
-                 this.shift.reset();
-               // Caches control key.
-               this.ctrl = this.querySelector('kb-modifier-key[char=Ctrl]');
-               if (this.ctrl)
-                 this.ctrl.reset();
-               // Caches alt key.
-               this.alt = this.querySelector('kb-modifier-key[char=Alt]');
-               if (this.alt)
-                 this.alt.reset();
-               this.fire('stateChange', {
-                 state: 'keysetLoaded',
-                 value: this.keyset,
-               });
-               keyboardLoaded();
-               return true;
-             }
-          }
-        }
-        if (keysetsLoaded)
-          console.error('No default keyset found for ' + this.layout);
-        return false;
-      }
-    });
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-keyboard.js b/ui/keyboard/resources/elements/kb-keyboard.js
new file mode 100644
index 0000000..23c49e5
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-keyboard.js
@@ -0,0 +1,1003 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * The repeat delay in milliseconds before a key starts repeating. Use the
+ * same rate as Chromebook.
+ * (See chrome/browser/chromeos/language_preferences.cc)
+ * @const
+ * @type {number}
+ */
+var REPEAT_DELAY_MSEC = 500;
+
+/**
+ * The repeat interval or number of milliseconds between subsequent
+ * keypresses. Use the same rate as Chromebook.
+ * @const
+ * @type {number}
+ */
+var REPEAT_INTERVAL_MSEC = 50;
+
+/**
+ * The double click/tap interval.
+ * @const
+ * @type {number}
+ */
+var DBL_INTERVAL_MSEC = 300;
+
+/**
+ * The index of the name of the keyset when searching for all keysets.
+ * @const
+ * @type {number}
+ */
+var REGEX_KEYSET_INDEX = 1;
+
+/**
+ * The integer number of matches when searching for keysets.
+ * @const
+ * @type {number}
+ */
+var REGEX_MATCH_COUNT = 2;
+
+/**
+ * The boolean to decide if keyboard should transit to upper case keyset
+ * when spacebar is pressed. If a closing punctuation is followed by a
+ * spacebar, keyboard should automatically transit to upper case.
+ * @type {boolean}
+ */
+var enterUpperOnSpace = false;
+
+/**
+ * A structure to track the currently repeating key on the keyboard.
+ */
+var repeatKey = {
+
+  /**
+    * The timer for the delay before repeating behaviour begins.
+    * @type {number|undefined}
+    */
+  timer: undefined,
+
+  /**
+   * The interval timer for issuing keypresses of a repeating key.
+   * @type {number|undefined}
+   */
+  interval: undefined,
+
+  /**
+   * The key which is currently repeating.
+   * @type {BaseKey|undefined}
+   */
+  key: undefined,
+
+  /**
+   * Cancel the repeat timers of the currently active key.
+   */
+  cancel: function() {
+    clearTimeout(this.timer);
+    clearInterval(this.interval);
+    this.timer = undefined;
+    this.interval = undefined;
+    this.key = undefined;
+  }
+};
+
+/**
+ * The minimum movement interval needed to trigger cursor move on
+ * horizontal and vertical way.
+ * @const
+ * @type {number}
+ */
+var MIN_SWIPE_DIST_X = 50;
+var MIN_SWIPE_DIST_Y = 20;
+
+/**
+ * The maximum swipe distance that will trigger hintText of a key
+ * to be typed.
+ * @const
+ * @type {number}
+ */
+var MAX_SWIPE_FLICK_DIST = 60;
+
+/**
+ * The boolean to decide if it is swipe in process or finished.
+ * @type {boolean}
+ */
+var swipeInProgress = false;
+
+// Flag values for ctrl, alt and shift as defined by EventFlags
+// in "event_constants.h".
+// @enum {number}
+var Modifier = {
+  NONE: 0,
+  ALT: 8,
+  CONTROL: 4,
+  SHIFT: 2
+};
+
+/**
+ * A structure to track the current swipe status.
+ */
+var swipeTracker = {
+  /**
+   * The latest PointerMove event in the swipe.
+   * @type {Object}
+   */
+  currentEvent: undefined,
+
+  /**
+   * Whether or not a swipe changes direction.
+   * @type {false}
+   */
+  isComplex: false,
+
+  /**
+   * The count of horizontal and vertical movement.
+   * @type {number}
+   */
+  offset_x : 0,
+  offset_y : 0,
+
+  /**
+   * Last touch coordinate.
+   * @type {number}
+   */
+  pre_x : 0,
+  pre_y : 0,
+
+  /**
+   * The PointerMove event which triggered the swipe.
+   * @type {Object}
+   */
+  startEvent: undefined,
+
+  /**
+   * The flag of current modifier key.
+   * @type {number}
+   */
+  swipeFlags : 0,
+
+  /**
+   * Current swipe direction.
+   * @type {number}
+   */
+  swipeDirection : 0,
+
+  /**
+   * The number of times we've swiped within a single swipe.
+   * @type {number}
+   */
+  swipeIndex: 0,
+
+  /**
+   * Returns the combined direction of the x and y offsets.
+   * @return {number} The latest direction.
+   */
+  getOffsetDirection: function() {
+    // TODO (rsadam): Use angles to figure out the direction.
+    var direction = 0;
+    // Checks for horizontal swipe.
+    if (Math.abs(this.offset_x) > MIN_SWIPE_DIST_X) {
+      if (this.offset_x > 0) {
+        direction |= SwipeDirection.RIGHT;
+      } else {
+        direction |= SwipeDirection.LEFT;
+      }
+    }
+    // Checks for vertical swipe.
+    if (Math.abs(this.offset_y) > MIN_SWIPE_DIST_Y) {
+      if (this.offset_y < 0) {
+        direction |= SwipeDirection.UP;
+      } else {
+        direction |= SwipeDirection.DOWN;
+      }
+    }
+    return direction;
+  },
+
+  /**
+   * Populates the swipe update details.
+   * @param {boolean} endSwipe Whether this is the final event for this
+   *     swipe.
+   * @return {Object} The current state of the swipeTracker.
+   */
+  populateDetails: function(endSwipe) {
+    var detail = {};
+    detail.direction = this.swipeDirection;
+    detail.index = this.swipeIndex;
+    detail.status = this.swipeStatus;
+    detail.endSwipe = endSwipe;
+    detail.startEvent = this.startEvent;
+    detail.currentEvent = this.currentEvent;
+    detail.isComplex = this.isComplex;
+    return detail;
+  },
+
+  /**
+   * Reset all the values when swipe finished.
+   */
+  resetAll: function() {
+    this.offset_x = 0;
+    this.offset_y = 0;
+    this.pre_x = 0;
+    this.pre_y = 0;
+    this.swipeFlags = 0;
+    this.swipeDirection = 0;
+    this.swipeIndex = 0;
+    this.startEvent = undefined;
+    this.currentEvent = undefined;
+    this.isComplex = false;
+  },
+
+  /**
+   * Updates the swipe path with the current event.
+   * @param {Object} event The PointerEvent that triggered this update.
+   * @return {boolean} Whether or not to notify swipe observers.
+   */
+  update: function(event) {
+    if(!event.isPrimary)
+      return false;
+    // Update priors.
+    this.offset_x += event.screenX - this.pre_x;
+    this.offset_y += event.screenY - this.pre_y;
+    this.pre_x = event.screenX;
+    this.pre_y = event.screenY;
+
+    // Check if movement crosses minimum thresholds in each direction.
+    var direction = this.getOffsetDirection();
+    if (direction == 0)
+      return false;
+    // If swipeIndex is zero the current event is triggering the swipe.
+    if (this.swipeIndex == 0) {
+      this.startEvent = event;
+    } else if (direction != this.swipeDirection) {
+      // Toggle the isComplex flag.
+      this.isComplex = true;
+    }
+    // Update the swipe tracker.
+    this.swipeDirection = direction;
+    this.offset_x = 0;
+    this.offset_y = 0;
+    this.currentEvent = event;
+    this.swipeIndex++;
+    return true;
+  },
+
+};
+
+Polymer('kb-keyboard', {
+  alt: null,
+  config: null,
+  control: null,
+  dblDetail_: null,
+  dblTimer_: null,
+  inputType: null,
+  lastPressedKey: null,
+  shift: null,
+  sounds: {},
+  stale: true,
+  swipeHandler: null,
+  voiceInput_: null,
+  //TODO(rsadam@): Add a control to let users change this.
+  volume: DEFAULT_VOLUME,
+
+  /**
+   * The default input type to keyboard layout map. The key must be one of
+   * the input box type values.
+   * @type {object}
+   */
+  inputTypeToLayoutMap: {
+    number: "numeric",
+    text: "qwerty",
+    password: "qwerty"
+  },
+
+  /**
+   * Caches the specified sound on the keyboard.
+   * @param {string} soundId The name of the .wav file in the "sounds"
+       directory.
+   */
+  addSound: function(soundId) {
+    // Check if already loaded.
+    if (soundId == Sound.NONE || this.sounds[soundId])
+      return;
+    var pool = [];
+    for (var i = 0; i < SOUND_POOL_SIZE; i++) {
+      var audio = document.createElement('audio');
+      audio.preload = "auto";
+      audio.id = soundId;
+      audio.src = "../sounds/" + soundId + ".wav";
+      audio.volume = this.volume;
+      pool.push(audio);
+    }
+    this.sounds[soundId] = pool;
+  },
+
+  /**
+   * Changes the current keyset.
+   * @param {Object} detail The detail of the event that called this
+   *     function.
+   */
+  changeKeyset: function(detail) {
+    if (detail.relegateToShift && this.shift) {
+      this.keyset = this.shift.textKeyset;
+      this.activeKeyset.nextKeyset = undefined;
+      return true;
+    }
+    var toKeyset = detail.toKeyset;
+    if (toKeyset) {
+      this.keyset = toKeyset;
+      this.activeKeyset.nextKeyset = detail.nextKeyset;
+      return true;
+    }
+    return false;
+  },
+
+  keysetChanged: function() {
+    var keyset = this.activeKeyset;
+    // Show the keyset if it has been initialized.
+    if (keyset)
+      keyset.show();
+  },
+
+  configChanged: function() {
+    this.layout = this.config.layout;
+  },
+
+  ready: function() {
+    this.voiceInput_ = new VoiceInput(this);
+    this.swipeHandler = this.move.bind(this);
+    var self = this;
+    getKeyboardConfig(function(config) {
+      self.config = config;
+    });
+  },
+
+  /**
+   * Registers a callback for state change events.
+   * @param{!Function} callback Callback function to register.
+   */
+  addKeysetChangedObserver: function(callback) {
+    this.addEventListener('stateChange', callback);
+  },
+
+  /**
+   * Called when the type of focused input box changes. If a keyboard layout
+   * is defined for the current input type, that layout will be loaded.
+   * Otherwise, the keyboard layout for 'text' type will be loaded.
+   */
+  inputTypeChanged: function() {
+    // Disable layout switching at accessbility mode.
+    if (this.config && this.config.a11ymode)
+      return;
+
+    // TODO(bshe): Toggle visibility of some keys in a keyboard layout
+    // according to the input type.
+    var layout = this.inputTypeToLayoutMap[this.inputType];
+    if (!layout)
+      layout = this.inputTypeToLayoutMap.text;
+    this.layout = layout;
+  },
+
+  /**
+   * When double click/tap event is enabled, the second key-down and key-up
+   * events on the same key should be skipped. Return true when the event
+   * with |detail| should be skipped.
+   * @param {Object} detail The detail of key-up or key-down event.
+   */
+  skipEvent: function(detail) {
+    if (this.dblDetail_) {
+      if (this.dblDetail_.char != detail.char) {
+        // The second key down is not on the same key. Double click/tap
+        // should be ignored.
+        this.dblDetail_ = null;
+        clearTimeout(this.dblTimer_);
+      } else if (this.dblDetail_.clickCount == 1) {
+        return true;
+      }
+    }
+    return false;
+  },
+
+  /**
+   * Handles a swipe update.
+   * param {Object} detail The swipe update details.
+   */
+  onSwipeUpdate: function(detail) {
+    var direction = detail.direction;
+    if (!direction)
+      console.error("Swipe direction cannot be: " + direction);
+    // Triggers swipe editting if it's a purely horizontal swipe.
+    if (!(direction & (SwipeDirection.UP | SwipeDirection.DOWN))) {
+      // Nothing to do if the swipe has ended.
+      if (detail.endSwipe)
+        return;
+      var modifiers = 0;
+      // TODO (rsadam): This doesn't take into account index shifts caused
+      // by vertical swipes.
+      if (detail.index % 2 != 0) {
+        modifiers |= Modifier.SHIFT;
+        modifiers |= Modifier.CONTROL;
+      }
+      MoveCursor(direction, modifiers);
+      return;
+    }
+    // Triggers swipe hintText if it's a purely vertical swipe.
+    if (!(direction & (SwipeDirection.LEFT | SwipeDirection.RIGHT))) {
+      // Check if event is relevant to us.
+      if ((!detail.endSwipe) || (detail.isComplex))
+        return;
+      // Too long a swipe.
+      var distance = Math.abs(detail.startEvent.screenY -
+          detail.currentEvent.screenY);
+      if (distance > MAX_SWIPE_FLICK_DIST)
+        return;
+      var triggerKey = detail.startEvent.target;
+      if (triggerKey && triggerKey.onFlick)
+        triggerKey.onFlick(detail);
+    }
+  },
+
+  /**
+   * This function is bound to swipeHandler. Updates the current swipe
+   * status so that PointerEvents can be converted to Swipe events.
+   * @param {PointerEvent} event.
+   */
+  move: function(event) {
+    if (!swipeTracker.update(event))
+      return;
+    // Conversion was successful, swipe is now in progress.
+    swipeInProgress = true;
+    if (this.lastPressedKey) {
+      this.lastPressedKey.classList.remove('active');
+      this.lastPressedKey = null;
+    }
+    this.onSwipeUpdate(swipeTracker.populateDetails(false));
+  },
+
+  /**
+   * Handles key-down event that is sent by kb-key-base.
+   * @param {CustomEvent} event The key-down event dispatched by
+   *     kb-key-base.
+   * @param {Object} detail The detail of pressed kb-key.
+   */
+  keyDown: function(event, detail) {
+    if (this.skipEvent(detail))
+      return;
+
+    if (this.lastPressedKey) {
+      this.lastPressedKey.classList.remove('active');
+      this.lastPressedKey.autoRelease();
+    }
+    this.lastPressedKey = event.target;
+    this.lastPressedKey.classList.add('active');
+    repeatKey.cancel();
+    this.playSound(detail.sound);
+
+    var char = detail.char;
+    switch(char) {
+      case 'Shift':
+        this.classList.remove('caps-locked');
+        break;
+      case 'Alt':
+      case 'Ctrl':
+        var modifier = char.toLowerCase() + "-active";
+        // Removes modifier if already active.
+        if (this.classList.contains(modifier))
+          this.classList.remove(modifier);
+        break;
+      case 'Invalid':
+        // Not all Invalid keys are transition keys. Reset control keys if
+        // we pressed a transition key.
+        if (event.target.toKeyset || detail.relegateToShift)
+          this.onNonControlKeyTyped();
+        break;
+      default:
+        // Notify shift key.
+        if (this.shift)
+          this.shift.onNonControlKeyDown();
+        if (this.ctrl)
+          this.ctrl.onNonControlKeyDown();
+        if (this.alt)
+          this.alt.onNonControlKeyDown();
+        break;
+    }
+    if(this.changeKeyset(detail))
+      return;
+    if (detail.repeat) {
+      this.keyTyped(detail);
+      this.onNonControlKeyTyped();
+      repeatKey.key = this.lastPressedKey;
+      var self = this;
+      repeatKey.timer = setTimeout(function() {
+        repeatKey.timer = undefined;
+        repeatKey.interval = setInterval(function() {
+           self.playSound(detail.sound);
+           self.keyTyped(detail);
+        }, REPEAT_INTERVAL_MSEC);
+      }, Math.max(0, REPEAT_DELAY_MSEC - REPEAT_INTERVAL_MSEC));
+    }
+  },
+
+  /**
+   * Handles key-out event that is sent by kb-shift-key.
+   * @param {CustomEvent} event The key-out event dispatched by
+   *     kb-shift-key.
+   * @param {Object} detail The detail of pressed kb-shift-key.
+   */
+  keyOut: function(event, detail) {
+    this.changeKeyset(detail);
+  },
+
+  /**
+   * Enable/start double click/tap event recognition.
+   * @param {CustomEvent} event The enable-dbl event dispatched by
+   *     kb-shift-key.
+   * @param {Object} detail The detail of pressed kb-shift-key.
+   */
+  enableDbl: function(event, detail) {
+    if (!this.dblDetail_) {
+      this.dblDetail_ = detail;
+      this.dblDetail_.clickCount = 0;
+      var self = this;
+      this.dblTimer_ = setTimeout(function() {
+        self.dblDetail_.callback = null;
+        self.dblDetail_ = null;
+      }, DBL_INTERVAL_MSEC);
+    }
+  },
+
+  /**
+   * Enable the selection while swipe.
+   * @param {CustomEvent} event The enable-dbl event dispatched by
+   *    kb-shift-key.
+   */
+  enableSel: function(event) {
+    // TODO(rsadam): Disabled for now. May come back if we revert swipe
+    // selection to not do word selection.
+  },
+
+  /**
+   * Handles pointerdown event. This is used for swipe selection process.
+   * to get the start pre_x and pre_y. And also add a pointermove handler
+   * to start handling the swipe selection event.
+   * @param {PointerEvent} event The pointerup event that received by
+   *     kb-keyboard.
+   */
+  down: function(event) {
+    var layout = getKeysetLayout(this.activeKeysetId);
+    var key = layout.findClosestKey(event.clientX, event.clientY);
+    if (key)
+      key.down(event);
+    if (event.isPrimary) {
+      swipeTracker.pre_x = event.screenX;
+      swipeTracker.pre_y = event.screenY;
+      this.addEventListener("pointermove", this.swipeHandler, false);
+    }
+  },
+
+  /**
+   * Handles pointerup event. This is used for double tap/click events.
+   * @param {PointerEvent} event The pointerup event that bubbled to
+   *     kb-keyboard.
+   */
+  up: function(event) {
+    var layout = getKeysetLayout(this.activeKeysetId);
+    var key = layout.findClosestKey(event.clientX, event.clientY);
+    if (key)
+      key.up(event);
+    // When touch typing, it is very possible that finger moves slightly out
+    // of the key area before releases. The key should not be dropped in
+    // this case.
+    // TODO(rsadam@) Change behaviour such that the key drops and the second
+    // key gets pressed.
+    if (this.lastPressedKey &&
+        this.lastPressedKey.pointerId == event.pointerId) {
+      this.lastPressedKey.autoRelease();
+    }
+
+    if (this.dblDetail_) {
+      this.dblDetail_.clickCount++;
+      if (this.dblDetail_.clickCount == 2) {
+        this.dblDetail_.callback();
+        this.changeKeyset(this.dblDetail_);
+        clearTimeout(this.dblTimer_);
+
+        this.classList.add('caps-locked');
+
+        this.dblDetail_ = null;
+      }
+    }
+
+    // TODO(zyaozhujun): There are some edge cases to deal with later.
+    // (for instance, what if a second finger trigger a down and up
+    // event sequence while swiping).
+    // When pointer up from the screen, a swipe selection session finished,
+    // all the data should be reset to prepare for the next session.
+    if (event.isPrimary && swipeInProgress) {
+      swipeInProgress = false;
+      this.onSwipeUpdate(swipeTracker.populateDetails(true))
+      swipeTracker.resetAll();
+    }
+    this.removeEventListener('pointermove', this.swipeHandler, false);
+  },
+
+  /**
+   * Handles PointerOut event. This is used for when a swipe gesture goes
+   * outside of the keyboard window.
+   * @param {Object} event The pointerout event that bubbled to the
+   *    kb-keyboard.
+   */
+  out: function(event) {
+    // Ignore if triggered from one of the keys.
+    if (this.compareDocumentPosition(event.relatedTarget) &
+        Node.DOCUMENT_POSITION_CONTAINED_BY)
+      return;
+    if (swipeInProgress)
+      this.onSwipeUpdate(swipeTracker.populateDetails(true))
+    // Touched outside of the keyboard area, so disables swipe.
+    swipeInProgress = false;
+    swipeTracker.resetAll();
+    this.removeEventListener('pointermove', this.swipeHandler, false);
+  },
+
+  /**
+   * Handles a TypeKey event. This is used for when we programmatically
+   * want to type a specific key.
+   * @param {CustomEvent} event The TypeKey event that bubbled to the
+   *    kb-keyboard.
+   */
+  type: function(event) {
+    this.keyTyped(event.detail);
+  },
+
+  /**
+   * Handles key-up event that is sent by kb-key-base.
+   * @param {CustomEvent} event The key-up event dispatched by kb-key-base.
+   * @param {Object} detail The detail of pressed kb-key.
+   */
+  keyUp: function(event, detail) {
+    if (this.skipEvent(detail))
+      return;
+    if (swipeInProgress)
+      return;
+    if (detail.activeModifier) {
+      var modifier = detail.activeModifier.toLowerCase() + "-active";
+      this.classList.add(modifier);
+    }
+    // Adds the current keyboard modifiers to the detail.
+    if (this.ctrl)
+      detail.controlModifier = this.ctrl.isActive();
+    if (this.alt)
+      detail.altModifier = this.alt.isActive();
+    if (this.lastPressedKey)
+      this.lastPressedKey.classList.remove('active');
+    // Keyset transition key. This is needed to transition from upper
+    // to lower case when we are not in caps mode, as well as when
+    // we're ending chording.
+    this.changeKeyset(detail);
+
+    if (this.lastPressedKey &&
+        this.lastPressedKey.charValue != event.target.charValue) {
+      return;
+    }
+    if (repeatKey.key == event.target) {
+      repeatKey.cancel();
+      this.lastPressedKey = null;
+      return;
+    }
+    var toLayoutId = detail.toLayout;
+    // Layout transition key.
+    if (toLayoutId)
+      this.layout = toLayoutId;
+    var char = detail.char;
+    this.lastPressedKey = null;
+    // Characters that should not be typed.
+    switch(char) {
+      case 'Invalid':
+      case 'Shift':
+      case 'Ctrl':
+      case 'Alt':
+        enterUpperOnSpace = false;
+        swipeTracker.swipeFlags = 0;
+        return;
+      case 'Microphone':
+        this.voiceInput_.onDown();
+        return;
+      default:
+        break;
+    }
+    // Tries to type the character. Resorts to insertText if that fails.
+    if(!this.keyTyped(detail))
+      insertText(char);
+    // Post-typing logic.
+    switch(char) {
+      case '\n':
+      case ' ':
+        if(enterUpperOnSpace) {
+          enterUpperOnSpace = false;
+          if (this.shift) {
+            var shiftDetail = this.shift.onSpaceAfterPunctuation();
+            // Check if transition defined.
+            this.changeKeyset(shiftDetail);
+          } else {
+            console.error('Capitalization on space after punctuation \
+                        enabled, but cannot find target keyset.');
+          }
+          // Immediately return to maintain shift-state. Space is a
+          // non-control key and would otherwise trigger a reset of the
+          // shift key, causing a transition to lower case.
+          return;
+        }
+        break;
+      case '.':
+      case '?':
+      case '!':
+        enterUpperOnSpace = this.shouldUpperOnSpace();
+        break;
+      default:
+        enterUpperOnSpace = false;
+        break;
+    }
+    // Reset control keys.
+    this.onNonControlKeyTyped();
+  },
+
+  /*
+   * Handles key-longpress event that is sent by kb-key-base.
+   * @param {CustomEvent} event The key-longpress event dispatched by
+   *     kb-key-base.
+   * @param {Object} detail The detail of pressed key.
+   */
+  keyLongpress: function(event, detail) {
+    // If the gesture is long press, remove the pointermove listener.
+    this.removeEventListener('pointermove', this.swipeHandler, false);
+    // Keyset transtion key.
+    if (this.changeKeyset(detail)) {
+      // Locks the keyset before removing active to prevent flicker.
+      this.classList.add('caps-locked');
+      // Makes last pressed key inactive if transit to a new keyset on long
+      // press.
+      if (this.lastPressedKey)
+        this.lastPressedKey.classList.remove('active');
+    }
+  },
+
+  /**
+   * Plays the specified sound.
+   * @param {Sound} sound The id of the audio tag.
+   */
+  playSound: function(sound) {
+    if (!sound || sound == Sound.NONE)
+      return;
+    var pool = this.sounds[sound];
+    if (!pool) {
+      console.error("Cannot find audio tag: " + sound);
+      return;
+    }
+    // Search the sound pool for a free resource.
+    for (var i = 0; i < pool.length; i++) {
+      if (pool[i].paused) {
+        pool[i].play();
+        return;
+      }
+    }
+  },
+
+  /**
+   * Whether we should transit to upper case when seeing a space after
+   * punctuation.
+   * @return {boolean}
+   */
+  shouldUpperOnSpace: function() {
+    // TODO(rsadam): Add other input types in which we should not
+    // transition to upper after a space.
+    return this.inputTypeValue != 'password';
+  },
+
+  /**
+   * Handler for the 'set-layout' event.
+   * @param {!Event} event The triggering event.
+   * @param {{layout: string}} details Details of the event, which contains
+   *     the name of the layout to activate.
+   */
+  setLayout: function(event, details) {
+    this.layout = details.layout;
+  },
+
+  /**
+   * Handles a change in the keyboard layout. Auto-selects the default
+   * keyset for the new layout.
+   */
+  layoutChanged: function() {
+    this.stale = true;
+    if (!this.selectDefaultKeyset()) {
+      this.fire('stateChange', {state: 'loadingKeyset'});
+
+      // Keyset selection fails if the keysets have not been loaded yet.
+      var keysets = document.querySelector('#' + this.layout);
+      if (keysets && keysets.content) {
+        var content = flattenKeysets(keysets.content);
+        this.appendChild(content);
+        this.selectDefaultKeyset();
+      } else {
+        // Add link for the keysets if missing from the document. Force
+        // a layout change after resolving the import of the link.
+        var query = 'link[id=' + this.layout + ']';
+        if (!document.querySelector(query)) {
+          // Layout has not beeen loaded yet.
+          var link = document.createElement('link');
+          link.id = this.layout;
+          link.setAttribute('rel', 'import');
+          link.setAttribute('href', 'layouts/' + this.layout + '.html');
+          document.head.appendChild(link);
+
+          // Load content for the new link element.
+          var self = this;
+          HTMLImports.importer.load(document, function() {
+            HTMLImports.parser.parseLink(link);
+            self.layoutChanged();
+          });
+        }
+      }
+    // New keyset has already been loaded, can show immediately.
+    } else {
+      this.activeKeyset.show();
+    }
+  },
+
+  /**
+   * Notifies the modifier keys that a non-control key was typed. This
+   * lets them reset sticky behaviour. A non-control key is defined as
+   * any key that is not Control, Alt, or Shift.
+   */
+  onNonControlKeyTyped: function() {
+    if (this.shift)
+      this.shift.onNonControlKeyTyped();
+    if (this.ctrl)
+      this.ctrl.onNonControlKeyTyped();
+    if (this.alt)
+      this.alt.onNonControlKeyTyped();
+    this.classList.remove('ctrl-active');
+    this.classList.remove('alt-active');
+  },
+
+  /**
+   * Callback function for when volume is changed.
+   */
+  volumeChanged: function() {
+    var toChange = Object.keys(this.sounds);
+    for (var i = 0; i < toChange.length; i++) {
+      var pool = this.sounds[toChange[i]];
+      for (var j = 0; j < pool.length; j++) {
+        pool[j].volume = this.volume;
+      }
+    }
+  },
+
+  /**
+   * Id for the active keyset.
+   * @type {string}
+   */
+  get activeKeysetId() {
+    return this.layout + '-' + this.keyset;
+  },
+
+  /**
+   * The active keyset DOM object.
+   * @type {kb-keyset}
+   */
+  get activeKeyset() {
+    return this.querySelector('#' + this.activeKeysetId);
+  },
+
+  /**
+   * The current input type.
+   * @type {string}
+   */
+  get inputTypeValue() {
+    return this.inputType;
+  },
+
+  /**
+   * Changes the input type if it's different from the current
+   * type, else resets the keyset to the default keyset.
+   * @type {string}
+   */
+  set inputTypeValue(value) {
+    if (value == this.inputType)
+      this.selectDefaultKeyset();
+    else
+      this.inputType = value;
+  },
+
+  /**
+   * The keyboard is ready for input once the target keyset appears
+   * in the distributed nodes for the keyboard.
+   * @return {boolean} Indicates if the keyboard is ready for input.
+   */
+  isReady: function() {
+    var keyset =  this.activeKeyset;
+    if (!keyset)
+      return false;
+    var nodes = this.$.content.getDistributedNodes();
+    for (var i = 0; i < nodes.length; i++) {
+      if (nodes[i].id && nodes[i].id == keyset.id)
+        return true;
+    }
+    return false;
+  },
+
+  /**
+   * Generates fabricated key events to simulate typing on a
+   * physical keyboard.
+   * @param {Object} detail Attributes of the key being typed.
+   * @return {boolean} Whether the key type succeeded.
+   */
+  keyTyped: function(detail) {
+    var builder = this.$.keyCodeMetadata;
+    if (this.ctrl)
+      detail.controlModifier = this.ctrl.isActive();
+    if (this.alt)
+      detail.altModifier = this.alt.isActive();
+    var downEvent = builder.createVirtualKeyEvent(detail, "keydown");
+    if (downEvent) {
+      sendKeyEvent(downEvent);
+      sendKeyEvent(builder.createVirtualKeyEvent(detail, "keyup"));
+      return true;
+    }
+    return false;
+  },
+
+  /**
+   * Selects the default keyset for a layout.
+   * @return {boolean} True if successful. This method can fail if the
+   *     keysets corresponding to the layout have not been injected.
+   */
+  selectDefaultKeyset: function() {
+    var keysets = this.querySelectorAll('kb-keyset');
+    // Full name of the keyset is of the form 'layout-keyset'.
+    var regex = new RegExp('^' + this.layout + '-(.+)');
+    var keysetsLoaded = false;
+    for (var i = 0; i < keysets.length; i++) {
+      var matches = keysets[i].id.match(regex);
+      if (matches && matches.length == REGEX_MATCH_COUNT) {
+         keysetsLoaded = true;
+         // Without both tests for a default keyset, it is possible to get
+         // into a state where multiple layouts are displayed.  A
+         // reproducable test case is do the following set of keyset
+         // transitions: qwerty -> system -> dvorak -> qwerty.
+         // TODO(kevers): Investigate why this is the case.
+         if (keysets[i].isDefault ||
+             keysets[i].getAttribute('isDefault') == 'true') {
+           this.keyset = matches[REGEX_KEYSET_INDEX];
+           this.classList.remove('caps-locked');
+           this.classList.remove('alt-active');
+           this.classList.remove('ctrl-active');
+           // Caches shift key.
+           this.shift = this.querySelector('kb-shift-key');
+           if (this.shift)
+             this.shift.reset();
+           // Caches control key.
+           this.ctrl = this.querySelector('kb-modifier-key[char=Ctrl]');
+           if (this.ctrl)
+             this.ctrl.reset();
+           // Caches alt key.
+           this.alt = this.querySelector('kb-modifier-key[char=Alt]');
+           if (this.alt)
+             this.alt.reset();
+           this.fire('stateChange', {
+             state: 'keysetLoaded',
+             value: this.keyset,
+           });
+           keyboardLoaded();
+           return true;
+         }
+      }
+    }
+    if (keysetsLoaded)
+      console.error('No default keyset found for ' + this.layout);
+    return false;
+  }
+});
diff --git a/ui/keyboard/resources/elements/kb-keyset.html b/ui/keyboard/resources/elements/kb-keyset.html
index e2ffb27..096f22d 100644
--- a/ui/keyboard/resources/elements/kb-keyset.html
+++ b/ui/keyboard/resources/elements/kb-keyset.html
@@ -4,10 +4,9 @@
   -- found in the LICENSE file.
   -->
 
-<polymer-element name="kb-keyset"
-    attributes="align isDefault nextKeyset pitch weightRight
-        weightTop weightBottom"
-    on-key-up="{{keyUp}}" on-key-longpress="{{keyLongpress}}">
+<polymer-element name="kb-keyset" attributes="align isDefault nextKeyset pitch
+    weightRight weightTop weightBottom" on-key-up="{{keyUp}}"
+    on-key-longpress="{{keyLongpress}}">
   <template>
     <style>
       :host(:not(.activeKeyset)) {
@@ -19,100 +18,4 @@
         touch-action="none"></content>
     <kb-altkey-data id="altkeyMetadata"></kb-altkey-data>
   </template>
-  <script>
-    Polymer('kb-keyset', {
-      align: "center",
-      isDefault: false,
-      nextKeyset: undefined,
-      // Weight offsets for positioning the keyset.
-      weightBottom: 15,
-      weightLeft: 10,
-      weightRight: 10,
-      weightTop: 15,
-
-      /**
-       * Weight assigned to space between keys, of the form "xPitch yPitch".
-       * Defaults to xPitch = yPitch if it's only a single number.
-       * @type {string}
-       */
-      pitch: "10",
-
-      // TODO(bshe): support select keyset on down, long and dbl events.
-      keyUp: function(event, detail) {
-        switch (detail.char) {
-          case 'Shift':
-          case 'Alt':
-          case 'Ctrl':
-          case 'Invalid':
-            return;
-          default:
-            break;
-        }
-        if (!detail.toKeyset)
-          detail.toKeyset = this.nextKeyset;
-      },
-      keyLongpress: function(event, detail) {
-        if (!detail.char)
-          return;
-
-        var altkeyContainer = this.$.altkeyContainer.getDistributedNodes()[0];
-        if (!altkeyContainer)
-          return;
-
-        var altkeyMetadata = this.$.altkeyMetadata;
-        var altkeys = altkeyMetadata.getAltkeys(detail.char,
-                                                !!detail.hintText);
-        if (!altkeys)
-          return;
-
-        var id = altkeys.id;
-        var activeAltKeySet = altkeyContainer.querySelector('#' + id);
-        if (!activeAltKeySet) {
-          var keyWidth = event.target.clientWidth;
-          var leftMargin = event.target.offsetLeft;
-          var maxLeftOffset = Math.round(leftMargin / keyWidth);
-          var rightMargin = this.clientWidth - leftMargin - keyWidth;
-          var maxRightOffset = Math.round(rightMargin / keyWidth);
-          activeAltKeySet = altkeyMetadata.createAltkeySet(detail.char,
-                                                           maxLeftOffset,
-                                                           maxRightOffset,
-                                                           detail.hintText);
-          altkeyContainer.appendChild(activeAltKeySet);
-        }
-
-        altkeyContainer.keyset = id;
-        event.target.dropKey();
-        activeAltKeySet.style.width = event.target.clientWidth *
-            activeAltKeySet.childElementCount + 'px';
-        activeAltKeySet.style.height = event.target.clientHeight + 'px';
-        activeAltKeySet.style.top = event.target.offsetTop + 'px';
-        var leftOffset = activeAltKeySet.offset * event.target.clientWidth;
-        activeAltKeySet.style.left = event.target.offsetLeft - leftOffset +
-            'px';
-        var nodes = activeAltKeySet.childNodes;
-        nodes[activeAltKeySet.offset].classList.add('active');
-        altkeyContainer.hidden = false;
-      },
-
-      show: function() {
-        var old = $('keyboard').querySelector('.activeKeyset');
-        if (old && old != this)
-          old.classList.remove('activeKeyset');
-        this.classList.add('activeKeyset');
-        this.fire('stateChange', {
-          state: 'keysetChanged',
-          value: this.id
-        });
-      },
-
-      enteredView: function() {
-        var self = this;
-        Platform.endOfMicrotask(function(){
-          self.fire('realign');
-          if (self.isDefault)
-            self.show();
-        });
-      },
-    });
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-keyset.js b/ui/keyboard/resources/elements/kb-keyset.js
new file mode 100644
index 0000000..e32fc0b
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-keyset.js
@@ -0,0 +1,98 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer('kb-keyset', {
+  align: "center",
+  isDefault: false,
+  nextKeyset: undefined,
+  // Weight offsets for positioning the keyset.
+  weightBottom: 15,
+  weightLeft: 10,
+  weightRight: 10,
+  weightTop: 6,
+
+  /**
+   * Weight assigned to space between keys, of the form "xPitch yPitch".
+   * Defaults to xPitch = yPitch if it's only a single number.
+   * @type {string}
+   */
+  pitch: "10",
+
+  // TODO(bshe): support select keyset on down, long and dbl events.
+  keyUp: function(event, detail) {
+    switch (detail.char) {
+      case 'Shift':
+      case 'Alt':
+      case 'Ctrl':
+      case 'Invalid':
+        return;
+      default:
+        break;
+    }
+    if (!detail.toKeyset)
+      detail.toKeyset = this.nextKeyset;
+  },
+  keyLongpress: function(event, detail) {
+    if (!detail.char)
+      return;
+
+    var altkeyContainer = this.$.altkeyContainer.getDistributedNodes()[0];
+    if (!altkeyContainer)
+      return;
+
+    var altkeyMetadata = this.$.altkeyMetadata;
+    var altkeys = altkeyMetadata.getAltkeys(detail.char,
+                                            !!detail.hintText);
+    if (!altkeys)
+      return;
+
+    var id = altkeys.id;
+    var activeAltKeySet = altkeyContainer.querySelector('#' + id);
+    if (!activeAltKeySet) {
+      var keyWidth = event.target.clientWidth;
+      var leftMargin = event.target.offsetLeft;
+      var maxLeftOffset = Math.round(leftMargin / keyWidth);
+      var rightMargin = this.clientWidth - leftMargin - keyWidth;
+      var maxRightOffset = Math.round(rightMargin / keyWidth);
+      activeAltKeySet = altkeyMetadata.createAltkeySet(detail.char,
+                                                       maxLeftOffset,
+                                                       maxRightOffset,
+                                                       detail.hintText);
+      altkeyContainer.appendChild(activeAltKeySet);
+    }
+
+    altkeyContainer.keyset = id;
+    event.target.dropKey();
+    activeAltKeySet.style.width = event.target.clientWidth *
+        activeAltKeySet.childElementCount + 'px';
+    activeAltKeySet.style.height = event.target.clientHeight + 'px';
+    activeAltKeySet.style.top = event.target.offsetTop + 'px';
+    var leftOffset = activeAltKeySet.offset * event.target.clientWidth;
+    activeAltKeySet.style.left = event.target.offsetLeft - leftOffset +
+        'px';
+    var nodes = activeAltKeySet.childNodes;
+    nodes[activeAltKeySet.offset].classList.add('active');
+    altkeyContainer.hidden = false;
+  },
+
+  show: function() {
+    var old = $('keyboard').querySelector('.activeKeyset');
+    if (old && old != this)
+      old.classList.remove('activeKeyset');
+    this.classList.add('activeKeyset');
+    this.fire('stateChange', {
+      state: 'keysetChanged',
+      value: this.id
+    });
+  },
+
+  enteredView: function() {
+    var self = this;
+    Platform.endOfMicrotask(function(){
+      self.fire('realign');
+      if (self.isDefault)
+        self.show();
+    });
+  },
+});
diff --git a/ui/keyboard/resources/elements/kb-modifier-key.html b/ui/keyboard/resources/elements/kb-modifier-key.html
index adba476..1a742cc 100644
--- a/ui/keyboard/resources/elements/kb-modifier-key.html
+++ b/ui/keyboard/resources/elements/kb-modifier-key.html
@@ -6,137 +6,4 @@
 
 <polymer-element name="kb-modifier-key" class="unlocked dark" extends="kb-key"
     on-pointerout="{{out}}">
-  <script>
-    (function () {
-
-      /**
-       * The possible states of the key.
-       * @const
-       * @type {Enum}
-       */
-      var KEY_STATES = {
-        PRESSED: "pressed", // Key-down.
-        UNLOCKED: "unlocked", // Default state.
-        TAPPED: "tapped", // Key-down followed by key-up.
-        CHORDING: "chording", // Chording mode.
-      };
-
-      /**
-       * A map of the state of all modifier keys.
-       * @type {Object}
-       */
-      var states = {};
-
-      Polymer('kb-modifier-key', {
-        up: function(event) {
-          if (this.state == KEY_STATES.PRESSED)
-            this.state = KEY_STATES.TAPPED;
-          else
-            this.state = KEY_STATES.UNLOCKED;
-          this.super([event]);
-        },
-
-        down: function(event) {
-          // First transition state so that populateDetails generates
-          // correct data.
-          switch (this.state) {
-            case KEY_STATES.UNLOCKED:
-              this.state = KEY_STATES.PRESSED;
-              break;
-            case KEY_STATES.TAPPED:
-              this.state = KEY_STATES.UNLOCKED;
-              break;
-            case KEY_STATES.PRESSED:
-            case KEY_STATES.CHORDING:
-              // We pressed another key at the same time,
-              // so ignore second press.
-              return;
-            default:
-              console.error("Undefined key state: " + state);
-              break;
-          }
-          this.super([event]);
-        },
-
-        /**
-         * Returns whether the modifier for this key is active.
-         * @return {boolean}
-         */
-        isActive: function() {
-          return this.state != KEY_STATES.UNLOCKED;
-        },
-
-        /**
-         * Notifies key that a non-control keyed down.
-         * A control key is defined as one of shift, control or alt.
-         */
-        onNonControlKeyDown: function() {
-          switch(this.state) {
-            case (KEY_STATES.PRESSED):
-              this.state = KEY_STATES.CHORDING;
-              break;
-          }
-        },
-
-        /**
-         * Notifies key that a non-control keyed was typed.
-         * A control key is defined as one of shift, control or alt.
-         */
-        onNonControlKeyTyped: function() {
-           switch(this.state) {
-             case (KEY_STATES.TAPPED):
-               this.state = KEY_STATES.UNLOCKED;
-               break;
-           }
-        },
-
-        /**
-         * Called on a pointer-out event. Ends chording.
-         * @param {event} event The pointer-out event.
-         */
-        out: function(event) {
-          // TODO(rsadam): Add chording event so that we don't reset
-          // when shift-chording.
-          if (this.state == KEY_STATES.CHORDING) {
-            this.state = KEY_STATES.UNLOCKED;
-          }
-        },
-
-        /*
-         * Overrides the autoRelease function to enable chording.
-         */
-        autoRelease: function() {
-        },
-
-        populateDetails: function(caller) {
-          var detail = this.super([caller]);
-          if (this.state != KEY_STATES.UNLOCKED)
-            detail.activeModifier = this.charValue;
-          return detail;
-        },
-
-        /**
-         *  Resets the modifier key state.
-         */
-        reset: function() {
-          this.state = KEY_STATES.UNLOCKED;
-        },
-
-        get state() {
-          var key = this.charValue;
-          if (!key)
-            console.error("missing key for kb-modifier-key state: " + this);
-          // All keys default to the unlock state.
-          if (!(key in states))
-            states[key] = KEY_STATES.UNLOCKED;
-          return states[key];
-        },
-
-        set state(value) {
-          var key = this.charValue;
-          states[key] = value;
-        }
-      });
-    })();
-  </script>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-modifier-key.js b/ui/keyboard/resources/elements/kb-modifier-key.js
new file mode 100644
index 0000000..0f9fd8a
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-modifier-key.js
@@ -0,0 +1,135 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function () {
+
+  /**
+   * The possible states of the key.
+   * @const
+   * @type {Enum}
+   */
+  var KEY_STATES = {
+    PRESSED: "pressed", // Key-down.
+    UNLOCKED: "unlocked", // Default state.
+    TAPPED: "tapped", // Key-down followed by key-up.
+    CHORDING: "chording", // Chording mode.
+  };
+
+  /**
+   * A map of the state of all modifier keys.
+   * @type {Object}
+   */
+  var states = {};
+
+  Polymer('kb-modifier-key', {
+    up: function(event) {
+      if (this.state == KEY_STATES.PRESSED)
+        this.state = KEY_STATES.TAPPED;
+      else
+        this.state = KEY_STATES.UNLOCKED;
+      this.super([event]);
+    },
+
+    down: function(event) {
+      // First transition state so that populateDetails generates
+      // correct data.
+      switch (this.state) {
+        case KEY_STATES.UNLOCKED:
+          this.state = KEY_STATES.PRESSED;
+          break;
+        case KEY_STATES.TAPPED:
+          this.state = KEY_STATES.UNLOCKED;
+          break;
+        case KEY_STATES.PRESSED:
+        case KEY_STATES.CHORDING:
+          // We pressed another key at the same time,
+          // so ignore second press.
+          return;
+        default:
+          console.error("Undefined key state: " + state);
+          break;
+      }
+      this.super([event]);
+    },
+
+    /**
+     * Returns whether the modifier for this key is active.
+     * @return {boolean}
+     */
+    isActive: function() {
+      return this.state != KEY_STATES.UNLOCKED;
+    },
+
+    /**
+     * Notifies key that a non-control keyed down.
+     * A control key is defined as one of shift, control or alt.
+     */
+    onNonControlKeyDown: function() {
+      switch(this.state) {
+        case (KEY_STATES.PRESSED):
+          this.state = KEY_STATES.CHORDING;
+          break;
+      }
+    },
+
+    /**
+     * Notifies key that a non-control keyed was typed.
+     * A control key is defined as one of shift, control or alt.
+     */
+    onNonControlKeyTyped: function() {
+       switch(this.state) {
+         case (KEY_STATES.TAPPED):
+           this.state = KEY_STATES.UNLOCKED;
+           break;
+       }
+    },
+
+    /**
+     * Called on a pointer-out event. Ends chording.
+     * @param {event} event The pointer-out event.
+     */
+    out: function(event) {
+      // TODO(rsadam): Add chording event so that we don't reset
+      // when shift-chording.
+      if (this.state == KEY_STATES.CHORDING) {
+        this.state = KEY_STATES.UNLOCKED;
+      }
+    },
+
+    /*
+     * Overrides the autoRelease function to enable chording.
+     */
+    autoRelease: function() {
+    },
+
+    populateDetails: function(caller) {
+      var detail = this.super([caller]);
+      if (this.state != KEY_STATES.UNLOCKED)
+        detail.activeModifier = this.charValue;
+      return detail;
+    },
+
+    /**
+     *  Resets the modifier key state.
+     */
+    reset: function() {
+      this.state = KEY_STATES.UNLOCKED;
+    },
+
+    get state() {
+      var key = this.charValue;
+      if (!key)
+        console.error("missing key for kb-modifier-key state: " + this);
+      // All keys default to the unlock state.
+      if (!(key in states))
+        states[key] = KEY_STATES.UNLOCKED;
+      return states[key];
+    },
+
+    set state(value) {
+      var key = this.charValue;
+      states[key] = value;
+    }
+  });
+})();
diff --git a/ui/keyboard/resources/elements/kb-options-menu.html b/ui/keyboard/resources/elements/kb-options-menu.html
deleted file mode 100644
index 57382ea..0000000
--- a/ui/keyboard/resources/elements/kb-options-menu.html
+++ /dev/null
@@ -1,148 +0,0 @@
-<!--
-  -- Copyright 2013 The Chromium Authors. All rights reserved.
-  -- Use of this source code is governed by a BSD-style license that can be
-  -- found in the LICENSE file.
-  -->
-
-<polymer-element name="kb-options-menu-item" attributes="label active"
-    on-pointerdown="down" on-pointerover="over" on-pointerout="out"
-    on-pointerup="up">
-  <template>
-    <style>
-      :host {
-        -webkit-padding-after: 5px;
-        -webkit-padding-before: 5px;
-        -webkit-padding-end: 40px;
-        -webkit-padding-start: 40px;
-        color: #fff;
-        display: -webkit-box;
-        font-family: roboto-bold;
-        font-size: 18px;
-        font-weight: 300;
-        height: 28px;
-      }
-
-      :host.active {
-        background-color: #848490;
-      }
-    </style>
-    <span>{{label}}</span>
-  </template>
-  <script>
-    Polymer('kb-options-menu-item', {
-      down: function(event) {
-        event.stopPropagation();
-      },
-
-      over: function(event) {
-        this.classList.add('active');
-      },
-
-      out: function(event) {
-        this.classList.remove('active');
-      },
-
-      up: function(event) {
-        this.hidden = true;
-        hideKeyboard();
-      },
-    });
-  </script>
-</polymer-element>
-
-<polymer-element name="kb-options-menu-toggle-lock-item"
-    extends="kb-options-menu-item">
-  <script>
-    (function() {
-      /**
-       * The lock and unlock label for this key.
-       * @const
-       * @enum {string}
-       */
-      // TODO(bshe): Localize the string resources. http://crbug.com/328871
-      var KEY_LABEL = {
-        LOCK: 'Lock',
-        UNLOCK: 'Unlock'
-      };
-
-      Polymer('kb-options-menu-toggle-lock-item', {
-        up: function(event) {
-          lockKeyboard(!keyboardLocked());
-          this.hidden = true;
-        },
-
-        get label() {
-          return keyboardLocked() ? KEY_LABEL.UNLOCK : KEY_LABEL.LOCK;
-        }
-      });
-    })();
-  </script>
-</polymer-element>
-
-<polymer-element name="kb-options-menu" noscript>
-  <template>
-    <style>
-      :host {
-        -webkit-box-orient: vertical;
-        background-color: #3b3b3e;
-        border-radius: 2px;
-        display: -webkit-box;
-        left: 0;
-        position: absolute;
-        top: 0;
-        white-space:nowrap;
-        z-index: 1;
-      }
-      .arm-dismiss :host {
-        opacity: 0;
-      }
-    </style>
-    <kb-options-menu-toggle-lock-item></kb-options-menu-toggle-lock-item>
-    <kb-options-menu-item layout="none" label="Hide">
-    </kb-options-menu-item>
-  </template>
-</polymer-element>
-
-<polymer-element name="kb-keyboard-overlay" attributes="keyset"
-    on-pointerdown="down" on-pointerup="up">
-  <template>
-    <style>
-      :host {
-        background-color: rgba(0, 0, 0, 0.6);
-        bottom: 0;
-        left: 0;
-        position: absolute;
-        right: 0;
-        top: 0;
-        z-index: 1;
-      }
-
-      :host.arm-dismiss {
-        background-color: rgba(0,0,0,0);
-      }
-    </style>
-    <!-- Insert popups here. -->
-    <kb-options-menu id="options" hidden></kb-options-menu>
-  </template>
-  <script>
-    Polymer('kb-keyboard-overlay', {
-      up: function(event) {
-        this.hidden = true;
-        this.classList.remove('arm-dismiss');
-        event.stopPropagation();
-      },
-
-      down: function(event) {
-        this.classList.add('arm-dismiss');
-        event.stopPropagation();
-      },
-
-      hiddenChanged: function() {
-        this.fire('stateChange', {
-          state: 'overlayVisibility',
-          value: !!this.hidden
-        });
-      }
-    });
-  </script>
-</polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-row.html b/ui/keyboard/resources/elements/kb-row.html
index e8429bb..6d0f254 100644
--- a/ui/keyboard/resources/elements/kb-row.html
+++ b/ui/keyboard/resources/elements/kb-row.html
@@ -1,5 +1,5 @@
 <!--
-  -- Copyright (c) 2013 The Chromium Authors. All rights reserved.
+  -- Copyright 2013 The Chromium Authors. All rights reserved.
   -- Use of this source code is governed by a BSD-style license that can be
   -- found in the LICENSE file.
   -->
@@ -7,7 +7,7 @@
 <polymer-element name="kb-row" attributes="align weight">
   <template>
     <style>
-    :host {
+    :host() {
       text-align: center;
       margin-right: 0.25em;
       margin-top: 0.25em;
@@ -18,10 +18,5 @@
     </style>
     <content select="*"></content>
   </template>
-  <script>
-    Polymer('kb-row', {
-      align: RowAlignment.STRETCH,
-      weight: DEFAULT_KEY_WEIGHT,
-    });
-  </script>
+
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-row.js b/ui/keyboard/resources/elements/kb-row.js
new file mode 100644
index 0000000..d32a94f
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-row.js
@@ -0,0 +1,8 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Polymer('kb-row', {
+  align: RowAlignment.STRETCH,
+  weight: DEFAULT_KEY_WEIGHT,
+});
diff --git a/ui/keyboard/resources/elements/kb-shift-key.html b/ui/keyboard/resources/elements/kb-shift-key.html
index 8c617b4..1deb07d 100644
--- a/ui/keyboard/resources/elements/kb-shift-key.html
+++ b/ui/keyboard/resources/elements/kb-shift-key.html
@@ -4,251 +4,69 @@
   -- found in the LICENSE file.
   -->
 
-<polymer-element name="kb-shift-key"
-    attributes="lowerCaseKeysetId upperCaseKeysetId"
-    class="shift dark" char="Shift" on-pointerout="{{out}}" extends="kb-key">
-  <script>
-    (function () {
+<polymer-element name="kb-shift-key" attributes="lowerCaseKeysetId
+    upperCaseKeysetId" class="shift dark" char="Shift" on-pointerout="{{out}}"
+    extends="kb-key">
+  <template>
+    <style>
+    :host() {
+      border-radius: 2px;
+      border-style: solid;
+      border-width: 1px 0;
+      color: #ffffff;
+      font-family: roboto-bold;
+      font-weight: 300;
+    }
 
-      /**
-       * The possible states of the shift key.
-       * Unlocked is the default state. Locked for capslocked, pressed is a
-       * key-down and tapped for a key-down followed by an immediate key-up.
-       * @const
-       * @type {Enum}
-       */
-      var KEY_STATES = {
-        PRESSED: "pressed", // Key-down on shift key.
-        LOCKED: "locked", // Key is capslocked.
-        UNLOCKED: "unlocked", // Default state.
-        TAPPED: "tapped", // Key-down followed by key-up.
-        CHORDING: "chording" // Key-down followed by other keys.
-      };
+    :host(.active) {
+      -webkit-box-shadow: inset 0 1px #969696, inset 0 -1px #6f6f6f;
+      background-image: -webkit-linear-gradient(#8b8b8b, #7d7d7d);
+      background-size: cover;
+      border-bottom-color: #5b5b5b;
+      border-top-color: #a4a4a4;
+    }
 
-      /**
-       * The pointerdown event on shiftkey that may eventually trigger chording
-       * state. pointerId and eventTarget are the two fields that is used now.
-       * @type {PointerEvent}
-       */
-      var enterChordingEvent = undefined;
+    :host() .key {
+      background-image: none;
+      background-position: center;
+      background-repeat: no-repeat;
+      background-size: contain;
+      bottom: 0;
+      font-size: 70%;
+      height: 70%;
+      left: 0;
+      margin: auto;
+      position: absolute;
+      right: 0;
+      top: 0;
+      width: auto;
+    }
 
-      /**
-       * Uses a closure to define one long press timer among all shift keys
-       * regardless of the layout they are in.
-       * @type {function}
-       */
-      var shiftLongPressTimer = undefined;
+    :host() .shift-light-wrapper {
+      bottom: 3px;
+      height: 10%;
+      margin: 0;
+      padding: 0;
+      position: absolute;
+      width: 100%;
+    }
 
-      /**
-       * The current state of the shift key.
-       * @type {Enum}
-       */
-      var state = KEY_STATES.UNLOCKED;
-
-      Polymer('kb-shift-key', {
-        /**
-         * Defines how capslock effects keyset transition. We always transition
-         * from the lowerCaseKeysetId to the upperCaseKeysetId if capslock is
-         * on.
-         * @type {string}
-         */
-        lowerCaseKeysetId: 'lower',
-        upperCaseKeysetId: 'upper',
-
-        up: function(event) {
-          if (state == KEY_STATES.CHORDING &&
-              event.pointerId != enterChordingEvent.pointerId) {
-            // Disables all other pointer events on shift keys when chording.
-            return;
-          }
-          switch (state) {
-            case KEY_STATES.PRESSED:
-              state = KEY_STATES.TAPPED;
-              break;
-            case KEY_STATES.CHORDING:
-              // Leaves chording only if the pointer that triggered it is
-              // released.
-              state = KEY_STATES.UNLOCKED;
-              break;
-            default:
-              break;
-          }
-          // When releasing the shift key, it is not the same shift key that was
-          // pressed. Updates the pointerId of the releasing shift key to make
-          // sure key-up event fires correctly in kb-key-base.
-          this.pointerId = enterChordingEvent.pointerId;
-          this.super([event]);
-        },
-
-        out: function(event) {
-          // Sliding off the shift key while chording is treated as a key-up.
-          // Note that we switch to a new keyset on shift keydown, and a finger
-          // movement on the new shift key will trigger this function being
-          // called on the old shift key. We should not end chording in that
-          // case.
-          if (state == KEY_STATES.CHORDING &&
-              event.pointerId == enterChordingEvent.pointerId &&
-              event.target != enterChordingEvent.target) {
-            state = KEY_STATES.UNLOCKED;
-            var detail = this.populateDetails('out');
-            this.fire("key-out", detail);
-          }
-        },
-
-        down: function(event) {
-          // First transition state so that populateDetails generates
-          // correct data.
-          switch (state) {
-            case KEY_STATES.UNLOCKED:
-              state = KEY_STATES.PRESSED;
-              break;
-            case KEY_STATES.TAPPED:
-            case KEY_STATES.LOCKED:
-              state = KEY_STATES.UNLOCKED;
-              break;
-            case KEY_STATES.PRESSED:
-            case KEY_STATES.CHORDING:
-              // We pressed another shift key at the same time,
-              // so ignore second press.
-              return;
-            default:
-              console.error("Undefined shift key state: " + state);
-              break;
-          }
-          enterChordingEvent = event;
-          // Trigger parent behaviour.
-          this.super([event]);
-          this.fire('enable-sel');
-          // Populate double click transition details.
-          var detail = {};
-          detail.char = this.char || this.textContent;
-          detail.toKeyset = this.upperCaseKeysetId;
-          detail.nextKeyset = undefined;
-          detail.callback = this.onDoubleClick;
-          this.fire('enable-dbl', detail);
-        },
-
-        generateLongPressTimer: function() {
-          return this.async(function() {
-            var detail = this.populateDetails();
-            if (state == KEY_STATES.LOCKED) {
-              // We don't care about the longpress if we are already
-              // capitalized.
-              return;
-            } else {
-              state = KEY_STATES.LOCKED;
-              detail.toKeyset = this.upperCaseKeysetId;
-              detail.nextKeyset = undefined;
-            }
-            this.fire('key-longpress', detail);
-          }, null, LONGPRESS_DELAY_MSEC);
-        },
-
-        // @return Whether the shift modifier is currently active.
-        isActive: function() {
-          return state != KEY_STATES.UNLOCKED;
-        },
-
-        /**
-         * Callback function for when a double click is triggered.
-         */
-        onDoubleClick: function() {
-          state = KEY_STATES.LOCKED;
-        },
-
-        /**
-         * Notifies shift key that a non-control key was pressed down.
-         * A control key is defined as one of shift, control or alt.
-         */
-        onNonControlKeyDown: function() {
-          switch (state) {
-            case (KEY_STATES.PRESSED):
-              state = KEY_STATES.CHORDING;
-              // Disable longpress timer.
-              clearTimeout(shiftLongPressTimer);
-              break;
-            default:
-              break;
-          }
-        },
-
-        /**
-         * Notifies key that a non-control keyed was typed.
-         * A control key is defined as one of shift, control or alt.
-         */
-        onNonControlKeyTyped: function() {
-          if (state == KEY_STATES.TAPPED)
-            state = KEY_STATES.UNLOCKED;
-        },
-
-        /**
-         * Callback function for when a space is pressed after punctuation.
-         * @return {Object} The keyset transitions the keyboard should make.
-         */
-        onSpaceAfterPunctuation: function() {
-           var detail = {};
-           detail.toKeyset = this.upperCaseKeysetId;
-           detail.nextKeyset = this.lowerCaseKeysetId;
-           state = KEY_STATES.TAPPED;
-           return detail;
-        },
-
-        populateDetails: function(caller) {
-          var detail = this.super([caller]);
-          switch(state) {
-            case(KEY_STATES.LOCKED):
-              detail.toKeyset = this.upperCaseKeysetId;
-              break;
-            case(KEY_STATES.UNLOCKED):
-              detail.toKeyset = this.lowerCaseKeysetId;
-              break;
-            case(KEY_STATES.PRESSED):
-              detail.toKeyset = this.upperCaseKeysetId;
-              break;
-            case(KEY_STATES.TAPPED):
-              detail.toKeyset = this.upperCaseKeysetId;
-              detail.nextKeyset = this.lowerCaseKeysetId;
-              break;
-            case(KEY_STATES.CHORDING):
-              detail.toKeyset = this.lowerCaseKeysetId;
-              break;
-            default:
-              break;
-          }
-          return detail;
-        },
-
-        /**
-         *  Resets the shift key state.
-         */
-        reset: function() {
-          state = KEY_STATES.UNLOCKED;
-        },
-
-        /**
-         * Overrides longPressTimer for the shift key.
-         */
-        get longPressTimer() {
-          return shiftLongPressTimer;
-        },
-
-        set longPressTimer(timer) {
-          shiftLongPressTimer = timer;
-        },
-
-        get state() {
-          return state;
-        },
-
-        get textKeyset() {
-          switch (state) {
-            case KEY_STATES.UNLOCKED:
-              return this.lowerCaseKeysetId;
-            default:
-              return this.upperCaseKeysetId;
-          }
-        },
-      });
-    })();
-  </script>
+    :host() .shift-light {
+      -webkit-box-shadow: inset 0 1px #101010, inset 0 -1px #444444;
+      background-image: -webkit-linear-gradient(#101010, #000000);
+      border: solid;
+      border-bottom-color: #1d1d1d;
+      border-top-color: #2d2d2d;
+      border-width: 1px 0;
+      height: 0.3em;
+      margin: 0 auto;
+      position: relative;
+      width: 1.8em;
+    }
+  </style>
+    <div id="key" class="key"> </div>
+    <div class="shift-light-wrapper">
+      <div class="shift-light"> </div>
+    </div>
+  </template>
 </polymer-element>
diff --git a/ui/keyboard/resources/elements/kb-shift-key.js b/ui/keyboard/resources/elements/kb-shift-key.js
new file mode 100644
index 0000000..4ebb633
--- /dev/null
+++ b/ui/keyboard/resources/elements/kb-shift-key.js
@@ -0,0 +1,246 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+(function () {
+
+  /**
+   * The possible states of the shift key.
+   * Unlocked is the default state. Locked for capslocked, pressed is a
+   * key-down and tapped for a key-down followed by an immediate key-up.
+   * @const
+   * @type {Enum}
+   */
+  var KEY_STATES = {
+    PRESSED: "pressed", // Key-down on shift key.
+    LOCKED: "locked", // Key is capslocked.
+    UNLOCKED: "unlocked", // Default state.
+    TAPPED: "tapped", // Key-down followed by key-up.
+    CHORDING: "chording" // Key-down followed by other keys.
+  };
+
+  /**
+   * The pointerdown event on shiftkey that may eventually trigger chording
+   * state. pointerId and eventTarget are the two fields that is used now.
+   * @type {PointerEvent}
+   */
+  var enterChordingEvent = undefined;
+
+  /**
+   * Uses a closure to define one long press timer among all shift keys
+   * regardless of the layout they are in.
+   * @type {function}
+   */
+  var shiftLongPressTimer = undefined;
+
+  /**
+   * The current state of the shift key.
+   * @type {Enum}
+   */
+  var state = KEY_STATES.UNLOCKED;
+
+  Polymer('kb-shift-key', {
+    /**
+     * Defines how capslock effects keyset transition. We always transition
+     * from the lowerCaseKeysetId to the upperCaseKeysetId if capslock is
+     * on.
+     * @type {string}
+     */
+    lowerCaseKeysetId: 'lower',
+    upperCaseKeysetId: 'upper',
+
+    up: function(event) {
+      if (state == KEY_STATES.CHORDING &&
+          event.pointerId != enterChordingEvent.pointerId) {
+        // Disables all other pointer events on shift keys when chording.
+        return;
+      }
+      switch (state) {
+        case KEY_STATES.PRESSED:
+          state = KEY_STATES.TAPPED;
+          break;
+        case KEY_STATES.CHORDING:
+          // Leaves chording only if the pointer that triggered it is
+          // released.
+          state = KEY_STATES.UNLOCKED;
+          break;
+        default:
+          break;
+      }
+      // When releasing the shift key, it is not the same shift key that was
+      // pressed. Updates the pointerId of the releasing shift key to make
+      // sure key-up event fires correctly in kb-key-base.
+      this.pointerId = enterChordingEvent.pointerId;
+      this.super([event]);
+    },
+
+    out: function(event) {
+      // Sliding off the shift key while chording is treated as a key-up.
+      // Note that we switch to a new keyset on shift keydown, and a finger
+      // movement on the new shift key will trigger this function being
+      // called on the old shift key. We should not end chording in that
+      // case.
+      if (state == KEY_STATES.CHORDING &&
+          event.pointerId == enterChordingEvent.pointerId &&
+          event.target != enterChordingEvent.target) {
+        state = KEY_STATES.UNLOCKED;
+        var detail = this.populateDetails('out');
+        this.fire("key-out", detail);
+      }
+    },
+
+    down: function(event) {
+      // First transition state so that populateDetails generates
+      // correct data.
+      switch (state) {
+        case KEY_STATES.UNLOCKED:
+          state = KEY_STATES.PRESSED;
+          break;
+        case KEY_STATES.TAPPED:
+        case KEY_STATES.LOCKED:
+          state = KEY_STATES.UNLOCKED;
+          break;
+        case KEY_STATES.PRESSED:
+        case KEY_STATES.CHORDING:
+          // We pressed another shift key at the same time,
+          // so ignore second press.
+          return;
+        default:
+          console.error("Undefined shift key state: " + state);
+          break;
+      }
+      enterChordingEvent = event;
+      // Trigger parent behaviour.
+      this.super([event]);
+      this.fire('enable-sel');
+      // Populate double click transition details.
+      var detail = {};
+      detail.char = this.char || this.textContent;
+      detail.toKeyset = this.upperCaseKeysetId;
+      detail.nextKeyset = undefined;
+      detail.callback = this.onDoubleClick;
+      this.fire('enable-dbl', detail);
+    },
+
+    generateLongPressTimer: function() {
+      return this.async(function() {
+        var detail = this.populateDetails();
+        if (state == KEY_STATES.LOCKED) {
+          // We don't care about the longpress if we are already
+          // capitalized.
+          return;
+        } else {
+          state = KEY_STATES.LOCKED;
+          detail.toKeyset = this.upperCaseKeysetId;
+          detail.nextKeyset = undefined;
+        }
+        this.fire('key-longpress', detail);
+      }, null, LONGPRESS_DELAY_MSEC);
+    },
+
+    // @return Whether the shift modifier is currently active.
+    isActive: function() {
+      return state != KEY_STATES.UNLOCKED;
+    },
+
+    /**
+     * Callback function for when a double click is triggered.
+     */
+    onDoubleClick: function() {
+      state = KEY_STATES.LOCKED;
+    },
+
+    /**
+     * Notifies shift key that a non-control key was pressed down.
+     * A control key is defined as one of shift, control or alt.
+     */
+    onNonControlKeyDown: function() {
+      switch (state) {
+        case (KEY_STATES.PRESSED):
+          state = KEY_STATES.CHORDING;
+          // Disable longpress timer.
+          clearTimeout(shiftLongPressTimer);
+          break;
+        default:
+          break;
+      }
+    },
+
+    /**
+     * Notifies key that a non-control keyed was typed.
+     * A control key is defined as one of shift, control or alt.
+     */
+    onNonControlKeyTyped: function() {
+      if (state == KEY_STATES.TAPPED)
+        state = KEY_STATES.UNLOCKED;
+    },
+
+    /**
+     * Callback function for when a space is pressed after punctuation.
+     * @return {Object} The keyset transitions the keyboard should make.
+     */
+    onSpaceAfterPunctuation: function() {
+       var detail = {};
+       detail.toKeyset = this.upperCaseKeysetId;
+       detail.nextKeyset = this.lowerCaseKeysetId;
+       state = KEY_STATES.TAPPED;
+       return detail;
+    },
+
+    populateDetails: function(caller) {
+      var detail = this.super([caller]);
+      switch(state) {
+        case(KEY_STATES.LOCKED):
+          detail.toKeyset = this.upperCaseKeysetId;
+          break;
+        case(KEY_STATES.UNLOCKED):
+          detail.toKeyset = this.lowerCaseKeysetId;
+          break;
+        case(KEY_STATES.PRESSED):
+          detail.toKeyset = this.upperCaseKeysetId;
+          break;
+        case(KEY_STATES.TAPPED):
+          detail.toKeyset = this.upperCaseKeysetId;
+          detail.nextKeyset = this.lowerCaseKeysetId;
+          break;
+        case(KEY_STATES.CHORDING):
+          detail.toKeyset = this.lowerCaseKeysetId;
+          break;
+        default:
+          break;
+      }
+      return detail;
+    },
+
+    /**
+     *  Resets the shift key state.
+     */
+    reset: function() {
+      state = KEY_STATES.UNLOCKED;
+    },
+
+    /**
+     * Overrides longPressTimer for the shift key.
+     */
+    get longPressTimer() {
+      return shiftLongPressTimer;
+    },
+
+    set longPressTimer(timer) {
+      shiftLongPressTimer = timer;
+    },
+
+    get state() {
+      return state;
+    },
+
+    get textKeyset() {
+      switch (state) {
+        case KEY_STATES.UNLOCKED:
+          return this.lowerCaseKeysetId;
+        default:
+          return this.upperCaseKeysetId;
+      }
+    },
+  });
+})();
diff --git a/ui/keyboard/resources/index.html b/ui/keyboard/resources/index.html
index e46e731..505bc11 100644
--- a/ui/keyboard/resources/index.html
+++ b/ui/keyboard/resources/index.html
@@ -9,32 +9,22 @@
   <head>
     <meta charset="UTF-8">
     <link rel="stylesheet" href="main.css">
-    <script src="constants.js"></script>
     <script src="polymer_loader.js"></script>
-    <script src="api_adapter.js"></script>
-    <script src="touch_fuzzing.js"></script>
-    <script src="voice_input.js"></script>
-    <script src="main.js"></script>
-
-    <!-- TODO(kevers): Dynamically load alternative keys based on locale. -->
-    <script src="layouts/latin-accents.js"></script>
-    <script src="layouts/symbol-altkeys.js"></script>
-
-    <link rel="import" href="elements/kb-altkey-container.html">
-    <link rel="import" href="elements/kb-altkey.html">
-    <link rel="import" href="elements/kb-altkey-data.html">
-    <link rel="import" href="elements/kb-altkey-set.html">
-    <link rel="import" href="elements/kb-key-codes.html">
-    <link rel="import" href="elements/kb-key-base.html">
-    <link rel="import" href="elements/kb-key.html">
-    <link rel="import" href="elements/kb-keyboard.html">
-    <link rel="import" href="elements/kb-keyset.html">
-    <link rel="import" href="elements/kb-modifier-key.html">
-    <link rel="import" href="elements/kb-row.html">
-    <link rel="import" href="elements/kb-shift-key.html">
-    <link rel="import" href="elements/kb-key-sequence.html">
-    <link rel="import" href="elements/kb-key-import.html">
-    <link rel="import" href="elements/kb-options-menu.html">
+    <script src="keyboard.js"></script>
+    <include src="elements/kb-altkey-container.html">
+    <include src="elements/kb-altkey.html">
+    <include src="elements/kb-altkey-data.html">
+    <include src="elements/kb-altkey-set.html">
+    <include src="elements/kb-key-codes.html">
+    <include src="elements/kb-key-base.html">
+    <include src="elements/kb-key.html">
+    <include src="elements/kb-keyboard.html">
+    <include src="elements/kb-keyset.html">
+    <include src="elements/kb-modifier-key.html">
+    <include src="elements/kb-row.html">
+    <include src="elements/kb-shift-key.html">
+    <include src="elements/kb-key-sequence.html">
+    <include src="elements/kb-key-import.html">
     <!-- New layouts are dynamically loaded on demand. The link elements are
       -- inserted here.
       -->
diff --git a/ui/keyboard/resources/keyboard.js b/ui/keyboard/resources/keyboard.js
new file mode 100644
index 0000000..4fe9fa5
--- /dev/null
+++ b/ui/keyboard/resources/keyboard.js
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+<include src="constants.js"></include>
+<include src="api_adapter.js"></include>
+<include src="touch_fuzzing.js"></include>
+<include src="voice_input.js"></include>
+<include src="main.js"></include>
+//TODO(kevers): Dynamically load alternative keys based on locale.
+<include src="layouts/latin-accents.js"></include>
+<include src="layouts/symbol-altkeys.js"></include>
+<include src="elements/kb-altkey-container.js"></include>
+<include src="elements/kb-altkey-set.js"></include>
+<include src="elements/kb-key-codes.js"></include>
+<include src="elements/kb-key-sequence.js"></include>
+<include src="elements/kb-altkey-data.js"></include>
+<include src="elements/kb-key-base.js"></include>
+<include src="elements/kb-key.js"></include>
+<include src="elements/kb-keyset.js"></include>
+<include src="elements/kb-row.js"></include>
+<include src="elements/kb-altkey.js"></include>
+<include src="elements/kb-keyboard.js"></include>
+<include src="elements/kb-key-import.js"></include>
+<include src="elements/kb-modifier-key.js"></include>
+<include src="elements/kb-shift-key.js"></include>
+
diff --git a/ui/keyboard/resources/layouts/qwerty.html b/ui/keyboard/resources/layouts/qwerty.html
index 678edf3..6c7e61e 100644
--- a/ui/keyboard/resources/layouts/qwerty.html
+++ b/ui/keyboard/resources/layouts/qwerty.html
@@ -5,7 +5,7 @@
   -->
 
 <template>
-  <kb-keyset id="qwerty-upper" align="stretch">
+  <kb-keyset id="qwerty-upper" pitch="10 20">
     <kb-row>
       <kb-key-sequence keys="QWERTYUIOP" hintTexts="1234567890">
       </kb-key-sequence>
@@ -38,7 +38,7 @@
     </kb-altkey-container>
   </kb-keyset>
 
-  <kb-keyset id="qwerty-lower" isDefault=true align="stretch">
+  <kb-keyset id="qwerty-lower" isDefault=true pitch="10 20">
     <kb-row>
       <kb-key-sequence keys="qwertyuiop" hintTexts="1234567890">
       </kb-key-sequence>
@@ -71,7 +71,7 @@
     </kb-altkey-container>
   </kb-keyset>
 
-  <kb-keyset id="qwerty-symbol" align="stretch">
+  <kb-keyset id="qwerty-symbol" pitch="10 20">
     <kb-row>
       <kb-key-sequence keys="1234567890"></kb-key-sequence>
       <kb-key class="dark" char="&#x0008;" align="right" image="backspace"
@@ -104,7 +104,7 @@
     </kb-altkey-container>
   </kb-keyset>
 
-  <kb-keyset id="qwerty-more" align="stretch">
+  <kb-keyset id="qwerty-more" pitch="10 20">
     <kb-row>
       <kb-key-sequence
           keys="~`|&#x2022;&radic;&Pi;&divide;&times;&para;&Delta;">
diff --git a/ui/keyboard/resources/layouts/system-qwerty.html b/ui/keyboard/resources/layouts/system-qwerty.html
index 9afdd54..9b2458b 100644
--- a/ui/keyboard/resources/layouts/system-qwerty.html
+++ b/ui/keyboard/resources/layouts/system-qwerty.html
@@ -4,8 +4,6 @@
   -- found in the LICENSE file.
   -->
 
-<link id="function-key-row" rel="import" href="function-key-row.html">
-
 <template>
   <kb-keyset id="system-qwerty-upper" align="center">
     <kb-row>
@@ -53,7 +51,7 @@
           weight="75"> </kb-key>
       <kb-key class="cursor dark" repeat char="Arrow-Right" image="right"
           weight="75"></kb-key>
-      <kb-hide-keyboard-key image="hide-keyboard" showMenu=false stretch>
+      <kb-hide-keyboard-key image="hide-keyboard" stretch>
       </kb-hide-keyboard-key>
     </kb-row>
     <kb-altkey-container hidden>
@@ -103,7 +101,7 @@
           weight="75"> </kb-key>
       <kb-key class="cursor dark" repeat char="Arrow-Right" image="right"
           weight="75"></kb-key>
-      <kb-hide-keyboard-key image="hide-keyboard" showMenu=false stretch>
+      <kb-hide-keyboard-key image="hide-keyboard" stretch>
       </kb-hide-keyboard-key>
     </kb-row>
     <kb-altkey-container hidden>
diff --git a/ui/keyboard/resources/layouts/webui_qwerty.html b/ui/keyboard/resources/layouts/webui_qwerty.html
deleted file mode 100644
index 2763307..0000000
--- a/ui/keyboard/resources/layouts/webui_qwerty.html
+++ /dev/null
@@ -1,122 +0,0 @@
-<!--
-  -- Copyright 2013 The Chromium Authors. All rights reserved.
-  -- Use of this source code is governed by a BSD-style license that can be
-  -- found in the LICENSE file.
-  -->
-
-<template>
-  <kb-keyset id="qwerty-upper">
-    <kb-row class="top">
-      <kb-key>Q</kb-key><kb-key>W</kb-key><kb-key>E</kb-key><kb-key>R</kb-key>
-      <kb-key>T</kb-key><kb-key>Y</kb-key><kb-key>U</kb-key>
-      <kb-key>I</kb-key><kb-key>O</kb-key><kb-key>P</kb-key>
-    </kb-row>
-    <kb-row>
-      <div class="half-key-spacer"></div>
-      <kb-key>A</kb-key><kb-key>S</kb-key><kb-key>D</kb-key><kb-key>F</kb-key>
-      <kb-key>G</kb-key><kb-key>H</kb-key><kb-key>J</kb-key><kb-key>K</kb-key>
-      <kb-key>L</kb-key>
-      <div class="half-key-spacer"></div>
-    </kb-row>
-    <kb-row>
-      <kb-shift-key class="padded-left-special" weight="1.4">shift</kb-shift-key>
-      <kb-key>Z</kb-key><kb-key>X</kb-key><kb-key>C</kb-key><kb-key>V</kb-key>
-      <kb-key>B</kb-key><kb-key>N</kb-key><kb-key>M</kb-key>
-      <kb-key class="backspace padded-right-special dark" char="&#x0008;" repeat>delete</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid">?123</kb-key>
-      <kb-key class="microphone dark" char="Microphone"></kb-key>
-      <kb-key class="dark">,</kb-key>
-      <kb-key class="space dark" char=" "></kb-key>
-      <kb-key class="dark">.</kb-key>
-      <kb-key class="return dark" char="&#000A;">enter</kb-key>
-    </kb-row>
-    <kb-altkey-container hidden>
-    </kb-altkey-container>
-  </kb-keyset>
-
-  <kb-keyset id="qwerty-lower" isDefault=true>
-    <kb-row class="top">
-      <kb-key>q</kb-key><kb-key>w</kb-key><kb-key>e</kb-key><kb-key>r</kb-key>
-      <kb-key>t</kb-key><kb-key>y</kb-key><kb-key>u</kb-key>
-      <kb-key>i</kb-key><kb-key>o</kb-key><kb-key>p</kb-key>
-    </kb-row>
-    <kb-row>
-      <div class="half-key-spacer"></div>
-      <kb-key>a</kb-key><kb-key>s</kb-key><kb-key>d</kb-key><kb-key>f</kb-key>
-      <kb-key>g</kb-key><kb-key>h</kb-key><kb-key>j</kb-key><kb-key>k</kb-key>
-      <kb-key>l</kb-key>
-      <div class="half-key-spacer"></div>
-    </kb-row>
-    <kb-row>
-      <kb-shift-key class="padded-left-special" weight="1.4">shift</kb-shift-key>
-      <kb-key>z</kb-key><kb-key>x</kb-key><kb-key>c</kb-key><kb-key>v</kb-key>
-      <kb-key>b</kb-key><kb-key>n</kb-key><kb-key>m</kb-key>
-      <kb-key class="backspace padded-right-special dark" char="&#x0008;" repeat>delete</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-key class="symbol dark" toKeyset="down:symbol" char="Invalid">?123</kb-key>
-      <kb-key class="microphone dark" char="Microphone"></kb-key>
-      <kb-key class="dark">,</kb-key>
-      <kb-key class="space dark" char=" "></kb-key>
-      <kb-key class="dark">.</kb-key>
-      <kb-key class='return dark' char="&#x000A;">enter</kb-key>
-    </kb-row>
-    <kb-altkey-container hidden>
-    </kb-altkey-container>
-  </kb-keyset>
-
-  <kb-keyset id="qwerty-symbol">
-    <kb-row class="top">
-      <kb-key>1</kb-key><kb-key>2</kb-key><kb-key>3</kb-key><kb-key>4</kb-key>
-      <kb-key>5</kb-key><kb-key>6</kb-key><kb-key>7</kb-key><kb-key>8</kb-key>
-      <kb-key>9</kb-key><kb-key>0</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-key>@</kb-key><kb-key>$</kb-key><kb-key>&</kb-key><kb-key>:</kb-key><kb-key>;</kb-key>
-      <kb-key>/</kb-key><kb-key>(</kb-key><kb-key>)</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-key class="left-more padded-left-special dark" toKeyset="down:more" char="Invalid">more</kb-key>
-      <kb-key>"</kb-key><kb-key>'</kb-key><kb-key>-</kb-key>
-      <kb-key>+</kb-key><kb-key>!</kb-key><kb-key>?</kb-key>
-      <kb-key class="backspace padded-right-special dark" char="&#x0008;" repeat>delete</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-abc-key>abc</kb-abc-key>
-      <kb-key class="microphone dark" char="Microphone"></kb-key>
-      <kb-key class="dark">,</kb-key>
-      <kb-key class="space dark" char=" "></kb-key>
-      <kb-key class="dark">.</kb-key>
-      <kb-key class='return dark' char="&#x000A;">enter</kb-key>
-    </kb-row>
-  </kb-keyset>
-
-  <kb-keyset id="qwerty-more">
-    <kb-row class="top">
-      <kb-key>&#x20AC;</kb-key><kb-key>&#x00A3;</kb-key><kb-key>&#x00A2;</kb-key>
-      <kb-key>&#x2022;</kb-key><kb-key>&#x00B6;</kb-key><kb-key>|</kb-key>
-      <kb-key>{</kb-key><kb-key>}</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-key class="tab padded-left-special dark" char="&#x0009;">tab</kb-key>
-      <kb-key>#</kb-key><kb-key>%</kb-key><kb-key>^</kb-key><kb-key>*</kb-key>
-      <kb-key>\</kb-key><kb-key>&#x003C;</kb-key><kb-key>&#x003E;</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-key class="left-more padded-left-special dark" toKeyset="down:symbol" char="Invalid">?123</kb-key>
-      <kb-key>`</kb-key><kb-key>~</kb-key><kb-key>_</kb-key><kb-key>=</kb-key>
-      <kb-key>[</kb-key><kb-key>]</kb-key>
-      <kb-key class="backspace padded-right-special dark" char="&#x0008;" repeat>delete</kb-key>
-    </kb-row>
-    <kb-row>
-      <kb-abc-key>abc</kb-abc-key>
-      <kb-key class="microphone dark" char="Microphone"></kb-key>
-      <kb-key class="dark">,</kb-key>
-      <kb-key class="space dark" char=" "></kb-key>
-      <kb-key class="dark">.</kb-key>
-      <kb-key class='return dark' char="&#x000A;">enter</kb-key>
-    </kb-row>
-  </kb-keyset>
-</template>
diff --git a/ui/keyboard/resources/main.css b/ui/keyboard/resources/main.css
index b96ac07..2c5b621 100644
--- a/ui/keyboard/resources/main.css
+++ b/ui/keyboard/resources/main.css
@@ -18,20 +18,72 @@
   color: lightblue;
 }
 
-/** TODO(rsadam@): Use different assets for caps-lock and highlight **/
-.caps-locked kb-shift-key.dark .key,
-/**
-* Controls whether the shift key should be highlighted or not.
-* Only highlights if we are in the upper keyset, but not capslocked.
-*/
-kb-keyboard:not(.caps-locked)[keyset=upper] kb-shift-key .key{
+kb-keyboard[keyset="upper"] kb-shift-key.dark /shadow-deep/ .key {
   background-image: url('images/shift-filled.svg');
 }
 
-kb-keyboard:not(.caps-locked)[keyset=lower] kb-shift-key .key{
+kb-keyboard[keyset="lower"] kb-shift-key /shadow-deep/ .key {
   background-image: url('images/shift.svg');
 }
 
+/**
+* Controls whether the shift key should be highlighted or not.
+*/
+kb-keyboard.caps-locked kb-shift-key.dark /shadow-deep/
+    .shift-light {
+  -webkit-box-shadow: 0 1px 1px rgba(213, 213, 213, 0.5),
+    0 -1px 1px rgba(213, 213, 213, 0.5);
+  background-image: -webkit-linear-gradient(#d5d5d5, #d5d5d5);
+  border: none;
+  height: 0.2em;
+}
+kb-keyboard.caps-locked kb-shift-key.dark /shadow-deep/
+    .shift-light-wrapper {
+  bottom: 2px;
+}
+
+kb-keyboard.ctrl-active kb-modifier-key[char=Ctrl],
+kb-keyboard.ctrl-active kb-modifier-key[char=Ctrl]  {
+  color: lightblue;
+}
+
+/** TODO(rsadam@): Move these rules to kb-row once we uprev to latest Polymer.*/
+kb-row:nth-child(2) kb-key:not(.dark):not(.active){
+  -webkit-box-shadow: inset 0px 1px #666666, inset 0px -1px #4c4c4c;
+  background-image: -webkit-linear-gradient(#5a5a5a, #515151);
+  background-size: cover;
+  border-bottom-color: #414141;
+  border-top-color: #7f7f7f;
+}
+
+kb-row:nth-child(3) kb-key:not(.dark):not(.active){
+  -webkit-box-shadow: inset 0px 1px #5d5d5d, inset 0px -1px #444444;
+  background-image: -webkit-linear-gradient(#505050, #494949);
+  background-size: cover;
+  border-bottom-color: #3a3a3a;
+  border-top-color: #787878;
+}
+
+kb-row:nth-child(n+3) kb-key:not(.dark):not(.active){
+  -webkit-box-shadow: inset 0px 1px #565656, inset 0px -1px #434343;
+  background-image: -webkit-linear-gradient(#484848, #474747);
+  background-size: cover;
+  border-bottom-color: #393939;
+  border-top-color: #717171;
+}
+
+kb-row:nth-child(2) kb-key:not([invert]) /shadow-deep/ .hint {
+  color: #2C2C2C;
+}
+
+kb-row:nth-child(3) kb-key:not([invert]) /shadow-deep/ .hint {
+  color: #272727;
+}
+
+kb-row:nth-child(n+3) kb-key:not([invert]) /shadow-deep/ .hint {
+  color: #232323;
+}
+
 .dark {
   font-size: 70%;
 }
@@ -50,16 +102,3 @@
   border-bottom-color: #5b5b5b;
   border-top-color: #a4a4a4;
 }
-
-/**
- * The microphone key is handled separately from other images since the image
- * displayed changes depending on whether it's pressed or not.
- */
-.microphone .key {
-  background-image: url('images/microphone.svg');
-  background-position: 10%;
-}
-
-.audio .microphone .key {
-  background-image: url('images/microphone-green.svg');
-}
diff --git a/ui/keyboard/resources/main.js b/ui/keyboard/resources/main.js
index bf255d1..dbfa81f 100644
--- a/ui/keyboard/resources/main.js
+++ b/ui/keyboard/resources/main.js
@@ -1,4 +1,4 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 (function(exports) {
diff --git a/ui/keyboard/resources/touch_fuzzing.js b/ui/keyboard/resources/touch_fuzzing.js
index a2789e9..f610dbe 100644
--- a/ui/keyboard/resources/touch_fuzzing.js
+++ b/ui/keyboard/resources/touch_fuzzing.js
@@ -55,7 +55,8 @@
       // row-centric.
       var splits = findSplits(this.keys, Orientation.HORIZONTAL);
       this.tree = createBinaryTree(0, splits.length - 1, splits);
-      this.tree.populate(this.keys);
+      if (this.tree)
+        this.tree.populate(this.keys);
     },
 
     /**
diff --git a/ui/keyboard/resources/webui/api_adapter.js b/ui/keyboard/resources/webui/api_adapter.js
deleted file mode 100644
index 206f60d..0000000
--- a/ui/keyboard/resources/webui/api_adapter.js
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-function insertText(text) {
-  chrome.send('insertText', [ text ]);
-}
-
-function sendKeyEvent(event) {
-  chrome.send('sendKeyEvent', [ event ]);
-}
-
-function hideKeyboard() {
-  chrome.send('hideKeyboard');
-}
-
-function keyboardLoaded() {
-  chrome.send('keyboardLoaded');
-}
-
-(function(exports) {
-  /**
-   * An array to save callbacks of each request.
-   * @type {Array.<function(Object)>}
-   */
-  var requestIdCallbackMap = [];
-
-  /**
-   * An incremental integer that represents a unique requestId.
-   * @type {number}
-   */
-  var requestId = 0;
-
-  /**
-   * Called when a text input box gets focus.
-   * @param {object} inputContext Describes an input context. It only contains
-   *     the type of text input box at present and only "password", "number" and
-   *     "text" are supported.
-   */
-  function OnTextInputBoxFocused(inputContext) {
-    // Do not want to use the system keyboard for passwords in webui.
-    if (inputContext.type == 'password')
-      inputContext.type = 'text';
-    keyboard.inputTypeValue = inputContext.type;
-  }
-
-  /**
-   * Gets the context of the focused input field. The context is returned as a
-   * paramter in the |callback|.
-   * @param {function(Object)} callback The callback function after the webui
-   *     function finished.
-   * @return {number} The ID of the new request.
-   */
-  function GetInputContext(callback) {
-    var id = requestId;
-    requestIdCallbackMap[id] = callback;
-    chrome.send('getInputContext', [ id ]);
-    requestId++;
-    return id;
-  }
-
-  /**
-   * Cancel the callback specified by requestId.
-   * @param {number} requestId The requestId of the callback that about to
-   *     cancel.
-   */
-  function CancelRequest(requestId) {
-    requestIdCallbackMap[requestId] = undefined;
-  }
-
-  /**
-   * Webui function callback. Any call to chrome.send('getInputContext', [id])
-   * should trigger this function being called with the parameter
-   * inputContext.requestId == id.
-   * @param {Object} inputContext The context of focused input field. Note we
-   *     only have type(input box type) and requestId fields now.
-   */
-  function GetInputContextCallback(inputContext) {
-    var requestId = inputContext.requestId;
-    if (!requestIdCallbackMap[requestId])
-      return;
-    requestIdCallbackMap[requestId](inputContext);
-  }
-
-  exports.OnTextInputBoxFocused = OnTextInputBoxFocused;
-  exports.getInputContext = GetInputContext;
-  exports.cancelRequest = CancelRequest;
-  exports.GetInputContextCallback = GetInputContextCallback;
-})(this);
diff --git a/ui/keyboard/resources/webui/constants.js b/ui/keyboard/resources/webui/constants.js
deleted file mode 100644
index 94ccfb2..0000000
--- a/ui/keyboard/resources/webui/constants.js
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-/**
- * Aspect ratio of keyboard.
- * @type {number}
- */
-var ASPECT_RATIO = 2.0;
-
-/**
- * Ratio of key height and font size.
- * @type {number}
- */
-var FONT_SIZE_RATIO = 2;
-
-/**
- * The number of rows in each keyset.
- * @type {number}
- */
-// TODO(bshe): The number of rows should equal to the number of kb-row elements
-// in kb-keyset. Remove this variable once figure out how to calculate the
-// number from keysets.
-
-var ROW_LENGTH = 4;
diff --git a/ui/keyboard/resources/webui/main.css b/ui/keyboard/resources/webui/main.css
deleted file mode 100644
index e14611d..0000000
--- a/ui/keyboard/resources/webui/main.css
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- Copyright (c) 2013 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
-*/
-
-body {
-  -webkit-box-pack: center;
-  -webkit-user-select: none;
-  background-color: #0b0b0b;
-  display: -webkit-box;
-  margin: 0;
-  overflow: hidden;
-  padding: 0;
-}
-
-kb-keyboard {
-  -webkit-box-orient: vertical;
-  display: -webkit-box;
-}
-
-kb-abc-key,
-kb-shift-key,
-kb-key {
-  background-color: #3b3b3e;
-  background-position: center center;
-  background-repeat: no-repeat;
-  background-size: contain;
-  border-top: 2px solid #4b4b4e;
-  border-radius: 1px;
-  color: #ffffff;
-  display: -webkit-box;
-  font-family: 'Open Sans', sans-serif;
-  font-weight: 600;
-  margin-left: 0.2em;
-  position: relative;
-}
-
-kb-abc-key::x-key,
-kb-shift-key::x-key,
-kb-key::x-key {
-  bottom: 0;
-  height: 1.2em;
-  left: 0;
-  margin: auto;
-  padding-left: 0.5em;
-  padding-right: 0.5em;
-  position: absolute;
-  right: 0;
-  top: 0;
-}
-
-kb-key::x-hinttext {
-  color: #7c7c7c;
-  font-size: 70%;
-  position: absolute;
-  right: 7%;
-  top: 5%;
-}
-
-kb-key::x-key[inverted] {
-  color: #7c7c7c;
-}
-
-kb-key::x-hinttext[inverted] {
-  color: #ffffff;
-}
-
-kb-abc-key.dark,
-kb-shift-key.dark,
-kb-key.dark {
-  background-color: #2a2a2c;
-  border-top: 2px solid #3a3a3c;
-}
-
-kb-altkey::x-key {
-  bottom: 0;
-  height: 1.2em;
-  left: 0;
-  margin: auto;
-  position: absolute;
-  right: 0;
-  top: 0;
-  text-align: center;
-}
-
-/* Left and right-side special keys with a character letter next to them need
- * additional padding.
- * */
-kb-abc-key.padded-left-special,
-kb-shift-key.padded-left-special,
-kb-key.padded-left-special {
-  margin-right: 2px;
-}
-
-kb-abc-key.padded-right-special,
-kb-shift-key.padded-right-special,
-kb-key.padded-right-special {
-  margin-left: 5px;
-}
-
-kb-row.top {
-  margin-top: 5px !important;
-}
-
-.active {
-  background-color: #848490 !important;
-  border-top: 2px solid #A9A9AF !important;
-  /* Do not use box shadow until performance improves
-   * http://code.google.com/p/chromium/issues/detail?id=99045
-   * box-shadow: 0px 0px 15px #fff;
-   * */
-}
-
-.at,
-.com,
-.comma,
-.hide,
-.microphone,
-.period,
-.tab {
-  -webkit-box-flex: 1.3 !important;
-}
-
-.symbol,
-.return {
-  -webkit-box-flex: 1.5 !important;
-}
-
-.backspace {
-  -webkit-box-flex: 1.7 !important;
-}
-
-.left-more {
-  -webkit-box-flex: 1.4 !important;
-}
-
-.right-more {
-  -webkit-box-flex: 1.6 !important;
-}
-
-.space {
-  -webkit-box-flex: 4.8 !important;
-}
-
-.bar {
-  -webkit-box-flex: 0.6 !important;
-}
-
-.backspace,
-.tab,
-.return,
-.shift,
-.left-more,
-.right-more,
-.symbol {
-  font-size: 55%;
-  font-weight: 200;
-}
-
-.microphone {
-  background-image: url('images/microphone.svg');
-}
-
-.audio .microphone {
-  background-image: url('images/microphone-green.svg');
-}
-
-.half-key-spacer {
-  -webkit-box-flex: 0.5;
-  margin-left: 4px;
-}
diff --git a/ui/keyboard/resources/webui_index.html b/ui/keyboard/resources/webui_index.html
deleted file mode 100644
index bdc8116..0000000
--- a/ui/keyboard/resources/webui_index.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE HTML>
-<!--
-  -- Copyright 2013 The Chromium Authors. All rights reserved.
-  -- Use of this source code is governed by a BSD-style license that can be
-  -- found in the LICENSE file.
-  -->
-
-<!--
-  -- To avoid unintentionally break webui keyboard when changing extension
-  -- keyboard, creates this file and uses it as index.html for webui keyboard.
-  -- TODO(bshe): remove this file when dynamic layout loading is fixed
-  -- (http://www.crbug.com/260278).
-  -->
-
-<html>
-  <head>
-    <meta charset="UTF-8">
-    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
-    <link rel="stylesheet" href="main.css">
-    <script src="constants.js"></script>
-    <script src="polymer_loader.js"></script>
-    <script src="api_adapter.js"></script>
-    <script src="voice_input.js"></script>
-    <link rel="import" href="elements/kb-altkey.html">
-    <link rel="import" href="elements/kb-altkey-container.html">
-    <link rel="import" href="elements/kb-altkey-data.html">
-    <link rel="import" href="elements/kb-altkey-set.html">
-    <link rel="import" href="elements/kb-key-codes.html">
-    <link rel="import" href="elements/kb-key-base.html">
-    <link rel="import" href="elements/kb-key.html">
-    <link rel="import" href="elements/kb-keyboard.html">
-    <link rel="import" href="elements/kb-keyset.html">
-    <link rel="import" href="elements/kb-row.html">
-    <link rel="import" href="elements/kb-shift-key.html">
-    <link id="numeric" rel="import" href="layouts/numeric.html">
-    <link id="qwerty" rel="import" href="layouts/qwerty.html">
-    <!--TODO(stevet): Import 'Open Sans' font. -->
-    <script src="main.js"></script>
-    <script src="layouts/latin-accents.js"></script>
-  </head>
-  <body>
-    <kb-keyboard id="keyboard" touch-action="none" layout="qwerty">
-    </kb-keyboard>
-  </body>
-</html>
diff --git a/ui/message_center/message_center.gyp b/ui/message_center/message_center.gyp
index e3ea206..8fc29a6 100644
--- a/ui/message_center/message_center.gyp
+++ b/ui/message_center/message_center.gyp
@@ -73,8 +73,6 @@
         'notifier_settings.h',
         'views/bounded_label.cc',
         'views/bounded_label.h',
-        'views/bounded_scroll_view.cc',
-        'views/bounded_scroll_view.h',
         'views/constants.h',
         'views/message_bubble_base.cc',
         'views/message_bubble_base.h',
@@ -201,11 +199,6 @@
         'test/run_all_unittests.cc',
       ],
       'conditions': [
-        ['desktop_linux == 1 or chromeos == 1 or OS=="ios"', {
-         'dependencies': [
-           '../base/strings/ui_strings.gyp:ui_unittest_strings',
-         ],
-        }],
         ['OS=="mac"', {
           'dependencies': [
             '../gfx/gfx.gyp:gfx_test_support',
@@ -221,7 +214,6 @@
           ],
           'sources': [
             'views/bounded_label_unittest.cc',
-            'views/bounded_scroll_view_unittest.cc',
             'views/message_center_view_unittest.cc',
             'views/message_popup_collection_unittest.cc',
             'views/notifier_settings_view_unittest.cc',
diff --git a/ui/message_center/views/bounded_scroll_view.cc b/ui/message_center/views/bounded_scroll_view.cc
deleted file mode 100644
index 7170105..0000000
--- a/ui/message_center/views/bounded_scroll_view.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/message_center/views/bounded_scroll_view.h"
-
-#include <algorithm>
-
-#include "ui/gfx/insets.h"
-#include "ui/gfx/size.h"
-#include "ui/message_center/message_center_style.h"
-#include "ui/views/background.h"
-#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
-
-namespace message_center {
-
-BoundedScrollView::BoundedScrollView(int min_height, int max_height)
-    : min_height_(min_height), max_height_(max_height) {
-  set_notify_enter_exit_on_child(true);
-  set_background(
-      views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
-  SetVerticalScrollBar(new views::OverlayScrollBar(false));
-}
-
-gfx::Size BoundedScrollView::GetPreferredSize() {
-  gfx::Size size = contents()->GetPreferredSize();
-  size.SetToMax(gfx::Size(size.width(), min_height_));
-  size.SetToMin(gfx::Size(size.width(), max_height_));
-  gfx::Insets insets = GetInsets();
-  size.Enlarge(insets.width(), insets.height());
-  return size;
-}
-
-int BoundedScrollView::GetHeightForWidth(int width) {
-  gfx::Insets insets = GetInsets();
-  width = std::max(0, width - insets.width());
-  int height = contents()->GetHeightForWidth(width) + insets.height();
-  return std::min(std::max(height, min_height_), max_height_);
-}
-
-void BoundedScrollView::Layout() {
-  int content_width = width();
-  int content_height = contents()->GetHeightForWidth(content_width);
-  if (content_height > height()) {
-    content_width = std::max(content_width - GetScrollBarWidth(), 0);
-    content_height = contents()->GetHeightForWidth(content_width);
-  }
-  if (contents()->bounds().size() != gfx::Size(content_width, content_height))
-    contents()->SetBounds(0, 0, content_width, content_height);
-  views::ScrollView::Layout();
-}
-
-}  // namespace
diff --git a/ui/message_center/views/bounded_scroll_view.h b/ui/message_center/views/bounded_scroll_view.h
deleted file mode 100644
index d3bb82d..0000000
--- a/ui/message_center/views/bounded_scroll_view.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_MESSAGE_CENTER_VIEWS_BOUNDED_SCROLL_VIEW_H_
-#define UI_MESSAGE_CENTER_VIEWS_BOUNDED_SCROLL_VIEW_H_
-
-#include "ui/gfx/size.h"
-#include "ui/message_center/message_center_export.h"
-#include "ui/views/controls/scroll_view.h"
-
-namespace message_center {
-
-// A custom scroll view whose height has a minimum and maximum value and whose
-// scroll bar disappears when not needed.
-class MESSAGE_CENTER_EXPORT BoundedScrollView : public views::ScrollView {
- public:
-  BoundedScrollView(int min_height, int max_height);
-
-  // Overridden from views::View:
-  virtual gfx::Size GetPreferredSize() OVERRIDE;
-  virtual int GetHeightForWidth(int width) OVERRIDE;
-  virtual void Layout() OVERRIDE;
-
- private:
-  int min_height_;
-  int max_height_;
-
-  DISALLOW_COPY_AND_ASSIGN(BoundedScrollView);
-};
-
-}  // namespace message_center
-
-#endif  // UI_MESSAGE_CENTER_VIEWS_BOUNDED_SCROLL_VIEW_H_
diff --git a/ui/message_center/views/bounded_scroll_view_unittest.cc b/ui/message_center/views/bounded_scroll_view_unittest.cc
deleted file mode 100644
index 590114d..0000000
--- a/ui/message_center/views/bounded_scroll_view_unittest.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/message_center/views/bounded_scroll_view.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/size.h"
-#include "ui/views/test/test_views.h"
-
-namespace message_center {
-
-namespace test {
-
-const int kMinHeight = 50;
-const int kMaxHeight = 100;
-
-const int kWidth = 100;
-
-class BoundedScrollViewTest : public testing::Test {
- public:
-  BoundedScrollViewTest() {}
-  virtual ~BoundedScrollViewTest() {}
-
-  virtual void SetUp() OVERRIDE {
-    scroller_.reset(
-        new message_center::BoundedScrollView(kMinHeight, kMaxHeight));
-  }
-
-  virtual void TearDown() OVERRIDE { scroller_.reset(); }
-
- protected:
-  message_center::BoundedScrollView* scroller() { return scroller_.get(); }
-
- private:
-  scoped_ptr<message_center::BoundedScrollView> scroller_;
-};
-
-TEST_F(BoundedScrollViewTest, NormalSizeContentTest) {
-  const int kNormalContentHeight = 75;
-  scroller()->SetContents(
-      new views::StaticSizedView(gfx::Size(kWidth, kNormalContentHeight)));
-
-  EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
-            scroller()->GetPreferredSize());
-
-  scroller()->SizeToPreferredSize();
-  scroller()->Layout();
-
-  EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
-            scroller()->contents()->size());
-  EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), scroller()->size());
-}
-
-TEST_F(BoundedScrollViewTest, ShortContentTest) {
-  const int kShortContentHeight = 10;
-  scroller()->SetContents(
-      new views::StaticSizedView(gfx::Size(kWidth, kShortContentHeight)));
-
-  EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroller()->GetPreferredSize());
-
-  scroller()->SizeToPreferredSize();
-  scroller()->Layout();
-
-  EXPECT_EQ(gfx::Size(kWidth, kShortContentHeight),
-            scroller()->contents()->size());
-  EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroller()->size());
-}
-
-TEST_F(BoundedScrollViewTest, TallContentTest) {
-  const int kTallContentHeight = 1000;
-  scroller()->SetContents(
-      new views::StaticSizedView(gfx::Size(kWidth, kTallContentHeight)));
-
-  EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroller()->GetPreferredSize());
-
-  scroller()->SizeToPreferredSize();
-  scroller()->Layout();
-
-  EXPECT_EQ(gfx::Size(kWidth, kTallContentHeight),
-            scroller()->contents()->size());
-  EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroller()->size());
-}
-
-TEST_F(BoundedScrollViewTest, NeedsScrollBarTest) {
-  // Create a view that will be much taller than it is high.
-  scroller()->SetContents(new views::ProportionallySizedView(1000));
-
-  // Without any width, it will default to 0,0 but be overridden by min height.
-  scroller()->SizeToPreferredSize();
-  EXPECT_EQ(gfx::Size(0, kMinHeight), scroller()->GetPreferredSize());
-
-  gfx::Size new_size(kWidth, scroller()->GetHeightForWidth(kWidth));
-  scroller()->SetSize(new_size);
-  scroller()->Layout();
-
-  int scroll_bar_width = scroller()->GetScrollBarWidth();
-  int expected_width = kWidth - scroll_bar_width;
-  EXPECT_EQ(scroller()->contents()->size().width(), expected_width);
-  EXPECT_EQ(scroller()->contents()->size().height(), 1000 * expected_width);
-  EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroller()->size());
-}
-
-}  // namespace test
-
-}  // namespace message_center
diff --git a/ui/message_center/views/message_center_view.cc b/ui/message_center/views/message_center_view.cc
index 174f4e1..0c31e16 100644
--- a/ui/message_center/views/message_center_view.cc
+++ b/ui/message_center/views/message_center_view.cc
@@ -25,7 +25,6 @@
 #include "ui/message_center/message_center_tray.h"
 #include "ui/message_center/message_center_types.h"
 #include "ui/message_center/message_center_util.h"
-#include "ui/message_center/views/bounded_scroll_view.h"
 #include "ui/message_center/views/message_center_button_bar.h"
 #include "ui/message_center/views/message_view.h"
 #include "ui/message_center/views/message_view_context_menu_controller.h"
@@ -37,6 +36,8 @@
 #include "ui/views/border.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/controls/label.h"
+#include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/widget/widget.h"
@@ -565,8 +566,11 @@
 
   const int button_height = button_bar_->GetPreferredSize().height();
 
-  scroller_ =
-      new BoundedScrollView(kMinScrollViewHeight, max_height - button_height);
+  scroller_ = new views::ScrollView();
+  scroller_->ClipHeightTo(kMinScrollViewHeight, max_height - button_height);
+  scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
+  scroller_->set_background(
+      views::Background::CreateSolidBackground(kMessageCenterBackgroundColor));
 
   scroller_->SetPaintToLayer(true);
   scroller_->SetFillsBoundsOpaquely(false);
diff --git a/ui/message_center/views/message_popup_collection.cc b/ui/message_center/views/message_popup_collection.cc
index 9f02145..252072b 100644
--- a/ui/message_center/views/message_popup_collection.cc
+++ b/ui/message_center/views/message_popup_collection.cc
@@ -506,9 +506,7 @@
 // deferred tasks are even able to run)
 // Then, see if there is vacant space for new toasts.
 void MessagePopupCollection::DoUpdateIfPossible() {
-  // |work_area_| can be set from some tests and those test expectations should
-  // not be reset here.
-  if (!screen_ && work_area_.IsEmpty()) {
+  if (!screen_) {
     gfx::Display display;
     if (!parent_) {
       // On Win+Aura, we don't have a parent since the popups currently show up
@@ -523,8 +521,11 @@
     screen_->AddObserver(this);
 
     display_id_ = display.id();
-    work_area_ = display.work_area();
-    ComputePopupAlignment(work_area_, display.bounds());
+    // |work_area_| can be set already and it should not be overwritten here.
+    if (work_area_.IsEmpty()) {
+      work_area_ = display.work_area();
+      ComputePopupAlignment(work_area_, display.bounds());
+    }
   }
 
   if (defer_counter_ > 0)
diff --git a/ui/native_theme/native_theme.target.darwin-arm.mk b/ui/native_theme/native_theme.target.darwin-arm.mk
index 507239d..19aa7a2 100644
--- a/ui/native_theme/native_theme.target.darwin-arm.mk
+++ b/ui/native_theme/native_theme.target.darwin-arm.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -228,6 +225,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/native_theme/native_theme.target.darwin-mips.mk b/ui/native_theme/native_theme.target.darwin-mips.mk
index 89137c7..07d1385 100644
--- a/ui/native_theme/native_theme.target.darwin-mips.mk
+++ b/ui/native_theme/native_theme.target.darwin-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -226,6 +223,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/native_theme/native_theme.target.darwin-x86.mk b/ui/native_theme/native_theme.target.darwin-x86.mk
index 836017d..0025780 100644
--- a/ui/native_theme/native_theme.target.darwin-x86.mk
+++ b/ui/native_theme/native_theme.target.darwin-x86.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/native_theme/native_theme.target.darwin-x86_64.mk b/ui/native_theme/native_theme.target.darwin-x86_64.mk
new file mode 100644
index 0000000..6eab773
--- /dev/null
+++ b/ui/native_theme/native_theme.target.darwin-x86_64.mk
@@ -0,0 +1,340 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_native_theme_native_theme_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/native_theme/common_theme.cc \
+	ui/native_theme/fallback_theme.cc \
+	ui/native_theme/native_theme.cc \
+	ui/native_theme/native_theme_android.cc \
+	ui/native_theme/native_theme_base.cc \
+	ui/native_theme/native_theme_switches.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNATIVE_THEME_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNATIVE_THEME_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_native_theme_native_theme_gyp
+
+# Alias gyp target name.
+.PHONY: native_theme
+native_theme: ui_native_theme_native_theme_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/native_theme/native_theme.target.linux-arm.mk b/ui/native_theme/native_theme.target.linux-arm.mk
index 507239d..19aa7a2 100644
--- a/ui/native_theme/native_theme.target.linux-arm.mk
+++ b/ui/native_theme/native_theme.target.linux-arm.mk
@@ -95,9 +95,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -228,6 +225,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/native_theme/native_theme.target.linux-mips.mk b/ui/native_theme/native_theme.target.linux-mips.mk
index 89137c7..07d1385 100644
--- a/ui/native_theme/native_theme.target.linux-mips.mk
+++ b/ui/native_theme/native_theme.target.linux-mips.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -214,9 +213,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -226,6 +223,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/native_theme/native_theme.target.linux-x86.mk b/ui/native_theme/native_theme.target.linux-x86.mk
index 836017d..0025780 100644
--- a/ui/native_theme/native_theme.target.linux-x86.mk
+++ b/ui/native_theme/native_theme.target.linux-x86.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -216,9 +215,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -227,6 +224,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/native_theme/native_theme.target.linux-x86_64.mk b/ui/native_theme/native_theme.target.linux-x86_64.mk
new file mode 100644
index 0000000..6eab773
--- /dev/null
+++ b/ui/native_theme/native_theme.target.linux-x86_64.mk
@@ -0,0 +1,340 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_native_theme_native_theme_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/native_theme/common_theme.cc \
+	ui/native_theme/fallback_theme.cc \
+	ui/native_theme/native_theme.cc \
+	ui/native_theme/native_theme_android.cc \
+	ui/native_theme/native_theme_base.cc \
+	ui/native_theme/native_theme_switches.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNATIVE_THEME_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DNATIVE_THEME_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_native_theme_native_theme_gyp
+
+# Alias gyp target name.
+.PHONY: native_theme
+native_theme: ui_native_theme_native_theme_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/ozone/platform/dri/cursor_factory_evdev_dri.cc b/ui/ozone/platform/dri/cursor_factory_evdev_dri.cc
index b11c1a0..fd073ca 100644
--- a/ui/ozone/platform/dri/cursor_factory_evdev_dri.cc
+++ b/ui/ozone/platform/dri/cursor_factory_evdev_dri.cc
@@ -15,6 +15,11 @@
   cursor_bounds_ = gfx::RectF(0, 0, 2560, 1700);  // TODO(spang): Argh!
   cursor_location_ =
       gfx::PointF(cursor_bounds_.width() / 2, cursor_bounds_.height() / 2);
+
+  // The DRI cursor is invisible unless explicitly set. Therefore, set the
+  // pointer cursor on initialization.
+  // TODO(spang): Move this to DRI window initialization.
+  SetCursor(dri->GetAcceleratedWidget(), GetDefaultCursor(kCursorPointer));
 }
 
 CursorFactoryEvdevDri::~CursorFactoryEvdevDri() {}
diff --git a/ui/resources/default_100_percent/common/app_list_experimental_icon.png b/ui/resources/default_100_percent/common/app_list_experimental_icon.png
index 802249c..3d6f702 100644
--- a/ui/resources/default_100_percent/common/app_list_experimental_icon.png
+++ b/ui/resources/default_100_percent/common/app_list_experimental_icon.png
Binary files differ
diff --git a/ui/resources/default_100_percent/win/app_list_user_indicator.png b/ui/resources/default_100_percent/common/app_list_user_indicator.png
similarity index 100%
rename from ui/resources/default_100_percent/win/app_list_user_indicator.png
rename to ui/resources/default_100_percent/common/app_list_user_indicator.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png
index 3f12632..9a7a1e8 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png
index 99f8222..3a2ee91 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png
index 4bf3a6d..a2c7253 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_center.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_center.png
index 21dedd6..5c87bea 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_center.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_center.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_left.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_left.png
index b31d391..5dece07 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_left.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_left.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_right.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_right.png
index 02b8009..5dece07 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_right.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_right.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top.png
index 7237cbb..9a7a1e8 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png
index 099ed24..96bef5e 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png
index 8fb15d6..816deb4 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png
index 754e454..37cfa86 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png
index d901f0c..7bca659 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png
index 43c9ef9..577b607 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png
index 2fbd539..37cfa86 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png
index 7d0f222..37cfa86 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png
index 545b8b5..37cfa86 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png
index bb793ed..bdde2bd 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png
index d114837..952854f 100644
--- a/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png
+++ b/ui/resources/default_100_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/back_arrow.png b/ui/resources/default_100_percent/common/back_arrow.png
index 1c92bc5..0334caf 100644
--- a/ui/resources/default_100_percent/common/back_arrow.png
+++ b/ui/resources/default_100_percent/common/back_arrow.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/pointers/xterm.png b/ui/resources/default_100_percent/common/pointers/xterm.png
index 6f3849f..8c16409 100644
--- a/ui/resources/default_100_percent/common/pointers/xterm.png
+++ b/ui/resources/default_100_percent/common/pointers/xterm.png
Binary files differ
diff --git a/ui/resources/default_100_percent/common/pointers/xterm_horiz.png b/ui/resources/default_100_percent/common/pointers/xterm_horiz.png
index 4939536..2dedbc0 100644
--- a/ui/resources/default_100_percent/common/pointers/xterm_horiz.png
+++ b/ui/resources/default_100_percent/common/pointers/xterm_horiz.png
Binary files differ
diff --git a/ui/resources/default_100_percent/oak.png b/ui/resources/default_100_percent/oak.png
deleted file mode 100644
index 4995479..0000000
--- a/ui/resources/default_100_percent/oak.png
+++ /dev/null
Binary files differ
diff --git a/ui/resources/default_200_percent/common/app_list_experimental_icon.png b/ui/resources/default_200_percent/common/app_list_experimental_icon.png
index c1db726..3c999d6 100644
--- a/ui/resources/default_200_percent/common/app_list_experimental_icon.png
+++ b/ui/resources/default_200_percent/common/app_list_experimental_icon.png
Binary files differ
diff --git a/ui/resources/default_200_percent/win/app_list_user_indicator.png b/ui/resources/default_200_percent/common/app_list_user_indicator.png
similarity index 100%
rename from ui/resources/default_200_percent/win/app_list_user_indicator.png
rename to ui/resources/default_200_percent/common/app_list_user_indicator.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png
index 9971f29..78d9c0f 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png
index 2e4660b..9617a5d 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_left.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png
index 993978d..69b617c 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_bottom_right.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_center.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_center.png
index f8618f1..56d451e 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_center.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_center.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_left.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_left.png
index 1576df2..535837d 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_left.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_left.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_right.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_right.png
index e7654f7..535837d 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_right.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_right.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top.png
index c5d42bb..78d9c0f 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png
index 1ad635b..07231fd 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_left.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png
index 9e3d934..136af2c 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_fill_top_right.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png
index 854c09d..5927847 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png
index 53641d9..6ad0393 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_left.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png
index 80d4e96..f7fb94d 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_bottom_right.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png
index 8ea7bf3..5927847 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_left.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png
index ce2db18..5927847 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_right.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png
index 10c2e6e..5927847 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png
index 01e01fb..84a594d 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_left.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png
index 67f0318..75f5bde 100644
--- a/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png
+++ b/ui/resources/default_200_percent/common/aura_scrollbar_overlay_thumb_stroke_top_right.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/back_arrow.png b/ui/resources/default_200_percent/common/back_arrow.png
index d10b993..e1f212f 100644
--- a/ui/resources/default_200_percent/common/back_arrow.png
+++ b/ui/resources/default_200_percent/common/back_arrow.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/forward_arrow.png b/ui/resources/default_200_percent/common/forward_arrow.png
index a8c9467..85ebf17 100644
--- a/ui/resources/default_200_percent/common/forward_arrow.png
+++ b/ui/resources/default_200_percent/common/forward_arrow.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/pointers/xterm.png b/ui/resources/default_200_percent/common/pointers/xterm.png
index 18ed44e..ecd9b61 100644
--- a/ui/resources/default_200_percent/common/pointers/xterm.png
+++ b/ui/resources/default_200_percent/common/pointers/xterm.png
Binary files differ
diff --git a/ui/resources/default_200_percent/common/pointers/xterm_horiz.png b/ui/resources/default_200_percent/common/pointers/xterm_horiz.png
index 1fd6d1d..b95e553 100644
--- a/ui/resources/default_200_percent/common/pointers/xterm_horiz.png
+++ b/ui/resources/default_200_percent/common/pointers/xterm_horiz.png
Binary files differ
diff --git a/ui/resources/ui_resources.grd b/ui/resources/ui_resources.grd
index 6121bd9..ee03db9 100644
--- a/ui/resources/ui_resources.grd
+++ b/ui/resources/ui_resources.grd
@@ -28,7 +28,7 @@
         <structure type="chrome_scaled_image" name="IDR_APP_LIST_SPEECH_MIC_OFF" file="common/app_list_mic_off.png" />
         <structure type="chrome_scaled_image" name="IDR_APP_LIST_SPEECH_MIC_RECORDING" file="common/app_list_mic_recording.png" />
         <if expr="is_win">
-          <structure type="chrome_scaled_image" name="IDR_APP_LIST_USER_INDICATOR" file="win/app_list_user_indicator.png" />
+          <structure type="chrome_scaled_image" name="IDR_APP_LIST_USER_INDICATOR" file="common/app_list_user_indicator.png" />
         </if>
       </if>
       <if expr="toolkit_views">
@@ -353,9 +353,6 @@
         <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_SETTINGS_HOVER" file="common/notification_settings_hover.png"/>
         <structure type="chrome_scaled_image" name="IDR_NOTIFICATION_SETTINGS_PRESSED" file="common/notification_settings_pressed.png"/>
       </if>
-      <if expr="use_aura">
-        <structure type="chrome_scaled_image" name="IDR_OAK" file="oak.png" />
-      </if>
       <if expr="not is_android and not is_ios">
         <structure type="chrome_scaled_image" name="IDR_OOBE_ACTION_BOX_BUTTON_HOVER" file="cros/action_box_button_hover.png" />
         <structure type="chrome_scaled_image" name="IDR_OOBE_ACTION_BOX_BUTTON_NORMAL" file="cros/action_box_button_normal.png" />
diff --git a/ui/resources/ui_resources.gyp b/ui/resources/ui_resources.gyp
index dbc800c..fa68ace 100644
--- a/ui/resources/ui_resources.gyp
+++ b/ui/resources/ui_resources.gyp
@@ -44,9 +44,6 @@
         '../base/strings/ui_strings.gyp:ui_strings',
         'ui_resources',
       ],
-      'variables': {
-        'repack_path': '../../tools/grit/grit/format/repack.py',
-      },
       'actions': [
         {
           'action_name': 'repack_ui_test_pack',
@@ -57,17 +54,63 @@
               '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/webui_resources.pak',
               '<(SHARED_INTERMEDIATE_DIR)/ui/ui_strings/ui_strings_en-US.pak',
             ],
+            'pak_output': '<(PRODUCT_DIR)/ui_test.pak',
           },
-          'inputs': [
-            '<(repack_path)',
-            '<@(pak_inputs)',
-          ],
-          'outputs': [
-            '<(PRODUCT_DIR)/ui_test.pak',
-          ],
-          'action': ['python', '<(repack_path)', '<@(_outputs)', '<@(pak_inputs)'],
+          'includes': [ '../../build/repack_action.gypi' ],
         },
       ],
+      'conditions': [
+        ['OS != "mac"', {
+          'copies': [
+            {
+              'destination': '<(PRODUCT_DIR)/ui',
+              'files': [
+                '<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources_100_percent.pak',
+              ],
+            },
+          ],
+        }],
+        ['OS == "ios"', {
+          'actions': [
+            {
+              'action_name': 'copy_ui_test_pak',
+              'message': 'Copying ui_test.pak into locale.pak',
+              'inputs': [
+                '<(PRODUCT_DIR)/ui_test.pak',
+              ],
+              'outputs': [
+                '<(PRODUCT_DIR)/ui/en.lproj/locale.pak',
+              ],
+              'action': [
+                'python',
+                '../../build/cp.py',
+                '<@(_inputs)',
+                '<@(_outputs)'
+              ],
+            },
+          ],
+        }],
+        ['OS != "mac" and OS !="ios"', {
+          'actions': [
+            {
+              'action_name': 'copy_ui_test_pak',
+              'message': 'Copying ui_test.pak into en-US.pak',
+              'inputs': [
+                '<(PRODUCT_DIR)/ui_test.pak',
+              ],
+              'outputs': [
+                '<(PRODUCT_DIR)/ui/en-US.pak',
+              ],
+              'action': [
+                'python',
+                '../../build/cp.py',
+                '<@(_inputs)',
+                '<@(_outputs)'
+              ],
+            },
+          ],
+        }],
+      ],
     },
   ],
 }
diff --git a/ui/resources/ui_resources.target.darwin-arm.mk b/ui/resources/ui_resources.target.darwin-arm.mk
index 24f7200..d6fd22d 100644
--- a/ui/resources/ui_resources.target.darwin-arm.mk
+++ b/ui/resources/ui_resources.target.darwin-arm.mk
@@ -32,7 +32,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/promise.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/ui/resources/ui_resources.target.darwin-mips.mk b/ui/resources/ui_resources.target.darwin-mips.mk
index 24f7200..d6fd22d 100644
--- a/ui/resources/ui_resources.target.darwin-mips.mk
+++ b/ui/resources/ui_resources.target.darwin-mips.mk
@@ -32,7 +32,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/promise.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/ui/resources/ui_resources.target.darwin-x86.mk b/ui/resources/ui_resources.target.darwin-x86.mk
index 26d6f31..d6fd22d 100644
--- a/ui/resources/ui_resources.target.darwin-x86.mk
+++ b/ui/resources/ui_resources.target.darwin-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_resources.grd $(LOCAL_PATH)/ui/resources/default_100_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_32.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_64.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_100_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-bar.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-left.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-right.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-value.png $(LOCAL_PATH)/ui/resources/default_100_percent/throbber.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_200_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/throbber.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ui_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
@@ -32,9 +32,9 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/promise.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
@@ -47,7 +47,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_unscaled_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ui_unscaled_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_unscaled_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_unscaled_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_resources/ui_unscaled_resources.rc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h ;
 
diff --git a/ui/resources/ui_resources.target.darwin-x86_64.mk b/ui/resources/ui_resources.target.darwin-x86_64.mk
new file mode 100644
index 0000000..d6fd22d
--- /dev/null
+++ b/ui/resources/ui_resources.target.darwin-x86_64.mk
@@ -0,0 +1,88 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_resources_ui_resources_gyp
+LOCAL_MODULE_STEM := ui_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "ui_resources":
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_resources.grd $(LOCAL_PATH)/ui/resources/default_100_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_32.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_64.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_100_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-bar.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-left.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-right.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-value.png $(LOCAL_PATH)/ui/resources/default_100_percent/throbber.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_200_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/throbber.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ui_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+
+### Rules for action "webui_resources":
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/webui_resources.pak: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
+
+### Rules for action "ui_unscaled_resources":
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_unscaled_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ui_unscaled_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_unscaled_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_unscaled_resources.rc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_200_percent.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/webui_resources.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_unscaled_resources.rc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_resources_ui_resources_gyp
+
+# Alias gyp target name.
+.PHONY: ui_resources
+ui_resources: ui_resources_ui_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/resources/ui_resources.target.linux-arm.mk b/ui/resources/ui_resources.target.linux-arm.mk
index 24f7200..d6fd22d 100644
--- a/ui/resources/ui_resources.target.linux-arm.mk
+++ b/ui/resources/ui_resources.target.linux-arm.mk
@@ -32,7 +32,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/promise.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/ui/resources/ui_resources.target.linux-mips.mk b/ui/resources/ui_resources.target.linux-mips.mk
index 24f7200..d6fd22d 100644
--- a/ui/resources/ui_resources.target.linux-mips.mk
+++ b/ui/resources/ui_resources.target.linux-mips.mk
@@ -32,7 +32,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/promise.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
 	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
diff --git a/ui/resources/ui_resources.target.linux-x86.mk b/ui/resources/ui_resources.target.linux-x86.mk
index 26d6f31..d6fd22d 100644
--- a/ui/resources/ui_resources.target.linux-x86.mk
+++ b/ui/resources/ui_resources.target.linux-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_resources.grd $(LOCAL_PATH)/ui/resources/default_100_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_32.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_64.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_100_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-bar.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-left.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-right.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-value.png $(LOCAL_PATH)/ui/resources/default_100_percent/throbber.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_200_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/throbber.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ui_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
@@ -32,9 +32,9 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
-$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/promise.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
@@ -47,7 +47,7 @@
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_unscaled_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ui_unscaled_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_unscaled_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_unscaled_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/ui/ui_resources/ui_unscaled_resources.rc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h ;
 
diff --git a/ui/resources/ui_resources.target.linux-x86_64.mk b/ui/resources/ui_resources.target.linux-x86_64.mk
new file mode 100644
index 0000000..d6fd22d
--- /dev/null
+++ b/ui/resources/ui_resources.target.linux-x86_64.mk
@@ -0,0 +1,88 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := ui_resources_ui_resources_gyp
+LOCAL_MODULE_STEM := ui_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "ui_resources":
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_resources.grd $(LOCAL_PATH)/ui/resources/default_100_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_32.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/default_favicon_64.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_100_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-bar.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-left.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-border-right.png $(LOCAL_PATH)/ui/resources/default_100_percent/linux/linux-progress-value.png $(LOCAL_PATH)/ui/resources/default_100_percent/throbber.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_mask.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_2_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/close_dialog_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/back_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_center.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_left.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/browser_action_badge_right.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkmark.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/default_favicon.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/forward_arrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/message_close.png $(LOCAL_PATH)/ui/resources/default_200_percent/cros/menu_droparrow.png $(LOCAL_PATH)/ui/resources/default_200_percent/throbber.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ui_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h ;
+
+### Rules for action "webui_resources":
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h: $(LOCAL_PATH)/third_party/jstemplate/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/webui_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_closed_rtl.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open.png $(LOCAL_PATH)/ui/resources/default_100_percent/common/folder_open_rtl.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/blue_button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/button_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_checked_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_focused_pressed.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_hover.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_inactive.png $(LOCAL_PATH)/ui/resources/default_200_percent/common/checkbox_pressed.png $(LOCAL_PATH)/ui/webui/resources/css/alert_overlay.css $(LOCAL_PATH)/ui/webui/resources/css/apps/common.css $(LOCAL_PATH)/ui/webui/resources/css/apps/topbutton_bar.css $(LOCAL_PATH)/ui/webui/resources/css/bubble.css $(LOCAL_PATH)/ui/webui/resources/css/bubble_button.css $(LOCAL_PATH)/ui/webui/resources/css/butter_bar.css $(LOCAL_PATH)/ui/webui/resources/css/chrome_shared.css $(LOCAL_PATH)/ui/webui/resources/css/dialogs.css $(LOCAL_PATH)/ui/webui/resources/css/list.css $(LOCAL_PATH)/ui/webui/resources/css/menu.css $(LOCAL_PATH)/ui/webui/resources/css/menu_button.css $(LOCAL_PATH)/ui/webui/resources/css/overlay.css $(LOCAL_PATH)/ui/webui/resources/css/spinner.css $(LOCAL_PATH)/ui/webui/resources/css/table.css $(LOCAL_PATH)/ui/webui/resources/css/tabs.css $(LOCAL_PATH)/ui/webui/resources/css/throbber.css $(LOCAL_PATH)/ui/webui/resources/css/trash.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css $(LOCAL_PATH)/ui/webui/resources/css/tree.css.js $(LOCAL_PATH)/ui/webui/resources/css/widgets.css $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/2x/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_hover.png $(LOCAL_PATH)/ui/webui/resources/images/apps/button_butter_bar_close_pressed.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_close.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_maximize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_minimize.png $(LOCAL_PATH)/ui/webui/resources/images/apps/topbar_button_settings.png $(LOCAL_PATH)/ui/webui/resources/images/check.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_black.png $(LOCAL_PATH)/ui/webui/resources/images/checkbox_white.png $(LOCAL_PATH)/ui/webui/resources/images/clouds.png $(LOCAL_PATH)/ui/webui/resources/images/disabled_select.png $(LOCAL_PATH)/ui/webui/resources/images/gear.png $(LOCAL_PATH)/ui/webui/resources/images/google-transparent.png $(LOCAL_PATH)/ui/webui/resources/images/help.png $(LOCAL_PATH)/ui/webui/resources/images/question_mark.png $(LOCAL_PATH)/ui/webui/resources/images/select.png $(LOCAL_PATH)/ui/webui/resources/images/spinner.svg $(LOCAL_PATH)/ui/webui/resources/images/throbber.svg $(LOCAL_PATH)/ui/webui/resources/images/trash.png $(LOCAL_PATH)/ui/webui/resources/js/assert.js $(LOCAL_PATH)/ui/webui/resources/js/cr.js $(LOCAL_PATH)/ui/webui/resources/js/cr/event_target.js $(LOCAL_PATH)/ui/webui/resources/js/cr/link_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/alert_overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/array_data_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/autocomplete_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/bubble_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/card_slider.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/command.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/context_menu_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/dialogs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/drag_wrapper.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/focus_outline_manager.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/grid.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_controller.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/list_single_selection_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/menu_item.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/overlay.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/position_util.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/repeating_button.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_column_model.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_header.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_list.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/table/table_splitter.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tabs.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/touch_handler.js $(LOCAL_PATH)/ui/webui/resources/js/cr/ui/tree.js $(LOCAL_PATH)/ui/webui/resources/js/event_tracker.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_process.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template2.js $(LOCAL_PATH)/ui/webui/resources/js/i18n_template_no_process.js $(LOCAL_PATH)/ui/webui/resources/js/jstemplate_compiled.js $(LOCAL_PATH)/ui/webui/resources/js/load_time_data.js $(LOCAL_PATH)/ui/webui/resources/js/local_strings.js $(LOCAL_PATH)/ui/webui/resources/js/media_common.js $(LOCAL_PATH)/ui/webui/resources/js/parse_html_subset.js $(LOCAL_PATH)/ui/webui/resources/js/util.js $(LOCAL_PATH)/ui/webui/resources/js/webui_resource_test.js $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ../webui/resources/webui_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ../webui/resources/webui_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.h: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
+$(gyp_shared_intermediate_dir)/ui/ui_resources/webui_resources.pak: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h ;
+
+### Rules for action "ui_unscaled_resources":
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/ui/resources/ui_unscaled_resources.grd $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ui_unscaled_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/ui/resources; mkdir -p $(gyp_shared_intermediate_dir)/ui/ui_resources/grit $(gyp_shared_intermediate_dir)/ui/ui_resources; python ../../tools/grit/grit.py -i ui_unscaled_resources.grd build -f ../../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/ui/ui_resources" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_unscaled_resources.rc: $(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_resources_map.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_100_percent.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_resources_200_percent.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.cc \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/webui_resources_map.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/webui_resources.pak \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/grit/ui_unscaled_resources.h \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources/ui_unscaled_resources.rc
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_resources_ui_resources_gyp
+
+# Alias gyp target name.
+.PHONY: ui_resources
+ui_resources: ui_resources_ui_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/ui/shell_dialogs/shell_dialogs.target.darwin-arm.mk b/ui/shell_dialogs/shell_dialogs.target.darwin-arm.mk
index 1e5f465..e47c94d 100644
--- a/ui/shell_dialogs/shell_dialogs.target.darwin-arm.mk
+++ b/ui/shell_dialogs/shell_dialogs.target.darwin-arm.mk
@@ -98,9 +98,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +230,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/shell_dialogs/shell_dialogs.target.darwin-mips.mk b/ui/shell_dialogs/shell_dialogs.target.darwin-mips.mk
index 9cf2eea..e4bf11e 100644
--- a/ui/shell_dialogs/shell_dialogs.target.darwin-mips.mk
+++ b/ui/shell_dialogs/shell_dialogs.target.darwin-mips.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/shell_dialogs/shell_dialogs.target.darwin-x86.mk b/ui/shell_dialogs/shell_dialogs.target.darwin-x86.mk
index af48ad6..0fe202e 100644
--- a/ui/shell_dialogs/shell_dialogs.target.darwin-x86.mk
+++ b/ui/shell_dialogs/shell_dialogs.target.darwin-x86.mk
@@ -99,9 +99,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/shell_dialogs/shell_dialogs.target.darwin-x86_64.mk b/ui/shell_dialogs/shell_dialogs.target.darwin-x86_64.mk
new file mode 100644
index 0000000..0fe6dbb
--- /dev/null
+++ b/ui/shell_dialogs/shell_dialogs.target.darwin-x86_64.mk
@@ -0,0 +1,347 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_shell_dialogs_shell_dialogs_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_base_strings_ui_strings_gyp)/ui_strings.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_base_ui_base_jni_headers_gyp)/ui_base_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/shell_dialogs/android/shell_dialogs_jni_registrar.cc \
+	ui/shell_dialogs/base_shell_dialog.cc \
+	ui/shell_dialogs/linux_shell_dialog.cc \
+	ui/shell_dialogs/select_file_dialog.cc \
+	ui/shell_dialogs/select_file_dialog_android.cc \
+	ui/shell_dialogs/select_file_dialog_factory.cc \
+	ui/shell_dialogs/select_file_policy.cc \
+	ui/shell_dialogs/selected_file_info.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSHELL_DIALOGS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSHELL_DIALOGS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_shell_dialogs_shell_dialogs_gyp
+
+# Alias gyp target name.
+.PHONY: shell_dialogs
+shell_dialogs: ui_shell_dialogs_shell_dialogs_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/shell_dialogs/shell_dialogs.target.linux-arm.mk b/ui/shell_dialogs/shell_dialogs.target.linux-arm.mk
index 1e5f465..e47c94d 100644
--- a/ui/shell_dialogs/shell_dialogs.target.linux-arm.mk
+++ b/ui/shell_dialogs/shell_dialogs.target.linux-arm.mk
@@ -98,9 +98,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +230,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/shell_dialogs/shell_dialogs.target.linux-mips.mk b/ui/shell_dialogs/shell_dialogs.target.linux-mips.mk
index 9cf2eea..e4bf11e 100644
--- a/ui/shell_dialogs/shell_dialogs.target.linux-mips.mk
+++ b/ui/shell_dialogs/shell_dialogs.target.linux-mips.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -219,9 +218,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/shell_dialogs/shell_dialogs.target.linux-x86.mk b/ui/shell_dialogs/shell_dialogs.target.linux-x86.mk
index af48ad6..0fe202e 100644
--- a/ui/shell_dialogs/shell_dialogs.target.linux-x86.mk
+++ b/ui/shell_dialogs/shell_dialogs.target.linux-x86.mk
@@ -99,9 +99,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +108,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/shell_dialogs/shell_dialogs.target.linux-x86_64.mk b/ui/shell_dialogs/shell_dialogs.target.linux-x86_64.mk
new file mode 100644
index 0000000..0fe6dbb
--- /dev/null
+++ b/ui/shell_dialogs/shell_dialogs.target.linux-x86_64.mk
@@ -0,0 +1,347 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_shell_dialogs_shell_dialogs_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_base_strings_ui_strings_gyp)/ui_strings.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_base_ui_base_jni_headers_gyp)/ui_base_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/shell_dialogs/android/shell_dialogs_jni_registrar.cc \
+	ui/shell_dialogs/base_shell_dialog.cc \
+	ui/shell_dialogs/linux_shell_dialog.cc \
+	ui/shell_dialogs/select_file_dialog.cc \
+	ui/shell_dialogs/select_file_dialog_android.cc \
+	ui/shell_dialogs/select_file_dialog_factory.cc \
+	ui/shell_dialogs/select_file_policy.cc \
+	ui/shell_dialogs/selected_file_info.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSHELL_DIALOGS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSHELL_DIALOGS_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/app_locale_settings \
+	$(gyp_shared_intermediate_dir)/ui/ui_strings \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_shell_dialogs_shell_dialogs_gyp
+
+# Alias gyp target name.
+.PHONY: shell_dialogs
+shell_dialogs: ui_shell_dialogs_shell_dialogs_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/snapshot/snapshot.target.darwin-arm.mk b/ui/snapshot/snapshot.target.darwin-arm.mk
index 1e52ce3..6d28f20 100644
--- a/ui/snapshot/snapshot.target.darwin-arm.mk
+++ b/ui/snapshot/snapshot.target.darwin-arm.mk
@@ -89,9 +89,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,9 +209,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -222,6 +219,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/snapshot/snapshot.target.darwin-mips.mk b/ui/snapshot/snapshot.target.darwin-mips.mk
index 36376d3..b67cb9e 100644
--- a/ui/snapshot/snapshot.target.darwin-mips.mk
+++ b/ui/snapshot/snapshot.target.darwin-mips.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -100,6 +98,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -208,9 +207,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -220,6 +217,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/snapshot/snapshot.target.darwin-x86.mk b/ui/snapshot/snapshot.target.darwin-x86.mk
index a5574ba..14c3ad7 100644
--- a/ui/snapshot/snapshot.target.darwin-x86.mk
+++ b/ui/snapshot/snapshot.target.darwin-x86.mk
@@ -90,9 +90,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,9 +209,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -221,6 +218,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/snapshot/snapshot.target.darwin-x86_64.mk b/ui/snapshot/snapshot.target.darwin-x86_64.mk
new file mode 100644
index 0000000..a2b38d6
--- /dev/null
+++ b/ui/snapshot/snapshot.target.darwin-x86_64.mk
@@ -0,0 +1,334 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_snapshot_snapshot_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/snapshot/snapshot_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSNAPSHOT_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSNAPSHOT_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_snapshot_snapshot_gyp
+
+# Alias gyp target name.
+.PHONY: snapshot
+snapshot: ui_snapshot_snapshot_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/snapshot/snapshot.target.linux-arm.mk b/ui/snapshot/snapshot.target.linux-arm.mk
index 1e52ce3..6d28f20 100644
--- a/ui/snapshot/snapshot.target.linux-arm.mk
+++ b/ui/snapshot/snapshot.target.linux-arm.mk
@@ -89,9 +89,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,9 +209,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -222,6 +219,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/snapshot/snapshot.target.linux-mips.mk b/ui/snapshot/snapshot.target.linux-mips.mk
index 36376d3..b67cb9e 100644
--- a/ui/snapshot/snapshot.target.linux-mips.mk
+++ b/ui/snapshot/snapshot.target.linux-mips.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -100,6 +98,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -208,9 +207,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -220,6 +217,7 @@
 	'-DPOSIX_AVOID_MMAP' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/snapshot/snapshot.target.linux-x86.mk b/ui/snapshot/snapshot.target.linux-x86.mk
index a5574ba..14c3ad7 100644
--- a/ui/snapshot/snapshot.target.linux-x86.mk
+++ b/ui/snapshot/snapshot.target.linux-x86.mk
@@ -90,9 +90,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -101,6 +99,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -210,9 +209,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -221,6 +218,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/snapshot/snapshot.target.linux-x86_64.mk b/ui/snapshot/snapshot.target.linux-x86_64.mk
new file mode 100644
index 0000000..a2b38d6
--- /dev/null
+++ b/ui/snapshot/snapshot.target.linux-x86_64.mk
@@ -0,0 +1,334 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_snapshot_snapshot_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/snapshot/snapshot_android.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSNAPSHOT_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSNAPSHOT_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/ui \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_snapshot_snapshot_gyp
+
+# Alias gyp target name.
+.PHONY: snapshot
+snapshot: ui_snapshot_snapshot_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/surface/surface.target.darwin-arm.mk b/ui/surface/surface.target.darwin-arm.mk
index 8dbd5b8..68fb464 100644
--- a/ui/surface/surface.target.darwin-arm.mk
+++ b/ui/surface/surface.target.darwin-arm.mk
@@ -93,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +230,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/surface/surface.target.darwin-mips.mk b/ui/surface/surface.target.darwin-mips.mk
index 2daa546..cc1205f 100644
--- a/ui/surface/surface.target.darwin-mips.mk
+++ b/ui/surface/surface.target.darwin-mips.mk
@@ -92,9 +92,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/surface/surface.target.darwin-x86.mk b/ui/surface/surface.target.darwin-x86.mk
index 66ff2b8..2adf8ea 100644
--- a/ui/surface/surface.target.darwin-x86.mk
+++ b/ui/surface/surface.target.darwin-x86.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/surface/surface.target.darwin-x86_64.mk b/ui/surface/surface.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4f77ccf
--- /dev/null
+++ b/ui/surface/surface.target.darwin-x86_64.mk
@@ -0,0 +1,349 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_surface_surface_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/surface/transport_dib.cc \
+	ui/surface/transport_dib_posix.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSURFACE_IMPLEMENTATION' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSURFACE_IMPLEMENTATION' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_surface_surface_gyp
+
+# Alias gyp target name.
+.PHONY: surface
+surface: ui_surface_surface_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/surface/surface.target.linux-arm.mk b/ui/surface/surface.target.linux-arm.mk
index 8dbd5b8..68fb464 100644
--- a/ui/surface/surface.target.linux-arm.mk
+++ b/ui/surface/surface.target.linux-arm.mk
@@ -93,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +230,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/surface/surface.target.linux-mips.mk b/ui/surface/surface.target.linux-mips.mk
index 2daa546..cc1205f 100644
--- a/ui/surface/surface.target.linux-mips.mk
+++ b/ui/surface/surface.target.linux-mips.mk
@@ -92,9 +92,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -105,6 +103,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -218,9 +217,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/surface/surface.target.linux-x86.mk b/ui/surface/surface.target.linux-x86.mk
index 66ff2b8..2adf8ea 100644
--- a/ui/surface/surface.target.linux-x86.mk
+++ b/ui/surface/surface.target.linux-x86.mk
@@ -94,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -106,6 +104,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/ui/surface/surface.target.linux-x86_64.mk b/ui/surface/surface.target.linux-x86_64.mk
new file mode 100644
index 0000000..4f77ccf
--- /dev/null
+++ b/ui/surface/surface.target.linux-x86_64.mk
@@ -0,0 +1,349 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := ui_surface_surface_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	ui/surface/transport_dib.cc \
+	ui/surface/transport_dib_posix.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSURFACE_IMPLEMENTATION' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSURFACE_IMPLEMENTATION' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: ui_surface_surface_gyp
+
+# Alias gyp target name.
+.PHONY: surface
+surface: ui_surface_surface_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/ui/ui_unittests.gyp b/ui/ui_unittests.gyp
index e311335..f09b35b 100644
--- a/ui/ui_unittests.gyp
+++ b/ui/ui_unittests.gyp
@@ -179,9 +179,9 @@
           ],
           # The ResourceBundle unittest expects a locale.pak file to exist in
           # the bundle for English-US. Copy it in from where it was generated
-          # by ui_strings.gyp:ui_unittest_strings.
+          # by ui_resources.gyp:ui_test_pak.
           'mac_bundle_resources': [
-            '<(PRODUCT_DIR)/ui_unittests_strings/en.lproj/locale.pak',
+            '<(PRODUCT_DIR)/ui/en.lproj/locale.pak',
           ],
         }],
         ['OS == "win"', {
@@ -234,11 +234,6 @@
             '../testing/android/native_test.gyp:native_test_native_code',
           ],
         }],
-        ['desktop_linux == 1 or chromeos == 1 or OS == "ios"', {
-          'dependencies': [
-            'base/strings/ui_strings.gyp:ui_unittest_strings',
-          ],
-        }],
         ['use_pango == 1', {
           'dependencies': [
             '../build/linux/system.gyp:fontconfig',
@@ -290,10 +285,6 @@
             'gfx/gfx.gyp:gfx_test_support',
             'ui_unittests_bundle',
           ],
-        }, { # OS!="mac"
-          'dependencies': [
-            'base/strings/ui_strings.gyp:ui_unittest_strings',
-          ],
         }],
         ['use_aura==1 or toolkit_views==1',  {
           'sources': [
diff --git a/ui/views/DEPS b/ui/views/DEPS
index 065ceac..b29fbd8 100644
--- a/ui/views/DEPS
+++ b/ui/views/DEPS
@@ -8,6 +8,7 @@
   "+ui/aura",
   "+ui/base",
   "+ui/compositor",
+  "+ui/display",
   "+ui/events",
   "+ui/gfx",
   "+ui/gl/gl_surface.h",  # To initialize GL for tests.
diff --git a/ui/views/accessibility/native_view_accessibility_win.cc b/ui/views/accessibility/native_view_accessibility_win.cc
index ead097f..10c17ff 100644
--- a/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/ui/views/accessibility/native_view_accessibility_win.cc
@@ -837,7 +837,7 @@
   // in IAccessible2. If any more are added, we may want to
   // add a helper function like MSAAState.
   *states = IA2_STATE_OPAQUE;
-  if (state.state & ui::AX_STATE_EDITABLE)
+  if (state.HasStateFlag(ui::AX_STATE_EDITABLE))
     *states |= IA2_STATE_EDITABLE;
 
   return S_OK;
@@ -1245,40 +1245,40 @@
   }
 }
 
-int32 NativeViewAccessibilityWin::MSAAState(uint32 state) {
+int32 NativeViewAccessibilityWin::MSAAState(const ui::AXViewState& state) {
   // This maps MSAA states for get_accState(). See also the IAccessible2
   // interface get_states().
 
   int32 msaa_state = 0;
-  if (state & ui::AX_STATE_CHECKED)
+  if (state.HasStateFlag(ui::AX_STATE_CHECKED))
     msaa_state |= STATE_SYSTEM_CHECKED;
-  if (state & ui::AX_STATE_COLLAPSED)
+  if (state.HasStateFlag(ui::AX_STATE_COLLAPSED))
     msaa_state |= STATE_SYSTEM_COLLAPSED;
-  if (state & ui::AX_STATE_DEFAULT)
+  if (state.HasStateFlag(ui::AX_STATE_DEFAULT))
     msaa_state |= STATE_SYSTEM_DEFAULT;
-  if (state & ui::AX_STATE_EXPANDED)
+  if (state.HasStateFlag(ui::AX_STATE_EXPANDED))
     msaa_state |= STATE_SYSTEM_EXPANDED;
-  if (state & ui::AX_STATE_HASPOPUP)
+  if (state.HasStateFlag(ui::AX_STATE_HASPOPUP))
     msaa_state |= STATE_SYSTEM_HASPOPUP;
-  if (state & ui::AX_STATE_HOVERED)
+  if (state.HasStateFlag(ui::AX_STATE_HOVERED))
     msaa_state |= STATE_SYSTEM_HOTTRACKED;
-  if (state & ui::AX_STATE_INVISIBLE)
+  if (state.HasStateFlag(ui::AX_STATE_INVISIBLE))
     msaa_state |= STATE_SYSTEM_INVISIBLE;
-  if (state & ui::AX_STATE_LINKED)
+  if (state.HasStateFlag(ui::AX_STATE_LINKED))
     msaa_state |= STATE_SYSTEM_LINKED;
-  if (state & ui::AX_STATE_OFFSCREEN)
+  if (state.HasStateFlag(ui::AX_STATE_OFFSCREEN))
     msaa_state |= STATE_SYSTEM_OFFSCREEN;
-  if (state & ui::AX_STATE_PRESSED)
+  if (state.HasStateFlag(ui::AX_STATE_PRESSED))
     msaa_state |= STATE_SYSTEM_PRESSED;
-  if (state & ui::AX_STATE_PROTECTED)
+  if (state.HasStateFlag(ui::AX_STATE_PROTECTED))
     msaa_state |= STATE_SYSTEM_PROTECTED;
-  if (state & ui::AX_STATE_READ_ONLY)
+  if (state.HasStateFlag(ui::AX_STATE_READ_ONLY))
     msaa_state |= STATE_SYSTEM_READONLY;
-  if (state & ui::AX_STATE_SELECTED)
+  if (state.HasStateFlag(ui::AX_STATE_SELECTED))
     msaa_state |= STATE_SYSTEM_SELECTED;
-  if (state & ui::AX_STATE_FOCUSED)
+  if (state.HasStateFlag(ui::AX_STATE_FOCUSED))
     msaa_state |= STATE_SYSTEM_FOCUSED;
-  if (state & ui::AX_STATE_DISABLED)
+  if (state.HasStateFlag(ui::AX_STATE_DISABLED))
     msaa_state |= STATE_SYSTEM_UNAVAILABLE;
   return msaa_state;
 }
@@ -1339,7 +1339,7 @@
   // Add on any view-specific states.
   ui::AXViewState view_state;
   view->GetAccessibleState(&view_state);
-  msaa_state->lVal |= MSAAState(view_state.state);
+  msaa_state->lVal |= MSAAState(view_state);
 }
 
 base::string16 NativeViewAccessibilityWin::TextForIAccessibleText() {
diff --git a/ui/views/accessibility/native_view_accessibility_win.h b/ui/views/accessibility/native_view_accessibility_win.h
index ffb9a4d..2c8c1fe 100644
--- a/ui/views/accessibility/native_view_accessibility_win.h
+++ b/ui/views/accessibility/native_view_accessibility_win.h
@@ -337,17 +337,17 @@
 
   // Static methods
 
-  // Returns a conversion from the event (as defined in accessibility_types.h)
+  // Returns a conversion from the event (as defined in ax_enums.idl)
   // to an MSAA event.
   static int32 MSAAEvent(ui::AXEvent event);
 
-  // Returns a conversion from the Role (as defined in accessibility_types.h)
+  // Returns a conversion from the Role (as defined in ax_enums.idl)
   // to an MSAA role.
   static int32 MSAARole(ui::AXRole role);
 
-  // Returns a conversion from the State (as defined in accessibility_types.h)
+  // Returns a conversion from the State (as defined in ax_enums.idl)
   // to MSAA states set.
-  static int32 MSAAState(uint32 state);
+  static int32 MSAAState(const ui::AXViewState& state);
 
  protected:
   NativeViewAccessibilityWin();
diff --git a/ui/views/bubble/bubble_delegate.cc b/ui/views/bubble/bubble_delegate.cc
index 7ba8862..9a8fe31 100644
--- a/ui/views/bubble/bubble_delegate.cc
+++ b/ui/views/bubble/bubble_delegate.cc
@@ -85,6 +85,8 @@
 }
 
 BubbleDelegateView::~BubbleDelegateView() {
+  if (GetWidget())
+    GetWidget()->RemoveObserver(this);
   SetLayoutManager(NULL);
   SetAnchorView(NULL);
 }
diff --git a/ui/views/controls/button/checkbox.cc b/ui/views/controls/button/checkbox.cc
index 2389b62..22c5f88 100644
--- a/ui/views/controls/button/checkbox.cc
+++ b/ui/views/controls/button/checkbox.cc
@@ -97,7 +97,8 @@
 void Checkbox::GetAccessibleState(ui::AXViewState* state) {
   LabelButton::GetAccessibleState(state);
   state->role = ui::AX_ROLE_CHECK_BOX;
-  state->state = checked() ? ui::AX_STATE_CHECKED : 0;
+  if (checked())
+    state->AddStateFlag(ui::AX_STATE_CHECKED);
 }
 
 void Checkbox::OnFocus() {
diff --git a/ui/views/controls/button/custom_button.cc b/ui/views/controls/button/custom_button.cc
index 4890b13..0e237a3 100644
--- a/ui/views/controls/button/custom_button.cc
+++ b/ui/views/controls/button/custom_button.cc
@@ -288,13 +288,13 @@
   Button::GetAccessibleState(state);
   switch (state_) {
     case STATE_HOVERED:
-      state->state = ui::AX_STATE_HOVERED;
+      state->AddStateFlag(ui::AX_STATE_HOVERED);
       break;
     case STATE_PRESSED:
-      state->state = ui::AX_STATE_PRESSED;
+      state->AddStateFlag(ui::AX_STATE_PRESSED);
       break;
     case STATE_DISABLED:
-      state->state = ui::AX_STATE_DISABLED;
+      state->AddStateFlag(ui::AX_STATE_DISABLED);
       break;
     case STATE_NORMAL:
     case STATE_COUNT:
diff --git a/ui/views/controls/button/menu_button.cc b/ui/views/controls/button/menu_button.cc
index 0f6a393..83af3c9 100644
--- a/ui/views/controls/button/menu_button.cc
+++ b/ui/views/controls/button/menu_button.cc
@@ -244,7 +244,7 @@
   CustomButton::GetAccessibleState(state);
   state->role = ui::AX_ROLE_POP_UP_BUTTON;
   state->default_action = l10n_util::GetStringUTF16(IDS_APP_ACCACTION_PRESS);
-  state->state = ui::AX_STATE_HASPOPUP;
+  state->AddStateFlag(ui::AX_STATE_HASPOPUP);
 }
 
 void MenuButton::PaintMenuMarker(gfx::Canvas* canvas) {
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc
index f35d119..7145323 100644
--- a/ui/views/controls/label.cc
+++ b/ui/views/controls/label.cc
@@ -291,7 +291,7 @@
 
 void Label::GetAccessibleState(ui::AXViewState* state) {
   state->role = ui::AX_ROLE_STATIC_TEXT;
-  state->state = ui::AX_STATE_READ_ONLY;
+  state->AddStateFlag(ui::AX_STATE_READ_ONLY);
   state->name = text_;
 }
 
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index c4941d8..42cc0cd 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -154,7 +154,7 @@
   label.GetAccessibleState(&state);
   EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, state.role);
   EXPECT_EQ(test_text, state.name);
-  EXPECT_TRUE(ui::AX_STATE_READ_ONLY & state.state);
+  EXPECT_TRUE(state.HasStateFlag(ui::AX_STATE_READ_ONLY));
 }
 
 TEST(LabelTest, SingleLineSizing) {
diff --git a/ui/views/controls/menu/menu_config.cc b/ui/views/controls/menu/menu_config.cc
index c03f193..089d666 100644
--- a/ui/views/controls/menu/menu_config.cc
+++ b/ui/views/controls/menu/menu_config.cc
@@ -27,8 +27,6 @@
       check_width(16),
       check_height(16),
       radio_width(16),
-      radio_height(16),
-      arrow_height(9),
       arrow_width(9),
       gutter_width(0),
       separator_height(11),
diff --git a/ui/views/controls/menu/menu_config.h b/ui/views/controls/menu/menu_config.h
index 1977e8d..3cdbccd 100644
--- a/ui/views/controls/menu/menu_config.h
+++ b/ui/views/controls/menu/menu_config.h
@@ -67,12 +67,10 @@
   int check_width;
   int check_height;
 
-  // Size of the radio bullet.
+  // Width of the radio bullet.
   int radio_width;
-  int radio_height;
 
-  // Size of the submenu arrow.
-  int arrow_height;
+  // Width of the submenu arrow.
   int arrow_width;
 
   // Width of the gutter. Only used if render_gutter is true.
diff --git a/ui/views/controls/menu/menu_config_views.cc b/ui/views/controls/menu/menu_config_views.cc
index 98f2a00..e22f565 100644
--- a/ui/views/controls/menu/menu_config_views.cc
+++ b/ui/views/controls/menu/menu_config_views.cc
@@ -33,8 +33,7 @@
   submenu_horizontal_inset = 1;
   arrow_to_edge_padding = 20;
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  arrow_width =
-      rb.GetImageNamed(IDR_MENU_HIERARCHY_ARROW).ToImageSkia()->width();
+  arrow_width = rb.GetImageNamed(IDR_MENU_HIERARCHY_ARROW).Width();
   gfx::ImageSkia check = GetMenuCheckImage(false);
   check_height = check.height();
   item_min_height = 29;
diff --git a/ui/views/controls/menu/menu_config_win.cc b/ui/views/controls/menu/menu_config_win.cc
index b4d0f9a..4ef5fac 100644
--- a/ui/views/controls/menu/menu_config_win.cc
+++ b/ui/views/controls/menu/menu_config_win.cc
@@ -53,23 +53,18 @@
   extra.menu_check.is_radio = true;
   gfx::Size radio_size = NativeThemeWin::instance()->GetPartSize(
       NativeTheme::kMenuCheck, NativeTheme::kNormal, extra);
-  if (!radio_size.IsEmpty()) {
+  if (!radio_size.IsEmpty())
     radio_width = radio_size.width();
-    radio_height = radio_size.height();
-  } else {
+  else
     radio_width = GetSystemMetrics(SM_CXMENUCHECK);
-    radio_height = GetSystemMetrics(SM_CYMENUCHECK);
-  }
 
   gfx::Size arrow_size = NativeThemeWin::instance()->GetPartSize(
       NativeTheme::kMenuPopupArrow, NativeTheme::kNormal, extra);
   if (!arrow_size.IsEmpty()) {
     arrow_width = arrow_size.width();
-    arrow_height = arrow_size.height();
   } else {
     // Sadly I didn't see a specify metrics for this.
     arrow_width = GetSystemMetrics(SM_CXMENUCHECK);
-    arrow_height = GetSystemMetrics(SM_CYMENUCHECK);
   }
 
   BOOL show_cues;
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 16f2ad3..5d58c69 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -13,7 +13,6 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "ui/aura/client/dispatcher_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
@@ -44,6 +43,7 @@
 #include "ui/views/widget/root_view.h"
 #include "ui/views/widget/tooltip_manager.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/dispatcher_client.h"
 
 #if defined(OS_WIN)
 #include "ui/base/win/internal_constants.h"
diff --git a/ui/views/controls/menu/menu_controller_aura.cc b/ui/views/controls/menu/menu_controller_aura.cc
index 726b8c4..ec402c7 100644
--- a/ui/views/controls/menu/menu_controller_aura.cc
+++ b/ui/views/controls/menu/menu_controller_aura.cc
@@ -5,14 +5,14 @@
 #include "ui/views/controls/menu/menu_controller.h"
 
 #include "base/run_loop.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_client.h"
-#include "ui/aura/client/dispatcher_client.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
 #include "ui/gfx/screen.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/dispatcher_client.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 namespace views {
 
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 386a23e..33c5e44 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -168,12 +168,12 @@
 
   switch (GetType()) {
     case SUBMENU:
-      state->state |= ui::AX_STATE_HASPOPUP;
+      state->AddStateFlag(ui::AX_STATE_HASPOPUP);
       break;
     case CHECKBOX:
     case RADIO:
-      state->state |= GetDelegate()->IsItemChecked(GetCommand()) ?
-          ui::AX_STATE_CHECKED : 0;
+      if (GetDelegate()->IsItemChecked(GetCommand()))
+        state->AddStateFlag(ui::AX_STATE_CHECKED);
       break;
     case NORMAL:
     case SEPARATOR:
@@ -742,13 +742,6 @@
        parent_menu_item_->GetSubmenu()->GetShowSelection(this) &&
        (NonIconChildViewsCount() == 0));
 
-  int icon_x = config.item_left_margin + left_icon_margin_;
-  int top_margin = GetTopMargin();
-  int bottom_margin = GetBottomMargin();
-  int icon_y = top_margin + (height() - config.item_top_margin -
-                             bottom_margin - config.check_height) / 2;
-  int icon_height = config.check_height;
-  int available_height = height() - top_margin - bottom_margin;
   MenuDelegate *delegate = GetDelegate();
   // Render the background. As MenuScrollViewContainer draws the background, we
   // only need the background when we want it to look different, as when we're
@@ -770,21 +763,27 @@
                         ui::NativeTheme::ExtraParams());
   }
 
+  const int icon_x = config.item_left_margin + left_icon_margin_;
+  const int top_margin = GetTopMargin();
+  const int bottom_margin = GetBottomMargin();
+  const int available_height = height() - top_margin - bottom_margin;
+
   // Render the check.
   if (type_ == CHECKBOX && delegate->IsItemChecked(GetCommand())) {
     gfx::ImageSkia check = GetMenuCheckImage(IsSelected());
     // Don't use config.check_width here as it's padded
     // to force more padding (AURA).
-    gfx::Rect check_bounds(icon_x, icon_y, check.width(), icon_height);
+    gfx::Rect check_bounds(icon_x,
+                           top_margin + (available_height - check.height()) / 2,
+                           check.width(),
+                           check.height());
     AdjustBoundsForRTLUI(&check_bounds);
     canvas->DrawImageInt(check, check_bounds.x(), check_bounds.y());
   } else if (type_ == RADIO) {
     gfx::ImageSkia image =
         GetRadioButtonImage(delegate->IsItemChecked(GetCommand()));
     gfx::Rect radio_bounds(icon_x,
-                           top_margin +
-                           (height() - top_margin - bottom_margin -
-                               image.height()) / 2,
+                           top_margin + (available_height - image.height()) / 2,
                            image.width(),
                            image.height());
     AdjustBoundsForRTLUI(&radio_bounds);
@@ -843,14 +842,14 @@
 
   // Render the submenu indicator (arrow).
   if (HasSubmenu()) {
+    gfx::ImageSkia arrow = GetSubmenuArrowImage(IsSelected());
     gfx::Rect arrow_bounds(this->width() - config.arrow_width -
                                config.arrow_to_edge_padding,
-                           top_margin + (available_height -
-                                         config.arrow_width) / 2,
-                           config.arrow_width, height());
+                           top_margin + (available_height - arrow.height()) / 2,
+                           config.arrow_width,
+                           arrow.height());
     AdjustBoundsForRTLUI(&arrow_bounds);
-    canvas->DrawImageInt(GetSubmenuArrowImage(IsSelected()),
-                         arrow_bounds.x(), arrow_bounds.y());
+    canvas->DrawImageInt(arrow, arrow_bounds.x(), arrow_bounds.y());
   }
 }
 
diff --git a/ui/views/controls/menu/menu_scroll_view_container.cc b/ui/views/controls/menu/menu_scroll_view_container.cc
index f01bea6..dfb9ef3 100644
--- a/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -259,7 +259,7 @@
   state->role = ui::AX_ROLE_MENU_BAR;
   // Some AT (like NVDA) will not process focus events on menu item children
   // unless a parent claims to be focused.
-  state->state = ui::AX_STATE_FOCUSED;
+  state->AddStateFlag(ui::AX_STATE_FOCUSED);
 }
 
 void MenuScrollViewContainer::OnBoundsChanged(
diff --git a/ui/views/controls/progress_bar.cc b/ui/views/controls/progress_bar.cc
index f1d7b1f..2049f6e 100644
--- a/ui/views/controls/progress_bar.cc
+++ b/ui/views/controls/progress_bar.cc
@@ -180,7 +180,7 @@
 
 void ProgressBar::GetAccessibleState(ui::AXViewState* state) {
   state->role = ui::AX_ROLE_PROGRESS_INDICATOR;
-  state->state = ui::AX_STATE_READ_ONLY;
+  state->AddStateFlag(ui::AX_STATE_READ_ONLY);
 }
 
 gfx::Size ProgressBar::GetPreferredSize() {
diff --git a/ui/views/controls/progress_bar_unittest.cc b/ui/views/controls/progress_bar_unittest.cc
index 91515a0..b9067b2 100644
--- a/ui/views/controls/progress_bar_unittest.cc
+++ b/ui/views/controls/progress_bar_unittest.cc
@@ -29,7 +29,7 @@
   bar.GetAccessibleState(&state);
   EXPECT_EQ(ui::AX_ROLE_PROGRESS_INDICATOR, state.role);
   EXPECT_EQ(base::string16(), state.name);
-  EXPECT_TRUE(ui::AX_STATE_READ_ONLY & state.state);
+  EXPECT_TRUE(state.HasStateFlag(ui::AX_STATE_READ_ONLY));
 }
 
 }  // namespace views
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc
index 22dbcb0..297be03 100644
--- a/ui/views/controls/scroll_view.cc
+++ b/ui/views/controls/scroll_view.cc
@@ -117,6 +117,8 @@
       horiz_sb_(new NativeScrollBar(true)),
       vert_sb_(new NativeScrollBar(false)),
       resize_corner_(NULL),
+      min_height_(-1),
+      max_height_(-1),
       hide_horizontal_scrollbar_(false) {
   set_notify_enter_exit_on_child(true);
 
@@ -163,6 +165,11 @@
                    contents_viewport_->width(), contents_viewport_->height());
 }
 
+void ScrollView::ClipHeightTo(int min_height, int max_height) {
+  min_height_ = min_height;
+  max_height_ = max_height;
+}
+
 int ScrollView::GetScrollBarWidth() const {
   return vert_sb_ ? vert_sb_->GetLayoutSize() : 0;
 }
@@ -187,7 +194,40 @@
   vert_sb_ = vert_sb;
 }
 
+gfx::Size ScrollView::GetPreferredSize() {
+  if (!is_bounded())
+    return View::GetPreferredSize();
+
+  gfx::Size size = contents()->GetPreferredSize();
+  size.SetToMax(gfx::Size(size.width(), min_height_));
+  size.SetToMin(gfx::Size(size.width(), max_height_));
+  gfx::Insets insets = GetInsets();
+  size.Enlarge(insets.width(), insets.height());
+  return size;
+}
+
+int ScrollView::GetHeightForWidth(int width) {
+  if (!is_bounded())
+    return View::GetHeightForWidth(width);
+
+  gfx::Insets insets = GetInsets();
+  width = std::max(0, width - insets.width());
+  int height = contents()->GetHeightForWidth(width) + insets.height();
+  return std::min(std::max(height, min_height_), max_height_);
+}
+
 void ScrollView::Layout() {
+  if (is_bounded()) {
+    int content_width = width();
+    int content_height = contents()->GetHeightForWidth(content_width);
+    if (content_height > height()) {
+      content_width = std::max(content_width - GetScrollBarWidth(), 0);
+      content_height = contents()->GetHeightForWidth(content_width);
+    }
+    if (contents()->bounds().size() != gfx::Size(content_width, content_height))
+      contents()->SetBounds(0, 0, content_width, content_height);
+  }
+
   // Most views will want to auto-fit the available space. Most of them want to
   // use all available width (without overflowing) and only overflow in
   // height. Examples are HistoryView, MostVisitedView, DownloadTabView, etc.
diff --git a/ui/views/controls/scroll_view.h b/ui/views/controls/scroll_view.h
index da87ffd..7e239f0 100644
--- a/ui/views/controls/scroll_view.h
+++ b/ui/views/controls/scroll_view.h
@@ -31,6 +31,7 @@
   static const char kViewClassName[];
 
   ScrollView();
+
   virtual ~ScrollView();
 
   // Creates a ScrollView with a theme specific border.
@@ -52,6 +53,13 @@
     hide_horizontal_scrollbar_ = visible;
   }
 
+  // Turns this scroll view into a bounded scroll view, with a fixed height.
+  // By default, a ScrollView will stretch to fill its outer container.
+  void ClipHeightTo(int min_height, int max_height);
+
+  // Returns whether or not the ScrollView is bounded (as set by ClipHeightTo).
+  bool is_bounded() { return max_height_ >= 0 && min_height_ >= 0; }
+
   // Retrieves the width/height of scrollbars. These return 0 if the scrollbar
   // has not yet been created.
   int GetScrollBarWidth() const;
@@ -67,6 +75,8 @@
   void SetVerticalScrollBar(ScrollBar* vert_sb);
 
   // View overrides:
+  virtual gfx::Size GetPreferredSize() OVERRIDE;
+  virtual int GetHeightForWidth(int width) OVERRIDE;
   virtual void Layout() OVERRIDE;
   virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
   virtual bool OnMouseWheel(const ui::MouseWheelEvent& e) OVERRIDE;
@@ -127,6 +137,11 @@
   // Resize corner.
   View* resize_corner_;
 
+  // The min and max height for the bounded scroll view. These are negative
+  // values if the view is not bounded.
+  int min_height_;
+  int max_height_;
+
   // If true, never show the horizontal scrollbar (even if the contents is wider
   // than the viewport).
   bool hide_horizontal_scrollbar_;
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc
index f0bdbd5..8fcd713 100644
--- a/ui/views/controls/scroll_view_unittest.cc
+++ b/ui/views/controls/scroll_view_unittest.cc
@@ -5,11 +5,17 @@
 #include "ui/views/controls/scroll_view.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
+#include "ui/views/test/test_views.h"
 
 namespace views {
 
 namespace {
 
+const int kWidth = 100;
+const int kMinHeight = 50;
+const int kMaxHeight = 100;
+
 // View implementation that allows setting the preferred size.
 class CustomView : public View {
  public:
@@ -20,9 +26,7 @@
     PreferredSizeChanged();
   }
 
-  virtual gfx::Size GetPreferredSize() OVERRIDE {
-    return preferred_size_;
-  }
+  virtual gfx::Size GetPreferredSize() OVERRIDE { return preferred_size_; }
 
   virtual void Layout() OVERRIDE {
     gfx::Size pref = GetPreferredSize();
@@ -148,7 +152,6 @@
   ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
   EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
 
-
   // Size the contents such that horizontal scrollbar is needed.
   contents->SetBounds(0, 0, 400, 50);
   scroll_view.Layout();
@@ -214,7 +217,6 @@
   EXPECT_EQ("-1,0", header->bounds().origin().ToString());
 }
 
-
 // Verifies ScrollRectToVisible() on the child works.
 TEST(ScrollViewTest, ScrollRectToVisible) {
   ScrollView scroll_view;
@@ -237,4 +239,97 @@
   EXPECT_EQ(-(415 - viewport_height), contents->y());
 }
 
+// Verifies ClipHeightTo() uses the height of the content when it is between the
+// minimum and maximum height values.
+TEST(ScrollViewTest, ClipHeightToNormalContentHeight) {
+  ScrollView scroll_view;
+
+  scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+  const int kNormalContentHeight = 75;
+  scroll_view.SetContents(
+      new views::StaticSizedView(gfx::Size(kWidth, kNormalContentHeight)));
+
+  EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
+            scroll_view.GetPreferredSize());
+
+  scroll_view.SizeToPreferredSize();
+  scroll_view.Layout();
+
+  EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
+            scroll_view.contents()->size());
+  EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), scroll_view.size());
+}
+
+// Verifies ClipHeightTo() uses the minimum height when the content is shorter
+// thamn the minimum height value.
+TEST(ScrollViewTest, ClipHeightToShortContentHeight) {
+  ScrollView scroll_view;
+
+  scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+  const int kShortContentHeight = 10;
+  scroll_view.SetContents(
+      new views::StaticSizedView(gfx::Size(kWidth, kShortContentHeight)));
+
+  EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.GetPreferredSize());
+
+  scroll_view.SizeToPreferredSize();
+  scroll_view.Layout();
+
+  EXPECT_EQ(gfx::Size(kWidth, kShortContentHeight),
+            scroll_view.contents()->size());
+  EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.size());
+}
+
+// Verifies ClipHeightTo() uses the maximum height when the content is longer
+// thamn the maximum height value.
+TEST(ScrollViewTest, ClipHeightToTallContentHeight) {
+  ScrollView scroll_view;
+
+  // Use a scrollbar that is disabled by default, so the width of the content is
+  // not affected.
+  scroll_view.SetVerticalScrollBar(new views::OverlayScrollBar(false));
+
+  scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+  const int kTallContentHeight = 1000;
+  scroll_view.SetContents(
+      new views::StaticSizedView(gfx::Size(kWidth, kTallContentHeight)));
+
+  EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.GetPreferredSize());
+
+  scroll_view.SizeToPreferredSize();
+  scroll_view.Layout();
+
+  EXPECT_EQ(gfx::Size(kWidth, kTallContentHeight),
+            scroll_view.contents()->size());
+  EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size());
+}
+
+// Verifies that when ClipHeightTo() produces a scrollbar, it reduces the width
+// of the inner content of the ScrollView.
+TEST(ScrollViewTest, ClipHeightToScrollbarUsesWidth) {
+  ScrollView scroll_view;
+
+  scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
+
+  // Create a view that will be much taller than it is wide.
+  scroll_view.SetContents(new views::ProportionallySizedView(1000));
+
+  // Without any width, it will default to 0,0 but be overridden by min height.
+  scroll_view.SizeToPreferredSize();
+  EXPECT_EQ(gfx::Size(0, kMinHeight), scroll_view.GetPreferredSize());
+
+  gfx::Size new_size(kWidth, scroll_view.GetHeightForWidth(kWidth));
+  scroll_view.SetSize(new_size);
+  scroll_view.Layout();
+
+  int scroll_bar_width = scroll_view.GetScrollBarWidth();
+  int expected_width = kWidth - scroll_bar_width;
+  EXPECT_EQ(scroll_view.contents()->size().width(), expected_width);
+  EXPECT_EQ(scroll_view.contents()->size().height(), 1000 * expected_width);
+  EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size());
+}
+
 }  // namespace views
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index f3f5859..65554ac 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -47,6 +47,8 @@
 // Default placeholder text color.
 const SkColor kDefaultPlaceholderTextColor = SK_ColorLTGRAY;
 
+const int kNoCommand = 0;
+
 void ConvertRectToScreen(const View* src, gfx::Rect* r) {
   DCHECK(src);
 
@@ -55,6 +57,78 @@
   r->set_origin(new_origin);
 }
 
+int GetCommandForKeyEvent(const ui::KeyEvent& event, bool has_selection) {
+  if (event.type() != ui::ET_KEY_PRESSED || event.IsUnicodeKeyCode())
+    return kNoCommand;
+
+  const bool shift = event.IsShiftDown();
+  const bool control = event.IsControlDown();
+  const bool alt = event.IsAltDown() || event.IsAltGrDown();
+  switch (event.key_code()) {
+    case ui::VKEY_Z:
+      if (control && !shift && !alt)
+        return IDS_APP_UNDO;
+      return (control && shift && !alt) ? IDS_APP_REDO : kNoCommand;
+    case ui::VKEY_Y:
+      return (control && !alt) ? IDS_APP_REDO : kNoCommand;
+    case ui::VKEY_A:
+      return (control && !alt) ? IDS_APP_SELECT_ALL : kNoCommand;
+    case ui::VKEY_X:
+      return (control && !alt) ? IDS_APP_CUT : kNoCommand;
+    case ui::VKEY_C:
+      return (control && !alt) ? IDS_APP_COPY : kNoCommand;
+    case ui::VKEY_V:
+      return (control && !alt) ? IDS_APP_PASTE : kNoCommand;
+    case ui::VKEY_RIGHT:
+      // Ignore alt+right, which may be a browser navigation shortcut.
+      if (alt)
+        return kNoCommand;
+      if (!shift)
+        return control ? IDS_MOVE_WORD_RIGHT : IDS_MOVE_RIGHT;
+      return control ? IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION :
+                        IDS_MOVE_RIGHT_AND_MODIFY_SELECTION;
+    case ui::VKEY_LEFT:
+      // Ignore alt+left, which may be a browser navigation shortcut.
+      if (alt)
+        return kNoCommand;
+      if (!shift)
+        return control ? IDS_MOVE_WORD_LEFT : IDS_MOVE_LEFT;
+      return control ? IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION :
+                        IDS_MOVE_LEFT_AND_MODIFY_SELECTION;
+    case ui::VKEY_HOME:
+      return shift ? IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION :
+                      IDS_MOVE_TO_BEGINNING_OF_LINE;
+    case ui::VKEY_END:
+      return shift ? IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION :
+                      IDS_MOVE_TO_END_OF_LINE;
+    case ui::VKEY_BACK:
+      if (!control || has_selection)
+        return IDS_DELETE_BACKWARD;
+#if defined(OS_LINUX)
+      // Only erase by line break on Linux and ChromeOS.
+      if (shift)
+        return IDS_DELETE_TO_BEGINNING_OF_LINE;
+#endif
+      return IDS_DELETE_WORD_BACKWARD;
+    case ui::VKEY_DELETE:
+      if (!control || has_selection)
+        return (shift && has_selection) ? IDS_APP_CUT : IDS_DELETE_FORWARD;
+#if defined(OS_LINUX)
+      // Only erase by line break on Linux and ChromeOS.
+      if (shift)
+        return IDS_DELETE_TO_END_OF_LINE;
+#endif
+      return IDS_DELETE_WORD_FORWARD;
+    case ui::VKEY_INSERT:
+      if (control && !shift)
+        return IDS_APP_COPY;
+      return (shift && !control) ? IDS_APP_PASTE : kNoCommand;
+    default:
+      return kNoCommand;
+  }
+  return kNoCommand;
+}
+
 }  // namespace
 
 // static
@@ -419,129 +493,15 @@
 }
 
 bool Textfield::OnKeyPressed(const ui::KeyEvent& event) {
-  bool handled = controller_ && controller_->HandleKeyEvent(this, event);
+  const bool handled = controller_ && controller_->HandleKeyEvent(this, event);
   touch_selection_controller_.reset();
   if (handled)
     return true;
 
-  // TODO(oshima): Refactor and consolidate with ExecuteCommand.
-  if (event.type() == ui::ET_KEY_PRESSED) {
-    ui::KeyboardCode key_code = event.key_code();
-    if (key_code == ui::VKEY_TAB || event.IsUnicodeKeyCode())
-      return false;
-
-    gfx::RenderText* render_text = GetRenderText();
-    const bool editable = !read_only();
-    const bool readable = text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD;
-    const bool shift = event.IsShiftDown();
-    const bool control = event.IsControlDown();
-    const bool alt = event.IsAltDown() || event.IsAltGrDown();
-    bool text_changed = false;
-    bool cursor_changed = false;
-
-    OnBeforeUserAction();
-    switch (key_code) {
-      case ui::VKEY_Z:
-        if (control && !shift && !alt && editable)
-          cursor_changed = text_changed = model_->Undo();
-        else if (control && shift && !alt && editable)
-          cursor_changed = text_changed = model_->Redo();
-        break;
-      case ui::VKEY_Y:
-        if (control && !alt && editable)
-          cursor_changed = text_changed = model_->Redo();
-        break;
-      case ui::VKEY_A:
-        if (control && !alt) {
-          model_->SelectAll(false);
-          UpdateSelectionClipboard();
-          cursor_changed = true;
-        }
-        break;
-      case ui::VKEY_X:
-        if (control && !alt && editable && readable)
-          cursor_changed = text_changed = Cut();
-        break;
-      case ui::VKEY_C:
-        if (control && !alt && readable)
-          Copy();
-        break;
-      case ui::VKEY_V:
-        if (control && !alt && editable)
-          cursor_changed = text_changed = Paste();
-        break;
-      case ui::VKEY_RIGHT:
-      case ui::VKEY_LEFT: {
-        // We should ignore the alt-left/right keys because alt key doesn't make
-        // any special effects for them and they can be shortcut keys such like
-        // forward/back of the browser history.
-        if (alt)
-          break;
-        const gfx::Range selection_range = render_text->selection();
-        model_->MoveCursor(
-            control ? gfx::WORD_BREAK : gfx::CHARACTER_BREAK,
-            (key_code == ui::VKEY_RIGHT) ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT,
-            shift);
-        UpdateSelectionClipboard();
-        cursor_changed = render_text->selection() != selection_range;
-        break;
-      }
-      case ui::VKEY_END:
-      case ui::VKEY_HOME:
-        if ((key_code == ui::VKEY_HOME) ==
-            (render_text->GetTextDirection() == base::i18n::RIGHT_TO_LEFT))
-          model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, shift);
-        else
-          model_->MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_LEFT, shift);
-        UpdateSelectionClipboard();
-        cursor_changed = true;
-        break;
-      case ui::VKEY_BACK:
-      case ui::VKEY_DELETE:
-        if (!editable)
-          break;
-        if (!model_->HasSelection()) {
-          gfx::VisualCursorDirection direction = (key_code == ui::VKEY_DELETE) ?
-              gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
-          if (shift && control) {
-            // If shift and control are pressed, erase up to the next line break
-            // on Linux and ChromeOS. Otherwise, do nothing.
-#if defined(OS_LINUX)
-            model_->MoveCursor(gfx::LINE_BREAK, direction, true);
-#else
-            break;
-#endif
-          } else if (control) {
-            // If only control is pressed, then erase the previous/next word.
-            model_->MoveCursor(gfx::WORD_BREAK, direction, true);
-          }
-        }
-        if (key_code == ui::VKEY_BACK)
-          model_->Backspace();
-        else if (shift && model_->HasSelection() && readable)
-          Cut();
-        else
-          model_->Delete();
-
-        // Consume backspace and delete keys even if the edit did nothing. This
-        // prevents potential unintended side-effects of further event handling.
-        text_changed = true;
-        break;
-      case ui::VKEY_INSERT:
-        if (control && !shift && readable)
-          Copy();
-        else if (shift && !control && editable)
-          cursor_changed = text_changed = Paste();
-        break;
-      default:
-        break;
-    }
-
-    // We must have input method in order to support text input.
-    DCHECK(GetInputMethod());
-    UpdateAfterChange(text_changed, cursor_changed);
-    OnAfterUserAction();
-    return (text_changed || cursor_changed);
+  const int command = GetCommandForKeyEvent(event, HasSelection());
+  if (IsCommandIdEnabled(command)) {
+    ExecuteCommand(command);
+    return true;
   }
   return false;
 }
@@ -736,9 +696,9 @@
   state->role = ui::AX_ROLE_TEXT_FIELD;
   state->name = accessible_name_;
   if (read_only())
-    state->state |= ui::AX_STATE_READ_ONLY;
+    state->AddStateFlag(ui::AX_STATE_READ_ONLY);
   if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD)
-    state->state |= ui::AX_STATE_PROTECTED;
+    state->AddStateFlag(ui::AX_STATE_PROTECTED);
   state->value = text();
 
   const gfx::Range range = GetSelectedRange();
@@ -960,6 +920,8 @@
   switch (command_id) {
     case IDS_APP_UNDO:
       return editable && model_->CanUndo();
+    case IDS_APP_REDO:
+      return editable && model_->CanRedo();
     case IDS_APP_CUT:
       return editable && readable && model_->HasSelection();
     case IDS_APP_COPY:
@@ -972,6 +934,26 @@
       return editable && model_->HasSelection();
     case IDS_APP_SELECT_ALL:
       return !text().empty();
+    case IDS_DELETE_FORWARD:
+    case IDS_DELETE_BACKWARD:
+    case IDS_DELETE_TO_BEGINNING_OF_LINE:
+    case IDS_DELETE_TO_END_OF_LINE:
+    case IDS_DELETE_WORD_BACKWARD:
+    case IDS_DELETE_WORD_FORWARD:
+      return editable;
+    case IDS_MOVE_LEFT:
+    case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
+    case IDS_MOVE_RIGHT:
+    case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
+    case IDS_MOVE_WORD_LEFT:
+    case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
+    case IDS_MOVE_WORD_RIGHT:
+    case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
+    case IDS_MOVE_TO_BEGINNING_OF_LINE:
+    case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
+    case IDS_MOVE_TO_END_OF_LINE:
+    case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
+      return true;
     default:
       return false;
   }
@@ -988,31 +970,102 @@
     return;
 
   bool text_changed = false;
+  bool cursor_changed = false;
+  bool rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
+  gfx::VisualCursorDirection begin = rtl ? gfx::CURSOR_RIGHT : gfx::CURSOR_LEFT;
+  gfx::VisualCursorDirection end = rtl ? gfx::CURSOR_LEFT : gfx::CURSOR_RIGHT;
+  gfx::Range selection_range = GetSelectedRange();
+
   OnBeforeUserAction();
   switch (command_id) {
     case IDS_APP_UNDO:
-      text_changed = model_->Undo();
+      text_changed = cursor_changed = model_->Undo();
+      break;
+    case IDS_APP_REDO:
+      text_changed = cursor_changed = model_->Redo();
       break;
     case IDS_APP_CUT:
-      text_changed = Cut();
+      text_changed = cursor_changed = Cut();
       break;
     case IDS_APP_COPY:
       Copy();
       break;
     case IDS_APP_PASTE:
-      text_changed = Paste();
+      text_changed = cursor_changed = Paste();
       break;
     case IDS_APP_DELETE:
-      text_changed = model_->Delete();
+      text_changed = cursor_changed = model_->Delete();
       break;
     case IDS_APP_SELECT_ALL:
       SelectAll(false);
       break;
+    case IDS_DELETE_BACKWARD:
+      text_changed = cursor_changed = model_->Backspace();
+      break;
+    case IDS_DELETE_FORWARD:
+      text_changed = cursor_changed = model_->Delete();
+      break;
+    case IDS_DELETE_TO_END_OF_LINE:
+      model_->MoveCursor(gfx::LINE_BREAK, end, true);
+      text_changed = cursor_changed = model_->Delete();
+      break;
+    case IDS_DELETE_TO_BEGINNING_OF_LINE:
+      model_->MoveCursor(gfx::LINE_BREAK, begin, true);
+      text_changed = cursor_changed = model_->Backspace();
+      break;
+    case IDS_DELETE_WORD_BACKWARD:
+      model_->MoveCursor(gfx::WORD_BREAK, begin, true);
+      text_changed = cursor_changed = model_->Backspace();
+      break;
+    case IDS_DELETE_WORD_FORWARD:
+      model_->MoveCursor(gfx::WORD_BREAK, end, true);
+      text_changed = cursor_changed = model_->Delete();
+      break;
+    case IDS_MOVE_LEFT:
+      model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, false);
+      break;
+    case IDS_MOVE_LEFT_AND_MODIFY_SELECTION:
+      model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_LEFT, true);
+      break;
+    case IDS_MOVE_RIGHT:
+      model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, false);
+      break;
+    case IDS_MOVE_RIGHT_AND_MODIFY_SELECTION:
+      model_->MoveCursor(gfx::CHARACTER_BREAK, gfx::CURSOR_RIGHT, true);
+      break;
+    case IDS_MOVE_WORD_LEFT:
+      model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, false);
+      break;
+    case IDS_MOVE_WORD_LEFT_AND_MODIFY_SELECTION:
+      model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, true);
+      break;
+    case IDS_MOVE_WORD_RIGHT:
+      model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, false);
+      break;
+    case IDS_MOVE_WORD_RIGHT_AND_MODIFY_SELECTION:
+      model_->MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_RIGHT, true);
+      break;
+    case IDS_MOVE_TO_BEGINNING_OF_LINE:
+      model_->MoveCursor(gfx::LINE_BREAK, begin, false);
+      break;
+    case IDS_MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION:
+      model_->MoveCursor(gfx::LINE_BREAK, begin, true);
+      break;
+    case IDS_MOVE_TO_END_OF_LINE:
+      model_->MoveCursor(gfx::LINE_BREAK, end, false);
+      break;
+    case IDS_MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION:
+      model_->MoveCursor(gfx::LINE_BREAK, end, true);
+      break;
     default:
       NOTREACHED();
       break;
   }
-  UpdateAfterChange(text_changed, text_changed);
+
+  cursor_changed |= GetSelectedRange() != selection_range;
+  if (cursor_changed)
+    UpdateSelectionClipboard();
+  UpdateAfterChange(text_changed, cursor_changed);
   OnAfterUserAction();
 }
 
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index 503c656..861b24d 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -430,13 +430,13 @@
   SendKeyEvent(ui::VKEY_BACK, false, false, true, false);
   EXPECT_STR_EQ("one two three ", textfield_->text());
 
-  // Delete to a line break on Linux and ChromeOS, no-op on Windows.
+  // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
   SendKeyEvent(ui::VKEY_LEFT, false, false, true, false);
   SendKeyEvent(ui::VKEY_BACK, false, true, true, false);
 #if defined(OS_LINUX)
   EXPECT_STR_EQ("three ", textfield_->text());
 #else
-  EXPECT_STR_EQ("one two three ", textfield_->text());
+  EXPECT_STR_EQ("one three ", textfield_->text());
 #endif
 
   // Delete the next word from cursor.
@@ -445,13 +445,13 @@
   SendKeyEvent(ui::VKEY_DELETE, false, false, true, false);
   EXPECT_STR_EQ(" two three four", textfield_->text());
 
-  // Delete to a line break on Linux and ChromeOS, no-op on Windows.
+  // Delete to a line break on Linux and ChromeOS, to a word break on Windows.
   SendKeyEvent(ui::VKEY_RIGHT, false, false, true, false);
   SendKeyEvent(ui::VKEY_DELETE, false, true, true, false);
 #if defined(OS_LINUX)
   EXPECT_STR_EQ(" two", textfield_->text());
 #else
-  EXPECT_STR_EQ(" two three four", textfield_->text());
+  EXPECT_STR_EQ(" two four", textfield_->text());
 #endif
 }
 
@@ -523,18 +523,33 @@
 TEST_F(TextfieldTest, OnKeyPressReturnValueTest) {
   InitTextfield();
 
-  // Character keys will be handled by input method.
+  // Character keys are handled by the input method.
   SendKeyEvent(ui::VKEY_A);
   EXPECT_TRUE(textfield_->key_received());
   EXPECT_FALSE(textfield_->key_handled());
   textfield_->clear();
 
-  // Home will be handled.
+  // Arrow keys and home/end are handled by the textfield.
+  SendKeyEvent(ui::VKEY_LEFT);
+  EXPECT_TRUE(textfield_->key_received());
+  EXPECT_TRUE(textfield_->key_handled());
+  textfield_->clear();
+
+  SendKeyEvent(ui::VKEY_RIGHT);
+  EXPECT_TRUE(textfield_->key_received());
+  EXPECT_TRUE(textfield_->key_handled());
+  textfield_->clear();
+
   SendKeyEvent(ui::VKEY_HOME);
   EXPECT_TRUE(textfield_->key_received());
   EXPECT_TRUE(textfield_->key_handled());
   textfield_->clear();
 
+  SendKeyEvent(ui::VKEY_END);
+  EXPECT_TRUE(textfield_->key_received());
+  EXPECT_TRUE(textfield_->key_handled());
+  textfield_->clear();
+
   // F24, up/down key won't be handled.
   SendKeyEvent(ui::VKEY_F24);
   EXPECT_TRUE(textfield_->key_received());
@@ -550,37 +565,6 @@
   EXPECT_TRUE(textfield_->key_received());
   EXPECT_FALSE(textfield_->key_handled());
   textfield_->clear();
-
-  // Empty Textfield does not handle left/right.
-  textfield_->SetText(base::string16());
-  SendKeyEvent(ui::VKEY_LEFT);
-  EXPECT_TRUE(textfield_->key_received());
-  EXPECT_FALSE(textfield_->key_handled());
-  textfield_->clear();
-
-  SendKeyEvent(ui::VKEY_RIGHT);
-  EXPECT_TRUE(textfield_->key_received());
-  EXPECT_FALSE(textfield_->key_handled());
-  textfield_->clear();
-
-  // Add a char. Right key should not be handled when cursor is at the end.
-  SendKeyEvent(ui::VKEY_B);
-  SendKeyEvent(ui::VKEY_RIGHT);
-  EXPECT_TRUE(textfield_->key_received());
-  EXPECT_FALSE(textfield_->key_handled());
-  textfield_->clear();
-
-  // First left key is handled to move cursor left to the beginning.
-  SendKeyEvent(ui::VKEY_LEFT);
-  EXPECT_TRUE(textfield_->key_received());
-  EXPECT_TRUE(textfield_->key_handled());
-  textfield_->clear();
-
-  // Now left key should not be handled.
-  SendKeyEvent(ui::VKEY_LEFT);
-  EXPECT_TRUE(textfield_->key_received());
-  EXPECT_FALSE(textfield_->key_handled());
-  textfield_->clear();
 }
 
 TEST_F(TextfieldTest, CursorMovement) {
@@ -1106,8 +1090,8 @@
   EXPECT_TRUE(client->GetCompositionTextRange(&range));
   EXPECT_STR_EQ("0321456789", textfield_->text());
   EXPECT_EQ(gfx::Range(1, 4), range);
-  EXPECT_EQ(2, on_before_user_action_);
-  EXPECT_EQ(2, on_after_user_action_);
+  EXPECT_EQ(1, on_before_user_action_);
+  EXPECT_EQ(1, on_after_user_action_);
 
   input_method_->SetResultTextForNextKey(UTF8ToUTF16("123"));
   on_before_user_action_ = on_after_user_action_ = 0;
@@ -1118,8 +1102,8 @@
   EXPECT_FALSE(client->HasCompositionText());
   EXPECT_FALSE(input_method_->cancel_composition_called());
   EXPECT_STR_EQ("0123456789", textfield_->text());
-  EXPECT_EQ(2, on_before_user_action_);
-  EXPECT_EQ(2, on_after_user_action_);
+  EXPECT_EQ(1, on_before_user_action_);
+  EXPECT_EQ(1, on_after_user_action_);
 
   input_method_->Clear();
   input_method_->SetCompositionTextForNextKey(composition);
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc
index 77d9780..bf75a65 100644
--- a/ui/views/controls/tree/tree_view.cc
+++ b/ui/views/controls/tree/tree_view.cc
@@ -406,7 +406,7 @@
 
 void TreeView::GetAccessibleState(ui::AXViewState* state) {
   state->role = ui::AX_ROLE_TREE;
-  state->state = ui::AX_STATE_READ_ONLY;
+  state->AddStateFlag(ui::AX_STATE_READ_ONLY);
   if (!selected_node_)
     return;
 
diff --git a/ui/views/controls/webview/web_dialog_view.cc b/ui/views/controls/webview/web_dialog_view.cc
index 98da5ad..949c82a 100644
--- a/ui/views/controls/webview/web_dialog_view.cc
+++ b/ui/views/controls/webview/web_dialog_view.cc
@@ -324,7 +324,8 @@
       was_blocked);
 }
 
-void WebDialogView::LoadingStateChanged(content::WebContents* source) {
+void WebDialogView::LoadingStateChanged(content::WebContents* source,
+    bool to_different_document) {
   if (delegate_)
     delegate_->OnLoadingStateChanged(source);
 }
diff --git a/ui/views/controls/webview/web_dialog_view.h b/ui/views/controls/webview/web_dialog_view.h
index 51d67eb..902aa32 100644
--- a/ui/views/controls/webview/web_dialog_view.h
+++ b/ui/views/controls/webview/web_dialog_view.h
@@ -110,7 +110,8 @@
                               const gfx::Rect& initial_pos,
                               bool user_gesture,
                               bool* was_blocked) OVERRIDE;
-  virtual void LoadingStateChanged(content::WebContents* source) OVERRIDE;
+  virtual void LoadingStateChanged(content::WebContents* source,
+                                   bool to_different_document) OVERRIDE;
   virtual void BeforeUnloadFired(content::WebContents* tab,
                                  bool proceed,
                                  bool* proceed_to_fire_unload) OVERRIDE;
diff --git a/ui/views/controls/webview/webview_tests.gyp b/ui/views/controls/webview/webview_tests.gyp
new file mode 100644
index 0000000..0adc5c2
--- /dev/null
+++ b/ui/views/controls/webview/webview_tests.gyp
@@ -0,0 +1,38 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'targets': [
+    {
+      'target_name': 'webview_test_support',
+      'type': 'static_library',
+      'dependencies': [
+        '../../../../base/base.gyp:base',
+        '../../../../content/content.gyp:content',
+        '../../../../content/content_shell_and_tests.gyp:test_support_content',
+        '../../../../ipc/ipc.gyp:test_support_ipc',
+        '../../../../skia/skia.gyp:skia',
+        '../../../../testing/gtest.gyp:gtest',
+        '../../../aura/aura.gyp:aura',
+        '../../../base/ui_base.gyp:ui_base',
+        '../../../events/events.gyp:events',
+        '../../../gfx/gfx.gyp:gfx',
+        '../../../gfx/gfx.gyp:gfx_geometry',
+        '../../views.gyp:views',
+        '../../views.gyp:views_test_support',
+        'webview.gyp:webview',
+      ],
+      'include_dirs': [
+        '../../../..',
+      ],
+      'sources': [
+        '../../test/webview_test_helper.cc',
+        '../../test/webview_test_helper.h',
+      ],
+    },
+  ],
+}
diff --git a/ui/views/corewm/desktop_capture_controller_unittest.cc b/ui/views/corewm/desktop_capture_controller_unittest.cc
index ad6d849..8807aaf 100644
--- a/ui/views/corewm/desktop_capture_controller_unittest.cc
+++ b/ui/views/corewm/desktop_capture_controller_unittest.cc
@@ -101,6 +101,7 @@
   EXPECT_TRUE(w1_dispatcher->mouse_pressed_handler() == NULL);
   EXPECT_TRUE(w1_dispatcher->mouse_moved_handler() == NULL);
   w2->ReleaseCapture();
+  RunPendingMessages();
 }
 
 // Tests aura::Window capture and whether gesture events are sent to the window
diff --git a/ui/views/corewm/tooltip_aura.cc b/ui/views/corewm/tooltip_aura.cc
index 5b8da6a..50ced84 100644
--- a/ui/views/corewm/tooltip_aura.cc
+++ b/ui/views/corewm/tooltip_aura.cc
@@ -64,7 +64,6 @@
       views::Background::CreateSolidBackground(kTooltipBackground));
   label_.set_owned_by_client();
   label_.SetMultiLine(true);
-  label_.SetHorizontalAlignment(gfx::ALIGN_LEFT);
 }
 
 TooltipAura::~TooltipAura() {
diff --git a/ui/views/corewm/tooltip_controller.cc b/ui/views/corewm/tooltip_controller.cc
index c5e621b..500466f 100644
--- a/ui/views/corewm/tooltip_controller.cc
+++ b/ui/views/corewm/tooltip_controller.cc
@@ -10,7 +10,6 @@
 #include "base/time/time.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/client/screen_position_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -20,6 +19,7 @@
 #include "ui/gfx/screen.h"
 #include "ui/views/corewm/tooltip.h"
 #include "ui/views/widget/tooltip_manager.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 namespace views {
 namespace corewm {
diff --git a/ui/views/corewm/tooltip_controller.h b/ui/views/corewm/tooltip_controller.h
index e75a1e6..9815df1 100644
--- a/ui/views/corewm/tooltip_controller.h
+++ b/ui/views/corewm/tooltip_controller.h
@@ -10,11 +10,11 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/strings/string16.h"
 #include "base/timer/timer.h"
-#include "ui/aura/client/tooltip_client.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
 #include "ui/gfx/point.h"
 #include "ui/views/views_export.h"
+#include "ui/wm/public/tooltip_client.h"
 
 namespace aura {
 class Window;
diff --git a/ui/views/corewm/tooltip_controller_unittest.cc b/ui/views/corewm/tooltip_controller_unittest.cc
index 39cab8e..152a5a2 100644
--- a/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/ui/views/corewm/tooltip_controller_unittest.cc
@@ -7,7 +7,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/tooltip_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/test/event_generator.h"
@@ -27,6 +26,7 @@
 #include "ui/views/widget/tooltip_manager.h"
 #include "ui/views/widget/widget.h"
 #include "ui/wm/core/wm_state.h"
+#include "ui/wm/public/tooltip_client.h"
 #include "ui/wm/public/window_types.h"
 
 #if defined(OS_WIN)
diff --git a/ui/views/drag_utils.cc b/ui/views/drag_utils.cc
index 27f6d58..840d75f 100644
--- a/ui/views/drag_utils.cc
+++ b/ui/views/drag_utils.cc
@@ -4,7 +4,6 @@
 
 #include "ui/views/drag_utils.h"
 
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/gfx/canvas.h"
@@ -12,6 +11,7 @@
 #include "ui/gfx/screen.h"
 #include "ui/gfx/size.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 float GetDeviceScaleForNativeView(views::Widget* widget) {
   float device_scale = 1.0f;
diff --git a/ui/views/examples/content_client/examples_browser_main_parts.cc b/ui/views/examples/content_client/examples_browser_main_parts.cc
index 9e9cecb..16e5eb6 100644
--- a/ui/views/examples/content_client/examples_browser_main_parts.cc
+++ b/ui/views/examples/content_client/examples_browser_main_parts.cc
@@ -18,7 +18,6 @@
 #include "ui/gfx/screen.h"
 #include "ui/views/examples/examples_window_with_content.h"
 #include "ui/views/test/desktop_test_views_delegate.h"
-#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #include "ui/views/widget/native_widget_aura.h"
 #include "ui/wm/core/wm_state.h"
 #include "url/gurl.h"
@@ -28,6 +27,8 @@
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/wm/test/wm_test_helper.h"
+#else  // !defined(OS_CHROMEOS)
+#include "ui/views/widget/desktop_aura/desktop_screen.h"
 #endif
 
 namespace views {
diff --git a/ui/views/examples/examples.gyp b/ui/views/examples/examples.gyp
new file mode 100644
index 0000000..100d8b9
--- /dev/null
+++ b/ui/views/examples/examples.gyp
@@ -0,0 +1,230 @@
+# Copyright 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+  'variables': {
+    'chromium_code': 1,
+  },
+  'targets': [
+    {
+      'target_name': 'views_examples_lib',
+      'type': '<(component)',
+      'dependencies': [
+        '../../../base/base.gyp:base',
+        '../../../skia/skia.gyp:skia',
+        '../../../third_party/icu/icu.gyp:icui18n',
+        '../../../third_party/icu/icu.gyp:icuuc',
+        '../../aura/aura.gyp:aura',
+        '../../base/ui_base.gyp:ui_base',
+        '../../events/events.gyp:events',
+        '../../gfx/gfx.gyp:gfx',
+        '../../gfx/gfx.gyp:gfx_geometry',
+        '../../resources/ui_resources.gyp:ui_resources',
+        '../../resources/ui_resources.gyp:ui_test_pak',
+        '../views.gyp:views',
+      ],
+      'include_dirs': [
+        '../../..',
+      ],
+      'defines': [
+        'VIEWS_EXAMPLES_IMPLEMENTATION',
+      ],
+      'sources': [
+        'bubble_example.cc',
+        'bubble_example.h',
+        'button_example.cc',
+        'button_example.h',
+        'checkbox_example.cc',
+        'checkbox_example.h',
+        'combobox_example.cc',
+        'combobox_example.h',
+        'double_split_view_example.cc',
+        'double_split_view_example.h',
+        'example_base.cc',
+        'example_base.h',
+        'example_combobox_model.cc',
+        'example_combobox_model.h',
+        'examples_window.cc',
+        'examples_window.h',
+        'label_example.cc',
+        'label_example.h',
+        'link_example.cc',
+        'link_example.h',
+        'message_box_example.cc',
+        'message_box_example.h',
+        'menu_example.cc',
+        'menu_example.h',
+        'multiline_example.cc',
+        'multiline_example.h',
+        'progress_bar_example.cc',
+        'progress_bar_example.h',
+        'radio_button_example.cc',
+        'radio_button_example.h',
+        'scroll_view_example.cc',
+        'scroll_view_example.h',
+        'single_split_view_example.cc',
+        'single_split_view_example.h',
+        'slider_example.cc',
+        'slider_example.h',
+        'tabbed_pane_example.cc',
+        'tabbed_pane_example.h',
+        'table_example.cc',
+        'table_example.h',
+        'text_example.cc',
+        'text_example.h',
+        'textfield_example.cc',
+        'textfield_example.h',
+        'throbber_example.cc',
+        'throbber_example.h',
+        'tree_view_example.cc',
+        'tree_view_example.h',
+        'views_examples_export.h',
+        'widget_example.cc',
+        'widget_example.h',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'include_dirs': [
+            '../../../third_party/wtl/include',
+          ],
+          # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+          'msvs_disabled_warnings': [ 4267, ],
+        }],
+      ],
+    },  # target_name: views_examples_lib
+    {
+      'target_name': 'views_examples_exe',
+      'type': 'executable',
+      'dependencies': [
+        '../../../base/base.gyp:base',
+        '../../../base/base.gyp:base_i18n',
+        '../../aura/aura.gyp:aura',
+        '../../base/ui_base.gyp:ui_base',
+        '../../compositor/compositor.gyp:compositor',
+        '../../compositor/compositor.gyp:compositor_test_support',
+        '../../gfx/gfx.gyp:gfx',
+        '../../resources/ui_resources.gyp:ui_test_pak',
+        '../views.gyp:views',
+        '../views.gyp:views_test_support',
+        'views_examples_lib',
+      ],
+      'sources': [
+        'examples_main.cc',
+      ],
+    },  # target_name: views_examples_exe
+    {
+      'target_name': 'views_examples_with_content_lib',
+      'type': '<(component)',
+      'dependencies': [
+        '../../../base/base.gyp:base',
+        '../../../base/base.gyp:base_i18n',
+        '../../../content/content.gyp:content',
+        '../../../skia/skia.gyp:skia',
+        '../../../third_party/icu/icu.gyp:icui18n',
+        '../../../third_party/icu/icu.gyp:icuuc',
+        '../../../url/url.gyp:url_lib',
+        '../../aura/aura.gyp:aura',
+        '../../base/ui_base.gyp:ui_base',
+        '../../events/events.gyp:events',
+        '../../gfx/gfx.gyp:gfx',
+        '../../gfx/gfx.gyp:gfx_geometry',
+        '../../resources/ui_resources.gyp:ui_resources',
+        '../../resources/ui_resources.gyp:ui_test_pak',
+        '../controls/webview/webview.gyp:webview',
+        '../views.gyp:views',
+        'views_examples_lib',
+      ],
+      'include_dirs': [
+        '../../..',
+      ],
+      'defines': [
+        'VIEWS_EXAMPLES_WITH_CONTENT_IMPLEMENTATION',
+      ],
+      'sources': [
+        'examples_window_with_content.cc',
+        'examples_window_with_content.h',
+        'views_examples_with_content_export.h',
+        'webview_example.cc',
+        'webview_example.h',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'include_dirs': [
+            '../../../third_party/wtl/include',
+          ],
+          # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+          'msvs_disabled_warnings': [ 4267, ],
+        }],
+      ],
+    },  # target_name: views_examples_with_content_lib
+    {
+      'target_name': 'views_examples_with_content_exe',
+      'type': 'executable',
+      'dependencies': [
+        '../../../base/base.gyp:base',
+        '../../../base/base.gyp:base_i18n',
+        '../../../content/content.gyp:content',
+        '../../../content/content_shell_and_tests.gyp:content_shell_lib',
+        '../../../content/content_shell_and_tests.gyp:test_support_content',
+        '../../../skia/skia.gyp:skia',
+        '../../../third_party/icu/icu.gyp:icui18n',
+        '../../../third_party/icu/icu.gyp:icuuc',
+        '../../aura/aura.gyp:aura',
+        '../../base/ui_base.gyp:ui_base',
+        '../../compositor/compositor.gyp:compositor',
+        '../../events/events.gyp:events',
+        '../../gfx/gfx.gyp:gfx',
+        '../../gfx/gfx.gyp:gfx_geometry',
+        '../../resources/ui_resources.gyp:ui_resources',
+        '../../resources/ui_resources.gyp:ui_test_pak',
+        '../../wm/wm.gyp:wm_test_support',
+        '../views.gyp:views',
+        '../views.gyp:views_test_support',
+        'views_examples_with_content_lib',
+      ],
+      'include_dirs': [
+        '../../..',
+      ],
+      'sources': [
+        '../../../content/app/startup_helper_win.cc',
+        'content_client/examples_browser_main_parts.cc',
+        'content_client/examples_browser_main_parts.h',
+        'content_client/examples_content_browser_client.cc',
+        'content_client/examples_content_browser_client.h',
+        'content_client/examples_main_delegate.cc',
+        'content_client/examples_main_delegate.h',
+        'content_client/examples_main.cc',
+      ],
+      'conditions': [
+        ['OS=="win"', {
+          'link_settings': {
+            'libraries': [
+              '-limm32.lib',
+              '-loleacc.lib',
+            ]
+          },
+          'msvs_settings': {
+            'VCManifestTool': {
+              'AdditionalManifestFiles': [
+                'views_examples.exe.manifest',
+              ],
+            },
+            'VCLinkerTool': {
+              'SubSystem': '2',  # Set /SUBSYSTEM:WINDOWS
+            },
+          },
+          'dependencies': [
+            '../../../sandbox/sandbox.gyp:sandbox',
+          ],
+        }],
+        ['OS=="win"', {
+          'sources/': [
+            # This is needed because the aura rule strips it from the default
+            # sources list.
+            ['include', '^../../../content/app/startup_helper_win.cc'],
+          ],
+        }],
+      ],
+    },  # target_name: views_examples_with_content_exe
+  ],
+}
diff --git a/ui/views/focus/view_storage.h b/ui/views/focus/view_storage.h
index 629aec1..5e36f3c 100644
--- a/ui/views/focus/view_storage.h
+++ b/ui/views/focus/view_storage.h
@@ -17,7 +17,7 @@
 // used for example in the FocusManager to store/restore focused views when the
 // main window becomes active/inactive.
 // It automatically removes a view from the storage if the view is removed from
-// the tree hierarchy.
+// the tree hierarchy or when the view is destroyed, which ever comes first.
 //
 // To use it, you first need to create a view storage id that can then be used
 // to store/retrieve views.
diff --git a/ui/views/ime/OWNERS b/ui/views/ime/OWNERS
index 953dfa3..9f6409a 100644
--- a/ui/views/ime/OWNERS
+++ b/ui/views/ime/OWNERS
@@ -1,3 +1,6 @@
-komatsu@chromium.org
+# primary reviewer
+yukishiino@chromium.org
+
+# backup reviewers.
+mukai@chromium.org
 nona@chromium.org
-penghuang@chromium.org
diff --git a/ui/views/view.cc b/ui/views/view.cc
index 5875c7c..2da6e30 100644
--- a/ui/views/view.cc
+++ b/ui/views/view.cc
@@ -20,7 +20,6 @@
 #include "ui/base/cursor/cursor.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/ui_base_switches_util.h"
-#include "ui/compositor/clone_layer.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_animator.h"
@@ -41,6 +40,7 @@
 #include "ui/views/border.h"
 #include "ui/views/context_menu_controller.h"
 #include "ui/views/drag_controller.h"
+#include "ui/views/focus/view_storage.h"
 #include "ui/views/layout/layout_manager.h"
 #include "ui/views/rect_based_targeting_utils.h"
 #include "ui/views/views_delegate.h"
@@ -171,6 +171,8 @@
   if (parent_)
     parent_->RemoveChildView(this);
 
+  ViewStorage::GetInstance()->ViewRemoved(this);
+
   for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) {
     (*i)->parent_ = NULL;
     if (!(*i)->owned_by_client_)
@@ -506,10 +508,6 @@
   }
 }
 
-scoped_ptr<ui::Layer> View::RecreateLayer() {
-  return ui::CloneLayer(this);
-}
-
 // RTL positioning -------------------------------------------------------------
 
 gfx::Rect View::GetMirroredBounds() const {
@@ -590,14 +588,19 @@
   return kViewClassName;
 }
 
-View* View::GetAncestorWithClassName(const std::string& name) {
-  for (View* view = this; view; view = view->parent_) {
+const View* View::GetAncestorWithClassName(const std::string& name) const {
+  for (const View* view = this; view; view = view->parent_) {
     if (!strcmp(view->GetClassName(), name.c_str()))
       return view;
   }
   return NULL;
 }
 
+View* View::GetAncestorWithClassName(const std::string& name) {
+  return const_cast<View*>(const_cast<const View*>(this)->
+      GetAncestorWithClassName(name));
+}
+
 const View* View::GetViewByID(int id) const {
   if (id == id_)
     return const_cast<View*>(this);
diff --git a/ui/views/view.h b/ui/views/view.h
index cc4c9a1..a839c06 100644
--- a/ui/views/view.h
+++ b/ui/views/view.h
@@ -323,9 +323,6 @@
   // Compositor.
   void SetPaintToLayer(bool paint_to_layer);
 
-  // Overriden from ui:LayerOwner:
-  virtual scoped_ptr<ui::Layer> RecreateLayer() OVERRIDE;
-
   // RTL positioning -----------------------------------------------------------
 
   // Methods for accessing the bounds and position of the view, relative to its
@@ -404,6 +401,7 @@
 
   // Returns the first ancestor, starting at this, whose class name is |name|.
   // Returns null if no ancestor has the class name |name|.
+  const View* GetAncestorWithClassName(const std::string& name) const;
   View* GetAncestorWithClassName(const std::string& name);
 
   // Recursively descends the view tree starting at this view, and returns
@@ -1024,6 +1022,8 @@
   // changed. The default implementation calls SchedulePaint() on this View.
   virtual void OnEnabledChanged();
 
+  bool needs_layout() const { return needs_layout_; }
+
   // Tree operations -----------------------------------------------------------
 
   // This method is invoked when the tree changes.
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
index 24a2612..d681114 100644
--- a/ui/views/view_unittest.cc
+++ b/ui/views/view_unittest.cc
@@ -41,10 +41,6 @@
 #include "ui/views/window/dialog_delegate.h"
 #include "ui/wm/core/window_util.h"
 
-#if defined(OS_WIN)
-#include "ui/views/test/test_views_delegate.h"
-#endif
-
 using base::ASCIIToUTF16;
 
 namespace {
@@ -3630,23 +3626,20 @@
 
 // Creates a widget of TYPE_CONTROL.
 // The caller takes ownership of the returned widget.
-views::Widget* CreateControlWidget(
-    aura::Window* parent,
-    const gfx::Rect& bounds) {
-  views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
+Widget* CreateControlWidget(aura::Window* parent, const gfx::Rect& bounds) {
+  Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
   params.parent = parent;
   params.bounds = bounds;
-  views::Widget* widget = new views::Widget();
+  Widget* widget = new Widget();
   widget->Init(params);
   return widget;
 }
 
 // Returns a view with a layer with the passed in |bounds| and |layer_name|.
 // The caller takes ownership of the returned view.
-views::View* CreateViewWithLayer(
-    const gfx::Rect& bounds,
-    const char* layer_name) {
-  views::View* view = new views::View();
+View* CreateViewWithLayer(const gfx::Rect& bounds,
+                          const char* layer_name) {
+  View* view = new View();
   view->SetBoundsRect(bounds);
   view->SetPaintToLayer(true);
   view->layer()->set_name(layer_name);
@@ -3666,35 +3659,50 @@
 //     +-- v5
 //         +-- v6
 // +-- v7
+//     +-- v8
+//     +-- v9
 TEST_F(ViewTest, RecreateLayers) {
-  views::Widget* w1 = CreateControlWidget(GetContext(),
-                                          gfx::Rect(0, 0, 100, 100));
+  Widget* w1 = CreateControlWidget(GetContext(), gfx::Rect(0, 0, 100, 100));
   w1->GetNativeView()->layer()->set_name("w1");
 
-  views::View* v2 = new views::View();
+  View* v2 = new View();
   v2->SetBounds(0, 1, 100, 101);
-  views::View* v3 = new views::View();
+  View* v3 = new View();
   v3->SetBounds(0, 2, 100, 102);
-  views::View* w2_host_view = new views::View();
+  View* w2_host_view = new View();
 
-  w1->GetRootView()->AddChildView(CreateViewWithLayer(
-      gfx::Rect(0, 3, 100, 103), "v1"));
+  View* v1 = CreateViewWithLayer(gfx::Rect(0, 3, 100, 103), "v1");
+  ui::Layer* v1_layer = v1->layer();
+  w1->GetRootView()->AddChildView(v1);
   w1->GetRootView()->AddChildView(v2);
   v2->AddChildView(v3);
-  v2->AddChildView(CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v4"));
+  View* v4 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v4");
+  ui::Layer* v4_layer = v4->layer();
+  v2->AddChildView(v4);
 
   w1->GetRootView()->AddChildView(w2_host_view);
-  w1->GetRootView()->AddChildView(CreateViewWithLayer(
-      gfx::Rect(0, 4, 100, 104), "v7"));
+  View* v7 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v7");
+  ui::Layer* v7_layer = v7->layer();
+  w1->GetRootView()->AddChildView(v7);
 
-  views::Widget* w2 = CreateControlWidget(w1->GetNativeView(),
+  View* v8 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v8");
+  ui::Layer* v8_layer = v8->layer();
+  v7->AddChildView(v8);
+
+  View* v9 = CreateViewWithLayer(gfx::Rect(0, 4, 100, 104), "v9");
+  ui::Layer* v9_layer = v9->layer();
+  v7->AddChildView(v9);
+
+  Widget* w2 = CreateControlWidget(w1->GetNativeView(),
                                           gfx::Rect(0, 5, 100, 105));
   w2->GetNativeView()->layer()->set_name("w2");
-  w2->GetNativeView()->SetProperty(views::kHostViewKey, w2_host_view);
+  w2->GetNativeView()->SetProperty(kHostViewKey, w2_host_view);
 
-  views::View* v5 = CreateViewWithLayer(gfx::Rect(0, 6, 100, 106), "v5");
+  View* v5 = CreateViewWithLayer(gfx::Rect(0, 6, 100, 106), "v5");
   w2->GetRootView()->AddChildView(v5);
-  v5->AddChildView(CreateViewWithLayer(gfx::Rect(0, 7, 100, 107), "v6"));
+  View* v6 = CreateViewWithLayer(gfx::Rect(0, 7, 100, 107), "v6");
+  ui::Layer* v6_layer = v6->layer();
+  v5->AddChildView(v6);
 
   // Test the initial order of the layers.
   ui::Layer* w1_layer = w1->GetNativeView()->layer();
@@ -3708,20 +3716,58 @@
   {
     scoped_ptr<ui::LayerTreeOwner> cloned_owner(
         wm::RecreateLayers(w1->GetNativeView()));
-    w1_layer = cloned_owner->root();
+    EXPECT_EQ(w1_layer, cloned_owner->root());
+    EXPECT_NE(w1_layer, w1->GetNativeView()->layer());
 
-    // The order of the layers returned by RecreateWindowLayers() should match
-    // the order of the layers prior to calling RecreateWindowLayers().
+    // The old layers should still exist and have the same hierarchy.
     ASSERT_EQ("w1", w1_layer->name());
     ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_layer));
-    w2_layer = w1_layer->children()[2];
     ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_layer));
-    v5_layer = w2_layer->children()[0];
     ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_layer));
+    EXPECT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_layer));
 
+    ASSERT_EQ(4u, w1_layer->children().size());
+    EXPECT_EQ(v1_layer, w1_layer->children()[0]);
+    EXPECT_EQ(v4_layer, w1_layer->children()[1]);
+    EXPECT_EQ(w2_layer, w1_layer->children()[2]);
+    EXPECT_EQ(v7_layer, w1_layer->children()[3]);
+
+    ASSERT_EQ(1u, w2_layer->children().size());
+    EXPECT_EQ(v5_layer, w2_layer->children()[0]);
+
+    ASSERT_EQ(1u, v5_layer->children().size());
+    EXPECT_EQ(v6_layer, v5_layer->children()[0]);
+
+    ASSERT_EQ(0u, v6_layer->children().size());
+
+    EXPECT_EQ(2u, v7_layer->children().size());
+    EXPECT_EQ(v8_layer, v7_layer->children()[0]);
+    EXPECT_EQ(v9_layer, v7_layer->children()[1]);
+
+    // The cloned layers should have the same hierarchy as old.
+    ui::Layer* w1_new_layer = w1->GetNativeView()->layer();
+    EXPECT_EQ("w1", w1_new_layer->name());
+    ASSERT_EQ("v1 v4 w2 v7", ui::test::ChildLayerNamesAsString(*w1_new_layer));
+    ui::Layer* w2_new_layer = w1_new_layer->children()[2];
+    ASSERT_EQ("v5", ui::test::ChildLayerNamesAsString(*w2_new_layer));
+    ui::Layer* v5_new_layer = w2_new_layer->children()[0];
+    ASSERT_EQ("v6", ui::test::ChildLayerNamesAsString(*v5_new_layer));
+    ui::Layer* v7_new_layer = w1_new_layer->children()[3];
+    ASSERT_EQ("v8 v9", ui::test::ChildLayerNamesAsString(*v7_new_layer));
   }
   // The views and the widgets are destroyed when AuraTestHelper::TearDown()
   // destroys root_window().
 }
 
+// Verifies when a view is deleted it is removed from ViewStorage.
+TEST_F(ViewTest, UpdateViewStorageOnDelete) {
+  ViewStorage* view_storage = ViewStorage::GetInstance();
+  const int storage_id = view_storage->CreateStorageID();
+  {
+    View view;
+    view_storage->StoreView(storage_id, &view);
+  }
+  EXPECT_TRUE(view_storage->RetrieveView(storage_id) == NULL);
+}
+
 }  // namespace views
diff --git a/ui/views/views.gyp b/ui/views/views.gyp
index 9b010e7..feb92d8 100644
--- a/ui/views/views.gyp
+++ b/ui/views/views.gyp
@@ -5,13 +5,6 @@
   'variables': {
     'chromium_code': 1,
   },
-  'target_defaults': {
-    'conditions': [
-      ['OS!="linux" or chromeos==1', {
-        'sources/': [ ['exclude', '_linux\\.(h|cc)$'] ],
-      }],
-    ],
-  },
   'targets': [
     {
       'target_name': 'views',
@@ -433,6 +426,11 @@
             'bubble/tray_bubble_view.h',
           ],
         }],
+        ['chromeos==0 and use_x11==1', {
+          'dependencies': [
+            '../display/display.gyp:display',
+          ],
+        }],
         ['OS=="linux" and chromeos==0', {
           'dependencies': [
             '../shell_dialogs/shell_dialogs.gyp:shell_dialogs',
@@ -551,33 +549,6 @@
       ],
     },  # target_name: views_test_support
     {
-      'target_name': 'views_with_content_test_support',
-      'type': 'static_library',
-      'dependencies': [
-        '../../base/base.gyp:base',
-        '../../content/content.gyp:content',
-        '../../content/content_shell_and_tests.gyp:test_support_content',
-        '../../ipc/ipc.gyp:test_support_ipc',
-        '../../skia/skia.gyp:skia',
-        '../../testing/gtest.gyp:gtest',
-        '../aura/aura.gyp:aura',
-        '../base/ui_base.gyp:ui_base',
-        '../events/events.gyp:events',
-        '../gfx/gfx.gyp:gfx',
-        '../gfx/gfx.gyp:gfx_geometry',
-        'controls/webview/webview.gyp:webview',
-        'views_test_support',
-        'views',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-      'sources': [
-        'test/webview_test_helper.cc',
-        'test/webview_test_helper.h',
-      ],
-    },  # target_name: views_with_content_test_support
-    {
       'target_name': 'views_unittests',
       'type': 'executable',
       'dependencies': [
@@ -718,225 +689,5 @@
         }],
       ],
     },  # target_name: views_unittests
-    {
-      'target_name': 'views_examples_lib',
-      'type': '<(component)',
-      'dependencies': [
-        '../../base/base.gyp:base',
-        '../../skia/skia.gyp:skia',
-        '../../third_party/icu/icu.gyp:icui18n',
-        '../../third_party/icu/icu.gyp:icuuc',
-        '../aura/aura.gyp:aura',
-        '../base/ui_base.gyp:ui_base',
-        '../events/events.gyp:events',
-        '../gfx/gfx.gyp:gfx',
-        '../gfx/gfx.gyp:gfx_geometry',
-        '../resources/ui_resources.gyp:ui_resources',
-        '../resources/ui_resources.gyp:ui_test_pak',
-        'views',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-      'defines': [
-        'VIEWS_EXAMPLES_IMPLEMENTATION',
-      ],
-      'sources': [
-        'examples/bubble_example.cc',
-        'examples/bubble_example.h',
-        'examples/button_example.cc',
-        'examples/button_example.h',
-        'examples/checkbox_example.cc',
-        'examples/checkbox_example.h',
-        'examples/combobox_example.cc',
-        'examples/combobox_example.h',
-        'examples/double_split_view_example.cc',
-        'examples/double_split_view_example.h',
-        'examples/example_base.cc',
-        'examples/example_base.h',
-        'examples/example_combobox_model.cc',
-        'examples/example_combobox_model.h',
-        'examples/examples_window.cc',
-        'examples/examples_window.h',
-        'examples/label_example.cc',
-        'examples/label_example.h',
-        'examples/link_example.cc',
-        'examples/link_example.h',
-        'examples/message_box_example.cc',
-        'examples/message_box_example.h',
-        'examples/menu_example.cc',
-        'examples/menu_example.h',
-        'examples/multiline_example.cc',
-        'examples/multiline_example.h',
-        'examples/progress_bar_example.cc',
-        'examples/progress_bar_example.h',
-        'examples/radio_button_example.cc',
-        'examples/radio_button_example.h',
-        'examples/scroll_view_example.cc',
-        'examples/scroll_view_example.h',
-        'examples/single_split_view_example.cc',
-        'examples/single_split_view_example.h',
-        'examples/slider_example.cc',
-        'examples/slider_example.h',
-        'examples/tabbed_pane_example.cc',
-        'examples/tabbed_pane_example.h',
-        'examples/table_example.cc',
-        'examples/table_example.h',
-        'examples/text_example.cc',
-        'examples/text_example.h',
-        'examples/textfield_example.cc',
-        'examples/textfield_example.h',
-        'examples/throbber_example.cc',
-        'examples/throbber_example.h',
-        'examples/tree_view_example.cc',
-        'examples/tree_view_example.h',
-        'examples/views_examples_export.h',
-        'examples/widget_example.cc',
-        'examples/widget_example.h',
-      ],
-      'conditions': [
-        ['OS=="win"', {
-          'include_dirs': [
-            '../third_party/wtl/include',
-          ],
-          # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-          'msvs_disabled_warnings': [ 4267, ],
-        }],
-      ],
-    },  # target_name: views_examples_lib
-    {
-      'target_name': 'views_examples_exe',
-      'type': 'executable',
-      'dependencies': [
-        '../../base/base.gyp:base',
-        '../../base/base.gyp:base_i18n',
-        '../aura/aura.gyp:aura',
-        '../base/ui_base.gyp:ui_base',
-        '../compositor/compositor.gyp:compositor',
-        '../compositor/compositor.gyp:compositor_test_support',
-        '../gfx/gfx.gyp:gfx',
-        '../resources/ui_resources.gyp:ui_test_pak',
-        'views',
-        'views_examples_lib',
-        'views_test_support',
-      ],
-      'sources': [
-        'examples/examples_main.cc',
-      ],
-    },  # target_name: views_examples_exe
-    {
-      'target_name': 'views_examples_with_content_lib',
-      'type': '<(component)',
-      'dependencies': [
-        '../../base/base.gyp:base',
-        '../../base/base.gyp:base_i18n',
-        '../../content/content.gyp:content',
-        '../../skia/skia.gyp:skia',
-        '../../third_party/icu/icu.gyp:icui18n',
-        '../../third_party/icu/icu.gyp:icuuc',
-        '../../url/url.gyp:url_lib',
-        '../aura/aura.gyp:aura',
-        '../base/ui_base.gyp:ui_base',
-        '../events/events.gyp:events',
-        '../gfx/gfx.gyp:gfx',
-        '../gfx/gfx.gyp:gfx_geometry',
-        '../resources/ui_resources.gyp:ui_resources',
-        '../resources/ui_resources.gyp:ui_test_pak',
-        'controls/webview/webview.gyp:webview',
-        'views',
-        'views_examples_lib',
-      ],
-      'include_dirs': [
-        '..',
-      ],
-      'defines': [
-        'VIEWS_EXAMPLES_WITH_CONTENT_IMPLEMENTATION',
-      ],
-      'sources': [
-        'examples/examples_window_with_content.cc',
-        'examples/examples_window_with_content.h',
-        'examples/views_examples_with_content_export.h',
-        'examples/webview_example.cc',
-        'examples/webview_example.h',
-      ],
-      'conditions': [
-        ['OS=="win"', {
-          'include_dirs': [
-            '../third_party/wtl/include',
-          ],
-          # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
-          'msvs_disabled_warnings': [ 4267, ],
-        }],
-      ],
-    },  # target_name: views_examples_with_content_lib
-    {
-      'target_name': 'views_examples_with_content_exe',
-      'type': 'executable',
-      'dependencies': [
-        '../../base/base.gyp:base',
-        '../../base/base.gyp:base_i18n',
-        '../../content/content.gyp:content',
-        '../../content/content_shell_and_tests.gyp:content_shell_lib',
-        '../../content/content_shell_and_tests.gyp:test_support_content',
-        '../../skia/skia.gyp:skia',
-        '../../third_party/icu/icu.gyp:icui18n',
-        '../../third_party/icu/icu.gyp:icuuc',
-        '../aura/aura.gyp:aura',
-        '../base/ui_base.gyp:ui_base',
-        '../compositor/compositor.gyp:compositor',
-        '../events/events.gyp:events',
-        '../gfx/gfx.gyp:gfx',
-        '../gfx/gfx.gyp:gfx_geometry',
-        '../resources/ui_resources.gyp:ui_resources',
-        '../resources/ui_resources.gyp:ui_test_pak',
-        '../wm/wm.gyp:wm_test_support',
-        'views',
-        'views_examples_with_content_lib',
-        'views_test_support'
-      ],
-      'include_dirs': [
-        '../..',
-      ],
-      'sources': [
-        '../../content/app/startup_helper_win.cc',
-        'examples/content_client/examples_browser_main_parts.cc',
-        'examples/content_client/examples_browser_main_parts.h',
-        'examples/content_client/examples_content_browser_client.cc',
-        'examples/content_client/examples_content_browser_client.h',
-        'examples/content_client/examples_main_delegate.cc',
-        'examples/content_client/examples_main_delegate.h',
-        'examples/content_client/examples_main.cc',
-      ],
-      'conditions': [
-        ['OS=="win"', {
-          'link_settings': {
-            'libraries': [
-              '-limm32.lib',
-              '-loleacc.lib',
-            ]
-          },
-          'msvs_settings': {
-            'VCManifestTool': {
-              'AdditionalManifestFiles': [
-                'examples\\views_examples.exe.manifest',
-              ],
-            },
-            'VCLinkerTool': {
-              'SubSystem': '2',  # Set /SUBSYSTEM:WINDOWS
-            },
-          },
-          'dependencies': [
-            '../../sandbox/sandbox.gyp:sandbox',
-          ],
-        }],
-        ['OS=="win"', {
-          'sources/': [
-            # This is needed because the aura rule strips it from the default
-            # sources list.
-            ['include', '^../../content/app/startup_helper_win.cc'],
-          ],
-        }],
-      ],
-    },  # target_name: views_examples_with_content_exe
   ],
 }
diff --git a/ui/views/widget/desktop_aura/desktop_dispatcher_client.h b/ui/views/widget/desktop_aura/desktop_dispatcher_client.h
index 0d01df2..5351d8a 100644
--- a/ui/views/widget/desktop_aura/desktop_dispatcher_client.h
+++ b/ui/views/widget/desktop_aura/desktop_dispatcher_client.h
@@ -8,8 +8,8 @@
 #include "base/basictypes.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/aura/client/dispatcher_client.h"
 #include "ui/views/views_export.h"
+#include "ui/wm/public/dispatcher_client.h"
 
 namespace views {
 
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
index 0fcebdc..c56a3ce 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -10,10 +10,9 @@
 #include "base/lazy_instance.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_pump_dispatcher.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
+#include "ui/base/clipboard/clipboard.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/drop_target_event.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
@@ -22,6 +21,8 @@
 #include "ui/base/x/x11_util.h"
 #include "ui/events/event.h"
 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/drag_drop_delegate.h"
 
 using aura::client::DragDropDelegate;
 using ui::OSExchangeData;
@@ -36,19 +37,23 @@
 const char kXdndActionCopy[] = "XdndActionCopy";
 const char kXdndActionMove[] = "XdndActionMove";
 const char kXdndActionLink[] = "XdndActionLink";
+const char kXdndActionDirectSave[] = "XdndActionDirectSave";
 
 const char kChromiumDragReciever[] = "_CHROMIUM_DRAG_RECEIVER";
 const char kXdndSelection[] = "XdndSelection";
+const char kXdndDirectSave0[] = "XdndDirectSave0";
 
 const char* kAtomsToCache[] = {
   kChromiumDragReciever,
   "XdndActionAsk",
   kXdndActionCopy,
+  kXdndActionDirectSave,
   kXdndActionLink,
   "XdndActionList",
   kXdndActionMove,
   "XdndActionPrivate",
   "XdndAware",
+  kXdndDirectSave0,
   "XdndDrop",
   "XdndEnter",
   "XdndFinished",
@@ -58,9 +63,15 @@
   kXdndSelection,
   "XdndStatus",
   "XdndTypeList",
+  ui::Clipboard::kMimeTypeText,
+  "_NET_WM_WINDOW_TYPE_MENU",
   NULL
 };
 
+// The time to wait for the target to respond after the user has released the
+// mouse button before ending the move loop.
+const int kEndMoveLoopTimeoutMs = 30000;
+
 static base::LazyInstance<
     std::map< ::Window, views::DesktopDragDropClientAuraX11*> >::Leaky
         g_live_client_map = LAZY_INSTANCE_INITIALIZER;
@@ -70,9 +81,11 @@
 class DragTargetWindowFinder : public ui::EnumerateWindowsDelegate {
  public:
   DragTargetWindowFinder(XID ignored_icon_window,
+                         Atom menu_type_atom,
                          gfx::Point screen_loc)
       : ignored_icon_window_(ignored_icon_window),
         output_window_(None),
+        menu_type_atom_(menu_type_atom),
         screen_loc_(screen_loc) {
     ui::EnumerateTopLevelWindows(this);
   }
@@ -92,7 +105,10 @@
     if (!ui::WindowContainsPoint(window, screen_loc_))
       return false;
 
-    if (ui::PropertyExists(window, "WM_STATE")) {
+    int value = 0;
+    if (ui::PropertyExists(window, "WM_STATE") ||
+        (ui::GetIntProperty(window, "_NET_WM_WINDOW_TYPE", &value) &&
+         static_cast<Atom>(value) == menu_type_atom_)) {
       output_window_ = window;
       return true;
     }
@@ -103,6 +119,7 @@
  private:
   XID ignored_icon_window_;
   XID output_window_;
+  const Atom menu_type_atom_;
   gfx::Point screen_loc_;
 
   DISALLOW_COPY_AND_ASSIGN(DragTargetWindowFinder);
@@ -113,8 +130,9 @@
 // |mouse_window|. If there's a Xdnd aware window, it will be returned in
 // |dest_window|.
 void FindWindowFor(const gfx::Point& screen_point,
-                   ::Window* mouse_window, ::Window* dest_window) {
-  DragTargetWindowFinder finder(None, screen_point);
+                   ::Window* mouse_window, ::Window* dest_window,
+                   Atom menu_type_atom) {
+  DragTargetWindowFinder finder(None, menu_type_atom, screen_point);
   *mouse_window = finder.window();
   *dest_window = None;
 
@@ -404,6 +422,7 @@
       target_window_(NULL),
       source_provider_(NULL),
       source_current_window_(None),
+      source_state_(SOURCE_STATE_OTHER),
       drag_operation_(0),
       resulting_operation_(0),
       grab_cursor_(cursor_manager->GetInitializedCursor(ui::kCursorGrabbing)),
@@ -423,6 +442,10 @@
 
 DesktopDragDropClientAuraX11::~DesktopDragDropClientAuraX11() {
   g_live_client_map.Get().erase(xwindow_);
+  // Make sure that all observers are unregistered from source and target
+  // windows. This may be necessary when the parent native widget gets destroyed
+  // while a drag operation is in progress.
+  NotifyDragLeave();
 }
 
 // static
@@ -489,6 +512,11 @@
   DVLOG(1) << "XdndStatus";
 
   unsigned long source_window = event.data.l[0];
+
+  waiting_on_status_.erase(source_window);
+  if (source_window != source_current_window_)
+    return;
+
   int drag_operation = ui::DragDropTypes::DRAG_NONE;
   if (event.data.l[1] & 1) {
     ::Atom atom_operation = event.data.l[4];
@@ -514,16 +542,16 @@
   // the spec) the other side must handle further position messages within
   // it. GTK+ doesn't bother with this, so neither should we.
 
-  waiting_on_status_.erase(source_window);
-
-  if (ContainsKey(pending_drop_, source_window)) {
+  if (source_state_ == SOURCE_STATE_PENDING_DROP) {
     // We were waiting on the status message so we could send the XdndDrop.
+    source_state_ = SOURCE_STATE_DROPPED;
     SendXdndDrop(source_window);
     return;
   }
 
   NextPositionMap::iterator it = next_position_message_.find(source_window);
-  if (it != next_position_message_.end()) {
+  if (source_state_ == SOURCE_STATE_OTHER &&
+      it != next_position_message_.end()) {
     // We were waiting on the status message so we could send off the next
     // position message we queued up.
     gfx::Point p = it->second.first;
@@ -599,6 +627,8 @@
   source_current_window_ = None;
   DCHECK(!g_current_drag_drop_client);
   g_current_drag_drop_client = this;
+  waiting_on_status_.clear();
+  source_state_ = SOURCE_STATE_OTHER;
   drag_operation_ = operation;
   resulting_operation_ = ui::DragDropTypes::DRAG_NONE;
 
@@ -609,6 +639,14 @@
   source_provider_->TakeOwnershipOfSelection();
 
   std::vector< ::Atom> actions = GetOfferedDragOperations();
+  if (!source_provider_->file_contents_name().empty()) {
+    actions.push_back(atom_cache_.GetAtom(kXdndActionDirectSave));
+    ui::SetStringProperty(
+        xwindow_,
+        atom_cache_.GetAtom(kXdndDirectSave0),
+        atom_cache_.GetAtom(ui::Clipboard::kMimeTypeText),
+        source_provider_->file_contents_name().AsUTF8Unsafe());
+  }
   ui::SetAtomArrayProperty(xwindow_, "XdndActionList", "ATOM", actions);
 
   // It is possible for the DesktopWindowTreeHostX11 to be destroyed during the
@@ -631,6 +669,7 @@
     g_current_drag_drop_client = NULL;
     drag_operation_ = 0;
     XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom("XdndActionList"));
+    XDeleteProperty(xdisplay_, xwindow_, atom_cache_.GetAtom(kXdndDirectSave0));
 
     return resulting_operation_;
   }
@@ -663,10 +702,14 @@
 void DesktopDragDropClientAuraX11::OnMouseMovement(XMotionEvent* event) {
   gfx::Point screen_point(event->x_root, event->y_root);
 
+  if (source_state_ != SOURCE_STATE_OTHER)
+    return;
+
   // Find the current window the cursor is over.
   ::Window mouse_window = None;
   ::Window dest_window = None;
-  FindWindowFor(screen_point, &mouse_window, &dest_window);
+  FindWindowFor(screen_point, &mouse_window, &dest_window,
+                atom_cache_.GetAtom("_NET_WM_WINDOW_TYPE_MENU"));
 
   if (source_current_window_ != dest_window) {
     if (source_current_window_ != None)
@@ -695,7 +738,11 @@
     if (ContainsKey(waiting_on_status_, source_current_window_)) {
       // If we are waiting for an XdndStatus message, we need to wait for it to
       // complete.
-      pending_drop_.insert(source_current_window_);
+      source_state_ = SOURCE_STATE_PENDING_DROP;
+
+      // Start timer to end the move loop if the target takes too long to send
+      // the XdndStatus and XdndFinished messages.
+      StartEndMoveLoopTimer();
       return;
     }
 
@@ -703,7 +750,12 @@
         negotiated_operation_.find(source_current_window_);
     if (it != negotiated_operation_.end() && it->second != None) {
       // We have negotiated an action with the other end.
+      source_state_ = SOURCE_STATE_DROPPED;
       SendXdndDrop(source_current_window_);
+
+      // Start timer to end the move loop if the target takes too long to send
+      // an XdndFinished message.
+      StartEndMoveLoopTimer();
       return;
     }
 
@@ -718,6 +770,20 @@
   if (source_current_window_ != None)
     SendXdndLeave(source_current_window_);
   target_current_context_.reset();
+  source_state_ = SOURCE_STATE_OTHER;
+  end_move_loop_timer_.Stop();
+}
+
+void DesktopDragDropClientAuraX11::StartEndMoveLoopTimer() {
+  end_move_loop_timer_.Start(FROM_HERE,
+                             base::TimeDelta::FromMilliseconds(
+                                 kEndMoveLoopTimeoutMs),
+                             this,
+                             &DesktopDragDropClientAuraX11::EndMoveLoop);
+}
+
+void DesktopDragDropClientAuraX11::EndMoveLoop() {
+  move_loop_.EndMoveLoop();
 }
 
 void DesktopDragDropClientAuraX11::DragTranslate(
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
index f77e60f..360e31c 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
@@ -11,7 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/aura/client/drag_drop_client.h"
+#include "base/timer/timer.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/cursor/cursor.h"
 #include "ui/gfx/point.h"
@@ -19,6 +19,7 @@
 #include "ui/views/views_export.h"
 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop_delegate.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 namespace aura {
 namespace client {
@@ -96,6 +97,28 @@
   virtual void OnMoveLoopEnded() OVERRIDE;
 
  private:
+  enum SourceState {
+    // |source_current_window_| will receive a drop once we receive an
+    // XdndStatus from it.
+    SOURCE_STATE_PENDING_DROP,
+
+    // The move looped will be ended once we receive XdndFinished from
+    // |source_current_window_|. We should not send XdndPosition to
+    // |source_current_window_| while in this state.
+    SOURCE_STATE_DROPPED,
+
+    // There is no drag in progress or there is a drag in progress and the
+    // user has not yet released the mouse.
+    SOURCE_STATE_OTHER,
+  };
+
+  // Start timer to end the move loop if the target is too slow to respond after
+  // the mouse is released.
+  void StartEndMoveLoopTimer();
+
+  // Ends the move loop.
+  void EndMoveLoop();
+
   typedef std::map< ::Window, std::pair<gfx::Point, unsigned long> >
       NextPositionMap;
 
@@ -184,6 +207,7 @@
   // Source side information.
   ui::OSExchangeDataProviderAuraX11 const* source_provider_;
   ::Window source_current_window_;
+  SourceState source_state_;
 
   // The current drag-drop client that has an active operation. Since we have
   // multiple root windows and multiple DesktopDragDropClientAuraX11 instances
@@ -198,10 +222,6 @@
   // message.
   int resulting_operation_;
 
-  // This window will be receiving a drop as soon as we receive an XdndStatus
-  // from it.
-  std::set< ::Window> pending_drop_;
-
   // We offer the other window a list of possible operations,
   // XdndActionsList. This is the requested action from the other window. This
   // is None if we haven't sent out an XdndPosition message yet, haven't yet
@@ -213,6 +233,10 @@
   // window responds to an XdndStatus.
   std::map< ::Window, ::Atom> negotiated_operation_;
 
+  // Ends the move loop if the target is too slow to respond after the mouse is
+  // released.
+  base::OneShotTimer<DesktopDragDropClientAuraX11> end_move_loop_timer_;
+
   // We use these cursors while dragging.
   gfx::NativeCursor grab_cursor_;
   gfx::NativeCursor copy_grab_cursor_;
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
index eda12e0..a8051ca 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
@@ -7,8 +7,8 @@
 
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/views/views_export.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 namespace ui {
 class DragSourceWin;
diff --git a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
index f1409f8..1369b62 100644
--- a/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
@@ -5,14 +5,14 @@
 #include "ui/views/widget/desktop_aura/desktop_drop_target_win.h"
 
 #include "base/win/win_util.h"
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/drop_target_event.h"
 #include "ui/base/dragdrop/os_exchange_data_provider_win.h"
 #include "ui/events/event_constants.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/drag_drop_delegate.h"
 
 using aura::client::DragDropDelegate;
 using ui::OSExchangeData;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 0caeab2..8341bce 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -6,10 +6,8 @@
 
 #include "base/bind.h"
 #include "base/debug/trace_event.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/window.h"
@@ -55,6 +53,8 @@
 #include "ui/wm/core/shadow_types.h"
 #include "ui/wm/core/visibility_controller.h"
 #include "ui/wm/core/window_modality_controller.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 #if defined(OS_WIN)
 #include "ui/base/win/shell.h"
@@ -983,9 +983,6 @@
   native_widget_delegate_->GetHitTestMask(mask);
 }
 
-void DesktopNativeWidgetAura::DidRecreateLayer(ui::Layer* old_layer,
-                                               ui::Layer* new_layer) {}
-
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopNativeWidgetAura, ui::EventHandler implementation:
 
@@ -1136,7 +1133,7 @@
 
 void DesktopNativeWidgetAura::OnHostCloseRequested(
     const aura::WindowTreeHost* host) {
-  Close();
+  GetWidget()->Close();
 }
 
 void DesktopNativeWidgetAura::OnHostResized(const aura::WindowTreeHost* host) {
@@ -1182,6 +1179,10 @@
 void DesktopNativeWidgetAura::UpdateWindowTransparency() {
   content_window_->SetTransparent(
       desktop_window_tree_host_->ShouldWindowContentsBeTransparent());
+  // Regardless of transparency or not, this root content window will always
+  // fill its bounds completely, so set this flag to true to avoid an
+  // unecessary clear before update.
+  content_window_->SetFillsBoundsCompletely(true);
 }
 
 void DesktopNativeWidgetAura::RootWindowDestroyed() {
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index 05573b9..c2966d9 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -6,9 +6,6 @@
 #define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_NATIVE_WIDGET_AURA_H_
 
 #include "base/memory/weak_ptr.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_tree_host_observer.h"
@@ -16,6 +13,9 @@
 #include "ui/views/ime/input_method_delegate.h"
 #include "ui/views/widget/native_widget_private.h"
 #include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_delegate.h"
+#include "ui/wm/public/drag_drop_delegate.h"
 
 namespace aura {
 class WindowEventDispatcher;
@@ -200,8 +200,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
   virtual bool HasHitTestMask() const OVERRIDE;
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE;
 
   // Overridden from ui::EventHandler:
   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
index 6752cfb..30dc551 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -6,12 +6,12 @@
 
 #include "base/bind.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/dispatcher_client.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/dispatcher_client.h"
 
 namespace views {
 
diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index f5a6a7f..970d86c 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -12,12 +12,12 @@
 
 #include "base/debug/trace_event.h"
 #include "base/logging.h"
-#include "base/x11/edid_parser_x11.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/layout.h"
 #include "ui/base/x/x11_util.h"
+#include "ui/display/x11/edid_parser_x11.h"
 #include "ui/gfx/display.h"
 #include "ui/gfx/display_observer.h"
 #include "ui/gfx/native_widget_types.h"
@@ -376,7 +376,7 @@
                                          output_info->crtc);
 
       int64 display_id = -1;
-      if (!base::GetDisplayId(output_id, i, &display_id)) {
+      if (!ui::GetDisplayId(output_id, static_cast<uint8>(i), &display_id)) {
         // It isn't ideal, but if we can't parse the EDID data, fallback on the
         // display number.
         display_id = i;
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 47bd630..2fc499b 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -10,7 +10,6 @@
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/client/focus_client.h"
-#include "ui/aura/client/scoped_tooltip_disabler.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_property.h"
 #include "ui/base/cursor/cursor_loader_win.h"
@@ -40,6 +39,7 @@
 #include "ui/wm/core/compound_event_filter.h"
 #include "ui/wm/core/input_method_event_filter.h"
 #include "ui/wm/core/window_animations.h"
+#include "ui/wm/public/scoped_tooltip_disabler.h"
 
 namespace views {
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index a510ed3..dc8a218 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -5,11 +5,11 @@
 #ifndef UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_WIN_H_
 #define UI_VIEWS_WIDGET_DESKTOP_AURA_DESKTOP_WINDOW_TREE_HOST_WIN_H_
 
-#include "ui/aura/client/animation_host.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/views/views_export.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
 #include "ui/views/win/hwnd_message_handler_delegate.h"
+#include "ui/wm/public/animation_host.h"
 
 namespace aura {
 namespace client {
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 41b4b50..716fbb9 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -85,6 +85,7 @@
   "_NET_WM_STATE_MAXIMIZED_VERT",
   "_NET_WM_STATE_SKIP_TASKBAR",
   "_NET_WM_STATE_STICKY",
+  "_NET_WM_USER_TIME",
   "_NET_WM_WINDOW_OPACITY",
   "_NET_WM_WINDOW_TYPE",
   "_NET_WM_WINDOW_TYPE_DND",
@@ -134,7 +135,8 @@
       desktop_native_widget_aura_(desktop_native_widget_aura),
       content_window_(NULL),
       window_parent_(NULL),
-      custom_window_shape_(NULL) {
+      custom_window_shape_(NULL),
+      urgency_hint_set_(false) {
 }
 
 DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
@@ -177,6 +179,7 @@
 void DesktopWindowTreeHostX11::HandleNativeWidgetActivationChanged(
     bool active) {
   if (active) {
+    FlashFrame(false);
     OnHostActivated();
     open_windows().remove(xwindow_);
     open_windows().insert(open_windows().begin(), xwindow_);
@@ -672,8 +675,24 @@
 }
 
 void DesktopWindowTreeHostX11::FlashFrame(bool flash_frame) {
-  // TODO(erg):
-  NOTIMPLEMENTED();
+  if (urgency_hint_set_ == flash_frame)
+    return;
+
+  XWMHints* hints = XGetWMHints(xdisplay_, xwindow_);
+  if (!hints) {
+    // The window hasn't had its hints set yet.
+    hints = XAllocWMHints();
+  }
+
+  if (flash_frame)
+    hints->flags |= XUrgencyHint;
+  else
+    hints->flags &= ~XUrgencyHint;
+
+  XSetWMHints(xdisplay_, xwindow_, hints);
+  XFree(hints);
+
+  urgency_hint_set_ = flash_frame;
 }
 
 void DesktopWindowTreeHostX11::OnRootViewLayout() const {
@@ -1145,6 +1164,11 @@
     event->set_flags(flags);
   }
 
+  // While we unset the urgency hint when we gain focus, we also must remove it
+  // on mouse clicks because we can call FlashFrame() on an active window.
+  if (event->IsAnyButton() || event->IsMouseWheelEvent())
+    FlashFrame(false);
+
   if (!g_current_capture || g_current_capture == this) {
     SendEventToProcessor(event);
   } else {
@@ -1250,13 +1274,26 @@
   size_hints.y = bounds_.y();
   XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
 
-  XWMHints wm_hints;
-  wm_hints.flags = InputHint | StateHint;
-  // If SHOW_STATE_INACTIVE, tell the window manager that the window is not
-  // focusable. This will make the window inactive upon creation.
-  wm_hints.input = show_state != ui::SHOW_STATE_INACTIVE;
-  wm_hints.initial_state = NormalState;
-  XSetWMHints(xdisplay_, xwindow_, &wm_hints);
+  // If SHOW_STATE_INACTIVE, tell the window manager not to focus the window
+  // when mapping. This is done by setting the _NET_WM_USER_TIME to 0. See e.g.
+  // http://standards.freedesktop.org/wm-spec/latest/ar01s05.html
+  if (show_state == ui::SHOW_STATE_INACTIVE) {
+    unsigned long value = 0;
+    XChangeProperty(xdisplay_,
+                    xwindow_,
+                    atom_cache_.GetAtom("_NET_WM_USER_TIME"),
+                    XA_CARDINAL,
+                    32,
+                    PropModeReplace,
+                    reinterpret_cast<const unsigned char *>(&value),
+                    1);
+  } else {
+    // TODO(piman): if this window was created in response to an X event, we
+    // should set the time to the server time of the event that caused this.
+    // https://crbug.com/355667
+    XDeleteProperty(
+        xdisplay_, xwindow_, atom_cache_.GetAtom("_NET_WM_USER_TIME"));
+  }
 
   XMapWindow(xdisplay_, xwindow_);
 
@@ -1265,15 +1302,6 @@
   // asynchronous.
   base::MessagePumpX11::Current()->BlockUntilWindowMapped(xwindow_);
   window_mapped_ = true;
-
-  // The window has been created and mapped. It should now accept input.
-  if (show_state == ui::SHOW_STATE_INACTIVE) {
-    XWMHints wm_hints;
-    wm_hints.flags = InputHint;
-    wm_hints.input = true;
-    // Tell the window manager that the window is now focusable.
-    XSetWMHints(xdisplay_, xwindow_, &wm_hints);
-  }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index 1537a69..eb27d7e 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -291,6 +291,12 @@
 
   base::string16 window_title_;
 
+  // Whether we currently are flashing our frame. This feature is implemented
+  // by setting the urgency hint with the window manager, which can draw
+  // attention to the window or completely ignore the hint. We stop flashing
+  // the frame when |xwindow_| gains focus or handles a mouse button event.
+  bool urgency_hint_set_;
+
   DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostX11);
 };
 
diff --git a/ui/views/widget/desktop_aura/x11_desktop_handler.cc b/ui/views/widget/desktop_aura/x11_desktop_handler.cc
index 3aa874d..46aef17 100644
--- a/ui/views/widget/desktop_aura/x11_desktop_handler.cc
+++ b/ui/views/widget/desktop_aura/x11_desktop_handler.cc
@@ -10,7 +10,9 @@
 #include "base/message_loop/message_loop.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/x/x11_menu_list.h"
 #include "ui/base/x/x11_util.h"
+#include "ui/gfx/x/x11_error_tracker.h"
 
 #if !defined(OS_CHROMEOS)
 #include "ui/views/ime/input_method.h"
@@ -138,6 +140,26 @@
       }
       break;
     }
+    // Menus created by Chrome can be drag and drop targets. Since they are
+    // direct children of the screen root window and have override_redirect
+    // we cannot use regular _NET_CLIENT_LIST_STACKING property to find them
+    // and use a separate cache to keep track of them.
+    // TODO(varkha): Implement caching of all top level X windows and their
+    // coordinates and stacking order to eliminate repeated calls to X server
+    // during mouse movement, drag and shaping events.
+    case CreateNotify: {
+      // The window might be destroyed if the message pump haven't gotten a
+      // chance to run but we can safely ignore the X error.
+      gfx::X11ErrorTracker error_tracker;
+      XCreateWindowEvent *xcwe = &event->xcreatewindow;
+      ui::XMenuList::GetInstance()->MaybeRegisterMenu(xcwe->window);
+      break;
+    }
+    case DestroyNotify: {
+      XDestroyWindowEvent *xdwe = &event->xdestroywindow;
+      ui::XMenuList::GetInstance()->MaybeUnregisterMenu(xdwe->window);
+      break;
+    }
   }
 
   return POST_DISPATCH_NONE;
diff --git a/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h b/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h
index 12e5928..42b7d02 100644
--- a/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h
+++ b/ui/views/widget/desktop_aura/x11_desktop_window_move_client.h
@@ -11,11 +11,11 @@
 #include "base/compiler_specific.h"
 #include "base/message_loop/message_loop.h"
 #include "base/timer/timer.h"
-#include "ui/aura/client/window_move_client.h"
 #include "ui/gfx/point.h"
 #include "ui/views/views_export.h"
 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h"
 #include "ui/views/widget/desktop_aura/x11_whole_screen_move_loop_delegate.h"
+#include "ui/wm/public/window_move_client.h"
 
 namespace aura {
 class WindowTreeHost;
diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
index 3f48b89..09e36dc 100644
--- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
+++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
@@ -8,6 +8,7 @@
 // Get rid of a macro from Xlib.h that conflicts with Aura's RootWindow class.
 #undef RootWindow
 
+#include "base/bind.h"
 #include "base/message_loop/message_loop.h"
 #include "base/message_loop/message_pump_x11.h"
 #include "base/run_loop.h"
@@ -31,6 +32,7 @@
 // The minimum alpha before we declare a pixel transparent when searching in
 // our source image.
 const uint32 kMinAlpha = 32;
+const unsigned char kDragWidgetOpacity = 0xc0;
 
 class ScopedCapturer {
  public:
@@ -56,7 +58,9 @@
     : delegate_(delegate),
       in_move_loop_(false),
       should_reset_mouse_flags_(false),
-      grab_input_window_(None) {
+      grab_input_window_(None),
+      weak_factory_(this) {
+  last_xmotion_.type = LASTEvent;
 }
 
 X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() {}
@@ -64,6 +68,15 @@
 ////////////////////////////////////////////////////////////////////////////////
 // DesktopWindowTreeHostLinux, MessagePumpDispatcher implementation:
 
+void X11WholeScreenMoveLoop::DispatchMouseMovement() {
+  if (!weak_factory_.HasWeakPtrs())
+    return;
+  weak_factory_.InvalidateWeakPtrs();
+  DCHECK_EQ(MotionNotify, last_xmotion_.type);
+  delegate_->OnMouseMovement(&last_xmotion_);
+  last_xmotion_.type = LASTEvent;
+}
+
 uint32_t X11WholeScreenMoveLoop::Dispatch(const base::NativeEvent& event) {
   XEvent* xev = event;
 
@@ -76,14 +89,25 @@
         gfx::Point location = gfx::ToFlooredPoint(
             screen->GetCursorScreenPoint() - drag_offset_);
         drag_widget_->SetBounds(gfx::Rect(location, drag_image_.size()));
+        drag_widget_->StackAtTop();
       }
-      delegate_->OnMouseMovement(&xev->xmotion);
+      last_xmotion_ = xev->xmotion;
+      if (!weak_factory_.HasWeakPtrs()) {
+        // Post a task to dispatch mouse movement event when control returns to
+        // the message loop. This allows smoother dragging since the events are
+        // dispatched without waiting for the drag widget updates.
+        base::MessageLoopForUI::current()->PostTask(
+            FROM_HERE,
+            base::Bind(&X11WholeScreenMoveLoop::DispatchMouseMovement,
+                       weak_factory_.GetWeakPtr()));
+      }
       break;
     }
     case ButtonRelease: {
       if (xev->xbutton.button == Button1) {
         // Assume that drags are being done with the left mouse button. Only
         // break the drag if the left mouse button was released.
+        DispatchMouseMovement();
         delegate_->OnMouseReleased();
       }
       break;
@@ -161,6 +185,10 @@
   if (!in_move_loop_)
     return;
 
+  // Prevent DispatchMouseMovement from dispatching any posted motion event.
+  weak_factory_.InvalidateWeakPtrs();
+  last_xmotion_.type = LASTEvent;
+
   // We undo our emulated mouse click from RunMoveLoop();
   if (should_reset_mouse_flags_) {
     aura::Env::GetInstance()->set_mouse_button_flags(0);
@@ -267,6 +295,7 @@
   widget->set_focus_on_creation(false);
   widget->set_frame_type(Widget::FRAME_TYPE_FORCE_NATIVE);
   widget->Init(params);
+  widget->SetOpacity(kDragWidgetOpacity);
   widget->GetNativeWindow()->SetName("DragWindow");
 
   ImageView* image = new ImageView();
diff --git a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h
index 9fd51cb..347771e 100644
--- a/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h
+++ b/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h
@@ -7,6 +7,7 @@
 
 #include "base/callback.h"
 #include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_pump_dispatcher.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/native_widget_types.h"
@@ -62,6 +63,9 @@
   // (defined as having a pixel with alpha > 32). If so, return true.
   bool CheckIfIconValid();
 
+  // Dispatch mouse movement event to |delegate_| in a posted task.
+  void DispatchMouseMovement();
+
   X11WholeScreenMoveLoopDelegate* delegate_;
 
   // Are we running a nested message loop from RunMoveLoop()?
@@ -81,6 +85,8 @@
   scoped_ptr<Widget> drag_widget_;
   gfx::ImageSkia drag_image_;
   gfx::Vector2dF drag_offset_;
+  XMotionEvent last_xmotion_;
+  base::WeakPtrFactory<X11WholeScreenMoveLoop> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(X11WholeScreenMoveLoop);
 };
diff --git a/ui/views/widget/native_widget_aura.cc b/ui/views/widget/native_widget_aura.cc
index 30f2aea..75e78a4 100644
--- a/ui/views/widget/native_widget_aura.cc
+++ b/ui/views/widget/native_widget_aura.cc
@@ -7,13 +7,10 @@
 #include "base/bind.h"
 #include "base/strings/string_util.h"
 #include "third_party/skia/include/core/SkRegion.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/window_move_client.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -30,7 +27,6 @@
 #include "ui/views/drag_utils.h"
 #include "ui/views/ime/input_method_bridge.h"
 #include "ui/views/views_delegate.h"
-#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
 #include "ui/views/widget/drop_helper.h"
 #include "ui/views/widget/native_widget_delegate.h"
 #include "ui/views/widget/root_view.h"
@@ -39,6 +35,9 @@
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/widget/window_reorderer.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/drag_drop_client.h"
+#include "ui/wm/public/window_move_client.h"
 #include "ui/wm/public/window_types.h"
 
 #if defined(OS_WIN)
@@ -53,6 +52,7 @@
 #endif
 
 #if !defined(OS_CHROMEOS)
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
 #include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
 #endif
 
@@ -811,10 +811,6 @@
   delegate_->GetHitTestMask(mask);
 }
 
-void NativeWidgetAura::DidRecreateLayer(ui::Layer *old_layer,
-                                        ui::Layer *new_layer) {
-}
-
 ////////////////////////////////////////////////////////////////////////////////
 // NativeWidgetAura, ui::EventHandler implementation:
 
diff --git a/ui/views/widget/native_widget_aura.h b/ui/views/widget/native_widget_aura.h
index f5082f0..6ca1e71 100644
--- a/ui/views/widget/native_widget_aura.h
+++ b/ui/views/widget/native_widget_aura.h
@@ -7,9 +7,6 @@
 
 #include "base/memory/scoped_vector.h"
 #include "base/memory/weak_ptr.h"
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_delegate.h"
-#include "ui/aura/client/drag_drop_delegate.h"
 #include "ui/aura/client/focus_change_observer.h"
 #include "ui/aura/window_delegate.h"
 #include "ui/base/cursor/cursor.h"
@@ -17,6 +14,9 @@
 #include "ui/views/ime/input_method_delegate.h"
 #include "ui/views/views_export.h"
 #include "ui/views/widget/native_widget_private.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_delegate.h"
+#include "ui/wm/public/drag_drop_delegate.h"
 
 namespace aura {
 class Window;
@@ -158,8 +158,6 @@
   virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE;
   virtual bool HasHitTestMask() const OVERRIDE;
   virtual void GetHitTestMask(gfx::Path* mask) const OVERRIDE;
-  virtual void DidRecreateLayer(ui::Layer* old_layer,
-                                ui::Layer* new_layer) OVERRIDE;
 
   // Overridden from ui::EventHandler:
   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE;
diff --git a/ui/views/widget/tooltip_manager_aura.cc b/ui/views/widget/tooltip_manager_aura.cc
index fa04cb0..986ea5d 100644
--- a/ui/views/widget/tooltip_manager_aura.cc
+++ b/ui/views/widget/tooltip_manager_aura.cc
@@ -6,13 +6,13 @@
 
 #include "base/logging.h"
 #include "ui/aura/client/screen_position_client.h"
-#include "ui/aura/client/tooltip_client.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/aura/window_tree_host.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/rect.h"
 #include "ui/gfx/screen.h"
 #include "ui/views/widget/widget.h"
+#include "ui/wm/public/tooltip_client.h"
 
 namespace views {
 
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc
index 232e88a..6aa255f 100644
--- a/ui/views/widget/widget_interactive_uitest.cc
+++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -6,7 +6,6 @@
 #include "base/bind.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
@@ -19,6 +18,7 @@
 #include "ui/views/test/widget_test.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
+#include "ui/wm/public/activation_client.h"
 
 #if !defined(OS_CHROMEOS)
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 41b7820..92c8512 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -1194,7 +1194,7 @@
     return;
 
   // We need to clip to the dirty rect ourselves.
-  layered_window_contents_->sk_canvas()->save(SkCanvas::kClip_SaveFlag);
+  layered_window_contents_->sk_canvas()->save();
   double scale = gfx::win::GetDeviceScaleFactor();
   layered_window_contents_->sk_canvas()->scale(
       SkScalar(scale),SkScalar(scale));
diff --git a/ui/webui/resources/js/cr/promise.js b/ui/webui/resources/js/cr/promise.js
deleted file mode 100644
index f0681c1..0000000
--- a/ui/webui/resources/js/cr/promise.js
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview This implementes a future promise class.
- */
-
-cr.define('cr', function() {
-
-  /**
-   * Sentinel used to mark a value as pending.
-   * @const
-   */
-  var PENDING_VALUE = {};
-
-  /**
-   * Creates a future promise.
-   * @param {*=} opt_value The value to set the promise to. If set completes
-   *     the promise immediately.
-   * @constructor
-   */
-  function Promise(opt_value) {
-    /**
-     * An array of the callbacks.
-     * @type {!Array.<!Function>}
-     * @private
-     */
-    this.callbacks_ = [];
-
-    if (arguments.length > 0)
-      this.value = opt_value;
-  }
-
-  Promise.prototype = {
-    /**
-     * The current value.
-     * @type {*}
-     * @private
-     */
-    value_: PENDING_VALUE,
-
-    /**
-     * The value of the future promise. Accessing this before the promise has
-     * been fulfilled will throw an error. If this is set to an exception
-     * accessing this will throw as well.
-     * @type {*}
-     */
-    get value() {
-      return this.done ? this.value_ : undefined;
-    },
-    set value(value) {
-      if (!this.done) {
-        this.value_ = value;
-        for (var i = 0; i < this.callbacks_.length; i++) {
-          this.callbacks_[i].call(null, value);
-        }
-        this.callbacks_.length = 0;
-      }
-    },
-
-    /**
-     * Whether the future promise has been fulfilled.
-     * @type {boolean}
-     */
-    get done() {
-      return this.value_ !== PENDING_VALUE;
-    },
-
-    /**
-     * Adds a listener to the future promise. The function will be called when
-     * the promise is fulfilled. If the promise is already fullfilled this will
-     * never call the function.
-     * @param {!Function} fun The function to call.
-     */
-    addListener: function(fun) {
-      if (this.done)
-        fun(this.value);
-      else
-        this.callbacks_.push(fun);
-    },
-
-    /**
-     * Removes a previously added listener from the future promise.
-     * @param {!Function} fun The function to remove.
-     */
-    removeListener: function(fun) {
-      var i = this.callbacks_.indexOf(fun);
-      if (i >= 0)
-        this.callbacks_.splice(i, 1);
-    },
-
-    /**
-     * If the promise is done then this returns the string representation of
-     * the value.
-     * @return {string} The string representation of the promise.
-     * @override
-     */
-    toString: function() {
-      if (this.done)
-        return String(this.value);
-      else
-        return '[object Promise]';
-    },
-
-    /**
-     * Override to allow arithmetic.
-     * @override
-     */
-    valueOf: function() {
-      return this.value;
-    }
-  };
-
-  /**
-   * When a future promise is done call {@code fun}. This also calls the
-   * function if the promise has already been fulfilled.
-   * @param {!Promise} p The promise.
-   * @param {!Function} fun The function to call when the promise is fulfilled.
-   */
-  Promise.when = function(p, fun) {
-    p.addListener(fun);
-  };
-
-  /**
-   * Creates a new promise the will be fulfilled after {@code t} ms.
-   * @param {number} t The time to wait before the promise is fulfilled.
-   * @param {*=} opt_value The value to return after the wait.
-   * @return {!Promise} The new future promise.
-   */
-  Promise.wait = function(t, opt_value) {
-    var p = new Promise;
-    window.setTimeout(function() {
-      p.value = opt_value;
-    }, t);
-    return p;
-  };
-
-  /**
-   * Creates a new future promise that is fulfilled when any of the promises are
-   * fulfilled. The value of the returned promise will be the value of the first
-   * fulfilled promise.
-   * @param {...!Promise} var_args The promises used to build up the new
-   *     promise.
-   * @return {!Promise} The new promise that will be fulfilled when any of the
-   *     passed in promises are fulfilled.
-   */
-  Promise.any = function(var_args) {
-    var p = new Promise;
-    function f(v) {
-      p.value = v;
-    }
-    for (var i = 0; i < arguments.length; i++) {
-      arguments[i].addListener(f);
-    }
-    return p;
-  };
-
-  /**
-   * Creates a new future promise that is fulfilled when all of the promises are
-   * fulfilled. The value of the returned promise is an array of the values of
-   * the promises passed in.
-   * @param {...!Promise} var_args The promises used to build up the new
-   *     promise.
-   * @return {!Promise} The promise that wraps all the promises in the array.
-   */
-  Promise.all = function(var_args) {
-    var p = new Promise;
-    var args = Array.prototype.slice.call(arguments);
-    var count = args.length;
-    if (!count) {
-      p.value = [];
-      return p;
-    }
-
-    function f(v) {
-      count--;
-      if (!count) {
-        p.value = args.map(function(argP) {
-          return argP.value;
-        });
-      }
-    }
-
-    // Do not use count here since count may be decremented in the call to
-    // addListener if the promise is already done.
-    for (var i = 0; i < args.length; i++) {
-      args[i].addListener(f);
-    }
-
-    return p;
-  };
-
-  /**
-   * Wraps an event in a future promise.
-   * @param {!EventTarget} target The object that dispatches the event.
-   * @param {string} type The type of the event.
-   * @param {boolean=} opt_useCapture Whether to listen to the capture phase or
-   *     the bubble phase.
-   * @return {!Promise} The promise that will be fulfilled when the event is
-   *     dispatched.
-   */
-  Promise.event = function(target, type, opt_useCapture) {
-    var p = new Promise;
-    target.addEventListener(type, function(e) {
-      p.value = e;
-    }, opt_useCapture);
-    return p;
-  };
-
-  return {
-    Promise: Promise
-  };
-});
diff --git a/ui/webui/resources/js/util.js b/ui/webui/resources/js/util.js
index 56e2d2d..8bf3059 100644
--- a/ui/webui/resources/js/util.js
+++ b/ui/webui/resources/js/util.js
@@ -21,6 +21,25 @@
 }
 
 /**
+ * Add an accessible message to the page that will be announced to
+ * users who have spoken feedback on, but will be invisible to all
+ * other users. It's removed right away so it doesn't clutter the DOM.
+ * @param {string} msg The text to be pronounced.
+ */
+function announceAccessibleMessage(msg) {
+  var element = document.createElement('div');
+  element.setAttribute('aria-live', 'polite');
+  element.style.position = 'relative';
+  element.style.left = '-9999px';
+  element.style.height = '0px';
+  element.innerText = msg;
+  document.body.appendChild(element);
+  window.setTimeout(function() {
+    document.body.removeChild(element);
+  }, 0);
+}
+
+/**
  * Calls chrome.send with a callback and restores the original afterwards.
  * @param {string} name The name of the message to send.
  * @param {!Array} params The parameters to send.
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd
index 107f7b6..dba0606 100644
--- a/ui/webui/resources/webui_resources.grd
+++ b/ui/webui/resources/webui_resources.grd
@@ -253,8 +253,6 @@
                  file="js/cr/event_target.js" type="chrome_html" />
       <structure name="IDR_WEBUI_JS_CR_LINK_CONTROLLER"
                  file="js/cr/link_controller.js" type="chrome_html" />
-      <structure name="IDR_WEBUI_JS_CR_PROMISE"
-                 file="js/cr/promise.js" type="chrome_html" />
       <structure name="IDR_WEBUI_JS_CR_UI"
                  file="js/cr/ui.js" type="chrome_html" />
       <structure name="IDR_WEBUI_JS_CR_UI_ALERT_OVERLAY"
diff --git a/ui/wm/core/base_focus_rules.cc b/ui/wm/core/base_focus_rules.cc
index bb90941..e7160b7 100644
--- a/ui/wm/core/base_focus_rules.cc
+++ b/ui/wm/core/base_focus_rules.cc
@@ -4,12 +4,12 @@
 
 #include "ui/wm/core/base_focus_rules.h"
 
-#include "ui/aura/client/activation_delegate.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/wm/core/window_modality_controller.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_delegate.h"
 
 namespace wm {
 namespace {
diff --git a/ui/wm/core/compound_event_filter.cc b/ui/wm/core/compound_event_filter.cc
index 620babd..edb7146 100644
--- a/ui/wm/core/compound_event_filter.cc
+++ b/ui/wm/core/compound_event_filter.cc
@@ -6,9 +6,7 @@
 
 #include "base/containers/hash_tables.h"
 #include "base/logging.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/cursor_client.h"
-#include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -16,6 +14,8 @@
 #include "ui/aura/window_tracker.h"
 #include "ui/base/hit_test.h"
 #include "ui/events/event.h"
+#include "ui/wm/public/activation_client.h"
+#include "ui/wm/public/drag_drop_client.h"
 
 #if defined(OS_CHROMEOS) && defined(USE_X11)
 #include "ui/events/x/touch_factory_x11.h"
@@ -291,17 +291,6 @@
     while (!event->stopped_propagation() && (handler = it.GetNext()) != NULL)
       handler->OnGestureEvent(event);
   }
-
-#if defined(OS_WIN)
-  // A Win8 edge swipe event is a special event that does not have location
-  // information associated with it, and is not preceeded by an ET_TOUCH_PRESSED
-  // event.  So we treat it specially here.
-  if (!event->handled() && event->type() == ui::ET_GESTURE_WIN8_EDGE_SWIPE &&
-      !aura::Env::GetInstance()->IsMouseButtonDown()) {
-    SetMouseEventsEnableStateOnEvent(
-        static_cast<aura::Window*>(event->target()), event, false);
-  }
-#endif
 }
 
 }  // namespace wm
diff --git a/ui/wm/core/compound_event_filter_unittest.cc b/ui/wm/core/compound_event_filter_unittest.cc
index a0d193e..9cc9b60 100644
--- a/ui/wm/core/compound_event_filter_unittest.cc
+++ b/ui/wm/core/compound_event_filter_unittest.cc
@@ -4,7 +4,6 @@
 
 #include "ui/wm/core/compound_event_filter.h"
 
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/cursor_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/test/aura_test_base.h"
@@ -15,6 +14,7 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/events/event.h"
 #include "ui/events/event_utils.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace {
 
diff --git a/ui/wm/core/easy_resize_window_targeter.cc b/ui/wm/core/easy_resize_window_targeter.cc
index 24d5760..d352e52 100644
--- a/ui/wm/core/easy_resize_window_targeter.cc
+++ b/ui/wm/core/easy_resize_window_targeter.cc
@@ -4,10 +4,10 @@
 
 #include "ui/wm/core/easy_resize_window_targeter.h"
 
-#include "ui/aura/client/transient_window_client.h"
 #include "ui/aura/window.h"
 #include "ui/gfx/geometry/insets_f.h"
 #include "ui/gfx/geometry/rect.h"
+#include "ui/wm/public/transient_window_client.h"
 
 namespace wm {
 
diff --git a/ui/wm/core/focus_controller.cc b/ui/wm/core/focus_controller.cc
index 38e8920..f4d3f3f 100644
--- a/ui/wm/core/focus_controller.cc
+++ b/ui/wm/core/focus_controller.cc
@@ -5,7 +5,6 @@
 #include "ui/wm/core/focus_controller.h"
 
 #include "base/auto_reset.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/capture_client.h"
 #include "ui/aura/client/focus_change_observer.h"
@@ -14,6 +13,7 @@
 #include "ui/events/event.h"
 #include "ui/wm/core/focus_rules.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace wm {
 namespace {
diff --git a/ui/wm/core/focus_controller.h b/ui/wm/core/focus_controller.h
index aa97d4d..fecdd2e 100644
--- a/ui/wm/core/focus_controller.h
+++ b/ui/wm/core/focus_controller.h
@@ -9,11 +9,11 @@
 #include "base/memory/scoped_ptr.h"
 #include "base/observer_list.h"
 #include "base/scoped_observer.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/focus_client.h"
 #include "ui/aura/window_observer.h"
 #include "ui/events/event_handler.h"
 #include "ui/wm/core/wm_core_export.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace wm {
 
diff --git a/ui/wm/core/focus_controller_unittest.cc b/ui/wm/core/focus_controller_unittest.cc
index 8a0ba29..d460100 100644
--- a/ui/wm/core/focus_controller_unittest.cc
+++ b/ui/wm/core/focus_controller_unittest.cc
@@ -6,8 +6,6 @@
 
 #include <map>
 
-#include "ui/aura/client/activation_change_observer.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/client/default_capture_client.h"
 #include "ui/aura/client/focus_change_observer.h"
@@ -21,6 +19,8 @@
 #include "ui/events/event_handler.h"
 #include "ui/wm/core/base_focus_rules.h"
 #include "ui/wm/core/wm_state.h"
+#include "ui/wm/public/activation_change_observer.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace wm {
 
diff --git a/ui/wm/core/input_method_event_filter_unittest.cc b/ui/wm/core/input_method_event_filter_unittest.cc
index 71dbcce..038ec00 100644
--- a/ui/wm/core/input_method_event_filter_unittest.cc
+++ b/ui/wm/core/input_method_event_filter_unittest.cc
@@ -5,7 +5,6 @@
 #include "ui/wm/core/input_method_event_filter.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/test/event_generator.h"
@@ -13,6 +12,7 @@
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/events/test/test_event_handler.h"
 #include "ui/wm/core/compound_event_filter.h"
+#include "ui/wm/public/activation_client.h"
 
 #if !defined(OS_WIN) && !defined(USE_X11)
 // On platforms except Windows and X11, aura::test::EventGenerator::PressKey
diff --git a/ui/wm/core/shadow_controller.cc b/ui/wm/core/shadow_controller.cc
index 31fb140..c809389 100644
--- a/ui/wm/core/shadow_controller.cc
+++ b/ui/wm/core/shadow_controller.cc
@@ -10,7 +10,6 @@
 #include "base/logging.h"
 #include "base/memory/linked_ptr.h"
 #include "base/scoped_observer.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/env.h"
 #include "ui/aura/env_observer.h"
 #include "ui/aura/window.h"
@@ -20,6 +19,7 @@
 #include "ui/wm/core/shadow.h"
 #include "ui/wm/core/shadow_types.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/activation_client.h"
 
 using std::make_pair;
 
diff --git a/ui/wm/core/shadow_controller.h b/ui/wm/core/shadow_controller.h
index d9451e7..47aa743 100644
--- a/ui/wm/core/shadow_controller.h
+++ b/ui/wm/core/shadow_controller.h
@@ -10,8 +10,8 @@
 #include "base/basictypes.h"
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
-#include "ui/aura/client/activation_change_observer.h"
 #include "ui/wm/core/wm_core_export.h"
+#include "ui/wm/public/activation_change_observer.h"
 
 namespace aura {
 class Window;
diff --git a/ui/wm/core/shadow_controller_unittest.cc b/ui/wm/core/shadow_controller_unittest.cc
index 3f31b2f..60d571e 100644
--- a/ui/wm/core/shadow_controller_unittest.cc
+++ b/ui/wm/core/shadow_controller_unittest.cc
@@ -8,7 +8,6 @@
 #include <vector>
 
 #include "base/memory/scoped_ptr.h"
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/client/window_tree_client.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/window.h"
@@ -18,6 +17,7 @@
 #include "ui/wm/core/shadow_types.h"
 #include "ui/wm/core/window_util.h"
 #include "ui/wm/core/wm_state.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace wm {
 
diff --git a/ui/wm/core/transient_window_controller.h b/ui/wm/core/transient_window_controller.h
index 598904e..125cd28 100644
--- a/ui/wm/core/transient_window_controller.h
+++ b/ui/wm/core/transient_window_controller.h
@@ -5,8 +5,8 @@
 #ifndef UI_WM_CORE_TRANSIENT_WINDOW_CONTROLLER_H_
 #define UI_WM_CORE_TRANSIENT_WINDOW_CONTROLLER_H_
 
-#include "ui/aura/client/transient_window_client.h"
 #include "ui/wm/core/wm_core_export.h"
+#include "ui/wm/public/transient_window_client.h"
 
 namespace wm {
 
diff --git a/ui/wm/core/window_animations.cc b/ui/wm/core/window_animations.cc
index e072867..c7b9c63 100644
--- a/ui/wm/core/window_animations.cc
+++ b/ui/wm/core/window_animations.cc
@@ -15,7 +15,6 @@
 #include "base/message_loop/message_loop.h"
 #include "base/stl_util.h"
 #include "base/time/time.h"
-#include "ui/aura/client/animation_host.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_delegate.h"
@@ -36,6 +35,7 @@
 #include "ui/gfx/vector3d_f.h"
 #include "ui/wm/core/window_util.h"
 #include "ui/wm/core/wm_core_switches.h"
+#include "ui/wm/public/animation_host.h"
 
 DECLARE_WINDOW_PROPERTY_TYPE(int)
 DECLARE_WINDOW_PROPERTY_TYPE(wm::WindowVisibilityAnimationType)
diff --git a/ui/wm/core/window_animations_unittest.cc b/ui/wm/core/window_animations_unittest.cc
index 5ca3e42..5968bf3 100644
--- a/ui/wm/core/window_animations_unittest.cc
+++ b/ui/wm/core/window_animations_unittest.cc
@@ -5,7 +5,6 @@
 #include "ui/wm/core/window_animations.h"
 
 #include "base/time/time.h"
-#include "ui/aura/client/animation_host.h"
 #include "ui/aura/test/aura_test_base.h"
 #include "ui/aura/test/test_windows.h"
 #include "ui/aura/window.h"
@@ -17,6 +16,7 @@
 #include "ui/wm/core/transient_window_manager.h"
 #include "ui/wm/core/transient_window_stacking_client.h"
 #include "ui/wm/core/window_util.h"
+#include "ui/wm/public/animation_host.h"
 
 using aura::Window;
 using ui::Layer;
diff --git a/ui/wm/core/window_util.cc b/ui/wm/core/window_util.cc
index dff8339..6d8cdc9 100644
--- a/ui/wm/core/window_util.cc
+++ b/ui/wm/core/window_util.cc
@@ -4,12 +4,12 @@
 
 #include "ui/wm/core/window_util.h"
 
-#include "ui/aura/client/activation_client.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_tree_owner.h"
 #include "ui/wm/core/transient_window_manager.h"
+#include "ui/wm/public/activation_client.h"
 
 namespace {
 
@@ -23,12 +23,12 @@
   Layers children(to_clone->children());
   for (Layers::const_iterator i = children.begin(); i != children.end(); ++i) {
     ui::LayerOwner* owner = (*i)->owner();
-    ui::Layer* clone = owner ? owner->RecreateLayer().release() : NULL;
-    if (clone) {
-      parent->Add(clone);
+    ui::Layer* old_layer = owner ? owner->RecreateLayer().release() : NULL;
+    if (old_layer) {
+      parent->Add(old_layer);
       // RecreateLayer() moves the existing children to the new layer. Create a
       // copy of those.
-      CloneChildren(owner->layer(), clone);
+      CloneChildren(owner->layer(), old_layer);
     }
   }
 }
@@ -82,11 +82,11 @@
 }
 
 scoped_ptr<ui::LayerTreeOwner> RecreateLayers(ui::LayerOwner* root) {
-  scoped_ptr<ui::LayerTreeOwner> owner(
+  scoped_ptr<ui::LayerTreeOwner> old_layer(
       new ui::LayerTreeOwner(root->RecreateLayer().release()));
-  if (owner->root())
-    CloneChildren(root->layer(), owner->root());
-  return owner.Pass();
+  if (old_layer->root())
+    CloneChildren(root->layer(), old_layer->root());
+  return old_layer.Pass();
 }
 
 aura::Window* GetTransientParent(aura::Window* window) {
diff --git a/ui/wm/public/DEPS b/ui/wm/public/DEPS
new file mode 100644
index 0000000..1e9f248
--- /dev/null
+++ b/ui/wm/public/DEPS
@@ -0,0 +1,9 @@
+include_rules = [
+  "+ui/base/dragdrop/drag_drop_types.h",
+]
+
+specific_include_rules = {
+  "drag_drop_client.h": [
+    "+ui/base/dragdrop/drag_drop_types.h",
+  ],
+}
diff --git a/ui/wm/public/activation_change_observer.cc b/ui/wm/public/activation_change_observer.cc
new file mode 100644
index 0000000..7fcbb7a
--- /dev/null
+++ b/ui/wm/public/activation_change_observer.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/activation_change_observer.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationChangeObserver*)
+
+namespace aura {
+namespace client {
+
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
+    ActivationChangeObserver*, kActivationChangeObserverKey, NULL);
+
+void SetActivationChangeObserver(
+    Window* window,
+    ActivationChangeObserver* observer) {
+  window->SetProperty(kActivationChangeObserverKey, observer);
+}
+
+ActivationChangeObserver* GetActivationChangeObserver(Window* window) {
+  return window ? window->GetProperty(kActivationChangeObserverKey) : NULL;
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/activation_change_observer.h b/ui/wm/public/activation_change_observer.h
new file mode 100644
index 0000000..68d5b8a
--- /dev/null
+++ b/ui/wm/public/activation_change_observer.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_ACTIVATION_CHANGE_OBSERVER_H_
+#define UI_WM_PUBLIC_ACTIVATION_CHANGE_OBSERVER_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+class Window;
+
+namespace client {
+
+class AURA_EXPORT ActivationChangeObserver {
+ public:
+  // Called when |active| gains focus, or there is no active window
+  // (|active| is NULL in this case.) |old_active| refers to the
+  // previous active window or NULL if there was no previously active
+  // window.
+  virtual void OnWindowActivated(Window* gained_active,
+                                 Window* lost_active) = 0;
+
+  // Called when during window activation the currently active window is
+  // selected for activation. This can happen when a window requested for
+  // activation cannot be activated because a system modal window is active.
+  virtual void OnAttemptToReactivateWindow(aura::Window* request_active,
+                                           aura::Window* actual_active) {}
+
+ protected:
+  virtual ~ActivationChangeObserver() {}
+};
+
+// Gets/Sets the ActivationChangeObserver for a specific window. This observer
+// is notified after the ActivationClient notifies all registered observers.
+AURA_EXPORT void SetActivationChangeObserver(
+    Window* window,
+    ActivationChangeObserver* observer);
+AURA_EXPORT ActivationChangeObserver* GetActivationChangeObserver(
+    Window* window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_ACTIVATION_CHANGE_OBSERVER_H_
diff --git a/ui/wm/public/activation_client.cc b/ui/wm/public/activation_client.cc
new file mode 100644
index 0000000..6a47554
--- /dev/null
+++ b/ui/wm/public/activation_client.cc
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/activation_client.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_EXPORTED_WINDOW_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationClient*)
+
+namespace aura {
+namespace client {
+
+DEFINE_WINDOW_PROPERTY_KEY(
+    ActivationClient*, kRootWindowActivationClientKey, NULL);
+DEFINE_WINDOW_PROPERTY_KEY(bool, kHideOnDeactivate, false);
+
+void SetActivationClient(Window* root_window, ActivationClient* client) {
+  root_window->SetProperty(kRootWindowActivationClientKey, client);
+}
+
+ActivationClient* GetActivationClient(Window* root_window) {
+  return root_window ?
+      root_window->GetProperty(kRootWindowActivationClientKey) : NULL;
+}
+
+void SetHideOnDeactivate(Window* window, bool hide_on_deactivate) {
+  window->SetProperty(kHideOnDeactivate, hide_on_deactivate);
+}
+
+bool GetHideOnDeactivate(Window* window) {
+  return window->GetProperty(kHideOnDeactivate);
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/activation_client.h b/ui/wm/public/activation_client.h
new file mode 100644
index 0000000..fc35131
--- /dev/null
+++ b/ui/wm/public/activation_client.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_ACTIVATION_CLIENT_H_
+#define UI_WM_PUBLIC_ACTIVATION_CLIENT_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace ui {
+class Event;
+}
+
+namespace aura {
+class Window;
+
+namespace client {
+class ActivationChangeObserver;
+
+// An interface implemented by an object that manages window activation.
+class AURA_EXPORT ActivationClient {
+ public:
+  // Adds/Removes ActivationChangeObservers.
+  virtual void AddObserver(ActivationChangeObserver* observer) = 0;
+  virtual void RemoveObserver(ActivationChangeObserver* observer) = 0;
+
+  // Activates |window|. If |window| is NULL, nothing happens.
+  virtual void ActivateWindow(Window* window) = 0;
+
+  // Deactivates |window|. What (if anything) is activated next is up to the
+  // client. If |window| is NULL, nothing happens.
+  virtual void DeactivateWindow(Window* window) = 0;
+
+  // Retrieves the active window, or NULL if there is none.
+  virtual Window* GetActiveWindow() = 0;
+
+  // Retrieves the activatable window for |window|, or NULL if there is none.
+  // Note that this is often but not always the toplevel window (see
+  // GetToplevelWindow() below), as the toplevel window may not be activatable
+  // (for example it may be blocked by a modal transient, or some other
+  // condition).
+  virtual Window* GetActivatableWindow(Window* window) = 0;
+
+  // Retrieves the toplevel window for |window|, or NULL if there is none.
+  virtual Window* GetToplevelWindow(Window* window) = 0;
+
+  // Invoked prior to |window| getting focus as a result of the |event|. |event|
+  // may be NULL. Returning false blocks |window| from getting focus.
+  virtual bool OnWillFocusWindow(Window* window, const ui::Event* event) = 0;
+
+  // Returns true if |window| can be activated, false otherwise. If |window| has
+  // a modal child it can not be activated.
+  virtual bool CanActivateWindow(Window* window) const = 0;
+
+ protected:
+  virtual ~ActivationClient() {}
+};
+
+// Sets/Gets the activation client on the root Window.
+AURA_EXPORT void SetActivationClient(Window* root_window,
+                                     ActivationClient* client);
+AURA_EXPORT ActivationClient* GetActivationClient(Window* root_window);
+
+// Some types of transient window are only visible when active.
+// The transient parents of these windows may have visual appearance properties
+// that differ from transient parents that can be deactivated.
+// The presence of this property implies these traits.
+// TODO(beng): currently the UI framework (views) implements the actual
+//             close-on-deactivate component of this feature but it should be
+//             possible to implement in the aura client.
+AURA_EXPORT void SetHideOnDeactivate(Window* window, bool hide_on_deactivate);
+AURA_EXPORT bool GetHideOnDeactivate(Window* window);
+
+}  // namespace clients
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_ACTIVATION_CLIENT_H_
diff --git a/ui/wm/public/activation_delegate.cc b/ui/wm/public/activation_delegate.cc
new file mode 100644
index 0000000..2a9bbc9
--- /dev/null
+++ b/ui/wm/public/activation_delegate.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/activation_delegate.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::ActivationDelegate*)
+
+namespace aura {
+namespace client {
+
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
+    ActivationDelegate*, kActivationDelegateKey, NULL);
+
+void SetActivationDelegate(Window* window, ActivationDelegate* delegate) {
+  window->SetProperty(kActivationDelegateKey, delegate);
+}
+
+ActivationDelegate* GetActivationDelegate(Window* window) {
+  return window->GetProperty(kActivationDelegateKey);
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/activation_delegate.h b/ui/wm/public/activation_delegate.h
new file mode 100644
index 0000000..3c5b3ae
--- /dev/null
+++ b/ui/wm/public/activation_delegate.h
@@ -0,0 +1,37 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_ACTIVATION_DELEGATE_H_
+#define UI_WM_PUBLIC_ACTIVATION_DELEGATE_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace ui {
+class Event;
+}
+
+namespace aura {
+class Window;
+namespace client {
+
+// An interface implemented by an object that configures and responds to changes
+// to a window's activation state.
+class AURA_EXPORT ActivationDelegate {
+ public:
+  // Returns true if the window should be activated.
+  virtual bool ShouldActivate() const = 0;
+
+ protected:
+  virtual ~ActivationDelegate() {}
+};
+
+// Sets/Gets the ActivationDelegate on the Window. No ownership changes.
+AURA_EXPORT void SetActivationDelegate(Window* window,
+                                       ActivationDelegate* delegate);
+AURA_EXPORT ActivationDelegate* GetActivationDelegate(Window* window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_ACTIVATION_DELEGATE_H_
diff --git a/ui/wm/public/animation_host.cc b/ui/wm/public/animation_host.cc
new file mode 100644
index 0000000..0d90f9c
--- /dev/null
+++ b/ui/wm/public/animation_host.cc
@@ -0,0 +1,28 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/animation_host.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::AnimationHost*)
+
+namespace aura {
+namespace client {
+
+DEFINE_WINDOW_PROPERTY_KEY(AnimationHost*, kRootWindowAnimationHostKey, NULL);
+
+void SetAnimationHost(Window* window, AnimationHost* animation_host) {
+  DCHECK(window);
+  window->SetProperty(kRootWindowAnimationHostKey, animation_host);
+}
+
+AnimationHost* GetAnimationHost(Window* window) {
+  DCHECK(window);
+  return window->GetProperty(kRootWindowAnimationHostKey);
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/animation_host.h b/ui/wm/public/animation_host.h
new file mode 100644
index 0000000..71f9f4d
--- /dev/null
+++ b/ui/wm/public/animation_host.h
@@ -0,0 +1,48 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_ANIMATION_HOST_H_
+#define UI_WM_PUBLIC_ANIMATION_HOST_H_
+
+#include "base/compiler_specific.h"
+#include "ui/aura/aura_export.h"
+
+namespace gfx {
+class Vector2d;
+}
+
+namespace aura {
+class Window;
+namespace client {
+
+// Interface for top level window host of animation. Communicates additional
+// bounds required for animation as well as animation completion for deferring
+// window closes on hide.
+class AURA_EXPORT AnimationHost {
+ public:
+  // Ensure the host window is at least this large so that transitions have
+  // sufficient space.
+  // The |top_left_delta| parameter contains the offset to be subtracted from
+  // the window bounds for the top left corner.
+  // The |bottom_right_delta| parameter contains the offset to be added to the
+  // window bounds for the bottom right.
+  virtual void SetHostTransitionOffsets(
+      const gfx::Vector2d& top_left_delta,
+      const gfx::Vector2d& bottom_right_delta) = 0;
+
+  // Called after the window has faded out on a hide.
+  virtual void OnWindowHidingAnimationCompleted() = 0;
+
+ protected:
+  virtual ~AnimationHost() {}
+};
+
+AURA_EXPORT void SetAnimationHost(Window* window,
+                                  AnimationHost* animation_host);
+AURA_EXPORT AnimationHost* GetAnimationHost(Window* window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_ANIMATION_HOST_H_
diff --git a/ui/wm/public/dispatcher_client.cc b/ui/wm/public/dispatcher_client.cc
new file mode 100644
index 0000000..cec4a8a
--- /dev/null
+++ b/ui/wm/public/dispatcher_client.cc
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/dispatcher_client.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DispatcherClient*);
+
+namespace aura {
+namespace client {
+
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(DispatcherClient*, kDispatcherClientKey, NULL);
+
+void SetDispatcherClient(Window* root_window, DispatcherClient* client) {
+  DCHECK_EQ(root_window->GetRootWindow(), root_window);
+  root_window->SetProperty(kDispatcherClientKey, client);
+}
+
+DispatcherClient* GetDispatcherClient(Window* root_window) {
+  if (root_window)
+    DCHECK_EQ(root_window->GetRootWindow(), root_window);
+  return root_window ? root_window->GetProperty(kDispatcherClientKey) : NULL;
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/dispatcher_client.h b/ui/wm/public/dispatcher_client.h
new file mode 100644
index 0000000..9fd9c94
--- /dev/null
+++ b/ui/wm/public/dispatcher_client.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_DISPATCHER_CLIENT_H_
+#define UI_WM_PUBLIC_DISPATCHER_CLIENT_H_
+
+#include "base/message_loop/message_pump_dispatcher.h"
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+class Window;
+namespace client {
+
+// An interface implemented by an object which handles nested dispatchers.
+class AURA_EXPORT DispatcherClient {
+ public:
+  virtual void RunWithDispatcher(base::MessagePumpDispatcher* dispatcher) = 0;
+
+  virtual void QuitNestedMessageLoop() = 0;
+};
+
+AURA_EXPORT void SetDispatcherClient(Window* root_window,
+                                     DispatcherClient* client);
+AURA_EXPORT DispatcherClient* GetDispatcherClient(Window* root_window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_DISPATCHER_CLIENT_H_
diff --git a/ui/wm/public/drag_drop_client.cc b/ui/wm/public/drag_drop_client.cc
new file mode 100644
index 0000000..c452f9e
--- /dev/null
+++ b/ui/wm/public/drag_drop_client.cc
@@ -0,0 +1,31 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/drag_drop_client.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DragDropClient*)
+
+namespace aura {
+namespace client {
+
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
+    DragDropClient*, kRootWindowDragDropClientKey, NULL);
+
+void SetDragDropClient(Window* root_window, DragDropClient* client) {
+  DCHECK_EQ(root_window->GetRootWindow(), root_window);
+  root_window->SetProperty(kRootWindowDragDropClientKey, client);
+}
+
+DragDropClient* GetDragDropClient(Window* root_window) {
+  if (root_window)
+    DCHECK_EQ(root_window->GetRootWindow(), root_window);
+  return root_window ?
+      root_window->GetProperty(kRootWindowDragDropClientKey) : NULL;
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/drag_drop_client.h b/ui/wm/public/drag_drop_client.h
new file mode 100644
index 0000000..62a2355
--- /dev/null
+++ b/ui/wm/public/drag_drop_client.h
@@ -0,0 +1,62 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_DRAG_DROP_CLIENT_H_
+#define UI_WM_PUBLIC_DRAG_DROP_CLIENT_H_
+
+#include "ui/aura/aura_export.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace ui {
+class LocatedEvent;
+class OSExchangeData;
+}
+
+namespace aura {
+class Window;
+namespace client {
+
+// An interface implemented by an object that controls a drag and drop session.
+class AURA_EXPORT DragDropClient {
+ public:
+  virtual ~DragDropClient() {}
+
+  // Initiates a drag and drop session. Returns the drag operation that was
+  // applied at the end of the drag drop session. |root_location| is in the
+  // root Window's coordinate system.
+  virtual int StartDragAndDrop(const ui::OSExchangeData& data,
+                               aura::Window* root_window,
+                               aura::Window* source_window,
+                               const gfx::Point& root_location,
+                               int operation,
+                               ui::DragDropTypes::DragEventSource source) = 0;
+
+  // Called when mouse is dragged during a drag and drop.
+  virtual void DragUpdate(aura::Window* target,
+                          const ui::LocatedEvent& event) = 0;
+
+  // Called when mouse is released during a drag and drop.
+  virtual void Drop(aura::Window* target,
+                    const ui::LocatedEvent& event) = 0;
+
+  // Called when a drag and drop session is cancelled.
+  virtual void DragCancel() = 0;
+
+  // Returns true if a drag and drop session is in progress.
+  virtual bool IsDragDropInProgress() = 0;
+};
+
+AURA_EXPORT void SetDragDropClient(Window* root_window,
+                                   DragDropClient* client);
+AURA_EXPORT DragDropClient* GetDragDropClient(Window* root_window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_DRAG_DROP_CLIENT_H_
diff --git a/ui/wm/public/drag_drop_delegate.cc b/ui/wm/public/drag_drop_delegate.cc
new file mode 100644
index 0000000..6380f96
--- /dev/null
+++ b/ui/wm/public/drag_drop_delegate.cc
@@ -0,0 +1,27 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/drag_drop_delegate.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::DragDropDelegate*)
+
+namespace aura {
+namespace client {
+
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
+    DragDropDelegate*, kDragDropDelegateKey, NULL);
+
+void SetDragDropDelegate(Window* window, DragDropDelegate* delegate) {
+  window->SetProperty(kDragDropDelegateKey, delegate);
+}
+
+DragDropDelegate* GetDragDropDelegate(Window* window) {
+  return window->GetProperty(kDragDropDelegateKey);
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/drag_drop_delegate.h b/ui/wm/public/drag_drop_delegate.h
new file mode 100644
index 0000000..50f6c26
--- /dev/null
+++ b/ui/wm/public/drag_drop_delegate.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_DRAG_DROP_DELEGATE_H_
+#define UI_WM_PUBLIC_DRAG_DROP_DELEGATE_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace ui {
+class DropTargetEvent;
+}
+
+namespace aura {
+class Window;
+namespace client {
+
+// Delegate interface for drag and drop actions on aura::Window.
+class AURA_EXPORT DragDropDelegate {
+ public:
+  // OnDragEntered is invoked when the mouse enters this window during a drag &
+  // drop session. This is immediately followed by an invocation of
+  // OnDragUpdated, and eventually one of OnDragExited or OnPerformDrop.
+  virtual void OnDragEntered(const ui::DropTargetEvent& event) = 0;
+
+  // Invoked during a drag and drop session while the mouse is over the window.
+  // This should return a bitmask of the DragDropTypes::DragOperation supported
+  // based on the location of the event. Return 0 to indicate the drop should
+  // not be accepted.
+  virtual int OnDragUpdated(const ui::DropTargetEvent& event) = 0;
+
+  // Invoked during a drag and drop session when the mouse exits the window, or
+  // when the drag session was canceled and the mouse was over the window.
+  virtual void OnDragExited() = 0;
+
+  // Invoked during a drag and drop session when OnDragUpdated returns a valid
+  // operation and the user release the mouse.
+  virtual int OnPerformDrop(const ui::DropTargetEvent& event) = 0;
+
+ protected:
+  virtual ~DragDropDelegate() {}
+};
+
+AURA_EXPORT void SetDragDropDelegate(Window* window,
+                                     DragDropDelegate* delegate);
+AURA_EXPORT DragDropDelegate* GetDragDropDelegate(Window* window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_DRAG_DROP_DELEGATE_H_
diff --git a/ui/wm/public/scoped_tooltip_disabler.cc b/ui/wm/public/scoped_tooltip_disabler.cc
new file mode 100644
index 0000000..45a39ca
--- /dev/null
+++ b/ui/wm/public/scoped_tooltip_disabler.cc
@@ -0,0 +1,43 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/scoped_tooltip_disabler.h"
+
+#include "ui/aura/window.h"
+#include "ui/wm/public/tooltip_client.h"
+
+namespace aura {
+namespace client {
+
+ScopedTooltipDisabler::ScopedTooltipDisabler(aura::Window* window)
+    : root_(window ? window->GetRootWindow() : NULL) {
+  if (root_) {
+    root_->AddObserver(this);
+    TooltipClient* client = GetTooltipClient(root_);
+    if (client)
+      client->SetTooltipsEnabled(false);
+  }
+}
+
+ScopedTooltipDisabler::~ScopedTooltipDisabler() {
+  EnableTooltips();
+}
+
+void ScopedTooltipDisabler::EnableTooltips() {
+  if (!root_)
+    return;
+  TooltipClient* client = GetTooltipClient(root_);
+  if (client)
+    client->SetTooltipsEnabled(true);
+  root_->RemoveObserver(this);
+  root_ = NULL;
+}
+
+void ScopedTooltipDisabler::OnWindowDestroying(aura::Window* window) {
+  EnableTooltips();
+}
+
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/scoped_tooltip_disabler.h b/ui/wm/public/scoped_tooltip_disabler.h
new file mode 100644
index 0000000..0fd3e11
--- /dev/null
+++ b/ui/wm/public/scoped_tooltip_disabler.h
@@ -0,0 +1,39 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_SCOPED_TOOLTIP_DISABLER_H_
+#define UI_WM_PUBLIC_SCOPED_TOOLTIP_DISABLER_H_
+
+#include "ui/aura/window_observer.h"
+
+namespace aura {
+namespace client {
+
+// Use to temporarily disable tooltips.
+class AURA_EXPORT ScopedTooltipDisabler : aura::WindowObserver {
+ public:
+  // Disables tooltips on |window| (does nothing if |window| is NULL). Tooltips
+  // are reenabled from the destructor when there are no most outstanding
+  // ScopedTooltipDisablers for |window|.
+  explicit ScopedTooltipDisabler(aura::Window* window);
+  virtual ~ScopedTooltipDisabler();
+
+ private:
+  // Reenables the tooltips on the TooltipClient.
+  void EnableTooltips();
+
+  // aura::WindowObserver:
+  virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
+
+  // The RootWindow to disable Tooltips on; NULL if the Window passed to the
+  // constructor was not in a root or the root has been destroyed.
+  aura::Window* root_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedTooltipDisabler);
+};
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_SCOPED_TOOLTIP_DISABLER_H_
diff --git a/ui/wm/public/tooltip_client.cc b/ui/wm/public/tooltip_client.cc
new file mode 100644
index 0000000..b473238
--- /dev/null
+++ b/ui/wm/public/tooltip_client.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/tooltip_client.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::TooltipClient*)
+DECLARE_WINDOW_PROPERTY_TYPE(base::string16*)
+
+namespace aura {
+namespace client {
+
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
+    TooltipClient*, kRootWindowTooltipClientKey, NULL);
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(base::string16*, kTooltipTextKey, NULL);
+
+void SetTooltipClient(Window* root_window, TooltipClient* client) {
+  DCHECK_EQ(root_window->GetRootWindow(), root_window);
+  root_window->SetProperty(kRootWindowTooltipClientKey, client);
+}
+
+TooltipClient* GetTooltipClient(Window* root_window) {
+  if (root_window)
+    DCHECK_EQ(root_window->GetRootWindow(), root_window);
+  return root_window ?
+      root_window->GetProperty(kRootWindowTooltipClientKey) : NULL;
+}
+
+void SetTooltipText(Window* window, base::string16* tooltip_text) {
+  window->SetProperty(kTooltipTextKey, tooltip_text);
+}
+
+const base::string16 GetTooltipText(Window* window) {
+  base::string16* string_ptr = window->GetProperty(kTooltipTextKey);
+  return string_ptr ? *string_ptr : base::string16();
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/tooltip_client.h b/ui/wm/public/tooltip_client.h
new file mode 100644
index 0000000..f592b21
--- /dev/null
+++ b/ui/wm/public/tooltip_client.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_TOOLTIP_CLIENT_H_
+#define UI_WM_PUBLIC_TOOLTIP_CLIENT_H_
+
+#include "ui/aura/aura_export.h"
+#include "ui/gfx/font.h"
+
+namespace aura {
+class Window;
+namespace client {
+
+class ScopedTooltipDisabler;
+
+class AURA_EXPORT TooltipClient {
+ public:
+  // Informs the shell tooltip manager of change in tooltip for window |target|.
+  virtual void UpdateTooltip(Window* target) = 0;
+
+  // Sets the time after which the tooltip is hidden for Window |target|. If
+  // |timeout_in_ms| is <= 0, the tooltip is shown indefinitely.
+  virtual void SetTooltipShownTimeout(Window* target, int timeout_in_ms) = 0;
+
+ protected:
+  // Enables/Disables tooltips. This is treated as a reference count. Consumers
+  // must use ScopedTooltipDisabler to enable/disabled tooltips.
+  virtual void SetTooltipsEnabled(bool enable) = 0;
+
+ private:
+  friend class ScopedTooltipDisabler;
+};
+
+AURA_EXPORT void SetTooltipClient(Window* root_window,
+                                  TooltipClient* client);
+AURA_EXPORT TooltipClient* GetTooltipClient(Window* root_window);
+
+AURA_EXPORT void SetTooltipText(Window* window, base::string16* tooltip_text);
+AURA_EXPORT const base::string16 GetTooltipText(Window* window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_TOOLTIP_CLIENT_H_
diff --git a/ui/wm/public/transient_window_client.cc b/ui/wm/public/transient_window_client.cc
new file mode 100644
index 0000000..aab8e51
--- /dev/null
+++ b/ui/wm/public/transient_window_client.cc
@@ -0,0 +1,25 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/transient_window_client.h"
+
+namespace aura {
+namespace client {
+
+namespace {
+
+TransientWindowClient* instance = NULL;
+
+}  // namespace
+
+void SetTransientWindowClient(TransientWindowClient* client) {
+  instance = client;
+}
+
+TransientWindowClient* GetTransientWindowClient() {
+  return instance;
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/transient_window_client.h b/ui/wm/public/transient_window_client.h
new file mode 100644
index 0000000..2086100
--- /dev/null
+++ b/ui/wm/public/transient_window_client.h
@@ -0,0 +1,47 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_TRANSIENT_WINDOW_CLIENT_H_
+#define UI_WM_PUBLIC_TRANSIENT_WINDOW_CLIENT_H_
+
+#include "base/basictypes.h"
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+
+class Window;
+
+namespace client {
+
+// TransientWindowClient is used to add or remove transient windows. Transient
+// children get the following behavior:
+// . The transient parent destroys any transient children when it is
+//   destroyed. This means a transient child is destroyed if either its parent
+//   or transient parent is destroyed.
+// . If a transient child and its transient parent share the same parent, then
+//   transient children are always ordered above the transient parent.
+// Transient windows are typically used for popups and menus.
+// TODO(sky): nuke this class and replace with calls to TransientWindowManager.
+// This is temporary until we start moving to ui/wm.
+class AURA_EXPORT TransientWindowClient {
+ public:
+  virtual void AddTransientChild(Window* parent, Window* child) = 0;
+  virtual void RemoveTransientChild(Window* parent, Window* child) = 0;
+  virtual Window* GetTransientParent(Window* window) = 0;
+  virtual const Window* GetTransientParent(const Window* window) = 0;
+
+ protected:
+  virtual ~TransientWindowClient() {}
+};
+
+// Sets/gets the TransientWindowClient. This does *not* take ownership of
+// |client|. It is assumed the caller will invoke SetTransientWindowClient(NULL)
+// before deleting |client|.
+AURA_EXPORT void SetTransientWindowClient(TransientWindowClient* client);
+AURA_EXPORT TransientWindowClient* GetTransientWindowClient();
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_TRANSIENT_WINDOW_CLIENT_H_
diff --git a/ui/wm/public/window_move_client.cc b/ui/wm/public/window_move_client.cc
new file mode 100644
index 0000000..44ccca9
--- /dev/null
+++ b/ui/wm/public/window_move_client.cc
@@ -0,0 +1,28 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/wm/public/window_move_client.h"
+
+#include "ui/aura/window.h"
+#include "ui/aura/window_property.h"
+
+DECLARE_WINDOW_PROPERTY_TYPE(aura::client::WindowMoveClient*)
+
+namespace aura {
+namespace client {
+
+// A property key to store a client that handles window moves.
+DEFINE_LOCAL_WINDOW_PROPERTY_KEY(
+    WindowMoveClient*, kWindowMoveClientKey, NULL);
+
+void SetWindowMoveClient(Window* window, WindowMoveClient* client) {
+  window->SetProperty(kWindowMoveClientKey, client);
+}
+
+WindowMoveClient* GetWindowMoveClient(Window* window) {
+  return window->GetProperty(kWindowMoveClientKey);
+}
+
+}  // namespace client
+}  // namespace aura
diff --git a/ui/wm/public/window_move_client.h b/ui/wm/public/window_move_client.h
new file mode 100644
index 0000000..b8943d3
--- /dev/null
+++ b/ui/wm/public/window_move_client.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_WM_PUBLIC_WINDOW_MOVE_CLIENT_H_
+#define UI_WM_PUBLIC_WINDOW_MOVE_CLIENT_H_
+
+#include "ui/aura/aura_export.h"
+#include "ui/gfx/vector2d.h"
+
+namespace gfx {
+class Point;
+}
+
+namespace aura {
+class Window;
+namespace client {
+
+enum WindowMoveResult {
+  MOVE_SUCCESSFUL,  // Moving window was successful.
+  MOVE_CANCELED    // Moving window was canceled.
+};
+
+enum WindowMoveSource {
+  WINDOW_MOVE_SOURCE_MOUSE,
+  WINDOW_MOVE_SOURCE_TOUCH,
+};
+
+// An interface implemented by an object that manages programatically keyed
+// window moving.
+class AURA_EXPORT WindowMoveClient {
+ public:
+  // Starts a nested message loop for moving the window. |drag_offset| is the
+  // offset from the window origin to the cursor when the drag was started.
+  // Returns MOVE_SUCCESSFUL if the move has completed successfully, or
+  // MOVE_CANCELED otherwise.
+  virtual WindowMoveResult RunMoveLoop(Window* window,
+                                       const gfx::Vector2d& drag_offset,
+                                       WindowMoveSource source) = 0;
+
+  // Ends a previously started move loop.
+  virtual void EndMoveLoop() = 0;
+
+ protected:
+  virtual ~WindowMoveClient() {}
+};
+
+// Sets/Gets the activation client for the specified window.
+AURA_EXPORT void SetWindowMoveClient(Window* window,
+                                     WindowMoveClient* client);
+AURA_EXPORT WindowMoveClient* GetWindowMoveClient(Window* window);
+
+}  // namespace client
+}  // namespace aura
+
+#endif  // UI_WM_PUBLIC_WINDOW_MOVE_CLIENT_H_
diff --git a/url/BUILD.gn b/url/BUILD.gn
index e32d434..131bfd5 100644
--- a/url/BUILD.gn
+++ b/url/BUILD.gn
@@ -3,7 +3,6 @@
 # found in the LICENSE file.
 
 component("url") {
-  external = true
   if (is_win) {
     # Don't conflict with Windows' "url.dll".
     output_name = "url_lib"
@@ -57,7 +56,6 @@
 }
 
 test("url_unittests") {
-  external = true
   sources = [
     "gurl_unittest.cc",
     "url_canon_unittest.cc",
diff --git a/url/url_lib.target.darwin-arm.mk b/url/url_lib.target.darwin-arm.mk
index 4993f08..3f1e11c 100644
--- a/url/url_lib.target.darwin-arm.mk
+++ b/url/url_lib.target.darwin-arm.mk
@@ -100,6 +100,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/url/url_lib.target.darwin-mips.mk b/url/url_lib.target.darwin-mips.mk
index 4f5755f..d25a5ba 100644
--- a/url/url_lib.target.darwin-mips.mk
+++ b/url/url_lib.target.darwin-mips.mk
@@ -99,6 +99,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/url/url_lib.target.darwin-x86.mk b/url/url_lib.target.darwin-x86.mk
index ada5e10..ac3b70d 100644
--- a/url/url_lib.target.darwin-x86.mk
+++ b/url/url_lib.target.darwin-x86.mk
@@ -101,6 +101,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -191,6 +192,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/url/url_lib.target.darwin-x86_64.mk b/url/url_lib.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7910758
--- /dev/null
+++ b/url/url_lib.target.darwin-x86_64.mk
@@ -0,0 +1,291 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := url_url_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	url/gurl.cc \
+	url/origin.cc \
+	url/third_party/mozilla/url_parse.cc \
+	url/url_canon_etc.cc \
+	url/url_canon_filesystemurl.cc \
+	url/url_canon_fileurl.cc \
+	url/url_canon_host.cc \
+	url/url_canon_icu.cc \
+	url/url_canon_internal.cc \
+	url/url_canon_ip.cc \
+	url/url_canon_mailtourl.cc \
+	url/url_canon_path.cc \
+	url/url_canon_pathurl.cc \
+	url/url_canon_query.cc \
+	url/url_canon_relative.cc \
+	url/url_canon_stdstring.cc \
+	url/url_canon_stdurl.cc \
+	url/url_parse_file.cc \
+	url/url_util.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DURL_IMPLEMENTATION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DURL_IMPLEMENTATION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: url_url_lib_gyp
+
+# Alias gyp target name.
+.PHONY: url_lib
+url_lib: url_url_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/url/url_lib.target.linux-arm.mk b/url/url_lib.target.linux-arm.mk
index 4993f08..3f1e11c 100644
--- a/url/url_lib.target.linux-arm.mk
+++ b/url/url_lib.target.linux-arm.mk
@@ -100,6 +100,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -190,6 +191,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/url/url_lib.target.linux-mips.mk b/url/url_lib.target.linux-mips.mk
index 4f5755f..d25a5ba 100644
--- a/url/url_lib.target.linux-mips.mk
+++ b/url/url_lib.target.linux-mips.mk
@@ -99,6 +99,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -188,6 +189,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/url/url_lib.target.linux-x86.mk b/url/url_lib.target.linux-x86.mk
index ada5e10..ac3b70d 100644
--- a/url/url_lib.target.linux-x86.mk
+++ b/url/url_lib.target.linux-x86.mk
@@ -101,6 +101,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -191,6 +192,7 @@
 	'-DURL_IMPLEMENTATION' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/url/url_lib.target.linux-x86_64.mk b/url/url_lib.target.linux-x86_64.mk
new file mode 100644
index 0000000..7910758
--- /dev/null
+++ b/url/url_lib.target.linux-x86_64.mk
@@ -0,0 +1,291 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := url_url_lib_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_icu_icui18n_gyp)/icui18n.stamp \
+	$(call intermediates-dir-for,GYP,third_party_icu_icuuc_gyp)/icuuc.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	url/gurl.cc \
+	url/origin.cc \
+	url/third_party/mozilla/url_parse.cc \
+	url/url_canon_etc.cc \
+	url/url_canon_filesystemurl.cc \
+	url/url_canon_fileurl.cc \
+	url/url_canon_host.cc \
+	url/url_canon_icu.cc \
+	url/url_canon_internal.cc \
+	url/url_canon_ip.cc \
+	url/url_canon_mailtourl.cc \
+	url/url_canon_path.cc \
+	url/url_canon_pathurl.cc \
+	url/url_canon_query.cc \
+	url/url_canon_relative.cc \
+	url/url_canon_stdstring.cc \
+	url/url_canon_stdurl.cc \
+	url/url_parse_file.cc \
+	url/url_util.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DURL_IMPLEMENTATION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DURL_IMPLEMENTATION' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: url_url_lib_gyp
+
+# Alias gyp target name.
+.PHONY: url_lib
+url_lib: url_url_lib_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/browser/appcache/appcache_histograms.cc b/webkit/browser/appcache/appcache_histograms.cc
index 0ee25c2..b7299e6 100644
--- a/webkit/browser/appcache/appcache_histograms.cc
+++ b/webkit/browser/appcache/appcache_histograms.cc
@@ -53,6 +53,58 @@
        result, NUM_CHECK_RESPONSE_RESULT_TYPES);
 }
 
+void AppCacheHistograms::CountResponseRetrieval(
+    bool success, bool is_main_resource, const GURL& origin_url) {
+  std::string label;
+  if (is_main_resource) {
+    label = "appcache.MainResourceResponseRetrieval";
+    UMA_HISTOGRAM_BOOLEAN(label, success);
+  } else {
+    label = "appcache.SubResourceResponseRetrieval";
+    UMA_HISTOGRAM_BOOLEAN(label, success);
+  }
+  const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
+  if (!suffix.empty()) {
+    base::BooleanHistogram::FactoryGet(
+        label + suffix,
+        base::HistogramBase::kUmaTargetedHistogramFlag)->Add(success);
+  }
+}
+
+void AppCacheHistograms::LogUpdateFailureStats(
+      const GURL& origin_url,
+      int percent_complete,
+      bool was_stalled,
+      bool was_off_origin_resource_failure) {
+  const std::string suffix = OriginToCustomHistogramSuffix(origin_url);
+
+  std::string label = "appcache.UpdateProgressAtPointOfFaliure";
+  UMA_HISTOGRAM_PERCENTAGE(label, percent_complete);
+  if (!suffix.empty()) {
+    base::LinearHistogram::FactoryGet(
+        label + suffix,
+        1, 101, 102,
+        base::HistogramBase::kUmaTargetedHistogramFlag)->Add(percent_complete);
+  }
+
+  label = "appcache.UpdateWasStalledAtPointOfFailure";
+  UMA_HISTOGRAM_BOOLEAN(label, was_stalled);
+  if (!suffix.empty()) {
+    base::BooleanHistogram::FactoryGet(
+        label + suffix,
+        base::HistogramBase::kUmaTargetedHistogramFlag)->Add(was_stalled);
+  }
+
+  label = "appcache.UpdateWasOffOriginAtPointOfFailure";
+  UMA_HISTOGRAM_BOOLEAN(label, was_off_origin_resource_failure);
+  if (!suffix.empty()) {
+    base::BooleanHistogram::FactoryGet(
+        label + suffix,
+        base::HistogramBase::kUmaTargetedHistogramFlag)->Add(
+            was_off_origin_resource_failure);
+  }
+}
+
 void AppCacheHistograms::AddTaskQueueTimeSample(
     const base::TimeDelta& duration) {
   UMA_HISTOGRAM_TIMES("appcache.TaskQueueTime", duration);
diff --git a/webkit/browser/appcache/appcache_histograms.h b/webkit/browser/appcache/appcache_histograms.h
index 94d467f..21cae36 100644
--- a/webkit/browser/appcache/appcache_histograms.h
+++ b/webkit/browser/appcache/appcache_histograms.h
@@ -31,7 +31,13 @@
     NUM_CHECK_RESPONSE_RESULT_TYPES
   };
   static void CountCheckResponseResult(CheckResponseResultType result);
-
+  static void CountResponseRetrieval(
+      bool success, bool is_main_resource, const GURL& origin_url);
+  static void LogUpdateFailureStats(
+      const GURL& origin_url,
+      int percent_complete,
+      bool was_making_progress,
+      bool off_origin_resource_failure);
   static void AddTaskQueueTimeSample(const base::TimeDelta& duration);
   static void AddTaskRunTimeSample(const base::TimeDelta& duration);
   static void AddCompletionQueueTimeSample(const base::TimeDelta& duration);
diff --git a/webkit/browser/appcache/appcache_request_handler.cc b/webkit/browser/appcache/appcache_request_handler.cc
index 102c184..483f8c3 100644
--- a/webkit/browser/appcache/appcache_request_handler.cc
+++ b/webkit/browser/appcache/appcache_request_handler.cc
@@ -103,14 +103,14 @@
     // 6.9.6, step 4: If this results in a redirect to another origin,
     // get the resource of the fallback entry.
     job_ = new AppCacheURLRequestJob(request, network_delegate,
-                                     storage(), host_);
+                                     storage(), host_, is_main_resource());
     DeliverAppCachedResponse(
         found_fallback_entry_, found_cache_id_, found_group_id_,
         found_manifest_url_,  true, found_namespace_entry_url_);
   } else if (!found_network_namespace_) {
     // 6.9.6, step 6: Fail the resource load.
     job_ = new AppCacheURLRequestJob(request, network_delegate,
-                                     storage(), host_);
+                                     storage(), host_, is_main_resource());
     DeliverErrorResponse();
   } else {
     // 6.9.6 step 3 and 5: Fetch the resource normally.
@@ -156,7 +156,7 @@
   // 6.9.6, step 4: If this results in a 4xx or 5xx status code
   // or there were network errors, get the resource of the fallback entry.
   job_ = new AppCacheURLRequestJob(request, network_delegate,
-                                   storage(), host_);
+                                   storage(), host_, is_main_resource());
   DeliverAppCachedResponse(
       found_fallback_entry_, found_cache_id_, found_group_id_,
       found_manifest_url_, true, found_namespace_entry_url_);
@@ -240,7 +240,7 @@
   // We may have to wait for our storage query to complete, but
   // this query can also complete syncrhonously.
   job_ = new AppCacheURLRequestJob(request, network_delegate,
-                                   storage(), host_);
+                                   storage(), host_, is_main_resource());
   storage()->FindResponseForMainRequest(
       request->url(), preferred_manifest_url, this);
 }
@@ -314,17 +314,18 @@
     // selected cache is loaded.
     is_waiting_for_cache_selection_ = true;
     job_ = new AppCacheURLRequestJob(request, network_delegate,
-                                     storage(), host_);
+                                     storage(), host_, is_main_resource());
     return;
   }
 
   if (!host_->associated_cache() ||
-      !host_->associated_cache()->is_complete()) {
+      !host_->associated_cache()->is_complete() ||
+      host_->associated_cache()->owning_group()->is_being_deleted()) {
     return;
   }
 
   job_ = new AppCacheURLRequestJob(request, network_delegate,
-                                   storage(), host_);
+                                   storage(), host_, is_main_resource());
   ContinueMaybeLoadSubResource();
 }
 
diff --git a/webkit/browser/appcache/appcache_update_job.cc b/webkit/browser/appcache/appcache_update_job.cc
index 253aee7..33a68b0 100644
--- a/webkit/browser/appcache/appcache_update_job.cc
+++ b/webkit/browser/appcache/appcache_update_job.cc
@@ -131,6 +131,7 @@
     net::URLRequest* request, const GURL& new_url,  bool* defer_redirect) {
   DCHECK(request_ == request);
   // Redirect is not allowed by the update process.
+  job_->MadeProgress();
   request->Cancel();
   result_ = REDIRECT_ERROR;
   OnResponseCompleted();
@@ -140,8 +141,10 @@
     net::URLRequest *request) {
   DCHECK(request == request_);
   int response_code = -1;
-  if (request->status().is_success())
+  if (request->status().is_success()) {
     response_code = request->GetResponseCode();
+    job_->MadeProgress();
+  }
   if ((response_code / 100) == 2) {
 
     // See http://code.google.com/p/chromium/issues/detail?id=69594
@@ -189,6 +192,7 @@
   DCHECK(request_ == request);
   bool data_consumed = true;
   if (request->status().is_success() && bytes_read > 0) {
+    job_->MadeProgress();
     data_consumed = ConsumeResponseData(bytes_read);
     if (data_consumed) {
       bytes_read = 0;
@@ -279,6 +283,9 @@
 }
 
 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted() {
+  if (request_->status().is_success())
+    job_->MadeProgress();
+
   // Retry for 503s where retry-after is 0.
   if (request_->status().is_success() &&
       request_->GetResponseCode() == 503 &&
@@ -394,6 +401,7 @@
   }
 
   // Begin update process for the group.
+  MadeProgress();
   group_->SetUpdateStatus(AppCacheGroup::CHECKING);
   if (group_->HasCache()) {
     update_type_ = UPGRADE_ATTEMPT;
@@ -422,19 +430,19 @@
 
 void AppCacheUpdateJob::HandleCacheFailure(
     const std::string& error_message,
-    ResultType result) {
+    ResultType result,
+    const GURL& failed_resource_url) {
   // 6.9.4 cache failure steps 2-8.
   DCHECK(internal_state_ != CACHE_FAILURE);
   DCHECK(!error_message.empty());
   DCHECK(result != UPDATE_OK);
   internal_state_ = CACHE_FAILURE;
+  LogHistogramStats(result, failed_resource_url);
   CancelAllUrlFetches();
   CancelAllMasterEntryFetches(error_message);
   NotifyAllError(error_message);
   DiscardInprogressCache();
   internal_state_ = COMPLETED;
-  AppCacheHistograms::CountUpdateJobResult(
-      result, manifest_url_.GetOrigin());
   DeleteSoon();  // To unwind the stack prior to deletion.
 }
 
@@ -498,7 +506,7 @@
     const char* kFormatString = "Manifest fetch failed (%d) %s";
     std::string message = FormatUrlErrorMessage(
         kFormatString, manifest_url_, fetcher->result(), response_code);
-    HandleCacheFailure(message, fetcher->result());
+    HandleCacheFailure(message, fetcher->result(), GURL());
   }
 }
 
@@ -514,7 +522,8 @@
     MaybeCompleteUpdate();
   } else {
     // Treat failure to mark group obsolete as a cache failure.
-    HandleCacheFailure("Failed to mark the cache as obsolete", DB_ERROR);
+    HandleCacheFailure("Failed to mark the cache as obsolete",
+                       DB_ERROR, GURL());
   }
 }
 
@@ -537,7 +546,7 @@
     const char* kFormatString = "Failed to parse manifest %s";
     const std::string message = base::StringPrintf(kFormatString,
         manifest_url_.spec().c_str());
-    HandleCacheFailure(message, MANIFEST_ERROR);
+    HandleCacheFailure(message, MANIFEST_ERROR, GURL());
     VLOG(1) << message;
     return;
   }
@@ -611,7 +620,7 @@
         const char* kFormatString = "Resource fetch failed (%d) %s";
         std::string message = FormatUrlErrorMessage(
             kFormatString, url, fetcher->result(), response_code);
-        HandleCacheFailure(message, fetcher->result());
+        HandleCacheFailure(message, fetcher->result(), url);
         return;
       }
     } else if (response_code == 404 || response_code == 410) {
@@ -707,7 +716,7 @@
 
       // Section 6.9.4, step 22.3.
       if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) {
-        HandleCacheFailure(message, fetcher->result());
+        HandleCacheFailure(message, fetcher->result(), GURL());
         return;
       }
     }
@@ -749,12 +758,13 @@
             << " response code: " << response_code;
     ScheduleUpdateRetry(kRerunDelayMs);
     if (response_code == 200) {
-      HandleCacheFailure("Manifest changed during update", MANIFEST_ERROR);
+      HandleCacheFailure(
+          "Manifest changed during update", MANIFEST_ERROR, GURL());
     } else {
       const char* kFormatString = "Manifest re-fetch failed (%d) %s";
       std::string message = FormatUrlErrorMessage(
           kFormatString, manifest_url_, fetcher->result(), response_code);
-      HandleCacheFailure(message, fetcher->result());
+      HandleCacheFailure(message, fetcher->result(), GURL());
     }
   }
 }
@@ -770,7 +780,7 @@
                    base::Unretained(this)));
   } else {
     HandleCacheFailure("Failed to write the manifest headers to storage",
-                       DISKCACHE_ERROR);
+                       DISKCACHE_ERROR, GURL());
   }
 }
 
@@ -784,7 +794,7 @@
     StoreGroupAndCache();
   } else {
     HandleCacheFailure("Failed to write the manifest data to storage",
-                       DISKCACHE_ERROR);
+                       DISKCACHE_ERROR, GURL());
   }
 }
 
@@ -825,7 +835,7 @@
       message.append(", would exceed quota");
       result = QUOTA_ERROR;
     }
-    HandleCacheFailure(message, result);
+    HandleCacheFailure(message, result, GURL());
   }
 }
 
@@ -911,7 +921,7 @@
       // Use a local variable because service_ is reset in HandleCacheFailure.
       AppCacheService* service = service_;
       HandleCacheFailure("Manifest entry not found in existing cache",
-                         DB_ERROR);
+                         DB_ERROR, GURL());
       AppCacheHistograms::AddMissingManifestEntrySample();
       service->DeleteAppCacheGroup(manifest_url_, net::CompletionCallback());
     }
@@ -1315,8 +1325,7 @@
         NotifyAllAssociatedHosts(UPDATE_READY_EVENT);
       DiscardDuplicateResponses();
       internal_state_ = COMPLETED;
-      AppCacheHistograms::CountUpdateJobResult(
-          UPDATE_OK, manifest_url_.GetOrigin());
+      LogHistogramStats(UPDATE_OK, GURL());
       break;
     case CACHE_FAILURE:
       NOTREACHED();  // See HandleCacheFailure
@@ -1340,6 +1349,8 @@
 void AppCacheUpdateJob::Cancel() {
   internal_state_ = CANCELLED;
 
+  LogHistogramStats(CANCELLED_ERROR, GURL());
+
   if (manifest_fetcher_) {
     delete manifest_fetcher_;
     manifest_fetcher_ = NULL;
@@ -1416,6 +1427,37 @@
   storage_->DoomResponses(manifest_url_, duplicate_response_ids_);
 }
 
+void AppCacheUpdateJob::LogHistogramStats(
+      ResultType result, const GURL& failed_resource_url) {
+  AppCacheHistograms::CountUpdateJobResult(result, manifest_url_.GetOrigin());
+  if (result == UPDATE_OK)
+    return;
+
+  int percent_complete = 0;
+  if (url_file_list_.size() > 0) {
+    size_t actual_fetches_completed = url_fetches_completed_;
+    if (!failed_resource_url.is_empty() && actual_fetches_completed)
+      --actual_fetches_completed;
+    percent_complete = (static_cast<double>(actual_fetches_completed) /
+                            static_cast<double>(url_file_list_.size())) * 100.0;
+    percent_complete = std::min(percent_complete, 99);
+  }
+
+  bool was_making_progress =
+      base::Time::Now() - last_progress_time_ <
+          base::TimeDelta::FromMinutes(5);
+
+  bool off_origin_resource_failure =
+      !failed_resource_url.is_empty() &&
+          (failed_resource_url.GetOrigin() != manifest_url_.GetOrigin());
+
+  AppCacheHistograms::LogUpdateFailureStats(
+      manifest_url_.GetOrigin(),
+      percent_complete,
+      was_making_progress,
+      off_origin_resource_failure);
+}
+
 void AppCacheUpdateJob::DeleteSoon() {
   ClearPendingMasterEntries();
   manifest_response_writer_.reset();
diff --git a/webkit/browser/appcache/appcache_update_job.h b/webkit/browser/appcache/appcache_update_job.h
index 3207fad..97ba905 100644
--- a/webkit/browser/appcache/appcache_update_job.h
+++ b/webkit/browser/appcache/appcache_update_job.h
@@ -13,6 +13,7 @@
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/ref_counted.h"
+#include "base/time/time.h"
 #include "net/base/completion_callback.h"
 #include "net/http/http_response_headers.h"
 #include "net/url_request/url_request.h"
@@ -38,7 +39,7 @@
   // Used for uma stats only for now, so new values are append only.
   enum ResultType {
     UPDATE_OK, DB_ERROR, DISKCACHE_ERROR, QUOTA_ERROR, REDIRECT_ERROR,
-    MANIFEST_ERROR, NETWORK_ERROR, SERVER_ERROR,
+    MANIFEST_ERROR, NETWORK_ERROR, SERVER_ERROR, CANCELLED_ERROR,
     NUM_UPDATE_JOB_RESULT_TYPES
   };
 
@@ -175,7 +176,9 @@
   virtual void OnServiceReinitialized(
       AppCacheStorageReference* old_storage) OVERRIDE;
 
-  void HandleCacheFailure(const std::string& error_message, ResultType result);
+  void HandleCacheFailure(const std::string& error_message,
+                          ResultType result,
+                          const GURL& failed_resource_url);
 
   void FetchManifest(bool is_first_fetch);
   void HandleManifestFetchCompleted(URLFetcher* fetcher);
@@ -245,6 +248,9 @@
   void DiscardInprogressCache();
   void DiscardDuplicateResponses();
 
+  void LogHistogramStats(ResultType result, const GURL& failed_resource_url);
+  void MadeProgress() { last_progress_time_ = base::Time::Now(); }
+
   // Deletes this object after letting the stack unwind.
   void DeleteSoon();
 
@@ -265,6 +271,7 @@
 
   UpdateType update_type_;
   InternalUpdateState internal_state_;
+  base::Time last_progress_time_;
 
   PendingMasters pending_master_entries_;
   size_t master_entries_completed_;
diff --git a/webkit/browser/appcache/appcache_url_request_job.cc b/webkit/browser/appcache/appcache_url_request_job.cc
index 30f1c1f..afef477 100644
--- a/webkit/browser/appcache/appcache_url_request_job.cc
+++ b/webkit/browser/appcache/appcache_url_request_job.cc
@@ -33,13 +33,15 @@
     net::URLRequest* request,
     net::NetworkDelegate* network_delegate,
     AppCacheStorage* storage,
-    AppCacheHost* host)
+    AppCacheHost* host,
+    bool is_main_resource)
     : net::URLRequestJob(request, network_delegate),
       host_(host),
       storage_(storage),
       has_been_started_(false), has_been_killed_(false),
       delivery_type_(AWAITING_DELIVERY_ORDERS),
       group_id_(0), cache_id_(kNoCacheId), is_fallback_(false),
+      is_main_resource_(is_main_resource),
       cache_entry_not_found_(false),
       weak_factory_(this) {
   DCHECK(storage_);
@@ -287,6 +289,8 @@
       // from the appcache.
       storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
                                                  entry_.response_id());
+      AppCacheHistograms::CountResponseRetrieval(
+          false, is_main_resource_, manifest_url_.GetOrigin());
     }
     cache_entry_not_found_ = true;
     NotifyRestartRequired();
@@ -331,12 +335,16 @@
   DCHECK(is_delivering_appcache_response());
   if (result == 0) {
     NotifyDone(net::URLRequestStatus());
+    AppCacheHistograms::CountResponseRetrieval(
+        true, is_main_resource_, manifest_url_.GetOrigin());
   } else if (result < 0) {
     if (storage_->service()->storage() == storage_) {
       storage_->service()->CheckAppCacheResponse(manifest_url_, cache_id_,
                                                  entry_.response_id());
     }
     NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED, result));
+    AppCacheHistograms::CountResponseRetrieval(
+        false, is_main_resource_, manifest_url_.GetOrigin());
   } else {
     SetStatus(net::URLRequestStatus());  // Clear the IO_PENDING status
   }
diff --git a/webkit/browser/appcache/appcache_url_request_job.h b/webkit/browser/appcache/appcache_url_request_job.h
index 87df368..52af0ec 100644
--- a/webkit/browser/appcache/appcache_url_request_job.h
+++ b/webkit/browser/appcache/appcache_url_request_job.h
@@ -33,7 +33,8 @@
   AppCacheURLRequestJob(net::URLRequest* request,
                         net::NetworkDelegate* network_delegate,
                         AppCacheStorage* storage,
-                        AppCacheHost* host);
+                        AppCacheHost* host,
+                        bool is_main_resource);
 
   // Informs the job of what response it should deliver. Only one of these
   // methods should be called, and only once per job. A job will sit idle and
@@ -158,6 +159,7 @@
   int64 cache_id_;
   AppCacheEntry entry_;
   bool is_fallback_;
+  bool is_main_resource_;  // Used for histogram logging.
   bool cache_entry_not_found_;
   scoped_refptr<AppCacheResponseInfo> info_;
   scoped_refptr<net::GrowableIOBuffer> handler_source_buffer_;
diff --git a/webkit/browser/appcache/appcache_url_request_job_unittest.cc b/webkit/browser/appcache/appcache_url_request_job_unittest.cc
index a6e6027..4445931 100644
--- a/webkit/browser/appcache/appcache_url_request_job_unittest.cc
+++ b/webkit/browser/appcache/appcache_url_request_job_unittest.cc
@@ -384,7 +384,7 @@
     // Create an instance and see that it looks as expected.
 
     job = new AppCacheURLRequestJob(
-        &request, NULL, storage, NULL);
+        &request, NULL, storage, NULL, false);
     EXPECT_TRUE(job->is_waiting());
     EXPECT_FALSE(job->is_delivering_appcache_response());
     EXPECT_FALSE(job->is_delivering_network_response());
@@ -408,17 +408,17 @@
     // Create an instance, give it a delivery order and see that
     // it looks as expected.
 
-    job = new AppCacheURLRequestJob(&request, NULL, storage, NULL);
+    job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
     job->DeliverErrorResponse();
     EXPECT_TRUE(job->is_delivering_error_response());
     EXPECT_FALSE(job->has_been_started());
 
-    job = new AppCacheURLRequestJob(&request, NULL, storage, NULL);
+    job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
     job->DeliverNetworkResponse();
     EXPECT_TRUE(job->is_delivering_network_response());
     EXPECT_FALSE(job->has_been_started());
 
-    job = new AppCacheURLRequestJob(&request, NULL, storage, NULL);
+    job = new AppCacheURLRequestJob(&request, NULL, storage, NULL, false);
     const GURL kManifestUrl("http://blah/");
     const int64 kCacheId(1);
     const int64 kGroupId(1);
@@ -454,7 +454,7 @@
     // Setup to create an AppCacheURLRequestJob with orders to deliver
     // a network response.
     mock_factory_job_ = new AppCacheURLRequestJob(
-        request_.get(), NULL, storage, NULL);
+        request_.get(), NULL, storage, NULL, false);
     mock_factory_job_->DeliverNetworkResponse();
     EXPECT_TRUE(mock_factory_job_->is_delivering_network_response());
     EXPECT_FALSE(mock_factory_job_->has_been_started());
@@ -490,7 +490,7 @@
     // Setup to create an AppCacheURLRequestJob with orders to deliver
     // a network response.
     mock_factory_job_ = new AppCacheURLRequestJob(
-        request_.get(), NULL, storage, NULL);
+        request_.get(), NULL, storage, NULL, false);
     mock_factory_job_->DeliverErrorResponse();
     EXPECT_TRUE(mock_factory_job_->is_delivering_error_response());
     EXPECT_FALSE(mock_factory_job_->has_been_started());
@@ -541,7 +541,7 @@
     // Setup to create an AppCacheURLRequestJob with orders to deliver
     // a network response.
     scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob(
-        request_.get(), NULL, storage, NULL));
+        request_.get(), NULL, storage, NULL, false));
 
     if (start_after_delivery_orders) {
       job->DeliverAppCachedResponse(
@@ -660,7 +660,7 @@
 
     // Create job with orders to deliver an appcached entry.
     scoped_refptr<AppCacheURLRequestJob> job(new AppCacheURLRequestJob(
-        request_.get(), NULL, storage, NULL));
+        request_.get(), NULL, storage, NULL, false));
     job->DeliverAppCachedResponse(
         GURL(), 0, 111,
         AppCacheEntry(AppCacheEntry::EXPLICIT, written_response_id_),
diff --git a/webkit/browser/database/vfs_backend.cc b/webkit/browser/database/vfs_backend.cc
index 3f51c2e..019e8b9 100644
--- a/webkit/browser/database/vfs_backend.cc
+++ b/webkit/browser/database/vfs_backend.cc
@@ -55,67 +55,60 @@
 }
 
 // static
-void VfsBackend::OpenFile(const base::FilePath& file_path,
-                          int desired_flags,
-                          base::PlatformFile* file_handle) {
+base::File VfsBackend::OpenFile(const base::FilePath& file_path,
+                                int desired_flags) {
   DCHECK(!file_path.empty());
 
   // Verify the flags for consistency and create the database
   // directory if it doesn't exist.
   if (!OpenFileFlagsAreConsistent(desired_flags) ||
-      !base::CreateDirectory(file_path.DirName()))
-    return;
+      !base::CreateDirectory(file_path.DirName())) {
+    return base::File();
+  }
 
   int flags = 0;
-  flags |= base::PLATFORM_FILE_READ;
+  flags |= base::File::FLAG_READ;
   if (desired_flags & SQLITE_OPEN_READWRITE)
-    flags |= base::PLATFORM_FILE_WRITE;
+    flags |= base::File::FLAG_WRITE;
 
-  if (!(desired_flags & SQLITE_OPEN_MAIN_DB)) {
-    flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
-             base::PLATFORM_FILE_EXCLUSIVE_WRITE;
-  }
+  if (!(desired_flags & SQLITE_OPEN_MAIN_DB))
+    flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE;
 
   flags |= ((desired_flags & SQLITE_OPEN_CREATE) ?
-      base::PLATFORM_FILE_OPEN_ALWAYS : base::PLATFORM_FILE_OPEN);
+           base::File::FLAG_OPEN_ALWAYS : base::File::FLAG_OPEN);
 
-  if (desired_flags & SQLITE_OPEN_EXCLUSIVE) {
-    flags |= base::PLATFORM_FILE_EXCLUSIVE_READ |
-             base::PLATFORM_FILE_EXCLUSIVE_WRITE;
-  }
+  if (desired_flags & SQLITE_OPEN_EXCLUSIVE)
+    flags |= base::File::FLAG_EXCLUSIVE_READ | base::File::FLAG_EXCLUSIVE_WRITE;
 
   if (desired_flags & SQLITE_OPEN_DELETEONCLOSE) {
-    flags |= base::PLATFORM_FILE_TEMPORARY | base::PLATFORM_FILE_HIDDEN |
-             base::PLATFORM_FILE_DELETE_ON_CLOSE;
+    flags |= base::File::FLAG_TEMPORARY | base::File::FLAG_HIDDEN |
+             base::File::FLAG_DELETE_ON_CLOSE;
   }
 
   // This flag will allow us to delete the file later on from the browser
   // process.
-  flags |= base::PLATFORM_FILE_SHARE_DELETE;
+  flags |= base::File::FLAG_SHARE_DELETE;
 
   // Try to open/create the DB file.
-  *file_handle =
-      base::CreatePlatformFile(file_path, flags, NULL, NULL);
+  return base::File(file_path, flags);
 }
 
 // static
-void VfsBackend::OpenTempFileInDirectory(
-    const base::FilePath& dir_path,
-    int desired_flags,
-    base::PlatformFile* file_handle) {
+base::File VfsBackend::OpenTempFileInDirectory(const base::FilePath& dir_path,
+                                               int desired_flags) {
   // We should be able to delete temp files when they're closed
   // and create them as needed
   if (!(desired_flags & SQLITE_OPEN_DELETEONCLOSE) ||
       !(desired_flags & SQLITE_OPEN_CREATE)) {
-    return;
+    return base::File();
   }
 
   // Get a unique temp file name in the database directory.
   base::FilePath temp_file_path;
   if (!base::CreateTemporaryFileInDir(dir_path, &temp_file_path))
-    return;
+    return base::File();
 
-  OpenFile(temp_file_path, desired_flags, file_handle);
+  return OpenFile(temp_file_path, desired_flags);
 }
 
 // static
@@ -128,14 +121,12 @@
   int error_code = SQLITE_OK;
 #if defined(OS_POSIX)
   if (sync_dir) {
-    base::PlatformFile dir_fd = base::CreatePlatformFile(
-        file_path.DirName(), base::PLATFORM_FILE_READ, NULL, NULL);
-    if (dir_fd == base::kInvalidPlatformFileValue) {
-      error_code = SQLITE_CANTOPEN;
-    } else {
-      if (fsync(dir_fd))
+    base::File dir(file_path.DirName(), base::File::FLAG_READ);
+    if (dir.IsValid()) {
+      if (!dir.Flush())
         error_code = SQLITE_IOERR_DIR_FSYNC;
-      base::ClosePlatformFile(dir_fd);
+    } else {
+      error_code = SQLITE_CANTOPEN;
     }
   }
 #endif
diff --git a/webkit/browser/database/vfs_backend.h b/webkit/browser/database/vfs_backend.h
index 6bc4e168..1fb63c9 100644
--- a/webkit/browser/database/vfs_backend.h
+++ b/webkit/browser/database/vfs_backend.h
@@ -5,7 +5,7 @@
 #ifndef WEBKIT_BROWSER_DATABASE_VFS_BACKEND_H_
 #define WEBKIT_BROWSER_DATABASE_VFS_BACKEND_H_
 
-#include "base/platform_file.h"
+#include "base/files/file.h"
 #include "base/process/process.h"
 #include "base/strings/string16.h"
 #include "webkit/browser/webkit_storage_browser_export.h"
@@ -18,13 +18,11 @@
 
 class WEBKIT_STORAGE_BROWSER_EXPORT VfsBackend {
  public:
-  static void OpenFile(const base::FilePath& file_path,
-                       int desired_flags,
-                       base::PlatformFile* file_handle);
+   static base::File OpenFile(const base::FilePath& file_path,
+                              int desired_flags);
 
-  static void OpenTempFileInDirectory(const base::FilePath& dir_path,
-                                      int desired_flags,
-                                      base::PlatformFile* file_handle);
+  static base::File OpenTempFileInDirectory(const base::FilePath& dir_path,
+                                            int desired_flags);
 
   static int DeleteFile(const base::FilePath& file_path, bool sync_dir);
 
diff --git a/webkit/browser/fileapi/file_system_context.cc b/webkit/browser/fileapi/file_system_context.cc
index 067b25b..f6e7df3 100644
--- a/webkit/browser/fileapi/file_system_context.cc
+++ b/webkit/browser/fileapi/file_system_context.cc
@@ -71,21 +71,24 @@
     case kFileSystemTypeNativeForPlatformApp:
     case kFileSystemTypeNativeLocal:
     case kFileSystemTypeCloudDevice:
+    case kFileSystemTypeProvided:
       return FILE_PERMISSION_USE_FILE_PERMISSION;
 
     case kFileSystemTypeRestrictedNativeLocal:
       return FILE_PERMISSION_READ_ONLY |
              FILE_PERMISSION_USE_FILE_PERMISSION;
 
-    // Following types are only accessed via IsolatedFileSystem, and
-    // don't have their own permission policies.
     case kFileSystemTypeDeviceMedia:
-    case kFileSystemTypeDragged:
-    case kFileSystemTypeForTransientFile:
     case kFileSystemTypeIphoto:
     case kFileSystemTypeItunes:
     case kFileSystemTypeNativeMedia:
     case kFileSystemTypePicasa:
+      return FILE_PERMISSION_USE_FILE_PERMISSION;
+
+    // Following types are only accessed via IsolatedFileSystem, and
+    // don't have their own permission policies.
+    case kFileSystemTypeDragged:
+    case kFileSystemTypeForTransientFile:
     case kFileSystemTypePluginPrivate:
       return FILE_PERMISSION_ALWAYS_DENY;
 
diff --git a/webkit/browser/fileapi/file_system_usage_cache.cc b/webkit/browser/fileapi/file_system_usage_cache.cc
index c264e69..89c6db1 100644
--- a/webkit/browser/fileapi/file_system_usage_cache.cc
+++ b/webkit/browser/fileapi/file_system_usage_cache.cc
@@ -162,12 +162,7 @@
 void FileSystemUsageCache::CloseCacheFiles() {
   TRACE_EVENT0("FileSystem", "UsageCache::CloseCacheFiles");
   DCHECK(CalledOnValidThread());
-  for (CacheFiles::iterator itr = cache_files_.begin();
-       itr != cache_files_.end(); ++itr) {
-    if (itr->second != base::kInvalidPlatformFileValue)
-      base::ClosePlatformFile(itr->second);
-  }
-  cache_files_.clear();
+  STLDeleteValues(&cache_files_);
   timer_.reset();
 }
 
@@ -228,63 +223,59 @@
   return true;
 }
 
-bool FileSystemUsageCache::GetPlatformFile(const base::FilePath& file_path,
-                                           base::PlatformFile* file) {
+base::File* FileSystemUsageCache::GetFile(const base::FilePath& file_path) {
   DCHECK(CalledOnValidThread());
   if (cache_files_.size() >= kMaxHandleCacheSize)
     CloseCacheFiles();
   ScheduleCloseTimer();
 
+  base::File* new_file = NULL;
   std::pair<CacheFiles::iterator, bool> inserted =
-      cache_files_.insert(
-          std::make_pair(file_path, base::kInvalidPlatformFileValue));
-  if (!inserted.second) {
-    *file = inserted.first->second;
-    return true;
-  }
+      cache_files_.insert(std::make_pair(file_path, new_file));
+  if (!inserted.second)
+    return inserted.first->second;
 
-  base::PlatformFileError error = base::PLATFORM_FILE_ERROR_FAILED;
-  base::PlatformFile platform_file =
-      base::CreatePlatformFile(file_path,
-                               base::PLATFORM_FILE_OPEN_ALWAYS |
-                               base::PLATFORM_FILE_READ |
-                               base::PLATFORM_FILE_WRITE,
-                               NULL, &error);
-  if (error != base::PLATFORM_FILE_OK) {
+  new_file = new base::File(file_path,
+                            base::File::FLAG_OPEN_ALWAYS |
+                            base::File::FLAG_READ |
+                            base::File::FLAG_WRITE);
+  if (!new_file->IsValid()) {
     cache_files_.erase(inserted.first);
-    return false;
+    delete new_file;
+    return NULL;
   }
 
-  inserted.first->second = platform_file;
-  *file = platform_file;
-  return true;
+  inserted.first->second = new_file;
+  return new_file;
 }
 
 bool FileSystemUsageCache::ReadBytes(const base::FilePath& file_path,
                                      char* buffer,
                                      int64 buffer_size) {
   DCHECK(CalledOnValidThread());
-  base::PlatformFile file;
-  if (!GetPlatformFile(file_path, &file))
+  base::File* file = GetFile(file_path);
+  if (!file)
     return false;
-  return base::ReadPlatformFile(file, 0, buffer, buffer_size) == buffer_size;
+  return file->Read(0, buffer, buffer_size) == buffer_size;
 }
 
 bool FileSystemUsageCache::WriteBytes(const base::FilePath& file_path,
                                       const char* buffer,
                                       int64 buffer_size) {
   DCHECK(CalledOnValidThread());
-  base::PlatformFile file;
-  if (!GetPlatformFile(file_path, &file))
+  base::File* file = GetFile(file_path);
+  if (!file)
     return false;
-  return base::WritePlatformFile(file, 0, buffer, buffer_size) == buffer_size;
+  return file->Write(0, buffer, buffer_size) == buffer_size;
 }
 
 bool FileSystemUsageCache::FlushFile(const base::FilePath& file_path) {
   TRACE_EVENT0("FileSystem", "UsageCache::FlushFile");
   DCHECK(CalledOnValidThread());
-  base::PlatformFile file = base::kInvalidPlatformFileValue;
-  return GetPlatformFile(file_path, &file) && base::FlushPlatformFile(file);
+  base::File* file = GetFile(file_path);
+  if (!file)
+    return false;
+  return file->Flush();
 }
 
 void FileSystemUsageCache::ScheduleCloseTimer() {
diff --git a/webkit/browser/fileapi/file_system_usage_cache.h b/webkit/browser/fileapi/file_system_usage_cache.h
index c3950a5..d4451e3 100644
--- a/webkit/browser/fileapi/file_system_usage_cache.h
+++ b/webkit/browser/fileapi/file_system_usage_cache.h
@@ -8,10 +8,10 @@
 #include <map>
 
 #include "base/basictypes.h"
+#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/memory/scoped_ptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/platform_file.h"
 #include "base/sequenced_task_runner.h"
 #include "webkit/browser/webkit_storage_browser_export.h"
 
@@ -61,7 +61,7 @@
   static const int kUsageFileHeaderSize;
 
  private:
-  typedef std::map<base::FilePath, base::PlatformFile> CacheFiles;
+  typedef std::map<base::FilePath, base::File*> CacheFiles;
 
   // Read the size, validity and the "dirty" entry described in the .usage file.
   // Returns less than zero if no .usage file is available.
@@ -75,8 +75,7 @@
              int32 dirty,
              int64 fs_usage);
 
-  bool GetPlatformFile(const base::FilePath& file_path,
-                       base::PlatformFile* file);
+  base::File* GetFile(const base::FilePath& file_path);
 
   bool ReadBytes(const base::FilePath& file_path,
                  char* buffer,
@@ -92,7 +91,7 @@
   bool CalledOnValidThread();
 
   scoped_ptr<TimedTaskHelper> timer_;
-  std::map<base::FilePath, base::PlatformFile> cache_files_;
+  CacheFiles cache_files_;
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
diff --git a/webkit/browser/fileapi/local_file_util.cc b/webkit/browser/fileapi/local_file_util.cc
index 032244f..90d45e3 100644
--- a/webkit/browser/fileapi/local_file_util.cc
+++ b/webkit/browser/fileapi/local_file_util.cc
@@ -89,13 +89,20 @@
   if (base::IsLink(file_path))
     return base::File::FILE_ERROR_NOT_FOUND;
 
-  return NativeFileUtil::CreateOrOpen(file_path, file_flags, file_handle,
-                                      created);
+  // TODO(rvargas): make FileSystemFileUtil use base::File.
+  base::File file = NativeFileUtil::CreateOrOpen(file_path, file_flags);
+  if (!file.IsValid())
+    return file.error_details();
+
+  *created = file.created();
+  *file_handle = file.TakePlatformFile();
+  return base::File::FILE_OK;
 }
 
 base::File::Error LocalFileUtil::Close(FileSystemOperationContext* context,
                                        base::PlatformFile file) {
-  return NativeFileUtil::Close(file);
+  base::File auto_closed(file);
+  return base::File::FILE_OK;
 }
 
 base::File::Error LocalFileUtil::EnsureFileExists(
diff --git a/webkit/browser/fileapi/native_file_util.cc b/webkit/browser/fileapi/native_file_util.cc
index e99e297..c022994 100644
--- a/webkit/browser/fileapi/native_file_util.cc
+++ b/webkit/browser/fileapi/native_file_util.cc
@@ -5,9 +5,9 @@
 #include "webkit/browser/fileapi/native_file_util.h"
 
 #include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/files/file_enumerator.h"
 #include "base/memory/scoped_ptr.h"
-#include "net/base/file_stream.h"
 #include "webkit/browser/fileapi/file_system_operation_context.h"
 #include "webkit/browser/fileapi/file_system_url.h"
 
@@ -37,15 +37,14 @@
 // Copies a file |from| to |to|, and ensure the written content is synced to
 // the disk. This is essentially base::CopyFile followed by fsync().
 bool CopyFileAndSync(const base::FilePath& from, const base::FilePath& to) {
-  net::FileStream infile(NULL);
-  if (infile.OpenSync(from,
-          base::PLATFORM_FILE_OPEN | base:: PLATFORM_FILE_READ) < 0) {
+  base::File infile(from, base::File::FLAG_OPEN | base::File::FLAG_READ);
+  if (!infile.IsValid()) {
     return false;
   }
 
-  net::FileStream outfile(NULL);
-  if (outfile.OpenSync(to,
-          base::PLATFORM_FILE_CREATE_ALWAYS | base:: PLATFORM_FILE_WRITE) < 0) {
+  base::File outfile(to,
+                     base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+  if (!outfile.IsValid()) {
     return false;
   }
 
@@ -53,21 +52,21 @@
   std::vector<char> buffer(kBufferSize);
 
   for (;;) {
-    int bytes_read = infile.ReadSync(&buffer[0], kBufferSize);
+    int bytes_read = infile.ReadAtCurrentPos(&buffer[0], kBufferSize);
     if (bytes_read < 0)
       return false;
     if (bytes_read == 0)
       break;
     for (int bytes_written = 0; bytes_written < bytes_read; ) {
-      int bytes_written_partial = outfile.WriteSync(&buffer[bytes_written],
-                                                    bytes_read - bytes_written);
+      int bytes_written_partial = outfile.WriteAtCurrentPos(
+          &buffer[bytes_written], bytes_read - bytes_written);
       if (bytes_written_partial < 0)
         return false;
       bytes_written += bytes_written_partial;
     }
   }
 
-  return outfile.FlushSync() >= 0;
+  return outfile.Flush();
 }
 
 }  // namespace
@@ -122,27 +121,18 @@
   return MOVE;
 }
 
-base::File::Error NativeFileUtil::CreateOrOpen(
-    const base::FilePath& path, int file_flags,
-    PlatformFile* file_handle, bool* created) {
+base::File NativeFileUtil::CreateOrOpen(const base::FilePath& path,
+                                        int file_flags) {
   if (!base::DirectoryExists(path.DirName())) {
     // If its parent does not exist, should return NOT_FOUND error.
-    return base::File::FILE_ERROR_NOT_FOUND;
+    return base::File(base::File::FILE_ERROR_NOT_FOUND);
   }
+
+  // TODO(rvargas): Check |file_flags| instead. See bug 356358.
   if (base::DirectoryExists(path))
-    return base::File::FILE_ERROR_NOT_A_FILE;
+    return base::File(base::File::FILE_ERROR_NOT_A_FILE);
 
-  // TODO(rvargas): convert this code to use base::File.
-  base::PlatformFileError error_code = base::PLATFORM_FILE_OK;
-  *file_handle = base::CreatePlatformFile(path, file_flags,
-                                          created, &error_code);
-  return static_cast<base::File::Error>(error_code);
-}
-
-base::File::Error NativeFileUtil::Close(PlatformFile file_handle) {
-  if (!base::ClosePlatformFile(file_handle))
-    return base::File::FILE_ERROR_FAILED;
-  return base::File::FILE_OK;
+  return base::File(path, file_flags);
 }
 
 base::File::Error NativeFileUtil::EnsureFileExists(
diff --git a/webkit/browser/fileapi/native_file_util.h b/webkit/browser/fileapi/native_file_util.h
index 7069c02..c6aeec4 100644
--- a/webkit/browser/fileapi/native_file_util.h
+++ b/webkit/browser/fileapi/native_file_util.h
@@ -9,7 +9,6 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util_proxy.h"
 #include "base/memory/scoped_ptr.h"
-#include "base/platform_file.h"
 #include "webkit/browser/fileapi/file_system_file_util.h"
 #include "webkit/browser/webkit_storage_browser_export.h"
 
@@ -39,12 +38,8 @@
   static CopyOrMoveMode CopyOrMoveModeForDestination(
       const FileSystemURL& dest_url, bool copy);
 
-  static base::File::Error CreateOrOpen(
-      const base::FilePath& path,
-      int file_flags,
-      base::PlatformFile* file_handle,
-      bool* created);
-  static base::File::Error Close(base::PlatformFile file);
+  static base::File CreateOrOpen(const base::FilePath& path,
+                                 int file_flags);
   static base::File::Error EnsureFileExists(const base::FilePath& path,
                                             bool* created);
   static base::File::Error CreateDirectory(const base::FilePath& path,
@@ -59,7 +54,7 @@
                                  const base::Time& last_access_time,
                                  const base::Time& last_modified_time);
   static base::File::Error Truncate(const base::FilePath& path,
-                                          int64 length);
+                                    int64 length);
   static bool PathExists(const base::FilePath& path);
   static bool DirectoryExists(const base::FilePath& path);
   static base::File::Error CopyOrMoveFile(
diff --git a/webkit/browser/fileapi/native_file_util_unittest.cc b/webkit/browser/fileapi/native_file_util_unittest.cc
index cdf088f..6850921 100644
--- a/webkit/browser/fileapi/native_file_util_unittest.cc
+++ b/webkit/browser/fileapi/native_file_util_unittest.cc
@@ -5,9 +5,9 @@
 #include <set>
 
 #include "base/file_util.h"
+#include "base/files/file.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/platform_file.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webkit/browser/fileapi/native_file_util.h"
 
@@ -49,28 +49,21 @@
 
 TEST_F(NativeFileUtilTest, CreateCloseAndDeleteFile) {
   base::FilePath file_name = Path("test_file");
-  base::PlatformFile file_handle;
-  bool created = false;
-  int flags = base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC;
-  ASSERT_EQ(base::File::FILE_OK,
-            NativeFileUtil::CreateOrOpen(file_name,
-                                         base::PLATFORM_FILE_CREATE | flags,
-                                         &file_handle, &created));
-  ASSERT_TRUE(created);
+  int flags = base::File::FLAG_WRITE | base::File::FLAG_ASYNC;
+  base::File file =
+      NativeFileUtil::CreateOrOpen(file_name, base::File::FLAG_CREATE | flags);
+  ASSERT_TRUE(file.IsValid());
+  ASSERT_TRUE(file.created());
 
   EXPECT_TRUE(base::PathExists(file_name));
   EXPECT_TRUE(NativeFileUtil::PathExists(file_name));
   EXPECT_EQ(0, GetSize(file_name));
-  EXPECT_NE(base::kInvalidPlatformFileValue, file_handle);
+  file.Close();
 
-  ASSERT_EQ(base::File::FILE_OK, NativeFileUtil::Close(file_handle));
-
-  ASSERT_EQ(base::File::FILE_OK,
-            NativeFileUtil::CreateOrOpen(file_name,
-                                         base::PLATFORM_FILE_OPEN | flags,
-                                         &file_handle, &created));
-  ASSERT_FALSE(created);
-  ASSERT_EQ(base::File::FILE_OK, NativeFileUtil::Close(file_handle));
+  file = NativeFileUtil::CreateOrOpen(file_name, base::File::FLAG_OPEN | flags);
+  ASSERT_TRUE(file.IsValid());
+  ASSERT_FALSE(file.created());
+  file.Close();
 
   ASSERT_EQ(base::File::FILE_OK,
             NativeFileUtil::DeleteFile(file_name));
diff --git a/webkit/browser/fileapi/obfuscated_file_util.cc b/webkit/browser/fileapi/obfuscated_file_util.cc
index 952645a..d720ca0 100644
--- a/webkit/browser/fileapi/obfuscated_file_util.cc
+++ b/webkit/browser/fileapi/obfuscated_file_util.cc
@@ -292,7 +292,8 @@
 base::File::Error ObfuscatedFileUtil::Close(
     FileSystemOperationContext* context,
     base::PlatformFile file) {
-  return NativeFileUtil::Close(file);
+  base::File auto_closed(file);
+  return base::File::FILE_OK;
 }
 
 base::File::Error ObfuscatedFileUtil::EnsureFileExists(
@@ -1080,17 +1081,23 @@
     created = true;
   } else {
     if (base::PathExists(dest_local_path)) {
-      if (!base::DeleteFile(dest_local_path, true /* recursive */)) {
-        NOTREACHED();
+      if (!base::DeleteFile(dest_local_path, true /* recursive */))
         return base::File::FILE_ERROR_FAILED;
-      }
       LOG(WARNING) << "A stray file detected";
       InvalidateUsageCache(context, dest_url.origin(), dest_url.type());
     }
 
     if (handle) {
-      error = NativeFileUtil::CreateOrOpen(
-          dest_local_path, file_flags, handle, &created);
+      // TODO(rvargas): Remove PlatformFile from this code.
+      base::File file =
+          NativeFileUtil::CreateOrOpen(dest_local_path, file_flags);
+      if (file.IsValid()) {
+        created = file.created();
+        *handle = file.TakePlatformFile();
+        error = base::File::FILE_OK;
+      } else {
+        error = file.error_details();
+      }
       // If this succeeds, we must close handle on any subsequent error.
     } else {
       DCHECK(!file_flags);  // file_flags is only used by CreateOrOpen.
@@ -1101,7 +1108,6 @@
     return error;
 
   if (!created) {
-    NOTREACHED();
     if (handle) {
       DCHECK_NE(base::kInvalidPlatformFileValue, *handle);
       base::ClosePlatformFile(*handle);
@@ -1396,23 +1402,30 @@
     AllocateQuota(context, delta);
   }
 
-  error = NativeFileUtil::CreateOrOpen(
-      local_path, file_flags, file_handle, created);
-  if (error == base::File::FILE_ERROR_NOT_FOUND) {
-    // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker.
-    // TODO(tzik): Delete database entry after ensuring the file lost.
-    InvalidateUsageCache(context, url.origin(), url.type());
-    LOG(WARNING) << "Lost a backing file.";
-    error = base::File::FILE_ERROR_FAILED;
+  // TODO(rvargas): make FileSystemFileUtil use base::File.
+  base::File file = NativeFileUtil::CreateOrOpen(local_path, file_flags);
+  if (!file.IsValid()) {
+    error = file.error_details();
+    if (error == base::File::FILE_ERROR_NOT_FOUND) {
+      // TODO(tzik): Also invalidate on-memory usage cache in UsageTracker.
+      // TODO(tzik): Delete database entry after ensuring the file lost.
+      InvalidateUsageCache(context, url.origin(), url.type());
+      LOG(WARNING) << "Lost a backing file.";
+      error = base::File::FILE_ERROR_FAILED;
+    }
+    return error;
   }
 
+  *created = file.created();
+  *file_handle = file.TakePlatformFile();
+
   // If truncating we need to update the usage.
-  if (error == base::File::FILE_OK && delta) {
+  if (delta) {
     UpdateUsage(context, url, delta);
     context->change_observers()->Notify(
         &FileChangeObserver::OnModifyFile, MakeTuple(url));
   }
-  return error;
+  return base::File::FILE_OK;
 }
 
 bool ObfuscatedFileUtil::HasIsolatedStorage(const GURL& origin) {
diff --git a/webkit/child/overscroller_jni_headers.target.darwin-arm.mk b/webkit/child/overscroller_jni_headers.target.darwin-arm.mk
index 18d95ab..e2534ee 100644
--- a/webkit/child/overscroller_jni_headers.target.darwin-arm.mk
+++ b/webkit/child/overscroller_jni_headers.target.darwin-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/overscroller_jni_headers.target.darwin-mips.mk b/webkit/child/overscroller_jni_headers.target.darwin-mips.mk
index b881fc9..c7b5098 100644
--- a/webkit/child/overscroller_jni_headers.target.darwin-mips.mk
+++ b/webkit/child/overscroller_jni_headers.target.darwin-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/overscroller_jni_headers.target.darwin-x86.mk b/webkit/child/overscroller_jni_headers.target.darwin-x86.mk
index 4fb17ee..32f319c 100644
--- a/webkit/child/overscroller_jni_headers.target.darwin-x86.mk
+++ b/webkit/child/overscroller_jni_headers.target.darwin-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/overscroller_jni_headers.target.darwin-x86_64.mk b/webkit/child/overscroller_jni_headers.target.darwin-x86_64.mk
new file mode 100644
index 0000000..e33740d
--- /dev/null
+++ b/webkit/child/overscroller_jni_headers.target.darwin-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := webkit_child_overscroller_jni_headers_gyp
+LOCAL_MODULE_STEM := overscroller_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/widget/OverScroller.class ($@)"
+	$(hide)cd $(gyp_local_path)/webkit/child; mkdir -p $(gyp_shared_intermediate_dir)/webkit/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/widget/OverScroller.class --output_dir "$(gyp_shared_intermediate_dir)/webkit/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_child_overscroller_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: overscroller_jni_headers
+overscroller_jni_headers: webkit_child_overscroller_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/webkit/child/overscroller_jni_headers.target.linux-arm.mk b/webkit/child/overscroller_jni_headers.target.linux-arm.mk
index 18d95ab..e2534ee 100644
--- a/webkit/child/overscroller_jni_headers.target.linux-arm.mk
+++ b/webkit/child/overscroller_jni_headers.target.linux-arm.mk
@@ -90,6 +90,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -172,6 +173,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/overscroller_jni_headers.target.linux-mips.mk b/webkit/child/overscroller_jni_headers.target.linux-mips.mk
index b881fc9..c7b5098 100644
--- a/webkit/child/overscroller_jni_headers.target.linux-mips.mk
+++ b/webkit/child/overscroller_jni_headers.target.linux-mips.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -170,6 +171,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/overscroller_jni_headers.target.linux-x86.mk b/webkit/child/overscroller_jni_headers.target.linux-x86.mk
index 4fb17ee..32f319c 100644
--- a/webkit/child/overscroller_jni_headers.target.linux-x86.mk
+++ b/webkit/child/overscroller_jni_headers.target.linux-x86.mk
@@ -91,6 +91,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -173,6 +174,7 @@
 	'-DENABLE_PRINTING=1' \
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/overscroller_jni_headers.target.linux-x86_64.mk b/webkit/child/overscroller_jni_headers.target.linux-x86_64.mk
new file mode 100644
index 0000000..e33740d
--- /dev/null
+++ b/webkit/child/overscroller_jni_headers.target.linux-x86_64.mk
@@ -0,0 +1,229 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := webkit_child_overscroller_jni_headers_gyp
+LOCAL_MODULE_STEM := overscroller_jni_headers
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "generate_jni_headers_from_jar_file":
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h: $(LOCAL_PATH)/base/android/jni_generator/jni_generator.py $(PWD)/prebuilts/sdk/18/android.jar $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating JNI bindings from  $(PWD)/prebuilts/sdk/18/android.jar/android/widget/OverScroller.class ($@)"
+	$(hide)cd $(gyp_local_path)/webkit/child; mkdir -p $(gyp_shared_intermediate_dir)/webkit/jni; ../../base/android/jni_generator/jni_generator.py -j "$(PWD)/prebuilts/sdk/18/android.jar" --input_file android/widget/OverScroller.class --output_dir "$(gyp_shared_intermediate_dir)/webkit/jni" --includes base/android/jni_generator/jni_generator_helper.h --optimize_generation 0
+
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_GENERATED_SOURCES := \
+	$(gyp_shared_intermediate_dir)/webkit/jni/OverScroller_jni.h
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES :=
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_child_overscroller_jni_headers_gyp
+
+# Alias gyp target name.
+.PHONY: overscroller_jni_headers
+overscroller_jni_headers: webkit_child_overscroller_jni_headers_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/webkit/child/resource_loader_bridge.cc b/webkit/child/resource_loader_bridge.cc
index 439a09f..35cf74e 100644
--- a/webkit/child/resource_loader_bridge.cc
+++ b/webkit/child/resource_loader_bridge.cc
@@ -4,28 +4,8 @@
 
 #include "webkit/child/resource_loader_bridge.h"
 
-#include "net/http/http_response_headers.h"
-#include "webkit/common/appcache/appcache_interfaces.h"
-#include "webkit/common/resource_response_info.h"
-
 namespace webkit_glue {
 
-ResourceLoaderBridge::RequestInfo::RequestInfo()
-    : referrer_policy(blink::WebReferrerPolicyDefault),
-      load_flags(0),
-      requestor_pid(0),
-      request_type(ResourceType::MAIN_FRAME),
-      priority(net::LOW),
-      request_context(0),
-      appcache_host_id(0),
-      routing_id(0),
-      download_to_file(false),
-      has_user_gesture(false),
-      extra_data(NULL) {
-}
-
-ResourceLoaderBridge::RequestInfo::~RequestInfo() {}
-
 ResourceLoaderBridge::SyncLoadResponse::SyncLoadResponse() {}
 
 ResourceLoaderBridge::SyncLoadResponse::~SyncLoadResponse() {}
diff --git a/webkit/child/resource_loader_bridge.h b/webkit/child/resource_loader_bridge.h
index 7532386..efe8b77 100644
--- a/webkit/child/resource_loader_bridge.h
+++ b/webkit/child/resource_loader_bridge.h
@@ -26,12 +26,9 @@
 #include "base/platform_file.h"
 #include "base/values.h"
 #include "net/base/request_priority.h"
-#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
 #include "url/gurl.h"
 #include "webkit/child/webkit_child_export.h"
 #include "webkit/common/resource_response_info.h"
-#include "webkit/common/resource_type.h"
 
 // TODO(pilgrim) remove this once resource loader is moved to content
 // http://crbug.com/338338
@@ -43,71 +40,6 @@
 
 class ResourceLoaderBridge {
  public:
-  // Structure used when calling
-  // WebKitPlatformSupportImpl::CreateResourceLoader().
-  struct WEBKIT_CHILD_EXPORT RequestInfo {
-    RequestInfo();
-    ~RequestInfo();
-
-    // HTTP-style method name (e.g., "GET" or "POST").
-    std::string method;
-
-    // Absolute URL encoded in ASCII per the rules of RFC-2396.
-    GURL url;
-
-    // URL of the document in the top-level window, which may be checked by the
-    // third-party cookie blocking policy.
-    GURL first_party_for_cookies;
-
-    // Optional parameter, a URL with similar constraints in how it must be
-    // encoded as the url member.
-    GURL referrer;
-
-    // The referrer policy that applies to the referrer.
-    blink::WebReferrerPolicy referrer_policy;
-
-    // For HTTP(S) requests, the headers parameter can be a \r\n-delimited and
-    // \r\n-terminated list of MIME headers.  They should be ASCII-encoded using
-    // the standard MIME header encoding rules.  The headers parameter can also
-    // be null if no extra request headers need to be set.
-    std::string headers;
-
-    // Composed of the values defined in url_request_load_flags.h.
-    int load_flags;
-
-    // Process id of the process making the request.
-    int requestor_pid;
-
-    // Indicates if the current request is the main frame load, a sub-frame
-    // load, or a sub objects load.
-    ResourceType::Type request_type;
-
-    // Indicates the priority of this request, as determined by WebKit.
-    net::RequestPriority priority;
-
-    // Used for plugin to browser requests.
-    uint32 request_context;
-
-    // Identifies what appcache host this request is associated with.
-    int appcache_host_id;
-
-    // Used to associated the bridge with a frame's network context.
-    int routing_id;
-
-    // If true, then the response body will be downloaded to a file and the
-    // path to that file will be provided in ResponseInfo::download_file_path.
-    bool download_to_file;
-
-    // True if the request was user initiated.
-    bool has_user_gesture;
-
-    // Extra data associated with this request.  We do not own this pointer.
-    blink::WebURLRequest::ExtraData* extra_data;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(RequestInfo);
-  };
-
   // See the SyncLoad method declared below.  (The name of this struct is not
   // suffixed with "Info" because it also contains the response data.)
   struct SyncLoadResponse : ResourceResponseInfo {
diff --git a/webkit/child/touch_fling_gesture_curve.cc b/webkit/child/touch_fling_gesture_curve.cc
deleted file mode 100644
index 91033da..0000000
--- a/webkit/child/touch_fling_gesture_curve.cc
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/child/touch_fling_gesture_curve.h"
-
-#include <cmath>
-
-#include "base/debug/trace_event.h"
-#include "base/logging.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-
-using blink::WebFloatPoint;
-using blink::WebFloatSize;
-using blink::WebGestureCurve;
-using blink::WebGestureCurveTarget;
-using blink::WebSize;
-
-namespace {
-
-const char* kCurveName = "TouchFlingGestureCurve";
-
-inline double position(double t, float* p) {
-  return p[0] * exp(-p[2] * t) - p[1] * t - p[0];
-}
-
-inline double velocity(double t, float* p) {
-  return -p[0] * p[2] * exp(-p[2] * t) - p[1];
-}
-
-inline double timeAtVelocity(double v, float* p) {
-    DCHECK(p[0]);
-    DCHECK(p[2]);
-    return -log((v + p[1]) / (-p[0] * p[2])) / p[2];
-}
-
-} // namespace
-
-
-namespace webkit_glue {
-
-// This curve implementation is based on the notion of a single, absolute
-// curve, which starts at a large velocity and smoothly decreases to
-// zero. For a given input velocity, we find where on the curve this
-// velocity occurs, and start the animation at this point---denoted by
-// (time_offset_, position_offset_).
-//
-// This has the effect of automatically determining an animation duration
-// that scales with input velocity, as faster initial velocities start
-// earlier on the curve and thus take longer to reach the end. No
-// complicated time scaling is required.
-//
-// Since the starting velocity is implicitly determined by our starting
-// point, we only store the relative magnitude and direction of both
-// initial x- and y-velocities, and use this to scale the computed
-// displacement at any point in time. This guarantees that fling
-// trajectories are straight lines when viewed in x-y space. Initial
-// velocities that lie outside the max velocity are constrained to start
-// at zero (and thus are implicitly scaled).
-//
-// The curve is modelled as a 4th order polynomial, starting at t = 0,
-// and ending at t = curve_duration_. Attempts to generate
-// position/velocity estimates outside this range are undefined.
-
-WebGestureCurve* TouchFlingGestureCurve::Create(
-    const WebFloatPoint& initial_velocity,
-    float p0,
-    float p1,
-    float p2,
-    const WebSize& cumulative_scroll) {
-  return new TouchFlingGestureCurve(initial_velocity, p0, p1, p2,
-                                    cumulative_scroll);
-}
-
-TouchFlingGestureCurve::TouchFlingGestureCurve(
-    const WebFloatPoint& initial_velocity,
-    float alpha,
-    float beta,
-    float gamma,
-    const WebSize& cumulative_scroll)
-    : cumulative_scroll_(WebFloatSize(cumulative_scroll.width,
-                                      cumulative_scroll.height)) {
-  DCHECK(initial_velocity != WebFloatPoint());
-
-  coefficients_[0] = alpha;
-  coefficients_[1] = beta;
-  coefficients_[2] = gamma;
-
-  // Curve ends when velocity reaches zero.
-  curve_duration_ = timeAtVelocity(0, coefficients_);
-  DCHECK(curve_duration_ > 0);
-
-  float max_start_velocity = std::max(fabs(initial_velocity.x),
-                                      fabs(initial_velocity.y));
-
-  // Force max_start_velocity to lie in the range v(0) to v(curve_duration),
-  // and assume that the curve parameters define a monotonically decreasing
-  // velocity, or else bisection search may fail.
-  if (max_start_velocity > velocity(0, coefficients_))
-    max_start_velocity = velocity(0, coefficients_);
-
-  if (max_start_velocity < 0)
-    max_start_velocity = 0;
-
-  // We keep track of relative magnitudes and directions of the
-  // velocity/displacement components here.
-  displacement_ratio_ = WebFloatPoint(initial_velocity.x / max_start_velocity,
-                                      initial_velocity.y / max_start_velocity);
-
-  // Compute time-offset for start velocity.
-  time_offset_ = timeAtVelocity(max_start_velocity, coefficients_);
-
-  // Compute curve position at offset time
-  position_offset_ = position(time_offset_, coefficients_);
-  TRACE_EVENT_ASYNC_BEGIN1("input", "GestureAnimation", this, "curve",
-      kCurveName);
-}
-
-TouchFlingGestureCurve::~TouchFlingGestureCurve() {
-  TRACE_EVENT_ASYNC_END0("input", "GestureAnimation", this);
-}
-
-bool TouchFlingGestureCurve::apply(double time, WebGestureCurveTarget* target) {
-  float displacement;
-  float speed;
-  if (time < 0) {
-    displacement = 0.f;
-    speed = 0.f;
-  } else if (time + time_offset_ < curve_duration_) {
-    displacement =
-        position(time + time_offset_, coefficients_) - position_offset_;
-    speed = velocity(time + time_offset_, coefficients_);
-  } else {
-    displacement = position(curve_duration_, coefficients_) - position_offset_;
-    speed = 0.f;
-  }
-
-  // Keep track of integer portion of scroll thus far, and prepare increment.
-  WebFloatSize scroll(displacement * displacement_ratio_.x,
-                      displacement * displacement_ratio_.y);
-  WebFloatSize scroll_increment(scroll.width - cumulative_scroll_.width,
-                                scroll.height - cumulative_scroll_.height);
-  WebFloatSize scroll_velocity(speed * displacement_ratio_.x,
-                               speed * displacement_ratio_.y);
-  cumulative_scroll_ = scroll;
-
-  if (time + time_offset_ < curve_duration_ ||
-      scroll_increment != WebFloatSize()) {
-    target->notifyCurrentFlingVelocity(scroll_velocity);
-    // scrollBy() could delete this curve if the animation is over, so don't
-    // touch any member variables after making that call.
-    target->scrollBy(scroll_increment);
-    return true;
-  }
-
-  return false;
-}
-
-} // namespace webkit_glue
diff --git a/webkit/child/touch_fling_gesture_curve.h b/webkit/child/touch_fling_gesture_curve.h
deleted file mode 100644
index 4f8876d..0000000
--- a/webkit/child/touch_fling_gesture_curve.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef WEBKIT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
-#define WEBKIT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
-
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-#include "webkit/child/webkit_child_export.h"
-
-namespace blink {
-class WebGestureCurveTarget;
-}
-
-namespace webkit_glue {
-
-// Implementation of WebGestureCurve suitable for touch pad/screen-based
-// fling scroll. Starts with a flat velocity profile based on 'velocity', which
-// tails off to zero. Time is scaled to that duration of the fling is
-// proportional to the initial velocity.
-class TouchFlingGestureCurve : public blink::WebGestureCurve {
- public:
-
-  WEBKIT_CHILD_EXPORT static WebGestureCurve* Create(
-      const blink::WebFloatPoint& initial_velocity,
-      float p0, float p1, float p2,
-      const blink::WebSize& cumulativeScroll);
-
- virtual bool apply(double monotonicTime,
-                    blink::WebGestureCurveTarget*) OVERRIDE;
-
- private:
-  TouchFlingGestureCurve(const blink::WebFloatPoint& initial_velocity,
-                         float p0,
-                         float p1,
-                         float p2,
-                         const blink::WebSize& cumulativeScroll);
-  virtual ~TouchFlingGestureCurve();
-
-  blink::WebFloatPoint displacement_ratio_;
-  blink::WebFloatSize cumulative_scroll_;
-  float coefficients_[3];
-  float time_offset_;
-  float curve_duration_;
-  float position_offset_;
-
-  DISALLOW_COPY_AND_ASSIGN(TouchFlingGestureCurve);
-};
-
-} // namespace webkit_glue
-
-#endif // WEBKIT_CHILD_TOUCH_FLING_GESTURE_CURVE_H_
diff --git a/webkit/child/touch_fling_gesture_curve_unittest.cc b/webkit/child/touch_fling_gesture_curve_unittest.cc
deleted file mode 100644
index 91b0609..0000000
--- a/webkit/child/touch_fling_gesture_curve_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-  // Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Tests for the TouchFlingGestureCurve.
-
-#include "webkit/child/touch_fling_gesture_curve.h"
-
-#include "base/memory/scoped_ptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebGestureCurveTarget.h"
-#include "third_party/WebKit/public/platform/WebSize.h"
-
-using blink::WebFloatPoint;
-using blink::WebFloatSize;
-using blink::WebGestureCurve;
-using blink::WebGestureCurveTarget;
-using blink::WebSize;
-
-namespace {
-
-class MockGestureCurveTarget : public WebGestureCurveTarget {
- public:
-  virtual void scrollBy(const WebFloatSize& delta) {
-    cumulative_delta_.width += delta.width;
-    cumulative_delta_.height += delta.height;
-  }
-
-  virtual void notifyCurrentFlingVelocity(const WebFloatSize& velocity) {
-    current_velocity_ = velocity;
-  }
-
-  WebFloatSize cumulative_delta() const { return cumulative_delta_; }
-  void resetCumulativeDelta() { cumulative_delta_ = WebFloatSize(); }
-
-  WebFloatSize current_velocity() const { return current_velocity_; }
-
- private:
-  WebFloatSize cumulative_delta_;
-  WebFloatSize current_velocity_;
-};
-
-} // namespace anonymous
-
-TEST(TouchFlingGestureCurve, flingCurveTouch)
-{
-  double initialVelocity = 5000;
-  MockGestureCurveTarget target;
-
-  scoped_ptr<WebGestureCurve> curve(webkit_glue::TouchFlingGestureCurve::Create(
-      WebFloatPoint(initialVelocity, 0),
-      -5.70762e+03f, 1.72e+02f, 3.7e+00f, WebSize()));
-
-  // Note: the expectations below are dependent on the curve parameters hard
-  // coded into the create call above.
-  EXPECT_TRUE(curve->apply(0, &target));
-  EXPECT_TRUE(curve->apply(0.25, &target));
-  EXPECT_NEAR(target.current_velocity().width, 1878, 1);
-  EXPECT_EQ(target.current_velocity().height, 0);
-  EXPECT_TRUE(curve->apply(0.45f, &target)); // Use non-uniform tick spacing.
-  EXPECT_TRUE(curve->apply(1, &target));
-  EXPECT_FALSE(curve->apply(1.5, &target));
-  EXPECT_NEAR(target.cumulative_delta().width, 1193, 1);
-  EXPECT_EQ(target.cumulative_delta().height, 0);
-  EXPECT_EQ(target.current_velocity().width, 0);
-  EXPECT_EQ(target.current_velocity().height, 0);
-}
-
diff --git a/webkit/child/webkit_child.gyp b/webkit/child/webkit_child.gyp
index 1d3c0d9..e4ac2d2 100644
--- a/webkit/child/webkit_child.gyp
+++ b/webkit/child/webkit_child.gyp
@@ -58,11 +58,7 @@
         'multipart_response_delegate.h',
         'resource_loader_bridge.cc',
         'resource_loader_bridge.h',
-        'touch_fling_gesture_curve.cc',
-        'touch_fling_gesture_curve.h',
         'webkit_child_export.h',
-        'weburlrequest_extradata_impl.cc',
-        'weburlrequest_extradata_impl.h',
         'weburlresponse_extradata_impl.cc',
         'weburlresponse_extradata_impl.h',
       ],
diff --git a/webkit/child/webkit_child.target.darwin-arm.mk b/webkit/child/webkit_child.target.darwin-arm.mk
index 5136aa5..2bfa6e8 100644
--- a/webkit/child/webkit_child.target.darwin-arm.mk
+++ b/webkit/child/webkit_child.target.darwin-arm.mk
@@ -30,8 +30,6 @@
 LOCAL_SRC_FILES := \
 	webkit/child/multipart_response_delegate.cc \
 	webkit/child/resource_loader_bridge.cc \
-	webkit/child/touch_fling_gesture_curve.cc \
-	webkit/child/weburlrequest_extradata_impl.cc \
 	webkit/child/weburlresponse_extradata_impl.cc
 
 
@@ -96,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +107,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -236,9 +233,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +246,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/webkit_child.target.darwin-mips.mk b/webkit/child/webkit_child.target.darwin-mips.mk
index b559b24..bbadba4 100644
--- a/webkit/child/webkit_child.target.darwin-mips.mk
+++ b/webkit/child/webkit_child.target.darwin-mips.mk
@@ -30,8 +30,6 @@
 LOCAL_SRC_FILES := \
 	webkit/child/multipart_response_delegate.cc \
 	webkit/child/resource_loader_bridge.cc \
-	webkit/child/touch_fling_gesture_curve.cc \
-	webkit/child/weburlrequest_extradata_impl.cc \
 	webkit/child/weburlresponse_extradata_impl.cc
 
 
@@ -95,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +106,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -234,9 +231,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +244,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/webkit_child.target.darwin-x86.mk b/webkit/child/webkit_child.target.darwin-x86.mk
index 0128980..7b0ff7b 100644
--- a/webkit/child/webkit_child.target.darwin-x86.mk
+++ b/webkit/child/webkit_child.target.darwin-x86.mk
@@ -30,8 +30,6 @@
 LOCAL_SRC_FILES := \
 	webkit/child/multipart_response_delegate.cc \
 	webkit/child/resource_loader_bridge.cc \
-	webkit/child/touch_fling_gesture_curve.cc \
-	webkit/child/weburlrequest_extradata_impl.cc \
 	webkit/child/weburlresponse_extradata_impl.cc
 
 
@@ -96,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +107,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -235,9 +232,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -250,6 +245,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/webkit_child.target.darwin-x86_64.mk b/webkit/child/webkit_child.target.darwin-x86_64.mk
new file mode 100644
index 0000000..63eefd3
--- /dev/null
+++ b/webkit/child/webkit_child.target.darwin-x86_64.mk
@@ -0,0 +1,375 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_child_webkit_child_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/child/multipart_response_delegate.cc \
+	webkit/child/resource_loader_bridge.cc \
+	webkit/child/weburlresponse_extradata_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_CHILD_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_CHILD_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_child_webkit_child_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_child
+webkit_child: webkit_child_webkit_child_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/child/webkit_child.target.linux-arm.mk b/webkit/child/webkit_child.target.linux-arm.mk
index 5136aa5..2bfa6e8 100644
--- a/webkit/child/webkit_child.target.linux-arm.mk
+++ b/webkit/child/webkit_child.target.linux-arm.mk
@@ -30,8 +30,6 @@
 LOCAL_SRC_FILES := \
 	webkit/child/multipart_response_delegate.cc \
 	webkit/child/resource_loader_bridge.cc \
-	webkit/child/touch_fling_gesture_curve.cc \
-	webkit/child/weburlrequest_extradata_impl.cc \
 	webkit/child/weburlresponse_extradata_impl.cc
 
 
@@ -96,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +107,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -236,9 +233,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -251,6 +246,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/webkit_child.target.linux-mips.mk b/webkit/child/webkit_child.target.linux-mips.mk
index b559b24..bbadba4 100644
--- a/webkit/child/webkit_child.target.linux-mips.mk
+++ b/webkit/child/webkit_child.target.linux-mips.mk
@@ -30,8 +30,6 @@
 LOCAL_SRC_FILES := \
 	webkit/child/multipart_response_delegate.cc \
 	webkit/child/resource_loader_bridge.cc \
-	webkit/child/touch_fling_gesture_curve.cc \
-	webkit/child/weburlrequest_extradata_impl.cc \
 	webkit/child/weburlresponse_extradata_impl.cc
 
 
@@ -95,9 +93,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -110,6 +106,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -234,9 +231,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -249,6 +244,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/webkit_child.target.linux-x86.mk b/webkit/child/webkit_child.target.linux-x86.mk
index 0128980..7b0ff7b 100644
--- a/webkit/child/webkit_child.target.linux-x86.mk
+++ b/webkit/child/webkit_child.target.linux-x86.mk
@@ -30,8 +30,6 @@
 LOCAL_SRC_FILES := \
 	webkit/child/multipart_response_delegate.cc \
 	webkit/child/resource_loader_bridge.cc \
-	webkit/child/touch_fling_gesture_curve.cc \
-	webkit/child/weburlrequest_extradata_impl.cc \
 	webkit/child/weburlresponse_extradata_impl.cc
 
 
@@ -96,9 +94,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -111,6 +107,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -235,9 +232,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -250,6 +245,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/child/webkit_child.target.linux-x86_64.mk b/webkit/child/webkit_child.target.linux-x86_64.mk
new file mode 100644
index 0000000..63eefd3
--- /dev/null
+++ b/webkit/child/webkit_child.target.linux-x86_64.mk
@@ -0,0 +1,375 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_child_webkit_child_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,GYP,v8_tools_gyp_v8_gyp)/v8.stamp \
+	$(call intermediates-dir-for,GYP,webkit_child_overscroller_jni_headers_gyp)/overscroller_jni_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/child/multipart_response_delegate.cc \
+	webkit/child/resource_loader_bridge.cc \
+	webkit/child/weburlresponse_extradata_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_CHILD_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_CHILD_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_child_webkit_child_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_child
+webkit_child: webkit_child_webkit_child_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/child/weburlrequest_extradata_impl.cc b/webkit/child/weburlrequest_extradata_impl.cc
deleted file mode 100644
index 8eed5e1..0000000
--- a/webkit/child/weburlrequest_extradata_impl.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "webkit/child/weburlrequest_extradata_impl.h"
-
-using blink::WebString;
-
-namespace webkit_glue {
-
-WebURLRequestExtraDataImpl::WebURLRequestExtraDataImpl(
-    const WebString& custom_user_agent,
-    bool was_after_preconnect_request)
-    : custom_user_agent_(custom_user_agent),
-      was_after_preconnect_request_(was_after_preconnect_request) {
-}
-
-WebURLRequestExtraDataImpl::~WebURLRequestExtraDataImpl() {
-}
-
-}  // namespace webkit_glue
diff --git a/webkit/child/weburlrequest_extradata_impl.h b/webkit/child/weburlrequest_extradata_impl.h
deleted file mode 100644
index 797a232..0000000
--- a/webkit/child/weburlrequest_extradata_impl.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef WEBKIT_CHILD_WEBURLREQUEST_EXTRADATA_IMPL_H_
-#define WEBKIT_CHILD_WEBURLREQUEST_EXTRADATA_IMPL_H_
-
-#include "base/compiler_specific.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "webkit/child/webkit_child_export.h"
-
-namespace webkit_glue {
-
-// Base class for Chrome's implementation of the "extra data" stored in each
-// ResourceRequest.
-class WEBKIT_CHILD_EXPORT WebURLRequestExtraDataImpl :
-    public NON_EXPORTED_BASE(blink::WebURLRequest::ExtraData) {
- public:
-  // |custom_user_agent| is used to communicate an overriding custom user agent
-  // to |RenderViewImpl::willSendRequest()|; set to a null string to indicate no
-  // override and an empty string to indicate that there should be no user
-  // agent. This needs to be here, instead of content's |RequestExtraData| since
-  // ppb_url_request_info_impl.cc needs to be able to set it.
-  explicit WebURLRequestExtraDataImpl(
-      const blink::WebString& custom_user_agent,
-      bool was_after_preconnect_request);
-  virtual ~WebURLRequestExtraDataImpl();
-
-  const blink::WebString& custom_user_agent() const {
-    return custom_user_agent_;
-  }
-  bool was_after_preconnect_request() { return was_after_preconnect_request_; }
-
- private:
-  blink::WebString custom_user_agent_;
-  bool was_after_preconnect_request_;
-
-  DISALLOW_COPY_AND_ASSIGN(WebURLRequestExtraDataImpl);
-};
-
-}  // namespace webkit_glue
-
-#endif  // WEBKIT_CHILD_WEBURLREQUEST_EXTRADATA_IMPL_H_
diff --git a/webkit/common/fileapi/file_system_types.h b/webkit/common/fileapi/file_system_types.h
index 48c7795..c24d8d3 100644
--- a/webkit/common/fileapi/file_system_types.h
+++ b/webkit/common/fileapi/file_system_types.h
@@ -119,6 +119,9 @@
   // A filesystem that is mounted via the Privet storage protocol.
   kFileSystemTypeCloudDevice,
 
+  // A filesystem that is mounted via the FileSystemProvider API.
+  kFileSystemTypeProvided,
+
   // --------------------------------------------------------------------
   // Marks the end of internal type enum. (This is not the actual fs type)
   // New internal filesystem types must be added above this line.
diff --git a/webkit/common/fileapi/file_system_util.cc b/webkit/common/fileapi/file_system_util.cc
index 61cbcdf..84c59b2 100644
--- a/webkit/common/fileapi/file_system_util.cc
+++ b/webkit/common/fileapi/file_system_util.cc
@@ -317,6 +317,8 @@
       return "PluginPrivate";
     case kFileSystemTypeCloudDevice:
       return "CloudDevice";
+    case kFileSystemTypeProvided:
+      return "Provided";
     case kFileSystemInternalTypeEnumStart:
     case kFileSystemInternalTypeEnumEnd:
       NOTREACHED();
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk b/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
index f821d89..ae8234e 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-arm.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk b/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
index cff7db8..998a23a 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk b/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
index 18926fa..280ecab 100644
--- a/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-x86.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -237,6 +234,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/webkit/common/gpu/webkit_gpu.target.darwin-x86_64.mk b/webkit/common/gpu/webkit_gpu.target.darwin-x86_64.mk
new file mode 100644
index 0000000..938a6ae
--- /dev/null
+++ b/webkit/common/gpu/webkit_gpu.target.darwin-x86_64.mk
@@ -0,0 +1,350 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_common_gpu_webkit_gpu_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_minimal_gyp)/blink_minimal.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/common/gpu/context_provider_in_process.cc \
+	webkit/common/gpu/grcontext_for_webgraphicscontext3d.cc \
+	webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_GPU_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_GPU_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_common_gpu_webkit_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_gpu
+webkit_gpu: webkit_common_gpu_webkit_gpu_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-arm.mk b/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
index f821d89..ae8234e 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-arm.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-mips.mk b/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
index cff7db8..998a23a 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -224,9 +223,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -236,6 +233,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-x86.mk b/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
index 18926fa..280ecab 100644
--- a/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
+++ b/webkit/common/gpu/webkit_gpu.target.linux-x86.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -109,6 +107,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
@@ -225,9 +224,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -237,6 +234,7 @@
 	'-DMESA_EGL_NO_X11_HEADERS' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-DANDROID' \
 	'-D__GNU_SOURCE=1' \
 	'-DUSE_STLPORT=1' \
diff --git a/webkit/common/gpu/webkit_gpu.target.linux-x86_64.mk b/webkit/common/gpu/webkit_gpu.target.linux-x86_64.mk
new file mode 100644
index 0000000..938a6ae
--- /dev/null
+++ b/webkit/common/gpu/webkit_gpu.target.linux-x86_64.mk
@@ -0,0 +1,350 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_common_gpu_webkit_gpu_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_minimal_gyp)/blink_minimal.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_gl_gl_gyp)/ui_gl_gl_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/common/gpu/context_provider_in_process.cc \
+	webkit/common/gpu/grcontext_for_webgraphicscontext3d.cc \
+	webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_GPU_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-Wno-unknown-pragmas \
+	-Wno-format \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Wno-address \
+	-Wno-format-security \
+	-Wno-return-type \
+	-Wno-sequence-point \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_GPU_IMPLEMENTATION' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DMESA_EGL_NO_X11_HEADERS' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(gyp_shared_intermediate_dir)/ui/gl \
+	$(LOCAL_PATH)/third_party/mesa/src/include \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wno-deprecated \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo \
+	-Wno-non-virtual-dtor
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_gl_gl_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_common_gpu_webkit_gpu_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_gpu
+webkit_gpu: webkit_common_gpu_webkit_gpu_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/common/quota/quota_types.h b/webkit/common/quota/quota_types.h
index 6cb45c9..bc8cd00 100644
--- a/webkit/common/quota/quota_types.h
+++ b/webkit/common/quota/quota_types.h
@@ -15,6 +15,7 @@
   kStorageTypeSyncable,
   kStorageTypeQuotaNotManaged,
   kStorageTypeUnknown,
+  kStorageTypeLast = kStorageTypeUnknown
 };
 
 enum QuotaLimitType {
diff --git a/webkit/common/webkit_common.target.darwin-arm.mk b/webkit/common/webkit_common.target.darwin-arm.mk
index 393acbc..533fa10 100644
--- a/webkit/common/webkit_common.target.darwin-arm.mk
+++ b/webkit/common/webkit_common.target.darwin-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +230,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/common/webkit_common.target.darwin-mips.mk b/webkit/common/webkit_common.target.darwin-mips.mk
index a0b1a1d..62c6ead 100644
--- a/webkit/common/webkit_common.target.darwin-mips.mk
+++ b/webkit/common/webkit_common.target.darwin-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/common/webkit_common.target.darwin-x86.mk b/webkit/common/webkit_common.target.darwin-x86.mk
index d7e9756..7c3d057 100644
--- a/webkit/common/webkit_common.target.darwin-x86.mk
+++ b/webkit/common/webkit_common.target.darwin-x86.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/common/webkit_common.target.darwin-x86_64.mk b/webkit/common/webkit_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..9a6699f
--- /dev/null
+++ b/webkit/common/webkit_common.target.darwin-x86_64.mk
@@ -0,0 +1,349 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_common_webkit_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/common/data_element.cc \
+	webkit/common/resource_devtools_info.cc \
+	webkit/common/resource_response_info.cc \
+	webkit/common/resource_type.cc \
+	webkit/common/webpreferences.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_common_webkit_common_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_common
+webkit_common: webkit_common_webkit_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/common/webkit_common.target.linux-arm.mk b/webkit/common/webkit_common.target.linux-arm.mk
index 393acbc..533fa10 100644
--- a/webkit/common/webkit_common.target.linux-arm.mk
+++ b/webkit/common/webkit_common.target.linux-arm.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -222,9 +221,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -233,6 +230,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/common/webkit_common.target.linux-mips.mk b/webkit/common/webkit_common.target.linux-mips.mk
index a0b1a1d..62c6ead 100644
--- a/webkit/common/webkit_common.target.linux-mips.mk
+++ b/webkit/common/webkit_common.target.linux-mips.mk
@@ -96,9 +96,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -107,6 +105,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -220,9 +219,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -231,6 +228,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/common/webkit_common.target.linux-x86.mk b/webkit/common/webkit_common.target.linux-x86.mk
index d7e9756..7c3d057 100644
--- a/webkit/common/webkit_common.target.linux-x86.mk
+++ b/webkit/common/webkit_common.target.linux-x86.mk
@@ -97,9 +97,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -108,6 +106,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -221,9 +220,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -232,6 +229,7 @@
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DU_USING_ICU_NAMESPACE=0' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/common/webkit_common.target.linux-x86_64.mk b/webkit/common/webkit_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..9a6699f
--- /dev/null
+++ b/webkit/common/webkit_common.target.linux-x86_64.mk
@@ -0,0 +1,349 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_common_webkit_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,ui_base_ui_base_gyp)/ui_base_ui_base_gyp.a \
+	$(call intermediates-dir-for,GYP,ui_resources_ui_resources_gyp)/ui_resources.stamp \
+	$(call intermediates-dir-for,GYP,webkit_webkit_resources_gyp)/webkit_resources.stamp \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_headers_gyp)/blink_headers.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/common/data_element.cc \
+	webkit/common/resource_devtools_info.cc \
+	webkit/common/resource_response_info.cc \
+	webkit/common/resource_type.cc \
+	webkit/common/webpreferences.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_intermediate_dir) \
+	$(gyp_shared_intermediate_dir)/ui \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(gyp_shared_intermediate_dir)/ui/ui_resources \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp \
+	ui_base_ui_base_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_common_webkit_common_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_common
+webkit_common: webkit_common_webkit_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/common/webpreferences.cc b/webkit/common/webpreferences.cc
index c6a430e..d27d490 100644
--- a/webkit/common/webpreferences.cc
+++ b/webkit/common/webpreferences.cc
@@ -131,7 +131,6 @@
       force_enable_zoom(false),
       double_tap_to_zoom_enabled(true),
       user_gesture_required_for_media_playback(true),
-      user_gesture_required_for_media_fullscreen(true),
       support_deprecated_target_density_dpi(false),
       use_legacy_background_size_shorthand_behavior(false),
       wide_viewport_quirk(false),
diff --git a/webkit/common/webpreferences.h b/webkit/common/webpreferences.h
index 8c04328..4af2f8e 100644
--- a/webkit/common/webpreferences.h
+++ b/webkit/common/webpreferences.h
@@ -175,7 +175,6 @@
   bool force_enable_zoom;
   bool double_tap_to_zoom_enabled;
   bool user_gesture_required_for_media_playback;
-  bool user_gesture_required_for_media_fullscreen;
   GURL default_video_poster_url;
   bool support_deprecated_target_density_dpi;
   bool use_legacy_background_size_shorthand_behavior;
diff --git a/webkit/renderer/compositor_bindings/web_content_layer_impl.cc b/webkit/renderer/compositor_bindings/web_content_layer_impl.cc
index 9ae09fe..95a4b7f 100644
--- a/webkit/renderer/compositor_bindings/web_content_layer_impl.cc
+++ b/webkit/renderer/compositor_bindings/web_content_layer_impl.cc
@@ -82,4 +82,6 @@
   layer_->invalidate();
 }
 
+bool WebContentLayerImpl::FillsBoundsCompletely() const { return false; }
+
 }  // namespace webkit
diff --git a/webkit/renderer/compositor_bindings/web_content_layer_impl.h b/webkit/renderer/compositor_bindings/web_content_layer_impl.h
index 5ff88a3..a6bb7d2 100644
--- a/webkit/renderer/compositor_bindings/web_content_layer_impl.h
+++ b/webkit/renderer/compositor_bindings/web_content_layer_impl.h
@@ -40,6 +40,7 @@
                              const gfx::Rect& clip,
                              gfx::RectF* opaque) OVERRIDE;
   virtual void DidChangeLayerCanUseLCDText() OVERRIDE;
+  virtual bool FillsBoundsCompletely() const OVERRIDE;
 
   scoped_ptr<WebLayerImpl> layer_;
   blink::WebContentLayerClient* client_;
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
index 698b119..c470611 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-arm.mk
@@ -109,9 +109,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -124,6 +122,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -247,9 +246,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -262,6 +259,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
index 694befe..ff6acb7 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-mips.mk
@@ -108,9 +108,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -123,6 +121,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -245,9 +244,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -260,6 +257,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
index 9b981ed..6b47e25 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -125,6 +123,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -248,9 +247,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -263,6 +260,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86_64.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86_64.mk
new file mode 100644
index 0000000..cab4eb0
--- /dev/null
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.darwin-x86_64.mk
@@ -0,0 +1,386 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,gpu_gpu_gyp)/gpu.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/renderer/compositor_bindings/scrollbar_impl.cc \
+	webkit/renderer/compositor_bindings/web_animation_curve_common.cc \
+	webkit/renderer/compositor_bindings/web_animation_impl.cc \
+	webkit/renderer/compositor_bindings/web_content_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_external_bitmap_impl.cc \
+	webkit/renderer/compositor_bindings/web_external_texture_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_filter_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_filter_operations_impl.cc \
+	webkit/renderer/compositor_bindings/web_float_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_image_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_layer_impl_fixed_bounds.cc \
+	webkit/renderer/compositor_bindings/web_nine_patch_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_scrollbar_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_solid_color_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.cc \
+	webkit/renderer/compositor_bindings/web_transform_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_transform_operations_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMPOSITOR_BINDINGS_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMPOSITOR_BINDINGS_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_compositor_bindings
+webkit_compositor_bindings: webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
index 698b119..c470611 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-arm.mk
@@ -109,9 +109,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -124,6 +122,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -247,9 +246,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -262,6 +259,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
index 694befe..ff6acb7 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-mips.mk
@@ -108,9 +108,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -123,6 +121,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -245,9 +244,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -260,6 +257,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
index 9b981ed..6b47e25 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86.mk
@@ -110,9 +110,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -125,6 +123,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -248,9 +247,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -263,6 +260,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86_64.mk b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86_64.mk
new file mode 100644
index 0000000..cab4eb0
--- /dev/null
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_bindings.target.linux-x86_64.mk
@@ -0,0 +1,386 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,gpu_gpu_gyp)/gpu.stamp \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/renderer/compositor_bindings/scrollbar_impl.cc \
+	webkit/renderer/compositor_bindings/web_animation_curve_common.cc \
+	webkit/renderer/compositor_bindings/web_animation_impl.cc \
+	webkit/renderer/compositor_bindings/web_content_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_external_bitmap_impl.cc \
+	webkit/renderer/compositor_bindings/web_external_texture_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_filter_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_filter_operations_impl.cc \
+	webkit/renderer/compositor_bindings/web_float_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_image_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_layer_impl_fixed_bounds.cc \
+	webkit/renderer/compositor_bindings/web_nine_patch_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_scroll_offset_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_scrollbar_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_solid_color_layer_impl.cc \
+	webkit/renderer/compositor_bindings/web_to_cc_animation_delegate_adapter.cc \
+	webkit/renderer/compositor_bindings/web_transform_animation_curve_impl.cc \
+	webkit/renderer/compositor_bindings/web_transform_operations_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMPOSITOR_BINDINGS_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_COMPOSITOR_BINDINGS_IMPLEMENTATION=1' \
+	'-DMEDIA_DISABLE_LIBVPX' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_compositor_bindings
+webkit_compositor_bindings: webkit_renderer_compositor_bindings_webkit_compositor_bindings_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
index 4294c15..d18dd01 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -97,6 +95,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -207,9 +206,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -217,6 +214,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
index 1ecd03d..e3b008a 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -96,6 +94,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -205,9 +204,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -215,6 +212,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
index e654ce8..f3570c5 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -98,6 +96,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -208,9 +207,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -218,6 +215,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86_64.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86_64.mk
new file mode 100644
index 0000000..ca4e82a
--- /dev/null
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.darwin-x86_64.mk
@@ -0,0 +1,330 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_renderer_compositor_bindings_webkit_compositor_support_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/renderer/compositor_bindings/web_compositor_support_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/webkit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/webkit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_renderer_compositor_bindings_webkit_compositor_support_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_compositor_support
+webkit_compositor_support: webkit_renderer_compositor_bindings_webkit_compositor_support_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
index 4294c15..d18dd01 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-arm.mk
@@ -87,9 +87,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -97,6 +95,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -207,9 +206,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -217,6 +214,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
index 1ecd03d..e3b008a 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-mips.mk
@@ -86,9 +86,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -96,6 +94,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -205,9 +204,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -215,6 +212,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
index e654ce8..f3570c5 100644
--- a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86.mk
@@ -88,9 +88,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -98,6 +96,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -208,9 +207,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -218,6 +215,7 @@
 	'-DSK_USE_POSIX_THREADS' \
 	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86_64.mk b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86_64.mk
new file mode 100644
index 0000000..ca4e82a
--- /dev/null
+++ b/webkit/renderer/compositor_bindings/webkit_compositor_support.target.linux-x86_64.mk
@@ -0,0 +1,330 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_renderer_compositor_bindings_webkit_compositor_support_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,skia_skia_gyp)/skia.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/renderer/compositor_bindings/web_compositor_support_impl.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/webkit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(LOCAL_PATH)/webkit \
+	$(gyp_shared_intermediate_dir)/webkit \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_renderer_compositor_bindings_webkit_compositor_support_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_compositor_support
+webkit_compositor_support: webkit_renderer_compositor_bindings_webkit_compositor_support_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/webkit_resources.target.darwin-x86.mk b/webkit/webkit_resources.target.darwin-x86.mk
index 28c97c3..4ebd3d9 100644
--- a/webkit/webkit_resources.target.darwin-x86.mk
+++ b/webkit/webkit_resources.target.darwin-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/resources/webkit_resources.grd $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_recording.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_waiting.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_overlay_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel_pressed.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier_results.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/synthetic_touch_cursor.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/textarea_resize_corner.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/textarea_resize_corner.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from glue/resources/webkit_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/resources/webkit_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/resources/webkit_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/webkit_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
@@ -32,7 +32,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: $(LOCAL_PATH)/third_party/WebKit/Source/platform/audio/resources/Composite.wav $(LOCAL_PATH)/third_party/WebKit/public/blink_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../third_party/WebKit/public/blink_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i ../third_party/WebKit/public/blink_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i ../third_party/WebKit/public/blink_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/blink_resources.rc: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/blink_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
diff --git a/webkit/webkit_resources.target.darwin-x86_64.mk b/webkit/webkit_resources.target.darwin-x86_64.mk
new file mode 100644
index 0000000..4ebd3d9
--- /dev/null
+++ b/webkit/webkit_resources.target.darwin-x86_64.mk
@@ -0,0 +1,69 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := webkit_webkit_resources_gyp
+LOCAL_MODULE_STEM := webkit_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "webkit_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/resources/webkit_resources.grd $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_recording.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_waiting.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_overlay_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel_pressed.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier_results.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/synthetic_touch_cursor.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/textarea_resize_corner.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/textarea_resize_corner.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from glue/resources/webkit_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/resources/webkit_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
+
+### Rules for action "blink_chromium_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: $(LOCAL_PATH)/third_party/WebKit/Source/platform/audio/resources/Composite.wav $(LOCAL_PATH)/third_party/WebKit/public/blink_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ../third_party/WebKit/public/blink_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i ../third_party/WebKit/public/blink_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/blink_resources.rc: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/blink_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_resources_200_percent.pak \
+	$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/blink_resources.rc \
+	$(gyp_shared_intermediate_dir)/webkit/blink_resources.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_resources_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_resources
+webkit_resources: webkit_webkit_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/webkit/webkit_resources.target.linux-x86.mk b/webkit/webkit_resources.target.linux-x86.mk
index 28c97c3..4ebd3d9 100644
--- a/webkit/webkit_resources.target.linux-x86.mk
+++ b/webkit/webkit_resources.target.linux-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/resources/webkit_resources.grd $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_recording.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_waiting.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_overlay_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel_pressed.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier_results.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/synthetic_touch_cursor.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/textarea_resize_corner.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/textarea_resize_corner.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from glue/resources/webkit_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/resources/webkit_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/resources/webkit_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/webkit_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
@@ -32,7 +32,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: $(LOCAL_PATH)/third_party/WebKit/Source/platform/audio/resources/Composite.wav $(LOCAL_PATH)/third_party/WebKit/public/blink_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from ../third_party/WebKit/public/blink_resources.grd ($@)"
-	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i ../third_party/WebKit/public/blink_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i ../third_party/WebKit/public/blink_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/blink_resources.rc: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
 $(gyp_shared_intermediate_dir)/webkit/blink_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
diff --git a/webkit/webkit_resources.target.linux-x86_64.mk b/webkit/webkit_resources.target.linux-x86_64.mk
new file mode 100644
index 0000000..4ebd3d9
--- /dev/null
+++ b/webkit/webkit_resources.target.linux-x86_64.mk
@@ -0,0 +1,69 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := webkit_webkit_resources_gyp
+LOCAL_MODULE_STEM := webkit_resources
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "webkit_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/resources/webkit_resources.grd $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_recording.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/input_speech_waiting.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_closedcaption_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_fullscreen_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_overlay_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_pause_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_play_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level0_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level1_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level2_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_sound_level3_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_disabled.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_down.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/mediaplayer_volume_slider_thumb_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/password_generation_hover.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_cancel_pressed.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/search_magnifier_results.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/synthetic_touch_cursor.png $(LOCAL_PATH)/webkit/glue/resources/default_100_percent/textarea_resize_corner.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/broken_image.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/pan_icon.png $(LOCAL_PATH)/webkit/glue/resources/default_200_percent/textarea_resize_corner.png $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from glue/resources/webkit_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/resources/webkit_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_resources_200_percent.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h ;
+
+### Rules for action "blink_chromium_resources":
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h: $(LOCAL_PATH)/third_party/WebKit/Source/platform/audio/resources/Composite.wav $(LOCAL_PATH)/third_party/WebKit/public/blink_resources.grd $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from ../third_party/WebKit/public/blink_resources.grd ($@)"
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i ../third_party/WebKit/public/blink_resources.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/blink_resources.rc: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
+$(gyp_shared_intermediate_dir)/webkit/blink_resources.pak: $(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/webkit_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_resources_100_percent.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_resources_200_percent.pak \
+	$(gyp_shared_intermediate_dir)/webkit/grit/blink_resources.h \
+	$(gyp_shared_intermediate_dir)/webkit/blink_resources.rc \
+	$(gyp_shared_intermediate_dir)/webkit/blink_resources.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_resources_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_resources
+webkit_resources: webkit_webkit_resources_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/webkit/webkit_storage_browser.target.darwin-arm.mk b/webkit/webkit_storage_browser.target.darwin-arm.mk
index 619bb29..40d1225 100644
--- a/webkit/webkit_storage_browser.target.darwin-arm.mk
+++ b/webkit/webkit_storage_browser.target.darwin-arm.mk
@@ -172,9 +172,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -187,6 +185,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -316,9 +315,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -331,6 +328,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_browser.target.darwin-mips.mk b/webkit/webkit_storage_browser.target.darwin-mips.mk
index 0121f55..004d73a 100644
--- a/webkit/webkit_storage_browser.target.darwin-mips.mk
+++ b/webkit/webkit_storage_browser.target.darwin-mips.mk
@@ -171,9 +171,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -186,6 +184,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -314,9 +313,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -329,6 +326,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_browser.target.darwin-x86.mk b/webkit/webkit_storage_browser.target.darwin-x86.mk
index 36c7130..8e2dc39 100644
--- a/webkit/webkit_storage_browser.target.darwin-x86.mk
+++ b/webkit/webkit_storage_browser.target.darwin-x86.mk
@@ -172,9 +172,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -187,6 +185,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -315,9 +314,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -330,6 +327,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_browser.target.darwin-x86_64.mk b/webkit/webkit_storage_browser.target.darwin-x86_64.mk
new file mode 100644
index 0000000..7f3d45f
--- /dev/null
+++ b/webkit/webkit_storage_browser.target.darwin-x86_64.mk
@@ -0,0 +1,460 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_webkit_storage_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/browser/appcache/appcache.cc \
+	webkit/browser/appcache/appcache_backend_impl.cc \
+	webkit/browser/appcache/appcache_database.cc \
+	webkit/browser/appcache/appcache_disk_cache.cc \
+	webkit/browser/appcache/appcache_group.cc \
+	webkit/browser/appcache/appcache_histograms.cc \
+	webkit/browser/appcache/appcache_host.cc \
+	webkit/browser/appcache/appcache_interceptor.cc \
+	webkit/browser/appcache/appcache_quota_client.cc \
+	webkit/browser/appcache/appcache_request_handler.cc \
+	webkit/browser/appcache/appcache_response.cc \
+	webkit/browser/appcache/appcache_service.cc \
+	webkit/browser/appcache/appcache_storage.cc \
+	webkit/browser/appcache/appcache_storage_impl.cc \
+	webkit/browser/appcache/appcache_working_set.cc \
+	webkit/browser/appcache/appcache_update_job.cc \
+	webkit/browser/appcache/appcache_url_request_job.cc \
+	webkit/browser/appcache/manifest_parser.cc \
+	webkit/browser/blob/blob_data_handle.cc \
+	webkit/browser/blob/blob_storage_context.cc \
+	webkit/browser/blob/blob_storage_host.cc \
+	webkit/browser/blob/blob_url_request_job.cc \
+	webkit/browser/blob/blob_url_request_job_factory.cc \
+	webkit/browser/blob/file_stream_reader.cc \
+	webkit/browser/blob/local_file_stream_reader.cc \
+	webkit/browser/blob/view_blob_internals_job.cc \
+	webkit/browser/database/database_quota_client.cc \
+	webkit/browser/database/database_tracker.cc \
+	webkit/browser/database/database_util.cc \
+	webkit/browser/database/databases_table.cc \
+	webkit/browser/database/vfs_backend.cc \
+	webkit/browser/fileapi/async_file_util_adapter.cc \
+	webkit/browser/fileapi/copy_or_move_operation_delegate.cc \
+	webkit/browser/fileapi/dragged_file_util.cc \
+	webkit/browser/fileapi/external_mount_points.cc \
+	webkit/browser/fileapi/file_system_context.cc \
+	webkit/browser/fileapi/file_system_dir_url_request_job.cc \
+	webkit/browser/fileapi/file_system_file_stream_reader.cc \
+	webkit/browser/fileapi/file_system_file_util.cc \
+	webkit/browser/fileapi/file_system_operation_context.cc \
+	webkit/browser/fileapi/file_system_operation_impl.cc \
+	webkit/browser/fileapi/file_system_operation_runner.cc \
+	webkit/browser/fileapi/file_system_options.cc \
+	webkit/browser/fileapi/file_system_quota_client.cc \
+	webkit/browser/fileapi/file_system_url.cc \
+	webkit/browser/fileapi/file_system_url_request_job.cc \
+	webkit/browser/fileapi/file_system_url_request_job_factory.cc \
+	webkit/browser/fileapi/file_system_usage_cache.cc \
+	webkit/browser/fileapi/file_writer_delegate.cc \
+	webkit/browser/fileapi/isolated_context.cc \
+	webkit/browser/fileapi/isolated_file_system_backend.cc \
+	webkit/browser/fileapi/local_file_stream_writer.cc \
+	webkit/browser/fileapi/local_file_util.cc \
+	webkit/browser/fileapi/mount_points.cc \
+	webkit/browser/fileapi/native_file_util.cc \
+	webkit/browser/fileapi/obfuscated_file_util.cc \
+	webkit/browser/fileapi/plugin_private_file_system_backend.cc \
+	webkit/browser/fileapi/quota/open_file_handle.cc \
+	webkit/browser/fileapi/quota/open_file_handle_context.cc \
+	webkit/browser/fileapi/quota/quota_backend_impl.cc \
+	webkit/browser/fileapi/quota/quota_reservation.cc \
+	webkit/browser/fileapi/quota/quota_reservation_buffer.cc \
+	webkit/browser/fileapi/quota/quota_reservation_manager.cc \
+	webkit/browser/fileapi/recursive_operation_delegate.cc \
+	webkit/browser/fileapi/remove_operation_delegate.cc \
+	webkit/browser/fileapi/sandbox_directory_database.cc \
+	webkit/browser/fileapi/sandbox_file_stream_writer.cc \
+	webkit/browser/fileapi/sandbox_file_system_backend.cc \
+	webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc \
+	webkit/browser/fileapi/sandbox_isolated_origin_database.cc \
+	webkit/browser/fileapi/sandbox_origin_database.cc \
+	webkit/browser/fileapi/sandbox_origin_database_interface.cc \
+	webkit/browser/fileapi/sandbox_prioritized_origin_database.cc \
+	webkit/browser/fileapi/sandbox_quota_observer.cc \
+	webkit/browser/fileapi/timed_task_helper.cc \
+	webkit/browser/fileapi/transient_file_util.cc \
+	webkit/browser/quota/quota_database.cc \
+	webkit/browser/quota/quota_manager.cc \
+	webkit/browser/quota/quota_manager_proxy.cc \
+	webkit/browser/quota/quota_task.cc \
+	webkit/browser/quota/quota_temporary_storage_evictor.cc \
+	webkit/browser/quota/special_storage_policy.cc \
+	webkit/browser/quota/usage_tracker.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_BROWSER_IMPLEMENTATION' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_BROWSER_IMPLEMENTATION' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_storage_browser_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_storage_browser
+webkit_storage_browser: webkit_webkit_storage_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/webkit_storage_browser.target.linux-arm.mk b/webkit/webkit_storage_browser.target.linux-arm.mk
index 619bb29..40d1225 100644
--- a/webkit/webkit_storage_browser.target.linux-arm.mk
+++ b/webkit/webkit_storage_browser.target.linux-arm.mk
@@ -172,9 +172,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -187,6 +185,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -316,9 +315,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -331,6 +328,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_browser.target.linux-mips.mk b/webkit/webkit_storage_browser.target.linux-mips.mk
index 0121f55..004d73a 100644
--- a/webkit/webkit_storage_browser.target.linux-mips.mk
+++ b/webkit/webkit_storage_browser.target.linux-mips.mk
@@ -171,9 +171,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -186,6 +184,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -314,9 +313,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -329,6 +326,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_browser.target.linux-x86.mk b/webkit/webkit_storage_browser.target.linux-x86.mk
index 36c7130..8e2dc39 100644
--- a/webkit/webkit_storage_browser.target.linux-x86.mk
+++ b/webkit/webkit_storage_browser.target.linux-x86.mk
@@ -172,9 +172,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -187,6 +185,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -315,9 +314,7 @@
 	'-DGR_GL_IGNORE_ES3_MSAA=0' \
 	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
 	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
-	'-DSK_SUPPORT_LEGACY_COMPATIBLEDEVICE_CONFIG=1' \
 	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
-	'-DSK_SUPPORT_LEGACY_READPIXELSCONFIG' \
 	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
 	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
 	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
@@ -330,6 +327,7 @@
 	'-DCHROME_PNG_READ_PACK_SUPPORT' \
 	'-DUSE_SYSTEM_LIBJPEG' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_browser.target.linux-x86_64.mk b/webkit/webkit_storage_browser.target.linux-x86_64.mk
new file mode 100644
index 0000000..7f3d45f
--- /dev/null
+++ b/webkit/webkit_storage_browser.target.linux-x86_64.mk
@@ -0,0 +1,460 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_webkit_storage_browser_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES := \
+	$(call intermediates-dir-for,GYP,third_party_WebKit_public_blink_gyp)/blink.stamp \
+	$(call intermediates-dir-for,STATIC_LIBRARIES,skia_skia_library_gyp)/skia_skia_library_gyp.a
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/browser/appcache/appcache.cc \
+	webkit/browser/appcache/appcache_backend_impl.cc \
+	webkit/browser/appcache/appcache_database.cc \
+	webkit/browser/appcache/appcache_disk_cache.cc \
+	webkit/browser/appcache/appcache_group.cc \
+	webkit/browser/appcache/appcache_histograms.cc \
+	webkit/browser/appcache/appcache_host.cc \
+	webkit/browser/appcache/appcache_interceptor.cc \
+	webkit/browser/appcache/appcache_quota_client.cc \
+	webkit/browser/appcache/appcache_request_handler.cc \
+	webkit/browser/appcache/appcache_response.cc \
+	webkit/browser/appcache/appcache_service.cc \
+	webkit/browser/appcache/appcache_storage.cc \
+	webkit/browser/appcache/appcache_storage_impl.cc \
+	webkit/browser/appcache/appcache_working_set.cc \
+	webkit/browser/appcache/appcache_update_job.cc \
+	webkit/browser/appcache/appcache_url_request_job.cc \
+	webkit/browser/appcache/manifest_parser.cc \
+	webkit/browser/blob/blob_data_handle.cc \
+	webkit/browser/blob/blob_storage_context.cc \
+	webkit/browser/blob/blob_storage_host.cc \
+	webkit/browser/blob/blob_url_request_job.cc \
+	webkit/browser/blob/blob_url_request_job_factory.cc \
+	webkit/browser/blob/file_stream_reader.cc \
+	webkit/browser/blob/local_file_stream_reader.cc \
+	webkit/browser/blob/view_blob_internals_job.cc \
+	webkit/browser/database/database_quota_client.cc \
+	webkit/browser/database/database_tracker.cc \
+	webkit/browser/database/database_util.cc \
+	webkit/browser/database/databases_table.cc \
+	webkit/browser/database/vfs_backend.cc \
+	webkit/browser/fileapi/async_file_util_adapter.cc \
+	webkit/browser/fileapi/copy_or_move_operation_delegate.cc \
+	webkit/browser/fileapi/dragged_file_util.cc \
+	webkit/browser/fileapi/external_mount_points.cc \
+	webkit/browser/fileapi/file_system_context.cc \
+	webkit/browser/fileapi/file_system_dir_url_request_job.cc \
+	webkit/browser/fileapi/file_system_file_stream_reader.cc \
+	webkit/browser/fileapi/file_system_file_util.cc \
+	webkit/browser/fileapi/file_system_operation_context.cc \
+	webkit/browser/fileapi/file_system_operation_impl.cc \
+	webkit/browser/fileapi/file_system_operation_runner.cc \
+	webkit/browser/fileapi/file_system_options.cc \
+	webkit/browser/fileapi/file_system_quota_client.cc \
+	webkit/browser/fileapi/file_system_url.cc \
+	webkit/browser/fileapi/file_system_url_request_job.cc \
+	webkit/browser/fileapi/file_system_url_request_job_factory.cc \
+	webkit/browser/fileapi/file_system_usage_cache.cc \
+	webkit/browser/fileapi/file_writer_delegate.cc \
+	webkit/browser/fileapi/isolated_context.cc \
+	webkit/browser/fileapi/isolated_file_system_backend.cc \
+	webkit/browser/fileapi/local_file_stream_writer.cc \
+	webkit/browser/fileapi/local_file_util.cc \
+	webkit/browser/fileapi/mount_points.cc \
+	webkit/browser/fileapi/native_file_util.cc \
+	webkit/browser/fileapi/obfuscated_file_util.cc \
+	webkit/browser/fileapi/plugin_private_file_system_backend.cc \
+	webkit/browser/fileapi/quota/open_file_handle.cc \
+	webkit/browser/fileapi/quota/open_file_handle_context.cc \
+	webkit/browser/fileapi/quota/quota_backend_impl.cc \
+	webkit/browser/fileapi/quota/quota_reservation.cc \
+	webkit/browser/fileapi/quota/quota_reservation_buffer.cc \
+	webkit/browser/fileapi/quota/quota_reservation_manager.cc \
+	webkit/browser/fileapi/recursive_operation_delegate.cc \
+	webkit/browser/fileapi/remove_operation_delegate.cc \
+	webkit/browser/fileapi/sandbox_directory_database.cc \
+	webkit/browser/fileapi/sandbox_file_stream_writer.cc \
+	webkit/browser/fileapi/sandbox_file_system_backend.cc \
+	webkit/browser/fileapi/sandbox_file_system_backend_delegate.cc \
+	webkit/browser/fileapi/sandbox_isolated_origin_database.cc \
+	webkit/browser/fileapi/sandbox_origin_database.cc \
+	webkit/browser/fileapi/sandbox_origin_database_interface.cc \
+	webkit/browser/fileapi/sandbox_prioritized_origin_database.cc \
+	webkit/browser/fileapi/sandbox_quota_observer.cc \
+	webkit/browser/fileapi/timed_task_helper.cc \
+	webkit/browser/fileapi/transient_file_util.cc \
+	webkit/browser/quota/quota_database.cc \
+	webkit/browser/quota/quota_manager.cc \
+	webkit/browser/quota/quota_manager_proxy.cc \
+	webkit/browser/quota/quota_task.cc \
+	webkit/browser/quota/quota_temporary_storage_evictor.cc \
+	webkit/browser/quota/special_storage_policy.cc \
+	webkit/browser/quota/usage_tracker.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_BROWSER_IMPLEMENTATION' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_BROWSER_IMPLEMENTATION' \
+	'-DAPPCACHE_USE_SIMPLE_CACHE' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DSK_ENABLE_INST_COUNT=0' \
+	'-DSK_SUPPORT_GPU=1' \
+	'-DGR_GL_CUSTOM_SETUP_HEADER="GrGLConfig_chrome.h"' \
+	'-DSK_ENABLE_LEGACY_API_ALIASING=1' \
+	'-DSK_ATTR_DEPRECATED=SK_NOTHING_ARG1' \
+	'-DGR_GL_IGNORE_ES3_MSAA=0' \
+	'-DSK_SUPPORT_LEGACY_LAYERRASTERIZER_API=1' \
+	'-DSK_WILL_NEVER_DRAW_PERSPECTIVE_TEXT' \
+	'-DSK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1' \
+	'-DSK_SUPPORT_LEGACY_GETCLIPTYPE' \
+	'-DSK_SUPPORT_LEGACY_GETTOTALCLIP' \
+	'-DSK_SUPPORT_LEGACY_GETTOPDEVICE' \
+	'-DSK_BUILD_FOR_ANDROID' \
+	'-DSK_USE_POSIX_THREADS' \
+	'-DSK_DEFERRED_CANVAS_USES_FACTORIES=1' \
+	'-DU_USING_ICU_NAMESPACE=0' \
+	'-DCHROME_PNG_WRITE_SUPPORT' \
+	'-DPNG_USER_CONFIG' \
+	'-DCHROME_PNG_READ_PACK_SUPPORT' \
+	'-DUSE_SYSTEM_LIBJPEG' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit/Source \
+	$(LOCAL_PATH)/third_party/khronos \
+	$(LOCAL_PATH)/gpu \
+	$(LOCAL_PATH)/third_party/leveldatabase/src/include \
+	$(LOCAL_PATH)/third_party/leveldatabase/src \
+	$(LOCAL_PATH)/third_party/leveldatabase \
+	$(LOCAL_PATH)/third_party/sqlite \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(LOCAL_PATH)/third_party/skia/src/core \
+	$(LOCAL_PATH)/third_party/skia/include/core \
+	$(LOCAL_PATH)/third_party/skia/include/effects \
+	$(LOCAL_PATH)/third_party/skia/include/pdf \
+	$(LOCAL_PATH)/third_party/skia/include/gpu \
+	$(LOCAL_PATH)/third_party/skia/include/lazy \
+	$(LOCAL_PATH)/third_party/skia/include/pathops \
+	$(LOCAL_PATH)/third_party/skia/include/pipe \
+	$(LOCAL_PATH)/third_party/skia/include/ports \
+	$(LOCAL_PATH)/third_party/skia/include/utils \
+	$(LOCAL_PATH)/skia/ext \
+	$(PWD)/external/icu4c/common \
+	$(PWD)/external/icu4c/i18n \
+	$(LOCAL_PATH)/third_party/npapi \
+	$(LOCAL_PATH)/third_party/npapi/bindings \
+	$(LOCAL_PATH)/v8/include \
+	$(LOCAL_PATH)/third_party/libpng \
+	$(LOCAL_PATH)/third_party/zlib \
+	$(LOCAL_PATH)/third_party/libwebp \
+	$(LOCAL_PATH)/third_party/ots/include \
+	$(LOCAL_PATH)/third_party/qcms/src \
+	$(LOCAL_PATH)/third_party/iccjpeg \
+	$(PWD)/external/jpeg \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES := \
+	skia_skia_library_gyp
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_storage_browser_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_storage_browser
+webkit_storage_browser: webkit_webkit_storage_browser_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/webkit_storage_common.target.darwin-arm.mk b/webkit/webkit_storage_common.target.darwin-arm.mk
index 33d811d..adf03bc 100644
--- a/webkit/webkit_storage_common.target.darwin-arm.mk
+++ b/webkit/webkit_storage_common.target.darwin-arm.mk
@@ -89,6 +89,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_common.target.darwin-mips.mk b/webkit/webkit_storage_common.target.darwin-mips.mk
index beee46e..22e3afc 100644
--- a/webkit/webkit_storage_common.target.darwin-mips.mk
+++ b/webkit/webkit_storage_common.target.darwin-mips.mk
@@ -88,6 +88,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_common.target.darwin-x86.mk b/webkit/webkit_storage_common.target.darwin-x86.mk
index 97f4321..d2c4afb 100644
--- a/webkit/webkit_storage_common.target.darwin-x86.mk
+++ b/webkit/webkit_storage_common.target.darwin-x86.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_common.target.darwin-x86_64.mk b/webkit/webkit_storage_common.target.darwin-x86_64.mk
new file mode 100644
index 0000000..57402f3
--- /dev/null
+++ b/webkit/webkit_storage_common.target.darwin-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_webkit_storage_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/common/appcache/appcache_interfaces.cc \
+	webkit/common/blob/blob_data.cc \
+	webkit/common/blob/scoped_file.cc \
+	webkit/common/blob/shareable_file_reference.cc \
+	webkit/common/database/database_connections.cc \
+	webkit/common/database/database_identifier.cc \
+	webkit/common/fileapi/directory_entry.cc \
+	webkit/common/fileapi/file_system_info.cc \
+	webkit/common/fileapi/file_system_util.cc \
+	webkit/common/quota/quota_status_code.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_storage_common_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_storage_common
+webkit_storage_common: webkit_webkit_storage_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/webkit_storage_common.target.linux-arm.mk b/webkit/webkit_storage_common.target.linux-arm.mk
index 33d811d..adf03bc 100644
--- a/webkit/webkit_storage_common.target.linux-arm.mk
+++ b/webkit/webkit_storage_common.target.linux-arm.mk
@@ -89,6 +89,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -179,6 +180,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_common.target.linux-mips.mk b/webkit/webkit_storage_common.target.linux-mips.mk
index beee46e..22e3afc 100644
--- a/webkit/webkit_storage_common.target.linux-mips.mk
+++ b/webkit/webkit_storage_common.target.linux-mips.mk
@@ -88,6 +88,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -177,6 +178,7 @@
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DPOSIX_AVOID_MMAP' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_common.target.linux-x86.mk b/webkit/webkit_storage_common.target.linux-x86.mk
index 97f4321..d2c4afb 100644
--- a/webkit/webkit_storage_common.target.linux-x86.mk
+++ b/webkit/webkit_storage_common.target.linux-x86.mk
@@ -89,6 +89,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
@@ -178,6 +179,7 @@
 	'-DENABLE_MANAGED_USERS=1' \
 	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
 	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
 	'-D__STDC_CONSTANT_MACROS' \
 	'-D__STDC_FORMAT_MACROS' \
 	'-DANDROID' \
diff --git a/webkit/webkit_storage_common.target.linux-x86_64.mk b/webkit/webkit_storage_common.target.linux-x86_64.mk
new file mode 100644
index 0000000..57402f3
--- /dev/null
+++ b/webkit/webkit_storage_common.target.linux-x86_64.mk
@@ -0,0 +1,280 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE := webkit_webkit_storage_common_gyp
+LOCAL_MODULE_SUFFIX := .a
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+GYP_GENERATED_OUTPUTS :=
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_GENERATED_SOURCES :=
+
+GYP_COPIED_SOURCE_ORIGIN_DIRS :=
+
+LOCAL_SRC_FILES := \
+	webkit/common/appcache/appcache_interfaces.cc \
+	webkit/common/blob/blob_data.cc \
+	webkit/common/blob/scoped_file.cc \
+	webkit/common/blob/shareable_file_reference.cc \
+	webkit/common/database/database_connections.cc \
+	webkit/common/database/database_identifier.cc \
+	webkit/common/fileapi/directory_entry.cc \
+	webkit/common/fileapi/file_system_info.cc \
+	webkit/common/fileapi/file_system_util.cc \
+	webkit/common/quota/quota_status_code.cc
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Debug := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-g \
+	-fomit-frame-pointer \
+	-fdata-sections \
+	-ffunction-sections \
+	-funwind-tables
+
+MY_DEFS_Debug := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=1' \
+	'-DWTF_USE_DYNAMIC_ANNOTATIONS=1' \
+	'-D_DEBUG'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Debug := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Debug := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+# Flags passed to both C and C++ files.
+MY_CFLAGS_Release := \
+	-fstack-protector \
+	--param=ssp-buffer-size=4 \
+	-Werror \
+	-fno-exceptions \
+	-fno-strict-aliasing \
+	-Wall \
+	-Wno-unused-parameter \
+	-Wno-missing-field-initializers \
+	-fvisibility=hidden \
+	-pipe \
+	-fPIC \
+	-Wno-unused-local-typedefs \
+	-m64 \
+	-march=x86-64 \
+	-fuse-ld=gold \
+	-ffunction-sections \
+	-funwind-tables \
+	-g \
+	-fstack-protector \
+	-fno-short-enums \
+	-finline-limit=64 \
+	-Wa,--noexecstack \
+	-U_FORTIFY_SOURCE \
+	-Wno-extra \
+	-Wno-ignored-qualifiers \
+	-Wno-type-limits \
+	-Wno-unused-but-set-variable \
+	-Os \
+	-fno-ident \
+	-fdata-sections \
+	-ffunction-sections \
+	-fomit-frame-pointer \
+	-funwind-tables
+
+MY_DEFS_Release := \
+	'-DV8_DEPRECATION_WARNINGS' \
+	'-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
+	'-D_FILE_OFFSET_BITS=64' \
+	'-DNO_TCMALLOC' \
+	'-DDISABLE_NACL' \
+	'-DCHROMIUM_BUILD' \
+	'-DUSE_LIBJPEG_TURBO=1' \
+	'-DUSE_PROPRIETARY_CODECS' \
+	'-DENABLE_CONFIGURATION_POLICY' \
+	'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
+	'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
+	'-DENABLE_EGLIMAGE=1' \
+	'-DCLD_VERSION=1' \
+	'-DENABLE_PRINTING=1' \
+	'-DENABLE_MANAGED_USERS=1' \
+	'-DWEBKIT_STORAGE_COMMON_IMPLEMENTATION' \
+	'-DPOSIX_AVOID_MMAP' \
+	'-DUSE_OPENSSL=1' \
+	'-DUSE_OPENSSL_CERTS=1' \
+	'-D__STDC_CONSTANT_MACROS' \
+	'-D__STDC_FORMAT_MACROS' \
+	'-DANDROID' \
+	'-D__GNU_SOURCE=1' \
+	'-DUSE_STLPORT=1' \
+	'-D_STLP_USE_PTR_SPECIALIZATIONS=1' \
+	'-DCHROME_BUILD_ID=""' \
+	'-DNDEBUG' \
+	'-DNVALGRIND' \
+	'-DDYNAMIC_ANNOTATIONS_ENABLED=0' \
+	'-D_FORTIFY_SOURCE=2'
+
+
+# Include paths placed before CFLAGS/CPPFLAGS
+LOCAL_C_INCLUDES_Release := \
+	$(gyp_shared_intermediate_dir)/shim_headers/icuuc/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/icui18n/target \
+	$(gyp_shared_intermediate_dir)/shim_headers/ashmem/target \
+	$(LOCAL_PATH) \
+	$(LOCAL_PATH)/skia/config \
+	$(LOCAL_PATH)/third_party/WebKit \
+	$(PWD)/frameworks/wilhelm/include \
+	$(PWD)/bionic \
+	$(PWD)/external/stlport/stlport
+
+
+# Flags passed to only C++ (and not C) files.
+LOCAL_CPPFLAGS_Release := \
+	-fno-rtti \
+	-fno-threadsafe-statics \
+	-fvisibility-inlines-hidden \
+	-Wsign-compare \
+	-Wno-non-virtual-dtor \
+	-Wno-sign-promo
+
+
+LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
+LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
+LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
+### Rules for final target.
+
+LOCAL_LDFLAGS_Debug := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel \
+	-Wl,-O1 \
+	-Wl,--as-needed
+
+
+LOCAL_LDFLAGS_Release := \
+	-Wl,--fatal-warnings \
+	-Wl,-z,now \
+	-Wl,-z,relro \
+	-Wl,-z,noexecstack \
+	-fPIC \
+	-m64 \
+	-fuse-ld=gold \
+	-nostdlib \
+	-Wl,--no-undefined \
+	-Wl,--exclude-libs=ALL \
+	-Wl,-O1 \
+	-Wl,--as-needed \
+	-Wl,--gc-sections \
+	-Wl,--warn-shared-textrel
+
+
+LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION))
+
+LOCAL_STATIC_LIBRARIES :=
+
+# Enable grouping to fix circular references
+LOCAL_GROUP_STATIC_LIBRARIES := true
+
+LOCAL_SHARED_LIBRARIES := \
+	libstlport \
+	libdl
+
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_storage_common_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_storage_common
+webkit_storage_common: webkit_webkit_storage_common_gyp
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/webkit/webkit_strings.target.darwin-x86.mk b/webkit/webkit_strings.target.darwin-x86.mk
index 6c6ad4d..1a0184b 100644
--- a/webkit/webkit_strings.target.darwin-x86.mk
+++ b/webkit/webkit_strings.target.darwin-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/webkit_strings.grd $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_am.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ar.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bg.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ca.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_cs.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_da.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_de.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_el.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_en-GB.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es-419.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_et.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fa.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fil.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_gu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_id.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_it.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_iw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ja.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_kn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ko.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lt.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ml.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_mr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ms.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_nl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_no.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-BR.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-PT.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ro.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ru.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ta.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_te.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_th.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_tr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_uk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_vi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-CN.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from glue/webkit_strings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/webkit_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/webkit_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.rc: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
 $(gyp_shared_intermediate_dir)/webkit/webkit_strings_am.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
diff --git a/webkit/webkit_strings.target.darwin-x86_64.mk b/webkit/webkit_strings.target.darwin-x86_64.mk
new file mode 100644
index 0000000..1a0184b
--- /dev/null
+++ b/webkit/webkit_strings.target.darwin-x86_64.mk
@@ -0,0 +1,160 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := webkit_webkit_strings_gyp
+LOCAL_MODULE_STEM := webkit_strings
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "webkit_strings":
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/webkit_strings.grd $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_am.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ar.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bg.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ca.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_cs.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_da.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_de.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_el.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_en-GB.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es-419.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_et.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fa.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fil.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_gu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_id.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_it.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_iw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ja.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_kn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ko.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lt.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ml.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_mr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ms.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_nl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_no.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-BR.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-PT.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ro.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ru.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ta.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_te.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_th.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_tr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_uk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_vi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-CN.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from glue/webkit_strings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/webkit_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.rc: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_am.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ar.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bg.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bn.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ca.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_cs.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_da.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_de.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_el.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-GB.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es-419.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_et.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fa.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fil.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_gu.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_he.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hu.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_id.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_it.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ja.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_kn.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ko.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lt.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lv.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ml.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_mr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ms.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nl.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nb.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pl.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-BR.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-PT.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ro.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ru.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sk.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sl.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sv.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sw.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ta.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_te.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_th.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_tr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_uk.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_vi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-CN.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-TW.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.rc \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_am.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ar.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bg.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bn.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ca.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_cs.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_da.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_de.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_el.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_et.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fa.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fil.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_gu.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_he.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hu.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_id.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_it.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ja.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_kn.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ko.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lt.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lv.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ml.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_mr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ms.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nl.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nb.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pl.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ro.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ru.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sk.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sl.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sv.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sw.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ta.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_te.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_th.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_tr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_uk.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_vi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-TW.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_strings_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_strings
+webkit_strings: webkit_webkit_strings_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/webkit/webkit_strings.target.linux-x86.mk b/webkit/webkit_strings.target.linux-x86.mk
index 6c6ad4d..1a0184b 100644
--- a/webkit/webkit_strings.target.linux-x86.mk
+++ b/webkit/webkit_strings.target.linux-x86.mk
@@ -20,7 +20,7 @@
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
 $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/webkit_strings.grd $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_am.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ar.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bg.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ca.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_cs.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_da.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_de.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_el.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_en-GB.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es-419.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_et.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fa.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fil.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_gu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_id.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_it.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_iw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ja.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_kn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ko.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lt.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ml.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_mr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ms.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_nl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_no.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-BR.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-PT.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ro.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ru.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ta.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_te.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_th.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_tr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_uk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_vi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-CN.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
 	@echo "Gyp action: Generating resources from glue/webkit_strings.grd ($@)"
-	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/webkit_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -D use_webaudio_enable_message -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/webkit_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
 
 $(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.rc: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
 $(gyp_shared_intermediate_dir)/webkit/webkit_strings_am.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
diff --git a/webkit/webkit_strings.target.linux-x86_64.mk b/webkit/webkit_strings.target.linux-x86_64.mk
new file mode 100644
index 0000000..1a0184b
--- /dev/null
+++ b/webkit/webkit_strings.target.linux-x86_64.mk
@@ -0,0 +1,160 @@
+# This file is generated by gyp; do not edit.
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_CLASS := GYP
+LOCAL_MODULE := webkit_webkit_strings_gyp
+LOCAL_MODULE_STEM := webkit_strings
+LOCAL_MODULE_SUFFIX := .stamp
+LOCAL_MODULE_TAGS := optional
+gyp_intermediate_dir := $(call local-intermediates-dir)
+gyp_shared_intermediate_dir := $(call intermediates-dir-for,GYP,shared)
+
+# Make sure our deps are built first.
+GYP_TARGET_DEPENDENCIES :=
+
+### Rules for action "webkit_strings":
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: gyp_local_path := $(LOCAL_PATH)
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: gyp_intermediate_dir := $(abspath $(gyp_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: gyp_shared_intermediate_dir := $(abspath $(gyp_shared_intermediate_dir))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))
+$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h: $(LOCAL_PATH)/tools/gritsettings/resource_ids $(LOCAL_PATH)/webkit/glue/webkit_strings.grd $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_am.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ar.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bg.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_bn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ca.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_cs.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_da.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_de.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_el.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_en-GB.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es-419.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_es.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_et.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fa.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fil.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_fr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_gu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_hu.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_id.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_it.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_iw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ja.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_kn.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ko.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lt.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_lv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ml.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_mr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ms.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_nl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_no.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-BR.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_pt-PT.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ro.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ru.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sl.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sv.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_sw.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_ta.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_te.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_th.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_tr.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_uk.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_vi.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-CN.xtb $(LOCAL_PATH)/webkit/glue/resources/webkit_strings_zh-TW.xtb $(LOCAL_PATH)/tools/grit/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit.py $(LOCAL_PATH)/tools/grit/grit/__init__.py $(LOCAL_PATH)/tools/grit/grit/clique.py $(LOCAL_PATH)/tools/grit/grit/constants.py $(LOCAL_PATH)/tools/grit/grit/exception.py $(LOCAL_PATH)/tools/grit/grit/extern/BogoFP.py $(LOCAL_PATH)/tools/grit/grit/extern/FP.py $(LOCAL_PATH)/tools/grit/grit/extern/__init__.py $(LOCAL_PATH)/tools/grit/grit/extern/tclib.py $(LOCAL_PATH)/tools/grit/grit/format/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/android_xml.py $(LOCAL_PATH)/tools/grit/grit/format/c_format.py $(LOCAL_PATH)/tools/grit/grit/format/chrome_messages_json.py $(LOCAL_PATH)/tools/grit/grit/format/data_pack.py $(LOCAL_PATH)/tools/grit/grit/format/html_inline.py $(LOCAL_PATH)/tools/grit/grit/format/js_map_format.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/PRESUBMIT.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/policy_template_generator.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/template_formatter.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writer_configuration.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/__init__.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adm_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/adml_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/admx_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/doc_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/json_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/mock_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_helper.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_strings_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/plist_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/reg_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/template_writer.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/writer_unittest_common.py $(LOCAL_PATH)/tools/grit/grit/format/policy_templates/writers/xml_formatted_writer.py $(LOCAL_PATH)/tools/grit/grit/format/rc.py $(LOCAL_PATH)/tools/grit/grit/format/rc_header.py $(LOCAL_PATH)/tools/grit/grit/format/repack.py $(LOCAL_PATH)/tools/grit/grit/format/resource_map.py $(LOCAL_PATH)/tools/grit/grit/gather/__init__.py $(LOCAL_PATH)/tools/grit/grit/gather/admin_template.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_html.py $(LOCAL_PATH)/tools/grit/grit/gather/chrome_scaled_image.py $(LOCAL_PATH)/tools/grit/grit/gather/igoogle_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/interface.py $(LOCAL_PATH)/tools/grit/grit/gather/json_loader.py $(LOCAL_PATH)/tools/grit/grit/gather/muppet_strings.py $(LOCAL_PATH)/tools/grit/grit/gather/policy_json.py $(LOCAL_PATH)/tools/grit/grit/gather/rc.py $(LOCAL_PATH)/tools/grit/grit/gather/regexp.py $(LOCAL_PATH)/tools/grit/grit/gather/skeleton_gatherer.py $(LOCAL_PATH)/tools/grit/grit/gather/tr_html.py $(LOCAL_PATH)/tools/grit/grit/gather/txt.py $(LOCAL_PATH)/tools/grit/grit/grd_reader.py $(LOCAL_PATH)/tools/grit/grit/grit_runner.py $(LOCAL_PATH)/tools/grit/grit/lazy_re.py $(LOCAL_PATH)/tools/grit/grit/node/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/base.py $(LOCAL_PATH)/tools/grit/grit/node/custom/__init__.py $(LOCAL_PATH)/tools/grit/grit/node/custom/filename.py $(LOCAL_PATH)/tools/grit/grit/node/empty.py $(LOCAL_PATH)/tools/grit/grit/node/include.py $(LOCAL_PATH)/tools/grit/grit/node/io.py $(LOCAL_PATH)/tools/grit/grit/node/mapping.py $(LOCAL_PATH)/tools/grit/grit/node/message.py $(LOCAL_PATH)/tools/grit/grit/node/misc.py $(LOCAL_PATH)/tools/grit/grit/node/structure.py $(LOCAL_PATH)/tools/grit/grit/node/variant.py $(LOCAL_PATH)/tools/grit/grit/pseudo.py $(LOCAL_PATH)/tools/grit/grit/pseudo_rtl.py $(LOCAL_PATH)/tools/grit/grit/scons.py $(LOCAL_PATH)/tools/grit/grit/shortcuts.py $(LOCAL_PATH)/tools/grit/grit/shortcuts_unittests.py $(LOCAL_PATH)/tools/grit/grit/tclib.py $(LOCAL_PATH)/tools/grit/grit/test_suite_all.py $(LOCAL_PATH)/tools/grit/grit/tool/__init__.py $(LOCAL_PATH)/tools/grit/grit/tool/android2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/build.py $(LOCAL_PATH)/tools/grit/grit/tool/buildinfo.py $(LOCAL_PATH)/tools/grit/grit/tool/count.py $(LOCAL_PATH)/tools/grit/grit/tool/diff_structures.py $(LOCAL_PATH)/tools/grit/grit/tool/interface.py $(LOCAL_PATH)/tools/grit/grit/tool/menu_from_parts.py $(LOCAL_PATH)/tools/grit/grit/tool/newgrd.py $(LOCAL_PATH)/tools/grit/grit/tool/postprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/preprocess_interface.py $(LOCAL_PATH)/tools/grit/grit/tool/rc2grd.py $(LOCAL_PATH)/tools/grit/grit/tool/resize.py $(LOCAL_PATH)/tools/grit/grit/tool/test.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_postprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/toolbar_preprocess.py $(LOCAL_PATH)/tools/grit/grit/tool/transl2tc.py $(LOCAL_PATH)/tools/grit/grit/tool/unit.py $(LOCAL_PATH)/tools/grit/grit/tool/xmb.py $(LOCAL_PATH)/tools/grit/grit/util.py $(LOCAL_PATH)/tools/grit/grit/xtb_reader.py $(LOCAL_PATH)/tools/grit/grit_info.py $(GYP_TARGET_DEPENDENCIES)
+	@echo "Gyp action: Generating resources from glue/webkit_strings.grd ($@)"
+	$(hide)cd $(gyp_local_path)/webkit; mkdir -p $(gyp_shared_intermediate_dir)/webkit/grit $(gyp_shared_intermediate_dir)/webkit; python ../tools/grit/grit.py -i glue/webkit_strings.grd build -f ../tools/gritsettings/resource_ids -o "$(gyp_shared_intermediate_dir)/webkit" -D _chromium -E "CHROMIUM_BUILD=chromium" -t android -E "ANDROID_JAVA_TAGGED_ONLY=true" -D enable_printing -D use_concatenated_impulse_responses
+
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.rc: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_am.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ar.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bg.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bn.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ca.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_cs.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_da.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_de.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_el.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-GB.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es-419.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_et.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fa.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fake-bidi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fil.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_gu.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_he.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hu.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_id.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_it.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ja.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_kn.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ko.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lt.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lv.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ml.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_mr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ms.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nl.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nb.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pl.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-BR.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-PT.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ro.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ru.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sk.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sl.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sv.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sw.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ta.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_te.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_th.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_tr.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_uk.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_vi.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-CN.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-TW.pak: $(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h ;
+
+
+GYP_GENERATED_OUTPUTS := \
+	$(gyp_shared_intermediate_dir)/webkit/grit/webkit_strings.h \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.rc \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_am.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ar.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bg.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_bn.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ca.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_cs.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_da.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_de.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_el.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-GB.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_en-US.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_es-419.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_et.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fa.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fake-bidi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fil.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_fr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_gu.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_he.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_hu.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_id.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_it.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ja.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_kn.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ko.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lt.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_lv.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ml.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_mr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ms.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nl.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_nb.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pl.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-BR.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_pt-PT.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ro.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ru.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sk.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sl.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sv.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_sw.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_ta.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_te.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_th.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_tr.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_uk.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_vi.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-CN.pak \
+	$(gyp_shared_intermediate_dir)/webkit/webkit_strings_zh-TW.pak
+
+# Make sure our deps and generated files are built first.
+LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) $(GYP_GENERATED_OUTPUTS)
+
+### Rules for final target.
+# Add target alias to "gyp_all_modules" target.
+.PHONY: gyp_all_modules
+gyp_all_modules: webkit_webkit_strings_gyp
+
+# Alias gyp target name.
+.PHONY: webkit_strings
+webkit_strings: webkit_webkit_strings_gyp
+
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp
+LOCAL_UNINSTALLABLE_MODULE := true
+
+include $(BUILD_SYSTEM)/base_rules.mk
+
+$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)
+	$(hide) echo "Gyp timestamp: $@"
+	$(hide) mkdir -p $(dir $@)
+	$(hide) touch $@
diff --git a/win8/delegate_execute/command_execute_impl.cc b/win8/delegate_execute/command_execute_impl.cc
index 405b24f..4c37e7b 100644
--- a/win8/delegate_execute/command_execute_impl.cc
+++ b/win8/delegate_execute/command_execute_impl.cc
@@ -432,7 +432,7 @@
   base::FilePath chrome_exe;
   if (!FindChromeExe(&chrome_exe) ||
       ShellUtil::GetChromeDefaultStateFromPath(chrome_exe) !=
-          ShellUtil::DefaultState::IS_DEFAULT) {
+          ShellUtil::IS_DEFAULT) {
     AtlTrace("Chrome is not default: launching in desktop mode\n");
     launch_mode = ECHUIM_DESKTOP;
     launch_mode_determined = true;
diff --git a/win8/metro_driver/chrome_app_view_ash.cc b/win8/metro_driver/chrome_app_view_ash.cc
index dc5923c..8e1f0e6 100644
--- a/win8/metro_driver/chrome_app_view_ash.cc
+++ b/win8/metro_driver/chrome_app_view_ash.cc
@@ -17,6 +17,7 @@
 #include "base/threading/thread.h"
 #include "base/win/metro.h"
 #include "base/win/win_util.h"
+#include "base/win/windows_version.h"
 #include "chrome/common/chrome_switches.h"
 #include "ipc/ipc_channel.h"
 #include "ipc/ipc_channel_proxy.h"
@@ -272,8 +273,8 @@
   int ms_elapsed = 0;
   while (!IPC::Channel::IsNamedServerInitialized(channel_name) &&
          ms_elapsed < 10000) {
-    ms_elapsed += 500;
-    Sleep(500);
+    ms_elapsed += 100;
+    Sleep(100);
   }
   return IPC::Channel::IsNamedServerInitialized(channel_name);
 }
@@ -573,7 +574,7 @@
   CheckHR(hr);
 
   mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher;
-  hr = window_->get_Dispatcher(&dispatcher);
+  hr = window_->get_Dispatcher(dispatcher.GetAddressOf());
   CheckHR(hr, "Get Dispatcher failed.");
 
   mswr::ComPtr<winui::Core::ICoreAcceleratorKeys> accelerator_keys;
@@ -602,21 +603,23 @@
       &window_activated_token_);
   CheckHR(hr);
 
-  // Register for edge gesture notifications.
-  mswr::ComPtr<winui::Input::IEdgeGestureStatics> edge_gesture_statics;
-  hr = winrt_utils::CreateActivationFactory(
-      RuntimeClass_Windows_UI_Input_EdgeGesture,
-      edge_gesture_statics.GetAddressOf());
-  CheckHR(hr);
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+    // Register for edge gesture notifications only for Windows 8 and above.
+    mswr::ComPtr<winui::Input::IEdgeGestureStatics> edge_gesture_statics;
+    hr = winrt_utils::CreateActivationFactory(
+        RuntimeClass_Windows_UI_Input_EdgeGesture,
+        edge_gesture_statics.GetAddressOf());
+    CheckHR(hr);
 
-  mswr::ComPtr<winui::Input::IEdgeGesture> edge_gesture;
-  hr = edge_gesture_statics->GetForCurrentView(&edge_gesture);
-  CheckHR(hr);
+    mswr::ComPtr<winui::Input::IEdgeGesture> edge_gesture;
+    hr = edge_gesture_statics->GetForCurrentView(&edge_gesture);
+    CheckHR(hr);
 
-  hr = edge_gesture->add_Completed(mswr::Callback<EdgeEventHandler>(
-      this, &ChromeAppViewAsh::OnEdgeGestureCompleted).Get(),
-      &edgeevent_token_);
-  CheckHR(hr);
+    hr = edge_gesture->add_Completed(mswr::Callback<EdgeEventHandler>(
+        this, &ChromeAppViewAsh::OnEdgeGestureCompleted).Get(),
+        &edgeevent_token_);
+    CheckHR(hr);
+  }
 
   // By initializing the direct 3D swap chain with the corewindow
   // we can now directly blit to it from the browser process.
@@ -627,6 +630,7 @@
 
 IFACEMETHODIMP
 ChromeAppViewAsh::Load(HSTRING entryPoint) {
+  // On Win7 |entryPoint| is NULL.
   DVLOG(1) << __FUNCTION__;
   return S_OK;
 }
@@ -635,7 +639,7 @@
 ChromeAppViewAsh::Run() {
   DVLOG(1) << __FUNCTION__;
   mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher;
-  HRESULT hr = window_->get_Dispatcher(&dispatcher);
+  HRESULT hr = window_->get_Dispatcher(dispatcher.GetAddressOf());
   CheckHR(hr, "Dispatcher failed.");
 
   hr = window_->Activate();
diff --git a/win8/metro_driver/direct3d_helper.cc b/win8/metro_driver/direct3d_helper.cc
index 056e84b..d0c30cf 100644
--- a/win8/metro_driver/direct3d_helper.cc
+++ b/win8/metro_driver/direct3d_helper.cc
@@ -7,7 +7,10 @@
 #include "win8/metro_driver/winrt_utils.h"
 
 #include "base/logging.h"
+#include "base/win/windows_version.h"
 
+#include <corewindow.h>
+#include <windows.applicationmodel.core.h>
 #include <windows.graphics.display.h>
 
 namespace {
@@ -83,9 +86,15 @@
 }
 
 void Direct3DHelper::CreateWindowSizeDependentResources() {
-  CheckIfFailed(window_->get_Bounds(&window_bounds_));
-  float window_width = ConvertDipsToPixels(window_bounds_.Width);
-  float window_height = ConvertDipsToPixels(window_bounds_.Height);
+  float window_width = 0;
+  float window_height = 0;
+
+  if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+    // Windows 8 returns in DIPs.
+    CheckIfFailed(window_->get_Bounds(&window_bounds_));
+    window_width = ConvertDipsToPixels(window_width);
+    window_height = ConvertDipsToPixels(window_height);
+  }
 
   // TODO(scottmg): Orientation.
 
@@ -116,12 +125,32 @@
     CheckIfFailed(dxgi_adapter->GetParent(
         __uuidof(IDXGIFactory2), &dxgi_factory));
 
-    CheckIfFailed(dxgi_factory->CreateSwapChainForCoreWindow(
-        d3d_device_.Get(),
-        reinterpret_cast<IUnknown*>(window_),
-        &swap_chain_desc,
-        nullptr,
-        &swap_chain_));
+    if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+      // On Win8 we need the CoreWindow interface to create the Swapchain.
+      CheckIfFailed(dxgi_factory->CreateSwapChainForCoreWindow(
+          d3d_device_.Get(),
+          reinterpret_cast<IUnknown*>(window_),
+          &swap_chain_desc,
+          nullptr,
+          &swap_chain_));
+    } else {
+      // On Win7 we need the raw HWND to create the Swapchain.
+      mswr::ComPtr<ICoreWindowInterop> interop;
+      CheckIfFailed(window_->QueryInterface(interop.GetAddressOf()));
+      HWND window = NULL;
+      interop->get_WindowHandle(&window);
+
+      swap_chain_desc.Scaling = DXGI_SCALING_STRETCH;
+      swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+      CheckIfFailed(dxgi_factory->CreateSwapChainForHwnd(
+          d3d_device_.Get(),
+          window,
+          &swap_chain_desc,
+          nullptr,
+          nullptr,
+          &swap_chain_));
+    }
   }
 }
 
diff --git a/win8/metro_driver/metro_driver.cc b/win8/metro_driver/metro_driver.cc
index eb87754..a60af6b 100644
--- a/win8/metro_driver/metro_driver.cc
+++ b/win8/metro_driver/metro_driver.cc
@@ -13,11 +13,9 @@
 #include "base/logging.h"
 #include "base/logging_win.h"
 #include "base/win/scoped_comptr.h"
+#include "base/win/windows_version.h"
 #include "win8/metro_driver/winrt_utils.h"
 
-// TODO(siggi): Move this to GYP.
-#pragma comment(lib, "runtimeobject.lib")
-
 namespace {
 
 LONG WINAPI ErrorReportingHandler(EXCEPTION_POINTERS* ex_info) {
@@ -37,6 +35,17 @@
   return EXCEPTION_CONTINUE_SEARCH;
 }
 
+void SetMetroReportingFlags() {
+#if !defined(NDEBUG)
+  // Set the error reporting flags to always raise an exception,
+  // which is then processed by our vectored exception handling
+  // above to log the error message.
+  winfoundtn::Diagnostics::SetErrorReportingFlags(
+      winfoundtn::Diagnostics::UseSetErrorInfo |
+      winfoundtn::Diagnostics::ForceExceptions);
+#endif
+}
+
 // TODO(robertshield): This GUID is hard-coded in a bunch of places that
 //     don't allow explicit includes. Find a single place for it to live.
 // {7FE69228-633E-4f06-80C1-527FEA23E3A7}
@@ -44,7 +53,7 @@
     0x7fe69228, 0x633e, 0x4f06,
         { 0x80, 0xc1, 0x52, 0x7f, 0xea, 0x23, 0xe3, 0xa7 } };
 
-}
+}  // namespace
 
 #if !defined(COMPONENT_BUILD)
 // Required for base initialization.
@@ -54,53 +63,58 @@
 base::AtExitManager at_exit;
 #endif
 
+mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows8() {
+  SetMetroReportingFlags();
+  HRESULT hr = ::Windows::Foundation::Initialize(RO_INIT_MULTITHREADED);
+  if (FAILED(hr))
+    CHECK(false);
+  mswr::ComPtr<winapp::Core::ICoreApplication> core_app;
+  hr = winrt_utils::CreateActivationFactory(
+      RuntimeClass_Windows_ApplicationModel_Core_CoreApplication,
+      core_app.GetAddressOf());
+  if (FAILED(hr))
+    CHECK(false);
+  return core_app;
+}
+
+mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows7();
+
 extern "C" __declspec(dllexport)
 int InitMetro() {
+  // Metro mode or its emulation is not supported in Vista or XP.
+  if (base::win::GetVersion() < base::win::VERSION_WIN7)
+    return 1;
   // Initialize the command line.
   CommandLine::Init(0, NULL);
+  // Initialize the logging system.
   logging::LoggingSettings settings;
   settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
   logging::InitLogging(settings);
-
 #if defined(NDEBUG)
   logging::SetMinLogLevel(logging::LOG_ERROR);
 #else
   logging::SetMinLogLevel(logging::LOG_VERBOSE);
-  // Set the error reporting flags to always raise an exception,
-  // which is then processed by our vectored exception handling
-  // above to log the error message.
-  winfoundtn::Diagnostics::SetErrorReportingFlags(
-      winfoundtn::Diagnostics::UseSetErrorInfo |
-      winfoundtn::Diagnostics::ForceExceptions);
-
-  HANDLE registration =
+    HANDLE registration =
       ::AddVectoredExceptionHandler(TRUE, ErrorReportingHandler);
 #endif
-
   // Enable trace control and transport through event tracing for Windows.
   logging::LogEventProvider::Initialize(kChromeTraceProviderName);
-
   DVLOG(1) << "InitMetro";
 
-  mswrw::RoInitializeWrapper ro_initializer(RO_INIT_MULTITHREADED);
-  CheckHR(ro_initializer, "RoInitialize failed");
-
+  // OS specific initialization.
   mswr::ComPtr<winapp::Core::ICoreApplication> core_app;
-  HRESULT hr = winrt_utils::CreateActivationFactory(
-      RuntimeClass_Windows_ApplicationModel_Core_CoreApplication,
-      core_app.GetAddressOf());
-  CheckHR(hr, "Failed to create app factory");
-  if (FAILED(hr))
-    return 1;
+  if (base::win::GetVersion() < base::win::VERSION_WIN8)
+    core_app = InitWindows7();
+  else
+    core_app = InitWindows8();
 
   auto view_factory = mswr::Make<ChromeAppViewFactory>(core_app.Get());
-  hr = core_app->Run(view_factory.Get());
+  HRESULT hr = core_app->Run(view_factory.Get());
   DVLOG(1) << "exiting InitMetro, hr=" << hr;
 
 #if !defined(NDEBUG)
   ::RemoveVectoredExceptionHandler(registration);
 #endif
-
   return hr;
 }
 
diff --git a/win8/metro_driver/metro_driver.gyp b/win8/metro_driver/metro_driver.gyp
index 42fd9c7..34fbcdd 100644
--- a/win8/metro_driver/metro_driver.gyp
+++ b/win8/metro_driver/metro_driver.gyp
@@ -22,6 +22,12 @@
             'AdditionalDependencies': [
               'D2D1.lib',
               'D3D11.lib',
+              'runtimeobject.lib',
+            ],
+            'DelayLoadDLLs': [
+              'API-MS-WIN-CORE-WINRT-ERROR-L1-1-0.DLL',
+              'API-MS-WIN-CORE-WINRT-L1-1-0.DLL',
+              'API-MS-WIN-CORE-WINRT-STRING-L1-1-0.DLL',
             ],
           },
           'VCCLCompilerTool': {
@@ -76,6 +82,7 @@
             'display_properties.h',
             'metro_driver.cc',
             'metro_driver.h',
+            'metro_driver_win7.cc',
             'stdafx.h',
             'winrt_utils.cc',
             'winrt_utils.h',
diff --git a/win8/metro_driver/metro_driver_win7.cc b/win8/metro_driver/metro_driver_win7.cc
index 253e527..2e5aba7 100644
--- a/win8/metro_driver/metro_driver_win7.cc
+++ b/win8/metro_driver/metro_driver_win7.cc
@@ -3,57 +3,30 @@
 // found in the LICENSE file.
 
 #include "stdafx.h"
+#include <corewindow.h>
+
+#include "base/logging.h"
 
 EXTERN_C IMAGE_DOS_HEADER __ImageBase;
 
-struct Globals {
-  LPTHREAD_START_ROUTINE host_main;
-  void* host_context;
-  HWND core_window;
-  HWND host_window;
-  HANDLE host_thread;
-  DWORD main_thread_id;
-} globals;
-
-
-void ODS(const char* str, LONG_PTR val = 0) {
-  char buf[80];
-  size_t len = strlen(str);
-  if (len > 50) {
-    ::OutputDebugStringA("ODS: buffer too long");
-    return;
-  }
-
-  if (str[0] == '!') {
-    // Fatal error.
-    DWORD gle = ::GetLastError();
-    if (::IsDebuggerPresent())
-      __debugbreak();
-    wsprintfA(buf, "ODS:fatal %s (%p) gle=0x%x", str, val, gle);
-    ::MessageBoxA(NULL, buf, "!!!", MB_OK);
-    ::ExitProcess(gle);
-  } else {
-    // Just information.
-    wsprintfA(buf, "ODS:%s (%p)\n", str, val);
-    ::OutputDebugStringA(buf);
-  }
-}
-
 LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                          WPARAM wparam, LPARAM lparam) {
   PAINTSTRUCT ps;
   HDC hdc;
   switch (message) {
     case WM_PAINT:
-      hdc = BeginPaint(hwnd, &ps);
+      hdc = ::BeginPaint(hwnd, &ps);
       EndPaint(hwnd, &ps);
       break;
+    case WM_LBUTTONUP:
+      //  TODO(cpu): Remove this test code.
+      ::InvalidateRect(hwnd, NULL, TRUE);
+      break;
     case WM_DESTROY:
       PostQuitMessage(0);
-      ODS("Metro WM_DESTROY received");
       break;
     default:
-      return DefWindowProc(hwnd, message, wparam, lparam);
+      return ::DefWindowProc(hwnd, message, wparam, lparam);
   }
   return 0;
 }
@@ -62,78 +35,660 @@
   HINSTANCE hInst = reinterpret_cast<HINSTANCE>(&__ImageBase);
   WNDCLASSEXW wcex;
   wcex.cbSize = sizeof(wcex);
-  wcex.style                    = CS_HREDRAW | CS_VREDRAW;
-        wcex.lpfnWndProc        = WndProc;
-        wcex.cbClsExtra         = 0;
-        wcex.cbWndExtra         = 0;
-        wcex.hInstance          = hInst;
-        wcex.hIcon              = 0;
-        wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
-        wcex.hbrBackground      = (HBRUSH)(COLOR_INACTIVECAPTION+1);
-        wcex.lpszMenuName       = 0;
-        wcex.lpszClassName      = L"Windows.UI.Core.CoreWindow";
-        wcex.hIconSm            = 0;
+  wcex.style              = CS_HREDRAW | CS_VREDRAW;
+  wcex.lpfnWndProc        = WndProc;
+  wcex.cbClsExtra         = 0;
+  wcex.cbWndExtra         = 0;
+  wcex.hInstance          = hInst;
+  wcex.hIcon              = 0;
+  wcex.hCursor            = LoadCursor(NULL, IDC_ARROW);
+  wcex.hbrBackground      = (HBRUSH)(COLOR_INACTIVECAPTION+1);
+  wcex.lpszMenuName       = 0;
+  wcex.lpszClassName      = L"Windows.UI.Core.CoreWindow";
+  wcex.hIconSm            = 0;
 
   HWND hwnd = ::CreateWindowExW(0,
                                 MAKEINTATOM(::RegisterClassExW(&wcex)),
-                                L"metro_metro",
-                                WS_POPUP,
-                                0, 0, 0, 0,
+                                L"metro_win7",
+                                WS_POPUP | WS_VISIBLE,
+                                0, 0, 1024, 1024,
                                 NULL, NULL, hInst, NULL);
   return hwnd;
 }
 
-DWORD WINAPI HostThread(void*) {
-  // The sleeps simulates the delay we have in the actual metro code
-  // which takes in account the corewindow being created and some other
-  // unknown machinations of metro.
-  ODS("Chrome main thread", ::GetCurrentThreadId());
-  ::Sleep(30);
-  return globals.host_main(globals.host_context);
-}
+typedef winfoundtn::ITypedEventHandler<
+    winapp::Core::CoreApplicationView*,
+    winapp::Activation::IActivatedEventArgs*> ActivatedHandler;
 
-extern "C" __declspec(dllexport)
-int InitMetro(LPTHREAD_START_ROUTINE thread_proc, void* context) {
-  ODS("InitMetro [Win7 emulation]");
-  HWND window = CreateMetroTopLevelWindow();
-  if (!window)
-    return 1;
-  // This magic incatation tells windows that the window is going fullscreen
-  // so the taskbar gets out of the wait automatically.
-  ::SetWindowPos(window,
-                 HWND_TOP,
-                 0,0,
-                 GetSystemMetrics(SM_CXSCREEN),
-                 GetSystemMetrics(SM_CYSCREEN),
-                 SWP_SHOWWINDOW);
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::WindowActivatedEventArgs*> WindowActivatedHandler;
 
-  // Ready to start our caller.
-  globals.core_window = window;
-  globals.host_main = thread_proc;
-  globals.host_context = context;
-  HANDLE thread = ::CreateThread(NULL, 0, &HostThread, NULL, 0, NULL);
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::AutomationProviderRequestedEventArgs*>
+        AutomationProviderHandler;
 
-  // Main message loop.
-  MSG msg = {0};
-  while (GetMessage(&msg, NULL, 0, 0)) {
-    TranslateMessage(&msg);
-    DispatchMessage(&msg);
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::CharacterReceivedEventArgs*> CharEventHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::CoreWindowEventArgs*> CoreWindowEventHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::InputEnabledEventArgs*> InputEnabledEventHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::KeyEventArgs*> KeyEventHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::PointerEventArgs*> PointerEventHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::WindowSizeChangedEventArgs*> SizeChangedHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::TouchHitTestingEventArgs*> TouchHitTestHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreWindow*,
+    winui::Core::VisibilityChangedEventArgs*> VisibilityChangedHandler;
+
+typedef winfoundtn::ITypedEventHandler<
+    winui::Core::CoreDispatcher*,
+    winui::Core::AcceleratorKeyEventArgs*> AcceleratorKeyEventHandler;
+
+// The following classes are the emulation of the WinRT system as exposed
+// to metro applications. There is one application (ICoreApplication) which
+// contains a series of Views (ICoreApplicationView) each one of them
+// containing a CoreWindow which represents a surface that can drawn to
+// and that receives events.
+//
+// Here is the general dependency hierachy in terms of interfaces:
+//
+//  IFrameworkViewSource --> IFrameworkView
+//          ^                     |
+//          |                     |                          metro app
+//  ---------------------------------------------------------------------
+//          |                     |                         winRT system
+//          |                     v
+//  ICoreApplication     ICoreApplicationView
+//                                |
+//                                v
+//                          ICoreWindow -----> ICoreWindowInterop
+//                                |                  |
+//                                |                  |
+//                                v                  V
+//                         ICoreDispatcher  <==>  real HWND
+//
+class CoreDispacherEmulation :
+    public mswr::RuntimeClass<
+        winui::Core::ICoreDispatcher,
+        winui::Core::ICoreAcceleratorKeys> {
+ public:
+  // ICoreDispatcher implementation:
+  virtual HRESULT STDMETHODCALLTYPE get_HasThreadAccess(boolean* value) {
+    return S_OK;
   }
 
-  return (int) msg.wParam;
-}
+  virtual HRESULT STDMETHODCALLTYPE ProcessEvents(
+      winui::Core::CoreProcessEventsOption options) {
+    // We don't support the other message pump modes. So we basically enter a
+    // traditional message loop that we only exit a teardown.
+    if (options != winui::Core::CoreProcessEventsOption_ProcessUntilQuit)
+      return E_FAIL;
 
-extern "C" _declspec(dllexport) HWND GetRootWindow() {
-  ODS("GetRootWindow", ULONG_PTR(globals.core_window));
-  return globals.core_window;
-}
+    MSG msg = {0};
+    while(::GetMessage(&msg, NULL, 0, 0) != 0) {
+      ::TranslateMessage(&msg);
+      ::DispatchMessage(&msg);
+    }
+    // TODO(cpu): figure what to do with msg.WParam which we would normally
+    // return here.
+    return S_OK;
+  }
 
-extern "C" _declspec(dllexport) void SetFrameWindow(HWND window) {
-  ODS("SetFrameWindow", ULONG_PTR(window));
-  globals.host_window = window;
-}
+  virtual HRESULT STDMETHODCALLTYPE RunAsync(
+      winui::Core::CoreDispatcherPriority priority,
+      winui::Core::IDispatchedHandler *agileCallback,
+      ABI::Windows::Foundation::IAsyncAction** asyncAction) {
+    return S_OK;
+  }
 
-extern "C" __declspec(dllexport) const wchar_t* GetInitialUrl() {
-  return L"";
+  virtual HRESULT STDMETHODCALLTYPE RunIdleAsync(
+      winui::Core::IIdleDispatchedHandler *agileCallback,
+      winfoundtn::IAsyncAction** asyncAction) {
+    return S_OK;
+  }
+
+  // ICoreAcceleratorKeys implementation:
+  virtual HRESULT STDMETHODCALLTYPE add_AcceleratorKeyActivated(
+      AcceleratorKeyEventHandler* handler,
+      EventRegistrationToken *pCookie) {
+    // TODO(cpu): implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_AcceleratorKeyActivated(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+};
+
+class CoreWindowEmulation
+    : public mswr::RuntimeClass<
+        mswr::RuntimeClassFlags<mswr::WinRtClassicComMix>,
+        winui::Core::ICoreWindow, ICoreWindowInterop> {
+ public:
+  CoreWindowEmulation() : core_hwnd_(NULL) {
+    dispatcher_ = mswr::Make<CoreDispacherEmulation>();
+    core_hwnd_ = CreateMetroTopLevelWindow();
+  }
+
+  ~CoreWindowEmulation() {
+    ::DestroyWindow(core_hwnd_);
+  }
+
+  // ICoreWindow implementation:
+  virtual HRESULT STDMETHODCALLTYPE get_AutomationHostProvider(
+      IInspectable** value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_Bounds(
+      winfoundtn::Rect* value) {
+    RECT rect;
+    if (!::GetClientRect(core_hwnd_, &rect))
+      return E_FAIL;
+    value->Width = rect.right;
+    value->Height = rect.bottom;
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_CustomProperties(
+      winfoundtn::Collections::IPropertySet** value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_Dispatcher(
+      winui::Core::ICoreDispatcher** value) {
+    return dispatcher_.CopyTo(value);
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_FlowDirection(
+      winui::Core::CoreWindowFlowDirection* value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE put_FlowDirection(
+      winui::Core::CoreWindowFlowDirection value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_IsInputEnabled(
+      boolean* value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE put_IsInputEnabled(
+      boolean value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_PointerCursor(
+      winui::Core::ICoreCursor** value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE put_PointerCursor(
+       winui::Core::ICoreCursor* value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_PointerPosition(
+      winfoundtn::Point* value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_Visible(
+      boolean* value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE Activate(void) {
+    // After we fire OnActivate on the View, Chrome calls us back here.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE Close(void) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE GetAsyncKeyState(
+      ABI::Windows::System::VirtualKey virtualKey,
+      winui::Core::CoreVirtualKeyStates* KeyState) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE GetKeyState(
+      ABI::Windows::System::VirtualKey virtualKey,
+      winui::Core::CoreVirtualKeyStates* KeyState) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE ReleasePointerCapture(void) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE SetPointerCapture(void) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_Activated(
+      WindowActivatedHandler* handler,
+      EventRegistrationToken* pCookie) {
+    // TODO(cpu) implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_Activated(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_AutomationProviderRequested(
+      AutomationProviderHandler* handler,
+      EventRegistrationToken* cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_AutomationProviderRequested(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_CharacterReceived(
+      CharEventHandler* handler,
+      EventRegistrationToken* pCookie) {
+    // TODO(cpu) : implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_CharacterReceived(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_Closed(
+      CoreWindowEventHandler* handler,
+      EventRegistrationToken* pCookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_Closed(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_InputEnabled(
+      InputEnabledEventHandler* handler,
+      EventRegistrationToken* pCookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_InputEnabled(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_KeyDown(
+      KeyEventHandler* handler,
+      EventRegistrationToken* pCookie) {
+    // TODO(cpu): implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_KeyDown(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_KeyUp(
+      KeyEventHandler* handler,
+      EventRegistrationToken* pCookie) {
+    // TODO(cpu): implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_KeyUp(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_PointerCaptureLost(
+      PointerEventHandler* handler,
+      EventRegistrationToken* cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_PointerCaptureLost(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_PointerEntered(
+      PointerEventHandler* handler,
+      EventRegistrationToken* cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_PointerEntered(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_PointerExited(
+      PointerEventHandler* handler,
+      EventRegistrationToken* cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_PointerExited(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_PointerMoved(
+      PointerEventHandler* handler,
+      EventRegistrationToken* cookie) {
+    // TODO(cpu) : implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_PointerMoved(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_PointerPressed(
+      PointerEventHandler* handler,
+      EventRegistrationToken* cookie) {
+    // TODO(cpu): implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_PointerPressed(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_PointerReleased(
+      PointerEventHandler* handler,
+      EventRegistrationToken* cookie) {
+    // TODO(cpu): implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_PointerReleased(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_TouchHitTesting(
+      TouchHitTestHandler* handler,
+      EventRegistrationToken* pCookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_TouchHitTesting(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_PointerWheelChanged(
+      PointerEventHandler* handler,
+      EventRegistrationToken* cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_PointerWheelChanged(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_SizeChanged(
+      SizeChangedHandler* handler,
+      EventRegistrationToken* pCookie) {
+    // TODO(cpu): implement this.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_SizeChanged(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged(
+      VisibilityChangedHandler* handler,
+      EventRegistrationToken* pCookie) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged(
+      EventRegistrationToken cookie) {
+    return S_OK;
+  }
+
+  // ICoreWindowInterop implementation:
+  virtual HRESULT STDMETHODCALLTYPE get_WindowHandle(HWND* hwnd) {
+    if (!core_hwnd_)
+      return E_FAIL;
+    *hwnd = core_hwnd_;
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE put_MessageHandled(
+    boolean value) {
+    return S_OK;
+  }
+
+ private:
+   HWND core_hwnd_;
+   mswr::ComPtr<winui::Core::ICoreDispatcher> dispatcher_;
+};
+
+class ActivatedEvent
+    : public mswr::RuntimeClass<winapp::Activation::IActivatedEventArgs> {
+ public:
+  ActivatedEvent(winapp::Activation::ActivationKind activation_kind)
+    : activation_kind_(activation_kind) {
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_Kind(
+    winapp::Activation::ActivationKind *value) {
+    *value = activation_kind_;
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_PreviousExecutionState(
+    winapp::Activation::ApplicationExecutionState *value) {
+    *value = winapp::Activation::ApplicationExecutionState_ClosedByUser;
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_SplashScreen(
+    winapp::Activation::ISplashScreen **value) {
+    return E_FAIL;
+  }
+
+ private:
+  winapp::Activation::ActivationKind activation_kind_;
+};
+
+class CoreApplicationViewEmulation
+    : public mswr::RuntimeClass<winapp::Core::ICoreApplicationView> {
+ public:
+   CoreApplicationViewEmulation() {
+      core_window_ = mswr::Make<CoreWindowEmulation>();
+   }
+
+  HRESULT Activate() {
+    if (activated_handler_) {
+      auto ae = mswr::Make<ActivatedEvent>(
+        winapp::Activation::ActivationKind_File);
+      return activated_handler_->Invoke(this, ae.Get());
+    } else {
+      return S_OK;
+    }
+  }
+
+  // ICoreApplicationView implementation:
+  virtual HRESULT STDMETHODCALLTYPE get_CoreWindow(
+    winui::Core::ICoreWindow** value) {
+    if (!core_window_)
+      return E_FAIL;
+    return core_window_.CopyTo(value);
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_Activated(
+     ActivatedHandler* handler,
+    EventRegistrationToken* token) {
+    // The real component supports multiple handles but we don't yet.
+    if (activated_handler_)
+      return E_FAIL;
+    activated_handler_ = handler;
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_Activated(
+    EventRegistrationToken token) {
+    // Chrome never unregisters handlers, so we don't care about it.
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_IsMain(
+    boolean* value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_IsHosted(
+    boolean* value) {
+    return S_OK;
+  }
+
+ private:
+  mswr::ComPtr<winui::Core::ICoreWindow> core_window_;
+  mswr::ComPtr<ActivatedHandler> activated_handler_;
+};
+
+class CoreApplicationWin7Emulation
+    : public mswr::RuntimeClass<winapp::Core::ICoreApplication,
+                                winapp::Core::ICoreApplicationExit> {
+ public:
+   // ICoreApplication implementation:
+
+  virtual HRESULT STDMETHODCALLTYPE get_Id(
+      HSTRING* value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_Suspending(
+      winfoundtn::IEventHandler<winapp::SuspendingEventArgs*>* handler,
+      EventRegistrationToken* token) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_Suspending(
+      EventRegistrationToken token) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_Resuming(
+       winfoundtn::IEventHandler<IInspectable*>* handler,
+      EventRegistrationToken* token) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_Resuming(
+      EventRegistrationToken token) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE get_Properties(
+      winfoundtn::Collections::IPropertySet** value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE GetCurrentView(
+      winapp::Core::ICoreApplicationView** value) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE Run(
+      winapp::Core::IFrameworkViewSource* viewSource) {
+    HRESULT hr = viewSource->CreateView(app_view_.GetAddressOf());
+    if (FAILED(hr))
+      return hr;
+    view_emulation_ = mswr::Make<CoreApplicationViewEmulation>();
+    hr = app_view_->Initialize(view_emulation_.Get());
+    if (FAILED(hr))
+      return hr;
+    mswr::ComPtr<winui::Core::ICoreWindow> core_window;
+    hr = view_emulation_->get_CoreWindow(core_window.GetAddressOf());
+    if (FAILED(hr))
+      return hr;
+    hr = app_view_->SetWindow(core_window.Get());
+    if (FAILED(hr))
+      return hr;
+    hr = app_view_->Load(NULL);
+    if (FAILED(hr))
+      return hr;
+    hr = view_emulation_->Activate();
+    if (FAILED(hr))
+      return hr;
+    return app_view_->Run();
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE RunWithActivationFactories(
+      winfoundtn::IGetActivationFactory* activationFactoryCallback) {
+    return S_OK;
+  }
+
+  // ICoreApplicationExit implementation:
+
+  virtual HRESULT STDMETHODCALLTYPE Exit(void) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE add_Exiting(
+       winfoundtn::IEventHandler<IInspectable*>* handler,
+      EventRegistrationToken* token) {
+    return S_OK;
+  }
+
+  virtual HRESULT STDMETHODCALLTYPE remove_Exiting(
+      EventRegistrationToken token) {
+    return S_OK;
+  }
+
+ private:
+  mswr::ComPtr<winapp::Core::IFrameworkView> app_view_;
+  mswr::ComPtr<CoreApplicationViewEmulation> view_emulation_;
+};
+
+
+mswr::ComPtr<winapp::Core::ICoreApplication> InitWindows7() {
+  HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED);
+  if (FAILED(hr))
+    CHECK(false);
+  return mswr::Make<CoreApplicationWin7Emulation>();
 }
 
diff --git a/win8/viewer/metro_viewer_process_host.cc b/win8/viewer/metro_viewer_process_host.cc
index 4fa5194..a44ea3c 100644
--- a/win8/viewer/metro_viewer_process_host.cc
+++ b/win8/viewer/metro_viewer_process_host.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/memory/ref_counted.h"
 #include "base/process/process.h"
+#include "base/process/process_handle.h"
 #include "base/strings/string16.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/time/time.h"
@@ -21,6 +22,12 @@
 #include "ui/metro_viewer/metro_viewer_messages.h"
 #include "win8/viewer/metro_viewer_constants.h"
 
+namespace {
+
+const int kViewerProcessConnectionTimeoutSecs = 60;
+
+}  // namespace
+
 namespace win8 {
 
 MetroViewerProcessHost::InternalMessageFilter::InternalMessageFilter(
@@ -43,6 +50,26 @@
 }
 
 MetroViewerProcessHost::~MetroViewerProcessHost() {
+  if (!channel_)
+    return;
+
+  base::ProcessId viewer_process_id = GetViewerProcessId();
+  channel_->Close();
+  if (message_filter_) {
+    // Wait for the viewer process to go away.
+    if (viewer_process_id != base::kNullProcessId) {
+      base::ProcessHandle viewer_process = NULL;
+      base::OpenProcessHandleWithAccess(
+          viewer_process_id,
+          PROCESS_QUERY_INFORMATION | SYNCHRONIZE,
+          &viewer_process);
+      if (viewer_process) {
+        ::WaitForSingleObject(viewer_process, INFINITE);
+        ::CloseHandle(viewer_process);
+      }
+    }
+    channel_->RemoveFilter(message_filter_);
+  }
 }
 
 base::ProcessId MetroViewerProcessHost::GetViewerProcessId() {
@@ -57,9 +84,8 @@
 
   channel_connected_event_.reset(new base::WaitableEvent(false, false));
 
-  scoped_refptr<InternalMessageFilter> message_filter(
-      new InternalMessageFilter(this));
-  channel_->AddFilter(message_filter);
+  message_filter_ = new InternalMessageFilter(this);
+  channel_->AddFilter(message_filter_);
 
   base::win::ScopedComPtr<IApplicationActivationManager> activator;
   HRESULT hr = activator.CreateInstance(CLSID_ApplicationActivationManager);
@@ -75,13 +101,9 @@
 
   // Having launched the viewer process, now we wait for it to connect.
   bool success =
-      channel_connected_event_->TimedWait(base::TimeDelta::FromSeconds(60));
+      channel_connected_event_->TimedWait(base::TimeDelta::FromSeconds(
+          kViewerProcessConnectionTimeoutSecs));
   channel_connected_event_.reset();
-
-  // |message_filter| is only used to signal |channel_connected_event_| above
-  // and can thus be removed after |channel_connected_event_| is no longer
-  // waiting.
-  channel_->RemoveFilter(message_filter);
   return success;
 }
 
diff --git a/win8/viewer/metro_viewer_process_host.h b/win8/viewer/metro_viewer_process_host.h
index e156226..209a94c 100644
--- a/win8/viewer/metro_viewer_process_host.h
+++ b/win8/viewer/metro_viewer_process_host.h
@@ -96,6 +96,7 @@
 
   scoped_ptr<IPC::ChannelProxy> channel_;
   scoped_ptr<base::WaitableEvent> channel_connected_event_;
+  scoped_refptr<InternalMessageFilter> message_filter_;
 
   DISALLOW_COPY_AND_ASSIGN(MetroViewerProcessHost);
 };